aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CREDITS37
-rwxr-xr-xDocumentation/BK-usage/bksend2
-rw-r--r--Documentation/Changes2
-rw-r--r--Documentation/DocBook/Makefile77
-rw-r--r--Documentation/DocBook/deviceiobook.tmpl4
-rw-r--r--Documentation/DocBook/gadget.tmpl5
-rw-r--r--Documentation/DocBook/journal-api.tmpl5
-rw-r--r--Documentation/DocBook/kernel-api.tmpl13
-rw-r--r--Documentation/DocBook/kernel-hacking.tmpl4
-rw-r--r--Documentation/DocBook/kernel-locking.tmpl240
-rw-r--r--Documentation/DocBook/libata.tmpl4
-rw-r--r--Documentation/DocBook/librs.tmpl6
-rw-r--r--Documentation/DocBook/lsm.tmpl11
-rw-r--r--Documentation/DocBook/mcabook.tmpl4
-rw-r--r--Documentation/DocBook/mtdnand.tmpl14
-rw-r--r--Documentation/DocBook/procfs-guide.tmpl27
-rw-r--r--Documentation/DocBook/scsidrivers.tmpl5
-rw-r--r--Documentation/DocBook/sis900.tmpl556
-rw-r--r--Documentation/DocBook/tulip-user.tmpl8
-rw-r--r--Documentation/DocBook/usb.tmpl5
-rw-r--r--Documentation/DocBook/via-audio.tmpl6
-rw-r--r--Documentation/DocBook/videobook.tmpl206
-rw-r--r--Documentation/DocBook/wanbook.tmpl4
-rw-r--r--Documentation/DocBook/writing_usb_driver.tmpl4
-rw-r--r--Documentation/DocBook/z8530book.tmpl4
-rw-r--r--Documentation/IPMI.txt6
-rw-r--r--Documentation/SecurityBugs38
-rw-r--r--Documentation/SubmittingDrivers7
-rw-r--r--Documentation/aoe/aoe.txt13
-rw-r--r--Documentation/aoe/status.sh7
-rw-r--r--Documentation/aoe/udev-install.sh26
-rw-r--r--Documentation/aoe/udev.txt23
-rw-r--r--Documentation/arm/IXP20002
-rw-r--r--Documentation/arm/Samsung-S3C24XX/H1940.txt40
-rw-r--r--Documentation/arm/Samsung-S3C24XX/Overview.txt47
-rw-r--r--Documentation/arm/Samsung-S3C24XX/SMDK2440.txt56
-rw-r--r--Documentation/cachetlb.txt17
-rw-r--r--Documentation/cciss.txt2
-rw-r--r--Documentation/cdrom/mcd4
-rw-r--r--Documentation/cdrom/mcdx17
-rw-r--r--Documentation/cdrom/packet-writing.txt8
-rw-r--r--Documentation/cpusets.txt415
-rw-r--r--Documentation/crypto/api-intro.txt3
-rw-r--r--Documentation/devices.txt4
-rw-r--r--Documentation/dvb/README.dibusb92
-rw-r--r--Documentation/dvb/contributors.txt3
-rw-r--r--Documentation/dvb/faq.txt2
-rw-r--r--Documentation/dvb/get_dvb_firmware58
-rw-r--r--Documentation/dvb/readme.txt7
-rw-r--r--Documentation/feature-removal-schedule.txt31
-rw-r--r--Documentation/filesystems/Locking64
-rw-r--r--Documentation/filesystems/jfs.txt12
-rw-r--r--Documentation/filesystems/proc.txt21
-rw-r--r--Documentation/i2c/porting-clients6
-rw-r--r--Documentation/i2c/writing-clients6
-rw-r--r--Documentation/ioctl/hdio.txt173
-rw-r--r--Documentation/kernel-docs.txt7
-rw-r--r--Documentation/kernel-parameters.txt80
-rw-r--r--Documentation/keys.txt59
-rw-r--r--Documentation/networking/bonding.txt2076
-rw-r--r--Documentation/networking/e100.txt3
-rw-r--r--Documentation/networking/ethertap.txt268
-rw-r--r--Documentation/networking/ixgb.txt9
-rw-r--r--Documentation/oops-tracing.txt32
-rw-r--r--Documentation/parisc/00-INDEX4
-rw-r--r--Documentation/parport.txt2
-rw-r--r--Documentation/pci.txt8
-rw-r--r--Documentation/pm.txt17
-rw-r--r--Documentation/power/devices.txt2
-rw-r--r--Documentation/power/video.txt162
-rw-r--r--Documentation/scsi/st.txt5
-rw-r--r--Documentation/scsi/sym53c8xx_2.txt2
-rw-r--r--Documentation/sound/alsa/ALSA-Configuration.txt300
-rw-r--r--Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl407
-rw-r--r--Documentation/sound/alsa/VIA82xx-mixer.txt8
-rw-r--r--Documentation/sound/alsa/hda_codec.txt299
-rw-r--r--Documentation/sound/alsa/serial-u16550.txt10
-rw-r--r--Documentation/spinlocks.txt26
-rw-r--r--Documentation/sysrq.txt35
-rw-r--r--Documentation/tty.txt5
-rw-r--r--Documentation/usb/error-codes.txt28
-rw-r--r--Documentation/usb/sn9c102.txt13
-rw-r--r--Documentation/usb/usbmon.txt156
-rw-r--r--Documentation/video4linux/CARDLIST.saa713435
-rw-r--r--Documentation/video4linux/README.cx883
-rw-r--r--Documentation/video4linux/bttv/Cards7
-rw-r--r--Documentation/video4linux/bttv/README2
-rw-r--r--MAINTAINERS131
-rw-r--r--Makefile55
-rw-r--r--REPORTING-BUGS4
-rw-r--r--arch/alpha/kernel/alpha_ksyms.c1
-rw-r--r--arch/alpha/kernel/osf_sys.c23
-rw-r--r--arch/alpha/kernel/setup.c2
-rw-r--r--arch/alpha/kernel/signal.c12
-rw-r--r--arch/alpha/kernel/smp.c54
-rw-r--r--arch/alpha/kernel/srmcons.c27
-rw-r--r--arch/arm/Kconfig354
-rw-r--r--arch/arm/Kconfig.debug9
-rw-r--r--arch/arm/Makefile6
-rw-r--r--arch/arm/common/Kconfig21
-rw-r--r--arch/arm/common/locomo.c359
-rw-r--r--arch/arm/common/rtctime.c40
-rw-r--r--arch/arm/common/scoop.c116
-rw-r--r--arch/arm/configs/a5k_defconfig522
-rw-r--r--arch/arm/configs/assabet_defconfig468
-rw-r--r--arch/arm/configs/badge4_defconfig1384
-rw-r--r--arch/arm/configs/bast_defconfig325
-rw-r--r--arch/arm/configs/cerfcube_defconfig591
-rw-r--r--arch/arm/configs/clps7500_defconfig743
-rw-r--r--arch/arm/configs/ebsa110_defconfig266
-rw-r--r--arch/arm/configs/edb7211_defconfig533
-rw-r--r--arch/arm/configs/enp2611_defconfig270
-rw-r--r--arch/arm/configs/ep80219_defconfig362
-rw-r--r--arch/arm/configs/epxa10db_defconfig346
-rw-r--r--arch/arm/configs/footbridge_defconfig1278
-rw-r--r--arch/arm/configs/fortunet_defconfig671
-rw-r--r--arch/arm/configs/h3600_defconfig1051
-rw-r--r--arch/arm/configs/h7201_defconfig250
-rw-r--r--arch/arm/configs/h7202_defconfig316
-rw-r--r--arch/arm/configs/hackkit_defconfig588
-rw-r--r--arch/arm/configs/integrator_defconfig324
-rw-r--r--arch/arm/configs/iq31244_defconfig361
-rw-r--r--arch/arm/configs/iq80321_defconfig234
-rw-r--r--arch/arm/configs/iq80331_defconfig360
-rw-r--r--arch/arm/configs/iq80332_defconfig360
-rw-r--r--arch/arm/configs/ixdp2400_defconfig270
-rw-r--r--arch/arm/configs/ixdp2401_defconfig270
-rw-r--r--arch/arm/configs/ixdp2800_defconfig270
-rw-r--r--arch/arm/configs/ixdp2801_defconfig270
-rw-r--r--arch/arm/configs/ixp4xx_defconfig532
-rw-r--r--arch/arm/configs/jornada720_defconfig1137
-rw-r--r--arch/arm/configs/lart_defconfig572
-rw-r--r--arch/arm/configs/lpd7a400_defconfig404
-rw-r--r--arch/arm/configs/lpd7a404_defconfig676
-rw-r--r--arch/arm/configs/lubbock_defconfig400
-rw-r--r--arch/arm/configs/lusl7200_defconfig532
-rw-r--r--arch/arm/configs/mainstone_defconfig398
-rw-r--r--arch/arm/configs/mx1ads_defconfig277
-rw-r--r--arch/arm/configs/neponset_defconfig970
-rw-r--r--arch/arm/configs/netwinder_defconfig825
-rw-r--r--arch/arm/configs/omap_h2_1610_defconfig394
-rw-r--r--arch/arm/configs/omnimeter_defconfig795
-rw-r--r--arch/arm/configs/pleb_defconfig220
-rw-r--r--arch/arm/configs/pxa255-idp_defconfig799
-rw-r--r--arch/arm/configs/rpc_defconfig897
-rw-r--r--arch/arm/configs/s3c2410_defconfig311
-rw-r--r--arch/arm/configs/shannon_defconfig792
-rw-r--r--arch/arm/configs/shark_defconfig824
-rw-r--r--arch/arm/configs/simpad_defconfig370
-rw-r--r--arch/arm/configs/smdk2410_defconfig398
-rw-r--r--arch/arm/configs/versatile_defconfig482
-rw-r--r--arch/arm/kernel/calls.S36
-rw-r--r--arch/arm/kernel/debug.S23
-rw-r--r--arch/arm/kernel/ecard.c218
-rw-r--r--arch/arm/kernel/entry-armv.S21
-rw-r--r--arch/arm/kernel/fiq.c47
-rw-r--r--arch/arm/kernel/head.S79
-rw-r--r--arch/arm/kernel/irq.c9
-rw-r--r--arch/arm/kernel/module.c34
-rw-r--r--arch/arm/kernel/ptrace.c49
-rw-r--r--arch/arm/kernel/setup.c2
-rw-r--r--arch/arm/kernel/signal.c8
-rw-r--r--arch/arm/kernel/sys_arm.c18
-rw-r--r--arch/arm/kernel/traps.c34
-rw-r--r--arch/arm/kernel/vmlinux.lds.S4
-rw-r--r--arch/arm/mach-clps7500/core.c11
-rw-r--r--arch/arm/mach-ebsa110/io.c87
-rw-r--r--arch/arm/mach-footbridge/cats-hw.c1
-rw-r--r--arch/arm/mach-imx/dma.c6
-rw-r--r--arch/arm/mach-imx/generic.c4
-rw-r--r--arch/arm/mach-ixp2000/core.c61
-rw-r--r--arch/arm/mach-ixp2000/enp2611.c4
-rw-r--r--arch/arm/mach-ixp2000/ixdp2x01.c2
-rw-r--r--arch/arm/mach-ixp4xx/Makefile1
-rw-r--r--arch/arm/mach-ixp4xx/common.c81
-rw-r--r--arch/arm/mach-ixp4xx/coyote-setup.c72
-rw-r--r--arch/arm/mach-ixp4xx/ixdp425-setup.c88
-rw-r--r--arch/arm/mach-ixp4xx/prpmc1100-pci.c120
-rw-r--r--arch/arm/mach-ixp4xx/prpmc1100-setup.c98
-rw-r--r--arch/arm/mach-lh7a40x/arch-lpd7a40x.c2
-rw-r--r--arch/arm/mach-lh7a40x/common.h2
-rw-r--r--arch/arm/mach-lh7a40x/irq-lpd7a40x.c2
-rw-r--r--arch/arm/mach-omap/Kconfig45
-rw-r--r--arch/arm/mach-omap/Makefile2
-rw-r--r--arch/arm/mach-omap/board-generic.c1
-rw-r--r--arch/arm/mach-omap/board-h2.c62
-rw-r--r--arch/arm/mach-omap/board-h3.c110
-rw-r--r--arch/arm/mach-omap/board-innovator.c74
-rw-r--r--arch/arm/mach-omap/board-netstar.c151
-rw-r--r--arch/arm/mach-omap/board-osk.c56
-rw-r--r--arch/arm/mach-omap/board-perseus2.c62
-rw-r--r--arch/arm/mach-omap/board-voiceblue.c256
-rw-r--r--arch/arm/mach-omap/clock.c211
-rw-r--r--arch/arm/mach-omap/clock.h14
-rw-r--r--arch/arm/mach-omap/common.c25
-rw-r--r--arch/arm/mach-omap/dma.c2
-rw-r--r--arch/arm/mach-omap/fpga.c29
-rw-r--r--arch/arm/mach-omap/gpio.c126
-rw-r--r--arch/arm/mach-omap/leds-h2p2-debug.c98
-rw-r--r--arch/arm/mach-omap/leds-osk.c198
-rw-r--r--arch/arm/mach-omap/leds.c35
-rw-r--r--arch/arm/mach-omap/leds.h1
-rw-r--r--arch/arm/mach-omap/ocpi.c50
-rw-r--r--arch/arm/mach-omap/pm.c1
-rw-r--r--arch/arm/mach-omap/time.c206
-rw-r--r--arch/arm/mach-omap/usb.c87
-rw-r--r--arch/arm/mach-pxa/Kconfig22
-rw-r--r--arch/arm/mach-pxa/Makefile3
-rw-r--r--arch/arm/mach-pxa/corgi.c2
-rw-r--r--arch/arm/mach-pxa/idp.c160
-rw-r--r--arch/arm/mach-pxa/irq.c8
-rw-r--r--arch/arm/mach-pxa/leds-idp.c17
-rw-r--r--arch/arm/mach-pxa/lubbock.c2
-rw-r--r--arch/arm/mach-pxa/mainstone.c9
-rw-r--r--arch/arm/mach-pxa/pm.c46
-rw-r--r--arch/arm/mach-pxa/poodle.c181
-rw-r--r--arch/arm/mach-pxa/sleep.S17
-rw-r--r--arch/arm/mach-rpc/dma.c2
-rw-r--r--arch/arm/mach-rpc/riscpc.c2
-rw-r--r--arch/arm/mach-s3c2410/Kconfig46
-rw-r--r--arch/arm/mach-s3c2410/Makefile4
-rw-r--r--arch/arm/mach-s3c2410/clock.c96
-rw-r--r--arch/arm/mach-s3c2410/clock.h15
-rw-r--r--arch/arm/mach-s3c2410/cpu.c9
-rw-r--r--arch/arm/mach-s3c2410/cpu.h11
-rw-r--r--arch/arm/mach-s3c2410/devs.c55
-rw-r--r--arch/arm/mach-s3c2410/devs.h12
-rw-r--r--arch/arm/mach-s3c2410/dma.c27
-rw-r--r--arch/arm/mach-s3c2410/gpio.c18
-rw-r--r--arch/arm/mach-s3c2410/irq.c199
-rw-r--r--arch/arm/mach-s3c2410/mach-bast.c43
-rw-r--r--arch/arm/mach-s3c2410/mach-h1940.c3
-rw-r--r--arch/arm/mach-s3c2410/mach-n30.c155
-rw-r--r--arch/arm/mach-s3c2410/mach-nexcoder.c156
-rw-r--r--arch/arm/mach-s3c2410/mach-otom.c124
-rw-r--r--arch/arm/mach-s3c2410/mach-rx3715.c16
-rw-r--r--arch/arm/mach-s3c2410/mach-smdk2410.c5
-rw-r--r--arch/arm/mach-s3c2410/mach-smdk2440.c135
-rw-r--r--arch/arm/mach-s3c2410/mach-vr1000.c34
-rw-r--r--arch/arm/mach-s3c2410/pm.c15
-rw-r--r--arch/arm/mach-s3c2410/pm.h2
-rw-r--r--arch/arm/mach-s3c2410/s3c2410.c17
-rw-r--r--arch/arm/mach-s3c2410/s3c2440-dsc.c2
-rw-r--r--arch/arm/mach-s3c2410/s3c2440.c72
-rw-r--r--arch/arm/mach-s3c2410/time.c23
-rw-r--r--arch/arm/mach-sa1100/Kconfig6
-rw-r--r--arch/arm/mach-sa1100/assabet.c8
-rw-r--r--arch/arm/mach-sa1100/collie.c2
-rw-r--r--arch/arm/mach-sa1100/neponset.c2
-rw-r--r--arch/arm/mm/abort-ev4t.S5
-rw-r--r--arch/arm/mm/abort-ev5t.S6
-rw-r--r--arch/arm/mm/abort-ev5tj.S6
-rw-r--r--arch/arm/mm/abort-macro.S42
-rw-r--r--arch/arm/mm/consistent.c9
-rw-r--r--arch/arm/mm/fault-armv.c4
-rw-r--r--arch/arm/mm/flush.c2
-rw-r--r--arch/arm/mm/init.c4
-rw-r--r--arch/arm/mm/mm-armv.c61
-rw-r--r--arch/arm/tools/mach-types65
-rw-r--r--arch/arm26/Kconfig.debug10
-rw-r--r--arch/arm26/kernel/setup.c1
-rw-r--r--arch/arm26/kernel/signal.c8
-rw-r--r--arch/arm26/mm/init.c2
-rw-r--r--arch/cris/arch-v10/drivers/eeprom.c2
-rw-r--r--arch/cris/arch-v10/drivers/gpio.c2
-rw-r--r--arch/cris/arch-v10/kernel/signal.c8
-rw-r--r--arch/cris/arch-v10/mm/init.c1
-rw-r--r--arch/cris/kernel/setup.c2
-rw-r--r--arch/frv/Kconfig146
-rw-r--r--arch/frv/Kconfig.debug74
-rw-r--r--arch/frv/kernel/setup.c3
-rw-r--r--arch/frv/kernel/signal.c9
-rw-r--r--arch/frv/mb93090-mb00/pci-frv.c4
-rw-r--r--arch/frv/mb93090-mb00/pci-vdk.c6
-rw-r--r--arch/h8300/kernel/signal.c8
-rw-r--r--arch/i386/Kconfig94
-rw-r--r--arch/i386/Kconfig.debug8
-rw-r--r--arch/i386/Makefile10
-rw-r--r--arch/i386/defconfig1
-rw-r--r--arch/i386/kernel/Makefile2
-rw-r--r--arch/i386/kernel/acpi/sleep.c9
-rw-r--r--arch/i386/kernel/apic.c10
-rw-r--r--arch/i386/kernel/apm.c25
-rw-r--r--arch/i386/kernel/asm-offsets.c6
-rw-r--r--arch/i386/kernel/cpu/common.c26
-rw-r--r--arch/i386/kernel/cpu/cpu.h1
-rw-r--r--arch/i386/kernel/cpu/cpufreq/Kconfig54
-rw-r--r--arch/i386/kernel/cpu/cyrix.c2
-rw-r--r--arch/i386/kernel/cpu/intel_cacheinfo.c456
-rw-r--r--arch/i386/kernel/cpu/mtrr/centaur.c5
-rw-r--r--arch/i386/kernel/cpu/mtrr/cyrix.c8
-rw-r--r--arch/i386/kernel/cpu/mtrr/generic.c35
-rw-r--r--arch/i386/kernel/cpu/mtrr/if.c8
-rw-r--r--arch/i386/kernel/cpu/mtrr/main.c6
-rw-r--r--arch/i386/kernel/cpu/mtrr/mtrr.h5
-rw-r--r--arch/i386/kernel/cpu/mtrr/state.c4
-rw-r--r--arch/i386/kernel/cpuid.c4
-rw-r--r--arch/i386/kernel/dmi_scan.c3
-rw-r--r--arch/i386/kernel/efi.c8
-rw-r--r--arch/i386/kernel/entry.S136
-rw-r--r--arch/i386/kernel/head.S2
-rw-r--r--arch/i386/kernel/i386_ksyms.c7
-rw-r--r--arch/i386/kernel/i387.c8
-rw-r--r--arch/i386/kernel/i8259.c19
-rw-r--r--arch/i386/kernel/io_apic.c20
-rw-r--r--arch/i386/kernel/irq.c5
-rw-r--r--arch/i386/kernel/kprobes.c19
-rw-r--r--arch/i386/kernel/mpparse.c11
-rw-r--r--arch/i386/kernel/msr.c4
-rw-r--r--arch/i386/kernel/nmi.c4
-rw-r--r--arch/i386/kernel/numaq.c10
-rw-r--r--arch/i386/kernel/pci-dma.c2
-rw-r--r--arch/i386/kernel/process.c40
-rw-r--r--arch/i386/kernel/ptrace.c4
-rw-r--r--arch/i386/kernel/quirks.c4
-rw-r--r--arch/i386/kernel/scx200.c60
-rw-r--r--arch/i386/kernel/semaphore.c10
-rw-r--r--arch/i386/kernel/setup.c82
-rw-r--r--arch/i386/kernel/signal.c20
-rw-r--r--arch/i386/kernel/smp.c2
-rw-r--r--arch/i386/kernel/smpboot.c27
-rw-r--r--arch/i386/kernel/srat.c62
-rw-r--r--arch/i386/kernel/time.c110
-rw-r--r--arch/i386/kernel/time_hpet.c28
-rw-r--r--arch/i386/kernel/timers/timer_hpet.c2
-rw-r--r--arch/i386/kernel/traps.c64
-rw-r--r--arch/i386/kernel/vm86.c21
-rw-r--r--arch/i386/lib/Makefile2
-rw-r--r--arch/i386/lib/putuser.S87
-rw-r--r--arch/i386/mach-default/topology.c2
-rw-r--r--arch/i386/mach-es7000/es7000plat.c14
-rw-r--r--arch/i386/mach-visws/mpparse.c2
-rw-r--r--arch/i386/mach-voyager/voyager_smp.c28
-rw-r--r--arch/i386/math-emu/errors.c6
-rw-r--r--arch/i386/math-emu/fpu_aux.c2
-rw-r--r--arch/i386/math-emu/fpu_entry.c10
-rw-r--r--arch/i386/math-emu/fpu_proto.h2
-rw-r--r--arch/i386/math-emu/fpu_system.h12
-rw-r--r--arch/i386/math-emu/get_address.c18
-rw-r--r--arch/i386/math-emu/load_store.c8
-rw-r--r--arch/i386/math-emu/reg_constant.c10
-rw-r--r--arch/i386/math-emu/reg_constant.h6
-rw-r--r--arch/i386/math-emu/reg_ld_str.c48
-rw-r--r--arch/i386/mm/boot_ioremap.c4
-rw-r--r--arch/i386/mm/discontig.c224
-rw-r--r--arch/i386/mm/highmem.c2
-rw-r--r--arch/i386/mm/hugetlbpage.c13
-rw-r--r--arch/i386/mm/init.c56
-rw-r--r--arch/i386/mm/ioremap.c137
-rw-r--r--arch/i386/mm/mmap.c7
-rw-r--r--arch/i386/mm/pageattr.c8
-rw-r--r--arch/i386/oprofile/backtrace.c15
-rw-r--r--arch/i386/pci/acpi.c17
-rw-r--r--arch/i386/pci/direct.c12
-rw-r--r--arch/i386/pci/fixup.c20
-rw-r--r--arch/i386/pci/irq.c73
-rw-r--r--arch/i386/pci/mmconfig.c6
-rw-r--r--arch/i386/pci/numa.c10
-rw-r--r--arch/i386/pci/pcbios.c6
-rw-r--r--arch/i386/power/cpu.c3
-rw-r--r--arch/i386/power/swsusp.S36
-rw-r--r--arch/ia64/Kconfig1
-rw-r--r--arch/ia64/configs/sn2_defconfig1
-rw-r--r--arch/ia64/hp/common/sba_iommu.c4
-rw-r--r--arch/ia64/ia32/ia32_entry.S2
-rw-r--r--arch/ia64/ia32/ia32_signal.c6
-rw-r--r--arch/ia64/ia32/ia32priv.h24
-rw-r--r--arch/ia64/ia32/sys_ia32.c47
-rw-r--r--arch/ia64/kernel/irq.c12
-rw-r--r--arch/ia64/kernel/ivt.S3
-rw-r--r--arch/ia64/kernel/minstate.h2
-rw-r--r--arch/ia64/kernel/ptrace.c19
-rw-r--r--arch/ia64/kernel/setup.c11
-rw-r--r--arch/ia64/kernel/smp.c1
-rw-r--r--arch/ia64/kernel/smpboot.c15
-rw-r--r--arch/ia64/lib/swiotlb.c2
-rw-r--r--arch/ia64/mm/contig.c2
-rw-r--r--arch/ia64/mm/extable.c45
-rw-r--r--arch/ia64/mm/hugetlbpage.c8
-rw-r--r--arch/ia64/mm/init.c3
-rw-r--r--arch/ia64/mm/tlb.c1
-rw-r--r--arch/ia64/pci/pci.c69
-rw-r--r--arch/m32r/boot/compressed/Makefile5
-rw-r--r--arch/m32r/boot/compressed/head.S5
-rw-r--r--arch/m32r/boot/compressed/m32r_sio.c7
-rw-r--r--arch/m32r/boot/setup.S5
-rw-r--r--arch/m32r/kernel/entry.S21
-rw-r--r--arch/m32r/kernel/m32r_ksyms.c1
-rw-r--r--arch/m32r/kernel/module.c6
-rw-r--r--arch/m32r/kernel/semaphore.c2
-rw-r--r--arch/m32r/kernel/setup.c31
-rw-r--r--arch/m32r/kernel/signal.c2
-rw-r--r--arch/m32r/kernel/smpboot.c5
-rw-r--r--arch/m32r/kernel/sys_m32r.c6
-rw-r--r--arch/m32r/kernel/traps.c2
-rw-r--r--arch/m32r/mm/cache.c7
-rw-r--r--arch/m32r/mm/discontig.c1
-rw-r--r--arch/m32r/mm/fault-nommu.c1
-rw-r--r--arch/m32r/mm/init.c2
-rw-r--r--arch/m68k/atari/stdma.c10
-rw-r--r--arch/m68k/atari/stram.c2
-rw-r--r--arch/m68k/configs/sun3_defconfig1
-rw-r--r--arch/m68k/configs/sun3x_defconfig1
-rw-r--r--arch/m68k/kernel/signal.c157
-rw-r--r--arch/m68knommu/Makefile8
-rw-r--r--arch/m68knommu/kernel/asm-offsets.c16
-rw-r--r--arch/m68knommu/kernel/entry.S6
-rw-r--r--arch/m68knommu/kernel/signal.c8
-rw-r--r--arch/m68knommu/platform/5206/ARNEWSH/crt0_ram.S213
-rw-r--r--arch/m68knommu/platform/5206/Makefile1
-rw-r--r--arch/m68knommu/platform/5206e/MOTOROLA/crt0_ram.S178
-rw-r--r--arch/m68knommu/platform/5206e/Makefile1
-rw-r--r--arch/m68knommu/platform/5206e/eLITE/crt0_ram.S346
-rw-r--r--arch/m68knommu/platform/5249/MOTOROLA/crt0_ram.S230
-rw-r--r--arch/m68knommu/platform/5249/Makefile1
-rw-r--r--arch/m68knommu/platform/5272/CANCam/crt0_ram.S154
-rw-r--r--arch/m68knommu/platform/5272/MOTOROLA/crt0_ram.S165
-rw-r--r--arch/m68knommu/platform/5272/Makefile1
-rw-r--r--arch/m68knommu/platform/5272/NETtel/crt0_ram.S196
-rw-r--r--arch/m68knommu/platform/5272/SCALES/crt0_ram.S154
-rw-r--r--arch/m68knommu/platform/5272/config.c8
-rw-r--r--arch/m68knommu/platform/5272/senTec/crt0_ram.S159
-rw-r--r--arch/m68knommu/platform/527x/M5271EVB/crt0_ram.S166
-rw-r--r--arch/m68knommu/platform/527x/M5275EVB/crt0_ram.S166
-rw-r--r--arch/m68knommu/platform/527x/Makefile1
-rw-r--r--arch/m68knommu/platform/528x/M5282EVB/crt0_ram.S171
-rw-r--r--arch/m68knommu/platform/528x/Makefile1
-rw-r--r--arch/m68knommu/platform/528x/senTec/crt0_ram.S180
-rw-r--r--arch/m68knommu/platform/5307/ARNEWSH/crt0_ram.S167
-rw-r--r--arch/m68knommu/platform/5307/CLEOPATRA/crt0_ram.S183
-rw-r--r--arch/m68knommu/platform/5307/MOTOROLA/crt0_ram.S167
-rw-r--r--arch/m68knommu/platform/5307/MP3/crt0_ram.S181
-rw-r--r--arch/m68knommu/platform/5307/Makefile4
-rw-r--r--arch/m68knommu/platform/5307/NETtel/crt0_ram.S204
-rw-r--r--arch/m68knommu/platform/5307/config.c8
-rw-r--r--arch/m68knommu/platform/5307/entry.S76
-rw-r--r--arch/m68knommu/platform/5307/head.S4
-rw-r--r--arch/m68knommu/platform/5407/CLEOPATRA/crt0_ram.S180
-rw-r--r--arch/m68knommu/platform/5407/MOTOROLA/crt0_ram.S160
-rw-r--r--arch/m68knommu/platform/5407/Makefile1
-rw-r--r--arch/m68knommu/platform/68328/Makefile22
-rw-r--r--arch/m68knommu/platform/68328/head-pilot.S (renamed from arch/m68knommu/platform/68328/pilot/crt0_rom.S)4
-rw-r--r--arch/m68knommu/platform/68328/head-ram.S (renamed from arch/m68knommu/platform/68VZ328/ucdimm/crt0_ram.S)0
-rw-r--r--arch/m68knommu/platform/68328/head-rom.S (renamed from arch/m68knommu/platform/68EZ328/ucsimm/crt0_fixed.S)0
-rw-r--r--arch/m68knommu/platform/68360/Makefile5
-rw-r--r--arch/m68knommu/platform/68360/uCquicc/crt0_ram.S408
-rw-r--r--arch/m68knommu/platform/68360/uCquicc/crt0_rom.S420
-rw-r--r--arch/m68knommu/platform/68EZ328/Makefile7
-rw-r--r--arch/m68knommu/platform/68EZ328/ucsimm/crt0_himem.S1
-rw-r--r--arch/m68knommu/platform/68EZ328/ucsimm/crt0_ram.S167
-rw-r--r--arch/m68knommu/platform/68EZ328/ucsimm/crt0_rom.S1
-rw-r--r--arch/m68knommu/platform/68VZ328/Makefile12
-rw-r--r--arch/m68knommu/platform/68VZ328/de2/Makefile12
-rw-r--r--arch/m68knommu/platform/68VZ328/de2/crt0_ram.S135
-rw-r--r--arch/m68knommu/platform/68VZ328/ucdimm/Makefile12
-rw-r--r--arch/m68knommu/platform/68VZ328/ucdimm/crt0_fixed.S109
-rw-r--r--arch/m68knommu/platform/68VZ328/ucdimm/crt0_himem.S1
-rw-r--r--arch/m68knommu/platform/68VZ328/ucdimm/crt0_rom.S1
-rw-r--r--arch/mips/Kconfig4
-rw-r--r--arch/mips/kernel/irixelf.c9
-rw-r--r--arch/mips/kernel/irixinv.c4
-rw-r--r--arch/mips/kernel/irixsig.c87
-rw-r--r--arch/mips/kernel/linux32.c2
-rw-r--r--arch/mips/kernel/ptrace.c4
-rw-r--r--arch/mips/kernel/setup.c4
-rw-r--r--arch/mips/kernel/signal32.c7
-rw-r--r--arch/mips/kernel/smp.c20
-rw-r--r--arch/mips/kernel/sysirix.c74
-rw-r--r--arch/mips/kernel/unaligned.c16
-rw-r--r--arch/mips/lib/Makefile4
-rw-r--r--arch/mips/math-emu/dsemul.c5
-rw-r--r--arch/mips/mm/c-r3k.c3
-rw-r--r--arch/mips/mm/c-r4k.c3
-rw-r--r--arch/mips/mm/c-sb1.c11
-rw-r--r--arch/mips/mm/c-tx39.c3
-rw-r--r--arch/mips/mm/cache.c4
-rw-r--r--arch/mips/mm/highmem.c2
-rw-r--r--arch/mips/mm/init.c3
-rw-r--r--arch/mips/pci/fixup-mpc30x.c2
-rw-r--r--arch/mips/pci/pci-vr41xx.c2
-rw-r--r--arch/mips/pmc-sierra/yosemite/ht.c6
-rw-r--r--arch/mips/vr41xx/casio-e55/setup.c13
-rw-r--r--arch/mips/vr41xx/common/Makefile4
-rw-r--r--arch/mips/vr41xx/common/bcu.c25
-rw-r--r--arch/mips/vr41xx/common/cmu.c69
-rw-r--r--arch/mips/vr41xx/common/init.c44
-rw-r--r--arch/mips/vr41xx/common/ksyms.c33
-rw-r--r--arch/mips/vr41xx/common/rtc.c321
-rw-r--r--arch/mips/vr41xx/common/serial.c178
-rw-r--r--arch/mips/vr41xx/common/vrc4171.c106
-rw-r--r--arch/mips/vr41xx/ibm-workpad/setup.c13
-rw-r--r--arch/mips/vr41xx/nec-cmbvr4133/setup.c12
-rw-r--r--arch/mips/vr41xx/tanbac-tb0226/setup.c17
-rw-r--r--arch/mips/vr41xx/tanbac-tb0229/Makefile2
-rw-r--r--arch/mips/vr41xx/tanbac-tb0229/setup.c18
-rw-r--r--arch/mips/vr41xx/victor-mpc30x/setup.c17
-rw-r--r--arch/mips/vr41xx/zao-capcella/setup.c18
-rw-r--r--arch/parisc/Kconfig24
-rw-r--r--arch/parisc/Makefile13
-rw-r--r--arch/parisc/configs/a500_defconfig64
-rw-r--r--arch/parisc/kernel/Makefile4
-rw-r--r--arch/parisc/kernel/binfmt_elf32.c1
-rw-r--r--arch/parisc/kernel/drivers.c20
-rw-r--r--arch/parisc/kernel/entry.S40
-rw-r--r--arch/parisc/kernel/firmware.c8
-rw-r--r--arch/parisc/kernel/hardware.c24
-rw-r--r--arch/parisc/kernel/head.S43
-rw-r--r--arch/parisc/kernel/hpmc.S36
-rw-r--r--arch/parisc/kernel/init_task.c12
-rw-r--r--arch/parisc/kernel/ioctl32.c2
-rw-r--r--arch/parisc/kernel/irq.c108
-rw-r--r--arch/parisc/kernel/module.c62
-rw-r--r--arch/parisc/kernel/pacache.S1132
-rw-r--r--arch/parisc/kernel/pci-dma.c24
-rw-r--r--arch/parisc/kernel/pdc_chassis.c6
-rw-r--r--arch/parisc/kernel/perf.c57
-rw-r--r--arch/parisc/kernel/perf_asm.S4
-rw-r--r--arch/parisc/kernel/process.c10
-rw-r--r--arch/parisc/kernel/real2.S3
-rw-r--r--arch/parisc/kernel/setup.c20
-rw-r--r--arch/parisc/kernel/signal.c43
-rw-r--r--arch/parisc/kernel/signal32.c27
-rw-r--r--arch/parisc/kernel/signal32.h12
-rw-r--r--arch/parisc/kernel/smp.c4
-rw-r--r--arch/parisc/kernel/sys_parisc.c16
-rw-r--r--arch/parisc/kernel/sys_parisc32.c72
-rw-r--r--arch/parisc/kernel/traps.c37
-rw-r--r--arch/parisc/kernel/unaligned.c4
-rw-r--r--arch/parisc/kernel/unwind.c95
-rw-r--r--arch/parisc/kernel/vmlinux.lds.S11
-rw-r--r--arch/parisc/lib/checksum.c6
-rw-r--r--arch/parisc/lib/debuglocks.c5
-rw-r--r--arch/parisc/lib/memcpy.c6
-rw-r--r--arch/parisc/math-emu/driver.c3
-rw-r--r--arch/parisc/mm/fault.c2
-rw-r--r--arch/parisc/mm/init.c10
-rw-r--r--arch/parisc/mm/kmap.c4
-rw-r--r--arch/ppc/8260_io/Kconfig11
-rw-r--r--arch/ppc/8260_io/fcc_enet.c969
-rw-r--r--arch/ppc/8xx_io/cs4218_tdm.c2
-rw-r--r--arch/ppc/8xx_io/enet.c2
-rw-r--r--arch/ppc/8xx_io/fec.c2
-rw-r--r--arch/ppc/Kconfig59
-rw-r--r--arch/ppc/Makefile31
-rw-r--r--arch/ppc/boot/common/util.S72
-rw-r--r--arch/ppc/boot/simple/Makefile9
-rw-r--r--arch/ppc/boot/simple/clear.S2
-rw-r--r--arch/ppc/boot/simple/embed_config.c2
-rw-r--r--arch/ppc/boot/simple/head.S7
-rw-r--r--arch/ppc/boot/simple/m8260_tty.c2
-rw-r--r--arch/ppc/boot/simple/misc-chestnut.S41
-rw-r--r--arch/ppc/boot/simple/misc-chestnut.c35
-rw-r--r--arch/ppc/boot/simple/misc-cpci690.c14
-rw-r--r--arch/ppc/boot/simple/misc-ev64260.S68
-rw-r--r--arch/ppc/boot/simple/misc-ev64260.c57
-rw-r--r--arch/ppc/boot/simple/misc-katana.c26
-rw-r--r--arch/ppc/boot/simple/misc-mv64x60.S57
-rw-r--r--arch/ppc/boot/simple/misc-mv64x60.c61
-rw-r--r--arch/ppc/boot/simple/misc-radstone_ppc7d.c26
-rw-r--r--arch/ppc/boot/simple/mpc52xx_tty.c35
-rw-r--r--arch/ppc/boot/simple/mv64x60_stub.c24
-rw-r--r--arch/ppc/boot/simple/mv64x60_tty.c134
-rw-r--r--arch/ppc/boot/simple/openbios.c37
-rw-r--r--arch/ppc/configs/chestnut_defconfig83
-rw-r--r--arch/ppc/configs/hdpu_defconfig (renamed from arch/parisc/configs/n4000_defconfig)715
-rw-r--r--arch/ppc/configs/katana_defconfig188
-rw-r--r--arch/ppc/configs/mpc834x_sys_defconfig644
-rw-r--r--arch/ppc/configs/pmac_defconfig363
-rw-r--r--arch/ppc/configs/radstone_ppc7d_defconfig956
-rw-r--r--arch/ppc/kernel/Makefile1
-rw-r--r--arch/ppc/kernel/align.c4
-rw-r--r--arch/ppc/kernel/asm-offsets.c5
-rw-r--r--arch/ppc/kernel/cpu_setup_6xx.S32
-rw-r--r--arch/ppc/kernel/cputable.c12
-rw-r--r--arch/ppc/kernel/dma-mapping.c13
-rw-r--r--arch/ppc/kernel/entry.S143
-rw-r--r--arch/ppc/kernel/head.S224
-rw-r--r--arch/ppc/kernel/head_44x.S175
-rw-r--r--arch/ppc/kernel/head_4xx.S184
-rw-r--r--arch/ppc/kernel/head_8xx.S166
-rw-r--r--arch/ppc/kernel/head_booke.h171
-rw-r--r--arch/ppc/kernel/head_e500.S189
-rw-r--r--arch/ppc/kernel/l2cr.S20
-rw-r--r--arch/ppc/kernel/misc.S17
-rw-r--r--arch/ppc/kernel/pci.c199
-rw-r--r--arch/ppc/kernel/ppc_htab.c8
-rw-r--r--arch/ppc/kernel/ppc_ksyms.c3
-rw-r--r--arch/ppc/kernel/setup.c26
-rw-r--r--arch/ppc/kernel/signal.c30
-rw-r--r--arch/ppc/kernel/smp.c6
-rw-r--r--arch/ppc/kernel/swsusp.S349
-rw-r--r--arch/ppc/kernel/syscalls.c10
-rw-r--r--arch/ppc/kernel/temp.c2
-rw-r--r--arch/ppc/kernel/traps.c87
-rw-r--r--arch/ppc/kernel/vmlinux.lds.S6
-rw-r--r--arch/ppc/mm/hashtable.S2
-rw-r--r--arch/ppc/mm/init.c36
-rw-r--r--arch/ppc/mm/mmu_decl.h2
-rw-r--r--arch/ppc/mm/pgtable.c14
-rw-r--r--arch/ppc/mm/ppc_mmu.c6
-rw-r--r--arch/ppc/mm/tlb.c20
-rw-r--r--arch/ppc/oprofile/op_model_fsl_booke.c3
-rw-r--r--arch/ppc/platforms/4xx/ebony.c34
-rw-r--r--arch/ppc/platforms/4xx/ebony.h14
-rw-r--r--arch/ppc/platforms/4xx/luan.h6
-rw-r--r--arch/ppc/platforms/4xx/ocotea.h4
-rw-r--r--arch/ppc/platforms/4xx/xilinx_ml300.c18
-rw-r--r--arch/ppc/platforms/83xx/Makefile4
-rw-r--r--arch/ppc/platforms/83xx/mpc834x_sys.c289
-rw-r--r--arch/ppc/platforms/83xx/mpc834x_sys.h51
-rw-r--r--arch/ppc/platforms/85xx/Makefile2
-rw-r--r--arch/ppc/platforms/85xx/mpc8540_ads.c4
-rw-r--r--arch/ppc/platforms/85xx/mpc8560_ads.c20
-rw-r--r--arch/ppc/platforms/85xx/mpc85xx_ads_common.c20
-rw-r--r--arch/ppc/platforms/85xx/mpc85xx_cds_common.c323
-rw-r--r--arch/ppc/platforms/85xx/mpc85xx_cds_common.h4
-rw-r--r--arch/ppc/platforms/85xx/sbc8560.c2
-rw-r--r--arch/ppc/platforms/85xx/sbc85xx.c20
-rw-r--r--arch/ppc/platforms/85xx/stx_gp3.c44
-rw-r--r--arch/ppc/platforms/Makefile7
-rw-r--r--arch/ppc/platforms/adir_setup.c4
-rw-r--r--arch/ppc/platforms/chestnut.c185
-rw-r--r--arch/ppc/platforms/chestnut.h35
-rw-r--r--arch/ppc/platforms/chrp_pegasos_eth.c101
-rw-r--r--arch/ppc/platforms/chrp_setup.c2
-rw-r--r--arch/ppc/platforms/cpci690.c45
-rw-r--r--arch/ppc/platforms/cpci690.h5
-rw-r--r--arch/ppc/platforms/ev64260.c16
-rw-r--r--arch/ppc/platforms/gemini_prom.S42
-rw-r--r--arch/ppc/platforms/gemini_setup.c10
-rw-r--r--arch/ppc/platforms/hdpu.c1062
-rw-r--r--arch/ppc/platforms/hdpu.h82
-rw-r--r--arch/ppc/platforms/k2.c18
-rw-r--r--arch/ppc/platforms/katana.c423
-rw-r--r--arch/ppc/platforms/katana.h82
-rw-r--r--arch/ppc/platforms/lite5200.c123
-rw-r--r--arch/ppc/platforms/lite5200.h2
-rw-r--r--arch/ppc/platforms/lopec.c4
-rw-r--r--arch/ppc/platforms/mcpn765.c4
-rw-r--r--arch/ppc/platforms/mpc5200.c2
-rw-r--r--arch/ppc/platforms/mvme5100.c4
-rw-r--r--arch/ppc/platforms/pcore.c4
-rw-r--r--arch/ppc/platforms/pmac_backlight.c80
-rw-r--r--arch/ppc/platforms/pmac_cache.S44
-rw-r--r--arch/ppc/platforms/pmac_cpufreq.c35
-rw-r--r--arch/ppc/platforms/pmac_feature.c191
-rw-r--r--arch/ppc/platforms/pmac_setup.c60
-rw-r--r--arch/ppc/platforms/pmac_sleep.S8
-rw-r--r--arch/ppc/platforms/pmac_smp.c6
-rw-r--r--arch/ppc/platforms/pplus.c8
-rw-r--r--arch/ppc/platforms/prep_setup.c6
-rw-r--r--arch/ppc/platforms/prpmc750.c4
-rw-r--r--arch/ppc/platforms/prpmc800.c4
-rw-r--r--arch/ppc/platforms/radstone_ppc7d.c1452
-rw-r--r--arch/ppc/platforms/radstone_ppc7d.h434
-rw-r--r--arch/ppc/platforms/sandpoint.c13
-rw-r--r--arch/ppc/platforms/spruce.c4
-rw-r--r--arch/ppc/syslib/Makefile17
-rw-r--r--arch/ppc/syslib/btext.c2
-rw-r--r--arch/ppc/syslib/cpc700.h26
-rw-r--r--arch/ppc/syslib/cpm2_pic.c94
-rw-r--r--arch/ppc/syslib/cpm2_pic.h3
-rw-r--r--arch/ppc/syslib/ibm440gx_common.c2
-rw-r--r--arch/ppc/syslib/ipic.c646
-rw-r--r--arch/ppc/syslib/ipic.h49
-rw-r--r--arch/ppc/syslib/m8260_setup.c8
-rw-r--r--arch/ppc/syslib/mpc52xx_devices.c318
-rw-r--r--arch/ppc/syslib/mpc52xx_pci.c235
-rw-r--r--arch/ppc/syslib/mpc52xx_pci.h139
-rw-r--r--arch/ppc/syslib/mpc52xx_pic.c23
-rw-r--r--arch/ppc/syslib/mpc52xx_setup.c58
-rw-r--r--arch/ppc/syslib/mpc52xx_sys.c38
-rw-r--r--arch/ppc/syslib/mpc83xx_devices.c237
-rw-r--r--arch/ppc/syslib/mpc83xx_sys.c100
-rw-r--r--arch/ppc/syslib/mpc85xx_devices.c (renamed from arch/ppc/platforms/85xx/mpc85xx_devices.c)0
-rw-r--r--arch/ppc/syslib/mpc85xx_sys.c (renamed from arch/ppc/platforms/85xx/mpc85xx_sys.c)20
-rw-r--r--arch/ppc/syslib/mv64360_pic.c29
-rw-r--r--arch/ppc/syslib/mv64x60.c20
-rw-r--r--arch/ppc/syslib/ppc4xx_pic.c49
-rw-r--r--arch/ppc/syslib/ppc4xx_serial.c171
-rw-r--r--arch/ppc/syslib/ppc83xx_setup.c138
-rw-r--r--arch/ppc/syslib/ppc83xx_setup.h53
-rw-r--r--arch/ppc/syslib/todc_time.c4
-rw-r--r--arch/ppc/syslib/xilinx_pic.c16
-rw-r--r--arch/ppc64/Kconfig36
-rw-r--r--arch/ppc64/Makefile33
-rw-r--r--arch/ppc64/boot/Makefile20
-rw-r--r--arch/ppc64/boot/install.sh3
-rw-r--r--arch/ppc64/boot/main.c6
-rw-r--r--arch/ppc64/boot/no_initrd.c2
-rw-r--r--arch/ppc64/boot/zImage.lds2
-rw-r--r--arch/ppc64/configs/g5_defconfig364
-rw-r--r--arch/ppc64/configs/iSeries_defconfig156
-rw-r--r--arch/ppc64/configs/maple_defconfig125
-rw-r--r--arch/ppc64/configs/pSeries_defconfig195
-rw-r--r--arch/ppc64/defconfig594
-rw-r--r--arch/ppc64/kernel/LparData.c3
-rw-r--r--arch/ppc64/kernel/Makefile7
-rw-r--r--arch/ppc64/kernel/align.c4
-rw-r--r--arch/ppc64/kernel/asm-offsets.c22
-rw-r--r--arch/ppc64/kernel/cputable.c3
-rw-r--r--arch/ppc64/kernel/dma.c102
-rw-r--r--arch/ppc64/kernel/eeh.c2
-rw-r--r--arch/ppc64/kernel/entry.S4
-rw-r--r--arch/ppc64/kernel/head.S38
-rw-r--r--arch/ppc64/kernel/i8259.c13
-rw-r--r--arch/ppc64/kernel/iSeries_htab.c4
-rw-r--r--arch/ppc64/kernel/iSeries_pci.c6
-rw-r--r--arch/ppc64/kernel/iSeries_setup.c128
-rw-r--r--arch/ppc64/kernel/iSeries_setup.h11
-rw-r--r--arch/ppc64/kernel/idle.c4
-rw-r--r--arch/ppc64/kernel/ioctl32.c1
-rw-r--r--arch/ppc64/kernel/iommu.c8
-rw-r--r--arch/ppc64/kernel/irq.c30
-rw-r--r--arch/ppc64/kernel/kprobes.c52
-rw-r--r--arch/ppc64/kernel/lmb.c26
-rw-r--r--arch/ppc64/kernel/lparcfg.c18
-rw-r--r--arch/ppc64/kernel/misc.S26
-rw-r--r--arch/ppc64/kernel/module.c3
-rw-r--r--arch/ppc64/kernel/nvram.c38
-rw-r--r--arch/ppc64/kernel/pSeries_hvCall.S186
-rw-r--r--arch/ppc64/kernel/pSeries_iommu.c80
-rw-r--r--arch/ppc64/kernel/pSeries_lpar.c4
-rw-r--r--arch/ppc64/kernel/pSeries_nvram.c5
-rw-r--r--arch/ppc64/kernel/pSeries_pci.c27
-rw-r--r--arch/ppc64/kernel/pSeries_reconfig.c434
-rw-r--r--arch/ppc64/kernel/pSeries_setup.c5
-rw-r--r--arch/ppc64/kernel/pSeries_smp.c231
-rw-r--r--arch/ppc64/kernel/pacaData.c8
-rw-r--r--arch/ppc64/kernel/pci.c163
-rw-r--r--arch/ppc64/kernel/pci.h3
-rw-r--r--arch/ppc64/kernel/pci_direct_iommu.c34
-rw-r--r--arch/ppc64/kernel/pci_dn.c25
-rw-r--r--arch/ppc64/kernel/pci_iommu.c55
-rw-r--r--arch/ppc64/kernel/pmac_feature.c41
-rw-r--r--arch/ppc64/kernel/pmac_pci.c22
-rw-r--r--arch/ppc64/kernel/pmac_setup.c64
-rw-r--r--arch/ppc64/kernel/pmac_smp.c5
-rw-r--r--arch/ppc64/kernel/pmac_time.c119
-rw-r--r--arch/ppc64/kernel/pmc.c64
-rw-r--r--arch/ppc64/kernel/ppc_ksyms.c68
-rw-r--r--arch/ppc64/kernel/proc_ppc64.c251
-rw-r--r--arch/ppc64/kernel/process.c24
-rw-r--r--arch/ppc64/kernel/prom.c499
-rw-r--r--arch/ppc64/kernel/prom_init.c141
-rw-r--r--arch/ppc64/kernel/ptrace.c3
-rw-r--r--arch/ppc64/kernel/rtas.c60
-rw-r--r--arch/ppc64/kernel/rtas_flash.c14
-rw-r--r--arch/ppc64/kernel/rtasd.c66
-rw-r--r--arch/ppc64/kernel/rtc.c2
-rw-r--r--arch/ppc64/kernel/scanlog.c2
-rw-r--r--arch/ppc64/kernel/semaphore.c5
-rw-r--r--arch/ppc64/kernel/setup.c83
-rw-r--r--arch/ppc64/kernel/signal.c30
-rw-r--r--arch/ppc64/kernel/signal32.c41
-rw-r--r--arch/ppc64/kernel/smp.c99
-rw-r--r--arch/ppc64/kernel/sys_ppc32.c17
-rw-r--r--arch/ppc64/kernel/syscalls.c3
-rw-r--r--arch/ppc64/kernel/sysfs.c28
-rw-r--r--arch/ppc64/kernel/time.c93
-rw-r--r--arch/ppc64/kernel/traps.c40
-rw-r--r--arch/ppc64/kernel/vdso.c614
-rw-r--r--arch/ppc64/kernel/vdso32/Makefile36
-rw-r--r--arch/ppc64/kernel/vdso32/cacheflush.S65
-rw-r--r--arch/ppc64/kernel/vdso32/datapage.S68
-rw-r--r--arch/ppc64/kernel/vdso32/gettimeofday.S139
-rw-r--r--arch/ppc64/kernel/vdso32/sigtramp.S300
-rw-r--r--arch/ppc64/kernel/vdso32/vdso32.lds.S111
-rw-r--r--arch/ppc64/kernel/vdso32/vdso32_wrapper.S13
-rw-r--r--arch/ppc64/kernel/vdso64/Makefile35
-rw-r--r--arch/ppc64/kernel/vdso64/cacheflush.S64
-rw-r--r--arch/ppc64/kernel/vdso64/datapage.S68
-rw-r--r--arch/ppc64/kernel/vdso64/gettimeofday.S91
-rw-r--r--arch/ppc64/kernel/vdso64/sigtramp.S294
-rw-r--r--arch/ppc64/kernel/vdso64/vdso64.lds.S110
-rw-r--r--arch/ppc64/kernel/vdso64/vdso64_wrapper.S13
-rw-r--r--arch/ppc64/kernel/vio.c55
-rw-r--r--arch/ppc64/kernel/viopath.c53
-rw-r--r--arch/ppc64/kernel/xics.c13
-rw-r--r--arch/ppc64/mm/fault.c24
-rw-r--r--arch/ppc64/mm/hash_low.S12
-rw-r--r--arch/ppc64/mm/hash_native.c14
-rw-r--r--arch/ppc64/mm/hash_utils.c42
-rw-r--r--arch/ppc64/mm/hugetlbpage.c33
-rw-r--r--arch/ppc64/mm/init.c47
-rw-r--r--arch/ppc64/mm/numa.c206
-rw-r--r--arch/ppc64/mm/slb.c4
-rw-r--r--arch/ppc64/mm/stab.c2
-rw-r--r--arch/ppc64/mm/tlb.c11
-rw-r--r--arch/ppc64/oprofile/common.c18
-rw-r--r--arch/ppc64/oprofile/op_model_power4.c4
-rw-r--r--arch/ppc64/oprofile/op_model_rs64.c2
-rw-r--r--arch/ppc64/xmon/xmon.c9
-rw-r--r--arch/s390/Kconfig6
-rw-r--r--arch/s390/Makefile2
-rw-r--r--arch/s390/defconfig11
-rw-r--r--arch/s390/kernel/compat_ioctl.c3
-rw-r--r--arch/s390/kernel/compat_linux.c13
-rw-r--r--arch/s390/kernel/compat_linux.h27
-rw-r--r--arch/s390/kernel/compat_signal.c8
-rw-r--r--arch/s390/kernel/compat_wrapper.S35
-rw-r--r--arch/s390/kernel/debug.c10
-rw-r--r--arch/s390/kernel/irq.c10
-rw-r--r--arch/s390/kernel/ptrace.c1
-rw-r--r--arch/s390/kernel/s390_ext.c4
-rw-r--r--arch/s390/kernel/signal.c10
-rw-r--r--arch/s390/kernel/smp.c77
-rw-r--r--arch/s390/kernel/syscalls.S6
-rw-r--r--arch/s390/kernel/time.c11
-rw-r--r--arch/s390/kernel/vtime.c2
-rw-r--r--arch/s390/mm/fault.c11
-rw-r--r--arch/s390/mm/init.c4
-rw-r--r--arch/s390/oprofile/Kconfig5
-rw-r--r--arch/sh/Kconfig9
-rw-r--r--arch/sh/Makefile7
-rw-r--r--arch/sh/boards/hp6xx/hp620/Makefile2
-rw-r--r--arch/sh/boards/hp6xx/hp620/setup.c45
-rw-r--r--arch/sh/boards/se/7300/io.c8
-rw-r--r--arch/sh/boards/sh03/rtc.c2
-rw-r--r--arch/sh/boards/snapgear/setup.c6
-rw-r--r--arch/sh/configs/adx_defconfig517
-rw-r--r--arch/sh/configs/cqreek_defconfig513
-rw-r--r--arch/sh/configs/dreamcast_defconfig218
-rw-r--r--arch/sh/configs/hp680_defconfig298
-rw-r--r--arch/sh/configs/microdev_defconfig84
-rw-r--r--arch/sh/configs/rts7751r2d_defconfig210
-rw-r--r--arch/sh/configs/se7300_defconfig102
-rw-r--r--arch/sh/configs/se73180_defconfig98
-rw-r--r--arch/sh/configs/se7705_defconfig93
-rw-r--r--arch/sh/configs/se7750_defconfig713
-rw-r--r--arch/sh/configs/se7751_defconfig348
-rw-r--r--arch/sh/configs/sh03_defconfig162
-rw-r--r--arch/sh/configs/snapgear_defconfig344
-rw-r--r--arch/sh/configs/systemh_defconfig245
-rw-r--r--arch/sh/defconfig372
-rw-r--r--arch/sh/drivers/pci/fixups-sh03.c4
-rw-r--r--arch/sh/drivers/pci/pci-sh7751.c10
-rw-r--r--arch/sh/drivers/pci/pci-st40.c2
-rw-r--r--arch/sh/kernel/cpu/sh4/sq.c2
-rw-r--r--arch/sh/kernel/cpufreq.c18
-rw-r--r--arch/sh/kernel/irq.c631
-rw-r--r--arch/sh/kernel/ptrace.c3
-rw-r--r--arch/sh/kernel/setup.c1
-rw-r--r--arch/sh/kernel/sh_ksyms.c8
-rw-r--r--arch/sh/kernel/signal.c17
-rw-r--r--arch/sh/kernel/smp.c3
-rw-r--r--arch/sh/kernel/time.c33
-rw-r--r--arch/sh/mm/cache-sh4.c40
-rw-r--r--arch/sh/mm/cache-sh7705.c20
-rw-r--r--arch/sh/mm/hugetlbpage.c8
-rw-r--r--arch/sh/mm/init.c2
-rw-r--r--arch/sh/mm/pg-sh4.c8
-rw-r--r--arch/sh/mm/pg-sh7705.c4
-rw-r--r--arch/sh64/Kconfig17
-rw-r--r--arch/sh64/Kconfig.debug7
-rw-r--r--arch/sh64/Makefile24
-rw-r--r--arch/sh64/configs/cayman_defconfig230
-rw-r--r--arch/sh64/defconfig667
-rw-r--r--arch/sh64/kernel/Makefile8
-rw-r--r--arch/sh64/kernel/dma.c2
-rw-r--r--arch/sh64/kernel/early_printk.c2
-rw-r--r--arch/sh64/kernel/entry.S26
-rw-r--r--arch/sh64/kernel/head.S6
-rw-r--r--arch/sh64/kernel/irq.c614
-rw-r--r--arch/sh64/kernel/module.c161
-rw-r--r--arch/sh64/kernel/pci_sh5.c2
-rw-r--r--arch/sh64/kernel/pcibios.c4
-rw-r--r--arch/sh64/kernel/process.c13
-rw-r--r--arch/sh64/kernel/ptrace.c17
-rw-r--r--arch/sh64/kernel/setup.c4
-rw-r--r--arch/sh64/kernel/sh_ksyms.c8
-rw-r--r--arch/sh64/kernel/signal.c24
-rw-r--r--arch/sh64/kernel/switchto.S3
-rw-r--r--arch/sh64/kernel/sys_sh64.c14
-rw-r--r--arch/sh64/kernel/syscalls.S7
-rw-r--r--arch/sh64/kernel/time.c6
-rw-r--r--arch/sh64/kernel/traps.c3
-rw-r--r--arch/sh64/lib/Makefile2
-rw-r--r--arch/sh64/lib/copy_user_memcpy.S14
-rw-r--r--arch/sh64/lib/dbg.c44
-rw-r--r--arch/sh64/lib/io.c73
-rw-r--r--arch/sh64/lib/iomap.c55
-rw-r--r--arch/sh64/lib/old-checksum.c17
-rw-r--r--arch/sh64/lib/page_clear.S3
-rw-r--r--arch/sh64/lib/page_copy.S9
-rw-r--r--arch/sh64/mach-cayman/Makefile2
-rw-r--r--arch/sh64/mach-cayman/iomap.c24
-rw-r--r--arch/sh64/mach-cayman/irq.c8
-rw-r--r--arch/sh64/mach-cayman/setup.c51
-rw-r--r--arch/sh64/mm/cache.c44
-rw-r--r--arch/sh64/mm/extable.c3
-rw-r--r--arch/sh64/mm/fault.c41
-rw-r--r--arch/sh64/mm/hugetlbpage.c8
-rw-r--r--arch/sh64/mm/init.c3
-rw-r--r--arch/sh64/mm/ioremap.c6
-rw-r--r--arch/sh64/mm/tlbmiss.c1
-rw-r--r--arch/sh64/oprofile/op_model_null.c2
-rw-r--r--arch/sparc/kernel/ioport.c4
-rw-r--r--arch/sparc/kernel/ptrace.c31
-rw-r--r--arch/sparc/kernel/signal.c8
-rw-r--r--arch/sparc/kernel/smp.c3
-rw-r--r--arch/sparc/kernel/sparc_ksyms.c1
-rw-r--r--arch/sparc/kernel/sun4d_smp.c1
-rw-r--r--arch/sparc/kernel/sun4m_smp.c1
-rw-r--r--arch/sparc/kernel/sys_sparc.c4
-rw-r--r--arch/sparc/kernel/sys_sunos.c4
-rw-r--r--arch/sparc/kernel/unaligned.c23
-rw-r--r--arch/sparc/mm/generic.c46
-rw-r--r--arch/sparc/mm/highmem.c2
-rw-r--r--arch/sparc/mm/init.c3
-rw-r--r--arch/sparc/mm/srmmu.c4
-rw-r--r--arch/sparc/mm/sun4c.c1
-rw-r--r--arch/sparc64/defconfig18
-rw-r--r--arch/sparc64/kernel/binfmt_aout32.c6
-rw-r--r--arch/sparc64/kernel/central.c128
-rw-r--r--arch/sparc64/kernel/ioctl32.c1
-rw-r--r--arch/sparc64/kernel/irq.c2
-rw-r--r--arch/sparc64/kernel/kprobes.c18
-rw-r--r--arch/sparc64/kernel/module.c101
-rw-r--r--arch/sparc64/kernel/pci.c21
-rw-r--r--arch/sparc64/kernel/pci_schizo.c112
-rw-r--r--arch/sparc64/kernel/signal.c2
-rw-r--r--arch/sparc64/kernel/signal32.c12
-rw-r--r--arch/sparc64/kernel/smp.c25
-rw-r--r--arch/sparc64/kernel/sparc64_ksyms.c6
-rw-r--r--arch/sparc64/kernel/sys_sparc32.c42
-rw-r--r--arch/sparc64/kernel/time.c7
-rw-r--r--arch/sparc64/mm/generic.c73
-rw-r--r--arch/sparc64/mm/hugetlbpage.c18
-rw-r--r--arch/sparc64/mm/init.c4
-rw-r--r--arch/sparc64/mm/tlb.c18
-rw-r--r--arch/um/Kconfig3
-rw-r--r--arch/um/Kconfig.debug16
-rw-r--r--arch/um/Kconfig_char14
-rw-r--r--arch/um/Makefile10
-rw-r--r--arch/um/Makefile-skas10
-rw-r--r--arch/um/Makefile-x86_644
-rw-r--r--arch/um/defconfig76
-rw-r--r--arch/um/drivers/Makefile15
-rw-r--r--arch/um/drivers/chan_kern.c9
-rw-r--r--arch/um/drivers/cow_user.c3
-rw-r--r--arch/um/drivers/fd.c8
-rw-r--r--arch/um/drivers/line.c2
-rw-r--r--arch/um/drivers/net_kern.c5
-rw-r--r--arch/um/drivers/null.c9
-rw-r--r--arch/um/drivers/port_kern.c45
-rw-r--r--arch/um/drivers/port_user.c11
-rw-r--r--arch/um/drivers/pty.c12
-rw-r--r--arch/um/drivers/random.c122
-rw-r--r--arch/um/drivers/slip_user.c6
-rw-r--r--arch/um/drivers/slirp_kern.c7
-rw-r--r--arch/um/drivers/tty.c7
-rw-r--r--arch/um/drivers/ubd_kern.c30
-rw-r--r--arch/um/drivers/xterm.c13
-rw-r--r--arch/um/drivers/xterm_kern.c10
-rw-r--r--arch/um/include/choose-mode.h7
-rw-r--r--arch/um/include/kern.h1
-rw-r--r--arch/um/include/registers.h2
-rw-r--r--arch/um/include/sysdep-i386/checksum.h2
-rw-r--r--arch/um/include/sysdep-i386/ptrace.h52
-rw-r--r--arch/um/include/sysdep-i386/ptrace_user.h7
-rw-r--r--arch/um/include/sysdep-i386/sigcontext.h2
-rw-r--r--arch/um/include/sysdep-i386/syscalls.h16
-rw-r--r--arch/um/include/sysdep-x86_64/checksum.h8
-rw-r--r--arch/um/include/sysdep-x86_64/ptrace.h62
-rw-r--r--arch/um/include/sysdep-x86_64/ptrace_user.h5
-rw-r--r--arch/um/include/sysdep-x86_64/sigcontext.h2
-rw-r--r--arch/um/include/sysdep-x86_64/syscalls.h5
-rw-r--r--arch/um/include/tlb.h44
-rw-r--r--arch/um/include/um_mmu.h12
-rw-r--r--arch/um/include/um_uaccess.h3
-rw-r--r--arch/um/include/user_util.h2
-rw-r--r--arch/um/kernel/Makefile47
-rw-r--r--arch/um/kernel/checksum.c43
-rw-r--r--arch/um/kernel/gmon_syms.c14
-rw-r--r--arch/um/kernel/mem.c2
-rw-r--r--arch/um/kernel/physmem.c1
-rw-r--r--arch/um/kernel/process.c17
-rw-r--r--arch/um/kernel/process_kern.c9
-rw-r--r--arch/um/kernel/ptrace.c15
-rw-r--r--arch/um/kernel/sigio_user.c29
-rw-r--r--arch/um/kernel/skas/Makefile8
-rw-r--r--arch/um/kernel/skas/include/skas.h9
-rw-r--r--arch/um/kernel/skas/mem_user.c11
-rw-r--r--arch/um/kernel/skas/process.c38
-rw-r--r--arch/um/kernel/skas/syscall_user.c15
-rw-r--r--arch/um/kernel/skas/tlb.c227
-rw-r--r--arch/um/kernel/skas/uaccess.c3
-rw-r--r--arch/um/kernel/smp.c6
-rw-r--r--arch/um/kernel/sys_call_table.c18
-rw-r--r--arch/um/kernel/syscall_kern.c11
-rw-r--r--arch/um/kernel/tlb.c334
-rw-r--r--arch/um/kernel/trap_user.c1
-rw-r--r--arch/um/kernel/tt/Makefile18
-rw-r--r--arch/um/kernel/tt/exec_user.c2
-rw-r--r--arch/um/kernel/tt/gdb.c2
-rw-r--r--arch/um/kernel/tt/include/tt.h1
-rw-r--r--arch/um/kernel/tt/mem.c2
-rw-r--r--arch/um/kernel/tt/process_kern.c96
-rw-r--r--arch/um/kernel/tt/ptproxy/Makefile5
-rw-r--r--arch/um/kernel/tt/ptproxy/proxy.c2
-rw-r--r--arch/um/kernel/tt/ptproxy/ptrace.c8
-rw-r--r--arch/um/kernel/tt/ptproxy/sysdep.c21
-rw-r--r--arch/um/kernel/tt/ptproxy/wait.c7
-rw-r--r--arch/um/kernel/tt/syscall_kern.c2
-rw-r--r--arch/um/kernel/tt/syscall_user.c18
-rw-r--r--arch/um/kernel/tt/tlb.c246
-rw-r--r--arch/um/kernel/tt/tracer.c30
-rw-r--r--arch/um/kernel/tt/trap_user.c3
-rw-r--r--arch/um/kernel/um_arch.c34
-rw-r--r--arch/um/kernel/user_util.c17
-rw-r--r--arch/um/os-Linux/Makefile6
-rw-r--r--arch/um/os-Linux/drivers/Makefile8
-rw-r--r--arch/um/os-Linux/process.c2
-rw-r--r--arch/um/os-Linux/sys-i386/Makefile5
-rw-r--r--arch/um/os-Linux/sys-i386/registers.c19
-rw-r--r--arch/um/os-Linux/sys-x86_64/Makefile5
-rw-r--r--arch/um/os-Linux/sys-x86_64/registers.c3
-rw-r--r--arch/um/os-Linux/util/Makefile4
-rw-r--r--arch/um/os-Linux/util/mk_user_constants.c29
-rw-r--r--arch/um/scripts/Makefile.rules13
-rw-r--r--arch/um/sys-i386/Makefile19
-rw-r--r--arch/um/sys-i386/ldt.c2
-rw-r--r--arch/um/sys-i386/ptrace.c2
-rw-r--r--arch/um/sys-i386/ptrace_user.c8
-rw-r--r--arch/um/sys-i386/signal.c34
-rw-r--r--arch/um/sys-i386/syscalls.c6
-rw-r--r--arch/um/sys-ppc/ptrace_user.c5
-rw-r--r--arch/um/sys-x86_64/Makefile22
-rw-r--r--arch/um/sys-x86_64/ptrace_user.c27
-rw-r--r--arch/um/sys-x86_64/signal.c2
-rw-r--r--arch/um/sys-x86_64/syscalls.c23
-rw-r--r--arch/v850/kernel/setup.c1
-rw-r--r--arch/v850/kernel/signal.c8
-rw-r--r--arch/v850/kernel/syscalls.c8
-rw-r--r--arch/x86_64/Kconfig54
-rw-r--r--arch/x86_64/defconfig81
-rw-r--r--arch/x86_64/ia32/ia32_aout.c6
-rw-r--r--arch/x86_64/ia32/ia32_signal.c44
-rw-r--r--arch/x86_64/ia32/ia32entry.S8
-rw-r--r--arch/x86_64/ia32/sys_ia32.c61
-rw-r--r--arch/x86_64/kernel/acpi/sleep.c9
-rw-r--r--arch/x86_64/kernel/apic.c4
-rw-r--r--arch/x86_64/kernel/asm-offsets.c2
-rw-r--r--arch/x86_64/kernel/e820.c16
-rw-r--r--arch/x86_64/kernel/entry.S11
-rw-r--r--arch/x86_64/kernel/head.S112
-rw-r--r--arch/x86_64/kernel/i8259.c10
-rw-r--r--arch/x86_64/kernel/io_apic.c14
-rw-r--r--arch/x86_64/kernel/kprobes.c160
-rw-r--r--arch/x86_64/kernel/module.c90
-rw-r--r--arch/x86_64/kernel/mpparse.c4
-rw-r--r--arch/x86_64/kernel/msr.c4
-rw-r--r--arch/x86_64/kernel/pci-gart.c22
-rw-r--r--arch/x86_64/kernel/process.c51
-rw-r--r--arch/x86_64/kernel/ptrace.c4
-rw-r--r--arch/x86_64/kernel/semaphore.c2
-rw-r--r--arch/x86_64/kernel/setup.c6
-rw-r--r--arch/x86_64/kernel/signal.c41
-rw-r--r--arch/x86_64/kernel/smp.c10
-rw-r--r--arch/x86_64/kernel/smpboot.c30
-rw-r--r--arch/x86_64/kernel/suspend_asm.S32
-rw-r--r--arch/x86_64/kernel/sys_x86_64.c3
-rw-r--r--arch/x86_64/kernel/time.c13
-rw-r--r--arch/x86_64/kernel/trampoline.S22
-rw-r--r--arch/x86_64/kernel/traps.c16
-rw-r--r--arch/x86_64/kernel/vmlinux.lds.S3
-rw-r--r--arch/x86_64/kernel/vsyscall.S169
-rw-r--r--arch/x86_64/kernel/vsyscall.c116
-rw-r--r--arch/x86_64/kernel/x8664_ksyms.c2
-rw-r--r--arch/x86_64/lib/bitops.c3
-rw-r--r--arch/x86_64/lib/delay.c2
-rw-r--r--arch/x86_64/lib/getuser.S65
-rw-r--r--arch/x86_64/lib/putuser.S77
-rw-r--r--arch/x86_64/mm/extable.c23
-rw-r--r--arch/x86_64/mm/ioremap.c12
-rw-r--r--arch/x86_64/mm/srat.c2
-rw-r--r--arch/x86_64/pci/k8-bus.c10
-rw-r--r--arch/x86_64/pci/mmconfig.c8
-rw-r--r--crypto/Kconfig13
-rw-r--r--crypto/Makefile1
-rw-r--r--crypto/aes.c53
-rw-r--r--crypto/blowfish.c8
-rw-r--r--crypto/cast5.c9
-rw-r--r--crypto/cast6.c8
-rw-r--r--crypto/cipher.c121
-rw-r--r--crypto/michael_mic.c18
-rw-r--r--crypto/scatterwalk.c53
-rw-r--r--crypto/scatterwalk.h22
-rw-r--r--crypto/serpent.c24
-rw-r--r--crypto/sha1.c83
-rw-r--r--crypto/sha256.c15
-rw-r--r--crypto/sha512.c2
-rw-r--r--crypto/tcrypt.c16
-rw-r--r--crypto/tcrypt.h131
-rw-r--r--crypto/tea.c4
-rw-r--r--crypto/tgr192.c735
-rw-r--r--drivers/Makefile3
-rw-r--r--drivers/acorn/char/i2c.c2
-rw-r--r--drivers/acorn/char/pcf8583.c1
-rw-r--r--drivers/acpi/Kconfig34
-rw-r--r--drivers/acpi/pci_irq.c6
-rw-r--r--drivers/acpi/sleep/proc.c5
-rw-r--r--drivers/atm/ambassador.c38
-rw-r--r--drivers/atm/ambassador.h100
-rw-r--r--drivers/atm/atmtcp.c14
-rw-r--r--drivers/atm/firestream.c2
-rw-r--r--drivers/atm/fore200e.c178
-rw-r--r--drivers/atm/fore200e.h2
-rw-r--r--drivers/atm/he.c4
-rw-r--r--drivers/atm/horizon.c2
-rw-r--r--drivers/atm/idt77252.c9
-rw-r--r--drivers/atm/iphase.c16
-rw-r--r--drivers/atm/lanai.c43
-rw-r--r--drivers/atm/nicstar.c6
-rw-r--r--drivers/atm/nicstar.h4
-rw-r--r--drivers/atm/zatm.c16
-rw-r--r--drivers/base/bus.c4
-rw-r--r--drivers/base/class.c96
-rw-r--r--drivers/base/class_simple.c21
-rw-r--r--drivers/base/dmapool.c2
-rw-r--r--drivers/base/driver.c13
-rw-r--r--drivers/base/map.c21
-rw-r--r--drivers/base/platform.c2
-rw-r--r--drivers/base/power/suspend.c2
-rw-r--r--drivers/base/sys.c39
-rw-r--r--drivers/base/transport_class.c24
-rw-r--r--drivers/block/DAC960.c4
-rw-r--r--drivers/block/Kconfig12
-rw-r--r--drivers/block/aoe/aoe.h1
-rw-r--r--drivers/block/aoe/aoeblk.c6
-rw-r--r--drivers/block/aoe/aoechr.c41
-rw-r--r--drivers/block/aoe/aoecmd.c8
-rw-r--r--drivers/block/as-iosched.c32
-rw-r--r--drivers/block/cciss.c119
-rw-r--r--drivers/block/cciss.h8
-rw-r--r--drivers/block/cciss_scsi.c35
-rw-r--r--drivers/block/cciss_scsi.h1
-rw-r--r--drivers/block/cfq-iosched.c18
-rw-r--r--drivers/block/cpqarray.c13
-rw-r--r--drivers/block/deadline-iosched.c4
-rw-r--r--drivers/block/elevator.c48
-rw-r--r--drivers/block/floppy.c23
-rw-r--r--drivers/block/genhd.c58
-rw-r--r--drivers/block/ll_rw_blk.c266
-rw-r--r--drivers/block/loop.c163
-rw-r--r--drivers/block/nbd.c8
-rw-r--r--drivers/block/paride/pcd.c22
-rw-r--r--drivers/block/paride/pd.c24
-rw-r--r--drivers/block/paride/pf.c25
-rw-r--r--drivers/block/paride/pg.c21
-rw-r--r--drivers/block/paride/pt.c22
-rw-r--r--drivers/block/paride/setup.h69
-rw-r--r--drivers/block/pktcdvd.c18
-rw-r--r--drivers/block/rd.c6
-rw-r--r--drivers/block/ub.c81
-rw-r--r--drivers/block/umem.c4
-rw-r--r--drivers/block/viodasd.c6
-rw-r--r--drivers/block/xd.c2
-rw-r--r--drivers/bluetooth/bfusb.c8
-rw-r--r--drivers/bluetooth/bluecard_cs.c14
-rw-r--r--drivers/bluetooth/hci_bcsp.c70
-rw-r--r--drivers/bluetooth/hci_usb.c2
-rw-r--r--drivers/bluetooth/hci_vhci.c11
-rw-r--r--drivers/cdrom/Kconfig56
-rw-r--r--drivers/cdrom/Makefile1
-rw-r--r--drivers/cdrom/cdu31a.c714
-rw-r--r--drivers/cdrom/mcd.c1565
-rw-r--r--drivers/cdrom/mcd.h106
-rw-r--r--drivers/cdrom/sbpcd.c6
-rw-r--r--drivers/cdrom/sjcd.c16
-rw-r--r--drivers/char/Kconfig33
-rw-r--r--drivers/char/Makefile6
-rw-r--r--drivers/char/agp/Kconfig25
-rw-r--r--drivers/char/agp/Makefile3
-rw-r--r--drivers/char/agp/agp.h35
-rw-r--r--drivers/char/agp/ali-agp.c6
-rw-r--r--drivers/char/agp/alpha-agp.c7
-rw-r--r--drivers/char/agp/amd-k7-agp.c56
-rw-r--r--drivers/char/agp/amd64-agp.c5
-rw-r--r--drivers/char/agp/ati-agp.c9
-rw-r--r--drivers/char/agp/backend.c128
-rw-r--r--drivers/char/agp/efficeon-agp.c8
-rw-r--r--drivers/char/agp/frontend.c74
-rw-r--r--drivers/char/agp/generic.c513
-rw-r--r--drivers/char/agp/hp-agp.c15
-rw-r--r--drivers/char/agp/i460-agp.c21
-rw-r--r--drivers/char/agp/intel-agp.c34
-rw-r--r--drivers/char/agp/intel-mch-agp.c643
-rw-r--r--drivers/char/agp/nvidia-agp.c5
-rw-r--r--drivers/char/agp/sgi-agp.c331
-rw-r--r--drivers/char/agp/sis-agp.c14
-rw-r--r--drivers/char/agp/sworks-agp.c16
-rw-r--r--drivers/char/agp/uninorth-agp.c359
-rw-r--r--drivers/char/agp/via-agp.c34
-rw-r--r--drivers/char/console_macros.h71
-rw-r--r--drivers/char/consolemap.c117
-rw-r--r--drivers/char/digi_bios.h177
-rw-r--r--drivers/char/digi_fep.h517
-rw-r--r--drivers/char/drm/Kconfig2
-rw-r--r--drivers/char/drm/drmP.h51
-rw-r--r--drivers/char/drm/drm_agpsupport.c49
-rw-r--r--drivers/char/drm/drm_auth.c4
-rw-r--r--drivers/char/drm/drm_bufs.c20
-rw-r--r--drivers/char/drm/drm_context.c12
-rw-r--r--drivers/char/drm/drm_core.h14
-rw-r--r--drivers/char/drm/drm_drv.c68
-rw-r--r--drivers/char/drm/drm_fops.c20
-rw-r--r--drivers/char/drm/drm_ioctl.c12
-rw-r--r--drivers/char/drm/drm_irq.c6
-rw-r--r--drivers/char/drm/drm_lock.c4
-rw-r--r--drivers/char/drm/drm_memory.c4
-rw-r--r--drivers/char/drm/drm_os_linux.h4
-rw-r--r--drivers/char/drm/drm_pciids.h5
-rw-r--r--drivers/char/drm/drm_proc.c6
-rw-r--r--drivers/char/drm/drm_scatter.c4
-rw-r--r--drivers/char/drm/drm_stub.c176
-rw-r--r--drivers/char/drm/drm_sysfs.c4
-rw-r--r--drivers/char/drm/drm_vm.c24
-rw-r--r--drivers/char/drm/i810_dma.c132
-rw-r--r--drivers/char/drm/i810_drv.c3
-rw-r--r--drivers/char/drm/i810_drv.h46
-rw-r--r--drivers/char/drm/i830_dma.c144
-rw-r--r--drivers/char/drm/i830_drv.c3
-rw-r--r--drivers/char/drm/i830_drv.h40
-rw-r--r--drivers/char/drm/i830_irq.c4
-rw-r--r--drivers/char/drm/i915_drv.c2
-rw-r--r--drivers/char/drm/mga_dma.c61
-rw-r--r--drivers/char/drm/mga_drv.c2
-rw-r--r--drivers/char/drm/mga_drv.h13
-rw-r--r--drivers/char/drm/mga_state.c44
-rw-r--r--drivers/char/drm/r128_cce.c4
-rw-r--r--drivers/char/drm/r128_drv.c2
-rw-r--r--drivers/char/drm/r128_drv.h16
-rw-r--r--drivers/char/drm/r128_state.c62
-rw-r--r--drivers/char/drm/radeon_cp.c5
-rw-r--r--drivers/char/drm/radeon_drm.h10
-rw-r--r--drivers/char/drm/radeon_drv.c2
-rw-r--r--drivers/char/drm/radeon_drv.h43
-rw-r--r--drivers/char/drm/radeon_irq.c10
-rw-r--r--drivers/char/drm/radeon_state.c262
-rw-r--r--drivers/char/drm/sis_drv.c2
-rw-r--r--drivers/char/drm/sis_drv.h7
-rw-r--r--drivers/char/drm/sis_ds.c84
-rw-r--r--drivers/char/drm/sis_ds.h19
-rw-r--r--drivers/char/drm/sis_mm.c41
-rw-r--r--drivers/char/drm/tdfx_drv.c2
-rw-r--r--drivers/char/esp.c268
-rw-r--r--drivers/char/fep.h168
-rw-r--r--drivers/char/ftape/lowlevel/fdc-io.c3
-rw-r--r--drivers/char/generic_nvram.c4
-rw-r--r--drivers/char/generic_serial.c115
-rw-r--r--drivers/char/hp600_keyb.c340
-rw-r--r--drivers/char/hpet.c6
-rw-r--r--drivers/char/hvsi.c40
-rw-r--r--drivers/char/ipmi/ipmi_msghandler.c32
-rw-r--r--drivers/char/ipmi/ipmi_si_intf.c105
-rw-r--r--drivers/char/isicom.c10
-rw-r--r--drivers/char/istallion.c76
-rw-r--r--drivers/char/keyboard.c24
-rw-r--r--drivers/char/lp.c28
-rw-r--r--drivers/char/mem.c290
-rw-r--r--drivers/char/mmtimer.c80
-rw-r--r--drivers/char/moxa.c2
-rw-r--r--drivers/char/mwave/smapi.c16
-rw-r--r--drivers/char/mxser.c22
-rw-r--r--drivers/char/n_hdlc.c10
-rw-r--r--drivers/char/n_tty.c8
-rw-r--r--drivers/char/nwflash.c2
-rw-r--r--drivers/char/pcxx.c2353
-rw-r--r--drivers/char/pcxx.h128
-rw-r--r--drivers/char/pty.c6
-rw-r--r--drivers/char/random.c1364
-rw-r--r--drivers/char/rio/rio_linux.c16
-rw-r--r--drivers/char/rio/riocmd.c67
-rw-r--r--drivers/char/rtc.c112
-rw-r--r--drivers/char/s3c2410-rtc.c5
-rw-r--r--drivers/char/selection.c14
-rw-r--r--drivers/char/snsc.c4
-rw-r--r--drivers/char/specialix.c990
-rw-r--r--drivers/char/specialix_io8.h9
-rw-r--r--drivers/char/stallion.c151
-rw-r--r--drivers/char/sx.c70
-rw-r--r--drivers/char/synclinkmp.c12
-rw-r--r--drivers/char/sysrq.c62
-rw-r--r--drivers/char/tb0219.c347
-rw-r--r--drivers/char/tpm/Kconfig39
-rw-r--r--drivers/char/tpm/Makefile7
-rw-r--r--drivers/char/tpm/tpm.c697
-rw-r--r--drivers/char/tpm/tpm.h93
-rw-r--r--drivers/char/tpm/tpm_atmel.c216
-rw-r--r--drivers/char/tpm/tpm_nsc.c373
-rw-r--r--drivers/char/tpqic02.c2812
-rw-r--r--drivers/char/tty_io.c5
-rw-r--r--drivers/char/vc_screen.c7
-rw-r--r--drivers/char/vr41xx_rtc.c709
-rw-r--r--drivers/char/vt.c1747
-rw-r--r--drivers/char/vt_ioctl.c168
-rw-r--r--drivers/char/watchdog/Kconfig4
-rw-r--r--drivers/char/watchdog/Makefile13
-rw-r--r--drivers/char/watchdog/machzwd.c2
-rw-r--r--drivers/char/watchdog/pcwd_pci.c6
-rw-r--r--drivers/char/watchdog/pcwd_usb.c6
-rw-r--r--drivers/char/watchdog/s3c2410_wdt.c14
-rw-r--r--drivers/char/watchdog/sa1100_wdt.c2
-rw-r--r--drivers/char/watchdog/sc1200wdt.c6
-rw-r--r--drivers/char/watchdog/scx200_wdt.c42
-rw-r--r--drivers/cpufreq/Kconfig20
-rw-r--r--drivers/cpufreq/proc_intf.c0
-rw-r--r--drivers/eisa/pci_eisa.c3
-rw-r--r--drivers/firmware/efivars.c44
-rw-r--r--drivers/i2c/algos/i2c-algo-ite.c4
-rw-r--r--drivers/i2c/algos/i2c-algo-pca.c30
-rw-r--r--drivers/i2c/algos/i2c-algo-pcf.c2
-rw-r--r--drivers/i2c/algos/i2c-algo-sgi.c2
-rw-r--r--drivers/i2c/busses/Kconfig12
-rw-r--r--drivers/i2c/busses/Makefile1
-rw-r--r--drivers/i2c/busses/i2c-au1550.c2
-rw-r--r--drivers/i2c/busses/i2c-elektor.c1
-rw-r--r--drivers/i2c/busses/i2c-ibm_iic.c2
-rw-r--r--drivers/i2c/busses/i2c-iop3xx.c2
-rw-r--r--drivers/i2c/busses/i2c-ixp4xx.c4
-rw-r--r--drivers/i2c/busses/i2c-keywest.c2
-rw-r--r--drivers/i2c/busses/i2c-mpc.c2
-rw-r--r--drivers/i2c/busses/i2c-mv64xxx.c596
-rw-r--r--drivers/i2c/busses/i2c-nforce2.c6
-rw-r--r--drivers/i2c/busses/i2c-s3c2410.c5
-rw-r--r--drivers/i2c/chips/Kconfig46
-rw-r--r--drivers/i2c/chips/Makefile4
-rw-r--r--drivers/i2c/chips/adm1021.c9
-rw-r--r--drivers/i2c/chips/adm1025.c12
-rw-r--r--drivers/i2c/chips/adm1026.c87
-rw-r--r--drivers/i2c/chips/adm1031.c9
-rw-r--r--drivers/i2c/chips/asb100.c9
-rw-r--r--drivers/i2c/chips/ds1621.c9
-rw-r--r--drivers/i2c/chips/eeprom.c7
-rw-r--r--drivers/i2c/chips/fscher.c11
-rw-r--r--drivers/i2c/chips/fscpos.c631
-rw-r--r--drivers/i2c/chips/gl518sm.c12
-rw-r--r--drivers/i2c/chips/gl520sm.c754
-rw-r--r--drivers/i2c/chips/isp1301_omap.c1
-rw-r--r--drivers/i2c/chips/it87.c76
-rw-r--r--drivers/i2c/chips/lm63.c5
-rw-r--r--drivers/i2c/chips/lm75.c9
-rw-r--r--drivers/i2c/chips/lm77.c9
-rw-r--r--drivers/i2c/chips/lm78.c58
-rw-r--r--drivers/i2c/chips/lm80.c30
-rw-r--r--drivers/i2c/chips/lm83.c12
-rw-r--r--drivers/i2c/chips/lm85.c14
-rw-r--r--drivers/i2c/chips/lm87.c12
-rw-r--r--drivers/i2c/chips/lm90.c12
-rw-r--r--drivers/i2c/chips/m41t00.c247
-rw-r--r--drivers/i2c/chips/max1619.c13
-rw-r--r--drivers/i2c/chips/pc87360.c4
-rw-r--r--drivers/i2c/chips/pcf8574.c4
-rw-r--r--drivers/i2c/chips/pcf8591.c4
-rw-r--r--drivers/i2c/chips/rtc8564.c18
-rw-r--r--drivers/i2c/chips/sis5595.c794
-rw-r--r--drivers/i2c/chips/smsc47b397.c5
-rw-r--r--drivers/i2c/chips/smsc47m1.c9
-rw-r--r--drivers/i2c/chips/via686a.c6
-rw-r--r--drivers/i2c/chips/w83627hf.c26
-rw-r--r--drivers/i2c/chips/w83781d.c29
-rw-r--r--drivers/i2c/chips/w83l785ts.c12
-rw-r--r--drivers/i2c/i2c-core.c81
-rw-r--r--drivers/i2c/i2c-dev.c18
-rw-r--r--drivers/i2c/i2c-sensor-detect.c7
-rw-r--r--drivers/ide/Kconfig1
-rw-r--r--drivers/ide/arm/icside.c2
-rw-r--r--drivers/ide/arm/rapide.c2
-rw-r--r--drivers/ide/ide-cd.c157
-rw-r--r--drivers/ide/ide-cd.h2
-rw-r--r--drivers/ide/ide-default.c17
-rw-r--r--drivers/ide/ide-disk.c388
-rw-r--r--drivers/ide/ide-floppy.c132
-rw-r--r--drivers/ide/ide-io.c333
-rw-r--r--drivers/ide/ide-iops.c20
-rw-r--r--drivers/ide/ide-probe.c62
-rw-r--r--drivers/ide/ide-proc.c8
-rw-r--r--drivers/ide/ide-tape.c205
-rw-r--r--drivers/ide/ide-taskfile.c6
-rw-r--r--drivers/ide/ide.c83
-rw-r--r--drivers/ide/pci/cs5520.c3
-rw-r--r--drivers/ide/pci/hpt366.c29
-rw-r--r--drivers/ide/pci/sgiioc4.c45
-rw-r--r--drivers/ide/ppc/pmac.c196
-rw-r--r--drivers/ieee1394/Kconfig1
-rw-r--r--drivers/ieee1394/amdtp.c16
-rw-r--r--drivers/ieee1394/config_roms.c2
-rw-r--r--drivers/ieee1394/csr1212.c132
-rw-r--r--drivers/ieee1394/dma.c14
-rw-r--r--drivers/ieee1394/dv1394.c18
-rw-r--r--drivers/ieee1394/eth1394.c19
-rw-r--r--drivers/ieee1394/highlevel.c34
-rw-r--r--drivers/ieee1394/ieee1394.h24
-rw-r--r--drivers/ieee1394/ieee1394_core.c81
-rw-r--r--drivers/ieee1394/ieee1394_core.h3
-rw-r--r--drivers/ieee1394/ieee1394_transactions.c28
-rw-r--r--drivers/ieee1394/nodemgr.c180
-rw-r--r--drivers/ieee1394/nodemgr.h2
-rw-r--r--drivers/ieee1394/ohci1394.c108
-rw-r--r--drivers/ieee1394/pcilynx.c76
-rw-r--r--drivers/ieee1394/raw1394.c4000
-rw-r--r--drivers/ieee1394/sbp2.c88
-rw-r--r--drivers/ieee1394/sbp2.h16
-rw-r--r--drivers/ieee1394/video1394.c173
-rw-r--r--drivers/infiniband/core/agent.c66
-rw-r--r--drivers/infiniband/core/agent_priv.h3
-rw-r--r--drivers/infiniband/core/cache.c4
-rw-r--r--drivers/infiniband/core/mad.c79
-rw-r--r--drivers/infiniband/core/mad_priv.h8
-rw-r--r--drivers/infiniband/core/smi.c2
-rw-r--r--drivers/infiniband/hw/mthca/Makefile2
-rw-r--r--drivers/infiniband/hw/mthca/mthca_av.c46
-rw-r--r--drivers/infiniband/hw/mthca/mthca_cmd.c9
-rw-r--r--drivers/infiniband/hw/mthca/mthca_cmd.h16
-rw-r--r--drivers/infiniband/hw/mthca/mthca_config_reg.h1
-rw-r--r--drivers/infiniband/hw/mthca/mthca_cq.c385
-rw-r--r--drivers/infiniband/hw/mthca/mthca_dev.h59
-rw-r--r--drivers/infiniband/hw/mthca/mthca_doorbell.h12
-rw-r--r--drivers/infiniband/hw/mthca/mthca_eq.c314
-rw-r--r--drivers/infiniband/hw/mthca/mthca_main.c241
-rw-r--r--drivers/infiniband/hw/mthca/mthca_memfree.c273
-rw-r--r--drivers/infiniband/hw/mthca/mthca_memfree.h45
-rw-r--r--drivers/infiniband/hw/mthca/mthca_mr.c46
-rw-r--r--drivers/infiniband/hw/mthca/mthca_profile.c11
-rw-r--r--drivers/infiniband/hw/mthca/mthca_provider.c40
-rw-r--r--drivers/infiniband/hw/mthca/mthca_provider.h55
-rw-r--r--drivers/infiniband/hw/mthca/mthca_qp.c649
-rw-r--r--drivers/infiniband/hw/mthca/mthca_reset.c2
-rw-r--r--drivers/infiniband/hw/mthca/mthca_uar.c78
-rw-r--r--drivers/infiniband/include/ib_verbs.h7
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib.h4
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_ib.c6
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_main.c52
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_multicast.c12
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_verbs.c1
-rw-r--r--drivers/input/Kconfig25
-rw-r--r--drivers/input/evbug.c4
-rw-r--r--drivers/input/evdev.c16
-rw-r--r--drivers/input/gameport/Kconfig48
-rw-r--r--drivers/input/gameport/cs461x.c37
-rw-r--r--drivers/input/gameport/emu10k1-gp.c46
-rw-r--r--drivers/input/gameport/fm801-gp.c63
-rw-r--r--drivers/input/gameport/gameport.c705
-rw-r--r--drivers/input/gameport/lightning.c180
-rw-r--r--drivers/input/gameport/ns558.c159
-rw-r--r--drivers/input/gameport/vortex.c82
-rw-r--r--drivers/input/input.c17
-rw-r--r--drivers/input/joydev.c39
-rw-r--r--drivers/input/joystick/Kconfig46
-rw-r--r--drivers/input/joystick/a3d.c174
-rw-r--r--drivers/input/joystick/adi.c122
-rw-r--r--drivers/input/joystick/analog.c102
-rw-r--r--drivers/input/joystick/cobra.c88
-rw-r--r--drivers/input/joystick/db9.c4
-rw-r--r--drivers/input/joystick/gamecon.c23
-rw-r--r--drivers/input/joystick/gf2k.c92
-rw-r--r--drivers/input/joystick/grip.c103
-rw-r--r--drivers/input/joystick/grip_mp.c97
-rw-r--r--drivers/input/joystick/guillemot.c95
-rw-r--r--drivers/input/joystick/iforce/iforce-serio.c45
-rw-r--r--drivers/input/joystick/interact.c80
-rw-r--r--drivers/input/joystick/joydump.c92
-rw-r--r--drivers/input/joystick/magellan.c46
-rw-r--r--drivers/input/joystick/sidewinder.c157
-rw-r--r--drivers/input/joystick/spaceball.c52
-rw-r--r--drivers/input/joystick/spaceorb.c46
-rw-r--r--drivers/input/joystick/stinger.c47
-rw-r--r--drivers/input/joystick/tmdc.c102
-rw-r--r--drivers/input/joystick/turbografx.c6
-rw-r--r--drivers/input/joystick/twidjoy.c44
-rw-r--r--drivers/input/joystick/warrior.c43
-rw-r--r--drivers/input/keyboard/Kconfig114
-rw-r--r--drivers/input/keyboard/Makefile5
-rw-r--r--drivers/input/keyboard/atkbd.c146
-rw-r--r--drivers/input/keyboard/corgikbd.c361
-rw-r--r--drivers/input/keyboard/hil_kbd.c375
-rw-r--r--drivers/input/keyboard/hilkbd.c343
-rw-r--r--drivers/input/keyboard/hpps2atkbd.h13
-rw-r--r--drivers/input/keyboard/lkkbd.c47
-rw-r--r--drivers/input/keyboard/locomokbd.c309
-rw-r--r--drivers/input/keyboard/newtonkbd.c48
-rw-r--r--drivers/input/keyboard/sunkbd.c52
-rw-r--r--drivers/input/keyboard/xtkbd.c47
-rw-r--r--drivers/input/misc/Kconfig23
-rw-r--r--drivers/input/misc/Makefile1
-rw-r--r--drivers/input/misc/hp_sdc_rtc.c724
-rw-r--r--drivers/input/misc/pcspkr.c4
-rw-r--r--drivers/input/misc/uinput.c227
-rw-r--r--drivers/input/mouse/Kconfig31
-rw-r--r--drivers/input/mouse/Makefile1
-rw-r--r--drivers/input/mouse/alps.c331
-rw-r--r--drivers/input/mouse/alps.h15
-rw-r--r--drivers/input/mouse/hil_ptr.c414
-rw-r--r--drivers/input/mouse/logips2pp.c23
-rw-r--r--drivers/input/mouse/psmouse-base.c149
-rw-r--r--drivers/input/mouse/psmouse.h2
-rw-r--r--drivers/input/mouse/sermouse.c87
-rw-r--r--drivers/input/mouse/synaptics.c73
-rw-r--r--drivers/input/mouse/synaptics.h2
-rw-r--r--drivers/input/mouse/vsxxxaa.c43
-rw-r--r--drivers/input/mousedev.c41
-rw-r--r--drivers/input/power.c12
-rw-r--r--drivers/input/serio/Kconfig57
-rw-r--r--drivers/input/serio/Makefile2
-rw-r--r--drivers/input/serio/ambakmi.c2
-rw-r--r--drivers/input/serio/ct82c710.c6
-rw-r--r--drivers/input/serio/gscps2.c14
-rw-r--r--drivers/input/serio/hil_mlc.c949
-rw-r--r--drivers/input/serio/hp_sdc.c1054
-rw-r--r--drivers/input/serio/hp_sdc_mlc.c358
-rw-r--r--drivers/input/serio/i8042-x86ia64io.h319
-rw-r--r--drivers/input/serio/i8042.c401
-rw-r--r--drivers/input/serio/i8042.h10
-rw-r--r--drivers/input/serio/maceps2.c2
-rw-r--r--drivers/input/serio/parkbd.c56
-rw-r--r--drivers/input/serio/pcips2.c4
-rw-r--r--drivers/input/serio/q40kbd.c2
-rw-r--r--drivers/input/serio/rpckbd.c2
-rw-r--r--drivers/input/serio/sa1111ps2.c2
-rw-r--r--drivers/input/serio/serio.c546
-rw-r--r--drivers/input/serio/serio_raw.c43
-rw-r--r--drivers/input/serio/serport.c20
-rw-r--r--drivers/input/touchscreen/Kconfig71
-rw-r--r--drivers/input/touchscreen/Makefile5
-rw-r--r--drivers/input/touchscreen/corgi_ts.c380
-rw-r--r--drivers/input/touchscreen/elo.c315
-rw-r--r--drivers/input/touchscreen/gunze.c56
-rw-r--r--drivers/input/touchscreen/h3600_ts_input.c52
-rw-r--r--drivers/input/touchscreen/hp680_ts_input.c135
-rw-r--r--drivers/input/touchscreen/mk712.c222
-rw-r--r--drivers/input/touchscreen/mtouch.c219
-rw-r--r--drivers/input/tsdev.c11
-rw-r--r--drivers/isdn/Makefile1
-rw-r--r--drivers/isdn/act2000/act2000_isa.c7
-rw-r--r--drivers/isdn/hardware/avm/b1pci.c2
-rw-r--r--drivers/isdn/hardware/avm/c4.c2
-rw-r--r--drivers/isdn/hardware/avm/t1pci.c2
-rw-r--r--drivers/isdn/hisax/Kconfig6
-rw-r--r--drivers/isdn/hisax/Makefile1
-rw-r--r--drivers/isdn/hisax/elsa.c4
-rw-r--r--drivers/isdn/hisax/hfc4s8s_l1.c1714
-rw-r--r--drivers/isdn/hisax/hfc4s8s_l1.h88
-rw-r--r--drivers/isdn/hisax/hfc_sx.c4
-rw-r--r--drivers/isdn/hisax/hfc_usb.c2289
-rw-r--r--drivers/isdn/hisax/hfc_usb.h228
-rw-r--r--drivers/isdn/hisax/hisax_fcpcipnp.c8
-rw-r--r--drivers/isdn/hisax/icc.c2
-rw-r--r--drivers/isdn/hisax/icc.h2
-rw-r--r--drivers/isdn/hisax/sedlbauer.c4
-rw-r--r--drivers/isdn/hisax/teles3.c4
-rw-r--r--drivers/isdn/hisax/w6692.c2
-rw-r--r--drivers/isdn/i4l/Kconfig2
-rw-r--r--drivers/isdn/i4l/isdn_common.c28
-rw-r--r--drivers/isdn/i4l/isdn_net.c1
-rw-r--r--drivers/isdn/i4l/isdn_ppp.c15
-rw-r--r--drivers/isdn/icn/icn.c5
-rw-r--r--drivers/isdn/isdnloop/isdnloop.c4
-rw-r--r--drivers/isdn/tpam/Kconfig15
-rw-r--r--drivers/isdn/tpam/Makefile11
-rw-r--r--drivers/isdn/tpam/tpam.h229
-rw-r--r--drivers/isdn/tpam/tpam_commands.c987
-rw-r--r--drivers/isdn/tpam/tpam_crcpc.c162
-rw-r--r--drivers/isdn/tpam/tpam_hdlc.c923
-rw-r--r--drivers/isdn/tpam/tpam_main.c297
-rw-r--r--drivers/isdn/tpam/tpam_memory.c247
-rw-r--r--drivers/isdn/tpam/tpam_nco.c651
-rw-r--r--drivers/isdn/tpam/tpam_queues.c401
-rw-r--r--drivers/macintosh/Kconfig8
-rw-r--r--drivers/macintosh/Makefile1
-rw-r--r--drivers/macintosh/adb.c12
-rw-r--r--drivers/macintosh/ans-lcd.c2
-rw-r--r--drivers/macintosh/macio_asic.c2
-rw-r--r--drivers/macintosh/macserial.c6
-rw-r--r--drivers/macintosh/mediabay.c32
-rw-r--r--drivers/macintosh/nvram.c4
-rw-r--r--drivers/macintosh/smu.c364
-rw-r--r--drivers/macintosh/therm_adt746x.c10
-rw-r--r--drivers/macintosh/therm_pm72.c488
-rw-r--r--drivers/macintosh/therm_pm72.h76
-rw-r--r--drivers/macintosh/therm_windtunnel.c4
-rw-r--r--drivers/macintosh/via-pmu.c105
-rw-r--r--drivers/md/Kconfig31
-rw-r--r--drivers/md/Makefile3
-rw-r--r--drivers/md/dm-bio-record.h45
-rw-r--r--drivers/md/dm-crypt.c6
-rw-r--r--drivers/md/dm-emc.c359
-rw-r--r--drivers/md/dm-hw-handler.c216
-rw-r--r--drivers/md/dm-hw-handler.h61
-rw-r--r--drivers/md/dm-io.c221
-rw-r--r--drivers/md/dm-linear.c5
-rw-r--r--drivers/md/dm-mpath.c1302
-rw-r--r--drivers/md/dm-mpath.h25
-rw-r--r--drivers/md/dm-path-selector.c156
-rw-r--r--drivers/md/dm-path-selector.h93
-rw-r--r--drivers/md/dm-raid1.c15
-rw-r--r--drivers/md/dm-round-robin.c214
-rw-r--r--drivers/md/dm-snap.c11
-rw-r--r--drivers/md/dm-stripe.c7
-rw-r--r--drivers/md/dm-table.c2
-rw-r--r--drivers/md/dm-zero.c17
-rw-r--r--drivers/md/dm.c19
-rw-r--r--drivers/md/dm.h2
-rw-r--r--drivers/md/md.c21
-rw-r--r--drivers/md/multipath.c2
-rw-r--r--drivers/md/raid1.c46
-rw-r--r--drivers/md/raid10.c4
-rw-r--r--drivers/md/raid5.c13
-rw-r--r--drivers/md/raid6altivec.uc2
-rw-r--r--drivers/md/raid6main.c12
-rw-r--r--drivers/media/common/ir-common.c164
-rw-r--r--drivers/media/common/saa7146_core.c86
-rw-r--r--drivers/media/common/saa7146_fops.c4
-rw-r--r--drivers/media/common/saa7146_hlp.c226
-rw-r--r--drivers/media/common/saa7146_i2c.c60
-rw-r--r--drivers/media/common/saa7146_vbi.c135
-rw-r--r--drivers/media/common/saa7146_video.c198
-rw-r--r--drivers/media/common/saa7146_vv_ksyms.c3
-rw-r--r--drivers/media/dvb/Kconfig6
-rw-r--r--drivers/media/dvb/b2c2/b2c2-common.c2
-rw-r--r--drivers/media/dvb/b2c2/b2c2-usb-core.c11
-rw-r--r--drivers/media/dvb/b2c2/skystar2.c26
-rw-r--r--drivers/media/dvb/bt8xx/Kconfig4
-rw-r--r--drivers/media/dvb/bt8xx/bt878.c21
-rw-r--r--drivers/media/dvb/bt8xx/bt878.h3
-rw-r--r--drivers/media/dvb/bt8xx/dst.c8
-rw-r--r--drivers/media/dvb/bt8xx/dst_priv.h1
-rw-r--r--drivers/media/dvb/bt8xx/dvb-bt8xx.c198
-rw-r--r--drivers/media/dvb/bt8xx/dvb-bt8xx.h5
-rw-r--r--drivers/media/dvb/cinergyT2/cinergyT2.c150
-rw-r--r--drivers/media/dvb/dibusb/Kconfig3
-rw-r--r--drivers/media/dvb/dibusb/Makefile2
-rw-r--r--drivers/media/dvb/dibusb/dvb-dibusb-core.c144
-rw-r--r--drivers/media/dvb/dibusb/dvb-dibusb-dvb.c48
-rw-r--r--drivers/media/dvb/dibusb/dvb-dibusb-fe-i2c.c238
-rw-r--r--drivers/media/dvb/dibusb/dvb-dibusb-firmware.c6
-rw-r--r--drivers/media/dvb/dibusb/dvb-dibusb-pid.c80
-rw-r--r--drivers/media/dvb/dibusb/dvb-dibusb-remote.c177
-rw-r--r--drivers/media/dvb/dibusb/dvb-dibusb-usb.c150
-rw-r--r--drivers/media/dvb/dibusb/dvb-dibusb.h76
-rw-r--r--drivers/media/dvb/dibusb/dvb-fe-dtt200u.c263
-rw-r--r--drivers/media/dvb/dvb-core/demux.h299
-rw-r--r--drivers/media/dvb/dvb-core/dmxdev.c226
-rw-r--r--drivers/media/dvb/dvb-core/dmxdev.h2
-rw-r--r--drivers/media/dvb/dvb-core/dvb_ca_en50221.c1768
-rw-r--r--drivers/media/dvb/dvb-core/dvb_demux.c433
-rw-r--r--drivers/media/dvb/dvb-core/dvb_demux.h24
-rw-r--r--drivers/media/dvb/dvb-core/dvb_filter.c63
-rw-r--r--drivers/media/dvb/dvb-core/dvb_filter.h34
-rw-r--r--drivers/media/dvb/dvb-core/dvb_frontend.c136
-rw-r--r--drivers/media/dvb/dvb-core/dvb_frontend.h2
-rw-r--r--drivers/media/dvb/dvb-core/dvb_net.c210
-rw-r--r--drivers/media/dvb/dvb-core/dvb_net.h3
-rw-r--r--drivers/media/dvb/dvb-core/dvb_ringbuffer.c18
-rw-r--r--drivers/media/dvb/dvb-core/dvb_ringbuffer.h18
-rw-r--r--drivers/media/dvb/dvb-core/dvbdev.c39
-rw-r--r--drivers/media/dvb/dvb-core/dvbdev.h8
-rw-r--r--drivers/media/dvb/frontends/Kconfig16
-rw-r--r--drivers/media/dvb/frontends/Makefile4
-rw-r--r--drivers/media/dvb/frontends/at76c651.c75
-rw-r--r--drivers/media/dvb/frontends/cx22700.c22
-rw-r--r--drivers/media/dvb/frontends/cx22702.c61
-rw-r--r--drivers/media/dvb/frontends/cx24110.c124
-rw-r--r--drivers/media/dvb/frontends/dib3000-common.c2
-rw-r--r--drivers/media/dvb/frontends/dib3000-common.h8
-rw-r--r--drivers/media/dvb/frontends/dib3000.h2
-rw-r--r--drivers/media/dvb/frontends/dib3000mb.c265
-rw-r--r--drivers/media/dvb/frontends/dib3000mc.c130
-rw-r--r--drivers/media/dvb/frontends/dib3000mc_priv.h14
-rw-r--r--drivers/media/dvb/frontends/dvb-pll.c168
-rw-r--r--drivers/media/dvb/frontends/dvb-pll.h34
-rw-r--r--drivers/media/dvb/frontends/dvb_dummy_fe.c86
-rw-r--r--drivers/media/dvb/frontends/l64781.c21
-rw-r--r--drivers/media/dvb/frontends/l64781.h5
-rw-r--r--drivers/media/dvb/frontends/mt312.c53
-rw-r--r--drivers/media/dvb/frontends/mt312.h2
-rw-r--r--drivers/media/dvb/frontends/mt352.c244
-rw-r--r--drivers/media/dvb/frontends/mt352.h15
-rw-r--r--drivers/media/dvb/frontends/nxt2002.c125
-rw-r--r--drivers/media/dvb/frontends/nxt2002.h2
-rw-r--r--drivers/media/dvb/frontends/nxt6000.c544
-rw-r--r--drivers/media/dvb/frontends/or51132.c628
-rw-r--r--drivers/media/dvb/frontends/or51132.h48
-rw-r--r--drivers/media/dvb/frontends/or51211.c631
-rw-r--r--drivers/media/dvb/frontends/or51211.h44
-rw-r--r--drivers/media/dvb/frontends/sp8870.c4
-rw-r--r--drivers/media/dvb/frontends/sp887x.c103
-rw-r--r--drivers/media/dvb/frontends/stv0297.c875
-rw-r--r--drivers/media/dvb/frontends/stv0299.c192
-rw-r--r--drivers/media/dvb/frontends/tda10021.c24
-rw-r--r--drivers/media/dvb/frontends/tda10021.h3
-rw-r--r--drivers/media/dvb/frontends/tda1004x.c81
-rw-r--r--drivers/media/dvb/frontends/tda8083.c42
-rw-r--r--drivers/media/dvb/frontends/tda80xx.c35
-rw-r--r--drivers/media/dvb/frontends/ves1820.c180
-rw-r--r--drivers/media/dvb/frontends/ves1820.h3
-rw-r--r--drivers/media/dvb/frontends/ves1x93.c183
-rw-r--r--drivers/media/dvb/ttpci/Kconfig1
-rw-r--r--drivers/media/dvb/ttpci/av7110.c1138
-rw-r--r--drivers/media/dvb/ttpci/av7110.h178
-rw-r--r--drivers/media/dvb/ttpci/av7110_av.c25
-rw-r--r--drivers/media/dvb/ttpci/av7110_av.h2
-rw-r--r--drivers/media/dvb/ttpci/av7110_ca.c20
-rw-r--r--drivers/media/dvb/ttpci/av7110_ca.h2
-rw-r--r--drivers/media/dvb/ttpci/av7110_hw.c24
-rw-r--r--drivers/media/dvb/ttpci/av7110_ipack.c167
-rw-r--r--drivers/media/dvb/ttpci/av7110_ipack.h3
-rw-r--r--drivers/media/dvb/ttpci/av7110_ir.c115
-rw-r--r--drivers/media/dvb/ttpci/av7110_v4l.c2
-rw-r--r--drivers/media/dvb/ttpci/budget-av.c235
-rw-r--r--drivers/media/dvb/ttpci/budget-ci.c193
-rw-r--r--drivers/media/dvb/ttpci/budget-core.c232
-rw-r--r--drivers/media/dvb/ttpci/budget-patch.c129
-rw-r--r--drivers/media/dvb/ttpci/budget.c88
-rw-r--r--drivers/media/dvb/ttpci/budget.h54
-rw-r--r--drivers/media/dvb/ttpci/ttpci-eeprom.c3
-rw-r--r--drivers/media/dvb/ttusb-budget/Kconfig2
-rw-r--r--drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c219
-rw-r--r--drivers/media/dvb/ttusb-dec/Kconfig2
-rw-r--r--drivers/media/dvb/ttusb-dec/ttusb_dec.c304
-rw-r--r--drivers/media/dvb/ttusb-dec/ttusbdecfe.c4
-rw-r--r--drivers/media/radio/miropcm20-radio.c12
-rw-r--r--drivers/media/radio/radio-sf16fmi.c10
-rw-r--r--drivers/media/radio/radio-zoltrix.c26
-rw-r--r--drivers/media/video/Kconfig15
-rw-r--r--drivers/media/video/Makefile1
-rw-r--r--drivers/media/video/adv7170.c7
-rw-r--r--drivers/media/video/adv7175.c7
-rw-r--r--drivers/media/video/bt819.c16
-rw-r--r--drivers/media/video/bt856.c5
-rw-r--r--drivers/media/video/btcx-risc.c12
-rw-r--r--drivers/media/video/bttv-cards.c177
-rw-r--r--drivers/media/video/bttv-driver.c95
-rw-r--r--drivers/media/video/bttv-gpio.c17
-rw-r--r--drivers/media/video/bttv-i2c.c18
-rw-r--r--drivers/media/video/bttv.h5
-rw-r--r--drivers/media/video/bttvp.h5
-rw-r--r--drivers/media/video/c-qcam.c2
-rw-r--r--drivers/media/video/cpia_usb.c8
-rw-r--r--drivers/media/video/cx88/Makefile3
-rw-r--r--drivers/media/video/cx88/cx88-blackbird.c29
-rw-r--r--drivers/media/video/cx88/cx88-cards.c393
-rw-r--r--drivers/media/video/cx88/cx88-core.c42
-rw-r--r--drivers/media/video/cx88/cx88-dvb.c187
-rw-r--r--drivers/media/video/cx88/cx88-i2c.c4
-rw-r--r--drivers/media/video/cx88/cx88-input.c396
-rw-r--r--drivers/media/video/cx88/cx88-mpeg.c44
-rw-r--r--drivers/media/video/cx88/cx88-tvaudio.c457
-rw-r--r--drivers/media/video/cx88/cx88-vbi.c5
-rw-r--r--drivers/media/video/cx88/cx88-video.c36
-rw-r--r--drivers/media/video/cx88/cx88.h38
-rw-r--r--drivers/media/video/ir-kbd-gpio.c51
-rw-r--r--drivers/media/video/meye.c2
-rw-r--r--drivers/media/video/msp3400.c8
-rw-r--r--drivers/media/video/mt20xx.c558
-rw-r--r--drivers/media/video/ovcamchip/ovcamchip_core.c1
-rw-r--r--drivers/media/video/planb.c24
-rw-r--r--drivers/media/video/saa5246a.c14
-rw-r--r--drivers/media/video/saa5249.c14
-rw-r--r--drivers/media/video/saa7110.c48
-rw-r--r--drivers/media/video/saa7111.c5
-rw-r--r--drivers/media/video/saa7114.c7
-rw-r--r--drivers/media/video/saa7134/Makefile1
-rw-r--r--drivers/media/video/saa7134/saa6752hs.c318
-rw-r--r--drivers/media/video/saa7134/saa7134-cards.c400
-rw-r--r--drivers/media/video/saa7134/saa7134-core.c45
-rw-r--r--drivers/media/video/saa7134/saa7134-dvb.c191
-rw-r--r--drivers/media/video/saa7134/saa7134-empress.c60
-rw-r--r--drivers/media/video/saa7134/saa7134-i2c.c40
-rw-r--r--drivers/media/video/saa7134/saa7134-input.c60
-rw-r--r--drivers/media/video/saa7134/saa7134-oss.c6
-rw-r--r--drivers/media/video/saa7134/saa7134-ts.c7
-rw-r--r--drivers/media/video/saa7134/saa7134-tvaudio.c63
-rw-r--r--drivers/media/video/saa7134/saa7134-vbi.c3
-rw-r--r--drivers/media/video/saa7134/saa7134-video.c63
-rw-r--r--drivers/media/video/saa7134/saa7134.h21
-rw-r--r--drivers/media/video/saa7185.c7
-rw-r--r--drivers/media/video/stradis.c9
-rw-r--r--drivers/media/video/tda7432.c1
-rw-r--r--drivers/media/video/tda8290.c224
-rw-r--r--drivers/media/video/tda9840.c4
-rw-r--r--drivers/media/video/tda9875.c1
-rw-r--r--drivers/media/video/tda9887.c2
-rw-r--r--drivers/media/video/tea6415c.c4
-rw-r--r--drivers/media/video/tea6420.c4
-rw-r--r--drivers/media/video/tuner-3036.c1
-rw-r--r--drivers/media/video/tuner-core.c443
-rw-r--r--drivers/media/video/tuner-simple.c474
-rw-r--r--drivers/media/video/tuner.c1425
-rw-r--r--drivers/media/video/tvaudio.c1
-rw-r--r--drivers/media/video/tveeprom.c28
-rw-r--r--drivers/media/video/video-buf.c13
-rw-r--r--drivers/media/video/videodev.c11
-rw-r--r--drivers/media/video/vpx3220.c19
-rw-r--r--drivers/media/video/zoran_card.c6
-rw-r--r--drivers/media/video/zoran_device.c10
-rw-r--r--drivers/media/video/zoran_driver.c56
-rw-r--r--drivers/media/video/zr36050.c2
-rw-r--r--drivers/media/video/zr36120.c34
-rw-r--r--drivers/message/fusion/mptbase.c5
-rw-r--r--drivers/message/fusion/mptbase.h10
-rw-r--r--drivers/message/fusion/mptctl.c626
-rw-r--r--drivers/message/fusion/mptscsih.c277
-rw-r--r--drivers/message/fusion/mptscsih.h8
-rw-r--r--drivers/message/i2o/pci.c1
-rw-r--r--drivers/misc/Makefile1
-rw-r--r--drivers/misc/hdpuftrs/Makefile1
-rw-r--r--drivers/misc/hdpuftrs/hdpu_cpustate.c234
-rw-r--r--drivers/misc/hdpuftrs/hdpu_nexus.c111
-rw-r--r--drivers/misc/ibmasm/module.c1
-rw-r--r--drivers/mmc/mmc_block.c2
-rw-r--r--drivers/mmc/mmc_sysfs.c79
-rw-r--r--drivers/mtd/Kconfig18
-rw-r--r--drivers/mtd/devices/block2mtd.c8
-rw-r--r--drivers/mtd/maps/Kconfig10
-rw-r--r--drivers/mtd/maps/Makefile1
-rw-r--r--drivers/mtd/maps/chestnut.c91
-rw-r--r--drivers/mtd/maps/ich2rom.c316
-rw-r--r--drivers/mtd/maps/scx200_docflash.c13
-rw-r--r--drivers/mtd/mtdchar.c14
-rw-r--r--drivers/net/3c503.c67
-rw-r--r--drivers/net/3c505.c2
-rw-r--r--drivers/net/3c509.c4
-rw-r--r--drivers/net/3c515.c32
-rw-r--r--drivers/net/3c527.c2
-rw-r--r--drivers/net/3c59x.c2
-rw-r--r--drivers/net/8139too.c105
-rw-r--r--drivers/net/8390.c1
-rw-r--r--drivers/net/Kconfig96
-rw-r--r--drivers/net/Makefile3
-rw-r--r--drivers/net/Space.c11
-rwxr-xr-xdrivers/net/amd8111e.c9
-rw-r--r--drivers/net/arcnet/arc-rawmode.c4
-rw-r--r--drivers/net/arcnet/arc-rimi.c14
-rw-r--r--drivers/net/arcnet/arcnet.c34
-rw-r--r--drivers/net/arcnet/com20020.c6
-rw-r--r--drivers/net/arcnet/com90io.c4
-rw-r--r--drivers/net/arcnet/com90xx.c8
-rw-r--r--drivers/net/arcnet/rfc1051.c8
-rw-r--r--drivers/net/arcnet/rfc1201.c12
-rw-r--r--drivers/net/arm/ether1.c294
-rw-r--r--drivers/net/arm/ether1.h11
-rw-r--r--drivers/net/arm/ether3.c348
-rw-r--r--drivers/net/arm/ether3.h27
-rw-r--r--drivers/net/au1000_eth.c1363
-rw-r--r--drivers/net/au1000_eth.h53
-rw-r--r--drivers/net/b44.c38
-rw-r--r--drivers/net/b44.h17
-rw-r--r--drivers/net/bagetlance.c1368
-rw-r--r--drivers/net/bonding/bond_3ad.c2
-rw-r--r--drivers/net/bonding/bond_3ad.h1
-rw-r--r--drivers/net/bonding/bond_alb.c16
-rw-r--r--drivers/net/bonding/bond_main.c39
-rw-r--r--drivers/net/cs89x0.c4
-rw-r--r--drivers/net/defxx.c2
-rw-r--r--drivers/net/depca.c7
-rw-r--r--drivers/net/dgrs.c6
-rw-r--r--drivers/net/dl2k.c2
-rw-r--r--drivers/net/e100.c4
-rw-r--r--drivers/net/e1000/e1000.h4
-rw-r--r--drivers/net/e1000/e1000_ethtool.c11
-rw-r--r--drivers/net/e1000/e1000_hw.c88
-rw-r--r--drivers/net/e1000/e1000_hw.h11
-rw-r--r--drivers/net/e1000/e1000_main.c290
-rw-r--r--drivers/net/eepro100.c29
-rw-r--r--drivers/net/eexpress.c2
-rw-r--r--drivers/net/epic100.c2
-rw-r--r--drivers/net/eql.c4
-rw-r--r--drivers/net/es3210.c32
-rw-r--r--drivers/net/ethertap.c390
-rw-r--r--drivers/net/ewrk3.c87
-rw-r--r--drivers/net/fc/Makefile8
-rw-r--r--drivers/net/fc/iph5526.c4645
-rw-r--r--drivers/net/fc/iph5526_ip.h24
-rw-r--r--drivers/net/fc/iph5526_novram.c278
-rw-r--r--drivers/net/fc/iph5526_scsi.h31
-rw-r--r--drivers/net/fc/tach.h475
-rw-r--r--drivers/net/fc/tach_structs.h428
-rw-r--r--drivers/net/fealnx.c275
-rw-r--r--drivers/net/gianfar.c2
-rw-r--r--drivers/net/hamradio/6pack.c4
-rw-r--r--drivers/net/hamradio/baycom_epp.c53
-rw-r--r--drivers/net/hamradio/baycom_par.c8
-rw-r--r--drivers/net/hamradio/baycom_ser_fdx.c7
-rw-r--r--drivers/net/hamradio/baycom_ser_hdx.c7
-rw-r--r--drivers/net/hamradio/bpqether.c19
-rw-r--r--drivers/net/hamradio/dmascc.c1901
-rw-r--r--drivers/net/hamradio/hdlcdrv.c48
-rw-r--r--drivers/net/hamradio/mkiss.c12
-rw-r--r--drivers/net/hamradio/yam.c38
-rw-r--r--drivers/net/hp100.c6
-rw-r--r--drivers/net/ibm_emac/ibm_emac.h4
-rw-r--r--drivers/net/ibm_emac/ibm_emac_core.c16
-rw-r--r--drivers/net/ibm_emac/ibm_emac_core.h2
-rw-r--r--drivers/net/ibmlana.c99
-rw-r--r--drivers/net/ibmlana.h1
-rw-r--r--drivers/net/ioc3-eth.c83
-rw-r--r--drivers/net/irda/act200l-sir.c5
-rw-r--r--drivers/net/irda/act200l.c9
-rw-r--r--drivers/net/irda/actisys.c5
-rw-r--r--drivers/net/irda/ali-ircc.c68
-rw-r--r--drivers/net/irda/donauboe.c22
-rw-r--r--drivers/net/irda/girbil-sir.c4
-rw-r--r--drivers/net/irda/girbil.c9
-rw-r--r--drivers/net/irda/irda-usb.c86
-rw-r--r--drivers/net/irda/irport.c194
-rw-r--r--drivers/net/irda/irport.h10
-rw-r--r--drivers/net/irda/irtty-sir.c62
-rw-r--r--drivers/net/irda/ma600-sir.c18
-rw-r--r--drivers/net/irda/ma600.c9
-rw-r--r--drivers/net/irda/mcp2120-sir.c4
-rw-r--r--drivers/net/irda/mcp2120.c9
-rw-r--r--drivers/net/irda/nsc-ircc.c90
-rw-r--r--drivers/net/irda/sir_dev.c29
-rw-r--r--drivers/net/irda/sir_kthread.c8
-rw-r--r--drivers/net/irda/smsc-ircc2.c150
-rw-r--r--drivers/net/irda/stir4200.c11
-rw-r--r--drivers/net/irda/tekram-sir.c5
-rw-r--r--drivers/net/irda/tekram.c13
-rw-r--r--drivers/net/irda/via-ircc.c54
-rw-r--r--drivers/net/irda/vlsi_ir.c100
-rw-r--r--drivers/net/irda/vlsi_ir.h2
-rw-r--r--drivers/net/irda/w83977af_ir.c28
-rw-r--r--drivers/net/ixgb/ixgb.h3
-rw-r--r--drivers/net/ixgb/ixgb_ee.c16
-rw-r--r--drivers/net/ixgb/ixgb_ee.h3
-rw-r--r--drivers/net/ixgb/ixgb_ethtool.c5
-rw-r--r--drivers/net/ixgb/ixgb_hw.c2
-rw-r--r--drivers/net/ixgb/ixgb_hw.h2
-rw-r--r--drivers/net/ixgb/ixgb_ids.h2
-rw-r--r--drivers/net/ixgb/ixgb_main.c95
-rw-r--r--drivers/net/ixgb/ixgb_osdep.h2
-rw-r--r--drivers/net/ixgb/ixgb_param.c2
-rw-r--r--drivers/net/jazzsonic.c217
-rw-r--r--drivers/net/lance.c1
-rw-r--r--drivers/net/loopback.c2
-rw-r--r--drivers/net/lp486e.c8
-rw-r--r--drivers/net/macsonic.c1
-rw-r--r--drivers/net/meth.c275
-rw-r--r--drivers/net/meth.h2
-rw-r--r--drivers/net/mii.c66
-rw-r--r--drivers/net/mv643xx_eth.c2695
-rw-r--r--drivers/net/mv643xx_eth.h639
-rw-r--r--drivers/net/natsemi.c2
-rw-r--r--drivers/net/ne2k-pci.c4
-rw-r--r--drivers/net/ne3210.c1
-rw-r--r--drivers/net/netconsole.c1
-rw-r--r--drivers/net/ni65.c3
-rw-r--r--drivers/net/ns83820.c5
-rw-r--r--drivers/net/pcmcia/ibmtr_cs.c7
-rw-r--r--drivers/net/pcmcia/xirc2ps_cs.c23
-rw-r--r--drivers/net/pcnet32.c50
-rw-r--r--drivers/net/ppp_async.c2
-rw-r--r--drivers/net/ppp_deflate.c4
-rw-r--r--drivers/net/ppp_generic.c2
-rw-r--r--drivers/net/pppoe.c107
-rw-r--r--drivers/net/pppox.c2
-rw-r--r--drivers/net/r8169.c239
-rw-r--r--drivers/net/rrunner.c2
-rw-r--r--drivers/net/s2io-regs.h2
-rw-r--r--drivers/net/s2io.c420
-rw-r--r--drivers/net/s2io.h127
-rw-r--r--drivers/net/sb1000.c28
-rw-r--r--drivers/net/sb1250-mac.c109
-rw-r--r--drivers/net/sgiseeq.c70
-rw-r--r--drivers/net/shaper.c2
-rw-r--r--drivers/net/sis900.c248
-rw-r--r--drivers/net/sk98lin/h/skdrv1st.h1
-rw-r--r--drivers/net/sk98lin/skethtool.c5
-rw-r--r--drivers/net/sk98lin/skge.c6
-rw-r--r--drivers/net/sk_mca.c126
-rw-r--r--drivers/net/sk_mca.h19
-rw-r--r--drivers/net/slhc.c27
-rw-r--r--drivers/net/smc-mca.c37
-rw-r--r--drivers/net/smc-ultra.c34
-rw-r--r--drivers/net/smc-ultra32.c30
-rw-r--r--drivers/net/smc91x.c275
-rw-r--r--drivers/net/smc91x.h98
-rw-r--r--drivers/net/sonic.c4
-rw-r--r--drivers/net/sundance.c7
-rw-r--r--drivers/net/sungem.c1016
-rw-r--r--drivers/net/sungem.h82
-rw-r--r--drivers/net/sungem_phy.c43
-rw-r--r--drivers/net/sungem_phy.h3
-rw-r--r--drivers/net/sunhme.c4
-rw-r--r--drivers/net/tg3.c220
-rw-r--r--drivers/net/tg3.h18
-rw-r--r--drivers/net/tokenring/ibmtr.c158
-rw-r--r--drivers/net/tulip/de2104x.c2
-rw-r--r--drivers/net/tulip/de4x5.c1
-rw-r--r--drivers/net/tulip/interrupt.c2
-rw-r--r--drivers/net/tulip/media.c4
-rw-r--r--drivers/net/tulip/tulip.h2
-rw-r--r--drivers/net/tulip/tulip_core.c23
-rw-r--r--drivers/net/tun.c16
-rw-r--r--drivers/net/typhoon-firmware.h5568
-rw-r--r--drivers/net/typhoon.c256
-rw-r--r--drivers/net/via-rhine.c11
-rw-r--r--drivers/net/via-velocity.c14
-rw-r--r--drivers/net/wan/Kconfig11
-rw-r--r--drivers/net/wan/cosa.c7
-rw-r--r--drivers/net/wan/hd6457x.c2
-rw-r--r--drivers/net/wan/sbni.c2
-rw-r--r--drivers/net/wan/wanxl.c38
-rw-r--r--drivers/net/wan/z85230.c4
-rw-r--r--drivers/net/wd.c36
-rw-r--r--drivers/net/wireless/airo.c27
-rw-r--r--drivers/net/wireless/airport.c22
-rw-r--r--drivers/net/wireless/arlan.h4
-rw-r--r--drivers/net/wireless/atmel.c103
-rw-r--r--drivers/net/wireless/atmel.h43
-rw-r--r--drivers/net/wireless/atmel_cs.c49
-rw-r--r--drivers/net/wireless/atmel_pci.c6
-rw-r--r--drivers/net/wireless/hermes.c72
-rw-r--r--drivers/net/wireless/hermes.h64
-rw-r--r--drivers/net/wireless/orinoco.c424
-rw-r--r--drivers/net/wireless/orinoco.h37
-rw-r--r--drivers/net/wireless/orinoco_cs.c49
-rw-r--r--drivers/net/wireless/orinoco_pci.c124
-rw-r--r--drivers/net/wireless/orinoco_plx.c235
-rw-r--r--drivers/net/wireless/orinoco_tmd.c152
-rw-r--r--drivers/net/wireless/prism54/Makefile2
-rw-r--r--drivers/net/wireless/prism54/isl_38xx.c12
-rw-r--r--drivers/net/wireless/prism54/isl_ioctl.c34
-rw-r--r--drivers/net/wireless/prism54/isl_ioctl.h5
-rw-r--r--drivers/net/wireless/prism54/islpci_dev.c5
-rw-r--r--drivers/net/wireless/prism54/islpci_dev.h2
-rw-r--r--drivers/net/wireless/prism54/islpci_hotplug.c2
-rw-r--r--drivers/net/wireless/prism54/islpci_mgt.c2
-rw-r--r--drivers/net/wireless/prism54/oid_mgt.c6
-rw-r--r--drivers/net/wireless/prism54/oid_mgt.h4
-rw-r--r--drivers/net/wireless/ray_cs.c5
-rw-r--r--drivers/net/wireless/strip.c16
-rw-r--r--drivers/oprofile/buffer_sync.c6
-rw-r--r--drivers/oprofile/cpu_buffer.c2
-rw-r--r--drivers/oprofile/event_buffer.c7
-rw-r--r--drivers/parisc/Kconfig25
-rw-r--r--drivers/parisc/Makefile1
-rw-r--r--drivers/parisc/asp.c38
-rw-r--r--drivers/parisc/ccio-dma.c66
-rw-r--r--drivers/parisc/dino.c5
-rw-r--r--drivers/parisc/eisa.c9
-rw-r--r--drivers/parisc/eisa_eeprom.c25
-rw-r--r--drivers/parisc/gsc.c26
-rw-r--r--drivers/parisc/hppb.c1
-rw-r--r--drivers/parisc/iosapic.c232
-rw-r--r--drivers/parisc/lasi.c2
-rw-r--r--drivers/parisc/lba_pci.c536
-rw-r--r--drivers/parisc/led.c23
-rw-r--r--drivers/parisc/pdc_stable.c735
-rw-r--r--drivers/parisc/power.c5
-rw-r--r--drivers/parisc/sba_iommu.c330
-rw-r--r--drivers/parisc/superio.c2
-rw-r--r--drivers/parisc/wax.c26
-rw-r--r--drivers/parport/Kconfig32
-rw-r--r--drivers/parport/ieee1284.c2
-rw-r--r--drivers/parport/parport_arc.c2
-rw-r--r--drivers/parport/parport_gsc.c93
-rw-r--r--drivers/parport/parport_gsc.h (renamed from include/asm-parisc/parport_gsc.h)75
-rw-r--r--drivers/parport/parport_pc.c75
-rw-r--r--drivers/parport/parport_serial.c92
-rw-r--r--drivers/parport/parport_sunbpp.c2
-rw-r--r--drivers/parport/probe.c2
-rw-r--r--drivers/pci/Kconfig2
-rw-r--r--drivers/pci/hotplug/ibmphp_pci.c3
-rw-r--r--drivers/pci/hotplug/pciehp_ctrl.c3
-rw-r--r--drivers/pci/hotplug/pciehprm_acpi.c3
-rw-r--r--drivers/pci/hotplug/rpadlpar_core.c10
-rw-r--r--drivers/pci/hotplug/rpaphp.h5
-rw-r--r--drivers/pci/hotplug/rpaphp_core.c6
-rw-r--r--drivers/pci/hotplug/rpaphp_pci.c22
-rw-r--r--drivers/pci/hotplug/rpaphp_slot.c4
-rw-r--r--drivers/pci/hotplug/rpaphp_vio.c4
-rw-r--r--drivers/pci/hotplug/shpchprm_acpi.c3
-rw-r--r--drivers/pci/msi.c25
-rw-r--r--drivers/pci/pci-driver.c1
-rw-r--r--drivers/pci/pci-sysfs.c2
-rw-r--r--drivers/pci/pci.c14
-rw-r--r--drivers/pci/pci.h6
-rw-r--r--drivers/pci/pci.ids1163
-rw-r--r--drivers/pci/pcie/Kconfig14
-rw-r--r--drivers/pci/pcie/portdrv_pci.c2
-rw-r--r--drivers/pci/probe.c9
-rw-r--r--drivers/pci/proc.c20
-rw-r--r--drivers/pci/quirks.c52
-rw-r--r--drivers/pci/setup-res.c4
-rw-r--r--drivers/pcmcia/Kconfig11
-rw-r--r--drivers/pcmcia/au1000_generic.c7
-rw-r--r--drivers/pcmcia/cs.c14
-rw-r--r--drivers/pcmcia/cs_internal.h1
-rw-r--r--drivers/pcmcia/ds.c476
-rw-r--r--drivers/pcmcia/hd64465_ss.c15
-rw-r--r--drivers/pcmcia/i82092.c12
-rw-r--r--drivers/pcmcia/i82092aa.h1
-rw-r--r--drivers/pcmcia/i82365.c8
-rw-r--r--drivers/pcmcia/m32r_cfc.c7
-rw-r--r--drivers/pcmcia/m32r_pcc.c6
-rw-r--r--drivers/pcmcia/pd6729.c10
-rw-r--r--drivers/pcmcia/pxa2xx_sharpsl.c40
-rw-r--r--drivers/pcmcia/rsrc_mgr.c41
-rw-r--r--drivers/pcmcia/rsrc_nonstatic.c179
-rw-r--r--drivers/pcmcia/soc_common.c7
-rw-r--r--drivers/pcmcia/socket_sysfs.c40
-rw-r--r--drivers/pcmcia/tcic.c8
-rw-r--r--drivers/pcmcia/ti113x.h1
-rw-r--r--drivers/pcmcia/vrc4171_card.c282
-rw-r--r--drivers/pcmcia/vrc4173_cardu.c7
-rw-r--r--drivers/pcmcia/yenta_socket.c7
-rw-r--r--drivers/pnp/core.c2
-rw-r--r--drivers/pnp/interface.c2
-rw-r--r--drivers/pnp/isapnp/core.c47
-rw-r--r--drivers/pnp/manager.c3
-rw-r--r--drivers/pnp/pnpbios/core.c12
-rw-r--r--drivers/pnp/pnpbios/proc.c2
-rw-r--r--drivers/pnp/resource.c15
-rw-r--r--drivers/s390/block/dasd.c21
-rw-r--r--drivers/s390/block/dasd_eckd.c95
-rw-r--r--drivers/s390/block/dasd_eckd.h8
-rw-r--r--drivers/s390/block/dasd_erp.c3
-rw-r--r--drivers/s390/char/keyboard.c10
-rw-r--r--drivers/s390/char/sclp_quiesce.c25
-rw-r--r--drivers/s390/cio/chsc.c117
-rw-r--r--drivers/s390/cio/chsc.h16
-rw-r--r--drivers/s390/cio/cio.c6
-rw-r--r--drivers/s390/cio/css.c12
-rw-r--r--drivers/s390/cio/css.h2
-rw-r--r--drivers/s390/cio/device.c10
-rw-r--r--drivers/s390/cio/device_fsm.c66
-rw-r--r--drivers/s390/cio/device_id.c1
-rw-r--r--drivers/s390/cio/device_ops.c45
-rw-r--r--drivers/s390/cio/device_pgid.c10
-rw-r--r--drivers/s390/crypto/z90main.c6
-rw-r--r--drivers/s390/net/Kconfig9
-rw-r--r--drivers/s390/net/Makefile2
-rw-r--r--drivers/s390/net/claw.c4447
-rw-r--r--drivers/s390/net/claw.h335
-rw-r--r--drivers/s390/net/ctcmain.c35
-rw-r--r--drivers/s390/net/ctctty.c7
-rw-r--r--drivers/s390/net/iucv.c8
-rw-r--r--drivers/s390/net/qeth.h105
-rw-r--r--drivers/s390/net/qeth_eddp.c643
-rw-r--r--drivers/s390/net/qeth_eddp.h85
-rw-r--r--drivers/s390/net/qeth_main.c688
-rw-r--r--drivers/s390/net/qeth_mpc.h5
-rw-r--r--drivers/s390/net/qeth_proc.c11
-rw-r--r--drivers/s390/net/qeth_sys.c186
-rw-r--r--drivers/s390/net/qeth_tso.c285
-rw-r--r--drivers/s390/net/qeth_tso.h58
-rw-r--r--drivers/s390/scsi/zfcp_aux.c4
-rw-r--r--drivers/sbus/char/aurora.c6
-rw-r--r--drivers/sbus/char/flash.c2
-rw-r--r--drivers/sbus/char/openprom.c10
-rw-r--r--drivers/sbus/char/vfc_dev.c6
-rw-r--r--drivers/scsi/3w-9xxx.c512
-rw-r--r--drivers/scsi/3w-9xxx.h88
-rw-r--r--drivers/scsi/3w-xxxx.c366
-rw-r--r--drivers/scsi/3w-xxxx.h4
-rw-r--r--drivers/scsi/53c700.c37
-rw-r--r--drivers/scsi/53c700.h3
-rw-r--r--drivers/scsi/Kconfig16
-rw-r--r--drivers/scsi/Makefile1
-rw-r--r--drivers/scsi/NCR5380.c15
-rw-r--r--drivers/scsi/NCR_D700.c45
-rw-r--r--drivers/scsi/NCR_Q720.c2
-rw-r--r--drivers/scsi/aacraid/aachba.c149
-rw-r--r--drivers/scsi/aacraid/aacraid.h193
-rw-r--r--drivers/scsi/aacraid/commctrl.c12
-rw-r--r--drivers/scsi/aacraid/comminit.c2
-rw-r--r--drivers/scsi/aacraid/commsup.c25
-rw-r--r--drivers/scsi/aacraid/linit.c115
-rw-r--r--drivers/scsi/aacraid/rkt.c21
-rw-r--r--drivers/scsi/aacraid/rx.c18
-rw-r--r--drivers/scsi/aacraid/sa.c28
-rw-r--r--drivers/scsi/advansys.c2
-rw-r--r--drivers/scsi/ahci.c48
-rw-r--r--drivers/scsi/arm/arxescsi.c18
-rw-r--r--drivers/scsi/arm/cumana_2.c97
-rw-r--r--drivers/scsi/arm/eesox.c84
-rw-r--r--drivers/scsi/arm/fas216.c20
-rw-r--r--drivers/scsi/arm/fas216.h4
-rw-r--r--drivers/scsi/arm/powertec.c74
-rw-r--r--drivers/scsi/ata_piix.c5
-rw-r--r--drivers/scsi/atp870u.c2760
-rw-r--r--drivers/scsi/atp870u.h92
-rw-r--r--drivers/scsi/cpqfcTSinit.c2
-rw-r--r--drivers/scsi/dc395x.c91
-rw-r--r--drivers/scsi/dpt_i2o.c2
-rw-r--r--drivers/scsi/hosts.c68
-rw-r--r--drivers/scsi/ide-scsi.c77
-rw-r--r--drivers/scsi/ipr.c248
-rw-r--r--drivers/scsi/ipr.h201
-rw-r--r--drivers/scsi/ips.c244
-rw-r--r--drivers/scsi/ips.h12
-rw-r--r--drivers/scsi/lasi700.c17
-rw-r--r--drivers/scsi/libata-core.c131
-rw-r--r--drivers/scsi/libata-scsi.c8
-rw-r--r--drivers/scsi/libata.h1
-rw-r--r--drivers/scsi/mac_scsi.c2
-rw-r--r--drivers/scsi/megaraid/megaraid_mm.c24
-rw-r--r--drivers/scsi/ncr53c8xx.c508
-rw-r--r--drivers/scsi/osst.c34
-rw-r--r--drivers/scsi/psi240i.c8
-rw-r--r--drivers/scsi/psi240i.h4
-rw-r--r--drivers/scsi/qla1280.c146
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c14
-rw-r--r--drivers/scsi/qlogicfc.c62
-rw-r--r--drivers/scsi/qlogicfc.h80
-rw-r--r--drivers/scsi/qlogicisp.c99
-rw-r--r--drivers/scsi/qlogicisp.h69
-rw-r--r--drivers/scsi/sata_nv.c17
-rw-r--r--drivers/scsi/sata_promise.c9
-rw-r--r--drivers/scsi/sata_qstor.c718
-rw-r--r--drivers/scsi/sata_sil.c45
-rw-r--r--drivers/scsi/sata_sis.c11
-rw-r--r--drivers/scsi/sata_svw.c15
-rw-r--r--drivers/scsi/sata_sx4.c9
-rw-r--r--drivers/scsi/sata_uli.c11
-rw-r--r--drivers/scsi/sata_via.c214
-rw-r--r--drivers/scsi/sata_vsc.c18
-rw-r--r--drivers/scsi/scsi.c105
-rw-r--r--drivers/scsi/scsi_devinfo.c6
-rw-r--r--drivers/scsi/scsi_error.c9
-rw-r--r--drivers/scsi/scsi_ioctl.c6
-rw-r--r--drivers/scsi/scsi_lib.c145
-rw-r--r--drivers/scsi/scsi_scan.c269
-rw-r--r--drivers/scsi/scsi_sysfs.c202
-rw-r--r--drivers/scsi/scsi_transport_fc.c1088
-rw-r--r--drivers/scsi/scsi_transport_iscsi.c30
-rw-r--r--drivers/scsi/scsi_transport_spi.c216
-rw-r--r--drivers/scsi/sd.c82
-rw-r--r--drivers/scsi/sg.c82
-rw-r--r--drivers/scsi/sim710.c18
-rw-r--r--drivers/scsi/sr.c6
-rw-r--r--drivers/scsi/st.c434
-rw-r--r--drivers/scsi/st.h19
-rw-r--r--drivers/scsi/sym53c416.c2
-rw-r--r--drivers/scsi/sym53c8xx_2/Makefile2
-rw-r--r--drivers/scsi/sym53c8xx_2/sym53c8xx.h60
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_conf.h110
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_defs.h4
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_fw.c2
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_glue.c628
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_glue.h299
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_hipd.c1354
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_hipd.h227
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_malloc.c124
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_misc.c111
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_nvram.c94
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_nvram.h11
-rw-r--r--drivers/scsi/sym53c8xx_defs.h54
-rw-r--r--drivers/scsi/ultrastor.c2
-rw-r--r--drivers/scsi/zalon.c23
-rw-r--r--drivers/serial/21285.c3
-rw-r--r--drivers/serial/68328serial.c27
-rw-r--r--drivers/serial/8250.c137
-rw-r--r--drivers/serial/8250.h14
-rw-r--r--drivers/serial/8250_pci.c50
-rw-r--r--drivers/serial/Kconfig34
-rw-r--r--drivers/serial/Makefile5
-rw-r--r--drivers/serial/au1x00_uart.c67
-rw-r--r--drivers/serial/cpm_uart/cpm_uart_core.c6
-rw-r--r--drivers/serial/crisv10.c6
-rw-r--r--drivers/serial/imx.c7
-rw-r--r--drivers/serial/ioc4_serial.c2909
-rw-r--r--drivers/serial/jsm/Makefile8
-rw-r--r--drivers/serial/jsm/jsm.h437
-rw-r--r--drivers/serial/jsm/jsm_driver.c404
-rw-r--r--drivers/serial/jsm/jsm_neo.c1427
-rw-r--r--drivers/serial/jsm/jsm_tty.c1043
-rw-r--r--drivers/serial/m32r_sio.c156
-rw-r--r--drivers/serial/m32r_sio.h1
-rw-r--r--drivers/serial/m32r_sio_reg.h190
-rw-r--r--drivers/serial/mcfserial.c32
-rw-r--r--drivers/serial/mpc52xx_uart.c201
-rw-r--r--drivers/serial/mux.c2
-rw-r--r--drivers/serial/s3c2410.c251
-rw-r--r--drivers/serial/sa1100.c6
-rw-r--r--drivers/serial/serial_core.c3
-rw-r--r--drivers/serial/serial_cs.c16
-rw-r--r--drivers/serial/sn_console.c9
-rw-r--r--drivers/serial/sunsu.c7
-rw-r--r--drivers/serial/sunzilog.c7
-rw-r--r--drivers/serial/vr41xx_siu.c1100
-rw-r--r--drivers/sh/Makefile6
-rw-r--r--drivers/sh/superhyway/Makefile7
-rw-r--r--drivers/sh/superhyway/superhyway-sysfs.c45
-rw-r--r--drivers/sh/superhyway/superhyway.c201
-rw-r--r--drivers/sn/Makefile6
-rw-r--r--drivers/sn/ioc4.c65
-rw-r--r--drivers/tc/zs.c30
-rw-r--r--drivers/telephony/ixj.c2
-rw-r--r--drivers/usb/Kconfig28
-rw-r--r--drivers/usb/Makefile4
-rw-r--r--drivers/usb/atm/speedtch.c8
-rw-r--r--drivers/usb/class/audio.c56
-rw-r--r--drivers/usb/class/cdc-acm.c96
-rw-r--r--drivers/usb/class/cdc-acm.h49
-rw-r--r--drivers/usb/class/usb-midi.c6
-rw-r--r--drivers/usb/class/usblp.c2
-rw-r--r--drivers/usb/core/buffer.c2
-rw-r--r--drivers/usb/core/config.c5
-rw-r--r--drivers/usb/core/devices.c32
-rw-r--r--drivers/usb/core/devio.c260
-rw-r--r--drivers/usb/core/file.c62
-rw-r--r--drivers/usb/core/hcd-pci.c173
-rw-r--r--drivers/usb/core/hcd.c414
-rw-r--r--drivers/usb/core/hcd.h112
-rw-r--r--drivers/usb/core/hub.c179
-rw-r--r--drivers/usb/core/hub.h3
-rw-r--r--drivers/usb/core/message.c83
-rw-r--r--drivers/usb/core/sysfs.c92
-rw-r--r--drivers/usb/core/usb.c46
-rw-r--r--drivers/usb/core/usb.h8
-rw-r--r--drivers/usb/gadget/Kconfig85
-rw-r--r--drivers/usb/gadget/config.c1
-rw-r--r--drivers/usb/gadget/dummy_hcd.c85
-rw-r--r--drivers/usb/gadget/ether.c494
-rw-r--r--drivers/usb/gadget/file_storage.c63
-rw-r--r--drivers/usb/gadget/gadget_chips.h13
-rw-r--r--drivers/usb/gadget/inode.c29
-rw-r--r--drivers/usb/gadget/net2280.c27
-rw-r--r--drivers/usb/gadget/omap_udc.c30
-rw-r--r--drivers/usb/gadget/pxa2xx_udc.c280
-rw-r--r--drivers/usb/gadget/pxa2xx_udc.h29
-rw-r--r--drivers/usb/gadget/rndis.c171
-rw-r--r--drivers/usb/gadget/rndis.h162
-rw-r--r--drivers/usb/gadget/serial.c160
-rw-r--r--drivers/usb/gadget/usbstring.c4
-rw-r--r--drivers/usb/gadget/zero.c52
-rw-r--r--drivers/usb/host/Kconfig49
-rw-r--r--drivers/usb/host/ehci-hcd.c79
-rw-r--r--drivers/usb/host/ehci-hub.c14
-rw-r--r--drivers/usb/host/ehci-q.c29
-rw-r--r--drivers/usb/host/ehci-sched.c51
-rw-r--r--drivers/usb/host/ehci.h10
-rw-r--r--drivers/usb/host/ohci-au1xxx.c136
-rw-r--r--drivers/usb/host/ohci-dbg.c10
-rw-r--r--drivers/usb/host/ohci-hcd.c71
-rw-r--r--drivers/usb/host/ohci-hub.c19
-rw-r--r--drivers/usb/host/ohci-lh7a404.c138
-rw-r--r--drivers/usb/host/ohci-omap.c266
-rw-r--r--drivers/usb/host/ohci-ppc-soc.c234
-rw-r--r--drivers/usb/host/ohci-pxa27x.c127
-rw-r--r--drivers/usb/host/ohci-q.c21
-rw-r--r--drivers/usb/host/ohci-sa1111.c130
-rw-r--r--drivers/usb/host/ohci.h58
-rw-r--r--drivers/usb/host/sl811-hcd.c89
-rw-r--r--drivers/usb/host/uhci-debug.c13
-rw-r--r--drivers/usb/host/uhci-hcd.c1635
-rw-r--r--drivers/usb/host/uhci-hcd.h37
-rw-r--r--drivers/usb/host/uhci-hub.c46
-rw-r--r--drivers/usb/host/uhci-q.c1539
-rw-r--r--drivers/usb/image/Kconfig11
-rw-r--r--drivers/usb/image/Makefile1
-rw-r--r--drivers/usb/image/hpusbscsi.c523
-rw-r--r--drivers/usb/image/hpusbscsi.h73
-rw-r--r--drivers/usb/image/mdc800.c42
-rw-r--r--drivers/usb/image/microtek.c8
-rw-r--r--drivers/usb/input/aiptek.c25
-rw-r--r--drivers/usb/input/ati_remote.c72
-rw-r--r--drivers/usb/input/hid-core.c308
-rw-r--r--drivers/usb/input/hid-debug.h12
-rw-r--r--drivers/usb/input/hid-ff.c1
-rw-r--r--drivers/usb/input/hid-input.c42
-rw-r--r--drivers/usb/input/hid-lgff.c1
-rw-r--r--drivers/usb/input/hid.h3
-rw-r--r--drivers/usb/input/hiddev.c13
-rw-r--r--drivers/usb/input/mtouchusb.c59
-rw-r--r--drivers/usb/input/pid.c252
-rw-r--r--drivers/usb/input/pid.h28
-rw-r--r--drivers/usb/input/powermate.c3
-rw-r--r--drivers/usb/input/touchkitusb.c19
-rw-r--r--drivers/usb/input/usbkbd.c20
-rw-r--r--drivers/usb/input/usbmouse.c19
-rw-r--r--drivers/usb/input/wacom.c337
-rw-r--r--drivers/usb/media/Kconfig36
-rw-r--r--drivers/usb/media/Makefile1
-rw-r--r--drivers/usb/media/ibmcam.c7
-rw-r--r--drivers/usb/media/konicawc.c2
-rw-r--r--drivers/usb/media/ov511.c6
-rw-r--r--drivers/usb/media/pwc/ChangeLog143
-rw-r--r--drivers/usb/media/pwc/Makefile20
-rw-r--r--drivers/usb/media/pwc/philips.txt236
-rw-r--r--drivers/usb/media/pwc/pwc-ctrl.c1630
-rw-r--r--drivers/usb/media/pwc/pwc-dec1.c42
-rw-r--r--drivers/usb/media/pwc/pwc-dec1.h36
-rw-r--r--drivers/usb/media/pwc/pwc-dec23.c623
-rw-r--r--drivers/usb/media/pwc/pwc-dec23.h58
-rw-r--r--drivers/usb/media/pwc/pwc-if.c2212
-rw-r--r--drivers/usb/media/pwc/pwc-ioctl.h292
-rw-r--r--drivers/usb/media/pwc/pwc-kiara.c891
-rw-r--r--drivers/usb/media/pwc/pwc-kiara.h45
-rw-r--r--drivers/usb/media/pwc/pwc-misc.c140
-rw-r--r--drivers/usb/media/pwc/pwc-nala.h66
-rw-r--r--drivers/usb/media/pwc/pwc-timon.c1446
-rw-r--r--drivers/usb/media/pwc/pwc-timon.h61
-rw-r--r--drivers/usb/media/pwc/pwc-uncompress.c147
-rw-r--r--drivers/usb/media/pwc/pwc-uncompress.h41
-rw-r--r--drivers/usb/media/pwc/pwc.h278
-rw-r--r--drivers/usb/media/se401.c6
-rw-r--r--drivers/usb/media/sn9c102.h8
-rw-r--r--drivers/usb/media/sn9c102_core.c52
-rw-r--r--drivers/usb/media/ultracam.c4
-rw-r--r--drivers/usb/media/usbvideo.c6
-rw-r--r--drivers/usb/media/vicam.c4
-rw-r--r--drivers/usb/media/w9968cf.h2
-rw-r--r--drivers/usb/misc/Kconfig2
-rw-r--r--drivers/usb/misc/Makefile2
-rw-r--r--drivers/usb/misc/auerswald.c21
-rw-r--r--drivers/usb/misc/cytherm.c2
-rw-r--r--drivers/usb/misc/emi26.c2
-rw-r--r--drivers/usb/misc/idmouse.c16
-rw-r--r--drivers/usb/misc/legousbtower.c4
-rw-r--r--drivers/usb/misc/phidgetkit.c29
-rw-r--r--drivers/usb/misc/phidgetservo.c4
-rw-r--r--drivers/usb/misc/rio500.c20
-rw-r--r--drivers/usb/misc/sisusbvga/Kconfig14
-rw-r--r--drivers/usb/misc/sisusbvga/Makefile6
-rw-r--r--drivers/usb/misc/sisusbvga/sisusb.c3145
-rw-r--r--drivers/usb/misc/sisusbvga/sisusb.h278
-rw-r--r--drivers/usb/misc/usblcd.c528
-rw-r--r--drivers/usb/misc/usbled.c2
-rw-r--r--drivers/usb/misc/usbtest.c12
-rw-r--r--drivers/usb/misc/uss720.c12
-rw-r--r--drivers/usb/mon/Kconfig22
-rw-r--r--drivers/usb/mon/Makefile7
-rw-r--r--drivers/usb/mon/mon_main.c377
-rw-r--r--drivers/usb/mon/mon_stat.c74
-rw-r--r--drivers/usb/mon/mon_text.c405
-rw-r--r--drivers/usb/mon/usb_mon.h51
-rw-r--r--drivers/usb/net/Kconfig21
-rw-r--r--drivers/usb/net/Makefile3
-rw-r--r--drivers/usb/net/catc.c5
-rw-r--r--drivers/usb/net/kaweth.c15
-rw-r--r--drivers/usb/net/kawethfw.h8
-rw-r--r--drivers/usb/net/pegasus.c353
-rw-r--r--drivers/usb/net/pegasus.h5
-rw-r--r--drivers/usb/net/rtl8150.c4
-rw-r--r--drivers/usb/net/usbnet.c996
-rw-r--r--drivers/usb/net/zd1201.c1905
-rw-r--r--drivers/usb/net/zd1201.h147
-rw-r--r--drivers/usb/serial/Kconfig10
-rw-r--r--drivers/usb/serial/Makefile1
-rw-r--r--drivers/usb/serial/belkin_sa.c2
-rw-r--r--drivers/usb/serial/cp2101.c591
-rw-r--r--drivers/usb/serial/cyberjack.c7
-rw-r--r--drivers/usb/serial/cypress_m8.c6
-rw-r--r--drivers/usb/serial/digi_acceleport.c29
-rw-r--r--drivers/usb/serial/ezusb.c2
-rw-r--r--drivers/usb/serial/ftdi_sio.c60
-rw-r--r--drivers/usb/serial/ftdi_sio.h1
-rw-r--r--drivers/usb/serial/garmin_gps.c4
-rw-r--r--drivers/usb/serial/io_edgeport.c51
-rw-r--r--drivers/usb/serial/io_ti.c7
-rw-r--r--drivers/usb/serial/ipaq.c2
-rw-r--r--drivers/usb/serial/ipw.c22
-rw-r--r--drivers/usb/serial/ir-usb.c2
-rw-r--r--drivers/usb/serial/keyspan_pda.c14
-rw-r--r--drivers/usb/serial/kl5kusb105.c47
-rw-r--r--drivers/usb/serial/kobil_sct.c14
-rw-r--r--drivers/usb/serial/mct_u232.c24
-rw-r--r--drivers/usb/serial/ti_usb_3410_5052.c6
-rw-r--r--drivers/usb/serial/usb-serial.c10
-rw-r--r--drivers/usb/serial/visor.c45
-rw-r--r--drivers/usb/serial/visor.h3
-rw-r--r--drivers/usb/serial/whiteheat.c5
-rw-r--r--drivers/usb/storage/Kconfig45
-rw-r--r--drivers/usb/storage/Makefile2
-rw-r--r--drivers/usb/storage/datafab.c2
-rw-r--r--drivers/usb/storage/debug.h2
-rw-r--r--drivers/usb/storage/dpcm.c2
-rw-r--r--drivers/usb/storage/freecom.c2
-rw-r--r--drivers/usb/storage/initializers.c2
-rw-r--r--drivers/usb/storage/isd200.c2
-rw-r--r--drivers/usb/storage/jumpshot.c2
-rw-r--r--drivers/usb/storage/protocol.c42
-rw-r--r--drivers/usb/storage/protocol.h3
-rw-r--r--drivers/usb/storage/scsiglue.c124
-rw-r--r--drivers/usb/storage/scsiglue.h6
-rw-r--r--drivers/usb/storage/sddr09.c2
-rw-r--r--drivers/usb/storage/sddr55.c2
-rw-r--r--drivers/usb/storage/shuttle_usbat.c1265
-rw-r--r--drivers/usb/storage/shuttle_usbat.h78
-rw-r--r--drivers/usb/storage/transport.c41
-rw-r--r--drivers/usb/storage/transport.h12
-rw-r--r--drivers/usb/storage/unusual_devs.h118
-rw-r--r--drivers/usb/storage/usb.c222
-rw-r--r--drivers/usb/storage/usb.h62
-rw-r--r--drivers/usb/usb-skeleton.c4
-rw-r--r--drivers/video/Kconfig433
-rw-r--r--drivers/video/Makefile157
-rw-r--r--drivers/video/acornfb.c2
-rw-r--r--drivers/video/amifb.c11
-rw-r--r--drivers/video/asiliantfb.c19
-rw-r--r--drivers/video/aty/aty128fb.c43
-rw-r--r--drivers/video/aty/atyfb.h1
-rw-r--r--drivers/video/aty/atyfb_base.c69
-rw-r--r--drivers/video/aty/mach64_ct.c7
-rw-r--r--drivers/video/aty/mach64_cursor.c2
-rw-r--r--drivers/video/aty/radeon_accel.c28
-rw-r--r--drivers/video/aty/radeon_base.c115
-rw-r--r--drivers/video/aty/radeon_i2c.c6
-rw-r--r--drivers/video/aty/radeon_monitor.c35
-rw-r--r--drivers/video/aty/radeon_pm.c76
-rw-r--r--drivers/video/aty/radeonfb.h177
-rw-r--r--drivers/video/au1100fb.c2
-rw-r--r--drivers/video/backlight/backlight.c2
-rw-r--r--drivers/video/backlight/corgi_bl.c4
-rw-r--r--drivers/video/backlight/lcd.c2
-rw-r--r--drivers/video/cfbcopyarea.c349
-rw-r--r--drivers/video/cfbfillrect.c337
-rw-r--r--drivers/video/chipsfb.c2
-rw-r--r--drivers/video/cirrusfb.c74
-rw-r--r--drivers/video/console/Kconfig51
-rw-r--r--drivers/video/console/Makefile12
-rw-r--r--drivers/video/console/bitblit.c24
-rw-r--r--drivers/video/console/dummycon.c2
-rw-r--r--drivers/video/console/fbcon.c263
-rw-r--r--drivers/video/console/fbcon.h10
-rw-r--r--drivers/video/console/mdacon.c11
-rw-r--r--drivers/video/console/promcon.c14
-rw-r--r--drivers/video/console/sticon.c12
-rw-r--r--drivers/video/console/sticore.c57
-rw-r--r--drivers/video/console/tileblit.c3
-rw-r--r--drivers/video/console/vgacon.c10
-rw-r--r--drivers/video/controlfb.c2
-rw-r--r--drivers/video/cyber2000fb.c13
-rw-r--r--drivers/video/fbmem.c108
-rw-r--r--drivers/video/fbmon.c37
-rw-r--r--drivers/video/fbsysfs.c317
-rw-r--r--drivers/video/geode/Kconfig29
-rw-r--r--drivers/video/geode/Makefile5
-rw-r--r--drivers/video/geode/display_gx1.c214
-rw-r--r--drivers/video/geode/display_gx1.h154
-rw-r--r--drivers/video/geode/geodefb.h39
-rw-r--r--drivers/video/geode/gx1fb_core.c359
-rw-r--r--drivers/video/geode/video_cs5530.c195
-rw-r--r--drivers/video/geode/video_cs5530.h75
-rw-r--r--drivers/video/hgafb.c14
-rw-r--r--drivers/video/hitfb.c33
-rw-r--r--drivers/video/i810/i810_gtf.c12
-rw-r--r--drivers/video/i810/i810_main.c37
-rw-r--r--drivers/video/i810/i810_main.h2
-rw-r--r--drivers/video/igafb.c3
-rw-r--r--drivers/video/imsttfb.c17
-rw-r--r--drivers/video/intelfb/intelfb.h8
-rw-r--r--drivers/video/intelfb/intelfbdrv.c128
-rw-r--r--drivers/video/intelfb/intelfbdrv.h3
-rw-r--r--drivers/video/intelfb/intelfbhw.c11
-rw-r--r--drivers/video/intelfb/intelfbhw.h3
-rw-r--r--drivers/video/kyro/STG4000InitDevice.c4
-rw-r--r--drivers/video/kyro/STG4000OverlayDevice.c4
-rw-r--r--drivers/video/kyro/STG4000Ramdac.c1
-rw-r--r--drivers/video/kyro/fbdev.c49
-rw-r--r--drivers/video/logo/Kconfig2
-rw-r--r--drivers/video/logo/Makefile41
-rw-r--r--drivers/video/logo/logo.c7
-rw-r--r--drivers/video/macmodes.c9
-rw-r--r--drivers/video/matrox/matroxfb_accel.c14
-rw-r--r--drivers/video/matrox/matroxfb_base.c8
-rw-r--r--drivers/video/matrox/matroxfb_base.h5
-rw-r--r--drivers/video/modedb.c48
-rw-r--r--drivers/video/neofb.c56
-rw-r--r--drivers/video/nvidia/Makefile12
-rw-r--r--drivers/video/nvidia/nv_accel.c419
-rw-r--r--drivers/video/nvidia/nv_dma.h188
-rw-r--r--drivers/video/nvidia/nv_hw.c1593
-rw-r--r--drivers/video/nvidia/nv_i2c.c215
-rw-r--r--drivers/video/nvidia/nv_local.h107
-rw-r--r--drivers/video/nvidia/nv_of.c59
-rw-r--r--drivers/video/nvidia/nv_proto.h58
-rw-r--r--drivers/video/nvidia/nv_setup.c636
-rw-r--r--drivers/video/nvidia/nv_type.h174
-rw-r--r--drivers/video/nvidia/nvidia.c1729
-rw-r--r--drivers/video/offb.c11
-rw-r--r--drivers/video/pm2fb.c72
-rw-r--r--drivers/video/pm3fb.c287
-rw-r--r--drivers/video/pvr2fb.c10
-rw-r--r--drivers/video/pxafb.c3
-rw-r--r--drivers/video/radeonfb.c57
-rw-r--r--drivers/video/riva/fbdev.c28
-rw-r--r--drivers/video/riva/rivafb-i2c.c11
-rw-r--r--drivers/video/s1d13xxxfb.c772
-rw-r--r--drivers/video/sa1100fb.c5
-rw-r--r--drivers/video/savage/Makefile7
-rw-r--r--drivers/video/savage/savagefb-i2c.c3
-rw-r--r--drivers/video/savage/savagefb_accel.c4
-rw-r--r--drivers/video/savage/savagefb_driver.c (renamed from drivers/video/savage/savagefb.c)17
-rw-r--r--drivers/video/sbuslib.c8
-rw-r--r--drivers/video/sis/sis_main.c9
-rw-r--r--drivers/video/skeletonfb.c20
-rw-r--r--drivers/video/sstfb.c13
-rw-r--r--drivers/video/stifb.c71
-rw-r--r--drivers/video/sun3fb.c2
-rw-r--r--drivers/video/tdfxfb.c59
-rw-r--r--drivers/video/tgafb.c2
-rw-r--r--drivers/video/tridentfb.c51
-rw-r--r--drivers/video/vesafb.c12
-rw-r--r--drivers/video/vfb.c12
-rw-r--r--drivers/video/vga16fb.c24
-rw-r--r--drivers/video/w100fb.c59
-rw-r--r--drivers/w1/dscore.c37
-rw-r--r--drivers/w1/dscore.h3
-rw-r--r--drivers/w1/matrox_w1.c2
-rw-r--r--drivers/w1/w1.c51
-rw-r--r--drivers/w1/w1.h9
-rw-r--r--drivers/w1/w1_family.c4
-rw-r--r--drivers/w1/w1_int.c4
-rw-r--r--drivers/w1/w1_therm.c12
-rw-r--r--drivers/zorro/zorro.c2
-rw-r--r--fs/Kconfig1
-rw-r--r--fs/adfs/dir_f.c17
-rw-r--r--fs/afs/kafsasyncd.c2
-rw-r--r--fs/afs/kafstimod.c2
-rw-r--r--fs/afs/main.c17
-rw-r--r--fs/aio.c2
-rw-r--r--fs/attr.c7
-rw-r--r--fs/autofs4/root.c2
-rw-r--r--fs/autofs4/waitq.c1
-rw-r--r--fs/bad_inode.c14
-rw-r--r--fs/binfmt_aout.c10
-rw-r--r--fs/binfmt_elf.c95
-rw-r--r--fs/binfmt_elf_fdpic.c2
-rw-r--r--fs/binfmt_flat.c2
-rw-r--r--fs/binfmt_som.c2
-rw-r--r--fs/bio.c216
-rw-r--r--fs/buffer.c64
-rw-r--r--fs/char_dev.c29
-rw-r--r--fs/cifs/AUTHORS2
-rw-r--r--fs/cifs/CHANGES31
-rw-r--r--fs/cifs/Makefile2
-rw-r--r--fs/cifs/README10
-rw-r--r--fs/cifs/asn1.c7
-rw-r--r--fs/cifs/cifs_debug.c21
-rw-r--r--fs/cifs/cifs_fs_sb.h3
-rw-r--r--fs/cifs/cifsencrypt.c1
-rw-r--r--fs/cifs/cifsencrypt.h34
-rw-r--r--fs/cifs/cifsfs.c96
-rw-r--r--fs/cifs/cifsfs.h12
-rw-r--r--fs/cifs/cifsglob.h3
-rw-r--r--fs/cifs/cifspdu.h83
-rw-r--r--fs/cifs/cifsproto.h54
-rw-r--r--fs/cifs/cifssmb.c781
-rw-r--r--fs/cifs/connect.c188
-rw-r--r--fs/cifs/fcntl.c3
-rw-r--r--fs/cifs/file.c1938
-rw-r--r--fs/cifs/inode.c742
-rw-r--r--fs/cifs/ioctl.c49
-rw-r--r--fs/cifs/md4.c2
-rw-r--r--fs/cifs/misc.c12
-rw-r--r--fs/cifs/netmisc.c6
-rw-r--r--fs/cifs/ntlmssp.h2
-rw-r--r--fs/cifs/readdir.c365
-rw-r--r--fs/cifs/smbdes.c6
-rw-r--r--fs/cifs/smbencrypt.c34
-rw-r--r--fs/cifs/transport.c74
-rw-r--r--fs/cifs/xattr.c22
-rw-r--r--fs/compat.c20
-rw-r--r--fs/compat_ioctl.c338
-rw-r--r--fs/cramfs/inode.c1
-rw-r--r--fs/dcache.c6
-rw-r--r--fs/debugfs/file.c4
-rw-r--r--fs/direct-io.c7
-rw-r--r--fs/dquot.c17
-rw-r--r--fs/eventpoll.c7
-rw-r--r--fs/exec.c14
-rw-r--r--fs/exportfs/expfs.c4
-rw-r--r--fs/ext2/dir.c1
-rw-r--r--fs/ext2/inode.c8
-rw-r--r--fs/ext2/super.c10
-rw-r--r--fs/ext3/balloc.c77
-rw-r--r--fs/ext3/hash.c70
-rw-r--r--fs/ext3/ialloc.c11
-rw-r--r--fs/ext3/inode.c83
-rw-r--r--fs/ext3/super.c29
-rw-r--r--fs/fat/Makefile2
-rw-r--r--fs/fat/cache.c141
-rw-r--r--fs/fat/dir.c687
-rw-r--r--fs/fat/fatent.c612
-rw-r--r--fs/fat/file.c214
-rw-r--r--fs/fat/inode.c195
-rw-r--r--fs/fat/misc.c166
-rw-r--r--fs/fs-writeback.c4
-rw-r--r--fs/hfs/bnode.c12
-rw-r--r--fs/hfs/brec.c10
-rw-r--r--fs/hfs/btree.h3
-rw-r--r--fs/hfs/catalog.c2
-rw-r--r--fs/hfs/dir.c20
-rw-r--r--fs/hfs/extent.c35
-rw-r--r--fs/hfs/hfs_fs.h10
-rw-r--r--fs/hfs/inode.c35
-rw-r--r--fs/hfs/super.c156
-rw-r--r--fs/hfsplus/bnode.c23
-rw-r--r--fs/hfsplus/brec.c10
-rw-r--r--fs/hfsplus/catalog.c39
-rw-r--r--fs/hfsplus/dir.c31
-rw-r--r--fs/hfsplus/extents.c9
-rw-r--r--fs/hfsplus/hfsplus_fs.h19
-rw-r--r--fs/hfsplus/inode.c14
-rw-r--r--fs/hfsplus/options.c151
-rw-r--r--fs/hfsplus/super.c35
-rw-r--r--fs/hfsplus/tables.c2839
-rw-r--r--fs/hfsplus/unicode.c219
-rw-r--r--fs/hostfs/Makefile19
-rw-r--r--fs/hostfs/hostfs_kern.c22
-rw-r--r--fs/hostfs/hostfs_user.c5
-rw-r--r--fs/hpfs/alloc.c4
-rw-r--r--fs/hpfs/dentry.c6
-rw-r--r--fs/hpfs/dnode.c14
-rw-r--r--fs/hpfs/hpfs.h12
-rw-r--r--fs/hpfs/hpfs_fn.h8
-rw-r--r--fs/hpfs/inode.c2
-rw-r--r--fs/hpfs/name.c4
-rw-r--r--fs/hpfs/super.c6
-rw-r--r--fs/hppfs/Makefile10
-rw-r--r--fs/hugetlbfs/inode.c2
-rw-r--r--fs/inode.c9
-rw-r--r--fs/isofs/inode.c5
-rw-r--r--fs/isofs/rock.c25
-rw-r--r--fs/jbd/commit.c159
-rw-r--r--fs/jbd/journal.c47
-rw-r--r--fs/jbd/transaction.c102
-rw-r--r--fs/jffs/inode-v23.c10
-rw-r--r--fs/jffs/intrep.c60
-rw-r--r--fs/jffs/intrep.h32
-rw-r--r--fs/jffs/jffs_fm.c12
-rw-r--r--fs/jffs/jffs_fm.h6
-rw-r--r--fs/jffs2/compr.c10
-rw-r--r--fs/jffs2/compr.h3
-rw-r--r--fs/jffs2/compr_rtime.c12
-rw-r--r--fs/jffs2/erase.c3
-rw-r--r--fs/jffs2/file.c15
-rw-r--r--fs/jffs2/fs.c3
-rw-r--r--fs/jffs2/nodelist.h1
-rw-r--r--fs/jffs2/os-linux.h5
-rw-r--r--fs/jffs2/wbuf.c2
-rw-r--r--fs/jfs/inode.c23
-rw-r--r--fs/jfs/jfs_dtree.c4
-rw-r--r--fs/jfs/jfs_incore.h6
-rw-r--r--fs/jfs/jfs_logmgr.c9
-rw-r--r--fs/jfs/jfs_metapage.c24
-rw-r--r--fs/jfs/jfs_txnmgr.c49
-rw-r--r--fs/jfs/namei.c2
-rw-r--r--fs/jfs/super.c23
-rw-r--r--fs/lockd/clntproc.c40
-rw-r--r--fs/lockd/host.c4
-rw-r--r--fs/lockd/svc.c33
-rw-r--r--fs/lockd/svclock.c1
-rw-r--r--fs/locks.c48
-rw-r--r--fs/mbcache.c2
-rw-r--r--fs/mpage.c47
-rw-r--r--fs/msdos/namei.c557
-rw-r--r--fs/namei.c66
-rw-r--r--fs/namespace.c34
-rw-r--r--fs/ncpfs/ncplib_kernel.c2
-rw-r--r--fs/ncpfs/ncpsign_kernel.c3
-rw-r--r--fs/nfs/callback.c156
-rw-r--r--fs/nfs/dir.c172
-rw-r--r--fs/nfs/file.c64
-rw-r--r--fs/nfs/inode.c48
-rw-r--r--fs/nfs/mount_clnt.c4
-rw-r--r--fs/nfs/nfs3proc.c76
-rw-r--r--fs/nfs/nfs4proc.c419
-rw-r--r--fs/nfs/nfs4state.c76
-rw-r--r--fs/nfs/nfs4xdr.c26
-rw-r--r--fs/nfs/nfsroot.c13
-rw-r--r--fs/nfs/proc.c56
-rw-r--r--fs/nfs/read.c2
-rw-r--r--fs/nfs/unlink.c9
-rw-r--r--fs/nfs/write.c29
-rw-r--r--fs/nfsd/export.c22
-rw-r--r--fs/nfsd/lockd.c2
-rw-r--r--fs/nfsd/nfs3proc.c4
-rw-r--r--fs/nfsd/nfs3xdr.c5
-rw-r--r--fs/nfsd/nfs4acl.c40
-rw-r--r--fs/nfsd/nfs4callback.c128
-rw-r--r--fs/nfsd/nfs4proc.c127
-rw-r--r--fs/nfsd/nfs4state.c899
-rw-r--r--fs/nfsd/nfs4xdr.c138
-rw-r--r--fs/nfsd/nfscache.c133
-rw-r--r--fs/nfsd/nfsfh.c11
-rw-r--r--fs/nfsd/nfsproc.c5
-rw-r--r--fs/nfsd/nfssvc.c8
-rw-r--r--fs/nfsd/vfs.c122
-rw-r--r--fs/partitions/Kconfig2
-rw-r--r--fs/partitions/msdos.c5
-rw-r--r--fs/pipe.c41
-rw-r--r--fs/posix_acl.c6
-rw-r--r--fs/proc/array.c13
-rw-r--r--fs/proc/base.c108
-rw-r--r--fs/proc/inode.c49
-rw-r--r--fs/proc/kcore.c2
-rw-r--r--fs/proc/proc_misc.c4
-rw-r--r--fs/proc/task_mmu.c109
-rw-r--r--fs/qnx4/bitmap.c4
-rw-r--r--fs/qnx4/inode.c8
-rw-r--r--fs/quota.c85
-rw-r--r--fs/ramfs/inode.c4
-rw-r--r--fs/reiserfs/inode.c2
-rw-r--r--fs/reiserfs/journal.c4
-rw-r--r--fs/reiserfs/namei.c32
-rw-r--r--fs/reiserfs/xattr.c6
-rw-r--r--fs/reiserfs/xattr_acl.c2
-rw-r--r--fs/select.c8
-rw-r--r--fs/seq_file.c25
-rw-r--r--fs/super.c4
-rw-r--r--fs/sysfs/file.c13
-rw-r--r--fs/sysfs/inode.c8
-rw-r--r--fs/sysfs/mount.c2
-rw-r--r--fs/ufs/super.c99
-rw-r--r--fs/vfat/namei.c523
-rw-r--r--fs/xfs/linux-2.6/kmem.h6
-rw-r--r--fs/xfs/linux-2.6/xfs_buf.c19
-rw-r--r--fs/xfs/linux-2.6/xfs_export.c119
-rw-r--r--fs/xfs/linux-2.6/xfs_export.h122
-rw-r--r--fs/xfs/linux-2.6/xfs_file.c37
-rw-r--r--fs/xfs/linux-2.6/xfs_ioctl.c236
-rw-r--r--fs/xfs/linux-2.6/xfs_linux.h3
-rw-r--r--fs/xfs/linux-2.6/xfs_lrw.c1
-rw-r--r--fs/xfs/linux-2.6/xfs_super.c27
-rw-r--r--fs/xfs/linux-2.6/xfs_vfs.c2
-rw-r--r--fs/xfs/linux-2.6/xfs_vfs.h2
-rw-r--r--fs/xfs/quota/xfs_dquot.c52
-rw-r--r--fs/xfs/quota/xfs_qm_syscalls.c6
-rw-r--r--fs/xfs/quota/xfs_quota_priv.h20
-rw-r--r--fs/xfs/quota/xfs_trans_dquot.c10
-rw-r--r--fs/xfs/xfs_acl.c45
-rw-r--r--fs/xfs/xfs_alloc.c6
-rw-r--r--fs/xfs/xfs_alloc_btree.c2
-rw-r--r--fs/xfs/xfs_arch.h159
-rw-r--r--fs/xfs/xfs_attr.c2
-rw-r--r--fs/xfs/xfs_attr_leaf.c60
-rw-r--r--fs/xfs/xfs_bmap.c2
-rw-r--r--fs/xfs/xfs_bmap_btree.c4
-rw-r--r--fs/xfs/xfs_bmap_btree.h4
-rw-r--r--fs/xfs/xfs_btree.c12
-rw-r--r--fs/xfs/xfs_clnt.h5
-rw-r--r--fs/xfs/xfs_da_btree.c42
-rw-r--r--fs/xfs/xfs_dinode.h156
-rw-r--r--fs/xfs/xfs_dir.c8
-rw-r--r--fs/xfs/xfs_dir2.c2
-rw-r--r--fs/xfs/xfs_dir2_block.c38
-rw-r--r--fs/xfs/xfs_dir2_block.h11
-rw-r--r--fs/xfs/xfs_dir2_data.c70
-rw-r--r--fs/xfs/xfs_dir2_data.h11
-rw-r--r--fs/xfs/xfs_dir2_leaf.c40
-rw-r--r--fs/xfs/xfs_dir2_leaf.h8
-rw-r--r--fs/xfs/xfs_dir2_node.c22
-rw-r--r--fs/xfs/xfs_dir2_sf.c96
-rw-r--r--fs/xfs/xfs_dir2_sf.h58
-rw-r--r--fs/xfs/xfs_dir_leaf.c70
-rw-r--r--fs/xfs/xfs_dir_leaf.h5
-rw-r--r--fs/xfs/xfs_dir_sf.h12
-rw-r--r--fs/xfs/xfs_fsops.c18
-rw-r--r--fs/xfs/xfs_ialloc.c37
-rw-r--r--fs/xfs/xfs_ialloc_btree.c16
-rw-r--r--fs/xfs/xfs_ialloc_btree.h22
-rw-r--r--fs/xfs/xfs_iget.c16
-rw-r--r--fs/xfs/xfs_inode.c97
-rw-r--r--fs/xfs/xfs_inode.h5
-rw-r--r--fs/xfs/xfs_inode_item.c4
-rw-r--r--fs/xfs/xfs_itable.c276
-rw-r--r--fs/xfs/xfs_log.c68
-rw-r--r--fs/xfs/xfs_log.h29
-rw-r--r--fs/xfs/xfs_log_priv.h18
-rw-r--r--fs/xfs/xfs_log_recover.c40
-rw-r--r--fs/xfs/xfs_macros.c173
-rw-r--r--fs/xfs/xfs_mount.c19
-rw-r--r--fs/xfs/xfs_mount.h7
-rw-r--r--fs/xfs/xfs_rename.c2
-rw-r--r--fs/xfs/xfs_vfsops.c18
-rw-r--r--fs/xfs/xfs_vnodeops.c16
-rw-r--r--include/asm-alpha/bitops.h6
-rw-r--r--include/asm-alpha/cacheflush.h2
-rw-r--r--include/asm-alpha/io.h11
-rw-r--r--include/asm-alpha/pci.h17
-rw-r--r--include/asm-alpha/pgtable.h13
-rw-r--r--include/asm-alpha/resource.h26
-rw-r--r--include/asm-alpha/spinlock.h99
-rw-r--r--include/asm-alpha/system.h2
-rw-r--r--include/asm-alpha/timex.h1
-rw-r--r--include/asm-alpha/uaccess.h3
-rw-r--r--include/asm-alpha/unaligned.h110
-rw-r--r--include/asm-alpha/unistd.h2
-rw-r--r--include/asm-arm/arch-cl7500/hardware.h19
-rw-r--r--include/asm-arm/arch-imx/hardware.h4
-rw-r--r--include/asm-arm/arch-ixp2000/entry-macro.S7
-rw-r--r--include/asm-arm/arch-ixp2000/io.h24
-rw-r--r--include/asm-arm/arch-ixp2000/irqs.h8
-rw-r--r--include/asm-arm/arch-ixp2000/ixdp2x00.h2
-rw-r--r--include/asm-arm/arch-ixp2000/ixdp2x01.h8
-rw-r--r--include/asm-arm/arch-ixp2000/ixp2000-regs.h91
-rw-r--r--include/asm-arm/arch-ixp2000/platform.h6
-rw-r--r--include/asm-arm/arch-ixp2000/system.h2
-rw-r--r--include/asm-arm/arch-ixp2000/vmalloc.h2
-rw-r--r--include/asm-arm/arch-ixp4xx/platform.h6
-rw-r--r--include/asm-arm/arch-omap/aic23.h112
-rw-r--r--include/asm-arm/arch-omap/board-h2.h8
-rw-r--r--include/asm-arm/arch-omap/board-h3.h4
-rw-r--r--include/asm-arm/arch-omap/board-h4.h4
-rw-r--r--include/asm-arm/arch-omap/board-innovator.h7
-rw-r--r--include/asm-arm/arch-omap/board-netstar.h19
-rw-r--r--include/asm-arm/arch-omap/board-osk.h8
-rw-r--r--include/asm-arm/arch-omap/board-voiceblue.h25
-rw-r--r--include/asm-arm/arch-omap/clocks.h216
-rw-r--r--include/asm-arm/arch-omap/fpga.h35
-rw-r--r--include/asm-arm/arch-omap/hardware.h110
-rw-r--r--include/asm-arm/arch-omap/irqs.h7
-rw-r--r--include/asm-arm/arch-omap/mcbsp.h4
-rw-r--r--include/asm-arm/arch-omap/memory.h4
-rw-r--r--include/asm-arm/arch-omap/mux.h20
-rw-r--r--include/asm-arm/arch-omap/omap16xx.h7
-rw-r--r--include/asm-arm/arch-omap/param.h22
-rw-r--r--include/asm-arm/arch-omap/tc.h72
-rw-r--r--include/asm-arm/arch-pxa/corgi.h4
-rw-r--r--include/asm-arm/arch-pxa/idp.h290
-rw-r--r--include/asm-arm/arch-pxa/irqs.h32
-rw-r--r--include/asm-arm/arch-pxa/poodle.h111
-rw-r--r--include/asm-arm/arch-rpc/hardware.h18
-rw-r--r--include/asm-arm/arch-rpc/io.h8
-rw-r--r--include/asm-arm/arch-s3c2410/debug-macro.S8
-rw-r--r--include/asm-arm/arch-s3c2410/entry-macro.S9
-rw-r--r--include/asm-arm/arch-s3c2410/hardware.h6
-rw-r--r--include/asm-arm/arch-s3c2410/io.h17
-rw-r--r--include/asm-arm/arch-s3c2410/irqs.h17
-rw-r--r--include/asm-arm/arch-s3c2410/map.h126
-rw-r--r--include/asm-arm/arch-s3c2410/memory.h8
-rw-r--r--include/asm-arm/arch-s3c2410/otom-map.h30
-rw-r--r--include/asm-arm/arch-s3c2410/regs-adc.h63
-rw-r--r--include/asm-arm/arch-s3c2410/regs-clock.h15
-rw-r--r--include/asm-arm/arch-s3c2410/regs-gpio.h12
-rw-r--r--include/asm-arm/arch-s3c2410/regs-iis.h11
-rw-r--r--include/asm-arm/arch-s3c2410/regs-irq.h5
-rw-r--r--include/asm-arm/arch-s3c2410/regs-lcd.h3
-rw-r--r--include/asm-arm/arch-s3c2410/regs-mem.h24
-rw-r--r--include/asm-arm/arch-s3c2410/regs-rtc.h3
-rw-r--r--include/asm-arm/arch-s3c2410/regs-serial.h14
-rw-r--r--include/asm-arm/arch-s3c2410/regs-timer.h5
-rw-r--r--include/asm-arm/arch-s3c2410/regs-udc.h3
-rw-r--r--include/asm-arm/arch-s3c2410/regs-watchdog.h3
-rw-r--r--include/asm-arm/arch-s3c2410/system.h2
-rw-r--r--include/asm-arm/arch-s3c2410/uncompress.h63
-rw-r--r--include/asm-arm/atomic.h1
-rw-r--r--include/asm-arm/cacheflush.h20
-rw-r--r--include/asm-arm/ecard.h15
-rw-r--r--include/asm-arm/hardware/locomo.h224
-rw-r--r--include/asm-arm/hardware/scoop.h10
-rw-r--r--include/asm-arm/io.h23
-rw-r--r--include/asm-arm/ipc.h29
-rw-r--r--include/asm-arm/mach/arch.h2
-rw-r--r--include/asm-arm/mach/map.h15
-rw-r--r--include/asm-arm/pgtable.h24
-rw-r--r--include/asm-arm/ptrace.h3
-rw-r--r--include/asm-arm/rtc.h1
-rw-r--r--include/asm-arm/system.h2
-rw-r--r--include/asm-arm/timex.h2
-rw-r--r--include/asm-arm/tlb.h38
-rw-r--r--include/asm-arm/uaccess.h3
-rw-r--r--include/asm-arm/unistd.h50
-rw-r--r--include/asm-arm26/cacheflush.h2
-rw-r--r--include/asm-arm26/io.h11
-rw-r--r--include/asm-arm26/ipc.h29
-rw-r--r--include/asm-arm26/pgtable.h10
-rw-r--r--include/asm-arm26/system.h2
-rw-r--r--include/asm-arm26/timex.h2
-rw-r--r--include/asm-arm26/tlb.h4
-rw-r--r--include/asm-arm26/uaccess.h3
-rw-r--r--include/asm-arm26/unistd.h2
-rw-r--r--include/asm-cris/cacheflush.h2
-rw-r--r--include/asm-cris/io.h11
-rw-r--r--include/asm-cris/ipc.h36
-rw-r--r--include/asm-cris/pgalloc.h1
-rw-r--r--include/asm-cris/pgtable.h4
-rw-r--r--include/asm-cris/system.h2
-rw-r--r--include/asm-cris/uaccess.h3
-rw-r--r--include/asm-cris/unistd.h2
-rw-r--r--include/asm-frv/cacheflush.h2
-rw-r--r--include/asm-frv/highmem.h2
-rw-r--r--include/asm-frv/io.h12
-rw-r--r--include/asm-frv/ipc.h34
-rw-r--r--include/asm-frv/pgtable.h25
-rw-r--r--include/asm-frv/system.h2
-rw-r--r--include/asm-frv/tlbflush.h3
-rw-r--r--include/asm-frv/uaccess.h3
-rw-r--r--include/asm-frv/unistd.h2
-rw-r--r--include/asm-generic/4level-fixup.h4
-rw-r--r--include/asm-generic/cputime.h2
-rw-r--r--include/asm-generic/dma-mapping.h4
-rw-r--r--include/asm-generic/ipc.h31
-rw-r--r--include/asm-generic/pgtable-nopmd.h5
-rw-r--r--include/asm-generic/pgtable-nopud.h5
-rw-r--r--include/asm-generic/pgtable.h150
-rw-r--r--include/asm-generic/resource.h76
-rw-r--r--include/asm-generic/siginfo.h1
-rw-r--r--include/asm-generic/tlb.h4
-rw-r--r--include/asm-generic/unaligned.h115
-rw-r--r--include/asm-h8300/cacheflush.h2
-rw-r--r--include/asm-h8300/io.h11
-rw-r--r--include/asm-h8300/ipc.h32
-rw-r--r--include/asm-h8300/pgtable.h7
-rw-r--r--include/asm-h8300/system.h2
-rw-r--r--include/asm-h8300/uaccess.h3
-rw-r--r--include/asm-i386/acpi.h1
-rw-r--r--include/asm-i386/cacheflush.h2
-rw-r--r--include/asm-i386/cpu.h1
-rw-r--r--include/asm-i386/desc.h4
-rw-r--r--include/asm-i386/dma-mapping.h2
-rw-r--r--include/asm-i386/hardirq.h7
-rw-r--r--include/asm-i386/highmem.h2
-rw-r--r--include/asm-i386/hpet.h2
-rw-r--r--include/asm-i386/i387.h6
-rw-r--r--include/asm-i386/io.h11
-rw-r--r--include/asm-i386/ipc.h33
-rw-r--r--include/asm-i386/mach-default/mach_traps.h12
-rw-r--r--include/asm-i386/mc146818rtc.h81
-rw-r--r--include/asm-i386/module.h2
-rw-r--r--include/asm-i386/mpspec.h1
-rw-r--r--include/asm-i386/msr.h15
-rw-r--r--include/asm-i386/pgalloc.h1
-rw-r--r--include/asm-i386/pgtable-2level.h3
-rw-r--r--include/asm-i386/pgtable-3level.h4
-rw-r--r--include/asm-i386/pgtable.h20
-rw-r--r--include/asm-i386/processor.h15
-rw-r--r--include/asm-i386/seccomp.h16
-rw-r--r--include/asm-i386/segment.h5
-rw-r--r--include/asm-i386/semaphore.h5
-rw-r--r--include/asm-i386/signal.h9
-rw-r--r--include/asm-i386/smp.h3
-rw-r--r--include/asm-i386/suspend.h7
-rw-r--r--include/asm-i386/system.h2
-rw-r--r--include/asm-i386/thread_info.h7
-rw-r--r--include/asm-i386/timex.h2
-rw-r--r--include/asm-i386/topology.h6
-rw-r--r--include/asm-i386/uaccess.h60
-rw-r--r--include/asm-i386/unistd.h2
-rw-r--r--include/asm-ia64/bitops.h6
-rw-r--r--include/asm-ia64/cacheflush.h2
-rw-r--r--include/asm-ia64/page.h2
-rw-r--r--include/asm-ia64/pci.h9
-rw-r--r--include/asm-ia64/pgalloc.h1
-rw-r--r--include/asm-ia64/pgtable.h72
-rw-r--r--include/asm-ia64/system.h3
-rw-r--r--include/asm-ia64/tlb.h4
-rw-r--r--include/asm-ia64/uaccess.h40
-rw-r--r--include/asm-ia64/unaligned.h117
-rw-r--r--include/asm-ia64/unistd.h2
-rw-r--r--include/asm-m32r/bug.h22
-rw-r--r--include/asm-m32r/cacheflush.h6
-rw-r--r--include/asm-m32r/io.h11
-rw-r--r--include/asm-m32r/ipc.h36
-rw-r--r--include/asm-m32r/mmu.h18
-rw-r--r--include/asm-m32r/pgalloc.h1
-rw-r--r--include/asm-m32r/pgtable-2level.h3
-rw-r--r--include/asm-m32r/pgtable.h21
-rw-r--r--include/asm-m32r/serial.h138
-rw-r--r--include/asm-m32r/spinlock.h6
-rw-r--r--include/asm-m32r/system.h2
-rw-r--r--include/asm-m32r/timex.h2
-rw-r--r--include/asm-m32r/uaccess.h5
-rw-r--r--include/asm-m32r/unistd.h2
-rw-r--r--include/asm-m68k/cacheflush.h15
-rw-r--r--include/asm-m68k/checksum.h41
-rw-r--r--include/asm-m68k/io.h14
-rw-r--r--include/asm-m68k/ipc.h32
-rw-r--r--include/asm-m68k/motorola_pgtable.h2
-rw-r--r--include/asm-m68k/pgtable.h8
-rw-r--r--include/asm-m68k/processor.h3
-rw-r--r--include/asm-m68k/signal.h2
-rw-r--r--include/asm-m68k/sun3_pgtable.h5
-rw-r--r--include/asm-m68k/system.h2
-rw-r--r--include/asm-m68k/thread_info.h6
-rw-r--r--include/asm-m68k/uaccess.h5
-rw-r--r--include/asm-m68k/unistd.h2
-rw-r--r--include/asm-m68knommu/cacheflush.h2
-rw-r--r--include/asm-m68knommu/entry.h53
-rw-r--r--include/asm-m68knommu/io.h11
-rw-r--r--include/asm-m68knommu/io_hw_swap.h113
-rw-r--r--include/asm-m68knommu/ipc.h2
-rw-r--r--include/asm-m68knommu/kmap_types.h6
-rw-r--r--include/asm-m68knommu/mcfcache.h6
-rw-r--r--include/asm-m68knommu/mmu.h13
-rw-r--r--include/asm-m68knommu/page.h6
-rw-r--r--include/asm-m68knommu/pgtable.h7
-rw-r--r--include/asm-m68knommu/semp3.h60
-rw-r--r--include/asm-m68knommu/system.h1
-rw-r--r--include/asm-m68knommu/thread_info.h27
-rw-r--r--include/asm-m68knommu/uaccess.h3
-rw-r--r--include/asm-m68knommu/unaligned.h10
-rw-r--r--include/asm-m68knommu/unistd.h2
-rw-r--r--include/asm-mips/cacheflush.h5
-rw-r--r--include/asm-mips/io.h11
-rw-r--r--include/asm-mips/ipc.h34
-rw-r--r--include/asm-mips/pci.h11
-rw-r--r--include/asm-mips/pgtable.h32
-rw-r--r--include/asm-mips/resource.h36
-rw-r--r--include/asm-mips/system.h2
-rw-r--r--include/asm-mips/timex.h1
-rw-r--r--include/asm-mips/uaccess.h11
-rw-r--r--include/asm-mips/unaligned.h132
-rw-r--r--include/asm-mips/unistd.h2
-rw-r--r--include/asm-mips/vr41xx/siu.h (renamed from arch/mips/vr41xx/tanbac-tb0229/tb0219.c)46
-rw-r--r--include/asm-mips/vr41xx/vr41xx.h31
-rw-r--r--include/asm-mips/vr41xx/vrc4171.h43
-rw-r--r--include/asm-parisc/assembly.h3
-rw-r--r--include/asm-parisc/bitops.h8
-rw-r--r--include/asm-parisc/cacheflush.h10
-rw-r--r--include/asm-parisc/checksum.h4
-rw-r--r--include/asm-parisc/compat.h8
-rw-r--r--include/asm-parisc/dma-mapping.h2
-rw-r--r--include/asm-parisc/dma.h8
-rw-r--r--include/asm-parisc/eisa_eeprom.h2
-rw-r--r--include/asm-parisc/hardirq.h12
-rw-r--r--include/asm-parisc/hardware.h1
-rw-r--r--include/asm-parisc/ide.h10
-rw-r--r--include/asm-parisc/io.h18
-rw-r--r--include/asm-parisc/irq.h8
-rw-r--r--include/asm-parisc/led.h8
-rw-r--r--include/asm-parisc/module.h4
-rw-r--r--include/asm-parisc/numnodes.h2
-rw-r--r--include/asm-parisc/parisc-device.h1
-rw-r--r--include/asm-parisc/pci.h62
-rw-r--r--include/asm-parisc/pdc_chassis.h6
-rw-r--r--include/asm-parisc/pdcpat.h6
-rw-r--r--include/asm-parisc/pgalloc.h1
-rw-r--r--include/asm-parisc/pgtable.h37
-rw-r--r--include/asm-parisc/serial.h2
-rw-r--r--include/asm-parisc/signal.h7
-rw-r--r--include/asm-parisc/spinlock.h2
-rw-r--r--include/asm-parisc/system.h4
-rw-r--r--include/asm-parisc/thread_info.h4
-rw-r--r--include/asm-parisc/timex.h2
-rw-r--r--include/asm-parisc/uaccess.h28
-rw-r--r--include/asm-parisc/unaligned.h17
-rw-r--r--include/asm-parisc/unistd.h2
-rw-r--r--include/asm-parisc/unwind.h17
-rw-r--r--include/asm-ppc/cache.h12
-rw-r--r--include/asm-ppc/cacheflush.h2
-rw-r--r--include/asm-ppc/cpm2.h5
-rw-r--r--include/asm-ppc/cputable.h5
-rw-r--r--include/asm-ppc/dma.h114
-rw-r--r--include/asm-ppc/floppy.h155
-rw-r--r--include/asm-ppc/highmem.h6
-rw-r--r--include/asm-ppc/io.h13
-rw-r--r--include/asm-ppc/ipc.h30
-rw-r--r--include/asm-ppc/ipic.h85
-rw-r--r--include/asm-ppc/irq.h179
-rw-r--r--include/asm-ppc/machdep.h9
-rw-r--r--include/asm-ppc/mmu.h26
-rw-r--r--include/asm-ppc/mpc10x.h4
-rw-r--r--include/asm-ppc/mpc52xx.h115
-rw-r--r--include/asm-ppc/mpc83xx.h114
-rw-r--r--include/asm-ppc/mpc85xx.h49
-rw-r--r--include/asm-ppc/mv64x60_defs.h46
-rw-r--r--include/asm-ppc/page.h2
-rw-r--r--include/asm-ppc/pci.h9
-rw-r--r--include/asm-ppc/pgtable.h89
-rw-r--r--include/asm-ppc/pmac_feature.h8
-rw-r--r--include/asm-ppc/ppc4xx_pic.h8
-rw-r--r--include/asm-ppc/ppc_sys.h6
-rw-r--r--include/asm-ppc/ppcboot.h6
-rw-r--r--include/asm-ppc/reg.h91
-rw-r--r--include/asm-ppc/reg_booke.h20
-rw-r--r--include/asm-ppc/serial.h6
-rw-r--r--include/asm-ppc/suspend.h12
-rw-r--r--include/asm-ppc/system.h6
-rw-r--r--include/asm-ppc/timex.h2
-rw-r--r--include/asm-ppc/todc.h23
-rw-r--r--include/asm-ppc/uaccess.h3
-rw-r--r--include/asm-ppc/uninorth.h7
-rw-r--r--include/asm-ppc/unistd.h5
-rw-r--r--include/asm-ppc64/a.out.h11
-rw-r--r--include/asm-ppc64/agp.h13
-rw-r--r--include/asm-ppc64/cacheflush.h5
-rw-r--r--include/asm-ppc64/cputable.h5
-rw-r--r--include/asm-ppc64/dma-mapping.h22
-rw-r--r--include/asm-ppc64/eeh.h31
-rw-r--r--include/asm-ppc64/elf.h19
-rw-r--r--include/asm-ppc64/hvcall.h14
-rw-r--r--include/asm-ppc64/iSeries/iSeries_fixup.h25
-rw-r--r--include/asm-ppc64/io.h11
-rw-r--r--include/asm-ppc64/iommu.h6
-rw-r--r--include/asm-ppc64/ipc.h35
-rw-r--r--include/asm-ppc64/kprobes.h5
-rw-r--r--include/asm-ppc64/lmb.h3
-rw-r--r--include/asm-ppc64/machdep.h26
-rw-r--r--include/asm-ppc64/mmu_context.h4
-rw-r--r--include/asm-ppc64/pSeries_reconfig.h25
-rw-r--r--include/asm-ppc64/paca.h3
-rw-r--r--include/asm-ppc64/page.h34
-rw-r--r--include/asm-ppc64/pci.h137
-rw-r--r--include/asm-ppc64/pgalloc.h31
-rw-r--r--include/asm-ppc64/pgtable.h108
-rw-r--r--include/asm-ppc64/pmc.h29
-rw-r--r--include/asm-ppc64/processor.h13
-rw-r--r--include/asm-ppc64/prom.h5
-rw-r--r--include/asm-ppc64/rtas.h3
-rw-r--r--include/asm-ppc64/seccomp.h21
-rw-r--r--include/asm-ppc64/sections.h9
-rw-r--r--include/asm-ppc64/smp.h9
-rw-r--r--include/asm-ppc64/smu.h22
-rw-r--r--include/asm-ppc64/system.h2
-rw-r--r--include/asm-ppc64/systemcfg.h13
-rw-r--r--include/asm-ppc64/thread_info.h4
-rw-r--r--include/asm-ppc64/time.h11
-rw-r--r--include/asm-ppc64/uaccess.h30
-rw-r--r--include/asm-ppc64/unistd.h5
-rw-r--r--include/asm-ppc64/vdso.h83
-rw-r--r--include/asm-ppc64/vio.h27
-rw-r--r--include/asm-s390/atomic.h4
-rw-r--r--include/asm-s390/cacheflush.h2
-rw-r--r--include/asm-s390/ccwdev.h3
-rw-r--r--include/asm-s390/cputime.h8
-rw-r--r--include/asm-s390/io.h11
-rw-r--r--include/asm-s390/ipc.h41
-rw-r--r--include/asm-s390/pgalloc.h7
-rw-r--r--include/asm-s390/pgtable.h35
-rw-r--r--include/asm-s390/posix_types.h8
-rw-r--r--include/asm-s390/smp.h25
-rw-r--r--include/asm-s390/system.h18
-rw-r--r--include/asm-s390/timex.h2
-rw-r--r--include/asm-s390/uaccess.h12
-rw-r--r--include/asm-s390/unistd.h11
-rw-r--r--include/asm-sh/bitops.h6
-rw-r--r--include/asm-sh/bug.h2
-rw-r--r--include/asm-sh/cacheflush.h6
-rw-r--r--include/asm-sh/cpu-sh2/cacheflush.h4
-rw-r--r--include/asm-sh/cpu-sh3/cacheflush.h6
-rw-r--r--include/asm-sh/cpu-sh3/freq.h4
-rw-r--r--include/asm-sh/cpu-sh3/timer.h64
-rw-r--r--include/asm-sh/cpu-sh4/cacheflush.h2
-rw-r--r--include/asm-sh/cpu-sh4/timer.h51
-rw-r--r--include/asm-sh/dma-mapping.h1
-rw-r--r--include/asm-sh/hardirq.h11
-rw-r--r--include/asm-sh/io.h11
-rw-r--r--include/asm-sh/ipc.h33
-rw-r--r--include/asm-sh/irq.h3
-rw-r--r--include/asm-sh/mc146818rtc.h1
-rw-r--r--include/asm-sh/pgalloc.h1
-rw-r--r--include/asm-sh/pgtable-2level.h2
-rw-r--r--include/asm-sh/pgtable.h11
-rw-r--r--include/asm-sh/sh03/ide.h7
-rw-r--r--include/asm-sh/system.h2
-rw-r--r--include/asm-sh/timex.h2
-rw-r--r--include/asm-sh/uaccess.h3
-rw-r--r--include/asm-sh/unaligned.h14
-rw-r--r--include/asm-sh/unistd.h2
-rw-r--r--include/asm-sh64/bug.h27
-rw-r--r--include/asm-sh64/cacheflush.h6
-rw-r--r--include/asm-sh64/elf.h6
-rw-r--r--include/asm-sh64/hardirq.h14
-rw-r--r--include/asm-sh64/hardware.h25
-rw-r--r--include/asm-sh64/ide.h5
-rw-r--r--include/asm-sh64/io.h92
-rw-r--r--include/asm-sh64/ioctls.h173
-rw-r--r--include/asm-sh64/ipc.h7
-rw-r--r--include/asm-sh64/irq.h5
-rw-r--r--include/asm-sh64/module.h8
-rw-r--r--include/asm-sh64/pgalloc.h1
-rw-r--r--include/asm-sh64/pgtable.h13
-rw-r--r--include/asm-sh64/system.h3
-rw-r--r--include/asm-sh64/thread_info.h8
-rw-r--r--include/asm-sh64/timex.h2
-rw-r--r--include/asm-sh64/uaccess.h9
-rw-r--r--include/asm-sh64/unaligned.h13
-rw-r--r--include/asm-sh64/unistd.h9
-rw-r--r--include/asm-sparc/cacheflush.h14
-rw-r--r--include/asm-sparc/io.h13
-rw-r--r--include/asm-sparc/ipc.h33
-rw-r--r--include/asm-sparc/mostek.h1
-rw-r--r--include/asm-sparc/pgtable.h17
-rw-r--r--include/asm-sparc/resource.h26
-rw-r--r--include/asm-sparc/system.h2
-rw-r--r--include/asm-sparc/timex.h1
-rw-r--r--include/asm-sparc/uaccess.h5
-rw-r--r--include/asm-sparc/unaligned.h15
-rw-r--r--include/asm-sparc/unistd.h2
-rw-r--r--include/asm-sparc64/bugs.h2
-rw-r--r--include/asm-sparc64/cacheflush.h14
-rw-r--r--include/asm-sparc64/io.h11
-rw-r--r--include/asm-sparc64/ipc.h34
-rw-r--r--include/asm-sparc64/mostek.h2
-rw-r--r--include/asm-sparc64/pci.h5
-rw-r--r--include/asm-sparc64/pgalloc.h22
-rw-r--r--include/asm-sparc64/pgtable.h43
-rw-r--r--include/asm-sparc64/resource.h22
-rw-r--r--include/asm-sparc64/siginfo.h28
-rw-r--r--include/asm-sparc64/smp.h2
-rw-r--r--include/asm-sparc64/system.h2
-rw-r--r--include/asm-sparc64/tlb.h4
-rw-r--r--include/asm-sparc64/uaccess.h16
-rw-r--r--include/asm-sparc64/unaligned.h15
-rw-r--r--include/asm-sparc64/unistd.h2
-rw-r--r--include/asm-um/archparam-i386.h2
-rw-r--r--include/asm-um/io.h11
-rw-r--r--include/asm-um/pgtable-2level.h2
-rw-r--r--include/asm-um/pgtable-3level.h1
-rw-r--r--include/asm-um/pgtable.h2
-rw-r--r--include/asm-um/processor-generic.h2
-rw-r--r--include/asm-um/processor-i386.h8
-rw-r--r--include/asm-um/processor-x86_64.h8
-rw-r--r--include/asm-um/setup.h5
-rw-r--r--include/asm-um/signal.h3
-rw-r--r--include/asm-um/timex.h2
-rw-r--r--include/asm-v850/cacheflush.h2
-rw-r--r--include/asm-v850/io.h11
-rw-r--r--include/asm-v850/ipc.h32
-rw-r--r--include/asm-v850/system.h2
-rw-r--r--include/asm-v850/uaccess.h3
-rw-r--r--include/asm-v850/unistd.h2
-rw-r--r--include/asm-x86_64/acpi.h1
-rw-r--r--include/asm-x86_64/cacheflush.h2
-rw-r--r--include/asm-x86_64/io.h15
-rw-r--r--include/asm-x86_64/ipc.h6
-rw-r--r--include/asm-x86_64/mmu_context.h10
-rw-r--r--include/asm-x86_64/mpspec.h3
-rw-r--r--include/asm-x86_64/msr.h20
-rw-r--r--include/asm-x86_64/page.h4
-rw-r--r--include/asm-x86_64/pgalloc.h6
-rw-r--r--include/asm-x86_64/pgtable.h25
-rw-r--r--include/asm-x86_64/processor.h1
-rw-r--r--include/asm-x86_64/seccomp.h24
-rw-r--r--include/asm-x86_64/segment.h7
-rw-r--r--include/asm-x86_64/suspend.h1
-rw-r--r--include/asm-x86_64/system.h2
-rw-r--r--include/asm-x86_64/thread_info.h6
-rw-r--r--include/asm-x86_64/timex.h2
-rw-r--r--include/asm-x86_64/uaccess.h33
-rw-r--r--include/asm-x86_64/unistd.h4
-rw-r--r--include/linux/ac97_codec.h1
-rw-r--r--include/linux/acct.h4
-rw-r--r--include/linux/agp_backend.h29
-rw-r--r--include/linux/agpgart.h4
-rw-r--r--include/linux/aio_abi.h2
-rw-r--r--include/linux/atalk.h12
-rw-r--r--include/linux/atmdev.h28
-rw-r--r--include/linux/audit.h21
-rw-r--r--include/linux/backing-dev.h41
-rw-r--r--include/linux/bio.h11
-rw-r--r--include/linux/bitmap.h8
-rw-r--r--include/linux/bitops.h22
-rw-r--r--include/linux/blkdev.h39
-rw-r--r--include/linux/buffer_head.h5
-rw-r--r--include/linux/capability.h2
-rw-r--r--include/linux/compat.h14
-rw-r--r--include/linux/compat_ioctl.h4
-rw-r--r--include/linux/compiler-gcc3.h10
-rw-r--r--include/linux/compiler-gcc4.h (renamed from include/linux/compiler-gcc+.h)8
-rw-r--r--include/linux/compiler.h12
-rw-r--r--include/linux/console.h9
-rw-r--r--include/linux/console_struct.h7
-rw-r--r--include/linux/consolemap.h2
-rw-r--r--include/linux/cpumask.h22
-rw-r--r--include/linux/cpuset.h64
-rw-r--r--include/linux/cryptohash.h12
-rw-r--r--include/linux/dcache.h19
-rw-r--r--include/linux/debugfs.h2
-rw-r--r--include/linux/device.h7
-rw-r--r--include/linux/dp83840.h41
-rw-r--r--include/linux/dqblk_xfs.h6
-rw-r--r--include/linux/dvb/audio.h31
-rw-r--r--include/linux/dvb/ca.h5
-rw-r--r--include/linux/dvb/dmx.h42
-rw-r--r--include/linux/dvb/frontend.h197
-rw-r--r--include/linux/dvb/net.h12
-rw-r--r--include/linux/dvb/osd.h9
-rw-r--r--include/linux/dvb/version.h1
-rw-r--r--include/linux/dvb/video.h65
-rw-r--r--include/linux/efi.h1
-rw-r--r--include/linux/elevator.h3
-rw-r--r--include/linux/etherdevice.h15
-rw-r--r--include/linux/ext3_fs.h1
-rw-r--r--include/linux/ext3_jbd.h21
-rw-r--r--include/linux/fb.h25
-rw-r--r--include/linux/fcdevice.h2
-rw-r--r--include/linux/fs.h21
-rw-r--r--include/linux/gameport.h133
-rw-r--r--include/linux/generic_serial.h6
-rw-r--r--include/linux/gfp.h36
-rw-r--r--include/linux/hayesesp.h1
-rw-r--r--include/linux/hdpu_features.h26
-rw-r--r--include/linux/hiddev.h4
-rw-r--r--include/linux/hugetlb.h4
-rw-r--r--include/linux/i2c-id.h18
-rw-r--r--include/linux/i2c.h61
-rw-r--r--include/linux/ibmtr.h15
-rw-r--r--include/linux/ide.h17
-rw-r--r--include/linux/if_ec.h10
-rw-r--r--include/linux/if_pppox.h19
-rw-r--r--include/linux/inetdevice.h20
-rw-r--r--include/linux/init_task.h12
-rw-r--r--include/linux/input.h2
-rw-r--r--include/linux/ioc4_common.h21
-rw-r--r--include/linux/ioport.h2
-rw-r--r--include/linux/ip.h15
-rw-r--r--include/linux/ip_mp_alg.h22
-rw-r--r--include/linux/ipmi_smi.h11
-rw-r--r--include/linux/ipv6.h7
-rw-r--r--include/linux/isapnp.h20
-rw-r--r--include/linux/jbd.h23
-rw-r--r--include/linux/jffs.h1
-rw-r--r--include/linux/journal-head.h7
-rw-r--r--include/linux/joystick.h8
-rw-r--r--include/linux/kernel.h35
-rw-r--r--include/linux/key.h5
-rw-r--r--include/linux/keyboard.h3
-rw-r--r--include/linux/kfifo.h16
-rw-r--r--include/linux/kobj_map.h2
-rw-r--r--include/linux/kobject.h2
-rw-r--r--include/linux/kref.h2
-rw-r--r--include/linux/libata.h64
-rw-r--r--include/linux/lockd/lockd.h3
-rw-r--r--include/linux/loop.h5
-rw-r--r--include/linux/major.h1
-rw-r--r--include/linux/mempool.h8
-rw-r--r--include/linux/mii.h20
-rw-r--r--include/linux/mm.h2
-rw-r--r--include/linux/mmc/card.h2
-rw-r--r--include/linux/mmc/mmc.h1
-rw-r--r--include/linux/mmc/protocol.h12
-rw-r--r--include/linux/mmzone.h11
-rw-r--r--include/linux/mod_devicetable.h10
-rw-r--r--include/linux/module.h14
-rw-r--r--include/linux/moduleparam.h19
-rw-r--r--include/linux/mpage.h6
-rw-r--r--include/linux/msdos_fs.h133
-rw-r--r--include/linux/mtio.h28
-rw-r--r--include/linux/mv643xx.h465
-rw-r--r--include/linux/namei.h2
-rw-r--r--include/linux/net.h2
-rw-r--r--include/linux/netdevice.h15
-rw-r--r--include/linux/netfilter.h38
-rw-r--r--include/linux/netfilter_arp/arp_tables.h2
-rw-r--r--include/linux/netfilter_ipv4/ip_conntrack_tcp.h5
-rw-r--r--include/linux/netfilter_ipv4/ip_tables.h2
-rw-r--r--include/linux/netfilter_ipv6/ip6_tables.h2
-rw-r--r--include/linux/netpoll.h35
-rw-r--r--include/linux/nfs_fs.h47
-rw-r--r--include/linux/nfs_fs_sb.h1
-rw-r--r--include/linux/nfs_xdr.h12
-rw-r--r--include/linux/nfsd/cache.h7
-rw-r--r--include/linux/nfsd/nfsd.h17
-rw-r--r--include/linux/nfsd/state.h19
-rw-r--r--include/linux/nfsd/xdr4.h1
-rw-r--r--include/linux/nodemask.h22
-rw-r--r--include/linux/page-flags.h7
-rw-r--r--include/linux/pagemap.h2
-rw-r--r--include/linux/parport.h12
-rw-r--r--include/linux/pci.h11
-rw-r--r--include/linux/pci_ids.h146
-rw-r--r--include/linux/personality.h3
-rw-r--r--include/linux/pkt_cls.h108
-rw-r--r--include/linux/pm.h10
-rw-r--r--include/linux/pnp.h2
-rw-r--r--include/linux/poll.h10
-rw-r--r--include/linux/posix-timers.h93
-rw-r--r--include/linux/posix_acl.h6
-rw-r--r--include/linux/qnx4_fs.h2
-rw-r--r--include/linux/random.h13
-rw-r--r--include/linux/reiserfs_fs_i.h5
-rw-r--r--include/linux/reiserfs_xattr.h9
-rw-r--r--include/linux/rtnetlink.h22
-rw-r--r--include/linux/sched.h76
-rw-r--r--include/linux/scx200.h10
-rw-r--r--include/linux/scx200_gpio.h2
-rw-r--r--include/linux/seccomp.h34
-rw-r--r--include/linux/security.h87
-rw-r--r--include/linux/seq_file.h1
-rw-r--r--include/linux/serial_core.h14
-rw-r--r--include/linux/serio.h94
-rw-r--r--include/linux/signal.h3
-rw-r--r--include/linux/skbuff.h109
-rw-r--r--include/linux/slab.h9
-rw-r--r--include/linux/smp.h6
-rw-r--r--include/linux/sort.h10
-rw-r--r--include/linux/stallion.h2
-rw-r--r--include/linux/stop_machine.h2
-rw-r--r--include/linux/sunrpc/auth.h19
-rw-r--r--include/linux/sunrpc/auth_gss.h7
-rw-r--r--include/linux/sunrpc/cache.h19
-rw-r--r--include/linux/sunrpc/clnt.h2
-rw-r--r--include/linux/sunrpc/gss_api.h14
-rw-r--r--include/linux/sunrpc/sched.h8
-rw-r--r--include/linux/sunrpc/svc.h3
-rw-r--r--include/linux/sunrpc/svcauth.h16
-rw-r--r--include/linux/sunrpc/xprt.h3
-rw-r--r--include/linux/superhyway.h79
-rw-r--r--include/linux/suspend.h21
-rw-r--r--include/linux/swap.h2
-rw-r--r--include/linux/sysctl.h16
-rw-r--r--include/linux/sysrq.h14
-rw-r--r--include/linux/tc_ematch/tc_em_cmp.h26
-rw-r--r--include/linux/tc_ematch/tc_em_meta.h69
-rw-r--r--include/linux/tc_ematch/tc_em_nbyte.h13
-rw-r--r--include/linux/tcp.h25
-rw-r--r--include/linux/threads.h7
-rw-r--r--include/linux/timex.h2
-rw-r--r--include/linux/topology.h5
-rw-r--r--include/linux/tpqic02.h738
-rw-r--r--include/linux/transport_class.h18
-rw-r--r--include/linux/uinput.h92
-rw-r--r--include/linux/usb.h21
-rw-r--r--include/linux/usb_cdc.h192
-rw-r--r--include/linux/usbdevice_fs.h23
-rw-r--r--include/linux/videodev2.h146
-rw-r--r--include/linux/vmalloc.h3
-rw-r--r--include/linux/vt_kern.h50
-rw-r--r--include/linux/wait.h62
-rw-r--r--include/linux/workqueue.h1
-rw-r--r--include/linux/writeback.h1
-rw-r--r--include/media/ir-common.h6
-rw-r--r--include/media/saa6752hs.h29
-rw-r--r--include/media/saa7146.h43
-rw-r--r--include/media/saa7146_vv.h28
-rw-r--r--include/media/tuner.h81
-rw-r--r--include/net/act_api.h2
-rw-r--r--include/net/addrconf.h4
-rw-r--r--include/net/bluetooth/bluetooth.h1
-rw-r--r--include/net/bluetooth/hci_core.h36
-rw-r--r--include/net/bluetooth/l2cap.h3
-rw-r--r--include/net/bluetooth/rfcomm.h3
-rw-r--r--include/net/bluetooth/sco.h3
-rw-r--r--include/net/checksum.h2
-rw-r--r--include/net/dn.h6
-rw-r--r--include/net/dst.h24
-rw-r--r--include/net/flow.h1
-rw-r--r--include/net/inetpeer.h3
-rw-r--r--include/net/ip_fib.h16
-rw-r--r--include/net/ip_mp_alg.h99
-rw-r--r--include/net/ipv6.h28
-rw-r--r--include/net/irda/af_irda.h9
-rw-r--r--include/net/irda/irda.h29
-rw-r--r--include/net/llc_conn.h11
-rw-r--r--include/net/ndisc.h14
-rw-r--r--include/net/neighbour.h3
-rw-r--r--include/net/netrom.h10
-rw-r--r--include/net/pkt_cls.h192
-rw-r--r--include/net/rose.h10
-rw-r--r--include/net/route.h9
-rw-r--r--include/net/scm.h4
-rw-r--r--include/net/slhc_vj.h3
-rw-r--r--include/net/sock.h63
-rw-r--r--include/net/tcp.h3
-rw-r--r--include/net/tcp_ecn.h2
-rw-r--r--include/net/x25.h10
-rw-r--r--include/net/xfrm.h8
-rw-r--r--include/pcmcia/ds.h15
-rw-r--r--include/pcmcia/ss.h13
-rw-r--r--include/scsi/scsi.h6
-rw-r--r--include/scsi/scsi_cmnd.h3
-rw-r--r--include/scsi/scsi_device.h18
-rw-r--r--include/scsi/scsi_devinfo.h1
-rw-r--r--include/scsi/scsi_driver.h2
-rw-r--r--include/scsi/scsi_host.h46
-rw-r--r--include/scsi/scsi_transport.h14
-rw-r--r--include/scsi/scsi_transport_fc.h204
-rw-r--r--include/scsi/scsi_transport_spi.h1
-rw-r--r--include/sound/ac97_codec.h15
-rw-r--r--include/sound/ak4114.h205
-rw-r--r--include/sound/ak4117.h6
-rw-r--r--include/sound/ak4xxx-adda.h3
-rw-r--r--include/sound/asound.h1
-rw-r--r--include/sound/asoundef.h2
-rw-r--r--include/sound/control.h7
-rw-r--r--include/sound/core.h50
-rw-r--r--include/sound/cs46xx.h4
-rw-r--r--include/sound/emu10k1.h186
-rw-r--r--include/sound/gus.h4
-rw-r--r--include/sound/hwdep.h1
-rw-r--r--include/sound/mixer_oss.h2
-rw-r--r--include/sound/mpu401.h3
-rw-r--r--include/sound/rawmidi.h8
-rw-r--r--include/sound/seq_midi_emul.h4
-rw-r--r--include/sound/seq_virmidi.h2
-rw-r--r--include/sound/trident.h10
-rw-r--r--include/sound/version.h4
-rw-r--r--include/sound/ymfpci.h22
-rw-r--r--include/sound/yss225.h23
-rw-r--r--include/video/kyro.h2
-rw-r--r--include/video/pm3fb.h40
-rw-r--r--include/video/s1d13xxxfb.h166
-rw-r--r--include/video/trident.h2
-rw-r--r--init/Kconfig53
-rw-r--r--init/do_mounts.c4
-rw-r--r--init/main.c33
-rw-r--r--ipc/compat_mq.c16
-rw-r--r--ipc/msg.c3
-rw-r--r--ipc/sem.c3
-rw-r--r--ipc/shm.c3
-rw-r--r--kernel/Makefile6
-rw-r--r--kernel/acct.c8
-rw-r--r--kernel/audit.c23
-rw-r--r--kernel/auditsc.c116
-rw-r--r--kernel/capability.c4
-rw-r--r--kernel/compat.c60
-rw-r--r--kernel/cpuset.c1564
-rw-r--r--kernel/exit.c26
-rw-r--r--kernel/fork.c110
-rw-r--r--kernel/futex.c134
-rw-r--r--kernel/intermodule.c3
-rw-r--r--kernel/irq/proc.c10
-rw-r--r--kernel/itimer.c225
-rw-r--r--kernel/kallsyms.c21
-rw-r--r--kernel/kfifo.c14
-rw-r--r--kernel/kprobes.c5
-rw-r--r--kernel/module.c33
-rw-r--r--kernel/panic.c3
-rw-r--r--kernel/posix-cpu-timers.c1559
-rw-r--r--kernel/posix-timers.c329
-rw-r--r--kernel/power/disk.c102
-rw-r--r--kernel/power/main.c10
-rw-r--r--kernel/power/pm.c2
-rw-r--r--kernel/power/poweroff.c3
-rw-r--r--kernel/power/smp.c2
-rw-r--r--kernel/power/swsusp.c602
-rw-r--r--kernel/printk.c96
-rw-r--r--kernel/rcupdate.c6
-rw-r--r--kernel/resource.c2
-rw-r--r--kernel/sched.c285
-rw-r--r--kernel/seccomp.c56
-rw-r--r--kernel/signal.c40
-rw-r--r--kernel/softirq.c12
-rw-r--r--kernel/spinlock.c2
-rw-r--r--kernel/stop_machine.c7
-rw-r--r--kernel/sys.c22
-rw-r--r--kernel/sys_ni.c139
-rw-r--r--kernel/sysctl.c108
-rw-r--r--kernel/time.c11
-rw-r--r--kernel/timer.c13
-rw-r--r--kernel/user.c3
-rw-r--r--kernel/workqueue.c24
-rw-r--r--lib/Kconfig.debug69
-rw-r--r--lib/Makefile7
-rw-r--r--lib/bitmap.c103
-rw-r--r--lib/extable.c32
-rw-r--r--lib/halfmd4.c66
-rw-r--r--lib/kernel_lock.c2
-rw-r--r--lib/kobject.c15
-rw-r--r--lib/kref.c11
-rw-r--r--lib/rwsem-spinlock.c42
-rw-r--r--lib/rwsem.c16
-rw-r--r--lib/sha1.c96
-rw-r--r--lib/sort.c119
-rw-r--r--lib/vsprintf.c4
-rw-r--r--mm/filemap.c99
-rw-r--r--mm/fremap.c12
-rw-r--r--mm/highmem.c12
-rw-r--r--mm/memory.c836
-rw-r--r--mm/mempolicy.c33
-rw-r--r--mm/mempool.c18
-rw-r--r--mm/mincore.c10
-rw-r--r--mm/mlock.c49
-rw-r--r--mm/mmap.c82
-rw-r--r--mm/mprotect.c154
-rw-r--r--mm/mremap.c32
-rw-r--r--mm/msync.c201
-rw-r--r--mm/nommu.c15
-rw-r--r--mm/oom_kill.c2
-rw-r--r--mm/page-writeback.c74
-rw-r--r--mm/page_alloc.c137
-rw-r--r--mm/page_io.c2
-rw-r--r--mm/readahead.c192
-rw-r--r--mm/rmap.c25
-rw-r--r--mm/shmem.c8
-rw-r--r--mm/slab.c135
-rw-r--r--mm/swap_state.c29
-rw-r--r--mm/swapfile.c197
-rw-r--r--mm/thrash.c2
-rw-r--r--mm/truncate.c67
-rw-r--r--mm/vmalloc.c303
-rw-r--r--mm/vmscan.c183
-rw-r--r--net/802/fc.c34
-rw-r--r--net/Kconfig35
-rw-r--r--net/appletalk/ddp.c26
-rw-r--r--net/atm/atm_misc.c7
-rw-r--r--net/atm/br2684.c4
-rw-r--r--net/atm/clip.c19
-rw-r--r--net/atm/common.c72
-rw-r--r--net/atm/ioctl.c9
-rw-r--r--net/atm/lec.c126
-rw-r--r--net/atm/lec.h17
-rw-r--r--net/atm/lec_arpc.h24
-rw-r--r--net/atm/mpc.c34
-rw-r--r--net/atm/mpc.h4
-rw-r--r--net/atm/pppoatm.c5
-rw-r--r--net/atm/proc.c18
-rw-r--r--net/atm/protocols.h2
-rw-r--r--net/atm/raw.c16
-rw-r--r--net/atm/signaling.c40
-rw-r--r--net/atm/svc.c71
-rw-r--r--net/ax25/af_ax25.c23
-rw-r--r--net/ax25/ax25_in.c6
-rw-r--r--net/ax25/ax25_route.c2
-rw-r--r--net/bluetooth/af_bluetooth.c49
-rw-r--r--net/bluetooth/bnep/sock.c11
-rw-r--r--net/bluetooth/cmtp/sock.c8
-rw-r--r--net/bluetooth/hci_conn.c18
-rw-r--r--net/bluetooth/hci_event.c38
-rw-r--r--net/bluetooth/hci_sock.c8
-rw-r--r--net/bluetooth/hci_sysfs.c2
-rw-r--r--net/bluetooth/hidp/sock.c8
-rw-r--r--net/bluetooth/l2cap.c22
-rw-r--r--net/bluetooth/rfcomm/core.c6
-rw-r--r--net/bluetooth/rfcomm/sock.c25
-rw-r--r--net/bluetooth/sco.c20
-rw-r--r--net/bridge/br.c10
-rw-r--r--net/bridge/br_device.c6
-rw-r--r--net/bridge/br_fdb.c193
-rw-r--r--net/bridge/br_if.c2
-rw-r--r--net/bridge/br_input.c4
-rw-r--r--net/bridge/br_ioctl.c2
-rw-r--r--net/bridge/br_netfilter.c6
-rw-r--r--net/bridge/br_private.h18
-rw-r--r--net/bridge/br_stp_if.c3
-rw-r--r--net/bridge/netfilter/ebtables.c21
-rw-r--r--net/core/dev.c54
-rw-r--r--net/core/gen_stats.c10
-rw-r--r--net/core/neighbour.c116
-rw-r--r--net/core/netfilter.c103
-rw-r--r--net/core/netpoll.c216
-rw-r--r--net/core/pktgen.c74
-rw-r--r--net/core/skbuff.c77
-rw-r--r--net/core/sock.c58
-rw-r--r--net/decnet/af_decnet.c33
-rw-r--r--net/decnet/dn_nsp_in.c2
-rw-r--r--net/decnet/dn_route.c3
-rw-r--r--net/econet/af_econet.c27
-rw-r--r--net/ipv4/Kconfig42
-rw-r--r--net/ipv4/Makefile5
-rw-r--r--net/ipv4/af_inet.c14
-rw-r--r--net/ipv4/ah4.c4
-rw-r--r--net/ipv4/arp.c2
-rw-r--r--net/ipv4/devinet.c29
-rw-r--r--net/ipv4/esp4.c4
-rw-r--r--net/ipv4/fib_hash.c38
-rw-r--r--net/ipv4/fib_lookup.h3
-rw-r--r--net/ipv4/fib_semantics.c25
-rw-r--r--net/ipv4/icmp.c37
-rw-r--r--net/ipv4/inetpeer.c4
-rw-r--r--net/ipv4/ip_gre.c12
-rw-r--r--net/ipv4/ip_input.c7
-rw-r--r--net/ipv4/ip_output.c15
-rw-r--r--net/ipv4/ip_sockglue.c2
-rw-r--r--net/ipv4/ipcomp.c4
-rw-r--r--net/ipv4/ipip.c6
-rw-r--r--net/ipv4/ipmr.c2
-rw-r--r--net/ipv4/ipvs/ip_vs_core.c2
-rw-r--r--net/ipv4/ipvs/ip_vs_ctl.c19
-rw-r--r--net/ipv4/ipvs/ip_vs_wrr.c6
-rw-r--r--net/ipv4/ipvs/ip_vs_xmit.c11
-rw-r--r--net/ipv4/multipath.c55
-rw-r--r--net/ipv4/multipath_drr.c265
-rw-r--r--net/ipv4/multipath_random.c128
-rw-r--r--net/ipv4/multipath_rr.c115
-rw-r--r--net/ipv4/multipath_wrandom.c344
-rw-r--r--net/ipv4/netfilter/arp_tables.c8
-rw-r--r--net/ipv4/netfilter/ip_conntrack_proto_sctp.c4
-rw-r--r--net/ipv4/netfilter/ip_conntrack_proto_tcp.c155
-rw-r--r--net/ipv4/netfilter/ip_conntrack_standalone.c131
-rw-r--r--net/ipv4/netfilter/ip_nat_ftp.c9
-rw-r--r--net/ipv4/netfilter/ip_nat_irc.c9
-rw-r--r--net/ipv4/netfilter/ip_queue.c42
-rw-r--r--net/ipv4/netfilter/ip_tables.c10
-rw-r--r--net/ipv4/netfilter/ipt_LOG.c10
-rw-r--r--net/ipv4/netfilter/ipt_REJECT.c149
-rw-r--r--net/ipv4/netfilter/ipt_TCPMSS.c6
-rw-r--r--net/ipv4/netfilter/ipt_hashlimit.c92
-rw-r--r--net/ipv4/raw.c2
-rw-r--r--net/ipv4/route.c788
-rw-r--r--net/ipv4/syncookies.c77
-rw-r--r--net/ipv4/tcp.c1
-rw-r--r--net/ipv4/tcp_input.c33
-rw-r--r--net/ipv4/tcp_ipv4.c15
-rw-r--r--net/ipv4/tcp_minisocks.c2
-rw-r--r--net/ipv4/tcp_output.c29
-rw-r--r--net/ipv4/tcp_timer.c1
-rw-r--r--net/ipv4/udp.c3
-rw-r--r--net/ipv4/xfrm4_output.c20
-rw-r--r--net/ipv4/xfrm4_policy.c82
-rw-r--r--net/ipv4/xfrm4_state.c4
-rw-r--r--net/ipv4/xfrm4_tunnel.c2
-rw-r--r--net/ipv6/README8
-rw-r--r--net/ipv6/addrconf.c117
-rw-r--r--net/ipv6/af_inet6.c32
-rw-r--r--net/ipv6/ah6.c4
-rw-r--r--net/ipv6/anycast.c30
-rw-r--r--net/ipv6/esp6.c4
-rw-r--r--net/ipv6/icmp.c4
-rw-r--r--net/ipv6/ip6_fib.c40
-rw-r--r--net/ipv6/ip6_flowlabel.c11
-rw-r--r--net/ipv6/ip6_input.c34
-rw-r--r--net/ipv6/ip6_output.c23
-rw-r--r--net/ipv6/ip6_tunnel.c5
-rw-r--r--net/ipv6/ipcomp6.c4
-rw-r--r--net/ipv6/ipv6_sockglue.c4
-rw-r--r--net/ipv6/ndisc.c198
-rw-r--r--net/ipv6/netfilter/Kconfig4
-rw-r--r--net/ipv6/netfilter/ip6_queue.c40
-rw-r--r--net/ipv6/netfilter/ip6_tables.c10
-rw-r--r--net/ipv6/proc.c34
-rw-r--r--net/ipv6/raw.c2
-rw-r--r--net/ipv6/route.c83
-rw-r--r--net/ipv6/sit.c4
-rw-r--r--net/ipv6/tcp_ipv6.c139
-rw-r--r--net/ipv6/udp.c2
-rw-r--r--net/ipv6/xfrm6_output.c18
-rw-r--r--net/ipv6/xfrm6_policy.c88
-rw-r--r--net/ipv6/xfrm6_state.c6
-rw-r--r--net/ipv6/xfrm6_tunnel.c2
-rw-r--r--net/ipx/af_ipx.c8
-rw-r--r--net/irda/af_irda.c132
-rw-r--r--net/irda/discovery.c10
-rw-r--r--net/irda/ircomm/ircomm_core.c48
-rw-r--r--net/irda/ircomm/ircomm_lmp.c39
-rw-r--r--net/irda/ircomm/ircomm_param.c50
-rw-r--r--net/irda/ircomm/ircomm_ttp.c42
-rw-r--r--net/irda/ircomm/ircomm_tty.c100
-rw-r--r--net/irda/ircomm/ircomm_tty_attach.c63
-rw-r--r--net/irda/ircomm/ircomm_tty_ioctl.c6
-rw-r--r--net/irda/irda_device.c36
-rw-r--r--net/irda/iriap.c109
-rw-r--r--net/irda/iriap_event.c56
-rw-r--r--net/irda/irias_object.c98
-rw-r--r--net/irda/irlan/irlan_client.c72
-rw-r--r--net/irda/irlan/irlan_client_event.c37
-rw-r--r--net/irda/irlan/irlan_common.c80
-rw-r--r--net/irda/irlan/irlan_eth.c16
-rw-r--r--net/irda/irlan/irlan_event.c8
-rw-r--r--net/irda/irlan/irlan_filter.c8
-rw-r--r--net/irda/irlan/irlan_provider.c42
-rw-r--r--net/irda/irlan/irlan_provider_event.c12
-rw-r--r--net/irda/irlap.c137
-rw-r--r--net/irda/irlap_event.c99
-rw-r--r--net/irda/irlap_frame.c79
-rw-r--r--net/irda/irlmp.c187
-rw-r--r--net/irda/irlmp_event.c88
-rw-r--r--net/irda/irlmp_frame.c38
-rw-r--r--net/irda/irnet/irnet_irda.c2
-rw-r--r--net/irda/irnet/irnet_ppp.c60
-rw-r--r--net/irda/irqueue.c32
-rw-r--r--net/irda/irttp.c150
-rw-r--r--net/irda/parameters.c50
-rw-r--r--net/irda/qos.c48
-rw-r--r--net/irda/timer.c22
-rw-r--r--net/irda/wrapper.c8
-rw-r--r--net/key/af_key.c35
-rw-r--r--net/llc/af_llc.c44
-rw-r--r--net/llc/llc_c_ac.c92
-rw-r--r--net/llc/llc_c_ev.c2
-rw-r--r--net/llc/llc_conn.c50
-rw-r--r--net/llc/llc_if.c4
-rw-r--r--net/llc/llc_proc.c8
-rw-r--r--net/llc/llc_sap.c2
-rw-r--r--net/netlink/Makefile1
-rw-r--r--net/netlink/af_netlink.c85
-rw-r--r--net/netlink/netlink_dev.c278
-rw-r--r--net/netrom/af_netrom.c66
-rw-r--r--net/netrom/nr_in.c19
-rw-r--r--net/netrom/nr_out.c14
-rw-r--r--net/netrom/nr_subr.c10
-rw-r--r--net/netrom/nr_timer.c18
-rw-r--r--net/packet/af_packet.c55
-rw-r--r--net/rose/af_rose.c77
-rw-r--r--net/rose/rose_in.c10
-rw-r--r--net/rose/rose_out.c6
-rw-r--r--net/rose/rose_route.c6
-rw-r--r--net/rose/rose_subr.c12
-rw-r--r--net/rose/rose_timer.c14
-rw-r--r--net/rxrpc/krxiod.c2
-rw-r--r--net/rxrpc/krxsecd.c2
-rw-r--r--net/rxrpc/krxtimod.c2
-rw-r--r--net/rxrpc/main.c12
-rw-r--r--net/sched/Kconfig74
-rw-r--r--net/sched/Makefile6
-rw-r--r--net/sched/act_api.c19
-rw-r--r--net/sched/cls_api.c2
-rw-r--r--net/sched/cls_basic.c303
-rw-r--r--net/sched/cls_u32.c8
-rw-r--r--net/sched/em_cmp.c101
-rw-r--r--net/sched/em_meta.c661
-rw-r--r--net/sched/em_nbyte.c82
-rw-r--r--net/sched/em_u32.c63
-rw-r--r--net/sched/ematch.c524
-rw-r--r--net/sched/ipt.c2
-rw-r--r--net/sched/sch_atm.c2
-rw-r--r--net/sctp/endpointola.c2
-rw-r--r--net/sctp/input.c22
-rw-r--r--net/sctp/ipv6.c2
-rw-r--r--net/sctp/protocol.c2
-rw-r--r--net/sctp/sm_statefuns.c2
-rw-r--r--net/sctp/transport.c4
-rw-r--r--net/socket.c5
-rw-r--r--net/sunrpc/auth.c185
-rw-r--r--net/sunrpc/auth_gss/auth_gss.c584
-rw-r--r--net/sunrpc/auth_gss/gss_krb5_mech.c105
-rw-r--r--net/sunrpc/auth_gss/gss_mech_switch.c8
-rw-r--r--net/sunrpc/auth_gss/gss_spkm3_mech.c131
-rw-r--r--net/sunrpc/auth_gss/svcauth_gss.c28
-rw-r--r--net/sunrpc/auth_null.c59
-rw-r--r--net/sunrpc/auth_unix.c74
-rw-r--r--net/sunrpc/cache.c4
-rw-r--r--net/sunrpc/clnt.c43
-rw-r--r--net/sunrpc/pmap_clnt.c5
-rw-r--r--net/sunrpc/sched.c7
-rw-r--r--net/sunrpc/sunrpc_syms.c1
-rw-r--r--net/sunrpc/svc.c17
-rw-r--r--net/sunrpc/svcauth.c13
-rw-r--r--net/sunrpc/svcauth_unix.c20
-rw-r--r--net/sunrpc/svcsock.c1
-rw-r--r--net/sunrpc/xprt.c8
-rw-r--r--net/unix/af_unix.c30
-rw-r--r--net/wanrouter/af_wanpipe.c34
-rw-r--r--net/x25/af_x25.c54
-rw-r--r--net/x25/x25_facilities.c2
-rw-r--r--net/x25/x25_in.c10
-rw-r--r--net/x25/x25_out.c8
-rw-r--r--net/x25/x25_proc.c2
-rw-r--r--net/x25/x25_subr.c14
-rw-r--r--net/x25/x25_timer.c14
-rw-r--r--net/xfrm/xfrm_policy.c122
-rw-r--r--net/xfrm/xfrm_state.c32
-rw-r--r--scripts/Makefile.lib28
-rw-r--r--scripts/Makefile.modinst5
-rw-r--r--scripts/checkstack.pl14
-rw-r--r--scripts/genksyms/genksyms.h16
-rw-r--r--scripts/kconfig/Makefile8
-rw-r--r--scripts/kconfig/gconf.c41
-rw-r--r--scripts/kconfig/gconf.glade40
-rwxr-xr-xscripts/kernel-doc78
-rw-r--r--scripts/lxdialog/checklist.c2
-rw-r--r--scripts/lxdialog/colors.h6
-rw-r--r--scripts/lxdialog/lxdialog.c8
-rw-r--r--scripts/lxdialog/menubox.c4
-rw-r--r--scripts/mod/file2alias.c23
-rw-r--r--scripts/mod/modpost.c5
-rw-r--r--scripts/mod/modpost.h4
-rw-r--r--scripts/mod/sumversion.c4
-rw-r--r--scripts/namespace.pl5
-rw-r--r--scripts/show_delta129
-rw-r--r--security/dummy.c7
-rw-r--r--security/keys/compat.c2
-rw-r--r--security/keys/key.c3
-rw-r--r--security/keys/keyctl.c2
-rw-r--r--security/keys/process_keys.c175
-rw-r--r--security/keys/request_key.c46
-rw-r--r--security/seclvl.c6
-rw-r--r--security/selinux/Kconfig28
-rw-r--r--security/selinux/avc.c174
-rw-r--r--security/selinux/hooks.c145
-rw-r--r--security/selinux/include/av_perm_to_string.h2
-rw-r--r--security/selinux/include/av_permissions.h2
-rw-r--r--security/selinux/include/avc.h7
-rw-r--r--security/selinux/include/avc_ss.h13
-rw-r--r--security/selinux/include/objsec.h2
-rw-r--r--security/selinux/include/security.h13
-rw-r--r--security/selinux/selinuxfs.c64
-rw-r--r--security/selinux/ss/Makefile4
-rw-r--r--security/selinux/ss/avtab.c29
-rw-r--r--security/selinux/ss/avtab.h6
-rw-r--r--security/selinux/ss/conditional.c6
-rw-r--r--security/selinux/ss/constraint.h7
-rw-r--r--security/selinux/ss/context.h30
-rw-r--r--security/selinux/ss/ebitmap.c43
-rw-r--r--security/selinux/ss/ebitmap.h1
-rw-r--r--security/selinux/ss/hashtab.c113
-rw-r--r--security/selinux/ss/hashtab.h38
-rw-r--r--security/selinux/ss/mls.c726
-rw-r--r--security/selinux/ss/mls.h79
-rw-r--r--security/selinux/ss/mls_types.h72
-rw-r--r--security/selinux/ss/policydb.c587
-rw-r--r--security/selinux/ss/policydb.h61
-rw-r--r--security/selinux/ss/services.c264
-rw-r--r--security/selinux/ss/services.h6
-rw-r--r--security/selinux/ss/sidtab.c36
-rw-r--r--sound/arm/sa11xx-uda1341.c8
-rw-r--r--sound/core/Kconfig24
-rw-r--r--sound/core/Makefile1
-rw-r--r--sound/core/control.c211
-rw-r--r--sound/core/control_compat.c412
-rw-r--r--sound/core/hwdep.c27
-rw-r--r--sound/core/hwdep_compat.c (renamed from sound/core/ioctl32/hwdep32.c)66
-rw-r--r--sound/core/info.c9
-rw-r--r--sound/core/init.c163
-rw-r--r--sound/core/ioctl32/Makefile11
-rw-r--r--sound/core/ioctl32/ioctl32.c433
-rw-r--r--sound/core/ioctl32/ioctl32.h102
-rw-r--r--sound/core/ioctl32/pcm32.c464
-rw-r--r--sound/core/ioctl32/rawmidi32.c91
-rw-r--r--sound/core/ioctl32/seq32.c116
-rw-r--r--sound/core/ioctl32/timer32.c105
-rw-r--r--sound/core/memory.c4
-rw-r--r--sound/core/misc.c8
-rw-r--r--sound/core/oss/mixer_oss.c63
-rw-r--r--sound/core/oss/pcm_oss.c51
-rw-r--r--sound/core/pcm.c38
-rw-r--r--sound/core/pcm_compat.c513
-rw-r--r--sound/core/pcm_lib.c19
-rw-r--r--sound/core/pcm_memory.c2
-rw-r--r--sound/core/pcm_native.c102
-rw-r--r--sound/core/rawmidi.c244
-rw-r--r--sound/core/rawmidi_compat.c120
-rw-r--r--sound/core/rtctimer.c2
-rw-r--r--sound/core/seq/oss/seq_oss.c21
-rw-r--r--sound/core/seq/oss/seq_oss_init.c46
-rw-r--r--sound/core/seq/oss/seq_oss_midi.c39
-rw-r--r--sound/core/seq/oss/seq_oss_readq.c5
-rw-r--r--sound/core/seq/oss/seq_oss_synth.c2
-rw-r--r--sound/core/seq/oss/seq_oss_writeq.c24
-rw-r--r--sound/core/seq/seq_clientmgr.c32
-rw-r--r--sound/core/seq/seq_compat.c137
-rw-r--r--sound/core/seq/seq_dummy.c1
-rw-r--r--sound/core/seq/seq_instr.c6
-rw-r--r--sound/core/seq/seq_memory.c8
-rw-r--r--sound/core/seq/seq_midi.c96
-rw-r--r--sound/core/seq/seq_midi_emul.c12
-rw-r--r--sound/core/seq/seq_midi_event.c12
-rw-r--r--sound/core/seq/seq_queue.c34
-rw-r--r--sound/core/seq/seq_queue.h2
-rw-r--r--sound/core/seq/seq_system.c62
-rw-r--r--sound/core/seq/seq_virmidi.c54
-rw-r--r--sound/core/sound.c9
-rw-r--r--sound/core/timer.c97
-rw-r--r--sound/core/timer_compat.c119
-rw-r--r--sound/drivers/mpu401/mpu401.c252
-rw-r--r--sound/drivers/mpu401/mpu401_uart.c39
-rw-r--r--sound/drivers/mtpav.c7
-rw-r--r--sound/drivers/serial-u16550.c23
-rw-r--r--sound/drivers/vx/vx_core.c17
-rw-r--r--sound/drivers/vx/vx_hwdep.c1
-rw-r--r--sound/i2c/other/Makefile2
-rw-r--r--sound/i2c/other/ak4114.c580
-rw-r--r--sound/i2c/other/ak4xxx-adda.c166
-rw-r--r--sound/i2c/other/tea575x-tuner.c5
-rw-r--r--sound/isa/Kconfig41
-rw-r--r--sound/isa/ad1848/ad1848_lib.c4
-rw-r--r--sound/isa/als100.c2
-rw-r--r--sound/isa/cs423x/cs4231_lib.c4
-rw-r--r--sound/isa/es18xx.c4
-rw-r--r--sound/isa/gus/gus_lfo.c429
-rw-r--r--sound/isa/gus/gus_pcm.c15
-rw-r--r--sound/isa/gus/gus_reset.c7
-rw-r--r--sound/isa/gus/gus_synth.c21
-rw-r--r--sound/isa/gus/interwave.c2
-rw-r--r--sound/isa/opl3sa2.c6
-rw-r--r--sound/isa/sb/emu8000.c4
-rw-r--r--sound/isa/sb/emu8000_patch.c4
-rw-r--r--sound/isa/sb/sb8_midi.c8
-rw-r--r--sound/isa/wavefront/wavefront_midi.c8
-rw-r--r--sound/isa/wavefront/wavefront_synth.c138
-rw-r--r--sound/oss/ac97_codec.c81
-rw-r--r--sound/oss/aedsp16.c10
-rw-r--r--sound/oss/ali5455.c2
-rw-r--r--sound/oss/btaudio.c6
-rw-r--r--sound/oss/cmpci.c102
-rw-r--r--sound/oss/cs4281/cs4281_wrapper-24.c2
-rw-r--r--sound/oss/cs4281/cs4281m.c2
-rw-r--r--sound/oss/cs46xx.c4
-rw-r--r--sound/oss/cs46xxpm-24.h2
-rw-r--r--sound/oss/dmasound/dac3550a.c4
-rw-r--r--sound/oss/dmasound/dmasound_awacs.c9
-rw-r--r--sound/oss/es1370.c36
-rw-r--r--sound/oss/es1371.c52
-rw-r--r--sound/oss/esssolo1.c51
-rw-r--r--sound/oss/gus_wave.c3
-rw-r--r--sound/oss/harmony.c2
-rw-r--r--sound/oss/i810_audio.c2
-rw-r--r--sound/oss/mad16.c47
-rw-r--r--sound/oss/maestro3.c6
-rw-r--r--sound/oss/maestro_tables.h333
-rw-r--r--sound/oss/nm256_audio.c2
-rw-r--r--sound/oss/opl3sa2.c2
-rw-r--r--sound/oss/pss.c2
-rw-r--r--sound/oss/sb_card.c4
-rw-r--r--sound/oss/sonicvibes.c53
-rw-r--r--sound/oss/soundcard.c10
-rw-r--r--sound/oss/sscape.c2
-rw-r--r--sound/oss/trident.c51
-rw-r--r--sound/oss/wavfront.c56
-rw-r--r--sound/oss/ymfpci.c2
-rw-r--r--sound/parisc/Kconfig2
-rw-r--r--sound/parisc/harmony.c1598
-rw-r--r--sound/parisc/harmony.h151
-rw-r--r--sound/pci/Kconfig12
-rw-r--r--sound/pci/Makefile1
-rw-r--r--sound/pci/ac97/ac97_codec.c424
-rw-r--r--sound/pci/ac97/ac97_local.h22
-rw-r--r--sound/pci/ac97/ac97_patch.c177
-rw-r--r--sound/pci/ac97/ac97_patch.h1
-rw-r--r--sound/pci/ac97/ac97_pcm.c6
-rw-r--r--sound/pci/ali5451/ali5451.c8
-rw-r--r--sound/pci/als4000.c111
-rw-r--r--sound/pci/atiixp.c24
-rw-r--r--sound/pci/atiixp_modem.c29
-rw-r--r--sound/pci/au88x0/au88x0.c7
-rw-r--r--sound/pci/au88x0/au88x0.h2
-rw-r--r--sound/pci/au88x0/au88x0_core.c5
-rw-r--r--sound/pci/au88x0/au88x0_game.c54
-rw-r--r--sound/pci/au88x0/au88x0_mixer.c1
-rw-r--r--sound/pci/au88x0/au88x0_pcm.c106
-rw-r--r--sound/pci/azt3328.c111
-rw-r--r--sound/pci/bt87x.c2
-rw-r--r--sound/pci/ca0106/ca0106_main.c23
-rw-r--r--sound/pci/cmipci.c188
-rw-r--r--sound/pci/cs4281.c99
-rw-r--r--sound/pci/cs46xx/cs46xx_lib.c87
-rw-r--r--sound/pci/emu10k1/Makefile2
-rw-r--r--sound/pci/emu10k1/emu10k1.c42
-rw-r--r--sound/pci/emu10k1/emu10k1_callback.c2
-rw-r--r--sound/pci/emu10k1/emu10k1_main.c182
-rw-r--r--sound/pci/emu10k1/emu10k1x.c3
-rw-r--r--sound/pci/emu10k1/emufx.c266
-rw-r--r--sound/pci/emu10k1/emumixer.c337
-rw-r--r--sound/pci/emu10k1/emumpu401.c2
-rw-r--r--sound/pci/emu10k1/emupcm.c454
-rw-r--r--sound/pci/emu10k1/emuproc.c111
-rw-r--r--sound/pci/emu10k1/io.c89
-rw-r--r--sound/pci/emu10k1/irq.c34
-rw-r--r--sound/pci/emu10k1/p16v.c736
-rw-r--r--sound/pci/emu10k1/p16v.h299
-rw-r--r--sound/pci/emu10k1/timer.c4
-rw-r--r--sound/pci/emu10k1/voice.c83
-rw-r--r--sound/pci/ens1370.c124
-rw-r--r--sound/pci/es1938.c56
-rw-r--r--sound/pci/es1968.c100
-rw-r--r--sound/pci/fm801.c2
-rw-r--r--sound/pci/hda/Makefile7
-rw-r--r--sound/pci/hda/hda_codec.c1856
-rw-r--r--sound/pci/hda/hda_codec.h604
-rw-r--r--sound/pci/hda/hda_generic.c906
-rw-r--r--sound/pci/hda/hda_intel.c1449
-rw-r--r--sound/pci/hda/hda_local.h161
-rw-r--r--sound/pci/hda/hda_patch.h17
-rw-r--r--sound/pci/hda/hda_proc.c298
-rw-r--r--sound/pci/hda/patch_analog.c445
-rw-r--r--sound/pci/hda/patch_cmedia.c621
-rw-r--r--sound/pci/hda/patch_realtek.c1503
-rw-r--r--sound/pci/ice1712/Makefile2
-rw-r--r--sound/pci/ice1712/ak4xxx.c12
-rw-r--r--sound/pci/ice1712/envy24ht.h2
-rw-r--r--sound/pci/ice1712/ice1712.c32
-rw-r--r--sound/pci/ice1712/ice1712.h12
-rw-r--r--sound/pci/ice1712/ice1724.c78
-rw-r--r--sound/pci/ice1712/juli.c230
-rw-r--r--sound/pci/ice1712/juli.h10
-rw-r--r--sound/pci/ice1712/phase.c138
-rw-r--r--sound/pci/ice1712/phase.h34
-rw-r--r--sound/pci/ice1712/prodigy192.c4
-rw-r--r--sound/pci/ice1712/revo.c24
-rw-r--r--sound/pci/ice1712/vt1720_mobo.c9
-rw-r--r--sound/pci/ice1712/vt1720_mobo.h4
-rw-r--r--sound/pci/intel8x0.c39
-rw-r--r--sound/pci/intel8x0m.c86
-rw-r--r--sound/pci/korg1212/korg1212.c87
-rw-r--r--sound/pci/maestro3.c13
-rw-r--r--sound/pci/mixart/mixart.c6
-rw-r--r--sound/pci/mixart/mixart.h2
-rw-r--r--sound/pci/mixart/mixart_hwdep.c91
-rw-r--r--sound/pci/nm256/nm256.c4
-rw-r--r--sound/pci/rme32.c5
-rw-r--r--sound/pci/rme9652/hdsp.c521
-rw-r--r--sound/pci/sonicvibes.c55
-rw-r--r--sound/pci/trident/trident.c2
-rw-r--r--sound/pci/trident/trident_main.c93
-rw-r--r--sound/pci/trident/trident_synth.c4
-rw-r--r--sound/pci/via82xx.c162
-rw-r--r--sound/pci/via82xx_modem.c17
-rw-r--r--sound/pci/vx222/vx222_ops.c1
-rw-r--r--sound/pci/ymfpci/ymfpci.c150
-rw-r--r--sound/pci/ymfpci/ymfpci_main.c13
-rw-r--r--sound/pcmcia/pdaudiocf/pdaudiocf.c16
-rw-r--r--sound/pcmcia/pdaudiocf/pdaudiocf.h4
-rw-r--r--sound/pcmcia/pdaudiocf/pdaudiocf_core.c4
-rw-r--r--sound/pcmcia/vx/vx_entry.c4
-rw-r--r--sound/pcmcia/vx/vxp_ops.c1
-rw-r--r--sound/ppc/keywest.c2
-rw-r--r--sound/ppc/pmac.c12
-rw-r--r--sound/usb/usbaudio.c51
-rw-r--r--sound/usb/usbaudio.h16
-rw-r--r--sound/usb/usbmidi.c654
-rw-r--r--sound/usb/usbmixer.c6
-rw-r--r--sound/usb/usbquirks.h250
-rw-r--r--sound/usb/usx2y/usX2Yhwdep.c2
-rw-r--r--sound/usb/usx2y/usbusx2yaudio.c1
4183 files changed, 228178 insertions, 133388 deletions
diff --git a/CREDITS b/CREDITS
index 17b8807b93578..671e9c2d31fea 100644
--- a/CREDITS
+++ b/CREDITS
@@ -34,8 +34,9 @@ N: Dave Airlie
E: airlied@linux.ie
W: http://www.csn.ul.ie/~airlied
D: NFS over TCP patches
-S: University of Limerick
-S: Ireland
+D: in-kernel DRM Maintainer
+S: Longford, Ireland
+S: Sydney, Australia
N: Tigran A. Aivazian
E: tigran@veritas.com
@@ -328,8 +329,6 @@ S: Brimson, MN 55602
S: USA
N: Hennus Bergman
-E: hennus@cybercomm.nl
-W: http://www.cybercomm.nl/~hennus/
P: 1024/77D50909 76 99 FD 31 91 E1 96 1C 90 BB 22 80 62 F6 BD 63
D: Author and maintainer of the QIC-02 tape driver
S: The Netherlands
@@ -805,6 +804,21 @@ S: One Dell Way
S: Round Rock, TX 78682
S: USA
+N: Ben Dooks
+E: ben-linux@fluff.org
+E: ben@simtec.co.uk
+W: http://www.fluff.org/ben/
+W: http://www.simtec.co.uk/
+D: Samsung S3C2410/S3C2440 support, general ARM support
+D: Maintaining Simtec Electronics development boards
+S: Simtec Electronics
+S: Avondale Drive
+S: Tarleton
+S: Preston
+S: Lancs
+S: PR4 6AX
+S: United Kingdom
+
N: John G Dorsey
E: john+@cs.cmu.edu
D: ARM Linux ports to Assabet/Neponset, Spot
@@ -826,6 +840,11 @@ E: cort@fsmlabs.com
W: http://www.fsmlabs.com/linuxppcbk.html
D: PowerPC
+N: Daniel Drake
+E: dsd@gentoo.org
+D: USBAT02 CompactFlash support in usb-storage
+S: UK
+
N: Oleg Drokin
E: green@ccssu.crimea.ua
W: http://www.ccssu.crimea.ua/~green
@@ -1080,7 +1099,7 @@ S: Brazil
N: Kumar Gala
E: kumar.gala@freescale.com
-D: Embedded PowerPC 6xx/7xx/74xx/82xx/85xx support
+D: Embedded PowerPC 6xx/7xx/74xx/82xx/83xx/85xx support
S: Austin, Texas 78729
S: USA
@@ -3336,10 +3355,11 @@ S: Santa Clara, CA 95054
S: USA
N: Matthias Urlichs
-E: urlichs@noris.de
-E: urlichs@smurf.sub.org
+E: smurf@smurf.noris.de
+E: smurf@debian.org
+E: matthias@urlichs.de
D: Consultant, developer, kernel hacker
-D: Playing with Streams, ISDN, and BSD networking code for Linux
+D: In a previous life, worked on Streams/ISDN/BSD networking code for Linux
S: Schleiermacherstrasse 12
S: 90491 Nuernberg
S: Germany
@@ -3411,6 +3431,7 @@ N: Jeroen Vreeken
E: pe1rxq@amsat.org
W: http://www.chello.nl/~j.vreeken/
D: SE401 usb webcam driver
+D: ZD1201 usb wireless lan driver
S: Maastrichterweg 63
S: 5554 GG Valkenswaard
S: The Netherlands
diff --git a/Documentation/BK-usage/bksend b/Documentation/BK-usage/bksend
index dbeeefa8e241e..836ca943694f4 100755
--- a/Documentation/BK-usage/bksend
+++ b/Documentation/BK-usage/bksend
@@ -27,7 +27,7 @@ echo "'| bk receive [path to repository]' or apply the patch as usual."
SEP="\n===================================================================\n\n"
echo -e $SEP
-bk changes -r$REV
+env PAGER=/bin/cat bk changes -r$REV
echo
bk export -tpatch -du -h -r$REV | diffstat
echo; echo
diff --git a/Documentation/Changes b/Documentation/Changes
index c056d65b1a30d..caa6a5529b6b8 100644
--- a/Documentation/Changes
+++ b/Documentation/Changes
@@ -339,7 +339,7 @@ o <http://prdownloads.sourceforge.net/e2fsprogs/e2fsprogs-1.29.tar.gz>
JFSutils
--------
-o <http://oss.software.ibm.com/jfs>
+o <http://jfs.sourceforge.net/>
Reiserfsprogs
-------------
diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile
index fc50b10731543..a221039ee4c97 100644
--- a/Documentation/DocBook/Makefile
+++ b/Documentation/DocBook/Makefile
@@ -6,38 +6,39 @@
# To add a new book the only step required is to add the book to the
# list of DOCBOOKS.
-DOCBOOKS := wanbook.sgml z8530book.sgml mcabook.sgml videobook.sgml \
- kernel-hacking.sgml kernel-locking.sgml via-audio.sgml \
- deviceiobook.sgml procfs-guide.sgml tulip-user.sgml \
- writing_usb_driver.sgml scsidrivers.sgml sis900.sgml \
- kernel-api.sgml journal-api.sgml lsm.sgml usb.sgml \
- gadget.sgml libata.sgml mtdnand.sgml librs.sgml
+DOCBOOKS := wanbook.xml z8530book.xml mcabook.xml videobook.xml \
+ kernel-hacking.xml kernel-locking.xml via-audio.xml \
+ deviceiobook.xml procfs-guide.xml tulip-user.xml \
+ writing_usb_driver.xml scsidrivers.xml sis900.xml \
+ kernel-api.xml journal-api.xml lsm.xml usb.xml \
+ gadget.xml libata.xml mtdnand.xml librs.xml
###
# The build process is as follows (targets):
-# (sgmldocs)
-# file.tmpl --> file.sgml +--> file.ps (psdocs)
-# +--> file.pdf (pdfdocs)
-# +--> DIR=file (htmldocs)
-# +--> man/ (mandocs)
+# (xmldocs)
+# file.tmpl --> file.xml +--> file.ps (psdocs)
+# +--> file.pdf (pdfdocs)
+# +--> DIR=file (htmldocs)
+# +--> man/ (mandocs)
###
# The targets that may be used.
-.PHONY: sgmldocs psdocs pdfdocs htmldocs mandocs installmandocs
+.PHONY: xmldocs sgmldocs psdocs pdfdocs htmldocs mandocs installmandocs
BOOKS := $(addprefix $(obj)/,$(DOCBOOKS))
-sgmldocs: $(BOOKS)
+xmldocs: $(BOOKS)
+sgmldocs: xmldocs
-PS := $(patsubst %.sgml, %.ps, $(BOOKS))
+PS := $(patsubst %.xml, %.ps, $(BOOKS))
psdocs: $(PS)
-PDF := $(patsubst %.sgml, %.pdf, $(BOOKS))
+PDF := $(patsubst %.xml, %.pdf, $(BOOKS))
pdfdocs: $(PDF)
-HTML := $(patsubst %.sgml, %.html, $(BOOKS))
+HTML := $(patsubst %.xml, %.html, $(BOOKS))
htmldocs: $(HTML)
-MAN := $(patsubst %.sgml, %.9, $(BOOKS))
+MAN := $(patsubst %.xml, %.9, $(BOOKS))
mandocs: $(MAN)
installmandocs: mandocs
@@ -55,7 +56,7 @@ MAKEMAN = $(PERL) $(srctree)/scripts/makeman
# 1) To generate a dependency list for a .tmpl file
# 2) To preprocess a .tmpl file and call kernel-doc with
# appropriate parameters.
-# The following rules are used to generate the .sgml documentation
+# The following rules are used to generate the .xml documentation
# required to generate the final targets. (ps, pdf, html).
quiet_cmd_docproc = DOCPROC $@
cmd_docproc = SRCTREE=$(srctree)/ $(DOCPROC) doc $< >$@
@@ -69,7 +70,7 @@ define rule_docproc
) > $(dir $@).$(notdir $@).cmd
endef
-%.sgml: %.tmpl FORCE
+%.xml: %.tmpl FORCE
$(call if_changed_rule,docproc)
###
@@ -87,9 +88,9 @@ $(BOOKS): $(KERNELDOC)
###
# procfs guide uses a .c file as example code.
# This requires an explicit dependency
-C-procfs-example = procfs_example.sgml
+C-procfs-example = procfs_example.xml
C-procfs-example2 = $(addprefix $(obj)/,$(C-procfs-example))
-$(obj)/procfs-guide.sgml: $(C-procfs-example2)
+$(obj)/procfs-guide.xml: $(C-procfs-example2)
###
# Rules to generate postscript, PDF and HTML
@@ -97,7 +98,7 @@ $(obj)/procfs-guide.sgml: $(C-procfs-example2)
quiet_cmd_db2ps = DB2PS $@
cmd_db2ps = db2ps -o $(dir $@) $<
-%.ps : %.sgml
+%.ps : %.xml
@(which db2ps > /dev/null 2>&1) || \
(echo "*** You need to install DocBook stylesheets ***"; \
exit 1)
@@ -105,7 +106,7 @@ quiet_cmd_db2ps = DB2PS $@
quiet_cmd_db2pdf = DB2PDF $@
cmd_db2pdf = db2pdf -o $(dir $@) $<
-%.pdf : %.sgml
+%.pdf : %.xml
@(which db2pdf > /dev/null 2>&1) || \
(echo "*** You need to install DocBook stylesheets ***"; \
exit 1)
@@ -116,7 +117,7 @@ quiet_cmd_db2html = DB2HTML $@
echo '<a HREF="$(patsubst %.html,%,$(notdir $@))/book1.html"> \
Goto $(patsubst %.html,%,$(notdir $@))</a><p>' > $@
-%.html: %.sgml
+%.html: %.xml
@(which db2html > /dev/null 2>&1) || \
(echo "*** You need to install DocBook stylesheets ***"; \
exit 1)
@@ -128,7 +129,7 @@ quiet_cmd_db2html = DB2HTML $@
###
# Rule to generate man files - output is placed in the man subdirectory
-%.9: %.sgml
+%.9: %.xml
ifneq ($(KBUILD_SRC),)
$(Q)mkdir -p $(objtree)/Documentation/DocBook/man
endif
@@ -156,8 +157,8 @@ quiet_cmd_fig2png = FIG2PNG $@
$(call cmd,fig2png)
###
-# Rule to convert a .c file to inline SGML documentation
-%.sgml: %.c
+# Rule to convert a .c file to inline XML documentation
+%.xml: %.c
@echo ' GEN $@'
@( \
echo "<programlisting>"; \
@@ -171,24 +172,24 @@ quiet_cmd_fig2png = FIG2PNG $@
# Help targets as used by the top-level makefile
dochelp:
@echo ' Linux kernel internal documentation in different formats:'
- @echo ' sgmldocs (SGML), psdocs (Postscript), pdfdocs (PDF)'
+ @echo ' xmldocs (XML DocBook), psdocs (Postscript), pdfdocs (PDF)'
@echo ' htmldocs (HTML), mandocs (man pages, use installmandocs to install)'
###
# Temporary files left by various tools
clean-files := $(DOCBOOKS) \
- $(patsubst %.sgml, %.dvi, $(DOCBOOKS)) \
- $(patsubst %.sgml, %.aux, $(DOCBOOKS)) \
- $(patsubst %.sgml, %.tex, $(DOCBOOKS)) \
- $(patsubst %.sgml, %.log, $(DOCBOOKS)) \
- $(patsubst %.sgml, %.out, $(DOCBOOKS)) \
- $(patsubst %.sgml, %.ps, $(DOCBOOKS)) \
- $(patsubst %.sgml, %.pdf, $(DOCBOOKS)) \
- $(patsubst %.sgml, %.html, $(DOCBOOKS)) \
- $(patsubst %.sgml, %.9, $(DOCBOOKS)) \
+ $(patsubst %.xml, %.dvi, $(DOCBOOKS)) \
+ $(patsubst %.xml, %.aux, $(DOCBOOKS)) \
+ $(patsubst %.xml, %.tex, $(DOCBOOKS)) \
+ $(patsubst %.xml, %.log, $(DOCBOOKS)) \
+ $(patsubst %.xml, %.out, $(DOCBOOKS)) \
+ $(patsubst %.xml, %.ps, $(DOCBOOKS)) \
+ $(patsubst %.xml, %.pdf, $(DOCBOOKS)) \
+ $(patsubst %.xml, %.html, $(DOCBOOKS)) \
+ $(patsubst %.xml, %.9, $(DOCBOOKS)) \
$(C-procfs-example)
-clean-dirs := $(patsubst %.sgml,%,$(DOCBOOKS))
+clean-dirs := $(patsubst %.xml,%,$(DOCBOOKS))
#man put files in man subdir - traverse down
subdir- := man/
diff --git a/Documentation/DocBook/deviceiobook.tmpl b/Documentation/DocBook/deviceiobook.tmpl
index 0d1da8cbd7524..6f41f2f5c6f6b 100644
--- a/Documentation/DocBook/deviceiobook.tmpl
+++ b/Documentation/DocBook/deviceiobook.tmpl
@@ -1,4 +1,6 @@
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V3.1//EN"[]>
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
<book id="DoingIO">
<bookinfo>
diff --git a/Documentation/DocBook/gadget.tmpl b/Documentation/DocBook/gadget.tmpl
index 0c28a966c1cee..a34442436128e 100644
--- a/Documentation/DocBook/gadget.tmpl
+++ b/Documentation/DocBook/gadget.tmpl
@@ -1,4 +1,7 @@
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V3.1//EN"[]>
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
+
<book id="USB-Gadget-API">
<bookinfo>
<title>USB Gadget API for Linux</title>
diff --git a/Documentation/DocBook/journal-api.tmpl b/Documentation/DocBook/journal-api.tmpl
index d0472f85da73b..1ef6f43c6d8f6 100644
--- a/Documentation/DocBook/journal-api.tmpl
+++ b/Documentation/DocBook/journal-api.tmpl
@@ -1,4 +1,7 @@
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V3.1//EN"[]>
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
+
<book id="LinuxJBDAPI">
<bookinfo>
<title>The Linux Journalling API</title>
diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl
index c8e2581cea4f2..1bd20c8602855 100644
--- a/Documentation/DocBook/kernel-api.tmpl
+++ b/Documentation/DocBook/kernel-api.tmpl
@@ -1,4 +1,7 @@
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V3.1//EN"[]>
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
+
<book id="LinuxKernelAPI">
<bookinfo>
<title>The Linux Kernel API</title>
@@ -97,6 +100,14 @@ KAO -->
</sect1>
</chapter>
+ <chapter id="kfifo">
+ <title>FIFO Buffer</title>
+ <sect1><title>kfifo interface</title>
+!Iinclude/linux/kfifo.h
+!Ekernel/kfifo.c
+ </sect1>
+ </chapter>
+
<chapter id="proc">
<title>The proc filesystem</title>
diff --git a/Documentation/DocBook/kernel-hacking.tmpl b/Documentation/DocBook/kernel-hacking.tmpl
index 1e8219d852555..49a9ef82d575f 100644
--- a/Documentation/DocBook/kernel-hacking.tmpl
+++ b/Documentation/DocBook/kernel-hacking.tmpl
@@ -1,4 +1,6 @@
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V3.1//EN"[]>
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
<book id="lk-hacking-guide">
<bookinfo>
diff --git a/Documentation/DocBook/kernel-locking.tmpl b/Documentation/DocBook/kernel-locking.tmpl
index 4fd97de055ca8..90dc2de8e0afd 100644
--- a/Documentation/DocBook/kernel-locking.tmpl
+++ b/Documentation/DocBook/kernel-locking.tmpl
@@ -1,4 +1,6 @@
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V3.1//EN"[]>
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
<book id="LKLockingGuide">
<bookinfo>
@@ -236,12 +238,12 @@
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
+ simply can't sleep (see <xref linkend="sleeping-things"/>), and so
have to use a spinlock instead.
</para>
<para>
Neither type of lock is recursive: see
- <xref linkend="deadlock">.
+ <xref linkend="deadlock"/>.
</para>
</sect1>
@@ -326,7 +328,7 @@
<para>
Note that you can also use <function>spin_lock_irq()</function>
or <function>spin_lock_irqsave()</function> here, which stop
- hardware interrupts as well: see <xref linkend="hardirq-context">.
+ hardware interrupts as well: see <xref linkend="hardirq-context"/>.
</para>
<para>
@@ -403,7 +405,7 @@
<para>
The same softirq can run on the other CPUs: you can use a
- per-CPU array (see <xref linkend="per-cpu">) for better
+ per-CPU array (see <xref linkend="per-cpu"/>) for better
performance. If you're going so far as to use a softirq,
you probably care about scalable performance enough
to justify the extra complexity.
@@ -545,120 +547,120 @@
</para>
<table>
<title>Table of Locking Requirements</title>
-<TGROUP COLS="11">
-<TBODY>
-<ROW>
-<ENTRY></ENTRY>
-<ENTRY>IRQ Handler A</ENTRY>
-<ENTRY>IRQ Handler B</ENTRY>
-<ENTRY>Softirq A</ENTRY>
-<ENTRY>Softirq B</ENTRY>
-<ENTRY>Tasklet A</ENTRY>
-<ENTRY>Tasklet B</ENTRY>
-<ENTRY>Timer A</ENTRY>
-<ENTRY>Timer B</ENTRY>
-<ENTRY>User Context A</ENTRY>
-<ENTRY>User Context B</ENTRY>
-</ROW>
-
-<ROW>
-<ENTRY>IRQ Handler A</ENTRY>
-<ENTRY>None</ENTRY>
-</ROW>
-
-<ROW>
-<ENTRY>IRQ Handler B</ENTRY>
-<ENTRY>spin_lock_irqsave</ENTRY>
-<ENTRY>None</ENTRY>
-</ROW>
-
-<ROW>
-<ENTRY>Softirq A</ENTRY>
-<ENTRY>spin_lock_irq</ENTRY>
-<ENTRY>spin_lock_irq</ENTRY>
-<ENTRY>spin_lock</ENTRY>
-</ROW>
-
-<ROW>
-<ENTRY>Softirq B</ENTRY>
-<ENTRY>spin_lock_irq</ENTRY>
-<ENTRY>spin_lock_irq</ENTRY>
-<ENTRY>spin_lock</ENTRY>
-<ENTRY>spin_lock</ENTRY>
-</ROW>
-
-<ROW>
-<ENTRY>Tasklet A</ENTRY>
-<ENTRY>spin_lock_irq</ENTRY>
-<ENTRY>spin_lock_irq</ENTRY>
-<ENTRY>spin_lock</ENTRY>
-<ENTRY>spin_lock</ENTRY>
-<ENTRY>None</ENTRY>
-</ROW>
-
-<ROW>
-<ENTRY>Tasklet B</ENTRY>
-<ENTRY>spin_lock_irq</ENTRY>
-<ENTRY>spin_lock_irq</ENTRY>
-<ENTRY>spin_lock</ENTRY>
-<ENTRY>spin_lock</ENTRY>
-<ENTRY>spin_lock</ENTRY>
-<ENTRY>None</ENTRY>
-</ROW>
-
-<ROW>
-<ENTRY>Timer A</ENTRY>
-<ENTRY>spin_lock_irq</ENTRY>
-<ENTRY>spin_lock_irq</ENTRY>
-<ENTRY>spin_lock</ENTRY>
-<ENTRY>spin_lock</ENTRY>
-<ENTRY>spin_lock</ENTRY>
-<ENTRY>spin_lock</ENTRY>
-<ENTRY>None</ENTRY>
-</ROW>
-
-<ROW>
-<ENTRY>Timer B</ENTRY>
-<ENTRY>spin_lock_irq</ENTRY>
-<ENTRY>spin_lock_irq</ENTRY>
-<ENTRY>spin_lock</ENTRY>
-<ENTRY>spin_lock</ENTRY>
-<ENTRY>spin_lock</ENTRY>
-<ENTRY>spin_lock</ENTRY>
-<ENTRY>spin_lock</ENTRY>
-<ENTRY>None</ENTRY>
-</ROW>
-
-<ROW>
-<ENTRY>User Context A</ENTRY>
-<ENTRY>spin_lock_irq</ENTRY>
-<ENTRY>spin_lock_irq</ENTRY>
-<ENTRY>spin_lock_bh</ENTRY>
-<ENTRY>spin_lock_bh</ENTRY>
-<ENTRY>spin_lock_bh</ENTRY>
-<ENTRY>spin_lock_bh</ENTRY>
-<ENTRY>spin_lock_bh</ENTRY>
-<ENTRY>spin_lock_bh</ENTRY>
-<ENTRY>None</ENTRY>
-</ROW>
-
-<ROW>
-<ENTRY>User Context B</ENTRY>
-<ENTRY>spin_lock_irq</ENTRY>
-<ENTRY>spin_lock_irq</ENTRY>
-<ENTRY>spin_lock_bh</ENTRY>
-<ENTRY>spin_lock_bh</ENTRY>
-<ENTRY>spin_lock_bh</ENTRY>
-<ENTRY>spin_lock_bh</ENTRY>
-<ENTRY>spin_lock_bh</ENTRY>
-<ENTRY>spin_lock_bh</ENTRY>
-<ENTRY>down_interruptible</ENTRY>
-<ENTRY>None</ENTRY>
-</ROW>
-
-</TBODY>
-</TGROUP>
-</TABLE>
+<tgroup cols="11">
+<tbody>
+<row>
+<entry></entry>
+<entry>IRQ Handler A</entry>
+<entry>IRQ Handler B</entry>
+<entry>Softirq A</entry>
+<entry>Softirq B</entry>
+<entry>Tasklet A</entry>
+<entry>Tasklet B</entry>
+<entry>Timer A</entry>
+<entry>Timer B</entry>
+<entry>User Context A</entry>
+<entry>User Context B</entry>
+</row>
+
+<row>
+<entry>IRQ Handler A</entry>
+<entry>None</entry>
+</row>
+
+<row>
+<entry>IRQ Handler B</entry>
+<entry>spin_lock_irqsave</entry>
+<entry>None</entry>
+</row>
+
+<row>
+<entry>Softirq A</entry>
+<entry>spin_lock_irq</entry>
+<entry>spin_lock_irq</entry>
+<entry>spin_lock</entry>
+</row>
+
+<row>
+<entry>Softirq B</entry>
+<entry>spin_lock_irq</entry>
+<entry>spin_lock_irq</entry>
+<entry>spin_lock</entry>
+<entry>spin_lock</entry>
+</row>
+
+<row>
+<entry>Tasklet A</entry>
+<entry>spin_lock_irq</entry>
+<entry>spin_lock_irq</entry>
+<entry>spin_lock</entry>
+<entry>spin_lock</entry>
+<entry>None</entry>
+</row>
+
+<row>
+<entry>Tasklet B</entry>
+<entry>spin_lock_irq</entry>
+<entry>spin_lock_irq</entry>
+<entry>spin_lock</entry>
+<entry>spin_lock</entry>
+<entry>spin_lock</entry>
+<entry>None</entry>
+</row>
+
+<row>
+<entry>Timer A</entry>
+<entry>spin_lock_irq</entry>
+<entry>spin_lock_irq</entry>
+<entry>spin_lock</entry>
+<entry>spin_lock</entry>
+<entry>spin_lock</entry>
+<entry>spin_lock</entry>
+<entry>None</entry>
+</row>
+
+<row>
+<entry>Timer B</entry>
+<entry>spin_lock_irq</entry>
+<entry>spin_lock_irq</entry>
+<entry>spin_lock</entry>
+<entry>spin_lock</entry>
+<entry>spin_lock</entry>
+<entry>spin_lock</entry>
+<entry>spin_lock</entry>
+<entry>None</entry>
+</row>
+
+<row>
+<entry>User Context A</entry>
+<entry>spin_lock_irq</entry>
+<entry>spin_lock_irq</entry>
+<entry>spin_lock_bh</entry>
+<entry>spin_lock_bh</entry>
+<entry>spin_lock_bh</entry>
+<entry>spin_lock_bh</entry>
+<entry>spin_lock_bh</entry>
+<entry>spin_lock_bh</entry>
+<entry>None</entry>
+</row>
+
+<row>
+<entry>User Context B</entry>
+<entry>spin_lock_irq</entry>
+<entry>spin_lock_irq</entry>
+<entry>spin_lock_bh</entry>
+<entry>spin_lock_bh</entry>
+<entry>spin_lock_bh</entry>
+<entry>spin_lock_bh</entry>
+<entry>spin_lock_bh</entry>
+<entry>spin_lock_bh</entry>
+<entry>down_interruptible</entry>
+<entry>None</entry>
+</row>
+
+</tbody>
+</tgroup>
+</table>
</sect1>
</chapter>
diff --git a/Documentation/DocBook/libata.tmpl b/Documentation/DocBook/libata.tmpl
index 92a405a0e3641..cf2fce7707da2 100644
--- a/Documentation/DocBook/libata.tmpl
+++ b/Documentation/DocBook/libata.tmpl
@@ -1,4 +1,6 @@
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V3.1//EN"[]>
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
<book id="libataDevGuide">
<bookinfo>
diff --git a/Documentation/DocBook/librs.tmpl b/Documentation/DocBook/librs.tmpl
index be482c0302034..3ff39bafc00e1 100644
--- a/Documentation/DocBook/librs.tmpl
+++ b/Documentation/DocBook/librs.tmpl
@@ -1,4 +1,6 @@
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V3.1//EN"[]>
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
<book id="Reed-Solomon-Library-Guide">
<bookinfo>
@@ -223,7 +225,7 @@ int numerr, errpos[8];
.....
/* Decode 512 byte in data8.*/
numerr = decode_rs8 (rs_decoder, NULL, NULL, 512, syn, 0, errpos, 0, corr);
-for (i = 0; i < numerr; i++) {
+for (i = 0; i &lt; numerr; i++) {
do_error_correction_in_your_buffer(errpos[i], corr[i]);
}
</programlisting>
diff --git a/Documentation/DocBook/lsm.tmpl b/Documentation/DocBook/lsm.tmpl
index 635fa59da21fe..f63822195871b 100644
--- a/Documentation/DocBook/lsm.tmpl
+++ b/Documentation/DocBook/lsm.tmpl
@@ -1,6 +1,9 @@
-<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook V3.1//EN"[]>
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
+
<article class="whitepaper" id="LinuxSecurityModule" lang="en">
- <artheader>
+ <articleinfo>
<title>Linux Security Modules: General Security Hooks for Linux</title>
<authorgroup>
<author>
@@ -28,7 +31,7 @@
</affiliation>
</author>
</authorgroup>
- </artheader>
+ </articleinfo>
<sect1><title>Introduction</title>
@@ -84,7 +87,7 @@ security; it merely provides the infrastructure to support security
modules. The LSM kernel patch also moves most of the capabilities
logic into an optional security module, with the system defaulting
to the traditional superuser logic. This capabilities module
-is discussed further in <XRef LinkEnd="cap">.
+is discussed further in <xref linkend="cap"/>.
</para>
<para>
diff --git a/Documentation/DocBook/mcabook.tmpl b/Documentation/DocBook/mcabook.tmpl
index a8902e333a15e..4367f4642f3df 100644
--- a/Documentation/DocBook/mcabook.tmpl
+++ b/Documentation/DocBook/mcabook.tmpl
@@ -1,4 +1,6 @@
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V3.1//EN"[]>
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
<book id="MCAGuide">
<bookinfo>
diff --git a/Documentation/DocBook/mtdnand.tmpl b/Documentation/DocBook/mtdnand.tmpl
index 435bb524535b0..6e463d0db266b 100644
--- a/Documentation/DocBook/mtdnand.tmpl
+++ b/Documentation/DocBook/mtdnand.tmpl
@@ -1,4 +1,6 @@
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V3.1//EN"[]>
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
<book id="MTD-NAND-Guide">
<bookinfo>
@@ -238,9 +240,9 @@ static void board_hwcontrol(struct mtd_info *mtd, int cmd)
struct nand_chip *this = (struct nand_chip *) mtd->priv;
switch(cmd){
case NAND_CTL_SETCLE: this->IO_ADDR_W |= CLE_ADRR_BIT; break;
- case NAND_CTL_CLRCLE: this->IO_ADDR_W &= ~CLE_ADRR_BIT; break;
+ case NAND_CTL_CLRCLE: this->IO_ADDR_W &amp;= ~CLE_ADRR_BIT; break;
case NAND_CTL_SETALE: this->IO_ADDR_W |= ALE_ADRR_BIT; break;
- case NAND_CTL_CLRALE: this->IO_ADDR_W &= ~ALE_ADRR_BIT; break;
+ case NAND_CTL_CLRALE: this->IO_ADDR_W &amp;= ~ALE_ADRR_BIT; break;
}
}
</programlisting>
@@ -391,7 +393,7 @@ static void board_select_chip (struct mtd_info *mtd, int chip)
/* Deselect all chips, set all nCE pins high */
GPIO(BOARD_NAND_NCE) |= 0xff;
if (chip >= 0)
- GPIO(BOARD_NAND_NCE) &= ~ (1 << chip);
+ GPIO(BOARD_NAND_NCE) &amp;= ~ (1 &lt;&lt; chip);
}
</programlisting>
<para>
@@ -405,8 +407,8 @@ static void board_select_chip (struct mtd_info *mtd, int chip)
struct nand_chip *this = (struct nand_chip *) mtd->priv;
/* Deselect all chips */
- this->IO_ADDR_R &= ~BOARD_NAND_ADDR_MASK;
- this->IO_ADDR_W &= ~BOARD_NAND_ADDR_MASK;
+ this->IO_ADDR_R &amp;= ~BOARD_NAND_ADDR_MASK;
+ this->IO_ADDR_W &amp;= ~BOARD_NAND_ADDR_MASK;
switch (chip) {
case 0:
this->IO_ADDR_R |= BOARD_NAND_ADDR_CHIP0;
diff --git a/Documentation/DocBook/procfs-guide.tmpl b/Documentation/DocBook/procfs-guide.tmpl
index 34206230c7199..45cad23efefa9 100644
--- a/Documentation/DocBook/procfs-guide.tmpl
+++ b/Documentation/DocBook/procfs-guide.tmpl
@@ -1,6 +1,7 @@
-<!-- -*- sgml -*- -->
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V3.1//EN"[
-<!ENTITY procfsexample SYSTEM "procfs_example.sgml">
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [
+<!ENTITY procfsexample SYSTEM "procfs_example.xml">
]>
<book id="LKProcfsGuide">
@@ -205,7 +206,7 @@
function will return a pointer to the freshly created
<structname>struct proc_dir_entry</structname>; otherwise it
will return <constant>NULL</constant>. <xref
- linkend="userland"> describes how to do something useful with
+ linkend="userland"/> describes how to do something useful with
regular files.
</para>
@@ -221,7 +222,7 @@
<para>
If you only want to be able to read the file, the function
<function>create_proc_read_entry</function> described in <xref
- linkend="convenience"> may be used to create and initialise
+ linkend="convenience"/> may be used to create and initialise
the procfs entry in one single call.
</para>
</sect1>
@@ -298,7 +299,7 @@
the <structname>struct proc_dir_entry</structname> before
<function>remove_proc_entry</function> is called (that is: if
there was some <structfield>data</structfield> allocated, of
- course). See <xref linkend="usingdata"> for more information
+ course). See <xref linkend="usingdata"/> for more information
on using the <structfield>data</structfield> entry.
</para>
</sect1>
@@ -333,7 +334,7 @@ entry->write_proc = write_proc_foo;
If you only want to use a the
<structfield>read_proc</structfield>, the function
<function>create_proc_read_entry</function> described in <xref
- linkend="convenience"> may be used to create and initialise the
+ linkend="convenience"/> may be used to create and initialise the
procfs entry in one single call.
</para>
@@ -386,7 +387,7 @@ entry->write_proc = write_proc_foo;
The parameter <parameter>start</parameter> doesn't seem to be
used anywhere in the kernel. The <parameter>data</parameter>
parameter can be used to create a single call back function for
- several files, see <xref linkend="usingdata">.
+ several files, see <xref linkend="usingdata"/>.
</para>
<para>
@@ -395,7 +396,7 @@ entry->write_proc = write_proc_foo;
</para>
<para>
- <xref linkend="example"> shows how to use a read call back
+ <xref linkend="example"/> shows how to use a read call back
function.
</para>
</sect1>
@@ -429,12 +430,12 @@ entry->write_proc = write_proc_foo;
kernel's memory space, so it should first be copied to kernel
space with <function>copy_from_user</function>. The
<parameter>file</parameter> parameter is usually
- ignored. <xref linkend="usingdata"> shows how to use the
+ ignored. <xref linkend="usingdata"/> shows how to use the
<parameter>data</parameter> parameter.
</para>
<para>
- Again, <xref linkend="example"> shows how to use this call back
+ Again, <xref linkend="example"/> shows how to use this call back
function.
</para>
</sect1>
@@ -525,10 +526,10 @@ int foo_read_func(char *page, char **start, off_t off,
<para>
This function creates a regular file in exactly the same way
as <function>create_proc_entry</function> from <xref
- linkend="regularfile"> does, but also allows to set the read
+ linkend="regularfile"/> does, but also allows to set the read
function <parameter>read_proc</parameter> in one call. This
function can set the <parameter>data</parameter> as well, like
- explained in <xref linkend="usingdata">.
+ explained in <xref linkend="usingdata"/>.
</para>
</sect1>
diff --git a/Documentation/DocBook/scsidrivers.tmpl b/Documentation/DocBook/scsidrivers.tmpl
index 81e1561caf141..d058e65daf19f 100644
--- a/Documentation/DocBook/scsidrivers.tmpl
+++ b/Documentation/DocBook/scsidrivers.tmpl
@@ -1,5 +1,6 @@
-<!-- -*- sgml -*- -->
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V4.1//EN"[]>
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
<book id="scsidrivers">
<bookinfo>
diff --git a/Documentation/DocBook/sis900.tmpl b/Documentation/DocBook/sis900.tmpl
index 48aebc20e782e..6c2cbac93c3f0 100644
--- a/Documentation/DocBook/sis900.tmpl
+++ b/Documentation/DocBook/sis900.tmpl
@@ -1,25 +1,27 @@
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V3.1//EN"[]>
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
<book id="SiS900Guide">
<bookinfo>
-<title>SiS 900/7016 Fast Ethernet Device Driver</Title>
+<title>SiS 900/7016 Fast Ethernet Device Driver</title>
<authorgroup>
<author>
-<FirstName>Ollie</FirstName>
+<firstname>Ollie</firstname>
<surname>Lho</surname>
</author>
<author>
-<FirstName>Lei Chun</FirstName>
+<firstname>Lei Chun</firstname>
<surname>Chang</surname>
</author>
</authorgroup>
-<edition>Document Revision: 0.3 for SiS900 driver v1.06 & v1.07</edition>
-<PubDate>November 16, 2000</PubDate>
+<edition>Document Revision: 0.3 for SiS900 driver v1.06 &amp; v1.07</edition>
+<pubdate>November 16, 2000</pubdate>
<copyright>
<year>1999</year>
@@ -48,21 +50,21 @@
</para>
</legalnotice>
-<Abstract>
-<Para>
+<abstract>
+<para>
This document gives some information on installation and usage of SiS 900/7016
device driver under Linux.
-</Para>
-</Abstract>
+</para>
+</abstract>
</bookinfo>
<toc></toc>
<chapter id="intro">
- <Title>Introduction</Title>
+ <title>Introduction</title>
-<Para>
+<para>
This document describes the revision 1.06 and 1.07 of SiS 900/7016 Fast Ethernet
device driver under Linux. The driver is developed by Silicon Integrated
System Corp. and distributed freely under the GNU General Public License (GPL).
@@ -70,265 +72,265 @@ The driver can be compiled as a loadable module and used under Linux kernel
version 2.2.x. (rev. 1.06)
With minimal changes, the driver can also be used under 2.3.x and 2.4.x kernel
(rev. 1.07), please see
-<XRef LinkEnd="install">. If you are intended to
+<xref linkend="install"/>. If you are intended to
use the driver for earlier kernels, you are on your own.
-</Para>
+</para>
-<Para>
+<para>
The driver is tested with usual TCP/IP applications including
FTP, Telnet, Netscape etc. and is used constantly by the developers.
-</Para>
+</para>
-<Para>
+<para>
Please send all comments/fixes/questions to
-<ULink URL="mailto:lcchang@sis.com.tw">Lei-Chun Chang</ULink>.
-</Para>
+<ulink url="mailto:lcchang@sis.com.tw">Lei-Chun Chang</ulink>.
+</para>
</chapter>
<chapter id="changes">
- <Title>Changes</Title>
+ <title>Changes</title>
-<Para>
+<para>
Changes made in Revision 1.07
-<OrderedList>
-<ListItem>
-<Para>
+<orderedlist>
+<listitem>
+<para>
Separation of sis900.c and sis900.h in order to move most
constant definition to sis900.h (many of those constants were
corrected)
-</Para>
-</ListItem>
+</para>
+</listitem>
-<ListItem>
-<Para>
+<listitem>
+<para>
Clean up PCI detection, the pci-scan from Donald Becker were not used,
just simple pci&lowbar;find&lowbar;*.
-</Para>
-</ListItem>
+</para>
+</listitem>
-<ListItem>
-<Para>
+<listitem>
+<para>
MII detection is modified to support multiple mii transceiver.
-</Para>
-</ListItem>
+</para>
+</listitem>
-<ListItem>
-<Para>
+<listitem>
+<para>
Bugs in read&lowbar;eeprom, mdio&lowbar;* were removed.
-</Para>
-</ListItem>
+</para>
+</listitem>
-<ListItem>
-<Para>
+<listitem>
+<para>
Lot of sis900 irrelevant comments were removed/changed and
more comments were added to reflect the real situation.
-</Para>
-</ListItem>
+</para>
+</listitem>
-<ListItem>
-<Para>
+<listitem>
+<para>
Clean up of physical/virtual address space mess in buffer
descriptors.
-</Para>
-</ListItem>
+</para>
+</listitem>
-<ListItem>
-<Para>
+<listitem>
+<para>
Better transmit/receive error handling.
-</Para>
-</ListItem>
+</para>
+</listitem>
-<ListItem>
-<Para>
+<listitem>
+<para>
The driver now uses zero-copy single buffer management
scheme to improve performance.
-</Para>
-</ListItem>
+</para>
+</listitem>
-<ListItem>
-<Para>
+<listitem>
+<para>
Names of variables were changed to be more consistent.
-</Para>
-</ListItem>
+</para>
+</listitem>
-<ListItem>
-<Para>
+<listitem>
+<para>
Clean up of auo-negotiation and timer code.
-</Para>
-</ListItem>
+</para>
+</listitem>
-<ListItem>
-<Para>
+<listitem>
+<para>
Automatic detection and change of PHY on the fly.
-</Para>
-</ListItem>
+</para>
+</listitem>
-<ListItem>
-<Para>
+<listitem>
+<para>
Bug in mac probing fixed.
-</Para>
-</ListItem>
+</para>
+</listitem>
-<ListItem>
-<Para>
+<listitem>
+<para>
Fix 630E equalier problem by modifying the equalizer workaround rule.
-</Para>
-</ListItem>
+</para>
+</listitem>
-<ListItem>
-<Para>
+<listitem>
+<para>
Support for ICS1893 10/100 Interated PHYceiver.
-</Para>
-</ListItem>
+</para>
+</listitem>
-<ListItem>
-<Para>
+<listitem>
+<para>
Support for media select by ifconfig.
-</Para>
-</ListItem>
+</para>
+</listitem>
-<ListItem>
-<Para>
+<listitem>
+<para>
Added kernel-doc extratable documentation.
-</Para>
-</ListItem>
+</para>
+</listitem>
-</OrderedList>
-</Para>
+</orderedlist>
+</para>
</chapter>
<chapter id="tested">
- <Title>Tested Environment</Title>
+ <title>Tested Environment</title>
-<Para>
+<para>
This driver is developed on the following hardware
-<ItemizedList>
-<ListItem>
+<itemizedlist>
+<listitem>
-<Para>
+<para>
Intel Celeron 500 with SiS 630 (rev 02) chipset
-</Para>
-</ListItem>
-<ListItem>
+</para>
+</listitem>
+<listitem>
-<Para>
+<para>
SiS 900 (rev 01) and SiS 7016/7014 Fast Ethernet Card
-</Para>
-</ListItem>
+</para>
+</listitem>
-</ItemizedList>
+</itemizedlist>
and tested with these software environments
-<ItemizedList>
-<ListItem>
+<itemizedlist>
+<listitem>
-<Para>
+<para>
Red Hat Linux version 6.2
-</Para>
-</ListItem>
-<ListItem>
+</para>
+</listitem>
+<listitem>
-<Para>
+<para>
Linux kernel version 2.4.0
-</Para>
-</ListItem>
-<ListItem>
+</para>
+</listitem>
+<listitem>
-<Para>
+<para>
Netscape version 4.6
-</Para>
-</ListItem>
-<ListItem>
+</para>
+</listitem>
+<listitem>
-<Para>
+<para>
NcFTP 3.0.0 beta 18
-</Para>
-</ListItem>
-<ListItem>
+</para>
+</listitem>
+<listitem>
-<Para>
+<para>
Samba version 2.0.3
-</Para>
-</ListItem>
+</para>
+</listitem>
-</ItemizedList>
+</itemizedlist>
-</Para>
+</para>
</chapter>
<chapter id="files">
-<Title>Files in This Package</Title>
+<title>Files in This Package</title>
-<Para>
+<para>
In the package you can find these files:
-</Para>
+</para>
-<Para>
-<VariableList>
+<para>
+<variablelist>
-<VarListEntry>
-<Term>sis900.c</Term>
-<ListItem>
-<Para>
+<varlistentry>
+<term>sis900.c</term>
+<listitem>
+<para>
Driver source file in C
-</Para>
-</ListItem>
-</VarListEntry>
-
-<VarListEntry>
-<Term>sis900.h</Term>
-<ListItem>
-<Para>
+</para>
+</listitem>
+</varlistentry>
+
+<varlistentry>
+<term>sis900.h</term>
+<listitem>
+<para>
Header file for sis900.c
-</Para>
-</ListItem>
-</VarListEntry>
-
-<VarListEntry>
-<Term>sis900.sgml</Term>
-<ListItem>
-<Para>
+</para>
+</listitem>
+</varlistentry>
+
+<varlistentry>
+<term>sis900.sgml</term>
+<listitem>
+<para>
DocBook SGML source of the document
-</Para>
-</ListItem>
-</VarListEntry>
-
-<VarListEntry>
-<Term>sis900.txt</Term>
-<ListItem>
-<Para>
+</para>
+</listitem>
+</varlistentry>
+
+<varlistentry>
+<term>sis900.txt</term>
+<listitem>
+<para>
Driver document in plain text
-</Para>
-</ListItem>
-</VarListEntry>
+</para>
+</listitem>
+</varlistentry>
-</VariableList>
-</Para>
+</variablelist>
+</para>
</chapter>
<chapter id="install">
- <Title>Installation</Title>
+ <title>Installation</title>
-<Para>
+<para>
Silicon Integrated System Corp. is cooperating closely with core Linux Kernel
developers. The revisions of SiS 900 driver are distributed by the usuall channels
for kernel tar files and patches. Those kernel tar files for official kernel and
patches for kernel pre-release can be download at
-<ULink URL="http://ftp.kernel.org/pub/linux/kernel/">official kernel ftp site</ULink>
+<ulink url="http://ftp.kernel.org/pub/linux/kernel/">official kernel ftp site</ulink>
and its mirrors.
The 1.06 revision can be found in kernel version later than 2.3.15 and pre-2.2.14,
and 1.07 revision can be found in kernel version 2.4.0.
If you have no prior experience in networking under Linux, please read
-<ULink URL="http://www.tldp.org/">Ethernet HOWTO</ULink> and
-<ULink URL="http://www.tldp.org/">Networking HOWTO</ULink> available from
+<ulink url="http://www.tldp.org/">Ethernet HOWTO</ulink> and
+<ulink url="http://www.tldp.org/">Networking HOWTO</ulink> available from
Linux Documentation Project (LDP).
-</Para>
+</para>
-<Para>
+<para>
The driver is bundled in release later than 2.2.11 and 2.3.15 so this
is the most easy case.
Be sure you have the appropriate packages for compiling kernel source.
@@ -338,63 +340,63 @@ in kernel release, you should have your driver file
<filename>sis900.c</filename> and <filename>sis900.h</filename>
copied into <filename class="directory">/usr/src/linux/drivers/net/</filename> first.
There are two alternative ways to install the driver
-</Para>
+</para>
-<Sect1>
-<Title>Building the driver as loadable module</Title>
+<sect1>
+<title>Building the driver as loadable module</title>
-<Para>
+<para>
To build the driver as a loadable kernel module you have to reconfigure
the kernel to activate network support by
-</Para>
+</para>
-<Para><screen>
+<para><screen>
make menuconfig
-</screen></Para>
+</screen></para>
-<Para>
+<para>
Choose <quote>Loadable module support ---></quote>,
then select <quote>Enable loadable module support</quote>.
-</Para>
+</para>
-<Para>
+<para>
Choose <quote>Network Device Support ---></quote>, select
<quote>Ethernet (10 or 100Mbit)</quote>.
Then select <quote>EISA, VLB, PCI and on board controllers</quote>,
and choose <quote>SiS 900/7016 PCI Fast Ethernet Adapter support</quote>
to <quote>M</quote>.
-</Para>
+</para>
-<Para>
+<para>
After reconfiguring the kernel, you can make the driver module by
-</Para>
+</para>
-<Para><screen>
+<para><screen>
make modules
-</screen></Para>
+</screen></para>
-<Para>
+<para>
The driver should be compiled with no errors. After compiling the driver,
the driver can be installed to proper place by
-</Para>
+</para>
-<Para><screen>
+<para><screen>
make modules_install
-</screen></Para>
+</screen></para>
-<Para>
+<para>
Load the driver into kernel by
-</Para>
+</para>
-<Para><screen>
+<para><screen>
insmod sis900
-</screen></Para>
+</screen></para>
-<Para>
+<para>
When loading the driver into memory, some information message can be view by
-</Para>
+</para>
-<Para>
+<para>
<screen>
dmesg
</screen>
@@ -404,103 +406,103 @@ or
<screen>
cat /var/log/message
</screen>
-</Para>
+</para>
-<Para>
+<para>
If the driver is loaded properly you will have messages similar to this:
-</Para>
+</para>
-<Para><screen>
+<para><screen>
sis900.c: v1.07.06 11/07/2000
eth0: SiS 900 PCI Fast Ethernet at 0xd000, IRQ 10, 00:00:e8:83:7f:a4.
eth0: SiS 900 Internal MII PHY transceiver found at address 1.
eth0: Using SiS 900 Internal MII PHY as default
-</screen></Para>
+</screen></para>
-<Para>
+<para>
showing the version of the driver and the results of probing routine.
-</Para>
+</para>
-<Para>
+<para>
Once the driver is loaded, network can be brought up by
-</Para>
+</para>
-<Para><screen>
+<para><screen>
/sbin/ifconfig eth0 IPADDR broadcast BROADCAST netmask NETMASK media TYPE
-</screen></Para>
+</screen></para>
-<Para>
+<para>
where IPADDR, BROADCAST, NETMASK are your IP address, broadcast address and
netmask respectively. TYPE is used to set medium type used by the device.
Typical values are "10baseT"(twisted-pair 10Mbps Ethernet) or "100baseT"
(twisted-pair 100Mbps Ethernet). For more information on how to configure
network interface, please refer to
-<ULink URL="http://www.tldp.org/">Networking HOWTO</ULink>.
-</Para>
+<ulink url="http://www.tldp.org/">Networking HOWTO</ulink>.
+</para>
-<Para>
+<para>
The link status is also shown by kernel messages. For example, after the
network interface is activated, you may have the message:
-</Para>
+</para>
-<Para><screen>
+<para><screen>
eth0: Media Link On 100mbps full-duplex
-</screen></Para>
+</screen></para>
-<Para>
+<para>
If you try to unplug the twist pair (TP) cable you will get
-</Para>
+</para>
-<Para><screen>
+<para><screen>
eth0: Media Link Off
-</screen></Para>
+</screen></para>
-<Para>
+<para>
indicating that the link is failed.
-</Para>
-</Sect1>
+</para>
+</sect1>
-<Sect1>
-<Title>Building the driver into kernel</Title>
+<sect1>
+<title>Building the driver into kernel</title>
-<Para>
+<para>
If you want to make the driver into kernel, choose <quote>Y</quote>
rather than <quote>M</quote> on
<quote>SiS 900/7016 PCI Fast Ethernet Adapter support</quote>
when configuring the kernel. Build the kernel image in the usual way
-</Para>
+</para>
-<Para><screen>
+<para><screen>
make clean
make bzlilo
-</screen></Para>
+</screen></para>
-<Para>
+<para>
Next time the system reboot, you have the driver in memory.
-</Para>
+</para>
-</Sect1>
+</sect1>
</chapter>
<chapter id="problems">
- <Title>Known Problems and Bugs</Title>
+ <title>Known Problems and Bugs</title>
-<Para>
+<para>
There are some known problems and bugs. If you find any other bugs please
-mail to <ULink URL="mailto:lcchang@sis.com.tw">lcchang@sis.com.tw</ULink>
+mail to <ulink url="mailto:lcchang@sis.com.tw">lcchang@sis.com.tw</ulink>
-<OrderedList>
+<orderedlist>
-<ListItem>
-<Para>
+<listitem>
+<para>
AM79C901 HomePNA PHY is not thoroughly tested, there may be some
bugs in the <quote>on the fly</quote> change of transceiver.
-</Para>
-</ListItem>
+</para>
+</listitem>
-<ListItem>
-<Para>
+<listitem>
+<para>
A bug is hidden somewhere in the receive buffer management code,
the bug causes NULL pointer reference in the kernel. This fault is
caught before bad things happen and reported with the message:
@@ -509,70 +511,70 @@ caught before bad things happen and reported with the message:
eth0: NULL pointer encountered in Rx ring, skipping
</computeroutput>
-which can be viewed with <Literal remap="tt">dmesg</Literal> or
-<Literal remap="tt">cat /var/log/message</Literal>.
-</Para>
-</ListItem>
+which can be viewed with <literal remap="tt">dmesg</literal> or
+<literal remap="tt">cat /var/log/message</literal>.
+</para>
+</listitem>
-<ListItem>
-<Para>
+<listitem>
+<para>
The media type change from 10Mbps to 100Mbps twisted-pair ethernet
by ifconfig causes the media link down.
-</Para>
-</ListItem>
+</para>
+</listitem>
-</OrderedList>
-</Para>
+</orderedlist>
+</para>
</chapter>
<chapter id="RHistory">
- <Title>Revision History</Title>
+ <title>Revision History</title>
-<Para>
-<ItemizedList>
+<para>
+<itemizedlist>
-<ListItem>
-<Para>
+<listitem>
+<para>
November 13, 2000, Revision 1.07, seventh release, 630E problem fixed
and further clean up.
-</Para>
-</ListItem>
+</para>
+</listitem>
-<ListItem>
-<Para>
+<listitem>
+<para>
November 4, 1999, Revision 1.06, Second release, lots of clean up
and optimization.
-</Para>
-</ListItem>
+</para>
+</listitem>
-<ListItem>
-<Para>
+<listitem>
+<para>
August 8, 1999, Revision 1.05, Initial Public Release
-</Para>
-</ListItem>
+</para>
+</listitem>
-</ItemizedList>
-</Para>
+</itemizedlist>
+</para>
</chapter>
<chapter id="acknowledgements">
- <Title>Acknowledgements</Title>
+ <title>Acknowledgements</title>
-<Para>
+<para>
This driver was originally derived form
-<ULink URL="mailto:becker@cesdis1.gsfc.nasa.gov">Donald Becker</ULink>'s
-<ULink URL="ftp://cesdis.gsfc.nasa.gov/pub/linux/drivers/kern-2.3/pci-skeleton.c"
->pci-skeleton</ULink> and
-<ULink URL="ftp://cesdis.gsfc.nasa.gov/pub/linux/drivers/kern-2.3/rtl8139.c"
->rtl8139</ULink> drivers. Donald also provided various suggestion
+<ulink url="mailto:becker@cesdis1.gsfc.nasa.gov">Donald Becker</ulink>'s
+<ulink url="ftp://cesdis.gsfc.nasa.gov/pub/linux/drivers/kern-2.3/pci-skeleton.c"
+>pci-skeleton</ulink> and
+<ulink url="ftp://cesdis.gsfc.nasa.gov/pub/linux/drivers/kern-2.3/rtl8139.c"
+>rtl8139</ulink> drivers. Donald also provided various suggestion
regarded with improvements made in revision 1.06.
-</Para>
+</para>
-<Para>
+<para>
The 1.05 revision was created by
-<ULink URL="mailto:cmhuang@sis.com.tw">Jim Huang</ULink>, AMD 79c901
-support was added by <ULink URL="mailto:lcs@sis.com.tw">Chin-Shan Li</ULink>.
-</Para>
+<ulink url="mailto:cmhuang@sis.com.tw">Jim Huang</ulink>, AMD 79c901
+support was added by <ulink url="mailto:lcs@sis.com.tw">Chin-Shan Li</ulink>.
+</para>
</chapter>
<chapter id="functions">
diff --git a/Documentation/DocBook/tulip-user.tmpl b/Documentation/DocBook/tulip-user.tmpl
index b74f8a363c892..6520d7a1b1329 100644
--- a/Documentation/DocBook/tulip-user.tmpl
+++ b/Documentation/DocBook/tulip-user.tmpl
@@ -1,4 +1,6 @@
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V3.1//EN"[]>
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
<book id="TulipUserGuide">
<bookinfo>
@@ -67,7 +69,7 @@ Jeff Garzik, Takashi Manabe and a cast of thousands.
<para>
For 2.4.x and later kernels, the Linux Tulip driver is available at
-<ULink URL="http://sourceforge.net/projects/tulip/">http://sourceforge.net/projects/tulip/</ULink>
+<ulink url="http://sourceforge.net/projects/tulip/">http://sourceforge.net/projects/tulip/</ulink>
</para>
<para>
@@ -85,7 +87,7 @@ For 2.4.x and later kernels, the Linux Tulip driver is available at
<para>
Additional information on Donald Becker's tulip.c
- is available at <ULink URL="http://www.scyld.com/network/tulip.html">http://www.scyld.com/network/tulip.html</ULink>
+ is available at <ulink url="http://www.scyld.com/network/tulip.html">http://www.scyld.com/network/tulip.html</ulink>
</para>
</chapter>
diff --git a/Documentation/DocBook/usb.tmpl b/Documentation/DocBook/usb.tmpl
index 0f0c3a33bc4ae..f3ef0bf435e9e 100644
--- a/Documentation/DocBook/usb.tmpl
+++ b/Documentation/DocBook/usb.tmpl
@@ -1,4 +1,7 @@
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V3.1//EN"[]>
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
+
<book id="Linux-USB-API">
<bookinfo>
<title>The Linux-USB Host Side API</title>
diff --git a/Documentation/DocBook/via-audio.tmpl b/Documentation/DocBook/via-audio.tmpl
index f91903c2a6e78..36e642147d6b2 100644
--- a/Documentation/DocBook/via-audio.tmpl
+++ b/Documentation/DocBook/via-audio.tmpl
@@ -1,4 +1,6 @@
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V3.1//EN"[]>
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
<book id="ViaAudioGuide">
<bookinfo>
@@ -262,7 +264,7 @@ Version 1.1.15
<listitem>
<para>
- Fixes for the SPEED, STEREO, CHANNELS, FMT ioctls when in read &
+ Fixes for the SPEED, STEREO, CHANNELS, FMT ioctls when in read &amp;
write mode (Rui Sousa)
</para>
</listitem>
diff --git a/Documentation/DocBook/videobook.tmpl b/Documentation/DocBook/videobook.tmpl
index 2c92b18368726..3ec6c875588ab 100644
--- a/Documentation/DocBook/videobook.tmpl
+++ b/Documentation/DocBook/videobook.tmpl
@@ -1,4 +1,6 @@
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V3.1//EN"[]>
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
<book id="V4LGuide">
<bookinfo>
@@ -180,23 +182,23 @@ int __init myradio_init(struct video_init *v)
<tgroup cols="3" align="left">
<tbody>
<row>
- <entry>VFL_TYPE_RADIO</><entry>/dev/radio{n}</><entry>
+ <entry>VFL_TYPE_RADIO</entry><entry>/dev/radio{n}</entry><entry>
Radio devices are assigned in this block. As with all of these
selections the actual number assignment is done by the video layer
accordijng to what is free.</entry>
</row><row>
- <entry>VFL_TYPE_GRABBER</><entry>/dev/video{n}</><entry>
+ <entry>VFL_TYPE_GRABBER</entry><entry>/dev/video{n}</entry><entry>
Video capture devices and also -- counter-intuitively for the name --
hardware video playback devices such as MPEG2 cards.</entry>
</row><row>
- <entry>VFL_TYPE_VBI</><entry>/dev/vbi{n}</><entry>
+ <entry>VFL_TYPE_VBI</entry><entry>/dev/vbi{n}</entry><entry>
The VBI devices capture the hidden lines on a television picture
that carry further information like closed caption data, teletext
(primarily in Europe) and now Intercast and the ATVEC internet
television encodings.</entry>
</row><row>
- <entry>VFL_TYPE_VTX</><entry>/dev/vtx[n}</><entry>
+ <entry>VFL_TYPE_VTX</entry><entry>/dev/vtx[n}</entry><entry>
VTX is 'Videotext' also known as 'Teletext'. This is a system for
sending numbered, 40x25, mostly textual page images over the hidden
lines. Unlike the /dev/vbi interfaces, this is for 'smart' decoder
@@ -301,25 +303,25 @@ static int radio_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
<tgroup cols="2" align="left">
<tbody>
<row>
- <entry>name</><entry>The device text name. This is intended for the user.</>
+ <entry>name</entry><entry>The device text name. This is intended for the user.</entry>
</row><row>
- <entry>channels</><entry>The number of different channels you can tune on
+ <entry>channels</entry><entry>The number of different channels you can tune on
this card. It could even by zero for a card that has
no tuning capability. For our simple FM radio it is 1.
An AM/FM radio would report 2.</entry>
</row><row>
- <entry>audios</><entry>The number of audio inputs on this device. For our
+ <entry>audios</entry><entry>The number of audio inputs on this device. For our
radio there is only one audio input.</entry>
</row><row>
- <entry>minwidth,minheight</><entry>The smallest size the card is capable of capturing
+ <entry>minwidth,minheight</entry><entry>The smallest size the card is capable of capturing
images in. We set these to zero. Radios do not
capture pictures</entry>
</row><row>
- <entry>maxwidth,maxheight</><entry>The largest image size the card is capable of
+ <entry>maxwidth,maxheight</entry><entry>The largest image size the card is capable of
capturing. For our radio we report 0.
</entry>
</row><row>
- <entry>type</><entry>This reports the capabilities of the device, and
+ <entry>type</entry><entry>This reports the capabilities of the device, and
matches the field we filled in in the struct
video_device when registering.</entry>
</row>
@@ -375,26 +377,26 @@ static int radio_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
<tgroup cols="2" align="left">
<tbody>
<row>
- <entry>int tuner</><entry>The number of the tuner in question</entry>
+ <entry>int tuner</entry><entry>The number of the tuner in question</entry>
</row><row>
- <entry>char name[32]</><entry>A text description of this tuner. "FM" will do fine.
+ <entry>char name[32]</entry><entry>A text description of this tuner. "FM" will do fine.
This is intended for the application.</entry>
</row><row>
- <entry>u32 flags</>
+ <entry>u32 flags</entry>
<entry>Tuner capability flags</entry>
</row>
<row>
- <entry>u16 mode</><entry>The current reception mode</entry>
+ <entry>u16 mode</entry><entry>The current reception mode</entry>
</row><row>
- <entry>u16 signal</><entry>The signal strength scaled between 0 and 65535. If
+ <entry>u16 signal</entry><entry>The signal strength scaled between 0 and 65535. If
a device cannot tell the signal strength it should
report 65535. Many simple cards contain only a
signal/no signal bit. Such cards will report either
0 or 65535.</entry>
</row><row>
- <entry>u32 rangelow, rangehigh</><entry>
+ <entry>u32 rangelow, rangehigh</entry><entry>
The range of frequencies supported by the radio
or TV. It is scaled according to the VIDEO_TUNER_LOW
flag.</entry>
@@ -408,20 +410,20 @@ static int radio_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
<tgroup cols="2" align="left">
<tbody>
<row>
- <entry>VIDEO_TUNER_PAL</><entry>A PAL TV tuner</entry>
+ <entry>VIDEO_TUNER_PAL</entry><entry>A PAL TV tuner</entry>
</row><row>
- <entry>VIDEO_TUNER_NTSC</><entry>An NTSC (US) TV tuner</entry>
+ <entry>VIDEO_TUNER_NTSC</entry><entry>An NTSC (US) TV tuner</entry>
</row><row>
- <entry>VIDEO_TUNER_SECAM</><entry>A SECAM (French) TV tuner</entry>
+ <entry>VIDEO_TUNER_SECAM</entry><entry>A SECAM (French) TV tuner</entry>
</row><row>
- <entry>VIDEO_TUNER_LOW</><entry>
+ <entry>VIDEO_TUNER_LOW</entry><entry>
The tuner frequency is scaled in 1/16th of a KHz
steps. If not it is in 1/16th of a MHz steps
</entry>
</row><row>
- <entry>VIDEO_TUNER_NORM</><entry>The tuner can set its format</entry>
+ <entry>VIDEO_TUNER_NORM</entry><entry>The tuner can set its format</entry>
</row><row>
- <entry>VIDEO_TUNER_STEREO_ON</><entry>The tuner is currently receiving a stereo signal</entry>
+ <entry>VIDEO_TUNER_STEREO_ON</entry><entry>The tuner is currently receiving a stereo signal</entry>
</row>
</tbody>
</tgroup>
@@ -431,13 +433,13 @@ static int radio_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
<tgroup cols="2" align="left">
<tbody>
<row>
- <entry>VIDEO_MODE_PAL</><entry>PAL Format</entry>
+ <entry>VIDEO_MODE_PAL</entry><entry>PAL Format</entry>
</row><row>
- <entry>VIDEO_MODE_NTSC</><entry>NTSC Format (USA)</entry>
+ <entry>VIDEO_MODE_NTSC</entry><entry>NTSC Format (USA)</entry>
</row><row>
- <entry>VIDEO_MODE_SECAM</><entry>French Format</entry>
+ <entry>VIDEO_MODE_SECAM</entry><entry>French Format</entry>
</row><row>
- <entry>VIDEO_MODE_AUTO</><entry>A device that does not need to do
+ <entry>VIDEO_MODE_AUTO</entry><entry>A device that does not need to do
TV format switching</entry>
</row>
</tbody>
@@ -521,7 +523,7 @@ static unsigned long current_freq;
if(copy_from_user(arg, &amp;freq,
sizeof(unsigned long))!=0)
return -EFAULT;
- if(hardware_set_freq(freq)<0)
+ if(hardware_set_freq(freq)&lt;0)
return -EINVAL;
current_freq = freq;
return 0;
@@ -582,32 +584,32 @@ static int current_volume=0;
<tgroup cols="2" align="left">
<tbody>
<row>
- <entry>audio</><entry>The input the user wishes to query</>
+ <entry>audio</entry><entry>The input the user wishes to query</entry>
</row><row>
- <entry>volume</><entry>The volume setting on a scale of 0-65535</>
+ <entry>volume</entry><entry>The volume setting on a scale of 0-65535</entry>
</row><row>
- <entry>base</><entry>The base level on a scale of 0-65535</>
+ <entry>base</entry><entry>The base level on a scale of 0-65535</entry>
</row><row>
- <entry>treble</><entry>The treble level on a scale of 0-65535</>
+ <entry>treble</entry><entry>The treble level on a scale of 0-65535</entry>
</row><row>
- <entry>flags</><entry>The features this audio device supports
+ <entry>flags</entry><entry>The features this audio device supports
</entry>
</row><row>
- <entry>name</><entry>A text name to display to the user. We picked
- "Radio" as it explains things quite nicely.</>
+ <entry>name</entry><entry>A text name to display to the user. We picked
+ "Radio" as it explains things quite nicely.</entry>
</row><row>
- <entry>mode</><entry>The current reception mode for the audio
+ <entry>mode</entry><entry>The current reception mode for the audio
We report MONO because our card is too stupid to know if it is in
mono or stereo.
</entry>
</row><row>
- <entry>balance</><entry>The stereo balance on a scale of 0-65535, 32768 is
- middle.</>
+ <entry>balance</entry><entry>The stereo balance on a scale of 0-65535, 32768 is
+ middle.</entry>
</row><row>
- <entry>step</><entry>The step by which the volume control jumps. This is
+ <entry>step</entry><entry>The step by which the volume control jumps. This is
used to help make it easy for applications to set
- slider behaviour.</>
+ slider behaviour.</entry>
</row>
</tbody>
</tgroup>
@@ -617,15 +619,15 @@ static int current_volume=0;
<tgroup cols="2" align="left">
<tbody>
<row>
- <entry>VIDEO_AUDIO_MUTE</><entry>The audio is currently muted. We
+ <entry>VIDEO_AUDIO_MUTE</entry><entry>The audio is currently muted. We
could fake this in our driver but we
choose not to bother.</entry>
</row><row>
- <entry>VIDEO_AUDIO_MUTABLE</><entry>The input has a mute option</entry>
+ <entry>VIDEO_AUDIO_MUTABLE</entry><entry>The input has a mute option</entry>
</row><row>
- <entry>VIDEO_AUDIO_TREBLE</><entry>The input has a treble control</entry>
+ <entry>VIDEO_AUDIO_TREBLE</entry><entry>The input has a treble control</entry>
</row><row>
- <entry>VIDEO_AUDIO_BASS</><entry>The input has a base control</entry>
+ <entry>VIDEO_AUDIO_BASS</entry><entry>The input has a base control</entry>
</row>
</tbody>
</tgroup>
@@ -635,13 +637,13 @@ static int current_volume=0;
<tgroup cols="2" align="left">
<tbody>
<row>
- <entry>VIDEO_SOUND_MONO</><entry>Mono sound</entry>
+ <entry>VIDEO_SOUND_MONO</entry><entry>Mono sound</entry>
</row><row>
- <entry>VIDEO_SOUND_STEREO</><entry>Stereo sound</entry>
+ <entry>VIDEO_SOUND_STEREO</entry><entry>Stereo sound</entry>
</row><row>
- <entry>VIDEO_SOUND_LANG1</><entry>Alternative language 1 (TV specific)</entry>
+ <entry>VIDEO_SOUND_LANG1</entry><entry>Alternative language 1 (TV specific)</entry>
</row><row>
- <entry>VIDEO_SOUND_LANG2</><entry>Alternative language 2 (TV specific)</entry>
+ <entry>VIDEO_SOUND_LANG2</entry><entry>Alternative language 2 (TV specific)</entry>
</row>
</tbody>
</tgroup>
@@ -866,37 +868,37 @@ static struct video_device my_camera
<tgroup cols="2" align="left">
<tbody>
<row>
-<entry>VID_TYPE_CAPTURE</><entry>We support image capture</>
+<entry>VID_TYPE_CAPTURE</entry><entry>We support image capture</entry>
</row><row>
-<entry>VID_TYPE_TELETEXT</><entry>A teletext capture device (vbi{n])</>
+<entry>VID_TYPE_TELETEXT</entry><entry>A teletext capture device (vbi{n])</entry>
</row><row>
-<entry>VID_TYPE_OVERLAY</><entry>The image can be directly overlaid onto the
- frame buffer</>
+<entry>VID_TYPE_OVERLAY</entry><entry>The image can be directly overlaid onto the
+ frame buffer</entry>
</row><row>
-<entry>VID_TYPE_CHROMAKEY</><entry>Chromakey can be used to select which parts
- of the image to display</>
+<entry>VID_TYPE_CHROMAKEY</entry><entry>Chromakey can be used to select which parts
+ of the image to display</entry>
</row><row>
-<entry>VID_TYPE_CLIPPING</><entry>It is possible to give the board a list of
- rectangles to draw around. </>
+<entry>VID_TYPE_CLIPPING</entry><entry>It is possible to give the board a list of
+ rectangles to draw around. </entry>
</row><row>
-<entry>VID_TYPE_FRAMERAM</><entry>The video capture goes into the video memory
+<entry>VID_TYPE_FRAMERAM</entry><entry>The video capture goes into the video memory
and actually changes it. Applications need
to know this so they can clean up after the
- card</>
+ card</entry>
</row><row>
-<entry>VID_TYPE_SCALES</><entry>The image can be scaled to various sizes,
- rather than being a single fixed size.</>
+<entry>VID_TYPE_SCALES</entry><entry>The image can be scaled to various sizes,
+ rather than being a single fixed size.</entry>
</row><row>
-<entry>VID_TYPE_MONOCHROME</><entry>The capture will be monochrome. This isn't a
+<entry>VID_TYPE_MONOCHROME</entry><entry>The capture will be monochrome. This isn't a
complete answer to the question since a mono
camera on a colour capture card will still
- produce mono output.</>
+ produce mono output.</entry>
</row><row>
-<entry>VID_TYPE_SUBCAPTURE</><entry>The card allows only part of its field of
+<entry>VID_TYPE_SUBCAPTURE</entry><entry>The card allows only part of its field of
view to be captured. This enables
applications to avoid copying all of a large
image into memory when only some section is
- relevant.</>
+ relevant.</entry>
</row>
</tbody>
</tgroup>
@@ -1207,18 +1209,18 @@ static int camera_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
<tbody>
<row>
- <entry>channel</><entry>The channel number we are selecting</entry>
+ <entry>channel</entry><entry>The channel number we are selecting</entry>
</row><row>
- <entry>name</><entry>The name for this channel. This is intended
+ <entry>name</entry><entry>The name for this channel. This is intended
to describe the port to the user.
Appropriate names are therefore things like
"Camera" "SCART input"</entry>
</row><row>
- <entry>flags</><entry>Channel properties</entry>
+ <entry>flags</entry><entry>Channel properties</entry>
</row><row>
- <entry>type</><entry>Input type</entry>
+ <entry>type</entry><entry>Input type</entry>
</row><row>
- <entry>norm</><entry>The current television encoding being used
+ <entry>norm</entry><entry>The current television encoding being used
if relevant for this channel.
</entry>
</row>
@@ -1229,9 +1231,9 @@ static int camera_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
<tgroup cols="2" align="left">
<tbody>
<row>
- <entry>VIDEO_VC_TUNER</><entry>Channel has a tuner.</entry>
+ <entry>VIDEO_VC_TUNER</entry><entry>Channel has a tuner.</entry>
</row><row>
- <entry>VIDEO_VC_AUDIO</><entry>Channel has audio.</entry>
+ <entry>VIDEO_VC_AUDIO</entry><entry>Channel has audio.</entry>
</row>
</tbody>
</tgroup>
@@ -1240,11 +1242,11 @@ static int camera_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
<tgroup cols="2" align="left">
<tbody>
<row>
- <entry>VIDEO_TYPE_TV</><entry>Television input.</entry>
+ <entry>VIDEO_TYPE_TV</entry><entry>Television input.</entry>
</row><row>
- <entry>VIDEO_TYPE_CAMERA</><entry>Fixed camera input.</entry>
+ <entry>VIDEO_TYPE_CAMERA</entry><entry>Fixed camera input.</entry>
</row><row>
- <entry>0</><entry>Type is unknown.</entry>
+ <entry>0</entry><entry>Type is unknown.</entry>
</row>
</tbody>
</tgroup>
@@ -1253,13 +1255,13 @@ static int camera_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
<tgroup cols="2" align="left">
<tbody>
<row>
- <entry>VIDEO_MODE_PAL</><entry>PAL encoded Television</entry>
+ <entry>VIDEO_MODE_PAL</entry><entry>PAL encoded Television</entry>
</row><row>
- <entry>VIDEO_MODE_NTSC</><entry>NTSC (US) encoded Television</entry>
+ <entry>VIDEO_MODE_NTSC</entry><entry>NTSC (US) encoded Television</entry>
</row><row>
- <entry>VIDEO_MODE_SECAM</><entry>SECAM (French) Television </entry>
+ <entry>VIDEO_MODE_SECAM</entry><entry>SECAM (French) Television </entry>
</row><row>
- <entry>VIDEO_MODE_AUTO</><entry>Automatic switching, or format does not
+ <entry>VIDEO_MODE_AUTO</entry><entry>Automatic switching, or format does not
matter</entry>
</row>
</tbody>
@@ -1339,14 +1341,14 @@ static int camera_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
<tgroup cols="2" align="left">
<tbody>
<row>
- <entry>GREY</><entry>Linear greyscale. This is for simple cameras and the
- like</>
+ <entry>GREY</entry><entry>Linear greyscale. This is for simple cameras and the
+ like</entry>
</row><row>
- <entry>RGB565</><entry>The top 5 bits hold 32 red levels, the next six bits
- hold green and the low 5 bits hold blue. </>
+ <entry>RGB565</entry><entry>The top 5 bits hold 32 red levels, the next six bits
+ hold green and the low 5 bits hold blue. </entry>
</row><row>
- <entry>RGB555</><entry>The top bit is clear. The red green and blue levels
- each occupy five bits.</>
+ <entry>RGB555</entry><entry>The top bit is clear. The red green and blue levels
+ each occupy five bits.</entry>
</row>
</tbody>
</tgroup>
@@ -1477,32 +1479,32 @@ static struct video_buffer capture_fb;
<tgroup cols="2" align="left">
<tbody>
<row>
- <entry>width</><entry>The width in pixels of the desired image. The card
- may use a smaller size if this size is not available</>
+ <entry>width</entry><entry>The width in pixels of the desired image. The card
+ may use a smaller size if this size is not available</entry>
</row><row>
- <entry>height</><entry>The height of the image. The card may use a smaller
- size if this size is not available.</>
+ <entry>height</entry><entry>The height of the image. The card may use a smaller
+ size if this size is not available.</entry>
</row><row>
- <entry>x</><entry> The X position of the top left of the window. This
+ <entry>x</entry><entry> The X position of the top left of the window. This
is in pixels relative to the left hand edge of the
picture. Not all cards can display images aligned on
any pixel boundary. If the position is unsuitable
the card adjusts the image right and reduces the
- width.</>
+ width.</entry>
</row><row>
- <entry>y</><entry> The Y position of the top left of the window. This
+ <entry>y</entry><entry> The Y position of the top left of the window. This
is counted in pixels relative to the top edge of the
picture. As with the width if the card cannot
display starting on this line it will adjust the
- values.</>
+ values.</entry>
</row><row>
- <entry>chromakey</><entry>The colour (expressed in RGB32 format) for the
- chromakey colour if chroma keying is being used. </>
+ <entry>chromakey</entry><entry>The colour (expressed in RGB32 format) for the
+ chromakey colour if chroma keying is being used. </entry>
</row><row>
- <entry>clips</><entry>An array of rectangles that must not be drawn
- over.</>
+ <entry>clips</entry><entry>An array of rectangles that must not be drawn
+ over.</entry>
</row><row>
- <entry>clipcount</><entry>The number of clips in this array.</>
+ <entry>clipcount</entry><entry>The number of clips in this array.</entry>
</row>
</tbody>
</tgroup>
@@ -1514,11 +1516,11 @@ static struct video_buffer capture_fb;
<tgroup cols="2" align="left">
<tbody>
<row>
- <entry>x, y</><entry>Co-ordinates relative to the display</>
+ <entry>x, y</entry><entry>Co-ordinates relative to the display</entry>
</row><row>
- <entry>width, height</><entry>Width and height in pixels</>
+ <entry>width, height</entry><entry>Width and height in pixels</entry>
</row><row>
- <entry>next</><entry>A spare field for the application to use</>
+ <entry>next</entry><entry>A spare field for the application to use</entry>
</row>
</tbody>
</tgroup>
@@ -1550,9 +1552,9 @@ static struct video_buffer capture_fb;
struct video_window v;
if(copy_from_user(&amp;v, arg, sizeof(v)))
return -EFAULT;
- if(v.width > 640 || v.height > 480)
+ if(v.width &gt; 640 || v.height &gt; 480)
return -EINVAL;
- if(v.width < 16 || v.height < 16)
+ if(v.width &lt; 16 || v.height &lt; 16)
return -EINVAL;
hardware_set_key(v.chromakey);
hardware_set_window(v);
diff --git a/Documentation/DocBook/wanbook.tmpl b/Documentation/DocBook/wanbook.tmpl
index 9b18bb2d8910e..9eebcc304de4b 100644
--- a/Documentation/DocBook/wanbook.tmpl
+++ b/Documentation/DocBook/wanbook.tmpl
@@ -1,4 +1,6 @@
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V3.1//EN"[]>
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
<book id="WANGuide">
<bookinfo>
diff --git a/Documentation/DocBook/writing_usb_driver.tmpl b/Documentation/DocBook/writing_usb_driver.tmpl
index 5b02c55e56ca1..51f3bfb6fb6e3 100644
--- a/Documentation/DocBook/writing_usb_driver.tmpl
+++ b/Documentation/DocBook/writing_usb_driver.tmpl
@@ -1,4 +1,6 @@
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V3.1//EN"[]>
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
<book id="USBDeviceDriver">
<bookinfo>
diff --git a/Documentation/DocBook/z8530book.tmpl b/Documentation/DocBook/z8530book.tmpl
index d9b6cd3af2662..a507876447aa3 100644
--- a/Documentation/DocBook/z8530book.tmpl
+++ b/Documentation/DocBook/z8530book.tmpl
@@ -1,4 +1,6 @@
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V3.1//EN"[]>
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
<book id="Z85230Guide">
<bookinfo>
diff --git a/Documentation/IPMI.txt b/Documentation/IPMI.txt
index d6dcb2769e0c2..90d10e708ca3f 100644
--- a/Documentation/IPMI.txt
+++ b/Documentation/IPMI.txt
@@ -342,6 +342,7 @@ You can change this at module load time (for a module) with:
irqs=<irq1>,<irq2>... trydefaults=[0|1]
regspacings=<sp1>,<sp2>,... regsizes=<size1>,<size2>,...
regshifts=<shift1>,<shift2>,...
+ slave_addrs=<addr1>,<addr2>,...
Each of these except si_trydefaults is a list, the first item for the
first interface, second item for the second interface, etc.
@@ -383,6 +384,10 @@ Since the register size may be larger than 32 bits, the IPMI data may not
be in the lower 8 bits. The regshifts parameter give the amount to shift
the data to get to the actual IPMI data.
+The slave_addrs specifies the IPMI address of the local BMC. This is
+usually 0x20 and the driver defaults to that, but in case it's not, it
+can be specified when the driver starts up.
+
When compiled into the kernel, the addresses can be specified on the
kernel command line as:
@@ -392,6 +397,7 @@ kernel command line as:
ipmi_si.regspacings=<sp1>,<sp2>,...
ipmi_si.regsizes=<size1>,<size2>,...
ipmi_si.regshifts=<shift1>,<shift2>,...
+ ipmi_si.slave_addrs=<addr1>,<addr2>,...
It works the same as the module parameters of the same names.
diff --git a/Documentation/SecurityBugs b/Documentation/SecurityBugs
new file mode 100644
index 0000000000000..26c3b3635d9fa
--- /dev/null
+++ b/Documentation/SecurityBugs
@@ -0,0 +1,38 @@
+Linux kernel developers take security very seriously. As such, we'd
+like to know when a security bug is found so that it can be fixed and
+disclosed as quickly as possible. Please report security bugs to the
+Linux kernel security team.
+
+1) Contact
+
+The Linux kernel security team can be contacted by email at
+<security@kernel.org>. This is a private list of security officers
+who will help verify the bug report and develop and release a fix.
+It is possible that the security team will bring in extra help from
+area maintainers to understand and fix the security vulnerability.
+
+As it is with any bug, the more information provided the easier it
+will be to diagnose and fix. Please review the procedure outlined in
+REPORTING-BUGS if you are unclear about what information is helpful.
+Any exploit code is very helpful and will not be released without
+consent from the reporter unless it has already been made public.
+
+2) Disclosure
+
+The goal of the Linux kernel security team is to work with the
+bug submitter to bug resolution as well as disclosure. We prefer
+to fully disclose the bug as soon as possible. It is reasonable to
+delay disclosure when the bug or the fix is not yet fully understood,
+the solution is not well-tested or for vendor coordination. However, we
+expect these delays to be short, measurable in days, not weeks or months.
+A disclosure date is negotiated by the security team working with the
+bug submitter as well as vendors. However, the kernel security team
+holds the final say when setting a disclosure date. The timeframe for
+disclosure is from immediate (esp. if it's already publically known)
+to a few weeks. As a basic default policy, we expect report date to
+disclosure date to be on the order of 7 days.
+
+3) Non-disclosure agreements
+
+The Linux kernel security team is not a formal body and therefore unable
+to enter any non-disclosure agreements.
diff --git a/Documentation/SubmittingDrivers b/Documentation/SubmittingDrivers
index 2630629d7ab56..de3b252e717d0 100644
--- a/Documentation/SubmittingDrivers
+++ b/Documentation/SubmittingDrivers
@@ -118,13 +118,18 @@ Linux kernel mailing list:
linux-kernel@vger.kernel.org
[mail majordomo@vger.kernel.org to subscribe]
+Linux Device Drivers, Third Edition (covers 2.6.10):
+ http://lwn.net/Kernel/LDD3/ (free version)
+
Kernel traffic:
Weekly summary of kernel list activity (much easier to read)
http://www.kerneltraffic.org/kernel-traffic/
LWN.net:
Weekly summary of kernel development activity - http://lwn.net/
- 2.6 driver porting information:
+ 2.6 API changes:
+ http://lwn.net/Articles/2.6-kernel-api/
+ Porting drivers from prior kernels to 2.6:
http://lwn.net/Articles/driver-porting/
KernelTrap:
diff --git a/Documentation/aoe/aoe.txt b/Documentation/aoe/aoe.txt
index 7af899ffdc128..43e50108d0e21 100644
--- a/Documentation/aoe/aoe.txt
+++ b/Documentation/aoe/aoe.txt
@@ -6,9 +6,16 @@ The EtherDrive (R) HOWTO for users of 2.6 kernels is found at ...
CREATING DEVICE NODES
- Users of udev should find device nodes created automatically. Two
- scripts are provided in Documentation/aoe as examples of static
- device node creation for using the aoe driver.
+ Users of udev should find the block device nodes created
+ automatically, but to create all the necessary device nodes, use the
+ udev configuration rules provided in udev.txt (in this directory).
+
+ There is a udev-install.sh script that shows how to install these
+ rules on your system.
+
+ If you are not using udev, two scripts are provided in
+ Documentation/aoe as examples of static device node creation for
+ using the aoe driver.
rm -rf /dev/etherd
sh Documentation/aoe/mkdevs.sh /dev/etherd
diff --git a/Documentation/aoe/status.sh b/Documentation/aoe/status.sh
index 8934ccc4454a4..6628116d4a9f7 100644
--- a/Documentation/aoe/status.sh
+++ b/Documentation/aoe/status.sh
@@ -4,10 +4,13 @@
set -e
format="%8s\t%8s\t%8s\n"
me=`basename $0`
+sysd=${sysfs_dir:-/sys}
# printf "$format" device mac netif state
-test -z "`mount | grep sysfs`" && {
+# Suse 9.1 Pro doesn't put /sys in /etc/mtab
+#test -z "`mount | grep sysfs`" && {
+test ! -d "$sysd/block" && {
echo "$me Error: sysfs is not mounted" 1>&2
exit 1
}
@@ -16,7 +19,7 @@ test -z "`lsmod | grep '^aoe'`" && {
exit 1
}
-for d in `ls -d /sys/block/etherd* 2>/dev/null | grep -v p` end; do
+for d in `ls -d $sysd/block/etherd* 2>/dev/null | grep -v p` end; do
# maybe ls comes up empty, so we use "end"
test $d = end && continue
diff --git a/Documentation/aoe/udev-install.sh b/Documentation/aoe/udev-install.sh
new file mode 100644
index 0000000000000..861a27f98771d
--- /dev/null
+++ b/Documentation/aoe/udev-install.sh
@@ -0,0 +1,26 @@
+# install the aoe-specific udev rules from udev.txt into
+# the system's udev configuration
+#
+
+me="`basename $0`"
+
+# find udev.conf, often /etc/udev/udev.conf
+# (or environment can specify where to find udev.conf)
+#
+if test -z "$conf"; then
+ if test -r /etc/udev/udev.conf; then
+ conf=/etc/udev/udev.conf
+ else
+ conf="`find /etc -type f -name udev.conf 2> /dev/null`"
+ if test -z "$conf" || test ! -r "$conf"; then
+ echo "$me Error: no udev.conf found" 1>&2
+ exit 1
+ fi
+ fi
+fi
+
+# find the directory where udev rules are stored, often
+# /etc/udev/rules.d
+#
+rules_d="`sed -n '/^udev_rules=/{ s!udev_rules=!!; s!\"!!g; p; }' $conf`"
+test "$rules_d" && sh -xc "cp `dirname $0`/udev.txt $rules_d/60-aoe.rules"
diff --git a/Documentation/aoe/udev.txt b/Documentation/aoe/udev.txt
new file mode 100644
index 0000000000000..ab39d8bb634cf
--- /dev/null
+++ b/Documentation/aoe/udev.txt
@@ -0,0 +1,23 @@
+# These rules tell udev what device nodes to create for aoe support.
+# They may be installed along the following lines (adjusted to what
+# you see on your system).
+#
+# ecashin@makki ~$ su
+# Password:
+# bash# find /etc -type f -name udev.conf
+# /etc/udev/udev.conf
+# bash# grep udev_rules= /etc/udev/udev.conf
+# udev_rules="/etc/udev/rules.d/"
+# bash# ls /etc/udev/rules.d/
+# 10-wacom.rules 50-udev.rules
+# bash# cp /path/to/linux-2.6.xx/Documentation/aoe/udev.txt \
+# /etc/udev/rules.d/60-aoe.rules
+#
+
+# aoe char devices
+SUBSYSTEM="aoe", KERNEL="discover", NAME="etherd/%k", GROUP="disk", MODE="0220"
+SUBSYSTEM="aoe", KERNEL="err", NAME="etherd/%k", GROUP="disk", MODE="0440"
+SUBSYSTEM="aoe", KERNEL="interfaces", NAME="etherd/%k", GROUP="disk", MODE="0220"
+
+# aoe block devices
+KERNEL="etherd*", NAME="%k", GROUP="disk"
diff --git a/Documentation/arm/IXP2000 b/Documentation/arm/IXP2000
index 969f165932f25..e0148b6b2c404 100644
--- a/Documentation/arm/IXP2000
+++ b/Documentation/arm/IXP2000
@@ -45,7 +45,7 @@ MAILING LISTS REGARDING THE INTEL SDK.
4. Usage Notes
-- The IXP2000 platforms ususally have rather complex PCI bus topologies
+- The IXP2000 platforms usually have rather complex PCI bus topologies
with large memory space requirements. In addition, b/c of the way the
Intel SDK is designed, devices are enumerated in a very specific
way. B/c of this this, we use "pci=firmware" option in the kernel
diff --git a/Documentation/arm/Samsung-S3C24XX/H1940.txt b/Documentation/arm/Samsung-S3C24XX/H1940.txt
new file mode 100644
index 0000000000000..d6b1de92b1115
--- /dev/null
+++ b/Documentation/arm/Samsung-S3C24XX/H1940.txt
@@ -0,0 +1,40 @@
+ HP IPAQ H1940
+ =============
+
+http://www.handhelds.org/projects/h1940.html
+
+Introduction
+------------
+
+ The HP H1940 is a S3C2410 based handheld device, with
+ bluetooth connectivity.
+
+
+Support
+-------
+
+ A variety of information is available
+
+ handhelds.org project page:
+
+ http://www.handhelds.org/projects/h1940.html
+
+ handhelds.org wiki page:
+
+ http://handhelds.org/moin/moin.cgi/HpIpaqH1940
+
+ Herbert Pötzl pages:
+
+ http://vserver.13thfloor.at/H1940/
+
+
+Maintainers
+-----------
+
+ This project is being maintained and developed by a variety
+ of people, including Ben Dooks, Arnaud Patard, and Herbert Pötzl.
+
+ Thanks to the many others who have also provided support.
+
+
+(c) 2005 Ben Dooks \ No newline at end of file
diff --git a/Documentation/arm/Samsung-S3C24XX/Overview.txt b/Documentation/arm/Samsung-S3C24XX/Overview.txt
index 5a05c2c72b291..3af4d29a89388 100644
--- a/Documentation/arm/Samsung-S3C24XX/Overview.txt
+++ b/Documentation/arm/Samsung-S3C24XX/Overview.txt
@@ -7,8 +7,8 @@ Introduction
------------
The Samsung S3C24XX range of ARM9 System-on-Chip CPUs are supported
- by the 's3c2410' architecture of ARM Linux. Currently the S3C2410 is
- the only supported CPU in this range.
+ by the 's3c2410' architecture of ARM Linux. Currently the S3C2410 and
+ the S3C2440 are supported CPUs.
Configuration
@@ -36,6 +36,10 @@ Machines
Samsung's own development board, geared for PDA work.
+ Samsung/Meritech SMDK2440
+
+ The S3C2440 compatible version of the SMDK2440
+
Thorcom VR1000
Custom embedded board
@@ -44,12 +48,41 @@ Machines
Handheld (IPAQ), available in several varieties
-
HP iPAQ rx3715
S3C2440 based IPAQ, with a number of variations depending on
features shipped.
+ Acer N30
+
+ A S3C2410 based PDA from Acer. There is a Wiki page at
+ http://handhelds.org/moin/moin.cgi/AcerN30Documentation .
+
+
+Adding New Machines
+-------------------
+
+ The archicture has been designed to support as many machines as can
+ be configured for it in one kernel build, and any future additions
+ should keep this in mind before altering items outside of their own
+ machine files.
+
+ Machine definitions should be kept in linux/arch/arm/mach-s3c2410,
+ and there are a number of examples that can be looked at.
+
+ Read the kernel patch submission policies as well as the
+ Documentation/arm directory before submitting patches. The
+ ARM kernel series is managed by Russell King, and has a patch system
+ located at http://www.arm.linux.org.uk/developer/patches/
+ as well as mailing lists that can be found from the same site.
+
+ As a courtesy, please notify <ben-linux@fluff.org> of any new
+ machines or other modifications.
+
+ Any large scale modifications, or new drivers should be discussed
+ on the ARM kernel mailing list (linux-arm-kernel) before being
+ attempted.
+
NAND
----
@@ -98,6 +131,9 @@ Port Contributors
Klaus Fetscher
Dimitry Andric
Shannon Holland
+ Guillaume Gourat (NexVision)
+ Christer Weinigel (wingel) (Acer N30)
+ Lucas Correia Villa Real (S3C2400 port)
Document Changes
@@ -108,6 +144,11 @@ Document Changes
25 Oct 2004 - BJD - Added Dimitry Andric to list of contributors
25 Oct 2004 - BJD - Updated the MTD from the 2.6.9 merge
21 Jan 2005 - BJD - Added rx3715, added Shannon to contributors
+ 10 Feb 2005 - BJD - Added Guillaume Gourat to contributors
+ 02 Mar 2005 - BJD - Added SMDK2440 to list of machines
+ 06 Mar 2005 - BJD - Added Christer Weinigel
+ 08 Mar 2005 - BJD - Added LCVR to list of people, updated introduction
+ 08 Mar 2005 - BJD - Added section on adding machines
Document Author
---------------
diff --git a/Documentation/arm/Samsung-S3C24XX/SMDK2440.txt b/Documentation/arm/Samsung-S3C24XX/SMDK2440.txt
new file mode 100644
index 0000000000000..32e1eae6a25fd
--- /dev/null
+++ b/Documentation/arm/Samsung-S3C24XX/SMDK2440.txt
@@ -0,0 +1,56 @@
+ Samsung/Meritech SMDK2440
+ =========================
+
+Introduction
+------------
+
+ The SMDK2440 is a two part evaluation board for the Samsung S3C2440
+ processor. It includes support for LCD, SmartMedia, Audio, SD and
+ 10MBit Ethernet, and expansion headers for various signals, including
+ the camera and unused GPIO.
+
+
+Configuration
+-------------
+
+ To set the default configuration, use `make smdk2440_defconfig` which
+ will configure the common features of this board, or use
+ `make s3c2410_config` to include support for all s3c2410/s3c2440 machines
+
+
+Support
+-------
+
+ Ben Dooks' SMDK2440 site at http://www.fluff.org/ben/smdk2440/ which
+ includes linux based USB download tools.
+
+ Some of the h1940 patches that can be found from the H1940 project
+ site at http://www.handhelds.org/projects/h1940.html can also be
+ applied to this board.
+
+
+Peripherals
+-----------
+
+ There is no current support for any of the extra peripherals on the
+ base-board itself.
+
+
+MTD
+---
+
+ The NAND flash should be supported by the in kernel MTD NAND support,
+ NOR flash will be added later.
+
+
+Maintainers
+-----------
+
+ This board is being maintained by Ben Dooks, for more info, see
+ http://www.fluff.org/ben/smdk2440/
+
+ Many thanks to Dimitry Andric of TomTom for the loan of the SMDK2440,
+ and to Simtec Electronics for allowing me time to work on this.
+
+
+(c) 2004 Ben Dooks \ No newline at end of file
diff --git a/Documentation/cachetlb.txt b/Documentation/cachetlb.txt
index 9e2f988a80097..e132fb1163b07 100644
--- a/Documentation/cachetlb.txt
+++ b/Documentation/cachetlb.txt
@@ -142,6 +142,11 @@ changes occur:
The ia64 sn2 platform is one example of a platform
that uses this interface.
+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.
+
Next, we have the cache flushing interfaces. In general, when Linux
is changing an existing virtual-->physical mapping to a new value,
@@ -155,7 +160,7 @@ the sequence will be in one of the following forms:
change_range_of_page_tables(mm, start, end);
flush_tlb_range(vma, start, end);
- 3) flush_cache_page(vma, addr);
+ 3) flush_cache_page(vma, addr, pfn);
set_pte(pte_pointer, new_pte_val);
flush_tlb_page(vma, addr);
@@ -203,7 +208,7 @@ Here are the routines, one by one:
call flush_cache_page (see below) for each entry which may be
modified.
-3) void flush_cache_page(struct vm_area_struct *vma, unsigned long addr)
+3) void flush_cache_page(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn)
This time we need to remove a PAGE_SIZE sized range
from the cache. The 'vma' is the backing structure used by
@@ -213,8 +218,14 @@ Here are the routines, one by one:
executable (and thus could be in the 'instruction cache' in
"Harvard" type cache layouts).
+ The 'pfn' indicates the physical page frame (shift this value
+ left by PAGE_SHIFT to get the physical address) that 'addr'
+ translates to. It is this mapping which should be removed from
+ the cache.
+
After running, there will be no entries in the cache for
- 'vma->vm_mm' for virtual address 'addr'.
+ 'vma->vm_mm' for virtual address 'addr' which translates
+ to 'pfn'.
This is used primarily during fault processing.
diff --git a/Documentation/cciss.txt b/Documentation/cciss.txt
index 74589c53a0c4a..d599beb9df8a7 100644
--- a/Documentation/cciss.txt
+++ b/Documentation/cciss.txt
@@ -15,6 +15,8 @@ This driver is known to work with the following cards:
* SA 6400 U320 Expansion Module
* SA 6i
* SA P600
+ * SA P800
+ * SA E400
If nodes are not already created in the /dev/cciss directory, run as root:
diff --git a/Documentation/cdrom/mcd b/Documentation/cdrom/mcd
deleted file mode 100644
index 39537f9f0b085..0000000000000
--- a/Documentation/cdrom/mcd
+++ /dev/null
@@ -1,4 +0,0 @@
-This driver does not support XA or MultiSession CDs (PhotoCDs). Use the
-experimental driver mcdx.c for that.
-
-You can use mcd for one interface, and mcdx for another.
diff --git a/Documentation/cdrom/mcdx b/Documentation/cdrom/mcdx
index 4ea89e32373e7..2bac4b7ff6da8 100644
--- a/Documentation/cdrom/mcdx
+++ b/Documentation/cdrom/mcdx
@@ -1,16 +1,3 @@
-This is a first attempt to create an `improved' driver for the Mitsumi drives.
-It is able to "live together" with mcd.c, if you have at least two Mitsumi
-drives: each driver can use its own drive.
-
-To allow this "coexistence" as long as mcdx.c is not a superset of mcd.c,
-this driver has to use its own device files. We use MAJOR 20 for it. So,
-you have to do
-
- # mknod /dev/mcdx0 b 20 0
- # mknod /dev/mcdx1 b 20 1
-
-and so on, one entry for each drive to support, once.
-
If you are using the driver as a module, you can specify your ports and IRQs
like
@@ -25,9 +12,7 @@ This driver:
ordinary CDs;
o supports up to 5 drives (of course, you'll need free
IRQs, i/o ports and slots);
- o uses much less kernel memory than the standard mcd driver
- (no extra driver internal buffers!).
- o plays audio (like the `old' driver, I hope)
+ o plays audio
This version doesn't support yet:
diff --git a/Documentation/cdrom/packet-writing.txt b/Documentation/cdrom/packet-writing.txt
index b402e4c949dab..3d44c561fe6d9 100644
--- a/Documentation/cdrom/packet-writing.txt
+++ b/Documentation/cdrom/packet-writing.txt
@@ -62,6 +62,14 @@ generates aligned writes.
# mount /dev/pktcdvd/dev_name /cdrom -t udf -o rw,noatime
+Packet writing for DVD-RAM media
+--------------------------------
+
+DVD-RAM discs are random writable, so using the pktcdvd driver is not
+necessary. However, using the pktcdvd driver can improve performance
+in the same way it does for DVD+RW media.
+
+
Notes
-----
diff --git a/Documentation/cpusets.txt b/Documentation/cpusets.txt
new file mode 100644
index 0000000000000..1ad26d2c20ae6
--- /dev/null
+++ b/Documentation/cpusets.txt
@@ -0,0 +1,415 @@
+ CPUSETS
+ -------
+
+Copyright (C) 2004 BULL SA.
+Written by Simon.Derr@bull.net
+
+Portions Copyright (c) 2004 Silicon Graphics, Inc.
+Modified by Paul Jackson <pj@sgi.com>
+
+CONTENTS:
+=========
+
+1. Cpusets
+ 1.1 What are cpusets ?
+ 1.2 Why are cpusets needed ?
+ 1.3 How are cpusets implemented ?
+ 1.4 How do I use cpusets ?
+2. Usage Examples and Syntax
+ 2.1 Basic Usage
+ 2.2 Adding/removing cpus
+ 2.3 Setting flags
+ 2.4 Attaching processes
+3. Questions
+4. Contact
+
+1. Cpusets
+==========
+
+1.1 What are cpusets ?
+----------------------
+
+Cpusets provide a mechanism for assigning a set of CPUs and Memory
+Nodes to a set of tasks.
+
+Cpusets constrain the CPU and Memory placement of tasks to only
+the resources within a tasks current cpuset. They form a nested
+hierarchy visible in a virtual file system. These are the essential
+hooks, beyond what is already present, required to manage dynamic
+job placement on large systems.
+
+Each task has a pointer to a cpuset. Multiple tasks may reference
+the same cpuset. Requests by a task, using the sched_setaffinity(2)
+system call to include CPUs in its CPU affinity mask, and using the
+mbind(2) and set_mempolicy(2) system calls to include Memory Nodes
+in its memory policy, are both filtered through that tasks cpuset,
+filtering out any CPUs or Memory Nodes not in that cpuset. The
+scheduler will not schedule a task on a CPU that is not allowed in
+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.
+
+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,
+specify and query to which cpuset a task is assigned, and list the
+task pids assigned to a cpuset.
+
+
+1.2 Why are cpusets needed ?
+----------------------------
+
+The management of large computer systems, with many processors (CPUs),
+complex memory cache hierarchies and multiple Memory Nodes having
+non-uniform access times (NUMA) presents additional challenges for
+the efficient scheduling and memory placement of processes.
+
+Frequently more modest sized systems can be operated with adequate
+efficiency just by letting the operating system automatically share
+the available CPU and Memory resources amongst the requesting tasks.
+
+But larger systems, which benefit more from careful processor and
+memory placement to reduce memory access times and contention,
+and which typically represent a larger investment for the customer,
+can benefit from explictly placing jobs on properly sized subsets of
+the system.
+
+This can be especially valuable on:
+
+ * Web Servers running multiple instances of the same web application,
+ * Servers running different applications (for instance, a web server
+ and a database), or
+ * NUMA systems running large HPC applications with demanding
+ performance characteristics.
+
+These subsets, or "soft partitions" must be able to be dynamically
+adjusted, as the job mix changes, without impacting other concurrently
+executing jobs.
+
+The kernel cpuset patch provides the minimum essential kernel
+mechanisms required to efficiently implement such subsets. It
+leverages existing CPU and Memory Placement facilities in the Linux
+kernel to avoid any additional impact on the critical scheduler or
+memory allocator code.
+
+
+1.3 How are cpusets implemented ?
+---------------------------------
+
+Cpusets provide a Linux kernel (2.6.7 and above) mechanism to constrain
+which CPUs and Memory Nodes are used by a process or set of processes.
+
+The Linux kernel already has a pair of mechanisms to specify on which
+CPUs a task may be scheduled (sched_setaffinity) and on which Memory
+Nodes it may obtain memory (mbind, set_mempolicy).
+
+Cpusets extends these two mechanisms as follows:
+
+ - Cpusets are sets of allowed CPUs and Memory Nodes, known to the
+ kernel.
+ - Each task in the system is attached to a cpuset, via a pointer
+ in the task structure to a reference counted cpuset structure.
+ - Calls to sched_setaffinity are filtered to just those CPUs
+ allowed in that tasks cpuset.
+ - Calls to mbind and set_mempolicy are filtered to just
+ those Memory Nodes allowed in that tasks cpuset.
+ - The root cpuset contains all the systems CPUs and Memory
+ Nodes.
+ - For any cpuset, one can define child cpusets containing a subset
+ of the parents CPU and Memory Node resources.
+ - The hierarchy of cpusets can be mounted at /dev/cpuset, for
+ browsing and manipulation from user space.
+ - A cpuset may be marked exclusive, which ensures that no other
+ cpuset (except direct ancestors and descendents) may contain
+ any overlapping CPUs or Memory Nodes.
+ - You can list all the tasks (by pid) attached to any cpuset.
+
+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 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.
+ - in sched.c migrate_all_tasks(), to keep migrating tasks within
+ the CPUs allowed by their cpuset, if possible.
+ - 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 vmscan.c, to restrict page recovery to the current cpuset.
+
+In addition a new file system, of type "cpuset" may be mounted,
+typically at /dev/cpuset, to enable browsing and modifying the cpusets
+presently known to the kernel. No new system calls are added for
+cpusets - all support for querying and modifying cpusets is via
+this cpuset file system.
+
+Each task under /proc has an added file named 'cpuset', displaying
+the cpuset name, as the path relative to the root of the cpuset file
+system.
+
+The /proc/<pid>/status file for each task has two added lines,
+displaying the tasks cpus_allowed (on which CPUs it may be scheduled)
+and mems_allowed (on which Memory Nodes it may obtain memory),
+in the format seen in the following example:
+
+ Cpus_allowed: ffffffff,ffffffff,ffffffff,ffffffff
+ Mems_allowed: ffffffff,ffffffff
+
+Each cpuset is represented by a directory in the cpuset file system
+containing the following files describing that cpuset:
+
+ - cpus: list of CPUs in that cpuset
+ - mems: list of Memory Nodes in that cpuset
+ - cpu_exclusive flag: is cpu placement exclusive?
+ - mem_exclusive flag: is memory placement exclusive?
+ - tasks: list of tasks (by pid) attached to that cpuset
+
+New cpusets are created using the mkdir system call or shell
+command. The properties of a cpuset, such as its flags, allowed
+CPUs and Memory Nodes, and attached tasks, are modified by writing
+to the appropriate file in that cpusets directory, as listed above.
+
+The named hierarchical structure of nested cpusets allows partitioning
+a large system into nested, dynamically changeable, "soft-partitions".
+
+The attachment of each task, automatically inherited at fork by any
+children of that task, to a cpuset allows organizing the work load
+on a system into related sets of tasks such that each set is constrained
+to using the CPUs and Memory Nodes of a particular cpuset. A task
+may be re-attached to any other cpuset, if allowed by the permissions
+on the necessary cpuset file system directories.
+
+Such management of a system "in the large" integrates smoothly with
+the detailed placement done on individual tasks and memory regions
+using the sched_setaffinity, mbind and set_mempolicy system calls.
+
+The following rules apply to each cpuset:
+
+ - Its CPUs and Memory Nodes must be a subset of its parents.
+ - It can only be marked exclusive if its parent is.
+ - If its cpu or memory is exclusive, they may not overlap any sibling.
+
+These rules, and the natural hierarchy of cpusets, enable efficient
+enforcement of the exclusive guarantee, without having to scan all
+cpusets every time any of them change to ensure nothing overlaps a
+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 ?
+--------------------------
+
+In order to minimize the impact of cpusets on critical kernel
+code, such as the scheduler, and due to the fact that the kernel
+does not support one task updating the memory placement of another
+task directly, the impact on a task of changing its cpuset CPU
+or Memory Node placement, or of changing to which cpuset a task
+is attached, is subtle.
+
+If a cpuset has its Memory Nodes modified, then for each task attached
+to that cpuset, the next time that the kernel attempts to allocate
+a page of memory for that task, the kernel will notice the change
+in the tasks cpuset, and update its per-task memory placement to
+remain within the new cpusets memory placement. If the task was using
+mempolicy MPOL_BIND, and the nodes to which it was bound overlap with
+its new cpuset, then the task will continue to use whatever subset
+of MPOL_BIND nodes are still allowed in the new cpuset. If the task
+was using MPOL_BIND and now none of its MPOL_BIND nodes are allowed
+in the new cpuset, then the task will be essentially treated as if it
+was MPOL_BIND bound to the new cpuset (even though its numa placement,
+as queried by get_mempolicy(), doesn't change). If a task is moved
+from one cpuset to another, then the kernel will adjust the tasks
+memory placement, as above, the next time that the kernel attempts
+to allocate a page of memory for that task.
+
+If a cpuset has its CPUs modified, then each task using that
+cpuset does _not_ change its behavior automatically. In order to
+minimize the impact on the critical scheduling code in the kernel,
+tasks will continue to use their prior CPU placement until they
+are rebound to their cpuset, by rewriting their pid to the 'tasks'
+file of their cpuset. If a task had been bound to some subset of its
+cpuset using the sched_setaffinity() call, and if any of that subset
+is still allowed in its new cpuset settings, then the task will be
+restricted to the intersection of the CPUs it was allowed on before,
+and its new cpuset CPU placement. If, on the other hand, there is
+no overlap between a tasks prior placement and its new cpuset CPU
+placement, then the task will be allowed to run on any CPU allowed
+in its new cpuset. If a task is moved from one cpuset to another,
+its CPU placement is updated in the same way as if the tasks pid is
+rewritten to the 'tasks' file of its current cpuset.
+
+In summary, the memory placement of a task whose cpuset is changed is
+updated by the kernel, on the next allocation of a page for that task,
+but the processor placement is not updated, until that tasks pid is
+rewritten to the 'tasks' file of its cpuset. This is done to avoid
+impacting the scheduler code in the kernel with a check for changes
+in a tasks processor placement.
+
+There is an exception to the above. If hotplug funtionality is used
+to remove all the CPUs that are currently assigned to a cpuset,
+then the kernel will automatically update the cpus_allowed of all
+tasks attached to CPUs in that cpuset with the online CPUs of the
+nearest parent cpuset that still has some CPUs online. When memory
+hotplug functionality for removing Memory Nodes is available, a
+similar exception is expected to apply there as well. In general,
+the kernel prefers to violate cpuset placement, over starving a task
+that has had all its allowed CPUs or Memory Nodes taken offline. User
+code should reconfigure cpusets to only refer to online CPUs and Memory
+Nodes when using hotplug to add or remove such resources.
+
+There is a second exception to the above. GFP_ATOMIC requests are
+kernel internal allocations that must be satisfied, immediately.
+The kernel may drop some request, in rare cases even panic, if a
+GFP_ATOMIC alloc fails. If the request cannot be satisfied within
+the current tasks cpuset, then we relax the cpuset, and look for
+memory anywhere we can find it. It's better to violate the cpuset
+than stress the kernel.
+
+To start a new job that is to be contained within a cpuset, the steps are:
+
+ 1) mkdir /dev/cpuset
+ 2) mount -t cpuset none /dev/cpuset
+ 3) Create the new cpuset by doing mkdir's and write's (or echo's) in
+ the /dev/cpuset virtual file system.
+ 4) Start a task that will be the "founding father" of the new job.
+ 5) Attach that task to the new cpuset by writing its pid to the
+ /dev/cpuset tasks file for that cpuset.
+ 6) fork, exec or clone the job tasks from this founding father task.
+
+For example, the following sequence of commands will setup a cpuset
+named "Charlie", containing just CPUs 2 and 3, and Memory Node 1,
+and then start a subshell 'sh' in that cpuset:
+
+ mount -t cpuset none /dev/cpuset
+ cd /dev/cpuset
+ mkdir Charlie
+ cd Charlie
+ /bin/echo 2-3 > cpus
+ /bin/echo 1 > mems
+ /bin/echo $$ > tasks
+ sh
+ # The subshell 'sh' is now running in cpuset Charlie
+ # The next line should display '/Charlie'
+ cat /proc/self/cpuset
+
+In the case that a change of cpuset includes wanting to move already
+allocated memory pages, consider further the work of IWAMOTO
+Toshihiro <iwamoto@valinux.co.jp> for page remapping and memory
+hotremoval, which can be found at:
+
+ http://people.valinux.co.jp/~iwamoto/mh.html
+
+The integration of cpusets with such memory migration is not yet
+available.
+
+In the future, a C library interface to cpusets will likely be
+available. For now, the only way to query or modify cpusets is
+via the cpuset file system, using the various cd, mkdir, echo, cat,
+rmdir commands from the shell, or their equivalent from C.
+
+The sched_setaffinity calls can also be done at the shell prompt using
+SGI's runon or Robert Love's taskset. The mbind and set_mempolicy
+calls can be done at the shell prompt using the numactl command
+(part of Andi Kleen's numa package).
+
+2. Usage Examples and Syntax
+============================
+
+2.1 Basic Usage
+---------------
+
+Creating, modifying, using the cpusets can be done through the cpuset
+virtual filesystem.
+
+To mount it, type:
+# mount -t cpuset none /dev/cpuset
+
+Then under /dev/cpuset you can find a tree that corresponds to the
+tree of the cpusets in the system. For instance, /dev/cpuset
+is the cpuset that holds the whole system.
+
+If you want to create a new cpuset under /dev/cpuset:
+# cd /dev/cpuset
+# mkdir my_cpuset
+
+Now you want to do something with this cpuset.
+# cd my_cpuset
+
+In this directory you can find several files:
+# ls
+cpus cpu_exclusive mems mem_exclusive tasks
+
+Reading them will give you information about the state of this cpuset:
+the CPUs and Memory Nodes it can use, the processes that are using
+it, its properties. By writing to these files you can manipulate
+the cpuset.
+
+Set some flags:
+# /bin/echo 1 > cpu_exclusive
+
+Add some cpus:
+# /bin/echo 0-7 > cpus
+
+Now attach your shell to this cpuset:
+# /bin/echo $$ > tasks
+
+You can also create cpusets inside your cpuset by using mkdir in this
+directory.
+# mkdir my_sub_cs
+
+To remove a cpuset, just use rmdir:
+# rmdir my_sub_cs
+This will fail if the cpuset is in use (has cpusets inside, or has
+processes attached).
+
+2.2 Adding/removing cpus
+------------------------
+
+This is the syntax to use when writing in the cpus or mems files
+in cpuset directories:
+
+# /bin/echo 1-4 > cpus -> set cpus list to cpus 1,2,3,4
+# /bin/echo 1,2,3,4 > cpus -> set cpus list to cpus 1,2,3,4
+
+2.3 Setting flags
+-----------------
+
+The syntax is very simple:
+
+# /bin/echo 1 > cpu_exclusive -> set flag 'cpu_exclusive'
+# /bin/echo 0 > cpu_exclusive -> unset flag 'cpu_exclusive'
+
+2.4 Attaching processes
+-----------------------
+
+# /bin/echo PID > tasks
+
+Note that it is PID, not PIDs. You can only attach ONE task at a time.
+If you have several tasks to attach, you have to do it one after another:
+
+# /bin/echo PID1 > tasks
+# /bin/echo PID2 > tasks
+ ...
+# /bin/echo PIDn > tasks
+
+
+3. Questions
+============
+
+Q: what's up with this '/bin/echo' ?
+A: bash's builtin 'echo' command does not check calls to write() against
+ errors. If you use it in the cpuset file system, you won't be
+ able to tell whether a command succeeded or failed.
+
+Q: When I attach processes, only the first of the line gets really attached !
+A: We can only return one error code per call to write(). So you should also
+ put only ONE pid.
+
+4. Contact
+==========
+
+Web: http://www.bullopensource.org/cpuset
diff --git a/Documentation/crypto/api-intro.txt b/Documentation/crypto/api-intro.txt
index fa0c8b9749505..a2d5b49007729 100644
--- a/Documentation/crypto/api-intro.txt
+++ b/Documentation/crypto/api-intro.txt
@@ -234,6 +234,9 @@ Whirlpool algorithm contributors:
Anubis algorithm contributors:
Aaron Grothe
+Tiger algorithm contributors:
+ Aaron Grothe
+
Generic scatterwalk code by Adam J. Richter <adam@yggdrasil.com>
Please send any credits updates or corrections to:
diff --git a/Documentation/devices.txt b/Documentation/devices.txt
index 9d0cdb431f96a..bb67cf25010ed 100644
--- a/Documentation/devices.txt
+++ b/Documentation/devices.txt
@@ -2754,6 +2754,8 @@ Your cooperation is appreciated.
50 = /dev/ttyIOC40 Altix serial card
...
81 = /dev/ttyIOC431 Altix serial card
+ 82 = /dev/ttyVR0 NEC VR4100 series SIU
+ 83 = /dev/ttyVR1 NEC VR4100 series DSIU
205 char Low-density serial ports (alternate device)
0 = /dev/culu0 Callout device for ttyLU0
@@ -2788,6 +2790,8 @@ Your cooperation is appreciated.
50 = /dev/cuioc40 Callout device for ttyIOC40
...
81 = /dev/cuioc431 Callout device for ttyIOC431
+ 82 = /dev/cuvr0 Callout device for ttyVR0
+ 83 = /dev/cuvr1 Callout device for ttyVR1
206 char OnStream SC-x0 tape devices
diff --git a/Documentation/dvb/README.dibusb b/Documentation/dvb/README.dibusb
index be4b5e2770c8c..7a9e958513f30 100644
--- a/Documentation/dvb/README.dibusb
+++ b/Documentation/dvb/README.dibusb
@@ -1,7 +1,7 @@
-Documentation for dib3000mb frontend driver and dibusb device driver
+Documentation for dib3000* frontend drivers and dibusb device driver
====================================================================
-Copyright (C) 2004 Patrick Boettcher (patrick.boettcher@desy.de),
+Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de),
dibusb and dib3000mb/mc drivers based on GPL code, which has
@@ -46,7 +46,7 @@ Produced and reselled by KWorld:
Others:
-------
-- Ultima Electronic/Artec T1 USB TVBOX (AN2135, AN2235, AN2235 with Panasonic Tuner)
+- Ultima Electronic/Artec T1 USB TVBOX (AN2135, AN2235, AN2235 with Panasonic Tuner)
http://82.161.246.249/products-tvbox.html
- Compro Videomate DVB-U2000 - DVB-T USB (2)
@@ -74,19 +74,27 @@ Supported devices USB2.0
- Artec T1 USB TVBOX (FX2) (2)
+- Hauppauge WinTV NOVA-T USB2
+ http://www.hauppauge.com/
+
+- KWorld/ADSTech Instant DVB-T USB2.0 (DiB3000M-B)
+
- DiBcom USB2.0 DVB-T reference device (non-public)
1) It is working almost.
-2) No test reports received yet.
+2) No test reports received yet.
0. NEWS:
- 2004-01-13 - moved the mirrored pid_filter_table back to dvb-dibusb
+ 2005-02-11 - added support for the KWorld/ADSTech Instant DVB-T USB2.0. Thanks a lot to Joachim von Caron
+ 2005-02-02 - added support for the Hauppauge Win-TV Nova-T USB2
+ 2005-01-31 - distorted streaming is finally gone for USB1.1 devices
+ 2005-01-13 - moved the mirrored pid_filter_table back to dvb-dibusb
- first almost working version for HanfTek UMT-010
- - found out, that Yakumo/HAMA/Typhoon are predessors of the HanfTek
- 2004-01-10 - refactoring completed, now everything is very delightful
+ - found out, that Yakumo/HAMA/Typhoon are predessors of the HanfTek UMT-010
+ 2005-01-10 - refactoring completed, now everything is very delightful
- tuner quirks for some weird devices (Artec T1 AN2235 device has sometimes a
- Panasonic Tuner assembled). Tunerprobing implemented. Thanks a lot to Gunnar Wittich.
+ Panasonic Tuner assembled). Tunerprobing implemented. Thanks a lot to Gunnar Wittich.
2004-12-29 - after several days of struggling around bug of no returning URBs fixed.
2004-12-26 - refactored the dibusb-driver, splitted into separate files
- i2c-probing enabled
@@ -106,7 +114,7 @@ Supported devices USB2.0
2004-09-28 - added support for a new device (Unkown, vendor ID is Hyper-Paltek)
2004-09-20 - added support for a new device (Compro DVB-U2000), thanks
to Amaury Demol for reporting
- - changed usb TS transfer method (several urbs, stopping transfer
+ - changed usb TS transfer method (several urbs, stopping transfer
before setting a new pid)
2004-09-13 - added support for a new device (Artec T1 USB TVBOX), thanks
to Christian Motschke for reporting
@@ -149,13 +157,20 @@ You can either use "get_dvb_firmware dibusb" to download the firmware or you
can get it directly via
for USB1.1 (AN2135)
-http://linuxtv.org/cgi-bin/cvsweb.cgi/dvb-kernel/firmware/dvb-dibusb-5.0.0.11.fw?rev=1.1&content-type=text/plain
+http://www.linuxtv.org/downloads/firmware/dvb-dibusb-5.0.0.11.fw
for USB1.1 (AN2235) (a few Artec T1 devices)
-http://linuxtv.org/cgi-bin/cvsweb.cgi/dvb-kernel/firmware/dvb-dibusb-an2235-1.fw?rev=1.1&content-type=text/plain
+http://www.linuxtv.org/downloads/firmware/dvb-dibusb-an2235-1.fw
+
+for USB2.0 (FX2) Hauppauge, DiBcom
+http://www.linuxtv.org/downloads/firmware/dvb-dibusb-6.0.0.5.fw
+
+for USB2.0 ADSTech/Kworld USB2.0
+http://www.linuxtv.org/downloads/firmware/dvb-dibusb-adstech-usb2-1.fw
+
+for USB2.0 HanfTek
+http://www.linuxtv.org/downloads/firmware/dvb-dibusb-an2235-1.fw
-for USB2.0 (FX2)
-http://linuxtv.org/cgi-bin/cvsweb.cgi/dvb-kernel/firmware/dvb-dibusb-6.0.0.5.fw?rev=1.1&content-type=text/plain
1.2. Compiling
@@ -191,13 +206,13 @@ turned on.
At this point you should be able to start a dvb-capable application. For myself
I used mplayer, dvbscan, tzap and kaxtv, they are working. Using the device
-in vdr (at least the USB2.0 one) is working.
+in vdr is working now also.
2. Known problems and bugs
-- none this time
+- Don't remove the USB device while running an DVB application, your system will die.
-2.1. Adding support for devices
+2.1. Adding support for devices
It is not possible to determine the range of devices based on the DiBcom
reference designs. This is because the reference design of DiBcom can be sold
@@ -213,56 +228,51 @@ of the device. I will add it to this list in order to make this clear to
others.
If you are familar with C you can also add the VID and PID of the device to
-the dvb-dibusb.h-file and create a patch and send it over to me or to
+the dvb-dibusb-core.c-file and create a patch and send it over to me or to
the linux-dvb mailing list, _after_ you have tried compiling and modprobing
it.
2.2. USB1.1 Bandwidth limitation
-Most of the current supported devices are USB1.1 and thus they have a
+Most of the currently supported devices are USB1.1 and thus they have a
maximum bandwidth of about 5-6 MBit/s when connected to a USB2.0 hub.
This is not enough for receiving the complete transport stream of a
DVB-T channel (which can be about 16 MBit/s). Normally this is not a
problem, if you only want to watch TV (this does not apply for HDTV),
-but watching a channel while recording another channel on the same
-frequency simply does not work. This applies to all USB1.1 DVB-T
-devices, not only dibusb)
-
-A special problem of the dibusb for the USB1.1 is, that the USB control
-IC has a problem with write accesses while having MPEG2-streaming
-enabled. When you set another pid while receiving MPEG2-TS it happens, that
-the stream is disturbed and probably data is lost (results in distortions of
-the video or strange beeps within the audio stream). DiBcom is preparing a
-firmware especially for Linux which perhaps solves the problem.
-
-Especially VDR users are victoms of this bug. VDR frequently requests new PIDs
-due the automatic scanning (introduced in 1.3.x, afaik) and epg-scan. Disabling
-these features is maybe a solution. Additionally this behaviour of VDR exceeds
-the USB1.1 bandwidth.
-
-Update:
-For the USB1.1 and VDR some work has been done (patches and comments are still
-very welcome). Maybe the problem is solved in the meantime because I now use
-the dmx_sw_filter function instead of dmx_sw_filter_packet. I hope the
+but watching a channel while recording another channel on the same
+frequency simply does not work very well. This applies to all USB1.1
+DVB-T devices, not just dibusb)
+
+Update: For the USB1.1 and VDR some work has been done (patches and comments
+are still very welcome). Maybe the problem is solved in the meantime because I
+now use the dmx_sw_filter function instead of dmx_sw_filter_packet. I hope the
linux-dvb software filter is able to get the best of the garbled TS.
+The bug, where the TS is distorted by a heavy usage of the device is gone
+definitely. All dibusb-devices I was using (Twinhan, Kworld, DiBcom) are
+working like charm now with VDR. Sometimes I even was able to record a channel
+and watch another one.
+
2.3. Comments
-Patches, comments and suggestions are very very welcome
+Patches, comments and suggestions are very very welcome.
3. Acknowledgements
Amaury Demol (ademol@dibcom.fr) and Francois Kanounnikoff from DiBcom for
- providing specs, code and help, on which the dvb-dibusb, dib3000mb and
+ providing specs, code and help, on which the dvb-dibusb, dib3000mb and
dib3000mc are based.
David Matthews for identifying a new device type (Artec T1 with AN2235)
and for extending dibusb with remote control event handling. Thank you.
Alex Woods for frequently answering question about usb and dvb
- stuff, a big thank you
+ stuff, a big thank you.
Bernd Wagner for helping with huge bug reports and discussions.
+ Gunnar Wittich and Joachim von Caron for their trust for giving me
+ root-shells on their machines to implement support for new devices.
+
Some guys on the linux-dvb mailing list for encouraging me
Peter Schildmann >peter.schildmann-nospam-at-web.de< for his
diff --git a/Documentation/dvb/contributors.txt b/Documentation/dvb/contributors.txt
index dd40ad665c502..c9d5ce3707012 100644
--- a/Documentation/dvb/contributors.txt
+++ b/Documentation/dvb/contributors.txt
@@ -72,5 +72,8 @@ Kenneth Aafløy <ke-aa@frisurf.no>
Ernst Peinlich <e.peinlich@inode.at>
for tuning/DiSEqC support for the DEC 3000-s
+Peter Beutner <p.beutner@gmx.net>
+ for the IR code for the ttusb-dec driver
+
(If you think you should be in this list, but you are not, drop a
line to the DVB mailing list)
diff --git a/Documentation/dvb/faq.txt b/Documentation/dvb/faq.txt
index 79c2ce4ca04a6..3bf51e45c9725 100644
--- a/Documentation/dvb/faq.txt
+++ b/Documentation/dvb/faq.txt
@@ -35,7 +35,7 @@ Some very frequently asked questions about linuxtv-dvb
Note: Only very recent versions of Mplayer and xine can decode.
MPEG2 transport streams (TS) directly. Then, run
'[sct]zap channelname -r' in one xterm, and keep it running,
- and start 'mplayer - < /dev/dvb/adapter0/dvr0' or
+ and start 'mplayer - < /dev/dvb/adapter0/dvr0' or
'xine stdin://mpeg2 < /dev/dvb/adapter0/dvr0' in a second xterm.
That's all far from perfect, but it seems no one has written
a nice DVB application which includes a builtin software MPEG
diff --git a/Documentation/dvb/get_dvb_firmware b/Documentation/dvb/get_dvb_firmware
index 22d410e6e6401..3ffdcb394299f 100644
--- a/Documentation/dvb/get_dvb_firmware
+++ b/Documentation/dvb/get_dvb_firmware
@@ -22,14 +22,15 @@ use File::Temp qw/ tempdir /;
use IO::Handle;
@components = ( "sp8870", "sp887x", "tda10045", "tda10046", "av7110", "dec2000t",
- "dec2540t", "dec3000s", "vp7041", "dibusb", "nxt2002" );
+ "dec2540t", "dec3000s", "vp7041", "dibusb", "nxt2002",
+ "or51211", "or51132_qam", "or51132_vsb");
# Check args
syntax() if (scalar(@ARGV) != 1);
$cid = $ARGV[0];
# Do it!
-for($i=0; $i < scalar(@components); $i++) {
+for ($i=0; $i < scalar(@components); $i++) {
if ($cid eq $components[$i]) {
$outfile = eval($cid);
die $@ if $@;
@@ -79,8 +80,8 @@ sub sp887x {
wgetfile($sourcefile, $url);
unzip($sourcefile, $tmpdir);
unshield("$tmpdir/$cabfile", $tmpdir);
- verify("$tmpdir/sc_main.mc", $hash);
- copy("$tmpdir/sc_main.mc", $outfile);
+ verify("$tmpdir/ZEnglish/sc_main.mc", $hash);
+ copy("$tmpdir/ZEnglish/sc_main.mc", $outfile);
$outfile;
}
@@ -122,9 +123,9 @@ sub tda10046 {
}
sub av7110 {
- my $sourcefile = "dvb-ttpci-01.fw-261c";
- my $url = "http://www.linuxtv.org/download/dvb/firmware/$sourcefile";
- my $hash = "7b263de6b0b92d2347319c65adc7d4fb";
+ my $sourcefile = "dvb-ttpci-01.fw-261d";
+ my $url = "http://www.linuxtv.org/downloads/firmware/$sourcefile";
+ my $hash = "603431b6259715a8e88f376a53b64e2f";
my $outfile = "dvb-ttpci-01.fw";
checkstandard();
@@ -222,7 +223,7 @@ sub vp7041 {
}
sub dibusb {
- my $url = "http://linuxtv.org/cgi-bin/cvsweb.cgi/dvb-kernel/firmware/dvb-dibusb-5.0.0.11.fw?rev=1.1&content-type=text/plain";
+ my $url = "http://www.linuxtv.org/downloads/firmware/dvb-dibusb-5.0.0.11.fw";
my $outfile = "dvb-dibusb-5.0.0.11.fw";
my $hash = "fa490295a527360ca16dcdf3224ca243";
@@ -251,6 +252,45 @@ sub nxt2002 {
$outfile;
}
+sub or51211 {
+ my $fwfile = "dvb-fe-or51211.fw";
+ my $url = "http://linuxtv.org/downloads/firmware/$fwfile";
+ my $hash = "d830949c771a289505bf9eafc225d491";
+
+ checkstandard();
+
+ wgetfile($fwfile, $url);
+ verify($fwfile, $hash);
+
+ $fwfile;
+}
+
+sub or51132_qam {
+ my $fwfile = "dvb-fe-or51132-qam.fw";
+ my $url = "http://linuxtv.org/downloads/firmware/$fwfile";
+ my $hash = "7702e8938612de46ccadfe9b413cb3b5";
+
+ checkstandard();
+
+ wgetfile($fwfile, $url);
+ verify($fwfile, $hash);
+
+ $fwfile;
+}
+
+sub or51132_vsb {
+ my $fwfile = "dvb-fe-or51132-vsb.fw";
+ my $url = "http://linuxtv.org/downloads/firmware/$fwfile";
+ my $hash = "c16208e02f36fc439a557ad4c613364a";
+
+ checkstandard();
+
+ wgetfile($fwfile, $url);
+ verify($fwfile, $hash);
+
+ $fwfile;
+}
+
# ---------------------------------------------------------------
# Utilities
@@ -292,7 +332,7 @@ sub unzip {
sub unshield {
my ($sourcefile, $todir) = @_;
- system("unshield -d \"$todir\" \"$sourcefile\" > /dev/null" ) and die ("unshield failed - unable to extract firmware");
+ system("unshield x -d \"$todir\" \"$sourcefile\" > /dev/null" ) and die ("unshield failed - unable to extract firmware");
}
sub verify {
diff --git a/Documentation/dvb/readme.txt b/Documentation/dvb/readme.txt
index a60c27d43b79a..754c98c6ad942 100644
--- a/Documentation/dvb/readme.txt
+++ b/Documentation/dvb/readme.txt
@@ -5,8 +5,9 @@ The main development site and CVS repository for these
drivers is http://linuxtv.org/.
The developer mailing list linux-dvb is also hosted there,
-see http://linuxtv.org/mailinglists.xml. Please check
-the archive http://linuxtv.org/mailinglists/linux-dvb/
+see http://linuxtv.org/lists.php. Please check
+the archive http://linuxtv.org/pipermail/linux-dvb/
+and the Wiki http://linuxtv.org/wiki/
before asking newbie questions on the list.
API documentation, utilities and test/example programs
@@ -15,7 +16,7 @@ are available as part of the old driver package for Linux 2.4
We plan to split this into separate packages, but it's not
been done yet.
-http://linuxtv.org/download/dvb/
+http://linuxtv.org/downloads/
What's inside this directory:
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 2da4a39e5a316..2ea080c958bbd 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -15,3 +15,34 @@ Why: It has been unmaintained for a number of years, has unfixable
against the LSB, and can be replaced by using udev.
Who: Greg Kroah-Hartman <greg@kroah.com>
+---------------------------
+
+What: /proc/sys/cpu/*, sysctl and /proc/cpufreq interfaces to cpufreq (2.4.x interfaces)
+When: January 2005
+Files: drivers/cpufreq/: cpufreq_userspace.c, proc_intf.c
+Why: /proc/sys/cpu/* has been deprecated since inclusion of cpufreq into
+ the main kernel tree. It bloats /proc/ unnecessarily and doesn't work
+ well with the "governor"-based design of cpufreq.
+ /proc/cpufreq/* has also been deprecated for a long time and was only
+ meant for usage during 2.5. until the new sysfs-based interface became
+ ready. It has an inconsistent interface which doesn't work well with
+ userspace setting the frequency. The output from /proc/cpufreq/* can
+ be emulated using "cpufreq-info --proc" (cpufrequtils).
+ Both interfaces are superseded by the cpufreq interface in
+ /sys/devices/system/cpu/cpu%n/cpufreq/.
+Who: Dominik Brodowski <linux@brodo.de>
+
+What: ACPI S4bios support
+When: May 2005
+Why: Noone uses it, and it probably does not work, anyway. swsusp is
+ faster, more reliable, and people are actually using it.
+Who: Pavel Machek <pavel@suse.cz>
+
+---------------------------
+
+What: io_remap_page_range() (macro or function)
+When: September 2005
+Why: Replaced by io_remap_pfn_range() which allows more memory space
+ addressabilty (by using a pfn) and supports sparc & sparc64
+ iospace as part of the pfn.
+Who: Randy Dunlap <rddunlap@osdl.org>
diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking
index 2c9ce27b189de..a934baeeb33a2 100644
--- a/Documentation/filesystems/Locking
+++ b/Documentation/filesystems/Locking
@@ -104,6 +104,8 @@ prototypes:
void (*clear_inode) (struct inode *);
void (*umount_begin) (struct super_block *);
int (*show_options)(struct seq_file *, struct vfsmount *);
+ ssize_t (*quota_read)(struct super_block *, int, char *, size_t, loff_t);
+ ssize_t (*quota_write)(struct super_block *, int, const char *, size_t, loff_t);
locking rules:
All may block.
@@ -126,10 +128,17 @@ remount_fs: no yes maybe (see below)
clear_inode: no
umount_begin: yes no no
show_options: no (vfsmount->sem)
+quota_read: no no no (see below)
+quota_write: no no no (see below)
->read_inode() is not a method - it's a callback used in iget().
->remount_fs() will have the s_umount lock if it's already mounted.
When called from get_sb_single, it does NOT have the s_umount lock.
+->quota_read() and ->quota_write() functions are both guaranteed to
+be the only ones operating on the quota file by the quota code (via
+dqio_sem) (unless an admin really wants to screw up something and
+writes to quota files with quotas on). For other details about locking
+see also dquot_operations section.
--------------------------- file_system_type ---------------------------
prototypes:
@@ -442,23 +451,46 @@ in sys_read() and friends.
--------------------------- dquot_operations -------------------------------
prototypes:
- void (*initialize) (struct inode *, short);
- void (*drop) (struct inode *);
- int (*alloc_block) (const struct inode *, unsigned long, char);
+ int (*initialize) (struct inode *, int);
+ int (*drop) (struct inode *);
+ int (*alloc_space) (struct inode *, qsize_t, int);
int (*alloc_inode) (const struct inode *, unsigned long);
- void (*free_block) (const struct inode *, unsigned long);
- void (*free_inode) (const struct inode *, unsigned long);
- int (*transfer) (struct dentry *, struct iattr *);
-
-locking rules:
- BKL
-initialize: no
-drop: no
-alloc_block: yes
-alloc_inode: yes
-free_block: yes
-free_inode: yes
-transfer: no
+ int (*free_space) (struct inode *, qsize_t);
+ int (*free_inode) (const struct inode *, unsigned long);
+ int (*transfer) (struct inode *, struct iattr *);
+ int (*write_dquot) (struct dquot *);
+ int (*acquire_dquot) (struct dquot *);
+ int (*release_dquot) (struct dquot *);
+ int (*mark_dirty) (struct dquot *);
+ int (*write_info) (struct super_block *, int);
+
+These operations are intended to be more or less wrapping functions that ensure
+a proper locking wrt the filesystem and call the generic quota operations.
+
+What filesystem should expect from the generic quota functions:
+
+ FS recursion Held locks when called
+initialize: yes maybe dqonoff_sem
+drop: yes -
+alloc_space: ->mark_dirty() -
+alloc_inode: ->mark_dirty() -
+free_space: ->mark_dirty() -
+free_inode: ->mark_dirty() -
+transfer: yes -
+write_dquot: yes dqonoff_sem or dqptr_sem
+acquire_dquot: yes dqonoff_sem or dqptr_sem
+release_dquot: yes dqonoff_sem or dqptr_sem
+mark_dirty: no -
+write_info: yes dqonoff_sem
+
+FS recursion means calling ->quota_read() and ->quota_write() from superblock
+operations.
+
+->alloc_space(), ->alloc_inode(), ->free_space(), ->free_inode() are called
+only directly by the filesystem and do not call any fs functions only
+the ->mark_dirty() operation.
+
+More details about quota locking can be found in fs/dquot.c.
--------------------------- vm_operations_struct -----------------------------
prototypes:
diff --git a/Documentation/filesystems/jfs.txt b/Documentation/filesystems/jfs.txt
index b0dd2a0ad1435..3e992daf99adb 100644
--- a/Documentation/filesystems/jfs.txt
+++ b/Documentation/filesystems/jfs.txt
@@ -1,13 +1,6 @@
IBM's Journaled File System (JFS) for Linux
-JFS Homepage: http://oss.software.ibm.com/jfs/
-
-Team members
-------------
-Dave Kleikamp shaggy@austin.ibm.com
-Dave Blaschke blaschke@us.ibm.com
-Steve Best sbest@us.ibm.com
-Barry Arndt barndt@us.ibm.com
+JFS Homepage: http://jfs.sourceforge.net/
The following mount options are supported:
@@ -15,6 +8,7 @@ iocharset=name Character set to use for converting from Unicode to
ASCII. The default is to do no conversion. Use
iocharset=utf8 for UTF8 translations. This requires
CONFIG_NLS_UTF8 to be set in the kernel .config file.
+ iocharset=none specifies the default behavior explicitly.
resize=value Resize the volume to <value> blocks. JFS only supports
growing a volume, not shrinking it. This option is only
@@ -38,4 +32,4 @@ errors=panic Panic and halt the machine if an error occurs.
Please send bugs, comments, cards and letters to shaggy@austin.ibm.com.
The JFS mailing list can be subscribed to by using the link labeled
-"Mail list Subscribe" at our web page http://oss.software.ibm.com/jfs/.
+"Mail list Subscribe" at our web page http://jfs.sourceforge.net/
diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
index f3f69ad01a87e..cbe85c17176b3 100644
--- a/Documentation/filesystems/proc.txt
+++ b/Documentation/filesystems/proc.txt
@@ -1754,18 +1754,25 @@ settings contain additional options to set garbage collection parameters.
In the interface directories you'll find the following entries:
-base_reachable_time
--------------------
+base_reachable_time, base_reachable_time_ms
+-------------------------------------------
A base value used for computing the random reachable time value as specified
in RFC2461.
-retrans_time
-------------
+Expression of base_reachable_time, which is deprecated, is in seconds.
+Expression of base_reachable_time_ms is in milliseconds.
+
+retrans_time, retrans_time_ms
+-----------------------------
+
+The time between retransmitted Neighbor Solicitation messages.
+Used for address resolution and to determine if a neighbor is
+unreachable.
-The time, expressed in jiffies (1/100 sec), between retransmitted Neighbor
-Solicitation messages. Used for address resolution and to determine if a
-neighbor is unreachable.
+Expression of retrans_time, which is deprecated, is in 1/100 seconds (for
+IPv4) or in jiffies (for IPv6).
+Expression of retrans_time_ms is in milliseconds.
unres_qlen
----------
diff --git a/Documentation/i2c/porting-clients b/Documentation/i2c/porting-clients
index 18b9acef0def1..56404918eabc3 100644
--- a/Documentation/i2c/porting-clients
+++ b/Documentation/i2c/porting-clients
@@ -49,9 +49,8 @@ Technical changes:
static void lm75_update_client(struct i2c_client *client);
* [Sysctl] All sysctl stuff is of course gone (defines, ctl_table
- and functions). Instead, right after the static id definition
- line, you have to define show and set functions for each sysfs
- file. Only define set for writable values. Take a look at an
+ 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
to define the attributes for each file (this is that step that
links callback functions). Use the file names specified in
@@ -86,6 +85,7 @@ Technical changes:
Replace the sysctl directory registration by calls to
device_create_file. Move the driver initialization before any
sysfs file creation.
+ Drop client->id.
* [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
diff --git a/Documentation/i2c/writing-clients b/Documentation/i2c/writing-clients
index 011e92094c028..ad27511e3c7d7 100644
--- a/Documentation/i2c/writing-clients
+++ b/Documentation/i2c/writing-clients
@@ -344,9 +344,6 @@ detection just fails for this address, return 0.
For now, you can ignore the `flags' parameter. It is there for future use.
- /* Unique ID allocation */
- static int foo_id = 0;
-
int foo_detect_client(struct i2c_adapter *adapter, int address,
unsigned short flags, int kind)
{
@@ -482,7 +479,6 @@ For now, you can ignore the `flags' parameter. It is there for future use.
data->type = kind;
/* SENSORS ONLY END */
- new_client->id = foo_id++; /* Automatically unique */
data->valid = 0; /* Only if you use this field */
init_MUTEX(&data->update_lock); /* Only if you use this field */
@@ -642,7 +638,7 @@ contains the i2c address, so you do not have to include it. The second
parameter contains the bytes the read/write, the third the length of the
buffer. Returned is the actual number of bytes read/written.
- extern int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
+ extern int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msg,
int num);
This sends a series of messages. Each message can be a read or write,
diff --git a/Documentation/ioctl/hdio.txt b/Documentation/ioctl/hdio.txt
index c42d3b68577e7..9a7aea0636a53 100644
--- a/Documentation/ioctl/hdio.txt
+++ b/Documentation/ioctl/hdio.txt
@@ -573,26 +573,43 @@ HDIO_DRIVE_TASKFILE execute raw taskfile
EFAULT req_cmd == TASKFILE_IN_OUT (not implemented as of 2.6.8)
EPERM req_cmd == TASKFILE_MULTI_OUT and drive
multi-count not yet set.
-
+ EIO Drive failed the command.
notes:
- [1] Currently (2.6.8), both the input and output buffers are
- copied from the user and written back to the user, even when
- not used. This may be a bug.
+ [1] READ THE FOLLOWING NOTES *CAREFULLY*. THIS IOCTL IS
+ FULL OF GOTCHAS. Extreme caution should be used with using
+ this ioctl. A mistake can easily corrupt data or hang the
+ system.
+
+ [2] Both the input and output buffers are copied from the
+ user and written back to the user, even when not used.
+
+ [3] If one or more bits are set in out_flags and in_flags is
+ zero, the following values are used for in_flags.all and
+ written back into in_flags on completion.
+
+ * IDE_TASKFILE_STD_IN_FLAGS | (IDE_HOB_STD_IN_FLAGS << 8)
+ if LBA48 addressing is enabled for the drive
+ * IDE_TASKFILE_STD_IN_FLAGS
+ if CHS/LBA28
- [2] The out_flags and in_flags are returned to the user after
- the ioctl completes. Currently (2.6.8) these are the same
- as the input values, unchanged. In the future, they may have
- more significance.
+ The association between in_flags.all and each enable
+ bitfield flips depending on endianess; fortunately, TASKFILE
+ only uses inflags.b.data bit and ignores all other bits.
+ The end result is that, on any endian machines, it has no
+ effect other than modifying in_flags on completion.
- Extreme caution should be used with using this ioctl. A
- mistake can easily corrupt data or hang the system.
+ [4] The default value of SELECT is (0xa0|DEV_bit|LBA_bit)
+ except for four drives per port chipsets. For four drives
+ per port chipsets, it's (0xa0|DEV_bit|LBA_bit) for the first
+ pair and (0x80|DEV_bit|LBA_bit) for the second pair.
- The argument to the ioctl is a pointer to a region of memory
- containing a ide_task_request_t structure, followed by an
- optional buffer of data to be transmitted to the drive,
- followed by an optional buffer to receive data from the drive.
+ [5] The argument to the ioctl is a pointer to a region of
+ memory containing a ide_task_request_t structure, followed
+ by an optional buffer of data to be transmitted to the
+ drive, followed by an optional buffer to receive data from
+ the drive.
Command is passed to the disk drive via the ide_task_request_t
structure, which contains these fields:
@@ -611,11 +628,66 @@ HDIO_DRIVE_TASKFILE execute raw taskfile
out_size output (user->drive) buffer size, bytes
in_size input (drive->user) buffer size, bytes
- This ioctl does not necessarily respect all flags in the
- out_flags and in_flags values -- some taskfile registers
- may be written or read even if not requested in the flags.
- Unused fields of io_ports[] and hob_ports[] should be set
- to zero.
+ When out_flags is zero, the following registers are loaded.
+
+ HOB_FEATURE If the drive supports LBA48
+ HOB_NSECTOR If the drive supports LBA48
+ HOB_SECTOR If the drive supports LBA48
+ HOB_LCYL If the drive supports LBA48
+ HOB_HCYL If the drive supports LBA48
+ FEATURE
+ NSECTOR
+ SECTOR
+ LCYL
+ HCYL
+ SELECT First, masked with 0xE0 if LBA48, 0xEF
+ otherwise; then, or'ed with the default
+ value of SELECT.
+
+ If any bit in out_flags is set, the following registers are loaded.
+
+ HOB_DATA If out_flags.b.data is set. HOB_DATA will
+ travel on DD8-DD15 on little endian machines
+ and on DD0-DD7 on big endian machines.
+ DATA If out_flags.b.data is set. DATA will
+ travel on DD0-DD7 on little endian machines
+ and on DD8-DD15 on big endian machines.
+ HOB_NSECTOR If out_flags.b.nsector_hob is set
+ HOB_SECTOR If out_flags.b.sector_hob is set
+ HOB_LCYL If out_flags.b.lcyl_hob is set
+ HOB_HCYL If out_flags.b.hcyl_hob is set
+ FEATURE If out_flags.b.feature is set
+ NSECTOR If out_flags.b.nsector is set
+ SECTOR If out_flags.b.sector is set
+ LCYL If out_flags.b.lcyl is set
+ HCYL If out_flags.b.hcyl is set
+ SELECT Or'ed with the default value of SELECT and
+ loaded regardless of out_flags.b.select.
+
+ Taskfile registers are read back from the drive into
+ {io|hob}_ports[] after the command completes iff one of the
+ following conditions is met; otherwise, the original values
+ will be written back, unchanged.
+
+ 1. The drive fails the command (EIO).
+ 2. One or more than one bits are set in out_flags.
+ 3. The requested data_phase is TASKFILE_NO_DATA.
+
+ HOB_DATA If in_flags.b.data is set. It will contain
+ DD8-DD15 on little endian machines and
+ DD0-DD7 on big endian machines.
+ DATA If in_flags.b.data is set. It will contain
+ DD0-DD7 on little endian machines and
+ DD8-DD15 on big endian machines.
+ HOB_FEATURE If the drive supports LBA48
+ HOB_NSECTOR If the drive supports LBA48
+ HOB_SECTOR If the drive supports LBA48
+ HOB_LCYL If the drive supports LBA48
+ HOB_HCYL If the drive supports LBA48
+ NSECTOR
+ SECTOR
+ LCYL
+ HCYL
The data_phase field describes the data transfer to be
performed. Value is one of:
@@ -626,27 +698,30 @@ HDIO_DRIVE_TASKFILE execute raw taskfile
TASKFILE_MULTI_OUT
TASKFILE_IN_OUT
TASKFILE_IN_DMA
- TASKFILE_IN_DMAQ
+ TASKFILE_IN_DMAQ == IN_DMA (queueing not supported)
TASKFILE_OUT_DMA
- TASKFILE_OUT_DMAQ
- TASKFILE_P_IN
- TASKFILE_P_IN_DMA
- TASKFILE_P_IN_DMAQ
- TASKFILE_P_OUT
- TASKFILE_P_OUT_DMA
- TASKFILE_P_OUT_DMAQ
+ TASKFILE_OUT_DMAQ == OUT_DMA (queueing not supported)
+ TASKFILE_P_IN unimplemented
+ TASKFILE_P_IN_DMA unimplemented
+ TASKFILE_P_IN_DMAQ unimplemented
+ TASKFILE_P_OUT unimplemented
+ TASKFILE_P_OUT_DMA unimplemented
+ TASKFILE_P_OUT_DMAQ unimplemented
The req_cmd field classifies the command type. It may be
one of:
IDE_DRIVE_TASK_NO_DATA
- IDE_DRIVE_TASK_SET_XFER
+ IDE_DRIVE_TASK_SET_XFER unimplemented
IDE_DRIVE_TASK_IN
- IDE_DRIVE_TASK_OUT
+ IDE_DRIVE_TASK_OUT unimplemented
IDE_DRIVE_TASK_RAW_WRITE
-
-
+ [6] Do not access {in|out}_flags->all except for resetting
+ all the bits. Always access individual bit fields. ->all
+ value will flip depending on endianess. For the same
+ reason, do not use IDE_{TASKFILE|HOB}_STD_{OUT|IN}_FLAGS
+ constants defined in hdreg.h.
@@ -663,7 +738,13 @@ HDIO_DRIVE_CMD execute a special drive command
inputs:
- Taskfile register values:
+ Commands other than WIN_SMART
+ args[0] COMMAND
+ args[1] NSECTOR
+ args[2] FEATURE
+ args[3] NSECTOR
+
+ WIN_SMART
args[0] COMMAND
args[1] SECTOR
args[2] FEATURE
@@ -682,11 +763,28 @@ HDIO_DRIVE_CMD execute a special drive command
error returns:
EACCES Access denied: requires CAP_SYS_RAWIO
ENOMEM Unable to allocate memory for task
+ EIO Drive reports error
notes:
- Taskfile registers IDE_LCYL, IDE_HCYL, and IDE_SELECT are
- set to zero before executing the command.
+ [1] For commands other than WIN_SMART, args[1] should equal
+ args[3]. SECTOR, LCYL and HCYL are undefined. For
+ WIN_SMART, 0x4f and 0xc2 are loaded into LCYL and HCYL
+ respectively. In both cases SELECT will contain the default
+ value for the drive. Please refer to HDIO_DRIVE_TASKFILE
+ notes for the default value of SELECT.
+
+ [2] If NSECTOR value is greater than zero and the drive sets
+ DRQ when interrupting for the command, NSECTOR * 512 bytes
+ are read from the device into the area following NSECTOR.
+ In the above example, the area would be
+ args[4..4+XFER_SIZE]. 16bit PIO is used regardless of
+ HDIO_SET_32BIT setting.
+
+ [3] If COMMAND == WIN_SETFEATURES && FEATURE == SETFEATURES_XFER
+ && NSECTOR >= XFER_SW_DMA_0 && the drive supports any DMA
+ mode, IDE driver will try to tune the transfer mode of the
+ drive accordingly.
@@ -726,7 +824,14 @@ HDIO_DRIVE_TASK execute task and special drive command
error returns:
EACCES Access denied: requires CAP_SYS_RAWIO
ENOMEM Unable to allocate memory for task
+ ENOMSG Device is not a disk drive.
+ EIO Drive failed the command.
+
+ notes:
+ [1] DEV bit (0x10) of SELECT register is ignored and the
+ appropriate value for the drive is used. All other bits
+ are used unaltered.
diff --git a/Documentation/kernel-docs.txt b/Documentation/kernel-docs.txt
index cffca06ad4cef..cb89fb3b61efd 100644
--- a/Documentation/kernel-docs.txt
+++ b/Documentation/kernel-docs.txt
@@ -39,6 +39,13 @@
ON-LINE DOCS:
+ * Title: "Linux Device Drivers, Third Edition"
+ Author: Jonathan Corbet, Alessandro Rubini, Greg Kroah-Hartman
+ URL: http://lwn.net/Kernel/LDD3/
+ Description: A 600-page book covering the (2.6.10) driver
+ programming API and kernel hacking in general. Available under the
+ Creative Commons Attribution-ShareAlike 2.0 license.
+
* Title: "The Linux Kernel"
Author: David A. Rusling.
URL: http://www.tldp.org/LDP/tlk/tlk.html
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index b24c796f05958..4924d387a6573 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -67,17 +67,22 @@ restrictions referred to are that the relevant option is valid if:
SCSI Appropriate SCSI support is enabled.
A lot of drivers has their options described inside of
Documentation/scsi/.
+ SELINUX SELinux support is enabled.
SERIAL Serial support is enabled.
SMP The kernel is an SMP kernel.
SPARC Sparc architecture is enabled.
SWSUSP Software suspension is enabled.
TS Appropriate touchscreen support is enabled.
USB USB support is enabled.
+ USBHID USB Human Interface Device support is enabled.
V4L Video For Linux support is enabled.
VGA The VGA console has been enabled.
VT Virtual terminal support is enabled.
WDT Watchdog support is enabled.
XT IBM PC/XT MFM hard disk support is enabled.
+ X86-64 X86-64 architecture is enabled.
+ More X86-64 boot options can be found in
+ Documentation/x86_64/boot-options.txt .
In addition, the following text indicates that the option:
@@ -295,6 +300,14 @@ running once the system is up.
See header of drivers/cdrom/cdu31a.c.
chandev= [HW,NET] Generic channel device initialisation
+
+ checkreqprot [SELINUX] Set initial checkreqprot flag value.
+ Format: { "0" | "1" }
+ See security/selinux/Kconfig help text.
+ 0 -- check protection applied by kernel (includes any implied execute protection).
+ 1 -- check protection requested by application.
+ Default value is set via a kernel config option.
+ Value can be changed at runtime via /selinux/checkreqprot.
clock= [BUGS=IA-32, HW] gettimeofday timesource override.
Forces specified timesource (if avaliable) to be used
@@ -393,7 +406,7 @@ running once the system is up.
dtc3181e= [HW,SCSI]
- earlyprintk= [x86, x86_64]
+ earlyprintk= [IA-32, X86-64]
earlyprintk=vga
earlyprintk=serial[,ttySn[,baudrate]]
@@ -435,6 +448,14 @@ running once the system is up.
See Documentation/block/as-iosched.txt
and Documentation/block/deadline-iosched.txt for details.
+ enforcing [SELINUX] Set initial enforcing status.
+ Format: {"0" | "1"}
+ See security/selinux/Kconfig help text.
+ 0 -- permissive (log only, no denials).
+ 1 -- enforcing (deny and log).
+ Default value is 0.
+ Value can be changed at runtime via /selinux/enforce.
+
es1370= [HW,OSS]
Format: <lineout>[,<micbias>]
See also header of sound/oss/es1370.c.
@@ -514,11 +535,14 @@ running once the system is up.
i8042.dumbkbd [HW] Pretend that controlled can only read data from
keyboard and can not control its state
(Don't attempt to blink the leds)
- i8042.noacpi [HW] Don't use ACPI to discover KBD/AUX controller
- settings
i8042.noaux [HW] Don't check for auxiliary (== mouse) port
i8042.nomux [HW] Don't check presence of an active multiplexing
controller
+ i8042.nopnp [HW] Don't use ACPIPnP / PnPBIOS to discover KBD/AUX
+ controllers
+ i8042.panicblink=
+ [HW] Frequency with which keyboard LEDs should blink
+ when kernel panics (default is 0.5 sec)
i8042.reset [HW] Reset the controller during init and cleanup
i8042.unlock [HW] Unlock (ignore) the keylock
@@ -614,6 +638,9 @@ running once the system is up.
keepinitrd [HW,ARM]
+ kstack=N [IA-32, X86-64] Print N words from the kernel stack
+ in oops dumps.
+
l2cr= [PPC]
lapic [IA-32,APIC] Enable the local APIC even if BIOS disabled it.
@@ -634,6 +661,20 @@ running once the system is up.
logibm.irq= [HW,MOUSE] Logitech Bus Mouse Driver
Format: <irq>
+ loglevel= All Kernel Messages with a loglevel smaller than the
+ console loglevel will be printed to the console. It can
+ also be changed with klogd or other programs. The
+ loglevels are defined as follows:
+
+ 0 (KERN_EMERG) system is unusable
+ 1 (KERN_ALERT) action must be taken immediately
+ 2 (KERN_CRIT) critical conditions
+ 3 (KERN_ERR) error conditions
+ 4 (KERN_WARNING) warning conditions
+ 5 (KERN_NOTICE) normal but significant condition
+ 6 (KERN_INFO) informational
+ 7 (KERN_DEBUG) debug-level messages
+
log_buf_len=n Sets the size of the printk ring buffer, in bytes.
Format is n, nk, nM. n must be a power of two. The
default is set in kernel config.
@@ -776,6 +817,10 @@ running once the system is up.
mtdparts= [MTD]
See drivers/mtd/cmdline.c.
+ mtouchusb.raw_coordinates=
+ [HW] Make the MicroTouch USB driver use raw coordinates ('y', default)
+ or cooked coordinates ('n')
+
n2= [NET] SDL Inc. RISCom/N2 synchronous serial card
NCR_D700= [HW,SCSI]
@@ -825,7 +870,7 @@ running once the system is up.
noexec [IA-64]
- noexec [i386, x86_64]
+ noexec [IA-32, X86-64]
noexec=on: enable non-executable mappings (default)
noexec=off: disable nn-executable mappings
@@ -837,6 +882,13 @@ running once the system is up.
instruction doesn't work correctly and not to
use it.
+ nohalt [IA-64] Tells the kernel not to use the power saving
+ function PAL_HALT_LIGHT when idle. This increases
+ power-consumption. On the positive side, it reduces
+ interrupt wake-up latency, which may improve performance
+ in certain environments such as networked servers or
+ real-time systems.
+
noirqdebug [IA-32] Disables the code which attempts to detect and
disable unhandled interrupt sources.
@@ -1146,10 +1198,16 @@ running once the system is up.
scsi_logging= [SCSI]
- serialnumber [BUGS=IA-32]
+ selinux [SELINUX] Disable or enable SELinux at boot time.
+ Format: { "0" | "1" }
+ See security/selinux/Kconfig help text.
+ 0 -- disable.
+ 1 -- enable.
+ Default value is set via kernel config option.
+ If enabled at boot time, /selinux/disable can be used
+ later to disable prior to initial policy load.
- sf16fm= [HW] SF16FMI radio driver for Linux
- Format: <io>
+ serialnumber [BUGS=IA-32]
sg_def_reserved_size=
[SCSI]
@@ -1345,9 +1403,6 @@ running once the system is up.
sym53c416= [HW,SCSI]
See header of drivers/scsi/sym53c416.c.
- sym53c8xx= [HW,SCSI]
- See Documentation/scsi/ncr53c8xx.txt.
-
t128= [HW,SCSI]
See header of drivers/scsi/t128.c.
@@ -1356,6 +1411,8 @@ running once the system is up.
thash_entries= [KNL,NET]
Set number of hash buckets for TCP connection
+ time Show timing data prefixed to each printk message line
+
tipar.timeout= [HW,PPT]
Set communications timeout in tenths of a second
(default 15).
@@ -1393,6 +1450,9 @@ running once the system is up.
Format: <io>,<irq>
usb-handoff [HW] Enable early USB BIOS -> OS handoff
+
+ usbhid.mousepoll=
+ [USBHID] The interval which mice are to be polled at.
video= [FB] Frame buffer configuration
See Documentation/fb/modedb.txt.
diff --git a/Documentation/keys.txt b/Documentation/keys.txt
index 36cbb0dd0f329..36d80aeeaf28c 100644
--- a/Documentation/keys.txt
+++ b/Documentation/keys.txt
@@ -151,8 +151,8 @@ The key service provides a number of features besides keys:
by using PR_JOIN_SESSION_KEYRING. It is permitted to request an anonymous
new one, or to attempt to create or join one of a specific name.
- The ownership of the thread and process-specific keyrings changes when
- the real UID and GID of the thread changes.
+ The ownership of the thread keyring changes when the real UID and GID of
+ the thread changes.
(*) Each user ID resident in the system holds two special keyrings: a user
specific keyring and a default user session keyring. The default session
@@ -606,8 +606,12 @@ open call, and the key released upon close. How to deal with conflicting keys
due to two different users opening the same file is left to the filesystem
author to solve.
-When accessing a key's payload data, the key->lock should be at least read
-locked, or else the data may be changed by update during the access.
+When accessing a key's payload data, key->lock should be at least read locked,
+or else the data may be changed by an update being performed from userspace
+whilst the driver or filesystem is trying to access it. If no update method is
+supplied, then the key's payload may be accessed without holding a lock as
+there is no way to change it, provided it can be guaranteed that the key's
+type definition won't go away.
(*) To search for a key, call:
@@ -719,13 +723,19 @@ The structure has a number of fields, some of which are mandatory:
(*) int (*instantiate)(struct key *key, const void *data, size_t datalen);
- This method is called to attach a payload to a key during
- construction. The payload attached need not bear any relation to the data
- passed to this function.
+ This method is called to attach a payload to a key during construction.
+ The payload attached need not bear any relation to the data passed to
+ this function.
If the amount of data attached to the key differs from the size in
keytype->def_datalen, then key_payload_reserve() should be called.
+ This method does not have to lock the 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.
+
+ This method may sleep if it wishes.
+
(*) int (*duplicate)(struct key *key, const struct key *source);
@@ -734,8 +744,8 @@ The structure has a number of fields, some of which are mandatory:
the new key. The data length on the new key will have been updated and
the quota adjusted already.
- The source key will be locked against change on the source->sem, so it is
- safe to sleep here.
+ This method will be called with the source key's semaphore read-locked to
+ prevent its payload from being changed. It is safe to sleep here.
(*) int (*update)(struct key *key, const void *data, size_t datalen);
@@ -749,30 +759,47 @@ The structure has a number of fields, some of which are mandatory:
type is committed to changing the key because it's already been altered,
so all memory allocation must be done first.
- The key will be locked against other changers on key->sem, so it is safe
- to sleep here.
-
key_payload_reserve() should be called with the key->lock write locked,
and the changes to the key's attached payload should be made before the
key is locked.
+ The key will have its semaphore write-locked before this method is
+ called. Any changes to the key should be made with the key's rwlock
+ write-locked also. It is safe to sleep here.
+
(*) int (*match)(const struct key *key, const void *desc);
This method is called to match a key against a description. It should
return non-zero if the two match, zero if they don't.
+ This method should not need to lock the key in any way. The type and
+ description can be considered invariant, and the payload should not be
+ accessed (the key may not yet be instantiated).
+
+ It is not safe to sleep in this method; the caller may hold spinlocks.
+
(*) void (*destroy)(struct key *key);
This method is optional. It is called to discard the payload data on a
key when it is being destroyed.
+ This method does not need to lock the key; it can consider the key as
+ being inaccessible. Note that the key's type may have changed before this
+ function is called.
+
+ It is not safe to sleep in this method; the caller may hold spinlocks.
+
(*) void (*describe)(const struct key *key, struct seq_file *p);
This method is optional. It is called during /proc/keys reading to
- summarise a key in text form.
+ summarise a key's description and payload in text form.
+
+ This method will be called with the key's rwlock read-locked. This will
+ prevent the key's payload and state changing; also the description should
+ not change. This also means it is not safe to sleep in this method.
(*) long (*read)(const struct key *key, char __user *buffer, size_t buflen);
@@ -785,6 +812,12 @@ The structure has a number of fields, some of which are mandatory:
If successful, the blob size that could be produced should be returned
rather than the size copied.
+ This method will be called with the key's semaphore read-locked. This
+ will prevent the key's payload changing. It is not necessary to also
+ read-lock key->lock when accessing the key's payload. It is safe to sleep
+ in this method, such as might happen when the userspace buffer is
+ accessed.
+
============================
REQUEST-KEY CALLBACK SERVICE
diff --git a/Documentation/networking/bonding.txt b/Documentation/networking/bonding.txt
index da3ea9d0c2a65..0bc2ed136a383 100644
--- a/Documentation/networking/bonding.txt
+++ b/Documentation/networking/bonding.txt
@@ -1,5 +1,5 @@
- Linux Ethernet Bonding Driver mini-howto
+ Linux Ethernet Bonding Driver HOWTO
Initial release : Thomas Davis <tadavis at lbl.gov>
Corrections, HA extensions : 2000/10/03-15 :
@@ -9,8 +9,11 @@ Corrections, HA extensions : 2000/10/03-15 :
- Janice Girouard <girouard at us dot ibm dot com>
- Jay Vosburgh <fubar at us dot ibm dot com>
+Reorganized and updated Feb 2005 by Jay Vosburgh
+
Note :
------
+
The bonding driver originally came from Donald Becker's beowulf patches for
kernel 2.0. It has changed quite a bit since, and the original tools from
extreme-linux and beowulf sites will not work with this version of the driver.
@@ -18,218 +21,190 @@ extreme-linux and beowulf sites will not work with this version of the driver.
For new versions of the driver, patches for older kernels and the updated
userspace tools, please follow the links at the end of this file.
-
Table of Contents
=================
-Installation
-Bond Configuration
-Module Parameters
-Configuring Multiple Bonds
-Switch Configuration
-Verifying Bond Configuration
-Frequently Asked Questions
-High Availability
-Promiscuous Sniffing notes
-8021q VLAN support
-Limitations
-Resources and Links
-
-
-Installation
-============
-
-1) Build kernel with the bonding driver
----------------------------------------
-For the latest version of the bonding driver, use kernel 2.4.12 or above
-(otherwise you will need to apply a patch).
-
-Configure kernel with `make menuconfig/xconfig/config', and select "Bonding
-driver support" in the "Network device support" section. It is recommended
-to configure the driver as module since it is currently the only way to
-pass parameters to the driver and configure more than one bonding device.
-
-Build and install the new kernel and modules.
-
-2) Get and install the userspace tools
---------------------------------------
-This version of the bonding driver requires updated ifenslave program. The
-original one from extreme-linux and beowulf will not work. Kernels 2.4.12
-and above include the updated version of ifenslave.c in
-Documentation/networking directory. For older kernels, please follow the
-links at the end of this file.
-
-IMPORTANT!!! If you are running on Redhat 7.1 or greater, you need
-to be careful because /usr/include/linux is no longer a symbolic link
-to /usr/src/linux/include/linux. If you build ifenslave while this is
-true, ifenslave will appear to succeed but your bond won't work. The purpose
-of the -I option on the ifenslave compile line is to make sure it uses
-/usr/src/linux/include/linux/if_bonding.h instead of the version from
-/usr/include/linux.
-
-To install ifenslave.c, do:
- # gcc -Wall -Wstrict-prototypes -O -I/usr/src/linux/include ifenslave.c -o ifenslave
- # cp ifenslave /sbin/ifenslave
-
-
-Bond Configuration
-==================
+1. Bonding Driver Installation
-You will need to add at least the following line to /etc/modprobe.conf
-so the bonding driver will automatically load when the bond0 interface is
-configured. Refer to the modprobe.conf manual page for specific modprobe.conf
-syntax details. The Module Parameters section of this document describes each
-bonding driver parameter.
+2. Bonding Driver Options
- alias bond0 bonding
+3. Configuring Bonding Devices
+3.1 Configuration with sysconfig support
+3.2 Configuration with initscripts support
+3.3 Configuring Bonding Manually
+3.4 Configuring Multiple Bonds
-Use standard distribution techniques to define the bond0 network interface. For
-example, on modern Red Hat distributions, create an ifcfg-bond0 file in
-the /etc/sysconfig/network-scripts directory that resembles the following:
+5. Querying Bonding Configuration
+5.1 Bonding Configuration
+5.2 Network Configuration
-DEVICE=bond0
-IPADDR=192.168.1.1
-NETMASK=255.255.255.0
-NETWORK=192.168.1.0
-BROADCAST=192.168.1.255
-ONBOOT=yes
-BOOTPROTO=none
-USERCTL=no
+6. Switch Configuration
-(use appropriate values for your network above)
+7. 802.1q VLAN Support
-All interfaces that are part of a bond should have SLAVE and MASTER
-definitions. For example, in the case of Red Hat, if you wish to make eth0 and
-eth1 a part of the bonding interface bond0, their config files (ifcfg-eth0 and
-ifcfg-eth1) should resemble the following:
+8. Link Monitoring
+8.1 ARP Monitor Operation
+8.2 Configuring Multiple ARP Targets
+8.3 MII Monitor Operation
-DEVICE=eth0
-USERCTL=no
-ONBOOT=yes
-MASTER=bond0
-SLAVE=yes
-BOOTPROTO=none
+9. Potential Trouble Sources
+9.1 Adventures in Routing
+9.2 Ethernet Device Renaming
+9.3 Painfully Slow Or No Failed Link Detection By Miimon
-Use DEVICE=eth1 in the ifcfg-eth1 config file. If you configure a second
-bonding interface (bond1), use MASTER=bond1 in the config file to make the
-network interface be a slave of bond1.
+10. SNMP agents
-Restart the networking subsystem or just bring up the bonding device if your
-administration tools allow it. Otherwise, reboot. On Red Hat distros you can
-issue `ifup bond0' or `/etc/rc.d/init.d/network restart'.
+11. Promiscuous mode
-If the administration tools of your distribution do not support
-master/slave notation in configuring network interfaces, you will need to
-manually configure the bonding device with the following commands:
+12. High Availability Information
+12.1 High Availability in a Single Switch Topology
+12.1.1 Bonding Mode Selection for Single Switch Topology
+12.1.2 Link Monitoring for Single Switch Topology
+12.2 High Availability in a Multiple Switch Topology
+12.2.1 Bonding Mode Selection for Multiple Switch Topology
+12.2.2 Link Monitoring for Multiple Switch Topology
+12.3 Switch Behavior Issues for High Availability
- # /sbin/ifconfig bond0 192.168.1.1 netmask 255.255.255.0 \
- broadcast 192.168.1.255 up
+13. Hardware Specific Considerations
+13.1 IBM BladeCenter
- # /sbin/ifenslave bond0 eth0
- # /sbin/ifenslave bond0 eth1
+14. Frequently Asked Questions
-(use appropriate values for your network above)
+15. Resources and Links
-You can then create a script containing these commands and place it in the
-appropriate rc directory.
-If you specifically need all network drivers loaded before the bonding driver,
-adding the following line to modprobe.conf will cause the network driver for
-eth0 and eth1 to be loaded before the bonding driver.
+1. Bonding Driver Installation
+==============================
-install bond0 /sbin/modprobe -a eth0 eth1 && /sbin/modprobe bonding
+ Most popular distro kernels ship with the bonding driver
+already available as a module and the ifenslave user level control
+program installed and ready for use. If your distro does not, or you
+have need to compile bonding from source (e.g., configuring and
+installing a mainline kernel from kernel.org), you'll need to perform
+the following steps:
-Be careful not to reference bond0 itself at the end of the line, or modprobe
-will die in an endless recursive loop.
+1.1 Configure and build the kernel with bonding
+-----------------------------------------------
-If running SNMP agents, the bonding driver should be loaded before any network
-drivers participating in a bond. This requirement is due to the the interface
-index (ipAdEntIfIndex) being associated to the first interface found with a
-given IP address. That is, there is only one ipAdEntIfIndex for each IP
-address. For example, if eth0 and eth1 are slaves of bond0 and the driver for
-eth0 is loaded before the bonding driver, the interface for the IP address
-will be associated with the eth0 interface. This configuration is shown below,
-the IP address 192.168.1.1 has an interface index of 2 which indexes to eth0
-in the ifDescr table (ifDescr.2).
+ The latest version of the bonding driver is available in the
+drivers/net/bonding subdirectory of the most recent kernel source
+(which is available on http://kernel.org).
- interfaces.ifTable.ifEntry.ifDescr.1 = lo
- interfaces.ifTable.ifEntry.ifDescr.2 = eth0
- interfaces.ifTable.ifEntry.ifDescr.3 = eth1
- interfaces.ifTable.ifEntry.ifDescr.4 = eth2
- interfaces.ifTable.ifEntry.ifDescr.5 = eth3
- interfaces.ifTable.ifEntry.ifDescr.6 = bond0
- ip.ipAddrTable.ipAddrEntry.ipAdEntIfIndex.10.10.10.10 = 5
- ip.ipAddrTable.ipAddrEntry.ipAdEntIfIndex.192.168.1.1 = 2
- ip.ipAddrTable.ipAddrEntry.ipAdEntIfIndex.10.74.20.94 = 4
- ip.ipAddrTable.ipAddrEntry.ipAdEntIfIndex.127.0.0.1 = 1
+ Prior to the 2.4.11 kernel, the bonding driver was maintained
+largely outside the kernel tree; patches for some earlier kernels are
+available on the bonding sourceforge site, although those patches are
+still several years out of date. Most users will want to use either
+the most recent kernel from kernel.org or whatever kernel came with
+their distro.
-This problem is avoided by loading the bonding driver before any network
-drivers participating in a bond. Below is an example of loading the bonding
-driver first, the IP address 192.168.1.1 is correctly associated with
-ifDescr.2.
+ Configure kernel with "make menuconfig" (or "make xconfig" or
+"make config"), then select "Bonding driver support" in the "Network
+device support" section. It is recommended that you configure the
+driver as module since it is currently the only way to pass parameters
+to the driver or configure more than one bonding device.
- interfaces.ifTable.ifEntry.ifDescr.1 = lo
- interfaces.ifTable.ifEntry.ifDescr.2 = bond0
- interfaces.ifTable.ifEntry.ifDescr.3 = eth0
- interfaces.ifTable.ifEntry.ifDescr.4 = eth1
- interfaces.ifTable.ifEntry.ifDescr.5 = eth2
- interfaces.ifTable.ifEntry.ifDescr.6 = eth3
- ip.ipAddrTable.ipAddrEntry.ipAdEntIfIndex.10.10.10.10 = 6
- ip.ipAddrTable.ipAddrEntry.ipAdEntIfIndex.192.168.1.1 = 2
- ip.ipAddrTable.ipAddrEntry.ipAdEntIfIndex.10.74.20.94 = 5
- ip.ipAddrTable.ipAddrEntry.ipAdEntIfIndex.127.0.0.1 = 1
+ Build and install the new kernel and modules, then proceed to
+step 2.
-While some distributions may not report the interface name in ifDescr,
-the association between the IP address and IfIndex remains and SNMP
-functions such as Interface_Scan_Next will report that association.
+1.2 Install ifenslave Control Utility
+-------------------------------------
+ The ifenslave user level control program is included in the
+kernel source tree, in the file Documentation/networking/ifenslave.c.
+It is generally recommended that you use the ifenslave that
+corresponds to the kernel that you are using (either from the same
+source tree or supplied with the distro), however, ifenslave
+executables from older kernels should function (but features newer
+than the ifenslave release are not supported). Running an ifenslave
+that is newer than the kernel is not supported, and may or may not
+work.
-Module Parameters
-=================
+ To install ifenslave, do the following:
+
+# gcc -Wall -O -I/usr/src/linux/include ifenslave.c -o ifenslave
+# cp ifenslave /sbin/ifenslave
+
+ If your kernel source is not in "/usr/src/linux," then replace
+"/usr/src/linux/include" in the above with the location of your kernel
+source include directory.
+
+ You may wish to back up any existing /sbin/ifenslave, or, for
+testing or informal use, tag the ifenslave to the kernel version
+(e.g., name the ifenslave executable /sbin/ifenslave-2.6.10).
+
+IMPORTANT NOTE:
-Optional parameters for the bonding driver can be supplied as command line
-arguments to the insmod command. Typically, these parameters are specified in
-the file /etc/modprobe.conf (see the manual page for modprobe.conf). The
-available bonding driver parameters are listed below. If a parameter is not
-specified the default value is used. When initially configuring a bond, it
-is recommended "tail -f /var/log/messages" be run in a separate window to
-watch for bonding driver error messages.
+ If you omit the "-I" or specify an incorrect directory, you
+may end up with an ifenslave that is incompatible with the kernel
+you're trying to build it for. Some distros (e.g., Red Hat from 7.1
+onwards) do not have /usr/include/linux symbolically linked to the
+default kernel source include directory.
-It is critical that either the miimon or arp_interval and arp_ip_target
-parameters be specified, otherwise serious network degradation will occur
-during link failures.
+
+2. Bonding Driver Options
+=========================
+
+ Options for the bonding driver are supplied as parameters to
+the bonding module at load time. They may be given as command line
+arguments to the insmod or modprobe command, but are usually specified
+in either the /etc/modprobe.conf configuration file, or in a
+distro-specific configuration file (some of which are detailed in the
+next section).
+
+ The available bonding driver parameters are listed below. If a
+parameter is not specified the default value is used. When initially
+configuring a bond, it is recommended "tail -f /var/log/messages" be
+run in a separate window to watch for bonding driver error messages.
+
+ It is critical that either the miimon or arp_interval and
+arp_ip_target parameters be specified, otherwise serious network
+degradation will occur during link failures. Very few devices do not
+support at least miimon, so there is really no reason not to use it.
+
+ Options with textual values will accept either the text name
+ or, for backwards compatibility, the option value. E.g.,
+ "mode=802.3ad" and "mode=4" set the same mode.
+
+ The parameters are as follows:
arp_interval
- Specifies the ARP monitoring frequency in milli-seconds.
- If ARP monitoring is used in a load-balancing mode (mode 0 or 2), the
- switch should be configured in a mode that evenly distributes packets
- across all links - such as round-robin. If the switch is configured to
- distribute the packets in an XOR fashion, all replies from the ARP
- targets will be received on the same link which could cause the other
- team members to fail. ARP monitoring should not be used in conjunction
- with miimon. A value of 0 disables ARP monitoring. The default value
- is 0.
+ Specifies the ARP monitoring frequency in milli-seconds. If
+ ARP monitoring is used in a load-balancing mode (mode 0 or 2),
+ the switch should be configured in a mode that evenly
+ distributes packets across all links - such as round-robin. If
+ the switch is configured to distribute the packets in an XOR
+ fashion, all replies from the ARP targets will be received on
+ the same link which could cause the other team members to
+ fail. ARP monitoring should not be used in conjunction with
+ miimon. A value of 0 disables ARP monitoring. The default
+ value is 0.
arp_ip_target
- Specifies the ip addresses to use when arp_interval is > 0. These
- are the targets of the ARP request sent to determine the health of
- the link to the targets. Specify these values in ddd.ddd.ddd.ddd
- format. Multiple ip adresses must be seperated by a comma. At least
- one ip address needs to be given for ARP monitoring to work. The
- maximum number of targets that can be specified is set at 16.
+ Specifies the ip addresses to use when arp_interval is > 0.
+ These are the targets of the ARP request sent to determine the
+ health of the link to the targets. Specify these values in
+ ddd.ddd.ddd.ddd format. Multiple ip adresses must be
+ seperated by a comma. At least one IP address must be given
+ for ARP monitoring to function. The maximum number of targets
+ that can be specified is 16. The default value is no IP
+ addresses.
downdelay
- Specifies the delay time in milli-seconds to disable a link after a
- link failure has been detected. This should be a multiple of miimon
- value, otherwise the value will be rounded. The default value is 0.
+ Specifies the time, in milliseconds, to wait before disabling
+ a slave after a link failure has been detected. This option
+ is only valid for the miimon link monitor. The downdelay
+ value should be a multiple of the miimon value; if not, it
+ will be rounded down to the nearest multiple. The default
+ value is 0.
lacp_rate
- Option specifying the rate in which we'll ask our link partner to
- transmit LACPDU packets in 802.3ad mode. Possible values are:
+ Option specifying the rate in which we'll ask our link partner
+ to transmit LACPDU packets in 802.3ad mode. Possible values
+ are:
slow or 0
Request partner to transmit LACPDUs every 30 seconds (default)
@@ -246,69 +221,76 @@ max_bonds
miimon
- Specifies the frequency in milli-seconds that MII link monitoring
- will occur. A value of zero disables MII link monitoring. A value
- of 100 is a good starting point. See High Availability section for
- additional information. The default value is 0.
+ Specifies the frequency in milli-seconds that MII link
+ monitoring will occur. A value of zero disables MII link
+ monitoring. A value of 100 is a good starting point. The
+ use_carrier option, below, affects how the link state is
+ determined. See the High Availability section for additional
+ information. The default value is 0.
mode
Specifies one of the bonding policies. The default is
- round-robin (balance-rr). Possible values are (you can use
- either the text or numeric option):
+ balance-rr (round robin). Possible values are:
balance-rr or 0
- Round-robin policy: Transmit in a sequential order
- from the first available slave through the last. This
- mode provides load balancing and fault tolerance.
+ Round-robin policy: Transmit packets in sequential
+ order from the first available slave through the
+ last. This mode provides load balancing and fault
+ tolerance.
active-backup or 1
Active-backup policy: Only one slave in the bond is
- active. A different slave becomes active if, and only
- if, the active slave fails. The bond's MAC address is
+ active. A different slave becomes active if, and only
+ if, the active slave fails. The bond's MAC address is
externally visible on only one port (network adapter)
to avoid confusing the switch. This mode provides
- fault tolerance.
+ fault tolerance. The primary option affects the
+ behavior of this mode.
balance-xor or 2
XOR policy: Transmit based on [(source MAC address
- XOR'd with destination MAC address) modula slave
- count]. This selects the same slave for each
- destination MAC address. This mode provides load
+ XOR'd with destination MAC address) modulo slave
+ count]. This selects the same slave for each
+ destination MAC address. This mode provides load
balancing and fault tolerance.
broadcast or 3
Broadcast policy: transmits everything on all slave
- interfaces. This mode provides fault tolerance.
+ interfaces. This mode provides fault tolerance.
802.3ad or 4
- IEEE 802.3ad Dynamic link aggregation. Creates aggregation
- groups that share the same speed and duplex settings.
- Transmits and receives on all slaves in the active
- aggregator.
+ IEEE 802.3ad Dynamic link aggregation. Creates
+ aggregation groups that share the same speed and
+ duplex settings. Utilizes all slaves in the active
+ aggregator according to the 802.3ad specification.
Pre-requisites:
- 1. Ethtool support in the base drivers for retrieving the
- speed and duplex of each slave.
+ 1. Ethtool support in the base drivers for retrieving
+ the speed and duplex of each slave.
2. A switch that supports IEEE 802.3ad Dynamic link
aggregation.
+ Most switches will require some type of configuration
+ to enable 802.3ad mode.
+
balance-tlb or 5
- Adaptive transmit load balancing: channel bonding that does
- not require any special switch support. The outgoing
- traffic is distributed according to the current load
- (computed relative to the speed) on each slave. Incoming
- traffic is received by the current slave. If the receiving
- slave fails, another slave takes over the MAC address of
- the failed receiving slave.
+ Adaptive transmit load balancing: channel bonding that
+ does not require any special switch support. The
+ outgoing traffic is distributed according to the
+ current load (computed relative to the speed) on each
+ slave. Incoming traffic is received by the current
+ slave. If the receiving slave fails, another slave
+ takes over the MAC address of the failed receiving
+ slave.
Prerequisite:
@@ -317,205 +299,452 @@ mode
balance-alb or 6
- Adaptive load balancing: includes balance-tlb + receive
- load balancing (rlb) for IPV4 traffic and does not require
- any special switch support. The receive load balancing is
- achieved by ARP negotiation. The bonding driver intercepts
- the ARP Replies sent by the server on their way out and
- overwrites the src hw address with the unique hw address of
- one of the slaves in the bond such that different clients
- use different hw addresses for the server.
-
- Receive traffic from connections created by the server is
- also balanced. When the server sends an ARP Request the
- bonding driver copies and saves the client's IP information
- from the ARP. When the ARP Reply arrives from the client,
- its hw address is retrieved and the bonding driver
- initiates an ARP reply to this client assigning it to one
- of the slaves in the bond. A problematic outcome of using
- ARP negotiation for balancing is that each time that an ARP
- request is broadcasted it uses the hw address of the
- bond. Hence, clients learn the hw address of the bond and
- the balancing of receive traffic collapses to the current
- salve. This is handled by sending updates (ARP Replies) to
- all the clients with their assigned hw address such that
- the traffic is redistributed. Receive traffic is also
- redistributed when a new slave is added to the bond and
- when an inactive slave is re-activated. The receive load is
- distributed sequentially (round robin) among the group of
- highest speed slaves in the bond.
-
- When a link is reconnected or a new slave joins the bond
- the receive traffic is redistributed among all active
- slaves in the bond by intiating ARP Replies with the
- selected mac address to each of the clients. The updelay
- modeprobe parameter must be set to a value equal or greater
- than the switch's forwarding delay so that the ARP Replies
- sent to the clients will not be blocked by the switch.
+ Adaptive load balancing: includes balance-tlb plus
+ receive load balancing (rlb) for IPV4 traffic, and
+ does not require any special switch support. The
+ receive load balancing is achieved by ARP negotiation.
+ The bonding driver intercepts the ARP Replies sent by
+ the local system on their way out and overwrites the
+ source hardware address with the unique hardware
+ address of one of the slaves in the bond such that
+ different peers use different hardware addresses for
+ the server.
+
+ Receive traffic from connections created by the server
+ is also balanced. When the local system sends an ARP
+ Request the bonding driver copies and saves the peer's
+ IP information from the ARP packet. When the ARP
+ Reply arrives from the peer, its hardware address is
+ retrieved and the bonding driver initiates an ARP
+ reply to this peer assigning it to one of the slaves
+ in the bond. A problematic outcome of using ARP
+ negotiation for balancing is that each time that an
+ ARP request is broadcast it uses the hardware address
+ of the bond. Hence, peers learn the hardware address
+ of the bond and the balancing of receive traffic
+ collapses to the current slave. This is handled by
+ sending updates (ARP Replies) to all the peers with
+ their individually assigned hardware address such that
+ the traffic is redistributed. Receive traffic is also
+ redistributed when a new slave is added to the bond
+ and when an inactive slave is re-activated. The
+ receive load is distributed sequentially (round robin)
+ among the group of highest speed slaves in the bond.
+
+ When a link is reconnected or a new slave joins the
+ bond the receive traffic is redistributed among all
+ active slaves in the bond by intiating ARP Replies
+ with the selected mac address to each of the
+ clients. The updelay parameter (detailed below) must
+ be set to a value equal or greater than the switch's
+ forwarding delay so that the ARP Replies sent to the
+ peers will not be blocked by the switch.
Prerequisites:
- 1. Ethtool support in the base drivers for retrieving the
- speed of each slave.
+ 1. Ethtool support in the base drivers for retrieving
+ the speed of each slave.
- 2. Base driver support for setting the hw address of a
- device also when it is open. This is required so that there
- will always be one slave in the team using the bond hw
- address (the curr_active_slave) while having a unique hw
- address for each slave in the bond. If the curr_active_slave
- fails it's hw address is swapped with the new curr_active_slave
- that was chosen.
+ 2. Base driver support for setting the hardware
+ address of a device while it is open. This is
+ required so that there will always be one slave in the
+ team using the bond hardware address (the
+ curr_active_slave) while having a unique hardware
+ address for each slave in the bond. If the
+ curr_active_slave fails its hardware address is
+ swapped with the new curr_active_slave that was
+ chosen.
primary
- A string (eth0, eth2, etc) to equate to a primary device. If this
- value is entered, and the device is on-line, it will be used first
- as the output media. Only when this device is off-line, will
- alternate devices be used. Otherwise, once a failover is detected
- and a new default output is chosen, it will remain the output media
- until it too fails. This is useful when one slave was preferred
- over another, i.e. when one slave is 1000Mbps and another is
- 100Mbps. If the 1000Mbps slave fails and is later restored, it may
- be preferred the faster slave gracefully become the active slave -
- without deliberately failing the 100Mbps slave. Specifying a
- primary is only valid in active-backup mode.
+ A string (eth0, eth2, etc) specifying which slave is the
+ primary device. The specified device will always be the
+ active slave while it is available. Only when the primary is
+ off-line will alternate devices be used. This is useful when
+ one slave is preferred over another, e.g., when one slave has
+ higher throughput than another.
+
+ The primary option is only valid for active-backup mode.
updelay
- Specifies the delay time in milli-seconds to enable a link after a
- link up status has been detected. This should be a multiple of miimon
- value, otherwise the value will be rounded. The default value is 0.
+ Specifies the time, in milliseconds, to wait before enabling a
+ slave after a link recovery has been detected. This option is
+ only valid for the miimon link monitor. The updelay value
+ should be a multiple of the miimon value; if not, it will be
+ rounded down to the nearest multiple. The default value is 0.
use_carrier
- Specifies whether or not miimon should use MII or ETHTOOL
- ioctls vs. netif_carrier_ok() to determine the link status.
- The MII or ETHTOOL ioctls are less efficient and utilize a
- deprecated calling sequence within the kernel. The
- netif_carrier_ok() relies on the device driver to maintain its
- state with netif_carrier_on/off; at this writing, most, but
- not all, device drivers support this facility.
-
- If bonding insists that the link is up when it should not be,
- it may be that your network device driver does not support
- netif_carrier_on/off. This is because the default state for
- netif_carrier is "carrier on." In this case, disabling
- use_carrier will cause bonding to revert to the MII / ETHTOOL
- ioctl method to determine the link state.
-
- A value of 1 enables the use of netif_carrier_ok(), a value of
- 0 will use the deprecated MII / ETHTOOL ioctls. The default
- value is 1.
-
-
-Configuring Multiple Bonds
-==========================
-
-If several bonding interfaces are required, either specify the max_bonds
-parameter (described above), or load the driver multiple times. Using
-the max_bonds parameter is less complicated, but has the limitation that
-all bonding instances created will have the same options. Loading the
-driver multiple times allows each instance of the driver to have differing
-options.
-
-For example, to configure two bonding interfaces, one with mii link
-monitoring performed every 100 milliseconds, and one with ARP link
-monitoring performed every 200 milliseconds, the /etc/conf.modules should
-resemble the following:
+ Specifies whether or not miimon should use MII or ETHTOOL
+ ioctls vs. netif_carrier_ok() to determine the link
+ status. The MII or ETHTOOL ioctls are less efficient and
+ utilize a deprecated calling sequence within the kernel. The
+ netif_carrier_ok() relies on the device driver to maintain its
+ state with netif_carrier_on/off; at this writing, most, but
+ not all, device drivers support this facility.
+
+ If bonding insists that the link is up when it should not be,
+ it may be that your network device driver does not support
+ netif_carrier_on/off. The default state for netif_carrier is
+ "carrier on," so if a driver does not support netif_carrier,
+ it will appear as if the link is always up. In this case,
+ setting use_carrier to 0 will cause bonding to revert to the
+ MII / ETHTOOL ioctl method to determine the link state.
+
+ A value of 1 enables the use of netif_carrier_ok(), a value of
+ 0 will use the deprecated MII / ETHTOOL ioctls. The default
+ value is 1.
-alias bond0 bonding
-alias bond1 bonding
-options bond0 miimon=100
-options bond1 -o bonding1 arp_interval=200 arp_ip_target=10.0.0.1
-Configuring Multiple ARP Targets
-================================
+3. Configuring Bonding Devices
+==============================
-While ARP monitoring can be done with just one target, it can be useful
-in a High Availability setup to have several targets to monitor. In the
-case of just one target, the target itself may go down or have a problem
-making it unresponsive to ARP requests. Having an additional target (or
-several) increases the reliability of the ARP monitoring.
+ There are, essentially, two methods for configuring bonding:
+with support from the distro's network initialization scripts, and
+without. Distros generally use one of two packages for the network
+initialization scripts: initscripts or sysconfig. Recent versions of
+these packages have support for bonding, while older versions do not.
+
+ We will first describe the options for configuring bonding for
+distros using versions of initscripts and sysconfig with full or
+partial support for bonding, then provide information on enabling
+bonding without support from the network initialization scripts (i.e.,
+older versions of initscripts or sysconfig).
-Multiple ARP targets must be seperated by commas as follows:
+ If you're unsure whether your distro uses sysconfig or
+initscripts, or don't know if it's new enough, have no fear.
+Determining this is fairly straightforward.
-# example options for ARP monitoring with three targets
-alias bond0 bonding
-options bond0 arp_interval=60 arp_ip_target=192.168.0.1,192.168.0.3,192.168.0.9
+ First, issue the command:
+
+$ rpm -qf /sbin/ifup
-For just a single target the options would resemble:
+ It will respond with a line of text starting with either
+"initscripts" or "sysconfig," followed by some numbers. This is the
+package that provides your network initialization scripts.
-# example options for ARP monitoring with one target
-alias bond0 bonding
-options bond0 arp_interval=60 arp_ip_target=192.168.0.100
+ Next, to determine if your installation supports bonding,
+issue the command:
-Potential Problems When Using ARP Monitor
-=========================================
+$ grep ifenslave /sbin/ifup
-1. Driver support
+ If this returns any matches, then your initscripts or
+sysconfig has support for bonding.
-The ARP monitor relies on the network device driver to maintain two
-statistics: the last receive time (dev->last_rx), and the last
-transmit time (dev->trans_start). If the network device driver does
-not update one or both of these, then the typical result will be that,
-upon startup, all links in the bond will immediately be declared down,
-and remain that way. A network monitoring tool (tcpdump, e.g.) will
-show ARP requests and replies being sent and received on the bonding
-device.
+3.1 Configuration with sysconfig support
+----------------------------------------
-The possible resolutions for this are to (a) fix the device driver, or
-(b) discontinue the ARP monitor (using miimon as an alternative, for
-example).
+ This section applies to distros using a version of sysconfig
+with bonding support, for example, SuSE Linux Enterprise Server 9.
-2. Adventures in Routing
+ SuSE SLES 9's networking configuration system does support
+bonding, however, at this writing, the YaST system configuration
+frontend does not provide any means to work with bonding devices.
+Bonding devices can be managed by hand, however, as follows.
-When bonding is set up with the ARP monitor, it is important that the
-slave devices not have routes that supercede routes of the master (or,
-generally, not have routes at all). For example, suppose the bonding
-device bond0 has two slaves, eth0 and eth1, and the routing table is
-as follows:
+ First, if they have not already been configured, configure the
+slave devices. On SLES 9, this is most easily done by running the
+yast2 sysconfig configuration utility. The goal is for to create an
+ifcfg-id file for each slave device. The simplest way to accomplish
+this is to configure the devices for DHCP. The name of the
+configuration file for each device will be of the form:
-Kernel IP routing table
-Destination Gateway Genmask Flags MSS Window irtt Iface
-10.0.0.0 0.0.0.0 255.255.0.0 U 40 0 0 eth0
-10.0.0.0 0.0.0.0 255.255.0.0 U 40 0 0 eth1
-10.0.0.0 0.0.0.0 255.255.0.0 U 40 0 0 bond0
-127.0.0.0 0.0.0.0 255.0.0.0 U 40 0 0 lo
+ifcfg-id-xx:xx:xx:xx:xx:xx
-In this case, the ARP monitor (and ARP itself) may become confused,
-because ARP requests will be sent on one interface (bond0), but the
-corresponding reply will arrive on a different interface (eth0). This
-reply looks to ARP as an unsolicited ARP reply (because ARP matches
-replies on an interface basis), and is discarded. This will likely
-still update the receive/transmit times in the driver, but will lose
-packets.
-
-The resolution here is simply to insure that slaves do not have routes
-of their own, and if for some reason they must, those routes do not
-supercede routes of their master. This should generally be the case,
-but unusual configurations or errant manual or automatic static route
-additions may cause trouble.
-
-Switch Configuration
-====================
+ Where the "xx" portion will be replaced with the digits from
+the device's permanent MAC address.
-While the switch does not need to be configured when the active-backup,
-balance-tlb or balance-alb policies (mode=1,5,6) are used, it does need to
-be configured for the round-robin, XOR, broadcast, or 802.3ad policies
-(mode=0,2,3,4).
+ Once the set of ifcfg-id-xx:xx:xx:xx:xx:xx files has been
+created, it is necessary to edit the configuration files for the slave
+devices (the MAC addresses correspond to those of the slave devices).
+Before editing, the file will contain muliple lines, and will look
+something like this:
+BOOTPROTO='dhcp'
+STARTMODE='on'
+USERCTL='no'
+UNIQUE='XNzu.WeZGOGF+4wE'
+_nm_name='bus-pci-0001:61:01.0'
-Verifying Bond Configuration
-============================
+ Change the BOOTPROTO and STARTMODE lines to the following:
-1) Bonding information files
-----------------------------
-The bonding driver information files reside in the /proc/net/bonding directory.
+BOOTPROTO='none'
+STARTMODE='off'
+
+ Do not alter the UNIQUE or _nm_name lines. Remove any other
+lines (USERCTL, etc).
+
+ Once the ifcfg-id-xx:xx:xx:xx:xx:xx files have been modified,
+it's time to create the configuration file for the bonding device
+itself. This file is named ifcfg-bondX, where X is the number of the
+bonding device to create, starting at 0. The first such file is
+ifcfg-bond0, the second is ifcfg-bond1, and so on. The sysconfig
+network configuration system will correctly start multiple instances
+of bonding.
+
+ The contents of the ifcfg-bondX file is as follows:
+
+BOOTPROTO="static"
+BROADCAST="10.0.2.255"
+IPADDR="10.0.2.10"
+NETMASK="255.255.0.0"
+NETWORK="10.0.2.0"
+REMOTE_IPADDR=""
+STARTMODE="onboot"
+BONDING_MASTER="yes"
+BONDING_MODULE_OPTS="mode=active-backup miimon=100"
+BONDING_SLAVE0="eth0"
+BONDING_SLAVE1="eth1"
+
+ Replace the sample BROADCAST, IPADDR, NETMASK and NETWORK
+values with the appropriate values for your network.
+
+ Note that configuring the bonding device with BOOTPROTO='dhcp'
+does not work; the scripts attempt to obtain the device address from
+DHCP prior to adding any of the slave devices. Without active slaves,
+the DHCP requests are not sent to the network.
+
+ The STARTMODE specifies when the device is brought online.
+The possible values are:
+
+ onboot: The device is started at boot time. If you're not
+ sure, this is probably what you want.
+
+ manual: The device is started only when ifup is called
+ manually. Bonding devices may be configured this
+ way if you do not wish them to start automatically
+ at boot for some reason.
+
+ hotplug: The device is started by a hotplug event. This is not
+ a valid choice for a bonding device.
+
+ off or ignore: The device configuration is ignored.
+
+ The line BONDING_MASTER='yes' indicates that the device is a
+bonding master device. The only useful value is "yes."
+
+ The contents of BONDING_MODULE_OPTS are supplied to the
+instance of the bonding module for this device. Specify the options
+for the bonding mode, link monitoring, and so on here. Do not include
+the max_bonds bonding parameter; this will confuse the configuration
+system if you have multiple bonding devices.
+
+ Finally, supply one BONDING_SLAVEn="ethX" for each slave,
+where "n" is an increasing value, one for each slave, and "ethX" is
+the name of the slave device (eth0, eth1, etc).
-Sample contents of /proc/net/bonding/bond0 after the driver is loaded with
-parameters of mode=0 and miimon=1000 is shown below.
+ When all configuration files have been modified or created,
+networking must be restarted for the configuration changes to take
+effect. This can be accomplished via the following:
+# /etc/init.d/network restart
+
+ Note that the network control script (/sbin/ifdown) will
+remove the bonding module as part of the network shutdown processing,
+so it is not necessary to remove the module by hand if, e.g., the
+module paramters have changed.
+
+ Also, at this writing, YaST/YaST2 will not manage bonding
+devices (they do not show bonding interfaces on its list of network
+devices). It is necessary to edit the configuration file by hand to
+change the bonding configuration.
+
+ Additional general options and details of the ifcfg file
+format can be found in an example ifcfg template file:
+
+/etc/sysconfig/network/ifcfg.template
+
+ Note that the template does not document the various BONDING_
+settings described above, but does describe many of the other options.
+
+3.2 Configuration with initscripts support
+------------------------------------------
+
+ This section applies to distros using a version of initscripts
+with bonding support, for example, Red Hat Linux 9 or Red Hat
+Enterprise Linux version 3. On these systems, the network
+initialization scripts have some knowledge of bonding, and can be
+configured to control bonding devices.
+
+ These distros will not automatically load the network adapter
+driver unless the ethX device is configured with an IP address.
+Because of this constraint, users must manually configure a
+network-script file for all physical adapters that will be members of
+a bondX link. Network script files are located in the directory:
+
+/etc/sysconfig/network-scripts
+
+ The file name must be prefixed with "ifcfg-eth" and suffixed
+with the adapter's physical adapter number. For example, the script
+for eth0 would be named /etc/sysconfig/network-scripts/ifcfg-eth0.
+Place the following text in the file:
+
+DEVICE=eth0
+USERCTL=no
+ONBOOT=yes
+MASTER=bond0
+SLAVE=yes
+BOOTPROTO=none
+
+ The DEVICE= line will be different for every ethX device and
+must correspond with the name of the file, i.e., ifcfg-eth1 must have
+a device line of DEVICE=eth1. The setting of the MASTER= line will
+also depend on the final bonding interface name chosen for your bond.
+As with other network devices, these typically start at 0, and go up
+one for each device, i.e., the first bonding instance is bond0, the
+second is bond1, and so on.
+
+ Next, create a bond network script. The file name for this
+script will be /etc/sysconfig/network-scripts/ifcfg-bondX where X is
+the number of the bond. For bond0 the file is named "ifcfg-bond0",
+for bond1 it is named "ifcfg-bond1", and so on. Within that file,
+place the following text:
+
+DEVICE=bond0
+IPADDR=192.168.1.1
+NETMASK=255.255.255.0
+NETWORK=192.168.1.0
+BROADCAST=192.168.1.255
+ONBOOT=yes
+BOOTPROTO=none
+USERCTL=no
+
+ Be sure to change the networking specific lines (IPADDR,
+NETMASK, NETWORK and BROADCAST) to match your network configuration.
+
+ Finally, it is necessary to edit /etc/modules.conf to load the
+bonding module when the bond0 interface is brought up. The following
+sample lines in /etc/modules.conf will load the bonding module, and
+select its options:
+
+alias bond0 bonding
+options bond0 mode=balance-alb miimon=100
+
+ Replace the sample parameters with the appropriate set of
+options for your configuration.
+
+ Finally run "/etc/rc.d/init.d/network restart" as root. This
+will restart the networking subsystem and your bond link should be now
+up and running.
+
+
+3.3 Configuring Bonding Manually
+--------------------------------
+
+ This section applies to distros whose network initialization
+scripts (the sysconfig or initscripts package) do not have specific
+knowledge of bonding. One such distro is SuSE Linux Enterprise Server
+version 8.
+
+ The general methodology for these systems is to place the
+bonding module parameters into /etc/modprobe.conf, then add modprobe
+and/or ifenslave commands to the system's global init script. The
+name of the global init script differs; for sysconfig, it is
+/etc/init.d/boot.local and for initscripts it is /etc/rc.d/rc.local.
+
+ For example, if you wanted to make a simple bond of two e100
+devices (presumed to be eth0 and eth1), and have it persist across
+reboots, edit the appropriate file (/etc/init.d/boot.local or
+/etc/rc.d/rc.local), and add the following:
+
+modprobe bonding -obond0 mode=balance-alb miimon=100
+modprobe e100
+ifconfig bond0 192.168.1.1 netmask 255.255.255.0 up
+ifenslave bond0 eth0
+ifenslave bond0 eth1
+
+ Replace the example bonding module parameters and bond0
+network configuration (IP address, netmask, etc) with the appropriate
+values for your configuration. The above example loads the bonding
+module with the name "bond0," this simplifies the naming if multiple
+bonding modules are loaded (each successive instance of the module is
+given a different name, and the module instance names match the
+bonding interface names).
+
+ Unfortunately, this method will not provide support for the
+ifup and ifdown scripts on the bond devices. To reload the bonding
+configuration, it is necessary to run the initialization script, e.g.,
+
+# /etc/init.d/boot.local
+
+ or
+
+# /etc/rc.d/rc.local
+
+ It may be desirable in such a case to create a separate script
+which only initializes the bonding configuration, then call that
+separate script from within boot.local. This allows for bonding to be
+enabled without re-running the entire global init script.
+
+ To shut down the bonding devices, it is necessary to first
+mark the bonding device itself as being down, then remove the
+appropriate device driver modules. For our example above, you can do
+the following:
+
+# ifconfig bond0 down
+# rmmod bond0
+# rmmod e100
+
+ Again, for convenience, it may be desirable to create a script
+with these commands.
+
+
+3.4 Configuring Multiple Bonds
+------------------------------
+
+ This section contains information on configuring multiple
+bonding devices with differing options. If you require multiple
+bonding devices, but all with the same options, see the "max_bonds"
+module paramter, documented above.
+
+ To create multiple bonding devices with differing options, it
+is necessary to load the bonding driver multiple times. Note that
+current versions of the sysconfig network initialization scripts
+handle this automatically; if your distro uses these scripts, no
+special action is needed. See the section Configuring Bonding
+Devices, above, if you're not sure about your network initialization
+scripts.
+
+ To load multiple instances of the module, it is necessary to
+specify a different name for each instance (the module loading system
+requires that every loaded module, even multiple instances of the same
+module, have a unique name). This is accomplished by supplying
+multiple sets of bonding options in /etc/modprobe.conf, for example:
+
+alias bond0 bonding
+options bond0 -o bond0 mode=balance-rr miimon=100
+
+alias bond1 bonding
+options bond1 -o bond1 mode=balance-alb miimon=50
+
+ will load the bonding module two times. The first instance is
+named "bond0" and creates the bond0 device in balance-rr mode with an
+miimon of 100. The second instance is named "bond1" and creates the
+bond1 device in balance-alb mode with an miimon of 50.
+
+ This may be repeated any number of times, specifying a new and
+unique name in place of bond0 or bond1 for each instance.
+
+ When the appropriate module paramters are in place, then
+configure bonding according to the instructions for your distro.
+
+5. Querying Bonding Configuration
+=================================
+
+5.1 Bonding Configuration
+-------------------------
+
+ Each bonding device has a read-only file residing in the
+/proc/net/bonding directory. The file contents include information
+about the bonding configuration, options and state of each slave.
+
+ For example, the contents of /proc/net/bonding/bond0 after the
+driver is loaded with parameters of mode=0 and miimon=1000 is
+generally as follows:
+
+ Ethernet Channel Bonding Driver: 2.6.1 (October 29, 2004)
Bonding Mode: load balancing (round-robin)
Currently Active Slave: eth0
MII Status: up
@@ -531,15 +760,23 @@ parameters of mode=0 and miimon=1000 is shown below.
MII Status: up
Link Failure Count: 1
-2) Network verification
------------------------
-The network configuration can be verified using the ifconfig command. In
-the example below, the bond0 interface is the master (MASTER) while eth0 and
-eth1 are slaves (SLAVE). Notice all slaves of bond0 have the same MAC address
-(HWaddr) as bond0 for all modes except TLB and ALB that require a unique MAC
-address for each slave.
+ The precise format and contents will change depending upon the
+bonding configuration, state, and version of the bonding driver.
+
+5.2 Network configuration
+-------------------------
+
+ The network configuration can be inspected using the ifconfig
+command. Bonding devices will have the MASTER flag set; Bonding slave
+devices will have the SLAVE flag set. The ifconfig output does not
+contain information on which slaves are associated with which masters.
+
+ In the example below, the bond0 interface is the master
+(MASTER) while eth0 and eth1 are slaves (SLAVE). Notice all slaves of
+bond0 have the same MAC address (HWaddr) as bond0 for all modes except
+TLB and ALB that require a unique MAC address for each slave.
-[root]# /sbin/ifconfig
+# /sbin/ifconfig
bond0 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 MASTER MULTICAST MTU:1500 Metric:1
@@ -563,430 +800,819 @@ eth1 Link encap:Ethernet HWaddr 00:C0:F0:1F:37:B4
collisions:0 txqueuelen:100
Interrupt:9 Base address:0x1400
+6. Switch Configuration
+=======================
+
+ For this section, "switch" refers to whatever system the
+bonded devices are directly connected to (i.e., where the other end of
+the cable plugs into). This may be an actual dedicated switch device,
+or it may be another regular system (e.g., another computer running
+Linux),
+
+ The active-backup, balance-tlb and balance-alb modes do not
+require any specific configuration of the switch.
+
+ The 802.3ad mode requires that the switch have the appropriate
+ports configured as an 802.3ad aggregation. The precise method used
+to configure this varies from switch to switch, but, for example, a
+Cisco 3550 series switch requires that the appropriate ports first be
+grouped together in a single etherchannel instance, then that
+etherchannel is set to mode "lacp" to enable 802.3ad (instead of
+standard EtherChannel).
+
+ The balance-rr, balance-xor and broadcast modes generally
+require that the switch have the appropriate ports grouped together.
+The nomenclature for such a group differs between switches, it may be
+called an "etherchannel" (as in the Cisco example, above), a "trunk
+group" or some other similar variation. For these modes, each switch
+will also have its own configuration options for the switch's transmit
+policy to the bond. Typical choices include XOR of either the MAC or
+IP addresses. The transmit policy of the two peers does not need to
+match. For these three modes, the bonding mode really selects a
+transmit policy for an EtherChannel group; all three will interoperate
+with another EtherChannel group.
+
+
+7. 802.1q VLAN Support
+======================
+
+ It is possible to configure VLAN devices over a bond interface
+using the 8021q driver. However, only packets coming from the 8021q
+driver and passing through bonding will be tagged by default. Self
+generated packets, for example, bonding's learning packets or ARP
+packets generated by either ALB mode or the ARP monitor mechanism, are
+tagged internally by bonding itself. As a result, bonding must
+"learn" the VLAN IDs configured above it, and use those IDs to tag
+self generated packets.
+
+ For reasons of simplicity, and to support the use of adapters
+that can do VLAN hardware acceleration offloding, the bonding
+interface declares itself as fully hardware offloaing capable, it gets
+the add_vid/kill_vid notifications to gather the necessary
+information, and it propagates those actions to the slaves. In case
+of mixed adapter types, hardware accelerated tagged packets that
+should go through an adapter that is not offloading capable are
+"un-accelerated" by the bonding driver so the VLAN tag sits in the
+regular location.
+
+ VLAN interfaces *must* be added on top of a bonding interface
+only after enslaving at least one slave. The bonding interface has a
+hardware address of 00:00:00:00:00:00 until the first slave is added.
+If the VLAN interface is created prior to the first enslavement, it
+would pick up the all-zeroes hardware address. Once the first slave
+is attached to the bond, the bond device itself will pick up the
+slave's hardware address, which is then available for the VLAN device.
+
+ Also, be aware that a similar problem can occur if all slaves
+are released from a bond that still has one or more VLAN interfaces on
+top of it. When a new slave is added, the bonding interface will
+obtain its hardware address from the first slave, which might not
+match the hardware address of the VLAN interfaces (which was
+ultimately copied from an earlier slave).
+
+ There are two methods to insure that the VLAN device operates
+with the correct hardware address if all slaves are removed from a
+bond interface:
+
+ 1. Remove all VLAN interfaces then recreate them
+
+ 2. Set the bonding interface's hardware address so that it
+matches the hardware address of the VLAN interfaces.
+
+ Note that changing a VLAN interface's HW address would set the
+underlying device -- i.e. the bonding interface -- to promiscouos
+mode, which might not be what you want.
+
+
+8. Link Monitoring
+==================
-Frequently Asked Questions
-==========================
-
-1. Is it SMP safe?
-
- Yes. The old 2.0.xx channel bonding patch was not SMP safe.
- The new driver was designed to be SMP safe from the start.
-
-2. What type of cards will work with it?
-
- Any Ethernet type cards (you can even mix cards - a Intel
- EtherExpress PRO/100 and a 3com 3c905b, for example).
- You can even bond together Gigabit Ethernet cards!
-
-3. How many bonding devices can I have?
-
- There is no limit.
-
-4. How many slaves can a bonding device have?
-
- Limited by the number of network interfaces Linux supports and/or the
- number of network cards you can place in your system.
-
-5. What happens when a slave link dies?
+ The bonding driver at present supports two schemes for
+monitoring a slave device's link state: the ARP monitor and the MII
+monitor.
+
+ At the present time, due to implementation restrictions in the
+bonding driver itself, it is not possible to enable both ARP and MII
+monitoring simultaneously.
+
+8.1 ARP Monitor Operation
+-------------------------
+
+ The ARP monitor operates as its name suggests: it sends ARP
+queries to one or more designated peer systems on the network, and
+uses the response as an indication that the link is operating. This
+gives some assurance that traffic is actually flowing to and from one
+or more peers on the local network.
+
+ The ARP monitor relies on the device driver itself to verify
+that traffic is flowing. In particular, the driver must keep up to
+date the last receive time, dev->last_rx, and transmit start time,
+dev->trans_start. If these are not updated by the driver, then the
+ARP monitor will immediately fail any slaves using that driver, and
+those slaves will stay down. If networking monitoring (tcpdump, etc)
+shows the ARP requests and replies on the network, then it may be that
+your device driver is not updating last_rx and trans_start.
+
+8.2 Configuring Multiple ARP Targets
+------------------------------------
- If your ethernet cards support MII or ETHTOOL link status monitoring
- and the MII monitoring has been enabled in the driver (see description
- of module parameters), there will be no adverse consequences. This
- release of the bonding driver knows how to get the MII information and
- enables or disables its slaves according to their link status.
- See section on High Availability for additional information.
-
- For ethernet cards not supporting MII status, the arp_interval and
- arp_ip_target parameters must be specified for bonding to work
- correctly. If packets have not been sent or received during the
- specified arp_interval duration, an ARP request is sent to the
- targets to generate send and receive traffic. If after this
- interval, either the successful send and/or receive count has not
- incremented, the next slave in the sequence will become the active
- slave.
-
- If neither mii_monitor and arp_interval is configured, the bonding
- driver will not handle this situation very well. The driver will
- continue to send packets but some packets will be lost. Retransmits
- will cause serious degradation of performance (in the case when one
- of two slave links fails, 50% packets will be lost, which is a serious
- problem for both TCP and UDP).
+ While ARP monitoring can be done with just one target, it can
+be useful in a High Availability setup to have several targets to
+monitor. In the case of just one target, the target itself may go
+down or have a problem making it unresponsive to ARP requests. Having
+an additional target (or several) increases the reliability of the ARP
+monitoring.
-6. Can bonding be used for High Availability?
+ Multiple ARP targets must be seperated by commas as follows:
- Yes, if you use MII monitoring and ALL your cards support MII link
- status reporting. See section on High Availability for more
- information.
+# example options for ARP monitoring with three targets
+alias bond0 bonding
+options bond0 arp_interval=60 arp_ip_target=192.168.0.1,192.168.0.3,192.168.0.9
-7. Which switches/systems does it work with?
+ For just a single target the options would resemble:
- In round-robin and XOR mode, it works with systems that support
- trunking:
+# example options for ARP monitoring with one target
+alias bond0 bonding
+options bond0 arp_interval=60 arp_ip_target=192.168.0.100
- * Many Cisco switches and routers (look for EtherChannel support).
- * SunTrunking software.
- * Alteon AceDirector switches / WebOS (use Trunks).
- * BayStack Switches (trunks must be explicitly configured). Stackable
- models (450) can define trunks between ports on different physical
- units.
- * Linux bonding, of course !
- In 802.3ad mode, it works with with systems that support IEEE 802.3ad
- Dynamic Link Aggregation:
+8.3 MII Monitor Operation
+-------------------------
+
+ The MII monitor monitors only the carrier state of the local
+network interface. It accomplishes this in one of three ways: by
+depending upon the device driver to maintain its carrier state, by
+querying the device's MII registers, or by making an ethtool query to
+the device.
+
+ If the use_carrier module parameter is 1 (the default value),
+then the MII monitor will rely on the driver for carrier state
+information (via the netif_carrier subsystem). As explained in the
+use_carrier parameter information, above, if the MII monitor fails to
+detect carrier loss on the device (e.g., when the cable is physically
+disconnected), it may be that the driver does not support
+netif_carrier.
+
+ If use_carrier is 0, then the MII monitor will first query the
+device's (via ioctl) MII registers and check the link state. If that
+request fails (not just that it returns carrier down), then the MII
+monitor will make an ethtool ETHOOL_GLINK request to attempt to obtain
+the same information. If both methods fail (i.e., the driver either
+does not support or had some error in processing both the MII register
+and ethtool requests), then the MII monitor will assume the link is
+up.
+
+9. Potential Sources of Trouble
+===============================
+
+9.1 Adventures in Routing
+-------------------------
+
+ When bonding is configured, it is important that the slave
+devices not have routes that supercede routes of the master (or,
+generally, not have routes at all). For example, suppose the bonding
+device bond0 has two slaves, eth0 and eth1, and the routing table is
+as follows:
- * Extreme networks Summit 7i (look for link-aggregation).
- * Many Cisco switches and routers (look for LACP support; this may
- require an upgrade to your IOS software; LACP support was added
- by Cisco in late 2002).
- * Foundry Big Iron 4000
+Kernel IP routing table
+Destination Gateway Genmask Flags MSS Window irtt Iface
+10.0.0.0 0.0.0.0 255.255.0.0 U 40 0 0 eth0
+10.0.0.0 0.0.0.0 255.255.0.0 U 40 0 0 eth1
+10.0.0.0 0.0.0.0 255.255.0.0 U 40 0 0 bond0
+127.0.0.0 0.0.0.0 255.0.0.0 U 40 0 0 lo
- In active-backup, balance-tlb and balance-alb modes, it should work
- with any Layer-II switch.
+ This routing configuration will likely still update the
+receive/transmit times in the driver (needed by the ARP monitor), but
+may bypass the bonding driver (because outgoing traffic to, in this
+case, another host on network 10 would use eth0 or eth1 before bond0).
+
+ The ARP monitor (and ARP itself) may become confused by this
+configuration, because ARP requests (generated by the ARP monitor)
+will be sent on one interface (bond0), but the corresponding reply
+will arrive on a different interface (eth0). This reply looks to ARP
+as an unsolicited ARP reply (because ARP matches replies on an
+interface basis), and is discarded. The MII monitor is not affected
+by the state of the routing table.
+
+ The solution here is simply to insure that slaves do not have
+routes of their own, and if for some reason they must, those routes do
+not supercede routes of their master. This should generally be the
+case, but unusual configurations or errant manual or automatic static
+route additions may cause trouble.
+
+9.2 Ethernet Device Renaming
+----------------------------
+ On systems with network configuration scripts that do not
+associate physical devices directly with network interface names (so
+that the same physical device always has the same "ethX" name), it may
+be necessary to add some special logic to either /etc/modules.conf or
+/etc/modprobe.conf (depending upon which is installed on the system).
-8. Where does a bonding device get its MAC address from?
+ For example, given a modules.conf containing the following:
- If not explicitly configured with ifconfig, the MAC address of the
- bonding device is taken from its first slave device. This MAC address
- is then passed to all following slaves and remains persistent (even if
- the the first slave is removed) until the bonding device is brought
- down or reconfigured.
+alias bond0 bonding
+options bond0 mode=some-mode miimon=50
+alias eth0 tg3
+alias eth1 tg3
+alias eth2 e1000
+alias eth3 e1000
+
+ If neither eth0 and eth1 are slaves to bond0, then when the
+bond0 interface comes up, the devices may end up reordered. This
+happens because bonding is loaded first, then its slave device's
+drivers are loaded next. Since no other drivers have been loaded,
+when the e1000 driver loads, it will receive eth0 and eth1 for its
+devices, but the bonding configuration tries to enslave eth2 and eth3
+(which may later be assigned to the tg3 devices).
+
+ Adding the following:
+
+add above bonding e1000 tg3
+
+ causes modprobe to load e1000 then tg3, in that order, when
+bonding is loaded. This command is fully documented in the
+modules.conf manual page.
+
+ On systems utilizing modprobe.conf (or modprobe.conf.local),
+an equivalent problem can occur. In this case, the following can be
+added to modprobe.conf (or modprobe.conf.local, as appropriate), as
+follows (all on one line; it has been split here for clarity):
+
+install bonding /sbin/modprobe tg3; /sbin/modprobe e1000;
+ /sbin/modprobe --ignore-install bonding
+
+ This will, when loading the bonding module, rather than
+performing the normal action, instead execute the provided command.
+This command loads the device drivers in the order needed, then calls
+modprobe with --ingore-install to cause the normal action to then take
+place. Full documentation on this can be found in the modprobe.conf
+and modprobe manual pages.
+
+9.3. Painfully Slow Or No Failed Link Detection By Miimon
+---------------------------------------------------------
+
+ By default, bonding enables the use_carrier option, which
+instructs bonding to trust the driver to maintain carrier state.
+
+ As discussed in the options section, above, some drivers do
+not support the netif_carrier_on/_off link state tracking system.
+With use_carrier enabled, bonding will always see these links as up,
+regardless of their actual state.
+
+ Additionally, other drivers do support netif_carrier, but do
+not maintain it in real time, e.g., only polling the link state at
+some fixed interval. In this case, miimon will detect failures, but
+only after some long period of time has expired. If it appears that
+miimon is very slow in detecting link failures, try specifying
+use_carrier=0 to see if that improves the failure detection time. If
+it does, then it may be that the driver checks the carrier state at a
+fixed interval, but does not cache the MII register values (so the
+use_carrier=0 method of querying the registers directly works). If
+use_carrier=0 does not improve the failover, then the driver may cache
+the registers, or the problem may be elsewhere.
+
+ Also, remember that miimon only checks for the device's
+carrier state. It has no way to determine the state of devices on or
+beyond other ports of a switch, or if a switch is refusing to pass
+traffic while still maintaining carrier on.
+
+10. SNMP agents
+===============
+
+ If running SNMP agents, the bonding driver should be loaded
+before any network drivers participating in a bond. This requirement
+is due to the the interface index (ipAdEntIfIndex) being associated to
+the first interface found with a given IP address. That is, there is
+only one ipAdEntIfIndex for each IP address. For example, if eth0 and
+eth1 are slaves of bond0 and the driver for eth0 is loaded before the
+bonding driver, the interface for the IP address will be associated
+with the eth0 interface. This configuration is shown below, the IP
+address 192.168.1.1 has an interface index of 2 which indexes to eth0
+in the ifDescr table (ifDescr.2).
- If you wish to change the MAC address, you can set it with ifconfig:
+ interfaces.ifTable.ifEntry.ifDescr.1 = lo
+ interfaces.ifTable.ifEntry.ifDescr.2 = eth0
+ interfaces.ifTable.ifEntry.ifDescr.3 = eth1
+ interfaces.ifTable.ifEntry.ifDescr.4 = eth2
+ interfaces.ifTable.ifEntry.ifDescr.5 = eth3
+ interfaces.ifTable.ifEntry.ifDescr.6 = bond0
+ ip.ipAddrTable.ipAddrEntry.ipAdEntIfIndex.10.10.10.10 = 5
+ ip.ipAddrTable.ipAddrEntry.ipAdEntIfIndex.192.168.1.1 = 2
+ ip.ipAddrTable.ipAddrEntry.ipAdEntIfIndex.10.74.20.94 = 4
+ ip.ipAddrTable.ipAddrEntry.ipAdEntIfIndex.127.0.0.1 = 1
- # ifconfig bond0 hw ether 00:11:22:33:44:55
+ This problem is avoided by loading the bonding driver before
+any network drivers participating in a bond. Below is an example of
+loading the bonding driver first, the IP address 192.168.1.1 is
+correctly associated with ifDescr.2.
- The MAC address can be also changed by bringing down/up the device
- and then changing its slaves (or their order):
+ interfaces.ifTable.ifEntry.ifDescr.1 = lo
+ interfaces.ifTable.ifEntry.ifDescr.2 = bond0
+ interfaces.ifTable.ifEntry.ifDescr.3 = eth0
+ interfaces.ifTable.ifEntry.ifDescr.4 = eth1
+ interfaces.ifTable.ifEntry.ifDescr.5 = eth2
+ interfaces.ifTable.ifEntry.ifDescr.6 = eth3
+ ip.ipAddrTable.ipAddrEntry.ipAdEntIfIndex.10.10.10.10 = 6
+ ip.ipAddrTable.ipAddrEntry.ipAdEntIfIndex.192.168.1.1 = 2
+ ip.ipAddrTable.ipAddrEntry.ipAdEntIfIndex.10.74.20.94 = 5
+ ip.ipAddrTable.ipAddrEntry.ipAdEntIfIndex.127.0.0.1 = 1
- # ifconfig bond0 down ; modprobe -r bonding
- # ifconfig bond0 .... up
- # ifenslave bond0 eth...
+ While some distributions may not report the interface name in
+ifDescr, the association between the IP address and IfIndex remains
+and SNMP functions such as Interface_Scan_Next will report that
+association.
- This method will automatically take the address from the next slave
- that will be added.
+11. Promiscuous mode
+====================
- To restore your slaves' MAC addresses, you need to detach them
- from the bond (`ifenslave -d bond0 eth0'). The bonding driver will then
- restore the MAC addresses that the slaves had before they were enslaved.
+ When running network monitoring tools, e.g., tcpdump, it is
+common to enable promiscuous mode on the device, so that all traffic
+is seen (instead of seeing only traffic destined for the local host).
+The bonding driver handles promiscuous mode changes to the bonding
+master device (e.g., bond0), and propogates the setting to the slave
+devices.
-9. Which transmit polices can be used?
+ For the balance-rr, balance-xor, broadcast, and 802.3ad modes,
+the promiscuous mode setting is propogated to all slaves.
- Round-robin, based on the order of enslaving, the output device
- is selected base on the next available slave. Regardless of
- the source and/or destination of the packet.
+ For the active-backup, balance-tlb and balance-alb modes, the
+promiscuous mode setting is propogated only to the active slave.
- Active-backup policy that ensures that one and only one device will
- transmit at any given moment. Active-backup policy is useful for
- implementing high availability solutions using two hubs (see
- section on High Availability).
+ For balance-tlb mode, the active slave is the slave currently
+receiving inbound traffic.
- XOR, based on (src hw addr XOR dst hw addr) % slave count. This
- policy selects the same slave for each destination hw address.
+ For balance-alb mode, the active slave is the slave used as a
+"primary." This slave is used for mode-specific control traffic, for
+sending to peers that are unassigned or if the load is unbalanced.
- Broadcast policy transmits everything on all slave interfaces.
+ For the active-backup, balance-tlb and balance-alb modes, when
+the active slave changes (e.g., due to a link failure), the
+promiscuous setting will be propogated to the new active slave.
- 802.3ad, based on XOR but distributes traffic among all interfaces
- in the active aggregator.
+12. High Availability Information
+=================================
- Transmit load balancing (balance-tlb) balances the traffic
- according to the current load on each slave. The balancing is
- clients based and the least loaded slave is selected for each new
- client. The load of each slave is calculated relative to its speed
- and enables load balancing in mixed speed teams.
+ High Availability refers to configurations that provide
+maximum network availability by having redundant or backup devices,
+links and switches between the host and the rest of the world.
- Adaptive load balancing (balance-alb) uses the Transmit load
- balancing for the transmit load. The receive load is balanced only
- among the group of highest speed active slaves in the bond. The
- load is distributed with round-robin i.e. next available slave in
- the high speed group of active slaves.
+ There are currently two basic methods for configuring to
+maximize availability. They are dependent on the network topology and
+the primary goal of the configuration, but in general, a configuration
+can be optimized for maximum available bandwidth, or for maximum
+network availability.
-High Availability
-=================
+12.1 High Availability in a Single Switch Topology
+--------------------------------------------------
-To implement high availability using the bonding driver, the driver needs to be
-compiled as a module, because currently it is the only way to pass parameters
-to the driver. This may change in the future.
+ If two hosts (or a host and a switch) are directly connected
+via multiple physical links, then there is no network availability
+penalty for optimizing for maximum bandwidth: there is only one switch
+(or peer), so if it fails, you have no alternative access to fail over
+to.
-High availability is achieved by using MII or ETHTOOL status reporting. You
-need to verify that all your interfaces support MII or ETHTOOL link status
-reporting. On Linux kernel 2.2.17, all the 100 Mbps capable drivers and
-yellowfin gigabit driver support MII. To determine if ETHTOOL link reporting
-is available for interface eth0, type "ethtool eth0" and the "Link detected:"
-line should contain the correct link status. If your system has an interface
-that does not support MII or ETHTOOL status reporting, a failure of its link
-will not be detected! A message indicating MII and ETHTOOL is not supported by
-a network driver is logged when the bonding driver is loaded with a non-zero
-miimon value.
+Example 1 : host to switch (or other host)
-The bonding driver can regularly check all its slaves links using the ETHTOOL
-IOCTL (ETHTOOL_GLINK command) or by checking the MII status registers. The
-check interval is specified by the module argument "miimon" (MII monitoring).
-It takes an integer that represents the checking time in milliseconds. It
-should not come to close to (1000/HZ) (10 milli-seconds on i386) because it
-may then reduce the system interactivity. A value of 100 seems to be a good
-starting point. It means that a dead link will be detected at most 100
-milli-seconds after it goes down.
+ +----------+ +----------+
+ | |eth0 eth0| switch |
+ | Host A +--------------------------+ or |
+ | +--------------------------+ other |
+ | |eth1 eth1| host |
+ +----------+ +----------+
-Example:
- # modprobe bonding miimon=100
+12.1.1 Bonding Mode Selection for single switch topology
+--------------------------------------------------------
+
+ This configuration is the easiest to set up and to understand,
+although you will have to decide which bonding mode best suits your
+needs. The tradeoffs for each mode are detailed below:
+
+balance-rr: This mode is the only mode that will permit a single
+ TCP/IP connection to stripe traffic across multiple
+ interfaces. It is therefore the only mode that will allow a
+ single TCP/IP stream to utilize more than one interface's
+ worth of throughput. This comes at a cost, however: the
+ striping often results in peer systems receiving packets out
+ of order, causing TCP/IP's congestion control system to kick
+ in, often by retransmitting segments.
+
+ It is possible to adjust TCP/IP's congestion limits by
+ altering the net.ipv4.tcp_reordering sysctl parameter. The
+ usual default value is 3, and the maximum useful value is 127.
+ For a four interface balance-rr bond, expect that a single
+ TCP/IP stream will utilize no more than approximately 2.3
+ interface's worth of throughput, even after adjusting
+ tcp_reordering.
+
+ If you are utilizing protocols other than TCP/IP, UDP for
+ example, and your application can tolerate out of order
+ delivery, then this mode can allow for single stream datagram
+ performance that scales near linearly as interfaces are added
+ to the bond.
+
+ This mode requires the switch to have the appropriate ports
+ configured for "etherchannel" or "trunking."
+
+active-backup: There is not much advantage in this network topology to
+ the active-backup mode, as the inactive backup devices are all
+ connected to the same peer as the primary. In this case, a
+ load balancing mode (with link monitoring) will provide the
+ same level of network availability, but with increased
+ available bandwidth. On the plus side, it does not require
+ any configuration of the switch.
+
+balance-xor: This mode will limit traffic such that packets destined
+ for specific peers will always be sent over the same
+ interface. Since the destination is determined by the MAC
+ addresses involved, this may be desirable if you have a large
+ network with many hosts. It is likely to be suboptimal if all
+ your traffic is passed through a single router, however. As
+ with balance-rr, the switch ports need to be configured for
+ "etherchannel" or "trunking."
+
+broadcast: Like active-backup, there is not much advantage to this
+ mode in this type of network topology.
+
+802.3ad: This mode can be a good choice for this type of network
+ topology. The 802.3ad mode is an IEEE standard, so all peers
+ that implement 802.3ad should interoperate well. The 802.3ad
+ protocol includes automatic configuration of the aggregates,
+ so minimal manual configuration of the switch is needed
+ (typically only to designate that some set of devices is
+ usable for 802.3ad). The 802.3ad standard also mandates that
+ frames be delivered in order (within certain limits), so in
+ general single connections will not see misordering of
+ packets. The 802.3ad mode does have some drawbacks: the
+ standard mandates that all devices in the aggregate operate at
+ the same speed and duplex. Also, as with all bonding load
+ balance modes other than balance-rr, no single connection will
+ be able to utilize more than a single interface's worth of
+ bandwidth. Additionally, the linux bonding 802.3ad
+ implementation distributes traffic by peer (using an XOR of
+ MAC addresses), so in general all traffic to a particular
+ destination will use the same interface. Finally, the 802.3ad
+ mode mandates the use of the MII monitor, therefore, the ARP
+ monitor is not available in this mode.
+
+balance-tlb: This mode is also a good choice for this type of
+ topology. It has no special switch configuration
+ requirements, and balances outgoing traffic by peer, in a
+ vaguely intelligent manner (not a simple XOR as in balance-xor
+ or 802.3ad mode), so that unlucky MAC addresses will not all
+ "bunch up" on a single interface. Interfaces may be of
+ differing speeds. On the down side, in this mode all incoming
+ traffic arrives over a single interface, this mode requires
+ certain ethtool support in the network device driver of the
+ slave interfaces, and the ARP monitor is not available.
+
+balance-alb: This mode is everything that balance-tlb is, and more. It
+ has all of the features (and restrictions) of balance-tlb, and
+ will also balance incoming traffic from peers (as described in
+ the Bonding Module Options section, above). The only extra
+ down side to this mode is that the network device driver must
+ support changing the hardware address while the device is
+ open.
+
+12.1.2 Link Monitoring for Single Switch Topology
+-------------------------------------------------
+
+ The choice of link monitoring may largely depend upon which
+mode you choose to use. The more advanced load balancing modes do not
+support the use of the ARP monitor, and are thus restricted to using
+the MII monitor (which does not provide as high a level of assurance
+as the ARP monitor).
+
+
+12.2 High Availability in a Multiple Switch Topology
+----------------------------------------------------
+
+ With multiple switches, the configuration of bonding and the
+network changes dramatically. In multiple switch topologies, there is
+a tradeoff between network availability and usable bandwidth.
+
+ Below is a sample network, configured to maximize the
+availability of the network:
-Or, put the following line in /etc/modprobe.conf:
+ | |
+ |port3 port3|
+ +-----+----+ +-----+----+
+ | |port2 ISL port2| |
+ | switch A +--------------------------+ switch B |
+ | | | |
+ +-----+----+ +-----++---+
+ |port1 port1|
+ | +-------+ |
+ +-------------+ host1 +---------------+
+ eth0 +-------+ eth1
- options bond0 miimon=100
+ In this configuration, there is a link between the two
+switches (ISL, or inter switch link), and multiple ports connecting to
+the outside world ("port3" on each switch). There is no technical
+reason that this could not be extended to a third switch.
+
+12.2.1 Bonding Mode Selection for Multiple Switch Topology
+----------------------------------------------------------
+
+ In a topology such as this, the active-backup and broadcast
+modes are the only useful bonding modes; the other modes require all
+links to terminate on the same peer for them to behave rationally.
+
+active-backup: This is generally the preferred mode, particularly if
+ the switches have an ISL and play together well. If the
+ network configuration is such that one switch is specifically
+ a backup switch (e.g., has lower capacity, higher cost, etc),
+ then the primary option can be used to insure that the
+ preferred link is always used when it is available.
+
+broadcast: This mode is really a special purpose mode, and is suitable
+ only for very specific needs. For example, if the two
+ switches are not connected (no ISL), and the networks beyond
+ them are totally independant. In this case, if it is
+ necessary for some specific one-way traffic to reach both
+ independent networks, then the broadcast mode may be suitable.
+
+12.2.2 Link Monitoring Selection for Multiple Switch Topology
+-------------------------------------------------------------
+
+ The choice of link monitoring ultimately depends upon your
+switch. If the switch can reliably fail ports in response to other
+failures, then either the MII or ARP monitors should work. For
+example, in the above example, if the "port3" link fails at the remote
+end, the MII monitor has no direct means to detect this. The ARP
+monitor could be configured with a target at the remote end of port3,
+thus detecting that failure without switch support.
+
+ In general, however, in a multiple switch topology, the ARP
+monitor can provide a higher level of reliability in detecting link
+failures. Additionally, it should be configured with multiple targets
+(at least one for each switch in the network). This will insure that,
+regardless of which switch is active, the ARP monitor has a suitable
+target to query.
+
+
+12.3 Switch Behavior Issues for High Availability
+-------------------------------------------------
+
+ You may encounter issues with the timing of link up and down
+reporting by the switch.
+
+ First, when a link comes up, some switches may indicate that
+the link is up (carrier available), but not pass traffic over the
+interface for some period of time. This delay is typically due to
+some type of autonegotiation or routing protocol, but may also occur
+during switch initialization (e.g., during recovery after a switch
+failure). If you find this to be a problem, specify an appropriate
+value to the updelay bonding module option to delay the use of the
+relevant interface(s).
+
+ Second, some switches may "bounce" the link state one or more
+times while a link is changing state. This occurs most commonly while
+the switch is initializing. Again, an appropriate updelay value may
+help, but note that if all links are down, then updelay is ignored
+when any link becomes active (the slave closest to completing its
+updelay is chosen).
+
+ Note that when a bonding interface has no active links, the
+driver will immediately reuse the first link that goes up, even if
+updelay parameter was specified. If there are slave interfaces
+waiting for the updelay timeout to expire, the interface that first
+went into that state will be immediately reused. This reduces down
+time of the network if the value of updelay has been overestimated.
+
+ In addition to the concerns about switch timings, if your
+switches take a long time to go into backup mode, it may be desirable
+to not activate a backup interface immediately after a link goes down.
+Failover may be delayed via the downdelay bonding module option.
+
+13. Hardware Specific Considerations
+====================================
+
+ This section contains additional information for configuring
+bonding on specific hardware platforms, or for interfacing bonding
+with particular switches or other devices.
+
+13.1 IBM BladeCenter
+--------------------
+
+ This applies to the JS20 and similar systems.
+
+ On the JS20 blades, the bonding driver supports only
+balance-rr, active-backup, balance-tlb and balance-alb modes. This is
+largely due to the network topology inside the BladeCenter, detailed
+below.
+
+JS20 network adapter information
+--------------------------------
+
+ All JS20s come with two Broadcom Gigabit Ethernet ports
+integrated on the planar. In the BladeCenter chassis, the eth0 port
+of all JS20 blades is hard wired to I/O Module #1; similarly, all eth1
+ports are wired to I/O Module #2. An add-on Broadcom daughter card
+can be installed on a JS20 to provide two more Gigabit Ethernet ports.
+These ports, eth2 and eth3, are wired to I/O Modules 3 and 4,
+respectively.
+
+ Each I/O Module may contain either a switch or a passthrough
+module (which allows ports to be directly connected to an external
+switch). Some bonding modes require a specific BladeCenter internal
+network topology in order to function; these are detailed below.
+
+ Additional BladeCenter-specific networking information can be
+found in two IBM Redbooks (www.ibm.com/redbooks):
+
+"IBM eServer BladeCenter Networking Options"
+"IBM eServer BladeCenter Layer 2-7 Network Switching"
+
+BladeCenter networking configuration
+------------------------------------
-There are currently two policies for high availability. They are dependent on
-whether:
+ Because a BladeCenter can be configured in a very large number
+of ways, this discussion will be confined to describing basic
+configurations.
+
+ Normally, Ethernet Switch Modules (ESM) are used in I/O
+modules 1 and 2. In this configuration, the eth0 and eth1 ports of a
+JS20 will be connected to different internal switches (in the
+respective I/O modules).
+
+ An optical passthru module (OPM) connects the I/O module
+directly to an external switch. By using OPMs in I/O module #1 and
+#2, the eth0 and eth1 interfaces of a JS20 can be redirected to the
+outside world and connected to a common external switch.
+
+ Depending upon the mix of ESM and OPM modules, the network
+will appear to bonding as either a single switch topology (all OPM
+modules) or as a multiple switch topology (one or more ESM modules,
+zero or more OPM modules). It is also possible to connect ESM modules
+together, resulting in a configuration much like the example in "High
+Availability in a multiple switch topology."
+
+Requirements for specifc modes
+------------------------------
+
+ The balance-rr mode requires the use of OPM modules for
+devices in the bond, all connected to an common external switch. That
+switch must be configured for "etherchannel" or "trunking" on the
+appropriate ports, as is usual for balance-rr.
+
+ The balance-alb and balance-tlb modes will function with
+either switch modules or passthrough modules (or a mix). The only
+specific requirement for these modes is that all network interfaces
+must be able to reach all destinations for traffic sent over the
+bonding device (i.e., the network must converge at some point outside
+the BladeCenter).
+
+ The active-backup mode has no additional requirements.
+
+Link monitoring issues
+----------------------
+
+ When an Ethernet Switch Module is in place, only the ARP
+monitor will reliably detect link loss to an external switch. This is
+nothing unusual, but examination of the BladeCenter cabinet would
+suggest that the "external" network ports are the ethernet ports for
+the system, when it fact there is a switch between these "external"
+ports and the devices on the JS20 system itself. The MII monitor is
+only able to detect link failures between the ESM and the JS20 system.
+
+ When a passthrough module is in place, the MII monitor does
+detect failures to the "external" port, which is then directly
+connected to the JS20 system.
+
+Other concerns
+--------------
+
+ The Serial Over LAN link is established over the primary
+ethernet (eth0) only, therefore, any loss of link to eth0 will result
+in losing your SoL connection. It will not fail over with other
+network traffic.
+
+ It may be desirable to disable spanning tree on the switch
+(either the internal Ethernet Switch Module, or an external switch) to
+avoid fail-over delays issues when using bonding.
+
+
+14. Frequently Asked Questions
+==============================
- a) hosts are connected to a single host or switch that support trunking
+1. Is it SMP safe?
- b) hosts are connected to several different switches or a single switch that
- does not support trunking
+ Yes. The old 2.0.xx channel bonding patch was not SMP safe.
+The new driver was designed to be SMP safe from the start.
+2. What type of cards will work with it?
-1) High Availability on a single switch or host - load balancing
-----------------------------------------------------------------
-It is the easiest to set up and to understand. Simply configure the
-remote equipment (host or switch) to aggregate traffic over several
-ports (Trunk, EtherChannel, etc.) and configure the bonding interfaces.
-If the module has been loaded with the proper MII option, it will work
-automatically. You can then try to remove and restore different links
-and see in your logs what the driver detects. When testing, you may
-encounter problems on some buggy switches that disable the trunk for a
-long time if all ports in a trunk go down. This is not Linux, but really
-the switch (reboot it to ensure).
+ Any Ethernet type cards (you can even mix cards - a Intel
+EtherExpress PRO/100 and a 3com 3c905b, for example). They need not
+be of the same speed.
-Example 1 : host to host at twice the speed
+3. How many bonding devices can I have?
- +----------+ +----------+
- | |eth0 eth0| |
- | Host A +--------------------------+ Host B |
- | +--------------------------+ |
- | |eth1 eth1| |
- +----------+ +----------+
+ There is no limit.
- On each host :
- # modprobe bonding miimon=100
- # ifconfig bond0 addr
- # ifenslave bond0 eth0 eth1
+4. How many slaves can a bonding device have?
-Example 2 : host to switch at twice the speed
+ This is limited only by the number of network interfaces Linux
+supports and/or the number of network cards you can place in your
+system.
- +----------+ +----------+
- | |eth0 port1| |
- | Host A +--------------------------+ switch |
- | +--------------------------+ |
- | |eth1 port2| |
- +----------+ +----------+
+5. What happens when a slave link dies?
- On host A : On the switch :
- # modprobe bonding miimon=100 # set up a trunk on port1
- # ifconfig bond0 addr and port2
- # ifenslave bond0 eth0 eth1
+ If link monitoring is enabled, then the failing device will be
+disabled. The active-backup mode will fail over to a backup link, and
+other modes will ignore the failed link. The link will continue to be
+monitored, and should it recover, it will rejoin the bond (in whatever
+manner is appropriate for the mode). See the section on High
+Availability for additional information.
+
+ Link monitoring can be enabled via either the miimon or
+arp_interval paramters (described in the module paramters section,
+above). In general, miimon monitors the carrier state as sensed by
+the underlying network device, and the arp monitor (arp_interval)
+monitors connectivity to another host on the local network.
+
+ If no link monitoring is configured, the bonding driver will
+be unable to detect link failures, and will assume that all links are
+always available. This will likely result in lost packets, and a
+resulting degredation of performance. The precise performance loss
+depends upon the bonding mode and network configuration.
+6. Can bonding be used for High Availability?
-2) High Availability on two or more switches (or a single switch without
- trunking support)
----------------------------------------------------------------------------
-This mode is more problematic because it relies on the fact that there
-are multiple ports and the host's MAC address should be visible on one
-port only to avoid confusing the switches.
+ Yes. See the section on High Availability for details.
-If you need to know which interface is the active one, and which ones are
-backup, use ifconfig. All backup interfaces have the NOARP flag set.
+7. Which switches/systems does it work with?
-To use this mode, pass "mode=1" to the module at load time :
+ The full answer to this depends upon the desired mode.
- # modprobe bonding miimon=100 mode=active-backup
+ In the basic balance modes (balance-rr and balance-xor), it
+works with any system that supports etherchannel (also called
+trunking). Most managed switches currently available have such
+support, and many unmananged switches as well.
- or:
+ The advanced balance modes (balance-tlb and balance-alb) do
+not have special switch requirements, but do need device drivers that
+support specific features (described in the appropriate section under
+module paramters, above).
- # modprobe bonding miimon=100 mode=1
+ In 802.3ad mode, it works with with systems that support IEEE
+802.3ad Dynamic Link Aggregation. Most managed and many unmanaged
+switches currently available support 802.3ad.
-Or, put in your /etc/modprobe.conf :
+ The active-backup mode should work with any Layer-II switch.
- options bond0 miimon=100 mode=active-backup
+8. Where does a bonding device get its MAC address from?
-Example 1: Using multiple host and multiple switches to build a "no single
-point of failure" solution.
+ If not explicitly configured with ifconfig, the MAC address of
+the bonding device is taken from its first slave device. This MAC
+address is then passed to all following slaves and remains persistent
+(even if the the first slave is removed) until the bonding device is
+brought down or reconfigured.
+ If you wish to change the MAC address, you can set it with
+ifconfig:
- | |
- |port3 port3|
- +-----+----+ +-----+----+
- | |port7 ISL port7| |
- | switch A +--------------------------+ switch B |
- | +--------------------------+ |
- | |port8 port8| |
- +----++----+ +-----++---+
- port2||port1 port1||port2
- || +-------+ ||
- |+-------------+ host1 +---------------+|
- | eth0 +-------+ eth1 |
- | |
- | +-------+ |
- +--------------+ host2 +----------------+
- eth0 +-------+ eth1
+# ifconfig bond0 hw ether 00:11:22:33:44:55
-In this configuration, there is an ISL - Inter Switch Link (could be a trunk),
-several servers (host1, host2 ...) attached to both switches each, and one or
-more ports to the outside world (port3...). One and only one slave on each host
-is active at a time, while all links are still monitored (the system can
-detect a failure of active and backup links).
+ The MAC address can be also changed by bringing down/up the
+device and then changing its slaves (or their order):
-Each time a host changes its active interface, it sticks to the new one until
-it goes down. In this example, the hosts are negligibly affected by the
-expiration time of the switches' forwarding tables.
+# ifconfig bond0 down ; modprobe -r bonding
+# ifconfig bond0 .... up
+# ifenslave bond0 eth...
-If host1 and host2 have the same functionality and are used in load balancing
-by another external mechanism, it is good to have host1's active interface
-connected to one switch and host2's to the other. Such system will survive
-a failure of a single host, cable, or switch. The worst thing that may happen
-in the case of a switch failure is that half of the hosts will be temporarily
-unreachable until the other switch expires its tables.
+ This method will automatically take the address from the next
+slave that is added.
-Example 2: Using multiple ethernet cards connected to a switch to configure
- NIC failover (switch is not required to support trunking).
+ To restore your slaves' MAC addresses, you need to detach them
+from the bond (`ifenslave -d bond0 eth0'). The bonding driver will
+then restore the MAC addresses that the slaves had before they were
+enslaved.
+15. Resources and Links
+=======================
- +----------+ +----------+
- | |eth0 port1| |
- | Host A +--------------------------+ switch |
- | +--------------------------+ |
- | |eth1 port2| |
- +----------+ +----------+
+The latest version of the bonding driver can be found in the latest
+version of the linux kernel, found on http://kernel.org
- On host A : On the switch :
- # modprobe bonding miimon=100 mode=1 # (optional) minimize the time
- # ifconfig bond0 addr # for table expiration
- # ifenslave bond0 eth0 eth1
+Discussions regarding the bonding driver take place primarily on the
+bonding-devel mailing list, hosted at sourceforge.net. If you have
+questions or problems, post them to the list.
-Each time the host changes its active interface, it sticks to the new one until
-it goes down. In this example, the host is strongly affected by the expiration
-time of the switch forwarding table.
+bonding-devel@lists.sourceforge.net
+https://lists.sourceforge.net/lists/listinfo/bonding-devel
-3) Adapting to your switches' timing
-------------------------------------
-If your switches take a long time to go into backup mode, it may be
-desirable not to activate a backup interface immediately after a link goes
-down. It is possible to delay the moment at which a link will be
-completely disabled by passing the module parameter "downdelay" (in
-milliseconds, must be a multiple of miimon).
-
-When a switch reboots, it is possible that its ports report "link up" status
-before they become usable. This could fool a bond device by causing it to
-use some ports that are not ready yet. It is possible to delay the moment at
-which an active link will be reused by passing the module parameter "updelay"
-(in milliseconds, must be a multiple of miimon).
-
-A similar situation can occur when a host re-negotiates a lost link with the
-switch (a case of cable replacement).
-
-A special case is when a bonding interface has lost all slave links. Then the
-driver will immediately reuse the first link that goes up, even if updelay
-parameter was specified. (If there are slave interfaces in the "updelay" state,
-the interface that first went into that state will be immediately reused.) This
-allows to reduce down-time if the value of updelay has been overestimated.
-
-Examples :
-
- # modprobe bonding miimon=100 mode=1 downdelay=2000 updelay=5000
- # modprobe bonding miimon=100 mode=balance-rr downdelay=0 updelay=5000
-
-
-Promiscuous Sniffing notes
-==========================
-
-If you wish to bond channels together for a network sniffing
-application --- you wish to run tcpdump, or ethereal, or an IDS like
-snort, with its input aggregated from multiple interfaces using the
-bonding driver --- then you need to handle the Promiscuous interface
-setting by hand. Specifically, when you "ifconfing bond0 up" you
-must add the promisc flag there; it will be propagated down to the
-slave interfaces at ifenslave time; a full example might look like:
-
- ifconfig bond0 promisc up
- for if in eth1 eth2 ...;do
- ifconfig $if up
- ifenslave bond0 $if
- done
- snort ... -i bond0 ...
-
-Ifenslave also wants to propagate addresses from interface to
-interface, appropriately for its design functions in HA and channel
-capacity aggregating; but it works fine for unnumbered interfaces;
-just ignore all the warnings it emits.
-
-
-8021q VLAN support
-==================
+There is also a project site on sourceforge.
-It is possible to configure VLAN devices over a bond interface using the 8021q
-driver. However, only packets coming from the 8021q driver and passing through
-bonding will be tagged by default. Self generated packets, like bonding's
-learning packets or ARP packets generated by either ALB mode or the ARP
-monitor mechanism, are tagged internally by bonding itself. As a result,
-bonding has to "learn" what VLAN IDs are configured on top of it, and it uses
-those IDs to tag self generated packets.
-
-For simplicity reasons, and to support the use of adapters that can do VLAN
-hardware acceleration offloding, the bonding interface declares itself as
-fully hardware offloaing capable, it gets the add_vid/kill_vid notifications
-to gather the necessary information, and it propagates those actions to the
-slaves.
-In case of mixed adapter types, hardware accelerated tagged packets that should
-go through an adapter that is not offloading capable are "un-accelerated" by the
-bonding driver so the VLAN tag sits in the regular location.
-
-VLAN interfaces *must* be added on top of a bonding interface only after
-enslaving at least one slave. This is because until the first slave is added the
-bonding interface has a HW address of 00:00:00:00:00:00, which will be copied by
-the VLAN interface when it is created.
-
-Notice that a problem would occur if all slaves are released from a bond that
-still has VLAN interfaces on top of it. When later coming to add new slaves, the
-bonding interface would get a HW address from the first slave, which might not
-match that of the VLAN interfaces. It is recommended that either all VLANs are
-removed and then re-added, or to manually set the bonding interface's HW
-address so it matches the VLAN's. (Note: changing a VLAN interface's HW address
-would set the underlying device -- i.e. the bonding interface -- to promiscouos
-mode, which might not be what you want).
-
-
-Limitations
-===========
-The main limitations are :
- - only the link status is monitored. If the switch on the other side is
- partially down (e.g. doesn't forward anymore, but the link is OK), the link
- won't be disabled. Another way to check for a dead link could be to count
- incoming frames on a heavily loaded host. This is not applicable to small
- servers, but may be useful when the front switches send multicast
- information on their links (e.g. VRRP), or even health-check the servers.
- Use the arp_interval/arp_ip_target parameters to count incoming/outgoing
- frames.
-
-
-
-Resources and Links
-===================
-
-Current development on this driver is posted to:
- - http://www.sourceforge.net/projects/bonding/
+http://www.sourceforge.net/projects/bonding
Donald Becker's Ethernet Drivers and diag programs may be found at :
- http://www.scyld.com/network/
-You will also find a lot of information regarding Ethernet, NWay, MII, etc. at
-www.scyld.com.
-
-Patches for 2.2 kernels are at Willy Tarreau's site :
- - http://wtarreau.free.fr/pub/bonding/
- - http://www-miaif.lip6.fr/~tarreau/pub/bonding/
-
-To get latest informations about Linux Kernel development, please consult
-the Linux Kernel Mailing List Archives at :
- http://www.ussg.iu.edu/hypermail/linux/kernel/
+You will also find a lot of information regarding Ethernet, NWay, MII,
+etc. at www.scyld.com.
-- END --
diff --git a/Documentation/networking/e100.txt b/Documentation/networking/e100.txt
index df7246947858e..4ef9f7cd5dc33 100644
--- a/Documentation/networking/e100.txt
+++ b/Documentation/networking/e100.txt
@@ -140,8 +140,7 @@ Additional Configurations
NAPI
----
- NAPI (Rx polling mode) is supported in the e100 driver. NAPI is enabled
- or disabled based on the configuration of the kernel.
+ NAPI (Rx polling mode) is supported in the e100 driver.
See www.cyberus.ca/~hadi/usenix-paper.tgz for more information on NAPI.
diff --git a/Documentation/networking/ethertap.txt b/Documentation/networking/ethertap.txt
deleted file mode 100644
index 337f650d7678b..0000000000000
--- a/Documentation/networking/ethertap.txt
+++ /dev/null
@@ -1,268 +0,0 @@
-NOTE: Ethertap is now an obsolete facility, and is scheduled
- to be removed in the 2.5.x kernel series. Those writing
- applications using ethertap should convert their code to
- use the TUN/TAP driver instead, see 'tuntap.txt' in this
- directory for more details. -DaveM
-
-Ethertap programming mini-HOWTO
--------------------------------
-
-The ethertap driver was written by Jay Schulist <jschlst@samba.org>,
-you should contact him for further information. This document was written by
-bert hubert <bert.hubert@netherlabs.nl>. Updates are welcome.
-
-What ethertap can do for you
-----------------------------
-
-Ethertap allows you to easily run your own network stack from userspace.
-Tunnels can benefit greatly from this. You can also use it to do network
-experiments. The alternative would be to use a raw socket to send data and
-use libpcap to receive it. Using ethertap saves you this multiplicity and
-also does ARP for you if you want.
-
-The more technical blurb:
-
-Ethertap provides packet reception and transmission for user space programs.
-It can be viewed as a simple Ethernet device, which instead of receiving
-packets from a network wire, it receives them from user space.
-
-Ethertap can be used for anything from AppleTalk to IPX to even building
-bridging tunnels. It also has many other general purpose uses.
-
-Configuring your kernel
------------------------
-
-Firstly, you need this in Networking Options:
-
- #
- # Code maturity level options
- #
- CONFIG_EXPERIMENTAL=y
-
-Then you need Netlink support:
-
- CONFIG_NETLINK=y
-
-This allows the kernel to exchange data with userspace applications. There
-are two ways of doing this, the new way works with netlink sockets and I
-have no experience with that yet. ANK uses it in his excellent iproute2
-package, see for example rtmon.c. iproute2 can be found on
-ftp://ftp.tux.org/pub/net/ip-routing/iproute2*
-
-The new way is described, partly in netlink(7), available on
-http://www.europe.redhat.com/documentation/man-pages/man7/netlink.7.php3
-
-There is also a Netlink-HOWTO, available on http://snafu.freedom.org/linux2.2/docs/netlink-HOWTO.html
-Sadly I know of no code using ethertap with this new interface.
-
-The older way works by opening character special files with major node 36.
-Enable this with:
-
- CONFIG_NETLINK_DEV=m
-
-Please be advised that this support is going to be dropped somewhere in the
-future!
-
-Then finally in the Network Devices section,
-
- CONFIG_ETHERTAP=m
-
-You can include it directly in the kernel if you want, of course, no need
-for modules.
-
-Setting it all up
------------------
-
-First we need to create the /dev/tap0 device node:
-
- # mknod /dev/tap0 c 36 16
- # mknod /dev/tap1 c 36 17
- (etc)
-
-Include the relevant modules (ethertap.o, netlink_dev.o, perhaps netlink.o),
-and bring up your tap0 device:
-
- # ifconfig tap0 10.0.0.123 up
-
-Now your device is up and running, you can ping it as well. This is what
-confused me to no end, because nothing is connected to our ethertap as yet,
-how is it that we can ping it?
-
-It turns out that the ethertap is just like a regular network interface -
-even when it's down you can ping it. We need to route stuff to it:
-
- # route add -host 10.0.0.124 gw 10.0.0.123
-
-Now we can read /dev/tap0 and when we ping 10.0.0.124 from our
-localhost, output should appear on the screen.
-
- # cat /dev/tap0
- :ßVU:9````````````````````````þýþET@?'
-
-
-Getting this to work from other hosts
--------------------------------------
-
-For this to work, you often need proxy ARP.
-
- # echo 1 > /proc/sys/net/ipv4/conf/eth0/proxy_arp
-
-eth0 here stands for the interface that connects to 'other hosts'.
-
-Chances are that you are trying this on a non-routing desktop computer, so
-you need to enable ip forwarding:
-
- # echo 1 > /proc/sys/net/ipv4/ip_forward
-
-You should now be able to ping 10.0.0.124 from other hosts on your
-10.0.0.0/8 subnet. If you are using public ip space, it should work from
-everywhere.
-
-ARP
----
-
-If we were to take things very literally, your tcp/ip pseudo stack would
-also have to implement ARP and MAC addresses. This is often a bit silly as
-the ethertap device is a figment of our imagination anyway. However, should
-you want to go 'all the way', you can add the 'arp' flag to ifconfig:
-
- # ifconfig tap0 10.0.0.123 up arp
-
-This may also be useful when implementing a bridge, which needs to bridge
-ARP packets as well.
-
-The sample program below will no longer work then, because it does not
-implement ARP.
-
-Sample program
---------------
-
-A sample program is included somewhere in the bowels of the netfilter
-source. I've extracted this program and list it here. It implements a very
-tiny part of the IP stack and can respond to any pings it receives. It gets
-confused if it receives ARP, as it tries to parse it by treating it as an IP
-packet.
-
-/* Simple program to listen to /dev/tap0 and reply to pings. */
-#include <fcntl.h>
-#include <netinet/ip.h>
-#include <netinet/ip_icmp.h>
-#if defined(__GLIBC__) && (__GLIBC__ == 2)
-#include <netinet/tcp.h>
-#include <netinet/udp.h>
-#else
-#include <linux/tcp.h>
-#include <linux/udp.h>
-#endif
-#include <string.h>
-#include <stdio.h>
-#include <errno.h>
-#include <unistd.h>
-
-u_int16_t csum_partial(void *buffer, unsigned int len, u_int16_t prevsum)
-{
- u_int32_t sum = 0;
- u_int16_t *ptr = buffer;
-
- while (len > 1) {
- sum += *ptr++;
- len -= 2;
- }
- if (len) {
- union {
- u_int8_t byte;
- u_int16_t wyde;
- } odd;
- odd.wyde = 0;
- odd.byte = *((u_int8_t *)ptr);
- sum += odd.wyde;
- }
- sum = (sum >> 16) + (sum & 0xFFFF);
- sum += prevsum;
- return (sum + (sum >> 16));
-}
-
-int main()
-{
- int fd, len;
- union {
- struct {
- char etherhdr[16];
- struct iphdr ip;
- } fmt;
- unsigned char raw[65536];
- } u;
-
- fd = open("/dev/tap0", O_RDWR);
- if (fd < 0) {
- perror("Opening `/dev/tap0'");
- return 1;
- }
-
- /* u.fmt.ip.ihl in host order! Film at 11. */
- while ((len = read(fd, &u, sizeof(u))) > 0) {
- u_int32_t tmp;
- struct icmphdr *icmp
- = (void *)((u_int32_t *)&u.fmt.ip + u.fmt.ip.ihl );
- struct tcphdr *tcp = (void *)icmp;
- struct udphdr *udp = (void *)icmp;
-
- fprintf(stderr, "SRC = %u.%u.%u.%u DST = %u.%u.%u.%u\n",
- (ntohl(u.fmt.ip.saddr) >> 24) & 0xFF,
- (ntohl(u.fmt.ip.saddr) >> 16) & 0xFF,
- (ntohl(u.fmt.ip.saddr) >> 8) & 0xFF,
- (ntohl(u.fmt.ip.saddr) >> 0) & 0xFF,
- (ntohl(u.fmt.ip.daddr) >> 24) & 0xFF,
- (ntohl(u.fmt.ip.daddr) >> 16) & 0xFF,
- (ntohl(u.fmt.ip.daddr) >> 8) & 0xFF,
- (ntohl(u.fmt.ip.daddr) >> 0) & 0xFF);
-
- switch (u.fmt.ip.protocol) {
- case IPPROTO_ICMP:
- if (icmp->type == ICMP_ECHO) {
- fprintf(stderr, "PONG! (iphdr = %u bytes)\n",
- (unsigned int)((char *)icmp
- - (char *)&u.fmt.ip));
-
- /* Turn it around */
- tmp = u.fmt.ip.saddr;
- u.fmt.ip.saddr = u.fmt.ip.daddr;
- u.fmt.ip.daddr = tmp;
-
- icmp->type = ICMP_ECHOREPLY;
- icmp->checksum = 0;
- icmp->checksum
- = ~csum_partial(icmp,
- ntohs(u.fmt.ip.tot_len)
- - u.fmt.ip.ihl*4, 0);
-
- {
- unsigned int i;
- for (i = 44;
- i < ntohs(u.fmt.ip.tot_len); i++){
- printf("%u:0x%02X ", i,
- ((unsigned char *)
- &u.fmt.ip)[i]);
- }
- printf("\n");
- }
- write(fd, &u, len);
- }
- break;
- case IPPROTO_TCP:
- fprintf(stderr, "TCP: %u -> %u\n", ntohs(tcp->source),
- ntohs(tcp->dest));
- break;
-
- case IPPROTO_UDP:
- fprintf(stderr, "UDP: %u -> %u\n", ntohs(udp->source),
- ntohs(udp->dest));
- break;
- }
- }
- if (len < 0)
- perror("Reading from `/dev/tap0'");
- else fprintf(stderr, "Empty read from `/dev/tap0'");
- return len < 0 ? 1 : 0;
-}
-
diff --git a/Documentation/networking/ixgb.txt b/Documentation/networking/ixgb.txt
index c62d588edef66..7c98277777ebc 100644
--- a/Documentation/networking/ixgb.txt
+++ b/Documentation/networking/ixgb.txt
@@ -1,7 +1,7 @@
Linux* Base Driver for the Intel(R) PRO/10GbE Family of Adapters
================================================================
-September 13, 2004
+November 17, 2004
Contents
@@ -18,8 +18,7 @@ In This Release
===============
This file describes the Linux* Base Driver for the Intel(R) PRO/10GbE Family
-of Adapters, version 1.0.x. This driver includes support for Itanium(TM)2 and
-EM64T systems.
+of Adapters, version 1.0.x.
For questions related to hardware requirements, refer to the documentation
supplied with your Intel PRO/10GbE adapter. All hardware requirements listed
@@ -71,8 +70,8 @@ Default: Read from the EEPROM
Ethernet PAUSE frames.
RxDescriptors
-Valid Range: 64-4096
-Default Value: 1024
+Valid Range: 64-512
+Default Value: 512
This value is the number of receive descriptors allocated by the driver.
Increasing this value allows the driver to buffer more incoming packets.
Each descriptor is 16 bytes. A receive buffer is also allocated for
diff --git a/Documentation/oops-tracing.txt b/Documentation/oops-tracing.txt
index 53b58a6ace67e..da711028e5f71 100644
--- a/Documentation/oops-tracing.txt
+++ b/Documentation/oops-tracing.txt
@@ -1,23 +1,22 @@
+NOTE: ksymoops is useless on 2.6. Please use the Oops in its original format
+(from dmesg, etc). Ignore any references in this or other docs to "decoding
+the Oops" or "running it through ksymoops". If you post an Oops fron 2.6 that
+has been run through ksymoops, people will just tell you to repost it.
+
Quick Summary
-------------
-Install ksymoops from
-ftp://ftp.<country>.kernel.org/pub/linux/utils/kernel/ksymoops
-Read the ksymoops man page.
-ksymoops < the_oops.txt
-
-and send the output the maintainer of the kernel area that seems to be
-involved with the problem, not to the ksymoops maintainer. Don't worry
-too much about getting the wrong person. If you are unsure send it to
-the person responsible for the code relevant to what you were doing.
-If it occurs repeatably try and describe how to recreate it. Thats
-worth even more than the oops
+Find the Oops and send it to the maintainer of the kernel area that seems to be
+involved with the problem. Don't worry too much about getting the wrong person.
+If you are unsure send it to the person responsible for the code relevant to
+what you were doing. If it occurs repeatably try and describe how to recreate
+it. That's worth even more than the oops.
If you are totally stumped as to whom to send the report, send it to
linux-kernel@vger.kernel.org. Thanks for your help in making Linux as
stable as humanly possible.
-Where is the_oops.txt?
+Where is the Oops?
----------------------
Normally the Oops text is read from the kernel buffers by klogd and
@@ -43,15 +42,14 @@ the disk is not available then you have three options :-
them yourself. Search kernel archives for kmsgdump, lkcd and
oops+smram.
-No matter how you capture the log output, feed the resulting file to
-ksymoops along with /proc/ksyms and /proc/modules that applied at the
-time of the crash. /var/log/ksymoops can be useful to capture the
-latter, man ksymoops for details.
-
Full Information
----------------
+NOTE: the message from Linus below applies to 2.4 kernel. I have preserved it
+for historical reasons, and because some of the information in it still
+applies. Especially, please ignore any references to ksymoops.
+
From: Linus Torvalds <torvalds@osdl.org>
How to track down an Oops.. [originally a mail to linux-kernel]
diff --git a/Documentation/parisc/00-INDEX b/Documentation/parisc/00-INDEX
index 7c8494ea2952f..cbd060961f434 100644
--- a/Documentation/parisc/00-INDEX
+++ b/Documentation/parisc/00-INDEX
@@ -1,10 +1,6 @@
00-INDEX
- this file.
-IODC.txt
- - Documentation IODC
debugging
- some debugging hints for real-mode code
-mm
- - Documentation on parisc mm status
registers
- current/planned usage of registers
diff --git a/Documentation/parport.txt b/Documentation/parport.txt
index 48dcd934026f0..93a7ceef398d3 100644
--- a/Documentation/parport.txt
+++ b/Documentation/parport.txt
@@ -264,5 +264,5 @@ the DMA channel, and try with:
io=0x378 irq=7 dma=none (for PIO)
io=0x378 irq=7 dma=3 (for DMA)
--
-Philip.Blundell@pobox.com
+philb@gnu.org
tim@cyberelk.net
diff --git a/Documentation/pci.txt b/Documentation/pci.txt
index b0676d1145ca8..67514bf87ccde 100644
--- a/Documentation/pci.txt
+++ b/Documentation/pci.txt
@@ -99,10 +99,10 @@ where all fields are passed in as hexadecimal values (no leading 0x).
Users need pass only as many fields as necessary; vendor, device,
subvendor, and subdevice fields default to PCI_ANY_ID (FFFFFFFF),
class and classmask fields default to 0, and driver_data defaults to
-0UL. Device drivers must call
- pci_dynids_set_use_driver_data(pci_driver *, 1)
-in order for the driver_data field to get passed to the driver.
-Otherwise, only a 0 is passed in that field.
+0UL. Device drivers must initialize use_driver_data in the dynids struct
+in their pci_driver struct prior to calling pci_register_driver in order
+for the driver_data field to get passed to the driver. Otherwise, only a
+0 is passed in that field.
When the driver exits, it just calls pci_unregister_driver() and the PCI layer
automatically calls the remove hook for all devices handled by the driver.
diff --git a/Documentation/pm.txt b/Documentation/pm.txt
index 6b9aecc4cd5fb..cc63ae18d147e 100644
--- a/Documentation/pm.txt
+++ b/Documentation/pm.txt
@@ -222,23 +222,6 @@ communicate with drivers through the existing generic power
management interface.
/*
- * Send a request to a single device
- *
- * Parameters:
- * dev - PM device previously returned from pm_register or pm_find
- * rqst - request type
- * data - data, if any, associated with the request
- *
- * Returns: 0 if the request is successful
- * See "pm_callback" return for errors
- *
- * Details: Forward request to device callback and, if a suspend
- * or resume request, update the pm_dev "state" field
- * appropriately
- */
-int pm_send(struct pm_dev *dev, pm_request_t rqst, void *data);
-
-/*
* Send a request to all devices
*
* Parameters:
diff --git a/Documentation/power/devices.txt b/Documentation/power/devices.txt
index 2e7eccd13e706..5d4ae9a39f1d5 100644
--- a/Documentation/power/devices.txt
+++ b/Documentation/power/devices.txt
@@ -15,7 +15,7 @@ The methods to suspend and resume devices reside in struct bus_type:
struct bus_type {
...
- int (*suspend)(struct device * dev, u32 state);
+ int (*suspend)(struct device * dev, pm_message_t state);
int (*resume)(struct device * dev);
};
diff --git a/Documentation/power/video.txt b/Documentation/power/video.txt
index ed8788e931225..8686968416ca1 100644
--- a/Documentation/power/video.txt
+++ b/Documentation/power/video.txt
@@ -1,7 +1,7 @@
Video issues with S3 resume
~~~~~~~~~~~~~~~~~~~~~~~~~~~
- 2003-2004, Pavel Machek
+ 2003-2005, Pavel Machek
During S3 resume, hardware needs to be reinitialized. For most
devices, this is easy, and kernel driver knows how to do
@@ -11,33 +11,159 @@ boot video card. (Kernel usually does not even contain video card
driver -- vesafb and vgacon are widely used).
This is not problem for swsusp, because during swsusp resume, BIOS is
-run normally so video card is normally initialized.
+run normally so video card is normally initialized. S3 has absolutely
+no chance of working with SMP/HT. Be sure it to turn it off before
+testing (swsusp should work ok, OTOH).
-There are three types of systems where video works after S3 resume:
+There are a few types of systems where video works after S3 resume:
-* systems where video state is preserved over S3. (Athlon HP Omnibook xe3s)
+(1) systems where video state is preserved over S3.
-* systems where it is possible to call video bios during S3
- resume. Unfortunately, it is not correct to call video BIOS at that
- point, but it happens to work on some machines. Use
- acpi_sleep=s3_bios (Athlon64 desktop system)
+(2) systems where it is possible to call the video BIOS during S3
+ resume. Unfortunately, it is not correct to call the video BIOS at
+ that point, but it happens to work on some machines. Use
+ acpi_sleep=s3_bios.
-* systems that initialize video card into vga text mode and where BIOS
- works well enough to be able to set video mode. Use
- acpi_sleep=s3_mode on these. (Toshiba 4030cdt)
+(3) systems that initialize video card into vga text mode and where
+ the BIOS works well enough to be able to set video mode. Use
+ acpi_sleep=s3_mode on these.
-* on some systems s3_bios kicks video into text mode, and
- acpi_sleep=s3_bios,s3_mode is needed (Toshiba Satellite P10-554)
+(4) on some systems s3_bios kicks video into text mode, and
+ acpi_sleep=s3_bios,s3_mode is needed.
-* radeon systems, where X can soft-boot your video card. You'll need
- patched X, and plain text console (no vesafb or radeonfb), see
- http://www.doesi.gmxhome.de/linux/tm800s3/s3.html. (Acer TM 800)
+(5) radeon systems, where X can soft-boot your video card. You'll need
+ new enough X, and plain text console (no vesafb or radeonfb), see
+ http://www.doesi.gmxhome.de/linux/tm800s3/s3.html. Actually you
+ should probably use vbetool (6) instead.
+
+(6) other radeon systems, where vbetool is enough to bring system back
+ to life. It needs text console to be working. Do vbetool vbestate
+ save > /tmp/delme; echo 3 > /proc/acpi/sleep; vbetool post; vbetool
+ vbestate restore < /tmp/delme; setfont <whatever>, and your video
+ should work.
+
+(7) on some systems, it is possible to boot most of kernel, and then
+ POSTing bios works. Ole Rohne has patch to do just that at
+ http://dev.gentoo.org/~marineam/patch-radeonfb-2.6.11-rc2-mm2.
Now, if you pass acpi_sleep=something, and it does not work with your
-bios, you'll get hard crash during resume. Be carefull.
+bios, you'll get a hard crash during resume. Be careful. Also it is
+safest to do your experiments with plain old VGA console. The vesafb
+and radeonfb (etc) drivers have a tendency to crash the machine during
+resume.
-You may have system where none of above works. At that point you
+You may have a system where none of above works. At that point you
either invent another ugly hack that works, or write proper driver for
your video card (good luck getting docs :-(). Maybe suspending from X
(proper X, knowing your hardware, not XF68_FBcon) might have better
chance of working.
+
+Table of known working systems:
+
+Model hack (or "how to do it")
+------------------------------------------------------------------------------
+Acer Aspire 1406LC ole's late BIOS init (7), turn off DRI
+Acer TM 242FX vbetool (6)
+Acer TM C300 vga=normal (only suspend on console, not in X), vbetool (6)
+Acer TM 4052LCi s3_bios (2)
+Acer TM 636Lci s3_bios vga=normal (2)
+Acer TM 650 (Radeon M7) vga=normal plus boot-radeon (5) gets text console back
+Acer TM 660 ??? (*)
+Acer TM 800 vga=normal, X patches, see webpage (5) or vbetool (6)
+Acer TM 803 vga=normal, X patches, see webpage (5) or vbetool (6)
+Acer TM 803LCi vga=normal, vbetool (6)
+Arima W730a vbetool needed (6)
+Asus L2400D s3_mode (3)(***) (S1 also works OK)
+Asus L3800C (Radeon M7) s3_bios (2) (S1 also works OK)
+Asus M6NE ??? (*)
+Athlon64 desktop prototype s3_bios (2)
+Compal CL-50 ??? (*)
+Compaq Armada E500 - P3-700 none (1) (S1 also works OK)
+Compaq Evo N620c vga=normal, s3_bios (2)
+Dell 600m, ATI R250 Lf none (1), but needs xorg-x11-6.8.1.902-1
+Dell D600, ATI RV250 vga=normal and X, or try vbestate (6)
+Dell Inspiron 4000 ??? (*)
+Dell Inspiron 500m ??? (*)
+Dell Inspiron 600m ??? (*)
+Dell Inspiron 8200 ??? (*)
+Dell Inspiron 8500 ??? (*)
+Dell Inspiron 8600 ??? (*)
+eMachines athlon64 machines vbetool needed (6) (someone please get me model #s)
+HP NC6000 s3_bios, may not use radeonfb (2); or vbetool (6)
+HP NX7000 ??? (*)
+HP Pavilion ZD7000 vbetool post needed, need open-source nv driver for X
+HP Omnibook XE3 athlon version none (1)
+HP Omnibook XE3GC none (1), video is S3 Savage/IX-MV
+IBM TP T20, model 2647-44G none (1), video is S3 Inc. 86C270-294 Savage/IX-MV, vesafb gets "interesting" but X work.
+IBM TP A31 / Type 2652-M5G s3_mode (3) [works ok with BIOS 1.04 2002-08-23, but not at all with BIOS 1.11 2004-11-05 :-(]
+IBM TP R32 / Type 2658-MMG none (1)
+IBM TP R40 2722B3G ??? (*)
+IBM TP R50p / Type 1832-22U s3_bios (2)
+IBM TP R51 ??? (*)
+IBM TP T30 236681A ??? (*)
+IBM TP T40 / Type 2373-MU4 none (1)
+IBM TP T40p none (1)
+IBM TP R40p s3_bios (2)
+IBM TP T41p s3_bios (2), switch to X after resume
+IBM TP T42 ??? (*)
+IBM ThinkPad T42p (2373-GTG) s3_bios (2)
+IBM TP X20 ??? (*)
+IBM TP X30 ??? (*)
+IBM TP X31 / Type 2672-XXH none (1), use radeontool (http://fdd.com/software/radeon/) to turn off backlight.
+IBM Thinkpad X40 Type 2371-7JG s3_bios,s3_mode (4)
+Medion MD4220 ??? (*)
+Samsung P35 vbetool needed (6)
+Sharp PC-AR10 (ATI rage) none (1)
+Sony Vaio PCG-F403 ??? (*)
+Sony Vaio PCG-N505SN ??? (*)
+Sony Vaio vgn-s260 X or boot-radeon can init it (5)
+Toshiba Libretto L5 none (1)
+Toshiba Satellite 4030CDT s3_mode (3)
+Toshiba Satellite 4080XCDT s3_mode (3)
+Toshiba Satellite 4090XCDT ??? (*)
+Toshiba Satellite P10-554 s3_bios,s3_mode (4)(****)
+Uniwill 244IIO ??? (*)
+
+
+(*) from http://www.ubuntulinux.org/wiki/HoaryPMResults, not sure
+ which options to use. If you know, please tell me.
+
+(***) To be tested with a newer kernel.
+
+(****) Not with SMP kernel, UP only.
+
+VBEtool details
+~~~~~~~~~~~~~~~
+(with thanks to Carl-Daniel Hailfinger)
+
+First, boot into X and run the following script ONCE:
+#!/bin/bash
+statedir=/root/s3/state
+mkdir -p $statedir
+chvt 2
+sleep 1
+vbetool vbestate save >$statedir/vbe
+
+
+To suspend and resume properly, call the following script as root:
+#!/bin/bash
+statedir=/root/s3/state
+curcons=`fgconsole`
+fuser /dev/tty$curcons 2>/dev/null|xargs ps -o comm= -p|grep -q X && chvt 2
+cat /dev/vcsa >$statedir/vcsa
+sync
+echo 3 >/proc/acpi/sleep
+sync
+vbetool post
+vbetool vbestate restore <$statedir/vbe
+cat $statedir/vcsa >/dev/vcsa
+rckbd restart
+chvt $[curcons%6+1]
+chvt $curcons
+
+
+Unless you change your graphics card or other hardware configuration,
+the state once saved will be OK for every resume afterwards.
+NOTE: The "rckbd restart" command may be different for your
+distribution. Simply replace it with the command you would use to
+set the fonts on screen.
diff --git a/Documentation/scsi/st.txt b/Documentation/scsi/st.txt
index d2e8bee1c821a..20e30cf31877f 100644
--- a/Documentation/scsi/st.txt
+++ b/Documentation/scsi/st.txt
@@ -2,7 +2,7 @@ This file contains brief information about the SCSI tape driver.
The driver is currently maintained by Kai Mäkisara (email
Kai.Makisara@kolumbus.fi)
-Last modified: Wed Feb 25 14:09:08 2004 by makisara
+Last modified: Mon Mar 7 21:14:44 2005 by kai.makisara
BASICS
@@ -85,6 +85,9 @@ writing and the last operation has been a write. Two filemarks can be
optionally written. In both cases end of data is signified by
returning zero bytes for two consecutive reads.
+If rewind, offline, bsf, or seek is done and previous tape operation was
+write, a filemark is written before moving tape.
+
The compile options are defined in the file linux/drivers/scsi/st_options.h.
4. If the open option O_NONBLOCK is used, open succeeds even if the
diff --git a/Documentation/scsi/sym53c8xx_2.txt b/Documentation/scsi/sym53c8xx_2.txt
index af9abe2913c34..7f516cdcd2628 100644
--- a/Documentation/scsi/sym53c8xx_2.txt
+++ b/Documentation/scsi/sym53c8xx_2.txt
@@ -440,7 +440,7 @@ lilo: linux root=/dev/sda2 sym53c8xx.cmd_per_lun=4 sym53c8xx.sync=10 sym53c8xx.d
The following command will install the driver module with the same
options as above.
- modprobe sym53c8xx cmd_per_lun=4 sync=10 debug=0x200"
+ modprobe sym53c8xx cmd_per_lun=4 sync=10 debug=0x200
10.2 Available arguments
diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
index 23fbf00f14be2..71ef0498d5e03 100644
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -7,75 +7,75 @@
Kernel Configuration
====================
-To enable the ALSA support, at least you need to build the kernel with
-the primary sound card support (CONFIG_SOUND). Since ALSA can emulate
-the OSS, you don't have to choose any of the OSS/Free modules. Please
-enable "OSS API emulation" (CONFIG_SND_OSSEMUL) and both OSS mixer and
-PCM supports if you want to run the OSS application with the ALSA.
-
-When you want to support the WaveTable functionality on some cards
-such like SB Live!, you need to enable "Sequencer support"
+To enable ALSA support you need at least to build the kernel with
+primary sound card support (CONFIG_SOUND). Since ALSA can emulate OSS,
+you don't have to choose any of the OSS modules.
+
+Enable "OSS API emulation" (CONFIG_SND_OSSEMUL) and both OSS mixer and
+PCM supports if you want to run OSS applications with ALSA.
+
+If you want to support the WaveTable functionality on cards such as
+SB Live! then you need to enable "Sequencer support"
(CONFIG_SND_SEQUENCER).
-For getting more verbose debug messages, turn on "Verbose printk" and
-"Debug" options. For checking the memory leaks, you can turn on
-"Debug memory" option, too. "Debug detection" will put more
-additional checks for the detection of cards.
+To make ALSA debug messages more verbose, enable the "Verbose printk"
+and "Debug" options. To check for memory leaks, turn on "Debug memory"
+too. "Debug detection" will add checks for the detection of cards.
-Please note that all the ALSA ISA drivers support Linux isapnp API (if
-the card supports). You don't need to configure the PnP via
-isapnptools.
+Please note that all the ALSA ISA drivers support the Linux isapnp API
+(if the card supports ISA PnP). You don't need to configure the cards
+using isapnptools.
Creating ALSA devices
=====================
-Use the /dev/MAKEDEV script to create the nessecary device nodes.
+This depends on your distribution, but normally you use the /dev/MAKEDEV
+script to create the necessary device nodes. On some systems you use a
+script named 'snddevices'.
Module parameters
=================
- A user can modify or set parameters at the load time of the module. If
- the module supports more cards and you have got more than one card
- of the same type, you may simply specify more values for the parameter,
- delimited by commas.
-
- Note that module option names were changed in 0.9.0rc4. The 'snd_'
- prefix was removed.
+The user can load modules with options. If the module supports more than
+one card and you have more than one card of the same type then you can
+specify multiple values for the option separated by commas.
+
+Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
Module snd
----------
- The module snd is the ALSA core module, which is used by all ALSA
- card drivers. This takes the global options for creating devices,
- etc.
+ The core ALSA module. It is used by all ALSA card drivers.
+ It takes the following options which have global effects.
- major - major # for sound driver
- - default is 116
+ major - major number for sound driver
+ - Default: 116
cards_limit
- - specifies card limit # for auto-loading (1-8)
- - default is 1
- - for auto-loading more than 1 card, specify this option
- together with snd-card-X aliases.
+ - limiting card index for auto-loading (1-8)
+ - Default: 1
+ - For auto-loading more than one card, specify this
+ option together with snd-card-X aliases.
device_mode
- - specifies permission mask for dynamic sound device filesystem
- (available only when DEVFS is enabled)
- - default value = 0666
- - for example 'device_mode=0660'
+ - permission mask for dynamic sound device filesystem
+ - This is available only when DEVFS is enabled
+ - Default: 0666
+ - E.g.: device_mode=0660
Module snd-pcm-oss
------------------
The PCM OSS emulation module.
- This module takes the options to change the mapping of devices.
+ This module takes options which change the mapping of devices.
dsp_map - PCM device number maps assigned to the 1st OSS device.
- (default: 0)
+ - Default: 0
adsp_map - PCM device number maps assigned to the 2st OSS device.
- (default: 1)
- nonblock_open - Don't block opening busy PCM devices.
+ - Default: 1
+ nonblock_open
+ - Don't block opening busy PCM devices.
For example, when dsp_map=2, /dev/dsp will be mapped to PCM #2 of
the card #0. Similarly, when adsp_map=0, /dev/adsp will be mapped
@@ -91,33 +91,39 @@ Module parameters
Module snd-rawmidi
------------------
- This module takes the options to change the mapping of OSS
- devices like snd-pcm-oss module.
+ This module takes options which change the mapping of devices.
+ similar to those of the snd-pcm-oss module.
midi_map - MIDI device number maps assigned to the 1st OSS device.
- (default: 0)
+ - Default: 0
amidi_map - MIDI device number maps assigned to the 2st OSS device.
- (default: 1)
-
- Common parameters for top soundcard modules
- -------------------------------------------
-
- Each of top-level soundcard module takes some general options,
-
- index - 0-7 - index (slot #) for soundcard
- - if not set or -1, first free index (slot #) is assigned
- id - user identification for card (up to 15 chars)
- - default expression is 'card<index>' (for example card1)
- - value is used for /proc/asound filesystem
- - this value can be used by applications for identification
- of card if user does not want identify card with index number
- enable - enable card. (all cards enabled for PCI and ISA PnP cards
- as default.)
+ - Default: 1
+
+ Common parameters for top sound card modules
+ --------------------------------------------
+
+ Each of top level sound card module takes the following options.
+
+ index - index (slot #) of sound card
+ - Values: 0 through 7 or negative
+ - If nonnegative, assign that index number
+ - if negative, interpret as a bitmask of permissible
+ indices; the first free permitted index is assigned
+ - Default: -1
+ id - card ID (identifier or name)
+ - Can be up to 15 characters long
+ - Default: the card type
+ - A directory by this name is created under /proc/asound/
+ containing information about the card
+ - This ID can be used instead of the index number in
+ identifying the card
+ enable - enable card
+ - Default: enabled, for PCI and ISA PnP cards
Module snd-ad1816a
------------------
- Module for soundcards based on Analog Devices AD1816A/AD1815 ISA chips.
+ Module for sound cards based on Analog Devices AD1816A/AD1815 ISA chips.
port - port # for AD1816A chip (PnP setup)
mpu_port - port # for MPU-401 UART (PnP setup)
@@ -132,7 +138,7 @@ Module parameters
Module snd-ad1848
-----------------
- Module for soundcards based on AD1848/AD1847/CS4248 ISA chips.
+ Module for sound cards based on AD1848/AD1847/CS4248 ISA chips.
port - port # for AD1848 chip
irq - IRQ # for AD1848 chip
@@ -147,7 +153,8 @@ Module parameters
Module for ALi M5451 PCI chip.
pcm_channels - Number of hardware channels assigned for PCM
- spdif - Support SPDIF I/O (disabled by default)
+ spdif - Support SPDIF I/O
+ - Default: disabled
Module supports autoprobe and multiple chips (max 8).
@@ -156,7 +163,7 @@ Module parameters
Module snd-als100
-----------------
- Module for soundcards based on Avance Logic ALS100/ALS120 ISA chips.
+ Module for sound cards based on Avance Logic ALS100/ALS120 ISA chips.
port - port # for ALS100 (SB16) chip (PnP setup)
irq - IRQ # for ALS100 (SB16) chip (PnP setup)
@@ -171,7 +178,7 @@ Module parameters
Module snd-als4000
------------------
- Module for soundcards based on Avance Logic ALS4000 PCI chip.
+ Module for sound cards based on Avance Logic ALS4000 PCI chip.
joystick_port - port # for legacy joystick support.
0 = disabled (default), 1 = auto-detect
@@ -197,6 +204,9 @@ Module parameters
Module supports up to 8 cards.
+ Note: The default index value of this module is -2, i.e. the first
+ slot is excluded.
+
Module snd-au8810, snd-au8820, snd-au8830
-----------------------------------------
@@ -226,7 +236,7 @@ Module parameters
Module snd-azt2320
------------------
- Module for soundcards based on Aztech System AZT2320 ISA chip (PnP only).
+ Module for sound cards based on Aztech System AZT2320 ISA chip (PnP only).
port - port # for AZT2320 chip (PnP setup)
wss_port - port # for WSS (PnP setup)
@@ -242,7 +252,7 @@ Module parameters
Module snd-azt3328
------------------
- Module for soundcards based on Aztech AZF3328 PCI chip.
+ Module for sound cards based on Aztech AZF3328 PCI chip.
joystick - Enable joystick (default off)
@@ -258,6 +268,9 @@ Module parameters
Module supports up to 8 cards.
+ Note: The default index value of this module is -2, i.e. the first
+ slot is excluded.
+
Module snd-ca0106
-----------------
@@ -269,7 +282,7 @@ Module parameters
Module snd-cmi8330
------------------
- Module for soundcards based on C-Media CMI8330 ISA chips.
+ Module for sound cards based on C-Media CMI8330 ISA chips.
wssport - port # for CMI8330 chip (WSS)
wssirq - IRQ # for CMI8330 chip (WSS)
@@ -284,7 +297,7 @@ Module parameters
Module snd-cmipci
-----------------
- Module for C-Media CMI8338 and 8738 PCI soundcards.
+ Module for C-Media CMI8338 and 8738 PCI sound cards.
mpu_port - 0x300,0x310,0x320,0x330, 0 = disable (default)
fm_port - 0x388 (default), 0 = disable (default)
@@ -297,7 +310,7 @@ Module parameters
Module snd-cs4231
-----------------
- Module for soundcards based on CS4231 ISA chips.
+ Module for sound cards based on CS4231 ISA chips.
port - port # for CS4231 chip
mpu_port - port # for MPU-401 UART (optional), -1 = disable
@@ -314,7 +327,7 @@ Module parameters
Module snd-cs4232
-----------------
- Module for soundcards based on CS4232/CS4232A ISA chips.
+ Module for sound cards based on CS4232/CS4232A ISA chips.
port - port # for CS4232 chip (PnP setup - 0x534)
cport - control port # for CS4232 chip (PnP setup - 0x120,0x210,0xf00)
@@ -334,7 +347,7 @@ Module parameters
Module snd-cs4236
-----------------
- Module for soundcards based on CS4235/CS4236/CS4236B/CS4237B/
+ Module for sound cards based on CS4235/CS4236/CS4236B/CS4237B/
CS4238B/CS4239 ISA chips.
port - port # for CS4236 chip (PnP setup - 0x534)
@@ -367,7 +380,7 @@ Module parameters
Module snd-cs46xx
-----------------
- Module for PCI soundcards based on CS4610/CS4612/CS4614/CS4615/CS4622/
+ Module for PCI sound cards based on CS4610/CS4612/CS4614/CS4615/CS4622/
CS4624/CS4630/CS4280 PCI chips.
external_amp - Force to enable external amplifer.
@@ -400,14 +413,14 @@ Module parameters
Module snd-dummy
----------------
- Module for the dummy soundcard. This soundcard doesn't do any output
+ Module for the dummy sound card. This "card" doesn't do any output
or input, but you may use this module for any application which
- requires a soundcard (like RealPlayer).
+ requires a sound card (like RealPlayer).
Module snd-emu10k1
------------------
- Module for EMU10K1/EMU10k2 based PCI soundcards.
+ Module for EMU10K1/EMU10k2 based PCI sound cards.
* Sound Blaster Live!
* Sound Blaster PCI 512
* Emu APS (partially supported)
@@ -447,7 +460,7 @@ Module parameters
Module snd-ens1370
------------------
- Module for Ensoniq AudioPCI ES1370 PCI soundcards.
+ Module for Ensoniq AudioPCI ES1370 PCI sound cards.
* SoundBlaster PCI 64
* SoundBlaster PCI 128
@@ -458,7 +471,7 @@ Module parameters
Module snd-ens1371
------------------
- Module for Ensoniq AudioPCI ES1371 PCI soundcards.
+ Module for Ensoniq AudioPCI ES1371 PCI sound cards.
* SoundBlaster PCI 64
* SoundBlaster PCI 128
* SoundBlaster Vibra PCI
@@ -471,7 +484,7 @@ Module parameters
Module snd-es968
----------------
- Module for soundcards based on ESS ES968 chip (PnP only).
+ Module for sound cards based on ESS ES968 chip (PnP only).
port - port # for ES968 (SB8) chip (PnP setup)
irq - IRQ # for ES968 (SB8) chip (PnP setup)
@@ -482,7 +495,7 @@ Module parameters
Module snd-es1688
-----------------
- Module for ESS AudioDrive ES-1688 and ES-688 soundcards.
+ Module for ESS AudioDrive ES-1688 and ES-688 sound cards.
port - port # for ES-1688 chip (0x220,0x240,0x260)
mpu_port - port # for MPU-401 port (0x300,0x310,0x320,0x330), -1 = disable (default)
@@ -495,7 +508,7 @@ Module parameters
Module snd-es18xx
-----------------
- Module for ESS AudioDrive ES-18xx soundcards.
+ Module for ESS AudioDrive ES-18xx sound cards.
port - port # for ES-18xx chip (0x220,0x240,0x260)
mpu_port - port # for MPU-401 port (0x300,0x310,0x320,0x330), -1 = disable (default)
@@ -514,14 +527,14 @@ Module parameters
Module snd-es1938
-----------------
- Module for soundcards based on ESS Solo-1 (ES1938,ES1946) chips.
+ Module for sound cards based on ESS Solo-1 (ES1938,ES1946) chips.
Module supports up to 8 cards and autoprobe.
Module snd-es1968
-----------------
- Module for soundcards based on ESS Maestro-1/2/2E (ES1968/ES1978) chips.
+ Module for sound cards based on ESS Maestro-1/2/2E (ES1968/ES1978) chips.
total_bufsize - total buffer size in kB (1-4096kB)
pcm_substreams_p - playback channels (1-8, default=2)
@@ -539,7 +552,7 @@ Module parameters
Module snd-fm801
----------------
- Module for ForteMedia FM801 based PCI soundcards.
+ Module for ForteMedia FM801 based PCI sound cards.
tea575x_tuner - Enable TEA575x tuner
- 1 = MediaForte 256-PCS
@@ -553,7 +566,7 @@ Module parameters
Module snd-gusclassic
---------------------
- Module for Gravis UltraSound Classic soundcard.
+ Module for Gravis UltraSound Classic sound card.
port - port # for GF1 chip (0x220,0x230,0x240,0x250,0x260)
irq - IRQ # for GF1 chip (3,5,9,11,12,15)
@@ -568,7 +581,7 @@ Module parameters
Module snd-gusextreme
---------------------
- Module for Gravis UltraSound Extreme (Synergy ViperMax) soundcard.
+ Module for Gravis UltraSound Extreme (Synergy ViperMax) sound card.
port - port # for ES-1688 chip (0x220,0x230,0x240,0x250,0x260)
gf1_port - port # for GF1 chip (0x210,0x220,0x230,0x240,0x250,0x260,0x270)
@@ -587,7 +600,7 @@ Module parameters
Module snd-gusmax
-----------------
- Module for Gravis UltraSound MAX soundcard.
+ Module for Gravis UltraSound MAX sound card.
port - port # for GF1 chip (0x220,0x230,0x240,0x250,0x260)
irq - IRQ # for GF1 chip (3,5,9,11,12,15)
@@ -599,18 +612,42 @@ Module parameters
Module supports up to 8 cards and autoprobe.
+ Module snd-hda-intel
+ --------------------
+
+ Module for Intel HD Audio (ICH6, ICH6M, ICH7)
+
+ model - force the model name
+
+ Module supports up to 8 cards.
+
+ Each codec may have a model table for different configurations.
+ If your machine isn't listed there, the default (usually minimal)
+ configuration is set up. You can pass "model=<name>" option to
+ specify a certain model in such a case. There are different
+ models depending on the codec chip.
+
+ Model name Description
+ ---------- -----------
+ ALC880
+ 3stack 3-jack in back and a headphone out
+ 3stack-digout 3-jack in back, a HP out and a SPDIF out
+ 5stack 5-jack in back, 2-jack in front
+ 5stack-digout 5-jack in back, 2-jack in front, a SPDIF out
+ w810 3-jack
+
+ CMI9880
+ minimal 3-jack in back
+ min_fp 3-jack in back, 2-jack in front
+ full 6-jack in back, 2-jack in front
+ full_dig 6-jack in back, 2-jack in front, SPDIF I/O
+ allout 5-jack in back, 2-jack in front, SPDIF out
+
Module snd-hdsp
---------------
Module for RME Hammerfall DSP audio interface(s)
- precise_ptr - Enable precise pointer (doesn't work reliably).
- (default = 0)
- line_outs_monitor - Send all input and playback streams to line outs
- by default. (default = 0)
- force_firmware - Force a reload of the I/O box firmware
- (default = 0)
-
Module supports up to 8 cards.
Note: The firmware data can be automatically loaded via hotplug
@@ -628,7 +665,7 @@ Module parameters
Module snd-ice1712
------------------
- Module for Envy24 (ICE1712) based PCI soundcards.
+ Module for Envy24 (ICE1712) based PCI sound cards.
* MidiMan M Audio Delta 1010
* MidiMan M Audio Delta 1010LT
* MidiMan M Audio Delta DiO 2496
@@ -660,7 +697,7 @@ Module parameters
Module snd-ice1724
------------------
- Module for Envy24HT (VT/ICE1724) based PCI soundcards.
+ Module for Envy24HT (VT/ICE1724) based PCI sound cards.
* MidiMan M Audio Revolution 7.1
* AMP Ltd AUDIO2000
* TerraTec Aureon Sky-5.1, Space-7.1
@@ -689,7 +726,7 @@ Module parameters
hp_only = use headphone control as master
swap_hp = swap headphone and master controls
swap_surround = swap master and surround controls
- ad_shring = for AD1985, turn on OMS bit and use headphone
+ ad_sharing = for AD1985, turn on OMS bit and use headphone
alc_jack = for ALC65x, turn on the jack sense mode
inv_eapd = inverted EAPD implementation
mute_led = bind EAPD bit for turning on/off mute LED
@@ -726,11 +763,14 @@ Module parameters
This module supports up to 8 cards and autoprobe.
+ Note: The default index value of this module is -2, i.e. the first
+ slot is excluded.
+
Module snd-interwave
--------------------
Module for Gravis UltraSound PnP, Dynasonic 3-D/Pro, STB Sound Rage 32
- and other soundcards based on AMD InterWave (tm) chip.
+ and other sound cards based on AMD InterWave (tm) chip.
port - port # for InterWave chip (0x210,0x220,0x230,0x240,0x250,0x260)
irq - IRQ # for InterWave chip (3,5,9,11,12,15)
@@ -747,8 +787,8 @@ Module parameters
Module snd-interwave-stb
------------------------
- Module for UltraSound 32-Pro (soundcard from STB used by Compaq)
- and other soundcards based on AMD InterWave (tm) chip with TEA6330T
+ Module for UltraSound 32-Pro (sound card from STB used by Compaq)
+ and other sound cards based on AMD InterWave (tm) chip with TEA6330T
circuit for extended control of bass, treble and master volume.
port - port # for InterWave chip (0x210,0x220,0x230,0x240,0x250,0x260)
@@ -794,7 +834,7 @@ Module parameters
Module snd-mixart
-----------------
- Module for Digigram miXart8 soundcards.
+ Module for Digigram miXart8 sound cards.
Module supports multiple cards.
Note: One miXart8 board will be represented as 4 alsa cards.
@@ -813,10 +853,9 @@ Module parameters
port - port number or -1 (disable)
irq - IRQ number or -1 (disable)
- acpipnp - ACPI PnP detection - 0 = disable, 1 = enable (default)
+ pnp - PnP detection - 0 = disable, 1 = enable (default)
- Module supports multiple devices (max 8) and ACPI PnP. If PnP is not
- used (or ACPI not enabled), port and irq must be specified.
+ Module supports multiple devices (max 8) and PnP.
Module snd-mtpav
----------------
@@ -883,7 +922,7 @@ Module parameters
Module snd-opl3sa2
------------------
- Module for Yamaha OPL3-SA2/SA3 soundcards.
+ Module for Yamaha OPL3-SA2/SA3 sound cards.
port - control port # for OPL3-SA chip (0x370)
sb_port - SB port # for OPL3-SA chip (0x220,0x240)
@@ -903,7 +942,7 @@ Module parameters
Module snd-opti92x-ad1848
-------------------------
- Module for soundcards based on OPTi 82c92x and Analog Devices AD1848 chips.
+ Module for sound cards based on OPTi 82c92x and Analog Devices AD1848 chips.
Module works with OAK Mozart cards as well.
port - port # for WSS chip (0x530,0xe80,0xf40,0x604)
@@ -918,7 +957,7 @@ Module parameters
Module snd-opti92x-cs4231
-------------------------
- Module for soundcards based on OPTi 82c92x and Crystal CS4231 chips.
+ Module for sound cards based on OPTi 82c92x and Crystal CS4231 chips.
port - port # for WSS chip (0x530,0xe80,0xf40,0x604)
mpu_port - port # for MPU-401 UART (0x300,0x310,0x320,0x330)
@@ -933,7 +972,7 @@ Module parameters
Module snd-opti93x
------------------
- Module for soundcards based on OPTi 82c93x chips.
+ Module for sound cards based on OPTi 82c93x chips.
port - port # for WSS chip (0x530,0xe80,0xf40,0x604)
mpu_port - port # for MPU-401 UART (0x300,0x310,0x320,0x330)
@@ -962,21 +1001,21 @@ Module parameters
----------------
Module for RME Digi32, Digi32 Pro and Digi32/8 (Sek'd Prodif32,
- Prodif96 and Prodif Gold) soundcards.
+ Prodif96 and Prodif Gold) sound cards.
Module supports up to 8 cards.
Module snd-rme96
----------------
- Module for RME Digi96, Digi96/8 and Digi96/8 PRO/PAD/PST soundcards.
+ Module for RME Digi96, Digi96/8 and Digi96/8 PRO/PAD/PST sound cards.
Module supports up to 8 cards.
Module snd-rme9652
------------------
- Module for RME Digi9652 (Hammerfall, Hammerfall-Light) soundcards.
+ Module for RME Digi9652 (Hammerfall, Hammerfall-Light) sound cards.
precise_ptr - Enable precise pointer (doesn't work reliably).
(default = 0)
@@ -992,7 +1031,7 @@ Module parameters
Module snd-sa11xx-uda1341 (on arm only)
---------------------------------------
- Module for Philips UDA1341TS on Compaq iPAQ H3600 soundcard.
+ Module for Philips UDA1341TS on Compaq iPAQ H3600 sound card.
Module supports only one card.
Module has no enable and index options.
@@ -1039,7 +1078,7 @@ Module parameters
Module snd-sgalaxy
------------------
- Module for Aztech Sound Galaxy soundcard.
+ Module for Aztech Sound Galaxy sound card.
sbport - Port # for SB16 interface (0x220,0x240)
wssport - Port # for WSS interface (0x530,0xe80,0xf40,0x604)
@@ -1079,7 +1118,7 @@ Module parameters
Module snd-wavefront
--------------------
- Module for Turtle Beach Maui, Tropez and Tropez+ soundcards.
+ Module for Turtle Beach Maui, Tropez and Tropez+ sound cards.
cs4232_pcm_port - Port # for CS4232 PCM interface.
cs4232_pcm_irq - IRQ # for CS4232 PCM interface (5,7,9,11,12,15).
@@ -1099,7 +1138,7 @@ Module parameters
Module snd-sonicvibes
---------------------
- Module for S3 SonicVibes PCI soundcards.
+ Module for S3 SonicVibes PCI sound cards.
* PINE Schubert 32 PCI
reverb - Reverb Enable - 1 = enable, 0 = disable (default)
@@ -1131,7 +1170,7 @@ Module parameters
Module snd-trident
------------------
- Module for Trident 4DWave DX/NX soundcards.
+ Module for Trident 4DWave DX/NX sound cards.
* Best Union Miss Melody 4DWave PCI
* HIS 4DWave PCI
* Warpspeed ONSpeed 4DWave PCI
@@ -1223,6 +1262,9 @@ Module parameters
Module supports up to 8 cards.
+ Note: The default index value of this module is -2, i.e. the first
+ slot is excluded.
+
Module snd-virmidi
------------------
@@ -1266,10 +1308,6 @@ Module parameters
Module for Digigram VX-Pocket VX2 PCMCIA card.
- irq_mask - IRQ bitmask, specifies the available IRQs as bits
- (default = 0xffff, all available)
- irq_list - List of available interrupts (default = -1, not specified)
- 4 numbers must be given (if specified).
ibl - Capture IBL size. (default = 0, minimum size)
Module supports up to 8 cards. The module is compiled only when
@@ -1284,9 +1322,6 @@ Module parameters
When no hotplug fw loader is available, you need to load the
firmware via vxloader utility in alsa-tools package.
- The irq_mask and irq_list are provided to avoid allocation of
- specific IRQs. Usually you don't need to specify them.
-
About capture IBL, see the description of snd-vx222 module.
Note: the driver is build only when CONFIG_ISA is set.
@@ -1296,9 +1331,6 @@ Module parameters
Module for Digigram VX-Pocket 440 PCMCIA card.
- irq_mask - IRQ bitmask, specifies the available IRQs as bits
- irq_list - List of available interrupts (default = -1, not specified)
- 4 numbers must be given (if specified).
ibl - Capture IBL size. (default = 0, minimum size)
Module supports up to 8 cards. The module is compiled only when
@@ -1313,9 +1345,6 @@ Module parameters
When no hotplug fw loader is available, you need to load the
firmware via vxloader utility in alsa-tools package.
- The irq_mask and irq_list are provided to avoid allocation of
- specific IRQs. Usually you don't need to specify them.
-
About capture IBL, see the description of snd-vx222 module.
Note: the driver is build only when CONFIG_ISA is set.
@@ -1340,10 +1369,7 @@ Module parameters
Module snd-pdaudiocf
--------------------
- Module for Sound Core PDAudioCF soundcard.
-
- irq_mask - IRQ mask (PCMCIA type)
- irq_list - List of available interrupts for this soundcard
+ Module for Sound Core PDAudioCF sound card.
Note: the driver is build only when CONFIG_ISA is set.
@@ -1366,7 +1392,7 @@ Module Autoloading Support
The ALSA drivers can be loaded automatically on demand by defining
module aliases. The string 'snd-card-%1' is requested for ALSA native
-devices where %i is soundcard number from zero to seven.
+devices where %i is sound card number from zero to seven.
To auto-load an ALSA driver for OSS services, define the string
'sound-slot-%i' where %i means the slot number for OSS, which
@@ -1379,16 +1405,16 @@ alias snd-card-0 snd-emu10k1
alias sound-slot-0 snd-emu10k1
----- /etc/modprobe.conf
-The available number of auto-loaded soundcards depends on the module
+The available number of auto-loaded sound cards depends on the module
option "cards_limit" of snd module. As default it's set to 1.
To enable the auto-loading of multiple cards, specify the number of
-soundcards in that option.
+sound cards in that option.
When multiple cards are available, it'd better to specify the index
number for each card via module option, too, so that the order of
cards is kept consistent.
-An example configuration for two soundcards is like below:
+An example configuration for two sound cards is like below:
----- /etc/modprobe.conf
# ALSA portion
@@ -1420,7 +1446,7 @@ ALSA PCM devices to OSS devices mapping
/dev/snd/pcmC2D1[c|p] -> /dev/adsp2 -> minor 12+32 = 44
The first number from /dev/snd/pcmC{X}D{Y}[c|p] expression means
-soundcard number and second means device number. The ALSA devices
+sound card number and second means device number. The ALSA devices
have either 'c' or 'p' suffix indicating the direction, capture and
playback, respectively.
diff --git a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
index 82d4029ef270f..e789475304b6e 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>July 11, 2004</date>
- <edition>0.3.3</edition>
+ <date>March 6, 2005</date>
+ <edition>0.3.4</edition>
<abstract>
<para>
@@ -110,9 +110,9 @@
</para>
<para>
- One is the the trees provided as a tarball or via cvs from the
+ One is the trees provided as a tarball or via cvs from the
ALSA's ftp site, and another is the 2.6 (or later) Linux kernel
- tree. To synchronize both, the ALSA driver tree is split to
+ tree. To synchronize both, the ALSA driver tree is split into
two different trees: alsa-kernel and alsa-driver. The former
contains purely the source codes for the Linux 2.6 (or later)
tree. This tree is designed only for compilation on 2.6 or
@@ -766,7 +766,7 @@
</para>
<para>
- The ALSA interfaces like PCM or control API are define in other
+ The ALSA interfaces like PCM or control API are defined in other
header files as <filename>&lt;sound/xxx.h&gt;</filename>.
They have to be included after
<filename>&lt;sound/core.h&gt;</filename>.
@@ -1103,7 +1103,7 @@
/* release the irq */
if (chip->irq >= 0)
free_irq(chip->irq, (void *)chip);
- /* release the i/o ports */
+ /* release the i/o ports & memory */
pci_release_regions(chip->pci);
/* disable the PCI entry */
pci_disable_device(chip->pci);
@@ -1314,6 +1314,7 @@
</para>
<para>
+ <!-- obsolete -->
It will reserve the i/o port region of 8 bytes of the given
PCI device. The returned value, chip-&gt;res_port, is allocated
via <function>kmalloc()</function> by
@@ -1936,6 +1937,7 @@
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
&snd_mychip_capture_ops);
/* pre-allocation of buffers */
+ /* NOTE: this may fail */
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
snd_dma_pci_data(chip->pci),
64*1024, 64*1024);
@@ -1950,7 +1952,7 @@
<section id="pcm-interface-constructor">
<title>Constructor</title>
<para>
- A pcm instance is allocated <function>snd_pcm_new()</function>
+ A pcm instance is allocated by <function>snd_pcm_new()</function>
function. It would be better to create a constructor for pcm,
namely,
@@ -2235,7 +2237,8 @@ struct _snd_pcm_runtime {
unsigned char *dma_area; /* DMA area */
dma_addr_t dma_addr; /* physical bus address (not accessible from main CPU) */
size_t dma_bytes; /* size of DMA area */
- void *dma_private; /* private DMA data for the memory allocator */
+
+ struct snd_dma_buffer *dma_buffer_p; /* allocated buffer */
#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
/* -- OSS things -- */
@@ -2250,7 +2253,7 @@ struct _snd_pcm_runtime {
<para>
For the operators (callbacks) of each sound driver, most of
these records are supposed to be read-only. Only the PCM
- middle-layer changes / updates these info. The excpetions are
+ middle-layer changes / updates these info. The exceptions are
the hardware description (hw), interrupt callbacks
(transfer_ack_xxx), DMA buffer information, and the private
data. Besides, if you use the standard buffer allocation
@@ -3008,6 +3011,9 @@ struct _snd_pcm_runtime {
current appl_ptr for the internal buffer, and this callback
is useful only for such a purpose.
</para>
+ <para>
+ This callback is atomic.
+ </para>
</section>
<section id="pcm-interface-operators-page-callback">
@@ -3205,6 +3211,11 @@ struct _snd_pcm_runtime {
<function>udelay()</function> or <function>mdelay()</function>.
</para>
+ <para>
+ All three atomic callbacks (trigger, pointer, and ack) are
+ called with local interrupts disabled.
+ </para>
+
</section>
<section id="pcm-interface-constraints">
<title>Constraints</title>
@@ -3250,7 +3261,7 @@ struct _snd_pcm_runtime {
<para>
There are many different constraints.
- Look in <filename>sound/asound.h</filename> for a complete list.
+ Look in <filename>sound/pcm.h</filename> for a complete list.
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
@@ -4066,7 +4077,7 @@ struct _snd_pcm_runtime {
Both <function>snd_ac97_write()</function> and
<function>snd_ac97_update()</function> functions are used to
set a value to the given register
- (<constant>AC97_XXX</constant>). The different between them is
+ (<constant>AC97_XXX</constant>). The difference between them is
that <function>snd_ac97_update()</function> doesn't write a
value if the given value has been already set, while
<function>snd_ac97_write()</function> always rewrites the
@@ -4152,8 +4163,8 @@ struct _snd_pcm_runtime {
<title>Proc Files</title>
<para>
The ALSA AC97 interface will create a proc file such as
- <filename>/proc/asound/card0/ac97#0</filename> and
- <filename>ac97#0regs</filename>. You can refer to these files to
+ <filename>/proc/asound/card0/codec97#0/ac97#0-0</filename> and
+ <filename>ac97#0-0+regs</filename>. You can refer to these files to
see the current status and registers of the codec.
</para>
</section>
@@ -4200,18 +4211,6 @@ struct _snd_pcm_runtime {
implementation of mpu401 stuff. For example, emu10k1 has its own
mpu401 routines.
</para>
-
- <para>
- In this document, I won't explain the rawmidi interface API,
- which is the basis of MPU401-UART implementation.
- </para>
-
- <para>
- For details, please check the source,
- <filename>core/rawmidi.c</filename>, and examples such as
- <filename>drivers/mpu401/mpu401_uart.c</filename> or
- <filename>usb/usbmidi.c</filename>.
- </para>
</section>
<section id="midi-interface-constructor">
@@ -4335,6 +4334,354 @@ struct _snd_pcm_runtime {
<!-- ****************************************************** -->
+<!-- RawMIDI Interface -->
+<!-- ****************************************************** -->
+ <chapter id="rawmidi-interface">
+ <title>RawMIDI Interface</title>
+
+ <section id="rawmidi-interface-overview">
+ <title>Overview</title>
+
+ <para>
+ The raw MIDI interface is used for hardware MIDI ports that can
+ be accessed as a byte stream. It is not used for synthesizer
+ chips that do not directly understand MIDI.
+ </para>
+
+ <para>
+ ALSA handles file and buffer management. All you have to do is
+ to write some code to move data between the buffer and the
+ hardware.
+ </para>
+
+ <para>
+ The rawmidi API is defined in
+ <filename>&lt;sound/rawmidi.h&gt;</filename>.
+ </para>
+ </section>
+
+ <section id="rawmidi-interface-constructor">
+ <title>Constructor</title>
+
+ <para>
+ To create a rawmidi device, call the
+ <function>snd_rawmidi_new</function> function:
+ <informalexample>
+ <programlisting>
+<![CDATA[
+ snd_rawmidi_t *rmidi;
+ err = snd_rawmidi_new(chip->card, "MyMIDI", 0, outs, ins, &rmidi);
+ if (err < 0)
+ return err;
+ rmidi->private_data = chip;
+ strcpy(rmidi->name, "My MIDI");
+ rmidi->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT |
+ SNDRV_RAWMIDI_INFO_INPUT |
+ SNDRV_RAWMIDI_INFO_DUPLEX;
+]]>
+ </programlisting>
+ </informalexample>
+ </para>
+
+ <para>
+ The first argument is the card pointer, the second argument is
+ the ID string.
+ </para>
+
+ <para>
+ The third argument is the index of this component. You can
+ create up to 8 rawmidi devices.
+ </para>
+
+ <para>
+ The fourth and fifth arguments are the number of output and
+ input substreams, respectively, of this device. (A substream is
+ the equivalent of a MIDI port.)
+ </para>
+
+ <para>
+ Set the <structfield>info_flags</structfield> field to specify
+ the capabilities of the device.
+ Set <constant>SNDRV_RAWMIDI_INFO_OUTPUT</constant> if there is
+ at least one output port,
+ <constant>SNDRV_RAWMIDI_INFO_INPUT</constant> if there is at
+ least one input port,
+ and <constant>SNDRV_RAWMIDI_INFO_DUPLEX</constant> if the device
+ can handle output and input at the same time.
+ </para>
+
+ <para>
+ After the rawmidi device is created, you need to set the
+ operators (callbacks) for each substream. There are helper
+ functions to set the operators for all substream of a device:
+ <informalexample>
+ <programlisting>
+<![CDATA[
+ snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_mymidi_output_ops);
+ snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_mymidi_input_ops);
+]]>
+ </programlisting>
+ </informalexample>
+ </para>
+
+ <para>
+ The operators are usually defined like this:
+ <informalexample>
+ <programlisting>
+<![CDATA[
+ static snd_rawmidi_ops_t snd_mymidi_output_ops = {
+ .open = snd_mymidi_output_open,
+ .close = snd_mymidi_output_close,
+ .trigger = snd_mymidi_output_trigger,
+ };
+]]>
+ </programlisting>
+ </informalexample>
+ These callbacks are explained in the <link
+ linkend="rawmidi-interface-callbacks"><citetitle>Callbacks</citetitle></link>
+ section.
+ </para>
+
+ <para>
+ If there is more than one substream, you should give each one a
+ unique name:
+ <informalexample>
+ <programlisting>
+<![CDATA[
+ struct list_head *list;
+ snd_rawmidi_substream_t *substream;
+ list_for_each(list, &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams) {
+ substream = list_entry(list, snd_rawmidi_substream_t, list);
+ sprintf(substream->name, "My MIDI Port %d", substream->number + 1);
+ }
+ /* same for SNDRV_RAWMIDI_STREAM_INPUT */
+]]>
+ </programlisting>
+ </informalexample>
+ </para>
+ </section>
+
+ <section id="rawmidi-interface-callbacks">
+ <title>Callbacks</title>
+
+ <para>
+ In all callbacks, the private data that you've set for the
+ rawmidi device can be accessed as
+ substream-&gt;rmidi-&gt;private_data.
+ <!-- <code> isn't available before DocBook 4.3 -->
+ </para>
+
+ <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
+ callback:
+ <informalexample>
+ <programlisting>
+<![CDATA[
+ snd_rawmidi_substream_t *substream;
+ int index = substream->number;
+]]>
+ </programlisting>
+ </informalexample>
+ </para>
+
+ <section id="rawmidi-interface-op-open">
+ <title><function>open</function> callback</title>
+
+ <informalexample>
+ <programlisting>
+<![CDATA[
+ static int snd_xxx_open(snd_rawmidi_substream_t *substream);
+]]>
+ </programlisting>
+ </informalexample>
+
+ <para>
+ This is called when a substream is opened.
+ You can initialize the hardware here, but you should not yet
+ start transmitting/receiving data.
+ </para>
+ </section>
+
+ <section id="rawmidi-interface-op-close">
+ <title><function>close</function> callback</title>
+
+ <informalexample>
+ <programlisting>
+<![CDATA[
+ static int snd_xxx_close(snd_rawmidi_substream_t *substream);
+]]>
+ </programlisting>
+ </informalexample>
+
+ <para>
+ Guess what.
+ </para>
+
+ <para>
+ The <function>open</function> and <function>close</function>
+ callbacks of a rawmidi device are serialized with a mutex,
+ and can sleep.
+ </para>
+ </section>
+
+ <section id="rawmidi-interface-op-trigger-out">
+ <title><function>trigger</function> callback for output
+ substreams</title>
+
+ <informalexample>
+ <programlisting>
+<![CDATA[
+ static void snd_xxx_output_trigger(snd_rawmidi_substream_t *substream, int up);
+]]>
+ </programlisting>
+ </informalexample>
+
+ <para>
+ This is called with a nonzero <parameter>up</parameter>
+ parameter when there is some data in the substream buffer that
+ must be transmitted.
+ </para>
+
+ <para>
+ To read data from the buffer, call
+ <function>snd_rawmidi_transmit_peek</function>. It will
+ return the number of bytes that have been read; this will be
+ less than the number of bytes requested when there is no more
+ data in the buffer.
+ After the data has been transmitted successfully, call
+ <function>snd_rawmidi_transmit_ack</function> to remove the
+ data from the substream buffer:
+ <informalexample>
+ <programlisting>
+<![CDATA[
+ unsigned char data;
+ while (snd_rawmidi_transmit_peek(substream, &data, 1) == 1) {
+ if (mychip_try_to_transmit(data))
+ snd_rawmidi_transmit_ack(substream, 1);
+ else
+ break; /* hardware FIFO full */
+ }
+]]>
+ </programlisting>
+ </informalexample>
+ </para>
+
+ <para>
+ If you know beforehand that the hardware will accept data, you
+ can use the <function>snd_rawmidi_transmit</function> function
+ which reads some data and removes it from the buffer at once:
+ <informalexample>
+ <programlisting>
+<![CDATA[
+ while (mychip_transmit_possible()) {
+ unsigned char data;
+ if (snd_rawmidi_transmit(substream, &data, 1) != 1)
+ break; /* no more data */
+ mychip_transmit(data);
+ }
+]]>
+ </programlisting>
+ </informalexample>
+ </para>
+
+ <para>
+ If you know beforehand how many bytes you can accept, you can
+ use a buffer size greater than one with the
+ <function>snd_rawmidi_transmit*</function> functions.
+ </para>
+
+ <para>
+ The <function>trigger</function> callback must not sleep. If
+ the hardware FIFO is full before the substream buffer has been
+ emptied, you have to continue transmitting data later, either
+ in an interrupt handler, or with a timer if the hardware
+ doesn't have a MIDI transmit interrupt.
+ </para>
+
+ <para>
+ The <function>trigger</function> callback is called with a
+ zero <parameter>up</parameter> parameter when the transmission
+ of data should be aborted.
+ </para>
+ </section>
+
+ <section id="rawmidi-interface-op-trigger-in">
+ <title><function>trigger</function> callback for input
+ substreams</title>
+
+ <informalexample>
+ <programlisting>
+<![CDATA[
+ static void snd_xxx_input_trigger(snd_rawmidi_substream_t *substream, int up);
+]]>
+ </programlisting>
+ </informalexample>
+
+ <para>
+ This is called with a nonzero <parameter>up</parameter>
+ parameter to enable receiving data, or with a zero
+ <parameter>up</parameter> parameter do disable receiving data.
+ </para>
+
+ <para>
+ The <function>trigger</function> callback must not sleep; the
+ actual reading of data from the device is usually done in an
+ interrupt handler.
+ </para>
+
+ <para>
+ When data reception is enabled, your interrupt handler should
+ call <function>snd_rawmidi_receive</function> for all received
+ data:
+ <informalexample>
+ <programlisting>
+<![CDATA[
+ void snd_mychip_midi_interrupt(...)
+ {
+ while (mychip_midi_available()) {
+ unsigned char data;
+ data = mychip_midi_read();
+ snd_rawmidi_receive(substream, &data, 1);
+ }
+ }
+]]>
+ </programlisting>
+ </informalexample>
+ </para>
+ </section>
+
+ <section id="rawmidi-interface-op-drain">
+ <title><function>drain</function> callback</title>
+
+ <informalexample>
+ <programlisting>
+<![CDATA[
+ static void snd_xxx_drain(snd_rawmidi_substream_t *substream);
+]]>
+ </programlisting>
+ </informalexample>
+
+ <para>
+ This is only used with output substreams. This function should wait
+ until all data read from the substream buffer has been transmitted.
+ This ensures that the device can be closed and the driver unloaded
+ without losing data.
+ </para>
+
+ <para>
+ This callback is optional. If you do not set
+ <structfield>drain</structfield> in the snd_rawmidi_ops_t
+ structure, ALSA will simply wait for 50&nbsp;milliseconds
+ instead.
+ </para>
+ </section>
+ </section>
+
+ </chapter>
+
+
+<!-- ****************************************************** -->
<!-- Miscellaneous Devices -->
<!-- ****************************************************** -->
<chapter id="misc-devices">
@@ -4633,7 +4980,7 @@ struct _snd_pcm_runtime {
where <parameter>size</parameter> is the byte size to be
pre-allocated and the <parameter>max</parameter> is the maximal
size to be changed via <filename>prealloc</filename> proc file.
- The allocator will try to get as the large area as possible
+ The allocator will try to get as large area as possible
within the given size.
</para>
@@ -4855,7 +5202,7 @@ struct _snd_pcm_runtime {
If your hardware supports the page table like emu10k1 or the
buffer descriptors like via82xx, you can use the scatter-gather
(SG) DMA. ALSA provides an interface for handling SG-buffers.
- The API is provided in <filename>&lt;sound/pcm_sgbuf.h&gt;</filename>.
+ The API is provided in <filename>&lt;sound/pcm.h&gt;</filename>.
</para>
<para>
@@ -5159,12 +5506,12 @@ struct _snd_pcm_runtime {
<programlisting>
<![CDATA[
#ifdef CONFIG_PM
- static int snd_my_suspend(snd_card_t *card, unsigned int state)
+ static int snd_my_suspend(snd_card_t *card, pm_message_t state)
{
.... // do things for suspsend
return 0;
}
- static int snd_my_resume(snd_card_t *card, unsigned int state)
+ static int snd_my_resume(snd_card_t *card)
{
.... // do things for suspsend
return 0;
@@ -5193,7 +5540,7 @@ struct _snd_pcm_runtime {
<informalexample>
<programlisting>
<![CDATA[
- static int mychip_suspend(snd_card_t *card, unsigned int state)
+ static int mychip_suspend(snd_card_t *card, pm_message_t state)
{
/* (1) */
mychip_t *chip = card->pm_private_data;
diff --git a/Documentation/sound/alsa/VIA82xx-mixer.txt b/Documentation/sound/alsa/VIA82xx-mixer.txt
new file mode 100644
index 0000000000000..1b0ac06ba95db
--- /dev/null
+++ b/Documentation/sound/alsa/VIA82xx-mixer.txt
@@ -0,0 +1,8 @@
+
+ VIA82xx mixer
+ =============
+
+On many VIA82xx boards, the 'Input Source Select' mixer control does not work.
+Setting it to 'Input2' on such boards will cause recording to hang, or fail
+with EIO (input/output error) via OSS emulation. This control should be left
+at 'Input1' for such cards.
diff --git a/Documentation/sound/alsa/hda_codec.txt b/Documentation/sound/alsa/hda_codec.txt
new file mode 100644
index 0000000000000..e9d07b8f1acb5
--- /dev/null
+++ b/Documentation/sound/alsa/hda_codec.txt
@@ -0,0 +1,299 @@
+Notes on Universal Interface for Intel High Definition Audio Codec
+------------------------------------------------------------------
+
+Takashi Iwai <tiwai@suse.de>
+
+
+[Still a draft version]
+
+
+General
+=======
+
+The snd-hda-codec module supports the generic access function for the
+High Definition (HD) audio codecs. It's designed to be independent
+from the controller code like ac97 codec module. The real accessors
+from/to the controller must be implemented in the lowlevel driver.
+
+The structure of this module is similar with ac97_codec module.
+Each codec chip belongs to a bus class which communicates with the
+controller.
+
+
+Initialization of Bus Instance
+==============================
+
+The card driver has to create struct hda_bus at first. The template
+struct should be filled and passed to the constructor:
+
+struct hda_bus_template {
+ void *private_data;
+ struct pci_dev *pci;
+ const char *modelname;
+ struct hda_bus_ops ops;
+};
+
+The card driver can set and use the private_data field to retrieve its
+own data in callback functions. The pci field is used when the patch
+needs to check the PCI subsystem IDs, so on. For non-PCI system, it
+doesn't have to be set, of course.
+The modelname field specifies the board's specific configuration. The
+string is passed to the codec parser, and it depends on the parser how
+the string is used.
+These fields, private_data, pci and modelname are all optional.
+
+The ops field contains the callback functions as the following:
+
+struct hda_bus_ops {
+ int (*command)(struct hda_codec *codec, hda_nid_t nid, int direct,
+ unsigned int verb, unsigned int parm);
+ unsigned int (*get_response)(struct hda_codec *codec);
+ void (*private_free)(struct hda_bus *);
+};
+
+The command callback is called when the codec module needs to send a
+VERB to the controller. It's always a single command.
+The get_response callback is called when the codec requires the answer
+for the last command. These two callbacks are mandatory and have to
+be given.
+The last, private_free callback, is optional. It's called in the
+destructor to release any necessary data in the lowlevel driver.
+
+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,
+ struct hda_bus **busp);
+
+It returns zero if successful. A negative return value means any
+error during creation.
+
+
+Creation of Codec Instance
+==========================
+
+Each codec chip on the board is then created on the BUS instance.
+To create a codec instance, call snd_hda_codec_new().
+
+int snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
+ struct hda_codec **codecp);
+
+The first argument is the BUS instance, the second argument is the
+address of the codec, and the last one is the pointer to store the
+resultant codec instance (can be NULL if not needed).
+
+The codec is stored in a linked list of bus instance. You can follow
+the codec list like:
+
+ struct list_head *p;
+ struct hda_codec *codec;
+ list_for_each(p, &bus->codec_list) {
+ codec = list_entry(p, struct hda_codec, list);
+ ...
+ }
+
+The codec isn't initialized at this stage properly. The
+initialization sequence is called when the controls are built later.
+
+
+Codec Access
+============
+
+To access codec, use snd_codec_read() and snd_codec_write().
+snd_hda_param_read() is for reading parameters.
+For writing a sequence of verbs, use snd_hda_sequence_write().
+
+To retrieve the number of sub nodes connected to the given node, use
+snd_hda_get_sub_nodes(). The connection list can be obtained via
+snd_hda_get_connections() call.
+
+When an unsolicited event happens, pass the event via
+snd_hda_queue_unsol_event() so that the codec routines will process it
+later.
+
+
+(Mixer) Controls
+================
+
+To create mixer controls of all codecs, call
+snd_hda_build_controls(). It then builds the mixers and does
+initialization stuff on each codec.
+
+
+PCM Stuff
+=========
+
+snd_hda_build_pcms() gives the necessary information to create PCM
+streams. When it's called, each codec belonging to the bus stores
+codec->num_pcms and codec->pcm_info fields. The num_pcms indicates
+the number of elements in pcm_info array. The card driver is supposed
+to traverse the codec linked list, read the pcm information in
+pcm_info array, and build pcm instances according to them.
+
+The pcm_info array contains the following record:
+
+/* PCM information for each substream */
+struct hda_pcm_stream {
+ unsigned int substreams; /* number of substreams, 0 = not exist */
+ unsigned int channels_min; /* min. number of channels */
+ unsigned int channels_max; /* max. number of channels */
+ hda_nid_t nid; /* default NID to query rates/formats/bps, or set up */
+ u32 rates; /* supported rates */
+ u64 formats; /* supported formats (SNDRV_PCM_FMTBIT_) */
+ unsigned int maxbps; /* supported max. bit per sample */
+ struct hda_pcm_ops ops;
+};
+
+/* for PCM creation */
+struct hda_pcm {
+ char *name;
+ struct hda_pcm_stream stream[2];
+};
+
+The name can be passed to snd_pcm_new(). The stream field contains
+the information for playback (SNDRV_PCM_STREAM_PLAYBACK = 0) and
+capture (SNDRV_PCM_STREAM_CAPTURE = 1) directions. The card driver
+should pass substreams to snd_pcm_new() for the number of substreams
+to create.
+
+The channels_min, channels_max, rates and formats should be copied to
+runtime->hw record. They and maxbps fields are used also to compute
+the format value for the HDA codec and controller. Call
+snd_hda_calc_stream_format() to get the format value.
+
+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);
+ int (*close)(struct hda_pcm_stream *info, struct hda_codec *codec,
+ snd_pcm_substream_t *substream);
+ int (*prepare)(struct hda_pcm_stream *info, struct hda_codec *codec,
+ unsigned int stream_tag, unsigned int format,
+ snd_pcm_substream_t *substream);
+ int (*cleanup)(struct hda_pcm_stream *info, struct hda_codec *codec,
+ snd_pcm_substream_t *substream);
+};
+
+All are non-NULL, so you can call them safely without NULL check.
+
+The open callback should be called in PCM open after runtime->hw is
+set up. It may override some setting and constraints additionally.
+Similarly, the close callback should be called in the PCM close.
+
+The prepare callback should be called in PCM prepare. This will set
+up the codec chip properly for the operation. The cleanup should be
+called in hw_free to clean up the configuration.
+
+The caller should check the return value, at least for open and
+prepare callbacks. When a negative value is returned, some error
+occurred.
+
+
+Proc Files
+==========
+
+Each codec dumps the widget node information in
+/proc/asound/card*/codec#* file. This information would be really
+helpful for debugging. Please provide its contents together with the
+bug report.
+
+
+Power Management
+================
+
+It's simple:
+Call snd_hda_suspend() in the PM suspend callback.
+Call snd_hda_resume() in the PM resume callback.
+
+
+Codec Preset (Patch)
+====================
+
+To set up and handle the codec functionality fully, each codec may
+have a codec preset (patch). It's defined in struct hda_codec_preset:
+
+ struct hda_codec_preset {
+ unsigned int id;
+ unsigned int mask;
+ unsigned int subs;
+ unsigned int subs_mask;
+ unsigned int rev;
+ const char *name;
+ int (*patch)(struct hda_codec *codec);
+ };
+
+When the codec id and codec subsystem id match with the given id and
+subs fields bitwise (with bitmask mask and subs_mask), the callback
+patch is called. The patch callback should initialize the codec and
+set the codec->patch_ops field. This is defined as below:
+
+ struct hda_codec_ops {
+ int (*build_controls)(struct hda_codec *codec);
+ int (*build_pcms)(struct hda_codec *codec);
+ int (*init)(struct hda_codec *codec);
+ void (*free)(struct hda_codec *codec);
+ void (*unsol_event)(struct hda_codec *codec, unsigned int res);
+ #ifdef CONFIG_PM
+ int (*suspend)(struct hda_codec *codec, pm_message_t state);
+ int (*resume)(struct hda_codec *codec);
+ #endif
+ };
+
+The build_controls callback is called from snd_hda_build_controls().
+Similarly, the build_pcms callback is called from
+snd_hda_build_pcms(). The init callback is called after
+build_controls to initialize the hardware.
+The free callback is called as a destructor.
+
+The unsol_event callback is called when an unsolicited event is
+received.
+
+The suspend and resume callbacks are for power management.
+
+Each entry can be NULL if not necessary to be called.
+
+
+Generic Parser
+==============
+
+When the device doesn't match with any given presets, the widgets are
+parsed via th generic parser (hda_generic.c). Its support is
+limited: no multi-channel support, for example.
+
+
+Digital I/O
+===========
+
+Call snd_hda_create_spdif_out_ctls() from the patch to create controls
+related with SPDIF out. In the patch resume callback, call
+snd_hda_resume_spdif().
+
+
+Helper Functions
+================
+
+snd_hda_get_codec_name() stores the codec name on the given string.
+
+snd_hda_check_board_config() can be used to obtain the configuration
+information matching with the device. Define the table with struct
+hda_board_config entries (zero-terminated), and pass it to the
+function. The function checks the modelname given as a module
+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
+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
+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.
+
+The input MUX helper callbacks for such a control are provided, too:
+snd_hda_input_mux_info() and snd_hda_input_mux_put(). See
+patch_realtek.c for example.
diff --git a/Documentation/sound/alsa/serial-u16550.txt b/Documentation/sound/alsa/serial-u16550.txt
index 65a7264773ad7..c1919559d5091 100644
--- a/Documentation/sound/alsa/serial-u16550.txt
+++ b/Documentation/sound/alsa/serial-u16550.txt
@@ -23,12 +23,12 @@ send the F5 NN command sequence at all; perhaps it ought to.
Usage example for simple serial converter:
- /sbin/setserial /dev/ttyS0 none
+ /sbin/setserial /dev/ttyS0 uart none
/sbin/modprobe snd-serial-u16550 port=0x3f8 irq=4 speed=115200
Usage example for Roland SoundCanvas with 4 MIDI ports:
- /sbin/setserial /dev/ttyS0 none
+ /sbin/setserial /dev/ttyS0 uart none
/sbin/modprobe snd-serial-u16550 port=0x3f8 irq=4 outs=4
In MS-124T mode, one raw MIDI substream is supported (midiCnD0); the outs
@@ -38,7 +38,7 @@ parameter to match (A=19200, B=9600).
Usage example for MS-124T, with A-B switch in A position:
- /sbin/setserial /dev/ttyS0 none
+ /sbin/setserial /dev/ttyS0 uart none
/sbin/modprobe snd-serial-u16550 port=0x3f8 irq=4 adaptor=1 \
speed=19200
@@ -48,7 +48,7 @@ the same data to all four MIDI Out connectors at full MIDI speed.
Usage example for S/A mode:
- /sbin/setserial /dev/ttyS0 none
+ /sbin/setserial /dev/ttyS0 uart none
/sbin/modprobe snd-serial-u16550 port=0x3f8 irq=4 adaptor=2
In MS-124W M/B mode, the driver supports 16 ALSA raw MIDI substreams;
@@ -64,7 +64,7 @@ one byte every 320 us per port.
Usage example for M/B mode:
- /sbin/setserial /dev/ttyS0 none
+ /sbin/setserial /dev/ttyS0 uart none
/sbin/modprobe snd-serial-u16550 port=0x3f8 irq=4 adaptor=3
The MS-124W hardware's M/A mode is currently not supported. This mode allows
diff --git a/Documentation/spinlocks.txt b/Documentation/spinlocks.txt
index c6e24f82d34e6..c2122996631e4 100644
--- a/Documentation/spinlocks.txt
+++ b/Documentation/spinlocks.txt
@@ -1,3 +1,29 @@
+UPDATE March 21 2005 Amit Gud <gud@eth.net>
+
+Macros SPIN_LOCK_UNLOCKED and RW_LOCK_UNLOCKED are deprecated and will be
+removed soon. So for any new code dynamic initialization should be used:
+
+ spinlock_t xxx_lock;
+ rwlock_t xxx_rw_lock;
+
+ static int __init xxx_init(void)
+ {
+ spin_lock_init(&xxx_lock);
+ rw_lock_init(&xxx_rw_lock);
+ ...
+ }
+
+ module_init(xxx_init);
+
+Reasons for deprecation
+ - it hurts automatic lock validators
+ - it becomes intrusive for the realtime preemption patches
+
+Following discussion is still valid, however, with the dynamic initialization
+of spinlocks instead of static.
+
+-----------------------
+
On Fri, 2 Jan 1998, Doug Ledford wrote:
>
> I'm working on making the aic7xxx driver more SMP friendly (as well as
diff --git a/Documentation/sysrq.txt b/Documentation/sysrq.txt
index 63581ae722959..f98c2e31c143e 100644
--- a/Documentation/sysrq.txt
+++ b/Documentation/sysrq.txt
@@ -10,13 +10,32 @@ regardless of whatever else it is doing, unless it is completely locked up.
* How do I enable the magic SysRq key?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
You need to say "yes" to 'Magic SysRq key (CONFIG_MAGIC_SYSRQ)' when
-configuring the kernel. When running on a kernel with SysRq compiled in, it
-may be DISABLED at run-time using following command:
-
- echo "0" > /proc/sys/kernel/sysrq
-
-Note that previous versions disabled sysrq by default, and you were required
-to specifically enable it at run-time. That is not the case any longer.
+configuring the kernel. When running a kernel with SysRq compiled in,
+/proc/sys/kernel/sysrq controls the functions allowed to be invoked via
+the SysRq key. By default the file contains 1 which means that every
+possible SysRq request is allowed (in older versions SysRq was disabled
+by default, and you were required to specifically enable it at run-time
+but this is not the case any more). Here is the list of possible values
+in /proc/sys/kernel/sysrq:
+ 0 - disable sysrq completely
+ 1 - enable all functions of sysrq
+ >1 - bitmask of allowed sysrq functions (see below for detailed function
+ description):
+ 2 - enable control of console logging level
+ 4 - enable control of keyboard (SAK, unraw)
+ 8 - enable debugging dumps of processes etc.
+ 16 - enable sync command
+ 32 - enable remount read-only
+ 64 - enable signalling of processes (term, kill, oom-kill)
+ 128 - allow reboot/poweroff
+ 256 - allow nicing of all RT tasks
+
+You can set the value in the file by the following command:
+ echo "number" >/proc/sys/kernel/sysrq
+
+Note that the value of /proc/sys/kernel/sysrq influences only the invocation
+via a keyboard. Invocation of any operation via /proc/sysrq-trigger is always
+allowed.
* How do I use the magic SysRq key?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -73,6 +92,8 @@ On all - write a character to /proc/sysrq-trigger. eg:
it so that only emergency messages like PANICs or OOPSes would
make it to your console.)
+'f' - Will call oom_kill to kill a memory hog process
+
'e' - Send a SIGTERM to all processes, except for init.
'i' - Send a SIGKILL to all processes, except for init.
diff --git a/Documentation/tty.txt b/Documentation/tty.txt
index 5f6dc126775e2..3958cf746dde8 100644
--- a/Documentation/tty.txt
+++ b/Documentation/tty.txt
@@ -93,6 +93,11 @@ write_wakeup() - May be called at any point between open and close.
ldisc must be careful about setting order and to
handle unexpected calls. Must not sleep.
+ The driver is forbidden from calling this directly
+ from the ->write call from the ldisc as the ldisc
+ is permitted to call the driver write method from
+ this function. In such a situation defer it.
+
Locking
diff --git a/Documentation/usb/error-codes.txt b/Documentation/usb/error-codes.txt
index 9e41284f7e754..1e36f1661cd0a 100644
--- a/Documentation/usb/error-codes.txt
+++ b/Documentation/usb/error-codes.txt
@@ -23,6 +23,9 @@ USB-specific:
-ENODEV specified USB-device or bus doesn't exist
+-ENOENT specified interface or endpoint does not exist or
+ is not enabled
+
-ENXIO host controller driver does not support queuing of this type
of urb. (treat as a host controller bug.)
@@ -88,13 +91,19 @@ one or more packets could finish before an error stops further endpoint I/O.
prescribed bus turn-around time
c) unknown USB error
- In cases b) and c) either -EPROTO or -EILSEQ
- may be returned. Note that often the controller
- hardware does not distinguish among cases a),
- b), and c), so a driver cannot tell whether
- there was a protocol error, a failure to respond
- (often caused by device disconnect), or some
- other fault.
+ Note that often the controller hardware does not
+ distinguish among cases a), b), and c), so a
+ driver cannot tell whether there was a protocol
+ error, a failure to respond (often caused by
+ device disconnect), or some other fault.
+
+-ETIMEDOUT (**) No response packet received within the prescribed
+ bus turn-around time. This error may instead be
+ reported as -EPROTO or -EILSEQ.
+
+ Note that the synchronous USB message functions
+ also use this code to indicate timeout expired
+ before the transfer completed.
-EPIPE (**) Endpoint stalled. For non-control endpoints,
reset this status with usb_clear_halt().
@@ -152,4 +161,7 @@ usb_register():
usb_get_*/usb_set_*():
usb_control_msg():
usb_bulk_msg():
--ETIMEDOUT timeout expired before the transfer completed
+-ETIMEDOUT Timeout expired before the transfer completed.
+ In the future this code may change to -ETIME,
+ whose definition is a closer match to this sort
+ of error.
diff --git a/Documentation/usb/sn9c102.txt b/Documentation/usb/sn9c102.txt
index f6911442b141d..cf9a1187edce5 100644
--- a/Documentation/usb/sn9c102.txt
+++ b/Documentation/usb/sn9c102.txt
@@ -210,8 +210,8 @@ There are other four entries in the directory above for each registered camera:
SN9C10x bridge, while the other two control the sensor chip. "reg" and
"i2c_reg" hold the values of the current register index where the following
reading/writing operations are addressed at through "val" and "i2c_val". Their
-use is not intended for end-users. Note that "i2c_reg" and "i2c_val" won't be
-created if the sensor does not actually support the standard I2C protocol or
+use is not intended for end-users. Note that "i2c_reg" and "i2c_val" will not
+be created if the sensor does not actually support the standard I2C protocol or
its registers are not 8-bit long. Also, remember that you must be logged in as
root before writing to them.
@@ -341,15 +341,8 @@ TAS5130D1B Taiwan Advanced Sensor Corporation
All the available control settings of each image sensor are supported through
the V4L2 interface.
-If you think your camera is based on the above hardware and is not actually
-listed in the above table, you may try to add the specific USB VendorID and
-ProductID identifiers to the sn9c102_id_table[] in the file "sn9c102_sensor.h";
-then compile, load the module again and look at the kernel output.
-If this works, please send an email to the author reporting the kernel
-messages, so that a new entry in the list of supported devices can be added.
-
Donations of new models for further testing and support would be much
-appreciated. Non-available hardware won't be supported by the author of this
+appreciated. Non-available hardware will not be supported by the author of this
driver.
diff --git a/Documentation/usb/usbmon.txt b/Documentation/usb/usbmon.txt
new file mode 100644
index 0000000000000..2f8431f92b77f
--- /dev/null
+++ b/Documentation/usb/usbmon.txt
@@ -0,0 +1,156 @@
+* Introduction
+
+The name "usbmon" in lowercase refers to a facility in kernel which is
+used to collect traces of I/O on the USB bus. This function is analogous
+to a packet socket used by network monitoring tools such as tcpdump(1)
+or Ethereal. Similarly, it is expected that a tool such as usbdump or
+USBMon (with uppercase letters) is used to examine raw traces produced
+by usbmon.
+
+The usbmon reports requests made by peripheral-specific drivers to Host
+Controller Drivers (HCD). So, if HCD is buggy, the traces reported by
+usbmon may not correspond to bus transactions precisely. This is the same
+situation as with tcpdump.
+
+* How to use usbmon to collect raw text traces
+
+Unlike the packet socket, usbmon has an interface which provides traces
+in a text format. This is used for two purposes. First, it serves as a
+common trace exchange format for tools while most sophisticated formats
+are finalized. Second, humans can read it in case tools are not available.
+
+To collect a raw text trace, execute following steps.
+
+1. Prepare
+
+Mount debugfs (it has to be enabled in your kernel configuration), and
+load the usbmon module (if built as module). The second step is skipped
+if usbmon is built into the kernel.
+
+# mount -t debugfs none_debugs /sys/kernel/debug
+# modprobe usbmon
+
+Verify that bus sockets are present.
+
+[root@lembas zaitcev]# ls /sys/kernel/debug/usbmon
+1s 1t 2s 2t 3s 3t 4s 4t
+[root@lembas zaitcev]#
+
+# ls /sys/kernel
+
+2. Find which bus connects to the desired device
+
+Run "cat /proc/bus/usb/devices", and find the T-line which corresponds to
+the device. Usually you do it by looking for the vendor string. If you have
+many similar devices, unplug one and compare two /proc/bus/usb/devices outputs.
+The T-line will have a bus number. Example:
+
+T: Bus=03 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=12 MxCh= 0
+D: Ver= 1.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
+P: Vendor=0557 ProdID=2004 Rev= 1.00
+S: Manufacturer=ATEN
+S: Product=UC100KM V2.00
+
+Bus=03 means it's bus 3.
+
+3. Start 'cat'
+
+# cat /sys/kernel/debug/usbmon/3t > /tmp/1.mon.out
+
+This process will be reading until killed. Naturally, the output can be
+redirected to a desirable location. This is preferred, because it is going
+to be quite long.
+
+4. Perform the desired operation on the USB bus
+
+This is where you do something that creates the traffic: plug in a flash key,
+copy files, control a webcam, etc.
+
+5. Kill cat
+
+Usually it's done with a keyboard interrupt (Control-C).
+
+At this point the output file (/tmp/1.mon.out in this example) can be saved,
+sent by e-mail, or inspected with a text editor. In the last case make sure
+that the file size is not excessive for your favourite editor.
+
+* Raw text data format
+
+The '0t' type data consists of a stream of events, such as URB submission,
+URB callback, submission error. Every event is a text line, which consists
+of whitespace separated words. The number of position of words may depend
+on the event type, but there is a set of words, common for all types.
+
+Here is the list of words, from left to right:
+- URB Tag. This is used to identify URBs is normally a kernel mode address
+ of the URB structure in hexadecimal.
+- Timestamp in microseconds, a decimal number. The timestamp's resolution
+ depends on available clock, and so it can be much worse than a microsecond
+ (if the implementation uses jiffies, for example).
+- Event Type. This type refers to the format of the event, not URB type.
+ Available types are: S - submission, C - callback, E - submission error.
+- "Pipe". The pipe concept is deprecated. This is a composite word, used to
+ be derived from information in pipes. It consists of three fields, separated
+ by colons: URB type and direction, Device address, Endpoint number.
+ Type and direction are encoded with two bytes in the following manner:
+ Ci Co Control input and output
+ Zi Zo Isochronous input and output
+ Ii Io Interrupt input and output
+ Bi Bo Bulk input and output
+ Device address and Endpoint number are decimal numbers with leading zeroes
+ or 3 and 2 positions, correspondingly.
+- URB Status. This field makes no sense for submissions, but is present
+ to help scripts with parsing. In error case, it contains the error code.
+- Data Length. This is the actual length in the URB.
+- Data tag. The usbmon may not always capture data, even if length is nonzero.
+ Only if tag is '=', the data words are present.
+- Data words follow, in big endian hexadecimal format. Notice that they are
+ not machine words, but really just a byte stream split into words to make
+ it easier to read. Thus, the last word may contain from one to four bytes.
+ The length of collected data is limited and can be less than the data length
+ report in Data Length word.
+
+Here is an example of code to read the data stream in a well known programming
+language:
+
+class ParsedLine {
+ int data_len; /* Available length of data */
+ byte data[];
+
+ void parseData(StringTokenizer st) {
+ int availwords = st.countTokens();
+ data = new byte[availwords * 4];
+ data_len = 0;
+ while (st.hasMoreTokens()) {
+ String data_str = st.nextToken();
+ int len = data_str.length() / 2;
+ int i;
+ for (i = 0; i < len; i++) {
+ data[data_len] = Byte.parseByte(
+ data_str.substring(i*2, i*2 + 2),
+ 16);
+ data_len++;
+ }
+ }
+ }
+}
+
+This format is obviously deficient. For example, the setup packet for control
+transfers is not delivered. This will change in the future.
+
+Examples:
+
+An input control transfer to get a port status:
+
+d74ff9a0 2640288196 S Ci:001:00 -115 4 <
+d74ff9a0 2640288202 C Ci:001:00 0 4 = 01010100
+
+An output bulk transfer to send a SCSI command 0x5E in a 31-byte Bulk wrapper
+to a storage device at address 5:
+
+dd65f0e8 4128379752 S Bo:005:02 -115 31 = 55534243 5e000000 00000000 00000600 00000000 00000000 00000000 000000
+dd65f0e8 4128379808 C Bo:005:02 0 31 >
+
+* Raw binary format and API
+
+TBD
diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134
index 117dd29599c81..a6c82fa4de025 100644
--- a/Documentation/video4linux/CARDLIST.saa7134
+++ b/Documentation/video4linux/CARDLIST.saa7134
@@ -6,23 +6,23 @@
5 -> SKNet Monster TV [1131:4e85]
6 -> Tevion MD 9717
7 -> KNC One TV-Station RDS / Typhoon TV Tuner RDS [1131:fe01,1894:fe01]
- 8 -> KNC One TV-Station DVR [1894:a006]
- 9 -> Terratec Cinergy 400 TV [153B:1142]
- 10 -> Medion 5044
- 11 -> Kworld/KuroutoShikou SAA7130-TVPCI
- 12 -> Terratec Cinergy 600 TV [153B:1143]
- 13 -> Medion 7134 [16be:0003]
- 14 -> Typhoon TV+Radio 90031
- 15 -> ELSA EX-VISION 300TV [1048:226b]
- 16 -> ELSA EX-VISION 500TV [1048:226b]
- 17 -> ASUS TV-FM 7134 [1043:4842,1043:4830,1043:4840]
- 18 -> AOPEN VA1000 POWER [1131:7133]
- 19 -> 10MOONS PCI TV CAPTURE CARD [1131:2001]
- 20 -> BMK MPEX No Tuner
- 21 -> Compro VideoMate TV [185b:c100]
- 22 -> Matrox CronosPlus [102B:48d0]
- 23 -> Medion 2819/ AverMedia M156 [1461:a70b,1461:2115]
- 24 -> BMK MPEX Tuner
+ 8 -> Terratec Cinergy 400 TV [153B:1142]
+ 9 -> Medion 5044
+ 10 -> Kworld/KuroutoShikou SAA7130-TVPCI
+ 11 -> Terratec Cinergy 600 TV [153B:1143]
+ 12 -> Medion 7134 [16be:0003]
+ 13 -> Typhoon TV+Radio 90031
+ 14 -> ELSA EX-VISION 300TV [1048:226b]
+ 15 -> ELSA EX-VISION 500TV [1048:226b]
+ 16 -> ASUS TV-FM 7134 [1043:4842,1043:4830,1043:4840]
+ 17 -> AOPEN VA1000 POWER [1131:7133]
+ 18 -> BMK MPEX No Tuner
+ 19 -> Compro VideoMate TV [185b:c100]
+ 20 -> Matrox CronosPlus [102B:48d0]
+ 21 -> 10MOONS PCI TV CAPTURE CARD [1131:2001]
+ 22 -> Medion 2819/ AverMedia M156 [1461:a70b,1461:2115]
+ 23 -> BMK MPEX Tuner
+ 24 -> KNC One TV-Station DVR [1894:a006]
25 -> ASUS TV-FM 7133 [1043:4843]
26 -> Pinnacle PCTV Stereo (saa7134) [11bd:002b]
27 -> Manli MuchTV M-TV002
@@ -32,3 +32,4 @@
31 -> Elitegroup ECS TVP3XP FM1236 Tuner Card (NTSC,FM) [1019:4cb5]
32 -> AVACS SmartTV
33 -> AVerMedia DVD EZMaker [1461:10ff]
+ 34 -> LifeView FlyTV Platinum33 mini [5168:0212]
diff --git a/Documentation/video4linux/README.cx88 b/Documentation/video4linux/README.cx88
index 026acd207a206..897ab834839ad 100644
--- a/Documentation/video4linux/README.cx88
+++ b/Documentation/video4linux/README.cx88
@@ -11,9 +11,6 @@ current status
video
- Basically works.
- Some minor image quality glitches.
- - Red and blue are swapped sometimes for not-yet known
- reasons (seems to depend on the image size, try to resize
- your tv app window as workaround ...).
- For now only capture, overlay support isn't completed yet.
audio
diff --git a/Documentation/video4linux/bttv/Cards b/Documentation/video4linux/bttv/Cards
index 7865e56c5d2ce..7f8c7eb70ab26 100644
--- a/Documentation/video4linux/bttv/Cards
+++ b/Documentation/video4linux/bttv/Cards
@@ -1,9 +1,9 @@
Gunther Mayer's bttv card gallery (graphical version of this text file :-)
-is available at: http://mayerg.gmxhome.de/bttv/bttv-gallery.html
+is available at: http://www.bttv-gallery.de/
-Suppported cards:
+Supported cards:
Bt848/Bt848a/Bt849/Bt878/Bt879 cards
------------------------------------
@@ -166,6 +166,9 @@ Lifeview Flyvideo Series:
or Flyvideo 3000 (SAA7134) w/Stereo TV
These exist in variations w/FM and w/Remote sometimes denoted
by suffixes "FM" and "R".
+ 3) You have a laptop (miniPCI card):
+ Product = FlyTV Platinum Mini
+ Model/Chip = LR212/saa7135
Lifeview.com.tw states (Feb. 2002):
"The FlyVideo2000 and FlyVideo2000s product name have renamed to FlyVideo98."
diff --git a/Documentation/video4linux/bttv/README b/Documentation/video4linux/bttv/README
index 8719b4201d112..a72f4c94fb0b7 100644
--- a/Documentation/video4linux/bttv/README
+++ b/Documentation/video4linux/bttv/README
@@ -22,7 +22,7 @@ very likely specified the wrong (or no) card type. A list of supported
cards is in CARDLIST.bttv
If bttv takes very long to load (happens sometimes with the cheap
-cards which have no tuner), try adding this to your modprobe.conf:
+cards which have no tuner), try adding this to your modules.conf:
options i2c-algo-bit bit_test=1
For the WinTV/PVR you need one firmware file from the driver CD:
diff --git a/MAINTAINERS b/MAINTAINERS
index 7cd2c7ad35fcd..2d0fd20388cef 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -80,7 +80,7 @@ S: Maintained
3C505 NETWORK DRIVER
P: Philip Blundell
-M: Philip.Blundell@pobox.com
+M: philb@gnu.org
L: linux-net@vger.kernel.org
S: Maintained
@@ -155,7 +155,7 @@ S: Maintained
AIO
P: Benjamin LaHaise
-M: bcrl@redhat.com
+M: bcrl@kvack.org
L: linux-aio@kvack.org
S: Supported
@@ -457,6 +457,11 @@ P: Marcel Holtmann
M: marcel@holtmann.org
S: Maintained
+BLUETOOTH HCI BPA10X DRIVER
+P: Marcel Holtmann
+M: marcel@holtmann.org
+S: Maintained
+
BLUETOOTH HCI BFUSB DRIVER
P: Marcel Holtmann
M: marcel@holtmann.org
@@ -501,7 +506,7 @@ P: Gerd Knorr
M: kraxel@bytesex.org
L: video4linux-list@redhat.com
W: http://bytesex.org/bttv/
-S: Maintained
+S: Orphan
BUSLOGIC SCSI DRIVER
P: Leonard N. Zubkoff
@@ -596,11 +601,10 @@ W: http://developer.axis.com
S: Maintained
CRYPTO API
-P: James Morris
-M: jmorris@redhat.com
+P: Herbert Xu
+M: herbert@gondor.apana.org.au
P: David S. Miller
M: davem@davemloft.net
-W http://samba.org/~jamesm/crypto/
L: linux-kernel@vger.kernel.org
S: Maintained
@@ -708,13 +712,6 @@ L: linux-net@vger.kernel.org
W: http://www.digi.com
S: Orphaned
-DIGIBOARD PC/XE AND PC/XI DRIVER
-P: Christoph Lameter
-M: christoph@lameter.com
-W: http://www.digi.com
-L: digilnux@digi.com
-S: Obsolete
-
DIRECTORY NOTIFICATION
P: Stephen Rothwell
M: sfr@canb.auug.org.au
@@ -754,8 +751,10 @@ L: linux-kernel@vger.kernel.org
S: Supported
DRM DRIVERS
+P: David Airlie
+M: airlied@linux.ie
L: dri-devel@lists.sourceforge.net
-S: Supported
+S: Maintained
DSCC4 DRIVER
P: François Romieu
@@ -814,7 +813,7 @@ S: Maintained
ETHEREXPRESS-16 NETWORK DRIVER
P: Philip Blundell
-M: Philip.Blundell@pobox.com
+M: philb@gnu.org
L: linux-net@vger.kernel.org
S: Maintained
@@ -910,10 +909,17 @@ L: linux-scsi@vger.kernel.org
W: http://www.icp-vortex.com/
S: Supported
-GENERIC HDLC DRIVER, N2 AND C101 DRIVERS
+GENERIC HDLC DRIVER, N2, C101, PCI200SYN and WANXL DRIVERS
P: Krzysztof Halasa
M: khc@pm.waw.pl
-W: http://hq.pm.waw.pl/hdlc/
+W: http://www.kernel.org/pub/linux/utils/net/hdlc/
+S: Maintained
+
+HARMONY SOUND DRIVER
+P: Kyle McMartin
+M: kyle@parisc-linux.org
+W: http://www.parisc-linux.org/~kyle/harmony/
+L: parisc-linux@lists.parisc-linux.org
S: Maintained
HAYES ESP SERIAL DRIVER
@@ -978,11 +984,6 @@ M: mikulas@artax.karlin.mff.cuni.cz
W: http://artax.karlin.mff.cuni.cz/~mikulas/vyplody/hpfs/index-e.cgi
S: Maintained
-HPUSBSCSI
-P: Oliver Neukum
-M: oliver@neukum.name
-S: Maintained
-
HUGETLB FILESYSTEM
P: William Irwin
M: wli@holomorphy.com
@@ -991,8 +992,8 @@ S: Maintained
I2C AND SENSORS DRIVERS
P: Greg Kroah-Hartman
M: greg@kroah.com
-P: Philip Edelbrock
-M: phil@netroedge.com
+P: Jean Delvare
+M: khali@linux-fr.org
L: sensors@stimpy.netroedge.com
W: http://www.lm-sensors.nu/
S: Maintained
@@ -1082,9 +1083,21 @@ M: Gadi Oxman <gadio@netvision.net.il>
L: linux-kernel@vger.kernel.org
S: Maintained
+IEEE 1394 ETHERNET (eth1394)
+L: linux1394-devel@lists.sourceforge.net
+W: http://www.linux1394.org/
+S: Orphan
+
+IEEE 1394 SBP2
+L: linux1394-devel@lists.sourceforge.net
+W: http://www.linux1394.org/
+S: Orphan
+
IEEE 1394 SUBSYSTEM
P: Ben Collins
M: bcollins@debian.org
+P: Jody McIntyre
+M: scjody@steamballoon.com
L: linux1394-devel@lists.sourceforge.net
W: http://www.linux1394.org/
S: Maintained
@@ -1092,13 +1105,15 @@ S: Maintained
IEEE 1394 OHCI DRIVER
P: Ben Collins
M: bcollins@debian.org
+P: Jody McIntyre
+M: scjody@steamballoon.com
L: linux1394-devel@lists.sourceforge.net
W: http://www.linux1394.org/
S: Maintained
IEEE 1394 PCILYNX DRIVER
-P: Andreas Bombe
-M: andreas.bombe@munich.netsurf.de
+P: Jody McIntyre
+M: scjody@steamballoon.com
L: linux1394-devel@lists.sourceforge.net
W: http://www.linux1394.org/
S: Maintained
@@ -1106,6 +1121,8 @@ S: Maintained
IEEE 1394 RAW I/O DRIVER
P: Ben Collins
M: bcollins@debian.org
+P: Dan Dennedy
+M: dan@dennedy.org
L: linux1394-devel@lists.sourceforge.net
W: http://www.linux1394.org/
S: Maintained
@@ -1247,8 +1264,8 @@ S: Maintained
JFS FILESYSTEM
P: Dave Kleikamp
M: shaggy@austin.ibm.com
-L: jfs-discussion@oss.software.ibm.com
-W: http://oss.software.ibm.com/jfs/
+L: jfs-discussion@lists.sourceforge.net
+W: http://jfs.sourceforge.net/
S: Supported
KCONFIG
@@ -1372,7 +1389,7 @@ W: http://www.penguinppc.org/
L: linuxppc-embedded@ozlabs.org
S: Maintained
-LINUX FOR POWERPC EMBEDDED PPC85XX
+LINUX FOR POWERPC EMBEDDED PPC83XX AND PPC85XX
P: Kumar Gala
M: kumar.gala@freescale.com
W: http://www.penguinppc.org/
@@ -1695,13 +1712,13 @@ S: Maintained
PARALLEL PORT SUPPORT
P: Phil Blundell
-M: Philip.Blundell@pobox.com
+M: philb@gnu.org
P: Tim Waugh
M: tim@cyberelk.net
P: David Campbell
M: campbell@torque.net
P: Andrea Arcangeli
-M: andrea@e-mind.com
+M: andrea@suse.de
L: linux-parport@lists.infradead.org
W: http://people.redhat.com/twaugh/parport/
S: Maintained
@@ -1966,6 +1983,11 @@ M: christer@weinigel.se
W: http://www.weinigel.se
S: Supported
+SECURITY CONTACT
+P: Security Officers
+M: security@kernel.org
+S: Supported
+
SELINUX SECURITY MODULE
P: Stephen Smalley
M: sds@epoch.ncsc.mil
@@ -2017,10 +2039,11 @@ W: http://gyver.homeip.net/sis5513/index.html
S: Maintained
SIS 900/7016 FAST ETHERNET DRIVER
-P: Ollie Lho
-M: ollie@sis.com.tw
+P: Daniele Venzano
+M: venza@brownhat.org
+W: http://www.brownhat.org/sis900.html
L: linux-net@vger.kernel.org
-S: Supported
+S: Maintained
SIS FRAMEBUFFER DRIVER
P: Thomas Winischhofer
@@ -2028,6 +2051,12 @@ M: thomas@winischhofer.net
W: http://www.winischhofer.net/linuxsisvga.shtml
S: Maintained
+SIS USB2VGA DRIVER
+P: Thomas Winischhofer
+M: thomas@winischhofer.net
+W: http://www.winischhofer.at/linuxsisusbvga.shtml
+S: Maintained
+
SMSC47M1 HARDWARE MONITOR DRIVER
P: Jean Delvare
M: khali@linux-fr.org
@@ -2162,9 +2191,10 @@ SUPERH64 (sh64)
P: Paul Mundt
M: lethal@linux-sh.org
P: Richard Curnow
-M: richard.curnow@superh.com
+M: rc@rc0.org.uk
L: linuxsh-shmedia-dev@lists.sourceforge.net
W: http://www.linux-sh.org
+W: http://www.rc0.org.uk/sh64
S: Maintained
SUN3/3X
@@ -2279,6 +2309,13 @@ L: linux-usb-users@lists.sourceforge.net
L: linux-usb-devel@lists.sourceforge.net
S: Maintained
+USB BLOCK DRIVER (UB ub)
+P: Pete Zaitcev
+M: zaitcev@redhat.com
+L: linux-kernel@vger.kernel.org
+L: linux-usb-devel@lists.sourceforge.net
+S: Supported
+
USB BLUETOOTH TTY CONVERTER DRIVER
P: Greg Kroah-Hartman
M: greg@kroah.com
@@ -2376,6 +2413,12 @@ L: linux-usb-devel@lists.sourceforge.net
W: http://www.chello.nl/~j.vreeken/se401/
S: Maintained
+USB SERIAL CYBERJACK DRIVER
+P: Matthias Bruestle and Harald Welte
+M: support@reiner-sct.com
+W: http://www.reiner-sct.de/support/treiber_cyberjack.php
+S: Maintained
+
USB SERIAL DIGI ACCELEPORT DRIVER
P: Peter Berger and Al Borchers
M: pberger@brimson.com
@@ -2477,6 +2520,14 @@ L: linux-usb-devel@lists.sourceforge.net
W: http://www.linux-projects.org
S: Maintained
+USB ZD1201 DRIVER
+P: Jeroen Vreeken
+M: pe1rxq@amsat.org
+L: linux-usb-users@lists.sourceforge.net
+L: linux-usb-devel@lists.sourceforge.net
+W: http://linux-lc100020.sourceforge.net
+S: Maintained
+
USER-MODE LINUX
P: Jeff Dike
M: jdike@karaya.com
@@ -2500,8 +2551,9 @@ P: Roger Luethi
M: rl@hellgate.ch
S: Maintained
-UCLINUX
+UCLINUX (AND M68KNOMMU)
P: Greg Ungerer
+M: gerg@uclinux.org
M: gerg@snapgear.com
P: David McCullough
M: davidm@snapgear.com
@@ -2534,7 +2586,8 @@ S: Maintained
VIDEO FOR LINUX
P: Gerd Knorr
M: kraxel@bytesex.org
-S: Maintained
+L: video4linux-list@redhat.com
+S: Orphan
W1 DALLAS'S 1-WIRE BUS
P: Evgeniy Polyakov
@@ -2612,11 +2665,11 @@ M: jpr@f6fbb.org
L: linux-hams@vger.kernel.org
S: Maintained
-YMFPCI YAMAHA PCI SOUND
+YMFPCI YAMAHA PCI SOUND (Use ALSA instead)
P: Pete Zaitcev
M: zaitcev@yahoo.com
L: linux-kernel@vger.kernel.org
-S: Maintained
+S: Obsolete
Z8530 DRIVER FOR AX.25
P: Joerg Reuter
diff --git a/Makefile b/Makefile
index 17e08ea79edec..0e5fd7a04e555 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
VERSION = 2
PATCHLEVEL = 6
-SUBLEVEL = 11
-EXTRAVERSION =-rc4
+SUBLEVEL = 12
+EXTRAVERSION =-rc1
NAME=Woozy Numbat
# *DOCUMENTATION*
@@ -18,7 +18,7 @@ MAKEFLAGS += --no-print-directory
#
# Most importantly: sub-Makefiles should only ever modify files in
# their own directory. If in some directory we have a dependency on
-# a file in another dir (which doesn't happen often, but it's of
+# a file in another dir (which doesn't happen often, but it's often
# unavoidable when linking the built-in.o targets which finally
# turn into vmlinux), we will call a sub make in that other dir, and
# after that we are sure that everything which is in that other dir
@@ -67,7 +67,7 @@ endif
# kbuild supports saving output files in a separate directory.
-# To locate output files in a separate directory two syntax'es are supported.
+# To locate output files in a separate directory two syntaxes are supported.
# In both cases the working directory must be the root of the kernel src.
# 1) O=
# Use "make O=dir/to/store/output/files/"
@@ -78,7 +78,8 @@ endif
# export KBUILD_OUTPUT=dir/to/store/output/files/
# make
#
-# The O= assigment takes precedence over the KBUILD_OUTPUT environment variable.
+# The O= assignment takes precedence over the KBUILD_OUTPUT environment
+# variable.
# KBUILD_SRC is set on invocation of make in OBJ directory
@@ -539,16 +540,14 @@ CFLAGS += $(call cc-option,-Wno-pointer-sign,)
# Default kernel image to build when no specific target is given.
# KBUILD_IMAGE may be overruled on the commandline or
# set in the environment
-# Also any assingments in arch/$(ARCH)/Makefiel take precedence over
+# Also any assignments in arch/$(ARCH)/Makefile take precedence over
# this default value
export KBUILD_IMAGE ?= vmlinux
#
# INSTALL_PATH specifies where to place the updated kernel and system map
-# images. Uncomment if you want to place them anywhere other than root.
-#
-
-#export INSTALL_PATH=/boot
+# images. Default is /boot, but you can set it to other values
+export INSTALL_PATH ?= /boot
#
# INSTALL_MOD_PATH specifies a prefix to MODLIB for module directory
@@ -898,7 +897,7 @@ depmod_opts := -b $(INSTALL_MOD_PATH) -r
endif
.PHONY: _modinst_post
_modinst_post: _modinst_
- if [ -r System.map ]; then $(DEPMOD) -ae -F System.map $(depmod_opts) $(KERNELRELEASE); fi
+ if [ -r System.map -a -x $(DEPMOD) ]; then $(DEPMOD) -ae -F System.map $(depmod_opts) $(KERNELRELEASE); fi
else # CONFIG_MODULES
@@ -1096,9 +1095,17 @@ KBUILD_MODULES := 1
crmodverdir:
$(Q)mkdir -p $(MODVERDIR)
+.PHONY: $(objtree)/Module.symvers
+$(objtree)/Module.symvers:
+ @test -e $(objtree)/Module.symvers || ( \
+ echo; \
+ echo " WARNING: Symbol version dump $(objtree)/Module.symvers"; \
+ echo " is missing; modules will have no dependencies and modversions."; \
+ echo )
+
module-dirs := $(addprefix _module_,$(KBUILD_EXTMOD))
.PHONY: $(module-dirs) modules
-$(module-dirs): crmodverdir
+$(module-dirs): crmodverdir $(objtree)/Module.symvers
$(Q)$(MAKE) $(build)=$(patsubst _module_%,%,$@)
modules: $(module-dirs)
@@ -1136,20 +1143,30 @@ endif # KBUILD_EXTMOD
# Generate tags for editors
# ---------------------------------------------------------------------------
+#We want __srctree to totally vanish out when KBUILD_OUTPUT is not set
+#(which is the most common case IMHO) to avoid unneeded clutter in the big tags file.
+#Adding $(srctree) adds about 20M on i386 to the size of the output file!
+
+ifeq ($(KBUILD_OUTPUT),)
+__srctree =
+else
+__srctree = $(srctree)/
+endif
+
define all-sources
- ( find $(srctree) $(RCS_FIND_IGNORE) \
+ ( find $(__srctree) $(RCS_FIND_IGNORE) \
\( -name include -o -name arch \) -prune -o \
-name '*.[chS]' -print; \
- find $(srctree)/arch/$(ARCH) $(RCS_FIND_IGNORE) \
+ find $(__srctree)arch/$(ARCH) $(RCS_FIND_IGNORE) \
-name '*.[chS]' -print; \
- find $(srctree)/security/selinux/include $(RCS_FIND_IGNORE) \
+ find $(__srctree)security/selinux/include $(RCS_FIND_IGNORE) \
-name '*.[chS]' -print; \
- find $(srctree)/include $(RCS_FIND_IGNORE) \
+ find $(__srctree)include $(RCS_FIND_IGNORE) \
\( -name config -o -name 'asm-*' \) -prune \
-o -name '*.[chS]' -print; \
- find $(srctree)/include/asm-$(ARCH) $(RCS_FIND_IGNORE) \
+ find $(__srctree)include/asm-$(ARCH) $(RCS_FIND_IGNORE) \
-name '*.[chS]' -print; \
- find $(srctree)/include/asm-generic $(RCS_FIND_IGNORE) \
+ find $(__srctree)include/asm-generic $(RCS_FIND_IGNORE) \
-name '*.[chS]' -print )
endef
@@ -1172,7 +1189,7 @@ 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"`; \
- $(all-sources) | xargs ctags $$CTAGSF -a
+ $(all-sources) | xargs ctags $$CTAGSF -a --extra=+f
endef
TAGS: FORCE
diff --git a/REPORTING-BUGS b/REPORTING-BUGS
index 4160d1a4fced5..2045eaea2d9e1 100644
--- a/REPORTING-BUGS
+++ b/REPORTING-BUGS
@@ -16,6 +16,10 @@ code relevant to what you were doing. If it occurs repeatably try and
describe how to recreate it. That is worth even more than the oops itself.
The list of maintainers is in the MAINTAINERS file in this directory.
+ If it is a security bug, please copy the Security Contact listed
+in the MAINTAINERS file. They can help coordinate bugfix and disclosure.
+See Documentation/SecurityBugs for more infomation.
+
If you are totally stumped as to whom to send the report, send it to
linux-kernel@vger.kernel.org. (For more information on the linux-kernel
mailing list see http://www.tux.org/lkml/).
diff --git a/arch/alpha/kernel/alpha_ksyms.c b/arch/alpha/kernel/alpha_ksyms.c
index 64ba44928e247..fc5ef90c4fc95 100644
--- a/arch/alpha/kernel/alpha_ksyms.c
+++ b/arch/alpha/kernel/alpha_ksyms.c
@@ -176,7 +176,6 @@ EXPORT_SYMBOL(up);
#ifdef CONFIG_SMP
EXPORT_SYMBOL(synchronize_irq);
-EXPORT_SYMBOL(flush_tlb_all);
EXPORT_SYMBOL(flush_tlb_mm);
EXPORT_SYMBOL(flush_tlb_range);
EXPORT_SYMBOL(flush_tlb_page);
diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c
index dcad8d31d8391..b5d0fd2bb10a0 100644
--- a/arch/alpha/kernel/osf_sys.c
+++ b/arch/alpha/kernel/osf_sys.c
@@ -437,11 +437,10 @@ asmlinkage int
osf_getdomainname(char __user *name, int namelen)
{
unsigned len;
- int i, error;
+ int i;
- error = verify_area(VERIFY_WRITE, name, namelen);
- if (error)
- goto out;
+ if (!access_ok(VERIFY_WRITE, name, namelen))
+ return -EFAULT;
len = namelen;
if (namelen > 32)
@@ -454,8 +453,8 @@ osf_getdomainname(char __user *name, int namelen)
break;
}
up_read(&uts_sem);
- out:
- return error;
+
+ return 0;
}
asmlinkage long
@@ -990,18 +989,19 @@ osf_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp,
char *bits;
size_t size;
long timeout;
- int ret;
+ int ret = -EINVAL;
timeout = MAX_SCHEDULE_TIMEOUT;
if (tvp) {
time_t sec, usec;
- if ((ret = verify_area(VERIFY_READ, tvp, sizeof(*tvp)))
- || (ret = __get_user(sec, &tvp->tv_sec))
- || (ret = __get_user(usec, &tvp->tv_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;
@@ -1011,7 +1011,6 @@ osf_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp,
}
}
- ret = -EINVAL;
if (n < 0 || n > current->files->max_fdset)
goto out_nofds;
diff --git a/arch/alpha/kernel/setup.c b/arch/alpha/kernel/setup.c
index a4724d9957c75..b4e5f8ff2b256 100644
--- a/arch/alpha/kernel/setup.c
+++ b/arch/alpha/kernel/setup.c
@@ -111,8 +111,6 @@ struct alpha_machine_vector alpha_mv;
int alpha_using_srm;
#endif
-unsigned char aux_device_present = 0xaa;
-
#define N(a) (sizeof(a)/sizeof(a[0]))
static struct alpha_machine_vector *get_sysvec(unsigned long, unsigned long,
diff --git a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c
index 974329cf0e5b4..08fe8071a7f8f 100644
--- a/arch/alpha/kernel/signal.c
+++ b/arch/alpha/kernel/signal.c
@@ -91,7 +91,7 @@ osf_sigaction(int sig, const struct osf_sigaction __user *act,
if (act) {
old_sigset_t mask;
- if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
+ if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
__get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
__get_user(new_ka.sa.sa_flags, &act->sa_flags))
return -EFAULT;
@@ -103,7 +103,7 @@ osf_sigaction(int sig, const struct osf_sigaction __user *act,
ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
if (!ret && oact) {
- if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
+ if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
__put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
__put_user(old_ka.sa.sa_flags, &oact->sa_flags))
return -EFAULT;
@@ -298,7 +298,7 @@ do_sigreturn(struct sigcontext __user *sc, struct pt_regs *regs,
sigset_t set;
/* Verify that it's a good sigcontext before using it */
- if (verify_area(VERIFY_READ, sc, sizeof(*sc)))
+ if (!access_ok(VERIFY_READ, sc, sizeof(*sc)))
goto give_sigsegv;
if (__get_user(set.sig[0], &sc->sc_mask))
goto give_sigsegv;
@@ -336,7 +336,7 @@ do_rt_sigreturn(struct rt_sigframe __user *frame, struct pt_regs *regs,
sigset_t set;
/* Verify that it's a good ucontext_t before using it */
- if (verify_area(VERIFY_READ, &frame->uc, sizeof(frame->uc)))
+ if (!access_ok(VERIFY_READ, &frame->uc, sizeof(frame->uc)))
goto give_sigsegv;
if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
goto give_sigsegv;
@@ -446,7 +446,7 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
oldsp = rdusp();
frame = get_sigframe(ka, oldsp, sizeof(*frame));
- if (verify_area(VERIFY_WRITE, frame, sizeof(*frame)))
+ if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
goto give_sigsegv;
err |= setup_sigcontext(&frame->sc, regs, sw, set->sig[0], oldsp);
@@ -497,7 +497,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
oldsp = rdusp();
frame = get_sigframe(ka, oldsp, sizeof(*frame));
- if (verify_area(VERIFY_WRITE, frame, sizeof(*frame)))
+ if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
goto give_sigsegv;
err |= copy_siginfo_to_user(&frame->info, info);
diff --git a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c
index 04a4d366b2a62..8f1e78551b1e3 100644
--- a/arch/alpha/kernel/smp.c
+++ b/arch/alpha/kernel/smp.c
@@ -78,8 +78,6 @@ static unsigned long hwrpb_cpu_present_mask __initdata = 0;
int smp_num_probed; /* Internal processor count */
int smp_num_cpus = 1; /* Number that came online. */
-cycles_t cacheflush_time;
-unsigned long cache_decay_ticks;
extern void calibrate_delay(void);
@@ -177,57 +175,6 @@ smp_callin(void)
cpu_idle();
}
-
-/*
- * Rough estimation for SMP scheduling, this is the number of cycles it
- * takes for a fully memory-limited process to flush the SMP-local cache.
- *
- * We are not told how much cache there is, so we have to guess.
- */
-static void __init
-smp_tune_scheduling (int cpuid)
-{
- struct percpu_struct *cpu;
- unsigned long on_chip_cache; /* kB */
- unsigned long freq; /* Hz */
- unsigned long bandwidth = 350; /* MB/s */
-
- cpu = (struct percpu_struct*)((char*)hwrpb + hwrpb->processor_offset
- + cpuid * hwrpb->processor_size);
- switch (cpu->type)
- {
- case EV45_CPU:
- on_chip_cache = 16 + 16;
- break;
-
- case EV5_CPU:
- case EV56_CPU:
- on_chip_cache = 8 + 8 + 96;
- break;
-
- case PCA56_CPU:
- on_chip_cache = 16 + 8;
- break;
-
- case EV6_CPU:
- case EV67_CPU:
- default:
- on_chip_cache = 64 + 64;
- break;
- }
-
- freq = hwrpb->cycle_freq ? : est_cycle_freq;
-
- cacheflush_time = (freq / 1000000) * (on_chip_cache << 10) / bandwidth;
- cache_decay_ticks = cacheflush_time / (freq / 1000) * HZ / 1000;
-
- printk("per-CPU timeslice cutoff: %ld.%02ld usecs.\n",
- cacheflush_time/(freq/1000000),
- (cacheflush_time*100/(freq/1000000)) % 100);
- printk("task migration cache decay timeout: %ld msecs.\n",
- (cache_decay_ticks + 1) * 1000 / HZ);
-}
-
/* Wait until hwrpb->txrdy is clear for cpu. Return -1 on timeout. */
static int __init
wait_for_txrdy (unsigned long cpumask)
@@ -528,7 +475,6 @@ smp_prepare_cpus(unsigned int max_cpus)
current_thread_info()->cpu = boot_cpuid;
smp_store_cpu_info(boot_cpuid);
- smp_tune_scheduling(boot_cpuid);
smp_setup_percpu_timer(boot_cpuid);
/* Nothing to do on a UP box, or when told not to. */
diff --git a/arch/alpha/kernel/srmcons.c b/arch/alpha/kernel/srmcons.c
index b5660fc3a68ef..3b30d4f1fc42d 100644
--- a/arch/alpha/kernel/srmcons.c
+++ b/arch/alpha/kernel/srmcons.c
@@ -164,29 +164,22 @@ srmcons_get_private_struct(struct srmcons_private **ps)
unsigned long flags;
int retval = 0;
- spin_lock_irqsave(&srmconsp_lock, flags);
-
- do {
- if (srmconsp != NULL) {
- *ps = srmconsp;
- break;
- }
+ if (srmconsp == NULL) {
+ spin_lock_irqsave(&srmconsp_lock, flags);
srmconsp = kmalloc(sizeof(*srmconsp), GFP_KERNEL);
- if (srmconsp == NULL) {
+ if (srmconsp == NULL)
retval = -ENOMEM;
- break;
+ else {
+ srmconsp->tty = NULL;
+ spin_lock_init(&srmconsp->lock);
+ init_timer(&srmconsp->timer);
}
- srmconsp->tty = NULL;
- spin_lock_init(&srmconsp->lock);
- init_timer(&srmconsp->timer);
-
- *ps = srmconsp;
- } while(0);
-
- spin_unlock_irqrestore(&srmconsp_lock, flags);
+ spin_unlock_irqrestore(&srmconsp_lock, flags);
+ }
+ *ps = srmconsp;
return retval;
}
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 1ef65fd36a99b..4055115ae0e28 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -71,6 +71,9 @@ config GENERIC_IOMAP
bool
default y
+config FIQ
+ bool
+
source "init/Kconfig"
menu "System Type"
@@ -81,6 +84,7 @@ choice
config ARCH_CLPS7500
bool "Cirrus-CL-PS7500FE"
+ select TIMER_ACORN
config ARCH_CLPS711X
bool "CLPS711x/EP721x-based"
@@ -111,18 +115,22 @@ config ARCH_FOOTBRIDGE
config ARCH_INTEGRATOR
bool "Integrator"
+ select ARM_AMBA
+ select ICST525
config ARCH_IOP3XX
bool "IOP3xx-based"
config ARCH_IXP4XX
bool "IXP4xx-based"
+ select DMABOUNCE
config ARCH_IXP2000
bool "IXP2400/2800-based"
config ARCH_L7200
bool "LinkUp-L7200"
+ select FIQ
help
Say Y here if you intend to run this kernel on a LinkUp Systems
L7200 Software Development Board which uses an ARM720T processor.
@@ -138,6 +146,9 @@ config ARCH_PXA
config ARCH_RPC
bool "RiscPC"
+ select ARCH_ACORN
+ select FIQ
+ select TIMER_ACORN
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.
@@ -168,6 +179,8 @@ config ARCH_OMAP
config ARCH_VERSATILE
bool "Versatile"
+ select ARM_AMBA
+ select ICST307
help
This enables support for ARM Ltd Versatile board.
@@ -214,54 +227,72 @@ source "arch/arm/mach-versatile/Kconfig"
# Definitions to make life easier
config ARCH_ACORN
bool
- depends on ARCH_RPC
- default y
-config TIMER_ACORN
- bool
- depends on ARCH_ACORN || ARCH_CLPS7500
- default y
+source arch/arm/mm/Kconfig
-#####################################################################
-# SA1111 support
-config SA1111
+# bool 'Use XScale PMU as timer source' CONFIG_XSCALE_PMU_TIMER
+config XSCALE_PMU
bool
- depends on ASSABET_NEPONSET || SA1100_ADSBITSY || SA1100_BADGE4 || SA1100_CONSUS || SA1100_GRAPHICSMASTER || SA1100_JORNADA720 || ARCH_LUBBOCK || SA1100_PFS168 || SA1100_PT_SYSTEM3 || SA1100_XP860
+ depends on CPU_XSCALE && !XSCALE_PMU_TIMER
default y
-config SHARP_LOCOMO
- bool
- depends on SA1100_COLLIE
- default y
+endmenu
-config SHARP_SCOOP
- bool
- depends on PXA_SHARPSL || SA1100_COLLIE
- default y
+source "arch/arm/common/Kconfig"
config FORCE_MAX_ZONEORDER
int
depends on SA1111
default "9"
-config DMABOUNCE
+menu "Bus support"
+
+config ARM_AMBA
+ bool
+
+config ISA
bool
- depends on SA1111 || ARCH_IXP4XX
+ depends on FOOTBRIDGE_HOST || ARCH_SHARK || ARCH_CLPS7500 || ARCH_EBSA110 || ARCH_CDB89712 || ARCH_EDB7211 || ARCH_SA1100 || ARCH_MX1ADS
default y
+ 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
+ inside your box. Other bus systems are PCI, EISA, MicroChannel
+ (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.
-source arch/arm/mm/Kconfig
+config ISA_DMA
+ bool
+ depends on FOOTBRIDGE_HOST || ARCH_SHARK
+ default y
-# bool 'Use XScale PMU as timer source' CONFIG_XSCALE_PMU_TIMER
-config XSCALE_PMU
+config PCI
+ bool "PCI support" if ARCH_INTEGRATOR_AP
+ default y if ARCH_SHARK || FOOTBRIDGE_HOST || ARCH_IOP3XX || ARCH_IXP4XX || ARCH_IXP2000
+ help
+ Find out whether you have a PCI motherboard. PCI is the name of a
+ bus system, i.e. the way the CPU talks to the other stuff inside
+ your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or
+ VESA. If you have PCI, say Y, otherwise N.
+
+ The PCI-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>, contains valuable
+ information about which PCI hardware does work under Linux and which
+ doesn't.
+
+# Select the host bridge type
+config PCI_HOST_VIA82C505
bool
- depends on CPU_XSCALE && !XSCALE_PMU_TIMER
+ depends on PCI && ARCH_SHARK
default y
-endmenu
+source "drivers/pci/Kconfig"
-menu "General setup"
+source "drivers/pcmcia/Kconfig"
+
+endmenu
-# Select various configuration options depending on the machine type
+menu "Kernel Features"
config SMP
bool "Symmetric Multi-Processing (EXPERIMENTAL)"
@@ -286,9 +317,23 @@ config SMP
config NR_CPUS
int "Maximum number of CPUs (2-32)"
+ range 2 32
depends on SMP
default "4"
+config PREEMPT
+ bool "Preemptible Kernel (EXPERIMENTAL)"
+ depends on EXPERIMENTAL
+ help
+ This option reduces the latency of the kernel when reacting to
+ real-time or interactive events by allowing a low priority process to
+ be preempted even if it is in kernel mode executing a system call.
+ This allows applications to run more reliably even when the system is
+ under load.
+
+ Say Y here if you are building a kernel for a desktop, embedded
+ or real-time system. Say N if you are unsure.
+
config DISCONTIGMEM
bool
depends on ARCH_EDB7211 || ARCH_SA1100 || (ARCH_LH7A40X && !LH7A40X_CONTIGMEM)
@@ -299,62 +344,68 @@ config DISCONTIGMEM
or have huge holes in the physical address space for other reasons.
See <file:Documentation/vm/numa> for more.
-# Now handle the bus types
-config PCI
- bool "PCI support" if ARCH_INTEGRATOR_AP
- default y if ARCH_SHARK || FOOTBRIDGE_HOST || ARCH_IOP3XX || ARCH_IXP4XX || ARCH_IXP2000
+config LEDS
+ bool "Timer and CPU usage LEDs"
+ depends on ARCH_CDB89712 || ARCH_CO285 || ARCH_EBSA110 || \
+ 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
help
- Find out whether you have a PCI motherboard. PCI is the name of a
- bus system, i.e. the way the CPU talks to the other stuff inside
- your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or
- VESA. If you have PCI, say Y, otherwise N.
+ If you say Y here, the LEDs on your machine will be used
+ to provide useful information about your current system status.
- The PCI-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>, contains valuable
- information about which PCI hardware does work under Linux and which
- doesn't.
+ If you are compiling a kernel for a NetWinder or EBSA-285, you will
+ be able to select which LEDs are active using the options below. If
+ you are compiling a kernel for the EBSA-110 or the LART however, the
+ red LED will simply flash regularly to indicate that the system is
+ still functional. It is safe to say Y here if you have a CATS
+ system, but the driver will do nothing.
-# Select the host bridge type
-config PCI_HOST_VIA82C505
- bool
- depends on PCI && ARCH_SHARK
- default y
+config LEDS_TIMER
+ bool "Timer LED" if (!ARCH_CDB89712 && !ARCH_OMAP) || \
+ MACH_OMAP_H2 || MACH_OMAP_PERSEUS2
+ depends on LEDS
+ default y if ARCH_EBSA110
+ help
+ If you say Y here, one of the system LEDs (the green one on the
+ NetWinder, the amber one on the EBSA285, or the red one on the LART)
+ will flash regularly to indicate that the system is still
+ operational. This is mainly useful to kernel hackers who are
+ debugging unstable kernels.
-config ICST525
- bool
- depends on ARCH_INTEGRATOR
- default y
+ The LART uses the same LED for both Timer LED and CPU usage LED
+ functions. You may choose to use both, but the Timer LED function
+ will overrule the CPU usage LED.
-config ICST307
- bool
- depends on ARCH_VERSATILE
- default y
+config LEDS_CPU
+ bool "CPU usage LED" if (!ARCH_CDB89712 && !ARCH_EBSA110 && \
+ !ARCH_OMAP) || MACH_OMAP_H2 || MACH_OMAP_PERSEUS2
+ depends on LEDS
+ help
+ If you say Y here, the red LED will be used to give a good real
+ time indication of CPU usage, by lighting whenever the idle task
+ is not currently executing.
-config ARM_AMBA
- bool
- depends on ARCH_INTEGRATOR || ARCH_VERSATILE
- default y
+ The LART uses the same LED for both Timer LED and CPU usage LED
+ functions. You may choose to use both, but the Timer LED function
+ will overrule the CPU usage LED.
-config ISA
+config ALIGNMENT_TRAP
bool
- depends on FOOTBRIDGE_HOST || ARCH_SHARK || ARCH_CLPS7500 || ARCH_EBSA110 || ARCH_CDB89712 || ARCH_EDB7211 || ARCH_SA1100 || ARCH_MX1ADS
- default y
+ default y if !ARCH_EBSA110
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
- inside your box. Other bus systems are PCI, EISA, MicroChannel
- (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.
+ ARM processors can not fetch/store information which is not
+ naturally aligned on the bus, i.e., a 4 byte fetch must start at an
+ address divisible by 4. On 32-bit ARM processors, these non-aligned
+ fetch/store instructions will be emulated in software if you say
+ here, which has a severe performance impact. This is necessary for
+ correct operation of some network protocols. With an IP-only
+ configuration it is safe to say N, otherwise say Y.
-config ISA_DMA
- bool
- depends on FOOTBRIDGE_HOST || ARCH_SHARK
- default y
+endmenu
-config FIQ
- bool
- depends on ARCH_ACORN || ARCH_L7200
- default y
+menu "Boot options"
# Compressed boot loader in ROM. Yes, we really want to ask about
# TEXT and BSS so we preserve their values in the config files.
@@ -388,6 +439,16 @@ config ZBOOT_ROM
Say Y here if you intend to execute your compressed kernel image
(zImage) directly from ROM or flash. If unsure, say N.
+config CMDLINE
+ string "Default kernel command string"
+ default ""
+ help
+ On some architectures (EBSA110 and CATS), there is currently no way
+ for the boot loader to pass arguments to the kernel. For these
+ architectures, you should supply some command-line options at build
+ time by entering them here. As a minimum, you should specify the
+ memory size and the root device (e.g., mem=64M root=/dev/nfs).
+
config XIP_KERNEL
bool "Kernel Execute-In-Place from ROM"
depends on !ZBOOT_ROM
@@ -418,8 +479,12 @@ config XIP_PHYS_ADDR
be linked for and stored to. This address is dependent on your
own flash usage.
+endmenu
+
if (ARCH_SA1100 || ARCH_INTEGRATOR)
+menu "CPU Frequency scaling"
+
source "drivers/cpufreq/Kconfig"
config CPU_FREQ_SA1100
@@ -434,7 +499,7 @@ config CPU_FREQ_SA1110
config CPU_FREQ_INTEGRATOR
tristate "CPUfreq driver for ARM Integrator CPUs"
- depends on ARCH_INTEGRATOR && ICST525 && CPU_FREQ
+ depends on ARCH_INTEGRATOR && CPU_FREQ
default y
help
This enables the CPUfreq driver for ARM Integrator CPUs.
@@ -443,13 +508,13 @@ config CPU_FREQ_INTEGRATOR
If in doubt, say Y.
-endif
+endmenu
-source "drivers/pci/Kconfig"
+endif
-source "drivers/pcmcia/Kconfig"
+menu "Floating point emulation"
-comment "At least one math emulation must be selected"
+comment "At least one emulation must be selected"
config FPE_NWFPE
bool "NWFPE math emulation"
@@ -500,9 +565,24 @@ config VFP
Say N if your target does not have VFP hardware.
+endmenu
+
+menu "Userspace binary formats"
+
source "fs/Kconfig.binfmt"
-source "drivers/base/Kconfig"
+config ARTHUR
+ tristate "RISC OS personality"
+ 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
+ experimental; if this sounds frightening, say N and sleep in peace.
+ You can also say M here to compile this support as a module (which
+ will be called arthur).
+
+endmenu
+
+menu "Power management options"
config PM
bool "Power Management support"
@@ -524,19 +604,6 @@ config PM
will issue the hlt instruction if nothing is to be done, thereby
sending the processor to sleep and saving power.
-config PREEMPT
- bool "Preemptible Kernel (EXPERIMENTAL)"
- depends on CPU_32 && EXPERIMENTAL
- help
- This option reduces the latency of the kernel when reacting to
- real-time or interactive events by allowing a low priority process to
- be preempted even if it is in kernel mode executing a system call.
- This allows applications to run more reliably even when the system is
- under load.
-
- Say Y here if you are building a kernel for a desktop, embedded
- or real-time system. Say N if you are unsure.
-
config APM
tristate "Advanced Power Management Emulation"
depends on PM
@@ -596,115 +663,44 @@ config APM
To compile this driver as a module, choose M here: the
module will be called apm.
-config ARTHUR
- tristate "RISC OS personality"
- depends on CPU_32
- 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
- experimental; if this sounds frightening, say N and sleep in peace.
- You can also say M here to compile this support as a module (which
- will be called arthur).
-
-config CMDLINE
- string "Default kernel command string"
- default ""
- help
- On some architectures (EBSA110 and CATS), there is currently no way
- for the boot loader to pass arguments to the kernel. For these
- architectures, you should supply some command-line options at build
- time by entering them here. As a minimum, you should specify the
- memory size and the root device (e.g., mem=64M root=/dev/nfs).
-
-config LEDS
- bool "Timer and CPU usage LEDs"
- depends on ARCH_NETWINDER || ARCH_EBSA110 || ARCH_EBSA285 || ARCH_SHARK || ARCH_CO285 || ARCH_SA1100 || ARCH_LUBBOCK || MACH_MAINSTONE || ARCH_PXA_IDP || ARCH_INTEGRATOR || ARCH_CDB89712 || ARCH_P720T || ARCH_OMAP || ARCH_VERSATILE || ARCH_IMX
- help
- If you say Y here, the LEDs on your machine will be used
- to provide useful information about your current system status.
-
- If you are compiling a kernel for a NetWinder or EBSA-285, you will
- be able to select which LEDs are active using the options below. If
- you are compiling a kernel for the EBSA-110 or the LART however, the
- red LED will simply flash regularly to indicate that the system is
- still functional. It is safe to say Y here if you have a CATS
- system, but the driver will do nothing.
-
-config LEDS_TIMER
- bool "Timer LED" if LEDS && (ARCH_NETWINDER || ARCH_EBSA285 || ARCH_SHARK || MACH_MAINSTONE || ARCH_CO285 || ARCH_SA1100 || ARCH_LUBBOCK || ARCH_PXA_IDP || ARCH_INTEGRATOR || ARCH_P720T || ARCH_VERSATILE || ARCH_IMX || MACH_OMAP_H2 || MACH_OMAP_PERSEUS2)
- depends on ARCH_NETWINDER || ARCH_EBSA110 || ARCH_EBSA285 || ARCH_SHARK || ARCH_CO285 || ARCH_SA1100 || ARCH_LUBBOCK || MACH_MAINSTONE || ARCH_PXA_IDP || ARCH_INTEGRATOR || ARCH_CDB89712 || ARCH_P720T || ARCH_OMAP || ARCH_VERSATILE || ARCH_IMX
- default y if ARCH_EBSA110
- help
- If you say Y here, one of the system LEDs (the green one on the
- NetWinder, the amber one on the EBSA285, or the red one on the LART)
- will flash regularly to indicate that the system is still
- operational. This is mainly useful to kernel hackers who are
- debugging unstable kernels.
-
- The LART uses the same LED for both Timer LED and CPU usage LED
- functions. You may choose to use both, but the Timer LED function
- will overrule the CPU usage LED.
-
-config LEDS_CPU
- bool "CPU usage LED"
- depends on LEDS && (ARCH_NETWINDER || ARCH_EBSA285 || ARCH_SHARK || ARCH_CO285 || ARCH_SA1100 || ARCH_LUBBOCK || MACH_MAINSTONE || ARCH_PXA_IDP || ARCH_INTEGRATOR || ARCH_P720T || ARCH_VERSATILE || ARCH_IMX || MACH_OMAP_H2 || MACH_OMAP_PERSEUS2)
- help
- If you say Y here, the red LED will be used to give a good real
- time indication of CPU usage, by lighting whenever the idle task
- is not currently executing.
-
- The LART uses the same LED for both Timer LED and CPU usage LED
- functions. You may choose to use both, but the Timer LED function
- will overrule the CPU usage LED.
-
-config ALIGNMENT_TRAP
- bool
- depends on CPU_32
- default y if !ARCH_EBSA110
- help
- ARM processors can not fetch/store information which is not
- naturally aligned on the bus, i.e., a 4 byte fetch must start at an
- address divisible by 4. On 32-bit ARM processors, these non-aligned
- fetch/store instructions will be emulated in software if you say
- here, which has a severe performance impact. This is necessary for
- correct operation of some network protocols. With an IP-only
- configuration it is safe to say N, otherwise say Y.
-
endmenu
-source "drivers/parport/Kconfig"
+menu "Device Drivers"
+
+source "drivers/base/Kconfig"
if ALIGNMENT_TRAP
source "drivers/mtd/Kconfig"
endif
+source "drivers/parport/Kconfig"
+
source "drivers/pnp/Kconfig"
source "drivers/block/Kconfig"
-source "drivers/md/Kconfig"
-
source "drivers/acorn/block/Kconfig"
-source "net/Kconfig"
-
if ARCH_CLPS7500 || ARCH_IOP3XX || ARCH_IXP4XX || ARCH_L7200 || ARCH_LH7A40X || ARCH_PXA || ARCH_RPC || ARCH_S3C2410 || ARCH_SA1100 || ARCH_SHARK || FOOTBRIDGE
source "drivers/ide/Kconfig"
endif
source "drivers/scsi/Kconfig"
+source "drivers/md/Kconfig"
+
source "drivers/message/fusion/Kconfig"
source "drivers/ieee1394/Kconfig"
source "drivers/message/i2o/Kconfig"
+source "net/Kconfig"
+
source "drivers/isdn/Kconfig"
-#
# input before char - char/joystick depends on it. As does USB.
-#
+
source "drivers/input/Kconfig"
source "drivers/char/Kconfig"
@@ -713,22 +709,24 @@ source "drivers/i2c/Kconfig"
#source "drivers/l3/Kconfig"
-source "drivers/media/Kconfig"
-
-source "fs/Kconfig"
+source "drivers/misc/Kconfig"
-source "arch/arm/oprofile/Kconfig"
+source "drivers/media/Kconfig"
source "drivers/video/Kconfig"
source "sound/Kconfig"
-source "drivers/misc/Kconfig"
-
source "drivers/usb/Kconfig"
source "drivers/mmc/Kconfig"
+endmenu
+
+source "fs/Kconfig"
+
+source "arch/arm/oprofile/Kconfig"
+
source "arch/arm/Kconfig.debug"
source "security/Kconfig"
diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
index 27542c0f9c096..45a5709eaaa45 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -47,15 +47,6 @@ config DEBUG_ERRORS
you are concerned with the code size or don't want to see these
messages.
-config DEBUG_INFO
- bool "Include GDB debugging information in kernel binary"
- help
- Say Y here to include source-level debugging information in the
- `vmlinux' binary image. This is handy if you want to use gdb or
- addr2line to debug the kernel. It has no impact on the in-memory
- footprint of the running kernel but it can increase the amount of
- time and disk space needed for compilation of the kernel. If in
- doubt say N.
# These options are only for real kernel hackers who want to get their hands dirty.
config DEBUG_LL
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 8b9760b93ee72..2277e3d179cc7 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -22,15 +22,13 @@ CFLAGS +=-fno-omit-frame-pointer -mapcs -mno-sched-prolog
endif
ifeq ($(CONFIG_CPU_BIG_ENDIAN),y)
-CFLAGS += -mbig-endian
+CPPFLAGS += -mbig-endian
AS += -EB
LD += -EB
-AFLAGS += -mbig-endian
else
-CFLAGS += -mlittle-endian
+CPPFLAGS += -mlittle-endian
AS += -EL
LD += -EL
-AFLAGS += -mlittle-endian
endif
comma = ,
diff --git a/arch/arm/common/Kconfig b/arch/arm/common/Kconfig
new file mode 100644
index 0000000000000..7f5df795881df
--- /dev/null
+++ b/arch/arm/common/Kconfig
@@ -0,0 +1,21 @@
+config ICST525
+ bool
+
+config ICST307
+ bool
+
+config SA1111
+ bool
+ select DMABOUNCE
+
+config DMABOUNCE
+ bool
+
+config TIMER_ACORN
+ bool
+
+config SHARP_LOCOMO
+ bool
+
+config SHARP_SCOOP
+ bool
diff --git a/arch/arm/common/locomo.c b/arch/arm/common/locomo.c
index 34c8cf33ad9ae..41f12658c8b47 100644
--- a/arch/arm/common/locomo.c
+++ b/arch/arm/common/locomo.c
@@ -34,11 +34,33 @@
#include <asm/hardware/locomo.h>
+/* M62332 output channel selection */
+#define M62332_EVR_CH 1 /* M62332 volume channel number */
+ /* 0 : CH.1 , 1 : CH. 2 */
+/* DAC send data */
+#define M62332_SLAVE_ADDR 0x4e /* Slave address */
+#define M62332_W_BIT 0x00 /* W bit (0 only) */
+#define M62332_SUB_ADDR 0x00 /* Sub address */
+#define M62332_A_BIT 0x00 /* A bit (0 only) */
+
+/* DAC setup and hold times (expressed in us) */
+#define DAC_BUS_FREE_TIME 5 /* 4.7 us */
+#define DAC_START_SETUP_TIME 5 /* 4.7 us */
+#define DAC_STOP_SETUP_TIME 4 /* 4.0 us */
+#define DAC_START_HOLD_TIME 5 /* 4.7 us */
+#define DAC_SCL_LOW_HOLD_TIME 5 /* 4.7 us */
+#define DAC_SCL_HIGH_HOLD_TIME 4 /* 4.0 us */
+#define DAC_DATA_SETUP_TIME 1 /* 250 ns */
+#define DAC_DATA_HOLD_TIME 1 /* 300 ns */
+#define DAC_LOW_SETUP_TIME 1 /* 300 ns */
+#define DAC_HIGH_SETUP_TIME 1 /* 1000 ns */
+
/* the following is the overall data for the locomo chip */
struct locomo {
struct device *dev;
unsigned long phys;
unsigned int irq;
+ spinlock_t lock;
void *base;
};
@@ -50,7 +72,57 @@ struct locomo_dev_info {
const char * name;
};
+/* All the locomo devices. If offset is non-zero, the mapbase for the
+ * locomo_dev will be set to the chip base plus offset. If offset is
+ * zero, then the mapbase for the locomo_dev will be set to zero. An
+ * offset of zero means the device only uses GPIOs or other helper
+ * functions inside this file */
static struct locomo_dev_info locomo_devices[] = {
+ {
+ .devid = LOCOMO_DEVID_KEYBOARD,
+ .irq = {
+ IRQ_LOCOMO_KEY,
+ },
+ .name = "locomo-keyboard",
+ .offset = LOCOMO_KEYBOARD,
+ .length = 16,
+ },
+ {
+ .devid = LOCOMO_DEVID_FRONTLIGHT,
+ .irq = {},
+ .name = "locomo-frontlight",
+ .offset = LOCOMO_FRONTLIGHT,
+ .length = 8,
+
+ },
+ {
+ .devid = LOCOMO_DEVID_BACKLIGHT,
+ .irq = {},
+ .name = "locomo-backlight",
+ .offset = LOCOMO_BACKLIGHT,
+ .length = 8,
+ },
+ {
+ .devid = LOCOMO_DEVID_AUDIO,
+ .irq = {},
+ .name = "locomo-audio",
+ .offset = LOCOMO_AUDIO,
+ .length = 4,
+ },
+ {
+ .devid = LOCOMO_DEVID_LED,
+ .irq = {},
+ .name = "locomo-led",
+ .offset = LOCOMO_LED,
+ .length = 8,
+ },
+ {
+ .devid = LOCOMO_DEVID_UART,
+ .irq = {},
+ .name = "locomo-uart",
+ .offset = 0,
+ .length = 0,
+ },
};
@@ -146,7 +218,7 @@ static void locomo_key_handler(unsigned int irq, struct irqdesc *desc,
struct irqdesc *d;
void *mapbase = get_irq_chipdata(irq);
- if (locomo_readl(mapbase + LOCOMO_KIC) & 0x0001) {
+ if (locomo_readl(mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC) & 0x0001) {
d = irq_desc + LOCOMO_IRQ_KEY_START;
d->handle(LOCOMO_IRQ_KEY_START, d, regs);
}
@@ -156,27 +228,27 @@ static void locomo_key_ack_irq(unsigned int irq)
{
void *mapbase = get_irq_chipdata(irq);
unsigned int r;
- r = locomo_readl(mapbase + LOCOMO_KIC);
+ r = locomo_readl(mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC);
r &= ~(0x0100 << (irq - LOCOMO_IRQ_KEY_START));
- locomo_writel(r, mapbase + LOCOMO_KIC);
+ locomo_writel(r, mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC);
}
static void locomo_key_mask_irq(unsigned int irq)
{
void *mapbase = get_irq_chipdata(irq);
unsigned int r;
- r = locomo_readl(mapbase + LOCOMO_KIC);
+ r = locomo_readl(mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC);
r &= ~(0x0010 << (irq - LOCOMO_IRQ_KEY_START));
- locomo_writel(r, mapbase + LOCOMO_KIC);
+ locomo_writel(r, mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC);
}
static void locomo_key_unmask_irq(unsigned int irq)
{
void *mapbase = get_irq_chipdata(irq);
unsigned int r;
- r = locomo_readl(mapbase + LOCOMO_KIC);
+ r = locomo_readl(mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC);
r |= (0x0010 << (irq - LOCOMO_IRQ_KEY_START));
- locomo_writel(r, mapbase + LOCOMO_KIC);
+ locomo_writel(r, mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC);
}
static struct irqchip locomo_key_chip = {
@@ -421,13 +493,11 @@ static void locomo_dev_release(struct device *_dev)
{
struct locomo_dev *dev = LOCOMO_DEV(_dev);
- release_resource(&dev->res);
kfree(dev);
}
static int
-locomo_init_one_child(struct locomo *lchip, struct resource *parent,
- struct locomo_dev_info *info)
+locomo_init_one_child(struct locomo *lchip, struct locomo_dev_info *info)
{
struct locomo_dev *dev;
int ret;
@@ -454,25 +524,17 @@ locomo_init_one_child(struct locomo *lchip, struct resource *parent,
dev->dev.bus = &locomo_bus_type;
dev->dev.release = locomo_dev_release;
dev->dev.coherent_dma_mask = lchip->dev->coherent_dma_mask;
- dev->res.start = lchip->phys + info->offset;
- dev->res.end = dev->res.start + info->length;
- dev->res.name = dev->dev.bus_id;
- dev->res.flags = IORESOURCE_MEM;
- dev->mapbase = lchip->base + info->offset;
- memmove(dev->irq, info->irq, sizeof(dev->irq));
- if (info->length) {
- ret = request_resource(parent, &dev->res);
- if (ret) {
- printk("LoCoMo: failed to allocate resource for %s\n",
- dev->res.name);
- goto out;
- }
- }
+ if (info->offset)
+ dev->mapbase = lchip->base + info->offset;
+ else
+ dev->mapbase = 0;
+ dev->length = info->length;
+
+ memmove(dev->irq, info->irq, sizeof(dev->irq));
ret = device_register(&dev->dev);
if (ret) {
- release_resource(&dev->res);
out:
kfree(dev);
}
@@ -504,6 +566,8 @@ __locomo_probe(struct device *me, struct resource *mem, int irq)
memset(lchip, 0, sizeof(struct locomo));
+ spin_lock_init(&lchip->lock);
+
lchip->dev = me;
dev_set_drvdata(lchip->dev, lchip);
@@ -523,7 +587,7 @@ __locomo_probe(struct device *me, struct resource *mem, int irq)
/* locomo initialize */
locomo_writel(0, lchip->base + LOCOMO_ICR);
/* KEYBOARD */
- locomo_writel(0, lchip->base + LOCOMO_KIC);
+ locomo_writel(0, lchip->base + LOCOMO_KEYBOARD + LOCOMO_KIC);
/* GPIO */
locomo_writel(0, lchip->base + LOCOMO_GPO);
@@ -534,8 +598,8 @@ __locomo_probe(struct device *me, struct resource *mem, int irq)
locomo_writel(0, lchip->base + LOCOMO_GIE);
/* FrontLight */
- locomo_writel(0, lchip->base + LOCOMO_ALS);
- locomo_writel(0, lchip->base + LOCOMO_ALD);
+ locomo_writel(0, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALS);
+ locomo_writel(0, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALD);
/* Longtime timer */
locomo_writel(0, lchip->base + LOCOMO_LTINT);
/* SPI */
@@ -578,7 +642,7 @@ __locomo_probe(struct device *me, struct resource *mem, int irq)
locomo_setup_irq(lchip);
for (i = 0; i < ARRAY_SIZE(locomo_devices); i++)
- locomo_init_one_child(lchip, mem, &locomo_devices[i]);
+ locomo_init_one_child(lchip, &locomo_devices[i]);
return 0;
@@ -654,6 +718,238 @@ static inline struct locomo *locomo_chip_driver(struct locomo_dev *ldev)
return (struct locomo *)dev_get_drvdata(ldev->dev.parent);
}
+void locomo_gpio_set_dir(struct locomo_dev *ldev, unsigned int bits, unsigned int dir)
+{
+ struct locomo *lchip = locomo_chip_driver(ldev);
+ unsigned long flags;
+ unsigned int r;
+
+ spin_lock_irqsave(&lchip->lock, flags);
+
+ r = locomo_readl(lchip->base + LOCOMO_GPD);
+ r &= ~bits;
+ locomo_writel(r, lchip->base + LOCOMO_GPD);
+
+ r = locomo_readl(lchip->base + LOCOMO_GPE);
+ if (dir)
+ r |= bits;
+ else
+ r &= ~bits;
+ locomo_writel(r, lchip->base + LOCOMO_GPE);
+
+ spin_unlock_irqrestore(&lchip->lock, flags);
+}
+
+unsigned int locomo_gpio_read_level(struct locomo_dev *ldev, unsigned int bits)
+{
+ struct locomo *lchip = locomo_chip_driver(ldev);
+ unsigned long flags;
+ unsigned int ret;
+
+ spin_lock_irqsave(&lchip->lock, flags);
+ ret = locomo_readl(lchip->base + LOCOMO_GPL);
+ spin_unlock_irqrestore(&lchip->lock, flags);
+
+ ret &= bits;
+ return ret;
+}
+
+unsigned int locomo_gpio_read_output(struct locomo_dev *ldev, unsigned int bits)
+{
+ struct locomo *lchip = locomo_chip_driver(ldev);
+ unsigned long flags;
+ unsigned int ret;
+
+ spin_lock_irqsave(&lchip->lock, flags);
+ ret = locomo_readl(lchip->base + LOCOMO_GPO);
+ spin_unlock_irqrestore(&lchip->lock, flags);
+
+ ret &= bits;
+ return ret;
+}
+
+void locomo_gpio_write(struct locomo_dev *ldev, unsigned int bits, unsigned int set)
+{
+ struct locomo *lchip = locomo_chip_driver(ldev);
+ unsigned long flags;
+ unsigned int r;
+
+ spin_lock_irqsave(&lchip->lock, flags);
+
+ r = locomo_readl(lchip->base + LOCOMO_GPO);
+ if (set)
+ r |= bits;
+ else
+ r &= ~bits;
+ locomo_writel(r, lchip->base + LOCOMO_GPO);
+
+ spin_unlock_irqrestore(&lchip->lock, flags);
+}
+
+static void locomo_m62332_sendbit(void *mapbase, int bit)
+{
+ unsigned int r;
+
+ r = locomo_readl(mapbase + LOCOMO_DAC);
+ r &= ~(LOCOMO_DAC_SCLOEB);
+ locomo_writel(r, mapbase + LOCOMO_DAC);
+ udelay(DAC_LOW_SETUP_TIME); /* 300 nsec */
+ udelay(DAC_DATA_HOLD_TIME); /* 300 nsec */
+ r = locomo_readl(mapbase + LOCOMO_DAC);
+ r &= ~(LOCOMO_DAC_SCLOEB);
+ locomo_writel(r, mapbase + LOCOMO_DAC);
+ udelay(DAC_LOW_SETUP_TIME); /* 300 nsec */
+ udelay(DAC_SCL_LOW_HOLD_TIME); /* 4.7 usec */
+
+ if (bit & 1) {
+ r = locomo_readl(mapbase + LOCOMO_DAC);
+ r |= LOCOMO_DAC_SDAOEB;
+ locomo_writel(r, mapbase + LOCOMO_DAC);
+ udelay(DAC_HIGH_SETUP_TIME); /* 1000 nsec */
+ } else {
+ r = locomo_readl(mapbase + LOCOMO_DAC);
+ r &= ~(LOCOMO_DAC_SDAOEB);
+ locomo_writel(r, mapbase + LOCOMO_DAC);
+ udelay(DAC_LOW_SETUP_TIME); /* 300 nsec */
+ }
+
+ udelay(DAC_DATA_SETUP_TIME); /* 250 nsec */
+ r = locomo_readl(mapbase + LOCOMO_DAC);
+ r |= LOCOMO_DAC_SCLOEB;
+ locomo_writel(r, mapbase + LOCOMO_DAC);
+ udelay(DAC_HIGH_SETUP_TIME); /* 1000 nsec */
+ udelay(DAC_SCL_HIGH_HOLD_TIME); /* 4.0 usec */
+}
+
+void locomo_m62332_senddata(struct locomo_dev *ldev, unsigned int dac_data, int channel)
+{
+ struct locomo *lchip = locomo_chip_driver(ldev);
+ int i;
+ unsigned char data;
+ unsigned int r;
+ void *mapbase = lchip->base;
+ unsigned long flags;
+
+ spin_lock_irqsave(&lchip->lock, flags);
+
+ /* Start */
+ udelay(DAC_BUS_FREE_TIME); /* 5.0 usec */
+ r = locomo_readl(mapbase + LOCOMO_DAC);
+ r |= LOCOMO_DAC_SCLOEB | LOCOMO_DAC_SDAOEB;
+ locomo_writel(r, mapbase + LOCOMO_DAC);
+ udelay(DAC_HIGH_SETUP_TIME); /* 1000 nsec */
+ udelay(DAC_SCL_HIGH_HOLD_TIME); /* 4.0 usec */
+ r = locomo_readl(mapbase + LOCOMO_DAC);
+ r &= ~(LOCOMO_DAC_SDAOEB);
+ locomo_writel(r, mapbase + LOCOMO_DAC);
+ udelay(DAC_START_HOLD_TIME); /* 5.0 usec */
+ udelay(DAC_DATA_HOLD_TIME); /* 300 nsec */
+
+ /* Send slave address and W bit (LSB is W bit) */
+ data = (M62332_SLAVE_ADDR << 1) | M62332_W_BIT;
+ for (i = 1; i <= 8; i++) {
+ locomo_m62332_sendbit(mapbase, data >> (8 - i));
+ }
+
+ /* Check A bit */
+ r = locomo_readl(mapbase + LOCOMO_DAC);
+ r &= ~(LOCOMO_DAC_SCLOEB);
+ locomo_writel(r, mapbase + LOCOMO_DAC);
+ udelay(DAC_LOW_SETUP_TIME); /* 300 nsec */
+ udelay(DAC_SCL_LOW_HOLD_TIME); /* 4.7 usec */
+ r = locomo_readl(mapbase + LOCOMO_DAC);
+ r &= ~(LOCOMO_DAC_SDAOEB);
+ locomo_writel(r, mapbase + LOCOMO_DAC);
+ udelay(DAC_LOW_SETUP_TIME); /* 300 nsec */
+ r = locomo_readl(mapbase + LOCOMO_DAC);
+ r |= LOCOMO_DAC_SCLOEB;
+ locomo_writel(r, mapbase + LOCOMO_DAC);
+ udelay(DAC_HIGH_SETUP_TIME); /* 1000 nsec */
+ udelay(DAC_SCL_HIGH_HOLD_TIME); /* 4.7 usec */
+ if (locomo_readl(mapbase + LOCOMO_DAC) & LOCOMO_DAC_SDAOEB) { /* High is error */
+ printk(KERN_WARNING "locomo: m62332_senddata Error 1\n");
+ return;
+ }
+
+ /* Send Sub address (LSB is channel select) */
+ /* channel = 0 : ch1 select */
+ /* = 1 : ch2 select */
+ data = M62332_SUB_ADDR + channel;
+ for (i = 1; i <= 8; i++) {
+ locomo_m62332_sendbit(mapbase, data >> (8 - i));
+ }
+
+ /* Check A bit */
+ r = locomo_readl(mapbase + LOCOMO_DAC);
+ r &= ~(LOCOMO_DAC_SCLOEB);
+ locomo_writel(r, mapbase + LOCOMO_DAC);
+ udelay(DAC_LOW_SETUP_TIME); /* 300 nsec */
+ udelay(DAC_SCL_LOW_HOLD_TIME); /* 4.7 usec */
+ r = locomo_readl(mapbase + LOCOMO_DAC);
+ r &= ~(LOCOMO_DAC_SDAOEB);
+ locomo_writel(r, mapbase + LOCOMO_DAC);
+ udelay(DAC_LOW_SETUP_TIME); /* 300 nsec */
+ r = locomo_readl(mapbase + LOCOMO_DAC);
+ r |= LOCOMO_DAC_SCLOEB;
+ locomo_writel(r, mapbase + LOCOMO_DAC);
+ udelay(DAC_HIGH_SETUP_TIME); /* 1000 nsec */
+ udelay(DAC_SCL_HIGH_HOLD_TIME); /* 4.7 usec */
+ if (locomo_readl(mapbase + LOCOMO_DAC) & LOCOMO_DAC_SDAOEB) { /* High is error */
+ printk(KERN_WARNING "locomo: m62332_senddata Error 2\n");
+ return;
+ }
+
+ /* Send DAC data */
+ for (i = 1; i <= 8; i++) {
+ locomo_m62332_sendbit(mapbase, dac_data >> (8 - i));
+ }
+
+ /* Check A bit */
+ r = locomo_readl(mapbase + LOCOMO_DAC);
+ r &= ~(LOCOMO_DAC_SCLOEB);
+ locomo_writel(r, mapbase + LOCOMO_DAC);
+ udelay(DAC_LOW_SETUP_TIME); /* 300 nsec */
+ udelay(DAC_SCL_LOW_HOLD_TIME); /* 4.7 usec */
+ r = locomo_readl(mapbase + LOCOMO_DAC);
+ r &= ~(LOCOMO_DAC_SDAOEB);
+ locomo_writel(r, mapbase + LOCOMO_DAC);
+ udelay(DAC_LOW_SETUP_TIME); /* 300 nsec */
+ r = locomo_readl(mapbase + LOCOMO_DAC);
+ r |= LOCOMO_DAC_SCLOEB;
+ locomo_writel(r, mapbase + LOCOMO_DAC);
+ udelay(DAC_HIGH_SETUP_TIME); /* 1000 nsec */
+ udelay(DAC_SCL_HIGH_HOLD_TIME); /* 4.7 usec */
+ if (locomo_readl(mapbase + LOCOMO_DAC) & LOCOMO_DAC_SDAOEB) { /* High is error */
+ printk(KERN_WARNING "locomo: m62332_senddata Error 3\n");
+ return;
+ }
+
+ /* stop */
+ r = locomo_readl(mapbase + LOCOMO_DAC);
+ r &= ~(LOCOMO_DAC_SCLOEB);
+ locomo_writel(r, mapbase + LOCOMO_DAC);
+ udelay(DAC_LOW_SETUP_TIME); /* 300 nsec */
+ udelay(DAC_SCL_LOW_HOLD_TIME); /* 4.7 usec */
+ r = locomo_readl(mapbase + LOCOMO_DAC);
+ r |= LOCOMO_DAC_SCLOEB;
+ locomo_writel(r, mapbase + LOCOMO_DAC);
+ udelay(DAC_HIGH_SETUP_TIME); /* 1000 nsec */
+ udelay(DAC_SCL_HIGH_HOLD_TIME); /* 4 usec */
+ r = locomo_readl(mapbase + LOCOMO_DAC);
+ r |= LOCOMO_DAC_SDAOEB;
+ locomo_writel(r, mapbase + LOCOMO_DAC);
+ udelay(DAC_HIGH_SETUP_TIME); /* 1000 nsec */
+ udelay(DAC_SCL_HIGH_HOLD_TIME); /* 4 usec */
+
+ r = locomo_readl(mapbase + LOCOMO_DAC);
+ r |= LOCOMO_DAC_SCLOEB | LOCOMO_DAC_SDAOEB;
+ locomo_writel(r, mapbase + LOCOMO_DAC);
+ udelay(DAC_LOW_SETUP_TIME); /* 1000 nsec */
+ udelay(DAC_SCL_LOW_HOLD_TIME); /* 4.7 usec */
+
+ spin_unlock_irqrestore(&lchip->lock, flags);
+}
+
/*
* LoCoMo "Register Access Bus."
*
@@ -755,3 +1051,8 @@ MODULE_AUTHOR("John Lenz <lenz@cs.wisc.edu>");
EXPORT_SYMBOL(locomo_driver_register);
EXPORT_SYMBOL(locomo_driver_unregister);
+EXPORT_SYMBOL(locomo_gpio_set_dir);
+EXPORT_SYMBOL(locomo_gpio_read_level);
+EXPORT_SYMBOL(locomo_gpio_read_output);
+EXPORT_SYMBOL(locomo_gpio_write);
+EXPORT_SYMBOL(locomo_m62332_senddata);
diff --git a/arch/arm/common/rtctime.c b/arch/arm/common/rtctime.c
index 812dac1fa8863..c397e71f938d0 100644
--- a/arch/arm/common/rtctime.c
+++ b/arch/arm/common/rtctime.c
@@ -94,24 +94,29 @@ void rtc_time_to_tm(unsigned long time, struct rtc_time *tm)
EXPORT_SYMBOL(rtc_time_to_tm);
/*
- * Convert Gregorian date to seconds since 01-01-1970 00:00:00.
+ * Does the rtc_time represent a valid date/time?
*/
-int rtc_tm_to_time(struct rtc_time *tm, unsigned long *time)
+int rtc_valid_tm(struct rtc_time *tm)
{
- unsigned int yrs = tm->tm_year + 1900;
-
- *time = 0;
-
- if (yrs < 1970 ||
+ if (tm->tm_year < 70 ||
tm->tm_mon >= 12 ||
tm->tm_mday < 1 ||
- tm->tm_mday > month_days(tm->tm_mon, yrs) ||
+ tm->tm_mday > month_days(tm->tm_mon, tm->tm_year + 1900) ||
tm->tm_hour >= 24 ||
tm->tm_min >= 60 ||
tm->tm_sec >= 60)
return -EINVAL;
- *time = mktime(yrs, tm->tm_mon + 1, tm->tm_mday,
+ return 0;
+}
+EXPORT_SYMBOL(rtc_valid_tm);
+
+/*
+ * Convert Gregorian date to seconds since 01-01-1970 00:00:00.
+ */
+int rtc_tm_to_time(struct rtc_time *tm, unsigned long *time)
+{
+ *time = mktime(tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec);
return 0;
@@ -144,7 +149,13 @@ static inline void rtc_read_time(struct rtc_ops *ops, struct rtc_time *tm)
static inline int rtc_set_time(struct rtc_ops *ops, struct rtc_time *tm)
{
- return ops->set_time(tm);
+ int ret;
+
+ ret = rtc_valid_tm(tm);
+ if (ret == 0)
+ ret = ops->set_time(tm);
+
+ return ret;
}
static inline int rtc_read_alarm(struct rtc_ops *ops, struct rtc_wkalrm *alrm)
@@ -412,7 +423,6 @@ static int rtc_read_proc(char *page, char **start, off_t off, int count, int *eo
struct rtc_wkalrm alrm;
struct rtc_time tm;
char *p = page;
- int len;
rtc_read_time(ops, &tm);
@@ -461,13 +471,7 @@ static int rtc_read_proc(char *page, char **start, off_t off, int count, int *eo
if (ops->proc)
p += ops->proc(p);
- len = (p - page) - off;
- if (len < 0)
- len = 0;
- *eof = len <= count;
- *start = page + off;
-
- return len;
+ return p - page;
}
int register_rtc(struct rtc_ops *ops)
diff --git a/arch/arm/common/scoop.c b/arch/arm/common/scoop.c
index 811c554982804..cfd0d3e550d9e 100644
--- a/arch/arm/common/scoop.c
+++ b/arch/arm/common/scoop.c
@@ -15,47 +15,52 @@
#include <asm/io.h>
#include <asm/hardware/scoop.h>
-static void __iomem *scoop_io_base;
+#define SCOOP_REG(d,adr) (*(volatile unsigned short*)(d +(adr)))
-#define SCOOP_REG(adr) (*(volatile unsigned short*)(scoop_io_base+(adr)))
+struct scoop_dev {
+ void *base;
+ spinlock_t scoop_lock;
+ u32 scoop_gpwr;
+};
-void reset_scoop(void)
+void reset_scoop(struct device *dev)
{
- SCOOP_REG(SCOOP_MCR) = 0x0100; // 00
- SCOOP_REG(SCOOP_CDR) = 0x0000; // 04
- SCOOP_REG(SCOOP_CPR) = 0x0000; // 0C
- SCOOP_REG(SCOOP_CCR) = 0x0000; // 10
- SCOOP_REG(SCOOP_IMR) = 0x0000; // 18
- SCOOP_REG(SCOOP_IRM) = 0x00FF; // 14
- SCOOP_REG(SCOOP_ISR) = 0x0000; // 1C
- SCOOP_REG(SCOOP_IRM) = 0x0000;
+ struct scoop_dev *sdev = dev_get_drvdata(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
+ SCOOP_REG(sdev->base,SCOOP_ISR) = 0x0000; // 1C
+ SCOOP_REG(sdev->base,SCOOP_IRM) = 0x0000;
}
-static DEFINE_SPINLOCK(scoop_lock);
-static u32 scoop_gpwr;
-
-unsigned short set_scoop_gpio(unsigned short bit)
+unsigned short set_scoop_gpio(struct device *dev, unsigned short bit)
{
unsigned short gpio_bit;
unsigned long flag;
+ struct scoop_dev *sdev = dev_get_drvdata(dev);
- spin_lock_irqsave(&scoop_lock, flag);
- gpio_bit = SCOOP_REG(SCOOP_GPWR) | bit;
- SCOOP_REG(SCOOP_GPWR) = gpio_bit;
- spin_unlock_irqrestore(&scoop_lock, flag);
+ spin_lock_irqsave(&sdev->scoop_lock, flag);
+ gpio_bit = SCOOP_REG(sdev->base, SCOOP_GPWR) | bit;
+ SCOOP_REG(sdev->base, SCOOP_GPWR) = gpio_bit;
+ spin_unlock_irqrestore(&sdev->scoop_lock, flag);
return gpio_bit;
}
-unsigned short reset_scoop_gpio(unsigned short bit)
+unsigned short reset_scoop_gpio(struct device *dev, unsigned short bit)
{
unsigned short gpio_bit;
unsigned long flag;
+ struct scoop_dev *sdev = dev_get_drvdata(dev);
- spin_lock_irqsave(&scoop_lock, flag);
- gpio_bit = SCOOP_REG(SCOOP_GPWR) & ~bit;
- SCOOP_REG(SCOOP_GPWR) = gpio_bit;
- spin_unlock_irqrestore(&scoop_lock, flag);
+ spin_lock_irqsave(&sdev->scoop_lock, flag);
+ gpio_bit = SCOOP_REG(sdev->base, SCOOP_GPWR) & ~bit;
+ SCOOP_REG(sdev->base,SCOOP_GPWR) = gpio_bit;
+ spin_unlock_irqrestore(&sdev->scoop_lock, flag);
return gpio_bit;
}
@@ -63,25 +68,30 @@ unsigned short reset_scoop_gpio(unsigned short bit)
EXPORT_SYMBOL(set_scoop_gpio);
EXPORT_SYMBOL(reset_scoop_gpio);
-unsigned short read_scoop_reg(unsigned short reg)
+unsigned short read_scoop_reg(struct device *dev, unsigned short reg)
{
- return SCOOP_REG(reg);
+ struct scoop_dev *sdev = dev_get_drvdata(dev);
+ return SCOOP_REG(sdev->base,reg);
}
-void write_scoop_reg(unsigned short reg, unsigned short data)
+void write_scoop_reg(struct device *dev, unsigned short reg, unsigned short data)
{
- SCOOP_REG(reg)=data;
+ struct scoop_dev *sdev = dev_get_drvdata(dev);
+ SCOOP_REG(sdev->base,reg)=data;
}
EXPORT_SYMBOL(reset_scoop);
EXPORT_SYMBOL(read_scoop_reg);
EXPORT_SYMBOL(write_scoop_reg);
+#ifdef CONFIG_PM
static int scoop_suspend(struct device *dev, uint32_t state, uint32_t level)
{
if (level == SUSPEND_POWER_DOWN) {
- scoop_gpwr = SCOOP_REG(SCOOP_GPWR);
- SCOOP_REG(SCOOP_GPWR) = 0;
+ struct scoop_dev *sdev = dev_get_drvdata(dev);
+
+ sdev->scoop_gpwr = SCOOP_REG(sdev->base,SCOOP_GPWR);
+ SCOOP_REG(sdev->base,SCOOP_GPWR) = 0;
}
return 0;
}
@@ -89,13 +99,20 @@ static int scoop_suspend(struct device *dev, uint32_t state, uint32_t level)
static int scoop_resume(struct device *dev, uint32_t level)
{
if (level == RESUME_POWER_ON) {
- SCOOP_REG(SCOOP_GPWR) = scoop_gpwr;
+ struct scoop_dev *sdev = dev_get_drvdata(dev);
+
+ SCOOP_REG(sdev->base,SCOOP_GPWR) = sdev->scoop_gpwr;
}
return 0;
}
+#else
+#define scoop_suspend NULL
+#define scoop_resume NULL
+#endif
int __init scoop_probe(struct device *dev)
{
+ struct scoop_dev *devptr;
struct scoop_config *inf;
struct platform_device *pdev = to_platform_device(dev);
struct resource *mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -103,25 +120,50 @@ int __init scoop_probe(struct device *dev)
if (!mem)
return -EINVAL;
+ devptr = kmalloc(sizeof(struct scoop_dev), GFP_KERNEL);
+
+ if (!devptr)
+ return -ENOMEM;
+
+ memset(devptr, 0, sizeof(struct scoop_dev));
+ spin_lock_init(&devptr->scoop_lock);
+
inf = dev->platform_data;
- scoop_io_base = ioremap(mem->start, 0x1000);
- if (!scoop_io_base)
+ devptr->base = ioremap(mem->start, mem->end - mem->start + 1);
+
+ if (!devptr->base) {
+ kfree(devptr);
return -ENOMEM;
+ }
- SCOOP_REG(SCOOP_MCR) = 0x0140;
+ dev_set_drvdata(dev, devptr);
- reset_scoop();
+ printk("Sharp Scoop Device found at 0x%08x -> 0x%08x\n",(unsigned int)mem->start,(unsigned int)devptr->base);
- SCOOP_REG(SCOOP_GPCR) = inf->io_dir & 0xffff;
- SCOOP_REG(SCOOP_GPWR) = inf->io_out & 0xffff;
+ SCOOP_REG(devptr->base, SCOOP_MCR) = 0x0140;
+ reset_scoop(dev);
+ SCOOP_REG(devptr->base, SCOOP_GPCR) = inf->io_dir & 0xffff;
+ SCOOP_REG(devptr->base, SCOOP_GPWR) = inf->io_out & 0xffff;
return 0;
}
+static int scoop_remove(struct device *dev)
+{
+ struct scoop_dev *sdev = dev_get_drvdata(dev);
+ if (sdev) {
+ iounmap(sdev->base);
+ kfree(sdev);
+ dev_set_drvdata(dev, NULL);
+ }
+ return 0;
+}
+
static struct device_driver scoop_driver = {
.name = "sharp-scoop",
.bus = &platform_bus_type,
.probe = scoop_probe,
+ .remove = scoop_remove,
.suspend = scoop_suspend,
.resume = scoop_resume,
};
diff --git a/arch/arm/configs/a5k_defconfig b/arch/arm/configs/a5k_defconfig
deleted file mode 100644
index ec03535a7671c..0000000000000
--- a/arch/arm/configs/a5k_defconfig
+++ /dev/null
@@ -1,522 +0,0 @@
-#
-# Automatically generated make config: don't edit
-#
-CONFIG_ARM=y
-# CONFIG_SBUS is not set
-CONFIG_UID16=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-CONFIG_OBSOLETE=y
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-# CONFIG_MODVERSIONS is not set
-CONFIG_KMOD=y
-
-#
-# System Type
-#
-CONFIG_ARCH_ARCA5K=y
-# CONFIG_ARCH_CLPS7500 is not set
-# CONFIG_ARCH_CO285 is not set
-# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_FOOTBRIDGE is not set
-# CONFIG_ARCH_INTEGRATOR is not set
-# CONFIG_ARCH_RPC is not set
-# CONFIG_ARCH_SA1100 is not set
-
-#
-# Archimedes/A5000 Implementations
-#
-
-#
-# Archimedes/A5000 Implementations (select only ONE)
-#
-# CONFIG_ARCH_ARC is not set
-CONFIG_ARCH_A5K=y
-
-#
-# Footbridge Implementations
-#
-
-#
-# SA11x0 Implementations
-#
-CONFIG_ARCH_ACORN=y
-# CONFIG_FOOTBRIDGE is not set
-# CONFIG_FOOTBRIDGE_HOST is not set
-# CONFIG_FOOTBRIDGE_ADDIN is not set
-# CONFIG_CPU_32 is not set
-CONFIG_CPU_26=y
-# CONFIG_PAGESIZE_16 is not set
-
-#
-# Processor Type
-#
-# CONFIG_DISCONTIGMEM is not set
-
-#
-# General setup
-#
-# CONFIG_PCI is not set
-# CONFIG_ISA is not set
-# CONFIG_ISA_DMA is not set
-# CONFIG_HOTPLUG is not set
-# CONFIG_PCMCIA is not set
-CONFIG_NET=y
-CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
-CONFIG_NWFPE=y
-CONFIG_KCORE_ELF=y
-# CONFIG_KCORE_AOUT is not set
-CONFIG_BINFMT_AOUT=y
-# CONFIG_BINFMT_ELF is not set
-# CONFIG_BINFMT_MISC is not set
-# CONFIG_PM is not set
-
-#
-# Parallel port support
-#
-CONFIG_PARPORT=m
-CONFIG_PARPORT_PC=m
-# CONFIG_PARPORT_PC_FIFO is not set
-CONFIG_PARPORT_PC_SUPERIO=y
-# CONFIG_PARPORT_ARC is not set
-# CONFIG_PARPORT_AMIGA is not set
-# CONFIG_PARPORT_MFC3 is not set
-# CONFIG_PARPORT_ATARI is not set
-# CONFIG_PARPORT_SUNBPP is not set
-# CONFIG_PARPORT_OTHER is not set
-# CONFIG_PARPORT_1284 is not set
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Plug and Play configuration
-#
-# CONFIG_PNP is not set
-# CONFIG_ISAPNP is not set
-
-#
-# Block devices
-#
-CONFIG_BLK_DEV_FD=y
-# CONFIG_BLK_DEV_XD is not set
-# CONFIG_PARIDE is not set
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-CONFIG_BLK_DEV_LOOP=m
-# CONFIG_BLK_DEV_NBD is not set
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=4096
-CONFIG_BLK_DEV_INITRD=y
-
-#
-# Acorn-specific block devices
-#
-# CONFIG_BLK_DEV_FD1772 is not set
-CONFIG_BLK_DEV_MFM=m
-CONFIG_BLK_DEV_MFM_AUTODETECT=y
-
-#
-# Networking options
-#
-# CONFIG_PACKET is not set
-# CONFIG_NETLINK is not set
-# CONFIG_NETFILTER is not set
-# CONFIG_FILTER is not set
-CONFIG_UNIX=y
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-# CONFIG_IP_PNP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_INET_ECN is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_IPV6 is not set
-# CONFIG_KHTTPD is not set
-# CONFIG_ATM is not set
-
-#
-#
-#
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_LLC is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network device support
-#
-CONFIG_NETDEVICES=y
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-# CONFIG_NET_SB1000 is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-CONFIG_ARM_ETHER1=y
-CONFIG_ARM_ETHER3=y
-# CONFIG_ARM_ETHERH is not set
-# CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_LANCE is not set
-# CONFIG_NET_VENDOR_SMC is not set
-# CONFIG_NET_VENDOR_RACAL is not set
-# CONFIG_AT1700 is not set
-# CONFIG_DEPCA is not set
-# CONFIG_NET_ISA is not set
-# CONFIG_NET_PCI is not set
-# CONFIG_NET_POCKET is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PLIP is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Token Ring devices
-#
-# CONFIG_TR is not set
-# CONFIG_NET_FC is not set
-# CONFIG_RCPCI is not set
-# CONFIG_SHAPER is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
-# ATA/IDE/MFM/RLL support
-#
-CONFIG_IDE=y
-
-#
-# IDE, ATA and ATAPI Block devices
-#
-CONFIG_BLK_DEV_IDE=y
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
-# CONFIG_BLK_DEV_HD_IDE is not set
-# CONFIG_BLK_DEV_HD 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
-# CONFIG_BLK_DEV_IDESCSI is not set
-
-#
-# IDE chipset support/bugfixes
-#
-# CONFIG_BLK_DEV_CMD640 is not set
-# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
-# CONFIG_BLK_DEV_ISAPNP is not set
-CONFIG_BLK_DEV_IDE_ICSIDE=y
-# CONFIG_BLK_DEV_IDEDMA_ICS is not set
-# CONFIG_IDEDMA_ICS_AUTO is not set
-# CONFIG_BLK_DEV_IDEDMA is not set
-# CONFIG_BLK_DEV_IDE_RAPIDE is not set
-# CONFIG_IDE_CHIPSETS is not set
-# CONFIG_IDEDMA_AUTO is not set
-
-#
-# SCSI support
-#
-# CONFIG_SCSI is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-# CONFIG_I2O_BLOCK is not set
-# CONFIG_I2O_LAN is not set
-# CONFIG_I2O_SCSI is not set
-# CONFIG_I2O_PROC is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN is not set
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_SERIAL=y
-CONFIG_SERIAL_CONSOLE=y
-# CONFIG_ATOMWIDE_SERIAL is not set
-# CONFIG_DUALSP_SERIAL is not set
-# CONFIG_SERIAL_EXTENDED is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
-# CONFIG_UNIX98_PTYS is not set
-# CONFIG_PRINTER is not set
-# CONFIG_PPDEV is not set
-
-#
-# I2C support
-#
-CONFIG_I2C=y
-CONFIG_I2C_ALGOBIT=y
-# CONFIG_I2C_ALGOPCF is not set
-CONFIG_I2C_CHARDEV=y
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-CONFIG_MOUSE=y
-# CONFIG_PSMOUSE is not set
-# CONFIG_82C710_MOUSE is not set
-# CONFIG_PC110_PAD is not set
-
-#
-# Joysticks
-#
-# CONFIG_JOYSTICK is not set
-
-#
-# Input core support is needed for joysticks
-#
-# CONFIG_QIC02_TAPE is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_INTEL_RNG is not set
-# CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
-
-#
-# File systems
-#
-# CONFIG_QUOTA is not set
-# CONFIG_AUTOFS_FS is not set
-CONFIG_AUTOFS4_FS=y
-CONFIG_ADFS_FS=y
-# CONFIG_ADFS_FS_RW is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_BFS_FS is not set
-CONFIG_FAT_FS=m
-CONFIG_MSDOS_FS=m
-# CONFIG_UMSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_JFFS_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_RAMFS is not set
-# CONFIG_ISO9660_FS is not set
-# CONFIG_JOLIET is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_NTFS_FS is not set
-# CONFIG_NTFS_DEBUG is not set
-# CONFIG_NTFS_RW is not set
-# CONFIG_HPFS_FS is not set
-CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
-# CONFIG_DEVFS_MOUNT is not set
-# CONFIG_DEVFS_DEBUG is not set
-# CONFIG_DEVPTS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_QNX4FS_RW is not set
-# CONFIG_ROMFS_FS is not set
-CONFIG_EXT2_FS=y
-# CONFIG_SYSV_FS is not set
-# CONFIG_SYSV_FS_WRITE is not set
-# CONFIG_UDF_FS is not set
-# CONFIG_UDF_RW is not set
-# CONFIG_UFS_FS is not set
-# CONFIG_UFS_FS_WRITE is not set
-
-#
-# Network File Systems
-#
-# CONFIG_CODA_FS is not set
-CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
-# CONFIG_ROOT_NFS is not set
-# CONFIG_NFSD is not set
-# CONFIG_NFSD_V3 is not set
-CONFIG_SUNRPC=y
-CONFIG_LOCKD=y
-# CONFIG_SMB_FS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_NCPFS_PACKET_SIGNING is not set
-# CONFIG_NCPFS_IOCTL_LOCKING is not set
-# CONFIG_NCPFS_STRONG is not set
-# CONFIG_NCPFS_NFS_NS is not set
-# CONFIG_NCPFS_OS2_NS is not set
-# CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_MOUNT_SUBDIR is not set
-# CONFIG_NCPFS_NDS_DOMAINS is not set
-# CONFIG_NCPFS_NLS is not set
-# CONFIG_NCPFS_EXTRAS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-CONFIG_ACORN_PARTITION=y
-CONFIG_ACORN_PARTITION_ADFS=y
-CONFIG_ACORN_PARTITION_ICS=y
-CONFIG_ACORN_PARTITION_POWERTEC=y
-CONFIG_ACORN_PARTITION_RISCIX=y
-CONFIG_NLS=y
-
-#
-# Native Language Support
-#
-CONFIG_NLS_DEFAULT="iso8859-1"
-# CONFIG_NLS_CODEPAGE_437 is not set
-# CONFIG_NLS_CODEPAGE_737 is not set
-# CONFIG_NLS_CODEPAGE_775 is not set
-# CONFIG_NLS_CODEPAGE_850 is not set
-# CONFIG_NLS_CODEPAGE_852 is not set
-# CONFIG_NLS_CODEPAGE_855 is not set
-# CONFIG_NLS_CODEPAGE_857 is not set
-# CONFIG_NLS_CODEPAGE_860 is not set
-# CONFIG_NLS_CODEPAGE_861 is not set
-# CONFIG_NLS_CODEPAGE_862 is not set
-# CONFIG_NLS_CODEPAGE_863 is not set
-# CONFIG_NLS_CODEPAGE_864 is not set
-# CONFIG_NLS_CODEPAGE_865 is not set
-# CONFIG_NLS_CODEPAGE_866 is not set
-# CONFIG_NLS_CODEPAGE_869 is not set
-# CONFIG_NLS_CODEPAGE_874 is not set
-# CONFIG_NLS_CODEPAGE_932 is not set
-# CONFIG_NLS_CODEPAGE_936 is not set
-# CONFIG_NLS_CODEPAGE_949 is not set
-# CONFIG_NLS_CODEPAGE_950 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_8 is not set
-# CONFIG_NLS_ISO8859_9 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_UTF8 is not set
-
-#
-# Console drivers
-#
-CONFIG_FB=y
-
-#
-# Frame-buffer support
-#
-CONFIG_FB=y
-CONFIG_DUMMY_CONSOLE=y
-CONFIG_FB_ACORN=y
-# CONFIG_FB_CYBER2000 is not set
-# CONFIG_FB_VIRTUAL is not set
-# CONFIG_FBCON_ADVANCED is not set
-CONFIG_FBCON_MFB=y
-CONFIG_FBCON_CFB2=y
-CONFIG_FBCON_CFB4=y
-CONFIG_FBCON_CFB8=y
-# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
-CONFIG_FBCON_FONTS=y
-# CONFIG_FONT_8x8 is not set
-# CONFIG_FONT_8x16 is not set
-# CONFIG_FONT_SUN8x16 is not set
-# CONFIG_FONT_SUN12x22 is not set
-# CONFIG_FONT_6x11 is not set
-# CONFIG_FONT_PEARL_8x8 is not set
-CONFIG_FONT_ACORN_8x8=y
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-# CONFIG_USB is not set
-
-#
-# Kernel hacking
-#
-CONFIG_FRAME_POINTER=y
-CONFIG_DEBUG_ERRORS=y
-CONFIG_DEBUG_USER=y
-# CONFIG_DEBUG_INFO is not set
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_NO_PGT_CACHE=y
-CONFIG_DEBUG_LL=y
diff --git a/arch/arm/configs/assabet_defconfig b/arch/arm/configs/assabet_defconfig
index 3e46829452795..ccbb4c0d58c48 100644
--- a/arch/arm/configs/assabet_defconfig
+++ b/arch/arm/configs/assabet_defconfig
@@ -1,22 +1,26 @@
#
# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11
+# Wed Mar 9 13:13:30 2005
#
CONFIG_ARM=y
CONFIG_MMU=y
CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_IOMAP=y
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
CONFIG_CLEAN_COMPILE=y
-CONFIG_STANDALONE=y
CONFIG_BROKEN_ON_SMP=y
#
# General setup
#
+CONFIG_LOCALVERSION=""
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
# CONFIG_POSIX_MQUEUE is not set
@@ -25,16 +29,22 @@ CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
CONFIG_LOG_BUF_SHIFT=14
CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
# CONFIG_IKCONFIG is not set
# CONFIG_EMBEDDED is not set
CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=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
@@ -43,106 +53,52 @@ CONFIG_MODULES=y
# CONFIG_MODULE_UNLOAD is not set
CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
# CONFIG_KMOD is not set
#
# System Type
#
-# CONFIG_ARCH_ADIFCC is not set
# CONFIG_ARCH_CLPS7500 is not set
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
-# CONFIG_ARCH_PXA 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=y
-# CONFIG_ARCH_SHARK 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_PB is not set
-
-#
-# CLPS711X/EP721X Implementations
-#
-
-#
-# Epxa10db
-#
-
-#
-# Footbridge Implementations
-#
-
-#
-# IOP3xx Implementation Options
-#
-# CONFIG_ARCH_IOP310 is not set
-# CONFIG_ARCH_IOP321 is not set
-
-#
-# IOP3xx Chipset Features
-#
-
-#
-# Intel PXA250/210 Implementations
-#
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_H720X is not set
#
# SA11x0 Implementations
#
CONFIG_SA1100_ASSABET=y
# CONFIG_ASSABET_NEPONSET is not set
-# CONFIG_SA1100_ADSBITSY is not set
-# CONFIG_SA1100_BRUTUS is not set
# CONFIG_SA1100_CERF is not set
+# CONFIG_SA1100_COLLIE is not set
# CONFIG_SA1100_H3100 is not set
# CONFIG_SA1100_H3600 is not set
# CONFIG_SA1100_H3800 is not set
-# CONFIG_SA1100_EXTENEX1 is not set
-# CONFIG_SA1100_FLEXANET is not set
-# CONFIG_SA1100_FREEBIRD is not set
-# CONFIG_SA1100_GRAPHICSCLIENT is not set
-# CONFIG_SA1100_GRAPHICSMASTER is not set
# CONFIG_SA1100_BADGE4 is not set
# CONFIG_SA1100_JORNADA720 is not set
# CONFIG_SA1100_HACKKIT is not set
-# CONFIG_SA1100_HUW_WEBPANEL is not set
-# CONFIG_SA1100_ITSY is not set
# CONFIG_SA1100_LART is not set
-# CONFIG_SA1100_NANOENGINE is not set
-# CONFIG_SA1100_OMNIMETER is not set
-# CONFIG_SA1100_PANGOLIN is not set
# CONFIG_SA1100_PLEB is not set
-# CONFIG_SA1100_PT_SYSTEM3 is not set
# CONFIG_SA1100_SHANNON is not set
-# CONFIG_SA1100_SHERMAN is not set
# CONFIG_SA1100_SIMPAD is not set
-# CONFIG_SA1100_PFS168 is not set
-# CONFIG_SA1100_VICTOR is not set
-# CONFIG_SA1100_XP860 is not set
-# CONFIG_SA1100_YOPY is not set
-# CONFIG_SA1100_STORK is not set
# CONFIG_SA1100_SSP is not set
-CONFIG_SA1100_USB=m
-CONFIG_SA1100_USB_NETLINK=m
-# CONFIG_SA1100_USB_CHAR is not set
-
-#
-# TI OMAP Implementations
-#
-
-#
-# OMAP Feature Selections
-#
-
-#
-# S3C2410 Implementations
-#
#
# Processor Type
@@ -152,6 +108,7 @@ CONFIG_CPU_SA1100=y
CONFIG_CPU_32v4=y
CONFIG_CPU_ABRT_EV4=y
CONFIG_CPU_CACHE_V4WB=y
+CONFIG_CPU_CACHE_VIVT=y
CONFIG_CPU_TLB_V4WB=y
CONFIG_CPU_MINICACHE=y
@@ -160,60 +117,86 @@ CONFIG_CPU_MINICACHE=y
#
#
-# General setup
+# Bus support
#
-CONFIG_DISCONTIGMEM=y
CONFIG_ISA=y
-# CONFIG_ZBOOT_ROM is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+CONFIG_PCCARD=y
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=y
+
+#
+# PC-card bridges
+#
+# CONFIG_I82365 is not set
+# CONFIG_TCIC is not set
+CONFIG_PCMCIA_SA1100=y
+
+#
+# Kernel Features
+#
+# CONFIG_PREEMPT is not set
+CONFIG_DISCONTIGMEM=y
+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=ttySA0,38400n8 initrd=0xc0800000,3M root=/dev/ram"
+# CONFIG_XIP_KERNEL is not set
CONFIG_CPU_FREQ=y
-CONFIG_CPU_FREQ_SA1110=y
-# CONFIG_CPU_FREQ_PROC_INTF is not set
+# CONFIG_CPU_FREQ_DEBUG is not set
# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
# CONFIG_CPU_FREQ_GOV_PERFORMANCE is not set
# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set
CONFIG_CPU_FREQ_GOV_USERSPACE=y
-CONFIG_CPU_FREQ_24_API=y
+# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set
+CONFIG_CPU_FREQ_SA1110=y
#
-# PCMCIA/CardBus support
+# Floating point emulation
#
-CONFIG_PCMCIA=y
-# CONFIG_PCMCIA_DEBUG is not set
-# CONFIG_I82365 is not set
-# CONFIG_TCIC is not set
-CONFIG_PCMCIA_SA1100=y
#
-# At least one math emulation must be selected
+# 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
#
-# Generic Driver Options
+# Power management options
#
-# CONFIG_FW_LOADER is not set
CONFIG_PM=y
-# CONFIG_PREEMPT is not set
# CONFIG_APM is not set
-# CONFIG_ARTHUR is not set
-CONFIG_CMDLINE="mem=32M console=ttySA0,38400n8 initrd=0xc0800000,3M root=/dev/ram"
-CONFIG_LEDS=y
-CONFIG_LEDS_TIMER=y
-CONFIG_LEDS_CPU=y
-CONFIG_ALIGNMENT_TRAP=y
#
-# Parallel port support
+# Device Drivers
#
-# CONFIG_PARPORT is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
#
# Memory Technology Devices (MTD)
@@ -223,6 +206,9 @@ CONFIG_MTD=y
CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_CONCAT is not set
CONFIG_MTD_REDBOOT_PARTS=y
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
+# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
# CONFIG_MTD_CMDLINE_PARTS is not set
# CONFIG_MTD_AFS_PARTS is not set
@@ -246,10 +232,12 @@ CONFIG_MTD_CFI_NOSWAP=y
# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
CONFIG_MTD_CFI_GEOMETRY=y
-# CONFIG_MTD_CFI_B1 is not set
-# CONFIG_MTD_CFI_B2 is not set
-CONFIG_MTD_CFI_B4=y
-# CONFIG_MTD_CFI_B8 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 is not set
CONFIG_MTD_CFI_I2=y
# CONFIG_MTD_CFI_I4 is not set
@@ -257,10 +245,11 @@ CONFIG_MTD_CFI_I2=y
CONFIG_MTD_CFI_INTELEXT=y
# CONFIG_MTD_CFI_AMDSTD is not set
# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
+# CONFIG_MTD_XIP is not set
#
# Mapping drivers for chip access
@@ -275,8 +264,10 @@ CONFIG_MTD_SA1100=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
@@ -291,6 +282,11 @@ CONFIG_MTD_SA1100=y
# CONFIG_MTD_NAND is not set
#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
# Plug and Play support
#
# CONFIG_PNP is not set
@@ -300,12 +296,58 @@ CONFIG_MTD_SA1100=y
#
# CONFIG_BLK_DEV_FD is not set
# CONFIG_BLK_DEV_XD is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
CONFIG_BLK_DEV_LOOP=m
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
# CONFIG_BLK_DEV_NBD 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_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_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
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+# CONFIG_IDE_ARM is not set
+# CONFIG_IDE_CHIPSETS is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
#
# Multi-device support (RAID and LVM)
@@ -313,6 +355,18 @@ CONFIG_BLK_DEV_INITRD=y
# CONFIG_MD is not set
#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
# Networking support
#
CONFIG_NET=y
@@ -335,6 +389,9 @@ CONFIG_INET=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_IP_TCPDIAG is not set
+# CONFIG_IP_TCPDIAG_IPV6 is not set
# CONFIG_IPV6 is not set
# CONFIG_NETFILTER is not set
@@ -354,12 +411,12 @@ CONFIG_INET=y
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
#
# QoS and/or fair queueing
#
# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
#
# Network testing
@@ -411,11 +468,9 @@ CONFIG_IRLAN=m
#
# 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_SA1100_FIR=m
-# CONFIG_VIA_FIR is not set
# CONFIG_BT is not set
CONFIG_NETDEVICES=y
# CONFIG_DUMMY is not set
@@ -436,6 +491,7 @@ CONFIG_NET_ETHERNET=y
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_LANCE is not set
# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_SMC91X is not set
# CONFIG_NET_VENDOR_RACAL is not set
# CONFIG_AT1700 is not set
# CONFIG_DEPCA is not set
@@ -485,51 +541,6 @@ CONFIG_PCMCIA_PCNET=y
# CONFIG_NETCONSOLE is not set
#
-# ATA/ATAPI/MFM/RLL support
-#
-CONFIG_IDE=y
-CONFIG_BLK_DEV_IDE=y
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
-CONFIG_BLK_DEV_IDEDISK=y
-# CONFIG_IDEDISK_MULTI_MODE is not set
-# CONFIG_IDEDISK_STROKE is not set
-# CONFIG_BLK_DEV_IDECD is not set
-# CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
-# CONFIG_IDE_TASK_IOCTL is not set
-# CONFIG_IDE_TASKFILE_IO is not set
-
-#
-# IDE chipset support/bugfixes
-#
-CONFIG_IDE_GENERIC=y
-# CONFIG_IDE_CHIPSETS is not set
-# CONFIG_BLK_DEV_IDEDMA is not set
-# CONFIG_IDEDMA_AUTO is not set
-# CONFIG_BLK_DEV_HD is not set
-
-#
-# SCSI device support
-#
-# CONFIG_SCSI is not set
-
-#
-# Fusion MPT device support
-#
-
-#
-# IEEE 1394 (FireWire) support
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-
-#
# ISDN subsystem
#
# CONFIG_ISDN is not set
@@ -559,7 +570,6 @@ CONFIG_INPUT_EVDEV=y
# CONFIG_GAMEPORT is not set
CONFIG_SOUND_GAMEPORT=y
# CONFIG_SERIO is not set
-# CONFIG_SERIO_I8042 is not set
#
# Input Device Drivers
@@ -596,7 +606,6 @@ CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
-# CONFIG_QIC02_TAPE is not set
#
# IPMI
@@ -609,17 +618,12 @@ CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_WATCHDOG is not set
# CONFIG_NVRAM is not set
# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
-CONFIG_SA1100_RTC=y
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
#
# Ftape, the floppy tape device driver
#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
# CONFIG_DRM is not set
#
@@ -634,12 +638,8 @@ CONFIG_SA1100_RTC=y
# CONFIG_I2C is not set
#
-# L3 serial bus support
+# Misc devices
#
-CONFIG_L3=y
-CONFIG_L3_ALGOBIT=y
-CONFIG_L3_BIT_SA1100_GPIO=y
-CONFIG_BIT_SA1100_GPIO=y
#
# Multimedia devices
@@ -652,6 +652,60 @@ CONFIG_BIT_SA1100_GPIO=y
# CONFIG_DVB is not set
#
+# Graphics support
+#
+CONFIG_FB=y
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+CONFIG_FB_SA1100=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 is not set
+
+#
+# Logo configuration
+#
+# CONFIG_LOGO is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+CONFIG_SOUND=y
+
+#
+# Advanced Linux Sound Architecture
+#
+# CONFIG_SND is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
# MMC/SD Card support
#
# CONFIG_MMC is not set
@@ -665,10 +719,15 @@ CONFIG_EXT2_FS=y
# CONFIG_JBD is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
# CONFIG_XFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
@@ -684,6 +743,7 @@ CONFIG_EXT2_FS=y
CONFIG_FAT_FS=y
CONFIG_MSDOS_FS=y
# CONFIG_VFAT_FS is not set
+CONFIG_FAT_DEFAULT_CODEPAGE=437
# CONFIG_NTFS_FS is not set
#
@@ -694,6 +754,7 @@ CONFIG_SYSFS=y
# CONFIG_DEVFS_FS is not set
# CONFIG_DEVPTS_FS_XATTR is not set
CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
@@ -711,6 +772,11 @@ CONFIG_RAMFS=y
CONFIG_JFFS2_FS=y
CONFIG_JFFS2_FS_DEBUG=0
# CONFIG_JFFS2_FS_NAND is not set
+# CONFIG_JFFS2_FS_NOR_ECC is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
# CONFIG_CRAMFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_HPFS_FS is not set
@@ -727,14 +793,13 @@ CONFIG_NFS_FS=y
# CONFIG_NFS_DIRECTIO is not set
# CONFIG_NFSD is not set
CONFIG_LOCKD=y
-# CONFIG_EXPORTFS is not set
CONFIG_SUNRPC=y
# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
# CONFIG_CIFS is not set
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
# CONFIG_AFS_FS is not set
#
@@ -752,7 +817,6 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_SOLARIS_X86_PARTITION is not set
# CONFIG_UNIXWARE_DISKLABEL is not set
# CONFIG_LDM_PARTITION is not set
-# CONFIG_NEC98_PARTITION is not set
# CONFIG_SGI_PARTITION is not set
# CONFIG_ULTRIX_PARTITION is not set
# CONFIG_SUN_PARTITION is not set
@@ -786,6 +850,7 @@ CONFIG_NLS_CODEPAGE_437=y
# 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
@@ -807,84 +872,19 @@ CONFIG_NLS_CODEPAGE_437=y
# CONFIG_PROFILING is not set
#
-# Graphics support
-#
-CONFIG_FB=y
-CONFIG_FB_SA1100=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 is not set
-
-#
-# Logo configuration
-#
-# CONFIG_LOGO is not set
-
-#
-# Sound
-#
-CONFIG_SOUND=y
-
-#
-# Advanced Linux Sound Architecture
-#
-# CONFIG_SND is not set
-
-#
-# Open Sound System
-#
-# CONFIG_SOUND_PRIME is not set
-CONFIG_SOUND_SA1100=y
-CONFIG_SOUND_UDA1341=y
-CONFIG_SOUND_ASSABET_UDA1341=y
-# CONFIG_SOUND_SA1100SSP is not set
-
-#
-# Misc devices
-#
-
-#
-# Multimedia Capabilities Port drivers
-#
-CONFIG_MCP=y
-CONFIG_MCP_SA1100=y
-CONFIG_MCP_UCB1200=y
-CONFIG_MCP_UCB1200_AUDIO=m
-CONFIG_MCP_UCB1200_TS=y
-
-#
-# Console Switches
-#
-CONFIG_SWITCHES=y
-CONFIG_SWITCHES_SA1100=y
-CONFIG_SWITCHES_UCB1X00=y
-
-#
-# USB support
-#
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
# Kernel hacking
#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_PRINTK_TIME is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_INFO is not set
CONFIG_FRAME_POINTER=y
CONFIG_DEBUG_USER=y
-# CONFIG_DEBUG_INFO is not set
-# CONFIG_DEBUG_KERNEL is not set
#
# Security options
#
+# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
#
@@ -893,8 +893,14 @@ CONFIG_DEBUG_USER=y
# CONFIG_CRYPTO is not set
#
+# Hardware crypto devices
+#
+
+#
# Library routines
#
+CONFIG_CRC_CCITT=m
CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/arm/configs/badge4_defconfig b/arch/arm/configs/badge4_defconfig
index 3f8bb2e0e101b..2b4059d2f8e45 100644
--- a/arch/arm/configs/badge4_defconfig
+++ b/arch/arm/configs/badge4_defconfig
@@ -1,41 +1,64 @@
#
# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.12-rc1-bk2
+# Sat Mar 26 21:32:26 2005
#
CONFIG_ARM=y
-# CONFIG_EISA is not set
-# CONFIG_SBUS is not set
-# CONFIG_MCA is not set
+CONFIG_MMU=y
CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
-# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
-# CONFIG_GENERIC_BUST_SPINLOCK is not set
-# CONFIG_GENERIC_ISA_DMA is not set
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_IOMAP=y
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
#
# General setup
#
-CONFIG_NET=y
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
# CONFIG_SYSVIPC is not set
+# 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_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
#
# Loadable module support
#
CONFIG_MODULES=y
+# CONFIG_MODULE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
+# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_KMOD=y
#
# System Type
#
-# CONFIG_ARCH_ADIFCC is not set
-# CONFIG_ARCH_ARCA5K is not set
# CONFIG_ARCH_CLPS7500 is not set
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
@@ -43,161 +66,134 @@ CONFIG_KMOD=y
# CONFIG_ARCH_CAMELOT is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
# CONFIG_ARCH_INTEGRATOR is not set
-# CONFIG_ARCH_IOP310 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=y
+# CONFIG_ARCH_S3C2410 is not set
# CONFIG_ARCH_SHARK is not set
-
-#
-# Archimedes/A5000 Implementations
-#
-
-#
-# Archimedes/A5000 Implementations (select only ONE)
-#
-# CONFIG_ARCH_ARC is not set
-# CONFIG_ARCH_A5K is not set
-
-#
-# Footbridge Implementations
-#
-# CONFIG_ARCH_CATS is not set
-# CONFIG_ARCH_PERSONAL_SERVER is not set
-# CONFIG_ARCH_EBSA285_ADDIN is not set
-# CONFIG_ARCH_EBSA285_HOST is not set
-# CONFIG_ARCH_NETWINDER 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
#
# SA11x0 Implementations
#
# CONFIG_SA1100_ASSABET is not set
-# CONFIG_ASSABET_NEPONSET is not set
-# CONFIG_SA1100_ADSBITSY is not set
-# CONFIG_SA1100_BRUTUS is not set
# CONFIG_SA1100_CERF is not set
+# CONFIG_SA1100_COLLIE is not set
# CONFIG_SA1100_H3100 is not set
# CONFIG_SA1100_H3600 is not set
# CONFIG_SA1100_H3800 is not set
-# CONFIG_SA1100_H3XXX is not set
-# CONFIG_SA1100_EXTENEX1 is not set
-# CONFIG_SA1100_FLEXANET is not set
-# CONFIG_SA1100_FREEBIRD is not set
-# CONFIG_SA1100_GRAPHICSCLIENT is not set
-# CONFIG_SA1100_GRAPHICSMASTER is not set
CONFIG_SA1100_BADGE4=y
# CONFIG_SA1100_JORNADA720 is not set
-# CONFIG_SA1100_HUW_WEBPANEL is not set
-# CONFIG_SA1100_ITSY is not set
+# CONFIG_SA1100_HACKKIT is not set
# CONFIG_SA1100_LART is not set
-# CONFIG_SA1100_NANOENGINE is not set
-# CONFIG_SA1100_OMNIMETER is not set
-# CONFIG_SA1100_PANGOLIN is not set
# CONFIG_SA1100_PLEB is not set
-# CONFIG_SA1100_PT_SYSTEM3 is not set
# CONFIG_SA1100_SHANNON is not set
-# CONFIG_SA1100_SHERMAN is not set
# CONFIG_SA1100_SIMPAD is not set
-# CONFIG_SA1100_PFS168 is not set
-# CONFIG_SA1100_VICTOR is not set
-# CONFIG_SA1100_XP860 is not set
-# CONFIG_SA1100_YOPY is not set
-# CONFIG_SA1100_STORK is not set
-CONFIG_SA1111=y
-CONFIG_FORCE_MAX_ZONEORDER=9
-# CONFIG_SA1100_USB is not set
-# CONFIG_SA1100_USB_NETLINK is not set
-# CONFIG_SA1100_USB_CHAR is not set
-# CONFIG_H3600_SLEEVE is not set
-
-#
-# CLPS711X/EP721X Implementations
-#
-# CONFIG_ARCH_AUTCPU12 is not set
-# CONFIG_ARCH_CDB89712 is not set
-# CONFIG_ARCH_CLEP7312 is not set
-# CONFIG_ARCH_EDB7211 is not set
-# CONFIG_ARCH_P720T is not set
-# CONFIG_ARCH_FORTUNET is not set
-# CONFIG_ARCH_EP7211 is not set
-# CONFIG_ARCH_EP7212 is not set
-# CONFIG_ARCH_ACORN is not set
-# CONFIG_FOOTBRIDGE is not set
-# CONFIG_FOOTBRIDGE_HOST is not set
-# CONFIG_FOOTBRIDGE_ADDIN is not set
-CONFIG_CPU_32=y
-# CONFIG_CPU_26 is not set
+# CONFIG_SA1100_SSP is not set
#
# Processor Type
#
-# CONFIG_CPU_32v3 is not set
-CONFIG_CPU_32v4=y
-# CONFIG_CPU_ARM610 is not set
-# CONFIG_CPU_ARM710 is not set
-# CONFIG_CPU_ARM720T is not set
-# CONFIG_CPU_ARM920T is not set
-# CONFIG_CPU_ARM922T is not set
-# CONFIG_CPU_ARM926T is not set
-# CONFIG_CPU_ARM1020 is not set
-# CONFIG_CPU_SA110 is not set
+CONFIG_CPU_32=y
CONFIG_CPU_SA1100=y
-# CONFIG_XSCALE_PMU is not set
-# CONFIG_ARM_THUMB is not set
-CONFIG_DISCONTIGMEM=y
+CONFIG_CPU_32v4=y
+CONFIG_CPU_ABRT_EV4=y
+CONFIG_CPU_CACHE_V4WB=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_TLB_V4WB=y
+CONFIG_CPU_MINICACHE=y
#
-# General setup
+# Processor Features
+#
+CONFIG_SA1111=y
+CONFIG_DMABOUNCE=y
+CONFIG_FORCE_MAX_ZONEORDER=9
+
+#
+# Bus support
#
-# CONFIG_PCI is not set
CONFIG_ISA=y
-# CONFIG_ISA_DMA is not set
-# CONFIG_FIQ is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_PREEMPT is not set
+CONFIG_DISCONTIGMEM=y
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="init=/linuxrc root=/dev/mtdblock3"
+# CONFIG_XIP_KERNEL is not set
+
+#
+# CPU Frequency scaling
+#
CONFIG_CPU_FREQ=y
-CONFIG_HOTPLUG=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 is not set
+# CONFIG_CPU_FREQ_GOV_USERSPACE is not set
+# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set
#
-# PCMCIA/CardBus support
+# Floating point emulation
#
-CONFIG_PCMCIA=y
-CONFIG_PCMCIA_PROBE=y
-# CONFIG_I82092 is not set
-# CONFIG_I82365 is not set
-# CONFIG_TCIC is not set
-# CONFIG_PCMCIA_CLPS6700 is not set
-CONFIG_PCMCIA_SA1100=y
#
-# At least one math emulation must be selected
+# At least one emulation must be selected
#
CONFIG_FPE_NWFPE=y
-CONFIG_FPE_FASTFPE=m
-CONFIG_KCORE_ELF=y
-# CONFIG_KCORE_AOUT is not set
-CONFIG_BINFMT_AOUT=m
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+
+#
+# Userspace binary formats
+#
CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_AOUT=m
CONFIG_BINFMT_MISC=m
-# CONFIG_PM is not set
-# CONFIG_PREEMPT is not set
-# CONFIG_APM is not set
CONFIG_ARTHUR=m
-CONFIG_CMDLINE="init=/linuxrc root=/dev/mtdblock3"
-# CONFIG_LEDS is not set
-CONFIG_ALIGNMENT_TRAP=y
#
-# Parallel port support
+# Power management options
#
-CONFIG_PARPORT=m
-# CONFIG_PARPORT_PC is not set
-# CONFIG_PARPORT_ARC is not set
-# CONFIG_PARPORT_AMIGA is not set
-# CONFIG_PARPORT_MFC3 is not set
-# CONFIG_PARPORT_ATARI is not set
-# CONFIG_PARPORT_GSC is not set
-# CONFIG_PARPORT_SUNBPP is not set
-# CONFIG_PARPORT_OTHER is not set
-# CONFIG_PARPORT_1284 is not set
+# CONFIG_PM 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
#
# Memory Technology Devices (MTD)
@@ -205,9 +201,10 @@ CONFIG_PARPORT=m
CONFIG_MTD=y
CONFIG_MTD_DEBUG=y
CONFIG_MTD_DEBUG_VERBOSE=0
+# CONFIG_MTD_CONCAT is not set
CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_REDBOOT_PARTS is not set
-# CONFIG_MTD_BOOTLDR_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
# CONFIG_MTD_AFS_PARTS is not set
#
@@ -217,6 +214,7 @@ CONFIG_MTD_CHAR=y
CONFIG_MTD_BLOCK=y
# CONFIG_FTL is not set
# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
#
# RAM/ROM/Flash chip drivers
@@ -229,51 +227,49 @@ CONFIG_MTD_CFI_NOSWAP=y
# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
CONFIG_MTD_CFI_GEOMETRY=y
-# CONFIG_MTD_CFI_B1 is not set
-CONFIG_MTD_CFI_B2=y
-# CONFIG_MTD_CFI_B4 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 is not set
# 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=y
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
-# CONFIG_MTD_AMDSTD is not set
-# CONFIG_MTD_SHARP is not set
-# CONFIG_MTD_JEDEC 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_NORA is not set
# CONFIG_MTD_ARM_INTEGRATOR is not set
-# CONFIG_MTD_CDB89712 is not set
CONFIG_MTD_SA1100=y
-# CONFIG_MTD_2PARTS_IPAQ is not set
-# CONFIG_MTD_DC21285 is not set
-# CONFIG_MTD_IQ80310 is not set
-# CONFIG_MTD_EPXA10DB is not set
-# CONFIG_MTD_PCI is not set
+# CONFIG_MTD_EDB7312 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_DOC1000 is not set
# CONFIG_MTD_DOC2000 is not set
# CONFIG_MTD_DOC2001 is not set
-# CONFIG_MTD_DOCPROBE is not set
+# CONFIG_MTD_DOC2001PLUS is not set
#
# NAND Flash Device Drivers
@@ -281,11 +277,19 @@ CONFIG_MTD_SA1100=y
# CONFIG_MTD_NAND is not set
#
-# Plug and Play configuration
+# Parallel port support
+#
+CONFIG_PARPORT=m
+# CONFIG_PARPORT_PC is not set
+CONFIG_PARPORT_NOT_PC=y
+# CONFIG_PARPORT_ARC is not set
+# CONFIG_PARPORT_GSC is not set
+# CONFIG_PARPORT_1284 is not set
+
+#
+# Plug and Play support
#
# CONFIG_PNP is not set
-# CONFIG_ISAPNP is not set
-# CONFIG_PNPBIOS is not set
#
# Block devices
@@ -293,178 +297,193 @@ CONFIG_MTD_SA1100=y
# CONFIG_BLK_DEV_FD is not set
# CONFIG_BLK_DEV_XD is not set
# CONFIG_PARIDE is not set
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_CISS_SCSI_TAPE is not set
-# CONFIG_BLK_DEV_DAC960 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=m
+# CONFIG_BLK_DEV_UB is not set
# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CDROM_PKTCDVD is not set
#
-# Multi-device support (RAID and LVM)
+# IO Schedulers
#
-# CONFIG_MD is not set
-# CONFIG_BLK_DEV_MD is not set
-# CONFIG_MD_LINEAR is not set
-# CONFIG_MD_RAID0 is not set
-# CONFIG_MD_RAID1 is not set
-# CONFIG_MD_RAID5 is not set
-# CONFIG_MD_MULTIPATH is not set
-# CONFIG_BLK_DEV_LVM is not set
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
#
-# Networking options
+# ATA/ATAPI/MFM/RLL support
#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-# CONFIG_NETLINK_DEV is not set
-# CONFIG_NETFILTER is not set
-# CONFIG_FILTER is not set
-CONFIG_UNIX=y
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-# CONFIG_IP_PNP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_INET_ECN is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_IPV6 is not set
-# CONFIG_KHTTPD is not set
-# CONFIG_ATM is not set
-# CONFIG_VLAN_8021Q is not set
+CONFIG_IDE=m
+CONFIG_BLK_DEV_IDE=m
#
+# Please see Documentation/ide.txt for help/info on IDE drives
#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=m
+# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_BLK_DEV_IDECD=m
+# CONFIG_BLK_DEV_IDETAPE is not set
+CONFIG_BLK_DEV_IDEFLOPPY=m
+CONFIG_BLK_DEV_IDESCSI=m
+# CONFIG_IDE_TASK_IOCTL is not set
+
#
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_LLC is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=m
+# 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
#
-# QoS and/or fair queueing
+# SCSI device support
#
-# CONFIG_NET_SCHED is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
#
-# Network device support
+# SCSI support type (disk, tape, CD-ROM)
#
-CONFIG_NETDEVICES=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=m
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=m
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_CHR_DEV_SG=y
#
-# ARCnet devices
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
#
-# CONFIG_ARCNET is not set
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
#
-# Ethernet (10 or 100Mbit)
+# SCSI Transport Attributes
#
-# CONFIG_NET_ETHERNET is not set
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
#
-# Ethernet (1000 Mbit)
+# SCSI low-level drivers
#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_MYRI_SBUS is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PLIP is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
+# CONFIG_SCSI_7000FASST is not set
+# CONFIG_SCSI_AHA152X is not set
+# CONFIG_SCSI_AHA1542 is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_IN2000 is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DTC3280 is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
+# CONFIG_SCSI_PPA is not set
+# CONFIG_SCSI_IMM is not set
+# CONFIG_SCSI_NCR53C406A is not set
+# CONFIG_SCSI_PAS16 is not set
+# CONFIG_SCSI_PSI240I is not set
+# CONFIG_SCSI_QLOGIC_FAS is not set
+# CONFIG_SCSI_SYM53C416 is not set
+# CONFIG_SCSI_T128 is not set
+# CONFIG_SCSI_U14_34F is not set
+# CONFIG_SCSI_DEBUG is not set
#
-# Wireless LAN (non-hamradio)
+# Multi-device support (RAID and LVM)
#
-CONFIG_NET_RADIO=y
-# CONFIG_STRIP is not set
-# CONFIG_ARLAN is not set
-# CONFIG_AIRONET4500 is not set
-# CONFIG_AIRONET4500_NONCS is not set
-# CONFIG_AIRONET4500_PROC is not set
+# CONFIG_MD is not set
#
-# Wireless ISA/PCI cards support
+# Fusion MPT device support
#
-# CONFIG_WAVELAN is not set
-# CONFIG_AIRO is not set
-CONFIG_HERMES=y
#
-# Wireless Pcmcia/Cardbus cards support
+# IEEE 1394 (FireWire) support
#
-CONFIG_PCMCIA_NETWAVE=m
-CONFIG_PCMCIA_WAVELAN=m
-CONFIG_PCMCIA_HERMES=y
-CONFIG_AIRO_CS=m
-CONFIG_NET_WIRELESS=y
#
-# Token Ring devices
+# I2O device support
#
-# CONFIG_TR is not set
-# CONFIG_NET_FC is not set
-# CONFIG_RCPCI is not set
-# CONFIG_SHAPER is not set
#
-# Wan interfaces
+# Networking support
#
-# CONFIG_WAN is not set
+CONFIG_NET=y
#
-# PCMCIA network device support
+# Networking options
#
-CONFIG_NET_PCMCIA=y
-CONFIG_PCMCIA_3C589=y
-CONFIG_PCMCIA_3C574=m
-CONFIG_PCMCIA_FMVJ18X=m
-CONFIG_PCMCIA_PCNET=y
-CONFIG_PCMCIA_NMCLAN=m
-CONFIG_PCMCIA_SMC91C92=m
-CONFIG_PCMCIA_XIRC2PS=m
-CONFIG_PCMCIA_AXNET=m
-# CONFIG_ARCNET_COM20020_CS is not set
-# CONFIG_PCMCIA_IBMTR is not set
-CONFIG_NET_PCMCIA_RADIO=y
-CONFIG_PCMCIA_RAYCS=m
-# CONFIG_AIRONET4500_CS is not set
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
#
-# Amateur Radio support
+# SCTP Configuration (EXPERIMENTAL)
#
-# CONFIG_HAMRADIO 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
#
-# IrDA (infrared) support
+# 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=y
#
# IrDA protocols
#
CONFIG_IRLAN=y
-# CONFIG_IRNET is not set
CONFIG_IRCOMM=y
CONFIG_IRDA_ULTRA=y
@@ -483,139 +502,106 @@ CONFIG_IRDA_ULTRA=y
# SIR device drivers
#
# CONFIG_IRTTY_SIR is not set
-# CONFIG_IRPORT_SIR is not set
#
# 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_SA1100_FIR=y
+CONFIG_BT=m
+CONFIG_BT_L2CAP=m
+# CONFIG_BT_SCO is not set
+# CONFIG_BT_RFCOMM is not set
+# CONFIG_BT_BNEP is not set
+# CONFIG_BT_HIDP is not set
#
-# ATA/IDE/MFM/RLL support
+# Bluetooth device drivers
#
-CONFIG_IDE=m
+CONFIG_BT_HCIUSB=m
+# CONFIG_BT_HCIUSB_SCO is not set
+CONFIG_BT_HCIUART=m
+# CONFIG_BT_HCIUART_H4 is not set
+# CONFIG_BT_HCIUART_BCSP is not set
+# CONFIG_BT_HCIBCM203X is not set
+# CONFIG_BT_HCIBPA10X is not set
+# CONFIG_BT_HCIBFUSB is not set
+CONFIG_BT_HCIVHCI=m
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
#
-# IDE, ATA and ATAPI Block devices
+# ARCnet devices
#
-CONFIG_BLK_DEV_IDE=m
+# CONFIG_ARCNET is not set
#
-# Please see Documentation/ide.txt for help/info on IDE drives
+# Ethernet (10 or 100Mbit)
#
-# CONFIG_BLK_DEV_HD_IDE is not set
-# CONFIG_BLK_DEV_HD is not set
-CONFIG_BLK_DEV_IDEDISK=m
-# CONFIG_IDEDISK_MULTI_MODE is not set
-# CONFIG_IDEDISK_STROKE is not set
-# CONFIG_BLK_DEV_IDECS is not set
-CONFIG_BLK_DEV_IDECD=m
-# CONFIG_BLK_DEV_IDETAPE is not set
-CONFIG_BLK_DEV_IDEFLOPPY=m
-CONFIG_BLK_DEV_IDESCSI=m
+# CONFIG_NET_ETHERNET is not set
+CONFIG_MII=m
#
-# IDE chipset support/bugfixes
+# Ethernet (1000 Mbit)
#
-# CONFIG_BLK_DEV_CMD640 is not set
-# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
-# CONFIG_BLK_DEV_ISAPNP is not set
-# CONFIG_IDE_CHIPSETS is not set
-# CONFIG_IDEDMA_AUTO is not set
-# CONFIG_BLK_DEV_ATARAID is not set
-# CONFIG_BLK_DEV_ATARAID_PDC is not set
-# CONFIG_BLK_DEV_ATARAID_HPT is not set
#
-# SCSI support
+# Ethernet (10000 Mbit)
#
-CONFIG_SCSI=y
#
-# SCSI support type (disk, tape, CD-ROM)
+# Token Ring devices
#
-CONFIG_BLK_DEV_SD=y
-CONFIG_SD_EXTRA_DEVS=40
-CONFIG_CHR_DEV_ST=m
-# CONFIG_CHR_DEV_OSST is not set
-CONFIG_BLK_DEV_SR=m
-# CONFIG_BLK_DEV_SR_VENDOR is not set
-CONFIG_SR_EXTRA_DEVS=2
-CONFIG_CHR_DEV_SG=y
+# CONFIG_TR is not set
#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+# Wireless LAN (non-hamradio)
#
-# CONFIG_SCSI_MULTI_LUN is not set
-# CONFIG_SCSI_CONSTANTS is not set
-# CONFIG_SCSI_LOGGING is not set
+CONFIG_NET_RADIO=y
#
-# SCSI low-level drivers
+# Obsolete Wireless cards support (pre-802.11)
#
-# CONFIG_SCSI_7000FASST is not set
-# CONFIG_SCSI_ACARD is not set
-# CONFIG_SCSI_AHA152X is not set
-# CONFIG_SCSI_AHA1542 is not set
-# CONFIG_SCSI_AHA1740 is not set
-# CONFIG_SCSI_AIC7XXX is not set
-# CONFIG_SCSI_AIC7XXX_OLD is not set
-# CONFIG_SCSI_DPT_I2O is not set
-# CONFIG_SCSI_ADVANSYS is not set
-# CONFIG_SCSI_IN2000 is not set
-# CONFIG_SCSI_AM53C974 is not set
-# CONFIG_SCSI_MEGARAID is not set
-# CONFIG_SCSI_BUSLOGIC is not set
-# CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_DTC3280 is not set
-# CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_EATA_DMA is not set
-# CONFIG_SCSI_EATA_PIO is not set
-# CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
-# CONFIG_SCSI_GENERIC_NCR5380 is not set
-# CONFIG_SCSI_INITIO is not set
-# CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_PPA is not set
-# CONFIG_SCSI_IMM is not set
-# CONFIG_SCSI_NCR53C406A is not set
-# CONFIG_SCSI_NCR53C7xx is not set
-# CONFIG_SCSI_PAS16 is not set
-# CONFIG_SCSI_PCI2000 is not set
-# CONFIG_SCSI_PCI2220I is not set
-# CONFIG_SCSI_PSI240I is not set
-# CONFIG_SCSI_QLOGIC_FAS is not set
-# CONFIG_SCSI_SIM710 is not set
-# CONFIG_SCSI_SYM53C416 is not set
-# CONFIG_SCSI_T128 is not set
-# CONFIG_SCSI_U14_34F is not set
-# CONFIG_SCSI_DEBUG is not set
+# CONFIG_STRIP is not set
+# CONFIG_ARLAN is not set
+# CONFIG_WAVELAN is not set
#
-# PCMCIA SCSI adapter support
+# Wireless 802.11b ISA/PCI cards support
#
-# CONFIG_SCSI_PCMCIA is not set
+# CONFIG_ATMEL is not set
+CONFIG_NET_WIRELESS=y
#
-# I2O device support
+# Wan interfaces
#
-# CONFIG_I2O is not set
-# CONFIG_I2O_BLOCK is not set
-# CONFIG_I2O_LAN is not set
-# CONFIG_I2O_SCSI is not set
-# CONFIG_I2O_PROC is not set
+# CONFIG_WAN is not set
+# CONFIG_PLIP is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
#
# ISDN subsystem
@@ -626,129 +612,152 @@ CONFIG_CHR_DEV_SG=y
# Input device support
#
# CONFIG_INPUT is not set
-# CONFIG_INPUT_KEYBDEV is not set
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_EVDEV is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
# CONFIG_GAMEPORT is not set
CONFIG_SOUND_GAMEPORT=y
-# CONFIG_GAMEPORT_NS558 is not set
-# CONFIG_GAMEPORT_L4 is not set
-# CONFIG_INPUT_EMU10K1 is not set
-# CONFIG_GAMEPORT_PCIGAME is not set
-# CONFIG_GAMEPORT_FM801 is not set
-# CONFIG_GAMEPORT_CS461x is not set
-# CONFIG_SERIO is not set
-# CONFIG_SERIO_SERPORT is not set
#
# Character devices
#
# CONFIG_VT is not set
-# CONFIG_SERIAL is not set
-# CONFIG_SERIAL_EXTENDED is not set
# CONFIG_SERIAL_NONSTANDARD is not set
#
# Serial drivers
#
-# CONFIG_SERIAL_AMBA is not set
-# CONFIG_SERIAL_AMBA_CONSOLE is not set
-# CONFIG_SERIAL_CLPS711X is not set
-# CONFIG_SERIAL_CLPS711X_CONSOLE is not set
-# CONFIG_SERIAL_21285 is not set
-# CONFIG_SERIAL_21285_OLD is not set
-# CONFIG_SERIAL_21285_CONSOLE is not set
-# CONFIG_SERIAL_UART00 is not set
-# CONFIG_SERIAL_UART00_CONSOLE is not set
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
CONFIG_SERIAL_SA1100=y
CONFIG_SERIAL_SA1100_CONSOLE=y
-CONFIG_SA1100_DEFAULT_BAUDRATE=115200
-# CONFIG_SERIAL_8250 is not set
-# CONFIG_SERIAL_8250_CONSOLE is not set
-# CONFIG_ATOMWIDE_SERIAL is not set
-# CONFIG_DUALSP_SERIAL is not set
-# CONFIG_SERIAL_8250_EXTENDED is not set
-# CONFIG_SERIAL_8250_MANY_PORTS is not set
-# CONFIG_SERIAL_8250_SHARE_IRQ is not set
-# CONFIG_SERIAL_8250_DETECT_IRQ is not set
-# CONFIG_SERIAL_8250_MULTIPORT is not set
-# CONFIG_SERIAL_8250_RSA is not set
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_PRINTER is not set
# CONFIG_PPDEV is not set
+# CONFIG_TIPAR is not set
#
-# I2C support
+# IPMI
#
-CONFIG_I2C=m
-CONFIG_I2C_ALGOBIT=m
-# CONFIG_I2C_BIT_SA1100_GPIO is not set
-CONFIG_I2C_ALGOPCF=m
-CONFIG_I2C_ELEKTOR=m
-CONFIG_I2C_CHARDEV=m
-CONFIG_I2C_PROC=m
+# CONFIG_IPMI_HANDLER is not set
#
-# L3 serial bus support
+# Watchdog Cards
#
-CONFIG_L3=y
-# CONFIG_L3_ALGOBIT is not set
-# CONFIG_L3_BIT_SA1100_GPIO is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
#
-# Other L3 adapters
+# Watchdog Device Drivers
#
-CONFIG_L3_SA1111=y
-# CONFIG_BIT_SA1100_GPIO is not set
+CONFIG_SOFT_WATCHDOG=m
+CONFIG_SA1100_WATCHDOG=m
#
-# Mice
+# ISA-based Watchdog Cards
#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_MOUSE is not set
-# CONFIG_QIC02_TAPE is not set
+# CONFIG_PCWATCHDOG is not set
+# CONFIG_MIXCOMWD is not set
+# CONFIG_WDT is not set
#
-# Watchdog Cards
+# USB-based Watchdog Cards
#
-CONFIG_WATCHDOG=y
-# CONFIG_WATCHDOG_NOWAYOUT is not set
-CONFIG_SOFT_WATCHDOG=m
-# CONFIG_WDT is not set
-# CONFIG_WDTPCI is not set
-# CONFIG_PCWATCHDOG is not set
-# CONFIG_ACQUIRE_WDT is not set
-# CONFIG_ADVANTECH_WDT is not set
-# CONFIG_21285_WATCHDOG is not set
-# CONFIG_977_WATCHDOG is not set
-CONFIG_SA1100_WATCHDOG=m
-# CONFIG_EUROTECH_WDT is not set
-# CONFIG_IB700_WDT is not set
-# CONFIG_MIXCOMWD is not set
-# CONFIG_60XX_WDT is not set
-# CONFIG_W83877F_WDT is not set
-# CONFIG_MACHZ_WDT is not set
-# CONFIG_INTEL_RNG is not set
+# CONFIG_USBPCWATCHDOG is not set
# CONFIG_NVRAM is not set
CONFIG_RTC=m
-CONFIG_SA1100_RTC=m
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
#
# Ftape, the floppy tape device driver
#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
#
-# PCMCIA character devices
+# I2C support
+#
+CONFIG_I2C=m
+CONFIG_I2C_CHARDEV=m
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=m
+CONFIG_I2C_ALGOPCF=m
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+CONFIG_I2C_ELEKTOR=m
+# CONFIG_I2C_ISA is not set
+# CONFIG_I2C_PARPORT is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Hardware Sensors Chip support
+#
+# CONFIG_I2C_SENSOR 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_ASB100 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+
+#
+# Other I2C Chip support
+#
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# Misc devices
#
#
@@ -759,27 +768,18 @@ CONFIG_VIDEO_DEV=y
#
# Video For Linux
#
-CONFIG_VIDEO_PROC_FS=y
-# CONFIG_I2C_PARPORT is not set
#
# Video Adapters
#
-# CONFIG_VIDEO_BT848 is not set
# CONFIG_VIDEO_PMS is not set
# CONFIG_VIDEO_BWQCAM is not set
# CONFIG_VIDEO_CQCAM is not set
# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_SAA5246A is not set
# CONFIG_VIDEO_SAA5249 is not set
# CONFIG_TUNER_3036 is not set
-# CONFIG_VIDEO_STRADIS is not set
-# CONFIG_VIDEO_ZORAN is not set
-# CONFIG_VIDEO_ZORAN_BUZ is not set
-# CONFIG_VIDEO_ZORAN_DC10 is not set
-# CONFIG_VIDEO_ZORAN_LML33 is not set
-# CONFIG_VIDEO_ZR36120 is not set
-# CONFIG_VIDEO_MEYE is not set
-# CONFIG_VIDEO_CYBERPRO is not set
+# CONFIG_VIDEO_OVCAMCHIP is not set
#
# Radio Adapters
@@ -789,215 +789,54 @@ CONFIG_VIDEO_PROC_FS=y
# CONFIG_RADIO_RTRACK2 is not set
# CONFIG_RADIO_AZTECH is not set
# CONFIG_RADIO_GEMTEK is not set
-# CONFIG_RADIO_GEMTEK_PCI is not set
-# CONFIG_RADIO_MAXIRADIO is not set
# CONFIG_RADIO_MAESTRO is not set
-# CONFIG_RADIO_MIROPCM20 is not set
-# CONFIG_RADIO_MIROPCM20_RDS is not set
# CONFIG_RADIO_SF16FMI is not set
+# CONFIG_RADIO_SF16FMR2 is not set
# CONFIG_RADIO_TERRATEC is not set
# CONFIG_RADIO_TRUST is not set
# CONFIG_RADIO_TYPHOON is not set
# CONFIG_RADIO_ZOLTRIX is not set
#
-# File systems
+# Digital Video Broadcasting Devices
#
-# CONFIG_QUOTA is not set
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_REISERFS_CHECK is not set
-# CONFIG_REISERFS_PROC_INFO is not set
-# CONFIG_ADFS_FS is not set
-# CONFIG_ADFS_FS_RW is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_BFS_FS is not set
-CONFIG_EXT3_FS=m
-CONFIG_JBD=m
-# CONFIG_JBD_DEBUG is not set
-CONFIG_FAT_FS=y
-CONFIG_MSDOS_FS=y
-# CONFIG_UMSDOS_FS is not set
-CONFIG_VFAT_FS=m
-# CONFIG_EFS_FS is not set
-# CONFIG_JFFS_FS is not set
-CONFIG_JFFS2_FS=y
-CONFIG_JFFS2_FS_DEBUG=0
-CONFIG_CRAMFS=m
-CONFIG_TMPFS=y
-CONFIG_RAMFS=y
-# CONFIG_ISO9660_FS is not set
-# CONFIG_JOLIET is not set
-# CONFIG_ZISOFS is not set
-CONFIG_MINIX_FS=m
-# CONFIG_VXFS_FS is not set
-# CONFIG_NTFS_FS is not set
-# CONFIG_NTFS_DEBUG is not set
-# CONFIG_NTFS_RW is not set
-# CONFIG_HPFS_FS is not set
-CONFIG_PROC_FS=y
-CONFIG_DEVFS_FS=y
-CONFIG_DEVFS_MOUNT=y
-# CONFIG_DEVFS_DEBUG is not set
-# CONFIG_DEVPTS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_QNX4FS_RW is not set
-# CONFIG_ROMFS_FS is not set
-CONFIG_EXT2_FS=m
-# CONFIG_SYSV_FS is not set
-# CONFIG_UDF_FS is not set
-# CONFIG_UDF_RW is not set
-# CONFIG_UFS_FS is not set
-# CONFIG_UFS_FS_WRITE is not set
+# CONFIG_DVB is not set
#
-# Network File Systems
+# Graphics support
#
-# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
-CONFIG_NFS_FS=m
-CONFIG_NFS_V3=y
-# CONFIG_ROOT_NFS is not set
-# CONFIG_NFSD is not set
-# CONFIG_NFSD_V3 is not set
-CONFIG_SUNRPC=m
-CONFIG_LOCKD=m
-CONFIG_LOCKD_V4=y
-CONFIG_SMB_FS=m
-# CONFIG_SMB_NLS_DEFAULT is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_NCPFS_PACKET_SIGNING is not set
-# CONFIG_NCPFS_IOCTL_LOCKING is not set
-# CONFIG_NCPFS_STRONG is not set
-# CONFIG_NCPFS_NFS_NS is not set
-# CONFIG_NCPFS_OS2_NS is not set
-# CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_NLS is not set
-# CONFIG_NCPFS_EXTRAS is not set
-# CONFIG_ZISOFS_FS is not set
+# CONFIG_FB is not set
#
-# Partition Types
-#
-CONFIG_PARTITION_ADVANCED=y
-# CONFIG_ACORN_PARTITION is not set
-# CONFIG_OSF_PARTITION is not set
-# CONFIG_AMIGA_PARTITION is not set
-# CONFIG_ATARI_PARTITION is not set
-# CONFIG_MAC_PARTITION is not set
-CONFIG_MSDOS_PARTITION=y
-# CONFIG_BSD_DISKLABEL is not set
-# CONFIG_MINIX_SUBPARTITION is not set
-# CONFIG_SOLARIS_X86_PARTITION is not set
-# CONFIG_UNIXWARE_DISKLABEL is not set
-# CONFIG_LDM_PARTITION is not set
-# CONFIG_SGI_PARTITION is not set
-# CONFIG_ULTRIX_PARTITION is not set
-# CONFIG_SUN_PARTITION is not set
-CONFIG_SMB_NLS=y
-CONFIG_NLS=y
-
-#
-# Native Language Support
+# Sound
#
-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_1251 is not set
-# CONFIG_NLS_ISO8859_1 is not set
-# CONFIG_NLS_ISO8859_2 is not set
-# CONFIG_NLS_ISO8859_3 is not set
-# CONFIG_NLS_ISO8859_4 is not set
-# CONFIG_NLS_ISO8859_5 is not set
-# CONFIG_NLS_ISO8859_6 is not set
-# CONFIG_NLS_ISO8859_7 is not set
-# CONFIG_NLS_ISO8859_9 is not set
-# CONFIG_NLS_ISO8859_13 is not set
-# CONFIG_NLS_ISO8859_14 is not set
-# CONFIG_NLS_ISO8859_15 is not set
-# CONFIG_NLS_KOI8_R is not set
-# CONFIG_NLS_KOI8_U is not set
-# CONFIG_NLS_UTF8 is not set
+CONFIG_SOUND=y
#
-# Sound
+# Advanced Linux Sound Architecture
#
-CONFIG_SOUND=y
+# CONFIG_SND is not set
#
# Open Sound System
#
CONFIG_SOUND_PRIME=y
# CONFIG_SOUND_BT878 is not set
-# CONFIG_SOUND_CMPCI is not set
-# CONFIG_SOUND_EMU10K1 is not set
-# CONFIG_MIDI_EMU10K1 is not set
# CONFIG_SOUND_FUSION is not set
# CONFIG_SOUND_CS4281 is not set
-# CONFIG_SOUND_ES1370 is not set
-# CONFIG_SOUND_ES1371 is not set
-# CONFIG_SOUND_ESSSOLO1 is not set
-# CONFIG_SOUND_MAESTRO is not set
-# CONFIG_SOUND_MAESTRO3 is not set
-# CONFIG_SOUND_ICH is not set
-# CONFIG_SOUND_RME96XX is not set
# CONFIG_SOUND_SONICVIBES is not set
# CONFIG_SOUND_TRIDENT is not set
# CONFIG_SOUND_MSNDCLAS is not set
# CONFIG_SOUND_MSNDPIN is not set
-# CONFIG_SOUND_VIA82CXXX is not set
-# CONFIG_MIDI_VIA82CXXX is not set
-CONFIG_SOUND_SA1100=y
-CONFIG_SOUND_UDA1341=y
-# CONFIG_SOUND_ASSABET_UDA1341 is not set
-# CONFIG_SOUND_H3600_UDA1341 is not set
-# CONFIG_SOUND_PANGOLIN_UDA1341 is not set
-CONFIG_SOUND_SA1111_UDA1341=y
-# CONFIG_SOUND_STORK_UDA1341 is not set
-# CONFIG_SOUND_SA1100SSP is not set
-# CONFIG_SOUND_STORK_AC97 is not set
# CONFIG_SOUND_OSS is not set
-# CONFIG_SOUND_WAVEARTIST is not set
# CONFIG_SOUND_TVMIXER is not set
-
-#
-# Advanced Linux Sound Architecture
-#
-# CONFIG_SND is not set
-
-#
-# Multimedia Capabilities Port drivers
-#
-CONFIG_MCP=y
-CONFIG_MCP_SA1100=y
-# CONFIG_MCP_UCB1200 is not set
-# CONFIG_MCP_UCB1200_AUDIO is not set
-# CONFIG_MCP_UCB1200_TS is not set
+# CONFIG_SOUND_AD1980 is not set
#
# USB support
#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
CONFIG_USB=y
CONFIG_USB_DEBUG=y
@@ -1006,75 +845,106 @@ CONFIG_USB_DEBUG=y
#
CONFIG_USB_DEVICEFS=y
# CONFIG_USB_BANDWIDTH is not set
-# CONFIG_USB_LONG_TIMEOUT is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
#
# USB Host Controller Drivers
#
-# CONFIG_USB_EHCI_HCD is not set
# CONFIG_USB_OHCI_HCD is not set
-# CONFIG_USB_UHCI is not set
-# CONFIG_USB_UHCI_ALT is not set
-# CONFIG_USB_OHCI is not set
-CONFIG_USB_OHCI_SA1111=y
+# CONFIG_USB_SL811_HCD is not set
#
# USB Device Class drivers
#
CONFIG_USB_AUDIO=y
-CONFIG_USB_BLUETOOTH=m
+
+#
+# USB Bluetooth TTY can only be used with disabled Bluetooth subsystem
+#
+# CONFIG_USB_MIDI is not set
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
CONFIG_USB_STORAGE=y
CONFIG_USB_STORAGE_DEBUG=y
+# CONFIG_USB_STORAGE_RW_DETECT is not set
# CONFIG_USB_STORAGE_DATAFAB is not set
# CONFIG_USB_STORAGE_FREECOM is not set
# CONFIG_USB_STORAGE_ISD200 is not set
# CONFIG_USB_STORAGE_DPCM is not set
-# CONFIG_USB_STORAGE_HP8200e is not set
+# CONFIG_USB_STORAGE_USBAT is not set
# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
# CONFIG_USB_STORAGE_JUMPSHOT is not set
-CONFIG_USB_ACM=m
-CONFIG_USB_PRINTER=m
#
-# USB Human Interface Devices (HID)
+# USB Input Devices
#
+# CONFIG_USB_HID is not set
#
-# Input core support is needed for USB HID
+# USB HID Boot Protocol drivers
#
#
# USB Imaging devices
#
-CONFIG_USB_DC2XX=m
CONFIG_USB_MDC800=m
-CONFIG_USB_SCANNER=m
CONFIG_USB_MICROTEK=m
-CONFIG_USB_HPUSBSCSI=m
#
# USB Multimedia devices
#
+CONFIG_USB_DABUSB=m
+CONFIG_USB_VICAM=m
+CONFIG_USB_DSBR=m
CONFIG_USB_IBMCAM=m
+CONFIG_USB_KONICAWC=m
CONFIG_USB_OV511=m
-CONFIG_USB_PWC=m
CONFIG_USB_SE401=m
+# CONFIG_USB_SN9C102 is not set
# CONFIG_USB_STV680 is not set
-CONFIG_USB_VICAM=m
-CONFIG_USB_DSBR=m
-CONFIG_USB_DABUSB=m
-CONFIG_USB_KONICAWC=m
+CONFIG_USB_PWC=m
#
-# USB Network adaptors
+# USB Network Adapters
#
-CONFIG_USB_PEGASUS=m
-CONFIG_USB_KAWETH=m
CONFIG_USB_CATC=m
-CONFIG_USB_CDCETHER=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+# CONFIG_USB_RTL8150 is not set
CONFIG_USB_USBNET=m
#
+# USB Host-to-Host Cables
+#
+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_ZD1201 is not set
+CONFIG_USB_MON=y
+
+#
# USB port drivers
#
CONFIG_USB_USS720=m
@@ -1087,14 +957,19 @@ CONFIG_USB_SERIAL_GENERIC=y
CONFIG_USB_SERIAL_BELKIN=m
CONFIG_USB_SERIAL_WHITEHEAT=m
CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+# CONFIG_USB_SERIAL_CYPRESS_M8 is not set
CONFIG_USB_SERIAL_EMPEG=m
CONFIG_USB_SERIAL_FTDI_SIO=m
CONFIG_USB_SERIAL_VISOR=m
# CONFIG_USB_SERIAL_IPAQ is not set
CONFIG_USB_SERIAL_IR=m
CONFIG_USB_SERIAL_EDGEPORT=m
+# 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 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
@@ -1102,53 +977,264 @@ CONFIG_USB_SERIAL_KEYSPAN=m
# 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_MCT_U232=m
+# CONFIG_USB_SERIAL_KEYSPAN_USA49WLC is not set
# CONFIG_USB_SERIAL_KLSI is not set
+# CONFIG_USB_SERIAL_KOBIL_SCT is not set
+CONFIG_USB_SERIAL_MCT_U232=m
CONFIG_USB_SERIAL_PL2303=m
+# CONFIG_USB_SERIAL_SAFE is not set
+# CONFIG_USB_SERIAL_TI is not set
CONFIG_USB_SERIAL_CYBERJACK=m
CONFIG_USB_SERIAL_XIRCOM=m
CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_EZUSB=y
#
# USB Miscellaneous drivers
#
-CONFIG_USB_RIO500=m
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
# CONFIG_USB_AUERSWALD is not set
+CONFIG_USB_RIO500=m
+# 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_TEST is not set
#
-# Bluetooth support
+# USB ATM/DSL drivers
#
-CONFIG_BT=m
-CONFIG_BT_L2CAP=m
#
-# Bluetooth device drivers
+# USB Gadget Support
#
-CONFIG_BT_HCIUSB=m
-CONFIG_BT_HCIUART=m
-CONFIG_BT_HCIVHCI=m
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=m
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=m
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=m
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
+# CONFIG_XFS_FS is not set
+CONFIG_MINIX_FS=m
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+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_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=y
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_JFFS2_FS_NAND is not set
+# CONFIG_JFFS2_FS_NOR_ECC is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_CRAMFS=m
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_SUNRPC=m
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
#
# Kernel hacking
#
-CONFIG_FRAME_POINTER=y
-CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_INFO=y
+# CONFIG_PRINTK_TIME is not set
CONFIG_DEBUG_KERNEL=y
-# CONFIG_DEBUG_SLAB is not set
CONFIG_MAGIC_SYSRQ=y
+CONFIG_LOG_BUF_SHIFT=14
+# 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=y
+CONFIG_DEBUG_USER=y
# CONFIG_DEBUG_WAITQ is not set
-CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_DEBUG_ERRORS=y
CONFIG_DEBUG_LL=y
-# CONFIG_DEBUG_DC21285_PORT is not set
-# CONFIG_DEBUG_CLPS711X_UART2 is not set
+# 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_CRC32 is not set
+CONFIG_CRC_CCITT=y
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/arm/configs/bast_defconfig b/arch/arm/configs/bast_defconfig
index dc986caceb193..2d985e9611cdc 100644
--- a/arch/arm/configs/bast_defconfig
+++ b/arch/arm/configs/bast_defconfig
@@ -1,12 +1,13 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.10-rc2
-# Mon Nov 15 15:32:48 2004
+# Linux kernel version: 2.6.12-rc1-bk2
+# Sun Mar 27 02:24:16 2005
#
CONFIG_ARM=y
CONFIG_MMU=y
CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_GENERIC_IOMAP=y
#
@@ -27,7 +28,6 @@ CONFIG_SYSVIPC=y
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=16
# CONFIG_HOTPLUG is not set
CONFIG_KOBJECT_UEVENT=y
# CONFIG_IKCONFIG is not set
@@ -35,6 +35,7 @@ CONFIG_KOBJECT_UEVENT=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
@@ -44,6 +45,7 @@ CONFIG_CC_ALIGN_LABELS=0
CONFIG_CC_ALIGN_LOOPS=0
CONFIG_CC_ALIGN_JUMPS=0
# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
#
# Loadable module support
@@ -85,12 +87,21 @@ CONFIG_ARCH_S3C2410=y
#
CONFIG_ARCH_BAST=y
# CONFIG_ARCH_H1940 is not set
+# CONFIG_MACH_N30 is not set
# CONFIG_ARCH_SMDK2410 is not set
+# CONFIG_ARCH_S3C2440 is not set
CONFIG_MACH_VR1000=y
# CONFIG_MACH_RX3715 is not set
+# CONFIG_MACH_OTOM is not set
+# CONFIG_MACH_NEXCODER_2440 is not set
CONFIG_CPU_S3C2410=y
#
+# S3C2410 Boot
+#
+# CONFIG_S3C2410_BOOT_WATCHDOG is not set
+
+#
# S3C2410 Setup
#
CONFIG_S3C2410_DMA=y
@@ -120,53 +131,74 @@ CONFIG_CPU_TLB_V4WBI=y
# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
#
-# General setup
+# Bus support
+#
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_PREEMPT is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
#
-# CONFIG_ZBOOT_ROM is not set
CONFIG_ZBOOT_ROM_TEXT=0x0
CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="root=/dev/hda1 ro init=/bin/bash console=ttySAC0"
# CONFIG_XIP_KERNEL is not set
#
-# At least one math emulation must be selected
+# 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=y
# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
#
-# Generic Driver Options
+# Power management options
#
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_DEBUG_DRIVER is not set
CONFIG_PM=y
-# CONFIG_PREEMPT is not set
CONFIG_APM=y
-# CONFIG_ARTHUR is not set
-CONFIG_CMDLINE="root=/dev/hda1 ro init=/bin/bash console=ttySAC0"
-CONFIG_ALIGNMENT_TRAP=y
#
-# Parallel port support
+# Device Drivers
#
-CONFIG_PARPORT=y
-# CONFIG_PARPORT_PC is not set
-# CONFIG_PARPORT_ARC is not set
-CONFIG_PARPORT_OTHER=y
-CONFIG_PARPORT_1284=y
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
#
# Memory Technology Devices (MTD)
#
CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
-CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
CONFIG_MTD_REDBOOT_PARTS=y
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
CONFIG_MTD_CMDLINE_PARTS=y
@@ -206,6 +238,7 @@ CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
# CONFIG_MTD_OBSOLETE_CHIPS is not set
+# CONFIG_MTD_XIP is not set
#
# Mapping drivers for chip access
@@ -225,6 +258,7 @@ CONFIG_MTD_BAST_MAXSIZE=4
# 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
@@ -243,6 +277,16 @@ CONFIG_MTD_NAND_S3C2410=y
# CONFIG_MTD_NAND_S3C2410_DEBUG is not set
# CONFIG_MTD_NAND_S3C2410_HWECC is not set
# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+
+#
+# Parallel port support
+#
+CONFIG_PARPORT=y
+# CONFIG_PARPORT_PC is not set
+# CONFIG_PARPORT_ARC is not set
+# CONFIG_PARPORT_GSC is not set
+CONFIG_PARPORT_1284=y
#
# Plug and Play support
@@ -253,10 +297,12 @@ CONFIG_MTD_NAND_S3C2410=y
#
# CONFIG_BLK_DEV_FD is not set
# CONFIG_PARIDE is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
CONFIG_BLK_DEV_NBD=m
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=""
@@ -269,6 +315,39 @@ CONFIG_IOSCHED_NOOP=y
CONFIG_IOSCHED_AS=y
CONFIG_IOSCHED_DEADLINE=y
CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_BLK_DEV_IDECD=y
+CONFIG_BLK_DEV_IDETAPE=m
+CONFIG_BLK_DEV_IDEFLOPPY=m
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+# CONFIG_IDE_ARM is not set
+CONFIG_BLK_DEV_IDE_BAST=y
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
#
# Multi-device support (RAID and LVM)
@@ -276,6 +355,19 @@ CONFIG_IOSCHED_CFQ=y
# CONFIG_MD is not set
#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+
+#
# Networking support
#
CONFIG_NET=y
@@ -380,51 +472,6 @@ CONFIG_NET_ETHERNET=y
# CONFIG_NETCONSOLE 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=y
-CONFIG_BLK_DEV_IDETAPE=m
-CONFIG_BLK_DEV_IDEFLOPPY=m
-# CONFIG_IDE_TASK_IOCTL is not set
-
-#
-# IDE chipset support/bugfixes
-#
-CONFIG_IDE_GENERIC=y
-# CONFIG_IDE_ARM is not set
-CONFIG_BLK_DEV_IDE_BAST=y
-# CONFIG_BLK_DEV_IDEDMA is not set
-# CONFIG_IDEDMA_AUTO is not set
-# CONFIG_BLK_DEV_HD is not set
-
-#
-# SCSI device support
-#
-# CONFIG_SCSI is not set
-
-#
-# Fusion MPT device support
-#
-
-#
-# IEEE 1394 (FireWire) support
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-
-#
# ISDN subsystem
#
# CONFIG_ISDN is not set
@@ -447,17 +494,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_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PARKBD is not set
-# CONFIG_SERIO_RAW is not set
-
-#
# Input Device Drivers
#
CONFIG_INPUT_KEYBOARD=y
@@ -475,6 +511,17 @@ CONFIG_MOUSE_PS2=y
# CONFIG_INPUT_MISC is not set
#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_PARKBD is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
+#
# Character devices
#
CONFIG_VT=y
@@ -485,9 +532,9 @@ CONFIG_SERIAL_NONSTANDARD=y
# CONFIG_ROCKETPORT is not set
# CONFIG_CYCLADES is not set
# CONFIG_DIGIEPCA is not set
-# CONFIG_DIGI is not set
# CONFIG_MOXA_INTELLIO is not set
# CONFIG_MOXA_SMARTIO is not set
+# CONFIG_ISI is not set
# CONFIG_SYNCLINKMP is not set
# CONFIG_N_HDLC is not set
# CONFIG_RISCOM8 is not set
@@ -554,6 +601,11 @@ CONFIG_S3C2410_RTC=y
# CONFIG_RAW_DRIVER is not set
#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
# I2C support
#
CONFIG_I2C=y
@@ -582,11 +634,14 @@ CONFIG_I2C_S3C2410=y
CONFIG_I2C_SENSOR=m
# CONFIG_SENSORS_ADM1021 is not set
# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ASB100 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
# CONFIG_SENSORS_IT87 is not set
# CONFIG_SENSORS_LM63 is not set
CONFIG_SENSORS_LM75=m
@@ -599,6 +654,7 @@ CONFIG_SENSORS_LM85=m
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
# CONFIG_SENSORS_SMSC47M1 is not set
# CONFIG_SENSORS_W83781D is not set
# CONFIG_SENSORS_W83L785TS is not set
@@ -617,6 +673,10 @@ CONFIG_SENSORS_EEPROM=m
# CONFIG_I2C_DEBUG_CHIP is not set
#
+# Misc devices
+#
+
+#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -627,6 +687,53 @@ CONFIG_SENSORS_EEPROM=m
# CONFIG_DVB is not set
#
+# Graphics support
+#
+CONFIG_FB=y
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_SOFT_CURSOR is not set
+CONFIG_FB_MODE_HELPERS=y
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE is not set
+
+#
+# Logo configuration
+#
+# CONFIG_LOGO is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -640,6 +747,10 @@ CONFIG_JBD=y
CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
# CONFIG_XFS_FS is not set
# CONFIG_MINIX_FS is not set
CONFIG_ROMFS_FS=y
@@ -692,6 +803,7 @@ CONFIG_JFFS_FS_VERBOSE=0
CONFIG_JFFS2_FS=y
CONFIG_JFFS2_FS_DEBUG=0
# CONFIG_JFFS2_FS_NAND is not set
+# CONFIG_JFFS2_FS_NOR_ECC is not set
# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
CONFIG_JFFS2_ZLIB=y
CONFIG_JFFS2_RTIME=y
@@ -713,7 +825,6 @@ CONFIG_NFS_FS=y
# CONFIG_NFSD is not set
CONFIG_ROOT_NFS=y
CONFIG_LOCKD=y
-# CONFIG_EXPORTFS is not set
CONFIG_SUNRPC=y
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
@@ -793,62 +904,20 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_PROFILING is not set
#
-# Graphics support
-#
-CONFIG_FB=y
-CONFIG_FB_MODE_HELPERS=y
-# CONFIG_FB_TILEBLITTING is not set
-# CONFIG_FB_VIRTUAL is not set
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-# CONFIG_FRAMEBUFFER_CONSOLE is not set
-
-#
-# Logo configuration
-#
-# CONFIG_LOGO is not set
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# Misc devices
-#
-
-#
-# USB support
-#
-# CONFIG_USB is not set
-CONFIG_USB_ARCH_HAS_HCD=y
-# CONFIG_USB_ARCH_HAS_OHCI is not set
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
-# CONFIG_MMC 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=16
# CONFIG_SCHEDSTATS is not set
# CONFIG_DEBUG_SLAB is not set
# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
# CONFIG_DEBUG_KOBJECT is not set
-# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_FS is not set
CONFIG_FRAME_POINTER=y
CONFIG_DEBUG_USER=y
# CONFIG_DEBUG_WAITQ is not set
@@ -870,6 +939,10 @@ CONFIG_DEBUG_S3C2410_UART=0
# CONFIG_CRYPTO is not set
#
+# Hardware crypto devices
+#
+
+#
# Library routines
#
# CONFIG_CRC_CCITT is not set
diff --git a/arch/arm/configs/cerfcube_defconfig b/arch/arm/configs/cerfcube_defconfig
index 3f64361abf766..d8fe0f40408f6 100644
--- a/arch/arm/configs/cerfcube_defconfig
+++ b/arch/arm/configs/cerfcube_defconfig
@@ -1,35 +1,51 @@
#
# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.12-rc1-bk2
+# Sun Mar 27 14:19:40 2005
#
CONFIG_ARM=y
CONFIG_MMU=y
CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_IOMAP=y
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
CONFIG_CLEAN_COMPILE=y
-CONFIG_STANDALONE=y
CONFIG_BROKEN_ON_SMP=y
#
# General setup
#
+CONFIG_LOCALVERSION=""
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
CONFIG_SYSCTL=y
-CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_AUDIT is not set
+CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
# CONFIG_IKCONFIG 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_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
#
# Loadable module support
@@ -39,94 +55,54 @@ 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
#
# System Type
#
-# CONFIG_ARCH_ADIFCC is not set
# CONFIG_ARCH_CLPS7500 is not set
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
-# CONFIG_ARCH_PXA 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=y
+# CONFIG_ARCH_S3C2410 is not set
# CONFIG_ARCH_SHARK is not set
-
-#
-# CLPS711X/EP721X Implementations
-#
-
-#
-# Epxa10db
-#
-
-#
-# Footbridge Implementations
-#
-
-#
-# IOP3xx Implementation Options
-#
-# CONFIG_ARCH_IOP310 is not set
-# CONFIG_ARCH_IOP321 is not set
-
-#
-# IOP3xx Chipset Features
-#
-
-#
-# Intel PXA250/210 Implementations
-#
+# 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
#
# SA11x0 Implementations
#
# CONFIG_SA1100_ASSABET is not set
-# CONFIG_SA1100_ADSBITSY is not set
-# CONFIG_SA1100_BRUTUS is not set
CONFIG_SA1100_CERF=y
# CONFIG_SA1100_CERF_FLASH_8MB is not set
CONFIG_SA1100_CERF_FLASH_16MB=y
# CONFIG_SA1100_CERF_FLASH_32MB is not set
-# CONFIG_SA1100_CERF_CPLD is not set
+# CONFIG_SA1100_COLLIE is not set
# CONFIG_SA1100_H3100 is not set
# CONFIG_SA1100_H3600 is not set
# CONFIG_SA1100_H3800 is not set
-# CONFIG_SA1100_EXTENEX1 is not set
-# CONFIG_SA1100_FLEXANET is not set
-# CONFIG_SA1100_FREEBIRD is not set
-# CONFIG_SA1100_GRAPHICSCLIENT is not set
-# CONFIG_SA1100_GRAPHICSMASTER is not set
# CONFIG_SA1100_BADGE4 is not set
# CONFIG_SA1100_JORNADA720 is not set
# CONFIG_SA1100_HACKKIT is not set
-# CONFIG_SA1100_HUW_WEBPANEL is not set
-# CONFIG_SA1100_ITSY is not set
# CONFIG_SA1100_LART is not set
-# CONFIG_SA1100_NANOENGINE is not set
-# CONFIG_SA1100_OMNIMETER is not set
-# CONFIG_SA1100_PANGOLIN is not set
# CONFIG_SA1100_PLEB is not set
-# CONFIG_SA1100_PT_SYSTEM3 is not set
# CONFIG_SA1100_SHANNON is not set
-# CONFIG_SA1100_SHERMAN is not set
# CONFIG_SA1100_SIMPAD is not set
-# CONFIG_SA1100_PFS168 is not set
-# CONFIG_SA1100_VICTOR is not set
-# CONFIG_SA1100_XP860 is not set
-# CONFIG_SA1100_YOPY is not set
-# CONFIG_SA1100_STORK is not set
# CONFIG_SA1100_SSP is not set
-CONFIG_SA1100_USB=m
-CONFIG_SA1100_USB_NETLINK=m
-# CONFIG_SA1100_USB_CHAR is not set
#
# Processor Type
@@ -136,6 +112,7 @@ CONFIG_CPU_SA1100=y
CONFIG_CPU_32v4=y
CONFIG_CPU_ABRT_EV4=y
CONFIG_CPU_CACHE_V4WB=y
+CONFIG_CPU_CACHE_VIVT=y
CONFIG_CPU_TLB_V4WB=y
CONFIG_CPU_MINICACHE=y
@@ -144,69 +121,105 @@ CONFIG_CPU_MINICACHE=y
#
#
-# General setup
+# Bus support
#
-CONFIG_DISCONTIGMEM=y
CONFIG_ISA=y
-# CONFIG_ZBOOT_ROM is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+CONFIG_PCCARD=m
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=m
+
+#
+# PC-card bridges
+#
+# CONFIG_I82365 is not set
+# CONFIG_TCIC is not set
+CONFIG_PCMCIA_SA1100=m
+
+#
+# Kernel Features
+#
+# CONFIG_PREEMPT is not set
+CONFIG_DISCONTIGMEM=y
+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="console=ttySA0,38400 root=/dev/mtdblock3 rootfstype=jffs2 rw mem=32M init=/linuxrc"
+# CONFIG_XIP_KERNEL is not set
+
+#
+# CPU Frequency scaling
+#
CONFIG_CPU_FREQ=y
-CONFIG_CPU_FREQ_SA1110=y
-# CONFIG_CPU_FREQ_PROC_INTF is not set
+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 is not set
CONFIG_CPU_FREQ_GOV_USERSPACE=m
-CONFIG_CPU_FREQ_24_API=y
-CONFIG_HOTPLUG=y
+# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set
+CONFIG_CPU_FREQ_SA1110=y
#
-# PCMCIA/CardBus support
+# Floating point emulation
#
-CONFIG_PCMCIA=m
-# CONFIG_PCMCIA_DEBUG is not set
-# CONFIG_I82365 is not set
-# CONFIG_TCIC is not set
-CONFIG_PCMCIA_SA1100=m
#
-# At least one math emulation must be selected
+# At least one emulation must be selected
#
# CONFIG_FPE_NWFPE is not set
CONFIG_FPE_FASTFPE=y
+
+#
+# Userspace binary formats
+#
CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_AOUT is not set
# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
#
-# Generic Driver Options
+# Power management options
#
-# CONFIG_FW_LOADER is not set
CONFIG_PM=y
-# CONFIG_PREEMPT is not set
# CONFIG_APM is not set
-# CONFIG_ARTHUR is not set
-CONFIG_CMDLINE="console=ttySA0,38400 root=/dev/mtdblock3 rootfstype=jffs2 rw mem=32M init=/linuxrc"
-CONFIG_LEDS=y
-CONFIG_LEDS_TIMER=y
-CONFIG_LEDS_CPU=y
-CONFIG_ALIGNMENT_TRAP=y
#
-# Parallel port support
+# Device Drivers
#
-# CONFIG_PARPORT is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
#
# Memory Technology Devices (MTD)
#
CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
-CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
CONFIG_MTD_REDBOOT_PARTS=y
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
+# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
CONFIG_MTD_CMDLINE_PARTS=y
# CONFIG_MTD_AFS_PARTS is not set
@@ -226,13 +239,24 @@ CONFIG_MTD_CFI=y
# CONFIG_MTD_JEDECPROBE is not set
CONFIG_MTD_GEN_PROBE=y
# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
CONFIG_MTD_CFI_INTELEXT=y
# CONFIG_MTD_CFI_AMDSTD is not set
# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
+# CONFIG_MTD_XIP is not set
#
# Mapping drivers for chip access
@@ -247,8 +271,10 @@ CONFIG_MTD_SA1100=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
@@ -263,6 +289,11 @@ CONFIG_MTD_SA1100=y
# CONFIG_MTD_NAND is not set
#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
# Plug and Play support
#
# CONFIG_PNP is not set
@@ -272,12 +303,57 @@ CONFIG_MTD_SA1100=y
#
# CONFIG_BLK_DEV_FD is not set
# CONFIG_BLK_DEV_XD is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
CONFIG_BLK_DEV_LOOP=m
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
# CONFIG_BLK_DEV_NBD is not set
CONFIG_BLK_DEV_RAM=m
+CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
-CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# 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=m
+# 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
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+# CONFIG_IDE_ARM is not set
+# CONFIG_IDE_CHIPSETS is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
#
# Multi-device support (RAID and LVM)
@@ -285,6 +361,18 @@ CONFIG_BLK_DEV_INITRD=y
# CONFIG_MD is not set
#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
# Networking support
#
CONFIG_NET=y
@@ -307,23 +395,24 @@ CONFIG_IP_PNP_RARP=y
# CONFIG_NET_IPIP is not set
# CONFIG_NET_IPGRE is not set
# CONFIG_ARPD is not set
-# CONFIG_INET_ECN is not set
# CONFIG_SYN_COOKIES is not set
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
# CONFIG_IPV6 is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
# CONFIG_NETFILTER is not set
#
# SCTP Configuration (EXPERIMENTAL)
#
-CONFIG_IPV6_SCTP__=y
# CONFIG_IP_SCTP is not set
# CONFIG_ATM is not set
+# CONFIG_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
@@ -332,37 +421,42 @@ CONFIG_IPV6_SCTP__=y
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
#
# QoS and/or fair queueing
#
# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
#
# Network testing
#
# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
#
# ARCnet devices
#
# CONFIG_ARCNET is not set
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
#
# Ethernet (10 or 100Mbit)
#
CONFIG_NET_ETHERNET=y
# CONFIG_MII is not set
-# CONFIG_SMC91X is not set
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_LANCE is not set
# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_SMC91X is not set
# CONFIG_NET_VENDOR_RACAL is not set
# CONFIG_AT1700 is not set
# CONFIG_DEPCA is not set
@@ -372,7 +466,6 @@ CONFIG_NET_PCI=y
# CONFIG_AC3200 is not set
# CONFIG_APRICOT is not set
# CONFIG_CS89x0 is not set
-CONFIG_CS8900=m
# CONFIG_NET_POCKET is not set
#
@@ -382,25 +475,16 @@ CONFIG_CS8900=m
#
# Ethernet (10000 Mbit)
#
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-# CONFIG_HOSTAP is not set
#
# Token Ring devices
#
# CONFIG_TR is not set
-# CONFIG_SHAPER is not set
#
-# Wan interfaces
+# Wireless LAN (non-hamradio)
#
-# CONFIG_WAN is not set
+# CONFIG_NET_RADIO is not set
#
# PCMCIA network device support
@@ -408,60 +492,18 @@ CONFIG_CS8900=m
# CONFIG_NET_PCMCIA is not set
#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
-# Bluetooth support
-#
-# CONFIG_BT is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-CONFIG_IDE=y
-CONFIG_BLK_DEV_IDE=y
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
-CONFIG_BLK_DEV_IDEDISK=m
-# CONFIG_IDEDISK_MULTI_MODE is not set
-# CONFIG_IDEDISK_STROKE is not set
-CONFIG_BLK_DEV_IDECS=m
-# CONFIG_BLK_DEV_IDECD is not set
-# CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
-# CONFIG_IDE_TASK_IOCTL is not set
-# CONFIG_IDE_TASKFILE_IO is not set
-
-#
-# IDE chipset support/bugfixes
-#
-# CONFIG_IDE_CHIPSETS is not set
-# CONFIG_BLK_DEV_IDEDMA is not set
-# CONFIG_IDEDMA_AUTO is not set
-# CONFIG_BLK_DEV_HD is not set
-
-#
-# SCSI device support
-#
-# CONFIG_SCSI is not set
-
-#
-# I2O device support
+# 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
#
# ISDN subsystem
#
-# CONFIG_ISDN_BOOL is not set
+# CONFIG_ISDN is not set
#
# Input device support
@@ -477,19 +519,10 @@ 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_TSLIBDEV is not set
# CONFIG_INPUT_EVDEV is not set
# CONFIG_INPUT_EVBUG is not set
#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-# CONFIG_SERIO is not set
-# CONFIG_SERIO_I8042 is not set
-
-#
# Input Device Drivers
#
# CONFIG_INPUT_KEYBOARD is not set
@@ -499,6 +532,13 @@ CONFIG_SOUND_GAMEPORT=y
# CONFIG_INPUT_MISC is not set
#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
+#
# Character devices
#
CONFIG_VT=y
@@ -514,42 +554,13 @@ CONFIG_HW_CONSOLE=y
#
# Non-8250 serial port support
#
-# CONFIG_SERIAL_DZ is not set
CONFIG_SERIAL_SA1100=y
CONFIG_SERIAL_SA1100_CONSOLE=y
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=32
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# I2C Algorithms
-#
-
-#
-# I2C Hardware Bus support
-#
-
-#
-# I2C Hardware Sensors Chip support
-#
-# CONFIG_I2C_SENSOR is not set
-
-#
-# L3 serial bus support
-#
-CONFIG_L3=m
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_QIC02_TAPE is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
#
# IPMI
@@ -561,40 +572,27 @@ CONFIG_L3=m
#
CONFIG_WATCHDOG=y
# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
# CONFIG_SOFT_WATCHDOG is not set
-# CONFIG_WDT is not set
-# CONFIG_WDTPCI is not set
-# CONFIG_PCWATCHDOG is not set
-# CONFIG_ACQUIRE_WDT is not set
-# CONFIG_ADVANTECH_WDT is not set
CONFIG_SA1100_WATCHDOG=m
-# CONFIG_EUROTECH_WDT is not set
-# CONFIG_IB700_WDT is not set
+
+#
+# ISA-based Watchdog Cards
+#
+# CONFIG_PCWATCHDOG is not set
# CONFIG_MIXCOMWD is not set
-# CONFIG_SCx200_WDT is not set
-# CONFIG_60XX_WDT is not set
-# CONFIG_W83877F_WDT is not set
-# CONFIG_MACHZ_WDT is not set
-# CONFIG_SC520_WDT is not set
-# CONFIG_AMD7XX_TCO is not set
-# CONFIG_ALIM7101_WDT is not set
-# CONFIG_ALIM1535_WDT is not set
-# CONFIG_SC1200_WDT is not set
-# CONFIG_WAFER_WDT is not set
-# CONFIG_CPU5_WDT is not set
+# CONFIG_WDT is not set
# CONFIG_NVRAM is not set
# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
-# CONFIG_SA1100_RTC is not set
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
#
# Ftape, the floppy tape device driver
#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
# CONFIG_DRM is not set
#
@@ -604,6 +602,20 @@ CONFIG_SA1100_WATCHDOG=m
# CONFIG_RAW_DRIVER is not set
#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Misc devices
+#
+
+#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -614,6 +626,35 @@ CONFIG_SA1100_WATCHDOG=m
# CONFIG_DVB is not set
#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_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 is not set
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
# MMC/SD Card support
#
# CONFIG_MMC is not set
@@ -632,10 +673,16 @@ CONFIG_JBD=m
CONFIG_FS_MBCACHE=m
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+
+#
+# XFS support
+#
# CONFIG_XFS_FS is not set
# CONFIG_MINIX_FS is not set
CONFIG_ROMFS_FS=y
# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
@@ -651,16 +698,19 @@ CONFIG_ROMFS_FS=y
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_SYSFS=y
# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS=y
# CONFIG_DEVPTS_FS_XATTR is not set
CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
@@ -670,6 +720,7 @@ CONFIG_RAMFS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
# CONFIG_BEFS_FS is not set
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
@@ -677,6 +728,11 @@ CONFIG_RAMFS=y
CONFIG_JFFS2_FS=y
CONFIG_JFFS2_FS_DEBUG=0
# CONFIG_JFFS2_FS_NAND is not set
+# CONFIG_JFFS2_FS_NOR_ECC is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
# CONFIG_CRAMFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_HPFS_FS is not set
@@ -694,18 +750,19 @@ CONFIG_NFS_V4=y
CONFIG_NFSD=m
CONFIG_NFSD_V3=y
CONFIG_NFSD_V4=y
-# CONFIG_NFSD_TCP is not set
+CONFIG_NFSD_TCP=y
CONFIG_LOCKD=m
CONFIG_LOCKD_V4=y
CONFIG_EXPORTFS=m
CONFIG_SUNRPC=m
-# CONFIG_SUNRPC_GSS is not set
+CONFIG_SUNRPC_GSS=m
+CONFIG_RPCSEC_GSS_KRB5=m
+# 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_INTERMEZZO_FS is not set
# CONFIG_AFS_FS is not set
#
@@ -723,17 +780,15 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_SOLARIS_X86_PARTITION is not set
# CONFIG_UNIXWARE_DISKLABEL is not set
# CONFIG_LDM_PARTITION is not set
-# CONFIG_NEC98_PARTITION is not set
# CONFIG_SGI_PARTITION is not set
# CONFIG_ULTRIX_PARTITION is not set
# CONFIG_SUN_PARTITION is not set
# CONFIG_EFI_PARTITION is not set
-CONFIG_SMB_NLS=y
-CONFIG_NLS=y
#
# Native Language Support
#
+CONFIG_NLS=y
CONFIG_NLS_DEFAULT="iso8859-1"
CONFIG_NLS_CODEPAGE_437=m
# CONFIG_NLS_CODEPAGE_737 is not set
@@ -758,6 +813,7 @@ CONFIG_NLS_CODEPAGE_437=m
# CONFIG_NLS_ISO8859_8 is not set
# CONFIG_NLS_CODEPAGE_1250 is not set
# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
CONFIG_NLS_ISO8859_1=m
# CONFIG_NLS_ISO8859_2 is not set
# CONFIG_NLS_ISO8859_3 is not set
@@ -774,69 +830,76 @@ CONFIG_NLS_ISO8859_1=m
# CONFIG_NLS_UTF8 is not set
#
-# Graphics support
-#
-# CONFIG_FB is not set
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_MDA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# Misc devices
-#
-
-#
-# Multimedia Capabilities Port drivers
-#
-# CONFIG_MCP is not set
-
-#
-# Console Switches
+# Profiling support
#
-# CONFIG_SWITCHES is not set
-
-#
-# USB support
-#
-# CONFIG_USB_GADGET is not set
+# CONFIG_PROFILING is not set
#
# Kernel hacking
#
-CONFIG_FRAME_POINTER=y
-CONFIG_DEBUG_USER=y
-# CONFIG_DEBUG_INFO is not set
+# CONFIG_PRINTK_TIME is not set
CONFIG_DEBUG_KERNEL=y
-# CONFIG_DEBUG_SLAB is not set
CONFIG_MAGIC_SYSRQ=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_WAITQ 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_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_WAITQ is not set
CONFIG_DEBUG_ERRORS=y
CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
#
# Security options
#
+# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
#
# Cryptographic options
#
-# CONFIG_CRYPTO is not set
+CONFIG_CRYPTO=y
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=m
+# 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=m
+# 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_CRC32=y
+# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/arm/configs/clps7500_defconfig b/arch/arm/configs/clps7500_defconfig
index 7444861d4450b..9087583714058 100644
--- a/arch/arm/configs/clps7500_defconfig
+++ b/arch/arm/configs/clps7500_defconfig
@@ -1,17 +1,49 @@
#
# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.12-rc1-bk2
+# Sun Mar 27 17:20:48 2005
#
CONFIG_ARM=y
-# CONFIG_EISA is not set
-# CONFIG_SBUS is not set
-# CONFIG_MCA is not set
+CONFIG_MMU=y
CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_IOMAP=y
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_OBSOLETE=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_SYSCTL is not set
+# CONFIG_AUDIT is not set
+# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
#
# Loadable module support
@@ -21,138 +53,177 @@ CONFIG_OBSOLETE=y
#
# System Type
#
-# CONFIG_ARCH_ARCA5K is not set
CONFIG_ARCH_CLPS7500=y
+# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_L7200 is not set
-# CONFIG_ARCH_FTVPCI is not set
-# CONFIG_ARCH_TBOX is not set
-# CONFIG_ARCH_SHARK 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_CLPS711X 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
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM710=y
+CONFIG_CPU_32v3=y
+CONFIG_CPU_CACHE_V3=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V3=y
+CONFIG_CPU_TLB_V3=y
#
-# Archimedes/A5000 Implementations
+# Processor Features
#
+CONFIG_TIMER_ACORN=y
#
-# Footbridge Implementations
+# Bus support
#
+CONFIG_ISA=y
#
-# SA11x0 Implementations
+# PCCARD (PCMCIA/CardBus) support
#
+# CONFIG_PCCARD is not set
#
-# CLPS711X/EP721X Implementations
+# Kernel Features
#
-# CONFIG_ARCH_ACORN is not set
-# CONFIG_FOOTBRIDGE is not set
-# CONFIG_FOOTBRIDGE_HOST is not set
-# CONFIG_FOOTBRIDGE_ADDIN is not set
-CONFIG_CPU_32=y
-# CONFIG_CPU_26 is not set
+# CONFIG_PREEMPT is not set
+CONFIG_ALIGNMENT_TRAP=y
#
-# Processor Type
+# Boot options
#
-CONFIG_CPU_32v3=y
-# CONFIG_CPU_32v4 is not set
-# CONFIG_CPU_ARM610 is not set
-CONFIG_CPU_ARM710=y
-# CONFIG_CPU_ARM720T is not set
-# CONFIG_CPU_ARM920T is not set
-# CONFIG_CPU_ARM1020 is not set
-# CONFIG_CPU_SA110 is not set
-# CONFIG_CPU_SA1100 is not set
-# CONFIG_DISCONTIGMEM is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="mem=16M root=nfs"
+# CONFIG_XIP_KERNEL is not set
#
-# General setup
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+# CONFIG_FPE_NWFPE is not set
+
+#
+# Userspace binary formats
#
-CONFIG_ANGELBOOT=y
-# CONFIG_PCI is not set
-CONFIG_ISA=y
-# CONFIG_ISA_DMA is not set
-# CONFIG_HOTPLUG is not set
-# CONFIG_PCMCIA is not set
-CONFIG_NET=y
-CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-# CONFIG_SYSCTL is not set
-CONFIG_NWFPE=y
-CONFIG_KCORE_ELF=y
-# CONFIG_KCORE_AOUT is not set
-# CONFIG_BINFMT_AOUT is not set
CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
# CONFIG_BINFMT_MISC is not set
-# CONFIG_PM is not set
# CONFIG_ARTHUR is not set
-CONFIG_CMDLINE="mem=16M root=nfs"
-# CONFIG_ALIGNMENT_TRAP is not set
#
-# Parallel port support
+# Power management options
+#
+# CONFIG_PM is not set
+
+#
+# Device Drivers
#
-CONFIG_PARPORT=y
-CONFIG_PARPORT_PC=y
-CONFIG_PARPORT_PC_FIFO=y
-# CONFIG_PARPORT_PC_SUPERIO is not set
-# CONFIG_PARPORT_AMIGA is not set
-# CONFIG_PARPORT_MFC3 is not set
-# CONFIG_PARPORT_ATARI is not set
-# CONFIG_PARPORT_SUNBPP is not set
-# CONFIG_PARPORT_OTHER is not set
-CONFIG_PARPORT_1284=y
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
#
# Memory Technology Devices (MTD)
#
CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+# CONFIG_MTD_PARTITIONS is not set
#
-# Disk-On-Chip Device Drivers
+# User Modules And Translation Layers
#
-# CONFIG_MTD_DOC1000 is not set
-# CONFIG_MTD_DOC2000 is not set
-# CONFIG_MTD_DOC2001 is not set
-# CONFIG_MTD_DOCPROBE is not set
+# CONFIG_MTD_CHAR is not set
+# CONFIG_MTD_BLOCK is not set
+# CONFIG_MTD_BLOCK_RO is not set
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM 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
#
-# RAM/ROM Device Drivers
+# Self-contained MTD device drivers
#
# CONFIG_MTD_SLRAM is not set
-# CONFIG_MTD_PMC551_BUGFIX is not set
-# CONFIG_MTD_PMC551_DEBUG 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
#
-# Linearly Mapped Flash Device Drivers
+# Disk-On-Chip Device Drivers
#
-# CONFIG_MTD_CFI is not set
-# CONFIG_MTD_RAM is not set
-# CONFIG_MTD_ROM is not set
-# CONFIG_MTD_JEDEC is not set
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
#
-# Drivers for chip mappings
+# NAND Flash Device Drivers
#
+# CONFIG_MTD_NAND is not set
#
-# User modules and translation layers for MTD devices
+# Parallel port support
#
-# CONFIG_MTD_CHAR is not set
-# CONFIG_MTD_BLOCK is not set
-# CONFIG_FTL is not set
-# CONFIG_NFTL is not set
+CONFIG_PARPORT=y
+CONFIG_PARPORT_PC=y
+CONFIG_PARPORT_PC_FIFO=y
+# CONFIG_PARPORT_PC_SUPERIO is not set
+# CONFIG_PARPORT_ARC is not set
+# CONFIG_PARPORT_GSC is not set
+CONFIG_PARPORT_1284=y
#
-# Plug and Play configuration
+# Plug and Play support
#
# CONFIG_PNP is not set
@@ -162,77 +233,136 @@ CONFIG_MTD=y
# CONFIG_BLK_DEV_FD is not set
# CONFIG_BLK_DEV_XD is not set
# CONFIG_PARIDE is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
# CONFIG_BLK_DEV_LOOP is not set
CONFIG_BLK_DEV_NBD=y
CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
# CONFIG_BLK_DEV_INITRD is not set
-# CONFIG_BLK_DEV_FLD7500 is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
#
# Networking options
#
# CONFIG_PACKET is not set
-# CONFIG_NETLINK is not set
-# CONFIG_NETFILTER is not set
-# CONFIG_FILTER is not set
+# CONFIG_NETLINK_DEV is not set
CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
CONFIG_INET=y
# CONFIG_IP_MULTICAST is not set
# CONFIG_IP_ADVANCED_ROUTER is not set
CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP 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_INET_ECN is not set
+# CONFIG_ARPD is not set
# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
# CONFIG_IPV6 is not set
-# CONFIG_KHTTPD is not set
-# CONFIG_ATM 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_DECNET is not set
-# CONFIG_BRIDGE is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-# CONFIG_LLC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
#
# QoS and/or fair queueing
#
# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
#
-# Network device support
+# 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=y
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
#
# ARCnet devices
#
# CONFIG_ARCNET is not set
-CONFIG_DUMMY=y
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-# CONFIG_NET_SB1000 is not set
#
# Ethernet (10 or 100Mbit)
#
CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_LANCE is not set
# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_SMC91X is not set
# CONFIG_NET_VENDOR_RACAL is not set
# CONFIG_AT1700 is not set
# CONFIG_DEPCA is not set
@@ -242,18 +372,34 @@ CONFIG_NET_PCI=y
# CONFIG_AC3200 is not set
# CONFIG_APRICOT is not set
CONFIG_CS89x0=y
-# CONFIG_ZNET is not set
# CONFIG_NET_POCKET is not set
#
# Ethernet (1000 Mbit)
#
-# CONFIG_ACENIC_OMIT_TIGON_I is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
# CONFIG_PLIP is not set
CONFIG_PPP=y
# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
# CONFIG_PPP_ASYNC is not set
# CONFIG_PPP_SYNC_TTY is not set
# CONFIG_PPP_DEFLATE is not set
@@ -263,183 +409,340 @@ CONFIG_SLIP=y
CONFIG_SLIP_COMPRESSED=y
# CONFIG_SLIP_SMART is not set
# CONFIG_SLIP_MODE_SLIP6 is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
#
-# Wireless LAN (non-hamradio)
+# ISDN subsystem
#
-# CONFIG_NET_RADIO is not set
+# CONFIG_ISDN is not set
#
-# Token Ring devices
+# Input device support
#
-# CONFIG_TR is not set
-# CONFIG_NET_FC is not set
-# CONFIG_RCPCI is not set
-# CONFIG_SHAPER is not set
+CONFIG_INPUT=y
#
-# Wan interfaces
+# Userland interfaces
#
-# CONFIG_WAN is not set
-# CONFIG_ASH is not set
+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
#
-# Amateur Radio support
+# Input Device Drivers
#
-# CONFIG_HAMRADIO is not set
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_INPORT is not set
+# CONFIG_MOUSE_LOGIBM is not set
+# CONFIG_MOUSE_PC110PAD is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
#
-# IrDA (infrared) support
+# Hardware I/O ports
#
-# CONFIG_IRDA is not set
+CONFIG_SERIO=y
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_PARKBD is not set
+CONFIG_SERIO_RPCKBD=y
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
#
-# ATA/IDE/MFM/RLL support
+# Character devices
#
-# CONFIG_IDE is not set
-# CONFIG_BLK_DEV_HD is not set
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
#
-# SCSI support
+# Serial drivers
#
-# CONFIG_SCSI is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
#
-# I2O device support
+# Non-8250 serial port support
#
-# CONFIG_I2O 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
+CONFIG_PRINTER=y
+# CONFIG_LP_CONSOLE is not set
+# CONFIG_PPDEV is not set
+# CONFIG_TIPAR is not set
#
-# ISDN subsystem
+# IPMI
#
-# CONFIG_ISDN is not set
+# CONFIG_IPMI_HANDLER is not set
#
-# Input core support
+# Watchdog Cards
#
-# CONFIG_INPUT is not set
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
#
-# Character devices
+# Ftape, the floppy tape device driver
#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_SERIAL=y
-# CONFIG_SERIAL_CONSOLE is not set
-# CONFIG_SERIAL_EXTENDED is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
-CONFIG_PRINTER=y
-# CONFIG_LP_CONSOLE is not set
-# CONFIG_PPDEV is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
#
# I2C support
#
CONFIG_I2C=y
+# CONFIG_I2C_CHARDEV is not set
+
+#
+# I2C Algorithms
+#
CONFIG_I2C_ALGOBIT=y
# CONFIG_I2C_ALGOPCF is not set
-# CONFIG_I2C_CHARDEV is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ELEKTOR is not set
+# CONFIG_I2C_ISA is not set
+# CONFIG_I2C_PARPORT is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Hardware Sensors Chip support
+#
+# CONFIG_I2C_SENSOR is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+
+#
+# Other I2C Chip support
+#
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
#
-# Mice
+# Multimedia devices
#
-CONFIG_BUSMOUSE=y
-# CONFIG_ATIXL_BUSMOUSE is not set
-# CONFIG_LOGIBUSMOUSE is not set
-# CONFIG_MS_BUSMOUSE is not set
-CONFIG_MOUSE=y
-# CONFIG_PSMOUSE is not set
-# CONFIG_82C710_MOUSE is not set
-# CONFIG_PC110_PAD is not set
+# CONFIG_VIDEO_DEV is not set
#
-# Joysticks
+# Digital Video Broadcasting Devices
#
+# CONFIG_DVB is not set
#
-# Game port support
+# Graphics support
#
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+CONFIG_FB_SOFT_CURSOR=y
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+CONFIG_FB_ACORN=y
+# CONFIG_FB_VIRTUAL is not set
#
-# Gameport joysticks
+# 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_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+# CONFIG_FONT_ACORN_8x8 is not set
+# CONFIG_FONT_MINI_4x6 is not set
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
#
-# Serial port support
+# 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
#
-# Serial port joysticks
+# Sound
#
+# CONFIG_SOUND is not set
#
-# Parallel port joysticks
+# USB support
#
-# CONFIG_QIC02_TAPE is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB is not set
#
-# Watchdog Cards
+# USB Gadget Support
#
-# CONFIG_WATCHDOG is not set
-CONFIG_CLPS7500_FLASH=y
-# CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
+# CONFIG_USB_GADGET is not set
#
-# Multimedia devices
+# MMC/SD Card support
#
-# CONFIG_VIDEO_DEV is not set
+# CONFIG_MMC is not set
#
# File systems
#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
+# CONFIG_XFS_FS is not set
+CONFIG_MINIX_FS=y
+# CONFIG_ROMFS_FS is not set
# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS 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_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# 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_FAT_FS is not set
# CONFIG_EFS_FS is not set
# CONFIG_JFFS_FS is not set
+# CONFIG_JFFS2_FS is not set
# CONFIG_CRAMFS is not set
-# CONFIG_RAMFS is not set
-# CONFIG_ISO9660_FS is not set
-CONFIG_MINIX_FS=y
-# CONFIG_NTFS_FS is not set
-# CONFIG_NTFS_DEBUG is not set
-# CONFIG_NTFS_RW is not set
+# CONFIG_VXFS_FS is not set
# CONFIG_HPFS_FS is not set
-CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS=y
# CONFIG_QNX4FS_FS is not set
-# CONFIG_ROMFS_FS is not set
-CONFIG_EXT2_FS=y
# CONFIG_SYSV_FS is not set
-# CONFIG_UDF_FS is not set
# CONFIG_UFS_FS is not set
#
# Network File Systems
#
-# CONFIG_CODA_FS is not set
CONFIG_NFS_FS=y
# CONFIG_NFS_V3 is not set
-CONFIG_ROOT_NFS=y
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
# CONFIG_NFSD is not set
-CONFIG_SUNRPC=y
+CONFIG_ROOT_NFS=y
CONFIG_LOCKD=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
#
# Partition Types
@@ -451,66 +754,50 @@ CONFIG_PARTITION_ADVANCED=y
# 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_SMB_NLS is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
# CONFIG_NLS is not set
#
-# Console drivers
+# Profiling support
#
-CONFIG_PC_KEYB=y
-CONFIG_PC_KEYMAP=y
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_FB=y
+# CONFIG_PROFILING is not set
#
-# Frame-buffer support
+# Kernel hacking
#
-CONFIG_FB=y
-CONFIG_DUMMY_CONSOLE=y
-CONFIG_FB_ACORN=y
-# CONFIG_CHRONTEL_7003 is not set
-# CONFIG_FB_VIRTUAL is not set
-CONFIG_FBCON_ADVANCED=y
-CONFIG_FBCON_MFB=y
-CONFIG_FBCON_CFB2=y
-CONFIG_FBCON_CFB4=y
-CONFIG_FBCON_CFB8=y
-CONFIG_FBCON_CFB16=y
-CONFIG_FBCON_CFB24=y
-# CONFIG_FBCON_CFB32 is not set
-# CONFIG_FBCON_AFB is not set
-# CONFIG_FBCON_ILBM is not set
-# CONFIG_FBCON_IPLAN2P2 is not set
-# CONFIG_FBCON_IPLAN2P4 is not set
-# CONFIG_FBCON_IPLAN2P8 is not set
-# CONFIG_FBCON_MAC is not set
-# CONFIG_FBCON_VGA_PLANES is not set
-# CONFIG_FBCON_VGA is not set
-# CONFIG_FBCON_HGA is not set
-# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
-# CONFIG_FBCON_FONTS is not set
-CONFIG_FONT_8x8=y
-CONFIG_FONT_8x16=y
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_DEBUG_USER is not set
#
-# Sound
+# Security options
#
-# CONFIG_SOUND is not set
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
#
-# USB support
+# Cryptographic options
#
-# CONFIG_USB is not set
+# CONFIG_CRYPTO is not set
#
-# Kernel hacking
+# Hardware crypto devices
#
-# CONFIG_FRAME_POINTER is not set
-# CONFIG_DEBUG_ERRORS is not set
-# CONFIG_DEBUG_USER is not set
-# CONFIG_DEBUG_INFO is not set
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_LL=y
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
diff --git a/arch/arm/configs/ebsa110_defconfig b/arch/arm/configs/ebsa110_defconfig
index 5296812f87d8c..6f61929b97a89 100644
--- a/arch/arm/configs/ebsa110_defconfig
+++ b/arch/arm/configs/ebsa110_defconfig
@@ -1,40 +1,50 @@
#
# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.12-rc1-bk2
+# Sun Mar 27 18:29:48 2005
#
CONFIG_ARM=y
CONFIG_MMU=y
CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_IOMAP=y
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
CONFIG_CLEAN_COMPILE=y
-CONFIG_STANDALONE=y
CONFIG_BROKEN_ON_SMP=y
#
# General setup
#
+CONFIG_LOCALVERSION=""
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
# CONFIG_POSIX_MQUEUE is not set
CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
# CONFIG_IKCONFIG is not set
CONFIG_EMBEDDED=y
CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=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
@@ -43,12 +53,12 @@ CONFIG_MODULES=y
# CONFIG_MODULE_UNLOAD is not set
CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_KMOD=y
#
# System Type
#
-# CONFIG_ARCH_ADIFCC is not set
# CONFIG_ARCH_CLPS7500 is not set
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
@@ -58,6 +68,7 @@ CONFIG_ARCH_EBSA110=y
# 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
@@ -66,7 +77,9 @@ CONFIG_ARCH_EBSA110=y
# CONFIG_ARCH_SHARK is not set
# CONFIG_ARCH_LH7A40X is not set
# CONFIG_ARCH_OMAP is not set
-# CONFIG_ARCH_VERSATILE_PB is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_H720X is not set
#
# Processor Type
@@ -76,6 +89,7 @@ CONFIG_CPU_SA110=y
CONFIG_CPU_32v4=y
CONFIG_CPU_ABRT_EV4=y
CONFIG_CPU_CACHE_V4WB=y
+CONFIG_CPU_CACHE_VIVT=y
CONFIG_CPU_COPY_V4WB=y
CONFIG_CPU_TLB_V4WB=y
@@ -84,54 +98,85 @@ CONFIG_CPU_TLB_V4WB=y
#
#
-# General setup
+# Bus support
#
CONFIG_ISA=y
-# CONFIG_ZBOOT_ROM is not set
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
#
-# PCMCIA/CardBus support
+# PCCARD (PCMCIA/CardBus) support
#
-CONFIG_PCMCIA=m
+CONFIG_PCCARD=m
# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=m
+
+#
+# PC-card bridges
+#
CONFIG_I82365=m
# CONFIG_TCIC is not set
CONFIG_PCMCIA_PROBE=y
+CONFIG_PCCARD_NONSTATIC=m
+
+#
+# Kernel Features
+#
+# CONFIG_PREEMPT is not set
+CONFIG_LEDS=y
+CONFIG_LEDS_TIMER=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="root=/dev/nfs rw mem=16M console=ttyS1,38400n8"
+# CONFIG_XIP_KERNEL is not set
#
-# At least one math emulation must be selected
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
#
CONFIG_FPE_NWFPE=y
# CONFIG_FPE_NWFPE_XP is not set
CONFIG_FPE_FASTFPE=y
+
+#
+# Userspace binary formats
+#
CONFIG_BINFMT_ELF=y
CONFIG_BINFMT_AOUT=y
# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+
+#
+# Device Drivers
+#
#
# Generic Driver Options
#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
# CONFIG_FW_LOADER is not set
-# CONFIG_PM is not set
-# CONFIG_PREEMPT is not set
-# CONFIG_ARTHUR is not set
-CONFIG_CMDLINE="root=/dev/nfs rw mem=16M console=ttyS1,38400n8"
-CONFIG_LEDS=y
-CONFIG_LEDS_TIMER=y
#
# Parallel port support
#
CONFIG_PARPORT=y
CONFIG_PARPORT_PC=y
-CONFIG_PARPORT_PC_CML1=y
CONFIG_PARPORT_PC_FIFO=y
# CONFIG_PARPORT_PC_SUPERIO is not set
# CONFIG_PARPORT_PC_PCMCIA is not set
# CONFIG_PARPORT_ARC is not set
-# CONFIG_PARPORT_OTHER is not set
+# CONFIG_PARPORT_GSC is not set
CONFIG_PARPORT_1284=y
#
@@ -145,11 +190,29 @@ CONFIG_PARPORT_1284=y
# CONFIG_BLK_DEV_FD is not set
# CONFIG_BLK_DEV_XD is not set
# CONFIG_PARIDE is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
# CONFIG_BLK_DEV_LOOP is not set
# CONFIG_BLK_DEV_NBD is not set
CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
#
# Multi-device support (RAID and LVM)
@@ -157,6 +220,18 @@ CONFIG_BLK_DEV_RAM_SIZE=4096
# CONFIG_MD is not set
#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
# Networking support
#
CONFIG_NET=y
@@ -174,7 +249,6 @@ CONFIG_IP_MULTICAST=y
CONFIG_IP_ADVANCED_ROUTER=y
CONFIG_IP_MULTIPLE_TABLES=y
CONFIG_IP_ROUTE_FWMARK=y
-CONFIG_IP_ROUTE_NAT=y
# CONFIG_IP_ROUTE_MULTIPATH is not set
CONFIG_IP_ROUTE_VERBOSE=y
CONFIG_IP_PNP=y
@@ -189,6 +263,9 @@ CONFIG_SYN_COOKIES=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+CONFIG_IP_TCPDIAG_IPV6=y
#
# IP: Virtual Server Configuration
@@ -199,6 +276,7 @@ CONFIG_IPV6=y
# CONFIG_INET6_AH is not set
# CONFIG_INET6_ESP is not set
# CONFIG_INET6_IPCOMP is not set
+# CONFIG_INET6_TUNNEL is not set
# CONFIG_IPV6_TUNNEL is not set
CONFIG_NETFILTER=y
# CONFIG_NETFILTER_DEBUG is not set
@@ -207,6 +285,9 @@ CONFIG_NETFILTER=y
# IP: Netfilter Configuration
#
CONFIG_IP_NF_CONNTRACK=y
+# CONFIG_IP_NF_CT_ACCT is not set
+# CONFIG_IP_NF_CONNTRACK_MARK is not set
+# CONFIG_IP_NF_CT_PROTO_SCTP is not set
CONFIG_IP_NF_FTP=y
CONFIG_IP_NF_IRC=y
# CONFIG_IP_NF_TFTP is not set
@@ -231,8 +312,16 @@ CONFIG_IP_NF_MATCH_HELPER=y
CONFIG_IP_NF_MATCH_STATE=y
CONFIG_IP_NF_MATCH_CONNTRACK=y
# CONFIG_IP_NF_MATCH_OWNER is not set
+# 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_COMMENT is not set
+# CONFIG_IP_NF_MATCH_HASHLIMIT is not set
CONFIG_IP_NF_FILTER=y
CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_IP_NF_TARGET_LOG=y
+# CONFIG_IP_NF_TARGET_ULOG is not set
+CONFIG_IP_NF_TARGET_TCPMSS=y
CONFIG_IP_NF_NAT=y
CONFIG_IP_NF_NAT_NEEDED=y
CONFIG_IP_NF_TARGET_MASQUERADE=y
@@ -248,14 +337,11 @@ CONFIG_IP_NF_TARGET_ECN=y
CONFIG_IP_NF_TARGET_DSCP=y
CONFIG_IP_NF_TARGET_MARK=y
CONFIG_IP_NF_TARGET_CLASSIFY=y
-CONFIG_IP_NF_TARGET_LOG=y
-# CONFIG_IP_NF_TARGET_ULOG is not set
-CONFIG_IP_NF_TARGET_TCPMSS=y
-# CONFIG_IP_NF_ARPTABLES is not set
# CONFIG_IP_NF_RAW is not set
+# CONFIG_IP_NF_ARPTABLES is not set
#
-# IPv6: Netfilter Configuration
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
#
# CONFIG_IP6_NF_QUEUE is not set
CONFIG_IP6_NF_IPTABLES=y
@@ -294,12 +380,12 @@ CONFIG_IP6_NF_TARGET_MARK=y
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
#
# QoS and/or fair queueing
#
# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
#
# Network testing
@@ -330,6 +416,7 @@ CONFIG_ARM_AM79C961A=y
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_LANCE is not set
# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_SMC91X is not set
# CONFIG_NET_VENDOR_RACAL is not set
# CONFIG_AT1700 is not set
# CONFIG_DEPCA is not set
@@ -387,24 +474,6 @@ CONFIG_PPP_BSDCOMP=m
# CONFIG_NETCONSOLE is not set
#
-# SCSI device support
-#
-# CONFIG_SCSI is not set
-
-#
-# Fusion MPT device support
-#
-
-#
-# IEEE 1394 (FireWire) support
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-
-#
# ISDN subsystem
#
# CONFIG_ISDN is not set
@@ -415,20 +484,11 @@ CONFIG_PPP_BSDCOMP=m
# CONFIG_INPUT is not set
#
-# Userland interfaces
-#
-
-#
-# Input I/O drivers
+# Hardware I/O ports
#
+# CONFIG_SERIO is not set
# CONFIG_GAMEPORT is not set
CONFIG_SOUND_GAMEPORT=y
-# CONFIG_SERIO is not set
-# CONFIG_SERIO_I8042 is not set
-
-#
-# Input Device Drivers
-#
#
# Character devices
@@ -457,7 +517,6 @@ CONFIG_PRINTER=m
# CONFIG_LP_CONSOLE is not set
# CONFIG_PPDEV is not set
# CONFIG_TIPAR is not set
-# CONFIG_QIC02_TAPE is not set
#
# IPMI
@@ -483,16 +542,12 @@ CONFIG_SOFT_WATCHDOG=y
# CONFIG_WDT is not set
# CONFIG_NVRAM is not set
# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
#
# Ftape, the floppy tape device driver
#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
# CONFIG_DRM is not set
#
@@ -502,11 +557,20 @@ CONFIG_SOFT_WATCHDOG=y
# CONFIG_RAW_DRIVER is not set
#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
# I2C support
#
# CONFIG_I2C is not set
#
+# Misc devices
+#
+
+#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -517,6 +581,33 @@ CONFIG_SOFT_WATCHDOG=y
# 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 is not set
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
# File systems
#
# CONFIG_EXT2_FS is not set
@@ -524,10 +615,15 @@ CONFIG_SOFT_WATCHDOG=y
# CONFIG_JBD is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
# CONFIG_XFS_FS is not set
CONFIG_MINIX_FS=y
# CONFIG_ROMFS_FS is not set
# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
CONFIG_AUTOFS4_FS=y
@@ -540,7 +636,8 @@ CONFIG_AUTOFS4_FS=y
#
# DOS/FAT/NT Filesystems
#
-# CONFIG_FAT_FS is not set
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
# CONFIG_NTFS_FS is not set
#
@@ -581,9 +678,10 @@ CONFIG_NFS_V3=y
# CONFIG_NFSD is not set
CONFIG_ROOT_NFS=y
CONFIG_LOCKD=y
-# CONFIG_EXPORTFS is not set
+CONFIG_LOCKD_V4=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
@@ -601,7 +699,6 @@ CONFIG_PARTITION_ADVANCED=y
# CONFIG_MAC_PARTITION is not set
# CONFIG_MSDOS_PARTITION is not set
# CONFIG_LDM_PARTITION is not set
-# CONFIG_NEC98_PARTITION is not set
# CONFIG_SGI_PARTITION is not set
# CONFIG_ULTRIX_PARTITION is not set
# CONFIG_SUN_PARTITION is not set
@@ -618,39 +715,19 @@ CONFIG_PARTITION_ADVANCED=y
# CONFIG_PROFILING is not set
#
-# Graphics support
-#
-# CONFIG_FB is not set
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# Misc devices
-#
-
-#
-# USB support
-#
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
# Kernel hacking
#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_BUGVERBOSE is not set
CONFIG_FRAME_POINTER=y
# CONFIG_DEBUG_USER is not set
-# CONFIG_DEBUG_INFO is not set
-# CONFIG_DEBUG_KERNEL is not set
#
# Security options
#
+# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
#
@@ -659,8 +736,13 @@ CONFIG_FRAME_POINTER=y
# CONFIG_CRYPTO is not set
#
+# Hardware crypto devices
+#
+
+#
# Library routines
#
+CONFIG_CRC_CCITT=m
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=m
diff --git a/arch/arm/configs/edb7211_defconfig b/arch/arm/configs/edb7211_defconfig
index 4a5542336b3aa..78b08ed4d5f44 100644
--- a/arch/arm/configs/edb7211_defconfig
+++ b/arch/arm/configs/edb7211_defconfig
@@ -1,17 +1,49 @@
#
-# Automatically generated by make menuconfig: don't edit
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.12-rc1-bk2
+# Sun Mar 27 21:48:12 2005
#
CONFIG_ARM=y
-# CONFIG_EISA is not set
-# CONFIG_SBUS is not set
-# CONFIG_MCA is not set
+CONFIG_MMU=y
CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_IOMAP=y
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-# CONFIG_OBSOLETE is not set
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+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_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
#
# Loadable module support
@@ -21,81 +53,116 @@ CONFIG_EXPERIMENTAL=y
#
# System Type
#
-# CONFIG_ARCH_ARCA5K is not set
# CONFIG_ARCH_CLPS7500 is not set
+CONFIG_ARCH_CLPS711X=y
# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_L7200 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_CLPS711X=y
+# 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
+
+#
+# CLPS711X/EP721X Implementations
+#
+# CONFIG_ARCH_AUTCPU12 is not set
+# CONFIG_ARCH_CDB89712 is not set
+# CONFIG_ARCH_CEIVA is not set
+# CONFIG_ARCH_CLEP7312 is not set
+CONFIG_ARCH_EDB7211=y
+# CONFIG_ARCH_P720T is not set
+# CONFIG_ARCH_FORTUNET is not set
+CONFIG_ARCH_EP7211=y
+# CONFIG_EP72XX_ROM_BOOT is not set
#
-# Archimedes/A5000 Implementations
+# Processor Type
#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM720T=y
+CONFIG_CPU_32v4=y
+CONFIG_CPU_ABRT_LV4T=y
+CONFIG_CPU_CACHE_V4=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WT=y
+CONFIG_CPU_TLB_V4WT=y
#
-# Footbridge Implementations
+# Processor Features
#
+CONFIG_ARM_THUMB=y
#
-# SA11x0 Implementations
+# Bus support
#
+CONFIG_ISA=y
#
-# CLPS711X/EP721X Implementations
+# PCCARD (PCMCIA/CardBus) support
#
-CONFIG_ARCH_EDB7211=y
-CONFIG_EP7211_BOOT_MODE=y
-# CONFIG_ARCH_P720T is not set
-# CONFIG_ARCH_ACORN is not set
-CONFIG_ARCH_EP7211=y
-# CONFIG_ARCH_EP7212 is not set
-# CONFIG_FOOTBRIDGE is not set
-# CONFIG_FOOTBRIDGE_HOST is not set
-# CONFIG_FOOTBRIDGE_ADDIN is not set
-CONFIG_CPU_32=y
-# CONFIG_CPU_26 is not set
-# CONFIG_CPU_32v3 is not set
-CONFIG_CPU_32v4=y
-# CONFIG_CPU_ARM610 is not set
-# CONFIG_CPU_ARM710 is not set
-CONFIG_CPU_ARM720T=y
-# CONFIG_CPU_ARM920T is not set
-# CONFIG_CPU_ARM1020 is not set
-# CONFIG_CPU_SA110 is not set
-# CONFIG_CPU_SA1100 is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_PREEMPT is not set
CONFIG_DISCONTIGMEM=y
+CONFIG_ALIGNMENT_TRAP=y
#
-# General setup
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE=""
+# CONFIG_XIP_KERNEL is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+# CONFIG_FPE_NWFPE is not set
+# CONFIG_FPE_FASTFPE is not set
+
+#
+# Userspace binary formats
#
-# CONFIG_ANGELBOOT is not set
-# CONFIG_PCI is not set
-# CONFIG_ISA is not set
-# CONFIG_ISA_DMA is not set
-# CONFIG_HOTPLUG is not set
-# CONFIG_PCMCIA is not set
-CONFIG_NET=y
-CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
-CONFIG_NWFPE=y
-CONFIG_KCORE_ELF=y
-# CONFIG_KCORE_AOUT is not set
-# CONFIG_BINFMT_AOUT is not set
CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
# CONFIG_BINFMT_MISC is not set
-# CONFIG_PM is not set
# CONFIG_ARTHUR is not set
-CONFIG_ALIGNMENT_TRAP=y
#
-# Parallel port support
+# Power management options
#
-# CONFIG_PARPORT is not set
+# CONFIG_PM is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
#
# Memory Technology Devices (MTD)
@@ -103,77 +170,133 @@ CONFIG_ALIGNMENT_TRAP=y
# CONFIG_MTD is not set
#
-# Plug and Play configuration
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
#
# CONFIG_PNP is not set
-# CONFIG_ISAPNP is not set
#
# Block devices
#
# CONFIG_BLK_DEV_FD is not set
# CONFIG_BLK_DEV_XD is not set
-# CONFIG_PARIDE is not set
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
# CONFIG_BLK_DEV_LOOP is not set
# CONFIG_BLK_DEV_NBD is not set
CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
#
# Networking options
#
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
-# CONFIG_NETLINK is not set
-# CONFIG_NETFILTER is not set
-# CONFIG_FILTER is not set
+# CONFIG_NETLINK_DEV is not set
CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
CONFIG_INET=y
# CONFIG_IP_MULTICAST is not set
# CONFIG_IP_ADVANCED_ROUTER is not set
# CONFIG_IP_PNP is not set
# CONFIG_NET_IPIP is not set
# CONFIG_NET_IPGRE is not set
-# CONFIG_INET_ECN 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_KHTTPD 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_DECNET is not set
-# CONFIG_BRIDGE is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-# CONFIG_LLC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
#
# QoS and/or fair queueing
#
# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
#
-# Network device support
+# Network testing
#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
#
# ARCnet devices
#
# CONFIG_ARCNET is not set
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-# CONFIG_NET_SB1000 is not set
#
# Ethernet (10 or 100Mbit)
@@ -183,121 +306,105 @@ CONFIG_NETDEVICES=y
#
# Ethernet (1000 Mbit)
#
-# CONFIG_ACENIC is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
#
-# Wireless LAN (non-hamradio)
+# Ethernet (10000 Mbit)
#
-# CONFIG_NET_RADIO is not set
#
# Token Ring devices
#
# CONFIG_TR is not set
-# CONFIG_NET_FC is not set
-# CONFIG_RCPCI is not set
-# CONFIG_SHAPER is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
#
-# Amateur Radio support
+# Wireless LAN (non-hamradio)
#
-# CONFIG_HAMRADIO is not set
+# CONFIG_NET_RADIO is not set
#
-# IrDA (infrared) support
+# Wan interfaces
#
-# CONFIG_IRDA is not set
+# 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
#
-# ATA/IDE/MFM/RLL support
+# ISDN subsystem
#
-# CONFIG_IDE is not set
-# CONFIG_BLK_DEV_HD is not set
+# CONFIG_ISDN is not set
#
-# SCSI support
+# Input device support
#
-# CONFIG_SCSI is not set
+# CONFIG_INPUT is not set
#
-# I2O device support
+# Hardware I/O ports
#
-# CONFIG_I2O is not set
-# CONFIG_I2O_BLOCK is not set
-# CONFIG_I2O_LAN is not set
-# CONFIG_I2O_SCSI is not set
-# CONFIG_I2O_PROC is not set
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
#
-# ISDN subsystem
+# Character devices
#
-# CONFIG_ISDN is not set
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
#
-# Input core support
+# Serial drivers
#
-# CONFIG_INPUT is not set
+# CONFIG_SERIAL_8250 is not set
#
-# Character devices
+# Non-8250 serial port support
#
-# CONFIG_VT is not set
-# CONFIG_SERIAL is not set
-# CONFIG_SERIAL_EXTENDED is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
CONFIG_SERIAL_CLPS711X=y
CONFIG_SERIAL_CLPS711X_CONSOLE=y
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
#
-# I2C support
+# IPMI
#
-# CONFIG_I2C is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_MOUSE is not set
-
-#
-# Joysticks
-#
-# CONFIG_JOYSTICK is not set
-# CONFIG_QIC02_TAPE is not set
+# CONFIG_IPMI_HANDLER is not set
#
# Watchdog Cards
#
# CONFIG_WATCHDOG is not set
-# CONFIG_INTEL_RNG is not set
# CONFIG_NVRAM is not set
# CONFIG_RTC is not set
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
#
# Ftape, the floppy tape device driver
#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Misc devices
+#
#
# Multimedia devices
@@ -305,68 +412,109 @@ CONFIG_UNIX98_PTY_COUNT=256
# 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 is not set
+# CONFIG_USB is not set
+
+#
+# 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_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_XFS_FS is not set
+CONFIG_MINIX_FS=y
+# CONFIG_ROMFS_FS is not set
# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS 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_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
# CONFIG_ADFS_FS is not set
-# CONFIG_ADFS_FS_RW 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_FAT_FS is not set
-# CONFIG_MSDOS_FS is not set
-# CONFIG_UMSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
# CONFIG_EFS_FS is not set
-# CONFIG_JFFS_FS is not set
# CONFIG_CRAMFS is not set
-CONFIG_RAMFS=y
-# CONFIG_ISO9660_FS is not set
-# CONFIG_JOLIET is not set
-CONFIG_MINIX_FS=y
-# CONFIG_NTFS_FS is not set
-# CONFIG_NTFS_DEBUG is not set
-# CONFIG_NTFS_RW is not set
+# CONFIG_VXFS_FS is not set
# CONFIG_HPFS_FS is not set
-CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
-# CONFIG_DEVFS_MOUNT is not set
-# CONFIG_DEVFS_DEBUG is not set
-CONFIG_DEVPTS_FS=y
# CONFIG_QNX4FS_FS is not set
-# CONFIG_QNX4FS_RW is not set
-# CONFIG_ROMFS_FS is not set
-CONFIG_EXT2_FS=y
# CONFIG_SYSV_FS is not set
-# CONFIG_SYSV_FS_WRITE is not set
-# CONFIG_UDF_FS is not set
-# CONFIG_UDF_RW is not set
# CONFIG_UFS_FS is not set
-# CONFIG_UFS_FS_WRITE is not set
#
# Network File Systems
#
-# CONFIG_CODA_FS is not set
# CONFIG_NFS_FS is not set
-# CONFIG_NFS_V3 is not set
-# CONFIG_ROOT_NFS is not set
# CONFIG_NFSD is not set
-# CONFIG_NFSD_V3 is not set
-# CONFIG_SUNRPC is not set
-# CONFIG_LOCKD is not set
# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
# CONFIG_NCP_FS is not set
-# CONFIG_NCPFS_PACKET_SIGNING is not set
-# CONFIG_NCPFS_IOCTL_LOCKING is not set
-# CONFIG_NCPFS_STRONG is not set
-# CONFIG_NCPFS_NFS_NS is not set
-# CONFIG_NCPFS_OS2_NS is not set
-# CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_NLS is not set
-# CONFIG_NCPFS_EXTRAS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
#
# Partition Types
@@ -378,23 +526,50 @@ CONFIG_PARTITION_ADVANCED=y
# 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_SMB_NLS is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
# CONFIG_NLS is not set
#
-# USB support
+# Profiling support
#
-# CONFIG_USB is not set
+# 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_DEBUG_BUGVERBOSE is not set
CONFIG_FRAME_POINTER=y
-CONFIG_DEBUG_ERRORS=y
CONFIG_DEBUG_USER=y
-# CONFIG_DEBUG_INFO is not set
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_LL=y
+
+#
+# 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_CRC32=y
+# CONFIG_LIBCRC32C is not set
diff --git a/arch/arm/configs/enp2611_defconfig b/arch/arm/configs/enp2611_defconfig
index 2f09ba9603906..e8f9fccffe84a 100644
--- a/arch/arm/configs/enp2611_defconfig
+++ b/arch/arm/configs/enp2611_defconfig
@@ -1,10 +1,14 @@
#
# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.12-rc1-bk2
+# Sun Mar 27 22:08:24 2005
#
CONFIG_ARM=y
CONFIG_MMU=y
CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_IOMAP=y
#
# Code maturity level options
@@ -16,6 +20,7 @@ CONFIG_BROKEN_ON_SMP=y
#
# General setup
#
+CONFIG_LOCALVERSION=""
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
# CONFIG_POSIX_MQUEUE is not set
@@ -23,20 +28,24 @@ CONFIG_BSD_PROCESS_ACCT=y
# CONFIG_BSD_PROCESS_ACCT_V3 is not set
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
# CONFIG_IKCONFIG is not set
CONFIG_EMBEDDED=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=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
@@ -64,7 +73,9 @@ CONFIG_ARCH_IXP2000=y
# CONFIG_ARCH_SHARK is not set
# CONFIG_ARCH_LH7A40X is not set
# CONFIG_ARCH_OMAP is not set
-# CONFIG_ARCH_VERSATILE_PB is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_H720X is not set
CONFIG_ARCH_SUPPORTS_BIG_ENDIAN=y
#
@@ -87,6 +98,7 @@ CONFIG_CPU_32=y
CONFIG_CPU_XSCALE=y
CONFIG_CPU_32v5=y
CONFIG_CPU_ABRT_EV5T=y
+CONFIG_CPU_CACHE_VIVT=y
CONFIG_CPU_TLB_V4WBI=y
CONFIG_CPU_MINICACHE=y
@@ -98,51 +110,75 @@ CONFIG_CPU_BIG_ENDIAN=y
CONFIG_XSCALE_PMU=y
#
-# General setup
+# Bus support
#
CONFIG_PCI=y
-# CONFIG_ZBOOT_ROM is not set
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
CONFIG_PCI_LEGACY_PROC=y
CONFIG_PCI_NAMES=y
#
-# At least one math emulation must be selected
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_PREEMPT is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="console=ttyS0,57600 root=/dev/nfs ip=bootp mem=64M@0x0 pci=firmware"
+# 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
-# CONFIG_VFP 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
#
-# Generic Driver Options
+# Power management options
#
-CONFIG_STANDALONE=y
-# CONFIG_PREVENT_FIRMWARE_BUILD is not set
-# CONFIG_DEBUG_DRIVER is not set
# CONFIG_PM is not set
-# CONFIG_PREEMPT is not set
-# CONFIG_ARTHUR is not set
-CONFIG_CMDLINE="console=ttyS0,57600 root=/dev/nfs ip=bootp mem=64M@0x0 pci=firmware"
-CONFIG_ALIGNMENT_TRAP=y
#
-# Parallel port support
+# Device Drivers
#
-# CONFIG_PARPORT is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
#
# Memory Technology Devices (MTD)
#
CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
-CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
CONFIG_MTD_REDBOOT_PARTS=y
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
CONFIG_MTD_REDBOOT_PARTS_READONLY=y
# CONFIG_MTD_CMDLINE_PARTS is not set
@@ -181,6 +217,7 @@ CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_XIP is not set
#
# Mapping drivers for chip access
@@ -200,6 +237,7 @@ CONFIG_MTD_IXP2000=y
# 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
@@ -214,6 +252,11 @@ CONFIG_MTD_IXP2000=y
# CONFIG_MTD_NAND is not set
#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
# Plug and Play support
#
@@ -225,13 +268,31 @@ CONFIG_MTD_IXP2000=y
# CONFIG_BLK_CPQ_CISS_DA is not set
# CONFIG_BLK_DEV_DAC960 is not set
# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_SX8 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_INITRAMFS_SOURCE=""
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
#
# Multi-device support (RAID and LVM)
@@ -239,6 +300,20 @@ CONFIG_BLK_DEV_INITRD=y
# CONFIG_MD is not set
#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
# Networking support
#
CONFIG_NET=y
@@ -265,6 +340,9 @@ CONFIG_SYN_COOKIES=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_IP_TCPDIAG is not set
+# CONFIG_IP_TCPDIAG_IPV6 is not set
# CONFIG_IPV6 is not set
# CONFIG_NETFILTER is not set
@@ -284,8 +362,6 @@ CONFIG_SYN_COOKIES=y
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_FASTROUTE is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
#
# QoS and/or fair queueing
@@ -336,7 +412,6 @@ CONFIG_NET_PCI=y
# CONFIG_FORCEDETH is not set
# CONFIG_DGRS is not set
CONFIG_EEPRO100=y
-# CONFIG_EEPRO100_PIO is not set
# CONFIG_E100 is not set
# CONFIG_FEALNX is not set
# CONFIG_NATSEMI is not set
@@ -348,7 +423,6 @@ CONFIG_EEPRO100=y
# CONFIG_SUNDANCE is not set
# CONFIG_TLAN is not set
# CONFIG_VIA_RHINE is not set
-# CONFIG_VIA_VELOCITY is not set
#
# Ethernet (1000 Mbit)
@@ -361,6 +435,7 @@ CONFIG_EEPRO100=y
# CONFIG_YELLOWFIN is not set
# CONFIG_R8169 is not set
# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
# CONFIG_TIGON3 is not set
#
@@ -410,25 +485,6 @@ CONFIG_DLCI_MAX=8
# CONFIG_NETCONSOLE is not set
#
-# SCSI device support
-#
-# CONFIG_SCSI is not set
-
-#
-# Fusion MPT device support
-#
-
-#
-# IEEE 1394 (FireWire) support
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-
-#
# ISDN subsystem
#
# CONFIG_ISDN is not set
@@ -451,14 +507,6 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
# CONFIG_INPUT_EVBUG is not set
#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-# CONFIG_SERIO is not set
-# CONFIG_SERIO_I8042 is not set
-
-#
# Input Device Drivers
#
# CONFIG_INPUT_KEYBOARD is not set
@@ -468,6 +516,13 @@ CONFIG_SOUND_GAMEPORT=y
# CONFIG_INPUT_MISC is not set
#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
+#
# Character devices
#
# CONFIG_VT is not set
@@ -489,7 +544,6 @@ CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
-# CONFIG_QIC02_TAPE is not set
#
# IPMI
@@ -515,7 +569,6 @@ CONFIG_IXP2000_WATCHDOG=y
# CONFIG_WDTPCI is not set
# CONFIG_NVRAM is not set
# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
@@ -523,11 +576,15 @@ CONFIG_IXP2000_WATCHDOG=y
#
# 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
+
+#
# I2C support
#
CONFIG_I2C=y
@@ -538,6 +595,7 @@ CONFIG_I2C_CHARDEV=y
#
CONFIG_I2C_ALGOBIT=y
# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
#
# I2C Hardware Bus support
@@ -563,6 +621,7 @@ CONFIG_I2C_ALGOBIT=y
# 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
#
# Hardware Sensors Chip support
@@ -570,20 +629,29 @@ CONFIG_I2C_ALGOBIT=y
CONFIG_I2C_SENSOR=y
# CONFIG_SENSORS_ADM1021 is not set
# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ASB100 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
# CONFIG_SENSORS_LM75 is not set
# CONFIG_SENSORS_LM77 is not set
# CONFIG_SENSORS_LM78 is not set
# CONFIG_SENSORS_LM80 is not set
# CONFIG_SENSORS_LM83 is not set
# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
# CONFIG_SENSORS_VIA686A is not set
# CONFIG_SENSORS_W83781D is not set
# CONFIG_SENSORS_W83L785TS is not set
@@ -602,6 +670,10 @@ CONFIG_SENSORS_EEPROM=y
# CONFIG_I2C_DEBUG_CHIP is not set
#
+# Misc devices
+#
+
+#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -612,6 +684,33 @@ CONFIG_SENSORS_EEPROM=y
# 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
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -628,10 +727,15 @@ CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
CONFIG_FS_POSIX_ACL=y
+
+#
+# XFS support
+#
# CONFIG_XFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
@@ -656,6 +760,7 @@ CONFIG_SYSFS=y
# CONFIG_DEVFS_FS is not set
# CONFIG_DEVPTS_FS_XATTR is not set
CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
@@ -673,6 +778,7 @@ CONFIG_RAMFS=y
CONFIG_JFFS2_FS=y
CONFIG_JFFS2_FS_DEBUG=0
# CONFIG_JFFS2_FS_NAND is not set
+# CONFIG_JFFS2_FS_NOR_ECC is not set
# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
CONFIG_JFFS2_ZLIB=y
CONFIG_JFFS2_RTIME=y
@@ -695,9 +801,9 @@ CONFIG_NFS_V3=y
CONFIG_ROOT_NFS=y
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
-# CONFIG_EXPORTFS is not set
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
@@ -735,49 +841,31 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_PROFILING is not set
#
-# Graphics support
-#
-# CONFIG_FB is not set
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# Misc devices
-#
-
-#
-# USB support
-#
-# CONFIG_USB is not set
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
# Kernel hacking
#
-CONFIG_FRAME_POINTER=y
-CONFIG_DEBUG_USER=y
-# CONFIG_DEBUG_INFO is not set
+# CONFIG_PRINTK_TIME is not set
CONFIG_DEBUG_KERNEL=y
-# CONFIG_DEBUG_SLAB is not set
CONFIG_MAGIC_SYSRQ=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_WAITQ 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_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_WAITQ is not set
CONFIG_DEBUG_ERRORS=y
CONFIG_DEBUG_LL=y
# CONFIG_DEBUG_ICEDCC is not set
-# CONFIG_DEBUG_BDI2000_XSCALE is not set
#
# Security options
#
+# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
#
@@ -786,6 +874,10 @@ CONFIG_DEBUG_LL=y
# CONFIG_CRYPTO is not set
#
+# Hardware crypto devices
+#
+
+#
# Library routines
#
# CONFIG_CRC_CCITT is not set
diff --git a/arch/arm/configs/ep80219_defconfig b/arch/arm/configs/ep80219_defconfig
index 2659f0d325091..96342afa9c5f8 100644
--- a/arch/arm/configs/ep80219_defconfig
+++ b/arch/arm/configs/ep80219_defconfig
@@ -1,12 +1,13 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.10
-# Thu Jan 6 10:54:33 2005
+# Linux kernel version: 2.6.12-rc1-bk2
+# Sun Mar 27 22:34:12 2005
#
CONFIG_ARM=y
CONFIG_MMU=y
CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_GENERIC_IOMAP=y
#
@@ -27,13 +28,13 @@ CONFIG_BSD_PROCESS_ACCT=y
# CONFIG_BSD_PROCESS_ACCT_V3 is not set
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
# CONFIG_HOTPLUG is not set
CONFIG_KOBJECT_UEVENT=y
# CONFIG_IKCONFIG is not set
# CONFIG_EMBEDDED is not set
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
@@ -43,6 +44,7 @@ CONFIG_CC_ALIGN_LABELS=0
CONFIG_CC_ALIGN_LOOPS=0
CONFIG_CC_ALIGN_JUMPS=0
# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
#
# Loadable module support
@@ -117,49 +119,75 @@ CONFIG_CPU_MINICACHE=y
CONFIG_XSCALE_PMU=y
#
-# General setup
+# Bus support
#
CONFIG_PCI=y
+# CONFIG_PCI_LEGACY_PROC is not set
+CONFIG_PCI_NAMES=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_PREEMPT is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
CONFIG_ZBOOT_ROM_TEXT=0x0
CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="ip=boot root=nfs console=ttyS0,115200"
# CONFIG_XIP_KERNEL is not set
-# CONFIG_PCI_LEGACY_PROC is not set
-CONFIG_PCI_NAMES=y
#
-# At least one math emulation must be selected
+# 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=y
# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
#
-# Generic Driver Options
+# Power management options
#
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
# CONFIG_PM is not set
-# CONFIG_PREEMPT is not set
-# CONFIG_ARTHUR is not set
-CONFIG_CMDLINE="ip=boot root=nfs console=ttyS0,115200"
-CONFIG_ALIGNMENT_TRAP=y
#
-# Parallel port support
+# Device Drivers
#
-# CONFIG_PARPORT is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
#
# Memory Technology Devices (MTD)
#
CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
-CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
CONFIG_MTD_REDBOOT_PARTS=y
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
CONFIG_MTD_REDBOOT_PARTS_READONLY=y
# CONFIG_MTD_CMDLINE_PARTS is not set
@@ -198,6 +226,7 @@ CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_XIP is not set
#
# Mapping drivers for chip access
@@ -218,6 +247,7 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=2
# 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
@@ -232,6 +262,11 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=2
# CONFIG_MTD_NAND is not set
#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
# Plug and Play support
#
@@ -243,6 +278,7 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=2
# CONFIG_BLK_CPQ_CISS_DA is not set
# CONFIG_BLK_DEV_DAC960 is not set
# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
# CONFIG_BLK_DEV_LOOP is not set
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_SX8 is not set
@@ -260,6 +296,78 @@ CONFIG_IOSCHED_NOOP=y
CONFIG_IOSCHED_AS=y
CONFIG_IOSCHED_DEADLINE=y
CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+CONFIG_CHR_DEV_SG=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_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+CONFIG_SCSI_QLA2XXX=y
+# CONFIG_SCSI_QLA21XX is not set
+# CONFIG_SCSI_QLA22XX is not set
+# CONFIG_SCSI_QLA2300 is not set
+# CONFIG_SCSI_QLA2322 is not set
+# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
#
# Multi-device support (RAID and LVM)
@@ -279,6 +387,22 @@ CONFIG_BLK_DEV_DM=y
# 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
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
#
# Networking support
@@ -381,7 +505,6 @@ CONFIG_NET_PCI=y
# CONFIG_DGRS is not set
# CONFIG_EEPRO100 is not set
CONFIG_E100=y
-CONFIG_E100_NAPI=y
# CONFIG_FEALNX is not set
# CONFIG_NATSEMI is not set
# CONFIG_NE2K_PCI is not set
@@ -437,94 +560,6 @@ CONFIG_E1000_NAPI=y
# CONFIG_NETCONSOLE is not set
#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-CONFIG_SCSI=y
-CONFIG_SCSI_PROC_FS=y
-
-#
-# SCSI support type (disk, tape, CD-ROM)
-#
-CONFIG_BLK_DEV_SD=y
-# CONFIG_CHR_DEV_ST is not set
-# CONFIG_CHR_DEV_OSST is not set
-# CONFIG_BLK_DEV_SR is not set
-CONFIG_CHR_DEV_SG=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_LOGGING is not set
-
-#
-# SCSI Transport Attributes
-#
-# CONFIG_SCSI_SPI_ATTRS is not set
-# CONFIG_SCSI_FC_ATTRS is not set
-
-#
-# SCSI low-level drivers
-#
-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
-# CONFIG_SCSI_3W_9XXX is not set
-# CONFIG_SCSI_ACARD is not set
-# CONFIG_SCSI_AACRAID is not set
-# CONFIG_SCSI_AIC7XXX is not set
-# CONFIG_SCSI_AIC7XXX_OLD is not set
-# CONFIG_SCSI_AIC79XX is not set
-# CONFIG_SCSI_DPT_I2O is not set
-# CONFIG_MEGARAID_NEWGEN is not set
-# CONFIG_MEGARAID_LEGACY is not set
-# CONFIG_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_EATA_PIO is not set
-# CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
-# CONFIG_SCSI_IPS is not set
-# CONFIG_SCSI_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 is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
-# CONFIG_SCSI_QLOGIC_1280 is not set
-CONFIG_SCSI_QLA2XXX=y
-# CONFIG_SCSI_QLA21XX is not set
-# CONFIG_SCSI_QLA22XX is not set
-# CONFIG_SCSI_QLA2300 is not set
-# CONFIG_SCSI_QLA2322 is not set
-# CONFIG_SCSI_QLA6312 is not set
-# CONFIG_SCSI_QLA6322 is not set
-# CONFIG_SCSI_DC395x is not set
-# CONFIG_SCSI_DC390T is not set
-# CONFIG_SCSI_NSP32 is not set
-# CONFIG_SCSI_DEBUG is not set
-
-#
-# 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
-
-#
# ISDN subsystem
#
# CONFIG_ISDN is not set
@@ -547,13 +582,6 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
# CONFIG_INPUT_EVBUG is not set
#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-# CONFIG_SERIO is not set
-
-#
# Input Device Drivers
#
# CONFIG_INPUT_KEYBOARD is not set
@@ -563,6 +591,13 @@ CONFIG_SOUND_GAMEPORT=y
# CONFIG_INPUT_MISC is not set
#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
+#
# Character devices
#
CONFIG_VT=y
@@ -609,6 +644,11 @@ CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_RAW_DRIVER is not set
#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
# I2C support
#
CONFIG_I2C=y
@@ -659,7 +699,9 @@ CONFIG_I2C_IOP3XX=y
# CONFIG_SENSORS_ASB100 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
# CONFIG_SENSORS_IT87 is not set
# CONFIG_SENSORS_LM63 is not set
# CONFIG_SENSORS_LM75 is not set
@@ -672,6 +714,8 @@ CONFIG_I2C_IOP3XX=y
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_SIS5595 is not set
# CONFIG_SENSORS_SMSC47M1 is not set
# CONFIG_SENSORS_VIA686A is not set
# CONFIG_SENSORS_W83781D is not set
@@ -691,6 +735,10 @@ CONFIG_I2C_IOP3XX=y
# CONFIG_I2C_DEBUG_CHIP is not set
#
+# Misc devices
+#
+
+#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -701,6 +749,39 @@ CONFIG_I2C_IOP3XX=y
# 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 is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -714,7 +795,12 @@ CONFIG_JBD=y
CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
CONFIG_XFS_FS=y
+CONFIG_XFS_EXPORT=y
# CONFIG_XFS_RT is not set
# CONFIG_XFS_QUOTA is not set
CONFIG_XFS_SECURITY=y
@@ -765,6 +851,7 @@ CONFIG_RAMFS=y
CONFIG_JFFS2_FS=y
CONFIG_JFFS2_FS_DEBUG=0
# CONFIG_JFFS2_FS_NAND is not set
+# CONFIG_JFFS2_FS_NOR_ECC is not set
# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
CONFIG_JFFS2_ZLIB=y
CONFIG_JFFS2_RTIME=y
@@ -831,51 +918,12 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_PROFILING 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
-
-#
-# Misc devices
-#
-
-#
-# USB support
-#
-# CONFIG_USB is not set
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
-# CONFIG_MMC is not set
-
-#
# Kernel hacking
#
+# CONFIG_PRINTK_TIME is not set
# CONFIG_DEBUG_KERNEL is not set
-# CONFIG_DEBUG_INFO is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_FRAME_POINTER=y
CONFIG_DEBUG_USER=y
@@ -891,6 +939,10 @@ CONFIG_DEBUG_USER=y
# CONFIG_CRYPTO is not set
#
+# Hardware crypto devices
+#
+
+#
# Library routines
#
# CONFIG_CRC_CCITT is not set
diff --git a/arch/arm/configs/epxa10db_defconfig b/arch/arm/configs/epxa10db_defconfig
index d649de5908ba2..9fb8b58c4954d 100644
--- a/arch/arm/configs/epxa10db_defconfig
+++ b/arch/arm/configs/epxa10db_defconfig
@@ -1,37 +1,49 @@
#
# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.12-rc1-bk2
+# Sun Mar 27 22:46: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
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
CONFIG_CLEAN_COMPILE=y
-CONFIG_STANDALONE=y
CONFIG_BROKEN_ON_SMP=y
#
# General setup
#
+CONFIG_LOCALVERSION=""
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
-CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_AUDIT is not set
# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
# CONFIG_IKCONFIG is not set
# CONFIG_EMBEDDED is not set
CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
#
# Loadable module support
@@ -41,30 +53,33 @@ 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_ADIFCC is not set
-# CONFIG_ARCH_ANAKIN is not set
# CONFIG_ARCH_CLPS7500 is not set
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
-# CONFIG_ARCH_PXA 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
-
-#
-# CLPS711X/EP721X Implementations
-#
+# 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
@@ -77,28 +92,6 @@ CONFIG_PLD=y
# CONFIG_PLD_HOTSWAP is not set
#
-# Footbridge Implementations
-#
-
-#
-# IOP3xx Implementation Options
-#
-# CONFIG_ARCH_IOP310 is not set
-# CONFIG_ARCH_IOP321 is not set
-
-#
-# IOP3xx Chipset Features
-#
-
-#
-# Intel PXA250/210 Implementations
-#
-
-#
-# SA11x0 Implementations
-#
-
-#
# Processor Type
#
CONFIG_CPU_32=y
@@ -106,6 +99,7 @@ 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
@@ -118,35 +112,62 @@ CONFIG_CPU_TLB_V4WBI=y
# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
#
-# General setup
+# Bus support
+#
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_PREEMPT is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
#
-# CONFIG_ZBOOT_ROM is not set
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
#
-# At least one math emulation must be selected
+# 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
#
-# Generic Driver Options
+# Power management options
#
# CONFIG_PM is not set
-# CONFIG_PREEMPT is not set
-# CONFIG_ARTHUR is not set
-CONFIG_CMDLINE="mem=32M console=ttyUA0,115200 initrd=0x00200000,8M root=/dev/ram0 rw"
-CONFIG_ALIGNMENT_TRAP=y
#
-# Parallel port support
+# Device Drivers
#
-# CONFIG_PARPORT is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
#
# Memory Technology Devices (MTD)
@@ -154,6 +175,11 @@ CONFIG_ALIGNMENT_TRAP=y
# CONFIG_MTD is not set
#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
# Plug and Play support
#
@@ -161,12 +187,30 @@ CONFIG_ALIGNMENT_TRAP=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_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=8192
CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
#
# Multi-device support (RAID and LVM)
@@ -174,6 +218,18 @@ CONFIG_BLK_DEV_INITRD=y
# CONFIG_MD is not set
#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
# Networking support
#
CONFIG_NET=y
@@ -197,23 +253,24 @@ CONFIG_IP_PNP=y
# CONFIG_NET_IPGRE is not set
# CONFIG_IP_MROUTE is not set
# CONFIG_ARPD is not set
-# CONFIG_INET_ECN is not set
# CONFIG_SYN_COOKIES is not set
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
+# 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_DECNET is not set
-# CONFIG_BRIDGE is not set
# CONFIG_NETFILTER is not set
#
# SCTP Configuration (EXPERIMENTAL)
#
-CONFIG_IPV6_SCTP__=y
# CONFIG_IP_SCTP is not set
# CONFIG_ATM is not set
+# CONFIG_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
@@ -222,17 +279,22 @@ CONFIG_IPV6_SCTP__=y
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
#
# QoS and/or fair queueing
#
# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
#
# Network testing
#
# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
CONFIG_NETDEVICES=y
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
@@ -251,68 +313,31 @@ CONFIG_NETDEVICES=y
#
# Ethernet (10000 Mbit)
#
-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_SLIP is not set
#
-# Wireless LAN (non-hamradio)
+# Token Ring devices
#
-# CONFIG_NET_RADIO is not set
#
-# Token Ring devices
+# Wireless LAN (non-hamradio)
#
-# CONFIG_SHAPER is not set
+# CONFIG_NET_RADIO is not set
#
# Wan interfaces
#
# CONFIG_WAN is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
-# Bluetooth support
-#
-# CONFIG_BT is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-# CONFIG_SCSI is not set
-
-#
-# Fusion MPT device support
-#
-
-#
-# IEEE 1394 (FireWire) support
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
+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_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
#
# ISDN subsystem
@@ -337,16 +362,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=y
-# CONFIG_SERIO_CT82C710 is not set
-
-#
# Input Device Drivers
#
# CONFIG_INPUT_KEYBOARD is not set
@@ -356,6 +371,15 @@ CONFIG_SERIO_SERPORT=y
# CONFIG_INPUT_MISC is not set
#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
+#
# Character devices
#
CONFIG_VT=y
@@ -380,12 +404,6 @@ CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_QIC02_TAPE is not set
-
-#
# IPMI
#
# CONFIG_IPMI_HANDLER is not set
@@ -396,25 +414,30 @@ CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_WATCHDOG is not set
# CONFIG_NVRAM is not set
# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
#
# Ftape, the floppy tape device driver
#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
# CONFIG_DRM is not set
# CONFIG_RAW_DRIVER is not set
#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
# I2C support
#
# CONFIG_I2C is not set
#
+# Misc devices
+#
+
+#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -425,6 +448,39 @@ CONFIG_LEGACY_PTY_COUNT=256
# 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 is not set
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -433,10 +489,15 @@ CONFIG_EXT2_FS=y
# CONFIG_JBD is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
# CONFIG_XFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
CONFIG_AUTOFS_FS=y
CONFIG_AUTOFS4_FS=y
@@ -449,13 +510,15 @@ CONFIG_AUTOFS4_FS=y
#
# DOS/FAT/NT Filesystems
#
-# CONFIG_FAT_FS is not set
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
# CONFIG_NTFS_FS is not set
#
# Pseudo filesystems
#
CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
# CONFIG_DEVFS_FS is not set
# CONFIG_DEVPTS_FS_XATTR is not set
# CONFIG_TMPFS is not set
@@ -484,7 +547,6 @@ CONFIG_RAMFS=y
#
# CONFIG_NFS_FS is not set
# CONFIG_NFSD is not set
-# CONFIG_EXPORTFS is not set
CONFIG_SMB_FS=y
# CONFIG_SMB_NLS_DEFAULT is not set
# CONFIG_CIFS is not set
@@ -496,6 +558,7 @@ CONFIG_SMB_FS=y
# Partition Types
#
# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
#
# Native Language Support
@@ -525,6 +588,7 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_NLS_ISO8859_8 is not set
# CONFIG_NLS_CODEPAGE_1250 is not set
# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
# CONFIG_NLS_ISO8859_1 is not set
# CONFIG_NLS_ISO8859_2 is not set
# CONFIG_NLS_ISO8859_3 is not set
@@ -546,41 +610,19 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_PROFILING is not set
#
-# Graphics support
-#
-# CONFIG_FB is not set
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_MDA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-
-#
-# Misc devices
-#
-
-#
-# USB support
-#
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
# Kernel hacking
#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_FRAME_POINTER=y
# CONFIG_DEBUG_USER is not set
-# CONFIG_DEBUG_INFO is not set
-# CONFIG_DEBUG_KERNEL is not set
#
# Security options
#
+# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
#
@@ -589,8 +631,14 @@ CONFIG_FRAME_POINTER=y
# CONFIG_CRYPTO is not set
#
+# Hardware crypto devices
+#
+
+#
# Library routines
#
+CONFIG_CRC_CCITT=y
CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/arm/configs/footbridge_defconfig b/arch/arm/configs/footbridge_defconfig
index 04c4485e133b2..9737c48507210 100644
--- a/arch/arm/configs/footbridge_defconfig
+++ b/arch/arm/configs/footbridge_defconfig
@@ -1,101 +1,186 @@
#
# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.12-rc1-bk2
+# Sun Mar 27 23:02:24 2005
#
CONFIG_ARM=y
-# CONFIG_EISA is not set
-# CONFIG_SBUS is not set
-# CONFIG_MCA is not set
+CONFIG_MMU=y
CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_IOMAP=y
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-# CONFIG_OBSOLETE is not set
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
#
# Loadable module support
#
CONFIG_MODULES=y
+# CONFIG_MODULE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_KMOD=y
#
# System Type
#
-# CONFIG_ARCH_ARCA5K is not set
# 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=y
# 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_CLPS711X is not set
-
-#
-# Archimedes/A5000 Implementations
-#
+# 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
#
# Footbridge Implementations
#
-# CONFIG_ARCH_CATS is not set
-# CONFIG_ARCH_PERSONAL_SERVER is not set
+CONFIG_ARCH_CATS=y
+CONFIG_ARCH_PERSONAL_SERVER=y
# CONFIG_ARCH_EBSA285_ADDIN is not set
CONFIG_ARCH_EBSA285_HOST=y
CONFIG_ARCH_NETWINDER=y
-
-#
-# SA11x0 Implementations
-#
-
-#
-# CLPS711X/EP721X Implementations
-#
-# CONFIG_ARCH_ACORN is not set
CONFIG_FOOTBRIDGE=y
CONFIG_FOOTBRIDGE_HOST=y
-# CONFIG_FOOTBRIDGE_ADDIN is not set
CONFIG_ARCH_EBSA285=y
-CONFIG_CPU_32=y
-# CONFIG_CPU_26 is not set
#
# Processor Type
#
-CONFIG_CPU_32v4=y
+CONFIG_CPU_32=y
CONFIG_CPU_SA110=y
-# CONFIG_DISCONTIGMEM is not set
+CONFIG_CPU_32v4=y
+CONFIG_CPU_ABRT_EV4=y
+CONFIG_CPU_CACHE_V4WB=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WB=y
#
-# General setup
+# Processor Features
+#
+
+#
+# Bus support
#
-# CONFIG_ANGELBOOT is not set
-CONFIG_PCI=y
CONFIG_ISA=y
CONFIG_ISA_DMA=y
+CONFIG_PCI=y
+# CONFIG_PCI_LEGACY_PROC is not set
CONFIG_PCI_NAMES=y
-# CONFIG_HOTPLUG is not set
-# CONFIG_PCMCIA is not set
-CONFIG_NET=y
-CONFIG_SYSVIPC=y
-CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_SYSCTL=y
-CONFIG_NWFPE=y
-CONFIG_KCORE_ELF=y
-# CONFIG_KCORE_AOUT is not set
-CONFIG_BINFMT_AOUT=y
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-# CONFIG_PM is not set
-# CONFIG_ARTHUR is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_PREEMPT is not set
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=""
+# CONFIG_XIP_KERNEL is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+CONFIG_FPE_NWFPE_XP=y
+# CONFIG_FPE_FASTFPE is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_AOUT=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
# Parallel port support
#
CONFIG_PARPORT=y
@@ -103,22 +188,18 @@ CONFIG_PARPORT_PC=y
CONFIG_PARPORT_PC_FIFO=y
# CONFIG_PARPORT_PC_SUPERIO is not set
# CONFIG_PARPORT_ARC is not set
-# CONFIG_PARPORT_AMIGA is not set
-# CONFIG_PARPORT_MFC3 is not set
-# CONFIG_PARPORT_ATARI is not set
-# CONFIG_PARPORT_SUNBPP is not set
-# CONFIG_PARPORT_OTHER is not set
+# CONFIG_PARPORT_GSC is not set
CONFIG_PARPORT_1284=y
#
-# Memory Technology Devices (MTD)
+# Plug and Play support
#
-# CONFIG_MTD is not set
+CONFIG_PNP=y
+# CONFIG_PNP_DEBUG is not set
#
-# Plug and Play configuration
+# Protocols
#
-CONFIG_PNP=y
CONFIG_ISAPNP=y
#
@@ -143,11 +224,13 @@ CONFIG_PARIDE_PG=m
#
CONFIG_PARIDE_ATEN=m
CONFIG_PARIDE_BPCK=m
+# CONFIG_PARIDE_BPCK6 is not set
CONFIG_PARIDE_COMM=m
CONFIG_PARIDE_DSTR=m
CONFIG_PARIDE_FIT2=m
CONFIG_PARIDE_FIT3=m
CONFIG_PARIDE_EPAT=m
+# CONFIG_PARIDE_EPATC8 is not set
CONFIG_PARIDE_EPIA=m
CONFIG_PARIDE_FRIQ=m
CONFIG_PARIDE_FRPW=m
@@ -158,67 +241,202 @@ CONFIG_PARIDE_ON26=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=m
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
CONFIG_BLK_DEV_NBD=m
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# 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=y
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+# CONFIG_BLK_DEV_IDEPNP is not set
+# CONFIG_BLK_DEV_IDEPCI is not set
+# CONFIG_IDE_ARM is not set
+# CONFIG_IDE_CHIPSETS is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
#
# Networking options
#
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
-# CONFIG_NETLINK is not set
-# CONFIG_NETFILTER is not set
-# CONFIG_FILTER is not set
+# CONFIG_NETLINK_DEV is not set
CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
# CONFIG_IP_ADVANCED_ROUTER is not set
CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
CONFIG_IP_PNP_BOOTP=y
# CONFIG_IP_PNP_RARP is not set
# CONFIG_NET_IPIP is not set
# CONFIG_NET_IPGRE is not set
# CONFIG_IP_MROUTE is not set
-# CONFIG_INET_ECN is not set
+# CONFIG_ARPD is not set
CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_IP_TCPDIAG is not set
+# CONFIG_IP_TCPDIAG_IPV6 is not set
# CONFIG_IPV6 is not set
-# CONFIG_KHTTPD is not set
-CONFIG_ATM=y
-# CONFIG_ATM_CLIP is not set
-# CONFIG_ATM_LANE is not set
+# CONFIG_NETFILTER is not set
#
-#
+# SCTP Configuration (EXPERIMENTAL)
#
+# CONFIG_IP_SCTP is not set
+CONFIG_ATM=y
+# CONFIG_ATM_CLIP is not set
+# CONFIG_ATM_LANE is not set
+# CONFIG_ATM_BR2684 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_DECNET is not set
-# CONFIG_BRIDGE is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-# CONFIG_LLC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
#
# QoS and/or fair queueing
#
# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
#
-# Network device support
+# Network testing
#
-CONFIG_NETDEVICES=y
+# 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=m
#
-# ARCnet devices
+# IrDA protocols
#
-# CONFIG_ARCNET is not set
+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=y
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+# CONFIG_IRTTY_SIR is not set
+
+#
+# Dongle support
+#
+
+#
+# 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=m
+# CONFIG_TOSHIBA_FIR is not set
+# CONFIG_SMC_IRCC_FIR is not set
+# CONFIG_ALI_FIR is not set
+# CONFIG_VLSI_FIR is not set
+# CONFIG_VIA_FIR is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
@@ -226,9 +444,17 @@ CONFIG_NETDEVICES=y
# CONFIG_NET_SB1000 is not set
#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
# Ethernet (10 or 100Mbit)
#
CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
CONFIG_NET_VENDOR_3COM=y
# CONFIG_EL1 is not set
# CONFIG_EL2 is not set
@@ -236,301 +462,252 @@ CONFIG_NET_VENDOR_3COM=y
# CONFIG_EL16 is not set
# CONFIG_EL3 is not set
# CONFIG_3C515 is not set
-# CONFIG_ELMC is not set
-# CONFIG_ELMC_II is not set
CONFIG_VORTEX=y
+# CONFIG_TYPHOON is not set
# CONFIG_LANCE is not set
# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_SMC91X is not set
# CONFIG_NET_VENDOR_RACAL is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
# CONFIG_AT1700 is not set
# CONFIG_DEPCA is not set
# CONFIG_HP100 is not set
# CONFIG_NET_ISA is not set
CONFIG_NET_PCI=y
# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
# CONFIG_ADAPTEC_STARFIRE is not set
# CONFIG_AC3200 is not set
# CONFIG_APRICOT is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
# CONFIG_CS89x0 is not set
-CONFIG_TULIP=m
-# CONFIG_DE4X5 is not set
# CONFIG_DGRS is not set
-# CONFIG_DM9102 is not set
# CONFIG_EEPRO100 is not set
-# CONFIG_EEPRO100_PM is not set
-# CONFIG_LNE390 is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
# CONFIG_NATSEMI is not set
CONFIG_NE2K_PCI=y
-# CONFIG_NE3210 is not set
-# CONFIG_ES3210 is not set
+# CONFIG_8139CP is not set
# CONFIG_8139TOO is not set
-# CONFIG_RTL8129 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_WINBOND_840 is not set
-# CONFIG_HAPPYMEAL is not set
# CONFIG_NET_POCKET is not set
#
# Ethernet (1000 Mbit)
#
# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
# CONFIG_SK98LIN is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PLIP is not set
-CONFIG_PPP=m
-# CONFIG_PPP_MULTILINK is not set
-CONFIG_PPP_ASYNC=m
-# CONFIG_PPP_SYNC_TTY is not set
-CONFIG_PPP_DEFLATE=m
-CONFIG_PPP_BSDCOMP=m
-CONFIG_PPPOE=m
-CONFIG_SLIP=m
-CONFIG_SLIP_COMPRESSED=y
-CONFIG_SLIP_SMART=y
-CONFIG_SLIP_MODE_SLIP6=y
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
#
-# Wireless LAN (non-hamradio)
+# Ethernet (10000 Mbit)
#
-# CONFIG_NET_RADIO is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
#
# Token Ring devices
#
# CONFIG_TR is not set
-# CONFIG_NET_FC is not set
-# CONFIG_RCPCI is not set
-# CONFIG_SHAPER is not set
#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-CONFIG_IRDA=m
-
-#
-# IrDA protocols
-#
-CONFIG_IRLAN=m
-CONFIG_IRNET=m
-CONFIG_IRCOMM=m
-CONFIG_IRDA_ULTRA=y
-CONFIG_IRDA_OPTIONS=y
-
-#
-# IrDA options
-#
-CONFIG_IRDA_CACHE_LAST_LSAP=y
-CONFIG_IRDA_FAST_RR=y
-CONFIG_IRDA_DEBUG=y
-
-#
-# Infrared-port device drivers
-#
-
-#
-# SIR device drivers
-#
-# CONFIG_IRTTY_SIR is not set
-# CONFIG_IRPORT_SIR is not set
-
-#
-# FIR device drivers
-#
-# CONFIG_NSC_FIR is not set
-CONFIG_WINBOND_FIR=m
-# CONFIG_TOSHIBA_FIR is not set
-# CONFIG_SMC_IRCC_FIR is not set
-
-#
-# Dongle support
-#
-# CONFIG_DONGLE is not set
-
-#
-# ATA/IDE/MFM/RLL support
-#
-CONFIG_IDE=y
-
-#
-# IDE, ATA and ATAPI Block devices
+# Wireless LAN (non-hamradio)
#
-CONFIG_BLK_DEV_IDE=y
+# CONFIG_NET_RADIO is not set
#
-# Please see Documentation/ide.txt for help/info on IDE drives
+# Wan interfaces
#
-# CONFIG_BLK_DEV_HD_IDE is not set
-# CONFIG_BLK_DEV_HD is not set
-CONFIG_BLK_DEV_IDEDISK=y
-CONFIG_IDEDISK_MULTI_MODE=y
-# 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
-# CONFIG_BLK_DEV_IDESCSI is not set
+# CONFIG_WAN is not set
#
-# IDE chipset support/bugfixes
-#
-# CONFIG_BLK_DEV_CMD640 is not set
-# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
-# CONFIG_BLK_DEV_ISAPNP is not set
-# CONFIG_BLK_DEV_RZ1000 is not set
-CONFIG_IDEPCI_SHARE_IRQ=y
-CONFIG_BLK_DEV_IDEDMA_PCI=y
-CONFIG_BLK_DEV_OFFBOARD=y
-CONFIG_IDEDMA_PCI_AUTO=y
-CONFIG_BLK_DEV_IDEDMA=y
-# CONFIG_BLK_DEV_AEC62XX is not set
-# CONFIG_AEC62XX_TUNING is not set
-# CONFIG_BLK_DEV_ALI15X3 is not set
-# CONFIG_WDC_ALI15X3 is not set
-# CONFIG_BLK_DEV_AMD7409 is not set
-# CONFIG_AMD7409_OVERRIDE is not set
-# CONFIG_BLK_DEV_CMD64X is not set
-CONFIG_BLK_DEV_CY82C693=y
-# CONFIG_BLK_DEV_CS5530 is not set
-# CONFIG_BLK_DEV_HPT34X is not set
-# CONFIG_HPT34X_AUTODMA is not set
-# CONFIG_BLK_DEV_HPT366 is not set
-# CONFIG_BLK_DEV_NS87415 is not set
-# CONFIG_BLK_DEV_OPTI621 is not set
-# CONFIG_PDC202XX_BURST is not set
-# CONFIG_BLK_DEV_OSB4 is not set
-# CONFIG_BLK_DEV_SIS5513 is not set
-# CONFIG_BLK_DEV_TRM290 is not set
-# CONFIG_BLK_DEV_VIA82CXXX is not set
-CONFIG_BLK_DEV_SL82C105=y
-# CONFIG_IDE_CHIPSETS is not set
-CONFIG_IDEDMA_AUTO=y
-# CONFIG_IDEDMA_IVB is not set
+# ATM drivers
+#
+# CONFIG_ATM_TCP is not set
+# 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_NICSTAR is not set
+# CONFIG_ATM_IDT77252 is not set
+# CONFIG_ATM_AMBASSADOR is not set
+# CONFIG_ATM_HORIZON is not set
+# CONFIG_ATM_IA is not set
+# CONFIG_ATM_FORE200E_MAYBE is not set
+# CONFIG_ATM_HE is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PLIP is not set
+CONFIG_PPP=m
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+# CONFIG_PPP_SYNC_TTY is not set
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPPOE=m
+# CONFIG_PPPOATM is not set
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLIP_SMART=y
+CONFIG_SLIP_MODE_SLIP6=y
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
#
-# SCSI support
+# ISDN subsystem
#
-# CONFIG_SCSI is not set
+# CONFIG_ISDN is not set
#
-# IEEE 1394 (FireWire) support
+# Input device support
#
-# CONFIG_IEEE1394 is not set
+CONFIG_INPUT=y
#
-# I2O device support
+# Userland interfaces
#
-# CONFIG_I2O is not set
-# CONFIG_I2O_PCI is not set
-# CONFIG_I2O_BLOCK is not set
-# CONFIG_I2O_LAN is not set
-# CONFIG_I2O_SCSI is not set
-# CONFIG_I2O_PROC is not set
+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
#
-# ISDN subsystem
+# Input Device Drivers
#
-# CONFIG_ISDN is not set
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_INPORT is not set
+# CONFIG_MOUSE_LOGIBM is not set
+# CONFIG_MOUSE_PC110PAD is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
#
-# Input core support
+# Hardware I/O ports
#
-# CONFIG_INPUT is not set
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_PARKBD is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
#
# Character devices
#
CONFIG_VT=y
CONFIG_VT_CONSOLE=y
-CONFIG_SERIAL=y
-CONFIG_SERIAL_CONSOLE=y
-# CONFIG_SERIAL_EXTENDED is not set
+CONFIG_HW_CONSOLE=y
CONFIG_SERIAL_NONSTANDARD=y
# CONFIG_COMPUTONE is not set
# CONFIG_ROCKETPORT is not set
# CONFIG_CYCLADES is not set
# CONFIG_DIGIEPCA is not set
-# CONFIG_DIGI is not set
# CONFIG_ESPSERIAL is not set
# CONFIG_MOXA_INTELLIO is not set
# CONFIG_MOXA_SMARTIO is not set
# CONFIG_ISI is not set
# CONFIG_SYNCLINK is not set
+# CONFIG_SYNCLINKMP is not set
# CONFIG_N_HDLC is not set
# CONFIG_RISCOM8 is not set
# CONFIG_SPECIALIX is not set
# CONFIG_SX is not set
# CONFIG_RIO is not set
# CONFIG_STALDRV is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
CONFIG_SERIAL_21285=y
CONFIG_SERIAL_21285_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
CONFIG_PRINTER=m
# CONFIG_LP_CONSOLE is not set
# CONFIG_PPDEV is not set
+# CONFIG_TIPAR is not set
#
-# I2C support
+# IPMI
#
-CONFIG_I2C=m
-# CONFIG_I2C_ALGOBIT is not set
-# CONFIG_I2C_ALGOPCF is not set
-# CONFIG_I2C_CHARDEV is not set
+# CONFIG_IPMI_HANDLER is not set
#
-# Mice
+# Watchdog Cards
#
-# CONFIG_BUSMOUSE is not set
-CONFIG_MOUSE=y
-CONFIG_PSMOUSE=y
-# CONFIG_82C710_MOUSE is not set
-# CONFIG_PC110_PAD is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
#
-# Joysticks
+# Watchdog Device Drivers
#
-# CONFIG_JOYSTICK is not set
+CONFIG_SOFT_WATCHDOG=y
+CONFIG_21285_WATCHDOG=m
+CONFIG_977_WATCHDOG=m
#
-# Input core support is needed for joysticks
+# ISA-based Watchdog Cards
#
-# CONFIG_QIC02_TAPE is not set
+# CONFIG_PCWATCHDOG is not set
+# CONFIG_MIXCOMWD is not set
+# CONFIG_WDT is not set
#
-# Watchdog Cards
+# PCI-based Watchdog Cards
#
-CONFIG_WATCHDOG=y
-# CONFIG_WATCHDOG_NOWAYOUT is not set
-CONFIG_SOFT_WATCHDOG=y
-# CONFIG_WDT is not set
+# CONFIG_PCIPCWATCHDOG is not set
# CONFIG_WDTPCI is not set
-# CONFIG_PCWATCHDOG is not set
-# CONFIG_ACQUIRE_WDT is not set
-# CONFIG_60XX_WDT is not set
-# CONFIG_MIXCOMWD is not set
-CONFIG_21285_WATCHDOG=m
-CONFIG_977_WATCHDOG=m
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
CONFIG_DS1620=y
CONFIG_NWBUTTON=y
CONFIG_NWBUTTON_REBOOT=y
CONFIG_NWFLASH=m
-# CONFIG_INTEL_RNG is not set
CONFIG_NVRAM=m
CONFIG_RTC=y
# CONFIG_DTLK is not set
@@ -540,9 +717,104 @@ CONFIG_RTC=y
#
# Ftape, the floppy tape device driver
#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=m
+# CONFIG_I2C_CHARDEV is not set
+
+#
+# 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_ELEKTOR is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_ISA is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_PARPORT is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_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
+
+#
+# Hardware Sensors Chip support
+#
+# CONFIG_I2C_SENSOR is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+
+#
+# Other I2C Chip support
+#
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
#
# Multimedia devices
@@ -552,23 +824,27 @@ CONFIG_VIDEO_DEV=m
#
# Video For Linux
#
-CONFIG_VIDEO_PROC_FS=y
-# CONFIG_I2C_PARPORT is not set
#
# Video Adapters
#
+# CONFIG_VIDEO_BT848 is not set
# CONFIG_VIDEO_PMS is not set
# CONFIG_VIDEO_BWQCAM is not set
# CONFIG_VIDEO_CQCAM is not set
+# CONFIG_VIDEO_W9966 is not set
# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_SAA5246A is not set
# CONFIG_VIDEO_SAA5249 is not set
# CONFIG_TUNER_3036 is not set
# CONFIG_VIDEO_STRADIS is not set
-# CONFIG_VIDEO_ZORAN is not set
-# CONFIG_VIDEO_BUZ is not set
-# CONFIG_VIDEO_ZR36120 is not set
-CONFIG_VIDEO_CYBERPRO=m
+# CONFIG_VIDEO_SAA7134 is not set
+# CONFIG_VIDEO_MXB is not set
+# CONFIG_VIDEO_DPC is not set
+# CONFIG_VIDEO_HEXIUM_ORION is not set
+# CONFIG_VIDEO_HEXIUM_GEMINI is not set
+# CONFIG_VIDEO_CX88 is not set
+# CONFIG_VIDEO_OVCAMCHIP is not set
#
# Radio Adapters
@@ -578,85 +854,306 @@ CONFIG_VIDEO_CYBERPRO=m
# CONFIG_RADIO_RTRACK2 is not set
# CONFIG_RADIO_AZTECH is not set
# CONFIG_RADIO_GEMTEK is not set
+# CONFIG_RADIO_GEMTEK_PCI is not set
+# CONFIG_RADIO_MAXIRADIO is not set
# CONFIG_RADIO_MAESTRO is not set
-# CONFIG_RADIO_MIROPCM20 is not set
# CONFIG_RADIO_SF16FMI is not set
+# CONFIG_RADIO_SF16FMR2 is not set
# CONFIG_RADIO_TERRATEC is not set
# CONFIG_RADIO_TRUST is not set
# CONFIG_RADIO_TYPHOON is not set
# CONFIG_RADIO_ZOLTRIX is not set
#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+CONFIG_FB_SOFT_CURSOR=y
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+CONFIG_FB_CYBER2000=y
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT 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 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_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE is not set
+
+#
+# Logo configuration
+#
+# CONFIG_LOGO is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+# CONFIG_SND 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=m
+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_EHCI_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_AUDIO=m
+# CONFIG_USB_BLUETOOTH_TTY is not set
+# CONFIG_USB_MIDI is not set
+# CONFIG_USB_ACM is not set
+CONFIG_USB_PRINTER=m
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+# 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_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 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 is not set
+# CONFIG_USB_STV680 is not set
+# CONFIG_USB_PWC is not set
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+CONFIG_USB_MON=m
+
+#
+# USB port drivers
+#
+# CONFIG_USB_USS720 is not set
+
+#
+# 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_TEST is not set
+
+#
+# USB ATM/DSL drivers
+#
+# CONFIG_USB_ATM is not set
+# CONFIG_USB_SPEEDTOUCH is not set
+
+#
+# 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_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_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
CONFIG_AUTOFS4_FS=y
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+# CONFIG_ZISOFS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
CONFIG_ADFS_FS=m
# CONFIG_ADFS_FS_RW 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_FAT_FS=m
-CONFIG_MSDOS_FS=m
-# CONFIG_UMSDOS_FS is not set
-CONFIG_VFAT_FS=m
# CONFIG_EFS_FS is not set
-# CONFIG_JFFS_FS is not set
# CONFIG_CRAMFS is not set
-# CONFIG_RAMFS is not set
-CONFIG_ISO9660_FS=m
-CONFIG_JOLIET=y
-# CONFIG_MINIX_FS is not set
-# CONFIG_NTFS_FS is not set
-# CONFIG_NTFS_DEBUG is not set
-# CONFIG_NTFS_RW is not set
+# CONFIG_VXFS_FS is not set
# CONFIG_HPFS_FS is not set
-CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
-# CONFIG_DEVFS_MOUNT is not set
-# CONFIG_DEVFS_DEBUG is not set
-CONFIG_DEVPTS_FS=y
# CONFIG_QNX4FS_FS is not set
-# CONFIG_QNX4FS_RW is not set
-# CONFIG_ROMFS_FS is not set
-CONFIG_EXT2_FS=y
# CONFIG_SYSV_FS is not set
-# CONFIG_SYSV_FS_WRITE is not set
-# CONFIG_UDF_FS is not set
-# CONFIG_UDF_RW is not set
# CONFIG_UFS_FS is not set
-# CONFIG_UFS_FS_WRITE is not set
#
# Network File Systems
#
-# CONFIG_CODA_FS is not set
CONFIG_NFS_FS=y
# CONFIG_NFS_V3 is not set
-CONFIG_ROOT_NFS=y
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
CONFIG_NFSD=m
# CONFIG_NFSD_V3 is not set
-CONFIG_SUNRPC=y
+CONFIG_NFSD_TCP=y
+CONFIG_ROOT_NFS=y
CONFIG_LOCKD=y
+CONFIG_EXPORTFS=m
+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_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_MOUNT_SUBDIR is not set
-# CONFIG_NCPFS_NDS_DOMAINS is not set
-# CONFIG_NCPFS_NLS is not set
-# CONFIG_NCPFS_EXTRAS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
#
# Partition Types
#
CONFIG_PARTITION_ADVANCED=y
CONFIG_ACORN_PARTITION=y
+# CONFIG_ACORN_PARTITION_CUMANA is not set
+# CONFIG_ACORN_PARTITION_EESOX is not set
# CONFIG_ACORN_PARTITION_ICS is not set
CONFIG_ACORN_PARTITION_ADFS=y
# CONFIG_ACORN_PARTITION_POWERTEC is not set
@@ -667,16 +1164,19 @@ CONFIG_ACORN_PARTITION_ADFS=y
# CONFIG_MAC_PARTITION is not set
CONFIG_MSDOS_PARTITION=y
# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
# CONFIG_SOLARIS_X86_PARTITION is not set
# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
# CONFIG_SGI_PARTITION is not set
# CONFIG_ULTRIX_PARTITION is not set
# CONFIG_SUN_PARTITION is not set
-CONFIG_NLS=y
+# 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
@@ -693,11 +1193,15 @@ CONFIG_NLS_CODEPAGE_852=m
# CONFIG_NLS_CODEPAGE_865 is not set
# CONFIG_NLS_CODEPAGE_866 is not set
# CONFIG_NLS_CODEPAGE_869 is not set
-# CONFIG_NLS_CODEPAGE_874 is not set
-# CONFIG_NLS_CODEPAGE_932 is not set
# CONFIG_NLS_CODEPAGE_936 is not set
-# CONFIG_NLS_CODEPAGE_949 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=m
# CONFIG_NLS_ISO8859_3 is not set
@@ -705,173 +1209,49 @@ CONFIG_NLS_ISO8859_2=m
# CONFIG_NLS_ISO8859_5 is not set
# CONFIG_NLS_ISO8859_6 is not set
# CONFIG_NLS_ISO8859_7 is not set
-# CONFIG_NLS_ISO8859_8 is not set
# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
# CONFIG_NLS_ISO8859_14 is not set
CONFIG_NLS_ISO8859_15=m
# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
# CONFIG_NLS_UTF8 is not set
#
-# Console drivers
-#
-CONFIG_PC_KEYB=y
-CONFIG_PC_KEYMAP=y
-CONFIG_VGA_CONSOLE=y
-CONFIG_FB=y
-
-#
-# Frame-buffer support
-#
-CONFIG_FB=y
-CONFIG_DUMMY_CONSOLE=y
-# CONFIG_FB_RIVA is not set
-# CONFIG_FB_CLGEN is not set
-# CONFIG_FB_PM2 is not set
-# CONFIG_FB_ACORN is not set
-# CONFIG_FB_CLPS711X is not set
-CONFIG_FB_CYBER2000=y
-# CONFIG_FB_SA1100 is not set
-# CONFIG_FB_MATROX is not set
-# CONFIG_FB_ATY is not set
-# CONFIG_FB_ATY128 is not set
-# CONFIG_FB_3DFX is not set
-# CONFIG_FB_SIS is not set
-# CONFIG_FB_VIRTUAL is not set
-CONFIG_FBCON_ADVANCED=y
-# CONFIG_FBCON_MFB is not set
-# CONFIG_FBCON_CFB2 is not set
-# CONFIG_FBCON_CFB4 is not set
-CONFIG_FBCON_CFB8=y
-CONFIG_FBCON_CFB16=y
-CONFIG_FBCON_CFB24=y
-# CONFIG_FBCON_CFB32 is not set
-# CONFIG_FBCON_AFB is not set
-# CONFIG_FBCON_ILBM is not set
-# CONFIG_FBCON_IPLAN2P2 is not set
-# CONFIG_FBCON_IPLAN2P4 is not set
-# CONFIG_FBCON_IPLAN2P8 is not set
-# CONFIG_FBCON_MAC is not set
-# CONFIG_FBCON_VGA_PLANES is not set
-CONFIG_FBCON_VGA=y
-# CONFIG_FBCON_HGA is not set
-# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
-CONFIG_FBCON_FONTS=y
-# CONFIG_FONT_8x8 is not set
-# CONFIG_FONT_8x16 is not set
-# CONFIG_FONT_SUN8x16 is not set
-# CONFIG_FONT_SUN12x22 is not set
-# CONFIG_FONT_6x11 is not set
-# CONFIG_FONT_PEARL_8x8 is not set
-CONFIG_FONT_ACORN_8x8=y
-
-#
-# Sound
-#
-CONFIG_SOUND=m
-# CONFIG_SOUND_CMPCI is not set
-# CONFIG_SOUND_EMU10K1 is not set
-# CONFIG_SOUND_FUSION is not set
-# CONFIG_SOUND_CS4281 is not set
-# CONFIG_SOUND_ES1370 is not set
-# CONFIG_SOUND_ES1371 is not set
-# CONFIG_SOUND_ESSSOLO1 is not set
-# CONFIG_SOUND_MAESTRO is not set
-# CONFIG_SOUND_SONICVIBES is not set
-# CONFIG_SOUND_TRIDENT is not set
-# CONFIG_SOUND_MSNDCLAS is not set
-# CONFIG_SOUND_MSNDPIN is not set
-# CONFIG_SOUND_VIA82CXXX is not set
-CONFIG_SOUND_OSS=m
-# CONFIG_SOUND_TRACEINIT is not set
-# CONFIG_SOUND_DMAP is not set
-# CONFIG_SOUND_AD1816 is not set
-# CONFIG_SOUND_SGALAXY is not set
-CONFIG_SOUND_ADLIB=m
-# CONFIG_SOUND_ACI_MIXER is not set
-# CONFIG_SOUND_CS4232 is not set
-# CONFIG_SOUND_SSCAPE is not set
-# CONFIG_SOUND_GUS is not set
-# CONFIG_SOUND_ICH is not set
-# CONFIG_SOUND_VMIDI is not set
-# CONFIG_SOUND_TRIX is not set
-# CONFIG_SOUND_MSS is not set
-# CONFIG_SOUND_MPU401 is not set
-# CONFIG_SOUND_NM256 is not set
-# CONFIG_SOUND_MAD16 is not set
-# CONFIG_SOUND_PAS is not set
-# CONFIG_PAS_JOYSTICK is not set
-# CONFIG_SOUND_PSS is not set
-CONFIG_SOUND_SB=m
-# CONFIG_SOUND_AWE32_SYNTH is not set
-# CONFIG_SOUND_WAVEFRONT is not set
-# CONFIG_SOUND_MAUI is not set
-# CONFIG_SOUND_YM3812 is not set
-# CONFIG_SOUND_OPL3SA1 is not set
-# CONFIG_SOUND_OPL3SA2 is not set
-# CONFIG_SOUND_YMPCI is not set
-# CONFIG_SOUND_UART6850 is not set
-# CONFIG_SOUND_AEDSP16 is not set
-CONFIG_SOUND_WAVEARTIST=m
-# CONFIG_SOUND_TVMIXER is not set
-
-#
-# USB support
-#
-CONFIG_USB=m
-CONFIG_USB_DEBUG=y
-
-#
-# Miscellaneous USB options
+# Profiling support
#
-CONFIG_USB_DEVICEFS=y
-# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_PROFILING is not set
#
-# USB Controllers
+# Kernel hacking
#
-# CONFIG_USB_UHCI is not set
-# CONFIG_USB_UHCI_ALT is not set
-CONFIG_USB_OHCI=m
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
#
-# USB Devices
+# Security options
#
-CONFIG_USB_PRINTER=m
-# CONFIG_USB_SCANNER is not set
-# CONFIG_USB_MICROTEK is not set
-CONFIG_USB_AUDIO=m
-# CONFIG_USB_ACM is not set
-# CONFIG_USB_SERIAL is not set
-# CONFIG_USB_IBMCAM is not set
-# CONFIG_USB_OV511 is not set
-# CONFIG_USB_DC2XX is not set
-# CONFIG_USB_MDC800 is not set
-# CONFIG_USB_STORAGE is not set
-# CONFIG_USB_USS720 is not set
-# CONFIG_USB_DABUSB is not set
-# CONFIG_USB_PLUSB is not set
-# CONFIG_USB_PEGASUS is not set
-# CONFIG_USB_RIO500 is not set
-# CONFIG_USB_DSBR is not set
-# CONFIG_USB_BLUETOOTH is not set
-# CONFIG_USB_NET1080 is not set
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
#
-# USB Human Interface Devices (HID)
+# Cryptographic options
#
+# CONFIG_CRYPTO is not set
#
-# Input core support is needed for USB HID
+# Hardware crypto devices
#
#
-# Kernel hacking
+# Library routines
#
-CONFIG_FRAME_POINTER=y
-CONFIG_DEBUG_ERRORS=y
-CONFIG_DEBUG_USER=y
-# CONFIG_DEBUG_INFO is not set
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_LL=y
-# CONFIG_DEBUG_DC21285_PORT is not set
+CONFIG_CRC_CCITT=m
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=m
+CONFIG_ZLIB_DEFLATE=m
diff --git a/arch/arm/configs/fortunet_defconfig b/arch/arm/configs/fortunet_defconfig
index 621e9f5c6c932..b6f688d850dcb 100644
--- a/arch/arm/configs/fortunet_defconfig
+++ b/arch/arm/configs/fortunet_defconfig
@@ -1,33 +1,58 @@
#
-# Automatically generated by make menuconfig: don't edit
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.12-rc1-bk2
+# Sun Mar 27 23:51:10 2005
#
CONFIG_ARM=y
-# CONFIG_EISA is not set
-# CONFIG_SBUS is not set
-# CONFIG_MCA is not set
+CONFIG_MMU=y
CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
-# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
-# CONFIG_GENERIC_BUST_SPINLOCK is not set
-# CONFIG_GENERIC_ISA_DMA is not set
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_IOMAP=y
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-# CONFIG_OBSOLETE is not set
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+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_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
#
# Loadable module support
#
# CONFIG_MODULES is not set
-# CONFIG_MODVERSIONS is not set
-# CONFIG_KMOD is not set
#
# System Type
#
-# CONFIG_ARCH_ARCA5K is not set
# CONFIG_ARCH_CLPS7500 is not set
CONFIG_ARCH_CLPS711X=y
# CONFIG_ARCH_CO285 is not set
@@ -35,135 +60,122 @@ CONFIG_ARCH_CLPS711X=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
+# 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
-
-#
-# Archimedes/A5000 Implementations
-#
-# CONFIG_ARCH_ARC is not set
-# CONFIG_ARCH_A5K is not set
-
-#
-# Footbridge Implementations
-#
-# CONFIG_ARCH_CATS is not set
-# CONFIG_ARCH_PERSONAL_SERVER is not set
-# CONFIG_ARCH_EBSA285_ADDIN is not set
-# CONFIG_ARCH_EBSA285_HOST is not set
-# CONFIG_ARCH_NETWINDER is not set
-
-#
-# SA11x0 Implementations
-#
-# CONFIG_SA1100_ASSABET is not set
-# CONFIG_ASSABET_NEPONSET is not set
-# CONFIG_SA1100_ADSBITSY is not set
-# CONFIG_SA1100_BRUTUS is not set
-# CONFIG_SA1100_CERF is not set
-# CONFIG_SA1100_H3100 is not set
-# CONFIG_SA1100_H3600 is not set
-# CONFIG_SA1100_H3800 is not set
-# CONFIG_SA1100_H3XXX is not set
-# CONFIG_SA1100_EXTENEX1 is not set
-# CONFIG_SA1100_FLEXANET is not set
-# CONFIG_SA1100_FREEBIRD is not set
-# CONFIG_SA1100_GRAPHICSCLIENT is not set
-# CONFIG_SA1100_GRAPHICSMASTER is not set
-# CONFIG_SA1100_JORNADA720 is not set
-# CONFIG_SA1100_HUW_WEBPANEL is not set
-# CONFIG_SA1100_ITSY is not set
-# CONFIG_SA1100_LART is not set
-# CONFIG_SA1100_NANOENGINE is not set
-# CONFIG_SA1100_OMNIMETER is not set
-# CONFIG_SA1100_PANGOLIN is not set
-# CONFIG_SA1100_PLEB is not set
-# CONFIG_SA1100_SHANNON is not set
-# CONFIG_SA1100_SHERMAN is not set
-# CONFIG_SA1100_SIMPAD is not set
-# CONFIG_SA1100_PFS168 is not set
-# CONFIG_SA1100_VICTOR is not set
-# CONFIG_SA1100_XP860 is not set
-# CONFIG_SA1100_YOPY is not set
-# CONFIG_SA1100_USB is not set
-# CONFIG_SA1100_USB_NETLINK is not set
-# CONFIG_SA1100_USB_CHAR is not set
-# CONFIG_H3600_SLEEVE 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
#
# CLPS711X/EP721X Implementations
#
# CONFIG_ARCH_AUTCPU12 is not set
# CONFIG_ARCH_CDB89712 is not set
+# CONFIG_ARCH_CEIVA is not set
# CONFIG_ARCH_CLEP7312 is not set
# CONFIG_ARCH_EDB7211 is not set
# CONFIG_ARCH_P720T is not set
CONFIG_ARCH_FORTUNET=y
-# CONFIG_ARCH_EP7211 is not set
-# CONFIG_ARCH_EP7212 is not set
-# CONFIG_ARCH_ACORN is not set
-# CONFIG_FOOTBRIDGE is not set
-# CONFIG_FOOTBRIDGE_HOST is not set
-# CONFIG_FOOTBRIDGE_ADDIN is not set
+
+#
+# Processor Type
+#
CONFIG_CPU_32=y
-# CONFIG_CPU_26 is not set
-# CONFIG_CPU_32v3 is not set
-CONFIG_CPU_32v4=y
-# CONFIG_CPU_ARM610 is not set
-# CONFIG_CPU_ARM710 is not set
CONFIG_CPU_ARM720T=y
-# CONFIG_CPU_ARM920T is not set
-# CONFIG_CPU_ARM922T is not set
-# CONFIG_CPU_ARM926T is not set
-# CONFIG_CPU_ARM1020 is not set
-# CONFIG_CPU_SA110 is not set
-# CONFIG_CPU_SA1100 is not set
+CONFIG_CPU_32v4=y
+CONFIG_CPU_ABRT_LV4T=y
+CONFIG_CPU_CACHE_V4=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WT=y
+CONFIG_CPU_TLB_V4WT=y
+
+#
+# Processor Features
+#
# CONFIG_ARM_THUMB is not set
-# CONFIG_DISCONTIGMEM is not set
#
-# General setup
+# Bus support
+#
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_PREEMPT is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE=""
+# CONFIG_XIP_KERNEL is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
#
-# CONFIG_PCI is not set
-# CONFIG_ISA is not set
-# CONFIG_ISA_DMA is not set
-# CONFIG_HOTPLUG is not set
-# CONFIG_PCMCIA is not set
-CONFIG_NET=y
-CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
# CONFIG_FPE_NWFPE is not set
CONFIG_FPE_FASTFPE=y
-CONFIG_KCORE_ELF=y
-# CONFIG_KCORE_AOUT is not set
-CONFIG_BINFMT_AOUT=y
+
+#
+# Userspace binary formats
+#
CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_AOUT=y
# CONFIG_BINFMT_MISC is not set
-# CONFIG_PM is not set
# CONFIG_ARTHUR is not set
-CONFIG_ALIGNMENT_TRAP=y
#
-# Parallel port support
+# Power management options
#
-# CONFIG_PARPORT is not set
+# CONFIG_PM is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
#
# Memory Technology Devices (MTD)
#
CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
# CONFIG_MTD_PARTITIONS is not set
-# CONFIG_MTD_REDBOOT_PARTS is not set
-# CONFIG_MTD_BOOTLDR_PARTS is not set
-# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
CONFIG_MTD_CHAR=y
CONFIG_MTD_BLOCK=y
# CONFIG_FTL is not set
# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
#
# RAM/ROM/Flash chip drivers
@@ -172,40 +184,48 @@ CONFIG_MTD_CFI=y
# CONFIG_MTD_JEDECPROBE is not set
CONFIG_MTD_GEN_PROBE=y
# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
CONFIG_MTD_CFI_INTELEXT=y
# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
-# CONFIG_MTD_AMDSTD is not set
-# CONFIG_MTD_SHARP is not set
-# CONFIG_MTD_JEDEC 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_NORA is not set
# CONFIG_MTD_ARM_INTEGRATOR is not set
-# CONFIG_MTD_CDB89712 is not set
-# CONFIG_MTD_SA1100 is not set
-# CONFIG_MTD_DC21285 is not set
-# CONFIG_MTD_IQ80310 is not set
-CONFIG_MTD_FORTUNET=y
-# CONFIG_MTD_PCI is not set
+# CONFIG_MTD_EDB7312 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_DOC1000 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_DOCPROBE is not set
+# CONFIG_MTD_DOC2001PLUS is not set
#
# NAND Flash Device Drivers
@@ -213,157 +233,166 @@ CONFIG_MTD_FORTUNET=y
# CONFIG_MTD_NAND is not set
#
-# Plug and Play configuration
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
#
-# CONFIG_PNP is not set
-# CONFIG_ISAPNP is not set
#
# Block devices
#
# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_DEV_XD is not set
-# CONFIG_PARIDE is not set
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
# CONFIG_BLK_DEV_LOOP is not set
# CONFIG_BLK_DEV_NBD is not set
CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
#
# Multi-device support (RAID and LVM)
#
# CONFIG_MD is not set
-# CONFIG_BLK_DEV_MD is not set
-# CONFIG_MD_LINEAR is not set
-# CONFIG_MD_RAID0 is not set
-# CONFIG_MD_RAID1 is not set
-# CONFIG_MD_RAID5 is not set
-# CONFIG_MD_MULTIPATH is not set
-# CONFIG_BLK_DEV_LVM is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
#
# Networking options
#
# CONFIG_PACKET is not set
# CONFIG_NETLINK_DEV is not set
-# CONFIG_NETFILTER is not set
-# CONFIG_FILTER is not set
CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
# CONFIG_INET is not set
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_NETFILTER 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_DECNET is not set
-# CONFIG_BRIDGE is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-# CONFIG_LLC is not set
# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET_AUNUDP is not set
-# CONFIG_ECONET_NATIVE is not set
# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
#
# QoS and/or fair queueing
#
# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
#
-# Network device support
+# 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 is not set
#
-# Amateur Radio support
+# ISDN subsystem
#
-# CONFIG_HAMRADIO is not set
+# CONFIG_ISDN is not set
#
-# IrDA (infrared) support
+# Input device support
#
-# CONFIG_IRDA is not set
+# CONFIG_INPUT is not set
#
-# ATA/IDE/MFM/RLL support
+# Hardware I/O ports
#
-# CONFIG_IDE is not set
-# CONFIG_BLK_DEV_HD is not set
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
#
-# SCSI support
+# Character devices
#
-# CONFIG_SCSI is not set
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
#
-# Synchronous Serial Interface
+# Serial drivers
#
-# CONFIG_SSI is not set
-# CONFIG_SSI_CLPS711X is not set
-# CONFIG_SSI_JUNO is not set
+# CONFIG_SERIAL_8250 is not set
#
-# I2O device support
+# Non-8250 serial port support
#
-# CONFIG_I2O is not set
-# CONFIG_I2O_BLOCK is not set
-# CONFIG_I2O_LAN is not set
-# CONFIG_I2O_SCSI is not set
-# CONFIG_I2O_PROC is not set
+CONFIG_SERIAL_CLPS711X=y
+CONFIG_SERIAL_CLPS711X_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
#
-# ISDN subsystem
+# IPMI
#
-# CONFIG_ISDN is not set
+# CONFIG_IPMI_HANDLER is not set
#
-# Input core support
+# Watchdog Cards
#
-# CONFIG_INPUT is not set
-# CONFIG_INPUT_KEYBDEV is not set
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_EVDEV is not set
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
#
-# Character devices
+# Ftape, the floppy tape device driver
#
-# CONFIG_VT is not set
-# CONFIG_SERIAL is not set
-# CONFIG_SERIAL_EXTENDED is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
#
-# Serial drivers
+# TPM devices
#
-# CONFIG_SERIAL_AMBA is not set
-# CONFIG_SERIAL_AMBA_CONSOLE is not set
-CONFIG_SERIAL_CLPS711X=y
-CONFIG_SERIAL_CLPS711X_CONSOLE=y
-# CONFIG_SERIAL_21285 is not set
-# CONFIG_SERIAL_21285_OLD is not set
-# CONFIG_SERIAL_21285_CONSOLE is not set
-# CONFIG_SERIAL_UART00 is not set
-# CONFIG_SERIAL_UART00_CONSOLE is not set
-# CONFIG_SERIAL_SA1100 is not set
-# CONFIG_SERIAL_SA1100_CONSOLE is not set
-# CONFIG_SERIAL_8250 is not set
-# CONFIG_SERIAL_8250_CONSOLE is not set
-# CONFIG_SERIAL_8250_EXTENDED is not set
-# CONFIG_SERIAL_8250_MANY_PORTS is not set
-# CONFIG_SERIAL_8250_SHARE_IRQ is not set
-# CONFIG_SERIAL_8250_DETECT_IRQ is not set
-# CONFIG_SERIAL_8250_MULTIPORT is not set
-# CONFIG_SERIAL_8250_HUB6 is not set
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
+# CONFIG_TCG_TPM is not set
#
# I2C support
@@ -371,219 +400,159 @@ CONFIG_UNIX98_PTY_COUNT=256
# CONFIG_I2C is not set
#
-# L3 serial bus support
+# Misc devices
#
-# CONFIG_L3 is not set
-# CONFIG_L3_ALGOBIT is not set
-# CONFIG_L3_BIT_SA1100_GPIO is not set
-# CONFIG_L3_SA1111 is not set
-# CONFIG_BIT_SA1100_GPIO is not set
#
-# Mice
+# Multimedia devices
#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_MOUSE is not set
+# CONFIG_VIDEO_DEV is not set
#
-# Joysticks
+# Digital Video Broadcasting Devices
#
-# CONFIG_INPUT_GAMEPORT is not set
-# CONFIG_QIC02_TAPE is not set
#
-# Watchdog Cards
+# Graphics support
#
-# CONFIG_WATCHDOG is not set
-# CONFIG_INTEL_RNG is not set
-# CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
+# CONFIG_FB is not set
#
-# Ftape, the floppy tape device driver
+# Sound
#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
+# CONFIG_SOUND is not set
#
-# Multimedia devices
+# USB support
#
-# CONFIG_VIDEO_DEV is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB is not set
+
+#
+# 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_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_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_REISERFS_CHECK is not set
-# CONFIG_REISERFS_PROC_INFO 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_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
# CONFIG_ADFS_FS is not set
-# CONFIG_ADFS_FS_RW 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_EXT3_FS is not set
-# CONFIG_JBD is not set
-# CONFIG_JBD_DEBUG is not set
-# CONFIG_FAT_FS is not set
-# CONFIG_MSDOS_FS is not set
-# CONFIG_UMSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
# CONFIG_EFS_FS is not set
CONFIG_JFFS_FS=y
CONFIG_JFFS_FS_VERBOSE=0
# CONFIG_JFFS_PROC_FS is not set
# CONFIG_JFFS2_FS is not set
# CONFIG_CRAMFS is not set
-# CONFIG_TMPFS is not set
-# CONFIG_RAMFS is not set
-# CONFIG_ISO9660_FS is not set
-# CONFIG_JOLIET is not set
-# CONFIG_ZISOFS is not set
-# CONFIG_MINIX_FS is not set
# CONFIG_VXFS_FS is not set
-# CONFIG_NTFS_FS is not set
-# CONFIG_NTFS_DEBUG is not set
-# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
-CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
-# CONFIG_DEVFS_MOUNT is not set
-# CONFIG_DEVFS_DEBUG is not set
-CONFIG_DEVPTS_FS=y
# CONFIG_QNX4FS_FS is not set
-# CONFIG_QNX4FS_RW is not set
-# CONFIG_ROMFS_FS is not set
-CONFIG_EXT2_FS=y
# CONFIG_SYSV_FS is not set
-# CONFIG_UDF_FS is not set
-# CONFIG_UDF_RW is not set
# CONFIG_UFS_FS is not set
-# CONFIG_UFS_FS_WRITE is not set
#
# Network File Systems
#
-# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
-# CONFIG_NFS_FS is not set
-# CONFIG_NFS_V3 is not set
-# CONFIG_ROOT_NFS is not set
-# CONFIG_NFSD is not set
-# CONFIG_NFSD_V3 is not set
-# CONFIG_SUNRPC is not set
-# CONFIG_LOCKD is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_NCPFS_NLS is not set
-# CONFIG_ZISOFS_FS is not set
-# CONFIG_ZLIB_FS_INFLATE is not set
#
# Partition Types
#
# CONFIG_PARTITION_ADVANCED is not set
CONFIG_MSDOS_PARTITION=y
-# CONFIG_SMB_NLS is not set
-# CONFIG_NLS is not set
#
-# Multimedia Capabilities Port drivers
+# Native Language Support
#
-# CONFIG_MCP is not set
-# CONFIG_MCP_SA1100 is not set
-# CONFIG_MCP_UCB1200 is not set
-# CONFIG_MCP_UCB1200_AUDIO is not set
-# CONFIG_MCP_UCB1200_TS is not set
+# CONFIG_NLS is not set
#
-# USB support
-#
-# CONFIG_USB is not set
-# CONFIG_USB_UHCI is not set
-# CONFIG_USB_UHCI_ALT is not set
-# CONFIG_USB_OHCI is not set
-# CONFIG_USB_OHCI_SA1111 is not set
-# CONFIG_USB_AUDIO is not set
-# CONFIG_USB_BLUETOOTH is not set
-# CONFIG_USB_STORAGE is not set
-# CONFIG_USB_STORAGE_DEBUG is not set
-# CONFIG_USB_STORAGE_DATAFAB is not set
-# CONFIG_USB_STORAGE_FREECOM is not set
-# CONFIG_USB_STORAGE_ISD200 is not set
-# CONFIG_USB_STORAGE_DPCM is not set
-# CONFIG_USB_STORAGE_HP8200e is not set
-# CONFIG_USB_STORAGE_SDDR09 is not set
-# CONFIG_USB_STORAGE_JUMPSHOT is not set
-# CONFIG_USB_ACM is not set
-# CONFIG_USB_PRINTER is not set
-# CONFIG_USB_DC2XX is not set
-# CONFIG_USB_MDC800 is not set
-# CONFIG_USB_SCANNER is not set
-# CONFIG_USB_MICROTEK is not set
-# CONFIG_USB_HPUSBSCSI is not set
-# CONFIG_USB_PEGASUS is not set
-# CONFIG_USB_KAWETH is not set
-# CONFIG_USB_CATC is not set
-# CONFIG_USB_CDCETHER is not set
-# CONFIG_USB_USBNET is not set
-# CONFIG_USB_USS720 is not set
-
-#
-# USB Serial Converter support
-#
-# CONFIG_USB_SERIAL is not set
-# CONFIG_USB_SERIAL_GENERIC is not set
-# CONFIG_USB_SERIAL_BELKIN is not set
-# CONFIG_USB_SERIAL_WHITEHEAT is not set
-# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
-# CONFIG_USB_SERIAL_EMPEG is not set
-# CONFIG_USB_SERIAL_FTDI_SIO is not set
-# CONFIG_USB_SERIAL_VISOR is not set
-# CONFIG_USB_SERIAL_IR is not set
-# CONFIG_USB_SERIAL_EDGEPORT is not set
-# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
-# CONFIG_USB_SERIAL_KEYSPAN 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_USA49W is not set
-# CONFIG_USB_SERIAL_MCT_U232 is not set
-# CONFIG_USB_SERIAL_PL2303 is not set
-# CONFIG_USB_SERIAL_CYBERJACK is not set
-# CONFIG_USB_SERIAL_XIRCOM is not set
-# CONFIG_USB_SERIAL_OMNINET is not set
-# CONFIG_USB_RIO500 is not set
-
-#
-# Bluetooth support
+# Profiling support
#
-# CONFIG_BT is not set
+# CONFIG_PROFILING is not set
#
# Kernel hacking
#
-CONFIG_FRAME_POINTER=y
-CONFIG_DEBUG_USER=y
-# CONFIG_DEBUG_INFO is not set
-# CONFIG_NO_PGT_CACHE is not set
+# CONFIG_PRINTK_TIME is not set
# CONFIG_DEBUG_KERNEL is not set
-# CONFIG_DEBUG_SLAB is not set
-# CONFIG_MAGIC_SYSRQ is not set
-# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_WAITQ is not set
+CONFIG_LOG_BUF_SHIFT=14
# CONFIG_DEBUG_BUGVERBOSE is not set
-# CONFIG_DEBUG_ERRORS is not set
-# CONFIG_DEBUG_LL is not set
-# CONFIG_DEBUG_DC21285_PORT is not set
-# CONFIG_DEBUG_CLPS711X_UART2 is not set
-# CONFIG_DEBUG_LL_SER3 is not set
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
+
+#
+# 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_CRC32=y
+# CONFIG_LIBCRC32C is not set
diff --git a/arch/arm/configs/h3600_defconfig b/arch/arm/configs/h3600_defconfig
index 5a32ac2330650..b4e297dd54b22 100644
--- a/arch/arm/configs/h3600_defconfig
+++ b/arch/arm/configs/h3600_defconfig
@@ -1,33 +1,63 @@
#
# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.12-rc1-bk2
+# Mon Mar 28 00:02:26 2005
#
CONFIG_ARM=y
-# CONFIG_EISA is not set
-# CONFIG_SBUS is not set
-# CONFIG_MCA is not set
+CONFIG_MMU=y
CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
-# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
-# CONFIG_GENERIC_BUST_SPINLOCK is not set
-# CONFIG_GENERIC_ISA_DMA is not set
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_IOMAP=y
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-# CONFIG_OBSOLETE is not set
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
#
# Loadable module support
#
CONFIG_MODULES=y
+# CONFIG_MODULE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
# CONFIG_KMOD is not set
#
# System Type
#
-# CONFIG_ARCH_ARCA5K is not set
# CONFIG_ARCH_CLPS7500 is not set
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
@@ -35,144 +65,155 @@ CONFIG_MODULES=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
+# 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=y
+# CONFIG_ARCH_S3C2410 is not set
# CONFIG_ARCH_SHARK is not set
-
-#
-# Archimedes/A5000 Implementations
-#
-
-#
-# Archimedes/A5000 Implementations (select only ONE)
-#
-# CONFIG_ARCH_ARC is not set
-# CONFIG_ARCH_A5K is not set
-
-#
-# Footbridge Implementations
-#
-# CONFIG_ARCH_CATS is not set
-# CONFIG_ARCH_PERSONAL_SERVER is not set
-# CONFIG_ARCH_EBSA285_ADDIN is not set
-# CONFIG_ARCH_EBSA285_HOST is not set
-# CONFIG_ARCH_NETWINDER 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
#
# SA11x0 Implementations
#
# CONFIG_SA1100_ASSABET is not set
-# CONFIG_ASSABET_NEPONSET is not set
-# CONFIG_SA1100_ADSBITSY is not set
-# CONFIG_SA1100_BRUTUS is not set
# CONFIG_SA1100_CERF is not set
+# CONFIG_SA1100_COLLIE is not set
+# CONFIG_SA1100_H3100 is not set
CONFIG_SA1100_H3600=y
-# CONFIG_SA1100_EXTENEX1 is not set
-# CONFIG_SA1100_FLEXANET is not set
-# CONFIG_SA1100_FREEBIRD is not set
-# CONFIG_SA1100_GRAPHICSCLIENT is not set
-# CONFIG_SA1100_GRAPHICSMASTER is not set
+# CONFIG_SA1100_H3800 is not set
+CONFIG_SA1100_H3XXX=y
+# CONFIG_SA1100_BADGE4 is not set
# CONFIG_SA1100_JORNADA720 is not set
-# CONFIG_SA1100_HUW_WEBPANEL is not set
-# CONFIG_SA1100_ITSY is not set
+# CONFIG_SA1100_HACKKIT is not set
# CONFIG_SA1100_LART is not set
-# CONFIG_SA1100_NANOENGINE is not set
-# CONFIG_SA1100_OMNIMETER is not set
-# CONFIG_SA1100_PANGOLIN is not set
# CONFIG_SA1100_PLEB is not set
-# CONFIG_SA1100_SHERMAN is not set
+# CONFIG_SA1100_SHANNON is not set
# CONFIG_SA1100_SIMPAD is not set
-# CONFIG_SA1100_PFS168 is not set
-# CONFIG_SA1100_VICTOR is not set
-# CONFIG_SA1100_XP860 is not set
-# CONFIG_SA1100_YOPY is not set
-CONFIG_SA1100_USB=m
-CONFIG_SA1100_USB_NETLINK=m
-# CONFIG_SA1100_USB_CHAR is not set
-
-#
-# CLPS711X/EP721X Implementations
-#
-# CONFIG_ARCH_CDB89712 is not set
-# CONFIG_ARCH_CLEP7312 is not set
-# CONFIG_ARCH_EDB7211 is not set
-# CONFIG_ARCH_P720T is not set
-# CONFIG_ARCH_EP7211 is not set
-# CONFIG_ARCH_EP7212 is not set
-# CONFIG_ARCH_ACORN is not set
-# CONFIG_FOOTBRIDGE is not set
-# CONFIG_FOOTBRIDGE_HOST is not set
-# CONFIG_FOOTBRIDGE_ADDIN is not set
-CONFIG_CPU_32=y
-# CONFIG_CPU_26 is not set
+# CONFIG_SA1100_SSP is not set
+# CONFIG_H3600_SLEEVE is not set
#
# Processor Type
#
-# CONFIG_CPU_32v3 is not set
-CONFIG_CPU_32v4=y
-# CONFIG_CPU_ARM610 is not set
-# CONFIG_CPU_ARM710 is not set
-# CONFIG_CPU_ARM720T is not set
-# CONFIG_CPU_ARM920T is not set
-# CONFIG_CPU_ARM1020 is not set
-# CONFIG_CPU_SA110 is not set
+CONFIG_CPU_32=y
CONFIG_CPU_SA1100=y
-# CONFIG_ARM_THUMB is not set
-CONFIG_DISCONTIGMEM=y
+CONFIG_CPU_32v4=y
+CONFIG_CPU_ABRT_EV4=y
+CONFIG_CPU_CACHE_V4WB=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_TLB_V4WB=y
+CONFIG_CPU_MINICACHE=y
#
-# General setup
+# Processor Features
+#
+
+#
+# Bus support
#
-# CONFIG_PCI is not set
CONFIG_ISA=y
-# CONFIG_ISA_DMA is not set
-CONFIG_CPU_FREQ=y
-CONFIG_HOTPLUG=y
#
-# PCMCIA/CardBus support
+# PCCARD (PCMCIA/CardBus) support
#
+CONFIG_PCCARD=y
+# CONFIG_PCMCIA_DEBUG is not set
CONFIG_PCMCIA=y
+
+#
+# PC-card bridges
+#
# CONFIG_I82365 is not set
# CONFIG_TCIC is not set
-# CONFIG_PCMCIA_CLPS6700 is not set
CONFIG_PCMCIA_SA1100=y
-CONFIG_NET=y
-CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
#
-# At least one math emulation must be selected
+# Kernel Features
+#
+# CONFIG_PREEMPT is not set
+CONFIG_DISCONTIGMEM=y
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE=""
+# CONFIG_XIP_KERNEL is not set
+
+#
+# CPU Frequency scaling
+#
+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 is not set
+# CONFIG_CPU_FREQ_GOV_USERSPACE is not set
+# CONFIG_CPU_FREQ_GOV_ONDEMAND 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
-CONFIG_KCORE_ELF=y
-# CONFIG_KCORE_AOUT is not set
-# CONFIG_BINFMT_AOUT is not set
+
+#
+# Userspace binary formats
+#
CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
# CONFIG_BINFMT_MISC is not set
-CONFIG_PM=y
# CONFIG_ARTHUR is not set
-CONFIG_CMDLINE=""
-# CONFIG_LEDS is not set
-CONFIG_ALIGNMENT_TRAP=y
#
-# Parallel port support
+# Power management options
#
-# CONFIG_PARPORT is not set
+CONFIG_PM=y
+# CONFIG_APM is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
#
# Memory Technology Devices (MTD)
#
CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
CONFIG_MTD_PARTITIONS=y
CONFIG_MTD_REDBOOT_PARTS=y
-CONFIG_MTD_BOOTLDR_PARTS=y
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
+# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
# CONFIG_MTD_AFS_PARTS is not set
#
@@ -182,6 +223,7 @@ CONFIG_MTD_CHAR=y
CONFIG_MTD_BLOCK=y
# CONFIG_FTL is not set
# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
#
# RAM/ROM/Flash chip drivers
@@ -194,49 +236,49 @@ CONFIG_MTD_CFI_NOSWAP=y
# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
CONFIG_MTD_CFI_GEOMETRY=y
-# CONFIG_MTD_CFI_B1 is not set
-# CONFIG_MTD_CFI_B2 is not set
-CONFIG_MTD_CFI_B4=y
+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 is not set
CONFIG_MTD_CFI_I2=y
# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
CONFIG_MTD_CFI_INTELEXT=y
# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
-# CONFIG_MTD_AMDSTD is not set
-# CONFIG_MTD_SHARP is not set
-# CONFIG_MTD_JEDEC 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_NORA is not set
# CONFIG_MTD_ARM_INTEGRATOR is not set
-# CONFIG_MTD_CDB89712 is not set
CONFIG_MTD_SA1100=y
-# CONFIG_MTD_DC21285 is not set
-# CONFIG_MTD_IQ80310 is not set
-# CONFIG_MTD_PCI is not set
+# CONFIG_MTD_EDB7312 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_DOC1000 is not set
# CONFIG_MTD_DOC2000 is not set
# CONFIG_MTD_DOC2001 is not set
-# CONFIG_MTD_DOCPROBE is not set
+# CONFIG_MTD_DOC2001PLUS is not set
#
# NAND Flash Device Drivers
@@ -244,95 +286,209 @@ CONFIG_MTD_SA1100=y
# CONFIG_MTD_NAND is not set
#
-# Plug and Play configuration
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
#
# CONFIG_PNP is not set
-# CONFIG_ISAPNP is not set
-# CONFIG_PNPBIOS is not set
#
# Block devices
#
# CONFIG_BLK_DEV_FD is not set
# CONFIG_BLK_DEV_XD is not set
-# CONFIG_PARIDE is not set
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_CISS_SCSI_TAPE is not set
-# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
CONFIG_BLK_DEV_LOOP=m
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
# CONFIG_BLK_DEV_NBD 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_INITRAMFS_SOURCE=""
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=m
+CONFIG_BLK_DEV_IDE=m
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=m
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDECS is not set
+CONFIG_BLK_DEV_IDECD=m
+# 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=m
+# CONFIG_IDE_ARM is not set
+# CONFIG_IDE_CHIPSETS is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
#
# Multi-device support (RAID and LVM)
#
# CONFIG_MD is not set
-# CONFIG_BLK_DEV_MD is not set
-# CONFIG_MD_LINEAR is not set
-# CONFIG_MD_RAID0 is not set
-# CONFIG_MD_RAID1 is not set
-# CONFIG_MD_RAID5 is not set
-# CONFIG_MD_MULTIPATH is not set
-# CONFIG_BLK_DEV_LVM is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
#
# Networking options
#
# CONFIG_PACKET is not set
-# CONFIG_NETLINK is not set
-# CONFIG_NETFILTER is not set
-# CONFIG_FILTER is not set
+# CONFIG_NETLINK_DEV is not set
CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
CONFIG_INET=y
# CONFIG_IP_MULTICAST is not set
# CONFIG_IP_ADVANCED_ROUTER is not set
# CONFIG_IP_PNP is not set
# CONFIG_NET_IPIP is not set
# CONFIG_NET_IPGRE is not set
-# CONFIG_INET_ECN 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_KHTTPD is not set
-# CONFIG_ATM 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_DECNET is not set
-# CONFIG_BRIDGE is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-# CONFIG_LLC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
#
# QoS and/or fair queueing
#
# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
#
-# Network device support
+# Network testing
#
-CONFIG_NETDEVICES=y
+# 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=m
#
-# ARCnet devices
+# IrDA protocols
#
-# CONFIG_ARCNET is not set
+CONFIG_IRLAN=m
+CONFIG_IRNET=m
+CONFIG_IRCOMM=m
+# CONFIG_IRDA_ULTRA is not set
+
+#
+# IrDA options
+#
+# CONFIG_IRDA_CACHE_LAST_LSAP is not set
+# CONFIG_IRDA_FAST_RR is not set
+# 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
+#
+# CONFIG_IRPORT_SIR is not set
+
+#
+# Old Serial dongle support
+#
+
+#
+# FIR device drivers
+#
+# CONFIG_NSC_FIR is not set
+# CONFIG_WINBOND_FIR is not set
+# CONFIG_SMC_IRCC_FIR is not set
+# CONFIG_ALI_FIR is not set
+CONFIG_SA1100_FIR=m
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
# Ethernet (10 or 100Mbit)
#
# CONFIG_NET_ETHERNET is not set
@@ -340,43 +496,20 @@ CONFIG_NETDEVICES=y
#
# Ethernet (1000 Mbit)
#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_MYRI_SBUS is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PLIP is not set
-CONFIG_PPP=m
-# CONFIG_PPP_MULTILINK is not set
-# CONFIG_PPP_FILTER is not set
-CONFIG_PPP_ASYNC=m
-# CONFIG_PPP_SYNC_TTY is not set
-CONFIG_PPP_DEFLATE=m
-CONFIG_PPP_BSDCOMP=m
-# CONFIG_PPPOE is not set
-# CONFIG_SLIP is not set
#
-# Wireless LAN (non-hamradio)
+# Ethernet (10000 Mbit)
#
-# CONFIG_NET_RADIO is not set
#
# Token Ring devices
#
# CONFIG_TR is not set
-# CONFIG_NET_FC is not set
-# CONFIG_RCPCI is not set
-# CONFIG_SHAPER is not set
#
-# Wan interfaces
+# Wireless LAN (non-hamradio)
#
-# CONFIG_WAN is not set
+# CONFIG_NET_RADIO is not set
#
# PCMCIA network device support
@@ -389,316 +522,317 @@ CONFIG_PCMCIA_PCNET=y
# CONFIG_PCMCIA_NMCLAN is not set
# CONFIG_PCMCIA_SMC91C92 is not set
# CONFIG_PCMCIA_XIRC2PS is not set
-# CONFIG_ARCNET_COM20020_CS is not set
-# CONFIG_PCMCIA_IBMTR is not set
-# CONFIG_NET_PCMCIA_RADIO is not set
+# CONFIG_PCMCIA_AXNET is not set
#
-# Amateur Radio support
+# Wan interfaces
#
-# CONFIG_HAMRADIO is not set
+# CONFIG_WAN is not set
+CONFIG_PPP=m
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+# CONFIG_PPP_SYNC_TTY is not set
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+# CONFIG_PPPOE is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
#
-# IrDA (infrared) support
+# ISDN subsystem
#
-CONFIG_IRDA=m
+# CONFIG_ISDN is not set
#
-# IrDA protocols
+# Input device support
#
-CONFIG_IRLAN=m
-CONFIG_IRNET=m
-CONFIG_IRCOMM=m
-# CONFIG_IRDA_ULTRA is not set
-# CONFIG_IRDA_OPTIONS is not set
+CONFIG_INPUT=y
#
-# Infrared-port device drivers
+# 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
#
-# SIR device drivers
+# Input Device Drivers
#
-# CONFIG_IRTTY_SIR is not set
-# CONFIG_IRPORT_SIR is not set
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_INPORT is not set
+# CONFIG_MOUSE_LOGIBM is not set
+# CONFIG_MOUSE_PC110PAD is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
#
-# Dongle support
+# Hardware I/O ports
#
-# CONFIG_DONGLE is not set
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
#
-# FIR device drivers
+# Character devices
#
-# CONFIG_USB_IRDA 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_SA1100_FIR=m
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
#
-# ATA/IDE/MFM/RLL support
+# Serial drivers
#
-CONFIG_IDE=m
+CONFIG_SERIAL_8250=m
+# CONFIG_SERIAL_8250_CS is not set
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
#
-# IDE, ATA and ATAPI Block devices
+# Non-8250 serial port support
#
-CONFIG_BLK_DEV_IDE=m
+CONFIG_SERIAL_SA1100=y
+CONFIG_SERIAL_SA1100_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
#
-# Please see Documentation/ide.txt for help/info on IDE drives
+# IPMI
#
-# CONFIG_BLK_DEV_HD_IDE is not set
-# CONFIG_BLK_DEV_HD is not set
-CONFIG_BLK_DEV_IDEDISK=m
-# CONFIG_IDEDISK_MULTI_MODE is not set
-# CONFIG_BLK_DEV_IDECS is not set
-CONFIG_BLK_DEV_IDECD=m
-# CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
-# CONFIG_BLK_DEV_IDESCSI is not set
+# CONFIG_IPMI_HANDLER is not set
#
-# IDE chipset support/bugfixes
+# Watchdog Cards
#
-# CONFIG_BLK_DEV_CMD640 is not set
-# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
-# CONFIG_BLK_DEV_ISAPNP is not set
-# CONFIG_IDE_CHIPSETS is not set
-# CONFIG_IDEDMA_AUTO is not set
-# CONFIG_BLK_DEV_ATARAID is not set
-# CONFIG_BLK_DEV_ATARAID_PDC is not set
-# CONFIG_BLK_DEV_ATARAID_HPT is not set
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
#
-# SCSI support
+# Ftape, the floppy tape device driver
#
-# CONFIG_SCSI is not set
+# CONFIG_DRM is not set
#
-# I2O device support
+# PCMCIA character devices
#
-# CONFIG_I2O is not set
-# CONFIG_I2O_BLOCK is not set
-# CONFIG_I2O_LAN is not set
-# CONFIG_I2O_SCSI is not set
-# CONFIG_I2O_PROC is not set
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_RAW_DRIVER is not set
#
-# ISDN subsystem
+# TPM devices
#
-# CONFIG_ISDN is not set
+# CONFIG_TCG_TPM is not set
#
-# Input core support
+# I2C support
#
-# CONFIG_INPUT is not set
-# CONFIG_INPUT_KEYBDEV is not set
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_EVDEV is not set
+# CONFIG_I2C is not set
#
-# Character devices
+# Misc devices
#
-CONFIG_VT=y
-# CONFIG_VT_CONSOLE is not set
-CONFIG_SERIAL=m
-# CONFIG_SERIAL_EXTENDED is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
#
-# Serial drivers
+# Multimedia devices
#
-# CONFIG_SERIAL_AMBA is not set
-# CONFIG_SERIAL_AMBA_CONSOLE is not set
-# CONFIG_SERIAL_CLPS711X is not set
-# CONFIG_SERIAL_CLPS711X_CONSOLE is not set
-# CONFIG_SERIAL_21285 is not set
-# CONFIG_SERIAL_21285_OLD is not set
-# CONFIG_SERIAL_21285_CONSOLE is not set
-# CONFIG_SERIAL_UART00 is not set
-# CONFIG_SERIAL_UART00_CONSOLE is not set
-CONFIG_SERIAL_SA1100=y
-CONFIG_SERIAL_SA1100_CONSOLE=y
-CONFIG_SA1100_DEFAULT_BAUDRATE=38400
-CONFIG_SERIAL_8250=m
-# CONFIG_SERIAL_8250_CONSOLE is not set
-# CONFIG_SERIAL_8250_EXTENDED is not set
-# CONFIG_SERIAL_8250_MANY_PORTS is not set
-# CONFIG_SERIAL_8250_SHARE_IRQ is not set
-# CONFIG_SERIAL_8250_DETECT_IRQ is not set
-# CONFIG_SERIAL_8250_MULTIPORT is not set
-# CONFIG_SERIAL_8250_HUB6 is not set
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=32
+# CONFIG_VIDEO_DEV is not set
#
-# I2C support
+# Digital Video Broadcasting Devices
#
-# CONFIG_I2C is not set
+# CONFIG_DVB is not set
#
-# L3 serial bus support
+# Graphics support
#
-CONFIG_L3=y
-CONFIG_L3_ALGOBIT=y
-CONFIG_L3_BIT_SA1100_GPIO=y
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+CONFIG_FB_SOFT_CURSOR=y
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+CONFIG_FB_SA1100=y
+# CONFIG_FB_VIRTUAL is not set
#
-# Other L3 adapters
+# Console display driver support
#
-# CONFIG_L3_SA1111 is not set
-CONFIG_BIT_SA1100_GPIO=y
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE is not set
#
-# Mice
+# Logo configuration
#
-# CONFIG_BUSMOUSE is not set
-CONFIG_MOUSE=m
-# CONFIG_PSMOUSE is not set
-# CONFIG_82C710_MOUSE is not set
-# CONFIG_PC110_PAD is not set
+# CONFIG_LOGO is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
-# Joysticks
+# Sound
#
-# CONFIG_INPUT_GAMEPORT is not set
+CONFIG_SOUND=y
#
-# Input core support is needed for gameports
+# Advanced Linux Sound Architecture
#
+# CONFIG_SND is not set
#
-# Input core support is needed for joysticks
+# Open Sound System
#
-# CONFIG_QIC02_TAPE is not set
+# CONFIG_SOUND_PRIME is not set
#
-# Watchdog Cards
+# USB support
#
-# CONFIG_WATCHDOG is not set
-# CONFIG_INTEL_RNG is not set
-# CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
-CONFIG_SA1100_RTC=m
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB is not set
#
-# Ftape, the floppy tape device driver
+# USB Gadget Support
#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
+# CONFIG_USB_GADGET is not set
#
-# PCMCIA character devices
+# MMC/SD Card support
#
-# CONFIG_PCMCIA_SERIAL_CS is not set
-# CONFIG_MWAVE is not set
+# CONFIG_MMC is not set
#
-# Multimedia devices
+# File systems
#
-# CONFIG_VIDEO_DEV is not set
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
#
-# File systems
+# XFS support
#
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_REISERFS_CHECK is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=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_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
# CONFIG_ADFS_FS is not set
-# CONFIG_ADFS_FS_RW 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_CMS_FS is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_JBD is not set
-# CONFIG_JBD_DEBUG is not set
-CONFIG_FAT_FS=m
-CONFIG_MSDOS_FS=m
-# CONFIG_UMSDOS_FS is not set
-CONFIG_VFAT_FS=m
# CONFIG_EFS_FS is not set
# CONFIG_JFFS_FS is not set
CONFIG_JFFS2_FS=y
CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_JFFS2_FS_NAND is not set
+# CONFIG_JFFS2_FS_NOR_ECC is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
CONFIG_CRAMFS=m
-# CONFIG_TMPFS is not set
-CONFIG_RAMFS=y
-# CONFIG_ISO9660_FS is not set
-# CONFIG_JOLIET is not set
-# CONFIG_ZISOFS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_FREEVXFS_FS is not set
-# CONFIG_NTFS_FS is not set
-# CONFIG_NTFS_DEBUG is not set
-# CONFIG_NTFS_RW is not set
+# CONFIG_VXFS_FS is not set
# CONFIG_HPFS_FS is not set
-CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
-# CONFIG_DEVFS_MOUNT is not set
-# CONFIG_DEVFS_DEBUG is not set
-CONFIG_DEVPTS_FS=y
# CONFIG_QNX4FS_FS is not set
-# CONFIG_QNX4FS_RW is not set
-# CONFIG_ROMFS_FS is not set
-CONFIG_EXT2_FS=y
# CONFIG_SYSV_FS is not set
-# CONFIG_UDF_FS is not set
-# CONFIG_UDF_RW is not set
# CONFIG_UFS_FS is not set
-# CONFIG_UFS_FS_WRITE is not set
#
# Network File Systems
#
-# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
CONFIG_NFS_FS=y
# CONFIG_NFS_V3 is not set
-# CONFIG_ROOT_NFS is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
CONFIG_NFSD=m
# CONFIG_NFSD_V3 is not set
-CONFIG_SUNRPC=y
+CONFIG_NFSD_TCP=y
CONFIG_LOCKD=y
+CONFIG_EXPORTFS=m
+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_NCPFS_PACKET_SIGNING is not set
-# CONFIG_NCPFS_IOCTL_LOCKING is not set
-# CONFIG_NCPFS_STRONG is not set
-# CONFIG_NCPFS_NFS_NS is not set
-# CONFIG_NCPFS_OS2_NS is not set
-# CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_NLS is not set
-# CONFIG_NCPFS_EXTRAS is not set
-# CONFIG_ZISOFS_FS is not set
-CONFIG_ZLIB_FS_INFLATE=m
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
#
# Partition Types
#
# CONFIG_PARTITION_ADVANCED is not set
CONFIG_MSDOS_PARTITION=y
-CONFIG_SMB_NLS=y
-CONFIG_NLS=y
#
# Native Language Support
#
+CONFIG_NLS=y
CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_NLS_CODEPAGE_437 is not set
# CONFIG_NLS_CODEPAGE_737 is not set
@@ -721,7 +855,9 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# 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
@@ -738,209 +874,40 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_NLS_UTF8 is not set
#
-# Console drivers
-#
-CONFIG_PC_KEYMAP=y
-# CONFIG_VGA_CONSOLE is not set
-
-#
-# Frame-buffer support
-#
-CONFIG_FB=y
-CONFIG_DUMMY_CONSOLE=y
-# CONFIG_FB_ACORN is not set
-# CONFIG_FB_CLPS711X is not set
-CONFIG_FB_SA1100=y
-# CONFIG_FB_CYBER2000 is not set
-# CONFIG_FB_VIRTUAL is not set
-CONFIG_FBCON_ADVANCED=y
-# CONFIG_FBCON_MFB is not set
-# CONFIG_FBCON_CFB2 is not set
-# CONFIG_FBCON_CFB4 is not set
-# CONFIG_FBCON_CFB8 is not set
-CONFIG_FBCON_CFB16=y
-# CONFIG_FBCON_CFB24 is not set
-# CONFIG_FBCON_CFB32 is not set
-# CONFIG_FBCON_AFB is not set
-# CONFIG_FBCON_ILBM is not set
-# CONFIG_FBCON_IPLAN2P2 is not set
-# CONFIG_FBCON_IPLAN2P4 is not set
-# CONFIG_FBCON_IPLAN2P8 is not set
-# CONFIG_FBCON_MAC is not set
-# CONFIG_FBCON_VGA_PLANES is not set
-# CONFIG_FBCON_VGA is not set
-# CONFIG_FBCON_HGA is not set
-CONFIG_FBCON_FONTWIDTH8_ONLY=y
-CONFIG_FBCON_FONTS=y
-CONFIG_FONT_8x8=y
-# CONFIG_FONT_8x16 is not set
-# CONFIG_FONT_SUN8x16 is not set
-# CONFIG_FONT_PEARL_8x8 is not set
-# CONFIG_FONT_ACORN_8x8 is not set
-
-#
-# Sound
-#
-CONFIG_SOUND=y
-# CONFIG_SOUND_BT878 is not set
-# CONFIG_SOUND_CMPCI is not set
-# CONFIG_SOUND_EMU10K1 is not set
-# CONFIG_MIDI_EMU10K1 is not set
-# CONFIG_SOUND_FUSION is not set
-# CONFIG_SOUND_CS4281 is not set
-# CONFIG_SOUND_ES1370 is not set
-# CONFIG_SOUND_ES1371 is not set
-# CONFIG_SOUND_ESSSOLO1 is not set
-# CONFIG_SOUND_MAESTRO is not set
-# CONFIG_SOUND_MAESTRO3 is not set
-# CONFIG_SOUND_ICH is not set
-# CONFIG_SOUND_RME96XX is not set
-# CONFIG_SOUND_SONICVIBES is not set
-# CONFIG_SOUND_TRIDENT is not set
-# CONFIG_SOUND_MSNDCLAS is not set
-# CONFIG_SOUND_MSNDPIN is not set
-# CONFIG_SOUND_VIA82CXXX is not set
-# CONFIG_MIDI_VIA82CXXX is not set
-CONFIG_SOUND_SA1100=y
-CONFIG_SOUND_UDA1341=y
-# CONFIG_SOUND_ASSABET_UDA1341 is not set
-CONFIG_SOUND_H3600_UDA1341=y
-# CONFIG_SOUND_PANGOLIN_UDA1341 is not set
-# CONFIG_SOUND_SA1111_UDA1341 is not set
-# CONFIG_SOUND_SA1100SSP is not set
-# CONFIG_SOUND_OSS is not set
-# CONFIG_SOUND_WAVEARTIST is not set
-# CONFIG_SOUND_TVMIXER is not set
-
-#
-# Multimedia Capabilities Port drivers
-#
-# CONFIG_MCP is not set
-# CONFIG_MCP_SA1100 is not set
-# CONFIG_MCP_UCB1200 is not set
-# CONFIG_MCP_UCB1200_AUDIO is not set
-# CONFIG_MCP_UCB1200_TS is not set
-
-#
-# USB support
-#
-# CONFIG_USB is not set
-
-#
-# USB Controllers
-#
-# CONFIG_USB_UHCI is not set
-# CONFIG_USB_UHCI_ALT is not set
-# CONFIG_USB_OHCI is not set
-# CONFIG_USB_OHCI_SA1111 is not set
-
-#
-# USB Device Class drivers
+# Profiling support
#
-# CONFIG_USB_AUDIO is not set
-# CONFIG_USB_BLUETOOTH is not set
-# CONFIG_USB_STORAGE is not set
-# CONFIG_USB_STORAGE_DEBUG is not set
-# CONFIG_USB_STORAGE_DATAFAB is not set
-# CONFIG_USB_STORAGE_FREECOM is not set
-# CONFIG_USB_STORAGE_ISD200 is not set
-# CONFIG_USB_STORAGE_DPCM is not set
-# CONFIG_USB_STORAGE_HP8200e is not set
-# CONFIG_USB_STORAGE_SDDR09 is not set
-# CONFIG_USB_STORAGE_JUMPSHOT is not set
-# CONFIG_USB_ACM is not set
-# CONFIG_USB_PRINTER is not set
+# CONFIG_PROFILING is not set
#
-# USB Human Interface Devices (HID)
-#
-
-#
-# Input core support is needed for USB HID
-#
-
-#
-# USB Imaging devices
-#
-# CONFIG_USB_DC2XX is not set
-# CONFIG_USB_MDC800 is not set
-# CONFIG_USB_SCANNER is not set
-# CONFIG_USB_MICROTEK is not set
-# CONFIG_USB_HPUSBSCSI is not set
-
-#
-# USB Multimedia devices
-#
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
-#
-# USB Network adaptors
-#
-# CONFIG_USB_PEGASUS is not set
-# CONFIG_USB_KAWETH is not set
-# CONFIG_USB_CATC is not set
-# CONFIG_USB_CDCETHER is not set
-# CONFIG_USB_USBNET is not set
-
-#
-# USB port drivers
+# Kernel hacking
#
-# CONFIG_USB_USS720 is not set
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_FRAME_POINTER=y
+# CONFIG_DEBUG_USER is not set
#
-# USB Serial Converter support
+# Security options
#
-# CONFIG_USB_SERIAL is not set
-# CONFIG_USB_SERIAL_GENERIC is not set
-# CONFIG_USB_SERIAL_BELKIN is not set
-# CONFIG_USB_SERIAL_WHITEHEAT is not set
-# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
-# CONFIG_USB_SERIAL_EMPEG is not set
-# CONFIG_USB_SERIAL_FTDI_SIO is not set
-# CONFIG_USB_SERIAL_VISOR is not set
-# CONFIG_USB_SERIAL_IR is not set
-# CONFIG_USB_SERIAL_EDGEPORT is not set
-# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
-# CONFIG_USB_SERIAL_KEYSPAN 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_USA49W is not set
-# CONFIG_USB_SERIAL_MCT_U232 is not set
-# CONFIG_USB_SERIAL_PL2303 is not set
-# CONFIG_USB_SERIAL_CYBERJACK is not set
-# CONFIG_USB_SERIAL_XIRCOM is not set
-# CONFIG_USB_SERIAL_OMNINET is not set
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
#
-# USB Miscellaneous drivers
+# Cryptographic options
#
-# CONFIG_USB_RIO500 is not set
-# CONFIG_USB_ID75 is not set
+# CONFIG_CRYPTO is not set
#
-# Bluetooth support
+# Hardware crypto devices
#
-# CONFIG_BT is not set
#
-# Kernel hacking
+# Library routines
#
-CONFIG_FRAME_POINTER=y
-CONFIG_DEBUG_ERRORS=y
-# CONFIG_DEBUG_USER is not set
-# CONFIG_DEBUG_INFO is not set
-# CONFIG_DEBUG_SLAB is not set
-CONFIG_MAGIC_SYSRQ=y
-# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_NO_PGT_CACHE is not set
-# CONFIG_DEBUG_LL is not set
-# CONFIG_DEBUG_DC21285_PORT is not set
-# CONFIG_DEBUG_CLPS711X_UART2 is not set
+CONFIG_CRC_CCITT=m
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/arm/configs/h7201_defconfig b/arch/arm/configs/h7201_defconfig
index e18dad412fbcc..39c13a3545417 100644
--- a/arch/arm/configs/h7201_defconfig
+++ b/arch/arm/configs/h7201_defconfig
@@ -1,12 +1,14 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.9-rc1
-# Thu Sep 2 11:04:11 2004
+# Linux kernel version: 2.6.12-rc1-bk2
+# Mon Mar 28 00:11:33 2005
#
CONFIG_ARM=y
CONFIG_MMU=y
CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_IOMAP=y
#
# Code maturity level options
@@ -18,24 +20,28 @@ CONFIG_BROKEN_ON_SMP=y
#
# General setup
#
+CONFIG_LOCALVERSION=""
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
CONFIG_HOTPLUG=y
# CONFIG_IKCONFIG is not set
# CONFIG_EMBEDDED is not set
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=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
@@ -44,6 +50,7 @@ CONFIG_MODULES=y
# CONFIG_MODULE_UNLOAD is not set
CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_KMOD=y
#
@@ -58,6 +65,7 @@ CONFIG_KMOD=y
# 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
@@ -66,7 +74,7 @@ CONFIG_KMOD=y
# CONFIG_ARCH_SHARK is not set
# CONFIG_ARCH_LH7A40X is not set
# CONFIG_ARCH_OMAP is not set
-# CONFIG_ARCH_VERSATILE_PB is not set
+# CONFIG_ARCH_VERSATILE is not set
# CONFIG_ARCH_IMX is not set
CONFIG_ARCH_H720X=y
@@ -85,6 +93,7 @@ CONFIG_CPU_ARM720T=y
CONFIG_CPU_32v4=y
CONFIG_CPU_ABRT_LV4T=y
CONFIG_CPU_CACHE_V4=y
+CONFIG_CPU_CACHE_VIVT=y
CONFIG_CPU_COPY_V4WT=y
CONFIG_CPU_TLB_V4WT=y
@@ -94,46 +103,62 @@ CONFIG_CPU_TLB_V4WT=y
CONFIG_ARM_THUMB=y
#
-# General setup
+# Bus support
+#
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_PREEMPT is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
#
-# CONFIG_ZBOOT_ROM is not set
CONFIG_ZBOOT_ROM_TEXT=0x0
CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE=""
+# CONFIG_XIP_KERNEL is not set
#
-# PCMCIA/CardBus support
+# Floating point emulation
#
-CONFIG_PCMCIA=y
-# CONFIG_PCMCIA_DEBUG is not set
-# CONFIG_TCIC is not set
#
-# At least one math emulation must be selected
+# At least one emulation must be selected
#
CONFIG_FPE_NWFPE=y
# CONFIG_FPE_NWFPE_XP is not set
# CONFIG_FPE_FASTFPE is not set
-# CONFIG_VFP 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
#
-# Generic Driver Options
+# Power management options
#
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
# CONFIG_PM is not set
-# CONFIG_PREEMPT is not set
-# CONFIG_ARTHUR is not set
-CONFIG_CMDLINE=""
-CONFIG_ALIGNMENT_TRAP=y
#
-# Parallel port support
+# Device Drivers
#
-# CONFIG_PARPORT is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
#
# Memory Technology Devices (MTD)
@@ -141,8 +166,8 @@ CONFIG_ALIGNMENT_TRAP=y
CONFIG_MTD=y
CONFIG_MTD_DEBUG=y
CONFIG_MTD_DEBUG_VERBOSE=0
-CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_REDBOOT_PARTS is not set
# CONFIG_MTD_CMDLINE_PARTS is not set
# CONFIG_MTD_AFS_PARTS is not set
@@ -184,6 +209,7 @@ CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_XIP is not set
#
# Mapping drivers for chip access
@@ -201,6 +227,7 @@ CONFIG_MTD_CFI_UTIL=y
# 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
@@ -215,6 +242,11 @@ CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_NAND is not set
#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
# Plug and Play support
#
@@ -222,27 +254,32 @@ CONFIG_MTD_CFI_UTIL=y
# Block devices
#
# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
# CONFIG_BLK_DEV_LOOP is not set
CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=8192
CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CDROM_PKTCDVD is not set
#
-# Multi-device support (RAID and LVM)
+# IO Schedulers
#
-# CONFIG_MD is not set
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
#
-# Networking support
+# SCSI device support
#
-# CONFIG_NET is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_SCSI is not set
#
-# SCSI device support
+# Multi-device support (RAID and LVM)
#
-# CONFIG_SCSI is not set
+# CONFIG_MD is not set
#
# Fusion MPT device support
@@ -257,6 +294,13 @@ CONFIG_BLK_DEV_INITRD=y
#
#
+# Networking support
+#
+# CONFIG_NET is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
# ISDN subsystem
#
@@ -278,16 +322,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=y
-# CONFIG_SERIO_CT82C710 is not set
-
-#
# Input Device Drivers
#
# CONFIG_INPUT_KEYBOARD is not set
@@ -297,6 +331,15 @@ CONFIG_SERIO_SERPORT=y
# CONFIG_INPUT_MISC is not set
#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
+#
# Character devices
#
CONFIG_VT=y
@@ -315,7 +358,6 @@ CONFIG_HW_CONSOLE=y
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
-# CONFIG_QIC02_TAPE is not set
#
# IPMI
@@ -328,21 +370,19 @@ CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_WATCHDOG is not set
# CONFIG_NVRAM is not set
# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
#
# Ftape, the floppy tape device driver
#
-# CONFIG_AGP is not set
# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
#
-# PCMCIA character devices
+# TPM devices
#
-# CONFIG_SYNCLINK_CS is not set
-# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
#
# I2C support
@@ -350,6 +390,10 @@ CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_I2C is not set
#
+# Misc devices
+#
+
+#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -359,6 +403,49 @@ CONFIG_LEGACY_PTY_COUNT=256
#
#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+# CONFIG_SND 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 is not set
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -367,10 +454,15 @@ CONFIG_EXT2_FS=y
# CONFIG_JBD is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
# CONFIG_XFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
@@ -412,6 +504,7 @@ CONFIG_RAMFS=y
CONFIG_JFFS2_FS=y
CONFIG_JFFS2_FS_DEBUG=0
# CONFIG_JFFS2_FS_NAND is not set
+# CONFIG_JFFS2_FS_NOR_ECC is not set
# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
CONFIG_JFFS2_ZLIB=y
CONFIG_JFFS2_RTIME=y
@@ -427,6 +520,7 @@ CONFIG_JFFS2_RTIME=y
# Partition Types
#
# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
#
# Native Language Support
@@ -439,61 +533,19 @@ CONFIG_JFFS2_RTIME=y
# CONFIG_PROFILING is not set
#
-# Graphics support
-#
-# CONFIG_FB is not set
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_MDA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-
-#
-# Sound
-#
-CONFIG_SOUND=m
-
-#
-# Advanced Linux Sound Architecture
-#
-# CONFIG_SND is not set
-
-#
-# Open Sound System
-#
-# CONFIG_SOUND_PRIME is not set
-
-#
-# Misc devices
-#
-
-#
-# USB support
-#
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
-# CONFIG_MMC is not set
-
-#
# Kernel hacking
#
+# CONFIG_PRINTK_TIME is not set
# CONFIG_DEBUG_KERNEL is not set
-# CONFIG_DEBUG_INFO is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_FRAME_POINTER=y
CONFIG_DEBUG_USER=y
#
# Security options
#
+# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
#
@@ -502,6 +554,10 @@ CONFIG_DEBUG_USER=y
# CONFIG_CRYPTO is not set
#
+# Hardware crypto devices
+#
+
+#
# Library routines
#
# CONFIG_CRC_CCITT is not set
diff --git a/arch/arm/configs/h7202_defconfig b/arch/arm/configs/h7202_defconfig
index ba3f6392a8e7e..fbf5c244c696f 100644
--- a/arch/arm/configs/h7202_defconfig
+++ b/arch/arm/configs/h7202_defconfig
@@ -1,12 +1,14 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.9-rc1
-# Thu Sep 30 10:30:42 2004
+# Linux kernel version: 2.6.12-rc1-bk2
+# Mon Mar 28 00:15:45 2005
#
CONFIG_ARM=y
CONFIG_MMU=y
CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_IOMAP=y
#
# Code maturity level options
@@ -18,26 +20,31 @@ CONFIG_BROKEN_ON_SMP=y
#
# General setup
#
+CONFIG_LOCALVERSION=""
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
# CONFIG_IKCONFIG is not set
# CONFIG_EMBEDDED is not set
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=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
@@ -46,6 +53,7 @@ CONFIG_MODULES=y
# CONFIG_MODULE_UNLOAD is not set
CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_KMOD=y
#
@@ -60,6 +68,7 @@ CONFIG_KMOD=y
# 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
@@ -68,7 +77,7 @@ CONFIG_KMOD=y
# CONFIG_ARCH_SHARK is not set
# CONFIG_ARCH_LH7A40X is not set
# CONFIG_ARCH_OMAP is not set
-# CONFIG_ARCH_VERSATILE_PB is not set
+# CONFIG_ARCH_VERSATILE is not set
# CONFIG_ARCH_IMX is not set
CONFIG_ARCH_H720X=y
@@ -77,8 +86,8 @@ CONFIG_ARCH_H720X=y
#
# CONFIG_ARCH_H7201 is not set
CONFIG_ARCH_H7202=y
-# CONFIG_ARCH_FU7202 is not set
CONFIG_CPU_H7202=y
+# CONFIG_H7202_SERIAL23 is not set
#
# Processor Type
@@ -88,6 +97,7 @@ CONFIG_CPU_ARM720T=y
CONFIG_CPU_32v4=y
CONFIG_CPU_ABRT_LV4T=y
CONFIG_CPU_CACHE_V4=y
+CONFIG_CPU_CACHE_VIVT=y
CONFIG_CPU_COPY_V4WT=y
CONFIG_CPU_TLB_V4WT=y
@@ -97,47 +107,71 @@ CONFIG_CPU_TLB_V4WT=y
# CONFIG_ARM_THUMB is not set
#
-# General setup
+# Bus support
+#
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_PREEMPT is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
#
-# CONFIG_ZBOOT_ROM is not set
CONFIG_ZBOOT_ROM_TEXT=0x0
CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="console=ttyS0,19200"
+# CONFIG_XIP_KERNEL is not set
+
+#
+# Floating point emulation
+#
#
-# At least one math emulation must be selected
+# At least one emulation must be selected
#
CONFIG_FPE_NWFPE=y
CONFIG_FPE_NWFPE_XP=y
# CONFIG_FPE_FASTFPE is not set
-# CONFIG_VFP 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
#
-# Generic Driver Options
+# Power management options
#
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_DEBUG_DRIVER is not set
# CONFIG_PM is not set
-# CONFIG_PREEMPT is not set
-# CONFIG_ARTHUR is not set
-CONFIG_CMDLINE="console=ttyS0,19200"
-CONFIG_ALIGNMENT_TRAP=y
#
-# Parallel port support
+# Device Drivers
#
-# CONFIG_PARPORT is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
#
# Memory Technology Devices (MTD)
#
CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
-CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_REDBOOT_PARTS is not set
CONFIG_MTD_CMDLINE_PARTS=y
# CONFIG_MTD_AFS_PARTS is not set
@@ -175,6 +209,7 @@ CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_XIP is not set
#
# Mapping drivers for chip access
@@ -192,6 +227,7 @@ CONFIG_MTD_H720X=y
# 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
@@ -206,6 +242,11 @@ CONFIG_MTD_H720X=y
# CONFIG_MTD_NAND is not set
#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
# Plug and Play support
#
@@ -213,9 +254,27 @@ CONFIG_MTD_H720X=y
# Block devices
#
# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
# CONFIG_BLK_DEV_LOOP is not set
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
#
# Multi-device support (RAID and LVM)
@@ -223,6 +282,18 @@ CONFIG_MTD_H720X=y
# CONFIG_MD is not set
#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
# Networking support
#
CONFIG_NET=y
@@ -249,6 +320,8 @@ CONFIG_IP_PNP_BOOTP=y
# 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
@@ -268,7 +341,6 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
#
# QoS and/or fair queueing
@@ -297,8 +369,6 @@ CONFIG_NETDEVICES=y
CONFIG_NET_ETHERNET=y
# CONFIG_MII is not set
# CONFIG_SMC91X is not set
-# CONFIG_CS89x0 is not set
-CONFIG_CIRRUS=y
#
# Ethernet (1000 Mbit)
@@ -327,23 +397,6 @@ CONFIG_CIRRUS=y
# CONFIG_NETCONSOLE is not set
#
-# SCSI device support
-#
-# CONFIG_SCSI is not set
-
-#
-# Fusion MPT device support
-#
-
-#
-# IEEE 1394 (FireWire) support
-#
-
-#
-# I2O device support
-#
-
-#
# ISDN subsystem
#
# CONFIG_ISDN is not set
@@ -366,17 +419,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=y
-# CONFIG_SERIO_CT82C710 is not set
-CONFIG_SERIO_H7202=y
-
-#
# Input Device Drivers
#
CONFIG_INPUT_KEYBOARD=y
@@ -394,6 +436,16 @@ CONFIG_MOUSE_PS2=y
# CONFIG_INPUT_MISC is not set
#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
+#
# Character devices
#
CONFIG_VT=y
@@ -417,7 +469,6 @@ CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
-# CONFIG_QIC02_TAPE is not set
#
# IPMI
@@ -430,23 +481,30 @@ CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_WATCHDOG is not set
# CONFIG_NVRAM is not set
# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
#
# 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
+
+#
# I2C support
#
# CONFIG_I2C is not set
#
+# Misc devices
+#
+
+#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -457,6 +515,68 @@ CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_DVB is not set
#
+# Graphics support
+#
+CONFIG_FB=y
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_SOFT_CURSOR is not set
+CONFIG_FB_MODE_HELPERS=y
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE is not set
+
+#
+# Logo configuration
+#
+# CONFIG_LOGO is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+CONFIG_USB_GADGET=m
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_PXA2XX is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_SA1100 is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_DUALSPEED is not set
+CONFIG_USB_ZERO=m
+# CONFIG_USB_ETH is not set
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_FILE_STORAGE_TEST=y
+CONFIG_USB_G_SERIAL=m
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -465,10 +585,15 @@ CONFIG_EXT2_FS=y
# CONFIG_JBD is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
# CONFIG_XFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
@@ -495,6 +620,7 @@ CONFIG_DEVFS_MOUNT=y
# CONFIG_DEVFS_DEBUG is not set
# CONFIG_DEVPTS_FS_XATTR is not set
CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
@@ -512,6 +638,7 @@ CONFIG_RAMFS=y
CONFIG_JFFS2_FS=y
CONFIG_JFFS2_FS_DEBUG=0
# CONFIG_JFFS2_FS_NAND is not set
+# CONFIG_JFFS2_FS_NOR_ECC is not set
# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
CONFIG_JFFS2_ZLIB=y
CONFIG_JFFS2_RTIME=y
@@ -534,7 +661,6 @@ CONFIG_NFS_V3=y
# CONFIG_ROOT_NFS is not set
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
-# CONFIG_EXPORTFS is not set
CONFIG_SUNRPC=y
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
@@ -548,6 +674,7 @@ CONFIG_SUNRPC=y
# Partition Types
#
# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
#
# Native Language Support
@@ -560,72 +687,20 @@ CONFIG_SUNRPC=y
# CONFIG_PROFILING is not set
#
-# Graphics support
-#
-CONFIG_FB=y
-CONFIG_FB_MODE_HELPERS=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 is not set
-
-#
-# Logo configuration
-#
-# CONFIG_LOGO is not set
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# Misc devices
-#
-
-#
-# USB support
-#
-
-#
-# USB Gadget Support
-#
-CONFIG_USB_GADGET=m
-# CONFIG_USB_GADGET_NET2280 is not set
-# CONFIG_USB_GADGET_PXA2XX is not set
-# CONFIG_USB_GADGET_GOKU is not set
-# CONFIG_USB_GADGET_SA1100 is not set
-CONFIG_USB_GADGET_H7202=y
-CONFIG_USB_H7202=m
-# CONFIG_USB_GADGET_DUMMY_HCD is not set
-# CONFIG_USB_GADGET_DUALSPEED is not set
-CONFIG_USB_ZERO=m
-# CONFIG_USB_ETH is not set
-CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
-CONFIG_USB_FILE_STORAGE_TEST=y
-CONFIG_USB_G_SERIAL=m
-CONFIG_USB_G_MULTISER=m
-
-#
-# MMC/SD Card support
-#
-# CONFIG_MMC is not set
-
-#
# Kernel hacking
#
+# CONFIG_PRINTK_TIME is not set
CONFIG_DEBUG_KERNEL=y
CONFIG_MAGIC_SYSRQ=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_SCHEDSTATS is not set
# CONFIG_DEBUG_SLAB is not set
# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_FS is not set
CONFIG_FRAME_POINTER=y
CONFIG_DEBUG_USER=y
# CONFIG_DEBUG_WAITQ is not set
@@ -635,6 +710,7 @@ CONFIG_DEBUG_USER=y
#
# Security options
#
+# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
#
@@ -643,6 +719,10 @@ CONFIG_DEBUG_USER=y
# CONFIG_CRYPTO is not set
#
+# Hardware crypto devices
+#
+
+#
# Library routines
#
# CONFIG_CRC_CCITT is not set
diff --git a/arch/arm/configs/hackkit_defconfig b/arch/arm/configs/hackkit_defconfig
index a07c70279fa39..6987c8c5ddb4a 100644
--- a/arch/arm/configs/hackkit_defconfig
+++ b/arch/arm/configs/hackkit_defconfig
@@ -1,119 +1,103 @@
#
# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.12-rc1-bk2
+# Mon Mar 28 00:22:34 2005
#
CONFIG_ARM=y
CONFIG_MMU=y
-CONFIG_SWAP=y
CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_IOMAP=y
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
#
# General setup
#
-CONFIG_NET=y
+CONFIG_LOCALVERSION=""
+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_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
#
# Loadable module support
#
CONFIG_MODULES=y
# CONFIG_MODULE_UNLOAD is not set
-# 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
#
# System Type
#
-# CONFIG_ARCH_ADIFCC is not set
-# CONFIG_ARCH_ARCA5K is not set
# CONFIG_ARCH_CLPS7500 is not set
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
-# CONFIG_ARCH_PXA 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_IOP310 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=y
+# CONFIG_ARCH_S3C2410 is not set
# CONFIG_ARCH_SHARK is not set
-
-#
-# Archimedes/A5000 Implementations
-#
-
-#
-# Archimedes/A5000 Implementations (select only ONE)
-#
-
-#
-# CLPS711X/EP721X Implementations
-#
-
-#
-# Epxa10db
-#
-
-#
-# Footbridge Implementations
-#
-
-#
-# IOP310 Implementation Options
-#
-
-#
-# IOP310 Chipset Features
-#
-
-#
-# Intel PXA250/210 Implementations
-#
+# 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
#
# SA11x0 Implementations
#
# CONFIG_SA1100_ASSABET is not set
-# CONFIG_SA1100_ADSBITSY is not set
-# CONFIG_SA1100_BRUTUS is not set
# CONFIG_SA1100_CERF is not set
+# CONFIG_SA1100_COLLIE is not set
# CONFIG_SA1100_H3100 is not set
# CONFIG_SA1100_H3600 is not set
# CONFIG_SA1100_H3800 is not set
-# CONFIG_SA1100_EXTENEX1 is not set
-# CONFIG_SA1100_FLEXANET is not set
-# CONFIG_SA1100_FREEBIRD is not set
-# CONFIG_SA1100_GRAPHICSCLIENT is not set
-# CONFIG_SA1100_GRAPHICSMASTER is not set
# CONFIG_SA1100_BADGE4 is not set
# CONFIG_SA1100_JORNADA720 is not set
CONFIG_SA1100_HACKKIT=y
-# CONFIG_SA1100_HUW_WEBPANEL is not set
-# CONFIG_SA1100_ITSY is not set
# CONFIG_SA1100_LART is not set
-# CONFIG_SA1100_NANOENGINE is not set
-# CONFIG_SA1100_OMNIMETER is not set
-# CONFIG_SA1100_PANGOLIN is not set
# CONFIG_SA1100_PLEB is not set
-# CONFIG_SA1100_PT_SYSTEM3 is not set
# CONFIG_SA1100_SHANNON is not set
-# CONFIG_SA1100_SHERMAN is not set
# CONFIG_SA1100_SIMPAD is not set
-# CONFIG_SA1100_PFS168 is not set
-# CONFIG_SA1100_VICTOR is not set
-# CONFIG_SA1100_XP860 is not set
-# CONFIG_SA1100_YOPY is not set
-# CONFIG_SA1100_STORK is not set
-# CONFIG_SA1100_USB is not set
+# CONFIG_SA1100_SSP is not set
#
# Processor Type
@@ -121,47 +105,94 @@ CONFIG_SA1100_HACKKIT=y
CONFIG_CPU_32=y
CONFIG_CPU_SA1100=y
CONFIG_CPU_32v4=y
+CONFIG_CPU_ABRT_EV4=y
+CONFIG_CPU_CACHE_V4WB=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_TLB_V4WB=y
+CONFIG_CPU_MINICACHE=y
#
# Processor Features
#
#
-# General setup
+# Bus support
#
-CONFIG_DISCONTIGMEM=y
CONFIG_ISA=y
-# CONFIG_ZBOOT_ROM is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_PREEMPT is not set
+CONFIG_DISCONTIGMEM=y
+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="console=ttySA0,115200 root=/dev/ram0 initrd=0xc0400000,8M init=/rootshell"
+# CONFIG_XIP_KERNEL is not set
+
+#
+# CPU Frequency scaling
+#
CONFIG_CPU_FREQ=y
-CONFIG_CPU_FREQ_24_API=y
-CONFIG_CPU_FREQ_26_API=y
-# CONFIG_HOTPLUG is not set
+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 is not set
+# CONFIG_CPU_FREQ_GOV_USERSPACE is not set
+# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set
#
-# At least one math emulation must be selected
+# 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
-CONFIG_KCORE_ELF=y
-# CONFIG_KCORE_AOUT is not set
-CONFIG_BINFMT_AOUT=y
+
+#
+# Userspace binary formats
+#
CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_AOUT=y
# CONFIG_BINFMT_MISC is not set
-# CONFIG_PM is not set
-# CONFIG_PREEMPT is not set
# CONFIG_ARTHUR is not set
-CONFIG_CMDLINE="console=ttySA0,115200 root=/dev/ram0 initrd=0xc0400000,8M init=/rootshell"
-CONFIG_LEDS=y
-CONFIG_LEDS_TIMER=y
-CONFIG_LEDS_CPU=y
-CONFIG_ALIGNMENT_TRAP=y
#
-# Parallel port support
+# Power management options
#
-# CONFIG_PARPORT is not set
+# CONFIG_PM 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
#
# Memory Technology Devices (MTD)
@@ -169,8 +200,8 @@ CONFIG_ALIGNMENT_TRAP=y
CONFIG_MTD=y
CONFIG_MTD_DEBUG=y
CONFIG_MTD_DEBUG_VERBOSE=3
-# CONFIG_MTD_PARTITIONS is not set
# CONFIG_MTD_CONCAT is not set
+# CONFIG_MTD_PARTITIONS is not set
#
# User Modules And Translation Layers
@@ -179,6 +210,7 @@ CONFIG_MTD_CHAR=y
CONFIG_MTD_BLOCK=y
# CONFIG_FTL is not set
# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
#
# RAM/ROM/Flash chip drivers
@@ -187,18 +219,30 @@ CONFIG_MTD_CFI=y
# CONFIG_MTD_JEDECPROBE is not set
CONFIG_MTD_GEN_PROBE=y
# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
CONFIG_MTD_CFI_INTELEXT=y
# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
+# 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_NORA is not set
# CONFIG_MTD_ARM_INTEGRATOR is not set
# CONFIG_MTD_EDB7312 is not set
@@ -206,15 +250,17 @@ CONFIG_MTD_CFI_INTELEXT=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_DOC1000 is not set
# CONFIG_MTD_DOC2000 is not set
# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
#
# NAND Flash Device Drivers
@@ -222,7 +268,12 @@ CONFIG_MTD_CFI_INTELEXT=y
# CONFIG_MTD_NAND is not set
#
-# Plug and Play configuration
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
#
# CONFIG_PNP is not set
@@ -231,11 +282,34 @@ CONFIG_MTD_CFI_INTELEXT=y
#
# CONFIG_BLK_DEV_FD is not set
# CONFIG_BLK_DEV_XD is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
# CONFIG_BLK_DEV_LOOP is not set
# CONFIG_BLK_DEV_NBD is not set
CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=8192
CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
#
# Multi-device support (RAID and LVM)
@@ -243,13 +317,28 @@ CONFIG_BLK_DEV_INITRD=y
# CONFIG_MD is not set
#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
# Networking options
#
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
# CONFIG_NETLINK_DEV is not set
-# CONFIG_NETFILTER is not set
-# CONFIG_FILTER is not set
CONFIG_UNIX=y
# CONFIG_NET_KEY is not set
CONFIG_INET=y
@@ -259,54 +348,58 @@ CONFIG_INET=y
# CONFIG_NET_IPIP is not set
# CONFIG_NET_IPGRE is not set
# CONFIG_ARPD is not set
-CONFIG_INET_ECN=y
CONFIG_SYN_COOKIES=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
-# CONFIG_XFRM_USER 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_IPV6_SCTP__=y
# CONFIG_IP_SCTP is not set
# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
# CONFIG_VLAN_8021Q is not set
-# CONFIG_LLC is not set
# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
#
# QoS and/or fair queueing
#
# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
#
# Network testing
#
# CONFIG_NET_PKTGEN is not set
-
-#
-# Network device support
-#
+# 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=y
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
#
# ARCnet devices
#
# CONFIG_ARCNET is not set
-CONFIG_DUMMY=y
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
#
# Ethernet (10 or 100Mbit)
@@ -316,67 +409,47 @@ CONFIG_DUMMY=y
#
# Ethernet (1000 Mbit)
#
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-CONFIG_NET_RADIO=y
-# CONFIG_STRIP is not set
-# CONFIG_ARLAN is not set
-# CONFIG_AIRONET4500 is not set
-
-#
-# Wireless ISA/PCI cards support
-#
-# CONFIG_WAVELAN is not set
-# CONFIG_AIRO is not set
-# CONFIG_HERMES is not set
-CONFIG_NET_WIRELESS=y
-
-#
-# Token Ring devices (depends on LLC=y)
-#
-# CONFIG_NET_FC is not set
-# CONFIG_SHAPER is not set
#
-# Wan interfaces
+# Ethernet (10000 Mbit)
#
-# CONFIG_WAN is not set
#
-# IrDA (infrared) support
+# Token Ring devices
#
-# CONFIG_IRDA is not set
+# CONFIG_TR is not set
#
-# Amateur Radio support
+# Wireless LAN (non-hamradio)
#
-# CONFIG_HAMRADIO is not set
+CONFIG_NET_RADIO=y
#
-# ATA/ATAPI/MFM/RLL support
+# Obsolete Wireless cards support (pre-802.11)
#
-# CONFIG_IDE is not set
+# CONFIG_STRIP is not set
+# CONFIG_ARLAN is not set
+# CONFIG_WAVELAN is not set
#
-# SCSI support
+# Wireless 802.11b ISA/PCI cards support
#
-# CONFIG_SCSI is not set
+# CONFIG_ATMEL is not set
+CONFIG_NET_WIRELESS=y
#
-# I2O device support
+# Wan interfaces
#
-# CONFIG_I2O is not set
+# 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
#
# ISDN subsystem
#
-# CONFIG_ISDN_BOOL is not set
+# CONFIG_ISDN is not set
#
# Input device support
@@ -392,21 +465,10 @@ 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_TSLIBDEV is not set
# CONFIG_INPUT_EVDEV is not set
# CONFIG_INPUT_EVBUG is not set
#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-
-#
# Input Device Drivers
#
# CONFIG_INPUT_KEYBOARD is not set
@@ -416,6 +478,15 @@ CONFIG_SERIO_SERPORT=y
# CONFIG_INPUT_MISC is not set
#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
+#
# Character devices
#
CONFIG_VT=y
@@ -436,23 +507,13 @@ CONFIG_SERIAL_SA1100_CONSOLE=y
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
#
-# L3 serial bus support
+# IPMI
#
-# CONFIG_L3 is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_QIC02_TAPE is not set
+# CONFIG_IPMI_HANDLER is not set
#
# Watchdog Cards
@@ -460,88 +521,162 @@ CONFIG_UNIX98_PTY_COUNT=256
# CONFIG_WATCHDOG is not set
# CONFIG_NVRAM is not set
# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
-CONFIG_SA1100_RTC=y
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
#
# Ftape, the floppy tape device driver
#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
# CONFIG_DRM is not set
# CONFIG_RAW_DRIVER is not set
#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Misc devices
+#
+
+#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_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 is not set
+# CONFIG_USB is not set
+
+#
+# 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_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_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
-# CONFIG_REISERFS_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# 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_EXT3_FS is not set
-# CONFIG_JBD is not set
-CONFIG_FAT_FS=y
-CONFIG_MSDOS_FS=y
-CONFIG_VFAT_FS=y
# CONFIG_EFS_FS is not set
# CONFIG_JFFS_FS is not set
# CONFIG_JFFS2_FS is not set
CONFIG_CRAMFS=y
-CONFIG_TMPFS=y
-CONFIG_RAMFS=y
-# CONFIG_ISO9660_FS is not set
-# CONFIG_JFS_FS is not set
-# CONFIG_MINIX_FS is not set
# CONFIG_VXFS_FS is not set
-# CONFIG_NTFS_FS is not set
# CONFIG_HPFS_FS is not set
-CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS=y
# CONFIG_QNX4FS_FS is not set
-# CONFIG_ROMFS_FS is not set
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_SYSV_FS is not set
-# CONFIG_UDF_FS is not set
# CONFIG_UFS_FS is not set
-# CONFIG_XFS_FS is not set
#
# Network File Systems
#
-# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
# CONFIG_NFS_FS is not set
# CONFIG_NFSD is not set
-# CONFIG_EXPORTFS is not set
-# CONFIG_CIFS is not set
# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
# CONFIG_AFS_FS is not set
#
# Partition Types
#
# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_NLS=y
+CONFIG_MSDOS_PARTITION=y
#
# Native Language Support
#
+CONFIG_NLS=y
CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_NLS_CODEPAGE_437 is not set
# CONFIG_NLS_CODEPAGE_737 is not set
@@ -566,6 +701,7 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_NLS_ISO8859_8 is not set
# CONFIG_NLS_CODEPAGE_1250 is not set
# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
# CONFIG_NLS_ISO8859_1 is not set
# CONFIG_NLS_ISO8859_2 is not set
# CONFIG_NLS_ISO8859_3 is not set
@@ -582,63 +718,37 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_NLS_UTF8 is not set
#
-# Console drivers
+# Profiling support
#
-# CONFIG_VGA_CONSOLE is not set
-
-#
-# Frame-buffer support
-#
-# CONFIG_FB is not set
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# Misc devices
-#
-
-#
-# Multimedia Capabilities Port drivers
-#
-# CONFIG_MCP is not set
-
-#
-# Console Switches
-#
-# CONFIG_SWITCHES is not set
-
-#
-# USB support
-#
-
-#
-# Bluetooth support
-#
-# CONFIG_BT is not set
+# CONFIG_PROFILING is not set
#
# Kernel hacking
#
-CONFIG_FRAME_POINTER=y
-CONFIG_DEBUG_USER=y
-# CONFIG_DEBUG_INFO is not set
+# CONFIG_PRINTK_TIME is not set
CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_SLAB=y
CONFIG_MAGIC_SYSRQ=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_SCHEDSTATS is not set
+CONFIG_DEBUG_SLAB=y
CONFIG_DEBUG_SPINLOCK=y
-CONFIG_DEBUG_WAITQ=y
+# 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_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_WAITQ=y
CONFIG_DEBUG_ERRORS=y
-CONFIG_KALLSYMS=y
CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
#
# Security options
#
-CONFIG_SECURITY_CAPABILITIES=y
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
#
# Cryptographic options
@@ -646,7 +756,13 @@ CONFIG_SECURITY_CAPABILITIES=y
# CONFIG_CRYPTO is not set
#
+# Hardware crypto devices
+#
+
+#
# Library routines
#
+# CONFIG_CRC_CCITT is not set
# CONFIG_CRC32 is not set
+# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=y
diff --git a/arch/arm/configs/integrator_defconfig b/arch/arm/configs/integrator_defconfig
index 5efaeef3e7585..27ee768252547 100644
--- a/arch/arm/configs/integrator_defconfig
+++ b/arch/arm/configs/integrator_defconfig
@@ -1,12 +1,13 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.10-rc3
-# Mon Dec 20 16:08:21 2004
+# Linux kernel version: 2.6.12-rc1-bk2
+# Sun Mar 27 21:14: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
#
@@ -26,7 +27,6 @@ CONFIG_SYSVIPC=y
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
# CONFIG_HOTPLUG is not set
CONFIG_KOBJECT_UEVENT=y
CONFIG_IKCONFIG=y
@@ -35,6 +35,7 @@ CONFIG_IKCONFIG_PROC=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
@@ -44,6 +45,7 @@ CONFIG_CC_ALIGN_LABELS=0
CONFIG_CC_ALIGN_LOOPS=0
CONFIG_CC_ALIGN_JUMPS=0
# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
#
# Loadable module support
@@ -94,6 +96,7 @@ CONFIG_ARCH_INTEGRATOR_AP=y
CONFIG_CPU_32=y
CONFIG_CPU_ARM720T=y
CONFIG_CPU_ARM920T=y
+# CONFIG_CPU_ARM922T is not set
# CONFIG_CPU_ARM926T is not set
# CONFIG_CPU_ARM1020 is not set
# CONFIG_CPU_ARM1022 is not set
@@ -117,68 +120,98 @@ CONFIG_ARM_THUMB=y
# CONFIG_CPU_ICACHE_DISABLE is not set
# CONFIG_CPU_DCACHE_DISABLE is not set
# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+CONFIG_ICST525=y
#
-# General setup
+# Bus support
#
-CONFIG_PCI=y
-CONFIG_ICST525=y
CONFIG_ARM_AMBA=y
+CONFIG_PCI=y
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_PREEMPT is not set
+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="console=ttyAM0,38400n8 root=/dev/nfs ip=bootp mem=32M"
# CONFIG_XIP_KERNEL is not set
+
+#
+# CPU Frequency scaling
+#
CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
# CONFIG_CPU_FREQ_DEBUG is not set
-# CONFIG_CPU_FREQ_PROC_INTF 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_24_API is not set
CONFIG_CPU_FREQ_GOV_ONDEMAND=y
CONFIG_CPU_FREQ_INTEGRATOR=y
-CONFIG_PCI_LEGACY_PROC=y
-CONFIG_PCI_NAMES=y
#
-# At least one math emulation must be selected
+# 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
#
-# Generic Driver Options
+# Power management options
#
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_DEBUG_DRIVER is not set
CONFIG_PM=y
-# CONFIG_PREEMPT is not set
# CONFIG_APM is not set
-# CONFIG_ARTHUR is not set
-CONFIG_CMDLINE="console=ttyAM0,38400n8 root=/dev/nfs ip=bootp mem=32M"
-CONFIG_LEDS=y
-CONFIG_LEDS_TIMER=y
-CONFIG_LEDS_CPU=y
-CONFIG_ALIGNMENT_TRAP=y
#
-# Parallel port support
+# Device Drivers
#
-# CONFIG_PARPORT is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
#
# Memory Technology Devices (MTD)
#
CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
-CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_REDBOOT_PARTS is not set
CONFIG_MTD_CMDLINE_PARTS=y
CONFIG_MTD_AFS_PARTS=y
@@ -220,6 +253,7 @@ CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_XIP is not set
#
# Mapping drivers for chip access
@@ -237,6 +271,7 @@ CONFIG_MTD_CFI_UTIL=y
# 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
@@ -251,6 +286,11 @@ CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_NAND is not set
#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
# Plug and Play support
#
@@ -262,6 +302,7 @@ CONFIG_MTD_CFI_UTIL=y
# CONFIG_BLK_CPQ_CISS_DA is not set
# CONFIG_BLK_DEV_DAC960 is not set
# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
# CONFIG_BLK_DEV_NBD is not set
@@ -280,6 +321,12 @@ CONFIG_IOSCHED_NOOP=y
CONFIG_IOSCHED_AS=y
CONFIG_IOSCHED_DEADLINE=y
CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
#
# Multi-device support (RAID and LVM)
@@ -287,6 +334,20 @@ CONFIG_IOSCHED_CFQ=y
# CONFIG_MD is not set
#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
# Networking support
#
CONFIG_NET=y
@@ -387,7 +448,6 @@ CONFIG_NET_PCI=y
# CONFIG_DGRS is not set
# CONFIG_EEPRO100 is not set
CONFIG_E100=y
-# CONFIG_E100_NAPI is not set
# CONFIG_FEALNX is not set
# CONFIG_NATSEMI is not set
# CONFIG_NE2K_PCI is not set
@@ -441,25 +501,6 @@ CONFIG_E100=y
# CONFIG_NETCONSOLE is not set
#
-# SCSI device support
-#
-# CONFIG_SCSI is not set
-
-#
-# Fusion MPT device support
-#
-
-#
-# IEEE 1394 (FireWire) support
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-
-#
# ISDN subsystem
#
# CONFIG_ISDN is not set
@@ -482,18 +523,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_SERPORT is not set
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_AMBAKMI is not set
-# CONFIG_SERIO_PCIPS2 is not set
-# CONFIG_SERIO_RAW is not set
-
-#
# Input Device Drivers
#
CONFIG_INPUT_KEYBOARD=y
@@ -511,6 +540,18 @@ CONFIG_MOUSE_PS2=y
# CONFIG_INPUT_MISC is not set
#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_AMBAKMI is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
+#
# Character devices
#
CONFIG_VT=y
@@ -557,11 +598,20 @@ CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_RAW_DRIVER is not set
#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
# I2C support
#
# CONFIG_I2C is not set
#
+# Misc devices
+#
+
+#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -572,6 +622,77 @@ CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_DVB is not set
#
+# Graphics support
+#
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+CONFIG_FB_SOFT_CURSOR=y
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_ARMCLCD is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_NVIDIA is not set
+# CONFIG_FB_RIVA is not set
+CONFIG_FB_MATROX=y
+CONFIG_FB_MATROX_MILLENIUM=y
+CONFIG_FB_MATROX_MYSTIQUE=y
+# CONFIG_FB_MATROX_G is not set
+CONFIG_FB_MATROX_MULTIHEAD=y
+# CONFIG_FB_RADEON_OLD is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_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_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+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 is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -580,6 +701,10 @@ CONFIG_EXT2_FS=y
# CONFIG_JBD is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
# CONFIG_XFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
@@ -627,6 +752,7 @@ CONFIG_RAMFS=y
CONFIG_JFFS2_FS=y
CONFIG_JFFS2_FS_DEBUG=0
# CONFIG_JFFS2_FS_NAND is not set
+# CONFIG_JFFS2_FS_NOR_ECC is not set
# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
CONFIG_JFFS2_ZLIB=y
CONFIG_JFFS2_RTIME=y
@@ -693,90 +819,20 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_PROFILING is not set
#
-# Graphics support
-#
-CONFIG_FB=y
-CONFIG_FB_MODE_HELPERS=y
-# CONFIG_FB_TILEBLITTING is not set
-# CONFIG_FB_CIRRUS is not set
-# CONFIG_FB_PM2 is not set
-# CONFIG_FB_ARMCLCD is not set
-# CONFIG_FB_CYBER2000 is not set
-# CONFIG_FB_ASILIANT is not set
-# CONFIG_FB_IMSTT is not set
-# CONFIG_FB_RIVA is not set
-CONFIG_FB_MATROX=y
-CONFIG_FB_MATROX_MILLENIUM=y
-CONFIG_FB_MATROX_MYSTIQUE=y
-CONFIG_FB_MATROX_G450=y
-CONFIG_FB_MATROX_G100=y
-CONFIG_FB_MATROX_MULTIHEAD=y
-# CONFIG_FB_RADEON_OLD is not set
-# CONFIG_FB_RADEON is not set
-# CONFIG_FB_ATY128 is not set
-# CONFIG_FB_ATY is not set
-# CONFIG_FB_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_VIRTUAL is not set
-
-#
-# Console display driver support
-#
-CONFIG_VGA_CONSOLE=y
-CONFIG_DUMMY_CONSOLE=y
-# CONFIG_FRAMEBUFFER_CONSOLE is not set
-
-#
-# Logo configuration
-#
-# CONFIG_LOGO is not set
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# Misc devices
-#
-
-#
-# USB support
-#
-# CONFIG_USB is not set
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
-# CONFIG_MMC is not set
-
-#
# Kernel hacking
#
+# CONFIG_PRINTK_TIME is not set
CONFIG_DEBUG_KERNEL=y
CONFIG_MAGIC_SYSRQ=y
+CONFIG_LOG_BUF_SHIFT=14
# 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_BUGVERBOSE=y
# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_FS is not set
CONFIG_FRAME_POINTER=y
# CONFIG_DEBUG_USER is not set
# CONFIG_DEBUG_WAITQ is not set
@@ -795,6 +851,10 @@ CONFIG_DEBUG_ERRORS=y
# CONFIG_CRYPTO is not set
#
+# Hardware crypto devices
+#
+
+#
# Library routines
#
# CONFIG_CRC_CCITT is not set
diff --git a/arch/arm/configs/iq31244_defconfig b/arch/arm/configs/iq31244_defconfig
index 5dd8397ca17c3..e71443b973908 100644
--- a/arch/arm/configs/iq31244_defconfig
+++ b/arch/arm/configs/iq31244_defconfig
@@ -1,12 +1,13 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.10
-# Thu Jan 6 10:53:05 2005
+# Linux kernel version: 2.6.12-rc1-bk2
+# Sun Mar 27 02:10:38 2005
#
CONFIG_ARM=y
CONFIG_MMU=y
CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_GENERIC_IOMAP=y
#
@@ -27,7 +28,6 @@ CONFIG_BSD_PROCESS_ACCT=y
# CONFIG_BSD_PROCESS_ACCT_V3 is not set
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
# CONFIG_HOTPLUG is not set
CONFIG_KOBJECT_UEVENT=y
CONFIG_IKCONFIG=y
@@ -35,6 +35,7 @@ CONFIG_IKCONFIG_PROC=y
# CONFIG_EMBEDDED is not set
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
@@ -44,6 +45,7 @@ CONFIG_CC_ALIGN_LABELS=0
CONFIG_CC_ALIGN_LOOPS=0
CONFIG_CC_ALIGN_JUMPS=0
# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
#
# Loadable module support
@@ -118,49 +120,75 @@ CONFIG_CPU_MINICACHE=y
CONFIG_XSCALE_PMU=y
#
-# General setup
+# Bus support
#
CONFIG_PCI=y
+# CONFIG_PCI_LEGACY_PROC is not set
+CONFIG_PCI_NAMES=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_PREEMPT is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
CONFIG_ZBOOT_ROM_TEXT=0x0
CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="ip=boot root=nfs console=ttyS0,115200"
# CONFIG_XIP_KERNEL is not set
-# CONFIG_PCI_LEGACY_PROC is not set
-CONFIG_PCI_NAMES=y
#
-# At least one math emulation must be selected
+# 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=y
# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
#
-# Generic Driver Options
+# Power management options
#
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
# CONFIG_PM is not set
-# CONFIG_PREEMPT is not set
-# CONFIG_ARTHUR is not set
-CONFIG_CMDLINE="ip=boot root=nfs console=ttyS0,115200"
-CONFIG_ALIGNMENT_TRAP=y
#
-# Parallel port support
+# Device Drivers
#
-# CONFIG_PARPORT is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
#
# Memory Technology Devices (MTD)
#
CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
-CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
CONFIG_MTD_REDBOOT_PARTS=y
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
CONFIG_MTD_REDBOOT_PARTS_READONLY=y
# CONFIG_MTD_CMDLINE_PARTS is not set
@@ -199,6 +227,7 @@ CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_XIP is not set
#
# Mapping drivers for chip access
@@ -219,6 +248,7 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=2
# 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
@@ -233,6 +263,11 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=2
# CONFIG_MTD_NAND is not set
#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
# Plug and Play support
#
@@ -244,6 +279,7 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=2
# CONFIG_BLK_CPQ_CISS_DA is not set
# CONFIG_BLK_DEV_DAC960 is not set
# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
# CONFIG_BLK_DEV_LOOP is not set
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_SX8 is not set
@@ -261,6 +297,78 @@ CONFIG_IOSCHED_NOOP=y
CONFIG_IOSCHED_AS=y
CONFIG_IOSCHED_DEADLINE=y
CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+CONFIG_CHR_DEV_SG=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_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+CONFIG_SCSI_QLA2XXX=y
+# CONFIG_SCSI_QLA21XX is not set
+# CONFIG_SCSI_QLA22XX is not set
+# CONFIG_SCSI_QLA2300 is not set
+# CONFIG_SCSI_QLA2322 is not set
+# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
#
# Multi-device support (RAID and LVM)
@@ -280,6 +388,22 @@ CONFIG_BLK_DEV_DM=y
# 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
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
#
# Networking support
@@ -406,94 +530,6 @@ CONFIG_E1000_NAPI=y
# CONFIG_NETCONSOLE is not set
#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-CONFIG_SCSI=y
-CONFIG_SCSI_PROC_FS=y
-
-#
-# SCSI support type (disk, tape, CD-ROM)
-#
-CONFIG_BLK_DEV_SD=y
-# CONFIG_CHR_DEV_ST is not set
-# CONFIG_CHR_DEV_OSST is not set
-# CONFIG_BLK_DEV_SR is not set
-CONFIG_CHR_DEV_SG=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_LOGGING is not set
-
-#
-# SCSI Transport Attributes
-#
-# CONFIG_SCSI_SPI_ATTRS is not set
-# CONFIG_SCSI_FC_ATTRS is not set
-
-#
-# SCSI low-level drivers
-#
-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
-# CONFIG_SCSI_3W_9XXX is not set
-# CONFIG_SCSI_ACARD is not set
-# CONFIG_SCSI_AACRAID is not set
-# CONFIG_SCSI_AIC7XXX is not set
-# CONFIG_SCSI_AIC7XXX_OLD is not set
-# CONFIG_SCSI_AIC79XX is not set
-# CONFIG_SCSI_DPT_I2O is not set
-# CONFIG_MEGARAID_NEWGEN is not set
-# CONFIG_MEGARAID_LEGACY is not set
-# CONFIG_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_EATA_PIO is not set
-# CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
-# CONFIG_SCSI_IPS is not set
-# CONFIG_SCSI_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 is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
-# CONFIG_SCSI_QLOGIC_1280 is not set
-CONFIG_SCSI_QLA2XXX=y
-# CONFIG_SCSI_QLA21XX is not set
-# CONFIG_SCSI_QLA22XX is not set
-# CONFIG_SCSI_QLA2300 is not set
-# CONFIG_SCSI_QLA2322 is not set
-# CONFIG_SCSI_QLA6312 is not set
-# CONFIG_SCSI_QLA6322 is not set
-# CONFIG_SCSI_DC395x is not set
-# CONFIG_SCSI_DC390T is not set
-# CONFIG_SCSI_NSP32 is not set
-# CONFIG_SCSI_DEBUG is not set
-
-#
-# 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
-
-#
# ISDN subsystem
#
# CONFIG_ISDN is not set
@@ -516,13 +552,6 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
# CONFIG_INPUT_EVBUG is not set
#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-# CONFIG_SERIO is not set
-
-#
# Input Device Drivers
#
# CONFIG_INPUT_KEYBOARD is not set
@@ -532,6 +561,13 @@ CONFIG_SOUND_GAMEPORT=y
# CONFIG_INPUT_MISC is not set
#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
+#
# Character devices
#
CONFIG_VT=y
@@ -578,6 +614,11 @@ CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_RAW_DRIVER is not set
#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
# I2C support
#
CONFIG_I2C=y
@@ -628,7 +669,9 @@ CONFIG_I2C_IOP3XX=y
# CONFIG_SENSORS_ASB100 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
# CONFIG_SENSORS_IT87 is not set
# CONFIG_SENSORS_LM63 is not set
# CONFIG_SENSORS_LM75 is not set
@@ -641,6 +684,8 @@ CONFIG_I2C_IOP3XX=y
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_SIS5595 is not set
# CONFIG_SENSORS_SMSC47M1 is not set
# CONFIG_SENSORS_VIA686A is not set
# CONFIG_SENSORS_W83781D is not set
@@ -660,6 +705,10 @@ CONFIG_I2C_IOP3XX=y
# CONFIG_I2C_DEBUG_CHIP is not set
#
+# Misc devices
+#
+
+#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -670,6 +719,39 @@ CONFIG_I2C_IOP3XX=y
# 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 is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -683,7 +765,12 @@ CONFIG_JBD=y
CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
CONFIG_XFS_FS=y
+CONFIG_XFS_EXPORT=y
# CONFIG_XFS_RT is not set
# CONFIG_XFS_QUOTA is not set
CONFIG_XFS_SECURITY=y
@@ -734,6 +821,7 @@ CONFIG_RAMFS=y
CONFIG_JFFS2_FS=y
CONFIG_JFFS2_FS_DEBUG=0
# CONFIG_JFFS2_FS_NAND is not set
+# CONFIG_JFFS2_FS_NOR_ECC is not set
# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
CONFIG_JFFS2_ZLIB=y
CONFIG_JFFS2_RTIME=y
@@ -800,51 +888,12 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_PROFILING 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
-
-#
-# Misc devices
-#
-
-#
-# USB support
-#
-# CONFIG_USB is not set
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
-# CONFIG_MMC is not set
-
-#
# Kernel hacking
#
+# CONFIG_PRINTK_TIME is not set
# CONFIG_DEBUG_KERNEL is not set
-# CONFIG_DEBUG_INFO is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_FRAME_POINTER=y
CONFIG_DEBUG_USER=y
@@ -860,6 +909,10 @@ CONFIG_DEBUG_USER=y
# CONFIG_CRYPTO is not set
#
+# Hardware crypto devices
+#
+
+#
# Library routines
#
# CONFIG_CRC_CCITT is not set
diff --git a/arch/arm/configs/iq80321_defconfig b/arch/arm/configs/iq80321_defconfig
index 527b62a0f8ff2..ab5ad23b27da0 100644
--- a/arch/arm/configs/iq80321_defconfig
+++ b/arch/arm/configs/iq80321_defconfig
@@ -1,12 +1,13 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.10
-# Thu Jan 6 10:52:05 2005
+# Linux kernel version: 2.6.12-rc1-bk2
+# Sun Mar 27 13:24:10 2005
#
CONFIG_ARM=y
CONFIG_MMU=y
CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_GENERIC_IOMAP=y
#
@@ -27,13 +28,13 @@ CONFIG_BSD_PROCESS_ACCT=y
# CONFIG_BSD_PROCESS_ACCT_V3 is not set
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
# CONFIG_HOTPLUG is not set
CONFIG_KOBJECT_UEVENT=y
# CONFIG_IKCONFIG is not set
# CONFIG_EMBEDDED is not set
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
@@ -43,6 +44,7 @@ CONFIG_CC_ALIGN_LABELS=0
CONFIG_CC_ALIGN_LOOPS=0
CONFIG_CC_ALIGN_JUMPS=0
# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
#
# Loadable module support
@@ -117,49 +119,75 @@ CONFIG_CPU_MINICACHE=y
CONFIG_XSCALE_PMU=y
#
-# General setup
+# Bus support
#
CONFIG_PCI=y
+# CONFIG_PCI_LEGACY_PROC is not set
+CONFIG_PCI_NAMES=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_PREEMPT is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
CONFIG_ZBOOT_ROM_TEXT=0x0
CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="ip=boot root=nfs console=ttyS0,115200"
# CONFIG_XIP_KERNEL is not set
-# CONFIG_PCI_LEGACY_PROC is not set
-CONFIG_PCI_NAMES=y
#
-# At least one math emulation must be selected
+# 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=y
# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
#
-# Generic Driver Options
+# Power management options
#
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
# CONFIG_PM is not set
-# CONFIG_PREEMPT is not set
-# CONFIG_ARTHUR is not set
-CONFIG_CMDLINE="ip=boot root=nfs console=ttyS0,115200"
-CONFIG_ALIGNMENT_TRAP=y
#
-# Parallel port support
+# Device Drivers
#
-# CONFIG_PARPORT is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
#
# Memory Technology Devices (MTD)
#
CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
-CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
CONFIG_MTD_REDBOOT_PARTS=y
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
CONFIG_MTD_REDBOOT_PARTS_READONLY=y
# CONFIG_MTD_CMDLINE_PARTS is not set
@@ -198,6 +226,7 @@ CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_XIP is not set
#
# Mapping drivers for chip access
@@ -218,6 +247,7 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=1
# 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
@@ -232,6 +262,11 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=1
# CONFIG_MTD_NAND is not set
#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
# Plug and Play support
#
@@ -243,6 +278,7 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=1
# CONFIG_BLK_CPQ_CISS_DA is not set
# CONFIG_BLK_DEV_DAC960 is not set
# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
# CONFIG_BLK_DEV_LOOP is not set
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_SX8 is not set
@@ -260,6 +296,17 @@ CONFIG_IOSCHED_NOOP=y
CONFIG_IOSCHED_AS=y
CONFIG_IOSCHED_DEADLINE=y
CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
#
# Multi-device support (RAID and LVM)
@@ -267,6 +314,20 @@ CONFIG_IOSCHED_CFQ=y
# CONFIG_MD is not set
#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
# Networking support
#
CONFIG_NET=y
@@ -390,30 +451,6 @@ CONFIG_E1000_NAPI=y
# CONFIG_NETCONSOLE is not set
#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-# CONFIG_SCSI is not set
-
-#
-# Fusion MPT device support
-#
-
-#
-# IEEE 1394 (FireWire) support
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-
-#
# ISDN subsystem
#
# CONFIG_ISDN is not set
@@ -436,13 +473,6 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
# CONFIG_INPUT_EVBUG is not set
#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-# CONFIG_SERIO is not set
-
-#
# Input Device Drivers
#
# CONFIG_INPUT_KEYBOARD is not set
@@ -452,6 +482,13 @@ CONFIG_SOUND_GAMEPORT=y
# CONFIG_INPUT_MISC is not set
#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
+#
# Character devices
#
CONFIG_VT=y
@@ -498,6 +535,11 @@ CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_RAW_DRIVER is not set
#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
# I2C support
#
CONFIG_I2C=y
@@ -548,7 +590,9 @@ CONFIG_I2C_IOP3XX=y
# CONFIG_SENSORS_ASB100 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
# CONFIG_SENSORS_IT87 is not set
# CONFIG_SENSORS_LM63 is not set
# CONFIG_SENSORS_LM75 is not set
@@ -561,6 +605,8 @@ CONFIG_I2C_IOP3XX=y
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_SIS5595 is not set
# CONFIG_SENSORS_SMSC47M1 is not set
# CONFIG_SENSORS_VIA686A is not set
# CONFIG_SENSORS_W83781D is not set
@@ -580,6 +626,10 @@ CONFIG_I2C_IOP3XX=y
# CONFIG_I2C_DEBUG_CHIP is not set
#
+# Misc devices
+#
+
+#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -590,6 +640,39 @@ CONFIG_I2C_IOP3XX=y
# 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 is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -603,7 +686,12 @@ CONFIG_JBD=y
CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
CONFIG_XFS_FS=y
+CONFIG_XFS_EXPORT=y
# CONFIG_XFS_RT is not set
# CONFIG_XFS_QUOTA is not set
CONFIG_XFS_SECURITY=y
@@ -654,6 +742,7 @@ CONFIG_RAMFS=y
CONFIG_JFFS2_FS=y
CONFIG_JFFS2_FS_DEBUG=0
# CONFIG_JFFS2_FS_NAND is not set
+# CONFIG_JFFS2_FS_NOR_ECC is not set
# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
CONFIG_JFFS2_ZLIB=y
CONFIG_JFFS2_RTIME=y
@@ -720,51 +809,12 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_PROFILING 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
-
-#
-# Misc devices
-#
-
-#
-# USB support
-#
-# CONFIG_USB is not set
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
-# CONFIG_MMC is not set
-
-#
# Kernel hacking
#
+# CONFIG_PRINTK_TIME is not set
# CONFIG_DEBUG_KERNEL is not set
-# CONFIG_DEBUG_INFO is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_FRAME_POINTER=y
CONFIG_DEBUG_USER=y
@@ -780,6 +830,10 @@ CONFIG_DEBUG_USER=y
# CONFIG_CRYPTO is not set
#
+# Hardware crypto devices
+#
+
+#
# Library routines
#
# CONFIG_CRC_CCITT is not set
diff --git a/arch/arm/configs/iq80331_defconfig b/arch/arm/configs/iq80331_defconfig
index 43aeebbb92052..bb536133ef87d 100644
--- a/arch/arm/configs/iq80331_defconfig
+++ b/arch/arm/configs/iq80331_defconfig
@@ -1,12 +1,13 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.10
-# Thu Jan 6 10:44:16 2005
+# Linux kernel version: 2.6.12-rc1-bk2
+# Sun Mar 27 15:13:37 2005
#
CONFIG_ARM=y
CONFIG_MMU=y
CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_GENERIC_IOMAP=y
#
@@ -27,13 +28,13 @@ CONFIG_BSD_PROCESS_ACCT=y
# CONFIG_BSD_PROCESS_ACCT_V3 is not set
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
# CONFIG_HOTPLUG is not set
CONFIG_KOBJECT_UEVENT=y
# CONFIG_IKCONFIG is not set
# CONFIG_EMBEDDED is not set
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
@@ -43,6 +44,7 @@ CONFIG_CC_ALIGN_LABELS=0
CONFIG_CC_ALIGN_LOOPS=0
CONFIG_CC_ALIGN_JUMPS=0
# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
#
# Loadable module support
@@ -117,49 +119,75 @@ CONFIG_CPU_MINICACHE=y
CONFIG_XSCALE_PMU=y
#
-# General setup
+# Bus support
#
CONFIG_PCI=y
+# CONFIG_PCI_LEGACY_PROC is not set
+CONFIG_PCI_NAMES=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_PREEMPT is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
CONFIG_ZBOOT_ROM_TEXT=0x0
CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="ip=boot root=nfs console=ttyS0,115200"
# CONFIG_XIP_KERNEL is not set
-# CONFIG_PCI_LEGACY_PROC is not set
-CONFIG_PCI_NAMES=y
#
-# At least one math emulation must be selected
+# 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=y
# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
#
-# Generic Driver Options
+# Power management options
#
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
# CONFIG_PM is not set
-# CONFIG_PREEMPT is not set
-# CONFIG_ARTHUR is not set
-CONFIG_CMDLINE="ip=boot root=nfs console=ttyS0,115200"
-CONFIG_ALIGNMENT_TRAP=y
#
-# Parallel port support
+# Device Drivers
#
-# CONFIG_PARPORT is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
#
# Memory Technology Devices (MTD)
#
CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
-CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
CONFIG_MTD_REDBOOT_PARTS=y
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
CONFIG_MTD_REDBOOT_PARTS_READONLY=y
# CONFIG_MTD_CMDLINE_PARTS is not set
@@ -202,6 +230,7 @@ CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_XIP is not set
#
# Mapping drivers for chip access
@@ -222,6 +251,7 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=1
# 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
@@ -236,6 +266,11 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=1
# CONFIG_MTD_NAND is not set
#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
# Plug and Play support
#
@@ -247,6 +282,7 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=1
# CONFIG_BLK_CPQ_CISS_DA is not set
# CONFIG_BLK_DEV_DAC960 is not set
# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
# CONFIG_BLK_DEV_LOOP is not set
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_SX8 is not set
@@ -264,6 +300,78 @@ CONFIG_IOSCHED_NOOP=y
CONFIG_IOSCHED_AS=y
CONFIG_IOSCHED_DEADLINE=y
CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+CONFIG_CHR_DEV_SG=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_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+CONFIG_SCSI_QLA2XXX=y
+# CONFIG_SCSI_QLA21XX is not set
+# CONFIG_SCSI_QLA22XX is not set
+# CONFIG_SCSI_QLA2300 is not set
+# CONFIG_SCSI_QLA2322 is not set
+# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
#
# Multi-device support (RAID and LVM)
@@ -283,6 +391,22 @@ CONFIG_BLK_DEV_DM=y
# 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
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
#
# Networking support
@@ -409,94 +533,6 @@ CONFIG_E1000_NAPI=y
# CONFIG_NETCONSOLE is not set
#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-CONFIG_SCSI=y
-CONFIG_SCSI_PROC_FS=y
-
-#
-# SCSI support type (disk, tape, CD-ROM)
-#
-CONFIG_BLK_DEV_SD=y
-# CONFIG_CHR_DEV_ST is not set
-# CONFIG_CHR_DEV_OSST is not set
-# CONFIG_BLK_DEV_SR is not set
-CONFIG_CHR_DEV_SG=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_LOGGING is not set
-
-#
-# SCSI Transport Attributes
-#
-# CONFIG_SCSI_SPI_ATTRS is not set
-# CONFIG_SCSI_FC_ATTRS is not set
-
-#
-# SCSI low-level drivers
-#
-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
-# CONFIG_SCSI_3W_9XXX is not set
-# CONFIG_SCSI_ACARD is not set
-# CONFIG_SCSI_AACRAID is not set
-# CONFIG_SCSI_AIC7XXX is not set
-# CONFIG_SCSI_AIC7XXX_OLD is not set
-# CONFIG_SCSI_AIC79XX is not set
-# CONFIG_SCSI_DPT_I2O is not set
-# CONFIG_MEGARAID_NEWGEN is not set
-# CONFIG_MEGARAID_LEGACY is not set
-# CONFIG_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_EATA_PIO is not set
-# CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
-# CONFIG_SCSI_IPS is not set
-# CONFIG_SCSI_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 is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
-# CONFIG_SCSI_QLOGIC_1280 is not set
-CONFIG_SCSI_QLA2XXX=y
-# CONFIG_SCSI_QLA21XX is not set
-# CONFIG_SCSI_QLA22XX is not set
-# CONFIG_SCSI_QLA2300 is not set
-# CONFIG_SCSI_QLA2322 is not set
-# CONFIG_SCSI_QLA6312 is not set
-# CONFIG_SCSI_QLA6322 is not set
-# CONFIG_SCSI_DC395x is not set
-# CONFIG_SCSI_DC390T is not set
-# CONFIG_SCSI_NSP32 is not set
-# CONFIG_SCSI_DEBUG is not set
-
-#
-# 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
-
-#
# ISDN subsystem
#
# CONFIG_ISDN is not set
@@ -519,13 +555,6 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
# CONFIG_INPUT_EVBUG is not set
#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-# CONFIG_SERIO is not set
-
-#
# Input Device Drivers
#
# CONFIG_INPUT_KEYBOARD is not set
@@ -535,6 +564,13 @@ CONFIG_SOUND_GAMEPORT=y
# CONFIG_INPUT_MISC is not set
#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
+#
# Character devices
#
CONFIG_VT=y
@@ -581,6 +617,11 @@ CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_RAW_DRIVER is not set
#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
# I2C support
#
CONFIG_I2C=y
@@ -631,7 +672,9 @@ CONFIG_I2C_IOP3XX=y
# CONFIG_SENSORS_ASB100 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
# CONFIG_SENSORS_IT87 is not set
# CONFIG_SENSORS_LM63 is not set
# CONFIG_SENSORS_LM75 is not set
@@ -644,6 +687,8 @@ CONFIG_I2C_IOP3XX=y
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_SIS5595 is not set
# CONFIG_SENSORS_SMSC47M1 is not set
# CONFIG_SENSORS_VIA686A is not set
# CONFIG_SENSORS_W83781D is not set
@@ -663,6 +708,10 @@ CONFIG_I2C_IOP3XX=y
# CONFIG_I2C_DEBUG_CHIP is not set
#
+# Misc devices
+#
+
+#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -673,6 +722,39 @@ CONFIG_I2C_IOP3XX=y
# 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 is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -686,7 +768,12 @@ CONFIG_JBD=y
CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
CONFIG_XFS_FS=y
+CONFIG_XFS_EXPORT=y
# CONFIG_XFS_RT is not set
# CONFIG_XFS_QUOTA is not set
CONFIG_XFS_SECURITY=y
@@ -797,51 +884,12 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_PROFILING 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
-
-#
-# Misc devices
-#
-
-#
-# USB support
-#
-# CONFIG_USB is not set
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
-# CONFIG_MMC is not set
-
-#
# Kernel hacking
#
+# CONFIG_PRINTK_TIME is not set
# CONFIG_DEBUG_KERNEL is not set
-# CONFIG_DEBUG_INFO is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_FRAME_POINTER=y
CONFIG_DEBUG_USER=y
@@ -857,6 +905,10 @@ CONFIG_DEBUG_USER=y
# CONFIG_CRYPTO is not set
#
+# Hardware crypto devices
+#
+
+#
# Library routines
#
# CONFIG_CRC_CCITT is not set
diff --git a/arch/arm/configs/iq80332_defconfig b/arch/arm/configs/iq80332_defconfig
index f6dacc4539d2c..305f01f3a7299 100644
--- a/arch/arm/configs/iq80332_defconfig
+++ b/arch/arm/configs/iq80332_defconfig
@@ -1,12 +1,13 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.10
-# Thu Jan 6 10:51:02 2005
+# Linux kernel version: 2.6.12-rc1-bk2
+# Sun Mar 27 17:33:39 2005
#
CONFIG_ARM=y
CONFIG_MMU=y
CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_GENERIC_IOMAP=y
#
@@ -27,13 +28,13 @@ CONFIG_BSD_PROCESS_ACCT=y
# CONFIG_BSD_PROCESS_ACCT_V3 is not set
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
# CONFIG_HOTPLUG is not set
CONFIG_KOBJECT_UEVENT=y
# CONFIG_IKCONFIG is not set
# CONFIG_EMBEDDED is not set
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
@@ -43,6 +44,7 @@ CONFIG_CC_ALIGN_LABELS=0
CONFIG_CC_ALIGN_LOOPS=0
CONFIG_CC_ALIGN_JUMPS=0
# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
#
# Loadable module support
@@ -117,49 +119,75 @@ CONFIG_CPU_MINICACHE=y
CONFIG_XSCALE_PMU=y
#
-# General setup
+# Bus support
#
CONFIG_PCI=y
+# CONFIG_PCI_LEGACY_PROC is not set
+CONFIG_PCI_NAMES=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_PREEMPT is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
CONFIG_ZBOOT_ROM_TEXT=0x0
CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="ip=boot root=nfs console=ttyS0,115200"
# CONFIG_XIP_KERNEL is not set
-# CONFIG_PCI_LEGACY_PROC is not set
-CONFIG_PCI_NAMES=y
#
-# At least one math emulation must be selected
+# 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=y
# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
#
-# Generic Driver Options
+# Power management options
#
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
# CONFIG_PM is not set
-# CONFIG_PREEMPT is not set
-# CONFIG_ARTHUR is not set
-CONFIG_CMDLINE="ip=boot root=nfs console=ttyS0,115200"
-CONFIG_ALIGNMENT_TRAP=y
#
-# Parallel port support
+# Device Drivers
#
-# CONFIG_PARPORT is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
#
# Memory Technology Devices (MTD)
#
CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
-CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
CONFIG_MTD_REDBOOT_PARTS=y
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
CONFIG_MTD_REDBOOT_PARTS_READONLY=y
# CONFIG_MTD_CMDLINE_PARTS is not set
@@ -202,6 +230,7 @@ CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_XIP is not set
#
# Mapping drivers for chip access
@@ -222,6 +251,7 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=1
# 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
@@ -236,6 +266,11 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=1
# CONFIG_MTD_NAND is not set
#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
# Plug and Play support
#
@@ -247,6 +282,7 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=1
# CONFIG_BLK_CPQ_CISS_DA is not set
# CONFIG_BLK_DEV_DAC960 is not set
# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
# CONFIG_BLK_DEV_LOOP is not set
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_SX8 is not set
@@ -264,6 +300,78 @@ CONFIG_IOSCHED_NOOP=y
CONFIG_IOSCHED_AS=y
CONFIG_IOSCHED_DEADLINE=y
CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+CONFIG_CHR_DEV_SG=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_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+CONFIG_SCSI_QLA2XXX=y
+# CONFIG_SCSI_QLA21XX is not set
+# CONFIG_SCSI_QLA22XX is not set
+# CONFIG_SCSI_QLA2300 is not set
+# CONFIG_SCSI_QLA2322 is not set
+# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
#
# Multi-device support (RAID and LVM)
@@ -283,6 +391,22 @@ CONFIG_BLK_DEV_DM=y
# 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
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
#
# Networking support
@@ -409,94 +533,6 @@ CONFIG_E1000_NAPI=y
# CONFIG_NETCONSOLE is not set
#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-CONFIG_SCSI=y
-CONFIG_SCSI_PROC_FS=y
-
-#
-# SCSI support type (disk, tape, CD-ROM)
-#
-CONFIG_BLK_DEV_SD=y
-# CONFIG_CHR_DEV_ST is not set
-# CONFIG_CHR_DEV_OSST is not set
-# CONFIG_BLK_DEV_SR is not set
-CONFIG_CHR_DEV_SG=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_LOGGING is not set
-
-#
-# SCSI Transport Attributes
-#
-# CONFIG_SCSI_SPI_ATTRS is not set
-# CONFIG_SCSI_FC_ATTRS is not set
-
-#
-# SCSI low-level drivers
-#
-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
-# CONFIG_SCSI_3W_9XXX is not set
-# CONFIG_SCSI_ACARD is not set
-# CONFIG_SCSI_AACRAID is not set
-# CONFIG_SCSI_AIC7XXX is not set
-# CONFIG_SCSI_AIC7XXX_OLD is not set
-# CONFIG_SCSI_AIC79XX is not set
-# CONFIG_SCSI_DPT_I2O is not set
-# CONFIG_MEGARAID_NEWGEN is not set
-# CONFIG_MEGARAID_LEGACY is not set
-# CONFIG_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_EATA_PIO is not set
-# CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
-# CONFIG_SCSI_IPS is not set
-# CONFIG_SCSI_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 is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
-# CONFIG_SCSI_QLOGIC_1280 is not set
-CONFIG_SCSI_QLA2XXX=y
-# CONFIG_SCSI_QLA21XX is not set
-# CONFIG_SCSI_QLA22XX is not set
-# CONFIG_SCSI_QLA2300 is not set
-# CONFIG_SCSI_QLA2322 is not set
-# CONFIG_SCSI_QLA6312 is not set
-# CONFIG_SCSI_QLA6322 is not set
-# CONFIG_SCSI_DC395x is not set
-# CONFIG_SCSI_DC390T is not set
-# CONFIG_SCSI_NSP32 is not set
-# CONFIG_SCSI_DEBUG is not set
-
-#
-# 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
-
-#
# ISDN subsystem
#
# CONFIG_ISDN is not set
@@ -519,13 +555,6 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
# CONFIG_INPUT_EVBUG is not set
#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-# CONFIG_SERIO is not set
-
-#
# Input Device Drivers
#
# CONFIG_INPUT_KEYBOARD is not set
@@ -535,6 +564,13 @@ CONFIG_SOUND_GAMEPORT=y
# CONFIG_INPUT_MISC is not set
#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
+#
# Character devices
#
CONFIG_VT=y
@@ -581,6 +617,11 @@ CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_RAW_DRIVER is not set
#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
# I2C support
#
CONFIG_I2C=y
@@ -631,7 +672,9 @@ CONFIG_I2C_IOP3XX=y
# CONFIG_SENSORS_ASB100 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
# CONFIG_SENSORS_IT87 is not set
# CONFIG_SENSORS_LM63 is not set
# CONFIG_SENSORS_LM75 is not set
@@ -644,6 +687,8 @@ CONFIG_I2C_IOP3XX=y
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_SIS5595 is not set
# CONFIG_SENSORS_SMSC47M1 is not set
# CONFIG_SENSORS_VIA686A is not set
# CONFIG_SENSORS_W83781D is not set
@@ -663,6 +708,10 @@ CONFIG_I2C_IOP3XX=y
# CONFIG_I2C_DEBUG_CHIP is not set
#
+# Misc devices
+#
+
+#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -673,6 +722,39 @@ CONFIG_I2C_IOP3XX=y
# 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 is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -686,7 +768,12 @@ CONFIG_JBD=y
CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
CONFIG_XFS_FS=y
+CONFIG_XFS_EXPORT=y
# CONFIG_XFS_RT is not set
# CONFIG_XFS_QUOTA is not set
CONFIG_XFS_SECURITY=y
@@ -797,51 +884,12 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_PROFILING 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
-
-#
-# Misc devices
-#
-
-#
-# USB support
-#
-# CONFIG_USB is not set
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
-# CONFIG_MMC is not set
-
-#
# Kernel hacking
#
+# CONFIG_PRINTK_TIME is not set
# CONFIG_DEBUG_KERNEL is not set
-# CONFIG_DEBUG_INFO is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_FRAME_POINTER=y
CONFIG_DEBUG_USER=y
@@ -857,6 +905,10 @@ CONFIG_DEBUG_USER=y
# CONFIG_CRYPTO is not set
#
+# Hardware crypto devices
+#
+
+#
# Library routines
#
# CONFIG_CRC_CCITT is not set
diff --git a/arch/arm/configs/ixdp2400_defconfig b/arch/arm/configs/ixdp2400_defconfig
index 2f028ed2a1801..4fd663ecbe390 100644
--- a/arch/arm/configs/ixdp2400_defconfig
+++ b/arch/arm/configs/ixdp2400_defconfig
@@ -1,10 +1,14 @@
#
# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.12-rc1-bk2
+# Sun Mar 27 21:13:38 2005
#
CONFIG_ARM=y
CONFIG_MMU=y
CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_IOMAP=y
#
# Code maturity level options
@@ -16,6 +20,7 @@ CONFIG_BROKEN_ON_SMP=y
#
# General setup
#
+CONFIG_LOCALVERSION=""
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
# CONFIG_POSIX_MQUEUE is not set
@@ -23,20 +28,24 @@ CONFIG_BSD_PROCESS_ACCT=y
# CONFIG_BSD_PROCESS_ACCT_V3 is not set
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
# CONFIG_IKCONFIG is not set
CONFIG_EMBEDDED=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=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
@@ -64,7 +73,9 @@ CONFIG_ARCH_IXP2000=y
# CONFIG_ARCH_SHARK is not set
# CONFIG_ARCH_LH7A40X is not set
# CONFIG_ARCH_OMAP is not set
-# CONFIG_ARCH_VERSATILE_PB is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_H720X is not set
CONFIG_ARCH_SUPPORTS_BIG_ENDIAN=y
#
@@ -88,6 +99,7 @@ CONFIG_CPU_32=y
CONFIG_CPU_XSCALE=y
CONFIG_CPU_32v5=y
CONFIG_CPU_ABRT_EV5T=y
+CONFIG_CPU_CACHE_VIVT=y
CONFIG_CPU_TLB_V4WBI=y
CONFIG_CPU_MINICACHE=y
@@ -99,51 +111,75 @@ CONFIG_CPU_BIG_ENDIAN=y
CONFIG_XSCALE_PMU=y
#
-# General setup
+# Bus support
#
CONFIG_PCI=y
-# CONFIG_ZBOOT_ROM is not set
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
CONFIG_PCI_LEGACY_PROC=y
CONFIG_PCI_NAMES=y
#
-# At least one math emulation must be selected
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_PREEMPT is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="console=ttyS0,57600 root=/dev/nfs ip=bootp mem=64M@0x0 pci=firmware"
+# 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
-# CONFIG_VFP 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
#
-# Generic Driver Options
+# Power management options
#
-CONFIG_STANDALONE=y
-# CONFIG_PREVENT_FIRMWARE_BUILD is not set
-# CONFIG_DEBUG_DRIVER is not set
# CONFIG_PM is not set
-# CONFIG_PREEMPT is not set
-# CONFIG_ARTHUR is not set
-CONFIG_CMDLINE="console=ttyS0,57600 root=/dev/nfs ip=bootp mem=64M@0x0 pci=firmware"
-CONFIG_ALIGNMENT_TRAP=y
#
-# Parallel port support
+# Device Drivers
#
-# CONFIG_PARPORT is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
#
# Memory Technology Devices (MTD)
#
CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
-CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
CONFIG_MTD_REDBOOT_PARTS=y
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
CONFIG_MTD_REDBOOT_PARTS_READONLY=y
# CONFIG_MTD_CMDLINE_PARTS is not set
@@ -182,6 +218,7 @@ CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_XIP is not set
#
# Mapping drivers for chip access
@@ -201,6 +238,7 @@ CONFIG_MTD_IXP2000=y
# 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
@@ -215,6 +253,11 @@ CONFIG_MTD_IXP2000=y
# CONFIG_MTD_NAND is not set
#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
# Plug and Play support
#
@@ -226,13 +269,31 @@ CONFIG_MTD_IXP2000=y
# CONFIG_BLK_CPQ_CISS_DA is not set
# CONFIG_BLK_DEV_DAC960 is not set
# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_SX8 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_INITRAMFS_SOURCE=""
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
#
# Multi-device support (RAID and LVM)
@@ -240,6 +301,20 @@ CONFIG_BLK_DEV_INITRD=y
# CONFIG_MD is not set
#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
# Networking support
#
CONFIG_NET=y
@@ -266,6 +341,9 @@ CONFIG_SYN_COOKIES=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_IP_TCPDIAG is not set
+# CONFIG_IP_TCPDIAG_IPV6 is not set
# CONFIG_IPV6 is not set
# CONFIG_NETFILTER is not set
@@ -285,8 +363,6 @@ CONFIG_SYN_COOKIES=y
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_FASTROUTE is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
#
# QoS and/or fair queueing
@@ -337,7 +413,6 @@ CONFIG_NET_PCI=y
# CONFIG_FORCEDETH is not set
# CONFIG_DGRS is not set
CONFIG_EEPRO100=y
-# CONFIG_EEPRO100_PIO is not set
# CONFIG_E100 is not set
# CONFIG_FEALNX is not set
# CONFIG_NATSEMI is not set
@@ -349,7 +424,6 @@ CONFIG_EEPRO100=y
# CONFIG_SUNDANCE is not set
# CONFIG_TLAN is not set
# CONFIG_VIA_RHINE is not set
-# CONFIG_VIA_VELOCITY is not set
#
# Ethernet (1000 Mbit)
@@ -362,6 +436,7 @@ CONFIG_EEPRO100=y
# CONFIG_YELLOWFIN is not set
# CONFIG_R8169 is not set
# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
# CONFIG_TIGON3 is not set
#
@@ -411,25 +486,6 @@ CONFIG_DLCI_MAX=8
# CONFIG_NETCONSOLE is not set
#
-# SCSI device support
-#
-# CONFIG_SCSI is not set
-
-#
-# Fusion MPT device support
-#
-
-#
-# IEEE 1394 (FireWire) support
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-
-#
# ISDN subsystem
#
# CONFIG_ISDN is not set
@@ -452,14 +508,6 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
# CONFIG_INPUT_EVBUG is not set
#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-# CONFIG_SERIO is not set
-# CONFIG_SERIO_I8042 is not set
-
-#
# Input Device Drivers
#
# CONFIG_INPUT_KEYBOARD is not set
@@ -469,6 +517,13 @@ CONFIG_SOUND_GAMEPORT=y
# CONFIG_INPUT_MISC is not set
#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
+#
# Character devices
#
# CONFIG_VT is not set
@@ -490,7 +545,6 @@ CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
-# CONFIG_QIC02_TAPE is not set
#
# IPMI
@@ -516,7 +570,6 @@ CONFIG_IXP2000_WATCHDOG=y
# CONFIG_WDTPCI is not set
# CONFIG_NVRAM is not set
# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
@@ -524,11 +577,15 @@ CONFIG_IXP2000_WATCHDOG=y
#
# 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
+
+#
# I2C support
#
CONFIG_I2C=y
@@ -539,6 +596,7 @@ CONFIG_I2C_CHARDEV=y
#
CONFIG_I2C_ALGOBIT=y
# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
#
# I2C Hardware Bus support
@@ -564,6 +622,7 @@ CONFIG_I2C_ALGOBIT=y
# 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
#
# Hardware Sensors Chip support
@@ -571,20 +630,29 @@ CONFIG_I2C_ALGOBIT=y
CONFIG_I2C_SENSOR=y
# CONFIG_SENSORS_ADM1021 is not set
# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ASB100 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
# CONFIG_SENSORS_LM75 is not set
# CONFIG_SENSORS_LM77 is not set
# CONFIG_SENSORS_LM78 is not set
# CONFIG_SENSORS_LM80 is not set
# CONFIG_SENSORS_LM83 is not set
# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
# CONFIG_SENSORS_VIA686A is not set
# CONFIG_SENSORS_W83781D is not set
# CONFIG_SENSORS_W83L785TS is not set
@@ -603,6 +671,10 @@ CONFIG_SENSORS_EEPROM=y
# CONFIG_I2C_DEBUG_CHIP is not set
#
+# Misc devices
+#
+
+#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -613,6 +685,33 @@ CONFIG_SENSORS_EEPROM=y
# 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
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -629,10 +728,15 @@ CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
CONFIG_FS_POSIX_ACL=y
+
+#
+# XFS support
+#
# CONFIG_XFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
@@ -657,6 +761,7 @@ CONFIG_SYSFS=y
# CONFIG_DEVFS_FS is not set
# CONFIG_DEVPTS_FS_XATTR is not set
CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
@@ -674,6 +779,7 @@ CONFIG_RAMFS=y
CONFIG_JFFS2_FS=y
CONFIG_JFFS2_FS_DEBUG=0
# CONFIG_JFFS2_FS_NAND is not set
+# CONFIG_JFFS2_FS_NOR_ECC is not set
# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
CONFIG_JFFS2_ZLIB=y
CONFIG_JFFS2_RTIME=y
@@ -696,9 +802,9 @@ CONFIG_NFS_V3=y
CONFIG_ROOT_NFS=y
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
-# CONFIG_EXPORTFS is not set
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
@@ -736,49 +842,31 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_PROFILING is not set
#
-# Graphics support
-#
-# CONFIG_FB is not set
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# Misc devices
-#
-
-#
-# USB support
-#
-# CONFIG_USB is not set
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
# Kernel hacking
#
-CONFIG_FRAME_POINTER=y
-CONFIG_DEBUG_USER=y
-# CONFIG_DEBUG_INFO is not set
+# CONFIG_PRINTK_TIME is not set
CONFIG_DEBUG_KERNEL=y
-# CONFIG_DEBUG_SLAB is not set
CONFIG_MAGIC_SYSRQ=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_WAITQ 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_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_WAITQ is not set
CONFIG_DEBUG_ERRORS=y
CONFIG_DEBUG_LL=y
# CONFIG_DEBUG_ICEDCC is not set
-# CONFIG_DEBUG_BDI2000_XSCALE is not set
#
# Security options
#
+# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
#
@@ -787,6 +875,10 @@ CONFIG_DEBUG_LL=y
# CONFIG_CRYPTO is not set
#
+# Hardware crypto devices
+#
+
+#
# Library routines
#
# CONFIG_CRC_CCITT is not set
diff --git a/arch/arm/configs/ixdp2401_defconfig b/arch/arm/configs/ixdp2401_defconfig
index 7af19ae3cb770..6f51c98084a35 100644
--- a/arch/arm/configs/ixdp2401_defconfig
+++ b/arch/arm/configs/ixdp2401_defconfig
@@ -1,10 +1,14 @@
#
# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.12-rc1-bk2
+# Sun Mar 27 21:53:55 2005
#
CONFIG_ARM=y
CONFIG_MMU=y
CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_IOMAP=y
#
# Code maturity level options
@@ -16,6 +20,7 @@ CONFIG_BROKEN_ON_SMP=y
#
# General setup
#
+CONFIG_LOCALVERSION=""
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
# CONFIG_POSIX_MQUEUE is not set
@@ -23,20 +28,24 @@ CONFIG_BSD_PROCESS_ACCT=y
# CONFIG_BSD_PROCESS_ACCT_V3 is not set
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
# CONFIG_IKCONFIG is not set
CONFIG_EMBEDDED=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=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
@@ -64,7 +73,9 @@ CONFIG_ARCH_IXP2000=y
# CONFIG_ARCH_SHARK is not set
# CONFIG_ARCH_LH7A40X is not set
# CONFIG_ARCH_OMAP is not set
-# CONFIG_ARCH_VERSATILE_PB is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_H720X is not set
CONFIG_ARCH_SUPPORTS_BIG_ENDIAN=y
#
@@ -88,6 +99,7 @@ CONFIG_CPU_32=y
CONFIG_CPU_XSCALE=y
CONFIG_CPU_32v5=y
CONFIG_CPU_ABRT_EV5T=y
+CONFIG_CPU_CACHE_VIVT=y
CONFIG_CPU_TLB_V4WBI=y
CONFIG_CPU_MINICACHE=y
@@ -99,51 +111,75 @@ CONFIG_CPU_BIG_ENDIAN=y
CONFIG_XSCALE_PMU=y
#
-# General setup
+# Bus support
#
CONFIG_PCI=y
-# CONFIG_ZBOOT_ROM is not set
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
CONFIG_PCI_LEGACY_PROC=y
CONFIG_PCI_NAMES=y
#
-# At least one math emulation must be selected
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_PREEMPT is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="console=ttyS0,57600 root=/dev/nfs ip=bootp mem=64M@0x0 pci=firmware"
+# 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
-# CONFIG_VFP 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
#
-# Generic Driver Options
+# Power management options
#
-CONFIG_STANDALONE=y
-# CONFIG_PREVENT_FIRMWARE_BUILD is not set
-# CONFIG_DEBUG_DRIVER is not set
# CONFIG_PM is not set
-# CONFIG_PREEMPT is not set
-# CONFIG_ARTHUR is not set
-CONFIG_CMDLINE="console=ttyS0,57600 root=/dev/nfs ip=bootp mem=64M@0x0 pci=firmware"
-CONFIG_ALIGNMENT_TRAP=y
#
-# Parallel port support
+# Device Drivers
#
-# CONFIG_PARPORT is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
#
# Memory Technology Devices (MTD)
#
CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
-CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
CONFIG_MTD_REDBOOT_PARTS=y
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
CONFIG_MTD_REDBOOT_PARTS_READONLY=y
# CONFIG_MTD_CMDLINE_PARTS is not set
@@ -182,6 +218,7 @@ CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_XIP is not set
#
# Mapping drivers for chip access
@@ -201,6 +238,7 @@ CONFIG_MTD_IXP2000=y
# 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
@@ -215,6 +253,11 @@ CONFIG_MTD_IXP2000=y
# CONFIG_MTD_NAND is not set
#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
# Plug and Play support
#
@@ -226,13 +269,31 @@ CONFIG_MTD_IXP2000=y
# CONFIG_BLK_CPQ_CISS_DA is not set
# CONFIG_BLK_DEV_DAC960 is not set
# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_SX8 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_INITRAMFS_SOURCE=""
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
#
# Multi-device support (RAID and LVM)
@@ -240,6 +301,20 @@ CONFIG_BLK_DEV_INITRD=y
# CONFIG_MD is not set
#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
# Networking support
#
CONFIG_NET=y
@@ -266,6 +341,9 @@ CONFIG_SYN_COOKIES=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
# CONFIG_IPV6 is not set
# CONFIG_NETFILTER is not set
@@ -285,8 +363,6 @@ CONFIG_SYN_COOKIES=y
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_FASTROUTE is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
#
# QoS and/or fair queueing
@@ -338,7 +414,6 @@ CONFIG_NET_PCI=y
CONFIG_CS89x0=y
# CONFIG_DGRS is not set
CONFIG_EEPRO100=y
-# CONFIG_EEPRO100_PIO is not set
# CONFIG_E100 is not set
# CONFIG_FEALNX is not set
# CONFIG_NATSEMI is not set
@@ -350,7 +425,6 @@ CONFIG_EEPRO100=y
# CONFIG_SUNDANCE is not set
# CONFIG_TLAN is not set
# CONFIG_VIA_RHINE is not set
-# CONFIG_VIA_VELOCITY is not set
#
# Ethernet (1000 Mbit)
@@ -363,6 +437,7 @@ CONFIG_EEPRO100=y
# CONFIG_YELLOWFIN is not set
# CONFIG_R8169 is not set
# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
# CONFIG_TIGON3 is not set
#
@@ -412,25 +487,6 @@ CONFIG_DLCI_MAX=8
# CONFIG_NETCONSOLE is not set
#
-# SCSI device support
-#
-# CONFIG_SCSI is not set
-
-#
-# Fusion MPT device support
-#
-
-#
-# IEEE 1394 (FireWire) support
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-
-#
# ISDN subsystem
#
# CONFIG_ISDN is not set
@@ -453,14 +509,6 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
# CONFIG_INPUT_EVBUG is not set
#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-# CONFIG_SERIO is not set
-# CONFIG_SERIO_I8042 is not set
-
-#
# Input Device Drivers
#
# CONFIG_INPUT_KEYBOARD is not set
@@ -470,6 +518,13 @@ CONFIG_SOUND_GAMEPORT=y
# CONFIG_INPUT_MISC is not set
#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
+#
# Character devices
#
# CONFIG_VT is not set
@@ -491,7 +546,6 @@ CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
-# CONFIG_QIC02_TAPE is not set
#
# IPMI
@@ -517,7 +571,6 @@ CONFIG_IXP2000_WATCHDOG=y
# CONFIG_WDTPCI is not set
# CONFIG_NVRAM is not set
# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
@@ -525,11 +578,15 @@ CONFIG_IXP2000_WATCHDOG=y
#
# 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
+
+#
# I2C support
#
CONFIG_I2C=y
@@ -540,6 +597,7 @@ CONFIG_I2C_CHARDEV=y
#
CONFIG_I2C_ALGOBIT=y
# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
#
# I2C Hardware Bus support
@@ -565,6 +623,7 @@ CONFIG_I2C_ALGOBIT=y
# 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
#
# Hardware Sensors Chip support
@@ -572,20 +631,29 @@ CONFIG_I2C_ALGOBIT=y
CONFIG_I2C_SENSOR=y
# CONFIG_SENSORS_ADM1021 is not set
# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ASB100 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
# CONFIG_SENSORS_LM75 is not set
# CONFIG_SENSORS_LM77 is not set
# CONFIG_SENSORS_LM78 is not set
# CONFIG_SENSORS_LM80 is not set
# CONFIG_SENSORS_LM83 is not set
# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
# CONFIG_SENSORS_VIA686A is not set
# CONFIG_SENSORS_W83781D is not set
# CONFIG_SENSORS_W83L785TS is not set
@@ -604,6 +672,10 @@ CONFIG_SENSORS_EEPROM=y
# CONFIG_I2C_DEBUG_CHIP is not set
#
+# Misc devices
+#
+
+#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -614,6 +686,33 @@ CONFIG_SENSORS_EEPROM=y
# 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
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -630,10 +729,15 @@ CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
CONFIG_FS_POSIX_ACL=y
+
+#
+# XFS support
+#
# CONFIG_XFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
@@ -658,6 +762,7 @@ CONFIG_SYSFS=y
# CONFIG_DEVFS_FS is not set
# CONFIG_DEVPTS_FS_XATTR is not set
CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
@@ -675,6 +780,7 @@ CONFIG_RAMFS=y
CONFIG_JFFS2_FS=y
CONFIG_JFFS2_FS_DEBUG=0
# CONFIG_JFFS2_FS_NAND is not set
+# CONFIG_JFFS2_FS_NOR_ECC is not set
# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
CONFIG_JFFS2_ZLIB=y
CONFIG_JFFS2_RTIME=y
@@ -697,9 +803,9 @@ CONFIG_NFS_V3=y
CONFIG_ROOT_NFS=y
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
-# CONFIG_EXPORTFS is not set
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
@@ -737,49 +843,31 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_PROFILING is not set
#
-# Graphics support
-#
-# CONFIG_FB is not set
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# Misc devices
-#
-
-#
-# USB support
-#
-# CONFIG_USB is not set
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
# Kernel hacking
#
-CONFIG_FRAME_POINTER=y
-CONFIG_DEBUG_USER=y
-# CONFIG_DEBUG_INFO is not set
+# CONFIG_PRINTK_TIME is not set
CONFIG_DEBUG_KERNEL=y
-# CONFIG_DEBUG_SLAB is not set
CONFIG_MAGIC_SYSRQ=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_WAITQ 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_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_WAITQ is not set
CONFIG_DEBUG_ERRORS=y
CONFIG_DEBUG_LL=y
# CONFIG_DEBUG_ICEDCC is not set
-# CONFIG_DEBUG_BDI2000_XSCALE is not set
#
# Security options
#
+# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
#
@@ -788,6 +876,10 @@ CONFIG_DEBUG_LL=y
# CONFIG_CRYPTO is not set
#
+# Hardware crypto devices
+#
+
+#
# Library routines
#
# CONFIG_CRC_CCITT is not set
diff --git a/arch/arm/configs/ixdp2800_defconfig b/arch/arm/configs/ixdp2800_defconfig
index ea4b05ad0d4f3..d36f991929621 100644
--- a/arch/arm/configs/ixdp2800_defconfig
+++ b/arch/arm/configs/ixdp2800_defconfig
@@ -1,10 +1,14 @@
#
# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.12-rc1-bk2
+# Sun Mar 27 22:15:23 2005
#
CONFIG_ARM=y
CONFIG_MMU=y
CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_IOMAP=y
#
# Code maturity level options
@@ -16,6 +20,7 @@ CONFIG_BROKEN_ON_SMP=y
#
# General setup
#
+CONFIG_LOCALVERSION=""
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
# CONFIG_POSIX_MQUEUE is not set
@@ -23,20 +28,24 @@ CONFIG_BSD_PROCESS_ACCT=y
# CONFIG_BSD_PROCESS_ACCT_V3 is not set
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
# CONFIG_IKCONFIG is not set
CONFIG_EMBEDDED=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=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
@@ -64,7 +73,9 @@ CONFIG_ARCH_IXP2000=y
# CONFIG_ARCH_SHARK is not set
# CONFIG_ARCH_LH7A40X is not set
# CONFIG_ARCH_OMAP is not set
-# CONFIG_ARCH_VERSATILE_PB is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_H720X is not set
CONFIG_ARCH_SUPPORTS_BIG_ENDIAN=y
#
@@ -88,6 +99,7 @@ CONFIG_CPU_32=y
CONFIG_CPU_XSCALE=y
CONFIG_CPU_32v5=y
CONFIG_CPU_ABRT_EV5T=y
+CONFIG_CPU_CACHE_VIVT=y
CONFIG_CPU_TLB_V4WBI=y
CONFIG_CPU_MINICACHE=y
@@ -99,51 +111,75 @@ CONFIG_CPU_BIG_ENDIAN=y
CONFIG_XSCALE_PMU=y
#
-# General setup
+# Bus support
#
CONFIG_PCI=y
-# CONFIG_ZBOOT_ROM is not set
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
CONFIG_PCI_LEGACY_PROC=y
CONFIG_PCI_NAMES=y
#
-# At least one math emulation must be selected
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_PREEMPT is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="console=ttyS0,9600 root=/dev/nfs ip=bootp mem=64M@0x0 pci=firmware"
+# 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
-# CONFIG_VFP 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
#
-# Generic Driver Options
+# Power management options
#
-CONFIG_STANDALONE=y
-# CONFIG_PREVENT_FIRMWARE_BUILD is not set
-# CONFIG_DEBUG_DRIVER is not set
# CONFIG_PM is not set
-# CONFIG_PREEMPT is not set
-# CONFIG_ARTHUR is not set
-CONFIG_CMDLINE="console=ttyS0,9600 root=/dev/nfs ip=bootp mem=64M@0x0 pci=firmware"
-CONFIG_ALIGNMENT_TRAP=y
#
-# Parallel port support
+# Device Drivers
#
-# CONFIG_PARPORT is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
#
# Memory Technology Devices (MTD)
#
CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
-CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
CONFIG_MTD_REDBOOT_PARTS=y
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
CONFIG_MTD_REDBOOT_PARTS_READONLY=y
# CONFIG_MTD_CMDLINE_PARTS is not set
@@ -182,6 +218,7 @@ CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_XIP is not set
#
# Mapping drivers for chip access
@@ -201,6 +238,7 @@ CONFIG_MTD_IXP2000=y
# 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
@@ -215,6 +253,11 @@ CONFIG_MTD_IXP2000=y
# CONFIG_MTD_NAND is not set
#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
# Plug and Play support
#
@@ -226,13 +269,31 @@ CONFIG_MTD_IXP2000=y
# CONFIG_BLK_CPQ_CISS_DA is not set
# CONFIG_BLK_DEV_DAC960 is not set
# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_SX8 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_INITRAMFS_SOURCE=""
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
#
# Multi-device support (RAID and LVM)
@@ -240,6 +301,20 @@ CONFIG_BLK_DEV_INITRD=y
# CONFIG_MD is not set
#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
# Networking support
#
CONFIG_NET=y
@@ -266,6 +341,9 @@ CONFIG_SYN_COOKIES=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_IP_TCPDIAG is not set
+# CONFIG_IP_TCPDIAG_IPV6 is not set
# CONFIG_IPV6 is not set
# CONFIG_NETFILTER is not set
@@ -285,8 +363,6 @@ CONFIG_SYN_COOKIES=y
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_FASTROUTE is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
#
# QoS and/or fair queueing
@@ -337,7 +413,6 @@ CONFIG_NET_PCI=y
# CONFIG_FORCEDETH is not set
# CONFIG_DGRS is not set
CONFIG_EEPRO100=y
-# CONFIG_EEPRO100_PIO is not set
# CONFIG_E100 is not set
# CONFIG_FEALNX is not set
# CONFIG_NATSEMI is not set
@@ -349,7 +424,6 @@ CONFIG_EEPRO100=y
# CONFIG_SUNDANCE is not set
# CONFIG_TLAN is not set
# CONFIG_VIA_RHINE is not set
-# CONFIG_VIA_VELOCITY is not set
#
# Ethernet (1000 Mbit)
@@ -362,6 +436,7 @@ CONFIG_EEPRO100=y
# CONFIG_YELLOWFIN is not set
# CONFIG_R8169 is not set
# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
# CONFIG_TIGON3 is not set
#
@@ -411,25 +486,6 @@ CONFIG_DLCI_MAX=8
# CONFIG_NETCONSOLE is not set
#
-# SCSI device support
-#
-# CONFIG_SCSI is not set
-
-#
-# Fusion MPT device support
-#
-
-#
-# IEEE 1394 (FireWire) support
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-
-#
# ISDN subsystem
#
# CONFIG_ISDN is not set
@@ -452,14 +508,6 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
# CONFIG_INPUT_EVBUG is not set
#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-# CONFIG_SERIO is not set
-# CONFIG_SERIO_I8042 is not set
-
-#
# Input Device Drivers
#
# CONFIG_INPUT_KEYBOARD is not set
@@ -469,6 +517,13 @@ CONFIG_SOUND_GAMEPORT=y
# CONFIG_INPUT_MISC is not set
#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
+#
# Character devices
#
# CONFIG_VT is not set
@@ -490,7 +545,6 @@ CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
-# CONFIG_QIC02_TAPE is not set
#
# IPMI
@@ -516,7 +570,6 @@ CONFIG_IXP2000_WATCHDOG=y
# CONFIG_WDTPCI is not set
# CONFIG_NVRAM is not set
# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
@@ -524,11 +577,15 @@ CONFIG_IXP2000_WATCHDOG=y
#
# 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
+
+#
# I2C support
#
CONFIG_I2C=y
@@ -539,6 +596,7 @@ CONFIG_I2C_CHARDEV=y
#
CONFIG_I2C_ALGOBIT=y
# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
#
# I2C Hardware Bus support
@@ -564,6 +622,7 @@ CONFIG_I2C_ALGOBIT=y
# 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
#
# Hardware Sensors Chip support
@@ -571,20 +630,29 @@ CONFIG_I2C_ALGOBIT=y
CONFIG_I2C_SENSOR=y
# CONFIG_SENSORS_ADM1021 is not set
# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ASB100 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
# CONFIG_SENSORS_LM75 is not set
# CONFIG_SENSORS_LM77 is not set
# CONFIG_SENSORS_LM78 is not set
# CONFIG_SENSORS_LM80 is not set
# CONFIG_SENSORS_LM83 is not set
# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
# CONFIG_SENSORS_VIA686A is not set
# CONFIG_SENSORS_W83781D is not set
# CONFIG_SENSORS_W83L785TS is not set
@@ -603,6 +671,10 @@ CONFIG_SENSORS_EEPROM=y
# CONFIG_I2C_DEBUG_CHIP is not set
#
+# Misc devices
+#
+
+#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -613,6 +685,33 @@ CONFIG_SENSORS_EEPROM=y
# 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
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -629,10 +728,15 @@ CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
CONFIG_FS_POSIX_ACL=y
+
+#
+# XFS support
+#
# CONFIG_XFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
@@ -657,6 +761,7 @@ CONFIG_SYSFS=y
# CONFIG_DEVFS_FS is not set
# CONFIG_DEVPTS_FS_XATTR is not set
CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
@@ -674,6 +779,7 @@ CONFIG_RAMFS=y
CONFIG_JFFS2_FS=y
CONFIG_JFFS2_FS_DEBUG=0
# CONFIG_JFFS2_FS_NAND is not set
+# CONFIG_JFFS2_FS_NOR_ECC is not set
# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
CONFIG_JFFS2_ZLIB=y
CONFIG_JFFS2_RTIME=y
@@ -696,9 +802,9 @@ CONFIG_NFS_V3=y
CONFIG_ROOT_NFS=y
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
-# CONFIG_EXPORTFS is not set
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
@@ -736,49 +842,31 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_PROFILING is not set
#
-# Graphics support
-#
-# CONFIG_FB is not set
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# Misc devices
-#
-
-#
-# USB support
-#
-# CONFIG_USB is not set
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
# Kernel hacking
#
-CONFIG_FRAME_POINTER=y
-CONFIG_DEBUG_USER=y
-# CONFIG_DEBUG_INFO is not set
+# CONFIG_PRINTK_TIME is not set
CONFIG_DEBUG_KERNEL=y
-# CONFIG_DEBUG_SLAB is not set
CONFIG_MAGIC_SYSRQ=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_WAITQ 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_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_WAITQ is not set
CONFIG_DEBUG_ERRORS=y
CONFIG_DEBUG_LL=y
# CONFIG_DEBUG_ICEDCC is not set
-# CONFIG_DEBUG_BDI2000_XSCALE is not set
#
# Security options
#
+# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
#
@@ -787,6 +875,10 @@ CONFIG_DEBUG_LL=y
# CONFIG_CRYPTO is not set
#
+# Hardware crypto devices
+#
+
+#
# Library routines
#
# CONFIG_CRC_CCITT is not set
diff --git a/arch/arm/configs/ixdp2801_defconfig b/arch/arm/configs/ixdp2801_defconfig
index f0b0b1c4a0574..cd84a20f30f1e 100644
--- a/arch/arm/configs/ixdp2801_defconfig
+++ b/arch/arm/configs/ixdp2801_defconfig
@@ -1,10 +1,14 @@
#
# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.12-rc1-bk2
+# Sun Mar 27 22:39:19 2005
#
CONFIG_ARM=y
CONFIG_MMU=y
CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_IOMAP=y
#
# Code maturity level options
@@ -16,6 +20,7 @@ CONFIG_BROKEN_ON_SMP=y
#
# General setup
#
+CONFIG_LOCALVERSION=""
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
# CONFIG_POSIX_MQUEUE is not set
@@ -23,20 +28,24 @@ CONFIG_BSD_PROCESS_ACCT=y
# CONFIG_BSD_PROCESS_ACCT_V3 is not set
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
# CONFIG_IKCONFIG is not set
CONFIG_EMBEDDED=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=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
@@ -64,7 +73,9 @@ CONFIG_ARCH_IXP2000=y
# CONFIG_ARCH_SHARK is not set
# CONFIG_ARCH_LH7A40X is not set
# CONFIG_ARCH_OMAP is not set
-# CONFIG_ARCH_VERSATILE_PB is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_H720X is not set
CONFIG_ARCH_SUPPORTS_BIG_ENDIAN=y
#
@@ -88,6 +99,7 @@ CONFIG_CPU_32=y
CONFIG_CPU_XSCALE=y
CONFIG_CPU_32v5=y
CONFIG_CPU_ABRT_EV5T=y
+CONFIG_CPU_CACHE_VIVT=y
CONFIG_CPU_TLB_V4WBI=y
CONFIG_CPU_MINICACHE=y
@@ -99,51 +111,75 @@ CONFIG_CPU_BIG_ENDIAN=y
CONFIG_XSCALE_PMU=y
#
-# General setup
+# Bus support
#
CONFIG_PCI=y
-# CONFIG_ZBOOT_ROM is not set
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
CONFIG_PCI_LEGACY_PROC=y
CONFIG_PCI_NAMES=y
#
-# At least one math emulation must be selected
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_PREEMPT is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/nfs ip=bootp mem=64M@0x0 pci=firmware ixdp2x01_clock=50000000"
+# 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
-# CONFIG_VFP 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
#
-# Generic Driver Options
+# Power management options
#
-CONFIG_STANDALONE=y
-# CONFIG_PREVENT_FIRMWARE_BUILD is not set
-# CONFIG_DEBUG_DRIVER is not set
# CONFIG_PM is not set
-# CONFIG_PREEMPT is not set
-# CONFIG_ARTHUR is not set
-CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/nfs ip=bootp mem=64M@0x0 pci=firmware ixdp2x01_clock=50000000"
-CONFIG_ALIGNMENT_TRAP=y
#
-# Parallel port support
+# Device Drivers
#
-# CONFIG_PARPORT is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
#
# Memory Technology Devices (MTD)
#
CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
-CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
CONFIG_MTD_REDBOOT_PARTS=y
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
CONFIG_MTD_REDBOOT_PARTS_READONLY=y
# CONFIG_MTD_CMDLINE_PARTS is not set
@@ -182,6 +218,7 @@ CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_XIP is not set
#
# Mapping drivers for chip access
@@ -201,6 +238,7 @@ CONFIG_MTD_IXP2000=y
# 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
@@ -215,6 +253,11 @@ CONFIG_MTD_IXP2000=y
# CONFIG_MTD_NAND is not set
#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
# Plug and Play support
#
@@ -226,13 +269,31 @@ CONFIG_MTD_IXP2000=y
# CONFIG_BLK_CPQ_CISS_DA is not set
# CONFIG_BLK_DEV_DAC960 is not set
# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_SX8 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_INITRAMFS_SOURCE=""
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
#
# Multi-device support (RAID and LVM)
@@ -240,6 +301,20 @@ CONFIG_BLK_DEV_INITRD=y
# CONFIG_MD is not set
#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
# Networking support
#
CONFIG_NET=y
@@ -266,6 +341,9 @@ CONFIG_SYN_COOKIES=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_IP_TCPDIAG is not set
+# CONFIG_IP_TCPDIAG_IPV6 is not set
# CONFIG_IPV6 is not set
# CONFIG_NETFILTER is not set
@@ -285,8 +363,6 @@ CONFIG_SYN_COOKIES=y
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_FASTROUTE is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
#
# QoS and/or fair queueing
@@ -338,7 +414,6 @@ CONFIG_NET_PCI=y
CONFIG_CS89x0=y
# CONFIG_DGRS is not set
CONFIG_EEPRO100=y
-# CONFIG_EEPRO100_PIO is not set
# CONFIG_E100 is not set
# CONFIG_FEALNX is not set
# CONFIG_NATSEMI is not set
@@ -350,7 +425,6 @@ CONFIG_EEPRO100=y
# CONFIG_SUNDANCE is not set
# CONFIG_TLAN is not set
# CONFIG_VIA_RHINE is not set
-# CONFIG_VIA_VELOCITY is not set
#
# Ethernet (1000 Mbit)
@@ -363,6 +437,7 @@ CONFIG_EEPRO100=y
# CONFIG_YELLOWFIN is not set
# CONFIG_R8169 is not set
# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
# CONFIG_TIGON3 is not set
#
@@ -412,25 +487,6 @@ CONFIG_DLCI_MAX=8
# CONFIG_NETCONSOLE is not set
#
-# SCSI device support
-#
-# CONFIG_SCSI is not set
-
-#
-# Fusion MPT device support
-#
-
-#
-# IEEE 1394 (FireWire) support
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-
-#
# ISDN subsystem
#
# CONFIG_ISDN is not set
@@ -453,14 +509,6 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
# CONFIG_INPUT_EVBUG is not set
#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-# CONFIG_SERIO is not set
-# CONFIG_SERIO_I8042 is not set
-
-#
# Input Device Drivers
#
# CONFIG_INPUT_KEYBOARD is not set
@@ -470,6 +518,13 @@ CONFIG_SOUND_GAMEPORT=y
# CONFIG_INPUT_MISC is not set
#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
+#
# Character devices
#
# CONFIG_VT is not set
@@ -491,7 +546,6 @@ CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
-# CONFIG_QIC02_TAPE is not set
#
# IPMI
@@ -517,7 +571,6 @@ CONFIG_IXP2000_WATCHDOG=y
# CONFIG_WDTPCI is not set
# CONFIG_NVRAM is not set
# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
@@ -525,11 +578,15 @@ CONFIG_IXP2000_WATCHDOG=y
#
# 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
+
+#
# I2C support
#
CONFIG_I2C=y
@@ -540,6 +597,7 @@ CONFIG_I2C_CHARDEV=y
#
CONFIG_I2C_ALGOBIT=y
# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
#
# I2C Hardware Bus support
@@ -565,6 +623,7 @@ CONFIG_I2C_ALGOBIT=y
# 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
#
# Hardware Sensors Chip support
@@ -572,20 +631,29 @@ CONFIG_I2C_ALGOBIT=y
CONFIG_I2C_SENSOR=y
# CONFIG_SENSORS_ADM1021 is not set
# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ASB100 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
# CONFIG_SENSORS_LM75 is not set
# CONFIG_SENSORS_LM77 is not set
# CONFIG_SENSORS_LM78 is not set
# CONFIG_SENSORS_LM80 is not set
# CONFIG_SENSORS_LM83 is not set
# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
# CONFIG_SENSORS_VIA686A is not set
# CONFIG_SENSORS_W83781D is not set
# CONFIG_SENSORS_W83L785TS is not set
@@ -604,6 +672,10 @@ CONFIG_SENSORS_EEPROM=y
# CONFIG_I2C_DEBUG_CHIP is not set
#
+# Misc devices
+#
+
+#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -614,6 +686,33 @@ CONFIG_SENSORS_EEPROM=y
# 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
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -630,10 +729,15 @@ CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
CONFIG_FS_POSIX_ACL=y
+
+#
+# XFS support
+#
# CONFIG_XFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
@@ -658,6 +762,7 @@ CONFIG_SYSFS=y
# CONFIG_DEVFS_FS is not set
# CONFIG_DEVPTS_FS_XATTR is not set
CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
@@ -675,6 +780,7 @@ CONFIG_RAMFS=y
CONFIG_JFFS2_FS=y
CONFIG_JFFS2_FS_DEBUG=0
# CONFIG_JFFS2_FS_NAND is not set
+# CONFIG_JFFS2_FS_NOR_ECC is not set
# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
CONFIG_JFFS2_ZLIB=y
CONFIG_JFFS2_RTIME=y
@@ -697,9 +803,9 @@ CONFIG_NFS_V3=y
CONFIG_ROOT_NFS=y
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
-# CONFIG_EXPORTFS is not set
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
@@ -737,49 +843,31 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_PROFILING is not set
#
-# Graphics support
-#
-# CONFIG_FB is not set
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# Misc devices
-#
-
-#
-# USB support
-#
-# CONFIG_USB is not set
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
# Kernel hacking
#
-CONFIG_FRAME_POINTER=y
-CONFIG_DEBUG_USER=y
-# CONFIG_DEBUG_INFO is not set
+# CONFIG_PRINTK_TIME is not set
CONFIG_DEBUG_KERNEL=y
-# CONFIG_DEBUG_SLAB is not set
CONFIG_MAGIC_SYSRQ=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_WAITQ 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_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_WAITQ is not set
CONFIG_DEBUG_ERRORS=y
CONFIG_DEBUG_LL=y
# CONFIG_DEBUG_ICEDCC is not set
-# CONFIG_DEBUG_BDI2000_XSCALE is not set
#
# Security options
#
+# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
#
@@ -788,6 +876,10 @@ CONFIG_DEBUG_LL=y
# CONFIG_CRYPTO is not set
#
+# Hardware crypto devices
+#
+
+#
# Library routines
#
# CONFIG_CRC_CCITT is not set
diff --git a/arch/arm/configs/ixp4xx_defconfig b/arch/arm/configs/ixp4xx_defconfig
index 3a068df0e6d73..94aafec5fb465 100644
--- a/arch/arm/configs/ixp4xx_defconfig
+++ b/arch/arm/configs/ixp4xx_defconfig
@@ -1,40 +1,51 @@
#
# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.12-rc1-bk2
+# Sun Mar 27 22:53:40 2005
#
CONFIG_ARM=y
CONFIG_MMU=y
CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_IOMAP=y
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
CONFIG_CLEAN_COMPILE=y
-CONFIG_STANDALONE=y
CONFIG_BROKEN_ON_SMP=y
#
# General setup
#
+CONFIG_LOCALVERSION=""
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
# CONFIG_POSIX_MQUEUE is not set
CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
# CONFIG_IKCONFIG is not set
CONFIG_EMBEDDED=y
CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=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
@@ -43,52 +54,33 @@ CONFIG_MODULES=y
# CONFIG_MODULE_UNLOAD is not set
CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
+# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_KMOD=y
#
# System Type
#
-# CONFIG_ARCH_ADIFCC is not set
# CONFIG_ARCH_CLPS7500 is not set
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
-# CONFIG_ARCH_PXA 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=y
+# 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_SHARK is not set
# CONFIG_ARCH_S3C2410 is not set
-# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_SHARK is not set
# CONFIG_ARCH_LH7A40X is not set
-# CONFIG_ARCH_VERSATILE_PB is not set
-
-#
-# CLPS711X/EP721X Implementations
-#
-
-#
-# Epxa10db
-#
-
-#
-# Footbridge Implementations
-#
-
-#
-# IOP3xx Implementation Options
-#
-# CONFIG_ARCH_IOP310 is not set
-# CONFIG_ARCH_IOP321 is not set
-
-#
-# IOP3xx Chipset Features
-#
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_H720X is not set
CONFIG_ARCH_SUPPORTS_BIG_ENDIAN=y
#
@@ -98,12 +90,15 @@ CONFIG_ARCH_SUPPORTS_BIG_ENDIAN=y
#
# IXP4xx Platforms
#
+# CONFIG_ARCH_AVILA is not set
+CONFIG_ARCH_ADI_COYOTE=y
CONFIG_ARCH_IXDP425=y
+# CONFIG_MACH_IXDPG425 is not set
+# CONFIG_MACH_IXDP465 is not set
CONFIG_ARCH_IXCDP1100=y
CONFIG_ARCH_PRPMC1100=y
-CONFIG_ARCH_ADI_COYOTE=y
-# CONFIG_ARCH_AVILA is not set
CONFIG_ARCH_IXDP4XX=y
+# CONFIG_MACH_GTWX5715 is not set
#
# IXP4xx Options
@@ -111,45 +106,13 @@ CONFIG_ARCH_IXDP4XX=y
# CONFIG_IXP4XX_INDIRECT_PCI is not set
#
-# Intel PXA250/210 Implementations
-#
-
-#
-# SA11x0 Implementations
-#
-
-#
-# TI OMAP Implementations
-#
-
-#
-# OMAP Core Type
-#
-
-#
-# OMAP Board Type
-#
-
-#
-# OMAP Feature Selections
-#
-
-#
-# S3C2410 Implementations
-#
-
-#
-# LH7A40X Implementations
-#
-CONFIG_DMABOUNCE=y
-
-#
# Processor Type
#
CONFIG_CPU_32=y
CONFIG_CPU_XSCALE=y
CONFIG_CPU_32v5=y
CONFIG_CPU_ABRT_EV5T=y
+CONFIG_CPU_CACHE_VIVT=y
CONFIG_CPU_TLB_V4WBI=y
CONFIG_CPU_MINICACHE=y
@@ -159,51 +122,81 @@ CONFIG_CPU_MINICACHE=y
# CONFIG_ARM_THUMB is not set
CONFIG_CPU_BIG_ENDIAN=y
CONFIG_XSCALE_PMU=y
+CONFIG_DMABOUNCE=y
#
-# General setup
+# Bus support
#
CONFIG_PCI=y
-# CONFIG_ZBOOT_ROM is not set
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
CONFIG_PCI_LEGACY_PROC=y
CONFIG_PCI_NAMES=y
#
-# At least one math emulation must be selected
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_PREEMPT is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="console=ttyS0,115200 ip=bootp root=/dev/nfs"
+# 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
#
-# Generic Driver Options
+# Power management options
#
-# CONFIG_DEBUG_DRIVER is not set
CONFIG_PM=y
-# CONFIG_PREEMPT is not set
CONFIG_APM=y
-# CONFIG_ARTHUR is not set
-CONFIG_CMDLINE="console=ttyS0,115200 ip=bootp root=/dev/nfs"
-CONFIG_ALIGNMENT_TRAP=y
#
-# Parallel port support
+# Device Drivers
#
-# CONFIG_PARPORT is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
#
# Memory Technology Devices (MTD)
#
CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
-CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
CONFIG_MTD_REDBOOT_PARTS=y
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
+# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
# CONFIG_MTD_CMDLINE_PARTS is not set
# CONFIG_MTD_AFS_PARTS is not set
@@ -223,13 +216,24 @@ CONFIG_MTD_CFI=y
# CONFIG_MTD_JEDECPROBE is not set
CONFIG_MTD_GEN_PROBE=y
# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
CONFIG_MTD_CFI_INTELEXT=y
# CONFIG_MTD_CFI_AMDSTD is not set
# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
+# CONFIG_MTD_XIP is not set
#
# Mapping drivers for chip access
@@ -246,8 +250,10 @@ CONFIG_MTD_IXP4XX=y
#
# 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
@@ -262,6 +268,13 @@ CONFIG_MTD_IXP4XX=y
CONFIG_MTD_NAND=m
# CONFIG_MTD_NAND_VERIFY_WRITE is not set
CONFIG_MTD_NAND_IDS=m
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
#
# Plug and Play support
@@ -275,13 +288,88 @@ CONFIG_MTD_NAND_IDS=m
# CONFIG_BLK_CPQ_CISS_DA is not set
# CONFIG_BLK_DEV_DAC960 is not set
# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_CARMEL is not set
+# CONFIG_BLK_DEV_SX8 is not set
CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=8192
CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# 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 is not set
+# CONFIG_BLK_DEV_OFFBOARD is not set
+# CONFIG_BLK_DEV_GENERIC is not set
+# CONFIG_BLK_DEV_OPTI621 is not set
+# CONFIG_BLK_DEV_SL82C105 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+# CONFIG_IDEDMA_PCI_AUTO is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+CONFIG_BLK_DEV_CMD64X=y
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+CONFIG_BLK_DEV_HPT366=y
+# CONFIG_BLK_DEV_SC1200 is not set
+# CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+CONFIG_BLK_DEV_PDC202XX_NEW=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_IDE_ARM is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
#
# Multi-device support (RAID and LVM)
@@ -289,6 +377,20 @@ CONFIG_BLK_DEV_INITRD=y
# CONFIG_MD is not set
#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
# Networking support
#
CONFIG_NET=y
@@ -306,14 +408,14 @@ CONFIG_IP_MULTICAST=y
CONFIG_IP_ADVANCED_ROUTER=y
CONFIG_IP_MULTIPLE_TABLES=y
CONFIG_IP_ROUTE_FWMARK=y
-CONFIG_IP_ROUTE_NAT=y
CONFIG_IP_ROUTE_MULTIPATH=y
+# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set
CONFIG_IP_ROUTE_VERBOSE=y
CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y
CONFIG_IP_PNP_BOOTP=y
# CONFIG_IP_PNP_RARP is not set
-CONFIG_NET_IPIP=m
+# CONFIG_NET_IPIP is not set
CONFIG_NET_IPGRE=m
CONFIG_NET_IPGRE_BROADCAST=y
CONFIG_IP_MROUTE=y
@@ -324,6 +426,9 @@ CONFIG_SYN_COOKIES=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
+CONFIG_INET_TUNNEL=m
+# CONFIG_IP_TCPDIAG is not set
+# CONFIG_IP_TCPDIAG_IPV6 is not set
#
# IP: Virtual Server Configuration
@@ -366,6 +471,9 @@ CONFIG_BRIDGE_NETFILTER=y
# 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_CT_PROTO_SCTP is not set
CONFIG_IP_NF_FTP=m
CONFIG_IP_NF_IRC=m
# CONFIG_IP_NF_TFTP is not set
@@ -391,8 +499,16 @@ CONFIG_IP_NF_MATCH_STATE=m
# CONFIG_IP_NF_MATCH_CONNTRACK is not set
CONFIG_IP_NF_MATCH_OWNER=m
# CONFIG_IP_NF_MATCH_PHYSDEV is not set
+# 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_COMMENT is not set
+# CONFIG_IP_NF_MATCH_HASHLIMIT is not set
CONFIG_IP_NF_FILTER=m
CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=m
CONFIG_IP_NF_NAT=m
CONFIG_IP_NF_NAT_NEEDED=y
CONFIG_IP_NF_TARGET_MASQUERADE=m
@@ -408,15 +524,10 @@ CONFIG_IP_NF_TARGET_TOS=m
# CONFIG_IP_NF_TARGET_DSCP is not set
CONFIG_IP_NF_TARGET_MARK=m
# CONFIG_IP_NF_TARGET_CLASSIFY is not set
-CONFIG_IP_NF_TARGET_LOG=m
-CONFIG_IP_NF_TARGET_ULOG=m
-CONFIG_IP_NF_TARGET_TCPMSS=m
+# CONFIG_IP_NF_RAW is not set
CONFIG_IP_NF_ARPTABLES=m
CONFIG_IP_NF_ARPFILTER=m
# CONFIG_IP_NF_ARP_MANGLE is not set
-CONFIG_IP_NF_COMPAT_IPCHAINS=m
-CONFIG_IP_NF_COMPAT_IPFWADM=m
-# CONFIG_IP_NF_RAW is not set
#
# Bridge: Netfilter Configuration
@@ -455,16 +566,17 @@ CONFIG_ECONET=m
CONFIG_ECONET_AUNUDP=y
CONFIG_ECONET_NATIVE=y
CONFIG_WAN_ROUTER=m
-# CONFIG_NET_HW_FLOWCONTROL 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
CONFIG_NET_SCH_CBQ=m
CONFIG_NET_SCH_HTB=m
# CONFIG_NET_SCH_HFSC is not set
-CONFIG_NET_SCH_CSZ=m
# CONFIG_NET_SCH_ATM is not set
CONFIG_NET_SCH_PRIO=m
CONFIG_NET_SCH_RED=m
@@ -473,18 +585,24 @@ CONFIG_NET_SCH_TEQL=m
CONFIG_NET_SCH_TBF=m
CONFIG_NET_SCH_GRED=m
CONFIG_NET_SCH_DSMARK=m
-# CONFIG_NET_SCH_DELAY is not set
+# CONFIG_NET_SCH_NETEM is not set
CONFIG_NET_SCH_INGRESS=m
CONFIG_NET_QOS=y
CONFIG_NET_ESTIMATOR=y
CONFIG_NET_CLS=y
+# CONFIG_NET_CLS_BASIC is not set
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 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
#
@@ -516,6 +634,7 @@ CONFIG_MII=y
# CONFIG_HAPPYMEAL is not set
# CONFIG_SUNGEM is not set
# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_SMC91X is not set
#
# Tulip family network device support
@@ -530,7 +649,6 @@ CONFIG_NET_PCI=y
# CONFIG_FORCEDETH is not set
# CONFIG_DGRS is not set
CONFIG_EEPRO100=y
-# CONFIG_EEPRO100_PIO is not set
# CONFIG_E100 is not set
# CONFIG_FEALNX is not set
# CONFIG_NATSEMI is not set
@@ -554,6 +672,7 @@ CONFIG_EEPRO100=y
# CONFIG_YELLOWFIN is not set
# CONFIG_R8169 is not set
# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
# CONFIG_TIGON3 is not set
#
@@ -580,7 +699,6 @@ 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
@@ -590,6 +708,7 @@ CONFIG_PCI_HERMES=y
#
# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
#
+# CONFIG_PRISM54 is not set
CONFIG_NET_WIRELESS=y
#
@@ -637,89 +756,10 @@ CONFIG_ATM_TCP=m
# CONFIG_HIPPI is not set
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
-# CONFIG_RCPCI is not set
# CONFIG_SHAPER is not set
# CONFIG_NETCONSOLE is not set
#
-# ATA/ATAPI/MFM/RLL support
-#
-CONFIG_IDE=y
-CONFIG_BLK_DEV_IDE=y
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
-CONFIG_BLK_DEV_IDEDISK=y
-# CONFIG_IDEDISK_MULTI_MODE is not set
-# CONFIG_IDEDISK_STROKE is not set
-# CONFIG_BLK_DEV_IDECD is not set
-# CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
-# CONFIG_IDE_TASK_IOCTL is not set
-# CONFIG_IDE_TASKFILE_IO is not set
-
-#
-# IDE chipset support/bugfixes
-#
-CONFIG_IDE_GENERIC=y
-CONFIG_BLK_DEV_IDEPCI=y
-# CONFIG_IDEPCI_SHARE_IRQ is not set
-# CONFIG_BLK_DEV_OFFBOARD is not set
-# CONFIG_BLK_DEV_GENERIC is not set
-# CONFIG_BLK_DEV_OPTI621 is not set
-# CONFIG_BLK_DEV_SL82C105 is not set
-CONFIG_BLK_DEV_IDEDMA_PCI=y
-# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
-# CONFIG_IDEDMA_PCI_AUTO is not set
-CONFIG_BLK_DEV_ADMA=y
-# CONFIG_BLK_DEV_AEC62XX is not set
-# CONFIG_BLK_DEV_ALI15X3 is not set
-# CONFIG_BLK_DEV_AMD74XX is not set
-CONFIG_BLK_DEV_CMD64X=y
-# CONFIG_BLK_DEV_TRIFLEX is not set
-# CONFIG_BLK_DEV_CY82C693 is not set
-# CONFIG_BLK_DEV_CS5520 is not set
-# CONFIG_BLK_DEV_CS5530 is not set
-# CONFIG_BLK_DEV_HPT34X is not set
-CONFIG_BLK_DEV_HPT366=y
-# CONFIG_BLK_DEV_SC1200 is not set
-# CONFIG_BLK_DEV_PIIX is not set
-# CONFIG_BLK_DEV_NS87415 is not set
-# CONFIG_BLK_DEV_PDC202XX_OLD is not set
-CONFIG_BLK_DEV_PDC202XX_NEW=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_IDEDMA=y
-# CONFIG_IDEDMA_IVB is not set
-# CONFIG_IDEDMA_AUTO is not set
-# CONFIG_BLK_DEV_HD is not set
-
-#
-# SCSI device support
-#
-# CONFIG_SCSI is not set
-
-#
-# 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
-
-#
# ISDN subsystem
#
# CONFIG_ISDN is not set
@@ -742,14 +782,6 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
# CONFIG_INPUT_EVBUG is not set
#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-# CONFIG_SERIO is not set
-# CONFIG_SERIO_I8042 is not set
-
-#
# Input Device Drivers
#
# CONFIG_INPUT_KEYBOARD is not set
@@ -759,6 +791,13 @@ CONFIG_SOUND_GAMEPORT=y
# CONFIG_INPUT_MISC is not set
#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
+#
# Character devices
#
# CONFIG_VT is not set
@@ -780,7 +819,6 @@ CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
-# CONFIG_QIC02_TAPE is not set
#
# IPMI
@@ -806,7 +844,6 @@ CONFIG_IXP4XX_WATCHDOG=y
# CONFIG_WDTPCI is not set
# CONFIG_NVRAM is not set
# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
@@ -814,12 +851,15 @@ CONFIG_IXP4XX_WATCHDOG=y
#
# Ftape, the floppy tape device driver
#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
# CONFIG_DRM is not set
# CONFIG_RAW_DRIVER is not set
#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
# I2C support
#
CONFIG_I2C=y
@@ -830,6 +870,7 @@ CONFIG_I2C_CHARDEV=y
#
CONFIG_I2C_ALGOBIT=y
# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
#
# I2C Hardware Bus support
@@ -841,6 +882,7 @@ CONFIG_I2C_ALGOBIT=y
# CONFIG_I2C_AMD8111 is not set
# CONFIG_I2C_I801 is not set
# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_IOP3XX is not set
# CONFIG_I2C_ISA is not set
CONFIG_I2C_IXP4XX=y
# CONFIG_I2C_NFORCE2 is not set
@@ -852,26 +894,41 @@ CONFIG_I2C_IXP4XX=y
# 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
#
# Hardware Sensors Chip support
#
CONFIG_I2C_SENSOR=y
# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ASB100 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
# CONFIG_SENSORS_LM78 is not set
# CONFIG_SENSORS_LM80 is not set
# CONFIG_SENSORS_LM83 is not set
# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
# CONFIG_SENSORS_VIA686A is not set
# CONFIG_SENSORS_W83781D is not set
# CONFIG_SENSORS_W83L785TS is not set
@@ -883,12 +940,17 @@ CONFIG_I2C_SENSOR=y
CONFIG_SENSORS_EEPROM=y
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
# CONFIG_I2C_DEBUG_CORE is not set
# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
# CONFIG_I2C_DEBUG_CHIP is not set
#
+# Misc devices
+#
+
+#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -899,6 +961,33 @@ CONFIG_SENSORS_EEPROM=y
# 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
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -915,10 +1004,15 @@ CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
CONFIG_FS_POSIX_ACL=y
+
+#
+# XFS support
+#
# CONFIG_XFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
@@ -931,7 +1025,8 @@ CONFIG_FS_POSIX_ACL=y
#
# DOS/FAT/NT Filesystems
#
-# CONFIG_FAT_FS is not set
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
# CONFIG_NTFS_FS is not set
#
@@ -942,6 +1037,7 @@ CONFIG_SYSFS=y
# CONFIG_DEVFS_FS is not set
# CONFIG_DEVPTS_FS_XATTR is not set
CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
@@ -959,6 +1055,11 @@ CONFIG_RAMFS=y
CONFIG_JFFS2_FS=y
CONFIG_JFFS2_FS_DEBUG=0
# CONFIG_JFFS2_FS_NAND is not set
+# CONFIG_JFFS2_FS_NOR_ECC is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
# CONFIG_CRAMFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_HPFS_FS is not set
@@ -977,14 +1078,13 @@ CONFIG_NFS_V3=y
CONFIG_ROOT_NFS=y
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
-# CONFIG_EXPORTFS is not set
CONFIG_SUNRPC=y
# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
# CONFIG_CIFS is not set
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
# CONFIG_AFS_FS is not set
#
@@ -1002,7 +1102,6 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_SOLARIS_X86_PARTITION is not set
# CONFIG_UNIXWARE_DISKLABEL is not set
# CONFIG_LDM_PARTITION is not set
-# CONFIG_NEC98_PARTITION is not set
# CONFIG_SGI_PARTITION is not set
# CONFIG_ULTRIX_PARTITION is not set
# CONFIG_SUN_PARTITION is not set
@@ -1019,49 +1118,31 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_PROFILING is not set
#
-# Graphics support
-#
-# CONFIG_FB is not set
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# Misc devices
-#
-
-#
-# USB support
-#
-# CONFIG_USB is not set
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
# Kernel hacking
#
-CONFIG_FRAME_POINTER=y
-# CONFIG_DEBUG_USER is not set
-# CONFIG_DEBUG_INFO is not set
+# CONFIG_PRINTK_TIME is not set
CONFIG_DEBUG_KERNEL=y
-# CONFIG_DEBUG_SLAB is not set
CONFIG_MAGIC_SYSRQ=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_WAITQ 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_FRAME_POINTER=y
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_WAITQ is not set
CONFIG_DEBUG_ERRORS=y
CONFIG_DEBUG_LL=y
# CONFIG_DEBUG_ICEDCC is not set
-# CONFIG_DEBUG_BDI2000_XSCALE is not set
#
# Security options
#
+# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
#
@@ -1070,8 +1151,13 @@ CONFIG_DEBUG_LL=y
# CONFIG_CRYPTO is not set
#
+# Hardware crypto devices
+#
+
+#
# Library routines
#
+# CONFIG_CRC_CCITT is not set
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=y
diff --git a/arch/arm/configs/jornada720_defconfig b/arch/arm/configs/jornada720_defconfig
index b601e918a6d5b..b88aeba82bc0d 100644
--- a/arch/arm/configs/jornada720_defconfig
+++ b/arch/arm/configs/jornada720_defconfig
@@ -1,33 +1,64 @@
#
-# Automatically generated by make menuconfig: don't edit
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.12-rc1-bk2
+# Sun Mar 27 23:10:35 2005
#
CONFIG_ARM=y
-# CONFIG_EISA is not set
-# CONFIG_SBUS is not set
-# CONFIG_MCA is not set
+CONFIG_MMU=y
CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
-# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
-# CONFIG_GENERIC_BUST_SPINLOCK is not set
-# CONFIG_GENERIC_ISA_DMA is not set
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_IOMAP=y
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-# CONFIG_OBSOLETE is not set
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
#
# Loadable module support
#
CONFIG_MODULES=y
+# CONFIG_MODULE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_KMOD=y
#
# System Type
#
-# CONFIG_ARCH_ARCA5K is not set
# CONFIG_ARCH_CLPS7500 is not set
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
@@ -35,136 +66,136 @@ CONFIG_KMOD=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
+# 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=y
+# CONFIG_ARCH_S3C2410 is not set
# CONFIG_ARCH_SHARK is not set
-
-#
-# Archimedes/A5000 Implementations
-#
-# CONFIG_ARCH_ARC is not set
-# CONFIG_ARCH_A5K is not set
-
-#
-# Footbridge Implementations
-#
-# CONFIG_ARCH_CATS is not set
-# CONFIG_ARCH_PERSONAL_SERVER is not set
-# CONFIG_ARCH_EBSA285_ADDIN is not set
-# CONFIG_ARCH_EBSA285_HOST is not set
-# CONFIG_ARCH_NETWINDER 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
#
# SA11x0 Implementations
#
# CONFIG_SA1100_ASSABET is not set
-# CONFIG_ASSABET_NEPONSET is not set
-# CONFIG_SA1100_ADSBITSY is not set
-# CONFIG_SA1100_BRUTUS is not set
# CONFIG_SA1100_CERF is not set
+# CONFIG_SA1100_COLLIE is not set
# CONFIG_SA1100_H3100 is not set
# CONFIG_SA1100_H3600 is not set
# CONFIG_SA1100_H3800 is not set
-# CONFIG_SA1100_H3XXX is not set
-# CONFIG_SA1100_EXTENEX1 is not set
-# CONFIG_SA1100_FLEXANET is not set
-# CONFIG_SA1100_FREEBIRD is not set
-# CONFIG_SA1100_GRAPHICSCLIENT is not set
-# CONFIG_SA1100_GRAPHICSMASTER is not set
+# CONFIG_SA1100_BADGE4 is not set
CONFIG_SA1100_JORNADA720=y
-# CONFIG_SA1100_HUW_WEBPANEL is not set
-# CONFIG_SA1100_ITSY is not set
+# CONFIG_SA1100_HACKKIT is not set
# CONFIG_SA1100_LART is not set
-# CONFIG_SA1100_NANOENGINE is not set
-# CONFIG_SA1100_OMNIMETER is not set
-# CONFIG_SA1100_PANGOLIN is not set
# CONFIG_SA1100_PLEB is not set
# CONFIG_SA1100_SHANNON is not set
-# CONFIG_SA1100_SHERMAN is not set
# CONFIG_SA1100_SIMPAD is not set
-# CONFIG_SA1100_PFS168 is not set
-# CONFIG_SA1100_VICTOR is not set
-# CONFIG_SA1100_XP860 is not set
-# CONFIG_SA1100_YOPY is not set
-CONFIG_SA1111=y
-CONFIG_FORCE_MAX_ZONEORDER=9
-# CONFIG_SA1100_USB is not set
-# CONFIG_SA1100_USB_NETLINK is not set
-# CONFIG_SA1100_USB_CHAR is not set
-# CONFIG_REGISTERS is not set
-
-#
-# CLPS711X/EP721X Implementations
-#
-# CONFIG_ARCH_AUTCPU12 is not set
-# CONFIG_ARCH_CDB89712 is not set
-# CONFIG_ARCH_CLEP7312 is not set
-# CONFIG_ARCH_EDB7211 is not set
-# CONFIG_ARCH_P720T is not set
-# CONFIG_ARCH_EP7211 is not set
-# CONFIG_ARCH_EP7212 is not set
-# CONFIG_ARCH_ACORN is not set
-# CONFIG_FOOTBRIDGE is not set
-# CONFIG_FOOTBRIDGE_HOST is not set
-# CONFIG_FOOTBRIDGE_ADDIN is not set
+# CONFIG_SA1100_SSP is not set
+
+#
+# Processor Type
+#
CONFIG_CPU_32=y
-# CONFIG_CPU_26 is not set
-# CONFIG_CPU_32v3 is not set
-CONFIG_CPU_32v4=y
-# CONFIG_CPU_ARM610 is not set
-# CONFIG_CPU_ARM710 is not set
-# CONFIG_CPU_ARM720T is not set
-# CONFIG_CPU_ARM920T is not set
-# CONFIG_CPU_ARM922T is not set
-# CONFIG_CPU_ARM926T is not set
-# CONFIG_CPU_ARM1020 is not set
-# CONFIG_CPU_SA110 is not set
CONFIG_CPU_SA1100=y
-# CONFIG_ARM_THUMB is not set
-CONFIG_DISCONTIGMEM=y
+CONFIG_CPU_32v4=y
+CONFIG_CPU_ABRT_EV4=y
+CONFIG_CPU_CACHE_V4WB=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_TLB_V4WB=y
+CONFIG_CPU_MINICACHE=y
#
-# General setup
+# Processor Features
+#
+CONFIG_SA1111=y
+CONFIG_DMABOUNCE=y
+CONFIG_FORCE_MAX_ZONEORDER=9
+
+#
+# Bus support
#
-# CONFIG_PCI is not set
CONFIG_ISA=y
-# CONFIG_ISA_DMA is not set
-# CONFIG_CPU_FREQ is not set
-CONFIG_HOTPLUG=y
#
-# PCMCIA/CardBus support
+# PCCARD (PCMCIA/CardBus) support
#
+CONFIG_PCCARD=y
+# CONFIG_PCMCIA_DEBUG is not set
CONFIG_PCMCIA=y
-# CONFIG_I82092 is not set
-# CONFIG_I82365 is not set
+
+#
+# PC-card bridges
+#
+CONFIG_I82365=y
# CONFIG_TCIC is not set
-# CONFIG_PCMCIA_CLPS6700 is not set
CONFIG_PCMCIA_SA1100=y
-# CONFIG_MERCURY_BACKPAQ is not set
-CONFIG_NET=y
-CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
+# CONFIG_PCMCIA_SA1111 is not set
+CONFIG_PCCARD_NONSTATIC=y
+
+#
+# Kernel Features
+#
+# CONFIG_PREEMPT is not set
+CONFIG_DISCONTIGMEM=y
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="keepinitrd mem=32M"
+# CONFIG_XIP_KERNEL is not set
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ 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=y
-CONFIG_KCORE_ELF=y
-# CONFIG_KCORE_AOUT is not set
-CONFIG_BINFMT_AOUT=m
+
+#
+# Userspace binary formats
+#
CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_AOUT=m
# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
CONFIG_PM=y
# CONFIG_APM is not set
-# CONFIG_ARTHUR is not set
-CONFIG_CMDLINE="keepinitrd mem=32M"
-# CONFIG_LEDS is not set
-CONFIG_ALIGNMENT_TRAP=y
#
-# Parallel port support
+# Device Drivers
#
-# CONFIG_PARPORT is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
#
# Memory Technology Devices (MTD)
@@ -172,14 +203,20 @@ CONFIG_ALIGNMENT_TRAP=y
CONFIG_MTD=y
CONFIG_MTD_DEBUG=y
CONFIG_MTD_DEBUG_VERBOSE=1
+# CONFIG_MTD_CONCAT is not set
CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_REDBOOT_PARTS is not set
-CONFIG_MTD_BOOTLDR_PARTS=y
+# CONFIG_MTD_CMDLINE_PARTS is not set
# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
CONFIG_MTD_CHAR=m
CONFIG_MTD_BLOCK=y
# CONFIG_FTL is not set
# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
#
# RAM/ROM/Flash chip drivers
@@ -192,45 +229,49 @@ CONFIG_MTD_CFI_NOSWAP=y
# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
CONFIG_MTD_CFI_GEOMETRY=y
-# CONFIG_MTD_CFI_B1 is not set
-CONFIG_MTD_CFI_B2=y
-CONFIG_MTD_CFI_B4=y
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
CONFIG_MTD_CFI_I1=y
CONFIG_MTD_CFI_I2=y
# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
CONFIG_MTD_CFI_INTELEXT=y
# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
-# CONFIG_MTD_AMDSTD is not set
-# CONFIG_MTD_SHARP is not set
-# CONFIG_MTD_JEDEC 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_NORA is not set
# CONFIG_MTD_ARM_INTEGRATOR is not set
-# CONFIG_MTD_CDB89712 is not set
CONFIG_MTD_SA1100=y
-# CONFIG_MTD_H3600_BACKPAQ is not set
-# CONFIG_MTD_DC21285 is not set
-# CONFIG_MTD_IQ80310 is not set
+# CONFIG_MTD_EDB7312 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_DOC1000 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_DOCPROBE is not set
+# CONFIG_MTD_DOC2001PLUS is not set
#
# NAND Flash Device Drivers
@@ -238,49 +279,101 @@ CONFIG_MTD_SA1100=y
# CONFIG_MTD_NAND is not set
#
-# Plug and Play configuration
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
#
# CONFIG_PNP is not set
-# CONFIG_ISAPNP is not set
#
# Block devices
#
# CONFIG_BLK_DEV_FD is not set
# CONFIG_BLK_DEV_XD is not set
-# CONFIG_PARIDE is not set
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
CONFIG_BLK_DEV_LOOP=m
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
CONFIG_BLK_DEV_NBD=m
# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=m
+CONFIG_BLK_DEV_IDE=m
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=m
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDECS is not set
+CONFIG_BLK_DEV_IDECD=m
+# 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=m
+# CONFIG_IDE_ARM is not set
+# CONFIG_IDE_CHIPSETS is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
#
# Multi-device support (RAID and LVM)
#
# CONFIG_MD is not set
-# CONFIG_BLK_DEV_MD is not set
-# CONFIG_MD_LINEAR is not set
-# CONFIG_MD_RAID0 is not set
-# CONFIG_MD_RAID1 is not set
-# CONFIG_MD_RAID5 is not set
-# CONFIG_MD_MULTIPATH is not set
-# CONFIG_BLK_DEV_LVM is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
#
# Networking options
#
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
-CONFIG_NETLINK=y
-CONFIG_RTNETLINK=y
# CONFIG_NETLINK_DEV is not set
-CONFIG_NETFILTER=y
-# CONFIG_NETFILTER_DEBUG is not set
-CONFIG_FILTER=y
CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
# CONFIG_IP_ADVANCED_ROUTER is not set
@@ -289,204 +382,200 @@ CONFIG_IP_MULTICAST=y
# CONFIG_NET_IPGRE is not set
# CONFIG_IP_MROUTE is not set
# CONFIG_ARPD is not set
-# CONFIG_INET_ECN is not set
# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_IP_TCPDIAG is not set
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
#
-# IP: Netfilter Configuration
+# IP: Netfilter Configuration
#
# CONFIG_IP_NF_CONNTRACK is not set
+# CONFIG_IP_NF_CONNTRACK_MARK is not set
# CONFIG_IP_NF_QUEUE is not set
# CONFIG_IP_NF_IPTABLES is not set
-# CONFIG_IP_NF_COMPAT_IPCHAINS is not set
-# CONFIG_IP_NF_COMPAT_IPFWADM is not set
-# CONFIG_IPV6 is not set
-# CONFIG_KHTTPD is not set
+# CONFIG_IP_NF_ARPTABLES 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_DECNET is not set
-# CONFIG_BRIDGE is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-# CONFIG_LLC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
#
# QoS and/or fair queueing
#
# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
#
-# Network device support
+# Network testing
#
-CONFIG_NETDEVICES=y
+# 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=m
#
-# ARCnet devices
+# IrDA protocols
#
-# CONFIG_ARCNET is not set
+CONFIG_IRLAN=m
+# CONFIG_IRNET is not set
+CONFIG_IRCOMM=m
+# CONFIG_IRDA_ULTRA is not set
+
+#
+# IrDA options
+#
+# CONFIG_IRDA_CACHE_LAST_LSAP is not set
+# CONFIG_IRDA_FAST_RR is not set
+# 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
+#
+# CONFIG_IRPORT_SIR is not set
+
+#
+# Old Serial dongle support
+#
+
+#
+# FIR device drivers
+#
+# CONFIG_NSC_FIR is not set
+# CONFIG_WINBOND_FIR is not set
+# CONFIG_SMC_IRCC_FIR is not set
+# CONFIG_ALI_FIR is not set
+CONFIG_SA1100_FIR=m
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
#
# Ethernet (10 or 100Mbit)
#
# CONFIG_NET_ETHERNET is not set
+CONFIG_MII=m
#
# Ethernet (1000 Mbit)
#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_MYRI_SBUS is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PLIP is not set
-CONFIG_PPP=m
-# CONFIG_PPP_MULTILINK is not set
-# CONFIG_PPP_FILTER is not set
-CONFIG_PPP_ASYNC=m
-# CONFIG_PPP_SYNC_TTY is not set
-CONFIG_PPP_DEFLATE=m
-CONFIG_PPP_BSDCOMP=m
-# CONFIG_PPPOE is not set
-# CONFIG_SLIP is not set
#
-# Wireless LAN (non-hamradio)
+# Ethernet (10000 Mbit)
#
-CONFIG_NET_RADIO=y
-# CONFIG_STRIP is not set
-CONFIG_WAVELAN=m
-CONFIG_ARLAN=m
-CONFIG_AIRONET4500=m
-CONFIG_AIRONET4500_NONCS=m
-# CONFIG_AIRONET4500_PNP is not set
-# CONFIG_AIRONET4500_PCI is not set
-# CONFIG_AIRONET4500_ISA is not set
-# CONFIG_AIRONET4500_I365 is not set
-# CONFIG_AIRONET4500_PROC is not set
-# CONFIG_AIRO is not set
-CONFIG_HERMES=m
-CONFIG_PCMCIA_HERMES=m
-CONFIG_AIRO_CS=m
-CONFIG_NET_WIRELESS=y
#
# Token Ring devices
#
# CONFIG_TR is not set
-# CONFIG_NET_FC is not set
-# CONFIG_RCPCI is not set
-# CONFIG_SHAPER is not set
#
-# Wan interfaces
+# Wireless LAN (non-hamradio)
#
-# CONFIG_WAN is not set
+CONFIG_NET_RADIO=y
#
-# PCMCIA network device support
+# Obsolete Wireless cards support (pre-802.11)
#
-CONFIG_NET_PCMCIA=y
-CONFIG_PCMCIA_3C589=m
-CONFIG_PCMCIA_3C574=m
-CONFIG_PCMCIA_FMVJ18X=m
-CONFIG_PCMCIA_PCNET=m
-CONFIG_PCMCIA_NMCLAN=m
-CONFIG_PCMCIA_SMC91C92=m
-CONFIG_PCMCIA_XIRC2PS=m
-# CONFIG_PCMCIA_AXNET is not set
-# CONFIG_ARCNET_COM20020_CS is not set
-# CONFIG_PCMCIA_IBMTR is not set
-CONFIG_NET_PCMCIA_RADIO=y
-# CONFIG_PCMCIA_RAYCS is not set
-# CONFIG_PCMCIA_NETWAVE is not set
+# CONFIG_STRIP is not set
+CONFIG_ARLAN=m
+CONFIG_WAVELAN=m
CONFIG_PCMCIA_WAVELAN=m
-CONFIG_AIRONET4500_CS=m
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-CONFIG_IRDA=m
-CONFIG_IRLAN=m
-# CONFIG_IRNET is not set
-CONFIG_IRCOMM=m
-# CONFIG_IRDA_ULTRA is not set
-# CONFIG_IRDA_OPTIONS is not set
+# CONFIG_PCMCIA_NETWAVE is not set
#
-# Infrared-port device drivers
+# Wireless 802.11 Frequency Hopping cards support
#
-# CONFIG_IRTTY_SIR is not set
-# CONFIG_IRPORT_SIR is not set
-# CONFIG_DONGLE is not set
-# CONFIG_USB_IRDA 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_SA1100_FIR=m
+# CONFIG_PCMCIA_RAYCS is not set
#
-# ATA/IDE/MFM/RLL support
+# Wireless 802.11b ISA/PCI cards support
#
-CONFIG_IDE=m
+CONFIG_HERMES=m
+# CONFIG_ATMEL is not set
#
-# IDE, ATA and ATAPI Block devices
+# Wireless 802.11b Pcmcia/Cardbus cards support
#
-CONFIG_BLK_DEV_IDE=m
-# CONFIG_BLK_DEV_HD_IDE is not set
-# CONFIG_BLK_DEV_HD is not set
-CONFIG_BLK_DEV_IDEDISK=m
-# CONFIG_IDEDISK_MULTI_MODE is not set
-CONFIG_BLK_DEV_IDECS=m
-CONFIG_BLK_DEV_IDECD=m
-# CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
-# CONFIG_BLK_DEV_IDESCSI is not set
-# CONFIG_BLK_DEV_CMD640 is not set
-# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
-# CONFIG_BLK_DEV_ISAPNP is not set
-# CONFIG_IDE_CHIPSETS is not set
-# CONFIG_IDEDMA_AUTO is not set
-# CONFIG_BLK_DEV_ATARAID is not set
-# CONFIG_BLK_DEV_ATARAID_PDC is not set
-# CONFIG_BLK_DEV_ATARAID_HPT is not set
+CONFIG_PCMCIA_HERMES=m
+CONFIG_AIRO_CS=m
+# CONFIG_PCMCIA_WL3501 is not set
+CONFIG_NET_WIRELESS=y
#
-# SCSI support
+# PCMCIA network device support
#
-# CONFIG_SCSI is not set
+CONFIG_NET_PCMCIA=y
+CONFIG_PCMCIA_3C589=m
+CONFIG_PCMCIA_3C574=m
+CONFIG_PCMCIA_FMVJ18X=m
+CONFIG_PCMCIA_PCNET=m
+CONFIG_PCMCIA_NMCLAN=m
+CONFIG_PCMCIA_SMC91C92=m
+CONFIG_PCMCIA_XIRC2PS=m
+CONFIG_PCMCIA_AXNET=m
#
-# I2O device support
+# Wan interfaces
#
-# CONFIG_I2O is not set
-# CONFIG_I2O_BLOCK is not set
-# CONFIG_I2O_LAN is not set
-# CONFIG_I2O_SCSI is not set
-# CONFIG_I2O_PROC is not set
+# CONFIG_WAN is not set
+CONFIG_PPP=m
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+# CONFIG_PPP_SYNC_TTY is not set
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+# CONFIG_PPPOE is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
#
# ISDN subsystem
@@ -494,399 +583,337 @@ CONFIG_BLK_DEV_IDECD=m
# CONFIG_ISDN is not set
#
-# Input core support
+# Input device support
#
CONFIG_INPUT=y
-# CONFIG_INPUT_KEYBDEV is not set
+
+#
+# Userland interfaces
+#
CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
CONFIG_INPUT_MOUSEDEV_SCREEN_X=640
CONFIG_INPUT_MOUSEDEV_SCREEN_Y=240
# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_INPORT is not set
+# CONFIG_MOUSE_LOGIBM is not set
+# CONFIG_MOUSE_PC110PAD is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_SA1111 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
#
# Character devices
#
CONFIG_VT=y
CONFIG_VT_CONSOLE=y
-CONFIG_SERIAL=m
-# CONFIG_SERIAL_EXTENDED is not set
+CONFIG_HW_CONSOLE=y
# CONFIG_SERIAL_NONSTANDARD is not set
#
# Serial drivers
#
-# CONFIG_SERIAL_AMBA is not set
-# CONFIG_SERIAL_AMBA_CONSOLE is not set
-# CONFIG_SERIAL_CLPS711X is not set
-# CONFIG_SERIAL_CLPS711X_CONSOLE is not set
-# CONFIG_SERIAL_21285 is not set
-# CONFIG_SERIAL_21285_OLD is not set
-# CONFIG_SERIAL_21285_CONSOLE is not set
-# CONFIG_SERIAL_UART00 is not set
-# CONFIG_SERIAL_UART00_CONSOLE is not set
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
CONFIG_SERIAL_SA1100=y
CONFIG_SERIAL_SA1100_CONSOLE=y
-CONFIG_SA1100_DEFAULT_BAUDRATE=115200
-# CONFIG_SERIAL_8250 is not set
-# CONFIG_SERIAL_8250_CONSOLE is not set
-# CONFIG_SERIAL_8250_EXTENDED is not set
-# CONFIG_SERIAL_8250_MANY_PORTS is not set
-# CONFIG_SERIAL_8250_SHARE_IRQ is not set
-# CONFIG_SERIAL_8250_DETECT_IRQ is not set
-# CONFIG_SERIAL_8250_MULTIPORT is not set
-# CONFIG_SERIAL_8250_HUB6 is not set
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=32
-# CONFIG_NEWTONKBD is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
#
-# I2C support
-#
-# CONFIG_I2C is not set
-
+# IPMI
#
-# L3 serial bus support
-#
-# CONFIG_L3 is not set
-# CONFIG_L3_ALGOBIT is not set
-# CONFIG_L3_BIT_SA1100_GPIO is not set
-# CONFIG_L3_SA1111 is not set
-# CONFIG_BIT_SA1100_GPIO is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-CONFIG_MOUSE=m
-# CONFIG_PSMOUSE is not set
-# CONFIG_82C710_MOUSE is not set
-# CONFIG_PC110_PAD is not set
-
-#
-# Joysticks
-#
-# CONFIG_INPUT_GAMEPORT is not set
-# CONFIG_INPUT_NS558 is not set
-# CONFIG_INPUT_LIGHTNING is not set
-# CONFIG_INPUT_PCIGAME is not set
-# CONFIG_INPUT_CS461X is not set
-# CONFIG_INPUT_EMU10K1 is not set
-# CONFIG_INPUT_SERIO is not set
-# CONFIG_INPUT_SERPORT is not set
-# CONFIG_INPUT_ANALOG is not set
-# CONFIG_INPUT_A3D is not set
-# CONFIG_INPUT_ADI is not set
-# CONFIG_INPUT_COBRA is not set
-# CONFIG_INPUT_GF2K is not set
-# CONFIG_INPUT_GRIP is not set
-# CONFIG_INPUT_INTERACT is not set
-# CONFIG_INPUT_TMDC is not set
-# CONFIG_INPUT_SIDEWINDER is not set
-# CONFIG_INPUT_IFORCE_USB is not set
-# CONFIG_INPUT_IFORCE_232 is not set
-# CONFIG_INPUT_WARRIOR is not set
-# CONFIG_INPUT_MAGELLAN is not set
-# CONFIG_INPUT_SPACEORB is not set
-# CONFIG_INPUT_SPACEBALL is not set
-# CONFIG_INPUT_STINGER is not set
-# CONFIG_INPUT_DB9 is not set
-# CONFIG_INPUT_GAMECON is not set
-# CONFIG_INPUT_TURBOGRAFX is not set
-# CONFIG_QIC02_TAPE is not set
+# CONFIG_IPMI_HANDLER is not set
#
# Watchdog Cards
#
# CONFIG_WATCHDOG is not set
-# CONFIG_INTEL_RNG is not set
# CONFIG_NVRAM is not set
# CONFIG_RTC is not set
-CONFIG_SA1100_RTC=m
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
#
# Ftape, the floppy tape device driver
#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
# CONFIG_DRM is not set
#
# PCMCIA character devices
#
-# CONFIG_PCMCIA_SERIAL_CS is not set
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Misc devices
+#
#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
-# CONFIG_V4L2_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_SOFT_CURSOR is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_SA1100 is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE is not set
+
+#
+# Logo configuration
+#
+# CONFIG_LOGO is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+# CONFIG_SND 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 is not set
+
+#
+# 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_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_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_REISERFS_CHECK is not set
-# CONFIG_REISERFS_PROC_INFO is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS 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_DEVFS_FS=y
+CONFIG_DEVFS_MOUNT=y
+CONFIG_DEVFS_DEBUG=y
+# CONFIG_DEVPTS_FS_XATTR is not set
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
# CONFIG_ADFS_FS is not set
-# CONFIG_ADFS_FS_RW 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_EXT3_FS is not set
-# CONFIG_JBD is not set
-# CONFIG_JBD_DEBUG is not set
-# CONFIG_FAT_FS is not set
-# CONFIG_MSDOS_FS is not set
-# CONFIG_UMSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
# CONFIG_EFS_FS is not set
# CONFIG_JFFS_FS is not set
CONFIG_JFFS2_FS=y
CONFIG_JFFS2_FS_DEBUG=2
+# CONFIG_JFFS2_FS_NAND is not set
+# CONFIG_JFFS2_FS_NOR_ECC is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
# CONFIG_CRAMFS is not set
-# CONFIG_TMPFS is not set
-CONFIG_RAMFS=y
-CONFIG_ISO9660_FS=m
-# CONFIG_JOLIET is not set
-# CONFIG_ZISOFS is not set
-# CONFIG_MINIX_FS is not set
# CONFIG_VXFS_FS is not set
-# CONFIG_NTFS_FS is not set
-# CONFIG_NTFS_DEBUG is not set
-# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
-CONFIG_PROC_FS=y
-CONFIG_DEVFS_FS=y
-CONFIG_DEVFS_MOUNT=y
-CONFIG_DEVFS_DEBUG=y
-# CONFIG_DRIVERFS_FS is not set
-CONFIG_DEVPTS_FS=y
# CONFIG_QNX4FS_FS is not set
-# CONFIG_QNX4FS_RW is not set
-# CONFIG_ROMFS_FS is not set
-CONFIG_EXT2_FS=y
# CONFIG_SYSV_FS is not set
-# CONFIG_UDF_FS is not set
-# CONFIG_UDF_RW is not set
# CONFIG_UFS_FS is not set
-# CONFIG_UFS_FS_WRITE is not set
#
# Network File Systems
#
-# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
CONFIG_NFS_FS=m
CONFIG_NFS_V3=y
-# CONFIG_ROOT_NFS is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
# CONFIG_NFSD is not set
-# CONFIG_NFSD_V3 is not set
-CONFIG_SUNRPC=m
CONFIG_LOCKD=m
CONFIG_LOCKD_V4=y
+CONFIG_SUNRPC=m
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
# CONFIG_NCP_FS is not set
-# CONFIG_NCPFS_PACKET_SIGNING is not set
-# CONFIG_NCPFS_IOCTL_LOCKING is not set
-# CONFIG_NCPFS_STRONG is not set
-# CONFIG_NCPFS_NFS_NS is not set
-# CONFIG_NCPFS_OS2_NS is not set
-# CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_NLS is not set
-# CONFIG_NCPFS_EXTRAS is not set
-# CONFIG_ZISOFS_FS is not set
-# CONFIG_ZLIB_FS_INFLATE is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
#
# Partition Types
#
# CONFIG_PARTITION_ADVANCED is not set
CONFIG_MSDOS_PARTITION=y
-# CONFIG_SMB_NLS is not set
+
+#
+# Native Language Support
+#
# CONFIG_NLS is not set
#
-# Console drivers
+# Profiling support
#
-CONFIG_PC_KEYMAP=y
-# CONFIG_VGA_CONSOLE is not set
+# CONFIG_PROFILING is not set
#
-# Frame-buffer support
+# Kernel hacking
#
-CONFIG_FB=y
-CONFIG_DUMMY_CONSOLE=y
-# CONFIG_FB_ACORN is not set
-# CONFIG_FB_CLPS711X is not set
-# CONFIG_FB_SA1100 is not set
-CONFIG_FB_EPSON1356=y
-# CONFIG_FB_CYBER2000 is not set
-# CONFIG_FB_VIRTUAL is not set
-CONFIG_FBCON_ADVANCED=y
-# CONFIG_FBCON_MFB is not set
-# CONFIG_FBCON_CFB2 is not set
-# CONFIG_FBCON_CFB4 is not set
-# CONFIG_FBCON_CFB8 is not set
-CONFIG_FBCON_CFB16=y
-# CONFIG_FBCON_CFB24 is not set
-# CONFIG_FBCON_CFB32 is not set
-# CONFIG_FBCON_AFB is not set
-# CONFIG_FBCON_ILBM is not set
-# CONFIG_FBCON_IPLAN2P2 is not set
-# CONFIG_FBCON_IPLAN2P4 is not set
-# CONFIG_FBCON_IPLAN2P8 is not set
-# CONFIG_FBCON_MAC is not set
-# CONFIG_FBCON_VGA_PLANES is not set
-# CONFIG_FBCON_VGA is not set
-# CONFIG_FBCON_HGA is not set
-CONFIG_FBCON_FONTWIDTH8_ONLY=y
-CONFIG_FBCON_FONTS=y
-CONFIG_FONT_8x8=y
-# CONFIG_FONT_8x16 is not set
-# CONFIG_FONT_SUN8x16 is not set
-# CONFIG_FONT_PEARL_8x8 is not set
-# CONFIG_FONT_ACORN_8x8 is not set
+# CONFIG_PRINTK_TIME is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_SCHEDSTATS is not set
+CONFIG_DEBUG_SLAB=y
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_FS is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_WAITQ is not set
+CONFIG_DEBUG_ERRORS=y
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
#
-# Sound
+# Security options
#
-CONFIG_SOUND=m
-# CONFIG_SOUND_BT878 is not set
-# CONFIG_SOUND_CMPCI is not set
-# CONFIG_SOUND_EMU10K1 is not set
-# CONFIG_MIDI_EMU10K1 is not set
-# CONFIG_SOUND_FUSION is not set
-# CONFIG_SOUND_CS4281 is not set
-# CONFIG_SOUND_ES1370 is not set
-# CONFIG_SOUND_ES1371 is not set
-# CONFIG_SOUND_ESSSOLO1 is not set
-# CONFIG_SOUND_MAESTRO is not set
-# CONFIG_SOUND_MAESTRO3 is not set
-# CONFIG_SOUND_ICH is not set
-# CONFIG_SOUND_RME96XX is not set
-# CONFIG_SOUND_SONICVIBES is not set
-# CONFIG_SOUND_TRIDENT is not set
-# CONFIG_SOUND_MSNDCLAS is not set
-# CONFIG_SOUND_MSNDPIN is not set
-# CONFIG_SOUND_VIA82CXXX is not set
-# CONFIG_MIDI_VIA82CXXX is not set
-CONFIG_SOUND_SA1100=m
-# CONFIG_SOUND_UDA1341 is not set
-# CONFIG_SOUND_ASSABET_UDA1341 is not set
-# CONFIG_SOUND_H3600_UDA1341 is not set
-# CONFIG_SOUND_PANGOLIN_UDA1341 is not set
-# CONFIG_SOUND_SA1111_UDA1341 is not set
-# CONFIG_SOUND_SA1100SSP is not set
-# CONFIG_SOUND_OSS is not set
-# CONFIG_SOUND_WAVEARTIST is not set
-# CONFIG_SOUND_TVMIXER is not set
-
-#
-# Multimedia Capabilities Port drivers
-#
-# CONFIG_MCP is not set
-# CONFIG_MCP_SA1100 is not set
-# CONFIG_MCP_UCB1200 is not set
-# CONFIG_MCP_UCB1200_AUDIO is not set
-# CONFIG_MCP_UCB1200_TS is not set
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
#
-# USB support
+# Cryptographic options
#
-# CONFIG_USB is not set
-# CONFIG_USB_UHCI is not set
-# CONFIG_USB_UHCI_ALT is not set
-# CONFIG_USB_OHCI is not set
-# CONFIG_USB_OHCI_SA1111 is not set
-# CONFIG_USB_AUDIO is not set
-# CONFIG_USB_BLUETOOTH is not set
-# CONFIG_USB_STORAGE is not set
-# CONFIG_USB_STORAGE_DEBUG is not set
-# CONFIG_USB_STORAGE_DATAFAB is not set
-# CONFIG_USB_STORAGE_FREECOM is not set
-# CONFIG_USB_STORAGE_ISD200 is not set
-# CONFIG_USB_STORAGE_DPCM is not set
-# CONFIG_USB_STORAGE_HP8200e is not set
-# CONFIG_USB_STORAGE_SDDR09 is not set
-# CONFIG_USB_STORAGE_JUMPSHOT is not set
-# CONFIG_USB_ACM is not set
-# CONFIG_USB_PRINTER is not set
-# CONFIG_USB_HID is not set
-# CONFIG_USB_HIDDEV is not set
-# CONFIG_USB_KBD is not set
-# CONFIG_USB_MOUSE is not set
-# CONFIG_USB_WACOM is not set
-# CONFIG_USB_DC2XX is not set
-# CONFIG_USB_MDC800 is not set
-# CONFIG_USB_SCANNER is not set
-# CONFIG_USB_MICROTEK is not set
-# CONFIG_USB_HPUSBSCSI is not set
-# CONFIG_USB_PEGASUS is not set
-# CONFIG_USB_KAWETH is not set
-# CONFIG_USB_CATC is not set
-# CONFIG_USB_CDCETHER is not set
-# CONFIG_USB_USBNET is not set
-# CONFIG_USB_USS720 is not set
-
-#
-# USB Serial Converter support
-#
-# CONFIG_USB_SERIAL is not set
-# CONFIG_USB_SERIAL_GENERIC is not set
-# CONFIG_USB_SERIAL_BELKIN is not set
-# CONFIG_USB_SERIAL_WHITEHEAT is not set
-# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
-# CONFIG_USB_SERIAL_EMPEG is not set
-# CONFIG_USB_SERIAL_FTDI_SIO is not set
-# CONFIG_USB_SERIAL_VISOR is not set
-# CONFIG_USB_SERIAL_IR is not set
-# CONFIG_USB_SERIAL_EDGEPORT is not set
-# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
-# CONFIG_USB_SERIAL_KEYSPAN 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_USA49W is not set
-# CONFIG_USB_SERIAL_MCT_U232 is not set
-# CONFIG_USB_SERIAL_PL2303 is not set
-# CONFIG_USB_SERIAL_CYBERJACK is not set
-# CONFIG_USB_SERIAL_XIRCOM is not set
-# CONFIG_USB_SERIAL_OMNINET is not set
-# CONFIG_USB_RIO500 is not set
-
-#
-# Bluetooth support
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
#
-# CONFIG_BT is not set
#
-# Kernel hacking
+# Library routines
#
-CONFIG_FRAME_POINTER=y
-# CONFIG_DEBUG_USER is not set
-# CONFIG_DEBUG_INFO is not set
-# CONFIG_NO_PGT_CACHE is not set
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_SLAB=y
-# CONFIG_MAGIC_SYSRQ is not set
-# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_WAITQ is not set
-# CONFIG_DEBUG_BUGVERBOSE is not set
-CONFIG_DEBUG_ERRORS=y
-CONFIG_DEBUG_LL=y
-# CONFIG_DEBUG_DC21285_PORT is not set
-# CONFIG_DEBUG_CLPS711X_UART2 is not set
-# CONFIG_DEBUG_LL_SER3 is not set
+CONFIG_CRC_CCITT=m
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/arm/configs/lart_defconfig b/arch/arm/configs/lart_defconfig
index 64fd2a7611ce4..7033829ed1452 100644
--- a/arch/arm/configs/lart_defconfig
+++ b/arch/arm/configs/lart_defconfig
@@ -1,35 +1,49 @@
#
# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.12-rc1-bk2
+# Sun Mar 27 23:53:24 2005
#
CONFIG_ARM=y
CONFIG_MMU=y
CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_IOMAP=y
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
CONFIG_CLEAN_COMPILE=y
-CONFIG_STANDALONE=y
CONFIG_BROKEN_ON_SMP=y
#
# General setup
#
+CONFIG_LOCALVERSION=""
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
-CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_AUDIT is not set
+# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
# CONFIG_IKCONFIG is not set
# CONFIG_EMBEDDED is not set
CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
#
# Loadable module support
@@ -38,90 +52,51 @@ CONFIG_MODULES=y
# CONFIG_MODULE_UNLOAD is not set
CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_KMOD=y
#
# System Type
#
-# CONFIG_ARCH_ADIFCC is not set
# CONFIG_ARCH_CLPS7500 is not set
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
-# CONFIG_ARCH_PXA 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=y
+# CONFIG_ARCH_S3C2410 is not set
# CONFIG_ARCH_SHARK is not set
-
-#
-# CLPS711X/EP721X Implementations
-#
-
-#
-# Epxa10db
-#
-
-#
-# Footbridge Implementations
-#
-
-#
-# IOP3xx Implementation Options
-#
-# CONFIG_ARCH_IOP310 is not set
-# CONFIG_ARCH_IOP321 is not set
-
-#
-# IOP3xx Chipset Features
-#
-
-#
-# Intel PXA250/210 Implementations
-#
+# 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
#
# SA11x0 Implementations
#
# CONFIG_SA1100_ASSABET is not set
-# CONFIG_SA1100_ADSBITSY is not set
-# CONFIG_SA1100_BRUTUS is not set
# CONFIG_SA1100_CERF is not set
+# CONFIG_SA1100_COLLIE is not set
# CONFIG_SA1100_H3100 is not set
# CONFIG_SA1100_H3600 is not set
# CONFIG_SA1100_H3800 is not set
-# CONFIG_SA1100_EXTENEX1 is not set
-# CONFIG_SA1100_FLEXANET is not set
-# CONFIG_SA1100_FREEBIRD is not set
-# CONFIG_SA1100_GRAPHICSCLIENT is not set
-# CONFIG_SA1100_GRAPHICSMASTER is not set
# CONFIG_SA1100_BADGE4 is not set
# CONFIG_SA1100_JORNADA720 is not set
# CONFIG_SA1100_HACKKIT is not set
-# CONFIG_SA1100_HUW_WEBPANEL is not set
-# CONFIG_SA1100_ITSY is not set
CONFIG_SA1100_LART=y
-# CONFIG_SA1100_NANOENGINE is not set
-# CONFIG_SA1100_OMNIMETER is not set
-# CONFIG_SA1100_PANGOLIN is not set
# CONFIG_SA1100_PLEB is not set
-# CONFIG_SA1100_PT_SYSTEM3 is not set
# CONFIG_SA1100_SHANNON is not set
-# CONFIG_SA1100_SHERMAN is not set
# CONFIG_SA1100_SIMPAD is not set
-# CONFIG_SA1100_PFS168 is not set
-# CONFIG_SA1100_VICTOR is not set
-# CONFIG_SA1100_XP860 is not set
-# CONFIG_SA1100_YOPY is not set
-# CONFIG_SA1100_STORK is not set
# CONFIG_SA1100_SSP is not set
-CONFIG_SA1100_USB=m
-CONFIG_SA1100_USB_NETLINK=m
-CONFIG_SA1100_USB_CHAR=m
#
# Processor Type
@@ -131,6 +106,7 @@ CONFIG_CPU_SA1100=y
CONFIG_CPU_32v4=y
CONFIG_CPU_ABRT_EV4=y
CONFIG_CPU_CACHE_V4WB=y
+CONFIG_CPU_CACHE_VIVT=y
CONFIG_CPU_TLB_V4WB=y
CONFIG_CPU_MINICACHE=y
@@ -139,51 +115,84 @@ CONFIG_CPU_MINICACHE=y
#
#
-# General setup
+# Bus support
#
-CONFIG_DISCONTIGMEM=y
CONFIG_ISA=y
-# CONFIG_ZBOOT_ROM is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_PREEMPT is not set
+CONFIG_DISCONTIGMEM=y
+CONFIG_LEDS=y
+# CONFIG_LEDS_TIMER is not set
+CONFIG_LEDS_CPU=y
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
CONFIG_ZBOOT_ROM_TEXT=0x0
CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="console=ttySA0,9600 root=/dev/ram"
+# CONFIG_XIP_KERNEL is not set
+
+#
+# CPU Frequency scaling
+#
CONFIG_CPU_FREQ=y
-CONFIG_CPU_FREQ_SA1100=y
-# CONFIG_CPU_FREQ_PROC_INTF is not set
+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 is not set
CONFIG_CPU_FREQ_GOV_USERSPACE=y
-CONFIG_CPU_FREQ_24_API=y
-# CONFIG_HOTPLUG is not set
+# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set
+CONFIG_CPU_FREQ_SA1100=y
+
+#
+# Floating point emulation
+#
#
-# At least one math emulation must be selected
+# 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=y
# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
#
-# Generic Driver Options
+# Power management options
#
CONFIG_PM=y
-# CONFIG_PREEMPT is not set
CONFIG_APM=m
-# CONFIG_ARTHUR is not set
-CONFIG_CMDLINE="console=ttySA0,9600 root=/dev/ram"
-CONFIG_LEDS=y
-# CONFIG_LEDS_TIMER is not set
-CONFIG_LEDS_CPU=y
-CONFIG_ALIGNMENT_TRAP=y
#
-# Parallel port support
+# Device Drivers
#
-# CONFIG_PARPORT is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
#
# Memory Technology Devices (MTD)
@@ -191,8 +200,8 @@ CONFIG_ALIGNMENT_TRAP=y
CONFIG_MTD=y
CONFIG_MTD_DEBUG=y
CONFIG_MTD_DEBUG_VERBOSE=1
-CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_REDBOOT_PARTS is not set
# CONFIG_MTD_CMDLINE_PARTS is not set
# CONFIG_MTD_AFS_PARTS is not set
@@ -211,10 +220,19 @@ CONFIG_MTD_BLOCK=y
#
# CONFIG_MTD_CFI is not set
# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
# CONFIG_MTD_RAM is not set
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
#
# Mapping drivers for chip access
@@ -225,9 +243,11 @@ CONFIG_MTD_BLOCK=y
# Self-contained MTD device drivers
#
# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
CONFIG_MTD_LART=y
# CONFIG_MTD_MTDRAM is not set
# CONFIG_MTD_BLKMTD is not set
+# CONFIG_MTD_BLOCK2MTD is not set
#
# Disk-On-Chip Device Drivers
@@ -242,6 +262,11 @@ CONFIG_MTD_LART=y
# CONFIG_MTD_NAND is not set
#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
# Plug and Play support
#
# CONFIG_PNP is not set
@@ -251,11 +276,56 @@ CONFIG_MTD_LART=y
#
# CONFIG_BLK_DEV_FD is not set
# CONFIG_BLK_DEV_XD is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
# CONFIG_BLK_DEV_LOOP is not set
# CONFIG_BLK_DEV_NBD is not set
CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=m
+CONFIG_BLK_DEV_IDE=m
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=m
+# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_BLK_DEV_IDECD=m
+# 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=m
+# CONFIG_IDE_ARM is not set
+# CONFIG_IDE_CHIPSETS is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
#
# Multi-device support (RAID and LVM)
@@ -263,6 +333,18 @@ CONFIG_BLK_DEV_INITRD=y
# CONFIG_MD is not set
#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
# Networking support
#
CONFIG_NET=y
@@ -282,23 +364,24 @@ CONFIG_INET=y
# CONFIG_NET_IPIP is not set
# CONFIG_NET_IPGRE is not set
# CONFIG_ARPD is not set
-CONFIG_INET_ECN=y
CONFIG_SYN_COOKIES=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
# CONFIG_IPV6 is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
# CONFIG_NETFILTER is not set
#
# SCTP Configuration (EXPERIMENTAL)
#
-CONFIG_IPV6_SCTP__=y
# CONFIG_IP_SCTP is not set
# CONFIG_ATM is not set
+# CONFIG_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
@@ -307,88 +390,20 @@ CONFIG_IPV6_SCTP__=y
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
#
# QoS and/or fair queueing
#
# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
#
# Network testing
#
# CONFIG_NET_PKTGEN is not set
-CONFIG_NETDEVICES=y
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-CONFIG_DUMMY=m
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
-# CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_LANCE is not set
-# CONFIG_NET_VENDOR_SMC is not set
-# CONFIG_NET_VENDOR_RACAL is not set
-# CONFIG_AT1700 is not set
-# CONFIG_DEPCA is not set
-# CONFIG_HP100 is not set
-# CONFIG_NET_ISA is not set
-# CONFIG_NET_PCI is not set
-# CONFIG_NET_POCKET is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-
-#
-# Ethernet (10000 Mbit)
-#
-CONFIG_PPP=m
-# CONFIG_PPP_MULTILINK is not set
-# CONFIG_PPP_FILTER is not set
-CONFIG_PPP_ASYNC=m
-# CONFIG_PPP_SYNC_TTY is not set
-CONFIG_PPP_DEFLATE=m
-CONFIG_PPP_BSDCOMP=m
-# CONFIG_PPPOE is not set
-CONFIG_SLIP=m
-CONFIG_SLIP_COMPRESSED=y
-# CONFIG_SLIP_SMART is not set
-# CONFIG_SLIP_MODE_SLIP6 is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Token Ring devices
-#
-# CONFIG_TR is not set
-# CONFIG_SHAPER is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# Amateur Radio support
-#
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
CONFIG_IRDA=m
#
@@ -433,56 +448,79 @@ CONFIG_IRDA_DEBUG=y
#
# 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_SA1100_FIR=m
-# CONFIG_VIA_FIR is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
#
-# Bluetooth support
+# ARCnet devices
#
-# CONFIG_BT is not set
+# CONFIG_ARCNET is not set
#
-# ATA/ATAPI/MFM/RLL support
+# Ethernet (10 or 100Mbit)
#
-CONFIG_IDE=m
-CONFIG_BLK_DEV_IDE=m
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_LANCE is not set
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_SMC91X is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_AT1700 is not set
+# CONFIG_DEPCA is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_ISA is not set
+# CONFIG_NET_PCI is not set
+# CONFIG_NET_POCKET is not set
#
-# Please see Documentation/ide.txt for help/info on IDE drives
+# Ethernet (1000 Mbit)
#
-CONFIG_BLK_DEV_IDEDISK=m
-# CONFIG_IDEDISK_MULTI_MODE is not set
-# CONFIG_IDEDISK_STROKE is not set
-CONFIG_BLK_DEV_IDECD=m
-# CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
-# CONFIG_IDE_TASK_IOCTL is not set
-# CONFIG_IDE_TASKFILE_IO is not set
#
-# IDE chipset support/bugfixes
+# Ethernet (10000 Mbit)
#
-# CONFIG_IDE_CHIPSETS is not set
-# CONFIG_BLK_DEV_IDEDMA is not set
-# CONFIG_IDEDMA_AUTO is not set
-# CONFIG_BLK_DEV_HD is not set
#
-# SCSI device support
+# Token Ring devices
#
-# CONFIG_SCSI is not set
+# CONFIG_TR is not set
#
-# I2O device support
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
#
+# CONFIG_WAN is not set
+CONFIG_PPP=m
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+# CONFIG_PPP_SYNC_TTY is not set
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+# CONFIG_PPPOE is not set
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+# CONFIG_SLIP_SMART is not set
+# CONFIG_SLIP_MODE_SLIP6 is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
#
# ISDN subsystem
#
-# CONFIG_ISDN_BOOL is not set
+# CONFIG_ISDN is not set
#
# Input device support
@@ -502,35 +540,36 @@ 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=y
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-
-#
# Input Device Drivers
#
CONFIG_INPUT_KEYBOARD=y
CONFIG_KEYBOARD_ATKBD=y
# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
# CONFIG_KEYBOARD_XTKBD is not set
# CONFIG_KEYBOARD_NEWTON is not set
CONFIG_INPUT_MOUSE=y
CONFIG_MOUSE_PS2=y
-# CONFIG_MOUSE_PS2_SYNAPTICS is not set
# CONFIG_MOUSE_SERIAL is not set
# CONFIG_MOUSE_INPORT is not set
# CONFIG_MOUSE_LOGIBM is not set
# CONFIG_MOUSE_PC110PAD is not set
+# CONFIG_MOUSE_VSXXXAA is not set
# CONFIG_INPUT_JOYSTICK is not set
# CONFIG_INPUT_TOUCHSCREEN is not set
# CONFIG_INPUT_MISC is not set
#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
+#
# Character devices
#
CONFIG_VT=y
@@ -551,7 +590,33 @@ CONFIG_SERIAL_SA1100_CONSOLE=y
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
+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_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
#
# I2C support
@@ -559,57 +624,62 @@ CONFIG_UNIX98_PTY_COUNT=256
# CONFIG_I2C is not set
#
-# I2C Algorithms
+# Misc devices
#
#
-# I2C Hardware Bus support
+# Multimedia devices
#
+# CONFIG_VIDEO_DEV is not set
#
-# I2C Hardware Sensors Chip support
+# Digital Video Broadcasting Devices
#
-# CONFIG_I2C_SENSOR is not set
+# CONFIG_DVB is not set
#
-# Mice
+# Graphics support
#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_QIC02_TAPE is not set
+# CONFIG_FB is not set
#
-# IPMI
+# Console display driver support
#
-# CONFIG_IPMI_HANDLER is not set
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
#
-# Watchdog Cards
+# Sound
#
-# CONFIG_WATCHDOG is not set
-# CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
+CONFIG_SOUND=m
#
-# Ftape, the floppy tape device driver
+# Advanced Linux Sound Architecture
#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
+# CONFIG_SND is not set
#
-# Multimedia devices
+# Open Sound System
#
-# CONFIG_VIDEO_DEV is not set
+# CONFIG_SOUND_PRIME is not set
#
-# Digital Video Broadcasting Devices
+# USB support
#
-# CONFIG_DVB is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
#
# File systems
@@ -626,11 +696,17 @@ CONFIG_FS_MBCACHE=y
CONFIG_REISERFS_FS=m
# CONFIG_REISERFS_CHECK is not set
# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_REISERFS_FS_XATTR is not set
# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
# CONFIG_XFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
@@ -641,21 +717,24 @@ CONFIG_ISO9660_FS=m
CONFIG_JOLIET=y
# CONFIG_ZISOFS is not set
CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
#
# DOS/FAT/NT Filesystems
#
-# CONFIG_FAT_FS is not set
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
# CONFIG_NTFS_FS is not set
#
# Pseudo filesystems
#
CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS=y
# CONFIG_DEVPTS_FS_XATTR is not set
CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
@@ -665,6 +744,7 @@ CONFIG_RAMFS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
# CONFIG_BEFS_FS is not set
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
@@ -672,6 +752,11 @@ CONFIG_RAMFS=y
CONFIG_JFFS2_FS=m
CONFIG_JFFS2_FS_DEBUG=1
# CONFIG_JFFS2_FS_NAND is not set
+# CONFIG_JFFS2_FS_NOR_ECC is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
CONFIG_CRAMFS=m
# CONFIG_VXFS_FS is not set
# CONFIG_HPFS_FS is not set
@@ -685,6 +770,7 @@ CONFIG_CRAMFS=m
CONFIG_NFS_FS=m
CONFIG_NFS_V3=y
# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
CONFIG_NFSD=m
CONFIG_NFSD_V3=y
# CONFIG_NFSD_V4 is not set
@@ -693,23 +779,24 @@ CONFIG_LOCKD=m
CONFIG_LOCKD_V4=y
CONFIG_EXPORTFS=m
CONFIG_SUNRPC=m
-# CONFIG_SUNRPC_GSS is not set
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
# CONFIG_CIFS is not set
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
# CONFIG_AFS_FS is not set
#
# Partition Types
#
# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_NLS=y
+CONFIG_MSDOS_PARTITION=y
#
# Native Language Support
#
+CONFIG_NLS=y
CONFIG_NLS_DEFAULT="iso8859-1"
CONFIG_NLS_CODEPAGE_437=m
# CONFIG_NLS_CODEPAGE_737 is not set
@@ -734,6 +821,7 @@ CONFIG_NLS_CODEPAGE_850=m
# CONFIG_NLS_ISO8859_8 is not set
# CONFIG_NLS_CODEPAGE_1250 is not set
# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
CONFIG_NLS_ISO8859_1=m
# CONFIG_NLS_ISO8859_2 is not set
# CONFIG_NLS_ISO8859_3 is not set
@@ -750,52 +838,24 @@ CONFIG_NLS_ISO8859_15=m
CONFIG_NLS_UTF8=m
#
-# Graphics support
-#
-# CONFIG_FB is not set
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_MDA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-
-#
-# Sound
+# Profiling support
#
-CONFIG_SOUND=m
-
-#
-# Advanced Linux Sound Architecture
-#
-# CONFIG_SND is not set
-
-#
-# Open Sound System
-#
-# CONFIG_SOUND_PRIME is not set
-
-#
-# Misc devices
-#
-
-#
-# USB support
-#
-# CONFIG_USB_GADGET is not set
+# 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_DEBUG_BUGVERBOSE=y
CONFIG_FRAME_POINTER=y
CONFIG_DEBUG_USER=y
-# CONFIG_DEBUG_INFO is not set
-# CONFIG_DEBUG_KERNEL is not set
#
# Security options
#
+# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
#
@@ -804,8 +864,14 @@ CONFIG_DEBUG_USER=y
# CONFIG_CRYPTO is not set
#
+# Hardware crypto devices
+#
+
+#
# Library routines
#
+CONFIG_CRC_CCITT=m
CONFIG_CRC32=m
+# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=m
CONFIG_ZLIB_DEFLATE=m
diff --git a/arch/arm/configs/lpd7a400_defconfig b/arch/arm/configs/lpd7a400_defconfig
index 89936684e715d..d64706d3ff359 100644
--- a/arch/arm/configs/lpd7a400_defconfig
+++ b/arch/arm/configs/lpd7a400_defconfig
@@ -1,42 +1,52 @@
#
# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.12-rc1-bk2
+# Mon Mar 28 00:06:33 2005
#
CONFIG_ARM=y
CONFIG_MMU=y
CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_IOMAP=y
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
CONFIG_CLEAN_COMPILE=y
-CONFIG_STANDALONE=y
CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
#
# General setup
#
+CONFIG_LOCALVERSION=""
# CONFIG_SWAP is not set
CONFIG_SYSVIPC=y
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
CONFIG_IKCONFIG=y
# CONFIG_IKCONFIG_PROC is not set
CONFIG_EMBEDDED=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
# CONFIG_EPOLL is not set
-CONFIG_IOSCHED_NOOP=y
-# CONFIG_IOSCHED_AS is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-CONFIG_IOSCHED_CFQ=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
#
# Loadable module support
@@ -46,7 +56,6 @@ CONFIG_CC_OPTIMIZE_FOR_SIZE=y
#
# System Type
#
-# CONFIG_ARCH_ADIFCC is not set
# CONFIG_ARCH_CLPS7500 is not set
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
@@ -56,6 +65,7 @@ CONFIG_CC_OPTIMIZE_FOR_SIZE=y
# 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
@@ -64,69 +74,9 @@ CONFIG_CC_OPTIMIZE_FOR_SIZE=y
# CONFIG_ARCH_SHARK is not set
CONFIG_ARCH_LH7A40X=y
# CONFIG_ARCH_OMAP is not set
-# CONFIG_ARCH_VERSATILE_PB is not set
-
-#
-# CLPS711X/EP721X Implementations
-#
-
-#
-# Epxa10db
-#
-
-#
-# Footbridge Implementations
-#
-
-#
-# IOP3xx Implementation Options
-#
-# CONFIG_ARCH_IOP310 is not set
-# CONFIG_ARCH_IOP321 is not set
-
-#
-# IOP3xx Chipset Features
-#
-
-#
-# Intel IXP4xx Implementation Options
-#
-
-#
-# IXP4xx Platforms
-#
-
-#
-# IXP4xx Options
-#
-
-#
-# Intel PXA2xx Implementations
-#
-
-#
-# SA11x0 Implementations
-#
-
-#
-# TI OMAP Implementations
-#
-
-#
-# OMAP Core Type
-#
-
-#
-# OMAP Board Type
-#
-
-#
-# OMAP Feature Selections
-#
-
-#
-# S3C2410 Implementations
-#
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_H720X is not set
#
# LH7A40X Implementations
@@ -135,6 +85,8 @@ CONFIG_ARCH_LH7A40X=y
CONFIG_MACH_LPD7A400=y
# CONFIG_MACH_LPD7A404 is not set
CONFIG_ARCH_LH7A400=y
+# CONFIG_LH7A40X_CONTIGMEM is not set
+# CONFIG_LH7A40X_ONE_BANK_PER_NODE is not set
#
# Processor Type
@@ -144,6 +96,7 @@ 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
@@ -156,46 +109,72 @@ CONFIG_ARM_THUMB=y
# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
#
-# General setup
+# Bus support
#
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_PREEMPT=y
CONFIG_DISCONTIGMEM=y
-CONFIG_FIQ=y
-# CONFIG_ZBOOT_ROM is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
CONFIG_ZBOOT_ROM_TEXT=0x0
CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE=""
+# CONFIG_XIP_KERNEL is not set
+
+#
+# Floating point emulation
+#
#
-# At least one math emulation must be selected
+# 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
#
-# Generic Driver Options
+# Power management options
#
-# CONFIG_DEBUG_DRIVER is not set
# CONFIG_PM is not set
-CONFIG_PREEMPT=y
-# CONFIG_ARTHUR is not set
-CONFIG_CMDLINE=""
-CONFIG_ALIGNMENT_TRAP=y
#
-# Parallel port support
+# Device Drivers
#
-# CONFIG_PARPORT is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
#
# Memory Technology Devices (MTD)
#
CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
-CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_REDBOOT_PARTS is not set
# CONFIG_MTD_CMDLINE_PARTS is not set
# CONFIG_MTD_AFS_PARTS is not set
@@ -216,13 +195,24 @@ CONFIG_MTD_CFI=y
# CONFIG_MTD_JEDECPROBE is not set
CONFIG_MTD_GEN_PROBE=y
# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
CONFIG_MTD_CFI_INTELEXT=y
# CONFIG_MTD_CFI_AMDSTD is not set
# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
+# CONFIG_MTD_XIP is not set
#
# Mapping drivers for chip access
@@ -230,15 +220,16 @@ CONFIG_MTD_CFI_INTELEXT=y
# CONFIG_MTD_COMPLEX_MAPPINGS is not set
# CONFIG_MTD_PHYSMAP is not set
# CONFIG_MTD_ARM_INTEGRATOR is not set
-CONFIG_MTD_LPD7A40X=y
# CONFIG_MTD_EDB7312 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
@@ -253,6 +244,11 @@ CONFIG_MTD_LPD7A40X=y
# CONFIG_MTD_NAND is not set
#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
# Plug and Play support
#
@@ -260,10 +256,54 @@ CONFIG_MTD_LPD7A40X=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_RAM is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+# CONFIG_IDE_ARM is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
#
# Multi-device support (RAID and LVM)
@@ -271,6 +311,18 @@ CONFIG_BLK_DEV_LOOP=y
# CONFIG_MD is not set
#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
# Networking support
#
CONFIG_NET=y
@@ -297,6 +349,9 @@ CONFIG_IP_PNP_RARP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_IP_TCPDIAG is not set
+# CONFIG_IP_TCPDIAG_IPV6 is not set
# CONFIG_IPV6 is not set
# CONFIG_NETFILTER is not set
@@ -316,12 +371,12 @@ CONFIG_IP_PNP_RARP=y
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
#
# QoS and/or fair queueing
#
# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
#
# Network testing
@@ -372,52 +427,6 @@ CONFIG_SMC91X=y
# CONFIG_NETCONSOLE is not set
#
-# ATA/ATAPI/MFM/RLL support
-#
-CONFIG_IDE=y
-CONFIG_BLK_DEV_IDE=y
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
-CONFIG_BLK_DEV_IDEDISK=y
-# CONFIG_IDEDISK_MULTI_MODE is not set
-# CONFIG_IDEDISK_STROKE is not set
-# CONFIG_BLK_DEV_IDECD is not set
-# CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
-# CONFIG_IDE_TASK_IOCTL is not set
-# CONFIG_IDE_TASKFILE_IO is not set
-CONFIG_IDE_POLL=y
-
-#
-# IDE chipset support/bugfixes
-#
-CONFIG_IDE_GENERIC=y
-CONFIG_IDE_ARM=y
-# CONFIG_BLK_DEV_IDEDMA is not set
-# CONFIG_IDEDMA_AUTO is not set
-# CONFIG_BLK_DEV_HD is not set
-
-#
-# SCSI device support
-#
-# CONFIG_SCSI is not set
-
-#
-# Fusion MPT device support
-#
-
-#
-# IEEE 1394 (FireWire) support
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-
-#
# ISDN subsystem
#
# CONFIG_ISDN is not set
@@ -440,14 +449,6 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
# CONFIG_INPUT_EVBUG is not set
#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-# CONFIG_SERIO is not set
-# CONFIG_SERIO_I8042 is not set
-
-#
# Input Device Drivers
#
# CONFIG_INPUT_KEYBOARD is not set
@@ -457,6 +458,13 @@ CONFIG_SOUND_GAMEPORT=y
# CONFIG_INPUT_MISC is not set
#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
+#
# Character devices
#
CONFIG_VT=y
@@ -479,7 +487,6 @@ CONFIG_SERIAL_LH7A40X_CONSOLE=y
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
-# CONFIG_QIC02_TAPE is not set
#
# IPMI
@@ -494,22 +501,28 @@ CONFIG_LEGACY_PTY_COUNT=256
CONFIG_RTC=y
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
#
# Ftape, the floppy tape device driver
#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
# CONFIG_DRM is not set
# CONFIG_RAW_DRIVER is not set
#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
# I2C support
#
# CONFIG_I2C is not set
#
+# Misc devices
+#
+
+#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -520,6 +533,39 @@ CONFIG_RTC=y
# 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 is not set
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -533,10 +579,15 @@ CONFIG_JBD=y
CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
# CONFIG_XFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
@@ -552,6 +603,8 @@ CONFIG_FS_MBCACHE=y
CONFIG_FAT_FS=y
# CONFIG_MSDOS_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
#
@@ -562,6 +615,7 @@ CONFIG_SYSFS=y
# CONFIG_DEVFS_FS is not set
# CONFIG_DEVPTS_FS_XATTR is not set
CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
@@ -579,6 +633,11 @@ CONFIG_RAMFS=y
CONFIG_JFFS2_FS=y
CONFIG_JFFS2_FS_DEBUG=0
# CONFIG_JFFS2_FS_NAND is not set
+# CONFIG_JFFS2_FS_NOR_ECC is not set
+# CONFIG_JFFS2_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
@@ -597,9 +656,9 @@ CONFIG_NFS_V3=y
CONFIG_ROOT_NFS=y
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
-# CONFIG_EXPORTFS is not set
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
@@ -621,7 +680,6 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_SOLARIS_X86_PARTITION is not set
# CONFIG_UNIXWARE_DISKLABEL is not set
# CONFIG_LDM_PARTITION is not set
-# CONFIG_NEC98_PARTITION is not set
# CONFIG_SGI_PARTITION is not set
# CONFIG_ULTRIX_PARTITION is not set
# CONFIG_SUN_PARTITION is not set
@@ -655,6 +713,7 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_NLS_ISO8859_8 is not set
# CONFIG_NLS_CODEPAGE_1250 is not set
# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
# CONFIG_NLS_ISO8859_1 is not set
# CONFIG_NLS_ISO8859_2 is not set
# CONFIG_NLS_ISO8859_3 is not set
@@ -676,53 +735,31 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_PROFILING is not set
#
-# Graphics support
-#
-# CONFIG_FB is not set
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_MDA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# Misc devices
-#
-
-#
-# USB support
-#
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
# Kernel hacking
#
-CONFIG_FRAME_POINTER=y
-CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_INFO=y
+# CONFIG_PRINTK_TIME is not set
CONFIG_DEBUG_KERNEL=y
-# CONFIG_DEBUG_SLAB is not set
CONFIG_MAGIC_SYSRQ=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_DEBUG_PREEMPT=y
# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_WAITQ is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_FS is not set
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_WAITQ is not set
CONFIG_DEBUG_ERRORS=y
# CONFIG_DEBUG_LL is not set
#
# Security options
#
+# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
#
@@ -731,8 +768,13 @@ CONFIG_DEBUG_ERRORS=y
# CONFIG_CRYPTO is not set
#
+# Hardware crypto devices
+#
+
+#
# Library routines
#
+# CONFIG_CRC_CCITT is not set
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=y
diff --git a/arch/arm/configs/lpd7a404_defconfig b/arch/arm/configs/lpd7a404_defconfig
index 23de2aaaa56c6..87cbedfb303f5 100644
--- a/arch/arm/configs/lpd7a404_defconfig
+++ b/arch/arm/configs/lpd7a404_defconfig
@@ -1,42 +1,52 @@
#
# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.12-rc1-bk2
+# Mon Mar 28 00:14:08 2005
#
CONFIG_ARM=y
CONFIG_MMU=y
CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_IOMAP=y
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
CONFIG_CLEAN_COMPILE=y
-CONFIG_STANDALONE=y
CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
#
# General setup
#
+CONFIG_LOCALVERSION=""
# CONFIG_SWAP is not set
CONFIG_SYSVIPC=y
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
CONFIG_IKCONFIG=y
# CONFIG_IKCONFIG_PROC is not set
CONFIG_EMBEDDED=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
# CONFIG_EPOLL is not set
-CONFIG_IOSCHED_NOOP=y
-# CONFIG_IOSCHED_AS is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-CONFIG_IOSCHED_CFQ=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
#
# Loadable module support
@@ -46,7 +56,6 @@ CONFIG_CC_OPTIMIZE_FOR_SIZE=y
#
# System Type
#
-# CONFIG_ARCH_ADIFCC is not set
# CONFIG_ARCH_CLPS7500 is not set
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
@@ -56,6 +65,7 @@ CONFIG_CC_OPTIMIZE_FOR_SIZE=y
# 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
@@ -64,69 +74,9 @@ CONFIG_CC_OPTIMIZE_FOR_SIZE=y
# CONFIG_ARCH_SHARK is not set
CONFIG_ARCH_LH7A40X=y
# CONFIG_ARCH_OMAP is not set
-# CONFIG_ARCH_VERSATILE_PB is not set
-
-#
-# CLPS711X/EP721X Implementations
-#
-
-#
-# Epxa10db
-#
-
-#
-# Footbridge Implementations
-#
-
-#
-# IOP3xx Implementation Options
-#
-# CONFIG_ARCH_IOP310 is not set
-# CONFIG_ARCH_IOP321 is not set
-
-#
-# IOP3xx Chipset Features
-#
-
-#
-# Intel IXP4xx Implementation Options
-#
-
-#
-# IXP4xx Platforms
-#
-
-#
-# IXP4xx Options
-#
-
-#
-# Intel PXA2xx Implementations
-#
-
-#
-# SA11x0 Implementations
-#
-
-#
-# TI OMAP Implementations
-#
-
-#
-# OMAP Core Type
-#
-
-#
-# OMAP Board Type
-#
-
-#
-# OMAP Feature Selections
-#
-
-#
-# S3C2410 Implementations
-#
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_H720X is not set
#
# LH7A40X Implementations
@@ -135,6 +85,8 @@ CONFIG_ARCH_LH7A40X=y
# CONFIG_MACH_LPD7A400 is not set
CONFIG_MACH_LPD7A404=y
CONFIG_ARCH_LH7A404=y
+# CONFIG_LH7A40X_CONTIGMEM is not set
+# CONFIG_LH7A40X_ONE_BANK_PER_NODE is not set
#
# Processor Type
@@ -144,6 +96,7 @@ 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
@@ -156,45 +109,72 @@ CONFIG_ARM_THUMB=y
# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
#
-# General setup
+# Bus support
+#
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
#
+CONFIG_PREEMPT=y
CONFIG_DISCONTIGMEM=y
-# CONFIG_ZBOOT_ROM is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
CONFIG_ZBOOT_ROM_TEXT=0x0
CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE=""
+# CONFIG_XIP_KERNEL is not set
#
-# At least one math emulation must be selected
+# 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
#
-# Generic Driver Options
+# Power management options
#
-# CONFIG_DEBUG_DRIVER is not set
# CONFIG_PM is not set
-CONFIG_PREEMPT=y
-# CONFIG_ARTHUR is not set
-CONFIG_CMDLINE=""
-CONFIG_ALIGNMENT_TRAP=y
#
-# Parallel port support
+# Device Drivers
#
-# CONFIG_PARPORT is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
#
# Memory Technology Devices (MTD)
#
CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
-CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_REDBOOT_PARTS is not set
# CONFIG_MTD_CMDLINE_PARTS is not set
# CONFIG_MTD_AFS_PARTS is not set
@@ -215,13 +195,24 @@ CONFIG_MTD_CFI=y
# CONFIG_MTD_JEDECPROBE is not set
CONFIG_MTD_GEN_PROBE=y
# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
CONFIG_MTD_CFI_INTELEXT=y
# CONFIG_MTD_CFI_AMDSTD is not set
# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
+# CONFIG_MTD_XIP is not set
#
# Mapping drivers for chip access
@@ -229,15 +220,16 @@ CONFIG_MTD_CFI_INTELEXT=y
# CONFIG_MTD_COMPLEX_MAPPINGS is not set
# CONFIG_MTD_PHYSMAP is not set
# CONFIG_MTD_ARM_INTEGRATOR is not set
-CONFIG_MTD_LPD7A40X=y
# CONFIG_MTD_EDB7312 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
@@ -252,6 +244,11 @@ CONFIG_MTD_LPD7A40X=y
# CONFIG_MTD_NAND is not set
#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
# Plug and Play support
#
@@ -259,10 +256,86 @@ CONFIG_MTD_LPD7A40X=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_UB is not set
# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+# CONFIG_IDE_ARM is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=y
+# CONFIG_SCSI_PROC_FS is not set
+
+#
+# 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
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_DEBUG is not set
#
# Multi-device support (RAID and LVM)
@@ -270,6 +343,18 @@ CONFIG_BLK_DEV_LOOP=y
# CONFIG_MD is not set
#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
# Networking support
#
CONFIG_NET=y
@@ -296,6 +381,9 @@ CONFIG_IP_PNP_RARP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_IP_TCPDIAG is not set
+# CONFIG_IP_TCPDIAG_IPV6 is not set
# CONFIG_IPV6 is not set
# CONFIG_NETFILTER is not set
@@ -315,12 +403,12 @@ CONFIG_IP_PNP_RARP=y
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
#
# QoS and/or fair queueing
#
# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
#
# Network testing
@@ -371,85 +459,6 @@ CONFIG_SMC91X=y
# CONFIG_NETCONSOLE is not set
#
-# ATA/ATAPI/MFM/RLL support
-#
-CONFIG_IDE=y
-CONFIG_BLK_DEV_IDE=y
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
-CONFIG_BLK_DEV_IDEDISK=y
-# CONFIG_IDEDISK_MULTI_MODE is not set
-# CONFIG_IDEDISK_STROKE is not set
-# CONFIG_BLK_DEV_IDECD is not set
-# CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
-# CONFIG_BLK_DEV_IDESCSI is not set
-# CONFIG_IDE_TASK_IOCTL is not set
-# CONFIG_IDE_TASKFILE_IO is not set
-CONFIG_IDE_POLL=y
-
-#
-# IDE chipset support/bugfixes
-#
-CONFIG_IDE_GENERIC=y
-CONFIG_IDE_ARM=y
-# CONFIG_BLK_DEV_IDEDMA is not set
-# CONFIG_IDEDMA_AUTO is not set
-# CONFIG_BLK_DEV_HD is not set
-
-#
-# SCSI device support
-#
-CONFIG_SCSI=y
-# CONFIG_SCSI_PROC_FS is not set
-
-#
-# 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
-
-#
-# 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
-
-#
-# SCSI low-level drivers
-#
-# CONFIG_SCSI_AIC7XXX_OLD is not set
-# CONFIG_SCSI_DPT_I2O is not set
-# CONFIG_SCSI_SATA is not set
-# CONFIG_SCSI_EATA_PIO is not set
-# CONFIG_SCSI_DEBUG is not set
-
-#
-# Fusion MPT device support
-#
-
-#
-# IEEE 1394 (FireWire) support
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-
-#
# ISDN subsystem
#
# CONFIG_ISDN is not set
@@ -469,14 +478,6 @@ CONFIG_INPUT=y
# CONFIG_INPUT_EVBUG is not set
#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-# CONFIG_SERIO is not set
-# CONFIG_SERIO_I8042 is not set
-
-#
# Input Device Drivers
#
# CONFIG_INPUT_KEYBOARD is not set
@@ -486,6 +487,13 @@ CONFIG_SOUND_GAMEPORT=y
# CONFIG_INPUT_MISC is not set
#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
+#
# Character devices
#
CONFIG_VT=y
@@ -508,7 +516,6 @@ CONFIG_SERIAL_LH7A40X_CONSOLE=y
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
-# CONFIG_QIC02_TAPE is not set
#
# IPMI
@@ -523,22 +530,28 @@ CONFIG_LEGACY_PTY_COUNT=256
CONFIG_RTC=y
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
#
# Ftape, the floppy tape device driver
#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
# CONFIG_DRM is not set
# CONFIG_RAW_DRIVER is not set
#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
# I2C support
#
# CONFIG_I2C is not set
#
+# Misc devices
+#
+
+#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -549,6 +562,148 @@ CONFIG_RTC=y
# 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 is not set
+
+#
+# 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_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_BLUETOOTH_TTY is not set
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+CONFIG_USB_STORAGE_DEBUG=y
+# CONFIG_USB_STORAGE_RW_DETECT is not set
+CONFIG_USB_STORAGE_DATAFAB=y
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=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_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB Multimedia devices
+#
+# CONFIG_USB_DABUSB is not set
+
+#
+# Video4Linux support is needed for USB Multimedia device support
+#
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS 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_TEST is not set
+
+#
+# USB ATM/DSL drivers
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -562,10 +717,15 @@ CONFIG_JBD=y
CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
# CONFIG_XFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
@@ -581,6 +741,8 @@ CONFIG_FS_MBCACHE=y
CONFIG_FAT_FS=y
# CONFIG_MSDOS_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
#
@@ -591,6 +753,7 @@ CONFIG_SYSFS=y
# CONFIG_DEVFS_FS is not set
# CONFIG_DEVPTS_FS_XATTR is not set
CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
@@ -608,6 +771,11 @@ CONFIG_RAMFS=y
CONFIG_JFFS2_FS=y
CONFIG_JFFS2_FS_DEBUG=0
# CONFIG_JFFS2_FS_NAND is not set
+# CONFIG_JFFS2_FS_NOR_ECC is not set
+# CONFIG_JFFS2_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
@@ -626,9 +794,9 @@ CONFIG_NFS_V3=y
CONFIG_ROOT_NFS=y
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
-# CONFIG_EXPORTFS is not set
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
@@ -650,7 +818,6 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_SOLARIS_X86_PARTITION is not set
# CONFIG_UNIXWARE_DISKLABEL is not set
# CONFIG_LDM_PARTITION is not set
-# CONFIG_NEC98_PARTITION is not set
# CONFIG_SGI_PARTITION is not set
# CONFIG_ULTRIX_PARTITION is not set
# CONFIG_SUN_PARTITION is not set
@@ -684,6 +851,7 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_NLS_ISO8859_8 is not set
# CONFIG_NLS_CODEPAGE_1250 is not set
# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
# CONFIG_NLS_ISO8859_1 is not set
# CONFIG_NLS_ISO8859_2 is not set
# CONFIG_NLS_ISO8859_3 is not set
@@ -705,152 +873,31 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_PROFILING is not set
#
-# Graphics support
-#
-# CONFIG_FB is not set
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_MDA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# Misc devices
-#
-
-#
-# USB support
-#
-CONFIG_USB=y
-# CONFIG_USB_DEBUG is not set
-
-#
-# Miscellaneous USB options
-#
-CONFIG_USB_DEVICEFS=y
-# CONFIG_USB_BANDWIDTH is not set
-# CONFIG_USB_DYNAMIC_MINORS is not set
-
-#
-# USB Host Controller Drivers
-#
-# CONFIG_USB_EHCI_HCD is not set
-CONFIG_USB_OHCI_HCD=y
-# CONFIG_USB_UHCI_HCD is not set
-# CONFIG_USB_SL811HS is not set
-
-#
-# USB Device Class drivers
-#
-# CONFIG_USB_BLUETOOTH_TTY is not set
-# CONFIG_USB_ACM is not set
-# CONFIG_USB_PRINTER is not set
-CONFIG_USB_STORAGE=y
-CONFIG_USB_STORAGE_DEBUG=y
-CONFIG_USB_STORAGE_DATAFAB=y
-# CONFIG_USB_STORAGE_FREECOM is not set
-# CONFIG_USB_STORAGE_ISD200 is not set
-# CONFIG_USB_STORAGE_DPCM is not set
-# CONFIG_USB_STORAGE_HP8200e is not set
-# CONFIG_USB_STORAGE_SDDR09 is not set
-# CONFIG_USB_STORAGE_SDDR55 is not set
-# CONFIG_USB_STORAGE_JUMPSHOT is not set
-
-#
-# USB Human Interface Devices (HID)
-#
-CONFIG_USB_HID=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_KBTAB is not set
-# CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_MTOUCH is not set
-# CONFIG_USB_EGALAX is not set
-# CONFIG_USB_XPAD is not set
-# CONFIG_USB_ATI_REMOTE is not set
-
-#
-# USB Imaging devices
-#
-# CONFIG_USB_MDC800 is not set
-# CONFIG_USB_MICROTEK is not set
-# CONFIG_USB_HPUSBSCSI is not set
-
-#
-# USB Multimedia devices
-#
-# CONFIG_USB_DABUSB is not set
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
-#
-# USB Network adaptors
-#
-# CONFIG_USB_CATC is not set
-# CONFIG_USB_KAWETH is not set
-# CONFIG_USB_PEGASUS is not set
-# CONFIG_USB_RTL8150 is not set
-# CONFIG_USB_USBNET is not set
-
-#
-# USB port drivers
-#
-
-#
-# 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_TIGL 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_PHIDGETSERVO is not set
-# CONFIG_USB_TEST is not set
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
# Kernel hacking
#
-CONFIG_FRAME_POINTER=y
-CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_INFO=y
+# CONFIG_PRINTK_TIME is not set
CONFIG_DEBUG_KERNEL=y
-# CONFIG_DEBUG_SLAB is not set
CONFIG_MAGIC_SYSRQ=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_DEBUG_PREEMPT=y
# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_WAITQ is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_FS is not set
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_WAITQ is not set
CONFIG_DEBUG_ERRORS=y
# CONFIG_DEBUG_LL is not set
#
# Security options
#
+# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
#
@@ -859,8 +906,13 @@ CONFIG_DEBUG_ERRORS=y
# CONFIG_CRYPTO is not set
#
+# Hardware crypto devices
+#
+
+#
# Library routines
#
+# CONFIG_CRC_CCITT is not set
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=y
diff --git a/arch/arm/configs/lubbock_defconfig b/arch/arm/configs/lubbock_defconfig
index b49f4043839e3..4bc8717c6f579 100644
--- a/arch/arm/configs/lubbock_defconfig
+++ b/arch/arm/configs/lubbock_defconfig
@@ -1,40 +1,50 @@
#
# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.12-rc1-bk2
+# Mon Mar 28 00:18:13 2005
#
CONFIG_ARM=y
CONFIG_MMU=y
CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_IOMAP=y
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
CONFIG_CLEAN_COMPILE=y
-CONFIG_STANDALONE=y
CONFIG_BROKEN_ON_SMP=y
#
# General setup
#
+CONFIG_LOCALVERSION=""
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
# CONFIG_IKCONFIG 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_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=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
@@ -43,50 +53,33 @@ CONFIG_MODULES=y
# CONFIG_MODULE_UNLOAD is not set
CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
# CONFIG_KMOD is not set
#
# System Type
#
-# CONFIG_ARCH_ADIFCC is not set
# CONFIG_ARCH_CLPS7500 is not set
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
-CONFIG_ARCH_PXA=y
# 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=y
# CONFIG_ARCH_RPC is not set
# CONFIG_ARCH_SA1100 is not set
-# CONFIG_ARCH_SHARK 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_PB is not set
-
-#
-# CLPS711X/EP721X Implementations
-#
-
-#
-# Epxa10db
-#
-
-#
-# Footbridge Implementations
-#
-
-#
-# IOP3xx Implementation Options
-#
-# CONFIG_ARCH_IOP310 is not set
-# CONFIG_ARCH_IOP321 is not set
-
-#
-# IOP3xx Chipset Features
-#
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_H720X is not set
#
# Intel PXA2xx Implementations
@@ -94,95 +87,110 @@ CONFIG_ARCH_PXA=y
CONFIG_ARCH_LUBBOCK=y
# CONFIG_MACH_MAINSTONE is not set
# CONFIG_ARCH_PXA_IDP is not set
+# CONFIG_PXA_SHARPSL is not set
CONFIG_PXA25x=y
#
-# SA11x0 Implementations
+# Processor Type
#
+CONFIG_CPU_32=y
+CONFIG_CPU_XSCALE=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5T=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_MINICACHE=y
#
-# TI OMAP Implementations
+# Processor Features
#
+# CONFIG_ARM_THUMB is not set
+CONFIG_XSCALE_PMU=y
+CONFIG_SA1111=y
+CONFIG_DMABOUNCE=y
+CONFIG_FORCE_MAX_ZONEORDER=9
#
-# OMAP Feature Selections
+# Bus support
#
#
-# S3C2410 Implementations
+# PCCARD (PCMCIA/CardBus) support
#
-CONFIG_SA1111=y
-CONFIG_FORCE_MAX_ZONEORDER=9
-CONFIG_DMABOUNCE=y
+CONFIG_PCCARD=y
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=y
#
-# Processor Type
+# PC-card bridges
#
-CONFIG_CPU_32=y
-CONFIG_CPU_XSCALE=y
-CONFIG_CPU_32v5=y
-CONFIG_CPU_ABRT_EV5T=y
-CONFIG_CPU_TLB_V4WBI=y
-CONFIG_CPU_MINICACHE=y
+# CONFIG_TCIC is not set
+CONFIG_PCMCIA_PXA2XX=y
#
-# Processor Features
+# Kernel Features
#
-# CONFIG_ARM_THUMB is not set
-CONFIG_XSCALE_PMU=y
+# CONFIG_PREEMPT is not set
+CONFIG_LEDS=y
+CONFIG_LEDS_TIMER=y
+CONFIG_LEDS_CPU=y
+CONFIG_ALIGNMENT_TRAP=y
#
-# General setup
+# Boot options
#
-# CONFIG_ZBOOT_ROM is not set
CONFIG_ZBOOT_ROM_TEXT=0x0
CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="root=/dev/nfs ip=bootp console=ttyS0,115200 mem=64M"
+# CONFIG_XIP_KERNEL is not set
#
-# PCMCIA/CardBus support
+# Floating point emulation
#
-CONFIG_PCMCIA=y
-# CONFIG_PCMCIA_DEBUG is not set
-# CONFIG_TCIC is not set
-CONFIG_PCMCIA_PXA2XX=y
#
-# At least one math emulation must be selected
+# 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
#
-# Generic Driver Options
+# Power management options
#
-# CONFIG_FW_LOADER is not set
-# CONFIG_DEBUG_DRIVER is not set
# CONFIG_PM is not set
-# CONFIG_PREEMPT is not set
-# CONFIG_ARTHUR is not set
-CONFIG_CMDLINE="root=/dev/nfs ip=bootp console=ttyS0,115200 mem=64M"
-CONFIG_LEDS=y
-CONFIG_LEDS_TIMER=y
-CONFIG_LEDS_CPU=y
-CONFIG_ALIGNMENT_TRAP=y
#
-# Parallel port support
+# Device Drivers
#
-# CONFIG_PARPORT is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
#
# Memory Technology Devices (MTD)
#
CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
-CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
CONFIG_MTD_REDBOOT_PARTS=y
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
+# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
# CONFIG_MTD_CMDLINE_PARTS is not set
# CONFIG_MTD_AFS_PARTS is not set
@@ -206,10 +214,12 @@ CONFIG_MTD_CFI_NOSWAP=y
# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
CONFIG_MTD_CFI_GEOMETRY=y
-# CONFIG_MTD_CFI_B1 is not set
-# CONFIG_MTD_CFI_B2 is not set
-CONFIG_MTD_CFI_B4=y
-# CONFIG_MTD_CFI_B8 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 is not set
CONFIG_MTD_CFI_I2=y
# CONFIG_MTD_CFI_I4 is not set
@@ -217,10 +227,11 @@ CONFIG_MTD_CFI_I2=y
CONFIG_MTD_CFI_INTELEXT=y
# CONFIG_MTD_CFI_AMDSTD is not set
# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
+# CONFIG_MTD_XIP is not set
#
# Mapping drivers for chip access
@@ -230,13 +241,16 @@ CONFIG_MTD_CFI_INTELEXT=y
CONFIG_MTD_LUBBOCK=y
# CONFIG_MTD_ARM_INTEGRATOR is not set
# CONFIG_MTD_EDB7312 is not set
+# CONFIG_MTD_SHARP_SL 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
@@ -251,6 +265,11 @@ CONFIG_MTD_LUBBOCK=y
# CONFIG_MTD_NAND is not set
#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
# Plug and Play support
#
@@ -258,9 +277,32 @@ CONFIG_MTD_LUBBOCK=y
# Block devices
#
# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
# CONFIG_BLK_DEV_LOOP is not set
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
#
# Multi-device support (RAID and LVM)
@@ -268,6 +310,18 @@ CONFIG_MTD_LUBBOCK=y
# CONFIG_MD is not set
#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
# Networking support
#
CONFIG_NET=y
@@ -293,6 +347,9 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL 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
@@ -312,12 +369,12 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
#
# QoS and/or fair queueing
#
# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
#
# Network testing
@@ -381,29 +438,6 @@ CONFIG_PCMCIA_PCNET=y
# CONFIG_NETCONSOLE is not set
#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-# CONFIG_SCSI is not set
-
-#
-# Fusion MPT device support
-#
-
-#
-# IEEE 1394 (FireWire) support
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-
-#
# ISDN subsystem
#
# CONFIG_ISDN is not set
@@ -426,17 +460,6 @@ CONFIG_INPUT_EVDEV=y
# CONFIG_INPUT_EVBUG is not set
#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-# CONFIG_SERIO_SERPORT is not set
-# CONFIG_SERIO_CT82C710 is not set
-CONFIG_SERIO_SA1111=y
-
-#
# Input Device Drivers
#
CONFIG_INPUT_KEYBOARD=y
@@ -454,6 +477,17 @@ CONFIG_MOUSE_PS2=y
# CONFIG_INPUT_MISC is not set
#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIO_SA1111=y
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
+#
# Character devices
#
CONFIG_VT=y
@@ -476,7 +510,6 @@ CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
-# CONFIG_QIC02_TAPE is not set
#
# IPMI
@@ -489,16 +522,12 @@ CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_WATCHDOG is not set
# CONFIG_NVRAM is not set
# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
#
# Ftape, the floppy tape device driver
#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
# CONFIG_DRM is not set
#
@@ -508,11 +537,20 @@ CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_RAW_DRIVER is not set
#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
# I2C support
#
# CONFIG_I2C is not set
#
+# Misc devices
+#
+
+#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -523,6 +561,55 @@ CONFIG_LEGACY_PTY_COUNT=256
# 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 is not set
+
+#
+# USB Gadget Support
+#
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+CONFIG_USB_GADGET_PXA2XX=y
+CONFIG_USB_PXA2XX=y
+CONFIG_USB_PXA2XX_SMALL=y
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_SA1100 is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+# CONFIG_USB_GADGET_OMAP 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=y
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -531,10 +618,15 @@ CONFIG_EXT2_FS=y
# CONFIG_JBD is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
# CONFIG_XFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
@@ -550,6 +642,7 @@ CONFIG_EXT2_FS=y
CONFIG_FAT_FS=y
CONFIG_MSDOS_FS=y
# CONFIG_VFAT_FS is not set
+CONFIG_FAT_DEFAULT_CODEPAGE=437
# CONFIG_NTFS_FS is not set
#
@@ -577,6 +670,11 @@ CONFIG_RAMFS=y
CONFIG_JFFS2_FS=y
CONFIG_JFFS2_FS_DEBUG=0
# CONFIG_JFFS2_FS_NAND is not set
+# CONFIG_JFFS2_FS_NOR_ECC is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
# CONFIG_CRAMFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_HPFS_FS is not set
@@ -594,20 +692,20 @@ CONFIG_NFS_FS=y
# CONFIG_NFSD is not set
CONFIG_ROOT_NFS=y
CONFIG_LOCKD=y
-# CONFIG_EXPORTFS is not set
CONFIG_SUNRPC=y
# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
# CONFIG_CIFS is not set
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
# CONFIG_AFS_FS is not set
#
# Partition Types
#
# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
#
# Native Language Support
@@ -637,6 +735,7 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_NLS_ISO8859_8 is not set
# CONFIG_NLS_CODEPAGE_1250 is not set
# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
CONFIG_NLS_ISO8859_1=y
# CONFIG_NLS_ISO8859_2 is not set
# CONFIG_NLS_ISO8859_3 is not set
@@ -658,61 +757,23 @@ CONFIG_NLS_ISO8859_1=y
# CONFIG_PROFILING is not set
#
-# Graphics support
-#
-# CONFIG_FB is not set
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_MDA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# Misc devices
-#
-
-#
-# USB support
-#
-# CONFIG_USB is not set
-
-#
-# USB Gadget Support
-#
-CONFIG_USB_GADGET=y
-# CONFIG_USB_GADGET_NET2280 is not set
-CONFIG_USB_GADGET_PXA2XX=y
-CONFIG_USB_PXA2XX=y
-CONFIG_USB_PXA2XX_SMALL=y
-# CONFIG_USB_GADGET_GOKU is not set
-# CONFIG_USB_GADGET_SA1100 is not set
-# 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=y
-
-#
# Kernel hacking
#
-CONFIG_FRAME_POINTER=y
-CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_INFO=y
+# CONFIG_PRINTK_TIME is not set
CONFIG_DEBUG_KERNEL=y
-# CONFIG_DEBUG_SLAB is not set
CONFIG_MAGIC_SYSRQ=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_WAITQ is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_FS is not set
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_WAITQ is not set
CONFIG_DEBUG_ERRORS=y
CONFIG_DEBUG_LL=y
# CONFIG_DEBUG_ICEDCC is not set
@@ -720,6 +781,7 @@ CONFIG_DEBUG_LL=y
#
# Security options
#
+# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
#
@@ -728,8 +790,14 @@ CONFIG_DEBUG_LL=y
# CONFIG_CRYPTO is not set
#
+# Hardware crypto devices
+#
+
+#
# Library routines
#
+# CONFIG_CRC_CCITT is not set
CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/arm/configs/lusl7200_defconfig b/arch/arm/configs/lusl7200_defconfig
index 8af9118b19352..3ca64cabc92c8 100644
--- a/arch/arm/configs/lusl7200_defconfig
+++ b/arch/arm/configs/lusl7200_defconfig
@@ -1,41 +1,63 @@
#
# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.12-rc1-bk2
+# Mon Mar 28 00:24:38 2005
#
CONFIG_ARM=y
-# CONFIG_EISA is not set
-# CONFIG_SBUS is not set
-# CONFIG_MCA is not set
+CONFIG_MMU=y
CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
-# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
-# CONFIG_GENERIC_BUST_SPINLOCK is not set
-# CONFIG_GENERIC_ISA_DMA is not set
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_IOMAP=y
+CONFIG_FIQ=y
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
#
# General setup
#
-# CONFIG_NET is not set
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
CONFIG_SYSVIPC=y
CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_HOTPLUG is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
#
# Loadable module support
#
CONFIG_MODULES=y
+# CONFIG_MODULE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_KMOD=y
#
# System Type
#
-# CONFIG_ARCH_ADIFCC is not set
-# CONFIG_ARCH_ARCA5K is not set
# CONFIG_ARCH_CLPS7500 is not set
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
@@ -43,106 +65,32 @@ CONFIG_KMOD=y
# CONFIG_ARCH_CAMELOT is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
# CONFIG_ARCH_INTEGRATOR is not set
-# CONFIG_ARCH_IOP310 is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
CONFIG_ARCH_L7200=y
+# 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
-
-#
-# Archimedes/A5000 Implementations
-#
-
-#
-# Archimedes/A5000 Implementations (select only ONE)
-#
-# CONFIG_ARCH_ARC is not set
-# CONFIG_ARCH_A5K is not set
-
-#
-# Footbridge Implementations
-#
-# CONFIG_ARCH_CATS is not set
-# CONFIG_ARCH_PERSONAL_SERVER is not set
-# CONFIG_ARCH_EBSA285_ADDIN is not set
-# CONFIG_ARCH_EBSA285_HOST is not set
-# CONFIG_ARCH_NETWINDER is not set
-
-#
-# SA11x0 Implementations
-#
-# CONFIG_SA1100_ASSABET is not set
-# CONFIG_ASSABET_NEPONSET is not set
-# CONFIG_SA1100_ADSBITSY is not set
-# CONFIG_SA1100_BRUTUS is not set
-# CONFIG_SA1100_CERF is not set
-# CONFIG_SA1100_H3100 is not set
-# CONFIG_SA1100_H3600 is not set
-# CONFIG_SA1100_H3800 is not set
-# CONFIG_SA1100_H3XXX is not set
-# CONFIG_SA1100_EXTENEX1 is not set
-# CONFIG_SA1100_FLEXANET is not set
-# CONFIG_SA1100_FREEBIRD is not set
-# CONFIG_SA1100_GRAPHICSCLIENT is not set
-# CONFIG_SA1100_GRAPHICSMASTER is not set
-# CONFIG_SA1100_BADGE4 is not set
-# CONFIG_SA1100_JORNADA720 is not set
-# CONFIG_SA1100_HUW_WEBPANEL is not set
-# CONFIG_SA1100_ITSY is not set
-# CONFIG_SA1100_LART is not set
-# CONFIG_SA1100_NANOENGINE is not set
-# CONFIG_SA1100_OMNIMETER is not set
-# CONFIG_SA1100_PANGOLIN is not set
-# CONFIG_SA1100_PLEB is not set
-# CONFIG_SA1100_PT_SYSTEM3 is not set
-# CONFIG_SA1100_SHANNON is not set
-# CONFIG_SA1100_SHERMAN is not set
-# CONFIG_SA1100_SIMPAD is not set
-# CONFIG_SA1100_PFS168 is not set
-# CONFIG_SA1100_VICTOR is not set
-# CONFIG_SA1100_XP860 is not set
-# CONFIG_SA1100_YOPY is not set
-# CONFIG_SA1100_STORK is not set
-# CONFIG_SA1100_USB is not set
-# CONFIG_SA1100_USB_NETLINK is not set
-# CONFIG_SA1100_USB_CHAR is not set
-# CONFIG_H3600_SLEEVE is not set
-
-#
-# CLPS711X/EP721X Implementations
-#
-# CONFIG_ARCH_AUTCPU12 is not set
-# CONFIG_ARCH_CDB89712 is not set
-# CONFIG_ARCH_CLEP7312 is not set
-# CONFIG_ARCH_EDB7211 is not set
-# CONFIG_ARCH_P720T is not set
-# CONFIG_ARCH_FORTUNET is not set
-# CONFIG_ARCH_EP7211 is not set
-# CONFIG_ARCH_EP7212 is not set
-# CONFIG_ARCH_ACORN is not set
-# CONFIG_FOOTBRIDGE is not set
-# CONFIG_FOOTBRIDGE_HOST is not set
-# CONFIG_FOOTBRIDGE_ADDIN is not set
-CONFIG_CPU_32=y
-# CONFIG_CPU_26 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
#
# Processor Type
#
-# CONFIG_CPU_32v3 is not set
-CONFIG_CPU_32v4=y
-# CONFIG_CPU_32v5 is not set
-# CONFIG_CPU_ARM610 is not set
-# CONFIG_CPU_ARM710 is not set
+CONFIG_CPU_32=y
CONFIG_CPU_ARM720T=y
-# CONFIG_CPU_ARM920T is not set
-# CONFIG_CPU_ARM922T is not set
-# CONFIG_CPU_ARM926T is not set
-# CONFIG_CPU_ARM1020 is not set
-# CONFIG_CPU_SA110 is not set
-# CONFIG_CPU_SA1100 is not set
-# CONFIG_CPU_XSCALE is not set
-# CONFIG_XSCALE_PMU is not set
+CONFIG_CPU_32v4=y
+CONFIG_CPU_ABRT_LV4T=y
+CONFIG_CPU_CACHE_V4=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WT=y
+CONFIG_CPU_TLB_V4WT=y
#
# Processor Features
@@ -150,40 +98,61 @@ CONFIG_CPU_ARM720T=y
# CONFIG_ARM_THUMB is not set
#
-# General setup
+# Bus support
#
-# CONFIG_DISCONTIGMEM is not set
-# CONFIG_PCI is not set
-# CONFIG_ISA is not set
-# CONFIG_ISA_DMA is not set
-CONFIG_FIQ=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_PREEMPT is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x00010000
+CONFIG_ZBOOT_ROM_BSS=0xf03e0000
CONFIG_ZBOOT_ROM=y
-CONFIG_ZBOOT_ROM_TEXT=00010000
-CONFIG_ZBOOT_ROM_BSS=f03e0000
-# CONFIG_HOTPLUG is not set
-# CONFIG_PCMCIA is not set
+CONFIG_CMDLINE="console=tty0 console=ttyLU1,115200 root=/dev/ram initrd=0xf1000000,0x005dac7b mem=32M"
+
+#
+# Floating point emulation
+#
#
-# At least one math emulation must be selected
+# At least one emulation must be selected
#
# CONFIG_FPE_NWFPE is not set
# CONFIG_FPE_FASTFPE is not set
-CONFIG_KCORE_ELF=y
-# CONFIG_KCORE_AOUT is not set
-CONFIG_BINFMT_AOUT=y
+
+#
+# Userspace binary formats
+#
CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_AOUT=y
# CONFIG_BINFMT_MISC is not set
-# CONFIG_PM is not set
-# CONFIG_PREEMPT is not set
-# CONFIG_APM is not set
# CONFIG_ARTHUR is not set
-CONFIG_CMDLINE="console=tty0 console=ttyLU1,115200 root=/dev/ram initrd=0xf1000000,0x005dac7b mem=32M"
-CONFIG_ALIGNMENT_TRAP=y
#
-# Parallel port support
+# Power management options
#
-# CONFIG_PARPORT is not set
+# CONFIG_PM is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
#
# Memory Technology Devices (MTD)
@@ -191,59 +160,68 @@ CONFIG_ALIGNMENT_TRAP=y
# CONFIG_MTD is not set
#
-# Plug and Play configuration
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
#
-# CONFIG_PNP is not set
-# CONFIG_ISAPNP is not set
-# CONFIG_PNPBIOS is not set
#
# Block devices
#
# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_DEV_XD is not set
-# CONFIG_PARIDE is not set
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_CISS_SCSI_TAPE is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
# CONFIG_BLK_DEV_LOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CDROM_PKTCDVD is not set
#
-# Multi-device support (RAID and LVM)
+# IO Schedulers
#
-# CONFIG_MD is not set
-# CONFIG_BLK_DEV_MD is not set
-# CONFIG_MD_LINEAR is not set
-# CONFIG_MD_RAID0 is not set
-# CONFIG_MD_RAID1 is not set
-# CONFIG_MD_RAID5 is not set
-# CONFIG_MD_MULTIPATH is not set
-# CONFIG_BLK_DEV_LVM is not set
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
#
-# ATA/IDE/MFM/RLL support
+# ATA/ATAPI/MFM/RLL support
#
# CONFIG_IDE is not set
-# CONFIG_BLK_DEV_HD is not set
#
-# SCSI support
+# SCSI device support
#
# CONFIG_SCSI is not set
#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
# I2O device support
#
-# CONFIG_I2O is not set
-# CONFIG_I2O_BLOCK is not set
-# CONFIG_I2O_SCSI is not set
-# CONFIG_I2O_PROC is not set
+
+#
+# Networking support
+#
+# CONFIG_NET is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
#
# ISDN subsystem
@@ -253,37 +231,29 @@ CONFIG_BLK_DEV_INITRD=y
# Input device support
#
# CONFIG_INPUT is not set
-# CONFIG_INPUT_KEYBDEV is not set
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_EVDEV is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_LIBPS2 is not set
+# CONFIG_SERIO_RAW is not set
# CONFIG_GAMEPORT is not set
CONFIG_SOUND_GAMEPORT=y
-# CONFIG_GAMEPORT_NS558 is not set
-# CONFIG_GAMEPORT_L4 is not set
-# CONFIG_INPUT_EMU10K1 is not set
-# CONFIG_GAMEPORT_PCIGAME is not set
-# CONFIG_GAMEPORT_FM801 is not set
-# CONFIG_GAMEPORT_CS461x is not set
-# CONFIG_SERIO is not set
-# CONFIG_SERIO_SERPORT is not set
#
# Character devices
#
# CONFIG_VT is not set
-# CONFIG_SERIAL_EXTENDED is not set
CONFIG_SERIAL_NONSTANDARD=y
# CONFIG_COMPUTONE is not set
# CONFIG_ROCKETPORT is not set
# CONFIG_CYCLADES is not set
# CONFIG_DIGIEPCA is not set
-# CONFIG_DIGI is not set
-# CONFIG_ESPSERIAL is not set
# CONFIG_MOXA_INTELLIO is not set
# CONFIG_MOXA_SMARTIO is not set
# CONFIG_ISI is not set
-# CONFIG_SYNCLINK is not set
# CONFIG_SYNCLINKMP is not set
# CONFIG_N_HDLC is not set
# CONFIG_RISCOM8 is not set
@@ -296,35 +266,38 @@ CONFIG_SERIAL_NONSTANDARD=y
# Serial drivers
#
# CONFIG_SERIAL_8250 is not set
-# CONFIG_SERIAL_8250_CONSOLE is not set
-# CONFIG_SERIAL_8250_EXTENDED is not set
-# CONFIG_SERIAL_8250_MANY_PORTS is not set
-# CONFIG_SERIAL_8250_SHARE_IRQ is not set
-# CONFIG_SERIAL_8250_DETECT_IRQ is not set
-# CONFIG_SERIAL_8250_MULTIPORT is not set
-# CONFIG_SERIAL_8250_RSA is not set
#
# Non-8250 serial port support
#
+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_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
#
-# ARM Serial drivers
+# TPM devices
#
-# CONFIG_ATOMWIDE_SERIAL is not set
-# CONFIG_DUALSP_SERIAL is not set
-# CONFIG_SERIAL_AMBA is not set
-# CONFIG_SERIAL_AMBA_CONSOLE is not set
-# CONFIG_SERIAL_CLPS711X is not set
-# CONFIG_SERIAL_CLPS711X_CONSOLE is not set
-# CONFIG_SERIAL_21285 is not set
-# CONFIG_SERIAL_21285_OLD is not set
-# CONFIG_SERIAL_21285_CONSOLE is not set
-# CONFIG_SERIAL_UART00 is not set
-# CONFIG_SERIAL_UART00_CONSOLE is not set
-# CONFIG_SERIAL_SA1100 is not set
-# CONFIG_SERIAL_SA1100_CONSOLE is not set
-# CONFIG_UNIX98_PTYS is not set
+# CONFIG_TCG_TPM is not set
#
# I2C support
@@ -332,154 +305,151 @@ CONFIG_SERIAL_NONSTANDARD=y
# CONFIG_I2C is not set
#
-# L3 serial bus support
+# Misc devices
#
-# CONFIG_L3 is not set
-# CONFIG_L3_ALGOBIT is not set
-# CONFIG_L3_BIT_SA1100_GPIO is not set
#
-# Other L3 adapters
+# Multimedia devices
#
-# CONFIG_L3_SA1111 is not set
-# CONFIG_BIT_SA1100_GPIO is not set
+# CONFIG_VIDEO_DEV is not set
#
-# Mice
+# Digital Video Broadcasting Devices
#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_MOUSE is not set
-# CONFIG_QIC02_TAPE is not set
#
-# Watchdog Cards
+# Graphics support
#
-# CONFIG_WATCHDOG is not set
-# CONFIG_INTEL_RNG is not set
-# CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
+# CONFIG_FB is not set
#
-# Ftape, the floppy tape device driver
+# Sound
#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
+# CONFIG_SOUND is not set
#
-# Multimedia devices
+# USB support
#
-# CONFIG_VIDEO_DEV is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB is not set
+
+#
+# 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_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_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
# CONFIG_QUOTA is not set
-# CONFIG_QFMT_V1 is not set
-# CONFIG_QFMT_V2 is not set
-# CONFIG_QIFACE_COMPAT is not set
+CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_REISERFS_CHECK is not set
-# CONFIG_REISERFS_PROC_INFO 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_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
# CONFIG_ADFS_FS is not set
-# CONFIG_ADFS_FS_RW 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_EXT3_FS is not set
-# CONFIG_JBD is not set
-# CONFIG_JBD_DEBUG is not set
-# CONFIG_FAT_FS is not set
-# CONFIG_MSDOS_FS is not set
-# CONFIG_UMSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
# CONFIG_EFS_FS is not set
-# CONFIG_JFFS_FS is not set
-# CONFIG_JFFS2_FS is not set
# CONFIG_CRAMFS is not set
-# CONFIG_TMPFS is not set
-CONFIG_RAMFS=y
-# CONFIG_ISO9660_FS is not set
-# CONFIG_JOLIET is not set
-# CONFIG_ZISOFS is not set
-# CONFIG_JFS_FS is not set
-# CONFIG_JFS_DEBUG is not set
-# CONFIG_JFS_STATISTICS is not set
-# CONFIG_MINIX_FS is not set
# CONFIG_VXFS_FS is not set
-# CONFIG_NTFS_FS is not set
-# CONFIG_NTFS_DEBUG is not set
-# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
-CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
-# CONFIG_DEVFS_MOUNT is not set
-# CONFIG_DEVFS_DEBUG is not set
-# CONFIG_DEVPTS_FS is not set
# CONFIG_QNX4FS_FS is not set
-# CONFIG_QNX4FS_RW is not set
-# CONFIG_ROMFS_FS is not set
-CONFIG_EXT2_FS=y
# CONFIG_SYSV_FS is not set
-# CONFIG_UDF_FS is not set
-# CONFIG_UDF_RW is not set
# CONFIG_UFS_FS is not set
-# CONFIG_UFS_FS_WRITE is not set
-# CONFIG_NCPFS_NLS is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_ZISOFS_FS is not set
#
# Partition Types
#
# CONFIG_PARTITION_ADVANCED is not set
-# CONFIG_SMB_NLS is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
# CONFIG_NLS is not set
#
-# Multimedia Capabilities Port drivers
+# Profiling support
#
-# CONFIG_MCP is not set
-# CONFIG_MCP_SA1100 is not set
-# CONFIG_MCP_UCB1200 is not set
-# CONFIG_MCP_UCB1200_AUDIO is not set
-# CONFIG_MCP_UCB1200_TS is not set
+# CONFIG_PROFILING is not set
#
-# Console Switches
+# Kernel hacking
#
-# CONFIG_SWITCHES is not set
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
#
-# USB support
+# Security options
#
-# CONFIG_USB is not set
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
#
-# Kernel hacking
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
#
-CONFIG_FRAME_POINTER=y
-CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_INFO=y
-# CONFIG_DEBUG_KERNEL is not set
-# CONFIG_DEBUG_SLAB is not set
-# CONFIG_MAGIC_SYSRQ is not set
-# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_WAITQ is not set
-# CONFIG_DEBUG_BUGVERBOSE is not set
-# CONFIG_DEBUG_ERRORS is not set
-# CONFIG_DEBUG_LL is not set
-# CONFIG_DEBUG_DC21285_PORT is not set
-# CONFIG_DEBUG_CLPS711X_UART2 is not set
#
# Library routines
#
+# CONFIG_CRC_CCITT is not set
# CONFIG_CRC32 is not set
-# CONFIG_ZLIB_INFLATE is not set
-# CONFIG_ZLIB_DEFLATE is not set
+# CONFIG_LIBCRC32C is not set
diff --git a/arch/arm/configs/mainstone_defconfig b/arch/arm/configs/mainstone_defconfig
index 4ab6e265a561a..153d68594beb5 100644
--- a/arch/arm/configs/mainstone_defconfig
+++ b/arch/arm/configs/mainstone_defconfig
@@ -1,41 +1,50 @@
#
# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.12-rc1-bk2
+# Sat Mar 26 20:00:45 2005
#
CONFIG_ARM=y
CONFIG_MMU=y
CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_IOMAP=y
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
CONFIG_CLEAN_COMPILE=y
-CONFIG_STANDALONE=y
CONFIG_BROKEN_ON_SMP=y
#
# General setup
#
+CONFIG_LOCALVERSION=""
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
# CONFIG_IKCONFIG 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_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=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
@@ -44,12 +53,12 @@ CONFIG_MODULES=y
# CONFIG_MODULE_UNLOAD is not set
CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
# CONFIG_KMOD is not set
#
# System Type
#
-# CONFIG_ARCH_ADIFCC is not set
# CONFIG_ARCH_CLPS7500 is not set
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
@@ -59,6 +68,7 @@ CONFIG_OBSOLETE_MODPARM=y
# 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=y
# CONFIG_ARCH_RPC is not set
@@ -67,7 +77,9 @@ CONFIG_ARCH_PXA=y
# CONFIG_ARCH_SHARK is not set
# CONFIG_ARCH_LH7A40X is not set
# CONFIG_ARCH_OMAP is not set
-# CONFIG_ARCH_VERSATILE_PB is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_H720X is not set
#
# Intel PXA2xx Implementations
@@ -75,6 +87,7 @@ CONFIG_ARCH_PXA=y
# CONFIG_ARCH_LUBBOCK is not set
CONFIG_MACH_MAINSTONE=y
# CONFIG_ARCH_PXA_IDP is not set
+# CONFIG_PXA_SHARPSL is not set
CONFIG_PXA27x=y
CONFIG_IWMMXT=y
@@ -85,6 +98,7 @@ CONFIG_CPU_32=y
CONFIG_CPU_XSCALE=y
CONFIG_CPU_32v5=y
CONFIG_CPU_ABRT_EV5T=y
+CONFIG_CPU_CACHE_VIVT=y
CONFIG_CPU_TLB_V4WBI=y
CONFIG_CPU_MINICACHE=y
@@ -95,59 +109,78 @@ CONFIG_CPU_MINICACHE=y
CONFIG_XSCALE_PMU=y
#
-# General setup
+# Bus support
+#
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_PREEMPT is not set
+CONFIG_LEDS=y
+CONFIG_LEDS_TIMER=y
+CONFIG_LEDS_CPU=y
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
#
-# CONFIG_ZBOOT_ROM is not set
CONFIG_ZBOOT_ROM_TEXT=0x0
CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="root=/dev/nfs ip=bootp console=ttyS0,115200 mem=64M"
+# CONFIG_XIP_KERNEL is not set
#
-# PCMCIA/CardBus support
+# Floating point emulation
#
-CONFIG_PCMCIA=y
-# CONFIG_PCMCIA_DEBUG is not set
-# CONFIG_TCIC is not set
-CONFIG_PCMCIA_PXA2XX=y
#
-# At least one math emulation must be selected
+# At least one emulation must be selected
#
CONFIG_FPE_NWFPE=y
# CONFIG_FPE_NWFPE_XP is not set
# CONFIG_FPE_FASTFPE is not set
-# CONFIG_VFP 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
#
-# Generic Driver Options
+# Power management options
#
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
-# CONFIG_DEBUG_DRIVER is not set
# CONFIG_PM is not set
-# CONFIG_PREEMPT is not set
-# CONFIG_ARTHUR is not set
-CONFIG_CMDLINE="root=/dev/nfs ip=bootp console=ttyS0,115200 mem=64M"
-CONFIG_LEDS=y
-CONFIG_LEDS_TIMER=y
-CONFIG_LEDS_CPU=y
-CONFIG_ALIGNMENT_TRAP=y
#
-# Parallel port support
+# Device Drivers
#
-# CONFIG_PARPORT is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
#
# Memory Technology Devices (MTD)
#
CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
-CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
CONFIG_MTD_REDBOOT_PARTS=y
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
+# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
# CONFIG_MTD_CMDLINE_PARTS is not set
# CONFIG_MTD_AFS_PARTS is not set
@@ -171,10 +204,12 @@ CONFIG_MTD_CFI_NOSWAP=y
# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
CONFIG_MTD_CFI_GEOMETRY=y
-# CONFIG_MTD_CFI_B1 is not set
-# CONFIG_MTD_CFI_B2 is not set
-CONFIG_MTD_CFI_B4=y
-# CONFIG_MTD_CFI_B8 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 is not set
CONFIG_MTD_CFI_I2=y
# CONFIG_MTD_CFI_I4 is not set
@@ -182,10 +217,11 @@ CONFIG_MTD_CFI_I2=y
CONFIG_MTD_CFI_INTELEXT=y
# CONFIG_MTD_CFI_AMDSTD is not set
# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
+# CONFIG_MTD_XIP is not set
#
# Mapping drivers for chip access
@@ -194,13 +230,16 @@ CONFIG_MTD_CFI_INTELEXT=y
# CONFIG_MTD_PHYSMAP is not set
# CONFIG_MTD_ARM_INTEGRATOR is not set
# CONFIG_MTD_EDB7312 is not set
+# CONFIG_MTD_SHARP_SL 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
@@ -215,6 +254,11 @@ CONFIG_MTD_CFI_INTELEXT=y
# CONFIG_MTD_NAND is not set
#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
# Plug and Play support
#
@@ -222,9 +266,53 @@ CONFIG_MTD_CFI_INTELEXT=y
# Block devices
#
# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
# CONFIG_BLK_DEV_LOOP is not set
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# 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 is not set
+# CONFIG_IDE_ARM is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
#
# Multi-device support (RAID and LVM)
@@ -232,6 +320,18 @@ CONFIG_MTD_CFI_INTELEXT=y
# CONFIG_MD is not set
#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
# Networking support
#
CONFIG_NET=y
@@ -257,6 +357,9 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
# CONFIG_IPV6 is not set
# CONFIG_NETFILTER is not set
@@ -276,12 +379,12 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
#
# QoS and/or fair queueing
#
# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
#
# Network testing
@@ -323,11 +426,6 @@ CONFIG_SMC91X=y
# CONFIG_NET_RADIO is not set
#
-# PCMCIA network device support
-#
-# CONFIG_NET_PCMCIA is not set
-
-#
# Wan interfaces
#
# CONFIG_WAN is not set
@@ -337,51 +435,6 @@ CONFIG_SMC91X=y
# CONFIG_NETCONSOLE is not set
#
-# ATA/ATAPI/MFM/RLL support
-#
-CONFIG_IDE=y
-CONFIG_BLK_DEV_IDE=y
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
-CONFIG_BLK_DEV_IDEDISK=y
-# CONFIG_IDEDISK_MULTI_MODE is not set
-CONFIG_BLK_DEV_IDECS=y
-# CONFIG_BLK_DEV_IDECD is not set
-# CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
-# CONFIG_IDE_TASK_IOCTL is not set
-# CONFIG_IDE_TASKFILE_IO is not set
-
-#
-# IDE chipset support/bugfixes
-#
-# CONFIG_IDE_GENERIC is not set
-# CONFIG_IDE_ARM is not set
-# CONFIG_BLK_DEV_IDEDMA is not set
-# CONFIG_IDEDMA_AUTO is not set
-# CONFIG_BLK_DEV_HD is not set
-
-#
-# SCSI device support
-#
-# CONFIG_SCSI is not set
-
-#
-# Fusion MPT device support
-#
-
-#
-# IEEE 1394 (FireWire) support
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-
-#
# ISDN subsystem
#
# CONFIG_ISDN is not set
@@ -404,16 +457,6 @@ CONFIG_INPUT_EVDEV=y
# CONFIG_INPUT_EVBUG is not set
#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-# CONFIG_SERIO_SERPORT is not set
-# CONFIG_SERIO_CT82C710 is not set
-
-#
# Input Device Drivers
#
CONFIG_INPUT_KEYBOARD=y
@@ -428,6 +471,16 @@ CONFIG_KEYBOARD_ATKBD=y
# CONFIG_INPUT_MISC is not set
#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
+#
# Character devices
#
CONFIG_VT=y
@@ -450,7 +503,6 @@ CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
-# CONFIG_QIC02_TAPE is not set
#
# IPMI
@@ -463,23 +515,19 @@ CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_WATCHDOG is not set
# CONFIG_NVRAM is not set
# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
#
# Ftape, the floppy tape device driver
#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
#
-# PCMCIA character devices
+# TPM devices
#
-# CONFIG_SYNCLINK_CS is not set
-# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
#
# I2C support
@@ -487,6 +535,10 @@ CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_I2C is not set
#
+# Misc devices
+#
+
+#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -497,6 +549,61 @@ CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_DVB is not set
#
+# Graphics support
+#
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+CONFIG_FB_SOFT_CURSOR=y
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+CONFIG_FB_PXA=y
+# CONFIG_FB_PXA_PARAMETERS is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT 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
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -505,10 +612,15 @@ CONFIG_EXT2_FS=y
# CONFIG_JBD is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
# CONFIG_XFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
@@ -552,6 +664,11 @@ CONFIG_RAMFS=y
CONFIG_JFFS2_FS=y
CONFIG_JFFS2_FS_DEBUG=0
# CONFIG_JFFS2_FS_NAND is not set
+# CONFIG_JFFS2_FS_NOR_ECC is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
# CONFIG_CRAMFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_HPFS_FS is not set
@@ -569,9 +686,9 @@ CONFIG_NFS_FS=y
# CONFIG_NFSD is not set
CONFIG_ROOT_NFS=y
CONFIG_LOCKD=y
-# CONFIG_EXPORTFS is not set
CONFIG_SUNRPC=y
# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
# CONFIG_CIFS is not set
# CONFIG_NCP_FS is not set
@@ -582,6 +699,7 @@ CONFIG_SUNRPC=y
# Partition Types
#
# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
#
# Native Language Support
@@ -633,63 +751,23 @@ CONFIG_NLS_ISO8859_1=y
# CONFIG_PROFILING is not set
#
-# Graphics support
-#
-CONFIG_FB=y
-CONFIG_FB_PXA=y
-# CONFIG_FB_PXA_PARAMETERS is not set
-# CONFIG_FB_VIRTUAL is not set
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_MDA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_PCI_CONSOLE=y
-# CONFIG_FONTS is not set
-CONFIG_FONT_8x8=y
-CONFIG_FONT_8x16=y
-
-#
-# Logo configuration
-#
-CONFIG_LOGO=y
-CONFIG_LOGO_LINUX_MONO=y
-CONFIG_LOGO_LINUX_VGA16=y
-CONFIG_LOGO_LINUX_CLUT224=y
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# Misc devices
-#
-
-#
-# USB support
-#
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
# Kernel hacking
#
-CONFIG_FRAME_POINTER=y
-CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_INFO=y
+# CONFIG_PRINTK_TIME is not set
CONFIG_DEBUG_KERNEL=y
-# CONFIG_DEBUG_SLAB is not set
CONFIG_MAGIC_SYSRQ=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_WAITQ is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_FS is not set
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_WAITQ is not set
CONFIG_DEBUG_ERRORS=y
CONFIG_DEBUG_LL=y
# CONFIG_DEBUG_ICEDCC is not set
@@ -697,6 +775,7 @@ CONFIG_DEBUG_LL=y
#
# Security options
#
+# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
#
@@ -705,8 +784,13 @@ CONFIG_DEBUG_LL=y
# CONFIG_CRYPTO is not set
#
+# Hardware crypto devices
+#
+
+#
# Library routines
#
+# CONFIG_CRC_CCITT is not set
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=y
diff --git a/arch/arm/configs/mx1ads_defconfig b/arch/arm/configs/mx1ads_defconfig
index 89da10c664893..6517d167acf09 100644
--- a/arch/arm/configs/mx1ads_defconfig
+++ b/arch/arm/configs/mx1ads_defconfig
@@ -1,40 +1,49 @@
#
# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.12-rc1-bk2
+# Sun Mar 27 02:15:46 2005
#
CONFIG_ARM=y
CONFIG_MMU=y
CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_IOMAP=y
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
CONFIG_CLEAN_COMPILE=y
-CONFIG_STANDALONE=y
CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
#
# General setup
#
+CONFIG_LOCALVERSION=""
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
# CONFIG_POSIX_MQUEUE 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_KOBJECT_UEVENT=y
# CONFIG_IKCONFIG is not set
CONFIG_EMBEDDED=y
# CONFIG_KALLSYMS is not set
+CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
-# CONFIG_IOSCHED_NOOP is not set
-# CONFIG_IOSCHED_AS is not set
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
#
# Loadable module support
@@ -44,6 +53,7 @@ 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
#
@@ -58,6 +68,7 @@ CONFIG_KMOD=y
# 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
@@ -66,8 +77,9 @@ CONFIG_KMOD=y
# CONFIG_ARCH_SHARK is not set
# CONFIG_ARCH_LH7A40X is not set
# CONFIG_ARCH_OMAP is not set
-# CONFIG_ARCH_VERSATILE_PB is not set
+# CONFIG_ARCH_VERSATILE is not set
CONFIG_ARCH_IMX=y
+# CONFIG_ARCH_H720X is not set
#
# IMX Implementations
@@ -82,6 +94,7 @@ 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
@@ -94,49 +107,73 @@ CONFIG_CPU_TLB_V4WBI=y
# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
#
-# General setup
+# Bus support
#
CONFIG_ISA=y
-# CONFIG_ZBOOT_ROM is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_PREEMPT=y
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
CONFIG_ZBOOT_ROM_TEXT=0x0
CONFIG_ZBOOT_ROM_BSS=0x0
-# CONFIG_CPU_FREQ is not set
+CONFIG_CMDLINE="console=ttySMX0,57600n8 ip=bootp root=/dev/nfs"
+# CONFIG_XIP_KERNEL is not set
+
+#
+# Floating point emulation
+#
#
-# At least one math emulation must be selected
+# At least one emulation must be selected
#
CONFIG_FPE_NWFPE=y
CONFIG_FPE_NWFPE_XP=y
CONFIG_FPE_FASTFPE=y
-# CONFIG_VFP 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
#
-# Generic Driver Options
+# Power management options
#
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_DEBUG_DRIVER is not set
# CONFIG_PM is not set
-CONFIG_PREEMPT=y
-# CONFIG_ARTHUR is not set
-CONFIG_CMDLINE="console=ttySMX0,57600n8 ip=bootp root=/dev/nfs"
-# CONFIG_LEDS is not set
-CONFIG_ALIGNMENT_TRAP=y
#
-# Parallel port support
+# Device Drivers
#
-# CONFIG_PARPORT is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
#
# Memory Technology Devices (MTD)
#
CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
-CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_REDBOOT_PARTS is not set
# CONFIG_MTD_CMDLINE_PARTS is not set
# CONFIG_MTD_AFS_PARTS is not set
@@ -155,23 +192,33 @@ CONFIG_MTD_BLOCK=y
#
# CONFIG_MTD_CFI is not set
# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
# CONFIG_MTD_RAM is not set
CONFIG_MTD_ROM=y
# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
#
# Mapping drivers for chip access
#
# CONFIG_MTD_COMPLEX_MAPPINGS is not set
-CONFIG_MTD_MX1ADS=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
@@ -186,6 +233,11 @@ CONFIG_MTD_MX1ADS=y
# CONFIG_MTD_NAND is not set
#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
# Plug and Play support
#
# CONFIG_PNP is not set
@@ -195,10 +247,28 @@ CONFIG_MTD_MX1ADS=y
#
# CONFIG_BLK_DEV_FD is not set
# CONFIG_BLK_DEV_XD is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_INITRAMFS_SOURCE=""
+# 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_ATA_OVER_ETH is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
#
# Multi-device support (RAID and LVM)
@@ -206,6 +276,18 @@ CONFIG_BLK_DEV_LOOP=y
# CONFIG_MD is not set
#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
# Networking support
#
CONFIG_NET=y
@@ -232,6 +314,9 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
# CONFIG_IPV6 is not set
# CONFIG_NETFILTER is not set
@@ -251,8 +336,6 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_FASTROUTE is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
#
# QoS and/or fair queueing
@@ -285,10 +368,10 @@ CONFIG_NETDEVICES=y
#
CONFIG_NET_ETHERNET=y
CONFIG_MII=y
-# CONFIG_SMC91X is not set
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_LANCE is not set
# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_SMC91X is not set
# CONFIG_NET_VENDOR_RACAL is not set
# CONFIG_AT1700 is not set
# CONFIG_DEPCA is not set
@@ -332,24 +415,6 @@ CONFIG_PPP_BSDCOMP=y
# CONFIG_NETCONSOLE is not set
#
-# SCSI device support
-#
-# CONFIG_SCSI is not set
-
-#
-# Fusion MPT device support
-#
-
-#
-# IEEE 1394 (FireWire) support
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-
-#
# ISDN subsystem
#
# CONFIG_ISDN is not set
@@ -360,20 +425,11 @@ CONFIG_PPP_BSDCOMP=y
# CONFIG_INPUT is not set
#
-# Userland interfaces
-#
-
-#
-# Input I/O drivers
+# Hardware I/O ports
#
+# CONFIG_SERIO is not set
# CONFIG_GAMEPORT is not set
CONFIG_SOUND_GAMEPORT=y
-# CONFIG_SERIO is not set
-# CONFIG_SERIO_I8042 is not set
-
-#
-# Input Device Drivers
-#
#
# Character devices
@@ -395,7 +451,6 @@ CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
# CONFIG_LEGACY_PTYS is not set
-# CONFIG_QIC02_TAPE is not set
#
# IPMI
@@ -408,25 +463,30 @@ CONFIG_UNIX98_PTYS=y
# CONFIG_WATCHDOG is not set
# CONFIG_NVRAM is not set
CONFIG_RTC=m
-# CONFIG_GEN_RTC is not set
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
#
# Ftape, the floppy tape device driver
#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
# CONFIG_DRM is not set
# CONFIG_RAW_DRIVER is not set
#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
# I2C support
#
# CONFIG_I2C is not set
#
+# Misc devices
+#
+
+#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -437,6 +497,33 @@ CONFIG_RTC=m
# 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 is not set
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
# File systems
#
# CONFIG_EXT2_FS is not set
@@ -444,10 +531,15 @@ CONFIG_RTC=m
# CONFIG_JBD is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
# CONFIG_XFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
@@ -477,6 +569,7 @@ CONFIG_DEVFS_MOUNT=y
# CONFIG_DEVFS_DEBUG is not set
# CONFIG_DEVPTS_FS_XATTR is not set
CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
@@ -494,6 +587,11 @@ CONFIG_RAMFS=y
CONFIG_JFFS2_FS=y
CONFIG_JFFS2_FS_DEBUG=0
# CONFIG_JFFS2_FS_NAND is not set
+# CONFIG_JFFS2_FS_NOR_ECC is not set
+# CONFIG_JFFS2_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
@@ -512,9 +610,9 @@ CONFIG_NFS_V3=y
CONFIG_ROOT_NFS=y
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
-# CONFIG_EXPORTFS is not set
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
@@ -525,6 +623,7 @@ CONFIG_SUNRPC=y
# Partition Types
#
# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
#
# Native Language Support
@@ -576,46 +675,31 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_PROFILING is not set
#
-# Graphics support
-#
-# CONFIG_FB is not set
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# Misc devices
-#
-
-#
-# USB support
-#
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
# Kernel hacking
#
-CONFIG_FRAME_POINTER=y
-CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_INFO=y
+# CONFIG_PRINTK_TIME is not set
CONFIG_DEBUG_KERNEL=y
-# CONFIG_DEBUG_SLAB is not set
CONFIG_MAGIC_SYSRQ=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_DEBUG_PREEMPT=y
# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_WAITQ is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_FS is not set
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_WAITQ is not set
CONFIG_DEBUG_ERRORS=y
# CONFIG_DEBUG_LL is not set
#
# Security options
#
+# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
#
@@ -629,6 +713,8 @@ CONFIG_CRYPTO=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 is not set
# CONFIG_CRYPTO_BLOWFISH is not set
# CONFIG_CRYPTO_TWOFISH is not set
@@ -636,16 +722,23 @@ CONFIG_CRYPTO=y
# 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_CRC16=y
+CONFIG_CRC_CCITT=y
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=y
diff --git a/arch/arm/configs/neponset_defconfig b/arch/arm/configs/neponset_defconfig
index 1a955e1ca48a4..7fb1f7c7bf433 100644
--- a/arch/arm/configs/neponset_defconfig
+++ b/arch/arm/configs/neponset_defconfig
@@ -1,122 +1,106 @@
#
# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11
+# Wed Mar 9 14:28:26 2005
#
CONFIG_ARM=y
CONFIG_MMU=y
-CONFIG_SWAP=y
CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_IOMAP=y
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
#
# General setup
#
-CONFIG_NET=y
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG 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_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_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 is not set
#
# System Type
#
-# CONFIG_ARCH_ADIFCC is not set
-# CONFIG_ARCH_ARCA5K is not set
# CONFIG_ARCH_CLPS7500 is not set
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
-# CONFIG_ARCH_PXA 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_IOP310 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=y
+# CONFIG_ARCH_S3C2410 is not set
# CONFIG_ARCH_SHARK is not set
-
-#
-# Archimedes/A5000 Implementations
-#
-
-#
-# Archimedes/A5000 Implementations (select only ONE)
-#
-
-#
-# CLPS711X/EP721X Implementations
-#
-
-#
-# Epxa10db
-#
-
-#
-# Footbridge Implementations
-#
-
-#
-# IOP310 Implementation Options
-#
-
-#
-# IOP310 Chipset Features
-#
-
-#
-# Intel PXA250/210 Implementations
-#
+# 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
#
# SA11x0 Implementations
#
CONFIG_SA1100_ASSABET=y
CONFIG_ASSABET_NEPONSET=y
-# CONFIG_SA1100_ADSBITSY is not set
-# CONFIG_SA1100_BRUTUS is not set
# CONFIG_SA1100_CERF is not set
+# CONFIG_SA1100_COLLIE is not set
# CONFIG_SA1100_H3100 is not set
# CONFIG_SA1100_H3600 is not set
# CONFIG_SA1100_H3800 is not set
-# CONFIG_SA1100_EXTENEX1 is not set
-# CONFIG_SA1100_FLEXANET is not set
-# CONFIG_SA1100_FREEBIRD is not set
-# CONFIG_SA1100_GRAPHICSCLIENT is not set
-# CONFIG_SA1100_GRAPHICSMASTER is not set
# CONFIG_SA1100_BADGE4 is not set
# CONFIG_SA1100_JORNADA720 is not set
-# CONFIG_SA1100_HUW_WEBPANEL is not set
-# CONFIG_SA1100_ITSY is not set
+# CONFIG_SA1100_HACKKIT is not set
# CONFIG_SA1100_LART is not set
-# CONFIG_SA1100_NANOENGINE is not set
-# CONFIG_SA1100_OMNIMETER is not set
-# CONFIG_SA1100_PANGOLIN is not set
# CONFIG_SA1100_PLEB is not set
-# CONFIG_SA1100_PT_SYSTEM3 is not set
# CONFIG_SA1100_SHANNON is not set
-# CONFIG_SA1100_SHERMAN is not set
# CONFIG_SA1100_SIMPAD is not set
-# CONFIG_SA1100_PFS168 is not set
-# CONFIG_SA1100_VICTOR is not set
-# CONFIG_SA1100_XP860 is not set
-# CONFIG_SA1100_YOPY is not set
-# CONFIG_SA1100_STORK is not set
-CONFIG_SA1100_USB=m
-CONFIG_SA1100_USB_NETLINK=m
-CONFIG_SA1100_USB_CHAR=m
-CONFIG_SA1111=y
-CONFIG_FORCE_MAX_ZONEORDER=9
+# CONFIG_SA1100_SSP is not set
#
# Processor Type
@@ -124,57 +108,102 @@ CONFIG_FORCE_MAX_ZONEORDER=9
CONFIG_CPU_32=y
CONFIG_CPU_SA1100=y
CONFIG_CPU_32v4=y
+CONFIG_CPU_ABRT_EV4=y
+CONFIG_CPU_CACHE_V4WB=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_TLB_V4WB=y
+CONFIG_CPU_MINICACHE=y
#
# Processor Features
#
+CONFIG_SA1111=y
+CONFIG_DMABOUNCE=y
+CONFIG_FORCE_MAX_ZONEORDER=9
#
-# General setup
+# Bus support
#
-CONFIG_DISCONTIGMEM=y
CONFIG_ISA=y
-CONFIG_ZBOOT_ROM=y
-CONFIG_ZBOOT_ROM_TEXT=0x80000
-CONFIG_ZBOOT_ROM_BSS=0xc1000000
-CONFIG_CPU_FREQ=y
-CONFIG_CPU_FREQ_24_API=y
-CONFIG_CPU_FREQ_26_API=y
-CONFIG_HOTPLUG=y
#
-# PCMCIA/CardBus support
+# PCCARD (PCMCIA/CardBus) support
#
+CONFIG_PCCARD=y
+# CONFIG_PCMCIA_DEBUG is not set
CONFIG_PCMCIA=y
+
+#
+# PC-card bridges
+#
# CONFIG_I82365 is not set
# CONFIG_TCIC is not set
CONFIG_PCMCIA_SA1100=y
CONFIG_PCMCIA_SA1111=y
#
-# At least one math emulation must be selected
+# Kernel Features
+#
+# CONFIG_PREEMPT is not set
+CONFIG_DISCONTIGMEM=y
+CONFIG_LEDS=y
+CONFIG_LEDS_TIMER=y
+CONFIG_LEDS_CPU=y
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x80000
+CONFIG_ZBOOT_ROM_BSS=0xc1000000
+CONFIG_ZBOOT_ROM=y
+CONFIG_CMDLINE="console=ttySA0,38400n8 cpufreq=221200 rw root=/dev/mtdblock2 mtdparts=sa1100:512K(boot),1M(kernel),2560K(initrd),4M(root) load_ramdisk=1 prompt_ramdisk=0 mem=32M noinitrd initrd=0xc0800000,3M"
+CONFIG_CPU_FREQ=y
+# CONFIG_CPU_FREQ_DEBUG is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
+# CONFIG_CPU_FREQ_GOV_PERFORMANCE is not set
+# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set
+CONFIG_CPU_FREQ_SA1110=y
+
+#
+# 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
-CONFIG_KCORE_ELF=y
-# CONFIG_KCORE_AOUT is not set
-CONFIG_BINFMT_AOUT=y
+
+#
+# Userspace binary formats
+#
CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_AOUT=y
# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
CONFIG_PM=y
-# CONFIG_PREEMPT is not set
CONFIG_APM=y
-# CONFIG_ARTHUR is not set
-CONFIG_CMDLINE="console=ttySA0,38400n8 cpufreq=221200 rw root=/dev/mtdblock2 mtdparts=sa1100:512K(boot),1M(kernel),2560K(initrd),4M(root) load_ramdisk=1 prompt_ramdisk=0 mem=32M noinitrd initrd=0xc0800000,3M"
-CONFIG_LEDS=y
-CONFIG_LEDS_TIMER=y
-CONFIG_LEDS_CPU=y
-CONFIG_ALIGNMENT_TRAP=y
#
-# Parallel port support
+# Device Drivers
#
-# CONFIG_PARPORT is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
#
# Memory Technology Devices (MTD)
@@ -184,6 +213,9 @@ CONFIG_MTD=y
CONFIG_MTD_PARTITIONS=y
CONFIG_MTD_CONCAT=y
CONFIG_MTD_REDBOOT_PARTS=y
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
+# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
CONFIG_MTD_CMDLINE_PARTS=y
# CONFIG_MTD_AFS_PARTS is not set
@@ -194,6 +226,7 @@ CONFIG_MTD_CMDLINE_PARTS=y
CONFIG_MTD_BLOCK=y
# CONFIG_FTL is not set
# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
#
# RAM/ROM/Flash chip drivers
@@ -206,37 +239,49 @@ CONFIG_MTD_CFI_NOSWAP=y
# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
# CONFIG_MTD_CFI_GEOMETRY 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=y
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
+# CONFIG_MTD_XIP is not set
#
# Mapping drivers for chip access
#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
# CONFIG_MTD_PHYSMAP is not set
-# CONFIG_MTD_NORA is not set
# CONFIG_MTD_ARM_INTEGRATOR is not set
CONFIG_MTD_SA1100=y
# CONFIG_MTD_EDB7312 is not set
-CONFIG_MTD_PCMCIA=y
-# CONFIG_MTD_UCLINUX is not set
#
# Self-contained MTD device drivers
#
# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
# CONFIG_MTD_MTDRAM is not set
# CONFIG_MTD_BLKMTD is not set
+# CONFIG_MTD_BLOCK2MTD is not set
#
# Disk-On-Chip Device Drivers
#
-# CONFIG_MTD_DOC1000 is not set
# CONFIG_MTD_DOC2000 is not set
# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
#
# NAND Flash Device Drivers
@@ -244,7 +289,12 @@ CONFIG_MTD_PCMCIA=y
# CONFIG_MTD_NAND is not set
#
-# Plug and Play configuration
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
#
# CONFIG_PNP is not set
@@ -253,11 +303,94 @@ CONFIG_MTD_PCMCIA=y
#
# CONFIG_BLK_DEV_FD is not set
# CONFIG_BLK_DEV_XD is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
# CONFIG_BLK_DEV_LOOP is not set
# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_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_INITRAMFS_SOURCE=""
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+# 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
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_SCSI_7000FASST is not set
+# CONFIG_SCSI_AHA152X is not set
+# CONFIG_SCSI_AHA1542 is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_IN2000 is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DTC3280 is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
+# CONFIG_SCSI_NCR53C406A is not set
+# CONFIG_SCSI_PAS16 is not set
+# CONFIG_SCSI_PSI240I is not set
+# CONFIG_SCSI_QLOGIC_FAS is not set
+# CONFIG_SCSI_SYM53C416 is not set
+# CONFIG_SCSI_T128 is not set
+# CONFIG_SCSI_U14_34F 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)
@@ -265,14 +398,30 @@ CONFIG_BLK_DEV_INITRD=y
# CONFIG_MD is not set
#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
# Networking options
#
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
# CONFIG_NETLINK_DEV is not set
-# CONFIG_NETFILTER is not set
-# CONFIG_FILTER is not set
CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
CONFIG_INET=y
# CONFIG_IP_MULTICAST is not set
# CONFIG_IP_ADVANCED_ROUTER is not set
@@ -280,56 +429,70 @@ CONFIG_INET=y
# CONFIG_NET_IPIP is not set
# CONFIG_NET_IPGRE is not set
# CONFIG_ARPD is not set
-# CONFIG_INET_ECN is not set
# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_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_IPV6_SCTP__=y
# CONFIG_IP_SCTP is not set
# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
# CONFIG_VLAN_8021Q is not set
-# CONFIG_LLC is not set
# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
#
# QoS and/or fair queueing
#
# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
#
-# Network device support
+# Network testing
#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
#
# ARCnet devices
#
# CONFIG_ARCNET is not set
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
#
# Ethernet (10 or 100Mbit)
#
CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_LANCE is not set
CONFIG_NET_VENDOR_SMC=y
# CONFIG_WD80x3 is not set
# CONFIG_ULTRA is not set
+CONFIG_SMC91X=y
CONFIG_SMC9194=y
# CONFIG_NET_VENDOR_RACAL is not set
# CONFIG_AT1700 is not set
@@ -342,27 +505,20 @@ CONFIG_SMC9194=y
#
# Ethernet (1000 Mbit)
#
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
#
-# Wireless LAN (non-hamradio)
+# Ethernet (10000 Mbit)
#
-# CONFIG_NET_RADIO is not set
#
# Token Ring devices
#
# CONFIG_TR is not set
-# CONFIG_NET_FC is not set
-# CONFIG_SHAPER is not set
#
-# Wan interfaces
+# Wireless LAN (non-hamradio)
#
-# CONFIG_WAN is not set
+# CONFIG_NET_RADIO is not set
#
# PCMCIA network device support
@@ -376,37 +532,20 @@ CONFIG_PCMCIA_PCNET=y
# CONFIG_PCMCIA_SMC91C92 is not set
# CONFIG_PCMCIA_XIRC2PS is not set
# CONFIG_PCMCIA_AXNET is not set
-# CONFIG_NET_PCMCIA_RADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
#
-# SCSI support
-#
-# CONFIG_SCSI is not set
-
-#
-# I2O device support
+# Wan interfaces
#
-# CONFIG_I2O is not set
+# 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
#
# ISDN subsystem
#
-# CONFIG_ISDN_BOOL is not set
+# CONFIG_ISDN is not set
#
# Input device support
@@ -416,12 +555,14 @@ CONFIG_INPUT=y
#
# Userland interfaces
#
-# CONFIG_INPUT_MOUSEDEV is not set
+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=y
CONFIG_INPUT_TSDEV_SCREEN_X=240
CONFIG_INPUT_TSDEV_SCREEN_Y=320
-CONFIG_INPUT_TSLIBDEV=y
# CONFIG_INPUT_EVDEV is not set
# CONFIG_INPUT_EVBUG is not set
@@ -431,10 +572,11 @@ CONFIG_INPUT_TSLIBDEV=y
# CONFIG_GAMEPORT is not set
CONFIG_SOUND_GAMEPORT=y
CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
CONFIG_SERIO_SERPORT=m
# CONFIG_SERIO_CT82C710 is not set
CONFIG_SERIO_SA1111=y
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
#
# Input Device Drivers
@@ -442,6 +584,7 @@ CONFIG_SERIO_SA1111=y
CONFIG_INPUT_KEYBOARD=y
CONFIG_KEYBOARD_ATKBD=y
# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
# CONFIG_KEYBOARD_XTKBD is not set
# CONFIG_KEYBOARD_NEWTON is not set
# CONFIG_INPUT_MOUSE is not set
@@ -466,7 +609,6 @@ CONFIG_SERIAL_NONSTANDARD=y
# CONFIG_MOXA_INTELLIO is not set
# CONFIG_MOXA_SMARTIO is not set
# CONFIG_ISI is not set
-# CONFIG_SYNCLINK is not set
# CONFIG_SYNCLINKMP is not set
# CONFIG_N_HDLC is not set
# CONFIG_RISCOM8 is not set
@@ -481,6 +623,7 @@ CONFIG_SERIAL_NONSTANDARD=y
CONFIG_SERIAL_8250=y
# CONFIG_SERIAL_8250_CONSOLE is not set
CONFIG_SERIAL_8250_CS=y
+CONFIG_SERIAL_8250_NR_UARTS=4
# CONFIG_SERIAL_8250_EXTENDED is not set
#
@@ -491,65 +634,45 @@ CONFIG_SERIAL_SA1100_CONSOLE=y
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=32
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=64
#
-# I2C support
+# IPMI
#
-CONFIG_I2C=y
-CONFIG_I2C_ALGOBIT=y
-# CONFIG_SCx200_ACB is not set
-CONFIG_I2C_BIT_SA1100_GPIO=y
-# CONFIG_I2C_ALGOPCF is not set
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_PROC=y
+# CONFIG_IPMI_HANDLER is not set
#
-# L3 serial bus support
+# Watchdog Cards
#
-CONFIG_L3=y
-CONFIG_L3_ALGOBIT=y
-CONFIG_L3_BIT_SA1100_GPIO=y
-CONFIG_BIT_SA1100_GPIO=y
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
#
-# Mice
+# Watchdog Device Drivers
#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_QIC02_TAPE is not set
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_SA1100_WATCHDOG=m
#
-# Watchdog Cards
+# ISA-based Watchdog Cards
#
-CONFIG_WATCHDOG=y
-# CONFIG_WATCHDOG_NOWAYOUT is not set
-# CONFIG_SOFT_WATCHDOG is not set
-# CONFIG_WDT is not set
-# CONFIG_WDTPCI is not set
# CONFIG_PCWATCHDOG is not set
-# CONFIG_ACQUIRE_WDT is not set
-# CONFIG_ADVANTECH_WDT is not set
-CONFIG_SA1100_WATCHDOG=m
-# CONFIG_EUROTECH_WDT is not set
-# CONFIG_IB700_WDT is not set
# CONFIG_MIXCOMWD is not set
-# CONFIG_SCx200_WDT is not set
-# CONFIG_60XX_WDT is not set
-# CONFIG_W83877F_WDT is not set
-# CONFIG_MACHZ_WDT is not set
+# CONFIG_WDT is not set
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
# CONFIG_NVRAM is not set
# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
-CONFIG_SA1100_RTC=y
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
#
# Ftape, the floppy tape device driver
#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
# CONFIG_DRM is not set
#
@@ -559,154 +682,110 @@ CONFIG_SA1100_RTC=y
# CONFIG_RAW_DRIVER is not set
#
-# Multimedia devices
+# I2C support
#
-# CONFIG_VIDEO_DEV is not set
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
#
-# File systems
+# I2C Algorithms
#
-# CONFIG_QUOTA is not set
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_JBD is not set
-CONFIG_FAT_FS=m
-CONFIG_MSDOS_FS=m
-CONFIG_VFAT_FS=m
-# CONFIG_EFS_FS is not set
-# CONFIG_JFFS_FS is not set
-CONFIG_JFFS2_FS=y
-CONFIG_JFFS2_FS_DEBUG=0
-# CONFIG_JFFS2_FS_NAND is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_TMPFS is not set
-CONFIG_RAMFS=y
-# CONFIG_ISO9660_FS is not set
-# CONFIG_JFS_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_NTFS_FS is not set
-# CONFIG_HPFS_FS is not set
-CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS=y
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_ROMFS_FS is not set
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UDF_FS is not set
-# CONFIG_UFS_FS is not set
-# CONFIG_XFS_FS is not set
+CONFIG_I2C_ALGOBIT=y
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ELEKTOR is not set
+# CONFIG_I2C_ISA is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Hardware Sensors Chip support
+#
+# CONFIG_I2C_SENSOR 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_ASB100 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+
+#
+# Other I2C Chip support
+#
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
#
-# Network File Systems
+# Misc devices
#
-# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
-CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
-# CONFIG_NFS_V4 is not set
-# CONFIG_NFSD is not set
-CONFIG_SUNRPC=y
-CONFIG_LOCKD=y
-# CONFIG_EXPORTFS is not set
-# CONFIG_CIFS is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_AFS_FS is not set
#
-# Partition Types
+# Multimedia devices
#
-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
-CONFIG_NLS=y
+# CONFIG_VIDEO_DEV is not set
#
-# Native Language Support
+# Digital Video Broadcasting Devices
#
-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_ISO8859_1=m
-# CONFIG_NLS_ISO8859_2 is not set
-# CONFIG_NLS_ISO8859_3 is not set
-# CONFIG_NLS_ISO8859_4 is not set
-# CONFIG_NLS_ISO8859_5 is not set
-# CONFIG_NLS_ISO8859_6 is not set
-# CONFIG_NLS_ISO8859_7 is not set
-# CONFIG_NLS_ISO8859_9 is not set
-# CONFIG_NLS_ISO8859_13 is not set
-# CONFIG_NLS_ISO8859_14 is not set
-# CONFIG_NLS_ISO8859_15 is not set
-# CONFIG_NLS_KOI8_R is not set
-# CONFIG_NLS_KOI8_U is not set
-# CONFIG_NLS_UTF8 is not set
+# CONFIG_DVB is not set
#
-# Console drivers
+# Graphics support
#
-# CONFIG_VGA_CONSOLE is not set
+CONFIG_FB=y
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+CONFIG_FB_SA1100=y
+# CONFIG_FB_VIRTUAL is not set
#
-# Frame-buffer support
+# Console display driver support
#
-CONFIG_FB=y
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
CONFIG_DUMMY_CONSOLE=y
-CONFIG_FB_SA1100=y
-# CONFIG_FB_VIRTUAL is not set
-# CONFIG_FBCON_ADVANCED is not set
-CONFIG_FBCON_CFB2=y
-CONFIG_FBCON_CFB4=y
-CONFIG_FBCON_CFB8=y
-CONFIG_FBCON_CFB16=y
-CONFIG_FBCON_FONTWIDTH8_ONLY=y
-# CONFIG_FONT_SUN8x16 is not set
-CONFIG_FBCON_FONTS=y
-# CONFIG_FONT_8x8 is not set
-# CONFIG_FONT_8x16 is not set
-# CONFIG_FONT_PEARL_8x8 is not set
-CONFIG_FONT_ACORN_8x8=y
-# CONFIG_FONT_MINI_4x6 is not set
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+# CONFIG_LOGO is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
# Sound
@@ -714,48 +793,24 @@ CONFIG_FONT_ACORN_8x8=y
CONFIG_SOUND=y
#
+# Advanced Linux Sound Architecture
+#
+# CONFIG_SND is not set
+
+#
# Open Sound System
#
CONFIG_SOUND_PRIME=y
# CONFIG_SOUND_BT878 is not set
# CONFIG_SOUND_FUSION is not set
# CONFIG_SOUND_CS4281 is not set
-# CONFIG_SOUND_ESSSOLO1 is not set
-# CONFIG_SOUND_MAESTRO is not set
# CONFIG_SOUND_SONICVIBES is not set
# CONFIG_SOUND_TRIDENT is not set
# CONFIG_SOUND_MSNDCLAS is not set
# CONFIG_SOUND_MSNDPIN is not set
-CONFIG_SOUND_SA1100=y
-CONFIG_SOUND_UDA1341=y
-CONFIG_SOUND_ASSABET_UDA1341=y
-CONFIG_SOUND_SA1111_UDA1341=y
-# CONFIG_SOUND_SA1100SSP is not set
# CONFIG_SOUND_OSS is not set
# CONFIG_SOUND_TVMIXER is not set
-
-#
-# Advanced Linux Sound Architecture
-#
-# CONFIG_SND is not set
-
-#
-# Misc devices
-#
-
-#
-# Multimedia Capabilities Port drivers
-#
-CONFIG_MCP=y
-CONFIG_MCP_SA1100=y
-CONFIG_MCP_UCB1200=y
-CONFIG_MCP_UCB1200_AUDIO=m
-CONFIG_MCP_UCB1200_TS=y
-
-#
-# Console Switches
-#
-# CONFIG_SWITCHES is not set
+# CONFIG_SOUND_AD1980 is not set
#
# USB support
@@ -767,17 +822,20 @@ CONFIG_USB_DEBUG=y
# Miscellaneous USB options
#
CONFIG_USB_DEVICEFS=y
-# CONFIG_USB_LONG_TIMEOUT is not set
# CONFIG_USB_BANDWIDTH is not set
# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND 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
#
-# CONFIG_USB_EHCI_HCD is not set
CONFIG_USB_OHCI_HCD=m
-# CONFIG_USB_UHCI_HCD_ALT is not set
-# CONFIG_USB_SL811HS is not set
+# 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
@@ -789,11 +847,21 @@ CONFIG_USB_OHCI_HCD=m
# CONFIG_USB_PRINTER is not set
#
-# SCSI support is needed for USB Storage
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_RW_DETECT 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 Human Interface Devices (HID)
+# USB Input Devices
#
# CONFIG_USB_HID is not set
@@ -804,14 +872,18 @@ CONFIG_USB_OHCI_HCD=m
CONFIG_USB_MOUSE=m
# CONFIG_USB_AIPTEK is not set
# CONFIG_USB_WACOM is not set
+# CONFIG_USB_KBTAB is not set
# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_EGALAX is not set
# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
#
# USB Imaging devices
#
# CONFIG_USB_MDC800 is not set
-# CONFIG_USB_SCANNER is not set
+# CONFIG_USB_MICROTEK is not set
#
# USB Multimedia devices
@@ -823,14 +895,14 @@ CONFIG_USB_MOUSE=m
#
#
-# USB Network adaptors
+# USB Network Adapters
#
# CONFIG_USB_CATC is not set
-# CONFIG_USB_CDCETHER 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=m
#
# USB port drivers
@@ -844,37 +916,215 @@ CONFIG_USB_MOUSE=m
#
# USB Miscellaneous drivers
#
-# CONFIG_USB_TIGL is not set
+# 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_TEST is not set
#
-# Bluetooth support
+# USB ATM/DSL drivers
#
-# CONFIG_BT is not set
+
+#
+# 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_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_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# 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_NAND is not set
+# CONFIG_JFFS2_FS_NOR_ECC is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+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=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 is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
#
# Kernel hacking
#
-CONFIG_FRAME_POINTER=y
-CONFIG_DEBUG_USER=y
-# CONFIG_DEBUG_INFO is not set
CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_SLAB=y
CONFIG_MAGIC_SYSRQ=y
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_SCHEDSTATS is not set
+CONFIG_DEBUG_SLAB=y
# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_WAITQ 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_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_WAITQ is not set
CONFIG_DEBUG_ERRORS=y
-# CONFIG_KALLSYMS is not set
CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
#
# Security options
#
-CONFIG_SECURITY_CAPABILITIES=y
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
#
# Cryptographic options
@@ -882,8 +1132,14 @@ CONFIG_SECURITY_CAPABILITIES=y
# CONFIG_CRYPTO is not set
#
+# Hardware crypto devices
+#
+
+#
# Library routines
#
-# CONFIG_CRC32 is not set
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/arm/configs/netwinder_defconfig b/arch/arm/configs/netwinder_defconfig
index 1ed01995f9aae..6e81acf94c2f1 100644
--- a/arch/arm/configs/netwinder_defconfig
+++ b/arch/arm/configs/netwinder_defconfig
@@ -1,35 +1,50 @@
#
# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.12-rc1-bk2
+# Sun Mar 27 15:18:42 2005
#
CONFIG_ARM=y
CONFIG_MMU=y
CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_IOMAP=y
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
CONFIG_CLEAN_COMPILE=y
-CONFIG_STANDALONE=y
CONFIG_BROKEN_ON_SMP=y
#
# General setup
#
+CONFIG_LOCALVERSION=""
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
-CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_AUDIT is not set
+# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
# CONFIG_IKCONFIG 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_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
#
# Loadable module support
@@ -39,28 +54,27 @@ CONFIG_IOSCHED_DEADLINE=y
#
# System Type
#
-# CONFIG_ARCH_ADIFCC is not set
# CONFIG_ARCH_CLPS7500 is not set
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
-# CONFIG_ARCH_PXA 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
+# 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
-
-#
-# CLPS711X/EP721X Implementations
-#
-
-#
-# Epxa10db
-#
+# 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
#
# Footbridge Implementations
@@ -70,24 +84,6 @@ CONFIG_ARCH_FOOTBRIDGE=y
# CONFIG_ARCH_EBSA285_ADDIN is not set
# CONFIG_ARCH_EBSA285_HOST is not set
CONFIG_ARCH_NETWINDER=y
-
-#
-# IOP3xx Implementation Options
-#
-# CONFIG_ARCH_IOP310 is not set
-# CONFIG_ARCH_IOP321 is not set
-
-#
-# IOP3xx Chipset Features
-#
-
-#
-# Intel PXA250/210 Implementations
-#
-
-#
-# SA11x0 Implementations
-#
CONFIG_FOOTBRIDGE=y
CONFIG_FOOTBRIDGE_HOST=y
@@ -99,6 +95,7 @@ CONFIG_CPU_SA110=y
CONFIG_CPU_32v4=y
CONFIG_CPU_ABRT_EV4=y
CONFIG_CPU_CACHE_V4WB=y
+CONFIG_CPU_CACHE_VIVT=y
CONFIG_CPU_COPY_V4WB=y
CONFIG_CPU_TLB_V4WB=y
@@ -107,59 +104,90 @@ CONFIG_CPU_TLB_V4WB=y
#
#
-# General setup
+# Bus support
#
-CONFIG_PCI=y
CONFIG_ISA=y
CONFIG_ISA_DMA=y
-# CONFIG_ZBOOT_ROM is not set
-CONFIG_ZBOOT_ROM_TEXT=0
-CONFIG_ZBOOT_ROM_BSS=0
+CONFIG_PCI=y
CONFIG_PCI_LEGACY_PROC=y
CONFIG_PCI_NAMES=y
-# CONFIG_HOTPLUG is not set
#
-# At least one math emulation must be selected
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_PREEMPT is not set
+CONFIG_LEDS=y
+# CONFIG_LEDS_TIMER is not set
+CONFIG_LEDS_CPU=y
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="root=0x301"
+# 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=y
# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
#
-# Generic Driver Options
+# Power management options
#
# CONFIG_PM is not set
-# CONFIG_PREEMPT is not set
-# CONFIG_ARTHUR is not set
-CONFIG_CMDLINE="root=0x301"
-CONFIG_LEDS=y
-# CONFIG_LEDS_TIMER is not set
-CONFIG_LEDS_CPU=y
-CONFIG_ALIGNMENT_TRAP=y
+
+#
+# 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
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
#
# Parallel port support
#
CONFIG_PARPORT=y
CONFIG_PARPORT_PC=y
-CONFIG_PARPORT_PC_CML1=y
# CONFIG_PARPORT_SERIAL is not set
# CONFIG_PARPORT_PC_FIFO is not set
CONFIG_PARPORT_PC_SUPERIO=y
# CONFIG_PARPORT_ARC is not set
-# CONFIG_PARPORT_OTHER is not set
+# CONFIG_PARPORT_GSC is not set
# CONFIG_PARPORT_1284 is not set
#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
# Plug and Play support
#
# CONFIG_PNP is not set
@@ -174,11 +202,87 @@ CONFIG_PARPORT_PC_SUPERIO=y
# CONFIG_BLK_CPQ_CISS_DA is not set
# CONFIG_BLK_DEV_DAC960 is not set
# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# 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=y
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_IDEPCI=y
+# CONFIG_IDEPCI_SHARE_IRQ is not set
+# CONFIG_BLK_DEV_OFFBOARD is not set
+# CONFIG_BLK_DEV_GENERIC is not set
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_SL82C105=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_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_IDE_CHIPSETS is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
#
# Multi-device support (RAID and LVM)
@@ -186,6 +290,20 @@ CONFIG_BLK_DEV_LOOP=y
# CONFIG_MD is not set
#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
# Networking support
#
CONFIG_NET=y
@@ -208,19 +326,19 @@ CONFIG_IP_PNP_RARP=y
# CONFIG_NET_IPIP is not set
# CONFIG_NET_IPGRE is not set
# CONFIG_ARPD is not set
-# CONFIG_INET_ECN is not set
# CONFIG_SYN_COOKIES is not set
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
#
# IP: Virtual Server Configuration
#
# CONFIG_IP_VS is not set
# CONFIG_IPV6 is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
CONFIG_NETFILTER=y
# CONFIG_NETFILTER_DEBUG is not set
@@ -228,6 +346,9 @@ CONFIG_NETFILTER=y
# IP: Netfilter Configuration
#
CONFIG_IP_NF_CONNTRACK=y
+# CONFIG_IP_NF_CT_ACCT is not set
+# CONFIG_IP_NF_CONNTRACK_MARK is not set
+# CONFIG_IP_NF_CT_PROTO_SCTP is not set
CONFIG_IP_NF_FTP=y
# CONFIG_IP_NF_IRC is not set
# CONFIG_IP_NF_TFTP is not set
@@ -252,21 +373,28 @@ CONFIG_IP_NF_IPTABLES=y
# CONFIG_IP_NF_MATCH_STATE is not set
# CONFIG_IP_NF_MATCH_CONNTRACK is not set
# CONFIG_IP_NF_MATCH_OWNER is not set
+# 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_COMMENT is not set
+# CONFIG_IP_NF_MATCH_HASHLIMIT is not set
# CONFIG_IP_NF_FILTER is not set
-# CONFIG_IP_NF_NAT is not set
-# CONFIG_IP_NF_MANGLE is not set
# CONFIG_IP_NF_TARGET_LOG is not set
# CONFIG_IP_NF_TARGET_ULOG is not set
# CONFIG_IP_NF_TARGET_TCPMSS is not set
+# CONFIG_IP_NF_NAT is not set
+# CONFIG_IP_NF_MANGLE is not set
+# CONFIG_IP_NF_RAW is not set
# CONFIG_IP_NF_ARPTABLES is not set
#
# SCTP Configuration (EXPERIMENTAL)
#
-CONFIG_IPV6_SCTP__=y
# 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
@@ -275,23 +403,23 @@ CONFIG_IPV6_SCTP__=y
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
#
# QoS and/or fair queueing
#
# CONFIG_NET_SCHED is not set
+# 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
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
@@ -299,16 +427,21 @@ CONFIG_NETDEVICES=y
# CONFIG_ETHERTAP is not set
#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
# Ethernet (10 or 100Mbit)
#
CONFIG_NET_ETHERNET=y
CONFIG_MII=y
-# CONFIG_SMC91X is not set
# CONFIG_HAPPYMEAL is not set
# CONFIG_SUNGEM is not set
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_LANCE is not set
# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_SMC91X is not set
# CONFIG_NET_VENDOR_RACAL is not set
#
@@ -319,6 +452,7 @@ CONFIG_NET_TULIP=y
CONFIG_TULIP=y
# CONFIG_TULIP_MWI is not set
CONFIG_TULIP_MMIO=y
+# CONFIG_TULIP_NAPI is not set
# CONFIG_DE4X5 is not set
# CONFIG_WINBOND_840 is not set
# CONFIG_DM9102 is not set
@@ -333,6 +467,7 @@ CONFIG_NET_PCI=y
# CONFIG_AC3200 is not set
# CONFIG_APRICOT is not set
# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
# CONFIG_CS89x0 is not set
# CONFIG_DGRS is not set
# CONFIG_EEPRO100 is not set
@@ -359,130 +494,42 @@ CONFIG_NE2K_PCI=y
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
# CONFIG_R8169 is not set
-# CONFIG_SIS190 is not set
# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
# CONFIG_TIGON3 is not set
#
# Ethernet (10000 Mbit)
#
# CONFIG_IXGB is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PLIP is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-# CONFIG_HOSTAP is not set
+# CONFIG_S2IO is not set
#
# Token Ring devices
#
# CONFIG_TR is not set
-# CONFIG_RCPCI is not set
-# CONFIG_SHAPER is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
-# Bluetooth support
-#
-# CONFIG_BT is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-CONFIG_IDE=y
-CONFIG_BLK_DEV_IDE=y
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
-CONFIG_BLK_DEV_IDEDISK=y
-CONFIG_IDEDISK_MULTI_MODE=y
-# CONFIG_IDEDISK_STROKE is not set
-# CONFIG_BLK_DEV_IDECD is not set
-# CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
-# CONFIG_IDE_TASK_IOCTL is not set
-# CONFIG_IDE_TASKFILE_IO is not set
-
-#
-# IDE chipset support/bugfixes
-#
-CONFIG_BLK_DEV_IDEPCI=y
-# CONFIG_IDEPCI_SHARE_IRQ is not set
-# CONFIG_BLK_DEV_OFFBOARD is not set
-# CONFIG_BLK_DEV_GENERIC is not set
-# CONFIG_BLK_DEV_OPTI621 is not set
-CONFIG_BLK_DEV_SL82C105=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_ADMA=y
-# CONFIG_BLK_DEV_AEC62XX is not set
-# CONFIG_BLK_DEV_ALI15X3 is not set
-# CONFIG_BLK_DEV_AMD74XX is not set
-# CONFIG_BLK_DEV_CMD64X is not set
-# CONFIG_BLK_DEV_TRIFLEX is not set
-# CONFIG_BLK_DEV_CY82C693 is not set
-# CONFIG_BLK_DEV_CS5520 is not set
-# CONFIG_BLK_DEV_CS5530 is not set
-# CONFIG_BLK_DEV_HPT34X is not set
-# CONFIG_BLK_DEV_HPT366 is not set
-# CONFIG_BLK_DEV_SC1200 is not set
-# CONFIG_BLK_DEV_PIIX is not set
-# CONFIG_BLK_DEV_NS87415 is not set
-# CONFIG_BLK_DEV_PDC202XX_OLD is not set
-# CONFIG_BLK_DEV_PDC202XX_NEW is not set
-# CONFIG_BLK_DEV_SVWKS is not set
-# CONFIG_BLK_DEV_SIIMAGE is not set
-# CONFIG_BLK_DEV_SLC90E66 is not set
-# CONFIG_BLK_DEV_TRM290 is not set
-# CONFIG_BLK_DEV_VIA82CXXX is not set
-# CONFIG_IDE_CHIPSETS is not set
-CONFIG_BLK_DEV_IDEDMA=y
-# CONFIG_IDEDMA_IVB is not set
-CONFIG_IDEDMA_AUTO=y
-# CONFIG_BLK_DEV_HD is not set
-
-#
-# SCSI device support
-#
-# CONFIG_SCSI is not set
#
-# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+# Wireless LAN (non-hamradio)
#
-# CONFIG_IEEE1394 is not set
+# CONFIG_NET_RADIO is not set
#
-# I2O device support
+# Wan interfaces
#
-# CONFIG_I2O is not set
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PLIP is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
#
# ISDN subsystem
#
-# CONFIG_ISDN_BOOL is not set
+# CONFIG_ISDN is not set
#
# Input device support
@@ -498,44 +545,44 @@ 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_TSLIBDEV is not set
# CONFIG_INPUT_EVDEV is not set
# CONFIG_INPUT_EVBUG is not set
#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-CONFIG_SERIO_I8042=y
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PARKBD is not set
-# CONFIG_SERIO_PCIPS2 is not set
-
-#
# Input Device Drivers
#
CONFIG_INPUT_KEYBOARD=y
CONFIG_KEYBOARD_ATKBD=y
# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
# CONFIG_KEYBOARD_XTKBD is not set
# CONFIG_KEYBOARD_NEWTON is not set
CONFIG_INPUT_MOUSE=y
CONFIG_MOUSE_PS2=y
-# CONFIG_MOUSE_PS2_SYNAPTICS is not set
CONFIG_MOUSE_SERIAL=y
# CONFIG_MOUSE_INPORT is not set
# CONFIG_MOUSE_LOGIBM is not set
# CONFIG_MOUSE_PC110PAD is not set
+# CONFIG_MOUSE_VSXXXAA is not set
# CONFIG_INPUT_JOYSTICK is not set
# CONFIG_INPUT_TOUCHSCREEN is not set
CONFIG_INPUT_MISC=y
-# CONFIG_INPUT_PCSPKR is not set
CONFIG_INPUT_UINPUT=y
#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_PARKBD is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
+#
# Character devices
#
CONFIG_VT=y
@@ -554,78 +601,47 @@ CONFIG_SERIAL_8250_NR_UARTS=4
#
# Non-8250 serial port support
#
-# CONFIG_SERIAL_DZ is not set
# CONFIG_SERIAL_21285 is not set
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
CONFIG_PRINTER=y
# CONFIG_LP_CONSOLE is not set
# CONFIG_PPDEV is not set
# CONFIG_TIPAR is not set
#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# I2C Algorithms
-#
-
-#
-# I2C Hardware Bus support
-#
-
-#
-# I2C Hardware Sensors Chip support
+# IPMI
#
-# CONFIG_I2C_SENSOR is not set
+# CONFIG_IPMI_HANDLER is not set
#
-# L3 serial bus support
+# Watchdog Cards
#
-# CONFIG_L3 is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
#
-# Mice
+# Watchdog Device Drivers
#
-CONFIG_BUSMOUSE=y
-# CONFIG_QIC02_TAPE is not set
+# CONFIG_SOFT_WATCHDOG is not set
+# CONFIG_21285_WATCHDOG is not set
+CONFIG_977_WATCHDOG=y
#
-# IPMI
+# ISA-based Watchdog Cards
#
-# CONFIG_IPMI_HANDLER is not set
+# CONFIG_PCWATCHDOG is not set
+# CONFIG_MIXCOMWD is not set
+# CONFIG_WDT is not set
#
-# Watchdog Cards
+# PCI-based Watchdog Cards
#
-CONFIG_WATCHDOG=y
-# CONFIG_WATCHDOG_NOWAYOUT is not set
-# CONFIG_SOFT_WATCHDOG is not set
-# CONFIG_WDT is not set
+# CONFIG_PCIPCWATCHDOG is not set
# CONFIG_WDTPCI is not set
-# CONFIG_PCWATCHDOG is not set
-# CONFIG_ACQUIRE_WDT is not set
-# CONFIG_ADVANTECH_WDT is not set
-# CONFIG_21285_WATCHDOG is not set
-CONFIG_977_WATCHDOG=y
-# CONFIG_EUROTECH_WDT is not set
-# CONFIG_IB700_WDT is not set
-# CONFIG_MIXCOMWD is not set
-# CONFIG_SCx200_WDT is not set
-# CONFIG_60XX_WDT is not set
-# CONFIG_W83877F_WDT is not set
-# CONFIG_MACHZ_WDT is not set
-# CONFIG_SC520_WDT is not set
-# CONFIG_AMD7XX_TCO is not set
-# CONFIG_ALIM7101_WDT is not set
-# CONFIG_ALIM1535_WDT is not set
-# CONFIG_SC1200_WDT is not set
-# CONFIG_WAFER_WDT is not set
-# CONFIG_CPU5_WDT is not set
CONFIG_DS1620=y
CONFIG_NWBUTTON=y
CONFIG_NWBUTTON_REBOOT=y
@@ -639,12 +655,24 @@ CONFIG_RTC=y
#
# Ftape, the floppy tape device driver
#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
# CONFIG_DRM is not set
# CONFIG_RAW_DRIVER is not set
#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Misc devices
+#
+
+#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -655,6 +683,137 @@ CONFIG_RTC=y
# CONFIG_DVB is not set
#
+# Graphics support
+#
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+CONFIG_FB_SOFT_CURSOR=y
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+CONFIG_FB_CYBER2000=y
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT 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 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_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+# CONFIG_FONT_ACORN_8x8 is not set
+# CONFIG_FONT_MINI_4x6 is not set
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+
+#
+# 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=y
+
+#
+# Advanced Linux Sound Architecture
+#
+# CONFIG_SND is not set
+
+#
+# Open Sound System
+#
+CONFIG_SOUND_PRIME=y
+# CONFIG_SOUND_BT878 is not set
+# CONFIG_SOUND_CMPCI is not set
+# CONFIG_SOUND_EMU10K1 is not set
+# CONFIG_SOUND_FUSION is not set
+# CONFIG_SOUND_CS4281 is not set
+# CONFIG_SOUND_ES1370 is not set
+# CONFIG_SOUND_ES1371 is not set
+# CONFIG_SOUND_ESSSOLO1 is not set
+# CONFIG_SOUND_MAESTRO is not set
+# CONFIG_SOUND_MAESTRO3 is not set
+# CONFIG_SOUND_ICH is not set
+# CONFIG_SOUND_SONICVIBES is not set
+# CONFIG_SOUND_TRIDENT is not set
+# CONFIG_SOUND_VIA82CXXX is not set
+CONFIG_SOUND_OSS=y
+CONFIG_SOUND_TRACEINIT=y
+CONFIG_SOUND_DMAP=y
+# CONFIG_SOUND_AD1816 is not set
+# CONFIG_SOUND_AD1889 is not set
+# CONFIG_SOUND_SGALAXY is not set
+# CONFIG_SOUND_ADLIB is not set
+# CONFIG_SOUND_ACI_MIXER is not set
+# CONFIG_SOUND_CS4232 is not set
+# CONFIG_SOUND_SSCAPE is not set
+# CONFIG_SOUND_GUS is not set
+# CONFIG_SOUND_VMIDI is not set
+# CONFIG_SOUND_TRIX is not set
+# CONFIG_SOUND_MSS is not set
+# CONFIG_SOUND_MPU401 is not set
+# CONFIG_SOUND_NM256 is not set
+# CONFIG_SOUND_MAD16 is not set
+# CONFIG_SOUND_PAS is not set
+# CONFIG_SOUND_PSS is not set
+# CONFIG_SOUND_SB is not set
+# CONFIG_SOUND_AWE32_SYNTH is not set
+# CONFIG_SOUND_MAUI is not set
+CONFIG_SOUND_YM3812=y
+# CONFIG_SOUND_OPL3SA1 is not set
+# CONFIG_SOUND_OPL3SA2 is not set
+# CONFIG_SOUND_YMFPCI is not set
+# CONFIG_SOUND_UART6850 is not set
+# CONFIG_SOUND_AEDSP16 is not set
+CONFIG_SOUND_WAVEARTIST=y
+# CONFIG_SOUND_ALI5455 is not set
+# CONFIG_SOUND_FORTE is not set
+# CONFIG_SOUND_RME96XX is not set
+# CONFIG_SOUND_AD1980 is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
# MMC/SD Card support
#
# CONFIG_MMC is not set
@@ -668,10 +827,15 @@ CONFIG_EXT2_FS=y
# CONFIG_JBD is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
# CONFIG_XFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
CONFIG_AUTOFS_FS=y
# CONFIG_AUTOFS4_FS is not set
@@ -686,17 +850,19 @@ CONFIG_JOLIET=y
#
# DOS/FAT/NT Filesystems
#
-# CONFIG_FAT_FS is not set
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
# CONFIG_NTFS_FS is not set
#
# Pseudo filesystems
#
CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS=y
# CONFIG_DEVPTS_FS_XATTR is not set
CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
@@ -706,6 +872,7 @@ CONFIG_RAMFS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
# CONFIG_BEFS_FS is not set
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
@@ -733,12 +900,13 @@ CONFIG_LOCKD_V4=y
CONFIG_EXPORTFS=y
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
CONFIG_SMB_FS=y
# 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_INTERMEZZO_FS is not set
# CONFIG_AFS_FS is not set
#
@@ -756,17 +924,15 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_SOLARIS_X86_PARTITION is not set
# CONFIG_UNIXWARE_DISKLABEL is not set
# CONFIG_LDM_PARTITION is not set
-# CONFIG_NEC98_PARTITION is not set
# CONFIG_SGI_PARTITION is not set
# CONFIG_ULTRIX_PARTITION is not set
# CONFIG_SUN_PARTITION is not set
# CONFIG_EFI_PARTITION is not set
-CONFIG_SMB_NLS=y
-CONFIG_NLS=y
#
# Native Language Support
#
+CONFIG_NLS=y
CONFIG_NLS_DEFAULT="iso8859-1"
CONFIG_NLS_CODEPAGE_437=y
# CONFIG_NLS_CODEPAGE_737 is not set
@@ -791,6 +957,7 @@ CONFIG_NLS_CODEPAGE_852=y
# CONFIG_NLS_ISO8859_8 is not set
# CONFIG_NLS_CODEPAGE_1250 is not set
# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
CONFIG_NLS_ISO8859_1=y
CONFIG_NLS_ISO8859_2=y
# CONFIG_NLS_ISO8859_3 is not set
@@ -807,157 +974,73 @@ CONFIG_NLS_ISO8859_15=y
CONFIG_NLS_UTF8=y
#
-# Graphics support
-#
-CONFIG_FB=y
-CONFIG_FB_CYBER2000=y
-# CONFIG_FB_IMSTT is not set
-# CONFIG_FB_RIVA is not set
-# CONFIG_FB_MATROX is not set
-# CONFIG_FB_RADEON is not set
-# CONFIG_FB_ATY128 is not set
-# CONFIG_FB_ATY is not set
-# CONFIG_FB_SIS is not set
-# CONFIG_FB_NEOMAGIC is not set
-# CONFIG_FB_3DFX is not set
-# CONFIG_FB_VOODOO1 is not set
-# CONFIG_FB_TRIDENT is not set
-# CONFIG_FB_VIRTUAL is not set
-
-#
-# Console display driver support
-#
-CONFIG_VGA_CONSOLE=y
-# CONFIG_MDA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_PCI_CONSOLE=y
-CONFIG_FONTS=y
-CONFIG_FONT_8x8=y
-CONFIG_FONT_8x16=y
-# CONFIG_FONT_6x11 is not set
-# CONFIG_FONT_PEARL_8x8 is not set
-# CONFIG_FONT_ACORN_8x8 is not set
-# CONFIG_FONT_MINI_4x6 is not set
-# CONFIG_FONT_SUN8x16 is not set
-# CONFIG_FONT_SUN12x22 is not set
-
-#
-# Logo configuration
-#
-CONFIG_LOGO=y
-CONFIG_LOGO_LINUX_MONO=y
-CONFIG_LOGO_LINUX_VGA16=y
-CONFIG_LOGO_LINUX_CLUT224=y
-
-#
-# Sound
-#
-CONFIG_SOUND=y
-
-#
-# Advanced Linux Sound Architecture
-#
-# CONFIG_SND is not set
-
-#
-# Open Sound System
-#
-CONFIG_SOUND_PRIME=y
-# CONFIG_SOUND_BT878 is not set
-# CONFIG_SOUND_CMPCI is not set
-# CONFIG_SOUND_EMU10K1 is not set
-# CONFIG_SOUND_FUSION is not set
-# CONFIG_SOUND_CS4281 is not set
-# CONFIG_SOUND_ES1370 is not set
-# CONFIG_SOUND_ES1371 is not set
-# CONFIG_SOUND_ESSSOLO1 is not set
-# CONFIG_SOUND_MAESTRO is not set
-# CONFIG_SOUND_MAESTRO3 is not set
-# CONFIG_SOUND_ICH is not set
-# CONFIG_SOUND_SONICVIBES is not set
-# CONFIG_SOUND_TRIDENT is not set
-# CONFIG_SOUND_VIA82CXXX is not set
-CONFIG_SOUND_OSS=y
-CONFIG_SOUND_TRACEINIT=y
-CONFIG_SOUND_DMAP=y
-# CONFIG_SOUND_AD1816 is not set
-# CONFIG_SOUND_AD1889 is not set
-# CONFIG_SOUND_SGALAXY is not set
-# CONFIG_SOUND_ADLIB is not set
-# CONFIG_SOUND_ACI_MIXER is not set
-# CONFIG_SOUND_CS4232 is not set
-# CONFIG_SOUND_SSCAPE is not set
-# CONFIG_SOUND_GUS is not set
-# CONFIG_SOUND_VMIDI is not set
-# CONFIG_SOUND_TRIX is not set
-# CONFIG_SOUND_MSS is not set
-# CONFIG_SOUND_MPU401 is not set
-# CONFIG_SOUND_NM256 is not set
-# CONFIG_SOUND_MAD16 is not set
-# CONFIG_SOUND_PAS is not set
-# CONFIG_SOUND_PSS is not set
-# CONFIG_SOUND_SB is not set
-# CONFIG_SOUND_AWE32_SYNTH is not set
-# CONFIG_SOUND_MAUI is not set
-CONFIG_SOUND_YM3812=y
-# CONFIG_SOUND_OPL3SA1 is not set
-# CONFIG_SOUND_OPL3SA2 is not set
-# CONFIG_SOUND_YMFPCI is not set
-# CONFIG_SOUND_UART6850 is not set
-# CONFIG_SOUND_AEDSP16 is not set
-CONFIG_SOUND_WAVEARTIST=y
-# CONFIG_SOUND_ALI5455 is not set
-# CONFIG_SOUND_FORTE is not set
-# CONFIG_SOUND_RME96XX is not set
-# CONFIG_SOUND_AD1980 is not set
-
-#
-# Misc devices
+# Profiling support
#
-
-#
-# Multimedia Capabilities Port drivers
-#
-# CONFIG_MCP is not set
-
-#
-# Console Switches
-#
-# CONFIG_SWITCHES is not set
-
-#
-# USB support
-#
-# CONFIG_USB is not set
-# CONFIG_USB_GADGET is not set
+# CONFIG_PROFILING is not set
#
# Kernel hacking
#
-CONFIG_FRAME_POINTER=y
-CONFIG_DEBUG_USER=y
-# CONFIG_DEBUG_INFO is not set
+# CONFIG_PRINTK_TIME is not set
CONFIG_DEBUG_KERNEL=y
-# CONFIG_DEBUG_SLAB is not set
CONFIG_MAGIC_SYSRQ=y
+CONFIG_LOG_BUF_SHIFT=14
+# 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_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
# CONFIG_DEBUG_WAITQ is not set
-# CONFIG_DEBUG_BUGVERBOSE is not set
# CONFIG_DEBUG_ERRORS is not set
# CONFIG_DEBUG_LL is not set
#
# Security options
#
+# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
#
# Cryptographic options
#
-# CONFIG_CRYPTO is not set
+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_CRC32=y
+# CONFIG_LIBCRC32C is not set
diff --git a/arch/arm/configs/omap_h2_1610_defconfig b/arch/arm/configs/omap_h2_1610_defconfig
index f569a6ff35a66..4e58d9341bce7 100644
--- a/arch/arm/configs/omap_h2_1610_defconfig
+++ b/arch/arm/configs/omap_h2_1610_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc2
-# Tue Feb 1 14:01:46 2005
+# Linux kernel version: 2.6.12-rc1-bk2
+# Sun Mar 27 17:52:41 2005
#
CONFIG_ARM=y
CONFIG_MMU=y
@@ -28,7 +28,6 @@ CONFIG_SYSVIPC=y
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
# CONFIG_HOTPLUG is not set
CONFIG_KOBJECT_UEVENT=y
# CONFIG_IKCONFIG is not set
@@ -36,6 +35,7 @@ CONFIG_KOBJECT_UEVENT=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
@@ -45,6 +45,7 @@ CONFIG_CC_ALIGN_LABELS=0
CONFIG_CC_ALIGN_LOOPS=0
CONFIG_CC_ALIGN_JUMPS=0
# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
#
# Loadable module support
@@ -110,6 +111,8 @@ CONFIG_MACH_OMAP_H2=y
CONFIG_OMAP_MUX=y
# CONFIG_OMAP_MUX_DEBUG is not set
CONFIG_OMAP_MUX_WARNINGS=y
+CONFIG_OMAP_MPU_TIMER=y
+# CONFIG_OMAP_32K_TIMER is not set
CONFIG_OMAP_LL_DEBUG_UART1=y
# CONFIG_OMAP_LL_DEBUG_UART2 is not set
# CONFIG_OMAP_LL_DEBUG_UART3 is not set
@@ -140,11 +143,8 @@ CONFIG_ARM_THUMB=y
# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
#
-# General setup
+# Bus support
#
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-# CONFIG_XIP_KERNEL is not set
#
# PCCARD (PCMCIA/CardBus) support
@@ -152,39 +152,57 @@ CONFIG_ZBOOT_ROM_BSS=0x0
# CONFIG_PCCARD is not set
#
-# PC-card bridges
+# Kernel Features
#
+CONFIG_PREEMPT=y
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
#
-# At least one math emulation must be selected
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="mem=32M console=ttyS0,115200n8 root=0801 ro init=/bin/sh"
+# 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
# CONFIG_VFP is not set
+
+#
+# Userspace binary formats
+#
CONFIG_BINFMT_ELF=y
CONFIG_BINFMT_AOUT=y
# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
#
-# Generic Driver Options
+# Power management options
#
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
-CONFIG_DEBUG_DRIVER=y
CONFIG_PM=y
-CONFIG_PREEMPT=y
# CONFIG_APM is not set
-# CONFIG_ARTHUR is not set
-CONFIG_CMDLINE="mem=32M console=ttyS0,115200n8 root=0801 ro init=/bin/sh"
-# CONFIG_LEDS is not set
-CONFIG_ALIGNMENT_TRAP=y
#
-# Parallel port support
+# Device Drivers
#
-# CONFIG_PARPORT is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+CONFIG_DEBUG_DRIVER=y
#
# Memory Technology Devices (MTD)
@@ -192,8 +210,8 @@ CONFIG_ALIGNMENT_TRAP=y
CONFIG_MTD=y
CONFIG_MTD_DEBUG=y
CONFIG_MTD_DEBUG_VERBOSE=3
-CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_REDBOOT_PARTS is not set
CONFIG_MTD_CMDLINE_PARTS=y
# CONFIG_MTD_AFS_PARTS is not set
@@ -263,6 +281,11 @@ CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_NAND is not set
#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
# Plug and Play support
#
@@ -291,11 +314,58 @@ CONFIG_IOSCHED_CFQ=y
CONFIG_ATA_OVER_ETH=m
#
+# SCSI device support
+#
+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
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
# Multi-device support (RAID and LVM)
#
# CONFIG_MD is not set
#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
# Networking support
#
CONFIG_NET=y
@@ -410,53 +480,6 @@ CONFIG_SLIP_COMPRESSED=y
# CONFIG_NETCONSOLE is not set
#
-# SCSI device support
-#
-CONFIG_SCSI=y
-CONFIG_SCSI_PROC_FS=y
-
-#
-# SCSI support type (disk, tape, CD-ROM)
-#
-# CONFIG_BLK_DEV_SD 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
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
-# CONFIG_SCSI_MULTI_LUN is not set
-# CONFIG_SCSI_CONSTANTS is not set
-# CONFIG_SCSI_LOGGING is not set
-
-#
-# SCSI Transport Attributes
-#
-# CONFIG_SCSI_SPI_ATTRS is not set
-# CONFIG_SCSI_FC_ATTRS is not set
-# CONFIG_SCSI_ISCSI_ATTRS is not set
-
-#
-# SCSI low-level drivers
-#
-# CONFIG_SCSI_SATA is not set
-# CONFIG_SCSI_DEBUG is not set
-
-#
-# Fusion MPT device support
-#
-
-#
-# IEEE 1394 (FireWire) support
-#
-
-#
-# I2O device support
-#
-
-#
# ISDN subsystem
#
# CONFIG_ISDN is not set
@@ -479,16 +502,6 @@ CONFIG_INPUT_EVDEV=y
CONFIG_INPUT_EVBUG=y
#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_RAW is not set
-
-#
# Input Device Drivers
#
# CONFIG_INPUT_KEYBOARD is not set
@@ -499,6 +512,15 @@ CONFIG_INPUT_MISC=y
CONFIG_INPUT_UINPUT=y
#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
+#
# Character devices
#
CONFIG_VT=y
@@ -549,6 +571,11 @@ CONFIG_WATCHDOG_NOWAYOUT=y
# CONFIG_RAW_DRIVER is not set
#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
# I2C support
#
CONFIG_I2C=y
@@ -580,7 +607,9 @@ CONFIG_I2C_CHARDEV=y
# CONFIG_SENSORS_ASB100 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
# CONFIG_SENSORS_IT87 is not set
# CONFIG_SENSORS_LM63 is not set
# CONFIG_SENSORS_LM75 is not set
@@ -613,6 +642,10 @@ CONFIG_ISP1301_OMAP=y
# CONFIG_I2C_DEBUG_CHIP is not set
#
+# Misc devices
+#
+
+#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -623,6 +656,101 @@ CONFIG_ISP1301_OMAP=y
# CONFIG_DVB is not set
#
+# Graphics support
+#
+CONFIG_FB=y
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_SOFT_CURSOR is not set
+CONFIG_FB_MODE_HELPERS=y
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+# CONFIG_FONT_ACORN_8x8 is not set
+# CONFIG_FONT_MINI_4x6 is not set
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+CONFIG_SOUND=y
+
+#
+# Advanced Linux Sound Architecture
+#
+# CONFIG_SND is not set
+
+#
+# Open Sound System
+#
+CONFIG_SOUND_PRIME=y
+# CONFIG_SOUND_BT878 is not set
+# CONFIG_SOUND_FUSION is not set
+# CONFIG_SOUND_CS4281 is not set
+# CONFIG_SOUND_SONICVIBES is not set
+# CONFIG_SOUND_TRIDENT is not set
+# CONFIG_SOUND_MSNDCLAS is not set
+# CONFIG_SOUND_MSNDPIN is not set
+# CONFIG_SOUND_OSS is not set
+# CONFIG_SOUND_TVMIXER is not set
+# CONFIG_SOUND_AD1980 is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_PXA2XX is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_SA1100 is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+CONFIG_USB_GADGET_OMAP=y
+CONFIG_USB_OMAP=y
+# CONFIG_USB_GADGET_DUALSPEED is not set
+# CONFIG_USB_ZERO is not set
+CONFIG_USB_ETH=y
+CONFIG_USB_ETH_RNDIS=y
+# 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 is not set
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -631,6 +759,10 @@ CONFIG_EXT2_FS=y
# CONFIG_JBD is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
# CONFIG_XFS_FS is not set
# CONFIG_MINIX_FS is not set
CONFIG_ROMFS_FS=y
@@ -702,7 +834,6 @@ CONFIG_NFS_V4=y
CONFIG_ROOT_NFS=y
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
-# CONFIG_EXPORTFS is not set
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=y
CONFIG_RPCSEC_GSS_KRB5=y
@@ -769,113 +900,17 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_PROFILING is not set
#
-# Graphics support
-#
-CONFIG_FB=y
-CONFIG_FB_MODE_HELPERS=y
-# CONFIG_FB_TILEBLITTING is not set
-# CONFIG_FB_VIRTUAL is not set
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_FONTS=y
-CONFIG_FONT_8x8=y
-CONFIG_FONT_8x16=y
-# CONFIG_FONT_6x11 is not set
-# CONFIG_FONT_PEARL_8x8 is not set
-# CONFIG_FONT_ACORN_8x8 is not set
-# CONFIG_FONT_MINI_4x6 is not set
-# CONFIG_FONT_SUN8x16 is not set
-# CONFIG_FONT_SUN12x22 is not set
-
-#
-# Logo configuration
-#
-CONFIG_LOGO=y
-# CONFIG_LOGO_LINUX_MONO is not set
-# CONFIG_LOGO_LINUX_VGA16 is not set
-CONFIG_LOGO_LINUX_CLUT224=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
-
-#
-# Sound
-#
-CONFIG_SOUND=y
-
-#
-# Advanced Linux Sound Architecture
-#
-# CONFIG_SND is not set
-
-#
-# Open Sound System
-#
-CONFIG_SOUND_PRIME=y
-# CONFIG_SOUND_BT878 is not set
-# CONFIG_SOUND_FUSION is not set
-# CONFIG_SOUND_CS4281 is not set
-# CONFIG_SOUND_SONICVIBES is not set
-# CONFIG_SOUND_TRIDENT is not set
-# CONFIG_SOUND_MSNDCLAS is not set
-# CONFIG_SOUND_MSNDPIN is not set
-# CONFIG_SOUND_OSS is not set
-# CONFIG_SOUND_TVMIXER is not set
-# CONFIG_SOUND_AD1980 is not set
-
-#
-# Misc devices
-#
-
-#
-# USB support
-#
-# CONFIG_USB is not set
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
-
-#
-# USB Gadget Support
-#
-CONFIG_USB_GADGET=y
-# CONFIG_USB_GADGET_DEBUG_FILES is not set
-# CONFIG_USB_GADGET_NET2280 is not set
-# CONFIG_USB_GADGET_PXA2XX is not set
-# CONFIG_USB_GADGET_GOKU is not set
-# CONFIG_USB_GADGET_SA1100 is not set
-# CONFIG_USB_GADGET_LH7A40X is not set
-# CONFIG_USB_GADGET_DUMMY_HCD is not set
-CONFIG_USB_GADGET_OMAP=y
-CONFIG_USB_OMAP=y
-# CONFIG_USB_GADGET_DUALSPEED is not set
-# CONFIG_USB_ZERO is not set
-CONFIG_USB_ETH=y
-CONFIG_USB_ETH_RNDIS=y
-# 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 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_SCHEDSTATS is not set
# CONFIG_DEBUG_SLAB is not set
CONFIG_DEBUG_PREEMPT=y
# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
# CONFIG_DEBUG_KOBJECT is not set
CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_DEBUG_INFO=y
@@ -905,6 +940,7 @@ CONFIG_CRYPTO_MD5=y
# CONFIG_CRYPTO_SHA256 is not set
# CONFIG_CRYPTO_SHA512 is not set
# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
CONFIG_CRYPTO_DES=y
# CONFIG_CRYPTO_BLOWFISH is not set
# CONFIG_CRYPTO_TWOFISH is not set
diff --git a/arch/arm/configs/omnimeter_defconfig b/arch/arm/configs/omnimeter_defconfig
index fd3849e96d403..78fdb4a428b17 100644
--- a/arch/arm/configs/omnimeter_defconfig
+++ b/arch/arm/configs/omnimeter_defconfig
@@ -1,113 +1,193 @@
#
-# Automatically generated by make menuconfig: don't edit
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.12-rc1-bk2
+# Sun Mar 27 21:31:45 2005
#
CONFIG_ARM=y
-# CONFIG_SBUS is not set
+CONFIG_MMU=y
CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_IOMAP=y
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-# CONFIG_OBSOLETE is not set
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
#
# Loadable module support
#
CONFIG_MODULES=y
+# CONFIG_MODULE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_KMOD=y
#
# System Type
#
-# CONFIG_ARCH_ARCA5K is not set
# 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=y
-# CONFIG_ARCH_CLPS711X is not set
-
-#
-# Archimedes/A5000 Implementations
-#
-
-#
-# Footbridge Implementations
-#
+# 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
#
# SA11x0 Implementations
#
# CONFIG_SA1100_ASSABET is not set
-# CONFIG_SA1100_BRUTUS is not set
-CONFIG_SA1100_OMNIMETER=y
# CONFIG_SA1100_CERF is not set
-# CONFIG_SA1100_BITSY is not set
+# CONFIG_SA1100_COLLIE is not set
+# CONFIG_SA1100_H3100 is not set
+# CONFIG_SA1100_H3600 is not set
+# CONFIG_SA1100_H3800 is not set
+# CONFIG_SA1100_BADGE4 is not set
+# CONFIG_SA1100_JORNADA720 is not set
+# CONFIG_SA1100_HACKKIT is not set
# CONFIG_SA1100_LART is not set
-# CONFIG_SA1100_GRAPHICSCLIENT is not set
-# CONFIG_SA1100_NANOENGINE is not set
-# CONFIG_SA1100_VICTOR is not set
-# CONFIG_SA1100_SHERMAN is not set
-# CONFIG_SA1100_XP860 is not set
-# CONFIG_SA1100_PANGOLIN is not set
-# CONFIG_SA1100_USB is not set
-# CONFIG_SA1100_FREQUENCY_SCALE is not set
-# CONFIG_SA1100_VOLTAGE_SCALE is not set
-
-#
-# CLPS711X/EP721X Implementations
-#
-# CONFIG_ARCH_ACORN is not set
-# CONFIG_FOOTBRIDGE is not set
-# CONFIG_FOOTBRIDGE_HOST is not set
-# CONFIG_FOOTBRIDGE_ADDIN is not set
+# CONFIG_SA1100_PLEB is not set
+# CONFIG_SA1100_SHANNON is not set
+# CONFIG_SA1100_SIMPAD is not set
+# CONFIG_SA1100_SSP is not set
+
+#
+# Processor Type
+#
CONFIG_CPU_32=y
-# CONFIG_CPU_26 is not set
-CONFIG_CPU_32v4=y
CONFIG_CPU_SA1100=y
-CONFIG_DISCONTIGMEM=y
+CONFIG_CPU_32v4=y
+CONFIG_CPU_ABRT_EV4=y
+CONFIG_CPU_CACHE_V4WB=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_TLB_V4WB=y
+CONFIG_CPU_MINICACHE=y
#
-# General setup
+# Processor Features
+#
+
+#
+# Bus support
#
-# CONFIG_ANGELBOOT is not set
-# CONFIG_PCI is not set
CONFIG_ISA=y
-# CONFIG_ISA_DMA is not set
-CONFIG_HOTPLUG=y
#
-# PCMCIA/CardBus support
+# PCCARD (PCMCIA/CardBus) support
#
+CONFIG_PCCARD=y
+# CONFIG_PCMCIA_DEBUG is not set
CONFIG_PCMCIA=y
+
+#
+# PC-card bridges
+#
CONFIG_I82365=y
-# CONFIG_PCMCIA_CLPS6700 is not set
-CONFIG_SA1100_PCMCIA=y
-# CONFIG_H3600_SLEEVE is not set
-CONFIG_NET=y
-CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
-CONFIG_NWFPE=y
-CONFIG_KCORE_ELF=y
-# CONFIG_KCORE_AOUT is not set
-CONFIG_BINFMT_AOUT=y
+# CONFIG_TCIC is not set
+CONFIG_PCMCIA_SA1100=y
+CONFIG_PCCARD_NONSTATIC=y
+
+#
+# Kernel Features
+#
+# CONFIG_PREEMPT is not set
+CONFIG_DISCONTIGMEM=y
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="keepinitrd mem=16M root=/dev/ram ramdisk=8192 initrd=0xd0000000,4M"
+# CONFIG_XIP_KERNEL is not set
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+# CONFIG_FPE_NWFPE is not set
+# CONFIG_FPE_FASTFPE is not set
+
+#
+# Userspace binary formats
+#
CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_AOUT=y
# CONFIG_BINFMT_MISC is not set
-# CONFIG_PM is not set
# CONFIG_ARTHUR is not set
-CONFIG_CMDLINE="keepinitrd mem=16M root=/dev/ram ramdisk=8192 initrd=0xd0000000,4M"
-# CONFIG_LEDS is not set
-# CONFIG_ALIGNMENT_TRAP is not set
#
-# Parallel port support
+# Power management options
#
-# CONFIG_PARPORT is not set
+# CONFIG_PM is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
#
# Memory Technology Devices (MTD)
@@ -115,38 +195,101 @@ CONFIG_CMDLINE="keepinitrd mem=16M root=/dev/ram ramdisk=8192 initrd=0xd0000000,
# CONFIG_MTD is not set
#
-# Plug and Play configuration
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
#
# CONFIG_PNP is not set
-# CONFIG_ISAPNP is not set
#
# Block devices
#
# CONFIG_BLK_DEV_FD is not set
# CONFIG_BLK_DEV_XD is not set
-# CONFIG_PARIDE is not set
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
CONFIG_BLK_DEV_LOOP=m
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
CONFIG_BLK_DEV_NBD=m
# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
-# CONFIG_BLK_DEV_FLASH is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDECS is not set
+# CONFIG_BLK_DEV_IDECD 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_IDE_ARM is not set
+# CONFIG_IDE_CHIPSETS is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
#
# Networking options
#
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
-CONFIG_NETLINK=y
-CONFIG_RTNETLINK=y
# CONFIG_NETLINK_DEV is not set
-CONFIG_NETFILTER=y
-# CONFIG_NETFILTER_DEBUG is not set
-# CONFIG_FILTER 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
@@ -155,62 +298,83 @@ CONFIG_IP_MULTICAST=y
# CONFIG_NET_IPGRE is not set
# CONFIG_IP_MROUTE is not set
# CONFIG_ARPD is not set
-# CONFIG_INET_ECN is not set
# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
#
-# IP: Netfilter Configuration
+# IP: Netfilter Configuration
#
# CONFIG_IP_NF_CONNTRACK is not set
+# CONFIG_IP_NF_CONNTRACK_MARK is not set
# CONFIG_IP_NF_QUEUE is not set
# CONFIG_IP_NF_IPTABLES is not set
-# CONFIG_IP_NF_COMPAT_IPCHAINS is not set
-# CONFIG_IP_NF_COMPAT_IPFWADM is not set
-# CONFIG_IPV6 is not set
-# CONFIG_KHTTPD is not set
+# CONFIG_IP_NF_ARPTABLES 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_DECNET is not set
-# CONFIG_BRIDGE is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-# CONFIG_LLC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
#
# QoS and/or fair queueing
#
# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
#
-# Network device support
+# Network testing
#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
#
# ARCnet devices
#
# CONFIG_ARCNET is not set
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
-# CONFIG_NET_SB1000 is not set
-# CONFIG_NET_SA1100_USB_HOST is not set
-# CONFIG_NET_SA1100_USB_CLIENT is not set
#
# Ethernet (10 or 100Mbit)
#
CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_LANCE is not set
# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_SMC91X is not set
# CONFIG_NET_VENDOR_RACAL is not set
# CONFIG_AT1700 is not set
# CONFIG_DEPCA is not set
@@ -222,32 +386,47 @@ CONFIG_NET_ETHERNET=y
#
# Ethernet (1000 Mbit)
#
-# CONFIG_ACENIC is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
#
-# Wireless LAN (non-hamradio)
+# Ethernet (10000 Mbit)
#
-# CONFIG_NET_RADIO is not set
#
# Token Ring devices
#
# CONFIG_TR is not set
-# CONFIG_NET_FC is not set
-# CONFIG_RCPCI is not set
-# CONFIG_SHAPER is not set
#
-# Wan interfaces
+# Wireless LAN (non-hamradio)
#
-# CONFIG_WAN is not set
+CONFIG_NET_RADIO=y
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+# CONFIG_ARLAN is not set
+# CONFIG_WAVELAN is not set
+CONFIG_PCMCIA_WAVELAN=y
+# CONFIG_PCMCIA_NETWAVE is not set
+
+#
+# Wireless 802.11 Frequency Hopping cards support
+#
+# CONFIG_PCMCIA_RAYCS is not set
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+# CONFIG_HERMES is not set
+# CONFIG_ATMEL is not set
+
+#
+# Wireless 802.11b Pcmcia/Cardbus cards support
+#
+CONFIG_AIRO_CS=y
+CONFIG_PCMCIA_WL3501=y
+CONFIG_NET_WIRELESS=y
#
# PCMCIA network device support
@@ -260,218 +439,292 @@ CONFIG_PCMCIA_PCNET=y
# CONFIG_PCMCIA_NMCLAN is not set
# CONFIG_PCMCIA_SMC91C92 is not set
# CONFIG_PCMCIA_XIRC2PS is not set
-# CONFIG_ARCNET_COM20020_CS is not set
-# CONFIG_PCMCIA_IBMTR is not set
-CONFIG_NET_PCMCIA_RADIO=y
-# CONFIG_PCMCIA_RAYCS is not set
-# CONFIG_PCMCIA_NETWAVE is not set
-CONFIG_PCMCIA_WAVELAN=y
-CONFIG_AIRONET4500_CS=y
-CONFIG_PCMCIA_WVLAN=y
-CONFIG_PCMCIA_NETCARD=y
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
+# CONFIG_PCMCIA_AXNET is not set
#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
-# ATA/IDE/MFM/RLL support
+# Wan interfaces
#
-CONFIG_IDE=y
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
#
-# IDE, ATA and ATAPI Block devices
+# ISDN subsystem
#
-CONFIG_BLK_DEV_IDE=y
-# CONFIG_BLK_DEV_HD_IDE is not set
-# CONFIG_BLK_DEV_HD is not set
-CONFIG_BLK_DEV_IDEDISK=y
-# CONFIG_IDEDISK_MULTI_MODE is not set
-CONFIG_BLK_DEV_IDECS=y
-# CONFIG_BLK_DEV_IDECD is not set
-# CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
-# CONFIG_BLK_DEV_IDESCSI is not set
-# CONFIG_BLK_DEV_CMD640 is not set
-# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
-# CONFIG_BLK_DEV_ISAPNP is not set
-# CONFIG_IDE_CHIPSETS is not set
-# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_ISDN is not set
#
-# SCSI support
+# Input device support
#
-# CONFIG_SCSI is not set
+CONFIG_INPUT=y
#
-# I2O device support
+# Userland interfaces
#
-# CONFIG_I2O is not set
-# CONFIG_I2O_BLOCK is not set
-# CONFIG_I2O_LAN is not set
-# CONFIG_I2O_SCSI is not set
-# CONFIG_I2O_PROC is not set
+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
#
-# ISDN subsystem
+# Input Device Drivers
#
-# CONFIG_ISDN is not set
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_INPORT is not set
+# CONFIG_MOUSE_LOGIBM is not set
+# CONFIG_MOUSE_PC110PAD is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
#
-# Input core support
+# Hardware I/O ports
#
-# CONFIG_INPUT is not set
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
#
# Character devices
#
CONFIG_VT=y
CONFIG_VT_CONSOLE=y
-CONFIG_SERIAL_SA1100=y
-CONFIG_SERIAL_SA1100_CONSOLE=y
-# CONFIG_TOUCHSCREEN_UCB1200 is not set
-# CONFIG_TOUCHSCREEN_BITSY is not set
-# CONFIG_TOUCHSCREEN_BITSY_KEYBOARD is not set
-# CONFIG_H3600_SLEEVE is not set
-CONFIG_SERIAL=y
-# CONFIG_SERIAL_CONSOLE is not set
-# CONFIG_SERIAL_EXTENDED is not set
+CONFIG_HW_CONSOLE=y
# CONFIG_SERIAL_NONSTANDARD is not set
-CONFIG_SERIAL_SA1100=y
-CONFIG_SERIAL_SA1100_CONSOLE=y
-CONFIG_SA1100_DEFAULT_BAUDRATE=9600
-# CONFIG_TOUCHSCREEN_UCB1200 is not set
-# CONFIG_TOUCHSCREEN_BITSY is not set
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=32
#
-# I2C support
+# Serial drivers
#
-# CONFIG_I2C is not set
+# CONFIG_SERIAL_8250 is not set
#
-# Mice
+# Non-8250 serial port support
#
-# CONFIG_BUSMOUSE is not set
-CONFIG_MOUSE=m
-# CONFIG_PSMOUSE is not set
-# CONFIG_82C710_MOUSE is not set
-# CONFIG_PC110_PAD is not set
+CONFIG_SERIAL_SA1100=y
+CONFIG_SERIAL_SA1100_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
#
-# Joysticks
+# IPMI
#
-# CONFIG_JOYSTICK is not set
-# CONFIG_QIC02_TAPE is not set
+# CONFIG_IPMI_HANDLER is not set
#
# Watchdog Cards
#
# CONFIG_WATCHDOG is not set
-# CONFIG_INTEL_RNG is not set
# CONFIG_NVRAM is not set
# CONFIG_RTC is not set
-# CONFIG_SA1100_RTC is not set
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
#
# Ftape, the floppy tape device driver
#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
# CONFIG_DRM is not set
-CONFIG_PCMCIA_SERIAL=y
#
-# PCMCIA character device support
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+CONFIG_FB_SOFT_CURSOR=y
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+CONFIG_FB_SA1100=y
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
#
-# CONFIG_PCMCIA_SERIAL_CS is not set
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+# 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_MINI_4x6 is not set
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 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 is not set
+# CONFIG_USB is not set
+
+#
+# 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_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_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+# CONFIG_VFAT_FS is not set
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
# CONFIG_ADFS_FS is not set
-# CONFIG_ADFS_FS_RW 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_FAT_FS=y
-CONFIG_MSDOS_FS=y
-# CONFIG_UMSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
# CONFIG_EFS_FS is not set
-# CONFIG_JFFS_FS is not set
# CONFIG_CRAMFS is not set
-# CONFIG_RAMFS is not set
-# CONFIG_ISO9660_FS is not set
-# CONFIG_JOLIET is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_NTFS_FS is not set
-# CONFIG_NTFS_DEBUG is not set
-# CONFIG_NTFS_RW is not set
+# CONFIG_VXFS_FS is not set
# CONFIG_HPFS_FS is not set
-CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
-# CONFIG_DEVFS_MOUNT is not set
-# CONFIG_DEVFS_DEBUG is not set
-# CONFIG_DEVPTS_FS is not set
# CONFIG_QNX4FS_FS is not set
-# CONFIG_QNX4FS_RW is not set
-# CONFIG_ROMFS_FS is not set
-CONFIG_EXT2_FS=y
# CONFIG_SYSV_FS is not set
-# CONFIG_SYSV_FS_WRITE is not set
-# CONFIG_UDF_FS is not set
-# CONFIG_UDF_RW is not set
# CONFIG_UFS_FS is not set
-# CONFIG_UFS_FS_WRITE is not set
#
# Network File Systems
#
-# CONFIG_CODA_FS is not set
CONFIG_NFS_FS=y
# CONFIG_NFS_V3 is not set
-# CONFIG_ROOT_NFS is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
# CONFIG_NFSD is not set
-# CONFIG_NFSD_V3 is not set
-CONFIG_SUNRPC=y
CONFIG_LOCKD=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_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_MOUNT_SUBDIR is not set
-# CONFIG_NCPFS_NDS_DOMAINS is not set
-# CONFIG_NCPFS_NLS is not set
-# CONFIG_NCPFS_EXTRAS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
#
# Partition Types
#
# CONFIG_PARTITION_ADVANCED is not set
CONFIG_MSDOS_PARTITION=y
-CONFIG_NLS=y
#
# Native Language Support
#
+CONFIG_NLS=y
CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_NLS_CODEPAGE_437 is not set
# CONFIG_NLS_CODEPAGE_737 is not set
@@ -488,11 +741,15 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_NLS_CODEPAGE_865 is not set
# CONFIG_NLS_CODEPAGE_866 is not set
# CONFIG_NLS_CODEPAGE_869 is not set
-# CONFIG_NLS_CODEPAGE_874 is not set
-# CONFIG_NLS_CODEPAGE_932 is not set
# CONFIG_NLS_CODEPAGE_936 is not set
-# CONFIG_NLS_CODEPAGE_949 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
@@ -500,71 +757,47 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_NLS_ISO8859_5 is not set
# CONFIG_NLS_ISO8859_6 is not set
# CONFIG_NLS_ISO8859_7 is not set
-# CONFIG_NLS_ISO8859_8 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
#
-# Console drivers
+# Profiling support
#
-CONFIG_PC_KEYMAP=y
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_FB=y
+# CONFIG_PROFILING is not set
#
-# Frame-buffer support
+# Kernel hacking
#
-CONFIG_FB=y
-CONFIG_DUMMY_CONSOLE=y
-# CONFIG_FB_ACORN is not set
-# CONFIG_FB_CLPS711X is not set
-# CONFIG_FB_CYBER2000 is not set
-CONFIG_FB_SA1100=y
-# CONFIG_FB_VIRTUAL is not set
-CONFIG_FBCON_ADVANCED=y
-# CONFIG_FBCON_MFB is not set
-# CONFIG_FBCON_CFB2 is not set
-CONFIG_FBCON_CFB4=y
-# CONFIG_FBCON_CFB8 is not set
-# CONFIG_FBCON_CFB16 is not set
-# CONFIG_FBCON_CFB24 is not set
-# CONFIG_FBCON_CFB32 is not set
-# CONFIG_FBCON_AFB is not set
-# CONFIG_FBCON_ILBM is not set
-# CONFIG_FBCON_IPLAN2P2 is not set
-# CONFIG_FBCON_IPLAN2P4 is not set
-# CONFIG_FBCON_IPLAN2P8 is not set
-# CONFIG_FBCON_MAC is not set
-# CONFIG_FBCON_VGA_PLANES is not set
-# CONFIG_FBCON_VGA is not set
-# CONFIG_FBCON_HGA is not set
-CONFIG_FBCON_FONTWIDTH8_ONLY=y
-CONFIG_FBCON_FONTS=y
-CONFIG_FONT_8x8=y
-# CONFIG_FONT_8x16 is not set
-# CONFIG_FONT_SUN8x16 is not set
-# CONFIG_FONT_PEARL_8x8 is not set
-# CONFIG_FONT_ACORN_8x8 is not set
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_FRAME_POINTER=y
+# CONFIG_DEBUG_USER is not set
#
-# Sound
+# Security options
#
-# CONFIG_SOUND is not set
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
#
-# USB support
+# Cryptographic options
#
-# CONFIG_USB is not set
+# CONFIG_CRYPTO is not set
#
-# Kernel hacking
+# Hardware crypto devices
#
-CONFIG_FRAME_POINTER=y
-CONFIG_DEBUG_ERRORS=y
-# CONFIG_DEBUG_USER is not set
-# CONFIG_DEBUG_INFO is not set
-# CONFIG_MAGIC_SYSRQ is not set
-CONFIG_DEBUG_LL=y
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
diff --git a/arch/arm/configs/pleb_defconfig b/arch/arm/configs/pleb_defconfig
index ca2cb5af5a331..10fec890578dd 100644
--- a/arch/arm/configs/pleb_defconfig
+++ b/arch/arm/configs/pleb_defconfig
@@ -1,12 +1,13 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.10-rc2
-# Wed Nov 24 15:12:32 2004
+# Linux kernel version: 2.6.12-rc1-bk2
+# Sun Mar 27 22:03:02 2005
#
CONFIG_ARM=y
CONFIG_MMU=y
CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_GENERIC_IOMAP=y
#
@@ -26,7 +27,6 @@ CONFIG_SYSVIPC=y
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
# CONFIG_HOTPLUG is not set
# CONFIG_KOBJECT_UEVENT is not set
# CONFIG_IKCONFIG is not set
@@ -34,6 +34,7 @@ CONFIG_EMBEDDED=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
@@ -43,6 +44,7 @@ CONFIG_CC_ALIGN_LABELS=0
CONFIG_CC_ALIGN_LOOPS=0
CONFIG_CC_ALIGN_JUMPS=0
CONFIG_TINY_SHMEM=y
+CONFIG_BASE_SMALL=0
#
# Loadable module support
@@ -96,7 +98,6 @@ CONFIG_SA1100_PLEB=y
# CONFIG_SA1100_SHANNON is not set
# CONFIG_SA1100_SIMPAD is not set
# CONFIG_SA1100_SSP is not set
-# CONFIG_SA1100_USB is not set
#
# Processor Type
@@ -115,17 +116,39 @@ CONFIG_CPU_MINICACHE=y
#
#
-# General setup
+# Bus support
#
-CONFIG_DISCONTIGMEM=y
CONFIG_ISA=y
-# CONFIG_ZBOOT_ROM is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_PREEMPT is not set
+CONFIG_DISCONTIGMEM=y
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
CONFIG_ZBOOT_ROM_TEXT=0x0
CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="console=ttySA0,9600 mem=16M@0xc0000000 mem=16M@0xc8000000 root=/dev/ram initrd=0xc0400000,4M"
# CONFIG_XIP_KERNEL is not set
+
+#
+# CPU Frequency scaling
+#
CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
# CONFIG_CPU_FREQ_DEBUG is not set
-# CONFIG_CPU_FREQ_PROC_INTF 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
@@ -135,41 +158,50 @@ CONFIG_CPU_FREQ_GOV_ONDEMAND=y
CONFIG_CPU_FREQ_SA1100=y
#
-# At least one math emulation must be selected
+# 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
#
-# Generic Driver Options
+# Power management options
#
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_DEBUG_DRIVER is not set
# CONFIG_PM is not set
-# CONFIG_PREEMPT is not set
-# CONFIG_ARTHUR is not set
-CONFIG_CMDLINE="console=ttySA0,9600 mem=16M@0xc0000000 mem=16M@0xc8000000 root=/dev/ram initrd=0xc0400000,4M"
-# CONFIG_LEDS is not set
-CONFIG_ALIGNMENT_TRAP=y
#
-# Parallel port support
+# Device Drivers
#
-# CONFIG_PARPORT is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
#
# Memory Technology Devices (MTD)
#
CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
-CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
CONFIG_MTD_REDBOOT_PARTS=y
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
CONFIG_MTD_CMDLINE_PARTS=y
@@ -208,6 +240,7 @@ CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_XIP is not set
#
# Mapping drivers for chip access
@@ -225,6 +258,7 @@ CONFIG_MTD_SA1100=y
# 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
@@ -239,6 +273,11 @@ CONFIG_MTD_SA1100=y
# CONFIG_MTD_NAND is not set
#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
# Plug and Play support
#
# CONFIG_PNP is not set
@@ -248,10 +287,12 @@ CONFIG_MTD_SA1100=y
#
# CONFIG_BLK_DEV_FD is not set
# CONFIG_BLK_DEV_XD is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
# CONFIG_BLK_DEV_NBD 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_INITRAMFS_SOURCE=""
@@ -264,6 +305,17 @@ CONFIG_IOSCHED_NOOP=y
# CONFIG_IOSCHED_AS is not set
# CONFIG_IOSCHED_DEADLINE is not set
# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
#
# Multi-device support (RAID and LVM)
@@ -271,6 +323,18 @@ CONFIG_IOSCHED_NOOP=y
# CONFIG_MD is not set
#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
# Networking support
#
CONFIG_NET=y
@@ -388,28 +452,6 @@ CONFIG_SMC91X=y
# CONFIG_NETCONSOLE is not set
#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-# CONFIG_SCSI is not set
-
-#
-# Fusion MPT device support
-#
-
-#
-# IEEE 1394 (FireWire) support
-#
-
-#
-# I2O device support
-#
-
-#
# ISDN subsystem
#
# CONFIG_ISDN is not set
@@ -420,19 +462,11 @@ CONFIG_SMC91X=y
# CONFIG_INPUT is not set
#
-# Userland interfaces
-#
-
-#
-# Input I/O drivers
+# Hardware I/O ports
#
+# CONFIG_SERIO is not set
# CONFIG_GAMEPORT is not set
CONFIG_SOUND_GAMEPORT=y
-# CONFIG_SERIO is not set
-
-#
-# Input Device Drivers
-#
#
# Character devices
@@ -477,11 +511,20 @@ CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_RAW_DRIVER is not set
#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
# I2C support
#
# CONFIG_I2C is not set
#
+# Misc devices
+#
+
+#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -492,6 +535,33 @@ CONFIG_LEGACY_PTY_COUNT=256
# 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 is not set
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -502,6 +572,10 @@ CONFIG_JBD=y
# CONFIG_JBD_DEBUG is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
# CONFIG_XFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
@@ -567,7 +641,6 @@ CONFIG_NFS_DIRECTIO=y
# CONFIG_NFSD is not set
CONFIG_LOCKD=m
CONFIG_LOCKD_V4=y
-# CONFIG_EXPORTFS is not set
CONFIG_SUNRPC=m
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
@@ -633,47 +706,20 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_PROFILING is not set
#
-# Graphics support
-#
-# CONFIG_FB is not set
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# Misc devices
-#
-
-#
-# USB support
-#
-# CONFIG_USB is not set
-CONFIG_USB_ARCH_HAS_HCD=y
-# CONFIG_USB_ARCH_HAS_OHCI is not set
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
-# CONFIG_MMC is not set
-
-#
# Kernel hacking
#
+# CONFIG_PRINTK_TIME is not set
CONFIG_DEBUG_KERNEL=y
CONFIG_MAGIC_SYSRQ=y
+CONFIG_LOG_BUF_SHIFT=14
# 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_FRAME_POINTER=y
# CONFIG_DEBUG_USER is not set
# CONFIG_DEBUG_WAITQ is not set
@@ -692,6 +738,10 @@ CONFIG_FRAME_POINTER=y
# CONFIG_CRYPTO is not set
#
+# Hardware crypto devices
+#
+
+#
# Library routines
#
# CONFIG_CRC_CCITT is not set
diff --git a/arch/arm/configs/pxa255-idp_defconfig b/arch/arm/configs/pxa255-idp_defconfig
new file mode 100644
index 0000000000000..21c327883d8cd
--- /dev/null
+++ b/arch/arm/configs/pxa255-idp_defconfig
@@ -0,0 +1,799 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.12-rc1-bk2
+# Sun Mar 27 22:20:17 2005
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_IOMAP=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODULE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_KMOD 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 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=y
+# 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
+
+#
+# Intel PXA2xx Implementations
+#
+# CONFIG_ARCH_LUBBOCK is not set
+# CONFIG_MACH_MAINSTONE is not set
+CONFIG_ARCH_PXA_IDP=y
+# CONFIG_PXA_SHARPSL is not set
+CONFIG_PXA25x=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_XSCALE=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5T=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_MINICACHE=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+CONFIG_XSCALE_PMU=y
+
+#
+# Bus support
+#
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_PREEMPT is not set
+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="root=/dev/nfs ip=dhcp console=ttyS0,115200 mem=64M"
+# 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
+
+#
+# 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
+
+#
+# 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 is not set
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_NOSWAP=y
+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
+CONFIG_MTD_CFI_GEOMETRY=y
+# CONFIG_MTD_MAP_BANK_WIDTH_1 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_2 is not set
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+# CONFIG_MTD_CFI_I1 is not set
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_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_EDB7312 is not set
+# CONFIG_MTD_SHARP_SL 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
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND 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_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# 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 is not set
+# CONFIG_IDE_ARM is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_SMC91X=y
+
+#
+# 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
+
+#
+# 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=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_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=y
+# CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW 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_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_PXA=y
+CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+CONFIG_FB_SOFT_CURSOR=y
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+CONFIG_FB_PXA=y
+# CONFIG_FB_PXA_PARAMETERS is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+# CONFIG_FONT_ACORN_8x8 is not set
+# CONFIG_FONT_MINI_4x6 is not set
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+
+#
+# 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 is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB is not set
+
+#
+# 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_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_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+# CONFIG_VFAT_FS is not set
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# 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_NAND is not set
+# CONFIG_JFFS2_FS_NOR_ECC is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 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=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_LOG_BUF_SHIFT=14
+# 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=y
+# CONFIG_DEBUG_FS is not set
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_WAITQ is not set
+CONFIG_DEBUG_ERRORS=y
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/arm/configs/rpc_defconfig b/arch/arm/configs/rpc_defconfig
index 8097cdc4f9052..19184c1010adf 100644
--- a/arch/arm/configs/rpc_defconfig
+++ b/arch/arm/configs/rpc_defconfig
@@ -1,124 +1,178 @@
#
# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11
+# Wed Mar 9 14:41:48 2005
#
CONFIG_ARM=y
CONFIG_MMU=y
-CONFIG_SWAP=y
CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_IOMAP=y
+CONFIG_FIQ=y
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
#
# General setup
#
-CONFIG_NET=y
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_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
#
# System Type
#
-# CONFIG_ARCH_ADIFCC is not set
-# CONFIG_ARCH_ARCA5K is not set
# CONFIG_ARCH_CLPS7500 is not set
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
-# CONFIG_ARCH_PXA 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_IOP310 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=y
# 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
+CONFIG_ARCH_ACORN=y
#
-# Archimedes/A5000 Implementations
+# Processor Type
#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM610=y
+CONFIG_CPU_ARM710=y
+CONFIG_CPU_SA110=y
+CONFIG_CPU_32v3=y
+CONFIG_CPU_ABRT_EV4=y
+CONFIG_CPU_CACHE_V3=y
+CONFIG_CPU_CACHE_V4WB=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V3=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V3=y
+CONFIG_CPU_TLB_V4WB=y
#
-# Archimedes/A5000 Implementations (select only ONE)
+# Processor Features
#
+CONFIG_TIMER_ACORN=y
#
-# CLPS711X/EP721X Implementations
+# Bus support
#
#
-# Epxa10db
+# PCCARD (PCMCIA/CardBus) support
#
+# CONFIG_PCCARD is not set
#
-# Footbridge Implementations
+# PC-card bridges
#
#
-# IOP310 Implementation Options
+# Kernel Features
#
+# CONFIG_PREEMPT is not set
+CONFIG_ALIGNMENT_TRAP=y
#
-# IOP310 Chipset Features
+# Boot options
#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE=""
+# CONFIG_XIP_KERNEL is not set
#
-# Intel PXA250/210 Implementations
+# Floating point emulation
#
#
-# SA11x0 Implementations
+# At least one emulation must be selected
#
-CONFIG_ARCH_ACORN=y
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
#
-# Processor Type
+# Userspace binary formats
#
-CONFIG_CPU_32=y
-CONFIG_CPU_ARM610=y
-CONFIG_CPU_ARM710=y
-CONFIG_CPU_SA110=y
-CONFIG_CPU_32v3=y
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_AOUT=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
#
-# Processor Features
+# Power management options
+#
+# CONFIG_PM is not set
+
+#
+# Device Drivers
#
#
-# General setup
+# Generic Driver Options
#
-CONFIG_FIQ=y
-# CONFIG_ZBOOT_ROM is not set
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-# CONFIG_HOTPLUG is not set
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
#
-# At least one math emulation must be selected
+# Memory Technology Devices (MTD)
#
-CONFIG_FPE_NWFPE=y
-CONFIG_KCORE_ELF=y
-# CONFIG_KCORE_AOUT is not set
-CONFIG_BINFMT_AOUT=y
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-# CONFIG_PM is not set
-# CONFIG_PREEMPT is not set
-# CONFIG_ARTHUR is not set
-CONFIG_CMDLINE=""
-CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_MTD is not set
#
# Parallel port support
@@ -126,7 +180,6 @@ CONFIG_ALIGNMENT_TRAP=y
CONFIG_PARPORT=y
CONFIG_PARPORT_PC=y
CONFIG_PARPORT_PC_CML1=y
-# CONFIG_PARPORT_SERIAL is not set
CONFIG_PARPORT_PC_FIFO=y
# CONFIG_PARPORT_PC_SUPERIO is not set
# CONFIG_PARPORT_ARC is not set
@@ -134,163 +187,52 @@ CONFIG_PARPORT_PC_FIFO=y
# CONFIG_PARPORT_1284 is not set
#
-# Memory Technology Devices (MTD)
+# Plug and Play support
#
-# CONFIG_MTD is not set
-
-#
-# Plug and Play configuration
-#
-# CONFIG_PNP is not set
#
# Block devices
#
CONFIG_BLK_DEV_FD=y
# CONFIG_PARIDE is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
CONFIG_BLK_DEV_LOOP=m
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
# CONFIG_BLK_DEV_NBD 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_CDROM_PKTCDVD is not set
#
-# Multi-device support (RAID and LVM)
+# IO Schedulers
#
-# CONFIG_MD is not set
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
#
# Acorn-specific block devices
#
#
-# Networking options
-#
-# CONFIG_PACKET is not set
-CONFIG_NETLINK_DEV=y
-# CONFIG_NETFILTER is not set
-# CONFIG_FILTER is not set
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-# CONFIG_IP_PNP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE is not set
-# CONFIG_ARPD is not set
-# CONFIG_INET_ECN is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_IPV6 is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-CONFIG_IPV6_SCTP__=y
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_LLC is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network device support
-#
-CONFIG_NETDEVICES=y
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-CONFIG_ARM_ETHER1=y
-CONFIG_ARM_ETHER3=y
-CONFIG_ARM_ETHERH=y
-# CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_NET_VENDOR_SMC is not set
-# CONFIG_NET_VENDOR_RACAL is not set
-# CONFIG_NET_POCKET is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PLIP is not set
-CONFIG_PPP=m
-# CONFIG_PPP_MULTILINK is not set
-# CONFIG_PPP_ASYNC is not set
-# CONFIG_PPP_SYNC_TTY is not set
-# CONFIG_PPP_DEFLATE is not set
-# CONFIG_PPP_BSDCOMP is not set
-CONFIG_PPPOE=m
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Token Ring devices
-#
-# CONFIG_NET_FC is not set
-# CONFIG_SHAPER is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
# ATA/ATAPI/MFM/RLL support
#
CONFIG_IDE=y
-
-#
-# IDE, ATA and ATAPI Block devices
-#
CONFIG_BLK_DEV_IDE=y
#
# Please see Documentation/ide.txt for help/info on IDE drives
#
-# CONFIG_BLK_DEV_HD is not set
+# CONFIG_BLK_DEV_IDE_SATA is not set
CONFIG_BLK_DEV_IDEDISK=y
CONFIG_IDEDISK_MULTI_MODE=y
-# CONFIG_IDEDISK_STROKE is not set
CONFIG_BLK_DEV_IDECD=y
+# 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
@@ -298,18 +240,22 @@ CONFIG_BLK_DEV_IDECD=y
#
# IDE chipset support/bugfixes
#
-CONFIG_BLK_DEV_IDEDMA=y
+CONFIG_IDE_GENERIC=y
+CONFIG_IDE_ARM=y
CONFIG_BLK_DEV_IDE_ICSIDE=y
CONFIG_BLK_DEV_IDEDMA_ICS=y
CONFIG_IDEDMA_ICS_AUTO=y
CONFIG_BLK_DEV_IDE_RAPIDE=y
-CONFIG_IDEDMA_AUTO=y
+CONFIG_BLK_DEV_IDEDMA=y
# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_HD is not set
#
-# SCSI support
+# SCSI device support
#
CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
#
# SCSI support type (disk, tape, CD-ROM)
@@ -319,43 +265,30 @@ CONFIG_CHR_DEV_ST=m
# CONFIG_CHR_DEV_OSST is not set
CONFIG_BLK_DEV_SR=y
CONFIG_BLK_DEV_SR_VENDOR=y
-CONFIG_SR_EXTRA_DEVS=2
CONFIG_CHR_DEV_SG=y
#
# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
#
# CONFIG_SCSI_MULTI_LUN is not set
-# CONFIG_SCSI_REPORT_LUNS is not set
CONFIG_SCSI_CONSTANTS=y
CONFIG_SCSI_LOGGING=y
#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+
+#
# SCSI low-level drivers
#
-# CONFIG_SCSI_ACARD is not set
-# CONFIG_SCSI_AIC7XXX is not set
-# CONFIG_SCSI_AIC7XXX_OLD is not set
-# CONFIG_SCSI_DPT_I2O is not set
-# CONFIG_SCSI_ADVANSYS is not set
-# CONFIG_SCSI_IN2000 is not set
-# CONFIG_SCSI_MEGARAID is not set
-# CONFIG_SCSI_BUSLOGIC is not set
-# CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_EATA_DMA is not set
-# CONFIG_SCSI_EATA_PIO is not set
-# CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
-# CONFIG_SCSI_GENERIC_NCR5380 is not set
-# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
+# CONFIG_SCSI_SATA is not set
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_PCI2000 is not set
-# CONFIG_SCSI_PCI2220I is not set
-# CONFIG_SCSI_U14_34F is not set
-# CONFIG_SCSI_NSP32 is not set
# CONFIG_SCSI_DEBUG is not set
CONFIG_SCSI_ACORNSCSI_3=m
CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE=y
@@ -372,14 +305,145 @@ CONFIG_SCSI_CUMANA_1=m
CONFIG_SCSI_OAK1=m
#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
# I2O device support
#
-# CONFIG_I2O is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+CONFIG_NETLINK_DEV=y
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_IP_TCPDIAG is not set
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+CONFIG_IPV6=m
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+CONFIG_ARM_ETHER1=y
+CONFIG_ARM_ETHER3=y
+CONFIG_ARM_ETHERH=y
+# CONFIG_SMC91X 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_PLIP is not set
+CONFIG_PPP=m
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+# CONFIG_PPP_ASYNC is not set
+# CONFIG_PPP_SYNC_TTY is not set
+# CONFIG_PPP_DEFLATE is not set
+# CONFIG_PPP_BSDCOMP is not set
+CONFIG_PPPOE=m
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
#
# ISDN subsystem
#
-# CONFIG_ISDN_BOOL is not set
+# CONFIG_ISDN is not set
#
# Input device support
@@ -395,7 +459,6 @@ 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_TSLIBDEV is not set
CONFIG_INPUT_EVDEV=y
# CONFIG_INPUT_EVBUG is not set
@@ -405,11 +468,12 @@ CONFIG_INPUT_EVDEV=y
# 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_PARKBD is not set
CONFIG_SERIO_RPCKBD=y
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
#
# Input Device Drivers
@@ -417,12 +481,14 @@ CONFIG_SERIO_RPCKBD=y
CONFIG_INPUT_KEYBOARD=y
CONFIG_KEYBOARD_ATKBD=y
# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
# CONFIG_KEYBOARD_XTKBD is not set
# CONFIG_KEYBOARD_NEWTON is not set
CONFIG_INPUT_MOUSE=y
# CONFIG_MOUSE_PS2 is not set
# CONFIG_MOUSE_SERIAL is not set
CONFIG_MOUSE_RISCPC=y
+# CONFIG_MOUSE_VSXXXAA is not set
# CONFIG_INPUT_JOYSTICK is not set
# CONFIG_INPUT_TOUCHSCREEN is not set
# CONFIG_INPUT_MISC is not set
@@ -440,6 +506,7 @@ CONFIG_HW_CONSOLE=y
#
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=16
# CONFIG_SERIAL_8250_EXTENDED is not set
#
@@ -449,32 +516,17 @@ CONFIG_SERIAL_8250_ACORN=y
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=64
CONFIG_PRINTER=m
# CONFIG_LP_CONSOLE is not set
# CONFIG_PPDEV is not set
# CONFIG_TIPAR is not set
#
-# I2C support
-#
-CONFIG_I2C=y
-CONFIG_I2C_ALGOBIT=y
-# CONFIG_SCx200_ACB is not set
-# CONFIG_I2C_ALGOPCF is not set
-CONFIG_I2C_CHARDEV=y
-# CONFIG_I2C_PROC is not set
-
-#
-# L3 serial bus support
+# IPMI
#
-# CONFIG_L3 is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_QIC02_TAPE is not set
+# CONFIG_IPMI_HANDLER is not set
#
# Watchdog Cards
@@ -482,84 +534,292 @@ CONFIG_I2C_CHARDEV=y
# CONFIG_WATCHDOG is not set
# CONFIG_NVRAM is not set
# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
#
# Ftape, the floppy tape device driver
#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
# CONFIG_DRM is not set
# CONFIG_RAW_DRIVER is not set
#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=y
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ISA is not set
+# CONFIG_I2C_PARPORT is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Hardware Sensors Chip support
+#
+# CONFIG_I2C_SENSOR 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_ASB100 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+
+#
+# Other I2C Chip support
+#
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+CONFIG_FB_ACORN=y
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FONTS=y
+# CONFIG_FONT_8x8 is not set
+CONFIG_FONT_8x16=y
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+CONFIG_FONT_ACORN_8x8=y
+# CONFIG_FONT_MINI_4x6 is not set
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+
+#
+# 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
+
+#
+# Advanced Linux Sound Architecture
+#
+# CONFIG_SND is not set
+
+#
+# Open Sound System
+#
+CONFIG_SOUND_PRIME=m
+# CONFIG_SOUND_BT878 is not set
+# CONFIG_SOUND_FUSION is not set
+# CONFIG_SOUND_CS4281 is not set
+# CONFIG_SOUND_SONICVIBES is not set
+# CONFIG_SOUND_TRIDENT is not set
+# CONFIG_SOUND_MSNDCLAS is not set
+# CONFIG_SOUND_MSNDPIN is not set
+CONFIG_SOUND_OSS=m
+# CONFIG_SOUND_TRACEINIT is not set
+# CONFIG_SOUND_DMAP is not set
+# CONFIG_SOUND_AD1816 is not set
+# CONFIG_SOUND_AD1889 is not set
+# CONFIG_SOUND_SGALAXY is not set
+# CONFIG_SOUND_ADLIB is not set
+# CONFIG_SOUND_ACI_MIXER is not set
+# CONFIG_SOUND_CS4232 is not set
+# CONFIG_SOUND_SSCAPE is not set
+# CONFIG_SOUND_GUS is not set
+# CONFIG_SOUND_VMIDI is not set
+# CONFIG_SOUND_TRIX is not set
+# CONFIG_SOUND_MSS is not set
+# CONFIG_SOUND_MPU401 is not set
+# CONFIG_SOUND_NM256 is not set
+# CONFIG_SOUND_MAD16 is not set
+# CONFIG_SOUND_PAS is not set
+# CONFIG_SOUND_PSS is not set
+# CONFIG_SOUND_SB is not set
+# CONFIG_SOUND_AWE32_SYNTH is not set
+# CONFIG_SOUND_WAVEFRONT is not set
+# CONFIG_SOUND_MAUI is not set
+# CONFIG_SOUND_YM3812 is not set
+# CONFIG_SOUND_OPL3SA1 is not set
+# CONFIG_SOUND_OPL3SA2 is not set
+# CONFIG_SOUND_UART6850 is not set
+# CONFIG_SOUND_AEDSP16 is not set
+CONFIG_SOUND_VIDC=m
+# CONFIG_SOUND_TVMIXER is not set
+# CONFIG_SOUND_AD1980 is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
# File systems
#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
CONFIG_AUTOFS4_FS=m
-# CONFIG_REISERFS_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+# CONFIG_ZISOFS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=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_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
CONFIG_ADFS_FS=y
# CONFIG_ADFS_FS_RW 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_EXT3_FS=y
-CONFIG_EXT3_FS_XATTR=y
-# CONFIG_EXT3_FS_POSIX_ACL is not set
-CONFIG_JBD=y
-# CONFIG_JBD_DEBUG is not set
-# CONFIG_FAT_FS is not set
# CONFIG_EFS_FS is not set
# CONFIG_CRAMFS is not set
-# CONFIG_TMPFS is not set
-CONFIG_RAMFS=y
-CONFIG_ISO9660_FS=y
-CONFIG_JOLIET=y
-# CONFIG_ZISOFS is not set
-# CONFIG_JFS_FS is not set
-# CONFIG_MINIX_FS is not set
# CONFIG_VXFS_FS is not set
-# CONFIG_NTFS_FS is not set
# CONFIG_HPFS_FS is not set
-CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS=y
# CONFIG_QNX4FS_FS is not set
-# CONFIG_ROMFS_FS is not set
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_SYSV_FS is not set
-# CONFIG_UDF_FS is not set
# CONFIG_UFS_FS is not set
-# CONFIG_XFS_FS is not set
#
# Network File Systems
#
-# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
CONFIG_NFS_FS=y
# CONFIG_NFS_V3 is not set
# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
# CONFIG_NFSD is not set
-CONFIG_SUNRPC=y
CONFIG_LOCKD=y
-# CONFIG_EXPORTFS is not set
-# CONFIG_CIFS is not set
+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_FS_MBCACHE=y
#
# Partition Types
@@ -586,11 +846,11 @@ CONFIG_SGI_PARTITION=y
# CONFIG_ULTRIX_PARTITION is not set
CONFIG_SUN_PARTITION=y
# CONFIG_EFI_PARTITION is not set
-CONFIG_NLS=y
#
# Native Language Support
#
+CONFIG_NLS=y
CONFIG_NLS_DEFAULT="iso8859-1"
CONFIG_NLS_CODEPAGE_437=m
CONFIG_NLS_CODEPAGE_737=m
@@ -615,6 +875,7 @@ CONFIG_NLS_CODEPAGE_874=m
CONFIG_NLS_ISO8859_8=m
# CONFIG_NLS_CODEPAGE_1250 is not set
# CONFIG_NLS_CODEPAGE_1251 is not set
+CONFIG_NLS_ASCII=y
CONFIG_NLS_ISO8859_1=m
CONFIG_NLS_ISO8859_2=m
CONFIG_NLS_ISO8859_3=m
@@ -631,139 +892,35 @@ CONFIG_NLS_KOI8_R=m
# CONFIG_NLS_UTF8 is not set
#
-# Console drivers
-#
-
-#
-# Frame-buffer support
-#
-CONFIG_FB=y
-CONFIG_DUMMY_CONSOLE=y
-CONFIG_FB_ACORN=y
-# CONFIG_FB_VIRTUAL is not set
-CONFIG_FBCON_ADVANCED=y
-CONFIG_FBCON_MFB=y
-CONFIG_FBCON_CFB2=y
-CONFIG_FBCON_CFB4=y
-CONFIG_FBCON_CFB8=y
-CONFIG_FBCON_CFB16=y
-CONFIG_FBCON_CFB24=y
-CONFIG_FBCON_CFB32=y
-# CONFIG_FBCON_ACCEL is not set
-# CONFIG_FBCON_AFB is not set
-# CONFIG_FBCON_ILBM is not set
-# CONFIG_FBCON_IPLAN2P2 is not set
-# CONFIG_FBCON_IPLAN2P4 is not set
-# CONFIG_FBCON_IPLAN2P8 is not set
-# CONFIG_FBCON_VGA_PLANES is not set
-# CONFIG_FBCON_HGA is not set
-# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
-# CONFIG_FONT_SUN8x16 is not set
-# CONFIG_FONT_SUN12x22 is not set
-CONFIG_FBCON_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=y
-# CONFIG_FONT_MINI_4x6 is not set
-
-#
-# Sound
+# Profiling support
#
-CONFIG_SOUND=m
-
-#
-# Open Sound System
-#
-CONFIG_SOUND_PRIME=m
-# CONFIG_SOUND_BT878 is not set
-# CONFIG_SOUND_FUSION is not set
-# CONFIG_SOUND_CS4281 is not set
-# CONFIG_SOUND_ESSSOLO1 is not set
-# CONFIG_SOUND_MAESTRO is not set
-# CONFIG_SOUND_SONICVIBES is not set
-# CONFIG_SOUND_TRIDENT is not set
-# CONFIG_SOUND_MSNDCLAS is not set
-# CONFIG_SOUND_MSNDPIN is not set
-CONFIG_SOUND_OSS=m
-# CONFIG_SOUND_TRACEINIT is not set
-# CONFIG_SOUND_DMAP is not set
-# CONFIG_SOUND_AD1816 is not set
-# CONFIG_SOUND_SGALAXY is not set
-# CONFIG_SOUND_ADLIB is not set
-# CONFIG_SOUND_ACI_MIXER is not set
-# CONFIG_SOUND_CS4232 is not set
-# CONFIG_SOUND_SSCAPE is not set
-# CONFIG_SOUND_GUS is not set
-# CONFIG_SOUND_VMIDI is not set
-# CONFIG_SOUND_TRIX is not set
-# CONFIG_SOUND_MSS is not set
-# CONFIG_SOUND_MPU401 is not set
-# CONFIG_SOUND_NM256 is not set
-# CONFIG_SOUND_MAD16 is not set
-# CONFIG_SOUND_PAS is not set
-# CONFIG_SOUND_PSS is not set
-# CONFIG_SOUND_SB is not set
-# CONFIG_SOUND_AWE32_SYNTH is not set
-# CONFIG_SOUND_WAVEFRONT is not set
-# CONFIG_SOUND_MAUI is not set
-# CONFIG_SOUND_YM3812 is not set
-# CONFIG_SOUND_OPL3SA1 is not set
-# CONFIG_SOUND_OPL3SA2 is not set
-# CONFIG_SOUND_UART6850 is not set
-# CONFIG_SOUND_AEDSP16 is not set
-CONFIG_SOUND_VIDC=m
-# CONFIG_SOUND_TVMIXER is not set
-
-#
-# Advanced Linux Sound Architecture
-#
-# CONFIG_SND is not set
-
-#
-# Misc devices
-#
-
-#
-# Multimedia Capabilities Port drivers
-#
-# CONFIG_MCP is not set
-
-#
-# Console Switches
-#
-# CONFIG_SWITCHES is not set
-
-#
-# USB support
-#
-
-#
-# Bluetooth support
-#
-# CONFIG_BT is not set
+# CONFIG_PROFILING is not set
#
# Kernel hacking
#
-CONFIG_FRAME_POINTER=y
-CONFIG_DEBUG_USER=y
-# CONFIG_DEBUG_INFO is not set
CONFIG_DEBUG_KERNEL=y
-# CONFIG_DEBUG_SLAB is not set
CONFIG_MAGIC_SYSRQ=y
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
# CONFIG_DEBUG_SPINLOCK 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_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
# CONFIG_DEBUG_WAITQ is not set
-# CONFIG_DEBUG_BUGVERBOSE is not set
CONFIG_DEBUG_ERRORS=y
-# CONFIG_KALLSYMS is not set
CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
#
# Security options
#
-CONFIG_SECURITY_CAPABILITIES=y
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
#
# Cryptographic options
@@ -771,6 +928,12 @@ CONFIG_SECURITY_CAPABILITIES=y
# CONFIG_CRYPTO is not set
#
+# Hardware crypto devices
+#
+
+#
# Library routines
#
-# CONFIG_CRC32 is not set
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
diff --git a/arch/arm/configs/s3c2410_defconfig b/arch/arm/configs/s3c2410_defconfig
index e8c2255aae911..2a63fb2771967 100644
--- a/arch/arm/configs/s3c2410_defconfig
+++ b/arch/arm/configs/s3c2410_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc1-bk5
-# Tue Jan 18 11:36:49 2005
+# Linux kernel version: 2.6.12-rc1-bk2
+# Sun Mar 27 17:47:45 2005
#
CONFIG_ARM=y
CONFIG_MMU=y
@@ -28,7 +28,6 @@ CONFIG_SYSVIPC=y
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=16
# CONFIG_HOTPLUG is not set
CONFIG_KOBJECT_UEVENT=y
# CONFIG_IKCONFIG is not set
@@ -36,6 +35,7 @@ CONFIG_KOBJECT_UEVENT=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
@@ -45,6 +45,7 @@ CONFIG_CC_ALIGN_LABELS=0
CONFIG_CC_ALIGN_LOOPS=0
CONFIG_CC_ALIGN_JUMPS=0
# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
#
# Loadable module support
@@ -86,13 +87,22 @@ CONFIG_ARCH_S3C2410=y
#
CONFIG_ARCH_BAST=y
CONFIG_ARCH_H1940=y
+CONFIG_MACH_N30=y
CONFIG_ARCH_SMDK2410=y
+CONFIG_ARCH_S3C2440=y
CONFIG_MACH_VR1000=y
CONFIG_MACH_RX3715=y
+CONFIG_MACH_OTOM=y
+CONFIG_MACH_NEXCODER_2440=y
CONFIG_CPU_S3C2410=y
CONFIG_CPU_S3C2440=y
#
+# S3C2410 Boot
+#
+# CONFIG_S3C2410_BOOT_WATCHDOG is not set
+
+#
# S3C2410 Setup
#
CONFIG_S3C2410_DMA=y
@@ -122,11 +132,8 @@ CONFIG_CPU_TLB_V4WBI=y
# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
#
-# General setup
+# Bus support
#
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-# CONFIG_XIP_KERNEL is not set
#
# PCCARD (PCMCIA/CardBus) support
@@ -134,49 +141,63 @@ CONFIG_ZBOOT_ROM_BSS=0x0
# CONFIG_PCCARD is not set
#
-# PC-card bridges
+# Kernel Features
+#
+# CONFIG_PREEMPT is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="root=/dev/hda1 ro init=/bin/bash console=ttySAC0"
+# CONFIG_XIP_KERNEL is not set
+
+#
+# Floating point emulation
#
#
-# At least one math emulation must be selected
+# 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=y
# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
#
-# Generic Driver Options
+# Power management options
#
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
-# CONFIG_DEBUG_DRIVER is not set
CONFIG_PM=y
-# CONFIG_PREEMPT is not set
CONFIG_APM=y
-# CONFIG_ARTHUR is not set
-CONFIG_CMDLINE="root=/dev/hda1 ro init=/bin/bash console=ttySAC0"
-CONFIG_ALIGNMENT_TRAP=y
#
-# Parallel port support
+# Device Drivers
#
-CONFIG_PARPORT=y
-# CONFIG_PARPORT_PC is not set
-# CONFIG_PARPORT_ARC is not set
-CONFIG_PARPORT_OTHER=y
-CONFIG_PARPORT_1284=y
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
#
# Memory Technology Devices (MTD)
#
CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
-CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
CONFIG_MTD_REDBOOT_PARTS=y
CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
@@ -261,6 +282,15 @@ CONFIG_MTD_NAND_S3C2410=y
# CONFIG_MTD_NAND_NANDSIM is not set
#
+# Parallel port support
+#
+CONFIG_PARPORT=y
+# CONFIG_PARPORT_PC is not set
+# CONFIG_PARPORT_ARC is not set
+# CONFIG_PARPORT_GSC is not set
+CONFIG_PARPORT_1284=y
+
+#
# Plug and Play support
#
@@ -290,11 +320,56 @@ CONFIG_IOSCHED_CFQ=y
CONFIG_ATA_OVER_ETH=m
#
+# 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=y
+CONFIG_BLK_DEV_IDETAPE=m
+CONFIG_BLK_DEV_IDEFLOPPY=m
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+# CONFIG_IDE_ARM is not set
+CONFIG_BLK_DEV_IDE_BAST=y
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
# Multi-device support (RAID and LVM)
#
# CONFIG_MD is not set
#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+
+#
# Networking support
#
CONFIG_NET=y
@@ -399,51 +474,6 @@ CONFIG_NET_ETHERNET=y
# CONFIG_NETCONSOLE 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=y
-CONFIG_BLK_DEV_IDETAPE=m
-CONFIG_BLK_DEV_IDEFLOPPY=m
-# CONFIG_IDE_TASK_IOCTL is not set
-
-#
-# IDE chipset support/bugfixes
-#
-CONFIG_IDE_GENERIC=y
-# CONFIG_IDE_ARM is not set
-CONFIG_BLK_DEV_IDE_BAST=y
-# CONFIG_BLK_DEV_IDEDMA is not set
-# CONFIG_IDEDMA_AUTO is not set
-# CONFIG_BLK_DEV_HD is not set
-
-#
-# SCSI device support
-#
-# CONFIG_SCSI is not set
-
-#
-# Fusion MPT device support
-#
-
-#
-# IEEE 1394 (FireWire) support
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-
-#
# ISDN subsystem
#
# CONFIG_ISDN is not set
@@ -466,18 +496,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_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PARKBD is not set
-CONFIG_SERIO_LIBPS2=y
-# CONFIG_SERIO_RAW is not set
-
-#
# Input Device Drivers
#
CONFIG_INPUT_KEYBOARD=y
@@ -495,6 +513,17 @@ CONFIG_MOUSE_PS2=y
# CONFIG_INPUT_MISC is not set
#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_PARKBD is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
+#
# Character devices
#
CONFIG_VT=y
@@ -505,7 +534,6 @@ CONFIG_SERIAL_NONSTANDARD=y
# CONFIG_ROCKETPORT is not set
# CONFIG_CYCLADES is not set
# CONFIG_DIGIEPCA is not set
-# CONFIG_DIGI is not set
# CONFIG_MOXA_INTELLIO is not set
# CONFIG_MOXA_SMARTIO is not set
# CONFIG_ISI is not set
@@ -575,6 +603,11 @@ CONFIG_S3C2410_RTC=y
# CONFIG_RAW_DRIVER is not set
#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
# I2C support
#
CONFIG_I2C=y
@@ -608,7 +641,9 @@ CONFIG_I2C_SENSOR=m
# CONFIG_SENSORS_ASB100 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
# CONFIG_SENSORS_IT87 is not set
# CONFIG_SENSORS_LM63 is not set
CONFIG_SENSORS_LM75=m
@@ -640,6 +675,10 @@ CONFIG_SENSORS_EEPROM=m
# CONFIG_I2C_DEBUG_CHIP is not set
#
+# Misc devices
+#
+
+#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -650,6 +689,53 @@ CONFIG_SENSORS_EEPROM=m
# CONFIG_DVB is not set
#
+# Graphics support
+#
+CONFIG_FB=y
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_SOFT_CURSOR is not set
+CONFIG_FB_MODE_HELPERS=y
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE is not set
+
+#
+# Logo configuration
+#
+# CONFIG_LOGO is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -663,6 +749,10 @@ CONFIG_JBD=y
CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
# CONFIG_XFS_FS is not set
# CONFIG_MINIX_FS is not set
CONFIG_ROMFS_FS=y
@@ -737,7 +827,6 @@ CONFIG_NFS_FS=y
# CONFIG_NFSD is not set
CONFIG_ROOT_NFS=y
CONFIG_LOCKD=y
-# CONFIG_EXPORTFS is not set
CONFIG_SUNRPC=y
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
@@ -817,64 +906,16 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_PROFILING is not set
#
-# Graphics support
-#
-CONFIG_FB=y
-CONFIG_FB_MODE_HELPERS=y
-# CONFIG_FB_TILEBLITTING is not set
-# CONFIG_FB_VIRTUAL is not set
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-# CONFIG_FRAMEBUFFER_CONSOLE is not set
-
-#
-# Logo configuration
-#
-# CONFIG_LOGO is not set
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# Misc devices
-#
-
-#
-# USB support
-#
-# CONFIG_USB is not set
-CONFIG_USB_ARCH_HAS_HCD=y
-# CONFIG_USB_ARCH_HAS_OHCI is not set
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
-# CONFIG_MMC 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=16
# CONFIG_SCHEDSTATS is not set
# CONFIG_DEBUG_SLAB is not set
# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
# CONFIG_DEBUG_KOBJECT is not set
CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_DEBUG_INFO=y
diff --git a/arch/arm/configs/shannon_defconfig b/arch/arm/configs/shannon_defconfig
index 393731f70a523..e3facc4fe792c 100644
--- a/arch/arm/configs/shannon_defconfig
+++ b/arch/arm/configs/shannon_defconfig
@@ -1,33 +1,63 @@
#
# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.12-rc1-bk2
+# Sun Mar 27 23:26:46 2005
#
CONFIG_ARM=y
-# CONFIG_EISA is not set
-# CONFIG_SBUS is not set
-# CONFIG_MCA is not set
+CONFIG_MMU=y
CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
-# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
-# CONFIG_GENERIC_BUST_SPINLOCK is not set
-# CONFIG_GENERIC_ISA_DMA is not set
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_IOMAP=y
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_OBSOLETE=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
#
# Loadable module support
#
CONFIG_MODULES=y
+# CONFIG_MODULE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
# CONFIG_KMOD is not set
#
# System Type
#
-# CONFIG_ARCH_ARCA5K is not set
# CONFIG_ARCH_CLPS7500 is not set
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
@@ -35,133 +65,139 @@ CONFIG_MODULES=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
+# 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=y
+# CONFIG_ARCH_S3C2410 is not set
# CONFIG_ARCH_SHARK is not set
-
-#
-# Archimedes/A5000 Implementations
-#
-
-#
-# Archimedes/A5000 Implementations (select only ONE)
-#
-
-#
-# Footbridge Implementations
-#
+# 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
#
# SA11x0 Implementations
#
# CONFIG_SA1100_ASSABET is not set
-# CONFIG_SA1100_ADSBITSY is not set
-# CONFIG_SA1100_BRUTUS is not set
# CONFIG_SA1100_CERF is not set
+# CONFIG_SA1100_COLLIE is not set
+# CONFIG_SA1100_H3100 is not set
# CONFIG_SA1100_H3600 is not set
-# CONFIG_SA1100_EXTENEX1 is not set
-# CONFIG_SA1100_FLEXANET is not set
-# CONFIG_SA1100_FREEBIRD is not set
-# CONFIG_SA1100_GRAPHICSCLIENT is not set
-# CONFIG_SA1100_GRAPHICSMASTER is not set
+# CONFIG_SA1100_H3800 is not set
+# CONFIG_SA1100_BADGE4 is not set
# CONFIG_SA1100_JORNADA720 is not set
-# CONFIG_SA1100_HUW_WEBPANEL is not set
-# CONFIG_SA1100_ITSY is not set
+# CONFIG_SA1100_HACKKIT is not set
# CONFIG_SA1100_LART is not set
-# CONFIG_SA1100_NANOENGINE is not set
-# CONFIG_SA1100_OMNIMETER is not set
-# CONFIG_SA1100_PANGOLIN is not set
# CONFIG_SA1100_PLEB is not set
CONFIG_SA1100_SHANNON=y
-# CONFIG_SA1100_SHERMAN is not set
# CONFIG_SA1100_SIMPAD is not set
-# CONFIG_SA1100_PFS168 is not set
-# CONFIG_SA1100_VICTOR is not set
-# CONFIG_SA1100_XP860 is not set
-# CONFIG_SA1100_YOPY is not set
-# CONFIG_SA1100_USB is not set
+# CONFIG_SA1100_SSP is not set
#
-# CLPS711X/EP721X Implementations
+# Processor Type
#
-# CONFIG_ARCH_EP7211 is not set
-# CONFIG_ARCH_EP7212 is not set
-# CONFIG_ARCH_ACORN is not set
-# CONFIG_FOOTBRIDGE is not set
-# CONFIG_FOOTBRIDGE_HOST is not set
-# CONFIG_FOOTBRIDGE_ADDIN is not set
CONFIG_CPU_32=y
-# CONFIG_CPU_26 is not set
+CONFIG_CPU_SA1100=y
+CONFIG_CPU_32v4=y
+CONFIG_CPU_ABRT_EV4=y
+CONFIG_CPU_CACHE_V4WB=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_TLB_V4WB=y
+CONFIG_CPU_MINICACHE=y
#
-# Processor Type
+# Processor Features
#
-# CONFIG_CPU_32v3 is not set
-CONFIG_CPU_32v4=y
-# CONFIG_CPU_ARM610 is not set
-# CONFIG_CPU_ARM710 is not set
-# CONFIG_CPU_ARM720T is not set
-# CONFIG_CPU_ARM920T is not set
-# CONFIG_CPU_ARM922T is not set
-# CONFIG_CPU_ARM926T is not set
-# CONFIG_CPU_ARM1020 is not set
-# CONFIG_CPU_SA110 is not set
-CONFIG_CPU_SA1100=y
-# CONFIG_ARM_THUMB is not set
-CONFIG_DISCONTIGMEM=y
#
-# General setup
+# Bus support
#
-# CONFIG_PCI is not set
CONFIG_ISA=y
-# CONFIG_ISA_DMA is not set
-# CONFIG_CPU_FREQ is not set
-CONFIG_HOTPLUG=y
#
-# PCMCIA/CardBus support
+# PCCARD (PCMCIA/CardBus) support
#
+CONFIG_PCCARD=y
+# CONFIG_PCMCIA_DEBUG is not set
CONFIG_PCMCIA=y
-# CONFIG_I82092 is not set
+
+#
+# PC-card bridges
+#
# CONFIG_I82365 is not set
# CONFIG_TCIC is not set
CONFIG_PCMCIA_SA1100=y
-CONFIG_NET=y
-CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
#
-# At least one math emulation must be selected
+# Kernel Features
+#
+# CONFIG_PREEMPT is not set
+CONFIG_DISCONTIGMEM=y
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="console=ttySA0,9600 console=tty1 root=/dev/mtdblock2 init=/linuxrc"
+# CONFIG_XIP_KERNEL is not set
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ 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
-CONFIG_KCORE_ELF=y
-# CONFIG_KCORE_AOUT is not set
-# CONFIG_BINFMT_AOUT is not set
+
+#
+# Userspace binary formats
+#
CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
# CONFIG_BINFMT_MISC is not set
-# CONFIG_PM is not set
# CONFIG_ARTHUR is not set
-CONFIG_CMDLINE="console=ttySA0,9600 console=tty1 root=/dev/mtdblock2 init=/linuxrc"
-# CONFIG_LEDS is not set
-CONFIG_ALIGNMENT_TRAP=y
#
-# Parallel port support
+# Power management options
#
-# CONFIG_PARPORT is not set
+# CONFIG_PM is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
#
# Memory Technology Devices (MTD)
#
CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_REDBOOT_PARTS is not set
-# CONFIG_MTD_BOOTLDR_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
# CONFIG_MTD_AFS_PARTS is not set
#
@@ -171,6 +207,7 @@ CONFIG_MTD_CHAR=y
CONFIG_MTD_BLOCK=y
# CONFIG_FTL is not set
# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
#
# RAM/ROM/Flash chip drivers
@@ -179,36 +216,49 @@ 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
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
#
# Mapping drivers for chip access
#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
# CONFIG_MTD_PHYSMAP is not set
-# CONFIG_MTD_NORA is not set
# CONFIG_MTD_ARM_INTEGRATOR is not set
CONFIG_MTD_SA1100=y
-# CONFIG_MTD_IQ80310 is not set
+# CONFIG_MTD_EDB7312 is not set
#
# Self-contained MTD device drivers
#
# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
# CONFIG_MTD_MTDRAM is not set
# CONFIG_MTD_BLKMTD is not set
+# CONFIG_MTD_BLOCK2MTD is not set
#
# Disk-On-Chip Device Drivers
#
-# CONFIG_MTD_DOC1000 is not set
# CONFIG_MTD_DOC2000 is not set
# CONFIG_MTD_DOC2001 is not set
-# CONFIG_MTD_DOCPROBE is not set
+# CONFIG_MTD_DOC2001PLUS is not set
#
# NAND Flash Device Drivers
@@ -216,7 +266,12 @@ CONFIG_MTD_SA1100=y
# CONFIG_MTD_NAND is not set
#
-# Plug and Play configuration
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
#
# CONFIG_PNP is not set
@@ -225,11 +280,57 @@ CONFIG_MTD_SA1100=y
#
# CONFIG_BLK_DEV_FD is not set
# CONFIG_BLK_DEV_XD is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
# CONFIG_BLK_DEV_LOOP is not set
# CONFIG_BLK_DEV_NBD is not set
CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=8192
CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=m
+CONFIG_BLK_DEV_IDE=m
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+# CONFIG_BLK_DEV_IDEDISK is not set
+# 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
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=m
+# CONFIG_IDE_ARM is not set
+# CONFIG_IDE_CHIPSETS is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
#
# Multi-device support (RAID and LVM)
@@ -237,67 +338,99 @@ CONFIG_BLK_DEV_INITRD=y
# CONFIG_MD is not set
#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
# Networking options
#
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
-# CONFIG_NETLINK is not set
-# CONFIG_NETFILTER is not set
-# CONFIG_FILTER is not set
+# CONFIG_NETLINK_DEV is not set
CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
CONFIG_INET=y
# CONFIG_IP_MULTICAST is not set
# CONFIG_IP_ADVANCED_ROUTER is not set
# CONFIG_IP_PNP is not set
# CONFIG_NET_IPIP is not set
# CONFIG_NET_IPGRE is not set
-# CONFIG_INET_ECN 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_KHTTPD is not set
-# CONFIG_ATM 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_DECNET is not set
-# CONFIG_BRIDGE is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
-# CONFIG_LLC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
#
# QoS and/or fair queueing
#
# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
#
-# Network device support
+# Network testing
#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
#
# ARCnet devices
#
# CONFIG_ARCNET is not set
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
#
# Ethernet (10 or 100Mbit)
#
CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_LANCE is not set
# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_SMC91X is not set
# CONFIG_NET_VENDOR_RACAL is not set
# CONFIG_AT1700 is not set
# CONFIG_DEPCA is not set
@@ -309,28 +442,20 @@ CONFIG_NET_ETHERNET=y
#
# Ethernet (1000 Mbit)
#
-# CONFIG_ACENIC_OMIT_TIGON_I is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
#
-# Wireless LAN (non-hamradio)
+# Ethernet (10000 Mbit)
#
-# CONFIG_NET_RADIO is not set
#
# Token Ring devices
#
# CONFIG_TR is not set
-# CONFIG_NET_FC is not set
-# CONFIG_SHAPER is not set
#
-# Wan interfaces
+# Wireless LAN (non-hamradio)
#
-# CONFIG_WAN is not set
+# CONFIG_NET_RADIO is not set
#
# PCMCIA network device support
@@ -343,90 +468,136 @@ CONFIG_PCMCIA_PCNET=y
# CONFIG_PCMCIA_NMCLAN is not set
CONFIG_PCMCIA_SMC91C92=y
# CONFIG_PCMCIA_XIRC2PS is not set
-# CONFIG_NET_PCMCIA_RADIO is not set
+# CONFIG_PCMCIA_AXNET is not set
#
-# Amateur Radio support
+# Wan interfaces
#
-# CONFIG_HAMRADIO is not set
+# 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
#
-# IrDA (infrared) support
+# ISDN subsystem
#
-# CONFIG_IRDA is not set
+# CONFIG_ISDN is not set
#
-# ATA/IDE/MFM/RLL support
+# Input device support
#
-CONFIG_IDE=m
+CONFIG_INPUT=y
#
-# IDE, ATA and ATAPI Block devices
+# Userland interfaces
#
-CONFIG_BLK_DEV_IDE=m
+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
#
-# Please see Documentation/ide.txt for help/info on IDE drives
+# Input Device Drivers
#
-# CONFIG_BLK_DEV_HD_IDE is not set
-# CONFIG_BLK_DEV_HD is not set
-# CONFIG_BLK_DEV_IDEDISK 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
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_INPORT is not set
+# CONFIG_MOUSE_LOGIBM is not set
+# CONFIG_MOUSE_PC110PAD is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
#
-# IDE chipset support/bugfixes
+# Hardware I/O ports
#
-# CONFIG_BLK_DEV_CMD640 is not set
-# CONFIG_IDE_CHIPSETS is not set
-# CONFIG_IDEDMA_AUTO is not set
-# CONFIG_BLK_DEV_ATARAID is not set
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
#
-# SCSI support
+# Character devices
#
-# CONFIG_SCSI is not set
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
#
-# I2O device support
+# Serial drivers
#
-# CONFIG_I2O is not set
+# CONFIG_SERIAL_8250 is not set
#
-# ISDN subsystem
+# Non-8250 serial port support
#
-# CONFIG_ISDN is not set
+CONFIG_SERIAL_SA1100=y
+CONFIG_SERIAL_SA1100_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
#
-# Input core support
+# IPMI
#
-CONFIG_INPUT=y
-CONFIG_INPUT_KEYBDEV=y
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_EVDEV is not set
+# CONFIG_IPMI_HANDLER is not set
#
-# Character devices
+# Watchdog Cards
#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-# CONFIG_SERIAL is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
#
-# Serial drivers
+# Watchdog Device Drivers
#
-CONFIG_SERIAL_SA1100=y
-CONFIG_SERIAL_SA1100_CONSOLE=y
-CONFIG_SA1100_DEFAULT_BAUDRATE=9600
-# CONFIG_SERIAL_8250 is not set
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_SA1100_WATCHDOG=y
+
+#
+# ISA-based Watchdog Cards
+#
+# CONFIG_PCWATCHDOG is not set
+# CONFIG_MIXCOMWD is not set
+# CONFIG_WDT is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+
+#
+# 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,129 +605,168 @@ CONFIG_UNIX98_PTY_COUNT=256
# CONFIG_I2C is not set
#
-# L3 serial bus support
+# Misc devices
#
-# CONFIG_L3 is not set
#
-# Other L3 adapters
+# Multimedia devices
#
-# CONFIG_BIT_SA1100_GPIO is not set
+# CONFIG_VIDEO_DEV is not set
#
-# Mice
+# Digital Video Broadcasting Devices
#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_MOUSE is not set
+# CONFIG_DVB is not set
#
-# Joysticks
+# Graphics support
#
-# CONFIG_INPUT_GAMEPORT is not set
-# CONFIG_INPUT_SERIO is not set
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+CONFIG_FB_SOFT_CURSOR=y
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+CONFIG_FB_SA1100=y
+# CONFIG_FB_VIRTUAL is not set
#
-# Joysticks
+# Console display driver support
#
-# CONFIG_QIC02_TAPE is not set
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE is not set
#
-# Watchdog Cards
+# Logo configuration
#
-CONFIG_WATCHDOG=y
-# CONFIG_WATCHDOG_NOWAYOUT is not set
-# CONFIG_SOFT_WATCHDOG is not set
-# CONFIG_WDT is not set
-# CONFIG_WDTPCI is not set
-# CONFIG_PCWATCHDOG is not set
-# CONFIG_ACQUIRE_WDT is not set
-# CONFIG_ADVANTECH_WDT is not set
-CONFIG_SA1100_WATCHDOG=y
-# CONFIG_EUROTECH_WDT is not set
-# CONFIG_IB700_WDT is not set
-# CONFIG_MIXCOMWD is not set
-# CONFIG_60XX_WDT is not set
-# CONFIG_W83877F_WDT is not set
-# CONFIG_MACHZ_WDT is not set
-# CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
-CONFIG_SA1100_RTC=y
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
+# CONFIG_LOGO is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
-# Ftape, the floppy tape device driver
+# Sound
#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
+CONFIG_SOUND=y
#
-# PCMCIA character devices
+# Advanced Linux Sound Architecture
#
+# CONFIG_SND is not set
#
-# Multimedia devices
+# Open Sound System
#
-# CONFIG_VIDEO_DEV is not set
+# CONFIG_SOUND_PRIME is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
#
# File systems
#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
+# CONFIG_XFS_FS is not set
+CONFIG_MINIX_FS=y
+# CONFIG_ROMFS_FS is not set
# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
-# CONFIG_REISERFS_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# 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_CMS_FS is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_JBD is not set
-CONFIG_FAT_FS=y
-CONFIG_MSDOS_FS=y
-# CONFIG_UMSDOS_FS is not set
-CONFIG_VFAT_FS=y
# CONFIG_EFS_FS is not set
# CONFIG_JFFS_FS is not set
CONFIG_JFFS2_FS=y
CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_JFFS2_FS_NAND is not set
+# CONFIG_JFFS2_FS_NOR_ECC is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
# CONFIG_CRAMFS is not set
-# CONFIG_TMPFS is not set
-CONFIG_RAMFS=y
-# CONFIG_ISO9660_FS is not set
-CONFIG_MINIX_FS=y
-# CONFIG_FREEVXFS_FS is not set
-# CONFIG_NTFS_FS is not set
-# CONFIG_NTFS_DEBUG is not set
-# CONFIG_NTFS_RW is not set
+# CONFIG_VXFS_FS is not set
# CONFIG_HPFS_FS is not set
-CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS=y
# CONFIG_QNX4FS_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_EXT2_FS is not set
# CONFIG_SYSV_FS is not set
-# CONFIG_UDF_FS is not set
# CONFIG_UFS_FS is not set
#
# Network File Systems
#
-# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
CONFIG_NFS_FS=y
# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
# CONFIG_NFSD is not set
-CONFIG_SUNRPC=y
CONFIG_LOCKD=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_ZISOFS_FS is not set
-# CONFIG_ZLIB_FS_INFLATE is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
#
# Partition Types
@@ -576,12 +786,12 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_SGI_PARTITION is not set
# CONFIG_ULTRIX_PARTITION is not set
# CONFIG_SUN_PARTITION is not set
-# CONFIG_SMB_NLS is not set
-CONFIG_NLS=y
+# CONFIG_EFI_PARTITION is not set
#
# Native Language Support
#
+CONFIG_NLS=y
CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_NLS_CODEPAGE_437 is not set
# CONFIG_NLS_CODEPAGE_737 is not set
@@ -604,7 +814,9 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# 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
@@ -621,112 +833,40 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_NLS_UTF8 is not set
#
-# Console drivers
-#
-CONFIG_PC_KEYMAP=y
-# CONFIG_VGA_CONSOLE is not set
-
-#
-# Frame-buffer support
-#
-CONFIG_FB=y
-CONFIG_DUMMY_CONSOLE=y
-CONFIG_FB_SA1100=y
-# CONFIG_FB_VIRTUAL is not set
-# CONFIG_FBCON_ADVANCED is not set
-CONFIG_FBCON_CFB2=y
-CONFIG_FBCON_CFB4=y
-CONFIG_FBCON_CFB8=y
-CONFIG_FBCON_CFB16=y
-# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
-# CONFIG_FBCON_FONTS is not set
-CONFIG_FONT_8x8=y
-CONFIG_FONT_8x16=y
-
-#
-# Sound
-#
-CONFIG_SOUND=y
-# CONFIG_SOUND_BT878 is not set
-# CONFIG_SOUND_FUSION is not set
-# CONFIG_SOUND_CS4281 is not set
-# CONFIG_SOUND_ESSSOLO1 is not set
-# CONFIG_SOUND_MAESTRO is not set
-# CONFIG_SOUND_SONICVIBES is not set
-# CONFIG_SOUND_TRIDENT is not set
-# CONFIG_SOUND_MSNDCLAS is not set
-# CONFIG_SOUND_MSNDPIN is not set
-CONFIG_SOUND_SA1100=y
-# CONFIG_SOUND_SA1100SSP is not set
-# CONFIG_SOUND_OSS is not set
-
-#
-# Multimedia Capabilities Port drivers
-#
-CONFIG_MCP=y
-CONFIG_MCP_SA1100=y
-CONFIG_MCP_UCB1200=y
-CONFIG_MCP_UCB1200_AUDIO=y
-CONFIG_MCP_UCB1200_TS=y
-
-#
-# USB support
-#
-# CONFIG_USB is not set
-
-#
-# USB Controllers
-#
-
-#
-# USB Device Class drivers
+# Profiling support
#
+# CONFIG_PROFILING is not set
#
-# USB Human Interface Devices (HID)
-#
-
-#
-# USB Imaging devices
-#
-
-#
-# USB Multimedia devices
-#
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
-#
-# USB Network adaptors
-#
-
-#
-# USB port drivers
+# Kernel hacking
#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
#
-# USB Serial Converter support
+# Security options
#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
#
-# USB Miscellaneous drivers
+# Cryptographic options
#
+# CONFIG_CRYPTO is not set
#
-# Bluetooth support
+# Hardware crypto devices
#
-# CONFIG_BT is not set
#
-# Kernel hacking
+# Library routines
#
-CONFIG_FRAME_POINTER=y
-CONFIG_DEBUG_ERRORS=y
-CONFIG_DEBUG_USER=y
-# CONFIG_DEBUG_INFO is not set
-# CONFIG_DEBUG_SLAB is not set
-CONFIG_MAGIC_SYSRQ=y
-# CONFIG_DEBUG_SPINLOCK is not set
-CONFIG_DEBUG_LL=y
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/arm/configs/shark_defconfig b/arch/arm/configs/shark_defconfig
index f455e3b417667..1d9bcbbc8dfc8 100644
--- a/arch/arm/configs/shark_defconfig
+++ b/arch/arm/configs/shark_defconfig
@@ -1,36 +1,50 @@
#
# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.12-rc1-bk2
+# Sun Mar 27 23:59:14 2005
#
CONFIG_ARM=y
CONFIG_MMU=y
CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_IOMAP=y
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
# CONFIG_CLEAN_COMPILE is not set
-# CONFIG_STANDALONE is not set
CONFIG_BROKEN=y
CONFIG_BROKEN_ON_SMP=y
#
# General setup
#
+CONFIG_LOCALVERSION=""
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
-CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_AUDIT is not set
+# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
# CONFIG_IKCONFIG is not set
# CONFIG_EMBEDDED is not set
CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
#
# Loadable module support
@@ -40,125 +54,134 @@ 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
#
# System Type
#
-# CONFIG_ARCH_ADIFCC is not set
# CONFIG_ARCH_CLPS7500 is not set
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
-# CONFIG_ARCH_PXA 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=y
+# 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
#
-# CLPS711X/EP721X Implementations
+# Processor Type
#
+CONFIG_CPU_32=y
+CONFIG_CPU_SA110=y
+CONFIG_CPU_32v4=y
+CONFIG_CPU_ABRT_EV4=y
+CONFIG_CPU_CACHE_V4WB=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WB=y
#
-# Epxa10db
+# Processor Features
#
#
-# Footbridge Implementations
+# Bus support
#
+CONFIG_ISA=y
+CONFIG_ISA_DMA=y
+CONFIG_PCI=y
+CONFIG_PCI_HOST_VIA82C505=y
+CONFIG_PCI_LEGACY_PROC=y
+# CONFIG_PCI_NAMES is not set
#
-# IOP3xx Implementation Options
+# PCCARD (PCMCIA/CardBus) support
#
-# CONFIG_ARCH_IOP310 is not set
-# CONFIG_ARCH_IOP321 is not set
+# CONFIG_PCCARD is not set
#
-# IOP3xx Chipset Features
+# Kernel Features
#
+# CONFIG_PREEMPT is not set
+CONFIG_LEDS=y
+CONFIG_LEDS_TIMER=y
+# CONFIG_LEDS_CPU is not set
+CONFIG_ALIGNMENT_TRAP=y
#
-# Intel PXA250/210 Implementations
+# Boot options
#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE=""
+# CONFIG_XIP_KERNEL is not set
#
-# SA11x0 Implementations
+# Floating point emulation
#
#
-# Processor Type
+# At least one emulation must be selected
#
-CONFIG_CPU_32=y
-CONFIG_CPU_SA110=y
-CONFIG_CPU_32v4=y
-CONFIG_CPU_ABRT_EV4=y
-CONFIG_CPU_CACHE_V4WB=y
-CONFIG_CPU_COPY_V4WB=y
-CONFIG_CPU_TLB_V4WB=y
+# CONFIG_FPE_NWFPE is not set
+CONFIG_FPE_FASTFPE=y
#
-# Processor Features
+# Userspace binary formats
#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
#
-# General setup
+# Power management options
#
-CONFIG_PCI=y
-CONFIG_PCI_HOST_VIA82C505=y
-CONFIG_ISA=y
-CONFIG_ISA_DMA=y
-# CONFIG_ZBOOT_ROM is not set
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_PCI_LEGACY_PROC=y
-# CONFIG_PCI_NAMES is not set
-# CONFIG_HOTPLUG is not set
+# CONFIG_PM is not set
#
-# At least one math emulation must be selected
+# Device Drivers
#
-# CONFIG_FPE_NWFPE is not set
-CONFIG_FPE_FASTFPE=y
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_AOUT is not set
-# CONFIG_BINFMT_MISC is not set
#
# Generic Driver Options
#
-# CONFIG_PM is not set
-# CONFIG_PREEMPT is not set
-# CONFIG_ARTHUR is not set
-CONFIG_CMDLINE=""
-CONFIG_LEDS=y
-CONFIG_LEDS_TIMER=y
-# CONFIG_LEDS_CPU is not set
-CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_STANDALONE is not set
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
#
# Parallel port support
#
CONFIG_PARPORT=y
CONFIG_PARPORT_PC=y
-CONFIG_PARPORT_PC_CML1=y
# CONFIG_PARPORT_SERIAL is not set
# CONFIG_PARPORT_PC_FIFO is not set
# CONFIG_PARPORT_PC_SUPERIO is not set
# CONFIG_PARPORT_ARC is not set
-# CONFIG_PARPORT_OTHER is not set
+# CONFIG_PARPORT_GSC is not set
# CONFIG_PARPORT_1284 is not set
#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
# Plug and Play support
#
# CONFIG_PNP is not set
@@ -173,12 +196,144 @@ CONFIG_PARPORT_PC_CML1=y
# CONFIG_BLK_CPQ_CISS_DA is not set
# CONFIG_BLK_DEV_DAC960 is not set
# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# 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=y
+# CONFIG_BLK_DEV_IDETAPE is not set
+CONFIG_BLK_DEV_IDEFLOPPY=y
+# CONFIG_BLK_DEV_IDESCSI is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+# CONFIG_BLK_DEV_IDEPCI is not set
+CONFIG_IDE_ARM=y
+# CONFIG_IDE_CHIPSETS is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+CONFIG_CHR_DEV_ST=m
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=m
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_CHR_DEV_SG=m
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_7000FASST is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AHA152X is not set
+# CONFIG_SCSI_AHA1542 is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_IN2000 is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_CPQFCTS is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_DTC3280 is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_PPA is not set
+# CONFIG_SCSI_IMM is not set
+# CONFIG_SCSI_NCR53C406A is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_PAS16 is not set
+# CONFIG_SCSI_PCI2000 is not set
+# CONFIG_SCSI_PCI2220I is not set
+# CONFIG_SCSI_PSI240I is not set
+# CONFIG_SCSI_QLOGIC_FAS is not set
+# CONFIG_SCSI_QLOGIC_ISP is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+CONFIG_SCSI_QLA2XXX=m
+# 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_SYM53C416 is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_T128 is not set
+# CONFIG_SCSI_U14_34F is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
#
# Multi-device support (RAID and LVM)
@@ -186,6 +341,21 @@ CONFIG_BLK_DEV_RAM_SIZE=4096
# 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
+
+#
# Networking support
#
CONFIG_NET=y
@@ -205,23 +375,24 @@ CONFIG_INET=y
# CONFIG_NET_IPIP is not set
# CONFIG_NET_IPGRE is not set
# CONFIG_ARPD is not set
-# CONFIG_INET_ECN is not set
# CONFIG_SYN_COOKIES is not set
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_IP_TCPDIAG is not set
+# CONFIG_IP_TCPDIAG_IPV6 is not set
# CONFIG_IPV6 is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
# CONFIG_NETFILTER is not set
#
# SCTP Configuration (EXPERIMENTAL)
#
-CONFIG_IPV6_SCTP__=y
# CONFIG_IP_SCTP is not set
# CONFIG_ATM is not set
+# CONFIG_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
@@ -230,39 +401,44 @@ CONFIG_IPV6_SCTP__=y
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
#
# QoS and/or fair queueing
#
# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
#
# Network testing
#
# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
#
# ARCnet devices
#
# CONFIG_ARCNET is not set
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
#
# Ethernet (10 or 100Mbit)
#
CONFIG_NET_ETHERNET=y
# CONFIG_MII is not set
-# CONFIG_SMC91X is not set
# CONFIG_HAPPYMEAL is not set
# CONFIG_SUNGEM is not set
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_LANCE is not set
# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_SMC91X is not set
# CONFIG_NET_VENDOR_RACAL is not set
#
@@ -280,6 +456,7 @@ CONFIG_NET_PCI=y
# CONFIG_AC3200 is not set
# CONFIG_APRICOT is not set
# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
CONFIG_CS89x0=y
# CONFIG_DGRS is not set
# CONFIG_EEPRO100 is not set
@@ -306,169 +483,43 @@ CONFIG_CS89x0=y
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
# CONFIG_R8169 is not set
-# CONFIG_SIS190 is not set
# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
# CONFIG_TIGON3 is not set
#
# Ethernet (10000 Mbit)
#
# CONFIG_IXGB is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PLIP is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-# CONFIG_HOSTAP is not set
+# CONFIG_S2IO is not set
#
# Token Ring devices
#
# CONFIG_TR is not set
-# CONFIG_NET_FC is not set
-# CONFIG_RCPCI is not set
-# CONFIG_SHAPER is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
-# Bluetooth support
-#
-# CONFIG_BT is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-CONFIG_IDE=y
-CONFIG_BLK_DEV_IDE=y
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
-CONFIG_BLK_DEV_IDEDISK=y
-# CONFIG_IDEDISK_MULTI_MODE is not set
-# CONFIG_IDEDISK_STROKE is not set
-CONFIG_BLK_DEV_IDECD=y
-# CONFIG_BLK_DEV_IDETAPE is not set
-CONFIG_BLK_DEV_IDEFLOPPY=y
-# CONFIG_BLK_DEV_IDESCSI is not set
-# CONFIG_IDE_TASK_IOCTL is not set
-# CONFIG_IDE_TASKFILE_IO is not set
-
-#
-# IDE chipset support/bugfixes
-#
-# CONFIG_BLK_DEV_IDEPCI is not set
-# CONFIG_IDE_CHIPSETS is not set
-# CONFIG_BLK_DEV_IDEDMA is not set
-# CONFIG_IDEDMA_AUTO is not set
-# CONFIG_BLK_DEV_HD is not set
-
-#
-# SCSI device support
-#
-CONFIG_SCSI=m
-CONFIG_SCSI_PROC_FS=y
-
-#
-# SCSI support type (disk, tape, CD-ROM)
-#
-CONFIG_BLK_DEV_SD=m
-CONFIG_CHR_DEV_ST=m
-# CONFIG_CHR_DEV_OSST is not set
-CONFIG_BLK_DEV_SR=m
-# CONFIG_BLK_DEV_SR_VENDOR is not set
-CONFIG_CHR_DEV_SG=m
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
-# CONFIG_SCSI_MULTI_LUN is not set
-# CONFIG_SCSI_REPORT_LUNS is not set
-# CONFIG_SCSI_CONSTANTS is not set
-# CONFIG_SCSI_LOGGING is not set
-
-#
-# SCSI low-level drivers
-#
-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
-# CONFIG_SCSI_7000FASST is not set
-# CONFIG_SCSI_ACARD is not set
-# CONFIG_SCSI_AHA152X is not set
-# CONFIG_SCSI_AHA1542 is not set
-# CONFIG_SCSI_AACRAID is not set
-# CONFIG_SCSI_AIC7XXX is not set
-# CONFIG_SCSI_AIC7XXX_OLD is not set
-# CONFIG_SCSI_AIC79XX is not set
-# CONFIG_SCSI_DPT_I2O is not set
-# CONFIG_SCSI_ADVANSYS is not set
-# CONFIG_SCSI_IN2000 is not set
-# CONFIG_SCSI_MEGARAID is not set
-# CONFIG_SCSI_BUSLOGIC is not set
-# CONFIG_SCSI_CPQFCTS is not set
-# CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_DTC3280 is not set
-# CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_EATA_PIO is not set
-# CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
-# CONFIG_SCSI_GENERIC_NCR5380 is not set
-# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
-# CONFIG_SCSI_IPS is not set
-# CONFIG_SCSI_INITIO is not set
-# CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_PPA is not set
-# CONFIG_SCSI_IMM is not set
-# CONFIG_SCSI_NCR53C406A is not set
-# CONFIG_SCSI_SYM53C8XX_2 is not set
-# CONFIG_SCSI_PAS16 is not set
-# CONFIG_SCSI_PCI2000 is not set
-# CONFIG_SCSI_PCI2220I is not set
-# CONFIG_SCSI_PSI240I is not set
-# CONFIG_SCSI_QLOGIC_FAS is not set
-# CONFIG_SCSI_QLOGIC_ISP is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
-# CONFIG_SCSI_QLOGIC_1280 is not set
-# CONFIG_SCSI_SYM53C416 is not set
-# CONFIG_SCSI_DC395x is not set
-# CONFIG_SCSI_DC390T is not set
-# CONFIG_SCSI_T128 is not set
-# CONFIG_SCSI_U14_34F is not set
-# CONFIG_SCSI_NSP32 is not set
-# CONFIG_SCSI_DEBUG is not set
-
-#
-# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+# Wireless LAN (non-hamradio)
#
-# CONFIG_IEEE1394 is not set
+# CONFIG_NET_RADIO is not set
#
-# I2O device support
+# Wan interfaces
#
-# CONFIG_I2O is not set
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PLIP is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
#
# ISDN subsystem
#
-# CONFIG_ISDN_BOOL is not set
+# CONFIG_ISDN is not set
#
# Input device support
@@ -484,42 +535,43 @@ 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_TSLIBDEV is not set
# CONFIG_INPUT_EVDEV is not set
# CONFIG_INPUT_EVBUG is not set
#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-CONFIG_SERIO_I8042=y
-# CONFIG_SERIO_SERPORT is not set
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PARKBD is not set
-# CONFIG_SERIO_PCIPS2 is not set
-
-#
# Input Device Drivers
#
CONFIG_INPUT_KEYBOARD=y
CONFIG_KEYBOARD_ATKBD=y
# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
# CONFIG_KEYBOARD_XTKBD is not set
# CONFIG_KEYBOARD_NEWTON is not set
CONFIG_INPUT_MOUSE=y
CONFIG_MOUSE_PS2=y
-# CONFIG_MOUSE_PS2_SYNAPTICS is not set
# CONFIG_MOUSE_SERIAL is not set
# CONFIG_MOUSE_INPORT is not set
# CONFIG_MOUSE_LOGIBM is not set
# CONFIG_MOUSE_PC110PAD is not set
+# CONFIG_MOUSE_VSXXXAA is not set
# CONFIG_INPUT_JOYSTICK is not set
# CONFIG_INPUT_TOUCHSCREEN is not set
# CONFIG_INPUT_MISC is not set
#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_PARKBD is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
+#
# Character devices
#
CONFIG_VT=y
@@ -538,77 +590,189 @@ CONFIG_SERIAL_8250_NR_UARTS=4
#
# Non-8250 serial port support
#
-# CONFIG_SERIAL_DZ is not set
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
CONFIG_PRINTER=m
# CONFIG_LP_CONSOLE is not set
# CONFIG_PPDEV is not set
# CONFIG_TIPAR is not set
#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
# I2C support
#
# CONFIG_I2C is not set
#
-# I2C Algorithms
+# Misc devices
#
#
-# I2C Hardware Bus support
+# Multimedia devices
#
+# CONFIG_VIDEO_DEV is not set
#
-# I2C Hardware Sensors Chip support
+# Digital Video Broadcasting Devices
#
-# CONFIG_I2C_SENSOR is not set
+# CONFIG_DVB is not set
#
-# L3 serial bus support
+# Graphics support
#
-# CONFIG_L3 is not set
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+CONFIG_FB_SOFT_CURSOR=y
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+CONFIG_FB_CYBER2000=y
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT 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 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_PM3 is not set
+# CONFIG_FB_VIRTUAL is not set
#
-# Mice
+# Console display driver support
#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_QIC02_TAPE is not set
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
#
-# IPMI
+# Logo configuration
#
-# CONFIG_IPMI_HANDLER is not set
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
-# Watchdog Cards
+# Sound
#
-# CONFIG_WATCHDOG is not set
-# CONFIG_NVRAM is not set
-CONFIG_RTC=y
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
+CONFIG_SOUND=m
#
-# Ftape, the floppy tape device driver
+# Advanced Linux Sound Architecture
#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
+# CONFIG_SND is not set
#
-# Multimedia devices
+# Open Sound System
#
-# CONFIG_VIDEO_DEV is not set
+CONFIG_SOUND_PRIME=m
+# CONFIG_SOUND_BT878 is not set
+# CONFIG_SOUND_CMPCI is not set
+# CONFIG_SOUND_EMU10K1 is not set
+# CONFIG_SOUND_FUSION is not set
+# CONFIG_SOUND_CS4281 is not set
+# CONFIG_SOUND_ES1370 is not set
+# CONFIG_SOUND_ES1371 is not set
+# CONFIG_SOUND_ESSSOLO1 is not set
+# CONFIG_SOUND_MAESTRO is not set
+# CONFIG_SOUND_MAESTRO3 is not set
+# CONFIG_SOUND_ICH is not set
+# CONFIG_SOUND_SONICVIBES is not set
+# CONFIG_SOUND_TRIDENT is not set
+# CONFIG_SOUND_MSNDCLAS is not set
+# CONFIG_SOUND_MSNDPIN is not set
+# CONFIG_SOUND_VIA82CXXX is not set
+CONFIG_SOUND_OSS=m
+# CONFIG_SOUND_TRACEINIT is not set
+# CONFIG_SOUND_DMAP is not set
+# CONFIG_SOUND_AD1816 is not set
+# CONFIG_SOUND_AD1889 is not set
+# CONFIG_SOUND_SGALAXY is not set
+CONFIG_SOUND_ADLIB=m
+# CONFIG_SOUND_ACI_MIXER is not set
+# CONFIG_SOUND_CS4232 is not set
+# CONFIG_SOUND_SSCAPE is not set
+# CONFIG_SOUND_GUS is not set
+# CONFIG_SOUND_VMIDI is not set
+# CONFIG_SOUND_TRIX is not set
+# CONFIG_SOUND_MSS is not set
+# CONFIG_SOUND_MPU401 is not set
+# CONFIG_SOUND_NM256 is not set
+# CONFIG_SOUND_MAD16 is not set
+# CONFIG_SOUND_PAS is not set
+# CONFIG_SOUND_PSS is not set
+CONFIG_SOUND_SB=m
+# CONFIG_SOUND_AWE32_SYNTH is not set
+# CONFIG_SOUND_WAVEFRONT is not set
+# CONFIG_SOUND_MAUI is not set
+# CONFIG_SOUND_YM3812 is not set
+# CONFIG_SOUND_OPL3SA1 is not set
+# CONFIG_SOUND_OPL3SA2 is not set
+# CONFIG_SOUND_YMFPCI is not set
+# CONFIG_SOUND_UART6850 is not set
+# CONFIG_SOUND_AEDSP16 is not set
+# CONFIG_SOUND_KAHLUA is not set
+# CONFIG_SOUND_ALI5455 is not set
+# CONFIG_SOUND_FORTE is not set
+# CONFIG_SOUND_RME96XX is not set
+# CONFIG_SOUND_AD1980 is not set
#
-# Digital Video Broadcasting Devices
+# USB support
#
-# CONFIG_DVB is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
#
# MMC/SD Card support
@@ -629,10 +793,15 @@ CONFIG_JBD=y
CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
# CONFIG_XFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
@@ -650,16 +819,19 @@ CONFIG_JOLIET=y
CONFIG_FAT_FS=y
CONFIG_MSDOS_FS=y
CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
# CONFIG_NTFS_FS is not set
#
# Pseudo filesystems
#
CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
CONFIG_DEVFS_FS=y
CONFIG_DEVFS_MOUNT=y
# CONFIG_DEVFS_DEBUG is not set
-# CONFIG_DEVPTS_FS 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
@@ -671,6 +843,7 @@ CONFIG_RAMFS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
# CONFIG_BEFS_FS is not set
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
@@ -690,14 +863,13 @@ CONFIG_NFS_FS=y
# CONFIG_NFS_DIRECTIO is not set
# CONFIG_NFSD is not set
CONFIG_LOCKD=y
-# CONFIG_EXPORTFS is not set
CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_GSS is not set
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
# CONFIG_CIFS is not set
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
# CONFIG_AFS_FS is not set
#
@@ -715,16 +887,15 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_SOLARIS_X86_PARTITION is not set
# CONFIG_UNIXWARE_DISKLABEL is not set
# CONFIG_LDM_PARTITION is not set
-# CONFIG_NEC98_PARTITION is not set
# CONFIG_SGI_PARTITION is not set
# CONFIG_ULTRIX_PARTITION is not set
# CONFIG_SUN_PARTITION is not set
# CONFIG_EFI_PARTITION is not set
-CONFIG_NLS=y
#
# Native Language Support
#
+CONFIG_NLS=y
CONFIG_NLS_DEFAULT="iso8859-1"
CONFIG_NLS_CODEPAGE_437=y
# CONFIG_NLS_CODEPAGE_737 is not set
@@ -749,6 +920,7 @@ CONFIG_NLS_CODEPAGE_850=y
# CONFIG_NLS_ISO8859_8 is not set
# CONFIG_NLS_CODEPAGE_1250 is not set
# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
CONFIG_NLS_ISO8859_1=y
# CONFIG_NLS_ISO8859_2 is not set
# CONFIG_NLS_ISO8859_3 is not set
@@ -765,142 +937,24 @@ CONFIG_NLS_ISO8859_1=y
# CONFIG_NLS_UTF8 is not set
#
-# Graphics support
-#
-CONFIG_FB=y
-# CONFIG_FB_CIRRUS is not set
-# CONFIG_FB_PM2 is not set
-CONFIG_FB_CYBER2000=y
-# CONFIG_FB_IMSTT is not set
-# CONFIG_FB_RIVA is not set
-# CONFIG_FB_MATROX is not set
-# CONFIG_FB_RADEON is not set
-# CONFIG_FB_ATY128 is not set
-# CONFIG_FB_ATY is not set
-# CONFIG_FB_SIS is not set
-# CONFIG_FB_NEOMAGIC is not set
-# CONFIG_FB_3DFX is not set
-# CONFIG_FB_VOODOO1 is not set
-# CONFIG_FB_TRIDENT is not set
-# CONFIG_FB_PM3 is not set
-# CONFIG_FB_VIRTUAL is not set
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_MDA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_PCI_CONSOLE=y
-# CONFIG_FONTS is not set
-CONFIG_FONT_8x8=y
-CONFIG_FONT_8x16=y
-
-#
-# Logo configuration
-#
-CONFIG_LOGO=y
-# CONFIG_LOGO_LINUX_MONO is not set
-# CONFIG_LOGO_LINUX_VGA16 is not set
-CONFIG_LOGO_LINUX_CLUT224=y
-
-#
-# Sound
-#
-CONFIG_SOUND=m
-
-#
-# Advanced Linux Sound Architecture
-#
-# CONFIG_SND is not set
-
-#
-# Open Sound System
-#
-CONFIG_SOUND_PRIME=m
-# CONFIG_SOUND_BT878 is not set
-# CONFIG_SOUND_CMPCI is not set
-# CONFIG_SOUND_EMU10K1 is not set
-# CONFIG_SOUND_FUSION is not set
-# CONFIG_SOUND_CS4281 is not set
-# CONFIG_SOUND_ES1370 is not set
-# CONFIG_SOUND_ES1371 is not set
-# CONFIG_SOUND_ESSSOLO1 is not set
-# CONFIG_SOUND_MAESTRO is not set
-# CONFIG_SOUND_MAESTRO3 is not set
-# CONFIG_SOUND_ICH is not set
-# CONFIG_SOUND_SONICVIBES is not set
-# CONFIG_SOUND_TRIDENT is not set
-# CONFIG_SOUND_MSNDCLAS is not set
-# CONFIG_SOUND_MSNDPIN is not set
-# CONFIG_SOUND_VIA82CXXX is not set
-CONFIG_SOUND_OSS=m
-# CONFIG_SOUND_TRACEINIT is not set
-# CONFIG_SOUND_DMAP is not set
-# CONFIG_SOUND_AD1816 is not set
-# CONFIG_SOUND_AD1889 is not set
-# CONFIG_SOUND_SGALAXY is not set
-CONFIG_SOUND_ADLIB=m
-# CONFIG_SOUND_ACI_MIXER is not set
-# CONFIG_SOUND_CS4232 is not set
-# CONFIG_SOUND_SSCAPE is not set
-# CONFIG_SOUND_GUS is not set
-# CONFIG_SOUND_VMIDI is not set
-# CONFIG_SOUND_TRIX is not set
-# CONFIG_SOUND_MSS is not set
-# CONFIG_SOUND_MPU401 is not set
-# CONFIG_SOUND_NM256 is not set
-# CONFIG_SOUND_MAD16 is not set
-# CONFIG_SOUND_PAS is not set
-# CONFIG_SOUND_PSS is not set
-CONFIG_SOUND_SB=m
-# CONFIG_SOUND_AWE32_SYNTH is not set
-# CONFIG_SOUND_WAVEFRONT is not set
-# CONFIG_SOUND_MAUI is not set
-# CONFIG_SOUND_YM3812 is not set
-# CONFIG_SOUND_OPL3SA1 is not set
-# CONFIG_SOUND_OPL3SA2 is not set
-# CONFIG_SOUND_YMFPCI is not set
-# CONFIG_SOUND_UART6850 is not set
-# CONFIG_SOUND_AEDSP16 is not set
-# CONFIG_SOUND_KAHLUA is not set
-# CONFIG_SOUND_ALI5455 is not set
-# CONFIG_SOUND_FORTE is not set
-# CONFIG_SOUND_RME96XX is not set
-# CONFIG_SOUND_AD1980 is not set
-
-#
-# Misc devices
-#
-
-#
-# Multimedia Capabilities Port drivers
-#
-# CONFIG_MCP is not set
-
-#
-# Console Switches
-#
-# CONFIG_SWITCHES is not set
-
-#
-# USB support
+# Profiling support
#
-# CONFIG_USB is not set
-# CONFIG_USB_GADGET is not set
+# 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_DEBUG_BUGVERBOSE=y
CONFIG_FRAME_POINTER=y
CONFIG_DEBUG_USER=y
-# CONFIG_DEBUG_INFO is not set
-# CONFIG_DEBUG_KERNEL is not set
#
# Security options
#
+# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
#
@@ -909,6 +963,12 @@ CONFIG_DEBUG_USER=y
# CONFIG_CRYPTO is not set
#
+# Hardware crypto devices
+#
+
+#
# Library routines
#
+# CONFIG_CRC_CCITT is not set
CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
diff --git a/arch/arm/configs/simpad_defconfig b/arch/arm/configs/simpad_defconfig
index 10effbca6cef4..5373eeb7d578f 100644
--- a/arch/arm/configs/simpad_defconfig
+++ b/arch/arm/configs/simpad_defconfig
@@ -1,12 +1,13 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.9-rc2
-# Thu Sep 16 15:42:43 2004
+# Linux kernel version: 2.6.12-rc1-bk2
+# Mon Mar 28 00:10:36 2005
#
CONFIG_ARM=y
CONFIG_MMU=y
CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_GENERIC_IOMAP=y
#
@@ -15,6 +16,7 @@ CONFIG_GENERIC_IOMAP=y
CONFIG_EXPERIMENTAL=y
CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
#
# General setup
@@ -26,22 +28,24 @@ CONFIG_SYSVIPC=y
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
# CONFIG_IKCONFIG is not set
CONFIG_EMBEDDED=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
CONFIG_KALLSYMS_EXTRA_PASS=y
+CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=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
@@ -50,6 +54,7 @@ CONFIG_MODULES=y
# CONFIG_MODULE_UNLOAD is not set
CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_KMOD=y
#
@@ -73,46 +78,27 @@ CONFIG_ARCH_SA1100=y
# CONFIG_ARCH_SHARK is not set
# CONFIG_ARCH_LH7A40X is not set
# CONFIG_ARCH_OMAP is not set
-# CONFIG_ARCH_VERSATILE_PB is not set
+# CONFIG_ARCH_VERSATILE is not set
# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_H720X is not set
#
# SA11x0 Implementations
#
# CONFIG_SA1100_ASSABET is not set
-# CONFIG_SA1100_ADSBITSY is not set
-# CONFIG_SA1100_BRUTUS is not set
# CONFIG_SA1100_CERF is not set
# CONFIG_SA1100_COLLIE is not set
# CONFIG_SA1100_H3100 is not set
# CONFIG_SA1100_H3600 is not set
# CONFIG_SA1100_H3800 is not set
-# CONFIG_SA1100_EXTENEX1 is not set
-# CONFIG_SA1100_FLEXANET is not set
-# CONFIG_SA1100_FREEBIRD is not set
-# CONFIG_SA1100_GRAPHICSCLIENT is not set
-# CONFIG_SA1100_GRAPHICSMASTER is not set
# CONFIG_SA1100_BADGE4 is not set
# CONFIG_SA1100_JORNADA720 is not set
# CONFIG_SA1100_HACKKIT is not set
-# CONFIG_SA1100_HUW_WEBPANEL is not set
-# CONFIG_SA1100_ITSY is not set
# CONFIG_SA1100_LART is not set
-# CONFIG_SA1100_NANOENGINE is not set
-# CONFIG_SA1100_OMNIMETER is not set
-# CONFIG_SA1100_PANGOLIN is not set
# CONFIG_SA1100_PLEB is not set
-# CONFIG_SA1100_PT_SYSTEM3 is not set
# CONFIG_SA1100_SHANNON is not set
-# CONFIG_SA1100_SHERMAN is not set
CONFIG_SA1100_SIMPAD=y
-# CONFIG_SA1100_PFS168 is not set
-# CONFIG_SA1100_VICTOR is not set
-# CONFIG_SA1100_XP860 is not set
-# CONFIG_SA1100_YOPY is not set
-# CONFIG_SA1100_STORK is not set
# CONFIG_SA1100_SSP is not set
-# CONFIG_SA1100_USB is not set
#
# Processor Type
@@ -122,6 +108,7 @@ CONFIG_CPU_SA1100=y
CONFIG_CPU_32v4=y
CONFIG_CPU_ABRT_EV4=y
CONFIG_CPU_CACHE_V4WB=y
+CONFIG_CPU_CACHE_VIVT=y
CONFIG_CPU_TLB_V4WB=y
CONFIG_CPU_MINICACHE=y
@@ -130,63 +117,91 @@ CONFIG_CPU_MINICACHE=y
#
#
-# General setup
+# Bus support
#
-CONFIG_DISCONTIGMEM=y
CONFIG_ISA=y
-# CONFIG_ZBOOT_ROM is not set
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-# CONFIG_CPU_FREQ is not set
#
-# PCMCIA/CardBus support
+# PCCARD (PCMCIA/CardBus) support
#
-CONFIG_PCMCIA=y
+CONFIG_PCCARD=y
# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=y
+
+#
+# PC-card bridges
+#
# CONFIG_I82365 is not set
# CONFIG_TCIC is not set
CONFIG_PCMCIA_SA1100=y
#
-# At least one math emulation must be selected
+# Kernel Features
+#
+CONFIG_PREEMPT=y
+CONFIG_DISCONTIGMEM=y
+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="mtdparts=sa1100:512k(boot),1m(kernel),-(root) console=ttySA0 root=1f02 noinitrd mem=64M jffs2_orphaned_inodes=delete rootfstype=jffs2"
+# CONFIG_XIP_KERNEL is not set
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ 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=m
+# CONFIG_ARTHUR is not set
#
-# Generic Driver Options
+# Power management options
#
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-CONFIG_FW_LOADER=m
-# CONFIG_DEBUG_DRIVER is not set
CONFIG_PM=y
-CONFIG_PREEMPT=y
CONFIG_APM=y
-# CONFIG_ARTHUR is not set
-CONFIG_CMDLINE="mtdparts=sa1100:512k(boot),1m(kernel),-(root) console=ttySA0 root=1f02 noinitrd mem=64M jffs2_orphaned_inodes=delete rootfstype=jffs2"
-CONFIG_LEDS=y
-CONFIG_LEDS_TIMER=y
-# CONFIG_LEDS_CPU is not set
-CONFIG_ALIGNMENT_TRAP=y
#
-# Parallel port support
+# Device Drivers
#
-# CONFIG_PARPORT is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=m
+# CONFIG_DEBUG_DRIVER is not set
#
# Memory Technology Devices (MTD)
#
CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
-CONFIG_MTD_PARTITIONS=y
CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_REDBOOT_PARTS is not set
CONFIG_MTD_CMDLINE_PARTS=y
# CONFIG_MTD_AFS_PARTS is not set
@@ -228,6 +243,7 @@ CONFIG_MTD_CFI_UTIL=y
CONFIG_MTD_RAM=y
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_XIP is not set
#
# Mapping drivers for chip access
@@ -246,6 +262,7 @@ CONFIG_MTD_SA1100=y
# 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
@@ -260,6 +277,11 @@ CONFIG_MTD_SA1100=y
# CONFIG_MTD_NAND is not set
#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
# Plug and Play support
#
# CONFIG_PNP is not set
@@ -269,11 +291,34 @@ CONFIG_MTD_SA1100=y
#
# CONFIG_BLK_DEV_FD is not set
# CONFIG_BLK_DEV_XD is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
CONFIG_BLK_DEV_LOOP=m
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
# CONFIG_BLK_DEV_NBD is not set
CONFIG_BLK_DEV_RAM=m
+CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
#
# Multi-device support (RAID and LVM)
@@ -281,6 +326,18 @@ CONFIG_BLK_DEV_RAM_SIZE=8192
# CONFIG_MD is not set
#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
# Networking support
#
CONFIG_NET=y
@@ -308,6 +365,8 @@ CONFIG_IP_PNP_BOOTP=y
# 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
@@ -327,7 +386,6 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
#
# QoS and/or fair queueing
@@ -405,10 +463,10 @@ CONFIG_BT_BNEP_PROTO_FILTER=y
# Bluetooth device drivers
#
# CONFIG_BT_HCIUART is not set
-CONFIG_BT_HCIDTL1=m
-CONFIG_BT_HCIBT3C=m
-CONFIG_BT_HCIBLUECARD=m
-CONFIG_BT_HCIBTUART=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_NETDEVICES=y
CONFIG_DUMMY=y
@@ -482,7 +540,7 @@ CONFIG_PCMCIA_WAVELAN=m
#
# Wireless 802.11b Pcmcia/Cardbus cards support
#
-CONFIG_AIRO_CS=m
+# CONFIG_AIRO_CS is not set
# CONFIG_PCMCIA_WL3501 is not set
CONFIG_NET_WIRELESS=y
@@ -516,28 +574,6 @@ CONFIG_PPPOE=m
# CONFIG_NETCONSOLE is not set
#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-# CONFIG_SCSI is not set
-
-#
-# Fusion MPT device support
-#
-
-#
-# IEEE 1394 (FireWire) support
-#
-
-#
-# I2O device support
-#
-
-#
# ISDN subsystem
#
# CONFIG_ISDN is not set
@@ -562,15 +598,6 @@ CONFIG_INPUT_EVDEV=m
CONFIG_INPUT_EVBUG=y
#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=m
-CONFIG_SERIO_SERPORT=m
-CONFIG_SERIO_CT82C710=m
-
-#
# Input Device Drivers
#
# CONFIG_INPUT_KEYBOARD is not set
@@ -580,6 +607,16 @@ CONFIG_SERIO_CT82C710=m
# CONFIG_INPUT_MISC is not set
#
+# Hardware I/O ports
+#
+CONFIG_SERIO=m
+CONFIG_SERIO_SERPORT=m
+# CONFIG_SERIO_LIBPS2 is not set
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
+#
# Character devices
#
CONFIG_VT=y
@@ -629,11 +666,20 @@ CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_RAW_DRIVER is not set
#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
# I2C support
#
# CONFIG_I2C is not set
#
+# Misc devices
+#
+
+#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -644,6 +690,71 @@ CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_DVB is not set
#
+# Graphics support
+#
+CONFIG_FB=y
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_SOFT_CURSOR is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_SA1100 is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_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=y
+
+#
+# Advanced Linux Sound Architecture
+#
+# CONFIG_SND 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 is not set
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
# File systems
#
CONFIG_EXT2_FS=m
@@ -660,10 +771,15 @@ CONFIG_REISERFS_FS=m
CONFIG_REISERFS_PROC_INFO=y
# CONFIG_REISERFS_FS_XATTR is not set
# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
# CONFIG_XFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
@@ -712,6 +828,7 @@ CONFIG_JFFS_FS_VERBOSE=0
CONFIG_JFFS2_FS=y
CONFIG_JFFS2_FS_DEBUG=0
# CONFIG_JFFS2_FS_NAND is not set
+# CONFIG_JFFS2_FS_NOR_ECC is not set
# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
CONFIG_JFFS2_ZLIB=y
CONFIG_JFFS2_RTIME=y
@@ -734,7 +851,6 @@ CONFIG_NFS_V3=y
# CONFIG_ROOT_NFS is not set
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
-# CONFIG_EXPORTFS is not set
CONFIG_SUNRPC=y
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
@@ -749,6 +865,7 @@ CONFIG_SMB_FS=m
# Partition Types
#
# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
#
# Native Language Support
@@ -800,75 +917,21 @@ CONFIG_NLS_ISO8859_15=y
# CONFIG_PROFILING is not set
#
-# Graphics support
-#
-CONFIG_FB=y
-# CONFIG_FB_MODE_HELPERS is not set
-# CONFIG_FB_SA1100 is not set
-CONFIG_FB_MQ200=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_FONTS is not set
-CONFIG_FONT_8x8=y
-CONFIG_FONT_8x16=y
-
-#
-# Logo configuration
-#
-CONFIG_LOGO=y
-CONFIG_LOGO_LINUX_MONO=y
-CONFIG_LOGO_LINUX_VGA16=y
-CONFIG_LOGO_LINUX_CLUT224=y
-
-#
-# Sound
-#
-CONFIG_SOUND=y
-
-#
-# Advanced Linux Sound Architecture
-#
-# CONFIG_SND is not set
-
-#
-# Open Sound System
-#
-# CONFIG_SOUND_PRIME is not set
-
-#
-# Misc devices
-#
-
-#
-# USB support
-#
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
-# CONFIG_MMC 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_SCHEDSTATS is not set
# CONFIG_DEBUG_SLAB is not set
+CONFIG_DEBUG_PREEMPT=y
# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_FS is not set
CONFIG_FRAME_POINTER=y
CONFIG_DEBUG_USER=y
# CONFIG_DEBUG_WAITQ is not set
@@ -879,6 +942,7 @@ CONFIG_DEBUG_LL=y
#
# Security options
#
+# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
#
@@ -887,6 +951,10 @@ CONFIG_DEBUG_LL=y
# CONFIG_CRYPTO is not set
#
+# Hardware crypto devices
+#
+
+#
# Library routines
#
CONFIG_CRC_CCITT=m
diff --git a/arch/arm/configs/smdk2410_defconfig b/arch/arm/configs/smdk2410_defconfig
index 1309997f70162..2c60865fda19e 100644
--- a/arch/arm/configs/smdk2410_defconfig
+++ b/arch/arm/configs/smdk2410_defconfig
@@ -1,40 +1,50 @@
#
# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.12-rc1-bk2
+# Sun Mar 27 22:42:40 2005
#
CONFIG_ARM=y
CONFIG_MMU=y
CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_IOMAP=y
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
CONFIG_CLEAN_COMPILE=y
-CONFIG_STANDALONE=y
CONFIG_BROKEN_ON_SMP=y
#
# General setup
#
+CONFIG_LOCALVERSION=""
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
# CONFIG_IKCONFIG is not set
# CONFIG_EMBEDDED is not set
CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=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
@@ -44,82 +54,51 @@ CONFIG_CC_OPTIMIZE_FOR_SIZE=y
#
# System Type
#
-# CONFIG_ARCH_ADIFCC is not set
# CONFIG_ARCH_CLPS7500 is not set
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
-# CONFIG_ARCH_PXA 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_SHARK is not set
CONFIG_ARCH_S3C2410=y
-# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_SHARK is not set
# CONFIG_ARCH_LH7A40X is not set
-# CONFIG_ARCH_VERSATILE_PB is not set
-
-#
-# CLPS711X/EP721X Implementations
-#
-
-#
-# Epxa10db
-#
-
-#
-# Footbridge Implementations
-#
-
-#
-# IOP3xx Implementation Options
-#
-# CONFIG_ARCH_IOP310 is not set
-# CONFIG_ARCH_IOP321 is not set
-
-#
-# IOP3xx Chipset Features
-#
-
-#
-# Intel PXA250/210 Implementations
-#
-
-#
-# SA11x0 Implementations
-#
-
-#
-# TI OMAP Implementations
-#
-
-#
-# OMAP Core Type
-#
-
-#
-# OMAP Board Type
-#
-
-#
-# OMAP Feature Selections
-#
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_H720X is not set
#
-# S3C2410 Implementations
+# S3C24XX Implementations
#
# CONFIG_ARCH_BAST is not set
# CONFIG_ARCH_H1940 is not set
+# CONFIG_MACH_N30 is not set
CONFIG_ARCH_SMDK2410=y
+# CONFIG_ARCH_S3C2440 is not set
# CONFIG_MACH_VR1000 is not set
+# CONFIG_MACH_RX3715 is not set
+# CONFIG_MACH_OTOM is not set
+# CONFIG_MACH_NEXCODER_2440 is not set
+CONFIG_CPU_S3C2410=y
+
+#
+# S3C2410 Boot
+#
#
-# LH7A40X Implementations
+# S3C2410 Setup
#
+# CONFIG_S3C2410_DMA is not set
+CONFIG_S3C2410_LOWLEVEL_UART_PORT=0
#
# Processor Type
@@ -129,6 +108,7 @@ 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
@@ -141,43 +121,70 @@ CONFIG_ARM_THUMB=y
# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
#
-# General setup
+# Bus support
+#
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_PREEMPT is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="root=1f04 mem=32M"
+# CONFIG_XIP_KERNEL is not set
+
+#
+# Floating point emulation
#
-# CONFIG_ZBOOT_ROM is not set
-CONFIG_ZBOOT_ROM_TEXT=0
-CONFIG_ZBOOT_ROM_BSS=0
#
-# At least one math emulation must be selected
+# At least one emulation must be selected
#
# CONFIG_FPE_NWFPE is not set
# CONFIG_FPE_FASTFPE is not set
+
+#
+# Userspace binary formats
+#
CONFIG_BINFMT_ELF=y
CONFIG_BINFMT_AOUT=y
# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
#
-# Generic Driver Options
+# Power management options
#
-# CONFIG_DEBUG_DRIVER is not set
# CONFIG_PM is not set
-# CONFIG_PREEMPT is not set
-# CONFIG_ARTHUR is not set
-CONFIG_CMDLINE="root=1f04 mem=32M"
-CONFIG_ALIGNMENT_TRAP=y
#
-# Parallel port support
+# Device Drivers
#
-# CONFIG_PARPORT is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
#
# Memory Technology Devices (MTD)
#
CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
-# CONFIG_MTD_PARTITIONS is not set
# CONFIG_MTD_CONCAT is not set
+# CONFIG_MTD_PARTITIONS is not set
#
# User Modules And Translation Layers
@@ -195,13 +202,24 @@ CONFIG_MTD_CFI=y
# CONFIG_MTD_JEDECPROBE is not set
CONFIG_MTD_GEN_PROBE=y
# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
CONFIG_MTD_CFI_INTELEXT=y
# CONFIG_MTD_CFI_AMDSTD is not set
# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
+# CONFIG_MTD_XIP is not set
#
# Mapping drivers for chip access
@@ -215,8 +233,10 @@ CONFIG_MTD_CFI_INTELEXT=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
@@ -231,6 +251,11 @@ CONFIG_MTD_CFI_INTELEXT=y
# CONFIG_MTD_NAND is not set
#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
# Plug and Play support
#
@@ -238,11 +263,34 @@ CONFIG_MTD_CFI_INTELEXT=y
# Block devices
#
# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
# CONFIG_BLK_DEV_LOOP is not set
# CONFIG_BLK_DEV_NBD is not set
CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
#
# Multi-device support (RAID and LVM)
@@ -250,6 +298,18 @@ CONFIG_BLK_DEV_RAM_SIZE=4096
# CONFIG_MD is not set
#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
# Networking support
#
CONFIG_NET=y
@@ -275,6 +335,9 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL 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
@@ -294,12 +357,12 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
#
# QoS and/or fair queueing
#
# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
#
# Network testing
@@ -321,6 +384,7 @@ CONFIG_NETDEVICES=y
#
CONFIG_NET_ETHERNET=y
# CONFIG_MII is not set
+# CONFIG_SMC91X is not set
#
# Ethernet (1000 Mbit)
@@ -349,29 +413,6 @@ CONFIG_NET_ETHERNET=y
# CONFIG_NETCONSOLE is not set
#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-# CONFIG_SCSI is not set
-
-#
-# Fusion MPT device support
-#
-
-#
-# IEEE 1394 (FireWire) support
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-
-#
# ISDN subsystem
#
# CONFIG_ISDN is not set
@@ -394,16 +435,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=y
-# CONFIG_SERIO_CT82C710 is not set
-
-#
# Input Device Drivers
#
CONFIG_INPUT_KEYBOARD=y
@@ -421,6 +452,16 @@ CONFIG_MOUSE_PS2=y
# CONFIG_INPUT_MISC is not set
#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
+#
# Character devices
#
CONFIG_VT=y
@@ -443,7 +484,6 @@ CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
-# CONFIG_QIC02_TAPE is not set
#
# IPMI
@@ -456,25 +496,31 @@ CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_WATCHDOG is not set
# CONFIG_NVRAM is not set
# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
+# CONFIG_S3C2410_RTC is not set
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
#
# Ftape, the floppy tape device driver
#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
# CONFIG_DRM is not set
# CONFIG_RAW_DRIVER is not set
#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
# I2C support
#
# CONFIG_I2C is not set
#
+# Misc devices
+#
+
+#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -485,6 +531,56 @@ CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_DVB is not set
#
+# Graphics support
+#
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+CONFIG_FB_SOFT_CURSOR=y
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+CONFIG_FB_VIRTUAL=y
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+# CONFIG_LOGO 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 is not set
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -493,10 +589,15 @@ CONFIG_EXT2_FS=y
# CONFIG_JBD is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
# CONFIG_XFS_FS is not set
# CONFIG_MINIX_FS is not set
CONFIG_ROMFS_FS=y
# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
@@ -509,7 +610,8 @@ CONFIG_ROMFS_FS=y
#
# DOS/FAT/NT Filesystems
#
-# CONFIG_FAT_FS is not set
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
# CONFIG_NTFS_FS is not set
#
@@ -552,14 +654,13 @@ CONFIG_NFS_FS=y
# CONFIG_NFSD is not set
CONFIG_ROOT_NFS=y
CONFIG_LOCKD=y
-# CONFIG_EXPORTFS is not set
CONFIG_SUNRPC=y
# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
# CONFIG_CIFS is not set
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
# CONFIG_AFS_FS is not set
#
@@ -573,7 +674,6 @@ CONFIG_PARTITION_ADVANCED=y
# CONFIG_MAC_PARTITION is not set
# CONFIG_MSDOS_PARTITION is not set
# CONFIG_LDM_PARTITION is not set
-# CONFIG_NEC98_PARTITION is not set
# CONFIG_SGI_PARTITION is not set
# CONFIG_ULTRIX_PARTITION is not set
# CONFIG_SUN_PARTITION is not set
@@ -590,68 +690,33 @@ CONFIG_PARTITION_ADVANCED=y
# CONFIG_PROFILING is not set
#
-# Graphics support
-#
-CONFIG_FB=y
-CONFIG_FB_VIRTUAL=y
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_MDA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_PCI_CONSOLE=y
-# CONFIG_FONTS is not set
-CONFIG_FONT_8x8=y
-CONFIG_FONT_8x16=y
-
-#
-# Logo configuration
-#
-# CONFIG_LOGO is not set
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# Misc devices
-#
-
-#
-# USB support
-#
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
# Kernel hacking
#
-CONFIG_FRAME_POINTER=y
-CONFIG_DEBUG_USER=y
-# CONFIG_DEBUG_INFO is not set
+# CONFIG_PRINTK_TIME is not set
CONFIG_DEBUG_KERNEL=y
-# CONFIG_DEBUG_SLAB is not set
# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_LOG_BUF_SHIFT=14
+# 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_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
# CONFIG_DEBUG_WAITQ is not set
-# CONFIG_DEBUG_BUGVERBOSE is not set
# CONFIG_DEBUG_ERRORS is not set
CONFIG_DEBUG_LL=y
# CONFIG_DEBUG_ICEDCC is not set
-CONFIG_DEBUG_LL_PRINTK=y
CONFIG_DEBUG_S3C2410_PORT=y
CONFIG_DEBUG_S3C2410_UART=0
#
# Security options
#
+# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
#
@@ -660,7 +725,12 @@ CONFIG_DEBUG_S3C2410_UART=0
# CONFIG_CRYPTO is not set
#
+# Hardware crypto devices
+#
+
+#
# Library routines
#
+# CONFIG_CRC_CCITT is not set
CONFIG_CRC32=y
CONFIG_LIBCRC32C=y
diff --git a/arch/arm/configs/versatile_defconfig b/arch/arm/configs/versatile_defconfig
index e98f061a89ec2..d72f2c754268e 100644
--- a/arch/arm/configs/versatile_defconfig
+++ b/arch/arm/configs/versatile_defconfig
@@ -1,40 +1,50 @@
#
# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.12-rc1-bk2
+# Mon Mar 28 00:20:50 2005
#
CONFIG_ARM=y
CONFIG_MMU=y
CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_IOMAP=y
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
CONFIG_CLEAN_COMPILE=y
-CONFIG_STANDALONE=y
CONFIG_BROKEN_ON_SMP=y
#
# General setup
#
+CONFIG_LOCALVERSION=""
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
# CONFIG_IKCONFIG 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_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=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
@@ -44,70 +54,33 @@ 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
#
# System Type
#
-# CONFIG_ARCH_ADIFCC is not set
# CONFIG_ARCH_CLPS7500 is not set
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
-# CONFIG_ARCH_PXA 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_SHARK 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=y
-
-#
-# CLPS711X/EP721X Implementations
-#
-
-#
-# Epxa10db
-#
-
-#
-# Footbridge Implementations
-#
-
-#
-# IOP3xx Implementation Options
-#
-# CONFIG_ARCH_IOP310 is not set
-# CONFIG_ARCH_IOP321 is not set
-
-#
-# IOP3xx Chipset Features
-#
-
-#
-# Intel PXA250/210 Implementations
-#
-
-#
-# SA11x0 Implementations
-#
-
-#
-# TI OMAP Implementations
-#
-
-#
-# OMAP Feature Selections
-#
-
-#
-# S3C2410 Implementations
-#
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_H720X is not set
#
# Versatile platform type
@@ -122,6 +95,7 @@ CONFIG_CPU_32=y
CONFIG_CPU_ARM926T=y
CONFIG_CPU_32v5=y
CONFIG_CPU_ABRT_EV5TJ=y
+CONFIG_CPU_CACHE_VIVT=y
CONFIG_CPU_COPY_V4WB=y
CONFIG_CPU_TLB_V4WBI=y
@@ -133,56 +107,80 @@ CONFIG_ARM_THUMB=y
# CONFIG_CPU_DCACHE_DISABLE is not set
# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
+CONFIG_ICST307=y
#
-# General setup
+# Bus support
#
CONFIG_ARM_AMBA=y
-# CONFIG_ZBOOT_ROM is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_PREEMPT is not set
+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="root=1f03 mem=32M"
+# CONFIG_XIP_KERNEL is not set
#
-# PCMCIA/CardBus support
+# Floating point emulation
#
-# CONFIG_PCMCIA is not set
#
-# At least one math emulation must be selected
+# At least one emulation must be selected
#
CONFIG_FPE_NWFPE=y
# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+# CONFIG_VFP 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
#
-# Generic Driver Options
+# Power management options
#
-# CONFIG_FW_LOADER is not set
-# CONFIG_DEBUG_DRIVER is not set
CONFIG_PM=y
-# CONFIG_PREEMPT is not set
# CONFIG_APM is not set
-# CONFIG_ARTHUR is not set
-CONFIG_CMDLINE="root=1f03 mem=32M"
-CONFIG_LEDS=y
-CONFIG_LEDS_TIMER=y
-CONFIG_LEDS_CPU=y
-CONFIG_ALIGNMENT_TRAP=y
#
-# Parallel port support
+# Device Drivers
#
-# CONFIG_PARPORT is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
#
# Memory Technology Devices (MTD)
#
CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
-CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_REDBOOT_PARTS is not set
CONFIG_MTD_CMDLINE_PARTS=y
# CONFIG_MTD_AFS_PARTS is not set
@@ -207,13 +205,24 @@ CONFIG_MTD_CFI_NOSWAP=y
# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
# CONFIG_MTD_CFI_GEOMETRY is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
CONFIG_MTD_CFI_INTELEXT=y
# CONFIG_MTD_CFI_AMDSTD is not set
# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
+# CONFIG_MTD_XIP is not set
#
# Mapping drivers for chip access
@@ -227,8 +236,10 @@ CONFIG_MTD_ARM_INTEGRATOR=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
@@ -243,6 +254,11 @@ CONFIG_MTD_ARM_INTEGRATOR=y
# CONFIG_MTD_NAND is not set
#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
# Plug and Play support
#
@@ -250,11 +266,29 @@ CONFIG_MTD_ARM_INTEGRATOR=y
# Block devices
#
# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
# CONFIG_BLK_DEV_LOOP is not set
# CONFIG_BLK_DEV_NBD is not set
CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
#
# Multi-device support (RAID and LVM)
@@ -262,6 +296,18 @@ CONFIG_BLK_DEV_INITRD=y
# CONFIG_MD is not set
#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
# Networking support
#
CONFIG_NET=y
@@ -289,6 +335,9 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL 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
@@ -308,12 +357,12 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
#
# QoS and/or fair queueing
#
# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
#
# Network testing
@@ -353,7 +402,6 @@ CONFIG_SMC91X=y
# Wireless LAN (non-hamradio)
#
# CONFIG_NET_RADIO is not set
-# CONFIG_HOSTAP is not set
#
# Wan interfaces
@@ -365,29 +413,6 @@ CONFIG_SMC91X=y
# CONFIG_NETCONSOLE is not set
#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-# CONFIG_SCSI is not set
-
-#
-# Fusion MPT device support
-#
-
-#
-# IEEE 1394 (FireWire) support
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-
-#
# ISDN subsystem
#
# CONFIG_ISDN is not set
@@ -406,22 +431,10 @@ 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_TSLIBDEV is not set
# CONFIG_INPUT_EVDEV is not set
# CONFIG_INPUT_EVBUG is not set
#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-# CONFIG_SERIO_SERPORT is not set
-# CONFIG_SERIO_CT82C710 is not set
-CONFIG_SERIO_AMBAKMI=y
-
-#
# Input Device Drivers
#
CONFIG_INPUT_KEYBOARD=y
@@ -439,6 +452,17 @@ CONFIG_MOUSE_PS2=y
# CONFIG_INPUT_MISC is not set
#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIO_AMBAKMI=y
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
+#
# Character devices
#
CONFIG_VT=y
@@ -469,7 +493,6 @@ CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=16
-# CONFIG_QIC02_TAPE is not set
#
# IPMI
@@ -482,20 +505,21 @@ CONFIG_LEGACY_PTY_COUNT=16
# CONFIG_WATCHDOG is not set
# CONFIG_NVRAM is not set
# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
#
# Ftape, the floppy tape device driver
#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
# CONFIG_DRM is not set
# CONFIG_RAW_DRIVER is not set
#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
# I2C support
#
CONFIG_I2C=y
@@ -506,33 +530,44 @@ CONFIG_I2C_CHARDEV=m
#
CONFIG_I2C_ALGOBIT=y
# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
#
# I2C Hardware Bus support
#
-# CONFIG_I2C_AMD756 is not set
-# CONFIG_I2C_AMD8111 is not set
# CONFIG_I2C_ISA is not set
# CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_PCA_ISA is not set
#
# Hardware Sensors Chip support
#
CONFIG_I2C_SENSOR=m
# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ASB100 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
# CONFIG_SENSORS_LM78 is not set
# CONFIG_SENSORS_LM80 is not set
# CONFIG_SENSORS_LM83 is not set
# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
# CONFIG_SENSORS_LM90 is not set
-# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
# CONFIG_SENSORS_W83781D is not set
# CONFIG_SENSORS_W83L785TS is not set
# CONFIG_SENSORS_W83627HF is not set
@@ -543,15 +578,15 @@ CONFIG_I2C_SENSOR=m
CONFIG_SENSORS_EEPROM=m
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
# CONFIG_I2C_DEBUG_CORE is not set
# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
# CONFIG_I2C_DEBUG_CHIP is not set
#
-# L3 serial bus support
+# Misc devices
#
-# CONFIG_L3 is not set
#
# Multimedia devices
@@ -564,6 +599,88 @@ CONFIG_SENSORS_EEPROM=m
# CONFIG_DVB is not set
#
+# Graphics support
+#
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+CONFIG_FB_SOFT_CURSOR=y
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+CONFIG_FB_ARMCLCD=y
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FONTS=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=y
+# CONFIG_FONT_MINI_4x6 is not set
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+
+#
+# Logo configuration
+#
+# CONFIG_LOGO is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+CONFIG_SOUND=y
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+# CONFIG_SND_SEQUENCER is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+
+#
+# Generic devices
+#
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+
+#
+# ALSA ARM devices
+#
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
# MMC/SD Card support
#
CONFIG_MMC=y
@@ -580,10 +697,15 @@ CONFIG_EXT2_FS=y
# CONFIG_JBD is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
# CONFIG_XFS_FS is not set
CONFIG_MINIX_FS=y
CONFIG_ROMFS_FS=y
# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
@@ -599,6 +721,8 @@ CONFIG_ROMFS_FS=y
CONFIG_FAT_FS=m
# CONFIG_MSDOS_FS is not set
CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
# CONFIG_NTFS_FS is not set
#
@@ -626,6 +750,11 @@ CONFIG_RAMFS=y
CONFIG_JFFS2_FS=y
CONFIG_JFFS2_FS_DEBUG=0
# CONFIG_JFFS2_FS_NAND is not set
+# CONFIG_JFFS2_FS_NOR_ECC is not set
+# CONFIG_JFFS2_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
@@ -650,11 +779,11 @@ CONFIG_LOCKD_V4=y
CONFIG_EXPORTFS=y
CONFIG_SUNRPC=y
# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
# CONFIG_CIFS is not set
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
# CONFIG_AFS_FS is not set
#
@@ -672,7 +801,6 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_SOLARIS_X86_PARTITION is not set
# CONFIG_UNIXWARE_DISKLABEL is not set
# CONFIG_LDM_PARTITION is not set
-# CONFIG_NEC98_PARTITION is not set
# CONFIG_SGI_PARTITION is not set
# CONFIG_ULTRIX_PARTITION is not set
# CONFIG_SUN_PARTITION is not set
@@ -706,6 +834,7 @@ CONFIG_NLS_CODEPAGE_850=m
# CONFIG_NLS_ISO8859_8 is not set
# CONFIG_NLS_CODEPAGE_1250 is not set
# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
CONFIG_NLS_ISO8859_1=m
# CONFIG_NLS_ISO8859_2 is not set
# CONFIG_NLS_ISO8859_3 is not set
@@ -727,107 +856,23 @@ CONFIG_NLS_ISO8859_1=m
# CONFIG_PROFILING is not set
#
-# Graphics support
-#
-CONFIG_FB=y
-CONFIG_FB_ARMCLCD=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_PCI_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=y
-# CONFIG_FONT_MINI_4x6 is not set
-# CONFIG_FONT_SUN8x16 is not set
-# CONFIG_FONT_SUN12x22 is not set
-
-#
-# Logo configuration
-#
-# CONFIG_LOGO is not set
-
-#
-# Sound
-#
-CONFIG_SOUND=y
-
-#
-# Advanced Linux Sound Architecture
-#
-CONFIG_SND=m
-CONFIG_SND_TIMER=m
-CONFIG_SND_PCM=m
-# CONFIG_SND_SEQUENCER is not set
-CONFIG_SND_OSSEMUL=y
-CONFIG_SND_MIXER_OSS=m
-CONFIG_SND_PCM_OSS=m
-# CONFIG_SND_VERBOSE_PRINTK is not set
-# CONFIG_SND_DEBUG is not set
-
-#
-# Generic devices
-#
-# CONFIG_SND_DUMMY is not set
-# CONFIG_SND_MTPAV is not set
-# CONFIG_SND_SERIAL_U16550 is not set
-# CONFIG_SND_MPU401 is not set
-CONFIG_SND_AC97_CODEC=m
-
-#
-# ALSA ARM devices
-#
-CONFIG_SND_ARMAACI=m
-
-#
-# Open Sound System
-#
-# CONFIG_SOUND_PRIME is not set
-
-#
-# Misc devices
-#
-
-#
-# Multimedia Capabilities Port drivers
-#
-# CONFIG_MCP is not set
-
-#
-# Console Switches
-#
-# CONFIG_SWITCHES is not set
-
-#
-# USB support
-#
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
# Kernel hacking
#
-CONFIG_FRAME_POINTER=y
-CONFIG_DEBUG_USER=y
-# CONFIG_DEBUG_INFO is not set
+# CONFIG_PRINTK_TIME is not set
CONFIG_DEBUG_KERNEL=y
-# CONFIG_DEBUG_SLAB is not set
CONFIG_MAGIC_SYSRQ=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_WAITQ 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_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_WAITQ is not set
CONFIG_DEBUG_ERRORS=y
CONFIG_DEBUG_LL=y
# CONFIG_DEBUG_ICEDCC is not set
@@ -835,6 +880,7 @@ CONFIG_DEBUG_LL=y
#
# Security options
#
+# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
#
@@ -843,8 +889,14 @@ CONFIG_DEBUG_LL=y
# CONFIG_CRYPTO is not set
#
+# Hardware crypto devices
+#
+
+#
# Library routines
#
+# CONFIG_CRC_CCITT is not set
CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S
index fbb9b81a9d309..e5d370c235d74 100644
--- a/arch/arm/kernel/calls.S
+++ b/arch/arm/kernel/calls.S
@@ -1,7 +1,7 @@
/*
* linux/arch/arm/kernel/calls.S
*
- * Copyright (C) 1995-2004 Russell King
+ * Copyright (C) 1995-2005 Russell King
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -10,7 +10,7 @@
* This file is included twice in entry-common.S
*/
#ifndef NR_syscalls
-#define NR_syscalls 288
+#define NR_syscalls 320
#else
__syscall_start:
@@ -295,6 +295,38 @@ __syscall_start:
.long sys_mq_notify
.long sys_mq_getsetattr
/* 280 */ .long sys_waitid
+ .long sys_socket
+ .long sys_bind
+ .long sys_connect
+ .long sys_listen
+/* 285 */ .long sys_accept
+ .long sys_getsockname
+ .long sys_getpeername
+ .long sys_socketpair
+ .long sys_send
+/* 290 */ .long sys_sendto
+ .long sys_recv
+ .long sys_recvfrom
+ .long sys_shutdown
+ .long sys_setsockopt
+/* 295 */ .long sys_getsockopt
+ .long sys_sendmsg
+ .long sys_recvmsg
+ .long sys_semop
+ .long sys_semget
+/* 300 */ .long sys_semctl
+ .long sys_msgsnd
+ .long sys_msgrcv
+ .long sys_msgget
+ .long sys_msgctl
+/* 305 */ .long sys_shmat
+ .long sys_shmdt
+ .long sys_shmget
+ .long sys_shmctl
+ .long sys_add_key
+/* 310 */ .long sys_request_key
+ .long sys_keyctl
+ .long sys_semtimedop
__syscall_end:
.rept NR_syscalls - (__syscall_end - __syscall_start) / 4
diff --git a/arch/arm/kernel/debug.S b/arch/arm/kernel/debug.S
index 7c96388b1ef75..caaa919ab47a1 100644
--- a/arch/arm/kernel/debug.S
+++ b/arch/arm/kernel/debug.S
@@ -52,29 +52,6 @@
#include <asm/arch/debug-macro.S>
#endif
-#if 0
-// #elif defined(CONFIG_ARCH_FTVPCI)
- .macro addruart,rx
- mrc p15, 0, \rx, c1, c0
- tst \rx, #1 @ MMU enabled?
- movne \rx, #0xe0000000
- moveq \rx, #0x10000000
- .endm
-
- .macro senduart,rd,rx
- str \rd, [\rx, #0xc]
- .endm
-
- .macro busyuart,rd,rx
-1001: ldr \rd, [\rx, #0x4]
- tst \rd, #1 << 2
- beq 1001b
- .endm
-
- .macro waituart,rd,rx
- .endm
-#endif
-
/*
* Useful debugging routines
*/
diff --git a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c
index 3f6b4b529aa9f..3dc15b131f532 100644
--- a/arch/arm/kernel/ecard.c
+++ b/arch/arm/kernel/ecard.c
@@ -85,27 +85,21 @@ static struct expcard_blacklist __initdata blacklist[] = {
};
asmlinkage extern int
-ecard_loader_reset(volatile unsigned char *pa, loader_t loader);
+ecard_loader_reset(unsigned long base, loader_t loader);
asmlinkage extern int
-ecard_loader_read(int off, volatile unsigned char *pa, loader_t loader);
+ecard_loader_read(int off, unsigned long base, loader_t loader);
-static const struct ecard_id *
-ecard_match_device(const struct ecard_id *ids, struct expansion_card *ec);
-
-static inline unsigned short
-ecard_getu16(unsigned char *v)
+static inline unsigned short ecard_getu16(unsigned char *v)
{
return v[0] | v[1] << 8;
}
-static inline signed long
-ecard_gets24(unsigned char *v)
+static inline signed long ecard_gets24(unsigned char *v)
{
return v[0] | v[1] << 8 | v[2] << 16 | ((v[2] & 0x80) ? 0xff000000 : 0);
}
-static inline ecard_t *
-slot_to_ecard(unsigned int slot)
+static inline ecard_t *slot_to_ecard(unsigned int slot)
{
return slot < MAX_ECARDS ? slot_to_expcard[slot] : NULL;
}
@@ -122,26 +116,31 @@ slot_to_ecard(unsigned int slot)
* From a security standpoint, we trust the card vendors. This
* may be a misplaced trust.
*/
-#define BUS_ADDR(x) ((((unsigned long)(x)) << 2) + IO_BASE)
-#define POD_INT_ADDR(x) ((volatile unsigned char *)\
- ((BUS_ADDR((x)) - IO_BASE) + IO_START))
-
static void ecard_task_reset(struct ecard_request *req)
{
struct expansion_card *ec = req->ec;
- if (ec->loader)
- ecard_loader_reset(POD_INT_ADDR(ec->podaddr), ec->loader);
+ struct resource *res;
+
+ res = ec->slot_no == 8
+ ? &ec->resource[ECARD_RES_MEMC]
+ : ec->type == ECARD_EASI
+ ? &ec->resource[ECARD_RES_EASI]
+ : &ec->resource[ECARD_RES_IOCSYNC];
+
+ ecard_loader_reset(res->start, ec->loader);
}
static void ecard_task_readbytes(struct ecard_request *req)
{
- unsigned char *buf = (unsigned char *)req->buffer;
- volatile unsigned char *base_addr =
- (volatile unsigned char *)POD_INT_ADDR(req->ec->podaddr);
+ struct expansion_card *ec = req->ec;
+ unsigned char *buf = req->buffer;
unsigned int len = req->length;
unsigned int off = req->address;
- if (req->ec->slot_no == 8) {
+ if (ec->slot_no == 8) {
+ void __iomem *base = (void __iomem *)
+ ec->resource[ECARD_RES_MEMC].start;
+
/*
* The card maintains an index which increments the address
* into a 4096-byte page on each access. We need to keep
@@ -161,7 +160,7 @@ static void ecard_task_readbytes(struct ecard_request *req)
* greater than the offset, reset the hardware index counter.
*/
if (off == 0 || index > off) {
- *base_addr = 0;
+ writeb(0, base);
index = 0;
}
@@ -170,21 +169,24 @@ static void ecard_task_readbytes(struct ecard_request *req)
* required offset. The read bytes are discarded.
*/
while (index < off) {
- unsigned char byte;
- byte = base_addr[page];
+ readb(base + page);
index += 1;
}
while (len--) {
- *buf++ = base_addr[page];
+ *buf++ = readb(base + page);
index += 1;
}
} else {
+ unsigned long base = (ec->type == ECARD_EASI
+ ? &ec->resource[ECARD_RES_EASI]
+ : &ec->resource[ECARD_RES_IOCSYNC])->start;
+ void __iomem *pbase = (void __iomem *)base;
- if (!req->use_loader || !req->ec->loader) {
+ if (!req->use_loader || !ec->loader) {
off *= 4;
while (len--) {
- *buf++ = base_addr[off];
+ *buf++ = readb(pbase + off);
off += 4;
}
} else {
@@ -194,8 +196,8 @@ static void ecard_task_readbytes(struct ecard_request *req)
* expansion card loader programs.
*/
*(unsigned long *)0x108 = 0;
- *buf++ = ecard_loader_read(off++, base_addr,
- req->ec->loader);
+ *buf++ = ecard_loader_read(off++, base,
+ ec->loader);
}
}
}
@@ -226,7 +228,7 @@ static void ecard_init_pgtables(struct mm_struct *mm)
*/
pgd_t *src_pgd, *dst_pgd;
- src_pgd = pgd_offset(mm, IO_BASE);
+ src_pgd = pgd_offset(mm, (unsigned long)IO_BASE);
dst_pgd = pgd_offset(mm, IO_START);
memcpy(dst_pgd, src_pgd, sizeof(pgd_t) * (IO_SIZE / PGDIR_SIZE));
@@ -406,7 +408,7 @@ static void ecard_def_irq_disable(ecard_t *ec, int irqnr)
static int ecard_def_irq_pending(ecard_t *ec)
{
- return !ec->irqmask || ec->irqaddr[0] & ec->irqmask;
+ return !ec->irqmask || readb(ec->irqaddr) & ec->irqmask;
}
static void ecard_def_fiq_enable(ecard_t *ec, int fiqnr)
@@ -421,7 +423,7 @@ static void ecard_def_fiq_disable(ecard_t *ec, int fiqnr)
static int ecard_def_fiq_pending(ecard_t *ec)
{
- return !ec->fiqmask || ec->fiqaddr[0] & ec->fiqmask;
+ return !ec->fiqmask || readb(ec->fiqaddr) & ec->fiqmask;
}
static expansioncard_ops_t ecard_default_ops = {
@@ -522,7 +524,7 @@ static void ecard_dump_irq_state(void)
ec->ops->irqpending(ec) ? "" : "not ");
else
printk("irqaddr %p, mask = %02X, status = %02X\n",
- ec->irqaddr, ec->irqmask, *ec->irqaddr);
+ ec->irqaddr, ec->irqmask, readb(ec->irqaddr));
}
}
@@ -675,7 +677,7 @@ static int __init ecard_probeirqhw(void)
#define IO_EC_MEMC8_BASE 0
#endif
-unsigned int ecard_address(ecard_t *ec, card_type_t type, card_speed_t speed)
+unsigned int __ecard_address(ecard_t *ec, card_type_t type, card_speed_t speed)
{
unsigned long address = 0;
int slot = ec->slot_no;
@@ -779,55 +781,89 @@ static void ecard_proc_init(void)
get_ecard_dev_info);
}
-#define ec_set_resource(ec,nr,st,sz,flg) \
+#define ec_set_resource(ec,nr,st,sz) \
do { \
(ec)->resource[nr].name = ec->dev.bus_id; \
(ec)->resource[nr].start = st; \
(ec)->resource[nr].end = (st) + (sz) - 1; \
- (ec)->resource[nr].flags = flg; \
+ (ec)->resource[nr].flags = IORESOURCE_MEM; \
} while (0)
-static void __init ecard_init_resources(struct expansion_card *ec)
+static void __init ecard_free_card(struct expansion_card *ec)
+{
+ int i;
+
+ for (i = 0; i < ECARD_NUM_RESOURCES; i++)
+ if (ec->resource[i].flags)
+ release_resource(&ec->resource[i]);
+
+ kfree(ec);
+}
+
+static struct expansion_card *__init ecard_alloc_card(int type, int slot)
{
- unsigned long base = PODSLOT_IOC4_BASE;
- unsigned int slot = ec->slot_no;
+ struct expansion_card *ec;
+ unsigned long base;
int i;
+ ec = kmalloc(sizeof(ecard_t), GFP_KERNEL);
+ if (!ec) {
+ ec = ERR_PTR(-ENOMEM);
+ goto nomem;
+ }
+
+ memset(ec, 0, sizeof(ecard_t));
+
+ ec->slot_no = slot;
+ ec->type = type;
+ ec->irq = NO_IRQ;
+ ec->fiq = NO_IRQ;
+ ec->dma = NO_DMA;
+ ec->ops = &ecard_default_ops;
+
+ snprintf(ec->dev.bus_id, sizeof(ec->dev.bus_id), "ecard%d", slot);
+ ec->dev.parent = NULL;
+ ec->dev.bus = &ecard_bus_type;
+ ec->dev.dma_mask = &ec->dma_mask;
+ ec->dma_mask = (u64)0xffffffff;
+
if (slot < 4) {
ec_set_resource(ec, ECARD_RES_MEMC,
PODSLOT_MEMC_BASE + (slot << 14),
- PODSLOT_MEMC_SIZE, IORESOURCE_MEM);
- base = PODSLOT_IOC0_BASE;
- }
+ PODSLOT_MEMC_SIZE);
+ base = PODSLOT_IOC0_BASE + (slot << 14);
+ } else
+ base = PODSLOT_IOC4_BASE + ((slot - 4) << 14);
#ifdef CONFIG_ARCH_RPC
if (slot < 8) {
ec_set_resource(ec, ECARD_RES_EASI,
PODSLOT_EASI_BASE + (slot << 24),
- PODSLOT_EASI_SIZE, IORESOURCE_MEM);
+ PODSLOT_EASI_SIZE);
}
if (slot == 8) {
- ec_set_resource(ec, ECARD_RES_MEMC, NETSLOT_BASE,
- NETSLOT_SIZE, IORESOURCE_MEM);
+ ec_set_resource(ec, ECARD_RES_MEMC, NETSLOT_BASE, NETSLOT_SIZE);
} else
#endif
- for (i = 0; i <= ECARD_RES_IOCSYNC - ECARD_RES_IOCSLOW; i++) {
+ for (i = 0; i <= ECARD_RES_IOCSYNC - ECARD_RES_IOCSLOW; i++)
ec_set_resource(ec, i + ECARD_RES_IOCSLOW,
- base + (slot << 14) + (i << 19),
- PODSLOT_IOC_SIZE, IORESOURCE_MEM);
- }
+ base + (i << 19), PODSLOT_IOC_SIZE);
for (i = 0; i < ECARD_NUM_RESOURCES; i++) {
- if (ec->resource[i].start &&
+ if (ec->resource[i].flags &&
request_resource(&iomem_resource, &ec->resource[i])) {
printk(KERN_ERR "%s: resource(s) not available\n",
ec->dev.bus_id);
ec->resource[i].end -= ec->resource[i].start;
ec->resource[i].start = 0;
+ ec->resource[i].flags = 0;
}
}
+
+ nomem:
+ return ec;
}
static ssize_t ecard_show_irq(struct device *dev, char *buf)
@@ -836,16 +872,12 @@ static ssize_t ecard_show_irq(struct device *dev, char *buf)
return sprintf(buf, "%u\n", ec->irq);
}
-static DEVICE_ATTR(irq, S_IRUGO, ecard_show_irq, NULL);
-
static ssize_t ecard_show_dma(struct device *dev, char *buf)
{
struct expansion_card *ec = ECARD_DEV(dev);
return sprintf(buf, "%u\n", ec->dma);
}
-static DEVICE_ATTR(dma, S_IRUGO, ecard_show_dma, NULL);
-
static ssize_t ecard_show_resources(struct device *dev, char *buf)
{
struct expansion_card *ec = ECARD_DEV(dev);
@@ -861,23 +893,33 @@ static ssize_t ecard_show_resources(struct device *dev, char *buf)
return str - buf;
}
-static DEVICE_ATTR(resource, S_IRUGO, ecard_show_resources, NULL);
-
static ssize_t ecard_show_vendor(struct device *dev, char *buf)
{
struct expansion_card *ec = ECARD_DEV(dev);
return sprintf(buf, "%u\n", ec->cid.manufacturer);
}
-static DEVICE_ATTR(vendor, S_IRUGO, ecard_show_vendor, NULL);
-
static ssize_t ecard_show_device(struct device *dev, char *buf)
{
struct expansion_card *ec = ECARD_DEV(dev);
return sprintf(buf, "%u\n", ec->cid.product);
}
-static DEVICE_ATTR(device, S_IRUGO, ecard_show_device, NULL);
+static ssize_t ecard_show_type(struct device *dev, char *buf)
+{
+ struct expansion_card *ec = ECARD_DEV(dev);
+ return sprintf(buf, "%s\n", ec->type == ECARD_EASI ? "EASI" : "IOC");
+}
+
+static struct device_attribute ecard_dev_attrs[] = {
+ __ATTR(device, S_IRUGO, ecard_show_device, NULL),
+ __ATTR(dma, S_IRUGO, ecard_show_dma, NULL),
+ __ATTR(irq, S_IRUGO, ecard_show_irq, NULL),
+ __ATTR(resource, S_IRUGO, ecard_show_resources, NULL),
+ __ATTR(type, S_IRUGO, ecard_show_type, NULL),
+ __ATTR(vendor, S_IRUGO, ecard_show_vendor, NULL),
+ __ATTR_NULL,
+};
int ecard_request_resources(struct expansion_card *ec)
@@ -927,21 +969,13 @@ ecard_probe(int slot, card_type_t type)
ecard_t **ecp;
ecard_t *ec;
struct ex_ecid cid;
- int i, rc = -ENOMEM;
+ int i, rc;
- ec = kmalloc(sizeof(ecard_t), GFP_KERNEL);
- if (!ec)
+ ec = ecard_alloc_card(type, slot);
+ if (IS_ERR(ec)) {
+ rc = PTR_ERR(ec);
goto nomem;
-
- memset(ec, 0, sizeof(ecard_t));
-
- ec->slot_no = slot;
- ec->type = type;
- ec->irq = NO_IRQ;
- ec->fiq = NO_IRQ;
- ec->dma = NO_DMA;
- ec->card_desc = NULL;
- ec->ops = &ecard_default_ops;
+ }
rc = -ENODEV;
if ((ec->podaddr = ecard_address(ec, type, ECARD_SYNC)) == 0)
@@ -964,7 +998,7 @@ ecard_probe(int slot, card_type_t type)
ec->cid.fiqmask = cid.r_fiqmask;
ec->cid.fiqoff = ecard_gets24(cid.r_fiqoff);
ec->fiqaddr =
- ec->irqaddr = (unsigned char *)ioaddr(ec->podaddr);
+ ec->irqaddr = (void __iomem *)ioaddr(ec->podaddr);
if (ec->cid.is) {
ec->irqmask = ec->cid.irqmask;
@@ -983,14 +1017,6 @@ ecard_probe(int slot, card_type_t type)
break;
}
- snprintf(ec->dev.bus_id, sizeof(ec->dev.bus_id), "ecard%d", slot);
- ec->dev.parent = NULL;
- ec->dev.bus = &ecard_bus_type;
- ec->dev.dma_mask = &ec->dma_mask;
- ec->dma_mask = (u64)0xffffffff;
-
- ecard_init_resources(ec);
-
/*
* hook the interrupt handlers
*/
@@ -1017,17 +1043,12 @@ ecard_probe(int slot, card_type_t type)
slot_to_expcard[slot] = ec;
device_register(&ec->dev);
- device_create_file(&ec->dev, &dev_attr_dma);
- device_create_file(&ec->dev, &dev_attr_irq);
- device_create_file(&ec->dev, &dev_attr_resource);
- device_create_file(&ec->dev, &dev_attr_vendor);
- device_create_file(&ec->dev, &dev_attr_device);
return 0;
-nodev:
- kfree(ec);
-nomem:
+ nodev:
+ ecard_free_card(ec);
+ nomem:
return rc;
}
@@ -1128,9 +1149,15 @@ static void ecard_drv_shutdown(struct device *dev)
if (drv->shutdown)
drv->shutdown(ec);
ecard_release(ec);
- req.fn = ecard_task_reset;
- req.ec = ec;
- ecard_call(&req);
+
+ /*
+ * If this card has a loader, call the reset handler.
+ */
+ if (ec->loader) {
+ req.fn = ecard_task_reset;
+ req.ec = ec;
+ ecard_call(&req);
+ }
}
int ecard_register_driver(struct ecard_driver *drv)
@@ -1164,8 +1191,9 @@ static int ecard_match(struct device *_dev, struct device_driver *_drv)
}
struct bus_type ecard_bus_type = {
- .name = "ecard",
- .match = ecard_match,
+ .name = "ecard",
+ .dev_attrs = ecard_dev_attrs,
+ .match = ecard_match,
};
static int ecard_bus_init(void)
@@ -1176,7 +1204,7 @@ static int ecard_bus_init(void)
postcore_initcall(ecard_bus_init);
EXPORT_SYMBOL(ecard_readchunk);
-EXPORT_SYMBOL(ecard_address);
+EXPORT_SYMBOL(__ecard_address);
EXPORT_SYMBOL(ecard_register_driver);
EXPORT_SYMBOL(ecard_remove_driver);
EXPORT_SYMBOL(ecard_bus_type);
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 69f82e03dba03..bb27c317d94ba 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -280,13 +280,21 @@ __pabt_svc:
@
stmia r5, {r2 - r4}
stmdb r5, {sp, lr}^
+
+ @
+ @ Enable the alignment trap while in kernel mode
+ @
+ alignment_trap r7, r0, __temp_\sym
+
+ @
+ @ Clear FP to mark the first stack frame
+ @
+ zero_fp
.endm
.align 5
__dabt_usr:
usr_entry abt
- alignment_trap r7, r0, __temp_abt
- zero_fp
@
@ Call the processor-specific abort handler:
@@ -316,8 +324,7 @@ __dabt_usr:
.align 5
__irq_usr:
usr_entry irq
- alignment_trap r7, r0, __temp_irq
- zero_fp
+
#ifdef CONFIG_PREEMPT
get_thread_info r8
ldr r9, [r8, #TI_PREEMPT] @ get preempt count
@@ -348,8 +355,7 @@ __irq_usr:
.align 5
__und_usr:
usr_entry und
- alignment_trap r7, r0, __temp_und
- zero_fp
+
tst r3, #PSR_T_BIT @ Thumb mode?
bne fpundefinstr @ ignore FP
sub r4, r2, #4
@@ -465,8 +471,7 @@ fpundefinstr:
.align 5
__pabt_usr:
usr_entry abt
- alignment_trap r7, r0, __temp_abt
- zero_fp
+
enable_irq r0 @ Enable interrupts
mov r0, r2 @ address (pc)
mov r1, sp @ regs
diff --git a/arch/arm/kernel/fiq.c b/arch/arm/kernel/fiq.c
index a45c7874a467f..9299dfc256982 100644
--- a/arch/arm/kernel/fiq.c
+++ b/arch/arm/kernel/fiq.c
@@ -46,12 +46,6 @@
#include <asm/system.h>
#include <asm/uaccess.h>
-#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
-#warning This file requires GCC 3.3.x or older to build. Alternatively,
-#warning please talk to GCC people to resolve the issues with the
-#warning assembly clobber list.
-#endif
-
static unsigned long no_fiq_insn;
/* Default reacquire function
@@ -91,44 +85,43 @@ void set_fiq_handler(void *start, unsigned int length)
/*
* Taking an interrupt in FIQ mode is death, so both these functions
- * disable irqs for the duration.
+ * disable irqs for the duration. Note - these functions are almost
+ * entirely coded in assembly.
*/
-void set_fiq_regs(struct pt_regs *regs)
+void __attribute__((naked)) set_fiq_regs(struct pt_regs *regs)
{
register unsigned long tmp;
- __asm__ volatile (
- "mrs %0, cpsr\n\
+ asm volatile (
+ "mov ip, sp\n\
+ stmfd sp!, {fp, ip, lr, pc}\n\
+ sub fp, ip, #4\n\
+ mrs %0, cpsr\n\
msr cpsr_c, %2 @ select FIQ mode\n\
mov r0, r0\n\
ldmia %1, {r8 - r14}\n\
msr cpsr_c, %0 @ return to SVC mode\n\
- mov r0, r0"
+ mov r0, r0\n\
+ ldmea fp, {fp, sp, pc}"
: "=&r" (tmp)
- : "r" (&regs->ARM_r8), "I" (PSR_I_BIT | PSR_F_BIT | FIQ_MODE)
- /* These registers aren't modified by the above code in a way
- visible to the compiler, but we mark them as clobbers anyway
- so that GCC won't put any of the input or output operands in
- them. */
- : "r8", "r9", "r10", "r11", "r12", "r13", "r14");
+ : "r" (&regs->ARM_r8), "I" (PSR_I_BIT | PSR_F_BIT | FIQ_MODE));
}
-void get_fiq_regs(struct pt_regs *regs)
+void __attribute__((naked)) get_fiq_regs(struct pt_regs *regs)
{
register unsigned long tmp;
- __asm__ volatile (
- "mrs %0, cpsr\n\
+ asm volatile (
+ "mov ip, sp\n\
+ stmfd sp!, {fp, ip, lr, pc}\n\
+ sub fp, ip, #4\n\
+ mrs %0, cpsr\n\
msr cpsr_c, %2 @ select FIQ mode\n\
mov r0, r0\n\
stmia %1, {r8 - r14}\n\
msr cpsr_c, %0 @ return to SVC mode\n\
- mov r0, r0"
+ mov r0, r0\n\
+ ldmea fp, {fp, sp, pc}"
: "=&r" (tmp)
- : "r" (&regs->ARM_r8), "I" (PSR_I_BIT | PSR_F_BIT | FIQ_MODE)
- /* These registers aren't modified by the above code in a way
- visible to the compiler, but we mark them as clobbers anyway
- so that GCC won't put any of the input or output operands in
- them. */
- : "r8", "r9", "r10", "r11", "r12", "r13", "r14");
+ : "r" (&regs->ARM_r8), "I" (PSR_I_BIT | PSR_F_BIT | FIQ_MODE));
}
int claim_fiq(struct fiq_handler *f)
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index 587ac675640b3..171b3e811c716 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -24,9 +24,11 @@
#define PROCINFO_MMUFLAGS 8
#define PROCINFO_INITFUNC 12
+#define MACHINFO_TYPE 0
#define MACHINFO_PHYSRAM 4
#define MACHINFO_PHYSIO 8
#define MACHINFO_PGOFFIO 12
+#define MACHINFO_NAME 16
#ifndef CONFIG_XIP_KERNEL
/*
@@ -101,12 +103,10 @@ ENTRY(stext)
@ and irqs disabled
bl __lookup_processor_type @ r5=procinfo r9=cpuid
movs r10, r5 @ invalid processor (r5=0)?
- moveq r0, #'p' @ yes, error 'p'
- beq __error
+ beq __error_p @ yes, error 'p'
bl __lookup_machine_type @ r5=machinfo
movs r8, r5 @ invalid machine (r5=0)?
- moveq r0, #'a' @ yes, error 'a'
- beq __error
+ beq __error_a @ yes, error 'a'
bl __create_page_tables
/*
@@ -359,22 +359,59 @@ __create_page_tables:
* ought to tell the user, but since we don't have any guarantee that
* we're even running on the right architecture, we do virtually nothing.
*
- * r0 = ascii error character:
- * a = invalid architecture
- * p = invalid processor
- * i = invalid calling convention
- *
- * Generally, only serious errors cause this.
+ * If CONFIG_DEBUG_LL is set we try to print out something about the error
+ * and hope for the best (useful if bootloader fails to pass a proper
+ * machine ID for example).
*/
- .type __error, %function
-__error:
+
+ .type __error_p, %function
+__error_p:
+#ifdef CONFIG_DEBUG_LL
+ adr r0, str_p1
+ bl printascii
+ b __error
+str_p1: .asciz "\nError: unrecognized/unsupported processor variant.\n"
+ .align
+#endif
+
+ .type __error_a, %function
+__error_a:
#ifdef CONFIG_DEBUG_LL
- mov r8, r0 @ preserve r0
- adr r0, err_str
+ mov r4, r1 @ preserve machine ID
+ adr r0, str_a1
+ bl printascii
+ mov r0, r4
+ bl printhex8
+ adr r0, str_a2
+ bl printascii
+ adr r3, 3f
+ ldmia r3, {r4, r5, r6} @ get machine desc list
+ sub r4, r3, r4 @ get offset between virt&phys
+ add r5, r5, r4 @ convert virt addresses to
+ add r6, r6, r4 @ physical address space
+1: ldr r0, [r5, #MACHINFO_TYPE] @ get machine type
+ bl printhex8
+ mov r0, #'\t'
+ bl printch
+ ldr r0, [r5, #MACHINFO_NAME] @ get machine name
+ add r0, r0, r4
bl printascii
- mov r0, r8
+ mov r0, #'\n'
bl printch
+ add r5, r5, #SIZEOF_MACHINE_DESC @ next machine_desc
+ cmp r5, r6
+ blo 1b
+ adr r0, str_a3
+ bl printascii
+ b __error
+str_a1: .asciz "\nError: unrecognized/unsupported machine ID (r1 = 0x"
+str_a2: .asciz ").\n\nAvailable machine support:\n\nID (hex)\tNAME\n"
+str_a3: .asciz "\nPlease check your kernel config and/or bootloader.\n"
+ .align
#endif
+
+ .type __error, %function
+__error:
#ifdef CONFIG_ARCH_RPC
/*
* Turn the screen red on a error - RiscPC only.
@@ -391,12 +428,6 @@ __error:
1: mov r0, r0
b 1b
-#ifdef CONFIG_DEBUG_LL
- .type err_str, %object
-err_str:
- .asciz "\nError: "
- .align
-#endif
/*
* Read processor ID register (CP#15, CR0), and look up in the linker-built
@@ -424,7 +455,7 @@ __lookup_processor_type:
beq 2f
add r5, r5, #PROC_INFO_SZ @ sizeof(proc_info_list)
cmp r5, r6
- blt 1b
+ blo 1b
mov r5, #0 @ unknown processor
2: mov pc, lr
@@ -465,12 +496,12 @@ __lookup_machine_type:
sub r3, r3, r4 @ get offset between virt&phys
add r5, r5, r3 @ convert virt addresses to
add r6, r6, r3 @ physical address space
-1: ldr r3, [r5] @ get machine type
+1: ldr r3, [r5, #MACHINFO_TYPE] @ get machine type
teq r3, r1 @ matches loader number?
beq 2f @ found
add r5, r5, #SIZEOF_MACHINE_DESC @ next machine_desc
cmp r5, r6
- blt 1b
+ blo 1b
mov r5, #0 @ unknown machine
2: mov pc, lr
diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
index 7d07277e617e3..ff187f4308f01 100644
--- a/arch/arm/kernel/irq.c
+++ b/arch/arm/kernel/irq.c
@@ -56,6 +56,13 @@ struct irqdesc irq_desc[NR_IRQS];
void (*init_arch_irq)(void) __initdata = NULL;
/*
+ * No architecture-specific irq_finish function defined in arm/arch/irqs.h.
+ */
+#ifndef irq_finish
+#define irq_finish(irq) do { } while (0)
+#endif
+
+/*
* Dummy mask/unmask handler
*/
void dummy_mask_unmask_irq(unsigned int irq)
@@ -532,6 +539,8 @@ asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
if (!list_empty(&irq_pending))
do_pending_irqs(regs);
+ irq_finish(irq);
+
spin_unlock(&irq_controller_lock);
irq_exit();
}
diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c
index eb9240e9a7d51..1a85cfdad5aca 100644
--- a/arch/arm/kernel/module.c
+++ b/arch/arm/kernel/module.c
@@ -35,44 +35,16 @@ extern void _etext;
void *module_alloc(unsigned long size)
{
struct vm_struct *area;
- struct page **pages;
- unsigned int array_size, i;
size = PAGE_ALIGN(size);
if (!size)
- goto out_null;
+ return NULL;
area = __get_vm_area(size, VM_ALLOC, MODULE_START, MODULE_END);
if (!area)
- goto out_null;
-
- area->nr_pages = size >> PAGE_SHIFT;
- array_size = area->nr_pages * sizeof(struct page *);
- area->pages = pages = kmalloc(array_size, GFP_KERNEL);
- if (!area->pages) {
- remove_vm_area(area->addr);
- kfree(area);
- goto out_null;
- }
-
- memset(pages, 0, array_size);
-
- for (i = 0; i < area->nr_pages; i++) {
- pages[i] = alloc_page(GFP_KERNEL);
- if (unlikely(!pages[i])) {
- area->nr_pages = i;
- goto out_no_pages;
- }
- }
-
- if (map_vm_area(area, PAGE_KERNEL, &pages))
- goto out_no_pages;
- return area->addr;
+ return NULL;
- out_no_pages:
- vfree(area->addr);
- out_null:
- return NULL;
+ return __vmalloc_area(area, GFP_KERNEL, PAGE_KERNEL);
}
void module_free(struct module *module, void *region)
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
index 01273e6b6743b..efd7a341614bf 100644
--- a/arch/arm/kernel/ptrace.c
+++ b/arch/arm/kernel/ptrace.c
@@ -9,6 +9,7 @@
* 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/sched.h>
#include <linux/mm.h>
@@ -608,6 +609,44 @@ static int ptrace_setfpregs(struct task_struct *tsk, void __user *ufp)
sizeof(struct user_fp)) ? -EFAULT : 0;
}
+#ifdef CONFIG_IWMMXT
+
+/*
+ * Get the child iWMMXt state.
+ */
+static int ptrace_getwmmxregs(struct task_struct *tsk, void __user *ufp)
+{
+ struct thread_info *thread = tsk->thread_info;
+ void *ptr = &thread->fpstate;
+
+ if (!test_ti_thread_flag(thread, TIF_USING_IWMMXT))
+ return -ENODATA;
+ iwmmxt_task_disable(thread); /* force it to ram */
+ /* The iWMMXt state is stored doubleword-aligned. */
+ if (((long) ptr) & 4)
+ ptr += 4;
+ return copy_to_user(ufp, ptr, 0x98) ? -EFAULT : 0;
+}
+
+/*
+ * Set the child iWMMXt state.
+ */
+static int ptrace_setwmmxregs(struct task_struct *tsk, void __user *ufp)
+{
+ struct thread_info *thread = tsk->thread_info;
+ void *ptr = &thread->fpstate;
+
+ if (!test_ti_thread_flag(thread, TIF_USING_IWMMXT))
+ return -EACCES;
+ iwmmxt_task_release(thread); /* force a reload */
+ /* The iWMMXt state is stored doubleword-aligned. */
+ if (((long) ptr) & 4)
+ ptr += 4;
+ return copy_from_user(ptr, ufp, 0x98) ? -EFAULT : 0;
+}
+
+#endif
+
static int do_ptrace(int request, struct task_struct *child, long addr, long data)
{
unsigned long tmp;
@@ -719,6 +758,16 @@ static int do_ptrace(int request, struct task_struct *child, long addr, long dat
ret = ptrace_setfpregs(child, (void __user *)data);
break;
+#ifdef CONFIG_IWMMXT
+ case PTRACE_GETWMMXREGS:
+ ret = ptrace_getwmmxregs(child, (void __user *)data);
+ break;
+
+ case PTRACE_SETWMMXREGS:
+ ret = ptrace_setwmmxregs(child, (void __user *)data);
+ break;
+#endif
+
case PTRACE_GET_THREAD_AREA:
ret = put_user(child->thread_info->tp_value,
(unsigned long __user *) data);
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index adfe4ada640e1..c2a7da3ac0f1f 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -92,8 +92,6 @@ struct cpu_user_fns cpu_user;
struct cpu_cache_fns cpu_cache;
#endif
-unsigned char aux_device_present;
-
char elf_platform[ELF_PLATFORM_SIZE];
EXPORT_SYMBOL(elf_platform);
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index ef7fa2c71284d..931919fd51212 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -102,7 +102,7 @@ sys_sigaction(int sig, const struct old_sigaction __user *act,
if (act) {
old_sigset_t mask;
- if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
+ if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
__get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
__get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
return -EFAULT;
@@ -114,7 +114,7 @@ sys_sigaction(int sig, const struct old_sigaction __user *act,
ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
if (!ret && oact) {
- if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
+ if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
__put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
__put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
return -EFAULT;
@@ -317,7 +317,7 @@ asmlinkage int sys_sigreturn(struct pt_regs *regs)
frame = (struct sigframe __user *)regs->ARM_sp;
- if (verify_area(VERIFY_READ, frame, sizeof (*frame)))
+ if (!access_ok(VERIFY_READ, frame, sizeof (*frame)))
goto badframe;
if (__get_user(set.sig[0], &frame->sc.oldmask)
|| (_NSIG_WORDS > 1
@@ -365,7 +365,7 @@ asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
frame = (struct rt_sigframe __user *)regs->ARM_sp;
- if (verify_area(VERIFY_READ, frame, sizeof (*frame)))
+ if (!access_ok(VERIFY_READ, frame, sizeof (*frame)))
goto badframe;
if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
goto badframe;
diff --git a/arch/arm/kernel/sys_arm.c b/arch/arm/kernel/sys_arm.c
index c087e26021c0f..c41dc605f1211 100644
--- a/arch/arm/kernel/sys_arm.c
+++ b/arch/arm/kernel/sys_arm.c
@@ -169,7 +169,11 @@ asmlinkage int sys_ipc(uint call, int first, int second, int third,
switch (call) {
case SEMOP:
- return sys_semop(first, (struct sembuf __user *)ptr, second);
+ return sys_semtimedop (first, (struct sembuf __user *)ptr, second, NULL);
+ case SEMTIMEDOP:
+ return sys_semtimedop(first, (struct sembuf __user *)ptr, second,
+ (const struct timespec __user *)fifth);
+
case SEMGET:
return sys_semget (first, second, third);
case SEMCTL: {
@@ -230,6 +234,18 @@ asmlinkage int sys_ipc(uint call, int first, int second, int third,
}
}
+asmlinkage long sys_shmat(int shmid, char __user *shmaddr, int shmflg,
+ unsigned long __user *addr)
+{
+ unsigned long ret;
+ long err;
+
+ err = do_shmat(shmid, shmaddr, shmflg, &ret);
+ if (err == 0)
+ err = put_user(ret, addr);
+ return err;
+}
+
/* Fork a new task - this creates a new program thread.
* This is called indirectly via a small wrapper
*/
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 760191e3bd381..93dc4646cd7f7 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -240,6 +240,19 @@ void die_if_kernel(const char *str, struct pt_regs *regs, int err)
die(str, regs, err);
}
+static void notify_die(const char *str, struct pt_regs *regs, siginfo_t *info,
+ unsigned long err, unsigned long trap)
+{
+ if (user_mode(regs)) {
+ current->thread.error_code = err;
+ current->thread.trap_no = trap;
+
+ force_sig_info(info->si_signo, info, current);
+ } else {
+ die(str, regs, err);
+ }
+}
+
static LIST_HEAD(undef_hook);
static DEFINE_SPINLOCK(undef_lock);
@@ -299,17 +312,12 @@ asmlinkage void do_undefinstr(struct pt_regs *regs)
}
#endif
- current->thread.error_code = 0;
- current->thread.trap_no = 6;
-
info.si_signo = SIGILL;
info.si_errno = 0;
info.si_code = ILL_ILLOPC;
info.si_addr = pc;
- force_sig_info(SIGILL, &info, current);
-
- die_if_kernel("Oops - undefined instruction", regs, 0);
+ notify_die("Oops - undefined instruction", regs, &info, 0, 6);
}
asmlinkage void do_unexp_fiq (struct pt_regs *regs)
@@ -362,8 +370,8 @@ static int bad_syscall(int n, struct pt_regs *regs)
info.si_addr = (void __user *)instruction_pointer(regs) -
(thumb_mode(regs) ? 2 : 4);
- force_sig_info(SIGILL, &info, current);
- die_if_kernel("Oops - bad syscall", regs, n);
+ notify_die("Oops - bad syscall", regs, &info, n, 0);
+
return regs->ARM_r0;
}
@@ -406,9 +414,7 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs)
info.si_code = SEGV_MAPERR;
info.si_addr = NULL;
- force_sig_info(SIGSEGV, &info, current);
-
- die_if_kernel("branch through zero", regs, 0);
+ notify_die("branch through zero", regs, &info, 0, 0);
return 0;
case NR(breakpoint): /* SWI BREAK_POINT */
@@ -487,8 +493,7 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs)
info.si_addr = (void __user *)instruction_pointer(regs) -
(thumb_mode(regs) ? 2 : 4);
- force_sig_info(SIGILL, &info, current);
- die_if_kernel("Oops - bad syscall(2)", regs, no);
+ notify_die("Oops - bad syscall(2)", regs, &info, no, 0);
return 0;
}
@@ -524,8 +529,7 @@ baddataabort(int code, unsigned long instr, struct pt_regs *regs)
info.si_code = ILL_ILLOPC;
info.si_addr = (void __user *)addr;
- force_sig_info(SIGILL, &info, current);
- die_if_kernel("unknown data abort code", regs, instr);
+ notify_die("unknown data abort code", regs, &info, instr, 0);
}
volatile void __bug(const char *file, int line, void *data)
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index b885d32d1ca3b..a39c6a42d68ad 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -160,3 +160,7 @@ SECTIONS
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
}
+
+/* those must never be empty */
+ASSERT((__proc_info_end - __proc_info_begin), "missing CPU support")
+ASSERT((__arch_info_end - __arch_info_begin), "no machine record defined")
diff --git a/arch/arm/mach-clps7500/core.c b/arch/arm/mach-clps7500/core.c
index 1b37ac1886d1b..fdfededfd96f9 100644
--- a/arch/arm/mach-clps7500/core.c
+++ b/arch/arm/mach-clps7500/core.c
@@ -12,6 +12,7 @@
#include <linux/list.h>
#include <linux/sched.h>
#include <linux/init.h>
+#include <linux/device.h>
#include <linux/serial_8250.h>
#include <asm/mach/arch.h>
@@ -305,11 +306,10 @@ static struct irqaction clps7500_timer_irq = {
static void __init clps7500_timer_init(void)
{
ioctime_init();
-
setup_irq(IRQ_TIMER, &clps7500_timer_irq);
}
-static struct clps7500_timer = {
+static struct sys_timer clps7500_timer = {
.init = clps7500_timer_init,
.offset = ioc_timer_gettimeoffset,
};
@@ -358,9 +358,9 @@ static struct platform_device serial_device = {
},
};
-static int __init clps7500_init(void)
+static void __init clps7500_init(void)
{
- return platform_register_device(&serial_device);
+ platform_device_register(&serial_device);
}
MACHINE_START(CLPS7500, "CL-PS7500")
@@ -368,6 +368,7 @@ MACHINE_START(CLPS7500, "CL-PS7500")
BOOT_MEM(0x10000000, 0x03000000, 0xe0000000)
MAPIO(clps7500_map_io)
INITIRQ(clps7500_init_irq)
- .timer = &clps7500_timer,
+ .init_machine = clps7500_init,
+ .timer = &clps7500_timer,
MACHINE_END
diff --git a/arch/arm/mach-ebsa110/io.c b/arch/arm/mach-ebsa110/io.c
index f5181ed485ed8..ef7eb5dc91bd9 100644
--- a/arch/arm/mach-ebsa110/io.c
+++ b/arch/arm/mach-ebsa110/io.c
@@ -153,9 +153,9 @@ u8 __inb8(unsigned int port)
* The SuperIO registers use sane addressing techniques...
*/
if (SUPERIO_PORT(port))
- ret = __raw_readb(ISAIO_BASE + (port << 2));
+ ret = __raw_readb((void __iomem *)ISAIO_BASE + (port << 2));
else {
- void __iomem *a = ISAIO_BASE + ((port & ~1) << 1);
+ void __iomem *a = (void __iomem *)ISAIO_BASE + ((port & ~1) << 1);
/*
* Shame nothing else does
@@ -174,45 +174,33 @@ u8 __inb8(unsigned int port)
*/
u8 __inb16(unsigned int port)
{
- u32 ret;
+ unsigned int offset;
/*
* The SuperIO registers use sane addressing techniques...
*/
if (SUPERIO_PORT(port))
- ret = __raw_readb(ISAIO_BASE + (port << 2));
- else {
- void __iomem *a = ISAIO_BASE + ((port & ~1) << 1);
+ offset = port << 2;
+ else
+ offset = (port & ~1) << 1 | (port & 1);
- /*
- * Shame nothing else does
- */
- ret = __raw_readb(a + (port & 1));
- }
- return ret;
+ return __raw_readb((void __iomem *)ISAIO_BASE + offset);
}
u16 __inw(unsigned int port)
{
- u32 ret;
+ unsigned int offset;
/*
* The SuperIO registers use sane addressing techniques...
*/
if (SUPERIO_PORT(port))
- ret = __raw_readw(ISAIO_BASE + (port << 2));
+ offset = port << 2;
else {
- void __iomem *a = ISAIO_BASE + ((port & ~1) << 1);
-
- /*
- * Shame nothing else does
- */
- if (port & 1)
- BUG();
-
- ret = __raw_readw(a);
+ offset = port << 1;
+ BUG_ON(port & 1);
}
- return ret;
+ return __raw_readw((void __iomem *)ISAIO_BASE + offset);
}
/*
@@ -225,7 +213,7 @@ u32 __inl(unsigned int port)
if (SUPERIO_PORT(port) || port & 3)
BUG();
- a = ISAIO_BASE + (port << 1);
+ a = (void __iomem *)ISAIO_BASE + ((port & ~1) << 1);
return __raw_readw(a) | __raw_readw(a + 4) << 16;
}
@@ -241,9 +229,9 @@ void __outb8(u8 val, unsigned int port)
* The SuperIO registers use sane addressing techniques...
*/
if (SUPERIO_PORT(port))
- __raw_writeb(val, ISAIO_BASE + (port << 2));
+ __raw_writeb(val, (void __iomem *)ISAIO_BASE + (port << 2));
else {
- void __iomem *a = ISAIO_BASE + ((port & ~1) << 1);
+ void __iomem *a = (void __iomem *)ISAIO_BASE + ((port & ~1) << 1);
/*
* Shame nothing else does
@@ -257,37 +245,33 @@ void __outb8(u8 val, unsigned int port)
void __outb16(u8 val, unsigned int port)
{
+ unsigned int offset;
+
/*
* The SuperIO registers use sane addressing techniques...
*/
if (SUPERIO_PORT(port))
- __raw_writeb(val, ISAIO_BASE + (port << 2));
- else {
- void __iomem *a = ISAIO_BASE + ((port & ~1) << 1);
+ offset = port << 2;
+ else
+ offset = (port & ~1) << 1 | (port & 1);
- /*
- * Shame nothing else does
- */
- __raw_writeb(val, a + (port & 1));
- }
+ __raw_writeb(val, (void __iomem *)ISAIO_BASE + offset);
}
void __outw(u16 val, unsigned int port)
{
- u32 off;
+ unsigned int offset;
/*
* The SuperIO registers use sane addressing techniques...
*/
if (SUPERIO_PORT(port))
- off = port << 2;
+ offset = port << 2;
else {
- off = port << 1;
- if (port & 1)
- BUG();
-
+ offset = port << 1;
+ BUG_ON(port & 1);
}
- __raw_writew(val, ISAIO_BASE + off);
+ __raw_writew(val, (void __iomem *)ISAIO_BASE + offset);
}
void __outl(u32 val, unsigned int port)
@@ -300,13 +284,6 @@ EXPORT_SYMBOL(__outb16);
EXPORT_SYMBOL(__outw);
EXPORT_SYMBOL(__outl);
-extern void __arch_writesb(unsigned long virt, const void *from, int len);
-extern void __arch_writesw(unsigned long virt, const void *from, int len);
-extern void __arch_writesl(unsigned long virt, const void *from, int len);
-extern void __arch_readsb(unsigned long virt, void *from, int len);
-extern void __arch_readsw(unsigned long virt, void *from, int len);
-extern void __arch_readsl(unsigned long virt, void *from, int len);
-
void outsb(unsigned int port, const void *from, int len)
{
u32 off;
@@ -319,7 +296,7 @@ void outsb(unsigned int port, const void *from, int len)
BUG();
}
- __raw_writesb(ISAIO_BASE + off, from, len);
+ __raw_writesb((void __iomem *)ISAIO_BASE + off, from, len);
}
void insb(unsigned int port, void *from, int len)
@@ -334,7 +311,7 @@ void insb(unsigned int port, void *from, int len)
BUG();
}
- __raw_readsb(ISAIO_BASE + off, from, len);
+ __raw_readsb((void __iomem *)ISAIO_BASE + off, from, len);
}
EXPORT_SYMBOL(outsb);
@@ -352,7 +329,7 @@ void outsw(unsigned int port, const void *from, int len)
BUG();
}
- __raw_writesw(ISAIO_BASE + off, from, len);
+ __raw_writesw((void __iomem *)ISAIO_BASE + off, from, len);
}
void insw(unsigned int port, void *from, int len)
@@ -367,7 +344,7 @@ void insw(unsigned int port, void *from, int len)
BUG();
}
- __raw_readsw(ISAIO_BASE + off, from, len);
+ __raw_readsw((void __iomem *)ISAIO_BASE + off, from, len);
}
EXPORT_SYMBOL(outsw);
@@ -384,7 +361,7 @@ void outsl(unsigned int port, const void *from, int len)
if (SUPERIO_PORT(port) || port & 3)
BUG();
- __raw_writesw(ISAIO_BASE + off, from, len << 1);
+ __raw_writesw((void __iomem *)ISAIO_BASE + off, from, len << 1);
}
void insl(unsigned int port, void *from, int len)
@@ -394,7 +371,7 @@ void insl(unsigned int port, void *from, int len)
if (SUPERIO_PORT(port) || port & 3)
BUG();
- __raw_readsw(ISAIO_BASE + off, from, len << 1);
+ __raw_readsw((void __iomem *)ISAIO_BASE + off, from, len << 1);
}
EXPORT_SYMBOL(outsl);
diff --git a/arch/arm/mach-footbridge/cats-hw.c b/arch/arm/mach-footbridge/cats-hw.c
index f94d176c3201d..d1ced86c379c4 100644
--- a/arch/arm/mach-footbridge/cats-hw.c
+++ b/arch/arm/mach-footbridge/cats-hw.c
@@ -8,6 +8,7 @@
#include <linux/ioport.h>
#include <linux/kernel.h>
#include <linux/init.h>
+#include <linux/tty.h>
#include <asm/hardware/dec21285.h>
#include <asm/io.h>
diff --git a/arch/arm/mach-imx/dma.c b/arch/arm/mach-imx/dma.c
index 7387ccbd8720f..71a59e196166c 100644
--- a/arch/arm/mach-imx/dma.c
+++ b/arch/arm/mach-imx/dma.c
@@ -100,10 +100,11 @@ imx_free_dma(int dma_ch)
static irqreturn_t
dma_err_handler(int irq, void *dev_id, struct pt_regs *regs)
{
- int i;
+ int i, disr = DISR;
struct dma_channel *channel;
unsigned int err_mask = DBTOSR | DRTOSR | DSESR | DBOSR;
+ DISR = disr;
for (i = 0; i < 11; i++) {
channel = &dma_channels[i];
@@ -136,7 +137,6 @@ dma_err_handler(int irq, void *dev_id, struct pt_regs *regs)
i, channel->name);
DBOSR |= (1 << i);
}
- DISR |= (1 << i);
}
return IRQ_HANDLED;
}
@@ -146,6 +146,7 @@ dma_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
{
int i, disr = DISR;
+ DISR = disr;
for (i = 0; i < 11; i++) {
if (disr & (1 << i)) {
struct dma_channel *channel = &dma_channels[i];
@@ -158,7 +159,6 @@ dma_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
*/
printk(KERN_WARNING
"spurious IRQ for DMA channel %d\n", i);
- DISR |= (1 << i);
}
}
}
diff --git a/arch/arm/mach-imx/generic.c b/arch/arm/mach-imx/generic.c
index 4954653ec6ae9..54377d0f578c3 100644
--- a/arch/arm/mach-imx/generic.c
+++ b/arch/arm/mach-imx/generic.c
@@ -100,8 +100,8 @@ EXPORT_SYMBOL(imx_gpio_mode);
static unsigned int imx_decode_pll(unsigned int pll)
{
u32 mfi = (pll >> 10) & 0xf;
- u32 mfn = pll & 0x3f;
- u32 mfd = (pll >> 16) & 0x3f;
+ u32 mfn = pll & 0x3ff;
+ u32 mfd = (pll >> 16) & 0x3ff;
u32 pd = (pll >> 26) & 0xf;
u32 f_ref = (CSCR & CSCR_SYSTEM_SEL) ? 16000000 : (CLK32 * 512);
diff --git a/arch/arm/mach-ixp2000/core.c b/arch/arm/mach-ixp2000/core.c
index 36d9ecedaea97..4f3c3d5c781ca 100644
--- a/arch/arm/mach-ixp2000/core.c
+++ b/arch/arm/mach-ixp2000/core.c
@@ -79,31 +79,11 @@ void ixp2000_release_slowport(struct slowport_cfg *old_cfg)
/*************************************************************************
* Chip specific mappings shared by all IXP2000 systems
*************************************************************************/
-static struct map_desc ixp2000_small_io_desc[] __initdata = {
+static struct map_desc ixp2000_io_desc[] __initdata = {
{
- .virtual = IXP2000_GLOBAL_REG_VIRT_BASE,
- .physical = IXP2000_GLOBAL_REG_PHYS_BASE,
- .length = IXP2000_GLOBAL_REG_SIZE,
- .type = MT_DEVICE
- }, {
- .virtual = IXP2000_GPIO_VIRT_BASE,
- .physical = IXP2000_GPIO_PHYS_BASE,
- .length = IXP2000_GPIO_SIZE,
- .type = MT_DEVICE
- }, {
- .virtual = IXP2000_TIMER_VIRT_BASE,
- .physical = IXP2000_TIMER_PHYS_BASE,
- .length = IXP2000_TIMER_SIZE,
- .type = MT_DEVICE
- }, {
- .virtual = IXP2000_UART_VIRT_BASE,
- .physical = IXP2000_UART_PHYS_BASE,
- .length = IXP2000_UART_SIZE,
- .type = MT_DEVICE
- }, {
- .virtual = IXP2000_SLOWPORT_CSR_VIRT_BASE,
- .physical = IXP2000_SLOWPORT_CSR_PHYS_BASE,
- .length = IXP2000_SLOWPORT_CSR_SIZE,
+ .virtual = IXP2000_CAP_VIRT_BASE,
+ .physical = IXP2000_CAP_PHYS_BASE,
+ .length = IXP2000_CAP_SIZE,
.type = MT_DEVICE
}, {
.virtual = IXP2000_INTCTL_VIRT_BASE,
@@ -115,11 +95,7 @@ static struct map_desc ixp2000_small_io_desc[] __initdata = {
.physical = IXP2000_PCI_CREG_PHYS_BASE,
.length = IXP2000_PCI_CREG_SIZE,
.type = MT_DEVICE
- }
-};
-
-static struct map_desc ixp2000_large_io_desc[] __initdata = {
- {
+ }, {
.virtual = IXP2000_PCI_CSR_VIRT_BASE,
.physical = IXP2000_PCI_CSR_PHYS_BASE,
.length = IXP2000_PCI_CSR_SIZE,
@@ -157,8 +133,23 @@ static struct uart_port ixp2000_serial_port = {
void __init ixp2000_map_io(void)
{
- iotable_init(ixp2000_small_io_desc, ARRAY_SIZE(ixp2000_small_io_desc));
- iotable_init(ixp2000_large_io_desc, ARRAY_SIZE(ixp2000_large_io_desc));
+ extern unsigned int processor_id;
+
+ /*
+ * On IXP2400 CPUs we need to use MT_IXP2000_DEVICE for
+ * tweaking the PMDs so XCB=101. On IXP2800s we use the normal
+ * PMD flags.
+ */
+ if ((processor_id & 0xfffffff0) == 0x69054190) {
+ int i;
+
+ printk(KERN_INFO "Enabling IXP2400 erratum #66 workaround\n");
+
+ for(i=0;i<ARRAY_SIZE(ixp2000_io_desc);i++)
+ ixp2000_io_desc[i].type = MT_IXP2000_DEVICE;
+ }
+
+ iotable_init(ixp2000_io_desc, ARRAY_SIZE(ixp2000_io_desc));
early_serial_setup(&ixp2000_serial_port);
/* Set slowport to 8-bit mode. */
@@ -212,7 +203,7 @@ void __init ixp2000_init_time(unsigned long tick_rate)
ticks_per_jiffy = (tick_rate + HZ/2) / HZ;
ticks_per_usec = tick_rate / 1000000;
- ixp2000_reg_write(IXP2000_T1_CLD, ticks_per_jiffy);
+ ixp2000_reg_write(IXP2000_T1_CLD, ticks_per_jiffy - 1);
ixp2000_reg_write(IXP2000_T1_CTL, (1 << 7));
/*
@@ -220,7 +211,7 @@ void __init ixp2000_init_time(unsigned long tick_rate)
*/
ixp2000_reg_write(IXP2000_T4_CLD, -1);
ixp2000_reg_write(IXP2000_T4_CTL, (1 << 7));
- next_jiffy_time = 0xffffffff - ticks_per_jiffy;
+ next_jiffy_time = 0xffffffff;
/* register for interrupt */
setup_irq(IRQ_IXP2000_TIMER1, &ixp2000_timer_irq);
@@ -385,7 +376,9 @@ void __init ixp2000_init_irq(void)
set_irq_chained_handler(IRQ_IXP2000_GPIO, ixp2000_GPIO_irq_handler);
/*
- * Enable PCI irq
+ * Enable PCI irqs. The actual PCI[AB] decoding is done in
+ * entry-macro.S, so we don't need a chained handler for the
+ * PCI interrupt source.
*/
ixp2000_reg_write(IXP2000_IRQ_ENABLE_SET, (1 << IRQ_IXP2000_PCI));
for (irq = IRQ_IXP2000_PCIA; irq <= IRQ_IXP2000_PCIB; irq++) {
diff --git a/arch/arm/mach-ixp2000/enp2611.c b/arch/arm/mach-ixp2000/enp2611.c
index e4d2992d9427c..04b38bcf9aace 100644
--- a/arch/arm/mach-ixp2000/enp2611.c
+++ b/arch/arm/mach-ixp2000/enp2611.c
@@ -6,7 +6,7 @@
* Created 2004 by Lennert Buytenhek from the ixdp2x01 code. The
* original version carries the following notices:
*
- * Original Author: Andrzej Mialwoski <andrzej.mialwoski@intel.com>
+ * Original Author: Andrzej Mialkowski <andrzej.mialkowski@intel.com>
* Maintainer: Deepak Saxena <dsaxena@plexity.net>
*
* Copyright (C) 2002-2003 Intel Corp.
@@ -207,7 +207,6 @@ static void __init enp2611_init_machine(void)
}
-#ifdef CONFIG_ARCH_ENP2611
MACHINE_START(ENP2611, "Radisys ENP-2611 PCI network processor board")
MAINTAINER("Lennert Buytenhek <buytenh@wantstofly.org>")
BOOT_MEM(0x00000000, IXP2000_UART_PHYS_BASE, IXP2000_UART_VIRT_BASE)
@@ -217,6 +216,5 @@ MACHINE_START(ENP2611, "Radisys ENP-2611 PCI network processor board")
.timer = &enp2611_timer,
INIT_MACHINE(enp2611_init_machine)
MACHINE_END
-#endif
diff --git a/arch/arm/mach-ixp2000/ixdp2x01.c b/arch/arm/mach-ixp2000/ixdp2x01.c
index 0e919bbf9d92a..e94dace3d4122 100644
--- a/arch/arm/mach-ixp2000/ixdp2x01.c
+++ b/arch/arm/mach-ixp2000/ixdp2x01.c
@@ -3,7 +3,7 @@
*
* Code common to Intel IXDP2401 and IXDP2801 platforms
*
- * Original Author: Andrzej Mialwoski <andrzej.mialwoski@intel.com>
+ * Original Author: Andrzej Mialkowski <andrzej.mialkowski@intel.com>
* Maintainer: Deepak Saxena <dsaxena@plexity.net>
*
* Copyright (C) 2002-2003 Intel Corp.
diff --git a/arch/arm/mach-ixp4xx/Makefile b/arch/arm/mach-ixp4xx/Makefile
index 16ecbb0f11ea5..ddecbda4a633e 100644
--- a/arch/arm/mach-ixp4xx/Makefile
+++ b/arch/arm/mach-ixp4xx/Makefile
@@ -7,6 +7,5 @@ obj-y += common.o common-pci.o
obj-$(CONFIG_ARCH_IXDP4XX) += ixdp425-pci.o ixdp425-setup.o
obj-$(CONFIG_MACH_IXDPG425) += ixdpg425-pci.o coyote-setup.o
obj-$(CONFIG_ARCH_ADI_COYOTE) += coyote-pci.o coyote-setup.o
-obj-$(CONFIG_ARCH_PRPMC1100) += prpmc1100-pci.o prpmc1100-setup.o
obj-$(CONFIG_MACH_GTWX5715) += gtwx5715-pci.o gtwx5715-setup.o
diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c
index c3211bc6ab75c..267ba02d77dc7 100644
--- a/arch/arm/mach-ixp4xx/common.c
+++ b/arch/arm/mach-ixp4xx/common.c
@@ -38,6 +38,10 @@
#include <asm/mach/irq.h>
#include <asm/mach/time.h>
+enum ixp4xx_irq_type {
+ IXP4XX_IRQ_LEVEL, IXP4XX_IRQ_EDGE
+};
+static void ixp4xx_config_irq(unsigned irq, enum ixp4xx_irq_type type);
/*************************************************************************
* GPIO acces functions
@@ -51,9 +55,13 @@
*/
void gpio_line_config(u8 line, u32 style)
{
+ static const int gpio2irq[] = {
+ 6, 7, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29
+ };
u32 enable;
volatile u32 *int_reg;
u32 int_style;
+ enum ixp4xx_irq_type irq_type;
enable = *IXP4XX_GPIO_GPOER;
@@ -66,24 +74,33 @@ void gpio_line_config(u8 line, u32 style)
{
case (IXP4XX_GPIO_ACTIVE_HIGH):
int_style = IXP4XX_GPIO_STYLE_ACTIVE_HIGH;
+ irq_type = IXP4XX_IRQ_LEVEL;
break;
case (IXP4XX_GPIO_ACTIVE_LOW):
int_style = IXP4XX_GPIO_STYLE_ACTIVE_LOW;
+ irq_type = IXP4XX_IRQ_LEVEL;
break;
case (IXP4XX_GPIO_RISING_EDGE):
int_style = IXP4XX_GPIO_STYLE_RISING_EDGE;
+ irq_type = IXP4XX_IRQ_EDGE;
break;
case (IXP4XX_GPIO_FALLING_EDGE):
int_style = IXP4XX_GPIO_STYLE_FALLING_EDGE;
+ irq_type = IXP4XX_IRQ_EDGE;
break;
case (IXP4XX_GPIO_TRANSITIONAL):
int_style = IXP4XX_GPIO_STYLE_TRANSITIONAL;
+ irq_type = IXP4XX_IRQ_EDGE;
break;
default:
int_style = IXP4XX_GPIO_STYLE_ACTIVE_HIGH;
+ irq_type = IXP4XX_IRQ_LEVEL;
break;
}
+ if (style & IXP4XX_GPIO_INTSTYLE_MASK)
+ ixp4xx_config_irq(gpio2irq[line], irq_type);
+
if (line >= 8) { /* pins 8-15 */
line -= 8;
int_reg = IXP4XX_GPIO_GPIT2R;
@@ -138,10 +155,7 @@ void __init ixp4xx_map_io(void)
*
* TODO: GPIO IRQs should be marked invalid until the user of the IRQ
* (be it PCI or something else) configures that GPIO line
- * as an IRQ. Also, we should use a different chip structure for
- * level-based GPIO vs edge-based GPIO. Currently nobody needs this as
- * all HW that's publically available uses level IRQs, so we'll
- * worry about it if/when we have HW to test.
+ * as an IRQ.
**************************************************************************/
static void ixp4xx_irq_mask(unsigned int irq)
{
@@ -151,12 +165,15 @@ static void ixp4xx_irq_mask(unsigned int irq)
*IXP4XX_ICMR &= ~(1 << irq);
}
-static void ixp4xx_irq_mask_ack(unsigned int irq)
+static void ixp4xx_irq_unmask(unsigned int irq)
{
- ixp4xx_irq_mask(irq);
+ if (cpu_is_ixp46x() && irq >= 32)
+ *IXP4XX_ICMR2 |= (1 << (irq - 32));
+ else
+ *IXP4XX_ICMR |= (1 << irq);
}
-static void ixp4xx_irq_unmask(unsigned int irq)
+static void ixp4xx_irq_ack(unsigned int irq)
{
static int irq2gpio[32] = {
-1, -1, -1, -1, -1, -1, 0, 1,
@@ -166,26 +183,47 @@ static void ixp4xx_irq_unmask(unsigned int irq)
};
int line = (irq < 32) ? irq2gpio[irq] : -1;
- /*
- * This only works for LEVEL gpio IRQs as per the IXP4xx developer's
- * manual. If edge-triggered, need to move it to the mask_ack.
- * Nobody seems to be using the edge-triggered mode on the GPIOs.
- */
if (line >= 0)
gpio_line_isr_clear(line);
+}
- if (cpu_is_ixp46x() && irq >= 32)
- *IXP4XX_ICMR2 |= (1 << (irq - 32));
- else
- *IXP4XX_ICMR |= (1 << irq);
+/*
+ * Level triggered interrupts on GPIO lines can only be cleared when the
+ * interrupt condition disappears.
+ */
+static void ixp4xx_irq_level_unmask(unsigned int irq)
+{
+ ixp4xx_irq_ack(irq);
+ ixp4xx_irq_unmask(irq);
}
-static struct irqchip ixp4xx_irq_chip = {
- .ack = ixp4xx_irq_mask_ack,
+static struct irqchip ixp4xx_irq_level_chip = {
+ .ack = ixp4xx_irq_mask,
+ .mask = ixp4xx_irq_mask,
+ .unmask = ixp4xx_irq_level_unmask,
+};
+
+static struct irqchip ixp4xx_irq_edge_chip = {
+ .ack = ixp4xx_irq_ack,
.mask = ixp4xx_irq_mask,
.unmask = ixp4xx_irq_unmask,
};
+static void ixp4xx_config_irq(unsigned irq, enum ixp4xx_irq_type type)
+{
+ switch (type) {
+ case IXP4XX_IRQ_LEVEL:
+ set_irq_chip(irq, &ixp4xx_irq_level_chip);
+ set_irq_handler(irq, do_level_IRQ);
+ break;
+ case IXP4XX_IRQ_EDGE:
+ set_irq_chip(irq, &ixp4xx_irq_edge_chip);
+ set_irq_handler(irq, do_edge_IRQ);
+ break;
+ }
+ set_irq_flags(irq, IRQF_VALID);
+}
+
void __init ixp4xx_init_irq(void)
{
int i = 0;
@@ -204,12 +242,9 @@ void __init ixp4xx_init_irq(void)
*IXP4XX_ICMR2 = 0x00;
}
+ /* Default to all level triggered */
for(i = 0; i < NR_IRQS; i++)
- {
- set_irq_chip(i, &ixp4xx_irq_chip);
- set_irq_handler(i, do_level_IRQ);
- set_irq_flags(i, IRQF_VALID);
- }
+ ixp4xx_config_irq(i, IXP4XX_IRQ_LEVEL);
}
diff --git a/arch/arm/mach-ixp4xx/coyote-setup.c b/arch/arm/mach-ixp4xx/coyote-setup.c
index 1d06d364c34ed..8a05a1227e5f6 100644
--- a/arch/arm/mach-ixp4xx/coyote-setup.c
+++ b/arch/arm/mach-ixp4xx/coyote-setup.c
@@ -3,7 +3,7 @@
*
* Board setup for ADI Engineering and IXDGP425 boards
*
- * Copyright (C) 2003-2004 MontaVista Software, Inc.
+ * Copyright (C) 2003-2005 MontaVista Software, Inc.
*
* Author: Deepak Saxena <dsaxena@plexity.net>
*/
@@ -13,7 +13,7 @@
#include <linux/device.h>
#include <linux/serial.h>
#include <linux/tty.h>
-#include <linux/serial_core.h>
+#include <linux/serial_8250.h>
#include <asm/types.h>
#include <asm/setup.h>
@@ -24,39 +24,8 @@
#include <asm/mach/arch.h>
#include <asm/mach/flash.h>
-#ifdef __ARMEB__
-#define REG_OFFSET 3
-#else
-#define REG_OFFSET 0
-#endif
-
-/*
- * Only one serial port is connected on the Coyote & IXDPG425
- */
-static struct uart_port coyote_serial_port = {
- .membase = (char*)(IXP4XX_UART2_BASE_VIRT + REG_OFFSET),
- .mapbase = (IXP4XX_UART2_BASE_PHYS),
- .irq = IRQ_IXP4XX_UART2,
- .flags = UPF_SKIP_TEST,
- .iotype = UPIO_MEM,
- .regshift = 2,
- .uartclk = IXP4XX_UART_XTAL,
- .line = 0,
- .type = PORT_XSCALE,
- .fifosize = 32
-};
-
void __init coyote_map_io(void)
{
- if (machine_is_ixdpg425()) {
- coyote_serial_port.membase =
- (char*)(IXP4XX_UART1_BASE_VIRT + REG_OFFSET);
- coyote_serial_port.mapbase = IXP4XX_UART1_BASE_PHYS;
- coyote_serial_port.irq = IRQ_IXP4XX_UART1;
- }
-
- early_serial_setup(&coyote_serial_port);
-
ixp4xx_map_io();
}
@@ -81,8 +50,35 @@ static struct platform_device coyote_flash = {
.resource = &coyote_flash_resource,
};
+static struct resource coyote_uart_resource = {
+ .start = IXP4XX_UART2_BASE_PHYS,
+ .end = IXP4XX_UART2_BASE_PHYS + 0x0fff,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct plat_serial8250_port coyote_uart_data = {
+ .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 coyote_uart = {
+ .name = "serial8250",
+ .id = 0,
+ .dev = {
+ .platform_data = &coyote_uart_data,
+ },
+ .num_resources = 1,
+ .resource = &coyote_uart_resource,
+};
+
static struct platform_device *coyote_devices[] __initdata = {
- &coyote_flash
+ &coyote_flash,
+ &coyote_uart
};
static void __init coyote_init(void)
@@ -90,6 +86,14 @@ static void __init coyote_init(void)
*IXP4XX_EXP_CS0 |= IXP4XX_FLASH_WRITABLE;
*IXP4XX_EXP_CS1 = *IXP4XX_EXP_CS0;
+ if (machine_is_ixdpg425()) {
+ coyote_uart_data.membase =
+ (char*)(IXP4XX_UART1_BASE_VIRT + REG_OFFSET);
+ coyote_uart_data.mapbase = IXP4XX_UART1_BASE_PHYS;
+ coyote_uart_data.irq = IRQ_IXP4XX_UART1;
+ }
+
+
ixp4xx_sys_init();
platform_add_devices(coyote_devices, ARRAY_SIZE(coyote_devices));
}
diff --git a/arch/arm/mach-ixp4xx/ixdp425-setup.c b/arch/arm/mach-ixp4xx/ixdp425-setup.c
index 77006d96aacfd..77346c1f676bb 100644
--- a/arch/arm/mach-ixp4xx/ixdp425-setup.c
+++ b/arch/arm/mach-ixp4xx/ixdp425-setup.c
@@ -3,7 +3,7 @@
*
* IXDP425/IXCDP1100 board-setup
*
- * Copyright (C) 2003-2004 MontaVista Software, Inc.
+ * Copyright (C) 2003-2005 MontaVista Software, Inc.
*
* Author: Deepak Saxena <dsaxena@plexity.net>
*/
@@ -13,7 +13,7 @@
#include <linux/device.h>
#include <linux/serial.h>
#include <linux/tty.h>
-#include <linux/serial_core.h>
+#include <linux/serial_8250.h>
#include <asm/types.h>
#include <asm/setup.h>
@@ -24,46 +24,8 @@
#include <asm/mach/arch.h>
#include <asm/mach/flash.h>
-#ifdef __ARMEB__
-#define REG_OFFSET 3
-#else
-#define REG_OFFSET 0
-#endif
-
-/*
- * IXDP425 uses both chipset serial ports
- */
-static struct uart_port ixdp425_serial_ports[] = {
- {
- .membase = (char*)(IXP4XX_UART1_BASE_VIRT + REG_OFFSET),
- .mapbase = (IXP4XX_UART1_BASE_PHYS),
- .irq = IRQ_IXP4XX_UART1,
- .flags = UPF_SKIP_TEST,
- .iotype = UPIO_MEM,
- .regshift = 2,
- .uartclk = IXP4XX_UART_XTAL,
- .line = 0,
- .type = PORT_XSCALE,
- .fifosize = 32
- } , {
- .membase = (char*)(IXP4XX_UART2_BASE_VIRT + REG_OFFSET),
- .mapbase = (IXP4XX_UART2_BASE_PHYS),
- .irq = IRQ_IXP4XX_UART2,
- .flags = UPF_SKIP_TEST,
- .iotype = UPIO_MEM,
- .regshift = 2,
- .uartclk = IXP4XX_UART_XTAL,
- .line = 1,
- .type = PORT_XSCALE,
- .fifosize = 32
- }
-};
-
void __init ixdp425_map_io(void)
{
- early_serial_setup(&ixdp425_serial_ports[0]);
- early_serial_setup(&ixdp425_serial_ports[1]);
-
ixp4xx_map_io();
}
@@ -102,11 +64,55 @@ static struct platform_device ixdp425_i2c_controller = {
.num_resources = 0
};
+static struct resource ixdp425_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 ixdp425_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_UART1,
+ .flags = UPF_BOOT_AUTOCONF,
+ .iotype = UPIO_MEM,
+ .regshift = 2,
+ .uartclk = IXP4XX_UART_XTAL,
+ }
+};
+
+static struct platform_device ixdp425_uart = {
+ .name = "serial8250",
+ .id = 0,
+ .dev.platform_data = ixdp425_uart_data,
+ .num_resources = 2,
+ .resource = ixdp425_uart_resources
+};
+
static struct platform_device *ixdp425_devices[] __initdata = {
&ixdp425_i2c_controller,
- &ixdp425_flash
+ &ixdp425_flash,
+ &ixdp425_uart
};
+
static void __init ixdp425_init(void)
{
ixp4xx_sys_init();
diff --git a/arch/arm/mach-ixp4xx/prpmc1100-pci.c b/arch/arm/mach-ixp4xx/prpmc1100-pci.c
deleted file mode 100644
index 9ee0ab9dac3a6..0000000000000
--- a/arch/arm/mach-ixp4xx/prpmc1100-pci.c
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * arch/arm/mach-ixp4xx/prpmc1100-pci.c
- *
- * PrPMC1100 PCI initialization
- *
- * Copyright (C) 2003-2004 MontaVista Sofwtare, Inc.
- * Based on IXDP425 code originally (C) Intel Corporation
- *
- * Author: Deepak Saxena <dsaxena@plexity.net>
- *
- * PrPMC1100 PCI init code. GPIO usage is similar to that on
- * IXDP425, but the IRQ routing is completely different and
- * depends on what carrier you are using. This code is written
- * to work on the Motorola PrPMC800 ATX carrier board.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/config.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-
-#include <asm/mach-types.h>
-#include <asm/irq.h>
-#include <asm/hardware.h>
-
-#include <asm/mach/pci.h>
-
-
-void __init prpmc1100_pci_preinit(void)
-{
- gpio_line_config(PRPMC1100_PCI_INTA_PIN,
- IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW);
- gpio_line_config(PRPMC1100_PCI_INTB_PIN,
- IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW);
- gpio_line_config(PRPMC1100_PCI_INTC_PIN,
- IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW);
- gpio_line_config(PRPMC1100_PCI_INTD_PIN,
- IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW);
-
- gpio_line_isr_clear(PRPMC1100_PCI_INTA_PIN);
- gpio_line_isr_clear(PRPMC1100_PCI_INTB_PIN);
- gpio_line_isr_clear(PRPMC1100_PCI_INTC_PIN);
- gpio_line_isr_clear(PRPMC1100_PCI_INTD_PIN);
-
- ixp4xx_pci_preinit();
-}
-
-
-static int __init prpmc1100_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
-{
- int irq = -1;
-
- static int pci_irq_table[][4] = {
- { /* IDSEL 16 - PMC A1 */
- IRQ_PRPMC1100_PCI_INTD,
- IRQ_PRPMC1100_PCI_INTA,
- IRQ_PRPMC1100_PCI_INTB,
- IRQ_PRPMC1100_PCI_INTC
- }, { /* IDSEL 17 - PRPMC-A-B */
- IRQ_PRPMC1100_PCI_INTD,
- IRQ_PRPMC1100_PCI_INTA,
- IRQ_PRPMC1100_PCI_INTB,
- IRQ_PRPMC1100_PCI_INTC
- }, { /* IDSEL 18 - PMC A1-B */
- IRQ_PRPMC1100_PCI_INTA,
- IRQ_PRPMC1100_PCI_INTB,
- IRQ_PRPMC1100_PCI_INTC,
- IRQ_PRPMC1100_PCI_INTD
- }, { /* IDSEL 19 - Unused */
- 0, 0, 0, 0
- }, { /* IDSEL 20 - P2P Bridge */
- IRQ_PRPMC1100_PCI_INTA,
- IRQ_PRPMC1100_PCI_INTB,
- IRQ_PRPMC1100_PCI_INTC,
- IRQ_PRPMC1100_PCI_INTD
- }, { /* IDSEL 21 - PMC A2 */
- IRQ_PRPMC1100_PCI_INTC,
- IRQ_PRPMC1100_PCI_INTD,
- IRQ_PRPMC1100_PCI_INTA,
- IRQ_PRPMC1100_PCI_INTB
- }, { /* IDSEL 22 - PMC A2-B */
- IRQ_PRPMC1100_PCI_INTD,
- IRQ_PRPMC1100_PCI_INTA,
- IRQ_PRPMC1100_PCI_INTB,
- IRQ_PRPMC1100_PCI_INTC
- },
- };
-
- if (slot >= PRPMC1100_PCI_MIN_DEVID && slot <= PRPMC1100_PCI_MAX_DEVID
- && pin >= 1 && pin <= PRPMC1100_PCI_IRQ_LINES) {
- irq = pci_irq_table[slot - PRPMC1100_PCI_MIN_DEVID][pin - 1];
- }
-
- return irq;
-}
-
-
-struct hw_pci prpmc1100_pci __initdata = {
- .nr_controllers = 1,
- .preinit = prpmc1100_pci_preinit,
- .swizzle = pci_std_swizzle,
- .setup = ixp4xx_setup,
- .scan = ixp4xx_scan_bus,
- .map_irq = prpmc1100_map_irq,
-};
-
-int __init prpmc1100_pci_init(void)
-{
- if (machine_is_prpmc1100())
- pci_common_init(&prpmc1100_pci);
- return 0;
-}
-
-subsys_initcall(prpmc1100_pci_init);
-
diff --git a/arch/arm/mach-ixp4xx/prpmc1100-setup.c b/arch/arm/mach-ixp4xx/prpmc1100-setup.c
deleted file mode 100644
index ed4281565bcd8..0000000000000
--- a/arch/arm/mach-ixp4xx/prpmc1100-setup.c
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * arch/arm/mach-ixp4xx/prpmc1100-setup.c
- *
- * Motorola PrPMC1100 board setup
- *
- * Copyright (C) 2003-2004 MontaVista Software, Inc.
- *
- * Author: Deepak Saxena <dsaxena@plexity.net>
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/device.h>
-#include <linux/serial.h>
-#include <linux/tty.h>
-#include <linux/serial_core.h>
-
-#include <asm/types.h>
-#include <asm/setup.h>
-#include <asm/memory.h>
-#include <asm/hardware.h>
-#include <asm/irq.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/flash.h>
-
-#ifdef __ARMEB__
-#define REG_OFFSET 3
-#else
-#define REG_OFFSET 0
-#endif
-
-/*
- * Only one serial port is connected on the PrPMC1100
- */
-static struct uart_port prpmc1100_serial_port = {
- .membase = (char*)(IXP4XX_UART1_BASE_VIRT + REG_OFFSET),
- .mapbase = (IXP4XX_UART1_BASE_PHYS),
- .irq = IRQ_IXP4XX_UART1,
- .flags = UPF_SKIP_TEST,
- .iotype = UPIO_MEM,
- .regshift = 2,
- .uartclk = IXP4XX_UART_XTAL,
- .line = 0,
- .type = PORT_XSCALE,
- .fifosize = 32
-};
-
-void __init prpmc1100_map_io(void)
-{
- early_serial_setup(&prpmc1100_serial_port);
-
- ixp4xx_map_io();
-}
-
-static struct flash_platform_data prpmc1100_flash_data = {
- .map_name = "cfi_probe",
- .width = 2,
-};
-
-static struct resource prpmc1100_flash_resource = {
- .start = PRPMC1100_FLASH_BASE,
- .end = PRPMC1100_FLASH_BASE + PRPMC1100_FLASH_SIZE,
- .flags = IORESOURCE_MEM,
-};
-
-static struct platform_device prpmc1100_flash = {
- .name = "IXP4XX-Flash",
- .id = 0,
- .dev = {
- .platform_data = &prpmc1100_flash_data,
- },
- .num_resources = 1,
- .resource = &prpmc1100_flash_resource,
-};
-
-static struct platform_device *prpmc1100_devices[] __initdata = {
- &prpmc1100_flash
-};
-
-static void __init prpmc1100_init(void)
-{
- ixp4xx_sys_init();
-
- platform_add_devices(prpmc1100_devices, ARRAY_SIZE(prpmc1100_devices));
-}
-
-MACHINE_START(PRPMC1100, "Motorola PrPMC1100")
- MAINTAINER("MontaVista Software, Inc.")
- BOOT_MEM(PHYS_OFFSET, IXP4XX_PERIPHERAL_BASE_PHYS,
- IXP4XX_PERIPHERAL_BASE_VIRT)
- MAPIO(prpmc1100_map_io)
- INITIRQ(ixp4xx_init_irq)
- .timer = &ixp4xx_timer,
- BOOT_PARAMS(0x0100)
- INIT_MACHINE(prpmc1100_init)
-MACHINE_END
-
diff --git a/arch/arm/mach-lh7a40x/arch-lpd7a40x.c b/arch/arm/mach-lh7a40x/arch-lpd7a40x.c
index 06373b295f835..c823447a150f7 100644
--- a/arch/arm/mach-lh7a40x/arch-lpd7a40x.c
+++ b/arch/arm/mach-lh7a40x/arch-lpd7a40x.c
@@ -157,8 +157,6 @@ static struct irqchip lpd7a40x_cpld_chip = {
.unmask = lh7a40x_unmask_cpld_irq,
};
-#define IRQ_DISPATCH(irq) irq_desc[irq].handle ((irq), &irq_desc[irq], regs)
-
static void lpd7a40x_cpld_handler (unsigned int irq, struct irqdesc *desc,
struct pt_regs *regs)
{
diff --git a/arch/arm/mach-lh7a40x/common.h b/arch/arm/mach-lh7a40x/common.h
index 05564eca35467..beda7c2602fbe 100644
--- a/arch/arm/mach-lh7a40x/common.h
+++ b/arch/arm/mach-lh7a40x/common.h
@@ -12,3 +12,5 @@ extern struct sys_timer lh7a40x_timer;
extern void lh7a400_init_irq (void);
extern void lh7a404_init_irq (void);
+
+#define IRQ_DISPATCH(irq) irq_desc[irq].handle ((irq), &irq_desc[irq], regs)
diff --git a/arch/arm/mach-lh7a40x/irq-lpd7a40x.c b/arch/arm/mach-lh7a40x/irq-lpd7a40x.c
index 458a16a6f659c..6262d449120cd 100644
--- a/arch/arm/mach-lh7a40x/irq-lpd7a40x.c
+++ b/arch/arm/mach-lh7a40x/irq-lpd7a40x.c
@@ -55,8 +55,6 @@ static struct irqchip lh7a40x_cpld_chip = {
.unmask = lh7a40x_unmask_cpld_irq,
};
-#define IRQ_DISPATCH(irq) irq_desc[irq].handle ((irq), &irq_desc[irq], regs)
-
static void lh7a40x_cpld_handler (unsigned int irq, struct irqdesc *desc,
struct pt_regs *regs)
{
diff --git a/arch/arm/mach-omap/Kconfig b/arch/arm/mach-omap/Kconfig
index f8d265d7088de..9e42efa66b2b5 100644
--- a/arch/arm/mach-omap/Kconfig
+++ b/arch/arm/mach-omap/Kconfig
@@ -66,6 +66,19 @@ config MACH_OMAP_PERSEUS2
Support for TI OMAP 730 Perseus2 board. Say Y here if you have such
a board.
+config MACH_VOICEBLUE
+ bool "Voiceblue"
+ depends on ARCH_OMAP1510
+ help
+ Support for Voiceblue GSM/VoIP gateway. Say Y here if you have such
+ board.
+
+config MACH_NETSTAR
+ bool "NetStar"
+ depends on ARCH_OMAP1510
+ help
+ Support for NetStar PBX. Say Y here if you have such a board.
+
config MACH_OMAP_GENERIC
bool "Generic OMAP board"
depends on ARCH_OMAP1510 || ARCH_OMAP16XX
@@ -113,6 +126,38 @@ config OMAP_MUX_WARNINGS
printed, it's safe to deselect OMAP_MUX for your product.
choice
+ prompt "System timer"
+ default OMAP_MPU_TIMER
+
+config OMAP_MPU_TIMER
+ bool "Use mpu timer"
+ help
+ Select this option if you want to use the OMAP mpu timer. This
+ timer provides more intra-tick resolution than the 32KHz timer,
+ but consumes more power.
+
+config OMAP_32K_TIMER
+ bool "Use 32KHz timer"
+ depends on ARCH_OMAP16XX
+ help
+ Select this option if you want to enable the OMAP 32KHz timer.
+ This timer saves power compared to the OMAP_MPU_TIMER, and has
+ support for no tick during idle. The 32KHz timer provides less
+ intra-tick resolution than OMAP_MPU_TIMER. The 32KHz timer is
+ currently only available for OMAP-16xx.
+
+endchoice
+
+config OMAP_32K_TIMER_HZ
+ int "Kernel internal timer frequency for 32KHz timer"
+ range 32 1024
+ depends on OMAP_32K_TIMER
+ default "128"
+ help
+ Kernel internal timer frequency should be a divisor of 32768,
+ such as 64 or 128.
+
+choice
prompt "Low-level debug console UART"
depends on ARCH_OMAP
default OMAP_LL_DEBUG_UART1
diff --git a/arch/arm/mach-omap/Makefile b/arch/arm/mach-omap/Makefile
index 2a6c49542667b..4cafb11d2c02f 100644
--- a/arch/arm/mach-omap/Makefile
+++ b/arch/arm/mach-omap/Makefile
@@ -16,6 +16,8 @@ obj-$(CONFIG_MACH_OMAP_GENERIC) += board-generic.o
obj-$(CONFIG_MACH_OMAP_PERSEUS2) += board-perseus2.o
obj-$(CONFIG_MACH_OMAP_OSK) += board-osk.o
obj-$(CONFIG_MACH_OMAP_H3) += board-h3.o
+obj-$(CONFIG_MACH_VOICEBLUE) += board-voiceblue.o
+obj-$(CONFIG_MACH_NETSTAR) += board-netstar.o
# OCPI interconnect support for 1710, 1610 and 5912
obj-$(CONFIG_ARCH_OMAP16XX) += ocpi.o
diff --git a/arch/arm/mach-omap/board-generic.c b/arch/arm/mach-omap/board-generic.c
index 586bc127111dc..2102a2cd10135 100644
--- a/arch/arm/mach-omap/board-generic.c
+++ b/arch/arm/mach-omap/board-generic.c
@@ -26,7 +26,6 @@
#include <asm/arch/mux.h>
#include <asm/arch/usb.h>
#include <asm/arch/board.h>
-#include <asm/arch/serial.h>
#include "common.h"
diff --git a/arch/arm/mach-omap/board-h2.c b/arch/arm/mach-omap/board-h2.c
index c767d081030e9..1f067830d1fcd 100644
--- a/arch/arm/mach-omap/board-h2.c
+++ b/arch/arm/mach-omap/board-h2.c
@@ -23,14 +23,17 @@
#include <linux/init.h>
#include <linux/device.h>
#include <linux/delay.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
#include <asm/hardware.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
#include <asm/mach/map.h>
-#include <asm/arch/clocks.h>
#include <asm/arch/gpio.h>
+#include <asm/arch/tc.h>
#include <asm/arch/usb.h>
#include "common.h"
@@ -39,10 +42,64 @@ extern int omap_gpio_init(void);
static int __initdata h2_serial_ports[OMAP_MAX_NR_PORTS] = {1, 1, 1};
+static struct mtd_partition h2_partitions[] = {
+ /* bootloader (U-Boot, etc) in first sector */
+ {
+ .name = "bootloader",
+ .offset = 0,
+ .size = SZ_128K,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+ /* bootloader params in the next sector */
+ {
+ .name = "params",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_128K,
+ .mask_flags = 0,
+ },
+ /* kernel */
+ {
+ .name = "kernel",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_2M,
+ .mask_flags = 0
+ },
+ /* file system */
+ {
+ .name = "filesystem",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,
+ .mask_flags = 0
+ }
+};
+
+static struct flash_platform_data h2_flash_data = {
+ .map_name = "cfi_probe",
+ .width = 2,
+ .parts = h2_partitions,
+ .nr_parts = ARRAY_SIZE(h2_partitions),
+};
+
+static struct resource h2_flash_resource = {
+ .start = OMAP_CS2B_PHYS,
+ .end = OMAP_CS2B_PHYS + OMAP_CS2B_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device h2_flash_device = {
+ .name = "omapflash",
+ .id = 0,
+ .dev = {
+ .platform_data = &h2_flash_data,
+ },
+ .num_resources = 1,
+ .resource = &h2_flash_resource,
+};
+
static struct resource h2_smc91x_resources[] = {
[0] = {
.start = OMAP1610_ETHR_START, /* Physical */
- .end = OMAP1610_ETHR_START + SZ_4K,
+ .end = OMAP1610_ETHR_START + 0xf,
.flags = IORESOURCE_MEM,
},
[1] = {
@@ -60,6 +117,7 @@ static struct platform_device h2_smc91x_device = {
};
static struct platform_device *h2_devices[] __initdata = {
+ &h2_flash_device,
&h2_smc91x_device,
};
diff --git a/arch/arm/mach-omap/board-h3.c b/arch/arm/mach-omap/board-h3.c
index fd1d936266985..486a5a006c9a2 100644
--- a/arch/arm/mach-omap/board-h3.c
+++ b/arch/arm/mach-omap/board-h3.c
@@ -21,16 +21,22 @@
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/errno.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
#include <asm/setup.h>
#include <asm/page.h>
#include <asm/hardware.h>
+#include <asm/mach-types.h>
#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
#include <asm/mach/map.h>
+
+#include <asm/arch/gpio.h>
#include <asm/arch/irqs.h>
#include <asm/arch/mux.h>
-#include <asm/arch/gpio.h>
-#include <asm/mach-types.h>
+#include <asm/arch/tc.h>
+#include <asm/arch/usb.h>
#include "common.h"
@@ -38,10 +44,64 @@ extern int omap_gpio_init(void);
static int __initdata h3_serial_ports[OMAP_MAX_NR_PORTS] = {1, 1, 1};
+static struct mtd_partition h3_partitions[] = {
+ /* bootloader (U-Boot, etc) in first sector */
+ {
+ .name = "bootloader",
+ .offset = 0,
+ .size = SZ_128K,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+ /* bootloader params in the next sector */
+ {
+ .name = "params",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_128K,
+ .mask_flags = 0,
+ },
+ /* kernel */
+ {
+ .name = "kernel",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_2M,
+ .mask_flags = 0
+ },
+ /* file system */
+ {
+ .name = "filesystem",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,
+ .mask_flags = 0
+ }
+};
+
+static struct flash_platform_data h3_flash_data = {
+ .map_name = "cfi_probe",
+ .width = 2,
+ .parts = h3_partitions,
+ .nr_parts = ARRAY_SIZE(h3_partitions),
+};
+
+static struct resource h3_flash_resource = {
+ .start = OMAP_CS2B_PHYS,
+ .end = OMAP_CS2B_PHYS + OMAP_CS2B_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device flash_device = {
+ .name = "omapflash",
+ .id = 0,
+ .dev = {
+ .platform_data = &h3_flash_data,
+ },
+ .num_resources = 1,
+ .resource = &h3_flash_resource,
+};
+
static struct resource smc91x_resources[] = {
[0] = {
.start = OMAP1710_ETHR_START, /* Physical */
- .end = OMAP1710_ETHR_START + OMAP1710_ETHR_SIZE,
+ .end = OMAP1710_ETHR_START + 0xf,
.flags = IORESOURCE_MEM,
},
[1] = {
@@ -58,8 +118,52 @@ static struct platform_device smc91x_device = {
.resource = smc91x_resources,
};
+#define GPTIMER_BASE 0xFFFB1400
+#define GPTIMER_REGS(x) (0xFFFB1400 + (x * 0x800))
+#define GPTIMER_REGS_SIZE 0x46
+
+static struct resource intlat_resources[] = {
+ [0] = {
+ .start = GPTIMER_REGS(0), /* Physical */
+ .end = GPTIMER_REGS(0) + GPTIMER_REGS_SIZE,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = INT_1610_GPTIMER1,
+ .end = INT_1610_GPTIMER1,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device intlat_device = {
+ .name = "omap_intlat",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(intlat_resources),
+ .resource = intlat_resources,
+};
+
static struct platform_device *devices[] __initdata = {
+ &flash_device,
&smc91x_device,
+ &intlat_device,
+};
+
+static struct omap_usb_config h3_usb_config __initdata = {
+ /* usb1 has a Mini-AB port and external isp1301 transceiver */
+ .otg = 2,
+
+#ifdef CONFIG_USB_GADGET_OMAP
+ .hmc_mode = 19, /* 0:host(off) 1:dev|otg 2:disabled */
+#elif defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
+ /* NONSTANDARD CABLE NEEDED (B-to-Mini-B) */
+ .hmc_mode = 20, /* 1:dev|otg(off) 1:host 2:disabled */
+#endif
+
+ .pins[1] = 3,
+};
+
+static struct omap_board_config_kernel h3_config[] = {
+ { OMAP_TAG_USB, &h3_usb_config },
};
static void __init h3_init(void)
diff --git a/arch/arm/mach-omap/board-innovator.c b/arch/arm/mach-omap/board-innovator.c
index dfc67021e2780..57cf4da88d55b 100644
--- a/arch/arm/mach-omap/board-innovator.c
+++ b/arch/arm/mach-omap/board-innovator.c
@@ -20,21 +20,85 @@
#include <linux/init.h>
#include <linux/device.h>
#include <linux/delay.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
#include <asm/hardware.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
#include <asm/mach/map.h>
-#include <asm/arch/clocks.h>
-#include <asm/arch/gpio.h>
#include <asm/arch/fpga.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/tc.h>
#include <asm/arch/usb.h>
#include "common.h"
static int __initdata innovator_serial_ports[OMAP_MAX_NR_PORTS] = {1, 1, 1};
+static struct mtd_partition innovator_partitions[] = {
+ /* bootloader (U-Boot, etc) in first sector */
+ {
+ .name = "bootloader",
+ .offset = 0,
+ .size = SZ_128K,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+ /* bootloader params in the next sector */
+ {
+ .name = "params",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_128K,
+ .mask_flags = 0,
+ },
+ /* kernel */
+ {
+ .name = "kernel",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_2M,
+ .mask_flags = 0
+ },
+ /* rest of flash1 is a file system */
+ {
+ .name = "rootfs",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_16M - SZ_2M - 2 * SZ_128K,
+ .mask_flags = 0
+ },
+ /* file system */
+ {
+ .name = "filesystem",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,
+ .mask_flags = 0
+ }
+};
+
+static struct flash_platform_data innovator_flash_data = {
+ .map_name = "cfi_probe",
+ .width = 2,
+ .parts = innovator_partitions,
+ .nr_parts = ARRAY_SIZE(innovator_partitions),
+};
+
+static struct resource innovator_flash_resource = {
+ .start = OMAP_CS0_PHYS,
+ .end = OMAP_CS0_PHYS + SZ_32M - 1,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device innovator_flash_device = {
+ .name = "omapflash",
+ .id = 0,
+ .dev = {
+ .platform_data = &innovator_flash_data,
+ },
+ .num_resources = 1,
+ .resource = &innovator_flash_resource,
+};
+
#ifdef CONFIG_ARCH_OMAP1510
/* Only FPGA needs to be mapped here. All others are done with ioremap */
@@ -46,7 +110,7 @@ static struct map_desc innovator1510_io_desc[] __initdata = {
static struct resource innovator1510_smc91x_resources[] = {
[0] = {
.start = OMAP1510_FPGA_ETHR_START, /* Physical */
- .end = OMAP1510_FPGA_ETHR_START + 16,
+ .end = OMAP1510_FPGA_ETHR_START + 0xf,
.flags = IORESOURCE_MEM,
},
[1] = {
@@ -64,6 +128,7 @@ static struct platform_device innovator1510_smc91x_device = {
};
static struct platform_device *innovator1510_devices[] __initdata = {
+ &innovator_flash_device,
&innovator1510_smc91x_device,
};
@@ -74,7 +139,7 @@ static struct platform_device *innovator1510_devices[] __initdata = {
static struct resource innovator1610_smc91x_resources[] = {
[0] = {
.start = INNOVATOR1610_ETHR_START, /* Physical */
- .end = INNOVATOR1610_ETHR_START + SZ_4K,
+ .end = INNOVATOR1610_ETHR_START + 0xf,
.flags = IORESOURCE_MEM,
},
[1] = {
@@ -92,6 +157,7 @@ static struct platform_device innovator1610_smc91x_device = {
};
static struct platform_device *innovator1610_devices[] __initdata = {
+ &innovator_flash_device,
&innovator1610_smc91x_device,
};
diff --git a/arch/arm/mach-omap/board-netstar.c b/arch/arm/mach-omap/board-netstar.c
new file mode 100644
index 0000000000000..54acbd215c4bd
--- /dev/null
+++ b/arch/arm/mach-omap/board-netstar.c
@@ -0,0 +1,151 @@
+/*
+ * Modified from board-generic.c
+ *
+ * Copyright (C) 2004 2N Telekomunikace, Ladislav Michl <michl@2n.cz>
+ *
+ * Code for Netstar OMAP board.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <asm/arch/gpio.h>
+#include <asm/arch/mux.h>
+#include <asm/arch/usb.h>
+
+#include "common.h"
+
+extern void __init omap_init_time(void);
+extern int omap_gpio_init(void);
+
+static struct resource netstar_smc91x_resources[] = {
+ [0] = {
+ .start = OMAP_CS1_PHYS + 0x300,
+ .end = OMAP_CS1_PHYS + 0x300 + 16,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = OMAP_GPIO_IRQ(8),
+ .end = OMAP_GPIO_IRQ(8),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device netstar_smc91x_device = {
+ .name = "smc91x",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(netstar_smc91x_resources),
+ .resource = netstar_smc91x_resources,
+};
+
+static struct platform_device *netstar_devices[] __initdata = {
+ &netstar_smc91x_device,
+};
+
+static void __init netstar_init_irq(void)
+{
+ omap_init_irq();
+ omap_gpio_init();
+}
+
+static void __init netstar_init(void)
+{
+ /* green LED */
+ omap_request_gpio(4);
+ omap_set_gpio_direction(4, 0);
+ /* smc91x reset */
+ omap_request_gpio(7);
+ omap_set_gpio_direction(7, 0);
+ omap_set_gpio_dataout(7, 1);
+ udelay(2); /* wait at least 100ns */
+ omap_set_gpio_dataout(7, 0);
+ mdelay(50); /* 50ms until PHY ready */
+ /* smc91x interrupt pin */
+ omap_request_gpio(8);
+ omap_set_gpio_edge_ctrl(8, OMAP_GPIO_RISING_EDGE);
+
+ omap_request_gpio(12);
+ omap_request_gpio(13);
+ omap_request_gpio(14);
+ omap_request_gpio(15);
+ omap_set_gpio_edge_ctrl(12, OMAP_GPIO_FALLING_EDGE);
+ omap_set_gpio_edge_ctrl(13, OMAP_GPIO_FALLING_EDGE);
+ omap_set_gpio_edge_ctrl(14, OMAP_GPIO_FALLING_EDGE);
+ omap_set_gpio_edge_ctrl(15, OMAP_GPIO_FALLING_EDGE);
+
+ platform_add_devices(netstar_devices, ARRAY_SIZE(netstar_devices));
+
+ /* Switch on green LED */
+ omap_set_gpio_dataout(4, 0);
+ /* Switch off red LED */
+ omap_writeb(0x00, OMAP_LPG1_PMR); /* Disable clock */
+ omap_writeb(0x80, OMAP_LPG1_LCR);
+}
+
+static int __initdata omap_serial_ports[OMAP_MAX_NR_PORTS] = {1, 1, 1};
+
+static void __init netstar_map_io(void)
+{
+ omap_map_io();
+ omap_serial_init(omap_serial_ports);
+}
+
+#define MACHINE_PANICED 1
+#define MACHINE_REBOOTING 2
+#define MACHINE_REBOOT 4
+static unsigned long machine_state;
+
+static int panic_event(struct notifier_block *this, unsigned long event,
+ void *ptr)
+{
+ if (test_and_set_bit(MACHINE_PANICED, &machine_state))
+ return NOTIFY_DONE;
+
+ /* Switch off green LED */
+ omap_set_gpio_dataout(4, 1);
+ /* Flash red LED */
+ omap_writeb(0x78, OMAP_LPG1_LCR);
+ omap_writeb(0x01, OMAP_LPG1_PMR); /* Enable clock */
+
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block panic_block = {
+ .notifier_call = panic_event,
+};
+
+static int __init netstar_late_init(void)
+{
+ /* TODO: Setup front panel switch here */
+
+ /* Setup panic notifier */
+ notifier_chain_register(&panic_notifier_list, &panic_block);
+
+ return 0;
+}
+
+postcore_initcall(netstar_late_init);
+
+MACHINE_START(NETSTAR, "NetStar OMAP5910")
+ MAINTAINER("Ladislav Michl <michl@2n.cz>")
+ BOOT_MEM(0x10000000, 0xfff00000, 0xfef00000)
+ BOOT_PARAMS(0x10000100)
+ MAPIO(netstar_map_io)
+ INITIRQ(netstar_init_irq)
+ INIT_MACHINE(netstar_init)
+ .timer = &omap_timer,
+MACHINE_END
diff --git a/arch/arm/mach-omap/board-osk.c b/arch/arm/mach-omap/board-osk.c
index 51c616812c795..a951fc82459b3 100644
--- a/arch/arm/mach-omap/board-osk.c
+++ b/arch/arm/mach-omap/board-osk.c
@@ -35,10 +35,10 @@
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
-#include <asm/arch/clocks.h>
#include <asm/arch/gpio.h>
-#include <asm/arch/fpga.h>
#include <asm/arch/usb.h>
+#include <asm/arch/mux.h>
+#include <asm/arch/tc.h>
#include "common.h"
@@ -52,7 +52,7 @@ static int __initdata osk_serial_ports[OMAP_MAX_NR_PORTS] = {1, 0, 0};
static struct resource osk5912_smc91x_resources[] = {
[0] = {
.start = OMAP_OSK_ETHR_START, /* Physical */
- .end = OMAP_OSK_ETHR_START + SZ_4K,
+ .end = OMAP_OSK_ETHR_START + 0xf,
.flags = IORESOURCE_MEM,
},
[1] = {
@@ -64,13 +64,32 @@ static struct resource osk5912_smc91x_resources[] = {
static struct platform_device osk5912_smc91x_device = {
.name = "smc91x",
- .id = 0,
+ .id = -1,
.num_resources = ARRAY_SIZE(osk5912_smc91x_resources),
.resource = osk5912_smc91x_resources,
};
+static struct resource osk5912_cf_resources[] = {
+ [0] = {
+ .start = OMAP_GPIO_IRQ(62),
+ .end = OMAP_GPIO_IRQ(62),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device osk5912_cf_device = {
+ .name = "omap_cf",
+ .id = -1,
+ .dev = {
+ .platform_data = (void *) 2 /* CS2 */,
+ },
+ .num_resources = ARRAY_SIZE(osk5912_cf_resources),
+ .resource = osk5912_cf_resources,
+};
+
static struct platform_device *osk5912_devices[] __initdata = {
&osk5912_smc91x_device,
+ &osk5912_cf_device,
};
static void __init osk_init_smc91x(void)
@@ -80,6 +99,20 @@ static void __init osk_init_smc91x(void)
return;
}
omap_set_gpio_edge_ctrl(0, OMAP_GPIO_RISING_EDGE);
+
+ /* Check EMIFS wait states to fix errors with SMC_GET_PKT_HDR */
+ EMIFS_CCS(1) |= 0x2;
+}
+
+static void __init osk_init_cf(void)
+{
+ omap_cfg_reg(M7_1610_GPIO62);
+ if ((omap_request_gpio(62)) < 0) {
+ printk("Error requesting gpio 62 for CF irq\n");
+ return;
+ }
+ /* it's really active-low */
+ omap_set_gpio_edge_ctrl(62, OMAP_GPIO_FALLING_EDGE);
}
void osk_init_irq(void)
@@ -87,12 +120,22 @@ void osk_init_irq(void)
omap_init_irq();
omap_gpio_init();
osk_init_smc91x();
+ osk_init_cf();
}
static struct omap_usb_config osk_usb_config __initdata = {
- /* has usb host and device, but no Mini-AB port */
+ /* has usb host connector (A) ... for development it can also
+ * be used, with a NONSTANDARD gender-bending cable/dongle, as
+ * a peripheral.
+ */
+#ifdef CONFIG_USB_GADGET_OMAP
+ .register_dev = 1,
+ .hmc_mode = 0,
+#else
.register_host = 1,
.hmc_mode = 16,
+ .rwc = 1,
+#endif
.pins[0] = 2,
};
@@ -102,9 +145,10 @@ static struct omap_board_config_kernel osk_config[] = {
static void __init osk_init(void)
{
- platform_add_devices(osk5912_devices, ARRAY_SIZE(osk5912_devices));
+ platform_add_devices(osk5912_devices, ARRAY_SIZE(osk5912_devices));
omap_board_config = osk_config;
omap_board_config_size = ARRAY_SIZE(osk_config);
+ USB_TRANSCEIVER_CTRL_REG |= (3 << 1);
}
static void __init osk_map_io(void)
diff --git a/arch/arm/mach-omap/board-perseus2.c b/arch/arm/mach-omap/board-perseus2.c
index 4a5e54ca58460..64515aeb49cf3 100644
--- a/arch/arm/mach-omap/board-perseus2.c
+++ b/arch/arm/mach-omap/board-perseus2.c
@@ -15,24 +15,25 @@
#include <linux/init.h>
#include <linux/device.h>
#include <linux/delay.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
#include <asm/hardware.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
#include <asm/mach/map.h>
-#include <asm/arch/clocks.h>
#include <asm/arch/gpio.h>
#include <asm/arch/mux.h>
#include <asm/arch/fpga.h>
-#include <asm/arch/serial.h>
#include "common.h"
static struct resource smc91x_resources[] = {
[0] = {
.start = H2P2_DBG_FPGA_ETHR_START, /* Physical */
- .end = H2P2_DBG_FPGA_ETHR_START + SZ_4K,
+ .end = H2P2_DBG_FPGA_ETHR_START + 0xf,
.flags = IORESOURCE_MEM,
},
[1] = {
@@ -44,6 +45,60 @@ static struct resource smc91x_resources[] = {
static int __initdata p2_serial_ports[OMAP_MAX_NR_PORTS] = {1, 1, 0};
+static struct mtd_partition p2_partitions[] = {
+ /* bootloader (U-Boot, etc) in first sector */
+ {
+ .name = "bootloader",
+ .offset = 0,
+ .size = SZ_128K,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+ /* bootloader params in the next sector */
+ {
+ .name = "params",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_128K,
+ .mask_flags = 0,
+ },
+ /* kernel */
+ {
+ .name = "kernel",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_2M,
+ .mask_flags = 0
+ },
+ /* rest of flash is a file system */
+ {
+ .name = "rootfs",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,
+ .mask_flags = 0
+ },
+};
+
+static struct flash_platform_data p2_flash_data = {
+ .map_name = "cfi_probe",
+ .width = 2,
+ .parts = p2_partitions,
+ .nr_parts = ARRAY_SIZE(p2_partitions),
+};
+
+static struct resource p2_flash_resource = {
+ .start = OMAP_FLASH_0_START,
+ .end = OMAP_FLASH_0_START + OMAP_FLASH_0_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device p2_flash_device = {
+ .name = "omapflash",
+ .id = 0,
+ .dev = {
+ .platform_data = &p2_flash_data,
+ },
+ .num_resources = 1,
+ .resource = &p2_flash_resource,
+};
+
static struct platform_device smc91x_device = {
.name = "smc91x",
.id = 0,
@@ -52,6 +107,7 @@ static struct platform_device smc91x_device = {
};
static struct platform_device *devices[] __initdata = {
+ &p2_flash_device,
&smc91x_device,
};
diff --git a/arch/arm/mach-omap/board-voiceblue.c b/arch/arm/mach-omap/board-voiceblue.c
new file mode 100644
index 0000000000000..f1a5bffac6668
--- /dev/null
+++ b/arch/arm/mach-omap/board-voiceblue.c
@@ -0,0 +1,256 @@
+/*
+ * linux/arch/arm/mach-omap/board-voiceblue.c
+ *
+ * Modified from board-generic.c
+ *
+ * Copyright (C) 2004 2N Telekomunikace, Ladislav Michl <michl@2n.cz>
+ *
+ * Code for OMAP5910 based VoiceBlue board (VoIP to GSM gateway).
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/serial_8250.h>
+#include <linux/serial_reg.h>
+
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <asm/arch/gpio.h>
+#include <asm/arch/tc.h>
+#include <asm/arch/mux.h>
+#include <asm/arch/usb.h>
+
+#include "common.h"
+
+extern void omap_init_time(void);
+extern int omap_gpio_init(void);
+
+static struct plat_serial8250_port voiceblue_ports[] = {
+ {
+ .mapbase = (unsigned long)(OMAP_CS1_PHYS + 0x40000),
+ .irq = OMAP_GPIO_IRQ(12),
+ .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP,
+ .iotype = UPIO_MEM,
+ .regshift = 1,
+ .uartclk = 3686400,
+ },
+ {
+ .mapbase = (unsigned long)(OMAP_CS1_PHYS + 0x50000),
+ .irq = OMAP_GPIO_IRQ(13),
+ .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP,
+ .iotype = UPIO_MEM,
+ .regshift = 1,
+ .uartclk = 3686400,
+ },
+ {
+ .mapbase = (unsigned long)(OMAP_CS1_PHYS + 0x60000),
+ .irq = OMAP_GPIO_IRQ(14),
+ .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP,
+ .iotype = UPIO_MEM,
+ .regshift = 1,
+ .uartclk = 3686400,
+ },
+ {
+ .mapbase = (unsigned long)(OMAP_CS1_PHYS + 0x70000),
+ .irq = OMAP_GPIO_IRQ(15),
+ .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP,
+ .iotype = UPIO_MEM,
+ .regshift = 1,
+ .uartclk = 3686400,
+ },
+ { },
+};
+
+static struct platform_device serial_device = {
+ .name = "serial8250",
+ .id = 1,
+ .dev = {
+ .platform_data = voiceblue_ports,
+ },
+};
+
+static int __init ext_uart_init(void)
+{
+ return platform_device_register(&serial_device);
+}
+arch_initcall(ext_uart_init);
+
+static struct resource voiceblue_smc91x_resources[] = {
+ [0] = {
+ .start = OMAP_CS2_PHYS + 0x300,
+ .end = OMAP_CS2_PHYS + 0x300 + 16,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = OMAP_GPIO_IRQ(8),
+ .end = OMAP_GPIO_IRQ(8),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device voiceblue_smc91x_device = {
+ .name = "smc91x",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(voiceblue_smc91x_resources),
+ .resource = voiceblue_smc91x_resources,
+};
+
+static struct platform_device *voiceblue_devices[] __initdata = {
+ &voiceblue_smc91x_device,
+};
+
+static struct omap_usb_config voiceblue_usb_config __initdata = {
+ .hmc_mode = 3,
+ .register_host = 1,
+ .register_dev = 1,
+ .pins[0] = 2,
+ .pins[1] = 6,
+ .pins[2] = 6,
+};
+
+static struct omap_board_config_kernel voiceblue_config[] = {
+ { OMAP_TAG_USB, &voiceblue_usb_config },
+};
+
+static void __init voiceblue_init_irq(void)
+{
+ omap_init_irq();
+ omap_gpio_init();
+}
+
+static void __init voiceblue_init(void)
+{
+ /* There is a good chance board is going up, so enable Power LED
+ * (it is connected through invertor) */
+ omap_writeb(0x00, OMAP_LPG1_LCR);
+ /* Watchdog */
+ omap_request_gpio(0);
+ /* smc91x reset */
+ omap_request_gpio(7);
+ omap_set_gpio_direction(7, 0);
+ omap_set_gpio_dataout(7, 1);
+ udelay(2); /* wait at least 100ns */
+ omap_set_gpio_dataout(7, 0);
+ mdelay(50); /* 50ms until PHY ready */
+ /* smc91x interrupt pin */
+ omap_request_gpio(8);
+ omap_set_gpio_edge_ctrl(8, OMAP_GPIO_RISING_EDGE);
+ /* 16C554 reset*/
+ omap_request_gpio(6);
+ omap_set_gpio_direction(6, 0);
+ omap_set_gpio_dataout(6, 0);
+ /* 16C554 interrupt pins */
+ omap_request_gpio(12);
+ omap_request_gpio(13);
+ omap_request_gpio(14);
+ omap_request_gpio(15);
+ omap_set_gpio_edge_ctrl(12, OMAP_GPIO_RISING_EDGE);
+ omap_set_gpio_edge_ctrl(13, OMAP_GPIO_RISING_EDGE);
+ omap_set_gpio_edge_ctrl(14, OMAP_GPIO_RISING_EDGE);
+ omap_set_gpio_edge_ctrl(15, OMAP_GPIO_RISING_EDGE);
+
+ platform_add_devices(voiceblue_devices, ARRAY_SIZE(voiceblue_devices));
+ omap_board_config = voiceblue_config;
+ omap_board_config_size = ARRAY_SIZE(voiceblue_config);
+}
+
+static int __initdata omap_serial_ports[OMAP_MAX_NR_PORTS] = {1, 1, 1};
+
+static void __init voiceblue_map_io(void)
+{
+ omap_map_io();
+ omap_serial_init(omap_serial_ports);
+}
+
+#define MACHINE_PANICED 1
+#define MACHINE_REBOOTING 2
+#define MACHINE_REBOOT 4
+static unsigned long machine_state;
+
+static int panic_event(struct notifier_block *this, unsigned long event,
+ void *ptr)
+{
+ if (test_and_set_bit(MACHINE_PANICED, &machine_state))
+ return NOTIFY_DONE;
+
+ /* Flash Power LED
+ * (TODO: Enable clock right way (enabled in bootloader already)) */
+ omap_writeb(0x78, OMAP_LPG1_LCR);
+
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block panic_block = {
+ .notifier_call = panic_event,
+};
+
+static int __init setup_notifier(void)
+{
+ /* Setup panic notifier */
+ notifier_chain_register(&panic_notifier_list, &panic_block);
+
+ return 0;
+}
+
+postcore_initcall(setup_notifier);
+
+static int wdt_gpio_state;
+
+void voiceblue_wdt_enable(void)
+{
+ omap_set_gpio_direction(0, 0);
+ omap_set_gpio_dataout(0, 0);
+ omap_set_gpio_dataout(0, 1);
+ omap_set_gpio_dataout(0, 0);
+ wdt_gpio_state = 0;
+}
+
+void voiceblue_wdt_disable(void)
+{
+ omap_set_gpio_dataout(0, 0);
+ omap_set_gpio_dataout(0, 1);
+ omap_set_gpio_dataout(0, 0);
+ omap_set_gpio_direction(0, 1);
+}
+
+void voiceblue_wdt_ping(void)
+{
+ if (test_bit(MACHINE_REBOOT, &machine_state))
+ return;
+
+ wdt_gpio_state = !wdt_gpio_state;
+ omap_set_gpio_dataout(0, wdt_gpio_state);
+}
+
+void voiceblue_reset(void)
+{
+ set_bit(MACHINE_REBOOT, &machine_state);
+ voiceblue_wdt_enable();
+ while (1) ;
+}
+
+EXPORT_SYMBOL(voiceblue_wdt_enable);
+EXPORT_SYMBOL(voiceblue_wdt_disable);
+EXPORT_SYMBOL(voiceblue_wdt_ping);
+
+MACHINE_START(VOICEBLUE, "VoiceBlue OMAP5910")
+ MAINTAINER("Ladislav Michl <michl@2n.cz>")
+ BOOT_MEM(0x10000000, 0xfff00000, 0xfef00000)
+ BOOT_PARAMS(0x10000100)
+ MAPIO(voiceblue_map_io)
+ INITIRQ(voiceblue_init_irq)
+ INIT_MACHINE(voiceblue_init)
+ .timer = &omap_timer,
+MACHINE_END
diff --git a/arch/arm/mach-omap/clock.c b/arch/arm/mach-omap/clock.c
index be4cc1ffec3b0..e91186b5341a3 100644
--- a/arch/arm/mach-omap/clock.c
+++ b/arch/arm/mach-omap/clock.c
@@ -17,6 +17,7 @@
#include <asm/semaphore.h>
#include <asm/hardware/clock.h>
#include <asm/arch/board.h>
+#include <asm/arch/usb.h>
#include "clock.h"
@@ -24,34 +25,41 @@ static LIST_HEAD(clocks);
static DECLARE_MUTEX(clocks_sem);
static DEFINE_SPINLOCK(clockfw_lock);
static void propagate_rate(struct clk * clk);
+/* External clock (MCLK & BCLK) functions */
+static int set_ext_clk_rate(struct clk * clk, unsigned long rate);
+static long round_ext_clk_rate(struct clk * clk, unsigned long rate);
+static void init_ext_clk(struct clk * clk);
/* MPU virtual clock functions */
-static int select_table_rate(unsigned long rate);
-static long round_to_table_rate(unsigned long rate);
+static int select_table_rate(struct clk * clk, unsigned long rate);
+static long round_to_table_rate(struct clk * clk, unsigned long rate);
void clk_setdpll(__u16, __u16);
struct mpu_rate rate_table[] = {
/* MPU MHz, xtal MHz, dpll1 MHz, CKCTL, DPLL_CTL
* armdiv, dspdiv, dspmmu, tcdiv, perdiv, lcddiv
*/
-#if defined(CONFIG_OMAP_ARM_216MHZ) && defined(CONFIG_ARCH_OMAP16XX)
+#if defined(CONFIG_OMAP_ARM_216MHZ)
{ 216000000, 12000000, 216000000, 0x050d, 0x2910 }, /* 1/1/2/2/2/8 */
#endif
-#if defined(CONFIG_OMAP_ARM_195MHZ) && defined(CONFIG_ARCH_OMAP730)
+#if defined(CONFIG_OMAP_ARM_195MHZ)
{ 195000000, 13000000, 195000000, 0x050e, 0x2790 }, /* 1/1/2/2/4/8 */
#endif
-#if defined(CONFIG_OMAP_ARM_192MHZ) && defined(CONFIG_ARCH_OMAP16XX)
+#if defined(CONFIG_OMAP_ARM_192MHZ)
{ 192000000, 19200000, 192000000, 0x050f, 0x2510 }, /* 1/1/2/2/8/8 */
{ 192000000, 12000000, 192000000, 0x050f, 0x2810 }, /* 1/1/2/2/8/8 */
{ 96000000, 12000000, 192000000, 0x055f, 0x2810 }, /* 2/2/2/2/8/8 */
{ 48000000, 12000000, 192000000, 0x0ccf, 0x2810 }, /* 4/4/4/4/8/8 */
{ 24000000, 12000000, 192000000, 0x0fff, 0x2810 }, /* 8/8/8/8/8/8 */
#endif
-#if defined(CONFIG_OMAP_ARM_182MHZ) && defined(CONFIG_ARCH_OMAP730)
+#if defined(CONFIG_OMAP_ARM_182MHZ)
{ 182000000, 13000000, 182000000, 0x050e, 0x2710 }, /* 1/1/2/2/4/8 */
#endif
#if defined(CONFIG_OMAP_ARM_168MHZ)
{ 168000000, 12000000, 168000000, 0x010f, 0x2710 }, /* 1/1/1/2/8/8 */
#endif
+#if defined(CONFIG_OMAP_ARM_150MHZ)
+ { 150000000, 12000000, 150000000, 0x150a, 0x2cb0 }, /* 0/0/1/1/2/2 */
+#endif
#if defined(CONFIG_OMAP_ARM_120MHZ)
{ 120000000, 12000000, 120000000, 0x010a, 0x2510 }, /* 1/1/1/2/4/4 */
#endif
@@ -174,12 +182,12 @@ static struct clk armwdt_ck = {
.recalc = &watchdog_recalc,
};
-static struct clk arminth_ck1610 = {
+static struct clk arminth_ck16xx = {
.name = "arminth_ck",
.parent = &arm_ck,
.flags = CLOCK_IN_OMAP16XX,
.recalc = &followparent_recalc,
- /* Note: On 1610/1710 frequency can be divided by 2 by programming
+ /* Note: On 16xx the frequency can be divided by 2 by programming
* ARM_CKCTL:ARM_INTHCK_SEL(14) to 1
*
* 1510 version is in TC clocks.
@@ -209,7 +217,7 @@ static struct clk dspmmu_ck = {
static struct clk tc_ck = {
.name = "tc_ck",
.parent = &ck_dpll1,
- .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
+ .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP730 |
RATE_CKCTL | RATE_PROPAGATES | ALWAYS_ENABLED,
.rate_offset = CKCTL_TCDIV_OFFSET,
.recalc = &ckctl_recalc,
@@ -220,9 +228,9 @@ static struct clk arminth_ck1510 = {
.parent = &tc_ck,
.flags = CLOCK_IN_OMAP1510,
.recalc = &followparent_recalc,
- /* Note: On 1510 frequency follows TC_CK
+ /* Note: On 1510 the frequency follows TC_CK
*
- * 1610/1710 version is in MPU clocks.
+ * 16xx version is in MPU clocks.
*/
};
@@ -309,7 +317,7 @@ static struct clk rhea2_ck = {
static struct clk lcd_ck = {
.name = "lcd_ck",
.parent = &ck_dpll1,
- .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
+ .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | CLOCK_IN_OMAP730 |
RATE_CKCTL,
.enable_reg = ARM_IDLECT2,
.enable_bit = EN_LCDCK,
@@ -338,7 +346,7 @@ static struct clk uart2_ck = {
RATE_FIXED | ENABLE_REG_32BIT,
.enable_reg = MOD_CONF_CTRL_0,
.enable_bit = 30,
- /* (1510/1610/1710)
+ /* (for both 1510 and 16xx)
* The "enable bit" actually chooses between 48MHz and 12MHz/32kHz.
*/
};
@@ -356,42 +364,72 @@ static struct clk uart3_ck = {
*/
};
-static struct clk usb_ck1610 = {
- .name = "usb_ck",
+static struct clk usb_clko = { /* 6 MHz output on W4_USB_CLKO */
+ .name = "usb_clko",
/* Direct from ULPD, no parent */
- .rate = 48000000,
- .flags = CLOCK_IN_OMAP16XX |
+ .rate = 6000000,
+ .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
RATE_FIXED | ENABLE_REG_32BIT,
.enable_reg = ULPD_CLOCK_CTRL,
- .enable_bit = USB_MCLK_EN,
-};
-
-static struct clk usb_ck1510 = {
- .name = "usb_ck",
- /* Direct from ULPD, no parent */
- .rate = 48000000,
- .flags = CLOCK_IN_OMAP1510 | RATE_FIXED,
+ .enable_bit = USB_MCLK_EN_BIT,
};
-static struct clk usb_hhc_ck = {
+static struct clk usb_hhc_ck1510 = {
.name = "usb_hhc_ck",
/* Direct from ULPD, no parent */
.rate = 48000000, /* Actually 2 clocks, 12MHz and 48MHz */
- .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
+ .flags = CLOCK_IN_OMAP1510 |
RATE_FIXED | ENABLE_REG_32BIT,
.enable_reg = MOD_CONF_CTRL_0,
.enable_bit = USB_HOST_HHC_UHOST_EN,
};
-/* To be done --
-static struct clk mclk = {
+static struct clk usb_hhc_ck16xx = {
+ .name = "usb_hhc_ck",
+ /* Direct from ULPD, no parent */
+ .rate = 48000000,
+ /* OTG_SYSCON_2.OTG_PADEN == 0 (not 1510-compatible) */
+ .flags = CLOCK_IN_OMAP16XX |
+ RATE_FIXED | ENABLE_REG_32BIT,
+ .enable_reg = OTG_BASE + 0x08 /* OTG_SYSCON_2 */,
+ .enable_bit = 8 /* UHOST_EN */,
+};
+
+static struct clk mclk_1510 = {
.name = "mclk",
+ /* Direct from ULPD, no parent. May be enabled by ext hardware. */
+ .rate = 12000000,
+ .flags = CLOCK_IN_OMAP1510 | RATE_FIXED,
+};
+
+static struct clk mclk_16xx = {
+ .name = "mclk",
+ /* Direct from ULPD, no parent. May be enabled by ext hardware. */
+ .flags = CLOCK_IN_OMAP16XX,
+ .enable_reg = COM_CLK_DIV_CTRL_SEL,
+ .enable_bit = COM_ULPD_PLL_CLK_REQ,
+ .set_rate = &set_ext_clk_rate,
+ .round_rate = &round_ext_clk_rate,
+ .init = &init_ext_clk,
+};
+
+static struct clk bclk_1510 = {
+ .name = "bclk",
+ /* Direct from ULPD, no parent. May be enabled by ext hardware. */
+ .rate = 12000000,
+ .flags = CLOCK_IN_OMAP1510 | RATE_FIXED,
};
-static struct clk bclk = {
+static struct clk bclk_16xx = {
.name = "bclk",
+ /* Direct from ULPD, no parent. May be enabled by ext hardware. */
+ .flags = CLOCK_IN_OMAP16XX,
+ .enable_reg = SWD_CLK_DIV_CTRL_SEL,
+ .enable_bit = SWD_ULPD_PLL_CLK_REQ,
+ .set_rate = &set_ext_clk_rate,
+ .round_rate = &round_ext_clk_rate,
+ .init = &init_ext_clk,
};
--- to be done */
static struct clk mmc1_ck = {
.name = "mmc1_ck",
@@ -438,8 +476,7 @@ static struct clk * onchip_clks[] = {
&armxor_ck,
&armtim_ck,
&armwdt_ck,
- &arminth_ck1510,
- &arminth_ck1610,
+ &arminth_ck1510, &arminth_ck16xx,
/* CK_GEN2 clocks */
&dsp_ck,
&dspmmu_ck,
@@ -460,13 +497,10 @@ static struct clk * onchip_clks[] = {
&uart1_ck,
&uart2_ck,
&uart3_ck,
- &usb_ck1510,
- &usb_ck1610,
- &usb_hhc_ck,
- /* To be done --
- &mclk,
- &bclk,
- -- to be done */
+ &usb_clko,
+ &usb_hhc_ck1510, &usb_hhc_ck16xx,
+ &mclk_1510, &mclk_16xx,
+ &bclk_1510, &bclk_16xx,
&mmc1_ck,
&mmc2_ck,
/* Virtual clocks */
@@ -629,6 +663,13 @@ void clk_unuse(struct clk *clk)
EXPORT_SYMBOL(clk_unuse);
+int clk_get_usecount(struct clk *clk)
+{
+ return clk->usecount;
+}
+EXPORT_SYMBOL(clk_get_usecount);
+
+
unsigned long clk_get_rate(struct clk *clk)
{
return clk->rate;
@@ -742,7 +783,7 @@ long clk_round_rate(struct clk *clk, unsigned long rate)
}
if(clk->round_rate != 0)
- return clk->round_rate(rate);
+ return clk->round_rate(clk, rate);
return clk->rate;
}
@@ -761,11 +802,14 @@ static void propagate_rate(struct clk * clk)
}
-static int select_table_rate(unsigned long rate)
+static int select_table_rate(struct clk * clk, unsigned long rate)
{
/* Find the highest supported frequency <= rate and switch to it */
struct mpu_rate * ptr;
+ if (clk != &virtual_ck_mpu)
+ return -EINVAL;
+
for (ptr = rate_table; ptr->rate; ptr++) {
if (ptr->xtal != ck_ref.rate)
continue;
@@ -792,12 +836,15 @@ static int select_table_rate(unsigned long rate)
}
-static long round_to_table_rate(unsigned long rate)
+static long round_to_table_rate(struct clk * clk, unsigned long rate)
{
/* Find the highest supported frequency <= rate */
struct mpu_rate * ptr;
long highest_rate;
+ if (clk != &virtual_ck_mpu)
+ return -EINVAL;
+
highest_rate = -EINVAL;
for (ptr = rate_table; ptr->rate; ptr++) {
@@ -840,7 +887,7 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
ret = 0;
} else if(clk->set_rate != 0) {
spin_lock_irqsave(&clockfw_lock, flags);
- ret = clk->set_rate(rate);
+ ret = clk->set_rate(clk, rate);
spin_unlock_irqrestore(&clockfw_lock, flags);
}
@@ -852,10 +899,79 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
EXPORT_SYMBOL(clk_set_rate);
+static unsigned calc_ext_dsor(unsigned long rate)
+{
+ unsigned dsor;
+
+ /* MCLK and BCLK divisor selection is not linear:
+ * freq = 96MHz / dsor
+ *
+ * RATIO_SEL range: dsor <-> RATIO_SEL
+ * 0..6: (RATIO_SEL+2) <-> (dsor-2)
+ * 6..48: (8+(RATIO_SEL-6)*2) <-> ((dsor-8)/2+6)
+ * Minimum dsor is 2 and maximum is 96. Odd divisors starting from 9
+ * can not be used.
+ */
+ for (dsor = 2; dsor < 96; ++dsor) {
+ if ((dsor & 1) && dsor > 8)
+ continue;
+ if (rate >= 96000000 / dsor)
+ break;
+ }
+ return dsor;
+}
+
+
+static int set_ext_clk_rate(struct clk * clk, unsigned long rate)
+{
+ unsigned dsor;
+ __u16 ratio_bits;
+
+ dsor = calc_ext_dsor(rate);
+ clk->rate = 96000000 / dsor;
+ if (dsor > 8)
+ ratio_bits = ((dsor - 8) / 2 + 6) << 2;
+ else
+ ratio_bits = (dsor - 2) << 2;
+
+ ratio_bits |= omap_readw(clk->enable_reg) & ~0xfd;
+ omap_writew(ratio_bits, clk->enable_reg);
+
+ return 0;
+}
+
+
+static long round_ext_clk_rate(struct clk * clk, unsigned long rate)
+{
+ return 96000000 / calc_ext_dsor(rate);
+}
+
+
+static void init_ext_clk(struct clk * clk)
+{
+ unsigned dsor;
+ __u16 ratio_bits;
+
+ /* Determine current rate and ensure clock is based on 96MHz APLL */
+ ratio_bits = omap_readw(clk->enable_reg) & ~1;
+ omap_writew(ratio_bits, clk->enable_reg);
+
+ ratio_bits = (ratio_bits & 0xfc) >> 2;
+ if (ratio_bits > 6)
+ dsor = (ratio_bits - 6) * 2 + 8;
+ else
+ dsor = ratio_bits + 2;
+
+ clk-> rate = 96000000 / dsor;
+}
+
+
int clk_register(struct clk *clk)
{
down(&clocks_sem);
list_add(&clk->node, &clocks);
+ if (clk->init)
+ clk->init(clk);
up(&clocks_sem);
return 0;
}
@@ -887,6 +1003,11 @@ int __init clk_init(void)
clk_register(*clkp);
continue;
}
+
+ if (((*clkp)->flags &CLOCK_IN_OMAP730) && cpu_is_omap730()) {
+ clk_register(*clkp);
+ continue;
+ }
}
info = omap_get_config(OMAP_TAG_CLOCK, struct omap_clock_config);
@@ -906,7 +1027,7 @@ int __init clk_init(void)
omap_writew(0x1000, ARM_SYSST);
/* Find the highest supported frequency and enable it */
- if (select_table_rate(~0)) {
+ if (select_table_rate(&virtual_ck_mpu, ~0)) {
printk(KERN_ERR "System frequencies not set. Check your config.\n");
/* Guess sane values (60MHz) */
omap_writew(0x2290, DPLL_CTL);
diff --git a/arch/arm/mach-omap/clock.h b/arch/arm/mach-omap/clock.h
index f3037bc0b96b3..08c0ddde1835b 100644
--- a/arch/arm/mach-omap/clock.h
+++ b/arch/arm/mach-omap/clock.h
@@ -22,13 +22,14 @@ struct clk {
struct clk *parent;
unsigned long rate;
__s8 usecount;
- __u8 flags;
+ __u16 flags;
__u32 enable_reg;
__u8 enable_bit;
__u8 rate_offset;
void (*recalc)(struct clk *);
- int (*set_rate)(unsigned long);
- long (*round_rate)(unsigned long);
+ int (*set_rate)(struct clk *, unsigned long);
+ long (*round_rate)(struct clk *, unsigned long);
+ void (*init)(struct clk *);
};
@@ -50,6 +51,7 @@ struct mpu_rate {
#define ENABLE_REG_32BIT 32
#define CLOCK_IN_OMAP16XX 64
#define CLOCK_IN_OMAP1510 128
+#define CLOCK_IN_OMAP730 256
/* ARM_CKCTL bit shifts */
#define CKCTL_PERDIV_OFFSET 0
@@ -95,8 +97,12 @@ struct mpu_rate {
#define EN_TC2_CK 4
/* Various register defines for clock controls scattered around OMAP chip */
-#define USB_MCLK_EN 4 /* In ULPD_CLKC_CTRL */
+#define USB_MCLK_EN_BIT 4 /* In ULPD_CLKC_CTRL */
#define USB_HOST_HHC_UHOST_EN 9 /* In MOD_CONF_CTRL_0 */
+#define SWD_ULPD_PLL_CLK_REQ 1 /* In SWD_CLK_DIV_CTRL_SEL */
+#define COM_ULPD_PLL_CLK_REQ 1 /* In COM_CLK_DIV_CTRL_SEL */
+#define SWD_CLK_DIV_CTRL_SEL 0xfffe0874
+#define COM_CLK_DIV_CTRL_SEL 0xfffe0878
int clk_register(struct clk *clk);
diff --git a/arch/arm/mach-omap/common.c b/arch/arm/mach-omap/common.c
index 6cc8c21eaa8d7..265cde48586f0 100644
--- a/arch/arm/mach-omap/common.c
+++ b/arch/arm/mach-omap/common.c
@@ -263,9 +263,6 @@ static void __init _omap_map_io(void)
iotable_init(omap_io_desc, ARRAY_SIZE(omap_io_desc));
omap_check_revision();
- /* clear BM to canonicalize CS0 (not CS3) at 0000:0000 */
- omap_writel(omap_readl(EMIFS_CONFIG) & 0x0d, EMIFS_CONFIG);
-
#ifdef CONFIG_ARCH_OMAP730
if (cpu_is_omap730()) {
iotable_init(omap730_io_desc, ARRAY_SIZE(omap730_io_desc));
@@ -436,6 +433,9 @@ void __init omap_serial_init(int ports[OMAP_MAX_NR_PORTS])
omap_cfg_reg(UART3_TX);
omap_cfg_reg(UART3_RX);
}
+ if (cpu_is_omap1710()) {
+ clk_enable(clk_get(0, "uart3_ck"));
+ }
break;
}
omap_serial_reset(&serial_platform_data[i]);
@@ -475,6 +475,12 @@ static const void *get_config(u16 tag, size_t len, int skip, size_t *len_out)
skip--;
}
+ if ((info->len & 0x03) != 0) {
+ /* We bail out to avoid an alignment fault */
+ printk(KERN_ERR "OMAP peripheral config: Length (%d) not word-aligned (tag %04x)\n",
+ info->len, info->tag);
+ return NULL;
+ }
next = (u8 *) info + sizeof(*info) + info->len;
if (next >= omap_bootloader_tag + omap_bootloader_tag_len)
info = NULL;
@@ -484,10 +490,15 @@ static const void *get_config(u16 tag, size_t len, int skip, size_t *len_out)
if (info != NULL) {
/* Check the length as a lame attempt to check for
* binary inconsistancy. */
- if (len != NO_LENGTH_CHECK && info->len != len) {
- printk(KERN_ERR "OMAP peripheral config: Length mismatch with tag %x (want %d, got %d)\n",
- tag, len, info->len);
- return NULL;
+ if (len != NO_LENGTH_CHECK) {
+ /* Word-align len */
+ if (len & 0x03)
+ len = (len + 3) & ~0x03;
+ if (info->len != len) {
+ printk(KERN_ERR "OMAP peripheral config: Length mismatch with tag %x (want %d, got %d)\n",
+ tag, len, info->len);
+ return NULL;
+ }
}
if (len_out != NULL)
*len_out = info->len;
diff --git a/arch/arm/mach-omap/dma.c b/arch/arm/mach-omap/dma.c
index 515aa6a5e4d0c..7a9ebe80d6f8e 100644
--- a/arch/arm/mach-omap/dma.c
+++ b/arch/arm/mach-omap/dma.c
@@ -494,7 +494,7 @@ int omap_request_dma(int dev_id, const char *dev_name,
chan->data = data;
chan->enabled_irqs = OMAP_DMA_TOUT_IRQ | OMAP_DMA_DROP_IRQ | OMAP_DMA_BLOCK_IRQ;
- if (cpu_is_omap16xx() || cpu_is_omap730()) {
+ if (cpu_is_omap16xx()) {
/* If the sync device is set, configure it dynamically. */
if (dev_id != 0) {
set_gdma_dev(free_ch + 1, dev_id);
diff --git a/arch/arm/mach-omap/fpga.c b/arch/arm/mach-omap/fpga.c
index f0ce5c12a2ad9..7c08f6c2e1d0b 100644
--- a/arch/arm/mach-omap/fpga.c
+++ b/arch/arm/mach-omap/fpga.c
@@ -92,26 +92,17 @@ void innovator_fpga_IRQ_demux(unsigned int irq, struct irqdesc *desc,
u32 stat;
int fpga_irq;
- /*
- * Acknowledge the parent IRQ.
- */
- desc->chip->ack(irq);
+ stat = get_fpga_unmasked_irqs();
- for (;;) {
- stat = get_fpga_unmasked_irqs();
-
- if (!stat) {
- break;
- }
+ if (!stat)
+ return;
- for (fpga_irq = OMAP1510_IH_FPGA_BASE;
- (fpga_irq < (OMAP1510_IH_FPGA_BASE + NR_FPGA_IRQS)) && stat;
- fpga_irq++, stat >>= 1) {
- if (stat & 1) {
- d = irq_desc + fpga_irq;
- d->handle(fpga_irq, d, regs);
- desc->chip->unmask(irq);
- }
+ for (fpga_irq = OMAP1510_IH_FPGA_BASE;
+ (fpga_irq < (OMAP1510_IH_FPGA_BASE + NR_FPGA_IRQS)) && stat;
+ fpga_irq++, stat >>= 1) {
+ if (stat & 1) {
+ d = irq_desc + fpga_irq;
+ d->handle(fpga_irq, d, regs);
}
}
}
@@ -177,7 +168,7 @@ void omap1510_fpga_init_irq(void)
set_irq_chip(i, &omap_fpga_irq);
}
- set_irq_handler(i, do_level_IRQ);
+ set_irq_handler(i, do_edge_IRQ);
set_irq_flags(i, IRQF_VALID);
}
diff --git a/arch/arm/mach-omap/gpio.c b/arch/arm/mach-omap/gpio.c
index e66dcf6ffb362..9045dfd469ade 100644
--- a/arch/arm/mach-omap/gpio.c
+++ b/arch/arm/mach-omap/gpio.c
@@ -114,7 +114,7 @@ static struct gpio_bank gpio_bank_1510[2] = {
#ifdef CONFIG_ARCH_OMAP730
static struct gpio_bank gpio_bank_730[7] = {
{ OMAP_MPUIO_BASE, INT_730_MPUIO, IH_MPUIO_BASE, METHOD_MPUIO },
- { OMAP730_GPIO1_BASE, INT_GPIO_BANK1, IH_GPIO_BASE, METHOD_GPIO_730 },
+ { OMAP730_GPIO1_BASE, INT_730_GPIO_BANK1, IH_GPIO_BASE, METHOD_GPIO_730 },
{ OMAP730_GPIO2_BASE, INT_730_GPIO_BANK2, IH_GPIO_BASE + 32, METHOD_GPIO_730 },
{ OMAP730_GPIO3_BASE, INT_730_GPIO_BANK3, IH_GPIO_BASE + 64, METHOD_GPIO_730 },
{ OMAP730_GPIO4_BASE, INT_730_GPIO_BANK4, IH_GPIO_BASE + 96, METHOD_GPIO_730 },
@@ -307,6 +307,9 @@ int omap_get_gpio_datain(int gpio)
case METHOD_GPIO_1610:
reg += OMAP1610_GPIO_DATAIN;
break;
+ case METHOD_GPIO_730:
+ reg += OMAP730_GPIO_DATA_INPUT;
+ break;
default:
BUG();
return -1;
@@ -407,13 +410,13 @@ static int _get_gpio_edge_ctrl(struct gpio_bank *bank, int gpio)
}
}
-static void _clear_gpio_irqstatus(struct gpio_bank *bank, int gpio)
+static void _clear_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
{
u32 reg = bank->base;
switch (bank->method) {
case METHOD_MPUIO:
- /* MPUIO irqstatus cannot be cleared one bit at a time,
+ /* MPUIO irqstatus is reset by reading the status register,
* so do nothing here */
return;
case METHOD_GPIO_1510:
@@ -429,10 +432,15 @@ static void _clear_gpio_irqstatus(struct gpio_bank *bank, int gpio)
BUG();
return;
}
- __raw_writel(1 << get_gpio_index(gpio), reg);
+ __raw_writel(gpio_mask, reg);
+}
+
+static inline void _clear_gpio_irqstatus(struct gpio_bank *bank, int gpio)
+{
+ _clear_gpio_irqbank(bank, 1 << get_gpio_index(gpio));
}
-static void _set_gpio_irqenable(struct gpio_bank *bank, int gpio, int enable)
+static void _enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask, int enable)
{
u32 reg = bank->base;
u32 l;
@@ -442,33 +450,32 @@ static void _set_gpio_irqenable(struct gpio_bank *bank, int gpio, int enable)
reg += OMAP_MPUIO_GPIO_MASKIT;
l = __raw_readl(reg);
if (enable)
- l &= ~(1 << gpio);
+ l &= ~(gpio_mask);
else
- l |= 1 << gpio;
+ l |= gpio_mask;
break;
case METHOD_GPIO_1510:
reg += OMAP1510_GPIO_INT_MASK;
l = __raw_readl(reg);
if (enable)
- l &= ~(1 << gpio);
+ l &= ~(gpio_mask);
else
- l |= 1 << gpio;
+ l |= gpio_mask;
break;
case METHOD_GPIO_1610:
- if (enable) {
+ if (enable)
reg += OMAP1610_GPIO_SET_IRQENABLE1;
- _clear_gpio_irqstatus(bank, gpio);
- } else
+ else
reg += OMAP1610_GPIO_CLEAR_IRQENABLE1;
- l = 1 << gpio;
+ l = gpio_mask;
break;
case METHOD_GPIO_730:
reg += OMAP730_GPIO_INT_MASK;
l = __raw_readl(reg);
if (enable)
- l &= ~(1 << gpio);
+ l &= ~(gpio_mask);
else
- l |= 1 << gpio;
+ l |= gpio_mask;
break;
default:
BUG();
@@ -477,6 +484,11 @@ static void _set_gpio_irqenable(struct gpio_bank *bank, int gpio, int enable)
__raw_writel(l, reg);
}
+static inline void _set_gpio_irqenable(struct gpio_bank *bank, int gpio, int enable)
+{
+ _enable_gpio_irqbank(bank, 1 << get_gpio_index(gpio), enable);
+}
+
int omap_request_gpio(int gpio)
{
struct gpio_bank *bank;
@@ -523,31 +535,31 @@ void omap_free_gpio(int gpio)
}
bank->reserved_map &= ~(1 << get_gpio_index(gpio));
_set_gpio_direction(bank, get_gpio_index(gpio), 1);
- _set_gpio_irqenable(bank, get_gpio_index(gpio), 0);
+ _set_gpio_irqenable(bank, gpio, 0);
+ _clear_gpio_irqstatus(bank, gpio);
spin_unlock(&bank->lock);
}
+/*
+ * We need to unmask the GPIO bank interrupt as soon as possible to
+ * avoid missing GPIO interrupts for other lines in the bank.
+ * Then we need to mask-read-clear-unmask the triggered GPIO lines
+ * in the bank to avoid missing nested interrupts for a GPIO line.
+ * If we wait to unmask individual GPIO lines in the bank after the
+ * line's interrupt handler has been run, we may miss some nested
+ * interrupts.
+ */
static void gpio_irq_handler(unsigned int irq, struct irqdesc *desc,
struct pt_regs *regs)
{
u32 isr_reg = 0;
- struct gpio_bank *bank = (struct gpio_bank *) desc->data;
+ u32 isr;
+ unsigned int gpio_irq;
+ struct gpio_bank *bank;
- /*
- * Acknowledge the parent IRQ.
- */
desc->chip->ack(irq);
- /* Since the level 1 GPIO interrupt cascade (IRQ14) is configured as
- * edge-sensitive, we need to unmask it here in order to avoid missing
- * any additional GPIO interrupts that might occur after the last time
- * we check for pending GPIO interrupts here.
- * We are relying on the fact that this interrupt handler was installed
- * with the SA_INTERRUPT flag so that interrupts are disabled at the
- * CPU while it is executing.
- */
- desc->chip->unmask(irq);
-
+ bank = (struct gpio_bank *) desc->data;
if (bank->method == METHOD_MPUIO)
isr_reg = bank->base + OMAP_MPUIO_GPIO_INT;
#ifdef CONFIG_ARCH_OMAP1510
@@ -562,20 +574,23 @@ static void gpio_irq_handler(unsigned int irq, struct irqdesc *desc,
if (bank->method == METHOD_GPIO_730)
isr_reg = bank->base + OMAP730_GPIO_INT_STATUS;
#endif
- for (;;) {
- u32 isr = __raw_readl(isr_reg);
- unsigned int gpio_irq;
-
- if (!isr)
- break;
- gpio_irq = bank->virtual_irq_start;
-
- for (; isr != 0; isr >>= 1, gpio_irq++) {
- if (isr & 1) {
- struct irqdesc *d = irq_desc + gpio_irq;
- d->handle(gpio_irq, d, regs);
- }
- }
+
+ isr = __raw_readl(isr_reg);
+ _enable_gpio_irqbank(bank, isr, 0);
+ _clear_gpio_irqbank(bank, isr);
+ _enable_gpio_irqbank(bank, isr, 1);
+ desc->chip->unmask(irq);
+
+ if (unlikely(!isr))
+ return;
+
+ gpio_irq = bank->virtual_irq_start;
+ for (; isr != 0; isr >>= 1, gpio_irq++) {
+ struct irqdesc *d;
+ if (!(isr & 1))
+ continue;
+ d = irq_desc + gpio_irq;
+ d->handle(gpio_irq, d, regs);
}
}
@@ -584,18 +599,7 @@ static void gpio_ack_irq(unsigned int irq)
unsigned int gpio = irq - IH_GPIO_BASE;
struct gpio_bank *bank = get_gpio_bank(gpio);
-#ifdef CONFIG_ARCH_OMAP1510
- if (bank->method == METHOD_GPIO_1510)
- __raw_writew(1 << (gpio & 0x0f), bank->base + OMAP1510_GPIO_INT_STATUS);
-#endif
-#if defined(CONFIG_ARCH_OMAP16XX)
- if (bank->method == METHOD_GPIO_1610)
- __raw_writew(1 << (gpio & 0x0f), bank->base + OMAP1610_GPIO_IRQSTATUS1);
-#endif
-#ifdef CONFIG_ARCH_OMAP730
- if (bank->method == METHOD_GPIO_730)
- __raw_writel(1 << (gpio & 0x1f), bank->base + OMAP730_GPIO_INT_STATUS);
-#endif
+ _clear_gpio_irqstatus(bank, gpio);
}
static void gpio_mask_irq(unsigned int irq)
@@ -603,7 +607,7 @@ static void gpio_mask_irq(unsigned int irq)
unsigned int gpio = irq - IH_GPIO_BASE;
struct gpio_bank *bank = get_gpio_bank(gpio);
- _set_gpio_irqenable(bank, get_gpio_index(gpio), 0);
+ _set_gpio_irqenable(bank, gpio, 0);
}
static void gpio_unmask_irq(unsigned int irq)
@@ -616,7 +620,7 @@ static void gpio_unmask_irq(unsigned int irq)
gpio);
_set_gpio_edge_ctrl(bank, get_gpio_index(gpio), OMAP_GPIO_RISING_EDGE);
}
- _set_gpio_irqenable(bank, get_gpio_index(gpio), 1);
+ _set_gpio_irqenable(bank, gpio, 1);
}
static void mpuio_ack_irq(unsigned int irq)
@@ -629,7 +633,7 @@ static void mpuio_mask_irq(unsigned int irq)
unsigned int gpio = OMAP_MPUIO(irq - IH_MPUIO_BASE);
struct gpio_bank *bank = get_gpio_bank(gpio);
- _set_gpio_irqenable(bank, get_gpio_index(gpio), 0);
+ _set_gpio_irqenable(bank, gpio, 0);
}
static void mpuio_unmask_irq(unsigned int irq)
@@ -637,7 +641,7 @@ static void mpuio_unmask_irq(unsigned int irq)
unsigned int gpio = OMAP_MPUIO(irq - IH_MPUIO_BASE);
struct gpio_bank *bank = get_gpio_bank(gpio);
- _set_gpio_irqenable(bank, get_gpio_index(gpio), 1);
+ _set_gpio_irqenable(bank, gpio, 1);
}
static struct irqchip gpio_irq_chip = {
@@ -722,7 +726,7 @@ static int __init _omap_gpio_init(void)
set_irq_chip(j, &mpuio_irq_chip);
else
set_irq_chip(j, &gpio_irq_chip);
- set_irq_handler(j, do_edge_IRQ);
+ set_irq_handler(j, do_simple_IRQ);
set_irq_flags(j, IRQF_VALID);
}
set_irq_chained_handler(bank->irq, gpio_irq_handler);
diff --git a/arch/arm/mach-omap/leds-h2p2-debug.c b/arch/arm/mach-omap/leds-h2p2-debug.c
index 8ff27af0b7c1b..6e98290cca5ca 100644
--- a/arch/arm/mach-omap/leds-h2p2-debug.c
+++ b/arch/arm/mach-omap/leds-h2p2-debug.c
@@ -3,6 +3,11 @@
*
* Copyright 2003 by Texas Instruments Incorporated
*
+ * There are 16 LEDs on the debug board (all green); four may be used
+ * for logical 'green', 'amber', 'red', and 'blue' (after "claiming").
+ *
+ * The "surfer" expansion board and H2 sample board also have two-color
+ * green+red LEDs (in parallel), used here for timer and idle indicators.
*/
#include <linux/config.h>
#include <linux/init.h>
@@ -16,78 +21,111 @@
#include <asm/system.h>
#include <asm/arch/fpga.h>
+#include <asm/arch/gpio.h>
#include "leds.h"
+
+#define GPIO_LED_RED 3
+#define GPIO_LED_GREEN OMAP_MPUIO(4)
+
+
+#define LED_STATE_ENABLED 0x01
+#define LED_STATE_CLAIMED 0x02
+#define LED_TIMER_ON 0x04
+
+#define GPIO_IDLE GPIO_LED_GREEN
+#define GPIO_TIMER GPIO_LED_RED
+
+
void h2p2_dbg_leds_event(led_event_t evt)
{
unsigned long flags;
- static unsigned long hw_led_state = 0;
+
+ static struct h2p2_dbg_fpga __iomem *fpga;
+ static u16 led_state, hw_led_state;
local_irq_save(flags);
+ if (!(led_state & LED_STATE_ENABLED) && evt != led_start)
+ goto done;
+
switch (evt) {
case led_start:
- hw_led_state |= H2P2_DBG_FPGA_LED_STARTSTOP;
+ if (!fpga)
+ fpga = ioremap(H2P2_DBG_FPGA_START,
+ H2P2_DBG_FPGA_SIZE);
+ if (fpga) {
+ led_state |= LED_STATE_ENABLED;
+ __raw_writew(~0, &fpga->leds);
+ }
break;
case led_stop:
- hw_led_state &= ~H2P2_DBG_FPGA_LED_STARTSTOP;
- break;
+ case led_halted:
+ /* all leds off during suspend or shutdown */
+ omap_set_gpio_dataout(GPIO_TIMER, 0);
+ omap_set_gpio_dataout(GPIO_IDLE, 0);
+ __raw_writew(~0, &fpga->leds);
+ led_state &= ~LED_STATE_ENABLED;
+ if (evt == led_halted) {
+ iounmap(fpga);
+ fpga = NULL;
+ }
+ goto done;
case led_claim:
- hw_led_state |= H2P2_DBG_FPGA_LED_CLAIMRELEASE;
+ led_state |= LED_STATE_CLAIMED;
+ hw_led_state = 0;
break;
case led_release:
- hw_led_state &= ~H2P2_DBG_FPGA_LED_CLAIMRELEASE;
+ led_state &= ~LED_STATE_CLAIMED;
break;
#ifdef CONFIG_LEDS_TIMER
case led_timer:
- /*
- * Toggle Timer LED
- */
- if (hw_led_state & H2P2_DBG_FPGA_LED_TIMER)
- hw_led_state &= ~H2P2_DBG_FPGA_LED_TIMER;
- else
- hw_led_state |= H2P2_DBG_FPGA_LED_TIMER;
- break;
+ led_state ^= LED_TIMER_ON;
+ omap_set_gpio_dataout(GPIO_TIMER, led_state & LED_TIMER_ON);
+ goto done;
#endif
#ifdef CONFIG_LEDS_CPU
case led_idle_start:
- hw_led_state |= H2P2_DBG_FPGA_LED_IDLE;
- break;
+ omap_set_gpio_dataout(GPIO_IDLE, 1);
+ goto done;
case led_idle_end:
- hw_led_state &= ~H2P2_DBG_FPGA_LED_IDLE;
- break;
+ omap_set_gpio_dataout(GPIO_IDLE, 0);
+ goto done;
#endif
- case led_halted:
- if (hw_led_state & H2P2_DBG_FPGA_LED_HALTED)
- hw_led_state &= ~H2P2_DBG_FPGA_LED_HALTED;
- else
- hw_led_state |= H2P2_DBG_FPGA_LED_HALTED;
- break;
-
case led_green_on:
+ hw_led_state |= H2P2_DBG_FPGA_LED_GREEN;
break;
-
case led_green_off:
+ hw_led_state &= ~H2P2_DBG_FPGA_LED_GREEN;
break;
case led_amber_on:
+ hw_led_state |= H2P2_DBG_FPGA_LED_AMBER;
break;
-
case led_amber_off:
+ hw_led_state &= ~H2P2_DBG_FPGA_LED_AMBER;
break;
case led_red_on:
+ hw_led_state |= H2P2_DBG_FPGA_LED_RED;
break;
-
case led_red_off:
+ hw_led_state &= ~H2P2_DBG_FPGA_LED_RED;
+ break;
+
+ case led_blue_on:
+ hw_led_state |= H2P2_DBG_FPGA_LED_BLUE;
+ break;
+ case led_blue_off:
+ hw_led_state &= ~H2P2_DBG_FPGA_LED_BLUE;
break;
default:
@@ -98,7 +136,9 @@ void h2p2_dbg_leds_event(led_event_t evt)
/*
* Actually burn the LEDs
*/
- __raw_writew(~hw_led_state & 0xffff, H2P2_DBG_FPGA_LEDS);
+ if (led_state & LED_STATE_CLAIMED)
+ __raw_writew(~hw_led_state, &fpga->leds);
+done:
local_irq_restore(flags);
}
diff --git a/arch/arm/mach-omap/leds-osk.c b/arch/arm/mach-omap/leds-osk.c
new file mode 100644
index 0000000000000..f5177f430793b
--- /dev/null
+++ b/arch/arm/mach-omap/leds-osk.c
@@ -0,0 +1,198 @@
+/*
+ * linux/arch/arm/mach-omap/leds-osk.c
+ *
+ * LED driver for OSK, and optionally Mistral QVGA, boards
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/workqueue.h>
+
+#include <asm/hardware.h>
+#include <asm/leds.h>
+#include <asm/system.h>
+
+#include <asm/arch/gpio.h>
+#include <asm/arch/tps65010.h>
+
+#include "leds.h"
+
+
+#define LED_STATE_ENABLED (1 << 0)
+#define LED_STATE_CLAIMED (1 << 1)
+static u8 led_state;
+
+#define GREEN_LED (1 << 0) /* TPS65010 LED1 */
+#define AMBER_LED (1 << 1) /* TPS65010 LED2 */
+#define RED_LED (1 << 2) /* TPS65010 GPIO2 */
+#define TIMER_LED (1 << 3) /* Mistral board */
+#define IDLE_LED (1 << 4) /* Mistral board */
+static u8 hw_led_state;
+
+
+/* TPS65010 leds are changed using i2c -- from a task context.
+ * Using one of these for the "idle" LED would be impractical...
+ */
+#define TPS_LEDS (GREEN_LED | RED_LED | AMBER_LED)
+
+static u8 tps_leds_change;
+
+static void tps_work(void *unused)
+{
+ for (;;) {
+ u8 leds;
+
+ local_irq_disable();
+ leds = tps_leds_change;
+ tps_leds_change = 0;
+ local_irq_enable();
+
+ if (!leds)
+ break;
+
+ /* careful: the set_led() value is on/off/blink */
+ if (leds & GREEN_LED)
+ tps65010_set_led(LED1, !!(hw_led_state & GREEN_LED));
+ if (leds & AMBER_LED)
+ tps65010_set_led(LED2, !!(hw_led_state & AMBER_LED));
+
+ /* the gpio led doesn't have that issue */
+ if (leds & RED_LED)
+ tps65010_set_gpio_out_value(GPIO2,
+ !(hw_led_state & RED_LED));
+ }
+}
+
+static DECLARE_WORK(work, tps_work, NULL);
+
+#ifdef CONFIG_FB_OMAP
+
+/* For now, all system indicators require the Mistral board, since that
+ * LED can be manipulated without a task context. This LED is either red,
+ * or green, but not both; it can't give the full "disco led" effect.
+ */
+
+#define GPIO_LED_RED 3
+#define GPIO_LED_GREEN OMAP_MPUIO(4)
+
+static void mistral_setled(void)
+{
+ int red = 0;
+ int green = 0;
+
+ if (hw_led_state & TIMER_LED)
+ red = 1;
+ else if (hw_led_state & IDLE_LED)
+ green = 1;
+ // else both sides are disabled
+
+ omap_set_gpio_dataout(GPIO_LED_GREEN, green);
+ omap_set_gpio_dataout(GPIO_LED_RED, red);
+}
+
+#endif
+
+void osk_leds_event(led_event_t evt)
+{
+ unsigned long flags;
+ u16 leds;
+
+ local_irq_save(flags);
+
+ if (!(led_state & LED_STATE_ENABLED) && evt != led_start)
+ goto done;
+
+ leds = hw_led_state;
+ switch (evt) {
+ case led_start:
+ led_state |= LED_STATE_ENABLED;
+ hw_led_state = 0;
+ leds = ~0;
+ break;
+
+ case led_halted:
+ case led_stop:
+ led_state &= ~LED_STATE_ENABLED;
+ hw_led_state = 0;
+ // NOTE: work may still be pending!!
+ break;
+
+ case led_claim:
+ led_state |= LED_STATE_CLAIMED;
+ hw_led_state = 0;
+ leds = ~0;
+ break;
+
+ case led_release:
+ led_state &= ~LED_STATE_CLAIMED;
+ hw_led_state = 0;
+ break;
+
+#ifdef CONFIG_FB_OMAP
+
+#ifdef CONFIG_LEDS_TIMER
+ case led_timer:
+ hw_led_state ^= TIMER_LED;
+ mistral_setled();
+ break;
+#endif
+
+#ifdef CONFIG_LEDS_CPU
+ case led_idle_start:
+ hw_led_state |= IDLE_LED;
+ mistral_setled();
+ break;
+
+ case led_idle_end:
+ hw_led_state &= ~IDLE_LED;
+ mistral_setled();
+ break;
+#endif
+
+#endif /* CONFIG_FB_OMAP */
+
+ /* "green" == tps LED1 (leftmost, normally power-good)
+ * works only with DC adapter, not on battery power!
+ */
+ case led_green_on:
+ if (led_state & LED_STATE_CLAIMED)
+ hw_led_state |= GREEN_LED;
+ break;
+ case led_green_off:
+ if (led_state & LED_STATE_CLAIMED)
+ hw_led_state &= ~GREEN_LED;
+ break;
+
+ /* "amber" == tps LED2 (middle) */
+ case led_amber_on:
+ if (led_state & LED_STATE_CLAIMED)
+ hw_led_state |= AMBER_LED;
+ break;
+ case led_amber_off:
+ if (led_state & LED_STATE_CLAIMED)
+ hw_led_state &= ~AMBER_LED;
+ break;
+
+ /* "red" == LED on tps gpio3 (rightmost) */
+ case led_red_on:
+ if (led_state & LED_STATE_CLAIMED)
+ hw_led_state |= RED_LED;
+ break;
+ case led_red_off:
+ if (led_state & LED_STATE_CLAIMED)
+ hw_led_state &= ~RED_LED;
+ break;
+
+ default:
+ break;
+ }
+
+ leds ^= hw_led_state;
+ leds &= TPS_LEDS;
+ if (leds && (led_state & LED_STATE_CLAIMED)) {
+ tps_leds_change |= leds;
+ schedule_work(&work);
+ }
+
+done:
+ local_irq_restore(flags);
+}
diff --git a/arch/arm/mach-omap/leds.c b/arch/arm/mach-omap/leds.c
index b6d0c7203dab8..8ab21fe98e1bc 100644
--- a/arch/arm/mach-omap/leds.c
+++ b/arch/arm/mach-omap/leds.c
@@ -9,6 +9,9 @@
#include <asm/leds.h>
#include <asm/mach-types.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/mux.h>
+
#include "leds.h"
static int __init
@@ -17,8 +20,38 @@ omap_leds_init(void)
if (machine_is_omap_innovator())
leds_event = innovator_leds_event;
- else if (machine_is_omap_h2() || machine_is_omap_perseus2()) {
+ else if (machine_is_omap_h2() || machine_is_omap_perseus2())
leds_event = h2p2_dbg_leds_event;
+
+ else if (machine_is_omap_osk())
+ leds_event = osk_leds_event;
+
+ else
+ return -1;
+
+ if (machine_is_omap_h2()
+ || machine_is_omap_perseus2()
+ || machine_is_omap_osk()) {
+
+ /* LED1/LED2 pins can be used as GPIO (as done here), or by
+ * the LPG (works even in deep sleep!), to drive a bicolor
+ * LED on the H2 sample board, and another on the H2/P2
+ * "surfer" expansion board.
+ *
+ * The same pins drive a LED on the OSK Mistral board, but
+ * that's a different kind of LED (just one color at a time).
+ */
+ omap_cfg_reg(P18_1610_GPIO3);
+ if (omap_request_gpio(3) == 0)
+ omap_set_gpio_direction(3, 0);
+ else
+ printk(KERN_WARNING "LED: can't get GPIO3/red?\n");
+
+ omap_cfg_reg(MPUIO4);
+ if (omap_request_gpio(OMAP_MPUIO(4)) == 0)
+ omap_set_gpio_direction(OMAP_MPUIO(4), 0);
+ else
+ printk(KERN_WARNING "LED: can't get MPUIO4/green?\n");
}
leds_event(led_start);
diff --git a/arch/arm/mach-omap/leds.h b/arch/arm/mach-omap/leds.h
index 7571e2d635e34..a1e9fedc376cf 100644
--- a/arch/arm/mach-omap/leds.h
+++ b/arch/arm/mach-omap/leds.h
@@ -1,2 +1,3 @@
extern void innovator_leds_event(led_event_t evt);
extern void h2p2_dbg_leds_event(led_event_t evt);
+extern void osk_leds_event(led_event_t evt);
diff --git a/arch/arm/mach-omap/ocpi.c b/arch/arm/mach-omap/ocpi.c
index e27041ffe2389..c9ced134a75d6 100644
--- a/arch/arm/mach-omap/ocpi.c
+++ b/arch/arm/mach-omap/ocpi.c
@@ -1,11 +1,13 @@
/*
* linux/arch/arm/mach-omap/ocpi.c
*
- * Minimal OCP bus support for OMAP-1610 and OMAP-5912
+ * Minimal OCP bus support for omap16xx
*
- * Copyright (C) 2003 - 2004 Nokia Corporation
+ * Copyright (C) 2003 - 2005 Nokia Corporation
* Written by Tony Lindgren <tony@atomide.com>
*
+ * Modified for clock framework by Paul Mundt <paul.mundt@nokia.com>.
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
@@ -29,8 +31,10 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/spinlock.h>
+#include <linux/err.h>
#include <asm/io.h>
+#include <asm/hardware/clock.h>
#include <asm/arch/hardware.h>
#define OCPI_BASE 0xfffec320
@@ -42,13 +46,12 @@
#define OCPI_PROT (OCPI_BASE + 0x14)
#define OCPI_SEC (OCPI_BASE + 0x18)
-#define EN_OCPI_CK (1 << 0)
-#define IDLOCPI_ARM (1 << 1)
-
/* USB OHCI OCPI access error registers */
#define HOSTUEADDR 0xfffba0e0
#define HOSTUESTATUS 0xfffba0e4
+static struct clk *ocpi_ck;
+
/*
* Enables device access to OMAP buses via the OCPI bridge
* FIXME: Add locking
@@ -57,16 +60,12 @@ int ocpi_enable(void)
{
unsigned int val;
+ if (!cpu_is_omap16xx())
+ return -ENODEV;
+
/* Make sure there's clock for OCPI */
+ clk_enable(ocpi_ck);
-#if defined(CONFIG_ARCH_OMAP16XX)
- if (cpu_is_omap1610() || cpu_is_omap1710()) {
- val = omap_readl(OMAP16XX_ARM_IDLECT3);
- val |= EN_OCPI_CK;
- val &= ~IDLOCPI_ARM;
- omap_writel(val, OMAP16XX_ARM_IDLECT3);
- }
-#endif
/* Enable access for OHCI in OCPI */
val = omap_readl(OCPI_PROT);
val &= ~0xff;
@@ -81,19 +80,16 @@ int ocpi_enable(void)
}
EXPORT_SYMBOL(ocpi_enable);
-int ocpi_status(void)
+static int __init omap_ocpi_init(void)
{
- printk("OCPI: addr: 0x%08x cmd: 0x%08x\n"
- " ohci-addr: 0x%08x ohci-status: 0x%08x\n",
- omap_readl(OCPI_FAULT), omap_readl(OCPI_CMD_FAULT),
- omap_readl(HOSTUEADDR), omap_readl(HOSTUESTATUS));
+ if (!cpu_is_omap16xx())
+ return -ENODEV;
- return 1;
-}
-EXPORT_SYMBOL(ocpi_status);
+ ocpi_ck = clk_get(NULL, "l3_ocpi_ck");
+ if (IS_ERR(ocpi_ck))
+ return PTR_ERR(ocpi_ck);
-static int __init omap_ocpi_init(void)
-{
+ clk_use(ocpi_ck);
ocpi_enable();
printk("OMAP OCPI interconnect driver loaded\n");
@@ -102,7 +98,13 @@ static int __init omap_ocpi_init(void)
static void __exit omap_ocpi_exit(void)
{
- /* FIXME: Disable OCPI */
+ /* REVISIT: Disable OCPI */
+
+ if (!cpu_is_omap16xx())
+ return;
+
+ clk_unuse(ocpi_ck);
+ clk_put(ocpi_ck);
}
MODULE_AUTHOR("Tony Lindgren <tony@atomide.com>");
diff --git a/arch/arm/mach-omap/pm.c b/arch/arm/mach-omap/pm.c
index 68a4ec092baf0..00fac155df2a6 100644
--- a/arch/arm/mach-omap/pm.c
+++ b/arch/arm/mach-omap/pm.c
@@ -45,6 +45,7 @@
#include <asm/arch/omap16xx.h>
#include <asm/arch/pm.h>
#include <asm/arch/mux.h>
+#include <asm/arch/tc.h>
#include <asm/arch/tps65010.h>
#include "clock.h"
diff --git a/arch/arm/mach-omap/time.c b/arch/arm/mach-omap/time.c
index f673eeedd1d96..4205fdcb632c2 100644
--- a/arch/arm/mach-omap/time.c
+++ b/arch/arm/mach-omap/time.c
@@ -51,6 +51,8 @@
struct sys_timer omap_timer;
+#ifdef CONFIG_OMAP_MPU_TIMER
+
/*
* ---------------------------------------------------------------------------
* MPU timer
@@ -67,6 +69,36 @@ struct sys_timer omap_timer;
#define MPU_TIMER_AR (1 << 1)
#define MPU_TIMER_ST (1 << 0)
+/* cycles to nsec conversions taken from arch/i386/kernel/timers/timer_tsc.c,
+ * converted to use kHz by Kevin Hilman */
+/* convert from cycles(64bits) => nanoseconds (64bits)
+ * basic equation:
+ * ns = cycles / (freq / ns_per_sec)
+ * ns = cycles * (ns_per_sec / freq)
+ * ns = cycles * (10^9 / (cpu_khz * 10^3))
+ * ns = cycles * (10^6 / cpu_khz)
+ *
+ * Then we use scaling math (suggested by george at mvista.com) to get:
+ * ns = cycles * (10^6 * SC / cpu_khz / SC
+ * ns = cycles * cyc2ns_scale / SC
+ *
+ * And since SC is a constant power of two, we can convert the div
+ * into a shift.
+ * -johnstul at us.ibm.com "math is hard, lets go shopping!"
+ */
+static unsigned long cyc2ns_scale;
+#define CYC2NS_SCALE_FACTOR 10 /* 2^10, carefully chosen */
+
+static inline void set_cyc2ns_scale(unsigned long cpu_khz)
+{
+ cyc2ns_scale = (1000000 << CYC2NS_SCALE_FACTOR)/cpu_khz;
+}
+
+static inline unsigned long long cycles_2_ns(unsigned long long cyc)
+{
+ return (cyc * cyc2ns_scale) >> CYC2NS_SCALE_FACTOR;
+}
+
/*
* MPU_TICKS_PER_SEC must be an even number, otherwise machinecycles_to_usecs
* will break. On P2, the timer count rate is 6.5 MHz after programming PTV
@@ -112,8 +144,10 @@ static inline void omap_mpu_timer_start(int nr, unsigned long load_val)
unsigned long omap_mpu_timer_ticks_to_usecs(unsigned long nr_ticks)
{
- /* Round up to nearest usec */
- return ((nr_ticks * 1000) / (MPU_TICKS_PER_SEC / 2 / 1000) + 1) >> 1;
+ unsigned long long nsec;
+
+ nsec = cycles_2_ns((unsigned long long)nr_ticks);
+ return (unsigned long)nsec / 1000;
}
/*
@@ -158,22 +192,190 @@ static struct irqaction omap_mpu_timer_irq = {
.handler = omap_mpu_timer_interrupt
};
+static unsigned long omap_mpu_timer1_overflows;
+static irqreturn_t omap_mpu_timer1_interrupt(int irq, void *dev_id,
+ struct pt_regs *regs)
+{
+ omap_mpu_timer1_overflows++;
+ return IRQ_HANDLED;
+}
+
+static struct irqaction omap_mpu_timer1_irq = {
+ .name = "mpu timer1 overflow",
+ .flags = SA_INTERRUPT,
+ .handler = omap_mpu_timer1_interrupt
+};
+
static __init void omap_init_mpu_timer(void)
{
+ set_cyc2ns_scale(MPU_TICKS_PER_SEC / 1000);
omap_timer.offset = omap_mpu_timer_gettimeoffset;
+ setup_irq(INT_TIMER1, &omap_mpu_timer1_irq);
setup_irq(INT_TIMER2, &omap_mpu_timer_irq);
omap_mpu_timer_start(0, 0xffffffff);
omap_mpu_timer_start(1, MPU_TIMER_TICK_PERIOD);
}
/*
+ * Scheduler clock - returns current time in nanosec units.
+ */
+unsigned long long sched_clock(void)
+{
+ unsigned long ticks = 0 - omap_mpu_timer_read(0);
+ unsigned long long ticks64;
+
+ ticks64 = omap_mpu_timer1_overflows;
+ ticks64 <<= 32;
+ ticks64 |= ticks;
+
+ return cycles_2_ns(ticks64);
+}
+#endif /* CONFIG_OMAP_MPU_TIMER */
+
+#ifdef CONFIG_OMAP_32K_TIMER
+
+#ifdef CONFIG_ARCH_OMAP1510
+#error OMAP 32KHz timer does not currently work on 1510!
+#endif
+
+/*
+ * ---------------------------------------------------------------------------
+ * 32KHz OS timer
+ *
+ * This currently works only on 16xx, as 1510 does not have the continuous
+ * 32KHz synchronous timer. The 32KHz synchronous timer is used to keep track
+ * of time in addition to the 32KHz OS timer. Using only the 32KHz OS timer
+ * on 1510 would be possible, but the timer would not be as accurate as
+ * with the 32KHz synchronized timer.
+ * ---------------------------------------------------------------------------
+ */
+#define OMAP_32K_TIMER_BASE 0xfffb9000
+#define OMAP_32K_TIMER_CR 0x08
+#define OMAP_32K_TIMER_TVR 0x00
+#define OMAP_32K_TIMER_TCR 0x04
+
+#define OMAP_32K_TICKS_PER_HZ (32768 / HZ)
+
+/*
+ * TRM says 1 / HZ = ( TVR + 1) / 32768, so TRV = (32768 / HZ) - 1
+ * so with HZ = 100, TVR = 327.68.
+ */
+#define OMAP_32K_TIMER_TICK_PERIOD ((32768 / HZ) - 1)
+#define MAX_SKIP_JIFFIES 25
+#define TIMER_32K_SYNCHRONIZED 0xfffbc410
+
+#define JIFFIES_TO_HW_TICKS(nr_jiffies, clock_rate) \
+ (((nr_jiffies) * (clock_rate)) / HZ)
+
+static inline void omap_32k_timer_write(int val, int reg)
+{
+ omap_writew(val, reg + OMAP_32K_TIMER_BASE);
+}
+
+static inline unsigned long omap_32k_timer_read(int reg)
+{
+ return omap_readl(reg + OMAP_32K_TIMER_BASE) & 0xffffff;
+}
+
+/*
+ * The 32KHz synchronized timer is an additional timer on 16xx.
+ * It is always running.
+ */
+static inline unsigned long omap_32k_sync_timer_read(void)
+{
+ return omap_readl(TIMER_32K_SYNCHRONIZED);
+}
+
+static inline void omap_32k_timer_start(unsigned long load_val)
+{
+ omap_32k_timer_write(load_val, OMAP_32K_TIMER_TVR);
+ omap_32k_timer_write(0x0f, OMAP_32K_TIMER_CR);
+}
+
+static inline void omap_32k_timer_stop(void)
+{
+ omap_32k_timer_write(0x0, OMAP_32K_TIMER_CR);
+}
+
+/*
+ * Rounds down to nearest usec
+ */
+static inline unsigned long omap_32k_ticks_to_usecs(unsigned long ticks_32k)
+{
+ return (ticks_32k * 5*5*5*5*5*5) >> 9;
+}
+
+static unsigned long omap_32k_last_tick = 0;
+
+/*
+ * Returns elapsed usecs since last 32k timer interrupt
+ */
+static unsigned long omap_32k_timer_gettimeoffset(void)
+{
+ unsigned long now = omap_32k_sync_timer_read();
+ return omap_32k_ticks_to_usecs(now - omap_32k_last_tick);
+}
+
+/*
+ * Timer interrupt for 32KHz timer. When dynamic tick is enabled, this
+ * function is also called from other interrupts to remove latency
+ * issues with dynamic tick. In the dynamic tick case, we need to lock
+ * with irqsave.
+ */
+static irqreturn_t omap_32k_timer_interrupt(int irq, void *dev_id,
+ struct pt_regs *regs)
+{
+ unsigned long flags;
+ unsigned long now;
+
+ write_seqlock_irqsave(&xtime_lock, flags);
+ now = omap_32k_sync_timer_read();
+
+ while (now - omap_32k_last_tick >= OMAP_32K_TICKS_PER_HZ) {
+ omap_32k_last_tick += OMAP_32K_TICKS_PER_HZ;
+ timer_tick(regs);
+ }
+
+ /* Restart timer so we don't drift off due to modulo or dynamic tick.
+ * By default we program the next timer to be continuous to avoid
+ * latencies during high system load. During dynamic tick operation the
+ * continuous timer can be overridden from pm_idle to be longer.
+ */
+ omap_32k_timer_start(omap_32k_last_tick + OMAP_32K_TICKS_PER_HZ - now);
+ write_sequnlock_irqrestore(&xtime_lock, flags);
+
+ return IRQ_HANDLED;
+}
+
+static struct irqaction omap_32k_timer_irq = {
+ .name = "32KHz timer",
+ .flags = SA_INTERRUPT,
+ .handler = omap_32k_timer_interrupt
+};
+
+static __init void omap_init_32k_timer(void)
+{
+ setup_irq(INT_OS_TIMER, &omap_32k_timer_irq);
+ omap_timer.offset = omap_32k_timer_gettimeoffset;
+ omap_32k_last_tick = omap_32k_sync_timer_read();
+ omap_32k_timer_start(OMAP_32K_TIMER_TICK_PERIOD);
+}
+#endif /* CONFIG_OMAP_32K_TIMER */
+
+/*
* ---------------------------------------------------------------------------
* Timer initialization
* ---------------------------------------------------------------------------
*/
void __init omap_timer_init(void)
{
+#if defined(CONFIG_OMAP_MPU_TIMER)
omap_init_mpu_timer();
+#elif defined(CONFIG_OMAP_32K_TIMER)
+ omap_init_32k_timer();
+#else
+#error No system timer selected in Kconfig!
+#endif
}
struct sys_timer omap_timer = {
diff --git a/arch/arm/mach-omap/usb.c b/arch/arm/mach-omap/usb.c
index 4eeabe4fecc84..6e805d451d0e7 100644
--- a/arch/arm/mach-omap/usb.c
+++ b/arch/arm/mach-omap/usb.c
@@ -49,10 +49,13 @@
/* TESTED ON:
* - 1611B H2 (with usb1 mini-AB) using standard Mini-B or OTG cables
+ * - 5912 OSK OHCI (with usb0 standard-A), standard A-to-B cables
+ * - 5912 OSK UDC, with *nonstandard* A-to-A cable
* - 1510 Innovator UDC with bundled usb0 cable
* - 1510 Innovator OHCI with bundled usb1/usb2 cable
* - 1510 Innovator OHCI with custom usb0 cable, feeding 5V VBUS
* - 1710 custom development board using alternate pin group
+ * - 1710 H3 (with usb1 mini-AB) using standard Mini-B or OTG cables
*/
/*-------------------------------------------------------------------------*/
@@ -101,50 +104,48 @@ static u32 __init omap_usb0_init(unsigned nwires, unsigned is_device)
return 0;
}
- /*
- * VP and VM are needed for all active usb0 configurations.
- * USB0_VP and USB0_VM are always set on 1510, there's no muxing
- * available for them.
- */
- if (nwires >= 2 && !cpu_is_omap15xx()) {
- omap_cfg_reg(AA9_USB0_VP);
- omap_cfg_reg(R9_USB0_VM);
- }
if (is_device)
omap_cfg_reg(W4_USB_PUEN);
/* internal transceiver */
if (nwires == 2) {
+ // omap_cfg_reg(P9_USB_DP);
+ // omap_cfg_reg(R8_USB_DM);
+
if (cpu_is_omap15xx()) {
- /* This works for OHCI on 1510-Innovator */
+ /* This works on 1510-Innovator */
return 0;
}
- /* NOTE: host OR device mode for now, no OTG */
+ /* NOTES:
+ * - peripheral should configure VBUS detection!
+ * - only peripherals may use the internal D+/D- pulldowns
+ * - OTG support on this port not yet written
+ */
+
USB_TRANSCEIVER_CTRL_REG &= ~(7 << 4);
- if (is_device) {
- omap_cfg_reg(R18_1510_USB_GPIO0);
- // omap_cfg_reg(USB0_VBUS);
- // USB_TRANSCEIVER_CTRL_REG.CONF_USB0_PORT_R = 7
- } else /* host mode needs D+ and D- pulldowns */
- USB_TRANSCEIVER_CTRL_REG &= ~(3 << 1);
+ if (!is_device)
+ USB_TRANSCEIVER_CTRL_REG |= (3 << 1);
return 3 << 16;
}
/* alternate pin config, external transceiver */
+ if (cpu_is_omap15xx()) {
+ printk(KERN_ERR "no usb0 alt pin config on 15xx\n");
+ return 0;
+ }
+
omap_cfg_reg(V6_USB0_TXD);
omap_cfg_reg(W9_USB0_TXEN);
omap_cfg_reg(W5_USB0_SE0);
-#ifdef CONFIG_ARCH_OMAP_USB_SPEED
- /* FIXME: there's good chance that pin V9 is used for MMC2 port cmddir */
- omap_cfg_reg(V9_USB0_SPEED);
- // omap_cfg_reg(V9_USB0_SUSP);
-#endif
+ /* NOTE: SPEED and SUSP aren't configured here */
if (nwires != 3)
omap_cfg_reg(Y5_USB0_RCV);
+ if (nwires != 6)
+ USB_TRANSCEIVER_CTRL_REG &= ~CONF_USB2_UNI_R;
switch (nwires) {
case 3:
@@ -155,7 +156,8 @@ static u32 __init omap_usb0_init(unsigned nwires, unsigned is_device)
break;
case 6:
syscon1 = 3;
- /* REVISIT: Is CONF_USB2_UNI_R only needed when nwires = 6? */
+ omap_cfg_reg(AA9_USB0_VP);
+ omap_cfg_reg(R9_USB0_VM);
USB_TRANSCEIVER_CTRL_REG |= CONF_USB2_UNI_R;
break;
default:
@@ -181,10 +183,13 @@ static u32 __init omap_usb1_init(unsigned nwires)
omap_cfg_reg(USB1_SEO);
omap_cfg_reg(USB1_SPEED);
// SUSP
- } else if (cpu_is_omap16xx()) {
+ } else if (cpu_is_omap1610() || cpu_is_omap5912()) {
omap_cfg_reg(W13_1610_USB1_SE0);
omap_cfg_reg(R13_1610_USB1_SPEED);
// SUSP
+ } else if (cpu_is_omap1710()) {
+ omap_cfg_reg(R13_1710_USB1_SE0);
+ // SUSP
} else {
pr_debug("usb unrecognized\n");
}
@@ -216,12 +221,11 @@ static u32 __init omap_usb2_init(unsigned nwires, unsigned alt_pingroup)
{
u32 syscon1 = 0;
+ /* NOTE erratum: must leave USB2_UNI_R set if usb0 in use */
if (alt_pingroup || nwires == 0)
return 0;
if (nwires != 6 && !cpu_is_omap15xx())
USB_TRANSCEIVER_CTRL_REG &= ~CONF_USB2_UNI_R;
- if (nwires == 0)
- return 0;
/* external transceiver */
if (cpu_is_omap15xx()) {
@@ -322,8 +326,8 @@ static u64 ohci_dmamask = ~(u32)0;
static struct resource ohci_resources[] = {
{
- .start = IO_ADDRESS(OMAP_OHCI_BASE),
- .end = IO_ADDRESS(OMAP_OHCI_BASE + 4096),
+ .start = OMAP_OHCI_BASE,
+ .end = OMAP_OHCI_BASE + 4096,
.flags = IORESOURCE_MEM,
},
{
@@ -374,6 +378,10 @@ static struct platform_device otg_device = {
/*-------------------------------------------------------------------------*/
+#define ULPD_CLOCK_CTRL_REG __REG16(ULPD_CLOCK_CTRL)
+#define ULPD_SOFT_REQ_REG __REG16(ULPD_SOFT_REQ)
+
+
// FIXME correct answer depends on hmc_mode,
// as does any nonzero value for config->otg port number
#ifdef CONFIG_USB_GADGET_OMAP
@@ -412,12 +420,11 @@ omap_otg_init(struct omap_usb_config *config)
syscon = config->hmc_mode;
syscon |= USBX_SYNCHRO | (4 << 16) /* B_ASE0_BRST */;
- if (config->otg || config->register_host)
- syscon |= UHOST_EN;
#ifdef CONFIG_USB_OTG
if (config->otg)
syscon |= OTG_EN;
#endif
+ pr_debug("USB_TRANSCEIVER_CTRL_REG = %03x\n", USB_TRANSCEIVER_CTRL_REG);
pr_debug("OTG_SYSCON_2_REG = %08x\n", syscon);
OTG_SYSCON_2_REG = syscon;
@@ -435,7 +442,10 @@ omap_otg_init(struct omap_usb_config *config)
printk(", Mini-AB on usb%d", config->otg - 1);
printk("\n");
- /* don't clock unused USB controllers */
+ /* leave USB clocks/controllers off until needed */
+ ULPD_SOFT_REQ_REG &= ~SOFT_USB_CLK_REQ;
+ ULPD_CLOCK_CTRL_REG &= ~USB_MCLK_EN;
+ ULPD_CLOCK_CTRL_REG |= DIS_USB_PVCI_CLK;
syscon = OTG_SYSCON_1_REG;
syscon |= HST_IDLE_EN|DEV_IDLE_EN|OTG_IDLE_EN;
@@ -443,6 +453,7 @@ omap_otg_init(struct omap_usb_config *config)
if (config->otg || config->register_dev) {
syscon &= ~DEV_IDLE_EN;
udc_device.dev.platform_data = config;
+ /* FIXME patch IRQ numbers for omap730 */
status = platform_device_register(&udc_device);
if (status)
pr_debug("can't register UDC device, %d\n", status);
@@ -453,6 +464,8 @@ omap_otg_init(struct omap_usb_config *config)
if (config->otg || config->register_host) {
syscon &= ~HST_IDLE_EN;
ohci_device.dev.platform_data = config;
+ if (cpu_is_omap730())
+ ohci_resources[1].start = INT_730_USB_HHC_1;
status = platform_device_register(&ohci_device);
if (status)
pr_debug("can't register OHCI device, %d\n", status);
@@ -462,10 +475,12 @@ omap_otg_init(struct omap_usb_config *config)
#ifdef CONFIG_USB_OTG
if (config->otg) {
syscon &= ~OTG_IDLE_EN;
+ otg_device.dev.platform_data = config;
if (cpu_is_omap730())
otg_resources[1].start = INT_730_USB_OTG;
status = platform_device_register(&otg_device);
- // ...
+ if (status)
+ pr_debug("can't register OTG device, %d\n", status);
}
#endif
pr_debug("OTG_SYSCON_1_REG = %08x\n", syscon);
@@ -482,10 +497,6 @@ static inline void omap_otg_init(struct omap_usb_config *config) {}
#ifdef CONFIG_ARCH_OMAP1510
-#define ULPD_SOFT_REQ_REG __REG16(ULPD_SOFT_REQ)
-#define SOFT_UDC_REQ (1 << 4)
-#define SOFT_DPLL_REQ (1 << 0)
-
#define ULPD_DPLL_CTRL_REG __REG16(ULPD_DPLL_CTRL)
#define DPLL_IOB (1 << 13)
#define DPLL_PLL_ENABLE (1 << 4)
@@ -546,7 +557,6 @@ static void __init omap_1510_usb_init(struct omap_usb_config *config)
/* hcd explicitly gates 48MHz */
}
#endif
-
}
#else
@@ -564,7 +574,8 @@ omap_usb_init(void)
config = omap_get_config(OMAP_TAG_USB, struct omap_usb_config);
if (config == NULL) {
- printk(KERN_ERR "USB: No board-specific platform config found\n");
+ printk(KERN_ERR "USB: No board-specific "
+ "platform config found\n");
return -ENODEV;
}
platform_data = *config;
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index f09e49d30efa8..c437660bf92f8 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -8,6 +8,7 @@ choice
config ARCH_LUBBOCK
bool "Intel DBPXA250 Development Platform"
select PXA25x
+ select SA1111
config MACH_MAINSTONE
bool "Intel HCDDBBVA0 Development Platform"
@@ -19,28 +20,38 @@ config ARCH_PXA_IDP
select PXA25x
config PXA_SHARPSL
- bool "SHARP SL-C7xx Models (Corgi, Shepherd and Husky)"
+ bool "SHARP SL-5600 and SL-C7xx Models"
select PXA25x
+ select SHARP_SCOOP
help
Say Y here if you intend to run this kernel on a
- Sharp SL-C700 (Corgi), SL-C750 (Shepherd) or a
- Sharp SL-C760 (Husky) handheld computer.
+ Sharp SL-5600 (Poodle), Sharp SL-C700 (Corgi),
+ SL-C750 (Shepherd) or a Sharp SL-C760 (Husky)
+ handheld computer.
endchoice
endmenu
+config MACH_POODLE
+ bool "Enable Sharp SL-5600 (Poodle) Support"
+ depends PXA_SHARPSL
+ select SHARP_LOCOMO
+
config MACH_CORGI
bool "Enable Sharp SL-C700 (Corgi) Support"
depends PXA_SHARPSL
+ select PXA_SHARP_C7xx
config MACH_SHEPHERD
bool "Enable Sharp SL-C750 (Shepherd) Support"
depends PXA_SHARPSL
+ select PXA_SHARP_C7xx
config MACH_HUSKY
bool "Enable Sharp SL-C760 (Husky) Support"
depends PXA_SHARPSL
+ select PXA_SHARP_C7xx
config PXA25x
bool
@@ -57,4 +68,9 @@ config IWMMXT
help
Enable support for iWMMXt
+config PXA_SHARP_C7xx
+ bool
+ help
+ Enable support for all Sharp C7xx models
+
endif
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
index d480bd54c95d7..c4e6d25235853 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -11,7 +11,8 @@ obj-$(CONFIG_PXA27x) += pxa27x.o
obj-$(CONFIG_ARCH_LUBBOCK) += lubbock.o
obj-$(CONFIG_MACH_MAINSTONE) += mainstone.o
obj-$(CONFIG_ARCH_PXA_IDP) += idp.o
-obj-$(CONFIG_PXA_SHARPSL) += corgi.o corgi_ssp.o ssp.o
+obj-$(CONFIG_PXA_SHARP_C7xx) += corgi.o corgi_ssp.o ssp.o
+obj-$(CONFIG_MACH_POODLE) += poodle.o
# Support for blinky lights
led-y := leds.o
diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c
index 5260436cdb3b1..94841068a688e 100644
--- a/arch/arm/mach-pxa/corgi.c
+++ b/arch/arm/mach-pxa/corgi.c
@@ -59,7 +59,7 @@ static struct scoop_config corgi_scoop_setup = {
.io_out = CORGI_SCOOP_IO_OUT,
};
-static struct platform_device corgiscoop_device = {
+struct platform_device corgiscoop_device = {
.name = "sharp-scoop",
.id = -1,
.dev = {
diff --git a/arch/arm/mach-pxa/idp.c b/arch/arm/mach-pxa/idp.c
index 4333a0f19b327..c5a66bf4d3d53 100644
--- a/arch/arm/mach-pxa/idp.c
+++ b/arch/arm/mach-pxa/idp.c
@@ -10,13 +10,16 @@
* 2001-09-13: Cliff Brake <cbrake@accelent.com>
* Initial code
*
- * Expected command line: mem=32M initrd=0xa1000000,4M root=/dev/ram ramdisk=8192
+ * 2005-02-15: Cliff Brake <cliff.brake@gmail.com>
+ * <http://www.vibren.com> <http://bec-systems.com>
+ * Updated for 2.6 kernel
+ *
*/
-#include <linux/kernel.h>
+
#include <linux/init.h>
-#include <linux/major.h>
-#include <linux/fs.h>
#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/fb.h>
#include <asm/setup.h>
#include <asm/memory.h>
@@ -29,68 +32,133 @@
#include <asm/arch/pxa-regs.h>
#include <asm/arch/idp.h>
+#include <asm/arch/pxafb.h>
+#include <asm/arch/bitfield.h>
+#include <asm/arch/mmc.h>
#include "generic.h"
-#ifndef PXA_IDP_REV02
-/* shadow registers for write only registers */
-unsigned int idp_cpld_led_control_shadow = 0x1;
-unsigned int idp_cpld_periph_pwr_shadow = 0xd;
-unsigned int ipd_cpld_cir_shadow = 0;
-unsigned int idp_cpld_kb_col_high_shadow = 0;
-unsigned int idp_cpld_kb_col_low_shadow = 0;
-unsigned int idp_cpld_pccard_en_shadow = 0xC3;
-unsigned int idp_cpld_gpioh_dir_shadow = 0;
-unsigned int idp_cpld_gpioh_value_shadow = 0;
-unsigned int idp_cpld_gpiol_dir_shadow = 0;
-unsigned int idp_cpld_gpiol_value_shadow = 0;
-
-/*
- * enable all LCD signals -- they should still be on
- * write protect flash
- * enable all serial port transceivers
+/* TODO:
+ * - add pxa2xx_audio_ops_t device structure
+ * - Ethernet interrupt
*/
-unsigned int idp_control_port_shadow = ((0x7 << 21) | /* LCD power */
- (0x1 << 19) | /* disable flash write enable */
- (0x7 << 9)); /* enable serial port transeivers */
+static struct resource smc91x_resources[] = {
+ [0] = {
+ .start = (IDP_ETH_PHYS + 0x300),
+ .end = (IDP_ETH_PHYS + 0xfffff),
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_GPIO(4),
+ .end = IRQ_GPIO(4),
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static struct platform_device smc91x_device = {
+ .name = "smc91x",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(smc91x_resources),
+ .resource = smc91x_resources,
+};
+
+static void idp_backlight_power(int on)
+{
+ if (on) {
+ IDP_CPLD_LCD |= (1<<1);
+ } else {
+ IDP_CPLD_LCD &= ~(1<<1);
+ }
+}
+
+static void idp_vlcd(int on)
+{
+ if (on) {
+ IDP_CPLD_LCD |= (1<<2);
+ } else {
+ IDP_CPLD_LCD &= ~(1<<2);
+ }
+}
+
+static void idp_lcd_power(int on)
+{
+ if (on) {
+ IDP_CPLD_LCD |= (1<<0);
+ } else {
+ IDP_CPLD_LCD &= ~(1<<0);
+ }
+
+ /* call idp_vlcd for now as core driver does not support
+ * both power and vlcd hooks. Note, this is not technically
+ * the correct sequence, but seems to work. Disclaimer:
+ * this may eventually damage the display.
+ */
+
+ idp_vlcd(on);
+}
+
+static struct pxafb_mach_info sharp_lm8v31 __initdata = {
+ .pixclock = 270000,
+ .xres = 640,
+ .yres = 480,
+ .bpp = 16,
+ .hsync_len = 1,
+ .left_margin = 3,
+ .right_margin = 3,
+ .vsync_len = 1,
+ .upper_margin = 0,
+ .lower_margin = 0,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ .cmap_greyscale = 0,
+ .cmap_inverse = 0,
+ .cmap_static = 0,
+ .lccr0 = LCCR0_SDS,
+ .lccr3 = LCCR3_PCP | LCCR3_Acb(255),
+ .pxafb_backlight_power = &idp_backlight_power,
+ .pxafb_lcd_power = &idp_lcd_power
+};
-#endif
+static int idp_mci_init(struct device *dev, irqreturn_t (*idp_detect_int)(int, void *, struct pt_regs *), void *data)
+{
+ /* setup GPIO for PXA25x MMC controller */
+ pxa_gpio_mode(GPIO6_MMCCLK_MD);
+ pxa_gpio_mode(GPIO8_MMCCS0_MD);
+
+ return 0;
+}
+
+static struct pxamci_platform_data idp_mci_platform_data = {
+ .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34,
+ .init = idp_mci_init,
+};
static void __init idp_init(void)
{
printk("idp_init()\n");
+
+ platform_device_register(&smc91x_device);
+ //platform_device_register(&mst_audio_device);
+ set_pxa_fb_info(&sharp_lm8v31);
+ pxa_set_mci_info(&idp_mci_platform_data);
}
static void __init idp_init_irq(void)
{
+
pxa_init_irq();
+
+ set_irq_type(TOUCH_PANEL_IRQ, TOUCH_PANEL_IRQ_EDGE);
}
static struct map_desc idp_io_desc[] __initdata = {
/* virtual physical length type */
-
-#ifndef PXA_IDP_REV02
- { IDP_CTRL_PORT_BASE,
- IDP_CTRL_PORT_PHYS,
- IDP_CTRL_PORT_SIZE,
- MT_DEVICE },
-#endif
-
- { IDP_IDE_BASE,
- IDP_IDE_PHYS,
- IDP_IDE_SIZE,
- MT_DEVICE },
- { IDP_ETH_BASE,
- IDP_ETH_PHYS,
- IDP_ETH_SIZE,
- MT_DEVICE },
- { IDP_COREVOLT_BASE,
+ { IDP_COREVOLT_VIRT,
IDP_COREVOLT_PHYS,
IDP_COREVOLT_SIZE,
MT_DEVICE },
- { IDP_CPLD_BASE,
+ { IDP_CPLD_VIRT,
IDP_CPLD_PHYS,
IDP_CPLD_SIZE,
MT_DEVICE }
@@ -101,8 +169,6 @@ static void __init idp_map_io(void)
pxa_map_io();
iotable_init(idp_io_desc, ARRAY_SIZE(idp_io_desc));
- set_irq_type(TOUCH_PANEL_IRQ, TOUCH_PANEL_IRQ_EDGE);
-
// serial ports 2 & 3
pxa_gpio_mode(GPIO42_BTRXD_MD);
pxa_gpio_mode(GPIO43_BTTXD_MD);
@@ -114,8 +180,8 @@ static void __init idp_map_io(void)
}
-MACHINE_START(PXA_IDP, "Accelent Xscale IDP")
- MAINTAINER("Accelent Systems Inc.")
+MACHINE_START(PXA_IDP, "Vibren PXA255 IDP")
+ MAINTAINER("Vibren Technologies")
BOOT_MEM(0xa0000000, 0x40000000, io_p2v(0x40000000))
MAPIO(idp_map_io)
INITIRQ(idp_init_irq)
diff --git a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c
index a676a8657b382..f3cac43124a51 100644
--- a/arch/arm/mach-pxa/irq.c
+++ b/arch/arm/mach-pxa/irq.c
@@ -97,23 +97,23 @@ static int pxa_gpio_irq_type(unsigned int irq, unsigned int type)
type = __IRQT_RISEDGE | __IRQT_FALEDGE;
}
- printk(KERN_DEBUG "IRQ%d (GPIO%d): ", irq, gpio);
+ /* printk(KERN_DEBUG "IRQ%d (GPIO%d): ", irq, gpio); */
pxa_gpio_mode(gpio | GPIO_IN);
if (type & __IRQT_RISEDGE) {
- printk("rising ");
+ /* printk("rising "); */
__set_bit (gpio, GPIO_IRQ_rising_edge);
} else
__clear_bit (gpio, GPIO_IRQ_rising_edge);
if (type & __IRQT_FALEDGE) {
- printk("falling ");
+ /* printk("falling "); */
__set_bit (gpio, GPIO_IRQ_falling_edge);
} else
__clear_bit (gpio, GPIO_IRQ_falling_edge);
- printk("edges\n");
+ /* printk("edges\n"); */
GRER(gpio) = GPIO_IRQ_rising_edge[idx] & GPIO_IRQ_mask[idx];
GFER(gpio) = GPIO_IRQ_falling_edge[idx] & GPIO_IRQ_mask[idx];
diff --git a/arch/arm/mach-pxa/leds-idp.c b/arch/arm/mach-pxa/leds-idp.c
index adb108c6c2bb3..5eba6ea0b0f79 100644
--- a/arch/arm/mach-pxa/leds-idp.c
+++ b/arch/arm/mach-pxa/leds-idp.c
@@ -19,6 +19,7 @@
#include <asm/leds.h>
#include <asm/system.h>
+#include <asm/arch/pxa-regs.h>
#include <asm/arch/idp.h>
#include "leds.h"
@@ -65,12 +66,12 @@ void idp_leds_event(led_event_t evt)
#ifdef CONFIG_LEDS_CPU
case led_idle_start:
if (!(led_state & LED_STATE_CLAIMED))
- hw_led_state |= IDP_BUSY_LED;
+ hw_led_state &= ~IDP_BUSY_LED;
break;
case led_idle_end:
if (!(led_state & LED_STATE_CLAIMED))
- hw_led_state &= ~IDP_BUSY_LED;
+ hw_led_state |= IDP_BUSY_LED;
break;
#endif
@@ -79,12 +80,12 @@ void idp_leds_event(led_event_t evt)
case led_green_on:
if (led_state & LED_STATE_CLAIMED)
- hw_led_state &= ~IDP_HB_LED;
+ hw_led_state |= IDP_HB_LED;
break;
case led_green_off:
if (led_state & LED_STATE_CLAIMED)
- hw_led_state |= IDP_HB_LED;
+ hw_led_state &= ~IDP_HB_LED;
break;
case led_amber_on:
@@ -95,12 +96,12 @@ void idp_leds_event(led_event_t evt)
case led_red_on:
if (led_state & LED_STATE_CLAIMED)
- hw_led_state &= ~IDP_BUSY_LED;
+ hw_led_state |= IDP_BUSY_LED;
break;
case led_red_off:
if (led_state & LED_STATE_CLAIMED)
- hw_led_state |= IDP_BUSY_LED;
+ hw_led_state &= ~IDP_BUSY_LED;
break;
default:
@@ -108,7 +109,9 @@ void idp_leds_event(led_event_t evt)
}
if (led_state & LED_STATE_ENABLED)
- IDP_WRITE_LEDS(hw_led_state);
+ IDP_CPLD_LED_CONTROL = ( (IDP_CPLD_LED_CONTROL | IDP_LEDS_MASK) & ~hw_led_state);
+ else
+ IDP_CPLD_LED_CONTROL |= IDP_LEDS_MASK;
local_irq_restore(flags);
}
diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c
index d4516a8ad351d..dd012d6e2f5ca 100644
--- a/arch/arm/mach-pxa/lubbock.c
+++ b/arch/arm/mach-pxa/lubbock.c
@@ -138,6 +138,7 @@ static struct platform_device sa1111_device = {
static struct resource smc91x_resources[] = {
[0] = {
+ .name = "smc91x-regs",
.start = 0x0c000000,
.end = 0x0c0fffff,
.flags = IORESOURCE_MEM,
@@ -148,6 +149,7 @@ static struct resource smc91x_resources[] = {
.flags = IORESOURCE_IRQ,
},
[2] = {
+ .name = "smc91x-attrib",
.start = 0x0e000000,
.end = 0x0e0fffff,
.flags = IORESOURCE_MEM,
diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c
index 2e5f1a954923e..3f952237ae3dd 100644
--- a/arch/arm/mach-pxa/mainstone.c
+++ b/arch/arm/mach-pxa/mainstone.c
@@ -295,6 +295,15 @@ static void __init mainstone_map_io(void)
{
pxa_map_io();
iotable_init(mainstone_io_desc, ARRAY_SIZE(mainstone_io_desc));
+
+ /* initialize sleep mode regs (wake-up sources, etc) */
+ PGSR0 = 0x00008800;
+ PGSR1 = 0x00000002;
+ PGSR2 = 0x0001FC00;
+ PGSR3 = 0x00001F81;
+ PWER = 0xC0000002;
+ PRER = 0x00000002;
+ PFER = 0x00000002;
}
MACHINE_START(MAINSTONE, "Intel HCDDBBVA0 Development Platform (aka Mainstone)")
diff --git a/arch/arm/mach-pxa/pm.c b/arch/arm/mach-pxa/pm.c
index 901ee6880016c..82a4bf34c251c 100644
--- a/arch/arm/mach-pxa/pm.c
+++ b/arch/arm/mach-pxa/pm.c
@@ -47,12 +47,18 @@ extern void pxa_cpu_resume(void);
*/
enum { SLEEP_SAVE_START = 0,
- SLEEP_SAVE_GPLR0, SLEEP_SAVE_GPLR1, SLEEP_SAVE_GPLR2,
- SLEEP_SAVE_GPDR0, SLEEP_SAVE_GPDR1, SLEEP_SAVE_GPDR2,
- SLEEP_SAVE_GRER0, SLEEP_SAVE_GRER1, SLEEP_SAVE_GRER2,
- SLEEP_SAVE_GFER0, SLEEP_SAVE_GFER1, SLEEP_SAVE_GFER2,
- SLEEP_SAVE_GAFR0_L, SLEEP_SAVE_GAFR1_L, SLEEP_SAVE_GAFR2_L,
- SLEEP_SAVE_GAFR0_U, SLEEP_SAVE_GAFR1_U, SLEEP_SAVE_GAFR2_U,
+ SLEEP_SAVE_GPLR0, SLEEP_SAVE_GPLR1, SLEEP_SAVE_GPLR2, SLEEP_SAVE_GPLR3,
+ SLEEP_SAVE_GPDR0, SLEEP_SAVE_GPDR1, SLEEP_SAVE_GPDR2, SLEEP_SAVE_GPDR3,
+ SLEEP_SAVE_GRER0, SLEEP_SAVE_GRER1, SLEEP_SAVE_GRER2, SLEEP_SAVE_GRER3,
+ SLEEP_SAVE_GFER0, SLEEP_SAVE_GFER1, SLEEP_SAVE_GFER2, SLEEP_SAVE_GFER3,
+ SLEEP_SAVE_PGSR0, SLEEP_SAVE_PGSR1, SLEEP_SAVE_PGSR2, SLEEP_SAVE_PGSR3,
+
+ SLEEP_SAVE_GAFR0_L, SLEEP_SAVE_GAFR0_U,
+ SLEEP_SAVE_GAFR1_L, SLEEP_SAVE_GAFR1_U,
+ SLEEP_SAVE_GAFR2_L, SLEEP_SAVE_GAFR2_U,
+ SLEEP_SAVE_GAFR3_L, SLEEP_SAVE_GAFR3_U,
+
+ SLEEP_SAVE_PSTR,
SLEEP_SAVE_ICMR,
SLEEP_SAVE_CKEN,
@@ -73,6 +79,11 @@ static int pxa_pm_enter(suspend_state_t state)
if (state != PM_SUSPEND_MEM)
return -EINVAL;
+#ifdef CONFIG_IWMMXT
+ /* force any iWMMXt context to ram **/
+ iwmmxt_task_disable(NULL);
+#endif
+
/* preserve current time */
rtc.tv_sec = RCNR;
rtc.tv_nsec = 0;
@@ -82,20 +93,32 @@ static int pxa_pm_enter(suspend_state_t state)
SAVE(GPDR0); SAVE(GPDR1); SAVE(GPDR2);
SAVE(GRER0); SAVE(GRER1); SAVE(GRER2);
SAVE(GFER0); SAVE(GFER1); SAVE(GFER2);
+ SAVE(PGSR0); SAVE(PGSR1); SAVE(PGSR2);
+
SAVE(GAFR0_L); SAVE(GAFR0_U);
SAVE(GAFR1_L); SAVE(GAFR1_U);
SAVE(GAFR2_L); SAVE(GAFR2_U);
+#ifdef CONFIG_PXA27x
+ SAVE(GPLR3); SAVE(GPDR3); SAVE(GRER3); SAVE(GFER3); SAVE(PGSR3);
+ SAVE(GAFR3_L); SAVE(GAFR3_U);
+#endif
+
SAVE(ICMR);
ICMR = 0;
SAVE(CKEN);
CKEN = 0;
+ SAVE(PSTR);
+
/* Note: wake up source are set up in each machine specific files */
/* clear GPIO transition detect bits */
GEDR0 = GEDR0; GEDR1 = GEDR1; GEDR2 = GEDR2;
+#ifdef CONFIG_PXA27x
+ GEDR3 = GEDR3;
+#endif
/* Clear sleep reset status */
RCSR = RCSR_SMR;
@@ -121,7 +144,8 @@ static int pxa_pm_enter(suspend_state_t state)
#ifdef CONFIG_ARCH_LUBBOCK
LUB_HEXLED = 0xbadbadc5;
#endif
- while (1);
+ while (1)
+ pxa_cpu_suspend();
}
/* ensure not to come back here if it wasn't intended */
@@ -135,6 +159,12 @@ static int pxa_pm_enter(suspend_state_t state)
RESTORE(GPDR0); RESTORE(GPDR1); RESTORE(GPDR2);
RESTORE(GRER0); RESTORE(GRER1); RESTORE(GRER2);
RESTORE(GFER0); RESTORE(GFER1); RESTORE(GFER2);
+ RESTORE(PGSR0); RESTORE(PGSR1); RESTORE(PGSR2);
+
+#ifdef CONFIG_PXA27x
+ RESTORE(GAFR3_L); RESTORE(GAFR3_U); RESTORE_GPLEVEL(3);
+ RESTORE(GPDR3); RESTORE(GRER3); RESTORE(GFER3); RESTORE(PGSR3);
+#endif
PSSR = PSSR_RDH | PSSR_PH;
@@ -144,6 +174,8 @@ static int pxa_pm_enter(suspend_state_t state)
ICCR = 1;
RESTORE(ICMR);
+ RESTORE(PSTR);
+
/* restore current time */
rtc.tv_sec = RCNR;
restore_time_delta(&delta, &rtc);
diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c
new file mode 100644
index 0000000000000..5ee67808224a9
--- /dev/null
+++ b/arch/arm/mach-pxa/poodle.c
@@ -0,0 +1,181 @@
+/*
+ * linux/arch/arm/mach-pxa/poodle.c
+ *
+ * Support for the SHARP Poodle Board.
+ *
+ * Based on:
+ * linux/arch/arm/mach-pxa/lubbock.c Author: Nicolas Pitre
+ *
+ * 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.
+ *
+ * Change Log
+ * 12-Dec-2002 Sharp Corporation for Poodle
+ * John Lenz <lenz@cs.wisc.edu> updates to 2.6
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/fb.h>
+
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+#include <asm/setup.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/arch/pxa-regs.h>
+#include <asm/arch/irq.h>
+#include <asm/arch/poodle.h>
+#include <asm/arch/pxafb.h>
+
+#include <asm/hardware/scoop.h>
+#include <asm/hardware/locomo.h>
+
+#include "generic.h"
+
+static struct resource poodle_scoop_resources[] = {
+ [0] = {
+ .start = 0x10800000,
+ .end = 0x10800fff,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct scoop_config poodle_scoop_setup = {
+ .io_dir = POODLE_SCOOP_IO_DIR,
+ .io_out = POODLE_SCOOP_IO_OUT,
+};
+
+struct platform_device poodle_scoop_device = {
+ .name = "sharp-scoop",
+ .id = -1,
+ .dev = {
+ .platform_data = &poodle_scoop_setup,
+ },
+ .num_resources = ARRAY_SIZE(poodle_scoop_resources),
+ .resource = poodle_scoop_resources,
+};
+
+
+/* LoCoMo device */
+static struct resource locomo_resources[] = {
+ [0] = {
+ .start = 0x10000000,
+ .end = 0x10001fff,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_GPIO(10),
+ .end = IRQ_GPIO(10),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device locomo_device = {
+ .name = "locomo",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(locomo_resources),
+ .resource = locomo_resources,
+};
+
+/* PXAFB device */
+static struct pxafb_mach_info poodle_fb_info __initdata = {
+ .pixclock = 144700,
+
+ .xres = 320,
+ .yres = 240,
+ .bpp = 16,
+
+ .hsync_len = 7,
+ .left_margin = 11,
+ .right_margin = 30,
+
+ .vsync_len = 2,
+ .upper_margin = 2,
+ .lower_margin = 0,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+
+ .lccr0 = LCCR0_Act | LCCR0_Sngl | LCCR0_Color,
+ .lccr3 = 0,
+
+ .pxafb_backlight_power = NULL,
+ .pxafb_lcd_power = NULL,
+};
+
+static struct platform_device *devices[] __initdata = {
+ &locomo_device,
+ &poodle_scoop_device,
+};
+
+static void __init poodle_init(void)
+{
+ int ret = 0;
+
+ /* cpu initialize */
+ /* Pgsr Register */
+ PGSR0 = 0x0146dd80;
+ PGSR1 = 0x03bf0890;
+ PGSR2 = 0x0001c000;
+
+ /* Alternate Register */
+ GAFR0_L = 0x01001000;
+ GAFR0_U = 0x591a8010;
+ GAFR1_L = 0x900a8451;
+ GAFR1_U = 0xaaa5aaaa;
+ GAFR2_L = 0x8aaaaaaa;
+ GAFR2_U = 0x00000002;
+
+ /* Direction Register */
+ GPDR0 = 0xd3f0904c;
+ GPDR1 = 0xfcffb7d3;
+ GPDR2 = 0x0001ffff;
+
+ /* Output Register */
+ GPCR0 = 0x00000000;
+ GPCR1 = 0x00000000;
+ GPCR2 = 0x00000000;
+
+ GPSR0 = 0x00400000;
+ GPSR1 = 0x00000000;
+ GPSR2 = 0x00000000;
+
+ set_pxa_fb_info(&poodle_fb_info);
+
+ ret = platform_add_devices(devices, ARRAY_SIZE(devices));
+ if (ret) {
+ printk(KERN_WARNING "poodle: Unable to register LoCoMo device\n");
+ }
+}
+
+static struct map_desc poodle_io_desc[] __initdata = {
+ /* virtual physical length */
+ { 0xef800000, 0x00000000, 0x00800000, MT_DEVICE }, /* Boot Flash */
+};
+
+static void __init poodle_map_io(void)
+{
+ pxa_map_io();
+ iotable_init(poodle_io_desc, ARRAY_SIZE(poodle_io_desc));
+
+ /* setup sleep mode values */
+ PWER = 0x00000002;
+ PFER = 0x00000000;
+ PRER = 0x00000002;
+ PGSR0 = 0x00008000;
+ PGSR1 = 0x003F0202;
+ PGSR2 = 0x0001C000;
+ PCFR |= PCFR_OPDE;
+}
+
+MACHINE_START(POODLE, "SHARP Poodle")
+ BOOT_MEM(0xa0000000, 0x40000000, io_p2v(0x40000000))
+ MAPIO(poodle_map_io)
+ INITIRQ(pxa_init_irq)
+ .timer = &pxa_timer,
+ .init_machine = poodle_init,
+MACHINE_END
diff --git a/arch/arm/mach-pxa/sleep.S b/arch/arm/mach-pxa/sleep.S
index be00614f5fc45..16cad2c2497cf 100644
--- a/arch/arm/mach-pxa/sleep.S
+++ b/arch/arm/mach-pxa/sleep.S
@@ -32,6 +32,7 @@ ENTRY(pxa_cpu_suspend)
stmfd sp!, {r2 - r12, lr} @ save registers on stack
@ get coprocessor registers
+ mrc p14, 0, r3, c6, c0, 0 @ clock configuration, for turbo mode
mrc p15, 0, r4, c15, c1, 0 @ CP access reg
mrc p15, 0, r5, c13, c0, 0 @ PID
mrc p15, 0, r6, c3, c0, 0 @ domain ID
@@ -39,9 +40,11 @@ ENTRY(pxa_cpu_suspend)
mrc p15, 0, r8, c1, c1, 0 @ auxiliary control reg
mrc p15, 0, r9, c1, c0, 0 @ control reg
+ bic r3, r3, #2 @ clear frequency change bit
+
@ store them plus current virtual stack ptr on stack
mov r10, sp
- stmfd sp!, {r4 - r10}
+ stmfd sp!, {r3 - r10}
@ preserve phys address of stack
mov r0, sp
@@ -90,10 +93,11 @@ ENTRY(pxa_cpu_suspend)
orrne r7, r7, #1 @@ 99.53MHz
@ get ready for the change
- @ note, since we are making turbo=run, do not remove the turbo
- @ as this may cause non-turbo mode on resume
- mrc p14, 0, r0, c6, c0, 0
- bic r0, r0, #2 @ clear change bit
+
+ @ note, turbo is not preserved over sleep so there is no
+ @ point in preserving it here. we save it on the stack with the
+ @ other CP registers instead.
+ mov r0, #0
mcr p14, 0, r0, c6, c0, 0
orr r0, r0, #2 @ initiate change bit
@@ -145,7 +149,7 @@ ENTRY(pxa_cpu_resume)
ldr r0, sleep_save_sp @ stack phys addr
ldr r2, =resume_after_mmu @ its absolute virtual address
- ldmfd r0, {r4 - r9, sp} @ CP regs + virt stack ptr
+ ldmfd r0, {r3 - r9, sp} @ CP regs + virt stack ptr
mov r1, #0
mcr p15, 0, r1, c8, c7, 0 @ invalidate I & D TLBs
@@ -155,6 +159,7 @@ ENTRY(pxa_cpu_resume)
bic r9, r9, #0x0004 @ see cpu_xscale_proc_init
#endif
+ mcr p14, 0, r3, c6, c0, 0 @ clock configuration, turbo mode.
mcr p15, 0, r4, c15, c1, 0 @ CP access reg
mcr p15, 0, r5, c13, c0, 0 @ PID
mcr p15, 0, r6, c3, c0, 0 @ domain ID
diff --git a/arch/arm/mach-rpc/dma.c b/arch/arm/mach-rpc/dma.c
index 62607a8a4bcc0..bc0747439fb36 100644
--- a/arch/arm/mach-rpc/dma.c
+++ b/arch/arm/mach-rpc/dma.c
@@ -254,7 +254,7 @@ static void floppy_enable_dma(dmach_t channel, dma_t *dma)
regs.ARM_r9 = dma->buf.length;
regs.ARM_r10 = (unsigned long)dma->buf.__address;
- regs.ARM_fp = FLOPPYDMA_BASE;
+ regs.ARM_fp = (unsigned long)FLOPPYDMA_BASE;
if (claim_fiq(&fh)) {
printk("floppydma: couldn't claim FIQ.\n");
diff --git a/arch/arm/mach-rpc/riscpc.c b/arch/arm/mach-rpc/riscpc.c
index 2f60dea2a8a1d..815c53225cd86 100644
--- a/arch/arm/mach-rpc/riscpc.c
+++ b/arch/arm/mach-rpc/riscpc.c
@@ -67,7 +67,7 @@ __tagtable(ATAG_ACORN, parse_tag_acorn);
static struct map_desc rpc_io_desc[] __initdata = {
{ SCREEN_BASE, SCREEN_START, 2*1048576, MT_DEVICE }, /* VRAM */
- { IO_BASE, IO_START, IO_SIZE , MT_DEVICE }, /* IO space */
+ { (u32)IO_BASE, IO_START, IO_SIZE , MT_DEVICE }, /* IO space */
{ EASI_BASE, EASI_START, EASI_SIZE, MT_DEVICE } /* EASI space */
};
diff --git a/arch/arm/mach-s3c2410/Kconfig b/arch/arm/mach-s3c2410/Kconfig
index b1b216ef05382..534df0c6c7705 100644
--- a/arch/arm/mach-s3c2410/Kconfig
+++ b/arch/arm/mach-s3c2410/Kconfig
@@ -19,6 +19,14 @@ config ARCH_H1940
<http://www.handhelds.org/projects/h1940.html>.
+config MACH_N30
+ bool "Acer N30"
+ select CPU_S3C2410
+ help
+ Say Y here if you are using the Acer N30
+
+ <http://zoo.weinigel.se/n30>.
+
config ARCH_SMDK2410
bool "SMDK2410/A9M2410"
select CPU_S3C2410
@@ -26,6 +34,12 @@ config ARCH_SMDK2410
Say Y here if you are using the SMDK2410 or the derived module A9M2410
<http://www.fsforth.de>
+config ARCH_S3C2440
+ bool "SMDK2440"
+ select CPU_S3C2440
+ help
+ Say Y here if you are using the SMDK2440.
+
config MACH_VR1000
bool "Thorcom VR1000"
select CPU_S3C2410
@@ -44,6 +58,18 @@ config MACH_RX3715
See <http://www.handhelds.org/projects/rx3715.html> for more
information on this project
+config MACH_OTOM
+ bool "NexVision OTOM Board"
+ select CPU_S3C2410
+ help
+ Say Y here if you are using the Nex Vision OTOM board
+
+config MACH_NEXCODER_2440
+ bool "NexVision NEXCODER 2440 Light Board"
+ select CPU_S3C2440
+ help
+ Say Y here if you are using the Nex Vision NEXCODER 2440 Light Board
+
endmenu
config CPU_S3C2410
@@ -59,6 +85,26 @@ config CPU_S3C2440
help
Support for S3C2440 Samsung Mobile CPU based systems.
+comment "S3C2410 Boot"
+
+config S3C2410_BOOT_WATCHDOG
+ bool "S3C2410 Initialisation watchdog"
+ depends on ARCH_S3C2410 && S3C2410_WATCHDOG
+ help
+ Say y to enable the watchdog during the kernel decompression
+ stage. If the kernel fails to uncompress, then the watchdog
+ will trigger a reset and the system should restart.
+
+ Although this uses the same hardware unit as the kernel watchdog
+ driver, it is not a replacement for it. If you use this option,
+ you will have to use the watchdg driver to either stop the timeout
+ or restart it. If you do not, then your kernel will reboot after
+ startup.
+
+ The driver uses a fixed timeout value, so the exact time till the
+ system resets depends on the value of PCLK. The timeout on an
+ 200MHz s3c2410 should be about 30 seconds.
+
comment "S3C2410 Setup"
config S3C2410_DMA
diff --git a/arch/arm/mach-s3c2410/Makefile b/arch/arm/mach-s3c2410/Makefile
index aa8b308740ac7..7c379aad5d629 100644
--- a/arch/arm/mach-s3c2410/Makefile
+++ b/arch/arm/mach-s3c2410/Makefile
@@ -27,6 +27,10 @@ obj-$(CONFIG_CPU_S3C2440) += s3c2440.o s3c2440-dsc.o
obj-$(CONFIG_ARCH_BAST) += mach-bast.o usb-simtec.o
obj-$(CONFIG_ARCH_H1940) += mach-h1940.o
+obj-$(CONFIG_MACH_N30) += mach-n30.o
obj-$(CONFIG_ARCH_SMDK2410) += mach-smdk2410.o
+obj-$(CONFIG_ARCH_S3C2440) += mach-smdk2440.o
obj-$(CONFIG_MACH_VR1000) += mach-vr1000.o usb-simtec.o
obj-$(CONFIG_MACH_RX3715) += mach-rx3715.o
+obj-$(CONFIG_MACH_OTOM) += mach-otom.o
+obj-$(CONFIG_MACH_NEXCODER_2440) += mach-nexcoder.o
diff --git a/arch/arm/mach-s3c2410/clock.c b/arch/arm/mach-s3c2410/clock.c
index f6d7470fe531a..e23f534d4e1d1 100644
--- a/arch/arm/mach-s3c2410/clock.c
+++ b/arch/arm/mach-s3c2410/clock.c
@@ -1,7 +1,7 @@
/* linux/arch/arm/mach-s3c2410/clock.c
*
- * Copyright (c) 2004 Simtec Electronics
- * Ben Dooks <ben@simtec.co.uk>
+ * Copyright (c) 2004-2005 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
*
* S3C2410 Clock control support
*
@@ -33,6 +33,7 @@
#include <linux/errno.h>
#include <linux/err.h>
#include <linux/device.h>
+#include <linux/sysdev.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
@@ -46,18 +47,13 @@
#include <asm/arch/regs-clock.h>
#include "clock.h"
+#include "cpu.h"
/* clock information */
-unsigned long s3c24xx_xtal = 12*1000*1000; /* default 12MHz */
-unsigned long s3c24xx_fclk;
-unsigned long s3c24xx_hclk;
-unsigned long s3c24xx_pclk;
-
static LIST_HEAD(clocks);
static DECLARE_MUTEX(clocks_sem);
-
/* old functions */
void inline s3c24xx_clk_enable(unsigned int clocks, unsigned int enable)
@@ -206,6 +202,14 @@ EXPORT_SYMBOL(clk_get_parent);
/* base clocks */
+static struct clk clk_xtal = {
+ .name = "xtal",
+ .id = -1,
+ .rate = 0,
+ .parent = NULL,
+ .ctrlbit = 0,
+};
+
static struct clk clk_f = {
.name = "fclk",
.id = -1,
@@ -286,6 +290,7 @@ static struct clk init_clocks[] = {
.ctrlbit = S3C2410_CLKCON_USBD
},
{ .name = "timers",
+ .id = -1,
.parent = &clk_p,
.enable = s3c24xx_clkcon_enable,
.ctrlbit = S3C2410_CLKCON_PWMT
@@ -378,19 +383,24 @@ int s3c24xx_register_clock(struct clk *clk)
/* initalise all the clocks */
-int __init s3c24xx_setup_clocks(void)
+int __init s3c24xx_setup_clocks(unsigned long xtal,
+ unsigned long fclk,
+ unsigned long hclk,
+ unsigned long pclk)
{
struct clk *clkp = init_clocks;
int ptr;
int ret;
- printk(KERN_INFO "S3C2410 Clock control, (c) 2004 Simtec Electronics\n");
+ printk(KERN_INFO "S3C2410 Clocks, (c) 2004 Simtec Electronics\n");
/* initialise the main system clocks */
- clk_h.rate = s3c24xx_hclk;
- clk_p.rate = s3c24xx_pclk;
- clk_f.rate = s3c24xx_fclk;
+ clk_xtal.rate = xtal;
+
+ clk_h.rate = hclk;
+ 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
@@ -414,6 +424,9 @@ int __init s3c24xx_setup_clocks(void)
/* register our clocks */
+ if (s3c24xx_register_clock(&clk_xtal) < 0)
+ printk(KERN_ERR "failed to register master xtal\n");
+
if (s3c24xx_register_clock(&clk_f) < 0)
printk(KERN_ERR "failed to register cpu fclk\n");
@@ -423,6 +436,8 @@ int __init s3c24xx_setup_clocks(void)
if (s3c24xx_register_clock(&clk_p) < 0)
printk(KERN_ERR "failed to register cpu pclk\n");
+ /* register clocks from clock array */
+
for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) {
ret = s3c24xx_register_clock(clkp);
if (ret < 0) {
@@ -434,4 +449,59 @@ int __init s3c24xx_setup_clocks(void)
return 0;
}
+/* S3C2440 extended clock support */
+
+#ifdef CONFIG_CPU_S3C2440
+
+static struct clk s3c2440_clk_upll = {
+ .name = "upll",
+ .id = -1,
+};
+
+static struct clk s3c2440_clk_cam = {
+ .name = "camif",
+ .parent = &clk_h,
+ .id = -1,
+ .enable = s3c24xx_clkcon_enable,
+ .ctrlbit = S3C2440_CLKCON_CAMERA,
+};
+
+static struct clk s3c2440_clk_ac97 = {
+ .name = "ac97",
+ .parent = &clk_p,
+ .id = -1,
+ .enable = s3c24xx_clkcon_enable,
+ .ctrlbit = S3C2440_CLKCON_CAMERA,
+};
+
+static int s3c2440_clk_add(struct sys_device *sysdev)
+{
+ unsigned long upllcon = __raw_readl(S3C2410_UPLLCON);
+
+ s3c2440_clk_upll.rate = s3c2410_get_pll(upllcon, clk_xtal.rate) * 2;
+
+ printk("S3C2440: Clock Support, UPLL %ld.%03ld MHz\n",
+ print_mhz(s3c2440_clk_upll.rate));
+
+ s3c24xx_register_clock(&s3c2440_clk_ac97);
+ s3c24xx_register_clock(&s3c2440_clk_cam);
+ s3c24xx_register_clock(&s3c2440_clk_upll);
+
+ clk_disable(&s3c2440_clk_ac97);
+ clk_disable(&s3c2440_clk_cam);
+
+ return 0;
+}
+
+static struct sysdev_driver s3c2440_clk_driver = {
+ .add = s3c2440_clk_add,
+};
+
+static int s3c24xx_clk_driver(void)
+{
+ return sysdev_driver_register(&s3c2440_sysclass, &s3c2440_clk_driver);
+}
+
+arch_initcall(s3c24xx_clk_driver);
+#endif /* CONFIG_CPU_S3C2440 */
diff --git a/arch/arm/mach-s3c2410/clock.h b/arch/arm/mach-s3c2410/clock.h
index eae2c83375697..7953b6f397b9b 100644
--- a/arch/arm/mach-s3c2410/clock.h
+++ b/arch/arm/mach-s3c2410/clock.h
@@ -1,7 +1,8 @@
/*
* linux/arch/arm/mach-s3c2410/clock.h
*
- * Copyright (c) 2004 Simtec Electronics
+ * Copyright (c) 2004-2005 Simtec Electronics
+ * http://www.simtec.co.uk/products/SWLINUX/
* Written by Ben Dooks, <ben@simtec.co.uk>
*
* This program is free software; you can redistribute it and/or modify
@@ -29,13 +30,6 @@ extern struct clk s3c24xx_clkout0;
extern struct clk s3c24xx_clkout1;
extern struct clk s3c24xx_uclk;
-/* processor clock settings, in Hz */
-
-extern unsigned long s3c24xx_xtal;
-extern unsigned long s3c24xx_pclk;
-extern unsigned long s3c24xx_hclk;
-extern unsigned long s3c24xx_fclk;
-
/* exports for arch/arm/mach-s3c2410
*
* Please DO NOT use these outside of arch/arm/mach-s3c2410
@@ -44,4 +38,7 @@ extern unsigned long s3c24xx_fclk;
extern int s3c24xx_clkcon_enable(struct clk *clk, int enable);
extern int s3c24xx_register_clock(struct clk *clk);
-extern int s3c24xx_setup_clocks(void);
+extern int s3c24xx_setup_clocks(unsigned long xtal,
+ unsigned long fclk,
+ unsigned long hclk,
+ unsigned long pclk);
diff --git a/arch/arm/mach-s3c2410/cpu.c b/arch/arm/mach-s3c2410/cpu.c
index 0a66065360c88..ca366e9e264da 100644
--- a/arch/arm/mach-s3c2410/cpu.c
+++ b/arch/arm/mach-s3c2410/cpu.c
@@ -1,7 +1,8 @@
/* linux/arch/arm/mach-s3c2410/cpu.c
*
- * Copyright (c) 2004 Simtec Electronics
- * Ben Dooks <ben@simtec.co.uk>
+ * Copyright (c) 2004-2005 Simtec Electronics
+ * http://www.simtec.co.uk/products/SWLINUX/
+ * Ben Dooks <ben@simtec.co.uk>
*
* S3C24XX CPU Support
*
@@ -181,8 +182,8 @@ void __init s3c24xx_init_io(struct map_desc *mach_desc, int size)
void __init s3c24xx_init_clocks(int xtal)
{
- if (xtal != 0)
- s3c24xx_xtal = xtal;
+ if (xtal == 0)
+ xtal = 12*1000*1000;
if (cpu == NULL)
panic("s3c24xx_init_clocks: no cpu setup?\n");
diff --git a/arch/arm/mach-s3c2410/cpu.h b/arch/arm/mach-s3c2410/cpu.h
index 4418be659fd13..478c15c0e36a3 100644
--- a/arch/arm/mach-s3c2410/cpu.h
+++ b/arch/arm/mach-s3c2410/cpu.h
@@ -15,9 +15,13 @@
* 04-Jan-2005 BJD New uart initialisation
* 10-Jan-2005 BJD Moved generic init here, specific to cpu headers
* 14-Jan-2005 BJD Added s3c24xx_init_clocks() call
+ * 10-Mar-2005 LCVR Changed S3C2410_{VA,SZ} to S3C24XX_{VA,SZ} & IODESC_ENT
+ * 14-Mar-2005 BJD Updated for __iomem
*/
-#define IODESC_ENT(x) { S3C2410_VA_##x, S3C2410_PA_##x, S3C2410_SZ_##x, MT_DEVICE }
+/* todo - fix when rmk changes iodescs to use `void __iomem *` */
+
+#define IODESC_ENT(x) { (unsigned long)S3C24XX_VA_##x, S3C2410_PA_##x, S3C24XX_SZ_##x, MT_DEVICE }
#ifndef MHZ
#define MHZ (1000*1000)
@@ -27,6 +31,7 @@
/* forward declaration */
struct s3c2410_uartcfg;
+struct map_desc;
/* core initialisation functions */
@@ -58,3 +63,7 @@ extern void s3c24xx_set_board(struct s3c24xx_board *board);
struct sys_timer;
extern struct sys_timer s3c24xx_timer;
+
+/* system device classes */
+
+extern struct sysdev_class s3c2440_sysclass;
diff --git a/arch/arm/mach-s3c2410/devs.c b/arch/arm/mach-s3c2410/devs.c
index b1826df99159b..64792f6786688 100644
--- a/arch/arm/mach-s3c2410/devs.c
+++ b/arch/arm/mach-s3c2410/devs.c
@@ -10,6 +10,8 @@
* published by the Free Software Foundation.
*
* Modifications:
+ * 10-Mar-2005 LCVR Changed S3C2410_{VA,SZ} to S3C24XX_{VA,SZ}
+ * 10-Feb-2005 BJD Added camera from guillaume.gourat@nexvision.tv
* 29-Aug-2004 BJD Added timers 0 through 3
* 29-Aug-2004 BJD Changed index of devices we only have one of to -1
* 21-Aug-2004 BJD Added IRQ_TICK to RTC resources
@@ -45,7 +47,7 @@ struct platform_device *s3c24xx_uart_devs[3];
static struct resource s3c_usb_resource[] = {
[0] = {
.start = S3C2410_PA_USBHOST,
- .end = S3C2410_PA_USBHOST + S3C2410_SZ_USBHOST,
+ .end = S3C2410_PA_USBHOST + S3C24XX_SZ_USBHOST,
.flags = IORESOURCE_MEM,
},
[1] = {
@@ -75,7 +77,7 @@ EXPORT_SYMBOL(s3c_device_usb);
static struct resource s3c_lcd_resource[] = {
[0] = {
.start = S3C2410_PA_LCD,
- .end = S3C2410_PA_LCD + S3C2410_SZ_LCD,
+ .end = S3C2410_PA_LCD + S3C24XX_SZ_LCD,
.flags = IORESOURCE_MEM,
},
[1] = {
@@ -106,7 +108,7 @@ EXPORT_SYMBOL(s3c_device_lcd);
static struct resource s3c_nand_resource[] = {
[0] = {
.start = S3C2410_PA_NAND,
- .end = S3C2410_PA_NAND + S3C2410_SZ_NAND,
+ .end = S3C2410_PA_NAND + S3C24XX_SZ_NAND,
.flags = IORESOURCE_MEM,
}
};
@@ -125,7 +127,7 @@ EXPORT_SYMBOL(s3c_device_nand);
static struct resource s3c_usbgadget_resource[] = {
[0] = {
.start = S3C2410_PA_USBDEV,
- .end = S3C2410_PA_USBDEV + S3C2410_SZ_USBDEV,
+ .end = S3C2410_PA_USBDEV + S3C24XX_SZ_USBDEV,
.flags = IORESOURCE_MEM,
},
[1] = {
@@ -150,7 +152,7 @@ EXPORT_SYMBOL(s3c_device_usbgadget);
static struct resource s3c_wdt_resource[] = {
[0] = {
.start = S3C2410_PA_WATCHDOG,
- .end = S3C2410_PA_WATCHDOG + S3C2410_SZ_WATCHDOG,
+ .end = S3C2410_PA_WATCHDOG + S3C24XX_SZ_WATCHDOG,
.flags = IORESOURCE_MEM,
},
[1] = {
@@ -175,7 +177,7 @@ EXPORT_SYMBOL(s3c_device_wdt);
static struct resource s3c_i2c_resource[] = {
[0] = {
.start = S3C2410_PA_IIC,
- .end = S3C2410_PA_IIC + S3C2410_SZ_IIC,
+ .end = S3C2410_PA_IIC + S3C24XX_SZ_IIC,
.flags = IORESOURCE_MEM,
},
[1] = {
@@ -200,7 +202,7 @@ EXPORT_SYMBOL(s3c_device_i2c);
static struct resource s3c_iis_resource[] = {
[0] = {
.start = S3C2410_PA_IIS,
- .end = S3C2410_PA_IIS + S3C2410_SZ_IIS,
+ .end = S3C2410_PA_IIS + S3C24XX_SZ_IIS,
.flags = IORESOURCE_MEM,
}
};
@@ -254,7 +256,7 @@ EXPORT_SYMBOL(s3c_device_rtc);
static struct resource s3c_adc_resource[] = {
[0] = {
.start = S3C2410_PA_ADC,
- .end = S3C2410_PA_ADC + S3C2410_SZ_ADC,
+ .end = S3C2410_PA_ADC + S3C24XX_SZ_ADC,
.flags = IORESOURCE_MEM,
},
[1] = {
@@ -277,7 +279,7 @@ struct platform_device s3c_device_adc = {
static struct resource s3c_sdi_resource[] = {
[0] = {
.start = S3C2410_PA_SDI,
- .end = S3C2410_PA_SDI + S3C2410_SZ_SDI,
+ .end = S3C2410_PA_SDI + S3C24XX_SZ_SDI,
.flags = IORESOURCE_MEM,
},
[1] = {
@@ -446,3 +448,38 @@ struct platform_device s3c_device_timer3 = {
};
EXPORT_SYMBOL(s3c_device_timer3);
+
+#ifdef CONFIG_CPU_S3C2440
+
+/* Camif Controller */
+
+static struct resource s3c_camif_resource[] = {
+ [0] = {
+ .start = S3C2440_PA_CAMIF,
+ .end = S3C2440_PA_CAMIF + S3C2440_SZ_CAMIF,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_CAM,
+ .end = IRQ_CAM,
+ .flags = IORESOURCE_IRQ,
+ }
+
+};
+
+static u64 s3c_device_camif_dmamask = 0xffffffffUL;
+
+struct platform_device s3c_device_camif = {
+ .name = "s3c2440-camif",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(s3c_camif_resource),
+ .resource = s3c_camif_resource,
+ .dev = {
+ .dma_mask = &s3c_device_camif_dmamask,
+ .coherent_dma_mask = 0xffffffffUL
+ }
+};
+
+EXPORT_SYMBOL(s3c_device_camif);
+
+#endif // CONFIG_CPU_S32440
diff --git a/arch/arm/mach-s3c2410/devs.h b/arch/arm/mach-s3c2410/devs.h
index 08a4416595f8c..d6328f96728bf 100644
--- a/arch/arm/mach-s3c2410/devs.h
+++ b/arch/arm/mach-s3c2410/devs.h
@@ -12,7 +12,11 @@
* Modifications:
* 18-Aug-2004 BJD Created initial version
* 27-Aug-2004 BJD Added timers 0 through 3
+ * 10-Feb-2005 BJD Added camera from guillaume.gourat@nexvision.tv
*/
+#include <linux/config.h>
+
+extern struct platform_device *s3c24xx_uart_devs[];
extern struct platform_device s3c_device_usb;
extern struct platform_device s3c_device_lcd;
@@ -34,3 +38,11 @@ extern struct platform_device s3c_device_timer2;
extern struct platform_device s3c_device_timer3;
extern struct platform_device s3c_device_usbgadget;
+
+/* s3c2440 specific devices */
+
+#ifdef CONFIG_CPU_S3C2440
+
+extern struct platform_device s3c_device_camif;
+
+#endif
diff --git a/arch/arm/mach-s3c2410/dma.c b/arch/arm/mach-s3c2410/dma.c
index bc8cb6868e955..5ecfa58371160 100644
--- a/arch/arm/mach-s3c2410/dma.c
+++ b/arch/arm/mach-s3c2410/dma.c
@@ -1,6 +1,6 @@
/* linux/arch/arm/mach-bast/dma.c
*
- * (c) 2003,2004 Simtec Electronics
+ * (c) 2003-2005 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
*
* S3C2410 DMA core
@@ -12,6 +12,7 @@
* published by the Free Software Foundation.
*
* Changelog:
+ * 27-Feb-2005 BJD Added kmem cache for dma descriptors
* 18-Nov-2004 BJD Removed error for loading onto stopped channel
* 10-Nov-2004 BJD Ensure all external symbols exported for modules
* 10-Nov-2004 BJD Use sys_device and sysdev_class for power management
@@ -57,6 +58,7 @@
/* io map for dma */
static void __iomem *dma_base;
+static kmem_cache_t *dma_kmem;
/* dma channel state information */
s3c2410_dma_chan_t s3c2410_chans[S3C2410_DMA_CHANNELS];
@@ -432,7 +434,7 @@ int s3c2410_dma_enqueue(unsigned int channel, void *id,
pr_debug("%s: id=%p, data=%08x, size=%d\n",
__FUNCTION__, id, (unsigned int)data, size);
- buf = (s3c2410_dma_buf_t *)kmalloc(sizeof(*buf), GFP_ATOMIC);
+ buf = kmem_cache_alloc(dma_kmem, GFP_ATOMIC);
if (buf == NULL) {
pr_debug("%s: out of memory (%d alloc)\n",
__FUNCTION__, sizeof(*buf));
@@ -511,7 +513,7 @@ s3c2410_dma_freebuf(s3c2410_dma_buf_t *buf)
buf->magic = -1;
if (magicok) {
- kfree(buf);
+ kmem_cache_free(dma_kmem, buf);
} else {
printk("s3c2410_dma_freebuf: buff %p with bad magic\n", buf);
}
@@ -1128,6 +1130,14 @@ static struct sysdev_class dma_sysclass = {
.resume = s3c2410_dma_resume,
};
+/* kmem cache implementation */
+
+static void s3c2410_dma_cache_ctor(void *p, kmem_cache_t *c, unsigned long f)
+{
+ memset(p, 0, sizeof(s3c2410_dma_buf_t));
+}
+
+
/* initialisation code */
static int __init s3c2410_init_dma(void)
@@ -1150,6 +1160,16 @@ static int __init s3c2410_init_dma(void)
goto err;
}
+ dma_kmem = kmem_cache_create("dma_desc", sizeof(s3c2410_dma_buf_t), 0,
+ SLAB_HWCACHE_ALIGN,
+ s3c2410_dma_cache_ctor, NULL);
+
+ if (dma_kmem == NULL) {
+ printk(KERN_ERR "dma failed to make kmem cache\n");
+ ret = -ENOMEM;
+ goto err;
+ }
+
for (channel = 0; channel < S3C2410_DMA_CHANNELS; channel++) {
cp = &s3c2410_chans[channel];
@@ -1181,6 +1201,7 @@ static int __init s3c2410_init_dma(void)
return 0;
err:
+ kmem_cache_destroy(dma_kmem);
iounmap(dma_base);
dma_base = NULL;
return ret;
diff --git a/arch/arm/mach-s3c2410/gpio.c b/arch/arm/mach-s3c2410/gpio.c
index 129f29dbd3f87..94f1776cf3127 100644
--- a/arch/arm/mach-s3c2410/gpio.c
+++ b/arch/arm/mach-s3c2410/gpio.c
@@ -1,7 +1,7 @@
/* linux/arch/arm/mach-s3c2410/gpio.c
*
- * Copyright (c) 2004 Simtec Electronics
- * Ben Dooks <ben@simtec.co.uk>
+ * Copyright (c) 2004-2005 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
*
* S3C2410 GPIO support
*
@@ -29,9 +29,11 @@
* 01-Oct-2004 BJD Added getirq() to turn pin into irqno
* 04-Oct-2004 BJD Added irq filter controls for GPIO
* 05-Nov-2004 BJD EXPORT_SYMBOL() added for all code
+ * 13-Mar-2005 BJD Updates for __iomem
*/
+#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/interrupt.h>
@@ -45,7 +47,7 @@
void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function)
{
- unsigned long base = S3C2410_GPIO_BASE(pin);
+ void __iomem *base = S3C2410_GPIO_BASE(pin);
unsigned long mask;
unsigned long con;
unsigned long flags;
@@ -71,7 +73,7 @@ EXPORT_SYMBOL(s3c2410_gpio_cfgpin);
unsigned int s3c2410_gpio_getcfg(unsigned int pin)
{
- unsigned long base = S3C2410_GPIO_BASE(pin);
+ void __iomem *base = S3C2410_GPIO_BASE(pin);
unsigned long mask;
if (pin < S3C2410_GPIO_BANKB) {
@@ -87,7 +89,7 @@ EXPORT_SYMBOL(s3c2410_gpio_getcfg);
void s3c2410_gpio_pullup(unsigned int pin, unsigned int to)
{
- unsigned long base = S3C2410_GPIO_BASE(pin);
+ void __iomem *base = S3C2410_GPIO_BASE(pin);
unsigned long offs = S3C2410_GPIO_OFFSET(pin);
unsigned long flags;
unsigned long up;
@@ -109,7 +111,7 @@ EXPORT_SYMBOL(s3c2410_gpio_pullup);
void s3c2410_gpio_setpin(unsigned int pin, unsigned int to)
{
- unsigned long base = S3C2410_GPIO_BASE(pin);
+ void __iomem *base = S3C2410_GPIO_BASE(pin);
unsigned long offs = S3C2410_GPIO_OFFSET(pin);
unsigned long flags;
unsigned long dat;
@@ -128,7 +130,7 @@ EXPORT_SYMBOL(s3c2410_gpio_setpin);
unsigned int s3c2410_gpio_getpin(unsigned int pin)
{
- unsigned long base = S3C2410_GPIO_BASE(pin);
+ void __iomem *base = S3C2410_GPIO_BASE(pin);
unsigned long offs = S3C2410_GPIO_OFFSET(pin);
return __raw_readl(base + 0x04) & (1<< offs);
@@ -175,7 +177,7 @@ EXPORT_SYMBOL(s3c2410_gpio_getirq);
int s3c2410_gpio_irqfilter(unsigned int pin, unsigned int on,
unsigned int config)
{
- unsigned long reg = S3C2410_EINFLT0;
+ void __iomem *reg = S3C2410_EINFLT0;
unsigned long flags;
unsigned long val;
diff --git a/arch/arm/mach-s3c2410/irq.c b/arch/arm/mach-s3c2410/irq.c
index 6b0b93e5aa415..b668c48f43990 100644
--- a/arch/arm/mach-s3c2410/irq.c
+++ b/arch/arm/mach-s3c2410/irq.c
@@ -39,6 +39,9 @@
*
* 04-Nov-2004 Ben Dooks
* Fix standard IRQ wake for EINT0..4 and RTC
+ *
+ * 22-Feb-2004 Ben Dooks
+ * Fixed edge-triggering on ADC IRQ
*/
#include <linux/init.h>
@@ -57,6 +60,7 @@
#include <asm/arch/regs-irq.h>
#include <asm/arch/regs-gpio.h>
+#include "cpu.h"
#include "pm.h"
#define irqdbf(x...)
@@ -261,8 +265,8 @@ s3c_irqext_unmask(unsigned int irqno)
static int
s3c_irqext_type(unsigned int irq, unsigned int type)
{
- unsigned long extint_reg;
- unsigned long gpcon_reg;
+ void __iomem *extint_reg;
+ void __iomem *gpcon_reg;
unsigned long gpcon_offset, extint_offset;
unsigned long newvalue = 0, value;
@@ -425,6 +429,23 @@ s3c_irqsub_maskack(unsigned int irqno, unsigned int parentmask, unsigned int gro
}
}
+static inline void
+s3c_irqsub_ack(unsigned int irqno, unsigned int parentmask, unsigned int group)
+{
+ unsigned int bit = 1UL << (irqno - IRQ_S3CUART_RX0);
+
+ __raw_writel(bit, S3C2410_SUBSRCPND);
+
+ /* only ack parent if we've got all the irqs (seems we must
+ * ack, all and hope that the irq system retriggers ok when
+ * the interrupt goes off again)
+ */
+
+ if (1) {
+ __raw_writel(parentmask, S3C2410_SRCPND);
+ __raw_writel(parentmask, S3C2410_INTPND);
+ }
+}
/* UART0 */
@@ -521,7 +542,7 @@ s3c_irq_adc_unmask(unsigned int irqno)
static void
s3c_irq_adc_ack(unsigned int irqno)
{
- s3c_irqsub_maskack(irqno, INTMSK_ADCPARENT, 3 << 9);
+ s3c_irqsub_ack(irqno, INTMSK_ADCPARENT, 3 << 9);
}
static struct irqchip s3c_irq_adc = {
@@ -628,6 +649,7 @@ s3c_irq_demux_uart2(unsigned int irq,
s3c_irq_demux_uart(IRQ_S3CUART_RX2, regs);
}
+
/* s3c24xx_init_irq
*
* Initialise S3C2410 IRQ system
@@ -771,3 +793,174 @@ void __init s3c24xx_init_irq(void)
irqdbf("s3c2410: registered interrupt handlers\n");
}
+
+/* s3c2440 irq code
+*/
+
+#ifdef CONFIG_CPU_S3C2440
+
+/* WDT/AC97 */
+
+static void s3c_irq_demux_wdtac97(unsigned int irq,
+ struct irqdesc *desc,
+ struct pt_regs *regs)
+{
+ unsigned int subsrc, submsk;
+ struct irqdesc *mydesc;
+
+ /* read the current pending interrupts, and the mask
+ * for what it is available */
+
+ subsrc = __raw_readl(S3C2410_SUBSRCPND);
+ submsk = __raw_readl(S3C2410_INTSUBMSK);
+
+ subsrc &= ~submsk;
+ subsrc >>= 13;
+ subsrc &= 3;
+
+ if (subsrc != 0) {
+ if (subsrc & 1) {
+ mydesc = irq_desc + IRQ_S3C2440_WDT;
+ mydesc->handle( IRQ_S3C2440_WDT, mydesc, regs);
+ }
+ if (subsrc & 2) {
+ mydesc = irq_desc + IRQ_S3C2440_AC97;
+ mydesc->handle(IRQ_S3C2440_AC97, mydesc, regs);
+ }
+ }
+}
+
+
+#define INTMSK_WDT (1UL << (IRQ_WDT - IRQ_EINT0))
+
+static void
+s3c_irq_wdtac97_mask(unsigned int irqno)
+{
+ s3c_irqsub_mask(irqno, INTMSK_WDT, 3<<13);
+}
+
+static void
+s3c_irq_wdtac97_unmask(unsigned int irqno)
+{
+ s3c_irqsub_unmask(irqno, INTMSK_WDT);
+}
+
+static void
+s3c_irq_wdtac97_ack(unsigned int irqno)
+{
+ s3c_irqsub_maskack(irqno, INTMSK_WDT, 3<<13);
+}
+
+static struct irqchip s3c_irq_wdtac97 = {
+ .mask = s3c_irq_wdtac97_mask,
+ .unmask = s3c_irq_wdtac97_unmask,
+ .ack = s3c_irq_wdtac97_ack,
+};
+
+/* camera irq */
+
+static void s3c_irq_demux_cam(unsigned int irq,
+ struct irqdesc *desc,
+ struct pt_regs *regs)
+{
+ unsigned int subsrc, submsk;
+ struct irqdesc *mydesc;
+
+ /* read the current pending interrupts, and the mask
+ * for what it is available */
+
+ subsrc = __raw_readl(S3C2410_SUBSRCPND);
+ submsk = __raw_readl(S3C2410_INTSUBMSK);
+
+ subsrc &= ~submsk;
+ subsrc >>= 11;
+ subsrc &= 3;
+
+ if (subsrc != 0) {
+ if (subsrc & 1) {
+ mydesc = irq_desc + IRQ_S3C2440_CAM_C;
+ mydesc->handle( IRQ_S3C2440_WDT, mydesc, regs);
+ }
+ if (subsrc & 2) {
+ mydesc = irq_desc + IRQ_S3C2440_CAM_P;
+ mydesc->handle(IRQ_S3C2440_AC97, mydesc, regs);
+ }
+ }
+}
+
+#define INTMSK_CAM (1UL << (IRQ_CAM - IRQ_EINT0))
+
+static void
+s3c_irq_cam_mask(unsigned int irqno)
+{
+ s3c_irqsub_mask(irqno, INTMSK_CAM, 3<<11);
+}
+
+static void
+s3c_irq_cam_unmask(unsigned int irqno)
+{
+ s3c_irqsub_unmask(irqno, INTMSK_CAM);
+}
+
+static void
+s3c_irq_cam_ack(unsigned int irqno)
+{
+ s3c_irqsub_maskack(irqno, INTMSK_CAM, 3<<11);
+}
+
+static struct irqchip s3c_irq_cam = {
+ .mask = s3c_irq_cam_mask,
+ .unmask = s3c_irq_cam_unmask,
+ .ack = s3c_irq_cam_ack,
+};
+
+static int s3c2440_irq_add(struct sys_device *sysdev)
+{
+ unsigned int irqno;
+
+ printk("S3C2440: IRQ Support\n");
+
+ set_irq_chip(IRQ_NFCON, &s3c_irq_level_chip);
+ set_irq_handler(IRQ_NFCON, do_level_IRQ);
+ set_irq_flags(IRQ_NFCON, IRQF_VALID);
+
+ /* add new chained handler for wdt, ac7 */
+
+ set_irq_chip(IRQ_WDT, &s3c_irq_level_chip);
+ set_irq_handler(IRQ_WDT, do_level_IRQ);
+ set_irq_chained_handler(IRQ_WDT, s3c_irq_demux_wdtac97);
+
+ for (irqno = IRQ_S3C2440_WDT; irqno <= IRQ_S3C2440_AC97; irqno++) {
+ set_irq_chip(irqno, &s3c_irq_wdtac97);
+ set_irq_handler(irqno, do_level_IRQ);
+ set_irq_flags(irqno, IRQF_VALID);
+ }
+
+ /* add chained handler for camera */
+
+ set_irq_chip(IRQ_CAM, &s3c_irq_level_chip);
+ set_irq_handler(IRQ_CAM, do_level_IRQ);
+ set_irq_chained_handler(IRQ_CAM, s3c_irq_demux_cam);
+
+ for (irqno = IRQ_S3C2440_CAM_C; irqno <= IRQ_S3C2440_CAM_P; irqno++) {
+ set_irq_chip(irqno, &s3c_irq_cam);
+ set_irq_handler(irqno, do_level_IRQ);
+ set_irq_flags(irqno, IRQF_VALID);
+ }
+
+ return 0;
+}
+
+static struct sysdev_driver s3c2440_irq_driver = {
+ .add = s3c2440_irq_add,
+};
+
+static int s3c24xx_irq_driver(void)
+{
+ return sysdev_driver_register(&s3c2440_sysclass, &s3c2440_irq_driver);
+}
+
+arch_initcall(s3c24xx_irq_driver);
+
+#endif /* CONFIG_CPU_S3C2440 */
+
diff --git a/arch/arm/mach-s3c2410/mach-bast.c b/arch/arm/mach-s3c2410/mach-bast.c
index 96292e6323434..3bb97eb6e6932 100644
--- a/arch/arm/mach-s3c2410/mach-bast.c
+++ b/arch/arm/mach-s3c2410/mach-bast.c
@@ -23,6 +23,9 @@
* 04-Jan-2005 BJD New uart init call
* 10-Jan-2005 BJD Removed include of s3c2410.h
* 14-Jan-2005 BJD Add support for muitlple NAND devices
+ * 03-Mar-2005 BJD Ensured that bast-cpld.h is included
+ * 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA
+ * 14-Mar-2006 BJD Updated for __iomem changes
*/
#include <linux/kernel.h>
@@ -39,6 +42,7 @@
#include <asm/arch/bast-map.h>
#include <asm/arch/bast-irq.h>
+#include <asm/arch/bast-cpld.h>
#include <asm/hardware.h>
#include <asm/io.h>
@@ -65,10 +69,10 @@
#define COPYRIGHT ", (c) 2004-2005 Simtec Electronics"
/* macros for virtual address mods for the io space entries */
-#define VA_C5(item) ((item) + BAST_VAM_CS5)
-#define VA_C4(item) ((item) + BAST_VAM_CS4)
-#define VA_C3(item) ((item) + BAST_VAM_CS3)
-#define VA_C2(item) ((item) + BAST_VAM_CS2)
+#define VA_C5(item) ((unsigned long)(item) + BAST_VAM_CS5)
+#define VA_C4(item) ((unsigned long)(item) + BAST_VAM_CS4)
+#define VA_C3(item) ((unsigned long)(item) + BAST_VAM_CS3)
+#define VA_C2(item) ((unsigned long)(item) + BAST_VAM_CS2)
/* macros to modify the physical addresses for io space */
@@ -80,8 +84,8 @@
static struct map_desc bast_iodesc[] __initdata = {
/* ISA IO areas */
- { S3C2410_VA_ISA_BYTE, PA_CS2(BAST_PA_ISAIO), SZ_16M, MT_DEVICE },
- { S3C2410_VA_ISA_WORD, PA_CS3(BAST_PA_ISAIO), SZ_16M, MT_DEVICE },
+ { (u32)S3C24XX_VA_ISA_BYTE, PA_CS2(BAST_PA_ISAIO), SZ_16M, MT_DEVICE },
+ { (u32)S3C24XX_VA_ISA_WORD, PA_CS3(BAST_PA_ISAIO), SZ_16M, MT_DEVICE },
/* we could possibly compress the next set down into a set of smaller tables
* pagetables, but that would mean using an L2 section, and it still means
@@ -89,26 +93,15 @@ static struct map_desc bast_iodesc[] __initdata = {
*/
/* bast CPLD control registers, and external interrupt controls */
- { BAST_VA_CTRL1, BAST_PA_CTRL1, SZ_1M, MT_DEVICE },
- { BAST_VA_CTRL2, BAST_PA_CTRL2, SZ_1M, MT_DEVICE },
- { BAST_VA_CTRL3, BAST_PA_CTRL3, SZ_1M, MT_DEVICE },
- { BAST_VA_CTRL4, BAST_PA_CTRL4, SZ_1M, MT_DEVICE },
+ { (u32)BAST_VA_CTRL1, BAST_PA_CTRL1, SZ_1M, MT_DEVICE },
+ { (u32)BAST_VA_CTRL2, BAST_PA_CTRL2, SZ_1M, MT_DEVICE },
+ { (u32)BAST_VA_CTRL3, BAST_PA_CTRL3, SZ_1M, MT_DEVICE },
+ { (u32)BAST_VA_CTRL4, BAST_PA_CTRL4, SZ_1M, MT_DEVICE },
/* PC104 IRQ mux */
- { BAST_VA_PC104_IRQREQ, BAST_PA_PC104_IRQREQ, SZ_1M, MT_DEVICE },
- { BAST_VA_PC104_IRQRAW, BAST_PA_PC104_IRQRAW, SZ_1M, MT_DEVICE },
- { BAST_VA_PC104_IRQMASK, BAST_PA_PC104_IRQMASK, SZ_1M, MT_DEVICE },
-
- /* onboard 8bit lcd port */
-
- { BAST_VA_LCD_RCMD1, BAST_PA_LCD_RCMD1, SZ_1M, MT_DEVICE },
- { BAST_VA_LCD_WCMD1, BAST_PA_LCD_WCMD1, SZ_1M, MT_DEVICE },
- { BAST_VA_LCD_RDATA1, BAST_PA_LCD_RDATA1, SZ_1M, MT_DEVICE },
- { BAST_VA_LCD_WDATA1, BAST_PA_LCD_WDATA1, SZ_1M, MT_DEVICE },
- { BAST_VA_LCD_RCMD2, BAST_PA_LCD_RCMD2, SZ_1M, MT_DEVICE },
- { BAST_VA_LCD_WCMD2, BAST_PA_LCD_WCMD2, SZ_1M, MT_DEVICE },
- { BAST_VA_LCD_RDATA2, BAST_PA_LCD_RDATA2, SZ_1M, MT_DEVICE },
- { BAST_VA_LCD_WDATA2, BAST_PA_LCD_WDATA2, SZ_1M, MT_DEVICE },
+ { (u32)BAST_VA_PC104_IRQREQ, BAST_PA_PC104_IRQREQ, SZ_1M, MT_DEVICE },
+ { (u32)BAST_VA_PC104_IRQRAW, BAST_PA_PC104_IRQRAW, SZ_1M, MT_DEVICE },
+ { (u32)BAST_VA_PC104_IRQMASK, BAST_PA_PC104_IRQMASK, SZ_1M, MT_DEVICE },
/* peripheral space... one for each of fast/slow/byte/16bit */
/* note, ide is only decoded in word space, even though some registers
@@ -407,7 +400,7 @@ static __init void bast_init_machine(void)
MACHINE_START(BAST, "Simtec-BAST")
MAINTAINER("Ben Dooks <ben@simtec.co.uk>")
- BOOT_MEM(S3C2410_SDRAM_PA, S3C2410_PA_UART, S3C2410_VA_UART)
+ BOOT_MEM(S3C2410_SDRAM_PA, S3C2410_PA_UART, (u32)S3C24XX_VA_UART)
BOOT_PARAMS(S3C2410_SDRAM_PA + 0x100)
MAPIO(bast_map_io)
INITIRQ(bast_init_irq)
diff --git a/arch/arm/mach-s3c2410/mach-h1940.c b/arch/arm/mach-s3c2410/mach-h1940.c
index e834c00c30198..2924afc068a43 100644
--- a/arch/arm/mach-s3c2410/mach-h1940.c
+++ b/arch/arm/mach-s3c2410/mach-h1940.c
@@ -23,6 +23,7 @@
* 04-Jan-2005 BJD Updated uart init call
* 10-Jan-2005 BJD Removed include of s3c2410.h
* 14-Jan-2005 BJD Added clock init
+ * 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA
*/
#include <linux/kernel.h>
@@ -117,7 +118,7 @@ void __init h1940_init_irq(void)
MACHINE_START(H1940, "IPAQ-H1940")
MAINTAINER("Ben Dooks <ben@fluff.org>")
- BOOT_MEM(S3C2410_SDRAM_PA, S3C2410_PA_UART, S3C2410_VA_UART)
+ BOOT_MEM(S3C2410_SDRAM_PA, S3C2410_PA_UART, (u32)S3C24XX_VA_UART)
BOOT_PARAMS(S3C2410_SDRAM_PA + 0x100)
MAPIO(h1940_map_io)
INITIRQ(h1940_init_irq)
diff --git a/arch/arm/mach-s3c2410/mach-n30.c b/arch/arm/mach-s3c2410/mach-n30.c
new file mode 100644
index 0000000000000..bd15998c129bc
--- /dev/null
+++ b/arch/arm/mach-s3c2410/mach-n30.c
@@ -0,0 +1,155 @@
+/* linux/arch/arm/mach-s3c2410/mach-n30.c
+ *
+ * Copyright (c) 2003-2005 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * Copyright (c) 2005 Christer Weinigel <christer@weinigel.se>
+ *
+ * There is a wiki with more information about the n30 port at
+ * http://handhelds.org/moin/moin.cgi/AcerN30Documentation .
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/kthread.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/hardware.h>
+#include <asm/hardware/iomd.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+
+#include <asm/arch/regs-serial.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/iic.h>
+
+#include <linux/serial_core.h>
+
+#include "s3c2410.h"
+#include "clock.h"
+#include "devs.h"
+#include "cpu.h"
+
+static struct map_desc n30_iodesc[] __initdata = {
+ /* nothing here yet */
+};
+
+static struct s3c2410_uartcfg n30_uartcfgs[] = {
+ /* Normal serial port */
+ [0] = {
+ .hwport = 0,
+ .flags = 0,
+ .ucon = 0x2c5,
+ .ulcon = 0x03,
+ .ufcon = 0x51,
+ },
+ /* IR port */
+ [1] = {
+ .hwport = 1,
+ .flags = 0,
+ .uart_flags = UPF_CONS_FLOW,
+ .ucon = 0x2c5,
+ .ulcon = 0x43,
+ .ufcon = 0x51,
+ },
+ /* The BlueTooth controller is connected to port 2 */
+ [2] = {
+ .hwport = 2,
+ .flags = 0,
+ .ucon = 0x2c5,
+ .ulcon = 0x03,
+ .ufcon = 0x51,
+ },
+};
+
+static struct platform_device *n30_devices[] __initdata = {
+ &s3c_device_usb,
+ &s3c_device_lcd,
+ &s3c_device_wdt,
+ &s3c_device_i2c,
+ &s3c_device_iis,
+ &s3c_device_usbgadget,
+};
+
+static struct s3c2410_platform_i2c n30_i2ccfg = {
+ .flags = 0,
+ .slave_addr = 0x10,
+ .bus_freq = 10*1000,
+ .max_freq = 10*1000,
+};
+
+static struct s3c24xx_board n30_board __initdata = {
+ .devices = n30_devices,
+ .devices_count = ARRAY_SIZE(n30_devices)
+};
+
+void __init n30_map_io(void)
+{
+ s3c24xx_init_io(n30_iodesc, ARRAY_SIZE(n30_iodesc));
+ s3c24xx_init_clocks(0);
+ s3c24xx_init_uarts(n30_uartcfgs, ARRAY_SIZE(n30_uartcfgs));
+ s3c24xx_set_board(&n30_board);
+}
+
+void __init n30_init_irq(void)
+{
+ s3c24xx_init_irq();
+}
+
+
+static int n30_usbstart_thread(void *unused)
+{
+ /* Turn off suspend on both USB ports, and switch the
+ * selectable USB port to USB device mode. */
+ writel(readl(S3C2410_MISCCR) & ~0x00003008, S3C2410_MISCCR);
+
+ /* Turn off the D+ pull up for 3 seconds so that the USB host
+ * at the other end will do a rescan of the USB bus. */
+ s3c2410_gpio_setpin(S3C2410_GPB3, 0);
+
+ msleep_interruptible(3*HZ);
+
+ s3c2410_gpio_setpin(S3C2410_GPB3, 1);
+
+ return 0;
+}
+
+
+void __init n30_init(void)
+{
+ s3c_device_i2c.dev.platform_data = &n30_i2ccfg;
+
+ kthread_run(n30_usbstart_thread, NULL, "n30_usbstart");
+}
+
+MACHINE_START(N30, "Acer-N30")
+ MAINTAINER("Christer Weinigel <christer@weinigel.se>, Ben Dooks <ben-linux@fluff.org>")
+ BOOT_MEM(S3C2410_SDRAM_PA, S3C2410_PA_UART, (u32)S3C24XX_VA_UART)
+ BOOT_PARAMS(S3C2410_SDRAM_PA + 0x100)
+
+ .timer = &s3c24xx_timer,
+ .init_machine = n30_init,
+ .init_irq = n30_init_irq,
+ .map_io = n30_map_io,
+MACHINE_END
+
+/*
+ Local variables:
+ compile-command: "make ARCH=arm CROSS_COMPILE=/usr/local/arm/3.3.2/bin/arm-linux- -k -C ../../.."
+ c-basic-offset: 8
+ End:
+*/
diff --git a/arch/arm/mach-s3c2410/mach-nexcoder.c b/arch/arm/mach-s3c2410/mach-nexcoder.c
new file mode 100644
index 0000000000000..70487bf4b71ec
--- /dev/null
+++ b/arch/arm/mach-s3c2410/mach-nexcoder.c
@@ -0,0 +1,156 @@
+/* linux/arch/arm/mach-s3c2410/mach-nexcoder.c
+ *
+ * Copyright (c) 2004 Nex Vision
+ * Guillaume GOURAT <guillaume.gourat@nexvision.tv>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Modifications:
+ * 15-10-2004 GG Created initial version
+ * 12-03-2005 BJD Updated for release
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/device.h>
+
+#include <linux/mtd/map.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/setup.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+
+//#include <asm/debug-ll.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-serial.h>
+
+#include "s3c2410.h"
+#include "s3c2440.h"
+#include "clock.h"
+#include "devs.h"
+#include "cpu.h"
+
+static struct map_desc nexcoder_iodesc[] __initdata = {
+ /* nothing here yet */
+};
+
+#define UCON S3C2410_UCON_DEFAULT
+#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
+#define UFCON S3C2410_UFCON_RXTRIG12 | S3C2410_UFCON_FIFOMODE
+
+static struct s3c2410_uartcfg nexcoder_uartcfgs[] = {
+ [0] = {
+ .hwport = 0,
+ .flags = 0,
+ .ucon = UCON,
+ .ulcon = ULCON,
+ .ufcon = UFCON,
+ },
+ [1] = {
+ .hwport = 1,
+ .flags = 0,
+ .ucon = UCON,
+ .ulcon = ULCON,
+ .ufcon = UFCON,
+ },
+ [2] = {
+ .hwport = 2,
+ .flags = 0,
+ .ucon = UCON,
+ .ulcon = ULCON,
+ .ufcon = UFCON,
+ }
+};
+
+/* NOR Flash on NexVision NexCoder 2440 board */
+
+static struct resource nexcoder_nor_resource[] = {
+ [0] = {
+ .start = S3C2410_CS0,
+ .end = S3C2410_CS0 + (8*1024*1024) - 1,
+ .flags = IORESOURCE_MEM,
+ }
+};
+
+static struct map_info nexcoder_nor_map = {
+ .bankwidth = 2,
+};
+
+static struct platform_device nexcoder_device_nor = {
+ .name = "mtd-flash",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(nexcoder_nor_resource),
+ .resource = nexcoder_nor_resource,
+ .dev =
+ {
+ .platform_data = &nexcoder_nor_map,
+ }
+};
+
+/* Standard Nexcoder devices */
+
+static struct platform_device *nexcoder_devices[] __initdata = {
+ &s3c_device_usb,
+ &s3c_device_lcd,
+ &s3c_device_wdt,
+ &s3c_device_i2c,
+ &s3c_device_iis,
+ &s3c_device_rtc,
+ &s3c_device_camif,
+ &s3c_device_spi0,
+ &s3c_device_spi1,
+ &nexcoder_device_nor,
+};
+
+static struct s3c24xx_board nexcoder_board __initdata = {
+ .devices = nexcoder_devices,
+ .devices_count = ARRAY_SIZE(nexcoder_devices),
+};
+
+
+static void __init nexcoder_sensorboard_init(void)
+{
+ // Initialize SCCB bus
+ s3c2410_gpio_setpin(S3C2410_GPE14, 1); // IICSCL
+ s3c2410_gpio_cfgpin(S3C2410_GPE14, S3C2410_GPE14_OUTP);
+ s3c2410_gpio_setpin(S3C2410_GPE15, 1); // IICSDA
+ s3c2410_gpio_cfgpin(S3C2410_GPE15, S3C2410_GPE15_OUTP);
+
+ // Power up the sensor board
+ s3c2410_gpio_setpin(S3C2410_GPF1, 1);
+ s3c2410_gpio_cfgpin(S3C2410_GPF1, S3C2410_GPF1_OUTP); // CAM_GPIO7 => nLDO_PWRDN
+ s3c2410_gpio_setpin(S3C2410_GPF2, 0);
+ s3c2410_gpio_cfgpin(S3C2410_GPF2, S3C2410_GPF2_OUTP); // CAM_GPIO6 => CAM_PWRDN
+}
+
+void __init nexcoder_map_io(void)
+{
+ s3c24xx_init_io(nexcoder_iodesc, ARRAY_SIZE(nexcoder_iodesc));
+ s3c24xx_init_clocks(0);
+ s3c24xx_init_uarts(nexcoder_uartcfgs, ARRAY_SIZE(nexcoder_uartcfgs));
+ s3c24xx_set_board(&nexcoder_board);
+ nexcoder_sensorboard_init();
+}
+
+
+MACHINE_START(NEXCODER_2440, "NexVision - Nexcoder 2440")
+ MAINTAINER("Guillaume GOURAT <guillaume.gourat@nexvision.tv>")
+ BOOT_MEM(S3C2410_SDRAM_PA, S3C2410_PA_UART, (u32)S3C24XX_VA_UART)
+ BOOT_PARAMS(S3C2410_SDRAM_PA + 0x100)
+ .map_io = nexcoder_map_io,
+ .init_irq = s3c24xx_init_irq,
+ .timer = &s3c24xx_timer,
+MACHINE_END
diff --git a/arch/arm/mach-s3c2410/mach-otom.c b/arch/arm/mach-s3c2410/mach-otom.c
new file mode 100644
index 0000000000000..67d8ce8fb00f5
--- /dev/null
+++ b/arch/arm/mach-s3c2410/mach-otom.c
@@ -0,0 +1,124 @@
+/* linux/arch/arm/mach-s3c2410/mach-otom.c
+ *
+ * Copyright (c) 2004 Nex Vision
+ * Guillaume GOURAT <guillaume.gourat@nexvision.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/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/device.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/arch/otom-map.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+
+#include <asm/arch/regs-serial.h>
+#include <asm/arch/regs-gpio.h>
+
+#include "s3c2410.h"
+#include "clock.h"
+#include "devs.h"
+#include "cpu.h"
+
+static struct map_desc otom11_iodesc[] __initdata = {
+ /* Device area */
+ { (u32)OTOM_VA_CS8900A_BASE, OTOM_PA_CS8900A_BASE, SZ_16M, MT_DEVICE },
+};
+
+#define UCON S3C2410_UCON_DEFAULT
+#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
+#define UFCON S3C2410_UFCON_RXTRIG12 | S3C2410_UFCON_FIFOMODE
+
+static struct s3c2410_uartcfg otom11_uartcfgs[] = {
+ [0] = {
+ .hwport = 0,
+ .flags = 0,
+ .ucon = UCON,
+ .ulcon = ULCON,
+ .ufcon = UFCON,
+ },
+ [1] = {
+ .hwport = 1,
+ .flags = 0,
+ .ucon = UCON,
+ .ulcon = ULCON,
+ .ufcon = UFCON,
+ },
+ /* port 2 is not actually used */
+ [2] = {
+ .hwport = 2,
+ .flags = 0,
+ .ucon = UCON,
+ .ulcon = ULCON,
+ .ufcon = UFCON,
+ }
+};
+
+/* NOR Flash on NexVision OTOM board */
+
+static struct resource otom_nor_resource[] = {
+ [0] = {
+ .start = S3C2410_CS0,
+ .end = S3C2410_CS0 + (4*1024*1024) - 1,
+ .flags = IORESOURCE_MEM,
+ }
+};
+
+static struct platform_device otom_device_nor = {
+ .name = "mtd-flash",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(otom_nor_resource),
+ .resource = otom_nor_resource,
+};
+
+/* Standard OTOM devices */
+
+static struct platform_device *otom11_devices[] __initdata = {
+ &s3c_device_usb,
+ &s3c_device_lcd,
+ &s3c_device_wdt,
+ &s3c_device_i2c,
+ &s3c_device_iis,
+ &s3c_device_rtc,
+ &otom_device_nor,
+};
+
+static struct s3c24xx_board otom11_board __initdata = {
+ .devices = otom11_devices,
+ .devices_count = ARRAY_SIZE(otom11_devices)
+};
+
+
+void __init otom11_map_io(void)
+{
+ s3c24xx_init_io(otom11_iodesc, ARRAY_SIZE(otom11_iodesc));
+ s3c24xx_init_clocks(0);
+ s3c24xx_init_uarts(otom11_uartcfgs, ARRAY_SIZE(otom11_uartcfgs));
+ s3c24xx_set_board(&otom11_board);
+}
+
+
+MACHINE_START(OTOM, "Nex Vision - Otom 1.1")
+ MAINTAINER("Guillaume GOURAT <guillaume.gourat@nexvision.tv>")
+ BOOT_MEM(S3C2410_SDRAM_PA, S3C2410_PA_UART, (u32)S3C24XX_VA_UART)
+ BOOT_PARAMS(S3C2410_SDRAM_PA + 0x100)
+ .map_io = otom11_map_io,
+ .init_irq = s3c24xx_init_irq,
+ .timer = &s3c24xx_timer,
+MACHINE_END
diff --git a/arch/arm/mach-s3c2410/mach-rx3715.c b/arch/arm/mach-s3c2410/mach-rx3715.c
index cd8d4ff93fbd8..26e2d86cdd03c 100644
--- a/arch/arm/mach-s3c2410/mach-rx3715.c
+++ b/arch/arm/mach-s3c2410/mach-rx3715.c
@@ -10,10 +10,12 @@
* published by the Free Software Foundation.
*
* Modifications:
- * 16-Sep-2004 BJD Copied from mach-h1940.c
- * 25-Oct-2004 BJD Updates for 2.6.10-rc1
- * 10-Jan-2005 BJD Removed include of s3c2410.h s3c2440.h
- * 14-Jan-2005 BJD Added new clock init
+ * 16-Sep-2004 BJD Copied from mach-h1940.c
+ * 25-Oct-2004 BJD Updates for 2.6.10-rc1
+ * 10-Jan-2005 BJD Removed include of s3c2410.h s3c2440.h
+ * 14-Jan-2005 BJD Added new clock init
+ * 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA
+ * 14-Mar-2005 BJD Fixed __iomem warnings
*/
#include <linux/kernel.h>
@@ -48,8 +50,8 @@
static struct map_desc rx3715_iodesc[] __initdata = {
/* dump ISA space somewhere unused */
- { S3C2410_VA_ISA_WORD, S3C2410_CS3, SZ_16M, MT_DEVICE },
- { S3C2410_VA_ISA_BYTE, S3C2410_CS3, SZ_16M, MT_DEVICE },
+ { (u32)S3C24XX_VA_ISA_WORD, S3C2410_CS3, SZ_16M, MT_DEVICE },
+ { (u32)S3C24XX_VA_ISA_BYTE, S3C2410_CS3, SZ_16M, MT_DEVICE },
};
static struct s3c2410_uartcfg rx3715_uartcfgs[] = {
@@ -114,7 +116,7 @@ static void __init rx3715_init_machine(void)
MACHINE_START(RX3715, "IPAQ-RX3715")
MAINTAINER("Ben Dooks <ben@fluff.org>")
- BOOT_MEM(S3C2410_SDRAM_PA, S3C2410_PA_UART, S3C2410_VA_UART)
+ BOOT_MEM(S3C2410_SDRAM_PA, S3C2410_PA_UART, (u32)S3C24XX_VA_UART)
BOOT_PARAMS(S3C2410_SDRAM_PA + 0x100)
MAPIO(rx3715_map_io)
INITIRQ(rx3715_init_irq)
diff --git a/arch/arm/mach-s3c2410/mach-smdk2410.c b/arch/arm/mach-s3c2410/mach-smdk2410.c
index cd272f79f06ec..c1a4a1420ea0e 100644
--- a/arch/arm/mach-s3c2410/mach-smdk2410.c
+++ b/arch/arm/mach-s3c2410/mach-smdk2410.c
@@ -26,6 +26,9 @@
* @History:
* derived from linux/arch/arm/mach-s3c2410/mach-bast.c, written by
* Ben Dooks <ben@simtec.co.uk>
+ *
+ * 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA
+ *
***********************************************************************/
#include <linux/kernel.h>
@@ -110,7 +113,7 @@ void __init smdk2410_init_irq(void)
MACHINE_START(SMDK2410, "SMDK2410") /* @TODO: request a new identifier and switch
* to SMDK2410 */
MAINTAINER("Jonas Dietsche")
- BOOT_MEM(S3C2410_SDRAM_PA, S3C2410_PA_UART, S3C2410_VA_UART)
+ BOOT_MEM(S3C2410_SDRAM_PA, S3C2410_PA_UART, (u32)S3C24XX_VA_UART)
BOOT_PARAMS(S3C2410_SDRAM_PA + 0x100)
MAPIO(smdk2410_map_io)
INITIRQ(smdk2410_init_irq)
diff --git a/arch/arm/mach-s3c2410/mach-smdk2440.c b/arch/arm/mach-s3c2410/mach-smdk2440.c
new file mode 100644
index 0000000000000..7857176d9bcb2
--- /dev/null
+++ b/arch/arm/mach-s3c2410/mach-smdk2440.c
@@ -0,0 +1,135 @@
+/* linux/arch/arm/mach-s3c2410/mach-smdk2440.c
+ *
+ * Copyright (c) 2004,2005 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * http://www.fluff.org/ben/smdk2440/
+ *
+ * Thanks to Dimity Andric and TomTom for the loan of an SMDK2440.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Modifications:
+ * 01-Nov-2004 BJD Initial version
+ * 12-Nov-2004 BJD Updated for release
+ * 04-Jan-2005 BJD Fixes for pre-release
+ * 22-Feb-2005 BJD Updated for 2.6.11-rc5 relesa
+ * 10-Mar-2005 LCVR Replaced S3C2410_VA by S3C24XX_VA
+ * 14-Mar-2005 BJD void __iomem fixes
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/hardware.h>
+#include <asm/hardware/iomd.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+
+//#include <asm/debug-ll.h>
+#include <asm/arch/regs-serial.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/idle.h>
+
+#include "s3c2410.h"
+#include "s3c2440.h"
+#include "clock.h"
+#include "devs.h"
+#include "cpu.h"
+#include "pm.h"
+
+static struct map_desc smdk2440_iodesc[] __initdata = {
+ /* ISA IO Space map (memory space selected by A24) */
+
+ { (u32)S3C24XX_VA_ISA_WORD, S3C2410_CS2, SZ_16M, MT_DEVICE },
+ { (u32)S3C24XX_VA_ISA_BYTE, S3C2410_CS2, SZ_16M, MT_DEVICE },
+};
+
+#define UCON S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK
+#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
+#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
+
+static struct s3c2410_uartcfg smdk2440_uartcfgs[] = {
+ [0] = {
+ .hwport = 0,
+ .flags = 0,
+ .ucon = 0x3c5,
+ .ulcon = 0x03,
+ .ufcon = 0x51,
+ },
+ [1] = {
+ .hwport = 1,
+ .flags = 0,
+ .ucon = 0x3c5,
+ .ulcon = 0x03,
+ .ufcon = 0x51,
+ },
+ /* IR port */
+ [2] = {
+ .hwport = 2,
+ .flags = 0,
+ .ucon = 0x3c5,
+ .ulcon = 0x43,
+ .ufcon = 0x51,
+ }
+};
+
+static struct platform_device *smdk2440_devices[] __initdata = {
+ &s3c_device_usb,
+ &s3c_device_lcd,
+ &s3c_device_wdt,
+ &s3c_device_i2c,
+ &s3c_device_iis,
+};
+
+static struct s3c24xx_board smdk2440_board __initdata = {
+ .devices = smdk2440_devices,
+ .devices_count = ARRAY_SIZE(smdk2440_devices)
+};
+
+void __init smdk2440_map_io(void)
+{
+ s3c24xx_init_io(smdk2440_iodesc, ARRAY_SIZE(smdk2440_iodesc));
+ s3c24xx_init_clocks(16934400);
+ s3c24xx_init_uarts(smdk2440_uartcfgs, ARRAY_SIZE(smdk2440_uartcfgs));
+ s3c24xx_set_board(&smdk2440_board);
+}
+
+void __init smdk2440_machine_init(void)
+{
+ /* Configure the LEDs (even if we have no LED support)*/
+
+ s3c2410_gpio_cfgpin(S3C2410_GPF4, S3C2410_GPF4_OUTP);
+ s3c2410_gpio_cfgpin(S3C2410_GPF5, S3C2410_GPF5_OUTP);
+ s3c2410_gpio_cfgpin(S3C2410_GPF6, S3C2410_GPF6_OUTP);
+ s3c2410_gpio_cfgpin(S3C2410_GPF7, S3C2410_GPF7_OUTP);
+
+ s3c2410_gpio_setpin(S3C2410_GPF4, 0);
+ s3c2410_gpio_setpin(S3C2410_GPF5, 0);
+ s3c2410_gpio_setpin(S3C2410_GPF6, 0);
+ s3c2410_gpio_setpin(S3C2410_GPF7, 0);
+
+ s3c2410_pm_init();
+}
+
+MACHINE_START(S3C2440, "SMDK2440")
+ MAINTAINER("Ben Dooks <ben@fluff.org>")
+ BOOT_MEM(S3C2410_SDRAM_PA, S3C2410_PA_UART, (u32)S3C24XX_VA_UART)
+ BOOT_PARAMS(S3C2410_SDRAM_PA + 0x100)
+
+ .init_irq = s3c24xx_init_irq,
+ .map_io = smdk2440_map_io,
+ .init_machine = smdk2440_machine_init,
+ .timer = &s3c24xx_timer,
+MACHINE_END
diff --git a/arch/arm/mach-s3c2410/mach-vr1000.c b/arch/arm/mach-s3c2410/mach-vr1000.c
index 0834322e0ab18..5512146b1ce43 100644
--- a/arch/arm/mach-s3c2410/mach-vr1000.c
+++ b/arch/arm/mach-s3c2410/mach-vr1000.c
@@ -24,6 +24,9 @@
* 14-Jan-2005 BJD Added clock init
* 15-Jan-2005 BJD Add serial port device definition
* 20-Jan-2005 BJD Use UPF_IOREMAP for ports
+ * 10-Feb-2005 BJD Added power-off capability
+ * 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA
+ * 14-Mar-2006 BJD void __iomem fixes
*/
#include <linux/kernel.h>
@@ -52,8 +55,8 @@
#include <asm/irq.h>
#include <asm/mach-types.h>
-//#include <asm/debug-ll.h>
#include <asm/arch/regs-serial.h>
+#include <asm/arch/regs-gpio.h>
#include "clock.h"
#include "devs.h"
@@ -61,10 +64,10 @@
#include "usb-simtec.h"
/* macros for virtual address mods for the io space entries */
-#define VA_C5(item) ((item) + BAST_VAM_CS5)
-#define VA_C4(item) ((item) + BAST_VAM_CS4)
-#define VA_C3(item) ((item) + BAST_VAM_CS3)
-#define VA_C2(item) ((item) + BAST_VAM_CS2)
+#define VA_C5(item) ((unsigned long)(item) + BAST_VAM_CS5)
+#define VA_C4(item) ((unsigned long)(item) + BAST_VAM_CS4)
+#define VA_C3(item) ((unsigned long)(item) + BAST_VAM_CS3)
+#define VA_C2(item) ((unsigned long)(item) + BAST_VAM_CS2)
/* macros to modify the physical addresses for io space */
@@ -76,8 +79,8 @@
static struct map_desc vr1000_iodesc[] __initdata = {
/* ISA IO areas */
- { S3C2410_VA_ISA_BYTE, PA_CS2(BAST_PA_ISAIO), SZ_16M, MT_DEVICE },
- { S3C2410_VA_ISA_WORD, PA_CS3(BAST_PA_ISAIO), SZ_16M, MT_DEVICE },
+ { (u32)S3C24XX_VA_ISA_BYTE, PA_CS2(BAST_PA_ISAIO), SZ_16M, MT_DEVICE },
+ { (u32)S3C24XX_VA_ISA_WORD, PA_CS3(BAST_PA_ISAIO), SZ_16M, MT_DEVICE },
/* we could possibly compress the next set down into a set of smaller tables
* pagetables, but that would mean using an L2 section, and it still means
@@ -85,10 +88,10 @@ static struct map_desc vr1000_iodesc[] __initdata = {
*/
/* bast CPLD control registers, and external interrupt controls */
- { VR1000_VA_CTRL1, VR1000_PA_CTRL1, SZ_1M, MT_DEVICE },
- { VR1000_VA_CTRL2, VR1000_PA_CTRL2, SZ_1M, MT_DEVICE },
- { VR1000_VA_CTRL3, VR1000_PA_CTRL3, SZ_1M, MT_DEVICE },
- { VR1000_VA_CTRL4, VR1000_PA_CTRL4, SZ_1M, MT_DEVICE },
+ { (u32)VR1000_VA_CTRL1, VR1000_PA_CTRL1, SZ_1M, MT_DEVICE },
+ { (u32)VR1000_VA_CTRL2, VR1000_PA_CTRL2, SZ_1M, MT_DEVICE },
+ { (u32)VR1000_VA_CTRL3, VR1000_PA_CTRL3, SZ_1M, MT_DEVICE },
+ { (u32)VR1000_VA_CTRL4, VR1000_PA_CTRL4, SZ_1M, MT_DEVICE },
/* peripheral space... one for each of fast/slow/byte/16bit */
/* note, ide is only decoded in word space, even though some registers
@@ -269,6 +272,11 @@ static struct s3c24xx_board vr1000_board __initdata = {
.clocks_count = ARRAY_SIZE(vr1000_clocks),
};
+static void vr1000_power_off(void)
+{
+ s3c2410_gpio_cfgpin(S3C2410_GPB9, S3C2410_GPB9_OUTP);
+ s3c2410_gpio_setpin(S3C2410_GPB9, 1);
+}
void __init vr1000_map_io(void)
{
@@ -285,6 +293,8 @@ void __init vr1000_map_io(void)
s3c24xx_uclk.parent = &s3c24xx_clkout1;
+ pm_power_off = vr1000_power_off;
+
s3c24xx_init_io(vr1000_iodesc, ARRAY_SIZE(vr1000_iodesc));
s3c24xx_init_clocks(0);
s3c24xx_init_uarts(vr1000_uartcfgs, ARRAY_SIZE(vr1000_uartcfgs));
@@ -299,7 +309,7 @@ void __init vr1000_init_irq(void)
MACHINE_START(VR1000, "Thorcom-VR1000")
MAINTAINER("Ben Dooks <ben@simtec.co.uk>")
- BOOT_MEM(S3C2410_SDRAM_PA, S3C2410_PA_UART, S3C2410_VA_UART)
+ BOOT_MEM(S3C2410_SDRAM_PA, S3C2410_PA_UART, (u32)S3C24XX_VA_UART)
BOOT_PARAMS(S3C2410_SDRAM_PA + 0x100)
MAPIO(vr1000_map_io)
INITIRQ(vr1000_init_irq)
diff --git a/arch/arm/mach-s3c2410/pm.c b/arch/arm/mach-s3c2410/pm.c
index ea7c25a50c735..13a48ee774843 100644
--- a/arch/arm/mach-s3c2410/pm.c
+++ b/arch/arm/mach-s3c2410/pm.c
@@ -24,6 +24,9 @@
* Parts based on arch/arm/mach-pxa/pm.c
*
* Thanks to Dimitry Andric for debugging
+ *
+ * Modifications:
+ * 10-Mar-2005 LCVR Changed S3C2410_VA_UART to S3C24XX_VA_UART
*/
#include <linux/config.h>
@@ -144,9 +147,11 @@ static struct sleep_save gpio_save[] = {
SAVE_ITEM((va) + S3C2410_UBRDIV)
static struct sleep_save uart_save[] = {
- SAVE_UART(S3C2410_VA_UART0),
- SAVE_UART(S3C2410_VA_UART1),
- SAVE_UART(S3C2410_VA_UART2),
+ SAVE_UART(S3C24XX_VA_UART0),
+ SAVE_UART(S3C24XX_VA_UART1),
+#ifndef CONFIG_CPU_S3C2400
+ SAVE_UART(S3C24XX_VA_UART2),
+#endif
};
/* debug
@@ -391,7 +396,7 @@ void s3c2410_pm_do_save(struct sleep_save *ptr, int count)
{
for (; count > 0; count--, ptr++) {
ptr->val = __raw_readl(ptr->reg);
- DBG("saved %08lx value %08lx\n", ptr->reg, ptr->val);
+ DBG("saved %p value %08lx\n", ptr->reg, ptr->val);
}
}
@@ -406,7 +411,7 @@ void s3c2410_pm_do_save(struct sleep_save *ptr, int count)
void s3c2410_pm_do_restore(struct sleep_save *ptr, int count)
{
for (; count > 0; count--, ptr++) {
- printk(KERN_DEBUG "restore %08lx (restore %08lx, was %08x)\n",
+ printk(KERN_DEBUG "restore %p (restore %08lx, was %08x)\n",
ptr->reg, ptr->val, __raw_readl(ptr->reg));
__raw_writel(ptr->val, ptr->reg);
diff --git a/arch/arm/mach-s3c2410/pm.h b/arch/arm/mach-s3c2410/pm.h
index dcbe7146fbec4..7a5e714c73866 100644
--- a/arch/arm/mach-s3c2410/pm.h
+++ b/arch/arm/mach-s3c2410/pm.h
@@ -48,7 +48,7 @@ extern unsigned long s3c2410_sleep_save_phys;
/* sleep save info */
struct sleep_save {
- unsigned long reg;
+ void __iomem *reg;
unsigned long val;
};
diff --git a/arch/arm/mach-s3c2410/s3c2410.c b/arch/arm/mach-s3c2410/s3c2410.c
index b8270f26b0849..ff2f25409e446 100644
--- a/arch/arm/mach-s3c2410/s3c2410.c
+++ b/arch/arm/mach-s3c2410/s3c2410.c
@@ -17,7 +17,7 @@
* 21-Aug-2004 BJD Added new struct s3c2410_board handler
* 28-Sep-2004 BJD Updates for new serial port bits
* 04-Nov-2004 BJD Updated UART configuration process
- * 10-Jan-2004 BJD Removed s3c2410_clock_tick_rate
+ * 10-Jan-2005 BJD Removed s3c2410_clock_tick_rate
*/
#include <linux/kernel.h>
@@ -164,31 +164,32 @@ void __init s3c2410_map_io(struct map_desc *mach_desc, int mach_size)
void __init s3c2410_init_clocks(int xtal)
{
unsigned long tmp;
+ unsigned long fclk;
+ unsigned long hclk;
+ unsigned long pclk;
/* now we've got our machine bits initialised, work out what
* clocks we've got */
- s3c24xx_fclk = s3c2410_get_pll(__raw_readl(S3C2410_MPLLCON),
- s3c24xx_xtal);
+ fclk = s3c2410_get_pll(__raw_readl(S3C2410_MPLLCON), xtal);
tmp = __raw_readl(S3C2410_CLKDIVN);
/* work out clock scalings */
- s3c24xx_hclk = s3c24xx_fclk / ((tmp & S3C2410_CLKDIVN_HDIVN) ? 2 : 1);
- s3c24xx_pclk = s3c24xx_hclk / ((tmp & S3C2410_CLKDIVN_PDIVN) ? 2 : 1);
+ hclk = fclk / ((tmp & S3C2410_CLKDIVN_HDIVN) ? 2 : 1);
+ pclk = hclk / ((tmp & S3C2410_CLKDIVN_PDIVN) ? 2 : 1);
/* print brieft summary of clocks, etc */
printk("S3C2410: core %ld.%03ld MHz, memory %ld.%03ld MHz, peripheral %ld.%03ld MHz\n",
- print_mhz(s3c24xx_fclk), print_mhz(s3c24xx_hclk),
- print_mhz(s3c24xx_pclk));
+ print_mhz(fclk), print_mhz(hclk), print_mhz(pclk));
/* initialise the clocks here, to allow other things like the
* console to use them
*/
- s3c24xx_setup_clocks();
+ s3c24xx_setup_clocks(xtal, fclk, hclk, pclk);
}
int __init s3c2410_init(void)
diff --git a/arch/arm/mach-s3c2410/s3c2440-dsc.c b/arch/arm/mach-s3c2410/s3c2440-dsc.c
index 50ccc673ff053..16fa2a3b38fa0 100644
--- a/arch/arm/mach-s3c2410/s3c2440-dsc.c
+++ b/arch/arm/mach-s3c2410/s3c2440-dsc.c
@@ -37,7 +37,7 @@
int s3c2440_set_dsc(unsigned int pin, unsigned int value)
{
- unsigned long base;
+ void __iomem *base;
unsigned long val;
unsigned long flags;
unsigned long mask;
diff --git a/arch/arm/mach-s3c2410/s3c2440.c b/arch/arm/mach-s3c2410/s3c2440.c
index 58146b8f65741..7799d81494615 100644
--- a/arch/arm/mach-s3c2410/s3c2440.c
+++ b/arch/arm/mach-s3c2410/s3c2440.c
@@ -109,7 +109,6 @@ static struct platform_device s3c_uart0 = {
.resource = s3c_uart0_resource,
};
-
static struct platform_device s3c_uart1 = {
.name = "s3c2440-uart",
.id = 1,
@@ -149,19 +148,6 @@ void __init s3c2440_init_uarts(struct s3c2410_uartcfg *cfg, int no)
s3c2440_uart_count = uart;
}
-/* s3c2440 specific clock sources */
-
-static struct clk s3c2440_clk_cam = {
- .name = "camera",
- .enable = s3c24xx_clkcon_enable,
- .ctrlbit = S3C2440_CLKCON_CAMERA
-};
-
-static struct clk s3c2440_clk_ac97 = {
- .name = "ac97",
- .enable = s3c24xx_clkcon_enable,
- .ctrlbit = S3C2440_CLKCON_CAMERA
-};
#ifdef CONFIG_PM
@@ -190,7 +176,7 @@ static int s3c2440_resume(struct sys_device *dev)
#define s3c2440_resume NULL
#endif
-static struct sysdev_class s3c2440_sysclass = {
+struct sysdev_class s3c2440_sysclass = {
set_kset_name("s3c2440-core"),
.suspend = s3c2440_suspend,
.resume = s3c2440_resume
@@ -209,19 +195,24 @@ void __init s3c2440_map_io(struct map_desc *mach_desc, int size)
/* rename any peripherals used differing from the s3c2410 */
s3c_device_i2c.name = "s3c2440-i2c";
+
+ /* change irq for watchdog */
+
+ s3c_device_wdt.resource[1].start = IRQ_S3C2440_WDT;
+ s3c_device_wdt.resource[1].end = IRQ_S3C2440_WDT;
}
void __init s3c2440_init_clocks(int xtal)
{
unsigned long clkdiv;
unsigned long camdiv;
- int s3c2440_hdiv = 1;
+ unsigned long hclk, fclk, pclk;
+ int hdiv = 1;
/* now we've got our machine bits initialised, work out what
* clocks we've got */
- s3c24xx_fclk = s3c2410_get_pll(__raw_readl(S3C2410_MPLLCON),
- s3c24xx_xtal) * 2;
+ fclk = s3c2410_get_pll(__raw_readl(S3C2410_MPLLCON), xtal) * 2;
clkdiv = __raw_readl(S3C2410_CLKDIVN);
camdiv = __raw_readl(S3C2440_CAMDIVN);
@@ -230,63 +221,60 @@ void __init s3c2440_init_clocks(int xtal)
switch (clkdiv & S3C2440_CLKDIVN_HDIVN_MASK) {
case S3C2440_CLKDIVN_HDIVN_1:
- s3c2440_hdiv = 1;
+ hdiv = 1;
break;
case S3C2440_CLKDIVN_HDIVN_2:
- s3c2440_hdiv = 1;
+ hdiv = 1;
break;
case S3C2440_CLKDIVN_HDIVN_4_8:
- s3c2440_hdiv = (camdiv & S3C2440_CAMDIVN_HCLK4_HALF) ? 8 : 4;
+ hdiv = (camdiv & S3C2440_CAMDIVN_HCLK4_HALF) ? 8 : 4;
break;
case S3C2440_CLKDIVN_HDIVN_3_6:
- s3c2440_hdiv = (camdiv & S3C2440_CAMDIVN_HCLK3_HALF) ? 6 : 3;
+ hdiv = (camdiv & S3C2440_CAMDIVN_HCLK3_HALF) ? 6 : 3;
break;
}
- s3c24xx_hclk = s3c24xx_fclk / s3c2440_hdiv;
- s3c24xx_pclk = s3c24xx_hclk / ((clkdiv & S3C2440_CLKDIVN_PDIVN)? 2:1);
+ hclk = fclk / hdiv;
+ pclk = hclk / ((clkdiv & S3C2440_CLKDIVN_PDIVN)? 2:1);
/* print brief summary of clocks, etc */
printk("S3C2440: core %ld.%03ld MHz, memory %ld.%03ld MHz, peripheral %ld.%03ld MHz\n",
- print_mhz(s3c24xx_fclk), print_mhz(s3c24xx_hclk),
- print_mhz(s3c24xx_pclk));
+ print_mhz(fclk), print_mhz(hclk), print_mhz(pclk));
/* initialise the clocks here, to allow other things like the
* console to use them, and to add new ones after the initialisation
*/
- s3c24xx_setup_clocks();
-
- /* add s3c2440 specific clocks */
-
- s3c2440_clk_cam.parent = clk_get(NULL, "hclk");
- s3c2440_clk_ac97.parent = clk_get(NULL, "pclk");
+ s3c24xx_setup_clocks(xtal, fclk, hclk, pclk);
+}
- s3c24xx_register_clock(&s3c2440_clk_ac97);
- s3c24xx_register_clock(&s3c2440_clk_cam);
+/* need to register class before we actually register the device, and
+ * we also need to ensure that it has been initialised before any of the
+ * drivers even try to use it (even if not on an s3c2440 based system)
+ * as a driver which may support both 2410 and 2440 may try and use it.
+*/
- clk_disable(&s3c2440_clk_ac97);
- clk_disable(&s3c2440_clk_cam);
+int __init s3c2440_core_init(void)
+{
+ return sysdev_class_register(&s3c2440_sysclass);
}
+core_initcall(s3c2440_core_init);
+
int __init s3c2440_init(void)
{
int ret;
printk("S3C2440: Initialising architecture\n");
- ret = sysdev_class_register(&s3c2440_sysclass);
- if (ret == 0)
- ret = sysdev_register(&s3c2440_sysdev);
-
+ ret = sysdev_register(&s3c2440_sysdev);
if (ret != 0)
printk(KERN_ERR "failed to register sysdev for s3c2440\n");
-
- if (ret == 0)
+ else
ret = platform_add_devices(s3c24xx_uart_devs, s3c2440_uart_count);
return ret;
diff --git a/arch/arm/mach-s3c2410/time.c b/arch/arm/mach-s3c2410/time.c
index 715d65a40341b..179f0e031af48 100644
--- a/arch/arm/mach-s3c2410/time.c
+++ b/arch/arm/mach-s3c2410/time.c
@@ -1,6 +1,6 @@
/* linux/arch/arm/mach-s3c2410/time.c
*
- * Copyright (C) 2003,2004 Simtec Electronics
+ * Copyright (C) 2003-2005 Simtec Electronics
* Ben Dooks, <ben@simtec.co.uk>
*
* This program is free software; you can redistribute it and/or modify
@@ -23,6 +23,8 @@
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/interrupt.h>
+#include <linux/err.h>
+
#include <asm/system.h>
#include <asm/leds.h>
#include <asm/mach-types.h>
@@ -33,6 +35,7 @@
#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"
@@ -169,6 +172,9 @@ static void s3c2410_timer_setup (void)
tcfg1 &= ~S3C2410_TCFG1_MUX4_MASK;
tcfg1 |= S3C2410_TCFG1_MUX4_TCLK1;
} else {
+ unsigned long pclk;
+ struct clk *clk;
+
/* for the h1940 (and others), we use the pclk from the core
* to generate the timer values. since values around 50 to
* 70MHz are not values we can directly generate the timer
@@ -180,7 +186,18 @@ static void s3c2410_timer_setup (void)
/* this is used as default if no other timer can be found */
- timer_usec_ticks = timer_mask_usec_ticks(6, s3c24xx_pclk);
+ clk = clk_get(NULL, "timers");
+ if (IS_ERR(clk))
+ panic("failed to get clock for system timer");
+
+ clk_use(clk);
+ clk_enable(clk);
+
+ pclk = clk_get_rate(clk);
+
+ /* configure clock tick */
+
+ timer_usec_ticks = timer_mask_usec_ticks(6, pclk);
tcfg1 &= ~S3C2410_TCFG1_MUX4_MASK;
tcfg1 |= S3C2410_TCFG1_MUX4_DIV2;
@@ -188,7 +205,7 @@ static void s3c2410_timer_setup (void)
tcfg0 &= ~S3C2410_TCFG_PRESCALER1_MASK;
tcfg0 |= ((6 - 1) / 2) << S3C2410_TCFG_PRESCALER1_SHIFT;
- tcnt = (s3c24xx_pclk / 6) / HZ;
+ tcnt = (pclk / 6) / HZ;
}
/* timers reload after counting zero, so reduce the count by 1 */
diff --git a/arch/arm/mach-sa1100/Kconfig b/arch/arm/mach-sa1100/Kconfig
index aa7d1c7923e08..5178cde08ab96 100644
--- a/arch/arm/mach-sa1100/Kconfig
+++ b/arch/arm/mach-sa1100/Kconfig
@@ -11,6 +11,7 @@ config SA1100_ASSABET
config ASSABET_NEPONSET
bool "Include support for Neponset"
depends on SA1100_ASSABET
+ select SA1111
help
Say Y here if you are using the Intel(R) StrongARM(R) SA-1110
Microprocessor Development Board (Assabet) with the SA-1111
@@ -44,7 +45,8 @@ endchoice
config SA1100_COLLIE
bool "Sharp Zaurus SL5500"
- depends on ARCH_SA1100
+ select SHARP_LOCOMO
+ select SHARP_SCOOP
help
Say Y here to support the Sharp Zaurus SL5500 PDAs.
@@ -85,12 +87,14 @@ config SA1100_H3XXX
config SA1100_BADGE4
bool "HP Labs BadgePAD 4"
+ select SA1111
help
Say Y here if you want to build a kernel for the HP Laboratories
BadgePAD 4.
config SA1100_JORNADA720
bool "HP Jornada 720"
+ select SA1111
help
Say Y here if you want to build a kernel for the HP Jornada 720
handheld computer. See <http://www.hp.com/jornada/products/720>
diff --git a/arch/arm/mach-sa1100/assabet.c b/arch/arm/mach-sa1100/assabet.c
index a3003b8675557..bedf88fafe082 100644
--- a/arch/arm/mach-sa1100/assabet.c
+++ b/arch/arm/mach-sa1100/assabet.c
@@ -259,9 +259,11 @@ static void __init map_sa1100_gpio_regs( void )
unsigned long phys = __PREG(GPLR) & PMD_MASK;
unsigned long virt = io_p2v(phys);
int prot = PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_DOMAIN(DOMAIN_IO);
- pmd_t pmd;
- pmd_val(pmd) = phys | prot;
- set_pmd(pmd_offset(pgd_offset_k(virt), virt), pmd);
+ pmd_t *pmd;
+
+ pmd = pmd_offset(pgd_offset_k(virt), virt);
+ *pmd = __pmd(phys | prot);
+ flush_pmd_entry(pmd);
}
/*
diff --git a/arch/arm/mach-sa1100/collie.c b/arch/arm/mach-sa1100/collie.c
index 2bc071a7b7f35..da9412c5d385e 100644
--- a/arch/arm/mach-sa1100/collie.c
+++ b/arch/arm/mach-sa1100/collie.c
@@ -55,7 +55,7 @@ static struct scoop_config collie_scoop_setup = {
.io_out = COLLIE_SCOOP_IO_OUT,
};
-static struct platform_device colliescoop_device = {
+struct platform_device colliescoop_device = {
.name = "sharp-scoop",
.id = -1,
.dev = {
diff --git a/arch/arm/mach-sa1100/neponset.c b/arch/arm/mach-sa1100/neponset.c
index e3dc13832d769..6ffa50151a8c3 100644
--- a/arch/arm/mach-sa1100/neponset.c
+++ b/arch/arm/mach-sa1100/neponset.c
@@ -266,6 +266,7 @@ static struct platform_device sa1111_device = {
static struct resource smc91x_resources[] = {
[0] = {
+ .name = "smc91x-regs",
.start = SA1100_CS3_PHYS,
.end = SA1100_CS3_PHYS + 0x01ffffff,
.flags = IORESOURCE_MEM,
@@ -276,6 +277,7 @@ static struct resource smc91x_resources[] = {
.flags = IORESOURCE_IRQ,
},
[2] = {
+ .name = "smc91x-attrib",
.start = SA1100_CS3_PHYS + 0x02000000,
.end = SA1100_CS3_PHYS + 0x03ffffff,
.flags = IORESOURCE_MEM,
diff --git a/arch/arm/mm/abort-ev4t.S b/arch/arm/mm/abort-ev4t.S
index 831a4a21c2164..b6282548f922e 100644
--- a/arch/arm/mm/abort-ev4t.S
+++ b/arch/arm/mm/abort-ev4t.S
@@ -1,5 +1,6 @@
#include <linux/linkage.h>
#include <asm/assembler.h>
+#include "abort-macro.S"
/*
* Function: v4t_early_abort
*
@@ -21,11 +22,9 @@
ENTRY(v4t_early_abort)
mrc p15, 0, r1, c5, c0, 0 @ get FSR
mrc p15, 0, r0, c6, c0, 0 @ get FAR
- tst r3, #PSR_T_BIT
- ldrneh r3, [r2] @ read aborted thumb instruction
+ do_thumb_abort
ldreq r3, [r2] @ read aborted ARM instruction
bic r1, r1, #1 << 11 | 1 << 10 @ clear bits 11 and 10 of FSR
- movne r3, r3, lsl #(21 - 12) @ move thumb bit 11 to ARM bit 20
tst r3, #1 << 20 @ check write
orreq r1, r1, #1 << 11
mov pc, lr
diff --git a/arch/arm/mm/abort-ev5t.S b/arch/arm/mm/abort-ev5t.S
index 62fd4383640f0..02251b526c0df 100644
--- a/arch/arm/mm/abort-ev5t.S
+++ b/arch/arm/mm/abort-ev5t.S
@@ -1,5 +1,6 @@
#include <linux/linkage.h>
#include <asm/assembler.h>
+#include "abort-macro.S"
/*
* Function: v5t_early_abort
*
@@ -21,11 +22,10 @@
ENTRY(v5t_early_abort)
mrc p15, 0, r1, c5, c0, 0 @ get FSR
mrc p15, 0, r0, c6, c0, 0 @ get FAR
- tst r3, #PSR_T_BIT
- ldrneh r3, [r2] @ read aborted thumb instruction
+ do_thumb_abort
ldreq r3, [r2] @ read aborted ARM instruction
bic r1, r1, #1 << 11 @ clear bits 11 of FSR
- movne r3, r3, lsl #(21 - 12) @ move thumb bit 11 to ARM bit 20
+ do_ldrd_abort
tst r3, #1 << 20 @ check write
orreq r1, r1, #1 << 11
mov pc, lr
diff --git a/arch/arm/mm/abort-ev5tj.S b/arch/arm/mm/abort-ev5tj.S
index fd0584a92a121..bce68d601c8be 100644
--- a/arch/arm/mm/abort-ev5tj.S
+++ b/arch/arm/mm/abort-ev5tj.S
@@ -1,5 +1,6 @@
#include <linux/linkage.h>
#include <asm/assembler.h>
+#include "abort-macro.S"
/*
* Function: v5tj_early_abort
*
@@ -24,10 +25,9 @@ ENTRY(v5tj_early_abort)
bic r1, r1, #1 << 11 | 1 << 10 @ clear bits 11 and 10 of FSR
tst r3, #PSR_J_BIT @ Java?
movne pc, lr
- tst r3, #PSR_T_BIT @ Thumb?
- ldrneh r3, [r2] @ read aborted thumb instruction
+ do_thumb_abort
ldreq r3, [r2] @ read aborted ARM instruction
- movne r3, r3, lsl #(21 - 12) @ move thumb bit 11 to ARM bit 20
+ do_ldrd_abort
tst r3, #1 << 20 @ L = 0 -> write
orreq r1, r1, #1 << 11 @ yes.
mov pc, lr
diff --git a/arch/arm/mm/abort-macro.S b/arch/arm/mm/abort-macro.S
new file mode 100644
index 0000000000000..d7cb1bfa51a4c
--- /dev/null
+++ b/arch/arm/mm/abort-macro.S
@@ -0,0 +1,42 @@
+/*
+ * The ARM LDRD and Thumb LDRSB instructions use bit 20/11 (ARM/Thumb)
+ * differently than every other instruction, so it is set to 0 (write)
+ * even though the instructions are read instructions. This means that
+ * during an abort the instructions will be treated as a write and the
+ * handler will raise a signal from unwriteable locations if they
+ * fault. We have to specifically check for these instructions
+ * from the abort handlers to treat them properly.
+ *
+ */
+
+ .macro do_thumb_abort
+ tst r3, #PSR_T_BIT
+ beq not_thumb
+ ldrh r3, [r2] @ Read aborted Thumb instruction
+ and r3, r3, # 0xfe00 @ Mask opcode field
+ cmp r3, # 0x5600 @ Is it ldrsb?
+ orreq r3, r3, #1 << 11 @ Set L-bit if yes
+ tst r3, #1 << 11 @ L = 0 -> write
+ orreq r1, r1, #1 << 11 @ yes.
+ mov pc, lr
+not_thumb:
+ .endm
+
+/*
+ * We check for the following insturction encoding for LDRD.
+ *
+ * [27:25] == 0
+ * [7:4] == 1101
+ * [20] == 0
+ */
+ .macro do_ldrd_abort
+ tst r3, #0x0e000000 @ [27:25] == 0
+ bne not_ldrd
+ and r2, r3, #0x000000f0 @ [7:4] == 1101
+ cmp r2, #0x000000d0
+ bne not_ldrd
+ tst r3, #1 << 20 @ [20] == 0
+ moveq pc, lr
+not_ldrd:
+ .endm
+
diff --git a/arch/arm/mm/consistent.c b/arch/arm/mm/consistent.c
index 3c2bde8e357ba..26356ce4da544 100644
--- a/arch/arm/mm/consistent.c
+++ b/arch/arm/mm/consistent.c
@@ -293,7 +293,8 @@ static int dma_mmap(struct device *dev, struct vm_area_struct *vma,
vma->vm_flags |= VM_RESERVED;
ret = remap_pfn_range(vma, vma->vm_start,
page_to_pfn(c->vm_pages) + off,
- user_size, vma->vm_page_prot);
+ user_size << PAGE_SHIFT,
+ vma->vm_page_prot);
}
}
@@ -322,7 +323,7 @@ EXPORT_SYMBOL(dma_mmap_writecombine);
void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, dma_addr_t handle)
{
struct vm_region *c;
- unsigned long flags;
+ unsigned long flags, addr;
pte_t *ptep;
size = PAGE_ALIGN(size);
@@ -341,11 +342,13 @@ void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, dma_addr
}
ptep = consistent_pte + CONSISTENT_OFFSET(c->vm_start);
+ addr = c->vm_start;
do {
- pte_t pte = ptep_get_and_clear(ptep);
+ pte_t pte = ptep_get_and_clear(&init_mm, addr, ptep);
unsigned long pfn;
ptep++;
+ addr += PAGE_SIZE;
if (!pte_none(pte) && pte_present(pte)) {
pfn = pte_pfn(pte);
diff --git a/arch/arm/mm/fault-armv.c b/arch/arm/mm/fault-armv.c
index 5f0a790940ef7..01967ddeef53d 100644
--- a/arch/arm/mm/fault-armv.c
+++ b/arch/arm/mm/fault-armv.c
@@ -54,7 +54,7 @@ static int adjust_pte(struct vm_area_struct *vma, unsigned long address)
* fault (ie, is old), we can safely ignore any issues.
*/
if (pte_present(entry) && pte_val(entry) & shared_pte_mask) {
- flush_cache_page(vma, address);
+ flush_cache_page(vma, address, pte_pfn(entry));
pte_val(entry) &= ~shared_pte_mask;
set_pte(pte, entry);
flush_tlb_page(vma, address);
@@ -115,7 +115,7 @@ make_coherent(struct vm_area_struct *vma, unsigned long addr, struct page *page,
if (aliases)
adjust_pte(vma, addr);
else
- flush_cache_page(vma, addr);
+ flush_cache_page(vma, addr, page_to_pfn(page));
}
/*
diff --git a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c
index ff5f62ce42936..c6de48d895032 100644
--- a/arch/arm/mm/flush.c
+++ b/arch/arm/mm/flush.c
@@ -56,7 +56,7 @@ static void __flush_dcache_page(struct address_space *mapping, struct page *page
if (!(mpnt->vm_flags & VM_MAYSHARE))
continue;
offset = (pgoff - mpnt->vm_pgoff) << PAGE_SHIFT;
- flush_cache_page(mpnt, mpnt->vm_start + offset);
+ flush_cache_page(mpnt, mpnt->vm_start + offset, page_to_pfn(page));
if (cache_is_vipt())
break;
}
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index e9c99c2f12b7d..41156c5370f74 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -501,10 +501,6 @@ void __init paging_init(struct meminfo *mi, struct machine_desc *mdesc)
bdata->node_boot_start >> PAGE_SHIFT, zhole_size);
}
-#ifndef CONFIG_DISCONTIGMEM
- mem_map = contig_page_data.node_mem_map;
-#endif
-
/*
* finish off the bad pages once
* the mem_map is initialised
diff --git a/arch/arm/mm/mm-armv.c b/arch/arm/mm/mm-armv.c
index a9c9c33dfbc3a..f5a87db8b4983 100644
--- a/arch/arm/mm/mm-armv.c
+++ b/arch/arm/mm/mm-armv.c
@@ -252,7 +252,25 @@ alloc_init_section(unsigned long virt, unsigned long phys, int prot)
if (virt & (1 << 20))
pmdp++;
- set_pmd(pmdp, __pmd(phys | prot));
+ *pmdp = __pmd(phys | prot);
+ flush_pmd_entry(pmdp);
+}
+
+/*
+ * Create a SUPER SECTION PGD between VIRT and PHYS with protection PROT
+ */
+static inline void
+alloc_init_supersection(unsigned long virt, unsigned long phys, int prot)
+{
+ int i;
+
+ for (i = 0; i < 16; i += 1) {
+ alloc_init_section(virt, phys & SUPERSECTION_MASK,
+ prot | PMD_SECT_SUPER);
+
+ virt += (PGDIR_SIZE / 2);
+ phys += (PGDIR_SIZE / 2);
+ }
}
/*
@@ -338,6 +356,15 @@ static struct mem_types mem_types[] __initdata = {
[MT_ROM] = {
.prot_sect = PMD_TYPE_SECT,
.domain = DOMAIN_KERNEL,
+ },
+ [MT_IXP2000_DEVICE] = { /* IXP2400 requires XCB=101 for on-chip I/O */
+ .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
+ L_PTE_WRITE,
+ .prot_l1 = PMD_TYPE_TABLE,
+ .prot_sect = PMD_TYPE_SECT | PMD_SECT_UNCACHED |
+ PMD_SECT_AP_WRITE | PMD_SECT_BUFFERABLE |
+ PMD_SECT_TEX(1),
+ .domain = DOMAIN_IO,
}
};
@@ -436,7 +463,8 @@ static void __init build_mem_type_table(void)
* Create the page directory entries and any necessary
* page tables for the mapping specified by `md'. We
* are able to cope here with varying sizes and address
- * offsets, and we take full advantage of sections.
+ * offsets, and we take full advantage of sections and
+ * supersections.
*/
static void __init create_mapping(struct map_desc *md)
{
@@ -483,6 +511,30 @@ static void __init create_mapping(struct map_desc *md)
length -= PAGE_SIZE;
}
+ /* N.B. ARMv6 supersections are only defined to work with domain 0.
+ * Since domain assignments can in fact be arbitrary, the
+ * 'domain == 0' check below is required to insure that ARMv6
+ * supersections are only allocated for domain 0 regardless
+ * of the actual domain assignments in use.
+ */
+ if (cpu_architecture() >= CPU_ARCH_ARMv6 && domain == 0) {
+ /* Align to supersection boundary */
+ while ((virt & ~SUPERSECTION_MASK || (virt + off) &
+ ~SUPERSECTION_MASK) && length >= (PGDIR_SIZE / 2)) {
+ alloc_init_section(virt, virt + off, prot_sect);
+
+ virt += (PGDIR_SIZE / 2);
+ length -= (PGDIR_SIZE / 2);
+ }
+
+ while (length >= SUPERSECTION_SIZE) {
+ alloc_init_supersection(virt, virt + off, prot_sect);
+
+ virt += SUPERSECTION_SIZE;
+ length -= SUPERSECTION_SIZE;
+ }
+ }
+
/*
* A section mapping covers half a "pgdir" entry.
*/
@@ -526,8 +578,9 @@ void setup_mm_for_reboot(char mode)
if (cpu_arch <= CPU_ARCH_ARMv5)
pmdval |= PMD_BIT4;
pmd = pmd_offset(pgd + i, i << PGDIR_SHIFT);
- set_pmd(pmd, __pmd(pmdval));
- set_pmd(pmd + 1, __pmd(pmdval + (1 << (PGDIR_SHIFT - 1))));
+ pmd[0] = __pmd(pmdval);
+ pmd[1] = __pmd(pmdval + (1 << (PGDIR_SHIFT - 1)));
+ flush_pmd_entry(pmd);
}
}
diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types
index 0678f4fcba399..30c1dfbb052fc 100644
--- a/arch/arm/tools/mach-types
+++ b/arch/arm/tools/mach-types
@@ -6,7 +6,7 @@
# To add an entry into this database, please see Documentation/arm/README,
# or contact rmk@arm.linux.org.uk
#
-# Last update: Thu Jan 6 00:10:23 2005
+# Last update: Thu Mar 24 14:34:50 2005
#
# machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number
#
@@ -226,7 +226,7 @@ dnp1110 SA1100_DNP1110 DNP1110 214
pnp1110 SA1100_PNP1110 PNP1110 215
csb226 ARCH_CSB226 CSB226 216
arnold SA1100_ARNOLD ARNOLD 217
-voiceblue SA1100_PSIBOARD PSIBOARD 218
+voiceblue MACH_VOICEBLUE VOICEBLUE 218
jz8028 ARCH_JZ8028 JZ8028 219
h5400 ARCH_H5400 H5400 220
forte SA1100_FORTE FORTE 221
@@ -381,7 +381,7 @@ s5c7375 ARCH_S5C7375 S5C7375 369
spearhead ARCH_SPEARHEAD SPEARHEAD 370
pantera ARCH_PANTERA PANTERA 371
prayoglite ARCH_PRAYOGLITE PRAYOGLITE 372
-gumstik ARCH_GUMSTIK GUMSTIK 373
+gumstix ARCH_GUMSTIK GUMSTIK 373
rcube ARCH_RCUBE RCUBE 374
rea_olv ARCH_REA_OLV REA_OLV 375
pxa_iphone ARCH_PXA_IPHONE PXA_IPHONE 376
@@ -649,7 +649,6 @@ zefeerdzg MACH_ZEFEERDZG ZEFEERDZG 638
zefeerdzn MACH_ZEFEERDZN ZEFEERDZN 639
zefeerdzq MACH_ZEFEERDZQ ZEFEERDZQ 640
gtwx5715 MACH_GTWX5715 GTWX5715 641
-unknown MACH_VL420 VL420 642
astro_jack MACH_ASTRO_JACK ASTRO_JACK 643
tip03 MACH_TIP03 TIP03 644
a9200ec MACH_A9200EC A9200EC 645
@@ -667,3 +666,61 @@ n30 MACH_N30 N30 656
manga_ks8695 MACH_MANGA_KS8695 MANGA_KS8695 657
ajax MACH_AJAX AJAX 658
nec_mp900 MACH_NEC_MP900 NEC_MP900 659
+vvtk1000 MACH_VVTK1000 VVTK1000 661
+kafa MACH_KAFA KAFA 662
+vvtk3000 MACH_VVTK3000 VVTK3000 663
+pimx1 MACH_PIMX1 PIMX1 664
+ollie MACH_OLLIE OLLIE 665
+skymax MACH_SKYMAX SKYMAX 666
+jazz MACH_JAZZ JAZZ 667
+tel_t3 MACH_TEL_T3 TEL_T3 668
+aisino_fcr255 MACH_AISINO_FCR255 AISINO_FCR255 669
+btweb MACH_BTWEB BTWEB 670
+dbg_lh79520 MACH_DBG_LH79520 DBG_LH79520 671
+cm41xx MACH_CM41XX CM41XX 672
+ts72xx MACH_TS72XX TS72XX 673
+nggpxa MACH_NGGPXA NGGPXA 674
+csb535 MACH_CSB535 CSB535 675
+csb536 MACH_CSB536 CSB536 676
+pxa_trakpod MACH_PXA_TRAKPOD PXA_TRAKPOD 677
+praxis MACH_PRAXIS PRAXIS 678
+lh75411 MACH_LH75411 LH75411 679
+otom MACH_OTOM OTOM 680
+nexcoder_2440 MACH_NEXCODER_2440 NEXCODER_2440 681
+loox410 MACH_LOOX410 LOOX410 682
+westlake MACH_WESTLAKE WESTLAKE 683
+nsb MACH_NSB NSB 684
+esl_sarva_stn MACH_ESL_SARVA_STN ESL_SARVA_STN 685
+esl_sarva_tft MACH_ESL_SARVA_TFT ESL_SARVA_TFT 686
+esl_sarva_iad MACH_ESL_SARVA_IAD ESL_SARVA_IAD 687
+esl_sarva_acc MACH_ESL_SARVA_ACC ESL_SARVA_ACC 688
+typhoon MACH_TYPHOON TYPHOON 689
+cnav MACH_CNAV CNAV 690
+a730 MACH_A730 A730 691
+netstar MACH_NETSTAR NETSTAR 692
+supercon MACH_PHASEFALE_SUPERCON PHASEFALE_SUPERCON 693
+shiva1100 MACH_SHIVA1100 SHIVA1100 694
+etexsc MACH_ETEXSC ETEXSC 695
+ixdpg465 MACH_IXDPG465 IXDPG465 696
+a9m2410 MACH_A9M2410 A9M2410 697
+a9m2440 MACH_A9M2440 A9M2440 698
+a9m9750 MACH_A9M9750 A9M9750 699
+a9m9360 MACH_A9M9360 A9M9360 700
+unc90 MACH_UNC90 UNC90 701
+eco920 MACH_ECO920 ECO920 702
+satview MACH_SATVIEW SATVIEW 703
+roadrunner MACH_ROADRUNNER ROADRUNNER 704
+at91rm9200ek MACH_AT91RM9200EK AT91RM9200EK 705
+gp32 MACH_GP32 GP32 706
+gem MACH_GEM GEM 707
+i858 MACH_I858 I858 708
+hx2750 MACH_HX2750 HX2750 709
+zeusevb MACH_ZEUSEVB ZEUSEVB 710
+p700 MACH_P700 P700 711
+cpe MACH_CPE CPE 712
+spitz MACH_SPITZ SPITZ 713
+nimbra340 MACH_NIMBRA340 NIMBRA340 714
+lpc22xx MACH_LPC22XX LPC22XX 715
+omap_comet3 MACH_COMET3 COMET3 716
+omap_comet4 MACH_COMET4 COMET4 717
+csb625 MACH_CSB625 CSB625 718
diff --git a/arch/arm26/Kconfig.debug b/arch/arm26/Kconfig.debug
index e2c920dc1a698..611fc86503fca 100644
--- a/arch/arm26/Kconfig.debug
+++ b/arch/arm26/Kconfig.debug
@@ -38,16 +38,6 @@ config DEBUG_ERRORS
you are concerned with the code size or don't want to see these
messages.
-config DEBUG_INFO
- bool "Include GDB debugging information in kernel binary"
- help
- Say Y here to include source-level debugging information in the
- `vmlinux' binary image. This is handy if you want to use gdb or
- addr2line to debug the kernel. It has no impact on the in-memory
- footprint of the running kernel but it can increase the amount of
- time and disk space needed for compilation of the kernel. If in
- doubt say N.
-
# These options are only for real kernel hackers who want to get their hands dirty.
config DEBUG_LL
bool "Kernel low-level debugging functions"
diff --git a/arch/arm26/kernel/setup.c b/arch/arm26/kernel/setup.c
index 2909b2499049e..4eb329e3828a6 100644
--- a/arch/arm26/kernel/setup.c
+++ b/arch/arm26/kernel/setup.c
@@ -74,7 +74,6 @@ unsigned int number_mfm_drives;
struct processor processor;
-unsigned char aux_device_present;
char elf_platform[ELF_PLATFORM_SIZE];
unsigned long phys_initrd_start __initdata = 0;
diff --git a/arch/arm26/kernel/signal.c b/arch/arm26/kernel/signal.c
index bf05f1537aa1a..356d9809cc0bb 100644
--- a/arch/arm26/kernel/signal.c
+++ b/arch/arm26/kernel/signal.c
@@ -102,7 +102,7 @@ sys_sigaction(int sig, const struct old_sigaction *act,
if (act) {
old_sigset_t mask;
- if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
+ if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
__get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
__get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
return -EFAULT;
@@ -114,7 +114,7 @@ sys_sigaction(int sig, const struct old_sigaction *act,
ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
if (!ret && oact) {
- if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
+ if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
__put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
__put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
return -EFAULT;
@@ -186,7 +186,7 @@ asmlinkage int sys_sigreturn(struct pt_regs *regs)
frame = (struct sigframe *)regs->ARM_sp;
- if (verify_area(VERIFY_READ, frame, sizeof (*frame)))
+ if (!access_ok(VERIFY_READ, frame, sizeof (*frame)))
goto badframe;
if (__get_user(set.sig[0], &frame->sc.oldmask)
|| (_NSIG_WORDS > 1
@@ -231,7 +231,7 @@ asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
frame = (struct rt_sigframe *)regs->ARM_sp;
- if (verify_area(VERIFY_READ, frame, sizeof (*frame)))
+ if (!access_ok(VERIFY_READ, frame, sizeof (*frame)))
goto badframe;
if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
goto badframe;
diff --git a/arch/arm26/mm/init.c b/arch/arm26/mm/init.c
index 1dba6bf03db3f..1f09a9d0fb837 100644
--- a/arch/arm26/mm/init.c
+++ b/arch/arm26/mm/init.c
@@ -309,8 +309,6 @@ void __init paging_init(struct meminfo *mi)
free_area_init_node(0, pgdat, zone_size,
bdata->node_boot_start >> PAGE_SHIFT, zhole_size);
- mem_map = NODE_DATA(0)->node_mem_map;
-
/*
* finish off the bad pages once
* the mem_map is initialised
diff --git a/arch/cris/arch-v10/drivers/eeprom.c b/arch/cris/arch-v10/drivers/eeprom.c
index 960f4cbdcf5cc..316ca15d6802c 100644
--- a/arch/cris/arch-v10/drivers/eeprom.c
+++ b/arch/cris/arch-v10/drivers/eeprom.c
@@ -599,7 +599,7 @@ static ssize_t eeprom_write(struct file * file, const char * buf, size_t count,
int i, written, restart=1;
unsigned long p;
- if (verify_area(VERIFY_READ, buf, count))
+ if (!access_ok(VERIFY_READ, buf, count))
{
return -EFAULT;
}
diff --git a/arch/cris/arch-v10/drivers/gpio.c b/arch/cris/arch-v10/drivers/gpio.c
index 50548a234b1cc..c095de82a0dac 100644
--- a/arch/cris/arch-v10/drivers/gpio.c
+++ b/arch/cris/arch-v10/drivers/gpio.c
@@ -355,7 +355,7 @@ static ssize_t gpio_write(struct file * file, const char * buf, size_t count,
return -EFAULT;
}
- if (verify_area(VERIFY_READ, buf, count)) {
+ if (!access_ok(VERIFY_READ, buf, count)) {
return -EFAULT;
}
clk_mask = priv->clk_mask;
diff --git a/arch/cris/arch-v10/kernel/signal.c b/arch/cris/arch-v10/kernel/signal.c
index 97b7af26a6475..85e0032e664ff 100644
--- a/arch/cris/arch-v10/kernel/signal.c
+++ b/arch/cris/arch-v10/kernel/signal.c
@@ -125,7 +125,7 @@ sys_sigaction(int sig, const struct old_sigaction __user *act,
if (act) {
old_sigset_t mask;
- if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
+ if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
__get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
__get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
return -EFAULT;
@@ -137,7 +137,7 @@ sys_sigaction(int sig, const struct old_sigaction __user *act,
ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
if (!ret && oact) {
- if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
+ if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
__put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
__put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
return -EFAULT;
@@ -231,7 +231,7 @@ asmlinkage int sys_sigreturn(long r10, long r11, long r12, long r13, long mof,
if (((long)frame) & 3)
goto badframe;
- if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
+ if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
goto badframe;
if (__get_user(set.sig[0], &frame->sc.oldmask)
|| (_NSIG_WORDS > 1
@@ -273,7 +273,7 @@ asmlinkage int sys_rt_sigreturn(long r10, long r11, long r12, long r13,
if (((long)frame) & 3)
goto badframe;
- if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
+ if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
goto badframe;
if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
goto badframe;
diff --git a/arch/cris/arch-v10/mm/init.c b/arch/cris/arch-v10/mm/init.c
index 720b9c1561ddc..a9f975a9cfb54 100644
--- a/arch/cris/arch-v10/mm/init.c
+++ b/arch/cris/arch-v10/mm/init.c
@@ -184,7 +184,6 @@ paging_init(void)
*/
free_area_init_node(0, &contig_page_data, zones_size, PAGE_OFFSET >> PAGE_SHIFT, 0);
- mem_map = contig_page_data.node_mem_map;
}
/* Initialize remaps of some I/O-ports. It is important that this
diff --git a/arch/cris/kernel/setup.c b/arch/cris/kernel/setup.c
index 02f62310aeaf2..6ec2671078bf4 100644
--- a/arch/cris/kernel/setup.c
+++ b/arch/cris/kernel/setup.c
@@ -26,8 +26,6 @@
struct drive_info_struct { char dummy[32]; } drive_info;
struct screen_info screen_info;
-unsigned char aux_device_present;
-
extern int root_mountflags;
extern char _etext, _edata, _end;
diff --git a/arch/frv/Kconfig b/arch/frv/Kconfig
index 78e55051f98f1..2b19372767eb8 100644
--- a/arch/frv/Kconfig
+++ b/arch/frv/Kconfig
@@ -348,151 +348,7 @@ source "drivers/Kconfig"
source "fs/Kconfig"
-menu "Kernel hacking"
-
-config DEBUG_KERNEL
- bool "Kernel debugging"
- help
- Say Y here if you are developing drivers or trying to debug and
- identify kernel problems.
-
-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_SLAB
- bool "Debug memory allocations"
- depends on DEBUG_KERNEL
- 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
- memory.
-
-config MAGIC_SYSRQ
- bool "Magic SysRq key"
- depends on DEBUG_KERNEL
- 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
- will be able to flush the buffer cache to disk, reboot the system
- immediately or dump some status information). This is accomplished
- by pressing various keys while holding SysRq (Alt+PrintScreen). It
- also works on a serial console (on PC hardware at least), if you
- send a BREAK and then within 5 seconds a command keypress. The
- keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
- unless you really know what this hack does.
-
-config DEBUG_SPINLOCK
- bool "Spinlock debugging"
- depends on DEBUG_KERNEL
- help
- Say Y here and build SMP to catch missing spinlock initialization
- and certain other kinds of spinlock errors commonly made. This is
- best used in conjunction with the NMI watchdog so that spinlock
- deadlocks are also debuggable.
-
-config DEBUG_SPINLOCK_SLEEP
- bool "Sleep-inside-spinlock checking"
- depends on DEBUG_KERNEL
- help
- If you say Y here, various routines which may sleep will become very
- noisy if they are called with a spinlock held.
-
-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 DEBUG_HIGHMEM
- bool "Highmem debugging"
- depends on DEBUG_KERNEL && HIGHMEM
- help
- This options enables addition error checking for high memory systems.
- Disable for production systems.
-
-config DEBUG_INFO
- bool "Compile the kernel with debug info"
- depends on DEBUG_KERNEL
- help
- If you say Y here the resulting kernel image will include
- debugging info resulting in a larger kernel image.
- Say Y here only if you plan to use gdb to debug the kernel.
- If you don't debug the kernel, you can say N.
-
-config DEBUG_BUGVERBOSE
- bool "Verbose BUG() reporting"
- depends on DEBUG_KERNEL
-
-config FRAME_POINTER
- bool "Compile the kernel with frame pointers"
- depends on DEBUG_KERNEL
- help
- If you say Y here the resulting kernel image will be slightly larger
- and slower, but it will give very useful debugging information.
- If you don't debug the kernel, you can say N, but we may not be able
- to solve problems without frame pointers.
-
-config GDBSTUB
- bool "Remote GDB kernel debugging"
- depends on DEBUG_KERNEL
- select DEBUG_INFO
- select FRAME_POINTER
- help
- If you say Y here, it will be possible to remotely debug the kernel
- using gdb. This enlarges your kernel ELF image disk size by several
- megabytes and requires a machine with more than 16 MB, better 32 MB
- RAM to avoid excessive linking time. This is only useful for kernel
- hackers. If unsure, say N.
-
-choice
- prompt "GDB stub port"
- default GDBSTUB_UART1
- depends on GDBSTUB
- help
- Select the on-CPU port used for GDB-stub
-
-config GDBSTUB_UART0
- bool "/dev/ttyS0"
-
-config GDBSTUB_UART1
- bool "/dev/ttyS1"
-
-endchoice
-
-config GDBSTUB_IMMEDIATE
- bool "Break into GDB stub immediately"
- depends on GDBSTUB
- help
- If you say Y here, GDB stub will break into the program as soon as
- possible, leaving the program counter at the beginning of
- start_kernel() in init/main.c.
-
-config GDB_CONSOLE
- bool "Console output to GDB"
- depends on KGDB
- help
- If you are using GDB for remote debugging over a serial port and
- would like kernel messages to be formatted into GDB $O packets so
- that GDB prints them as program output, say 'Y'.
-
-endmenu
+source "arch/frv/Kconfig.debug"
source "security/Kconfig"
diff --git a/arch/frv/Kconfig.debug b/arch/frv/Kconfig.debug
new file mode 100644
index 0000000000000..0034b654995df
--- /dev/null
+++ b/arch/frv/Kconfig.debug
@@ -0,0 +1,74 @@
+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
+ select DEBUG_INFO
+ select FRAME_POINTER
+ help
+ If you say Y here, it will be possible to remotely debug the kernel
+ using gdb. This enlarges your kernel ELF image disk size by several
+ megabytes and requires a machine with more than 16 MB, better 32 MB
+ RAM to avoid excessive linking time. This is only useful for kernel
+ hackers. If unsure, say N.
+
+choice
+ prompt "GDB stub port"
+ default GDBSTUB_UART1
+ depends on GDBSTUB
+ help
+ Select the on-CPU port used for GDB-stub
+
+config GDBSTUB_UART0
+ bool "/dev/ttyS0"
+
+config GDBSTUB_UART1
+ bool "/dev/ttyS1"
+
+endchoice
+
+config GDBSTUB_IMMEDIATE
+ bool "Break into GDB stub immediately"
+ depends on GDBSTUB
+ help
+ If you say Y here, GDB stub will break into the program as soon as
+ possible, leaving the program counter at the beginning of
+ start_kernel() in init/main.c.
+
+config GDB_CONSOLE
+ bool "Console output to GDB"
+ depends on GDBSTUB
+ help
+ If you are using GDB for remote debugging over a serial port and
+ would like kernel messages to be formatted into GDB $O packets so
+ that GDB prints them as program output, say 'Y'.
+
+endmenu
diff --git a/arch/frv/kernel/setup.c b/arch/frv/kernel/setup.c
index 9ba4979188a82..ef6865f0b9792 100644
--- a/arch/frv/kernel/setup.c
+++ b/arch/frv/kernel/setup.c
@@ -65,9 +65,6 @@ static void __init setup_uclinux_memory(void);
#ifdef CONFIG_CONSOLE
extern struct consw *conswitchp;
-#ifdef CONFIG_FRAMEBUFFER
-extern struct consw fb_con;
-#endif
#endif
#ifdef CONFIG_MB93090_MB00
diff --git a/arch/frv/kernel/signal.c b/arch/frv/kernel/signal.c
index 1fccc1cc531de..d8d8f3d4304d9 100644
--- a/arch/frv/kernel/signal.c
+++ b/arch/frv/kernel/signal.c
@@ -114,7 +114,7 @@ asmlinkage int sys_sigaction(int sig,
if (act) {
old_sigset_t mask;
- if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
+ if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
__get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
__get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
return -EFAULT;
@@ -126,7 +126,7 @@ asmlinkage int sys_sigaction(int sig,
ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
if (!ret && oact) {
- if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
+ if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
__put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
__put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
return -EFAULT;
@@ -197,7 +197,7 @@ asmlinkage int sys_sigreturn(void)
sigset_t set;
int gr8;
- if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
+ if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
goto badframe;
if (__get_user(set.sig[0], &frame->sc.sc_oldmask))
goto badframe;
@@ -225,10 +225,9 @@ asmlinkage int sys_rt_sigreturn(void)
{
struct rt_sigframe __user *frame = (struct rt_sigframe __user *) __frame->sp;
sigset_t set;
- stack_t st;
int gr8;
- if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
+ if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
goto badframe;
if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
goto badframe;
diff --git a/arch/frv/mb93090-mb00/pci-frv.c b/arch/frv/mb93090-mb00/pci-frv.c
index 263a7dd6fc9c2..c5a7f78bf5f98 100644
--- a/arch/frv/mb93090-mb00/pci-frv.c
+++ b/arch/frv/mb93090-mb00/pci-frv.c
@@ -43,7 +43,7 @@ pcibios_update_resource(struct pci_dev *dev, struct resource *root,
pci_read_config_dword(dev, reg, &check);
if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) {
printk(KERN_ERR "PCI: Error while updating region "
- "%s/%d (%08x != %08x)\n", dev->slot_name, resource,
+ "%s/%d (%08x != %08x)\n", pci_name(dev), resource,
new, check);
}
}
@@ -128,7 +128,7 @@ static void __init pcibios_allocate_bus_resources(struct list_head *bus_list)
continue;
pr = pci_find_parent_resource(dev, r);
if (!pr || request_resource(pr, r) < 0)
- printk(KERN_ERR "PCI: Cannot allocate resource region %d of bridge %s\n", idx, dev->slot_name);
+ printk(KERN_ERR "PCI: Cannot allocate resource region %d of bridge %s\n", idx, pci_name(dev));
}
}
pcibios_allocate_bus_resources(&bus->children);
diff --git a/arch/frv/mb93090-mb00/pci-vdk.c b/arch/frv/mb93090-mb00/pci-vdk.c
index 11b5c06714543..c8817f7b8605d 100644
--- a/arch/frv/mb93090-mb00/pci-vdk.c
+++ b/arch/frv/mb93090-mb00/pci-vdk.c
@@ -294,7 +294,7 @@ static void __init pci_fixup_umc_ide(struct pci_dev *d)
*/
int i;
- printk("PCI: Fixing base address flags for device %s\n", d->slot_name);
+ printk("PCI: Fixing base address flags for device %s\n", pci_name(d));
for(i=0; i<4; i++)
d->resource[i].flags |= PCI_BASE_ADDRESS_SPACE_IO;
}
@@ -308,7 +308,7 @@ static void __init pci_fixup_ide_bases(struct pci_dev *d)
*/
if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE)
return;
- printk("PCI: IDE base address fixup for %s\n", d->slot_name);
+ printk("PCI: IDE base address fixup for %s\n", pci_name(d));
for(i=0; i<4; i++) {
struct resource *r = &d->resource[i];
if ((r->start & ~0x80) == 0x374) {
@@ -326,7 +326,7 @@ static void __init pci_fixup_ide_trash(struct pci_dev *d)
* There exist PCI IDE controllers which have utter garbage
* in first four base registers. Ignore that.
*/
- printk("PCI: IDE base address trash cleared for %s\n", d->slot_name);
+ printk("PCI: IDE base address trash cleared for %s\n", pci_name(d));
for(i=0; i<4; i++)
d->resource[i].start = d->resource[i].end = d->resource[i].flags = 0;
}
diff --git a/arch/h8300/kernel/signal.c b/arch/h8300/kernel/signal.c
index 962d4305a3da2..a4799d633ef40 100644
--- a/arch/h8300/kernel/signal.c
+++ b/arch/h8300/kernel/signal.c
@@ -113,7 +113,7 @@ sys_sigaction(int sig, const struct old_sigaction *act,
if (act) {
old_sigset_t mask;
- if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
+ if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
__get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
__get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
return -EFAULT;
@@ -125,7 +125,7 @@ sys_sigaction(int sig, const struct old_sigaction *act,
ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
if (!ret && oact) {
- if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
+ if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
__put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
__put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
return -EFAULT;
@@ -222,7 +222,7 @@ asmlinkage int do_sigreturn(unsigned long __unused,...)
sigset_t set;
int er0;
- if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
+ if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
goto badframe;
if (__get_user(set.sig[0], &frame->sc.sc_mask) ||
(_NSIG_WORDS > 1 &&
@@ -253,7 +253,7 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused,...)
sigset_t set;
int er0;
- if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
+ if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
goto badframe;
if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
goto badframe;
diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig
index 957b8c306f406..17a0cbce6f300 100644
--- a/arch/i386/Kconfig
+++ b/arch/i386/Kconfig
@@ -183,6 +183,7 @@ config M386
- "Winchip-C6" for original IDT Winchip.
- "Winchip-2" for IDT Winchip 2.
- "Winchip-2A" for IDT Winchips with 3dNow! capabilities.
+ - "MediaGX/Geode" for Cyrix MediaGX aka Geode.
- "CyrixIII/VIA C3" for VIA Cyrix III or VIA C3.
- "VIA C3-2 for VIA C3-2 "Nehemiah" (model 9 and above).
@@ -310,6 +311,13 @@ config MWINCHIP3D
stores for this CPU, which can increase performance of some
operations.
+config MGEODE
+ bool "MediaGX/Geode"
+ help
+ Select this for a Cyrix MediaGX aka Geode chip. Linux and GCC
+ treat this chip as a 586TSC with some extended instructions
+ and alignment reqirements.
+
config MCYRIXIII
bool "CyrixIII/VIA-C3"
help
@@ -360,7 +368,7 @@ 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
+ default "5" if MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCRUSOE || MEFFICEON || MCYRIXIII || MK6 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || M586 || MVIAC3_2 || MGEODE
default "6" if MK7 || MK8 || MPENTIUMM
config RWSEM_GENERIC_SPINLOCK
@@ -379,7 +387,7 @@ config GENERIC_CALIBRATE_DELAY
config X86_PPRO_FENCE
bool
- depends on M686 || M586MMX || M586TSC || M586 || M486 || M386
+ depends on M686 || M586MMX || M586TSC || M586 || M486 || M386 || MGEODE
default y
config X86_F00F_BUG
@@ -409,7 +417,7 @@ config X86_POPAD_OK
config X86_ALIGNMENT_16
bool
- depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || X86_ELAN || MK6 || M586MMX || M586TSC || M586 || M486 || MVIAC3_2
+ depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || X86_ELAN || MK6 || M586MMX || M586TSC || M586 || M486 || MVIAC3_2 || MGEODE
default y
config X86_GOOD_APIC
@@ -434,7 +442,7 @@ config X86_USE_3DNOW
config X86_OOSTORE
bool
- depends on (MWINCHIP3D || MWINCHIP2 || MWINCHIPC6) && MTRR
+ depends on (MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MGEODE) && MTRR
default y
config HPET_TIMER
@@ -529,9 +537,9 @@ config PREEMPT_BKL
Say N if you are unsure.
config X86_UP_APIC
- bool "Local APIC support on uniprocessors" if !SMP
- depends on !(X86_VISWS || X86_VOYAGER)
- ---help---
+ bool "Local APIC support on uniprocessors"
+ depends on !SMP && !(X86_VISWS || X86_VOYAGER)
+ help
A local APIC (Advanced Programmable Interrupt Controller) is an
integrated interrupt controller in the CPU. If you have a single-CPU
system which has a processor with a local APIC, you can say Y here to
@@ -541,36 +549,36 @@ config X86_UP_APIC
performance counters), and the NMI watchdog which detects hard
lockups.
- If you have a system with several CPUs, you do not need to say Y
- here: the local APIC will be used automatically.
-
config X86_UP_IOAPIC
bool "IO-APIC support on uniprocessors"
- depends on !SMP && X86_UP_APIC
+ depends on X86_UP_APIC
help
An IO-APIC (I/O Advanced Programmable Interrupt Controller) is an
SMP-capable replacement for PC-style interrupt controllers. Most
- SMP systems and a small number of uniprocessor systems have one.
+ SMP systems and many recent uniprocessor systems have one.
+
If you have a single-CPU system with an IO-APIC, you can say Y here
to use it. If you say Y here even though your machine doesn't have
an IO-APIC, then the kernel will still run with no slowdown at all.
- If you have a system with several CPUs, you do not need to say Y
- here: the IO-APIC will be used automatically.
-
config X86_LOCAL_APIC
bool
- depends on !SMP && X86_UP_APIC
+ depends on X86_UP_APIC || ((X86_VISWS || SMP) && !X86_VOYAGER)
default y
config X86_IO_APIC
bool
- depends on !SMP && X86_UP_IOAPIC
+ depends on X86_UP_IOAPIC || (SMP && !(X86_VISWS || X86_VOYAGER))
+ default y
+
+config X86_VISWS_APIC
+ bool
+ depends on X86_VISWS
default y
config X86_TSC
bool
- depends on (MWINCHIP3D || MWINCHIP2 || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2) && !X86_NUMAQ
+ depends on (MWINCHIP3D || MWINCHIP2 || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2 || MGEODE) && !X86_NUMAQ
default y
config X86_MCE
@@ -769,6 +777,16 @@ config HAVE_ARCH_BOOTMEM_NODE
depends on NUMA
default y
+config HAVE_MEMORY_PRESENT
+ bool
+ depends on DISCONTIGMEM
+ default y
+
+config NEED_NODE_MEMMAP_SIZE
+ bool
+ depends on DISCONTIGMEM
+ default y
+
config HIGHPTE
bool "Allocate 3rd-level pagetables from highmem"
depends on HIGHMEM4G || HIGHMEM64G
@@ -888,6 +906,23 @@ config REGPARM
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
+ default y
+ help
+ This kernel feature is useful for number crunching applications
+ that may need to compute untrusted bytecode during their
+ execution. By using pipes or other transports made available to
+ the process as file descriptors supporting the read/write
+ syscalls, it's possible to isolate those applications in
+ their own address space using seccomp. Once seccomp is
+ enabled via /proc/<pid>/seccomp, it cannot be disabled
+ and the task is only allowed to execute a few safe syscalls
+ defined by each seccomp mode.
+
+ If unsure, say Y. Only embedded should say N here.
+
endmenu
@@ -1052,21 +1087,6 @@ endmenu
menu "Bus options (PCI, PCMCIA, EISA, MCA, ISA)"
-config X86_VISWS_APIC
- bool
- depends on X86_VISWS
- default y
-
-config X86_LOCAL_APIC
- bool
- depends on (X86_VISWS || SMP) && !X86_VOYAGER
- default y
-
-config X86_IO_APIC
- bool
- depends on SMP && !(X86_VISWS || X86_VOYAGER)
- default y
-
config PCI
bool "PCI support" if !X86_VISWS
depends on !X86_VOYAGER
@@ -1164,18 +1184,14 @@ config EISA
source "drivers/eisa/Kconfig"
config MCA
- bool "MCA support"
- depends on !(X86_VISWS || X86_VOYAGER)
+ bool "MCA support" if !(X86_VISWS || X86_VOYAGER)
+ default y if X86_VOYAGER
help
MicroChannel Architecture is found in some IBM PS/2 machines and
laptops. It is a bus system similar to PCI or ISA. See
<file:Documentation/mca.txt> (and especially the web page given
there) before attempting to build an MCA bus kernel.
-config MCA
- depends on X86_VOYAGER
- default y if X86_VOYAGER
-
source "drivers/mca/Kconfig"
config SCx200
diff --git a/arch/i386/Kconfig.debug b/arch/i386/Kconfig.debug
index ffb6642256d92..bfb2064f71042 100644
--- a/arch/i386/Kconfig.debug
+++ b/arch/i386/Kconfig.debug
@@ -3,7 +3,7 @@ menu "Kernel hacking"
source "lib/Kconfig.debug"
config EARLY_PRINTK
- bool "Early printk" if EMBEDDED
+ bool "Early printk" if EMBEDDED && DEBUG_KERNEL
default y
help
Write kernel log output directly into the VGA buffer or to a serial
@@ -38,9 +38,12 @@ config DEBUG_STACK_USAGE
This option will slow down process creation somewhat.
+comment "Page alloc debug is incompatible with Software Suspend on i386"
+ depends on DEBUG_KERNEL && SOFTWARE_SUSPEND
+
config DEBUG_PAGEALLOC
bool "Page alloc debugging"
- depends on DEBUG_KERNEL
+ depends on DEBUG_KERNEL && !SOFTWARE_SUSPEND
help
Unmap pages from the kernel linear mapping after free_pages().
This results in a large slowdown, but helps to find certain types
@@ -48,6 +51,7 @@ config DEBUG_PAGEALLOC
config 4KSTACKS
bool "Use 4Kb for kernel stacks instead of 8Kb"
+ depends on DEBUG_KERNEL
help
If you say Y here the kernel will use a 4Kb stacksize for the
kernel stack attached to each process/thread. This facilitates
diff --git a/arch/i386/Makefile b/arch/i386/Makefile
index 8be151e672587..314c7146e9bf0 100644
--- a/arch/i386/Makefile
+++ b/arch/i386/Makefile
@@ -14,6 +14,8 @@
# 19990713 Artur Skawina <skawina@geocities.com>
# Added '-march' and '-mpreferred-stack-boundary' support
#
+# Kianusch Sayah Karadji <kianusch@sk-tech.net>
+# Added support for GEODE CPU
LDFLAGS := -m elf_i386
OBJCOPYFLAGS := -O binary -R .note -R .comment -S
@@ -52,6 +54,9 @@ cflags-$(CONFIG_MVIAC3_2) += $(call cc-option,-march=c3-2,-march=i686)
# AMD Elan support
cflags-$(CONFIG_X86_ELAN) += -march=i486
+# MediaGX aka Geode support
+cflags-$(CONFIG_MGEODE) += $(call cc-option,-march=pentium-mmx,-march=i586)
+
# -mregparm=3 works ok on gcc-3.0 and later
#
GCC_VERSION := $(call cc-version)
@@ -137,7 +142,10 @@ zlilo bzlilo: vmlinux
zdisk bzdisk: vmlinux
$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) zdisk
-install fdimage fdimage144 fdimage288: vmlinux
+fdimage fdimage144 fdimage288: vmlinux
+ $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) $@
+
+install:
$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) $@
prepare: include/asm-$(ARCH)/asm_offsets.h
diff --git a/arch/i386/defconfig b/arch/i386/defconfig
index 8b91f12fdbc5c..28e620383799a 100644
--- a/arch/i386/defconfig
+++ b/arch/i386/defconfig
@@ -802,7 +802,6 @@ CONFIG_AGP=y
# CONFIG_AGP_AMD is not set
# CONFIG_AGP_AMD64 is not set
CONFIG_AGP_INTEL=y
-CONFIG_AGP_INTEL_MCH=m
# CONFIG_AGP_NVIDIA is not set
# CONFIG_AGP_SIS is not set
# CONFIG_AGP_SWORKS is not set
diff --git a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile
index 711a5249f105d..933787a46b4c4 100644
--- a/arch/i386/kernel/Makefile
+++ b/arch/i386/kernel/Makefile
@@ -46,7 +46,7 @@ targets += vsyscall.lds
# The DSO images are built using a special linker script.
quiet_cmd_syscall = SYSCALL $@
- cmd_syscall = $(CC) -nostdlib $(SYSCFLAGS_$(@F)) \
+ cmd_syscall = $(CC) -m elf_i386 -nostdlib $(SYSCFLAGS_$(@F)) \
-Wl,-T,$(filter-out FORCE,$^) -o $@
export CPPFLAGS_vsyscall.lds += -P -C -U$(ARCH)
diff --git a/arch/i386/kernel/acpi/sleep.c b/arch/i386/kernel/acpi/sleep.c
index be4df5548111f..0b7e2d381a3eb 100644
--- a/arch/i386/kernel/acpi/sleep.c
+++ b/arch/i386/kernel/acpi/sleep.c
@@ -46,15 +46,6 @@ int acpi_save_state_mem (void)
return 0;
}
-/**
- * acpi_save_state_disk - save kernel state to disk
- *
- */
-int acpi_save_state_disk (void)
-{
- return 1;
-}
-
/*
* acpi_restore_state - undo effects of acpi_save_state_mem
*/
diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c
index 1fff2fcee2425..35c1751ea0b02 100644
--- a/arch/i386/kernel/apic.c
+++ b/arch/i386/kernel/apic.c
@@ -894,7 +894,7 @@ static void __init wait_8254_wraparound(void)
* Default initialization for 8254 timers. If we use other timers like HPET,
* we override this later
*/
-void (*wait_timer_tick)(void) = wait_8254_wraparound;
+void (*wait_timer_tick)(void) __initdata = wait_8254_wraparound;
/*
* This function sets up the local APIC timer, with a timeout of
@@ -909,7 +909,7 @@ void (*wait_timer_tick)(void) = wait_8254_wraparound;
#define APIC_DIVISOR 16
-void __setup_APIC_LVTT(unsigned int clocks)
+static void __setup_APIC_LVTT(unsigned int clocks)
{
unsigned int lvtt_value, tmp_value, ver;
@@ -930,7 +930,7 @@ void __setup_APIC_LVTT(unsigned int clocks)
apic_write_around(APIC_TMICT, clocks/APIC_DIVISOR);
}
-static void setup_APIC_timer(unsigned int clocks)
+static void __init setup_APIC_timer(unsigned int clocks)
{
unsigned long flags;
@@ -959,7 +959,7 @@ static void setup_APIC_timer(unsigned int clocks)
* APIC irq that way.
*/
-int __init calibrate_APIC_clock(void)
+static int __init calibrate_APIC_clock(void)
{
unsigned long long t1 = 0, t2 = 0;
long tt1, tt2;
@@ -1165,7 +1165,7 @@ fastcall void smp_apic_timer_interrupt(struct pt_regs *regs)
/*
* the NMI deadlock-detector uses this.
*/
- irq_stat[cpu].apic_timer_irqs++;
+ per_cpu(irq_stat, cpu).apic_timer_irqs++;
/*
* NOTE! We'd better ACK the irq immediately,
diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c
index a005116491f94..45641a8725500 100644
--- a/arch/i386/kernel/apm.c
+++ b/arch/i386/kernel/apm.c
@@ -166,14 +166,14 @@
* If an APM idle fails log it and idle sensibly
* 1.15: Don't queue events to clients who open the device O_WRONLY.
* Don't expect replies from clients who open the device O_RDONLY.
- * (Idea from Thomas Hood <jdthood@mail.com>)
+ * (Idea from Thomas Hood)
* Minor waitqueue cleanups. (John Fremlin <chief@bandits.org>)
* 1.16: Fix idle calling. (Andreas Steinmetz <ast@domdv.de> et al.)
* Notify listeners of standby or suspend events before notifying
* drivers. Return EBUSY to ioctl() if suspend is rejected.
* (Russell King <rmk@arm.linux.org.uk> and Thomas Hood)
* Ignore first resume after we generate our own resume event
- * after a suspend (Thomas Hood <jdthood@mail.com>)
+ * after a suspend (Thomas Hood)
* Daemonize now gets rid of our controlling terminal (sfr).
* CONFIG_APM_CPU_IDLE now just affects the default value of
* idle_threshold (sfr).
@@ -1202,10 +1202,11 @@ static int suspend(int vetoable)
}
device_suspend(PMSG_SUSPEND);
+ local_irq_disable();
device_power_down(PMSG_SUSPEND);
/* serialize with the timer interrupt */
- write_seqlock_irq(&xtime_lock);
+ write_seqlock(&xtime_lock);
/* protect against access to timer chip registers */
spin_lock(&i8253_lock);
@@ -1216,20 +1217,22 @@ static int suspend(int vetoable)
* We'll undo any timer changes due to interrupts below.
*/
spin_unlock(&i8253_lock);
- write_sequnlock_irq(&xtime_lock);
+ write_sequnlock(&xtime_lock);
+ local_irq_enable();
save_processor_state();
err = set_system_power_state(APM_STATE_SUSPEND);
restore_processor_state();
- write_seqlock_irq(&xtime_lock);
+ local_irq_disable();
+ write_seqlock(&xtime_lock);
spin_lock(&i8253_lock);
reinit_timer();
set_time();
ignore_normal_resume = 1;
spin_unlock(&i8253_lock);
- write_sequnlock_irq(&xtime_lock);
+ write_sequnlock(&xtime_lock);
if (err == APM_NO_ERROR)
err = APM_SUCCESS;
@@ -1237,6 +1240,7 @@ static int suspend(int vetoable)
apm_error("suspend", err);
err = (err == APM_SUCCESS) ? 0 : -EIO;
device_power_up();
+ local_irq_enable();
device_resume();
pm_send_all(PM_RESUME, (void *)0);
queue_event(APM_NORMAL_RESUME, NULL);
@@ -1255,17 +1259,22 @@ static void standby(void)
{
int err;
+ local_irq_disable();
device_power_down(PMSG_SUSPEND);
/* serialize with the timer interrupt */
- write_seqlock_irq(&xtime_lock);
+ write_seqlock(&xtime_lock);
/* If needed, notify drivers here */
get_time_diff();
- write_sequnlock_irq(&xtime_lock);
+ write_sequnlock(&xtime_lock);
+ local_irq_enable();
err = set_system_power_state(APM_STATE_STANDBY);
if ((err != APM_SUCCESS) && (err != APM_NO_ERROR))
apm_error("standby", err);
+
+ local_irq_disable();
device_power_up();
+ local_irq_enable();
}
static apm_event_t get_event(void)
diff --git a/arch/i386/kernel/asm-offsets.c b/arch/i386/kernel/asm-offsets.c
index 38d82e38093b6..36d66e2077d04 100644
--- a/arch/i386/kernel/asm-offsets.c
+++ b/arch/i386/kernel/asm-offsets.c
@@ -7,6 +7,7 @@
#include <linux/sched.h>
#include <linux/signal.h>
#include <linux/personality.h>
+#include <linux/suspend.h>
#include <asm/ucontext.h>
#include "sigframe.h"
#include <asm/fixmap.h>
@@ -56,6 +57,11 @@ void foo(void)
OFFSET(EXEC_DOMAIN_handler, exec_domain, handler);
OFFSET(RT_SIGFRAME_sigcontext, rt_sigframe, uc.uc_mcontext);
+ BLANK();
+
+ OFFSET(pbe_address, pbe, address);
+ OFFSET(pbe_orig_address, pbe, orig_address);
+ OFFSET(pbe_next, pbe, next);
/* Offset from the sysenter stack to tss.esp0 */
DEFINE(TSS_sysenter_esp0, offsetof(struct tss_struct, esp0) -
diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c
index 026167739bfde..ebd5d8247faae 100644
--- a/arch/i386/kernel/cpu/common.c
+++ b/arch/i386/kernel/cpu/common.c
@@ -21,6 +21,9 @@
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);
+
static int cachesize_override __initdata = -1;
static int disable_x86_fxsr __initdata = 0;
static int disable_x86_serial_nr __initdata = 1;
@@ -199,7 +202,7 @@ static inline int flag_is_changeable_p(u32 flag)
/* Probe for the CPUID instruction */
-int __init have_cpuid_p(void)
+static int __init have_cpuid_p(void)
{
return flag_is_changeable_p(X86_EFLAGS_ID);
}
@@ -207,7 +210,7 @@ int __init 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. */
-void __init early_cpu_detect(void)
+static void __init early_cpu_detect(void)
{
struct cpuinfo_x86 *c = &boot_cpu_data;
@@ -426,16 +429,6 @@ void __init identify_cpu(struct cpuinfo_x86 *c)
mcheck_init(c);
#endif
}
-/*
- * Perform early boot up checks for a valid TSC. See arch/i386/kernel/time.c
- */
-
-void __init dodgy_tsc(void)
-{
- if (( boot_cpu_data.x86_vendor == X86_VENDOR_CYRIX ) ||
- ( boot_cpu_data.x86_vendor == X86_VENDOR_NSC ))
- cpu_devs[X86_VENDOR_CYRIX]->c_init(&boot_cpu_data);
-}
#ifdef CONFIG_X86_HT
void __init detect_ht(struct cpuinfo_x86 *c)
@@ -523,7 +516,6 @@ extern int transmeta_init_cpu(void);
extern int rise_init_cpu(void);
extern int nexgen_init_cpu(void);
extern int umc_init_cpu(void);
-void early_cpu_detect(void);
void __init early_cpu_init(void)
{
@@ -557,6 +549,7 @@ void __init cpu_init (void)
int cpu = smp_processor_id();
struct tss_struct * t = &per_cpu(init_tss, cpu);
struct thread_struct *thread = &current->thread;
+ __u32 stk16_off = (__u32)&per_cpu(cpu_16bit_stack, cpu);
if (cpu_test_and_set(cpu, cpu_initialized)) {
printk(KERN_WARNING "CPU#%d already initialized!\n", cpu);
@@ -579,6 +572,13 @@ void __init cpu_init (void)
*/
memcpy(&per_cpu(cpu_gdt_table, cpu), cpu_gdt_table,
GDT_SIZE);
+
+ /* Set up GDT entry for 16bit stack */
+ *(__u64 *)&(per_cpu(cpu_gdt_table, cpu)[GDT_ENTRY_ESPFIX_SS]) |=
+ ((((__u64)stk16_off) << 16) & 0x000000ffffff0000ULL) |
+ ((((__u64)stk16_off) << 32) & 0xff00000000000000ULL) |
+ (CPU_16BIT_STACK_SIZE - 1);
+
cpu_gdt_descr[cpu].size = GDT_SIZE - 1;
cpu_gdt_descr[cpu].address =
(unsigned long)&per_cpu(cpu_gdt_table, cpu);
diff --git a/arch/i386/kernel/cpu/cpu.h b/arch/i386/kernel/cpu/cpu.h
index 9df38d993c396..5a1d4f163e84d 100644
--- a/arch/i386/kernel/cpu/cpu.h
+++ b/arch/i386/kernel/cpu/cpu.h
@@ -25,7 +25,6 @@ extern int get_model_name(struct cpuinfo_x86 *c);
extern void display_cacheinfo(struct cpuinfo_x86 *c);
extern void generic_identify(struct cpuinfo_x86 * c);
-extern int have_cpuid_p(void);
extern void early_intel_workaround(struct cpuinfo_x86 *c);
diff --git a/arch/i386/kernel/cpu/cpufreq/Kconfig b/arch/i386/kernel/cpu/cpufreq/Kconfig
index 0283d7561343b..f25ffd74235ca 100644
--- a/arch/i386/kernel/cpu/cpufreq/Kconfig
+++ b/arch/i386/kernel/cpu/cpufreq/Kconfig
@@ -6,22 +6,14 @@ menu "CPU Frequency scaling"
source "drivers/cpufreq/Kconfig"
-config CPU_FREQ_TABLE
- tristate "CPU frequency table helpers"
- depends on CPU_FREQ
- default y
- help
- Many CPUFreq drivers use these helpers, so only say N here if
- the CPUFreq driver of your choice doesn't need these helpers.
-
- If in doubt, say Y.
+if CPU_FREQ
comment "CPUFreq processor drivers"
- depends on CPU_FREQ
config X86_ACPI_CPUFREQ
tristate "ACPI Processor P-States driver"
- depends on CPU_FREQ_TABLE && ACPI_PROCESSOR
+ select CPU_FREQ_TABLE
+ depends on ACPI_PROCESSOR
help
This driver adds a CPUFreq driver which utilizes the ACPI
Processor Performance States.
@@ -32,7 +24,8 @@ config X86_ACPI_CPUFREQ
config ELAN_CPUFREQ
tristate "AMD Elan"
- depends on CPU_FREQ_TABLE && X86_ELAN
+ select CPU_FREQ_TABLE
+ depends on X86_ELAN
---help---
This adds the CPUFreq driver for AMD Elan SC400 and SC410
processors.
@@ -47,7 +40,7 @@ config ELAN_CPUFREQ
config X86_POWERNOW_K6
tristate "AMD Mobile K6-2/K6-3 PowerNow!"
- depends on CPU_FREQ_TABLE
+ select CPU_FREQ_TABLE
help
This adds the CPUFreq driver for mobile AMD K6-2+ and mobile
AMD K6-3+ processors.
@@ -58,7 +51,7 @@ config X86_POWERNOW_K6
config X86_POWERNOW_K7
tristate "AMD Mobile Athlon/Duron PowerNow!"
- depends on CPU_FREQ_TABLE
+ select CPU_FREQ_TABLE
help
This adds the CPUFreq driver for mobile AMD K7 mobile processors.
@@ -68,12 +61,14 @@ config X86_POWERNOW_K7
config X86_POWERNOW_K7_ACPI
bool
- depends on ((X86_POWERNOW_K7 = "m" && ACPI_PROCESSOR) || (X86_POWERNOW_K7 = "y" && ACPI_PROCESSOR = "y"))
+ depends on X86_POWERNOW_K7 && ACPI_PROCESSOR
+ depends on !(X86_POWERNOW_K7 = y && ACPI_PROCESSOR = m)
default y
config X86_POWERNOW_K8
tristate "AMD Opteron/Athlon64 PowerNow!"
- depends on CPU_FREQ_TABLE && EXPERIMENTAL
+ select CPU_FREQ_TABLE
+ depends on EXPERIMENTAL
help
This adds the CPUFreq driver for mobile AMD Opteron/Athlon64 processors.
@@ -83,12 +78,12 @@ config X86_POWERNOW_K8
config X86_POWERNOW_K8_ACPI
bool
- depends on ((X86_POWERNOW_K8 = "m" && ACPI_PROCESSOR) || (X86_POWERNOW_K8 = "y" && ACPI_PROCESSOR = "y"))
+ depends on X86_POWERNOW_K8 && ACPI_PROCESSOR
+ depends on !(X86_POWERNOW_K8 = y && ACPI_PROCESSOR = m)
default y
config X86_GX_SUSPMOD
tristate "Cyrix MediaGX/NatSemi Geode Suspend Modulation"
- depends on CPU_FREQ
help
This add the CPUFreq driver for NatSemi Geode processors which
support suspend modulation.
@@ -99,7 +94,7 @@ config X86_GX_SUSPMOD
config X86_SPEEDSTEP_CENTRINO
tristate "Intel Enhanced SpeedStep"
- depends on CPU_FREQ_TABLE
+ select CPU_FREQ_TABLE
select X86_SPEEDSTEP_CENTRINO_TABLE if (!X86_SPEEDSTEP_CENTRINO_ACPI)
help
This adds the CPUFreq driver for Enhanced SpeedStep enabled
@@ -114,8 +109,8 @@ config X86_SPEEDSTEP_CENTRINO
config X86_SPEEDSTEP_CENTRINO_ACPI
bool "Use ACPI tables to decode valid frequency/voltage pairs"
- depends on X86_SPEEDSTEP_CENTRINO
- depends on ((X86_SPEEDSTEP_CENTRINO = "m" && ACPI_PROCESSOR) || (X86_SPEEDSTEP_CENTRINO = "y" && ACPI_PROCESSOR = "y"))
+ depends on X86_SPEEDSTEP_CENTRINO && ACPI_PROCESSOR
+ depends on !(X86_SPEEDSTEP_CENTRINO = y && ACPI_PROCESSOR = m)
default y
help
Use primarily the information provided in the BIOS ACPI tables
@@ -136,7 +131,7 @@ config X86_SPEEDSTEP_CENTRINO_TABLE
config X86_SPEEDSTEP_ICH
tristate "Intel Speedstep on ICH-M chipsets (ioport interface)"
- depends on CPU_FREQ_TABLE
+ select CPU_FREQ_TABLE
help
This adds the CPUFreq driver for certain mobile Intel Pentium III
(Coppermine), all mobile Intel Pentium III-M (Tualatin) and all
@@ -149,7 +144,8 @@ config X86_SPEEDSTEP_ICH
config X86_SPEEDSTEP_SMI
tristate "Intel SpeedStep on 440BX/ZX/MX chipsets (SMI interface)"
- depends on CPU_FREQ_TABLE && EXPERIMENTAL
+ select CPU_FREQ_TABLE
+ depends on EXPERIMENTAL
help
This adds the CPUFreq driver for certain mobile Intel Pentium III
(Coppermine), all mobile Intel Pentium III-M (Tualatin)
@@ -161,7 +157,7 @@ config X86_SPEEDSTEP_SMI
config X86_P4_CLOCKMOD
tristate "Intel Pentium 4 clock modulation"
- depends on CPU_FREQ_TABLE
+ select CPU_FREQ_TABLE
help
This adds the CPUFreq driver for Intel Pentium 4 / XEON
processors.
@@ -172,7 +168,7 @@ config X86_P4_CLOCKMOD
config X86_CPUFREQ_NFORCE2
tristate "nVidia nForce2 FSB changing"
- depends on CPU_FREQ && EXPERIMENTAL
+ depends on EXPERIMENTAL
help
This adds the CPUFreq driver for FSB changing on nVidia nForce2
platforms.
@@ -183,7 +179,6 @@ config X86_CPUFREQ_NFORCE2
config X86_LONGRUN
tristate "Transmeta LongRun"
- depends on CPU_FREQ
help
This adds the CPUFreq driver for Transmeta Crusoe and Efficeon processors
which support LongRun.
@@ -194,7 +189,7 @@ config X86_LONGRUN
config X86_LONGHAUL
tristate "VIA Cyrix III Longhaul"
- depends on CPU_FREQ_TABLE
+ select CPU_FREQ_TABLE
help
This adds the CPUFreq driver for VIA Samuel/CyrixIII,
VIA Cyrix Samuel/C3, VIA Cyrix Ezra and VIA Cyrix Ezra-T
@@ -205,7 +200,6 @@ config X86_LONGHAUL
If in doubt, say N.
comment "shared options"
- depends on CPU_FREQ
config X86_ACPI_CPUFREQ_PROC_INTF
bool "/proc/acpi/processor/../performance interface (deprecated)"
@@ -220,8 +214,7 @@ config X86_ACPI_CPUFREQ_PROC_INTF
config X86_SPEEDSTEP_LIB
tristate
- depends on (X86_SPEEDSTEP_ICH || X86_SPEEDSTEP_SMI || X86_P4_CLOCKMOD)
- default (X86_SPEEDSTEP_ICH || X86_SPEEDSTEP_SMI || X86_P4_CLOCKMOD)
+ default X86_SPEEDSTEP_ICH || X86_SPEEDSTEP_SMI || X86_P4_CLOCKMOD
config X86_SPEEDSTEP_RELAXED_CAP_CHECK
bool "Relaxed speedstep capability checks"
@@ -233,5 +226,6 @@ config X86_SPEEDSTEP_RELAXED_CAP_CHECK
option lets the probing code bypass some of those checks if the
parameter "relaxed_check=1" is passed to the module.
+endif # CPU_FREQ
endmenu
diff --git a/arch/i386/kernel/cpu/cyrix.c b/arch/i386/kernel/cpu/cyrix.c
index 98b85b60477b9..ba4b01138c8f6 100644
--- a/arch/i386/kernel/cpu/cyrix.c
+++ b/arch/i386/kernel/cpu/cyrix.c
@@ -12,7 +12,7 @@
/*
* Read NSC/Cyrix DEVID registers (DIR) to get more detailed info. about the CPU
*/
-void __init do_cyrix_devid(unsigned char *dir0, unsigned char *dir1)
+static void __init do_cyrix_devid(unsigned char *dir0, unsigned char *dir1)
{
unsigned char ccr2, ccr3;
unsigned long flags;
diff --git a/arch/i386/kernel/cpu/intel_cacheinfo.c b/arch/i386/kernel/cpu/intel_cacheinfo.c
index d7c8f7b9f72a5..7d1d350bf87e8 100644
--- a/arch/i386/kernel/cpu/intel_cacheinfo.c
+++ b/arch/i386/kernel/cpu/intel_cacheinfo.c
@@ -1,5 +1,18 @@
+/*
+ * Routines to indentify caches on Intel CPU.
+ *
+ * Changes:
+ * Venkatesh Pallipadi : Adding cache identification through cpuid(4)
+ */
+
#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/compiler.h>
+#include <linux/cpu.h>
+
#include <asm/processor.h>
+#include <asm/smp.h>
#define LVL_1_INST 1
#define LVL_1_DATA 2
@@ -58,10 +71,142 @@ static struct _cache_table cache_table[] __initdata =
{ 0x00, 0, 0}
};
+
+enum _cache_type
+{
+ CACHE_TYPE_NULL = 0,
+ CACHE_TYPE_DATA = 1,
+ CACHE_TYPE_INST = 2,
+ CACHE_TYPE_UNIFIED = 3
+};
+
+union _cpuid4_leaf_eax {
+ struct {
+ enum _cache_type type:5;
+ unsigned int level:3;
+ unsigned int is_self_initializing:1;
+ unsigned int is_fully_associative:1;
+ unsigned int reserved:4;
+ unsigned int num_threads_sharing:12;
+ unsigned int num_cores_on_die:6;
+ } split;
+ u32 full;
+};
+
+union _cpuid4_leaf_ebx {
+ struct {
+ unsigned int coherency_line_size:12;
+ unsigned int physical_line_partition:10;
+ unsigned int ways_of_associativity:10;
+ } split;
+ u32 full;
+};
+
+union _cpuid4_leaf_ecx {
+ struct {
+ unsigned int number_of_sets:32;
+ } split;
+ u32 full;
+};
+
+struct _cpuid4_info {
+ union _cpuid4_leaf_eax eax;
+ union _cpuid4_leaf_ebx ebx;
+ union _cpuid4_leaf_ecx ecx;
+ unsigned long size;
+ cpumask_t shared_cpu_map;
+};
+
+#define MAX_CACHE_LEAVES 4
+static unsigned short __devinitdata num_cache_leaves;
+
+static int __devinit cpuid4_cache_lookup(int index, struct _cpuid4_info *this_leaf)
+{
+ unsigned int eax, ebx, ecx, edx;
+ union _cpuid4_leaf_eax cache_eax;
+
+ cpuid_count(4, index, &eax, &ebx, &ecx, &edx);
+ cache_eax.full = eax;
+ if (cache_eax.split.type == CACHE_TYPE_NULL)
+ return -1;
+
+ this_leaf->eax.full = eax;
+ this_leaf->ebx.full = ebx;
+ this_leaf->ecx.full = ecx;
+ this_leaf->size = (this_leaf->ecx.split.number_of_sets + 1) *
+ (this_leaf->ebx.split.coherency_line_size + 1) *
+ (this_leaf->ebx.split.physical_line_partition + 1) *
+ (this_leaf->ebx.split.ways_of_associativity + 1);
+ return 0;
+}
+
+static int __init find_num_cache_leaves(void)
+{
+ unsigned int eax, ebx, ecx, edx;
+ union _cpuid4_leaf_eax cache_eax;
+ int i;
+ int retval;
+
+ retval = MAX_CACHE_LEAVES;
+ /* Do cpuid(4) loop to find out num_cache_leaves */
+ for (i = 0; i < MAX_CACHE_LEAVES; i++) {
+ cpuid_count(4, i, &eax, &ebx, &ecx, &edx);
+ cache_eax.full = eax;
+ if (cache_eax.split.type == CACHE_TYPE_NULL) {
+ retval = i;
+ break;
+ }
+ }
+ return retval;
+}
+
unsigned int __init init_intel_cacheinfo(struct cpuinfo_x86 *c)
{
unsigned int trace = 0, l1i = 0, l1d = 0, l2 = 0, l3 = 0; /* Cache sizes */
+ unsigned int new_l1d = 0, new_l1i = 0; /* Cache sizes from cpuid(4) */
+ unsigned int new_l2 = 0, new_l3 = 0, i; /* Cache sizes from cpuid(4) */
+
+ if (c->cpuid_level > 4) {
+ static int is_initialized;
+
+ if (is_initialized == 0) {
+ /* Init num_cache_leaves from boot CPU */
+ num_cache_leaves = find_num_cache_leaves();
+ is_initialized++;
+ }
+
+ /*
+ * Whenever possible use cpuid(4), deterministic cache
+ * parameters cpuid leaf to find the cache details
+ */
+ for (i = 0; i < num_cache_leaves; i++) {
+ struct _cpuid4_info this_leaf;
+
+ int retval;
+ retval = cpuid4_cache_lookup(i, &this_leaf);
+ if (retval >= 0) {
+ switch(this_leaf.eax.split.level) {
+ case 1:
+ if (this_leaf.eax.split.type ==
+ CACHE_TYPE_DATA)
+ new_l1d = this_leaf.size/1024;
+ else if (this_leaf.eax.split.type ==
+ CACHE_TYPE_INST)
+ new_l1i = this_leaf.size/1024;
+ break;
+ case 2:
+ new_l2 = this_leaf.size/1024;
+ break;
+ case 3:
+ new_l3 = this_leaf.size/1024;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
if (c->cpuid_level > 1) {
/* supports eax=2 call */
int i, j, n;
@@ -114,6 +259,18 @@ unsigned int __init init_intel_cacheinfo(struct cpuinfo_x86 *c)
}
}
+ if (new_l1d)
+ l1d = new_l1d;
+
+ if (new_l1i)
+ l1i = new_l1i;
+
+ if (new_l2)
+ l2 = new_l2;
+
+ if (new_l3)
+ l3 = new_l3;
+
if ( trace )
printk (KERN_INFO "CPU: Trace cache: %dK uops", trace);
else if ( l1i )
@@ -138,3 +295,302 @@ unsigned int __init init_intel_cacheinfo(struct cpuinfo_x86 *c)
return l2;
}
+
+/* pointer to _cpuid4_info array (for each cache leaf) */
+static struct _cpuid4_info *cpuid4_info[NR_CPUS];
+#define CPUID4_INFO_IDX(x,y) (&((cpuid4_info[x])[y]))
+
+#ifdef CONFIG_SMP
+static void __devinit cache_shared_cpu_map_setup(unsigned int cpu, int index)
+{
+ struct _cpuid4_info *this_leaf;
+ unsigned long num_threads_sharing;
+
+ this_leaf = CPUID4_INFO_IDX(cpu, index);
+ num_threads_sharing = 1 + this_leaf->eax.split.num_threads_sharing;
+
+ if (num_threads_sharing == 1)
+ cpu_set(cpu, this_leaf->shared_cpu_map);
+ else if (num_threads_sharing == smp_num_siblings)
+ this_leaf->shared_cpu_map = cpu_sibling_map[cpu];
+ else
+ printk(KERN_INFO "Number of CPUs sharing cache didn't match "
+ "any known set of CPUs\n");
+}
+#else
+static void __init cache_shared_cpu_map_setup(unsigned int cpu, int index) {}
+#endif
+
+static void free_cache_attributes(unsigned int cpu)
+{
+ kfree(cpuid4_info[cpu]);
+ cpuid4_info[cpu] = NULL;
+}
+
+static int __devinit detect_cache_attributes(unsigned int cpu)
+{
+ struct _cpuid4_info *this_leaf;
+ unsigned long j;
+ int retval;
+
+ if (num_cache_leaves == 0)
+ return -ENOENT;
+
+ cpuid4_info[cpu] = kmalloc(
+ sizeof(struct _cpuid4_info) * num_cache_leaves, GFP_KERNEL);
+ if (unlikely(cpuid4_info[cpu] == NULL))
+ return -ENOMEM;
+ memset(cpuid4_info[cpu], 0,
+ sizeof(struct _cpuid4_info) * num_cache_leaves);
+
+ /* Do cpuid and store the results */
+ for (j = 0; j < num_cache_leaves; j++) {
+ this_leaf = CPUID4_INFO_IDX(cpu, j);
+ retval = cpuid4_cache_lookup(j, this_leaf);
+ if (unlikely(retval < 0))
+ goto err_out;
+ cache_shared_cpu_map_setup(cpu, j);
+ }
+ return 0;
+
+err_out:
+ free_cache_attributes(cpu);
+ return -ENOMEM;
+}
+
+#ifdef CONFIG_SYSFS
+
+#include <linux/kobject.h>
+#include <linux/sysfs.h>
+
+extern struct sysdev_class cpu_sysdev_class; /* from drivers/base/cpu.c */
+
+/* pointer to kobject for cpuX/cache */
+static struct kobject * cache_kobject[NR_CPUS];
+
+struct _index_kobject {
+ struct kobject kobj;
+ unsigned int cpu;
+ unsigned short index;
+};
+
+/* pointer to array of kobjects for cpuX/cache/indexY */
+static struct _index_kobject *index_kobject[NR_CPUS];
+#define INDEX_KOBJECT_PTR(x,y) (&((index_kobject[x])[y]))
+
+#define show_one_plus(file_name, object, val) \
+static ssize_t show_##file_name \
+ (struct _cpuid4_info *this_leaf, char *buf) \
+{ \
+ return sprintf (buf, "%lu\n", (unsigned long)this_leaf->object + val); \
+}
+
+show_one_plus(level, eax.split.level, 0);
+show_one_plus(coherency_line_size, ebx.split.coherency_line_size, 1);
+show_one_plus(physical_line_partition, ebx.split.physical_line_partition, 1);
+show_one_plus(ways_of_associativity, ebx.split.ways_of_associativity, 1);
+show_one_plus(number_of_sets, ecx.split.number_of_sets, 1);
+
+static ssize_t show_size(struct _cpuid4_info *this_leaf, char *buf)
+{
+ return sprintf (buf, "%luK\n", this_leaf->size / 1024);
+}
+
+static ssize_t show_shared_cpu_map(struct _cpuid4_info *this_leaf, char *buf)
+{
+ char mask_str[NR_CPUS];
+ cpumask_scnprintf(mask_str, NR_CPUS, this_leaf->shared_cpu_map);
+ return sprintf(buf, "%s\n", mask_str);
+}
+
+static ssize_t show_type(struct _cpuid4_info *this_leaf, char *buf) {
+ switch(this_leaf->eax.split.type) {
+ case CACHE_TYPE_DATA:
+ return sprintf(buf, "Data\n");
+ break;
+ case CACHE_TYPE_INST:
+ return sprintf(buf, "Instruction\n");
+ break;
+ case CACHE_TYPE_UNIFIED:
+ return sprintf(buf, "Unified\n");
+ break;
+ default:
+ return sprintf(buf, "Unknown\n");
+ break;
+ }
+}
+
+struct _cache_attr {
+ struct attribute attr;
+ ssize_t (*show)(struct _cpuid4_info *, char *);
+ ssize_t (*store)(struct _cpuid4_info *, const char *, size_t count);
+};
+
+#define define_one_ro(_name) \
+static struct _cache_attr _name = \
+ __ATTR(_name, 0444, show_##_name, NULL)
+
+define_one_ro(level);
+define_one_ro(type);
+define_one_ro(coherency_line_size);
+define_one_ro(physical_line_partition);
+define_one_ro(ways_of_associativity);
+define_one_ro(number_of_sets);
+define_one_ro(size);
+define_one_ro(shared_cpu_map);
+
+static struct attribute * default_attrs[] = {
+ &type.attr,
+ &level.attr,
+ &coherency_line_size.attr,
+ &physical_line_partition.attr,
+ &ways_of_associativity.attr,
+ &number_of_sets.attr,
+ &size.attr,
+ &shared_cpu_map.attr,
+ NULL
+};
+
+#define to_object(k) container_of(k, struct _index_kobject, kobj)
+#define to_attr(a) container_of(a, struct _cache_attr, attr)
+
+static ssize_t show(struct kobject * kobj, struct attribute * attr, char * buf)
+{
+ struct _cache_attr *fattr = to_attr(attr);
+ struct _index_kobject *this_leaf = to_object(kobj);
+ ssize_t ret;
+
+ ret = fattr->show ?
+ fattr->show(CPUID4_INFO_IDX(this_leaf->cpu, this_leaf->index),
+ buf) :
+ 0;
+ return ret;
+}
+
+static ssize_t store(struct kobject * kobj, struct attribute * attr,
+ const char * buf, size_t count)
+{
+ return 0;
+}
+
+static struct sysfs_ops sysfs_ops = {
+ .show = show,
+ .store = store,
+};
+
+static struct kobj_type ktype_cache = {
+ .sysfs_ops = &sysfs_ops,
+ .default_attrs = default_attrs,
+};
+
+static struct kobj_type ktype_percpu_entry = {
+ .sysfs_ops = &sysfs_ops,
+};
+
+static void cpuid4_cache_sysfs_exit(unsigned int cpu)
+{
+ kfree(cache_kobject[cpu]);
+ kfree(index_kobject[cpu]);
+ cache_kobject[cpu] = NULL;
+ index_kobject[cpu] = NULL;
+ free_cache_attributes(cpu);
+}
+
+static int __devinit cpuid4_cache_sysfs_init(unsigned int cpu)
+{
+
+ if (num_cache_leaves == 0)
+ return -ENOENT;
+
+ detect_cache_attributes(cpu);
+ if (cpuid4_info[cpu] == NULL)
+ return -ENOENT;
+
+ /* Allocate all required memory */
+ cache_kobject[cpu] = kmalloc(sizeof(struct kobject), GFP_KERNEL);
+ if (unlikely(cache_kobject[cpu] == NULL))
+ goto err_out;
+ memset(cache_kobject[cpu], 0, sizeof(struct kobject));
+
+ index_kobject[cpu] = kmalloc(
+ sizeof(struct _index_kobject ) * num_cache_leaves, GFP_KERNEL);
+ if (unlikely(index_kobject[cpu] == NULL))
+ goto err_out;
+ memset(index_kobject[cpu], 0,
+ sizeof(struct _index_kobject) * num_cache_leaves);
+
+ return 0;
+
+err_out:
+ cpuid4_cache_sysfs_exit(cpu);
+ return -ENOMEM;
+}
+
+/* Add/Remove cache interface for CPU device */
+static int __devinit cache_add_dev(struct sys_device * sys_dev)
+{
+ unsigned int cpu = sys_dev->id;
+ unsigned long i, j;
+ struct _index_kobject *this_object;
+ int retval = 0;
+
+ retval = cpuid4_cache_sysfs_init(cpu);
+ if (unlikely(retval < 0))
+ return retval;
+
+ cache_kobject[cpu]->parent = &sys_dev->kobj;
+ kobject_set_name(cache_kobject[cpu], "%s", "cache");
+ cache_kobject[cpu]->ktype = &ktype_percpu_entry;
+ retval = kobject_register(cache_kobject[cpu]);
+
+ for (i = 0; i < num_cache_leaves; i++) {
+ this_object = INDEX_KOBJECT_PTR(cpu,i);
+ this_object->cpu = cpu;
+ this_object->index = i;
+ this_object->kobj.parent = cache_kobject[cpu];
+ kobject_set_name(&(this_object->kobj), "index%1lu", i);
+ this_object->kobj.ktype = &ktype_cache;
+ retval = kobject_register(&(this_object->kobj));
+ if (unlikely(retval)) {
+ for (j = 0; j < i; j++) {
+ kobject_unregister(
+ &(INDEX_KOBJECT_PTR(cpu,j)->kobj));
+ }
+ kobject_unregister(cache_kobject[cpu]);
+ cpuid4_cache_sysfs_exit(cpu);
+ break;
+ }
+ }
+ return retval;
+}
+
+static int __devexit cache_remove_dev(struct sys_device * sys_dev)
+{
+ unsigned int cpu = sys_dev->id;
+ unsigned long i;
+
+ for (i = 0; i < num_cache_leaves; i++)
+ kobject_unregister(&(INDEX_KOBJECT_PTR(cpu,i)->kobj));
+ kobject_unregister(cache_kobject[cpu]);
+ cpuid4_cache_sysfs_exit(cpu);
+ return 0;
+}
+
+static struct sysdev_driver cache_sysdev_driver = {
+ .add = cache_add_dev,
+ .remove = __devexit_p(cache_remove_dev),
+};
+
+/* Register/Unregister the cpu_cache driver */
+static int __devinit cache_register_driver(void)
+{
+ if (num_cache_leaves == 0)
+ return 0;
+
+ return sysdev_driver_register(&cpu_sysdev_class,&cache_sysdev_driver);
+}
+
+device_initcall(cache_register_driver);
+
+#endif
+
diff --git a/arch/i386/kernel/cpu/mtrr/centaur.c b/arch/i386/kernel/cpu/mtrr/centaur.c
index 76af98ded23a8..33f00ac314ef3 100644
--- a/arch/i386/kernel/cpu/mtrr/centaur.c
+++ b/arch/i386/kernel/cpu/mtrr/centaur.c
@@ -86,6 +86,8 @@ static void centaur_set_mcr(unsigned int reg, unsigned long base,
centaur_mcr[reg].low = low;
wrmsr(MSR_IDT_MCR0 + reg, low, high);
}
+
+#if 0
/*
* Initialise the later (saner) Winchip MCR variant. In this version
* the BIOS can pass us the registers it has used (but not their values)
@@ -183,6 +185,7 @@ centaur_mcr_init(void)
set_mtrr_done(&ctxt);
}
+#endif
static int centaur_validate_add_page(unsigned long base,
unsigned long size, unsigned int type)
@@ -203,7 +206,7 @@ static int centaur_validate_add_page(unsigned long base,
static struct mtrr_ops centaur_mtrr_ops = {
.vendor = X86_VENDOR_CENTAUR,
- .init = centaur_mcr_init,
+// .init = centaur_mcr_init,
.set = centaur_set_mcr,
.get = centaur_get_mcr,
.get_free_region = centaur_get_free_region,
diff --git a/arch/i386/kernel/cpu/mtrr/cyrix.c b/arch/i386/kernel/cpu/mtrr/cyrix.c
index dec2b52759bb2..933b0dd62f485 100644
--- a/arch/i386/kernel/cpu/mtrr/cyrix.c
+++ b/arch/i386/kernel/cpu/mtrr/cyrix.c
@@ -218,12 +218,12 @@ typedef struct {
mtrr_type type;
} arr_state_t;
-arr_state_t arr_state[8] __initdata = {
+static arr_state_t arr_state[8] __initdata = {
{0UL, 0UL, 0UL}, {0UL, 0UL, 0UL}, {0UL, 0UL, 0UL}, {0UL, 0UL, 0UL},
{0UL, 0UL, 0UL}, {0UL, 0UL, 0UL}, {0UL, 0UL, 0UL}, {0UL, 0UL, 0UL}
};
-unsigned char ccr_state[7] __initdata = { 0, 0, 0, 0, 0, 0, 0 };
+static unsigned char ccr_state[7] __initdata = { 0, 0, 0, 0, 0, 0, 0 };
static void cyrix_set_all(void)
{
@@ -243,6 +243,7 @@ static void cyrix_set_all(void)
post_set();
}
+#if 0
/*
* On Cyrix 6x86(MX) and M II the ARR3 is special: it has connection
* with the SMM (System Management Mode) mode. So we need the following:
@@ -341,10 +342,11 @@ cyrix_arr_init(void)
if (ccrc[6])
printk(KERN_INFO "mtrr: ARR3 was write protected, unprotected\n");
}
+#endif
static struct mtrr_ops cyrix_mtrr_ops = {
.vendor = X86_VENDOR_CYRIX,
- .init = cyrix_arr_init,
+// .init = cyrix_arr_init,
.set_all = cyrix_set_all,
.set = cyrix_set_arr,
.get = cyrix_get_arr,
diff --git a/arch/i386/kernel/cpu/mtrr/generic.c b/arch/i386/kernel/cpu/mtrr/generic.c
index 01cead718534a..a4cce454d09b2 100644
--- a/arch/i386/kernel/cpu/mtrr/generic.c
+++ b/arch/i386/kernel/cpu/mtrr/generic.c
@@ -19,8 +19,7 @@ struct mtrr_state {
};
static unsigned long smp_changes_mask;
-struct mtrr_state mtrr_state = {};
-
+static struct mtrr_state mtrr_state = {};
/* Get the MSR pair relating to a var range */
static void __init
@@ -93,6 +92,16 @@ void __init mtrr_state_warn(void)
printk(KERN_INFO "mtrr: corrected configuration.\n");
}
+/* Doesn't attempt to pass an error out to MTRR users
+ because it's quite complicated in some cases and probably not
+ worth it because the best error handling is to ignore it. */
+void mtrr_wrmsr(unsigned msr, unsigned a, unsigned b)
+{
+ if (wrmsr_safe(msr, a, b) < 0)
+ printk(KERN_ERR
+ "MTRR: CPU %u: Writing MSR %x to %x:%x failed\n",
+ smp_processor_id(), msr, a, b);
+}
int generic_get_free_region(unsigned long base, unsigned long size)
/* [SUMMARY] Get a free MTRR.
@@ -151,14 +160,14 @@ static int set_fixed_ranges(mtrr_type * frs)
rdmsr(MTRRfix64K_00000_MSR, lo, hi);
if (p[0] != lo || p[1] != hi) {
- wrmsr(MTRRfix64K_00000_MSR, p[0], p[1]);
+ mtrr_wrmsr(MTRRfix64K_00000_MSR, p[0], p[1]);
changed = TRUE;
}
for (i = 0; i < 2; i++) {
rdmsr(MTRRfix16K_80000_MSR + i, lo, hi);
if (p[2 + i * 2] != lo || p[3 + i * 2] != hi) {
- wrmsr(MTRRfix16K_80000_MSR + i, p[2 + i * 2],
+ mtrr_wrmsr(MTRRfix16K_80000_MSR + i, p[2 + i * 2],
p[3 + i * 2]);
changed = TRUE;
}
@@ -167,7 +176,7 @@ static int set_fixed_ranges(mtrr_type * frs)
for (i = 0; i < 8; i++) {
rdmsr(MTRRfix4K_C0000_MSR + i, lo, hi);
if (p[6 + i * 2] != lo || p[7 + i * 2] != hi) {
- wrmsr(MTRRfix4K_C0000_MSR + i, p[6 + i * 2],
+ mtrr_wrmsr(MTRRfix4K_C0000_MSR + i, p[6 + i * 2],
p[7 + i * 2]);
changed = TRUE;
}
@@ -185,7 +194,7 @@ static int set_mtrr_var_ranges(unsigned int index, struct mtrr_var_range *vr)
rdmsr(MTRRphysBase_MSR(index), lo, hi);
if ((vr->base_lo & 0xfffff0ffUL) != (lo & 0xfffff0ffUL)
|| (vr->base_hi & 0xfUL) != (hi & 0xfUL)) {
- wrmsr(MTRRphysBase_MSR(index), vr->base_lo, vr->base_hi);
+ mtrr_wrmsr(MTRRphysBase_MSR(index), vr->base_lo, vr->base_hi);
changed = TRUE;
}
@@ -193,7 +202,7 @@ static int set_mtrr_var_ranges(unsigned int index, struct mtrr_var_range *vr)
if ((vr->mask_lo & 0xfffff800UL) != (lo & 0xfffff800UL)
|| (vr->mask_hi & 0xfUL) != (hi & 0xfUL)) {
- wrmsr(MTRRphysMask_MSR(index), vr->mask_lo, vr->mask_hi);
+ mtrr_wrmsr(MTRRphysMask_MSR(index), vr->mask_lo, vr->mask_hi);
changed = TRUE;
}
return changed;
@@ -268,7 +277,7 @@ static void prepare_set(void)
rdmsr(MTRRdefType_MSR, deftype_lo, deftype_hi);
/* Disable MTRRs, and set the default type to uncached */
- wrmsr(MTRRdefType_MSR, deftype_lo & 0xf300UL, deftype_hi);
+ mtrr_wrmsr(MTRRdefType_MSR, deftype_lo & 0xf300UL, deftype_hi);
}
static void post_set(void)
@@ -277,7 +286,7 @@ static void post_set(void)
__flush_tlb();
/* Intel (P6) standard MTRRs */
- wrmsr(MTRRdefType_MSR, deftype_lo, deftype_hi);
+ mtrr_wrmsr(MTRRdefType_MSR, deftype_lo, deftype_hi);
/* Enable caches */
write_cr0(read_cr0() & 0xbfffffff);
@@ -331,11 +340,11 @@ static void generic_set_mtrr(unsigned int reg, unsigned long base,
if (size == 0) {
/* The invalid bit is kept in the mask, so we simply clear the
relevant mask register to disable a range. */
- wrmsr(MTRRphysMask_MSR(reg), 0, 0);
+ mtrr_wrmsr(MTRRphysMask_MSR(reg), 0, 0);
} else {
- wrmsr(MTRRphysBase_MSR(reg), base << PAGE_SHIFT | type,
+ mtrr_wrmsr(MTRRphysBase_MSR(reg), base << PAGE_SHIFT | type,
(base & size_and_mask) >> (32 - PAGE_SHIFT));
- wrmsr(MTRRphysMask_MSR(reg), -size << PAGE_SHIFT | 0x800,
+ mtrr_wrmsr(MTRRphysMask_MSR(reg), -size << PAGE_SHIFT | 0x800,
(-size & size_and_mask) >> (32 - PAGE_SHIFT));
}
@@ -383,7 +392,7 @@ int generic_validate_add_page(unsigned long base, unsigned long size, unsigned i
}
-int generic_have_wrcomb(void)
+static int generic_have_wrcomb(void)
{
unsigned long config, dummy;
rdmsr(MTRRcap_MSR, config, dummy);
diff --git a/arch/i386/kernel/cpu/mtrr/if.c b/arch/i386/kernel/cpu/mtrr/if.c
index 0946844217b9c..1923e0aed26a8 100644
--- a/arch/i386/kernel/cpu/mtrr/if.c
+++ b/arch/i386/kernel/cpu/mtrr/if.c
@@ -98,16 +98,20 @@ mtrr_write(struct file *file, const char __user *buf, size_t len, loff_t * ppos)
unsigned long long base, size;
char *ptr;
char line[LINE_SIZE];
+ size_t linelen;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
+ if (!len)
+ return -EINVAL;
memset(line, 0, LINE_SIZE);
if (len > LINE_SIZE)
len = LINE_SIZE;
if (copy_from_user(line, buf, len - 1))
return -EFAULT;
- ptr = line + strlen(line) - 1;
- if (*ptr == '\n')
+ linelen = strlen(line);
+ ptr = line + linelen - 1;
+ if (linelen && *ptr == '\n')
*ptr = '\0';
if (!strncmp(line, "disable=", 8)) {
reg = simple_strtoul(line + 8, &ptr, 0);
diff --git a/arch/i386/kernel/cpu/mtrr/main.c b/arch/i386/kernel/cpu/mtrr/main.c
index f9efeeb81b1d9..8f67b490a7fdd 100644
--- a/arch/i386/kernel/cpu/mtrr/main.c
+++ b/arch/i386/kernel/cpu/mtrr/main.c
@@ -57,10 +57,6 @@ static struct mtrr_ops * mtrr_ops[X86_VENDOR_NUM] = {};
struct mtrr_ops * mtrr_if = NULL;
-__initdata char *mtrr_if_name[] = {
- "none", "Intel", "AMD K6", "Cyrix ARR", "Centaur MCR"
-};
-
static void set_mtrr(unsigned int reg, unsigned long base,
unsigned long size, mtrr_type type);
@@ -100,7 +96,7 @@ static int have_wrcomb(void)
}
/* This function returns the number of variable MTRRs */
-void __init set_num_var_ranges(void)
+static void __init set_num_var_ranges(void)
{
unsigned long config = 0, dummy;
diff --git a/arch/i386/kernel/cpu/mtrr/mtrr.h b/arch/i386/kernel/cpu/mtrr/mtrr.h
index 0d10c115db23b..de1351245599e 100644
--- a/arch/i386/kernel/cpu/mtrr/mtrr.h
+++ b/arch/i386/kernel/cpu/mtrr/mtrr.h
@@ -37,7 +37,7 @@ typedef u8 mtrr_type;
struct mtrr_ops {
u32 vendor;
u32 use_intel_if;
- void (*init)(void);
+// void (*init)(void);
void (*set)(unsigned int reg, unsigned long base,
unsigned long size, mtrr_type type);
void (*set_all)(void);
@@ -57,7 +57,6 @@ extern int generic_validate_add_page(unsigned long base, unsigned long size,
extern struct mtrr_ops generic_mtrr_ops;
-extern int generic_have_wrcomb(void);
extern int positive_have_wrcomb(void);
/* library functions for processor-specific routines */
@@ -95,5 +94,5 @@ extern unsigned int num_var_ranges;
void finalize_mtrr_state(void);
void mtrr_state_warn(void);
char *mtrr_attrib_to_str(int x);
+void mtrr_wrmsr(unsigned, unsigned, unsigned);
-extern char * mtrr_if_name[];
diff --git a/arch/i386/kernel/cpu/mtrr/state.c b/arch/i386/kernel/cpu/mtrr/state.c
index 3d32fbf352845..f62ecd15811a9 100644
--- a/arch/i386/kernel/cpu/mtrr/state.c
+++ b/arch/i386/kernel/cpu/mtrr/state.c
@@ -42,7 +42,7 @@ void set_mtrr_cache_disable(struct set_mtrr_context *ctxt)
{
if (use_intel())
/* Disable MTRRs, and set the default type to uncached */
- wrmsr(MTRRdefType_MSR, ctxt->deftype_lo & 0xf300UL,
+ mtrr_wrmsr(MTRRdefType_MSR, ctxt->deftype_lo & 0xf300UL,
ctxt->deftype_hi);
else if (is_cpu(CYRIX))
/* Cyrix ARRs - everything else were excluded at the top */
@@ -60,7 +60,7 @@ void set_mtrr_done(struct set_mtrr_context *ctxt)
/* Restore MTRRdefType */
if (use_intel())
/* Intel (P6) standard MTRRs */
- wrmsr(MTRRdefType_MSR, ctxt->deftype_lo, ctxt->deftype_hi);
+ mtrr_wrmsr(MTRRdefType_MSR, ctxt->deftype_lo, ctxt->deftype_hi);
else
/* Cyrix ARRs - everything else was excluded at the top */
setCx86(CX86_CCR3, ctxt->ccr3);
diff --git a/arch/i386/kernel/cpuid.c b/arch/i386/kernel/cpuid.c
index 32a0984318f6e..2e2756345bb23 100644
--- a/arch/i386/kernel/cpuid.c
+++ b/arch/i386/kernel/cpuid.c
@@ -189,7 +189,7 @@ static struct notifier_block cpuid_class_cpu_notifier =
.notifier_call = cpuid_class_cpu_callback,
};
-int __init cpuid_init(void)
+static int __init cpuid_init(void)
{
int i, err = 0;
i = 0;
@@ -227,7 +227,7 @@ out:
return err;
}
-void __exit cpuid_exit(void)
+static void __exit cpuid_exit(void)
{
int cpu = 0;
diff --git a/arch/i386/kernel/dmi_scan.c b/arch/i386/kernel/dmi_scan.c
index 78bbcba0c1b96..6ed7e28f306cf 100644
--- a/arch/i386/kernel/dmi_scan.c
+++ b/arch/i386/kernel/dmi_scan.c
@@ -12,8 +12,6 @@
#include <linux/bootmem.h>
-int es7000_plat = 0;
-
struct dmi_header
{
u8 type;
@@ -487,4 +485,3 @@ char * dmi_get_system_info(int field)
return dmi_ident[field];
}
-EXPORT_SYMBOL(dmi_get_system_info);
diff --git a/arch/i386/kernel/efi.c b/arch/i386/kernel/efi.c
index 8c3623b85b085..9e5e0d8bd36e0 100644
--- a/arch/i386/kernel/efi.c
+++ b/arch/i386/kernel/efi.c
@@ -46,7 +46,7 @@ extern efi_status_t asmlinkage efi_call_phys(void *, ...);
struct efi efi;
EXPORT_SYMBOL(efi);
-struct efi efi_phys __initdata;
+static struct efi efi_phys __initdata;
struct efi_memory_map memmap __initdata;
/*
@@ -151,7 +151,7 @@ phys_efi_set_virtual_address_map(unsigned long memory_map_size,
return status;
}
-efi_status_t
+static efi_status_t
phys_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc)
{
efi_status_t status;
@@ -240,7 +240,8 @@ void __init efi_map_memmap(void)
printk(KERN_ERR PFX "Could not remap the EFI memmap!\n");
}
-void __init print_efi_memmap(void)
+#if EFI_DEBUG
+static void __init print_efi_memmap(void)
{
efi_memory_desc_t *md;
int i;
@@ -254,6 +255,7 @@ void __init print_efi_memmap(void)
(md->num_pages >> (20 - EFI_PAGE_SHIFT)));
}
}
+#endif /* EFI_DEBUG */
/*
* Walks the EFI memory map and calls CALLBACK once for each EFI
diff --git a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S
index f15856e405341..1e45ff292bc99 100644
--- a/arch/i386/kernel/entry.S
+++ b/arch/i386/kernel/entry.S
@@ -47,6 +47,7 @@
#include <asm/segment.h>
#include <asm/smp.h>
#include <asm/page.h>
+#include <asm/desc.h>
#include "irq_vectors.h"
#define nr_syscalls ((syscall_table_size)/4)
@@ -78,7 +79,7 @@ VM_MASK = 0x00020000
#define preempt_stop cli
#else
#define preempt_stop
-#define resume_kernel restore_all
+#define resume_kernel restore_nocheck
#endif
#define SAVE_ALL \
@@ -122,24 +123,6 @@ VM_MASK = 0x00020000
.previous
-#define RESTORE_ALL \
- RESTORE_REGS \
- addl $4, %esp; \
-1: iret; \
-.section .fixup,"ax"; \
-2: sti; \
- movl $(__USER_DS), %edx; \
- movl %edx, %ds; \
- movl %edx, %es; \
- movl $11,%eax; \
- call do_exit; \
-.previous; \
-.section __ex_table,"a";\
- .align 4; \
- .long 1b,2b; \
-.previous
-
-
ENTRY(ret_from_fork)
pushl %eax
call schedule_tail
@@ -163,7 +146,7 @@ ret_from_intr:
movl EFLAGS(%esp), %eax # mix EFLAGS and CS
movb CS(%esp), %al
testl $(VM_MASK | 3), %eax
- jz resume_kernel # returning to kernel or vm86-space
+ jz resume_kernel
ENTRY(resume_userspace)
cli # make sure we don't miss an interrupt
# setting need_resched or sigpending
@@ -178,7 +161,7 @@ ENTRY(resume_userspace)
ENTRY(resume_kernel)
cli
cmpl $0,TI_preempt_count(%ebp) # non-zero preempt_count ?
- jnz restore_all
+ jnz restore_nocheck
need_resched:
movl TI_flags(%ebp), %ecx # need_resched set ?
testb $_TIF_NEED_RESCHED, %cl
@@ -219,7 +202,8 @@ sysenter_past_esp:
SAVE_ALL
GET_THREAD_INFO(%ebp)
- testb $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),TI_flags(%ebp)
+ /* Note, _TIF_SECCOMP is bit number 8, and so it needs testw and not testb */
+ testw $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),TI_flags(%ebp)
jnz syscall_trace_entry
cmpl $(nr_syscalls), %eax
jae syscall_badsys
@@ -243,7 +227,8 @@ ENTRY(system_call)
SAVE_ALL
GET_THREAD_INFO(%ebp)
# system call tracing in operation
- testb $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),TI_flags(%ebp)
+ /* Note, _TIF_SECCOMP is bit number 8, and so it needs testw and not testb */
+ testw $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),TI_flags(%ebp)
jnz syscall_trace_entry
cmpl $(nr_syscalls), %eax
jae syscall_badsys
@@ -257,8 +242,56 @@ syscall_exit:
movl TI_flags(%ebp), %ecx
testw $_TIF_ALLWORK_MASK, %cx # current->work
jne syscall_exit_work
+
restore_all:
- RESTORE_ALL
+ movl EFLAGS(%esp), %eax # mix EFLAGS, SS and CS
+ movb OLDSS(%esp), %ah
+ movb CS(%esp), %al
+ andl $(VM_MASK | (4 << 8) | 3), %eax
+ cmpl $((4 << 8) | 3), %eax
+ je ldt_ss # returning to user-space with LDT SS
+restore_nocheck:
+ RESTORE_REGS
+ addl $4, %esp
+1: iret
+.section .fixup,"ax"
+iret_exc:
+ sti
+ movl $__USER_DS, %edx
+ movl %edx, %ds
+ movl %edx, %es
+ movl $11,%eax
+ call do_exit
+.previous
+.section __ex_table,"a"
+ .align 4
+ .long 1b,iret_exc
+.previous
+
+ldt_ss:
+ larl OLDSS(%esp), %eax
+ jnz restore_nocheck
+ testl $0x00400000, %eax # returning to 32bit stack?
+ jnz restore_nocheck # allright, normal return
+ /* If returning to userspace with 16bit stack,
+ * try to fix the higher word of ESP, as the CPU
+ * won't restore it.
+ * This is an "official" bug of all the x86-compatible
+ * CPUs, which we can try to work around to make
+ * dosemu and wine happy. */
+ subl $8, %esp # reserve space for switch16 pointer
+ cli
+ movl %esp, %eax
+ /* Set up the 16bit stack frame with switch32 pointer on top,
+ * and a switch16 pointer on top of the current frame. */
+ call setup_x86_bogus_stack
+ RESTORE_REGS
+ lss 20+4(%esp), %esp # switch to 16bit stack
+1: iret
+.section __ex_table,"a"
+ .align 4
+ .long 1b,iret_exc
+.previous
# perform work that needs to be done immediately before resumption
ALIGN
@@ -334,6 +367,27 @@ syscall_badsys:
movl $-ENOSYS,EAX(%esp)
jmp resume_userspace
+#define FIXUP_ESPFIX_STACK \
+ movl %esp, %eax; \
+ /* switch to 32bit stack using the pointer on top of 16bit stack */ \
+ lss %ss:CPU_16BIT_STACK_SIZE-8, %esp; \
+ /* copy data from 16bit stack to 32bit stack */ \
+ call fixup_x86_bogus_stack; \
+ /* put ESP to the proper location */ \
+ movl %eax, %esp;
+#define UNWIND_ESPFIX_STACK \
+ pushl %eax; \
+ movl %ss, %eax; \
+ /* see if on 16bit stack */ \
+ cmpw $__ESPFIX_SS, %ax; \
+ jne 28f; \
+ movl $__KERNEL_DS, %edx; \
+ movl %edx, %ds; \
+ movl %edx, %es; \
+ /* switch to 32bit stack */ \
+ FIXUP_ESPFIX_STACK \
+28: popl %eax;
+
/*
* Build the entry stubs and pointer table with
* some assembler magic.
@@ -388,7 +442,9 @@ error_code:
pushl %ecx
pushl %ebx
cld
- movl %es, %ecx
+ pushl %es
+ UNWIND_ESPFIX_STACK
+ popl %ecx
movl ES(%esp), %edi # get the function address
movl ORIG_EAX(%esp), %edx # get the error code
movl %eax, ORIG_EAX(%esp)
@@ -470,6 +526,11 @@ debug_stack_correct:
* fault happened on the sysenter path.
*/
ENTRY(nmi)
+ pushl %eax
+ movl %ss, %eax
+ cmpw $__ESPFIX_SS, %ax
+ popl %eax
+ je nmi_16bit_stack
cmpl $sysenter_entry,(%esp)
je nmi_stack_fixup
pushl %eax
@@ -489,7 +550,7 @@ nmi_stack_correct:
xorl %edx,%edx # zero error code
movl %esp,%eax # pt_regs pointer
call do_nmi
- RESTORE_ALL
+ jmp restore_all
nmi_stack_fixup:
FIX_STACK(12,nmi_stack_correct, 1)
@@ -505,6 +566,29 @@ nmi_debug_stack_fixup:
FIX_STACK(24,nmi_stack_correct, 1)
jmp nmi_stack_correct
+nmi_16bit_stack:
+ /* create the pointer to lss back */
+ pushl %ss
+ pushl %esp
+ movzwl %sp, %esp
+ addw $4, (%esp)
+ /* copy the iret frame of 12 bytes */
+ .rept 3
+ pushl 16(%esp)
+ .endr
+ pushl %eax
+ SAVE_ALL
+ FIXUP_ESPFIX_STACK # %eax == %esp
+ xorl %edx,%edx # zero error code
+ call do_nmi
+ RESTORE_REGS
+ lss 12+4(%esp), %esp # back to 16bit stack
+1: iret
+.section __ex_table,"a"
+ .align 4
+ .long 1b,iret_exc
+.previous
+
ENTRY(int3)
pushl $-1 # mark this as an int
SAVE_ALL
diff --git a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S
index ea1ef3a32ec5b..d273fd7461921 100644
--- a/arch/i386/kernel/head.S
+++ b/arch/i386/kernel/head.S
@@ -512,7 +512,7 @@ ENTRY(cpu_gdt_table)
.quad 0x00009a0000000000 /* 0xc0 APM CS 16 code (16 bit) */
.quad 0x0040920000000000 /* 0xc8 APM DS data */
- .quad 0x0000000000000000 /* 0xd0 - unused */
+ .quad 0x0000920000000000 /* 0xd0 - ESPFIX 16-bit SS */
.quad 0x0000000000000000 /* 0xd8 - unused */
.quad 0x0000000000000000 /* 0xe0 - unused */
.quad 0x0000000000000000 /* 0xe8 - unused */
diff --git a/arch/i386/kernel/i386_ksyms.c b/arch/i386/kernel/i386_ksyms.c
index bd22e87625580..14ec354bec926 100644
--- a/arch/i386/kernel/i386_ksyms.c
+++ b/arch/i386/kernel/i386_ksyms.c
@@ -97,6 +97,11 @@ EXPORT_SYMBOL(__get_user_1);
EXPORT_SYMBOL(__get_user_2);
EXPORT_SYMBOL(__get_user_4);
+EXPORT_SYMBOL(__put_user_1);
+EXPORT_SYMBOL(__put_user_2);
+EXPORT_SYMBOL(__put_user_4);
+EXPORT_SYMBOL(__put_user_8);
+
EXPORT_SYMBOL(strpbrk);
EXPORT_SYMBOL(strstr);
@@ -112,7 +117,6 @@ EXPORT_SYMBOL(dma_alloc_coherent);
EXPORT_SYMBOL(dma_free_coherent);
#ifdef CONFIG_PCI
-EXPORT_SYMBOL(pcibios_penalize_isa_irq);
EXPORT_SYMBOL(pci_mem_start);
#endif
@@ -144,7 +148,6 @@ EXPORT_SYMBOL(smp_call_function);
/* TLB flushing */
EXPORT_SYMBOL(flush_tlb_page);
-EXPORT_SYMBOL_GPL(flush_tlb_all);
#endif
#ifdef CONFIG_X86_IO_APIC
diff --git a/arch/i386/kernel/i387.c b/arch/i386/kernel/i387.c
index 5af8b683883d8..c55e037f08f76 100644
--- a/arch/i386/kernel/i387.c
+++ b/arch/i386/kernel/i387.c
@@ -24,7 +24,7 @@
#define HAVE_HWFP 1
#endif
-unsigned long mxcsr_feature_mask = 0xffffffff;
+static unsigned long mxcsr_feature_mask = 0xffffffff;
void mxcsr_feature_mask_init(void)
{
@@ -177,6 +177,7 @@ unsigned short get_fpu_swd( struct task_struct *tsk )
}
}
+#if 0
unsigned short get_fpu_twd( struct task_struct *tsk )
{
if ( cpu_has_fxsr ) {
@@ -185,6 +186,7 @@ unsigned short get_fpu_twd( struct task_struct *tsk )
return (unsigned short)tsk->thread.i387.fsave.twd;
}
}
+#endif /* 0 */
unsigned short get_fpu_mxcsr( struct task_struct *tsk )
{
@@ -195,6 +197,8 @@ unsigned short get_fpu_mxcsr( struct task_struct *tsk )
}
}
+#if 0
+
void set_fpu_cwd( struct task_struct *tsk, unsigned short cwd )
{
if ( cpu_has_fxsr ) {
@@ -222,6 +226,8 @@ void set_fpu_twd( struct task_struct *tsk, unsigned short twd )
}
}
+#endif /* 0 */
+
/*
* FXSR floating point environment conversions.
*/
diff --git a/arch/i386/kernel/i8259.c b/arch/i386/kernel/i8259.c
index 5349062f54fb1..560bef1afb3b0 100644
--- a/arch/i386/kernel/i8259.c
+++ b/arch/i386/kernel/i8259.c
@@ -49,7 +49,7 @@ static void end_8259A_irq (unsigned int irq)
#define shutdown_8259A_irq disable_8259A_irq
-void mask_and_ack_8259A(unsigned int);
+static void mask_and_ack_8259A(unsigned int);
unsigned int startup_8259A_irq(unsigned int irq)
{
@@ -58,14 +58,13 @@ unsigned int startup_8259A_irq(unsigned int irq)
}
static struct hw_interrupt_type i8259A_irq_type = {
- "XT-PIC",
- startup_8259A_irq,
- shutdown_8259A_irq,
- enable_8259A_irq,
- disable_8259A_irq,
- mask_and_ack_8259A,
- end_8259A_irq,
- NULL
+ .typename = "XT-PIC",
+ .startup = startup_8259A_irq,
+ .shutdown = shutdown_8259A_irq,
+ .enable = enable_8259A_irq,
+ .disable = disable_8259A_irq,
+ .ack = mask_and_ack_8259A,
+ .end = end_8259A_irq,
};
/*
@@ -169,7 +168,7 @@ static inline int i8259A_irq_real(unsigned int irq)
* first, _then_ send the EOI, and the order of EOI
* to the two 8259s is important!
*/
-void mask_and_ack_8259A(unsigned int irq)
+static void mask_and_ack_8259A(unsigned int irq)
{
unsigned int irqmask = 1 << irq;
unsigned long flags;
diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c
index 4b6477b4d8f9a..9c1350e811d07 100644
--- a/arch/i386/kernel/io_apic.c
+++ b/arch/i386/kernel/io_apic.c
@@ -188,7 +188,7 @@ static void unmask_IO_APIC_irq (unsigned int irq)
spin_unlock_irqrestore(&ioapic_lock, flags);
}
-void clear_IO_APIC_pin(unsigned int apic, unsigned int pin)
+static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin)
{
struct IO_APIC_route_entry entry;
unsigned long flags;
@@ -264,7 +264,7 @@ cpumask_t __cacheline_aligned pending_irq_balance_cpumask[NR_IRQS];
static int irqbalance_disabled = IRQBALANCE_CHECK_ARCH;
static int physical_balance = 0;
-struct irq_cpu_info {
+static struct irq_cpu_info {
unsigned long * last_irq;
unsigned long * irq_delta;
unsigned long irq;
@@ -275,7 +275,7 @@ struct irq_cpu_info {
#define IRQ_DELTA(cpu,irq) (irq_cpu_data[cpu].irq_delta[irq])
#define IDLE_ENOUGH(cpu,now) \
- (idle_cpu(cpu) && ((now) - irq_stat[(cpu)].idle_timestamp > 1))
+ (idle_cpu(cpu) && ((now) - per_cpu(irq_stat, (cpu)).idle_timestamp > 1))
#define IRQ_ALLOWED(cpu, allowed_mask) cpu_isset(cpu, allowed_mask)
@@ -286,7 +286,7 @@ struct irq_cpu_info {
#define BALANCED_IRQ_MORE_DELTA (HZ/10)
#define BALANCED_IRQ_LESS_DELTA (HZ)
-long balanced_irq_interval = MAX_BALANCED_IRQ_INTERVAL;
+static long balanced_irq_interval = MAX_BALANCED_IRQ_INTERVAL;
static unsigned long move(int curr_cpu, cpumask_t allowed_mask,
unsigned long now, int direction)
@@ -685,8 +685,8 @@ void fastcall send_IPI_self(int vector)
*/
#define MAX_PIRQS 8
-int pirq_entries [MAX_PIRQS];
-int pirqs_enabled;
+static int pirq_entries [MAX_PIRQS];
+static int pirqs_enabled;
int skip_ioapic_setup;
static int __init ioapic_setup(char *str)
@@ -1179,7 +1179,7 @@ static inline void ioapic_register_intr(int irq, int vector, unsigned long trigg
}
}
-void __init setup_IO_APIC_irqs(void)
+static void __init setup_IO_APIC_irqs(void)
{
struct IO_APIC_route_entry entry;
int apic, pin, idx, irq, first_notcon = 1, vector;
@@ -1258,7 +1258,7 @@ void __init setup_IO_APIC_irqs(void)
/*
* Set up the 8259A-master output pin:
*/
-void __init setup_ExtINT_IRQ0_pin(unsigned int pin, int vector)
+static void __init setup_ExtINT_IRQ0_pin(unsigned int pin, int vector)
{
struct IO_APIC_route_entry entry;
unsigned long flags;
@@ -1452,6 +1452,8 @@ void __init print_IO_APIC(void)
return;
}
+#if 0
+
static void print_APIC_bitfield (int base)
{
unsigned int v;
@@ -1594,6 +1596,8 @@ void /*__init*/ print_PIC(void)
printk(KERN_DEBUG "... PIC ELCR: %04x\n", v);
}
+#endif /* 0 */
+
static void __init enable_IO_APIC(void)
{
union IO_APIC_reg_01 reg_01;
diff --git a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c
index 3d4e563127e7f..73945a3c53c4c 100644
--- a/arch/i386/kernel/irq.c
+++ b/arch/i386/kernel/irq.c
@@ -16,6 +16,9 @@
#include <linux/interrupt.h>
#include <linux/kernel_stat.h>
+DEFINE_PER_CPU(irq_cpustat_t, irq_stat) ____cacheline_maxaligned_in_smp;
+EXPORT_PER_CPU_SYMBOL(irq_stat);
+
#ifndef CONFIG_X86_LOCAL_APIC
/*
* 'what should we do if we get a hw irq event on an illegal vector'.
@@ -246,7 +249,7 @@ skip:
for (j = 0; j < NR_CPUS; j++)
if (cpu_online(j))
seq_printf(p, "%10u ",
- irq_stat[j].apic_timer_irqs);
+ per_cpu(irq_stat,j).apic_timer_irqs);
seq_putc(p, '\n');
#endif
seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
diff --git a/arch/i386/kernel/kprobes.c b/arch/i386/kernel/kprobes.c
index f74b755704c4c..6716816592434 100644
--- a/arch/i386/kernel/kprobes.c
+++ b/arch/i386/kernel/kprobes.c
@@ -84,7 +84,11 @@ static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
{
regs->eflags |= TF_MASK;
regs->eflags &= ~IF_MASK;
- regs->eip = (unsigned long)&p->ainsn.insn;
+ /*single step inline if the instruction is an int3*/
+ if (p->opcode == BREAKPOINT_INSTRUCTION)
+ regs->eip = (unsigned long)p->addr;
+ else
+ regs->eip = (unsigned long)&p->ainsn.insn;
}
/*
@@ -117,6 +121,12 @@ static int kprobe_handler(struct pt_regs *regs)
Disarm the probe we just hit, and ignore it. */
p = get_kprobe(addr);
if (p) {
+ if (kprobe_status == KPROBE_HIT_SS) {
+ regs->eflags &= ~TF_MASK;
+ regs->eflags |= kprobe_saved_eflags;
+ unlock_kprobes();
+ goto no_kprobe;
+ }
disarm_kprobe(p, regs);
ret = 1;
} else {
@@ -159,17 +169,16 @@ static int kprobe_handler(struct pt_regs *regs)
if (is_IF_modifier(p->opcode))
kprobe_saved_eflags &= ~IF_MASK;
- if (p->pre_handler(p, regs)) {
+ if (p->pre_handler && p->pre_handler(p, regs))
/* handler has already set things up, so skip ss setup */
return 1;
- }
- ss_probe:
+ss_probe:
prepare_singlestep(p, regs);
kprobe_status = KPROBE_HIT_SS;
return 1;
- no_kprobe:
+no_kprobe:
preempt_enable_no_resched();
return ret;
}
diff --git a/arch/i386/kernel/mpparse.c b/arch/i386/kernel/mpparse.c
index e5ad7e03fc7fe..1347ab4939e7e 100644
--- a/arch/i386/kernel/mpparse.c
+++ b/arch/i386/kernel/mpparse.c
@@ -49,7 +49,7 @@ int mp_bus_id_to_node [MAX_MP_BUSSES];
int mp_bus_id_to_local [MAX_MP_BUSSES];
int quad_local_to_mp_bus_id [NR_CPUS/4][4];
int mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 };
-int mp_current_pci_id;
+static int mp_current_pci_id;
/* I/O APIC entries */
struct mpc_config_ioapic mp_ioapics[MAX_IO_APICS];
@@ -119,7 +119,7 @@ static int MP_valid_apicid(int apicid, int version)
}
#endif
-void __init MP_processor_info (struct mpc_config_processor *m)
+static void __init MP_processor_info (struct mpc_config_processor *m)
{
int ver, apicid;
physid_mask_t tmp;
@@ -863,7 +863,7 @@ void __init mp_register_lapic (
#define MP_ISA_BUS 0
#define MP_MAX_IOAPIC_PIN 127
-struct mp_ioapic_routing {
+static struct mp_ioapic_routing {
int apic_id;
int gsi_base;
int gsi_end;
@@ -982,6 +982,7 @@ void __init mp_override_legacy_irq (
return;
}
+int es7000_plat;
void __init mp_config_acpi_legacy_irqs (void)
{
@@ -996,9 +997,9 @@ void __init mp_config_acpi_legacy_irqs (void)
Dprintk("Bus #%d is ISA\n", MP_ISA_BUS);
/*
- * ES7000 has no legacy identity mappings
+ * Older generations of ES7000 have no legacy identity mappings
*/
- if (es7000_plat)
+ if (es7000_plat == 1)
return;
/*
diff --git a/arch/i386/kernel/msr.c b/arch/i386/kernel/msr.c
index 670a71efafb38..05d9f8f363a69 100644
--- a/arch/i386/kernel/msr.c
+++ b/arch/i386/kernel/msr.c
@@ -291,7 +291,7 @@ static struct notifier_block msr_class_cpu_notifier =
.notifier_call = msr_class_cpu_callback,
};
-int __init msr_init(void)
+static int __init msr_init(void)
{
int i, err = 0;
i = 0;
@@ -328,7 +328,7 @@ out:
return err;
}
-void __exit msr_exit(void)
+static void __exit msr_exit(void)
{
int cpu = 0;
for_each_online_cpu(cpu)
diff --git a/arch/i386/kernel/nmi.c b/arch/i386/kernel/nmi.c
index 6bd4681df09f1..f5b0c5081bd65 100644
--- a/arch/i386/kernel/nmi.c
+++ b/arch/i386/kernel/nmi.c
@@ -110,7 +110,7 @@ int __init check_nmi_watchdog (void)
printk(KERN_INFO "testing NMI watchdog ... ");
for (cpu = 0; cpu < NR_CPUS; cpu++)
- prev_nmi_count[cpu] = irq_stat[cpu].__nmi_count;
+ prev_nmi_count[cpu] = per_cpu(irq_stat, cpu).__nmi_count;
local_irq_enable();
mdelay((10*1000)/nmi_hz); // wait 10 ticks
@@ -483,7 +483,7 @@ void nmi_watchdog_tick (struct pt_regs * regs)
*/
int sum, cpu = smp_processor_id();
- sum = irq_stat[cpu].apic_timer_irqs;
+ sum = per_cpu(irq_stat, cpu).apic_timer_irqs;
if (last_irq_sums[cpu] == sum) {
/*
diff --git a/arch/i386/kernel/numaq.c b/arch/i386/kernel/numaq.c
index 0ee22fcb12d15..e51edf0a65648 100644
--- a/arch/i386/kernel/numaq.c
+++ b/arch/i386/kernel/numaq.c
@@ -30,9 +30,7 @@
#include <linux/module.h>
#include <linux/nodemask.h>
#include <asm/numaq.h>
-
-/* These are needed before the pgdat's are created */
-extern long node_start_pfn[], node_end_pfn[];
+#include <asm/topology.h>
#define MB_TO_PAGES(addr) ((addr) << (20 - PAGE_SHIFT))
@@ -59,6 +57,12 @@ static void __init smp_dump_qct(void)
eq->hi_shrd_mem_start - eq->priv_mem_size);
node_end_pfn[node] = MB_TO_PAGES(
eq->hi_shrd_mem_start + eq->hi_shrd_mem_size);
+
+ memory_present(node,
+ node_start_pfn[node], node_end_pfn[node]);
+ node_remap_size[node] = node_memmap_size_bytes(node,
+ node_start_pfn[node],
+ node_end_pfn[node]);
}
}
}
diff --git a/arch/i386/kernel/pci-dma.c b/arch/i386/kernel/pci-dma.c
index 7087b1415f64c..4de2e03c7b451 100644
--- a/arch/i386/kernel/pci-dma.c
+++ b/arch/i386/kernel/pci-dma.c
@@ -22,7 +22,7 @@ struct dma_coherent_mem {
};
void *dma_alloc_coherent(struct device *dev, size_t size,
- dma_addr_t *dma_handle, int gfp)
+ dma_addr_t *dma_handle, unsigned int __nocast gfp)
{
void *ret;
struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
index 28b0d7bf0a846..c36fedf40e958 100644
--- a/arch/i386/kernel/process.c
+++ b/arch/i386/kernel/process.c
@@ -36,6 +36,7 @@
#include <linux/module.h>
#include <linux/kallsyms.h>
#include <linux/ptrace.h>
+#include <linux/random.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
@@ -55,7 +56,7 @@
asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
-int hlt_counter;
+static int hlt_counter;
unsigned long boot_option_idle_override = 0;
EXPORT_SYMBOL(boot_option_idle_override);
@@ -72,7 +73,7 @@ unsigned long thread_saved_pc(struct task_struct *tsk)
* Powermanagement idle function, if any..
*/
void (*pm_idle)(void);
-static cpumask_t cpu_idle_map;
+static DEFINE_PER_CPU(unsigned int, cpu_idle_state);
void disable_hlt(void)
{
@@ -145,22 +146,21 @@ static void poll_idle (void)
*/
void cpu_idle (void)
{
- int cpu = _smp_processor_id();
-
/* endless idle loop with no priority at all */
while (1) {
while (!need_resched()) {
void (*idle)(void);
- if (cpu_isset(cpu, cpu_idle_map))
- cpu_clear(cpu, cpu_idle_map);
+ if (__get_cpu_var(cpu_idle_state))
+ __get_cpu_var(cpu_idle_state) = 0;
+
rmb();
idle = pm_idle;
if (!idle)
idle = default_idle;
- irq_stat[cpu].idle_timestamp = jiffies;
+ __get_cpu_var(irq_stat).idle_timestamp = jiffies;
idle();
}
schedule();
@@ -169,16 +169,28 @@ void cpu_idle (void)
void cpu_idle_wait(void)
{
- int cpu;
+ unsigned int cpu, this_cpu = get_cpu();
cpumask_t map;
- for_each_online_cpu(cpu)
- cpu_set(cpu, cpu_idle_map);
+ set_cpus_allowed(current, cpumask_of_cpu(this_cpu));
+ put_cpu();
+
+ cpus_clear(map);
+ for_each_online_cpu(cpu) {
+ per_cpu(cpu_idle_state, cpu) = 1;
+ cpu_set(cpu, map);
+ }
+
+ __get_cpu_var(cpu_idle_state) = 0;
wmb();
do {
ssleep(1);
- cpus_and(map, cpu_idle_map, cpu_online_map);
+ for_each_online_cpu(cpu) {
+ if (cpu_isset(cpu, map) && !per_cpu(cpu_idle_state, cpu))
+ cpu_clear(cpu, map);
+ }
+ cpus_and(map, map, cpu_online_map);
} while (!cpus_empty(map));
}
EXPORT_SYMBOL_GPL(cpu_idle_wait);
@@ -828,3 +840,9 @@ asmlinkage int sys_get_thread_area(struct user_desc __user *u_info)
return 0;
}
+unsigned long arch_align_stack(unsigned long sp)
+{
+ if (randomize_va_space)
+ sp -= get_random_int() % 8192;
+ return sp & ~0xf;
+}
diff --git a/arch/i386/kernel/ptrace.c b/arch/i386/kernel/ptrace.c
index 3985587e1cd2f..b2f17640ceff4 100644
--- a/arch/i386/kernel/ptrace.c
+++ b/arch/i386/kernel/ptrace.c
@@ -15,6 +15,7 @@
#include <linux/user.h>
#include <linux/security.h>
#include <linux/audit.h>
+#include <linux/seccomp.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
@@ -678,6 +679,9 @@ void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, int error_code)
__attribute__((regparm(3)))
void do_syscall_trace(struct pt_regs *regs, int entryexit)
{
+ /* do the secure computing check first */
+ secure_computing(regs->orig_eax);
+
if (unlikely(current->audit_context)) {
if (!entryexit)
audit_syscall_entry(current, regs->orig_eax,
diff --git a/arch/i386/kernel/quirks.c b/arch/i386/kernel/quirks.c
index 847ba44c2e06e..aaf89cb2bc514 100644
--- a/arch/i386/kernel/quirks.c
+++ b/arch/i386/kernel/quirks.c
@@ -7,7 +7,7 @@
#if defined(CONFIG_X86_IO_APIC) && defined(CONFIG_SMP) && defined(CONFIG_PCI)
-void __devinit quirk_intel_irqbalance(struct pci_dev *dev)
+static void __devinit quirk_intel_irqbalance(struct pci_dev *dev)
{
u8 config, rev;
u32 word;
@@ -37,7 +37,9 @@ void __devinit quirk_intel_irqbalance(struct pci_dev *dev)
irqbalance_disable("");
#endif
noirqdebug_setup("");
+#ifdef CONFIG_PROC_FS
no_irq_affinity = 1;
+#endif
}
config &= ~0x2;
diff --git a/arch/i386/kernel/scx200.c b/arch/i386/kernel/scx200.c
index d02df17e44801..69e203a0d330e 100644
--- a/arch/i386/kernel/scx200.c
+++ b/arch/i386/kernel/scx200.c
@@ -13,6 +13,9 @@
#include <linux/scx200.h>
+/* Verify that the configuration block really is there */
+#define scx200_cb_probe(base) (inw((base) + SCx200_CBA) == (base))
+
#define NAME "scx200"
MODULE_AUTHOR("Christer Weinigel <wingel@nano-system.com>");
@@ -22,9 +25,13 @@ MODULE_LICENSE("GPL");
unsigned scx200_gpio_base = 0;
long scx200_gpio_shadow[2];
+unsigned scx200_cb_base = 0;
+
static struct pci_device_id scx200_tbl[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SCx200_BRIDGE) },
{ PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SC1100_BRIDGE) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SCx200_XBUS) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SC1100_XBUS) },
{ },
};
MODULE_DEVICE_TABLE(pci,scx200_tbl);
@@ -37,7 +44,6 @@ static struct pci_driver scx200_pci_driver = {
.probe = scx200_probe,
};
-DEFINE_SPINLOCK(scx200_gpio_lock);
static DEFINE_SPINLOCK(scx200_gpio_config_lock);
static int __devinit scx200_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
@@ -45,22 +51,39 @@ static int __devinit scx200_probe(struct pci_dev *pdev, const struct pci_device_
int bank;
unsigned base;
- base = pci_resource_start(pdev, 0);
- printk(KERN_INFO NAME ": GPIO base 0x%x\n", base);
-
- if (request_region(base, SCx200_GPIO_SIZE, "NatSemi SCx200 GPIO") == 0) {
- printk(KERN_ERR NAME ": can't allocate I/O for GPIOs\n");
- return -EBUSY;
+ if (pdev->device == PCI_DEVICE_ID_NS_SCx200_BRIDGE ||
+ pdev->device == PCI_DEVICE_ID_NS_SC1100_BRIDGE) {
+ base = pci_resource_start(pdev, 0);
+ printk(KERN_INFO NAME ": GPIO base 0x%x\n", base);
+
+ if (request_region(base, SCx200_GPIO_SIZE, "NatSemi SCx200 GPIO") == 0) {
+ printk(KERN_ERR NAME ": can't allocate I/O for GPIOs\n");
+ return -EBUSY;
+ }
+
+ scx200_gpio_base = base;
+
+ /* read the current values driven on the GPIO signals */
+ for (bank = 0; bank < 2; ++bank)
+ scx200_gpio_shadow[bank] = inl(scx200_gpio_base + 0x10 * bank);
+
+ } else {
+ /* find the base of the Configuration Block */
+ if (scx200_cb_probe(SCx200_CB_BASE_FIXED)) {
+ scx200_cb_base = SCx200_CB_BASE_FIXED;
+ } else {
+ pci_read_config_dword(pdev, SCx200_CBA_SCRATCH, &base);
+ if (scx200_cb_probe(base)) {
+ scx200_cb_base = base;
+ } else {
+ printk(KERN_WARNING NAME ": Configuration Block not found\n");
+ return -ENODEV;
+ }
+ }
+ printk(KERN_INFO NAME ": Configuration Block base 0x%x\n", scx200_cb_base);
}
- scx200_gpio_base = base;
-
- /* read the current values driven on the GPIO signals */
- for (bank = 0; bank < 2; ++bank)
- scx200_gpio_shadow[bank] = inl(scx200_gpio_base + 0x10 * bank);
-
return 0;
-
}
u32 scx200_gpio_configure(int index, u32 mask, u32 bits)
@@ -81,6 +104,7 @@ u32 scx200_gpio_configure(int index, u32 mask, u32 bits)
return config;
}
+#if 0
void scx200_gpio_dump(unsigned index)
{
u32 config = scx200_gpio_configure(index, ~0, 0);
@@ -112,15 +136,16 @@ void scx200_gpio_dump(unsigned index)
printk(" DEBOUNCE"); /* debounce */
printk("\n");
}
+#endif /* 0 */
-int __init scx200_init(void)
+static int __init scx200_init(void)
{
printk(KERN_INFO NAME ": NatSemi SCx200 Driver\n");
return pci_module_init(&scx200_pci_driver);
}
-void __exit scx200_cleanup(void)
+static void __exit scx200_cleanup(void)
{
pci_unregister_driver(&scx200_pci_driver);
release_region(scx200_gpio_base, SCx200_GPIO_SIZE);
@@ -131,9 +156,8 @@ module_exit(scx200_cleanup);
EXPORT_SYMBOL(scx200_gpio_base);
EXPORT_SYMBOL(scx200_gpio_shadow);
-EXPORT_SYMBOL(scx200_gpio_lock);
EXPORT_SYMBOL(scx200_gpio_configure);
-EXPORT_SYMBOL(scx200_gpio_dump);
+EXPORT_SYMBOL(scx200_cb_base);
/*
Local variables:
diff --git a/arch/i386/kernel/semaphore.c b/arch/i386/kernel/semaphore.c
index be61aa8af1883..469f496e55c0f 100644
--- a/arch/i386/kernel/semaphore.c
+++ b/arch/i386/kernel/semaphore.c
@@ -10,7 +10,7 @@
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
- * rw semaphores implemented November 1999 by Benjamin LaHaise <bcrl@redhat.com>
+ * rw semaphores implemented November 1999 by Benjamin LaHaise <bcrl@kvack.org>
*/
#include <linux/config.h>
#include <linux/sched.h>
@@ -49,12 +49,12 @@
* we cannot lose wakeup events.
*/
-fastcall void __up(struct semaphore *sem)
+static fastcall void __attribute_used__ __up(struct semaphore *sem)
{
wake_up(&sem->wait);
}
-fastcall void __sched __down(struct semaphore * sem)
+static fastcall void __attribute_used__ __sched __down(struct semaphore * sem)
{
struct task_struct *tsk = current;
DECLARE_WAITQUEUE(wait, tsk);
@@ -91,7 +91,7 @@ fastcall void __sched __down(struct semaphore * sem)
tsk->state = TASK_RUNNING;
}
-fastcall int __sched __down_interruptible(struct semaphore * sem)
+static fastcall int __attribute_used__ __sched __down_interruptible(struct semaphore * sem)
{
int retval = 0;
struct task_struct *tsk = current;
@@ -154,7 +154,7 @@ fastcall int __sched __down_interruptible(struct semaphore * sem)
* single "cmpxchg" without failure cases,
* but then it wouldn't work on a 386.
*/
-fastcall int __down_trylock(struct semaphore * sem)
+static fastcall int __attribute_used__ __down_trylock(struct semaphore * sem)
{
int sleepers;
unsigned long flags;
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
index 55ce1b114cdf5..945ec73163c8c 100644
--- a/arch/i386/kernel/setup.c
+++ b/arch/i386/kernel/setup.c
@@ -40,6 +40,7 @@
#include <linux/efi.h>
#include <linux/init.h>
#include <linux/edd.h>
+#include <linux/nodemask.h>
#include <video/edid.h>
#include <asm/e820.h>
#include <asm/mpspec.h>
@@ -74,7 +75,6 @@ struct cpuinfo_x86 new_cpu_data __initdata = { 0, 0, 0, 0, -1, 1, 0, 0, -1 };
struct cpuinfo_x86 boot_cpu_data = { 0, 0, 0, 0, -1, 1, 0, 0, -1 };
unsigned long mmu_cr4_features;
-EXPORT_SYMBOL_GPL(mmu_cr4_features);
#ifdef CONFIG_ACPI_INTERPRETER
int acpi_disabled = 0;
@@ -117,8 +117,6 @@ struct edid_info edid_info;
struct ist_info ist_info;
struct e820map e820;
-unsigned char aux_device_present;
-
extern void early_cpu_init(void);
extern void dmi_scan_machine(void);
extern void generic_apic_probe(char *);
@@ -427,10 +425,10 @@ struct change_member {
struct e820entry *pbios; /* pointer to original bios entry */
unsigned long long addr; /* address for this change point */
};
-struct change_member change_point_list[2*E820MAX] __initdata;
-struct change_member *change_point[2*E820MAX] __initdata;
-struct e820entry *overlap_list[E820MAX] __initdata;
-struct e820entry new_bios[E820MAX] __initdata;
+static struct change_member change_point_list[2*E820MAX] __initdata;
+static struct change_member *change_point[2*E820MAX] __initdata;
+static struct e820entry *overlap_list[E820MAX] __initdata;
+static struct e820entry new_bios[E820MAX] __initdata;
static int __init sanitize_e820_map(struct e820entry * biosmap, char * pnr_map)
{
@@ -951,8 +949,6 @@ unsigned long __init find_max_low_pfn(void)
return max_low_pfn;
}
-#ifndef CONFIG_DISCONTIGMEM
-
/*
* Free all available memory for boot time allocation. Used
* as a callback function by efi_memory_walk()
@@ -1026,15 +1022,15 @@ static void __init reserve_ebda_region(void)
reserve_bootmem(addr, PAGE_SIZE);
}
+#ifndef CONFIG_DISCONTIGMEM
+void __init setup_bootmem_allocator(void);
static unsigned long __init setup_memory(void)
{
- unsigned long bootmap_size, start_pfn, max_low_pfn;
-
/*
* partially used pages are not usable - thus
* we are rounding upwards:
*/
- start_pfn = PFN_UP(init_pg_tables_end);
+ min_low_pfn = PFN_UP(init_pg_tables_end);
find_max_pfn();
@@ -1050,10 +1046,43 @@ static unsigned long __init setup_memory(void)
#endif
printk(KERN_NOTICE "%ldMB LOWMEM available.\n",
pages_to_mb(max_low_pfn));
+
+ setup_bootmem_allocator();
+
+ return max_low_pfn;
+}
+
+void __init zone_sizes_init(void)
+{
+ unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0};
+ unsigned int max_dma, low;
+
+ max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
+ low = max_low_pfn;
+
+ if (low < max_dma)
+ zones_size[ZONE_DMA] = low;
+ else {
+ zones_size[ZONE_DMA] = max_dma;
+ zones_size[ZONE_NORMAL] = low - max_dma;
+#ifdef CONFIG_HIGHMEM
+ zones_size[ZONE_HIGHMEM] = highend_pfn - low;
+#endif
+ }
+ free_area_init(zones_size);
+}
+#else
+extern unsigned long setup_memory(void);
+extern void zone_sizes_init(void);
+#endif /* !CONFIG_DISCONTIGMEM */
+
+void __init setup_bootmem_allocator(void)
+{
+ unsigned long bootmap_size;
/*
* Initialize the boot-time allocator (with low memory only):
*/
- bootmap_size = init_bootmem(start_pfn, max_low_pfn);
+ bootmap_size = init_bootmem(min_low_pfn, max_low_pfn);
register_bootmem_low_pages(max_low_pfn);
@@ -1063,7 +1092,7 @@ static unsigned long __init setup_memory(void)
* the (very unlikely) case of us accidentally initializing the
* bootmem allocator with an invalid RAM area.
*/
- reserve_bootmem(HIGH_MEMORY, (PFN_PHYS(start_pfn) +
+ reserve_bootmem(HIGH_MEMORY, (PFN_PHYS(min_low_pfn) +
bootmap_size + PAGE_SIZE-1) - (HIGH_MEMORY));
/*
@@ -1120,11 +1149,25 @@ static unsigned long __init setup_memory(void)
}
}
#endif
- return max_low_pfn;
}
-#else
-extern unsigned long setup_memory(void);
-#endif /* !CONFIG_DISCONTIGMEM */
+
+/*
+ * The node 0 pgdat is initialized before all of these because
+ * it's needed for bootmem. node>0 pgdats have their virtual
+ * space allocated before the pagetables are in place to access
+ * them, so they can't be cleared then.
+ *
+ * This should all compile down to nothing when NUMA is off.
+ */
+void __init remapped_pgdat_init(void)
+{
+ int nid;
+
+ for_each_online_node(nid) {
+ if (nid != 0)
+ memset(NODE_DATA(nid), 0, sizeof(struct pglist_data));
+ }
+}
/*
* Request address space for all standard RAM and ROM resources
@@ -1384,7 +1427,6 @@ void __init setup_arch(char **cmdline_p)
machine_submodel_id = SYS_DESC_TABLE.table[1];
BIOS_revision = SYS_DESC_TABLE.table[2];
}
- aux_device_present = AUX_DEVICE_INFO;
bootloader_type = LOADER_TYPE;
#ifdef CONFIG_BLK_DEV_RAM
@@ -1432,6 +1474,8 @@ void __init setup_arch(char **cmdline_p)
smp_alloc_memory(); /* AP processor realmode stacks in low memory*/
#endif
paging_init();
+ remapped_pgdat_init();
+ zone_sizes_init();
/*
* NOTE: at this point the bootmem allocator is fully available.
diff --git a/arch/i386/kernel/signal.c b/arch/i386/kernel/signal.c
index 1e8b41ca083ff..ef3602e1c0522 100644
--- a/arch/i386/kernel/signal.c
+++ b/arch/i386/kernel/signal.c
@@ -93,7 +93,7 @@ sys_sigaction(int sig, const struct old_sigaction __user *act,
if (act) {
old_sigset_t mask;
- if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
+ if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
__get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
__get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
return -EFAULT;
@@ -105,7 +105,7 @@ sys_sigaction(int sig, const struct old_sigaction __user *act,
ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
if (!ret && oact) {
- if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
+ if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
__put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
__put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
return -EFAULT;
@@ -187,7 +187,7 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *peax
struct _fpstate __user * buf;
err |= __get_user(buf, &sc->fpstate);
if (buf) {
- if (verify_area(VERIFY_READ, buf, sizeof(*buf)))
+ if (!access_ok(VERIFY_READ, buf, sizeof(*buf)))
goto badframe;
err |= restore_i387(buf);
} else {
@@ -213,7 +213,7 @@ asmlinkage int sys_sigreturn(unsigned long __unused)
sigset_t set;
int eax;
- if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
+ if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
goto badframe;
if (__get_user(set.sig[0], &frame->sc.oldmask)
|| (_NSIG_WORDS > 1
@@ -243,7 +243,7 @@ asmlinkage int sys_rt_sigreturn(unsigned long __unused)
sigset_t set;
int eax;
- if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
+ if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
goto badframe;
if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
goto badframe;
@@ -557,6 +557,16 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
}
}
+ /*
+ * If TF is set due to a debugger (PT_DTRACE), clear the TF flag so
+ * that register information in the sigcontext is correct.
+ */
+ if (unlikely(regs->eflags & TF_MASK)
+ && likely(current->ptrace & PT_DTRACE)) {
+ current->ptrace &= ~PT_DTRACE;
+ regs->eflags &= ~TF_MASK;
+ }
+
/* Set up the stack frame */
if (ka->sa.sa_flags & SA_SIGINFO)
setup_rt_frame(sig, ka, info, oldset, regs);
diff --git a/arch/i386/kernel/smp.c b/arch/i386/kernel/smp.c
index 0ac1d19c7739f..6223c33ac91cc 100644
--- a/arch/i386/kernel/smp.c
+++ b/arch/i386/kernel/smp.c
@@ -188,7 +188,7 @@ void send_IPI_mask_bitmask(cpumask_t cpumask, int vector)
local_irq_restore(flags);
}
-inline void send_IPI_mask_sequence(cpumask_t mask, int vector)
+void send_IPI_mask_sequence(cpumask_t mask, int vector)
{
unsigned long cfg, flags;
unsigned int query_cpu;
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
index e99992e27abe3..332ee7a1d1a11 100644
--- a/arch/i386/kernel/smpboot.c
+++ b/arch/i386/kernel/smpboot.c
@@ -77,9 +77,6 @@ u8 x86_cpu_to_apicid[NR_CPUS] =
{ [0 ... NR_CPUS-1] = 0xff };
EXPORT_SYMBOL(x86_cpu_to_apicid);
-/* Set when the idlers are all forked */
-int smp_threads_ready;
-
/*
* Trampoline 80x86 program as an array.
*/
@@ -89,6 +86,8 @@ extern unsigned char trampoline_end [];
static unsigned char *trampoline_base;
static int trampoline_exec;
+static void map_cpu_to_logical_apicid(void);
+
/*
* Currently trivial. Write the real->protected mode
* bootstrap into the page concerned. The caller
@@ -319,7 +318,7 @@ extern void calibrate_delay(void);
static atomic_t init_deasserted;
-void __init smp_callin(void)
+static void __init smp_callin(void)
{
int cpuid, phys_id;
unsigned long timeout;
@@ -408,7 +407,7 @@ void __init smp_callin(void)
synchronize_tsc_ap();
}
-int cpucount;
+static int cpucount;
/*
* Activate a secondary processor.
@@ -506,7 +505,7 @@ static inline void unmap_cpu_to_node(int cpu)
u8 cpu_2_logical_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID };
-void map_cpu_to_logical_apicid(void)
+static void map_cpu_to_logical_apicid(void)
{
int cpu = smp_processor_id();
int apicid = logical_smp_processor_id();
@@ -515,7 +514,7 @@ void map_cpu_to_logical_apicid(void)
map_cpu_to_node(cpu, apicid_to_node(apicid));
}
-void unmap_cpu_to_logical_apicid(int cpu)
+static void unmap_cpu_to_logical_apicid(int cpu)
{
cpu_2_logical_apicid[cpu] = BAD_APICID;
unmap_cpu_to_node(cpu);
@@ -847,9 +846,6 @@ static int __init do_boot_cpu(int apicid)
return boot_error;
}
-cycles_t cacheflush_time;
-unsigned long cache_decay_ticks;
-
static void smp_tune_scheduling (void)
{
unsigned long cachesize; /* kB */
@@ -870,7 +866,6 @@ static void smp_tune_scheduling (void)
* this basically disables processor-affinity
* scheduling on SMP without a TSC.
*/
- cacheflush_time = 0;
return;
} else {
cachesize = boot_cpu_data.x86_cache_size;
@@ -878,17 +873,7 @@ static void smp_tune_scheduling (void)
cachesize = 16; /* Pentiums, 2x8kB cache */
bandwidth = 100;
}
-
- cacheflush_time = (cpu_khz>>10) * (cachesize<<10) / bandwidth;
}
-
- cache_decay_ticks = (long)cacheflush_time/cpu_khz + 1;
-
- printk("per-CPU timeslice cutoff: %ld.%02ld usecs.\n",
- (long)cacheflush_time/(cpu_khz/1000),
- ((long)cacheflush_time*100/(cpu_khz/1000)) % 100);
- printk("task migration cache decay timeout: %ld msecs.\n",
- cache_decay_ticks);
}
/*
diff --git a/arch/i386/kernel/srat.c b/arch/i386/kernel/srat.c
index 74b0c8e03fb80..7b3b27d644093 100644
--- a/arch/i386/kernel/srat.c
+++ b/arch/i386/kernel/srat.c
@@ -30,6 +30,7 @@
#include <linux/acpi.h>
#include <linux/nodemask.h>
#include <asm/srat.h>
+#include <asm/topology.h>
/*
* proximity macros and definitions
@@ -58,8 +59,6 @@ static int num_memory_chunks; /* total number of memory chunks */
static int zholes_size_init;
static unsigned long zholes_size[MAX_NUMNODES * MAX_NR_ZONES];
-extern unsigned long node_start_pfn[], node_end_pfn[];
-
extern void * boot_ioremap(unsigned long, unsigned long);
/* Identify CPU proximity domains */
@@ -182,6 +181,38 @@ static __init void chunk_to_zones(unsigned long cstart, unsigned long cend,
}
}
+/*
+ * The SRAT table always lists ascending addresses, so can always
+ * assume that the first "start" address that you see is the real
+ * start of the node, and that the current "end" address is after
+ * the previous one.
+ */
+static __init void node_read_chunk(int nid, struct node_memory_chunk_s *memory_chunk)
+{
+ /*
+ * Only add present memory as told by the e820.
+ * There is no guarantee from the SRAT that the memory it
+ * enumerates is present at boot time because it represents
+ * *possible* memory hotplug areas the same as normal RAM.
+ */
+ if (memory_chunk->start_pfn >= max_pfn) {
+ printk (KERN_INFO "Ignoring SRAT pfns: 0x%08lx -> %08lx\n",
+ memory_chunk->start_pfn, memory_chunk->end_pfn);
+ return;
+ }
+ if (memory_chunk->nid != nid)
+ return;
+
+ if (!node_has_online_mem(nid))
+ node_start_pfn[nid] = memory_chunk->start_pfn;
+
+ if (node_start_pfn[nid] > memory_chunk->start_pfn)
+ node_start_pfn[nid] = memory_chunk->start_pfn;
+
+ if (node_end_pfn[nid] < memory_chunk->end_pfn)
+ node_end_pfn[nid] = memory_chunk->end_pfn;
+}
+
/* Parse the ACPI Static Resource Affinity Table */
static int __init acpi20_parse_srat(struct acpi_table_srat *sratp)
{
@@ -262,29 +293,18 @@ static int __init acpi20_parse_srat(struct acpi_table_srat *sratp)
printk("Number of memory chunks in system = %d\n", num_memory_chunks);
for (j = 0; j < num_memory_chunks; j++){
+ struct node_memory_chunk_s * chunk = &node_memory_chunk[j];
printk("chunk %d nid %d start_pfn %08lx end_pfn %08lx\n",
- j, node_memory_chunk[j].nid,
- node_memory_chunk[j].start_pfn,
- node_memory_chunk[j].end_pfn);
+ j, chunk->nid, chunk->start_pfn, chunk->end_pfn);
+ node_read_chunk(chunk->nid, chunk);
}
- /*calculate node_start_pfn/node_end_pfn arrays*/
for_each_online_node(nid) {
- int been_here_before = 0;
-
- for (j = 0; j < num_memory_chunks; j++){
- if (node_memory_chunk[j].nid == nid) {
- if (been_here_before == 0) {
- node_start_pfn[nid] = node_memory_chunk[j].start_pfn;
- node_end_pfn[nid] = node_memory_chunk[j].end_pfn;
- been_here_before = 1;
- } else { /* We've found another chunk of memory for the node */
- if (node_start_pfn[nid] < node_memory_chunk[j].start_pfn) {
- node_end_pfn[nid] = node_memory_chunk[j].end_pfn;
- }
- }
- }
- }
+ unsigned long start = node_start_pfn[nid];
+ unsigned long end = node_end_pfn[nid];
+
+ memory_present(nid, start, end);
+ node_remap_size[nid] = node_memmap_size_bytes(nid, start, end);
}
return 1;
out_fail:
diff --git a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c
index 22d38b3a66b64..9b55e30e4490c 100644
--- a/arch/i386/kernel/time.c
+++ b/arch/i386/kernel/time.c
@@ -89,6 +89,35 @@ EXPORT_SYMBOL(i8253_lock);
struct timer_opts *cur_timer = &timer_none;
/*
+ * This is a special lock that is owned by the CPU and holds the index
+ * register we are working with. It is required for NMI access to the
+ * CMOS/RTC registers. See include/asm-i386/mc146818rtc.h for details.
+ */
+volatile unsigned long cmos_lock = 0;
+EXPORT_SYMBOL(cmos_lock);
+
+/* Routines for accessing the CMOS RAM/RTC. */
+unsigned char rtc_cmos_read(unsigned char addr)
+{
+ unsigned char val;
+ lock_cmos_prefix(addr);
+ outb_p(addr, RTC_PORT(0));
+ val = inb_p(RTC_PORT(1));
+ lock_cmos_suffix(addr);
+ return val;
+}
+EXPORT_SYMBOL(rtc_cmos_read);
+
+void rtc_cmos_write(unsigned char val, unsigned char addr)
+{
+ lock_cmos_prefix(addr);
+ outb_p(addr, RTC_PORT(0));
+ outb_p(val, RTC_PORT(1));
+ lock_cmos_suffix(addr);
+}
+EXPORT_SYMBOL(rtc_cmos_write);
+
+/*
* This version of gettimeofday has microsecond resolution
* and better than microsecond precision on fast x86 machines with TSC.
*/
@@ -175,19 +204,19 @@ static int set_rtc_mmss(unsigned long nowtime)
{
int retval;
+ WARN_ON(irqs_disabled());
+
/* gets recalled with irq locally disabled */
- spin_lock(&rtc_lock);
+ spin_lock_irq(&rtc_lock);
if (efi_enabled)
retval = efi_set_rtc_mmss(nowtime);
else
retval = mach_set_rtc_mmss(nowtime);
- spin_unlock(&rtc_lock);
+ spin_unlock_irq(&rtc_lock);
return retval;
}
-/* last time the cmos clock got updated */
-static long last_rtc_update;
int timer_ack;
@@ -239,28 +268,6 @@ static inline void do_timer_interrupt(int irq, void *dev_id,
do_timer_interrupt_hook(regs);
- /*
- * If we have an externally synchronized Linux clock, then update
- * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
- * called as close as possible to 500 ms before the new second starts.
- */
- if ((time_status & STA_UNSYNC) == 0 &&
- xtime.tv_sec > last_rtc_update + 660 &&
- (xtime.tv_nsec / 1000)
- >= USEC_AFTER - ((unsigned) TICK_SIZE) / 2 &&
- (xtime.tv_nsec / 1000)
- <= USEC_BEFORE + ((unsigned) TICK_SIZE) / 2) {
- /* horrible...FIXME */
- if (efi_enabled) {
- if (efi_set_rtc_mmss(xtime.tv_sec) == 0)
- last_rtc_update = xtime.tv_sec;
- else
- last_rtc_update = xtime.tv_sec - 600;
- } else if (set_rtc_mmss(xtime.tv_sec) == 0)
- last_rtc_update = xtime.tv_sec;
- else
- last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
- }
if (MCA_bus) {
/* The PS/2 uses level-triggered interrupts. You can't
@@ -317,6 +324,55 @@ unsigned long get_cmos_time(void)
return retval;
}
+static void sync_cmos_clock(unsigned long dummy);
+
+static struct timer_list sync_cmos_timer =
+ TIMER_INITIALIZER(sync_cmos_clock, 0, 0);
+
+static void sync_cmos_clock(unsigned long dummy)
+{
+ struct timeval now, next;
+ int fail = 1;
+
+ /*
+ * If we have an externally synchronized Linux clock, then update
+ * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
+ * called as close as possible to 500 ms before the new second starts.
+ * This code is run on a timer. If the clock is set, that timer
+ * may not expire at the correct time. Thus, we adjust...
+ */
+ if ((time_status & STA_UNSYNC) != 0)
+ /*
+ * Not synced, exit, do not restart a timer (if one is
+ * running, let it run out).
+ */
+ return;
+
+ do_gettimeofday(&now);
+ if (now.tv_usec >= USEC_AFTER - ((unsigned) TICK_SIZE) / 2 &&
+ now.tv_usec <= USEC_BEFORE + ((unsigned) TICK_SIZE) / 2)
+ fail = set_rtc_mmss(now.tv_sec);
+
+ next.tv_usec = USEC_AFTER - now.tv_usec;
+ if (next.tv_usec <= 0)
+ next.tv_usec += USEC_PER_SEC;
+
+ if (!fail)
+ next.tv_sec = 659;
+ else
+ next.tv_sec = 0;
+
+ if (next.tv_usec >= USEC_PER_SEC) {
+ next.tv_sec++;
+ next.tv_usec -= USEC_PER_SEC;
+ }
+ mod_timer(&sync_cmos_timer, jiffies + timeval_to_jiffies(&next));
+}
+
+void notify_arch_cmos_timer(void)
+{
+ mod_timer(&sync_cmos_timer, jiffies + 1);
+}
static long clock_cmos_diff, sleep_start;
@@ -378,7 +434,7 @@ device_initcall(time_init_device);
#ifdef CONFIG_HPET_TIMER
extern void (*late_time_init)(void);
/* Duplicate of time_init() below, with hpet_enable part added */
-void __init hpet_time_init(void)
+static void __init hpet_time_init(void)
{
xtime.tv_sec = get_cmos_time();
xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ);
diff --git a/arch/i386/kernel/time_hpet.c b/arch/i386/kernel/time_hpet.c
index 86b79c6647a3c..244a31b04be70 100644
--- a/arch/i386/kernel/time_hpet.c
+++ b/arch/i386/kernel/time_hpet.c
@@ -23,9 +23,9 @@
#include <asm/hpet.h>
#include <linux/hpet.h>
-unsigned long hpet_period; /* fsecs / HPET clock */
-unsigned long hpet_tick; /* hpet clks count per tick */
-unsigned long hpet_address; /* hpet memory map physical address */
+static unsigned long hpet_period; /* fsecs / HPET clock */
+unsigned long hpet_tick; /* hpet clks count per tick */
+unsigned long hpet_address; /* hpet memory map physical address */
static int use_hpet; /* can be used for runtime check of hpet */
static int boot_hpet_disable; /* boottime override for HPET timer */
@@ -38,7 +38,7 @@ int hpet_readl(unsigned long a)
return readl(hpet_virt_address + a);
}
-void hpet_writel(unsigned long d, unsigned long a)
+static void hpet_writel(unsigned long d, unsigned long a)
{
writel(d, hpet_virt_address + a);
}
@@ -49,7 +49,7 @@ void hpet_writel(unsigned long d, unsigned long a)
* comparator value and continue. Next tick can be caught by checking
* for a change in the comparator value. Used in apic.c.
*/
-void __init wait_hpet_tick(void)
+static void __init wait_hpet_tick(void)
{
unsigned int start_cmp_val, end_cmp_val;
@@ -81,9 +81,10 @@ static int hpet_timer_stop_set_go(unsigned long tick)
cfg |= HPET_TN_ENABLE | HPET_TN_PERIODIC |
HPET_TN_SETVAL | HPET_TN_32BIT;
hpet_writel(cfg, HPET_T0_CFG);
+
/*
- * Some systems seems to need two writes to HPET_T0_CMP,
- * to get interrupts working
+ * The first write after writing TN_SETVAL to the config register sets
+ * the counter value, the second write sets the threshold.
*/
hpet_writel(tick, HPET_T0_CMP);
hpet_writel(tick, HPET_T0_CMP);
@@ -121,11 +122,16 @@ int __init hpet_enable(void)
id = hpet_readl(HPET_ID);
/*
- * We are checking for value '1' or more in number field.
- * So, we are OK with HPET_EMULATE_RTC part too, where we need
- * to have atleast 2 timers.
+ * We are checking for value '1' or more in number field if
+ * CONFIG_HPET_EMULATE_RTC is set because we will need an
+ * additional timer for RTC emulation.
+ * However, we can do with one timer otherwise using the
+ * the single HPET timer for system time.
*/
- if (!(id & HPET_ID_NUMBER) ||
+ if (
+#ifdef CONFIG_HPET_EMULATE_RTC
+ !(id & HPET_ID_NUMBER) ||
+#endif
!(id & HPET_ID_LEGSUP))
return -1;
diff --git a/arch/i386/kernel/timers/timer_hpet.c b/arch/i386/kernel/timers/timer_hpet.c
index 56d8fc1ea1bf2..713134e718448 100644
--- a/arch/i386/kernel/timers/timer_hpet.c
+++ b/arch/i386/kernel/timers/timer_hpet.c
@@ -118,7 +118,7 @@ static void mark_offset_hpet(void)
write_sequnlock(&monotonic_lock);
}
-void delay_hpet(unsigned long loops)
+static void delay_hpet(unsigned long loops)
{
unsigned long hpet_start, hpet_end;
unsigned long eax;
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
index 065649245cde0..6c0e383915b6a 100644
--- a/arch/i386/kernel/traps.c
+++ b/arch/i386/kernel/traps.c
@@ -345,8 +345,7 @@ void die(const char * str, struct pt_regs * regs, long err)
if (panic_on_oops) {
printk(KERN_EMERG "Fatal exception: panic in 5 seconds\n");
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(5 * HZ);
+ ssleep(5);
panic("Fatal exception");
}
do_exit(SIGSEGV);
@@ -707,8 +706,6 @@ fastcall void do_debug(struct pt_regs * regs, long error_code)
/*
* Single-stepping through TF: make sure we ignore any events in
* kernel space (but re-enable TF when returning to user mode).
- * And if the event was due to a debugger (PT_DTRACE), clear the
- * TF flag so that register information is correct.
*/
if (condition & DR_STEP) {
/*
@@ -718,11 +715,6 @@ fastcall void do_debug(struct pt_regs * regs, long error_code)
*/
if ((regs->xcs & 3) == 0)
goto clear_TF_reenable;
-
- if (likely(tsk->ptrace & PT_DTRACE)) {
- tsk->ptrace &= ~PT_DTRACE;
- regs->eflags &= ~TF_MASK;
- }
}
/* Ok, finally something we can handle */
@@ -814,7 +806,7 @@ fastcall void do_coprocessor_error(struct pt_regs * regs, long error_code)
math_error((void __user *)regs->eip);
}
-void simd_math_error(void __user *eip)
+static void simd_math_error(void __user *eip)
{
struct task_struct * task;
siginfo_t info;
@@ -895,6 +887,51 @@ fastcall void do_spurious_interrupt_bug(struct pt_regs * regs,
#endif
}
+fastcall void setup_x86_bogus_stack(unsigned char * stk)
+{
+ unsigned long *switch16_ptr, *switch32_ptr;
+ struct pt_regs *regs;
+ unsigned long stack_top, stack_bot;
+ unsigned short iret_frame16_off;
+ int cpu = smp_processor_id();
+ /* reserve the space on 32bit stack for the magic switch16 pointer */
+ memmove(stk, stk + 8, sizeof(struct pt_regs));
+ switch16_ptr = (unsigned long *)(stk + sizeof(struct pt_regs));
+ regs = (struct pt_regs *)stk;
+ /* now the switch32 on 16bit stack */
+ stack_bot = (unsigned long)&per_cpu(cpu_16bit_stack, cpu);
+ stack_top = stack_bot + CPU_16BIT_STACK_SIZE;
+ switch32_ptr = (unsigned long *)(stack_top - 8);
+ iret_frame16_off = CPU_16BIT_STACK_SIZE - 8 - 20;
+ /* copy iret frame on 16bit stack */
+ memcpy((void *)(stack_bot + iret_frame16_off), &regs->eip, 20);
+ /* fill in the switch pointers */
+ switch16_ptr[0] = (regs->esp & 0xffff0000) | iret_frame16_off;
+ switch16_ptr[1] = __ESPFIX_SS;
+ switch32_ptr[0] = (unsigned long)stk + sizeof(struct pt_regs) +
+ 8 - CPU_16BIT_STACK_SIZE;
+ switch32_ptr[1] = __KERNEL_DS;
+}
+
+fastcall unsigned char * fixup_x86_bogus_stack(unsigned short sp)
+{
+ unsigned long *switch32_ptr;
+ unsigned char *stack16, *stack32;
+ unsigned long stack_top, stack_bot;
+ int len;
+ int cpu = smp_processor_id();
+ stack_bot = (unsigned long)&per_cpu(cpu_16bit_stack, cpu);
+ stack_top = stack_bot + CPU_16BIT_STACK_SIZE;
+ switch32_ptr = (unsigned long *)(stack_top - 8);
+ /* copy the data from 16bit stack to 32bit stack */
+ len = CPU_16BIT_STACK_SIZE - 8 - sp;
+ stack16 = (unsigned char *)(stack_bot + sp);
+ stack32 = (unsigned char *)
+ (switch32_ptr[0] + CPU_16BIT_STACK_SIZE - 8 - len);
+ memcpy(stack32, stack16, len);
+ return stack32;
+}
+
/*
* 'math_state_restore()' saves the current math information in the
* old math state array, and gets the new ones from the current task
@@ -1038,3 +1075,10 @@ void __init trap_init(void)
trap_init_hook();
}
+
+static int __init kstack_setup(char *s)
+{
+ kstack_depth_to_print = simple_strtoul(s, NULL, 0);
+ return 0;
+}
+__setup("kstack=", kstack_setup);
diff --git a/arch/i386/kernel/vm86.c b/arch/i386/kernel/vm86.c
index 2dd216ab0c704..2f3d52dacff77 100644
--- a/arch/i386/kernel/vm86.c
+++ b/arch/i386/kernel/vm86.c
@@ -145,29 +145,14 @@ static void mark_screen_rdonly(struct task_struct * tsk)
preempt_disable();
spin_lock(&tsk->mm->page_table_lock);
pgd = pgd_offset(tsk->mm, 0xA0000);
- if (pgd_none(*pgd))
+ if (pgd_none_or_clear_bad(pgd))
goto out;
- if (pgd_bad(*pgd)) {
- pgd_ERROR(*pgd);
- pgd_clear(pgd);
- goto out;
- }
pud = pud_offset(pgd, 0xA0000);
- if (pud_none(*pud))
- goto out;
- if (pud_bad(*pud)) {
- pud_ERROR(*pud);
- pud_clear(pud);
+ if (pud_none_or_clear_bad(pud))
goto out;
- }
pmd = pmd_offset(pud, 0xA0000);
- if (pmd_none(*pmd))
- goto out;
- if (pmd_bad(*pmd)) {
- pmd_ERROR(*pmd);
- pmd_clear(pmd);
+ if (pmd_none_or_clear_bad(pmd))
goto out;
- }
pte = mapped = pte_offset_map(pmd, 0xA0000);
for (i = 0; i < 32; i++) {
if (pte_present(*pte))
diff --git a/arch/i386/lib/Makefile b/arch/i386/lib/Makefile
index 1354843290e4f..7b1932d20f967 100644
--- a/arch/i386/lib/Makefile
+++ b/arch/i386/lib/Makefile
@@ -3,7 +3,7 @@
#
-lib-y = checksum.o delay.o usercopy.o getuser.o memcpy.o strstr.o \
+lib-y = checksum.o delay.o usercopy.o getuser.o putuser.o memcpy.o strstr.o \
bitops.o
lib-$(CONFIG_X86_USE_3DNOW) += mmx.o
diff --git a/arch/i386/lib/putuser.S b/arch/i386/lib/putuser.S
new file mode 100644
index 0000000000000..a32d9f570f48b
--- /dev/null
+++ b/arch/i386/lib/putuser.S
@@ -0,0 +1,87 @@
+/*
+ * __put_user functions.
+ *
+ * (C) Copyright 2005 Linus Torvalds
+ *
+ * These functions have a non-standard call interface
+ * to make them more efficient, especially as they
+ * return an error value in addition to the "real"
+ * return value.
+ */
+#include <asm/thread_info.h>
+
+
+/*
+ * __put_user_X
+ *
+ * Inputs: %eax[:%edx] contains the data
+ * %ecx contains the address
+ *
+ * Outputs: %eax is error code (0 or -EFAULT)
+ *
+ * These functions should not modify any other registers,
+ * as they get called from within inline assembly.
+ */
+
+#define ENTER pushl %ebx ; GET_THREAD_INFO(%ebx)
+#define EXIT popl %ebx ; ret
+
+.text
+.align 4
+.globl __put_user_1
+__put_user_1:
+ ENTER
+ cmpl TI_addr_limit(%ebx),%ecx
+ jae bad_put_user
+1: movb %al,(%ecx)
+ xorl %eax,%eax
+ EXIT
+
+.align 4
+.globl __put_user_2
+__put_user_2:
+ ENTER
+ movl TI_addr_limit(%ebx),%ebx
+ subl $1,%ebx
+ cmpl %ebx,%ecx
+ jae bad_put_user
+2: movw %ax,(%ecx)
+ xorl %eax,%eax
+ EXIT
+
+.align 4
+.globl __put_user_4
+__put_user_4:
+ ENTER
+ movl TI_addr_limit(%ebx),%ebx
+ subl $3,%ebx
+ cmpl %ebx,%ecx
+ jae bad_put_user
+3: movl %eax,(%ecx)
+ xorl %eax,%eax
+ EXIT
+
+.align 4
+.globl __put_user_8
+__put_user_8:
+ ENTER
+ movl TI_addr_limit(%ebx),%ebx
+ subl $7,%ebx
+ cmpl %ebx,%ecx
+ jae bad_put_user
+4: movl %eax,(%ecx)
+5: movl %edx,4(%ecx)
+ xorl %eax,%eax
+ EXIT
+
+bad_put_user:
+ movl $-14,%eax
+ EXIT
+
+.section __ex_table,"a"
+ .long 1b,bad_put_user
+ .long 2b,bad_put_user
+ .long 3b,bad_put_user
+ .long 4b,bad_put_user
+ .long 5b,bad_put_user
+.previous
diff --git a/arch/i386/mach-default/topology.c b/arch/i386/mach-default/topology.c
index 8e4f0ab374e40..5b3e8817dae82 100644
--- a/arch/i386/mach-default/topology.c
+++ b/arch/i386/mach-default/topology.c
@@ -30,7 +30,7 @@
#include <linux/nodemask.h>
#include <asm/cpu.h>
-struct i386_cpu cpu_devices[NR_CPUS];
+static struct i386_cpu cpu_devices[NR_CPUS];
int arch_register_cpu(int num){
struct node *parent = NULL;
diff --git a/arch/i386/mach-es7000/es7000plat.c b/arch/i386/mach-es7000/es7000plat.c
index 9707a9e45b46a..d5936d500479f 100644
--- a/arch/i386/mach-es7000/es7000plat.c
+++ b/arch/i386/mach-es7000/es7000plat.c
@@ -138,7 +138,19 @@ parse_unisys_oem (char *oemptr, int oem_entries)
es7000_plat = 0;
} else {
printk("\nEnabling ES7000 specific features...\n");
- es7000_plat = 1;
+ /*
+ * Determine the generation of the ES7000 currently running.
+ *
+ * es7000_plat = 0 if the machine is NOT a Unisys ES7000 box
+ * es7000_plat = 1 if the machine is a 5xx ES7000 box
+ * es7000_plat = 2 if the machine is a x86_64 ES7000 box
+ *
+ */
+ if (!(boot_cpu_data.x86 <= 15 && boot_cpu_data.x86_model <= 2))
+ es7000_plat = 2;
+ else
+ es7000_plat = 1;
+
ioapic_renumber_irq = es7000_rename_gsi;
}
return es7000_plat;
diff --git a/arch/i386/mach-visws/mpparse.c b/arch/i386/mach-visws/mpparse.c
index fa800641ae5ab..5a22082147f4e 100644
--- a/arch/i386/mach-visws/mpparse.c
+++ b/arch/i386/mach-visws/mpparse.c
@@ -36,7 +36,7 @@ unsigned int __initdata maxcpus = NR_CPUS;
* No problem for Linux.
*/
-void __init MP_processor_info (struct mpc_config_processor *m)
+static void __init MP_processor_info (struct mpc_config_processor *m)
{
int ver, logical_apicid;
physid_mask_t apic_cpus;
diff --git a/arch/i386/mach-voyager/voyager_smp.c b/arch/i386/mach-voyager/voyager_smp.c
index 743fe452426aa..903d739ca74ae 100644
--- a/arch/i386/mach-voyager/voyager_smp.c
+++ b/arch/i386/mach-voyager/voyager_smp.c
@@ -37,10 +37,6 @@ DEFINE_PER_CPU(struct tlb_state, cpu_tlbstate) ____cacheline_aligned = { &init_m
/* CPU IRQ affinity -- set to all ones initially */
static unsigned long cpu_irq_affinity[NR_CPUS] __cacheline_aligned = { [0 ... NR_CPUS-1] = ~0UL };
-/* Set when the idlers are all forked - Set in main.c but not actually
- * used by any other parts of the kernel */
-int smp_threads_ready = 0;
-
/* per CPU data structure (for /proc/cpuinfo et al), visible externally
* indexed physically */
struct cpuinfo_x86 cpu_data[NR_CPUS] __cacheline_aligned;
@@ -81,14 +77,6 @@ cpumask_t cpu_online_map = CPU_MASK_NONE;
* by scheduler but indexed physically */
cpumask_t phys_cpu_present_map = CPU_MASK_NONE;
-/* estimate of time used to flush the SMP-local cache - used in
- * processor affinity calculations */
-cycles_t cacheflush_time = 0;
-
-/* cache decay ticks for scheduler---a fairly useless quantity for the
- voyager system with its odd affinity and huge L3 cache */
-unsigned long cache_decay_ticks = 20;
-
/* The internal functions */
static void send_CPI(__u32 cpuset, __u8 cpi);
@@ -210,14 +198,14 @@ ack_CPI(__u8 cpi)
* 8259 IRQs except that masks and things must be kept per processor
*/
static struct hw_interrupt_type vic_irq_type = {
- "VIC-level",
- startup_vic_irq, /* startup */
- disable_vic_irq, /* shutdown */
- enable_vic_irq, /* enable */
- disable_vic_irq, /* disable */
- before_handle_vic_irq, /* ack */
- after_handle_vic_irq, /* end */
- set_vic_irq_affinity, /* affinity */
+ .typename = "VIC-level",
+ .startup = startup_vic_irq,
+ .shutdown = disable_vic_irq,
+ .enable = enable_vic_irq,
+ .disable = disable_vic_irq,
+ .ack = before_handle_vic_irq,
+ .end = after_handle_vic_irq,
+ .set_affinity = set_vic_irq_affinity,
};
/* used to count up as CPUs are brought on line (starts at 0) */
diff --git a/arch/i386/math-emu/errors.c b/arch/i386/math-emu/errors.c
index f755641cf4775..a1b0d22f69785 100644
--- a/arch/i386/math-emu/errors.c
+++ b/arch/i386/math-emu/errors.c
@@ -34,13 +34,14 @@
/* */
+#if 0
void Un_impl(void)
{
u_char byte1, FPU_modrm;
unsigned long address = FPU_ORIG_EIP;
RE_ENTRANT_CHECK_OFF;
- /* No need to verify_area(), we have previously fetched these bytes. */
+ /* No need to check access_ok(), we have previously fetched these bytes. */
printk("Unimplemented FPU Opcode at eip=%p : ", (void __user *) address);
if ( FPU_CS == __USER_CS )
{
@@ -69,6 +70,7 @@ void Un_impl(void)
EXCEPTION(EX_Invalid);
}
+#endif /* 0 */
/*
@@ -91,7 +93,7 @@ void FPU_printall(void)
unsigned long address = FPU_ORIG_EIP;
RE_ENTRANT_CHECK_OFF;
- /* No need to verify_area(), we have previously fetched these bytes. */
+ /* No need to check access_ok(), we have previously fetched these bytes. */
printk("At %p:", (void *) address);
if ( FPU_CS == __USER_CS )
{
diff --git a/arch/i386/math-emu/fpu_aux.c b/arch/i386/math-emu/fpu_aux.c
index 0251b2c6ba70b..20886cfb9f76f 100644
--- a/arch/i386/math-emu/fpu_aux.c
+++ b/arch/i386/math-emu/fpu_aux.c
@@ -21,7 +21,7 @@ static void fnop(void)
{
}
-void fclex(void)
+static void fclex(void)
{
partial_status &= ~(SW_Backward|SW_Summary|SW_Stack_Fault|SW_Precision|
SW_Underflow|SW_Overflow|SW_Zero_Div|SW_Denorm_Op|
diff --git a/arch/i386/math-emu/fpu_entry.c b/arch/i386/math-emu/fpu_entry.c
index 4162c3c1454aa..d93f16ef828f5 100644
--- a/arch/i386/math-emu/fpu_entry.c
+++ b/arch/i386/math-emu/fpu_entry.c
@@ -257,7 +257,7 @@ do_another_FPU_instruction:
}
RE_ENTRANT_CHECK_OFF;
- FPU_code_verify_area(1);
+ FPU_code_access_ok(1);
FPU_get_user(FPU_modrm, (u_char __user *) FPU_EIP);
RE_ENTRANT_CHECK_ON;
FPU_EIP++;
@@ -589,7 +589,7 @@ static int valid_prefix(u_char *Byte, u_char __user **fpu_eip,
*override = (overrides) { 0, 0, PREFIX_DEFAULT }; /* defaults */
RE_ENTRANT_CHECK_OFF;
- FPU_code_verify_area(1);
+ FPU_code_access_ok(1);
FPU_get_user(byte, ip);
RE_ENTRANT_CHECK_ON;
@@ -635,7 +635,7 @@ static int valid_prefix(u_char *Byte, u_char __user **fpu_eip,
do_next_byte:
ip++;
RE_ENTRANT_CHECK_OFF;
- FPU_code_verify_area(1);
+ FPU_code_access_ok(1);
FPU_get_user(byte, ip);
RE_ENTRANT_CHECK_ON;
break;
@@ -686,7 +686,7 @@ int restore_i387_soft(void *s387, struct _fpstate __user *buf)
int offset, other, i, tags, regnr, tag, newtop;
RE_ENTRANT_CHECK_OFF;
- FPU_verify_area(VERIFY_READ, d, 7*4 + 8*10);
+ FPU_access_ok(VERIFY_READ, d, 7*4 + 8*10);
if (__copy_from_user(&S387->cwd, d, 7*4))
return -1;
RE_ENTRANT_CHECK_ON;
@@ -732,7 +732,7 @@ int save_i387_soft(void *s387, struct _fpstate __user * buf)
int offset = (S387->ftop & 7) * 10, other = 80 - offset;
RE_ENTRANT_CHECK_OFF;
- FPU_verify_area(VERIFY_WRITE, d, 7*4 + 8*10);
+ FPU_access_ok(VERIFY_WRITE, d, 7*4 + 8*10);
#ifdef PECULIAR_486
S387->cwd &= ~0xe080;
/* An 80486 sets nearly all of the reserved bits to 1. */
diff --git a/arch/i386/math-emu/fpu_proto.h b/arch/i386/math-emu/fpu_proto.h
index a9fe07c9b554d..37a8a7fe7e2b1 100644
--- a/arch/i386/math-emu/fpu_proto.h
+++ b/arch/i386/math-emu/fpu_proto.h
@@ -2,7 +2,6 @@
#define _FPU_PROTO_H
/* errors.c */
-extern void Un_impl(void);
extern void FPU_illegal(void);
extern void FPU_printall(void);
asmlinkage void FPU_exception(int n);
@@ -41,7 +40,6 @@ extern void fsubp_(void);
extern void fdivrp(void);
extern void fdivp_(void);
/* fpu_aux.c */
-extern void fclex(void);
extern void finit(void);
extern void finit_(void);
extern void fstsw_(void);
diff --git a/arch/i386/math-emu/fpu_system.h b/arch/i386/math-emu/fpu_system.h
index 2ddfe120b2885..bf26341c8bdea 100644
--- a/arch/i386/math-emu/fpu_system.h
+++ b/arch/i386/math-emu/fpu_system.h
@@ -66,21 +66,21 @@
#define instruction_address (*(struct address *)&I387.soft.fip)
#define operand_address (*(struct address *)&I387.soft.foo)
-#define FPU_verify_area(x,y,z) if ( verify_area(x,y,z) ) \
+#define FPU_access_ok(x,y,z) if ( !access_ok(x,y,z) ) \
math_abort(FPU_info,SIGSEGV)
#undef FPU_IGNORE_CODE_SEGV
#ifdef FPU_IGNORE_CODE_SEGV
-/* verify_area() is very expensive, and causes the emulator to run
+/* access_ok() is very expensive, and causes the emulator to run
about 20% slower if applied to the code. Anyway, errors due to bad
code addresses should be much rarer than errors due to bad data
addresses. */
-#define FPU_code_verify_area(z)
+#define FPU_code_access_ok(z)
#else
-/* A simpler test than verify_area() can probably be done for
- FPU_code_verify_area() because the only possible error is to step
+/* A simpler test than access_ok() can probably be done for
+ FPU_code_access_ok() because the only possible error is to step
past the upper boundary of a legal code area. */
-#define FPU_code_verify_area(z) FPU_verify_area(VERIFY_READ,(void __user *)FPU_EIP,z)
+#define FPU_code_access_ok(z) FPU_access_ok(VERIFY_READ,(void __user *)FPU_EIP,z)
#endif
#define FPU_get_user(x,y) get_user((x),(y))
diff --git a/arch/i386/math-emu/get_address.c b/arch/i386/math-emu/get_address.c
index 59eee72186ec2..91175738e9480 100644
--- a/arch/i386/math-emu/get_address.c
+++ b/arch/i386/math-emu/get_address.c
@@ -81,7 +81,7 @@ static int sib(int mod, unsigned long *fpu_eip)
long offset;
RE_ENTRANT_CHECK_OFF;
- FPU_code_verify_area(1);
+ FPU_code_access_ok(1);
FPU_get_user(base, (u_char __user *) (*fpu_eip)); /* The SIB byte */
RE_ENTRANT_CHECK_ON;
(*fpu_eip)++;
@@ -111,7 +111,7 @@ static int sib(int mod, unsigned long *fpu_eip)
/* 8 bit signed displacement */
long displacement;
RE_ENTRANT_CHECK_OFF;
- FPU_code_verify_area(1);
+ FPU_code_access_ok(1);
FPU_get_user(displacement, (signed char __user *) (*fpu_eip));
offset += displacement;
RE_ENTRANT_CHECK_ON;
@@ -122,7 +122,7 @@ static int sib(int mod, unsigned long *fpu_eip)
/* 32 bit displacement */
long displacement;
RE_ENTRANT_CHECK_OFF;
- FPU_code_verify_area(4);
+ FPU_code_access_ok(4);
FPU_get_user(displacement, (long __user *) (*fpu_eip));
offset += displacement;
RE_ENTRANT_CHECK_ON;
@@ -276,7 +276,7 @@ void __user *FPU_get_address(u_char FPU_modrm, unsigned long *fpu_eip,
{
/* Special case: disp32 */
RE_ENTRANT_CHECK_OFF;
- FPU_code_verify_area(4);
+ FPU_code_access_ok(4);
FPU_get_user(address, (unsigned long __user *) (*fpu_eip));
(*fpu_eip) += 4;
RE_ENTRANT_CHECK_ON;
@@ -293,7 +293,7 @@ void __user *FPU_get_address(u_char FPU_modrm, unsigned long *fpu_eip,
case 1:
/* 8 bit signed displacement */
RE_ENTRANT_CHECK_OFF;
- FPU_code_verify_area(1);
+ FPU_code_access_ok(1);
FPU_get_user(address, (signed char __user *) (*fpu_eip));
RE_ENTRANT_CHECK_ON;
(*fpu_eip)++;
@@ -301,7 +301,7 @@ void __user *FPU_get_address(u_char FPU_modrm, unsigned long *fpu_eip,
case 2:
/* 32 bit displacement */
RE_ENTRANT_CHECK_OFF;
- FPU_code_verify_area(4);
+ FPU_code_access_ok(4);
FPU_get_user(address, (long __user *) (*fpu_eip));
(*fpu_eip) += 4;
RE_ENTRANT_CHECK_ON;
@@ -362,7 +362,7 @@ void __user *FPU_get_address_16(u_char FPU_modrm, unsigned long *fpu_eip,
{
/* Special case: disp16 */
RE_ENTRANT_CHECK_OFF;
- FPU_code_verify_area(2);
+ FPU_code_access_ok(2);
FPU_get_user(address, (unsigned short __user *) (*fpu_eip));
(*fpu_eip) += 2;
RE_ENTRANT_CHECK_ON;
@@ -372,7 +372,7 @@ void __user *FPU_get_address_16(u_char FPU_modrm, unsigned long *fpu_eip,
case 1:
/* 8 bit signed displacement */
RE_ENTRANT_CHECK_OFF;
- FPU_code_verify_area(1);
+ FPU_code_access_ok(1);
FPU_get_user(address, (signed char __user *) (*fpu_eip));
RE_ENTRANT_CHECK_ON;
(*fpu_eip)++;
@@ -380,7 +380,7 @@ void __user *FPU_get_address_16(u_char FPU_modrm, unsigned long *fpu_eip,
case 2:
/* 16 bit displacement */
RE_ENTRANT_CHECK_OFF;
- FPU_code_verify_area(2);
+ FPU_code_access_ok(2);
FPU_get_user(address, (unsigned short __user *) (*fpu_eip));
(*fpu_eip) += 2;
RE_ENTRANT_CHECK_ON;
diff --git a/arch/i386/math-emu/load_store.c b/arch/i386/math-emu/load_store.c
index ff3a61766f0fd..85314be2fef8d 100644
--- a/arch/i386/math-emu/load_store.c
+++ b/arch/i386/math-emu/load_store.c
@@ -53,7 +53,7 @@ u_char const data_sizes_16[32] = {
14, 0, 94, 10, 2, 10, 2, 8
};
-u_char const data_sizes_32[32] = {
+static u_char const data_sizes_32[32] = {
4, 4, 8, 2, 0, 0, 0, 0,
4, 4, 8, 2, 4, 4, 8, 2,
28, 0,108, 10, 2, 10, 0, 8,
@@ -208,7 +208,7 @@ int FPU_load_store(u_char type, fpu_addr_modes addr_modes,
break;
case 024: /* fldcw */
RE_ENTRANT_CHECK_OFF;
- FPU_verify_area(VERIFY_READ, data_address, 2);
+ FPU_access_ok(VERIFY_READ, data_address, 2);
FPU_get_user(control_word, (unsigned short __user *) data_address);
RE_ENTRANT_CHECK_ON;
if ( partial_status & ~control_word & CW_Exceptions )
@@ -243,7 +243,7 @@ int FPU_load_store(u_char type, fpu_addr_modes addr_modes,
break;
case 034: /* fstcw m16int */
RE_ENTRANT_CHECK_OFF;
- FPU_verify_area(VERIFY_WRITE,data_address,2);
+ FPU_access_ok(VERIFY_WRITE,data_address,2);
FPU_put_user(control_word, (unsigned short __user *) data_address);
RE_ENTRANT_CHECK_ON;
return 1;
@@ -255,7 +255,7 @@ int FPU_load_store(u_char type, fpu_addr_modes addr_modes,
break;
case 036: /* fstsw m2byte */
RE_ENTRANT_CHECK_OFF;
- FPU_verify_area(VERIFY_WRITE,data_address,2);
+ FPU_access_ok(VERIFY_WRITE,data_address,2);
FPU_put_user(status_word(),(unsigned short __user *) data_address);
RE_ENTRANT_CHECK_ON;
return 1;
diff --git a/arch/i386/math-emu/reg_constant.c b/arch/i386/math-emu/reg_constant.c
index ffbfebd5186c4..a85015801969c 100644
--- a/arch/i386/math-emu/reg_constant.c
+++ b/arch/i386/math-emu/reg_constant.c
@@ -21,15 +21,17 @@
((EXTENDED_Ebias+(e)) | ((SIGN_##s != 0)*0x8000)) }
FPU_REG const CONST_1 = MAKE_REG(POS, 0, 0x00000000, 0x80000000);
+#if 0
FPU_REG const CONST_2 = MAKE_REG(POS, 1, 0x00000000, 0x80000000);
FPU_REG const CONST_HALF = MAKE_REG(POS, -1, 0x00000000, 0x80000000);
-FPU_REG const CONST_L2T = MAKE_REG(POS, 1, 0xcd1b8afe, 0xd49a784b);
-FPU_REG const CONST_L2E = MAKE_REG(POS, 0, 0x5c17f0bc, 0xb8aa3b29);
+#endif /* 0 */
+static FPU_REG const CONST_L2T = MAKE_REG(POS, 1, 0xcd1b8afe, 0xd49a784b);
+static FPU_REG const CONST_L2E = MAKE_REG(POS, 0, 0x5c17f0bc, 0xb8aa3b29);
FPU_REG const CONST_PI = MAKE_REG(POS, 1, 0x2168c235, 0xc90fdaa2);
FPU_REG const CONST_PI2 = MAKE_REG(POS, 0, 0x2168c235, 0xc90fdaa2);
FPU_REG const CONST_PI4 = MAKE_REG(POS, -1, 0x2168c235, 0xc90fdaa2);
-FPU_REG const CONST_LG2 = MAKE_REG(POS, -2, 0xfbcff799, 0x9a209a84);
-FPU_REG const CONST_LN2 = MAKE_REG(POS, -1, 0xd1cf79ac, 0xb17217f7);
+static FPU_REG const CONST_LG2 = MAKE_REG(POS, -2, 0xfbcff799, 0x9a209a84);
+static FPU_REG const CONST_LN2 = MAKE_REG(POS, -1, 0xd1cf79ac, 0xb17217f7);
/* Extra bits to take pi/2 to more than 128 bits precision. */
FPU_REG const CONST_PI2extra = MAKE_REG(NEG, -66,
diff --git a/arch/i386/math-emu/reg_constant.h b/arch/i386/math-emu/reg_constant.h
index 09f13f777478a..1bffaec3a1341 100644
--- a/arch/i386/math-emu/reg_constant.h
+++ b/arch/i386/math-emu/reg_constant.h
@@ -12,16 +12,10 @@
#include "fpu_emu.h"
extern FPU_REG const CONST_1;
-extern FPU_REG const CONST_2;
-extern FPU_REG const CONST_HALF;
-extern FPU_REG const CONST_L2T;
-extern FPU_REG const CONST_L2E;
extern FPU_REG const CONST_PI;
extern FPU_REG const CONST_PI2;
extern FPU_REG const CONST_PI2extra;
extern FPU_REG const CONST_PI4;
-extern FPU_REG const CONST_LG2;
-extern FPU_REG const CONST_LN2;
extern FPU_REG const CONST_Z;
extern FPU_REG const CONST_PINF;
extern FPU_REG const CONST_INF;
diff --git a/arch/i386/math-emu/reg_ld_str.c b/arch/i386/math-emu/reg_ld_str.c
index 699fe331c6d37..f06ed41d191d5 100644
--- a/arch/i386/math-emu/reg_ld_str.c
+++ b/arch/i386/math-emu/reg_ld_str.c
@@ -91,7 +91,7 @@ int FPU_load_extended(long double __user *s, int stnr)
FPU_REG *sti_ptr = &st(stnr);
RE_ENTRANT_CHECK_OFF;
- FPU_verify_area(VERIFY_READ, s, 10);
+ FPU_access_ok(VERIFY_READ, s, 10);
__copy_from_user(sti_ptr, s, 10);
RE_ENTRANT_CHECK_ON;
@@ -106,7 +106,7 @@ int FPU_load_double(double __user *dfloat, FPU_REG *loaded_data)
unsigned m64, l64;
RE_ENTRANT_CHECK_OFF;
- FPU_verify_area(VERIFY_READ, dfloat, 8);
+ FPU_access_ok(VERIFY_READ, dfloat, 8);
FPU_get_user(m64, 1 + (unsigned long __user *) dfloat);
FPU_get_user(l64, (unsigned long __user *) dfloat);
RE_ENTRANT_CHECK_ON;
@@ -178,7 +178,7 @@ int FPU_load_single(float __user *single, FPU_REG *loaded_data)
int exp, tag, negative;
RE_ENTRANT_CHECK_OFF;
- FPU_verify_area(VERIFY_READ, single, 4);
+ FPU_access_ok(VERIFY_READ, single, 4);
FPU_get_user(m32, (unsigned long __user *) single);
RE_ENTRANT_CHECK_ON;
@@ -243,7 +243,7 @@ int FPU_load_int64(long long __user *_s)
FPU_REG *st0_ptr = &st(0);
RE_ENTRANT_CHECK_OFF;
- FPU_verify_area(VERIFY_READ, _s, 8);
+ FPU_access_ok(VERIFY_READ, _s, 8);
copy_from_user(&s,_s,8);
RE_ENTRANT_CHECK_ON;
@@ -274,7 +274,7 @@ int FPU_load_int32(long __user *_s, FPU_REG *loaded_data)
int negative;
RE_ENTRANT_CHECK_OFF;
- FPU_verify_area(VERIFY_READ, _s, 4);
+ FPU_access_ok(VERIFY_READ, _s, 4);
FPU_get_user(s, _s);
RE_ENTRANT_CHECK_ON;
@@ -302,7 +302,7 @@ int FPU_load_int16(short __user *_s, FPU_REG *loaded_data)
int s, negative;
RE_ENTRANT_CHECK_OFF;
- FPU_verify_area(VERIFY_READ, _s, 2);
+ FPU_access_ok(VERIFY_READ, _s, 2);
/* Cast as short to get the sign extended. */
FPU_get_user(s, _s);
RE_ENTRANT_CHECK_ON;
@@ -335,7 +335,7 @@ int FPU_load_bcd(u_char __user *s)
int sign;
RE_ENTRANT_CHECK_OFF;
- FPU_verify_area(VERIFY_READ, s, 10);
+ FPU_access_ok(VERIFY_READ, s, 10);
RE_ENTRANT_CHECK_ON;
for ( pos = 8; pos >= 0; pos--)
{
@@ -380,7 +380,7 @@ int FPU_store_extended(FPU_REG *st0_ptr, u_char st0_tag, long double __user *d)
if ( st0_tag != TAG_Empty )
{
RE_ENTRANT_CHECK_OFF;
- FPU_verify_area(VERIFY_WRITE, d, 10);
+ FPU_access_ok(VERIFY_WRITE, d, 10);
FPU_put_user(st0_ptr->sigl, (unsigned long __user *) d);
FPU_put_user(st0_ptr->sigh, (unsigned long __user *) ((u_char __user *)d + 4));
@@ -397,7 +397,7 @@ int FPU_store_extended(FPU_REG *st0_ptr, u_char st0_tag, long double __user *d)
/* The masked response */
/* Put out the QNaN indefinite */
RE_ENTRANT_CHECK_OFF;
- FPU_verify_area(VERIFY_WRITE,d,10);
+ FPU_access_ok(VERIFY_WRITE,d,10);
FPU_put_user(0, (unsigned long __user *) d);
FPU_put_user(0xc0000000, 1 + (unsigned long __user *) d);
FPU_put_user(0xffff, 4 + (short __user *) d);
@@ -607,7 +607,7 @@ int FPU_store_double(FPU_REG *st0_ptr, u_char st0_tag, double __user *dfloat)
/* The masked response */
/* Put out the QNaN indefinite */
RE_ENTRANT_CHECK_OFF;
- FPU_verify_area(VERIFY_WRITE,dfloat,8);
+ FPU_access_ok(VERIFY_WRITE,dfloat,8);
FPU_put_user(0, (unsigned long __user *) dfloat);
FPU_put_user(0xfff80000, 1 + (unsigned long __user *) dfloat);
RE_ENTRANT_CHECK_ON;
@@ -620,7 +620,7 @@ int FPU_store_double(FPU_REG *st0_ptr, u_char st0_tag, double __user *dfloat)
l[1] |= 0x80000000;
RE_ENTRANT_CHECK_OFF;
- FPU_verify_area(VERIFY_WRITE,dfloat,8);
+ FPU_access_ok(VERIFY_WRITE,dfloat,8);
FPU_put_user(l[0], (unsigned long __user *)dfloat);
FPU_put_user(l[1], 1 + (unsigned long __user *)dfloat);
RE_ENTRANT_CHECK_ON;
@@ -826,7 +826,7 @@ int FPU_store_single(FPU_REG *st0_ptr, u_char st0_tag, float __user *single)
/* The masked response */
/* Put out the QNaN indefinite */
RE_ENTRANT_CHECK_OFF;
- FPU_verify_area(VERIFY_WRITE,single,4);
+ FPU_access_ok(VERIFY_WRITE,single,4);
FPU_put_user(0xffc00000, (unsigned long __user *) single);
RE_ENTRANT_CHECK_ON;
return 1;
@@ -845,7 +845,7 @@ int FPU_store_single(FPU_REG *st0_ptr, u_char st0_tag, float __user *single)
templ |= 0x80000000;
RE_ENTRANT_CHECK_OFF;
- FPU_verify_area(VERIFY_WRITE,single,4);
+ FPU_access_ok(VERIFY_WRITE,single,4);
FPU_put_user(templ,(unsigned long __user *) single);
RE_ENTRANT_CHECK_ON;
@@ -906,7 +906,7 @@ int FPU_store_int64(FPU_REG *st0_ptr, u_char st0_tag, long long __user *d)
}
RE_ENTRANT_CHECK_OFF;
- FPU_verify_area(VERIFY_WRITE,d,8);
+ FPU_access_ok(VERIFY_WRITE,d,8);
copy_to_user(d, &tll, 8);
RE_ENTRANT_CHECK_ON;
@@ -963,7 +963,7 @@ int FPU_store_int32(FPU_REG *st0_ptr, u_char st0_tag, long __user *d)
}
RE_ENTRANT_CHECK_OFF;
- FPU_verify_area(VERIFY_WRITE,d,4);
+ FPU_access_ok(VERIFY_WRITE,d,4);
FPU_put_user(t.sigl, (unsigned long __user *) d);
RE_ENTRANT_CHECK_ON;
@@ -1020,7 +1020,7 @@ int FPU_store_int16(FPU_REG *st0_ptr, u_char st0_tag, short __user *d)
}
RE_ENTRANT_CHECK_OFF;
- FPU_verify_area(VERIFY_WRITE,d,2);
+ FPU_access_ok(VERIFY_WRITE,d,2);
FPU_put_user((short)t.sigl, d);
RE_ENTRANT_CHECK_ON;
@@ -1069,7 +1069,7 @@ int FPU_store_bcd(FPU_REG *st0_ptr, u_char st0_tag, u_char __user *d)
{
/* Produce the QNaN "indefinite" */
RE_ENTRANT_CHECK_OFF;
- FPU_verify_area(VERIFY_WRITE,d,10);
+ FPU_access_ok(VERIFY_WRITE,d,10);
for ( i = 0; i < 7; i++)
FPU_put_user(0, d+i); /* These bytes "undefined" */
FPU_put_user(0xc0, d+7); /* This byte "undefined" */
@@ -1088,7 +1088,7 @@ int FPU_store_bcd(FPU_REG *st0_ptr, u_char st0_tag, u_char __user *d)
}
RE_ENTRANT_CHECK_OFF;
- FPU_verify_area(VERIFY_WRITE,d,10);
+ FPU_access_ok(VERIFY_WRITE,d,10);
RE_ENTRANT_CHECK_ON;
for ( i = 0; i < 9; i++)
{
@@ -1186,7 +1186,7 @@ u_char __user *fldenv(fpu_addr_modes addr_modes, u_char __user *s)
^ (addr_modes.override.operand_size == OP_SIZE_PREFIX)) )
{
RE_ENTRANT_CHECK_OFF;
- FPU_verify_area(VERIFY_READ, s, 0x0e);
+ FPU_access_ok(VERIFY_READ, s, 0x0e);
FPU_get_user(control_word, (unsigned short __user *) s);
FPU_get_user(partial_status, (unsigned short __user *) (s+2));
FPU_get_user(tag_word, (unsigned short __user *) (s+4));
@@ -1206,7 +1206,7 @@ u_char __user *fldenv(fpu_addr_modes addr_modes, u_char __user *s)
else
{
RE_ENTRANT_CHECK_OFF;
- FPU_verify_area(VERIFY_READ, s, 0x1c);
+ FPU_access_ok(VERIFY_READ, s, 0x1c);
FPU_get_user(control_word, (unsigned short __user *) s);
FPU_get_user(partial_status, (unsigned short __user *) (s+4));
FPU_get_user(tag_word, (unsigned short __user *) (s+8));
@@ -1274,7 +1274,7 @@ void frstor(fpu_addr_modes addr_modes, u_char __user *data_address)
/* Copy all registers in stack order. */
RE_ENTRANT_CHECK_OFF;
- FPU_verify_area(VERIFY_READ,s,80);
+ FPU_access_ok(VERIFY_READ,s,80);
__copy_from_user(register_base+offset, s, other);
if ( offset )
__copy_from_user(register_base, s+other, offset);
@@ -1298,7 +1298,7 @@ u_char __user *fstenv(fpu_addr_modes addr_modes, u_char __user *d)
^ (addr_modes.override.operand_size == OP_SIZE_PREFIX)) )
{
RE_ENTRANT_CHECK_OFF;
- FPU_verify_area(VERIFY_WRITE,d,14);
+ FPU_access_ok(VERIFY_WRITE,d,14);
#ifdef PECULIAR_486
FPU_put_user(control_word & ~0xe080, (unsigned long __user *) d);
#else
@@ -1326,7 +1326,7 @@ u_char __user *fstenv(fpu_addr_modes addr_modes, u_char __user *d)
else
{
RE_ENTRANT_CHECK_OFF;
- FPU_verify_area(VERIFY_WRITE, d, 7*4);
+ FPU_access_ok(VERIFY_WRITE, d, 7*4);
#ifdef PECULIAR_486
control_word &= ~0xe080;
/* An 80486 sets nearly all of the reserved bits to 1. */
@@ -1356,7 +1356,7 @@ void fsave(fpu_addr_modes addr_modes, u_char __user *data_address)
d = fstenv(addr_modes, data_address);
RE_ENTRANT_CHECK_OFF;
- FPU_verify_area(VERIFY_WRITE,d,80);
+ FPU_access_ok(VERIFY_WRITE,d,80);
/* Copy all registers in stack order. */
__copy_to_user(d, register_base+offset, other);
diff --git a/arch/i386/mm/boot_ioremap.c b/arch/i386/mm/boot_ioremap.c
index d879c1aa90a2d..523b30634e0a8 100644
--- a/arch/i386/mm/boot_ioremap.c
+++ b/arch/i386/mm/boot_ioremap.c
@@ -61,8 +61,8 @@ static void __boot_ioremap(unsigned long phys_addr, unsigned long nrpages,
/* the virtual space we're going to remap comes from this array */
#define BOOT_IOREMAP_PAGES 4
#define BOOT_IOREMAP_SIZE (BOOT_IOREMAP_PAGES*PAGE_SIZE)
-__initdata char boot_ioremap_space[BOOT_IOREMAP_SIZE]
- __attribute__ ((aligned (PAGE_SIZE)));
+static __initdata char boot_ioremap_space[BOOT_IOREMAP_SIZE]
+ __attribute__ ((aligned (PAGE_SIZE)));
/*
* This only applies to things which need to ioremap before paging_init()
diff --git a/arch/i386/mm/discontig.c b/arch/i386/mm/discontig.c
index 2b535d2c97dac..1726b4096b107 100644
--- a/arch/i386/mm/discontig.c
+++ b/arch/i386/mm/discontig.c
@@ -60,6 +60,32 @@ bootmem_data_t node0_bdata;
*/
s8 physnode_map[MAX_ELEMENTS] = { [0 ... (MAX_ELEMENTS - 1)] = -1};
+void memory_present(int nid, unsigned long start, unsigned long end)
+{
+ unsigned long pfn;
+
+ printk(KERN_INFO "Node: %d, start_pfn: %ld, end_pfn: %ld\n",
+ nid, start, end);
+ printk(KERN_DEBUG " Setting physnode_map array to node %d for pfns:\n", nid);
+ printk(KERN_DEBUG " ");
+ for (pfn = start; pfn < end; pfn += PAGES_PER_ELEMENT) {
+ physnode_map[pfn / PAGES_PER_ELEMENT] = nid;
+ printk("%ld ", pfn);
+ }
+ printk("\n");
+}
+
+unsigned long node_memmap_size_bytes(int nid, unsigned long start_pfn,
+ unsigned long end_pfn)
+{
+ unsigned long nr_pages = end_pfn - start_pfn;
+
+ if (!nr_pages)
+ return 0;
+
+ return (nr_pages + 1) * sizeof(struct page);
+}
+
unsigned long node_start_pfn[MAX_NUMNODES];
unsigned long node_end_pfn[MAX_NUMNODES];
@@ -95,6 +121,7 @@ int __init get_memcfg_numa_flat(void)
find_max_pfn();
node_start_pfn[0] = 0;
node_end_pfn[0] = max_pfn;
+ memory_present(0, 0, max_pfn);
/* Indicate there is one node available. */
nodes_clear(node_online_map);
@@ -128,52 +155,11 @@ static void __init find_max_pfn_node(int nid)
*/
static void __init allocate_pgdat(int nid)
{
- if (nid)
+ if (nid && node_has_online_mem(nid))
NODE_DATA(nid) = (pg_data_t *)node_remap_start_vaddr[nid];
else {
NODE_DATA(nid) = (pg_data_t *)(__va(min_low_pfn << PAGE_SHIFT));
min_low_pfn += PFN_UP(sizeof(pg_data_t));
- memset(NODE_DATA(nid), 0, sizeof(pg_data_t));
- }
-}
-
-/*
- * Register fully available low RAM pages with the bootmem allocator.
- */
-static void __init register_bootmem_low_pages(unsigned long system_max_low_pfn)
-{
- int i;
-
- for (i = 0; i < e820.nr_map; i++) {
- unsigned long curr_pfn, last_pfn, size;
- /*
- * Reserve usable low memory
- */
- if (e820.map[i].type != E820_RAM)
- continue;
- /*
- * We are rounding up the start address of usable memory:
- */
- curr_pfn = PFN_UP(e820.map[i].addr);
- if (curr_pfn >= system_max_low_pfn)
- continue;
- /*
- * ... and at the end of the usable range downwards:
- */
- last_pfn = PFN_DOWN(e820.map[i].addr + e820.map[i].size);
-
- if (last_pfn > system_max_low_pfn)
- last_pfn = system_max_low_pfn;
-
- /*
- * .. finally, did all the rounding and playing
- * around just make the area go away?
- */
- if (last_pfn <= curr_pfn)
- continue;
-
- size = last_pfn - curr_pfn;
- free_bootmem_node(NODE_DATA(0), PFN_PHYS(curr_pfn), PFN_PHYS(size));
}
}
@@ -203,9 +189,21 @@ static unsigned long calculate_numa_remap_pages(void)
for_each_online_node(nid) {
if (nid == 0)
continue;
- /* calculate the size of the mem_map needed in bytes */
- size = (node_end_pfn[nid] - node_start_pfn[nid] + 1)
- * sizeof(struct page) + sizeof(pg_data_t);
+ if (!node_remap_size[nid])
+ continue;
+
+ /*
+ * The acpi/srat node info can show hot-add memroy zones
+ * where memory could be added but not currently present.
+ */
+ if (node_start_pfn[nid] > max_pfn)
+ continue;
+ if (node_end_pfn[nid] > max_pfn)
+ node_end_pfn[nid] = max_pfn;
+
+ /* ensure the remap includes space for the pgdat. */
+ size = node_remap_size[nid] + sizeof(pg_data_t);
+
/* convert size to large (pmd size) pages, rounding up */
size = (size + LARGE_PAGE_BYTES - 1) / LARGE_PAGE_BYTES;
/* now the roundup is correct, convert to PAGE_SIZE pages */
@@ -225,22 +223,12 @@ static unsigned long calculate_numa_remap_pages(void)
return reserve_pages;
}
-/*
- * workaround for Dell systems that neglect to reserve EBDA
- */
-static void __init reserve_ebda_region_node(void)
-{
- unsigned int addr;
- addr = get_bios_ebda();
- if (addr)
- reserve_bootmem_node(NODE_DATA(0), addr, PAGE_SIZE);
-}
-
+extern void setup_bootmem_allocator(void);
unsigned long __init setup_memory(void)
{
int nid;
- unsigned long bootmap_size, system_start_pfn, system_max_low_pfn;
- unsigned long reserve_pages, pfn;
+ unsigned long system_start_pfn, system_max_low_pfn;
+ unsigned long reserve_pages;
/*
* When mapping a NUMA machine we allocate the node_mem_map arrays
@@ -249,28 +237,14 @@ unsigned long __init setup_memory(void)
* this space and use it to adjust the boundry between ZONE_NORMAL
* and ZONE_HIGHMEM.
*/
+ find_max_pfn();
get_memcfg_numa();
- /* Fill in the physnode_map */
- for_each_online_node(nid) {
- printk("Node: %d, start_pfn: %ld, end_pfn: %ld\n",
- nid, node_start_pfn[nid], node_end_pfn[nid]);
- printk(" Setting physnode_map array to node %d for pfns:\n ",
- nid);
- for (pfn = node_start_pfn[nid]; pfn < node_end_pfn[nid];
- pfn += PAGES_PER_ELEMENT) {
- physnode_map[pfn / PAGES_PER_ELEMENT] = nid;
- printk("%ld ", pfn);
- }
- printk("\n");
- }
-
reserve_pages = calculate_numa_remap_pages();
/* partially used pages are not usable - thus round upwards */
system_start_pfn = min_low_pfn = PFN_UP(init_pg_tables_end);
- find_max_pfn();
system_max_low_pfn = max_low_pfn = find_max_low_pfn() - reserve_pages;
printk("reserve_pages = %ld find_max_low_pfn() ~ %ld\n",
reserve_pages, max_low_pfn + reserve_pages);
@@ -304,70 +278,10 @@ unsigned long __init setup_memory(void)
for_each_online_node(nid)
find_max_pfn_node(nid);
+ memset(NODE_DATA(0), 0, sizeof(struct pglist_data));
NODE_DATA(0)->bdata = &node0_bdata;
-
- /*
- * Initialize the boot-time allocator (with low memory only):
- */
- bootmap_size = init_bootmem_node(NODE_DATA(0), min_low_pfn, 0, system_max_low_pfn);
-
- register_bootmem_low_pages(system_max_low_pfn);
-
- /*
- * Reserve the bootmem bitmap itself as well. We do this in two
- * steps (first step was init_bootmem()) because this catches
- * the (very unlikely) case of us accidentally initializing the
- * bootmem allocator with an invalid RAM area.
- */
- reserve_bootmem_node(NODE_DATA(0), HIGH_MEMORY, (PFN_PHYS(min_low_pfn) +
- bootmap_size + PAGE_SIZE-1) - (HIGH_MEMORY));
-
- /*
- * reserve physical page 0 - it's a special BIOS page on many boxes,
- * enabling clean reboots, SMP operation, laptop functions.
- */
- reserve_bootmem_node(NODE_DATA(0), 0, PAGE_SIZE);
-
- /*
- * But first pinch a few for the stack/trampoline stuff
- * FIXME: Don't need the extra page at 4K, but need to fix
- * trampoline before removing it. (see the GDT stuff)
- */
- reserve_bootmem_node(NODE_DATA(0), PAGE_SIZE, PAGE_SIZE);
-
- /* reserve EBDA region, it's a 4K region */
- reserve_ebda_region_node();
-
-#ifdef CONFIG_ACPI_SLEEP
- /*
- * Reserve low memory region for sleep support.
- */
- acpi_reserve_bootmem();
-#endif
-
- /*
- * Find and reserve possible boot-time SMP configuration:
- */
- find_smp_config();
-
-#ifdef CONFIG_BLK_DEV_INITRD
- if (LOADER_TYPE && INITRD_START) {
- if (INITRD_START + INITRD_SIZE <= (system_max_low_pfn << PAGE_SHIFT)) {
- reserve_bootmem_node(NODE_DATA(0), INITRD_START, INITRD_SIZE);
- initrd_start =
- INITRD_START ? INITRD_START + PAGE_OFFSET : 0;
- initrd_end = initrd_start+INITRD_SIZE;
- }
- else {
- printk(KERN_ERR "initrd extends beyond end of memory "
- "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
- INITRD_START + INITRD_SIZE,
- system_max_low_pfn << PAGE_SHIFT);
- initrd_start = 0;
- }
- }
-#endif
- return system_max_low_pfn;
+ setup_bootmem_allocator();
+ return max_low_pfn;
}
void __init zone_sizes_init(void)
@@ -382,8 +296,6 @@ void __init zone_sizes_init(void)
for (nid = MAX_NUMNODES - 1; nid >= 0; nid--) {
if (!node_online(nid))
continue;
- if (nid)
- memset(NODE_DATA(nid), 0, sizeof(pg_data_t));
NODE_DATA(nid)->pgdat_next = pgdat_list;
pgdat_list = NODE_DATA(nid);
}
@@ -399,24 +311,27 @@ void __init zone_sizes_init(void)
max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
- if (start > low) {
+ if (node_has_online_mem(nid)){
+ if (start > low) {
#ifdef CONFIG_HIGHMEM
- BUG_ON(start > high);
- zones_size[ZONE_HIGHMEM] = high - start;
+ BUG_ON(start > high);
+ zones_size[ZONE_HIGHMEM] = high - start;
#endif
- } else {
- if (low < max_dma)
- zones_size[ZONE_DMA] = low;
- else {
- BUG_ON(max_dma > low);
- BUG_ON(low > high);
- zones_size[ZONE_DMA] = max_dma;
- zones_size[ZONE_NORMAL] = low - max_dma;
+ } else {
+ if (low < max_dma)
+ zones_size[ZONE_DMA] = low;
+ else {
+ BUG_ON(max_dma > low);
+ BUG_ON(low > high);
+ zones_size[ZONE_DMA] = max_dma;
+ zones_size[ZONE_NORMAL] = low - max_dma;
#ifdef CONFIG_HIGHMEM
- zones_size[ZONE_HIGHMEM] = high - low;
+ zones_size[ZONE_HIGHMEM] = high - low;
#endif
+ }
}
}
+
zholes_size = get_zholes_size(nid);
/*
* We let the lmem_map for node 0 be allocated from the
@@ -466,12 +381,3 @@ void __init set_highmem_pages_init(int bad_ppro)
totalram_pages += totalhigh_pages;
#endif
}
-
-void __init set_max_mapnr_init(void)
-{
-#ifdef CONFIG_HIGHMEM
- num_physpages = highend_pfn;
-#else
- num_physpages = max_low_pfn;
-#endif
-}
diff --git a/arch/i386/mm/highmem.c b/arch/i386/mm/highmem.c
index 2216986101212..fc4c4cad4e98e 100644
--- a/arch/i386/mm/highmem.c
+++ b/arch/i386/mm/highmem.c
@@ -66,7 +66,7 @@ void kunmap_atomic(void *kvaddr, enum km_type type)
* force other mappings to Oops if they'll try to access
* this pte without first remap it
*/
- pte_clear(kmap_pte-idx);
+ pte_clear(&init_mm, vaddr, kmap_pte-idx);
__flush_tlb_one(vaddr);
#endif
diff --git a/arch/i386/mm/hugetlbpage.c b/arch/i386/mm/hugetlbpage.c
index 74516dabf6292..a8c45143088b7 100644
--- a/arch/i386/mm/hugetlbpage.c
+++ b/arch/i386/mm/hugetlbpage.c
@@ -46,7 +46,7 @@ static void set_huge_pte(struct mm_struct *mm, struct vm_area_struct *vma, struc
{
pte_t entry;
- mm->rss += (HPAGE_SIZE / PAGE_SIZE);
+ add_mm_counter(mm, rss, HPAGE_SIZE / PAGE_SIZE);
if (write_access) {
entry =
pte_mkwrite(pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
@@ -86,7 +86,7 @@ int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src,
ptepage = pte_page(entry);
get_page(ptepage);
set_pte(dst_pte, entry);
- dst->rss += (HPAGE_SIZE / PAGE_SIZE);
+ add_mm_counter(dst, rss, HPAGE_SIZE / PAGE_SIZE);
addr += HPAGE_SIZE;
}
return 0;
@@ -209,20 +209,23 @@ void unmap_hugepage_range(struct vm_area_struct *vma,
{
struct mm_struct *mm = vma->vm_mm;
unsigned long address;
- pte_t pte;
+ pte_t pte, *ptep;
struct page *page;
BUG_ON(start & (HPAGE_SIZE - 1));
BUG_ON(end & (HPAGE_SIZE - 1));
for (address = start; address < end; address += HPAGE_SIZE) {
- pte = ptep_get_and_clear(huge_pte_offset(mm, address));
+ ptep = huge_pte_offset(mm, address);
+ if (!ptep)
+ continue;
+ pte = ptep_get_and_clear(mm, address, ptep);
if (pte_none(pte))
continue;
page = pte_page(pte);
put_page(page);
}
- mm->rss -= (end - start) >> PAGE_SHIFT;
+ add_mm_counter(mm ,rss, -((end - start) >> PAGE_SHIFT));
flush_tlb_range(vma, start, end);
}
diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c
index fe4e6b7b677a6..7a7ea37372652 100644
--- a/arch/i386/mm/init.c
+++ b/arch/i386/mm/init.c
@@ -233,13 +233,10 @@ static inline int page_is_ram(unsigned long pagenr)
pte_t *kmap_pte;
pgprot_t kmap_prot;
-EXPORT_SYMBOL(kmap_prot);
-EXPORT_SYMBOL(kmap_pte);
-
#define kmap_get_fixmap_pte(vaddr) \
pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k(vaddr), vaddr), (vaddr)), (vaddr))
-void __init kmap_init(void)
+static void __init kmap_init(void)
{
unsigned long kmap_vstart;
@@ -250,7 +247,7 @@ void __init kmap_init(void)
kmap_prot = PAGE_KERNEL;
}
-void __init permanent_kmaps_init(pgd_t *pgd_base)
+static void __init permanent_kmaps_init(pgd_t *pgd_base)
{
pgd_t *pgd;
pud_t *pud;
@@ -281,7 +278,7 @@ void __init one_highpage_init(struct page *page, int pfn, int bad_ppro)
}
#ifndef CONFIG_DISCONTIGMEM
-void __init set_highmem_pages_init(int bad_ppro)
+static void __init set_highmem_pages_init(int bad_ppro)
{
int pfn;
for (pfn = highstart_pfn; pfn < highend_pfn; pfn++)
@@ -394,31 +391,6 @@ void zap_low_mappings (void)
flush_tlb_all();
}
-#ifndef CONFIG_DISCONTIGMEM
-void __init zone_sizes_init(void)
-{
- unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0};
- unsigned int max_dma, high, low;
-
- max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
- low = max_low_pfn;
- high = highend_pfn;
-
- if (low < max_dma)
- zones_size[ZONE_DMA] = low;
- else {
- zones_size[ZONE_DMA] = max_dma;
- zones_size[ZONE_NORMAL] = low - max_dma;
-#ifdef CONFIG_HIGHMEM
- zones_size[ZONE_HIGHMEM] = high - low;
-#endif
- }
- free_area_init(zones_size);
-}
-#else
-extern void zone_sizes_init(void);
-#endif /* !CONFIG_DISCONTIGMEM */
-
static int disable_nx __initdata = 0;
u64 __supported_pte_mask = ~_PAGE_NX;
@@ -519,7 +491,6 @@ void __init paging_init(void)
__flush_tlb_all();
kmap_init();
- zone_sizes_init();
}
/*
@@ -529,7 +500,7 @@ void __init paging_init(void)
* but fortunately the switch to using exceptions got rid of all that.
*/
-void __init test_wp_bit(void)
+static void __init test_wp_bit(void)
{
printk("Checking if this processor honours the WP bit even in supervisor mode... ");
@@ -548,20 +519,17 @@ void __init test_wp_bit(void)
}
}
-#ifndef CONFIG_DISCONTIGMEM
static void __init set_max_mapnr_init(void)
{
#ifdef CONFIG_HIGHMEM
- max_mapnr = num_physpages = highend_pfn;
+ num_physpages = highend_pfn;
#else
- max_mapnr = num_physpages = max_low_pfn;
+ num_physpages = max_low_pfn;
+#endif
+#ifndef CONFIG_DISCONTIGMEM
+ max_mapnr = num_physpages;
#endif
}
-#define __free_all_bootmem() free_all_bootmem()
-#else
-#define __free_all_bootmem() free_all_bootmem_node(NODE_DATA(0))
-extern void set_max_mapnr_init(void);
-#endif /* !CONFIG_DISCONTIGMEM */
static struct kcore_list kcore_mem, kcore_vmalloc;
@@ -592,13 +560,13 @@ void __init mem_init(void)
set_max_mapnr_init();
#ifdef CONFIG_HIGHMEM
- high_memory = (void *) __va(highstart_pfn * PAGE_SIZE);
+ high_memory = (void *) __va(highstart_pfn * PAGE_SIZE - 1) + 1;
#else
- high_memory = (void *) __va(max_low_pfn * PAGE_SIZE);
+ high_memory = (void *) __va(max_low_pfn * PAGE_SIZE - 1) + 1;
#endif
/* this will put all low memory onto the freelists */
- totalram_pages += __free_all_bootmem();
+ totalram_pages += free_all_bootmem();
reservedpages = 0;
for (tmp = 0; tmp < max_low_pfn; tmp++)
diff --git a/arch/i386/mm/ioremap.c b/arch/i386/mm/ioremap.c
index 907326772fff5..db06f7399913f 100644
--- a/arch/i386/mm/ioremap.c
+++ b/arch/i386/mm/ioremap.c
@@ -17,89 +17,85 @@
#include <asm/tlbflush.h>
#include <asm/pgtable.h>
-static inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned long size,
- unsigned long phys_addr, unsigned long flags)
+#define ISA_START_ADDRESS 0xa0000
+#define ISA_END_ADDRESS 0x100000
+
+static int ioremap_pte_range(pmd_t *pmd, unsigned long addr,
+ unsigned long end, unsigned long phys_addr, unsigned long flags)
{
- unsigned long end;
+ pte_t *pte;
unsigned long pfn;
- address &= ~PMD_MASK;
- end = address + size;
- if (end > PMD_SIZE)
- end = PMD_SIZE;
- if (address >= end)
- BUG();
pfn = phys_addr >> PAGE_SHIFT;
+ pte = pte_alloc_kernel(&init_mm, pmd, addr);
+ if (!pte)
+ return -ENOMEM;
do {
- if (!pte_none(*pte)) {
- printk("remap_area_pte: page already exists\n");
- BUG();
- }
+ BUG_ON(!pte_none(*pte));
set_pte(pte, pfn_pte(pfn, __pgprot(_PAGE_PRESENT | _PAGE_RW |
_PAGE_DIRTY | _PAGE_ACCESSED | flags)));
- address += PAGE_SIZE;
pfn++;
- pte++;
- } while (address && (address < end));
+ } while (pte++, addr += PAGE_SIZE, addr != end);
+ return 0;
}
-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 ioremap_pmd_range(pud_t *pud, unsigned long addr,
+ unsigned long end, unsigned long phys_addr, unsigned long flags)
{
- unsigned long end;
-
- address &= ~PGDIR_MASK;
- end = address + size;
- if (end > PGDIR_SIZE)
- end = PGDIR_SIZE;
- phys_addr -= address;
- if (address >= end)
- BUG();
+ pmd_t *pmd;
+ unsigned long next;
+
+ phys_addr -= addr;
+ pmd = pmd_alloc(&init_mm, pud, addr);
+ if (!pmd)
+ return -ENOMEM;
do {
- pte_t * pte = pte_alloc_kernel(&init_mm, pmd, address);
- if (!pte)
+ next = pmd_addr_end(addr, end);
+ if (ioremap_pte_range(pmd, addr, next, phys_addr + addr, flags))
return -ENOMEM;
- remap_area_pte(pte, address, end - address, address + phys_addr, flags);
- address = (address + PMD_SIZE) & PMD_MASK;
- pmd++;
- } while (address && (address < end));
+ } while (pmd++, addr = next, addr != end);
return 0;
}
-static int remap_area_pages(unsigned long address, unsigned long phys_addr,
- unsigned long size, unsigned long flags)
+static inline int ioremap_pud_range(pgd_t *pgd, unsigned long addr,
+ unsigned long end, unsigned long phys_addr, unsigned long flags)
{
- int error;
- pgd_t * dir;
- unsigned long end = address + size;
+ pud_t *pud;
+ unsigned long next;
+
+ phys_addr -= addr;
+ pud = pud_alloc(&init_mm, pgd, addr);
+ if (!pud)
+ return -ENOMEM;
+ do {
+ next = pud_addr_end(addr, end);
+ if (ioremap_pmd_range(pud, addr, next, phys_addr + addr, flags))
+ return -ENOMEM;
+ } while (pud++, addr = next, addr != end);
+ return 0;
+}
- phys_addr -= address;
- dir = pgd_offset(&init_mm, address);
+static int ioremap_page_range(unsigned long addr,
+ unsigned long end, unsigned long phys_addr, unsigned long flags)
+{
+ pgd_t *pgd;
+ unsigned long next;
+ int err;
+
+ BUG_ON(addr >= end);
flush_cache_all();
- if (address >= end)
- BUG();
+ phys_addr -= addr;
+ pgd = pgd_offset_k(addr);
spin_lock(&init_mm.page_table_lock);
do {
- pud_t *pud;
- pmd_t *pmd;
-
- 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))
+ next = pgd_addr_end(addr, end);
+ err = ioremap_pud_range(pgd, addr, next, phys_addr+addr, flags);
+ if (err)
break;
- error = 0;
- address = (address + PGDIR_SIZE) & PGDIR_MASK;
- dir++;
- } while (address && (address < end));
+ } while (pgd++, addr = next, addr != end);
spin_unlock(&init_mm.page_table_lock);
flush_tlb_all();
- return error;
+ return err;
}
/*
@@ -129,7 +125,7 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l
/*
* Don't remap the low PCI/ISA area, it's always mapped..
*/
- if (phys_addr >= 0xA0000 && last_addr < 0x100000)
+ if (phys_addr >= ISA_START_ADDRESS && last_addr < ISA_END_ADDRESS)
return (void __iomem *) phys_to_virt(phys_addr);
/*
@@ -162,7 +158,8 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l
return NULL;
area->phys_addr = phys_addr;
addr = (void __iomem *) area->addr;
- if (remap_area_pages((unsigned long) addr, phys_addr, size, flags)) {
+ if (ioremap_page_range((unsigned long) addr,
+ (unsigned long) addr + size, phys_addr, flags)) {
vunmap((void __force *) addr);
return NULL;
}
@@ -230,7 +227,17 @@ void iounmap(volatile void __iomem *addr)
{
struct vm_struct *p;
if ((void __force *) addr <= high_memory)
- return;
+ return;
+
+ /*
+ * __ioremap special-cases the PCI/ISA range by not instantiating a
+ * vm_area and by simply returning an address into the kernel mapping
+ * of ISA space. So handle that here.
+ */
+ if (addr >= phys_to_virt(ISA_START_ADDRESS) &&
+ addr < phys_to_virt(ISA_END_ADDRESS))
+ return;
+
p = remove_vm_area((void *) (PAGE_MASK & (unsigned long __force) addr));
if (!p) {
printk("__iounmap: bad address %p\n", addr);
@@ -240,8 +247,8 @@ void iounmap(volatile void __iomem *addr)
if ((p->flags >> 20) && p->phys_addr < virt_to_phys(high_memory) - 1) {
/* p->size includes the guard page, but cpa doesn't like that */
change_page_attr(virt_to_page(__va(p->phys_addr)),
- (p->size - PAGE_SIZE) >> PAGE_SHIFT,
- PAGE_KERNEL);
+ p->size >> PAGE_SHIFT,
+ PAGE_KERNEL);
global_flush_tlb();
}
kfree(p);
@@ -261,7 +268,7 @@ void __init *bt_ioremap(unsigned long phys_addr, unsigned long size)
/*
* Don't remap the low PCI/ISA area, it's always mapped..
*/
- if (phys_addr >= 0xA0000 && last_addr < 0x100000)
+ if (phys_addr >= ISA_START_ADDRESS && last_addr < ISA_END_ADDRESS)
return phys_to_virt(phys_addr);
/*
diff --git a/arch/i386/mm/mmap.c b/arch/i386/mm/mmap.c
index c5e0d0119a1ea..e4730a1a43dda 100644
--- a/arch/i386/mm/mmap.c
+++ b/arch/i386/mm/mmap.c
@@ -26,6 +26,7 @@
#include <linux/personality.h>
#include <linux/mm.h>
+#include <linux/random.h>
/*
* Top of mmap area (just below the process stack).
@@ -38,13 +39,17 @@
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 TASK_SIZE - (gap & PAGE_MASK);
+ return PAGE_ALIGN(TASK_SIZE - gap - random_factor);
}
/*
diff --git a/arch/i386/mm/pageattr.c b/arch/i386/mm/pageattr.c
index 862326f5dc38e..cb3da6baa7042 100644
--- a/arch/i386/mm/pageattr.c
+++ b/arch/i386/mm/pageattr.c
@@ -189,7 +189,7 @@ int change_page_attr(struct page *page, int numpages, pgprot_t prot)
void global_flush_tlb(void)
{
LIST_HEAD(l);
- struct list_head* n;
+ struct page *pg, *next;
BUG_ON(irqs_disabled());
@@ -197,12 +197,8 @@ void global_flush_tlb(void)
list_splice_init(&df_list, &l);
spin_unlock_irq(&cpa_lock);
flush_map();
- n = l.next;
- while (n != &l) {
- struct page *pg = list_entry(n, struct page, lru);
- n = n->next;
+ list_for_each_entry_safe(pg, next, &l, lru)
__free_page(pg);
- }
}
#ifdef CONFIG_DEBUG_PAGEALLOC
diff --git a/arch/i386/oprofile/backtrace.c b/arch/i386/oprofile/backtrace.c
index 49a06053f70f0..52d72e074f7f9 100644
--- a/arch/i386/oprofile/backtrace.c
+++ b/arch/i386/oprofile/backtrace.c
@@ -18,7 +18,6 @@ struct frame_head {
unsigned long ret;
} __attribute__((packed));
-
static struct frame_head *
dump_backtrace(struct frame_head * head)
{
@@ -27,21 +26,11 @@ dump_backtrace(struct frame_head * head)
/* frame pointers should strictly progress back up the stack
* (towards higher addresses) */
if (head >= head->ebp)
- return 0;
+ return NULL;
return head->ebp;
}
-
-#ifdef CONFIG_X86_4G
-/* With a 4G kernel/user split, user pages are not directly
- * accessible from the kernel, so don't try
- */
-static int pages_present(struct frame_head * head)
-{
- return 0;
-}
-#else
/* check that the page(s) containing the frame head are present */
static int pages_present(struct frame_head * head)
{
@@ -53,8 +42,6 @@ static int pages_present(struct frame_head * head)
return check_user_page_readable(mm, (unsigned long)(head + 1));
}
-#endif /* CONFIG_X86_4G */
-
/*
* | | /\ Higher addresses
diff --git a/arch/i386/pci/acpi.c b/arch/i386/pci/acpi.c
index 0c0a169723da8..2db65ec45dc35 100644
--- a/arch/i386/pci/acpi.c
+++ b/arch/i386/pci/acpi.c
@@ -37,21 +37,12 @@ static int __init pci_acpi_init(void)
* also do it here in case there are still broken drivers that
* don't use pci_enable_device().
*/
- printk(KERN_INFO "** Routing PCI interrupts for all devices because \"pci=routeirq\"\n");
- printk(KERN_INFO "** was specified. If this was required to make a driver work,\n");
- printk(KERN_INFO "** please email the output of \"lspci\" to bjorn.helgaas@hp.com\n");
- printk(KERN_INFO "** so I can fix the driver.\n");
+ 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)
acpi_pci_irq_enable(dev);
- } else {
- printk(KERN_INFO "** PCI interrupts are no longer routed automatically. If this\n");
- printk(KERN_INFO "** causes a device to stop working, it is probably because the\n");
- printk(KERN_INFO "** driver failed to call pci_enable_device(). As a temporary\n");
- printk(KERN_INFO "** workaround, the \"pci=routeirq\" argument restores the old\n");
- printk(KERN_INFO "** behavior. If this argument makes the device work again,\n");
- printk(KERN_INFO "** please email the output of \"lspci\" to bjorn.helgaas@hp.com\n");
- printk(KERN_INFO "** so I can fix the driver.\n");
- }
+ } else
+ printk(KERN_INFO "PCI: If a device doesn't work, try \"pci=routeirq\". If it helps, post a report\n");
+
#ifdef CONFIG_X86_IO_APIC
if (acpi_ioapic)
print_IO_APIC();
diff --git a/arch/i386/pci/direct.c b/arch/i386/pci/direct.c
index 3decbc498b0a6..30b7e9b4f6a20 100644
--- a/arch/i386/pci/direct.c
+++ b/arch/i386/pci/direct.c
@@ -13,7 +13,8 @@
#define PCI_CONF1_ADDRESS(bus, devfn, reg) \
(0x80000000 | (bus << 16) | (devfn << 8) | (reg & ~3))
-static int pci_conf1_read (int seg, int bus, int devfn, int reg, int len, u32 *value)
+static int pci_conf1_read(unsigned int seg, unsigned int bus,
+ unsigned int devfn, int reg, int len, u32 *value)
{
unsigned long flags;
@@ -41,7 +42,8 @@ static int pci_conf1_read (int seg, int bus, int devfn, int reg, int len, u32 *v
return 0;
}
-static int pci_conf1_write (int seg, int bus, int devfn, int reg, int len, u32 value)
+static int pci_conf1_write(unsigned int seg, unsigned int bus,
+ unsigned int devfn, int reg, int len, u32 value)
{
unsigned long flags;
@@ -83,7 +85,8 @@ struct pci_raw_ops pci_direct_conf1 = {
#define PCI_CONF2_ADDRESS(dev, reg) (u16)(0xC000 | (dev << 8) | reg)
-static int pci_conf2_read(int seg, int bus, int devfn, int reg, int len, u32 *value)
+static int pci_conf2_read(unsigned int seg, unsigned int bus,
+ unsigned int devfn, int reg, int len, u32 *value)
{
unsigned long flags;
int dev, fn;
@@ -121,7 +124,8 @@ static int pci_conf2_read(int seg, int bus, int devfn, int reg, int len, u32 *va
return 0;
}
-static int pci_conf2_write (int seg, int bus, int devfn, int reg, int len, u32 value)
+static int pci_conf2_write(unsigned int seg, unsigned int bus,
+ unsigned int devfn, int reg, int len, u32 value)
{
unsigned long flags;
int dev, fn;
diff --git a/arch/i386/pci/fixup.c b/arch/i386/pci/fixup.c
index af18331b3fb29..be52c5ac4e054 100644
--- a/arch/i386/pci/fixup.c
+++ b/arch/i386/pci/fixup.c
@@ -343,7 +343,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MCH_PC1, pcie_r
/*
* Fixup to mark boot BIOS video selected by BIOS before it changes
*
- * From information provided by "Jon Smirl" <jonsmirl@yahoo.com>
+ * From information provided by "Jon Smirl" <jonsmirl@gmail.com>
*
* The standard boot ROM sequence for an x86 machine uses the BIOS
* to select an initial video card for boot display. This boot video
@@ -354,12 +354,13 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MCH_PC1, pcie_r
* See pci_map_rom() for use of this flag. IORESOURCE_ROM_SHADOW
* is marked here since the boot video device will be the only enabled
* video device at this point.
- *
- */static void __devinit pci_fixup_video(struct pci_dev *pdev)
+ */
+
+static void __devinit pci_fixup_video(struct pci_dev *pdev)
{
struct pci_dev *bridge;
struct pci_bus *bus;
- u16 l;
+ u16 config;
if ((pdev->class >> 8) != PCI_CLASS_DISPLAY_VGA)
return;
@@ -369,12 +370,17 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MCH_PC1, pcie_r
while (bus) {
bridge = bus->self;
if (bridge) {
- pci_read_config_word(bridge, PCI_BRIDGE_CONTROL, &l);
- if (!(l & PCI_BRIDGE_CTL_VGA))
+ pci_read_config_word(bridge, PCI_BRIDGE_CONTROL,
+ &config);
+ if (!(config & PCI_BRIDGE_CTL_VGA))
return;
}
bus = bus->parent;
}
- pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW;
+ pci_read_config_word(pdev, PCI_COMMAND, &config);
+ if (config & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) {
+ pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW;
+ printk(KERN_DEBUG "Boot video device is %s\n", pci_name(pdev));
+ }
}
DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_video);
diff --git a/arch/i386/pci/irq.c b/arch/i386/pci/irq.c
index 9882a43ce4c12..1128451b5d742 100644
--- a/arch/i386/pci/irq.c
+++ b/arch/i386/pci/irq.c
@@ -1031,56 +1031,55 @@ static int pirq_enable_irq(struct pci_dev *dev)
pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
if (pin && !pcibios_lookup_irq(dev, 1) && !dev->irq) {
- char *msg;
- msg = "";
+ char *msg = "";
+
+ pin--; /* interrupt pins are numbered starting from 1 */
+
if (io_apic_assign_pci_irqs) {
int irq;
- if (pin) {
- pin--; /* interrupt pins are numbered starting from 1 */
- irq = IO_APIC_get_PCI_irq_vector(dev->bus->number, PCI_SLOT(dev->devfn), pin);
- /*
- * Busses behind bridges are typically not listed in the MP-table.
- * In this case we have to look up the IRQ based on the parent bus,
- * parent slot, and pin number. The SMP code detects such bridged
- * busses itself so we should get into this branch reliably.
- */
- temp_dev = dev;
- while (irq < 0 && dev->bus->parent) { /* go back to the bridge */
- struct pci_dev * bridge = dev->bus->self;
-
- pin = (pin + PCI_SLOT(dev->devfn)) % 4;
- irq = IO_APIC_get_PCI_irq_vector(bridge->bus->number,
- PCI_SLOT(bridge->devfn), pin);
- if (irq >= 0)
- printk(KERN_WARNING "PCI: using PPB %s[%c] to get irq %d\n",
- pci_name(bridge), 'A' + pin, irq);
- dev = bridge;
- }
- dev = temp_dev;
- if (irq >= 0) {
+ irq = IO_APIC_get_PCI_irq_vector(dev->bus->number, PCI_SLOT(dev->devfn), pin);
+ /*
+ * Busses behind bridges are typically not listed in the MP-table.
+ * In this case we have to look up the IRQ based on the parent bus,
+ * parent slot, and pin number. The SMP code detects such bridged
+ * busses itself so we should get into this branch reliably.
+ */
+ temp_dev = dev;
+ while (irq < 0 && dev->bus->parent) { /* go back to the bridge */
+ struct pci_dev * bridge = dev->bus->self;
+
+ pin = (pin + PCI_SLOT(dev->devfn)) % 4;
+ irq = IO_APIC_get_PCI_irq_vector(bridge->bus->number,
+ PCI_SLOT(bridge->devfn), pin);
+ if (irq >= 0)
+ printk(KERN_WARNING "PCI: using PPB %s[%c] to get irq %d\n",
+ pci_name(bridge), 'A' + pin, irq);
+ dev = bridge;
+ }
+ dev = temp_dev;
+ if (irq >= 0) {
#ifdef CONFIG_PCI_MSI
- if (!platform_legacy_irq(irq))
- irq = IO_APIC_VECTOR(irq);
+ if (!platform_legacy_irq(irq))
+ irq = IO_APIC_VECTOR(irq);
#endif
- printk(KERN_INFO "PCI->APIC IRQ transform: %s[%c] -> IRQ %d\n",
- pci_name(dev), 'A' + pin, irq);
- dev->irq = irq;
- return 0;
- } else
- msg = " Probably buggy MP table.";
- }
+ printk(KERN_INFO "PCI->APIC IRQ transform: %s[%c] -> IRQ %d\n",
+ pci_name(dev), 'A' + pin, irq);
+ dev->irq = irq;
+ return 0;
+ } else
+ msg = " Probably buggy MP table.";
} else if (pci_probe & PCI_BIOS_IRQ_SCAN)
msg = "";
else
msg = " Please try using pci=biosirq.";
-
+
/* With IDE legacy devices the IRQ lookup failure is not a problem.. */
if (dev->class >> 8 == PCI_CLASS_STORAGE_IDE && !(dev->class & 0x5))
return 0;
-
+
printk(KERN_WARNING "PCI: No IRQ known for interrupt pin %c of device %s.%s\n",
- 'A' + pin - 1, pci_name(dev), msg);
+ 'A' + pin, pci_name(dev), msg);
}
/* VIA bridges use interrupt line for apic/pci steering across
the V-Link */
diff --git a/arch/i386/pci/mmconfig.c b/arch/i386/pci/mmconfig.c
index 504fb18fe87d7..021a50aa51f43 100644
--- a/arch/i386/pci/mmconfig.c
+++ b/arch/i386/pci/mmconfig.c
@@ -34,7 +34,8 @@ static inline void pci_exp_set_dev_base(int bus, int devfn)
}
}
-static int pci_mmcfg_read(int seg, int bus, int devfn, int reg, int len, u32 *value)
+static int pci_mmcfg_read(unsigned int seg, unsigned int bus,
+ unsigned int devfn, int reg, int len, u32 *value)
{
unsigned long flags;
@@ -62,7 +63,8 @@ static int pci_mmcfg_read(int seg, int bus, int devfn, int reg, int len, u32 *va
return 0;
}
-static int pci_mmcfg_write(int seg, int bus, int devfn, int reg, int len, u32 value)
+static int pci_mmcfg_write(unsigned int seg, unsigned int bus,
+ unsigned int devfn, int reg, int len, u32 value)
{
unsigned long flags;
diff --git a/arch/i386/pci/numa.c b/arch/i386/pci/numa.c
index ddf9ac72d87b7..9e3695461899b 100644
--- a/arch/i386/pci/numa.c
+++ b/arch/i386/pci/numa.c
@@ -14,11 +14,12 @@
#define PCI_CONF1_MQ_ADDRESS(bus, devfn, reg) \
(0x80000000 | (BUS2LOCAL(bus) << 16) | (devfn << 8) | (reg & ~3))
-static int pci_conf1_mq_read (int seg, int bus, int devfn, int reg, int len, u32 *value)
+static int pci_conf1_mq_read(unsigned int seg, unsigned int bus,
+ unsigned int devfn, int reg, int len, u32 *value)
{
unsigned long flags;
- if (!value || (bus > MAX_MP_BUSSES) || (devfn > 255) || (reg > 255))
+ if (!value || (bus >= MAX_MP_BUSSES) || (devfn > 255) || (reg > 255))
return -EINVAL;
spin_lock_irqsave(&pci_config_lock, flags);
@@ -42,11 +43,12 @@ static int pci_conf1_mq_read (int seg, int bus, int devfn, int reg, int len, u32
return 0;
}
-static int pci_conf1_mq_write (int seg, int bus, int devfn, int reg, int len, u32 value)
+static int pci_conf1_mq_write(unsigned int seg, unsigned int bus,
+ unsigned int devfn, int reg, int len, u32 value)
{
unsigned long flags;
- if ((bus > MAX_MP_BUSSES) || (devfn > 255) || (reg > 255))
+ if ((bus >= MAX_MP_BUSSES) || (devfn > 255) || (reg > 255))
return -EINVAL;
spin_lock_irqsave(&pci_config_lock, flags);
diff --git a/arch/i386/pci/pcbios.c b/arch/i386/pci/pcbios.c
index d0f3c2d0db89c..141421b673b06 100644
--- a/arch/i386/pci/pcbios.c
+++ b/arch/i386/pci/pcbios.c
@@ -172,7 +172,8 @@ static int __devinit pci_bios_find_device (unsigned short vendor, unsigned short
return (int) (ret & 0xff00) >> 8;
}
-static int pci_bios_read (int seg, int bus, int devfn, int reg, int len, u32 *value)
+static int pci_bios_read(unsigned int seg, unsigned int bus,
+ unsigned int devfn, int reg, int len, u32 *value)
{
unsigned long result = 0;
unsigned long flags;
@@ -227,7 +228,8 @@ static int pci_bios_read (int seg, int bus, int devfn, int reg, int len, u32 *va
return (int)((result & 0xff00) >> 8);
}
-static int pci_bios_write (int seg, int bus, int devfn, int reg, int len, u32 value)
+static int pci_bios_write(unsigned int seg, unsigned int bus,
+ unsigned int devfn, int reg, int len, u32 value)
{
unsigned long result = 0;
unsigned long flags;
diff --git a/arch/i386/power/cpu.c b/arch/i386/power/cpu.c
index adb50ba2a6794..cf337c673d92a 100644
--- a/arch/i386/power/cpu.c
+++ b/arch/i386/power/cpu.c
@@ -28,8 +28,7 @@
static struct saved_context saved_context;
-unsigned long saved_context_eax, saved_context_ebx;
-unsigned long saved_context_ecx, saved_context_edx;
+unsigned long saved_context_ebx;
unsigned long saved_context_esp, saved_context_ebp;
unsigned long saved_context_esi, saved_context_edi;
unsigned long saved_context_eflags;
diff --git a/arch/i386/power/swsusp.S b/arch/i386/power/swsusp.S
index 6e6335f891ee2..c4105286ff26f 100644
--- a/arch/i386/power/swsusp.S
+++ b/arch/i386/power/swsusp.S
@@ -12,6 +12,7 @@
#include <linux/linkage.h>
#include <asm/segment.h>
#include <asm/page.h>
+#include <asm/asm_offsets.h>
.text
@@ -28,28 +29,37 @@ ENTRY(swsusp_arch_suspend)
ret
ENTRY(swsusp_arch_resume)
- movl $swsusp_pg_dir-__PAGE_OFFSET,%ecx
- movl %ecx,%cr3
+ movl $swsusp_pg_dir-__PAGE_OFFSET, %ecx
+ movl %ecx, %cr3
- movl pagedir_nosave, %ebx
- xorl %eax, %eax
- xorl %edx, %edx
+ movl pagedir_nosave, %edx
.p2align 4,,7
copy_loop:
- movl 4(%ebx,%edx),%edi
- movl (%ebx,%edx),%esi
+ testl %edx, %edx
+ jz done
+
+ movl pbe_address(%edx), %esi
+ movl pbe_orig_address(%edx), %edi
movl $1024, %ecx
rep
movsl
- incl %eax
- addl $16, %edx
- cmpl nr_copy_pages,%eax
- jb copy_loop
+ movl pbe_next(%edx), %edx
+ jmp copy_loop
.p2align 4,,7
+done:
+ /* Flush TLB, including "global" things (vmalloc) */
+ movl mmu_cr4_features, %eax
+ movl %eax, %edx
+ andl $~(1<<7), %edx; # PGE
+ movl %edx, %cr4; # turn off PGE
+ movl %cr3, %ecx; # flush TLB
+ movl %ecx, %cr3
+ movl %eax, %cr4; # turn PGE back on
+
movl saved_context_esp, %esp
movl saved_context_ebp, %ebp
movl saved_context_ebx, %ebx
@@ -57,5 +67,7 @@ copy_loop:
movl saved_context_edi, %edi
pushl saved_context_eflags ; popfl
- call swsusp_restore
+
+ xorl %eax, %eax
+
ret
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index a337879e981da..33fcb205fcb7a 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -169,6 +169,7 @@ config NUMA
bool "NUMA support"
depends on !IA64_HP_SIM
default y if IA64_SGI_SN2
+ select ACPI_NUMA
help
Say Y to compile the kernel to support NUMA (Non-Uniform Memory
Access). This option is for configuring high-end multiprocessor
diff --git a/arch/ia64/configs/sn2_defconfig b/arch/ia64/configs/sn2_defconfig
index a32758a6a58b5..bfeb952fe8e28 100644
--- a/arch/ia64/configs/sn2_defconfig
+++ b/arch/ia64/configs/sn2_defconfig
@@ -31,6 +31,7 @@ CONFIG_KALLSYMS_ALL=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
CONFIG_FUTEX=y
CONFIG_EPOLL=y
+CONFIG_CPUSETS=y
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SHMEM=y
CONFIG_CC_ALIGN_FUNCTIONS=0
diff --git a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c
index 272291d6073c0..017c9ab5fc1b2 100644
--- a/arch/ia64/hp/common/sba_iommu.c
+++ b/arch/ia64/hp/common/sba_iommu.c
@@ -157,6 +157,7 @@
#define DELAYED_RESOURCE_CNT 64
#define ZX1_IOC_ID ((PCI_DEVICE_ID_HP_ZX1_IOC << 16) | PCI_VENDOR_ID_HP)
+#define ZX2_IOC_ID ((PCI_DEVICE_ID_HP_ZX2_IOC << 16) | PCI_VENDOR_ID_HP)
#define REO_IOC_ID ((PCI_DEVICE_ID_HP_REO_IOC << 16) | PCI_VENDOR_ID_HP)
#define SX1000_IOC_ID ((PCI_DEVICE_ID_HP_SX1000_IOC << 16) | PCI_VENDOR_ID_HP)
@@ -761,7 +762,7 @@ sba_io_pdir_entry(u64 *pdir_ptr, unsigned long vba)
#ifdef ENABLE_MARK_CLEAN
/**
* Since DMA is i-cache coherent, any (complete) pages that were written via
- * DMA can be marked as "clean" so that update_mmu_cache() doesn't have to
+ * DMA can be marked as "clean" so that lazy_mmu_prot_update() doesn't have to
* flush them when they get mapped into an executable vm-area.
*/
static void
@@ -1707,6 +1708,7 @@ struct ioc_iommu {
static struct ioc_iommu ioc_iommu_info[] __initdata = {
{ ZX1_IOC_ID, "zx1", ioc_zx1_init },
+ { ZX2_IOC_ID, "zx2", NULL },
{ SX1000_IOC_ID, "sx1000", NULL },
};
diff --git a/arch/ia64/ia32/ia32_entry.S b/arch/ia64/ia32/ia32_entry.S
index 1bb348d72359b..829a6d80711c1 100644
--- a/arch/ia64/ia32/ia32_entry.S
+++ b/arch/ia64/ia32/ia32_entry.S
@@ -494,7 +494,7 @@ ia32_syscall_table:
data8 compat_sys_mq_notify
data8 compat_sys_mq_getsetattr
data8 sys_ni_syscall /* reserved for kexec */
- data8 sys32_waitid
+ data8 compat_sys_waitid
// guard against failures to increase IA32_NR_syscalls
.org ia32_syscall_table + 8*IA32_NR_syscalls
diff --git a/arch/ia64/ia32/ia32_signal.c b/arch/ia64/ia32/ia32_signal.c
index 3b385f543c05c..19b02adce68cd 100644
--- a/arch/ia64/ia32/ia32_signal.c
+++ b/arch/ia64/ia32/ia32_signal.c
@@ -778,7 +778,7 @@ restore_sigcontext_ia32 (struct pt_regs *regs, struct sigcontext_ia32 __user *sc
struct _fpstate * buf;
err |= __get_user(buf, &sc->fpstate);
if (buf) {
- if (verify_area(VERIFY_READ, buf, sizeof(*buf)))
+ if (!access_ok(VERIFY_READ, buf, sizeof(*buf)))
goto badframe;
err |= restore_i387(buf);
}
@@ -978,7 +978,7 @@ sys32_sigreturn (int arg0, int arg1, int arg2, int arg3, int arg4, int arg5,
sigset_t set;
int eax;
- if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
+ if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
goto badframe;
if (__get_user(set.sig[0], &frame->sc.oldmask)
@@ -1010,7 +1010,7 @@ sys32_rt_sigreturn (int arg0, int arg1, int arg2, int arg3, int arg4,
sigset_t set;
int eax;
- if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
+ if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
goto badframe;
if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
goto badframe;
diff --git a/arch/ia64/ia32/ia32priv.h b/arch/ia64/ia32/ia32priv.h
index ebdd4e20bb0d2..b2de948bdaea7 100644
--- a/arch/ia64/ia32/ia32priv.h
+++ b/arch/ia64/ia32/ia32priv.h
@@ -225,13 +225,6 @@ struct stat64 {
unsigned int st_ino_hi;
};
-typedef union sigval32 {
- int sival_int;
- unsigned int sival_ptr;
-} sigval_t32;
-
-#define SIGEV_PAD_SIZE32 ((SIGEV_MAX_SIZE/sizeof(int)) - 3)
-
typedef struct compat_siginfo {
int si_signo;
int si_errno;
@@ -251,7 +244,7 @@ typedef struct compat_siginfo {
timer_t _tid; /* timer id */
int _overrun; /* overrun count */
char _pad[sizeof(unsigned int) - sizeof(int)];
- sigval_t32 _sigval; /* same as below */
+ compat_sigval_t _sigval; /* same as below */
int _sys_private; /* not to be passed to user */
} _timer;
@@ -259,7 +252,7 @@ typedef struct compat_siginfo {
struct {
unsigned int _pid; /* sender's pid */
unsigned int _uid; /* sender's uid */
- sigval_t32 _sigval;
+ compat_sigval_t _sigval;
} _rt;
/* SIGCHLD */
@@ -284,19 +277,6 @@ typedef struct compat_siginfo {
} _sifields;
} compat_siginfo_t;
-typedef struct sigevent32 {
- sigval_t32 sigev_value;
- int sigev_signo;
- int sigev_notify;
- union {
- int _pad[SIGEV_PAD_SIZE32];
- struct {
- u32 _function;
- u32 _attribute; /* really pthread_attr_t */
- } _sigev_thread;
- } _sigev_un;
-} sigevent_t32;
-
struct old_linux32_dirent {
u32 d_ino;
u32 d_offset;
diff --git a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c
index f2eccc24c3e72..247a21c64aea3 100644
--- a/arch/ia64/ia32/sys_ia32.c
+++ b/arch/ia64/ia32/sys_ia32.c
@@ -2402,12 +2402,11 @@ sys32_epoll_ctl(int epfd, int op, int fd, struct epoll_event32 __user *event)
{
mm_segment_t old_fs = get_fs();
struct epoll_event event64;
- int error = -EFAULT;
+ int error;
u32 data_halfword;
- if ((error = verify_area(VERIFY_READ, event,
- sizeof(struct epoll_event32))))
- return error;
+ if (!access_ok(VERIFY_READ, event, sizeof(struct epoll_event32)))
+ return -EFAULT;
__get_user(event64.events, &event->events);
__get_user(data_halfword, &event->data[0]);
@@ -2437,9 +2436,8 @@ sys32_epoll_wait(int epfd, struct epoll_event32 __user * events, int maxevents,
}
/* Verify that the area passed by the user is writeable */
- if ((error = verify_area(VERIFY_WRITE, events,
- maxevents * sizeof(struct epoll_event32))))
- return error;
+ if (!access_ok(VERIFY_WRITE, events, maxevents * sizeof(struct epoll_event32)))
+ return -EFAULT;
/*
* Allocate space for the intermediate copy. If the space needed
@@ -2592,7 +2590,7 @@ sys32_get_thread_area (struct ia32_user_desc __user *u_info)
}
asmlinkage long
-sys32_timer_create(u32 clock, struct sigevent32 __user *se32, timer_t __user *timer_id)
+sys32_timer_create(u32 clock, struct compat_sigevent __user *se32, timer_t __user *timer_id)
{
struct sigevent se;
mm_segment_t oldfs;
@@ -2602,12 +2600,7 @@ sys32_timer_create(u32 clock, struct sigevent32 __user *se32, timer_t __user *ti
if (se32 == NULL)
return sys_timer_create(clock, NULL, timer_id);
- memset(&se, 0, sizeof(struct sigevent));
- if (get_user(se.sigev_value.sival_int, &se32->sigev_value.sival_int) ||
- __get_user(se.sigev_signo, &se32->sigev_signo) ||
- __get_user(se.sigev_notify, &se32->sigev_notify) ||
- __copy_from_user(&se._sigev_un._pad, &se32->_sigev_un._pad,
- sizeof(se._sigev_un._pad)))
+ if (get_compat_sigevent(&se, se32))
return -EFAULT;
if (!access_ok(VERIFY_WRITE,timer_id,sizeof(timer_t)))
@@ -2633,32 +2626,6 @@ long sys32_fadvise64_64(int fd, __u32 offset_low, __u32 offset_high,
advice);
}
-asmlinkage long sys32_waitid(int which, compat_pid_t pid,
- compat_siginfo_t __user *uinfo, int options,
- struct compat_rusage __user *uru)
-{
- siginfo_t info;
- struct rusage ru;
- long ret;
- mm_segment_t old_fs = get_fs();
-
- info.si_signo = 0;
- set_fs (KERNEL_DS);
- ret = sys_waitid(which, pid, (siginfo_t __user *) &info, options,
- uru ? (struct rusage __user *) &ru : NULL);
- set_fs (old_fs);
-
- if (ret < 0 || info.si_signo == 0)
- return ret;
-
- if (uru && (ret = put_compat_rusage(&ru, uru)))
- return ret;
-
- BUG_ON(info.si_code & __SI_MASK);
- info.si_code |= __SI_CHLD;
- return copy_siginfo_to_user32(uinfo, &info);
-}
-
#ifdef NOTYET /* UNTESTED FOR IA64 FROM HERE DOWN */
asmlinkage long sys32_setreuid(compat_uid_t ruid, compat_uid_t euid)
diff --git a/arch/ia64/kernel/irq.c b/arch/ia64/kernel/irq.c
index 4413e54b123b0..28f2aadc38d00 100644
--- a/arch/ia64/kernel/irq.c
+++ b/arch/ia64/kernel/irq.c
@@ -94,12 +94,20 @@ skip:
/*
* This is updated when the user sets irq affinity via /proc
*/
-cpumask_t __cacheline_aligned pending_irq_cpumask[NR_IRQS];
+static cpumask_t __cacheline_aligned pending_irq_cpumask[NR_IRQS];
static unsigned long pending_irq_redir[BITS_TO_LONGS(NR_IRQS)];
-static cpumask_t irq_affinity [NR_IRQS] = { [0 ... NR_IRQS-1] = CPU_MASK_ALL };
static char irq_redir [NR_IRQS]; // = { [0 ... NR_IRQS-1] = 1 };
+/*
+ * Arch specific routine for deferred write to iosapic rte to reprogram
+ * intr destination.
+ */
+void proc_set_irq_affinity(unsigned int irq, cpumask_t mask_val)
+{
+ pending_irq_cpumask[irq] = mask_val;
+}
+
void set_irq_affinity_info (unsigned int irq, int hwid, int redir)
{
cpumask_t mask = CPU_MASK_NONE;
diff --git a/arch/ia64/kernel/ivt.S b/arch/ia64/kernel/ivt.S
index b3ed949a4f860..d9c05d53435bd 100644
--- a/arch/ia64/kernel/ivt.S
+++ b/arch/ia64/kernel/ivt.S
@@ -957,6 +957,8 @@ END(ia64_syscall_setup)
* element, followed by the arguments.
*/
ENTRY(dispatch_illegal_op_fault)
+ .prologue
+ .body
SAVE_MIN_WITH_COVER
ssm psr.ic | PSR_DEFAULT_BITS
;;
@@ -969,6 +971,7 @@ ENTRY(dispatch_illegal_op_fault)
mov out0=ar.ec
;;
SAVE_REST
+ PT_REGS_UNWIND_INFO(0)
;;
br.call.sptk.many rp=ia64_illegal_op_fault
.ret0: ;;
diff --git a/arch/ia64/kernel/minstate.h b/arch/ia64/kernel/minstate.h
index a01c2cd060380..1dbc7b2497c90 100644
--- a/arch/ia64/kernel/minstate.h
+++ b/arch/ia64/kernel/minstate.h
@@ -26,7 +26,7 @@
(pKStk) addl r1=-IA64_PT_REGS_SIZE,r1; /* if in kernel mode, use sp (r12) */ \
;; \
(pUStk) mov r18=ar.bsp; \
-(pUStk) mov ar.rsc=0x3; /* set eager mode, pl 0, little-endian, loadrs=0 */ \
+(pUStk) mov ar.rsc=0x3; /* set eager mode, pl 0, little-endian, loadrs=0 */
#define MINSTATE_END_SAVE_MIN_VIRT \
bsw.1; /* switch back to bank 1 (must be last in insn group) */ \
diff --git a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c
index 00cd9a2030c22..55789fcd72104 100644
--- a/arch/ia64/kernel/ptrace.c
+++ b/arch/ia64/kernel/ptrace.c
@@ -16,6 +16,7 @@
#include <linux/smp_lock.h>
#include <linux/user.h>
#include <linux/security.h>
+#include <linux/audit.h>
#include <asm/pgtable.h>
#include <asm/processor.h>
@@ -1073,15 +1074,12 @@ ptrace_getregs (struct task_struct *child, struct pt_all_user_regs __user *ppr)
struct ia64_fpreg fpval;
struct switch_stack *sw;
struct pt_regs *pt;
- long ret, retval;
+ long ret, retval = 0;
char nat = 0;
int i;
- retval = verify_area(VERIFY_WRITE, ppr,
- sizeof(struct pt_all_user_regs));
- if (retval != 0) {
+ if (!access_ok(VERIFY_WRITE, ppr, sizeof(struct pt_all_user_regs)))
return -EIO;
- }
pt = ia64_task_regs(child);
sw = (struct switch_stack *) (child->thread.ksp + 16);
@@ -1104,8 +1102,6 @@ ptrace_getregs (struct task_struct *child, struct pt_all_user_regs __user *ppr)
|| access_uarea(child, PT_NAT_BITS, &nat_bits, 0))
return -EIO;
- retval = 0;
-
/* control regs */
retval |= __put_user(pt->cr_iip, &ppr->cr_iip);
@@ -1222,16 +1218,13 @@ ptrace_setregs (struct task_struct *child, struct pt_all_user_regs __user *ppr)
struct switch_stack *sw;
struct ia64_fpreg fpval;
struct pt_regs *pt;
- long ret, retval;
+ long ret, retval = 0;
int i;
memset(&fpval, 0, sizeof(fpval));
- retval = verify_area(VERIFY_READ, ppr,
- sizeof(struct pt_all_user_regs));
- if (retval != 0) {
+ if (!access_ok(VERIFY_READ, ppr, sizeof(struct pt_all_user_regs)))
return -EIO;
- }
pt = ia64_task_regs(child);
sw = (struct switch_stack *) (child->thread.ksp + 16);
@@ -1245,8 +1238,6 @@ ptrace_setregs (struct task_struct *child, struct pt_all_user_regs __user *ppr)
return -EIO;
}
- retval = 0;
-
/* control regs */
retval |= __get_user(pt->cr_iip, &ppr->cr_iip);
diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
index 29684bf184c2b..f05650c801d2a 100644
--- a/arch/ia64/kernel/setup.c
+++ b/arch/ia64/kernel/setup.c
@@ -75,8 +75,6 @@ struct io_space io_space[MAX_IO_SPACES];
EXPORT_SYMBOL(io_space);
unsigned int num_io_spaces;
-unsigned char aux_device_present = 0xaa; /* XXX remove this when legacy I/O is gone */
-
/*
* The merge_mask variable needs to be set to (max(iommu_page_size(iommu)) - 1). This
* mask specifies a mask of address bits that must be 0 in order for two buffers to be
@@ -648,6 +646,15 @@ cpu_init (void)
ia64_set_kr(IA64_KR_FPU_OWNER, 0);
/*
+ * Initialize the page-table base register to a global
+ * directory with all zeroes. This ensure that we can handle
+ * TLB-misses to user address-space even before we created the
+ * first user address-space. This may happen, e.g., due to
+ * aggressive use of lfetch.fault.
+ */
+ ia64_set_kr(IA64_KR_PT_BASE, __pa(ia64_imva(empty_zero_page)));
+
+ /*
* Initialize default control register to defer all speculative faults. The
* kernel MUST NOT depend on a particular setting of these bits (in other words,
* the kernel must have recovery code for all speculative accesses). Turn on
diff --git a/arch/ia64/kernel/smp.c b/arch/ia64/kernel/smp.c
index 4149a0d49c4ff..953095e2ce157 100644
--- a/arch/ia64/kernel/smp.c
+++ b/arch/ia64/kernel/smp.c
@@ -227,7 +227,6 @@ smp_flush_tlb_all (void)
{
on_each_cpu((void (*)(void *))local_flush_tlb_all, NULL, 1, 1);
}
-EXPORT_SYMBOL(smp_flush_tlb_all);
void
smp_flush_tlb_mm (struct mm_struct *mm)
diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c
index 02dc1fc08a974..5318f0cbfc260 100644
--- a/arch/ia64/kernel/smpboot.c
+++ b/arch/ia64/kernel/smpboot.c
@@ -427,26 +427,12 @@ decay (char *str)
{
int ticks;
get_option (&str, &ticks);
- cache_decay_ticks = ticks;
return 1;
}
__setup("decay=", decay);
/*
- * # of ticks an idle task is considered cache-hot. Highly application-dependent. There
- * are apps out there which are known to suffer significantly with values >= 4.
- */
-unsigned long cache_decay_ticks = 10; /* equal to MIN_TIMESLICE */
-
-static void
-smp_tune_scheduling (void)
-{
- printk(KERN_INFO "task migration cache decay timeout: %ld msecs.\n",
- (cache_decay_ticks + 1) * 1000 / HZ);
-}
-
-/*
* Initialize the logical CPU number to SAPICID mapping
*/
void __init
@@ -544,7 +530,6 @@ smp_prepare_cpus (unsigned int max_cpus)
printk(KERN_INFO "Boot processor id 0x%x/0x%x\n", 0, boot_cpu_id);
current_thread_info()->cpu = 0;
- smp_tune_scheduling();
/*
* If SMP should be disabled, then really disable it!
diff --git a/arch/ia64/lib/swiotlb.c b/arch/ia64/lib/swiotlb.c
index e3e2fb75503a5..ab7b3ad99a7fa 100644
--- a/arch/ia64/lib/swiotlb.c
+++ b/arch/ia64/lib/swiotlb.c
@@ -444,7 +444,7 @@ swiotlb_map_single(struct device *hwdev, void *ptr, size_t size, int dir)
/*
* Since DMA is i-cache coherent, any (complete) pages that were written via
- * DMA can be marked as "clean" so that update_mmu_cache() doesn't have to
+ * DMA can be marked as "clean" so that lazy_mmu_prot_update() doesn't have to
* flush them when they get mapped into an executable vm-area.
*/
static void
diff --git a/arch/ia64/mm/contig.c b/arch/ia64/mm/contig.c
index b9b3e627a56fc..6daf15ac89405 100644
--- a/arch/ia64/mm/contig.c
+++ b/arch/ia64/mm/contig.c
@@ -280,7 +280,7 @@ paging_init (void)
vmem_map = (struct page *) vmalloc_end;
efi_memmap_walk(create_mem_map_page_table, NULL);
- mem_map = contig_page_data.node_mem_map = vmem_map;
+ NODE_DATA(0)->node_mem_map = vmem_map;
free_area_init_node(0, &contig_page_data, zones_size,
0, zholes_size);
diff --git a/arch/ia64/mm/extable.c b/arch/ia64/mm/extable.c
index 99edfed31c98b..6d259e34f3596 100644
--- a/arch/ia64/mm/extable.c
+++ b/arch/ia64/mm/extable.c
@@ -6,29 +6,29 @@
*/
#include <linux/config.h>
+#include <linux/sort.h>
#include <asm/uaccess.h>
#include <asm/module.h>
-static inline int
-compare_entries (struct exception_table_entry *l, struct exception_table_entry *r)
+static int cmp_ex(const void *a, const void *b)
{
+ const struct exception_table_entry *l = a, *r = b;
u64 lip = (u64) &l->addr + l->addr;
u64 rip = (u64) &r->addr + r->addr;
+ /* avoid overflow */
+ if (lip > rip)
+ return 1;
if (lip < rip)
return -1;
- if (lip == rip)
- return 0;
- else
- return 1;
+ return 0;
}
-static inline void
-swap_entries (struct exception_table_entry *l, struct exception_table_entry *r)
+static void swap_ex(void *a, void *b, int size)
{
+ struct exception_table_entry *l = a, *r = b, tmp;
u64 delta = (u64) r - (u64) l;
- struct exception_table_entry tmp;
tmp = *l;
l->addr = r->addr + delta;
@@ -38,23 +38,20 @@ swap_entries (struct exception_table_entry *l, struct exception_table_entry *r)
}
/*
- * Sort the exception table. It's usually already sorted, but there may be unordered
- * entries due to multiple text sections (such as the .init text section). Note that the
- * exception-table-entries contain location-relative addresses, which requires a bit of
- * care during sorting to avoid overflows in the offset members (e.g., it would not be
- * safe to make a temporary copy of an exception-table entry on the stack, because the
- * stack may be more than 2GB away from the exception-table).
+ * Sort the exception table. It's usually already sorted, but there
+ * may be unordered entries due to multiple text sections (such as the
+ * .init text section). Note that the exception-table-entries contain
+ * location-relative addresses, which requires a bit of care during
+ * sorting to avoid overflows in the offset members (e.g., it would
+ * not be safe to make a temporary copy of an exception-table entry on
+ * the stack, because the stack may be more than 2GB away from the
+ * exception-table).
*/
-void
-sort_extable (struct exception_table_entry *start, struct exception_table_entry *finish)
+void sort_extable (struct exception_table_entry *start,
+ struct exception_table_entry *finish)
{
- struct exception_table_entry *p, *q;
-
- /* insertion sort */
- for (p = start + 1; p < finish; ++p)
- /* start .. p-1 is sorted; push p down to it's proper place */
- for (q = p; q > start && compare_entries(&q[0], &q[-1]) < 0; --q)
- swap_entries(&q[0], &q[-1]);
+ sort(start, finish - start, sizeof(struct exception_table_entry),
+ cmp_ex, swap_ex);
}
const struct exception_table_entry *
diff --git a/arch/ia64/mm/hugetlbpage.c b/arch/ia64/mm/hugetlbpage.c
index 13e0f7d7c2912..40ad8328ffd5c 100644
--- a/arch/ia64/mm/hugetlbpage.c
+++ b/arch/ia64/mm/hugetlbpage.c
@@ -73,7 +73,7 @@ set_huge_pte (struct mm_struct *mm, struct vm_area_struct *vma,
{
pte_t entry;
- mm->rss += (HPAGE_SIZE / PAGE_SIZE);
+ add_mm_counter(mm, rss, HPAGE_SIZE / PAGE_SIZE);
if (write_access) {
entry =
pte_mkwrite(pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
@@ -116,7 +116,7 @@ int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src,
ptepage = pte_page(entry);
get_page(ptepage);
set_pte(dst_pte, entry);
- dst->rss += (HPAGE_SIZE / PAGE_SIZE);
+ add_mm_counter(dst, rss, HPAGE_SIZE / PAGE_SIZE);
addr += HPAGE_SIZE;
}
return 0;
@@ -244,9 +244,9 @@ void unmap_hugepage_range(struct vm_area_struct *vma, unsigned long start, unsig
continue;
page = pte_page(*pte);
put_page(page);
- pte_clear(pte);
+ pte_clear(mm, address, pte);
}
- mm->rss -= (end - start) >> PAGE_SHIFT;
+ add_mm_counter(mm, rss, - ((end - start) >> PAGE_SHIFT));
flush_tlb_range(vma, start, end);
}
diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c
index df0f1211517a8..65cf839573ea8 100644
--- a/arch/ia64/mm/init.c
+++ b/arch/ia64/mm/init.c
@@ -76,7 +76,7 @@ check_pgt_cache (void)
}
void
-update_mmu_cache (struct vm_area_struct *vma, unsigned long vaddr, pte_t pte)
+lazy_mmu_prot_update (pte_t pte)
{
unsigned long addr;
struct page *page;
@@ -85,7 +85,6 @@ update_mmu_cache (struct vm_area_struct *vma, unsigned long vaddr, pte_t pte)
return; /* not an executable page... */
page = pte_page(pte);
- /* don't use VADDR: it may not be mapped on this CPU (or may have just been flushed): */
addr = (unsigned long) page_address(page);
if (test_bit(PG_arch_1, &page->flags))
diff --git a/arch/ia64/mm/tlb.c b/arch/ia64/mm/tlb.c
index bd62f55b0a81d..464557e4ed824 100644
--- a/arch/ia64/mm/tlb.c
+++ b/arch/ia64/mm/tlb.c
@@ -127,7 +127,6 @@ local_flush_tlb_all (void)
local_irq_restore(flags);
ia64_srlz_i(); /* srlz.i implies srlz.d */
}
-EXPORT_SYMBOL(local_flush_tlb_all);
void
flush_tlb_range (struct vm_area_struct *vma, unsigned long start, unsigned long end)
diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
index 2a0dcf6083d62..61d8dd3c9c93a 100644
--- a/arch/ia64/pci/pci.c
+++ b/arch/ia64/pci/pci.c
@@ -3,9 +3,9 @@
*
* Derived from bios32.c of i386 tree.
*
- * Copyright (C) 2002 Hewlett-Packard Co
+ * (c) Copyright 2002, 2005 Hewlett-Packard Development Company, L.P.
* David Mosberger-Tang <davidm@hpl.hp.com>
- * Bjorn Helgaas <bjorn_helgaas@hp.com>
+ * Bjorn Helgaas <bjorn.helgaas@hp.com>
* Copyright (C) 2004 Silicon Graphics, Inc.
*
* Note: Above list of copyright holders is incomplete...
@@ -27,26 +27,12 @@
#include <asm/segment.h>
#include <asm/system.h>
#include <asm/io.h>
-
#include <asm/sal.h>
-
-
-#ifdef CONFIG_SMP
-# include <asm/smp.h>
-#endif
+#include <asm/smp.h>
#include <asm/irq.h>
#include <asm/hw_irq.h>
-#undef DEBUG
-#define DEBUG
-
-#ifdef DEBUG
-#define DBG(x...) printk(x)
-#else
-#define DBG(x...)
-#endif
-
static int pci_routeirq;
/*
@@ -55,23 +41,22 @@ static int pci_routeirq;
* synchronization mechanism here.
*/
-#define PCI_SAL_ADDRESS(seg, bus, devfn, reg) \
- ((u64)(seg << 24) | (u64)(bus << 16) | \
- (u64)(devfn << 8) | (u64)(reg))
+#define PCI_SAL_ADDRESS(seg, bus, devfn, reg) \
+ (((u64) seg << 24) | (bus << 16) | (devfn << 8) | (reg))
/* SAL 3.2 adds support for extended config space. */
#define PCI_SAL_EXT_ADDRESS(seg, bus, devfn, reg) \
- ((u64)(seg << 28) | (u64)(bus << 20) | \
- (u64)(devfn << 12) | (u64)(reg))
+ (((u64) seg << 28) | (bus << 20) | (devfn << 12) | (reg))
static int
-pci_sal_read (int seg, int bus, int devfn, int reg, int len, u32 *value)
+pci_sal_read (unsigned int seg, unsigned int bus, unsigned int devfn,
+ int reg, int len, u32 *value)
{
- u64 addr, mode, data = 0;
- int result = 0;
+ u64 addr, data = 0;
+ int mode, result;
- if ((seg > 65535) || (bus > 255) || (devfn > 255) || (reg > 4095))
+ if (!value || (seg > 65535) || (bus > 255) || (devfn > 255) || (reg > 4095))
return -EINVAL;
if ((seg | reg) <= 255) {
@@ -82,16 +67,19 @@ pci_sal_read (int seg, int bus, int devfn, int reg, int len, u32 *value)
mode = 1;
}
result = ia64_sal_pci_config_read(addr, mode, len, &data);
+ if (result != 0)
+ return -EINVAL;
*value = (u32) data;
-
- return result;
+ return 0;
}
static int
-pci_sal_write (int seg, int bus, int devfn, int reg, int len, u32 value)
+pci_sal_write (unsigned int seg, unsigned int bus, unsigned int devfn,
+ int reg, int len, u32 value)
{
- u64 addr, mode;
+ u64 addr;
+ int mode, result;
if ((seg > 65535) || (bus > 255) || (devfn > 255) || (reg > 4095))
return -EINVAL;
@@ -103,7 +91,10 @@ pci_sal_write (int seg, int bus, int devfn, int reg, int len, u32 value)
addr = PCI_SAL_EXT_ADDRESS(seg, bus, devfn, reg);
mode = 1;
}
- return ia64_sal_pci_config_write(addr, mode, len, value);
+ result = ia64_sal_pci_config_write(addr, mode, len, value);
+ if (result != 0)
+ return -EINVAL;
+ return 0;
}
static struct pci_raw_ops pci_sal_ops = {
@@ -160,21 +151,11 @@ pci_acpi_init (void)
* also do it here in case there are still broken drivers that
* don't use pci_enable_device().
*/
- printk(KERN_INFO "** Routing PCI interrupts for all devices because \"pci=routeirq\"\n");
- printk(KERN_INFO "** was specified. If this was required to make a driver work,\n");
- printk(KERN_INFO "** please email the output of \"lspci\" to bjorn.helgaas@hp.com\n");
- printk(KERN_INFO "** so I can fix the driver.\n");
+ printk(KERN_INFO "PCI: Routing interrupts for all devices because \"pci=routeirq\" specified\n");
for_each_pci_dev(dev)
acpi_pci_irq_enable(dev);
- } else {
- printk(KERN_INFO "** PCI interrupts are no longer routed automatically. If this\n");
- printk(KERN_INFO "** causes a device to stop working, it is probably because the\n");
- printk(KERN_INFO "** driver failed to call pci_enable_device(). As a temporary\n");
- printk(KERN_INFO "** workaround, the \"pci=routeirq\" argument restores the old\n");
- printk(KERN_INFO "** behavior. If this argument makes the device work again,\n");
- printk(KERN_INFO "** please email the output of \"lspci\" to bjorn.helgaas@hp.com\n");
- printk(KERN_INFO "** so I can fix the driver.\n");
- }
+ } else
+ printk(KERN_INFO "PCI: If a device doesn't work, try \"pci=routeirq\". If it helps, post a report\n");
return 0;
}
diff --git a/arch/m32r/boot/compressed/Makefile b/arch/m32r/boot/compressed/Makefile
index 994c9aa04bd38..d908e1d3c07f1 100644
--- a/arch/m32r/boot/compressed/Makefile
+++ b/arch/m32r/boot/compressed/Makefile
@@ -30,7 +30,12 @@ $(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE
CFLAGS_misc.o += -fpic
+ifdef CONFIG_MMU
LDFLAGS_piggy.o := -r --format binary --oformat elf32-m32r-linux -T
+else
+LDFLAGS_piggy.o := -r --format binary --oformat elf32-m32r -T
+endif
+
OBJCOPYFLAGS += -R .empty_zero_page
$(obj)/piggy.o: $(obj)/vmlinux.scr $(obj)/vmlinux.bin.gz FORCE
diff --git a/arch/m32r/boot/compressed/head.S b/arch/m32r/boot/compressed/head.S
index 10b928ed0f507..07cfd6ad1ae46 100644
--- a/arch/m32r/boot/compressed/head.S
+++ b/arch/m32r/boot/compressed/head.S
@@ -138,6 +138,11 @@ startup:
ldi r0, -1
ldi r1, 0xd0 ; invalidate i-cache, copy back d-cache
stb r1, @r0
+#elif defined(CONFIG_CHIP_M32102)
+ /* Cache flush */
+ ldi r0, -2
+ ldi r1, 0x0100 ; invalidate
+ stb r1, @r0
#else
#error "put your cache flush function, please"
#endif
diff --git a/arch/m32r/boot/compressed/m32r_sio.c b/arch/m32r/boot/compressed/m32r_sio.c
index bdfd1c2839664..bad5475eff90c 100644
--- a/arch/m32r/boot/compressed/m32r_sio.c
+++ b/arch/m32r/boot/compressed/m32r_sio.c
@@ -46,9 +46,14 @@ static void putc(char c)
}
*BOOT_SIO0TXB = c;
}
-#else
+#else /* defined(CONFIG_PLAT_M32700UT_Alpha) || defined(CONFIG_PLAT_M32700UT) */
+#ifdef CONFIG_MMU
#define SIO0STS (volatile unsigned short *)(0xa0efd000 + 14)
#define SIO0TXB (volatile unsigned short *)(0xa0efd000 + 30)
+#else
+#define SIO0STS (volatile unsigned short *)(0x00efd000 + 14)
+#define SIO0TXB (volatile unsigned short *)(0x00efd000 + 30)
+#endif
static void putc(char c)
{
diff --git a/arch/m32r/boot/setup.S b/arch/m32r/boot/setup.S
index 1b95a8b8dc752..5d256434b4ade 100644
--- a/arch/m32r/boot/setup.S
+++ b/arch/m32r/boot/setup.S
@@ -75,6 +75,11 @@ ENTRY(boot)
ldi r1, #0x73 ; cache on (with invalidation)
; ldi r1, #0x00 ; cache off
st r1, @r0
+#elif defined(CONFIG_CHIP_M32102)
+ ldi r0, #-4 ;LDIMM (r0, M32R_MCCR)
+ ldi r1, #0x101 ; cache on (with invalidation)
+; ldi r1, #0x00 ; cache off
+ st r1, @r0
#else
#error unknown chip configuration
#endif
diff --git a/arch/m32r/kernel/entry.S b/arch/m32r/kernel/entry.S
index e71801637083b..dddbf6b5ed2ce 100644
--- a/arch/m32r/kernel/entry.S
+++ b/arch/m32r/kernel/entry.S
@@ -69,16 +69,17 @@
#include <asm/mmu_context.h>
#if !defined(CONFIG_MMU)
-#define sys_madvise sys_ni_syscall
-#define sys_readahead sys_ni_syscall
-#define sys_mprotect sys_ni_syscall
-#define sys_msync sys_ni_syscall
-#define sys_mlock sys_ni_syscall
-#define sys_munlock sys_ni_syscall
-#define sys_mlockall sys_ni_syscall
-#define sys_munlockall sys_ni_syscall
-#define sys_mremap sys_ni_syscall
-#define sys_mincore sys_ni_syscall
+#define sys_madvise sys_ni_syscall
+#define sys_readahead sys_ni_syscall
+#define sys_mprotect sys_ni_syscall
+#define sys_msync sys_ni_syscall
+#define sys_mlock sys_ni_syscall
+#define sys_munlock sys_ni_syscall
+#define sys_mlockall sys_ni_syscall
+#define sys_munlockall sys_ni_syscall
+#define sys_mremap sys_ni_syscall
+#define sys_mincore sys_ni_syscall
+#define sys_remap_file_pages sys_ni_syscall
#endif /* CONFIG_MMU */
#define R4(reg) @reg
diff --git a/arch/m32r/kernel/m32r_ksyms.c b/arch/m32r/kernel/m32r_ksyms.c
index f5aa0766f532e..e5ec134d81d98 100644
--- a/arch/m32r/kernel/m32r_ksyms.c
+++ b/arch/m32r/kernel/m32r_ksyms.c
@@ -76,7 +76,6 @@ EXPORT_SYMBOL(smp_call_function);
/* TLB flushing */
EXPORT_SYMBOL(smp_flush_tlb_page);
-EXPORT_SYMBOL_GPL(smp_flush_tlb_all);
#endif
/* compiler generated symbol */
diff --git a/arch/m32r/kernel/module.c b/arch/m32r/kernel/module.c
index 2d5c384488bd8..f6a79a016ce01 100644
--- a/arch/m32r/kernel/module.c
+++ b/arch/m32r/kernel/module.c
@@ -14,6 +14,8 @@
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/moduleloader.h>
#include <linux/elf.h>
#include <linux/vmalloc.h>
@@ -31,7 +33,11 @@ void *module_alloc(unsigned long size)
{
if (size == 0)
return NULL;
+#ifdef CONFIG_MMU
return vmalloc_exec(size);
+#else
+ return vmalloc(size);
+#endif
}
diff --git a/arch/m32r/kernel/semaphore.c b/arch/m32r/kernel/semaphore.c
index 358f217c5a15a..9a6e6d754ddcf 100644
--- a/arch/m32r/kernel/semaphore.c
+++ b/arch/m32r/kernel/semaphore.c
@@ -19,7 +19,7 @@
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
- * rw semaphores implemented November 1999 by Benjamin LaHaise <bcrl@redhat.com>
+ * rw semaphores implemented November 1999 by Benjamin LaHaise <bcrl@kvack.org>
*/
#include <linux/config.h>
#include <linux/sched.h>
diff --git a/arch/m32r/kernel/setup.c b/arch/m32r/kernel/setup.c
index fb03be1a0c94c..4826cd6e40e8e 100644
--- a/arch/m32r/kernel/setup.c
+++ b/arch/m32r/kernel/setup.c
@@ -7,8 +7,6 @@
* Hitoshi Yamamoto
*/
-/* $Id$ */
-
#include <linux/config.h>
#include <linux/init.h>
#include <linux/stddef.h>
@@ -24,6 +22,9 @@
#include <linux/seq_file.h>
#include <linux/timex.h>
#include <linux/tty.h>
+#include <linux/cpu.h>
+#include <linux/nodemask.h>
+
#include <asm/processor.h>
#include <asm/pgtable.h>
#include <asm/io.h>
@@ -52,7 +53,7 @@ struct cpuinfo_m32r boot_cpu_data;
#ifdef CONFIG_BLK_DEV_RAM
extern int rd_doload; /* 1 = load ramdisk, 0 = don't load */
extern int rd_prompt; /* 1 = prompt for ramdisk, 0 = don't prompt */
-extern int rd_image_start; /* starting block # of image */
+extern int rd_image_start; /* starting block # of image */
#endif
#if defined(CONFIG_VGA_CONSOLE)
@@ -273,6 +274,21 @@ void __init setup_arch(char **cmdline_p)
paging_init();
}
+static struct cpu cpu[NR_CPUS];
+
+static int __init topology_init(void)
+{
+ int cpu_id;
+
+ for (cpu_id = 0; cpu_id < NR_CPUS; cpu_id++)
+ if (cpu_possible(cpu_id))
+ register_cpu(&cpu[cpu_id], cpu_id, NULL);
+
+ return 0;
+}
+
+subsys_initcall(topology_init);
+
#ifdef CONFIG_PROC_FS
/*
* Get CPU information for use by the procfs.
@@ -285,7 +301,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
#ifdef CONFIG_SMP
if (!cpu_online(cpu))
return 0;
-#endif /* CONFIG_SMP */
+#endif /* CONFIG_SMP */
seq_printf(m, "processor\t: %ld\n", cpu);
@@ -359,7 +375,7 @@ struct seq_operations cpuinfo_op = {
stop: c_stop,
show: show_cpuinfo,
};
-#endif /* CONFIG_PROC_FS */
+#endif /* CONFIG_PROC_FS */
unsigned long cpu_initialized __initdata = 0;
@@ -399,7 +415,6 @@ void __init cpu_init (void)
#endif
/* Set up ICUIMASK */
- outl(0x00070000, M32R_ICU_IMASK_PORTL); /* imask=111 */
+ outl(0x00070000, M32R_ICU_IMASK_PORTL); /* imask=111 */
}
-#endif /* defined(CONFIG_CHIP_VDEC2) ... */
-
+#endif /* defined(CONFIG_CHIP_VDEC2) ... */
diff --git a/arch/m32r/kernel/signal.c b/arch/m32r/kernel/signal.c
index d1f782517ad55..50311eb07a248 100644
--- a/arch/m32r/kernel/signal.c
+++ b/arch/m32r/kernel/signal.c
@@ -147,7 +147,7 @@ sys_rt_sigreturn(unsigned long r0, unsigned long r1,
stack_t st;
int result;
- if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
+ if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
goto badframe;
if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
goto badframe;
diff --git a/arch/m32r/kernel/smpboot.c b/arch/m32r/kernel/smpboot.c
index 5180c7a12a66d..f9a0e723478dd 100644
--- a/arch/m32r/kernel/smpboot.c
+++ b/arch/m32r/kernel/smpboot.c
@@ -81,9 +81,6 @@ static cpumask_t cpu_callin_map;
/* Per CPU bogomips and other parameters */
struct cpuinfo_m32r cpu_data[NR_CPUS] __cacheline_aligned;
-/* Set when the idlers are all forked */
-int smp_threads_ready;
-
static int cpucount;
static cpumask_t smp_commenced_mask;
@@ -106,8 +103,6 @@ spinlock_t ipi_lock[NR_IPIS];
static unsigned int calibration_result;
-unsigned long cache_decay_ticks = HZ / 100;
-
/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
/* Function Prototypes */
/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
diff --git a/arch/m32r/kernel/sys_m32r.c b/arch/m32r/kernel/sys_m32r.c
index 356e895fa0a89..e0500e12c5fbb 100644
--- a/arch/m32r/kernel/sys_m32r.c
+++ b/arch/m32r/kernel/sys_m32r.c
@@ -171,9 +171,9 @@ asmlinkage int sys_ipc(uint call, int first, int second,
case SHMAT: {
ulong raddr;
- if ((ret = verify_area(VERIFY_WRITE, (ulong __user *) third,
- sizeof(ulong))))
- return ret;
+ if (!access_ok(VERIFY_WRITE, (ulong __user *) third,
+ sizeof(ulong)))
+ return -EFAULT;
ret = do_shmat (first, (char __user *) ptr, second, &raddr);
if (ret)
return ret;
diff --git a/arch/m32r/kernel/traps.c b/arch/m32r/kernel/traps.c
index 8f9fd2f67e2e2..01922271d17ee 100644
--- a/arch/m32r/kernel/traps.c
+++ b/arch/m32r/kernel/traps.c
@@ -95,8 +95,10 @@ void set_eit_vector_entries(void)
eit_vector[31] = 0xff000000UL;
eit_vector[32] = BRA_INSN(ei_handler, 32);
eit_vector[64] = BRA_INSN(pie_handler, 64);
+#ifdef CONFIG_MMU
eit_vector[68] = BRA_INSN(ace_handler, 68);
eit_vector[72] = BRA_INSN(tme_handler, 72);
+#endif /* CONFIG_MMU */
#ifdef CONFIG_SMP
eit_vector[184] = (unsigned long)smp_reschedule_interrupt;
eit_vector[185] = (unsigned long)smp_invalidate_interrupt;
diff --git a/arch/m32r/mm/cache.c b/arch/m32r/mm/cache.c
index e2dd92d693808..31b0789c19922 100644
--- a/arch/m32r/mm/cache.c
+++ b/arch/m32r/mm/cache.c
@@ -4,8 +4,6 @@
* Copyright (C) 2002 Hirokazu Takata
*/
-/* $Id$ */
-
#include <linux/config.h>
#include <asm/pgtable.h>
@@ -25,8 +23,8 @@
#define MCCR_DCACHE_CBINV (MCCR_CC|MCCR_DIV|MCCR_DCB)
#define CHECK_MCCR(mccr) (mccr = *MCCR)
#elif defined(CONFIG_CHIP_M32102)
-#define MCCR ((volatile unsigned long*)0xfffffffc)
-#define MCCR_IIV (1UL << 8) /* I-cache invalidate */
+#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 */
@@ -65,4 +63,3 @@ void _flush_cache_copyback_all(void)
#endif
}
-
diff --git a/arch/m32r/mm/discontig.c b/arch/m32r/mm/discontig.c
index bf3104a159087..1d1a01e54b3fa 100644
--- a/arch/m32r/mm/discontig.c
+++ b/arch/m32r/mm/discontig.c
@@ -11,6 +11,7 @@
#include <linux/bootmem.h>
#include <linux/mmzone.h>
#include <linux/initrd.h>
+#include <linux/nodemask.h>
#include <asm/setup.h>
diff --git a/arch/m32r/mm/fault-nommu.c b/arch/m32r/mm/fault-nommu.c
index da267d843acfd..d9d488d782e8a 100644
--- a/arch/m32r/mm/fault-nommu.c
+++ b/arch/m32r/mm/fault-nommu.c
@@ -23,6 +23,7 @@
#include <linux/smp_lock.h>
#include <linux/interrupt.h>
#include <linux/init.h>
+#include <linux/vt_kern.h> /* For unblank_screen() */
#include <asm/m32r.h>
#include <asm/system.h>
diff --git a/arch/m32r/mm/init.c b/arch/m32r/mm/init.c
index ec968e453f79a..bc423d838fb82 100644
--- a/arch/m32r/mm/init.c
+++ b/arch/m32r/mm/init.c
@@ -121,8 +121,6 @@ unsigned long __init zone_sizes_init(void)
free_area_init_node(0, NODE_DATA(0), zones_size, start_pfn, 0);
- mem_map = contig_page_data.node_mem_map;
-
return 0;
}
#else /* CONFIG_DISCONTIGMEM */
diff --git a/arch/m68k/atari/stdma.c b/arch/m68k/atari/stdma.c
index 05f02e4fd8577..288f5e6a124eb 100644
--- a/arch/m68k/atari/stdma.c
+++ b/arch/m68k/atari/stdma.c
@@ -34,6 +34,7 @@
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/interrupt.h>
+#include <linux/wait.h>
#include <asm/atari_stdma.h>
#include <asm/atariints.h>
@@ -81,11 +82,10 @@ void stdma_lock(irqreturn_t (*handler)(int, void *, struct pt_regs *),
local_irq_save(flags); /* protect lock */
- while(stdma_locked)
- /* Since the DMA is used for file system purposes, we
- have to sleep uninterruptible (there may be locked
- buffers) */
- sleep_on(&stdma_wait);
+ /* Since the DMA is used for file system purposes, we
+ have to sleep uninterruptible (there may be locked
+ buffers) */
+ wait_event(stdma_wait, !stdma_locked);
stdma_locked = 1;
stdma_isr = handler;
diff --git a/arch/m68k/atari/stram.c b/arch/m68k/atari/stram.c
index 7ed86e722698f..5a3c106b40c83 100644
--- a/arch/m68k/atari/stram.c
+++ b/arch/m68k/atari/stram.c
@@ -635,7 +635,7 @@ static inline void unswap_pte(struct vm_area_struct * vma, unsigned long
set_pte(dir, pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
swap_free(entry);
get_page(page);
- ++vma->vm_mm->rss;
+ inc_mm_counter(vma->vm_mm, rss);
}
static inline void unswap_pmd(struct vm_area_struct * vma, pmd_t *dir,
diff --git a/arch/m68k/configs/sun3_defconfig b/arch/m68k/configs/sun3_defconfig
index 783d00cbb7072..33c4db63b72c0 100644
--- a/arch/m68k/configs/sun3_defconfig
+++ b/arch/m68k/configs/sun3_defconfig
@@ -730,6 +730,7 @@ CONFIG_CODA_FS=m
#
# CONFIG_PARTITION_ADVANCED is not set
CONFIG_MSDOS_PARTITION=y
+CONFIG_SUN_PARTITION=y
#
# Native Language Support
diff --git a/arch/m68k/configs/sun3x_defconfig b/arch/m68k/configs/sun3x_defconfig
index c25f91347893e..fe008c9b10c13 100644
--- a/arch/m68k/configs/sun3x_defconfig
+++ b/arch/m68k/configs/sun3x_defconfig
@@ -740,6 +740,7 @@ CONFIG_CODA_FS=m
#
# CONFIG_PARTITION_ADVANCED is not set
CONFIG_MSDOS_PARTITION=y
+CONFIG_SUN_PARTITION=y
#
# Native Language Support
diff --git a/arch/m68k/kernel/signal.c b/arch/m68k/kernel/signal.c
index 4a319bdef9572..9c636a4c238d5 100644
--- a/arch/m68k/kernel/signal.c
+++ b/arch/m68k/kernel/signal.c
@@ -130,7 +130,7 @@ sys_sigaction(int sig, const struct old_sigaction *act,
if (act) {
old_sigset_t mask;
- if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
+ if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
__get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
__get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
return -EFAULT;
@@ -142,7 +142,7 @@ sys_sigaction(int sig, const struct old_sigaction *act,
ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
if (!ret && oact) {
- if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
+ if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
__put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
__put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
return -EFAULT;
@@ -510,7 +510,7 @@ asmlinkage int do_sigreturn(unsigned long __unused)
sigset_t set;
int d0;
- if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
+ if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
goto badframe;
if (__get_user(set.sig[0], &frame->sc.sc_mask) ||
(_NSIG_WORDS > 1 &&
@@ -540,7 +540,7 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused)
sigset_t set;
int d0;
- if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
+ if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
goto badframe;
if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
goto badframe;
@@ -951,6 +951,21 @@ handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler)
}
}
+void ptrace_signal_deliver(struct pt_regs *regs, void *cookie)
+{
+ if (regs->orig_d0 < 0)
+ return;
+ switch (regs->d0) {
+ case -ERESTARTNOHAND:
+ case -ERESTARTSYS:
+ case -ERESTARTNOINTR:
+ regs->d0 = regs->orig_d0;
+ regs->orig_d0 = -1;
+ regs->pc -= 2;
+ break;
+ }
+}
+
/*
* OK, we're invoking a handler
*/
@@ -982,133 +997,22 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
* Note that 'init' is a special process: it doesn't get signals it doesn't
* want to handle. Thus you cannot kill init even with a SIGKILL even by
* mistake.
- *
- * Note that we go through the signals twice: once to check the signals
- * that the kernel can handle, and then we build all the user-level signal
- * handling stack-frames in one go after that.
*/
asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs)
{
siginfo_t info;
- struct k_sigaction *ka;
+ struct k_sigaction ka;
+ int signr;
current->thread.esp0 = (unsigned long) regs;
if (!oldset)
oldset = &current->blocked;
- for (;;) {
- int signr;
-
- signr = dequeue_signal(current, &current->blocked, &info);
-
- if (!signr)
- break;
-
- if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
- current->exit_code = signr;
- current->state = TASK_STOPPED;
- regs->sr &= ~PS_T;
-
- /* Did we come from a system call? */
- if (regs->orig_d0 >= 0) {
- /* Restart the system call the same way as
- if the process were not traced. */
- struct k_sigaction *ka =
- &current->sighand->action[signr-1];
- int has_handler =
- (ka->sa.sa_handler != SIG_IGN &&
- ka->sa.sa_handler != SIG_DFL);
- handle_restart(regs, ka, has_handler);
- }
- notify_parent(current, SIGCHLD);
- schedule();
-
- /* We're back. Did the debugger cancel the sig? */
- if (!(signr = current->exit_code)) {
- discard_frame:
- /* Make sure that a faulted bus cycle isn't
- restarted (only needed on the 680[23]0). */
- if (regs->format == 10 || regs->format == 11)
- regs->stkadj = frame_extra_sizes[regs->format];
- continue;
- }
- current->exit_code = 0;
-
- /* The debugger continued. Ignore SIGSTOP. */
- if (signr == SIGSTOP)
- goto discard_frame;
-
- /* Update the siginfo structure. Is this good? */
- if (signr != info.si_signo) {
- info.si_signo = signr;
- info.si_errno = 0;
- info.si_code = SI_USER;
- info.si_pid = current->parent->pid;
- info.si_uid = current->parent->uid;
- info.si_uid16 = high2lowuid(current->parent->uid);
- }
-
- /* If the (new) signal is now blocked, requeue it. */
- if (sigismember(&current->blocked, signr)) {
- send_sig_info(signr, &info, current);
- continue;
- }
- }
-
- ka = &current->sighand->action[signr-1];
- if (ka->sa.sa_handler == SIG_IGN) {
- if (signr != SIGCHLD)
- continue;
- /* Check for SIGCHLD: it's special. */
- while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0)
- /* nothing */;
- continue;
- }
-
- if (ka->sa.sa_handler == SIG_DFL) {
- int exit_code = signr;
-
- if (current->pid == 1)
- continue;
-
- switch (signr) {
- case SIGCONT: case SIGCHLD:
- case SIGWINCH: case SIGURG:
- continue;
-
- case SIGTSTP: case SIGTTIN: case SIGTTOU:
- if (is_orphaned_pgrp(process_group(current)))
- continue;
- /* FALLTHRU */
-
- case SIGSTOP: {
- struct sighand_struct *sighand;
- current->state = TASK_STOPPED;
- current->exit_code = signr;
- sighand = current->parent->sighand;
- if (sighand && !(sighand->action[SIGCHLD-1].sa.sa_flags
- & SA_NOCLDSTOP))
- notify_parent(current, SIGCHLD);
- schedule();
- continue;
- }
-
- case SIGQUIT: case SIGILL: case SIGTRAP:
- case SIGIOT: case SIGFPE: case SIGSEGV:
- case SIGBUS: case SIGSYS: case SIGXCPU: case SIGXFSZ:
- if (do_coredump(signr, exit_code, regs))
- exit_code |= 0x80;
- /* FALLTHRU */
-
- default:
- do_group_exit(signr);
- /* NOTREACHED */
- }
- }
-
+ signr = get_signal_to_deliver(&info, &ka, regs, NULL);
+ if (signr > 0) {
/* Whee! Actually deliver the signal. */
- handle_signal(signr, ka, &info, oldset, regs);
+ handle_signal(signr, &ka, &info, oldset, regs);
return 1;
}
@@ -1117,18 +1021,5 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs)
/* Restart the system call - no handlers present */
handle_restart(regs, NULL, 0);
- /* If we are about to discard some frame stuff we must copy
- over the remaining frame. */
- if (regs->stkadj) {
- struct pt_regs *tregs =
- (struct pt_regs *) ((ulong) regs + regs->stkadj);
-
- /* This must be copied with decreasing addresses to
- handle overlaps. */
- tregs->vector = 0;
- tregs->format = 0;
- tregs->pc = regs->pc;
- tregs->sr = regs->sr;
- }
return 0;
}
diff --git a/arch/m68knommu/Makefile b/arch/m68knommu/Makefile
index 2524de27235c8..a254aa9d49986 100644
--- a/arch/m68knommu/Makefile
+++ b/arch/m68knommu/Makefile
@@ -43,7 +43,6 @@ BOARD := $(board-y)
model-$(CONFIG_RAMKERNEL) := ram
model-$(CONFIG_ROMKERNEL) := rom
-model-$(CONFIG_HIMEMKERNEL) := himem
MODEL := $(model-y)
#
@@ -58,12 +57,15 @@ cpuclass-$(CONFIG_M5249) := 5307
cpuclass-$(CONFIG_M527x) := 5307
cpuclass-$(CONFIG_M5272) := 5307
cpuclass-$(CONFIG_M528x) := 5307
+cpuclass-$(CONFIG_M5307) := 5307
cpuclass-$(CONFIG_M5407) := 5307
+cpuclass-$(CONFIG_M68328) := 68328
cpuclass-$(CONFIG_M68EZ328) := 68328
cpuclass-$(CONFIG_M68VZ328) := 68328
+cpuclass-$(CONFIG_M68360) := 68360
CPUCLASS := $(cpuclass-y)
-ifneq ($(CPUCLASS),)
+ifneq ($(CPUCLASS),$(PLATFORM))
CLASSDIR := arch/m68knommu/platform/$(cpuclass-y)/
endif
@@ -93,7 +95,7 @@ CFLAGS += -O1 -g
CFLAGS += -D__linux__
CFLAGS += -DUTS_SYSNAME=\"uClinux\"
-head-y := arch/m68knommu/platform/$(platform-y)/$(board-y)/crt0_$(model-y).o
+head-y := arch/m68knommu/platform/$(cpuclass-y)/head.o
CLEAN_FILES := include/asm-$(ARCH)/asm-offsets.h \
arch/$(ARCH)/kernel/asm-offsets.s
diff --git a/arch/m68knommu/kernel/asm-offsets.c b/arch/m68knommu/kernel/asm-offsets.c
index 02c56f5385316..cd3ffe12653e1 100644
--- a/arch/m68knommu/kernel/asm-offsets.c
+++ b/arch/m68knommu/kernel/asm-offsets.c
@@ -15,6 +15,7 @@
#include <linux/hardirq.h>
#include <asm/bootinfo.h>
#include <asm/irq.h>
+#include <asm/thread_info.h>
#define DEFINE(sym, val) \
asm volatile("\n->" #sym " %0 " #val : : "i" (val))
@@ -63,10 +64,13 @@ int main(void)
DEFINE(PT_A2, offsetof(struct pt_regs, a2));
DEFINE(PT_PC, offsetof(struct pt_regs, pc));
DEFINE(PT_SR, offsetof(struct pt_regs, sr));
+
+#ifdef CONFIG_COLDFIRE
+ /* bitfields are a bit difficult */
+ DEFINE(PT_FORMATVEC, offsetof(struct pt_regs, sr) - 2);
+#else
/* bitfields are a bit difficult */
DEFINE(PT_VECTOR, offsetof(struct pt_regs, pc) + 4);
-
-#ifndef CONFIG_COLDFIRE
/* offsets into the irq_handler struct */
DEFINE(IRQ_HANDLER, offsetof(struct irq_node, handler));
DEFINE(IRQ_DEVID, offsetof(struct irq_node, dev_id));
@@ -85,5 +89,13 @@ int main(void)
DEFINE(PT_PTRACED, PT_PTRACED);
DEFINE(PT_DTRACE, PT_DTRACE);
+ DEFINE(THREAD_SIZE, THREAD_SIZE);
+
+ /* Offsets in thread_info structure */
+ DEFINE(TI_TASK, offsetof(struct thread_info, task));
+ DEFINE(TI_EXECDOMAIN, offsetof(struct thread_info, exec_domain));
+ DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
+ DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
+
return 0;
}
diff --git a/arch/m68knommu/kernel/entry.S b/arch/m68knommu/kernel/entry.S
index 2f66048153c0b..8b1f47239b9a1 100644
--- a/arch/m68knommu/kernel/entry.S
+++ b/arch/m68knommu/kernel/entry.S
@@ -47,7 +47,7 @@
ENTRY(buserr)
SAVE_ALL
moveq #-1,%d0
- movel %d0,%sp@(LORIG_D0)
+ movel %d0,%sp@(PT_ORIG_D0)
movel %sp,%sp@- /* stack frame pointer argument */
jsr buserr_c
addql #4,%sp
@@ -56,7 +56,7 @@ ENTRY(buserr)
ENTRY(trap)
SAVE_ALL
moveq #-1,%d0
- movel %d0,%sp@(LORIG_D0)
+ movel %d0,%sp@(PT_ORIG_D0)
movel %sp,%sp@- /* stack frame pointer argument */
jsr trap_c
addql #4,%sp
@@ -68,7 +68,7 @@ ENTRY(trap)
ENTRY(dbginterrupt)
SAVE_ALL
moveq #-1,%d0
- movel %d0,%sp@(LORIG_D0)
+ movel %d0,%sp@(PT_ORIG_D0)
movel %sp,%sp@- /* stack frame pointer argument */
jsr dbginterrupt_c
addql #4,%sp
diff --git a/arch/m68knommu/kernel/signal.c b/arch/m68knommu/kernel/signal.c
index c19722c5dcf2a..30dceb59a4620 100644
--- a/arch/m68knommu/kernel/signal.c
+++ b/arch/m68knommu/kernel/signal.c
@@ -116,7 +116,7 @@ sys_sigaction(int sig, const struct old_sigaction *act,
if (act) {
old_sigset_t mask;
- if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
+ if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
__get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
__get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
return -EFAULT;
@@ -128,7 +128,7 @@ sys_sigaction(int sig, const struct old_sigaction *act,
ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
if (!ret && oact) {
- if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
+ if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
__put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
__put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
return -EFAULT;
@@ -360,7 +360,7 @@ asmlinkage int do_sigreturn(unsigned long __unused)
sigset_t set;
int d0;
- if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
+ if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
goto badframe;
if (__get_user(set.sig[0], &frame->sc.sc_mask) ||
(_NSIG_WORDS > 1 &&
@@ -392,7 +392,7 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused)
sigset_t set;
int d0;
- if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
+ if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
goto badframe;
if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
goto badframe;
diff --git a/arch/m68knommu/platform/5206/ARNEWSH/crt0_ram.S b/arch/m68knommu/platform/5206/ARNEWSH/crt0_ram.S
deleted file mode 100644
index b8d893e65ee49..0000000000000
--- a/arch/m68knommu/platform/5206/ARNEWSH/crt0_ram.S
+++ /dev/null
@@ -1,213 +0,0 @@
-/*****************************************************************************/
-
-/*
- * crt0_ram.S -- startup code for MCF5206 ColdFire Arnewsh board.
- *
- * (C) Copyright 1999-2002, Greg Ungerer (gerg@snapgear.com).
- *
- * 1999/02/24 Modified for the 5307 processor David W. Miller
- */
-
-/*****************************************************************************/
-
-#include "linux/autoconf.h"
-#include "asm/coldfire.h"
-#include "asm/mcfsim.h"
-
-/*****************************************************************************/
-
-/*
- * Arnewsh m5206 ColdFire eval board, chip select and memory setup.
- */
-
-#define MEM_BASE 0x00000000 /* Memory base at address 0 */
-#define VBR_BASE MEM_BASE /* Vector address */
-
-/*
- * The following define the limits within which to search for
- * available RAM.
- */
-#define MEM_MIN 0x00100000 /* Search from 1Mb */
-#define MEM_MAX 0x02000000 /* Max DRAM 32Mb! */
-#define MEM_LUMP 0x00010000 /* 64 Kb chunks */
-
-#define MEM_TMPSTACK 0x00010000 /* At 64k - for exceptions */
-
-/*
- * Chip Select setup.
- */
-#define CS0_ADDR 0x0000f000 /* CS0 connected to Flash ROM */
-#define CS0_MASK 0xf0000000 /* is 1Mbyte */
-#define CS0_CTRL 0x00000000 /* read-only */
-#define CS1_ADDR 0x00000000 /* CS1 not connected */
-#define CS1_MASK 0x00000000
-#define CS1_CTRL 0x00000000
-#define CS2_ADDR 0x00003000 /* CS2 connected to SRAM */
-#define CS2_MASK 0x0000f000 /* is 1Mbyte */
-#define CS2_CTRL 0x00001903 /* read-write */
-#define CS3_ADDR 0x00004000 /* CS3 connected to LED, par port */
-#define CS3_MASK 0x0000f000 /* is 1Mbyte */
-#define CS3_CTRL 0x00000083 /* read-write */
-#define CS4_ADDR 0x00000000 /* CS4 not connected */
-#define CS4_MASK 0x00000000
-#define CS4_CTRL 0x00000123
-#define CS5_ADDR 0x00000000 /* CS5 not connected */
-#define CS5_MASK 0x00000000
-#define CS5_CTRL 0x00000000
-#define CS6_ADDR 0x00000000 /* CS6 not connected */
-#define CS6_MASK 0x00000000
-#define CS6_CTRL 0x00000000
-#define CS7_ADDR 0x00000000 /* CS7 not connected */
-#define CS7_MASK 0x00000000
-#define CS7_CTRL 0x00000000
-#define DMC_CTRL 0x00000000 /* default memory control */
-
-/*****************************************************************************/
-
-.global _start
-.global _rambase
-.global _ramvec
-.global _ramstart
-.global _ramend
-
-/*****************************************************************************/
-
-.data
-
-/*
- * Set up the usable of RAM stuff. Size of RAM is determined then
- * an initial stack set up at the end.
- */
-_rambase:
-.long 0
-_ramvec:
-.long 0
-_ramstart:
-.long 0
-_ramend:
-.long 0
-
-/*****************************************************************************/
-
-.text
-
-/*
- * This is the codes first entry point. This is where it all
- * begins...
- */
-
-_start:
- nop /* Filler */
- move.w #0x2700, %sr /* No interrupts */
-
-
- /*
- * Setup VBR here, otherwise buserror remap will not work.
- * if dBug was active before (on my SBC with dBug 1.1 of Dec 16 1996)
- *
- * bkr@cut.de 19990306
- *
- * Note: this is because dBUG points VBR to ROM, making vectors read
- * only, so the bus trap can't be changed. (RS)
- */
- move.l #VBR_BASE, %a7 /* Note VBR can't be read */
- movec %a7, %VBR
- move.l %a7, _ramvec /* Set up vector addr */
- move.l %a7, _rambase /* Set up base RAM addr */
-
-
- /*
- * Determine size of RAM, then set up initial stack.
- *
- * On the Arnewsh 5206 board we can probe for the amount
- * of DRAM present...
- */
- move.l #MEM_MIN, %a0 /* Start at bottom */
- move.l #MEM_MAX, %a1 /* Set stop point */
- lea.l MEM_TMPSTACK, %sp /* Set up tmp stack ptr */
-
- move.l #VBR_BASE+8, %a2 /* Address of bus trap */
- lea.l _ram_buserr, %a3 /* Get RAM trap address */
- move.l %a3, (%a2) /* Set trap to local ptr */
-
-_find_ram:
- move.l (%a0), %d0 /* Attempt read */
- add.l #MEM_LUMP, %a0 /* Try next bank */
- cmp.l %a1, %a0 /* Check more? */
- bne _find_ram
-
- /*
- * BUS error trap handler - used for RAM probing.
- */
-_ram_buserr:
- bra _found_ram
-
-_found_ram: /* Vectored here on bus err */
- move.l %a0, %d0 /* Mem end addr is in a0 */
- move.l %d0, %sp /* Set up initial stack ptr */
- move.l %d0, _ramend /* Set end ram addr */
-
-
- /*
- * Enable CPU internal cache.
- */
- move.l #0x01000000, %d0 /* Invalidate cache cmd */
- movec %d0, %CACR /* Invalidate cache */
- move.l #0x80000100, %d0 /* Setup cache mask */
- movec %d0, %CACR /* Enable cache */
-
-
-#ifdef CONFIG_ROMFS_FS
- /*
- * Move ROM filesystem above bss :-)
- */
- lea.l _sbss, %a0 /* Get start of bss */
- lea.l _ebss, %a1 /* Set up destination */
- move.l %a0, %a2 /* Copy of bss start */
-
- move.l 8(%a0), %d0 /* Get size of ROMFS */
- addq.l #8, %d0 /* Allow for rounding */
- and.l #0xfffffffc, %d0 /* Whole words */
-
- add.l %d0, %a0 /* Copy from end */
- add.l %d0, %a1 /* Copy from end */
- move.l %a1, _ramstart /* Set start of ram */
-
-_copy_romfs:
- move.l -(%a0), %d0 /* Copy dword */
- move.l %d0, -(%a1)
- cmp.l %a0, %a2 /* Check if at end */
- bne _copy_romfs
-
-#else /* CONFIG_ROMFS_FS */
- lea.l _ebss, %a1
- move.l %a1, _ramstart
-#endif /* CONFIG_ROMFS_FS */
-
-
- /*
- * Zero out the bss region.
- */
- lea.l _sbss, %a0 /* Get start of bss */
- lea.l _ebss, %a1 /* Get end of bss */
- clr.l %d0 /* Set value */
-_clear_bss:
- move.l %d0, (%a0)+ /* Clear each word */
- cmp.l %a0, %a1 /* Check if at end */
- bne _clear_bss
-
- /*
- * Load the current task pointer and stack.
- */
- lea init_thread_union, %a0
- lea 0x2000(%a0), %sp
-
- /*
- * Assember start up done, start code proper.
- */
- jsr start_kernel /* Start Linux kernel */
-
-_exit:
- jmp _exit /* Should never get here */
-
-/*****************************************************************************/
diff --git a/arch/m68knommu/platform/5206/Makefile b/arch/m68knommu/platform/5206/Makefile
index 74281a5d6bea8..701b7abe019d8 100644
--- a/arch/m68knommu/platform/5206/Makefile
+++ b/arch/m68knommu/platform/5206/Makefile
@@ -18,4 +18,3 @@ endif
obj-y := config.o
-extra-y := $(BOARD)/crt0_$(MODEL).o
diff --git a/arch/m68knommu/platform/5206e/MOTOROLA/crt0_ram.S b/arch/m68knommu/platform/5206e/MOTOROLA/crt0_ram.S
deleted file mode 100644
index 2049f44fd2892..0000000000000
--- a/arch/m68knommu/platform/5206e/MOTOROLA/crt0_ram.S
+++ /dev/null
@@ -1,178 +0,0 @@
-/*****************************************************************************/
-
-/*
- * crt0_ram.S -- startup code for MCF5206e ColdFire based CADRE3 boards.
- *
- * (C) Copyright 1999-2002, Greg Ungerer (gerg@snapgear.com)
- *
- * 1999/02/24 Modified for the 5307 processor David W. Miller
- */
-
-/*****************************************************************************/
-
-#include "linux/autoconf.h"
-#include "asm/coldfire.h"
-#include "asm/mcfsim.h"
-
-/*****************************************************************************/
-
-/*
- * Cadre-III M5206e ColdFire eval board, chip select and memory setup.
- */
-
-#define MEM_BASE 0x00000000 /* Memory base at address 0 */
-#define VBR_BASE MEM_BASE /* Vector address */
-
-/*****************************************************************************/
-
-.global _start
-.global _rambase
-.global _ramvec
-.global _ramstart
-.global _ramend
-
-/*****************************************************************************/
-
-.data
-
-/*
- * Set up the usable of RAM stuff. Size of RAM is determined then
- * an initial stack set up at the end.
- */
-_rambase:
-.long 0
-_ramvec:
-.long 0
-_ramstart:
-.long 0
-_ramend:
-.long 0
-
-/*****************************************************************************/
-
-.text
-
-/*
- * This is the codes first entry point. This is where it all
- * begins...
- */
-
-_start:
- nop /* Filler */
- move.w #0x2700, %sr /* No interrupts */
-
- /*
- * Setup VBR here, otherwise buserror remap will not work.
- * if dBug was active before (on my SBC with dBug 1.1 of Dec 16 1996)
- *
- * bkr@cut.de 19990306
- *
- * Note: this is because dBUG points VBR to ROM, making vectors read
- * only, so the bus trap can't be changed. (RS)
- */
- move.l #VBR_BASE, %a7 /* Note VBR can't be read */
- movec %a7, %VBR
- move.l %a7, _ramvec /* Set up vector addr */
- move.l %a7, _rambase /* Set up base RAM addr */
-
-
- /*
- * SDRAM size for the Cadre III board (m5206e).
- */
-#if defined(CONFIG_RAMAUTO)
- movea.l #0x00000000,%a0
- move.l MCF_MBAR+MCFSIM_DCMR0,%d0
- and.l #0x00fe0000, %d0
- beq noaddr1
- add.l #0x00020000,%d0
- move.l %d0,%a0
-noaddr1:
- move.l MCF_MBAR+MCFSIM_DCMR1,%d0
- and.l #0x00fe0000, %d0
- beq noaddr2
- add.l #0x00020000,%d0
- add.l %d0,%a0
-noaddr2:
-
-#else
-
-#if defined(CONFIG_RAM32MB)
-#define MEM_SIZE 0x02000000 /* Memory size 32Mb */
-#elif defined(CONFIG_RAM16MB)
-#define MEM_SIZE 0x01000000 /* Memory size 16Mb */
-#elif defined(CONFIG_RAM8MB)
-#define MEM_SIZE 0x00800000 /* Memory size 8Mb */
-#else
-#define MEM_SIZE 0x00400000 /* Memory size 4Mb */
-#endif
- move.l #MEM_SIZE, %a0
-#endif
-
- move.l %a0, %d0 /* Mem end addr is in a0 */
- move.l %d0, %sp /* Set up initial stack ptr */
- move.l %d0, _ramend /* Set end ram addr */
-
-
- /*
- * Enable CPU internal cache.
- */
- move.l #0x01000000, %d0 /* Invalidate cache cmd */
- movec %d0, %CACR /* Invalidate cache */
- move.l #0x80000100, %d0 /* Setup cache mask */
- movec %d0, %CACR /* Enable cache */
-
-
-#ifdef CONFIG_ROMFS_FS
- /*
- * Move ROM filesystem above bss :-)
- */
- lea.l _sbss, %a0 /* Get start of bss */
- lea.l _ebss, %a1 /* Set up destination */
- move.l %a0, %a2 /* Copy of bss start */
-
- move.l 8(%a0), %d0 /* Get size of ROMFS */
- addq.l #8, %d0 /* Allow for rounding */
- and.l #0xfffffffc, %d0 /* Whole words */
-
- add.l %d0, %a0 /* Copy from end */
- add.l %d0, %a1 /* Copy from end */
- move.l %a1, _ramstart /* Set start of ram */
-
-_copy_romfs:
- move.l -(%a0), %d0 /* Copy dword */
- move.l %d0, -(%a1)
- cmp.l %a0, %a2 /* Check if at end */
- bne _copy_romfs
-
-#else /* CONFIG_ROMFS_FS */
- lea.l _ebss, %a1
- move.l %a1, _ramstart
-#endif /* CONFIG_ROMFS_FS */
-
-
- /*
- * Zero out the bss region.
- */
- lea.l _sbss, %a0 /* Get start of bss */
- lea.l _ebss, %a1 /* Get end of bss */
- clr.l %d0 /* Set value */
-_clear_bss:
- move.l %d0, (%a0)+ /* Clear each word */
- cmp.l %a0, %a1 /* Check if at end */
- bne _clear_bss
-
- /*
- * Load the current task pointer and stack.
- */
- lea init_thread_union, %a0
- lea 0x2000(%a0), %sp
-
- /*
- * Assember start up done, start code proper.
- */
- jsr start_kernel /* Start Linux kernel */
-
-_exit:
- jmp _exit /* Should never get here */
-
-/*****************************************************************************/
diff --git a/arch/m68knommu/platform/5206e/Makefile b/arch/m68knommu/platform/5206e/Makefile
index 74281a5d6bea8..701b7abe019d8 100644
--- a/arch/m68knommu/platform/5206e/Makefile
+++ b/arch/m68knommu/platform/5206e/Makefile
@@ -18,4 +18,3 @@ endif
obj-y := config.o
-extra-y := $(BOARD)/crt0_$(MODEL).o
diff --git a/arch/m68knommu/platform/5206e/eLITE/crt0_ram.S b/arch/m68knommu/platform/5206e/eLITE/crt0_ram.S
deleted file mode 100644
index 3cf4464bbe282..0000000000000
--- a/arch/m68knommu/platform/5206e/eLITE/crt0_ram.S
+++ /dev/null
@@ -1,346 +0,0 @@
-/*****************************************************************************/
-
-/*
- * crt0_ram.S -- startup code for MCF5206e ColdFire based eLITE boards.
- *
- * (C) Copyright 1999-2002, Greg Ungerer (gerg@snapgear.com).
- * Copyright (C) 1999 Rob Scott (rscott@mtrob.fdns.net)
- *
- * 1999/02/24 Modified for the 5307 processor David W. Miller
- */
-
-/*****************************************************************************/
-
-#include "linux/autoconf.h"
-#include "asm/coldfire.h"
-#include "asm/mcfsim.h"
-
-/*****************************************************************************/
-
-/*
- * M5206eLITE ColdFire eval board, chip select and memory setup.
- */
-
-#ifdef CONFIG_SMALL
-#define MEM_BASE 0x30000000 /* Base memory for M5206eLITE */
-#define MEM_RESERVED 0x00020000 /* Don't use memory reserved by dBUG */
-#define MEM_SIZE 0x00100000 /* 1 MB of SRAM on M5206eLITE */
-#else
-#define MEM_BASE 0x00000000 /* Base memory for M5206eLITE */
-#define MEM_RESERVED 0x00010000 /* Skip first MEM_LUMP for colilo */
-#define MEM_SIZE 0x02000000 /* Max DRAM 32Mb */
-#endif
-#define MEM_MIN MEM_BASE+MEM_RESERVED
-/* Define end of probeable memory space */
-#define MEM_MAX MEM_BASE+MEM_SIZE
-#define MEM_BUILTIN 0x20000000 /* Put built in SRAM at dBUG loc */
-#define MEM_TMPSTACK MEM_BUILTIN+0x800 /* Use built in SRAM for tmp stack */
-#define MEM_LUMP 0x00010000 /* 64 Kb chunks */
-#define VBR_BASE MEM_BUILTIN /* Use built in SRAM for vectors */
-
-#define CS0_ADDR 0x0000ffe0 /* CS0 connected to Flash ROM */
-#define CS0_MASK 0x000f0000 /* is 1Mbyte */
-#define CS0_CTRL 0x00001da3 /* read-write (for flash) */
-#define CS1_ADDR 0x00000000 /* CS1 not connected */
-#define CS1_MASK 0x00000000
-#define CS1_CTRL 0x00000000
-#define CS2_ADDR 0x00003000 /* CS2 connected to SRAM */
-#define CS2_MASK 0x000f0000 /* is 1Mbyte */
-#define CS2_CTRL 0x00001903 /* read-write */
-#define CS3_ADDR 0x00004000 /* CS3 connected to LED, par port */
-#define CS3_MASK 0x000f0000 /* is 1Mbyte */
-#define CS3_CTRL 0x00000183 /* read-write */
-#define CS4_ADDR 0x00000000 /* CS4 not connected */
-#define CS4_MASK 0x00000000
-#define CS4_CTRL 0x00000000
-#define CS5_ADDR 0x00000000 /* CS5 not connected */
-#define CS5_MASK 0x00000000
-#define CS5_CTRL 0x00000000
-#define CS6_ADDR 0x00000000 /* CS6 not connected */
-#define CS6_MASK 0x00000000
-#define CS6_CTRL 0x00000000
-#define CS7_ADDR 0x00000000 /* CS7 not connected */
-#define CS7_MASK 0x00000000
-#define CS7_CTRL 0x00000000
-#define DMC_CTRL 0x00000000 /* default memory control */
-
-#define DCRR 0x00000034 /* Refresh period */
-/* DCTR definition:
- <15>: DAEM, 1 = Drive Multiplexed Address During External Master DRAM xfer
- <14>: EDO, 1 = EDO, 0 = Normal
- <12>: RCD, 1 = 2 clk RAS-to-CAS, 0 = 1.0 clk RAS-to-CAS
- <10:09>: RSH, 10 = 3.5 clk RAS low, 01 = 2.5 clk, 00 = 1.5 clk
- <06:05>: RP, 10 = 3.5 clk RAS Precharge, 01 = 2.5 clk, 00 = 1.5 clk
- <03>: CAS, 1 = 2.5 clk CAS assertion, 0 = 1.5 clk
- <01>: CP, 1 = 1.5 CAS clk precharge, 0 = .5 clk
- <00>: CSR, 1 = 2.0 clk CAS before RAS setup, 0 = 1.0 clk
-*/
-#define DCTR 0x0000144B /* Slow DRAM */
-#define DCAR0 0x00000000 /* DRAM0 address, 0 base addr */
-#define DCMR0 0x003e0000 /* DRAM0 mask, 4Mb DRAM */
-#define DCCR0 0x00000007 /* DRAM0 control, R/W, burst pg mde */
-#define DCAR1 0x00000000 /* DRAM1 address, 0 base addr */
-#define DCMR1 0x00000000 /* DRAM1 mask, no DRAM */
-#define DCCR1 0x00000000 /* DRAM1 control, off */
-
-/*****************************************************************************/
-
-.global _start
-.global _rambase
-.global _ramvec
-.global _ramstart
-.global _ramend
-
-/*****************************************************************************/
-
-.data
-
-/*
- * Set up the usable of RAM stuff. Size of RAM is determined then
- * an initial stack set up at the end.
- */
-_rambase:
-.long 0
-_ramvec:
-.long 0
-_ramstart:
-.long 0
-_ramend:
-.long 0
-
-/*****************************************************************************/
-
-.text
-
-/*
- * This is the codes first entry point. This is where it all
- * begins...
- */
-
-_start:
- nop /* Filler */
- move.w #0x2700, %sr /* No interrupts */
-
- move.l #MCF_MBAR+1, %a0 /* Set I/O base addr */
- movec %a0, %MBAR /* Note: bit 0 is Validate */
- move.l #MEM_BUILTIN+1,%a0 /* Set SRAM base addr */
- movec %a0, %RAMBAR0 /* Note: bit 0 is Validate */
-
- move.l #MCF_MBAR, %a0 /* Get I/O base addr */
-
- /* ----------------------- CS1 ----------------------- */
- move.w #CS1_ADDR, %d0 /* CS1 address */
- move.w %d0, MCFSIM_CSAR1(%a0) /* CS1 address */
- move.l #CS1_MASK, %d0 /* CS1 mask */
- move.l %d0, MCFSIM_CSMR1(%a0) /* CS1 mask */
- move.w #CS1_CTRL, %d0 /* CS1 control */
- move.w %d0, MCFSIM_CSCR1(%a0) /* CS1 control */
-
- /* ----------------------- CS2 ----------------------- */
- move.w #CS2_ADDR, %d0 /* CS2 address */
- move.w %d0, MCFSIM_CSAR2(%a0) /* CS2 address */
- move.l #CS2_MASK, %d0 /* CS2 mask */
- move.l %d0, MCFSIM_CSMR2(%a0) /* CS2 mask */
- move.w #CS2_CTRL, %d0 /* CS2 control */
- move.w %d0, MCFSIM_CSCR2(%a0) /* CS2 control */
-
- /* ----------------------- CS3 ----------------------- */
- move.w #CS3_ADDR, %d0 /* CS3 address */
- move.w %d0, MCFSIM_CSAR3(%a0) /* CS3 address */
- move.l #CS3_MASK, %d0 /* CS3 mask */
- move.l %d0, MCFSIM_CSMR3(%a0) /* CS3 mask */
- move.w #CS3_CTRL, %d0 /* CS3 control */
- move.w %d0, MCFSIM_CSCR3(%a0) /* CS3 control */
-
- /* ----------------------- CS4 ----------------------- */
- move.w #CS4_ADDR, %d0 /* CS4 address */
- move.w %d0, MCFSIM_CSAR4(%a0) /* CS4 address */
- move.l #CS4_MASK, %d0 /* CS4 mask */
- move.l %d0, MCFSIM_CSMR4(%a0) /* CS4 mask */
- move.w #CS4_CTRL, %d0 /* CS4 control */
- move.w %d0, MCFSIM_CSCR4(%a0) /* CS4 control */
-
- /* ----------------------- CS5 ----------------------- */
- move.w #CS5_ADDR, %d0 /* CS5 address */
- move.w %d0, MCFSIM_CSAR5(%a0) /* CS5 address */
- move.l #CS5_MASK, %d0 /* CS5 mask */
- move.l %d0, MCFSIM_CSMR5(%a0) /* CS5 mask */
- move.w #CS5_CTRL, %d0 /* CS5 control */
- move.w %d0, MCFSIM_CSCR5(%a0) /* CS5 control */
-
- /* ----------------------- CS6 ----------------------- */
- move.w #CS6_ADDR, %d0 /* CS6 address */
- move.w %d0, MCFSIM_CSAR6(%a0) /* CS6 address */
- move.l #CS6_MASK, %d0 /* CS6 mask */
- move.l %d0, MCFSIM_CSMR6(%a0) /* CS6 mask */
- move.w #CS6_CTRL, %d0 /* CS6 control */
- move.w %d0, MCFSIM_CSCR6(%a0) /* CS6 control */
-
- /* ----------------------- CS7 ----------------------- */
- move.w #CS7_ADDR, %d0 /* CS7 address */
- move.w %d0, MCFSIM_CSAR7(%a0) /* CS7 address */
- move.l #CS7_MASK, %d0 /* CS7 mask */
- move.l %d0, MCFSIM_CSMR7(%a0) /* CS7 mask */
- move.w #CS7_CTRL, %d0 /* CS7 control */
- move.w %d0, MCFSIM_CSCR7(%a0) /* CS7 control */
-
- /* --------------------- Default --------------------- */
- move.w #DMC_CTRL, %d0 /* Default control */
- move.w %d0, MCFSIM_DMCR(%a0) /* Default control */
-
- /* ----------------------- DRAM ------------------------ */
- move.w #DCRR, %d0 /* Refresh period */
- move.w %d0, MCFSIM_DCRR(%a0) /* Refresh period */
- move.w #DCTR, %d0 /* Timing address */
- move.w %d0, MCFSIM_DCTR(%a0) /* Timing address */
- move.w #DCAR0, %d0 /* DRAM0 base address */
- move.w %d0, MCFSIM_DCAR0(%a0) /* DRAM0 base address */
- move.l #DCMR0, %d0 /* DRAM0 mask */
- move.l %d0, MCFSIM_DCMR0(%a0) /* DRAM0 mask */
- move.b #DCCR0, %d0 /* DRAM0 control */
- move.b %d0, MCFSIM_DCCR0(%a0) /* DRAM0 control */
- move.w #DCAR1, %d0 /* DRAM1 base address */
- move.w %d0, MCFSIM_DCAR1(%a0) /* DRAM1 base address */
- move.l #DCMR1, %d0 /* DRAM1 mask */
- move.l %d0, MCFSIM_DCMR1(%a0) /* DRAM1 mask */
- move.b #DCCR1, %d0 /* DRAM1 control */
- move.b %d0, MCFSIM_DCCR1(%a0) /* DRAM1 control */
-
- /*
- * ChipSelect 0 - ROM cs
- *
- * ChipSelect 0 is the global chip select coming out of system reset.
- * CS0 is asserted for every access until CSMR0 is written. Therefore,
- * the entire ChipSelect must be properly set prior to asserting
- * CSCR0_V.
- */
- move.w #CS0_ADDR, %d0 /* CS0 address */
- move.w %d0, MCFSIM_CSAR0(%a0) /* CS0 address */
- move.l #CS0_MASK, %d0 /* CS0 mask */
- move.l %d0, MCFSIM_CSMR0(%a0) /* CS0 mask */
- move.w #CS0_CTRL, %d0 /* CS0 control */
- move.w %d0, MCFSIM_CSCR0(%a0) /* CS0 control */
-
-
- /*
- * Setup VBR here, otherwise buserror remap will not work.
- * if dBug was active before (on my SBC with dBug 1.1 of Dec 16 1996)
- *
- * bkr@cut.de 19990306
- *
- * Note: this is because dBUG points VBR to ROM, making vectors read
- * only, so the bus trap can't be changed. (RS)
- */
- move.l #VBR_BASE, %a7 /* Note VBR can't be read */
- movec %a7, %VBR
- move.l %a7, _ramvec /* Set up vector addr */
- move.l %a7, _rambase /* Set up base RAM addr */
-
-
- /*
- * Determine size of RAM, then set up initial stack
- * Done differently for different eval boards and cpus.
- */
-
-#if defined(CONFIG_SMALL)
- /*
- * Set to SRAM size when configuring a minimal system
- */
- move.l #MEM_MAX, %a0
-
-#else
- /*
- * On the Arnewsh 5206 board and the Motorola m5206eLITE board
- * we can probe for the amount of DRAM present...
- */
- move.l #MEM_MIN, %a0 /* Start at bottom */
- move.l #MEM_MAX, %a1 /* Set stop point */
- lea.l MEM_TMPSTACK, %sp /* Set up tmp stack ptr */
-
- move.l #VBR_BASE+8, %a2 /* Address of bus trap */
- lea.l _ram_buserr, %a3 /* Get RAM trap address */
- move.l %a3, (%a2) /* Set trap to local ptr */
-
-_find_ram:
- move.l (%a0), %d0 /* Attempt read */
- add.l #MEM_LUMP, %a0 /* Try next bank */
- cmp.l %a1, %a0 /* Check more? */
- bne _find_ram
-
- /*
- * BUS error trap handler - used for RAM probing.
- */
-_ram_buserr:
- bra _found_ram
-
-_found_ram: /* Vectored here on bus err */
-#endif
-
- move.l %a0, %d0 /* Mem end addr is in a0 */
- move.l %d0, %sp /* Set up initial stack ptr */
- move.l %d0, _ramend /* Set end ram addr */
-
-
- /*
- * Enable CPU internal cache.
- */
- move.l #0x01000000, %d0 /* Invalidate cache cmd */
- movec %d0, %CACR /* Invalidate cache */
- move.l #0x80000100, %d0 /* Setup cache mask */
- movec %d0, %CACR /* Enable cache */
-
-
-#ifdef CONFIG_ROMFS_FS
- /*
- * Move ROM filesystem above bss :-)
- */
- lea.l _sbss, %a0 /* Get start of bss */
- lea.l _ebss, %a1 /* Set up destination */
- move.l %a0, %a2 /* Copy of bss start */
-
- move.l 8(%a0), %d0 /* Get size of ROMFS */
- addq.l #8, %d0 /* Allow for rounding */
- and.l #0xfffffffc, %d0 /* Whole words */
-
- add.l %d0, %a0 /* Copy from end */
- add.l %d0, %a1 /* Copy from end */
- move.l %a1, _ramstart /* Set start of ram */
-
-_copy_romfs:
- move.l -(%a0), %d0 /* Copy dword */
- move.l %d0, -(%a1)
- cmp.l %a0, %a2 /* Check if at end */
- bne _copy_romfs
-
-#else /* CONFIG_ROMFS_FS */
- lea.l _ebss, %a1
- move.l %a1, _ramstart
-#endif /* CONFIG_ROMFS_FS */
-
-
- /*
- * Zero out the bss region.
- */
- lea.l _sbss, %a0 /* Get start of bss */
- lea.l _ebss, %a1 /* Get end of bss */
- clr.l %d0 /* Set value */
-_clear_bss:
- move.l %d0, (%a0)+ /* Clear each word */
- cmp.l %a0, %a1 /* Check if at end */
- bne _clear_bss
-
- /*
- * Load the current task pointer and stack.
- */
- lea init_thread_union, %a0
- lea 0x2000(%a0), %sp
-
- /*
- * Assember start up done, start code proper.
- */
- jsr start_kernel /* Start Linux kernel */
-
-_exit:
- jmp _exit /* Should never get here */
-
-/*****************************************************************************/
diff --git a/arch/m68knommu/platform/5249/MOTOROLA/crt0_ram.S b/arch/m68knommu/platform/5249/MOTOROLA/crt0_ram.S
deleted file mode 100644
index fa0152a1ab012..0000000000000
--- a/arch/m68knommu/platform/5249/MOTOROLA/crt0_ram.S
+++ /dev/null
@@ -1,230 +0,0 @@
-/*****************************************************************************/
-
-/*
- * crt0_ram.S -- startup code for Motorola M5249C3 eval board.
- *
- * (C) Copyright 1999-2002, Greg Ungerer (gerg@snapgear.com).
- */
-
-/*****************************************************************************/
-
-#include "linux/autoconf.h"
-#include "asm/coldfire.h"
-#include "asm/mcfsim.h"
-
-/*****************************************************************************/
-
-/*
- * Motorola M5249C3 ColdFire eval board, chip select and memory setup.
- */
-#define MEM_BASE 0x00000000 /* Memory base at address 0 */
-#define MEM_SIZE 0x00800000 /* Memory size 8MB */
-#define VBR_BASE MEM_BASE /* Vector address */
-
-/*****************************************************************************/
-
-.global _start
-.global _rambase
-.global _ramvec
-.global _ramstart
-.global _ramend
-
-/*****************************************************************************/
-
-.data
-
-/*
- * Set up the usable of RAM stuff. Size of RAM is determined then
- * an initial stack set up at the end.
- */
-_rambase:
-.long 0
-_ramvec:
-.long 0
-_ramstart:
-.long 0
-_ramend:
-.long 0
-
-/*****************************************************************************/
-
-.text
-
-/*
- * This is the codes first entry point. This is where it all
- * begins...
- */
-
-_start:
- nop /* Filler */
- move.w #0x2700, %sr /* No interrupts */
-
- /*
- * Set MBAR1 and MBAR2, just incase they are not set.
- */
- move.l #0x10000001, %a0
- movec %a0, %MBAR /* Map MBAR region */
- subq.l #1, %a0 /* Get MBAR address in a0 */
-
- move.l #0x80000001, %a1
- movec %a1, #3086 /* Map MBAR2 region */
- subq.l #1, %a1 /* Get MBAR2 address in a1 */
-
- /*
- * Move secondary interrupts to base at 128.
- */
- move.b #0x80, %d0
- move.b %d0, 0x16b(%a1) /* Interrupt base register */
-
-#if 1
- /*
- * Work around broken CSMR0/DRAM vector problem.
- */
- move.l #0x001F0021, %d0 /* Disable C/I bit */
- move.l %d0, 0x84(%a0) /* Set CSMR0 */
-#endif
-
- /*
- * Disable the PLL firstly. (Who knows what state it is
- * in here!).
- */
- move.l 0x180(%a1), %d0 /* Get current PLL value */
- and.l #0xfffffffe, %d0 /* PLL bypass first */
- move.l %d0, 0x180(%a1) /* Set PLL register */
- nop
-
-#ifdef CONFIG_CLOCK_140MHz
- /*
- * Set initial clock frequency. This assumes M5249C3 board
- * is fitted with 11.2896MHz crystal. It will program the
- * PLL for 140MHz. Lets go fast :-)
- */
- move.l #0x125a40f0, %d0 /* Set for 140MHz */
- move.l %d0, 0x180(%a1) /* Set PLL register */
- or.l #0x1, %d0
- move.l %d0, 0x180(%a1) /* Set PLL register */
-#endif
-
- /*
- * Setup CS1 for ethernet controller.
- * (Setup as per M5249C3 doco).
- */
- move.l #0xe0000000, %d0 /* CS1 mapped at 0xe0000000 */
- move.l %d0, 0x8c(%a0)
- move.l #0x001f0021, %d0 /* CS1 size of 1Mb */
- move.l %d0, 0x90(%a0)
- move.w #0x0080, %d0 /* CS1 = 16bit port, AA */
- move.w %d0, 0x96(%a0)
-
- /*
- * Setup CS2 for IDE interface.
- */
- move.l #0x50000000, %d0 /* CS2 mapped at 0x50000000 */
- move.l %d0, 0x98(%a0)
- move.l #0x001f0001, %d0 /* CS2 size of 1MB */
- move.l %d0, 0x9c(%a0)
- move.w #0x0080, %d0 /* CS2 = 16bit, TA */
- move.w %d0, 0xa2(%a0)
-
- move.l #0x00107000, %d0 /* IDEconfig1 */
- move.l %d0, 0x18c(%a1)
- move.l #0x000c0400, %d0 /* IDEconfig2 */
- move.l %d0, 0x190(%a1)
-
- move.l #0x00080000, %d0 /* GPIO19, IDE reset bit */
- or.l %d0, 0xc(%a1) /* Function GPIO19 */
- or.l %d0, 0x8(%a1) /* Enable GPIO19 as output */
- or.l %d0, 0x4(%a1) /* De-assert IDE reset */
-
-
- /*
- * Setup VBR as per eval board (really dBUG does this).
- * These settings must match it.
- */
- move.l #VBR_BASE, %a0 /* Note VBR can't be read */
- movec %a0, %VBR
- move.l %a0, _ramvec /* Set up vector addr */
- move.l %a0, _rambase /* Set up base RAM addr */
-
-
- /*
- * Set the memory size, and then set a temporary stack.
- */
- move.l #MEM_SIZE, %a0
-
- move.l %a0, %d0 /* Mem end addr is in a0 */
- move.l %d0, %sp /* Set up initial stack ptr */
- move.l %d0, _ramend /* Set end ram addr */
-
-
- /*
- * Enable CPU internal cache.
- */
- move.l #0x01000000, %d0 /* Invalidate whole cache */
- movec %d0, %CACR
- nop
-
- move.l #0x0000c000, %d0 /* Set SDRAM cached only */
- movec %d0, %ACR0
- move.l #0x00000000, %d0 /* No other regions cached */
- movec %d0, %ACR1
-
- move.l #0xa0000200, %d0 /* Enable cache... */
- movec %d0, %CACR
- nop
-
-
-#ifdef CONFIG_ROMFS_FS
- /*
- * Move ROM filesystem above bss :-)
- */
- lea.l _sbss, %a0 /* Get start of bss */
- lea.l _ebss, %a1 /* Set up destination */
- move.l %a0, %a2 /* Copy of bss start */
-
- move.l 8(%a0), %d0 /* Get size of ROMFS */
- addq.l #8, %d0 /* Allow for rounding */
- and.l #0xfffffffc, %d0 /* Whole words */
-
- add.l %d0, %a0 /* Copy from end */
- add.l %d0, %a1 /* Copy from end */
- move.l %a1, _ramstart /* Set start of ram */
-
-_copy_romfs:
- move.l -(%a0), %d0 /* Copy dword */
- move.l %d0, -(%a1)
- cmp.l %a0, %a2 /* Check if at end */
- bne _copy_romfs
-
-#else /* CONFIG_ROMFS_FS */
- lea.l _ebss, %a1
- move.l %a1, _ramstart
-#endif /* CONFIG_ROMFS_FS */
-
-
- /*
- * Zero out the bss region.
- */
- lea.l _sbss, %a0 /* Get start of bss */
- lea.l _ebss, %a1 /* Get end of bss */
- clr.l %d0 /* Set value */
-_clear_bss:
- move.l %d0, (%a0)+ /* Clear each word */
- cmp.l %a0, %a1 /* Check if at end */
- bne _clear_bss
-
- /*
- * Load the current thread pointer and stack.
- */
- lea init_thread_union, %a0
- lea 0x2000(%a0), %sp
-
- /*
- * Assember start up done, start code proper.
- */
- jsr start_kernel /* Start Linux kernel */
-
-_exit:
- jmp _exit /* Should never get here */
-
-/*****************************************************************************/
diff --git a/arch/m68knommu/platform/5249/Makefile b/arch/m68knommu/platform/5249/Makefile
index 74281a5d6bea8..701b7abe019d8 100644
--- a/arch/m68knommu/platform/5249/Makefile
+++ b/arch/m68knommu/platform/5249/Makefile
@@ -18,4 +18,3 @@ endif
obj-y := config.o
-extra-y := $(BOARD)/crt0_$(MODEL).o
diff --git a/arch/m68knommu/platform/5272/CANCam/crt0_ram.S b/arch/m68knommu/platform/5272/CANCam/crt0_ram.S
deleted file mode 100644
index 06ee803f8ebba..0000000000000
--- a/arch/m68knommu/platform/5272/CANCam/crt0_ram.S
+++ /dev/null
@@ -1,154 +0,0 @@
-/*****************************************************************************/
-
-/*
- * crt0_ram.S -- startup code for Feith CANCan board.
- *
- * (C) Copyright 1999-2002, Greg Ungerer (gerg@snapgear.com).
- * (C) Copyright 2000, Lineo (www.lineo.com).
- */
-
-/*****************************************************************************/
-
-#include <linux/config.h>
-#include <linux/threads.h>
-#include <linux/linkage.h>
-#include <asm/segment.h>
-#include <asm/coldfire.h>
-#include <asm/mcfsim.h>
-
-/*****************************************************************************/
-
-/*
- * Feith ColdFire CANCam, chip select and memory setup.
- */
-
-#define MEM_BASE 0x00000000 /* Memory base at address 0 */
-#define VBR_BASE MEM_BASE /* Vector address */
-#define MEM_SIZE 0x04000000 /* Memory size 64Mb */
-
-
-/*****************************************************************************/
-
-.global _start
-.global _rambase
-.global _ramvec
-.global _ramstart
-.global _ramend
-
-/*****************************************************************************/
-
-.data
-
-/*
- * Set up the usable of RAM stuff. Size of RAM is determined then
- * an initial stack set up at the end.
- */
-_rambase:
-.long 0
-_ramvec:
-.long 0
-_ramstart:
-.long 0
-_ramend:
-.long 0
-
-/*****************************************************************************/
-
-.text
-
-/*
- * This is the codes first entry point. This is where it all
- * begins...
- */
-
-_start:
- nop /* Filler */
- move.w #0x2700, %sr /* No interrupts */
-
- /*
- * Setup VBR here, otherwise buserror remap will not work.
- * if dBug was active before (on my SBC with dBug 1.1 of Dec 16 1996)
- *
- * bkr@cut.de 19990306
- *
- * Note: this is because dBUG points VBR to ROM, making vectors read
- * only, so the bus trap can't be changed. (RS)
- */
- move.l #VBR_BASE, %a7 /* Note VBR can't be read */
- movec %a7, %VBR
- move.l %a7, _ramvec /* Set up vector addr */
- move.l %a7, _rambase /* Set up base RAM addr */
-
-
- /*
- * Set memory size.
- */
- move.l #MEM_SIZE, %a0
-
- move.l %a0, %d0 /* Mem end addr is in a0 */
- move.l %d0, %sp /* Set up initial stack ptr */
- move.l %d0, _ramend /* Set end ram addr */
-
- /*
- * Enable CPU internal cache.
- */
- move.l #0x01000000, %d0 /* Invalidate cache cmd */
- movec %d0, %CACR /* Invalidate cache */
- move.l #0x80000100, %d0 /* Setup cache mask */
- movec %d0, %CACR /* Enable cache */
- nop
-
-#ifdef CONFIG_ROMFS_FS
- /*
- * Move ROM filesystem above bss :-)
- */
- lea.l _sbss, %a0 /* Get start of bss */
- lea.l _ebss, %a1 /* Set up destination */
- move.l %a0, %a2 /* Copy of bss start */
-
- move.l 8(%a0), %d0 /* Get size of ROMFS */
- addq.l #8, %d0 /* Allow for rounding */
- and.l #0xfffffffc, %d0 /* Whole words */
-
- add.l %d0, %a0 /* Copy from end */
- add.l %d0, %a1 /* Copy from end */
- move.l %a1, _ramstart /* Set start of ram */
-
-_copy_romfs:
- move.l -(%a0), %d0 /* Copy dword */
- move.l %d0, -(%a1)
- cmp.l %a0, %a2 /* Check if at end */
- bne _copy_romfs
-
-#else /* CONFIG_ROMFS_FS */
- lea.l _ebss, %a1
- move.l %a1, _ramstart
-#endif /* CONFIG_ROMFS_FS */
-
-
- /*
- * Zero out the bss region.
- */
- lea.l _sbss, %a0 /* Get start of bss */
- lea.l _ebss, %a1 /* Get end of bss */
- clr.l %d0 /* Set value */
-_clear_bss:
- move.l %d0, (%a0)+ /* Clear each word */
- cmp.l %a0, %a1 /* Check if at end */
- bne _clear_bss
-
- /*
- * Load the current thread pointer and stack.
- */
- lea init_thread_union, %a0
- lea 0x2000(%a0), %sp
-
- /*
- * Assember start up done, start code proper.
- */
- jsr start_kernel /* Start Linux kernel */
-
-_exit:
- jmp _exit /* Should never get here */
-
-/*****************************************************************************/
diff --git a/arch/m68knommu/platform/5272/MOTOROLA/crt0_ram.S b/arch/m68knommu/platform/5272/MOTOROLA/crt0_ram.S
deleted file mode 100644
index 37b6a01c27293..0000000000000
--- a/arch/m68knommu/platform/5272/MOTOROLA/crt0_ram.S
+++ /dev/null
@@ -1,165 +0,0 @@
-/*****************************************************************************/
-
-/*
- * crt0_ram.S -- startup code for MCF5272 ColdFire based MOTOROLA boards.
- *
- * (C) Copyright 1999-2002, Greg Ungerer (gerg@snapgear.com).
- * (C) Copyright 2000, Lineo (www.lineo.com).
- */
-
-/*****************************************************************************/
-
-#include <linux/config.h>
-#include <linux/threads.h>
-#include <linux/linkage.h>
-#include <asm/segment.h>
-#include <asm/coldfire.h>
-#include <asm/mcfsim.h>
-
-/*****************************************************************************/
-
-/*
- * Motorola M5272C3 ColdFire eval board, chip select and memory setup.
- */
-
-#define MEM_BASE 0x00000000 /* Memory base at address 0 */
-#define VBR_BASE MEM_BASE /* Vector address */
-
-/*****************************************************************************/
-
-.global _start
-.global _rambase
-.global _ramvec
-.global _ramstart
-.global _ramend
-
-/*****************************************************************************/
-
-.data
-
-/*
- * Set up the usable of RAM stuff. Size of RAM is determined then
- * an initial stack set up at the end.
- */
-_rambase:
-.long 0
-_ramvec:
-.long 0
-_ramstart:
-.long 0
-_ramend:
-.long 0
-
-/*****************************************************************************/
-
-.text
-
-/*
- * This is the codes first entry point. This is where it all
- * begins...
- */
-
-_start:
- nop /* Filler */
- move.w #0x2700, %sr /* No interrupts */
-
- /*
- * Setup VBR here, otherwise buserror remap will not work.
- * if dBug was active before (on my SBC with dBug 1.1 of Dec 16 1996)
- *
- * bkr@cut.de 19990306
- *
- * Note: this is because dBUG points VBR to ROM, making vectors read
- * only, so the bus trap can't be changed. (RS)
- */
- move.l #VBR_BASE, %a7 /* Note VBR can't be read */
- movec %a7, %VBR
- move.l %a7, _ramvec /* Set up vector addr */
- move.l %a7, _rambase /* Set up base RAM addr */
-
- /*
- * Determine size of RAM, then set up initial stack.
- */
-#if defined(CONFIG_RAMAUTO)
- move.l MCF_MBAR+0x7c,%d0 /* get SDRAM address mask */
- andi.l #0xfffff000,%d0 /* mask out chip select options */
- neg.l %d0 /* negate bits */
-#else
-#if defined(CONFIG_RAM16MB)
-#define MEM_SIZE 0x01000000 /* Memory size 16Mb */
-#elif defined(CONFIG_RAM8MB)
-#define MEM_SIZE 0x00800000 /* Memory size 8Mb */
-#else
-#define MEM_SIZE 0x00400000 /* Memory size 4Mb */
-#endif
- /*
- * Set memory size.
- */
- move.l #MEM_SIZE, %d0
-#endif
-
- move.l %d0, %sp /* Set up initial stack ptr */
- move.l %d0, _ramend /* Set end ram addr */
-
- /*
- * Enable CPU internal cache.
- */
- move.l #0x01000000, %d0 /* Invalidate cache cmd */
- movec %d0, %CACR /* Invalidate cache */
- move.l #0x80000100, %d0 /* Setup cache mask */
- movec %d0, %CACR /* Enable cache */
-
-#ifdef CONFIG_ROMFS_FS
- /*
- * Move ROM filesystem above bss :-)
- */
- lea.l _sbss, %a0 /* Get start of bss */
- lea.l _ebss, %a1 /* Set up destination */
- move.l %a0, %a2 /* Copy of bss start */
-
- move.l 8(%a0), %d0 /* Get size of ROMFS */
- addq.l #8, %d0 /* Allow for rounding */
- and.l #0xfffffffc, %d0 /* Whole words */
-
- add.l %d0, %a0 /* Copy from end */
- add.l %d0, %a1 /* Copy from end */
- move.l %a1, _ramstart /* Set start of ram */
-
-_copy_romfs:
- move.l -(%a0), %d0 /* Copy dword */
- move.l %d0, -(%a1)
- cmp.l %a0, %a2 /* Check if at end */
- bne _copy_romfs
-
-#else /* CONFIG_ROMFS_FS */
- lea.l _ebss, %a1
- move.l %a1, _ramstart
-#endif /* CONFIG_ROMFS_FS */
-
-
- /*
- * Zero out the bss region.
- */
- lea.l _sbss, %a0 /* Get start of bss */
- lea.l _ebss, %a1 /* Get end of bss */
- clr.l %d0 /* Set value */
-_clear_bss:
- move.l %d0, (%a0)+ /* Clear each word */
- cmp.l %a0, %a1 /* Check if at end */
- bne _clear_bss
-
- /*
- * Load the current thread pointer and stack.
- */
- lea init_thread_union, %a0
- lea 0x2000(%a0), %sp
-
- /*
- * Assember start up done, start code proper.
- */
- jsr start_kernel /* Start Linux kernel */
-
-_exit:
- jmp _exit /* Should never get here */
-
-/*****************************************************************************/
diff --git a/arch/m68knommu/platform/5272/Makefile b/arch/m68knommu/platform/5272/Makefile
index e49335fcd9c55..0871a29dd5891 100644
--- a/arch/m68knommu/platform/5272/Makefile
+++ b/arch/m68knommu/platform/5272/Makefile
@@ -18,4 +18,3 @@ endif
obj-y := config.o
-extra-y := $(BOARD)/crt0_$(MODEL).o
diff --git a/arch/m68knommu/platform/5272/NETtel/crt0_ram.S b/arch/m68knommu/platform/5272/NETtel/crt0_ram.S
deleted file mode 100644
index ddac6133d36a8..0000000000000
--- a/arch/m68knommu/platform/5272/NETtel/crt0_ram.S
+++ /dev/null
@@ -1,196 +0,0 @@
-/*****************************************************************************/
-
-/*
- * crt0_ram.S -- startup code for MCF5307 ColdFire based NETtel.
- *
- * (C) Copyright 1999-2002, Greg Ungerer (gerg@snapgear.com).
- * Copyright (C) 2000 Lineo Inc. (www.lineo.com)
- *
- * 1999/02/24 Modified for the 5307 processor David W. Miller
- */
-
-/*****************************************************************************/
-
-#include "linux/autoconf.h"
-#include "asm/coldfire.h"
-#include "asm/mcfsim.h"
-#include "asm/nettel.h"
-
-/*****************************************************************************/
-
-/*
- * Lineo NETtel board memory setup.
- */
-#define MEM_BASE 0x00000000 /* Memory base at address 0 */
-#define VBR_BASE MEM_BASE /* Vector address */
-
-#if defined(CONFIG_RAM16MB)
-#define MEM_SIZE 0x01000000 /* Memory size 16Mb */
-#elif defined(CONFIG_RAM8MB)
-#define MEM_SIZE 0x00800000 /* Memory size 8Mb */
-#else
-#define MEM_SIZE 0x00400000 /* Memory size 4Mb */
-#endif
-
-/*****************************************************************************/
-
-.global _start
-.global _rambase
-.global _ramvec
-.global _ramstart
-.global _ramend
-
-/*****************************************************************************/
-
-.data
-
-/*
- * Set up the usable of RAM stuff. Size of RAM is determined then
- * an initial stack set up at the end.
- */
-_rambase:
-.long 0
-_ramvec:
-.long 0
-_ramstart:
-.long 0
-_ramend:
-.long 0
-
-/*****************************************************************************/
-
-/*
- * The NETtel platform has some funky LEDs!
- */
-.global ppdata
-ppdata:
-.short 0x0000
-
-.global ledbank
-ledbank:
-.byte 0xff
-
-/*****************************************************************************/
-
-.text
-
-/*
- * This is the codes first entry point. This is where it all
- * begins...
- */
-
-_start:
- nop /* Filler */
- move.w #0x2700, %sr /* No interrupts */
-
- /*
- * Setup VBR here, otherwise buserror remap will not work.
- * if dBug was active before (on my SBC with dBug 1.1 of Dec 16 1996)
- *
- * bkr@cut.de 19990306
- *
- * Note: this is because dBUG points VBR to ROM, making vectors read
- * only, so the bus trap can't be changed. (RS)
- */
- move.l #VBR_BASE, %a7 /* Note VBR can't be read */
- movec %a7, %VBR
- move.l %a7, _ramvec /* Set up vector addr */
- move.l %a7, _rambase /* Set up base RAM addr */
-
-
- /*
- * Determine size of RAM, then set up initial stack.
- */
- move.l #MEM_SIZE, %a0
-
- move.l %a0, %d0 /* Mem end addr is in a0 */
- move.l %d0, %sp /* Set up initial stack ptr */
- move.l %d0, _ramend /* Set end ram addr */
-
- /*
- * Enable CPU internal cache.
- */
- move.l #0x01000000, %d0 /* Invalidate cache cmd */
- movec %d0, %CACR /* Invalidate cache */
- move.l #0x80000100, %d0 /* Setup cache mask */
- movec %d0, %CACR /* Enable cache */
- nop
-
-
-#ifdef CONFIG_ROMFS_FS
-#ifdef CONFIG_ROMFS_FROM_ROM
- /*
- * check for an in RAM romfs
- */
- lea.l _sbss, %a0 /* Get start of bss */
- mov.l (%a0), %d0
- cmp.l #0x2d726f6d, %d0 /* check for "-rom" */
- bne use_xip_romfs
- add.l #4, %a0
- mov.l (%a0), %d0
- cmp.l #0x3166732d, %d0 /* check for "1fs-" */
- bne use_xip_romfs
-#endif
-
- /*
- * Move ROM filesystem above bss :-)
- */
- lea.l _sbss, %a0 /* Get start of bss */
- lea.l _ebss, %a1 /* Set up destination */
- move.l %a0, %a2 /* Copy of bss start */
-
- move.l 8(%a0), %d0 /* Get size of ROMFS */
- addq.l #8, %d0 /* Allow for rounding */
- and.l #0xfffffffc, %d0 /* Whole words */
-
- add.l %d0, %a0 /* Copy from end */
- add.l %d0, %a1 /* Copy from end */
- move.l %a1, _ramstart /* Set start of ram */
-
-_copy_romfs:
- move.l -(%a0), %d0 /* Copy dword */
- move.l %d0, -(%a1)
- cmp.l %a0, %a2 /* Check if at end */
- bne _copy_romfs
-
-#ifdef CONFIG_ROMFS_FROM_ROM
- bra done_romfs
- use_xip_romfs:
- lea.l _ebss, %a1 /* Set up destination */
- mov.l #0, (%a1) /* make sure we don't use an old RAM version */
- move.l %a1, _ramstart /* Set start of ram */
- done_romfs:
-#endif
-
-#else /* CONFIG_ROMFS_FS */
- lea.l _ebss, %a1
- move.l %a1, _ramstart
-#endif /* CONFIG_ROMFS_FS */
-
-
- /*
- * Zero out the bss region.
- */
- lea.l _sbss, %a0 /* Get start of bss */
- lea.l _ebss, %a1 /* Get end of bss */
- clr.l %d0 /* Set value */
-_clear_bss:
- move.l %d0, (%a0)+ /* Clear each word */
- cmp.l %a0, %a1 /* Check if at end */
- bne _clear_bss
-
- /*
- * load the current task pointer and stack
- */
- lea init_thread_union, %a0
- lea 0x2000(%a0), %sp
-
- /*
- * Assember start up done, start code proper.
- */
- jsr start_kernel /* Start Linux kernel */
-
-_exit:
- jmp _exit /* Should never get here */
-
-/*****************************************************************************/
diff --git a/arch/m68knommu/platform/5272/SCALES/crt0_ram.S b/arch/m68knommu/platform/5272/SCALES/crt0_ram.S
deleted file mode 100644
index fd6927038d4cc..0000000000000
--- a/arch/m68knommu/platform/5272/SCALES/crt0_ram.S
+++ /dev/null
@@ -1,154 +0,0 @@
-/*****************************************************************************/
-
-/*
- * crt0_ram.S -- startup code for Feith SCALES board.
- *
- * (C) Copyright 1999-2002, Greg Ungerer (gerg@snapgear.com).
- * (C) Copyright 2000, Lineo (www.lineo.com).
- */
-
-/*****************************************************************************/
-
-#include <linux/config.h>
-#include <linux/threads.h>
-#include <linux/linkage.h>
-#include <asm/segment.h>
-#include <asm/coldfire.h>
-#include <asm/mcfsim.h>
-
-/*****************************************************************************/
-
-/*
- * Feith ColdFire SCALES, chip select and memory setup.
- */
-
-#define MEM_BASE 0x00000000 /* Memory base at address 0 */
-#define VBR_BASE MEM_BASE /* Vector address */
-#define MEM_SIZE 0x02000000 /* Memory size 32Mb */
-
-
-/*****************************************************************************/
-
-.global _start
-.global _rambase
-.global _ramvec
-.global _ramstart
-.global _ramend
-
-/*****************************************************************************/
-
-.data
-
-/*
- * Set up the usable of RAM stuff. Size of RAM is determined then
- * an initial stack set up at the end.
- */
-_rambase:
-.long 0
-_ramvec:
-.long 0
-_ramstart:
-.long 0
-_ramend:
-.long 0
-
-/*****************************************************************************/
-
-.text
-
-/*
- * This is the codes first entry point. This is where it all
- * begins...
- */
-
-_start:
- nop /* Filler */
- move.w #0x2700, %sr /* No interrupts */
-
- /*
- * Setup VBR here, otherwise buserror remap will not work.
- * if dBug was active before (on my SBC with dBug 1.1 of Dec 16 1996)
- *
- * bkr@cut.de 19990306
- *
- * Note: this is because dBUG points VBR to ROM, making vectors read
- * only, so the bus trap can't be changed. (RS)
- */
- move.l #VBR_BASE, %a7 /* Note VBR can't be read */
- movec %a7, %VBR
- move.l %a7, _ramvec /* Set up vector addr */
- move.l %a7, _rambase /* Set up base RAM addr */
-
-
- /*
- * Set memory size.
- */
- move.l #MEM_SIZE, %a0
-
- move.l %a0, %d0 /* Mem end addr is in a0 */
- move.l %d0, %sp /* Set up initial stack ptr */
- move.l %d0, _ramend /* Set end ram addr */
-
- /*
- * Enable CPU internal cache.
- */
- move.l #0x01000000, %d0 /* Invalidate cache cmd */
- movec %d0, %CACR /* Invalidate cache */
- move.l #0x80000100, %d0 /* Setup cache mask */
- movec %d0, %CACR /* Enable cache */
- nop
-
-#ifdef CONFIG_ROMFS_FS
- /*
- * Move ROM filesystem above bss :-)
- */
- lea.l _sbss, %a0 /* Get start of bss */
- lea.l _ebss, %a1 /* Set up destination */
- move.l %a0, %a2 /* Copy of bss start */
-
- move.l 8(%a0), %d0 /* Get size of ROMFS */
- addq.l #8, %d0 /* Allow for rounding */
- and.l #0xfffffffc, %d0 /* Whole words */
-
- add.l %d0, %a0 /* Copy from end */
- add.l %d0, %a1 /* Copy from end */
- move.l %a1, _ramstart /* Set start of ram */
-
-_copy_romfs:
- move.l -(%a0), %d0 /* Copy dword */
- move.l %d0, -(%a1)
- cmp.l %a0, %a2 /* Check if at end */
- bne _copy_romfs
-
-#else /* CONFIG_ROMFS_FS */
- lea.l _ebss, %a1
- move.l %a1, _ramstart
-#endif /* CONFIG_ROMFS_FS */
-
-
- /*
- * Zero out the bss region.
- */
- lea.l _sbss, %a0 /* Get start of bss */
- lea.l _ebss, %a1 /* Get end of bss */
- clr.l %d0 /* Set value */
-_clear_bss:
- move.l %d0, (%a0)+ /* Clear each word */
- cmp.l %a0, %a1 /* Check if at end */
- bne _clear_bss
-
- /*
- * Load the current thread pointer and stack.
- */
- lea init_thread_union, %a0
- lea 0x2000(%a0), %sp
-
- /*
- * Assember start up done, start code proper.
- */
- jsr start_kernel /* Start Linux kernel */
-
-_exit:
- jmp _exit /* Should never get here */
-
-/*****************************************************************************/
diff --git a/arch/m68knommu/platform/5272/config.c b/arch/m68knommu/platform/5272/config.c
index a9e0dcee10b6e..5cb28690f89a5 100644
--- a/arch/m68knommu/platform/5272/config.c
+++ b/arch/m68knommu/platform/5272/config.c
@@ -39,6 +39,14 @@ extern unsigned int mcf_timerlevel;
/***************************************************************************/
/*
+ * Some platforms need software versions of the GPIO data registers.
+ */
+unsigned short ppdata;
+unsigned char ledbank = 0xff;
+
+/***************************************************************************/
+
+/*
* DMA channel base address table.
*/
unsigned int dma_base_addr[MAX_M68K_DMA_CHANNELS] = {
diff --git a/arch/m68knommu/platform/5272/senTec/crt0_ram.S b/arch/m68knommu/platform/5272/senTec/crt0_ram.S
deleted file mode 100644
index ab5faf9cfd17e..0000000000000
--- a/arch/m68knommu/platform/5272/senTec/crt0_ram.S
+++ /dev/null
@@ -1,159 +0,0 @@
-/*****************************************************************************/
-
-/*
- * crt0_ram.S -- startup code for MCF5272 ColdFire based boards.
- *
- * (C) Copyright 1999-2002, Greg Ungerer (gerg@snapgear.com).
- * (C) Copyright 2000, Lineo (www.lineo.com).
- */
-
-/*****************************************************************************/
-
-#include <linux/config.h>
-#include <linux/threads.h>
-#include <linux/linkage.h>
-#include <asm/segment.h>
-#include <asm/coldfire.h>
-#include <asm/mcfsim.h>
-
-/*****************************************************************************/
-
-/*
- * senTec COBRA5272 board, chip select and memory setup.
- */
-
-#define MEM_BASE 0x00000000 /* Memory base at address 0 */
-#define VBR_BASE MEM_BASE /* Vector address */
-
-#if defined(CONFIG_RAM16MB)
-#define MEM_SIZE 0x01000000 /* Memory size 16Mb */
-#elif defined(CONFIG_RAM8MB)
-#define MEM_SIZE 0x00800000 /* Memory size 8Mb */
-#else
-#define MEM_SIZE 0x00400000 /* Memory size 4Mb */
-#endif
-
-/*****************************************************************************/
-
-.global _start
-.global _rambase
-.global _ramvec
-.global _ramstart
-.global _ramend
-
-/*****************************************************************************/
-
-.data
-
-/*
- * Set up the usable of RAM stuff. Size of RAM is determined then
- * an initial stack set up at the end.
- */
-_rambase:
-.long 0
-_ramvec:
-.long 0
-_ramstart:
-.long 0
-_ramend:
-.long 0
-
-/*****************************************************************************/
-
-.text
-
-/*
- * This is the codes first entry point. This is where it all
- * begins...
- */
-
-_start:
- nop /* Filler */
- move.w #0x2700, %sr /* No interrupts */
-
- /*
- * Setup VBR here, otherwise buserror remap will not work.
- * if dBug was active before (on my SBC with dBug 1.1 of Dec 16 1996)
- *
- * bkr@cut.de 19990306
- *
- * Note: this is because dBUG points VBR to ROM, making vectors read
- * only, so the bus trap can't be changed. (RS)
- */
- move.l #VBR_BASE, %a7 /* Note VBR can't be read */
- movec %a7, %VBR
- move.l %a7, _ramvec /* Set up vector addr */
- move.l %a7, _rambase /* Set up base RAM addr */
-
-
- /*
- * Set memory size.
- */
- move.l #MEM_SIZE, %a0
-
- move.l %a0, %d0 /* Mem end addr is in a0 */
- move.l %d0, %sp /* Set up initial stack ptr */
- move.l %d0, _ramend /* Set end ram addr */
-
- /*
- * Enable CPU internal cache.
- */
- move.l #0x01000000, %d0 /* Invalidate cache cmd */
- movec %d0, %CACR /* Invalidate cache */
- move.l #0x80000100, %d0 /* Setup cache mask */
- movec %d0, %CACR /* Enable cache */
-
-#ifdef CONFIG_ROMFS_FS
- /*
- * Move ROM filesystem above bss :-)
- */
- lea.l _sbss, %a0 /* Get start of bss */
- lea.l _ebss, %a1 /* Set up destination */
- move.l %a0, %a2 /* Copy of bss start */
-
- move.l 8(%a0), %d0 /* Get size of ROMFS */
- addq.l #8, %d0 /* Allow for rounding */
- and.l #0xfffffffc, %d0 /* Whole words */
-
- add.l %d0, %a0 /* Copy from end */
- add.l %d0, %a1 /* Copy from end */
- move.l %a1, _ramstart /* Set start of ram */
-
-_copy_romfs:
- move.l -(%a0), %d0 /* Copy dword */
- move.l %d0, -(%a1)
- cmp.l %a0, %a2 /* Check if at end */
- bne _copy_romfs
-
-#else /* CONFIG_ROMFS_FS */
- lea.l _ebss, %a1
- move.l %a1, _ramstart
-#endif /* CONFIG_ROMFS_FS */
-
-
- /*
- * Zero out the bss region.
- */
- lea.l _sbss, %a0 /* Get start of bss */
- lea.l _ebss, %a1 /* Get end of bss */
- clr.l %d0 /* Set value */
-_clear_bss:
- move.l %d0, (%a0)+ /* Clear each word */
- cmp.l %a0, %a1 /* Check if at end */
- bne _clear_bss
-
- /*
- * Load the current thread pointer and stack.
- */
- lea init_thread_union, %a0
- lea 0x2000(%a0), %sp
-
- /*
- * Assember start up done, start code proper.
- */
- jsr start_kernel /* Start Linux kernel */
-
-_exit:
- jmp _exit /* Should never get here */
-
-/*****************************************************************************/
diff --git a/arch/m68knommu/platform/527x/M5271EVB/crt0_ram.S b/arch/m68knommu/platform/527x/M5271EVB/crt0_ram.S
deleted file mode 100644
index 41f533f810ae5..0000000000000
--- a/arch/m68knommu/platform/527x/M5271EVB/crt0_ram.S
+++ /dev/null
@@ -1,166 +0,0 @@
-/*****************************************************************************/
-
-/*
- * crt0_ram.S -- startup code for MCF527x ColdFire based Freescale boards.
- *
- * (C) Copyright 2003-2004, Greg Ungerer (gerg@snapgear.com).
- */
-
-/*****************************************************************************/
-
-#include <linux/config.h>
-#include <linux/threads.h>
-#include <linux/linkage.h>
-#include <asm/segment.h>
-#include <asm/coldfire.h>
-#include <asm/mcfsim.h>
-
-/*****************************************************************************/
-
-/*
- * Freescale M5271EVB ColdFire eval board, chip select and memory setup.
- */
-
-#define MEM_BASE 0x00000000 /* Memory base at address 0 */
-#define VBR_BASE MEM_BASE /* Vector address */
-
-#if defined(CONFIG_RAM4MB)
-#define MEM_SIZE 0x00400000 /* Memory size 4Mb */
-#elif defined(CONFIG_RAM8MB)
-#define MEM_SIZE 0x00800000 /* Memory size 8Mb */
-#else
-#define MEM_SIZE 0x01000000 /* Memory size 16Mb */
-#endif
-
-/*****************************************************************************/
-
-.global _start
-.global _rambase
-.global _ramvec
-.global _ramstart
-.global _ramend
-
-/*****************************************************************************/
-
-.data
-
-/*
- * Set up the usable of RAM stuff. Size of RAM is determined then
- * an initial stack set up at the end.
- */
-_rambase:
-.long 0
-_ramvec:
-.long 0
-_ramstart:
-.long 0
-_ramend:
-.long 0
-
-/*****************************************************************************/
-
-.text
-
-/*
- * This is the codes first entry point. This is where it all
- * begins...
- */
-
-_start:
- nop /* Filler */
- move.w #0x2700, %sr /* No interrupts */
-
- /*
- * Setup VBR here, otherwise buserror remap will not work.
- * if dBug was active before (on my SBC with dBug 1.1 of Dec 16 1996)
- *
- * bkr@cut.de 19990306
- *
- * Note: this is because dBUG points VBR to ROM, making vectors read
- * only, so the bus trap can't be changed. (RS)
- */
- move.l #VBR_BASE, %a7 /* Note VBR can't be read */
- movec %a7, %VBR
- move.l %a7, _ramvec /* Set up vector addr */
- move.l %a7, _rambase /* Set up base RAM addr */
-
-
- /*
- * Set memory size.
- */
- move.l #MEM_SIZE, %a0
-
- move.l %a0, %d0 /* Mem end addr is in a0 */
- move.l %d0, %sp /* Set up initial stack ptr */
- move.l %d0, _ramend /* Set end ram addr */
-
- /*
- * Enable CPU internal cache.
- */
- move.l #0x01400000, %d0
- movec %d0, %CACR /* Invalidate cache */
- nop
-
- move.l #0x0000c000, %d0 /* Set SDRAM cached only */
- movec %d0, %ACR0
- move.l #0x00000000, %d0 /* No other regions cached */
- movec %d0, %ACR1
-
- move.l #0x80400100, %d0 /* Configure cache */
- movec %d0, %CACR /* Enable cache */
- nop
-
-
-#ifdef CONFIG_ROMFS_FS
- /*
- * Move ROM filesystem above bss :-)
- */
- lea.l _sbss, %a0 /* Get start of bss */
- lea.l _ebss, %a1 /* Set up destination */
- move.l %a0, %a2 /* Copy of bss start */
-
- move.l 8(%a0), %d0 /* Get size of ROMFS */
- addq.l #8, %d0 /* Allow for rounding */
- and.l #0xfffffffc, %d0 /* Whole words */
-
- add.l %d0, %a0 /* Copy from end */
- add.l %d0, %a1 /* Copy from end */
- move.l %a1, _ramstart /* Set start of ram */
-
-_copy_romfs:
- move.l -(%a0), %d0 /* Copy dword */
- move.l %d0, -(%a1)
- cmp.l %a0, %a2 /* Check if at end */
- bne _copy_romfs
-#else /* CONFIG_ROMFS_FS */
- lea.l _ebss, %a1
- move.l %a1, _ramstart
-#endif /* CONFIG_ROMFS_FS */
-
-
- /*
- * Zero out the bss region.
- */
- lea.l _sbss, %a0 /* Get start of bss */
- lea.l _ebss, %a1 /* Get end of bss */
- clr.l %d0 /* Set value */
-_clear_bss:
- move.l %d0, (%a0)+ /* Clear each word */
- cmp.l %a0, %a1 /* Check if at end */
- bne _clear_bss
-
- /*
- * Load the current thread pointer and stack.
- */
- lea init_thread_union, %a0
- lea 0x2000(%a0), %sp
-
- /*
- * Assember start up done, start code proper.
- */
- jsr start_kernel /* Start Linux kernel */
-
-_exit:
- jmp _exit /* Should never get here */
-
-/*****************************************************************************/
diff --git a/arch/m68knommu/platform/527x/M5275EVB/crt0_ram.S b/arch/m68knommu/platform/527x/M5275EVB/crt0_ram.S
deleted file mode 100644
index ceb9920a05951..0000000000000
--- a/arch/m68knommu/platform/527x/M5275EVB/crt0_ram.S
+++ /dev/null
@@ -1,166 +0,0 @@
-/*****************************************************************************/
-
-/*
- * crt0_ram.S -- startup code for MCF527x ColdFire based Freescale boards.
- *
- * (C) Copyright 2003-2004, Greg Ungerer (gerg@snapgear.com).
- */
-
-/*****************************************************************************/
-
-#include <linux/config.h>
-#include <linux/threads.h>
-#include <linux/linkage.h>
-#include <asm/segment.h>
-#include <asm/coldfire.h>
-#include <asm/mcfsim.h>
-
-/*****************************************************************************/
-
-/*
- * Freescale M5275EVB ColdFire eval board, chip select and memory setup.
- */
-
-#define MEM_BASE 0x00000000 /* Memory base at address 0 */
-#define VBR_BASE MEM_BASE /* Vector address */
-
-#if defined(CONFIG_RAM4MB)
-#define MEM_SIZE 0x00400000 /* Memory size 4Mb */
-#elif defined(CONFIG_RAM8MB)
-#define MEM_SIZE 0x00800000 /* Memory size 8Mb */
-#else
-#define MEM_SIZE 0x01000000 /* Memory size 16Mb */
-#endif
-
-/*****************************************************************************/
-
-.global _start
-.global _rambase
-.global _ramvec
-.global _ramstart
-.global _ramend
-
-/*****************************************************************************/
-
-.data
-
-/*
- * Set up the usable of RAM stuff. Size of RAM is determined then
- * an initial stack set up at the end.
- */
-_rambase:
-.long 0
-_ramvec:
-.long 0
-_ramstart:
-.long 0
-_ramend:
-.long 0
-
-/*****************************************************************************/
-
-.text
-
-/*
- * This is the codes first entry point. This is where it all
- * begins...
- */
-
-_start:
- nop /* Filler */
- move.w #0x2700, %sr /* No interrupts */
-
- /*
- * Setup VBR here, otherwise buserror remap will not work.
- * if dBug was active before (on my SBC with dBug 1.1 of Dec 16 1996)
- *
- * bkr@cut.de 19990306
- *
- * Note: this is because dBUG points VBR to ROM, making vectors read
- * only, so the bus trap can't be changed. (RS)
- */
- move.l #VBR_BASE, %a7 /* Note VBR can't be read */
- movec %a7, %VBR
- move.l %a7, _ramvec /* Set up vector addr */
- move.l %a7, _rambase /* Set up base RAM addr */
-
-
- /*
- * Set memory size.
- */
- move.l #MEM_SIZE, %a0
-
- move.l %a0, %d0 /* Mem end addr is in a0 */
- move.l %d0, %sp /* Set up initial stack ptr */
- move.l %d0, _ramend /* Set end ram addr */
-
- /*
- * Enable CPU internal cache.
- */
- move.l #0x01400000, %d0
- movec %d0, %CACR /* Invalidate cache */
- nop
-
- move.l #0x0000c000, %d0 /* Set SDRAM cached only */
- movec %d0, %ACR0
- move.l #0x00000000, %d0 /* No other regions cached */
- movec %d0, %ACR1
-
- move.l #0x80400100, %d0 /* Configure cache */
- movec %d0, %CACR /* Enable cache */
- nop
-
-
-#ifdef CONFIG_ROMFS_FS
- /*
- * Move ROM filesystem above bss :-)
- */
- lea.l _sbss, %a0 /* Get start of bss */
- lea.l _ebss, %a1 /* Set up destination */
- move.l %a0, %a2 /* Copy of bss start */
-
- move.l 8(%a0), %d0 /* Get size of ROMFS */
- addq.l #8, %d0 /* Allow for rounding */
- and.l #0xfffffffc, %d0 /* Whole words */
-
- add.l %d0, %a0 /* Copy from end */
- add.l %d0, %a1 /* Copy from end */
- move.l %a1, _ramstart /* Set start of ram */
-
-_copy_romfs:
- move.l -(%a0), %d0 /* Copy dword */
- move.l %d0, -(%a1)
- cmp.l %a0, %a2 /* Check if at end */
- bne _copy_romfs
-#else /* CONFIG_ROMFS_FS */
- lea.l _ebss, %a1
- move.l %a1, _ramstart
-#endif /* CONFIG_ROMFS_FS */
-
-
- /*
- * Zero out the bss region.
- */
- lea.l _sbss, %a0 /* Get start of bss */
- lea.l _ebss, %a1 /* Get end of bss */
- clr.l %d0 /* Set value */
-_clear_bss:
- move.l %d0, (%a0)+ /* Clear each word */
- cmp.l %a0, %a1 /* Check if at end */
- bne _clear_bss
-
- /*
- * Load the current thread pointer and stack.
- */
- lea init_thread_union, %a0
- lea 0x2000(%a0), %sp
-
- /*
- * Assember start up done, start code proper.
- */
- jsr start_kernel /* Start Linux kernel */
-
-_exit:
- jmp _exit /* Should never get here */
-
-/*****************************************************************************/
diff --git a/arch/m68knommu/platform/527x/Makefile b/arch/m68knommu/platform/527x/Makefile
index e49335fcd9c55..0871a29dd5891 100644
--- a/arch/m68knommu/platform/527x/Makefile
+++ b/arch/m68knommu/platform/527x/Makefile
@@ -18,4 +18,3 @@ endif
obj-y := config.o
-extra-y := $(BOARD)/crt0_$(MODEL).o
diff --git a/arch/m68knommu/platform/528x/M5282EVB/crt0_ram.S b/arch/m68knommu/platform/528x/M5282EVB/crt0_ram.S
deleted file mode 100644
index 2b14d9a12ed60..0000000000000
--- a/arch/m68knommu/platform/528x/M5282EVB/crt0_ram.S
+++ /dev/null
@@ -1,171 +0,0 @@
-/*****************************************************************************/
-
-/*
- * crt0_ram.S -- startup code for M5282EVB ColdFire based MOTOROLA boards.
- *
- * (C) Copyright 2003, Greg Ungerer (gerg@snapgear.com).
- */
-
-/*****************************************************************************/
-
-#include <linux/config.h>
-#include <linux/threads.h>
-#include <linux/linkage.h>
-#include <asm/segment.h>
-#include <asm/coldfire.h>
-#include <asm/mcfsim.h>
-
-/*****************************************************************************/
-
-/*
- * Motorola M5282EVB ColdFire eval board, chip select and memory setup.
- */
-
-#define MEM_BASE 0x00000000 /* Memory base at address 0 */
-#define VBR_BASE MEM_BASE /* Vector address */
-
-#if defined(CONFIG_RAM16MB)
-#define MEM_SIZE 0x01000000 /* Memory size 16Mb */
-#elif defined(CONFIG_RAM8MB)
-#define MEM_SIZE 0x00800000 /* Memory size 8Mb */
-#else
-#define MEM_SIZE 0x00400000 /* Memory size 4Mb */
-#endif
-
-/*****************************************************************************/
-
-.global _start
-.global _rambase
-.global _ramvec
-.global _ramstart
-.global _ramend
-
-/*****************************************************************************/
-
-.data
-
-/*
- * Set up the usable of RAM stuff. Size of RAM is determined then
- * an initial stack set up at the end.
- */
-_rambase:
-.long 0
-_ramvec:
-.long 0
-_ramstart:
-.long 0
-_ramend:
-.long 0
-
-/*****************************************************************************/
-
-.text
-
-/*
- * This is the codes first entry point. This is where it all
- * begins...
- */
-
-_start:
- nop /* Filler */
- move.w #0x2700, %sr /* No interrupts */
-
- /*
- * Setup VBR here, otherwise buserror remap will not work.
- * if dBug was active before (on my SBC with dBug 1.1 of Dec 16 1996)
- *
- * bkr@cut.de 19990306
- *
- * Note: this is because dBUG points VBR to ROM, making vectors read
- * only, so the bus trap can't be changed. (RS)
- */
- move.l #VBR_BASE, %a7 /* Note VBR can't be read */
- movec %a7, %VBR
- move.l %a7, _ramvec /* Set up vector addr */
- move.l %a7, _rambase /* Set up base RAM addr */
-
-
- /*
- * Set memory size.
- */
- move.l #MEM_SIZE, %a0
-
- move.l %a0, %d0 /* Mem end addr is in a0 */
- move.l %d0, %sp /* Set up initial stack ptr */
- move.l %d0, _ramend /* Set end ram addr */
-
- /*
- * Enable CPU internal cache.
- *
- * Cache is totally broken in first 5282 silicon.
- * No point enabling it for now.
- */
-#if 0
- move.l #0x01000000, %d0
- movec %d0, %CACR /* Invalidate cache */
- nop
-
- move.l #0x0000c000, %d0 /* Set SDRAM cached only */
- movec %d0, %ACR0
- move.l #0x00000000, %d0 /* No other regions cached */
- movec %d0, %ACR1
-
- move.l #0x00000000, %d0 /* Setup cache mask */
- movec %d0, %CACR /* Enable cache */
- nop
-#endif
-
-
-#ifdef CONFIG_ROMFS_FS
- /*
- * Move ROM filesystem above bss :-)
- */
- lea.l _sbss, %a0 /* Get start of bss */
- lea.l _ebss, %a1 /* Set up destination */
- move.l %a0, %a2 /* Copy of bss start */
-
- move.l 8(%a0), %d0 /* Get size of ROMFS */
- addq.l #8, %d0 /* Allow for rounding */
- and.l #0xfffffffc, %d0 /* Whole words */
-
- add.l %d0, %a0 /* Copy from end */
- add.l %d0, %a1 /* Copy from end */
- move.l %a1, _ramstart /* Set start of ram */
-
-_copy_romfs:
- move.l -(%a0), %d0 /* Copy dword */
- move.l %d0, -(%a1)
- cmp.l %a0, %a2 /* Check if at end */
- bne _copy_romfs
-#else /* CONFIG_ROMFS_FS */
- lea.l _ebss, %a1
- move.l %a1, _ramstart
-#endif /* CONFIG_ROMFS_FS */
-
-
- /*
- * Zero out the bss region.
- */
- lea.l _sbss, %a0 /* Get start of bss */
- lea.l _ebss, %a1 /* Get end of bss */
- clr.l %d0 /* Set value */
-_clear_bss:
- move.l %d0, (%a0)+ /* Clear each word */
- cmp.l %a0, %a1 /* Check if at end */
- bne _clear_bss
-
- /*
- * Load the current thread pointer and stack.
- */
- lea init_thread_union, %a0
- lea 0x2000(%a0), %sp
-
- /*
- * Assember start up done, start code proper.
- */
- jsr start_kernel /* Start Linux kernel */
-
-_exit:
- jmp _exit /* Should never get here */
-
-/*****************************************************************************/
diff --git a/arch/m68knommu/platform/528x/Makefile b/arch/m68knommu/platform/528x/Makefile
index e49335fcd9c55..0871a29dd5891 100644
--- a/arch/m68knommu/platform/528x/Makefile
+++ b/arch/m68knommu/platform/528x/Makefile
@@ -18,4 +18,3 @@ endif
obj-y := config.o
-extra-y := $(BOARD)/crt0_$(MODEL).o
diff --git a/arch/m68knommu/platform/528x/senTec/crt0_ram.S b/arch/m68knommu/platform/528x/senTec/crt0_ram.S
deleted file mode 100644
index c2f3bbd011892..0000000000000
--- a/arch/m68knommu/platform/528x/senTec/crt0_ram.S
+++ /dev/null
@@ -1,180 +0,0 @@
-/*****************************************************************************/
-
-/*
- * crt0_ram.S -- startup code for senTec COBRA5282 ColdFire based boards.
- *
- * (C) Copyright 2003, Greg Ungerer (gerg@snapgear.com).
- */
-
-/*****************************************************************************/
-
-#include <linux/config.h>
-#include <linux/threads.h>
-#include <linux/linkage.h>
-#include <asm/segment.h>
-#include <asm/coldfire.h>
-#include <asm/mcfsim.h>
-
-/*****************************************************************************/
-
-/*
- * senTec COBRA5282 board, chip select and memory setup.
- */
-
-#define MEM_BASE 0x00000000 /* Memory base at address 0 */
-#define VBR_BASE MEM_BASE /* Vector address */
-
-#if defined(CONFIG_RAM16MB)
-#define MEM_SIZE 0x01000000 /* Memory size 16Mb */
-#elif defined(CONFIG_RAM8MB)
-#define MEM_SIZE 0x00800000 /* Memory size 8Mb */
-#else
-#define MEM_SIZE 0x00400000 /* Memory size 4Mb */
-#endif
-
-#define IPSBAR 0x40000000
-#define GPACR0 0x30
-/*****************************************************************************/
-
-.global _start
-.global _rambase
-.global _ramvec
-.global _ramstart
-.global _ramend
-
-/*****************************************************************************/
-
-.data
-
-/*
- * Set up the usable of RAM stuff. Size of RAM is determined then
- * an initial stack set up at the end.
- */
-_rambase:
-.long 0
-_ramvec:
-.long 0
-_ramstart:
-.long 0
-_ramend:
-.long 0
-
-/*****************************************************************************/
-
-.text
-
-/*
- * This is the codes first entry point. This is where it all
- * begins...
- */
-
-_start:
- nop /* Filler */
- move.w #0x2700, %sr /* No interrupts */
-
- /*
- * Setup VBR here, otherwise buserror remap will not work.
- * if dBug was active before (on my SBC with dBug 1.1 of Dec 16 1996)
- *
- * bkr@cut.de 19990306
- *
- * Note: this is because dBUG points VBR to ROM, making vectors read
- * only, so the bus trap can't be changed. (RS)
- */
- move.l #VBR_BASE, %a7 /* Note VBR can't be read */
- movec %a7, %VBR
- move.l %a7, _ramvec /* Set up vector addr */
- move.l %a7, _rambase /* Set up base RAM addr */
-
-
- /*
- * Set memory size.
- */
- move.l #MEM_SIZE, %a0
-
- move.l %a0, %d0 /* Mem end addr is in a0 */
- move.l %d0, %sp /* Set up initial stack ptr */
- move.l %d0, _ramend /* Set end ram addr */
-
- /*
- * Enable CPU internal cache.
- *
- * Cache is totally broken in first 5282 silicon.
- * No point enabling it for now.
- */
-#if 0
- move.l #0x01000000, %d0
- movec %d0, %CACR /* Invalidate cache */
- nop
-
- move.l #0x0000c000, %d0 /* Set SDRAM cached only */
- movec %d0, %ACR0
- move.l #0x00000000, %d0 /* No other regions cached */
- movec %d0, %ACR1
-
- move.l #0x00000000, %d0 /* Setup cache mask */
- movec %d0, %CACR /* Enable cache */
- nop
-#endif
-
-
-#ifdef CONFIG_ROMFS_FS
- /*
- * Move ROM filesystem above bss :-)
- */
- lea.l _sbss, %a0 /* Get start of bss */
- lea.l _ebss, %a1 /* Set up destination */
- move.l %a0, %a2 /* Copy of bss start */
-
- move.l 8(%a0), %d0 /* Get size of ROMFS */
- addq.l #8, %d0 /* Allow for rounding */
- and.l #0xfffffffc, %d0 /* Whole words */
-
- add.l %d0, %a0 /* Copy from end */
- add.l %d0, %a1 /* Copy from end */
- move.l %a1, _ramstart /* Set start of ram */
-
-_copy_romfs:
- move.l -(%a0), %d0 /* Copy dword */
- move.l %d0, -(%a1)
- cmp.l %a0, %a2 /* Check if at end */
- bne _copy_romfs
-#else /* CONFIG_ROMFS_FS */
- lea.l _ebss, %a1
- move.l %a1, _ramstart
-#endif /* CONFIG_ROMFS_FS */
-
-
- /*
- * Zero out the bss region.
- */
- lea.l _sbss, %a0 /* Get start of bss */
- lea.l _ebss, %a1 /* Get end of bss */
- clr.l %d0 /* Set value */
-_clear_bss:
- move.l %d0, (%a0)+ /* Clear each word */
- cmp.l %a0, %a1 /* Check if at end */
- bne _clear_bss
-
- /*
- * Load the current thread pointer and stack.
- */
- lea init_thread_union, %a0
- lea 0x2000(%a0), %sp
-
- /*
- * User mode port access
- */
- move.l #0x0000000c, %d0
- move.b %d0, (IPSBAR+GPACR0)
-
-
- /*
- * Assember start up done, start code proper.
- */
- jsr start_kernel /* Start Linux kernel */
-
-_exit:
- jmp _exit /* Should never get here */
-
-/*****************************************************************************/
diff --git a/arch/m68knommu/platform/5307/ARNEWSH/crt0_ram.S b/arch/m68knommu/platform/5307/ARNEWSH/crt0_ram.S
deleted file mode 100644
index 6779bb0dee354..0000000000000
--- a/arch/m68knommu/platform/5307/ARNEWSH/crt0_ram.S
+++ /dev/null
@@ -1,167 +0,0 @@
-/*****************************************************************************/
-
-/*
- * crt0_ram.S -- startup code for MCF5307 ColdFire Arnewsh board.
- *
- * (C) Copyright 1999-2002, Greg Ungerer (gerg@snapgear.com).
- * Copyright (C) 2000 Lineo Inc. (www.lineo.com)
- *
- * 1999/02/24 Modified for the 5307 processor David W. Miller
- */
-
-/*****************************************************************************/
-
-#include "linux/autoconf.h"
-#include "asm/coldfire.h"
-#include "asm/mcfsim.h"
-#include "asm/nettel.h"
-
-/*****************************************************************************/
-
-/*
- * SnapGear/NETtel board memory setup.
- */
-#define MEM_BASE 0x00000000 /* Memory base at address 0 */
-#define MEM_SIZE 0x00800000 /* Memory size 8Mb */
-#define VBR_BASE MEM_BASE /* Vector address */
-
-/*****************************************************************************/
-
-.global _start
-.global _rambase
-.global _ramvec
-.global _ramstart
-.global _ramend
-
-/*****************************************************************************/
-
-.data
-
-/*
- * Set up the usable of RAM stuff. Size of RAM is determined then
- * an initial stack set up at the end.
- */
-_rambase:
-.long 0
-_ramvec:
-.long 0
-_ramstart:
-.long 0
-_ramend:
-.long 0
-
-/*****************************************************************************/
-
-.text
-
-/*
- * This is the codes first entry point. This is where it all
- * begins...
- */
-
-_start:
- nop /* Filler */
- move.w #0x2700, %sr /* No interrupts */
-
- /*
- * Setup VBR here, otherwise buserror remap will not work.
- * if dBug was active before (on my SBC with dBug 1.1 of Dec 16 1996)
- *
- * bkr@cut.de 19990306
- *
- * Note: this is because dBUG points VBR to ROM, making vectors read
- * only, so the bus trap can't be changed. (RS)
- */
- move.l #VBR_BASE, %a7 /* Note VBR can't be read */
- movec %a7, %VBR
- move.l %a7, _ramvec /* Set up vector addr */
- move.l %a7, _rambase /* Set up base RAM addr */
-
-
- /*
- * Determine size of RAM, then set up initial stack.
- */
- move.l #MEM_SIZE, %a0
-
- move.l %a0, %d0 /* Mem end addr is in a0 */
- move.l %d0, %sp /* Set up initial stack ptr */
- move.l %d0, _ramend /* Set end ram addr */
-
- /* make region ROM cachable (turn off for flash programming?) */
- /* 0xff000000 - 0xffffffff */
-#ifdef DEBUGGER_COMPATIBLE_CACHE
- movl #(0xff<<ACR_BASE_POS)+(0<<ACR_MASK_POS)+ACR_ENABLE+ACR_ANY+ACR_CM_WTHRU+ACR_WPROTECT,%d0
-#else
- movl #(0xff<<ACR_BASE_POS)+(0<<ACR_MASK_POS)+ACR_ENABLE+ACR_ANY+ACR_CM_WBACK+ACR_WPROTECT,%d0
-#endif
- movc %d0,%ACR0
-
- /* make region RAM cachable *
- /* 0x00000000 - 0x00ffffffff */
-#ifdef DEBUGGER_COMPATIBLE_CACHE
- movl #(0x00<<ACR_BASE_POS)+(0<<ACR_MASK_POS)+ACR_ENABLE+ACR_ANY+ACR_CM_WTHRU,%d0
-#else
- movl #(0x00<<ACR_BASE_POS)+(0<<ACR_MASK_POS)+ACR_ENABLE+ACR_ANY+ACR_CM_WBACK,%d0
-#endif
- movc %d0,%ACR1
-
- /* make the default cache mode precise */
- movl #CACR_EC+CACR_ESB+CACR_DCM_OFF_PRE,%d0 /* enable cache */
- movc %d0,%CACR
- nop
-
-
-#ifdef CONFIG_ROMFS_FS
- /*
- * Move ROM filesystem above bss :-)
- */
- lea.l _sbss, %a0 /* Get start of bss */
- lea.l _ebss, %a1 /* Set up destination */
- move.l %a0, %a2 /* Copy of bss start */
-
- move.l 8(%a0), %d0 /* Get size of ROMFS */
- addq.l #8, %d0 /* Allow for rounding */
- and.l #0xfffffffc, %d0 /* Whole words */
-
- add.l %d0, %a0 /* Copy from end */
- add.l %d0, %a1 /* Copy from end */
- move.l %a1, _ramstart /* Set start of ram */
-
-_copy_romfs:
- move.l -(%a0), %d0 /* Copy dword */
- move.l %d0, -(%a1)
- cmp.l %a0, %a2 /* Check if at end */
- bne _copy_romfs
-
-#else /* CONFIG_ROMFS_FS */
- lea.l _ebss, %a1
- move.l %a1, _ramstart
-#endif /* CONFIG_ROMFS_FS */
-
-
- /*
- * Zero out the bss region.
- */
- lea.l _sbss, %a0 /* Get start of bss */
- lea.l _ebss, %a1 /* Get end of bss */
- clr.l %d0 /* Set value */
-_clear_bss:
- move.l %d0, (%a0)+ /* Clear each word */
- cmp.l %a0, %a1 /* Check if at end */
- bne _clear_bss
-
- /*
- * load the current task pointer and stack
- */
- lea init_thread_union, %a0
- lea 0x2000(%a0), %sp
-
- /*
- * Assember start up done, start code proper.
- */
- jsr start_kernel /* Start Linux kernel */
-
-_exit:
- jmp _exit /* Should never get here */
-
-/*****************************************************************************/
diff --git a/arch/m68knommu/platform/5307/CLEOPATRA/crt0_ram.S b/arch/m68knommu/platform/5307/CLEOPATRA/crt0_ram.S
deleted file mode 100644
index 809b9ca2bdf0b..0000000000000
--- a/arch/m68knommu/platform/5307/CLEOPATRA/crt0_ram.S
+++ /dev/null
@@ -1,183 +0,0 @@
-/*****************************************************************************/
-
-/*
- * crt0_ram.S -- startup code for Feith CLEOPATRA board.
- *
- * (C) Copyright 2001, Roman Wagner.
- *
- * 1999/02/24 Modified for the 5307 processor David W. Miller
- */
-
-/*****************************************************************************/
-
-#include "linux/autoconf.h"
-#include "asm/coldfire.h"
-#include "asm/mcfsim.h"
-
-/*****************************************************************************/
-
-/*
- * Feith CLEOPATRA board, chip select and memory setup.
-*/
-
-#define MEM_BASE 0x00000000 /* Memory base at address 0 */
-#define VBR_BASE MEM_BASE /* Vector address */
-
-#if defined(CONFIG_RAM16MB)
-#define MEM_SIZE 0x01000000 /* Memory size 16Mb */
-#else
-#define MEM_SIZE 0x00800000 /* Memory size 8Mb */
-#endif
-
-/*****************************************************************************/
-
-.global _start
-.global _rambase
-.global _ramvec
-.global _ramstart
-.global _ramend
-
-/*****************************************************************************/
-
-.data
-
-/*
- * Set up the usable of RAM stuff. Size of RAM is determined then
- * an initial stack set up at the end.
- */
-_rambase:
-.long 0
-_ramvec:
-.long 0
-_ramstart:
-.long 0
-_ramend:
-.long 0
-
-/*****************************************************************************/
-
-.text
-
-/*
- * This is the codes first entry point. This is where it all
- * begins...
- */
-
-_start:
- nop /* Filler */
- move.w #0x2700, %sr /* No interrupts */
-
-
- /*
- * Setup VBR here, otherwise buserror remap will not work.
- * if dBug was active before (on my SBC with dBug 1.1 of Dec 16 1996)
- *
- * bkr@cut.de 19990306
- *
- * Note: this is because dBUG points VBR to ROM, making vectors read
- * only, so the bus trap can't be changed. (RS)
- */
- move.l #VBR_BASE, %a7 /* Note VBR can't be read */
- movec %a7, %VBR
- move.l %a7, _ramvec /* Set up vector addr */
- move.l %a7, _rambase /* Set up base RAM addr */
-
-
- /*
- * Determine size of RAM, then set up initial stack.
- */
-/*
- * The current version of the 5307 processor
- * SWT does not work. Probing invalid addresses
- * will hang the system.
- *
- * For now, set the memory size to 8 meg
- */
- move.l #MEM_SIZE, %a0
-
- move.l %a0, %d0 /* Mem end addr is in a0 */
- move.l %d0, %sp /* Set up initial stack ptr */
- move.l %d0, _ramend /* Set end ram addr */
-
-
- /* now fire off the cache, remember to invalidate it first */
- movl #0,%d0
- movc %d0,%CACR
- nop
- movc %d0,%CACR /* cache is off */
-
- movl #CACR_CINVA,%d0 /* invalidate whole cache */
- movc %d0,%CACR
- nop
- movc %d0,%CACR
- nop
-
- /* make region ROM cachable (turn off for flash programming?) */
- /* 0xff000000 - 0xffffffff */
- movl #(0xff<<ACR_BASE_POS)+(0<<ACR_MASK_POS)+ACR_ENABLE+ACR_ANY+ACR_CM_WBACK+ACR_WPROTECT,%d0
- movc %d0,%ACR0
-
- /* make region RAM cachable *
- /* 0x00000000 - 0x00ffffffff */
- movl #(0x00<<ACR_BASE_POS)+(0<<ACR_MASK_POS)+ACR_ENABLE+ACR_ANY+ACR_CM_WBACK,%d0
- movc %d0,%ACR1
-
- /* make the default cache mode precise */
- movl #CACR_EC+CACR_ESB+CACR_DCM_OFF_PRE,%d0 /* enable cache */
- movc %d0,%CACR
-
-
-#ifdef CONFIG_ROMFS_FS
- /*
- * Move ROM filesystem above bss :-)
- */
- lea.l _sbss, %a0 /* Get start of bss */
- lea.l _ebss, %a1 /* Set up destination */
- move.l %a0, %a2 /* Copy of bss start */
-
- move.l 8(%a0), %d0 /* Get size of ROMFS */
- addq.l #8, %d0 /* Allow for rounding */
- and.l #0xfffffffc, %d0 /* Whole words */
-
- add.l %d0, %a0 /* Copy from end */
- add.l %d0, %a1 /* Copy from end */
- move.l %a1, _ramstart /* Set start of ram */
-
-_copy_romfs:
- move.l -(%a0), %d0 /* Copy dword */
- move.l %d0, -(%a1)
- cmp.l %a0, %a2 /* Check if at end */
- bne _copy_romfs
-
-#else /* CONFIG_ROMFS_FS */
- lea.l _ebss, %a1
- move.l %a1, _ramstart
-#endif /* CONFIG_ROMFS_FS */
-
-
- /*
- * Zero out the bss region.
- */
- lea.l _sbss, %a0 /* Get start of bss */
- lea.l _ebss, %a1 /* Get end of bss */
- clr.l %d0 /* Set value */
-_clear_bss:
- move.l %d0, (%a0)+ /* Clear each word */
- cmp.l %a0, %a1 /* Check if at end */
- bne _clear_bss
-
- /*
- * load the current task pointer and stack
- */
- lea init_thread_union, %a0
- lea 0x2000(%a0), %sp
-
- /*
- * Assember start up done, start code proper.
- */
- jsr start_kernel /* Start Linux kernel */
-
-_exit:
- jmp _exit /* Should never get here */
-
-/*****************************************************************************/
diff --git a/arch/m68knommu/platform/5307/MOTOROLA/crt0_ram.S b/arch/m68knommu/platform/5307/MOTOROLA/crt0_ram.S
deleted file mode 100644
index 1fff8b293b778..0000000000000
--- a/arch/m68knommu/platform/5307/MOTOROLA/crt0_ram.S
+++ /dev/null
@@ -1,167 +0,0 @@
-/*****************************************************************************/
-
-/*
- * crt0_ram.S -- startup code for MCF5307C3 Cadre-III ColdFire board.
- *
- * (C) Copyright 1999-2002, Greg Ungerer (gerg@snapgear.com).
- * Copyright (C) 2000 Lineo Inc. (www.lineo.com)
- *
- * 1999/02/24 Modified for the 5307 processor David W. Miller
- */
-
-/*****************************************************************************/
-
-#include "linux/autoconf.h"
-#include "asm/coldfire.h"
-#include "asm/mcfsim.h"
-#include "asm/nettel.h"
-
-/*****************************************************************************/
-
-/*
- * SnapGear/NETtel board memory setup.
- */
-#define MEM_BASE 0x00000000 /* Memory base at address 0 */
-#define MEM_SIZE 0x00800000 /* Memory size 8Mb */
-#define VBR_BASE MEM_BASE /* Vector address */
-
-/*****************************************************************************/
-
-.global _start
-.global _rambase
-.global _ramvec
-.global _ramstart
-.global _ramend
-
-/*****************************************************************************/
-
-.data
-
-/*
- * Set up the usable of RAM stuff. Size of RAM is determined then
- * an initial stack set up at the end.
- */
-_rambase:
-.long 0
-_ramvec:
-.long 0
-_ramstart:
-.long 0
-_ramend:
-.long 0
-
-/*****************************************************************************/
-
-.text
-
-/*
- * This is the codes first entry point. This is where it all
- * begins...
- */
-
-_start:
- nop /* Filler */
- move.w #0x2700, %sr /* No interrupts */
-
- /*
- * Setup VBR here, otherwise buserror remap will not work.
- * if dBug was active before (on my SBC with dBug 1.1 of Dec 16 1996)
- *
- * bkr@cut.de 19990306
- *
- * Note: this is because dBUG points VBR to ROM, making vectors read
- * only, so the bus trap can't be changed. (RS)
- */
- move.l #VBR_BASE, %a7 /* Note VBR can't be read */
- movec %a7, %VBR
- move.l %a7, _ramvec /* Set up vector addr */
- move.l %a7, _rambase /* Set up base RAM addr */
-
-
- /*
- * Determine size of RAM, then set up initial stack.
- */
- move.l #MEM_SIZE, %a0
-
- move.l %a0, %d0 /* Mem end addr is in a0 */
- move.l %d0, %sp /* Set up initial stack ptr */
- move.l %d0, _ramend /* Set end ram addr */
-
- /* make region ROM cachable (turn off for flash programming?) */
- /* 0xff000000 - 0xffffffff */
-#ifdef DEBUGGER_COMPATIBLE_CACHE
- movl #(0xff<<ACR_BASE_POS)+(0<<ACR_MASK_POS)+ACR_ENABLE+ACR_ANY+ACR_CM_WTHRU+ACR_WPROTECT,%d0
-#else
- movl #(0xff<<ACR_BASE_POS)+(0<<ACR_MASK_POS)+ACR_ENABLE+ACR_ANY+ACR_CM_WBACK+ACR_WPROTECT,%d0
-#endif
- movc %d0,%ACR0
-
- /* make region RAM cachable *
- /* 0x00000000 - 0x00ffffffff */
-#ifdef DEBUGGER_COMPATIBLE_CACHE
- movl #(0x00<<ACR_BASE_POS)+(0<<ACR_MASK_POS)+ACR_ENABLE+ACR_ANY+ACR_CM_WTHRU,%d0
-#else
- movl #(0x00<<ACR_BASE_POS)+(0<<ACR_MASK_POS)+ACR_ENABLE+ACR_ANY+ACR_CM_WBACK,%d0
-#endif
- movc %d0,%ACR1
-
- /* make the default cache mode precise */
- movl #CACR_EC+CACR_ESB+CACR_DCM_OFF_PRE,%d0 /* enable cache */
- movc %d0,%CACR
- nop
-
-
-#ifdef CONFIG_ROMFS_FS
- /*
- * Move ROM filesystem above bss :-)
- */
- lea.l _sbss, %a0 /* Get start of bss */
- lea.l _ebss, %a1 /* Set up destination */
- move.l %a0, %a2 /* Copy of bss start */
-
- move.l 8(%a0), %d0 /* Get size of ROMFS */
- addq.l #8, %d0 /* Allow for rounding */
- and.l #0xfffffffc, %d0 /* Whole words */
-
- add.l %d0, %a0 /* Copy from end */
- add.l %d0, %a1 /* Copy from end */
- move.l %a1, _ramstart /* Set start of ram */
-
-_copy_romfs:
- move.l -(%a0), %d0 /* Copy dword */
- move.l %d0, -(%a1)
- cmp.l %a0, %a2 /* Check if at end */
- bne _copy_romfs
-
-#else /* CONFIG_ROMFS_FS */
- lea.l _ebss, %a1
- move.l %a1, _ramstart
-#endif /* CONFIG_ROMFS_FS */
-
-
- /*
- * Zero out the bss region.
- */
- lea.l _sbss, %a0 /* Get start of bss */
- lea.l _ebss, %a1 /* Get end of bss */
- clr.l %d0 /* Set value */
-_clear_bss:
- move.l %d0, (%a0)+ /* Clear each word */
- cmp.l %a0, %a1 /* Check if at end */
- bne _clear_bss
-
- /*
- * load the current task pointer and stack
- */
- lea init_thread_union, %a0
- lea 0x2000(%a0), %sp
-
- /*
- * Assember start up done, start code proper.
- */
- jsr start_kernel /* Start Linux kernel */
-
-_exit:
- jmp _exit /* Should never get here */
-
-/*****************************************************************************/
diff --git a/arch/m68knommu/platform/5307/MP3/crt0_ram.S b/arch/m68knommu/platform/5307/MP3/crt0_ram.S
deleted file mode 100644
index d99883ac3bd02..0000000000000
--- a/arch/m68knommu/platform/5307/MP3/crt0_ram.S
+++ /dev/null
@@ -1,181 +0,0 @@
-/*****************************************************************************/
-
-/*
- * crt0_ram.S -- startup code for MCF5307 ColdFire based MP3.
- *
- * (C) Copyright 1999-2002, Greg Ungerer (gerg@snapgear.com).
- * Copyright (C) 2000-2001 Lineo Inc. (www.lineo.com)
- *
- * 1999/02/24 Modified for the 5307 processor David W. Miller
- */
-
-/*****************************************************************************/
-
-#include "linux/autoconf.h"
-#include "asm/coldfire.h"
-#include "asm/mcfsim.h"
-#include "asm/nettel.h"
-
-/*****************************************************************************/
-
-/*
- * SnapGear/NETtel board memory setup.
- */
-#define MEM_BASE 0x00000000 /* Memory base at address 0 */
-#define VBR_BASE MEM_BASE /* Vector address */
-
-#if defined(CONFIG_RAM16MB)
-#define MEM_SIZE 0x01000000 /* Memory size 16Mb */
-#else
-#define MEM_SIZE 0x00800000 /* Memory size 8Mb */
-#endif
-
-/*****************************************************************************/
-
-.global _start
-.global _rambase
-.global _ramvec
-.global _ramstart
-.global _ramend
-
-/*****************************************************************************/
-
-.data
-
-/*
- * Set up the usable of RAM stuff. Size of RAM is determined then
- * an initial stack set up at the end.
- */
-_rambase:
-.long 0
-_ramvec:
-.long 0
-_ramstart:
-.long 0
-_ramend:
-.long 0
-
-/*****************************************************************************/
-
-.text
-
-/*
- * This is the codes first entry point. This is where it all
- * begins...
- */
-
-_start:
- nop /* Filler */
- move.w #0x2700, %sr /* No interrupts */
-
- /*
- * Disable watchdog timer.
- */
- move.l #MCF_MBAR, %a0 /* Get MBAR address */
- clr.l %d0 /* Disable SWT */
- move.b %d0, MCFSIM_SYPCR(%a0)
- move.b #0x55, %d0 /* Clear SWT as well */
- move.b %d0, MCFSIM_SWSR(%a0)
- move.b #0xaa, %d0
- move.b %d0, MCFSIM_SWSR(%a0)
- move.l #0xffffffff, %d0 /* Mask out all interrupts */
- move.l %d0, MCFSIM_IMR(%a0)
-
- /*
- * Setup VBR here, otherwise buserror remap will not work.
- * if dBug was active before (on my SBC with dBug 1.1 of Dec 16 1996)
- *
- * bkr@cut.de 19990306
- *
- * Note: this is because dBUG points VBR to ROM, making vectors read
- * only, so the bus trap can't be changed. (RS)
- */
- move.l #VBR_BASE, %a7 /* Note VBR can't be read */
- movec %a7, %VBR
- move.l %a7, _ramvec /* Set up vector addr */
- move.l %a7, _rambase /* Set up base RAM addr */
-
-
- /*
- * Determine size of RAM, then set up initial stack.
- */
- move.l #MEM_SIZE, %a0
-
- move.l %a0, %d0 /* Mem end addr is in a0 */
- move.l %d0, %sp /* Set up initial stack ptr */
- move.l %d0, _ramend /* Set end ram addr */
-
- /*
- * Enable CPU internal cache.
- */
- move.l #0x01000000, %d0 /* invalidate whole cache */
- movec %d0,%CACR
- nop
-
- /* MUST be write-through for DMA to work... */
- /* This also makes this debugger safe */
- move.l #0x0000c000, %d0 /* Set SDRAM cached only */
- movec %d0, %ACR0
- move.l #0x00000000, %d0 /* No other regions cached */
- movec %d0, %ACR1
-
- /* Enable cache */
- move.l #0xa0000200, %d0
- movec %d0,%CACR
- nop
-
-
-#ifdef CONFIG_ROMFS_FS
- /*
- * Move ROM filesystem above bss :-)
- */
- lea.l _sbss, %a0 /* Get start of bss */
- lea.l _ebss, %a1 /* Set up destination */
- move.l %a0, %a2 /* Copy of bss start */
-
- move.l 8(%a0), %d0 /* Get size of ROMFS */
- addq.l #8, %d0 /* Allow for rounding */
- and.l #0xfffffffc, %d0 /* Whole words */
-
- add.l %d0, %a0 /* Copy from end */
- add.l %d0, %a1 /* Copy from end */
- move.l %a1, _ramstart /* Set start of ram */
-
-_copy_romfs:
- move.l -(%a0), %d0 /* Copy dword */
- move.l %d0, -(%a1)
- cmp.l %a0, %a2 /* Check if at end */
- bne _copy_romfs
-
-#else /* CONFIG_ROMFS_FS */
- lea.l _ebss, %a1
- move.l %a1, _ramstart
-#endif /* CONFIG_ROMFS_FS */
-
-
- /*
- * Zero out the bss region.
- */
- lea.l _sbss, %a0 /* Get start of bss */
- lea.l _ebss, %a1 /* Get end of bss */
- clr.l %d0 /* Set value */
-_clear_bss:
- move.l %d0, (%a0)+ /* Clear each word */
- cmp.l %a0, %a1 /* Check if at end */
- bne _clear_bss
-
- /*
- * load the current task pointer and stack
- */
- lea init_thread_union, %a0
- lea 0x2000(%a0), %sp
-
- /*
- * Assember start up done, start code proper.
- */
- jsr start_kernel /* Start Linux kernel */
-
-_exit:
- jmp _exit /* Should never get here */
-
-/*****************************************************************************/
diff --git a/arch/m68knommu/platform/5307/Makefile b/arch/m68knommu/platform/5307/Makefile
index 3f54610881093..84b6b70641e17 100644
--- a/arch/m68knommu/platform/5307/Makefile
+++ b/arch/m68knommu/platform/5307/Makefile
@@ -26,6 +26,4 @@ obj-$(CONFIG_M5307) += config.o timers.o
obj-$(CONFIG_M528x) += pit.o
obj-$(CONFIG_M5407) += timers.o
-ifeq ($(CONFIG_M5307),y)
-extra-y := $(BOARD)/crt0_$(MODEL).o
-endif
+extra-y := head.o
diff --git a/arch/m68knommu/platform/5307/NETtel/crt0_ram.S b/arch/m68knommu/platform/5307/NETtel/crt0_ram.S
deleted file mode 100644
index 009a40506c06c..0000000000000
--- a/arch/m68knommu/platform/5307/NETtel/crt0_ram.S
+++ /dev/null
@@ -1,204 +0,0 @@
-/*****************************************************************************/
-
-/*
- * crt0_ram.S -- startup code for MCF5307 ColdFire based NETtel.
- *
- * (C) Copyright 1999-2002, Greg Ungerer (gerg@snapgear.com).
- * Copyright (C) 2000 Lineo Inc. (www.lineo.com)
- *
- * 1999/02/24 Modified for the 5307 processor David W. Miller
- */
-
-/*****************************************************************************/
-
-#include "linux/autoconf.h"
-#include "asm/coldfire.h"
-#include "asm/mcfsim.h"
-#include "asm/nettel.h"
-
-/*****************************************************************************/
-
-/*
- * SnapGear/NETtel board memory setup.
- */
-#define MEM_BASE 0x00000000 /* Memory base at address 0 */
-#define VBR_BASE MEM_BASE /* Vector address */
-
-#if defined(CONFIG_RAM16MB)
-#define MEM_SIZE 0x01000000 /* Memory size 16Mb */
-#elif defined(CONFIG_RAM8MB)
-#define MEM_SIZE 0x00800000 /* Memory size 8Mb */
-#else
-#define MEM_SIZE 0x00400000 /* Memory size 4Mb */
-#endif
-
-/*****************************************************************************/
-
-.global _start
-.global _rambase
-.global _ramvec
-.global _ramstart
-.global _ramend
-
-/*****************************************************************************/
-
-.data
-
-/*
- * Set up the usable of RAM stuff. Size of RAM is determined then
- * an initial stack set up at the end.
- */
-_rambase:
-.long 0
-_ramvec:
-.long 0
-_ramstart:
-.long 0
-_ramend:
-.long 0
-
-/*****************************************************************************/
-
-/*
- * The NETtel platform has some funky LEDs!
- */
-.global ppdata
-ppdata:
-.short 0x0000
-
-.global ledbank
-ledbank:
-.byte 0xff
-
-/*****************************************************************************/
-
-.text
-
-/*
- * This is the codes first entry point. This is where it all
- * begins...
- */
-
-_start:
- nop /* Filler */
- move.w #0x2700, %sr /* No interrupts */
-
- /*
- * Set LEDs to known startup state.
- */
- move.l #NETtel_LEDADDR, %a5 /* Addr of LED bank */
- move.b #0xff, (%a5) /* Turn them all off */
-
-
- /*
- * Disable watchdog timer.
- */
- move.l #MCF_MBAR, %a0 /* Get MBAR address */
- clr.l %d0 /* Disable SWT */
- move.b %d0, MCFSIM_SYPCR(%a0)
- move.b #0x55, %d0 /* Clear SWT as well */
- move.b %d0, MCFSIM_SWSR(%a0)
- move.b #0xaa, %d0
- move.b %d0, MCFSIM_SWSR(%a0)
- move.l #0xffffffff, %d0 /* Mask out all interrupts */
- move.l %d0, MCFSIM_IMR(%a0)
-
- /*
- * Setup VBR here, otherwise buserror remap will not work.
- * if dBug was active before (on my SBC with dBug 1.1 of Dec 16 1996)
- *
- * bkr@cut.de 19990306
- *
- * Note: this is because dBUG points VBR to ROM, making vectors read
- * only, so the bus trap can't be changed. (RS)
- */
- move.l #VBR_BASE, %a7 /* Note VBR can't be read */
- movec %a7, %VBR
- move.l %a7, _ramvec /* Set up vector addr */
- move.l %a7, _rambase /* Set up base RAM addr */
-
-
- /*
- * Determine size of RAM, then set up initial stack.
- */
- move.l #MEM_SIZE, %a0
-
- move.l %a0, %d0 /* Mem end addr is in a0 */
- move.l %d0, %sp /* Set up initial stack ptr */
- move.l %d0, _ramend /* Set end ram addr */
-
- /*
- * Enable CPU internal cache.
- */
- move.l #0x01000000, %d0 /* invalidate whole cache */
- movec %d0,%CACR
- nop
-#ifdef DEBUGGER_COMPATIBLE_CACHE
- move.l #0x0000c000, %d0 /* Set SDRAM cached only */
-#else
- move.l #0x0000c020, %d0 /* Set SDRAM cached only (copyback) */
-#endif
- movec %d0, %ACR0
- move.l #0x00000000, %d0 /* No other regions cached */
- movec %d0, %ACR1
-
- /* Enable cache */
- move.l #0xa0000200, %d0
- movec %d0,%CACR
- nop
-
-
-#ifdef CONFIG_ROMFS_FS
- /*
- * Move ROM filesystem above bss :-)
- */
- lea.l _sbss, %a0 /* Get start of bss */
- lea.l _ebss, %a1 /* Set up destination */
- move.l %a0, %a2 /* Copy of bss start */
-
- move.l 8(%a0), %d0 /* Get size of ROMFS */
- addq.l #8, %d0 /* Allow for rounding */
- and.l #0xfffffffc, %d0 /* Whole words */
-
- add.l %d0, %a0 /* Copy from end */
- add.l %d0, %a1 /* Copy from end */
- move.l %a1, _ramstart /* Set start of ram */
-
-_copy_romfs:
- move.l -(%a0), %d0 /* Copy dword */
- move.l %d0, -(%a1)
- cmp.l %a0, %a2 /* Check if at end */
- bne _copy_romfs
-
-#else /* CONFIG_ROMFS_FS */
- lea.l _ebss, %a1
- move.l %a1, _ramstart
-#endif /* CONFIG_ROMFS_FS */
-
-
- /*
- * Zero out the bss region.
- */
- lea.l _sbss, %a0 /* Get start of bss */
- lea.l _ebss, %a1 /* Get end of bss */
- clr.l %d0 /* Set value */
-_clear_bss:
- move.l %d0, (%a0)+ /* Clear each word */
- cmp.l %a0, %a1 /* Check if at end */
- bne _clear_bss
-
- /*
- * load the current task pointer and stack
- */
- lea init_thread_union, %a0
- lea 0x2000(%a0), %sp
-
- /*
- * Assember start up done, start code proper.
- */
- jsr start_kernel /* Start Linux kernel */
-
-_exit:
- jmp _exit /* Should never get here */
-
-/*****************************************************************************/
diff --git a/arch/m68knommu/platform/5307/config.c b/arch/m68knommu/platform/5307/config.c
index 3f505dabfcb0c..7ed5782e92368 100644
--- a/arch/m68knommu/platform/5307/config.c
+++ b/arch/m68knommu/platform/5307/config.c
@@ -40,6 +40,14 @@ extern unsigned int mcf_timerlevel;
/***************************************************************************/
/*
+ * Some platforms need software versions of the GPIO data registers.
+ */
+unsigned short ppdata;
+unsigned char ledbank = 0xff;
+
+/***************************************************************************/
+
+/*
* DMA channel base address table.
*/
unsigned int dma_base_addr[MAX_M68K_DMA_CHANNELS] = {
diff --git a/arch/m68knommu/platform/5307/entry.S b/arch/m68knommu/platform/5307/entry.S
index 6795d83e4d4f6..89b180d4ed6a9 100644
--- a/arch/m68knommu/platform/5307/entry.S
+++ b/arch/m68knommu/platform/5307/entry.S
@@ -5,6 +5,7 @@
* Copyright (C) 1998 D. Jeff Dionne <jeff@lineo.ca>,
* Kenneth Albanowski <kjahds@kjahds.com>,
* Copyright (C) 2000 Lineo Inc. (www.lineo.com)
+ * Copyright (C) 2004 Macq Electronique SA. (www.macqel.com)
*
* Based on:
*
@@ -22,6 +23,7 @@
* ColdFire support by Greg Ungerer (gerg@snapgear.com)
* 5307 fixes by David W. Miller
* linux 2.4 support David McCullough <davidm@snapgear.com>
+ * Bug, speed and maintainability fixes by Philippe De Muyter <phdm@macqel.be>
*/
#include <linux/config.h>
@@ -35,7 +37,7 @@
#include <asm/asm-offsets.h>
#include <asm/entry.h>
-.data
+.bss
sw_ksp:
.long 0
@@ -59,7 +61,7 @@ ENTRY(system_call)
move #0x2000,%sr /* enable intrs again */
movel #-LENOSYS,%d2
- movel %d2,LD0(%sp) /* default return value in d0 */
+ movel %d2,PT_D0(%sp) /* default return value in d0 */
/* original D0 is in orig_d0 */
movel %d0,%d2
@@ -77,14 +79,14 @@ ENTRY(system_call)
lsrl #2,%d2
movel %sp,%d2 /* get thread_info pointer */
- andl #0xffffe000,%d2 /* at start of 8k kernel stack */
+ andl #-THREAD_SIZE,%d2 /* at start of kernel stack */
movel %d2,%a0
btst #TIF_SYSCALL_TRACE,%a0@(TI_FLAGS)
bnes 1f
movel %d3,%a0
jbsr %a0@
- movel %d0,%sp@(LD0) /* save the return value */
+ movel %d0,%sp@(PT_D0) /* save the return value */
jra ret_from_exception
1:
subql #4,%sp
@@ -94,7 +96,7 @@ ENTRY(system_call)
addql #4,%sp
movel %d3,%a0
jbsr %a0@
- movel %d0,%sp@(LD0) /* save the return value */
+ movel %d0,%sp@(PT_D0) /* save the return value */
subql #4,%sp /* dummy return address */
SAVE_SWITCH_STACK
jbsr syscall_trace
@@ -104,20 +106,20 @@ ret_from_signal:
addql #4,%sp
ret_from_exception:
- btst #5,%sp@(LSR) /* check if returning to kernel */
+ btst #5,%sp@(PT_SR) /* check if returning to kernel */
jeq Luser_return /* if so, skip resched, signals */
Lkernel_return:
- moveml %sp@,%d1-%d5/%a0-%a2
- addl #32,%sp /* space for 8 regs */
- movel %sp@+,%d0
- addql #4,%sp /* orig d0 */
- addl %sp@+,%sp /* stk adj */
+ moveml %sp@,%d1-%d5/%a0-%a2
+ lea %sp@(32),%sp /* space for 8 regs */
+ movel %sp@+,%d0
+ addql #4,%sp /* orig d0 */
+ addl %sp@+,%sp /* stk adj */
rte
Luser_return:
movel %sp,%d1 /* get thread_info pointer */
- andl #0xffffe000,%d1 /* at base of 8k kernel stack */
+ andl #-THREAD_SIZE,%d1 /* at base of kernel stack */
movel %d1,%a0
movel %a0@(TI_FLAGS),%d1 /* get thread_info->flags */
andl #_TIF_WORK_MASK,%d1
@@ -126,27 +128,17 @@ Luser_return:
Lreturn:
move #0x2700,%sr /* disable intrs */
movel sw_usp,%a0 /* get usp */
- moveml %sp@(LFORMATVEC),%d1-%d2 /* copy exception */
- moveml %d1-%d2,%a0@(-8)
- bclr #5,%a0@(-8) /* clear format byte, bit 5 to make
- * stack appear modulo 4 which it WILL
- * be when we do the rte because it was
- * generated in setup_frame
- */
- bclr #4,%a0@(-8) /* clear format byte, bit 4 to make
- * stack appear modulo 4 which it WILL
- * be when we do the rte because it was
- * generated in setup_frame
- */
- moveml %sp@,%d1-%d5/%a0-%a2
- addl #32,%sp /* space for 8 regs */
- movel %sp@+,%d0
- addql #4,%sp /* orig d0 */
- addl %sp@+,%sp /* stk adj */
- addql #8,%sp /* remove exception */
- movel %sp,sw_ksp /* save ksp */
- movel sw_usp,%sp /* restore usp */
- subql #8,%sp /* set exception */
+ movel %sp@(PT_PC),%a0@- /* copy exception program counter */
+ movel %sp@(PT_FORMATVEC),%a0@-/* copy exception format/vector/sr */
+ moveml %sp@,%d1-%d5/%a0-%a2
+ lea %sp@(32),%sp /* space for 8 regs */
+ movel %sp@+,%d0
+ addql #4,%sp /* orig d0 */
+ addl %sp@+,%sp /* stk adj */
+ addql #8,%sp /* remove exception */
+ movel %sp,sw_ksp /* save ksp */
+ subql #8,sw_usp /* set exception */
+ movel sw_usp,%sp /* restore usp */
rte
Lwork_to_do:
@@ -160,8 +152,7 @@ Lsignal_return:
subql #4,%sp /* dummy return address */
SAVE_SWITCH_STACK
pea %sp@(SWITCH_STACK_SIZE)
- clr %d1
- movel %d1,%sp@-
+ clrl %sp@-
jsr do_signal
addql #8,%sp
RESTORE_SWITCH_STACK
@@ -176,10 +167,10 @@ Lsignal_return:
ENTRY(inthandler)
SAVE_ALL
moveq #-1,%d0
- movel %d0,%sp@(LORIG_D0)
+ movel %d0,%sp@(PT_ORIG_D0)
addql #1,local_irq_count
- movew %sp@(LFORMATVEC),%d0 /* put exception # in d0 */
+ movew %sp@(PT_FORMATVEC),%d0 /* put exception # in d0 */
andl #0x03fc,%d0 /* mask out vector only */
leal per_cpu__kstat+STAT_IRQ,%a0
@@ -197,7 +188,7 @@ ENTRY(inthandler)
movel %a0@,%a0 /* get function to call */
jbsr %a0@ /* call vector handler */
- addl #12,%sp /* pop parameters off stack */
+ lea %sp@(12),%sp /* pop parameters off stack */
bra ret_from_interrupt /* this was fallthrough */
@@ -210,15 +201,14 @@ ENTRY(inthandler)
ENTRY(fasthandler)
SAVE_LOCAL
- movew %sp@(LFORMATVEC),%d0
+ movew %sp@(PT_FORMATVEC),%d0
andl #0x03fc,%d0 /* mask out vector only */
leal per_cpu__kstat+STAT_IRQ,%a0
addql #1,%a0@(%d0)
movel %sp,%sp@- /* push regs arg onto stack */
- clrl %d1
- movel %d1,%sp@- /* push devid arg */
+ clrl %sp@- /* push devid arg */
lsrl #2,%d0 /* calculate real vector # */
movel %d0,%sp@- /* push vector # on stack */
@@ -226,7 +216,7 @@ ENTRY(fasthandler)
lea irq_list,%a0
movel %a0@(%d0),%a0 /* get function to call */
jbsr %a0@ /* call vector handler */
- addl #12,%sp /* pop parameters off stack */
+ lea %sp@(12),%sp /* pop parameters off stack */
RESTORE_LOCAL
@@ -236,7 +226,7 @@ ENTRY(ret_from_interrupt)
1:
RESTORE_ALL
2:
- moveb %sp@(LSR),%d0
+ moveb %sp@(PT_SR),%d0
andl #0x7,%d0
jhi 1b
diff --git a/arch/m68knommu/platform/5307/head.S b/arch/m68knommu/platform/5307/head.S
index f3a0bdf48320d..c7d7a395c4cc8 100644
--- a/arch/m68knommu/platform/5307/head.S
+++ b/arch/m68knommu/platform/5307/head.S
@@ -11,7 +11,7 @@
#include <linux/config.h>
#include <linux/sys.h>
#include <linux/linkage.h>
-#include <asm/thread_info.h>
+#include <asm/asm-offsets.h>
#include <asm/coldfire.h>
#include <asm/mcfcache.h>
#include <asm/mcfsim.h>
@@ -87,7 +87,7 @@
.endm
#elif defined(CONFIG_M5272)
-.macro GET_MEMORY_SIZE
+.macro GET_MEM_SIZE
movel MCF_MBAR+MCFSIM_CSOR7,%d0 /* get SDRAM address mask */
andil #0xfffff000,%d0 /* mask out chip select options */
negl %d0 /* negate bits */
diff --git a/arch/m68knommu/platform/5407/CLEOPATRA/crt0_ram.S b/arch/m68knommu/platform/5407/CLEOPATRA/crt0_ram.S
deleted file mode 100644
index 20d86dd7f88a4..0000000000000
--- a/arch/m68knommu/platform/5407/CLEOPATRA/crt0_ram.S
+++ /dev/null
@@ -1,180 +0,0 @@
-/*****************************************************************************/
-
-/*
- * crt0_ram.S -- startup code for Feith Cleopatra 2 board.
- *
- * (C) Copyright 2001, Roman Wagner.
- *
- * 1999/02/24 Modified for the 5307 processor David W. Miller
- */
-
-/*****************************************************************************/
-
-#include "linux/autoconf.h"
-#include "asm/coldfire.h"
-#include "asm/mcfsim.h"
-
-/*****************************************************************************/
-
-/*
- * Feith CLEOPATRA board, chip select and memory setup.
-*/
-
-#define MEM_BASE 0x00000000 /* Memory base at address 0 */
-#define VBR_BASE MEM_BASE /* Vector address */
-
-#define MEM_SIZE 0x01000000 /* Memory size 16Mb */
-
-/*****************************************************************************/
-
-.global _start
-.global _rambase
-.global _ramvec
-.global _ramstart
-.global _ramend
-
-/*****************************************************************************/
-
-.data
-
-/*
- * Set up the usable of RAM stuff. Size of RAM is determined then
- * an initial stack set up at the end.
- */
-_rambase:
-.long 0
-_ramvec:
-.long 0
-_ramstart:
-.long 0
-_ramend:
-.long 0
-
-/*****************************************************************************/
-
-.text
-
-/*
- * This is the codes first entry point. This is where it all
- * begins...
- */
-
-_start:
- nop /* Filler */
- move.w #0x2700, %sr /* No interrupts */
-
-
- /*
- * Setup VBR here, otherwise buserror remap will not work.
- * if dBug was active before (on my SBC with dBug 1.1 of Dec 16 1996)
- *
- * bkr@cut.de 19990306
- *
- * Note: this is because dBUG points VBR to ROM, making vectors read
- * only, so the bus trap can't be changed. (RS)
- */
- move.l #VBR_BASE, %a7 /* Note VBR can't be read */
- movec %a7, %VBR
- move.l %a7, _ramvec /* Set up vector addr */
- move.l %a7, _rambase /* Set up base RAM addr */
-
- /*
- * Determine size of RAM, then set up initial stack.
- */
-/*
- * The current version of the 5307 processor
- * SWT does not work. Probing invalid addresses
- * will hang the system.
- *
- * For now, set the memory size to 8 meg
- */
- move.l #MEM_SIZE, %a0
-
- move.l %a0, %d0 /* Mem end addr is in a0 */
- move.l %d0, %sp /* Set up initial stack ptr */
- move.l %d0, _ramend /* Set end ram addr */
-
-
- /*
- * Enable CPU internal cache.
- */
- move.l #0x01040100, %d0 /* Invalidate whole cache */
- movec %d0,%CACR
- nop
-
- /* make region ROM cachable (turn off for flash programming?) */
- /* 0xff000000 - 0xffffffff */
- move.l #(0xff<<ACR_BASE_POS)+(0<<ACR_MASK_POS)+ACR_ENABLE+ACR_ANY+ACR_CM_CP+ACR_WPROTECT,%d0
- movec %d0,%ACR0
-
- /* make region RAM cachable */
- /* 0x00000000 - 0x00ffffffff */
- move.l #(0x00<<ACR_BASE_POS)+(0<<ACR_MASK_POS)+ACR_ENABLE+ACR_ANY+ACR_CM_CP,%d0
- movec %d0,%ACR1
-
- move.l #(0xff<<ACR_BASE_POS)+(0<<ACR_MASK_POS)+ACR_ENABLE+ACR_ANY+ACR_CM_CP+ACR_WPROTECT,%d0
- movec %d0,%ACR2
-
- move.l #(0x00<<ACR_BASE_POS)+(0<<ACR_MASK_POS)+ACR_ENABLE+ACR_ANY+ACR_CM_CP,%d0
- movec %d0,%ACR3
-
- /* Enable cache */
- move.l #0xa4098400, %d0 /* Write buffer, dflt precise */
- movec %d0,%CACR
- nop
-
-
-#ifdef CONFIG_ROMFS_FS
- /*
- * Move ROM filesystem above bss :-)
- */
- lea.l _sbss, %a0 /* Get start of bss */
- lea.l _ebss, %a1 /* Set up destination */
- move.l %a0, %a2 /* Copy of bss start */
-
- move.l 8(%a0), %d0 /* Get size of ROMFS */
- addq.l #8, %d0 /* Allow for rounding */
- and.l #0xfffffffc, %d0 /* Whole words */
-
- add.l %d0, %a0 /* Copy from end */
- add.l %d0, %a1 /* Copy from end */
- move.l %a1, _ramstart /* Set start of ram */
-
-_copy_romfs:
- move.l -(%a0), %d0 /* Copy dword */
- move.l %d0, -(%a1)
- cmp.l %a0, %a2 /* Check if at end */
- bne _copy_romfs
-
-#else /* CONFIG_ROMFS_FS */
- lea.l _ebss, %a1
- move.l %a1, _ramstart
-#endif /* CONFIG_ROMFS_FS */
-
-
- /*
- * Zero out the bss region.
- */
- lea.l _sbss, %a0 /* Get start of bss */
- lea.l _ebss, %a1 /* Get end of bss */
- clr.l %d0 /* Set value */
-_clear_bss:
- move.l %d0, (%a0)+ /* Clear each word */
- cmp.l %a0, %a1 /* Check if at end */
- bne _clear_bss
-
- /*
- * Load the current task pointer and stack.
- */
- lea init_thread_union, %a0
- lea 0x2000(%a0), %sp
-
- /*
- * Assember start up done, start code proper.
- */
- jsr start_kernel /* Start Linux kernel */
-
-_exit:
- jmp _exit /* Should never get here */
-
-/*****************************************************************************/
diff --git a/arch/m68knommu/platform/5407/MOTOROLA/crt0_ram.S b/arch/m68knommu/platform/5407/MOTOROLA/crt0_ram.S
deleted file mode 100644
index 05a899df369e3..0000000000000
--- a/arch/m68knommu/platform/5407/MOTOROLA/crt0_ram.S
+++ /dev/null
@@ -1,160 +0,0 @@
-/*****************************************************************************/
-
-/*
- * crt0_ram.S -- startup code for Motorola 5407 eval board.
- *
- * (C) Copyright 1999-2002, Greg Ungerer (gerg@snapgear.com).
- * (C) Copyright 2000, Lineo (www.lineo.com).
- *
- * 1999/02/24 Modified for the 5307 processor David W. Miller
- */
-
-/*****************************************************************************/
-
-#include "linux/autoconf.h"
-#include "asm/coldfire.h"
-#include "asm/mcfsim.h"
-
-/*****************************************************************************/
-
-/*
- * Board setup info.
- */
-#define MEM_BASE 0x00000000 /* Memory base at address 0 */
-#define VBR_BASE MEM_BASE /* Vector address */
-
-#define MEM_SIZE 0x02000000 /* Memory size 32 */
-
-/*****************************************************************************/
-
-.global _start
-.global _rambase
-.global _ramvec
-.global _ramstart
-.global _ramend
-
-/*****************************************************************************/
-
-.data
-
-/*
- * Set up the usable of RAM stuff. Size of RAM is determined then
- * an initial stack set up at the end.
- */
-_rambase:
-.long 0
-_ramvec:
-.long 0
-_ramstart:
-.long 0
-_ramend:
-.long 0
-
-/*****************************************************************************/
-
-.text
-
-/*
- * This is the codes first entry point. This is where it all
- * begins...
- */
-
-_start:
- nop /* Filler */
- move.w #0x2700, %sr /* No interrupts */
-
- /*
- * Setup VBR as per eval board (really dBUG does this).
- * These settings must match it.
- */
- move.l #VBR_BASE, %a0 /* Note VBR can't be read */
- movec %a0, %VBR
- move.l %a0, _ramvec /* Set up vector addr */
- move.l %a0, _rambase /* Set up base RAM addr */
-
-
- /*
- * Determine size of RAM, then set up initial stack.
- */
- move.l #MEM_SIZE, %a0
-
- move.l %a0, %d0 /* Mem end addr is in a0 */
- move.l %d0, %sp /* Set up initial stack ptr */
- move.l %d0, _ramend /* Set end ram addr */
-
-
- /*
- * Enable CPU internal cache.
- */
- move.l #0x01040100, %d0 /* Invalidate whole cache */
- movec %d0,%CACR
- nop
- move.l #0x000fc000, %d0 /* Set SDRAM cached only */
- movec %d0, %ACR0
- move.l #0x00000000, %d0 /* No other regions cached */
- movec %d0, %ACR1
- move.l #0x000fc000, %d0 /* Set SDRAM cached only */
- movec %d0, %ACR2
- move.l #0x00000000, %d0 /* No other regions cached */
- movec %d0, %ACR3
-
- /* Enable cache */
- move.l #0xb6088400, %d0 /* Enable caches */
- movec %d0,%CACR
- nop
-
-
-#ifdef CONFIG_ROMFS_FS
- /*
- * Move ROM filesystem above bss :-)
- */
- lea.l _sbss, %a0 /* Get start of bss */
- lea.l _ebss, %a1 /* Set up destination */
- move.l %a0, %a2 /* Copy of bss start */
-
- move.l 8(%a0), %d0 /* Get size of ROMFS */
- addq.l #8, %d0 /* Allow for rounding */
- and.l #0xfffffffc, %d0 /* Whole words */
-
- add.l %d0, %a0 /* Copy from end */
- add.l %d0, %a1 /* Copy from end */
- move.l %a1, _ramstart /* Set start of ram */
-
-_copy_romfs:
- move.l -(%a0), %d0 /* Copy dword */
- move.l %d0, -(%a1)
- cmp.l %a0, %a2 /* Check if at end */
- bne _copy_romfs
-
-#else /* CONFIG_ROMFS_FS */
- lea.l _ebss, %a1
- move.l %a1, _ramstart
-#endif /* CONFIG_ROMFS_FS */
-
-
- /*
- * Zero out the bss region.
- */
- lea.l _sbss, %a0 /* Get start of bss */
- lea.l _ebss, %a1 /* Get end of bss */
- clr.l %d0 /* Set value */
-_clear_bss:
- move.l %d0, (%a0)+ /* Clear each word */
- cmp.l %a0, %a1 /* Check if at end */
- bne _clear_bss
-
- /*
- * Load the current task pointer and stack.
- */
- lea init_thread_union, %a0
- lea 0x2000(%a0), %sp
-
- /*
- * Assember start up done, start code proper.
- */
- jsr start_kernel /* Start Linux kernel */
-
-_exit:
- jmp _exit /* Should never get here */
-
-/*****************************************************************************/
diff --git a/arch/m68knommu/platform/5407/Makefile b/arch/m68knommu/platform/5407/Makefile
index dcfae2890c7d1..91b2f495dd396 100644
--- a/arch/m68knommu/platform/5407/Makefile
+++ b/arch/m68knommu/platform/5407/Makefile
@@ -18,4 +18,3 @@ endif
obj-y := config.o
-extra-y := $(BOARD)/crt0_$(MODEL).o
diff --git a/arch/m68knommu/platform/68328/Makefile b/arch/m68knommu/platform/68328/Makefile
index 80bf9bf50a65b..1b3b719e4479d 100644
--- a/arch/m68knommu/platform/68328/Makefile
+++ b/arch/m68knommu/platform/68328/Makefile
@@ -2,14 +2,20 @@
# Makefile for arch/m68knommu/platform/68328.
#
-obj-$(CONFIG_M68328) += entry.o ints.o config.o
-obj-$(CONFIG_M68EZ328) += entry.o ints.o
-obj-$(CONFIG_M68VZ328) += entry.o ints.o
+head-y = head-$(MODEL).o
+head-$(CONFIG_PILOT) = head-pilot.o
+head-$(CONFIG_DRAGEN2) = head-de2.o
-ifeq ($(CONFIG_M68328),y)
-extra-y := $(BOARD)/bootlogo.rh $(BOARD)/crt0_$(MODEL).o
-endif
+obj-y += entry.o ints.o timers.o
+obj-$(CONFIG_M68328) += config.o
-$(obj)/$(BOARD)/bootlogo.rh: $(src)/bootlogo.h
- perl $(src)/bootlogo.pl < $(src)/bootlogo.h > $(obj)/$(BOARD)/bootlogo.rh
+extra-y := head.o
+extra-$(CONFIG_M68328) += bootlogo.rh head.o
+$(obj)/bootlogo.rh: $(src)/bootlogo.h
+ perl $(src)/bootlogo.pl < $(src)/bootlogo.h > $(obj)/bootlogo.rh
+
+$(obj)/head.o: $(obj)/$(head-y)
+ ln -sf $(head-y) $(obj)/head.o
+
+clean-files := $(obj)/bootlogo.rh $(obj)/head.o $(head-y)
diff --git a/arch/m68knommu/platform/68328/pilot/crt0_rom.S b/arch/m68knommu/platform/68328/head-pilot.S
index 2bc208aa0347a..c46775fe04be0 100644
--- a/arch/m68knommu/platform/68328/pilot/crt0_rom.S
+++ b/arch/m68knommu/platform/68328/head-pilot.S
@@ -1,6 +1,6 @@
/*
- * linux/arch/m68knommu/platform/68328/pilot/crt0_rom.S
- * - A startup file for the MC68332
+ * linux/arch/m68knommu/platform/68328/head-rom.S
+ * - A startup file for the MC68328
*
* Copyright (C) 1998 D. Jeff Dionne <jeff@ryeham.ee.ryerson.ca>,
* Kenneth Albanowski <kjahds@kjahds.com>,
diff --git a/arch/m68knommu/platform/68VZ328/ucdimm/crt0_ram.S b/arch/m68knommu/platform/68328/head-ram.S
index 6bdc9bce43f2c..6bdc9bce43f2c 100644
--- a/arch/m68knommu/platform/68VZ328/ucdimm/crt0_ram.S
+++ b/arch/m68knommu/platform/68328/head-ram.S
diff --git a/arch/m68knommu/platform/68EZ328/ucsimm/crt0_fixed.S b/arch/m68knommu/platform/68328/head-rom.S
index 2b448a297011f..2b448a297011f 100644
--- a/arch/m68knommu/platform/68EZ328/ucsimm/crt0_fixed.S
+++ b/arch/m68knommu/platform/68328/head-rom.S
diff --git a/arch/m68knommu/platform/68360/Makefile b/arch/m68knommu/platform/68360/Makefile
index 3f21c1f488046..cf5af73a57899 100644
--- a/arch/m68knommu/platform/68360/Makefile
+++ b/arch/m68knommu/platform/68360/Makefile
@@ -4,4 +4,7 @@
obj-y := config.o commproc.o entry.o ints.o
-extra-y := $(BOARD)/crt0_$(MODEL).o
+extra-y := head.o
+
+$(obj)/head.o: $(obj)/head-$(MODEL).o
+ ln -sf head-$(MODEL).o $(obj)/head.o
diff --git a/arch/m68knommu/platform/68360/uCquicc/crt0_ram.S b/arch/m68knommu/platform/68360/uCquicc/crt0_ram.S
deleted file mode 100644
index 55200c6db5aff..0000000000000
--- a/arch/m68knommu/platform/68360/uCquicc/crt0_ram.S
+++ /dev/null
@@ -1,408 +0,0 @@
-/* arch/m68knommu/platform/68360/uCquicc/crt0_rom.S
- *
- * Startup code for Motorola 68360
- *
- * Copyright 2001 (C) SED Systems, a Division of Calian Ltd.
- * Based on: arch/m68knommu/platform/68328/pilot/crt0_rom.S
- * Based on: arch/m68knommu/platform/68360/uCquicc/crt0_rom.S, 2.0.38.1.pre7
- * uClinux Kernel
- * Copyright (C) Michael Leslie <mleslie@lineo.com>
- * Based on: arch/m68knommu/platform/68EZ328/ucsimm/crt0_rom.S
- * Copyright (C) 1998 D. Jeff Dionne <jeff@uclinux.org>,
- *
- */
-#define ASSEMBLY
-#include <linux/config.h>
-
-.global _stext
-.global _start
-
-.global _rambase
-.global __ramvec
-.global _ramvec
-.global _ramstart
-.global _ramend
-
-.global _quicc_base
-.global _periph_base
-
-#define REGB 0x1000
-#define PEPAR (_dprbase + REGB + 0x0016)
-#define GMR (_dprbase + REGB + 0x0040)
-#define OR0 (_dprbase + REGB + 0x0054)
-#define BR0 (_dprbase + REGB + 0x0050)
-#define OR1 (_dprbase + REGB + 0x0064)
-#define BR1 (_dprbase + REGB + 0x0060)
-#define OR4 (_dprbase + REGB + 0x0094)
-#define BR4 (_dprbase + REGB + 0x0090)
-#define OR6 (_dprbase + REGB + 0x00b4)
-#define BR6 (_dprbase + REGB + 0x00b0)
-#define OR7 (_dprbase + REGB + 0x00c4)
-#define BR7 (_dprbase + REGB + 0x00c0)
-
-#define MCR (_dprbase + REGB + 0x0000)
-#define AVR (_dprbase + REGB + 0x0008)
-
-#define SYPCR (_dprbase + REGB + 0x0022)
-
-#define PLLCR (_dprbase + REGB + 0x0010)
-#define CLKOCR (_dprbase + REGB + 0x000C)
-#define CDVCR (_dprbase + REGB + 0x0014)
-
-#define BKAR (_dprbase + REGB + 0x0030)
-#define BKCR (_dprbase + REGB + 0x0034)
-#define SWIV (_dprbase + REGB + 0x0023)
-#define PICR (_dprbase + REGB + 0x0026)
-#define PITR (_dprbase + REGB + 0x002A)
-
-/* Define for all memory configuration */
-#define MCU_SIM_GMR 0x00000000
-#define SIM_OR_MASK 0x0fffffff
-
-/* Defines for chip select zero - the flash */
-#define SIM_OR0_MASK 0x20000002
-#define SIM_BR0_MASK 0x00000001
-
-
-/* Defines for chip select one - the RAM */
-#define SIM_OR1_MASK 0x10000000
-#define SIM_BR1_MASK 0x00000001
-
-#define MCU_SIM_MBAR_ADRS 0x0003ff00
-#define MCU_SIM_MBAR_BA_MASK 0xfffff000
-#define MCU_SIM_MBAR_AS_MASK 0x00000001
-
-#define MCU_SIM_PEPAR 0x00B4
-
-#define MCU_DISABLE_INTRPTS 0x2700
-#define MCU_SIM_AVR 0x00
-
-#define MCU_SIM_MCR 0x00005cff
-
-#define MCU_SIM_CLKOCR 0x00
-#define MCU_SIM_PLLCR 0x8000
-#define MCU_SIM_CDVCR 0x0000
-
-#define MCU_SIM_SYPCR 0x0000
-#define MCU_SIM_SWIV 0x00
-#define MCU_SIM_PICR 0x0000
-#define MCU_SIM_PITR 0x0000
-
-
-#include <asm/m68360_regs.h>
-
-
-/*
- * By the time this RAM specific code begins to execute, DPRAM
- * and DRAM should already be mapped and accessible.
- */
-
- .text
-_start:
-_stext:
- nop
- ori.w #MCU_DISABLE_INTRPTS, %sr /* disable interrupts: */
- /* We should not need to setup the boot stack the reset should do it. */
- movea.l #__ramend, %sp /*set up stack at the end of DRAM:*/
-
-set_mbar_register:
- moveq.l #0x07, %d1 /* Setup MBAR */
- movec %d1, %dfc
-
- lea.l MCU_SIM_MBAR_ADRS, %a0
- move.l #_dprbase, %d0
- andi.l #MCU_SIM_MBAR_BA_MASK, %d0
- ori.l #MCU_SIM_MBAR_AS_MASK, %d0
- moves.l %d0, %a0@
-
- moveq.l #0x05, %d1
- movec.l %d1, %dfc
-
- /* Now we can begin to access registers in DPRAM */
-
-set_sim_mcr:
- /* Set Module Configuration Register */
- move.l #MCU_SIM_MCR, MCR
-
- /* to do: Determine cause of reset */
-
- /*
- * configure system clock MC68360 p. 6-40
- * (value +1)*osc/128 = system clock
- */
-set_sim_clock:
- move.w #MCU_SIM_PLLCR, PLLCR
- move.b #MCU_SIM_CLKOCR, CLKOCR
- move.w #MCU_SIM_CDVCR, CDVCR
-
- /* Wait for the PLL to settle */
- move.w #16384, %d0
-pll_settle_wait:
- subi.w #1, %d0
- bne pll_settle_wait
-
- /* Setup the system protection register, and watchdog timer register */
- move.b #MCU_SIM_SWIV, SWIV
- move.w #MCU_SIM_PICR, PICR
- move.w #MCU_SIM_PITR, PITR
- move.w #MCU_SIM_SYPCR, SYPCR
-
- /* Clear DPRAM - system + parameter */
- movea.l #_dprbase, %a0
- movea.l #_dprbase+0x2000, %a1
-
- /* Copy 0 to %a0 until %a0 == %a1 */
-clear_dpram:
- movel #0, %a0@+
- cmpal %a0, %a1
- bhi clear_dpram
-
-configure_memory_controller:
- /* Set up Global Memory Register (GMR) */
- move.l #MCU_SIM_GMR, %d0
- move.l %d0, GMR
-
-configure_chip_select_0:
- move.l #__ramend, %d0
- subi.l #__ramstart, %d0
- subq.l #0x01, %d0
- eori.l #SIM_OR_MASK, %d0
- ori.l #SIM_OR0_MASK, %d0
- move.l %d0, OR0
-
- move.l #__ramstart, %d0
- ori.l #SIM_BR0_MASK, %d0
- move.l %d0, BR0
-
-configure_chip_select_1:
- move.l #__rom_end, %d0
- subi.l #__rom_start, %d0
- subq.l #0x01, %d0
- eori.l #SIM_OR_MASK, %d0
- ori.l #SIM_OR1_MASK, %d0
- move.l %d0, OR1
-
- move.l #__rom_start, %d0
- ori.l #SIM_BR1_MASK, %d0
- move.l %d0, BR1
-
- move.w #MCU_SIM_PEPAR, PEPAR
-
- /* point to vector table: */
- move.l #_romvec, %a0
- move.l #_ramvec, %a1
-copy_vectors:
- move.l %a0@, %d0
- move.l %d0, %a1@
- move.l %a0@, %a1@
- addq.l #0x04, %a0
- addq.l #0x04, %a1
- cmp.l #_start, %a0
- blt copy_vectors
-
- move.l #_ramvec, %a1
- movec %a1, %vbr
-
-
- /* Copy data segment from ROM to RAM */
- moveal #_stext, %a0
- moveal #_sdata, %a1
- moveal #_edata, %a2
-
- /* Copy %a0 to %a1 until %a1 == %a2 */
-LD1:
- move.l %a0@, %d0
- addq.l #0x04, %a0
- move.l %d0, %a1@
- addq.l #0x04, %a1
- cmp.l #_edata, %a1
- blt LD1
-
- moveal #_sbss, %a0
- moveal #_ebss, %a1
-
- /* Copy 0 to %a0 until %a0 == %a1 */
-L1:
- movel #0, %a0@+
- cmpal %a0, %a1
- bhi L1
-
-load_quicc:
- move.l #_dprbase, _quicc_base
-
-store_ram_size:
- /* Set ram size information */
- move.l #_sdata, _rambase
- move.l #_ebss, _ramstart
- move.l #__ramend, %d0
- sub.l #0x1000, %d0 /* Reserve 4K for stack space.*/
- move.l %d0, _ramend /* Different from __ramend.*/
-
-store_flash_size:
- /* Set rom size information */
- move.l #__rom_end, %d0
- sub.l #__rom_start, %d0
- move.l %d0, rom_length
-
- pea 0
- pea env
- pea %sp@(4)
- pea 0
-
- lea init_thread_union, %a2
- lea 0x2000(%a2), %sp
-
-lp:
- jsr start_kernel
-
-_exit:
- jmp _exit
-
-
- .data
- .align 4
-env:
- .long 0
-_quicc_base:
- .long 0
-_periph_base:
- .long 0
-_ramvec:
- .long 0
-_rambase:
- .long 0
-_ramstart:
- .long 0
-_ramend:
- .long 0
-_dprbase:
- .long 0xffffe000
-
- .text
-
- /*
- * These are the exception vectors at boot up, they are copied into RAM
- * and then overwritten as needed.
- */
-
-.section ".data.initvect","awx"
- .long __ramend /* Reset: Initial Stack Pointer - 0. */
- .long _start /* Reset: Initial Program Counter - 1. */
- .long buserr /* Bus Error - 2. */
- .long trap /* Address Error - 3. */
- .long trap /* Illegal Instruction - 4. */
- .long trap /* Divide by zero - 5. */
- .long trap /* CHK, CHK2 Instructions - 6. */
- .long trap /* TRAPcc, TRAPV Instructions - 7. */
- .long trap /* Privilege Violation - 8. */
- .long trap /* Trace - 9. */
- .long trap /* Line 1010 Emulator - 10. */
- .long trap /* Line 1111 Emualtor - 11. */
- .long trap /* Harware Breakpoint - 12. */
- .long trap /* (Reserved for Coprocessor Protocol Violation)- 13. */
- .long trap /* Format Error - 14. */
- .long trap /* Uninitialized Interrupt - 15. */
- .long trap /* (Unassigned, Reserver) - 16. */
- .long trap /* (Unassigned, Reserver) - 17. */
- .long trap /* (Unassigned, Reserver) - 18. */
- .long trap /* (Unassigned, Reserver) - 19. */
- .long trap /* (Unassigned, Reserver) - 20. */
- .long trap /* (Unassigned, Reserver) - 21. */
- .long trap /* (Unassigned, Reserver) - 22. */
- .long trap /* (Unassigned, Reserver) - 23. */
- .long trap /* Spurious Interrupt - 24. */
- .long trap /* Level 1 Interrupt Autovector - 25. */
- .long trap /* Level 2 Interrupt Autovector - 26. */
- .long trap /* Level 3 Interrupt Autovector - 27. */
- .long trap /* Level 4 Interrupt Autovector - 28. */
- .long trap /* Level 5 Interrupt Autovector - 29. */
- .long trap /* Level 6 Interrupt Autovector - 30. */
- .long trap /* Level 7 Interrupt Autovector - 31. */
- .long system_call /* Trap Instruction Vectors 0 - 32. */
- .long trap /* Trap Instruction Vectors 1 - 33. */
- .long trap /* Trap Instruction Vectors 2 - 34. */
- .long trap /* Trap Instruction Vectors 3 - 35. */
- .long trap /* Trap Instruction Vectors 4 - 36. */
- .long trap /* Trap Instruction Vectors 5 - 37. */
- .long trap /* Trap Instruction Vectors 6 - 38. */
- .long trap /* Trap Instruction Vectors 7 - 39. */
- .long trap /* Trap Instruction Vectors 8 - 40. */
- .long trap /* Trap Instruction Vectors 9 - 41. */
- .long trap /* Trap Instruction Vectors 10 - 42. */
- .long trap /* Trap Instruction Vectors 11 - 43. */
- .long trap /* Trap Instruction Vectors 12 - 44. */
- .long trap /* Trap Instruction Vectors 13 - 45. */
- .long trap /* Trap Instruction Vectors 14 - 46. */
- .long trap /* Trap Instruction Vectors 15 - 47. */
- .long 0 /* (Reserved for Coprocessor) - 48. */
- .long 0 /* (Reserved for Coprocessor) - 49. */
- .long 0 /* (Reserved for Coprocessor) - 50. */
- .long 0 /* (Reserved for Coprocessor) - 51. */
- .long 0 /* (Reserved for Coprocessor) - 52. */
- .long 0 /* (Reserved for Coprocessor) - 53. */
- .long 0 /* (Reserved for Coprocessor) - 54. */
- .long 0 /* (Reserved for Coprocessor) - 55. */
- .long 0 /* (Reserved for Coprocessor) - 56. */
- .long 0 /* (Reserved for Coprocessor) - 57. */
- .long 0 /* (Reserved for Coprocessor) - 58. */
- .long 0 /* (Unassigned, Reserved) - 59. */
- .long 0 /* (Unassigned, Reserved) - 60. */
- .long 0 /* (Unassigned, Reserved) - 61. */
- .long 0 /* (Unassigned, Reserved) - 62. */
- .long 0 /* (Unassigned, Reserved) - 63. */
- /* The assignment of these vectors to the CPM is */
- /* dependent on the configuration of the CPM vba */
- /* fields. */
- .long 0 /* (User-Defined Vectors 1) CPM Error - 64. */
- .long 0 /* (User-Defined Vectors 2) CPM Parallel IO PC11- 65. */
- .long 0 /* (User-Defined Vectors 3) CPM Parallel IO PC10- 66. */
- .long 0 /* (User-Defined Vectors 4) CPM SMC2 / PIP - 67. */
- .long 0 /* (User-Defined Vectors 5) CPM SMC1 - 68. */
- .long 0 /* (User-Defined Vectors 6) CPM SPI - 69. */
- .long 0 /* (User-Defined Vectors 7) CPM Parallel IO PC9 - 70. */
- .long 0 /* (User-Defined Vectors 8) CPM Timer 4 - 71. */
- .long 0 /* (User-Defined Vectors 9) CPM Reserved - 72. */
- .long 0 /* (User-Defined Vectors 10) CPM Parallel IO PC8- 73. */
- .long 0 /* (User-Defined Vectors 11) CPM Parallel IO PC7- 74. */
- .long 0 /* (User-Defined Vectors 12) CPM Parallel IO PC6- 75. */
- .long 0 /* (User-Defined Vectors 13) CPM Timer 3 - 76. */
- .long 0 /* (User-Defined Vectors 14) CPM Reserved - 77. */
- .long 0 /* (User-Defined Vectors 15) CPM Parallel IO PC5- 78. */
- .long 0 /* (User-Defined Vectors 16) CPM Parallel IO PC4- 79. */
- .long 0 /* (User-Defined Vectors 17) CPM Reserved - 80. */
- .long 0 /* (User-Defined Vectors 18) CPM RISC Timer Tbl - 81. */
- .long 0 /* (User-Defined Vectors 19) CPM Timer 2 - 82. */
- .long 0 /* (User-Defined Vectors 21) CPM Reserved - 83. */
- .long 0 /* (User-Defined Vectors 22) CPM IDMA2 - 84. */
- .long 0 /* (User-Defined Vectors 23) CPM IDMA1 - 85. */
- .long 0 /* (User-Defined Vectors 24) CPM SDMA Bus Err - 86. */
- .long 0 /* (User-Defined Vectors 25) CPM Parallel IO PC3- 87. */
- .long 0 /* (User-Defined Vectors 26) CPM Parallel IO PC2- 88. */
- .long 0 /* (User-Defined Vectors 27) CPM Timer 1 - 89. */
- .long 0 /* (User-Defined Vectors 28) CPM Parallel IO PC1- 90. */
- .long 0 /* (User-Defined Vectors 29) CPM SCC 4 - 91. */
- .long 0 /* (User-Defined Vectors 30) CPM SCC 3 - 92. */
- .long 0 /* (User-Defined Vectors 31) CPM SCC 2 - 93. */
- .long 0 /* (User-Defined Vectors 32) CPM SCC 1 - 94. */
- .long 0 /* (User-Defined Vectors 33) CPM Parallel IO PC0- 95. */
- /* I don't think anything uses the vectors after here. */
- .long 0 /* (User-Defined Vectors 34) - 96. */
- .long 0,0,0,0,0 /* (User-Defined Vectors 35 - 39). */
- .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 40 - 49). */
- .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 50 - 59). */
- .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 60 - 69). */
- .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 70 - 79). */
- .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 80 - 89). */
- .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 90 - 99). */
- .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 100 - 109). */
- .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 110 - 119). */
- .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 120 - 129). */
- .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 130 - 139). */
- .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 140 - 149). */
- .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 150 - 159). */
- .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 160 - 169). */
- .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 170 - 179). */
- .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 180 - 189). */
- .long 0,0,0 /* (User-Defined Vectors 190 - 192). */
-.text
-ignore: rte
diff --git a/arch/m68knommu/platform/68360/uCquicc/crt0_rom.S b/arch/m68knommu/platform/68360/uCquicc/crt0_rom.S
deleted file mode 100644
index cb6da69d90079..0000000000000
--- a/arch/m68knommu/platform/68360/uCquicc/crt0_rom.S
+++ /dev/null
@@ -1,420 +0,0 @@
-/* arch/m68knommu/platform/68360/uCquicc/crt0_rom.S
- *
- * Startup code for Motorola 68360
- *
- * Copyright (C) SED Systems, a Division of Calian Ltd.
- * Based on: arch/m68knommu/platform/68328/pilot/crt0_rom.S
- * Based on: arch/m68knommu/platform/68360/uCquicc/crt0_rom.S, 2.0.38.1.pre7
- * uClinux Kernel
- * Copyright (C) Michael Leslie <mleslie@lineo.com>
- * Based on: arch/m68knommu/platform/68EZ328/ucsimm/crt0_rom.S
- * Copyright (C) 1998 D. Jeff Dionne <jeff@uclinux.org>,
- *
- */
-#include <linux/config.h>
-
-.global _stext
-.global _sbss
-.global _start
-
-.global _rambase
-.global __ramvec
-.global _ramvec
-.global _ramstart
-.global _ramend
-
-.global _quicc_base
-.global _periph_base
-
-#define REGB 0x1000
-#define PEPAR (_dprbase + REGB + 0x0016)
-#define GMR (_dprbase + REGB + 0x0040)
-#define OR0 (_dprbase + REGB + 0x0054)
-#define BR0 (_dprbase + REGB + 0x0050)
-
-#define OR1 (_dprbase + REGB + 0x0064)
-#define BR1 (_dprbase + REGB + 0x0060)
-
-#define OR2 (_dprbase + REGB + 0x0074)
-#define BR2 (_dprbase + REGB + 0x0070)
-
-#define OR3 (_dprbase + REGB + 0x0084)
-#define BR3 (_dprbase + REGB + 0x0080)
-
-#define OR4 (_dprbase + REGB + 0x0094)
-#define BR4 (_dprbase + REGB + 0x0090)
-
-#define OR5 (_dprbase + REGB + 0x00A4)
-#define BR5 (_dprbase + REGB + 0x00A0)
-
-#define OR6 (_dprbase + REGB + 0x00b4)
-#define BR6 (_dprbase + REGB + 0x00b0)
-
-#define OR7 (_dprbase + REGB + 0x00c4)
-#define BR7 (_dprbase + REGB + 0x00c0)
-
-#define MCR (_dprbase + REGB + 0x0000)
-#define AVR (_dprbase + REGB + 0x0008)
-
-#define SYPCR (_dprbase + REGB + 0x0022)
-
-#define PLLCR (_dprbase + REGB + 0x0010)
-#define CLKOCR (_dprbase + REGB + 0x000C)
-#define CDVCR (_dprbase + REGB + 0x0014)
-
-#define BKAR (_dprbase + REGB + 0x0030)
-#define BKCR (_dprbase + REGB + 0x0034)
-#define SWIV (_dprbase + REGB + 0x0023)
-#define PICR (_dprbase + REGB + 0x0026)
-#define PITR (_dprbase + REGB + 0x002A)
-
-/* Define for all memory configuration */
-#define MCU_SIM_GMR 0x00000000
-#define SIM_OR_MASK 0x0fffffff
-
-/* Defines for chip select zero - the flash */
-#define SIM_OR0_MASK 0x20000000
-#define SIM_BR0_MASK 0x00000001
-
-/* Defines for chip select one - the RAM */
-#define SIM_OR1_MASK 0x10000000
-#define SIM_BR1_MASK 0x00000001
-
-#define MCU_SIM_MBAR_ADRS 0x0003ff00
-#define MCU_SIM_MBAR_BA_MASK 0xfffff000
-#define MCU_SIM_MBAR_AS_MASK 0x00000001
-
-#define MCU_SIM_PEPAR 0x00B4
-
-#define MCU_DISABLE_INTRPTS 0x2700
-#define MCU_SIM_AVR 0x00
-
-#define MCU_SIM_MCR 0x00005cff
-
-#define MCU_SIM_CLKOCR 0x00
-#define MCU_SIM_PLLCR 0x8000
-#define MCU_SIM_CDVCR 0x0000
-
-#define MCU_SIM_SYPCR 0x0000
-#define MCU_SIM_SWIV 0x00
-#define MCU_SIM_PICR 0x0000
-#define MCU_SIM_PITR 0x0000
-
-
-#include <asm/m68360_regs.h>
-
-
-/*
- * By the time this RAM specific code begins to execute, DPRAM
- * and DRAM should already be mapped and accessible.
- */
-
- .text
-_start:
-_stext:
- nop
- ori.w #MCU_DISABLE_INTRPTS, %sr /* disable interrupts: */
- /* We should not need to setup the boot stack the reset should do it. */
- movea.l #__ramend, %sp /* set up stack at the end of DRAM:*/
-
-
-set_mbar_register:
- moveq.l #0x07, %d1 /* Setup MBAR */
- movec %d1, %dfc
-
- lea.l MCU_SIM_MBAR_ADRS, %a0
- move.l #_dprbase, %d0
- andi.l #MCU_SIM_MBAR_BA_MASK, %d0
- ori.l #MCU_SIM_MBAR_AS_MASK, %d0
- moves.l %d0, %a0@
-
- moveq.l #0x05, %d1
- movec.l %d1, %dfc
-
- /* Now we can begin to access registers in DPRAM */
-
-set_sim_mcr:
- /* Set Module Configuration Register */
- move.l #MCU_SIM_MCR, MCR
-
- /* to do: Determine cause of reset */
-
- /*
- * configure system clock MC68360 p. 6-40
- * (value +1)*osc/128 = system clock
- * or
- * (value + 1)*osc = system clock
- * You do not need to divide the oscillator by 128 unless you want to.
- */
-set_sim_clock:
- move.w #MCU_SIM_PLLCR, PLLCR
- move.b #MCU_SIM_CLKOCR, CLKOCR
- move.w #MCU_SIM_CDVCR, CDVCR
-
- /* Wait for the PLL to settle */
- move.w #16384, %d0
-pll_settle_wait:
- subi.w #1, %d0
- bne pll_settle_wait
-
- /* Setup the system protection register, and watchdog timer register */
- move.b #MCU_SIM_SWIV, SWIV
- move.w #MCU_SIM_PICR, PICR
- move.w #MCU_SIM_PITR, PITR
- move.w #MCU_SIM_SYPCR, SYPCR
-
- /* Clear DPRAM - system + parameter */
- movea.l #_dprbase, %a0
- movea.l #_dprbase+0x2000, %a1
-
- /* Copy 0 to %a0 until %a0 == %a1 */
-clear_dpram:
- movel #0, %a0@+
- cmpal %a0, %a1
- bhi clear_dpram
-
-configure_memory_controller:
- /* Set up Global Memory Register (GMR) */
- move.l #MCU_SIM_GMR, %d0
- move.l %d0, GMR
-
-configure_chip_select_0:
- move.l #0x00400000, %d0
- subq.l #0x01, %d0
- eori.l #SIM_OR_MASK, %d0
- ori.l #SIM_OR0_MASK, %d0
- move.l %d0, OR0
-
- move.l #__rom_start, %d0
- ori.l #SIM_BR0_MASK, %d0
- move.l %d0, BR0
-
- move.l #0x0, BR1
- move.l #0x0, BR2
- move.l #0x0, BR3
- move.l #0x0, BR4
- move.l #0x0, BR5
- move.l #0x0, BR6
- move.l #0x0, BR7
-
- move.w #MCU_SIM_PEPAR, PEPAR
-
- /* point to vector table: */
- move.l #_romvec, %a0
- move.l #_ramvec, %a1
-copy_vectors:
- move.l %a0@, %d0
- move.l %d0, %a1@
- move.l %a0@, %a1@
- addq.l #0x04, %a0
- addq.l #0x04, %a1
- cmp.l #_start, %a0
- blt copy_vectors
-
- move.l #_ramvec, %a1
- movec %a1, %vbr
-
-
- /* Copy data segment from ROM to RAM */
- moveal #_etext, %a0
- moveal #_sdata, %a1
- moveal #_edata, %a2
-
- /* Copy %a0 to %a1 until %a1 == %a2 */
-LD1:
- move.l %a0@, %d0
- addq.l #0x04, %a0
- move.l %d0, %a1@
- addq.l #0x04, %a1
- cmp.l #_edata, %a1
- blt LD1
-
- moveal #_sbss, %a0
- moveal #_ebss, %a1
-
- /* Copy 0 to %a0 until %a0 == %a1 */
-L1:
- movel #0, %a0@+
- cmpal %a0, %a1
- bhi L1
-
-load_quicc:
- move.l #_dprbase, _quicc_base
-
-store_ram_size:
- /* Set ram size information */
- move.l #_sdata, _rambase
- move.l #_ebss, _ramstart
- move.l #__ramend, %d0
- sub.l #0x1000, %d0 /* Reserve 4K for stack space.*/
- move.l %d0, _ramend /* Different from __ramend.*/
-
-store_flash_size:
- /* Set rom size information */
- move.l #__rom_end, %d0
- sub.l #__rom_start, %d0
- move.l %d0, rom_length
-
- pea 0
- pea env
- pea %sp@(4)
- pea 0
-
- lea init_thread_union, %a2
- lea 0x2000(%a2), %sp
-
-lp:
- jsr start_kernel
-
-_exit:
- jmp _exit
-
-
- .data
- .align 4
-env:
- .long 0
-_quicc_base:
- .long 0
-_periph_base:
- .long 0
-_ramvec:
- .long 0
-_rambase:
- .long 0
-_ramstart:
- .long 0
-_ramend:
- .long 0
-_dprbase:
- .long 0xffffe000
-
-
- .text
-
- /*
- * These are the exception vectors at boot up, they are copied into RAM
- * and then overwritten as needed.
- */
-
-.section ".data.initvect","awx"
- .long __ramend /* Reset: Initial Stack Pointer - 0. */
- .long _start /* Reset: Initial Program Counter - 1. */
- .long buserr /* Bus Error - 2. */
- .long trap /* Address Error - 3. */
- .long trap /* Illegal Instruction - 4. */
- .long trap /* Divide by zero - 5. */
- .long trap /* CHK, CHK2 Instructions - 6. */
- .long trap /* TRAPcc, TRAPV Instructions - 7. */
- .long trap /* Privilege Violation - 8. */
- .long trap /* Trace - 9. */
- .long trap /* Line 1010 Emulator - 10. */
- .long trap /* Line 1111 Emualtor - 11. */
- .long trap /* Harware Breakpoint - 12. */
- .long trap /* (Reserved for Coprocessor Protocol Violation)- 13. */
- .long trap /* Format Error - 14. */
- .long trap /* Uninitialized Interrupt - 15. */
- .long trap /* (Unassigned, Reserver) - 16. */
- .long trap /* (Unassigned, Reserver) - 17. */
- .long trap /* (Unassigned, Reserver) - 18. */
- .long trap /* (Unassigned, Reserver) - 19. */
- .long trap /* (Unassigned, Reserver) - 20. */
- .long trap /* (Unassigned, Reserver) - 21. */
- .long trap /* (Unassigned, Reserver) - 22. */
- .long trap /* (Unassigned, Reserver) - 23. */
- .long trap /* Spurious Interrupt - 24. */
- .long trap /* Level 1 Interrupt Autovector - 25. */
- .long trap /* Level 2 Interrupt Autovector - 26. */
- .long trap /* Level 3 Interrupt Autovector - 27. */
- .long trap /* Level 4 Interrupt Autovector - 28. */
- .long trap /* Level 5 Interrupt Autovector - 29. */
- .long trap /* Level 6 Interrupt Autovector - 30. */
- .long trap /* Level 7 Interrupt Autovector - 31. */
- .long system_call /* Trap Instruction Vectors 0 - 32. */
- .long trap /* Trap Instruction Vectors 1 - 33. */
- .long trap /* Trap Instruction Vectors 2 - 34. */
- .long trap /* Trap Instruction Vectors 3 - 35. */
- .long trap /* Trap Instruction Vectors 4 - 36. */
- .long trap /* Trap Instruction Vectors 5 - 37. */
- .long trap /* Trap Instruction Vectors 6 - 38. */
- .long trap /* Trap Instruction Vectors 7 - 39. */
- .long trap /* Trap Instruction Vectors 8 - 40. */
- .long trap /* Trap Instruction Vectors 9 - 41. */
- .long trap /* Trap Instruction Vectors 10 - 42. */
- .long trap /* Trap Instruction Vectors 11 - 43. */
- .long trap /* Trap Instruction Vectors 12 - 44. */
- .long trap /* Trap Instruction Vectors 13 - 45. */
- .long trap /* Trap Instruction Vectors 14 - 46. */
- .long trap /* Trap Instruction Vectors 15 - 47. */
- .long 0 /* (Reserved for Coprocessor) - 48. */
- .long 0 /* (Reserved for Coprocessor) - 49. */
- .long 0 /* (Reserved for Coprocessor) - 50. */
- .long 0 /* (Reserved for Coprocessor) - 51. */
- .long 0 /* (Reserved for Coprocessor) - 52. */
- .long 0 /* (Reserved for Coprocessor) - 53. */
- .long 0 /* (Reserved for Coprocessor) - 54. */
- .long 0 /* (Reserved for Coprocessor) - 55. */
- .long 0 /* (Reserved for Coprocessor) - 56. */
- .long 0 /* (Reserved for Coprocessor) - 57. */
- .long 0 /* (Reserved for Coprocessor) - 58. */
- .long 0 /* (Unassigned, Reserved) - 59. */
- .long 0 /* (Unassigned, Reserved) - 60. */
- .long 0 /* (Unassigned, Reserved) - 61. */
- .long 0 /* (Unassigned, Reserved) - 62. */
- .long 0 /* (Unassigned, Reserved) - 63. */
- /* The assignment of these vectors to the CPM is */
- /* dependent on the configuration of the CPM vba */
- /* fields. */
- .long 0 /* (User-Defined Vectors 1) CPM Error - 64. */
- .long 0 /* (User-Defined Vectors 2) CPM Parallel IO PC11- 65. */
- .long 0 /* (User-Defined Vectors 3) CPM Parallel IO PC10- 66. */
- .long 0 /* (User-Defined Vectors 4) CPM SMC2 / PIP - 67. */
- .long 0 /* (User-Defined Vectors 5) CPM SMC1 - 68. */
- .long 0 /* (User-Defined Vectors 6) CPM SPI - 69. */
- .long 0 /* (User-Defined Vectors 7) CPM Parallel IO PC9 - 70. */
- .long 0 /* (User-Defined Vectors 8) CPM Timer 4 - 71. */
- .long 0 /* (User-Defined Vectors 9) CPM Reserved - 72. */
- .long 0 /* (User-Defined Vectors 10) CPM Parallel IO PC8- 73. */
- .long 0 /* (User-Defined Vectors 11) CPM Parallel IO PC7- 74. */
- .long 0 /* (User-Defined Vectors 12) CPM Parallel IO PC6- 75. */
- .long 0 /* (User-Defined Vectors 13) CPM Timer 3 - 76. */
- .long 0 /* (User-Defined Vectors 14) CPM Reserved - 77. */
- .long 0 /* (User-Defined Vectors 15) CPM Parallel IO PC5- 78. */
- .long 0 /* (User-Defined Vectors 16) CPM Parallel IO PC4- 79. */
- .long 0 /* (User-Defined Vectors 17) CPM Reserved - 80. */
- .long 0 /* (User-Defined Vectors 18) CPM RISC Timer Tbl - 81. */
- .long 0 /* (User-Defined Vectors 19) CPM Timer 2 - 82. */
- .long 0 /* (User-Defined Vectors 21) CPM Reserved - 83. */
- .long 0 /* (User-Defined Vectors 22) CPM IDMA2 - 84. */
- .long 0 /* (User-Defined Vectors 23) CPM IDMA1 - 85. */
- .long 0 /* (User-Defined Vectors 24) CPM SDMA Bus Err - 86. */
- .long 0 /* (User-Defined Vectors 25) CPM Parallel IO PC3- 87. */
- .long 0 /* (User-Defined Vectors 26) CPM Parallel IO PC2- 88. */
- .long 0 /* (User-Defined Vectors 27) CPM Timer 1 - 89. */
- .long 0 /* (User-Defined Vectors 28) CPM Parallel IO PC1- 90. */
- .long 0 /* (User-Defined Vectors 29) CPM SCC 4 - 91. */
- .long 0 /* (User-Defined Vectors 30) CPM SCC 3 - 92. */
- .long 0 /* (User-Defined Vectors 31) CPM SCC 2 - 93. */
- .long 0 /* (User-Defined Vectors 32) CPM SCC 1 - 94. */
- .long 0 /* (User-Defined Vectors 33) CPM Parallel IO PC0- 95. */
- /* I don't think anything uses the vectors after here. */
- .long 0 /* (User-Defined Vectors 34) - 96. */
- .long 0,0,0,0,0 /* (User-Defined Vectors 35 - 39). */
- .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 40 - 49). */
- .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 50 - 59). */
- .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 60 - 69). */
- .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 70 - 79). */
- .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 80 - 89). */
- .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 90 - 99). */
- .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 100 - 109). */
- .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 110 - 119). */
- .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 120 - 129). */
- .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 130 - 139). */
- .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 140 - 149). */
- .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 150 - 159). */
- .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 160 - 169). */
- .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 170 - 179). */
- .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 180 - 189). */
- .long 0,0,0 /* (User-Defined Vectors 190 - 192). */
-.text
-ignore: rte
diff --git a/arch/m68knommu/platform/68EZ328/Makefile b/arch/m68knommu/platform/68EZ328/Makefile
index 17b573d1ca11f..ee97735a242c5 100644
--- a/arch/m68knommu/platform/68EZ328/Makefile
+++ b/arch/m68knommu/platform/68EZ328/Makefile
@@ -4,9 +4,8 @@
obj-y := config.o
-extra-y := $(BOARD)/bootlogo.rh $(BOARD)/crt0_$(MODEL).o
+extra-y := bootlogo.rh
-$(obj)/$(BOARD)/bootlogo.rh: $(src)/bootlogo.h
+$(obj)/bootlogo.rh: $(src)/bootlogo.h
perl $(src)/../68328/bootlogo.pl < $(src)/bootlogo.h \
- > $(obj)/$(BOARD)/bootlogo.rh
-
+ > $(obj)/bootlogo.rh
diff --git a/arch/m68knommu/platform/68EZ328/ucsimm/crt0_himem.S b/arch/m68knommu/platform/68EZ328/ucsimm/crt0_himem.S
deleted file mode 100644
index 4b9022a76f5ee..0000000000000
--- a/arch/m68knommu/platform/68EZ328/ucsimm/crt0_himem.S
+++ /dev/null
@@ -1 +0,0 @@
-#include "crt0_fixed.S"
diff --git a/arch/m68knommu/platform/68EZ328/ucsimm/crt0_ram.S b/arch/m68knommu/platform/68EZ328/ucsimm/crt0_ram.S
deleted file mode 100644
index 7034155342fbd..0000000000000
--- a/arch/m68knommu/platform/68EZ328/ucsimm/crt0_ram.S
+++ /dev/null
@@ -1,167 +0,0 @@
- .global __main
- .global __ram_start
- .global __ram_end
- .global __rom_start
- .global __rom_end
-
- .global _rambase
- .global _ramstart
-
- .global splash_bits
- .global _start
- .global _stext
-
-#define DEBUG
-#define ROM_OFFSET 0x10C00000
-#define STACK_GAURD 0x10
-
- .text
-
-_start:
-_stext:
- movew #0x2700, %sr /* Exceptions off! */
-
- /* Init chip registers. uCsimm specific */
- moveb #0x00, 0xfffffb0b /* Watchdog off */
- moveb #0x10, 0xfffff000 /* SCR */
-
- movew #0x2400, 0xfffff200 /* PLLCR */
- movew #0x0123, 0xfffff202 /* PLLFSR */
-
- moveb #0x00, 0xfffff40b /* enable chip select */
- moveb #0x00, 0xfffff423 /* enable /DWE */
- moveb #0x08, 0xfffffd0d /* disable hardmap */
- moveb #0x07, 0xfffffd0e /* level 7 interrupt clear */
-
- movew #0x8600, 0xfffff100 /* FLASH at 0x10c00000 */
- movew #0x018b, 0xfffff110 /* 2Meg, enable, 0ws */
-
- movew #0x8f00, 0xfffffc00 /* DRAM configuration */
- movew #0x9667, 0xfffffc02 /* DRAM control */
- movew #0x0000, 0xfffff106 /* DRAM at 0x00000000 */
- movew #0x068f, 0xfffff116 /* 8Meg, enable, 0ws */
-
- moveb #0x40, 0xfffff300 /* IVR */
- movel #0x007FFFFF, %d0 /* IMR */
- movel %d0, 0xfffff304
-
- moveb 0xfffff42b, %d0
- andb #0xe0, %d0
- moveb %d0, 0xfffff42b
-
- moveb #0x08, 0xfffff907 /* Ignore CTS */
- movew #0x010b, 0xfffff902 /* BAUD to 9600 */
- movew #0xe100, 0xfffff900 /* enable */
-
- movew #16384, %d0 /* PLL settle wait loop */
-L0:
- subw #1, %d0
- bne L0
-#ifdef DEBUG
- moveq #70, %d7 /* 'F' */
- moveb %d7,0xfffff907 /* No absolute addresses */
-pclp1:
- movew 0xfffff906, %d7
- andw #0x2000, %d7
- beq pclp1
-#endif /* DEBUG */
-
-#ifdef CONFIG_RELOCATE
- /* Copy me to RAM */
- moveal #__rom_start, %a0
- moveal #__ram_start, %a1
- moveal #_edata, %a2
-
- /* Copy %a0 to %a1 until %a1 == %a2 */
-LD1:
- movel %a0@+, %d0
- movel %d0, %a1@+
- cmpal %a1, %a2
- bhi LD1
-
-#ifdef DEBUG
- moveq #74, %d7 /* 'J' */
- moveb %d7,0xfffff907 /* No absolute addresses */
-pclp2:
- movew 0xfffff906, %d7
- andw #0x2000, %d7
- beq pclp2
-#endif /* DEBUG */
- /* jump into the RAM copy */
- jmp ram_jump
-ram_jump:
-
-#endif /* CONFIG_RELOCATE */
-
-#ifdef DEBUG
- moveq #82, %d7 /* 'R' */
- moveb %d7,0xfffff907 /* No absolute addresses */
-pclp3:
- movew 0xfffff906, %d7
- andw #0x2000, %d7
- beq pclp3
-#endif /* DEBUG */
- moveal #0x007ffff0, %ssp
- moveal #_sbss, %a0
- moveal #_ebss, %a1
-
- /* Copy 0 to %a0 until %a0 >= %a1 */
-L1:
- movel #0, %a0@+
- cmpal %a0, %a1
- bhi L1
-
-#ifdef DEBUG
- moveq #67, %d7 /* 'C' */
- jsr putc
-#endif /* DEBUG */
-
- pea 0
- pea env
- pea %sp@(4)
- pea 0
-
-#ifdef DEBUG
- moveq #70, %d7 /* 'F' */
- jsr putc
-#endif /* DEBUG */
-
-lp:
- jsr start_kernel
- jmp lp
-_exit:
-
- jmp _exit
-
-__main:
- /* nothing */
- rts
-
-#ifdef DEBUG
-putc:
- moveb %d7,0xfffff907
-pclp:
- movew 0xfffff906, %d7
- andw #0x2000, %d7
- beq pclp
- rts
-#endif /* DEBUG */
-
- .data
-
-/*
- * Set up the usable of RAM stuff. Size of RAM is determined then
- * an initial stack set up at the end.
- */
-.align 4
-_ramvec:
-.long 0
-_rambase:
-.long 0
-_ramstart:
-.long 0
-_ramend:
-.long 0
-
-env:
- .long 0
diff --git a/arch/m68knommu/platform/68EZ328/ucsimm/crt0_rom.S b/arch/m68knommu/platform/68EZ328/ucsimm/crt0_rom.S
deleted file mode 100644
index 4b9022a76f5ee..0000000000000
--- a/arch/m68knommu/platform/68EZ328/ucsimm/crt0_rom.S
+++ /dev/null
@@ -1 +0,0 @@
-#include "crt0_fixed.S"
diff --git a/arch/m68knommu/platform/68VZ328/Makefile b/arch/m68knommu/platform/68VZ328/Makefile
index f73432198665b..447ffa0fd7c7a 100644
--- a/arch/m68knommu/platform/68VZ328/Makefile
+++ b/arch/m68knommu/platform/68VZ328/Makefile
@@ -2,5 +2,15 @@
# Makefile for arch/m68knommu/platform/68VZ328.
#
-obj-y := $(BOARD)/
+obj-y := config.o
+logo-$(UCDIMM) := bootlogo.rh
+logo-$(DRAGEN2) := screen.h
+extra-y := $(logo-y)
+$(obj)/bootlogo.rh: $(src)/../68EZ328/bootlogo.h
+ perl $(src)/bootlogo.pl < $(src)/../68328/bootlogo.h > $(obj)/bootlogo.rh
+
+$(obj)/screen.h: $(src)/screen.xbm $(src)/xbm2lcd.pl
+ perl $(src)/xbm2lcd.pl < $(src)/screen.xbm > $(obj)/screen.h
+
+clean-files := $(obj)/screen.h $(obj)/bootlogo.rh
diff --git a/arch/m68knommu/platform/68VZ328/de2/Makefile b/arch/m68knommu/platform/68VZ328/de2/Makefile
deleted file mode 100644
index 409f96fdfabb8..0000000000000
--- a/arch/m68knommu/platform/68VZ328/de2/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-#
-# Makefile for arch/m68knommu/platform/68VZ328/de2.
-#
-
-obj-y := config.o
-
-EXTRA_TARGETS := bootlogo.rh crt0_$(MODEL).o
-
-$(obj)/bootlogo.rh: $(src)/../../68EZ328/bootlogo.h
- perl $(src)/../../68328/bootlogo.pl < $(src)/../../68EZ328/bootlogo.h \
- > $(obj)/bootlogo.rh
-
diff --git a/arch/m68knommu/platform/68VZ328/de2/crt0_ram.S b/arch/m68knommu/platform/68VZ328/de2/crt0_ram.S
deleted file mode 100644
index 94c5a1609a753..0000000000000
--- a/arch/m68knommu/platform/68VZ328/de2/crt0_ram.S
+++ /dev/null
@@ -1,135 +0,0 @@
-#include <linux/config.h>
-
-#if defined(CONFIG_RAM32MB)
-#define MEM_END 0x02000000 /* Memory size 32Mb */
-#elif defined(CONFIG_RAM16MB)
-#define MEM_END 0x01000000 /* Memory size 16Mb */
-#else
-#define MEM_END 0x00800000 /* Memory size 8Mb */
-#endif
-
-#undef CRT_DEBUG
-
-.macro PUTC CHAR
-#ifdef CRT_DEBUG
- moveq #\CHAR, %d7
- jsr putc
-#endif
-.endm
-
- .global _start
- .global _rambase
- .global _ramvec
- .global _ramstart
- .global _ramend
-
- .data
-
-/*
- * Set up the usable of RAM stuff
- */
-_rambase:
- .long 0
-_ramvec:
- .long 0
-_ramstart:
- .long 0
-_ramend:
- .long 0
-
- .text
-
-_start:
-
-/*
- * Setup initial stack
- */
- /* disable all interrupts */
- movew #0x2700, %sr
- movel #-1, 0xfffff304
- movel #MEM_END-4, %sp
-
- PUTC '\r'
- PUTC '\n'
- PUTC 'A'
- PUTC 'B'
-
-/*
- * Determine end of RAM
- */
-
- movel #MEM_END, %a0
- movel %a0, _ramend
-
- PUTC 'C'
-
-/*
- * Move ROM filesystem above bss :-)
- */
-
- moveal #_sbss, %a0 /* romfs at the start of bss */
- moveal #_ebss, %a1 /* Set up destination */
- movel %a0, %a2 /* Copy of bss start */
-
- movel 8(%a0), %d1 /* Get size of ROMFS */
- addql #8, %d1 /* Allow for rounding */
- andl #0xfffffffc, %d1 /* Whole words */
-
- addl %d1, %a0 /* Copy from end */
- addl %d1, %a1 /* Copy from end */
- movel %a1, _ramstart /* Set start of ram */
-
-1:
- movel -(%a0), %d0 /* Copy dword */
- movel %d0, -(%a1)
- cmpl %a0, %a2 /* Check if at end */
- bne 1b
-
- PUTC 'D'
-
-/*
- * Initialize BSS segment to 0
- */
-
- lea _sbss, %a0
- lea _ebss, %a1
-
- /* Copy 0 to %a0 until %a0 == %a1 */
-2: cmpal %a0, %a1
- beq 1f
- clrl (%a0)+
- bra 2b
-1:
-
- PUTC 'E'
-
-/*
- * Load the current task pointer and stack
- */
-
- lea init_thread_union, %a0
- lea 0x2000(%a0), %sp
-
- PUTC 'F'
- PUTC '\r'
- PUTC '\n'
-
-/*
- * Go
- */
-
- jmp start_kernel
-
-/*
- * Local functions
- */
-
-#ifdef CRT_DEBUG
-putc:
- moveb %d7, 0xfffff907
-1:
- movew 0xfffff906, %d7
- andw #0x2000, %d7
- beq 1b
- rts
-#endif
diff --git a/arch/m68knommu/platform/68VZ328/ucdimm/Makefile b/arch/m68knommu/platform/68VZ328/ucdimm/Makefile
deleted file mode 100644
index 52835a11d6ca9..0000000000000
--- a/arch/m68knommu/platform/68VZ328/ucdimm/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-#
-# Makefile for arch/m68knommu/platform/68VZ328/ucdimm.
-#
-
-obj-y := config.o
-
-EXTRA_TARGETS := bootlogo.rh crt0_$(MODEL).o
-
-$(obj)/bootlogo.rh: $(src)/../../68EZ328/bootlogo.h
- perl $(src)/../../68328/bootlogo.pl < $(src)/../../68EZ328/bootlogo.h \
- > $(obj)/bootlogo.rh
-
diff --git a/arch/m68knommu/platform/68VZ328/ucdimm/crt0_fixed.S b/arch/m68knommu/platform/68VZ328/ucdimm/crt0_fixed.S
deleted file mode 100644
index 2b448a297011f..0000000000000
--- a/arch/m68knommu/platform/68VZ328/ucdimm/crt0_fixed.S
+++ /dev/null
@@ -1,109 +0,0 @@
-#include <linux/config.h>
-
- .global _start
- .global _stext
-
- .global _rambase
- .global _ramvec
- .global _ramstart
- .global _ramend
-
-#ifdef CONFIG_INIT_LCD
- .global splash_bits
-#endif
-
- .data
-
-/*
- * Set up the usable of RAM stuff. Size of RAM is determined then
- * an initial stack set up at the end.
- */
-.align 4
-_ramvec:
-.long 0
-_rambase:
-.long 0
-_ramstart:
-.long 0
-_ramend:
-.long 0
-
-#ifdef CONFIG_INIT_LCD
-splash_bits:
-#include "bootlogo.rh"
-#endif
-
- .text
-_start:
-_stext: movew #0x2700,%sr
-#ifdef CONFIG_INIT_LCD
- movel #splash_bits, 0xfffffA00 /* LSSA */
- moveb #0x28, 0xfffffA05 /* LVPW */
- movew #0x280, 0xFFFFFa08 /* LXMAX */
- movew #0x1df, 0xFFFFFa0a /* LYMAX */
- moveb #0, 0xfffffa29 /* LBAR */
- moveb #0, 0xfffffa25 /* LPXCD */
- moveb #0x08, 0xFFFFFa20 /* LPICF */
- moveb #0x01, 0xFFFFFA21 /* -ve pol */
- moveb #0x81, 0xfffffA27 /* LCKCON */
- movew #0xff00, 0xfffff412 /* LCD pins */
-#endif
- moveal #__ramend-CONFIG_MEMORY_RESERVE*0x100000 - 0x10, %sp
- movew #32767, %d0 /* PLL settle wait loop */
-1: subq #1, %d0
- bne 1b
-
- /* Copy data segment from ROM to RAM */
- moveal #_etext, %a0
- moveal #_sdata, %a1
- moveal #_edata, %a2
-
- /* Copy %a0 to %a1 until %a1 == %a2 */
-1: movel %a0@+, %a1@+
- cmpal %a1, %a2
- bhi 1b
-
- moveal #_sbss, %a0
- moveal #_ebss, %a1
- /* Copy 0 to %a0 until %a0 == %a1 */
-
-1:
- clrl %a0@+
- cmpal %a0, %a1
- bhi 1b
-
- movel #_sdata, %d0
- movel %d0, _rambase
- movel #_ebss, %d0
- movel %d0, _ramstart
- movel #__ramend-CONFIG_MEMORY_RESERVE*0x100000, %d0
- movel %d0, _ramend
- movel #__ramvec, %d0
- movel %d0, _ramvec
-
-/*
- * load the current task pointer and stack
- */
- lea init_thread_union, %a0
- lea 0x2000(%a0), %sp
-
-1: jsr start_kernel
- bra 1b
-_exit:
-
- jmp _exit
-
-
-putc:
- moveb %d7,0xfffff907
-1:
- movew 0xfffff906, %d7
- andw #0x2000, %d7
- beq 1b
- rts
-
- .data
-env:
- .long 0
- .text
-
diff --git a/arch/m68knommu/platform/68VZ328/ucdimm/crt0_himem.S b/arch/m68knommu/platform/68VZ328/ucdimm/crt0_himem.S
deleted file mode 100644
index 4b9022a76f5ee..0000000000000
--- a/arch/m68knommu/platform/68VZ328/ucdimm/crt0_himem.S
+++ /dev/null
@@ -1 +0,0 @@
-#include "crt0_fixed.S"
diff --git a/arch/m68knommu/platform/68VZ328/ucdimm/crt0_rom.S b/arch/m68knommu/platform/68VZ328/ucdimm/crt0_rom.S
deleted file mode 100644
index 4b9022a76f5ee..0000000000000
--- a/arch/m68knommu/platform/68VZ328/ucdimm/crt0_rom.S
+++ /dev/null
@@ -1 +0,0 @@
-#include "crt0_fixed.S"
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 1fae06e53b7f7..5e666aad88152 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -122,10 +122,6 @@ config TANBAC_TB0229
The TANBAC TB0229 (VR4131DIMM) is a MIPS-based platform manufactured by TANBAC.
Please refer to <http://www.tanbac.co.jp/> about VR4131DIMM.
-config TANBAC_TB0219
- bool "Added TANBAC TB0219 Base board support"
- depends on TANBAC_TB0229
-
config VICTOR_MPC30X
bool "Support for Victor MP-C303/304"
select DMA_NONCOHERENT
diff --git a/arch/mips/kernel/irixelf.c b/arch/mips/kernel/irixelf.c
index 42fb65f890ddd..4af20cd91f9f7 100644
--- a/arch/mips/kernel/irixelf.c
+++ b/arch/mips/kernel/irixelf.c
@@ -692,7 +692,7 @@ static int load_irix_binary(struct linux_binprm * bprm, struct pt_regs * regs)
/* Do this so that we can load the interpreter, if need be. We will
* change some of these later.
*/
- current->mm->rss = 0;
+ set_mm_counter(current->mm, rss, 0);
setup_arg_pages(bprm, STACK_TOP, EXSTACK_DEFAULT);
current->mm->start_stack = bprm->p;
@@ -887,12 +887,11 @@ unsigned long irix_mapelf(int fd, struct elf_phdr *user_phdrp, int cnt)
/* First get the verification out of the way. */
hp = user_phdrp;
- retval = verify_area(VERIFY_READ, hp, (sizeof(struct elf_phdr) * cnt));
- if(retval) {
+ if (!access_ok(VERIFY_READ, hp, (sizeof(struct elf_phdr) * cnt))) {
#ifdef DEBUG_ELF
- printk("irix_mapelf: verify_area fails!\n");
+ printk("irix_mapelf: access_ok fails!\n");
#endif
- return retval;
+ return -EFAULT;
}
#ifdef DEBUG_ELF
diff --git a/arch/mips/kernel/irixinv.c b/arch/mips/kernel/irixinv.c
index b8f1446eebc20..60aa98cd17912 100644
--- a/arch/mips/kernel/irixinv.c
+++ b/arch/mips/kernel/irixinv.c
@@ -36,8 +36,8 @@ int dump_inventory_to_user (void *userbuf, int size)
inventory_t *user = userbuf;
int v;
- if ((v = verify_area (VERIFY_WRITE, userbuf, size)))
- return v;
+ if (!access_ok(VERIFY_WRITE, userbuf, size))
+ return -EFAULT;
for (v = 0; v < inventory_items; v++){
inv = &inventory [v];
diff --git a/arch/mips/kernel/irixsig.c b/arch/mips/kernel/irixsig.c
index 298af9916db32..3f956f809fa40 100644
--- a/arch/mips/kernel/irixsig.c
+++ b/arch/mips/kernel/irixsig.c
@@ -312,7 +312,7 @@ irix_sigaction(int sig, const struct sigaction *act,
#endif
if (act) {
sigset_t mask;
- if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
+ if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
__get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
__get_user(new_ka.sa.sa_flags, &act->sa_flags))
return -EFAULT;
@@ -331,7 +331,7 @@ irix_sigaction(int sig, const struct sigaction *act,
ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
if (!ret && oact) {
- if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
+ if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
__put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
__put_user(old_ka.sa.sa_flags, &oact->sa_flags))
return -EFAULT;
@@ -350,12 +350,10 @@ asmlinkage int irix_sigpending(irix_sigset_t *set)
asmlinkage int irix_sigprocmask(int how, irix_sigset_t *new, irix_sigset_t *old)
{
sigset_t oldbits, newbits;
- int error;
if (new) {
- error = verify_area(VERIFY_READ, new, sizeof(*new));
- if (error)
- return error;
+ if (!access_ok(VERIFY_READ, new, sizeof(*new)))
+ return -EFAULT;
__copy_from_user(&newbits, new, sizeof(unsigned long)*4);
sigdelsetmask(&newbits, ~_BLOCKABLE);
@@ -385,9 +383,8 @@ asmlinkage int irix_sigprocmask(int how, irix_sigset_t *new, irix_sigset_t *old)
spin_unlock_irq(&current->sighand->siglock);
}
if(old) {
- error = verify_area(VERIFY_WRITE, old, sizeof(*old));
- if(error)
- return error;
+ if (!access_ok(VERIFY_WRITE, old, sizeof(*old)))
+ return -EFAULT;
__copy_to_user(old, &current->blocked, sizeof(unsigned long)*4);
}
@@ -469,12 +466,13 @@ asmlinkage int irix_sigpoll_sys(unsigned long *set, struct irix5_siginfo *info,
#endif
/* Must always specify the signal set. */
- if(!set)
+ if (!set)
return -EINVAL;
- error = verify_area(VERIFY_READ, set, sizeof(kset));
- if (error)
+ if (!access_ok(VERIFY_READ, set, sizeof(kset))) {
+ error = -EFAULT;
goto out;
+ }
__copy_from_user(&kset, set, sizeof(set));
if (error)
@@ -485,11 +483,10 @@ asmlinkage int irix_sigpoll_sys(unsigned long *set, struct irix5_siginfo *info,
goto out;
}
- if(tp) {
- error = verify_area(VERIFY_READ, tp, sizeof(*tp));
- if(error)
- return error;
- if(!tp->tv_sec && !tp->tv_nsec) {
+ if (tp) {
+ if (!access_ok(VERIFY_READ, tp, sizeof(*tp)))
+ return -EFAULT;
+ if (!tp->tv_sec && !tp->tv_nsec) {
error = -EINVAL;
goto out;
}
@@ -564,13 +561,15 @@ asmlinkage int irix_waitsys(int type, int pid, struct irix5_siginfo *info,
retval = -EINVAL;
goto out;
}
- retval = verify_area(VERIFY_WRITE, info, sizeof(*info));
- if(retval)
+ if (!access_ok(VERIFY_WRITE, info, sizeof(*info))) {
+ retval = -EFAULT;
goto out;
+ }
if (ru) {
- retval = verify_area(VERIFY_WRITE, ru, sizeof(*ru));
- if(retval)
+ if (!access_ok(VERIFY_WRITE, ru, sizeof(*ru))) {
+ retval = -EFAULT;
goto out;
+ }
}
if (options & ~(W_MASK)) {
retval = -EINVAL;
@@ -690,7 +689,7 @@ struct irix5_context {
asmlinkage int irix_getcontext(struct pt_regs *regs)
{
- int error, i, base = 0;
+ int i, base = 0;
struct irix5_context *ctx;
unsigned long flags;
@@ -703,9 +702,9 @@ asmlinkage int irix_getcontext(struct pt_regs *regs)
current->comm, current->pid, ctx);
#endif
- error = verify_area(VERIFY_WRITE, ctx, sizeof(*ctx));
- if(error)
- goto out;
+ if (!access_ok(VERIFY_WRITE, ctx, sizeof(*ctx)))
+ return -EFAULT;
+
__put_user(current->thread.irix_oldctx, &ctx->link);
__copy_to_user(&ctx->sigmask, &current->blocked, sizeof(irix_sigset_t));
@@ -725,17 +724,15 @@ asmlinkage int irix_getcontext(struct pt_regs *regs)
__put_user(regs->cp0_epc, &ctx->regs[35]);
flags = 0x0f;
- if(!used_math()) {
+ if (!used_math()) {
flags &= ~(0x08);
} else {
/* XXX wheee... */
printk("Wheee, no code for saving IRIX FPU context yet.\n");
}
__put_user(flags, &ctx->flags);
- error = 0;
-out:
- return error;
+ return 0;
}
asmlinkage unsigned long irix_setcontext(struct pt_regs *regs)
@@ -752,9 +749,10 @@ asmlinkage unsigned long irix_setcontext(struct pt_regs *regs)
current->comm, current->pid, ctx);
#endif
- error = verify_area(VERIFY_READ, ctx, sizeof(*ctx));
- if (error)
+ if (!access_ok(VERIFY_READ, ctx, sizeof(*ctx))) {
+ error = -EFAULT;
goto out;
+ }
if (ctx->flags & 0x02) {
/* XXX sigstack garbage, todo... */
@@ -787,21 +785,19 @@ struct irix_sigstack { unsigned long sp; int status; };
asmlinkage int irix_sigstack(struct irix_sigstack *new, struct irix_sigstack *old)
{
- int error;
+ int error = -EFAULT;
#ifdef DEBUG_SIG
printk("[%s:%d] irix_sigstack(%p,%p)\n",
current->comm, current->pid, new, old);
#endif
if(new) {
- error = verify_area(VERIFY_READ, new, sizeof(*new));
- if(error)
+ if (!access_ok(VERIFY_READ, new, sizeof(*new)))
goto out;
}
if(old) {
- error = verify_area(VERIFY_WRITE, old, sizeof(*old));
- if(error)
+ if (!access_ok(VERIFY_WRITE, old, sizeof(*old)))
goto out;
}
error = 0;
@@ -815,21 +811,19 @@ struct irix_sigaltstack { unsigned long sp; int size; int status; };
asmlinkage int irix_sigaltstack(struct irix_sigaltstack *new,
struct irix_sigaltstack *old)
{
- int error;
+ int error = -EFAULT;
#ifdef DEBUG_SIG
printk("[%s:%d] irix_sigaltstack(%p,%p)\n",
current->comm, current->pid, new, old);
#endif
if (new) {
- error = verify_area(VERIFY_READ, new, sizeof(*new));
- if(error)
+ if (!access_ok(VERIFY_READ, new, sizeof(*new)))
goto out;
}
if (old) {
- error = verify_area(VERIFY_WRITE, old, sizeof(*old));
- if(error)
+ if (!access_ok(VERIFY_WRITE, old, sizeof(*old)))
goto out;
}
error = 0;
@@ -846,19 +840,14 @@ struct irix_procset {
asmlinkage int irix_sigsendset(struct irix_procset *pset, int sig)
{
- int error;
+ if (!access_ok(VERIFY_READ, pset, sizeof(*pset)))
+ return -EFAULT;
- error = verify_area(VERIFY_READ, pset, sizeof(*pset));
- if(error)
- goto out;
#ifdef DEBUG_SIG
printk("[%s:%d] irix_sigsendset([%d,%d,%d,%d,%d],%d)\n",
current->comm, current->pid,
pset->cmd, pset->ltype, pset->lid, pset->rtype, pset->rid,
sig);
#endif
- error = -EINVAL;
-
-out:
- return error;
+ return -EINVAL;
}
diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c
index 9476a1cb3655d..993abc868e549 100644
--- a/arch/mips/kernel/linux32.c
+++ b/arch/mips/kernel/linux32.c
@@ -239,7 +239,7 @@ put_rusage (struct rusage32 *ru, struct rusage *r)
{
int err;
- if (verify_area(VERIFY_WRITE, ru, sizeof *ru))
+ if (!access_ok(VERIFY_WRITE, ru, sizeof *ru))
return -EFAULT;
err = __put_user (r->ru_utime.tv_sec, &ru->ru_utime.tv_sec);
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index bdfe1c4b2b809..a166954a70b3e 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -21,10 +21,12 @@
#include <linux/mm.h>
#include <linux/errno.h>
#include <linux/ptrace.h>
+#include <linux/audit.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/user.h>
#include <linux/security.h>
+#include <linux/audit.h>
#include <asm/cpu.h>
#include <asm/fpu.h>
@@ -307,7 +309,7 @@ asmlinkage void do_syscall_trace(struct pt_regs *regs, int entryexit)
{
if (unlikely(current->audit_context)) {
if (!entryexit)
- audit_syscall_entry(current, regs->orig_eax,
+ audit_syscall_entry(current, regs->regs[2],
regs->regs[4], regs->regs[5],
regs->regs[6], regs->regs[7]);
else
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index a7fd69c5584bf..6018ca25aceba 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -86,8 +86,8 @@ EXPORT_SYMBOL(mips_io_port_base);
unsigned long isa_slot_offset;
EXPORT_SYMBOL(isa_slot_offset);
-static struct resource code_resource = { "Kernel code" };
-static struct resource data_resource = { "Kernel data" };
+static struct resource code_resource = { .name = "Kernel code", };
+static struct resource data_resource = { .name = "Kernel data", };
void __init add_memory_region(phys_t start, phys_t size, long type)
{
diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c
index 59f069840b3fa..1f3b19124c01f 100644
--- a/arch/mips/kernel/signal32.c
+++ b/arch/mips/kernel/signal32.c
@@ -32,11 +32,6 @@
#define SI_PAD_SIZE32 ((SI_MAX_SIZE/sizeof(int)) - 3)
-typedef union sigval32 {
- int sival_int;
- s32 sival_ptr;
-} sigval_t32;
-
typedef struct compat_siginfo {
int si_signo;
int si_code;
@@ -89,7 +84,7 @@ typedef struct compat_siginfo {
struct {
compat_pid_t _pid; /* sender's pid */
compat_uid_t _uid; /* sender's uid */
- sigval_t32 _sigval;
+ compat_sigval_t _sigval;
} _rt;
} _sifields;
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
index 20245b7fdfd08..af5cd3b8a3968 100644
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
@@ -46,9 +46,6 @@ int __cpu_logical_map[NR_CPUS]; /* Map logical to physical */
EXPORT_SYMBOL(phys_cpu_present_map);
EXPORT_SYMBOL(cpu_online_map);
-cycles_t cacheflush_time;
-unsigned long cache_decay_ticks;
-
static void smp_tune_scheduling (void)
{
struct cache_desc *cd = &current_cpu_data.scache;
@@ -71,25 +68,10 @@ static void smp_tune_scheduling (void)
* L1 cache), on PIIs it's around 50-100 usecs, depending on
* the cache size)
*/
- if (!cpu_khz) {
- /*
- * This basically disables processor-affinity scheduling on SMP
- * without a cycle counter. Currently all SMP capable MIPS
- * processors have a cycle counter.
- */
- cacheflush_time = 0;
+ if (!cpu_khz)
return;
- }
cachesize = cd->linesz * cd->sets * cd->ways;
- cacheflush_time = (cpu_khz>>10) * (cachesize<<10) / bandwidth;
- cache_decay_ticks = (long)cacheflush_time/cpu_khz * HZ / 1000;
-
- printk("per-CPU timeslice cutoff: %ld.%02ld usecs.\n",
- (long)cacheflush_time/(cpu_khz/1000),
- ((long)cacheflush_time*100/(cpu_khz/1000)) % 100);
- printk("task migration cache decay timeout: %ld msecs.\n",
- (cache_decay_ticks + 1) * 1000 / HZ);
}
extern void __init calibrate_delay(void);
diff --git a/arch/mips/kernel/sysirix.c b/arch/mips/kernel/sysirix.c
index 3bb59d7f5913d..f3bf0e43b8bb2 100644
--- a/arch/mips/kernel/sysirix.c
+++ b/arch/mips/kernel/sysirix.c
@@ -289,9 +289,10 @@ asmlinkage int irix_syssgi(struct pt_regs *regs)
struct task_struct *p;
char tcomm[sizeof(current->comm)];
- retval = verify_area(VERIFY_WRITE, buf, sizeof(tcomm));
- if (retval)
+ if (!access_ok(VERIFY_WRITE, buf, sizeof(tcomm))) {
+ retval = -EFAULT;
break;
+ }
read_lock(&tasklist_lock);
p = find_task_by_pid(pid);
if (!p) {
@@ -313,9 +314,10 @@ asmlinkage int irix_syssgi(struct pt_regs *regs)
char *buf = (char *) regs->regs[base+6];
char *value;
return -EINVAL; /* til I fix it */
- retval = verify_area(VERIFY_WRITE, buf, 128);
- if (retval)
+ if (!access_ok(VERIFY_WRITE, buf, 128)) {
+ retval = -EFAULT;
break;
+ }
value = prom_getenv(name); /* PROM lock? */
if (!value) {
retval = -EINVAL;
@@ -472,9 +474,8 @@ asmlinkage int irix_syssgi(struct pt_regs *regs)
pmd_t *pmdp;
pte_t *ptep;
- retval = verify_area(VERIFY_WRITE, pageno, sizeof(int));
- if (retval)
- return retval;
+ if (!access_ok(VERIFY_WRITE, pageno, sizeof(int)))
+ return -EFAULT;
down_read(&mm->mmap_sem);
pgdp = pgd_offset(mm, addr);
@@ -727,9 +728,10 @@ asmlinkage int irix_statfs(const char *path, struct irix_statfs *buf,
error = -EINVAL;
goto out;
}
- error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statfs));
- if (error)
+ if (!access_ok(VERIFY_WRITE, buf, sizeof(struct irix_statfs))) {
+ error = -EFAULT;
goto out;
+ }
error = user_path_walk(path, &nd);
if (error)
goto out;
@@ -763,9 +765,10 @@ asmlinkage int irix_fstatfs(unsigned int fd, struct irix_statfs *buf)
struct file *file;
int error, i;
- error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statfs));
- if (error)
+ if (!access_ok(VERIFY_WRITE, buf, sizeof(struct irix_statfs))) {
+ error = -EFAULT;
goto out;
+ }
if (!(file = fget(fd))) {
error = -EBADF;
goto out;
@@ -816,9 +819,8 @@ asmlinkage int irix_times(struct tms * tbuf)
int err = 0;
if (tbuf) {
- err = verify_area(VERIFY_WRITE,tbuf,sizeof *tbuf);
- if (err)
- return err;
+ if (!access_ok(VERIFY_WRITE,tbuf,sizeof *tbuf))
+ return -EFAULT;
err |= __put_user(current->utime, &tbuf->tms_utime);
err |= __put_user(current->stime, &tbuf->tms_stime);
err |= __put_user(current->signal->cutime, &tbuf->tms_cutime);
@@ -919,9 +921,8 @@ asmlinkage int irix_getdomainname(char *name, int len)
{
int error;
- error = verify_area(VERIFY_WRITE, name, len);
- if (error)
- return error;
+ if (!access_ok(VERIFY_WRITE, name, len))
+ return -EFAULT;
down_read(&uts_sem);
if (len > __NEW_UTS_LEN)
@@ -1050,7 +1051,7 @@ asmlinkage int irix_gettimeofday(struct timeval *tv)
long nsec, seq;
int err;
- if (verify_area(VERIFY_WRITE, tv, sizeof(struct timeval)))
+ if (!access_ok(VERIFY_WRITE, tv, sizeof(struct timeval)))
return -EFAULT;
do {
@@ -1396,9 +1397,10 @@ asmlinkage int irix_statvfs(char *fname, struct irix_statvfs *buf)
printk("[%s:%d] Wheee.. irix_statvfs(%s,%p)\n",
current->comm, current->pid, fname, buf);
- error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statvfs));
- if (error)
+ if (!access_ok(VERIFY_WRITE, buf, sizeof(struct irix_statvfs))) {
+ error = -EFAULT;
goto out;
+ }
error = user_path_walk(fname, &nd);
if (error)
goto out;
@@ -1443,9 +1445,10 @@ asmlinkage int irix_fstatvfs(int fd, struct irix_statvfs *buf)
printk("[%s:%d] Wheee.. irix_fstatvfs(%d,%p)\n",
current->comm, current->pid, fd, buf);
- error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statvfs));
- if (error)
+ if (!access_ok(VERIFY_WRITE, buf, sizeof(struct irix_statvfs))) {
+ error = -EFAULT;
goto out;
+ }
if (!(file = fget(fd))) {
error = -EBADF;
goto out;
@@ -1537,16 +1540,18 @@ asmlinkage int irix_mmap64(struct pt_regs *regs)
prot = regs->regs[base + 6];
if (!base) {
flags = regs->regs[base + 7];
- error = verify_area(VERIFY_READ, sp, (4 * sizeof(unsigned long)));
- if(error)
+ if (!access_ok(VERIFY_READ, sp, (4 * sizeof(unsigned long)))) {
+ error = -EFAULT;
goto out;
+ }
fd = sp[0];
__get_user(off1, &sp[1]);
__get_user(off2, &sp[2]);
} else {
- error = verify_area(VERIFY_READ, sp, (5 * sizeof(unsigned long)));
- if(error)
+ if (!access_ok(VERIFY_READ, sp, (5 * sizeof(unsigned long)))) {
+ error = -EFAULT;
goto out;
+ }
__get_user(flags, &sp[0]);
__get_user(fd, &sp[1]);
__get_user(off1, &sp[2]);
@@ -1650,9 +1655,10 @@ asmlinkage int irix_statvfs64(char *fname, struct irix_statvfs64 *buf)
printk("[%s:%d] Wheee.. irix_statvfs64(%s,%p)\n",
current->comm, current->pid, fname, buf);
- error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statvfs64));
- if(error)
+ if (!access_ok(VERIFY_WRITE, buf, sizeof(struct irix_statvfs64))) {
+ error = -EFAULT;
goto out;
+ }
error = user_path_walk(fname, &nd);
if (error)
goto out;
@@ -1697,9 +1703,10 @@ asmlinkage int irix_fstatvfs64(int fd, struct irix_statvfs *buf)
printk("[%s:%d] Wheee.. irix_fstatvfs64(%d,%p)\n",
current->comm, current->pid, fd, buf);
- error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statvfs));
- if (error)
+ if (!access_ok(VERIFY_WRITE, buf, sizeof(struct irix_statvfs))) {
+ error = -EFAULT;
goto out;
+ }
if (!(file = fget(fd))) {
error = -EBADF;
goto out;
@@ -1735,13 +1742,12 @@ out:
asmlinkage int irix_getmountid(char *fname, unsigned long *midbuf)
{
- int err;
+ int err = 0;
printk("[%s:%d] irix_getmountid(%s, %p)\n",
current->comm, current->pid, fname, midbuf);
- err = verify_area(VERIFY_WRITE, midbuf, (sizeof(unsigned long) * 4));
- if (err)
- return err;
+ if (!access_ok(VERIFY_WRITE, midbuf, (sizeof(unsigned long) * 4)))
+ return -EFAULT;
/*
* The idea with this system call is that when trying to determine
diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c
index 4516e359b09c4..3f24a1d45865b 100644
--- a/arch/mips/kernel/unaligned.c
+++ b/arch/mips/kernel/unaligned.c
@@ -143,7 +143,7 @@ static inline int emulate_load_store_insn(struct pt_regs *regs,
* The remaining opcodes are the ones that are really of interest.
*/
case lh_op:
- if (verify_area(VERIFY_READ, addr, 2))
+ if (!access_ok(VERIFY_READ, addr, 2))
goto sigbus;
__asm__ __volatile__ (".set\tnoat\n"
@@ -176,7 +176,7 @@ static inline int emulate_load_store_insn(struct pt_regs *regs,
break;
case lw_op:
- if (verify_area(VERIFY_READ, addr, 4))
+ if (!access_ok(VERIFY_READ, addr, 4))
goto sigbus;
__asm__ __volatile__ (
@@ -206,7 +206,7 @@ static inline int emulate_load_store_insn(struct pt_regs *regs,
break;
case lhu_op:
- if (verify_area(VERIFY_READ, addr, 2))
+ if (!access_ok(VERIFY_READ, addr, 2))
goto sigbus;
__asm__ __volatile__ (
@@ -248,7 +248,7 @@ static inline int emulate_load_store_insn(struct pt_regs *regs,
* would blow up, so for now we don't handle unaligned 64-bit
* instructions on 32-bit kernels.
*/
- if (verify_area(VERIFY_READ, addr, 4))
+ if (!access_ok(VERIFY_READ, addr, 4))
goto sigbus;
__asm__ __volatile__ (
@@ -292,7 +292,7 @@ static inline int emulate_load_store_insn(struct pt_regs *regs,
* would blow up, so for now we don't handle unaligned 64-bit
* instructions on 32-bit kernels.
*/
- if (verify_area(VERIFY_READ, addr, 8))
+ if (!access_ok(VERIFY_READ, addr, 8))
goto sigbus;
__asm__ __volatile__ (
@@ -326,7 +326,7 @@ static inline int emulate_load_store_insn(struct pt_regs *regs,
goto sigill;
case sh_op:
- if (verify_area(VERIFY_WRITE, addr, 2))
+ if (!access_ok(VERIFY_WRITE, addr, 2))
goto sigbus;
value = regs->regs[insn.i_format.rt];
@@ -362,7 +362,7 @@ static inline int emulate_load_store_insn(struct pt_regs *regs,
break;
case sw_op:
- if (verify_area(VERIFY_WRITE, addr, 4))
+ if (!access_ok(VERIFY_WRITE, addr, 4))
goto sigbus;
value = regs->regs[insn.i_format.rt];
@@ -400,7 +400,7 @@ static inline int emulate_load_store_insn(struct pt_regs *regs,
* would blow up, so for now we don't handle unaligned 64-bit
* instructions on 32-bit kernels.
*/
- if (verify_area(VERIFY_WRITE, addr, 8))
+ if (!access_ok(VERIFY_WRITE, addr, 8))
goto sigbus;
value = regs->regs[insn.i_format.rt];
diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile
index 0f4b55605612f..21b92b9dd0133 100644
--- a/arch/mips/lib/Makefile
+++ b/arch/mips/lib/Makefile
@@ -2,7 +2,9 @@
# Makefile for MIPS-specific library files..
#
-lib-y += csum_partial_copy.o dec_and_lock.o iomap.o memcpy.o promlib.o \
+lib-y += csum_partial_copy.o dec_and_lock.o memcpy.o promlib.o \
strlen_user.o strncpy_user.o strnlen_user.o
+obj-y += iomap.o
+
EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/math-emu/dsemul.c b/arch/mips/math-emu/dsemul.c
index 6a767feaf0d52..aa989c2246da9 100644
--- a/arch/mips/math-emu/dsemul.c
+++ b/arch/mips/math-emu/dsemul.c
@@ -95,7 +95,7 @@ int mips_dsemul(struct pt_regs *regs, mips_instruction ir, gpreg_t cpc)
fr = (struct emuframe *) dsemul_insns;
/* Verify that the stack pointer is not competely insane */
- if (unlikely(verify_area(VERIFY_WRITE, fr, sizeof(struct emuframe))))
+ if (unlikely(!access_ok(VERIFY_WRITE, fr, sizeof(struct emuframe))))
return SIGBUS;
err = __put_user(ir, &fr->emul);
@@ -128,7 +128,7 @@ int do_dsemulret(struct pt_regs *xcp)
* If we can't even access the area, something is very wrong, but we'll
* leave that to the default handling
*/
- if (verify_area(VERIFY_READ, fr, sizeof(struct emuframe)))
+ if (!access_ok(VERIFY_READ, fr, sizeof(struct emuframe)))
return 0;
/*
@@ -142,7 +142,6 @@ int do_dsemulret(struct pt_regs *xcp)
if (unlikely(err || (insn != BADINST) || (cookie != BD_COOKIE))) {
fpuemuprivate.stats.errors++;
-
return 0;
}
diff --git a/arch/mips/mm/c-r3k.c b/arch/mips/mm/c-r3k.c
index 887683b3cc403..c659f99eb39aa 100644
--- a/arch/mips/mm/c-r3k.c
+++ b/arch/mips/mm/c-r3k.c
@@ -254,8 +254,7 @@ static void r3k_flush_cache_range(struct vm_area_struct *vma,
{
}
-static void r3k_flush_cache_page(struct vm_area_struct *vma,
- unsigned long page)
+static void r3k_flush_cache_page(struct vm_area_struct *vma, unsigned long page, unsigned long pfn)
{
}
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
index b2808cea6fd7c..a03ebb2cba677 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -426,8 +426,7 @@ static inline void local_r4k_flush_cache_page(void *args)
}
}
-static void r4k_flush_cache_page(struct vm_area_struct *vma,
- unsigned long page)
+static void r4k_flush_cache_page(struct vm_area_struct *vma, unsigned long page, unsigned long pfn)
{
struct flush_cache_page_args args;
diff --git a/arch/mips/mm/c-sb1.c b/arch/mips/mm/c-sb1.c
index ad41b2b460040..ab30afd63b325 100644
--- a/arch/mips/mm/c-sb1.c
+++ b/arch/mips/mm/c-sb1.c
@@ -160,8 +160,7 @@ static inline void __sb1_flush_icache_all(void)
* dcache first, then invalidate the icache. If the page isn't
* executable, nothing is required.
*/
-static void local_sb1_flush_cache_page(struct vm_area_struct *vma,
- unsigned long addr)
+static void local_sb1_flush_cache_page(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn)
{
int cpu = smp_processor_id();
@@ -183,17 +182,18 @@ static void local_sb1_flush_cache_page(struct vm_area_struct *vma,
struct flush_cache_page_args {
struct vm_area_struct *vma;
unsigned long addr;
+ unsigned long pfn;
};
static void sb1_flush_cache_page_ipi(void *info)
{
struct flush_cache_page_args *args = info;
- local_sb1_flush_cache_page(args->vma, args->addr);
+ local_sb1_flush_cache_page(args->vma, args->addr, args->pfn);
}
/* Dirty dcache could be on another CPU, so do the IPIs */
-static void sb1_flush_cache_page(struct vm_area_struct *vma, unsigned long addr)
+static void sb1_flush_cache_page(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn)
{
struct flush_cache_page_args args;
@@ -203,10 +203,11 @@ static void sb1_flush_cache_page(struct vm_area_struct *vma, unsigned long addr)
addr &= PAGE_MASK;
args.vma = vma;
args.addr = addr;
+ args.pfn = pfn;
on_each_cpu(sb1_flush_cache_page_ipi, (void *) &args, 1, 1);
}
#else
-void sb1_flush_cache_page(struct vm_area_struct *vma, unsigned long addr)
+void sb1_flush_cache_page(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn)
__attribute__((alias("local_sb1_flush_cache_page")));
#endif
diff --git a/arch/mips/mm/c-tx39.c b/arch/mips/mm/c-tx39.c
index 9b0592dffb1a6..ff5afab64b2f8 100644
--- a/arch/mips/mm/c-tx39.c
+++ b/arch/mips/mm/c-tx39.c
@@ -178,8 +178,7 @@ static void tx39_flush_cache_range(struct vm_area_struct *vma,
}
}
-static void tx39_flush_cache_page(struct vm_area_struct *vma,
- unsigned long page)
+static void tx39_flush_cache_page(struct vm_area_struct *vma, unsigned long page, unsigned long pfn)
{
int exec = vma->vm_flags & VM_EXEC;
struct mm_struct *mm = vma->vm_mm;
diff --git a/arch/mips/mm/cache.c b/arch/mips/mm/cache.c
index e51ae38ddaf5e..1d95cdb77bede 100644
--- a/arch/mips/mm/cache.c
+++ b/arch/mips/mm/cache.c
@@ -23,7 +23,7 @@ void (*__flush_cache_all)(void);
void (*flush_cache_mm)(struct mm_struct *mm);
void (*flush_cache_range)(struct vm_area_struct *vma, unsigned long start,
unsigned long end);
-void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page);
+void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page, unsigned long pfn);
void (*flush_icache_range)(unsigned long start, unsigned long end);
void (*flush_icache_page)(struct vm_area_struct *vma, struct page *page);
@@ -52,7 +52,7 @@ EXPORT_SYMBOL(_dma_cache_inv);
asmlinkage int sys_cacheflush(unsigned long addr, unsigned long int bytes,
unsigned int cache)
{
- if (verify_area(VERIFY_WRITE, (void *) addr, bytes))
+ if (!access_ok(VERIFY_WRITE, (void *) addr, bytes))
return -EFAULT;
flush_icache_range(addr, addr + bytes);
diff --git a/arch/mips/mm/highmem.c b/arch/mips/mm/highmem.c
index 14b020d39d0f8..dd5e2e31885b8 100644
--- a/arch/mips/mm/highmem.c
+++ b/arch/mips/mm/highmem.c
@@ -75,7 +75,7 @@ void __kunmap_atomic(void *kvaddr, enum km_type type)
* force other mappings to Oops if they'll try to access
* this pte without first remap it
*/
- pte_clear(kmap_pte-idx);
+ pte_clear(&init_mm, vaddr, kmap_pte-idx);
local_flush_tlb_one(vaddr);
#endif
diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c
index d353091a86754..b027ce7efbc67 100644
--- a/arch/mips/mm/init.c
+++ b/arch/mips/mm/init.c
@@ -82,9 +82,6 @@ unsigned long setup_zero_pages(void)
pte_t *kmap_pte;
pgprot_t kmap_prot;
-EXPORT_SYMBOL(kmap_prot);
-EXPORT_SYMBOL(kmap_pte);
-
#define kmap_get_fixmap_pte(vaddr) \
pte_offset_kernel(pmd_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr))
diff --git a/arch/mips/pci/fixup-mpc30x.c b/arch/mips/pci/fixup-mpc30x.c
index 09d6b3647656b..4975846da75a9 100644
--- a/arch/mips/pci/fixup-mpc30x.c
+++ b/arch/mips/pci/fixup-mpc30x.c
@@ -29,7 +29,7 @@ static const int internal_func_irqs[] __initdata = {
VRC4173_USB_IRQ,
};
-static char irq_tab_mpc30x[] __initdata = {
+static const int irq_tab_mpc30x[] __initdata = {
[12] = VRC4173_PCMCIA1_IRQ,
[13] = VRC4173_PCMCIA2_IRQ,
[29] = MQ200_IRQ,
diff --git a/arch/mips/pci/pci-vr41xx.c b/arch/mips/pci/pci-vr41xx.c
index dc9795fe9a6ce..f3ccbf7fada41 100644
--- a/arch/mips/pci/pci-vr41xx.c
+++ b/arch/mips/pci/pci-vr41xx.c
@@ -288,4 +288,4 @@ static int __init vr41xx_pciu_init(void)
return 0;
}
-early_initcall(vr41xx_pciu_init);
+arch_initcall(vr41xx_pciu_init);
diff --git a/arch/mips/pmc-sierra/yosemite/ht.c b/arch/mips/pmc-sierra/yosemite/ht.c
index 95bbfd013d207..ca811853e87f5 100644
--- a/arch/mips/pmc-sierra/yosemite/ht.c
+++ b/arch/mips/pmc-sierra/yosemite/ht.c
@@ -303,7 +303,7 @@ int pcibios_enable_resources(struct pci_dev *dev)
if (!r->start && r->end) {
printk(KERN_ERR
"PCI: Device %s not available because of "
- "resource collisions\n", dev->slot_name);
+ "resource collisions\n", pci_name(dev));
return -EINVAL;
}
if (r->flags & IORESOURCE_IO)
@@ -377,7 +377,7 @@ void pcibios_update_resource(struct pci_dev *dev, struct resource *root,
((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK :
PCI_BASE_ADDRESS_MEM_MASK)) {
printk(KERN_ERR "PCI: Error while updating region "
- "%s/%d (%08x != %08x)\n", dev->slot_name, resource,
+ "%s/%d (%08x != %08x)\n", pci_name(dev), resource,
new, check);
}
}
@@ -396,7 +396,7 @@ void pcibios_align_resource(void *data, struct resource *res,
addresses kilobyte aligned. */
if (size > 0x100) {
printk(KERN_ERR "PCI: I/O Region %s/%d too large"
- " (%ld bytes)\n", dev->slot_name,
+ " (%ld bytes)\n", pci_name(dev),
dev->resource - res, size);
}
diff --git a/arch/mips/vr41xx/casio-e55/setup.c b/arch/mips/vr41xx/casio-e55/setup.c
index e41c7b0669f29..aa8605ab76ff2 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-2004 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * Copyright (C) 2002-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -17,7 +17,7 @@
* 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/ioport.h>
#include <asm/io.h>
@@ -28,18 +28,13 @@ const char *get_system_type(void)
return "CASIO CASSIOPEIA E-11/15/55/65";
}
-static int casio_e55_setup(void)
+static int __init casio_e55_setup(void)
{
set_io_port_base(IO_PORT_BASE);
ioport_resource.start = IO_PORT_RESOURCE_START;
ioport_resource.end = IO_PORT_RESOURCE_END;
-#ifdef CONFIG_SERIAL_8250
- vr41xx_select_siu_interface(SIU_RS232C, IRDA_NONE);
- vr41xx_siu_init();
-#endif
-
return 0;
}
-early_initcall(casio_e55_setup);
+arch_initcall(casio_e55_setup);
diff --git a/arch/mips/vr41xx/common/Makefile b/arch/mips/vr41xx/common/Makefile
index 899939be4206d..92c11e9bbb3fb 100644
--- a/arch/mips/vr41xx/common/Makefile
+++ b/arch/mips/vr41xx/common/Makefile
@@ -2,9 +2,7 @@
# Makefile for common code of the NEC VR4100 series.
#
-obj-y += bcu.o cmu.o giu.o icu.o init.o int-handler.o ksyms.o pmu.o rtc.o
-obj-$(CONFIG_SERIAL_8250) += serial.o
-obj-$(CONFIG_VRC4171) += vrc4171.o
+obj-y += bcu.o cmu.o giu.o icu.o init.o int-handler.o pmu.o
obj-$(CONFIG_VRC4173) += vrc4173.o
EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/vr41xx/common/bcu.c b/arch/mips/vr41xx/common/bcu.c
index d14dae150b8a6..cdfa4273a1c50 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-2004 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * Copyright (C) 2003-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -28,20 +28,16 @@
* Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
* - Added support for NEC VR4133.
*/
-#include <linux/init.h>
-#include <linux/ioport.h>
#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/smp.h>
#include <linux/types.h>
#include <asm/cpu.h>
#include <asm/io.h>
-#define IO_MEM_RESOURCE_START 0UL
-#define IO_MEM_RESOURCE_END 0x1fffffffUL
-
-#define CLKSPEEDREG_TYPE1 KSEG1ADDR(0x0b000014)
-#define CLKSPEEDREG_TYPE2 KSEG1ADDR(0x0f000014)
+#define CLKSPEEDREG_TYPE1 (void __iomem *)KSEG1ADDR(0x0b000014)
+#define CLKSPEEDREG_TYPE2 (void __iomem *)KSEG1ADDR(0x0f000014)
#define CLKSP(x) ((x) & 0x001f)
#define CLKSP_VR4133(x) ((x) & 0x0007)
@@ -63,11 +59,15 @@ unsigned long vr41xx_get_vtclock_frequency(void)
return vr41xx_vtclock;
}
+EXPORT_SYMBOL_GPL(vr41xx_get_vtclock_frequency);
+
unsigned long vr41xx_get_tclock_frequency(void)
{
return vr41xx_tclock;
}
+EXPORT_SYMBOL_GPL(vr41xx_get_tclock_frequency);
+
static inline uint16_t read_clkspeed(void)
{
switch (current_cpu_data.cputype) {
@@ -207,7 +207,7 @@ static inline unsigned long calculate_tclock(uint16_t clkspeed, unsigned long pc
return tclock;
}
-static int __init vr41xx_bcu_init(void)
+void vr41xx_calculate_clock_frequency(void)
{
unsigned long pclock;
uint16_t clkspeed;
@@ -217,11 +217,6 @@ static int __init vr41xx_bcu_init(void)
pclock = calculate_pclock(clkspeed);
vr41xx_vtclock = calculate_vtclock(clkspeed, pclock);
vr41xx_tclock = calculate_tclock(clkspeed, pclock, vr41xx_vtclock);
-
- iomem_resource.start = IO_MEM_RESOURCE_START;
- iomem_resource.end = IO_MEM_RESOURCE_END;
-
- return 0;
}
-early_initcall(vr41xx_bcu_init);
+EXPORT_SYMBOL_GPL(vr41xx_calculate_clock_frequency);
diff --git a/arch/mips/vr41xx/common/cmu.c b/arch/mips/vr41xx/common/cmu.c
index fd33d005f463e..fcd3cb8cdd9dd 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-2004 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * Copuright (C) 2003-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -29,6 +29,8 @@
* - Added support for NEC VR4133.
*/
#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
#include <linux/smp.h>
#include <linux/spinlock.h>
#include <linux/types.h>
@@ -37,8 +39,16 @@
#include <asm/io.h>
#include <asm/vr41xx/vr41xx.h>
-#define CMUCLKMSK_TYPE1 KSEG1ADDR(0x0b000060)
-#define CMUCLKMSK_TYPE2 KSEG1ADDR(0x0f000060)
+#define CMU_TYPE1_BASE 0x0b000060UL
+#define CMU_TYPE1_SIZE 0x4
+
+#define CMU_TYPE2_BASE 0x0f000060UL
+#define CMU_TYPE2_SIZE 0x4
+
+#define CMU_TYPE3_BASE 0x0f000060UL
+#define CMU_TYPE3_SIZE 0x8
+
+#define CMUCLKMSK 0x0
#define MSKPIU 0x0001
#define MSKSIU 0x0002
#define MSKAIU 0x0004
@@ -52,19 +62,17 @@
#define MSKFFIR 0x0400
#define MSKSCSI 0x1000
#define MSKPPCIU 0x2000
-#define CMUCLKMSK2 KSEG1ADDR(0x0f000064)
+#define CMUCLKMSK2 0x4
#define MSKCEU 0x0001
#define MSKMAC0 0x0002
#define MSKMAC1 0x0004
-static uint32_t cmu_base;
+static void __iomem *cmu_base;
static uint16_t cmuclkmsk, cmuclkmsk2;
static spinlock_t cmu_lock;
-#define read_cmuclkmsk() readw(cmu_base)
-#define read_cmuclkmsk2() readw(CMUCLKMSK2)
-#define write_cmuclkmsk() writew(cmuclkmsk, cmu_base)
-#define write_cmuclkmsk2() writew(cmuclkmsk2, CMUCLKMSK2)
+#define cmu_read(offset) readw(cmu_base + (offset))
+#define cmu_write(offset, value) writew((value), cmu_base + (offset))
void vr41xx_supply_clock(vr41xx_clock_t clock)
{
@@ -120,13 +128,15 @@ void vr41xx_supply_clock(vr41xx_clock_t clock)
if (clock == CEU_CLOCK || clock == ETHER0_CLOCK ||
clock == ETHER1_CLOCK)
- write_cmuclkmsk2();
+ cmu_write(CMUCLKMSK2, cmuclkmsk2);
else
- write_cmuclkmsk();
+ cmu_write(CMUCLKMSK, cmuclkmsk);
spin_unlock_irq(&cmu_lock);
}
+EXPORT_SYMBOL_GPL(vr41xx_supply_clock);
+
void vr41xx_mask_clock(vr41xx_clock_t clock)
{
spin_lock_irq(&cmu_lock);
@@ -160,7 +170,7 @@ void vr41xx_mask_clock(vr41xx_clock_t clock)
current_cpu_data.cputype == CPU_VR4121) {
cmuclkmsk &= ~MSKDSIU;
} else {
- if (cmuclkmsk & MSKSIU)
+ if (cmuclkmsk & MSKSSIU)
cmuclkmsk &= ~MSKDSIU;
else
cmuclkmsk &= ~(MSKSIU | MSKDSIU);
@@ -193,38 +203,55 @@ void vr41xx_mask_clock(vr41xx_clock_t clock)
if (clock == CEU_CLOCK || clock == ETHER0_CLOCK ||
clock == ETHER1_CLOCK)
- write_cmuclkmsk2();
+ cmu_write(CMUCLKMSK2, cmuclkmsk2);
else
- write_cmuclkmsk();
+ cmu_write(CMUCLKMSK, cmuclkmsk);
spin_unlock_irq(&cmu_lock);
}
+EXPORT_SYMBOL_GPL(vr41xx_mask_clock);
+
static int __init vr41xx_cmu_init(void)
{
+ unsigned long start, size;
+
switch (current_cpu_data.cputype) {
case CPU_VR4111:
case CPU_VR4121:
- cmu_base = CMUCLKMSK_TYPE1;
+ start = CMU_TYPE1_BASE;
+ size = CMU_TYPE1_SIZE;
break;
case CPU_VR4122:
case CPU_VR4131:
- cmu_base = CMUCLKMSK_TYPE2;
- break;
+ start = CMU_TYPE2_BASE;
+ size = CMU_TYPE2_SIZE;
+ break;
case CPU_VR4133:
- cmu_base = CMUCLKMSK_TYPE2;
- cmuclkmsk2 = read_cmuclkmsk2();
+ start = CMU_TYPE3_BASE;
+ size = CMU_TYPE3_SIZE;
break;
default:
panic("Unexpected CPU of NEC VR4100 series");
break;
}
- cmuclkmsk = read_cmuclkmsk();
+ if (request_mem_region(start, size, "CMU") == NULL)
+ return -EBUSY;
+
+ cmu_base = ioremap(start, size);
+ if (cmu_base == NULL) {
+ release_mem_region(start, size);
+ return -EBUSY;
+ }
+
+ cmuclkmsk = cmu_read(CMUCLKMSK);
+ if (current_cpu_data.cputype == CPU_VR4133)
+ cmuclkmsk2 = cmu_read(CMUCLKMSK2);
spin_lock_init(&cmu_lock);
return 0;
}
-early_initcall(vr41xx_cmu_init);
+core_initcall(vr41xx_cmu_init);
diff --git a/arch/mips/vr41xx/common/init.c b/arch/mips/vr41xx/common/init.c
index ffc8e1c36b674..e03be896cbc49 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-2004 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * Copyright (C) 2003-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -18,9 +18,45 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/irq.h>
#include <linux/string.h>
#include <asm/bootinfo.h>
+#include <asm/time.h>
+#include <asm/vr41xx/vr41xx.h>
+
+#define IO_MEM_RESOURCE_START 0UL
+#define IO_MEM_RESOURCE_END 0x1fffffffUL
+
+static void __init iomem_resource_init(void)
+{
+ iomem_resource.start = IO_MEM_RESOURCE_START;
+ iomem_resource.end = IO_MEM_RESOURCE_END;
+}
+
+static void __init setup_timer_frequency(void)
+{
+ unsigned long tclock;
+
+ tclock = vr41xx_get_tclock_frequency();
+ if (current_cpu_data.processor_id == PRID_VR4131_REV2_0 ||
+ current_cpu_data.processor_id == PRID_VR4131_REV2_1)
+ mips_hpt_frequency = tclock / 2;
+ else
+ mips_hpt_frequency = tclock / 4;
+}
+
+static void __init setup_timer_irq(struct irqaction *irq)
+{
+ setup_irq(TIMER_IRQ, irq);
+}
+
+static void __init timer_init(void)
+{
+ board_time_init = setup_timer_frequency;
+ board_timer_setup = setup_timer_irq;
+}
void __init prom_init(void)
{
@@ -35,6 +71,12 @@ void __init prom_init(void)
if (i < (argc - 1))
strcat(arcs_cmdline, " ");
}
+
+ vr41xx_calculate_clock_frequency();
+
+ timer_init();
+
+ iomem_resource_init();
}
unsigned long __init prom_free_prom_memory (void)
diff --git a/arch/mips/vr41xx/common/ksyms.c b/arch/mips/vr41xx/common/ksyms.c
deleted file mode 100644
index a2014106360d4..0000000000000
--- a/arch/mips/vr41xx/common/ksyms.c
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * ksyms.c, Export NEC VR4100 series specific functions needed for loadable modules.
- *
- * Copyright (C) 2003 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
- * Copyright (C) 2005 Ralf Baechle (ralf@linux-mips.org)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-#include <linux/module.h>
-
-#include <asm/vr41xx/vr41xx.h>
-
-EXPORT_SYMBOL(vr41xx_get_vtclock_frequency);
-EXPORT_SYMBOL(vr41xx_get_tclock_frequency);
-
-EXPORT_SYMBOL(vr41xx_set_rtclong1_cycle);
-EXPORT_SYMBOL(vr41xx_read_rtclong1_counter);
-EXPORT_SYMBOL(vr41xx_set_rtclong2_cycle);
-EXPORT_SYMBOL(vr41xx_read_rtclong2_counter);
-EXPORT_SYMBOL(vr41xx_set_tclock_cycle);
-EXPORT_SYMBOL(vr41xx_read_tclock_counter);
diff --git a/arch/mips/vr41xx/common/rtc.c b/arch/mips/vr41xx/common/rtc.c
deleted file mode 100644
index 07173afe1faf4..0000000000000
--- a/arch/mips/vr41xx/common/rtc.c
+++ /dev/null
@@ -1,321 +0,0 @@
-/*
- * rtc.c, RTC(has only timer function) routines for NEC VR4100 series.
- *
- * Copyright (C) 2003-2004 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-#include <linux/init.h>
-#include <linux/irq.h>
-#include <linux/smp.h>
-#include <linux/types.h>
-
-#include <asm/io.h>
-#include <asm/time.h>
-#include <asm/vr41xx/vr41xx.h>
-
-static uint32_t rtc1_base;
-static uint32_t rtc2_base;
-
-static uint64_t previous_elapsedtime;
-static unsigned int remainder_per_sec;
-static unsigned int cycles_per_sec;
-static unsigned int cycles_per_jiffy;
-static unsigned long epoch_time;
-
-#define CYCLES_PER_JIFFY (CLOCK_TICK_RATE / HZ)
-#define REMAINDER_PER_SEC (CLOCK_TICK_RATE - (CYCLES_PER_JIFFY * HZ))
-#define CYCLES_PER_100USEC ((CLOCK_TICK_RATE + (10000 / 2)) / 10000)
-
-#define ETIMELREG_TYPE1 KSEG1ADDR(0x0b0000c0)
-#define TCLKLREG_TYPE1 KSEG1ADDR(0x0b0001c0)
-
-#define ETIMELREG_TYPE2 KSEG1ADDR(0x0f000100)
-#define TCLKLREG_TYPE2 KSEG1ADDR(0x0f000120)
-
-/* RTC 1 registers */
-#define ETIMELREG 0x00
-#define ETIMEMREG 0x02
-#define ETIMEHREG 0x04
-/* RFU */
-#define ECMPLREG 0x08
-#define ECMPMREG 0x0a
-#define ECMPHREG 0x0c
-/* RFU */
-#define RTCL1LREG 0x10
-#define RTCL1HREG 0x12
-#define RTCL1CNTLREG 0x14
-#define RTCL1CNTHREG 0x16
-#define RTCL2LREG 0x18
-#define RTCL2HREG 0x1a
-#define RTCL2CNTLREG 0x1c
-#define RTCL2CNTHREG 0x1e
-
-/* RTC 2 registers */
-#define TCLKLREG 0x00
-#define TCLKHREG 0x02
-#define TCLKCNTLREG 0x04
-#define TCLKCNTHREG 0x06
-/* RFU */
-#define RTCINTREG 0x1e
- #define TCLOCK_INT 0x08
- #define RTCLONG2_INT 0x04
- #define RTCLONG1_INT 0x02
- #define ELAPSEDTIME_INT 0x01
-
-#define read_rtc1(offset) readw(rtc1_base + (offset))
-#define write_rtc1(val, offset) writew((val), rtc1_base + (offset))
-
-#define read_rtc2(offset) readw(rtc2_base + (offset))
-#define write_rtc2(val, offset) writew((val), rtc2_base + (offset))
-
-static inline uint64_t read_elapsedtime_counter(void)
-{
- uint64_t first, second;
- uint32_t first_mid, first_low;
- uint32_t second_mid, second_low;
-
- do {
- first_low = (uint32_t)read_rtc1(ETIMELREG);
- first_mid = (uint32_t)read_rtc1(ETIMEMREG);
- first = (uint64_t)read_rtc1(ETIMEHREG);
- second_low = (uint32_t)read_rtc1(ETIMELREG);
- second_mid = (uint32_t)read_rtc1(ETIMEMREG);
- second = (uint64_t)read_rtc1(ETIMEHREG);
- } while (first_low != second_low || first_mid != second_mid ||
- first != second);
-
- return (first << 32) | (uint64_t)((first_mid << 16) | first_low);
-}
-
-static inline void write_elapsedtime_counter(uint64_t time)
-{
- write_rtc1((uint16_t)time, ETIMELREG);
- write_rtc1((uint16_t)(time >> 16), ETIMEMREG);
- write_rtc1((uint16_t)(time >> 32), ETIMEHREG);
-}
-
-static inline void write_elapsedtime_compare(uint64_t time)
-{
- write_rtc1((uint16_t)time, ECMPLREG);
- write_rtc1((uint16_t)(time >> 16), ECMPMREG);
- write_rtc1((uint16_t)(time >> 32), ECMPHREG);
-}
-
-void vr41xx_set_rtclong1_cycle(uint32_t cycles)
-{
- write_rtc1((uint16_t)cycles, RTCL1LREG);
- write_rtc1((uint16_t)(cycles >> 16), RTCL1HREG);
-}
-
-uint32_t vr41xx_read_rtclong1_counter(void)
-{
- uint32_t first_high, first_low;
- uint32_t second_high, second_low;
-
- do {
- first_low = (uint32_t)read_rtc1(RTCL1CNTLREG);
- first_high = (uint32_t)read_rtc1(RTCL1CNTHREG);
- second_low = (uint32_t)read_rtc1(RTCL1CNTLREG);
- second_high = (uint32_t)read_rtc1(RTCL1CNTHREG);
- } while (first_low != second_low || first_high != second_high);
-
- return (first_high << 16) | first_low;
-}
-
-void vr41xx_set_rtclong2_cycle(uint32_t cycles)
-{
- write_rtc1((uint16_t)cycles, RTCL2LREG);
- write_rtc1((uint16_t)(cycles >> 16), RTCL2HREG);
-}
-
-uint32_t vr41xx_read_rtclong2_counter(void)
-{
- uint32_t first_high, first_low;
- uint32_t second_high, second_low;
-
- do {
- first_low = (uint32_t)read_rtc1(RTCL2CNTLREG);
- first_high = (uint32_t)read_rtc1(RTCL2CNTHREG);
- second_low = (uint32_t)read_rtc1(RTCL2CNTLREG);
- second_high = (uint32_t)read_rtc1(RTCL2CNTHREG);
- } while (first_low != second_low || first_high != second_high);
-
- return (first_high << 16) | first_low;
-}
-
-void vr41xx_set_tclock_cycle(uint32_t cycles)
-{
- write_rtc2((uint16_t)cycles, TCLKLREG);
- write_rtc2((uint16_t)(cycles >> 16), TCLKHREG);
-}
-
-uint32_t vr41xx_read_tclock_counter(void)
-{
- uint32_t first_high, first_low;
- uint32_t second_high, second_low;
-
- do {
- first_low = (uint32_t)read_rtc2(TCLKCNTLREG);
- first_high = (uint32_t)read_rtc2(TCLKCNTHREG);
- second_low = (uint32_t)read_rtc2(TCLKCNTLREG);
- second_high = (uint32_t)read_rtc2(TCLKCNTHREG);
- } while (first_low != second_low || first_high != second_high);
-
- return (first_high << 16) | first_low;
-}
-
-static void vr41xx_timer_ack(void)
-{
- uint64_t cur;
-
- write_rtc2(ELAPSEDTIME_INT, RTCINTREG);
-
- previous_elapsedtime += (uint64_t)cycles_per_jiffy;
- cycles_per_sec += cycles_per_jiffy;
-
- if (cycles_per_sec >= CLOCK_TICK_RATE) {
- cycles_per_sec = 0;
- remainder_per_sec = REMAINDER_PER_SEC;
- }
-
- cycles_per_jiffy = 0;
-
- do {
- cycles_per_jiffy += CYCLES_PER_JIFFY;
- if (remainder_per_sec > 0) {
- cycles_per_jiffy++;
- remainder_per_sec--;
- }
-
- cur = read_elapsedtime_counter();
- } while (cur >= previous_elapsedtime + (uint64_t)cycles_per_jiffy);
-
- write_elapsedtime_compare(previous_elapsedtime + (uint64_t)cycles_per_jiffy);
-}
-
-static void vr41xx_hpt_init(unsigned int count)
-{
-}
-
-static unsigned int vr41xx_hpt_read(void)
-{
- uint64_t cur;
-
- cur = read_elapsedtime_counter();
-
- return (unsigned int)cur;
-}
-
-static unsigned long vr41xx_gettimeoffset(void)
-{
- uint64_t cur;
- unsigned long gap;
-
- cur = read_elapsedtime_counter();
- gap = (unsigned long)(cur - previous_elapsedtime);
- gap = gap / CYCLES_PER_100USEC * 100; /* usec */
-
- return gap;
-}
-
-static unsigned long vr41xx_get_time(void)
-{
- uint64_t counts;
-
- counts = read_elapsedtime_counter();
- counts >>= 15;
-
- return epoch_time + (unsigned long)counts;
-
-}
-
-static int vr41xx_set_time(unsigned long sec)
-{
- if (sec < epoch_time)
- return -EINVAL;
-
- sec -= epoch_time;
-
- write_elapsedtime_counter((uint64_t)sec << 15);
-
- return 0;
-}
-
-void vr41xx_set_epoch_time(unsigned long time)
-{
- epoch_time = time;
-}
-
-static void __init vr41xx_time_init(void)
-{
- switch (current_cpu_data.cputype) {
- case CPU_VR4111:
- case CPU_VR4121:
- rtc1_base = ETIMELREG_TYPE1;
- rtc2_base = TCLKLREG_TYPE1;
- break;
- case CPU_VR4122:
- case CPU_VR4131:
- case CPU_VR4133:
- rtc1_base = ETIMELREG_TYPE2;
- rtc2_base = TCLKLREG_TYPE2;
- break;
- default:
- panic("Unexpected CPU of NEC VR4100 series");
- break;
- }
-
- mips_timer_ack = vr41xx_timer_ack;
-
- mips_hpt_init = vr41xx_hpt_init;
- mips_hpt_read = vr41xx_hpt_read;
- mips_hpt_frequency = CLOCK_TICK_RATE;
-
- if (epoch_time == 0)
- epoch_time = mktime(1970, 1, 1, 0, 0, 0);
-
- rtc_get_time = vr41xx_get_time;
- rtc_set_time = vr41xx_set_time;
-}
-
-static void __init vr41xx_timer_setup(struct irqaction *irq)
-{
- do_gettimeoffset = vr41xx_gettimeoffset;
-
- remainder_per_sec = REMAINDER_PER_SEC;
- cycles_per_jiffy = CYCLES_PER_JIFFY;
-
- if (remainder_per_sec > 0) {
- cycles_per_jiffy++;
- remainder_per_sec--;
- }
-
- previous_elapsedtime = read_elapsedtime_counter();
- write_elapsedtime_compare(previous_elapsedtime + (uint64_t)cycles_per_jiffy);
- write_rtc2(ELAPSEDTIME_INT, RTCINTREG);
-
- setup_irq(ELAPSEDTIME_IRQ, irq);
-}
-
-static int __init vr41xx_rtc_init(void)
-{
- board_time_init = vr41xx_time_init;
- board_timer_setup = vr41xx_timer_setup;
-
- return 0;
-}
-
-early_initcall(vr41xx_rtc_init);
diff --git a/arch/mips/vr41xx/common/serial.c b/arch/mips/vr41xx/common/serial.c
deleted file mode 100644
index 939ac827eb370..0000000000000
--- a/arch/mips/vr41xx/common/serial.c
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * serial.c, Serial Interface Unit routines for NEC VR4100 series.
- *
- * Copyright (C) 2002 MontaVista Software Inc.
- * Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com>
- * Copyright (C) 2003-2004 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the 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
- */
-/*
- * Changes:
- * MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com>
- * - New creation, NEC VR4122 and VR4131 are supported.
- * - Added support for NEC VR4111 and VR4121.
- *
- * Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
- * - Added support for NEC VR4133.
- */
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/tty.h>
-#include <linux/serial.h>
-#include <linux/serial_core.h>
-#include <linux/smp.h>
-
-#include <asm/addrspace.h>
-#include <asm/cpu.h>
-#include <asm/io.h>
-#include <asm/vr41xx/vr41xx.h>
-
-#define SIUIRSEL_TYPE1 KSEG1ADDR(0x0c000008)
-#define SIUIRSEL_TYPE2 KSEG1ADDR(0x0f000808)
- #define USE_RS232C 0x00
- #define USE_IRDA 0x01
- #define SIU_USES_IRDA 0x00
- #define FIR_USES_IRDA 0x02
- #define IRDA_MODULE_SHARP 0x00
- #define IRDA_MODULE_TEMIC 0x04
- #define IRDA_MODULE_HP 0x08
- #define TMICTX 0x10
- #define TMICMODE 0x20
-
-#define SIU_BASE_TYPE1 0x0c000000UL /* VR4111 and VR4121 */
-#define SIU_BASE_TYPE2 0x0f000800UL /* VR4122, VR4131 and VR4133 */
-#define SIU_SIZE 0x8UL
-
-#define SIU_BASE_BAUD 1152000
-
-/* VR4122, VR4131 and VR4133 DSIU Registers */
-#define DSIU_BASE 0x0f000820UL
-#define DSIU_SIZE 0x8UL
-
-#define DSIU_BASE_BAUD 1152000
-
-int vr41xx_serial_ports = 0;
-
-void vr41xx_select_siu_interface(siu_interface_t interface,
- irda_module_t module)
-{
- uint16_t val = USE_RS232C; /* Select RS-232C */
-
- /* Select IrDA */
- if (interface == SIU_IRDA) {
- switch (module) {
- case IRDA_SHARP:
- val = IRDA_MODULE_SHARP;
- break;
- case IRDA_TEMIC:
- val = IRDA_MODULE_TEMIC;
- break;
- case IRDA_HP:
- val = IRDA_MODULE_HP;
- break;
- default:
- printk(KERN_ERR "SIU: unknown IrDA module\n");
- return;
- }
- val |= USE_IRDA | SIU_USES_IRDA;
- }
-
- switch (current_cpu_data.cputype) {
- case CPU_VR4111:
- case CPU_VR4121:
- writew(val, SIUIRSEL_TYPE1);
- break;
- case CPU_VR4122:
- case CPU_VR4131:
- case CPU_VR4133:
- writew(val, SIUIRSEL_TYPE2);
- break;
- default:
- printk(KERN_ERR "SIU: unsupported CPU of NEC VR4100 series\n");
- break;
- }
-}
-
-void __init vr41xx_siu_init(void)
-{
- struct uart_port port;
-
- memset(&port, 0, sizeof(port));
-
- port.line = vr41xx_serial_ports;
- port.uartclk = SIU_BASE_BAUD * 16;
- port.irq = SIU_IRQ;
- port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
- switch (current_cpu_data.cputype) {
- case CPU_VR4111:
- case CPU_VR4121:
- port.mapbase = SIU_BASE_TYPE1;
- break;
- case CPU_VR4122:
- case CPU_VR4131:
- case CPU_VR4133:
- port.mapbase = SIU_BASE_TYPE2;
- break;
- default:
- printk(KERN_ERR "SIU: unsupported CPU of NEC VR4100 series\n");
- return;
- }
- port.regshift = 0;
- port.iotype = UPIO_MEM;
- port.membase = ioremap(port.mapbase, SIU_SIZE);
- if (port.membase != NULL) {
- if (early_serial_setup(&port) == 0) {
- vr41xx_supply_clock(SIU_CLOCK);
- vr41xx_serial_ports++;
- return;
- }
- }
-
- printk(KERN_ERR "SIU: setup failed!\n");
-}
-
-void __init vr41xx_dsiu_init(void)
-{
- struct uart_port port;
-
- if (current_cpu_data.cputype != CPU_VR4122 &&
- current_cpu_data.cputype != CPU_VR4131 &&
- current_cpu_data.cputype != CPU_VR4133) {
- printk(KERN_ERR "DSIU: unsupported CPU of NEC VR4100 series\n");
- return;
- }
-
- memset(&port, 0, sizeof(port));
-
- port.line = vr41xx_serial_ports;
- port.uartclk = DSIU_BASE_BAUD * 16;
- port.irq = DSIU_IRQ;
- port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
- port.mapbase = DSIU_BASE;
- port.regshift = 0;
- port.iotype = UPIO_MEM;
- port.membase = ioremap(port.mapbase, DSIU_SIZE);
- if (port.membase != NULL) {
- if (early_serial_setup(&port) == 0) {
- vr41xx_supply_clock(DSIU_CLOCK);
- vr41xx_enable_dsiuint(DSIUINT_ALL);
- vr41xx_serial_ports++;
- return;
- }
- }
-
- printk(KERN_ERR "DSIU: setup failed!\n");
-}
diff --git a/arch/mips/vr41xx/common/vrc4171.c b/arch/mips/vr41xx/common/vrc4171.c
deleted file mode 100644
index af082023786ab..0000000000000
--- a/arch/mips/vr41xx/common/vrc4171.c
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * vrc4171.c, NEC VRC4171 base driver.
- *
- * Copyright (C) 2003 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/module.h>
-#include <linux/types.h>
-
-#include <asm/io.h>
-#include <asm/vr41xx/vrc4171.h>
-
-MODULE_DESCRIPTION("NEC VRC4171 base driver");
-MODULE_AUTHOR("Yoichi Yuasa <yuasa@hh.iij4u.or.jp>");
-MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL_GPL(vrc4171_get_irq_status);
-EXPORT_SYMBOL_GPL(vrc4171_set_multifunction_pin);
-
-#define CONFIGURATION1 0x05fe
- #define SLOTB_CONFIG 0xc000
- #define SLOTB_NONE 0x0000
- #define SLOTB_PCCARD 0x4000
- #define SLOTB_CF 0x8000
- #define SLOTB_FLASHROM 0xc000
-
-#define CONFIGURATION2 0x05fc
-#define INTERRUPT_STATUS 0x05fa
-#define PCS_CONTROL 0x05ee
-#define GPIO_DATA PCS_CONTROL
-#define PCS0_UPPER_START 0x05ec
-#define PCS0_LOWER_START 0x05ea
-#define PCS0_UPPER_STOP 0x05e8
-#define PCS0_LOWER_STOP 0x05e6
-#define PCS1_UPPER_START 0x05e4
-#define PCS1_LOWER_START 0x05e2
-#define PCS1_UPPER_STOP 0x05de
-#define PCS1_LOWER_STOP 0x05dc
-
-#define VRC4171_REGS_BASE PCS1_LOWER_STOP
-#define VRC4171_REGS_SIZE 0x24
-
-uint16_t vrc4171_get_irq_status(void)
-{
- return inw(INTERRUPT_STATUS);
-}
-
-void vrc4171_set_multifunction_pin(int config)
-{
- uint16_t config1;
-
- config1 = inw(CONFIGURATION1);
- config1 &= ~SLOTB_CONFIG;
-
- switch (config) {
- case SLOTB_IS_NONE:
- config1 |= SLOTB_NONE;
- break;
- case SLOTB_IS_PCCARD:
- config1 |= SLOTB_PCCARD;
- break;
- case SLOTB_IS_CF:
- config1 |= SLOTB_CF;
- break;
- case SLOTB_IS_FLASHROM:
- config1 |= SLOTB_FLASHROM;
- break;
- default:
- break;
- }
-
- outw(config1, CONFIGURATION1);
-}
-
-static int __devinit vrc4171_init(void)
-{
- if (request_region(VRC4171_REGS_BASE, VRC4171_REGS_SIZE, "NEC VRC4171") == NULL)
- return -EBUSY;
-
- printk(KERN_INFO "NEC VRC4171 base driver\n");
-
- return 0;
-}
-
-static void __devexit vrc4171_exit(void)
-{
- release_region(VRC4171_REGS_BASE, VRC4171_REGS_SIZE);
-}
-
-module_init(vrc4171_init);
-module_exit(vrc4171_exit);
diff --git a/arch/mips/vr41xx/ibm-workpad/setup.c b/arch/mips/vr41xx/ibm-workpad/setup.c
index 3475d2ec8cb6c..cff44602d3d41 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-2004 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * Copyright (C) 2002-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -17,7 +17,7 @@
* 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/ioport.h>
#include <asm/io.h>
@@ -28,18 +28,13 @@ const char *get_system_type(void)
return "IBM WorkPad z50";
}
-static int ibm_workpad_setup(void)
+static int __init ibm_workpad_setup(void)
{
set_io_port_base(IO_PORT_BASE);
ioport_resource.start = IO_PORT_RESOURCE_START;
ioport_resource.end = IO_PORT_RESOURCE_END;
-#ifdef CONFIG_SERIAL_8250
- vr41xx_select_siu_interface(SIU_RS232C, IRDA_NONE);
- vr41xx_siu_init();
-#endif
-
return 0;
}
-early_initcall(ibm_workpad_setup);
+arch_initcall(ibm_workpad_setup);
diff --git a/arch/mips/vr41xx/nec-cmbvr4133/setup.c b/arch/mips/vr41xx/nec-cmbvr4133/setup.c
index b2ffa1d21b4f6..db686ce42e85b 100644
--- a/arch/mips/vr41xx/nec-cmbvr4133/setup.c
+++ b/arch/mips/vr41xx/nec-cmbvr4133/setup.c
@@ -16,7 +16,6 @@
*/
#include <linux/config.h>
#include <linux/init.h>
-#include <linux/console.h>
#include <linux/ide.h>
#include <linux/ioport.h>
@@ -55,15 +54,6 @@ static struct mtd_partition cmbvr4133_mtd_parts[] = {
#define number_partitions (sizeof(cmbvr4133_mtd_parts)/sizeof(struct mtd_partition))
#endif
-extern void (*late_time_init)(void);
-
-static void __init vr4133_serial_init(void)
-{
- vr41xx_select_siu_interface(SIU_RS232C, IRDA_NONE);
- vr41xx_siu_init();
- vr41xx_dsiu_init();
-}
-
extern void i8259_init(void);
static int __init nec_cmbvr4133_setup(void)
@@ -78,8 +68,6 @@ static int __init nec_cmbvr4133_setup(void)
mips_machgroup = MACH_GROUP_NEC_VR41XX;
mips_machtype = MACH_NEC_CMBVR4133;
- late_time_init = vr4133_serial_init;
-
#ifdef CONFIG_PCI
#ifdef CONFIG_ROCKHOPPER
ali_m5229_preinit();
diff --git a/arch/mips/vr41xx/tanbac-tb0226/setup.c b/arch/mips/vr41xx/tanbac-tb0226/setup.c
index 752c0e736920b..60027e5dea25c 100644
--- a/arch/mips/vr41xx/tanbac-tb0226/setup.c
+++ b/arch/mips/vr41xx/tanbac-tb0226/setup.c
@@ -1,7 +1,7 @@
/*
* setup.c, Setup for the TANBAC TB0226.
*
- * Copyright (C) 2002-2004 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * Copyright (C) 2002-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -17,23 +17,8 @@
* 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 <asm/vr41xx/vr41xx.h>
const char *get_system_type(void)
{
return "TANBAC TB0226";
}
-
-static int tanbac_tb0226_setup(void)
-{
-#ifdef CONFIG_SERIAL_8250
- vr41xx_select_siu_interface(SIU_RS232C, IRDA_NONE);
- vr41xx_siu_init();
-#endif
-
- return 0;
-}
-
-early_initcall(tanbac_tb0226_setup);
diff --git a/arch/mips/vr41xx/tanbac-tb0229/Makefile b/arch/mips/vr41xx/tanbac-tb0229/Makefile
index dd085394a876b..9c6b864ef2ef5 100644
--- a/arch/mips/vr41xx/tanbac-tb0229/Makefile
+++ b/arch/mips/vr41xx/tanbac-tb0229/Makefile
@@ -3,5 +3,3 @@
#
obj-y := setup.o
-
-obj-$(CONFIG_TANBAC_TB0219) += tb0219.o
diff --git a/arch/mips/vr41xx/tanbac-tb0229/setup.c b/arch/mips/vr41xx/tanbac-tb0229/setup.c
index 9209e3dc6db65..5c1b757bfb0c4 100644
--- a/arch/mips/vr41xx/tanbac-tb0229/setup.c
+++ b/arch/mips/vr41xx/tanbac-tb0229/setup.c
@@ -1,7 +1,7 @@
/*
* setup.c, Setup for the TANBAC TB0229 (VR4131DIMM)
*
- * Copyright (C) 2002-2004 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * Copyright (C) 2002-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
*
* Modified for TANBAC TB0229:
* Copyright (C) 2003 Megasolution Inc. <matsu@megasolution.jp>
@@ -20,24 +20,8 @@
* 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 <asm/vr41xx/vr41xx.h>
const char *get_system_type(void)
{
return "TANBAC TB0229";
}
-
-static int tanbac_tb0229_setup(void)
-{
-#ifdef CONFIG_SERIAL_8250
- vr41xx_select_siu_interface(SIU_RS232C, IRDA_NONE);
- vr41xx_siu_init();
- vr41xx_dsiu_init();
-#endif
-
- return 0;
-}
-
-early_initcall(tanbac_tb0229_setup);
diff --git a/arch/mips/vr41xx/victor-mpc30x/setup.c b/arch/mips/vr41xx/victor-mpc30x/setup.c
index 169ac00a15314..f591e36726e69 100644
--- a/arch/mips/vr41xx/victor-mpc30x/setup.c
+++ b/arch/mips/vr41xx/victor-mpc30x/setup.c
@@ -1,7 +1,7 @@
/*
* setup.c, Setup for the Victor MP-C303/304.
*
- * Copyright (C) 2002-2004 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * Copyright (C) 2002-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -17,23 +17,8 @@
* 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 <asm/vr41xx/vr41xx.h>
const char *get_system_type(void)
{
return "Victor MP-C303/304";
}
-
-static int victor_mpc30x_setup(void)
-{
-#ifdef CONFIG_SERIAL_8250
- vr41xx_select_siu_interface(SIU_RS232C, IRDA_NONE);
- vr41xx_siu_init();
-#endif
-
- return 0;
-}
-
-early_initcall(victor_mpc30x_setup);
diff --git a/arch/mips/vr41xx/zao-capcella/setup.c b/arch/mips/vr41xx/zao-capcella/setup.c
index 35b3a0a92f3d4..17bade241fe23 100644
--- a/arch/mips/vr41xx/zao-capcella/setup.c
+++ b/arch/mips/vr41xx/zao-capcella/setup.c
@@ -1,7 +1,7 @@
/*
* setup.c, Setup for the ZAO Networks Capcella.
*
- * Copyright (C) 2002-2004 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * Copyright (C) 2002-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -17,24 +17,8 @@
* 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 <asm/vr41xx/vr41xx.h>
const char *get_system_type(void)
{
return "ZAO Networks Capcella";
}
-
-static int zao_capcella_setup(void)
-{
-#ifdef CONFIG_SERIAL_8250
- vr41xx_select_siu_interface(SIU_RS232C, IRDA_NONE);
- vr41xx_siu_init();
- vr41xx_dsiu_init();
-#endif
-
- return 0;
-}
-
-early_initcall(zao_capcella_setup);
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig
index dd761da7ddcda..5b5cd00d98ca1 100644
--- a/arch/parisc/Kconfig
+++ b/arch/parisc/Kconfig
@@ -6,8 +6,7 @@
mainmenu "Linux/PA-RISC Kernel Configuration"
config PARISC
- bool
- default y
+ def_bool y
help
The PA-RISC microprocessor is designed by Hewlett-Packard and used
in many of their workstations & servers (HP9000 700 and 800 series,
@@ -15,19 +14,16 @@ config PARISC
at <http://www.parisc-linux.org/>.
config MMU
- bool
- default y
+ def_bool y
config STACK_GROWSUP
- bool
- default y
+ def_bool y
config UID16
bool
config RWSEM_GENERIC_SPINLOCK
- bool
- default y
+ def_bool y
config RWSEM_XCHGADD_ALGORITHM
bool
@@ -111,7 +107,7 @@ config PREFETCH
def_bool y
depends on PA8X00
-config PARISC64
+config 64BIT
bool "64-bit kernel"
depends on PA8X00
help
@@ -124,9 +120,6 @@ config PARISC64
enable this option otherwise. The 64bit kernel is significantly bigger
and slower than the 32bit one.
-config 64BIT
- def_bool PARISC64
-
config SMP
bool "Symmetric multi-processing support"
---help---
@@ -166,13 +159,12 @@ config PREEMPT
default n
config COMPAT
- bool
- depends on PARISC64
- default y
+ def_bool y
+ depends on 64BIT
config HPUX
bool "Support for HP-UX binaries"
- depends on !PARISC64
+ depends on !64BIT
config NR_CPUS
int "Maximum number of CPUs (2-32)"
diff --git a/arch/parisc/Makefile b/arch/parisc/Makefile
index 17ecb61c433fd..0403d2fcb85ef 100644
--- a/arch/parisc/Makefile
+++ b/arch/parisc/Makefile
@@ -17,9 +17,12 @@
# Mike Shaver, Helge Deller and Martin K. Petersen
#
NM = sh $(srctree)/arch/parisc/nm
-ifdef CONFIG_PARISC64
+CHECKFLAGS += -D__hppa__=1
+
+ifdef CONFIG_64BIT
CROSS_COMPILE := hppa64-linux-
UTS_MACHINE := parisc64
+CHECKFLAGS += -D__LP64__=1 -m64
else
MACHINE := $(subst 64,,$(shell uname -m))
ifneq ($(MACHINE),parisc)
@@ -65,8 +68,12 @@ libs-y += arch/parisc/lib/ `$(CC) -print-libgcc-file-name`
drivers-$(CONFIG_OPROFILE) += arch/parisc/oprofile/
+PALO := $(shell if which palo; then : ; \
+ elif [ -x /sbin/palo ]; then echo /sbin/palo; \
+ fi)
+
palo: vmlinux
- @if [ $$(palo -f /dev/null >/dev/null 2>&1 ; echo $$?) != 2 ]; then \
+ @if [ -x $PALO ]; then \
echo 'ERROR: Please install palo first (apt-get install palo)';\
echo 'or build it from source and install it somewhere in your $$PATH';\
false; \
@@ -78,7 +85,7 @@ palo: vmlinux
echo 'WARNING: the "lifimage" file is now placed in this directory by default!'; \
false; \
fi
- palo -f ./palo.conf
+ $(PALO) -f ./palo.conf
oldpalo: vmlinux
export TOPDIR=`pwd`; \
diff --git a/arch/parisc/configs/a500_defconfig b/arch/parisc/configs/a500_defconfig
index e76acae49f1e3..d28ebfa1070da 100644
--- a/arch/parisc/configs/a500_defconfig
+++ b/arch/parisc/configs/a500_defconfig
@@ -1,12 +1,15 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.10-pa5
-# Wed Jan 5 13:22:34 2005
+# Linux kernel version: 2.6.11-rc4-pa1
+# Wed Feb 16 11:32:49 2005
#
CONFIG_PARISC=y
CONFIG_MMU=y
CONFIG_STACK_GROWSUP=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
#
# Code maturity level options
@@ -68,7 +71,6 @@ CONFIG_STOP_MACHINE=y
CONFIG_PA8X00=y
CONFIG_PA20=y
CONFIG_PREFETCH=y
-CONFIG_PARISC64=y
CONFIG_64BIT=y
CONFIG_SMP=y
CONFIG_HOTPLUG_CPU=y
@@ -87,16 +89,12 @@ CONFIG_PCI_NAMES=y
CONFIG_PCI_LBA=y
CONFIG_IOSAPIC=y
CONFIG_IOMMU_SBA=y
-# CONFIG_SUPERIO is not set
-# CONFIG_CHASSIS_LCD_LED is not set
-CONFIG_PDC_CHASSIS=y
#
# PCCARD (PCMCIA/CardBus) support
#
CONFIG_PCCARD=m
# CONFIG_PCMCIA_DEBUG is not set
-# CONFIG_PCMCIA_OBSOLETE is not set
CONFIG_PCMCIA=m
CONFIG_CARDBUS=y
@@ -107,6 +105,7 @@ CONFIG_YENTA=m
CONFIG_PD6729=m
CONFIG_I82092=m
CONFIG_TCIC=m
+CONFIG_PCCARD_NONSTATIC=m
#
# PCI Hotplug Support
@@ -114,6 +113,14 @@ CONFIG_TCIC=m
# CONFIG_HOTPLUG_PCI is not set
#
+# PA-RISC specific drivers
+#
+# CONFIG_SUPERIO is not set
+# CONFIG_CHASSIS_LCD_LED is not set
+CONFIG_PDC_CHASSIS=y
+CONFIG_PDC_STABLE=y
+
+#
# Executable file formats
#
CONFIG_BINFMT_ELF=y
@@ -153,6 +160,7 @@ CONFIG_FW_LOADER=y
# CONFIG_BLK_CPQ_CISS_DA is not set
# CONFIG_BLK_DEV_DAC960 is not set
CONFIG_BLK_DEV_UMEM=m
+# 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
@@ -171,6 +179,7 @@ CONFIG_IOSCHED_NOOP=y
CONFIG_IOSCHED_AS=y
CONFIG_IOSCHED_DEADLINE=y
CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
#
# ATA/ATAPI/MFM/RLL support
@@ -205,6 +214,7 @@ CONFIG_SCSI_MULTI_LUN=y
#
CONFIG_SCSI_SPI_ATTRS=y
CONFIG_SCSI_FC_ATTRS=m
+CONFIG_SCSI_ISCSI_ATTRS=m
#
# SCSI low-level drivers
@@ -231,10 +241,10 @@ CONFIG_SCSI_FC_ATTRS=m
# 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_DMA_ADDRESSING_MODE=1
CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
-CONFIG_SCSI_SYM53C8XX_IOMAPPED=y
+# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
# CONFIG_SCSI_IPR is not set
# CONFIG_SCSI_PCI2000 is not set
# CONFIG_SCSI_PCI2220I is not set
@@ -249,7 +259,6 @@ CONFIG_SCSI_QLA2XXX=y
CONFIG_SCSI_QLA2300=m
CONFIG_SCSI_QLA2322=m
CONFIG_SCSI_QLA6312=m
-CONFIG_SCSI_QLA6322=m
# CONFIG_SCSI_DC395x is not set
# CONFIG_SCSI_DC390T is not set
CONFIG_SCSI_DEBUG=m
@@ -399,8 +408,6 @@ CONFIG_IP_NF_TARGET_NOTRACK=m
CONFIG_IP_NF_ARPTABLES=m
CONFIG_IP_NF_ARPFILTER=m
CONFIG_IP_NF_ARP_MANGLE=m
-# CONFIG_IP_NF_COMPAT_IPCHAINS is not set
-# CONFIG_IP_NF_COMPAT_IPFWADM is not set
CONFIG_XFRM=y
CONFIG_XFRM_USER=m
@@ -465,7 +472,7 @@ CONFIG_TYPHOON=m
#
CONFIG_NET_TULIP=y
CONFIG_DE2104X=m
-CONFIG_TULIP=m
+CONFIG_TULIP=y
# CONFIG_TULIP_MWI is not set
CONFIG_TULIP_MMIO=y
# CONFIG_TULIP_NAPI is not set
@@ -483,7 +490,6 @@ CONFIG_PCNET32=m
# CONFIG_FORCEDETH is not set
# CONFIG_DGRS is not set
CONFIG_EEPRO100=m
-# CONFIG_EEPRO100_PIO is not set
CONFIG_E100=m
CONFIG_E100_NAPI=y
# CONFIG_FEALNX is not set
@@ -524,6 +530,7 @@ CONFIG_IXGB=m
CONFIG_IXGB_NAPI=y
CONFIG_S2IO=m
CONFIG_S2IO_NAPI=y
+# CONFIG_2BUFF_MODE is not set
#
# Token Ring devices
@@ -691,7 +698,6 @@ CONFIG_GEN_RTC_X=y
#
# Ftape, the floppy tape device driver
#
-# CONFIG_AGP is not set
# CONFIG_DRM is not set
#
@@ -733,9 +739,9 @@ CONFIG_MAX_RAW_DEVS=256
#
# Console display driver support
#
+CONFIG_DUMMY_CONSOLE=y
CONFIG_DUMMY_CONSOLE_COLUMNS=160
CONFIG_DUMMY_CONSOLE_ROWS=64
-CONFIG_DUMMY_CONSOLE=y
#
# Sound
@@ -764,6 +770,15 @@ CONFIG_USB_ARCH_HAS_OHCI=y
# 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
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -775,10 +790,16 @@ CONFIG_JBD=y
# CONFIG_REISERFS_FS is not set
CONFIG_JFS_FS=m
# CONFIG_JFS_POSIX_ACL is not set
+# CONFIG_JFS_SECURITY is not set
# CONFIG_JFS_DEBUG is not set
# CONFIG_JFS_STATISTICS is not set
CONFIG_FS_POSIX_ACL=y
+
+#
+# XFS support
+#
CONFIG_XFS_FS=m
+CONFIG_XFS_EXPORT=y
# CONFIG_XFS_RT is not set
# CONFIG_XFS_QUOTA is not set
# CONFIG_XFS_SECURITY is not set
@@ -786,7 +807,7 @@ CONFIG_XFS_FS=m
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
# CONFIG_QUOTA is not set
-# CONFIG_DNOTIFY is not set
+CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
CONFIG_AUTOFS4_FS=y
@@ -817,7 +838,8 @@ CONFIG_PROC_KCORE=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_TMPFS_XATTR is not set
# CONFIG_HUGETLBFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
@@ -935,6 +957,8 @@ CONFIG_MAGIC_SYSRQ=y
# CONFIG_DEBUG_SPINLOCK is not set
# CONFIG_DEBUG_KOBJECT is not set
# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_IOREMAP is not set
+# CONFIG_DEBUG_FS is not set
# CONFIG_DEBUG_RWLOCK is not set
#
@@ -973,6 +997,10 @@ CONFIG_CRYPTO_CRC32C=m
CONFIG_CRYPTO_TEST=m
#
+# Hardware crypto devices
+#
+
+#
# Library routines
#
CONFIG_CRC_CCITT=m
diff --git a/arch/parisc/kernel/Makefile b/arch/parisc/kernel/Makefile
index 04cbd5cb6ea0b..171f9c239f60c 100644
--- a/arch/parisc/kernel/Makefile
+++ b/arch/parisc/kernel/Makefile
@@ -19,6 +19,6 @@ obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_PA11) += pci-dma.o
obj-$(CONFIG_PCI) += pci.o
obj-$(CONFIG_MODULES) += module.o
-obj-$(CONFIG_PARISC64) += binfmt_elf32.o sys_parisc32.o ioctl32.o signal32.o
+obj-$(CONFIG_64BIT) += binfmt_elf32.o sys_parisc32.o ioctl32.o signal32.o
# only supported for PCX-W/U in 64-bit mode at the moment
-obj-$(CONFIG_PARISC64) += perf.o perf_asm.o
+obj-$(CONFIG_64BIT) += perf.o perf_asm.o
diff --git a/arch/parisc/kernel/binfmt_elf32.c b/arch/parisc/kernel/binfmt_elf32.c
index 6fd07e90aad76..d1833f164bbea 100644
--- a/arch/parisc/kernel/binfmt_elf32.c
+++ b/arch/parisc/kernel/binfmt_elf32.c
@@ -37,7 +37,6 @@ typedef unsigned int elf_greg_t;
#include <linux/spinlock.h>
#include <asm/processor.h>
#include <linux/module.h>
-#include <linux/config.h>
#include <linux/elfcore.h>
#include <linux/compat.h> /* struct compat_timeval */
diff --git a/arch/parisc/kernel/drivers.c b/arch/parisc/kernel/drivers.c
index 1f69914ca13a2..ebf186656afbd 100644
--- a/arch/parisc/kernel/drivers.c
+++ b/arch/parisc/kernel/drivers.c
@@ -10,7 +10,7 @@
* Copyright (c) 2001 Matthew Wilcox for Hewlett Packard
* Copyright (c) 2001 Helge Deller <deller@gmx.de>
* Copyright (c) 2001,2002 Ryan Bradetich
- * Copyright (c) 2004 Thibaut VARENE <varenet@parisc-linux.org>
+ * Copyright (c) 2004-2005 Thibaut VARENE <varenet@parisc-linux.org>
*
* The file handles registering devices and drivers, then matching them.
* It's the closest we get to a dating agency.
@@ -611,6 +611,24 @@ struct device *hwpath_to_device(struct hardware_path *modpath)
}
EXPORT_SYMBOL(hwpath_to_device);
+/**
+ * device_to_hwpath - Populates the hwpath corresponding to the given device.
+ * @param dev the target device
+ * @param path pointer to a previously allocated hwpath struct to be filled in
+ */
+void device_to_hwpath(struct device *dev, struct hardware_path *path)
+{
+ struct parisc_device *padev;
+ if (dev->bus == &parisc_bus_type) {
+ padev = to_parisc_device(dev);
+ get_node_path(dev->parent, path);
+ path->mod = padev->hw_path;
+ } else if (is_pci_dev(dev)) {
+ get_node_path(dev, path);
+ }
+}
+EXPORT_SYMBOL(device_to_hwpath);
+
#define BC_PORT_MASK 0x8
#define BC_LOWER_PORT 0x8
diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S
index b1dd08b03552b..ee58d37dbb275 100644
--- a/arch/parisc/kernel/entry.S
+++ b/arch/parisc/kernel/entry.S
@@ -76,13 +76,11 @@
mtsp %r0, %sr5
mtsp %r0, %sr6
mtsp %r0, %sr7
- ldil L%KERNEL_PSW, %r1
- ldo R%KERNEL_PSW(%r1), %r1
+ load32 KERNEL_PSW, %r1
mtctl %r1, %cr22
mtctl %r0, %cr17 /* Clear IIASQ tail */
mtctl %r0, %cr17 /* Clear IIASQ head */
- ldil L%4f, %r1
- ldo R%4f(%r1), %r1
+ load32 4f, %r1
mtctl %r1, %cr18 /* Set IIAOQ tail */
ldo 4(%r1), %r1
mtctl %r1, %cr18 /* Set IIAOQ head */
@@ -197,8 +195,7 @@
/* HPMC handler */
.macro hpmc code
nop /* must be a NOP, will be patched later */
- ldil L%PA(os_hpmc), %r3
- ldo R%PA(os_hpmc)(%r3), %r3
+ load32 PA(os_hpmc), %r3
bv,n 0(%r3)
nop
.word 0 /* checksum (will be patched) */
@@ -860,8 +857,7 @@ _switch_to:
callee_save
- ldil L%_switch_to_ret, %r2
- ldo R%_switch_to_ret(%r2), %r2
+ load32 _switch_to_ret, %r2
STREG %r2, TASK_PT_KPC(%r26)
LDREG TASK_PT_KPC(%r25), %r2
@@ -914,16 +910,13 @@ syscall_exit_rfi:
depi 3,31,2,%r19
STREG %r19,PT_IAOQ1(%r16)
LDREG PT_PSW(%r16),%r19
- ldil L%USER_PSW_MASK,%r1
- ldo R%USER_PSW_MASK(%r1),%r1
+ load32 USER_PSW_MASK,%r1
#ifdef __LP64__
- ldil L%USER_PSW_HI_MASK,%r20
- ldo R%USER_PSW_HI_MASK(%r20),%r20
+ load32 USER_PSW_HI_MASK,%r20
depd %r20,31,32,%r1
#endif
and %r19,%r1,%r19 /* Mask out bits that user shouldn't play with */
- ldil L%USER_PSW,%r1
- ldo R%USER_PSW(%r1),%r1
+ load32 USER_PSW,%r1
or %r19,%r1,%r19 /* Make sure default USER_PSW bits are set */
STREG %r19,PT_PSW(%r16)
@@ -955,8 +948,7 @@ intr_return:
.import irq_stat,data
- ldil L%irq_stat,%r19
- ldo R%irq_stat(%r19),%r19
+ load32 irq_stat,%r19
#ifdef CONFIG_SMP
mfctl %cr30,%r1
ldw TI_CPU(%r1),%r1 /* get cpu # - int */
@@ -1079,7 +1071,7 @@ intr_do_signal:
BL do_signal,%r2
copy %r0, %r26 /* sigset_t *oldset = NULL */
- b intr_restore
+ b intr_check_sig
nop
/*
@@ -1607,8 +1599,7 @@ dbit_trap_20w:
#ifdef CONFIG_SMP
CMPIB=,n 0,spc,dbit_nolock_20w
- ldil L%PA(pa_dbit_lock),t0
- ldo R%PA(pa_dbit_lock)(t0),t0
+ load32 PA(pa_dbit_lock),t0
dbit_spin_20w:
ldcw 0(t0),t1
@@ -1644,8 +1635,7 @@ dbit_trap_11:
#ifdef CONFIG_SMP
CMPIB=,n 0,spc,dbit_nolock_11
- ldil L%PA(pa_dbit_lock),t0
- ldo R%PA(pa_dbit_lock)(t0),t0
+ load32 PA(pa_dbit_lock),t0
dbit_spin_11:
ldcw 0(t0),t1
@@ -1685,8 +1675,7 @@ dbit_trap_20:
#ifdef CONFIG_SMP
CMPIB=,n 0,spc,dbit_nolock_20
- ldil L%PA(pa_dbit_lock),t0
- ldo R%PA(pa_dbit_lock)(t0),t0
+ load32 PA(pa_dbit_lock),t0
dbit_spin_20:
ldcw 0(t0),t1
@@ -2082,8 +2071,7 @@ syscall_check_bh:
.import irq_stat,data
- ldil L%irq_stat,%r19
- ldo R%irq_stat(%r19),%r19
+ load32 irq_stat,%r19
#ifdef CONFIG_SMP
/* sched.h: int processor */
@@ -2282,7 +2270,7 @@ syscall_do_signal:
ldo TASK_REGS(%r1), %r20 /* reload pt_regs */
reg_restore %r20
- b,n syscall_restore
+ b,n syscall_check_sig
/*
* get_register is used by the non access tlb miss handlers to
diff --git a/arch/parisc/kernel/firmware.c b/arch/parisc/kernel/firmware.c
index e8b722d25aaff..f244fb200db1f 100644
--- a/arch/parisc/kernel/firmware.c
+++ b/arch/parisc/kernel/firmware.c
@@ -120,10 +120,10 @@ static unsigned long f_extend(unsigned long address)
#ifdef __LP64__
if(unlikely(parisc_narrow_firmware)) {
if((address & 0xff000000) == 0xf0000000)
- return 0xf0f0f0f000000000 | (u32)address;
+ return 0xf0f0f0f000000000UL | (u32)address;
if((address & 0xf0000000) == 0xf0000000)
- return 0xffffffff00000000 | (u32)address;
+ return 0xffffffff00000000UL | (u32)address;
}
#endif
return address;
@@ -782,6 +782,8 @@ int pdc_pci_irt(unsigned long num_entries, unsigned long hpa, void *tbl)
{
int retval;
+ BUG_ON((unsigned long)tbl & 0x7);
+
spin_lock_irq(&pdc_lock);
pdc_result[0] = num_entries;
retval = mem_pdc_call(PDC_PCI_INDEX, PDC_PCI_GET_INT_TBL,
@@ -912,7 +914,7 @@ int pdc_do_firm_test_reset(unsigned long ftc_bitmap)
*
* Reset the system.
*/
-int pdc_do_reset()
+int pdc_do_reset(void)
{
int retval;
diff --git a/arch/parisc/kernel/hardware.c b/arch/parisc/kernel/hardware.c
index 4abd43910db64..2071b5bba15cc 100644
--- a/arch/parisc/kernel/hardware.c
+++ b/arch/parisc/kernel/hardware.c
@@ -1296,18 +1296,18 @@ static struct hp_cpu_type_mask {
};
char *cpu_name_version[][2] = {
- [pcx] { "PA7000 (PCX)", "1.0" },
- [pcxs] { "PA7000 (PCX-S)", "1.1a" },
- [pcxt] { "PA7100 (PCX-T)", "1.1b" },
- [pcxt_] { "PA7200 (PCX-T')", "1.1c" },
- [pcxl] { "PA7100LC (PCX-L)", "1.1d" },
- [pcxl2] { "PA7300LC (PCX-L2)", "1.1e" },
- [pcxu] { "PA8000 (PCX-U)", "2.0" },
- [pcxu_] { "PA8200 (PCX-U+)", "2.0" },
- [pcxw] { "PA8500 (PCX-W)", "2.0" },
- [pcxw_] { "PA8600 (PCX-W+)", "2.0" },
- [pcxw2] { "PA8700 (PCX-W2)", "2.0" },
- [mako] { "PA8800 (Mako)", "2.0" }
+ [pcx] = { "PA7000 (PCX)", "1.0" },
+ [pcxs] = { "PA7000 (PCX-S)", "1.1a" },
+ [pcxt] = { "PA7100 (PCX-T)", "1.1b" },
+ [pcxt_] = { "PA7200 (PCX-T')", "1.1c" },
+ [pcxl] = { "PA7100LC (PCX-L)", "1.1d" },
+ [pcxl2] = { "PA7300LC (PCX-L2)", "1.1e" },
+ [pcxu] = { "PA8000 (PCX-U)", "2.0" },
+ [pcxu_] = { "PA8200 (PCX-U+)", "2.0" },
+ [pcxw] = { "PA8500 (PCX-W)", "2.0" },
+ [pcxw_] = { "PA8600 (PCX-W+)", "2.0" },
+ [pcxw2] = { "PA8700 (PCX-W2)", "2.0" },
+ [mako] = { "PA8800 (Mako)", "2.0" }
};
const char * __init
diff --git a/arch/parisc/kernel/head.S b/arch/parisc/kernel/head.S
index 1fb4c05c3553f..ddf7e914f15e0 100644
--- a/arch/parisc/kernel/head.S
+++ b/arch/parisc/kernel/head.S
@@ -71,47 +71,42 @@ $bss_loop:
stw,ma %arg2,4(%r1)
stw,ma %arg3,4(%r1)
- /* Initialize startup VM. Just map first 8 MB of memory */
- load32 PA(pg0),%r1
-
-#ifdef __LP64__
- load32 PA(pmd0),%r5
- shrd %r5,PxD_VALUE_SHIFT,%r3
-#else
- shr %r1,PxD_VALUE_SHIFT,%r3
-#endif
- ldo (PxD_FLAG_PRESENT+PxD_FLAG_VALID)(%r3),%r3
-
+ /* Initialize startup VM. Just map first 8/16 MB of memory */
load32 PA(swapper_pg_dir),%r4
mtctl %r4,%cr24 /* Initialize kernel root pointer */
mtctl %r4,%cr25 /* Initialize user root pointer */
#ifdef __LP64__
+ /* Set pmd in pgd */
+ load32 PA(pmd0),%r5
+ shrd %r5,PxD_VALUE_SHIFT,%r3
+ ldo (PxD_FLAG_PRESENT+PxD_FLAG_VALID)(%r3),%r3
stw %r3,ASM_PGD_ENTRY*ASM_PGD_ENTRY_SIZE(%r4)
- shrd %r1,PxD_VALUE_SHIFT,%r3
- ldo (PxD_FLAG_PRESENT+PxD_FLAG_VALID)(%r3),%r3
- ldo ASM_PMD_ENTRY*ASM_PMD_ENTRY_SIZE(%r5),%r5
+ ldo ASM_PMD_ENTRY*ASM_PMD_ENTRY_SIZE(%r5),%r4
#else
+ /* 2-level page table, so pmd == pgd */
ldo ASM_PGD_ENTRY*ASM_PGD_ENTRY_SIZE(%r4),%r4
#endif
+
+ /* Fill in pmd with enough pte directories */
+ load32 PA(pg0),%r1
+ SHRREG %r1,PxD_VALUE_SHIFT,%r3
+ ldo (PxD_FLAG_PRESENT+PxD_FLAG_VALID)(%r3),%r3
+
ldi ASM_PT_INITIAL,%r1
1:
-#ifdef __LP64__
- stw %r3,0(%r5)
-#else
- stw %r3,0(%r4)
-#endif
-
+ stw %r3,0(%r4)
ldo (ASM_PAGE_SIZE >> PxD_VALUE_SHIFT)(%r3),%r3
addib,> -1,%r1,1b
-
#ifdef __LP64__
- ldo ASM_PMD_ENTRY_SIZE(%r5),%r5
+ ldo ASM_PMD_ENTRY_SIZE(%r4),%r4
#else
- ldo ASM_PGD_ENTRY_SIZE(%r4),%r4
+ ldo ASM_PGD_ENTRY_SIZE(%r4),%r4
#endif
+
+ /* Now initialize the PTEs themselves */
ldo _PAGE_KERNEL(%r0),%r3 /* Hardwired 0 phys addr start */
load32 PA(pg0),%r1
@@ -306,7 +301,7 @@ $rfi:
mtctl %r11,%cr18 /* IIAOQ head */
ldo 4(%r11),%r11
mtctl %r11,%cr18 /* IIAOQ tail */
-
+
/* Jump to hyperspace */
rfi
nop
diff --git a/arch/parisc/kernel/hpmc.S b/arch/parisc/kernel/hpmc.S
index eeb39506c96e2..c412c0adc4a92 100644
--- a/arch/parisc/kernel/hpmc.S
+++ b/arch/parisc/kernel/hpmc.S
@@ -121,8 +121,7 @@ os_hpmc:
/* Setup stack pointer. */
- ldil L%PA(hpmc_stack),sp
- ldo R%PA(hpmc_stack)(sp),sp
+ load32 PA(hpmc_stack),sp
ldo 128(sp),sp /* leave room for arguments */
@@ -135,8 +134,7 @@ os_hpmc:
mtctl %r4,ipsw
mtctl %r0,pcsq
mtctl %r0,pcsq
- ldil L%PA(os_hpmc_1),%r4
- ldo R%PA(os_hpmc_1)(%r4),%r4
+ load32 PA(os_hpmc_1),%r4
mtctl %r4,pcoq
ldo 4(%r4),%r4
mtctl %r4,pcoq
@@ -155,12 +153,9 @@ os_hpmc_1:
ldo PDC_PIM(%r0), arg0
ldo PDC_PIM_HPMC(%r0),arg1 /* Transfer HPMC data */
- ldil L%PA(hpmc_raddr),arg2
- ldo R%PA(hpmc_raddr)(arg2),arg2
- ldil L%PA(hpmc_pim_data),arg3
- ldo R%PA(hpmc_pim_data)(arg3),arg3
- ldil L%HPMC_PIM_DATA_SIZE,%r4
- ldo R%HPMC_PIM_DATA_SIZE(%r4),%r4
+ load32 PA(hpmc_raddr),arg2
+ load32 PA(hpmc_pim_data),arg3
+ load32 HPMC_PIM_DATA_SIZE,%r4
stw %r4,-52(sp)
ldil L%PA(os_hpmc_2), rp
@@ -199,16 +194,13 @@ os_hpmc_3:
ldo PDC_IODC(%r0),arg0
ldo PDC_IODC_READ(%r0),arg1
- ldil L%PA(hpmc_raddr),arg2
- ldo R%PA(hpmc_raddr)(arg2),arg2
+ load32 PA(hpmc_raddr),arg2
ldw BOOT_CONSOLE_HPA_OFFSET(%r0),arg3 /* console hpa */
ldo PDC_IODC_RI_INIT(%r0),%r4
stw %r4,-52(sp)
- ldil L%PA(hpmc_iodc_buf),%r4
- ldo R%PA(hpmc_iodc_buf)(%r4),%r4
+ load32 PA(hpmc_iodc_buf),%r4
stw %r4,-56(sp)
- ldil L%HPMC_IODC_BUF_SIZE,%r4
- ldo R%HPMC_IODC_BUF_SIZE(%r4),%r4
+ load32 HPMC_IODC_BUF_SIZE,%r4
stw %r4,-60(sp)
ldil L%PA(os_hpmc_4),rp
@@ -225,16 +217,14 @@ os_hpmc_4:
ldw BOOT_CONSOLE_SPA_OFFSET(%r0),arg2 /* console spa */
depi 0,31,11,arg2 /* clear bits 21-31 */
ldo BOOT_CONSOLE_PATH_OFFSET(%r0),arg3 /* console path */
- ldil L%PA(hpmc_raddr),%r4
- ldo R%PA(hpmc_raddr)(%r4),%r4
+ load32 PA(hpmc_raddr),%r4
stw %r4, -52(sp)
stw %r0, -56(sp) /* HV */
stw %r0, -60(sp) /* HV */
stw %r0, -64(sp) /* HV */
stw %r0, -68(sp) /* lang, must be zero */
- ldil L%PA(hpmc_iodc_buf),%r5
- ldo R%PA(hpmc_iodc_buf)(%r5),%r5
+ load32 PA(hpmc_iodc_buf),%r5
ldil L%PA(os_hpmc_5),rp
bv (%r5)
ldo R%PA(os_hpmc_5)(rp),rp
@@ -249,8 +239,7 @@ os_hpmc_5:
* we don't intend to ever return to user land anyway)
*/
- ldil L%PA(swapper_pg_dir),%r4
- ldo R%PA(swapper_pg_dir)(%r4),%r4
+ load32 PA(swapper_pg_dir),%r4
mtctl %r4,%cr24 /* Initialize kernel root pointer */
mtctl %r4,%cr25 /* Initialize user root pointer */
@@ -265,8 +254,7 @@ os_hpmc_5:
rsm 8,%r0 /* Clear Q bit */
ldi 1,%r8 /* Set trap code to "1" for HPMC */
- ldil L%PA(intr_save), %r1
- ldo R%PA(intr_save)(%r1), %r1
+ load32 PA(intr_save),%r1
be 0(%sr7,%r1)
nop
diff --git a/arch/parisc/kernel/init_task.c b/arch/parisc/kernel/init_task.c
index c71b9462beda4..7e898fd644153 100644
--- a/arch/parisc/kernel/init_task.c
+++ b/arch/parisc/kernel/init_task.c
@@ -55,11 +55,15 @@ union thread_union init_thread_union
#ifdef __LP64__
/* NOTE: This layout exactly conforms to the hybrid L2/L3 page table layout
- * with the first pmd adjacent to the pgd and below it */
-pmd_t pmd0[PTRS_PER_PMD] __attribute__ ((aligned(PAGE_SIZE))) = { {0}, };
+ * with the first pmd adjacent to the pgd and below it. gcc doesn't actually
+ * guarantee that global objects will be laid out in memory in the same order
+ * as the order of declaration, so put these in different sections and use
+ * the linker script to order them. */
+pmd_t pmd0[PTRS_PER_PMD] __attribute__ ((aligned(PAGE_SIZE))) __attribute__ ((__section__ (".data.vm0.pmd"))) = { {0}, };
+
#endif
-pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__ ((aligned(PAGE_SIZE))) = { {0}, };
-pte_t pg0[PT_INITIAL * PTRS_PER_PTE] __attribute__ ((aligned(PAGE_SIZE))) = { {0}, };
+pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__ ((aligned(PAGE_SIZE))) __attribute__ ((__section__ (".data.vm0.pgd"))) = { {0}, };
+pte_t pg0[PT_INITIAL * PTRS_PER_PTE] __attribute__ ((aligned(PAGE_SIZE))) __attribute__ ((__section__ (".data.vm0.pte"))) = { {0}, };
/*
* Initial task structure.
diff --git a/arch/parisc/kernel/ioctl32.c b/arch/parisc/kernel/ioctl32.c
index 53ef897ec4050..1d3824b670d12 100644
--- a/arch/parisc/kernel/ioctl32.c
+++ b/arch/parisc/kernel/ioctl32.c
@@ -563,7 +563,7 @@ static int drm32_res_ctx(unsigned int fd, unsigned int cmd, unsigned long arg)
#endif
-#define HANDLE_IOCTL(cmd, handler) { cmd, (ioctl_trans_handler_t)handler, 0 },
+#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[] = {
diff --git a/arch/parisc/kernel/irq.c b/arch/parisc/kernel/irq.c
index 6388172ec2359..006385dbee660 100644
--- a/arch/parisc/kernel/irq.c
+++ b/arch/parisc/kernel/irq.c
@@ -5,6 +5,7 @@
* Copyright (C) 1994, 1995, 1996, 1997, 1998 Ralf Baechle
* Copyright (C) 1999 SuSE GmbH (Philipp Rumpf, prumpf@tux.org)
* Copyright (C) 1999-2000 Grant Grundler
+ * Copyright (c) 2005 Matthew Wilcox
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -22,38 +23,19 @@
*/
#include <linux/bitops.h>
#include <linux/config.h>
-#include <linux/eisa.h>
#include <linux/errno.h>
#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/signal.h>
-#include <linux/types.h>
-#include <linux/ioport.h>
-#include <linux/timex.h>
-#include <linux/slab.h>
-#include <linux/random.h>
-#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/kernel_stat.h>
-#include <linux/irq.h>
#include <linux/seq_file.h>
#include <linux/spinlock.h>
+#include <linux/types.h>
-#include <asm/cache.h>
-#include <asm/pdc.h>
-
-#undef DEBUG_IRQ
#undef PARISC_IRQ_CR16_COUNTS
extern irqreturn_t timer_interrupt(int, void *, struct pt_regs *);
extern irqreturn_t ipi_interrupt(int, void *, struct pt_regs *);
-#ifdef DEBUG_IRQ
-#define DBG_IRQ(irq, x) if ((irq) != TIMER_IRQ) printk x
-#else /* DEBUG_IRQ */
-#define DBG_IRQ(irq, x) do { } while (0)
-#endif /* DEBUG_IRQ */
-
#define EIEM_MASK(irq) (1UL<<(CPU_IRQ_MAX - irq))
/* Bits in EIEM correlate with cpu_irq_action[].
@@ -120,8 +102,10 @@ int show_interrupts(struct seq_file *p, void *v)
}
if (i < NR_IRQS) {
+ struct irqaction *action;
+
spin_lock_irqsave(&irq_desc[i].lock, flags);
- struct irqaction *action = irq_desc[i].action;
+ action = irq_desc[i].action;
if (!action)
goto skip;
seq_printf(p, "%3d: ", i);
@@ -200,7 +184,25 @@ int txn_claim_irq(int irq)
return cpu_claim_irq(irq, NULL, NULL) ? -1 : irq;
}
-int txn_alloc_irq(void)
+/*
+ * The bits_wide parameter accommodates the limitations of the HW/SW which
+ * use these bits:
+ * Legacy PA I/O (GSC/NIO): 5 bits (architected EIM register)
+ * V-class (EPIC): 6 bits
+ * N/L/A-class (iosapic): 8 bits
+ * PCI 2.2 MSI: 16 bits
+ * Some PCI devices: 32 bits (Symbios SCSI/ATM/HyperFabric)
+ *
+ * On the service provider side:
+ * o PA 1.1 (and PA2.0 narrow mode) 5-bits (width of EIR register)
+ * o PA 2.0 wide mode 6-bits (per processor)
+ * o IA64 8-bits (0-256 total)
+ *
+ * So a Legacy PA I/O device on a PA 2.0 box can't use all the bits supported
+ * by the processor...and the N/L-class I/O subsystem supports more bits than
+ * PA2.0 has. The first case is the problem.
+ */
+int txn_alloc_irq(unsigned int bits_wide)
{
int irq;
@@ -208,6 +210,8 @@ int txn_alloc_irq(void)
for (irq = CPU_IRQ_BASE + 1; irq <= CPU_IRQ_MAX; irq++) {
if (cpu_claim_irq(irq, NULL, NULL) < 0)
continue;
+ if ((irq - CPU_IRQ_BASE) >= (1 << bits_wide))
+ continue;
return irq;
}
@@ -215,7 +219,7 @@ int txn_alloc_irq(void)
return -1;
}
-unsigned long txn_alloc_addr(int virt_irq)
+unsigned long txn_alloc_addr(unsigned int virt_irq)
{
static int next_cpu = -1;
@@ -233,36 +237,8 @@ unsigned long txn_alloc_addr(int virt_irq)
}
-/*
-** The alloc process needs to accept a parameter to accommodate limitations
-** of the HW/SW which use these bits:
-** Legacy PA I/O (GSC/NIO): 5 bits (architected EIM register)
-** V-class (EPIC): 6 bits
-** N/L-class/A500: 8 bits (iosapic)
-** PCI 2.2 MSI: 16 bits (I think)
-** Existing PCI devices: 32-bits (all Symbios SCSI/ATM/HyperFabric)
-**
-** On the service provider side:
-** o PA 1.1 (and PA2.0 narrow mode) 5-bits (width of EIR register)
-** o PA 2.0 wide mode 6-bits (per processor)
-** o IA64 8-bits (0-256 total)
-**
-** So a Legacy PA I/O device on a PA 2.0 box can't use all
-** the bits supported by the processor...and the N/L-class
-** I/O subsystem supports more bits than PA2.0 has. The first
-** case is the problem.
-*/
-unsigned int txn_alloc_data(int virt_irq, unsigned int bits_wide)
+unsigned int txn_alloc_data(unsigned int virt_irq)
{
- /* XXX FIXME : bits_wide indicates how wide the transaction
- ** data is allowed to be...we may need a different virt_irq
- ** if this one won't work. Another reason to index virtual
- ** irq's into a table which can manage CPU/IRQ bit separately.
- */
- if ((virt_irq - CPU_IRQ_BASE) > (1 << (bits_wide - 1))) {
- panic("Sorry -- didn't allocate valid IRQ for this device\n");
- }
-
return virt_irq - CPU_IRQ_BASE;
}
@@ -270,42 +246,35 @@ unsigned int txn_alloc_data(int virt_irq, unsigned int bits_wide)
void do_cpu_irq_mask(struct pt_regs *regs)
{
unsigned long eirr_val;
- unsigned int i=3; /* limit time in interrupt context */
+
+ irq_enter();
/*
- * PSW_I or EIEM bits cannot be enabled until after the
- * interrupts are processed.
- * timer_interrupt() assumes it won't get interrupted when it
- * holds the xtime_lock...an unmasked interrupt source could
- * interrupt and deadlock by trying to grab xtime_lock too.
- * Keeping PSW_I and EIEM disabled avoids this.
+ * Only allow interrupt processing to be interrupted by the
+ * timer tick
*/
- set_eiem(0UL); /* disable all extr interrupt for now */
+ set_eiem(EIEM_MASK(TIMER_IRQ));
/* 1) only process IRQs that are enabled/unmasked (cpu_eiem)
* 2) We loop here on EIRR contents in order to avoid
* nested interrupts or having to take another interrupt
* when we could have just handled it right away.
- * 3) Limit the number of times we loop to make sure other
- * processing can occur.
*/
for (;;) {
unsigned long bit = (1UL << (BITS_PER_LONG - 1));
unsigned int irq;
eirr_val = mfctl(23) & cpu_eiem;
- if (!eirr_val || !i--)
+ if (!eirr_val)
break;
- mtctl(eirr_val, 23); /* reset bits we are going to process */
+ if (eirr_val & EIEM_MASK(TIMER_IRQ))
+ set_eiem(0);
-#ifdef DEBUG_IRQ
- if (eirr_val != (1UL << MAX_CPU_IRQ))
- printk(KERN_DEBUG "do_cpu_irq_mask 0x%x & 0x%x\n", eirr_val, cpu_eiem);
-#endif
+ mtctl(eirr_val, 23); /* reset bits we are going to process */
/* Work our way from MSb to LSb...same order we alloc EIRs */
for (irq = TIMER_IRQ; eirr_val && bit; bit>>=1, irq++) {
- if (!(bit & eirr_val & cpu_eiem))
+ if (!(bit & eirr_val))
continue;
/* clear bit in mask - can exit loop sooner */
@@ -315,6 +284,7 @@ void do_cpu_irq_mask(struct pt_regs *regs)
}
}
set_eiem(cpu_eiem);
+ irq_exit();
}
diff --git a/arch/parisc/kernel/module.c b/arch/parisc/kernel/module.c
index 1ac525b53b8c8..f27cfe4771b88 100644
--- a/arch/parisc/kernel/module.c
+++ b/arch/parisc/kernel/module.c
@@ -2,7 +2,7 @@
*
* The best reference for this stuff is probably the Processor-
* Specific ELF Supplement for PA-RISC:
- * http://ftp.parisc-linux.org/docs/elf-pa-hp.pdf
+ * http://ftp.parisc-linux.org/docs/arch/elf-pa-hp.pdf
*
* Linux/PA-RISC Project (http://www.parisc-linux.org/)
* Copyright (C) 2003 Randolph Chung <tausq at debian . org>
@@ -21,6 +21,23 @@
* You should have received a copy of the 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:
+ * - SEGREL32 handling
+ * We are not doing SEGREL32 handling correctly. According to the ABI, we
+ * should do a value offset, like this:
+ * if (is_init(me, (void *)val))
+ * val -= (uint32_t)me->module_init;
+ * else
+ * val -= (uint32_t)me->module_core;
+ * However, SEGREL32 is used only for PARISC unwind entries, and we want
+ * those entries to have an absolute address, and not just an offset.
+ *
+ * The unwind table mechanism has the ability to specify an offset for
+ * the unwind table; however, because we split off the init functions into
+ * a different piece of memory, it is not possible to do this using a
+ * single offset. Instead, we use the above hack for now.
*/
#include <linux/moduleloader.h>
@@ -30,6 +47,8 @@
#include <linux/string.h>
#include <linux/kernel.h>
+#include <asm/unwind.h>
+
#if 0
#define DEBUGP printk
#else
@@ -248,6 +267,10 @@ int module_frob_arch_sections(CONST Elf_Ehdr *hdr,
const Elf_Rela *rels = (void *)hdr + sechdrs[i].sh_offset;
unsigned long nrels = sechdrs[i].sh_size / sizeof(*rels);
+ if (strncmp(secstrings + sechdrs[i].sh_name,
+ ".PARISC.unwind", 14) == 0)
+ me->arch.unwind_section = i;
+
if (sechdrs[i].sh_type != SHT_RELA)
continue;
@@ -499,7 +522,9 @@ int apply_relocate_add(Elf_Shdr *sechdrs,
break;
case R_PARISC_SEGREL32:
/* 32-bit segment relative address */
- val -= (uint32_t)me->module_core;
+ /* See note about special handling of SEGREL32 at
+ * the beginning of this file.
+ */
*loc = fsel(val, addend);
break;
case R_PARISC_DPREL21L:
@@ -651,7 +676,9 @@ int apply_relocate_add(Elf_Shdr *sechdrs,
break;
case R_PARISC_SEGREL32:
/* 32-bit segment relative address */
- val -= (uint64_t)me->module_core;
+ /* See note about special handling of SEGREL32 at
+ * the beginning of this file.
+ */
*loc = fsel(val, addend);
break;
case R_PARISC_FPTR64:
@@ -682,6 +709,32 @@ int apply_relocate_add(Elf_Shdr *sechdrs,
}
#endif
+static void
+register_unwind_table(struct module *me,
+ const Elf_Shdr *sechdrs)
+{
+ unsigned char *table, *end;
+ unsigned long gp;
+
+ if (!me->arch.unwind_section)
+ return;
+
+ table = (unsigned char *)sechdrs[me->arch.unwind_section].sh_addr;
+ end = table + sechdrs[me->arch.unwind_section].sh_size;
+ gp = (Elf_Addr)me->module_core + me->arch.got_offset;
+
+ DEBUGP("register_unwind_table(), sect = %d at 0x%p - 0x%p (gp=0x%lx)\n",
+ me->arch.unwind_section, table, end, gp);
+ me->arch.unwind = unwind_table_add(me->name, 0, gp, table, end);
+}
+
+static void
+deregister_unwind_table(struct module *me)
+{
+ if (me->arch.unwind)
+ unwind_table_remove(me->arch.unwind);
+}
+
int module_finalize(const Elf_Ehdr *hdr,
const Elf_Shdr *sechdrs,
struct module *me)
@@ -711,6 +764,8 @@ int module_finalize(const Elf_Ehdr *hdr,
me->arch.fdesc_count, me->arch.fdesc_max);
#endif
+ register_unwind_table(me, sechdrs);
+
/* haven't filled in me->symtab yet, so have to find it
* ourselves */
for (i = 1; i < hdr->e_shnum; i++) {
@@ -763,4 +818,5 @@ int module_finalize(const Elf_Ehdr *hdr,
void module_arch_cleanup(struct module *mod)
{
+ deregister_unwind_table(mod);
}
diff --git a/arch/parisc/kernel/pacache.S b/arch/parisc/kernel/pacache.S
index c028480b8d9db..77e03bc0f9356 100644
--- a/arch/parisc/kernel/pacache.S
+++ b/arch/parisc/kernel/pacache.S
@@ -27,17 +27,17 @@
*/
#ifdef __LP64__
-#define ADDIB addib,*
-#define CMPB cmpb,*
-#define ANDCM andcm,*
+#define ADDIB addib,*
+#define CMPB cmpb,*
+#define ANDCM andcm,*
- .level 2.0w
+ .level 2.0w
#else
-#define ADDIB addib,
-#define CMPB cmpb,
-#define ANDCM andcm
+#define ADDIB addib,
+#define CMPB cmpb,
+#define ANDCM andcm
- .level 2.0
+ .level 2.0
#endif
#include <asm/assembly.h>
@@ -46,7 +46,7 @@
#include <asm/cache.h>
.text
- .align 128
+ .align 128
.export flush_tlb_all_local,code
@@ -68,7 +68,7 @@ flush_tlb_all_local:
* consolidated.
*/
- rsm PSW_SM_I,%r19 /* relied upon translation! PA 2.0 Arch. F-5 */
+ rsm PSW_SM_I, %r19 /* relied upon translation! PA 2.0 Arch. F-5 */
nop
nop
nop
@@ -77,127 +77,127 @@ flush_tlb_all_local:
nop
nop
- rsm PSW_SM_Q,%r0 /* Turn off Q bit to load iia queue */
- ldil L%REAL_MODE_PSW, %r1
- ldo R%REAL_MODE_PSW(%r1), %r1
- mtctl %r1, %cr22
- mtctl %r0, %cr17 /* Clear IIASQ tail */
- mtctl %r0, %cr17 /* Clear IIASQ head */
- ldil L%PA(1f),%r1
- ldo R%PA(1f)(%r1),%r1
- mtctl %r1, %cr18 /* IIAOQ head */
- ldo 4(%r1), %r1
- mtctl %r1, %cr18 /* IIAOQ tail */
+ rsm PSW_SM_Q, %r0 /* Turn off Q bit to load iia queue */
+ ldil L%REAL_MODE_PSW, %r1
+ ldo R%REAL_MODE_PSW(%r1), %r1
+ mtctl %r1, %cr22
+ mtctl %r0, %cr17 /* Clear IIASQ tail */
+ mtctl %r0, %cr17 /* Clear IIASQ head */
+ ldil L%PA(1f), %r1
+ ldo R%PA(1f)(%r1), %r1
+ mtctl %r1, %cr18 /* IIAOQ head */
+ ldo 4(%r1), %r1
+ mtctl %r1, %cr18 /* IIAOQ tail */
rfi
nop
-1: ldil L%PA(cache_info),%r1
- ldo R%PA(cache_info)(%r1),%r1
+1: ldil L%PA(cache_info), %r1
+ ldo R%PA(cache_info)(%r1), %r1
/* Flush Instruction Tlb */
- LDREG ITLB_SID_BASE(%r1),%r20
- LDREG ITLB_SID_STRIDE(%r1),%r21
- LDREG ITLB_SID_COUNT(%r1),%r22
- LDREG ITLB_OFF_BASE(%r1),%arg0
- LDREG ITLB_OFF_STRIDE(%r1),%arg1
- LDREG ITLB_OFF_COUNT(%r1),%arg2
- LDREG ITLB_LOOP(%r1),%arg3
-
- ADDIB= -1,%arg3,fitoneloop /* Preadjust and test */
- movb,<,n %arg3,%r31,fitdone /* If loop < 0, skip */
- copy %arg0,%r28 /* Init base addr */
-
-fitmanyloop: /* Loop if LOOP >= 2 */
- mtsp %r20,%sr1
- add %r21,%r20,%r20 /* increment space */
- copy %arg2,%r29 /* Init middle loop count */
-
-fitmanymiddle: /* Loop if LOOP >= 2 */
- ADDIB> -1,%r31,fitmanymiddle /* Adjusted inner loop decr */
- pitlbe 0(%sr1,%r28)
- pitlbe,m %arg1(%sr1,%r28) /* Last pitlbe and addr adjust */
- ADDIB> -1,%r29,fitmanymiddle /* Middle loop decr */
- copy %arg3,%r31 /* Re-init inner loop count */
-
- movb,tr %arg0,%r28,fitmanyloop /* Re-init base addr */
- ADDIB<=,n -1,%r22,fitdone /* Outer loop count decr */
-
-fitoneloop: /* Loop if LOOP = 1 */
- mtsp %r20,%sr1
- copy %arg0,%r28 /* init base addr */
- copy %arg2,%r29 /* init middle loop count */
-
-fitonemiddle: /* Loop if LOOP = 1 */
- ADDIB> -1,%r29,fitonemiddle /* Middle loop count decr */
- pitlbe,m %arg1(%sr1,%r28) /* pitlbe for one loop */
-
- ADDIB> -1,%r22,fitoneloop /* Outer loop count decr */
- add %r21,%r20,%r20 /* increment space */
+ LDREG ITLB_SID_BASE(%r1), %r20
+ LDREG ITLB_SID_STRIDE(%r1), %r21
+ LDREG ITLB_SID_COUNT(%r1), %r22
+ LDREG ITLB_OFF_BASE(%r1), %arg0
+ LDREG ITLB_OFF_STRIDE(%r1), %arg1
+ LDREG ITLB_OFF_COUNT(%r1), %arg2
+ LDREG ITLB_LOOP(%r1), %arg3
+
+ ADDIB= -1, %arg3, fitoneloop /* Preadjust and test */
+ movb,<,n %arg3, %r31, fitdone /* If loop < 0, skip */
+ copy %arg0, %r28 /* Init base addr */
+
+fitmanyloop: /* Loop if LOOP >= 2 */
+ mtsp %r20, %sr1
+ add %r21, %r20, %r20 /* increment space */
+ copy %arg2, %r29 /* Init middle loop count */
+
+fitmanymiddle: /* Loop if LOOP >= 2 */
+ ADDIB> -1, %r31, fitmanymiddle /* Adjusted inner loop decr */
+ pitlbe 0(%sr1, %r28)
+ pitlbe,m %arg1(%sr1, %r28) /* Last pitlbe and addr adjust */
+ ADDIB> -1, %r29, fitmanymiddle /* Middle loop decr */
+ copy %arg3, %r31 /* Re-init inner loop count */
+
+ movb,tr %arg0, %r28, fitmanyloop /* Re-init base addr */
+ ADDIB<=,n -1, %r22, fitdone /* Outer loop count decr */
+
+fitoneloop: /* Loop if LOOP = 1 */
+ mtsp %r20, %sr1
+ copy %arg0, %r28 /* init base addr */
+ copy %arg2, %r29 /* init middle loop count */
+
+fitonemiddle: /* Loop if LOOP = 1 */
+ ADDIB> -1, %r29, fitonemiddle /* Middle loop count decr */
+ pitlbe,m %arg1(%sr1, %r28) /* pitlbe for one loop */
+
+ ADDIB> -1, %r22, fitoneloop /* Outer loop count decr */
+ add %r21, %r20, %r20 /* increment space */
fitdone:
/* Flush Data Tlb */
- LDREG DTLB_SID_BASE(%r1),%r20
- LDREG DTLB_SID_STRIDE(%r1),%r21
- LDREG DTLB_SID_COUNT(%r1),%r22
- LDREG DTLB_OFF_BASE(%r1),%arg0
- LDREG DTLB_OFF_STRIDE(%r1),%arg1
- LDREG DTLB_OFF_COUNT(%r1),%arg2
- LDREG DTLB_LOOP(%r1),%arg3
-
- ADDIB= -1,%arg3,fdtoneloop /* Preadjust and test */
- movb,<,n %arg3,%r31,fdtdone /* If loop < 0, skip */
- copy %arg0,%r28 /* Init base addr */
-
-fdtmanyloop: /* Loop if LOOP >= 2 */
- mtsp %r20,%sr1
- add %r21,%r20,%r20 /* increment space */
- copy %arg2,%r29 /* Init middle loop count */
-
-fdtmanymiddle: /* Loop if LOOP >= 2 */
- ADDIB> -1,%r31,fdtmanymiddle /* Adjusted inner loop decr */
- pdtlbe 0(%sr1,%r28)
- pdtlbe,m %arg1(%sr1,%r28) /* Last pdtlbe and addr adjust */
- ADDIB> -1,%r29,fdtmanymiddle /* Middle loop decr */
- copy %arg3,%r31 /* Re-init inner loop count */
-
- movb,tr %arg0,%r28,fdtmanyloop /* Re-init base addr */
- ADDIB<=,n -1,%r22,fdtdone /* Outer loop count decr */
-
-fdtoneloop: /* Loop if LOOP = 1 */
- mtsp %r20,%sr1
- copy %arg0,%r28 /* init base addr */
- copy %arg2,%r29 /* init middle loop count */
-
-fdtonemiddle: /* Loop if LOOP = 1 */
- ADDIB> -1,%r29,fdtonemiddle /* Middle loop count decr */
- pdtlbe,m %arg1(%sr1,%r28) /* pdtlbe for one loop */
-
- ADDIB> -1,%r22,fdtoneloop /* Outer loop count decr */
- add %r21,%r20,%r20 /* increment space */
+ LDREG DTLB_SID_BASE(%r1), %r20
+ LDREG DTLB_SID_STRIDE(%r1), %r21
+ LDREG DTLB_SID_COUNT(%r1), %r22
+ LDREG DTLB_OFF_BASE(%r1), %arg0
+ LDREG DTLB_OFF_STRIDE(%r1), %arg1
+ LDREG DTLB_OFF_COUNT(%r1), %arg2
+ LDREG DTLB_LOOP(%r1), %arg3
+
+ ADDIB= -1, %arg3, fdtoneloop /* Preadjust and test */
+ movb,<,n %arg3, %r31, fdtdone /* If loop < 0, skip */
+ copy %arg0, %r28 /* Init base addr */
+
+fdtmanyloop: /* Loop if LOOP >= 2 */
+ mtsp %r20, %sr1
+ add %r21, %r20, %r20 /* increment space */
+ copy %arg2, %r29 /* Init middle loop count */
+
+fdtmanymiddle: /* Loop if LOOP >= 2 */
+ ADDIB> -1, %r31, fdtmanymiddle /* Adjusted inner loop decr */
+ pdtlbe 0(%sr1, %r28)
+ pdtlbe,m %arg1(%sr1, %r28) /* Last pdtlbe and addr adjust */
+ ADDIB> -1, %r29, fdtmanymiddle /* Middle loop decr */
+ copy %arg3, %r31 /* Re-init inner loop count */
+
+ movb,tr %arg0, %r28, fdtmanyloop /* Re-init base addr */
+ ADDIB<=,n -1, %r22,fdtdone /* Outer loop count decr */
+
+fdtoneloop: /* Loop if LOOP = 1 */
+ mtsp %r20, %sr1
+ copy %arg0, %r28 /* init base addr */
+ copy %arg2, %r29 /* init middle loop count */
+
+fdtonemiddle: /* Loop if LOOP = 1 */
+ ADDIB> -1, %r29, fdtonemiddle /* Middle loop count decr */
+ pdtlbe,m %arg1(%sr1, %r28) /* pdtlbe for one loop */
+
+ ADDIB> -1, %r22, fdtoneloop /* Outer loop count decr */
+ add %r21, %r20, %r20 /* increment space */
fdtdone:
/* Switch back to virtual mode */
- rsm PSW_SM_Q,%r0 /* clear Q bit to load iia queue */
- ldil L%KERNEL_PSW, %r1
- ldo R%KERNEL_PSW(%r1), %r1
- or %r1,%r19,%r1 /* Set I bit if set on entry */
- mtctl %r1, %cr22
- mtctl %r0, %cr17 /* Clear IIASQ tail */
- mtctl %r0, %cr17 /* Clear IIASQ head */
- ldil L%(2f), %r1
- ldo R%(2f)(%r1), %r1
- mtctl %r1, %cr18 /* IIAOQ head */
- ldo 4(%r1), %r1
- mtctl %r1, %cr18 /* IIAOQ tail */
+ rsm PSW_SM_Q, %r0 /* clear Q bit to load iia queue */
+ ldil L%KERNEL_PSW, %r1
+ ldo R%KERNEL_PSW(%r1), %r1
+ or %r1, %r19, %r1 /* Set I bit if set on entry */
+ mtctl %r1, %cr22
+ mtctl %r0, %cr17 /* Clear IIASQ tail */
+ mtctl %r0, %cr17 /* Clear IIASQ head */
+ ldil L%(2f), %r1
+ ldo R%(2f)(%r1), %r1
+ mtctl %r1, %cr18 /* IIAOQ head */
+ ldo 4(%r1), %r1
+ mtctl %r1, %cr18 /* IIAOQ tail */
rfi
nop
-2: bv %r0(%r2)
+2: bv %r0(%r2)
nop
.exit
@@ -211,140 +211,198 @@ flush_instruction_cache_local:
.callinfo NO_CALLS
.entry
- mtsp %r0,%sr1
- ldil L%cache_info,%r1
- ldo R%cache_info(%r1),%r1
+ mtsp %r0, %sr1
+ ldil L%cache_info, %r1
+ ldo R%cache_info(%r1), %r1
/* Flush Instruction Cache */
- LDREG ICACHE_BASE(%r1),%arg0
- LDREG ICACHE_STRIDE(%r1),%arg1
- LDREG ICACHE_COUNT(%r1),%arg2
- LDREG ICACHE_LOOP(%r1),%arg3
- rsm PSW_SM_I,%r22 /* No mmgt ops during loop*/
- ADDIB= -1,%arg3,fioneloop /* Preadjust and test */
- movb,<,n %arg3,%r31,fisync /* If loop < 0, do sync */
-
-fimanyloop: /* Loop if LOOP >= 2 */
- ADDIB> -1,%r31,fimanyloop /* Adjusted inner loop decr */
- fice 0(%sr1,%arg0)
- fice,m %arg1(%sr1,%arg0) /* Last fice and addr adjust */
- movb,tr %arg3,%r31,fimanyloop /* Re-init inner loop count */
- ADDIB<=,n -1,%arg2,fisync /* Outer loop decr */
-
-fioneloop: /* Loop if LOOP = 1 */
- ADDIB> -1,%arg2,fioneloop /* Outer loop count decr */
- fice,m %arg1(%sr1,%arg0) /* Fice for one loop */
+ LDREG ICACHE_BASE(%r1), %arg0
+ LDREG ICACHE_STRIDE(%r1), %arg1
+ LDREG ICACHE_COUNT(%r1), %arg2
+ LDREG ICACHE_LOOP(%r1), %arg3
+ rsm PSW_SM_I, %r22 /* No mmgt ops during loop*/
+ ADDIB= -1, %arg3, fioneloop /* Preadjust and test */
+ movb,<,n %arg3, %r31, fisync /* If loop < 0, do sync */
+
+fimanyloop: /* Loop if LOOP >= 2 */
+ ADDIB> -1, %r31, fimanyloop /* Adjusted inner loop decr */
+ fice 0(%sr1, %arg0)
+ fice,m %arg1(%sr1, %arg0) /* Last fice and addr adjust */
+ movb,tr %arg3, %r31, fimanyloop /* Re-init inner loop count */
+ ADDIB<=,n -1, %arg2, fisync /* Outer loop decr */
+
+fioneloop: /* Loop if LOOP = 1 */
+ ADDIB> -1, %arg2, fioneloop /* Outer loop count decr */
+ fice,m %arg1(%sr1, %arg0) /* Fice for one loop */
fisync:
sync
- mtsm %r22
- bv %r0(%r2)
+ mtsm %r22
+ bv %r0(%r2)
nop
.exit
.procend
- .export flush_data_cache_local,code
- .import cache_info,data
+ .export flush_data_cache_local, code
+ .import cache_info, data
flush_data_cache_local:
.proc
.callinfo NO_CALLS
.entry
- mtsp %r0,%sr1
- ldil L%cache_info,%r1
- ldo R%cache_info(%r1),%r1
+ mtsp %r0, %sr1
+ ldil L%cache_info, %r1
+ ldo R%cache_info(%r1), %r1
/* Flush Data Cache */
- LDREG DCACHE_BASE(%r1),%arg0
- LDREG DCACHE_STRIDE(%r1),%arg1
- LDREG DCACHE_COUNT(%r1),%arg2
- LDREG DCACHE_LOOP(%r1),%arg3
- rsm PSW_SM_I,%r22
- ADDIB= -1,%arg3,fdoneloop /* Preadjust and test */
- movb,<,n %arg3,%r31,fdsync /* If loop < 0, do sync */
-
-fdmanyloop: /* Loop if LOOP >= 2 */
- ADDIB> -1,%r31,fdmanyloop /* Adjusted inner loop decr */
- fdce 0(%sr1,%arg0)
- fdce,m %arg1(%sr1,%arg0) /* Last fdce and addr adjust */
- movb,tr %arg3,%r31,fdmanyloop /* Re-init inner loop count */
- ADDIB<=,n -1,%arg2,fdsync /* Outer loop decr */
-
-fdoneloop: /* Loop if LOOP = 1 */
- ADDIB> -1,%arg2,fdoneloop /* Outer loop count decr */
- fdce,m %arg1(%sr1,%arg0) /* Fdce for one loop */
+ LDREG DCACHE_BASE(%r1), %arg0
+ LDREG DCACHE_STRIDE(%r1), %arg1
+ LDREG DCACHE_COUNT(%r1), %arg2
+ LDREG DCACHE_LOOP(%r1), %arg3
+ rsm PSW_SM_I, %r22
+ ADDIB= -1, %arg3, fdoneloop /* Preadjust and test */
+ movb,<,n %arg3, %r31, fdsync /* If loop < 0, do sync */
+
+fdmanyloop: /* Loop if LOOP >= 2 */
+ ADDIB> -1, %r31, fdmanyloop /* Adjusted inner loop decr */
+ fdce 0(%sr1, %arg0)
+ fdce,m %arg1(%sr1, %arg0) /* Last fdce and addr adjust */
+ movb,tr %arg3, %r31, fdmanyloop /* Re-init inner loop count */
+ ADDIB<=,n -1, %arg2, fdsync /* Outer loop decr */
+
+fdoneloop: /* Loop if LOOP = 1 */
+ ADDIB> -1, %arg2, fdoneloop /* Outer loop count decr */
+ fdce,m %arg1(%sr1, %arg0) /* Fdce for one loop */
fdsync:
syncdma
sync
- mtsm %r22
- bv %r0(%r2)
+ mtsm %r22
+ bv %r0(%r2)
nop
.exit
.procend
.export copy_user_page_asm,code
+ .align 16
copy_user_page_asm:
.proc
.callinfo NO_CALLS
.entry
- ldi 64,%r1
+#ifdef __LP64__
+ /* PA8x00 CPUs can consume 2 loads or 1 store per cycle.
+ * Unroll the loop by hand and arrange insn appropriately.
+ * GCC probably can do this just as well.
+ */
+
+ ldd 0(%r25), %r19
+ ldi 32, %r1 /* PAGE_SIZE/128 == 32 */
+ ldw 64(%r25), %r0 /* prefetch 1 cacheline ahead */
+ ldw 128(%r25), %r0 /* prefetch 2 */
+
+1: ldd 8(%r25), %r20
+ ldw 192(%r25), %r0 /* prefetch 3 */
+ ldw 256(%r25), %r0 /* prefetch 4 */
+
+ ldd 16(%r25), %r21
+ ldd 24(%r25), %r22
+ std %r19, 0(%r26)
+ std %r20, 8(%r26)
+
+ ldd 32(%r25), %r19
+ ldd 40(%r25), %r20
+ std %r21, 16(%r26)
+ std %r22, 24(%r26)
+
+ ldd 48(%r25), %r21
+ ldd 56(%r25), %r22
+ std %r19, 32(%r26)
+ std %r20, 40(%r26)
+
+ ldd 64(%r25), %r19
+ ldd 72(%r25), %r20
+ std %r21, 48(%r26)
+ std %r22, 56(%r26)
+
+ ldd 80(%r25), %r21
+ ldd 88(%r25), %r22
+ std %r19, 64(%r26)
+ std %r20, 72(%r26)
+
+ ldd 96(%r25), %r19
+ ldd 104(%r25), %r20
+ std %r21, 80(%r26)
+ std %r22, 88(%r26)
+
+ ldd 112(%r25), %r21
+ ldd 120(%r25), %r22
+ std %r19, 96(%r26)
+ std %r20, 104(%r26)
+
+ ldo 128(%r25), %r25
+ std %r21, 112(%r26)
+ std %r22, 120(%r26)
+ ldo 128(%r26), %r26
+
+ ADDIB> -1, %r1, 1b /* bundle 10 */
+ ldd 0(%r25), %r19 /* start next loads */
+
+#else
/*
* This loop is optimized for PCXL/PCXL2 ldw/ldw and stw/stw
- * bundles (very restricted rules for bundling). It probably
- * does OK on PCXU and better, but we could do better with
- * ldd/std instructions. Note that until (if) we start saving
+ * bundles (very restricted rules for bundling).
+ * Note that until (if) we start saving
* the full 64 bit register values on interrupt, we can't
* use ldd/std on a 32 bit kernel.
*/
-
+ ldi 64, %r1 /* PAGE_SIZE/64 == 64 */
1:
- ldw 0(%r25),%r19
- ldw 4(%r25),%r20
- ldw 8(%r25),%r21
- ldw 12(%r25),%r22
- stw %r19,0(%r26)
- stw %r20,4(%r26)
- stw %r21,8(%r26)
- stw %r22,12(%r26)
- ldw 16(%r25),%r19
- ldw 20(%r25),%r20
- ldw 24(%r25),%r21
- ldw 28(%r25),%r22
- stw %r19,16(%r26)
- stw %r20,20(%r26)
- stw %r21,24(%r26)
- stw %r22,28(%r26)
- ldw 32(%r25),%r19
- ldw 36(%r25),%r20
- ldw 40(%r25),%r21
- ldw 44(%r25),%r22
- stw %r19,32(%r26)
- stw %r20,36(%r26)
- stw %r21,40(%r26)
- stw %r22,44(%r26)
- ldw 48(%r25),%r19
- ldw 52(%r25),%r20
- ldw 56(%r25),%r21
- ldw 60(%r25),%r22
- stw %r19,48(%r26)
- stw %r20,52(%r26)
- stw %r21,56(%r26)
- stw %r22,60(%r26)
- ldo 64(%r26),%r26
- ADDIB> -1,%r1,1b
- ldo 64(%r25),%r25
-
- bv %r0(%r2)
+ ldw 0(%r25), %r19
+ ldw 4(%r25), %r20
+ ldw 8(%r25), %r21
+ ldw 12(%r25), %r22
+ stw %r19, 0(%r26)
+ stw %r20, 4(%r26)
+ stw %r21, 8(%r26)
+ stw %r22, 12(%r26)
+ ldw 16(%r25), %r19
+ ldw 20(%r25), %r20
+ ldw 24(%r25), %r21
+ ldw 28(%r25), %r22
+ stw %r19, 16(%r26)
+ stw %r20, 20(%r26)
+ stw %r21, 24(%r26)
+ stw %r22, 28(%r26)
+ ldw 32(%r25), %r19
+ ldw 36(%r25), %r20
+ ldw 40(%r25), %r21
+ ldw 44(%r25), %r22
+ stw %r19, 32(%r26)
+ stw %r20, 36(%r26)
+ stw %r21, 40(%r26)
+ stw %r22, 44(%r26)
+ ldw 48(%r25), %r19
+ ldw 52(%r25), %r20
+ ldw 56(%r25), %r21
+ ldw 60(%r25), %r22
+ stw %r19, 48(%r26)
+ stw %r20, 52(%r26)
+ stw %r21, 56(%r26)
+ stw %r22, 60(%r26)
+ ldo 64(%r26), %r26
+ ADDIB> -1, %r1, 1b
+ ldo 64(%r25), %r25
+#endif
+ bv %r0(%r2)
nop
.exit
@@ -393,33 +451,33 @@ copy_user_page_asm:
.callinfo NO_CALLS
.entry
- ldil L%(__PAGE_OFFSET),%r1
- sub %r26,%r1,%r26
- sub %r25,%r1,%r23 /* move physical addr into non shadowed reg */
+ ldil L%(__PAGE_OFFSET), %r1
+ sub %r26, %r1, %r26
+ sub %r25, %r1, %r23 /* move physical addr into non shadowed reg */
- ldil L%(TMPALIAS_MAP_START),%r28
+ ldil L%(TMPALIAS_MAP_START), %r28
#ifdef __LP64__
- extrd,u %r26,56,32,%r26 /* convert phys addr to tlb insert format */
- extrd,u %r23,56,32,%r23 /* convert phys addr to tlb insert format */
- depd %r24,63,22,%r28 /* Form aliased virtual address 'to' */
- depdi 0,63,12,%r28 /* Clear any offset bits */
- copy %r28,%r29
- depdi 1,41,1,%r29 /* Form aliased virtual address 'from' */
+ extrd,u %r26,56,32, %r26 /* convert phys addr to tlb insert format */
+ extrd,u %r23,56,32, %r23 /* convert phys addr to tlb insert format */
+ depd %r24,63,22, %r28 /* Form aliased virtual address 'to' */
+ depdi 0, 63,12, %r28 /* Clear any offset bits */
+ copy %r28, %r29
+ depdi 1, 41,1, %r29 /* Form aliased virtual address 'from' */
#else
- extrw,u %r26,24,25,%r26 /* convert phys addr to tlb insert format */
- extrw,u %r23,24,25,%r23 /* convert phys addr to tlb insert format */
- depw %r24,31,22,%r28 /* Form aliased virtual address 'to' */
- depwi 0,31,12,%r28 /* Clear any offset bits */
- copy %r28,%r29
- depwi 1,9,1,%r29 /* Form aliased virtual address 'from' */
+ extrw,u %r26, 24,25, %r26 /* convert phys addr to tlb insert format */
+ extrw,u %r23, 24,25, %r23 /* convert phys addr to tlb insert format */
+ depw %r24, 31,22, %r28 /* Form aliased virtual address 'to' */
+ depwi 0, 31,12, %r28 /* Clear any offset bits */
+ copy %r28, %r29
+ depwi 1, 9,1, %r29 /* Form aliased virtual address 'from' */
#endif
/* Purge any old translations */
- pdtlb 0(%r28)
- pdtlb 0(%r29)
+ pdtlb 0(%r28)
+ pdtlb 0(%r29)
- ldi 64,%r1
+ ldi 64, %r1
/*
* This loop is optimized for PCXL/PCXL2 ldw/ldw and stw/stw
@@ -432,43 +490,43 @@ copy_user_page_asm:
1:
- ldw 0(%r29),%r19
- ldw 4(%r29),%r20
- ldw 8(%r29),%r21
- ldw 12(%r29),%r22
- stw %r19,0(%r28)
- stw %r20,4(%r28)
- stw %r21,8(%r28)
- stw %r22,12(%r28)
- ldw 16(%r29),%r19
- ldw 20(%r29),%r20
- ldw 24(%r29),%r21
- ldw 28(%r29),%r22
- stw %r19,16(%r28)
- stw %r20,20(%r28)
- stw %r21,24(%r28)
- stw %r22,28(%r28)
- ldw 32(%r29),%r19
- ldw 36(%r29),%r20
- ldw 40(%r29),%r21
- ldw 44(%r29),%r22
- stw %r19,32(%r28)
- stw %r20,36(%r28)
- stw %r21,40(%r28)
- stw %r22,44(%r28)
- ldw 48(%r29),%r19
- ldw 52(%r29),%r20
- ldw 56(%r29),%r21
- ldw 60(%r29),%r22
- stw %r19,48(%r28)
- stw %r20,52(%r28)
- stw %r21,56(%r28)
- stw %r22,60(%r28)
- ldo 64(%r28),%r28
- ADDIB> -1,%r1,1b
- ldo 64(%r29),%r29
-
- bv %r0(%r2)
+ ldw 0(%r29), %r19
+ ldw 4(%r29), %r20
+ ldw 8(%r29), %r21
+ ldw 12(%r29), %r22
+ stw %r19, 0(%r28)
+ stw %r20, 4(%r28)
+ stw %r21, 8(%r28)
+ stw %r22, 12(%r28)
+ ldw 16(%r29), %r19
+ ldw 20(%r29), %r20
+ ldw 24(%r29), %r21
+ ldw 28(%r29), %r22
+ stw %r19, 16(%r28)
+ stw %r20, 20(%r28)
+ stw %r21, 24(%r28)
+ stw %r22, 28(%r28)
+ ldw 32(%r29), %r19
+ ldw 36(%r29), %r20
+ ldw 40(%r29), %r21
+ ldw 44(%r29), %r22
+ stw %r19, 32(%r28)
+ stw %r20, 36(%r28)
+ stw %r21, 40(%r28)
+ stw %r22, 44(%r28)
+ ldw 48(%r29), %r19
+ ldw 52(%r29), %r20
+ ldw 56(%r29), %r21
+ ldw 60(%r29), %r22
+ stw %r19, 48(%r28)
+ stw %r20, 52(%r28)
+ stw %r21, 56(%r28)
+ stw %r22, 60(%r28)
+ ldo 64(%r28), %r28
+ ADDIB> -1, %r1,1b
+ ldo 64(%r29), %r29
+
+ bv %r0(%r2)
nop
.exit
@@ -482,49 +540,77 @@ __clear_user_page_asm:
.callinfo NO_CALLS
.entry
- tophys_r1 %r26
+ tophys_r1 %r26
- ldil L%(TMPALIAS_MAP_START),%r28
+ ldil L%(TMPALIAS_MAP_START), %r28
#ifdef __LP64__
#if (TMPALIAS_MAP_START >= 0x80000000)
- depdi 0,31,32,%r28 /* clear any sign extension */
+ depdi 0, 31,32, %r28 /* clear any sign extension */
#endif
- extrd,u %r26,56,32,%r26 /* convert phys addr to tlb insert format */
- depd %r25,63,22,%r28 /* Form aliased virtual address 'to' */
- depdi 0,63,12,%r28 /* Clear any offset bits */
+ extrd,u %r26, 56,32, %r26 /* convert phys addr to tlb insert format */
+ depd %r25, 63,22, %r28 /* Form aliased virtual address 'to' */
+ depdi 0, 63,12, %r28 /* Clear any offset bits */
#else
- extrw,u %r26,24,25,%r26 /* convert phys addr to tlb insert format */
- depw %r25,31,22,%r28 /* Form aliased virtual address 'to' */
- depwi 0,31,12,%r28 /* Clear any offset bits */
+ extrw,u %r26, 24,25, %r26 /* convert phys addr to tlb insert format */
+ depw %r25, 31,22, %r28 /* Form aliased virtual address 'to' */
+ depwi 0, 31,12, %r28 /* Clear any offset bits */
#endif
/* Purge any old translation */
- pdtlb 0(%r28)
+ pdtlb 0(%r28)
- ldi 64,%r1
+#ifdef __LP64__
+ ldi 32, %r1 /* PAGE_SIZE/128 == 32 */
+
+ /* PREFETCH (Write) has not (yet) been proven to help here */
+/* #define PREFETCHW_OP ldd 256(%0), %r0 */
+
+1: std %r0, 0(%r28)
+ std %r0, 8(%r28)
+ std %r0, 16(%r28)
+ std %r0, 24(%r28)
+ std %r0, 32(%r28)
+ std %r0, 40(%r28)
+ std %r0, 48(%r28)
+ std %r0, 56(%r28)
+ std %r0, 64(%r28)
+ std %r0, 72(%r28)
+ std %r0, 80(%r28)
+ std %r0, 88(%r28)
+ std %r0, 96(%r28)
+ std %r0, 104(%r28)
+ std %r0, 112(%r28)
+ std %r0, 120(%r28)
+ ADDIB> -1, %r1, 1b
+ ldo 128(%r28), %r28
+
+#else /* ! __LP64 */
+
+ ldi 64, %r1 /* PAGE_SIZE/64 == 64 */
1:
- stw %r0,0(%r28)
- stw %r0,4(%r28)
- stw %r0,8(%r28)
- stw %r0,12(%r28)
- stw %r0,16(%r28)
- stw %r0,20(%r28)
- stw %r0,24(%r28)
- stw %r0,28(%r28)
- stw %r0,32(%r28)
- stw %r0,36(%r28)
- stw %r0,40(%r28)
- stw %r0,44(%r28)
- stw %r0,48(%r28)
- stw %r0,52(%r28)
- stw %r0,56(%r28)
- stw %r0,60(%r28)
- ADDIB> -1,%r1,1b
- ldo 64(%r28),%r28
-
- bv %r0(%r2)
+ stw %r0, 0(%r28)
+ stw %r0, 4(%r28)
+ stw %r0, 8(%r28)
+ stw %r0, 12(%r28)
+ stw %r0, 16(%r28)
+ stw %r0, 20(%r28)
+ stw %r0, 24(%r28)
+ stw %r0, 28(%r28)
+ stw %r0, 32(%r28)
+ stw %r0, 36(%r28)
+ stw %r0, 40(%r28)
+ stw %r0, 44(%r28)
+ stw %r0, 48(%r28)
+ stw %r0, 52(%r28)
+ stw %r0, 56(%r28)
+ stw %r0, 60(%r28)
+ ADDIB> -1, %r1, 1b
+ ldo 64(%r28), %r28
+#endif /* __LP64 */
+
+ bv %r0(%r2)
nop
.exit
@@ -537,38 +623,38 @@ flush_kernel_dcache_page:
.callinfo NO_CALLS
.entry
- ldil L%dcache_stride,%r1
- ldw R%dcache_stride(%r1),%r23
+ ldil L%dcache_stride, %r1
+ ldw R%dcache_stride(%r1), %r23
#ifdef __LP64__
- depdi,z 1,63-PAGE_SHIFT,1,%r25
+ depdi,z 1, 63-PAGE_SHIFT,1, %r25
#else
- depwi,z 1,31-PAGE_SHIFT,1,%r25
+ depwi,z 1, 31-PAGE_SHIFT,1, %r25
#endif
- add %r26,%r25,%r25
- sub %r25,%r23,%r25
-
-
-1: fdc,m %r23(%r26)
- fdc,m %r23(%r26)
- fdc,m %r23(%r26)
- fdc,m %r23(%r26)
- fdc,m %r23(%r26)
- fdc,m %r23(%r26)
- fdc,m %r23(%r26)
- fdc,m %r23(%r26)
- fdc,m %r23(%r26)
- fdc,m %r23(%r26)
- fdc,m %r23(%r26)
- fdc,m %r23(%r26)
- fdc,m %r23(%r26)
- fdc,m %r23(%r26)
- fdc,m %r23(%r26)
- CMPB<< %r26,%r25,1b
- fdc,m %r23(%r26)
+ add %r26, %r25, %r25
+ sub %r25, %r23, %r25
+
+
+1: fdc,m %r23(%r26)
+ fdc,m %r23(%r26)
+ fdc,m %r23(%r26)
+ fdc,m %r23(%r26)
+ fdc,m %r23(%r26)
+ fdc,m %r23(%r26)
+ fdc,m %r23(%r26)
+ fdc,m %r23(%r26)
+ fdc,m %r23(%r26)
+ fdc,m %r23(%r26)
+ fdc,m %r23(%r26)
+ fdc,m %r23(%r26)
+ fdc,m %r23(%r26)
+ fdc,m %r23(%r26)
+ fdc,m %r23(%r26)
+ CMPB<< %r26, %r25,1b
+ fdc,m %r23(%r26)
sync
- bv %r0(%r2)
+ bv %r0(%r2)
nop
.exit
@@ -581,38 +667,38 @@ flush_user_dcache_page:
.callinfo NO_CALLS
.entry
- ldil L%dcache_stride,%r1
- ldw R%dcache_stride(%r1),%r23
+ ldil L%dcache_stride, %r1
+ ldw R%dcache_stride(%r1), %r23
#ifdef __LP64__
- depdi,z 1,63-PAGE_SHIFT,1,%r25
+ depdi,z 1,63-PAGE_SHIFT,1, %r25
#else
- depwi,z 1,31-PAGE_SHIFT,1,%r25
+ depwi,z 1,31-PAGE_SHIFT,1, %r25
#endif
- add %r26,%r25,%r25
- sub %r25,%r23,%r25
-
-
-1: fdc,m %r23(%sr3,%r26)
- fdc,m %r23(%sr3,%r26)
- fdc,m %r23(%sr3,%r26)
- fdc,m %r23(%sr3,%r26)
- fdc,m %r23(%sr3,%r26)
- fdc,m %r23(%sr3,%r26)
- fdc,m %r23(%sr3,%r26)
- fdc,m %r23(%sr3,%r26)
- fdc,m %r23(%sr3,%r26)
- fdc,m %r23(%sr3,%r26)
- fdc,m %r23(%sr3,%r26)
- fdc,m %r23(%sr3,%r26)
- fdc,m %r23(%sr3,%r26)
- fdc,m %r23(%sr3,%r26)
- fdc,m %r23(%sr3,%r26)
- CMPB<< %r26,%r25,1b
- fdc,m %r23(%sr3,%r26)
+ add %r26, %r25, %r25
+ sub %r25, %r23, %r25
+
+
+1: fdc,m %r23(%sr3, %r26)
+ fdc,m %r23(%sr3, %r26)
+ fdc,m %r23(%sr3, %r26)
+ fdc,m %r23(%sr3, %r26)
+ fdc,m %r23(%sr3, %r26)
+ fdc,m %r23(%sr3, %r26)
+ fdc,m %r23(%sr3, %r26)
+ fdc,m %r23(%sr3, %r26)
+ fdc,m %r23(%sr3, %r26)
+ fdc,m %r23(%sr3, %r26)
+ fdc,m %r23(%sr3, %r26)
+ fdc,m %r23(%sr3, %r26)
+ fdc,m %r23(%sr3, %r26)
+ fdc,m %r23(%sr3, %r26)
+ fdc,m %r23(%sr3, %r26)
+ CMPB<< %r26, %r25,1b
+ fdc,m %r23(%sr3, %r26)
sync
- bv %r0(%r2)
+ bv %r0(%r2)
nop
.exit
@@ -625,38 +711,38 @@ flush_user_icache_page:
.callinfo NO_CALLS
.entry
- ldil L%dcache_stride,%r1
- ldw R%dcache_stride(%r1),%r23
+ ldil L%dcache_stride, %r1
+ ldw R%dcache_stride(%r1), %r23
#ifdef __LP64__
- depdi,z 1,63-PAGE_SHIFT,1,%r25
+ depdi,z 1, 63-PAGE_SHIFT,1, %r25
#else
- depwi,z 1,31-PAGE_SHIFT,1,%r25
+ depwi,z 1, 31-PAGE_SHIFT,1, %r25
#endif
- add %r26,%r25,%r25
- sub %r25,%r23,%r25
-
-
-1: fic,m %r23(%sr3,%r26)
- fic,m %r23(%sr3,%r26)
- fic,m %r23(%sr3,%r26)
- fic,m %r23(%sr3,%r26)
- fic,m %r23(%sr3,%r26)
- fic,m %r23(%sr3,%r26)
- fic,m %r23(%sr3,%r26)
- fic,m %r23(%sr3,%r26)
- fic,m %r23(%sr3,%r26)
- fic,m %r23(%sr3,%r26)
- fic,m %r23(%sr3,%r26)
- fic,m %r23(%sr3,%r26)
- fic,m %r23(%sr3,%r26)
- fic,m %r23(%sr3,%r26)
- fic,m %r23(%sr3,%r26)
- CMPB<< %r26,%r25,1b
- fic,m %r23(%sr3,%r26)
+ add %r26, %r25, %r25
+ sub %r25, %r23, %r25
+
+
+1: fic,m %r23(%sr3, %r26)
+ fic,m %r23(%sr3, %r26)
+ fic,m %r23(%sr3, %r26)
+ fic,m %r23(%sr3, %r26)
+ fic,m %r23(%sr3, %r26)
+ fic,m %r23(%sr3, %r26)
+ fic,m %r23(%sr3, %r26)
+ fic,m %r23(%sr3, %r26)
+ fic,m %r23(%sr3, %r26)
+ fic,m %r23(%sr3, %r26)
+ fic,m %r23(%sr3, %r26)
+ fic,m %r23(%sr3, %r26)
+ fic,m %r23(%sr3, %r26)
+ fic,m %r23(%sr3, %r26)
+ fic,m %r23(%sr3, %r26)
+ CMPB<< %r26, %r25,1b
+ fic,m %r23(%sr3, %r26)
sync
- bv %r0(%r2)
+ bv %r0(%r2)
nop
.exit
@@ -670,37 +756,37 @@ purge_kernel_dcache_page:
.callinfo NO_CALLS
.entry
- ldil L%dcache_stride,%r1
- ldw R%dcache_stride(%r1),%r23
+ ldil L%dcache_stride, %r1
+ ldw R%dcache_stride(%r1), %r23
#ifdef __LP64__
- depdi,z 1,63-PAGE_SHIFT,1,%r25
+ depdi,z 1, 63-PAGE_SHIFT,1, %r25
#else
- depwi,z 1,31-PAGE_SHIFT,1,%r25
+ depwi,z 1, 31-PAGE_SHIFT,1, %r25
#endif
- add %r26,%r25,%r25
- sub %r25,%r23,%r25
-
-1: pdc,m %r23(%r26)
- pdc,m %r23(%r26)
- pdc,m %r23(%r26)
- pdc,m %r23(%r26)
- pdc,m %r23(%r26)
- pdc,m %r23(%r26)
- pdc,m %r23(%r26)
- pdc,m %r23(%r26)
- pdc,m %r23(%r26)
- pdc,m %r23(%r26)
- pdc,m %r23(%r26)
- pdc,m %r23(%r26)
- pdc,m %r23(%r26)
- pdc,m %r23(%r26)
- pdc,m %r23(%r26)
- CMPB<< %r26,%r25,1b
- pdc,m %r23(%r26)
+ add %r26, %r25, %r25
+ sub %r25, %r23, %r25
+
+1: pdc,m %r23(%r26)
+ pdc,m %r23(%r26)
+ pdc,m %r23(%r26)
+ pdc,m %r23(%r26)
+ pdc,m %r23(%r26)
+ pdc,m %r23(%r26)
+ pdc,m %r23(%r26)
+ pdc,m %r23(%r26)
+ pdc,m %r23(%r26)
+ pdc,m %r23(%r26)
+ pdc,m %r23(%r26)
+ pdc,m %r23(%r26)
+ pdc,m %r23(%r26)
+ pdc,m %r23(%r26)
+ pdc,m %r23(%r26)
+ CMPB<< %r26, %r25, 1b
+ pdc,m %r23(%r26)
sync
- bv %r0(%r2)
+ bv %r0(%r2)
nop
.exit
@@ -718,54 +804,54 @@ flush_alias_page:
.callinfo NO_CALLS
.entry
- tophys_r1 %r26
+ tophys_r1 %r26
- ldil L%(TMPALIAS_MAP_START),%r28
+ ldil L%(TMPALIAS_MAP_START), %r28
#ifdef __LP64__
- extrd,u %r26,56,32,%r26 /* convert phys addr to tlb insert format */
- depd %r25,63,22,%r28 /* Form aliased virtual address 'to' */
- depdi 0,63,12,%r28 /* Clear any offset bits */
+ extrd,u %r26, 56,32, %r26 /* convert phys addr to tlb insert format */
+ depd %r25, 63,22, %r28 /* Form aliased virtual address 'to' */
+ depdi 0, 63,12, %r28 /* Clear any offset bits */
#else
- extrw,u %r26,24,25,%r26 /* convert phys addr to tlb insert format */
- depw %r25,31,22,%r28 /* Form aliased virtual address 'to' */
- depwi 0,31,12,%r28 /* Clear any offset bits */
+ extrw,u %r26, 24,25, %r26 /* convert phys addr to tlb insert format */
+ depw %r25, 31,22, %r28 /* Form aliased virtual address 'to' */
+ depwi 0, 31,12, %r28 /* Clear any offset bits */
#endif
/* Purge any old translation */
- pdtlb 0(%r28)
+ pdtlb 0(%r28)
- ldil L%dcache_stride,%r1
- ldw R%dcache_stride(%r1),%r23
+ ldil L%dcache_stride, %r1
+ ldw R%dcache_stride(%r1), %r23
#ifdef __LP64__
- depdi,z 1,63-PAGE_SHIFT,1,%r29
+ depdi,z 1, 63-PAGE_SHIFT,1, %r29
#else
- depwi,z 1,31-PAGE_SHIFT,1,%r29
+ depwi,z 1, 31-PAGE_SHIFT,1, %r29
#endif
- add %r28,%r29,%r29
- sub %r29,%r23,%r29
-
-1: fdc,m %r23(%r28)
- fdc,m %r23(%r28)
- fdc,m %r23(%r28)
- fdc,m %r23(%r28)
- fdc,m %r23(%r28)
- fdc,m %r23(%r28)
- fdc,m %r23(%r28)
- fdc,m %r23(%r28)
- fdc,m %r23(%r28)
- fdc,m %r23(%r28)
- fdc,m %r23(%r28)
- fdc,m %r23(%r28)
- fdc,m %r23(%r28)
- fdc,m %r23(%r28)
- fdc,m %r23(%r28)
- CMPB<< %r28,%r29,1b
- fdc,m %r23(%r28)
+ add %r28, %r29, %r29
+ sub %r29, %r23, %r29
+
+1: fdc,m %r23(%r28)
+ fdc,m %r23(%r28)
+ fdc,m %r23(%r28)
+ fdc,m %r23(%r28)
+ fdc,m %r23(%r28)
+ fdc,m %r23(%r28)
+ fdc,m %r23(%r28)
+ fdc,m %r23(%r28)
+ fdc,m %r23(%r28)
+ fdc,m %r23(%r28)
+ fdc,m %r23(%r28)
+ fdc,m %r23(%r28)
+ fdc,m %r23(%r28)
+ fdc,m %r23(%r28)
+ fdc,m %r23(%r28)
+ CMPB<< %r28, %r29, 1b
+ fdc,m %r23(%r28)
sync
- bv %r0(%r2)
+ bv %r0(%r2)
nop
.exit
@@ -779,16 +865,16 @@ flush_user_dcache_range_asm:
.callinfo NO_CALLS
.entry
- ldil L%dcache_stride,%r1
- ldw R%dcache_stride(%r1),%r23
- ldo -1(%r23),%r21
- ANDCM %r26,%r21,%r26
+ ldil L%dcache_stride, %r1
+ ldw R%dcache_stride(%r1), %r23
+ ldo -1(%r23), %r21
+ ANDCM %r26, %r21, %r26
-1: CMPB<<,n %r26,%r25,1b
- fdc,m %r23(%sr3,%r26)
+1: CMPB<<,n %r26, %r25, 1b
+ fdc,m %r23(%sr3, %r26)
sync
- bv %r0(%r2)
+ bv %r0(%r2)
nop
.exit
@@ -801,17 +887,17 @@ flush_kernel_dcache_range_asm:
.callinfo NO_CALLS
.entry
- ldil L%dcache_stride,%r1
- ldw R%dcache_stride(%r1),%r23
- ldo -1(%r23),%r21
- ANDCM %r26,%r21,%r26
+ ldil L%dcache_stride, %r1
+ ldw R%dcache_stride(%r1), %r23
+ ldo -1(%r23), %r21
+ ANDCM %r26, %r21, %r26
-1: CMPB<<,n %r26,%r25,1b
- fdc,m %r23(%r26)
+1: CMPB<<,n %r26, %r25,1b
+ fdc,m %r23(%r26)
sync
syncdma
- bv %r0(%r2)
+ bv %r0(%r2)
nop
.exit
@@ -824,16 +910,16 @@ flush_user_icache_range_asm:
.callinfo NO_CALLS
.entry
- ldil L%icache_stride,%r1
- ldw R%icache_stride(%r1),%r23
- ldo -1(%r23),%r21
- ANDCM %r26,%r21,%r26
+ ldil L%icache_stride, %r1
+ ldw R%icache_stride(%r1), %r23
+ ldo -1(%r23), %r21
+ ANDCM %r26, %r21, %r26
-1: CMPB<<,n %r26,%r25,1b
- fic,m %r23(%sr3,%r26)
+1: CMPB<<,n %r26, %r25,1b
+ fic,m %r23(%sr3, %r26)
sync
- bv %r0(%r2)
+ bv %r0(%r2)
nop
.exit
@@ -846,38 +932,38 @@ flush_kernel_icache_page:
.callinfo NO_CALLS
.entry
- ldil L%icache_stride,%r1
- ldw R%icache_stride(%r1),%r23
+ ldil L%icache_stride, %r1
+ ldw R%icache_stride(%r1), %r23
#ifdef __LP64__
- depdi,z 1,63-PAGE_SHIFT,1,%r25
+ depdi,z 1, 63-PAGE_SHIFT,1, %r25
#else
- depwi,z 1,31-PAGE_SHIFT,1,%r25
+ depwi,z 1, 31-PAGE_SHIFT,1, %r25
#endif
- add %r26,%r25,%r25
- sub %r25,%r23,%r25
-
-
-1: fic,m %r23(%r26)
- fic,m %r23(%r26)
- fic,m %r23(%r26)
- fic,m %r23(%r26)
- fic,m %r23(%r26)
- fic,m %r23(%r26)
- fic,m %r23(%r26)
- fic,m %r23(%r26)
- fic,m %r23(%r26)
- fic,m %r23(%r26)
- fic,m %r23(%r26)
- fic,m %r23(%r26)
- fic,m %r23(%r26)
- fic,m %r23(%r26)
- fic,m %r23(%r26)
- CMPB<< %r26,%r25,1b
- fic,m %r23(%r26)
+ add %r26, %r25, %r25
+ sub %r25, %r23, %r25
+
+
+1: fic,m %r23(%r26)
+ fic,m %r23(%r26)
+ fic,m %r23(%r26)
+ fic,m %r23(%r26)
+ fic,m %r23(%r26)
+ fic,m %r23(%r26)
+ fic,m %r23(%r26)
+ fic,m %r23(%r26)
+ fic,m %r23(%r26)
+ fic,m %r23(%r26)
+ fic,m %r23(%r26)
+ fic,m %r23(%r26)
+ fic,m %r23(%r26)
+ fic,m %r23(%r26)
+ fic,m %r23(%r26)
+ CMPB<< %r26, %r25, 1b
+ fic,m %r23(%r26)
sync
- bv %r0(%r2)
+ bv %r0(%r2)
nop
.exit
@@ -890,22 +976,22 @@ flush_kernel_icache_range_asm:
.callinfo NO_CALLS
.entry
- ldil L%icache_stride,%r1
- ldw R%icache_stride(%r1),%r23
- ldo -1(%r23),%r21
- ANDCM %r26,%r21,%r26
+ ldil L%icache_stride, %r1
+ ldw R%icache_stride(%r1), %r23
+ ldo -1(%r23), %r21
+ ANDCM %r26, %r21, %r26
-1: CMPB<<,n %r26,%r25,1b
- fic,m %r23(%r26)
+1: CMPB<<,n %r26, %r25, 1b
+ fic,m %r23(%r26)
sync
- bv %r0(%r2)
+ bv %r0(%r2)
nop
.exit
.procend
- .align 128
+ .align 128
.export disable_sr_hashing_asm,code
@@ -916,7 +1002,7 @@ disable_sr_hashing_asm:
/* Switch to real mode */
- ssm 0,%r0 /* relied upon translation! */
+ ssm 0, %r0 /* relied upon translation! */
nop
nop
nop
@@ -925,73 +1011,73 @@ disable_sr_hashing_asm:
nop
nop
- rsm (PSW_SM_Q|PSW_SM_I),%r0 /* disable Q&I to load the iia queue */
- ldil L%REAL_MODE_PSW, %r1
- ldo R%REAL_MODE_PSW(%r1), %r1
- mtctl %r1, %cr22
- mtctl %r0, %cr17 /* Clear IIASQ tail */
- mtctl %r0, %cr17 /* Clear IIASQ head */
- ldil L%PA(1f),%r1
- ldo R%PA(1f)(%r1),%r1
- mtctl %r1, %cr18 /* IIAOQ head */
- ldo 4(%r1), %r1
- mtctl %r1, %cr18 /* IIAOQ tail */
+ rsm (PSW_SM_Q|PSW_SM_I), %r0 /* disable Q&I to load the iia queue */
+ ldil L%REAL_MODE_PSW, %r1
+ ldo R%REAL_MODE_PSW(%r1), %r1
+ mtctl %r1, %cr22
+ mtctl %r0, %cr17 /* Clear IIASQ tail */
+ mtctl %r0, %cr17 /* Clear IIASQ head */
+ ldil L%PA(1f), %r1
+ ldo R%PA(1f)(%r1), %r1
+ mtctl %r1, %cr18 /* IIAOQ head */
+ ldo 4(%r1), %r1
+ mtctl %r1, %cr18 /* IIAOQ tail */
rfi
nop
-1: cmpib,=,n SRHASH_PCXST,%r26,srdis_pcxs
- cmpib,=,n SRHASH_PCXL,%r26,srdis_pcxl
- cmpib,=,n SRHASH_PA20,%r26,srdis_pa20
- b,n srdis_done
+1: cmpib,=,n SRHASH_PCXST, %r26,srdis_pcxs
+ cmpib,=,n SRHASH_PCXL, %r26,srdis_pcxl
+ cmpib,=,n SRHASH_PA20, %r26,srdis_pa20
+ b,n srdis_done
srdis_pcxs:
/* Disable Space Register Hashing for PCXS,PCXT,PCXT' */
- .word 0x141c1a00 /* mfdiag %dr0,%r28 */
- .word 0x141c1a00 /* must issue twice */
- depwi 0,18,1,%r28 /* Clear DHE (dcache hash enable) */
- depwi 0,20,1,%r28 /* Clear IHE (icache hash enable) */
- .word 0x141c1600 /* mtdiag %r28,%dr0 */
- .word 0x141c1600 /* must issue twice */
- b,n srdis_done
+ .word 0x141c1a00 /* mfdiag %dr0, %r28 */
+ .word 0x141c1a00 /* must issue twice */
+ depwi 0,18,1, %r28 /* Clear DHE (dcache hash enable) */
+ depwi 0,20,1, %r28 /* Clear IHE (icache hash enable) */
+ .word 0x141c1600 /* mtdiag %r28, %dr0 */
+ .word 0x141c1600 /* must issue twice */
+ b,n srdis_done
srdis_pcxl:
/* Disable Space Register Hashing for PCXL */
- .word 0x141c0600 /* mfdiag %dr0,%r28 */
- depwi 0,28,2,%r28 /* Clear DHASH_EN & IHASH_EN */
- .word 0x141c0240 /* mtdiag %r28,%dr0 */
- b,n srdis_done
+ .word 0x141c0600 /* mfdiag %dr0, %r28 */
+ depwi 0,28,2, %r28 /* Clear DHASH_EN & IHASH_EN */
+ .word 0x141c0240 /* mtdiag %r28, %dr0 */
+ b,n srdis_done
srdis_pa20:
/* Disable Space Register Hashing for PCXU,PCXU+,PCXW,PCXW+ */
- .word 0x144008bc /* mfdiag %dr2,%r28 */
- depdi 0,54,1,%r28 /* clear DIAG_SPHASH_ENAB (bit 54) */
- .word 0x145c1840 /* mtdiag %r28,%dr2 */
+ .word 0x144008bc /* mfdiag %dr2, %r28 */
+ depdi 0, 54,1, %r28 /* clear DIAG_SPHASH_ENAB (bit 54) */
+ .word 0x145c1840 /* mtdiag %r28, %dr2 */
srdis_done:
/* Switch back to virtual mode */
- rsm PSW_SM_Q,%r0 /* clear Q bit to load iia queue */
- ldil L%KERNEL_PSW, %r1
- ldo R%KERNEL_PSW(%r1), %r1
- mtctl %r1, %cr22
- mtctl %r0, %cr17 /* Clear IIASQ tail */
- mtctl %r0, %cr17 /* Clear IIASQ head */
- ldil L%(2f), %r1
- ldo R%(2f)(%r1), %r1
- mtctl %r1, %cr18 /* IIAOQ head */
- ldo 4(%r1), %r1
- mtctl %r1, %cr18 /* IIAOQ tail */
+ rsm PSW_SM_Q, %r0 /* clear Q bit to load iia queue */
+ ldil L%KERNEL_PSW, %r1
+ ldo R%KERNEL_PSW(%r1), %r1
+ mtctl %r1, %cr22
+ mtctl %r0, %cr17 /* Clear IIASQ tail */
+ mtctl %r0, %cr17 /* Clear IIASQ head */
+ ldil L%(2f), %r1
+ ldo R%(2f)(%r1), %r1
+ mtctl %r1, %cr18 /* IIAOQ head */
+ ldo 4(%r1), %r1
+ mtctl %r1, %cr18 /* IIAOQ tail */
rfi
nop
-2: bv %r0(%r2)
+2: bv %r0(%r2)
nop
.exit
diff --git a/arch/parisc/kernel/pci-dma.c b/arch/parisc/kernel/pci-dma.c
index 07850b6e19228..368cc095c99fd 100644
--- a/arch/parisc/kernel/pci-dma.c
+++ b/arch/parisc/kernel/pci-dma.c
@@ -32,18 +32,6 @@
#include <asm/pgalloc.h>
#include <asm/uaccess.h>
-#ifdef DEBUG_PCI
-#undef ASSERT
-#define ASSERT(expr) \
- if(!(expr)) { \
- printk("\n%s:%d: Assertion " #expr " failed!\n", \
- __FILE__, __LINE__); \
- panic(#expr); \
- }
-#else
-#define ASSERT(expr)
-#endif
-
static struct proc_dir_entry * proc_gsc_root = NULL;
static int pcxl_proc_info(char *buffer, char **start, off_t offset, int length);
@@ -180,7 +168,7 @@ static inline void unmap_uncached_pte(pmd_t * pmd, unsigned long vaddr,
end = PMD_SIZE;
do {
pte_t page = *pte;
- pte_clear(pte);
+ pte_clear(&init_mm, vaddr, pte);
purge_tlb_start();
pdtlb_kernel(orig_vaddr);
purge_tlb_end();
@@ -259,10 +247,6 @@ pcxl_alloc_range(size_t size)
u_long mask, flags;
unsigned int pages_needed = size >> PAGE_SHIFT;
- ASSERT(pages_needed);
- ASSERT((pages_needed * PAGE_SIZE) < DMA_CHUNK_SIZE);
- ASSERT(pages_needed < (BITS_PER_LONG - PAGE_SHIFT));
-
mask = (u_long) -1L;
mask >>= BITS_PER_LONG - pages_needed;
@@ -306,7 +290,7 @@ resource_found:
#define PCXL_FREE_MAPPINGS(idx, m, size) \
u##size *res_ptr = (u##size *)&(pcxl_res_map[(idx) + (((size >> 3) - 1) & (~((size >> 3) - 1)))]); \
- ASSERT((*res_ptr & m) == m); \
+ /* BUG_ON((*res_ptr & m) != m); */ \
*res_ptr &= ~m;
/*
@@ -319,10 +303,6 @@ pcxl_free_range(unsigned long vaddr, size_t size)
unsigned int res_idx = (vaddr - pcxl_dma_start) >> (PAGE_SHIFT + 3);
unsigned int pages_mapped = size >> PAGE_SHIFT;
- ASSERT(pages_mapped);
- ASSERT((pages_mapped * PAGE_SIZE) < DMA_CHUNK_SIZE);
- ASSERT(pages_mapped < (BITS_PER_LONG - PAGE_SHIFT));
-
mask = (u_long) -1L;
mask >>= BITS_PER_LONG - pages_mapped;
diff --git a/arch/parisc/kernel/pdc_chassis.c b/arch/parisc/kernel/pdc_chassis.c
index 7268abfcd43df..52004ae28d20c 100644
--- a/arch/parisc/kernel/pdc_chassis.c
+++ b/arch/parisc/kernel/pdc_chassis.c
@@ -2,7 +2,7 @@
* interfaces to log Chassis Codes via PDC (firmware)
*
* Copyright (C) 2002 Laurent Canet <canetl@esiee.fr>
- * Copyright (C) 2002-2004 Thibaut VARENE <varenet@esiee.fr>
+ * Copyright (C) 2002-2004 Thibaut VARENE <varenet@parisc-linux.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -182,7 +182,7 @@ int pdc_chassis_send_status(int message)
DPRINTK(KERN_DEBUG "%s: pdc_chassis_send_status(%d)\n", __FILE__, message);
-#ifdef CONFIG_PARISC64
+#ifdef CONFIG_64BIT
if (is_pdc_pat()) {
switch(message) {
case PDC_CHASSIS_DIRECT_BSTART:
@@ -238,7 +238,7 @@ int pdc_chassis_send_status(int message)
retval = -1;
}
} else retval = -1;
-#endif /* CONFIG_PARISC64 */
+#endif /* CONFIG_64BIT */
} /* if (pdc_chassis_enabled) */
#endif /* CONFIG_PDC_CHASSIS */
return retval;
diff --git a/arch/parisc/kernel/perf.c b/arch/parisc/kernel/perf.c
index f8bacd79a631e..b3ad0a505b876 100644
--- a/arch/parisc/kernel/perf.c
+++ b/arch/parisc/kernel/perf.c
@@ -42,7 +42,6 @@
* on every box.
*/
-#include <linux/config.h>
#include <linux/init.h>
#include <linux/proc_fs.h>
#include <linux/miscdevice.h>
@@ -157,16 +156,16 @@ static struct rdr_tbl_ent perf_rdr_tbl_U[] = {
* this array.
*/
static uint64_t perf_bitmasks[] = {
- 0x0000000000000000, /* first dbl word must be zero */
- 0xfdffe00000000000, /* RDR0 bitmask */
- 0x003f000000000000, /* RDR1 bitmask */
- 0x00ffffffffffffff, /* RDR20-RDR21 bitmask (152 bits) */
- 0xffffffffffffffff,
- 0xfffffffc00000000,
- 0xffffffffffffffff, /* RDR22-RDR23 bitmask (233 bits) */
- 0xffffffffffffffff,
- 0xfffffffffffffffc,
- 0xff00000000000000
+ 0x0000000000000000ul, /* first dbl word must be zero */
+ 0xfdffe00000000000ul, /* RDR0 bitmask */
+ 0x003f000000000000ul, /* RDR1 bitmask */
+ 0x00fffffffffffffful, /* RDR20-RDR21 bitmask (152 bits) */
+ 0xfffffffffffffffful,
+ 0xfffffffc00000000ul,
+ 0xfffffffffffffffful, /* RDR22-RDR23 bitmask (233 bits) */
+ 0xfffffffffffffffful,
+ 0xfffffffffffffffcul,
+ 0xff00000000000000ul
};
/*
@@ -174,16 +173,16 @@ static uint64_t perf_bitmasks[] = {
* somethings have changed slightly.
*/
static uint64_t perf_bitmasks_piranha[] = {
- 0x0000000000000000, /* first dbl word must be zero */
- 0xfdffe00000000000, /* RDR0 bitmask */
- 0x003f000000000000, /* RDR1 bitmask */
- 0x00ffffffffffffff, /* RDR20-RDR21 bitmask (158 bits) */
- 0xffffffffffffffff,
- 0xfffffffc00000000,
- 0xffffffffffffffff, /* RDR22-RDR23 bitmask (210 bits) */
- 0xffffffffffffffff,
- 0xffffffffffffffff,
- 0xfffc000000000000
+ 0x0000000000000000ul, /* first dbl word must be zero */
+ 0xfdffe00000000000ul, /* RDR0 bitmask */
+ 0x003f000000000000ul, /* RDR1 bitmask */
+ 0x00fffffffffffffful, /* RDR20-RDR21 bitmask (158 bits) */
+ 0xfffffffffffffffful,
+ 0xfffffffc00000000ul,
+ 0xfffffffffffffffful, /* RDR22-RDR23 bitmask (210 bits) */
+ 0xfffffffffffffffful,
+ 0xfffffffffffffffful,
+ 0xfffc000000000000ul
};
static uint64_t *bitmask_array; /* array of bitmasks to use */
@@ -194,8 +193,8 @@ static uint64_t *bitmask_array; /* array of bitmasks to use */
static int perf_config(uint32_t *image_ptr);
static int perf_release(struct inode *inode, struct file *file);
static int perf_open(struct inode *inode, struct file *file);
-static ssize_t perf_read(struct file *file, char *buf, size_t cnt, loff_t *ppos);
-static ssize_t perf_write(struct file *file, const char *buf, size_t count,
+static ssize_t perf_read(struct file *file, char __user *buf, size_t cnt, loff_t *ppos);
+static ssize_t perf_write(struct file *file, const char __user *buf, size_t count,
loff_t *ppos);
static int perf_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
unsigned long arg);
@@ -287,7 +286,7 @@ static int perf_release(struct inode *inode, struct file *file)
/*
* Read does nothing for this driver
*/
-static ssize_t perf_read(struct file *file, char *buf, size_t cnt, loff_t *ppos)
+static ssize_t perf_read(struct file *file, char __user *buf, size_t cnt, loff_t *ppos)
{
return 0;
}
@@ -299,7 +298,7 @@ static ssize_t perf_read(struct file *file, char *buf, size_t cnt, loff_t *ppos)
* called on the processor that the download should happen
* on.
*/
-static ssize_t perf_write(struct file *file, const char *buf, size_t count,
+static ssize_t perf_write(struct file *file, const char __user *buf, size_t count,
loff_t *ppos)
{
int err;
@@ -460,7 +459,7 @@ static int perf_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
}
/* copy out the Counters */
- if (copy_to_user((void *)arg, raddr,
+ if (copy_to_user((void __user *)arg, raddr,
sizeof (raddr)) != 0) {
return -EFAULT;
}
@@ -607,7 +606,7 @@ static int perf_stop_counters(uint32_t *raddr)
* all of dword 22 and 58 bits (plus 6 don't care bits) of
* dword 23.
*/
- userbuf[21] &= 0xfffffffffffffc00; /* 0 to last 10 bits */
+ userbuf[21] &= 0xfffffffffffffc00ul; /* 0 to last 10 bits */
userbuf[22] = 0;
userbuf[23] = 0;
@@ -802,8 +801,8 @@ static int perf_write_image(uint64_t *memaddr)
proc_hpa = cpu_device->hpa;
/* Merge intrigue bits into Runway STATUS 0 */
- tmp64 = __raw_readq(proc_hpa + RUNWAY_STATUS) & 0xffecffffffffffff;
- __raw_writeq(tmp64 | (*memaddr++ & 0x0013000000000000), proc_hpa + RUNWAY_STATUS);
+ tmp64 = __raw_readq(proc_hpa + RUNWAY_STATUS) & 0xffecfffffffffffful;
+ __raw_writeq(tmp64 | (*memaddr++ & 0x0013000000000000ul), proc_hpa + RUNWAY_STATUS);
/* Write RUNWAY DEBUG registers */
for (i = 0; i < 8; i++) {
diff --git a/arch/parisc/kernel/perf_asm.S b/arch/parisc/kernel/perf_asm.S
index 87993ae27cb16..adb3c64449102 100644
--- a/arch/parisc/kernel/perf_asm.S
+++ b/arch/parisc/kernel/perf_asm.S
@@ -22,9 +22,9 @@
#include <linux/config.h>
#include <asm/assembly.h>
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
.level 2.0w
-#endif /* __LP64__ */
+#endif /* CONFIG_64BIT */
#define MTDIAG_1(gr) .word 0x14201840 + gr*0x10000
#define MTDIAG_2(gr) .word 0x14401840 + gr*0x10000
diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c
index 320fca55fa1a4..46e4a6881f11c 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>
-int hlt_counter;
+static int hlt_counter;
/*
* Power off function, if any
@@ -251,7 +251,7 @@ int
sys_clone(unsigned long clone_flags, unsigned long usp,
struct pt_regs *regs)
{
- int *user_tid = (int *)regs->gr[26];
+ int __user *user_tid = (int __user *)regs->gr[26];
/* usp must be word aligned. This also prevents users from
* passing in the value 1 (which is the signal for a special
@@ -357,12 +357,12 @@ asmlinkage int sys_execve(struct pt_regs *regs)
int error;
char *filename;
- filename = getname((char *) regs->gr[26]);
+ filename = getname((const char __user *) regs->gr[26]);
error = PTR_ERR(filename);
if (IS_ERR(filename))
goto out;
- error = do_execve(filename, (char **) regs->gr[25],
- (char **) regs->gr[24], regs);
+ error = do_execve(filename, (char __user **) regs->gr[25],
+ (char __user **) regs->gr[24], regs);
if (error == 0) {
task_lock(current);
current->ptrace &= ~PT_DTRACE;
diff --git a/arch/parisc/kernel/real2.S b/arch/parisc/kernel/real2.S
index 8b8ee543ae106..8dd5defb73161 100644
--- a/arch/parisc/kernel/real2.S
+++ b/arch/parisc/kernel/real2.S
@@ -81,8 +81,7 @@ real32_call_asm:
rsm PSW_SM_W, %r0 /* go narrow */
#endif
- ldil L%PA(ric_ret), %r2
- ldo R%PA(ric_ret)(%r2), %r2
+ load32 PA(ric_ret), %r2
bv 0(%r31)
nop
ric_ret:
diff --git a/arch/parisc/kernel/setup.c b/arch/parisc/kernel/setup.c
index f3267597085bf..73e9c34b09483 100644
--- a/arch/parisc/kernel/setup.c
+++ b/arch/parisc/kernel/setup.c
@@ -53,6 +53,15 @@ struct proc_dir_entry * proc_runway_root = NULL;
struct proc_dir_entry * proc_gsc_root = NULL;
struct proc_dir_entry * proc_mckinley_root = NULL;
+#if !defined(CONFIG_PA20) && (defined(CONFIG_IOMMU_CCIO) || defined(CONFIG_IOMMU_SBA))
+int parisc_bus_is_phys = 1; /* Assume no IOMMU is present */
+EXPORT_SYMBOL(parisc_bus_is_phys);
+#endif
+
+/* This sets the vmerge boundary and size, it's here because it has to
+ * be available on all platforms (zero means no-virtual merging) */
+unsigned long parisc_vmerge_boundary = 0;
+unsigned long parisc_vmerge_max_size = 0;
void __init setup_cmdline(char **cmdline_p)
{
@@ -112,6 +121,10 @@ extern void collect_boot_cpu_data(void);
void __init setup_arch(char **cmdline_p)
{
+#ifdef __LP64__
+ extern int parisc_narrow_firmware;
+#endif
+
init_per_cpu(smp_processor_id()); /* Set Modes & Enable FP */
#ifdef __LP64__
@@ -123,7 +136,6 @@ void __init setup_arch(char **cmdline_p)
pdc_console_init();
#ifdef __LP64__
- extern int parisc_narrow_firmware;
if(parisc_narrow_firmware) {
printk(KERN_INFO "Kernel is using PDC in 32-bit mode.\n");
}
@@ -199,7 +211,7 @@ static void __init parisc_proc_mkdir(void)
case pcxl2:
if (NULL == proc_gsc_root)
{
- proc_gsc_root = proc_mkdir("bus/gsc", 0);
+ proc_gsc_root = proc_mkdir("bus/gsc", NULL);
}
break;
case pcxt_:
@@ -210,13 +222,13 @@ static void __init parisc_proc_mkdir(void)
case pcxw2:
if (NULL == proc_runway_root)
{
- proc_runway_root = proc_mkdir("bus/runway", 0);
+ proc_runway_root = proc_mkdir("bus/runway", NULL);
}
break;
case mako:
if (NULL == proc_mckinley_root)
{
- proc_mckinley_root = proc_mkdir("bus/mckinley", 0);
+ proc_mckinley_root = proc_mkdir("bus/mckinley", NULL);
}
break;
default:
diff --git a/arch/parisc/kernel/signal.c b/arch/parisc/kernel/signal.c
index 4a0a8adbc79d7..9421bb98ea639 100644
--- a/arch/parisc/kernel/signal.c
+++ b/arch/parisc/kernel/signal.c
@@ -32,6 +32,7 @@
#include <asm/uaccess.h>
#include <asm/pgalloc.h>
#include <asm/cacheflush.h>
+#include <asm/offsets.h>
#ifdef CONFIG_COMPAT
#include <linux/compat.h>
@@ -69,7 +70,7 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall);
#endif
asmlinkage int
-sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize, struct pt_regs *regs)
+sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, struct pt_regs *regs)
{
sigset_t saveset, newset;
#ifdef __LP64__
@@ -79,7 +80,7 @@ sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize, struct pt_regs *regs)
/* XXX: Don't preclude handling different sized sigset_t's. */
if (sigsetsize != sizeof(compat_sigset_t))
return -EINVAL;
- if (copy_from_user(&newset32, (compat_sigset_t *)unewset, sizeof(newset32)))
+ if (copy_from_user(&newset32, (compat_sigset_t __user *)unewset, sizeof(newset32)))
return -EFAULT;
sigset_32to64(&newset,&newset32);
@@ -125,7 +126,7 @@ sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize, struct pt_regs *regs)
#define INSN_DIE_HORRIBLY 0x68000ccc /* stw %r0,0x666(%sr0,%r0) */
static long
-restore_sigcontext(struct sigcontext *sc, struct pt_regs *regs)
+restore_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs)
{
long err = 0;
@@ -143,14 +144,14 @@ restore_sigcontext(struct sigcontext *sc, struct pt_regs *regs)
void
sys_rt_sigreturn(struct pt_regs *regs, int in_syscall)
{
- struct rt_sigframe *frame;
+ struct rt_sigframe __user *frame;
struct siginfo si;
sigset_t set;
unsigned long usp = (regs->gr[30] & ~(0x01UL));
unsigned long sigframe_size = PARISC_RT_SIGFRAME_SIZE;
#ifdef __LP64__
compat_sigset_t compat_set;
- struct compat_rt_sigframe * compat_frame;
+ struct compat_rt_sigframe __user * compat_frame;
if(personality(current->personality) == PER_LINUX32)
sigframe_size = PARISC_RT_SIGFRAME_SIZE32;
@@ -158,12 +159,12 @@ sys_rt_sigreturn(struct pt_regs *regs, int in_syscall)
/* Unwind the user stack to get the rt_sigframe structure. */
- frame = (struct rt_sigframe *)
+ frame = (struct rt_sigframe __user *)
(usp - sigframe_size);
DBG(2,"sys_rt_sigreturn: frame is %p\n", frame);
#ifdef __LP64__
- compat_frame = (struct compat_rt_sigframe *)frame;
+ compat_frame = (struct compat_rt_sigframe __user *)frame;
if(personality(current->personality) == PER_LINUX32){
DBG(2,"sys_rt_sigreturn: ELF32 process.\n");
@@ -238,7 +239,7 @@ give_sigsegv:
* Set up a signal frame.
*/
-static inline void *
+static inline void __user *
get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
{
/*FIXME: ELF32 vs. ELF64 has different frame_size, but since we
@@ -251,11 +252,11 @@ get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
sp = current->sas_ss_sp; /* Stacks grow up! */
DBG(1,"get_sigframe: Returning sp = %#lx\n", (unsigned long)sp);
- return (void *) sp; /* Stacks grow up. Fun. */
+ return (void __user *) sp; /* Stacks grow up. Fun. */
}
static long
-setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs, int in_syscall)
+setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, int in_syscall)
{
unsigned long flags = 0;
@@ -292,14 +293,14 @@ static long
setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
sigset_t *set, struct pt_regs *regs, int in_syscall)
{
- struct rt_sigframe *frame;
+ struct rt_sigframe __user *frame;
unsigned long rp, usp;
unsigned long haddr, sigframe_size;
struct siginfo si;
int err = 0;
#ifdef __LP64__
compat_int_t compat_val;
- struct compat_rt_sigframe * compat_frame;
+ struct compat_rt_sigframe __user * compat_frame;
compat_sigset_t compat_set;
#endif
@@ -313,7 +314,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
#ifdef __LP64__
- compat_frame = (struct compat_rt_sigframe *)frame;
+ compat_frame = (struct compat_rt_sigframe __user *)frame;
if(personality(current->personality) == PER_LINUX32) {
DBG(1,"setup_rt_frame: frame->info = 0x%p\n", &compat_frame->info);
@@ -396,7 +397,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
#endif
if (haddr & PA_PLABEL_FDESC) {
Elf32_Fdesc fdesc;
- Elf32_Fdesc *ufdesc = (Elf32_Fdesc *)A(haddr & ~3);
+ Elf32_Fdesc __user *ufdesc = (Elf32_Fdesc __user *)A(haddr & ~3);
err = __copy_from_user(&fdesc, ufdesc, sizeof(fdesc));
@@ -409,7 +410,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
#ifdef __LP64__
} else {
Elf64_Fdesc fdesc;
- Elf64_Fdesc *ufdesc = (Elf64_Fdesc *)A(haddr & ~3);
+ Elf64_Fdesc __user *ufdesc = (Elf64_Fdesc __user *)A(haddr & ~3);
err = __copy_from_user(&fdesc, ufdesc, sizeof(fdesc));
@@ -443,6 +444,18 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
psw |= PSW_W;
#endif
+ /* If we are singlestepping, arrange a trap to be delivered
+ when we return to userspace. Note the semantics -- we
+ should trap before the first insn in the handler is
+ executed. Ref:
+ http://sources.redhat.com/ml/gdb/2004-11/msg00245.html
+ */
+ if (pa_psw(current)->r) {
+ pa_psw(current)->r = 0;
+ psw |= PSW_R;
+ mtctl(-1, 0);
+ }
+
regs->gr[0] = psw;
regs->iaoq[0] = haddr | 3;
regs->iaoq[1] = regs->iaoq[0] + 4;
diff --git a/arch/parisc/kernel/signal32.c b/arch/parisc/kernel/signal32.c
index 1c1668b6f02f3..0792e20efef38 100644
--- a/arch/parisc/kernel/signal32.c
+++ b/arch/parisc/kernel/signal32.c
@@ -20,7 +20,6 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include <linux/config.h>
#include <linux/compat.h>
#include <linux/slab.h>
#include <linux/module.h>
@@ -65,7 +64,7 @@ sigset_64to32(compat_sigset_t *s32, sigset_t *s64)
}
static int
-put_sigset32(compat_sigset_t *up, sigset_t *set, size_t sz)
+put_sigset32(compat_sigset_t __user *up, sigset_t *set, size_t sz)
{
compat_sigset_t s;
@@ -76,7 +75,7 @@ put_sigset32(compat_sigset_t *up, sigset_t *set, size_t sz)
}
static int
-get_sigset32(compat_sigset_t *up, sigset_t *set, size_t sz)
+get_sigset32(compat_sigset_t __user *up, sigset_t *set, size_t sz)
{
compat_sigset_t s;
int r;
@@ -90,7 +89,7 @@ get_sigset32(compat_sigset_t *up, sigset_t *set, size_t sz)
return r;
}
-int sys32_rt_sigprocmask(int how, compat_sigset_t *set, compat_sigset_t *oset,
+int sys32_rt_sigprocmask(int how, compat_sigset_t __user *set, compat_sigset_t __user *oset,
unsigned int sigsetsize)
{
sigset_t old_set, new_set;
@@ -99,8 +98,8 @@ int sys32_rt_sigprocmask(int how, compat_sigset_t *set, compat_sigset_t *oset,
if (set && get_sigset32(set, &new_set, sigsetsize))
return -EFAULT;
- KERNEL_SYSCALL(ret, sys_rt_sigprocmask, how, set ? &new_set : NULL,
- oset ? &old_set : NULL, sigsetsize);
+ KERNEL_SYSCALL(ret, sys_rt_sigprocmask, how, set ? (sigset_t __user *)&new_set : NULL,
+ oset ? (sigset_t __user *)&old_set : NULL, sigsetsize);
if (!ret && oset && put_sigset32(oset, &old_set, sigsetsize))
return -EFAULT;
@@ -109,12 +108,12 @@ int sys32_rt_sigprocmask(int how, compat_sigset_t *set, compat_sigset_t *oset,
}
-int sys32_rt_sigpending(compat_sigset_t *uset, unsigned int sigsetsize)
+int sys32_rt_sigpending(compat_sigset_t __user *uset, unsigned int sigsetsize)
{
int ret;
sigset_t set;
- KERNEL_SYSCALL(ret, sys_rt_sigpending, &set, sigsetsize);
+ KERNEL_SYSCALL(ret, sys_rt_sigpending, (sigset_t __user *)&set, sigsetsize);
if (!ret && put_sigset32(uset, &set, sigsetsize))
return -EFAULT;
@@ -123,7 +122,7 @@ int sys32_rt_sigpending(compat_sigset_t *uset, unsigned int sigsetsize)
}
long
-sys32_rt_sigaction(int sig, const struct sigaction32 *act, struct sigaction32 *oact,
+sys32_rt_sigaction(int sig, const struct sigaction32 __user *act, struct sigaction32 __user *oact,
size_t sigsetsize)
{
struct k_sigaction32 new_sa32, old_sa32;
@@ -151,7 +150,7 @@ sys32_rt_sigaction(int sig, const struct sigaction32 *act, struct sigaction32 *o
}
int
-do_sigaltstack32 (const compat_stack_t *uss32, compat_stack_t *uoss32, unsigned long sp)
+do_sigaltstack32 (const compat_stack_t __user *uss32, compat_stack_t __user *uoss32, unsigned long sp)
{
compat_stack_t ss32, oss32;
stack_t ss, oss;
@@ -162,7 +161,7 @@ do_sigaltstack32 (const compat_stack_t *uss32, compat_stack_t *uoss32, unsigned
if (copy_from_user(&ss32, uss32, sizeof ss32))
return -EFAULT;
- ss.ss_sp = (void *)(unsigned long)ss32.ss_sp;
+ ss.ss_sp = (void __user *)(unsigned long)ss32.ss_sp;
ss.ss_flags = ss32.ss_flags;
ss.ss_size = ss32.ss_size;
@@ -172,7 +171,7 @@ do_sigaltstack32 (const compat_stack_t *uss32, compat_stack_t *uoss32, unsigned
if (uoss32)
ossp = &oss;
- KERNEL_SYSCALL(ret, do_sigaltstack, ssp, ossp, sp);
+ KERNEL_SYSCALL(ret, do_sigaltstack, (const stack_t __user *)ssp, (stack_t __user *)ossp, sp);
if (!ret && uoss32) {
oss32.ss_sp = (unsigned int)(unsigned long)oss.ss_sp;
@@ -186,7 +185,7 @@ do_sigaltstack32 (const compat_stack_t *uss32, compat_stack_t *uoss32, unsigned
}
long
-restore_sigcontext32(struct compat_sigcontext *sc, struct compat_regfile * rf,
+restore_sigcontext32(struct compat_sigcontext __user *sc, struct compat_regfile __user * rf,
struct pt_regs *regs)
{
long err = 0;
@@ -265,7 +264,7 @@ restore_sigcontext32(struct compat_sigcontext *sc, struct compat_regfile * rf,
* truncate for a 32-bit userspace.
*/
long
-setup_sigcontext32(struct compat_sigcontext *sc, struct compat_regfile * rf,
+setup_sigcontext32(struct compat_sigcontext __user *sc, struct compat_regfile __user * rf,
struct pt_regs *regs, int in_syscall)
{
compat_int_t flags = 0;
diff --git a/arch/parisc/kernel/signal32.h b/arch/parisc/kernel/signal32.h
index 9c29b63d9e4a6..4d1569e717cc9 100644
--- a/arch/parisc/kernel/signal32.h
+++ b/arch/parisc/kernel/signal32.h
@@ -31,13 +31,13 @@ struct k_sigaction32 {
void sigset_32to64(sigset_t *s64, compat_sigset_t *s32);
void sigset_64to32(compat_sigset_t *s32, sigset_t *s64);
-int do_sigaltstack32 (const compat_stack_t *uss32,
- compat_stack_t *uoss32, unsigned long sp);
-long restore_sigcontext32(struct compat_sigcontext *sc,
- struct compat_regfile *rf,
+int do_sigaltstack32 (const compat_stack_t __user *uss32,
+ compat_stack_t __user *uoss32, unsigned long sp);
+long restore_sigcontext32(struct compat_sigcontext __user *sc,
+ struct compat_regfile __user *rf,
struct pt_regs *regs);
-long setup_sigcontext32(struct compat_sigcontext *sc,
- struct compat_regfile *rf,
+long setup_sigcontext32(struct compat_sigcontext __user *sc,
+ struct compat_regfile __user *rf,
struct pt_regs *regs, int in_syscall);
#endif
diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c
index 75894bcd310aa..bcc7e83f5142e 100644
--- a/arch/parisc/kernel/smp.c
+++ b/arch/parisc/kernel/smp.c
@@ -60,8 +60,6 @@ volatile struct task_struct *smp_init_current_idle_task;
static volatile int cpu_now_booting = 0; /* track which CPU is booting */
-unsigned long cache_decay_ticks; /* declared by include/linux/sched.h */
-
static int parisc_max_cpus = 1;
/* online cpus are ones that we've managed to bring up completely
@@ -583,8 +581,6 @@ void __devinit smp_prepare_boot_cpu(void)
cpu_set(bootstrap_processor, cpu_online_map);
cpu_set(bootstrap_processor, cpu_present_map);
-
- cache_decay_ticks = HZ/100; /* FIXME very rough. */
}
diff --git a/arch/parisc/kernel/sys_parisc.c b/arch/parisc/kernel/sys_parisc.c
index 96ad250edfa55..7958cd8c8bf80 100644
--- a/arch/parisc/kernel/sys_parisc.c
+++ b/arch/parisc/kernel/sys_parisc.c
@@ -32,7 +32,7 @@
#include <linux/smp_lock.h>
#include <linux/syscalls.h>
-int sys_pipe(int *fildes)
+int sys_pipe(int __user *fildes)
{
int fd[2];
int error;
@@ -161,7 +161,7 @@ asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len,
}
}
-long sys_shmat_wrapper(int shmid, char *shmaddr, int shmflag)
+long sys_shmat_wrapper(int shmid, char __user *shmaddr, int shmflag)
{
unsigned long raddr;
int r;
@@ -174,8 +174,8 @@ long sys_shmat_wrapper(int shmid, char *shmaddr, int shmflag)
/* Fucking broken ABI */
-#ifdef CONFIG_PARISC64
-asmlinkage long parisc_truncate64(const char * path,
+#ifdef CONFIG_64BIT
+asmlinkage long parisc_truncate64(const char __user * path,
unsigned int high, unsigned int low)
{
return sys_truncate(path, (long)high << 32 | low);
@@ -189,7 +189,7 @@ asmlinkage long parisc_ftruncate64(unsigned int fd,
/* stubs for the benefit of the syscall_table since truncate64 and truncate
* are identical on LP64 */
-asmlinkage long sys_truncate64(const char * path, unsigned long length)
+asmlinkage long sys_truncate64(const char __user * path, unsigned long length)
{
return sys_truncate(path, length);
}
@@ -203,7 +203,7 @@ asmlinkage long sys_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg
}
#else
-asmlinkage long parisc_truncate64(const char * path,
+asmlinkage long parisc_truncate64(const char __user * path,
unsigned int high, unsigned int low)
{
return sys_truncate64(path, (loff_t)high << 32 | low);
@@ -216,13 +216,13 @@ asmlinkage long parisc_ftruncate64(unsigned int fd,
}
#endif
-asmlinkage ssize_t parisc_pread64(unsigned int fd, char *buf, size_t count,
+asmlinkage ssize_t parisc_pread64(unsigned int fd, char __user *buf, size_t count,
unsigned int high, unsigned int low)
{
return sys_pread64(fd, buf, count, (loff_t)high << 32 | low);
}
-asmlinkage ssize_t parisc_pwrite64(unsigned int fd, const char *buf,
+asmlinkage ssize_t parisc_pwrite64(unsigned int fd, const char __user *buf,
size_t count, unsigned int high, unsigned int low)
{
return sys_pwrite64(fd, buf, count, (loff_t)high << 32 | low);
diff --git a/arch/parisc/kernel/sys_parisc32.c b/arch/parisc/kernel/sys_parisc32.c
index e4e6bfcaa7112..6135690184109 100644
--- a/arch/parisc/kernel/sys_parisc32.c
+++ b/arch/parisc/kernel/sys_parisc32.c
@@ -74,7 +74,7 @@ asmlinkage int sys32_execve(struct pt_regs *regs)
char *filename;
DBG(("sys32_execve(%p) r26 = 0x%lx\n", regs, regs->gr[26]));
- filename = getname((char *) regs->gr[26]);
+ filename = getname((const char __user *) regs->gr[26]);
error = PTR_ERR(filename);
if (IS_ERR(filename))
goto out;
@@ -111,13 +111,13 @@ struct __sysctl_args32 {
u32 __unused[4];
};
-asmlinkage long sys32_sysctl(struct __sysctl_args32 *args)
+asmlinkage long sys32_sysctl(struct __sysctl_args32 __user *args)
{
struct __sysctl_args32 tmp;
int error;
unsigned int oldlen32;
size_t oldlen, *oldlenp = NULL;
- unsigned long addr = (((long)&args->__unused[0]) + 7) & ~7;
+ unsigned long addr = (((long __force)&args->__unused[0]) + 7) & ~7;
extern int do_sysctl(int *name, int nlen, void *oldval, size_t *oldlenp,
void *newval, size_t newlen);
@@ -159,7 +159,7 @@ asmlinkage long sys32_sysctl(struct __sysctl_args32 *args)
error = -EFAULT;
}
}
- if (copy_to_user(args->__unused, tmp.__unused, sizeof(tmp.__unused)))
+ if (copy_to_user(&args->__unused[0], tmp.__unused, sizeof(tmp.__unused)))
error = -EFAULT;
}
return error;
@@ -168,19 +168,19 @@ asmlinkage long sys32_sysctl(struct __sysctl_args32 *args)
#endif /* CONFIG_SYSCTL */
asmlinkage long sys32_sched_rr_get_interval(pid_t pid,
- struct compat_timespec *interval)
+ struct compat_timespec __user *interval)
{
struct timespec t;
int ret;
-
- KERNEL_SYSCALL(ret, sys_sched_rr_get_interval, pid, &t);
+
+ KERNEL_SYSCALL(ret, sys_sched_rr_get_interval, pid, (struct timespec __user *)&t);
if (put_compat_timespec(&t, interval))
return -EFAULT;
return ret;
}
static int
-put_compat_timeval(struct compat_timeval *u, struct timeval *t)
+put_compat_timeval(struct compat_timeval __user *u, struct timeval *t)
{
struct compat_timeval t32;
t32.tv_sec = t->tv_sec;
@@ -188,7 +188,7 @@ put_compat_timeval(struct compat_timeval *u, struct timeval *t)
return copy_to_user(u, &t32, sizeof t32);
}
-static inline long get_ts32(struct timespec *o, struct compat_timeval *i)
+static inline long get_ts32(struct timespec *o, struct compat_timeval __user *i)
{
long usec;
@@ -201,7 +201,7 @@ static inline long get_ts32(struct timespec *o, struct compat_timeval *i)
}
asmlinkage int
-sys32_gettimeofday(struct compat_timeval *tv, struct timezone *tz)
+sys32_gettimeofday(struct compat_timeval __user *tv, struct timezone __user *tz)
{
extern void do_gettimeofday(struct timeval *tv);
@@ -220,7 +220,7 @@ sys32_gettimeofday(struct compat_timeval *tv, struct timezone *tz)
}
asmlinkage
-int sys32_settimeofday(struct compat_timeval *tv, struct timezone *tz)
+int sys32_settimeofday(struct compat_timeval __user *tv, struct timezone __user *tz)
{
struct timespec kts;
struct timezone ktz;
@@ -237,7 +237,7 @@ int sys32_settimeofday(struct compat_timeval *tv, struct timezone *tz)
return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL);
}
-int cp_compat_stat(struct kstat *stat, struct compat_stat *statbuf)
+int cp_compat_stat(struct kstat *stat, struct compat_stat __user *statbuf)
{
int err;
@@ -294,24 +294,24 @@ struct old_linux32_dirent {
};
struct getdents32_callback {
- struct linux32_dirent * current_dir;
- struct linux32_dirent * previous;
+ struct linux32_dirent __user * current_dir;
+ struct linux32_dirent __user * previous;
int count;
int error;
};
struct readdir32_callback {
- struct old_linux32_dirent * dirent;
+ struct old_linux32_dirent __user * dirent;
int count;
};
#define ROUND_UP(x,a) ((__typeof__(x))(((unsigned long)(x) + ((a) - 1)) & ~((a) - 1)))
-#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
+#define NAME_OFFSET(de) ((int) ((de)->d_name - (char __user *) (de)))
static int
filldir32 (void *__buf, const char *name, int namlen, loff_t offset, ino_t ino,
unsigned int d_type)
{
- struct linux32_dirent * dirent;
+ struct linux32_dirent __user * dirent;
struct getdents32_callback * buf = (struct getdents32_callback *) __buf;
int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1, 4);
@@ -327,17 +327,17 @@ filldir32 (void *__buf, const char *name, int namlen, loff_t offset, ino_t ino,
put_user(reclen, &dirent->d_reclen);
copy_to_user(dirent->d_name, name, namlen);
put_user(0, dirent->d_name + namlen);
- dirent = (struct linux32_dirent *)((char *)dirent + reclen);
+ dirent = ((void __user *)dirent) + reclen;
buf->current_dir = dirent;
buf->count -= reclen;
return 0;
}
asmlinkage long
-sys32_getdents (unsigned int fd, void * dirent, unsigned int count)
+sys32_getdents (unsigned int fd, void __user * dirent, unsigned int count)
{
struct file * file;
- struct linux32_dirent * lastdirent;
+ struct linux32_dirent __user * lastdirent;
struct getdents32_callback buf;
int error;
@@ -346,7 +346,7 @@ sys32_getdents (unsigned int fd, void * dirent, unsigned int count)
if (!file)
goto out;
- buf.current_dir = (struct linux32_dirent *) dirent;
+ buf.current_dir = (struct linux32_dirent __user *) dirent;
buf.previous = NULL;
buf.count = count;
buf.error = 0;
@@ -372,7 +372,7 @@ fillonedir32 (void * __buf, const char * name, int namlen, loff_t offset, ino_t
unsigned int d_type)
{
struct readdir32_callback * buf = (struct readdir32_callback *) __buf;
- struct old_linux32_dirent * dirent;
+ struct old_linux32_dirent __user * dirent;
if (buf->count)
return -EINVAL;
@@ -387,7 +387,7 @@ fillonedir32 (void * __buf, const char * name, int namlen, loff_t offset, ino_t
}
asmlinkage long
-sys32_readdir (unsigned int fd, void * dirent, unsigned int count)
+sys32_readdir (unsigned int fd, void __user * dirent, unsigned int count)
{
int error;
struct file * file;
@@ -422,7 +422,7 @@ get_fd_set32(unsigned long n, u32 *ufdset, unsigned long *fdset)
if (ufdset) {
unsigned long odd;
- if (verify_area(VERIFY_WRITE, ufdset, n*sizeof(u32)))
+ if (!access_ok(VERIFY_WRITE, ufdset, n*sizeof(u32)))
return -EFAULT;
odd = n & 1UL;
@@ -477,7 +477,7 @@ struct msgbuf32 {
};
asmlinkage long sys32_msgsnd(int msqid,
- struct msgbuf32 *umsgp32,
+ struct msgbuf32 __user *umsgp32,
size_t msgsz, int msgflg)
{
struct msgbuf *mb;
@@ -494,14 +494,14 @@ asmlinkage long sys32_msgsnd(int msqid,
if (err)
err = -EFAULT;
else
- KERNEL_SYSCALL(err, sys_msgsnd, msqid, mb, msgsz, msgflg);
+ KERNEL_SYSCALL(err, sys_msgsnd, msqid, (struct msgbuf __user *)mb, msgsz, msgflg);
kfree(mb);
return err;
}
asmlinkage long sys32_msgrcv(int msqid,
- struct msgbuf32 *umsgp32,
+ struct msgbuf32 __user *umsgp32,
size_t msgsz, long msgtyp, int msgflg)
{
struct msgbuf *mb;
@@ -511,7 +511,7 @@ asmlinkage long sys32_msgrcv(int msqid,
if ((mb = kmalloc(msgsz + sizeof *mb + 4, GFP_KERNEL)) == NULL)
return -ENOMEM;
- KERNEL_SYSCALL(err, sys_msgrcv, msqid, mb, msgsz, msgtyp, msgflg);
+ KERNEL_SYSCALL(err, sys_msgrcv, msqid, (struct msgbuf __user *)mb, msgsz, msgtyp, msgflg);
if (err >= 0) {
len = err;
@@ -528,7 +528,7 @@ asmlinkage long sys32_msgrcv(int msqid,
return err;
}
-asmlinkage int sys32_sendfile(int out_fd, int in_fd, compat_off_t *offset, s32 count)
+asmlinkage int sys32_sendfile(int out_fd, int in_fd, compat_off_t __user *offset, s32 count)
{
mm_segment_t old_fs = get_fs();
int ret;
@@ -538,7 +538,7 @@ asmlinkage int sys32_sendfile(int out_fd, int in_fd, compat_off_t *offset, s32 c
return -EFAULT;
set_fs(KERNEL_DS);
- ret = sys_sendfile(out_fd, in_fd, offset ? &of : NULL, count);
+ ret = sys_sendfile(out_fd, in_fd, offset ? (off_t __user *)&of : NULL, count);
set_fs(old_fs);
if (offset && put_user(of, offset))
@@ -547,9 +547,7 @@ asmlinkage int sys32_sendfile(int out_fd, int in_fd, compat_off_t *offset, s32 c
return ret;
}
-typedef long __kernel_loff_t32; /* move this to asm/posix_types.h? */
-
-asmlinkage int sys32_sendfile64(int out_fd, int in_fd, __kernel_loff_t32 *offset, s32 count)
+asmlinkage int sys32_sendfile64(int out_fd, int in_fd, compat_loff_t __user *offset, s32 count)
{
mm_segment_t old_fs = get_fs();
int ret;
@@ -559,7 +557,7 @@ asmlinkage int sys32_sendfile64(int out_fd, int in_fd, __kernel_loff_t32 *offset
return -EFAULT;
set_fs(KERNEL_DS);
- ret = sys_sendfile64(out_fd, in_fd, offset ? &lof : NULL, count);
+ ret = sys_sendfile64(out_fd, in_fd, offset ? (loff_t __user *)&lof : NULL, count);
set_fs(old_fs);
if (offset && put_user(lof, offset))
@@ -598,7 +596,7 @@ struct timex32 {
int :32; int :32; int :32; int :32;
};
-asmlinkage long sys32_adjtimex(struct timex32 *txc_p32)
+asmlinkage long sys32_adjtimex(struct timex32 __user *txc_p32)
{
struct timex txc;
struct timex32 t32;
@@ -647,7 +645,7 @@ struct sysinfo32 {
* damage, I decided to just duplicate the code from sys_sysinfo here.
*/
-asmlinkage int sys32_sysinfo(struct sysinfo32 *info)
+asmlinkage int sys32_sysinfo(struct sysinfo32 __user *info)
{
struct sysinfo val;
int err;
@@ -714,7 +712,7 @@ asmlinkage long sys32_semctl(int semid, int semnum, int cmd, union semun arg)
return sys_semctl (semid, semnum, cmd, arg);
}
-long sys32_lookup_dcookie(u32 cookie_high, u32 cookie_low, char *buf,
+long sys32_lookup_dcookie(u32 cookie_high, u32 cookie_low, char __user *buf,
size_t len)
{
return sys_lookup_dcookie((u64)cookie_high << 32 | cookie_low,
diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c
index 69a253fe2e8dd..d2e5b229a2f49 100644
--- a/arch/parisc/kernel/traps.c
+++ b/arch/parisc/kernel/traps.c
@@ -163,13 +163,20 @@ void show_stack(struct task_struct *task, unsigned long *s)
struct unwind_frame_info info;
if (!task) {
- unsigned long sp, ip, rp;
+ unsigned long sp;
+ struct pt_regs *r;
HERE:
asm volatile ("copy %%r30, %0" : "=r"(sp));
- ip = (unsigned long)&&HERE;
- rp = (unsigned long)__builtin_return_address(0);
- unwind_frame_init(&info, current, sp, ip, rp);
+ r = (struct pt_regs *)kmalloc(sizeof(struct pt_regs), GFP_KERNEL);
+ if (!r)
+ return;
+ memset(r, 0, sizeof(struct pt_regs));
+ r->iaoq[0] = (unsigned long)&&HERE;
+ r->gr[2] = (unsigned long)__builtin_return_address(0);
+ r->gr[30] = sp;
+ unwind_frame_init(&info, current, r);
+ kfree(r);
} else {
unwind_frame_init_from_blocked_task(&info, task);
}
@@ -242,7 +249,7 @@ void handle_gdb_break(struct pt_regs *regs, int wot)
struct siginfo si;
si.si_code = wot;
- si.si_addr = (void *) (regs->iaoq[0] & ~3);
+ si.si_addr = (void __user *) (regs->iaoq[0] & ~3);
si.si_signo = SIGTRAP;
si.si_errno = 0;
force_sig_info(SIGTRAP, &si, current);
@@ -263,7 +270,7 @@ void handle_break(unsigned iir, struct pt_regs *regs)
show_regs(regs);
#endif
si.si_code = TRAP_BRKPT;
- si.si_addr = (void *) (regs->iaoq[0] & ~3);
+ si.si_addr = (void __user *) (regs->iaoq[0] & ~3);
si.si_signo = SIGTRAP;
force_sig_info(SIGTRAP, &si, current);
break;
@@ -281,7 +288,7 @@ void handle_break(unsigned iir, struct pt_regs *regs)
#endif
si.si_signo = SIGTRAP;
si.si_code = TRAP_BRKPT;
- si.si_addr = (void *) (regs->iaoq[0] & ~3);
+ si.si_addr = (void __user *) (regs->iaoq[0] & ~3);
force_sig_info(SIGTRAP, &si, current);
return;
}
@@ -416,7 +423,7 @@ void parisc_terminate(char *msg, struct pt_regs *regs, int code, unsigned long o
{
/* show_stack(NULL, (unsigned long *)regs->gr[30]); */
struct unwind_frame_info info;
- unwind_frame_init(&info, current, regs->gr[30], regs->iaoq[0], regs->gr[2]);
+ unwind_frame_init(&info, current, regs);
do_show_stack(&info);
}
@@ -569,7 +576,7 @@ void handle_interruption(int code, struct pt_regs *regs)
give_sigill:
si.si_signo = SIGILL;
si.si_errno = 0;
- si.si_addr = (void *) regs->iaoq[0];
+ si.si_addr = (void __user *) regs->iaoq[0];
force_sig_info(SIGILL, &si, current);
return;
@@ -577,7 +584,7 @@ void handle_interruption(int code, struct pt_regs *regs)
/* Overflow Trap, let the userland signal handler do the cleanup */
si.si_signo = SIGFPE;
si.si_code = FPE_INTOVF;
- si.si_addr = (void *) regs->iaoq[0];
+ si.si_addr = (void __user *) regs->iaoq[0];
force_sig_info(SIGFPE, &si, current);
return;
@@ -699,9 +706,9 @@ void handle_interruption(int code, struct pt_regs *regs)
si.si_signo = SIGSEGV;
si.si_errno = 0;
if (code == 7)
- si.si_addr = (void *) regs->iaoq[0];
+ si.si_addr = (void __user *) regs->iaoq[0];
else
- si.si_addr = (void *) regs->ior;
+ si.si_addr = (void __user *) regs->ior;
force_sig_info(SIGSEGV, &si, current);
return;
@@ -721,7 +728,7 @@ void handle_interruption(int code, struct pt_regs *regs)
si.si_signo = SIGBUS;
si.si_code = BUS_OBJERR;
si.si_errno = 0;
- si.si_addr = (void *) regs->ior;
+ si.si_addr = (void __user *) regs->ior;
force_sig_info(SIGBUS, &si, current);
return;
}
@@ -732,7 +739,7 @@ void handle_interruption(int code, struct pt_regs *regs)
}
if (user_mode(regs)) {
- if ((fault_space>>SPACEID_SHIFT) != (regs->sr[7] >> SPACEID_SHIFT)) {
+ if ((fault_space >> SPACEID_SHIFT) != (regs->sr[7] >> SPACEID_SHIFT)) {
#ifdef PRINT_USER_FAULTS
if (fault_space == 0)
printk(KERN_DEBUG "User Fault on Kernel Space ");
@@ -745,7 +752,7 @@ void handle_interruption(int code, struct pt_regs *regs)
si.si_signo = SIGSEGV;
si.si_errno = 0;
si.si_code = SEGV_MAPERR;
- si.si_addr = (void *) regs->ior;
+ si.si_addr = (void __user *) regs->ior;
force_sig_info(SIGSEGV, &si, current);
return;
}
diff --git a/arch/parisc/kernel/unaligned.c b/arch/parisc/kernel/unaligned.c
index 3eda1dadc3790..62eea35bcd69b 100644
--- a/arch/parisc/kernel/unaligned.c
+++ b/arch/parisc/kernel/unaligned.c
@@ -744,7 +744,7 @@ void handle_unaligned(struct pt_regs *regs)
si.si_signo = SIGSEGV;
si.si_errno = 0;
si.si_code = SEGV_MAPERR;
- si.si_addr = (void *)regs->ior;
+ si.si_addr = (void __user *)regs->ior;
force_sig_info(SIGSEGV, &si, current);
}
else
@@ -754,7 +754,7 @@ force_sigbus:
si.si_signo = SIGBUS;
si.si_errno = 0;
si.si_code = BUS_ADRALN;
- si.si_addr = (void *)regs->ior;
+ si.si_addr = (void __user *)regs->ior;
force_sig_info(SIGBUS, &si, current);
}
diff --git a/arch/parisc/kernel/unwind.c b/arch/parisc/kernel/unwind.c
index 5e1e115200822..db141108412e6 100644
--- a/arch/parisc/kernel/unwind.c
+++ b/arch/parisc/kernel/unwind.c
@@ -36,8 +36,7 @@ static spinlock_t unwind_lock;
* possible (before the slab allocator is initialized)
*/
static struct unwind_table kernel_unwind_table;
-static struct unwind_table *unwind_tables, *unwind_tables_end;
-
+static LIST_HEAD(unwind_tables);
static inline const struct unwind_table_entry *
find_unwind_entry_in_table(const struct unwind_table *table, unsigned long addr)
@@ -65,14 +64,14 @@ find_unwind_entry_in_table(const struct unwind_table *table, unsigned long addr)
static const struct unwind_table_entry *
find_unwind_entry(unsigned long addr)
{
- struct unwind_table *table = unwind_tables;
+ struct unwind_table *table;
const struct unwind_table_entry *e = NULL;
if (addr >= kernel_unwind_table.start &&
addr <= kernel_unwind_table.end)
e = find_unwind_entry_in_table(&kernel_unwind_table, addr);
- else
- for (; table; table = table->next) {
+ else
+ list_for_each_entry(table, &unwind_tables, list) {
if (addr >= table->start &&
addr <= table->end)
e = find_unwind_entry_in_table(table, addr);
@@ -99,7 +98,7 @@ unwind_table_init(struct unwind_table *table, const char *name,
table->end = base_addr + end->region_end;
table->table = (struct unwind_table_entry *)table_start;
table->length = end - start + 1;
- table->next = NULL;
+ INIT_LIST_HEAD(&table->list);
for (; start <= end; start++) {
if (start < end &&
@@ -112,33 +111,60 @@ unwind_table_init(struct unwind_table *table, const char *name,
}
}
-void *
+static void
+unwind_table_sort(struct unwind_table_entry *start,
+ struct unwind_table_entry *finish)
+{
+ struct unwind_table_entry el, *p, *q;
+
+ for (p = start + 1; p < finish; ++p) {
+ if (p[0].region_start < p[-1].region_start) {
+ el = *p;
+ q = p;
+ do {
+ q[0] = q[-1];
+ --q;
+ } while (q > start &&
+ el.region_start < q[-1].region_start);
+ *q = el;
+ }
+ }
+}
+
+struct unwind_table *
unwind_table_add(const char *name, unsigned long base_addr,
unsigned long gp,
void *start, void *end)
{
struct unwind_table *table;
unsigned long flags;
+ struct unwind_table_entry *s = (struct unwind_table_entry *)start;
+ struct unwind_table_entry *e = (struct unwind_table_entry *)end;
+
+ unwind_table_sort(s, e);
table = kmalloc(sizeof(struct unwind_table), GFP_USER);
if (table == NULL)
return NULL;
unwind_table_init(table, name, base_addr, gp, start, end);
spin_lock_irqsave(&unwind_lock, flags);
- if (unwind_tables)
- {
- unwind_tables_end->next = table;
- unwind_tables_end = table;
- }
- else
- {
- unwind_tables = unwind_tables_end = table;
- }
+ list_add_tail(&table->list, &unwind_tables);
spin_unlock_irqrestore(&unwind_lock, flags);
return table;
}
+void unwind_table_remove(struct unwind_table *table)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&unwind_lock, flags);
+ list_del(&table->list);
+ spin_unlock_irqrestore(&unwind_lock, flags);
+
+ kfree(table);
+}
+
/* Called from setup_arch to import the kernel unwind info */
static int unwind_init(void)
{
@@ -148,6 +174,8 @@ static int unwind_init(void)
start = (long)&__start___unwind[0];
stop = (long)&__stop___unwind[0];
+ spin_lock_init(&unwind_lock);
+
printk("unwind_init: start = 0x%lx, end = 0x%lx, entries = %lu\n",
start, stop,
(stop - start) / sizeof(struct unwind_table_entry));
@@ -239,9 +267,9 @@ static void unwind_frame_regs(struct unwind_frame_info *info)
info->prev_sp, info->prev_ip);
} else {
dbg("e->start = 0x%x, e->end = 0x%x, Save_SP = %d, "
- "Save_RP = %d size = %u\n", e->region_start,
- e->region_end, e->Save_SP, e->Save_RP,
- e->Total_frame_size);
+ "Save_RP = %d, Millicode = %d size = %u\n",
+ e->region_start, e->region_end, e->Save_SP, e->Save_RP,
+ e->Millicode, e->Total_frame_size);
looking_for_rp = e->Save_RP;
@@ -284,7 +312,9 @@ static void unwind_frame_regs(struct unwind_frame_info *info)
}
info->prev_sp = info->sp - frame_size;
- if (rpoffset)
+ if (e->Millicode)
+ info->rp = info->r31;
+ else if (rpoffset)
info->rp = *(unsigned long *)(info->prev_sp - rpoffset);
info->prev_ip = info->rp;
info->rp = 0;
@@ -296,13 +326,14 @@ static void unwind_frame_regs(struct unwind_frame_info *info)
}
void unwind_frame_init(struct unwind_frame_info *info, struct task_struct *t,
- unsigned long sp, unsigned long ip, unsigned long rp)
+ struct pt_regs *regs)
{
memset(info, 0, sizeof(struct unwind_frame_info));
info->t = t;
- info->sp = sp;
- info->ip = ip;
- info->rp = rp;
+ info->sp = regs->gr[30];
+ info->ip = regs->iaoq[0];
+ info->rp = regs->gr[2];
+ info->r31 = regs->gr[31];
dbg("(%d) Start unwind from sp=%08lx ip=%08lx\n",
t ? (int)t->pid : -1, info->sp, info->ip);
@@ -310,14 +341,22 @@ void unwind_frame_init(struct unwind_frame_info *info, struct task_struct *t,
void unwind_frame_init_from_blocked_task(struct unwind_frame_info *info, struct task_struct *t)
{
- struct pt_regs *regs = &t->thread.regs;
- unwind_frame_init(info, t, regs->ksp, regs->kpc, 0);
+ struct pt_regs *r = &t->thread.regs;
+ struct pt_regs *r2;
+
+ r2 = (struct pt_regs *)kmalloc(sizeof(struct pt_regs), GFP_KERNEL);
+ if (!r2)
+ return;
+ *r2 = *r;
+ r2->gr[30] = r->ksp;
+ r2->iaoq[0] = r->kpc;
+ unwind_frame_init(info, t, r2);
+ kfree(r2);
}
void unwind_frame_init_running(struct unwind_frame_info *info, struct pt_regs *regs)
{
- unwind_frame_init(info, current, regs->gr[30], regs->iaoq[0],
- regs->gr[2]);
+ unwind_frame_init(info, current, regs);
}
int unwind_once(struct unwind_frame_info *next_frame)
diff --git a/arch/parisc/kernel/vmlinux.lds.S b/arch/parisc/kernel/vmlinux.lds.S
index e011bc856fc1a..e5fac3e08c7a0 100644
--- a/arch/parisc/kernel/vmlinux.lds.S
+++ b/arch/parisc/kernel/vmlinux.lds.S
@@ -29,7 +29,7 @@
#include <asm/page.h>
/* ld script to make hppa Linux kernel */
-#ifndef CONFIG_PARISC64
+#ifndef CONFIG_64BIT
OUTPUT_FORMAT("elf32-hppa-linux")
OUTPUT_ARCH(hppa)
#else
@@ -38,7 +38,7 @@ OUTPUT_ARCH(hppa:hppa2.0w)
#endif
ENTRY(_stext)
-#ifndef CONFIG_PARISC64
+#ifndef CONFIG_64BIT
jiffies = jiffies_64 + 4;
#else
jiffies = jiffies_64;
@@ -84,6 +84,9 @@ SECTIONS
.data : { /* Data */
*(.data)
+ *(.data.vm0.pmd)
+ *(.data.vm0.pgd)
+ *(.data.vm0.pte)
CONSTRUCTORS
}
@@ -112,7 +115,7 @@ SECTIONS
. = ALIGN(16384);
init_istack : { *(init_istack) }
-#ifdef CONFIG_PARISC64
+#ifdef CONFIG_64BIT
. = ALIGN(16); /* Linkage tables */
.opd : { *(.opd) } PROVIDE (__gp = .);
.plt : { *(.plt) }
@@ -180,7 +183,7 @@ SECTIONS
/* Sections to be discarded */
/DISCARD/ : {
*(.exitcall.exit)
-#ifdef CONFIG_PARISC64
+#ifdef CONFIG_64BIT
/* temporary hack until binutils is fixed to not emit these
for static binaries */
*(.interp)
diff --git a/arch/parisc/lib/checksum.c b/arch/parisc/lib/checksum.c
index 9866c93f1e6f9..8a1e08068e7de 100644
--- a/arch/parisc/lib/checksum.c
+++ b/arch/parisc/lib/checksum.c
@@ -131,9 +131,9 @@ EXPORT_SYMBOL(csum_partial_copy_nocheck);
* Copy from userspace and compute checksum. If we catch an exception
* then zero the rest of the buffer.
*/
-unsigned int csum_partial_copy_from_user (const unsigned char *src, unsigned char *dst,
- int len, unsigned int sum,
- int *err_ptr)
+unsigned int csum_partial_copy_from_user(const unsigned char __user *src,
+ unsigned char *dst, int len,
+ unsigned int sum, int *err_ptr)
{
int missing;
diff --git a/arch/parisc/lib/debuglocks.c b/arch/parisc/lib/debuglocks.c
index 5ac3eb0472766..1b33fe6e5b7a1 100644
--- a/arch/parisc/lib/debuglocks.c
+++ b/arch/parisc/lib/debuglocks.c
@@ -1,7 +1,7 @@
/*
* Debugging versions of SMP locking primitives.
*
- * Copyright (C) 2004 Thibaut VARENE <varenet@esiee.fr>
+ * Copyright (C) 2004 Thibaut VARENE <varenet@parisc-linux.org>
*
* Some code stollen from alpha & sparc64 ;)
*
@@ -239,8 +239,6 @@ int _dbg_write_trylock(rwlock_t *rw, const char *bfile, int bline)
if(rw->counter != 0) {
/* this basically never happens */
_raw_spin_unlock(&rw->lock);
-
-
return 0;
}
@@ -250,6 +248,7 @@ int _dbg_write_trylock(rwlock_t *rw, const char *bfile, int bline)
pdc_printf("%s:%d: try write_lock grabbed in %s at %p(%d)\n",
bfile, bline, current->comm, inline_pc, cpu);
#endif
+ return 1;
}
void _dbg_read_lock(rwlock_t * rw, const char *bfile, int bline)
diff --git a/arch/parisc/lib/memcpy.c b/arch/parisc/lib/memcpy.c
index 20ec35530ca4f..feb1b9f42c2bf 100644
--- a/arch/parisc/lib/memcpy.c
+++ b/arch/parisc/lib/memcpy.c
@@ -111,7 +111,7 @@ DECLARE_PER_CPU(struct exception_data, exception_data);
"\t" EXC_WORD "\t" #_e "\n" \
"\t.previous\n" \
: _tt(_t), "+r"(_a) \
- : "1"(_a) \
+ : \
: "r8")
#define def_store_ai_insn(_insn,_sz,_tt,_s,_a,_t,_e) \
@@ -122,7 +122,7 @@ DECLARE_PER_CPU(struct exception_data, exception_data);
"\t" EXC_WORD "\t" #_e "\n" \
"\t.previous\n" \
: "+r"(_a) \
- : _tt(_t), "0"(_a) \
+ : _tt(_t) \
: "r8")
#define ldbma(_s, _a, _t, _e) def_load_ai_insn(ldbs,1,"=r",_s,_a,_t,_e)
@@ -297,7 +297,7 @@ handle_store_error:
unsigned long pa_memcpy(void *dstp, const void *srcp, unsigned long len)
{
register unsigned long src, dst, t1, t2, t3;
- register char *pcs, *pcd;
+ register unsigned char *pcs, *pcd;
register unsigned int *pws, *pwd;
register double *pds, *pdd;
unsigned long ret = 0;
diff --git a/arch/parisc/math-emu/driver.c b/arch/parisc/math-emu/driver.c
index e202c240f06f6..09ef4136c6935 100644
--- a/arch/parisc/math-emu/driver.c
+++ b/arch/parisc/math-emu/driver.c
@@ -27,7 +27,6 @@
* Copyright (C) 2001 Hewlett-Packard <bame@debian.org>
*/
-#include <linux/config.h>
#include <linux/sched.h>
#include "float.h"
#include "math-emu.h"
@@ -120,7 +119,7 @@ handle_fpe(struct pt_regs *regs)
si.si_signo = signalcode >> 24;
si.si_errno = 0;
si.si_code = signalcode & 0xffffff;
- si.si_addr = (void *) regs->iaoq[0];
+ si.si_addr = (void __user *) regs->iaoq[0];
force_sig_info(si.si_signo, &si, current);
return -1;
}
diff --git a/arch/parisc/mm/fault.c b/arch/parisc/mm/fault.c
index fd1c77280b35a..eaa701479f5f1 100644
--- a/arch/parisc/mm/fault.c
+++ b/arch/parisc/mm/fault.c
@@ -225,7 +225,7 @@ bad_area:
si.si_signo = SIGSEGV;
si.si_errno = 0;
si.si_code = SEGV_MAPERR;
- si.si_addr = (void *) address;
+ si.si_addr = (void __user *) address;
force_sig_info(SIGSEGV, &si, current);
return;
}
diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c
index ff0e1eabe37a3..cac37589e35cb 100644
--- a/arch/parisc/mm/init.c
+++ b/arch/parisc/mm/init.c
@@ -21,6 +21,7 @@
#include <linux/swap.h>
#include <linux/unistd.h>
#include <linux/nodemask.h> /* for node_online_map */
+#include <linux/pagemap.h> /* for release_pages and page_cache_release */
#include <asm/pgalloc.h>
#include <asm/tlb.h>
@@ -59,8 +60,6 @@ static struct resource pdcdata_resource = {
static struct resource sysram_resources[MAX_PHYSMEM_RANGES];
-static unsigned long max_pfn;
-
/* The following array is initialized from the firmware specific
* information retrieved in kernel/inventory.c.
*/
@@ -180,7 +179,7 @@ static void __init setup_bootmem(void)
size = (pmem_ranges[i].pages << PAGE_SHIFT);
start = (pmem_ranges[i].start_pfn << PAGE_SHIFT);
- printk(KERN_INFO "%2d) Start 0x%016lx End 0x%016lx Size %6ld Mb\n",
+ printk(KERN_INFO "%2d) Start 0x%016lx End 0x%016lx Size %6ld MB\n",
i,start, start + (size - 1), size >> 20);
}
}
@@ -213,7 +212,7 @@ static void __init setup_bootmem(void)
rsize = pmem_ranges[i].pages << PAGE_SHIFT;
if ((mem_max + rsize) > mem_limit) {
- printk(KERN_WARNING "Memory truncated to %ld Mb\n", mem_limit >> 20);
+ printk(KERN_WARNING "Memory truncated to %ld MB\n", mem_limit >> 20);
if (mem_max == mem_limit)
npmem_ranges = i;
else {
@@ -229,7 +228,7 @@ static void __init setup_bootmem(void)
mem_max += rsize;
}
- printk(KERN_INFO "Total Memory: %ld Mb\n",mem_max >> 20);
+ printk(KERN_INFO "Total Memory: %ld MB\n",mem_max >> 20);
#ifndef CONFIG_DISCONTIGMEM
/* Merge the ranges, keeping track of the holes */
@@ -445,7 +444,6 @@ void __init mem_init(void)
#ifndef CONFIG_DISCONTIGMEM
max_mapnr = page_to_pfn(virt_to_page(high_memory - 1)) + 1;
- mem_map = zone_table[ZONE_DMA]->zone_mem_map;
totalram_pages += free_all_bootmem();
#else
{
diff --git a/arch/parisc/mm/kmap.c b/arch/parisc/mm/kmap.c
index 20468fec54917..1b1acd5e2f6e2 100644
--- a/arch/parisc/mm/kmap.c
+++ b/arch/parisc/mm/kmap.c
@@ -49,10 +49,10 @@ typedef void (*pte_iterator_t) (pte_t * pte, unsigned long arg);
* unmap_uncached_page() and save a little code space but I didn't
* do that since I'm not certain whether this is the right path. -PB
*/
-static void unmap_cached_pte(pte_t * pte, unsigned long arg)
+static void unmap_cached_pte(pte_t * pte, unsigned long addr, unsigned long arg)
{
pte_t page = *pte;
- pte_clear(pte);
+ pte_clear(&init_mm, addr, pte);
if (!pte_none(page)) {
if (pte_present(page)) {
unsigned long map_nr = pte_pagenr(page);
diff --git a/arch/ppc/8260_io/Kconfig b/arch/ppc/8260_io/Kconfig
index 391e8541f5989..ea9651e2dd6a7 100644
--- a/arch/ppc/8260_io/Kconfig
+++ b/arch/ppc/8260_io/Kconfig
@@ -42,7 +42,7 @@ config USE_MDIO
choice
prompt "Type of PHY"
depends on 8260 && USE_MDIO
- default FCC_LXT971
+ default FCC_GENERIC_PHY
config FCC_LXT970
bool "LXT970"
@@ -53,6 +53,13 @@ config FCC_LXT971
config FCC_QS6612
bool "QS6612"
+config FCC_DM9131
+ bool "DM9131"
+
+config FCC_DM9161
+ bool "DM9161"
+
+config FCC_GENERIC_PHY
+ bool "Generic"
endchoice
endmenu
-
diff --git a/arch/ppc/8260_io/fcc_enet.c b/arch/ppc/8260_io/fcc_enet.c
index a38487b115038..2086c6ad11475 100644
--- a/arch/ppc/8260_io/fcc_enet.c
+++ b/arch/ppc/8260_io/fcc_enet.c
@@ -16,6 +16,9 @@
* small packets. Since this is a cache coherent processor and CPM,
* I could also preallocate SKB's and use them directly on the interface.
*
+ * 2004-12 Leo Li (leoli@freescale.com)
+ * - Rework the FCC clock configuration part, make it easier to configure.
+ *
*/
#include <linux/config.h>
@@ -34,6 +37,8 @@
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/spinlock.h>
+#include <linux/mii.h>
+#include <linux/workqueue.h>
#include <linux/bitops.h>
#include <asm/immap_cpm2.h>
@@ -41,6 +46,26 @@
#include <asm/mpc8260.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
+#include <asm/signal.h>
+
+/* We can't use the PHY interrupt if we aren't using MDIO. */
+#if !defined(CONFIG_USE_MDIO)
+#undef PHY_INTERRUPT
+#endif
+
+/* If we have a PHY interrupt, we will advertise both full-duplex and half-
+ * duplex capabilities. If we don't have a PHY interrupt, then we will only
+ * advertise half-duplex capabilities.
+ */
+#define MII_ADVERTISE_HALF (ADVERTISE_100HALF | ADVERTISE_10HALF | \
+ ADVERTISE_CSMA)
+#define MII_ADVERTISE_ALL (ADVERTISE_100FULL | ADVERTISE_10FULL | \
+ MII_ADVERTISE_HALF)
+#ifdef PHY_INTERRUPT
+#define MII_ADVERTISE_DEFAULT MII_ADVERTISE_ALL
+#else
+#define MII_ADVERTISE_DEFAULT MII_ADVERTISE_HALF
+#endif
#include <asm/cpm2.h>
/* The transmitter timeout
@@ -65,18 +90,6 @@ typedef struct {
const phy_cmd_t *shutdown;
} phy_info_t;
-/* Register definitions for the PHY. */
-
-#define MII_REG_CR 0 /* Control Register */
-#define MII_REG_SR 1 /* Status Register */
-#define MII_REG_PHYIR1 2 /* PHY Identification Register 1 */
-#define MII_REG_PHYIR2 3 /* PHY Identification Register 2 */
-#define MII_REG_ANAR 4 /* A-N Advertisement Register */
-#define MII_REG_ANLPAR 5 /* A-N Link Partner Ability Register */
-#define MII_REG_ANER 6 /* A-N Expansion Register */
-#define MII_REG_ANNPTR 7 /* A-N Next Page Transmit Register */
-#define MII_REG_ANLPRNPR 8 /* A-N Link Partner Received Next Page Reg. */
-
/* values for phy_status */
#define PHY_CONF_ANE 0x0001 /* 1 auto-negotiation enabled */
@@ -111,13 +124,15 @@ typedef struct {
#define TX_RING_MOD_MASK 15 /* for this to work */
/* The FCC stores dest/src/type, data, and checksum for receive packets.
+ * size includes support for VLAN
*/
-#define PKT_MAXBUF_SIZE 1518
+#define PKT_MAXBUF_SIZE 1522
#define PKT_MINBUF_SIZE 64
/* Maximum input DMA size. Must be a should(?) be a multiple of 4.
-*/
-#define PKT_MAXDMA_SIZE 1520
+ * size includes support for VLAN
+ */
+#define PKT_MAXDMA_SIZE 1524
/* Maximum input buffer size. Must be a multiple of 32.
*/
@@ -129,8 +144,9 @@ static int fcc_enet_rx(struct net_device *dev);
static irqreturn_t fcc_enet_interrupt(int irq, void *dev_id, struct pt_regs *);
static int fcc_enet_close(struct net_device *dev);
static struct net_device_stats *fcc_enet_get_stats(struct net_device *dev);
-static void set_multicast_list(struct net_device *dev);
+/* static void set_multicast_list(struct net_device *dev); */
static void fcc_restart(struct net_device *dev, int duplex);
+static void fcc_stop(struct net_device *dev);
static int fcc_enet_set_mac_address(struct net_device *dev, void *addr);
/* These will be configurable for the FCC choice.
@@ -141,6 +157,65 @@ static int fcc_enet_set_mac_address(struct net_device *dev, void *addr);
* help show what pins are used for each device.
*/
+/* Since the CLK setting changes greatly from board to board, I changed
+ * it to a easy way. You just need to specify which CLK number to use.
+ * Note that only limited choices can be make on each port.
+ */
+
+/* FCC1 Clock Source Configuration. There are board specific.
+ Can only choose from CLK9-12 */
+#ifdef CONFIG_SBC82xx
+#define F1_RXCLK 9
+#define F1_TXCLK 10
+#elif defined(CONFIG_ADS8272)
+#define F1_RXCLK 11
+#define F1_TXCLK 10
+#else
+#define F1_RXCLK 12
+#define F1_TXCLK 11
+#endif
+
+/* FCC2 Clock Source Configuration. There are board specific.
+ Can only choose from CLK13-16 */
+#ifdef CONFIG_ADS8272
+#define F2_RXCLK 15
+#define F2_TXCLK 16
+#else
+#define F2_RXCLK 13
+#define F2_TXCLK 14
+#endif
+
+/* FCC3 Clock Source Configuration. There are board specific.
+ Can only choose from CLK13-16 */
+#define F3_RXCLK 15
+#define F3_TXCLK 16
+
+/* Automatically generates register configurations */
+#define PC_CLK(x) ((uint)(1<<(x-1))) /* FCC CLK I/O ports */
+
+#define CMXFCR_RF1CS(x) ((uint)((x-5)<<27)) /* FCC1 Receive Clock Source */
+#define CMXFCR_TF1CS(x) ((uint)((x-5)<<24)) /* FCC1 Transmit Clock Source */
+#define CMXFCR_RF2CS(x) ((uint)((x-9)<<19)) /* FCC2 Receive Clock Source */
+#define CMXFCR_TF2CS(x) ((uint)((x-9)<<16)) /* FCC2 Transmit Clock Source */
+#define CMXFCR_RF3CS(x) ((uint)((x-9)<<11)) /* FCC3 Receive Clock Source */
+#define CMXFCR_TF3CS(x) ((uint)((x-9)<<8)) /* FCC3 Transmit Clock Source */
+
+#define PC_F1RXCLK PC_CLK(F1_RXCLK)
+#define PC_F1TXCLK PC_CLK(F1_TXCLK)
+#define CMX1_CLK_ROUTE (CMXFCR_RF1CS(F1_RXCLK) | CMXFCR_TF1CS(F1_TXCLK))
+#define CMX1_CLK_MASK ((uint)0xff000000)
+
+#define PC_F2RXCLK PC_CLK(F2_RXCLK)
+#define PC_F2TXCLK PC_CLK(F2_TXCLK)
+#define CMX2_CLK_ROUTE (CMXFCR_RF2CS(F2_RXCLK) | CMXFCR_TF2CS(F2_TXCLK))
+#define CMX2_CLK_MASK ((uint)0x00ff0000)
+
+#define PC_F3RXCLK PC_CLK(F3_RXCLK)
+#define PC_F3TXCLK PC_CLK(F3_TXCLK)
+#define CMX3_CLK_ROUTE (CMXFCR_RF3CS(F3_RXCLK) | CMXFCR_TF3CS(F3_TXCLK))
+#define CMX3_CLK_MASK ((uint)0x0000ff00)
+
+
/* I/O Pin assignment for FCC1. I don't yet know the best way to do this,
* but there is little variation among the choices.
*/
@@ -152,30 +227,12 @@ static int fcc_enet_set_mac_address(struct net_device *dev, void *addr);
#define PA1_RXER ((uint)0x00000020)
#define PA1_TXDAT ((uint)0x00003c00)
#define PA1_RXDAT ((uint)0x0003c000)
-#define PA1_PSORA0 (PA1_RXDAT | PA1_TXDAT)
-#define PA1_PSORA1 (PA1_COL | PA1_CRS | PA1_TXER | PA1_TXEN | \
+#define PA1_PSORA_BOUT (PA1_RXDAT | PA1_TXDAT)
+#define PA1_PSORA_BIN (PA1_COL | PA1_CRS | PA1_TXER | PA1_TXEN | \
PA1_RXDV | PA1_RXER)
-#define PA1_DIRA0 (PA1_RXDAT | PA1_CRS | PA1_COL | PA1_RXER | PA1_RXDV)
-#define PA1_DIRA1 (PA1_TXDAT | PA1_TXEN | PA1_TXER)
+#define PA1_DIRA_BOUT (PA1_RXDAT | PA1_CRS | PA1_COL | PA1_RXER | PA1_RXDV)
+#define PA1_DIRA_BIN (PA1_TXDAT | PA1_TXEN | PA1_TXER)
-#ifdef CONFIG_SBC82xx
-/* rx is clk9, tx is clk10 */
-#define PC_F1RXCLK ((uint)0x00000100)
-#define PC_F1TXCLK ((uint)0x00000200)
-#define CMX1_CLK_ROUTE ((uint)0x25000000)
-#define CMX1_CLK_MASK ((uint)0xff000000)
-#elif defined(CONFIG_ADS8272)
-#define PC_F1RXCLK ((uint)0x00000400)
-#define PC_F1TXCLK ((uint)0x00000200)
-#define CMX1_CLK_ROUTE ((uint)0x36000000)
-#define CMX1_CLK_MASK ((uint)0xff000000)
-#else /* other boards */
-/* CLK12 is receive, CLK11 is transmit. These are board specific. */
-#define PC_F1RXCLK ((uint)0x00000800)
-#define PC_F1TXCLK ((uint)0x00000400)
-#define CMX1_CLK_ROUTE ((uint)0x3e000000)
-#define CMX1_CLK_MASK ((uint)0xff000000)
-#endif
/* I/O Pin assignment for FCC2. I don't yet know the best way to do this,
* but there is little variation among the choices.
@@ -188,25 +245,12 @@ static int fcc_enet_set_mac_address(struct net_device *dev, void *addr);
#define PB2_CRS ((uint)0x00000020)
#define PB2_TXDAT ((uint)0x000003c0)
#define PB2_RXDAT ((uint)0x00003c00)
-#define PB2_PSORB0 (PB2_RXDAT | PB2_TXDAT | PB2_CRS | PB2_COL | \
+#define PB2_PSORB_BOUT (PB2_RXDAT | PB2_TXDAT | PB2_CRS | PB2_COL | \
PB2_RXER | PB2_RXDV | PB2_TXER)
-#define PB2_PSORB1 (PB2_TXEN)
-#define PB2_DIRB0 (PB2_RXDAT | PB2_CRS | PB2_COL | PB2_RXER | PB2_RXDV)
-#define PB2_DIRB1 (PB2_TXDAT | PB2_TXEN | PB2_TXER)
+#define PB2_PSORB_BIN (PB2_TXEN)
+#define PB2_DIRB_BOUT (PB2_RXDAT | PB2_CRS | PB2_COL | PB2_RXER | PB2_RXDV)
+#define PB2_DIRB_BIN (PB2_TXDAT | PB2_TXEN | PB2_TXER)
-/* CLK13 is receive, CLK14 is transmit. These are board dependent.
-*/
-#ifdef CONFIG_ADS8272
-#define PC_F2RXCLK ((uint)0x00004000)
-#define PC_F2TXCLK ((uint)0x00008000)
-#define CMX2_CLK_ROUTE ((uint)0x00370000)
-#define CMX2_CLK_MASK ((uint)0x00ff0000)
-#else
-#define PC_F2RXCLK ((uint)0x00001000)
-#define PC_F2TXCLK ((uint)0x00002000)
-#define CMX2_CLK_ROUTE ((uint)0x00250000)
-#define CMX2_CLK_MASK ((uint)0x00ff0000)
-#endif
/* I/O Pin assignment for FCC3. I don't yet know the best way to do this,
* but there is little variation among the choices.
@@ -217,35 +261,61 @@ static int fcc_enet_set_mac_address(struct net_device *dev, void *addr);
#define PB3_TXEN ((uint)0x00020000)
#define PB3_COL ((uint)0x00040000)
#define PB3_CRS ((uint)0x00080000)
+#ifndef CONFIG_RPX8260
+#define PB3_TXDAT ((uint)0x0f000000)
+#define PC3_TXDAT ((uint)0x00000000)
+#else
#define PB3_TXDAT ((uint)0x0f000000)
+#define PC3_TXDAT 0
+#endif
#define PB3_RXDAT ((uint)0x00f00000)
-#define PB3_PSORB0 (PB3_RXDAT | PB3_TXDAT | PB3_CRS | PB3_COL | \
+#define PB3_PSORB_BOUT (PB3_RXDAT | PB3_TXDAT | PB3_CRS | PB3_COL | \
PB3_RXER | PB3_RXDV | PB3_TXER | PB3_TXEN)
-#define PB3_PSORB1 (0)
-#define PB3_DIRB0 (PB3_RXDAT | PB3_CRS | PB3_COL | PB3_RXER | PB3_RXDV)
-#define PB3_DIRB1 (PB3_TXDAT | PB3_TXEN | PB3_TXER)
+#define PB3_PSORB_BIN (0)
+#define PB3_DIRB_BOUT (PB3_RXDAT | PB3_CRS | PB3_COL | PB3_RXER | PB3_RXDV)
+#define PB3_DIRB_BIN (PB3_TXDAT | PB3_TXEN | PB3_TXER)
+
+#define PC3_PSORC_BOUT (PC3_TXDAT)
+#define PC3_PSORC_BIN (0)
+#define PC3_DIRC_BOUT (0)
+#define PC3_DIRC_BIN (PC3_TXDAT)
-/* CLK15 is receive, CLK16 is transmit. These are board dependent.
-*/
-#define PC_F3RXCLK ((uint)0x00004000)
-#define PC_F3TXCLK ((uint)0x00008000)
-#define CMX3_CLK_ROUTE ((uint)0x00003700)
-#define CMX3_CLK_MASK ((uint)0x0000ff00)
/* MII status/control serial interface.
*/
-#ifdef CONFIG_TQM8260
+#if defined(CONFIG_RPX8260)
+/* The EP8260 doesn't use Port C for MDIO */
+#define PC_MDIO ((uint)0x00000000)
+#define PC_MDCK ((uint)0x00000000)
+#elif defined(CONFIG_TQM8260)
/* TQM8260 has MDIO and MDCK on PC30 and PC31 respectively */
#define PC_MDIO ((uint)0x00000002)
#define PC_MDCK ((uint)0x00000001)
#elif defined(CONFIG_ADS8272)
#define PC_MDIO ((uint)0x00002000)
#define PC_MDCK ((uint)0x00001000)
+#elif defined(CONFIG_EST8260) || defined(CONFIG_ADS8260) || defined(CONFIG_PQ2FADS)
+#define PC_MDIO ((uint)0x00400000)
+#define PC_MDCK ((uint)0x00200000)
#else
#define PC_MDIO ((uint)0x00000004)
#define PC_MDCK ((uint)0x00000020)
#endif
+#if defined(CONFIG_USE_MDIO) && (!defined(PC_MDIO) || !defined(PC_MDCK))
+#error "Must define PC_MDIO and PC_MDCK if using MDIO"
+#endif
+
+/* PHY addresses */
+/* default to dynamic config of phy addresses */
+#define FCC1_PHY_ADDR 0
+#ifdef CONFIG_PQ2FADS
+#define FCC2_PHY_ADDR 0
+#else
+#define FCC2_PHY_ADDR 2
+#endif
+#define FCC3_PHY_ADDR 3
+
/* A table of information for supporting FCCs. This does two things.
* First, we know how many FCCs we have and they are always externally
* numbered from zero. Second, it holds control register and I/O
@@ -253,6 +323,7 @@ static int fcc_enet_set_mac_address(struct net_device *dev, void *addr);
*/
typedef struct fcc_info {
uint fc_fccnum;
+ uint fc_phyaddr;
uint fc_cpmblock;
uint fc_cpmpage;
uint fc_proff;
@@ -266,33 +337,19 @@ typedef struct fcc_info {
static fcc_info_t fcc_ports[] = {
#ifdef CONFIG_FCC1_ENET
- { 0, CPM_CR_FCC1_SBLOCK, CPM_CR_FCC1_PAGE, PROFF_FCC1, SIU_INT_FCC1,
+ { 0, FCC1_PHY_ADDR, CPM_CR_FCC1_SBLOCK, CPM_CR_FCC1_PAGE, PROFF_FCC1, SIU_INT_FCC1,
(PC_F1RXCLK | PC_F1TXCLK), CMX1_CLK_ROUTE, CMX1_CLK_MASK,
-# if defined(CONFIG_TQM8260) || defined(CONFIG_ADS8272)
PC_MDIO, PC_MDCK },
-# else
- 0x00000004, 0x00000100 },
-# endif
#endif
#ifdef CONFIG_FCC2_ENET
- { 1, CPM_CR_FCC2_SBLOCK, CPM_CR_FCC2_PAGE, PROFF_FCC2, SIU_INT_FCC2,
+ { 1, FCC2_PHY_ADDR, CPM_CR_FCC2_SBLOCK, CPM_CR_FCC2_PAGE, PROFF_FCC2, SIU_INT_FCC2,
(PC_F2RXCLK | PC_F2TXCLK), CMX2_CLK_ROUTE, CMX2_CLK_MASK,
-# if defined(CONFIG_TQM8260) || defined(CONFIG_ADS8272)
PC_MDIO, PC_MDCK },
-# elif defined(CONFIG_EST8260) || defined(CONFIG_ADS8260)
- 0x00400000, 0x00200000 },
-# else
- 0x00000002, 0x00000080 },
-# endif
#endif
#ifdef CONFIG_FCC3_ENET
- { 2, CPM_CR_FCC3_SBLOCK, CPM_CR_FCC3_PAGE, PROFF_FCC3, SIU_INT_FCC3,
+ { 2, FCC3_PHY_ADDR, CPM_CR_FCC3_SBLOCK, CPM_CR_FCC3_PAGE, PROFF_FCC3, SIU_INT_FCC3,
(PC_F3RXCLK | PC_F3TXCLK), CMX3_CLK_ROUTE, CMX3_CLK_MASK,
-# if defined(CONFIG_TQM8260) || defined(CONFIG_ADS8272)
PC_MDIO, PC_MDCK },
-# else
- 0x00000001, 0x00000040 },
-# endif
#endif
};
@@ -310,8 +367,6 @@ struct fcc_enet_private {
ushort skb_cur;
ushort skb_dirty;
- atomic_t n_pkts; /* Number of packets in tx ring */
-
/* CPM dual port RAM relative addresses.
*/
cbd_t *rx_bd_base; /* Address of Rx and Tx buffers. */
@@ -321,7 +376,7 @@ struct fcc_enet_private {
volatile fcc_t *fccp;
volatile fcc_enet_t *ep;
struct net_device_stats stats;
- uint tx_full;
+ uint tx_free;
spinlock_t lock;
#ifdef CONFIG_USE_MDIO
@@ -329,7 +384,8 @@ struct fcc_enet_private {
uint phy_id_done;
uint phy_status;
phy_info_t *phy;
- struct tq_struct phy_task;
+ struct work_struct phy_relink;
+ struct work_struct phy_display_config;
uint sequence_done;
@@ -354,14 +410,13 @@ static void init_fcc_param(fcc_info_t *fip, struct net_device *dev,
#ifdef CONFIG_USE_MDIO
static int mii_queue(struct net_device *dev, int request, void (*func)(uint, struct net_device *));
static uint mii_send_receive(fcc_info_t *fip, uint cmd);
-
-static void fcc_stop(struct net_device *dev);
+static void mii_do_cmd(struct net_device *dev, const phy_cmd_t *c);
/* Make MII read/write commands for the FCC.
*/
-#define mk_mii_read(REG) (0x60020000 | ((REG & 0x1f) << 18))
-#define mk_mii_write(REG, VAL) (0x50020000 | ((REG & 0x1f) << 18) | \
- (VAL & 0xffff))
+#define mk_mii_read(REG) (0x60020000 | (((REG) & 0x1f) << 18))
+#define mk_mii_write(REG, VAL) (0x50020000 | (((REG) & 0x1f) << 18) | \
+ ((VAL) & 0xffff))
#define mk_mii_end 0
#endif /* CONFIG_USE_MDIO */
@@ -371,20 +426,14 @@ fcc_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct fcc_enet_private *cep = (struct fcc_enet_private *)dev->priv;
volatile cbd_t *bdp;
- int idx;
-
- if (!cep->link) {
- /* Link is down or autonegotiation is in progress. */
- return 1;
- }
/* Fill in a Tx ring entry */
bdp = cep->cur_tx;
#ifndef final_version
- if (bdp->cbd_sc & BD_ENET_TX_READY) {
+ if (!cep->tx_free || (bdp->cbd_sc & BD_ENET_TX_READY)) {
/* Ooops. All transmit buffers are full. Bail out.
- * This should not happen, since cep->tx_full should be set.
+ * This should not happen, since the tx queue should be stopped.
*/
printk("%s: tx queue full!.\n", dev->name);
return 1;
@@ -407,21 +456,10 @@ fcc_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
spin_lock_irq(&cep->lock);
/* Save skb pointer. */
- idx = cep->skb_cur & TX_RING_MOD_MASK;
- if (cep->tx_skbuff[idx]) {
- /* This should never happen (any more).
- Leave the sanity check in for now... */
- printk(KERN_ERR "EEP. cep->tx_skbuff[%d] is %p not NULL in %s\n",
- idx, cep->tx_skbuff[idx], __func__);
- printk(KERN_ERR "Expect to lose %d bytes of sock space",
- cep->tx_skbuff[idx]->truesize);
- }
- cep->tx_skbuff[idx] = skb;
+ cep->tx_skbuff[cep->skb_cur] = skb;
cep->stats.tx_bytes += skb->len;
- cep->skb_cur++;
-
- atomic_inc(&cep->n_pkts);
+ cep->skb_cur = (cep->skb_cur+1) & TX_RING_MOD_MASK;
/* Send it on its way. Tell CPM its ready, interrupt when done,
* its the last BD of the frame, and to put the CRC on the end.
@@ -440,14 +478,8 @@ fcc_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
else
bdp++;
-
- /* If the tx_ring is full, stop the queue */
- if (atomic_read(&cep->n_pkts) >= (TX_RING_SIZE-1)) {
- if (!netif_queue_stopped(dev)) {
- netif_stop_queue(dev);
- cep->tx_full = 1;
- }
- }
+ if (!--cep->tx_free)
+ netif_stop_queue(dev);
cep->cur_tx = (cbd_t *)bdp;
@@ -468,8 +500,8 @@ fcc_enet_timeout(struct net_device *dev)
{
int i;
cbd_t *bdp;
- printk(" Ring data dump: cur_tx %p%s cur_rx %p.\n",
- cep->cur_tx, cep->tx_full ? " (full)" : "",
+ printk(" Ring data dump: cur_tx %p tx_free %d cur_rx %p.\n",
+ cep->cur_tx, cep->tx_free,
cep->cur_rx);
bdp = cep->tx_bd_base;
printk(" Tx @base %p :\n", bdp);
@@ -487,7 +519,7 @@ fcc_enet_timeout(struct net_device *dev)
bdp->cbd_bufaddr);
}
#endif
- if (!cep->tx_full)
+ if (cep->tx_free)
netif_wake_queue(dev);
}
@@ -500,16 +532,22 @@ fcc_enet_interrupt(int irq, void * dev_id, struct pt_regs * regs)
volatile cbd_t *bdp;
ushort int_events;
int must_restart;
- int idx;
cep = (struct fcc_enet_private *)dev->priv;
/* Get the interrupt events that caused us to be here.
*/
int_events = cep->fccp->fcc_fcce;
- cep->fccp->fcc_fcce = int_events;
+ cep->fccp->fcc_fcce = (int_events & cep->fccp->fcc_fccm);
must_restart = 0;
+#ifdef PHY_INTERRUPT
+ /* We have to be careful here to make sure that we aren't
+ * interrupted by a PHY interrupt.
+ */
+ disable_irq_nosync(PHY_INTERRUPT);
+#endif
+
/* Handle receive event in its own function.
*/
if (int_events & FCC_ENET_RXF)
@@ -530,7 +568,7 @@ fcc_enet_interrupt(int irq, void * dev_id, struct pt_regs * regs)
spin_lock(&cep->lock);
bdp = cep->dirty_tx;
while ((bdp->cbd_sc&BD_ENET_TX_READY)==0) {
- if ((bdp==cep->cur_tx) && (cep->tx_full == 0))
+ if (cep->tx_free == TX_RING_SIZE)
break;
if (bdp->cbd_sc & BD_ENET_TX_HB) /* No heartbeat */
@@ -563,12 +601,9 @@ fcc_enet_interrupt(int irq, void * dev_id, struct pt_regs * regs)
cep->stats.collisions++;
/* Free the sk buffer associated with this last transmit. */
- idx = cep->skb_dirty & TX_RING_MOD_MASK;
- dev_kfree_skb_irq(cep->tx_skbuff[idx]);
- cep->tx_skbuff[idx] = NULL;
- cep->skb_dirty++;
-
- atomic_dec(&cep->n_pkts);
+ dev_kfree_skb_irq(cep->tx_skbuff[cep->skb_dirty]);
+ cep->tx_skbuff[cep->skb_dirty] = NULL;
+ cep->skb_dirty = (cep->skb_dirty + 1) & TX_RING_MOD_MASK;
/* Update pointer to next buffer descriptor to be transmitted. */
if (bdp->cbd_sc & BD_ENET_TX_WRAP)
@@ -588,8 +623,7 @@ fcc_enet_interrupt(int irq, void * dev_id, struct pt_regs * regs)
/* Since we have freed up a buffer, the ring is no longer
* full.
*/
- if (cep->tx_full) {
- cep->tx_full = 0;
+ if (!cep->tx_free++) {
if (netif_queue_stopped(dev)) {
netif_wake_queue(dev);
}
@@ -626,8 +660,13 @@ fcc_enet_interrupt(int irq, void * dev_id, struct pt_regs * regs)
* put them.
*/
if (int_events & FCC_ENET_BSY) {
+ cep->fccp->fcc_fcce = FCC_ENET_BSY;
cep->stats.rx_dropped++;
}
+
+#ifdef PHY_INTERRUPT
+ enable_irq(PHY_INTERRUPT);
+#endif
return IRQ_HANDLED;
}
@@ -726,8 +765,16 @@ for (;;) {
static int
fcc_enet_close(struct net_device *dev)
{
- /* Don't know what to do yet. */
+#ifdef CONFIG_USE_MDIO
+ struct fcc_enet_private *fep = dev->priv;
+#endif
+
netif_stop_queue(dev);
+ fcc_stop(dev);
+#ifdef CONFIG_USE_MDIO
+ if (fep->phy)
+ mii_do_cmd(dev, fep->phy->shutdown);
+#endif
return 0;
}
@@ -784,15 +831,14 @@ static void mii_parse_sr(uint mii_reg, struct net_device *dev)
s &= ~(PHY_STAT_LINK | PHY_STAT_FAULT | PHY_STAT_ANC);
- if (mii_reg & 0x0004)
+ if (mii_reg & BMSR_LSTATUS)
s |= PHY_STAT_LINK;
- if (mii_reg & 0x0010)
+ if (mii_reg & BMSR_RFAULT)
s |= PHY_STAT_FAULT;
- if (mii_reg & 0x0020)
+ if (mii_reg & BMSR_ANEGCOMPLETE)
s |= PHY_STAT_ANC;
fep->phy_status = s;
- fep->link = (s & PHY_STAT_LINK) ? 1 : 0;
}
static void mii_parse_cr(uint mii_reg, struct net_device *dev)
@@ -802,9 +848,9 @@ static void mii_parse_cr(uint mii_reg, struct net_device *dev)
s &= ~(PHY_CONF_ANE | PHY_CONF_LOOP);
- if (mii_reg & 0x1000)
+ if (mii_reg & BMCR_ANENABLE)
s |= PHY_CONF_ANE;
- if (mii_reg & 0x4000)
+ if (mii_reg & BMCR_LOOPBACK)
s |= PHY_CONF_LOOP;
fep->phy_status = s;
@@ -817,17 +863,59 @@ static void mii_parse_anar(uint mii_reg, struct net_device *dev)
s &= ~(PHY_CONF_SPMASK);
- if (mii_reg & 0x0020)
+ if (mii_reg & ADVERTISE_10HALF)
s |= PHY_CONF_10HDX;
- if (mii_reg & 0x0040)
+ if (mii_reg & ADVERTISE_10FULL)
s |= PHY_CONF_10FDX;
- if (mii_reg & 0x0080)
+ if (mii_reg & ADVERTISE_100HALF)
s |= PHY_CONF_100HDX;
- if (mii_reg & 0x00100)
+ if (mii_reg & ADVERTISE_100FULL)
s |= PHY_CONF_100FDX;
fep->phy_status = s;
}
+
+/* ------------------------------------------------------------------------- */
+/* Generic PHY support. Should work for all PHYs, but does not support link
+ * change interrupts.
+ */
+#ifdef CONFIG_FCC_GENERIC_PHY
+
+static phy_info_t phy_info_generic = {
+ 0x00000000, /* 0-->match any PHY */
+ "GENERIC",
+
+ (const phy_cmd_t []) { /* config */
+ /* advertise only half-duplex capabilities */
+ { mk_mii_write(MII_ADVERTISE, MII_ADVERTISE_HALF),
+ mii_parse_anar },
+
+ /* enable auto-negotiation */
+ { mk_mii_write(MII_BMCR, BMCR_ANENABLE), mii_parse_cr },
+ { mk_mii_end, }
+ },
+ (const phy_cmd_t []) { /* startup */
+ /* restart auto-negotiation */
+ { mk_mii_write(MII_BMCR, BMCR_ANENABLE | BMCR_ANRESTART),
+ NULL },
+ { mk_mii_end, }
+ },
+ (const phy_cmd_t []) { /* ack_int */
+ /* We don't actually use the ack_int table with a generic
+ * PHY, but putting a reference to mii_parse_sr here keeps
+ * us from getting a compiler warning about unused static
+ * functions in the case where we only compile in generic
+ * PHY support.
+ */
+ { mk_mii_read(MII_BMSR), mii_parse_sr },
+ { mk_mii_end, }
+ },
+ (const phy_cmd_t []) { /* shutdown */
+ { mk_mii_end, }
+ },
+};
+#endif /* ifdef CONFIG_FCC_GENERIC_PHY */
+
/* ------------------------------------------------------------------------- */
/* The Level one LXT970 is used by many boards */
@@ -867,26 +955,26 @@ static phy_info_t phy_info_lxt970 = {
(const phy_cmd_t []) { /* config */
#if 0
-// { mk_mii_write(MII_REG_ANAR, 0x0021), NULL },
+// { mk_mii_write(MII_ADVERTISE, 0x0021), NULL },
/* Set default operation of 100-TX....for some reason
* some of these bits are set on power up, which is wrong.
*/
{ mk_mii_write(MII_LXT970_CONFIG, 0), NULL },
#endif
- { mk_mii_read(MII_REG_CR), mii_parse_cr },
- { mk_mii_read(MII_REG_ANAR), mii_parse_anar },
+ { mk_mii_read(MII_BMCR), mii_parse_cr },
+ { mk_mii_read(MII_ADVERTISE), mii_parse_anar },
{ mk_mii_end, }
},
(const phy_cmd_t []) { /* startup - enable interrupts */
{ mk_mii_write(MII_LXT970_IER, 0x0002), NULL },
- { mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */
+ { mk_mii_write(MII_BMCR, 0x1200), NULL }, /* autonegotiate */
{ mk_mii_end, }
},
(const phy_cmd_t []) { /* ack_int */
/* read SR and ISR to acknowledge */
- { mk_mii_read(MII_REG_SR), mii_parse_sr },
+ { mk_mii_read(MII_BMSR), mii_parse_sr },
{ mk_mii_read(MII_LXT970_ISR), NULL },
/* find out the current status */
@@ -951,30 +1039,29 @@ static phy_info_t phy_info_lxt971 = {
"LXT971",
(const phy_cmd_t []) { /* config */
-// { mk_mii_write(MII_REG_ANAR, 0x021), NULL }, /* 10 Mbps, HD */
- { mk_mii_read(MII_REG_CR), mii_parse_cr },
- { mk_mii_read(MII_REG_ANAR), mii_parse_anar },
+ /* configure link capabilities to advertise */
+ { mk_mii_write(MII_ADVERTISE, MII_ADVERTISE_DEFAULT),
+ mii_parse_anar },
+
+ /* enable auto-negotiation */
+ { mk_mii_write(MII_BMCR, BMCR_ANENABLE), mii_parse_cr },
{ mk_mii_end, }
},
(const phy_cmd_t []) { /* startup - enable interrupts */
{ mk_mii_write(MII_LXT971_IER, 0x00f2), NULL },
- { mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */
-
- /* Somehow does the 971 tell me that the link is down
- * the first read after power-up.
- * read here to get a valid value in ack_int */
- { mk_mii_read(MII_REG_SR), mii_parse_sr },
+ /* restart auto-negotiation */
+ { mk_mii_write(MII_BMCR, BMCR_ANENABLE | BMCR_ANRESTART),
+ NULL },
{ mk_mii_end, }
},
(const phy_cmd_t []) { /* ack_int */
/* find out the current status */
-
- { mk_mii_read(MII_REG_SR), mii_parse_sr },
+ { mk_mii_read(MII_BMSR), NULL },
+ { mk_mii_read(MII_BMSR), mii_parse_sr },
{ mk_mii_read(MII_LXT971_SR2), mii_parse_lxt971_sr2 },
/* we only need to read ISR to acknowledge */
-
{ mk_mii_read(MII_LXT971_ISR), NULL },
{ mk_mii_end, }
},
@@ -984,8 +1071,7 @@ static phy_info_t phy_info_lxt971 = {
},
};
-#endif /* CONFIG_FEC_LXT970 */
-
+#endif /* CONFIG_FCC_LXT971 */
/* ------------------------------------------------------------------------- */
/* The Quality Semiconductor QS6612 is used on the RPX CLLF */
@@ -1023,7 +1109,7 @@ static phy_info_t phy_info_qs6612 = {
"QS6612",
(const phy_cmd_t []) { /* config */
-// { mk_mii_write(MII_REG_ANAR, 0x061), NULL }, /* 10 Mbps */
+// { mk_mii_write(MII_ADVERTISE, 0x061), NULL }, /* 10 Mbps */
/* The PHY powers up isolated on the RPX,
* so send a command to allow operation.
@@ -1033,13 +1119,13 @@ static phy_info_t phy_info_qs6612 = {
/* parse cr and anar to get some info */
- { mk_mii_read(MII_REG_CR), mii_parse_cr },
- { mk_mii_read(MII_REG_ANAR), mii_parse_anar },
+ { mk_mii_read(MII_BMCR), mii_parse_cr },
+ { mk_mii_read(MII_ADVERTISE), mii_parse_anar },
{ mk_mii_end, }
},
(const phy_cmd_t []) { /* startup - enable interrupts */
{ mk_mii_write(MII_QS6612_IMR, 0x003a), NULL },
- { mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */
+ { mk_mii_write(MII_BMCR, 0x1200), NULL }, /* autonegotiate */
{ mk_mii_end, }
},
(const phy_cmd_t []) { /* ack_int */
@@ -1047,8 +1133,8 @@ static phy_info_t phy_info_qs6612 = {
/* we need to read ISR, SR and ANER to acknowledge */
{ mk_mii_read(MII_QS6612_ISR), NULL },
- { mk_mii_read(MII_REG_SR), mii_parse_sr },
- { mk_mii_read(MII_REG_ANER), NULL },
+ { mk_mii_read(MII_BMSR), mii_parse_sr },
+ { mk_mii_read(MII_EXPANSION), NULL },
/* read pcr to get info */
@@ -1102,13 +1188,13 @@ static phy_info_t phy_info_dm9131 = {
(const phy_cmd_t []) { /* config */
/* parse cr and anar to get some info */
- { mk_mii_read(MII_REG_CR), mii_parse_cr },
- { mk_mii_read(MII_REG_ANAR), mii_parse_anar },
+ { mk_mii_read(MII_BMCR), mii_parse_cr },
+ { mk_mii_read(MII_ADVERTISE), mii_parse_anar },
{ mk_mii_end, }
},
(const phy_cmd_t []) { /* startup - enable interrupts */
{ mk_mii_write(MII_DM9131_INTR, 0x0002), NULL },
- { mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */
+ { mk_mii_write(MII_BMCR, 0x1200), NULL }, /* autonegotiate */
{ mk_mii_end, }
},
(const phy_cmd_t []) { /* ack_int */
@@ -1116,8 +1202,8 @@ static phy_info_t phy_info_dm9131 = {
/* we need to read INTR, SR and ANER to acknowledge */
{ mk_mii_read(MII_DM9131_INTR), NULL },
- { mk_mii_read(MII_REG_SR), mii_parse_sr },
- { mk_mii_read(MII_REG_ANER), NULL },
+ { mk_mii_read(MII_BMSR), mii_parse_sr },
+ { mk_mii_read(MII_EXPANSION), NULL },
/* read acsr to get info */
@@ -1132,7 +1218,147 @@ static phy_info_t phy_info_dm9131 = {
#endif /* CONFIG_FEC_DM9131 */
+#ifdef CONFIG_FCC_DM9161
+/* ------------------------------------------------------------------------- */
+/* DM9161 Control register values */
+#define MIIM_DM9161_CR_STOP 0x0400
+#define MIIM_DM9161_CR_RSTAN 0x1200
+
+#define MIIM_DM9161_SCR 0x10
+#define MIIM_DM9161_SCR_INIT 0x0610
+
+/* DM9161 Specified Configuration and Status Register */
+#define MIIM_DM9161_SCSR 0x11
+#define MIIM_DM9161_SCSR_100F 0x8000
+#define MIIM_DM9161_SCSR_100H 0x4000
+#define MIIM_DM9161_SCSR_10F 0x2000
+#define MIIM_DM9161_SCSR_10H 0x1000
+/* DM9161 10BT register */
+#define MIIM_DM9161_10BTCSR 0x12
+#define MIIM_DM9161_10BTCSR_INIT 0x7800
+/* DM9161 Interrupt Register */
+#define MIIM_DM9161_INTR 0x15
+#define MIIM_DM9161_INTR_PEND 0x8000
+#define MIIM_DM9161_INTR_DPLX_MASK 0x0800
+#define MIIM_DM9161_INTR_SPD_MASK 0x0400
+#define MIIM_DM9161_INTR_LINK_MASK 0x0200
+#define MIIM_DM9161_INTR_MASK 0x0100
+#define MIIM_DM9161_INTR_DPLX_CHANGE 0x0010
+#define MIIM_DM9161_INTR_SPD_CHANGE 0x0008
+#define MIIM_DM9161_INTR_LINK_CHANGE 0x0004
+#define MIIM_DM9161_INTR_INIT 0x0000
+#define MIIM_DM9161_INTR_STOP \
+(MIIM_DM9161_INTR_DPLX_MASK | MIIM_DM9161_INTR_SPD_MASK \
+ | MIIM_DM9161_INTR_LINK_MASK | MIIM_DM9161_INTR_MASK)
+
+static void mii_parse_dm9161_sr(uint mii_reg, struct net_device * dev)
+{
+ volatile struct fcc_enet_private *fep = dev->priv;
+ uint regstat, timeout=0xffff;
+ while(!(mii_reg & 0x0020) && timeout--)
+ {
+ regstat=mk_mii_read(MII_BMSR);
+ regstat |= fep->phy_addr <<23;
+ mii_reg = mii_send_receive(fep->fip,regstat);
+ }
+
+ mii_parse_sr(mii_reg, dev);
+}
+
+static void mii_parse_dm9161_scsr(uint mii_reg, struct net_device * dev)
+{
+ volatile struct fcc_enet_private *fep = dev->priv;
+ uint s = fep->phy_status;
+
+ s &= ~(PHY_STAT_SPMASK);
+ switch((mii_reg >>12) & 0xf) {
+ case 1:
+ {
+ s |= PHY_STAT_10HDX;
+ printk("10BaseT Half Duplex\n");
+ break;
+ }
+ case 2:
+ {
+ s |= PHY_STAT_10FDX;
+ printk("10BaseT Full Duplex\n");
+ break;
+ }
+ case 4:
+ {
+ s |= PHY_STAT_100HDX;
+ printk("100BaseT Half Duplex\n");
+ break;
+ }
+ case 8:
+ {
+ s |= PHY_STAT_100FDX;
+ printk("100BaseT Full Duplex\n");
+ break;
+ }
+ }
+
+ fep->phy_status = s;
+
+}
+
+static void mii_dm9161_wait(uint mii_reg, struct net_device *dev)
+{
+ int timeout = HZ;
+
+ /* Davicom takes a bit to come up after a reset,
+ * so wait here for a bit */
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(timeout);
+}
+
+static phy_info_t phy_info_dm9161 = {
+ 0x00181b88,
+ "Davicom DM9161E",
+ (const phy_cmd_t[]) { /* config */
+ { mk_mii_write(MII_BMCR, MIIM_DM9161_CR_STOP), NULL},
+ /* Do not bypass the scrambler/descrambler */
+ { mk_mii_write(MIIM_DM9161_SCR, MIIM_DM9161_SCR_INIT), NULL},
+ /* Configure 10BTCSR register */
+ { mk_mii_write(MIIM_DM9161_10BTCSR, MIIM_DM9161_10BTCSR_INIT),NULL},
+ /* Configure some basic stuff */
+ { mk_mii_write(MII_BMCR, 0x1000), NULL},
+ { mk_mii_read(MII_BMCR), mii_parse_cr },
+ { mk_mii_read(MII_ADVERTISE), mii_parse_anar },
+ { mk_mii_end,}
+ },
+ (const phy_cmd_t[]) { /* startup */
+ /* Restart Auto Negotiation */
+ { mk_mii_write(MII_BMCR, MIIM_DM9161_CR_RSTAN), NULL},
+ /* Status is read once to clear old link state */
+ { mk_mii_read(MII_BMSR), mii_dm9161_wait},
+ /* Auto-negotiate */
+ { mk_mii_read(MII_BMSR), mii_parse_dm9161_sr},
+ /* Read the status */
+ { mk_mii_read(MIIM_DM9161_SCSR), mii_parse_dm9161_scsr},
+ /* Clear any pending interrupts */
+ { mk_mii_read(MIIM_DM9161_INTR), NULL},
+ /* Enable Interrupts */
+ { mk_mii_write(MIIM_DM9161_INTR, MIIM_DM9161_INTR_INIT), NULL},
+ { mk_mii_end,}
+ },
+ (const phy_cmd_t[]) { /* ack_int */
+ { mk_mii_read(MIIM_DM9161_INTR), NULL},
+#if 0
+ { mk_mii_read(MII_BMSR), NULL},
+ { mk_mii_read(MII_BMSR), mii_parse_dm9161_sr},
+ { mk_mii_read(MIIM_DM9161_SCSR), mii_parse_dm9161_scsr},
+#endif
+ { mk_mii_end,}
+ },
+ (const phy_cmd_t[]) { /* shutdown */
+ { mk_mii_read(MIIM_DM9161_INTR),NULL},
+ { mk_mii_write(MIIM_DM9161_INTR, MIIM_DM9161_INTR_STOP), NULL},
+ { mk_mii_end,}
+ },
+};
+#endif /* CONFIG_FCC_DM9161 */
static phy_info_t *phy_info[] = {
@@ -1152,11 +1378,24 @@ static phy_info_t *phy_info[] = {
&phy_info_dm9131,
#endif /* CONFIG_FEC_DM9131 */
+#ifdef CONFIG_FCC_DM9161
+ &phy_info_dm9161,
+#endif /* CONFIG_FCC_DM9161 */
+
+#ifdef CONFIG_FCC_GENERIC_PHY
+ /* Generic PHY support. This must be the last PHY in the table.
+ * It will be used to support any PHY that doesn't match a previous
+ * entry in the table.
+ */
+ &phy_info_generic,
+#endif /* CONFIG_FCC_GENERIC_PHY */
+
NULL
};
-static void mii_display_status(struct net_device *dev)
+static void mii_display_status(void *data)
{
+ struct net_device *dev = data;
volatile struct fcc_enet_private *fep = dev->priv;
uint s = fep->phy_status;
@@ -1191,8 +1430,9 @@ static void mii_display_status(struct net_device *dev)
printk(".\n");
}
-static void mii_display_config(struct net_device *dev)
+static void mii_display_config(void *data)
{
+ struct net_device *dev = data;
volatile struct fcc_enet_private *fep = dev->priv;
uint s = fep->phy_status;
@@ -1225,20 +1465,23 @@ static void mii_display_config(struct net_device *dev)
static void mii_relink(struct net_device *dev)
{
struct fcc_enet_private *fep = dev->priv;
- int duplex;
+ int duplex = 0;
- fep->link = (fep->phy_status & PHY_STAT_LINK) ? 1 : 0;
- mii_display_status(dev);
fep->old_link = fep->link;
+ fep->link = (fep->phy_status & PHY_STAT_LINK) ? 1 : 0;
+
+#ifdef MDIO_DEBUG
+ printk(" mii_relink: link=%d\n", fep->link);
+#endif
if (fep->link) {
- duplex = 0;
if (fep->phy_status
& (PHY_STAT_100FDX | PHY_STAT_10FDX))
duplex = 1;
fcc_restart(dev, duplex);
- } else {
- fcc_stop(dev);
+#ifdef MDIO_DEBUG
+ printk(" mii_relink: duplex=%d\n", duplex);
+#endif
}
}
@@ -1246,25 +1489,21 @@ static void mii_queue_relink(uint mii_reg, struct net_device *dev)
{
struct fcc_enet_private *fep = dev->priv;
- fep->phy_task.routine = (void *)mii_relink;
- fep->phy_task.data = dev;
- schedule_task(&fep->phy_task);
+ mii_relink(dev);
+
+ schedule_work(&fep->phy_relink);
}
static void mii_queue_config(uint mii_reg, struct net_device *dev)
{
struct fcc_enet_private *fep = dev->priv;
- fep->phy_task.routine = (void *)mii_display_config;
- fep->phy_task.data = dev;
- schedule_task(&fep->phy_task);
+ schedule_work(&fep->phy_display_config);
}
-
-
-phy_cmd_t phy_cmd_relink[] = { { mk_mii_read(MII_REG_CR), mii_queue_relink },
+phy_cmd_t phy_cmd_relink[] = { { mk_mii_read(MII_BMCR), mii_queue_relink },
{ mk_mii_end, } };
-phy_cmd_t phy_cmd_config[] = { { mk_mii_read(MII_REG_CR), mii_queue_config },
+phy_cmd_t phy_cmd_config[] = { { mk_mii_read(MII_BMCR), mii_queue_config },
{ mk_mii_end, } };
@@ -1277,10 +1516,11 @@ mii_discover_phy3(uint mii_reg, struct net_device *dev)
int i;
fep = dev->priv;
+ printk("mii_reg: %08x\n", mii_reg);
fep->phy_id |= (mii_reg & 0xffff);
for(i = 0; phy_info[i]; i++)
- if(phy_info[i]->id == (fep->phy_id >> 4))
+ if((phy_info[i]->id == (fep->phy_id >> 4)) || !phy_info[i]->id)
break;
if(!phy_info[i])
@@ -1288,6 +1528,7 @@ mii_discover_phy3(uint mii_reg, struct net_device *dev)
dev->name, fep->phy_id);
fep->phy = phy_info[i];
+ fep->phy_id_done = 1;
printk("%s: Phy @ 0x%x, type %s (0x%08x)\n",
dev->name, fep->phy_addr, fep->phy->name, fep->phy_id);
@@ -1304,36 +1545,49 @@ mii_discover_phy(uint mii_reg, struct net_device *dev)
fep = dev->priv;
- if ((phytype = (mii_reg & 0xfff)) != 0xfff) {
+ if ((phytype = (mii_reg & 0xffff)) != 0xffff) {
/* Got first part of ID, now get remainder. */
fep->phy_id = phytype << 16;
- mii_queue(dev, mk_mii_read(MII_REG_PHYIR2), mii_discover_phy3);
+ mii_queue(dev, mk_mii_read(MII_PHYSID2), mii_discover_phy3);
} else {
fep->phy_addr++;
if (fep->phy_addr < 32) {
- mii_queue(dev, mk_mii_read(MII_REG_PHYIR1),
+ mii_queue(dev, mk_mii_read(MII_PHYSID1),
mii_discover_phy);
} else {
printk("fec: No PHY device found.\n");
}
}
}
+#endif /* CONFIG_USE_MDIO */
+#ifdef PHY_INTERRUPT
/* This interrupt occurs when the PHY detects a link change. */
static irqreturn_t
mii_link_interrupt(int irq, void * dev_id, struct pt_regs * regs)
{
struct net_device *dev = dev_id;
struct fcc_enet_private *fep = dev->priv;
+ fcc_info_t *fip = fep->fip;
+
+ if (fep->phy) {
+ /* We don't want to be interrupted by an FCC
+ * interrupt here.
+ */
+ disable_irq_nosync(fip->fc_interrupt);
- mii_do_cmd(dev, fep->phy->ack_int);
- mii_do_cmd(dev, phy_cmd_relink); /* restart and display status */
+ mii_do_cmd(dev, fep->phy->ack_int);
+ /* restart and display status */
+ mii_do_cmd(dev, phy_cmd_relink);
+
+ enable_irq(fip->fc_interrupt);
+ }
return IRQ_HANDLED;
}
+#endif /* ifdef PHY_INTERRUPT */
-#endif /* CONFIG_USE_MDIO */
-
+#if 0 /* This should be fixed someday */
/* Set or clear the multicast filter for this adaptor.
* Skeleton taken from sunlance driver.
* The CPM Ethernet implementation allows Multicast as well as individual
@@ -1383,8 +1637,8 @@ return;
dmi = dev->mc_list;
- for (i=0; i<dev->mc_count; i++) {
-
+ for (i=0; i<dev->mc_count; i++, dmi = dmi->next) {
+
/* Only support group multicast for now.
*/
if (!(dmi->dmi_addr[0] & 1))
@@ -1411,6 +1665,7 @@ return;
}
}
}
+#endif /* if 0 */
/* Set the individual MAC address.
@@ -1482,7 +1737,7 @@ static int __init fec_enet_init(void)
dev->watchdog_timeo = TX_TIMEOUT;
dev->stop = fcc_enet_close;
dev->get_stats = fcc_enet_get_stats;
- dev->set_multicast_list = set_multicast_list;
+ /* dev->set_multicast_list = set_multicast_list; */
dev->set_mac_address = fcc_enet_set_mac_address;
init_fcc_startup(fip, dev);
@@ -1502,8 +1757,11 @@ static int __init fec_enet_init(void)
/* Queue up command to detect the PHY and initialize the
* remainder of the interface.
*/
- cep->phy_addr = 0;
- mii_queue(dev, mk_mii_read(MII_REG_PHYIR1), mii_discover_phy);
+ cep->phy_id_done = 0;
+ cep->phy_addr = fip->fc_phyaddr;
+ mii_queue(dev, mk_mii_read(MII_PHYSID1), mii_discover_phy);
+ INIT_WORK(&cep->phy_relink, mii_display_status, dev);
+ INIT_WORK(&cep->phy_display_config, mii_display_config, dev);
#endif /* CONFIG_USE_MDIO */
fip++;
@@ -1549,29 +1807,36 @@ init_fcc_ioports(fcc_info_t *fip, volatile iop_cpm2_t *io,
if (fip->fc_proff == PROFF_FCC1) {
/* Configure port A and C pins for FCC1 Ethernet.
*/
- io->iop_pdira &= ~PA1_DIRA0;
- io->iop_pdira |= PA1_DIRA1;
- io->iop_psora &= ~PA1_PSORA0;
- io->iop_psora |= PA1_PSORA1;
- io->iop_ppara |= (PA1_DIRA0 | PA1_DIRA1);
+ io->iop_pdira &= ~PA1_DIRA_BOUT;
+ io->iop_pdira |= PA1_DIRA_BIN;
+ io->iop_psora &= ~PA1_PSORA_BOUT;
+ io->iop_psora |= PA1_PSORA_BIN;
+ io->iop_ppara |= (PA1_DIRA_BOUT | PA1_DIRA_BIN);
}
if (fip->fc_proff == PROFF_FCC2) {
/* Configure port B and C pins for FCC Ethernet.
*/
- io->iop_pdirb &= ~PB2_DIRB0;
- io->iop_pdirb |= PB2_DIRB1;
- io->iop_psorb &= ~PB2_PSORB0;
- io->iop_psorb |= PB2_PSORB1;
- io->iop_pparb |= (PB2_DIRB0 | PB2_DIRB1);
+ io->iop_pdirb &= ~PB2_DIRB_BOUT;
+ io->iop_pdirb |= PB2_DIRB_BIN;
+ io->iop_psorb &= ~PB2_PSORB_BOUT;
+ io->iop_psorb |= PB2_PSORB_BIN;
+ io->iop_pparb |= (PB2_DIRB_BOUT | PB2_DIRB_BIN);
}
if (fip->fc_proff == PROFF_FCC3) {
/* Configure port B and C pins for FCC Ethernet.
*/
- io->iop_pdirb &= ~PB3_DIRB0;
- io->iop_pdirb |= PB3_DIRB1;
- io->iop_psorb &= ~PB3_PSORB0;
- io->iop_psorb |= PB3_PSORB1;
- io->iop_pparb |= (PB3_DIRB0 | PB3_DIRB1);
+ io->iop_pdirb &= ~PB3_DIRB_BOUT;
+ io->iop_pdirb |= PB3_DIRB_BIN;
+ io->iop_psorb &= ~PB3_PSORB_BOUT;
+ io->iop_psorb |= PB3_PSORB_BIN;
+ io->iop_pparb |= (PB3_DIRB_BOUT | PB3_DIRB_BIN);
+
+ io->iop_pdirc &= ~PC3_DIRC_BOUT;
+ io->iop_pdirc |= PC3_DIRC_BIN;
+ io->iop_psorc &= ~PC3_PSORC_BOUT;
+ io->iop_psorc |= PC3_PSORC_BIN;
+ io->iop_pparc |= (PC3_DIRC_BOUT | PC3_DIRC_BIN);
+
}
/* Port C has clocks......
@@ -1699,6 +1964,11 @@ init_fcc_param(fcc_info_t *fip, struct net_device *dev,
*/
eap = (unsigned char *)&(ep->fen_paddrh);
for (i=5; i>=0; i--) {
+
+/*
+ * The EP8260 only uses FCC3, so we can safely give it the real
+ * MAC address.
+ */
#ifdef CONFIG_SBC82xx
if (i == 5) {
/* bd->bi_enetaddr holds the SCC0 address; the FCC
@@ -1708,15 +1978,17 @@ init_fcc_param(fcc_info_t *fip, struct net_device *dev,
*eap++ = dev->dev_addr[i];
}
#else
+#ifndef CONFIG_RPX8260
if (i == 3) {
dev->dev_addr[i] = bd->bi_enetaddr[i];
dev->dev_addr[i] |= (1 << (7 - fip->fc_fccnum));
*eap++ = dev->dev_addr[i];
- }
+ } else
#endif
- else {
+ {
*eap++ = dev->dev_addr[i] = bd->bi_enetaddr[i];
}
+#endif
}
ep->fen_taddrh = 0;
@@ -1798,7 +2070,6 @@ init_fcc_param(fcc_info_t *fip, struct net_device *dev,
while (cp->cp_cpcr & CPM_CR_FLG);
cep->skb_cur = cep->skb_dirty = 0;
- atomic_set(&cep->n_pkts, 0);
}
/* Let 'er rip.
@@ -1812,25 +2083,56 @@ init_fcc_startup(fcc_info_t *fip, struct net_device *dev)
cep = (struct fcc_enet_private *)(dev->priv);
fccp = cep->fccp;
+#ifdef CONFIG_RPX8260
+#ifdef PHY_INTERRUPT
+ /* Route PHY interrupt to IRQ. The following code only works for
+ * IRQ1 - IRQ7. It does not work for Port C interrupts.
+ */
+ *((volatile u_char *) (RPX_CSR_ADDR + 13)) &= ~BCSR13_FETH_IRQMASK;
+ *((volatile u_char *) (RPX_CSR_ADDR + 13)) |=
+ ((PHY_INTERRUPT - SIU_INT_IRQ1 + 1) << 4);
+#endif
+ /* Initialize MDIO pins. */
+ *((volatile u_char *) (RPX_CSR_ADDR + 4)) &= ~BCSR4_MII_MDC;
+ *((volatile u_char *) (RPX_CSR_ADDR + 4)) |=
+ BCSR4_MII_READ | BCSR4_MII_MDIO;
+ /* Enable external LXT971 PHY. */
+ *((volatile u_char *) (RPX_CSR_ADDR + 4)) |= BCSR4_EN_PHY;
+ udelay(1000);
+ *((volatile u_char *) (RPX_CSR_ADDR+ 4)) |= BCSR4_EN_MII;
+ udelay(1000);
+#endif /* ifdef CONFIG_RPX8260 */
+
fccp->fcc_fcce = 0xffff; /* Clear any pending events */
- /* Enable interrupts for transmit error, complete frame
- * received, and any transmit buffer we have also set the
- * interrupt flag.
+ /* Leave FCC interrupts masked for now. Will be unmasked by
+ * fcc_restart().
*/
- fccp->fcc_fccm = (FCC_ENET_TXE | FCC_ENET_RXF | FCC_ENET_TXB);
+ fccp->fcc_fccm = 0;
/* Install our interrupt handler.
*/
- if (request_irq(fip->fc_interrupt, fcc_enet_interrupt, 0,
- "fenet", dev) < 0)
+ if (request_irq(fip->fc_interrupt, fcc_enet_interrupt, 0, "fenet",
+ dev) < 0)
printk("Can't get FCC IRQ %d\n", fip->fc_interrupt);
-#ifdef CONFIG_USE_MDIO
+#ifdef PHY_INTERRUPT
+#ifdef CONFIG_ADS8272
+ if (request_irq(PHY_INTERRUPT, mii_link_interrupt, SA_SHIRQ,
+ "mii", dev) < 0)
+ printk(KERN_CRIT "Can't get MII IRQ %d\n", PHY_INTERRUPT);
+#else
+ /* Make IRQn edge triggered. This does not work if PHY_INTERRUPT is
+ * on Port C.
+ */
+ ((volatile cpm2_map_t *) CPM_MAP_ADDR)->im_intctl.ic_siexr |=
+ (1 << (14 - (PHY_INTERRUPT - SIU_INT_IRQ1)));
+
if (request_irq(PHY_INTERRUPT, mii_link_interrupt, 0,
"mii", dev) < 0)
- printk("Can't get MII IRQ %d\n", fip->fc_interrupt);
-#endif /* CONFIG_USE_MDIO */
+ printk(KERN_CRIT "Can't get MII IRQ %d\n", PHY_INTERRUPT);
+#endif
+#endif /* PHY_INTERRUPT */
/* Set GFMR to enable Ethernet operating mode.
*/
@@ -1847,10 +2149,14 @@ init_fcc_startup(fcc_info_t *fip, struct net_device *dev)
fccp->fcc_fpsmr = FCC_PSMR_ENCRC;
#ifdef CONFIG_PQ2ADS
- /* Enable the PHY.
- */
- *(volatile uint *)(BCSR_ADDR + 4) &= ~BCSR1_FETHIEN;
- *(volatile uint *)(BCSR_ADDR + 4) |= BCSR1_FETH_RST;
+ /* Enable the PHY. */
+ *(volatile uint *)(BCSR_ADDR + 4) &= ~BCSR1_FETHIEN;
+ *(volatile uint *)(BCSR_ADDR + 4) |= BCSR1_FETH_RST;
+#endif
+#if defined(CONFIG_PQ2ADS) || defined(CONFIG_PQ2FADS)
+ /* Enable the 2nd PHY. */
+ *(volatile uint *)(BCSR_ADDR + 12) &= ~BCSR3_FETHIEN2;
+ *(volatile uint *)(BCSR_ADDR + 12) |= BCSR3_FETH2_RST;
#endif
#if defined(CONFIG_USE_MDIO) || defined(CONFIG_TQM8260)
@@ -1872,54 +2178,74 @@ init_fcc_startup(fcc_info_t *fip, struct net_device *dev)
* I wonder what "they" were thinking (maybe weren't) when they leave
* the I2C in the CPM but I have to toggle these bits......
*/
-
-#define FCC_PDATC_MDIO(bit) \
- if (bit) \
- io->iop_pdatc |= fip->fc_mdio; \
- else \
- io->iop_pdatc &= ~fip->fc_mdio;
-
-#define FCC_PDATC_MDC(bit) \
- if (bit) \
- io->iop_pdatc |= fip->fc_mdck; \
- else \
- io->iop_pdatc &= ~fip->fc_mdck;
+#ifdef CONFIG_RPX8260
+ /* The EP8260 has the MDIO pins in a BCSR instead of on Port C
+ * like most other boards.
+ */
+#define MDIO_ADDR ((volatile u_char *)(RPX_CSR_ADDR + 4))
+#define MAKE_MDIO_OUTPUT *MDIO_ADDR &= ~BCSR4_MII_READ
+#define MAKE_MDIO_INPUT *MDIO_ADDR |= BCSR4_MII_READ | BCSR4_MII_MDIO
+#define OUT_MDIO(bit) \
+ if (bit) \
+ *MDIO_ADDR |= BCSR4_MII_MDIO; \
+ else \
+ *MDIO_ADDR &= ~BCSR4_MII_MDIO;
+#define IN_MDIO (*MDIO_ADDR & BCSR4_MII_MDIO)
+#define OUT_MDC(bit) \
+ if (bit) \
+ *MDIO_ADDR |= BCSR4_MII_MDC; \
+ else \
+ *MDIO_ADDR &= ~BCSR4_MII_MDC;
+#else /* ifdef CONFIG_RPX8260 */
+ /* This is for the usual case where the MDIO pins are on Port C.
+ */
+#define MDIO_ADDR (((volatile cpm2_map_t *)CPM_MAP_ADDR)->im_ioport)
+#define MAKE_MDIO_OUTPUT MDIO_ADDR.iop_pdirc |= fip->fc_mdio
+#define MAKE_MDIO_INPUT MDIO_ADDR.iop_pdirc &= ~fip->fc_mdio
+#define OUT_MDIO(bit) \
+ if (bit) \
+ MDIO_ADDR.iop_pdatc |= fip->fc_mdio; \
+ else \
+ MDIO_ADDR.iop_pdatc &= ~fip->fc_mdio;
+#define IN_MDIO ((MDIO_ADDR.iop_pdatc) & fip->fc_mdio)
+#define OUT_MDC(bit) \
+ if (bit) \
+ MDIO_ADDR.iop_pdatc |= fip->fc_mdck; \
+ else \
+ MDIO_ADDR.iop_pdatc &= ~fip->fc_mdck;
+#endif /* ifdef CONFIG_RPX8260 */
static uint
mii_send_receive(fcc_info_t *fip, uint cmd)
{
uint retval;
int read_op, i, off;
- volatile cpm2_map_t *immap;
- volatile iop_cpm2_t *io;
-
- immap = (cpm2_map_t *)CPM_MAP_ADDR;
- io = &immap->im_ioport;
-
- io->iop_pdirc |= (fip->fc_mdio | fip->fc_mdck);
+ const int us = 1;
read_op = ((cmd & 0xf0000000) == 0x60000000);
/* Write preamble
*/
+ OUT_MDIO(1);
+ MAKE_MDIO_OUTPUT;
+ OUT_MDIO(1);
for (i = 0; i < 32; i++)
{
- FCC_PDATC_MDC(0);
- FCC_PDATC_MDIO(1);
- udelay(1);
- FCC_PDATC_MDC(1);
- udelay(1);
+ udelay(us);
+ OUT_MDC(1);
+ udelay(us);
+ OUT_MDC(0);
}
/* Write data
*/
for (i = 0, off = 31; i < (read_op ? 14 : 32); i++, --off)
{
- FCC_PDATC_MDC(0);
- FCC_PDATC_MDIO((cmd >> off) & 0x00000001);
- udelay(1);
- FCC_PDATC_MDC(1);
- udelay(1);
+ OUT_MDIO((cmd >> off) & 0x00000001);
+ udelay(us);
+ OUT_MDC(1);
+ udelay(us);
+ OUT_MDC(0);
}
retval = cmd;
@@ -1928,68 +2254,111 @@ mii_send_receive(fcc_info_t *fip, uint cmd)
{
retval >>= 16;
- FCC_PDATC_MDC(0);
- io->iop_pdirc &= ~fip->fc_mdio;
- udelay(1);
- FCC_PDATC_MDC(1);
- udelay(1);
- FCC_PDATC_MDC(0);
- udelay(1);
+ MAKE_MDIO_INPUT;
+ udelay(us);
+ OUT_MDC(1);
+ udelay(us);
+ OUT_MDC(0);
- for (i = 0, off = 15; i < 16; i++, off--)
+ for (i = 0; i < 16; i++)
{
- FCC_PDATC_MDC(1);
+ udelay(us);
+ OUT_MDC(1);
+ udelay(us);
retval <<= 1;
- if (io->iop_pdatc & fip->fc_mdio)
+ if (IN_MDIO)
retval++;
- udelay(1);
- FCC_PDATC_MDC(0);
- udelay(1);
+ OUT_MDC(0);
}
}
- io->iop_pdirc |= (fip->fc_mdio | fip->fc_mdck);
-
- for (i = 0; i < 32; i++)
- {
- FCC_PDATC_MDC(0);
- FCC_PDATC_MDIO(1);
- udelay(1);
- FCC_PDATC_MDC(1);
- udelay(1);
- }
+ MAKE_MDIO_INPUT;
+ udelay(us);
+ OUT_MDC(1);
+ udelay(us);
+ OUT_MDC(0);
return retval;
}
+#endif /* CONFIG_USE_MDIO */
static void
fcc_stop(struct net_device *dev)
{
- volatile fcc_t *fccp;
- struct fcc_enet_private *fcp;
+ struct fcc_enet_private *fep= (struct fcc_enet_private *)(dev->priv);
+ volatile fcc_t *fccp = fep->fccp;
+ fcc_info_t *fip = fep->fip;
+ volatile fcc_enet_t *ep = fep->ep;
+ volatile cpm_cpm2_t *cp = cpmp;
+ volatile cbd_t *bdp;
+ int i;
+
+ if ((fccp->fcc_gfmr & (FCC_GFMR_ENR | FCC_GFMR_ENT)) == 0)
+ return; /* already down */
+
+ fccp->fcc_fccm = 0;
- fcp = (struct fcc_enet_private *)(dev->priv);
- fccp = fcp->fccp;
+ /* issue the graceful stop tx command */
+ while (cp->cp_cpcr & CPM_CR_FLG);
+ cp->cp_cpcr = mk_cr_cmd(fip->fc_cpmpage, fip->fc_cpmblock,
+ 0x0c, CPM_CR_GRA_STOP_TX) | CPM_CR_FLG;
+ while (cp->cp_cpcr & CPM_CR_FLG);
/* Disable transmit/receive */
fccp->fcc_gfmr &= ~(FCC_GFMR_ENR | FCC_GFMR_ENT);
+
+ /* issue the restart tx command */
+ fccp->fcc_fcce = FCC_ENET_GRA;
+ while (cp->cp_cpcr & CPM_CR_FLG);
+ cp->cp_cpcr = mk_cr_cmd(fip->fc_cpmpage, fip->fc_cpmblock,
+ 0x0c, CPM_CR_RESTART_TX) | CPM_CR_FLG;
+ while (cp->cp_cpcr & CPM_CR_FLG);
+
+ /* free tx buffers */
+ fep->skb_cur = fep->skb_dirty = 0;
+ for (i=0; i<=TX_RING_MOD_MASK; i++) {
+ if (fep->tx_skbuff[i] != NULL) {
+ dev_kfree_skb(fep->tx_skbuff[i]);
+ fep->tx_skbuff[i] = NULL;
+ }
+ }
+ fep->dirty_tx = fep->cur_tx = fep->tx_bd_base;
+ fep->tx_free = TX_RING_SIZE;
+ ep->fen_genfcc.fcc_tbptr = ep->fen_genfcc.fcc_tbase;
+
+ /* Initialize the tx buffer descriptors. */
+ bdp = fep->tx_bd_base;
+ for (i=0; i<TX_RING_SIZE; i++) {
+ bdp->cbd_sc = 0;
+ bdp->cbd_datlen = 0;
+ bdp->cbd_bufaddr = 0;
+ bdp++;
+ }
+ /* Set the last buffer to wrap. */
+ bdp--;
+ bdp->cbd_sc |= BD_SC_WRAP;
}
-#endif /* CONFIG_USE_MDIO */
static void
fcc_restart(struct net_device *dev, int duplex)
{
- volatile fcc_t *fccp;
- struct fcc_enet_private *fcp;
+ struct fcc_enet_private *fep = (struct fcc_enet_private *)(dev->priv);
+ volatile fcc_t *fccp = fep->fccp;
- fcp = (struct fcc_enet_private *)(dev->priv);
- fccp = fcp->fccp;
+ /* stop any transmissions in progress */
+ fcc_stop(dev);
if (duplex)
fccp->fcc_fpsmr |= FCC_PSMR_FDE | FCC_PSMR_LPB;
else
fccp->fcc_fpsmr &= ~(FCC_PSMR_FDE | FCC_PSMR_LPB);
+ /* Enable interrupts for transmit error, complete frame
+ * received, and any transmit buffer we have also set the
+ * interrupt flag.
+ */
+ fccp->fcc_fccm = (FCC_ENET_TXE | FCC_ENET_RXF | FCC_ENET_TXB);
+
/* Enable transmit/receive */
fccp->fcc_gfmr |= FCC_GFMR_ENR | FCC_GFMR_ENT;
}
@@ -2004,6 +2373,7 @@ fcc_enet_open(struct net_device *dev)
fep->link = 0;
if (fep->phy) {
+ fcc_restart(dev, 0); /* always start in half-duplex */
mii_do_cmd(dev, fep->phy->ack_int);
mii_do_cmd(dev, fep->phy->config);
mii_do_cmd(dev, phy_cmd_config); /* display configuration */
@@ -2017,6 +2387,7 @@ fcc_enet_open(struct net_device *dev)
return -ENODEV; /* No PHY we understand */
#else
fep->link = 1;
+ fcc_restart(dev, 0); /* always start in half-duplex */
netif_start_queue(dev);
return 0; /* Always succeed */
#endif /* CONFIG_USE_MDIO */
diff --git a/arch/ppc/8xx_io/cs4218_tdm.c b/arch/ppc/8xx_io/cs4218_tdm.c
index be7cef18d828f..89fe0ceeaa402 100644
--- a/arch/ppc/8xx_io/cs4218_tdm.c
+++ b/arch/ppc/8xx_io/cs4218_tdm.c
@@ -55,7 +55,7 @@ static int irq_installed = 0;
static char **sound_buffers = NULL;
static char **sound_read_buffers = NULL;
-static spinlock_t cs4218_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(cs4218_lock);
/* Local copies of things we put in the control register. Output
* volume, like most codecs is really attenuation.
diff --git a/arch/ppc/8xx_io/enet.c b/arch/ppc/8xx_io/enet.c
index f720d2a4ca6da..4ea7158e5062f 100644
--- a/arch/ppc/8xx_io/enet.c
+++ b/arch/ppc/8xx_io/enet.c
@@ -657,7 +657,7 @@ static int __init scc_enet_init(void)
cp = cpmp; /* Get pointer to Communication Processor */
- immap = (immap_t *)(mfspr(IMMR) & 0xFFFF0000); /* and to internal registers */
+ immap = (immap_t *)(mfspr(SPRN_IMMR) & 0xFFFF0000); /* and to internal registers */
bd = (bd_t *)__res;
diff --git a/arch/ppc/8xx_io/fec.c b/arch/ppc/8xx_io/fec.c
index 88eb1aa10dc07..0730392dcc206 100644
--- a/arch/ppc/8xx_io/fec.c
+++ b/arch/ppc/8xx_io/fec.c
@@ -1735,7 +1735,7 @@ static int __init fec_enet_init(void)
/* Bits moved from Rev. D onward.
*/
- if ((mfspr(IMMR) & 0xffff) < 0x0501)
+ if ((mfspr(SPRN_IMMR) & 0xffff) < 0x0501)
immap->im_ioport.iop_pddir = 0x1c58; /* Pre rev. D */
else
immap->im_ioport.iop_pddir = 0x1fff; /* Rev. D and later */
diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig
index 6fd6d12d7ceb7..59995a4308683 100644
--- a/arch/ppc/Kconfig
+++ b/arch/ppc/Kconfig
@@ -52,17 +52,17 @@ choice
default 6xx
config 6xx
- bool "6xx/7xx/74xx/52xx/8260"
+ bool "6xx/7xx/74xx/52xx/82xx/83xx"
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, 8260), the IBM 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)
Unless you are building a kernel for one of the embedded processor
systems, 64 bit IBM RS/6000 or an Apple G5, choose 6xx.
Note that the kernel runs in 32-bit mode even on 64-bit chips.
- Also note that because the 52xx & 82xx family has a 603e core,
+ Also note that because the 52xx, 82xx, & 83xx family has a 603e core,
specific support for that chipset is asked later on.
config 40x
@@ -109,7 +109,7 @@ config PHYS_64BIT
config ALTIVEC
bool "AltiVec Support"
depends on 6xx || POWER4
- depends on !8260
+ depends on !8260 && !83xx
---help---
This option enables kernel support for the Altivec extensions to the
PowerPC processor. The kernel currently supports saving and restoring
@@ -140,7 +140,7 @@ config SPE
config TAU
bool "Thermal Management Support"
- depends on 6xx && !8260
+ depends on 6xx && !8260 && !83xx
help
G3 and G4 processors have an on-chip temperature sensor called the
'Thermal Assist Unit (TAU)', which, in theory, can measure the on-die
@@ -209,7 +209,7 @@ config CPU_FREQ_PMAC
PowerBook.
config CPU_FREQ_TABLE
- bool
+ tristate
depends on CPU_FREQ_PMAC
default y
@@ -538,6 +538,17 @@ config CHESTNUT
config SPRUCE
bool "IBM-Spruce"
+config HDPU
+ bool "Sky-HDPU"
+ help
+ Select HDPU if configuring a Sky Computers Compute Blade.
+
+config HDPU_FEATURES
+ depends HDPU
+ tristate "HDPU-Features"
+ help
+ Select to enable HDPU enhanced features.
+
config EV64260
bool "Marvell-EV64260BP"
help
@@ -568,6 +579,9 @@ config SANDPOINT
Select SANDPOINT if configuring for a Motorola Sandpoint X3
(any flavor).
+config RADSTONE_PPC7D
+ bool "Radstone Technology PPC7D board"
+
config ADIR
bool "SBS-Adirondack"
@@ -638,6 +652,11 @@ 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.
+
endchoice
config PQ2ADS
@@ -676,6 +695,14 @@ 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
@@ -715,7 +742,8 @@ config PPC_GEN550
bool
depends on SANDPOINT || MCPN765 || SPRUCE || PPLUS || PCORE || \
PRPMC750 || K2 || PRPMC800 || LOPEC || \
- (EV64260 && !SERIAL_MPSC) || CHESTNUT
+ (EV64260 && !SERIAL_MPSC) || CHESTNUT || RADSTONE_PPC7D || \
+ 83xx
default y
config FORCE
@@ -728,16 +756,11 @@ config GT64260
depends on EV64260 || CPCI690
default y
-config MV64360
+config MV64360 # Really MV64360 & MV64460
bool
- depends on KATANA
+ depends on CHESTNUT || KATANA || RADSTONE_PPC7D || HDPU
default y
-config MV64360
- bool
- depends on CHESTNUT
- default y
-
config MV64X60
bool
depends on (GT64260 || MV64360)
@@ -793,7 +816,7 @@ config MPC10X_BRIDGE
config FSL_OCP
bool
- depends on MPC10X_BRIDGE || PPC_MPC52xx
+ depends on MPC10X_BRIDGE
default y
config MPC10X_OPENPIC
@@ -1046,6 +1069,8 @@ config PROC_HARDWARE
source "drivers/zorro/Kconfig"
+source kernel/power/Kconfig
+
endmenu
menu "Bus options"
@@ -1079,8 +1104,8 @@ config MCA
bool
config PCI
- bool "PCI support" if 40x || CPM2 || 85xx
- default y if !40x && !CPM2 && !8xx && !APUS && !85xx
+ bool "PCI support" if 40x || CPM2 || 83xx || 85xx || PPC_MPC52xx
+ default y if !40x && !CPM2 && !8xx && !APUS && !83xx && !85xx
default PCI_PERMEDIA if !4xx && !CPM2 && !8xx && APUS
default PCI_QSPAN if !4xx && !CPM2 && 8xx
help
diff --git a/arch/ppc/Makefile b/arch/ppc/Makefile
index e8b93926d7d9f..80497b9078336 100644
--- a/arch/ppc/Makefile
+++ b/arch/ppc/Makefile
@@ -57,6 +57,7 @@ head-$(CONFIG_POWER4) += arch/ppc/kernel/idle_power4.o
core-y += arch/ppc/kernel/ arch/ppc/platforms/ \
arch/ppc/mm/ arch/ppc/lib/ arch/ppc/syslib/
core-$(CONFIG_4xx) += arch/ppc/platforms/4xx/
+core-$(CONFIG_83xx) += arch/ppc/platforms/83xx/
core-$(CONFIG_85xx) += arch/ppc/platforms/85xx/
core-$(CONFIG_MATH_EMULATION) += arch/ppc/math-emu/
core-$(CONFIG_XMON) += arch/ppc/xmon/
@@ -112,26 +113,24 @@ include/asm-$(ARCH)/offsets.h: arch/$(ARCH)/kernel/asm-offsets.s
TOUT := .tmp_gas_check
# Ensure this is binutils 2.12.1 (or 2.12.90.0.7) or later for altivec
# instructions.
-AS_ALTIVEC := $(shell echo dssall | $(AS) -many -o $(TOUT) >/dev/null 2>&1 ; echo $$?)
# gcc-3.4 and binutils-2.14 are a fatal combination.
GCC_VERSION := $(call cc-version)
-BAD_GCC_AS := $(shell echo mftb 5 | $(AS) -mppc -many -o $(TOUT) >/dev/null 2>&1 && echo 0 || echo 1)
checkbin:
-ifeq ($(GCC_VERSION)$(BAD_GCC_AS),03041)
- @echo -n '*** ${VERSION}.${PATCHLEVEL} kernels no longer build '
- @echo 'correctly with gcc-3.4 and your version of binutils.'
- @echo '*** Please upgrade your binutils or downgrade your gcc'
- @false
-endif
-ifneq ($(AS_ALTIVEC),0)
- echo $(AS_ALTIVEC)
- @echo -n '*** ${VERSION}.${PATCHLEVEL} kernels no longer build '
- @echo 'correctly with old versions of binutils.'
- @echo '*** Please upgrade your binutils to 2.12.1 or newer'
- @false
-endif
- @true
+ @if test "$(GCC_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.'; \
+ echo '*** Please upgrade your binutils or downgrade your gcc'; \
+ false; \
+ fi ; \
+ fi
+ @if ! /bin/echo dssall | $(AS) -many -o $(TOUT) >/dev/null 2>&1 ; then \
+ echo -n '*** ${VERSION}.${PATCHLEVEL} kernels no longer build ' ; \
+ echo 'correctly with old versions of binutils.' ; \
+ echo '*** Please upgrade your binutils to 2.12.1 or newer' ; \
+ false ; \
+ fi
CLEAN_FILES += include/asm-$(ARCH)/offsets.h \
arch/$(ARCH)/kernel/asm-offsets.s \
diff --git a/arch/ppc/boot/common/util.S b/arch/ppc/boot/common/util.S
index d0161ac4cc567..47e641455bc59 100644
--- a/arch/ppc/boot/common/util.S
+++ b/arch/ppc/boot/common/util.S
@@ -47,23 +47,23 @@ disable_6xx_mmu:
/* Clear BATs */
li r8,0
- mtspr DBAT0U,r8
- mtspr DBAT0L,r8
- mtspr DBAT1U,r8
- mtspr DBAT1L,r8
- mtspr DBAT2U,r8
- mtspr DBAT2L,r8
- mtspr DBAT3U,r8
- mtspr DBAT3L,r8
+ mtspr SPRN_DBAT0U,r8
+ mtspr SPRN_DBAT0L,r8
+ mtspr SPRN_DBAT1U,r8
+ mtspr SPRN_DBAT1L,r8
+ mtspr SPRN_DBAT2U,r8
+ mtspr SPRN_DBAT2L,r8
+ mtspr SPRN_DBAT3U,r8
+ mtspr SPRN_DBAT3L,r8
.clearbats_601:
- mtspr IBAT0U,r8
- mtspr IBAT0L,r8
- mtspr IBAT1U,r8
- mtspr IBAT1L,r8
- mtspr IBAT2U,r8
- mtspr IBAT2L,r8
- mtspr IBAT3U,r8
- mtspr IBAT3L,r8
+ mtspr SPRN_IBAT0U,r8
+ mtspr SPRN_IBAT0L,r8
+ mtspr SPRN_IBAT1U,r8
+ mtspr SPRN_IBAT1L,r8
+ mtspr SPRN_IBAT2U,r8
+ mtspr SPRN_IBAT2L,r8
+ mtspr SPRN_IBAT3U,r8
+ mtspr SPRN_IBAT3L,r8
isync
sync
sync
@@ -84,14 +84,14 @@ disable_6xx_l1cache:
/* Enable, invalidate and then disable the L1 icache/dcache. */
li r8,0
ori r8,r8,(HID0_ICE|HID0_DCE|HID0_ICFI|HID0_DCI)
- mfspr r11,HID0
+ mfspr r11,SPRN_HID0
or r11,r11,r8
andc r10,r11,r8
isync
- mtspr HID0,r8
+ mtspr SPRN_HID0,r8
sync
isync
- mtspr HID0,r10
+ mtspr SPRN_HID0,r10
sync
isync
blr
@@ -107,17 +107,17 @@ _setup_L2CR:
/* Invalidate/disable L2 cache */
sync
isync
- mfspr r8,L2CR
+ mfspr r8,SPRN_L2CR
rlwinm r8,r8,0,1,31
oris r8,r8,L2CR_L2I@h
sync
isync
- mtspr L2CR,r8
+ mtspr SPRN_L2CR,r8
sync
isync
/* Wait for the invalidation to complete */
- mfspr r8,PVR
+ mfspr r8,SPRN_PVR
srwi r8,r8,16
cmplwi cr0,r8,0x8000 /* 7450 */
cmplwi cr1,r8,0x8001 /* 7455 */
@@ -126,19 +126,19 @@ _setup_L2CR:
cror 4*cr0+eq,4*cr0+eq,4*cr2+eq
bne 2f
-1: mfspr r8,L2CR /* On 745x, poll L2I bit (bit 10) */
+1: mfspr r8,SPRN_L2CR /* On 745x, poll L2I bit (bit 10) */
rlwinm. r9,r8,0,10,10
bne 1b
b 3f
-2: mfspr r8,L2CR /* On 75x & 74[01]0, poll L2IP bit (bit 31) */
+2: mfspr r8,SPRN_L2CR /* On 75x & 74[01]0, poll L2IP bit (bit 31) */
rlwinm. r9,r8,0,31,31
bne 2b
3: rlwinm r8,r8,0,11,9 /* Turn off L2I bit */
sync
isync
- mtspr L2CR,r8
+ mtspr SPRN_L2CR,r8
sync
isync
blr
@@ -148,24 +148,24 @@ _setup_L3CR:
/* Invalidate/disable L3 cache */
sync
isync
- mfspr r8,L3CR
+ mfspr r8,SPRN_L3CR
rlwinm r8,r8,0,1,31
ori r8,r8,L3CR_L3I@l
sync
isync
- mtspr L3CR,r8
+ mtspr SPRN_L3CR,r8
sync
isync
/* Wait for the invalidation to complete */
-1: mfspr r8,L3CR
+1: mfspr r8,SPRN_L3CR
rlwinm. r9,r8,0,21,21
bne 1b
rlwinm r8,r8,0,22,20 /* Turn off L3I bit */
sync
isync
- mtspr L3CR,r8
+ mtspr SPRN_L3CR,r8
sync
isync
blr
@@ -190,7 +190,7 @@ timebase_period_ns:
*/
.globl udelay
udelay:
- mfspr r4,PVR
+ mfspr r4,SPRN_PVR
srwi r4,r4,16
cmpwi 0,r4,1 /* 601 ? */
bne .udelay_not_601
@@ -240,11 +240,11 @@ _GLOBAL(flush_instruction_cache)
#ifdef CONFIG_8xx
lis r3, IDC_INVALL@h
- mtspr IC_CST, r3
+ mtspr SPRN_IC_CST, r3
lis r3, IDC_ENABLE@h
- mtspr IC_CST, r3
+ mtspr SPRN_IC_CST, r3
lis r3, IDC_DISABLE@h
- mtspr DC_CST, r3
+ mtspr SPRN_DC_CST, r3
#elif CONFIG_4xx
lis r3,start@h # r9 = &_start
lis r4,_etext@ha
@@ -258,14 +258,14 @@ _GLOBAL(flush_instruction_cache)
/* Enable, invalidate and then disable the L1 icache/dcache. */
li r3,0
ori r3,r3,(HID0_ICE|HID0_DCE|HID0_ICFI|HID0_DCI)
- mfspr r4,HID0
+ mfspr r4,SPRN_HID0
or r5,r4,r3
isync
- mtspr HID0,r5
+ mtspr SPRN_HID0,r5
sync
isync
ori r5,r4,HID0_ICE /* Enable cache */
- mtspr HID0,r5
+ mtspr SPRN_HID0,r5
sync
isync
#endif
diff --git a/arch/ppc/boot/simple/Makefile b/arch/ppc/boot/simple/Makefile
index a0437d10bb1e2..d8d801fcee10a 100644
--- a/arch/ppc/boot/simple/Makefile
+++ b/arch/ppc/boot/simple/Makefile
@@ -49,7 +49,7 @@ clear_L2_L3 := $(srctree)/$(boot)/simple/clear.S
#----------------------------------------------------------------------------
zimage-$(CONFIG_CPCI690) := zImage-STRIPELF
zimageinitrd-$(CONFIG_CPCI690) := zImage.initrd-STRIPELF
- extra.o-$(CONFIG_CPCI690) := misc-cpci690.o mv64x60_stub.o
+ extra.o-$(CONFIG_CPCI690) := misc-cpci690.o
end-$(CONFIG_CPCI690) := cpci690
cacheflag-$(CONFIG_CPCI690) := -include $(clear_L2_L3)
@@ -65,6 +65,7 @@ zimageinitrd-$(CONFIG_IBM_OPENBIOS) := zImage.initrd-TREE
zimageinitrd-$(CONFIG_EBONY) := zImage.initrd-TREE
end-$(CONFIG_EBONY) := ebony
entrypoint-$(CONFIG_EBONY) := 0x01000000
+ extra.o-$(CONFIG_EBONY) := openbios.o
zimage-$(CONFIG_LUAN) := zImage-TREE
zimageinitrd-$(CONFIG_LUAN) := zImage.initrd-TREE
@@ -93,10 +94,14 @@ zimageinitrd-$(CONFIG_GEMINI) := zImage.initrd-STRIPELF
end-$(CONFIG_K2) := k2
cacheflag-$(CONFIG_K2) := -include $(clear_L2_L3)
- extra.o-$(CONFIG_KATANA) := misc-katana.o mv64x60_stub.o
+ extra.o-$(CONFIG_KATANA) := misc-katana.o
end-$(CONFIG_KATANA) := katana
cacheflag-$(CONFIG_KATANA) := -include $(clear_L2_L3)
+ extra.o-$(CONFIG_RADSTONE_PPC7D) := misc-radstone_ppc7d.o
+ end-$(CONFIG_RADSTONE_PPC7D) := radstone_ppc7d
+ cacheflag-$(CONFIG_RADSTONE_PPC7D) := -include $(clear_L2_L3)
+
# kconfig 'feature', only one of these will ever be 'y' at a time.
# The rest will be unset.
motorola := $(CONFIG_MCPN765)$(CONFIG_MVME5100)$(CONFIG_PRPMC750) \
diff --git a/arch/ppc/boot/simple/clear.S b/arch/ppc/boot/simple/clear.S
index cd15b1644969e..95c5647a0f511 100644
--- a/arch/ppc/boot/simple/clear.S
+++ b/arch/ppc/boot/simple/clear.S
@@ -7,7 +7,7 @@
bl _setup_L2CR; \
\
/* If 745x, turn off L3CR as well */ \
- mfspr r8,PVR; \
+ mfspr r8,SPRN_PVR; \
srwi r8,r8,16; \
\
cmpli cr0,r8,0x8000; /* 7450 */ \
diff --git a/arch/ppc/boot/simple/embed_config.c b/arch/ppc/boot/simple/embed_config.c
index a4fbc390084c4..c342b47e763e5 100644
--- a/arch/ppc/boot/simple/embed_config.c
+++ b/arch/ppc/boot/simple/embed_config.c
@@ -506,7 +506,7 @@ embed_config(bd_t **bdp)
memcpy(bd->bi_enetaddr, cp, 6);
/* can busfreq be calculated? */
- pvr = mfspr(PVR);
+ pvr = mfspr(SPRN_PVR);
if ((pvr & 0xffff0000) == 0x80820000) {
bd->bi_busfreq = 100000000;
clk_8280(bd);
diff --git a/arch/ppc/boot/simple/head.S b/arch/ppc/boot/simple/head.S
index ba4c7b2687370..524053202bb48 100644
--- a/arch/ppc/boot/simple/head.S
+++ b/arch/ppc/boot/simple/head.S
@@ -52,7 +52,7 @@ start_:
*/
li r4,0x0000
isync
- mtspr HID0,r4
+ mtspr SPRN_HID0,r4
sync
isync
#endif
@@ -135,11 +135,6 @@ haveOF:
*/
#endif
-#ifdef CONFIG_MV64X60
- /* mv64x60 specific hook to do things like moving register base, etc. */
- bl mv64x60_init
-#endif
-
/* Get the load address.
*/
subi r3, r3, 4 /* Get the actual IP, not NIP */
diff --git a/arch/ppc/boot/simple/m8260_tty.c b/arch/ppc/boot/simple/m8260_tty.c
index c3e2c39425f8f..d770947e9b8fe 100644
--- a/arch/ppc/boot/simple/m8260_tty.c
+++ b/arch/ppc/boot/simple/m8260_tty.c
@@ -159,7 +159,7 @@ serial_init(int ignored, bd_t *bd)
sccp->scc_sccm = 0;
sccp->scc_scce = 0xffff;
sccp->scc_dsr = 0x7e7e;
- sccp->scc_pmsr = 0x3000;
+ sccp->scc_psmr = 0x3000;
/* Wire BRG1 to SCC1. The console driver will take care of
* others.
diff --git a/arch/ppc/boot/simple/misc-chestnut.S b/arch/ppc/boot/simple/misc-chestnut.S
deleted file mode 100644
index f75c06c3394ff..0000000000000
--- a/arch/ppc/boot/simple/misc-chestnut.S
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * arch/ppc/boot/simple/misc-chestnut.S
- *
- * Setup for the IBM Chestnut (ibm-750fxgx_eval)
- *
- * Author: <source@mvista.com>
- *
- * <2004> (c) MontaVista Software, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-
-
-#include <asm/ppc_asm.h>
-#include <asm/mv64x60_defs.h>
-#include <platforms/chestnut.h>
-
- .globl mv64x60_board_init
-mv64x60_board_init:
- /*
- * move UART to 0xffc00000
- */
-
- li r23,16
-
- addis r25,0,CONFIG_MV64X60_BASE@h
- ori r25,r25,MV64x60_CPU2DEV_2_BASE
- addis r26,0,CHESTNUT_UART_BASE@h
- srw r26,r26,r23
- stwbrx r26,0,(r25)
- sync
-
- addis r25,0,CONFIG_MV64X60_BASE@h
- ori r25,r25,MV64x60_CPU2DEV_2_SIZE
- addis r26,0,0x00100000@h
- srw r26,r26,r23
- stwbrx r26,0,(r25)
- sync
-
- blr
diff --git a/arch/ppc/boot/simple/misc-chestnut.c b/arch/ppc/boot/simple/misc-chestnut.c
new file mode 100644
index 0000000000000..0dce7f3557e4d
--- /dev/null
+++ b/arch/ppc/boot/simple/misc-chestnut.c
@@ -0,0 +1,35 @@
+/*
+ * arch/ppc/boot/simple/misc-chestnut.c
+ *
+ * Setup for the IBM Chestnut (ibm-750fxgx_eval)
+ *
+ * Author: Mark A. Greer <mgreer@mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <asm/io.h>
+#include <asm/mv64x60_defs.h>
+#include <platforms/chestnut.h>
+
+/* Not in the kernel so won't include kernel.h to get its 'max' definition */
+#define max(a,b) (((a) > (b)) ? (a) : (b))
+
+void
+mv64x60_board_init(void __iomem *old_base, void __iomem *new_base)
+{
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+ /*
+ * Change device bus 2 window so that bootoader can do I/O thru
+ * 8250/16550 UART that's mapped in that window.
+ */
+ out_le32(new_base + MV64x60_CPU2DEV_2_BASE, CHESTNUT_UART_BASE >> 16);
+ out_le32(new_base + MV64x60_CPU2DEV_2_SIZE, CHESTNUT_UART_SIZE >> 16);
+ __asm__ __volatile__("sync");
+#endif
+}
diff --git a/arch/ppc/boot/simple/misc-cpci690.c b/arch/ppc/boot/simple/misc-cpci690.c
index b37d02f2d2c90..ef08e86c9b25d 100644
--- a/arch/ppc/boot/simple/misc-cpci690.c
+++ b/arch/ppc/boot/simple/misc-cpci690.c
@@ -12,4 +12,16 @@
*/
#include <linux/types.h>
-long mv64x60_mpsc_clk_freq = 133000000;
+#include <platforms/cpci690.h>
+
+extern u32 mv64x60_console_baud;
+extern u32 mv64x60_mpsc_clk_src;
+extern u32 mv64x60_mpsc_clk_freq;
+
+void
+mv64x60_board_init(void __iomem *old_base, void __iomem *new_base)
+{
+ mv64x60_console_baud = CPCI690_MPSC_BAUD;
+ mv64x60_mpsc_clk_src = CPCI690_MPSC_CLK_SRC;
+ mv64x60_mpsc_clk_freq = CPCI690_BUS_FREQ;
+}
diff --git a/arch/ppc/boot/simple/misc-ev64260.S b/arch/ppc/boot/simple/misc-ev64260.S
deleted file mode 100644
index 2dc3e6c5032af..0000000000000
--- a/arch/ppc/boot/simple/misc-ev64260.S
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * arch/ppc/boot/simple/misc-ev64260.S
- *
- * Host bridge init code for the Marvell/Galileo EV-64260-BP evaluation board
- * with a GT64260 onboard.
- *
- * Author: Mark Greer <mgreer@mvista.com>
- *
- * 2001 (c) MontaVista Software, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-
-#include <asm/ppc_asm.h>
-#include <asm/processor.h>
-#include <asm/cache.h>
-#include <asm/mv64x60_defs.h>
-#include <platforms/ev64260.h>
-
- .globl mv64x60_board_init
-mv64x60_board_init:
- /* DINK doesn't enable 745x timebase, so enable here (Adrian Cox) */
- mfspr r25,PVR
- srwi r25,r25,16
- cmplwi r25,(PVR_7450 >> 16)
- bne 1f
- mfspr r25,HID0
- oris r25,r25,(HID0_TBEN >> 16)
- mtspr HID0,r25
-1:
-#if (CONFIG_MV64X60_NEW_BASE != CONFIG_MV64X60_BASE)
- li r23,20
-
- /*
- * Change the CS2 window for the UART so that the bootloader
- * can do I/O thru the UARTs.
- */
- addis r25,0,CONFIG_MV64X60_NEW_BASE@h
- ori r25,r25,MV64x60_CPU2DEV_2_BASE
- addis r26,0,EV64260_UART_BASE@h
- srw r26,r26,r23
- stwbrx r26,0,(r25)
- sync
-
- addis r25,0,CONFIG_MV64X60_NEW_BASE@h
- ori r25,r25,MV64x60_CPU2DEV_2_SIZE
- addis r26,0,EV64260_UART_END@h
- srw r26,r26,r23
- stwbrx r26,0,(r25)
- sync
-#endif
- blr
-
-#if defined(CONFIG_SERIAL_MPSC_CONSOLE)
-.data
- .globl mv64x60_console_baud
-mv64x60_console_baud:
-.long EV64260_DEFAULT_BAUD
-
- .globl mv64x60_mpsc_clk_src
-mv64x60_mpsc_clk_src:
-.long EV64260_MPSC_CLK_SRC
-
- .globl mv64x60_mpsc_clk_freq
-mv64x60_mpsc_clk_freq:
-.long EV64260_MPSC_CLK_FREQ
-#endif
diff --git a/arch/ppc/boot/simple/misc-ev64260.c b/arch/ppc/boot/simple/misc-ev64260.c
new file mode 100644
index 0000000000000..52ece6937a7ab
--- /dev/null
+++ b/arch/ppc/boot/simple/misc-ev64260.c
@@ -0,0 +1,57 @@
+/*
+ * arch/ppc/boot/simple/misc-ev64260.c
+ *
+ * Host bridge init code for the Marvell/Galileo EV-64260-BP evaluation board
+ * with a GT64260 onboard.
+ *
+ * Author: Mark A. Greer <mgreer@mvista.com>
+ *
+ * 2001 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <asm/reg.h>
+#include <asm/io.h>
+#include <asm/mv64x60_defs.h>
+#include <platforms/ev64260.h>
+
+#ifdef CONFIG_SERIAL_MPSC_CONSOLE
+extern u32 mv64x60_console_baud;
+extern u32 mv64x60_mpsc_clk_src;
+extern u32 mv64x60_mpsc_clk_freq;
+#endif
+
+void
+mv64x60_board_init(void __iomem *old_base, void __iomem *new_base)
+{
+ u32 p, v;
+
+ /* DINK doesn't enable 745x timebase, so enable here (Adrian Cox) */
+ p = mfspr(SPRN_PVR);
+ p >>= 16;
+
+ /* Reasonable SWAG at a 745x PVR value */
+ if (((p & 0xfff0) == 0x8000) && (p != 0x800c)) {
+ v = mfspr(SPRN_HID0);
+ v |= HID0_TBEN;
+ mtspr(SPRN_HID0, v);
+ }
+
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+ /*
+ * Change device bus 2 window so that bootoader can do I/O thru
+ * 8250/16550 UART that's mapped in that window.
+ */
+ out_le32(new_base + MV64x60_CPU2DEV_2_BASE, EV64260_UART_BASE >> 20);
+ out_le32(new_base + MV64x60_CPU2DEV_2_SIZE, EV64260_UART_END >> 20);
+ __asm__ __volatile__("sync");
+#elif defined(CONFIG_SERIAL_MPSC_CONSOLE)
+ mv64x60_console_baud = EV64260_DEFAULT_BAUD;
+ mv64x60_mpsc_clk_src = EV64260_MPSC_CLK_SRC;
+ mv64x60_mpsc_clk_freq = EV64260_MPSC_CLK_FREQ;
+#endif
+}
diff --git a/arch/ppc/boot/simple/misc-katana.c b/arch/ppc/boot/simple/misc-katana.c
index c4a90d5ce28bc..b6e1bb833157d 100644
--- a/arch/ppc/boot/simple/misc-katana.c
+++ b/arch/ppc/boot/simple/misc-katana.c
@@ -1,7 +1,7 @@
/*
* arch/ppc/boot/simple/misc-katana.c
*
- * Add birec data for Artesyn KATANA board.
+ * Set up MPSC values to bootwrapper can prompt user.
*
* Author: Mark A. Greer <source@mvista.com>
*
@@ -11,5 +11,27 @@
* or implied.
*/
+#include <linux/config.h>
#include <linux/types.h>
-long mv64x60_mpsc_clk_freq = 133333333;
+#include <asm/io.h>
+#include <asm/mv64x60_defs.h>
+#include <platforms/katana.h>
+
+extern u32 mv64x60_console_baud;
+extern u32 mv64x60_mpsc_clk_src;
+extern u32 mv64x60_mpsc_clk_freq;
+
+/* Not in the kernel so won't include kernel.h to get its 'min' definition */
+#ifndef min
+#define min(a,b) (((a) < (b)) ? (a) : (b))
+#endif
+
+void
+mv64x60_board_init(void __iomem *old_base, void __iomem *new_base)
+{
+ mv64x60_console_baud = KATANA_DEFAULT_BAUD;
+ mv64x60_mpsc_clk_src = KATANA_MPSC_CLK_SRC;
+ mv64x60_mpsc_clk_freq =
+ min(katana_bus_freq((void __iomem *)KATANA_CPLD_BASE),
+ MV64x60_TCLK_FREQ_MAX);
+}
diff --git a/arch/ppc/boot/simple/misc-mv64x60.S b/arch/ppc/boot/simple/misc-mv64x60.S
deleted file mode 100644
index 0978e42e7354d..0000000000000
--- a/arch/ppc/boot/simple/misc-mv64x60.S
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * arch/ppc/boot/simple/misc-mv64x60.S
- *
- * Code to change the base address of the host bridges and call board specific
- * init routine.
- *
- * Author: Mark Greer <mgreer@mvista.com>
- *
- * 2002 (c) MontaVista, Software, Inc. This file is licensed under the terms
- * of the GNU General Public License version 2. This program is licensed
- * "as is" without any warranty of any kind, whether express or implied.
- */
-
-#include <linux/config.h>
-#include <asm/ppc_asm.h>
-#include <asm/processor.h>
-#include <asm/cache.h>
-#include <asm/mv64x60_defs.h>
-
- .globl mv64x60_init
-mv64x60_init:
- mflr r27
-
-#if (CONFIG_MV64X60_NEW_BASE != CONFIG_MV64X60_BASE)
- bl move_base
-#endif
- bl mv64x60_board_init
-
- mtlr r27
- blr
-
-#if (CONFIG_MV64X60_NEW_BASE != CONFIG_MV64X60_BASE)
-move_base:
- li r20,0
- li r23,20
-
- /* Relocate bridge's regs */
- addis r25,0,CONFIG_MV64X60_BASE@h
- ori r25,r25,MV64x60_INTERNAL_SPACE_DECODE
- lwbrx r26,0,(r25)
- lis r24,0xffff
- and r26,r26,r24
- addis r24,0,CONFIG_MV64X60_NEW_BASE@h
- srw r24,r24,r23
- or r26,r26,r24
- stwbrx r26,0,(r25)
- sync
-
- /* Wait for write to take effect */
- addis r25,0,CONFIG_MV64X60_NEW_BASE@h
- ori r25,r25,MV64x60_INTERNAL_SPACE_DECODE
-1: lwbrx r24,0,(r25)
- cmpw r24,r26
- bne 1b
-
- blr
-#endif
diff --git a/arch/ppc/boot/simple/misc-mv64x60.c b/arch/ppc/boot/simple/misc-mv64x60.c
new file mode 100644
index 0000000000000..7e88fc6d207d2
--- /dev/null
+++ b/arch/ppc/boot/simple/misc-mv64x60.c
@@ -0,0 +1,61 @@
+/*
+ * arch/ppc/boot/simple/misc-mv64x60.c
+ *
+ * Relocate bridge's register base and call board specific routine.
+ *
+ * Author: Mark A. Greer <source@mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <asm/io.h>
+#include <asm/mv64x60_defs.h>
+
+extern struct bi_record *decompress_kernel(unsigned long load_addr,
+ int num_words, unsigned long cksum);
+
+void
+mv64x60_move_base(void __iomem *old_base, void __iomem *new_base)
+{
+ u32 bits, mask, b;
+
+ if (old_base != new_base) {
+#ifdef CONFIG_GT64260
+ bits = 12;
+ mask = 0x07000000;
+#else /* Must be mv64[34]60 */
+ bits = 16;
+ mask = 0x03000000;
+#endif
+ b = in_le32(old_base + MV64x60_INTERNAL_SPACE_DECODE);
+ b &= mask;
+ b |= ((u32)new_base >> (32 - bits));
+ out_le32(old_base + MV64x60_INTERNAL_SPACE_DECODE, b);
+
+ __asm__ __volatile__("sync");
+
+ /* Wait for change to happen (in accordance with the manual) */
+ while (in_le32(new_base + MV64x60_INTERNAL_SPACE_DECODE) != b);
+ }
+}
+
+void __attribute__ ((weak))
+mv64x60_board_init(void __iomem *old_base, void __iomem *new_base)
+{
+}
+
+void *
+load_kernel(unsigned long load_addr, int num_words, unsigned long cksum,
+ void *ign1, void *ign2)
+{
+ mv64x60_move_base((void __iomem *)CONFIG_MV64X60_BASE,
+ (void __iomem *)CONFIG_MV64X60_NEW_BASE);
+ mv64x60_board_init((void __iomem *)CONFIG_MV64X60_BASE,
+ (void __iomem *)CONFIG_MV64X60_NEW_BASE);
+ return decompress_kernel(load_addr, num_words, cksum);
+}
diff --git a/arch/ppc/boot/simple/misc-radstone_ppc7d.c b/arch/ppc/boot/simple/misc-radstone_ppc7d.c
new file mode 100644
index 0000000000000..569e0d4feeaf1
--- /dev/null
+++ b/arch/ppc/boot/simple/misc-radstone_ppc7d.c
@@ -0,0 +1,26 @@
+/*
+ * arch/ppc/boot/simple/misc-radstone_ppc7d.c
+ *
+ * Misc data for Radstone PPC7D board.
+ *
+ * Author: James Chapman <jchapman@katalix.com>
+ */
+
+#include <linux/types.h>
+#include <platforms/radstone_ppc7d.h>
+
+#if defined(CONFIG_SERIAL_MPSC_CONSOLE)
+extern u32 mv64x60_console_baud;
+extern u32 mv64x60_mpsc_clk_src;
+extern u32 mv64x60_mpsc_clk_freq;
+#endif
+
+void
+mv64x60_board_init(void __iomem *old_base, void __iomem *new_base)
+{
+#if defined(CONFIG_SERIAL_MPSC_CONSOLE)
+ mv64x60_console_baud = PPC7D_DEFAULT_BAUD;
+ mv64x60_mpsc_clk_src = PPC7D_MPSC_CLK_SRC;
+ mv64x60_mpsc_clk_freq = PPC7D_MPSC_CLK_FREQ;
+#endif
+}
diff --git a/arch/ppc/boot/simple/mpc52xx_tty.c b/arch/ppc/boot/simple/mpc52xx_tty.c
index efde532b41e0e..3acc6b7c0727c 100644
--- a/arch/ppc/boot/simple/mpc52xx_tty.c
+++ b/arch/ppc/boot/simple/mpc52xx_tty.c
@@ -20,31 +20,31 @@
#include <asm/io.h>
#include <asm/time.h>
-#if MPC52xx_PF_CONSOLE_PORT == 0
-#define MPC52xx_CONSOLE MPC52xx_PSC1
-#define MPC52xx_PSC_CONFIG_SHIFT 0
-#elif MPC52xx_PF_CONSOLE_PORT == 1
-#define MPC52xx_CONSOLE MPC52xx_PSC2
-#define MPC52xx_PSC_CONFIG_SHIFT 4
-#elif MPC52xx_PF_CONSOLE_PORT == 2
-#define MPC52xx_CONSOLE MPC52xx_PSC3
-#define MPC52xx_PSC_CONFIG_SHIFT 8
+
+#ifdef MPC52xx_PF_CONSOLE_PORT
+#define MPC52xx_CONSOLE MPC52xx_PSCx_OFFSET(MPC52xx_PF_CONSOLE_PORT)
+#define MPC52xx_PSC_CONFIG_SHIFT ((MPC52xx_PF_CONSOLE_PORT-1)<<2)
#else
#error "MPC52xx_PF_CONSOLE_PORT not defined"
#endif
-static struct mpc52xx_psc *psc = (struct mpc52xx_psc *)MPC52xx_CONSOLE;
+static struct mpc52xx_psc __iomem *psc =
+ (struct mpc52xx_psc __iomem *) MPC52xx_PA(MPC52xx_CONSOLE);
/* The decrementer counts at the system bus clock frequency
* divided by four. The most accurate time base is connected to the
- * rtc. We read the decrementer change during one rtc tick (one second)
- * and multiply by 4 to get the system bus clock frequency.
+ * rtc. We read the decrementer change during one rtc tick
+ * and multiply by 4 to get the system bus clock frequency. Since a
+ * rtc tick is one seconds, and that's pretty long, we change the rtc
+ * dividers temporarly to set them 64x faster ;)
*/
-int
+static int
mpc52xx_ipbfreq(void)
{
- struct mpc52xx_rtc *rtc = (struct mpc52xx_rtc*)MPC52xx_RTC;
- struct mpc52xx_cdm *cdm = (struct mpc52xx_cdm*)MPC52xx_CDM;
+ struct mpc52xx_rtc __iomem *rtc =
+ (struct mpc52xx_rtc __iomem *) MPC52xx_PA(MPC52xx_RTC_OFFSET);
+ struct mpc52xx_cdm __iomem *cdm =
+ (struct mpc52xx_cdm __iomem *) MPC52xx_PA(MPC52xx_CDM_OFFSET);
int current_time, previous_time;
int tbl_start, tbl_end;
int xlbfreq, ipbfreq;
@@ -67,7 +67,8 @@ mpc52xx_ipbfreq(void)
unsigned long
serial_init(int ignored, void *ignored2)
{
- struct mpc52xx_gpio *gpio = (struct mpc52xx_gpio *)MPC52xx_GPIO;
+ struct mpc52xx_gpio __iomem *gpio =
+ (struct mpc52xx_gpio __iomem *) MPC52xx_PA(MPC52xx_GPIO_OFFSET);
int divisor;
int mode1;
int mode2;
@@ -117,7 +118,7 @@ serial_init(int ignored, void *ignored2)
void
serial_putc(void *ignored, const char c)
{
- serial_init(0, 0);
+ serial_init(0, NULL);
while (!(in_be16(&psc->mpc52xx_psc_status) & MPC52xx_PSC_SR_TXEMP)) ;
out_8(&psc->mpc52xx_psc_buffer_8, c);
diff --git a/arch/ppc/boot/simple/mv64x60_stub.c b/arch/ppc/boot/simple/mv64x60_stub.c
deleted file mode 100644
index 43ae96bb16e25..0000000000000
--- a/arch/ppc/boot/simple/mv64x60_stub.c
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * arch/ppc/boot/simple/mv64x60_stub.c
- *
- * Stub for board_init() routine called from mv64x60_init().
- *
- * Author: Mark A. Greer <mgreer@mvista.com>
- *
- * 2002 (c) MontaVista, Software, Inc. This file is licensed under the terms
- * of the GNU General Public License version 2. This program is licensed
- * "as is" without any warranty of any kind, whether express or implied.
- */
-
-#include <linux/config.h>
-
-#if defined(CONFIG_SERIAL_MPSC_CONSOLE)
-long __attribute__ ((weak)) mv64x60_console_baud = 9600;
-long __attribute__ ((weak)) mv64x60_mpsc_clk_src = 8; /* TCLK */
-long __attribute__ ((weak)) mv64x60_mpsc_clk_freq = 100000000;
-#endif
-
-void __attribute__ ((weak))
-mv64x60_board_init(void)
-{
-}
diff --git a/arch/ppc/boot/simple/mv64x60_tty.c b/arch/ppc/boot/simple/mv64x60_tty.c
index de260eafdd31d..5b45eb46b6693 100644
--- a/arch/ppc/boot/simple/mv64x60_tty.c
+++ b/arch/ppc/boot/simple/mv64x60_tty.c
@@ -18,36 +18,18 @@
#include <linux/types.h>
#include <linux/serial_reg.h>
#include <asm/serial.h>
+#include <asm/io.h>
#include <asm/mv64x60_defs.h>
#include <mpsc_defs.h>
+u32 mv64x60_console_baud = 9600;
+u32 mv64x60_mpsc_clk_src = 8; /* TCLK */
+u32 mv64x60_mpsc_clk_freq = 100000000;
+
extern void udelay(long);
static void stop_dma(int chan);
-static u32 mv64x60_base = CONFIG_MV64X60_NEW_BASE;
-
-inline unsigned
-mv64x60_in_le32(volatile unsigned *addr)
-{
- unsigned ret;
-
- __asm__ __volatile__("lwbrx %0,0,%1; eieio" : "=r" (ret) :
- "r" (addr), "m" (*addr));
- return ret;
-}
-
-inline void
-mv64x60_out_le32(volatile unsigned *addr, int val)
-{
- __asm__ __volatile__("stwbrx %1,0,%2; eieio" : "=m" (*addr) :
- "r" (val), "r" (addr));
-}
-
-#define MV64x60_REG_READ(offs) \
- (mv64x60_in_le32((volatile uint *)(mv64x60_base + (offs))))
-#define MV64x60_REG_WRITE(offs, d) \
- (mv64x60_out_le32((volatile uint *)(mv64x60_base + (offs)), (int)(d)))
-
+static void __iomem *mv64x60_base = (void __iomem *)CONFIG_MV64X60_NEW_BASE;
struct sdma_regs {
u32 sdc;
@@ -142,9 +124,6 @@ serial_init(int chan, void *ignored)
{
u32 mpsc_routing_base, sdma_base, brg_bcr, cdv;
int i;
- extern long mv64x60_console_baud;
- extern long mv64x60_mpsc_clk_src;
- extern long mv64x60_mpsc_clk_freq;
chan = (chan == 1); /* default to chan 0 if anything but 1 */
@@ -157,8 +136,7 @@ serial_init(int chan, void *ignored)
sdma_base = MV64x60_SDMA_0_OFFSET;
brg_bcr = MV64x60_BRG_0_OFFSET + BRG_BCR;
SDMA_REGS_INIT(&sdma_regs[0], MV64x60_SDMA_0_OFFSET);
- }
- else {
+ } else {
sdma_base = MV64x60_SDMA_1_OFFSET;
brg_bcr = MV64x60_BRG_1_OFFSET + BRG_BCR;
SDMA_REGS_INIT(&sdma_regs[0], MV64x60_SDMA_1_OFFSET);
@@ -186,10 +164,10 @@ serial_init(int chan, void *ignored)
td[chan][TX_NUM_DESC - 1].next_desc_ptr = (u32)&td[chan][0];
/* Set MPSC Routing */
- MV64x60_REG_WRITE(mpsc_routing_base + MPSC_MRR, 0x3ffffe38);
+ out_le32(mv64x60_base + mpsc_routing_base + MPSC_MRR, 0x3ffffe38);
#ifdef CONFIG_GT64260
- MV64x60_REG_WRITE(GT64260_MPP_SERIAL_PORTS_MULTIPLEX, 0x00001102);
+ out_le32(mv64x60_base + GT64260_MPP_SERIAL_PORTS_MULTIPLEX, 0x00001102);
#else /* Must be MV64360 or MV64460 */
{
u32 enables, prot_bits, v;
@@ -197,68 +175,70 @@ serial_init(int chan, void *ignored)
/* Set up comm unit to memory mapping windows */
/* Note: Assumes MV64x60_CPU2MEM_WINDOWS == 4 */
- enables = MV64x60_REG_READ(MV64360_CPU_BAR_ENABLE) & 0xf;
+ enables = in_le32(mv64x60_base + MV64360_CPU_BAR_ENABLE) & 0xf;
prot_bits = 0;
for (i=0; i<MV64x60_CPU2MEM_WINDOWS; i++) {
if (!(enables & (1 << i))) {
- v = MV64x60_REG_READ(cpu2mem_tab[i][0]);
+ v = in_le32(mv64x60_base + cpu2mem_tab[i][0]);
v = ((v & 0xffff) << 16) | (dram_selects[i] << 8);
- MV64x60_REG_WRITE(com2mem_tab[i][0], v);
+ out_le32(mv64x60_base + com2mem_tab[i][0], v);
- v = MV64x60_REG_READ(cpu2mem_tab[i][1]);
+ v = in_le32(mv64x60_base + cpu2mem_tab[i][1]);
v = (v & 0xffff) << 16;
- MV64x60_REG_WRITE(com2mem_tab[i][1], v);
+ out_le32(mv64x60_base + com2mem_tab[i][1], v);
prot_bits |= (0x3 << (i << 1)); /* r/w access */
}
}
- MV64x60_REG_WRITE(MV64360_MPSC_0_REMAP, 0);
- MV64x60_REG_WRITE(MV64360_MPSC_1_REMAP, 0);
- MV64x60_REG_WRITE(MV64360_MPSC2MEM_ACC_PROT_0, prot_bits);
- MV64x60_REG_WRITE(MV64360_MPSC2MEM_ACC_PROT_1, prot_bits);
- MV64x60_REG_WRITE(MV64360_MPSC2MEM_BAR_ENABLE, enables);
+ out_le32(mv64x60_base + MV64360_MPSC_0_REMAP, 0);
+ out_le32(mv64x60_base + MV64360_MPSC_1_REMAP, 0);
+ out_le32(mv64x60_base + MV64360_MPSC2MEM_ACC_PROT_0, prot_bits);
+ out_le32(mv64x60_base + MV64360_MPSC2MEM_ACC_PROT_1, prot_bits);
+ out_le32(mv64x60_base + MV64360_MPSC2MEM_BAR_ENABLE, enables);
}
#endif
/* MPSC 0/1 Rx & Tx get clocks BRG0/1 */
- MV64x60_REG_WRITE(mpsc_routing_base + MPSC_RCRR, 0x00000100);
- MV64x60_REG_WRITE(mpsc_routing_base + MPSC_TCRR, 0x00000100);
+ out_le32(mv64x60_base + mpsc_routing_base + MPSC_RCRR, 0x00000100);
+ out_le32(mv64x60_base + mpsc_routing_base + MPSC_TCRR, 0x00000100);
/* clear pending interrupts */
- MV64x60_REG_WRITE(MV64x60_SDMA_INTR_OFFSET + SDMA_INTR_MASK, 0);
+ out_le32(mv64x60_base + MV64x60_SDMA_INTR_OFFSET + SDMA_INTR_MASK, 0);
- MV64x60_REG_WRITE(SDMA_SCRDP + sdma_base, &rd[chan][0]);
- MV64x60_REG_WRITE(SDMA_SCTDP + sdma_base, &td[chan][TX_NUM_DESC - 1]);
- MV64x60_REG_WRITE(SDMA_SFTDP + sdma_base, &td[chan][TX_NUM_DESC - 1]);
+ out_le32(mv64x60_base + SDMA_SCRDP + sdma_base, (int)&rd[chan][0]);
+ out_le32(mv64x60_base + SDMA_SCTDP + sdma_base,
+ (int)&td[chan][TX_NUM_DESC - 1]);
+ out_le32(mv64x60_base + SDMA_SFTDP + sdma_base,
+ (int)&td[chan][TX_NUM_DESC - 1]);
- MV64x60_REG_WRITE(SDMA_SDC + sdma_base,
+ out_le32(mv64x60_base + SDMA_SDC + sdma_base,
SDMA_SDC_RFT | SDMA_SDC_SFM | SDMA_SDC_BLMR | SDMA_SDC_BLMT |
(3 << 12));
cdv = ((mv64x60_mpsc_clk_freq/(32*mv64x60_console_baud))-1);
- MV64x60_REG_WRITE(brg_bcr,
+ out_le32(mv64x60_base + brg_bcr,
((mv64x60_mpsc_clk_src << 18) | (1 << 16) | cdv));
/* Put MPSC into UART mode, no null modem, 16x clock mode */
- MV64x60_REG_WRITE(MPSC_MMCRL + mpsc_base[chan], 0x000004c4);
- MV64x60_REG_WRITE(MPSC_MMCRH + mpsc_base[chan], 0x04400400);
-
- MV64x60_REG_WRITE(MPSC_CHR_1 + mpsc_base[chan], 0);
- MV64x60_REG_WRITE(MPSC_CHR_9 + mpsc_base[chan], 0);
- MV64x60_REG_WRITE(MPSC_CHR_10 + mpsc_base[chan], 0);
- MV64x60_REG_WRITE(MPSC_CHR_3 + mpsc_base[chan], 4);
- MV64x60_REG_WRITE(MPSC_CHR_4 + mpsc_base[chan], 0);
- MV64x60_REG_WRITE(MPSC_CHR_5 + mpsc_base[chan], 0);
- MV64x60_REG_WRITE(MPSC_CHR_6 + mpsc_base[chan], 0);
- MV64x60_REG_WRITE(MPSC_CHR_7 + mpsc_base[chan], 0);
- MV64x60_REG_WRITE(MPSC_CHR_8 + mpsc_base[chan], 0);
+ out_le32(mv64x60_base + MPSC_MMCRL + mpsc_base[chan], 0x000004c4);
+ out_le32(mv64x60_base + MPSC_MMCRH + mpsc_base[chan], 0x04400400);
+
+ out_le32(mv64x60_base + MPSC_CHR_1 + mpsc_base[chan], 0);
+ out_le32(mv64x60_base + MPSC_CHR_9 + mpsc_base[chan], 0);
+ out_le32(mv64x60_base + MPSC_CHR_10 + mpsc_base[chan], 0);
+ out_le32(mv64x60_base + MPSC_CHR_3 + mpsc_base[chan], 4);
+ out_le32(mv64x60_base + MPSC_CHR_4 + mpsc_base[chan], 0);
+ out_le32(mv64x60_base + MPSC_CHR_5 + mpsc_base[chan], 0);
+ out_le32(mv64x60_base + MPSC_CHR_6 + mpsc_base[chan], 0);
+ out_le32(mv64x60_base + MPSC_CHR_7 + mpsc_base[chan], 0);
+ out_le32(mv64x60_base + MPSC_CHR_8 + mpsc_base[chan], 0);
/* 8 data bits, 1 stop bit */
- MV64x60_REG_WRITE(MPSC_MPCR + mpsc_base[chan], (3 << 12));
- MV64x60_REG_WRITE(SDMA_SDCM + sdma_base, SDMA_SDCM_ERD);
- MV64x60_REG_WRITE(MPSC_CHR_2 + mpsc_base[chan], MPSC_CHR_2_EH);
+ out_le32(mv64x60_base + MPSC_MPCR + mpsc_base[chan], (3 << 12));
+ out_le32(mv64x60_base + SDMA_SDCM + sdma_base, SDMA_SDCM_ERD);
+ out_le32(mv64x60_base + MPSC_CHR_2 + mpsc_base[chan], MPSC_CHR_2_EH);
udelay(100);
@@ -271,20 +251,19 @@ stop_dma(int chan)
int i;
/* Abort MPSC Rx (aborting Tx messes things up) */
- MV64x60_REG_WRITE(MPSC_CHR_2 + mpsc_base[chan], MPSC_CHR_2_RA);
+ out_le32(mv64x60_base + MPSC_CHR_2 + mpsc_base[chan], MPSC_CHR_2_RA);
/* Abort SDMA Rx, Tx */
- MV64x60_REG_WRITE(sdma_regs[chan].sdcm, SDMA_SDCM_AR | SDMA_SDCM_STD);
+ out_le32(mv64x60_base + sdma_regs[chan].sdcm,
+ SDMA_SDCM_AR | SDMA_SDCM_STD);
for (i=0; i<MAX_RESET_WAIT; i++) {
- if ((MV64x60_REG_READ(sdma_regs[chan].sdcm) &
+ if ((in_le32(mv64x60_base + sdma_regs[chan].sdcm) &
(SDMA_SDCM_AR | SDMA_SDCM_AT)) == 0)
break;
udelay(100);
}
-
- return;
}
static int
@@ -293,7 +272,7 @@ wait_for_ownership(int chan)
int i;
for (i=0; i<MAX_TX_WAIT; i++) {
- if ((MV64x60_REG_READ(sdma_regs[chan].sdcm) &
+ if ((in_le32(mv64x60_base + sdma_regs[chan].sdcm) &
SDMA_SDCM_TXD) == 0)
break;
@@ -321,12 +300,11 @@ serial_putc(unsigned long com_port, unsigned char c)
tdp->cmd_stat = SDMA_DESC_CMDSTAT_L | SDMA_DESC_CMDSTAT_F |
SDMA_DESC_CMDSTAT_O;
- MV64x60_REG_WRITE(sdma_regs[com_port].sctdp, tdp);
- MV64x60_REG_WRITE(sdma_regs[com_port].sftdp, tdp);
- MV64x60_REG_WRITE(sdma_regs[com_port].sdcm,
- MV64x60_REG_READ(sdma_regs[com_port].sdcm) | SDMA_SDCM_TXD);
-
- return;
+ out_le32(mv64x60_base + sdma_regs[com_port].sctdp, (int)tdp);
+ out_le32(mv64x60_base + sdma_regs[com_port].sftdp, (int)tdp);
+ out_le32(mv64x60_base + sdma_regs[com_port].sdcm,
+ in_le32(mv64x60_base + sdma_regs[com_port].sdcm) |
+ SDMA_SDCM_TXD);
}
unsigned char
@@ -366,8 +344,7 @@ serial_tstc(unsigned long com_port)
if (++cur_rd[com_port] >= RX_NUM_DESC)
cur_rd[com_port] = 0;
rdp = (struct mv64x60_rx_desc *)rdp->next_desc_ptr;
- }
- else {
+ } else {
rc = 1;
break;
}
@@ -380,5 +357,4 @@ void
serial_close(unsigned long com_port)
{
stop_dma(com_port);
- return;
}
diff --git a/arch/ppc/boot/simple/openbios.c b/arch/ppc/boot/simple/openbios.c
new file mode 100644
index 0000000000000..c732b6d70cfbe
--- /dev/null
+++ b/arch/ppc/boot/simple/openbios.c
@@ -0,0 +1,37 @@
+/*
+ * arch/ppc/boot/simple/openbios.c
+ *
+ * 2005 (c) SYSGO AG - g.jaeger@sysgo.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.
+ *
+ * Derived from arch/ppc/boot/simple/pibs.c (from MontaVista)
+ */
+
+#include <linux/types.h>
+#include <linux/config.h>
+#include <linux/string.h>
+#include <asm/ppcboot.h>
+#include <platforms/4xx/ebony.h>
+
+extern unsigned long decompress_kernel(unsigned long load_addr, int num_words,
+ unsigned long cksum);
+
+/* We need to make sure that this is before the images to ensure
+ * that it's in a mapped location. */
+bd_t hold_resid_buf __attribute__ ((__section__ (".data.boot")));
+bd_t *hold_residual = &hold_resid_buf;
+
+void *
+load_kernel(unsigned long load_addr, int num_words, unsigned long cksum,
+ void *ign1, void *ign2)
+{
+ decompress_kernel(load_addr, num_words, cksum);
+
+ /* simply copy the MAC addresses */
+ memcpy(hold_residual->bi_enetaddr, (char *)EBONY_OPENBIOS_MAC_BASE, 6);
+ memcpy(hold_residual->bi_enet1addr, (char *)(EBONY_OPENBIOS_MAC_BASE+EBONY_OPENBIOS_MAC_OFFSET), 6);
+
+ return (void *)hold_residual;
+}
diff --git a/arch/ppc/configs/chestnut_defconfig b/arch/ppc/configs/chestnut_defconfig
index 2c34eb8fde484..e219aad4d0e33 100644
--- a/arch/ppc/configs/chestnut_defconfig
+++ b/arch/ppc/configs/chestnut_defconfig
@@ -1,11 +1,12 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.10-rc2
-# Tue Dec 7 16:02:09 2004
+# Linux kernel version: 2.6.11
+# Fri Mar 11 14:32:49 2005
#
CONFIG_MMU=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_HAVE_DEC_LOCK=y
CONFIG_PPC=y
CONFIG_PPC32=y
@@ -35,6 +36,7 @@ CONFIG_KOBJECT_UEVENT=y
# CONFIG_EMBEDDED is not set
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -44,6 +46,7 @@ CONFIG_CC_ALIGN_LABELS=0
CONFIG_CC_ALIGN_LOOPS=0
CONFIG_CC_ALIGN_JUMPS=0
# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
#
# Loadable module support
@@ -78,7 +81,9 @@ CONFIG_NOT_COHERENT_CACHE=y
#
# CONFIG_PPC_MULTIPLATFORM is not set
# CONFIG_APUS is not set
+# CONFIG_KATANA is not set
# CONFIG_WILLOW is not set
+# CONFIG_CPCI690 is not set
# CONFIG_PCORE is not set
# CONFIG_POWERPMC250 is not set
CONFIG_CHESTNUT=y
@@ -91,6 +96,7 @@ CONFIG_CHESTNUT=y
# CONFIG_PRPMC750 is not set
# CONFIG_PRPMC800 is not set
# CONFIG_SANDPOINT is not set
+# CONFIG_RADSTONE_PPC7D is not set
# CONFIG_ADIR is not set
# CONFIG_K2 is not set
# CONFIG_PAL4 is not set
@@ -101,7 +107,9 @@ CONFIG_CHESTNUT=y
# CONFIG_RPX8260 is not set
# CONFIG_TQM8260 is not set
# CONFIG_ADS8272 is not set
+# CONFIG_PQ2FADS is not set
# CONFIG_LITE5200 is not set
+# CONFIG_MPC834x_SYS is not set
CONFIG_MV64360=y
CONFIG_MV64X60=y
@@ -128,6 +136,15 @@ CONFIG_PCI_LEGACY_PROC=y
CONFIG_PCI_NAMES=y
#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
# Advanced setup
#
CONFIG_ADVANCED_OPTIONS=y
@@ -154,6 +171,7 @@ CONFIG_BOOT_LOAD=0x00800000
#
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
#
# Memory Technology Devices (MTD)
@@ -181,6 +199,9 @@ 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_CFI_NOSWAP is not set
+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
CONFIG_MTD_MAP_BANK_WIDTH_1=y
CONFIG_MTD_MAP_BANK_WIDTH_2=y
CONFIG_MTD_MAP_BANK_WIDTH_4=y
@@ -198,13 +219,16 @@ 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_CHESTNUT=y
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0xfc000000
+CONFIG_MTD_PHYSMAP_LEN=0x02000000
+CONFIG_MTD_PHYSMAP_BANKWIDTH=4
#
# Self-contained MTD device drivers
@@ -214,6 +238,7 @@ CONFIG_MTD_CHESTNUT=y
# 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
@@ -244,11 +269,13 @@ CONFIG_MTD_CHESTNUT=y
# CONFIG_BLK_CPQ_CISS_DA is not set
# CONFIG_BLK_DEV_DAC960 is not set
# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_SX8 is not set
CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
@@ -262,6 +289,7 @@ CONFIG_IOSCHED_NOOP=y
CONFIG_IOSCHED_AS=y
CONFIG_IOSCHED_DEADLINE=y
CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
#
# ATA/ATAPI/MFM/RLL support
@@ -404,7 +432,6 @@ CONFIG_NET_PCI=y
# CONFIG_DGRS is not set
# CONFIG_EEPRO100 is not set
CONFIG_E100=y
-# CONFIG_E100_NAPI is not set
# CONFIG_FEALNX is not set
# CONFIG_NATSEMI is not set
# CONFIG_NE2K_PCI is not set
@@ -429,6 +456,10 @@ CONFIG_E100=y
# CONFIG_SK98LIN is not set
# CONFIG_VIA_VELOCITY is not set
# CONFIG_TIGON3 is not set
+CONFIG_MV643XX_ETH=y
+CONFIG_MV643XX_ETH_0=y
+CONFIG_MV643XX_ETH_1=y
+# CONFIG_MV643XX_ETH_2 is not set
#
# Ethernet (10000 Mbit)
@@ -485,14 +516,6 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
# CONFIG_INPUT_EVBUG is not set
#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-# CONFIG_SERIO is not set
-# CONFIG_SERIO_I8042 is not set
-
-#
# Input Device Drivers
#
# CONFIG_INPUT_KEYBOARD is not set
@@ -502,6 +525,13 @@ CONFIG_SOUND_GAMEPORT=y
# CONFIG_INPUT_MISC is not set
#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
+#
# Character devices
#
CONFIG_VT=y
@@ -520,6 +550,7 @@ CONFIG_SERIAL_8250_NR_UARTS=2
#
# Non-8250 serial port support
#
+# CONFIG_SERIAL_MPSC is not set
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
@@ -550,6 +581,11 @@ CONFIG_GEN_RTC=y
# CONFIG_RAW_DRIVER is not set
#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
# I2C support
#
# CONFIG_I2C is not set
@@ -606,6 +642,16 @@ CONFIG_USB_ARCH_HAS_OHCI=y
# CONFIG_USB_GADGET is not set
#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -614,6 +660,10 @@ CONFIG_EXT2_FS=y
# CONFIG_JBD is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
# CONFIG_XFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
@@ -664,6 +714,7 @@ CONFIG_RAMFS=y
CONFIG_JFFS2_FS=y
CONFIG_JFFS2_FS_DEBUG=0
# CONFIG_JFFS2_FS_NAND is not set
+# CONFIG_JFFS2_FS_NOR_ECC is not set
# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
CONFIG_JFFS2_ZLIB=y
CONFIG_JFFS2_RTIME=y
@@ -686,7 +737,6 @@ CONFIG_NFS_V3=y
CONFIG_ROOT_NFS=y
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
-# CONFIG_EXPORTFS is not set
CONFIG_SUNRPC=y
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
@@ -725,6 +775,7 @@ CONFIG_ZLIB_DEFLATE=y
# Kernel hacking
#
# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_PRINTK_TIME is not set
# CONFIG_SERIAL_TEXT_DEBUG is not set
#
@@ -737,3 +788,7 @@ CONFIG_ZLIB_DEFLATE=y
# Cryptographic options
#
# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
diff --git a/arch/parisc/configs/n4000_defconfig b/arch/ppc/configs/hdpu_defconfig
index 6cb334cb587e1..956a17897e331 100644
--- a/arch/parisc/configs/n4000_defconfig
+++ b/arch/ppc/configs/hdpu_defconfig
@@ -1,20 +1,23 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.10-pa5
-# Wed Jan 5 13:40:36 2005
+# Linux kernel version: 2.6.11
+# Wed Mar 16 12:43:19 2005
#
-CONFIG_PARISC=y
CONFIG_MMU=y
-CONFIG_STACK_GROWSUP=y
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_GENERIC_NVRAM=y
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-# CONFIG_CLEAN_COMPILE is not set
-CONFIG_BROKEN=y
-CONFIG_BROKEN_ON_SMP=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_LOCK_KERNEL=y
#
# General setup
@@ -22,19 +25,17 @@ CONFIG_BROKEN_ON_SMP=y
CONFIG_LOCALVERSION=""
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
-CONFIG_POSIX_MQUEUE=y
+# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=16
CONFIG_HOTPLUG=y
CONFIG_KOBJECT_UEVENT=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
+# CONFIG_IKCONFIG is not set
+# CONFIG_CPUSETS is not set
CONFIG_EMBEDDED=y
-CONFIG_KALLSYMS=y
-CONFIG_KALLSYMS_ALL=y
-# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_KALLSYMS is not set
+CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -44,48 +45,98 @@ 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=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
-
-#
-# Processor type and features
-#
-# CONFIG_PA7000 is not set
-# CONFIG_PA7100LC is not set
-# CONFIG_PA7200 is not set
-# CONFIG_PA7300LC is not set
-CONFIG_PA8X00=y
-CONFIG_PA20=y
-CONFIG_PREFETCH=y
-CONFIG_PARISC64=y
-CONFIG_64BIT=y
+CONFIG_STOP_MACHINE=y
+
+#
+# Processor
+#
+CONFIG_6xx=y
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+# CONFIG_E500 is not set
+CONFIG_ALTIVEC=y
+# CONFIG_TAU is not set
+# CONFIG_CPU_FREQ is not set
+# CONFIG_PM is not set
+CONFIG_PPC_STD_MMU=y
+# CONFIG_NOT_COHERENT_CACHE is not set
+
+#
+# Platform options
+#
+# CONFIG_PPC_MULTIPLATFORM is not set
+# CONFIG_APUS is not set
+# CONFIG_KATANA is not set
+# CONFIG_WILLOW is not set
+# CONFIG_CPCI690 is not set
+# CONFIG_PCORE is not set
+# CONFIG_POWERPMC250 is not set
+# CONFIG_CHESTNUT is not set
+# CONFIG_SPRUCE is not set
+CONFIG_HDPU=y
+# CONFIG_EV64260 is not set
+# CONFIG_LOPEC is not set
+# CONFIG_MCPN765 is not set
+# CONFIG_MVME5100 is not set
+# CONFIG_PPLUS is not set
+# CONFIG_PRPMC750 is not set
+# CONFIG_PRPMC800 is not set
+# CONFIG_SANDPOINT is not set
+# CONFIG_RADSTONE_PPC7D is not set
+# CONFIG_ADIR is not set
+# CONFIG_K2 is not set
+# CONFIG_PAL4 is not set
+# CONFIG_GEMINI is not set
+# CONFIG_EST8260 is not set
+# CONFIG_SBC82xx is not set
+# CONFIG_SBS8260 is not set
+# CONFIG_RPX8260 is not set
+# CONFIG_TQM8260 is not set
+# CONFIG_ADS8272 is not set
+# CONFIG_PQ2FADS is not set
+# CONFIG_LITE5200 is not set
+# CONFIG_MPC834x_SYS is not set
+CONFIG_MV64360=y
+CONFIG_MV64X60=y
+
+#
+# Set bridge options
+#
+CONFIG_MV64X60_BASE=0xf1000000
+CONFIG_MV64X60_NEW_BASE=0xf1000000
# CONFIG_SMP is not set
-CONFIG_DISCONTIGMEM=y
-# CONFIG_PREEMPT is not set
-CONFIG_COMPAT=y
+# CONFIG_IRQ_ALL_CPUS is not set
+# CONFIG_NR_CPUS is not set
+CONFIG_PREEMPT=y
+CONFIG_HIGHMEM=y
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=y
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="root=/dev/nfs ip=auto"
#
-# Bus options (PCI, PCMCIA, EISA, GSC, ISA)
+# Bus options
#
-# CONFIG_GSC is not set
+CONFIG_GENERIC_ISA_DMA=y
CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
CONFIG_PCI_LEGACY_PROC=y
CONFIG_PCI_NAMES=y
-CONFIG_PCI_LBA=y
-CONFIG_IOSAPIC=y
-CONFIG_IOMMU_SBA=y
-# CONFIG_SUPERIO is not set
-CONFIG_CHASSIS_LCD_LED=y
-# CONFIG_PDC_CHASSIS is not set
#
# PCCARD (PCMCIA/CardBus) support
@@ -93,36 +144,106 @@ CONFIG_CHASSIS_LCD_LED=y
# CONFIG_PCCARD is not set
#
-# PC-card bridges
+# Advanced setup
#
+CONFIG_ADVANCED_OPTIONS=y
+# CONFIG_HIGHMEM_START_BOOL is not set
+CONFIG_HIGHMEM_START=0xfe000000
+# CONFIG_LOWMEM_SIZE_BOOL is not set
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START_BOOL=y
+CONFIG_KERNEL_START=0x80000000
+# CONFIG_TASK_SIZE_BOOL is not set
+CONFIG_TASK_SIZE=0x80000000
+# CONFIG_BOOT_LOAD_BOOL is not set
+CONFIG_BOOT_LOAD=0x00800000
#
-# PCI Hotplug Support
+# Device Drivers
#
-# CONFIG_HOTPLUG_PCI is not set
#
-# Executable file formats
+# Generic Driver Options
#
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
#
-# Device Drivers
+# 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 is not set
#
-# Generic Driver Options
+# User Modules And Translation Layers
#
-# CONFIG_STANDALONE is not set
-# CONFIG_PREVENT_FIRMWARE_BUILD is not set
-CONFIG_FW_LOADER=y
-# CONFIG_DEBUG_DRIVER is not set
+CONFIG_MTD_CHAR=y
+# CONFIG_MTD_BLOCK is not set
+# CONFIG_MTD_BLOCK_RO is not set
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
#
-# Memory Technology Devices (MTD)
+# 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
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0xfc000000
+CONFIG_MTD_PHYSMAP_LEN=0x04000000
+CONFIG_MTD_PHYSMAP_BANKWIDTH=4
+
+#
+# Self-contained MTD device drivers
#
-# CONFIG_MTD is not set
+# 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
#
# Parallel port support
@@ -140,19 +261,19 @@ CONFIG_FW_LOADER=y
# 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=m
+# 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=6144
+CONFIG_BLK_DEV_RAM_SIZE=8192
CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
-CONFIG_CDROM_PKTCDVD=m
-CONFIG_CDROM_PKTCDVD_BUFFERS=8
-# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+# CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
#
# IO Schedulers
@@ -161,6 +282,7 @@ CONFIG_IOSCHED_NOOP=y
CONFIG_IOSCHED_AS=y
CONFIG_IOSCHED_DEADLINE=y
CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
#
# ATA/ATAPI/MFM/RLL support
@@ -186,15 +308,16 @@ CONFIG_CHR_DEV_SG=y
#
# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
#
-CONFIG_SCSI_MULTI_LUN=y
-# CONFIG_SCSI_CONSTANTS is not set
+# 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=m
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
#
# SCSI low-level drivers
@@ -203,15 +326,19 @@ CONFIG_SCSI_FC_ATTRS=m
# 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=y
+CONFIG_AIC7XXX_CMDS_PER_DEVICE=32
+CONFIG_AIC7XXX_RESET_DELAY_MS=15000
+# CONFIG_AIC7XXX_DEBUG_ENABLE is not set
+CONFIG_AIC7XXX_DEBUG_MASK=0
+# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set
# CONFIG_SCSI_AIC7XXX_OLD is not set
# CONFIG_SCSI_AIC79XX is not set
-# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_DPT_I2O is not set
# CONFIG_MEGARAID_NEWGEN is not set
# CONFIG_MEGARAID_LEGACY is not set
# CONFIG_SCSI_SATA is not set
# CONFIG_SCSI_BUSLOGIC is not set
-# CONFIG_SCSI_CPQFCTS is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_EATA is not set
# CONFIG_SCSI_EATA_PIO is not set
@@ -220,51 +347,31 @@ CONFIG_SCSI_FC_ATTRS=m
# 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=y
+# CONFIG_SCSI_SYM53C8XX_2 is not set
# CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_PCI2000 is not set
-# CONFIG_SCSI_PCI2220I is not set
# CONFIG_SCSI_QLOGIC_ISP is not set
-CONFIG_SCSI_QLOGIC_FC=m
-# CONFIG_SCSI_QLOGIC_FC_FIRMWARE is not set
-CONFIG_SCSI_QLOGIC_1280=m
-# CONFIG_SCSI_QLOGIC_1280_1040 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=m
-CONFIG_SCSI_QLA2322=m
-CONFIG_SCSI_QLA6312=m
-CONFIG_SCSI_QLA6322=m
+# CONFIG_SCSI_QLA2300 is not set
+# CONFIG_SCSI_QLA2322 is not set
+# CONFIG_SCSI_QLA6312 is not set
# CONFIG_SCSI_DC395x is not set
# CONFIG_SCSI_DC390T is not set
-CONFIG_SCSI_DEBUG=m
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
#
# Multi-device support (RAID and LVM)
#
-CONFIG_MD=y
-CONFIG_BLK_DEV_MD=y
-CONFIG_MD_LINEAR=y
-CONFIG_MD_RAID0=y
-CONFIG_MD_RAID1=y
-# CONFIG_MD_RAID10 is not set
-# CONFIG_MD_RAID5 is not set
-# CONFIG_MD_RAID6 is not set
-# CONFIG_MD_MULTIPATH is not set
-# CONFIG_MD_FAULTY is not set
-# CONFIG_BLK_DEV_DM is not set
+# CONFIG_MD is not set
#
# Fusion MPT device support
#
-CONFIG_FUSION=m
-CONFIG_FUSION_MAX_SGE=40
-CONFIG_FUSION_CTL=m
+# CONFIG_FUSION is not set
#
# IEEE 1394 (FireWire) support
@@ -277,6 +384,10 @@ CONFIG_FUSION_CTL=m
# CONFIG_I2O is not set
#
+# Macintosh device drivers
+#
+
+#
# Networking support
#
CONFIG_NET=y
@@ -286,14 +397,14 @@ CONFIG_NET=y
#
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
-CONFIG_NETLINK_DEV=y
+# CONFIG_NETLINK_DEV is not set
CONFIG_UNIX=y
-CONFIG_NET_KEY=m
+# CONFIG_NET_KEY is not set
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
# CONFIG_IP_ADVANCED_ROUTER is not set
CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_DHCP is not set
CONFIG_IP_PNP_BOOTP=y
# CONFIG_IP_PNP_RARP is not set
# CONFIG_NET_IPIP is not set
@@ -301,88 +412,14 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_IP_MROUTE is not set
# CONFIG_ARPD is not set
# CONFIG_SYN_COOKIES is not set
-CONFIG_INET_AH=m
-CONFIG_INET_ESP=m
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
# CONFIG_INET_TUNNEL is not set
-CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG is not set
# CONFIG_IP_TCPDIAG_IPV6 is not set
-
-#
-# IP: Virtual Server Configuration
-#
-# CONFIG_IP_VS is not set
# CONFIG_IPV6 is not set
-CONFIG_NETFILTER=y
-# CONFIG_NETFILTER_DEBUG is not set
-
-#
-# IP: Netfilter Configuration
-#
-CONFIG_IP_NF_CONNTRACK=m
-# CONFIG_IP_NF_CT_ACCT is not set
-# CONFIG_IP_NF_CONNTRACK_MARK 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_TFTP=m
-CONFIG_IP_NF_AMANDA=m
-CONFIG_IP_NF_QUEUE=m
-CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_LIMIT=m
-CONFIG_IP_NF_MATCH_IPRANGE=m
-CONFIG_IP_NF_MATCH_MAC=m
-CONFIG_IP_NF_MATCH_PKTTYPE=m
-CONFIG_IP_NF_MATCH_MARK=m
-CONFIG_IP_NF_MATCH_MULTIPORT=m
-CONFIG_IP_NF_MATCH_TOS=m
-CONFIG_IP_NF_MATCH_RECENT=m
-CONFIG_IP_NF_MATCH_ECN=m
-CONFIG_IP_NF_MATCH_DSCP=m
-CONFIG_IP_NF_MATCH_AH_ESP=m
-CONFIG_IP_NF_MATCH_LENGTH=m
-CONFIG_IP_NF_MATCH_TTL=m
-CONFIG_IP_NF_MATCH_TCPMSS=m
-CONFIG_IP_NF_MATCH_HELPER=m
-CONFIG_IP_NF_MATCH_STATE=m
-CONFIG_IP_NF_MATCH_CONNTRACK=m
-CONFIG_IP_NF_MATCH_OWNER=m
-CONFIG_IP_NF_MATCH_ADDRTYPE=m
-CONFIG_IP_NF_MATCH_REALM=m
-CONFIG_IP_NF_MATCH_SCTP=m
-CONFIG_IP_NF_MATCH_COMMENT=m
-CONFIG_IP_NF_MATCH_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_RAW=m
-CONFIG_IP_NF_TARGET_NOTRACK=m
-CONFIG_IP_NF_ARPTABLES=m
-CONFIG_IP_NF_ARPFILTER=m
-CONFIG_IP_NF_ARP_MANGLE=m
-# CONFIG_IP_NF_COMPAT_IPCHAINS is not set
-# CONFIG_IP_NF_COMPAT_IPFWADM is not set
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=m
+# CONFIG_NETFILTER is not set
#
# SCTP Configuration (EXPERIMENTAL)
@@ -392,8 +429,7 @@ CONFIG_XFRM_USER=m
# CONFIG_BRIDGE is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
-CONFIG_LLC=m
-CONFIG_LLC2=m
+# CONFIG_LLC2 is not set
# CONFIG_IPX is not set
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
@@ -406,23 +442,22 @@ CONFIG_LLC2=m
# QoS and/or fair queueing
#
# CONFIG_NET_SCHED is not set
-CONFIG_NET_CLS_ROUTE=y
+# CONFIG_NET_CLS_ROUTE is not set
#
# Network testing
#
-CONFIG_NET_PKTGEN=m
+# 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=m
-CONFIG_BONDING=m
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
-CONFIG_TUN=m
-# CONFIG_ETHERTAP is not set
+# CONFIG_TUN is not set
#
# ARCnet devices
@@ -433,75 +468,40 @@ CONFIG_TUN=m
# Ethernet (10 or 100Mbit)
#
CONFIG_NET_ETHERNET=y
-CONFIG_MII=m
+CONFIG_MII=y
# CONFIG_HAPPYMEAL is not set
# CONFIG_SUNGEM is not set
-CONFIG_NET_VENDOR_3COM=y
-CONFIG_VORTEX=m
-CONFIG_TYPHOON=m
+# CONFIG_NET_VENDOR_3COM is not set
#
# Tulip family network device support
#
-CONFIG_NET_TULIP=y
-CONFIG_DE2104X=y
-CONFIG_TULIP=y
-# CONFIG_TULIP_MWI is not set
-CONFIG_TULIP_MMIO=y
-# CONFIG_TULIP_NAPI is not set
-# CONFIG_DE4X5 is not set
-# CONFIG_WINBOND_840 is not set
-# CONFIG_DM9102 is not set
-CONFIG_HP100=m
-CONFIG_NET_PCI=y
-CONFIG_PCNET32=m
-# 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=m
-# CONFIG_EEPRO100_PIO is not set
-CONFIG_E100=m
-CONFIG_E100_NAPI=y
-# CONFIG_FEALNX is not set
-CONFIG_NATSEMI=m
-# 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 is not set
-CONFIG_EPIC100=m
-# CONFIG_SUNDANCE is not set
-CONFIG_VIA_RHINE=m
-CONFIG_VIA_RHINE_MMIO=y
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
#
# Ethernet (1000 Mbit)
#
-CONFIG_ACENIC=m
-CONFIG_ACENIC_OMIT_TIGON_I=y
-CONFIG_DL2K=m
-CONFIG_E1000=m
-CONFIG_E1000_NAPI=y
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
# CONFIG_R8169 is not set
# CONFIG_SK98LIN is not set
-# CONFIG_VIA_VELOCITY is not set
-CONFIG_TIGON3=m
+# CONFIG_TIGON3 is not set
+CONFIG_MV643XX_ETH=y
+CONFIG_MV643XX_ETH_0=y
+# CONFIG_MV643XX_ETH_1 is not set
+# CONFIG_MV643XX_ETH_2 is not set
#
# Ethernet (10000 Mbit)
#
-CONFIG_IXGB=m
-CONFIG_IXGB_NAPI=y
-CONFIG_S2IO=m
-CONFIG_S2IO_NAPI=y
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
#
# Token Ring devices
@@ -511,27 +511,7 @@ CONFIG_S2IO_NAPI=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 is not set
-
-#
-# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
-#
-# CONFIG_PRISM54 is not set
-CONFIG_NET_WIRELESS=y
+# CONFIG_NET_RADIO is not set
#
# Wan interfaces
@@ -539,14 +519,7 @@ CONFIG_NET_WIRELESS=y
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
-CONFIG_PPP=m
-# CONFIG_PPP_MULTILINK is not set
-# CONFIG_PPP_FILTER is not set
-CONFIG_PPP_ASYNC=m
-CONFIG_PPP_SYNC_TTY=m
-CONFIG_PPP_DEFLATE=m
-CONFIG_PPP_BSDCOMP=m
-# CONFIG_PPPOE is not set
+# CONFIG_PPP is not set
# CONFIG_SLIP is not set
# CONFIG_NET_FC is not set
# CONFIG_SHAPER is not set
@@ -570,20 +543,16 @@ CONFIG_INPUT=y
#
# Userland interfaces
#
-# CONFIG_INPUT_MOUSEDEV is not set
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
# CONFIG_INPUT_JOYDEV is not set
# CONFIG_INPUT_TSDEV is not set
# CONFIG_INPUT_EVDEV is not set
# CONFIG_INPUT_EVBUG is not set
#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-# CONFIG_SERIO is not set
-
-#
# Input Device Drivers
#
# CONFIG_INPUT_KEYBOARD is not set
@@ -593,35 +562,33 @@ CONFIG_SOUND_GAMEPORT=y
# CONFIG_INPUT_MISC is not set
#
+# Hardware I/O ports
+#
+# 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
#
# Serial drivers
#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_NR_UARTS=8
-CONFIG_SERIAL_8250_EXTENDED=y
-CONFIG_SERIAL_8250_MANY_PORTS=y
-CONFIG_SERIAL_8250_SHARE_IRQ=y
-# CONFIG_SERIAL_8250_DETECT_IRQ is not set
-# CONFIG_SERIAL_8250_MULTIPORT is not set
-# CONFIG_SERIAL_8250_RSA is not set
+# CONFIG_SERIAL_8250 is not set
#
# Non-8250 serial port support
#
-# CONFIG_SERIAL_MUX is not set
-CONFIG_PDC_CONSOLE=y
+CONFIG_SERIAL_MPSC=y
+CONFIG_SERIAL_MPSC_CONSOLE=y
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
-# CONFIG_LEGACY_PTYS is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
#
# IPMI
@@ -632,8 +599,9 @@ CONFIG_UNIX98_PTYS=y
# Watchdog Cards
#
# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
CONFIG_GEN_RTC=y
-CONFIG_GEN_RTC_X=y
+# CONFIG_GEN_RTC_X is not set
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
@@ -643,8 +611,12 @@ CONFIG_GEN_RTC_X=y
#
# CONFIG_AGP is not set
# CONFIG_DRM is not set
-CONFIG_RAW_DRIVER=y
-CONFIG_MAX_RAW_DEVS=256
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
#
# I2C support
@@ -676,13 +648,6 @@ CONFIG_MAX_RAW_DEVS=256
# CONFIG_FB is not set
#
-# Console display driver support
-#
-CONFIG_DUMMY_CONSOLE_COLUMNS=160
-CONFIG_DUMMY_CONSOLE_ROWS=64
-CONFIG_DUMMY_CONSOLE=y
-
-#
# Sound
#
# CONFIG_SOUND is not set
@@ -690,13 +655,9 @@ CONFIG_DUMMY_CONSOLE=y
#
# USB support
#
-# CONFIG_USB is not set
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
+# CONFIG_USB is not set
#
# USB Gadget Support
@@ -709,6 +670,11 @@ CONFIG_USB_ARCH_HAS_OHCI=y
# CONFIG_MMC is not set
#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -718,22 +684,19 @@ CONFIG_EXT3_FS=y
CONFIG_JBD=y
# CONFIG_JBD_DEBUG is not set
# CONFIG_REISERFS_FS is not set
-CONFIG_JFS_FS=m
-# CONFIG_JFS_POSIX_ACL is not set
-# CONFIG_JFS_DEBUG is not set
-# CONFIG_JFS_STATISTICS is not set
+# CONFIG_JFS_FS is not set
CONFIG_FS_POSIX_ACL=y
-CONFIG_XFS_FS=m
-# CONFIG_XFS_RT is not set
-# CONFIG_XFS_QUOTA is not set
-# CONFIG_XFS_SECURITY is not set
-# CONFIG_XFS_POSIX_ACL is not set
+
+#
+# XFS support
+#
+# CONFIG_XFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
# CONFIG_QUOTA is not set
-# CONFIG_DNOTIFY is not set
+CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
-CONFIG_AUTOFS4_FS=y
+# CONFIG_AUTOFS4_FS is not set
#
# CD-ROM/DVD Filesystems
@@ -741,17 +704,14 @@ CONFIG_AUTOFS4_FS=y
CONFIG_ISO9660_FS=y
CONFIG_JOLIET=y
# CONFIG_ZISOFS is not set
-CONFIG_UDF_FS=m
+CONFIG_UDF_FS=y
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_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
# CONFIG_NTFS_FS is not set
#
@@ -764,7 +724,6 @@ CONFIG_SYSFS=y
# CONFIG_DEVPTS_FS_XATTR is not set
CONFIG_TMPFS=y
# CONFIG_TMPFS_XATTR is not set
-# CONFIG_HUGETLBFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
@@ -778,13 +737,21 @@ CONFIG_RAMFS=y
# CONFIG_BEFS_FS is not set
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_JFFS2_FS_NAND is not set
+# CONFIG_JFFS2_FS_NOR_ECC is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
# CONFIG_CRAMFS 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=m
-# CONFIG_UFS_FS_WRITE is not set
+# CONFIG_UFS_FS is not set
#
# Network File Systems
@@ -793,25 +760,20 @@ CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
CONFIG_NFS_V4=y
CONFIG_NFS_DIRECTIO=y
-CONFIG_NFSD=m
+CONFIG_NFSD=y
CONFIG_NFSD_V3=y
CONFIG_NFSD_V4=y
CONFIG_NFSD_TCP=y
CONFIG_ROOT_NFS=y
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
-CONFIG_EXPORTFS=m
+CONFIG_EXPORTFS=y
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=y
CONFIG_RPCSEC_GSS_KRB5=y
# CONFIG_RPCSEC_GSS_SPKM3 is not set
-CONFIG_SMB_FS=m
-CONFIG_SMB_NLS_DEFAULT=y
-CONFIG_SMB_NLS_REMOTE="cp437"
-CONFIG_CIFS=m
-# CONFIG_CIFS_STATS is not set
-# CONFIG_CIFS_XATTR is not set
-# CONFIG_CIFS_EXPERIMENTAL is not set
+# CONFIG_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
@@ -827,19 +789,19 @@ CONFIG_MSDOS_PARTITION=y
#
CONFIG_NLS=y
CONFIG_NLS_DEFAULT="iso8859-1"
-CONFIG_NLS_CODEPAGE_437=m
+# 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=m
-CONFIG_NLS_CODEPAGE_852=m
+# 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=m
+# CONFIG_NLS_CODEPAGE_863 is not set
# CONFIG_NLS_CODEPAGE_864 is not set
-CONFIG_NLS_CODEPAGE_865=m
+# 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
@@ -851,37 +813,42 @@ CONFIG_NLS_CODEPAGE_865=m
# CONFIG_NLS_CODEPAGE_1250 is not set
# CONFIG_NLS_CODEPAGE_1251 is not set
# CONFIG_NLS_ASCII is not set
-CONFIG_NLS_ISO8859_1=m
-CONFIG_NLS_ISO8859_2=m
-CONFIG_NLS_ISO8859_3=m
-CONFIG_NLS_ISO8859_4=m
+# 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=m
+# CONFIG_NLS_ISO8859_15 is not set
# CONFIG_NLS_KOI8_R is not set
# CONFIG_NLS_KOI8_U is not set
-CONFIG_NLS_UTF8=m
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
#
# Profiling support
#
-CONFIG_PROFILING=y
-CONFIG_OPROFILE=m
+# CONFIG_PROFILING is not set
#
# Kernel hacking
#
-CONFIG_DEBUG_KERNEL=y
-CONFIG_MAGIC_SYSRQ=y
-# CONFIG_SCHEDSTATS is not set
-# CONFIG_DEBUG_SLAB is not set
-# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_KOBJECT is not set
-# CONFIG_DEBUG_INFO is not set
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=15
+# CONFIG_SERIAL_TEXT_DEBUG is not set
#
# Security options
@@ -893,35 +860,31 @@ CONFIG_MAGIC_SYSRQ=y
# Cryptographic options
#
CONFIG_CRYPTO=y
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_NULL=m
-CONFIG_CRYPTO_MD4=m
+# 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=m
-CONFIG_CRYPTO_SHA256=m
-CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_WP512=m
+# 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=m
-CONFIG_CRYPTO_TWOFISH=m
-CONFIG_CRYPTO_SERPENT=m
-CONFIG_CRYPTO_AES=m
-CONFIG_CRYPTO_CAST5=m
-CONFIG_CRYPTO_CAST6=m
-CONFIG_CRYPTO_TEA=m
+# CONFIG_CRYPTO_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=m
-CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_DEFLATE=m
+# 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=m
-CONFIG_CRYPTO_TEST=m
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_TEST is not set
#
-# Library routines
+# Hardware crypto devices
#
-CONFIG_CRC_CCITT=m
-CONFIG_CRC32=y
-CONFIG_LIBCRC32C=m
-CONFIG_ZLIB_INFLATE=m
-CONFIG_ZLIB_DEFLATE=m
diff --git a/arch/ppc/configs/katana_defconfig b/arch/ppc/configs/katana_defconfig
index 0134ae18c9b98..f0b0d57201540 100644
--- a/arch/ppc/configs/katana_defconfig
+++ b/arch/ppc/configs/katana_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc2
-# Tue Jan 25 16:31:13 2005
+# Linux kernel version: 2.6.11
+# Tue Mar 8 17:31:00 2005
#
CONFIG_MMU=y
CONFIG_GENERIC_HARDIRQS=y
@@ -36,6 +36,7 @@ CONFIG_KOBJECT_UEVENT=y
# CONFIG_EMBEDDED is not set
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -45,6 +46,7 @@ CONFIG_CC_ALIGN_LABELS=0
CONFIG_CC_ALIGN_LOOPS=0
CONFIG_CC_ALIGN_JUMPS=0
# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
#
# Loadable module support
@@ -70,6 +72,7 @@ CONFIG_6xx=y
CONFIG_ALTIVEC=y
# CONFIG_TAU is not set
# CONFIG_CPU_FREQ is not set
+# CONFIG_83xx is not set
CONFIG_PPC_STD_MMU=y
CONFIG_NOT_COHERENT_CACHE=y
@@ -93,6 +96,7 @@ CONFIG_KATANA=y
# CONFIG_PRPMC750 is not set
# CONFIG_PRPMC800 is not set
# CONFIG_SANDPOINT is not set
+# CONFIG_RADSTONE_PPC7D is not set
# CONFIG_ADIR is not set
# CONFIG_K2 is not set
# CONFIG_PAL4 is not set
@@ -152,8 +156,8 @@ CONFIG_KERNEL_START=0xc0000000
CONFIG_TASK_SIZE=0x80000000
CONFIG_CONSISTENT_START_BOOL=y
CONFIG_CONSISTENT_START=0xf0000000
-# CONFIG_CONSISTENT_SIZE_BOOL is not set
-CONFIG_CONSISTENT_SIZE=0x00200000
+CONFIG_CONSISTENT_SIZE_BOOL=y
+CONFIG_CONSISTENT_SIZE=0x00400000
# CONFIG_BOOT_LOAD_BOOL is not set
CONFIG_BOOT_LOAD=0x00800000
@@ -171,7 +175,82 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
#
# Memory Technology Devices (MTD)
#
-# CONFIG_MTD is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_CONCAT=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_NOSWAP=y
+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
+CONFIG_MTD_CFI_GEOMETRY=y
+# CONFIG_MTD_MAP_BANK_WIDTH_1 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_2 is not set
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+# CONFIG_MTD_CFI_I1 is not set
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_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=y
+CONFIG_MTD_PHYSMAP_START=0xe0000000
+CONFIG_MTD_PHYSMAP_LEN=0x0
+CONFIG_MTD_PHYSMAP_BANKWIDTH=4
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+CONFIG_MTD_PHRAM=y
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
#
# Parallel port support
@@ -353,7 +432,6 @@ CONFIG_NET_PCI=y
# CONFIG_DGRS is not set
# CONFIG_EEPRO100 is not set
CONFIG_E100=y
-# CONFIG_E100_NAPI is not set
# CONFIG_FEALNX is not set
# CONFIG_NATSEMI is not set
# CONFIG_NE2K_PCI is not set
@@ -378,6 +456,10 @@ CONFIG_E100=y
# CONFIG_SK98LIN is not set
# CONFIG_VIA_VELOCITY is not set
# CONFIG_TIGON3 is not set
+CONFIG_MV643XX_ETH=y
+CONFIG_MV643XX_ETH_0=y
+CONFIG_MV643XX_ETH_1=y
+CONFIG_MV643XX_ETH_2=y
#
# Ethernet (10000 Mbit)
@@ -500,7 +582,90 @@ CONFIG_GEN_RTC=y
#
# I2C support
#
-# CONFIG_I2C is not set
+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_ISA is not set
+# CONFIG_I2C_MPC is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+# CONFIG_I2C_PCA_ISA is not set
+CONFIG_I2C_MV64XXX=y
+
+#
+# Hardware Sensors Chip support
+#
+# CONFIG_I2C_SENSOR is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+
+#
+# Other I2C Chip support
+#
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+CONFIG_SENSORS_M41T00=y
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
#
# Dallas's 1-wire bus
@@ -531,7 +696,6 @@ CONFIG_GEN_RTC=y
#
# CONFIG_VGA_CONSOLE is not set
CONFIG_DUMMY_CONSOLE=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
# Sound
@@ -573,6 +737,10 @@ CONFIG_EXT2_FS=y
# CONFIG_JBD is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
# CONFIG_XFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
@@ -619,6 +787,8 @@ CONFIG_RAMFS=y
# CONFIG_BEFS_FS is not set
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+# CONFIG_JFFS2_FS is not set
# CONFIG_CRAMFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_HPFS_FS is not set
@@ -637,7 +807,6 @@ CONFIG_NFS_V3=y
CONFIG_ROOT_NFS=y
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
-# CONFIG_EXPORTFS is not set
CONFIG_SUNRPC=y
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
@@ -674,6 +843,7 @@ CONFIG_CRC32=y
# Kernel hacking
#
# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_PRINTK_TIME is not set
#
# Security options
diff --git a/arch/ppc/configs/mpc834x_sys_defconfig b/arch/ppc/configs/mpc834x_sys_defconfig
new file mode 100644
index 0000000000000..4a5522ca8207e
--- /dev/null
+++ b/arch/ppc/configs/mpc834x_sys_defconfig
@@ -0,0 +1,644 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-rc4
+# Thu Feb 17 16:12:23 2005
+#
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_GENERIC_NVRAM=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+# CONFIG_KALLSYMS is not set
+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
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# Processor
+#
+CONFIG_6xx=y
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+# CONFIG_E500 is not set
+# CONFIG_CPU_FREQ is not set
+CONFIG_PPC_GEN550=y
+CONFIG_83xx=y
+
+#
+# Freescale 83xx options
+#
+CONFIG_MPC834x_SYS=y
+CONFIG_MPC834x=y
+CONFIG_PPC_STD_MMU=y
+
+#
+# Platform options
+#
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Bus options
+#
+CONFIG_GENERIC_ISA_DMA=y
+# CONFIG_PCI is not set
+# CONFIG_PCI_DOMAINS is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00800000
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_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_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=32768
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+
+#
+# Ethernet (1000 Mbit)
+#
+CONFIG_GIANFAR=y
+# CONFIG_GFAR_NAPI is not set
+
+#
+# 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
+
+#
+# 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 I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_SERIO is not set
+# CONFIG_SERIO_I8042 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# 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
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ISA is not set
+CONFIG_I2C_MPC=y
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Hardware Sensors Chip support
+#
+# CONFIG_I2C_SENSOR is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+
+#
+# Other I2C Chip support
+#
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS 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_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+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_CRC32=y
+# CONFIG_LIBCRC32C is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL 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/pmac_defconfig b/arch/ppc/configs/pmac_defconfig
index c8e1d5d0c70d6..8eebb04557665 100644
--- a/arch/ppc/configs/pmac_defconfig
+++ b/arch/ppc/configs/pmac_defconfig
@@ -1,8 +1,12 @@
#
# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-rc4
+# Sun Feb 13 14:56:58 2005
#
CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_HAVE_DEC_LOCK=y
CONFIG_PPC=y
CONFIG_PPC32=y
@@ -13,40 +17,45 @@ CONFIG_GENERIC_NVRAM=y
#
CONFIG_EXPERIMENTAL=y
CONFIG_CLEAN_COMPILE=y
-# CONFIG_STANDALONE is not set
CONFIG_BROKEN_ON_SMP=y
#
# General setup
#
+CONFIG_LOCALVERSION=""
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
CONFIG_POSIX_MQUEUE=y
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
-# CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
+CONFIG_LOG_BUF_SHIFT=16
CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
# CONFIG_EMBEDDED is not set
CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
CONFIG_FUTEX=y
CONFIG_EPOLL=y
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
#
# Loadable module support
#
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
-CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
CONFIG_OBSOLETE_MODPARM=y
-# CONFIG_MODVERSIONS is not set
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_KMOD=y
#
@@ -58,17 +67,21 @@ CONFIG_6xx=y
# CONFIG_POWER3 is not set
# CONFIG_POWER4 is not set
# CONFIG_8xx is not set
+# CONFIG_E500 is not set
CONFIG_ALTIVEC=y
CONFIG_TAU=y
# CONFIG_TAU_INT is not set
# CONFIG_TAU_AVERAGE is not set
CONFIG_CPU_FREQ=y
-CONFIG_CPU_FREQ_PROC_INTF=y
+# CONFIG_CPU_FREQ_DEBUG is not set
+CONFIG_CPU_FREQ_STAT=m
+CONFIG_CPU_FREQ_STAT_DETAILS=y
CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
-# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set
-# CONFIG_CPU_FREQ_GOV_USERSPACE is not set
+CONFIG_CPU_FREQ_GOV_POWERSAVE=m
+CONFIG_CPU_FREQ_GOV_USERSPACE=m
+CONFIG_CPU_FREQ_GOV_ONDEMAND=m
CONFIG_CPU_FREQ_PMAC=y
CONFIG_CPU_FREQ_TABLE=y
CONFIG_PPC601_SYNC_FIX=y
@@ -80,11 +93,14 @@ CONFIG_PPC_STD_MMU=y
#
CONFIG_PPC_MULTIPLATFORM=y
# CONFIG_APUS is not set
+# CONFIG_KATANA is not set
# CONFIG_WILLOW is not set
+# CONFIG_CPCI690 is not set
# CONFIG_PCORE is not set
# CONFIG_POWERPMC250 is not set
-# CONFIG_EV64260 is not set
+# CONFIG_CHESTNUT is not set
# CONFIG_SPRUCE is not set
+# CONFIG_EV64260 is not set
# CONFIG_LOPEC is not set
# CONFIG_MCPN765 is not set
# CONFIG_MVME5100 is not set
@@ -97,9 +113,13 @@ CONFIG_PPC_MULTIPLATFORM=y
# CONFIG_PAL4 is not set
# CONFIG_GEMINI is not set
# CONFIG_EST8260 is not set
+# CONFIG_SBC82xx is not set
# CONFIG_SBS8260 is not set
-# CONFIG_RPX6 is not set
+# CONFIG_RPX8260 is not set
# CONFIG_TQM8260 is not set
+# CONFIG_ADS8272 is not set
+# CONFIG_PQ2FADS is not set
+# CONFIG_LITE5200 is not set
CONFIG_PPC_CHRP=y
CONFIG_PPC_PMAC=y
CONFIG_PPC_PREP=y
@@ -108,11 +128,9 @@ CONFIG_PPCBUG_NVRAM=y
# CONFIG_SMP is not set
# CONFIG_PREEMPT is not set
# CONFIG_HIGHMEM is not set
-CONFIG_KERNEL_ELF=y
CONFIG_BINFMT_ELF=y
CONFIG_BINFMT_MISC=m
CONFIG_PROC_DEVICETREE=y
-CONFIG_PPC_RTAS=y
# CONFIG_PREP_RESIDUAL is not set
# CONFIG_CMDLINE_BOOL is not set
@@ -127,14 +145,21 @@ CONFIG_PCI_LEGACY_PROC=y
CONFIG_PCI_NAMES=y
#
-# PCMCIA/CardBus support
+# PCCARD (PCMCIA/CardBus) support
#
-CONFIG_PCMCIA=m
+CONFIG_PCCARD=m
# CONFIG_PCMCIA_DEBUG is not set
-CONFIG_YENTA=m
+CONFIG_PCMCIA=m
CONFIG_CARDBUS=y
-CONFIG_I82092=m
-CONFIG_TCIC=m
+
+#
+# PC-card bridges
+#
+CONFIG_YENTA=m
+# CONFIG_PD6729 is not set
+# CONFIG_I82092 is not set
+# CONFIG_TCIC is not set
+CONFIG_PCCARD_NONSTATIC=m
#
# Advanced setup
@@ -156,7 +181,10 @@ CONFIG_BOOT_LOAD=0x00800000
#
# Generic Driver Options
#
+# CONFIG_STANDALONE is not set
+CONFIG_PREVENT_FIRMWARE_BUILD=y
# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
#
# Memory Technology Devices (MTD)
@@ -176,18 +204,35 @@ CONFIG_BOOT_LOAD=0x00800000
# 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_CARMEL is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
CONFIG_LBD=y
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
#
# ATA/ATAPI/MFM/RLL support
@@ -198,16 +243,15 @@ 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_IDEDISK_STROKE is not set
-CONFIG_BLK_DEV_IDECS=m
+# CONFIG_BLK_DEV_IDECS is not set
CONFIG_BLK_DEV_IDECD=y
# CONFIG_BLK_DEV_IDETAPE is not set
CONFIG_BLK_DEV_IDEFLOPPY=y
CONFIG_BLK_DEV_IDESCSI=y
# CONFIG_IDE_TASK_IOCTL is not set
-# CONFIG_IDE_TASKFILE_IO is not set
#
# IDE chipset support/bugfixes
@@ -218,12 +262,11 @@ 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_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_ADMA=y
# CONFIG_BLK_DEV_AEC62XX is not set
# CONFIG_BLK_DEV_ALI15X3 is not set
# CONFIG_BLK_DEV_AMD74XX is not set
@@ -249,7 +292,7 @@ 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_BLK_DEV_IDEDMA_PMAC_AUTO=y
+# CONFIG_IDE_ARM is not set
CONFIG_BLK_DEV_IDEDMA=y
# CONFIG_IDEDMA_IVB is not set
CONFIG_IDEDMA_AUTO=y
@@ -275,7 +318,6 @@ CONFIG_CHR_DEV_SG=y
# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
#
# CONFIG_SCSI_MULTI_LUN is not set
-# CONFIG_SCSI_REPORT_LUNS is not set
CONFIG_SCSI_CONSTANTS=y
# CONFIG_SCSI_LOGGING is not set
@@ -284,33 +326,35 @@ CONFIG_SCSI_CONSTANTS=y
#
CONFIG_SCSI_SPI_ATTRS=y
# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
#
# SCSI low-level drivers
#
# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
# CONFIG_SCSI_ACARD is not set
# CONFIG_SCSI_AACRAID is not set
CONFIG_SCSI_AIC7XXX=m
CONFIG_AIC7XXX_CMDS_PER_DEVICE=253
CONFIG_AIC7XXX_RESET_DELAY_MS=15000
-# CONFIG_AIC7XXX_BUILD_FIRMWARE is not set
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_ADVANSYS=m
-# CONFIG_SCSI_MEGARAID is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
# CONFIG_SCSI_SATA is not set
# CONFIG_SCSI_BUSLOGIC is not set
-# CONFIG_SCSI_CPQFCTS is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_EATA is not set
# CONFIG_SCSI_EATA_PIO is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
# CONFIG_SCSI_GDTH is not set
# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
# CONFIG_SCSI_INIA100 is not set
CONFIG_SCSI_SYM53C8XX_2=y
CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
@@ -327,7 +371,6 @@ CONFIG_SCSI_QLA2XXX=y
# CONFIG_SCSI_QLA2300 is not set
# CONFIG_SCSI_QLA2322 is not set
# CONFIG_SCSI_QLA6312 is not set
-# CONFIG_SCSI_QLA6322 is not set
# CONFIG_SCSI_DC395x is not set
# CONFIG_SCSI_DC390T is not set
# CONFIG_SCSI_NSP32 is not set
@@ -384,7 +427,8 @@ CONFIG_IEEE1394_SBP2=m
CONFIG_IEEE1394_ETH1394=m
CONFIG_IEEE1394_DV1394=m
CONFIG_IEEE1394_RAWIO=m
-# CONFIG_IEEE1394_CMP is not set
+CONFIG_IEEE1394_CMP=m
+CONFIG_IEEE1394_AMDTP=m
#
# I2O device support
@@ -400,8 +444,6 @@ CONFIG_ADB_PMU=y
CONFIG_PMAC_PBOOK=y
CONFIG_PMAC_APM_EMU=y
CONFIG_PMAC_BACKLIGHT=y
-# CONFIG_MAC_FLOPPY is not set
-CONFIG_MAC_SERIAL=y
CONFIG_ADB_MACIO=y
CONFIG_INPUT_ADBHID=y
CONFIG_MAC_EMUMOUSEBTN=y
@@ -434,6 +476,9 @@ CONFIG_SYN_COOKIES=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
#
# IP: Virtual Server Configuration
@@ -447,11 +492,14 @@ CONFIG_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 is not set
+CONFIG_IP_NF_QUEUE=m
CONFIG_IP_NF_IPTABLES=m
CONFIG_IP_NF_MATCH_LIMIT=m
CONFIG_IP_NF_MATCH_IPRANGE=m
@@ -471,8 +519,17 @@ CONFIG_IP_NF_MATCH_HELPER=m
CONFIG_IP_NF_MATCH_STATE=m
CONFIG_IP_NF_MATCH_CONNTRACK=m
CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_REALM=m
+CONFIG_IP_NF_MATCH_SCTP=m
+CONFIG_IP_NF_MATCH_COMMENT=m
+CONFIG_IP_NF_MATCH_CONNMARK=m
+CONFIG_IP_NF_MATCH_HASHLIMIT=m
CONFIG_IP_NF_FILTER=m
CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=m
CONFIG_IP_NF_NAT=m
CONFIG_IP_NF_NAT_NEEDED=y
CONFIG_IP_NF_TARGET_MASQUERADE=m
@@ -484,17 +541,19 @@ CONFIG_IP_NF_NAT_IRC=m
CONFIG_IP_NF_NAT_FTP=m
CONFIG_IP_NF_NAT_TFTP=m
CONFIG_IP_NF_NAT_AMANDA=m
-# CONFIG_IP_NF_MANGLE is not set
-# CONFIG_IP_NF_TARGET_LOG is not set
-CONFIG_IP_NF_TARGET_ULOG=m
-CONFIG_IP_NF_TARGET_TCPMSS=m
+CONFIG_IP_NF_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
-CONFIG_IP_NF_COMPAT_IPCHAINS=m
-# CONFIG_IP_NF_COMPAT_IPFWADM is not set
-CONFIG_IP_NF_TARGET_NOTRACK=m
-CONFIG_IP_NF_RAW=m
#
# SCTP Configuration (EXPERIMENTAL)
@@ -512,12 +571,12 @@ CONFIG_IP_NF_RAW=m
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
#
# QoS and/or fair queueing
#
# CONFIG_NET_SCHED is not set
+CONFIG_NET_CLS_ROUTE=y
#
# Network testing
@@ -593,7 +652,6 @@ CONFIG_MII=y
CONFIG_MACE=y
# CONFIG_MACE_AAUI_PORT is not set
CONFIG_BMAC=y
-# CONFIG_OAKNET is not set
# CONFIG_HAPPYMEAL is not set
CONFIG_SUNGEM=y
# CONFIG_NET_VENDOR_3COM is not set
@@ -634,6 +692,7 @@ CONFIG_PCNET32=y
# CONFIG_YELLOWFIN is not set
# CONFIG_R8169 is not set
# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
# CONFIG_TIGON3 is not set
#
@@ -667,7 +726,6 @@ CONFIG_NET_RADIO=y
#
# Wireless 802.11b ISA/PCI cards support
#
-# CONFIG_AIRO is not set
CONFIG_HERMES=m
CONFIG_APPLE_AIRPORT=m
# CONFIG_PLX_HERMES is not set
@@ -691,15 +749,7 @@ CONFIG_NET_WIRELESS=y
#
# PCMCIA network device support
#
-CONFIG_NET_PCMCIA=y
-# CONFIG_PCMCIA_3C589 is not set
-# CONFIG_PCMCIA_3C574 is not set
-# CONFIG_PCMCIA_FMVJ18X is not set
-# CONFIG_PCMCIA_PCNET is not set
-# CONFIG_PCMCIA_NMCLAN is not set
-# CONFIG_PCMCIA_SMC91C92 is not set
-# CONFIG_PCMCIA_XIRC2PS is not set
-# CONFIG_PCMCIA_AXNET is not set
+# CONFIG_NET_PCMCIA is not set
#
# Wan interfaces
@@ -714,10 +764,9 @@ CONFIG_PPP_ASYNC=y
CONFIG_PPP_SYNC_TTY=m
CONFIG_PPP_DEFLATE=y
CONFIG_PPP_BSDCOMP=m
-# CONFIG_PPPOE is not set
+CONFIG_PPPOE=m
# CONFIG_SLIP is not set
# CONFIG_NET_FC is not set
-# CONFIG_RCPCI is not set
# CONFIG_SHAPER is not set
# CONFIG_NETCONSOLE is not set
@@ -740,7 +789,7 @@ CONFIG_INPUT=y
# Userland interfaces
#
CONFIG_INPUT_MOUSEDEV=y
-CONFIG_INPUT_MOUSEDEV_PSAUX=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
@@ -753,11 +802,8 @@ CONFIG_INPUT_EVDEV=y
#
# CONFIG_GAMEPORT is not set
CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
+# CONFIG_SERIO is not set
# CONFIG_SERIO_I8042 is not set
-# CONFIG_SERIO_SERPORT is not set
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PCIPS2 is not set
#
# Input Device Drivers
@@ -796,12 +842,12 @@ CONFIG_SERIAL_8250_NR_UARTS=4
# Non-8250 serial port support
#
CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_SERIAL_PMACZILOG=y
-# CONFIG_SERIAL_PMACZILOG_CONSOLE is not set
+CONFIG_SERIAL_PMACZILOG_CONSOLE=y
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
-# CONFIG_QIC02_TAPE is not set
#
# IPMI
@@ -822,9 +868,14 @@ CONFIG_GEN_RTC=y
#
# Ftape, the floppy tape device driver
#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
+CONFIG_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
#
# PCMCIA character devices
@@ -843,6 +894,7 @@ CONFIG_I2C_CHARDEV=m
#
CONFIG_I2C_ALGOBIT=y
# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
#
# I2C Hardware Bus support
@@ -857,6 +909,7 @@ CONFIG_I2C_ALGOBIT=y
# CONFIG_I2C_I810 is not set
# CONFIG_I2C_ISA is not set
CONFIG_I2C_KEYWEST=m
+# CONFIG_I2C_MPC is not set
# CONFIG_I2C_NFORCE2 is not set
# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_PIIX4 is not set
@@ -866,26 +919,38 @@ CONFIG_I2C_KEYWEST=m
# 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
#
# Hardware Sensors Chip support
#
# CONFIG_I2C_SENSOR is not set
# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ASB100 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_FSCHER is not set
# CONFIG_SENSORS_GL518SM is not set
# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
# CONFIG_SENSORS_LM78 is not set
# CONFIG_SENSORS_LM80 is not set
# CONFIG_SENSORS_LM83 is not set
# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
# CONFIG_SENSORS_VIA686A is not set
# CONFIG_SENSORS_W83781D is not set
# CONFIG_SENSORS_W83L785TS is not set
@@ -897,12 +962,18 @@ CONFIG_I2C_KEYWEST=m
# CONFIG_SENSORS_EEPROM is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
# CONFIG_I2C_DEBUG_CORE is not set
# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
# CONFIG_I2C_DEBUG_CHIP is not set
#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
# Misc devices
#
@@ -920,6 +991,9 @@ CONFIG_I2C_KEYWEST=m
# Graphics support
#
CONFIG_FB=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
@@ -927,16 +1001,14 @@ 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_S3TRIO is not set
# CONFIG_FB_VGA16 is not set
# CONFIG_FB_RIVA is not set
CONFIG_FB_MATROX=y
CONFIG_FB_MATROX_MILLENIUM=y
CONFIG_FB_MATROX_MYSTIQUE=y
-# CONFIG_FB_MATROX_G450 is not set
-CONFIG_FB_MATROX_G100A=y
-CONFIG_FB_MATROX_G100=y
+CONFIG_FB_MATROX_G=y
# CONFIG_FB_MATROX_I2C is not set
# CONFIG_FB_MATROX_MULTIHEAD is not set
# CONFIG_FB_RADEON_OLD is not set
@@ -946,12 +1018,15 @@ CONFIG_FB_RADEON_I2C=y
CONFIG_FB_ATY128=y
CONFIG_FB_ATY=y
CONFIG_FB_ATY_CT=y
-CONFIG_FB_ATY_GX=y
+CONFIG_FB_ATY_GENERIC_LCD=y
# CONFIG_FB_ATY_XL_INIT is not set
+CONFIG_FB_ATY_GX=y
+# CONFIG_FB_SAVAGE is not set
# CONFIG_FB_SIS is not set
# CONFIG_FB_NEOMAGIC is not set
# CONFIG_FB_KYRO is not set
CONFIG_FB_3DFX=y
+CONFIG_FB_3DFX_ACCEL=y
# CONFIG_FB_VOODOO1 is not set
# CONFIG_FB_TRIDENT is not set
# CONFIG_FB_VIRTUAL is not set
@@ -960,10 +1035,8 @@ CONFIG_FB_3DFX=y
# Console display driver support
#
# CONFIG_VGA_CONSOLE is not set
-# CONFIG_MDA_CONSOLE is not set
CONFIG_DUMMY_CONSOLE=y
CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_PCI_CONSOLE=y
# CONFIG_FONTS is not set
CONFIG_FONT_8x8=y
CONFIG_FONT_8x16=y
@@ -975,6 +1048,11 @@ CONFIG_LOGO=y
CONFIG_LOGO_LINUX_MONO=y
CONFIG_LOGO_LINUX_VGA16=y
CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_DEVICE=y
+CONFIG_LCD_CLASS_DEVICE=y
+CONFIG_LCD_DEVICE=y
#
# Sound
@@ -989,6 +1067,7 @@ CONFIG_DMASOUND=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
@@ -1013,6 +1092,7 @@ CONFIG_SND_DUMMY=m
#
# 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
@@ -1021,6 +1101,8 @@ CONFIG_SND_DUMMY=m
# CONFIG_SND_CS46XX is not set
# CONFIG_SND_CS4281 is not set
# CONFIG_SND_EMU10K1 is not set
+# CONFIG_SND_EMU10K1X is not set
+# CONFIG_SND_CA0106 is not set
# CONFIG_SND_KORG1212 is not set
# CONFIG_SND_MIXART is not set
# CONFIG_SND_NM256 is not set
@@ -1044,6 +1126,7 @@ CONFIG_SND_DUMMY=m
# CONFIG_SND_INTEL8X0M is not set
# CONFIG_SND_SONICVIBES is not set
# CONFIG_SND_VIA82XX is not set
+# CONFIG_SND_VIA82XX_MODEM is not set
# CONFIG_SND_VX222 is not set
#
@@ -1052,9 +1135,10 @@ CONFIG_SND_DUMMY=m
CONFIG_SND_POWERMAC=m
#
-# ALSA USB devices
+# USB devices
#
CONFIG_SND_USB_AUDIO=m
+CONFIG_SND_USB_USX2Y=m
#
# PCMCIA devices
@@ -1077,6 +1161,10 @@ CONFIG_USB=y
CONFIG_USB_DEVICEFS=y
# CONFIG_USB_BANDWIDTH is not set
CONFIG_USB_DYNAMIC_MINORS=y
+CONFIG_USB_SUSPEND=y
+# CONFIG_USB_OTG is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
#
# USB Host Controller Drivers
@@ -1084,6 +1172,7 @@ CONFIG_USB_DYNAMIC_MINORS=y
# CONFIG_USB_EHCI_HCD is not set
CONFIG_USB_OHCI_HCD=y
# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
#
# USB Device Class drivers
@@ -1093,20 +1182,25 @@ CONFIG_USB_OHCI_HCD=y
# CONFIG_USB_MIDI is not set
CONFIG_USB_ACM=m
CONFIG_USB_PRINTER=m
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
# CONFIG_USB_STORAGE is not set
#
-# USB Human Interface Devices (HID)
+# 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_HIDDEV=y
# CONFIG_USB_AIPTEK is not set
# CONFIG_USB_WACOM is not set
# CONFIG_USB_KBTAB is not set
# CONFIG_USB_POWERMATE is not set
# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_EGALAX is not set
# CONFIG_USB_XPAD is not set
# CONFIG_USB_ATI_REMOTE is not set
@@ -1115,7 +1209,6 @@ CONFIG_USB_HIDINPUT=y
#
# CONFIG_USB_MDC800 is not set
# CONFIG_USB_MICROTEK is not set
-# CONFIG_USB_HPUSBSCSI is not set
#
# USB Multimedia devices
@@ -1127,11 +1220,11 @@ CONFIG_USB_HIDINPUT=y
#
#
-# USB Network adaptors
+# USB Network Adapters
#
# CONFIG_USB_CATC is not set
# CONFIG_USB_KAWETH is not set
-# CONFIG_USB_PEGASUS is not set
+CONFIG_USB_PEGASUS=m
# CONFIG_USB_RTL8150 is not set
# CONFIG_USB_USBNET is not set
@@ -1147,6 +1240,7 @@ CONFIG_USB_SERIAL=m
# 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_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
@@ -1154,41 +1248,75 @@ CONFIG_USB_SERIAL_VISOR=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 is not set
-# CONFIG_USB_SERIAL_KEYSPAN is not set
+CONFIG_USB_SERIAL_KEYSPAN=m
+CONFIG_USB_SERIAL_KEYSPAN_MPR=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19=y
+CONFIG_USB_SERIAL_KEYSPAN_USA18X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
# CONFIG_USB_SERIAL_KLSI is not set
# CONFIG_USB_SERIAL_KOBIL_SCT is not set
# CONFIG_USB_SERIAL_MCT_U232 is not set
# CONFIG_USB_SERIAL_PL2303 is not set
# CONFIG_USB_SERIAL_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_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_TIGL 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_TEST is not set
#
+# USB ATM/DSL drivers
+#
+
+#
# 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
+
+#
# File systems
#
CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT2_FS_XATTR=y
+# CONFIG_EXT2_FS_POSIX_ACL is not set
+# CONFIG_EXT2_FS_SECURITY is not set
CONFIG_EXT3_FS=y
CONFIG_EXT3_FS_XATTR=y
# CONFIG_EXT3_FS_POSIX_ACL is not set
@@ -1198,10 +1326,15 @@ CONFIG_JBD=y
CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
# CONFIG_XFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
@@ -1211,7 +1344,8 @@ CONFIG_FS_MBCACHE=y
CONFIG_ISO9660_FS=y
# CONFIG_JOLIET is not set
# CONFIG_ZISOFS is not set
-# CONFIG_UDF_FS is not set
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
#
# DOS/FAT/NT Filesystems
@@ -1219,6 +1353,8 @@ CONFIG_ISO9660_FS=y
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
#
@@ -1227,11 +1363,12 @@ CONFIG_VFAT_FS=m
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_SYSFS=y
-CONFIG_DEVFS_FS=y
-# CONFIG_DEVFS_MOUNT is not set
-# CONFIG_DEVFS_DEBUG is not set
-# CONFIG_DEVPTS_FS_XATTR is not set
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS_XATTR=y
+CONFIG_DEVPTS_FS_SECURITY=y
CONFIG_TMPFS=y
+CONFIG_TMPFS_XATTR=y
+CONFIG_TMPFS_SECURITY=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
@@ -1245,7 +1382,7 @@ 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_CRAMFS=m
# CONFIG_VXFS_FS is not set
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
@@ -1256,16 +1393,19 @@ CONFIG_HFSPLUS_FS=m
# Network File Systems
#
CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
+CONFIG_NFS_V3=y
# 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_NFSD_V3=y
+# CONFIG_NFSD_V4 is not set
+CONFIG_NFSD_TCP=y
CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
CONFIG_EXPORTFS=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
@@ -1288,7 +1428,6 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_SOLARIS_X86_PARTITION is not set
# CONFIG_UNIXWARE_DISKLABEL is not set
# CONFIG_LDM_PARTITION is not set
-# CONFIG_NEC98_PARTITION is not set
# CONFIG_SGI_PARTITION is not set
# CONFIG_ULTRIX_PARTITION is not set
# CONFIG_SUN_PARTITION is not set
@@ -1320,8 +1459,9 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# 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_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=m
CONFIG_NLS_ISO8859_1=m
# CONFIG_NLS_ISO8859_2 is not set
# CONFIG_NLS_ISO8859_3 is not set
@@ -1332,31 +1472,52 @@ CONFIG_NLS_ISO8859_1=m
# CONFIG_NLS_ISO8859_9 is not set
# CONFIG_NLS_ISO8859_13 is not set
# CONFIG_NLS_ISO8859_14 is not set
-# CONFIG_NLS_ISO8859_15 is not set
+CONFIG_NLS_ISO8859_15=m
# CONFIG_NLS_KOI8_R is not set
# CONFIG_NLS_KOI8_U is not set
-# CONFIG_NLS_UTF8 is not set
+CONFIG_NLS_UTF8=m
#
# Library routines
#
+CONFIG_CRC_CCITT=y
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=y
#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
# Kernel hacking
#
-# CONFIG_DEBUG_KERNEL is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_MAGIC_SYSRQ=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_INFO is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_XMON is not set
+# CONFIG_BDI_SWITCH is not set
CONFIG_BOOTX_TEXT=y
#
# Security options
#
+# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
#
# Cryptographic options
#
# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
diff --git a/arch/ppc/configs/radstone_ppc7d_defconfig b/arch/ppc/configs/radstone_ppc7d_defconfig
new file mode 100644
index 0000000000000..7f6467e779491
--- /dev/null
+++ b/arch/ppc/configs/radstone_ppc7d_defconfig
@@ -0,0 +1,956 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11
+# Tue Mar 15 14:31:19 2005
+#
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_GENERIC_NVRAM=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+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_EMBEDDED=y
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_EXTRA_PASS=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Processor
+#
+CONFIG_6xx=y
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+# CONFIG_E500 is not set
+CONFIG_ALTIVEC=y
+# CONFIG_TAU is not set
+# CONFIG_CPU_FREQ is not set
+CONFIG_PPC_GEN550=y
+# CONFIG_PM is not set
+CONFIG_PPC_STD_MMU=y
+# CONFIG_NOT_COHERENT_CACHE is not set
+
+#
+# Platform options
+#
+# CONFIG_PPC_MULTIPLATFORM is not set
+# CONFIG_APUS is not set
+# CONFIG_KATANA is not set
+# CONFIG_WILLOW is not set
+# CONFIG_CPCI690 is not set
+# CONFIG_PCORE is not set
+# CONFIG_POWERPMC250 is not set
+# CONFIG_CHESTNUT is not set
+# CONFIG_SPRUCE is not set
+# CONFIG_EV64260 is not set
+# CONFIG_LOPEC is not set
+# CONFIG_MCPN765 is not set
+# CONFIG_MVME5100 is not set
+# CONFIG_PPLUS is not set
+# CONFIG_PRPMC750 is not set
+# CONFIG_PRPMC800 is not set
+# CONFIG_SANDPOINT is not set
+CONFIG_RADSTONE_PPC7D=y
+# CONFIG_ADIR is not set
+# CONFIG_K2 is not set
+# CONFIG_PAL4 is not set
+# CONFIG_GEMINI is not set
+# CONFIG_EST8260 is not set
+# CONFIG_SBC82xx is not set
+# CONFIG_SBS8260 is not set
+# CONFIG_RPX8260 is not set
+# CONFIG_TQM8260 is not set
+# CONFIG_ADS8272 is not set
+# CONFIG_PQ2FADS is not set
+# CONFIG_LITE5200 is not set
+# CONFIG_MPC834x_SYS is not set
+CONFIG_MV64360=y
+CONFIG_MV64X60=y
+
+#
+# Set bridge options
+#
+CONFIG_MV64X60_BASE=0xfef00000
+CONFIG_MV64X60_NEW_BASE=0xfef00000
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=y
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=ttyS0,9600"
+
+#
+# Bus options
+#
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Advanced setup
+#
+CONFIG_ADVANCED_OPTIONS=y
+CONFIG_HIGHMEM_START=0xfe000000
+# CONFIG_LOWMEM_SIZE_BOOL is not set
+CONFIG_LOWMEM_SIZE=0x30000000
+# CONFIG_KERNEL_START_BOOL is not set
+CONFIG_KERNEL_START=0xc0000000
+# CONFIG_TASK_SIZE_BOOL is not set
+CONFIG_TASK_SIZE=0x80000000
+# CONFIG_BOOT_LOAD_BOOL is not set
+CONFIG_BOOT_LOAD=0x00800000
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+# CONFIG_MTD_PARTITIONS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_FTL=y
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_NOSWAP=y
+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_GEOMETRY 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
+
+#
+# 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
+
+#
+# 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=8192
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=y
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=y
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+CONFIG_SCSI_SYM53C8XX_2=y
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
+# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_ISP is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+CONFIG_SCSI_QLA2XXX=y
+# CONFIG_SCSI_QLA21XX is not set
+# CONFIG_SCSI_QLA22XX is not set
+# CONFIG_SCSI_QLA2300 is not set
+# CONFIG_SCSI_QLA2322 is not set
+# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+CONFIG_BRIDGE=y
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+CONFIG_NET_TULIP=y
+# CONFIG_DE2104X is not set
+CONFIG_TULIP=y
+# CONFIG_TULIP_MWI is not set
+# CONFIG_TULIP_MMIO is not set
+# CONFIG_TULIP_NAPI is not set
+# CONFIG_DE4X5 is not set
+# CONFIG_WINBOND_840 is not set
+# CONFIG_DM9102 is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 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=y
+CONFIG_R8169_NAPI=y
+CONFIG_SK98LIN=y
+# CONFIG_VIA_VELOCITY is not set
+CONFIG_TIGON3=y
+CONFIG_MV643XX_ETH=y
+CONFIG_MV643XX_ETH_0=y
+CONFIG_MV643XX_ETH_1=y
+# CONFIG_MV643XX_ETH_2 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+CONFIG_KEYBOARD_XTKBD=y
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
+#
+# Character devices
+#
+CONFIG_VT=y
+# CONFIG_VT_CONSOLE is not set
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_MPSC=y
+# CONFIG_SERIAL_MPSC_CONSOLE 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
+
+#
+# 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
+
+#
+# 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_ISA is not set
+# CONFIG_I2C_MPC is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+# CONFIG_I2C_PCA_ISA is not set
+CONFIG_I2C_MV64XXX=y
+
+#
+# Hardware Sensors Chip support
+#
+CONFIG_I2C_SENSOR=y
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+CONFIG_SENSORS_LM90=y
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+
+#
+# Other I2C Chip support
+#
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_SENSORS_M41T00 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
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# 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 is not set
+
+#
+# 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
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
+# CONFIG_UDF_FS 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_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# 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_NAND is not set
+# CONFIG_JFFS2_FS_NOR_ECC is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS 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_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=y
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_DEBUG_KERNEL 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/kernel/Makefile b/arch/ppc/kernel/Makefile
index 464f01992141a..1f98f26e58aef 100644
--- a/arch/ppc/kernel/Makefile
+++ b/arch/ppc/kernel/Makefile
@@ -16,6 +16,7 @@ obj-y := entry.o traps.o irq.o idle.o time.o misc.o \
semaphore.o syscalls.o setup.o \
cputable.o ppc_htab.o perfmon.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
diff --git a/arch/ppc/kernel/align.c b/arch/ppc/kernel/align.c
index c7d99f0336335..79c9294750377 100644
--- a/arch/ppc/kernel/align.c
+++ b/arch/ppc/kernel/align.c
@@ -248,7 +248,7 @@ fix_alignment(struct pt_regs *regs)
*/
p = (long __user *) (regs->dar & -L1_CACHE_BYTES);
if (user_mode(regs)
- && verify_area(VERIFY_WRITE, p, L1_CACHE_BYTES))
+ && !access_ok(VERIFY_WRITE, p, L1_CACHE_BYTES))
return -EFAULT;
for (i = 0; i < L1_CACHE_BYTES / sizeof(long); ++i)
if (__put_user(0, p+i))
@@ -328,7 +328,7 @@ fix_alignment(struct pt_regs *regs)
/* Verify the address of the operand */
if (user_mode(regs)) {
- if (verify_area((flags & ST? VERIFY_WRITE: VERIFY_READ), addr, nb))
+ if (!access_ok((flags & ST? VERIFY_WRITE: VERIFY_READ), addr, nb))
return -EFAULT; /* bad address */
}
diff --git a/arch/ppc/kernel/asm-offsets.c b/arch/ppc/kernel/asm-offsets.c
index 946ea9922cc26..d9ad1d776d0ed 100644
--- a/arch/ppc/kernel/asm-offsets.c
+++ b/arch/ppc/kernel/asm-offsets.c
@@ -16,6 +16,7 @@
#include <linux/string.h>
#include <linux/types.h>
#include <linux/ptrace.h>
+#include <linux/suspend.h>
#include <linux/mman.h>
#include <linux/mm.h>
#include <asm/io.h>
@@ -136,6 +137,10 @@ main(void)
DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count));
+ DEFINE(pbe_address, offsetof(struct pbe, address));
+ DEFINE(pbe_orig_address, offsetof(struct pbe, orig_address));
+ DEFINE(pbe_next, offsetof(struct pbe, next));
+
DEFINE(NUM_USER_SEGMENTS, TASK_SIZE>>28);
return 0;
}
diff --git a/arch/ppc/kernel/cpu_setup_6xx.S b/arch/ppc/kernel/cpu_setup_6xx.S
index 9a4ee63fd07c6..74f781b486a31 100644
--- a/arch/ppc/kernel/cpu_setup_6xx.S
+++ b/arch/ppc/kernel/cpu_setup_6xx.S
@@ -73,16 +73,16 @@ _GLOBAL(__setup_cpu_745x)
/* Enable caches for 603's, 604, 750 & 7400 */
setup_common_caches:
- mfspr r11,HID0
+ mfspr r11,SPRN_HID0
andi. r0,r11,HID0_DCE
ori r11,r11,HID0_ICE|HID0_DCE
ori r8,r11,HID0_ICFI
bne 1f /* don't invalidate the D-cache */
ori r8,r8,HID0_DCI /* unless it wasn't enabled */
1: sync
- mtspr HID0,r8 /* enable and invalidate caches */
+ mtspr SPRN_HID0,r8 /* enable and invalidate caches */
sync
- mtspr HID0,r11 /* enable caches */
+ mtspr SPRN_HID0,r11 /* enable caches */
sync
isync
blr
@@ -91,13 +91,13 @@ setup_common_caches:
* Enable superscalar execution & branch history table
*/
setup_604_hid0:
- mfspr r11,HID0
+ mfspr r11,SPRN_HID0
ori r11,r11,HID0_SIED|HID0_BHTE
ori r8,r11,HID0_BTCD
sync
- mtspr HID0,r8 /* flush branch target address cache */
+ mtspr SPRN_HID0,r8 /* flush branch target address cache */
sync /* on 604e/604r */
- mtspr HID0,r11
+ mtspr SPRN_HID0,r11
sync
isync
blr
@@ -150,7 +150,7 @@ setup_7410_workarounds:
* Clear Instruction cache throttling (ICTC)
*/
setup_750_7400_hid0:
- mfspr r11,HID0
+ mfspr r11,SPRN_HID0
ori r11,r11,HID0_SGE | HID0_ABE | HID0_BHTE | HID0_BTIC
BEGIN_FTR_SECTION
oris r11,r11,HID0_DPM@h /* enable dynamic power mgmt */
@@ -158,9 +158,9 @@ END_FTR_SECTION_IFCLR(CPU_FTR_NO_DPM)
li r3,HID0_SPD
andc r11,r11,r3 /* clear SPD: enable speculative */
li r3,0
- mtspr ICTC,r3 /* Instruction Cache Throttling off */
+ mtspr SPRN_ICTC,r3 /* Instruction Cache Throttling off */
isync
- mtspr HID0,r11
+ mtspr SPRN_HID0,r11
sync
isync
blr
@@ -214,7 +214,7 @@ setup_745x_specifics:
andc r6,r6,r7
stw r6,CPU_SPEC_FEATURES(r5)
1:
- mfspr r11,HID0
+ mfspr r11,SPRN_HID0
/* All of the bits we have to set.....
*/
@@ -232,9 +232,9 @@ END_FTR_SECTION_IFCLR(CPU_FTR_NO_DPM)
andc r11,r11,r3 /* clear SPD: enable speculative */
li r3,0
- mtspr ICTC,r3 /* Instruction Cache Throttling off */
+ mtspr SPRN_ICTC,r3 /* Instruction Cache Throttling off */
isync
- mtspr HID0,r11
+ mtspr SPRN_HID0,r11
sync
isync
@@ -285,7 +285,7 @@ _GLOBAL(__save_cpu_setup)
stw r3,CS_HID0(r5)
/* Now deal with CPU type dependent registers */
- mfspr r3,PVR
+ mfspr r3,SPRN_PVR
srwi r3,r3,16
cmplwi cr0,r3,0x8000 /* 7450 */
cmplwi cr1,r3,0x000c /* 7400 */
@@ -323,7 +323,7 @@ _GLOBAL(__save_cpu_setup)
mfspr r4,SPRN_HID1
stw r4,CS_HID1(r5)
/* If rev 2.x, backup HID2 */
- mfspr r3,PVR
+ mfspr r3,SPRN_PVR
andi. r3,r3,0xff00
cmpwi cr0,r3,0x0200
bne 1f
@@ -354,7 +354,7 @@ _GLOBAL(__restore_cpu_setup)
isync
/* Now deal with CPU type dependent registers */
- mfspr r3,PVR
+ mfspr r3,SPRN_PVR
srwi r3,r3,16
cmplwi cr0,r3,0x8000 /* 7450 */
cmplwi cr1,r3,0x000c /* 7400 */
@@ -414,7 +414,7 @@ _GLOBAL(__restore_cpu_setup)
* to PLL 0 on all
*/
/* If rev 2.x, restore HID2 with low voltage bit cleared */
- mfspr r3,PVR
+ mfspr r3,SPRN_PVR
andi. r3,r3,0xff00
cmpwi cr0,r3,0x0200
bne 4f
diff --git a/arch/ppc/kernel/cputable.c b/arch/ppc/kernel/cputable.c
index c86b4b224306b..8aa5e8c69009b 100644
--- a/arch/ppc/kernel/cputable.c
+++ b/arch/ppc/kernel/cputable.c
@@ -560,6 +560,18 @@ struct cpu_spec cpu_specs[] = {
.dcache_bsize = 32,
.cpu_setup = __setup_cpu_603
},
+ { /* e300 (a 603e core, plus some) on 83xx */
+ .pvr_mask = 0x7fff0000,
+ .pvr_value = 0x00830000,
+ .cpu_name = "e300",
+ .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+ CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB |
+ CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS,
+ .cpu_user_features = COMMON_PPC,
+ .icache_bsize = 32,
+ .dcache_bsize = 32,
+ .cpu_setup = __setup_cpu_603
+ },
{ /* default match, we assume split I/D cache & TB (non-601)... */
.pvr_mask = 0x00000000,
.pvr_value = 0x00000000,
diff --git a/arch/ppc/kernel/dma-mapping.c b/arch/ppc/kernel/dma-mapping.c
index 59359d89d37dc..e0c631cf96b03 100644
--- a/arch/ppc/kernel/dma-mapping.c
+++ b/arch/ppc/kernel/dma-mapping.c
@@ -219,7 +219,8 @@ __dma_alloc_coherent(size_t size, dma_addr_t *handle, int 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);
+ unsigned long vaddr = c->vm_start;
+ pte_t *pte = consistent_pte + CONSISTENT_OFFSET(vaddr);
struct page *end = page + (1 << order);
/*
@@ -232,9 +233,11 @@ __dma_alloc_coherent(size_t size, dma_addr_t *handle, int gfp)
set_page_count(page, 1);
SetPageReserved(page);
- set_pte(pte, mk_pte(page, pgprot_noncached(PAGE_KERNEL)));
+ set_pte_at(&init_mm, vaddr,
+ pte, mk_pte(page, pgprot_noncached(PAGE_KERNEL)));
page++;
pte++;
+ vaddr += PAGE_SIZE;
} while (size -= PAGE_SIZE);
/*
@@ -262,7 +265,7 @@ EXPORT_SYMBOL(__dma_alloc_coherent);
void __dma_free_coherent(size_t size, void *vaddr)
{
struct vm_region *c;
- unsigned long flags;
+ unsigned long flags, addr;
pte_t *ptep;
size = PAGE_ALIGN(size);
@@ -281,11 +284,13 @@ void __dma_free_coherent(size_t size, void *vaddr)
}
ptep = consistent_pte + CONSISTENT_OFFSET(c->vm_start);
+ addr = c->vm_start;
do {
- pte_t pte = ptep_get_and_clear(ptep);
+ pte_t pte = ptep_get_and_clear(&init_mm, addr, ptep);
unsigned long pfn;
ptep++;
+ addr += PAGE_SIZE;
if (!pte_none(pte) && pte_present(pte)) {
pfn = pte_pfn(pte);
diff --git a/arch/ppc/kernel/entry.S b/arch/ppc/kernel/entry.S
index 08083be4c6abb..035217d6c0f11 100644
--- a/arch/ppc/kernel/entry.S
+++ b/arch/ppc/kernel/entry.S
@@ -45,40 +45,37 @@
#endif
#ifdef CONFIG_BOOKE
-#define COR r8 /* Critical Offset Register (COR) */
-#define BOOKE_LOAD_COR lis COR,crit_save@ha
-#define BOOKE_REST_COR mfspr COR,SPRG2
-#define BOOKE_SAVE_COR mtspr SPRG2,COR
-#else
-#define COR 0
-#define BOOKE_LOAD_COR
-#define BOOKE_REST_COR
-#define BOOKE_SAVE_COR
-#endif
-
-#ifdef CONFIG_BOOKE
+#include "head_booke.h"
.globl mcheck_transfer_to_handler
mcheck_transfer_to_handler:
- mtspr SPRG6W,r8
- lis r8,mcheck_save@ha
- lwz r0,mcheck_r10@l(r8)
+ mtspr MCHECK_SPRG,r8
+ BOOKE_LOAD_MCHECK_STACK
+ lwz r0,GPR10-INT_FRAME_SIZE(r8)
stw r0,GPR10(r11)
- lwz r0,mcheck_r11@l(r8)
+ lwz r0,GPR11-INT_FRAME_SIZE(r8)
stw r0,GPR11(r11)
- mfspr r8,SPRG6R
+ mfspr r8,MCHECK_SPRG
b transfer_to_handler_full
+
+ .globl crit_transfer_to_handler
+crit_transfer_to_handler:
+ mtspr CRIT_SPRG,r8
+ BOOKE_LOAD_CRIT_STACK
+ lwz r0,GPR10-INT_FRAME_SIZE(r8)
+ stw r0,GPR10(r11)
+ lwz r0,GPR11-INT_FRAME_SIZE(r8)
+ stw r0,GPR11(r11)
+ mfspr r8,CRIT_SPRG
+ /* fall through */
#endif
-#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
+#ifdef CONFIG_40x
.globl crit_transfer_to_handler
crit_transfer_to_handler:
- BOOKE_SAVE_COR
- BOOKE_LOAD_COR
- lwz r0,crit_r10@l(COR)
+ lwz r0,crit_r10@l(0)
stw r0,GPR10(r11)
- lwz r0,crit_r11@l(COR)
+ lwz r0,crit_r11@l(0)
stw r0,GPR11(r11)
- BOOKE_REST_COR
/* fall through */
#endif
@@ -101,10 +98,10 @@ transfer_to_handler:
stw r9,_MSR(r11)
andi. r2,r9,MSR_PR
mfctr r12
- mfspr r2,XER
+ mfspr r2,SPRN_XER
stw r12,_CTR(r11)
stw r2,_XER(r11)
- mfspr r12,SPRG3
+ mfspr r12,SPRN_SPRG3
addi r2,r12,-THREAD
tovirt(r2,r2) /* set r2 to current */
beq 2f /* if from user, fix up THREAD.regs */
@@ -152,8 +149,8 @@ transfer_to_handler_cont:
lwz r11,0(r9) /* virtual address of handler */
lwz r9,4(r9) /* where to go when done */
FIX_SRR1(r10,r12)
- mtspr SRR0,r11
- mtspr SRR1,r10
+ mtspr SPRN_SRR0,r11
+ mtspr SPRN_SRR1,r10
mtlr r9
SYNC
RFI /* jump to handler, enable MMU */
@@ -177,8 +174,8 @@ stack_ovf:
addi r9,r9,StackOverflow@l
LOAD_MSR_KERNEL(r10,MSR_KERNEL)
FIX_SRR1(r10,r12)
- mtspr SRR0,r9
- mtspr SRR1,r10
+ mtspr SPRN_SRR0,r9
+ mtspr SPRN_SRR1,r10
SYNC
RFI
@@ -260,8 +257,8 @@ syscall_exit_cont:
FIX_SRR1(r8, r0)
lwz r2,GPR2(r1)
lwz r1,GPR1(r1)
- mtspr SRR0,r7
- mtspr SRR1,r8
+ mtspr SPRN_SRR0,r7
+ mtspr SPRN_SRR1,r8
SYNC
RFI
@@ -538,7 +535,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
tophys(r0,r4)
CLR_TOP32(r0)
- mtspr SPRG3,r0 /* Update current THREAD phys addr */
+ mtspr SPRN_SPRG3,r0 /* Update current THREAD phys addr */
lwz r1,KSP(r4) /* Load new stack pointer */
/* save the old current 'last' for return value */
@@ -642,7 +639,7 @@ restore:
lwz r10,_XER(r1)
lwz r11,_CTR(r1)
- mtspr XER,r10
+ mtspr SPRN_XER,r10
mtctr r11
PPC405_ERR77(0,r1)
@@ -675,8 +672,8 @@ exc_exit_restart:
lwz r9,_MSR(r1)
lwz r12,_NIP(r1)
FIX_SRR1(r9,r10)
- mtspr SRR0,r12
- mtspr SRR1,r9
+ mtspr SPRN_SRR0,r12
+ mtspr SPRN_SRR1,r9
REST_4GPRS(9, r1)
lwz r1,GPR1(r1)
.globl exc_exit_restart_end
@@ -702,8 +699,8 @@ exc_exit_restart:
lwz r11,_NIP(r1)
lwz r12,_MSR(r1)
exc_exit_start:
- mtspr SRR0,r11
- mtspr SRR1,r12
+ mtspr SPRN_SRR0,r11
+ mtspr SPRN_SRR1,r12
REST_2GPRS(11, r1)
lwz r1,GPR1(r1)
.globl exc_exit_restart_end
@@ -724,8 +721,6 @@ exc_exit_restart_end:
* We have to restore various SPRs that may have been in use at the
* time of the critical interrupt.
*
- * Note that SPRG6 is used for machine check on CONFIG_BOOKE parts and
- * thus not saved in the critical handler
*/
.globl ret_from_crit_exc
ret_from_crit_exc:
@@ -742,7 +737,7 @@ ret_from_crit_exc:
lwz r10,_XER(r1)
lwz r11,_CTR(r1)
- mtspr XER,r10
+ mtspr SPRN_XER,r10
mtctr r11
PPC405_ERR77(0,r1)
@@ -766,36 +761,13 @@ ret_from_crit_exc:
mtspr SPRN_ESR,r10
lwz r11,_NIP(r1)
lwz r12,_MSR(r1)
- mtspr CSRR0,r11
- mtspr CSRR1,r12
+ mtspr SPRN_CSRR0,r11
+ mtspr SPRN_CSRR1,r12
lwz r9,GPR9(r1)
lwz r12,GPR12(r1)
- BOOKE_SAVE_COR
- BOOKE_LOAD_COR
- lwz r10,crit_sprg0@l(COR)
- mtspr SPRN_SPRG0,r10
- lwz r10,crit_sprg1@l(COR)
- mtspr SPRN_SPRG1,r10
- lwz r10,crit_sprg4@l(COR)
- mtspr SPRN_SPRG4,r10
- lwz r10,crit_sprg5@l(COR)
- mtspr SPRN_SPRG5,r10
-#ifdef CONFIG_40x
- lwz r10,crit_sprg6@l(COR)
- mtspr SPRN_SPRG6,r10
-#endif
- lwz r10,crit_sprg7@l(COR)
- mtspr SPRN_SPRG7,r10
- lwz r10,crit_srr0@l(COR)
- mtspr SRR0,r10
- lwz r10,crit_srr1@l(COR)
- mtspr SRR1,r10
- lwz r10,crit_pid@l(COR)
- mtspr SPRN_PID,r10
lwz r10,GPR10(r1)
lwz r11,GPR11(r1)
lwz r1,GPR1(r1)
- BOOKE_REST_COR
PPC405_ERR77_SYNC
rfci
b . /* prevent prefetch past rfci */
@@ -820,7 +792,7 @@ ret_from_mcheck_exc:
lwz r10,_XER(r1)
lwz r11,_CTR(r1)
- mtspr XER,r10
+ mtspr SPRN_XER,r10
mtctr r11
stwcx. r0,0,r1 /* to clear the reservation */
@@ -835,36 +807,13 @@ ret_from_mcheck_exc:
mtspr SPRN_ESR,r10
lwz r11,_NIP(r1)
lwz r12,_MSR(r1)
- mtspr MCSRR0,r11
- mtspr MCSRR1,r12
+ mtspr SPRN_MCSRR0,r11
+ mtspr SPRN_MCSRR1,r12
lwz r9,GPR9(r1)
lwz r12,GPR12(r1)
- mtspr SPRG6W,r8
- lis r8,mcheck_save@ha
- lwz r10,mcheck_sprg0@l(r8)
- mtspr SPRN_SPRG0,r10
- lwz r10,mcheck_sprg1@l(r8)
- mtspr SPRN_SPRG1,r10
- lwz r10,mcheck_sprg4@l(r8)
- mtspr SPRN_SPRG4,r10
- lwz r10,mcheck_sprg5@l(r8)
- mtspr SPRN_SPRG5,r10
- lwz r10,mcheck_sprg7@l(r8)
- mtspr SPRN_SPRG7,r10
- lwz r10,mcheck_srr0@l(r8)
- mtspr SRR0,r10
- lwz r10,mcheck_srr1@l(r8)
- mtspr SRR1,r10
- lwz r10,mcheck_csrr0@l(r8)
- mtspr CSRR0,r10
- lwz r10,mcheck_csrr1@l(r8)
- mtspr CSRR1,r10
- lwz r10,mcheck_pid@l(r8)
- mtspr SPRN_PID,r10
lwz r10,GPR10(r1)
lwz r11,GPR11(r1)
lwz r1,GPR1(r1)
- mfspr r8,SPRG6R
RFMCI
#endif /* CONFIG_BOOKE */
@@ -997,9 +946,9 @@ _GLOBAL(enter_rtas)
li r9,MSR_KERNEL & ~(MSR_IR|MSR_DR)
mtlr r6
CLR_TOP32(r7)
- mtspr SPRG2,r7
- mtspr SRR0,r8
- mtspr SRR1,r9
+ mtspr SPRN_SPRG2,r7
+ mtspr SPRN_SRR0,r8
+ mtspr SPRN_SRR1,r9
RFI
1: tophys(r9,r1)
lwz r8,INT_FRAME_SIZE+4(r9) /* get return address */
@@ -1007,9 +956,9 @@ _GLOBAL(enter_rtas)
FIX_SRR1(r9,r0)
addi r1,r1,INT_FRAME_SIZE
li r0,0
- mtspr SPRG2,r0
- mtspr SRR0,r8
- mtspr SRR1,r9
+ mtspr SPRN_SPRG2,r0
+ mtspr SPRN_SRR0,r8
+ mtspr SPRN_SRR1,r9
RFI /* return to caller */
.globl machine_check_in_rtas
diff --git a/arch/ppc/kernel/head.S b/arch/ppc/kernel/head.S
index 3a3e3c7424dfb..1a89a71e0acc9 100644
--- a/arch/ppc/kernel/head.S
+++ b/arch/ppc/kernel/head.S
@@ -41,12 +41,12 @@
#define LOAD_BAT(n, reg, RA, RB) \
ld RA,(n*32)+0(reg); \
ld RB,(n*32)+8(reg); \
- mtspr IBAT##n##U,RA; \
- mtspr IBAT##n##L,RB; \
+ mtspr SPRN_IBAT##n##U,RA; \
+ mtspr SPRN_IBAT##n##L,RB; \
ld RA,(n*32)+16(reg); \
ld RB,(n*32)+24(reg); \
- mtspr DBAT##n##U,RA; \
- mtspr DBAT##n##L,RB; \
+ mtspr SPRN_DBAT##n##U,RA; \
+ mtspr SPRN_DBAT##n##L,RB; \
#else /* CONFIG_PPC64BRIDGE */
@@ -54,17 +54,17 @@
#define LOAD_BAT(n, reg, RA, RB) \
/* see the comment for clear_bats() -- Cort */ \
li RA,0; \
- mtspr IBAT##n##U,RA; \
- mtspr DBAT##n##U,RA; \
+ mtspr SPRN_IBAT##n##U,RA; \
+ mtspr SPRN_DBAT##n##U,RA; \
lwz RA,(n*16)+0(reg); \
lwz RB,(n*16)+4(reg); \
- mtspr IBAT##n##U,RA; \
- mtspr IBAT##n##L,RB; \
+ mtspr SPRN_IBAT##n##U,RA; \
+ mtspr SPRN_IBAT##n##L,RB; \
beq 1f; \
lwz RA,(n*16)+8(reg); \
lwz RB,(n*16)+12(reg); \
- mtspr DBAT##n##U,RA; \
- mtspr DBAT##n##L,RB; \
+ mtspr SPRN_DBAT##n##U,RA; \
+ mtspr SPRN_DBAT##n##L,RB; \
1:
#endif /* CONFIG_PPC64BRIDGE */
@@ -224,10 +224,10 @@ __after_mmu_off:
turn_on_mmu:
mfmsr r0
ori r0,r0,MSR_DR|MSR_IR
- mtspr SRR1,r0
+ mtspr SPRN_SRR1,r0
lis r0,start_here@h
ori r0,r0,start_here@l
- mtspr SRR0,r0
+ mtspr SPRN_SRR0,r0
SYNC
RFI /* enables MMU */
@@ -260,18 +260,18 @@ __secondary_hold:
* task's thread_struct.
*/
#define EXCEPTION_PROLOG \
- mtspr SPRG0,r10; \
- mtspr SPRG1,r11; \
+ mtspr SPRN_SPRG0,r10; \
+ mtspr SPRN_SPRG1,r11; \
mfcr r10; \
EXCEPTION_PROLOG_1; \
EXCEPTION_PROLOG_2
#define EXCEPTION_PROLOG_1 \
- mfspr r11,SRR1; /* check whether user or kernel */ \
+ mfspr r11,SPRN_SRR1; /* check whether user or kernel */ \
andi. r11,r11,MSR_PR; \
tophys(r11,r1); /* use tophys(r1) if kernel */ \
beq 1f; \
- mfspr r11,SPRG3; \
+ mfspr r11,SPRN_SPRG3; \
lwz r11,THREAD_INFO-THREAD(r11); \
addi r11,r11,THREAD_SIZE; \
tophys(r11,r11); \
@@ -283,14 +283,14 @@ __secondary_hold:
stw r10,_CCR(r11); /* save registers */ \
stw r12,GPR12(r11); \
stw r9,GPR9(r11); \
- mfspr r10,SPRG0; \
+ mfspr r10,SPRN_SPRG0; \
stw r10,GPR10(r11); \
- mfspr r12,SPRG1; \
+ mfspr r12,SPRN_SPRG1; \
stw r12,GPR11(r11); \
mflr r10; \
stw r10,_LINK(r11); \
- mfspr r12,SRR0; \
- mfspr r9,SRR1; \
+ mfspr r12,SPRN_SRR0; \
+ mfspr r9,SPRN_SRR1; \
stw r1,GPR1(r11); \
stw r1,0(r11); \
tovirt(r1,r11); /* set new kernel sp */ \
@@ -373,11 +373,11 @@ i##n: \
* -- paulus.
*/
. = 0x200
- mtspr SPRG0,r10
- mtspr SPRG1,r11
+ mtspr SPRN_SPRG0,r10
+ mtspr SPRN_SPRG1,r11
mfcr r10
#ifdef CONFIG_PPC_CHRP
- mfspr r11,SPRG2
+ mfspr r11,SPRN_SPRG2
cmpwi 0,r11,0
bne 7f
#endif /* CONFIG_PPC_CHRP */
@@ -385,7 +385,7 @@ i##n: \
7: EXCEPTION_PROLOG_2
addi r3,r1,STACK_FRAME_OVERHEAD
#ifdef CONFIG_PPC_CHRP
- mfspr r4,SPRG2
+ mfspr r4,SPRN_SPRG2
cmpwi cr1,r4,0
bne cr1,1f
#endif
@@ -403,15 +403,15 @@ DataAccessCont:
DataAccess:
EXCEPTION_PROLOG
#endif /* CONFIG_PPC64BRIDGE */
- mfspr r10,DSISR
+ mfspr r10,SPRN_DSISR
andis. r0,r10,0xa470 /* weird error? */
bne 1f /* if not, try to put a PTE */
- mfspr r4,DAR /* into the hash table */
+ mfspr r4,SPRN_DAR /* into the hash table */
rlwinm r3,r10,32-15,21,21 /* DSISR_STORE -> _PAGE_RW */
bl hash_page
1: stw r10,_DSISR(r11)
mr r5,r10
- mfspr r4,DAR
+ mfspr r4,SPRN_DAR
EXC_XFER_EE_LITE(0x300, handle_page_fault)
#ifdef CONFIG_PPC64BRIDGE
@@ -451,9 +451,9 @@ InstructionAccess:
. = 0x600
Alignment:
EXCEPTION_PROLOG
- mfspr r4,DAR
+ mfspr r4,SPRN_DAR
stw r4,_DAR(r11)
- mfspr r5,DSISR
+ mfspr r5,SPRN_DSISR
stw r5,_DSISR(r11)
addi r3,r1,STACK_FRAME_OVERHEAD
EXC_XFER_EE(0x600, AlignmentException)
@@ -518,16 +518,16 @@ InstructionTLBMiss:
*/
mfctr r0
/* Get PTE (linux-style) and check access */
- mfspr r3,IMISS
+ mfspr r3,SPRN_IMISS
lis r1,KERNELBASE@h /* check if kernel address */
cmplw 0,r3,r1
- mfspr r2,SPRG3
+ mfspr r2,SPRN_SPRG3
li r1,_PAGE_USER|_PAGE_PRESENT /* low addresses tested as user */
lwz r2,PGDIR(r2)
blt+ 112f
lis r2,swapper_pg_dir@ha /* if kernel address, use */
addi r2,r2,swapper_pg_dir@l /* kernel page table */
- mfspr r1,SRR1 /* and MSR_PR bit from SRR1 */
+ mfspr r1,SPRN_SRR1 /* and MSR_PR bit from SRR1 */
rlwinm r1,r1,32-12,29,29 /* shift MSR_PR to _PAGE_USER posn */
112: tophys(r2,r2)
rlwimi r2,r3,12,20,29 /* insert top 10 bits of address */
@@ -553,26 +553,26 @@ InstructionTLBMiss:
ori r1,r1,0xe14 /* clear out reserved bits and M */
andc r1,r3,r1 /* PP = user? (rw&dirty? 2: 3): 0 */
mtspr SPRN_RPA,r1
- mfspr r3,IMISS
+ mfspr r3,SPRN_IMISS
tlbli r3
- mfspr r3,SRR1 /* Need to restore CR0 */
+ mfspr r3,SPRN_SRR1 /* Need to restore CR0 */
mtcrf 0x80,r3
rfi
InstructionAddressInvalid:
- mfspr r3,SRR1
+ mfspr r3,SPRN_SRR1
rlwinm r1,r3,9,6,6 /* Get load/store bit */
addis r1,r1,0x2000
- mtspr DSISR,r1 /* (shouldn't be needed) */
+ mtspr SPRN_DSISR,r1 /* (shouldn't be needed) */
mtctr r0 /* Restore CTR */
andi. r2,r3,0xFFFF /* Clear upper bits of SRR1 */
or r2,r2,r1
- mtspr SRR1,r2
- mfspr r1,IMISS /* Get failing address */
+ mtspr SPRN_SRR1,r2
+ mfspr r1,SPRN_IMISS /* Get failing address */
rlwinm. r2,r2,0,31,31 /* Check for little endian access */
rlwimi r2,r2,1,30,30 /* change 1 -> 3 */
xor r1,r1,r2
- mtspr DAR,r1 /* Set fault address */
+ mtspr SPRN_DAR,r1 /* Set fault address */
mfmsr r0 /* Restore "normal" registers */
xoris r0,r0,MSR_TGPR>>16
mtcrf 0x80,r3 /* Restore CR0 */
@@ -592,16 +592,16 @@ DataLoadTLBMiss:
*/
mfctr r0
/* Get PTE (linux-style) and check access */
- mfspr r3,DMISS
+ mfspr r3,SPRN_DMISS
lis r1,KERNELBASE@h /* check if kernel address */
cmplw 0,r3,r1
- mfspr r2,SPRG3
+ mfspr r2,SPRN_SPRG3
li r1,_PAGE_USER|_PAGE_PRESENT /* low addresses tested as user */
lwz r2,PGDIR(r2)
blt+ 112f
lis r2,swapper_pg_dir@ha /* if kernel address, use */
addi r2,r2,swapper_pg_dir@l /* kernel page table */
- mfspr r1,SRR1 /* and MSR_PR bit from SRR1 */
+ mfspr r1,SPRN_SRR1 /* and MSR_PR bit from SRR1 */
rlwinm r1,r1,32-12,29,29 /* shift MSR_PR to _PAGE_USER posn */
112: tophys(r2,r2)
rlwimi r2,r3,12,20,29 /* insert top 10 bits of address */
@@ -627,24 +627,24 @@ DataLoadTLBMiss:
ori r1,r1,0xe14 /* clear out reserved bits and M */
andc r1,r3,r1 /* PP = user? (rw&dirty? 2: 3): 0 */
mtspr SPRN_RPA,r1
- mfspr r3,DMISS
+ mfspr r3,SPRN_DMISS
tlbld r3
- mfspr r3,SRR1 /* Need to restore CR0 */
+ mfspr r3,SPRN_SRR1 /* Need to restore CR0 */
mtcrf 0x80,r3
rfi
DataAddressInvalid:
- mfspr r3,SRR1
+ mfspr r3,SPRN_SRR1
rlwinm r1,r3,9,6,6 /* Get load/store bit */
addis r1,r1,0x2000
- mtspr DSISR,r1
+ mtspr SPRN_DSISR,r1
mtctr r0 /* Restore CTR */
andi. r2,r3,0xFFFF /* Clear upper bits of SRR1 */
- mtspr SRR1,r2
- mfspr r1,DMISS /* Get failing address */
+ mtspr SPRN_SRR1,r2
+ mfspr r1,SPRN_DMISS /* Get failing address */
rlwinm. r2,r2,0,31,31 /* Check for little endian access */
beq 20f /* Jump if big endian */
xori r1,r1,3
-20: mtspr DAR,r1 /* Set fault address */
+20: mtspr SPRN_DAR,r1 /* Set fault address */
mfmsr r0 /* Restore "normal" registers */
xoris r0,r0,MSR_TGPR>>16
mtcrf 0x80,r3 /* Restore CR0 */
@@ -664,16 +664,16 @@ DataStoreTLBMiss:
*/
mfctr r0
/* Get PTE (linux-style) and check access */
- mfspr r3,DMISS
+ mfspr r3,SPRN_DMISS
lis r1,KERNELBASE@h /* check if kernel address */
cmplw 0,r3,r1
- mfspr r2,SPRG3
+ mfspr r2,SPRN_SPRG3
li r1,_PAGE_RW|_PAGE_USER|_PAGE_PRESENT /* access flags */
lwz r2,PGDIR(r2)
blt+ 112f
lis r2,swapper_pg_dir@ha /* if kernel address, use */
addi r2,r2,swapper_pg_dir@l /* kernel page table */
- mfspr r1,SRR1 /* and MSR_PR bit from SRR1 */
+ mfspr r1,SPRN_SRR1 /* and MSR_PR bit from SRR1 */
rlwinm r1,r1,32-12,29,29 /* shift MSR_PR to _PAGE_USER posn */
112: tophys(r2,r2)
rlwimi r2,r3,12,20,29 /* insert top 10 bits of address */
@@ -695,9 +695,9 @@ DataStoreTLBMiss:
li r1,0xe15 /* clear out reserved bits and M */
andc r1,r3,r1 /* PP = user? 2: 0 */
mtspr SPRN_RPA,r1
- mfspr r3,DMISS
+ mfspr r3,SPRN_DMISS
tlbld r3
- mfspr r3,SRR1 /* Need to restore CR0 */
+ mfspr r3,SPRN_SRR1 /* Need to restore CR0 */
mtcrf 0x80,r3
rfi
@@ -765,7 +765,7 @@ InstructionAccess:
DataSegment:
EXCEPTION_PROLOG
addi r3,r1,STACK_FRAME_OVERHEAD
- mfspr r4,DAR
+ mfspr r4,SPRN_DAR
stw r4,_DAR(r11)
EXC_XFER_STD(0x380, UnknownException)
@@ -816,7 +816,7 @@ load_up_fpu:
1:
#endif /* CONFIG_SMP */
/* enable use of FP after return */
- mfspr r5,SPRG3 /* current task's THREAD (phys) */
+ mfspr r5,SPRN_SPRG3 /* current task's THREAD (phys) */
lwz r4,THREAD_FPEXC_MODE(r5)
ori r9,r9,MSR_FP /* enable FP for current */
or r9,r9,r4
@@ -843,8 +843,8 @@ fast_exception_return:
lwz r10,_LINK(r11)
mtlr r10
REST_GPR(10, r11)
- mtspr SRR1,r9
- mtspr SRR0,r12
+ mtspr SPRN_SRR1,r9
+ mtspr SPRN_SRR0,r12
REST_GPR(9, r11)
REST_GPR(12, r11)
lwz r11,GPR11(r11)
@@ -945,7 +945,7 @@ load_up_altivec:
#endif /* CONFIG_SMP */
/* enable use of AltiVec after return */
oris r9,r9,MSR_VEC@h
- mfspr r5,SPRG3 /* current task's THREAD (phys) */
+ mfspr r5,SPRN_SPRG3 /* current task's THREAD (phys) */
li r4,1
li r10,THREAD_VSCR
stw r4,THREAD_USED_VR(r5)
@@ -1142,8 +1142,8 @@ fix_mem_constants:
lis r8,0
#endif
ori r8,r8,0x2 /* 128KB, supervisor */
- mtspr DBAT3U,r8
- mtspr DBAT3L,r8
+ mtspr SPRN_DBAT3U,r8
+ mtspr SPRN_DBAT3L,r8
lis r12,__ptov_table_begin@h
ori r12,r12,__ptov_table_begin@l
@@ -1179,12 +1179,12 @@ fix_mem_constants:
#ifdef CONFIG_GEMINI
.globl __secondary_start_gemini
__secondary_start_gemini:
- mfspr r4,HID0
+ mfspr r4,SPRN_HID0
ori r4,r4,HID0_ICFI
li r3,0
ori r3,r3,HID0_ICE
andc r4,r4,r3
- mtspr HID0,r4
+ mtspr SPRN_HID0,r4
sync
bl gemini_prom_init
b __secondary_start
@@ -1255,17 +1255,17 @@ __secondary_start:
tophys(r4,r2)
addi r4,r4,THREAD /* phys address of our thread_struct */
CLR_TOP32(r4)
- mtspr SPRG3,r4
+ mtspr SPRN_SPRG3,r4
li r3,0
- mtspr SPRG2,r3 /* 0 => not in RTAS */
+ mtspr SPRN_SPRG2,r3 /* 0 => not in RTAS */
/* enable MMU and jump to start_secondary */
li r4,MSR_KERNEL
FIX_SRR1(r4,r5)
lis r3,start_secondary@h
ori r3,r3,start_secondary@l
- mtspr SRR0,r3
- mtspr SRR1,r4
+ mtspr SPRN_SRR0,r3
+ mtspr SPRN_SRR1,r4
SYNC
RFI
#endif /* CONFIG_SMP */
@@ -1301,7 +1301,7 @@ load_up_mmu:
lis r6,_SDR1@ha
tophys(r6,r6)
lwz r6,_SDR1@l(r6)
- mtspr SDR1,r6
+ mtspr SPRN_SDR1,r6
#ifdef CONFIG_PPC64BRIDGE
/* clear the ASR so we only use the pseudo-segment registers. */
li r6,0
@@ -1343,9 +1343,9 @@ start_here:
tophys(r4,r2)
addi r4,r4,THREAD /* init task's THREAD */
CLR_TOP32(r4)
- mtspr SPRG3,r4
+ mtspr SPRN_SPRG3,r4
li r3,0
- mtspr SPRG2,r3 /* 0 => not in RTAS */
+ mtspr SPRN_SPRG2,r3 /* 0 => not in RTAS */
/* stack */
lis r1,init_thread_union@ha
@@ -1387,8 +1387,8 @@ start_here:
tophys(r4,r4)
li r3,MSR_KERNEL & ~(MSR_IR|MSR_DR)
FIX_SRR1(r3,r5)
- mtspr SRR0,r4
- mtspr SRR1,r3
+ mtspr SPRN_SRR0,r4
+ mtspr SPRN_SRR1,r3
SYNC
RFI
/* Load up the kernel context */
@@ -1413,8 +1413,8 @@ start_here:
FIX_SRR1(r4,r5)
lis r3,start_kernel@h
ori r3,r3,start_kernel@l
- mtspr SRR0,r3
- mtspr SRR1,r4
+ mtspr SPRN_SRR0,r3
+ mtspr SPRN_SRR1,r4
SYNC
RFI
@@ -1461,28 +1461,28 @@ _GLOBAL(set_context)
*/
clear_bats:
li r10,0
- mfspr r9,PVR
+ mfspr r9,SPRN_PVR
rlwinm r9,r9,16,16,31 /* r9 = 1 for 601, 4 for 604 */
cmpwi r9, 1
beq 1f
- mtspr DBAT0U,r10
- mtspr DBAT0L,r10
- mtspr DBAT1U,r10
- mtspr DBAT1L,r10
- mtspr DBAT2U,r10
- mtspr DBAT2L,r10
- mtspr DBAT3U,r10
- mtspr DBAT3L,r10
+ mtspr SPRN_DBAT0U,r10
+ mtspr SPRN_DBAT0L,r10
+ mtspr SPRN_DBAT1U,r10
+ mtspr SPRN_DBAT1L,r10
+ mtspr SPRN_DBAT2U,r10
+ mtspr SPRN_DBAT2L,r10
+ mtspr SPRN_DBAT3U,r10
+ mtspr SPRN_DBAT3L,r10
1:
- mtspr IBAT0U,r10
- mtspr IBAT0L,r10
- mtspr IBAT1U,r10
- mtspr IBAT1L,r10
- mtspr IBAT2U,r10
- mtspr IBAT2L,r10
- mtspr IBAT3U,r10
- mtspr IBAT3L,r10
+ mtspr SPRN_IBAT0U,r10
+ mtspr SPRN_IBAT0L,r10
+ mtspr SPRN_IBAT1U,r10
+ mtspr SPRN_IBAT1L,r10
+ mtspr SPRN_IBAT2U,r10
+ mtspr SPRN_IBAT2L,r10
+ mtspr SPRN_IBAT3U,r10
+ mtspr SPRN_IBAT3L,r10
BEGIN_FTR_SECTION
/* Here's a tweak: at this point, CPU setup have
* not been called yet, so HIGH_BAT_EN may not be
@@ -1523,8 +1523,8 @@ mmu_off:
andi. r0,r3,MSR_DR|MSR_IR /* MMU enabled? */
beqlr
andc r3,r3,r0
- mtspr SRR0,r4
- mtspr SRR1,r3
+ mtspr SPRN_SRR0,r4
+ mtspr SPRN_SRR1,r3
sync
RFI
@@ -1537,7 +1537,7 @@ mmu_off:
initial_bats:
lis r11,KERNELBASE@h
#ifndef CONFIG_PPC64BRIDGE
- mfspr r9,PVR
+ mfspr r9,SPRN_PVR
rlwinm r9,r9,16,16,31 /* r9 = 1 for 601, 4 for 604 */
cmpwi 0,r9,1
bne 4f
@@ -1545,10 +1545,10 @@ initial_bats:
li r8,0x7f /* valid, block length = 8MB */
oris r9,r11,0x800000@h /* set up BAT reg for 2nd 8M */
oris r10,r8,0x800000@h /* set up BAT reg for 2nd 8M */
- mtspr IBAT0U,r11 /* N.B. 601 has valid bit in */
- mtspr IBAT0L,r8 /* lower BAT register */
- mtspr IBAT1U,r9
- mtspr IBAT1L,r10
+ mtspr SPRN_IBAT0U,r11 /* N.B. 601 has valid bit in */
+ mtspr SPRN_IBAT0L,r8 /* lower BAT register */
+ mtspr SPRN_IBAT1U,r9
+ mtspr SPRN_IBAT1L,r10
isync
blr
#endif /* CONFIG_PPC64BRIDGE */
@@ -1570,10 +1570,10 @@ initial_bats:
clrldi r11,r11,32
clrldi r8,r8,32
#endif /* CONFIG_PPC64BRIDGE */
- mtspr DBAT0L,r8 /* N.B. 6xx (not 601) have valid */
- mtspr DBAT0U,r11 /* bit in upper BAT register */
- mtspr IBAT0L,r8
- mtspr IBAT0U,r11
+ mtspr SPRN_DBAT0L,r8 /* N.B. 6xx (not 601) have valid */
+ mtspr SPRN_DBAT0U,r11 /* bit in upper BAT register */
+ mtspr SPRN_IBAT0L,r8
+ mtspr SPRN_IBAT0U,r11
isync
blr
@@ -1589,15 +1589,15 @@ setup_disp_bat:
addi r8,r8,disp_BAT@l
lwz r11,0(r8)
lwz r8,4(r8)
- mfspr r9,PVR
+ mfspr r9,SPRN_PVR
rlwinm r9,r9,16,16,31 /* r9 = 1 for 601, 4 for 604 */
cmpwi 0,r9,1
beq 1f
- mtspr DBAT3L,r8
- mtspr DBAT3U,r11
+ mtspr SPRN_DBAT3L,r8
+ mtspr SPRN_DBAT3U,r11
blr
-1: mtspr IBAT3L,r8
- mtspr IBAT3U,r11
+1: mtspr SPRN_IBAT3L,r8
+ mtspr SPRN_IBAT3U,r11
blr
#endif /* !defined(CONFIG_APUS) && defined(CONFIG_BOOTX_TEXT) */
@@ -1612,7 +1612,7 @@ setup_disp_bat:
initial_mm_power4:
addis r14,r3,_SDR1@ha /* get the value from _SDR1 */
lwz r14,_SDR1@l(r14) /* assume hash table below 4GB */
- mtspr SDR1,r14
+ mtspr SPRN_SDR1,r14
slbia
lis r4,0x2000 /* set pseudo-segment reg 12 */
ori r5,r4,0x0ccc
@@ -1649,18 +1649,18 @@ m8260_gorom:
sync
mtmsr r0
sync
- mfspr r11, HID0
+ mfspr r11, SPRN_HID0
lis r10, 0
ori r10,r10,HID0_ICE|HID0_DCE
andc r11, r11, r10
- mtspr HID0, r11
+ mtspr SPRN_HID0, r11
isync
li r5, MSR_ME|MSR_RI
lis r6,2f@h
addis r6,r6,-KERNELBASE@h
ori r6,r6,2f@l
- mtspr SRR0,r6
- mtspr SRR1,r5
+ mtspr SPRN_SRR0,r6
+ mtspr SPRN_SRR1,r5
isync
sync
rfi
diff --git a/arch/ppc/kernel/head_44x.S b/arch/ppc/kernel/head_44x.S
index 1dc13796973b6..9ed8165a3d6c6 100644
--- a/arch/ppc/kernel/head_44x.S
+++ b/arch/ppc/kernel/head_44x.S
@@ -162,10 +162,10 @@ skpinv: addi r4,r4,1 /* Increment */
/* Force context change */
mfmsr r0
- mtspr SRR1, r0
+ mtspr SPRN_SRR1, r0
lis r0,3f@h
ori r0,r0,3f@l
- mtspr SRR0,r0
+ mtspr SPRN_SRR0,r0
sync
rfi
@@ -238,7 +238,7 @@ skpinv: addi r4,r4,1 /* Increment */
/* ptr to current thread */
addi r4,r2,THREAD /* init task's THREAD */
- mtspr SPRG3,r4
+ mtspr SPRN_SPRG3,r4
/* stack */
lis r1,init_thread_union@h
@@ -274,8 +274,8 @@ skpinv: addi r4,r4,1 /* Increment */
ori r4,r4,start_kernel@l
lis r3,MSR_KERNEL@h
ori r3,r3,MSR_KERNEL@l
- mtspr SRR0,r4
- mtspr SRR1,r3
+ mtspr SPRN_SRR0,r4
+ mtspr SPRN_SRR1,r3
rfi /* change context and jump to start_kernel */
/*
@@ -308,12 +308,12 @@ interrupt_base:
/* Data Storage Interrupt */
START_EXCEPTION(DataStorage)
- mtspr SPRG0, r10 /* Save some working registers */
- mtspr SPRG1, r11
- mtspr SPRG4W, r12
- mtspr SPRG5W, r13
+ mtspr SPRN_SPRG0, r10 /* Save some working registers */
+ mtspr SPRN_SPRG1, r11
+ mtspr SPRN_SPRG4W, r12
+ mtspr SPRN_SPRG5W, r13
mfcr r11
- mtspr SPRG7W, r11
+ mtspr SPRN_SPRG7W, r11
/*
* Check if it was a store fault, if not then bail
@@ -342,7 +342,7 @@ interrupt_base:
/* Get the PGD for the current thread */
3:
- mfspr r11,SPRG3
+ mfspr r11,SPRN_SPRG3
lwz r11,PGDIR(r11)
/* Load PID into MMUCR TID */
@@ -390,13 +390,13 @@ interrupt_base:
/* Done...restore registers and get out of here.
*/
- mfspr r11, SPRG7R
+ mfspr r11, SPRN_SPRG7R
mtcr r11
- mfspr r13, SPRG5R
- mfspr r12, SPRG4R
+ mfspr r13, SPRN_SPRG5R
+ mfspr r12, SPRN_SPRG4R
- mfspr r11, SPRG1
- mfspr r10, SPRG0
+ mfspr r11, SPRN_SPRG1
+ mfspr r10, SPRN_SPRG0
rfi /* Force context change */
2:
@@ -404,13 +404,13 @@ interrupt_base:
* The bailout. Restore registers to pre-exception conditions
* and call the heavyweights to help us out.
*/
- mfspr r11, SPRG7R
+ mfspr r11, SPRN_SPRG7R
mtcr r11
- mfspr r13, SPRG5R
- mfspr r12, SPRG4R
+ mfspr r13, SPRN_SPRG5R
+ mfspr r12, SPRN_SPRG4R
- mfspr r11, SPRG1
- mfspr r10, SPRG0
+ mfspr r11, SPRN_SPRG1
+ mfspr r10, SPRN_SPRG0
b data_access
/* Instruction Storage Interrupt */
@@ -449,12 +449,12 @@ interrupt_base:
/* Data TLB Error Interrupt */
START_EXCEPTION(DataTLBError)
- mtspr SPRG0, r10 /* Save some working registers */
- mtspr SPRG1, r11
- mtspr SPRG4W, r12
- mtspr SPRG5W, r13
+ mtspr SPRN_SPRG0, r10 /* Save some working registers */
+ mtspr SPRN_SPRG1, r11
+ mtspr SPRN_SPRG4W, r12
+ mtspr SPRN_SPRG5W, r13
mfcr r11
- mtspr SPRG7W, r11
+ mtspr SPRN_SPRG7W, r11
mfspr r10, SPRN_DEAR /* Get faulting address */
/* If we are faulting a kernel address, we have to use the
@@ -472,7 +472,7 @@ interrupt_base:
/* Get the PGD for the current thread */
3:
- mfspr r11,SPRG3
+ mfspr r11,SPRN_SPRG3
lwz r11,PGDIR(r11)
/* Load PID into MMUCR TID */
@@ -503,12 +503,12 @@ interrupt_base:
/* The bailout. Restore registers to pre-exception conditions
* and call the heavyweights to help us out.
*/
- mfspr r11, SPRG7R
+ mfspr r11, SPRN_SPRG7R
mtcr r11
- mfspr r13, SPRG5R
- mfspr r12, SPRG4R
- mfspr r11, SPRG1
- mfspr r10, SPRG0
+ mfspr r13, SPRN_SPRG5R
+ mfspr r12, SPRN_SPRG4R
+ mfspr r11, SPRN_SPRG1
+ mfspr r10, SPRN_SPRG0
b data_access
/* Instruction TLB Error Interrupt */
@@ -518,13 +518,13 @@ interrupt_base:
* to a different point.
*/
START_EXCEPTION(InstructionTLBError)
- mtspr SPRG0, r10 /* Save some working registers */
- mtspr SPRG1, r11
- mtspr SPRG4W, r12
- mtspr SPRG5W, r13
+ mtspr SPRN_SPRG0, r10 /* Save some working registers */
+ mtspr SPRN_SPRG1, r11
+ mtspr SPRN_SPRG4W, r12
+ mtspr SPRN_SPRG5W, r13
mfcr r11
- mtspr SPRG7W, r11
- mfspr r10, SRR0 /* Get faulting address */
+ mtspr SPRN_SPRG7W, r11
+ mfspr r10, SPRN_SRR0 /* Get faulting address */
/* If we are faulting a kernel address, we have to use the
* kernel page tables.
@@ -541,7 +541,7 @@ interrupt_base:
/* Get the PGD for the current thread */
3:
- mfspr r11,SPRG3
+ mfspr r11,SPRN_SPRG3
lwz r11,PGDIR(r11)
/* Load PID into MMUCR TID */
@@ -572,12 +572,12 @@ interrupt_base:
/* The bailout. Restore registers to pre-exception conditions
* and call the heavyweights to help us out.
*/
- mfspr r11, SPRG7R
+ mfspr r11, SPRN_SPRG7R
mtcr r11
- mfspr r13, SPRG5R
- mfspr r12, SPRG4R
- mfspr r11, SPRG1
- mfspr r10, SPRG0
+ mfspr r13, SPRN_SPRG5R
+ mfspr r12, SPRN_SPRG4R
+ mfspr r11, SPRN_SPRG1
+ mfspr r10, SPRN_SPRG0
b InstructionStorage
/* Debug Interrupt */
@@ -661,12 +661,12 @@ finish_tlb_load:
/* Done...restore registers and get out of here.
*/
- mfspr r11, SPRG7R
+ mfspr r11, SPRN_SPRG7R
mtcr r11
- mfspr r13, SPRG5R
- mfspr r12, SPRG4R
- mfspr r11, SPRG1
- mfspr r10, SPRG0
+ mfspr r13, SPRN_SPRG5R
+ mfspr r12, SPRN_SPRG4R
+ mfspr r11, SPRN_SPRG1
+ mfspr r10, SPRN_SPRG0
rfi /* Force context change */
/*
@@ -728,78 +728,13 @@ _GLOBAL(empty_zero_page)
_GLOBAL(swapper_pg_dir)
.space 8192
+/* Reserved 4k for the critical exception stack & 4k for the machine
+ * check stack per CPU for kernel mode exceptions */
.section .bss
-/* Stack for handling critical exceptions from kernel mode */
-critical_stack_bottom:
- .space 4096
-critical_stack_top:
- .previous
-
-/* Stack for handling machine check exceptions from kernel mode */
-mcheck_stack_bottom:
- .space 4096
-mcheck_stack_top:
- .previous
-
-/*
- * This area is used for temporarily saving registers during the
- * critical and machine check exception prologs. It must always
- * follow the page aligned allocations, so it starts on a page
- * boundary, ensuring that all crit_save areas are in a single
- * page.
- */
-
-/* crit_save */
-_GLOBAL(crit_save)
- .space 4
-_GLOBAL(crit_r10)
- .space 4
-_GLOBAL(crit_r11)
- .space 4
-_GLOBAL(crit_sprg0)
- .space 4
-_GLOBAL(crit_sprg1)
- .space 4
-_GLOBAL(crit_sprg4)
- .space 4
-_GLOBAL(crit_sprg5)
- .space 4
-_GLOBAL(crit_sprg7)
- .space 4
-_GLOBAL(crit_pid)
- .space 4
-_GLOBAL(crit_srr0)
- .space 4
-_GLOBAL(crit_srr1)
- .space 4
-
-/* mcheck_save */
-_GLOBAL(mcheck_save)
- .space 4
-_GLOBAL(mcheck_r10)
- .space 4
-_GLOBAL(mcheck_r11)
- .space 4
-_GLOBAL(mcheck_sprg0)
- .space 4
-_GLOBAL(mcheck_sprg1)
- .space 4
-_GLOBAL(mcheck_sprg4)
- .space 4
-_GLOBAL(mcheck_sprg5)
- .space 4
-_GLOBAL(mcheck_sprg7)
- .space 4
-_GLOBAL(mcheck_pid)
- .space 4
-_GLOBAL(mcheck_srr0)
- .space 4
-_GLOBAL(mcheck_srr1)
- .space 4
-_GLOBAL(mcheck_csrr0)
- .space 4
-_GLOBAL(mcheck_csrr1)
- .space 4
+ .align 12
+exception_stack_bottom:
+ .space BOOKE_EXCEPTION_STACK_SIZE
+_GLOBAL(exception_stack_top)
/*
* This space gets a copy of optional info passed to us by the bootstrap
diff --git a/arch/ppc/kernel/head_4xx.S b/arch/ppc/kernel/head_4xx.S
index f2b0f9f1bb704..6f5d380e23450 100644
--- a/arch/ppc/kernel/head_4xx.S
+++ b/arch/ppc/kernel/head_4xx.S
@@ -77,10 +77,10 @@ _GLOBAL(_start)
turn_on_mmu:
lis r0,MSR_KERNEL@h
ori r0,r0,MSR_KERNEL@l
- mtspr SRR1,r0
+ mtspr SPRN_SRR1,r0
lis r0,start_here@h
ori r0,r0,start_here@l
- mtspr SRR0,r0
+ mtspr SPRN_SRR0,r0
SYNC
rfi /* enables MMU */
b . /* prevent prefetch past rfi */
@@ -95,24 +95,6 @@ _GLOBAL(crit_r10)
.space 4
_GLOBAL(crit_r11)
.space 4
-_GLOBAL(crit_sprg0)
- .space 4
-_GLOBAL(crit_sprg1)
- .space 4
-_GLOBAL(crit_sprg4)
- .space 4
-_GLOBAL(crit_sprg5)
- .space 4
-_GLOBAL(crit_sprg6)
- .space 4
-_GLOBAL(crit_sprg7)
- .space 4
-_GLOBAL(crit_pid)
- .space 4
-_GLOBAL(crit_srr0)
- .space 4
-_GLOBAL(crit_srr1)
- .space 4
/*
* Exception vector entry code. This code runs with address translation
@@ -130,7 +112,7 @@ _GLOBAL(crit_srr1)
mfspr r11,SPRN_SRR1; /* check whether user or kernel */\
andi. r11,r11,MSR_PR; \
beq 1f; \
- mfspr r1,SPRG3; /* if from user, start at top of */\
+ mfspr r1,SPRN_SPRG3; /* if from user, start at top of */\
lwz r1,THREAD_INFO-THREAD(r1); /* this thread's kernel stack */\
addi r1,r1,THREAD_SIZE; \
1: subi r1,r1,INT_FRAME_SIZE; /* Allocate an exception frame */\
@@ -138,16 +120,16 @@ _GLOBAL(crit_srr1)
stw r10,_CCR(r11); /* save various registers */\
stw r12,GPR12(r11); \
stw r9,GPR9(r11); \
- mfspr r10,SPRG0; \
+ mfspr r10,SPRN_SPRG0; \
stw r10,GPR10(r11); \
- mfspr r12,SPRG1; \
+ mfspr r12,SPRN_SPRG1; \
stw r12,GPR11(r11); \
mflr r10; \
stw r10,_LINK(r11); \
- mfspr r10,SPRG2; \
- mfspr r12,SRR0; \
+ mfspr r10,SPRN_SPRG2; \
+ mfspr r12,SPRN_SRR0; \
stw r10,GPR1(r11); \
- mfspr r9,SRR1; \
+ mfspr r9,SPRN_SRR1; \
stw r10,0(r11); \
rlwinm r9,r9,0,14,12; /* clear MSR_WE (necessary?) */\
stw r0,GPR0(r11); \
@@ -165,24 +147,6 @@ _GLOBAL(crit_srr1)
#define CRITICAL_EXCEPTION_PROLOG \
stw r10,crit_r10@l(0); /* save two registers to work with */\
stw r11,crit_r11@l(0); \
- mfspr r10,SPRG0; \
- stw r10,crit_sprg0@l(0); \
- mfspr r10,SPRG1; \
- stw r10,crit_sprg1@l(0); \
- mfspr r10,SPRG4; \
- stw r10,crit_sprg4@l(0); \
- mfspr r10,SPRG5; \
- stw r10,crit_sprg5@l(0); \
- mfspr r10,SPRG6; \
- stw r10,crit_sprg6@l(0); \
- mfspr r10,SPRG7; \
- stw r10,crit_sprg7@l(0); \
- mfspr r10,SPRN_PID; \
- stw r10,crit_pid@l(0); \
- mfspr r10,SRR0; \
- stw r10,crit_srr0@l(0); \
- mfspr r10,SRR1; \
- stw r10,crit_srr1@l(0); \
mfcr r10; /* save CR in r10 for now */\
mfspr r11,SPRN_SRR3; /* check whether user or kernel */\
andi. r11,r11,MSR_PR; \
@@ -190,7 +154,7 @@ _GLOBAL(crit_srr1)
ori r11,r11,critical_stack_top@l; \
beq 1f; \
/* COMING FROM USER MODE */ \
- mfspr r11,SPRG3; /* if from user, start at top of */\
+ mfspr r11,SPRN_SPRG3; /* if from user, start at top of */\
lwz r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\
addi r11,r11,THREAD_SIZE; \
1: subi r11,r11,INT_FRAME_SIZE; /* Allocate an exception frame */\
@@ -204,9 +168,9 @@ _GLOBAL(crit_srr1)
stw r12,_DEAR(r11); /* since they may have had stuff */\
mfspr r9,SPRN_ESR; /* in them at the point where the */\
stw r9,_ESR(r11); /* exception was taken */\
- mfspr r12,SRR2; \
+ mfspr r12,SPRN_SRR2; \
stw r1,GPR1(r11); \
- mfspr r9,SRR3; \
+ mfspr r9,SPRN_SRR3; \
stw r1,0(r11); \
tovirt(r1,r11); \
rlwinm r9,r9,0,14,12; /* clear MSR_WE (necessary?) */\
@@ -221,9 +185,6 @@ _GLOBAL(crit_srr1)
* r11 saved in crit_r11 and in stack frame,
* now phys stack/exception frame pointer
* r12 saved in stack frame, now saved SRR2
- * SPRG0,1,4,5,6,7 saved in crit_sprg0,1,4,5,6,7
- * PID saved in crit_pid
- * SRR0,1 saved in crit_srr0,1
* CR saved in stack frame, CR0.EQ = !SRR3.PR
* LR, DEAR, ESR in stack frame
* r1 saved in stack frame, now virt stack/excframe pointer
@@ -299,8 +260,8 @@ label:
* and exit. Otherwise, we call heavywight functions to do the work.
*/
START_EXCEPTION(0x0300, DataStorage)
- mtspr SPRG0, r10 /* Save some working registers */
- mtspr SPRG1, r11
+ mtspr SPRN_SPRG0, r10 /* Save some working registers */
+ mtspr SPRN_SPRG1, r11
#ifdef CONFIG_403GCX
stw r12, 0(r0)
stw r9, 4(r0)
@@ -309,12 +270,12 @@ label:
stw r11, 8(r0)
stw r12, 12(r0)
#else
- mtspr SPRG4, r12
- mtspr SPRG5, r9
+ mtspr SPRN_SPRG4, r12
+ mtspr SPRN_SPRG5, r9
mfcr r11
mfspr r12, SPRN_PID
- mtspr SPRG7, r11
- mtspr SPRG6, r12
+ mtspr SPRN_SPRG7, r11
+ mtspr SPRN_SPRG6, r12
#endif
/* First, check if it was a zone fault (which means a user
@@ -341,7 +302,7 @@ label:
/* Get the PGD for the current thread.
*/
3:
- mfspr r11,SPRG3
+ mfspr r11,SPRN_SPRG3
lwz r11,PGDIR(r11)
4:
tophys(r11, r11)
@@ -388,15 +349,15 @@ label:
lwz r9, 4(r0)
lwz r12, 0(r0)
#else
- mfspr r12, SPRG6
- mfspr r11, SPRG7
+ mfspr r12, SPRN_SPRG6
+ mfspr r11, SPRN_SPRG7
mtspr SPRN_PID, r12
mtcr r11
- mfspr r9, SPRG5
- mfspr r12, SPRG4
+ mfspr r9, SPRN_SPRG5
+ mfspr r12, SPRN_SPRG4
#endif
- mfspr r11, SPRG1
- mfspr r10, SPRG0
+ mfspr r11, SPRN_SPRG1
+ mfspr r10, SPRN_SPRG0
PPC405_ERR77_SYNC
rfi /* Should sync shadow TLBs */
b . /* prevent prefetch past rfi */
@@ -413,15 +374,15 @@ label:
lwz r9, 4(r0)
lwz r12, 0(r0)
#else
- mfspr r12, SPRG6
- mfspr r11, SPRG7
+ mfspr r12, SPRN_SPRG6
+ mfspr r11, SPRN_SPRG7
mtspr SPRN_PID, r12
mtcr r11
- mfspr r9, SPRG5
- mfspr r12, SPRG4
+ mfspr r9, SPRN_SPRG5
+ mfspr r12, SPRN_SPRG4
#endif
- mfspr r11, SPRG1
- mfspr r10, SPRG0
+ mfspr r11, SPRN_SPRG1
+ mfspr r10, SPRN_SPRG0
b DataAccess
/*
@@ -496,8 +457,8 @@ label:
* load TLB entries from the page table if they exist.
*/
START_EXCEPTION(0x1100, DTLBMiss)
- mtspr SPRG0, r10 /* Save some working registers */
- mtspr SPRG1, r11
+ mtspr SPRN_SPRG0, r10 /* Save some working registers */
+ mtspr SPRN_SPRG1, r11
#ifdef CONFIG_403GCX
stw r12, 0(r0)
stw r9, 4(r0)
@@ -506,12 +467,12 @@ label:
stw r11, 8(r0)
stw r12, 12(r0)
#else
- mtspr SPRG4, r12
- mtspr SPRG5, r9
+ mtspr SPRN_SPRG4, r12
+ mtspr SPRN_SPRG5, r9
mfcr r11
mfspr r12, SPRN_PID
- mtspr SPRG7, r11
- mtspr SPRG6, r12
+ mtspr SPRN_SPRG7, r11
+ mtspr SPRN_SPRG6, r12
#endif
mfspr r10, SPRN_DEAR /* Get faulting address */
@@ -529,7 +490,7 @@ label:
/* Get the PGD for the current thread.
*/
3:
- mfspr r11,SPRG3
+ mfspr r11,SPRN_SPRG3
lwz r11,PGDIR(r11)
4:
tophys(r11, r11)
@@ -579,15 +540,15 @@ label:
lwz r9, 4(r0)
lwz r12, 0(r0)
#else
- mfspr r12, SPRG6
- mfspr r11, SPRG7
+ mfspr r12, SPRN_SPRG6
+ mfspr r11, SPRN_SPRG7
mtspr SPRN_PID, r12
mtcr r11
- mfspr r9, SPRG5
- mfspr r12, SPRG4
+ mfspr r9, SPRN_SPRG5
+ mfspr r12, SPRN_SPRG4
#endif
- mfspr r11, SPRG1
- mfspr r10, SPRG0
+ mfspr r11, SPRN_SPRG1
+ mfspr r10, SPRN_SPRG0
b DataAccess
/* 0x1200 - Instruction TLB Miss Exception
@@ -595,8 +556,8 @@ label:
* registers and bailout to a different point.
*/
START_EXCEPTION(0x1200, ITLBMiss)
- mtspr SPRG0, r10 /* Save some working registers */
- mtspr SPRG1, r11
+ mtspr SPRN_SPRG0, r10 /* Save some working registers */
+ mtspr SPRN_SPRG1, r11
#ifdef CONFIG_403GCX
stw r12, 0(r0)
stw r9, 4(r0)
@@ -605,14 +566,14 @@ label:
stw r11, 8(r0)
stw r12, 12(r0)
#else
- mtspr SPRG4, r12
- mtspr SPRG5, r9
+ mtspr SPRN_SPRG4, r12
+ mtspr SPRN_SPRG5, r9
mfcr r11
mfspr r12, SPRN_PID
- mtspr SPRG7, r11
- mtspr SPRG6, r12
+ mtspr SPRN_SPRG7, r11
+ mtspr SPRN_SPRG6, r12
#endif
- mfspr r10, SRR0 /* Get faulting address */
+ mfspr r10, SPRN_SRR0 /* Get faulting address */
/* If we are faulting a kernel address, we have to use the
* kernel page tables.
@@ -628,7 +589,7 @@ label:
/* Get the PGD for the current thread.
*/
3:
- mfspr r11,SPRG3
+ mfspr r11,SPRN_SPRG3
lwz r11,PGDIR(r11)
4:
tophys(r11, r11)
@@ -678,15 +639,15 @@ label:
lwz r9, 4(r0)
lwz r12, 0(r0)
#else
- mfspr r12, SPRG6
- mfspr r11, SPRG7
+ mfspr r12, SPRN_SPRG6
+ mfspr r11, SPRN_SPRG7
mtspr SPRN_PID, r12
mtcr r11
- mfspr r9, SPRG5
- mfspr r12, SPRG4
+ mfspr r9, SPRN_SPRG5
+ mfspr r12, SPRN_SPRG4
#endif
- mfspr r11, SPRG1
- mfspr r10, SPRG0
+ mfspr r11, SPRN_SPRG1
+ mfspr r10, SPRN_SPRG0
b InstructionAccess
EXCEPTION(0x1300, Trap_13, UnknownException, EXC_XFER_EE)
@@ -754,8 +715,8 @@ label:
lwz r0,GPR0(r11)
lwz r1,GPR1(r11)
mtcrf 0x80,r10
- mtspr SRR2,r12
- mtspr SRR3,r9
+ mtspr SPRN_SRR2,r12
+ mtspr SPRN_SRR3,r9
lwz r9,GPR9(r11)
lwz r12,GPR12(r11)
lwz r10,crit_r10@l(0)
@@ -831,15 +792,15 @@ finish_tlb_load:
lwz r9, 4(r0)
lwz r12, 0(r0)
#else
- mfspr r12, SPRG6
- mfspr r11, SPRG7
+ mfspr r12, SPRN_SPRG6
+ mfspr r11, SPRN_SPRG7
mtspr SPRN_PID, r12
mtcr r11
- mfspr r9, SPRG5
- mfspr r12, SPRG4
+ mfspr r9, SPRN_SPRG5
+ mfspr r12, SPRN_SPRG4
#endif
- mfspr r11, SPRG1
- mfspr r10, SPRG0
+ mfspr r11, SPRN_SPRG1
+ mfspr r10, SPRN_SPRG0
PPC405_ERR77_SYNC
rfi /* Should sync shadow TLBs */
b . /* prevent prefetch past rfi */
@@ -863,7 +824,7 @@ start_here:
/* ptr to phys current thread */
tophys(r4,r2)
addi r4,r4,THREAD /* init task's THREAD */
- mtspr SPRG3,r4
+ mtspr SPRN_SPRG3,r4
/* stack */
lis r1,init_thread_union@ha
@@ -894,8 +855,8 @@ start_here:
tophys(r4,r4)
lis r3,(MSR_KERNEL & ~(MSR_IR|MSR_DR))@h
ori r3,r3,(MSR_KERNEL & ~(MSR_IR|MSR_DR))@l
- mtspr SRR0,r4
- mtspr SRR1,r3
+ mtspr SPRN_SRR0,r4
+ mtspr SPRN_SRR1,r3
rfi
b . /* prevent prefetch past rfi */
@@ -920,8 +881,8 @@ start_here:
ori r4,r4,MSR_KERNEL@l
lis r3,start_kernel@h
ori r3,r3,start_kernel@l
- mtspr SRR0,r3
- mtspr SRR1,r4
+ mtspr SPRN_SRR0,r3
+ mtspr SPRN_SRR1,r4
rfi /* enable MMU and jump to start_kernel */
b . /* prevent prefetch past rfi */
@@ -1030,10 +991,11 @@ _GLOBAL(swapper_pg_dir)
/* Stack for handling critical exceptions from kernel mode */
.section .bss
-critical_stack_bottom:
+ .align 12
+exception_stack_bottom:
.space 4096
critical_stack_top:
- .previous
+_GLOBAL(exception_stack_top)
/* This space gets a copy of optional info passed to us by the bootstrap
* which is used to pass parameters into the kernel like root=/dev/sda1, etc.
diff --git a/arch/ppc/kernel/head_8xx.S b/arch/ppc/kernel/head_8xx.S
index db3b530941a8b..5a7a64e91fc5e 100644
--- a/arch/ppc/kernel/head_8xx.S
+++ b/arch/ppc/kernel/head_8xx.S
@@ -101,10 +101,10 @@ __start:
turn_on_mmu:
mfmsr r0
ori r0,r0,MSR_DR|MSR_IR
- mtspr SRR1,r0
+ mtspr SPRN_SRR1,r0
lis r0,start_here@h
ori r0,r0,start_here@l
- mtspr SRR0,r0
+ mtspr SPRN_SRR0,r0
SYNC
rfi /* enables MMU */
@@ -115,18 +115,18 @@ turn_on_mmu:
* task's thread_struct.
*/
#define EXCEPTION_PROLOG \
- mtspr SPRG0,r10; \
- mtspr SPRG1,r11; \
+ mtspr SPRN_SPRG0,r10; \
+ mtspr SPRN_SPRG1,r11; \
mfcr r10; \
EXCEPTION_PROLOG_1; \
EXCEPTION_PROLOG_2
#define EXCEPTION_PROLOG_1 \
- mfspr r11,SRR1; /* check whether user or kernel */ \
+ mfspr r11,SPRN_SRR1; /* check whether user or kernel */ \
andi. r11,r11,MSR_PR; \
tophys(r11,r1); /* use tophys(r1) if kernel */ \
beq 1f; \
- mfspr r11,SPRG3; \
+ mfspr r11,SPRN_SPRG3; \
lwz r11,THREAD_INFO-THREAD(r11); \
addi r11,r11,THREAD_SIZE; \
tophys(r11,r11); \
@@ -138,14 +138,14 @@ turn_on_mmu:
stw r10,_CCR(r11); /* save registers */ \
stw r12,GPR12(r11); \
stw r9,GPR9(r11); \
- mfspr r10,SPRG0; \
+ mfspr r10,SPRN_SPRG0; \
stw r10,GPR10(r11); \
- mfspr r12,SPRG1; \
+ mfspr r12,SPRN_SPRG1; \
stw r12,GPR11(r11); \
mflr r10; \
stw r10,_LINK(r11); \
- mfspr r12,SRR0; \
- mfspr r9,SRR1; \
+ mfspr r12,SPRN_SRR0; \
+ mfspr r9,SPRN_SRR1; \
stw r1,GPR1(r11); \
stw r1,0(r11); \
tovirt(r1,r11); /* set new kernel sp */ \
@@ -209,9 +209,9 @@ i##n: \
. = 0x200
MachineCheck:
EXCEPTION_PROLOG
- mfspr r4,DAR
+ mfspr r4,SPRN_DAR
stw r4,_DAR(r11)
- mfspr r5,DSISR
+ mfspr r5,SPRN_DSISR
stw r5,_DSISR(r11)
addi r3,r1,STACK_FRAME_OVERHEAD
EXC_XFER_STD(0x200, MachineCheckException)
@@ -223,10 +223,10 @@ MachineCheck:
. = 0x300
DataAccess:
EXCEPTION_PROLOG
- mfspr r10,DSISR
+ mfspr r10,SPRN_DSISR
stw r10,_DSISR(r11)
mr r5,r10
- mfspr r4,DAR
+ mfspr r4,SPRN_DAR
EXC_XFER_EE_LITE(0x300, handle_page_fault)
/* Instruction access exception.
@@ -247,9 +247,9 @@ InstructionAccess:
. = 0x600
Alignment:
EXCEPTION_PROLOG
- mfspr r4,DAR
+ mfspr r4,SPRN_DAR
stw r4,_DAR(r11)
- mfspr r5,DSISR
+ mfspr r5,SPRN_DSISR
stw r5,_DSISR(r11)
addi r3,r1,STACK_FRAME_OVERHEAD
EXC_XFER_EE(0x600, AlignmentException)
@@ -301,14 +301,14 @@ InstructionTLBMiss:
stw r3, 8(r0)
#endif
DO_8xx_CPU6(0x3f80, r3)
- mtspr M_TW, r10 /* Save a couple of working registers */
+ mtspr SPRN_M_TW, r10 /* Save a couple of working registers */
mfcr r10
stw r10, 0(r0)
stw r11, 4(r0)
- mfspr r10, SRR0 /* Get effective address of fault */
+ mfspr r10, SPRN_SRR0 /* Get effective address of fault */
DO_8xx_CPU6(0x3780, r3)
- mtspr MD_EPN, r10 /* Have to use MD_EPN for walk, MI_EPN can't */
- mfspr r10, M_TWB /* Get level 1 table entry address */
+ mtspr SPRN_MD_EPN, r10 /* Have to use MD_EPN for walk, MI_EPN can't */
+ mfspr r10, SPRN_M_TWB /* Get level 1 table entry address */
/* If we are faulting a kernel address, we have to use the
* kernel page tables.
@@ -328,10 +328,10 @@ InstructionTLBMiss:
*/
ori r11,r11,1 /* Set valid bit */
DO_8xx_CPU6(0x2b80, r3)
- mtspr MI_TWC, r11 /* Set segment attributes */
+ mtspr SPRN_MI_TWC, r11 /* Set segment attributes */
DO_8xx_CPU6(0x3b80, r3)
- mtspr MD_TWC, r11 /* Load pte table base address */
- mfspr r11, MD_TWC /* ....and get the pte address */
+ mtspr SPRN_MD_TWC, r11 /* Load pte table base address */
+ mfspr r11, SPRN_MD_TWC /* ....and get the pte address */
lwz r10, 0(r11) /* Get the pte */
ori r10, r10, _PAGE_ACCESSED
@@ -346,9 +346,9 @@ InstructionTLBMiss:
2: li r11, 0x00f0
rlwimi r10, r11, 0, 24, 28 /* Set 24-27, clear 28 */
DO_8xx_CPU6(0x2d80, r3)
- mtspr MI_RPN, r10 /* Update TLB entry */
+ mtspr SPRN_MI_RPN, r10 /* Update TLB entry */
- mfspr r10, M_TW /* Restore registers */
+ mfspr r10, SPRN_M_TW /* Restore registers */
lwz r11, 0(r0)
mtcr r11
lwz r11, 4(r0)
@@ -363,11 +363,11 @@ DataStoreTLBMiss:
stw r3, 8(r0)
#endif
DO_8xx_CPU6(0x3f80, r3)
- mtspr M_TW, r10 /* Save a couple of working registers */
+ mtspr SPRN_M_TW, r10 /* Save a couple of working registers */
mfcr r10
stw r10, 0(r0)
stw r11, 4(r0)
- mfspr r10, M_TWB /* Get level 1 table entry address */
+ mfspr r10, SPRN_M_TWB /* Get level 1 table entry address */
/* If we are faulting a kernel address, we have to use the
* kernel page tables.
@@ -386,8 +386,8 @@ DataStoreTLBMiss:
*/
ori r11, r11, 1 /* Set valid bit in physical L2 page */
DO_8xx_CPU6(0x3b80, r3)
- mtspr MD_TWC, r11 /* Load pte table base address */
- mfspr r10, MD_TWC /* ....and get the pte address */
+ 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.
@@ -398,9 +398,9 @@ DataStoreTLBMiss:
*/
rlwimi r11, r10, 0, 27, 27
DO_8xx_CPU6(0x3b80, r3)
- mtspr MD_TWC, r11
+ mtspr SPRN_MD_TWC, r11
- mfspr r11, MD_TWC /* get the pte address again */
+ mfspr r11, SPRN_MD_TWC /* get the pte address again */
ori r10, r10, _PAGE_ACCESSED
stw r10, 0(r11)
@@ -413,9 +413,9 @@ DataStoreTLBMiss:
2: li r11, 0x00f0
rlwimi r10, r11, 0, 24, 28 /* Set 24-27, clear 28 */
DO_8xx_CPU6(0x3d80, r3)
- mtspr MD_RPN, r10 /* Update TLB entry */
+ mtspr SPRN_MD_RPN, r10 /* Update TLB entry */
- mfspr r10, M_TW /* Restore registers */
+ mfspr r10, SPRN_M_TW /* Restore registers */
lwz r11, 0(r0)
mtcr r11
lwz r11, 4(r0)
@@ -446,14 +446,14 @@ DataTLBError:
stw r3, 8(r0)
#endif
DO_8xx_CPU6(0x3f80, r3)
- mtspr M_TW, r10 /* Save a couple of working registers */
+ mtspr SPRN_M_TW, r10 /* Save a couple of working registers */
mfcr r10
stw r10, 0(r0)
stw r11, 4(r0)
/* First, make sure this was a store operation.
*/
- mfspr r10, DSISR
+ mfspr r10, SPRN_DSISR
andis. r11, r10, 0x0200 /* If set, indicates store op */
beq 2f
@@ -473,15 +473,15 @@ DataTLBError:
* are initialized in mapin_ram(). This will avoid the problem,
* assuming we only use the dcbi instruction on kernel addresses.
*/
- mfspr r10, DAR
+ mfspr r10, SPRN_DAR
rlwinm r11, r10, 0, 0, 19
ori r11, r11, MD_EVALID
- mfspr r10, M_CASID
+ mfspr r10, SPRN_M_CASID
rlwimi r11, r10, 0, 28, 31
DO_8xx_CPU6(0x3780, r3)
- mtspr MD_EPN, r11
+ mtspr SPRN_MD_EPN, r11
- mfspr r10, M_TWB /* Get level 1 table entry address */
+ mfspr r10, SPRN_M_TWB /* Get level 1 table entry address */
/* If we are faulting a kernel address, we have to use the
* kernel page tables.
@@ -500,8 +500,8 @@ DataTLBError:
*/
ori r11, r11, 1 /* Set valid bit in physical L2 page */
DO_8xx_CPU6(0x3b80, r3)
- mtspr MD_TWC, r11 /* Load pte table base address */
- mfspr r11, MD_TWC /* ....and get the pte address */
+ mtspr SPRN_MD_TWC, r11 /* Load pte table base address */
+ mfspr r11, SPRN_MD_TWC /* ....and get the pte address */
lwz r10, 0(r11) /* Get the pte */
andi. r11, r10, _PAGE_RW /* Is it writeable? */
@@ -510,7 +510,7 @@ DataTLBError:
/* Update 'changed', among others.
*/
ori r10, r10, _PAGE_DIRTY|_PAGE_ACCESSED|_PAGE_HWWRITE
- mfspr r11, MD_TWC /* Get pte address again */
+ mfspr r11, SPRN_MD_TWC /* Get pte address again */
stw r10, 0(r11) /* and update pte in table */
/* The Linux PTE won't go exactly into the MMU TLB.
@@ -522,9 +522,9 @@ DataTLBError:
li r11, 0x00f0
rlwimi r10, r11, 0, 24, 28 /* Set 24-27, clear 28 */
DO_8xx_CPU6(0x3d80, r3)
- mtspr MD_RPN, r10 /* Update TLB entry */
+ mtspr SPRN_MD_RPN, r10 /* Update TLB entry */
- mfspr r10, M_TW /* Restore registers */
+ mfspr r10, SPRN_M_TW /* Restore registers */
lwz r11, 0(r0)
mtcr r11
lwz r11, 4(r0)
@@ -533,7 +533,7 @@ DataTLBError:
#endif
rfi
2:
- mfspr r10, M_TW /* Restore registers */
+ mfspr r10, SPRN_M_TW /* Restore registers */
lwz r11, 0(r0)
mtcr r11
lwz r11, 4(r0)
@@ -576,9 +576,9 @@ start_here:
/* ptr to phys current thread */
tophys(r4,r2)
addi r4,r4,THREAD /* init task's THREAD */
- mtspr SPRG3,r4
+ mtspr SPRN_SPRG3,r4
li r3,0
- mtspr SPRG2,r3 /* 0 => r1 has kernel sp */
+ mtspr SPRN_SPRG2,r3 /* 0 => r1 has kernel sp */
/* stack */
lis r1,init_thread_union@ha
@@ -619,13 +619,13 @@ start_here:
stw r3, 12(r4)
lwz r3, 12(r4)
#endif
- mtspr M_TWB, r6
+ mtspr SPRN_M_TWB, r6
lis r4,2f@h
ori r4,r4,2f@l
tophys(r4,r4)
li r3,MSR_KERNEL & ~(MSR_IR|MSR_DR)
- mtspr SRR0,r4
- mtspr SRR1,r3
+ mtspr SPRN_SRR0,r4
+ mtspr SPRN_SRR1,r3
rfi
/* Load up the kernel context */
2:
@@ -647,8 +647,8 @@ start_here:
li r4,MSR_KERNEL
lis r3,start_kernel@h
ori r3,r3,start_kernel@l
- mtspr SRR0,r3
- mtspr SRR1,r4
+ mtspr SPRN_SRR0,r3
+ mtspr SPRN_SRR1,r4
rfi /* enable MMU and jump to start_kernel */
/* Set up the initial MMU state so we can do the first level of
@@ -667,7 +667,7 @@ initial_mmu:
#else
li r8, 0
#endif
- mtspr MI_CTR, r8 /* Set instruction MMU control */
+ mtspr SPRN_MI_CTR, r8 /* Set instruction MMU control */
#ifdef CONFIG_PIN_TLB
lis r10, (MD_RSV4I | MD_RESETVAL)@h
@@ -679,7 +679,7 @@ initial_mmu:
#ifndef CONFIG_8xx_COPYBACK
oris r10, r10, MD_WTDEF@h
#endif
- mtspr MD_CTR, r10 /* Set data TLB control */
+ mtspr SPRN_MD_CTR, r10 /* Set data TLB control */
/* Now map the lower 8 Meg into the TLBs. For this quick hack,
* we can load the instruction and data TLB registers with the
@@ -687,61 +687,61 @@ initial_mmu:
*/
lis r8, KERNELBASE@h /* Create vaddr for TLB */
ori r8, r8, MI_EVALID /* Mark it valid */
- mtspr MI_EPN, r8
- mtspr MD_EPN, r8
+ mtspr SPRN_MI_EPN, r8
+ mtspr SPRN_MD_EPN, r8
li r8, MI_PS8MEG /* Set 8M byte page */
ori r8, r8, MI_SVALID /* Make it valid */
- mtspr MI_TWC, r8
- mtspr MD_TWC, r8
+ mtspr SPRN_MI_TWC, r8
+ mtspr SPRN_MD_TWC, r8
li r8, MI_BOOTINIT /* Create RPN for address 0 */
- mtspr MI_RPN, r8 /* Store TLB entry */
- mtspr MD_RPN, r8
+ mtspr SPRN_MI_RPN, r8 /* Store TLB entry */
+ mtspr SPRN_MD_RPN, r8
lis r8, MI_Kp@h /* Set the protection mode */
- mtspr MI_AP, r8
- mtspr MD_AP, r8
+ mtspr SPRN_MI_AP, r8
+ mtspr SPRN_MD_AP, r8
/* Map another 8 MByte at the IMMR to get the processor
* internal registers (among other things).
*/
#ifdef CONFIG_PIN_TLB
addi r10, r10, 0x0100
- mtspr MD_CTR, r10
+ mtspr SPRN_MD_CTR, r10
#endif
mfspr r9, 638 /* Get current IMMR */
andis. r9, r9, 0xff80 /* Get 8Mbyte boundary */
mr r8, r9 /* Create vaddr for TLB */
ori r8, r8, MD_EVALID /* Mark it valid */
- mtspr MD_EPN, r8
+ mtspr SPRN_MD_EPN, r8
li r8, MD_PS8MEG /* Set 8M byte page */
ori r8, r8, MD_SVALID /* Make it valid */
- mtspr MD_TWC, r8
+ mtspr SPRN_MD_TWC, r8
mr r8, r9 /* Create paddr for TLB */
ori r8, r8, MI_BOOTINIT|0x2 /* Inhibit cache -- Cort */
- mtspr MD_RPN, r8
+ mtspr SPRN_MD_RPN, r8
#ifdef CONFIG_PIN_TLB
/* Map two more 8M kernel data pages.
*/
addi r10, r10, 0x0100
- mtspr MD_CTR, r10
+ mtspr SPRN_MD_CTR, r10
lis r8, KERNELBASE@h /* Create vaddr for TLB */
addis r8, r8, 0x0080 /* Add 8M */
ori r8, r8, MI_EVALID /* Mark it valid */
- mtspr MD_EPN, r8
+ mtspr SPRN_MD_EPN, r8
li r9, MI_PS8MEG /* Set 8M byte page */
ori r9, r9, MI_SVALID /* Make it valid */
- mtspr MD_TWC, r9
+ mtspr SPRN_MD_TWC, r9
li r11, MI_BOOTINIT /* Create RPN for address 0 */
addis r11, r11, 0x0080 /* Add 8M */
- mtspr MD_RPN, r8
+ mtspr SPRN_MD_RPN, r8
addis r8, r8, 0x0080 /* Add 8M */
- mtspr MD_EPN, r8
- mtspr MD_TWC, r9
+ mtspr SPRN_MD_EPN, r8
+ mtspr SPRN_MD_TWC, r9
addis r11, r11, 0x0080 /* Add 8M */
- mtspr MD_RPN, r8
+ mtspr SPRN_MD_RPN, r8
#endif
/* Since the cache is enabled according to the information we
@@ -749,20 +749,20 @@ initial_mmu:
* We should probably check/set other modes....later.
*/
lis r8, IDC_INVALL@h
- mtspr IC_CST, r8
- mtspr DC_CST, r8
+ mtspr SPRN_IC_CST, r8
+ mtspr SPRN_DC_CST, r8
lis r8, IDC_ENABLE@h
- mtspr IC_CST, r8
+ mtspr SPRN_IC_CST, r8
#ifdef CONFIG_8xx_COPYBACK
- mtspr DC_CST, r8
+ mtspr SPRN_DC_CST, r8
#else
/* For a debug option, I left this here to easily enable
* the write through cache mode
*/
lis r8, DC_SFWT@h
- mtspr DC_CST, r8
+ mtspr SPRN_DC_CST, r8
lis r8, IDC_ENABLE@h
- mtspr DC_CST, r8
+ mtspr SPRN_DC_CST, r8
#endif
blr
@@ -793,15 +793,15 @@ _GLOBAL(set_context)
li r7, 0x3980
stw r7, 12(r6)
lwz r7, 12(r6)
- mtspr M_TWB, r4 /* Update MMU base address */
+ mtspr SPRN_M_TWB, r4 /* Update MMU base address */
li r7, 0x3380
stw r7, 12(r6)
lwz r7, 12(r6)
- mtspr M_CASID, r3 /* Update context */
+ mtspr SPRN_M_CASID, r3 /* Update context */
#else
- mtspr M_CASID,r3 /* Update context */
+ mtspr SPRN_M_CASID,r3 /* Update context */
tophys (r4, r4)
- mtspr M_TWB, r4 /* and pgd */
+ mtspr SPRN_M_TWB, r4 /* and pgd */
#endif
SYNC
blr
diff --git a/arch/ppc/kernel/head_booke.h b/arch/ppc/kernel/head_booke.h
index 618b469ac8386..884dac916bce7 100644
--- a/arch/ppc/kernel/head_booke.h
+++ b/arch/ppc/kernel/head_booke.h
@@ -18,72 +18,98 @@
mfspr r11,SPRN_SRR1; /* check whether user or kernel */\
andi. r11,r11,MSR_PR; \
beq 1f; \
- mfspr r1,SPRG3; /* if from user, start at top of */\
+ mfspr r1,SPRN_SPRG3; /* if from user, start at top of */\
lwz r1,THREAD_INFO-THREAD(r1); /* this thread's kernel stack */\
addi r1,r1,THREAD_SIZE; \
1: subi r1,r1,INT_FRAME_SIZE; /* Allocate an exception frame */\
- tophys(r11,r1); \
+ mr r11,r1; \
stw r10,_CCR(r11); /* save various registers */\
stw r12,GPR12(r11); \
stw r9,GPR9(r11); \
- mfspr r10,SPRG0; \
+ mfspr r10,SPRN_SPRG0; \
stw r10,GPR10(r11); \
- mfspr r12,SPRG1; \
+ mfspr r12,SPRN_SPRG1; \
stw r12,GPR11(r11); \
mflr r10; \
stw r10,_LINK(r11); \
- mfspr r10,SPRG4R; \
- mfspr r12,SRR0; \
+ mfspr r10,SPRN_SPRG4R; \
+ mfspr r12,SPRN_SRR0; \
stw r10,GPR1(r11); \
- mfspr r9,SRR1; \
+ mfspr r9,SPRN_SRR1; \
stw r10,0(r11); \
rlwinm r9,r9,0,14,12; /* clear MSR_WE (necessary?) */\
stw r0,GPR0(r11); \
SAVE_4GPRS(3, r11); \
SAVE_2GPRS(7, r11)
+/* To handle the additional exception priority levels on 40x and Book-E
+ * processors we allocate a 4k stack per additional priority level. The various
+ * head_xxx.S files allocate space (exception_stack_top) for each priority's
+ * stack times the number of CPUs
+ *
+ * On 40x critical is the only additional level
+ * On 44x/e500 we have critical and machine check
+ *
+ * Additionally we reserve a SPRG for each priority level so we can free up a
+ * GPR to use as the base for indirect access to the exception stacks. This
+ * is necessary since the MMU is always on, for Book-E parts, and the stacks
+ * are offset from KERNELBASE.
+ *
+ */
+#define BOOKE_EXCEPTION_STACK_SIZE (8192)
+
+/* CRIT_SPRG only used in critical exception handling */
+#define CRIT_SPRG SPRN_SPRG2
+/* MCHECK_SPRG only used in critical exception handling */
+#define MCHECK_SPRG SPRN_SPRG6W
+
+#define MCHECK_STACK_TOP (exception_stack_top - 4096)
+#define CRIT_STACK_TOP (exception_stack_top)
+
+#ifdef CONFIG_SMP
+#define BOOKE_LOAD_CRIT_STACK \
+ mfspr r8,SPRN_PIR; \
+ mulli r8,r8,BOOKE_EXCEPTION_STACK_SIZE; \
+ neg r8,r8; \
+ addis r8,r8,CRIT_STACK_TOP@ha; \
+ addi r8,r8,CRIT_STACK_TOP@l
+#define BOOKE_LOAD_MCHECK_STACK \
+ mfspr r8,SPRN_PIR; \
+ mulli r8,r8,BOOKE_EXCEPTION_STACK_SIZE; \
+ neg r8,r8; \
+ addis r8,r8,MCHECK_STACK_TOP@ha; \
+ addi r8,r8,MCHECK_STACK_TOP@l
+#else
+#define BOOKE_LOAD_CRIT_STACK \
+ lis r8,CRIT_STACK_TOP@h; \
+ ori r8,r8,CRIT_STACK_TOP@l
+#define BOOKE_LOAD_MCHECK_STACK \
+ lis r8,MCHECK_STACK_TOP@h; \
+ ori r8,r8,MCHECK_STACK_TOP@l
+#endif
+
/*
* Exception prolog for critical exceptions. This is a little different
* from the normal exception prolog above since a critical exception
* can potentially occur at any point during normal exception processing.
* Thus we cannot use the same SPRG registers as the normal prolog above.
- * Instead we use a couple of words of memory at low physical addresses.
- * This is OK since we don't support SMP on these processors. For Book E
- * processors, we also have a reserved register (SPRG2) that is only used
- * in critical exceptions so we can free up a GPR to use as the base for
- * indirect access to the critical exception save area. This is necessary
- * since the MMU is always on and the save area is offset from KERNELBASE.
+ * Instead we use a portion of the critical exception stack at low physical
+ * addresses.
*/
+
#define CRITICAL_EXCEPTION_PROLOG \
- mtspr SPRG2,r8; /* SPRG2 only used in criticals */ \
- lis r8,crit_save@ha; \
- stw r10,crit_r10@l(r8); \
- stw r11,crit_r11@l(r8); \
- mfspr r10,SPRG0; \
- stw r10,crit_sprg0@l(r8); \
- mfspr r10,SPRG1; \
- stw r10,crit_sprg1@l(r8); \
- mfspr r10,SPRG4R; \
- stw r10,crit_sprg4@l(r8); \
- mfspr r10,SPRG5R; \
- stw r10,crit_sprg5@l(r8); \
- mfspr r10,SPRG7R; \
- stw r10,crit_sprg7@l(r8); \
- mfspr r10,SPRN_PID; \
- stw r10,crit_pid@l(r8); \
- mfspr r10,SRR0; \
- stw r10,crit_srr0@l(r8); \
- mfspr r10,SRR1; \
- stw r10,crit_srr1@l(r8); \
- mfspr r8,SPRG2; /* SPRG2 only used in criticals */ \
+ mtspr CRIT_SPRG,r8; \
+ BOOKE_LOAD_CRIT_STACK; /* r8 points to the crit stack */ \
+ stw r10,GPR10-INT_FRAME_SIZE(r8); \
+ stw r11,GPR11-INT_FRAME_SIZE(r8); \
mfcr r10; /* save CR in r10 for now */\
mfspr r11,SPRN_CSRR1; /* check whether user or kernel */\
andi. r11,r11,MSR_PR; \
- lis r11,critical_stack_top@h; \
- ori r11,r11,critical_stack_top@l; \
+ mr r11,r8; \
+ mfspr r8,CRIT_SPRG; \
beq 1f; \
/* COMING FROM USER MODE */ \
- mfspr r11,SPRG3; /* if from user, start at top of */\
+ mfspr r11,SPRN_SPRG3; /* if from user, start at top of */\
lwz r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\
addi r11,r11,THREAD_SIZE; \
1: subi r11,r11,INT_FRAME_SIZE; /* Allocate an exception frame */\
@@ -96,11 +122,11 @@
stw r12,_DEAR(r11); /* since they may have had stuff */\
mfspr r9,SPRN_ESR; /* in them at the point where the */\
stw r9,_ESR(r11); /* exception was taken */\
- mfspr r12,CSRR0; \
+ mfspr r12,SPRN_CSRR0; \
stw r1,GPR1(r11); \
- mfspr r9,CSRR1; \
+ mfspr r9,SPRN_CSRR1; \
stw r1,0(r11); \
- tovirt(r1,r11); \
+ mr r1,r11; \
rlwinm r9,r9,0,14,12; /* clear MSR_WE (necessary?) */\
stw r0,GPR0(r11); \
SAVE_4GPRS(3, r11); \
@@ -109,46 +135,21 @@
/*
* Exception prolog for machine check exceptions. This is similar to
* the critical exception prolog, except that machine check exceptions
- * have their own save area. For Book E processors, we also have a
- * reserved register (SPRG6) that is only used in machine check exceptions
- * so we can free up a GPR to use as the base for indirect access to the
- * machine check exception save area. This is necessary since the MMU
- * is always on and the save area is offset from KERNELBASE.
+ * have their stack.
*/
#define MCHECK_EXCEPTION_PROLOG \
- mtspr SPRG6W,r8; /* SPRG6 used in machine checks */ \
- lis r8,mcheck_save@ha; \
- stw r10,mcheck_r10@l(r8); \
- stw r11,mcheck_r11@l(r8); \
- mfspr r10,SPRG0; \
- stw r10,mcheck_sprg0@l(r8); \
- mfspr r10,SPRG1; \
- stw r10,mcheck_sprg1@l(r8); \
- mfspr r10,SPRG4R; \
- stw r10,mcheck_sprg4@l(r8); \
- mfspr r10,SPRG5R; \
- stw r10,mcheck_sprg5@l(r8); \
- mfspr r10,SPRG7R; \
- stw r10,mcheck_sprg7@l(r8); \
- mfspr r10,SPRN_PID; \
- stw r10,mcheck_pid@l(r8); \
- mfspr r10,SRR0; \
- stw r10,mcheck_srr0@l(r8); \
- mfspr r10,SRR1; \
- stw r10,mcheck_srr1@l(r8); \
- mfspr r10,CSRR0; \
- stw r10,mcheck_csrr0@l(r8); \
- mfspr r10,CSRR1; \
- stw r10,mcheck_csrr1@l(r8); \
- mfspr r8,SPRG6R; /* SPRG6 used in machine checks */ \
+ mtspr MCHECK_SPRG,r8; \
+ BOOKE_LOAD_MCHECK_STACK; /* r8 points to the mcheck stack */\
+ stw r10,GPR10-INT_FRAME_SIZE(r8); \
+ stw r11,GPR11-INT_FRAME_SIZE(r8); \
mfcr r10; /* save CR in r10 for now */\
mfspr r11,SPRN_MCSRR1; /* check whether user or kernel */\
andi. r11,r11,MSR_PR; \
- lis r11,mcheck_stack_top@h; \
- ori r11,r11,mcheck_stack_top@l; \
+ mr r11,r8; \
+ mfspr r8,MCHECK_SPRG; \
beq 1f; \
/* COMING FROM USER MODE */ \
- mfspr r11,SPRG3; /* if from user, start at top of */\
+ mfspr r11,SPRN_SPRG3; /* if from user, start at top of */\
lwz r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\
addi r11,r11,THREAD_SIZE; \
1: subi r11,r11,INT_FRAME_SIZE; /* Allocate an exception frame */\
@@ -161,11 +162,11 @@
stw r12,_DEAR(r11); /* since they may have had stuff */\
mfspr r9,SPRN_ESR; /* in them at the point where the */\
stw r9,_ESR(r11); /* exception was taken */\
- mfspr r12,MCSRR0; \
+ mfspr r12,SPRN_MCSRR0; \
stw r1,GPR1(r11); \
- mfspr r9,MCSRR1; \
+ mfspr r9,SPRN_MCSRR1; \
stw r1,0(r11); \
- tovirt(r1,r11); \
+ mr r1,r11; \
rlwinm r9,r9,0,14,12; /* clear MSR_WE (necessary?) */\
stw r0,GPR0(r11); \
SAVE_4GPRS(3, r11); \
@@ -194,8 +195,8 @@ label:
CRITICAL_EXCEPTION_PROLOG; \
addi r3,r1,STACK_FRAME_OVERHEAD; \
EXC_XFER_TEMPLATE(hdlr, n+2, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \
- NOCOPY, transfer_to_handler_full, \
- ret_from_except_full)
+ NOCOPY, crit_transfer_to_handler, \
+ ret_from_crit_exc)
#define MCHECK_EXCEPTION(n, label, hdlr) \
START_EXCEPTION(label); \
@@ -285,15 +286,15 @@ label:
lwz r0,GPR0(r11); \
lwz r1,GPR1(r11); \
mtcrf 0x80,r10; \
- mtspr CSRR0,r12; \
- mtspr CSRR1,r9; \
+ mtspr SPRN_CSRR0,r12; \
+ mtspr SPRN_CSRR1,r9; \
lwz r9,GPR9(r11); \
lwz r12,GPR12(r11); \
- mtspr SPRG2,r8; /* SPRG2 only used in criticals */ \
- lis r8,crit_save@ha; \
- lwz r10,crit_r10@l(r8); \
- lwz r11,crit_r11@l(r8); \
- mfspr r8,SPRG2; \
+ mtspr CRIT_SPRG,r8; \
+ BOOKE_LOAD_CRIT_STACK; /* r8 points to the crit stack */ \
+ lwz r10,GPR10-INT_FRAME_SIZE(r8); \
+ lwz r11,GPR11-INT_FRAME_SIZE(r8); \
+ mfspr r8,CRIT_SPRG; \
\
rfci; \
b .; \
diff --git a/arch/ppc/kernel/head_e500.S b/arch/ppc/kernel/head_e500.S
index 47a35214f3d14..e478de5a92d32 100644
--- a/arch/ppc/kernel/head_e500.S
+++ b/arch/ppc/kernel/head_e500.S
@@ -33,6 +33,7 @@
*/
#include <linux/config.h>
+#include <linux/threads.h>
#include <asm/processor.h>
#include <asm/page.h>
#include <asm/mmu.h>
@@ -188,8 +189,8 @@ skpinv: addi r6,r6,1 /* Increment */
1: mflr r9
rlwimi r7,r9,0,20,31
addi r7,r7,24
- mtspr SRR0,r7
- mtspr SRR1,r6
+ mtspr SPRN_SRR0,r7
+ mtspr SPRN_SRR1,r6
rfi
/* 4. Clear out PIDs & Search info */
@@ -236,8 +237,8 @@ skpinv: addi r6,r6,1 /* Increment */
1: mflr r9
rlwimi r6,r9,0,20,31
addi r6,r6,24
- mtspr SRR0,r6
- mtspr SRR1,r7
+ mtspr SPRN_SRR0,r6
+ mtspr SPRN_SRR1,r7
rfi /* start execution out of TLB1[0] entry */
/* 8. Clear out the temp mapping */
@@ -302,7 +303,7 @@ skpinv: addi r6,r6,1 /* Increment */
/* ptr to current thread */
addi r4,r2,THREAD /* init task's THREAD */
- mtspr SPRG3,r4
+ mtspr SPRN_SPRG3,r4
/* stack */
lis r1,init_thread_union@h
@@ -342,8 +343,8 @@ skpinv: addi r6,r6,1 /* Increment */
ori r4,r4,start_kernel@l
lis r3,MSR_KERNEL@h
ori r3,r3,MSR_KERNEL@l
- mtspr SRR0,r4
- mtspr SRR1,r3
+ mtspr SPRN_SRR0,r4
+ mtspr SPRN_SRR1,r3
rfi /* change context and jump to start_kernel */
/*
@@ -372,12 +373,12 @@ interrupt_base:
/* Data Storage Interrupt */
START_EXCEPTION(DataStorage)
- mtspr SPRG0, r10 /* Save some working registers */
- mtspr SPRG1, r11
- mtspr SPRG4W, r12
- mtspr SPRG5W, r13
+ mtspr SPRN_SPRG0, r10 /* Save some working registers */
+ mtspr SPRN_SPRG1, r11
+ mtspr SPRN_SPRG4W, r12
+ mtspr SPRN_SPRG5W, r13
mfcr r11
- mtspr SPRG7W, r11
+ mtspr SPRN_SPRG7W, r11
/*
* Check if it was a store fault, if not then bail
@@ -401,7 +402,7 @@ interrupt_base:
/* Get the PGD for the current thread */
3:
- mfspr r11,SPRG3
+ mfspr r11,SPRN_SPRG3
lwz r11,PGDIR(r11)
4:
rlwimi r11, r10, 12, 20, 29 /* Create L1 (pgdir/pmd) address */
@@ -442,12 +443,12 @@ interrupt_base:
tlbwe
/* Done...restore registers and get out of here. */
- mfspr r11, SPRG7R
+ mfspr r11, SPRN_SPRG7R
mtcr r11
- mfspr r13, SPRG5R
- mfspr r12, SPRG4R
- mfspr r11, SPRG1
- mfspr r10, SPRG0
+ mfspr r13, SPRN_SPRG5R
+ mfspr r12, SPRN_SPRG4R
+ mfspr r11, SPRN_SPRG1
+ mfspr r10, SPRN_SPRG0
rfi /* Force context change */
2:
@@ -455,12 +456,12 @@ interrupt_base:
* The bailout. Restore registers to pre-exception conditions
* and call the heavyweights to help us out.
*/
- mfspr r11, SPRG7R
+ mfspr r11, SPRN_SPRG7R
mtcr r11
- mfspr r13, SPRG5R
- mfspr r12, SPRG4R
- mfspr r11, SPRG1
- mfspr r10, SPRG0
+ mfspr r13, SPRN_SPRG5R
+ mfspr r12, SPRN_SPRG4R
+ mfspr r11, SPRN_SPRG1
+ mfspr r10, SPRN_SPRG0
b data_access
/* Instruction Storage Interrupt */
@@ -499,12 +500,12 @@ interrupt_base:
/* Data TLB Error Interrupt */
START_EXCEPTION(DataTLBError)
- mtspr SPRG0, r10 /* Save some working registers */
- mtspr SPRG1, r11
- mtspr SPRG4W, r12
- mtspr SPRG5W, r13
+ mtspr SPRN_SPRG0, r10 /* Save some working registers */
+ mtspr SPRN_SPRG1, r11
+ mtspr SPRN_SPRG4W, r12
+ mtspr SPRN_SPRG5W, r13
mfcr r11
- mtspr SPRG7W, r11
+ mtspr SPRN_SPRG7W, r11
mfspr r10, SPRN_DEAR /* Get faulting address */
/* If we are faulting a kernel address, we have to use the
@@ -525,7 +526,7 @@ interrupt_base:
/* Get the PGD for the current thread */
3:
- mfspr r11,SPRG3
+ mfspr r11,SPRN_SPRG3
lwz r11,PGDIR(r11)
4:
@@ -548,12 +549,12 @@ interrupt_base:
/* The bailout. Restore registers to pre-exception conditions
* and call the heavyweights to help us out.
*/
- mfspr r11, SPRG7R
+ mfspr r11, SPRN_SPRG7R
mtcr r11
- mfspr r13, SPRG5R
- mfspr r12, SPRG4R
- mfspr r11, SPRG1
- mfspr r10, SPRG0
+ mfspr r13, SPRN_SPRG5R
+ mfspr r12, SPRN_SPRG4R
+ mfspr r11, SPRN_SPRG1
+ mfspr r10, SPRN_SPRG0
b data_access
/* Instruction TLB Error Interrupt */
@@ -563,13 +564,13 @@ interrupt_base:
* to a different point.
*/
START_EXCEPTION(InstructionTLBError)
- mtspr SPRG0, r10 /* Save some working registers */
- mtspr SPRG1, r11
- mtspr SPRG4W, r12
- mtspr SPRG5W, r13
+ mtspr SPRN_SPRG0, r10 /* Save some working registers */
+ mtspr SPRN_SPRG1, r11
+ mtspr SPRN_SPRG4W, r12
+ mtspr SPRN_SPRG5W, r13
mfcr r11
- mtspr SPRG7W, r11
- mfspr r10, SRR0 /* Get faulting address */
+ mtspr SPRN_SPRG7W, r11
+ mfspr r10, SPRN_SRR0 /* Get faulting address */
/* If we are faulting a kernel address, we have to use the
* kernel page tables.
@@ -589,7 +590,7 @@ interrupt_base:
/* Get the PGD for the current thread */
3:
- mfspr r11,SPRG3
+ mfspr r11,SPRN_SPRG3
lwz r11,PGDIR(r11)
4:
@@ -613,12 +614,12 @@ interrupt_base:
/* The bailout. Restore registers to pre-exception conditions
* and call the heavyweights to help us out.
*/
- mfspr r11, SPRG7R
+ mfspr r11, SPRN_SPRG7R
mtcr r11
- mfspr r13, SPRG5R
- mfspr r12, SPRG4R
- mfspr r11, SPRG1
- mfspr r10, SPRG0
+ mfspr r13, SPRN_SPRG5R
+ mfspr r12, SPRN_SPRG4R
+ mfspr r11, SPRN_SPRG1
+ mfspr r10, SPRN_SPRG0
b InstructionStorage
#ifdef CONFIG_SPE
@@ -713,12 +714,12 @@ finish_tlb_load:
tlbwe
/* Done...restore registers and get out of here. */
- mfspr r11, SPRG7R
+ mfspr r11, SPRN_SPRG7R
mtcr r11
- mfspr r13, SPRG5R
- mfspr r12, SPRG4R
- mfspr r11, SPRG1
- mfspr r10, SPRG0
+ mfspr r13, SPRN_SPRG5R
+ mfspr r12, SPRN_SPRG4R
+ mfspr r11, SPRN_SPRG1
+ mfspr r10, SPRN_SPRG0
rfi /* Force context change */
#ifdef CONFIG_SPE
@@ -762,7 +763,7 @@ load_up_spe:
#endif /* CONFIG_SMP */
/* enable use of SPE after return */
oris r9,r9,MSR_SPE@h
- mfspr r5,SPRG3 /* current task's THREAD (phys) */
+ mfspr r5,SPRN_SPRG3 /* current task's THREAD (phys) */
li r4,1
li r10,THREAD_ACC
stw r4,THREAD_USED_SPE(r5)
@@ -781,16 +782,14 @@ load_up_spe:
lwz r10,_LINK(r11)
mtlr r10
REST_GPR(10, r11)
- mtspr SRR1,r9
- mtspr SRR0,r12
+ mtspr SPRN_SRR1,r9
+ mtspr SPRN_SRR0,r12
REST_GPR(9, r11)
REST_GPR(12, r11)
lwz r11,GPR11(r11)
SYNC
rfi
-
-
/*
* SPE unavailable trap from kernel - print a message, but let
* the task use SPE in the kernel until it returns to user mode.
@@ -929,78 +928,13 @@ _GLOBAL(empty_zero_page)
_GLOBAL(swapper_pg_dir)
.space 4096
+/* Reserved 4k for the critical exception stack & 4k for the machine
+ * check stack per CPU for kernel mode exceptions */
.section .bss
-/* Stack for handling critical exceptions from kernel mode */
-critical_stack_bottom:
- .space 4096
-critical_stack_top:
- .previous
-
-/* Stack for handling machine check exceptions from kernel mode */
-mcheck_stack_bottom:
- .space 4096
-mcheck_stack_top:
- .previous
-
-/*
- * This area is used for temporarily saving registers during the
- * critical and machine check exception prologs. It must always
- * follow the page aligned allocations, so it starts on a page
- * boundary, ensuring that all crit_save areas are in a single
- * page.
- */
-
-/* crit_save */
-_GLOBAL(crit_save)
- .space 4
-_GLOBAL(crit_r10)
- .space 4
-_GLOBAL(crit_r11)
- .space 4
-_GLOBAL(crit_sprg0)
- .space 4
-_GLOBAL(crit_sprg1)
- .space 4
-_GLOBAL(crit_sprg4)
- .space 4
-_GLOBAL(crit_sprg5)
- .space 4
-_GLOBAL(crit_sprg7)
- .space 4
-_GLOBAL(crit_pid)
- .space 4
-_GLOBAL(crit_srr0)
- .space 4
-_GLOBAL(crit_srr1)
- .space 4
-
-/* mcheck_save */
-_GLOBAL(mcheck_save)
- .space 4
-_GLOBAL(mcheck_r10)
- .space 4
-_GLOBAL(mcheck_r11)
- .space 4
-_GLOBAL(mcheck_sprg0)
- .space 4
-_GLOBAL(mcheck_sprg1)
- .space 4
-_GLOBAL(mcheck_sprg4)
- .space 4
-_GLOBAL(mcheck_sprg5)
- .space 4
-_GLOBAL(mcheck_sprg7)
- .space 4
-_GLOBAL(mcheck_pid)
- .space 4
-_GLOBAL(mcheck_srr0)
- .space 4
-_GLOBAL(mcheck_srr1)
- .space 4
-_GLOBAL(mcheck_csrr0)
- .space 4
-_GLOBAL(mcheck_csrr1)
- .space 4
+ .align 12
+exception_stack_bottom:
+ .space BOOKE_EXCEPTION_STACK_SIZE * NR_CPUS
+_GLOBAL(exception_stack_top)
/*
* This space gets a copy of optional info passed to us by the bootstrap
@@ -1016,4 +950,3 @@ _GLOBAL(cmd_line)
abatron_pteptrs:
.space 8
-
diff --git a/arch/ppc/kernel/l2cr.S b/arch/ppc/kernel/l2cr.S
index 8abf2ee7a0c0e..c39441048266f 100644
--- a/arch/ppc/kernel/l2cr.S
+++ b/arch/ppc/kernel/l2cr.S
@@ -125,14 +125,14 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
* DPM can possibly interfere with the state machine in the processor
* that invalidates the L2 cache tags.
*/
- mfspr r8,HID0 /* Save HID0 in r8 */
+ mfspr r8,SPRN_HID0 /* Save HID0 in r8 */
rlwinm r4,r8,0,12,10 /* Turn off HID0[DPM] */
sync
- mtspr HID0,r4 /* Disable DPM */
+ mtspr SPRN_HID0,r4 /* Disable DPM */
sync
/* Get the current enable bit of the L2CR into r4 */
- mfspr r4,L2CR
+ mfspr r4,SPRN_L2CR
/* Tweak some bits */
rlwinm r5,r3,0,0,0 /* r5 contains the new enable bit */
@@ -186,7 +186,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
.balign L1_CACHE_LINE_SIZE
22:
sync
- mtspr L2CR,r3
+ mtspr SPRN_L2CR,r3
sync
b 23f
20:
@@ -199,27 +199,27 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
/* Perform a global invalidation */
oris r3,r3,0x0020
sync
- mtspr L2CR,r3
+ mtspr SPRN_L2CR,r3
sync
isync /* For errata */
BEGIN_FTR_SECTION
/* On the 7450, we wait for the L2I bit to clear......
*/
-10: mfspr r3,L2CR
+10: mfspr r3,SPRN_L2CR
andis. r4,r3,0x0020
bne 10b
b 11f
END_FTR_SECTION_IFSET(CPU_FTR_SPEC7450)
/* Wait for the invalidation to complete */
-3: mfspr r3,L2CR
+3: mfspr r3,SPRN_L2CR
rlwinm. r4,r3,0,31,31
bne 3b
11: rlwinm r3,r3,0,11,9 /* Turn off the L2I bit */
sync
- mtspr L2CR,r3
+ mtspr SPRN_L2CR,r3
sync
/* See if we need to enable the cache */
@@ -228,7 +228,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_SPEC7450)
/* Enable the cache */
oris r3,r3,0x8000
- mtspr L2CR,r3
+ mtspr SPRN_L2CR,r3
sync
4:
@@ -250,7 +250,7 @@ _GLOBAL(_get_L2CR)
/* Return the L2CR contents */
li r3,0
BEGIN_FTR_SECTION
- mfspr r3,L2CR
+ mfspr r3,SPRN_L2CR
END_FTR_SECTION_IFSET(CPU_FTR_L2CR)
blr
diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S
index 2513cb15ea44e..73f7c23b0dd4f 100644
--- a/arch/ppc/kernel/misc.S
+++ b/arch/ppc/kernel/misc.S
@@ -216,10 +216,10 @@ _GLOBAL(low_choose_750fx_pll)
/* If switching to PLL1, disable HID0:BTIC */
cmplwi cr0,r3,0
beq 1f
- mfspr r5,HID0
+ mfspr r5,SPRN_HID0
rlwinm r5,r5,0,27,25
sync
- mtspr HID0,r5
+ mtspr SPRN_HID0,r5
isync
sync
@@ -241,10 +241,10 @@ _GLOBAL(low_choose_750fx_pll)
/* If switching to PLL0, enable HID0:BTIC */
cmplwi cr0,r3,0
bne 1f
- mfspr r5,HID0
+ mfspr r5,SPRN_HID0
ori r5,r5,HID0_BTIC
sync
- mtspr HID0,r5
+ mtspr SPRN_HID0,r5
isync
sync
@@ -579,7 +579,7 @@ _GLOBAL(flush_instruction_cache)
#if defined(CONFIG_8xx)
isync
lis r5, IDC_INVALL@h
- mtspr IC_CST, r5
+ mtspr SPRN_IC_CST, r5
#elif defined(CONFIG_4xx)
#ifdef CONFIG_403GCX
li r3, 512
@@ -597,14 +597,14 @@ _GLOBAL(flush_instruction_cache)
ori r3,r3,L1CSR1_ICFI|L1CSR1_ICLFR
mtspr SPRN_L1CSR1,r3
#else
- mfspr r3,PVR
+ mfspr r3,SPRN_PVR
rlwinm r3,r3,16,16,31
cmpwi 0,r3,1
beqlr /* for 601, do nothing */
/* 603/604 processor - use invalidate-all bit in HID0 */
- mfspr r3,HID0
+ mfspr r3,SPRN_HID0
ori r3,r3,HID0_ICFI
- mtspr HID0,r3
+ mtspr SPRN_HID0,r3
#endif /* CONFIG_8xx/4xx */
isync
blr
@@ -1450,3 +1450,4 @@ _GLOBAL(sys_call_table)
.long sys_add_key
.long sys_request_key /* 270 */
.long sys_keyctl
+ .long sys_waitid
diff --git a/arch/ppc/kernel/pci.c b/arch/ppc/kernel/pci.c
index 7ed1d755ac8ff..b8f67396ec48d 100644
--- a/arch/ppc/kernel/pci.c
+++ b/arch/ppc/kernel/pci.c
@@ -1058,7 +1058,7 @@ do_update_p2p_io_resource(struct pci_bus *bus, int enable_vga)
return;
res = *(bus->resource[0]);
- DBG("Remapping Bus %d, bridge: %s\n", bus->number, bridge->slot_name);
+ 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);
@@ -1478,97 +1478,145 @@ pci_resource_to_bus(struct pci_dev *pdev, struct resource *res)
return res->start;
}
-/*
- * Platform support for /proc/bus/pci/X/Y mmap()s,
- * modelled on the sparc64 implementation by Dave Miller.
- * -- paulus.
- */
-/*
- * Adjust vm_pgoff of VMA such that it is the physical page offset
- * corresponding to the 32-bit pci bus offset for DEV requested by the user.
- *
- * Basically, the user finds the base address for his device which he wishes
- * to mmap. They read the 32-bit value from the config space base register,
- * add whatever PAGE_SIZE multiple offset they wish, and feed this into the
- * offset parameter of mmap on /proc/bus/pci/XXX for that device.
- *
- * Returns negative error code on failure, zero on success.
- */
-static __inline__ int
-__pci_mmap_make_offset(struct pci_dev *dev, struct vm_area_struct *vma,
- enum pci_mmap_state mmap_state)
+static struct resource *__pci_mmap_make_offset(struct pci_dev *dev,
+ unsigned long *offset,
+ enum pci_mmap_state mmap_state)
{
- struct pci_controller *hose = (struct pci_controller *) dev->sysdata;
- unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
- unsigned long size = vma->vm_end - vma->vm_start;
- unsigned long base;
- struct resource *res;
- int i;
- int ret = -EINVAL;
+ struct pci_controller *hose = pci_bus_to_hose(dev->bus->number);
+ unsigned long io_offset = 0;
+ int i, res_bit;
if (hose == 0)
- return -EINVAL; /* should never happen */
- if (offset + size <= offset)
- return -EINVAL;
+ return NULL; /* should never happen */
+ /* If memory, add on the PCI bridge address offset */
if (mmap_state == pci_mmap_mem) {
- /* PCI memory space */
- base = hose->pci_mem_offset;
- for (i = 0; i < 3; ++i) {
- res = &hose->mem_resources[i];
- if (res->flags == 0)
- continue;
- if (offset >= res->start - base
- && offset + size - 1 <= res->end - base) {
- ret = 0;
- break;
- }
- }
- offset += hose->pci_mem_offset;
+ *offset += hose->pci_mem_offset;
+ res_bit = IORESOURCE_MEM;
} else {
- /* PCI I/O space */
- base = (unsigned long)hose->io_base_virt - isa_io_base;
- res = &hose->io_resource;
- if (offset >= res->start - base
- && offset + size - 1 <= res->end - base)
- ret = 0;
- offset += hose->io_base_phys;
+ io_offset = (unsigned long)hose->io_base_virt;
+ *offset += io_offset;
+ res_bit = IORESOURCE_IO;
}
- vma->vm_pgoff = offset >> PAGE_SHIFT;
- return ret;
-}
+ /*
+ * 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;
-/*
- * Set vm_flags of VMA, as appropriate for this architecture, for a pci device
- * mapping.
- */
-static __inline__ void
-__pci_mmap_set_flags(struct pci_dev *dev, struct vm_area_struct *vma,
- enum pci_mmap_state mmap_state)
-{
- vma->vm_flags |= VM_SHM | VM_LOCKED | VM_IO;
+ /* 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_BASE;
+ return rp;
+ }
+
+ return NULL;
}
/*
* Set vm_page_prot of VMA, as appropriate for this architecture, for a pci
* device mapping.
*/
-static __inline__ void
-__pci_mmap_set_pgprot(struct pci_dev *dev, struct vm_area_struct *vma,
- enum pci_mmap_state mmap_state, int write_combine)
+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)
{
- int prot = pgprot_val(vma->vm_page_prot);
+ 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)
+ if (write_combine)
+ prot &= ~_PAGE_GUARDED;
+ else
prot |= _PAGE_GUARDED;
- vma->vm_page_prot = __pgprot(prot);
+
+ 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 offset,
+ unsigned long size,
+ pgprot_t protection)
+{
+ struct pci_dev *pdev = NULL;
+ struct resource *found = NULL;
+ unsigned long prot = pgprot_val(protection);
+ int i;
+
+ if (page_is_ram(offset >> PAGE_SHIFT))
+ 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
@@ -1582,14 +1630,19 @@ 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;
- ret = __pci_mmap_make_offset(dev, vma, mmap_state);
- if (ret < 0)
- return ret;
+ rp = __pci_mmap_make_offset(dev, &offset, mmap_state);
+ if (rp == NULL)
+ return -EINVAL;
- __pci_mmap_set_flags(dev, vma, mmap_state);
- __pci_mmap_set_pgprot(dev, vma, mmap_state, write_combine);
+ 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);
diff --git a/arch/ppc/kernel/ppc_htab.c b/arch/ppc/kernel/ppc_htab.c
index b5cd7e411e65c..ca810025993f3 100644
--- a/arch/ppc/kernel/ppc_htab.c
+++ b/arch/ppc/kernel/ppc_htab.c
@@ -108,7 +108,7 @@ static int ppc_htab_show(struct seq_file *m, void *v)
PTE *ptr;
#endif /* CONFIG_PPC_STD_MMU */
- if (cur_cpu_spec[0]->cpu_features & CPU_FTR_604_PERF_MON) {
+ if (cpu_has_feature(CPU_FTR_604_PERF_MON)) {
mmcr0 = mfspr(SPRN_MMCR0);
pmc1 = mfspr(SPRN_PMC1);
pmc2 = mfspr(SPRN_PMC2);
@@ -209,7 +209,7 @@ static ssize_t ppc_htab_write(struct file * file, const char __user * ubuffer,
if ( !strncmp( buffer, "reset", 5) )
{
- if (cur_cpu_spec[0]->cpu_features & CPU_FTR_604_PERF_MON) {
+ if (cpu_has_feature(CPU_FTR_604_PERF_MON)) {
/* reset PMC1 and PMC2 */
mtspr(SPRN_PMC1, 0);
mtspr(SPRN_PMC2, 0);
@@ -221,7 +221,7 @@ static ssize_t ppc_htab_write(struct file * file, const char __user * ubuffer,
}
/* Everything below here requires the performance monitor feature. */
- if ( !cur_cpu_spec[0]->cpu_features & CPU_FTR_604_PERF_MON )
+ if (!cpu_has_feature(CPU_FTR_604_PERF_MON))
return count;
/* turn off performance monitoring */
@@ -339,7 +339,7 @@ int proc_dol2crvec(ctl_table *table, int write, struct file *filp,
"0.5", "1.0", "(reserved2)", "(reserved3)"
};
- if (!(cur_cpu_spec[0]->cpu_features & CPU_FTR_L2CR))
+ if (!cpu_has_feature(CPU_FTR_L2CR))
return -EFAULT;
if ( /*!table->maxlen ||*/ (*ppos && !write)) {
diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c
index 1ee8c12bac750..2ccb58fe4fc3c 100644
--- a/arch/ppc/kernel/ppc_ksyms.c
+++ b/arch/ppc/kernel/ppc_ksyms.c
@@ -319,7 +319,8 @@ EXPORT_SYMBOL(debugger_fault_handler);
EXPORT_SYMBOL(cpm_install_handler);
EXPORT_SYMBOL(cpm_free_handler);
#endif /* CONFIG_8xx */
-#if defined(CONFIG_8xx) || defined(CONFIG_40x) || defined(CONFIG_85xx)
+#if defined(CONFIG_8xx) || defined(CONFIG_40x) || defined(CONFIG_85xx) ||\
+ defined(CONFIG_83xx)
EXPORT_SYMBOL(__res);
#endif
diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c
index 5e7ce4b8febc0..e97ce635b99e6 100644
--- a/arch/ppc/kernel/setup.c
+++ b/arch/ppc/kernel/setup.c
@@ -41,6 +41,10 @@
#include <asm/xmon.h>
#include <asm/ocp.h>
+#if defined(CONFIG_85xx) || defined(CONFIG_83xx)
+#include <asm/ppc_sys.h>
+#endif
+
#if defined CONFIG_KGDB
#include <asm/kgdb.h>
#endif
@@ -56,7 +60,6 @@ extern void ppc6xx_idle(void);
extern void power4_idle(void);
extern boot_infos_t *boot_infos;
-unsigned char aux_device_present;
struct ide_machdep_calls ppc_ide_md;
char *sysmap;
unsigned long sysmap_size;
@@ -179,7 +182,7 @@ int show_cpuinfo(struct seq_file *m, void *v)
pvr = cpu_data[i].pvr;
lpj = cpu_data[i].loops_per_jiffy;
#else
- pvr = mfspr(PVR);
+ pvr = mfspr(SPRN_PVR);
lpj = loops_per_jiffy;
#endif
@@ -227,6 +230,10 @@ int show_cpuinfo(struct seq_file *m, void *v)
maj = ((pvr >> 8) & 0xFF) - 1;
min = pvr & 0xFF;
break;
+ case 0x8083: /* e300 */
+ maj = PVR_MAJ(pvr);
+ min = PVR_MIN(pvr);
+ break;
case 0x8020: /* e500 */
maj = PVR_MAJ(pvr);
min = PVR_MIN(pvr);
@@ -243,6 +250,12 @@ int show_cpuinfo(struct seq_file *m, void *v)
seq_printf(m, "bogomips\t: %lu.%02lu\n",
lpj / (500000/HZ), (lpj / (5000/HZ)) % 100);
+#if defined(CONFIG_85xx) || defined(CONFIG_83xx)
+ if (cur_ppc_sys_spec->ppc_sys_name)
+ seq_printf(m, "chipset\t\t: %s\n",
+ cur_ppc_sys_spec->ppc_sys_name);
+#endif
+
#ifdef CONFIG_SMP
seq_printf(m, "\n");
#endif
@@ -335,14 +348,15 @@ int __openfirmware
of_show_percpuinfo(struct seq_file *m, int i)
{
struct device_node *cpu_node;
- int *fp, s;
+ u32 *fp;
+ int s;
cpu_node = find_type_devices("cpu");
if (!cpu_node)
return 0;
for (s = 0; s < i && cpu_node->next; s++)
cpu_node = cpu_node->next;
- fp = (int *) get_property(cpu_node, "clock-frequency", NULL);
+ fp = (u32 *)get_property(cpu_node, "clock-frequency", NULL);
if (fp)
seq_printf(m, "clock\t\t: %dMHz\n", *fp / 1000000);
return 0;
@@ -619,7 +633,7 @@ machine_init(unsigned long r3, unsigned long r4, unsigned long r5,
/* Checks "l2cr=xxxx" command-line option */
int __init ppc_setup_l2cr(char *str)
{
- if (cur_cpu_spec[0]->cpu_features & CPU_FTR_L2CR) {
+ if (cpu_has_feature(CPU_FTR_L2CR)) {
unsigned long val = simple_strtoul(str, NULL, 0);
printk(KERN_INFO "l2cr set to %lx\n", val);
_set_L2CR(0); /* force invalidate by disable cache */
@@ -720,7 +734,7 @@ void __init setup_arch(char **cmdline_p)
* Systems with OF can look in the properties on the cpu node(s)
* for a possibly more accurate value.
*/
- if (cur_cpu_spec[0]->cpu_features & CPU_FTR_SPLIT_ID_CACHE) {
+ if (cpu_has_feature(CPU_FTR_SPLIT_ID_CACHE)) {
dcache_bsize = cur_cpu_spec[0]->dcache_bsize;
icache_bsize = cur_cpu_spec[0]->icache_bsize;
ucache_bsize = 0;
diff --git a/arch/ppc/kernel/signal.c b/arch/ppc/kernel/signal.c
index 4b8b96d8a0c06..9567d3041ea7c 100644
--- a/arch/ppc/kernel/signal.c
+++ b/arch/ppc/kernel/signal.c
@@ -28,6 +28,7 @@
#include <linux/elf.h>
#include <linux/tty.h>
#include <linux/binfmts.h>
+#include <linux/suspend.h>
#include <asm/ucontext.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
@@ -118,7 +119,7 @@ sys_sigaction(int sig, const struct old_sigaction __user *act,
if (act) {
old_sigset_t mask;
- if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
+ if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
__get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
__get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
return -EFAULT;
@@ -130,7 +131,7 @@ sys_sigaction(int sig, const struct old_sigaction __user *act,
ret = do_sigaction(sig, (act? &new_ka: NULL), (oact? &old_ka: NULL));
if (!ret && oact) {
- if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
+ if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
__put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
__put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
return -EFAULT;
@@ -376,7 +377,7 @@ handle_rt_signal(unsigned long sig, struct k_sigaction *ka,
/* create a stack frame for the caller of the handler */
newsp -= __SIGNAL_FRAMESIZE + 16;
- if (verify_area(VERIFY_WRITE, (void __user *) newsp, origsp - newsp))
+ if (!access_ok(VERIFY_WRITE, (void __user *) newsp, origsp - newsp))
goto badframe;
/* Put the siginfo & fill in most of the ucontext */
@@ -445,7 +446,7 @@ int sys_swapcontext(struct ucontext __user *old_ctx,
return -EINVAL;
if (old_ctx != NULL) {
- if (verify_area(VERIFY_WRITE, old_ctx, sizeof(*old_ctx))
+ if (!access_ok(VERIFY_WRITE, old_ctx, sizeof(*old_ctx))
|| save_user_regs(regs, &old_ctx->uc_mcontext, 0)
|| __copy_to_user(&old_ctx->uc_sigmask,
&current->blocked, sizeof(sigset_t))
@@ -454,7 +455,7 @@ int sys_swapcontext(struct ucontext __user *old_ctx,
}
if (new_ctx == NULL)
return 0;
- if (verify_area(VERIFY_READ, new_ctx, sizeof(*new_ctx))
+ if (!access_ok(VERIFY_READ, new_ctx, sizeof(*new_ctx))
|| __get_user(tmp, (u8 __user *) new_ctx)
|| __get_user(tmp, (u8 __user *) (new_ctx + 1) - 1))
return -EFAULT;
@@ -464,7 +465,7 @@ int sys_swapcontext(struct ucontext __user *old_ctx,
* image of the user's registers, we can't just return -EFAULT
* because the user's registers will be corrupted. For instance
* the NIP value may have been updated but not some of the
- * other registers. Given that we have done the verify_area
+ * other registers. Given that we have done the access_ok
* and successfully read the first and last bytes of the region
* above, this should only happen in an out-of-memory situation
* or if another thread unmaps the region containing the context.
@@ -487,7 +488,7 @@ int sys_rt_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8,
rt_sf = (struct rt_sigframe __user *)
(regs->gpr[1] + __SIGNAL_FRAMESIZE + 16);
- if (verify_area(VERIFY_READ, rt_sf, sizeof(struct rt_sigframe)))
+ if (!access_ok(VERIFY_READ, rt_sf, sizeof(struct rt_sigframe)))
goto bad;
if (do_setcontext(&rt_sf->uc, regs, 1))
goto bad;
@@ -572,7 +573,7 @@ int sys_debug_setcontext(struct ucontext __user *ctx,
* image of the user's registers, we can't just return -EFAULT
* because the user's registers will be corrupted. For instance
* the NIP value may have been updated but not some of the
- * other registers. Given that we have done the verify_area
+ * other registers. Given that we have done the access_ok
* and successfully read the first and last bytes of the region
* above, this should only happen in an out-of-memory situation
* or if another thread unmaps the region containing the context.
@@ -622,7 +623,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
/* create a stack frame for the caller of the handler */
newsp -= __SIGNAL_FRAMESIZE;
- if (verify_area(VERIFY_WRITE, (void __user *) newsp, origsp - newsp))
+ if (!access_ok(VERIFY_WRITE, (void __user *) newsp, origsp - newsp))
goto badframe;
#if _NSIG != 64
@@ -680,7 +681,7 @@ int sys_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8,
restore_sigmask(&set);
sr = (struct mcontext __user *) sigctx.regs;
- if (verify_area(VERIFY_READ, sr, sizeof(*sr))
+ if (!access_ok(VERIFY_READ, sr, sizeof(*sr))
|| restore_user_regs(regs, sr, 1))
goto badframe;
@@ -704,6 +705,14 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
unsigned long frame, newsp;
int signr, ret;
+ if (current->flags & PF_FREEZE) {
+ refrigerator(PF_FREEZE);
+ signr = 0;
+ ret = regs->gpr[3];
+ if (!signal_pending(current))
+ goto no_signal;
+ }
+
if (!oldset)
oldset = &current->blocked;
@@ -726,6 +735,7 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
regs->gpr[3] = EINTR;
/* note that the cr0.SO bit is already set */
} else {
+no_signal:
regs->nip -= 4; /* Back up & retry system call */
regs->result = 0;
regs->trap = 0;
diff --git a/arch/ppc/kernel/smp.c b/arch/ppc/kernel/smp.c
index 7ed8a3bb81df4..e70b587b9e514 100644
--- a/arch/ppc/kernel/smp.c
+++ b/arch/ppc/kernel/smp.c
@@ -35,14 +35,12 @@
#include <asm/tlbflush.h>
#include <asm/xmon.h>
-int smp_threads_ready;
volatile int smp_commenced;
int smp_tb_synchronized;
struct cpuinfo_PPC cpu_data[NR_CPUS];
struct klock_info_struct klock_info = { KLOCK_CLEAR, 0 };
atomic_t ipi_recv;
atomic_t ipi_sent;
-unsigned long cache_decay_ticks = HZ/100;
cpumask_t cpu_online_map;
cpumask_t cpu_possible_map;
int smp_hw_index[NR_CPUS];
@@ -119,7 +117,7 @@ void smp_message_recv(int msg, struct pt_regs *regs)
*/
void smp_send_tlb_invalidate(int cpu)
{
- if ( PVR_VER(mfspr(PVR)) == 8 )
+ if ( PVR_VER(mfspr(SPRN_PVR)) == 8 )
smp_message_pass(MSG_ALL_BUT_SELF, PPC_MSG_INVALIDATE_TLB, 0, 0);
}
@@ -283,7 +281,7 @@ static void __devinit smp_store_cpu_info(int id)
/* assume bogomips are same for everything */
c->loops_per_jiffy = loops_per_jiffy;
- c->pvr = mfspr(PVR);
+ c->pvr = mfspr(SPRN_PVR);
}
void __init smp_prepare_cpus(unsigned int max_cpus)
diff --git a/arch/ppc/kernel/swsusp.S b/arch/ppc/kernel/swsusp.S
new file mode 100644
index 0000000000000..55148bb88d399
--- /dev/null
+++ b/arch/ppc/kernel/swsusp.S
@@ -0,0 +1,349 @@
+#include <linux/config.h>
+#include <linux/threads.h>
+#include <asm/processor.h>
+#include <asm/page.h>
+#include <asm/cputable.h>
+#include <asm/thread_info.h>
+#include <asm/ppc_asm.h>
+#include <asm/offsets.h>
+
+
+/*
+ * Structure for storing CPU registers on the save area.
+ */
+#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_LR 0x70
+#define SL_R12 0x74 /* r12 to r31 */
+#define SL_SIZE (SL_R12 + 80)
+
+ .section .data
+ .align 5
+
+_GLOBAL(swsusp_save_area)
+ .space SL_SIZE
+
+
+ .section .text
+ .align 5
+
+_GLOBAL(swsusp_arch_suspend)
+
+ lis r11,swsusp_save_area@h
+ ori r11,r11,swsusp_save_area@l
+
+ mflr r0
+ stw r0,SL_LR(r11)
+ mfcr r0
+ stw r0,SL_CR(r11)
+ stw r1,SL_SP(r11)
+ stw r2,SL_R2(r11)
+ stmw r12,SL_R12(r11)
+
+ /* Save MSR & SDR1 */
+ mfmsr r4
+ stw r4,SL_MSR(r11)
+ mfsdr1 r4
+ stw r4,SL_SDR1(r11)
+
+ /* Get a stable timebase and save it */
+1: mftbu r4
+ stw r4,SL_TB(r11)
+ mftb r5
+ stw r5,SL_TB+4(r11)
+ mftbu r3
+ cmpw r3,r4
+ bne 1b
+
+ /* Save SPRGs */
+ mfsprg r4,0
+ stw r4,SL_SPRG0(r11)
+ mfsprg r4,1
+ stw r4,SL_SPRG0+4(r11)
+ mfsprg r4,2
+ stw r4,SL_SPRG0+8(r11)
+ mfsprg r4,3
+ stw r4,SL_SPRG0+12(r11)
+
+ /* Save BATs */
+ mfdbatu r4,0
+ stw r4,SL_DBAT0(r11)
+ mfdbatl r4,0
+ stw r4,SL_DBAT0+4(r11)
+ mfdbatu r4,1
+ stw r4,SL_DBAT1(r11)
+ mfdbatl r4,1
+ stw r4,SL_DBAT1+4(r11)
+ mfdbatu r4,2
+ stw r4,SL_DBAT2(r11)
+ mfdbatl r4,2
+ stw r4,SL_DBAT2+4(r11)
+ mfdbatu r4,3
+ stw r4,SL_DBAT3(r11)
+ mfdbatl r4,3
+ stw r4,SL_DBAT3+4(r11)
+ mfibatu r4,0
+ stw r4,SL_IBAT0(r11)
+ mfibatl r4,0
+ stw r4,SL_IBAT0+4(r11)
+ mfibatu r4,1
+ stw r4,SL_IBAT1(r11)
+ mfibatl r4,1
+ stw r4,SL_IBAT1+4(r11)
+ mfibatu r4,2
+ stw r4,SL_IBAT2(r11)
+ mfibatl r4,2
+ stw r4,SL_IBAT2+4(r11)
+ mfibatu r4,3
+ stw r4,SL_IBAT3(r11)
+ mfibatl r4,3
+ stw r4,SL_IBAT3+4(r11)
+
+#if 0
+ /* Backup various CPU config stuffs */
+ bl __save_cpu_setup
+#endif
+ /* Call the low level suspend stuff (we should probably have made
+ * a stackframe...
+ */
+ bl swsusp_save
+
+ /* Restore LR from the save area */
+ lis r11,swsusp_save_area@h
+ ori r11,r11,swsusp_save_area@l
+ lwz r0,SL_LR(r11)
+ mtlr r0
+
+ blr
+
+
+/* Resume code */
+_GLOBAL(swsusp_arch_resume)
+
+ /* Stop pending alitvec streams and memory accesses */
+BEGIN_FTR_SECTION
+ DSSALL
+END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
+ sync
+
+ /* Disable MSR:DR to make sure we don't take a TLB or
+ * hash miss during the copy, as our hash table will
+ * for a while be unuseable. For .text, we assume we are
+ * covered by a BAT. This works only for non-G5 at this
+ * point. G5 will need a better approach, possibly using
+ * a small temporary hash table filled with large mappings,
+ * disabling the MMU completely isn't a good option for
+ * performance reasons.
+ * (Note that 750's may have the same performance issue as
+ * the G5 in this case, we should investigate using moving
+ * BATs for these CPUs)
+ */
+ mfmsr r0
+ sync
+ rlwinm r0,r0,0,28,26 /* clear MSR_DR */
+ mtmsr r0
+ sync
+ isync
+
+ /* Load ptr the list of pages to copy in r3 */
+ lis r11,(pagedir_nosave - KERNELBASE)@h
+ ori r11,r11,pagedir_nosave@l
+ lwz r10,0(r11)
+
+ /* Copy the pages. This is a very basic implementation, to
+ * be replaced by something more cache efficient */
+1:
+ tophys(r3,r10)
+ li r0,256
+ mtctr r0
+ lwz r11,pbe_address(r3) /* source */
+ tophys(r5,r11)
+ lwz r10,pbe_orig_address(r3) /* destination */
+ tophys(r6,r10)
+2:
+ lwz r8,0(r5)
+ lwz r9,4(r5)
+ lwz r10,8(r5)
+ lwz r11,12(r5)
+ addi r5,r5,16
+ stw r8,0(r6)
+ stw r9,4(r6)
+ stw r10,8(r6)
+ stw r11,12(r6)
+ addi r6,r6,16
+ bdnz 2b
+ lwz r10,pbe_next(r3)
+ cmpwi 0,r10,0
+ bne 1b
+
+ /* Do a very simple cache flush/inval of the L1 to ensure
+ * coherency of the icache
+ */
+ lis r3,0x0002
+ mtctr r3
+ li r3, 0
+1:
+ lwz r0,0(r3)
+ addi r3,r3,0x0020
+ bdnz 1b
+ isync
+ sync
+
+ /* Now flush those cache lines */
+ lis r3,0x0002
+ mtctr r3
+ li r3, 0
+1:
+ dcbf 0,r3
+ addi r3,r3,0x0020
+ bdnz 1b
+ sync
+
+ /* Ok, we are now running with the kernel data of the old
+ * kernel fully restored. We can get to the save area
+ * easily now. As for the rest of the code, it assumes the
+ * loader kernel and the booted one are exactly identical
+ */
+ lis r11,swsusp_save_area@h
+ ori r11,r11,swsusp_save_area@l
+ tophys(r11,r11)
+
+#if 0
+ /* Restore various CPU config stuffs */
+ bl __restore_cpu_setup
+#endif
+ /* Restore the BATs, and SDR1. Then we can turn on the MMU.
+ * This is a bit hairy as we are running out of those BATs,
+ * but first, our code is probably in the icache, and we are
+ * writing the same value to the BAT, so that should be fine,
+ * though a better solution will have to be found long-term
+ */
+ lwz r4,SL_SDR1(r11)
+ mtsdr1 r4
+ lwz r4,SL_SPRG0(r11)
+ mtsprg 0,r4
+ lwz r4,SL_SPRG0+4(r11)
+ mtsprg 1,r4
+ lwz r4,SL_SPRG0+8(r11)
+ mtsprg 2,r4
+ lwz r4,SL_SPRG0+12(r11)
+ mtsprg 3,r4
+
+#if 0
+ lwz r4,SL_DBAT0(r11)
+ mtdbatu 0,r4
+ lwz r4,SL_DBAT0+4(r11)
+ mtdbatl 0,r4
+ lwz r4,SL_DBAT1(r11)
+ mtdbatu 1,r4
+ lwz r4,SL_DBAT1+4(r11)
+ mtdbatl 1,r4
+ lwz r4,SL_DBAT2(r11)
+ mtdbatu 2,r4
+ lwz r4,SL_DBAT2+4(r11)
+ mtdbatl 2,r4
+ lwz r4,SL_DBAT3(r11)
+ mtdbatu 3,r4
+ lwz r4,SL_DBAT3+4(r11)
+ mtdbatl 3,r4
+ lwz r4,SL_IBAT0(r11)
+ mtibatu 0,r4
+ lwz r4,SL_IBAT0+4(r11)
+ mtibatl 0,r4
+ lwz r4,SL_IBAT1(r11)
+ mtibatu 1,r4
+ lwz r4,SL_IBAT1+4(r11)
+ mtibatl 1,r4
+ lwz r4,SL_IBAT2(r11)
+ mtibatu 2,r4
+ lwz r4,SL_IBAT2+4(r11)
+ mtibatl 2,r4
+ lwz r4,SL_IBAT3(r11)
+ mtibatu 3,r4
+ lwz r4,SL_IBAT3+4(r11)
+ mtibatl 3,r4
+#endif
+
+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(r11)
+ bl turn_on_mmu
+ tovirt(r11,r11)
+
+ /* Restore TB */
+ li r3,0
+ mttbl r3
+ lwz r3,SL_TB(r11)
+ lwz r4,SL_TB+4(r11)
+ mttbu r3
+ mttbl r4
+
+ /* Kick decrementer */
+ li r0,1
+ mtdec r0
+
+ /* Restore the callee-saved registers and return */
+ lwz r0,SL_CR(r11)
+ mtcr r0
+ lwz r2,SL_R2(r11)
+ lmw r12,SL_R12(r11)
+ lwz r1,SL_SP(r11)
+ lwz r0,SL_LR(r11)
+ mtlr r0
+
+ // XXX Note: we don't really need to call swsusp_resume
+
+ li r3,0
+ blr
+
+/* FIXME:This construct is actually not useful since we don't shut
+ * down the instruction MMU, we could just flip back MSR-DR on.
+ */
+turn_on_mmu:
+ mflr r4
+ mtsrr0 r4
+ mtsrr1 r3
+ sync
+ isync
+ rfi
+
diff --git a/arch/ppc/kernel/syscalls.c b/arch/ppc/kernel/syscalls.c
index 6d1c9c413cbef..124313ce3c090 100644
--- a/arch/ppc/kernel/syscalls.c
+++ b/arch/ppc/kernel/syscalls.c
@@ -77,7 +77,7 @@ sys_ipc (uint call, int first, int second, int third, void __user *ptr, long fif
if (!ptr)
break;
- if ((ret = verify_area (VERIFY_READ, ptr, sizeof(long)))
+ if ((ret = access_ok(VERIFY_READ, ptr, sizeof(long)) ? 0 : -EFAULT)
|| (ret = get_user(fourth.__pad, (void __user *__user *)ptr)))
break;
ret = sys_semctl (first, second, third, fourth);
@@ -93,7 +93,7 @@ sys_ipc (uint call, int first, int second, int third, void __user *ptr, long fif
if (!ptr)
break;
- if ((ret = verify_area (VERIFY_READ, ptr, sizeof(tmp)))
+ if ((ret = access_ok(VERIFY_READ, ptr, sizeof(tmp)) ? 0 : -EFAULT)
|| (ret = copy_from_user(&tmp,
(struct ipc_kludge __user *) ptr,
sizeof (tmp)) ? -EFAULT : 0))
@@ -117,8 +117,8 @@ sys_ipc (uint call, int first, int second, int third, void __user *ptr, long fif
case SHMAT: {
ulong raddr;
- if ((ret = verify_area(VERIFY_WRITE, (ulong __user *) third,
- sizeof(ulong))))
+ if ((ret = access_ok(VERIFY_WRITE, (ulong __user *) third,
+ sizeof(ulong)) ? 0 : -EFAULT))
break;
ret = do_shmat (first, (char __user *) ptr, second, &raddr);
if (ret)
@@ -213,7 +213,7 @@ ppc_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp, s
if ( (unsigned long)n >= 4096 )
{
unsigned long __user *buffer = (unsigned long __user *)n;
- if (verify_area(VERIFY_READ, buffer, 5*sizeof(unsigned long))
+ if (!access_ok(VERIFY_READ, buffer, 5*sizeof(unsigned long))
|| __get_user(n, buffer)
|| __get_user(inp, ((fd_set __user * __user *)(buffer+1)))
|| __get_user(outp, ((fd_set __user * __user *)(buffer+2)))
diff --git a/arch/ppc/kernel/temp.c b/arch/ppc/kernel/temp.c
index 8d4b226e1342a..fe8bb634ead0a 100644
--- a/arch/ppc/kernel/temp.c
+++ b/arch/ppc/kernel/temp.c
@@ -223,7 +223,7 @@ int __init TAU_init(void)
/* We assume in SMP that if one CPU has TAU support, they
* all have it --BenH
*/
- if (!(cur_cpu_spec[0]->cpu_features & CPU_FTR_TAU)) {
+ if (!cpu_has_feature(CPU_FTR_TAU)) {
printk("Thermal assist unit not available\n");
tau_initialized = 0;
return 1;
diff --git a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c
index 0d7eb748d709a..ed5c7acdca70a 100644
--- a/arch/ppc/kernel/traps.c
+++ b/arch/ppc/kernel/traps.c
@@ -389,6 +389,87 @@ void RunModeException(struct pt_regs *regs)
#define INST_MCRXR 0x7c000400
#define INST_MCRXR_MASK 0x7c0007fe
+#define INST_STRING 0x7c00042a
+#define INST_STRING_MASK 0x7c0007fe
+#define INST_STRING_GEN_MASK 0x7c00067e
+#define INST_LSWI 0x7c0004aa
+#define INST_LSWX 0x7c00042a
+#define INST_STSWI 0x7c0005aa
+#define INST_STSWX 0x7c00052a
+
+static int emulate_string_inst(struct pt_regs *regs, u32 instword)
+{
+ u8 rT = (instword >> 21) & 0x1f;
+ u8 rA = (instword >> 16) & 0x1f;
+ u8 NB_RB = (instword >> 11) & 0x1f;
+ u32 num_bytes;
+ u32 EA;
+ int pos = 0;
+
+ /* Early out if we are an invalid form of lswx */
+ if ((instword & INST_STRING_MASK) == INST_LSWX)
+ if ((rA >= rT) || (NB_RB >= rT) || (rT == rA) || (rT == NB_RB))
+ return -EINVAL;
+
+ /* Early out if we are an invalid form of lswi */
+ if ((instword & INST_STRING_MASK) == INST_LSWI)
+ if ((rA >= rT) || (rT == rA))
+ return -EINVAL;
+
+ EA = (rA == 0) ? 0 : regs->gpr[rA];
+
+ switch (instword & INST_STRING_MASK) {
+ case INST_LSWX:
+ case INST_STSWX:
+ EA += NB_RB;
+ num_bytes = regs->xer & 0x7f;
+ break;
+ case INST_LSWI:
+ case INST_STSWI:
+ num_bytes = (NB_RB == 0) ? 32 : NB_RB;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ while (num_bytes != 0)
+ {
+ u8 val;
+ u32 shift = 8 * (3 - (pos & 0x3));
+
+ switch ((instword & INST_STRING_MASK)) {
+ case INST_LSWX:
+ case INST_LSWI:
+ if (get_user(val, (u8 __user *)EA))
+ return -EFAULT;
+ /* first time updating this reg,
+ * zero it out */
+ if (pos == 0)
+ regs->gpr[rT] = 0;
+ regs->gpr[rT] |= val << shift;
+ break;
+ case INST_STSWI:
+ case INST_STSWX:
+ val = regs->gpr[rT] >> shift;
+ if (put_user(val, (u8 __user *)EA))
+ return -EFAULT;
+ break;
+ }
+ /* move EA to next address */
+ EA += 1;
+ num_bytes--;
+
+ /* manage our position within the register */
+ if (++pos == 4) {
+ pos = 0;
+ if (++rT == 32)
+ rT = 0;
+ }
+ }
+
+ return 0;
+}
+
static int emulate_instruction(struct pt_regs *regs)
{
u32 instword;
@@ -405,7 +486,7 @@ static int emulate_instruction(struct pt_regs *regs)
*/
if ((instword & INST_MFSPR_PVR_MASK) == INST_MFSPR_PVR) {
rd = (instword >> 21) & 0x1f;
- regs->gpr[rd] = mfspr(PVR);
+ regs->gpr[rd] = mfspr(SPRN_PVR);
return 0;
}
@@ -423,6 +504,10 @@ static int emulate_instruction(struct pt_regs *regs)
return 0;
}
+ /* Emulate load/store string insn. */
+ if ((instword & INST_STRING_GEN_MASK) == INST_STRING)
+ return emulate_string_inst(regs, instword);
+
return -EINVAL;
}
diff --git a/arch/ppc/kernel/vmlinux.lds.S b/arch/ppc/kernel/vmlinux.lds.S
index 5d2cbc7807f85..0c0e714b84de7 100644
--- a/arch/ppc/kernel/vmlinux.lds.S
+++ b/arch/ppc/kernel/vmlinux.lds.S
@@ -74,6 +74,12 @@ SECTIONS
CONSTRUCTORS
}
+ . = ALIGN(4096);
+ __nosave_begin = .;
+ .data_nosave : { *(.data.nosave) }
+ . = ALIGN(4096);
+ __nosave_end = .;
+
. = ALIGN(32);
.data.cacheline_aligned : { *(.data.cacheline_aligned) }
diff --git a/arch/ppc/mm/hashtable.S b/arch/ppc/mm/hashtable.S
index e3c7d94fc8442..ab83132a7ed0b 100644
--- a/arch/ppc/mm/hashtable.S
+++ b/arch/ppc/mm/hashtable.S
@@ -101,7 +101,7 @@ _GLOBAL(hash_page)
/* Get PTE (linux-style) and check access */
lis r0,KERNELBASE@h /* check if kernel address */
cmplw 0,r4,r0
- mfspr r8,SPRG3 /* current task's THREAD (phys) */
+ mfspr r8,SPRN_SPRG3 /* current task's THREAD (phys) */
ori r3,r3,_PAGE_USER|_PAGE_PRESENT /* test low addresses as user */
lwz r5,PGDIR(r8) /* virt page-table root */
blt+ 112f /* assume user more likely */
diff --git a/arch/ppc/mm/init.c b/arch/ppc/mm/init.c
index 6e31db0fe4b46..be02a7fec2b73 100644
--- a/arch/ppc/mm/init.c
+++ b/arch/ppc/mm/init.c
@@ -490,18 +490,6 @@ void __init mem_init(void)
printk(KERN_INFO "AGP special page: 0x%08lx\n", agp_special_page);
#endif
- /* Make sure all our pagetable pages have page->mapping
- and page->index set correctly. */
- for (addr = KERNELBASE; addr != 0; addr += PGDIR_SIZE) {
- struct page *pg;
- pmd_t *pmd = pmd_offset(pgd_offset_k(addr), addr);
- if (pmd_present(*pmd)) {
- pg = pmd_page(*pmd);
- pg->mapping = (void *) &init_mm;
- pg->index = addr;
- }
- }
-
mem_init_done = 1;
}
@@ -653,3 +641,27 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long address,
}
#endif
}
+
+/*
+ * This is called by /dev/mem to know if a given address has to
+ * be mapped non-cacheable or not
+ */
+int page_is_ram(unsigned long pfn)
+{
+ unsigned long paddr = (pfn << PAGE_SHIFT);
+
+ return paddr < __pa(high_memory);
+}
+
+pgprot_t phys_mem_access_prot(struct file *file, unsigned long addr,
+ unsigned long size, pgprot_t vma_prot)
+{
+ if (ppc_md.phys_mem_access_prot)
+ return ppc_md.phys_mem_access_prot(file, addr, size, vma_prot);
+
+ if (!page_is_ram(addr >> PAGE_SHIFT))
+ vma_prot = __pgprot(pgprot_val(vma_prot)
+ | _PAGE_GUARDED | _PAGE_NO_CACHE);
+ return vma_prot;
+}
+EXPORT_SYMBOL(phys_mem_access_prot);
diff --git a/arch/ppc/mm/mmu_decl.h b/arch/ppc/mm/mmu_decl.h
index 4699d6f640059..ffcdb46997dc3 100644
--- a/arch/ppc/mm/mmu_decl.h
+++ b/arch/ppc/mm/mmu_decl.h
@@ -75,7 +75,7 @@ static inline void flush_HPTE(unsigned context, unsigned long va,
unsigned long pdval)
{
if ((Hash != 0) &&
- (cur_cpu_spec[0]->cpu_features & CPU_FTR_HPTE_TABLE))
+ cpu_has_feature(CPU_FTR_HPTE_TABLE))
flush_hash_pages(0, va, pdval, 1);
else
_tlbie(va);
diff --git a/arch/ppc/mm/pgtable.c b/arch/ppc/mm/pgtable.c
index b5316b479228b..0a5cd20275c46 100644
--- a/arch/ppc/mm/pgtable.c
+++ b/arch/ppc/mm/pgtable.c
@@ -102,11 +102,6 @@ pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
if (mem_init_done) {
pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
- if (pte) {
- struct page *ptepage = virt_to_page(pte);
- ptepage->mapping = (void *) mm;
- ptepage->index = address & PMD_MASK;
- }
} else {
pte = (pte_t *)early_get_page();
if (pte)
@@ -126,11 +121,8 @@ struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
#endif
ptepage = alloc_pages(flags, 0);
- if (ptepage) {
- ptepage->mapping = (void *) mm;
- ptepage->index = address & PMD_MASK;
+ if (ptepage)
clear_highpage(ptepage);
- }
return ptepage;
}
@@ -139,7 +131,6 @@ void pte_free_kernel(pte_t *pte)
#ifdef CONFIG_SMP
hash_page_sync();
#endif
- virt_to_page(pte)->mapping = NULL;
free_page((unsigned long)pte);
}
@@ -148,7 +139,6 @@ void pte_free(struct page *ptepage)
#ifdef CONFIG_SMP
hash_page_sync();
#endif
- ptepage->mapping = NULL;
__free_page(ptepage);
}
@@ -298,7 +288,7 @@ map_page(unsigned long va, phys_addr_t pa, int flags)
pg = pte_alloc_kernel(&init_mm, pd, va);
if (pg != 0) {
err = 0;
- set_pte(pg, pfn_pte(pa >> PAGE_SHIFT, __pgprot(flags)));
+ set_pte_at(&init_mm, va, pg, pfn_pte(pa >> PAGE_SHIFT, __pgprot(flags)));
if (mem_init_done)
flush_HPTE(0, va, pmd_val(*pd));
}
diff --git a/arch/ppc/mm/ppc_mmu.c b/arch/ppc/mm/ppc_mmu.c
index 4fa5bf16fa1da..9a381ed5eb21a 100644
--- a/arch/ppc/mm/ppc_mmu.c
+++ b/arch/ppc/mm/ppc_mmu.c
@@ -138,11 +138,11 @@ void __init setbat(int index, unsigned long virt, unsigned long phys,
union ubat *bat = BATS[index];
if (((flags & _PAGE_NO_CACHE) == 0) &&
- (cur_cpu_spec[0]->cpu_features & CPU_FTR_NEED_COHERENT))
+ cpu_has_feature(CPU_FTR_NEED_COHERENT))
flags |= _PAGE_COHERENT;
bl = (size >> 17) - 1;
- if (PVR_VER(mfspr(PVR)) != 1) {
+ if (PVR_VER(mfspr(SPRN_PVR)) != 1) {
/* 603, 604, etc. */
/* Do DBAT first */
wimgxpp = flags & (_PAGE_WRITETHRU | _PAGE_NO_CACHE
@@ -191,7 +191,7 @@ void __init MMU_init_hw(void)
extern unsigned int hash_page[];
extern unsigned int flush_hash_patch_A[], flush_hash_patch_B[];
- if ((cur_cpu_spec[0]->cpu_features & CPU_FTR_HPTE_TABLE) == 0) {
+ if (!cpu_has_feature(CPU_FTR_HPTE_TABLE)) {
/*
* Put a blr (procedure return) instruction at the
* start of hash_page, since we can still get DSI
diff --git a/arch/ppc/mm/tlb.c b/arch/ppc/mm/tlb.c
index bedc1048e9a60..6c3dc3c44c86d 100644
--- a/arch/ppc/mm/tlb.c
+++ b/arch/ppc/mm/tlb.c
@@ -47,26 +47,6 @@ void flush_hash_entry(struct mm_struct *mm, pte_t *ptep, unsigned long addr)
}
/*
- * Called by ptep_test_and_clear_young()
- */
-void flush_hash_one_pte(pte_t *ptep)
-{
- struct page *ptepage;
- struct mm_struct *mm;
- unsigned long ptephys;
- unsigned long addr;
-
- if (Hash == 0)
- return;
-
- ptepage = virt_to_page(ptep);
- mm = (struct mm_struct *) ptepage->mapping;
- ptephys = __pa(ptep) & PAGE_MASK;
- addr = ptepage->index + (((unsigned long)ptep & ~PAGE_MASK) << 10);
- flush_hash_pages(mm->context, addr, ptephys, 1);
-}
-
-/*
* Called by ptep_set_access_flags, must flush on CPUs for which the
* DSI handler can't just "fixup" the TLB on a write fault
*/
diff --git a/arch/ppc/oprofile/op_model_fsl_booke.c b/arch/ppc/oprofile/op_model_fsl_booke.c
index 2048d0a2ac8f3..fc9c859358c64 100644
--- a/arch/ppc/oprofile/op_model_fsl_booke.c
+++ b/arch/ppc/oprofile/op_model_fsl_booke.c
@@ -150,7 +150,6 @@ static void fsl_booke_handle_interrupt(struct pt_regs *regs,
int is_kernel;
int val;
int i;
- unsigned int cpu = smp_processor_id();
/* set the PMM bit (see comment below) */
mtmsr(mfmsr() | MSR_PMM);
@@ -162,7 +161,7 @@ static void fsl_booke_handle_interrupt(struct pt_regs *regs,
val = ctr_read(i);
if (val < 0) {
if (oprofile_running && ctr[i].enabled) {
- oprofile_add_sample(pc, is_kernel, i, cpu);
+ oprofile_add_pc(pc, is_kernel, i);
ctr_write(i, reset_value[i]);
} else {
ctr_write(i, 0);
diff --git a/arch/ppc/platforms/4xx/ebony.c b/arch/ppc/platforms/4xx/ebony.c
index 86ef9bba20a2f..f63bca83e757c 100644
--- a/arch/ppc/platforms/4xx/ebony.c
+++ b/arch/ppc/platforms/4xx/ebony.c
@@ -49,8 +49,19 @@
#include <asm/todc.h>
#include <asm/bootinfo.h>
#include <asm/ppc4xx_pic.h>
+#include <asm/ppcboot.h>
#include <syslib/gen550.h>
+#include <syslib/ibm440gp_common.h>
+
+/*
+ * This is a horrible kludge, we eventually need to abstract this
+ * generic PHY stuff, so the standard phy mode defines can be
+ * easily used from arch code.
+ */
+#include "../../../../drivers/net/ibm_emac/ibm_emac_phy.h"
+
+bd_t __res;
static struct ibm44x_clocks clocks __initdata;
@@ -86,7 +97,7 @@ ebony_calibrate_decr(void)
* on Rev. C silicon then errata forces us to
* use the internal clock.
*/
- switch (PVR_REV(mfspr(PVR))) {
+ switch (PVR_REV(mfspr(SPRN_PVR))) {
case PVR_REV(PVR_440GP_RB):
freq = EBONY_440GP_RB_SYSCLK;
break;
@@ -258,19 +269,21 @@ ebony_early_serial_map(void)
static void __init
ebony_setup_arch(void)
{
- unsigned char * vpd_base;
struct ocp_def *def;
struct ocp_func_emac_data *emacdata;
/* Set mac_addr for each EMAC */
- vpd_base = ioremap64(EBONY_VPD_BASE, EBONY_VPD_SIZE);
def = ocp_get_one_device(OCP_VENDOR_IBM, OCP_FUNC_EMAC, 0);
emacdata = def->additions;
- memcpy(emacdata->mac_addr, EBONY_NA0_ADDR(vpd_base), 6);
+ emacdata->phy_map = 0x00000001; /* Skip 0x00 */
+ emacdata->phy_mode = PHY_MODE_RMII;
+ memcpy(emacdata->mac_addr, __res.bi_enetaddr, 6);
+
def = ocp_get_one_device(OCP_VENDOR_IBM, OCP_FUNC_EMAC, 1);
emacdata = def->additions;
- memcpy(emacdata->mac_addr, EBONY_NA1_ADDR(vpd_base), 6);
- iounmap(vpd_base);
+ emacdata->phy_map = 0x00000001; /* Skip 0x00 */
+ emacdata->phy_mode = PHY_MODE_RMII;
+ memcpy(emacdata->mac_addr, __res.bi_enet1addr, 6);
/*
* Determine various clocks.
@@ -314,7 +327,14 @@ ebony_setup_arch(void)
void __init platform_init(unsigned long r3, unsigned long r4,
unsigned long r5, unsigned long r6, unsigned long r7)
{
- parse_bootinfo((struct bi_record *) (r3 + KERNELBASE));
+ parse_bootinfo(find_bootinfo());
+
+ /*
+ * If we were passed in a board information, copy it into the
+ * residual data area.
+ */
+ if (r3)
+ __res = *(bd_t *)(r3 + KERNELBASE);
ibm44x_platform_init();
diff --git a/arch/ppc/platforms/4xx/ebony.h b/arch/ppc/platforms/4xx/ebony.h
index f90ddf309e201..47c391c9174d1 100644
--- a/arch/ppc/platforms/4xx/ebony.h
+++ b/arch/ppc/platforms/4xx/ebony.h
@@ -23,13 +23,9 @@
/* F/W TLB mapping used in bootloader glue to reset EMAC */
#define PPC44x_EMAC0_MR0 0xE0000800
-/* Macros to get at Ebony VPD info */
-#define EBONY_VPD_BASE 0x00000001fffffe00ULL
-#define EBONY_VPD_SIZE 0x24
-#define EBONY_NA0_OFFSET 0x0c
-#define EBONY_NA1_OFFSET 0x18
-#define EBONY_NA0_ADDR(base) (base + EBONY_NA0_OFFSET)
-#define EBONY_NA1_ADDR(base) (base + EBONY_NA1_OFFSET)
+/* Where to find the MAC info */
+#define EBONY_OPENBIOS_MAC_BASE 0xfffffe0c
+#define EBONY_OPENBIOS_MAC_OFFSET 0x0c
/* Default clock rates for Rev. B and Rev. C silicon */
#define EBONY_440GP_RB_SYSCLK 33000000
@@ -61,8 +57,8 @@
*/
/* OpenBIOS defined UART mappings, used before early_serial_setup */
-#define UART0_IO_BASE (u8 *) 0xE0000200
-#define UART1_IO_BASE (u8 *) 0xE0000300
+#define UART0_IO_BASE 0xE0000200
+#define UART1_IO_BASE 0xE0000300
/* external Epson SG-615P */
#define BASE_BAUD 691200
diff --git a/arch/ppc/platforms/4xx/luan.h b/arch/ppc/platforms/4xx/luan.h
index 107b952885f8d..09b444c878163 100644
--- a/arch/ppc/platforms/4xx/luan.h
+++ b/arch/ppc/platforms/4xx/luan.h
@@ -47,9 +47,9 @@
#define RS_TABLE_SIZE 3
/* PIBS defined UART mappings, used before early_serial_setup */
-#define UART0_IO_BASE (u8 *) 0xa0000200
-#define UART1_IO_BASE (u8 *) 0xa0000300
-#define UART2_IO_BASE (u8 *) 0xa0000600
+#define UART0_IO_BASE 0xa0000200
+#define UART1_IO_BASE 0xa0000300
+#define UART2_IO_BASE 0xa0000600
#define BASE_BAUD 11059200
#define STD_UART_OP(num) \
diff --git a/arch/ppc/platforms/4xx/ocotea.h b/arch/ppc/platforms/4xx/ocotea.h
index b49739a1745b5..202dc82511908 100644
--- a/arch/ppc/platforms/4xx/ocotea.h
+++ b/arch/ppc/platforms/4xx/ocotea.h
@@ -56,8 +56,8 @@
#define RS_TABLE_SIZE 2
/* OpenBIOS defined UART mappings, used before early_serial_setup */
-#define UART0_IO_BASE (u8 *) 0xE0000200
-#define UART1_IO_BASE (u8 *) 0xE0000300
+#define UART0_IO_BASE 0xE0000200
+#define UART1_IO_BASE 0xE0000300
#define BASE_BAUD 11059200/16
#define STD_UART_OP(num) \
diff --git a/arch/ppc/platforms/4xx/xilinx_ml300.c b/arch/ppc/platforms/4xx/xilinx_ml300.c
index d07fe022e20bf..0b1b77d986bfd 100644
--- a/arch/ppc/platforms/4xx/xilinx_ml300.c
+++ b/arch/ppc/platforms/4xx/xilinx_ml300.c
@@ -122,25 +122,7 @@ ml300_setup_arch(void)
void __init
ml300_init_irq(void)
{
- unsigned int i;
-
ppc4xx_init_IRQ();
-
- /*
- * For PowerPC 405 cores the default value for NR_IRQS is 32.
- * See include/asm-ppc/irq.h for details.
- * This is just fine for ML300.
- */
-#if (NR_IRQS != 32)
-#error NR_IRQS must be 32 for ML300
-#endif
-
- for (i = 0; i < NR_IRQS; i++) {
- if (XPAR_INTC_0_KIND_OF_INTR & (0x80000000 >> i))
- irq_desc[i].status &= ~IRQ_LEVEL;
- else
- irq_desc[i].status |= IRQ_LEVEL;
- }
}
void __init
diff --git a/arch/ppc/platforms/83xx/Makefile b/arch/ppc/platforms/83xx/Makefile
new file mode 100644
index 0000000000000..eb55341d6a174
--- /dev/null
+++ b/arch/ppc/platforms/83xx/Makefile
@@ -0,0 +1,4 @@
+#
+# Makefile for the PowerPC 83xx linux kernel.
+#
+obj-$(CONFIG_MPC834x_SYS) += mpc834x_sys.o
diff --git a/arch/ppc/platforms/83xx/mpc834x_sys.c b/arch/ppc/platforms/83xx/mpc834x_sys.c
new file mode 100644
index 0000000000000..b3b0f51979d2b
--- /dev/null
+++ b/arch/ppc/platforms/83xx/mpc834x_sys.c
@@ -0,0 +1,289 @@
+/*
+ * arch/ppc/platforms/83xx/mpc834x_sys.c
+ *
+ * MPC834x SYS board specific routines
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2005 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/config.h>
+#include <linux/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/irq.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+#include <linux/serial.h>
+#include <linux/tty.h> /* for linux/serial_core.h */
+#include <linux/serial_core.h>
+#include <linux/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/prom.h>
+#include <asm/ipic.h>
+#include <asm/bootinfo.h>
+#include <asm/pci-bridge.h>
+#include <asm/mpc83xx.h>
+#include <asm/irq.h>
+#include <asm/kgdb.h>
+#include <asm/ppc_sys.h>
+#include <mm/mmu_decl.h>
+
+#include <syslib/ppc83xx_setup.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)];
+
+#ifdef CONFIG_PCI
+#error "PCI is not supported"
+/* NEED mpc83xx_map_irq & mpc83xx_exclude_device
+ see platforms/85xx/mpc85xx_ads_common.c */
+#endif /* CONFIG_PCI */
+
+/* ************************************************************************
+ *
+ * Setup the architecture
+ *
+ */
+static void __init
+mpc834x_sys_setup_arch(void)
+{
+ bd_t *binfo = (bd_t *) __res;
+ unsigned int freq;
+ struct gianfar_platform_data *pdata;
+
+ /* get the core frequency */
+ freq = binfo->bi_intfreq;
+
+ /* 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 */
+ mpc83xx_sys_setup_hose();
+#endif
+ mpc83xx_early_serial_map();
+
+ /* setup the board related information for the enet controllers */
+ pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC83xx_TSEC1);
+ pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
+ pdata->interruptPHY = MPC83xx_IRQ_EXT1;
+ pdata->phyid = 0;
+ /* fixup phy address */
+ pdata->phy_reg_addr += binfo->bi_immr_base;
+ memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
+
+ pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC83xx_TSEC2);
+ pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
+ pdata->interruptPHY = MPC83xx_IRQ_EXT2;
+ pdata->phyid = 1;
+ /* fixup phy address */
+ pdata->phy_reg_addr += binfo->bi_immr_base;
+ memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
+
+#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
+}
+
+static void __init
+mpc834x_sys_map_io(void)
+{
+ /* we steal the lowest ioremap addr for virt space */
+ io_block_mapping(VIRT_IMMRBAR, immrbar, 1024*1024, _PAGE_IO);
+ io_block_mapping(BCSR_VIRT_ADDR, BCSR_PHYS_ADDR, BCSR_SIZE, _PAGE_IO);
+}
+
+int
+mpc834x_sys_show_cpuinfo(struct seq_file *m)
+{
+ uint pvid, svid, phid1;
+ 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: Freescale Inc.\n");
+ seq_printf(m, "Machine\t\t: mpc%s sys\n", cur_ppc_sys_spec->ppc_sys_name);
+ seq_printf(m, "core clock\t: %d MHz\n"
+ "bus clock\t: %d MHz\n",
+ (int)(binfo->bi_intfreq / 1000000),
+ (int)(binfo->bi_busfreq / 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", (int)(binfo->bi_memsize / (1024 * 1024)));
+
+ return 0;
+}
+
+
+void __init
+mpc834x_sys_init_IRQ(void)
+{
+ bd_t *binfo = (bd_t *) __res;
+
+ u8 senses[8] = {
+ 0, /* EXT 0 */
+ IRQ_SENSE_LEVEL, /* EXT 1 */
+ IRQ_SENSE_LEVEL, /* EXT 2 */
+ 0, /* EXT 3 */
+ 0, /* EXT 4 */
+ 0, /* EXT 5 */
+ 0, /* EXT 6 */
+ 0, /* EXT 7 */
+ };
+
+ ipic_init(binfo->bi_immr_base + 0x00700, 0, MPC83xx_IPIC_IRQ_OFFSET, senses, 8);
+
+ /* Initialize the default interrupt mapping priorities,
+ * in case the boot rom changed something on us.
+ */
+ ipic_set_default_priority();
+}
+
+static __inline__ void
+mpc834x_sys_set_bat(void)
+{
+ /* we steal the lowest ioremap addr for virt space */
+ mb();
+ mtspr(SPRN_DBAT1U, VIRT_IMMRBAR | 0x1e);
+ mtspr(SPRN_DBAT1L, immrbar | 0x2a);
+ mb();
+}
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7)
+{
+ bd_t *binfo = (bd_t *) __res;
+
+ /* 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_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));
+ }
+
+ immrbar = binfo->bi_immr_base;
+
+ mpc834x_sys_set_bat();
+
+#if defined(CONFIG_SERIAL_8250) && defined(CONFIG_SERIAL_TEXT_DEBUG)
+ {
+ struct uart_port p;
+
+ memset(&p, 0, sizeof (p));
+ p.iotype = SERIAL_IO_MEM;
+ p.membase = (unsigned char __iomem *)(VIRT_IMMRBAR + 0x4500);
+ p.uartclk = binfo->bi_busfreq;
+
+ gen550_init(0, &p);
+
+ memset(&p, 0, sizeof (p));
+ p.iotype = SERIAL_IO_MEM;
+ p.membase = (unsigned char __iomem *)(VIRT_IMMRBAR + 0x4600);
+ p.uartclk = binfo->bi_busfreq;
+
+ gen550_init(1, &p);
+ }
+#endif
+
+ identify_ppc_sys_by_id(mfspr(SPRN_SVR));
+
+ /* setup the PowerPC module struct */
+ ppc_md.setup_arch = mpc834x_sys_setup_arch;
+ ppc_md.show_cpuinfo = mpc834x_sys_show_cpuinfo;
+
+ ppc_md.init_IRQ = mpc834x_sys_init_IRQ;
+ ppc_md.get_irq = ipic_get_irq;
+
+ ppc_md.restart = mpc83xx_restart;
+ ppc_md.power_off = mpc83xx_power_off;
+ ppc_md.halt = mpc83xx_halt;
+
+ ppc_md.find_end_of_memory = mpc83xx_find_end_of_memory;
+ ppc_md.setup_io_mappings = mpc834x_sys_map_io;
+
+ ppc_md.time_init = mpc83xx_time_init;
+ ppc_md.set_rtc_time = NULL;
+ ppc_md.get_rtc_time = NULL;
+ ppc_md.calibrate_decr = mpc83xx_calibrate_decr;
+
+ ppc_md.early_serial_map = mpc83xx_early_serial_map;
+#if defined(CONFIG_SERIAL_8250) && defined(CONFIG_SERIAL_TEXT_DEBUG)
+ ppc_md.progress = gen550_progress;
+#endif /* CONFIG_SERIAL_8250 && CONFIG_SERIAL_TEXT_DEBUG */
+
+ if (ppc_md.progress)
+ ppc_md.progress("mpc834x_sys_init(): exit", 0);
+
+ return;
+}
diff --git a/arch/ppc/platforms/83xx/mpc834x_sys.h b/arch/ppc/platforms/83xx/mpc834x_sys.h
new file mode 100644
index 0000000000000..f4d055ae19c14
--- /dev/null
+++ b/arch/ppc/platforms/83xx/mpc834x_sys.h
@@ -0,0 +1,51 @@
+/*
+ * arch/ppc/platforms/83xx/mpc834x_sys.h
+ *
+ * MPC834X SYS common board definitions
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2005 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+#ifndef __MACH_MPC83XX_SYS_H__
+#define __MACH_MPC83XX_SYS_H__
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/seq_file.h>
+#include <syslib/ppc83xx_setup.h>
+#include <asm/ppcboot.h>
+
+#define VIRT_IMMRBAR ((uint)0xfe000000)
+
+#define BCSR_PHYS_ADDR ((uint)0xf8000000)
+#define BCSR_VIRT_ADDR ((uint)0xfe100000)
+#define BCSR_SIZE ((uint)(32 * 1024))
+
+#ifdef CONFIG_PCI
+/* PCI interrupt controller */
+#define PIRQA MPC83xx_IRQ_IRQ4
+#define PIRQB MPC83xx_IRQ_IRQ5
+#define PIRQC MPC83xx_IRQ_IRQ6
+#define PIRQD MPC83xx_IRQ_IRQ7
+
+#define MPC834x_SYS_PCI1_LOWER_IO 0x00000000
+#define MPC834x_SYS_PCI1_UPPER_IO 0x00ffffff
+
+#define MPC834x_SYS_PCI1_LOWER_MEM 0x80000000
+#define MPC834x_SYS_PCI1_UPPER_MEM 0x9fffffff
+
+#define MPC834x_SYS_PCI1_IO_BASE 0xe2000000
+#define MPC834x_SYS_PCI1_MEM_OFFSET 0x00000000
+
+#define MPC834x_SYS_PCI1_IO_SIZE 0x01000000
+#endif /* CONFIG_PCI */
+
+#endif /* __MACH_MPC83XX_SYS_H__ */
diff --git a/arch/ppc/platforms/85xx/Makefile b/arch/ppc/platforms/85xx/Makefile
index b5161e38652fd..854fbd298ba2a 100644
--- a/arch/ppc/platforms/85xx/Makefile
+++ b/arch/ppc/platforms/85xx/Makefile
@@ -1,8 +1,6 @@
#
# Makefile for the PowerPC 85xx linux kernel.
#
-obj-$(CONFIG_85xx) += mpc85xx_sys.o mpc85xx_devices.o
-
obj-$(CONFIG_MPC8540_ADS) += mpc85xx_ads_common.o mpc8540_ads.o
obj-$(CONFIG_MPC8555_CDS) += mpc85xx_cds_common.o
obj-$(CONFIG_MPC8560_ADS) += mpc85xx_ads_common.o mpc8560_ads.o
diff --git a/arch/ppc/platforms/85xx/mpc8540_ads.c b/arch/ppc/platforms/85xx/mpc8540_ads.c
index fca01e6bc4d0c..4d857d6d633d7 100644
--- a/arch/ppc/platforms/85xx/mpc8540_ads.c
+++ b/arch/ppc/platforms/85xx/mpc8540_ads.c
@@ -109,7 +109,7 @@ mpc8540ads_setup_arch(void)
memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_FEC);
- pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
+ pdata->board_flags = 0;
pdata->interruptPHY = MPC85xx_IRQ_EXT5;
pdata->phyid = 3;
/* fixup phy address */
@@ -187,7 +187,7 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
strcpy(cmd_line, (char *) (r6 + KERNELBASE));
}
- identify_ppc_sys_by_id(mfspr(SVR));
+ identify_ppc_sys_by_id(mfspr(SPRN_SVR));
/* setup the PowerPC module struct */
ppc_md.setup_arch = mpc8540ads_setup_arch;
diff --git a/arch/ppc/platforms/85xx/mpc8560_ads.c b/arch/ppc/platforms/85xx/mpc8560_ads.c
index 16c8c7b5d1b99..761b8c7b25d27 100644
--- a/arch/ppc/platforms/85xx/mpc8560_ads.c
+++ b/arch/ppc/platforms/85xx/mpc8560_ads.c
@@ -135,25 +135,11 @@ static struct irqaction cpm2_irqaction = {
static void __init
mpc8560_ads_init_IRQ(void)
{
- int i;
- volatile cpm2_map_t *immap = cpm2_immr;
-
/* Setup OpenPIC */
mpc85xx_ads_init_IRQ();
- /* disable all CPM interupts */
- immap->im_intctl.ic_simrh = 0x0;
- immap->im_intctl.ic_simrl = 0x0;
-
- for (i = CPM_IRQ_OFFSET; i < (NR_CPM_INTS + CPM_IRQ_OFFSET); i++)
- irq_desc[i].handler = &cpm2_pic;
-
- /* Initialize the default interrupt mapping priorities,
- * in case the boot rom changed something on us.
- */
- immap->im_intctl.ic_sicr = 0;
- immap->im_intctl.ic_scprrh = 0x05309770;
- immap->im_intctl.ic_scprrl = 0x05309770;
+ /* Setup CPM2 PIC */
+ cpm2_init_IRQ();
setup_irq(MPC85xx_IRQ_CPM, &cpm2_irqaction);
@@ -197,7 +183,7 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
strcpy(cmd_line, (char *) (r6 + KERNELBASE));
}
- identify_ppc_sys_by_id(mfspr(SVR));
+ identify_ppc_sys_by_id(mfspr(SPRN_SVR));
/* setup the PowerPC module struct */
ppc_md.setup_arch = mpc8560ads_setup_arch;
diff --git a/arch/ppc/platforms/85xx/mpc85xx_ads_common.c b/arch/ppc/platforms/85xx/mpc85xx_ads_common.c
index cf5bcd94d027f..ba9f9f562c458 100644
--- a/arch/ppc/platforms/85xx/mpc85xx_ads_common.c
+++ b/arch/ppc/platforms/85xx/mpc85xx_ads_common.c
@@ -43,6 +43,7 @@
#include <asm/mpc85xx.h>
#include <asm/irq.h>
#include <asm/immap_85xx.h>
+#include <asm/ppc_sys.h>
#include <mm/mmu_decl.h>
@@ -125,28 +126,17 @@ mpc85xx_ads_show_cpuinfo(struct seq_file *m)
/* get the core frequency */
freq = binfo->bi_intfreq;
- pvid = mfspr(PVR);
- svid = mfspr(SVR);
+ pvid = mfspr(SPRN_PVR);
+ svid = mfspr(SPRN_SVR);
seq_printf(m, "Vendor\t\t: Freescale Semiconductor\n");
-
- switch (svid & 0xffff0000) {
- case SVR_8540:
- seq_printf(m, "Machine\t\t: mpc8540ads\n");
- break;
- case SVR_8560:
- seq_printf(m, "Machine\t\t: mpc8560ads\n");
- break;
- default:
- seq_printf(m, "Machine\t\t: unknown\n");
- break;
- }
+ seq_printf(m, "Machine\t\t: mpc%sads\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(HID1);
+ phid1 = mfspr(SPRN_HID1);
seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f));
/* Display the amount of memory */
diff --git a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c
index a65eb0225d564..6c020d67ad704 100644
--- a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c
+++ b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c
@@ -39,6 +39,7 @@
#include <asm/page.h>
#include <asm/atomic.h>
#include <asm/time.h>
+#include <asm/todc.h>
#include <asm/io.h>
#include <asm/machdep.h>
#include <asm/prom.h>
@@ -73,60 +74,60 @@ static volatile u8 * cadmus;
/* Internal interrupts are all Level Sensitive, and Positive Polarity */
static u_char mpc85xx_cds_openpic_initsenses[] __initdata = {
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 0: L2 Cache */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 1: ECM */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 2: DDR DRAM */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 3: LBIU */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 4: DMA 0 */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 5: DMA 1 */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 6: DMA 2 */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 7: DMA 3 */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 8: PCI/PCI-X */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 9: RIO Inbound Port Write Error */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 10: RIO Doorbell Inbound */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 11: RIO Outbound Message */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 12: RIO Inbound Message */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 13: TSEC 0 Transmit */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 14: TSEC 0 Receive */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 15: Unused */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 16: Unused */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 17: Unused */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 18: TSEC 0 Receive/Transmit Error */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 19: TSEC 1 Transmit */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 20: TSEC 1 Receive */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 21: Unused */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 22: Unused */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 23: Unused */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 24: TSEC 1 Receive/Transmit Error */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 25: Fast Ethernet */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 26: DUART */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 27: I2C */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 28: Performance Monitor */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 29: Unused */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 30: CPM */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 31: Unused */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 0: L2 Cache */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 1: ECM */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 2: DDR DRAM */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 3: LBIU */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 4: DMA 0 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 5: DMA 1 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 6: DMA 2 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 7: DMA 3 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 8: PCI/PCI-X */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 9: RIO Inbound Port Write Error */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 10: RIO Doorbell Inbound */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 11: RIO Outbound Message */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 12: RIO Inbound Message */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 13: TSEC 0 Transmit */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 14: TSEC 0 Receive */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 15: Unused */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 16: Unused */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 17: Unused */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 18: TSEC 0 Receive/Transmit Error */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 19: TSEC 1 Transmit */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 20: TSEC 1 Receive */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 21: Unused */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 22: Unused */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 23: Unused */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 24: TSEC 1 Receive/Transmit Error */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 25: Fast Ethernet */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 26: DUART */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 27: I2C */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 28: Performance Monitor */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 29: Unused */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 30: CPM */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 31: Unused */
#if defined(CONFIG_PCI)
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 0: PCI1 slot */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 1: PCI1 slot */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 2: PCI1 slot */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 3: PCI1 slot */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 0: PCI1 slot */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 1: PCI1 slot */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 2: PCI1 slot */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 3: PCI1 slot */
#else
- 0x0, /* External 0: */
- 0x0, /* External 1: */
- 0x0, /* External 2: */
- 0x0, /* External 3: */
+ 0x0, /* External 0: */
+ 0x0, /* External 1: */
+ 0x0, /* External 2: */
+ 0x0, /* External 3: */
#endif
- 0x0, /* External 4: */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 5: PHY */
- 0x0, /* External 6: */
- 0x0, /* External 7: */
- 0x0, /* External 8: */
- 0x0, /* External 9: */
- 0x0, /* External 10: */
+ 0x0, /* External 4: */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 5: PHY */
+ 0x0, /* External 6: */
+ 0x0, /* External 7: */
+ 0x0, /* External 8: */
+ 0x0, /* External 9: */
+ 0x0, /* External 10: */
#if defined(CONFIG_85xx_PCI2) && defined(CONFIG_PCI)
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 11: PCI2 slot 0 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 11: PCI2 slot 0 */
#else
- 0x0, /* External 11: */
+ 0x0, /* External 11: */
#endif
};
@@ -134,31 +135,31 @@ static u_char mpc85xx_cds_openpic_initsenses[] __initdata = {
int
mpc85xx_cds_show_cpuinfo(struct seq_file *m)
{
- uint pvid, svid, phid1;
- uint memsize = total_memory;
- bd_t *binfo = (bd_t *) __res;
- unsigned int freq;
+ 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;
+ /* get the core frequency */
+ freq = binfo->bi_intfreq;
- pvid = mfspr(PVR);
- svid = mfspr(SVR);
+ pvid = mfspr(SPRN_PVR);
+ svid = mfspr(SPRN_SVR);
- seq_printf(m, "Vendor\t\t: Freescale Semiconductor\n");
- seq_printf(m, "Machine\t\t: CDS (%x)\n", cadmus[CM_VER]);
+ seq_printf(m, "Vendor\t\t: Freescale Semiconductor\n");
+ seq_printf(m, "Machine\t\t: CDS - MPC%s (%x)\n", cur_ppc_sys_spec->ppc_sys_name, cadmus[CM_VER]);
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);
+ 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(HID1);
- seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f));
+ /* 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));
+ /* Display the amount of memory */
+ seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024));
- return 0;
+ return 0;
}
#ifdef CONFIG_CPM2
@@ -180,46 +181,31 @@ void __init
mpc85xx_cds_init_IRQ(void)
{
bd_t *binfo = (bd_t *) __res;
-#ifdef CONFIG_CPM2
- volatile cpm2_map_t *immap = cpm2_immr;
- int i;
-#endif
- /* 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 = mpc85xx_cds_openpic_initsenses;
- OpenPIC_NumInitSenses = sizeof (mpc85xx_cds_openpic_initsenses);
+ /* 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 = mpc85xx_cds_openpic_initsenses;
+ OpenPIC_NumInitSenses = sizeof (mpc85xx_cds_openpic_initsenses);
- /* Skip reserved space and internal sources */
- openpic_set_sources(0, 32, OpenPIC_Addr + 0x10200);
- /* Map PIC IRQs 0-11 */
- openpic_set_sources(32, 12, OpenPIC_Addr + 0x10000);
+ /* Skip reserved space and internal sources */
+ openpic_set_sources(0, 32, OpenPIC_Addr + 0x10200);
+ /* Map PIC IRQs 0-11 */
+ openpic_set_sources(32, 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);
+ /* we let openpic interrupts starting from an offset, to
+ * leave space for cascading interrupts underneath.
+ */
+ openpic_init(MPC85xx_OPENPIC_IRQ_OFFSET);
#ifdef CONFIG_CPM2
- /* disable all CPM interupts */
- immap->im_intctl.ic_simrh = 0x0;
- immap->im_intctl.ic_simrl = 0x0;
-
- for (i = CPM_IRQ_OFFSET; i < (NR_CPM_INTS + CPM_IRQ_OFFSET); i++)
- irq_desc[i].handler = &cpm2_pic;
-
- /* Initialize the default interrupt mapping priorities,
- * in case the boot rom changed something on us.
- */
- immap->im_intctl.ic_sicr = 0;
- immap->im_intctl.ic_scprrh = 0x05309770;
- immap->im_intctl.ic_scprrl = 0x05309770;
+ /* Setup CPM2 PIC */
+ cpm2_init_IRQ();
setup_irq(MPC85xx_IRQ_CPM, &cpm2_irqaction);
#endif
- return;
+ return;
}
#ifdef CONFIG_PCI
@@ -278,8 +264,8 @@ mpc85xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
}
}
-#define ARCADIA_HOST_BRIDGE_IDSEL 17
-#define ARCADIA_2ND_BRIDGE_IDSEL 3
+#define ARCADIA_HOST_BRIDGE_IDSEL 17
+#define ARCADIA_2ND_BRIDGE_IDSEL 3
extern int mpc85xx_pci1_last_busno;
@@ -289,7 +275,7 @@ mpc85xx_exclude_device(u_char bus, u_char devfn)
if (bus == 0 && PCI_SLOT(devfn) == 0)
return PCIBIOS_DEVICE_NOT_FOUND;
#ifdef CONFIG_85xx_PCI2
- if (mpc85xx_pci1_last_busno)
+ if (mpc85xx_pci1_last_busno)
if (bus == (mpc85xx_pci1_last_busno + 1) && PCI_SLOT(devfn) == 0)
return PCIBIOS_DEVICE_NOT_FOUND;
#endif
@@ -303,6 +289,8 @@ mpc85xx_exclude_device(u_char bus, u_char devfn)
}
#endif /* CONFIG_PCI */
+TODC_ALLOC();
+
/* ************************************************************************
*
* Setup the architecture
@@ -311,14 +299,14 @@ mpc85xx_exclude_device(u_char bus, u_char devfn)
static void __init
mpc85xx_cds_setup_arch(void)
{
- bd_t *binfo = (bd_t *) __res;
- unsigned int freq;
+ bd_t *binfo = (bd_t *) __res;
+ unsigned int freq;
struct gianfar_platform_data *pdata;
- /* get the core frequency */
- freq = binfo->bi_intfreq;
+ /* get the core frequency */
+ freq = binfo->bi_intfreq;
- printk("mpc85xx_cds_setup_arch\n");
+ printk("mpc85xx_cds_setup_arch\n");
#ifdef CONFIG_CPM2
cpm2_reset();
@@ -328,17 +316,24 @@ mpc85xx_cds_setup_arch(void)
cds_pci_slot = ((cadmus[CM_CSR] >> 6) & 0x3) + 1;
printk("CDS Version = %x in PCI slot %d\n", cadmus[CM_VER], cds_pci_slot);
- /* Set loops_per_jiffy to a half-way reasonable value,
- for use until calibrate_delay gets called. */
- loops_per_jiffy = freq / HZ;
+ /* Setup TODC access */
+ TODC_INIT(TODC_TYPE_DS1743,
+ 0,
+ 0,
+ ioremap(CDS_RTC_ADDR, CDS_RTC_SIZE),
+ 8);
+
+ /* 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();
+ /* setup PCI host bridges */
+ mpc85xx_setup_hose();
#endif
#ifdef CONFIG_SERIAL_8250
- mpc85xx_early_serial_map();
+ mpc85xx_early_serial_map();
#endif
#ifdef CONFIG_SERIAL_TEXT_DEBUG
@@ -366,14 +361,14 @@ mpc85xx_cds_setup_arch(void)
#ifdef CONFIG_BLK_DEV_INITRD
- if (initrd_start)
- ROOT_DEV = Root_RAM0;
- else
+ if (initrd_start)
+ ROOT_DEV = Root_RAM0;
+ else
#endif
#ifdef CONFIG_ROOT_NFS
- ROOT_DEV = Root_NFS;
+ ROOT_DEV = Root_NFS;
#else
- ROOT_DEV = Root_HDA1;
+ ROOT_DEV = Root_HDA1;
#endif
}
@@ -382,18 +377,18 @@ 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));
-
- }
+ /* 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));
+
+ }
#ifdef CONFIG_SERIAL_TEXT_DEBUG
{
bd_t *binfo = (bd_t *) __res;
@@ -401,7 +396,7 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
/* Use the last TLB entry to map CCSRBAR to allow access to DUART regs */
settlbcam(NUM_TLBCAMS - 1, binfo->bi_immr_base,
- binfo->bi_immr_base, MPC85xx_CCSRBAR_SIZE, _PAGE_IO, 0);
+ binfo->bi_immr_base, MPC85xx_CCSRBAR_SIZE, _PAGE_IO, 0);
memset(&p, 0, sizeof (p));
p.iotype = SERIAL_IO_MEM;
@@ -420,49 +415,53 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
#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 */
+ /*
+ * 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));
+ }
- /* Copy the kernel command line arguments to a safe place. */
+ identify_ppc_sys_by_id(mfspr(SPRN_SVR));
- if (r6) {
- *(char *) (r7 + KERNELBASE) = 0;
- strcpy(cmd_line, (char *) (r6 + KERNELBASE));
- }
+ /* setup the PowerPC module struct */
+ ppc_md.setup_arch = mpc85xx_cds_setup_arch;
+ ppc_md.show_cpuinfo = mpc85xx_cds_show_cpuinfo;
- identify_ppc_sys_by_id(mfspr(SVR));
+ ppc_md.init_IRQ = mpc85xx_cds_init_IRQ;
+ ppc_md.get_irq = openpic_get_irq;
- /* setup the PowerPC module struct */
- ppc_md.setup_arch = mpc85xx_cds_setup_arch;
- ppc_md.show_cpuinfo = mpc85xx_cds_show_cpuinfo;
+ ppc_md.restart = mpc85xx_restart;
+ ppc_md.power_off = mpc85xx_power_off;
+ ppc_md.halt = mpc85xx_halt;
- ppc_md.init_IRQ = mpc85xx_cds_init_IRQ;
- ppc_md.get_irq = openpic_get_irq;
+ ppc_md.find_end_of_memory = mpc85xx_find_end_of_memory;
- ppc_md.restart = mpc85xx_restart;
- ppc_md.power_off = mpc85xx_power_off;
- ppc_md.halt = mpc85xx_halt;
+ ppc_md.calibrate_decr = mpc85xx_calibrate_decr;
- ppc_md.find_end_of_memory = mpc85xx_find_end_of_memory;
+ ppc_md.time_init = todc_time_init;
+ ppc_md.set_rtc_time = todc_set_rtc_time;
+ ppc_md.get_rtc_time = todc_get_rtc_time;
- ppc_md.time_init = NULL;
- ppc_md.set_rtc_time = NULL;
- ppc_md.get_rtc_time = NULL;
- ppc_md.calibrate_decr = mpc85xx_calibrate_decr;
+ ppc_md.nvram_read_val = todc_direct_read_val;
+ ppc_md.nvram_write_val = todc_direct_write_val;
#if defined(CONFIG_SERIAL_8250) && defined(CONFIG_SERIAL_TEXT_DEBUG)
- ppc_md.progress = gen550_progress;
+ ppc_md.progress = gen550_progress;
#endif /* CONFIG_SERIAL_8250 && CONFIG_SERIAL_TEXT_DEBUG */
- if (ppc_md.progress)
- ppc_md.progress("mpc85xx_cds_init(): exit", 0);
+ if (ppc_md.progress)
+ ppc_md.progress("mpc85xx_cds_init(): exit", 0);
- return;
+ return;
}
diff --git a/arch/ppc/platforms/85xx/mpc85xx_cds_common.h b/arch/ppc/platforms/85xx/mpc85xx_cds_common.h
index 4d49a9791a745..7627d77504bd0 100644
--- a/arch/ppc/platforms/85xx/mpc85xx_cds_common.h
+++ b/arch/ppc/platforms/85xx/mpc85xx_cds_common.h
@@ -33,6 +33,10 @@
#define CM_CSR (1)
#define CM_RST (2)
+/* CDS NVRAM/RTC */
+#define CDS_RTC_ADDR (0xf8000000)
+#define CDS_RTC_SIZE (8 * 1024)
+
/* PCI config */
#define PCI1_CFG_ADDR_OFFSET (0x8000)
#define PCI1_CFG_DATA_OFFSET (0x8004)
diff --git a/arch/ppc/platforms/85xx/sbc8560.c b/arch/ppc/platforms/85xx/sbc8560.c
index 6a857b7474d9a..9ab05e590c3e0 100644
--- a/arch/ppc/platforms/85xx/sbc8560.c
+++ b/arch/ppc/platforms/85xx/sbc8560.c
@@ -198,7 +198,7 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
strcpy(cmd_line, (char *) (r6 + KERNELBASE));
}
- identify_ppc_sys_by_id(mfspr(SVR));
+ identify_ppc_sys_by_id(mfspr(SPRN_SVR));
/* setup the PowerPC module struct */
ppc_md.setup_arch = sbc8560_setup_arch;
diff --git a/arch/ppc/platforms/85xx/sbc85xx.c b/arch/ppc/platforms/85xx/sbc85xx.c
index ddcca0d27e952..2d638c1c1bd6f 100644
--- a/arch/ppc/platforms/85xx/sbc85xx.c
+++ b/arch/ppc/platforms/85xx/sbc85xx.c
@@ -42,6 +42,7 @@
#include <asm/mpc85xx.h>
#include <asm/irq.h>
#include <asm/immap_85xx.h>
+#include <asm/ppc_sys.h>
#include <mm/mmu_decl.h>
@@ -125,28 +126,17 @@ sbc8560_show_cpuinfo(struct seq_file *m)
/* get the core frequency */
freq = binfo->bi_intfreq;
- pvid = mfspr(PVR);
- svid = mfspr(SVR);
+ pvid = mfspr(SPRN_PVR);
+ svid = mfspr(SPRN_SVR);
seq_printf(m, "Vendor\t\t: Wind River\n");
-
- switch (svid & 0xffff0000) {
- case SVR_8540:
- seq_printf(m, "Machine\t\t: hhmmm, this board isn't made yet!\n");
- break;
- case SVR_8560:
- seq_printf(m, "Machine\t\t: SBC8560\n");
- break;
- default:
- seq_printf(m, "Machine\t\t: unknown\n");
- break;
- }
+ seq_printf(m, "Machine\t\t: SBC%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(HID1);
+ phid1 = mfspr(SPRN_HID1);
seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f));
/* Display the amount of memory */
diff --git a/arch/ppc/platforms/85xx/stx_gp3.c b/arch/ppc/platforms/85xx/stx_gp3.c
index 8b637e69bc9d8..bc95836e417c5 100644
--- a/arch/ppc/platforms/85xx/stx_gp3.c
+++ b/arch/ppc/platforms/85xx/stx_gp3.c
@@ -34,8 +34,10 @@
#include <linux/root_dev.h>
#include <linux/seq_file.h>
#include <linux/serial.h>
+#include <linux/initrd.h>
#include <linux/module.h>
#include <linux/fsl_devices.h>
+#include <linux/interrupt.h>
#include <asm/system.h>
#include <asm/pgtable.h>
@@ -199,7 +201,6 @@ static void __init
gp3_init_IRQ(void)
{
int i;
- volatile cpm2_map_t *immap = cpm2_immr;
bd_t *binfo = (bd_t *) __res;
/*
@@ -225,24 +226,8 @@ gp3_init_IRQ(void)
*/
openpic_init(MPC85xx_OPENPIC_IRQ_OFFSET);
- /*
- * Setup CPM2 PIC
- */
-
- /* disable all CPM interupts */
- immap->im_intctl.ic_simrh = 0x0;
- immap->im_intctl.ic_simrl = 0x0;
-
- for (i = CPM_IRQ_OFFSET; i < (NR_CPM_INTS + CPM_IRQ_OFFSET); i++)
- irq_desc[i].handler = &cpm2_pic;
-
- /*
- * Initialize the default interrupt mapping priorities,
- * in case the boot rom changed something on us.
- */
- immap->im_intctl.ic_sicr = 0;
- immap->im_intctl.ic_scprrh = 0x05309770;
- immap->im_intctl.ic_scprrl = 0x05309770;
+ /* Setup CPM2 PIC */
+ cpm2_init_IRQ();
setup_irq(MPC85xx_IRQ_CPM, &cpm2_irqaction);
@@ -261,31 +246,20 @@ gp3_show_cpuinfo(struct seq_file *m)
/* get the core frequency */
freq = binfo->bi_intfreq;
- pvid = mfspr(PVR);
- svid = mfspr(SVR);
+ pvid = mfspr(SPRN_PVR);
+ svid = mfspr(SPRN_SVR);
memsize = total_memory;
seq_printf(m, "Vendor\t\t: RPC Electronics STx \n");
-
- switch (svid & 0xffff0000) {
- case SVR_8540:
- seq_printf(m, "Machine\t\t: GP3 - MPC8540\n");
- break;
- case SVR_8560:
- seq_printf(m, "Machine\t\t: GP3 - MPC8560\n");
- break;
- default:
- seq_printf(m, "Machine\t\t: unknown\n");
- break;
- }
+ seq_printf(m, "Machine\t\t: GP3 - MPC%s\n", cur_ppc_sys_spec->ppc_sys_name);
seq_printf(m, "bus freq\t: %u.%.6u MHz\n", freq / 1000000,
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(HID1);
+ phid1 = mfspr(SPRN_HID1);
seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f));
/* Display the amount of memory */
@@ -357,7 +331,7 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
strcpy(cmd_line, (char *) (r6 + KERNELBASE));
}
- identify_ppc_sys_by_id(mfspr(SVR));
+ identify_ppc_sys_by_id(mfspr(SPRN_SVR));
/* setup the PowerPC module struct */
ppc_md.setup_arch = gp3_setup_arch;
diff --git a/arch/ppc/platforms/Makefile b/arch/ppc/platforms/Makefile
index 6ec8fe0b86815..5488a053f4155 100644
--- a/arch/ppc/platforms/Makefile
+++ b/arch/ppc/platforms/Makefile
@@ -12,7 +12,8 @@ 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
+obj-$(CONFIG_PPC_CHRP) += chrp_setup.o chrp_time.o chrp_pci.o \
+ chrp_pegasos_eth.o
obj-$(CONFIG_PPC_PREP) += prep_pci.o prep_setup.o
ifeq ($(CONFIG_PPC_PMAC),y)
obj-$(CONFIG_NVRAM) += pmac_nvram.o
@@ -30,6 +31,7 @@ obj-$(CONFIG_GEMINI) += gemini_pci.o gemini_setup.o gemini_prom.o
obj-$(CONFIG_K2) += k2.o
obj-$(CONFIG_LOPEC) += lopec.o
obj-$(CONFIG_KATANA) += katana.o
+obj-$(CONFIG_HDPU) += hdpu.o
obj-$(CONFIG_MCPN765) += mcpn765.o
obj-$(CONFIG_MENF1) += menf1_setup.o menf1_pci.o
obj-$(CONFIG_MVME5100) += mvme5100.o
@@ -39,10 +41,11 @@ obj-$(CONFIG_POWERPMC250) += powerpmc250.o
obj-$(CONFIG_PPLUS) += pplus.o
obj-$(CONFIG_PRPMC750) += prpmc750.o
obj-$(CONFIG_PRPMC800) += prpmc800.o
+obj-$(CONFIG_RADSTONE_PPC7D) += radstone_ppc7d.o
obj-$(CONFIG_SANDPOINT) += sandpoint.o
obj-$(CONFIG_SBC82xx) += sbc82xx.o
obj-$(CONFIG_SPRUCE) += spruce.o
-obj-$(CONFIG_LITE5200) += lite5200.o mpc5200.o
+obj-$(CONFIG_LITE5200) += lite5200.o
ifeq ($(CONFIG_SMP),y)
obj-$(CONFIG_PPC_PMAC) += pmac_smp.o
diff --git a/arch/ppc/platforms/adir_setup.c b/arch/ppc/platforms/adir_setup.c
index 0b4c98648b361..6a6754ee06171 100644
--- a/arch/ppc/platforms/adir_setup.c
+++ b/arch/ppc/platforms/adir_setup.c
@@ -60,7 +60,7 @@ adir_get_cpu_speed(void)
unsigned long hid1;
int cpu_speed;
- hid1 = mfspr(HID1) >> 28;
+ hid1 = mfspr(SPRN_HID1) >> 28;
hid1 = cpu_750cx[hid1];
@@ -126,7 +126,7 @@ adir_setup_arch(void)
printk("SBS Adirondack port (C) 2001 SBS Technologies, Inc.\n");
/* Identify the CPU manufacturer */
- cpu = mfspr(PVR);
+ cpu = mfspr(SPRN_PVR);
printk("CPU manufacturer: IBM [rev=%04x]\n", (cpu & 0xffff));
}
diff --git a/arch/ppc/platforms/chestnut.c b/arch/ppc/platforms/chestnut.c
index 502291e4c3150..7786818bd9d03 100644
--- a/arch/ppc/platforms/chestnut.c
+++ b/arch/ppc/platforms/chestnut.c
@@ -28,6 +28,7 @@
#include <linux/ide.h>
#include <linux/serial.h>
#include <linux/serial_core.h>
+#include <linux/mtd/physmap.h>
#include <asm/system.h>
#include <asm/pgtable.h>
#include <asm/page.h>
@@ -42,8 +43,8 @@
#include <asm/mv64x60.h>
#include <platforms/chestnut.h>
-static u32 boot_base; /* Virtual addr of 8bit boot */
-static u32 cpld_base; /* Virtual addr of CPLD Regs */
+static void __iomem *sram_base; /* Virtual addr of Internal SRAM */
+static void __iomem *cpld_base; /* Virtual addr of CPLD Regs */
static mv64x60_handle_t bh;
@@ -65,7 +66,8 @@ extern void mv64360_pcibios_fixup(mv64x60_handle_t *bh);
*
****/
static void __init
-chestnut_calibrate_decr(void){
+chestnut_calibrate_decr(void)
+{
ulong freq;
freq = CHESTNUT_BUS_SPEED / 4;
@@ -75,8 +77,6 @@ chestnut_calibrate_decr(void){
tb_ticks_per_jiffy = freq / HZ;
tb_to_us = mulhwu_scale_factor(freq, 1000000);
-
- return;
}
static int
@@ -103,7 +103,7 @@ chestnut_find_end_of_memory(void)
mem_size = mv64x60_get_mem_size(CONFIG_MV64X60_NEW_BASE,
MV64x60_TYPE_MV64460);
}
- return(mem_size);
+ return mem_size;
}
#if defined(CONFIG_SERIAL_8250)
@@ -155,7 +155,7 @@ chestnut_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
};
const long min_idsel = 1, max_idsel = 4, irqs_per_slot = 4;
- return (PCI_IRQ_TABLE_LOOKUP);
+ return PCI_IRQ_TABLE_LOOKUP;
}
@@ -193,24 +193,30 @@ chestnut_setup_bridge(void)
si.pci_0.pci_cmd_bits = 0;
si.pci_0.latency_timer = 0x80;
- si.window_preserve_mask_32_lo = CHESTNUT_PRESERVE_MASK;
-
for (i=0; i<MV64x60_CPU2MEM_WINDOWS; i++) {
+#if defined(CONFIG_NOT_COHERENT_CACHE)
si.cpu_prot_options[i] = 0;
-#ifdef CONFIG_NOT_CACHE_COHERENT
- si.cpu_snoop_options[i] = MV64360_CPU_SNOOP_NONE;
+ si.enet_options[i] = MV64360_ENET2MEM_SNOOP_NONE;
+ si.mpsc_options[i] = MV64360_MPSC2MEM_SNOOP_NONE;
+ si.idma_options[i] = MV64360_IDMA2MEM_SNOOP_NONE;
+
+ si.pci_1.acc_cntl_options[i] =
+ MV64360_PCI_ACC_CNTL_SNOOP_NONE |
+ MV64360_PCI_ACC_CNTL_SWAP_NONE |
+ MV64360_PCI_ACC_CNTL_MBURST_128_BYTES |
+ MV64360_PCI_ACC_CNTL_RDSIZE_256_BYTES;
#else
- si.cpu_snoop_options[i] = MV64360_CPU_SNOOP_WB; /* risky */
-#endif
- si.pci_0.acc_cntl_options[i] =
-#ifdef CONFIG_NOT_CACHE_COHERENT
- MV64360_PCI_ACC_CNTL_SNOOP_NONE |
-#else
- MV64360_PCI_ACC_CNTL_SNOOP_WB | /* risky */
+ si.cpu_prot_options[i] = 0;
+ si.enet_options[i] = MV64360_ENET2MEM_SNOOP_NONE; /* errata */
+ si.mpsc_options[i] = MV64360_MPSC2MEM_SNOOP_NONE; /* errata */
+ si.idma_options[i] = MV64360_IDMA2MEM_SNOOP_NONE; /* errata */
+
+ si.pci_1.acc_cntl_options[i] =
+ MV64360_PCI_ACC_CNTL_SNOOP_WB |
+ MV64360_PCI_ACC_CNTL_SWAP_NONE |
+ MV64360_PCI_ACC_CNTL_MBURST_32_BYTES |
+ MV64360_PCI_ACC_CNTL_RDSIZE_32_BYTES;
#endif
- MV64360_PCI_ACC_CNTL_SWAP_NONE |
- MV64360_PCI_ACC_CNTL_MBURST_32_BYTES |
- MV64360_PCI_ACC_CNTL_RDSIZE_32_BYTES;
}
/* Lookup host bridge - on CPU 0 - no SMP support */
@@ -227,55 +233,44 @@ chestnut_setup_bridge(void)
bh.hose_a->first_busno = 0;
bh.hose_a->last_busno = 0xff;
bh.hose_a->last_busno = pciauto_bus_scan(bh.hose_a, 0);
-
}
void __init
chestnut_setup_peripherals(void)
{
-
mv64x60_set_32bit_window(&bh, MV64x60_CPU2BOOT_WIN,
CHESTNUT_BOOT_8BIT_BASE, CHESTNUT_BOOT_8BIT_SIZE, 0);
+ bh.ci->enable_window_32bit(&bh, MV64x60_CPU2BOOT_WIN);
mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_0_WIN,
CHESTNUT_32BIT_BASE, CHESTNUT_32BIT_SIZE, 0);
+ bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_0_WIN);
+
mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_1_WIN,
CHESTNUT_CPLD_BASE, CHESTNUT_CPLD_SIZE, 0);
+ bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_1_WIN);
+ cpld_base = ioremap(CHESTNUT_CPLD_BASE, CHESTNUT_CPLD_SIZE);
mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_2_WIN,
CHESTNUT_UART_BASE, CHESTNUT_UART_SIZE, 0);
+ bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_2_WIN);
+
mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_3_WIN,
CHESTNUT_FRAM_BASE, CHESTNUT_FRAM_SIZE, 0);
- /* Set up window for internal sram (256KByte insize) */
- mv64x60_set_32bit_window(&bh, MV64x60_CPU2SRAM_WIN,
- CHESTNUT_INTERNAL_SRAM_BASE,
- CHESTNUT_INTERNAL_SRAM_SIZE, 0);
+ bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_3_WIN);
- boot_base = (u32)ioremap(CHESTNUT_BOOT_8BIT_BASE,
- CHESTNUT_BOOT_8BIT_SIZE);
- cpld_base = (u32)ioremap(CHESTNUT_CPLD_BASE, CHESTNUT_CPLD_SIZE);
+ mv64x60_set_32bit_window(&bh, MV64x60_CPU2SRAM_WIN,
+ CHESTNUT_INTERNAL_SRAM_BASE, MV64360_SRAM_SIZE, 0);
+ bh.ci->enable_window_32bit(&bh, MV64x60_CPU2SRAM_WIN);
- /*
- * Configure internal SRAM -
- * Cache coherent write back, incase
- * CONFIG_MV64360_SRAM_CACHE_COHERENT set
- * Parity enabled.
- * Parity error propagation
- * Arbitration not parked for CPU only
- * Other bits are reserved.
- */
-#ifdef CONFIG_MV64360_SRAM_CACHE_COHERENT
- mv64x60_write(&bh, MV64360_SRAM_CONFIG, 0x001600b2);
-#else
+#ifdef CONFIG_NOT_COHERENT_CACHE
mv64x60_write(&bh, MV64360_SRAM_CONFIG, 0x001600b0);
+#else
+ mv64x60_write(&bh, MV64360_SRAM_CONFIG, 0x001600b2);
#endif
+ sram_base = ioremap(CHESTNUT_INTERNAL_SRAM_BASE, MV64360_SRAM_SIZE);
+ memset(sram_base, 0, MV64360_SRAM_SIZE);
- /*
- * Setting the SRAM to 0. Note that this generates parity errors on
- * internal data path in SRAM since it's first time accessing it
- * while after reset it's not configured
- */
- memset((void *)CHESTNUT_INTERNAL_SRAM_BASE, 0, CHESTNUT_INTERNAL_SRAM_SIZE);
/*
* Configure MPP pins for PCI DMA
*
@@ -312,9 +307,9 @@ chestnut_setup_peripherals(void)
(0xf << 20) | /* MPPSel13 GPIO[13] */
(0xf << 24) | /* MPPSel14 GPIO[14] */
(0xf << 28)); /* MPPSel15 GPIO[15] */
- mv64x60_set_bits(&bh, MV64x60_GPP_IO_CNTL,
+ mv64x60_set_bits(&bh, MV64x60_GPP_IO_CNTL, /* Output */
BIT(1) | BIT(2) | BIT(4) | BIT(5) | BIT(6) |
- BIT(9) | BIT(10) | BIT(13) | BIT(14) | BIT(15)); /* Output */
+ BIT(9) | BIT(10) | BIT(13) | BIT(14) | BIT(15));
/*
* Configure the following MPP pins to indicate a level
@@ -364,7 +359,7 @@ chestnut_setup_peripherals(void)
/*
* Dismiss and then enable interrupt on CPU #0 high cause register
* BIT27 summarizes GPP interrupts 24-31
- */
+ */
mv64x60_set_bits(&bh, MV64360_IC_CPU0_INTR_MASK_HI, BIT(27));
if (ppc_md.progress)
@@ -423,14 +418,32 @@ chestnut_setup_arch(void)
/* Identify the system */
printk(KERN_INFO "System Identification: IBM 750FX/GX Eval Board\n");
- printk(KERN_INFO "IBM 750FX/GX port (C) 2004 MontaVista Software, Inc. (source@mvista.com)\n");
+ printk(KERN_INFO "IBM 750FX/GX port (C) 2004 MontaVista Software, Inc."
+ " (source@mvista.com)\n");
if (ppc_md.progress)
ppc_md.progress("chestnut_setup_arch: exit", 0);
+}
+
+#ifdef CONFIG_MTD_PHYSMAP
+static struct mtd_partition ptbl;
+
+static int __init
+chestnut_setup_mtd(void)
+{
+ memset(&ptbl, 0, sizeof(ptbl));
+
+ ptbl.name = "User FS";
+ ptbl.size = CHESTNUT_32BIT_SIZE;
- return;
+ physmap_map.size = CHESTNUT_32BIT_SIZE;
+ physmap_set_partitions(&ptbl, 1);
+ return 0;
}
+arch_initcall(chestnut_setup_mtd);
+#endif
+
/**************************************************************************
* FUNCTION: chestnut_restart
*
@@ -450,7 +463,7 @@ chestnut_restart(char *cmd)
*
* MPP24 - board reset
*/
- writeb(0x1, (void __iomem *)(cpld_base+3));
+ writeb(0x1, cpld_base + 3);
/* GPP pin tied to MPP earlier */
mv64x60_set_bits(&bh, MV64x60_GPP_VALUE_SET, BIT(24));
@@ -474,37 +487,6 @@ chestnut_power_off(void)
/* NOTREACHED */
}
-#define SET_PCI_COMMAND_INVALIDATE
-#ifdef SET_PCI_COMMAND_INVALIDATE
-/*
- * Dave Wilhardt found that PCI_COMMAND_INVALIDATE must
- * be set for each device if you are using cache coherency.
- */
-static void __init
-set_pci_command_invalidate(void)
-{
- struct pci_dev *dev = NULL;
- u16 val;
-
- while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
- pci_read_config_word(dev, PCI_COMMAND, &val);
- val |= PCI_COMMAND_INVALIDATE;
- pci_write_config_word(dev, PCI_COMMAND, val);
-
- pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE,
- L1_CACHE_LINE_SIZE >> 2);
- }
-}
-#endif
-
-static void __init
-chestnut_pci_fixups(void)
-{
-#ifdef SET_PCI_COMMAND_INVALIDATE
- set_pci_command_invalidate();
-#endif
-}
-
/**************************************************************************
* FUNCTION: chestnut_map_io
*
@@ -514,27 +496,9 @@ chestnut_pci_fixups(void)
static void __init
chestnut_map_io(void)
{
-#ifdef CONFIG_MV64360_SRAM_CACHEABLE
- io_block_mapping(CHESTNUT_INTERNAL_SRAM_BASE,
- CHESTNUT_INTERNAL_SRAM_BASE,
- CHESTNUT_INTERNAL_SRAM_SIZE,
- _PAGE_KERNEL | _PAGE_GUARDED);
-#else
-#ifdef CONFIG_MV64360_SRAM_CACHE_COHERENT
- io_block_mapping(CHESTNUT_INTERNAL_SRAM_BASE,
- CHESTNUT_INTERNAL_SRAM_BASE,
- CHESTNUT_INTERNAL_SRAM_SIZE,
- _PAGE_KERNEL | _PAGE_GUARDED | _PAGE_COHERENT);
-#else
- io_block_mapping(CHESTNUT_INTERNAL_SRAM_BASE,
- CHESTNUT_INTERNAL_SRAM_BASE,
- CHESTNUT_INTERNAL_SRAM_SIZE,
- _PAGE_IO);
-#endif /* !CONFIG_MV64360_SRAM_CACHE_COHERENT */
-#endif /* !CONFIG_MV64360_SRAM_CACHEABLE */
-
#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
- io_block_mapping(CHESTNUT_UART_BASE, CHESTNUT_UART_BASE, 0x100000, _PAGE_IO);
+ io_block_mapping(CHESTNUT_UART_BASE, CHESTNUT_UART_BASE, 0x100000,
+ _PAGE_IO);
#endif
}
@@ -549,11 +513,9 @@ static __inline__ void
chestnut_set_bat(void)
{
mb();
- mtspr(DBAT3U, 0xf0001ffe);
- mtspr(DBAT3L, 0xf000002a);
+ mtspr(SPRN_DBAT3U, 0xf0001ffe);
+ mtspr(SPRN_DBAT3L, 0xf000002a);
mb();
-
- return;
}
/**************************************************************************
@@ -587,7 +549,6 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
ppc_md.find_end_of_memory = chestnut_find_end_of_memory;
ppc_md.setup_io_mappings = chestnut_map_io;
- ppc_md.pcibios_fixup = chestnut_pci_fixups;
ppc_md.restart = chestnut_restart;
ppc_md.power_off = chestnut_power_off;
@@ -603,8 +564,6 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
ppc_md.heartbeat = NULL;
- ppc_md.pcibios_fixup = chestnut_pci_fixups;
-
bh.p_base = CONFIG_MV64X60_NEW_BASE;
chestnut_set_bat();
@@ -618,6 +577,4 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
if (ppc_md.progress)
ppc_md.progress("chestnut_init(): exit", 0);
-
- return;
}
diff --git a/arch/ppc/platforms/chestnut.h b/arch/ppc/platforms/chestnut.h
index 560fd0d60bae2..0400b2be40ab5 100644
--- a/arch/ppc/platforms/chestnut.h
+++ b/arch/ppc/platforms/chestnut.h
@@ -24,11 +24,12 @@
* implement at 0xf1000000 only at this time
*
* 0xfff00000-0xffffffff - 8 Flash
+ * 0xffe00000-0xffefffff - BOOT SRAM
* 0xffd00000-0xffd00004 - CPLD
* 0xffc00000-0xffc0000f - UART
* 0xffb00000-0xffb07fff - FRAM
- * 0xffa00000-0xffafffff - *** HOLE ***
- * 0xff900000-0xff9fffff - MV64460 Integrated SRAM
+ * 0xff840000-0xffafffff - *** HOLE ***
+ * 0xff800000-0xff83ffff - MV64460 Integrated SRAM
* 0xfe000000-0xff8fffff - *** HOLE ***
* 0xfc000000-0xfdffffff - 32bit Flash
* 0xf1010000-0xfbffffff - *** HOLE ***
@@ -49,9 +50,7 @@
#define CHESTNUT_UART_SIZE_ACTUAL 16
#define CHESTNUT_FRAM_BASE 0xffb00000
#define CHESTNUT_FRAM_SIZE_ACTUAL (32*1024)
-#define CHESTNUT_BRIDGE_REG_BASE 0xf1000000
-#define CHESTNUT_INTERNAL_SRAM_BASE 0xff900000
-#define CHESTNUT_INTERNAL_SRAM_SIZE_ACTUAL (256*1024)
+#define CHESTNUT_INTERNAL_SRAM_BASE 0xff800000
#define CHESTNUT_32BIT_BASE 0xfc000000
#define CHESTNUT_32BIT_SIZE (32*1024*1024)
@@ -65,14 +64,16 @@
CHESTNUT_UART_SIZE_ACTUAL)
#define CHESTNUT_FRAM_SIZE max(MV64360_WINDOW_SIZE_MIN, \
CHESTNUT_FRAM_SIZE_ACTUAL)
-#define CHESTNUT_INTERNAL_SRAM_SIZE max(MV64360_WINDOW_SIZE_MIN, \
- CHESTNUT_INTERNAL_SRAM_SIZE_ACTUAL)
#define CHESTNUT_BUS_SPEED 200000000
#define CHESTNUT_PIBS_DATABASE 0xf0000 /* from PIBS src code */
-#define MV64360_ETH_PORT_SERIAL_CONTROL_REG_PORT0 0x243c
-#define MV64360_ETH_PORT_SERIAL_CONTROL_REG_PORT1 0x283c
+#define KATANA_ETH0_PHY_ADDR 12
+#define KATANA_ETH1_PHY_ADDR 11
+#define KATANA_ETH2_PHY_ADDR 4
+
+#define CHESTNUT_ETH_TX_QUEUE_SIZE 800
+#define CHESTNUT_ETH_RX_QUEUE_SIZE 400
/*
* PCI windows
@@ -89,17 +90,17 @@
/*
* Board-specific IRQ info
*/
-#define CHESTNUT_PCI_SLOT0_IRQ 64+31
-#define CHESTNUT_PCI_SLOT1_IRQ 64+30
-#define CHESTNUT_PCI_SLOT2_IRQ 64+29
-#define CHESTNUT_PCI_SLOT3_IRQ 64+28
+#define CHESTNUT_PCI_SLOT0_IRQ (64 + 31)
+#define CHESTNUT_PCI_SLOT1_IRQ (64 + 30)
+#define CHESTNUT_PCI_SLOT2_IRQ (64 + 29)
+#define CHESTNUT_PCI_SLOT3_IRQ (64 + 28)
/* serial port definitions */
-#define CHESTNUT_UART0_IO_BASE CHESTNUT_UART_BASE+8
+#define CHESTNUT_UART0_IO_BASE (CHESTNUT_UART_BASE + 8)
#define CHESTNUT_UART1_IO_BASE CHESTNUT_UART_BASE
-#define UART0_INT 64+25
-#define UART1_INT 64+26
+#define UART0_INT (64 + 25)
+#define UART1_INT (64 + 26)
#ifdef CONFIG_SERIAL_MANY_PORTS
#define RS_TABLE_SIZE 64
@@ -108,7 +109,7 @@
#endif
/* Rate for the 3.6864 Mhz clock for the onboard serial chip */
-#define BASE_BAUD ( 3686400 / 16 )
+#define BASE_BAUD (3686400 / 16)
#ifdef CONFIG_SERIAL_DETECT_IRQ
#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST|ASYNC_AUTO_IRQ)
diff --git a/arch/ppc/platforms/chrp_pegasos_eth.c b/arch/ppc/platforms/chrp_pegasos_eth.c
new file mode 100644
index 0000000000000..cad5bfa153b26
--- /dev/null
+++ b/arch/ppc/platforms/chrp_pegasos_eth.c
@@ -0,0 +1,101 @@
+/*
+ * arch/ppc/platforms/chrp_pegasos_eth.c
+ *
+ * Copyright (C) 2005 Sven Luther <sl@bplan-gmbh.de>
+ * Thanks to :
+ * Dale Farnsworth <dale@farnsworth.org>
+ * Mark A. Greer <mgreer@mvista.com>
+ * Nicolas DET <nd@bplan-gmbh.de>
+ * Benjamin Herrenschmidt <benh@kernel.crashing.org>
+ * And anyone else who helped me on this.
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/mv643xx.h>
+#include <linux/pci.h>
+
+/* Pegasos 2 specific Marvell MV 64361 gigabit ethernet port setup */
+static struct resource mv643xx_eth_shared_resources[] = {
+ [0] = {
+ .name = "ethernet shared base",
+ .start = 0xf1000000 + MV643XX_ETH_SHARED_REGS,
+ .end = 0xf1000000 + MV643XX_ETH_SHARED_REGS +
+ MV643XX_ETH_SHARED_REGS_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device mv643xx_eth_shared_device = {
+ .name = MV643XX_ETH_SHARED_NAME,
+ .id = 0,
+ .num_resources = ARRAY_SIZE(mv643xx_eth_shared_resources),
+ .resource = mv643xx_eth_shared_resources,
+};
+
+static struct resource mv643xx_eth0_resources[] = {
+ [0] = {
+ .name = "eth0 irq",
+ .start = 9,
+ .end = 9,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct mv643xx_eth_platform_data eth0_pd;
+
+static struct platform_device eth0_device = {
+ .name = MV643XX_ETH_NAME,
+ .id = 0,
+ .num_resources = ARRAY_SIZE(mv643xx_eth0_resources),
+ .resource = mv643xx_eth0_resources,
+ .dev = {
+ .platform_data = &eth0_pd,
+ },
+};
+
+static struct resource mv643xx_eth1_resources[] = {
+ [0] = {
+ .name = "eth1 irq",
+ .start = 9,
+ .end = 9,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct mv643xx_eth_platform_data eth1_pd;
+
+static struct platform_device eth1_device = {
+ .name = MV643XX_ETH_NAME,
+ .id = 1,
+ .num_resources = ARRAY_SIZE(mv643xx_eth1_resources),
+ .resource = mv643xx_eth1_resources,
+ .dev = {
+ .platform_data = &eth1_pd,
+ },
+};
+
+static struct platform_device *mv643xx_eth_pd_devs[] __initdata = {
+ &mv643xx_eth_shared_device,
+ &eth0_device,
+ &eth1_device,
+};
+
+
+int
+mv643xx_eth_add_pds(void)
+{
+ int ret = 0;
+ static struct pci_device_id pci_marvell_mv64360[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, PCI_DEVICE_ID_MARVELL_MV64360) },
+ { }
+ };
+
+ if (pci_dev_present(pci_marvell_mv64360)) {
+ ret = platform_add_devices(mv643xx_eth_pd_devs, ARRAY_SIZE(mv643xx_eth_pd_devs));
+ }
+ return ret;
+}
+device_initcall(mv643xx_eth_add_pds);
diff --git a/arch/ppc/platforms/chrp_setup.c b/arch/ppc/platforms/chrp_setup.c
index 163df2adf38a2..f23c4f3207605 100644
--- a/arch/ppc/platforms/chrp_setup.c
+++ b/arch/ppc/platforms/chrp_setup.c
@@ -527,6 +527,8 @@ chrp_init(unsigned long r3, unsigned long r4, unsigned long r5,
ppc_md.init = chrp_init2;
+ ppc_md.phys_mem_access_prot = pci_phys_mem_access_prot;
+
ppc_md.restart = chrp_restart;
ppc_md.power_off = chrp_power_off;
ppc_md.halt = chrp_halt;
diff --git a/arch/ppc/platforms/cpci690.c b/arch/ppc/platforms/cpci690.c
index 0405efe845e4b..507870c9a97a1 100644
--- a/arch/ppc/platforms/cpci690.c
+++ b/arch/ppc/platforms/cpci690.c
@@ -60,8 +60,7 @@ cpci690_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
const long min_idsel = 20, max_idsel = 20, irqs_per_slot = 4;
return PCI_IRQ_TABLE_LOOKUP;
- }
- else {
+ } else {
static char pci_irq_table[][4] =
/*
* PCI IDSEL/INTPIN->INTLINE
@@ -79,18 +78,12 @@ cpci690_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
}
static int
-cpci690_get_bus_speed(void)
-{
- return 133333333;
-}
-
-static int
cpci690_get_cpu_speed(void)
{
unsigned long hid1;
- hid1 = mfspr(HID1) >> 28;
- return cpci690_get_bus_speed() * cpu_7xx[hid1]/2;
+ hid1 = mfspr(SPRN_HID1) >> 28;
+ return CPCI690_BUS_FREQ * cpu_7xx[hid1]/2;
}
#define KB (1024UL)
@@ -226,8 +219,6 @@ cpci690_setup_bridge(void)
bh.hose_b->last_busno = 0xff;
bh.hose_b->last_busno = pciauto_bus_scan(bh.hose_b,
bh.hose_b->first_busno);
-
- return;
}
static void __init
@@ -285,8 +276,6 @@ cpci690_setup_peripherals(void)
/* Route MPP interrupt inputs to GPP */
mv64x60_write(&bh, MV64x60_MPP_CNTL_2, 0x00000000);
mv64x60_write(&bh, MV64x60_MPP_CNTL_3, 0x00000000);
-
- return;
}
static void __init
@@ -326,8 +315,6 @@ cpci690_setup_arch(void)
if (ppc_md.progress)
ppc_md.progress("cpci690_setup_arch: exit", 0);
-
- return;
}
/* Platform device data fixup routines. */
@@ -340,11 +327,9 @@ cpci690_fixup_mpsc_pdata(struct platform_device *pdev)
pdata = (struct mpsc_pdata *)pdev->dev.platform_data;
pdata->max_idle = 40;
- pdata->default_baud = 9600;
- pdata->brg_clk_src = 8;
- pdata->brg_clk_freq = 133000000;
-
- return;
+ pdata->default_baud = CPCI690_MPSC_BAUD;
+ pdata->brg_clk_src = CPCI690_MPSC_CLK_SRC;
+ pdata->brg_clk_freq = CPCI690_BUS_FREQ;
}
static int __init
@@ -354,8 +339,8 @@ cpci690_platform_notify(struct device *dev)
char *bus_id;
void ((*rtn)(struct platform_device *pdev));
} dev_map[] = {
- { MPSC_CTLR_NAME "0", cpci690_fixup_mpsc_pdata },
- { MPSC_CTLR_NAME "1", cpci690_fixup_mpsc_pdata },
+ { MPSC_CTLR_NAME ".0", cpci690_fixup_mpsc_pdata },
+ { MPSC_CTLR_NAME ".1", cpci690_fixup_mpsc_pdata },
};
struct platform_device *pdev;
int i;
@@ -412,7 +397,7 @@ cpci690_show_cpuinfo(struct seq_file *m)
seq_printf(m, "vendor\t\t: " BOARD_VENDOR "\n");
seq_printf(m, "machine\t\t: " BOARD_MACHINE "\n");
seq_printf(m, "cpu MHz\t\t: %d\n", cpci690_get_cpu_speed()/1000/1000);
- seq_printf(m, "bus MHz\t\t: %d\n", cpci690_get_bus_speed()/1000/1000);
+ seq_printf(m, "bus MHz\t\t: %d\n", CPCI690_BUS_FREQ/1000/1000);
return 0;
}
@@ -422,15 +407,13 @@ cpci690_calibrate_decr(void)
{
ulong freq;
- freq = cpci690_get_bus_speed()/4;
+ freq = CPCI690_BUS_FREQ / 4;
printk(KERN_INFO "time_init: decrementer frequency = %lu.%.6lu MHz\n",
freq/1000000, freq%1000000);
tb_ticks_per_jiffy = freq / HZ;
tb_to_us = mulhwu_scale_factor(freq, 1000000);
-
- return;
}
static __inline__ void
@@ -441,11 +424,9 @@ cpci690_set_bat(u32 addr, u32 size)
size = ((size >> 17) - 1) << 2;
mb();
- mtspr(DBAT1U, addr | size | 0x2); /* Vs == 1; Vp == 0 */
- mtspr(DBAT1L, addr | 0x2a); /* WIMG bits == 0101; PP == r/w access */
+ mtspr(SPRN_DBAT1U, addr | size | 0x2); /* Vs == 1; Vp == 0 */
+ mtspr(SPRN_DBAT1L, addr | 0x2a); /* WIMG bits == 0101; PP == r/w access */
mb();
-
- return;
}
#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
@@ -507,6 +488,4 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
#if defined(CONFIG_SERIAL_MPSC)
platform_notify = cpci690_platform_notify;
#endif
-
- return;
}
diff --git a/arch/ppc/platforms/cpci690.h b/arch/ppc/platforms/cpci690.h
index 3144b877920a6..36cd2673c7427 100644
--- a/arch/ppc/platforms/cpci690.h
+++ b/arch/ppc/platforms/cpci690.h
@@ -70,4 +70,9 @@ typedef struct board_info {
#define CPCI690_IPMI_SIZE max(GT64260_WINDOW_SIZE_MIN, \
CPCI690_IPMI_SIZE_ACTUAL)
+#define CPCI690_MPSC_BAUD 9600
+#define CPCI690_MPSC_CLK_SRC 8 /* TCLK */
+
+#define CPCI690_BUS_FREQ 133333333
+
#endif /* __PPC_PLATFORMS_CPCI690_H */
diff --git a/arch/ppc/platforms/ev64260.c b/arch/ppc/platforms/ev64260.c
index 29d494dce2148..aa50637a5cfb1 100644
--- a/arch/ppc/platforms/ev64260.c
+++ b/arch/ppc/platforms/ev64260.c
@@ -80,14 +80,14 @@ ev64260_get_cpu_speed(void)
{
unsigned long pvr, hid1, pll_ext;
- pvr = PVR_VER(mfspr(PVR));
+ pvr = PVR_VER(mfspr(SPRN_PVR));
if (pvr != PVR_VER(PVR_7450)) {
- hid1 = mfspr(HID1) >> 28;
+ hid1 = mfspr(SPRN_HID1) >> 28;
return ev64260_get_bus_speed() * cpu_7xx[hid1]/2;
}
else {
- hid1 = (mfspr(HID1) & 0x0001e000) >> 13;
+ hid1 = (mfspr(SPRN_HID1) & 0x0001e000) >> 13;
pll_ext = 0; /* No way to read; must get from schematic */
return ev64260_get_bus_speed() * cpu_745x[pll_ext][hid1]/2;
}
@@ -422,8 +422,8 @@ ev64260_platform_notify(struct device *dev)
char *bus_id;
void ((*rtn)(struct platform_device *pdev));
} dev_map[] = {
- { MPSC_CTLR_NAME "0", ev64260_fixup_mpsc_pdata },
- { MPSC_CTLR_NAME "1", ev64260_fixup_mpsc_pdata },
+ { MPSC_CTLR_NAME ".0", ev64260_fixup_mpsc_pdata },
+ { MPSC_CTLR_NAME ".1", ev64260_fixup_mpsc_pdata },
};
struct platform_device *pdev;
int i;
@@ -530,7 +530,7 @@ ev64260_show_cpuinfo(struct seq_file *m)
{
uint pvid;
- pvid = mfspr(PVR);
+ pvid = mfspr(SPRN_PVR);
seq_printf(m, "vendor\t\t: " BOARD_VENDOR "\n");
seq_printf(m, "machine\t\t: " BOARD_MACHINE "\n");
seq_printf(m, "cpu MHz\t\t: %d\n", ev64260_get_cpu_speed()/1000/1000);
@@ -563,8 +563,8 @@ static __inline__ void
ev64260_set_bat(void)
{
mb();
- mtspr(DBAT1U, 0xfb0001fe);
- mtspr(DBAT1L, 0xfb00002a);
+ mtspr(SPRN_DBAT1U, 0xfb0001fe);
+ mtspr(SPRN_DBAT1L, 0xfb00002a);
mb();
return;
diff --git a/arch/ppc/platforms/gemini_prom.S b/arch/ppc/platforms/gemini_prom.S
index 84729e2a093c9..8c5065d565054 100644
--- a/arch/ppc/platforms/gemini_prom.S
+++ b/arch/ppc/platforms/gemini_prom.S
@@ -40,29 +40,29 @@ _GLOBAL(gemini_prom_init)
/* zero out the bats now that the MMU is off */
prom_no_mmu:
li r3,0
- mtspr IBAT0U,r3
- mtspr IBAT0L,r3
- mtspr IBAT1U,r3
- mtspr IBAT1L,r3
- mtspr IBAT2U,r3
- mtspr IBAT2L,r3
- mtspr IBAT3U,r3
- mtspr IBAT3L,r3
+ mtspr SPRN_IBAT0U,r3
+ mtspr SPRN_IBAT0L,r3
+ mtspr SPRN_IBAT1U,r3
+ mtspr SPRN_IBAT1L,r3
+ mtspr SPRN_IBAT2U,r3
+ mtspr SPRN_IBAT2L,r3
+ mtspr SPRN_IBAT3U,r3
+ mtspr SPRN_IBAT3L,r3
- mtspr DBAT0U,r3
- mtspr DBAT0L,r3
- mtspr DBAT1U,r3
- mtspr DBAT1L,r3
- mtspr DBAT2U,r3
- mtspr DBAT2L,r3
- mtspr DBAT3U,r3
- mtspr DBAT3L,r3
+ mtspr SPRN_DBAT0U,r3
+ mtspr SPRN_DBAT0L,r3
+ mtspr SPRN_DBAT1U,r3
+ mtspr SPRN_DBAT1L,r3
+ mtspr SPRN_DBAT2U,r3
+ mtspr SPRN_DBAT2L,r3
+ mtspr SPRN_DBAT3U,r3
+ mtspr SPRN_DBAT3L,r3
#endif
/* the bootloader (as far as I'm currently aware) doesn't mess with page
tables, but since we're already here, might as well zap these, too */
li r4,0
- mtspr SDR1,r4
+ mtspr SPRN_SDR1,r4
li r4,16
mtctr r4
@@ -75,9 +75,9 @@ prom_no_mmu:
#ifdef CONFIG_SMP
/* The 750 book (and Mot/IBM support) says that this will "assist" snooping
when in SMP. Not sure yet whether this should stay or leave... */
- mfspr r4,HID0
+ mfspr r4,SPRN_HID0
ori r4,r4,HID0_ABE
- mtspr HID0,r4
+ mtspr SPRN_HID0,r4
sync
#endif /* CONFIG_SMP */
blr
@@ -88,6 +88,6 @@ _GLOBAL(_gemini_reboot)
lis r5,GEMINI_BOOT_INIT@h
ori r5,r5,GEMINI_BOOT_INIT@l
li r6,MSR_IP
- mtspr SRR0,r5
- mtspr SRR1,r6
+ mtspr SPRN_SRR0,r5
+ mtspr SPRN_SRR1,r6
rfi
diff --git a/arch/ppc/platforms/gemini_setup.c b/arch/ppc/platforms/gemini_setup.c
index 2576d8578c1b4..1a42cb9b1134c 100644
--- a/arch/ppc/platforms/gemini_setup.c
+++ b/arch/ppc/platforms/gemini_setup.c
@@ -202,8 +202,8 @@ gemini_get_clock_speed(void)
unsigned long hid1, pvr;
int clock;
- pvr = mfspr(PVR);
- hid1 = (mfspr(HID1) >> 28) & 0xf;
+ pvr = mfspr(SPRN_PVR);
+ hid1 = (mfspr(SPRN_HID1) >> 28) & 0xf;
if (PVR_VER(pvr) == 8 ||
PVR_VER(pvr) == 12)
hid1 = cpu_7xx[hid1];
@@ -238,7 +238,7 @@ void __init gemini_init_l2(void)
reg = readb(GEMINI_L2CFG);
brev = readb(GEMINI_BREV);
fam = readb(GEMINI_FEAT);
- pvr = mfspr(PVR);
+ pvr = mfspr(SPRN_PVR);
switch(PVR_VER(pvr)) {
@@ -537,8 +537,8 @@ void __init platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
int i;
/* Restore BATs for now */
- mtspr(DBAT3U, 0xf0001fff);
- mtspr(DBAT3L, 0xf000002a);
+ mtspr(SPRN_DBAT3U, 0xf0001fff);
+ mtspr(SPRN_DBAT3L, 0xf000002a);
parse_bootinfo(find_bootinfo());
diff --git a/arch/ppc/platforms/hdpu.c b/arch/ppc/platforms/hdpu.c
new file mode 100644
index 0000000000000..b659d7b3d7477
--- /dev/null
+++ b/arch/ppc/platforms/hdpu.c
@@ -0,0 +1,1062 @@
+
+/*
+ * arch/ppc/platforms/hdpu_setup.c
+ *
+ * Board setup routines for the Sky Computers HDPU Compute Blade.
+ *
+ * Written by Brian Waite <waite@skycomputers.com>
+ *
+ * Based on code done by - Mark A. Greer <mgreer@mvista.com>
+ * Rabeeh Khoury - rabeeh@galileo.co.il
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the 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/pci.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/ide.h>
+#include <linux/seq_file.h>
+
+#include <linux/initrd.h>
+#include <linux/root_dev.h>
+#include <linux/smp.h>
+
+#include <asm/time.h>
+#include <asm/machdep.h>
+#include <asm/todc.h>
+#include <asm/mv64x60.h>
+#include <asm/ppcboot.h>
+#include <platforms/hdpu.h>
+#include <linux/mv643xx.h>
+#include <linux/hdpu_features.h>
+#include <linux/device.h>
+#include <linux/mtd/physmap.h>
+
+#define BOARD_VENDOR "Sky Computers"
+#define BOARD_MACHINE "HDPU-CB-A"
+
+bd_t ppcboot_bd;
+int ppcboot_bd_valid = 0;
+
+static mv64x60_handle_t bh;
+
+extern char cmd_line[];
+
+unsigned long hdpu_find_end_of_memory(void);
+void hdpu_mpsc_progress(char *s, unsigned short hex);
+void hdpu_heartbeat(void);
+
+static void parse_bootinfo(unsigned long r3,
+ unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7);
+static void hdpu_set_l1pe(void);
+static void hdpu_cpustate_set(unsigned char new_state);
+#ifdef CONFIG_SMP
+static spinlock_t timebase_lock = SPIN_LOCK_UNLOCKED;
+static unsigned int timebase_upper = 0, timebase_lower = 0;
+extern int smp_tb_synchronized;
+
+void __devinit hdpu_tben_give(void);
+void __devinit hdpu_tben_take(void);
+#endif
+
+static int __init
+hdpu_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+ struct pci_controller *hose = pci_bus_to_hose(dev->bus->number);
+
+ if (hose->index == 0) {
+ static char pci_irq_table[][4] = {
+ {HDPU_PCI_0_IRQ, 0, 0, 0},
+ {HDPU_PCI_0_IRQ, 0, 0, 0},
+ };
+
+ const long min_idsel = 1, max_idsel = 2, irqs_per_slot = 4;
+ return PCI_IRQ_TABLE_LOOKUP;
+ } else {
+ static char pci_irq_table[][4] = {
+ {HDPU_PCI_1_IRQ, 0, 0, 0},
+ };
+
+ const long min_idsel = 1, max_idsel = 1, irqs_per_slot = 4;
+ return PCI_IRQ_TABLE_LOOKUP;
+ }
+}
+
+static void __init hdpu_intr_setup(void)
+{
+ mv64x60_write(&bh, MV64x60_GPP_IO_CNTL,
+ (1 | (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5) |
+ (1 << 6) | (1 << 7) | (1 << 12) | (1 << 16) |
+ (1 << 18) | (1 << 19) | (1 << 20) | (1 << 21) |
+ (1 << 22) | (1 << 23) | (1 << 24) | (1 << 25) |
+ (1 << 26) | (1 << 27) | (1 << 28) | (1 << 29)));
+
+ /* XXXX Erranum FEr PCI-#8 */
+ mv64x60_clr_bits(&bh, MV64x60_PCI0_CMD, (1 << 5) | (1 << 9));
+ mv64x60_clr_bits(&bh, MV64x60_PCI1_CMD, (1 << 5) | (1 << 9));
+
+ /*
+ * Dismiss and then enable interrupt on GPP interrupt cause
+ * for CPU #0
+ */
+ mv64x60_write(&bh, MV64x60_GPP_INTR_CAUSE, ~((1 << 8) | (1 << 13)));
+ mv64x60_set_bits(&bh, MV64x60_GPP_INTR_MASK, (1 << 8) | (1 << 13));
+
+ /*
+ * Dismiss and then enable interrupt on CPU #0 high cause reg
+ * BIT25 summarizes GPP interrupts 8-15
+ */
+ mv64x60_set_bits(&bh, MV64360_IC_CPU0_INTR_MASK_HI, (1 << 25));
+}
+
+static void __init hdpu_setup_peripherals(void)
+{
+ unsigned int val;
+
+ mv64x60_set_32bit_window(&bh, MV64x60_CPU2BOOT_WIN,
+ HDPU_EMB_FLASH_BASE, HDPU_EMB_FLASH_SIZE, 0);
+ bh.ci->enable_window_32bit(&bh, MV64x60_CPU2BOOT_WIN);
+
+ mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_0_WIN,
+ HDPU_TBEN_BASE, HDPU_TBEN_SIZE, 0);
+ bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_0_WIN);
+
+ mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_1_WIN,
+ HDPU_NEXUS_ID_BASE, HDPU_NEXUS_ID_SIZE, 0);
+ bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_1_WIN);
+
+ mv64x60_set_32bit_window(&bh, MV64x60_CPU2SRAM_WIN,
+ HDPU_INTERNAL_SRAM_BASE,
+ HDPU_INTERNAL_SRAM_SIZE, 0);
+ bh.ci->enable_window_32bit(&bh, MV64x60_CPU2SRAM_WIN);
+
+ bh.ci->disable_window_32bit(&bh, MV64x60_ENET2MEM_4_WIN);
+ mv64x60_set_32bit_window(&bh, MV64x60_ENET2MEM_4_WIN, 0, 0, 0);
+
+ mv64x60_clr_bits(&bh, MV64x60_PCI0_PCI_DECODE_CNTL, (1 << 3));
+ mv64x60_clr_bits(&bh, MV64x60_PCI1_PCI_DECODE_CNTL, (1 << 3));
+ mv64x60_clr_bits(&bh, MV64x60_TIMR_CNTR_0_3_CNTL,
+ ((1 << 0) | (1 << 8) | (1 << 16) | (1 << 24)));
+
+ /* Enable pipelining */
+ mv64x60_set_bits(&bh, MV64x60_CPU_CONFIG, (1 << 13));
+ /* Enable Snoop Pipelineing */
+ mv64x60_set_bits(&bh, MV64360_D_UNIT_CONTROL_HIGH, (1 << 24));
+
+ /*
+ * Change DRAM read buffer assignment.
+ * Assign read buffer 0 dedicated only for CPU,
+ * and the rest read buffer 1.
+ */
+ val = mv64x60_read(&bh, MV64360_SDRAM_CONFIG);
+ val = val & 0x03ffffff;
+ val = val | 0xf8000000;
+ mv64x60_write(&bh, MV64360_SDRAM_CONFIG, val);
+
+ /*
+ * Configure internal SRAM -
+ * Cache coherent write back, if CONFIG_MV64360_SRAM_CACHE_COHERENT set
+ * Parity enabled.
+ * Parity error propagation
+ * Arbitration not parked for CPU only
+ * Other bits are reserved.
+ */
+#ifdef CONFIG_MV64360_SRAM_CACHE_COHERENT
+ mv64x60_write(&bh, MV64360_SRAM_CONFIG, 0x001600b2);
+#else
+ mv64x60_write(&bh, MV64360_SRAM_CONFIG, 0x001600b0);
+#endif
+
+ hdpu_intr_setup();
+}
+
+static void __init hdpu_setup_bridge(void)
+{
+ struct mv64x60_setup_info si;
+ int i;
+
+ memset(&si, 0, sizeof(si));
+
+ si.phys_reg_base = HDPU_BRIDGE_REG_BASE;
+ si.pci_0.enable_bus = 1;
+ si.pci_0.pci_io.cpu_base = HDPU_PCI0_IO_START_PROC_ADDR;
+ si.pci_0.pci_io.pci_base_hi = 0;
+ si.pci_0.pci_io.pci_base_lo = HDPU_PCI0_IO_START_PCI_ADDR;
+ si.pci_0.pci_io.size = HDPU_PCI0_IO_SIZE;
+ si.pci_0.pci_io.swap = MV64x60_CPU2PCI_SWAP_NONE;
+ si.pci_0.pci_mem[0].cpu_base = HDPU_PCI0_MEM_START_PROC_ADDR;
+ si.pci_0.pci_mem[0].pci_base_hi = HDPU_PCI0_MEM_START_PCI_HI_ADDR;
+ si.pci_0.pci_mem[0].pci_base_lo = HDPU_PCI0_MEM_START_PCI_LO_ADDR;
+ si.pci_0.pci_mem[0].size = HDPU_PCI0_MEM_SIZE;
+ si.pci_0.pci_mem[0].swap = MV64x60_CPU2PCI_SWAP_NONE;
+ si.pci_0.pci_cmd_bits = 0;
+ si.pci_0.latency_timer = 0x80;
+
+ si.pci_1.enable_bus = 1;
+ si.pci_1.pci_io.cpu_base = HDPU_PCI1_IO_START_PROC_ADDR;
+ si.pci_1.pci_io.pci_base_hi = 0;
+ si.pci_1.pci_io.pci_base_lo = HDPU_PCI1_IO_START_PCI_ADDR;
+ si.pci_1.pci_io.size = HDPU_PCI1_IO_SIZE;
+ si.pci_1.pci_io.swap = MV64x60_CPU2PCI_SWAP_NONE;
+ si.pci_1.pci_mem[0].cpu_base = HDPU_PCI1_MEM_START_PROC_ADDR;
+ si.pci_1.pci_mem[0].pci_base_hi = HDPU_PCI1_MEM_START_PCI_HI_ADDR;
+ si.pci_1.pci_mem[0].pci_base_lo = HDPU_PCI1_MEM_START_PCI_LO_ADDR;
+ si.pci_1.pci_mem[0].size = HDPU_PCI1_MEM_SIZE;
+ si.pci_1.pci_mem[0].swap = MV64x60_CPU2PCI_SWAP_NONE;
+ si.pci_1.pci_cmd_bits = 0;
+ si.pci_1.latency_timer = 0x80;
+
+ for (i = 0; i < MV64x60_CPU2MEM_WINDOWS; i++) {
+#if defined(CONFIG_NOT_COHERENT_CACHE)
+ si.cpu_prot_options[i] = 0;
+ si.enet_options[i] = MV64360_ENET2MEM_SNOOP_NONE;
+ si.mpsc_options[i] = MV64360_MPSC2MEM_SNOOP_NONE;
+ si.idma_options[i] = MV64360_IDMA2MEM_SNOOP_NONE;
+
+ si.pci_1.acc_cntl_options[i] =
+ MV64360_PCI_ACC_CNTL_SNOOP_NONE |
+ MV64360_PCI_ACC_CNTL_SWAP_NONE |
+ MV64360_PCI_ACC_CNTL_MBURST_128_BYTES |
+ MV64360_PCI_ACC_CNTL_RDSIZE_256_BYTES;
+
+ si.pci_0.acc_cntl_options[i] =
+ MV64360_PCI_ACC_CNTL_SNOOP_NONE |
+ MV64360_PCI_ACC_CNTL_SWAP_NONE |
+ MV64360_PCI_ACC_CNTL_MBURST_128_BYTES |
+ MV64360_PCI_ACC_CNTL_RDSIZE_256_BYTES;
+
+#else
+ si.cpu_prot_options[i] = 0;
+ si.enet_options[i] = MV64360_ENET2MEM_SNOOP_WB; /* errata */
+ si.mpsc_options[i] = MV64360_MPSC2MEM_SNOOP_WB; /* errata */
+ si.idma_options[i] = MV64360_IDMA2MEM_SNOOP_WB; /* errata */
+
+ si.pci_0.acc_cntl_options[i] =
+ MV64360_PCI_ACC_CNTL_SNOOP_WB |
+ MV64360_PCI_ACC_CNTL_SWAP_NONE |
+ MV64360_PCI_ACC_CNTL_MBURST_32_BYTES |
+ MV64360_PCI_ACC_CNTL_RDSIZE_256_BYTES;
+
+ si.pci_1.acc_cntl_options[i] =
+ MV64360_PCI_ACC_CNTL_SNOOP_WB |
+ MV64360_PCI_ACC_CNTL_SWAP_NONE |
+ MV64360_PCI_ACC_CNTL_MBURST_32_BYTES |
+ MV64360_PCI_ACC_CNTL_RDSIZE_256_BYTES;
+#endif
+ }
+
+ hdpu_cpustate_set(CPUSTATE_KERNEL_MAJOR | CPUSTATE_KERNEL_INIT_PCI);
+
+ /* Lookup PCI host bridges */
+ mv64x60_init(&bh, &si);
+ pci_dram_offset = 0; /* System mem at same addr on PCI & cpu bus */
+ ppc_md.pci_swizzle = common_swizzle;
+ ppc_md.pci_map_irq = hdpu_map_irq;
+
+ mv64x60_set_bus(&bh, 0, 0);
+ bh.hose_a->first_busno = 0;
+ bh.hose_a->last_busno = 0xff;
+ bh.hose_a->last_busno = pciauto_bus_scan(bh.hose_a, 0);
+
+ bh.hose_b->first_busno = bh.hose_a->last_busno + 1;
+ mv64x60_set_bus(&bh, 1, bh.hose_b->first_busno);
+ bh.hose_b->last_busno = 0xff;
+ bh.hose_b->last_busno = pciauto_bus_scan(bh.hose_b,
+ bh.hose_b->first_busno);
+
+ ppc_md.pci_exclude_device = mv64x60_pci_exclude_device;
+
+ hdpu_cpustate_set(CPUSTATE_KERNEL_MAJOR | CPUSTATE_KERNEL_INIT_REG);
+ /*
+ * Enabling of PCI internal-vs-external arbitration
+ * is a platform- and errata-dependent decision.
+ */
+ return;
+}
+
+#if defined(CONFIG_SERIAL_MPSC_CONSOLE)
+static void __init hdpu_early_serial_map(void)
+{
+#ifdef CONFIG_KGDB
+ static char first_time = 1;
+
+#if defined(CONFIG_KGDB_TTYS0)
+#define KGDB_PORT 0
+#elif defined(CONFIG_KGDB_TTYS1)
+#define KGDB_PORT 1
+#else
+#error "Invalid kgdb_tty port"
+#endif
+
+ if (first_time) {
+ gt_early_mpsc_init(KGDB_PORT,
+ B9600 | CS8 | CREAD | HUPCL | CLOCAL);
+ first_time = 0;
+ }
+
+ return;
+#endif
+}
+#endif
+
+static void hdpu_init2(void)
+{
+ return;
+}
+
+#if defined(CONFIG_MV643XX_ETH)
+static void __init hdpu_fixup_eth_pdata(struct platform_device *pd)
+{
+
+ struct mv643xx_eth_platform_data *eth_pd;
+ eth_pd = pd->dev.platform_data;
+
+ eth_pd->port_serial_control =
+ mv64x60_read(&bh, MV643XX_ETH_PORT_SERIAL_CONTROL_REG(pd->id) & ~1);
+
+ eth_pd->force_phy_addr = 1;
+ eth_pd->phy_addr = pd->id;
+ eth_pd->tx_queue_size = 400;
+ eth_pd->rx_queue_size = 800;
+}
+#endif
+
+static void __init hdpu_fixup_mpsc_pdata(struct platform_device *pd)
+{
+
+ struct mpsc_pdata *pdata;
+
+ pdata = (struct mpsc_pdata *)pd->dev.platform_data;
+
+ pdata->max_idle = 40;
+ if (ppcboot_bd_valid)
+ pdata->default_baud = ppcboot_bd.bi_baudrate;
+ else
+ pdata->default_baud = HDPU_DEFAULT_BAUD;
+ pdata->brg_clk_src = HDPU_MPSC_CLK_SRC;
+ pdata->brg_clk_freq = HDPU_MPSC_CLK_FREQ;
+}
+
+#if defined(CONFIG_HDPU_FEATURES)
+static void __init hdpu_fixup_cpustate_pdata(struct platform_device *pd)
+{
+ struct platform_device *pds[1];
+ pds[0] = pd;
+ mv64x60_pd_fixup(&bh, pds, 1);
+}
+#endif
+
+static int __init hdpu_platform_notify(struct device *dev)
+{
+ static struct {
+ char *bus_id;
+ void ((*rtn) (struct platform_device * pdev));
+ } dev_map[] = {
+ {
+ MPSC_CTLR_NAME ".0", hdpu_fixup_mpsc_pdata},
+#if defined(CONFIG_MV643XX_ETH)
+ {
+ MV643XX_ETH_NAME ".0", hdpu_fixup_eth_pdata},
+#endif
+#if defined(CONFIG_HDPU_FEATURES)
+ {
+ HDPU_CPUSTATE_NAME ".0", hdpu_fixup_cpustate_pdata},
+#endif
+ };
+ struct platform_device *pdev;
+ int i;
+
+ if (dev && dev->bus_id)
+ for (i = 0; i < ARRAY_SIZE(dev_map); i++)
+ if (!strncmp(dev->bus_id, dev_map[i].bus_id,
+ BUS_ID_SIZE)) {
+
+ pdev = container_of(dev,
+ struct platform_device,
+ dev);
+ dev_map[i].rtn(pdev);
+ }
+
+ return 0;
+}
+
+static void __init hdpu_setup_arch(void)
+{
+ if (ppc_md.progress)
+ ppc_md.progress("hdpu_setup_arch: enter", 0);
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (initrd_start)
+ ROOT_DEV = Root_RAM0;
+ else
+#endif
+#ifdef CONFIG_ROOT_NFS
+ ROOT_DEV = Root_NFS;
+#else
+ ROOT_DEV = Root_SDA2;
+#endif
+
+ ppc_md.heartbeat = hdpu_heartbeat;
+
+ ppc_md.heartbeat_reset = HZ;
+ ppc_md.heartbeat_count = 1;
+
+ if (ppc_md.progress)
+ ppc_md.progress("hdpu_setup_arch: Enabling L2 cache", 0);
+
+ /* Enable L1 Parity Bits */
+ hdpu_set_l1pe();
+
+ /* Enable L2 and L3 caches (if 745x) */
+ _set_L2CR(0x80080000);
+
+ if (ppc_md.progress)
+ ppc_md.progress("hdpu_setup_arch: enter", 0);
+
+ hdpu_setup_bridge();
+
+ hdpu_setup_peripherals();
+
+#ifdef CONFIG_SERIAL_MPSC_CONSOLE
+ hdpu_early_serial_map();
+#endif
+
+ printk("SKY HDPU Compute Blade \n");
+
+ if (ppc_md.progress)
+ ppc_md.progress("hdpu_setup_arch: exit", 0);
+
+ hdpu_cpustate_set(CPUSTATE_KERNEL_MAJOR | CPUSTATE_KERNEL_OK);
+ return;
+}
+static void __init hdpu_init_irq(void)
+{
+ mv64360_init_irq();
+}
+
+static void __init hdpu_set_l1pe()
+{
+ unsigned long ictrl;
+ asm volatile ("mfspr %0, 1011":"=r" (ictrl):);
+ ictrl |= ICTRL_EICE | ICTRL_EDC | ICTRL_EICP;
+ asm volatile ("mtspr 1011, %0"::"r" (ictrl));
+}
+
+/*
+ * Set BAT 1 to map 0xf1000000 to end of physical memory space.
+ */
+static __inline__ void hdpu_set_bat(void)
+{
+ mb();
+ mtspr(SPRN_DBAT1U, 0xf10001fe);
+ mtspr(SPRN_DBAT1L, 0xf100002a);
+ mb();
+
+ return;
+}
+
+unsigned long __init hdpu_find_end_of_memory(void)
+{
+ return mv64x60_get_mem_size(CONFIG_MV64X60_NEW_BASE,
+ MV64x60_TYPE_MV64360);
+}
+
+static void hdpu_reset_board(void)
+{
+ volatile int infinite = 1;
+
+ hdpu_cpustate_set(CPUSTATE_KERNEL_MAJOR | CPUSTATE_KERNEL_RESET);
+
+ local_irq_disable();
+
+ /* Clear all the LEDs */
+ mv64x60_write(&bh, MV64x60_GPP_VALUE_CLR, ((1 << 4) |
+ (1 << 5) | (1 << 6)));
+
+ /* disable and invalidate the L2 cache */
+ _set_L2CR(0);
+ _set_L2CR(0x200000);
+
+ /* flush and disable L1 I/D cache */
+ __asm__ __volatile__
+ ("\n"
+ "mfspr 3,1008\n"
+ "ori 5,5,0xcc00\n"
+ "ori 4,3,0xc00\n"
+ "andc 5,3,5\n"
+ "sync\n"
+ "mtspr 1008,4\n"
+ "isync\n" "sync\n" "mtspr 1008,5\n" "isync\n" "sync\n");
+
+ /* Hit the reset bit */
+ mv64x60_write(&bh, MV64x60_GPP_VALUE_CLR, (1 << 3));
+
+ while (infinite)
+ infinite = infinite;
+
+ return;
+}
+
+static void hdpu_restart(char *cmd)
+{
+ volatile ulong i = 10000000;
+
+ hdpu_reset_board();
+
+ while (i-- > 0) ;
+ panic("restart failed\n");
+}
+
+static void hdpu_halt(void)
+{
+ local_irq_disable();
+
+ hdpu_cpustate_set(CPUSTATE_KERNEL_MAJOR | CPUSTATE_KERNEL_HALT);
+
+ /* Clear all the LEDs */
+ mv64x60_write(&bh, MV64x60_GPP_VALUE_CLR, ((1 << 4) | (1 << 5) |
+ (1 << 6)));
+ while (1) ;
+ /* NOTREACHED */
+}
+
+static void hdpu_power_off(void)
+{
+ hdpu_halt();
+ /* NOTREACHED */
+}
+
+static int hdpu_show_cpuinfo(struct seq_file *m)
+{
+ uint pvid;
+
+ pvid = mfspr(SPRN_PVR);
+ seq_printf(m, "vendor\t\t: Sky Computers\n");
+ seq_printf(m, "machine\t\t: HDPU Compute Blade\n");
+ seq_printf(m, "PVID\t\t: 0x%x, vendor: %s\n",
+ pvid, (pvid & (1 << 15) ? "IBM" : "Motorola"));
+
+ return 0;
+}
+
+static void __init hdpu_calibrate_decr(void)
+{
+ ulong freq;
+
+ if (ppcboot_bd_valid)
+ freq = ppcboot_bd.bi_busfreq / 4;
+ else
+ freq = 133000000;
+
+ printk("time_init: decrementer frequency = %lu.%.6lu MHz\n",
+ freq / 1000000, freq % 1000000);
+
+ tb_ticks_per_jiffy = freq / HZ;
+ tb_to_us = mulhwu_scale_factor(freq, 1000000);
+
+ return;
+}
+
+static void parse_bootinfo(unsigned long r3,
+ unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7)
+{
+ bd_t *bd = NULL;
+ char *cmdline_start = NULL;
+ int cmdline_len = 0;
+
+ if (r3) {
+ if ((r3 & 0xf0000000) == 0)
+ r3 += KERNELBASE;
+ if ((r3 & 0xf0000000) == KERNELBASE) {
+ bd = (void *)r3;
+
+ memcpy(&ppcboot_bd, bd, sizeof(ppcboot_bd));
+ ppcboot_bd_valid = 1;
+ }
+ }
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (r4 && r5 && r5 > r4) {
+ if ((r4 & 0xf0000000) == 0)
+ r4 += KERNELBASE;
+ if ((r5 & 0xf0000000) == 0)
+ r5 += KERNELBASE;
+ if ((r4 & 0xf0000000) == KERNELBASE) {
+ initrd_start = r4;
+ initrd_end = r5;
+ initrd_below_start_ok = 1;
+ }
+ }
+#endif /* CONFIG_BLK_DEV_INITRD */
+
+ if (r6 && r7 && r7 > r6) {
+ if ((r6 & 0xf0000000) == 0)
+ r6 += KERNELBASE;
+ if ((r7 & 0xf0000000) == 0)
+ r7 += KERNELBASE;
+ if ((r6 & 0xf0000000) == KERNELBASE) {
+ cmdline_start = (void *)r6;
+ cmdline_len = (r7 - r6);
+ strncpy(cmd_line, cmdline_start, cmdline_len);
+ }
+ }
+}
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+static int hdpu_ide_check_region(ide_ioreg_t from, unsigned int extent)
+{
+ return check_region(from, extent);
+}
+
+static void
+hdpu_ide_request_region(ide_ioreg_t from, unsigned int extent, const char *name)
+{
+ request_region(from, extent, name);
+ return;
+}
+
+static void hdpu_ide_release_region(ide_ioreg_t from, unsigned int extent)
+{
+ release_region(from, extent);
+ return;
+}
+
+static void __init
+hdpu_ide_pci_init_hwif_ports(hw_regs_t * hw, ide_ioreg_t data_port,
+ ide_ioreg_t ctrl_port, int *irq)
+{
+ struct pci_dev *dev;
+
+ pci_for_each_dev(dev) {
+ if (((dev->class >> 8) == PCI_CLASS_STORAGE_IDE) ||
+ ((dev->class >> 8) == PCI_CLASS_STORAGE_RAID)) {
+ hw->irq = dev->irq;
+
+ if (irq != NULL) {
+ *irq = dev->irq;
+ }
+ }
+ }
+
+ return;
+}
+#endif
+
+void hdpu_heartbeat(void)
+{
+ if (mv64x60_read(&bh, MV64x60_GPP_VALUE) & (1 << 5))
+ mv64x60_write(&bh, MV64x60_GPP_VALUE_CLR, (1 << 5));
+ else
+ mv64x60_write(&bh, MV64x60_GPP_VALUE_SET, (1 << 5));
+
+ ppc_md.heartbeat_count = ppc_md.heartbeat_reset;
+
+}
+
+static void __init hdpu_map_io(void)
+{
+ io_block_mapping(0xf1000000, 0xf1000000, 0x20000, _PAGE_IO);
+}
+
+#ifdef CONFIG_SMP
+char hdpu_smp0[] = "SMP Cpu #0";
+char hdpu_smp1[] = "SMP Cpu #1";
+
+static irqreturn_t hdpu_smp_cpu0_int_handler(int irq, void *dev_id,
+ struct pt_regs *regs)
+{
+ volatile unsigned int doorbell;
+
+ doorbell = mv64x60_read(&bh, MV64360_CPU0_DOORBELL);
+
+ /* Ack the doorbell interrupts */
+ mv64x60_write(&bh, MV64360_CPU0_DOORBELL_CLR, doorbell);
+
+ if (doorbell & 1) {
+ smp_message_recv(0, regs);
+ }
+ if (doorbell & 2) {
+ smp_message_recv(1, regs);
+ }
+ if (doorbell & 4) {
+ smp_message_recv(2, regs);
+ }
+ if (doorbell & 8) {
+ smp_message_recv(3, regs);
+ }
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t hdpu_smp_cpu1_int_handler(int irq, void *dev_id,
+ struct pt_regs *regs)
+{
+ volatile unsigned int doorbell;
+
+ doorbell = mv64x60_read(&bh, MV64360_CPU1_DOORBELL);
+
+ /* Ack the doorbell interrupts */
+ mv64x60_write(&bh, MV64360_CPU1_DOORBELL_CLR, doorbell);
+
+ if (doorbell & 1) {
+ smp_message_recv(0, regs);
+ }
+ if (doorbell & 2) {
+ smp_message_recv(1, regs);
+ }
+ if (doorbell & 4) {
+ smp_message_recv(2, regs);
+ }
+ if (doorbell & 8) {
+ smp_message_recv(3, regs);
+ }
+ return IRQ_HANDLED;
+}
+
+static void smp_hdpu_CPU_two(void)
+{
+ __asm__ __volatile__
+ ("\n"
+ "lis 3,0x0000\n"
+ "ori 3,3,0x00c0\n"
+ "mtspr 26, 3\n" "li 4,0\n" "mtspr 27,4\n" "rfi");
+
+}
+
+static int smp_hdpu_probe(void)
+{
+ int *cpu_count_reg;
+ int num_cpus = 0;
+
+ cpu_count_reg = ioremap(HDPU_NEXUS_ID_BASE, HDPU_NEXUS_ID_SIZE);
+ if (cpu_count_reg) {
+ num_cpus = (*cpu_count_reg >> 20) & 0x3;
+ iounmap(cpu_count_reg);
+ }
+
+ /* Validate the bits in the CPLD. If we could not map the reg, return 2.
+ * If the register reported 0 or 3, return 2.
+ * Older CPLD revisions set these bits to all ones (val = 3).
+ */
+ if ((num_cpus < 1) || (num_cpus > 2)) {
+ printk
+ ("Unable to determine the number of processors %d . deafulting to 2.\n",
+ num_cpus);
+ num_cpus = 2;
+ }
+ return num_cpus;
+}
+
+static void
+smp_hdpu_message_pass(int target, int msg, unsigned long data, int wait)
+{
+ if (msg > 0x3) {
+ printk("SMP %d: smp_message_pass: unknown msg %d\n",
+ smp_processor_id(), msg);
+ return;
+ }
+ switch (target) {
+ case MSG_ALL:
+ mv64x60_write(&bh, MV64360_CPU0_DOORBELL, 1 << msg);
+ mv64x60_write(&bh, MV64360_CPU1_DOORBELL, 1 << msg);
+ break;
+ case MSG_ALL_BUT_SELF:
+ if (smp_processor_id())
+ mv64x60_write(&bh, MV64360_CPU0_DOORBELL, 1 << msg);
+ else
+ mv64x60_write(&bh, MV64360_CPU1_DOORBELL, 1 << msg);
+ break;
+ default:
+ if (target == 0)
+ mv64x60_write(&bh, MV64360_CPU0_DOORBELL, 1 << msg);
+ else
+ mv64x60_write(&bh, MV64360_CPU1_DOORBELL, 1 << msg);
+ break;
+ }
+}
+
+static void smp_hdpu_kick_cpu(int nr)
+{
+ volatile unsigned int *bootaddr;
+
+ if (ppc_md.progress)
+ ppc_md.progress("smp_hdpu_kick_cpu", 0);
+
+ hdpu_cpustate_set(CPUSTATE_KERNEL_MAJOR | CPUSTATE_KERNEL_CPU1_KICK);
+
+ /* Disable BootCS. Must also reduce the windows size to zero. */
+ bh.ci->disable_window_32bit(&bh, MV64x60_CPU2BOOT_WIN);
+ mv64x60_set_32bit_window(&bh, MV64x60_CPU2BOOT_WIN, 0, 0, 0);
+
+ bootaddr = ioremap(HDPU_INTERNAL_SRAM_BASE, HDPU_INTERNAL_SRAM_SIZE);
+ if (!bootaddr) {
+ if (ppc_md.progress)
+ ppc_md.progress("smp_hdpu_kick_cpu: ioremap failed", 0);
+ return;
+ }
+
+ memcpy((void *)(bootaddr + 0x40), (void *)&smp_hdpu_CPU_two, 0x20);
+
+ /* map SRAM to 0xfff00000 */
+ bh.ci->disable_window_32bit(&bh, MV64x60_CPU2SRAM_WIN);
+
+ mv64x60_set_32bit_window(&bh, MV64x60_CPU2SRAM_WIN,
+ 0xfff00000, HDPU_INTERNAL_SRAM_SIZE, 0);
+ bh.ci->enable_window_32bit(&bh, MV64x60_CPU2SRAM_WIN);
+
+ /* Enable CPU1 arbitration */
+ mv64x60_clr_bits(&bh, MV64x60_CPU_MASTER_CNTL, (1 << 9));
+
+ /*
+ * Wait 100mSecond until other CPU has reached __secondary_start.
+ * When it reaches, it is permittable to rever the SRAM mapping etc...
+ */
+ mdelay(100);
+ *(unsigned long *)KERNELBASE = nr;
+ asm volatile ("dcbf 0,%0"::"r" (KERNELBASE):"memory");
+
+ iounmap(bootaddr);
+
+ /* Set up window for internal sram (256KByte insize) */
+ bh.ci->disable_window_32bit(&bh, MV64x60_CPU2SRAM_WIN);
+ mv64x60_set_32bit_window(&bh, MV64x60_CPU2SRAM_WIN,
+ HDPU_INTERNAL_SRAM_BASE,
+ HDPU_INTERNAL_SRAM_SIZE, 0);
+ bh.ci->enable_window_32bit(&bh, MV64x60_CPU2SRAM_WIN);
+ /*
+ * Set up windows for embedded FLASH (using boot CS window).
+ */
+
+ bh.ci->disable_window_32bit(&bh, MV64x60_CPU2BOOT_WIN);
+ mv64x60_set_32bit_window(&bh, MV64x60_CPU2BOOT_WIN,
+ HDPU_EMB_FLASH_BASE, HDPU_EMB_FLASH_SIZE, 0);
+ bh.ci->enable_window_32bit(&bh, MV64x60_CPU2BOOT_WIN);
+}
+
+static void smp_hdpu_setup_cpu(int cpu_nr)
+{
+ if (cpu_nr == 0) {
+ if (ppc_md.progress)
+ ppc_md.progress("smp_hdpu_setup_cpu 0", 0);
+ mv64x60_write(&bh, MV64360_CPU0_DOORBELL_CLR, 0xff);
+ mv64x60_write(&bh, MV64360_CPU0_DOORBELL_MASK, 0xff);
+ request_irq(60, hdpu_smp_cpu0_int_handler,
+ SA_INTERRUPT, hdpu_smp0, 0);
+ }
+
+ if (cpu_nr == 1) {
+ if (ppc_md.progress)
+ ppc_md.progress("smp_hdpu_setup_cpu 1", 0);
+
+ hdpu_cpustate_set(CPUSTATE_KERNEL_MAJOR |
+ CPUSTATE_KERNEL_CPU1_OK);
+
+ /* Enable L1 Parity Bits */
+ hdpu_set_l1pe();
+
+ /* Enable L2 cache */
+ _set_L2CR(0);
+ _set_L2CR(0x80080000);
+
+ mv64x60_write(&bh, MV64360_CPU1_DOORBELL_CLR, 0x0);
+ mv64x60_write(&bh, MV64360_CPU1_DOORBELL_MASK, 0xff);
+ request_irq(28, hdpu_smp_cpu1_int_handler,
+ SA_INTERRUPT, hdpu_smp1, 0);
+ }
+
+}
+
+void __devinit hdpu_tben_give()
+{
+ volatile unsigned long *val = 0;
+
+ /* By writing 0 to the TBEN_BASE, the timebases is frozen */
+ val = ioremap(HDPU_TBEN_BASE, 4);
+ *val = 0;
+ mb();
+
+ spin_lock(&timebase_lock);
+ timebase_upper = get_tbu();
+ timebase_lower = get_tbl();
+ spin_unlock(&timebase_lock);
+
+ while (timebase_upper || timebase_lower)
+ barrier();
+
+ /* By writing 1 to the TBEN_BASE, the timebases is thawed */
+ *val = 1;
+ mb();
+
+ iounmap(val);
+
+}
+
+void __devinit hdpu_tben_take()
+{
+ while (!(timebase_upper || timebase_lower))
+ barrier();
+
+ spin_lock(&timebase_lock);
+ set_tb(timebase_upper, timebase_lower);
+ timebase_upper = 0;
+ timebase_lower = 0;
+ spin_unlock(&timebase_lock);
+}
+
+static struct smp_ops_t hdpu_smp_ops = {
+ .message_pass = smp_hdpu_message_pass,
+ .probe = smp_hdpu_probe,
+ .kick_cpu = smp_hdpu_kick_cpu,
+ .setup_cpu = smp_hdpu_setup_cpu,
+ .give_timebase = hdpu_tben_give,
+ .take_timebase = hdpu_tben_take,
+};
+#endif /* CONFIG_SMP */
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7)
+{
+ parse_bootinfo(r3, r4, r5, r6, r7);
+
+ isa_mem_base = 0;
+
+ ppc_md.setup_arch = hdpu_setup_arch;
+ ppc_md.init = hdpu_init2;
+ ppc_md.show_cpuinfo = hdpu_show_cpuinfo;
+ ppc_md.init_IRQ = hdpu_init_irq;
+ ppc_md.get_irq = mv64360_get_irq;
+ ppc_md.restart = hdpu_restart;
+ ppc_md.power_off = hdpu_power_off;
+ ppc_md.halt = hdpu_halt;
+ ppc_md.find_end_of_memory = hdpu_find_end_of_memory;
+ ppc_md.calibrate_decr = hdpu_calibrate_decr;
+ ppc_md.setup_io_mappings = hdpu_map_io;
+
+ bh.p_base = CONFIG_MV64X60_NEW_BASE;
+ bh.v_base = (unsigned long *)bh.p_base;
+
+ hdpu_set_bat();
+
+#if defined(CONFIG_SERIAL_TEXT_DEBUG)
+ ppc_md.progress = hdpu_mpsc_progress; /* embedded UART */
+ mv64x60_progress_init(bh.p_base);
+#endif /* CONFIG_SERIAL_TEXT_DEBUG */
+
+#ifdef CONFIG_SMP
+ ppc_md.smp_ops = &hdpu_smp_ops;
+#endif /* CONFIG_SMP */
+
+#if defined(CONFIG_SERIAL_MPSC) || defined(CONFIG_MV643XX_ETH)
+ platform_notify = hdpu_platform_notify;
+#endif
+ return;
+}
+
+#if defined(CONFIG_SERIAL_TEXT_DEBUG) && defined(CONFIG_SERIAL_MPSC_CONSOLE)
+/* SMP safe version of the serial text debug routine. Uses Semaphore 0 */
+void hdpu_mpsc_progress(char *s, unsigned short hex)
+{
+ while (mv64x60_read(&bh, MV64360_WHO_AM_I) !=
+ mv64x60_read(&bh, MV64360_SEMAPHORE_0)) {
+ }
+ mv64x60_mpsc_progress(s, hex);
+ mv64x60_write(&bh, MV64360_SEMAPHORE_0, 0xff);
+}
+#endif
+
+static void hdpu_cpustate_set(unsigned char new_state)
+{
+ unsigned int state = (new_state << 21);
+ mv64x60_write(&bh, MV64x60_GPP_VALUE_CLR, (0xff << 21));
+ mv64x60_write(&bh, MV64x60_GPP_VALUE_CLR, state);
+}
+
+#ifdef CONFIG_MTD_PHYSMAP
+static struct mtd_partition hdpu_partitions[] = {
+ {
+ .name = "Root FS",
+ .size = 0x03400000,
+ .offset = 0,
+ .mask_flags = 0,
+ },{
+ .name = "User FS",
+ .size = 0x00800000,
+ .offset = 0x03400000,
+ .mask_flags = 0,
+ },{
+ .name = "Kernel Image",
+ .size = 0x002C0000,
+ .offset = 0x03C00000,
+ .mask_flags = 0,
+ },{
+ .name = "bootEnv",
+ .size = 0x00040000,
+ .offset = 0x03EC0000,
+ .mask_flags = 0,
+ },{
+ .name = "bootROM",
+ .size = 0x00100000,
+ .offset = 0x03F00000,
+ .mask_flags = 0,
+ }
+};
+
+static int __init hdpu_setup_mtd(void)
+{
+
+ physmap_set_partitions(hdpu_partitions, 5);
+ return 0;
+}
+
+arch_initcall(hdpu_setup_mtd);
+#endif
+
+#ifdef CONFIG_HDPU_FEATURES
+
+static struct resource hdpu_cpustate_resources[] = {
+ [0] = {
+ .name = "addr base",
+ .start = MV64x60_GPP_VALUE_SET,
+ .end = MV64x60_GPP_VALUE_CLR + 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct resource hdpu_nexus_resources[] = {
+ [0] = {
+ .name = "nexus register",
+ .start = HDPU_NEXUS_ID_BASE,
+ .end = HDPU_NEXUS_ID_BASE + HDPU_NEXUS_ID_SIZE,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device hdpu_cpustate_device = {
+ .name = HDPU_CPUSTATE_NAME,
+ .id = 0,
+ .num_resources = ARRAY_SIZE(hdpu_cpustate_resources),
+ .resource = hdpu_cpustate_resources,
+};
+
+static struct platform_device hdpu_nexus_device = {
+ .name = HDPU_NEXUS_NAME,
+ .id = 0,
+ .num_resources = ARRAY_SIZE(hdpu_nexus_resources),
+ .resource = hdpu_nexus_resources,
+};
+
+static int __init hdpu_add_pds(void)
+{
+ platform_device_register(&hdpu_cpustate_device);
+ platform_device_register(&hdpu_nexus_device);
+ return 0;
+}
+
+arch_initcall(hdpu_add_pds);
+#endif
diff --git a/arch/ppc/platforms/hdpu.h b/arch/ppc/platforms/hdpu.h
new file mode 100644
index 0000000000000..07c3cffb5c7b7
--- /dev/null
+++ b/arch/ppc/platforms/hdpu.h
@@ -0,0 +1,82 @@
+/*
+ * arch/ppc/platforms/hdpu.h
+ *
+ * Definitions for Sky Computers HDPU board.
+ *
+ * Brian Waite <waite@skycomputers.com>
+ *
+ * Based on code done by Rabeeh Khoury - rabeeh@galileo.co.il
+ * Based on code done by Mark A. Greer <mgreer@mvista.com>
+ * Based on code done by Tim Montgomery <timm@artesyncp.com>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+/*
+ * The MV64360 has 2 PCI buses each with 1 window from the CPU bus to
+ * PCI I/O space and 4 windows from the CPU bus to PCI MEM space.
+ * We'll only use one PCI MEM window on each PCI bus.
+ *
+ * This is the CPU physical memory map (windows must be at least 64K and start
+ * on a boundary that is a multiple of the window size):
+ *
+ * 0x80000000-0x8fffffff - PCI 0 MEM
+ * 0xa0000000-0xafffffff - PCI 1 MEM
+ * 0xc0000000-0xc0ffffff - PCI 0 I/O
+ * 0xc1000000-0xc1ffffff - PCI 1 I/O
+
+ * 0xf1000000-0xf100ffff - MV64360 Registers
+ * 0xf1010000-0xfb9fffff - HOLE
+ * 0xfbfa0000-0xfbfaffff - TBEN
+ * 0xfbf00000-0xfbfbffff - NEXUS
+ * 0xfbfc0000-0xfbffffff - Internal SRAM
+ * 0xfc000000-0xffffffff - Boot window
+ */
+
+#ifndef __PPC_PLATFORMS_HDPU_H
+#define __PPC_PLATFORMS_HDPU_H
+
+/* CPU Physical Memory Map setup. */
+#define HDPU_BRIDGE_REG_BASE 0xf1000000
+
+#define HDPU_TBEN_BASE 0xfbfa0000
+#define HDPU_TBEN_SIZE 0x00010000
+#define HDPU_NEXUS_ID_BASE 0xfbfb0000
+#define HDPU_NEXUS_ID_SIZE 0x00010000
+#define HDPU_INTERNAL_SRAM_BASE 0xfbfc0000
+#define HDPU_INTERNAL_SRAM_SIZE 0x00040000
+#define HDPU_EMB_FLASH_BASE 0xfc000000
+#define HDPU_EMB_FLASH_SIZE 0x04000000
+
+/* PCI Mappings */
+
+#define HDPU_PCI0_MEM_START_PROC_ADDR 0x80000000
+#define HDPU_PCI0_MEM_START_PCI_HI_ADDR 0x00000000
+#define HDPU_PCI0_MEM_START_PCI_LO_ADDR HDPU_PCI0_MEM_START_PROC_ADDR
+#define HDPU_PCI0_MEM_SIZE 0x10000000
+
+#define HDPU_PCI1_MEM_START_PROC_ADDR 0xc0000000
+#define HDPU_PCI1_MEM_START_PCI_HI_ADDR 0x00000000
+#define HDPU_PCI1_MEM_START_PCI_LO_ADDR HDPU_PCI1_MEM_START_PROC_ADDR
+#define HDPU_PCI1_MEM_SIZE 0x20000000
+
+#define HDPU_PCI0_IO_START_PROC_ADDR 0xc0000000
+#define HDPU_PCI0_IO_START_PCI_ADDR 0x00000000
+#define HDPU_PCI0_IO_SIZE 0x01000000
+
+#define HDPU_PCI1_IO_START_PROC_ADDR 0xc1000000
+#define HDPU_PCI1_IO_START_PCI_ADDR 0x01000000
+#define HDPU_PCI1_IO_SIZE 0x01000000
+
+#define HDPU_DEFAULT_BAUD 115200
+#define HDPU_MPSC_CLK_SRC 8 /* TCLK */
+#define HDPU_MPSC_CLK_FREQ 133000000 /* 133 Mhz */
+
+#define HDPU_PCI_0_IRQ (8+64)
+#define HDPU_PCI_1_IRQ (13+64)
+
+#endif /* __PPC_PLATFORMS_HDPU_H */
diff --git a/arch/ppc/platforms/k2.c b/arch/ppc/platforms/k2.c
index be5c0511ffb94..aacb438708fff 100644
--- a/arch/ppc/platforms/k2.c
+++ b/arch/ppc/platforms/k2.c
@@ -392,9 +392,9 @@ static int k2_get_cpu_speed(void)
unsigned long hid1;
int cpu_speed;
- hid1 = mfspr(HID1) >> 28;
+ hid1 = mfspr(SPRN_HID1) >> 28;
- if ((mfspr(PVR) >> 16) == 8)
+ if ((mfspr(SPRN_PVR) >> 16) == 8)
hid1 = cpu_7xx[hid1];
else
hid1 = cpu_6xx[hid1];
@@ -472,7 +472,7 @@ static void __init k2_setup_arch(void)
"(source@mvista.com)\n");
/* Identify the CPU manufacturer */
- cpu = PVR_REV(mfspr(PVR));
+ cpu = PVR_REV(mfspr(SPRN_PVR));
printk(KERN_INFO "CPU manufacturer: %s [rev=%04x]\n",
(cpu & (1 << 15)) ? "IBM" : "Motorola", cpu);
}
@@ -486,8 +486,8 @@ static void k2_restart(char *cmd)
/* SRR0 has system reset vector, SRR1 has default MSR value */
/* rfi restores MSR from SRR1 and sets the PC to the SRR0 value */
- mtspr(SRR0, 0xfff00100);
- mtspr(SRR1, 0);
+ mtspr(SPRN_SRR0, 0xfff00100);
+ mtspr(SPRN_SRR1, 0);
__asm__ __volatile__("rfi\n\t");
/* not reached */
@@ -513,10 +513,10 @@ static __inline__ void k2_set_bat(void)
mb();
/* setup DBATs */
- mtspr(DBAT2U, 0x80001ffe);
- mtspr(DBAT2L, 0x8000002a);
- mtspr(DBAT3U, 0xf0001ffe);
- mtspr(DBAT3L, 0xf000002a);
+ mtspr(SPRN_DBAT2U, 0x80001ffe);
+ mtspr(SPRN_DBAT2L, 0x8000002a);
+ mtspr(SPRN_DBAT3U, 0xf0001ffe);
+ mtspr(SPRN_DBAT3L, 0xf000002a);
/* wait for updates */
mb();
diff --git a/arch/ppc/platforms/katana.c b/arch/ppc/platforms/katana.c
index bad8f27fa614d..eda922ac31677 100644
--- a/arch/ppc/platforms/katana.c
+++ b/arch/ppc/platforms/katana.c
@@ -1,9 +1,10 @@
/*
* arch/ppc/platforms/katana.c
*
- * Board setup routines for the Artesyn Katana 750 based boards.
+ * Board setup routines for the Artesyn Katana cPCI boards.
*
- * Tim Montgomery <timm@artesyncp.com>
+ * Author: Tim Montgomery <timm@artesyncp.com>
+ * Maintained by: Mark A. Greer <mgreer@mvista.com>
*
* Based on code done by Rabeeh Khoury - rabeeh@galileo.co.il
* Based on code done by - Mark A. Greer <mgreer@mvista.com>
@@ -26,7 +27,8 @@
#include <linux/root_dev.h>
#include <linux/delay.h>
#include <linux/seq_file.h>
-#include <linux/smp.h>
+#include <linux/bootmem.h>
+#include <linux/mtd/physmap.h>
#include <linux/mv643xx.h>
#ifdef CONFIG_BOOTIMG
#include <linux/bootimg.h>
@@ -36,13 +38,21 @@
#include <asm/smp.h>
#include <asm/todc.h>
#include <asm/bootinfo.h>
+#include <asm/ppcboot.h>
#include <asm/mv64x60.h>
#include <platforms/katana.h>
static struct mv64x60_handle bh;
static katana_id_t katana_id;
-static u32 cpld_base;
-static u32 sram_base;
+static void __iomem *cpld_base;
+static void __iomem *sram_base;
+
+static u32 katana_flash_size_0;
+static u32 katana_flash_size_1;
+
+static u32 katana_bus_frequency;
+
+unsigned char __res[sizeof(bd_t)];
/* PCI Interrupt routing */
static int __init
@@ -105,7 +115,7 @@ katana_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
void __init
katana_get_board_id(void)
{
- switch (in_8((volatile char *)(cpld_base + KATANA_CPLD_PRODUCT_ID))) {
+ switch (in_8(cpld_base + KATANA_CPLD_PRODUCT_ID)) {
case KATANA_PRODUCT_ID_3750:
katana_id = KATANA_ID_3750;
break;
@@ -170,50 +180,107 @@ katana_get_proc_num(void)
static inline int
katana_is_monarch(void)
{
- return in_8((volatile char *)(cpld_base + KATANA_CPLD_BD_CFG_3)) &
+ return in_8(cpld_base + KATANA_CPLD_BD_CFG_3) &
KATANA_CPLD_BD_CFG_3_MONARCH;
}
static void __init
-katana_enable_ipmi(void)
+katana_setup_bridge(void)
{
- u8 reset_out;
+ struct pci_controller hose;
+ struct mv64x60_setup_info si;
+ void __iomem *vaddr;
+ int i;
+ u16 val;
+ u8 save_exclude;
- /* Enable access to IPMI ctlr by clearing IPMI PORTSEL bit in CPLD */
- reset_out = in_8((volatile char *)(cpld_base + KATANA_CPLD_RESET_OUT));
- reset_out &= ~KATANA_CPLD_RESET_OUT_PORTSEL;
- out_8((volatile void *)(cpld_base + KATANA_CPLD_RESET_OUT), reset_out);
- return;
-}
+ /*
+ * Some versions of the Katana firmware mistakenly change the vendor
+ * & device id fields in the bridge's pci device (visible via pci
+ * config accesses). This breaks mv64x60_init() because those values
+ * are used to identify the type of bridge that's there. Artesyn
+ * claims that the subsystem vendor/device id's will have the correct
+ * Marvell values so this code puts back the correct values from there.
+ */
+ memset(&hose, 0, sizeof(hose));
+ vaddr = ioremap(CONFIG_MV64X60_NEW_BASE, MV64x60_INTERNAL_SPACE_SIZE);
+ setup_indirect_pci_nomap(&hose, vaddr + MV64x60_PCI0_CONFIG_ADDR,
+ vaddr + MV64x60_PCI0_CONFIG_DATA);
+ save_exclude = mv64x60_pci_exclude_bridge;
+ mv64x60_pci_exclude_bridge = 0;
+
+ early_read_config_word(&hose, 0, PCI_DEVFN(0, 0), PCI_VENDOR_ID, &val);
+
+ if (val != PCI_VENDOR_ID_MARVELL) {
+ early_read_config_word(&hose, 0, PCI_DEVFN(0, 0),
+ PCI_SUBSYSTEM_VENDOR_ID, &val);
+ early_write_config_word(&hose, 0, PCI_DEVFN(0, 0),
+ PCI_VENDOR_ID, val);
+ early_read_config_word(&hose, 0, PCI_DEVFN(0, 0),
+ PCI_SUBSYSTEM_ID, &val);
+ early_write_config_word(&hose, 0, PCI_DEVFN(0, 0),
+ PCI_DEVICE_ID, val);
+ }
-static unsigned long
-katana_bus_freq(void)
-{
- u8 bd_cfg_0;
+ mv64x60_pci_exclude_bridge = save_exclude;
+ iounmap(vaddr);
- bd_cfg_0 = in_8((volatile char *)(cpld_base + KATANA_CPLD_BD_CFG_0));
+ memset(&si, 0, sizeof(si));
- switch (bd_cfg_0 & KATANA_CPLD_BD_CFG_0_SYSCLK_MASK) {
- case KATANA_CPLD_BD_CFG_0_SYSCLK_200:
- return 200000000;
- break;
+ si.phys_reg_base = CONFIG_MV64X60_NEW_BASE;
- case KATANA_CPLD_BD_CFG_0_SYSCLK_166:
- return 166666666;
- break;
+ si.pci_1.enable_bus = 1;
+ si.pci_1.pci_io.cpu_base = KATANA_PCI1_IO_START_PROC_ADDR;
+ si.pci_1.pci_io.pci_base_hi = 0;
+ si.pci_1.pci_io.pci_base_lo = KATANA_PCI1_IO_START_PCI_ADDR;
+ si.pci_1.pci_io.size = KATANA_PCI1_IO_SIZE;
+ si.pci_1.pci_io.swap = MV64x60_CPU2PCI_SWAP_NONE;
+ si.pci_1.pci_mem[0].cpu_base = KATANA_PCI1_MEM_START_PROC_ADDR;
+ si.pci_1.pci_mem[0].pci_base_hi = KATANA_PCI1_MEM_START_PCI_HI_ADDR;
+ si.pci_1.pci_mem[0].pci_base_lo = KATANA_PCI1_MEM_START_PCI_LO_ADDR;
+ si.pci_1.pci_mem[0].size = KATANA_PCI1_MEM_SIZE;
+ si.pci_1.pci_mem[0].swap = MV64x60_CPU2PCI_SWAP_NONE;
+ si.pci_1.pci_cmd_bits = 0;
+ si.pci_1.latency_timer = 0x80;
- case KATANA_CPLD_BD_CFG_0_SYSCLK_133:
- return 133333333;
- break;
+ for (i = 0; i < MV64x60_CPU2MEM_WINDOWS; i++) {
+#if defined(CONFIG_NOT_COHERENT_CACHE)
+ si.cpu_prot_options[i] = 0;
+ si.enet_options[i] = MV64360_ENET2MEM_SNOOP_NONE;
+ si.mpsc_options[i] = MV64360_MPSC2MEM_SNOOP_NONE;
+ si.idma_options[i] = MV64360_IDMA2MEM_SNOOP_NONE;
- case KATANA_CPLD_BD_CFG_0_SYSCLK_100:
- return 100000000;
- break;
+ si.pci_1.acc_cntl_options[i] =
+ MV64360_PCI_ACC_CNTL_SNOOP_NONE |
+ MV64360_PCI_ACC_CNTL_SWAP_NONE |
+ MV64360_PCI_ACC_CNTL_MBURST_128_BYTES |
+ MV64360_PCI_ACC_CNTL_RDSIZE_256_BYTES;
+#else
+ si.cpu_prot_options[i] = 0;
+ si.enet_options[i] = MV64360_ENET2MEM_SNOOP_NONE; /* errata */
+ si.mpsc_options[i] = MV64360_MPSC2MEM_SNOOP_NONE; /* errata */
+ si.idma_options[i] = MV64360_IDMA2MEM_SNOOP_NONE; /* errata */
- default:
- return 133333333;
- break;
+ si.pci_1.acc_cntl_options[i] =
+ MV64360_PCI_ACC_CNTL_SNOOP_WB |
+ MV64360_PCI_ACC_CNTL_SWAP_NONE |
+ MV64360_PCI_ACC_CNTL_MBURST_32_BYTES |
+ MV64360_PCI_ACC_CNTL_RDSIZE_32_BYTES;
+#endif
}
+
+ /* Lookup PCI host bridges */
+ if (mv64x60_init(&bh, &si))
+ printk(KERN_WARNING "Bridge initialization failed.\n");
+
+ pci_dram_offset = 0; /* sys mem at same addr on PCI & cpu bus */
+ ppc_md.pci_swizzle = common_swizzle;
+ ppc_md.pci_map_irq = katana_map_irq;
+ ppc_md.pci_exclude_device = mv64x60_pci_exclude_device;
+
+ mv64x60_set_bus(&bh, 1, 0);
+ bh.hose_b->first_busno = 0;
+ bh.hose_b->last_busno = 0xff;
}
/* Bridge & platform setup routines */
@@ -263,13 +330,12 @@ katana_intr_setup(void)
* BIT25 summarizes GPP interrupts 8-15
*/
mv64x60_set_bits(&bh, MV64360_IC_CPU0_INTR_MASK_HI, (1<<25));
- return;
}
void __init
katana_setup_peripherals(void)
{
- u32 base, size_0, size_1;
+ u32 base;
/* Set up windows for boot CS, soldered & socketed flash, and CPLD */
mv64x60_set_32bit_window(&bh, MV64x60_CPU2BOOT_WIN,
@@ -277,19 +343,22 @@ katana_setup_peripherals(void)
bh.ci->enable_window_32bit(&bh, MV64x60_CPU2BOOT_WIN);
/* Assume firmware set up window sizes correctly for dev 0 & 1 */
- mv64x60_get_32bit_window(&bh, MV64x60_CPU2DEV_0_WIN, &base, &size_0);
+ mv64x60_get_32bit_window(&bh, MV64x60_CPU2DEV_0_WIN, &base,
+ &katana_flash_size_0);
- if (size_0 > 0) {
+ if (katana_flash_size_0 > 0) {
mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_0_WIN,
- KATANA_SOLDERED_FLASH_BASE, size_0, 0);
+ KATANA_SOLDERED_FLASH_BASE, katana_flash_size_0, 0);
bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_0_WIN);
}
- mv64x60_get_32bit_window(&bh, MV64x60_CPU2DEV_1_WIN, &base, &size_1);
+ mv64x60_get_32bit_window(&bh, MV64x60_CPU2DEV_1_WIN, &base,
+ &katana_flash_size_1);
- if (size_1 > 0) {
+ if (katana_flash_size_1 > 0) {
mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_1_WIN,
- (KATANA_SOLDERED_FLASH_BASE + size_0), size_1, 0);
+ (KATANA_SOLDERED_FLASH_BASE + katana_flash_size_0),
+ katana_flash_size_1, 0);
bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_1_WIN);
}
@@ -300,12 +369,12 @@ katana_setup_peripherals(void)
mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_3_WIN,
KATANA_CPLD_BASE, KATANA_CPLD_SIZE, 0);
bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_3_WIN);
- cpld_base = (u32)ioremap(KATANA_CPLD_BASE, KATANA_CPLD_SIZE);
+ cpld_base = ioremap(KATANA_CPLD_BASE, KATANA_CPLD_SIZE);
mv64x60_set_32bit_window(&bh, MV64x60_CPU2SRAM_WIN,
KATANA_INTERNAL_SRAM_BASE, MV64360_SRAM_SIZE, 0);
bh.ci->enable_window_32bit(&bh, MV64x60_CPU2SRAM_WIN);
- sram_base = (u32)ioremap(KATANA_INTERNAL_SRAM_BASE, MV64360_SRAM_SIZE);
+ sram_base = ioremap(KATANA_INTERNAL_SRAM_BASE, MV64360_SRAM_SIZE);
/* Set up Enet->SRAM window */
mv64x60_set_32bit_window(&bh, MV64x60_ENET2MEM_4_WIN,
@@ -339,79 +408,22 @@ katana_setup_peripherals(void)
* internal data path in SRAM since it's first time accessing it
* while after reset it's not configured.
*/
- memset((void *)sram_base, 0, MV64360_SRAM_SIZE);
+ memset(sram_base, 0, MV64360_SRAM_SIZE);
/* Only processor zero [on 3750] is an PCI interrupt controller */
if (katana_get_proc_num() == 0)
katana_intr_setup();
-
- return;
}
static void __init
-katana_setup_bridge(void)
+katana_enable_ipmi(void)
{
- struct mv64x60_setup_info si;
- int i;
-
- memset(&si, 0, sizeof(si));
-
- si.phys_reg_base = KATANA_BRIDGE_REG_BASE;
-
- si.pci_1.enable_bus = 1;
- si.pci_1.pci_io.cpu_base = KATANA_PCI1_IO_START_PROC_ADDR;
- si.pci_1.pci_io.pci_base_hi = 0;
- si.pci_1.pci_io.pci_base_lo = KATANA_PCI1_IO_START_PCI_ADDR;
- si.pci_1.pci_io.size = KATANA_PCI1_IO_SIZE;
- si.pci_1.pci_io.swap = MV64x60_CPU2PCI_SWAP_NONE;
- si.pci_1.pci_mem[0].cpu_base = KATANA_PCI1_MEM_START_PROC_ADDR;
- si.pci_1.pci_mem[0].pci_base_hi = KATANA_PCI1_MEM_START_PCI_HI_ADDR;
- si.pci_1.pci_mem[0].pci_base_lo = KATANA_PCI1_MEM_START_PCI_LO_ADDR;
- si.pci_1.pci_mem[0].size = KATANA_PCI1_MEM_SIZE;
- si.pci_1.pci_mem[0].swap = MV64x60_CPU2PCI_SWAP_NONE;
- si.pci_1.pci_cmd_bits = 0;
- si.pci_1.latency_timer = 0x80;
-
- for (i = 0; i < MV64x60_CPU2MEM_WINDOWS; i++) {
-#if defined(CONFIG_NOT_COHERENT_CACHE)
- si.cpu_prot_options[i] = 0;
- si.enet_options[i] = MV64360_ENET2MEM_SNOOP_NONE;
- si.mpsc_options[i] = MV64360_MPSC2MEM_SNOOP_NONE;
- si.idma_options[i] = MV64360_IDMA2MEM_SNOOP_NONE;
-
- si.pci_1.acc_cntl_options[i] =
- MV64360_PCI_ACC_CNTL_SNOOP_NONE |
- MV64360_PCI_ACC_CNTL_SWAP_NONE |
- MV64360_PCI_ACC_CNTL_MBURST_128_BYTES |
- MV64360_PCI_ACC_CNTL_RDSIZE_256_BYTES;
-#else
- si.cpu_prot_options[i] = 0;
- si.enet_options[i] = MV64360_ENET2MEM_SNOOP_NONE; /* errata */
- si.mpsc_options[i] = MV64360_MPSC2MEM_SNOOP_NONE; /* errata */
- si.idma_options[i] = MV64360_IDMA2MEM_SNOOP_NONE; /* errata */
-
- si.pci_1.acc_cntl_options[i] =
- MV64360_PCI_ACC_CNTL_SNOOP_WB |
- MV64360_PCI_ACC_CNTL_SWAP_NONE |
- MV64360_PCI_ACC_CNTL_MBURST_32_BYTES |
- MV64360_PCI_ACC_CNTL_RDSIZE_32_BYTES;
-#endif
- }
-
- /* Lookup PCI host bridges */
- if (mv64x60_init(&bh, &si))
- printk(KERN_WARNING "Bridge initialization failed.\n");
-
- pci_dram_offset = 0; /* sys mem at same addr on PCI & cpu bus */
- ppc_md.pci_swizzle = common_swizzle;
- ppc_md.pci_map_irq = katana_map_irq;
- ppc_md.pci_exclude_device = mv64x60_pci_exclude_device;
-
- mv64x60_set_bus(&bh, 1, 0);
- bh.hose_b->first_busno = 0;
- bh.hose_b->last_busno = 0xff;
+ u8 reset_out;
- return;
+ /* Enable access to IPMI ctlr by clearing IPMI PORTSEL bit in CPLD */
+ reset_out = in_8(cpld_base + KATANA_CPLD_RESET_OUT);
+ reset_out &= ~KATANA_CPLD_RESET_OUT_PORTSEL;
+ out_8(cpld_base + KATANA_CPLD_RESET_OUT, reset_out);
}
static void __init
@@ -440,12 +452,11 @@ katana_setup_arch(void)
* DD2.0 has bug that requires the L2 to be in WRT mode
* avoid dirty data in cache
*/
- if (PVR_REV(mfspr(PVR)) == 0x0200) {
+ if (PVR_REV(mfspr(SPRN_PVR)) == 0x0200) {
printk(KERN_INFO "DD2.0 detected. Setting L2 cache"
"to Writethrough mode\n");
_set_L2CR(L2CR_L2E | L2CR_L2PE | L2CR_L2WT);
- }
- else
+ } else
_set_L2CR(L2CR_L2E | L2CR_L2PE);
if (ppc_md.progress)
@@ -455,10 +466,11 @@ katana_setup_arch(void)
katana_setup_peripherals();
katana_enable_ipmi();
+ katana_bus_frequency = katana_bus_freq(cpld_base);
+
printk(KERN_INFO "Artesyn Communication Products, LLC - Katana(TM)\n");
if (ppc_md.progress)
ppc_md.progress("katana_setup_arch: exit", 0);
- return;
}
/* Platform device data fixup routines. */
@@ -473,9 +485,12 @@ katana_fixup_mpsc_pdata(struct platform_device *pdev)
pdata->max_idle = 40;
pdata->default_baud = KATANA_DEFAULT_BAUD;
pdata->brg_clk_src = KATANA_MPSC_CLK_SRC;
- pdata->brg_clk_freq = KATANA_MPSC_CLK_FREQ;
-
- return;
+ /*
+ * TCLK (not SysCLk) is routed to BRG, then to the MPSC. On most parts,
+ * TCLK == SysCLK but on 64460, they are separate pins.
+ * SysCLK can go up to 200 MHz but TCLK can only go up to 133 MHz.
+ */
+ pdata->brg_clk_freq = min(katana_bus_frequency, MV64x60_TCLK_FREQ_MAX);
}
#endif
@@ -483,32 +498,18 @@ katana_fixup_mpsc_pdata(struct platform_device *pdev)
static void __init
katana_fixup_eth_pdata(struct platform_device *pdev)
{
- struct mv64xxx_eth_platform_data *eth_pd;
+ struct mv643xx_eth_platform_data *eth_pd;
static u16 phy_addr[] = {
KATANA_ETH0_PHY_ADDR,
KATANA_ETH1_PHY_ADDR,
KATANA_ETH2_PHY_ADDR,
};
- int rx_size = KATANA_ETH_RX_QUEUE_SIZE * MV64340_ETH_DESC_SIZE;
- int tx_size = KATANA_ETH_TX_QUEUE_SIZE * MV64340_ETH_DESC_SIZE;
eth_pd = pdev->dev.platform_data;
eth_pd->force_phy_addr = 1;
eth_pd->phy_addr = phy_addr[pdev->id];
eth_pd->tx_queue_size = KATANA_ETH_TX_QUEUE_SIZE;
eth_pd->rx_queue_size = KATANA_ETH_RX_QUEUE_SIZE;
- eth_pd->tx_sram_addr = mv643xx_sram_alloc(tx_size);
-
- if (eth_pd->tx_sram_addr)
- eth_pd->tx_sram_size = tx_size;
- else
- printk(KERN_ERR "mv643xx_sram_alloc failed\n");
-
- eth_pd->rx_sram_addr = mv643xx_sram_alloc(rx_size);
- if (eth_pd->rx_sram_addr)
- eth_pd->rx_sram_size = rx_size;
- else
- printk(KERN_ERR "mv643xx_sram_alloc failed\n");
}
#endif
@@ -520,13 +521,13 @@ katana_platform_notify(struct device *dev)
void ((*rtn)(struct platform_device *pdev));
} dev_map[] = {
#if defined(CONFIG_SERIAL_MPSC)
- { MPSC_CTLR_NAME "0", katana_fixup_mpsc_pdata },
- { MPSC_CTLR_NAME "1", katana_fixup_mpsc_pdata },
+ { MPSC_CTLR_NAME ".0", katana_fixup_mpsc_pdata },
+ { MPSC_CTLR_NAME ".1", katana_fixup_mpsc_pdata },
#endif
#if defined(CONFIG_MV643XX_ETH)
- { MV64XXX_ETH_NAME "0", katana_fixup_eth_pdata },
- { MV64XXX_ETH_NAME "1", katana_fixup_eth_pdata },
- { MV64XXX_ETH_NAME "2", katana_fixup_eth_pdata },
+ { MV643XX_ETH_NAME ".0", katana_fixup_eth_pdata },
+ { MV643XX_ETH_NAME ".1", katana_fixup_eth_pdata },
+ { MV643XX_ETH_NAME ".2", katana_fixup_eth_pdata },
#endif
};
struct platform_device *pdev;
@@ -545,14 +546,82 @@ katana_platform_notify(struct device *dev)
return 0;
}
+#ifdef CONFIG_MTD_PHYSMAP
+
+#ifndef MB
+#define MB (1 << 20)
+#endif
+
+/*
+ * MTD Layout depends on amount of soldered FLASH in system. Sizes in MB.
+ *
+ * FLASH Amount: 128 64 32 16
+ * ------------- --- -- -- --
+ * Monitor: 1 1 1 1
+ * Primary Kernel: 1.5 1.5 1.5 1.5
+ * Primary fs: 30 30 <end> <end>
+ * Secondary Kernel: 1.5 1.5 N/A N/A
+ * Secondary fs: <end> <end> N/A N/A
+ * User: <overlays entire FLASH except for "Monitor" section>
+ */
+static int __init
+katana_setup_mtd(void)
+{
+ u32 size;
+ int ptbl_entries;
+ static struct mtd_partition *ptbl;
+
+ size = katana_flash_size_0 + katana_flash_size_1;
+ if (!size)
+ return -ENOMEM;
+
+ ptbl_entries = (size >= (64*MB)) ? 6 : 4;
+
+ if ((ptbl = kmalloc(ptbl_entries * sizeof(struct mtd_partition),
+ GFP_KERNEL)) == NULL) {
+
+ printk(KERN_WARNING "Can't alloc MTD partition table\n");
+ return -ENOMEM;
+ }
+ memset(ptbl, 0, ptbl_entries * sizeof(struct mtd_partition));
+
+ ptbl[0].name = "Monitor";
+ ptbl[0].size = KATANA_MTD_MONITOR_SIZE;
+ ptbl[1].name = "Primary Kernel";
+ ptbl[1].offset = MTDPART_OFS_NXTBLK;
+ ptbl[1].size = 0x00180000; /* 1.5 MB */
+ ptbl[2].name = "Primary Filesystem";
+ ptbl[2].offset = MTDPART_OFS_APPEND;
+ ptbl[2].size = MTDPART_SIZ_FULL; /* Correct for 16 & 32 MB */
+ ptbl[ptbl_entries-1].name = "User FLASH";
+ ptbl[ptbl_entries-1].offset = KATANA_MTD_MONITOR_SIZE;
+ ptbl[ptbl_entries-1].size = MTDPART_SIZ_FULL;
+
+ if (size >= (64*MB)) {
+ ptbl[2].size = 30*MB;
+ ptbl[3].name = "Secondary Kernel";
+ ptbl[3].offset = MTDPART_OFS_NXTBLK;
+ ptbl[3].size = 0x00180000; /* 1.5 MB */
+ ptbl[4].name = "Secondary Filesystem";
+ ptbl[4].offset = MTDPART_OFS_APPEND;
+ ptbl[4].size = MTDPART_SIZ_FULL;
+ }
+
+ physmap_map.size = size;
+ physmap_set_partitions(ptbl, ptbl_entries);
+ return 0;
+}
+
+arch_initcall(katana_setup_mtd);
+#endif
+
static void
katana_restart(char *cmd)
{
- volatile ulong i = 10000000;
+ ulong i = 10000000;
/* issue hard reset to the reset command register */
- out_8((volatile char *)(cpld_base + KATANA_CPLD_RST_CMD),
- KATANA_CPLD_RST_CMD_HR);
+ out_8(cpld_base + KATANA_CPLD_RST_CMD, KATANA_CPLD_RST_CMD_HR);
while (i-- > 0) ;
panic("restart failed\n");
@@ -561,6 +630,14 @@ katana_restart(char *cmd)
static void
katana_halt(void)
{
+ u8 v;
+
+ if (katana_id == KATANA_ID_752I) {
+ v = in_8(cpld_base + HSL_PLD_BASE + HSL_PLD_HOT_SWAP_OFF);
+ v |= HSL_PLD_HOT_SWAP_LED_BIT;
+ out_8(cpld_base + HSL_PLD_BASE + HSL_PLD_HOT_SWAP_OFF, v);
+ }
+
while (1) ;
/* NOTREACHED */
}
@@ -598,12 +675,13 @@ katana_show_cpuinfo(struct seq_file *m)
}
seq_printf(m, "product ID\t: 0x%x\n",
- in_8((volatile char *)(cpld_base + KATANA_CPLD_PRODUCT_ID)));
+ in_8(cpld_base + KATANA_CPLD_PRODUCT_ID));
seq_printf(m, "hardware rev\t: 0x%x\n",
- in_8((volatile char *)(cpld_base+KATANA_CPLD_HARDWARE_VER)));
+ in_8(cpld_base+KATANA_CPLD_HARDWARE_VER));
seq_printf(m, "PLD rev\t\t: 0x%x\n",
- in_8((volatile char *)(cpld_base + KATANA_CPLD_PLD_VER)));
- seq_printf(m, "PLB freq\t: %ldMhz\n", katana_bus_freq() / 1000000);
+ in_8(cpld_base + KATANA_CPLD_PLD_VER));
+ seq_printf(m, "PLB freq\t: %ldMhz\n",
+ (long)katana_bus_frequency / 1000000);
seq_printf(m, "PCI\t\t: %sMonarch\n", katana_is_monarch()? "" : "Non-");
return 0;
@@ -612,35 +690,52 @@ katana_show_cpuinfo(struct seq_file *m)
static void __init
katana_calibrate_decr(void)
{
- ulong freq;
+ u32 freq;
- freq = katana_bus_freq() / 4;
+ freq = katana_bus_frequency / 4;
printk(KERN_INFO "time_init: decrementer frequency = %lu.%.6lu MHz\n",
- freq / 1000000, freq % 1000000);
+ (long)freq / 1000000, (long)freq % 1000000);
tb_ticks_per_jiffy = freq / HZ;
tb_to_us = mulhwu_scale_factor(freq, 1000000);
-
- return;
}
unsigned long __init
katana_find_end_of_memory(void)
{
- return mv64x60_get_mem_size(KATANA_BRIDGE_REG_BASE,
+ return mv64x60_get_mem_size(CONFIG_MV64X60_NEW_BASE,
MV64x60_TYPE_MV64360);
}
+#if defined(CONFIG_I2C_MV64XXX) && defined(CONFIG_SENSORS_M41T00)
+extern ulong m41t00_get_rtc_time(void);
+extern int m41t00_set_rtc_time(ulong);
+
+static int __init
+katana_rtc_hookup(void)
+{
+ struct timespec tv;
+
+ ppc_md.get_rtc_time = m41t00_get_rtc_time;
+ ppc_md.set_rtc_time = m41t00_set_rtc_time;
+
+ tv.tv_nsec = 0;
+ tv.tv_sec = (ppc_md.get_rtc_time)();
+ do_settimeofday(&tv);
+
+ return 0;
+}
+late_initcall(katana_rtc_hookup);
+#endif
+
static inline void
katana_set_bat(void)
{
mb();
- mtspr(DBAT2U, 0xf0001ffe);
- mtspr(DBAT2L, 0xf000002a);
+ mtspr(SPRN_DBAT2U, 0xf0001ffe);
+ mtspr(SPRN_DBAT2L, 0xf000002a);
mb();
-
- return;
}
#if defined(CONFIG_SERIAL_TEXT_DEBUG) && defined(CONFIG_SERIAL_MPSC_CONSOLE)
@@ -657,6 +752,23 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
{
parse_bootinfo(find_bootinfo());
+ /* ASSUMPTION: If both r3 (bd_t pointer) and r6 (cmdline pointer)
+ * are non-zero, then we should use the board info from the bd_t
+ * structure and the cmdline pointed to by r6 instead of the
+ * information from birecs, if any. Otherwise, use the information
+ * from birecs as discovered by the preceeding call to
+ * parse_bootinfo(). This rule should work with both PPCBoot, which
+ * uses a bd_t board info structure, and the kernel boot wrapper,
+ * which uses birecs.
+ */
+ if (r3 && r6) {
+ /* copy board info structure */
+ memcpy( (void *)__res,(void *)(r3+KERNELBASE), sizeof(bd_t) );
+ /* copy command line */
+ *(char *)(r7+KERNELBASE) = 0;
+ strcpy(cmd_line, (char *)(r6+KERNELBASE));
+ }
+
isa_mem_base = 0;
ppc_md.setup_arch = katana_setup_arch;
@@ -672,7 +784,7 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
#if defined(CONFIG_SERIAL_TEXT_DEBUG) && defined(CONFIG_SERIAL_MPSC_CONSOLE)
ppc_md.setup_io_mappings = katana_map_io;
ppc_md.progress = mv64x60_mpsc_progress;
- mv64x60_progress_init(KATANA_BRIDGE_REG_BASE);
+ mv64x60_progress_init(CONFIG_MV64X60_NEW_BASE);
#endif
#if defined(CONFIG_SERIAL_MPSC) || defined(CONFIG_MV643XX_ETH)
@@ -680,5 +792,4 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
#endif
katana_set_bat(); /* Need for katana_find_end_of_memory and progress */
- return;
}
diff --git a/arch/ppc/platforms/katana.h b/arch/ppc/platforms/katana.h
index 3b8ff9a95af85..b82ed81950f59 100644
--- a/arch/ppc/platforms/katana.h
+++ b/arch/ppc/platforms/katana.h
@@ -3,7 +3,8 @@
*
* Definitions for Artesyn Katana750i/3750 board.
*
- * Tim Montgomery <timm@artesyncp.com>
+ * Author: Tim Montgomery <timm@artesyncp.com>
+ * Maintained by: Mark A. Greer <mgreer@mvista.com>
*
* Based on code done by Rabeeh Khoury - rabeeh@galileo.co.il
* Based on code done by Mark A. Greer <mgreer@mvista.com>
@@ -19,18 +20,17 @@
* PCI I/O space and 4 windows from the CPU bus to PCI MEM space.
* We'll only use one PCI MEM window on each PCI bus.
*
- * This is the CPU physical memory map (windows must be at least 1MB and start
+ * This is the CPU physical memory map (windows must be at least 64 KB and start
* on a boundary that is a multiple of the window size):
*
* 0xff800000-0xffffffff - Boot window
- * 0xf8400000-0xf85fffff - Internal SRAM
- * 0xf8200000-0xf823ffff - CPLD
- * 0xf8100000-0xf810ffff - MV64360 Registers
- * 0xf8000000-0xf80fffff - PLCC socket
- * 0xf0000000-0xf01fffff - Consistent memory pool
- * 0xe8000000-0xefffffff - soldered flash
- * 0xc0000000-0xc0ffffff - PCI I/O
- * 0x80000000-0xbfffffff - PCI MEM
+ * 0xf8400000-0xf843ffff - Internal SRAM
+ * 0xf8200000-0xf83fffff - CPLD
+ * 0xf8100000-0xf810ffff - MV64360 Registers (CONFIG_MV64X60_NEW_BASE)
+ * 0xf8000000-0xf80fffff - Socketed FLASH
+ * 0xe0000000-0xefffffff - Soldered FLASH
+ * 0xc0000000-0xc3ffffff - PCI I/O (second hose)
+ * 0x80000000-0xbfffffff - PCI MEM (second hose)
*/
#ifndef __PPC_PLATFORMS_KATANA_H
@@ -38,33 +38,22 @@
/* CPU Physical Memory Map setup. */
#define KATANA_BOOT_WINDOW_BASE 0xff800000
+#define KATANA_BOOT_WINDOW_SIZE 0x00800000 /* 8 MB */
#define KATANA_INTERNAL_SRAM_BASE 0xf8400000
#define KATANA_CPLD_BASE 0xf8200000
-#define KATANA_BRIDGE_REG_BASE 0xf8100000
+#define KATANA_CPLD_SIZE 0x00200000 /* 2 MB */
#define KATANA_SOCKET_BASE 0xf8000000
-#define KATANA_SOLDERED_FLASH_BASE 0xe8000000
-
-#define KATANA_BOOT_WINDOW_SIZE_ACTUAL 0x00800000 /* 8MB */
-#define KATANA_CPLD_SIZE_ACTUAL 0x00020000 /* 128KB */
-#define KATANA_SOCKETED_FLASH_SIZE_ACTUAL 0x00080000 /* 512KB */
-#define KATANA_SOLDERED_FLASH_SIZE_ACTUAL 0x02000000 /* 32MB */
-
-#define KATANA_BOOT_WINDOW_SIZE max(MV64360_WINDOW_SIZE_MIN, \
- KATANA_BOOT_WINDOW_SIZE_ACTUAL)
-#define KATANA_CPLD_SIZE max(MV64360_WINDOW_SIZE_MIN, \
- KATANA_CPLD_SIZE_ACTUAL)
-#define KATANA_SOCKETED_FLASH_SIZE max(MV64360_WINDOW_SIZE_MIN, \
- KATANA_SOCKETED_FLASH_SIZE_ACTUAL)
-#define KATANA_SOLDERED_FLASH_SIZE max(MV64360_WINDOW_SIZE_MIN, \
- KATANA_SOLDERED_FLASH_SIZE_ACTUAL)
+#define KATANA_SOCKETED_FLASH_SIZE 0x00100000 /* 1 MB */
+#define KATANA_SOLDERED_FLASH_BASE 0xe0000000
+#define KATANA_SOLDERED_FLASH_SIZE 0x10000000 /* 256 MB */
#define KATANA_PCI1_MEM_START_PROC_ADDR 0x80000000
#define KATANA_PCI1_MEM_START_PCI_HI_ADDR 0x00000000
#define KATANA_PCI1_MEM_START_PCI_LO_ADDR 0x80000000
-#define KATANA_PCI1_MEM_SIZE 0x40000000
+#define KATANA_PCI1_MEM_SIZE 0x40000000 /* 1 GB */
#define KATANA_PCI1_IO_START_PROC_ADDR 0xc0000000
#define KATANA_PCI1_IO_START_PCI_ADDR 0x00000000
-#define KATANA_PCI1_IO_SIZE 0x01000000
+#define KATANA_PCI1_IO_SIZE 0x04000000 /* 64 MB */
/* Board-specific IRQ info */
#define KATANA_PCI_INTA_IRQ_3750 64+8
@@ -138,6 +127,8 @@
#define HSL_PLD_J4SGA_REG_OFF 0
#define HSL_PLD_J4GA_REG_OFF 1
#define HSL_PLD_J2GA_REG_OFF 2
+#define HSL_PLD_HOT_SWAP_OFF 6
+#define HSL_PLD_HOT_SWAP_LED_BIT 0x1
#define GA_MASK 0x1f
#define HSL_PLD_SIZE 0x1000
#define K3750_GPP_GEO_ADDR_PINS 0xf8000000
@@ -162,7 +153,8 @@
#define KATANA_DEFAULT_BAUD 9600
#define KATANA_MPSC_CLK_SRC 8 /* TCLK */
-#define KATANA_MPSC_CLK_FREQ 133333333 /* 133.3333... MHz */
+
+#define KATANA_MTD_MONITOR_SIZE (1 << 20) /* 1 MB */
#define KATANA_ETH0_PHY_ADDR 12
#define KATANA_ETH1_PHY_ADDR 11
@@ -230,4 +222,34 @@ typedef enum {
#endif
-#endif /* __PPC_PLATFORMS_KATANA_H */
+static inline u32
+katana_bus_freq(void __iomem *cpld_base)
+{
+ u8 bd_cfg_0;
+
+ bd_cfg_0 = in_8(cpld_base + KATANA_CPLD_BD_CFG_0);
+
+ switch (bd_cfg_0 & KATANA_CPLD_BD_CFG_0_SYSCLK_MASK) {
+ case KATANA_CPLD_BD_CFG_0_SYSCLK_200:
+ return 200000000;
+ break;
+
+ case KATANA_CPLD_BD_CFG_0_SYSCLK_166:
+ return 166666666;
+ break;
+
+ case KATANA_CPLD_BD_CFG_0_SYSCLK_133:
+ return 133333333;
+ break;
+
+ case KATANA_CPLD_BD_CFG_0_SYSCLK_100:
+ return 100000000;
+ break;
+
+ default:
+ return 133333333;
+ break;
+ }
+}
+
+#endif /* __PPC_PLATFORMS_KATANA_H */
diff --git a/arch/ppc/platforms/lite5200.c b/arch/ppc/platforms/lite5200.c
index db6ea440c80a3..b604cf8b3cae9 100644
--- a/arch/ppc/platforms/lite5200.c
+++ b/arch/ppc/platforms/lite5200.c
@@ -13,7 +13,7 @@
* Dale Farnsworth <dale.farnsworth@mvista.com> and
* Wolfgang Denk <wd@denx.de>
*
- * Copyright 2004 Sylvain Munaut <tnt@246tNt.com>
+ * Copyright 2004-2005 Sylvain Munaut <tnt@246tNt.com>
* Copyright 2003 Motorola Inc.
* Copyright 2003 MontaVista Software Inc.
* Copyright 2003 DENX Software Engineering (wd@denx.de)
@@ -29,11 +29,14 @@
#include <linux/kdev_t.h>
#include <linux/root_dev.h>
#include <linux/console.h>
+#include <linux/module.h>
#include <asm/bootinfo.h>
#include <asm/io.h>
-#include <asm/ocp.h>
#include <asm/mpc52xx.h>
+#include <asm/ppc_sys.h>
+
+#include <syslib/mpc52xx_pci.h>
extern int powersave_nap;
@@ -44,34 +47,20 @@ EXPORT_SYMBOL(__res); /* For modules */
/* ======================================================================== */
-/* OCP device definition */
-/* For board/shared resources like PSCs */
+/* Platform specific code */
/* ======================================================================== */
-/* Be sure not to load conficting devices : e.g. loading the UART drivers for
- * PSC1 and then also loading a AC97 for this same PSC.
- * For details about how to create an entry, look in the doc of the concerned
- * driver ( eg drivers/serial/mpc52xx_uart.c for the PSC in uart mode )
- */
-struct ocp_def board_ocp[] = {
- {
- .vendor = OCP_VENDOR_FREESCALE,
- .function = OCP_FUNC_PSC_UART,
- .index = 0,
- .paddr = MPC52xx_PSC1,
- .irq = MPC52xx_PSC1_IRQ,
- .pm = OCP_CPM_NA,
- },
- { /* Terminating entry */
- .vendor = OCP_VENDOR_INVALID
- }
-};
+/* Supported PSC function in "preference" order */
+struct mpc52xx_psc_func mpc52xx_psc_functions[] = {
+ { .id = 0,
+ .func = "uart",
+ },
+ { .id = -1, /* End entry */
+ .func = NULL,
+ }
+ };
-/* ======================================================================== */
-/* Platform specific code */
-/* ======================================================================== */
-
static int
lite5200_show_cpuinfo(struct seq_file *m)
{
@@ -79,22 +68,66 @@ lite5200_show_cpuinfo(struct seq_file *m)
return 0;
}
+#ifdef CONFIG_PCI
+static int
+lite5200_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+ return (pin == 1) && (idsel==24) ? MPC52xx_IRQ0 : -1;
+}
+#endif
+
static void __init
lite5200_setup_cpu(void)
{
- struct mpc52xx_intr *intr;
+ struct mpc52xx_cdm __iomem *cdm;
+ struct mpc52xx_gpio __iomem *gpio;
+ struct mpc52xx_intr __iomem *intr;
+ struct mpc52xx_xlb __iomem *xlb;
+ u32 port_config;
u32 intr_ctrl;
/* Map zones */
- intr = (struct mpc52xx_intr *)
- ioremap(MPC52xx_INTR,sizeof(struct mpc52xx_intr));
-
- if (!intr) {
- printk("lite5200.c: Error while mapping INTR during lite5200_setup_cpu\n");
+ cdm = ioremap(MPC52xx_PA(MPC52xx_CDM_OFFSET), MPC52xx_CDM_SIZE);
+ gpio = ioremap(MPC52xx_PA(MPC52xx_GPIO_OFFSET), MPC52xx_GPIO_SIZE);
+ xlb = ioremap(MPC52xx_PA(MPC52xx_XLB_OFFSET), MPC52xx_XLB_SIZE);
+ intr = ioremap(MPC52xx_PA(MPC52xx_INTR_OFFSET), MPC52xx_INTR_SIZE);
+
+ if (!cdm || !gpio || !xlb || !intr) {
+ printk("lite5200.c: Error while mapping CDM/GPIO/XLB/INTR during"
+ "lite5200_setup_cpu\n");
goto unmap_regs;
}
+ /* Use internal 48 Mhz */
+ out_8(&cdm->ext_48mhz_en, 0x00);
+ out_8(&cdm->fd_enable, 0x01);
+ if (in_be32(&cdm->rstcfg) & 0x40) /* Assumes 33Mhz clock */
+ out_be16(&cdm->fd_counters, 0x0001);
+ else
+ out_be16(&cdm->fd_counters, 0x5555);
+
+ /* Get port mux config */
+ port_config = in_be32(&gpio->port_config);
+
+ /* 48Mhz internal, pin is GPIO */
+ port_config &= ~0x00800000;
+
+ /* USB port */
+ port_config &= ~0x00007000; /* Differential mode - USB1 only */
+ port_config |= 0x00001000;
+
+ /* Commit port config */
+ out_be32(&gpio->port_config, port_config);
+
+ /* Configure the XLB Arbiter */
+ out_be32(&xlb->master_pri_enable, 0xff);
+ out_be32(&xlb->master_priority, 0x11111111);
+
+ /* Enable ram snooping for 1GB window */
+ out_be32(&xlb->config, in_be32(&xlb->config) | MPC52xx_XLB_CFG_SNOOP);
+ out_be32(&xlb->snoop_window, MPC52xx_PCI_TARGET_MEM | 0x1d);
+
/* IRQ[0-3] setup : IRQ0 - Level Active Low */
/* IRQ[1-3] - Level Active High */
intr_ctrl = in_be32(&intr->ctrl);
@@ -104,17 +137,22 @@ lite5200_setup_cpu(void)
/* Unmap reg zone */
unmap_regs:
+ if (cdm) iounmap(cdm);
+ if (gpio) iounmap(gpio);
+ if (xlb) iounmap(xlb);
if (intr) iounmap(intr);
}
static void __init
lite5200_setup_arch(void)
{
- /* Add board OCP definitions */
- mpc52xx_add_board_devices(board_ocp);
-
/* CPU & Port mux setup */
lite5200_setup_cpu();
+
+#ifdef CONFIG_PCI
+ /* PCI Bridge setup */
+ mpc52xx_find_bridges();
+#endif
}
void __init
@@ -150,15 +188,22 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
}
}
+ /* PPC Sys identification */
+ identify_ppc_sys_by_id(mfspr(SPRN_SVR));
+
/* BAT setup */
mpc52xx_set_bat();
- /* No ISA bus AFAIK */
+ /* No ISA bus by default */
isa_io_base = 0;
isa_mem_base = 0;
/* Powersave */
- powersave_nap = 1; /* We allow this platform to NAP */
+ /* This is provided as an example on how to do it. But you
+ need to be aware that NAP disable bus snoop and that may
+ be required for some devices to work properly, like USB ... */
+ /* powersave_nap = 1; */
+
/* Setup the ppc_md struct */
ppc_md.setup_arch = lite5200_setup_arch;
@@ -167,6 +212,10 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
ppc_md.init_IRQ = mpc52xx_init_irq;
ppc_md.get_irq = mpc52xx_get_irq;
+#ifdef CONFIG_PCI
+ ppc_md.pci_map_irq = lite5200_map_irq;
+#endif
+
ppc_md.find_end_of_memory = mpc52xx_find_end_of_memory;
ppc_md.setup_io_mappings = mpc52xx_map_io;
diff --git a/arch/ppc/platforms/lite5200.h b/arch/ppc/platforms/lite5200.h
index 833134b19c791..c1de2aa47175f 100644
--- a/arch/ppc/platforms/lite5200.h
+++ b/arch/ppc/platforms/lite5200.h
@@ -17,7 +17,7 @@
#define __PLATFORMS_LITE5200_H__
/* Serial port used for low-level debug */
-#define MPC52xx_PF_CONSOLE_PORT 0 /* PSC1 */
+#define MPC52xx_PF_CONSOLE_PORT 1 /* PSC1 */
#endif /* __PLATFORMS_LITE5200_H__ */
diff --git a/arch/ppc/platforms/lopec.c b/arch/ppc/platforms/lopec.c
index f0c203085937d..a5569525e0aff 100644
--- a/arch/ppc/platforms/lopec.c
+++ b/arch/ppc/platforms/lopec.c
@@ -319,8 +319,8 @@ static __inline__ void
lopec_set_bat(void)
{
mb();
- mtspr(DBAT1U, 0xf8000ffe);
- mtspr(DBAT1L, 0xf800002a);
+ mtspr(SPRN_DBAT1U, 0xf8000ffe);
+ mtspr(SPRN_DBAT1L, 0xf800002a);
mb();
}
diff --git a/arch/ppc/platforms/mcpn765.c b/arch/ppc/platforms/mcpn765.c
index 83dcc8fae8315..e88d294ea593d 100644
--- a/arch/ppc/platforms/mcpn765.c
+++ b/arch/ppc/platforms/mcpn765.c
@@ -470,8 +470,8 @@ static __inline__ void
mcpn765_set_bat(void)
{
mb();
- mtspr(DBAT1U, 0xfe8000fe);
- mtspr(DBAT1L, 0xfe80002a);
+ mtspr(SPRN_DBAT1U, 0xfe8000fe);
+ mtspr(SPRN_DBAT1L, 0xfe80002a);
mb();
}
diff --git a/arch/ppc/platforms/mpc5200.c b/arch/ppc/platforms/mpc5200.c
index dce7225ad3476..a58db438c1623 100644
--- a/arch/ppc/platforms/mpc5200.c
+++ b/arch/ppc/platforms/mpc5200.c
@@ -17,7 +17,7 @@
#include <asm/mpc52xx.h>
-struct ocp_fs_i2c_data mpc5200_i2c_def = {
+static struct ocp_fs_i2c_data mpc5200_i2c_def = {
.flags = FS_I2C_CLOCK_5200,
};
diff --git a/arch/ppc/platforms/mvme5100.c b/arch/ppc/platforms/mvme5100.c
index 0ecea917d205a..b292b44b760c4 100644
--- a/arch/ppc/platforms/mvme5100.c
+++ b/arch/ppc/platforms/mvme5100.c
@@ -246,8 +246,8 @@ static __inline__ void
mvme5100_set_bat(void)
{
mb();
- mtspr(DBAT1U, 0xf0001ffe);
- mtspr(DBAT1L, 0xf000002a);
+ mtspr(SPRN_DBAT1U, 0xf0001ffe);
+ mtspr(SPRN_DBAT1L, 0xf000002a);
mb();
}
diff --git a/arch/ppc/platforms/pcore.c b/arch/ppc/platforms/pcore.c
index af8b51d876d49..d7191630a6504 100644
--- a/arch/ppc/platforms/pcore.c
+++ b/arch/ppc/platforms/pcore.c
@@ -282,8 +282,8 @@ static __inline__ void
pcore_set_bat(void)
{
mb();
- mtspr(DBAT3U, 0xf0001ffe);
- mtspr(DBAT3L, 0xfe80002a);
+ mtspr(SPRN_DBAT3U, 0xf0001ffe);
+ mtspr(SPRN_DBAT3L, 0xfe80002a);
mb();
}
diff --git a/arch/ppc/platforms/pmac_backlight.c b/arch/ppc/platforms/pmac_backlight.c
index e0c797f59ac99..ed2b1cebc19ae 100644
--- a/arch/ppc/platforms/pmac_backlight.c
+++ b/arch/ppc/platforms/pmac_backlight.c
@@ -12,6 +12,7 @@
#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>
@@ -25,14 +26,19 @@
#include <linux/adb.h>
#include <linux/pmu.h>
-static struct backlight_controller *backlighter = NULL;
-static void* backlighter_data = NULL;
-static int backlight_autosave = 0;
+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;
-void __pmac
-register_backlight_controller(struct backlight_controller *ctrler, void *data, char *type)
+static void backlight_callback(void *);
+static DECLARE_WORK(backlight_work, backlight_callback, NULL);
+
+void __pmac register_backlight_controller(struct backlight_controller *ctrler,
+ void *data, char *type)
{
struct device_node* bk_node;
char *prop;
@@ -83,16 +89,18 @@ register_backlight_controller(struct backlight_controller *ctrler, void *data, c
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);
+ printk(KERN_INFO "Registered \"%s\" backlight controller,"
+ "level: %d/15\n", type, backlight_level);
}
EXPORT_SYMBOL(register_backlight_controller);
-void __pmac
-unregister_backlight_controller(struct backlight_controller *ctrler, void *data)
+void __pmac unregister_backlight_controller(struct backlight_controller
+ *ctrler, void *data)
{
/* We keep the current backlight level (for now) */
if (ctrler == backlighter && data == backlighter_data)
@@ -100,22 +108,32 @@ unregister_backlight_controller(struct backlight_controller *ctrler, void *data)
}
EXPORT_SYMBOL(unregister_backlight_controller);
-int __pmac
-set_backlight_enable(int enable)
+static int __pmac __set_backlight_enable(int enable)
{
int rc;
if (!backlighter)
return -ENODEV;
- rc = backlighter->set_enable(enable, backlight_level, backlighter_data);
+ acquire_console_sem();
+ rc = backlighter->set_enable(enable, backlight_level,
+ backlighter_data);
if (!rc)
backlight_enabled = enable;
+ release_console_sem();
return rc;
}
+int __pmac 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 __pmac
-get_backlight_enable(void)
+int __pmac get_backlight_enable(void)
{
if (!backlighter)
return -ENODEV;
@@ -123,8 +141,7 @@ get_backlight_enable(void)
}
EXPORT_SYMBOL(get_backlight_enable);
-int __pmac
-set_backlight_level(int level)
+static int __pmac __set_backlight_level(int level)
{
int rc = 0;
@@ -134,10 +151,12 @@ set_backlight_level(int level)
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)
@@ -146,13 +165,38 @@ set_backlight_level(int level)
}
return rc;
}
+int __pmac 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 __pmac
-get_backlight_level(void)
+int __pmac 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
index fa156633dbc76..c00e0352044d4 100644
--- a/arch/ppc/platforms/pmac_cache.S
+++ b/arch/ppc/platforms/pmac_cache.S
@@ -55,7 +55,7 @@ BEGIN_FTR_SECTION
END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
/* Stop DPM */
- mfspr r8,SPRN_HID0 /* Save HID0 in r8 */
+ 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 */
@@ -86,13 +86,13 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
sync
/* Get the current enable bit of the L2CR into r4 */
- mfspr r5,L2CR
+ 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 L2CR,r3
+1: mtspr SPRN_L2CR,r3
3: sync
isync
b 1f
@@ -117,7 +117,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
b 2f
/* When disabling L2, code must be in L1 */
.balign 32
-1: mtspr L2CR,r5
+1: mtspr SPRN_L2CR,r5
3: sync
isync
b 1f
@@ -129,18 +129,18 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
isync
/* Invalidate L2. This is pre-745x, we clear the L2I bit ourselves */
oris r4,r5,L2CR_L2I@h
- mtspr L2CR,r4
+ mtspr SPRN_L2CR,r4
sync
isync
xoris r4,r4,L2CR_L2I@h
sync
- mtspr L2CR,r4
+ mtspr SPRN_L2CR,r4
sync
/* now disable the L1 data cache */
- mfspr r0,HID0
+ mfspr r0,SPRN_HID0
rlwinm r0,r0,0,~HID0_DCE
- mtspr HID0,r0
+ mtspr SPRN_HID0,r0
sync
isync
@@ -239,14 +239,14 @@ flush_disable_745x:
isync
/* Flush the L2 cache using the hardware assist */
- mfspr r3,L2CR
+ 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 L2CR,r0 /* lock the L2 cache */
+1: mtspr SPRN_L2CR,r0 /* lock the L2 cache */
3: sync
isync
b 1f
@@ -258,8 +258,8 @@ flush_disable_745x:
isync
ori r0,r3,L2CR_L2HWF_745x
sync
- mtspr L2CR,r0 /* set the hardware flush bit */
-3: mfspr r0,L2CR /* wait for it to go to 0 */
+ 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
@@ -267,7 +267,7 @@ flush_disable_745x:
b 2f
/* When disabling L2, code must be in L1 */
.balign 32
-1: mtspr L2CR,r3 /* disable the L2 cache */
+1: mtspr SPRN_L2CR,r3 /* disable the L2 cache */
3: sync
isync
b 1f
@@ -278,34 +278,34 @@ flush_disable_745x:
1: sync
isync
oris r4,r3,L2CR_L2I@h
- mtspr L2CR,r4
+ mtspr SPRN_L2CR,r4
sync
isync
-1: mfspr r4,L2CR
+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,L3CR
+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 L3CR,r0 /* lock the L3 cache */
+ mtspr SPRN_L3CR,r0 /* lock the L3 cache */
sync
isync
ori r0,r0,L3CR_L3HWF
sync
- mtspr L3CR,r0 /* set the hardware flush bit */
-5: mfspr r0,L3CR /* wait for it to go to zero */
+ 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 L3CR,r3 /* disable the L3 cache */
+ mtspr SPRN_L3CR,r3 /* disable the L3 cache */
sync
ori r4,r3,L3CR_L3I
mtspr SPRN_L3CR,r4
@@ -315,9 +315,9 @@ BEGIN_FTR_SECTION
sync
END_FTR_SECTION_IFSET(CPU_FTR_L3CR)
-6: mfspr r0,HID0 /* now disable the L1 data cache */
+6: mfspr r0,SPRN_HID0 /* now disable the L1 data cache */
rlwinm r0,r0,0,~HID0_DCE
- mtspr HID0,r0
+ mtspr SPRN_HID0,r0
sync
isync
mtmsr r11 /* restore DR and EE */
diff --git a/arch/ppc/platforms/pmac_cpufreq.c b/arch/ppc/platforms/pmac_cpufreq.c
index 73843408c63d5..9c85f9ca1cfb3 100644
--- a/arch/ppc/platforms/pmac_cpufreq.c
+++ b/arch/ppc/platforms/pmac_cpufreq.c
@@ -156,7 +156,7 @@ static int __pmac dfs_set_cpu_speed(int low_speed)
static unsigned int __pmac dfs_get_cpu_speed(unsigned int cpu)
{
- if (mfspr(HID1) & HID1_DFS)
+ if (mfspr(SPRN_HID1) & HID1_DFS)
return low_freq;
else
return hi_freq;
@@ -230,7 +230,7 @@ static int __pmac pmu_set_cpu_speed(int low_speed)
enable_kernel_fp();
#ifdef CONFIG_ALTIVEC
- if (cur_cpu_spec[0]->cpu_features & CPU_FTR_ALTIVEC)
+ if (cpu_has_feature(CPU_FTR_ALTIVEC))
enable_kernel_altivec();
#endif /* CONFIG_ALTIVEC */
@@ -464,20 +464,22 @@ static int __pmac pmac_cpufreq_init_7447A(struct device_node *cpunode)
u32 *reg;
struct cpufreq_driver *driver = &pmac_cpufreq_driver;
- /* OF only reports the high frequency */
- hi_freq = cur_freq;
- low_freq = cur_freq/2;
- driver->get = dfs_get_cpu_speed;
- cur_freq = driver->get(0);
-
+ /* Look for voltage GPIO */
volt_gpio_np = of_find_node_by_name(NULL, "cpu-vcore-select");
+ reg = (u32 *)get_property(volt_gpio_np, "reg", NULL);
+ voltage_gpio = *reg;
if (!volt_gpio_np){
printk(KERN_ERR "cpufreq: missing cpu-vcore-select gpio\n");
return 1;
}
- reg = (u32 *)get_property(volt_gpio_np, "reg", NULL);
- voltage_gpio = *reg;
+ /* OF only reports the high frequency */
+ hi_freq = cur_freq;
+ low_freq = cur_freq/2;
+
+ /* Read actual frequency from CPU */
+ driver->get = dfs_get_cpu_speed;
+ cur_freq = driver->get(0);
set_speed_proc = dfs_set_cpu_speed;
return 0;
@@ -492,7 +494,7 @@ static int __pmac pmac_cpufreq_init_7447A(struct device_node *cpunode)
* - iBook2 500/600 (PMU based, 400Mhz & 500/600Mhz)
* - iBook2 700 (CPU based, 400Mhz & 700Mhz, support low voltage)
* - Recent MacRISC3 laptops
- * - iBook G4s and PowerBook G4s with 7447A CPUs
+ * - All new machines with 7447A CPUs
*/
static int __init pmac_cpufreq_setup(void)
{
@@ -513,11 +515,10 @@ static int __init pmac_cpufreq_setup(void)
goto out;
cur_freq = (*value) / 1000;
- /* Check for 7447A based iBook G4 or PowerBook */
- if (machine_is_compatible("PowerBook6,5") ||
- machine_is_compatible("PowerBook6,4") ||
- machine_is_compatible("PowerBook5,5") ||
- machine_is_compatible("PowerBook5,4")) {
+ /* 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") ||
@@ -542,7 +543,7 @@ static int __init pmac_cpufreq_setup(void)
set_speed_proc = pmu_set_cpu_speed;
}
/* Else check for 750FX */
- else if (PVR_VER(mfspr(PVR)) == 0x7000) {
+ else if (PVR_VER(mfspr(SPRN_PVR)) == 0x7000) {
if (get_property(cpunode, "dynamic-power-step", NULL) == NULL)
goto out;
hi_freq = cur_freq;
diff --git a/arch/ppc/platforms/pmac_feature.c b/arch/ppc/platforms/pmac_feature.c
index 8869713396c10..8e60550863a6e 100644
--- a/arch/ppc/platforms/pmac_feature.c
+++ b/arch/ppc/platforms/pmac_feature.c
@@ -1796,7 +1796,7 @@ core99_sleep_state(struct device_node* node, long param, long value)
if (value == 1) {
pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL,
*reg, 0x05);
- } else if (value == 0 && (mfspr(HID1) & HID1_DFS)) {
+ } else if (value == 0 && (mfspr(SPRN_HID1) & HID1_DFS)) {
pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL,
*reg, 0x04);
}
@@ -2022,10 +2022,11 @@ static struct feature_table_entry g5_features[] __pmacdata = {
#endif /* CONFIG_POWER4 */
static struct pmac_mb_def pmac_mb_defs[] __pmacdata = {
- /* Warning: ordering is important as some models may claim
- * beeing compatible with several types
- */
#ifndef CONFIG_POWER4
+ /*
+ * Desktops
+ */
+
{ "AAPL,8500", "PowerMac 8500/8600",
PMAC_TYPE_PSURGE, NULL,
0
@@ -2058,14 +2059,6 @@ static struct pmac_mb_def pmac_mb_defs[] __pmacdata = {
PMAC_TYPE_GAZELLE, NULL,
0
},
- { "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,Gossamer", "PowerMac G3 (Gossamer)",
PMAC_TYPE_GOSSAMER, heathrow_desktop_features,
0
@@ -2074,42 +2067,6 @@ static struct pmac_mb_def pmac_mb_defs[] __pmacdata = {
PMAC_TYPE_SILK, heathrow_desktop_features,
0
},
- { "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_MAY_SLEEP | PMAC_MB_MOBILE
- },
- { "iMac,1", "iMac (first generation)",
- PMAC_TYPE_ORIG_IMAC, paddington_features,
- 0
- },
- { "PowerMac4,1", "iMac \"Flower Power\"",
- PMAC_TYPE_PANGEA_IMAC, pangea_features,
- PMAC_MB_MAY_SLEEP
- },
- { "PowerBook4,3", "iBook 2 rev. 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,1", "iBook 2",
- PMAC_TYPE_IBOOK2, pangea_features,
- PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE
- },
- { "PowerMac4,4", "eMac",
- PMAC_TYPE_EMAC, core99_features,
- PMAC_MB_MAY_SLEEP
- },
- { "PowerMac4,2", "Flat panel iMac",
- PMAC_TYPE_FLAT_PANEL_IMAC, pangea_features,
- PMAC_MB_CAN_SLEEP
- },
{ "PowerMac1,1", "Blue&White G3",
PMAC_TYPE_YOSEMITE, paddington_features,
0
@@ -2118,9 +2075,13 @@ static struct pmac_mb_def pmac_mb_defs[] __pmacdata = {
PMAC_TYPE_YIKES, paddington_features,
0
},
- { "PowerBook2,1", "iBook (first generation)",
- PMAC_TYPE_ORIG_IBOOK, core99_features,
- PMAC_MB_CAN_SLEEP | PMAC_MB_OLD_CORE99 | PMAC_MB_MOBILE
+ { "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,
@@ -2134,30 +2095,96 @@ static struct pmac_mb_def pmac_mb_defs[] __pmacdata = {
PMAC_TYPE_SAWTOOTH, core99_features,
PMAC_MB_MAY_SLEEP | PMAC_MB_OLD_CORE99
},
- { "PowerMac2,1", "iMac FireWire",
- PMAC_TYPE_FW_IMAC, core99_features,
- PMAC_MB_MAY_SLEEP | PMAC_MB_OLD_CORE99
+ { "PowerMac3,4", "PowerMac G4 Silver",
+ PMAC_TYPE_QUICKSILVER, core99_features,
+ PMAC_MB_MAY_SLEEP
},
- { "PowerMac2,2", "iMac FireWire",
- PMAC_TYPE_FW_IMAC, core99_features,
- PMAC_MB_MAY_SLEEP | PMAC_MB_OLD_CORE99
+ { "PowerMac3,5", "PowerMac G4 Silver",
+ PMAC_TYPE_QUICKSILVER, core99_features,
+ PMAC_MB_MAY_SLEEP
},
- { "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
+ { "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
},
- { "PowerMac3,4", "PowerMac G4 Silver",
- PMAC_TYPE_QUICKSILVER, core99_features,
- PMAC_MB_MAY_SLEEP
+ { "PowerMac6,1", "Flat panel iMac",
+ PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
+ PMAC_MB_MAY_SLEEP,
},
- { "PowerMac3,5", "PowerMac G4 Silver",
- PMAC_TYPE_QUICKSILVER, core99_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_MAY_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,
@@ -2180,17 +2207,17 @@ static struct pmac_mb_def pmac_mb_defs[] __pmacdata = {
PMAC_TYPE_TITANIUM4, core99_features,
PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE
},
- { "RackMac1,1", "XServe",
- PMAC_TYPE_RACKMAC, rackmac_features,
- 0,
+ { "PowerBook4,1", "iBook 2",
+ PMAC_TYPE_IBOOK2, pangea_features,
+ PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE
},
- { "RackMac1,2", "XServe rev. 2",
- PMAC_TYPE_RACKMAC, rackmac_features,
- 0,
+ { "PowerBook4,2", "iBook 2",
+ PMAC_TYPE_IBOOK2, pangea_features,
+ PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE
},
- { "PowerMac3,6", "PowerMac G4 Windtunnel",
- PMAC_TYPE_WINDTUNNEL, core99_features,
- PMAC_MB_MAY_SLEEP,
+ { "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,
@@ -2212,6 +2239,14 @@ static struct pmac_mb_def pmac_mb_defs[] __pmacdata = {
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,
+ },
{ "PowerBook6,1", "PowerBook G4 12\"",
PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
@@ -2232,6 +2267,10 @@ static struct pmac_mb_def pmac_mb_defs[] __pmacdata = {
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,
diff --git a/arch/ppc/platforms/pmac_setup.c b/arch/ppc/platforms/pmac_setup.c
index 5139523319862..4d324b630f4f8 100644
--- a/arch/ppc/platforms/pmac_setup.c
+++ b/arch/ppc/platforms/pmac_setup.c
@@ -52,6 +52,7 @@
#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>
@@ -70,6 +71,8 @@
#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"
@@ -247,7 +250,7 @@ pmac_setup_arch(void)
int *fp;
unsigned long pvr;
- pvr = PVR_VER(mfspr(PVR));
+ pvr = PVR_VER(mfspr(SPRN_PVR));
/* Set loops_per_jiffy to a half-way reasonable value,
for use until calibrate_delay gets called. */
@@ -274,7 +277,7 @@ pmac_setup_arch(void)
pmac_find_bridges();
/* Checks "l2cr-value" property in the registry */
- if (cur_cpu_spec[0]->cpu_features & CPU_FTR_L2CR) {
+ if (cpu_has_feature(CPU_FTR_L2CR)) {
struct device_node *np = find_devices("cpus");
if (np == 0)
np = find_type_devices("cpu");
@@ -421,10 +424,62 @@ find_boot_device(void)
}
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[0]->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;
}
@@ -614,6 +669,7 @@ pmac_init(unsigned long r3, unsigned long r4, unsigned long r5,
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;
diff --git a/arch/ppc/platforms/pmac_sleep.S b/arch/ppc/platforms/pmac_sleep.S
index cc69636f17692..3139b6766ad3b 100644
--- a/arch/ppc/platforms/pmac_sleep.S
+++ b/arch/ppc/platforms/pmac_sleep.S
@@ -182,12 +182,12 @@ END_FTR_SECTION_IFSET(CPU_FTR_SPEC7450)
/*
* Set the HID0 and MSR for sleep.
*/
- mfspr r2,HID0
+ mfspr r2,SPRN_HID0
rlwinm r2,r2,0,10,7 /* clear doze, nap */
oris r2,r2,HID0_SLEEP@h
sync
isync
- mtspr HID0,r2
+ mtspr SPRN_HID0,r2
sync
/* This loop puts us back to sleep in case we have a spurrious
@@ -216,10 +216,10 @@ _GLOBAL(core99_wake_up)
/* Make sure HID0 no longer contains any sleep bit and that data cache
* is disabled
*/
- mfspr r3,HID0
+ 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 HID0,r3
+ mtspr SPRN_HID0,r3
sync
isync
diff --git a/arch/ppc/platforms/pmac_smp.c b/arch/ppc/platforms/pmac_smp.c
index d6624b018ed98..2b88745576a0d 100644
--- a/arch/ppc/platforms/pmac_smp.c
+++ b/arch/ppc/platforms/pmac_smp.c
@@ -119,7 +119,7 @@ static volatile int sec_tb_reset = 0;
static void __init core99_init_caches(int cpu)
{
- if (!(cur_cpu_spec[0]->cpu_features & CPU_FTR_L2CR))
+ if (!cpu_has_feature(CPU_FTR_L2CR))
return;
if (cpu == 0) {
@@ -132,7 +132,7 @@ static void __init core99_init_caches(int cpu)
printk("CPU%d: L2CR set to %lx\n", cpu, core99_l2_cache);
}
- if (!(cur_cpu_spec[0]->cpu_features & CPU_FTR_L3CR))
+ if (!cpu_has_feature(CPU_FTR_L3CR))
return;
if (cpu == 0){
@@ -294,7 +294,7 @@ static int __init smp_psurge_probe(void)
int i, ncpus;
/* We don't do SMP on the PPC601 -- paulus */
- if (PVR_VER(mfspr(PVR)) == 1)
+ if (PVR_VER(mfspr(SPRN_PVR)) == 1)
return 1;
/*
diff --git a/arch/ppc/platforms/pplus.c b/arch/ppc/platforms/pplus.c
index 1688f369516d7..65705c9117950 100644
--- a/arch/ppc/platforms/pplus.c
+++ b/arch/ppc/platforms/pplus.c
@@ -849,10 +849,10 @@ static __inline__ void pplus_set_bat(void)
mb();
/* setup DBATs */
- mtspr(DBAT2U, 0x80001ffe);
- mtspr(DBAT2L, 0x8000002a);
- mtspr(DBAT3U, 0xf0001ffe);
- mtspr(DBAT3L, 0xf000002a);
+ mtspr(SPRN_DBAT2U, 0x80001ffe);
+ mtspr(SPRN_DBAT2L, 0x8000002a);
+ mtspr(SPRN_DBAT3U, 0xf0001ffe);
+ mtspr(SPRN_DBAT3L, 0xf000002a);
/* wait for updates */
mb();
diff --git a/arch/ppc/platforms/prep_setup.c b/arch/ppc/platforms/prep_setup.c
index c6bd7b86bd61f..bc926be95472f 100644
--- a/arch/ppc/platforms/prep_setup.c
+++ b/arch/ppc/platforms/prep_setup.c
@@ -690,8 +690,8 @@ prep_set_bat(void)
mb();
/* setup DBATs */
- mtspr(DBAT2U, 0x80001ffe);
- mtspr(DBAT2L, 0x8000002a);
+ mtspr(SPRN_DBAT2U, 0x80001ffe);
+ mtspr(SPRN_DBAT2L, 0x8000002a);
/* wait for updates */
mb();
@@ -1144,6 +1144,8 @@ prep_init(unsigned long r3, unsigned long r4, unsigned long r5,
/* this gets changed later on if we have an OpenPIC -- Cort */
ppc_md.get_irq = i8259_irq;
+ ppc_md.phys_mem_access_prot = pci_phys_mem_access_prot;
+
ppc_md.restart = prep_restart;
ppc_md.power_off = NULL; /* set in prep_setup_arch() */
ppc_md.halt = prep_halt;
diff --git a/arch/ppc/platforms/prpmc750.c b/arch/ppc/platforms/prpmc750.c
index b89d144c80161..c894e1ab59342 100644
--- a/arch/ppc/platforms/prpmc750.c
+++ b/arch/ppc/platforms/prpmc750.c
@@ -302,8 +302,8 @@ static void __init prpmc750_init_IRQ(void)
static __inline__ void prpmc750_set_bat(void)
{
mb();
- mtspr(DBAT1U, 0xf0001ffe);
- mtspr(DBAT1L, 0xf000002a);
+ mtspr(SPRN_DBAT1U, 0xf0001ffe);
+ mtspr(SPRN_DBAT1L, 0xf000002a);
mb();
}
diff --git a/arch/ppc/platforms/prpmc800.c b/arch/ppc/platforms/prpmc800.c
index 0e99f8bc3f3ba..8b09fa69b35b2 100644
--- a/arch/ppc/platforms/prpmc800.c
+++ b/arch/ppc/platforms/prpmc800.c
@@ -419,8 +419,8 @@ static void __init prpmc800_init_IRQ(void)
static __inline__ void prpmc800_set_bat(void)
{
mb();
- mtspr(DBAT1U, 0xf0001ffe);
- mtspr(DBAT1L, 0xf000002a);
+ mtspr(SPRN_DBAT1U, 0xf0001ffe);
+ mtspr(SPRN_DBAT1L, 0xf000002a);
mb();
}
diff --git a/arch/ppc/platforms/radstone_ppc7d.c b/arch/ppc/platforms/radstone_ppc7d.c
new file mode 100644
index 0000000000000..2a99b43737a88
--- /dev/null
+++ b/arch/ppc/platforms/radstone_ppc7d.c
@@ -0,0 +1,1452 @@
+/*
+ * arch/ppc/platforms/radstone_ppc7d.c
+ *
+ * Board setup routines for the Radstone PPC7D boards.
+ *
+ * Author: James Chapman <jchapman@katalix.com>
+ *
+ * Based on code done by Rabeeh Khoury - rabeeh@galileo.co.il
+ * Based on code done by - Mark A. Greer <mgreer@mvista.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+/* Radstone PPC7D boards are rugged VME boards with PPC 7447A CPUs,
+ * Discovery-II, dual gigabit ethernet, dual PMC, USB, keyboard/mouse,
+ * 4 serial ports, 2 high speed serial ports (MPSCs) and optional
+ * SCSI / VGA.
+ */
+
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/major.h>
+#include <linux/initrd.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/ide.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/mv643xx.h>
+#include <linux/netdevice.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/time.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/prom.h>
+#include <asm/smp.h>
+#include <asm/vga.h>
+#include <asm/open_pic.h>
+#include <asm/i8259.h>
+#include <asm/todc.h>
+#include <asm/bootinfo.h>
+#include <asm/mpc10x.h>
+#include <asm/pci-bridge.h>
+#include <asm/mv64x60.h>
+#include <asm/i8259.h>
+
+#include "radstone_ppc7d.h"
+
+#undef DEBUG
+
+#define PPC7D_RST_PIN 17 /* GPP17 */
+
+extern u32 mv64360_irq_base;
+
+static struct mv64x60_handle bh;
+static int ppc7d_has_alma;
+
+extern void gen550_progress(char *, unsigned short);
+extern void gen550_init(int, struct uart_port *);
+
+/* residual data */
+unsigned char __res[sizeof(bd_t)];
+
+/*****************************************************************************
+ * Serial port code
+ *****************************************************************************/
+
+#if defined(CONFIG_KGDB) || defined(CONFIG_SERIAL_TEXT_DEBUG)
+static void __init ppc7d_early_serial_map(void)
+{
+#if defined(CONFIG_SERIAL_MPSC_CONSOLE)
+ mv64x60_progress_init(CONFIG_MV64X60_NEW_BASE);
+#elif defined(CONFIG_SERIAL_8250)
+ struct uart_port serial_req;
+
+ /* Setup serial port access */
+ memset(&serial_req, 0, sizeof(serial_req));
+ serial_req.uartclk = UART_CLK;
+ serial_req.irq = 4;
+ serial_req.flags = STD_COM_FLAGS;
+ serial_req.iotype = SERIAL_IO_MEM;
+ serial_req.membase = (u_char *) PPC7D_SERIAL_0;
+
+ gen550_init(0, &serial_req);
+ if (early_serial_setup(&serial_req) != 0)
+ printk(KERN_ERR "Early serial init of port 0 failed\n");
+
+ /* Assume early_serial_setup() doesn't modify serial_req */
+ serial_req.line = 1;
+ serial_req.irq = 3;
+ serial_req.membase = (u_char *) PPC7D_SERIAL_1;
+
+ gen550_init(1, &serial_req);
+ if (early_serial_setup(&serial_req) != 0)
+ printk(KERN_ERR "Early serial init of port 1 failed\n");
+#else
+#error CONFIG_KGDB || CONFIG_SERIAL_TEXT_DEBUG has no supported CONFIG_SERIAL_XXX
+#endif
+}
+#endif /* CONFIG_KGDB || CONFIG_SERIAL_TEXT_DEBUG */
+
+/*****************************************************************************
+ * Low-level board support code
+ *****************************************************************************/
+
+static unsigned long __init ppc7d_find_end_of_memory(void)
+{
+ bd_t *bp = (bd_t *) __res;
+
+ if (bp->bi_memsize)
+ return bp->bi_memsize;
+
+ return (256 * 1024 * 1024);
+}
+
+static void __init ppc7d_map_io(void)
+{
+ /* remove temporary mapping */
+ mtspr(SPRN_DBAT3U, 0x00000000);
+ mtspr(SPRN_DBAT3L, 0x00000000);
+
+ io_block_mapping(0xe8000000, 0xe8000000, 0x08000000, _PAGE_IO);
+ io_block_mapping(0xfe000000, 0xfe000000, 0x02000000, _PAGE_IO);
+}
+
+static void ppc7d_restart(char *cmd)
+{
+ u32 data;
+
+ /* Disable GPP17 interrupt */
+ data = mv64x60_read(&bh, MV64x60_GPP_INTR_MASK);
+ data &= ~(1 << PPC7D_RST_PIN);
+ mv64x60_write(&bh, MV64x60_GPP_INTR_MASK, data);
+
+ /* Configure MPP17 as GPP */
+ data = mv64x60_read(&bh, MV64x60_MPP_CNTL_2);
+ data &= ~(0x0000000f << 4);
+ mv64x60_write(&bh, MV64x60_MPP_CNTL_2, data);
+
+ /* Enable pin GPP17 for output */
+ data = mv64x60_read(&bh, MV64x60_GPP_IO_CNTL);
+ data |= (1 << PPC7D_RST_PIN);
+ mv64x60_write(&bh, MV64x60_GPP_IO_CNTL, data);
+
+ /* Toggle GPP9 pin to reset the board */
+ mv64x60_write(&bh, MV64x60_GPP_VALUE_CLR, 1 << PPC7D_RST_PIN);
+ mv64x60_write(&bh, MV64x60_GPP_VALUE_SET, 1 << PPC7D_RST_PIN);
+
+ for (;;) ; /* Spin until reset happens */
+ /* NOTREACHED */
+}
+
+static void ppc7d_power_off(void)
+{
+ u32 data;
+
+ local_irq_disable();
+
+ /* Ensure that internal MV643XX watchdog is disabled.
+ * The Disco watchdog uses MPP17 on this hardware.
+ */
+ data = mv64x60_read(&bh, MV64x60_MPP_CNTL_2);
+ data &= ~(0x0000000f << 4);
+ mv64x60_write(&bh, MV64x60_MPP_CNTL_2, data);
+
+ data = mv64x60_read(&bh, MV64x60_WDT_WDC);
+ if (data & 0x80000000) {
+ mv64x60_write(&bh, MV64x60_WDT_WDC, 1 << 24);
+ mv64x60_write(&bh, MV64x60_WDT_WDC, 2 << 24);
+ }
+
+ for (;;) ; /* No way to shut power off with software */
+ /* NOTREACHED */
+}
+
+static void ppc7d_halt(void)
+{
+ ppc7d_power_off();
+ /* NOTREACHED */
+}
+
+static unsigned long ppc7d_led_no_pulse;
+
+static int __init ppc7d_led_pulse_disable(char *str)
+{
+ ppc7d_led_no_pulse = 1;
+ return 1;
+}
+
+/* This kernel option disables the heartbeat pulsing of a board LED */
+__setup("ledoff", ppc7d_led_pulse_disable);
+
+static void ppc7d_heartbeat(void)
+{
+ u32 data32;
+ u8 data8;
+ static int max706_wdog = 0;
+
+ /* Unfortunately we can't access the LED control registers
+ * during early init because they're on the CPLD which is the
+ * other side of a PCI bridge which goes unreachable during
+ * PCI scan. So write the LEDs only if the MV64360 watchdog is
+ * enabled (i.e. userspace apps are running so kernel is up)..
+ */
+ data32 = mv64x60_read(&bh, MV64x60_WDT_WDC);
+ if (data32 & 0x80000000) {
+ /* Enable MAX706 watchdog if not done already */
+ if (!max706_wdog) {
+ outb(3, PPC7D_CPLD_RESET);
+ max706_wdog = 1;
+ }
+
+ /* Hit the MAX706 watchdog */
+ outb(0, PPC7D_CPLD_WATCHDOG_TRIG);
+
+ /* Pulse LED DS219 if not disabled */
+ if (!ppc7d_led_no_pulse) {
+ static int led_on = 0;
+
+ data8 = inb(PPC7D_CPLD_LEDS);
+ if (led_on)
+ data8 &= ~PPC7D_CPLD_LEDS_DS219_MASK;
+ else
+ data8 |= PPC7D_CPLD_LEDS_DS219_MASK;
+
+ outb(data8, PPC7D_CPLD_LEDS);
+ led_on = !led_on;
+ }
+ }
+ ppc_md.heartbeat_count = ppc_md.heartbeat_reset;
+}
+
+static int ppc7d_show_cpuinfo(struct seq_file *m)
+{
+ u8 val;
+ u8 val1, val2;
+ static int flash_sizes[4] = { 64, 32, 0, 16 };
+ static int flash_banks[4] = { 4, 3, 2, 1 };
+ static char *pci_modes[] = { "PCI33", "PCI66",
+ "Unknown", "Unknown",
+ "PCIX33", "PCIX66",
+ "PCIX100", "PCIX133"
+ };
+
+ seq_printf(m, "vendor\t\t: Radstone Technology\n");
+ seq_printf(m, "machine\t\t: PPC7D\n");
+
+ val = inb(PPC7D_CPLD_BOARD_REVISION);
+ val1 = (val & PPC7D_CPLD_BOARD_REVISION_NUMBER_MASK) >> 5;
+ val2 = (val & PPC7D_CPLD_BOARD_REVISION_LETTER_MASK);
+ seq_printf(m, "revision\t: %hd%c%c\n",
+ val1,
+ (val2 <= 0x18) ? 'A' + val2 : 'Y',
+ (val2 > 0x18) ? 'A' + (val2 - 0x19) : ' ');
+
+ val = inb(PPC7D_CPLD_MOTHERBOARD_TYPE);
+ val1 = val & PPC7D_CPLD_MB_TYPE_PLL_MASK;
+ val2 = val & (PPC7D_CPLD_MB_TYPE_ECC_FITTED_MASK |
+ PPC7D_CPLD_MB_TYPE_ECC_ENABLE_MASK);
+ seq_printf(m, "bus speed\t: %dMHz\n",
+ (val1 == PPC7D_CPLD_MB_TYPE_PLL_133) ? 133 :
+ (val1 == PPC7D_CPLD_MB_TYPE_PLL_100) ? 100 :
+ (val1 == PPC7D_CPLD_MB_TYPE_PLL_64) ? 64 : 0);
+
+ val = inb(PPC7D_CPLD_MEM_CONFIG_EXTEND);
+ val1 = val & PPC7D_CPLD_SDRAM_BANK_SIZE_MASK;
+ seq_printf(m, "SDRAM\t\t: %d%c",
+ (val1 == PPC7D_CPLD_SDRAM_BANK_SIZE_128M) ? 128 :
+ (val1 == PPC7D_CPLD_SDRAM_BANK_SIZE_256M) ? 256 :
+ (val1 == PPC7D_CPLD_SDRAM_BANK_SIZE_512M) ? 512 : 1,
+ (val1 == PPC7D_CPLD_SDRAM_BANK_SIZE_1G) ? 'G' : 'M');
+ if (val2 & PPC7D_CPLD_MB_TYPE_ECC_FITTED_MASK) {
+ seq_printf(m, " [ECC %sabled]",
+ (val2 & PPC7D_CPLD_MB_TYPE_ECC_ENABLE_MASK) ? "en" :
+ "dis");
+ }
+ seq_printf(m, "\n");
+
+ val1 = (val & PPC7D_CPLD_FLASH_DEV_SIZE_MASK);
+ val2 = (val & PPC7D_CPLD_FLASH_BANK_NUM_MASK) >> 2;
+ seq_printf(m, "FLASH\t\t: %d banks of %dM, total %dM\n",
+ flash_banks[val2], flash_sizes[val1],
+ flash_banks[val2] * flash_sizes[val1]);
+
+ val = inb(PPC7D_CPLD_FLASH_WRITE_CNTL);
+ val1 = inb(PPC7D_CPLD_SW_FLASH_WRITE_PROTECT);
+ seq_printf(m, " write links\t: %s%s%s%s\n",
+ (val & PPD7D_CPLD_FLASH_CNTL_WR_LINK_MASK) ? "WRITE " : "",
+ (val & PPD7D_CPLD_FLASH_CNTL_BOOT_LINK_MASK) ? "BOOT " : "",
+ (val & PPD7D_CPLD_FLASH_CNTL_USER_LINK_MASK) ? "USER " : "",
+ (val & (PPD7D_CPLD_FLASH_CNTL_WR_LINK_MASK |
+ PPD7D_CPLD_FLASH_CNTL_BOOT_LINK_MASK |
+ PPD7D_CPLD_FLASH_CNTL_USER_LINK_MASK)) ==
+ 0 ? "NONE" : "");
+ seq_printf(m, " write sector h/w enables: %s%s%s%s%s\n",
+ (val & PPD7D_CPLD_FLASH_CNTL_RECO_WR_MASK) ? "RECOVERY " :
+ "",
+ (val & PPD7D_CPLD_FLASH_CNTL_BOOT_WR_MASK) ? "BOOT " : "",
+ (val & PPD7D_CPLD_FLASH_CNTL_USER_WR_MASK) ? "USER " : "",
+ (val1 & PPC7D_CPLD_FLASH_CNTL_NVRAM_PROT_MASK) ? "NVRAM " :
+ "",
+ (((val &
+ (PPD7D_CPLD_FLASH_CNTL_RECO_WR_MASK |
+ PPD7D_CPLD_FLASH_CNTL_BOOT_WR_MASK |
+ PPD7D_CPLD_FLASH_CNTL_BOOT_WR_MASK)) == 0)
+ && ((val1 & PPC7D_CPLD_FLASH_CNTL_NVRAM_PROT_MASK) ==
+ 0)) ? "NONE" : "");
+ val1 =
+ inb(PPC7D_CPLD_SW_FLASH_WRITE_PROTECT) &
+ (PPC7D_CPLD_SW_FLASH_WRPROT_SYSBOOT_MASK |
+ PPC7D_CPLD_SW_FLASH_WRPROT_USER_MASK);
+ seq_printf(m, " software sector enables: %s%s%s\n",
+ (val1 & PPC7D_CPLD_SW_FLASH_WRPROT_SYSBOOT_MASK) ? "SYSBOOT "
+ : "",
+ (val1 & PPC7D_CPLD_SW_FLASH_WRPROT_USER_MASK) ? "USER " : "",
+ (val1 == 0) ? "NONE " : "");
+
+ seq_printf(m, "Boot options\t: %s%s%s%s\n",
+ (val & PPC7D_CPLD_FLASH_CNTL_ALTBOOT_LINK_MASK) ?
+ "ALTERNATE " : "",
+ (val & PPC7D_CPLD_FLASH_CNTL_VMEBOOT_LINK_MASK) ? "VME " :
+ "",
+ (val & PPC7D_CPLD_FLASH_CNTL_RECBOOT_LINK_MASK) ? "RECOVERY "
+ : "",
+ ((val &
+ (PPC7D_CPLD_FLASH_CNTL_ALTBOOT_LINK_MASK |
+ PPC7D_CPLD_FLASH_CNTL_VMEBOOT_LINK_MASK |
+ PPC7D_CPLD_FLASH_CNTL_RECBOOT_LINK_MASK)) ==
+ 0) ? "NONE" : "");
+
+ val = inb(PPC7D_CPLD_EQUIPMENT_PRESENT_1);
+ seq_printf(m, "Fitted modules\t: %s%s%s%s\n",
+ (val & PPC7D_CPLD_EQPT_PRES_1_PMC1_MASK) ? "" : "PMC1 ",
+ (val & PPC7D_CPLD_EQPT_PRES_1_PMC2_MASK) ? "" : "PMC2 ",
+ (val & PPC7D_CPLD_EQPT_PRES_1_AFIX_MASK) ? "AFIX " : "",
+ ((val & (PPC7D_CPLD_EQPT_PRES_1_PMC1_MASK |
+ PPC7D_CPLD_EQPT_PRES_1_PMC2_MASK |
+ PPC7D_CPLD_EQPT_PRES_1_AFIX_MASK)) ==
+ (PPC7D_CPLD_EQPT_PRES_1_PMC1_MASK |
+ PPC7D_CPLD_EQPT_PRES_1_PMC2_MASK)) ? "NONE" : "");
+
+ if (val & PPC7D_CPLD_EQPT_PRES_1_AFIX_MASK) {
+ static const char *ids[] = {
+ "unknown",
+ "1553 (Dual Channel)",
+ "1553 (Single Channel)",
+ "8-bit SCSI + VGA",
+ "16-bit SCSI + VGA",
+ "1553 (Single Channel with sideband)",
+ "1553 (Dual Channel with sideband)",
+ NULL
+ };
+ u8 id = __raw_readb((void *)PPC7D_AFIX_REG_BASE + 0x03);
+ seq_printf(m, "AFIX module\t: 0x%hx [%s]\n", id,
+ id < 7 ? ids[id] : "unknown");
+ }
+
+ val = inb(PPC7D_CPLD_PCI_CONFIG);
+ val1 = (val & PPC7D_CPLD_PCI_CONFIG_PCI0_MASK) >> 4;
+ val2 = (val & PPC7D_CPLD_PCI_CONFIG_PCI1_MASK);
+ seq_printf(m, "PCI#0\t\t: %s\nPCI#1\t\t: %s\n",
+ pci_modes[val1], pci_modes[val2]);
+
+ val = inb(PPC7D_CPLD_EQUIPMENT_PRESENT_2);
+ seq_printf(m, "PMC1\t\t: %s\nPMC2\t\t: %s\n",
+ (val & PPC7D_CPLD_EQPT_PRES_3_PMC1_V_MASK) ? "3.3v" : "5v",
+ (val & PPC7D_CPLD_EQPT_PRES_3_PMC2_V_MASK) ? "3.3v" : "5v");
+ seq_printf(m, "PMC power source: %s\n",
+ (val & PPC7D_CPLD_EQPT_PRES_3_PMC_POWER_MASK) ? "VME" :
+ "internal");
+
+ val = inb(PPC7D_CPLD_EQUIPMENT_PRESENT_4);
+ val2 = inb(PPC7D_CPLD_EQUIPMENT_PRESENT_2);
+ seq_printf(m, "Fit options\t: %s%s%s%s%s%s%s\n",
+ (val & PPC7D_CPLD_EQPT_PRES_4_LPT_MASK) ? "LPT " : "",
+ (val & PPC7D_CPLD_EQPT_PRES_4_PS2_FITTED) ? "PS2 " : "",
+ (val & PPC7D_CPLD_EQPT_PRES_4_USB2_FITTED) ? "USB2 " : "",
+ (val2 & PPC7D_CPLD_EQPT_PRES_2_UNIVERSE_MASK) ? "VME " : "",
+ (val2 & PPC7D_CPLD_EQPT_PRES_2_COM36_MASK) ? "COM3-6 " : "",
+ (val2 & PPC7D_CPLD_EQPT_PRES_2_GIGE_MASK) ? "eth0 " : "",
+ (val2 & PPC7D_CPLD_EQPT_PRES_2_DUALGIGE_MASK) ? "eth1 " :
+ "");
+
+ val = inb(PPC7D_CPLD_ID_LINK);
+ val1 = val & (PPC7D_CPLD_ID_LINK_E6_MASK |
+ PPC7D_CPLD_ID_LINK_E7_MASK |
+ PPC7D_CPLD_ID_LINK_E12_MASK |
+ PPC7D_CPLD_ID_LINK_E13_MASK);
+
+ val = inb(PPC7D_CPLD_FLASH_WRITE_CNTL) &
+ (PPD7D_CPLD_FLASH_CNTL_WR_LINK_MASK |
+ PPD7D_CPLD_FLASH_CNTL_BOOT_LINK_MASK |
+ PPD7D_CPLD_FLASH_CNTL_USER_LINK_MASK);
+
+ seq_printf(m, "Board links present: %s%s%s%s%s%s%s%s\n",
+ (val1 & PPC7D_CPLD_ID_LINK_E6_MASK) ? "E6 " : "",
+ (val1 & PPC7D_CPLD_ID_LINK_E7_MASK) ? "E7 " : "",
+ (val & PPD7D_CPLD_FLASH_CNTL_WR_LINK_MASK) ? "E9 " : "",
+ (val & PPD7D_CPLD_FLASH_CNTL_BOOT_LINK_MASK) ? "E10 " : "",
+ (val & PPD7D_CPLD_FLASH_CNTL_USER_LINK_MASK) ? "E11 " : "",
+ (val1 & PPC7D_CPLD_ID_LINK_E12_MASK) ? "E12 " : "",
+ (val1 & PPC7D_CPLD_ID_LINK_E13_MASK) ? "E13 " : "",
+ ((val == 0) && (val1 == 0)) ? "NONE" : "");
+
+ val = inb(PPC7D_CPLD_WDOG_RESETSW_MASK);
+ seq_printf(m, "Front panel reset switch: %sabled\n",
+ (val & PPC7D_CPLD_WDOG_RESETSW_MASK) ? "dis" : "en");
+
+ return 0;
+}
+
+static void __init ppc7d_calibrate_decr(void)
+{
+ ulong freq;
+
+ freq = 100000000 / 4;
+
+ pr_debug("time_init: decrementer frequency = %lu.%.6lu MHz\n",
+ freq / 1000000, freq % 1000000);
+
+ tb_ticks_per_jiffy = freq / HZ;
+ tb_to_us = mulhwu_scale_factor(freq, 1000000);
+}
+
+/*****************************************************************************
+ * Interrupt stuff
+ *****************************************************************************/
+
+static irqreturn_t ppc7d_i8259_intr(int irq, void *dev_id, struct pt_regs *regs)
+{
+ u32 temp = mv64x60_read(&bh, MV64x60_GPP_INTR_CAUSE);
+ if (temp & (1 << 28)) {
+ i8259_irq(regs);
+ mv64x60_write(&bh, MV64x60_GPP_INTR_CAUSE, temp & (~(1 << 28)));
+ return IRQ_HANDLED;
+ }
+
+ return IRQ_NONE;
+}
+
+/*
+ * Each interrupt cause is assigned an IRQ number.
+ * Southbridge has 16*2 (two 8259's) interrupts.
+ * Discovery-II has 96 interrupts (cause-hi, cause-lo, gpp x 32).
+ * If multiple interrupts are pending, get_irq() returns the
+ * lowest pending irq number first.
+ *
+ *
+ * IRQ # Source Trig Active
+ * =============================================================
+ *
+ * Southbridge
+ * -----------
+ * IRQ # Source Trig
+ * =============================================================
+ * 0 ISA High Resolution Counter Edge
+ * 1 Keyboard Edge
+ * 2 Cascade From (IRQ 8-15) Edge
+ * 3 Com 2 (Uart 2) Edge
+ * 4 Com 1 (Uart 1) Edge
+ * 5 PCI Int D/AFIX IRQZ ID4 (2,7) Level
+ * 6 GPIO Level
+ * 7 LPT Edge
+ * 8 RTC Alarm Edge
+ * 9 PCI Int A/PMC 2/AFIX IRQW ID1 (2,0) Level
+ * 10 PCI Int B/PMC 1/AFIX IRQX ID2 (2,1) Level
+ * 11 USB2 Level
+ * 12 Mouse Edge
+ * 13 Reserved internally by Ali M1535+
+ * 14 PCI Int C/VME/AFIX IRQY ID3 (2,6) Level
+ * 15 COM 5/6 Level
+ *
+ * 16..112 Discovery-II...
+ *
+ * MPP28 Southbridge Edge High
+ *
+ *
+ * Interrupts are cascaded through to the Discovery-II.
+ *
+ * PCI ---
+ * \
+ * CPLD --> ALI1535 -------> DISCOVERY-II
+ * INTF MPP28
+ */
+static void __init ppc7d_init_irq(void)
+{
+ int irq;
+
+ pr_debug("%s\n", __FUNCTION__);
+ i8259_init(0);
+ mv64360_init_irq();
+
+ /* IRQ 0..15 are handled by the cascaded 8259's of the Ali1535 */
+ for (irq = 0; irq < 16; irq++) {
+ irq_desc[irq].handler = &i8259_pic;
+ }
+ /* IRQs 5,6,9,10,11,14,15 are level sensitive */
+ irq_desc[5].status |= IRQ_LEVEL;
+ irq_desc[6].status |= IRQ_LEVEL;
+ irq_desc[9].status |= IRQ_LEVEL;
+ irq_desc[10].status |= IRQ_LEVEL;
+ irq_desc[11].status |= IRQ_LEVEL;
+ irq_desc[14].status |= IRQ_LEVEL;
+ irq_desc[15].status |= IRQ_LEVEL;
+
+ /* GPP28 is edge triggered */
+ irq_desc[mv64360_irq_base + MV64x60_IRQ_GPP28].status &= ~IRQ_LEVEL;
+}
+
+static u32 ppc7d_irq_canonicalize(u32 irq)
+{
+ if ((irq >= 16) && (irq < (16 + 96)))
+ irq -= 16;
+
+ return irq;
+}
+
+static int ppc7d_get_irq(struct pt_regs *regs)
+{
+ int irq;
+
+ irq = mv64360_get_irq(regs);
+ if (irq == (mv64360_irq_base + MV64x60_IRQ_GPP28))
+ irq = i8259_irq(regs);
+ return irq;
+}
+
+/*
+ * 9 PCI Int A/PMC 2/AFIX IRQW ID1 (2,0) Level
+ * 10 PCI Int B/PMC 1/AFIX IRQX ID2 (2,1) Level
+ * 14 PCI Int C/VME/AFIX IRQY ID3 (2,6) Level
+ * 5 PCI Int D/AFIX IRQZ ID4 (2,7) Level
+ */
+static int __init ppc7d_map_irq(struct pci_dev *dev, unsigned char idsel,
+ unsigned char pin)
+{
+ static const char pci_irq_table[][4] =
+ /*
+ * PCI IDSEL/INTPIN->INTLINE
+ * A B C D
+ */
+ {
+ {10, 14, 5, 9}, /* IDSEL 10 - PMC2 / AFIX IRQW */
+ {9, 10, 14, 5}, /* IDSEL 11 - PMC1 / AFIX IRQX */
+ {5, 9, 10, 14}, /* IDSEL 12 - AFIX IRQY */
+ {14, 5, 9, 10}, /* IDSEL 13 - AFIX IRQZ */
+ };
+ const long min_idsel = 10, max_idsel = 14, irqs_per_slot = 4;
+
+ pr_debug("%s: %04x/%04x/%x: idsel=%hx pin=%hu\n", __FUNCTION__,
+ dev->vendor, dev->device, PCI_FUNC(dev->devfn), idsel, pin);
+
+ return PCI_IRQ_TABLE_LOOKUP;
+}
+
+void __init ppc7d_intr_setup(void)
+{
+ u32 data;
+
+ /*
+ * Define GPP 28 interrupt polarity as active high
+ * input signal and level triggered
+ */
+ data = mv64x60_read(&bh, MV64x60_GPP_LEVEL_CNTL);
+ data &= ~(1 << 28);
+ mv64x60_write(&bh, MV64x60_GPP_LEVEL_CNTL, data);
+ data = mv64x60_read(&bh, MV64x60_GPP_IO_CNTL);
+ data &= ~(1 << 28);
+ mv64x60_write(&bh, MV64x60_GPP_IO_CNTL, data);
+
+ /* Config GPP intr ctlr to respond to level trigger */
+ data = mv64x60_read(&bh, MV64x60_COMM_ARBITER_CNTL);
+ data |= (1 << 10);
+ mv64x60_write(&bh, MV64x60_COMM_ARBITER_CNTL, data);
+
+ /* XXXX Erranum FEr PCI-#8 */
+ data = mv64x60_read(&bh, MV64x60_PCI0_CMD);
+ data &= ~((1 << 5) | (1 << 9));
+ mv64x60_write(&bh, MV64x60_PCI0_CMD, data);
+ data = mv64x60_read(&bh, MV64x60_PCI1_CMD);
+ data &= ~((1 << 5) | (1 << 9));
+ mv64x60_write(&bh, MV64x60_PCI1_CMD, data);
+
+ /*
+ * Dismiss and then enable interrupt on GPP interrupt cause
+ * for CPU #0
+ */
+ mv64x60_write(&bh, MV64x60_GPP_INTR_CAUSE, ~(1 << 28));
+ data = mv64x60_read(&bh, MV64x60_GPP_INTR_MASK);
+ data |= (1 << 28);
+ mv64x60_write(&bh, MV64x60_GPP_INTR_MASK, data);
+
+ /*
+ * Dismiss and then enable interrupt on CPU #0 high cause reg
+ * BIT27 summarizes GPP interrupts 23-31
+ */
+ mv64x60_write(&bh, MV64360_IC_MAIN_CAUSE_HI, ~(1 << 27));
+ data = mv64x60_read(&bh, MV64360_IC_CPU0_INTR_MASK_HI);
+ data |= (1 << 27);
+ mv64x60_write(&bh, MV64360_IC_CPU0_INTR_MASK_HI, data);
+}
+
+/*****************************************************************************
+ * Platform device data fixup routines.
+ *****************************************************************************/
+
+#if defined(CONFIG_SERIAL_MPSC)
+static void __init ppc7d_fixup_mpsc_pdata(struct platform_device *pdev)
+{
+ struct mpsc_pdata *pdata;
+
+ pdata = (struct mpsc_pdata *)pdev->dev.platform_data;
+
+ pdata->max_idle = 40;
+ pdata->default_baud = PPC7D_DEFAULT_BAUD;
+ pdata->brg_clk_src = PPC7D_MPSC_CLK_SRC;
+ pdata->brg_clk_freq = PPC7D_MPSC_CLK_FREQ;
+
+ return;
+}
+#endif
+
+#if defined(CONFIG_MV643XX_ETH)
+static void __init ppc7d_fixup_eth_pdata(struct platform_device *pdev)
+{
+ struct mv643xx_eth_platform_data *eth_pd;
+ static u16 phy_addr[] = {
+ PPC7D_ETH0_PHY_ADDR,
+ PPC7D_ETH1_PHY_ADDR,
+ PPC7D_ETH2_PHY_ADDR,
+ };
+ int i;
+
+ eth_pd = pdev->dev.platform_data;
+ eth_pd->force_phy_addr = 1;
+ eth_pd->phy_addr = phy_addr[pdev->id];
+ eth_pd->tx_queue_size = PPC7D_ETH_TX_QUEUE_SIZE;
+ eth_pd->rx_queue_size = PPC7D_ETH_RX_QUEUE_SIZE;
+
+ /* Adjust IRQ by mv64360_irq_base */
+ for (i = 0; i < pdev->num_resources; i++) {
+ struct resource *r = &pdev->resource[i];
+
+ if (r->flags & IORESOURCE_IRQ) {
+ r->start += mv64360_irq_base;
+ r->end += mv64360_irq_base;
+ pr_debug("%s, uses IRQ %d\n", pdev->name,
+ (int)r->start);
+ }
+ }
+
+}
+#endif
+
+#if defined(CONFIG_I2C_MV64XXX)
+static void __init
+ppc7d_fixup_i2c_pdata(struct platform_device *pdev)
+{
+ struct mv64xxx_i2c_pdata *pdata;
+ int i;
+
+ pdata = pdev->dev.platform_data;
+ if (pdata == NULL) {
+ pdata = kmalloc(sizeof(*pdata), GFP_KERNEL);
+ if (pdata == NULL)
+ return;
+
+ memset(pdata, 0, sizeof(*pdata));
+ pdev->dev.platform_data = pdata;
+ }
+
+ /* divisors M=8, N=3 for 100kHz I2C from 133MHz system clock */
+ pdata->freq_m = 8;
+ pdata->freq_n = 3;
+ pdata->timeout = 500;
+ pdata->retries = 3;
+
+ /* Adjust IRQ by mv64360_irq_base */
+ for (i = 0; i < pdev->num_resources; i++) {
+ struct resource *r = &pdev->resource[i];
+
+ if (r->flags & IORESOURCE_IRQ) {
+ r->start += mv64360_irq_base;
+ r->end += mv64360_irq_base;
+ pr_debug("%s, uses IRQ %d\n", pdev->name, (int) r->start);
+ }
+ }
+}
+#endif
+
+static int __init ppc7d_platform_notify(struct device *dev)
+{
+ static struct {
+ char *bus_id;
+ void ((*rtn) (struct platform_device * pdev));
+ } dev_map[] = {
+#if defined(CONFIG_SERIAL_MPSC)
+ { MPSC_CTLR_NAME ".0", ppc7d_fixup_mpsc_pdata },
+ { MPSC_CTLR_NAME ".1", ppc7d_fixup_mpsc_pdata },
+#endif
+#if defined(CONFIG_MV643XX_ETH)
+ { MV643XX_ETH_NAME ".0", ppc7d_fixup_eth_pdata },
+ { MV643XX_ETH_NAME ".1", ppc7d_fixup_eth_pdata },
+ { MV643XX_ETH_NAME ".2", ppc7d_fixup_eth_pdata },
+#endif
+#if defined(CONFIG_I2C_MV64XXX)
+ { MV64XXX_I2C_CTLR_NAME ".0", ppc7d_fixup_i2c_pdata },
+#endif
+ };
+ struct platform_device *pdev;
+ int i;
+
+ if (dev && dev->bus_id)
+ for (i = 0; i < ARRAY_SIZE(dev_map); i++)
+ if (!strncmp(dev->bus_id, dev_map[i].bus_id,
+ BUS_ID_SIZE)) {
+
+ pdev = container_of(dev,
+ struct platform_device,
+ dev);
+ dev_map[i].rtn(pdev);
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+ * PCI device fixups.
+ * These aren't really fixups per se. They are used to init devices as they
+ * are found during PCI scan.
+ *
+ * The PPC7D has an HB8 PCI-X bridge which must be set up during a PCI
+ * scan in order to find other devices on its secondary side.
+ *****************************************************************************/
+
+static void __init ppc7d_fixup_hb8(struct pci_dev *dev)
+{
+ u16 val16;
+
+ if (dev->bus->number == 0) {
+ pr_debug("PCI: HB8 init\n");
+
+ pci_write_config_byte(dev, 0x1c,
+ ((PPC7D_PCI0_IO_START_PCI_ADDR & 0xf000)
+ >> 8) | 0x01);
+ pci_write_config_byte(dev, 0x1d,
+ (((PPC7D_PCI0_IO_START_PCI_ADDR +
+ PPC7D_PCI0_IO_SIZE -
+ 1) & 0xf000) >> 8) | 0x01);
+ pci_write_config_word(dev, 0x30,
+ PPC7D_PCI0_IO_START_PCI_ADDR >> 16);
+ pci_write_config_word(dev, 0x32,
+ ((PPC7D_PCI0_IO_START_PCI_ADDR +
+ PPC7D_PCI0_IO_SIZE -
+ 1) >> 16) & 0xffff);
+
+ pci_write_config_word(dev, 0x20,
+ PPC7D_PCI0_MEM0_START_PCI_LO_ADDR >> 16);
+ pci_write_config_word(dev, 0x22,
+ ((PPC7D_PCI0_MEM0_START_PCI_LO_ADDR +
+ PPC7D_PCI0_MEM0_SIZE -
+ 1) >> 16) & 0xffff);
+ pci_write_config_word(dev, 0x24, 0);
+ pci_write_config_word(dev, 0x26, 0);
+ pci_write_config_dword(dev, 0x28, 0);
+ pci_write_config_dword(dev, 0x2c, 0);
+
+ pci_read_config_word(dev, 0x3e, &val16);
+ val16 |= ((1 << 5) | (1 << 1)); /* signal master aborts and
+ * SERR to primary
+ */
+ val16 &= ~(1 << 2); /* ISA disable, so all ISA
+ * ports forwarded to secondary
+ */
+ pci_write_config_word(dev, 0x3e, val16);
+ }
+}
+
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_HINT, 0x0028, ppc7d_fixup_hb8);
+
+/* This should perhaps be a separate driver as we're actually initializing
+ * the chip for this board here. It's hardly a fixup...
+ */
+static void __init ppc7d_fixup_ali1535(struct pci_dev *dev)
+{
+ pr_debug("PCI: ALI1535 init\n");
+
+ if (dev->bus->number == 1) {
+ /* Configure the ISA Port Settings */
+ pci_write_config_byte(dev, 0x43, 0x00);
+
+ /* Disable PCI Interrupt polling mode */
+ pci_write_config_byte(dev, 0x45, 0x00);
+
+ /* Multifunction pin select INTFJ -> INTF */
+ pci_write_config_byte(dev, 0x78, 0x00);
+
+ /* Set PCI INT -> IRQ Routing control in for external
+ * pins south bridge.
+ */
+ pci_write_config_byte(dev, 0x48, 0x31); /* [7-4] INT B -> IRQ10
+ * [3-0] INT A -> IRQ9
+ */
+ pci_write_config_byte(dev, 0x49, 0x5D); /* [7-4] INT D -> IRQ5
+ * [3-0] INT C -> IRQ14
+ */
+
+ /* PPC7D setup */
+ /* NEC USB device on IRQ 11 (INTE) - INTF disabled */
+ pci_write_config_byte(dev, 0x4A, 0x09);
+
+ /* GPIO on IRQ 6 */
+ pci_write_config_byte(dev, 0x76, 0x07);
+
+ /* SIRQ I (COMS 5/6) use IRQ line 15.
+ * Positive (not subtractive) address decode.
+ */
+ pci_write_config_byte(dev, 0x44, 0x0f);
+
+ /* SIRQ II disabled */
+ pci_write_config_byte(dev, 0x75, 0x0);
+
+ /* On board USB and RTC disabled */
+ pci_write_config_word(dev, 0x52, (1 << 14));
+ pci_write_config_byte(dev, 0x74, 0x00);
+
+ /* On board IDE disabled */
+ pci_write_config_byte(dev, 0x58, 0x00);
+
+ /* Decode 32-bit addresses */
+ pci_write_config_byte(dev, 0x5b, 0);
+
+ /* Disable docking IO */
+ pci_write_config_word(dev, 0x5c, 0x0000);
+
+ /* Disable modem, enable sound */
+ pci_write_config_byte(dev, 0x77, (1 << 6));
+
+ /* Disable hot-docking mode */
+ pci_write_config_byte(dev, 0x7d, 0x00);
+ }
+}
+
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x1533, ppc7d_fixup_ali1535);
+
+static int ppc7d_pci_exclude_device(u8 bus, u8 devfn)
+{
+ /* Early versions of this board were fitted with IBM ALMA
+ * PCI-VME bridge chips. The PCI config space of these devices
+ * was not set up correctly and causes PCI scan problems.
+ */
+ if ((bus == 1) && (PCI_SLOT(devfn) == 4) && ppc7d_has_alma)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ return mv64x60_pci_exclude_device(bus, devfn);
+}
+
+/* This hook is called when each PCI bus is probed.
+ */
+static void ppc7d_pci_fixup_bus(struct pci_bus *bus)
+{
+ pr_debug("PCI BUS %hu: %lx/%lx %lx/%lx %lx/%lx %lx/%lx\n",
+ bus->number,
+ bus->resource[0] ? bus->resource[0]->start : 0,
+ bus->resource[0] ? bus->resource[0]->end : 0,
+ bus->resource[1] ? bus->resource[1]->start : 0,
+ bus->resource[1] ? bus->resource[1]->end : 0,
+ bus->resource[2] ? bus->resource[2]->start : 0,
+ bus->resource[2] ? bus->resource[2]->end : 0,
+ bus->resource[3] ? bus->resource[3]->start : 0,
+ bus->resource[3] ? bus->resource[3]->end : 0);
+
+ if ((bus->number == 1) && (bus->resource[2] != NULL)) {
+ /* Hide PCI window 2 of Bus 1 which is used only to
+ * map legacy ISA memory space.
+ */
+ bus->resource[2]->start = 0;
+ bus->resource[2]->end = 0;
+ bus->resource[2]->flags = 0;
+ }
+}
+
+/*****************************************************************************
+ * Board device setup code
+ *****************************************************************************/
+
+void __init ppc7d_setup_peripherals(void)
+{
+ u32 val32;
+
+ /* Set up windows for boot CS */
+ mv64x60_set_32bit_window(&bh, MV64x60_CPU2BOOT_WIN,
+ PPC7D_BOOT_WINDOW_BASE, PPC7D_BOOT_WINDOW_SIZE,
+ 0);
+ bh.ci->enable_window_32bit(&bh, MV64x60_CPU2BOOT_WIN);
+
+ /* Boot firmware configures the following DevCS addresses.
+ * DevCS0 - board control/status
+ * DevCS1 - test registers
+ * DevCS2 - AFIX port/address registers (for identifying)
+ * DevCS3 - FLASH
+ *
+ * We don't use DevCS0, DevCS1.
+ */
+ val32 = mv64x60_read(&bh, MV64360_CPU_BAR_ENABLE);
+ val32 |= ((1 << 4) | (1 << 5));
+ mv64x60_write(&bh, MV64360_CPU_BAR_ENABLE, val32);
+ mv64x60_write(&bh, MV64x60_CPU2DEV_0_BASE, 0);
+ mv64x60_write(&bh, MV64x60_CPU2DEV_0_SIZE, 0);
+ mv64x60_write(&bh, MV64x60_CPU2DEV_1_BASE, 0);
+ mv64x60_write(&bh, MV64x60_CPU2DEV_1_SIZE, 0);
+
+ mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_2_WIN,
+ PPC7D_AFIX_REG_BASE, PPC7D_AFIX_REG_SIZE, 0);
+ bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_2_WIN);
+
+ mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_3_WIN,
+ PPC7D_FLASH_BASE, PPC7D_FLASH_SIZE_ACTUAL, 0);
+ bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_3_WIN);
+
+ mv64x60_set_32bit_window(&bh, MV64x60_CPU2SRAM_WIN,
+ PPC7D_INTERNAL_SRAM_BASE, MV64360_SRAM_SIZE,
+ 0);
+ bh.ci->enable_window_32bit(&bh, MV64x60_CPU2SRAM_WIN);
+
+ /* Set up Enet->SRAM window */
+ mv64x60_set_32bit_window(&bh, MV64x60_ENET2MEM_4_WIN,
+ PPC7D_INTERNAL_SRAM_BASE, MV64360_SRAM_SIZE,
+ 0x2);
+ bh.ci->enable_window_32bit(&bh, MV64x60_ENET2MEM_4_WIN);
+
+ /* Give enet r/w access to memory region */
+ val32 = mv64x60_read(&bh, MV64360_ENET2MEM_ACC_PROT_0);
+ val32 |= (0x3 << (4 << 1));
+ mv64x60_write(&bh, MV64360_ENET2MEM_ACC_PROT_0, val32);
+ val32 = mv64x60_read(&bh, MV64360_ENET2MEM_ACC_PROT_1);
+ val32 |= (0x3 << (4 << 1));
+ mv64x60_write(&bh, MV64360_ENET2MEM_ACC_PROT_1, val32);
+ val32 = mv64x60_read(&bh, MV64360_ENET2MEM_ACC_PROT_2);
+ val32 |= (0x3 << (4 << 1));
+ mv64x60_write(&bh, MV64360_ENET2MEM_ACC_PROT_2, val32);
+
+ val32 = mv64x60_read(&bh, MV64x60_TIMR_CNTR_0_3_CNTL);
+ val32 &= ~((1 << 0) | (1 << 8) | (1 << 16) | (1 << 24));
+ mv64x60_write(&bh, MV64x60_TIMR_CNTR_0_3_CNTL, val32);
+
+ /* Enumerate pci bus.
+ *
+ * We scan PCI#0 first (the bus with the HB8 and other
+ * on-board peripherals). We must configure the 64360 before
+ * each scan, according to the bus number assignments. Busses
+ * are assigned incrementally, starting at 0. PCI#0 is
+ * usually assigned bus#0, the secondary side of the HB8 gets
+ * bus#1 and PCI#1 (second PMC site) gets bus#2. However, if
+ * any PMC card has a PCI bridge, these bus assignments will
+ * change.
+ */
+
+ /* Turn off PCI retries */
+ val32 = mv64x60_read(&bh, MV64x60_CPU_CONFIG);
+ val32 |= (1 << 17);
+ mv64x60_write(&bh, MV64x60_CPU_CONFIG, val32);
+
+ /* Scan PCI#0 */
+ mv64x60_set_bus(&bh, 0, 0);
+ bh.hose_a->first_busno = 0;
+ bh.hose_a->last_busno = 0xff;
+ bh.hose_a->last_busno = pciauto_bus_scan(bh.hose_a, 0);
+ printk(KERN_INFO "PCI#0: first=%d last=%d\n",
+ bh.hose_a->first_busno, bh.hose_a->last_busno);
+
+ /* Scan PCI#1 */
+ bh.hose_b->first_busno = bh.hose_a->last_busno + 1;
+ mv64x60_set_bus(&bh, 1, bh.hose_b->first_busno);
+ bh.hose_b->last_busno = 0xff;
+ bh.hose_b->last_busno = pciauto_bus_scan(bh.hose_b,
+ bh.hose_b->first_busno);
+ printk(KERN_INFO "PCI#1: first=%d last=%d\n",
+ bh.hose_b->first_busno, bh.hose_b->last_busno);
+
+ /* Turn on PCI retries */
+ val32 = mv64x60_read(&bh, MV64x60_CPU_CONFIG);
+ val32 &= ~(1 << 17);
+ mv64x60_write(&bh, MV64x60_CPU_CONFIG, val32);
+
+ /* Setup interrupts */
+ ppc7d_intr_setup();
+}
+
+static void __init ppc7d_setup_bridge(void)
+{
+ struct mv64x60_setup_info si;
+ int i;
+ u32 temp;
+
+ mv64360_irq_base = 16; /* first 16 intrs are 2 x 8259's */
+
+ memset(&si, 0, sizeof(si));
+
+ si.phys_reg_base = CONFIG_MV64X60_NEW_BASE;
+
+ si.pci_0.enable_bus = 1;
+ si.pci_0.pci_io.cpu_base = PPC7D_PCI0_IO_START_PROC_ADDR;
+ si.pci_0.pci_io.pci_base_hi = 0;
+ si.pci_0.pci_io.pci_base_lo = PPC7D_PCI0_IO_START_PCI_ADDR;
+ si.pci_0.pci_io.size = PPC7D_PCI0_IO_SIZE;
+ si.pci_0.pci_io.swap = MV64x60_CPU2PCI_SWAP_NONE;
+ si.pci_0.pci_mem[0].cpu_base = PPC7D_PCI0_MEM0_START_PROC_ADDR;
+ si.pci_0.pci_mem[0].pci_base_hi = PPC7D_PCI0_MEM0_START_PCI_HI_ADDR;
+ si.pci_0.pci_mem[0].pci_base_lo = PPC7D_PCI0_MEM0_START_PCI_LO_ADDR;
+ si.pci_0.pci_mem[0].size = PPC7D_PCI0_MEM0_SIZE;
+ si.pci_0.pci_mem[0].swap = MV64x60_CPU2PCI_SWAP_NONE;
+ si.pci_0.pci_mem[1].cpu_base = PPC7D_PCI0_MEM1_START_PROC_ADDR;
+ si.pci_0.pci_mem[1].pci_base_hi = PPC7D_PCI0_MEM1_START_PCI_HI_ADDR;
+ si.pci_0.pci_mem[1].pci_base_lo = PPC7D_PCI0_MEM1_START_PCI_LO_ADDR;
+ si.pci_0.pci_mem[1].size = PPC7D_PCI0_MEM1_SIZE;
+ si.pci_0.pci_mem[1].swap = MV64x60_CPU2PCI_SWAP_NONE;
+ si.pci_0.pci_cmd_bits = 0;
+ si.pci_0.latency_timer = 0x80;
+
+ si.pci_1.enable_bus = 1;
+ si.pci_1.pci_io.cpu_base = PPC7D_PCI1_IO_START_PROC_ADDR;
+ si.pci_1.pci_io.pci_base_hi = 0;
+ si.pci_1.pci_io.pci_base_lo = PPC7D_PCI1_IO_START_PCI_ADDR;
+ si.pci_1.pci_io.size = PPC7D_PCI1_IO_SIZE;
+ si.pci_1.pci_io.swap = MV64x60_CPU2PCI_SWAP_NONE;
+ si.pci_1.pci_mem[0].cpu_base = PPC7D_PCI1_MEM0_START_PROC_ADDR;
+ si.pci_1.pci_mem[0].pci_base_hi = PPC7D_PCI1_MEM0_START_PCI_HI_ADDR;
+ si.pci_1.pci_mem[0].pci_base_lo = PPC7D_PCI1_MEM0_START_PCI_LO_ADDR;
+ si.pci_1.pci_mem[0].size = PPC7D_PCI1_MEM0_SIZE;
+ si.pci_1.pci_mem[0].swap = MV64x60_CPU2PCI_SWAP_NONE;
+ si.pci_1.pci_mem[1].cpu_base = PPC7D_PCI1_MEM1_START_PROC_ADDR;
+ si.pci_1.pci_mem[1].pci_base_hi = PPC7D_PCI1_MEM1_START_PCI_HI_ADDR;
+ si.pci_1.pci_mem[1].pci_base_lo = PPC7D_PCI1_MEM1_START_PCI_LO_ADDR;
+ si.pci_1.pci_mem[1].size = PPC7D_PCI1_MEM1_SIZE;
+ si.pci_1.pci_mem[1].swap = MV64x60_CPU2PCI_SWAP_NONE;
+ si.pci_1.pci_cmd_bits = 0;
+ si.pci_1.latency_timer = 0x80;
+
+ /* Don't clear the SRAM window since we use it for debug */
+ si.window_preserve_mask_32_lo = (1 << MV64x60_CPU2SRAM_WIN);
+
+ printk(KERN_INFO "PCI: MV64360 PCI#0 IO at %x, size %x\n",
+ si.pci_0.pci_io.cpu_base, si.pci_0.pci_io.size);
+ printk(KERN_INFO "PCI: MV64360 PCI#1 IO at %x, size %x\n",
+ si.pci_1.pci_io.cpu_base, si.pci_1.pci_io.size);
+
+ for (i = 0; i < MV64x60_CPU2MEM_WINDOWS; i++) {
+#if defined(CONFIG_NOT_COHERENT_CACHE)
+ si.cpu_prot_options[i] = 0;
+ si.enet_options[i] = MV64360_ENET2MEM_SNOOP_NONE;
+ si.mpsc_options[i] = MV64360_MPSC2MEM_SNOOP_NONE;
+ si.idma_options[i] = MV64360_IDMA2MEM_SNOOP_NONE;
+
+ si.pci_0.acc_cntl_options[i] =
+ MV64360_PCI_ACC_CNTL_SNOOP_NONE |
+ MV64360_PCI_ACC_CNTL_SWAP_NONE |
+ MV64360_PCI_ACC_CNTL_MBURST_128_BYTES |
+ MV64360_PCI_ACC_CNTL_RDSIZE_256_BYTES;
+
+ si.pci_1.acc_cntl_options[i] =
+ MV64360_PCI_ACC_CNTL_SNOOP_NONE |
+ MV64360_PCI_ACC_CNTL_SWAP_NONE |
+ MV64360_PCI_ACC_CNTL_MBURST_128_BYTES |
+ MV64360_PCI_ACC_CNTL_RDSIZE_256_BYTES;
+#else
+ si.cpu_prot_options[i] = 0;
+ /* All PPC7D hardware uses B0 or newer MV64360 silicon which
+ * does not have snoop bugs.
+ */
+ si.enet_options[i] = MV64360_ENET2MEM_SNOOP_WB;
+ si.mpsc_options[i] = MV64360_MPSC2MEM_SNOOP_WB;
+ si.idma_options[i] = MV64360_IDMA2MEM_SNOOP_WB;
+
+ si.pci_0.acc_cntl_options[i] =
+ MV64360_PCI_ACC_CNTL_SNOOP_WB |
+ MV64360_PCI_ACC_CNTL_SWAP_NONE |
+ MV64360_PCI_ACC_CNTL_MBURST_32_BYTES |
+ MV64360_PCI_ACC_CNTL_RDSIZE_32_BYTES;
+
+ si.pci_1.acc_cntl_options[i] =
+ MV64360_PCI_ACC_CNTL_SNOOP_WB |
+ MV64360_PCI_ACC_CNTL_SWAP_NONE |
+ MV64360_PCI_ACC_CNTL_MBURST_32_BYTES |
+ MV64360_PCI_ACC_CNTL_RDSIZE_32_BYTES;
+#endif
+ }
+
+ /* Lookup PCI host bridges */
+ if (mv64x60_init(&bh, &si))
+ printk(KERN_ERR "MV64360 initialization failed.\n");
+
+ pr_debug("MV64360 regs @ %lx/%p\n", bh.p_base, bh.v_base);
+
+ /* Enable WB Cache coherency on SRAM */
+ temp = mv64x60_read(&bh, MV64360_SRAM_CONFIG);
+ pr_debug("SRAM_CONFIG: %x\n", temp);
+#if defined(CONFIG_NOT_COHERENT_CACHE)
+ mv64x60_write(&bh, MV64360_SRAM_CONFIG, temp & ~0x2);
+#else
+ mv64x60_write(&bh, MV64360_SRAM_CONFIG, temp | 0x2);
+#endif
+ /* If system operates with internal bus arbiter (CPU master
+ * control bit8) clear AACK Delay bit [25] in CPU
+ * configuration register.
+ */
+ temp = mv64x60_read(&bh, MV64x60_CPU_MASTER_CNTL);
+ if (temp & (1 << 8)) {
+ temp = mv64x60_read(&bh, MV64x60_CPU_CONFIG);
+ mv64x60_write(&bh, MV64x60_CPU_CONFIG, (temp & ~(1 << 25)));
+ }
+
+ /* Data and address parity is enabled */
+ temp = mv64x60_read(&bh, MV64x60_CPU_CONFIG);
+ mv64x60_write(&bh, MV64x60_CPU_CONFIG,
+ (temp | (1 << 26) | (1 << 19)));
+
+ pci_dram_offset = 0; /* sys mem at same addr on PCI & cpu bus */
+ ppc_md.pci_swizzle = common_swizzle;
+ ppc_md.pci_map_irq = ppc7d_map_irq;
+ ppc_md.pci_exclude_device = ppc7d_pci_exclude_device;
+
+ mv64x60_set_bus(&bh, 0, 0);
+ bh.hose_a->first_busno = 0;
+ bh.hose_a->last_busno = 0xff;
+ bh.hose_a->mem_space.start = PPC7D_PCI0_MEM0_START_PCI_LO_ADDR;
+ bh.hose_a->mem_space.end =
+ PPC7D_PCI0_MEM0_START_PCI_LO_ADDR + PPC7D_PCI0_MEM0_SIZE;
+
+ /* These will be set later, as a result of PCI0 scan */
+ bh.hose_b->first_busno = 0;
+ bh.hose_b->last_busno = 0xff;
+ bh.hose_b->mem_space.start = PPC7D_PCI1_MEM0_START_PCI_LO_ADDR;
+ bh.hose_b->mem_space.end =
+ PPC7D_PCI1_MEM0_START_PCI_LO_ADDR + PPC7D_PCI1_MEM0_SIZE;
+
+ pr_debug("MV64360: PCI#0 IO decode %08x/%08x IO remap %08x\n",
+ mv64x60_read(&bh, 0x48), mv64x60_read(&bh, 0x50),
+ mv64x60_read(&bh, 0xf0));
+}
+
+static void __init ppc7d_setup_arch(void)
+{
+ int port;
+
+ loops_per_jiffy = 100000000 / HZ;
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (initrd_start)
+ ROOT_DEV = Root_RAM0;
+ else
+#endif
+#ifdef CONFIG_ROOT_NFS
+ ROOT_DEV = Root_NFS;
+#else
+ ROOT_DEV = Root_HDA1;
+#endif
+
+ if ((cur_cpu_spec[0]->cpu_features & CPU_FTR_SPEC7450) ||
+ (cur_cpu_spec[0]->cpu_features & CPU_FTR_L3CR))
+ /* 745x is different. We only want to pass along enable. */
+ _set_L2CR(L2CR_L2E);
+ else if (cur_cpu_spec[0]->cpu_features & CPU_FTR_L2CR)
+ /* All modules have 1MB of L2. We also assume that an
+ * L2 divisor of 3 will work.
+ */
+ _set_L2CR(L2CR_L2E | L2CR_L2SIZ_1MB | L2CR_L2CLK_DIV3
+ | L2CR_L2RAM_PIPE | L2CR_L2OH_1_0 | L2CR_L2DF);
+
+ if (cur_cpu_spec[0]->cpu_features & CPU_FTR_L3CR)
+ /* No L3 cache */
+ _set_L3CR(0);
+
+#ifdef CONFIG_DUMMY_CONSOLE
+ conswitchp = &dummy_con;
+#endif
+
+ /* Lookup PCI host bridges */
+ if (ppc_md.progress)
+ ppc_md.progress("ppc7d_setup_arch: calling setup_bridge", 0);
+
+ ppc7d_setup_bridge();
+ ppc7d_setup_peripherals();
+
+ /* Disable ethernet. It might have been setup by the bootrom */
+ for (port = 0; port < 3; port++)
+ mv64x60_write(&bh, MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port),
+ 0x0000ff00);
+
+ /* Clear queue pointers to ensure they are all initialized,
+ * otherwise since queues 1-7 are unused, they have random
+ * pointers which look strange in register dumps. Don't bother
+ * with queue 0 since it will be initialized later.
+ */
+ for (port = 0; port < 3; port++) {
+ mv64x60_write(&bh,
+ MV643XX_ETH_RX_CURRENT_QUEUE_DESC_PTR_1(port),
+ 0x00000000);
+ mv64x60_write(&bh,
+ MV643XX_ETH_RX_CURRENT_QUEUE_DESC_PTR_2(port),
+ 0x00000000);
+ mv64x60_write(&bh,
+ MV643XX_ETH_RX_CURRENT_QUEUE_DESC_PTR_3(port),
+ 0x00000000);
+ mv64x60_write(&bh,
+ MV643XX_ETH_RX_CURRENT_QUEUE_DESC_PTR_4(port),
+ 0x00000000);
+ mv64x60_write(&bh,
+ MV643XX_ETH_RX_CURRENT_QUEUE_DESC_PTR_5(port),
+ 0x00000000);
+ mv64x60_write(&bh,
+ MV643XX_ETH_RX_CURRENT_QUEUE_DESC_PTR_6(port),
+ 0x00000000);
+ mv64x60_write(&bh,
+ MV643XX_ETH_RX_CURRENT_QUEUE_DESC_PTR_7(port),
+ 0x00000000);
+ }
+
+ printk(KERN_INFO "Radstone Technology PPC7D\n");
+ if (ppc_md.progress)
+ ppc_md.progress("ppc7d_setup_arch: exit", 0);
+}
+
+/* This kernel command line parameter can be used to have the target
+ * wait for a JTAG debugger to attach. Of course, a JTAG debugger
+ * with hardware breakpoint support can have the target stop at any
+ * location during init, but this is a convenience feature that makes
+ * it easier in the common case of loading the code using the ppcboot
+ * bootloader..
+ */
+static unsigned long ppc7d_wait_debugger;
+
+static int __init ppc7d_waitdbg(char *str)
+{
+ ppc7d_wait_debugger = 1;
+ return 1;
+}
+
+__setup("waitdbg", ppc7d_waitdbg);
+
+/* Second phase board init, called after other (architecture common)
+ * low-level services have been initialized.
+ */
+static void ppc7d_init2(void)
+{
+ unsigned long flags;
+ u32 data;
+ u8 data8;
+
+ pr_debug("%s: enter\n", __FUNCTION__);
+
+ /* Wait for debugger? */
+ if (ppc7d_wait_debugger) {
+ printk("Waiting for debugger...\n");
+
+ while (readl(&ppc7d_wait_debugger)) ;
+ }
+
+ /* Hook up i8259 interrupt which is connected to GPP28 */
+ request_irq(mv64360_irq_base + MV64x60_IRQ_GPP28, ppc7d_i8259_intr,
+ SA_INTERRUPT, "I8259 (GPP28) interrupt", (void *)0);
+
+ /* Configure MPP16 as watchdog NMI, MPP17 as watchdog WDE */
+ spin_lock_irqsave(&mv64x60_lock, flags);
+ data = mv64x60_read(&bh, MV64x60_MPP_CNTL_2);
+ data &= ~(0x0000000f << 0);
+ data |= (0x00000004 << 0);
+ data &= ~(0x0000000f << 4);
+ data |= (0x00000004 << 4);
+ mv64x60_write(&bh, MV64x60_MPP_CNTL_2, data);
+ spin_unlock_irqrestore(&mv64x60_lock, flags);
+
+ /* All LEDs off */
+ data8 = inb(PPC7D_CPLD_LEDS);
+ data8 &= ~0x08;
+ data8 |= 0x07;
+ outb(data8, PPC7D_CPLD_LEDS);
+
+ pr_debug("%s: exit\n", __FUNCTION__);
+}
+
+/* Called from machine_init(), early, before any of the __init functions
+ * have run. We must init software-configurable pins before other functions
+ * such as interrupt controllers are initialised.
+ */
+void __init platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7)
+{
+ u8 val8;
+ u8 rev_num;
+
+ /* Map 0xe0000000-0xffffffff early because we need access to SRAM
+ * and the ISA memory space (for serial port) here. This mapping
+ * is redone properly in ppc7d_map_io() later.
+ */
+ mtspr(SPRN_DBAT3U, 0xe0003fff);
+ mtspr(SPRN_DBAT3L, 0xe000002a);
+
+ /*
+ * Zero SRAM. Note that this generates parity errors on
+ * internal data path in SRAM if it's first time accessing it
+ * after reset.
+ *
+ * We do this ASAP to avoid parity errors when reading
+ * uninitialized SRAM.
+ */
+ memset((void *)PPC7D_INTERNAL_SRAM_BASE, 0, MV64360_SRAM_SIZE);
+
+ pr_debug("platform_init: r3-r7: %lx %lx %lx %lx %lx\n",
+ r3, r4, r5, r6, r7);
+
+ parse_bootinfo(find_bootinfo());
+
+ /* ASSUMPTION: If both r3 (bd_t pointer) and r6 (cmdline pointer)
+ * are non-zero, then we should use the board info from the bd_t
+ * structure and the cmdline pointed to by r6 instead of the
+ * information from birecs, if any. Otherwise, use the information
+ * from birecs as discovered by the preceeding call to
+ * parse_bootinfo(). This rule should work with both PPCBoot, which
+ * uses a bd_t board info structure, and the kernel boot wrapper,
+ * which uses birecs.
+ */
+ if (r3 && r6) {
+ bd_t *bp = (bd_t *) __res;
+
+ /* copy board info structure */
+ memcpy((void *)__res, (void *)(r3 + KERNELBASE), sizeof(bd_t));
+ /* copy command line */
+ *(char *)(r7 + KERNELBASE) = 0;
+ strcpy(cmd_line, (char *)(r6 + KERNELBASE));
+
+ printk(KERN_INFO "Board info data:-\n");
+ printk(KERN_INFO " Internal freq: %lu MHz, bus freq: %lu MHz\n",
+ bp->bi_intfreq, bp->bi_busfreq);
+ printk(KERN_INFO " Memory: %lx, size %lx\n", bp->bi_memstart,
+ bp->bi_memsize);
+ printk(KERN_INFO " Console baudrate: %lu\n", bp->bi_baudrate);
+ printk(KERN_INFO " Ethernet address: "
+ "%02x:%02x:%02x:%02x:%02x:%02x\n",
+ bp->bi_enetaddr[0], bp->bi_enetaddr[1],
+ bp->bi_enetaddr[2], bp->bi_enetaddr[3],
+ bp->bi_enetaddr[4], bp->bi_enetaddr[5]);
+ }
+#ifdef CONFIG_BLK_DEV_INITRD
+ /* take care of initrd if we have one */
+ if (r4) {
+ initrd_start = r4 + KERNELBASE;
+ initrd_end = r5 + KERNELBASE;
+ printk(KERN_INFO "INITRD @ %lx/%lx\n", initrd_start, initrd_end);
+ }
+#endif /* CONFIG_BLK_DEV_INITRD */
+
+ /* Map in board regs, etc. */
+ isa_io_base = 0xe8000000;
+ isa_mem_base = 0xe8000000;
+ pci_dram_offset = 0x00000000;
+ ISA_DMA_THRESHOLD = 0x00ffffff;
+ DMA_MODE_READ = 0x44;
+ DMA_MODE_WRITE = 0x48;
+
+ ppc_md.setup_arch = ppc7d_setup_arch;
+ ppc_md.init = ppc7d_init2;
+ ppc_md.show_cpuinfo = ppc7d_show_cpuinfo;
+ ppc_md.irq_canonicalize = ppc7d_irq_canonicalize;
+ ppc_md.init_IRQ = ppc7d_init_irq;
+ ppc_md.get_irq = ppc7d_get_irq;
+
+ ppc_md.restart = ppc7d_restart;
+ ppc_md.power_off = ppc7d_power_off;
+ ppc_md.halt = ppc7d_halt;
+
+ ppc_md.find_end_of_memory = ppc7d_find_end_of_memory;
+ ppc_md.setup_io_mappings = ppc7d_map_io;
+
+ ppc_md.time_init = NULL;
+ ppc_md.set_rtc_time = NULL;
+ ppc_md.get_rtc_time = NULL;
+ ppc_md.calibrate_decr = ppc7d_calibrate_decr;
+ ppc_md.nvram_read_val = NULL;
+ ppc_md.nvram_write_val = NULL;
+
+ ppc_md.heartbeat = ppc7d_heartbeat;
+ ppc_md.heartbeat_reset = HZ;
+ ppc_md.heartbeat_count = ppc_md.heartbeat_reset;
+
+ ppc_md.pcibios_fixup_bus = ppc7d_pci_fixup_bus;
+
+#if defined(CONFIG_SERIAL_MPSC) || defined(CONFIG_MV643XX_ETH) || \
+ defined(CONFIG_I2C_MV64XXX)
+ platform_notify = ppc7d_platform_notify;
+#endif
+
+#ifdef CONFIG_SERIAL_MPSC
+ /* On PPC7D, we must configure MPSC support via CPLD control
+ * registers.
+ */
+ outb(PPC7D_CPLD_RTS_COM4_SCLK |
+ PPC7D_CPLD_RTS_COM56_ENABLED, PPC7D_CPLD_RTS);
+ outb(PPC7D_CPLD_COMS_COM3_TCLKEN |
+ PPC7D_CPLD_COMS_COM3_TXEN |
+ PPC7D_CPLD_COMS_COM4_TCLKEN |
+ PPC7D_CPLD_COMS_COM4_TXEN, PPC7D_CPLD_COMS);
+#endif /* CONFIG_SERIAL_MPSC */
+
+#if defined(CONFIG_KGDB) || defined(CONFIG_SERIAL_TEXT_DEBUG)
+ ppc7d_early_serial_map();
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
+#if defined(CONFIG_SERIAL_MPSC_CONSOLE)
+ ppc_md.progress = mv64x60_mpsc_progress;
+#elif defined(CONFIG_SERIAL_8250)
+ ppc_md.progress = gen550_progress;
+#else
+#error CONFIG_KGDB || CONFIG_SERIAL_TEXT_DEBUG has no supported CONFIG_SERIAL_XXX
+#endif /* CONFIG_SERIAL_8250 */
+#endif /* CONFIG_SERIAL_TEXT_DEBUG */
+#endif /* CONFIG_KGDB || CONFIG_SERIAL_TEXT_DEBUG */
+
+ /* Enable write access to user flash. This is necessary for
+ * flash probe.
+ */
+ val8 = readb((void *)isa_io_base + PPC7D_CPLD_SW_FLASH_WRITE_PROTECT);
+ writeb(val8 | (PPC7D_CPLD_SW_FLASH_WRPROT_ENABLED &
+ PPC7D_CPLD_SW_FLASH_WRPROT_USER_MASK),
+ (void *)isa_io_base + PPC7D_CPLD_SW_FLASH_WRITE_PROTECT);
+
+ /* Determine if this board has IBM ALMA VME devices */
+ val8 = readb((void *)isa_io_base + PPC7D_CPLD_BOARD_REVISION);
+ rev_num = (val8 & PPC7D_CPLD_BOARD_REVISION_NUMBER_MASK) >> 5;
+ if (rev_num <= 1)
+ ppc7d_has_alma = 1;
+
+#ifdef DEBUG
+ console_printk[0] = 8;
+#endif
+}
diff --git a/arch/ppc/platforms/radstone_ppc7d.h b/arch/ppc/platforms/radstone_ppc7d.h
new file mode 100644
index 0000000000000..4546fff2b0c33
--- /dev/null
+++ b/arch/ppc/platforms/radstone_ppc7d.h
@@ -0,0 +1,434 @@
+/*
+ * arch/ppc/platforms/radstone_ppc7d.h
+ *
+ * Board definitions for the Radstone PPC7D boards.
+ *
+ * Author: James Chapman <jchapman@katalix.com>
+ *
+ * Based on code done by Rabeeh Khoury - rabeeh@galileo.co.il
+ * Based on code done by - Mark A. Greer <mgreer@mvista.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+/*
+ * The MV64360 has 2 PCI buses each with 1 window from the CPU bus to
+ * PCI I/O space and 4 windows from the CPU bus to PCI MEM space.
+ * We'll only use one PCI MEM window on each PCI bus.
+ *
+ * This is the CPU physical memory map (windows must be at least 1MB
+ * and start on a boundary that is a multiple of the window size):
+ *
+ * 0xff800000-0xffffffff - Boot window
+ * 0xff000000-0xff000fff - AFIX registers (DevCS2)
+ * 0xfef00000-0xfef0ffff - Internal MV64x60 registers
+ * 0xfef40000-0xfef7ffff - Internal SRAM
+ * 0xfef00000-0xfef0ffff - MV64360 Registers
+ * 0x70000000-0x7fffffff - soldered flash (DevCS3)
+ * 0xe8000000-0xe9ffffff - PCI I/O
+ * 0x80000000-0xbfffffff - PCI MEM
+ */
+
+#ifndef __PPC_PLATFORMS_PPC7D_H
+#define __PPC_PLATFORMS_PPC7D_H
+
+#include <asm/ppcboot.h>
+
+/*****************************************************************************
+ * CPU Physical Memory Map setup.
+ *****************************************************************************/
+
+#define PPC7D_BOOT_WINDOW_BASE 0xff800000
+#define PPC7D_AFIX_REG_BASE 0xff000000
+#define PPC7D_INTERNAL_SRAM_BASE 0xfef40000
+#define PPC7D_FLASH_BASE 0x70000000
+
+#define PPC7D_BOOT_WINDOW_SIZE_ACTUAL 0x00800000 /* 8MB */
+#define PPC7D_FLASH_SIZE_ACTUAL 0x10000000 /* 256MB */
+
+#define PPC7D_BOOT_WINDOW_SIZE max(MV64360_WINDOW_SIZE_MIN, \
+ PPC7D_BOOT_WINDOW_SIZE_ACTUAL)
+#define PPC7D_FLASH_SIZE max(MV64360_WINDOW_SIZE_MIN, \
+ PPC7D_FLASH_SIZE_ACTUAL)
+#define PPC7D_AFIX_REG_SIZE max(MV64360_WINDOW_SIZE_MIN, 0xff)
+
+
+#define PPC7D_PCI0_MEM0_START_PROC_ADDR 0x80000000UL
+#define PPC7D_PCI0_MEM0_START_PCI_HI_ADDR 0x00000000UL
+#define PPC7D_PCI0_MEM0_START_PCI_LO_ADDR 0x80000000UL
+#define PPC7D_PCI0_MEM0_SIZE 0x20000000UL
+#define PPC7D_PCI0_MEM1_START_PROC_ADDR 0xe8010000UL
+#define PPC7D_PCI0_MEM1_START_PCI_HI_ADDR 0x00000000UL
+#define PPC7D_PCI0_MEM1_START_PCI_LO_ADDR 0x00000000UL
+#define PPC7D_PCI0_MEM1_SIZE 0x000f0000UL
+#define PPC7D_PCI0_IO_START_PROC_ADDR 0xe8000000UL
+#define PPC7D_PCI0_IO_START_PCI_ADDR 0x00000000UL
+#define PPC7D_PCI0_IO_SIZE 0x00010000UL
+
+#define PPC7D_PCI1_MEM0_START_PROC_ADDR 0xa0000000UL
+#define PPC7D_PCI1_MEM0_START_PCI_HI_ADDR 0x00000000UL
+#define PPC7D_PCI1_MEM0_START_PCI_LO_ADDR 0xa0000000UL
+#define PPC7D_PCI1_MEM0_SIZE 0x20000000UL
+#define PPC7D_PCI1_MEM1_START_PROC_ADDR 0xe9800000UL
+#define PPC7D_PCI1_MEM1_START_PCI_HI_ADDR 0x00000000UL
+#define PPC7D_PCI1_MEM1_START_PCI_LO_ADDR 0x00000000UL
+#define PPC7D_PCI1_MEM1_SIZE 0x00800000UL
+#define PPC7D_PCI1_IO_START_PROC_ADDR 0xe9000000UL
+#define PPC7D_PCI1_IO_START_PCI_ADDR 0x00000000UL
+#define PPC7D_PCI1_IO_SIZE 0x00010000UL
+
+#define PPC7D_DEFAULT_BAUD 9600
+#define PPC7D_MPSC_CLK_SRC 8 /* TCLK */
+#define PPC7D_MPSC_CLK_FREQ 133333333 /* 133.3333... MHz */
+
+#define PPC7D_ETH0_PHY_ADDR 8
+#define PPC7D_ETH1_PHY_ADDR 9
+#define PPC7D_ETH2_PHY_ADDR 0
+
+#define PPC7D_ETH_TX_QUEUE_SIZE 400
+#define PPC7D_ETH_RX_QUEUE_SIZE 400
+
+#define PPC7D_ETH_PORT_CONFIG_VALUE \
+ MV64340_ETH_UNICAST_NORMAL_MODE | \
+ MV64340_ETH_DEFAULT_RX_QUEUE_0 | \
+ MV64340_ETH_DEFAULT_RX_ARP_QUEUE_0 | \
+ MV64340_ETH_RECEIVE_BC_IF_NOT_IP_OR_ARP | \
+ MV64340_ETH_RECEIVE_BC_IF_IP | \
+ MV64340_ETH_RECEIVE_BC_IF_ARP | \
+ MV64340_ETH_CAPTURE_TCP_FRAMES_DIS | \
+ MV64340_ETH_CAPTURE_UDP_FRAMES_DIS | \
+ MV64340_ETH_DEFAULT_RX_TCP_QUEUE_0 | \
+ MV64340_ETH_DEFAULT_RX_UDP_QUEUE_0 | \
+ MV64340_ETH_DEFAULT_RX_BPDU_QUEUE_0
+
+#define PPC7D_ETH_PORT_CONFIG_EXTEND_VALUE \
+ MV64340_ETH_SPAN_BPDU_PACKETS_AS_NORMAL | \
+ MV64340_ETH_PARTITION_DISABLE
+
+#define GT_ETH_IPG_INT_RX(value) \
+ ((value & 0x3fff) << 8)
+
+#define PPC7D_ETH_PORT_SDMA_CONFIG_VALUE \
+ MV64340_ETH_RX_BURST_SIZE_4_64BIT | \
+ GT_ETH_IPG_INT_RX(0) | \
+ MV64340_ETH_TX_BURST_SIZE_4_64BIT
+
+#define PPC7D_ETH_PORT_SERIAL_CONTROL_VALUE \
+ MV64340_ETH_ENABLE_AUTO_NEG_FOR_DUPLX | \
+ MV64340_ETH_DISABLE_AUTO_NEG_FOR_FLOW_CTRL | \
+ MV64340_ETH_ADV_SYMMETRIC_FLOW_CTRL | \
+ MV64340_ETH_FORCE_FC_MODE_NO_PAUSE_DIS_TX | \
+ MV64340_ETH_FORCE_BP_MODE_NO_JAM | \
+ (1 << 9) | \
+ MV64340_ETH_DO_NOT_FORCE_LINK_FAIL | \
+ MV64340_ETH_RETRANSMIT_16_ATTEMPTS | \
+ MV64340_ETH_ENABLE_AUTO_NEG_SPEED_GMII | \
+ MV64340_ETH_DTE_ADV_0 | \
+ MV64340_ETH_DISABLE_AUTO_NEG_BYPASS | \
+ MV64340_ETH_AUTO_NEG_NO_CHANGE | \
+ MV64340_ETH_MAX_RX_PACKET_9700BYTE | \
+ MV64340_ETH_CLR_EXT_LOOPBACK | \
+ MV64340_ETH_SET_FULL_DUPLEX_MODE | \
+ MV64340_ETH_ENABLE_FLOW_CTRL_TX_RX_IN_FULL_DUPLEX
+
+/*****************************************************************************
+ * Serial defines.
+ *****************************************************************************/
+
+#define PPC7D_SERIAL_0 0xe80003f8
+#define PPC7D_SERIAL_1 0xe80002f8
+
+#define RS_TABLE_SIZE 2
+
+/* Rate for the 1.8432 Mhz clock for the onboard serial chip */
+#define UART_CLK 1843200
+#define BASE_BAUD ( UART_CLK / 16 )
+
+#ifdef CONFIG_SERIAL_DETECT_IRQ
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_AUTO_IRQ)
+#else
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF)
+#endif
+
+#define STD_SERIAL_PORT_DFNS \
+ { 0, BASE_BAUD, PPC7D_SERIAL_0, 4, STD_COM_FLAGS, /* ttyS0 */ \
+ iomem_base: (u8 *)PPC7D_SERIAL_0, \
+ io_type: SERIAL_IO_MEM, }, \
+ { 0, BASE_BAUD, PPC7D_SERIAL_1, 3, STD_COM_FLAGS, /* ttyS1 */ \
+ iomem_base: (u8 *)PPC7D_SERIAL_1, \
+ io_type: SERIAL_IO_MEM },
+
+#define SERIAL_PORT_DFNS \
+ STD_SERIAL_PORT_DFNS
+
+/*****************************************************************************
+ * CPLD defines.
+ *
+ * Register map:-
+ *
+ * 0000 to 000F South Bridge DMA 1 Control
+ * 0020 and 0021 South Bridge Interrupt 1 Control
+ * 0040 to 0043 South Bridge Counter Control
+ * 0060 Keyboard
+ * 0061 South Bridge NMI Status and Control
+ * 0064 Keyboard
+ * 0071 and 0072 RTC R/W
+ * 0078 to 007B South Bridge BIOS Timer
+ * 0080 to 0090 South Bridge DMA Pages
+ * 00A0 and 00A1 South Bridge Interrupt 2 Control
+ * 00C0 to 00DE South Bridge DMA 2 Control
+ * 02E8 to 02EF COM6 R/W
+ * 02F8 to 02FF South Bridge COM2 R/W
+ * 03E8 to 03EF COM5 R/W
+ * 03F8 to 03FF South Bridge COM1 R/W
+ * 040A South Bridge DMA Scatter/Gather RO
+ * 040B DMA 1 Extended Mode WO
+ * 0410 to 043F South Bridge DMA Scatter/Gather
+ * 0481 to 048B South Bridge DMA High Pages
+ * 04D0 and 04D1 South Bridge Edge/Level Control
+ * 04D6 DMA 2 Extended Mode WO
+ * 0804 Memory Configuration RO
+ * 0806 Memory Configuration Extend RO
+ * 0808 SCSI Activity LED R/W
+ * 080C Equipment Present 1 RO
+ * 080E Equipment Present 2 RO
+ * 0810 Equipment Present 3 RO
+ * 0812 Equipment Present 4 RO
+ * 0818 Key Lock RO
+ * 0820 LEDS R/W
+ * 0824 COMs R/W
+ * 0826 RTS R/W
+ * 0828 Reset R/W
+ * 082C Watchdog Trig R/W
+ * 082E Interrupt R/W
+ * 0830 Interrupt Status RO
+ * 0832 PCI configuration RO
+ * 0854 Board Revision RO
+ * 0858 Extended ID RO
+ * 0864 ID Link RO
+ * 0866 Motherboard Type RO
+ * 0868 FLASH Write control RO
+ * 086A Software FLASH write protect R/W
+ * 086E FLASH Control R/W
+ *****************************************************************************/
+
+#define PPC7D_CPLD_MEM_CONFIG 0x0804
+#define PPC7D_CPLD_MEM_CONFIG_EXTEND 0x0806
+#define PPC7D_CPLD_SCSI_ACTIVITY_LED 0x0808
+#define PPC7D_CPLD_EQUIPMENT_PRESENT_1 0x080C
+#define PPC7D_CPLD_EQUIPMENT_PRESENT_2 0x080E
+#define PPC7D_CPLD_EQUIPMENT_PRESENT_3 0x0810
+#define PPC7D_CPLD_EQUIPMENT_PRESENT_4 0x0812
+#define PPC7D_CPLD_KEY_LOCK 0x0818
+#define PPC7D_CPLD_LEDS 0x0820
+#define PPC7D_CPLD_COMS 0x0824
+#define PPC7D_CPLD_RTS 0x0826
+#define PPC7D_CPLD_RESET 0x0828
+#define PPC7D_CPLD_WATCHDOG_TRIG 0x082C
+#define PPC7D_CPLD_INTR 0x082E
+#define PPC7D_CPLD_INTR_STATUS 0x0830
+#define PPC7D_CPLD_PCI_CONFIG 0x0832
+#define PPC7D_CPLD_BOARD_REVISION 0x0854
+#define PPC7D_CPLD_EXTENDED_ID 0x0858
+#define PPC7D_CPLD_ID_LINK 0x0864
+#define PPC7D_CPLD_MOTHERBOARD_TYPE 0x0866
+#define PPC7D_CPLD_FLASH_WRITE_CNTL 0x0868
+#define PPC7D_CPLD_SW_FLASH_WRITE_PROTECT 0x086A
+#define PPC7D_CPLD_FLASH_CNTL 0x086E
+
+/* MEMORY_CONFIG_EXTEND */
+#define PPC7D_CPLD_SDRAM_BANK_SIZE_MASK 0xc0
+#define PPC7D_CPLD_SDRAM_BANK_SIZE_128M 0
+#define PPC7D_CPLD_SDRAM_BANK_SIZE_256M 0x40
+#define PPC7D_CPLD_SDRAM_BANK_SIZE_512M 0x80
+#define PPC7D_CPLD_SDRAM_BANK_SIZE_1G 0xc0
+#define PPC7D_CPLD_FLASH_DEV_SIZE_MASK 0x03
+#define PPC7D_CPLD_FLASH_BANK_NUM_MASK 0x0c
+#define PPC7D_CPLD_FLASH_DEV_SIZE_64M 0
+#define PPC7D_CPLD_FLASH_DEV_SIZE_32M 1
+#define PPC7D_CPLD_FLASH_DEV_SIZE_16M 3
+#define PPC7D_CPLD_FLASH_BANK_NUM_4 0x00
+#define PPC7D_CPLD_FLASH_BANK_NUM_3 0x04
+#define PPC7D_CPLD_FLASH_BANK_NUM_2 0x08
+#define PPC7D_CPLD_FLASH_BANK_NUM_1 0x0c
+
+/* SCSI_LED */
+#define PPC7D_CPLD_SCSI_ACTIVITY_LED_OFF 0
+#define PPC7D_CPLD_SCSI_ACTIVITY_LED_ON 1
+
+/* EQUIPMENT_PRESENT_1 */
+#define PPC7D_CPLD_EQPT_PRES_1_FITTED 0
+#define PPC7D_CPLD_EQPT_PRES_1_PMC2_MASK (0x80 >> 2)
+#define PPC7D_CPLD_EQPT_PRES_1_PMC1_MASK (0x80 >> 3)
+#define PPC7D_CPLD_EQPT_PRES_1_AFIX_MASK (0x80 >> 4)
+
+/* EQUIPMENT_PRESENT_2 */
+#define PPC7D_CPLD_EQPT_PRES_2_FITTED !0
+#define PPC7D_CPLD_EQPT_PRES_2_UNIVERSE_MASK (0x80 >> 0)
+#define PPC7D_CPLD_EQPT_PRES_2_COM36_MASK (0x80 >> 2)
+#define PPC7D_CPLD_EQPT_PRES_2_GIGE_MASK (0x80 >> 3)
+#define PPC7D_CPLD_EQPT_PRES_2_DUALGIGE_MASK (0x80 >> 4)
+
+/* EQUIPMENT_PRESENT_3 */
+#define PPC7D_CPLD_EQPT_PRES_3_PMC2_V_MASK (0x80 >> 3)
+#define PPC7D_CPLD_EQPT_PRES_3_PMC2_5V (0 >> 3)
+#define PPC7D_CPLD_EQPT_PRES_3_PMC2_3V (0x80 >> 3)
+#define PPC7D_CPLD_EQPT_PRES_3_PMC1_V_MASK (0x80 >> 4)
+#define PPC7D_CPLD_EQPT_PRES_3_PMC1_5V (0 >> 4)
+#define PPC7D_CPLD_EQPT_PRES_3_PMC1_3V (0x80 >> 4)
+#define PPC7D_CPLD_EQPT_PRES_3_PMC_POWER_MASK (0x80 >> 5)
+#define PPC7D_CPLD_EQPT_PRES_3_PMC_POWER_INTER (0 >> 5)
+#define PPC7D_CPLD_EQPT_PRES_3_PMC_POWER_VME (0x80 >> 5)
+
+/* EQUIPMENT_PRESENT_4 */
+#define PPC7D_CPLD_EQPT_PRES_4_LPT_MASK (0x80 >> 2)
+#define PPC7D_CPLD_EQPT_PRES_4_LPT_FITTED (0x80 >> 2)
+#define PPC7D_CPLD_EQPT_PRES_4_PS2_USB2_MASK (0xc0 >> 6)
+#define PPC7D_CPLD_EQPT_PRES_4_PS2_FITTED (0x40 >> 6)
+#define PPC7D_CPLD_EQPT_PRES_4_USB2_FITTED (0x80 >> 6)
+
+/* CPLD_LEDS */
+#define PPC7D_CPLD_LEDS_ON (!0)
+#define PPC7D_CPLD_LEDS_OFF (0)
+#define PPC7D_CPLD_LEDS_NVRAM_PAGE_MASK (0xc0 >> 2)
+#define PPC7D_CPLD_LEDS_DS201_MASK (0x80 >> 4)
+#define PPC7D_CPLD_LEDS_DS219_MASK (0x80 >> 5)
+#define PPC7D_CPLD_LEDS_DS220_MASK (0x80 >> 6)
+#define PPC7D_CPLD_LEDS_DS221_MASK (0x80 >> 7)
+
+/* CPLD_COMS */
+#define PPC7D_CPLD_COMS_COM3_TCLKEN (0x80 >> 0)
+#define PPC7D_CPLD_COMS_COM3_RTCLKEN (0x80 >> 1)
+#define PPC7D_CPLD_COMS_COM3_MODE_MASK (0x80 >> 2)
+#define PPC7D_CPLD_COMS_COM3_MODE_RS232 (0)
+#define PPC7D_CPLD_COMS_COM3_MODE_RS422 (0x80 >> 2)
+#define PPC7D_CPLD_COMS_COM3_TXEN (0x80 >> 3)
+#define PPC7D_CPLD_COMS_COM4_TCLKEN (0x80 >> 4)
+#define PPC7D_CPLD_COMS_COM4_RTCLKEN (0x80 >> 5)
+#define PPC7D_CPLD_COMS_COM4_MODE_MASK (0x80 >> 6)
+#define PPC7D_CPLD_COMS_COM4_MODE_RS232 (0)
+#define PPC7D_CPLD_COMS_COM4_MODE_RS422 (0x80 >> 6)
+#define PPC7D_CPLD_COMS_COM4_TXEN (0x80 >> 7)
+
+/* CPLD_RTS */
+#define PPC7D_CPLD_RTS_COM36_LOOPBACK (0x80 >> 0)
+#define PPC7D_CPLD_RTS_COM4_SCLK (0x80 >> 1)
+#define PPC7D_CPLD_RTS_COM3_TXFUNC_MASK (0xc0 >> 2)
+#define PPC7D_CPLD_RTS_COM3_TXFUNC_DISABLED (0 >> 2)
+#define PPC7D_CPLD_RTS_COM3_TXFUNC_ENABLED (0x80 >> 2)
+#define PPC7D_CPLD_RTS_COM3_TXFUNC_ENABLED_RTG3 (0xc0 >> 2)
+#define PPC7D_CPLD_RTS_COM3_TXFUNC_ENABLED_RTG3S (0xc0 >> 2)
+#define PPC7D_CPLD_RTS_COM56_MODE_MASK (0x80 >> 4)
+#define PPC7D_CPLD_RTS_COM56_MODE_RS232 (0)
+#define PPC7D_CPLD_RTS_COM56_MODE_RS422 (0x80 >> 4)
+#define PPC7D_CPLD_RTS_COM56_ENABLE_MASK (0x80 >> 5)
+#define PPC7D_CPLD_RTS_COM56_DISABLED (0)
+#define PPC7D_CPLD_RTS_COM56_ENABLED (0x80 >> 5)
+#define PPC7D_CPLD_RTS_COM4_TXFUNC_MASK (0xc0 >> 6)
+#define PPC7D_CPLD_RTS_COM4_TXFUNC_DISABLED (0 >> 6)
+#define PPC7D_CPLD_RTS_COM4_TXFUNC_ENABLED (0x80 >> 6)
+#define PPC7D_CPLD_RTS_COM4_TXFUNC_ENABLED_RTG3 (0x40 >> 6)
+#define PPC7D_CPLD_RTS_COM4_TXFUNC_ENABLED_RTG3S (0x40 >> 6)
+
+/* WATCHDOG_TRIG */
+#define PPC7D_CPLD_WDOG_CAUSE_MASK (0x80 >> 0)
+#define PPC7D_CPLD_WDOG_CAUSE_NORMAL_RESET (0 >> 0)
+#define PPC7D_CPLD_WDOG_CAUSE_WATCHDOG (0x80 >> 0)
+#define PPC7D_CPLD_WDOG_ENABLE_MASK (0x80 >> 6)
+#define PPC7D_CPLD_WDOG_ENABLE_OFF (0 >> 6)
+#define PPC7D_CPLD_WDOG_ENABLE_ON (0x80 >> 6)
+#define PPC7D_CPLD_WDOG_RESETSW_MASK (0x80 >> 7)
+#define PPC7D_CPLD_WDOG_RESETSW_OFF (0 >> 7)
+#define PPC7D_CPLD_WDOG_RESETSW_ON (0x80 >> 7)
+
+/* Interrupt mask and status bits */
+#define PPC7D_CPLD_INTR_TEMP_MASK (0x80 >> 0)
+#define PPC7D_CPLD_INTR_HB8_MASK (0x80 >> 1)
+#define PPC7D_CPLD_INTR_PHY1_MASK (0x80 >> 2)
+#define PPC7D_CPLD_INTR_PHY0_MASK (0x80 >> 3)
+#define PPC7D_CPLD_INTR_ISANMI_MASK (0x80 >> 5)
+#define PPC7D_CPLD_INTR_CRITTEMP_MASK (0x80 >> 6)
+
+/* CPLD_INTR */
+#define PPC7D_CPLD_INTR_ENABLE_OFF (0)
+#define PPC7D_CPLD_INTR_ENABLE_ON (!0)
+
+/* CPLD_INTR_STATUS */
+#define PPC7D_CPLD_INTR_STATUS_OFF (0)
+#define PPC7D_CPLD_INTR_STATUS_ON (!0)
+
+/* CPLD_PCI_CONFIG */
+#define PPC7D_CPLD_PCI_CONFIG_PCI0_MASK 0x70
+#define PPC7D_CPLD_PCI_CONFIG_PCI0_PCI33 0x00
+#define PPC7D_CPLD_PCI_CONFIG_PCI0_PCI66 0x10
+#define PPC7D_CPLD_PCI_CONFIG_PCI0_PCIX33 0x40
+#define PPC7D_CPLD_PCI_CONFIG_PCI0_PCIX66 0x50
+#define PPC7D_CPLD_PCI_CONFIG_PCI0_PCIX100 0x60
+#define PPC7D_CPLD_PCI_CONFIG_PCI0_PCIX133 0x70
+#define PPC7D_CPLD_PCI_CONFIG_PCI1_MASK 0x07
+#define PPC7D_CPLD_PCI_CONFIG_PCI1_PCI33 0x00
+#define PPC7D_CPLD_PCI_CONFIG_PCI1_PCI66 0x01
+#define PPC7D_CPLD_PCI_CONFIG_PCI1_PCIX33 0x04
+#define PPC7D_CPLD_PCI_CONFIG_PCI1_PCIX66 0x05
+#define PPC7D_CPLD_PCI_CONFIG_PCI1_PCIX100 0x06
+#define PPC7D_CPLD_PCI_CONFIG_PCI1_PCIX133 0x07
+
+/* CPLD_BOARD_REVISION */
+#define PPC7D_CPLD_BOARD_REVISION_NUMBER_MASK 0xe0
+#define PPC7D_CPLD_BOARD_REVISION_LETTER_MASK 0x1f
+
+/* CPLD_EXTENDED_ID */
+#define PPC7D_CPLD_EXTENDED_ID_PPC7D 0x18
+
+/* CPLD_ID_LINK */
+#define PPC7D_CPLD_ID_LINK_VME64_GAP_MASK (0x80 >> 2)
+#define PPC7D_CPLD_ID_LINK_VME64_GA4_MASK (0x80 >> 3)
+#define PPC7D_CPLD_ID_LINK_E13_MASK (0x80 >> 4)
+#define PPC7D_CPLD_ID_LINK_E12_MASK (0x80 >> 5)
+#define PPC7D_CPLD_ID_LINK_E7_MASK (0x80 >> 6)
+#define PPC7D_CPLD_ID_LINK_E6_MASK (0x80 >> 7)
+
+/* CPLD_MOTHERBOARD_TYPE */
+#define PPC7D_CPLD_MB_TYPE_ECC_ENABLE_MASK (0x80 >> 0)
+#define PPC7D_CPLD_MB_TYPE_ECC_ENABLED (0x80 >> 0)
+#define PPC7D_CPLD_MB_TYPE_ECC_DISABLED (0 >> 0)
+#define PPC7D_CPLD_MB_TYPE_ECC_FITTED_MASK (0x80 >> 3)
+#define PPC7D_CPLD_MB_TYPE_PLL_MASK 0x0c
+#define PPC7D_CPLD_MB_TYPE_PLL_133 0x00
+#define PPC7D_CPLD_MB_TYPE_PLL_100 0x08
+#define PPC7D_CPLD_MB_TYPE_PLL_64 0x04
+#define PPC7D_CPLD_MB_TYPE_HW_ID_MASK 0x03
+
+/* CPLD_FLASH_WRITE_CNTL */
+#define PPD7D_CPLD_FLASH_CNTL_WR_LINK_MASK (0x80 >> 0)
+#define PPD7D_CPLD_FLASH_CNTL_WR_LINK_FITTED (0x80 >> 0)
+#define PPD7D_CPLD_FLASH_CNTL_BOOT_LINK_MASK (0x80 >> 2)
+#define PPD7D_CPLD_FLASH_CNTL_BOOT_LINK_FITTED (0x80 >> 2)
+#define PPD7D_CPLD_FLASH_CNTL_USER_LINK_MASK (0x80 >> 3)
+#define PPD7D_CPLD_FLASH_CNTL_USER_LINK_FITTED (0x80 >> 3)
+#define PPD7D_CPLD_FLASH_CNTL_RECO_WR_MASK (0x80 >> 5)
+#define PPD7D_CPLD_FLASH_CNTL_RECO_WR_ENABLED (0x80 >> 5)
+#define PPD7D_CPLD_FLASH_CNTL_BOOT_WR_MASK (0x80 >> 6)
+#define PPD7D_CPLD_FLASH_CNTL_BOOT_WR_ENABLED (0x80 >> 6)
+#define PPD7D_CPLD_FLASH_CNTL_USER_WR_MASK (0x80 >> 7)
+#define PPD7D_CPLD_FLASH_CNTL_USER_WR_ENABLED (0x80 >> 7)
+
+/* CPLD_SW_FLASH_WRITE_PROTECT */
+#define PPC7D_CPLD_SW_FLASH_WRPROT_ENABLED (!0)
+#define PPC7D_CPLD_SW_FLASH_WRPROT_DISABLED (0)
+#define PPC7D_CPLD_SW_FLASH_WRPROT_SYSBOOT_MASK (0x80 >> 6)
+#define PPC7D_CPLD_SW_FLASH_WRPROT_USER_MASK (0x80 >> 7)
+
+/* CPLD_FLASH_WRITE_CNTL */
+#define PPC7D_CPLD_FLASH_CNTL_NVRAM_PROT_MASK (0x80 >> 0)
+#define PPC7D_CPLD_FLASH_CNTL_NVRAM_DISABLED (0 >> 0)
+#define PPC7D_CPLD_FLASH_CNTL_NVRAM_ENABLED (0x80 >> 0)
+#define PPC7D_CPLD_FLASH_CNTL_ALTBOOT_LINK_MASK (0x80 >> 1)
+#define PPC7D_CPLD_FLASH_CNTL_VMEBOOT_LINK_MASK (0x80 >> 2)
+#define PPC7D_CPLD_FLASH_CNTL_RECBOOT_LINK_MASK (0x80 >> 3)
+
+
+#endif /* __PPC_PLATFORMS_PPC7D_H */
diff --git a/arch/ppc/platforms/sandpoint.c b/arch/ppc/platforms/sandpoint.c
index b07f416cc0d40..531bfa0e45121 100644
--- a/arch/ppc/platforms/sandpoint.c
+++ b/arch/ppc/platforms/sandpoint.c
@@ -202,13 +202,6 @@ sandpoint_setup_winbond_83553(struct pci_controller *hose)
0x48, /* ISA-to-PCI Addr Decoder Control */
0xf0);
- /* Enable RTC and Keyboard address locations. */
- early_write_config_byte(hose,
- 0,
- devfn,
- 0x4d, /* Chip Select Control Register */
- 0x00);
-
/* Enable Port 92. */
early_write_config_byte(hose,
0,
@@ -319,10 +312,10 @@ sandpoint_setup_arch(void)
* We will do this now with good known values. Future versions
* of DINK32 are supposed to get this correct.
*/
- if (cur_cpu_spec[0]->cpu_features & CPU_FTR_SPEC7450)
+ if (cpu_has_feature(CPU_FTR_SPEC7450))
/* 745x is different. We only want to pass along enable. */
_set_L2CR(L2CR_L2E);
- else if (cur_cpu_spec[0]->cpu_features & CPU_FTR_L2CR)
+ else if (cpu_has_feature(CPU_FTR_L2CR))
/* All modules have 1MB of L2. We also assume that an
* L2 divisor of 3 will work.
*/
@@ -330,7 +323,7 @@ sandpoint_setup_arch(void)
| L2CR_L2RAM_PIPE | L2CR_L2OH_1_0 | L2CR_L2DF);
#if 0
/* Untested right now. */
- if (cur_cpu_spec[0]->cpu_features & CPU_FTR_L3CR) {
+ if (cpu_has_feature(CPU_FTR_L3CR)) {
/* Magic value. */
_set_L3CR(0x8f032000);
}
diff --git a/arch/ppc/platforms/spruce.c b/arch/ppc/platforms/spruce.c
index 74be324564fa4..5ad70d357cb98 100644
--- a/arch/ppc/platforms/spruce.c
+++ b/arch/ppc/platforms/spruce.c
@@ -278,8 +278,8 @@ static __inline__ void
spruce_set_bat(void)
{
mb();
- mtspr(DBAT1U, 0xf8000ffe);
- mtspr(DBAT1L, 0xf800002a);
+ mtspr(SPRN_DBAT1U, 0xf8000ffe);
+ mtspr(SPRN_DBAT1L, 0xf800002a);
mb();
}
diff --git a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile
index ff344fb019109..dd418ea3426c7 100644
--- a/arch/ppc/syslib/Makefile
+++ b/arch/ppc/syslib/Makefile
@@ -53,6 +53,7 @@ obj-$(CONFIG_GT64260) += gt64260_pic.o
obj-$(CONFIG_K2) += i8259.o indirect_pci.o todc_time.o \
pci_auto.o
obj-$(CONFIG_LOPEC) += i8259.o pci_auto.o todc_time.o
+obj-$(CONFIG_HDPU) += pci_auto.o
obj-$(CONFIG_LUAN) += indirect_pci.o pci_auto.o todc_time.o
obj-$(CONFIG_KATANA) += pci_auto.o
obj-$(CONFIG_MCPN765) += todc_time.o indirect_pci.o pci_auto.o \
@@ -74,6 +75,7 @@ obj-$(CONFIG_PRPMC750) += open_pic.o indirect_pci.o pci_auto.o \
hawk_common.o
obj-$(CONFIG_HARRIER) += harrier.o
obj-$(CONFIG_PRPMC800) += open_pic.o indirect_pci.o pci_auto.o
+obj-$(CONFIG_RADSTONE_PPC7D) += i8259.o pci_auto.o
obj-$(CONFIG_SANDPOINT) += i8259.o pci_auto.o todc_time.o
obj-$(CONFIG_SBC82xx) += todc_time.o
obj-$(CONFIG_SPRUCE) += cpc700_pic.o indirect_pci.o pci_auto.o \
@@ -95,8 +97,19 @@ obj-$(CONFIG_MPC10X_OPENPIC) += open_pic.o
obj-$(CONFIG_40x) += dcr.o
obj-$(CONFIG_BOOKE) += dcr.o
obj-$(CONFIG_85xx) += open_pic.o ppc85xx_common.o ppc85xx_setup.o \
- ppc_sys.o
+ ppc_sys.o mpc85xx_sys.o \
+ mpc85xx_devices.o
ifeq ($(CONFIG_85xx),y)
obj-$(CONFIG_PCI) += indirect_pci.o pci_auto.o
endif
-obj-$(CONFIG_PPC_MPC52xx) += mpc52xx_setup.o mpc52xx_pic.o
+obj-$(CONFIG_83xx) += ipic.o ppc83xx_setup.o ppc_sys.o \
+ mpc83xx_sys.o mpc83xx_devices.o
+ifeq ($(CONFIG_83xx),y)
+obj-$(CONFIG_PCI) += indirect_pci.o pci_auto.o
+endif
+obj-$(CONFIG_MPC8555_CDS) += todc_time.o
+obj-$(CONFIG_PPC_MPC52xx) += mpc52xx_setup.o mpc52xx_pic.o \
+ mpc52xx_sys.o mpc52xx_devices.o ppc_sys.o
+ifeq ($(CONFIG_PPC_MPC52xx),y)
+obj-$(CONFIG_PCI) += mpc52xx_pci.o
+endif
diff --git a/arch/ppc/syslib/btext.c b/arch/ppc/syslib/btext.c
index e3f9e8e3b6bb4..7734f68361746 100644
--- a/arch/ppc/syslib/btext.c
+++ b/arch/ppc/syslib/btext.c
@@ -137,7 +137,7 @@ btext_prepare_BAT(void)
boot_text_mapped = 0;
return;
}
- if (PVR_VER(mfspr(PVR)) != 1) {
+ if (PVR_VER(mfspr(SPRN_PVR)) != 1) {
/* 603, 604, G3, G4, ... */
lowbits = addr & ~0xFF000000UL;
addr &= 0xFF000000UL;
diff --git a/arch/ppc/syslib/cpc700.h b/arch/ppc/syslib/cpc700.h
index 2a717898b9d7a..f2c002531019e 100644
--- a/arch/ppc/syslib/cpc700.h
+++ b/arch/ppc/syslib/cpc700.h
@@ -17,13 +17,14 @@
* memory controller, PIC, UARTs, IIC, and Timers.
*/
-#ifndef _ASMPPC_CPC700_H
-#define _ASMPPC_CPC700_H
+#ifndef __PPC_SYSLIB_CPC700_H__
+#define __PPC_SYSLIB_CPC700_H__
#include <linux/stddef.h>
#include <linux/types.h>
#include <linux/init.h>
+/* XXX no barriers? not even any volatiles? -- paulus */
#define CPC700_OUT_32(a,d) (*(u_int *)a = d)
#define CPC700_IN_32(a) (*(u_int *)a)
@@ -33,21 +34,26 @@
#define CPC700_PCI_CONFIG_ADDR 0xfec00000
#define CPC700_PCI_CONFIG_DATA 0xfec00004
-#define CPC700_PMM0_LOCAL 0xff400000
-#define CPC700_PMM0_MASK_ATTR 0xff400004
-#define CPC700_PMM0_PCI_LOW 0xff400008
-#define CPC700_PMM0_PCI_HIGH 0xff40000c
+/* CPU -> PCI memory window 0 */
+#define CPC700_PMM0_LOCAL 0xff400000 /* CPU physical addr */
+#define CPC700_PMM0_MASK_ATTR 0xff400004 /* size and attrs */
+#define CPC700_PMM0_PCI_LOW 0xff400008 /* PCI addr, low word */
+#define CPC700_PMM0_PCI_HIGH 0xff40000c /* PCI addr, high wd */
+/* CPU -> PCI memory window 1 */
#define CPC700_PMM1_LOCAL 0xff400010
#define CPC700_PMM1_MASK_ATTR 0xff400014
#define CPC700_PMM1_PCI_LOW 0xff400018
#define CPC700_PMM1_PCI_HIGH 0xff40001c
+/* CPU -> PCI memory window 2 */
#define CPC700_PMM2_LOCAL 0xff400020
#define CPC700_PMM2_MASK_ATTR 0xff400024
#define CPC700_PMM2_PCI_LOW 0xff400028
#define CPC700_PMM2_PCI_HIGH 0xff40002c
-#define CPC700_PTM1_MEMSIZE 0xff400030
-#define CPC700_PTM1_LOCAL 0xff400034
-#define CPC700_PTM2_MEMSIZE 0xff400038
+/* PCI memory -> CPU window 1 */
+#define CPC700_PTM1_MEMSIZE 0xff400030 /* window size */
+#define CPC700_PTM1_LOCAL 0xff400034 /* CPU phys addr */
+/* PCI memory -> CPU window 2 */
+#define CPC700_PTM2_MEMSIZE 0xff400038 /* size and enable */
#define CPC700_PTM2_LOCAL 0xff40003c
/*
@@ -89,4 +95,4 @@ extern unsigned int cpc700_irq_assigns[32][2];
extern void __init cpc700_init_IRQ(void);
extern int cpc700_get_irq(struct pt_regs *);
-#endif /* _ASMPPC_CPC700_H */
+#endif /* __PPC_SYSLIB_CPC700_H__ */
diff --git a/arch/ppc/syslib/cpm2_pic.c b/arch/ppc/syslib/cpm2_pic.c
index bd8335b84d93a..954b07fc1df39 100644
--- a/arch/ppc/syslib/cpm2_pic.c
+++ b/arch/ppc/syslib/cpm2_pic.c
@@ -32,15 +32,17 @@ static u_char irq_to_siureg[] = {
0, 0, 0, 0, 0, 0, 0, 0
};
+/* bit numbers do not match the docs, these are precomputed so the bit for
+ * a given irq is (1 << irq_to_siubit[irq]) */
static u_char irq_to_siubit[] = {
- 31, 16, 17, 18, 19, 20, 21, 22,
- 23, 24, 25, 26, 27, 28, 29, 30,
- 29, 30, 16, 17, 18, 19, 20, 21,
- 22, 23, 24, 25, 26, 27, 28, 31,
- 0, 1, 2, 3, 4, 5, 6, 7,
- 8, 9, 10, 11, 12, 13, 14, 15,
- 15, 14, 13, 12, 11, 10, 9, 8,
- 7, 6, 5, 4, 3, 2, 1, 0
+ 0, 15, 14, 13, 12, 11, 10, 9,
+ 8, 7, 6, 5, 4, 3, 2, 1,
+ 2, 1, 15, 14, 13, 12, 11, 10,
+ 9, 8, 7, 6, 5, 4, 3, 0,
+ 31, 30, 29, 28, 27, 26, 25, 24,
+ 23, 22, 21, 20, 19, 18, 17, 16,
+ 16, 17, 18, 19, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31,
};
static void cpm2_mask_irq(unsigned int irq_nr)
@@ -48,11 +50,13 @@ static void cpm2_mask_irq(unsigned int irq_nr)
int bit, word;
volatile uint *simr;
+ irq_nr -= CPM_IRQ_OFFSET;
+
bit = irq_to_siubit[irq_nr];
word = irq_to_siureg[irq_nr];
simr = &(cpm2_immr->im_intctl.ic_simrh);
- ppc_cached_irq_mask[word] &= ~(1 << (31 - bit));
+ ppc_cached_irq_mask[word] &= ~(1 << bit);
simr[word] = ppc_cached_irq_mask[word];
}
@@ -61,11 +65,13 @@ static void cpm2_unmask_irq(unsigned int irq_nr)
int bit, word;
volatile uint *simr;
+ irq_nr -= CPM_IRQ_OFFSET;
+
bit = irq_to_siubit[irq_nr];
word = irq_to_siureg[irq_nr];
simr = &(cpm2_immr->im_intctl.ic_simrh);
- ppc_cached_irq_mask[word] |= (1 << (31 - bit));
+ ppc_cached_irq_mask[word] |= 1 << bit;
simr[word] = ppc_cached_irq_mask[word];
}
@@ -74,14 +80,16 @@ static void cpm2_mask_and_ack(unsigned int irq_nr)
int bit, word;
volatile uint *simr, *sipnr;
+ irq_nr -= CPM_IRQ_OFFSET;
+
bit = irq_to_siubit[irq_nr];
word = irq_to_siureg[irq_nr];
simr = &(cpm2_immr->im_intctl.ic_simrh);
sipnr = &(cpm2_immr->im_intctl.ic_sipnrh);
- ppc_cached_irq_mask[word] &= ~(1 << (31 - bit));
+ ppc_cached_irq_mask[word] &= ~(1 << bit);
simr[word] = ppc_cached_irq_mask[word];
- sipnr[word] = 1 << (31 - bit);
+ sipnr[word] = 1 << bit;
}
static void cpm2_end_irq(unsigned int irq_nr)
@@ -92,29 +100,25 @@ static void cpm2_end_irq(unsigned int irq_nr)
if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS))
&& irq_desc[irq_nr].action) {
+ irq_nr -= CPM_IRQ_OFFSET;
bit = irq_to_siubit[irq_nr];
word = irq_to_siureg[irq_nr];
simr = &(cpm2_immr->im_intctl.ic_simrh);
- ppc_cached_irq_mask[word] |= (1 << (31 - bit));
+ ppc_cached_irq_mask[word] |= 1 << bit;
simr[word] = ppc_cached_irq_mask[word];
}
}
-struct hw_interrupt_type cpm2_pic = {
- " CPM2 SIU ",
- NULL,
- NULL,
- cpm2_unmask_irq,
- cpm2_mask_irq,
- cpm2_mask_and_ack,
- cpm2_end_irq,
- 0
+static struct hw_interrupt_type cpm2_pic = {
+ .typename = " CPM2 SIU ",
+ .enable = cpm2_unmask_irq,
+ .disable = cpm2_mask_irq,
+ .ack = cpm2_mask_and_ack,
+ .end = cpm2_end_irq,
};
-
-int
-cpm2_get_irq(struct pt_regs *regs)
+int cpm2_get_irq(struct pt_regs *regs)
{
int irq;
unsigned long bits;
@@ -126,5 +130,43 @@ cpm2_get_irq(struct pt_regs *regs)
if (irq == 0)
return(-1);
- return irq;
+ return irq+CPM_IRQ_OFFSET;
+}
+
+void cpm2_init_IRQ(void)
+{
+ int i;
+
+ /* Clear the CPM IRQ controller, in case it has any bits set
+ * from the bootloader
+ */
+
+ /* Mask out everything */
+ cpm2_immr->im_intctl.ic_simrh = 0x00000000;
+ cpm2_immr->im_intctl.ic_simrl = 0x00000000;
+ wmb();
+
+ /* Ack everything */
+ cpm2_immr->im_intctl.ic_sipnrh = 0xffffffff;
+ cpm2_immr->im_intctl.ic_sipnrl = 0xffffffff;
+ wmb();
+
+ /* Dummy read of the vector */
+ i = cpm2_immr->im_intctl.ic_sivec;
+ rmb();
+
+ /* Initialize the default interrupt mapping priorities,
+ * in case the boot rom changed something on us.
+ */
+ cpm2_immr->im_intctl.ic_sicr = 0;
+ cpm2_immr->im_intctl.ic_scprrh = 0x05309770;
+ cpm2_immr->im_intctl.ic_scprrl = 0x05309770;
+
+
+ /* Enable chaining to OpenPIC, and make everything level
+ */
+ for (i = 0; i < NR_CPM_INTS; i++) {
+ irq_desc[i+CPM_IRQ_OFFSET].handler = &cpm2_pic;
+ irq_desc[i+CPM_IRQ_OFFSET].status |= IRQ_LEVEL;
+ }
}
diff --git a/arch/ppc/syslib/cpm2_pic.h b/arch/ppc/syslib/cpm2_pic.h
index d05003b091f53..97cab8f13a1a0 100644
--- a/arch/ppc/syslib/cpm2_pic.h
+++ b/arch/ppc/syslib/cpm2_pic.h
@@ -1,7 +1,8 @@
#ifndef _PPC_KERNEL_CPM2_H
#define _PPC_KERNEL_CPM2_H
-extern struct hw_interrupt_type cpm2_pic;
extern int cpm2_get_irq(struct pt_regs *regs);
+extern void cpm2_init_IRQ(void);
+
#endif /* _PPC_KERNEL_CPM2_H */
diff --git a/arch/ppc/syslib/ibm440gx_common.c b/arch/ppc/syslib/ibm440gx_common.c
index 5e2ce6bf59764..4ad85e0e02342 100644
--- a/arch/ppc/syslib/ibm440gx_common.c
+++ b/arch/ppc/syslib/ibm440gx_common.c
@@ -221,7 +221,7 @@ void __init ibm440gx_l2c_setup(struct ibm44x_clocks* p)
/* Disable L2C on rev.A, rev.B and 800MHz version of rev.C,
enable it on all other revisions
*/
- u32 pvr = mfspr(PVR);
+ u32 pvr = mfspr(SPRN_PVR);
if (pvr == PVR_440GX_RA || pvr == PVR_440GX_RB ||
(pvr == PVR_440GX_RC && p->cpu > 667000000))
ibm440gx_l2c_disable();
diff --git a/arch/ppc/syslib/ipic.c b/arch/ppc/syslib/ipic.c
new file mode 100644
index 0000000000000..acb2cde3171f8
--- /dev/null
+++ b/arch/ppc/syslib/ipic.c
@@ -0,0 +1,646 @@
+/*
+ * include/asm-ppc/ipic.c
+ *
+ * IPIC routines implementations.
+ *
+ * Copyright 2005 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/slab.h>
+#include <linux/stddef.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/sysdev.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/ipic.h>
+#include <asm/mpc83xx.h>
+
+#include "ipic.h"
+
+static struct ipic p_ipic;
+static struct ipic * primary_ipic;
+
+static struct ipic_info ipic_info[] = {
+ [9] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_H,
+ .prio = IPIC_SIPRR_D,
+ .force = IPIC_SIFCR_H,
+ .bit = 24,
+ .prio_mask = 0,
+ },
+ [10] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_H,
+ .prio = IPIC_SIPRR_D,
+ .force = IPIC_SIFCR_H,
+ .bit = 25,
+ .prio_mask = 1,
+ },
+ [11] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_H,
+ .prio = IPIC_SIPRR_D,
+ .force = IPIC_SIFCR_H,
+ .bit = 26,
+ .prio_mask = 2,
+ },
+ [14] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_H,
+ .prio = IPIC_SIPRR_D,
+ .force = IPIC_SIFCR_H,
+ .bit = 29,
+ .prio_mask = 5,
+ },
+ [15] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_H,
+ .prio = IPIC_SIPRR_D,
+ .force = IPIC_SIFCR_H,
+ .bit = 30,
+ .prio_mask = 6,
+ },
+ [16] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_H,
+ .prio = IPIC_SIPRR_D,
+ .force = IPIC_SIFCR_H,
+ .bit = 31,
+ .prio_mask = 7,
+ },
+ [17] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SEMSR,
+ .prio = IPIC_SMPRR_A,
+ .force = IPIC_SEFCR,
+ .bit = 1,
+ .prio_mask = 5,
+ },
+ [18] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SEMSR,
+ .prio = IPIC_SMPRR_A,
+ .force = IPIC_SEFCR,
+ .bit = 2,
+ .prio_mask = 6,
+ },
+ [19] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SEMSR,
+ .prio = IPIC_SMPRR_A,
+ .force = IPIC_SEFCR,
+ .bit = 3,
+ .prio_mask = 7,
+ },
+ [20] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SEMSR,
+ .prio = IPIC_SMPRR_B,
+ .force = IPIC_SEFCR,
+ .bit = 4,
+ .prio_mask = 4,
+ },
+ [21] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SEMSR,
+ .prio = IPIC_SMPRR_B,
+ .force = IPIC_SEFCR,
+ .bit = 5,
+ .prio_mask = 5,
+ },
+ [22] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SEMSR,
+ .prio = IPIC_SMPRR_B,
+ .force = IPIC_SEFCR,
+ .bit = 6,
+ .prio_mask = 6,
+ },
+ [23] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SEMSR,
+ .prio = IPIC_SMPRR_B,
+ .force = IPIC_SEFCR,
+ .bit = 7,
+ .prio_mask = 7,
+ },
+ [32] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_H,
+ .prio = IPIC_SIPRR_A,
+ .force = IPIC_SIFCR_H,
+ .bit = 0,
+ .prio_mask = 0,
+ },
+ [33] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_H,
+ .prio = IPIC_SIPRR_A,
+ .force = IPIC_SIFCR_H,
+ .bit = 1,
+ .prio_mask = 1,
+ },
+ [34] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_H,
+ .prio = IPIC_SIPRR_A,
+ .force = IPIC_SIFCR_H,
+ .bit = 2,
+ .prio_mask = 2,
+ },
+ [35] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_H,
+ .prio = IPIC_SIPRR_A,
+ .force = IPIC_SIFCR_H,
+ .bit = 3,
+ .prio_mask = 3,
+ },
+ [36] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_H,
+ .prio = IPIC_SIPRR_A,
+ .force = IPIC_SIFCR_H,
+ .bit = 4,
+ .prio_mask = 4,
+ },
+ [37] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_H,
+ .prio = IPIC_SIPRR_A,
+ .force = IPIC_SIFCR_H,
+ .bit = 5,
+ .prio_mask = 5,
+ },
+ [38] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_H,
+ .prio = IPIC_SIPRR_A,
+ .force = IPIC_SIFCR_H,
+ .bit = 6,
+ .prio_mask = 6,
+ },
+ [39] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_H,
+ .prio = IPIC_SIPRR_A,
+ .force = IPIC_SIFCR_H,
+ .bit = 7,
+ .prio_mask = 7,
+ },
+ [48] = {
+ .pend = IPIC_SEPNR,
+ .mask = IPIC_SEMSR,
+ .prio = IPIC_SMPRR_A,
+ .force = IPIC_SEFCR,
+ .bit = 0,
+ .prio_mask = 4,
+ },
+ [64] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = IPIC_SMPRR_A,
+ .force = IPIC_SIFCR_L,
+ .bit = 0,
+ .prio_mask = 0,
+ },
+ [65] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = IPIC_SMPRR_A,
+ .force = IPIC_SIFCR_L,
+ .bit = 1,
+ .prio_mask = 1,
+ },
+ [66] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = IPIC_SMPRR_A,
+ .force = IPIC_SIFCR_L,
+ .bit = 2,
+ .prio_mask = 2,
+ },
+ [67] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = IPIC_SMPRR_A,
+ .force = IPIC_SIFCR_L,
+ .bit = 3,
+ .prio_mask = 3,
+ },
+ [68] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = IPIC_SMPRR_B,
+ .force = IPIC_SIFCR_L,
+ .bit = 4,
+ .prio_mask = 0,
+ },
+ [69] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = IPIC_SMPRR_B,
+ .force = IPIC_SIFCR_L,
+ .bit = 5,
+ .prio_mask = 1,
+ },
+ [70] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = IPIC_SMPRR_B,
+ .force = IPIC_SIFCR_L,
+ .bit = 6,
+ .prio_mask = 2,
+ },
+ [71] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = IPIC_SMPRR_B,
+ .force = IPIC_SIFCR_L,
+ .bit = 7,
+ .prio_mask = 3,
+ },
+ [72] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = 0,
+ .force = IPIC_SIFCR_L,
+ .bit = 8,
+ },
+ [73] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = 0,
+ .force = IPIC_SIFCR_L,
+ .bit = 9,
+ },
+ [74] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = 0,
+ .force = IPIC_SIFCR_L,
+ .bit = 10,
+ },
+ [75] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = 0,
+ .force = IPIC_SIFCR_L,
+ .bit = 11,
+ },
+ [76] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = 0,
+ .force = IPIC_SIFCR_L,
+ .bit = 12,
+ },
+ [77] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = 0,
+ .force = IPIC_SIFCR_L,
+ .bit = 13,
+ },
+ [78] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = 0,
+ .force = IPIC_SIFCR_L,
+ .bit = 14,
+ },
+ [79] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = 0,
+ .force = IPIC_SIFCR_L,
+ .bit = 15,
+ },
+ [80] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = 0,
+ .force = IPIC_SIFCR_L,
+ .bit = 16,
+ },
+ [84] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = 0,
+ .force = IPIC_SIFCR_L,
+ .bit = 20,
+ },
+ [85] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = 0,
+ .force = IPIC_SIFCR_L,
+ .bit = 21,
+ },
+ [90] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = 0,
+ .force = IPIC_SIFCR_L,
+ .bit = 26,
+ },
+ [91] = {
+ .pend = IPIC_SIPNR_H,
+ .mask = IPIC_SIMSR_L,
+ .prio = 0,
+ .force = IPIC_SIFCR_L,
+ .bit = 27,
+ },
+};
+
+static inline u32 ipic_read(volatile u32 __iomem *base, unsigned int reg)
+{
+ return in_be32(base + (reg >> 2));
+}
+
+static inline void ipic_write(volatile u32 __iomem *base, unsigned int reg, u32 value)
+{
+ out_be32(base + (reg >> 2), value);
+}
+
+static inline struct ipic * ipic_from_irq(unsigned int irq)
+{
+ return primary_ipic;
+}
+
+static void ipic_enable_irq(unsigned int irq)
+{
+ struct ipic *ipic = ipic_from_irq(irq);
+ unsigned int src = irq - ipic->irq_offset;
+ u32 temp;
+
+ temp = ipic_read(ipic->regs, ipic_info[src].mask);
+ temp |= (1 << (31 - ipic_info[src].bit));
+ ipic_write(ipic->regs, ipic_info[src].mask, temp);
+}
+
+static void ipic_disable_irq(unsigned int irq)
+{
+ struct ipic *ipic = ipic_from_irq(irq);
+ unsigned int src = irq - ipic->irq_offset;
+ u32 temp;
+
+ temp = ipic_read(ipic->regs, ipic_info[src].mask);
+ temp &= ~(1 << (31 - ipic_info[src].bit));
+ ipic_write(ipic->regs, ipic_info[src].mask, temp);
+}
+
+static void ipic_disable_irq_and_ack(unsigned int irq)
+{
+ struct ipic *ipic = ipic_from_irq(irq);
+ unsigned int src = irq - ipic->irq_offset;
+ u32 temp;
+
+ ipic_disable_irq(irq);
+
+ temp = ipic_read(ipic->regs, ipic_info[src].pend);
+ temp |= (1 << (31 - ipic_info[src].bit));
+ ipic_write(ipic->regs, ipic_info[src].pend, temp);
+}
+
+static void ipic_end_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+ ipic_enable_irq(irq);
+}
+
+struct hw_interrupt_type ipic = {
+ .typename = " IPIC ",
+ .enable = ipic_enable_irq,
+ .disable = ipic_disable_irq,
+ .ack = ipic_disable_irq_and_ack,
+ .end = ipic_end_irq,
+};
+
+void __init ipic_init(phys_addr_t phys_addr,
+ unsigned int flags,
+ unsigned int irq_offset,
+ unsigned char *senses,
+ unsigned int senses_count)
+{
+ u32 i, temp = 0;
+
+ primary_ipic = &p_ipic;
+ primary_ipic->regs = ioremap(phys_addr, MPC83xx_IPIC_SIZE);
+
+ primary_ipic->irq_offset = irq_offset;
+
+ ipic_write(primary_ipic->regs, IPIC_SICNR, 0x0);
+
+ /* default priority scheme is grouped. If spread mode is required
+ * configure SICFR accordingly */
+ if (flags & IPIC_SPREADMODE_GRP_A)
+ temp |= SICFR_IPSA;
+ if (flags & IPIC_SPREADMODE_GRP_D)
+ temp |= SICFR_IPSD;
+ if (flags & IPIC_SPREADMODE_MIX_A)
+ temp |= SICFR_MPSA;
+ if (flags & IPIC_SPREADMODE_MIX_B)
+ temp |= SICFR_MPSB;
+
+ ipic_write(primary_ipic->regs, IPIC_SICNR, temp);
+
+ /* handle MCP route */
+ temp = 0;
+ if (flags & IPIC_DISABLE_MCP_OUT)
+ temp = SERCR_MCPR;
+ ipic_write(primary_ipic->regs, IPIC_SERCR, temp);
+
+ /* handle routing of IRQ0 to MCP */
+ temp = ipic_read(primary_ipic->regs, IPIC_SEMSR);
+
+ if (flags & IPIC_IRQ0_MCP)
+ temp |= SEMSR_SIRQ0;
+ else
+ temp &= ~SEMSR_SIRQ0;
+
+ ipic_write(primary_ipic->regs, IPIC_SEMSR, temp);
+
+ for (i = 0 ; i < NR_IPIC_INTS ; i++) {
+ irq_desc[i+irq_offset].handler = &ipic;
+ irq_desc[i+irq_offset].status = IRQ_LEVEL;
+ }
+
+ temp = 0;
+ for (i = 0 ; i < senses_count ; i++) {
+ if ((senses[i] & IRQ_SENSE_MASK) == IRQ_SENSE_EDGE) {
+ temp |= 1 << (16 - i);
+ if (i != 0)
+ irq_desc[i + irq_offset + MPC83xx_IRQ_EXT1 - 1].status = 0;
+ else
+ irq_desc[irq_offset + MPC83xx_IRQ_EXT0].status = 0;
+ }
+ }
+ ipic_write(primary_ipic->regs, IPIC_SECNR, temp);
+
+ printk ("IPIC (%d IRQ sources, %d External IRQs) at %p\n", NR_IPIC_INTS,
+ senses_count, primary_ipic->regs);
+}
+
+int ipic_set_priority(unsigned int irq, unsigned int priority)
+{
+ struct ipic *ipic = ipic_from_irq(irq);
+ unsigned int src = irq - ipic->irq_offset;
+ u32 temp;
+
+ if (priority > 7)
+ return -EINVAL;
+ if (src > 127)
+ return -EINVAL;
+ if (ipic_info[src].prio == 0)
+ return -EINVAL;
+
+ temp = ipic_read(ipic->regs, ipic_info[src].prio);
+
+ if (priority < 4) {
+ temp &= ~(0x7 << (20 + (3 - priority) * 3));
+ temp |= ipic_info[src].prio_mask << (20 + (3 - priority) * 3);
+ } else {
+ temp &= ~(0x7 << (4 + (7 - priority) * 3));
+ temp |= ipic_info[src].prio_mask << (4 + (7 - priority) * 3);
+ }
+
+ ipic_write(ipic->regs, ipic_info[src].prio, temp);
+
+ return 0;
+}
+
+void ipic_set_highest_priority(unsigned int irq)
+{
+ struct ipic *ipic = ipic_from_irq(irq);
+ unsigned int src = irq - ipic->irq_offset;
+ u32 temp;
+
+ temp = ipic_read(ipic->regs, IPIC_SICFR);
+
+ /* clear and set HPI */
+ temp &= 0x7f000000;
+ temp |= (src & 0x7f) << 24;
+
+ ipic_write(ipic->regs, IPIC_SICFR, temp);
+}
+
+void ipic_set_default_priority(void)
+{
+ ipic_set_priority(MPC83xx_IRQ_TSEC1_TX, 0);
+ ipic_set_priority(MPC83xx_IRQ_TSEC1_RX, 1);
+ ipic_set_priority(MPC83xx_IRQ_TSEC1_ERROR, 2);
+ ipic_set_priority(MPC83xx_IRQ_TSEC2_TX, 3);
+ ipic_set_priority(MPC83xx_IRQ_TSEC2_RX, 4);
+ ipic_set_priority(MPC83xx_IRQ_TSEC2_ERROR, 5);
+ ipic_set_priority(MPC83xx_IRQ_USB2_DR, 6);
+ ipic_set_priority(MPC83xx_IRQ_USB2_MPH, 7);
+
+ ipic_set_priority(MPC83xx_IRQ_UART1, 0);
+ ipic_set_priority(MPC83xx_IRQ_UART2, 1);
+ ipic_set_priority(MPC83xx_IRQ_SEC2, 2);
+ ipic_set_priority(MPC83xx_IRQ_IIC1, 5);
+ ipic_set_priority(MPC83xx_IRQ_IIC2, 6);
+ ipic_set_priority(MPC83xx_IRQ_SPI, 7);
+ ipic_set_priority(MPC83xx_IRQ_RTC_SEC, 0);
+ ipic_set_priority(MPC83xx_IRQ_PIT, 1);
+ ipic_set_priority(MPC83xx_IRQ_PCI1, 2);
+ ipic_set_priority(MPC83xx_IRQ_PCI2, 3);
+ ipic_set_priority(MPC83xx_IRQ_EXT0, 4);
+ ipic_set_priority(MPC83xx_IRQ_EXT1, 5);
+ ipic_set_priority(MPC83xx_IRQ_EXT2, 6);
+ ipic_set_priority(MPC83xx_IRQ_EXT3, 7);
+ ipic_set_priority(MPC83xx_IRQ_RTC_ALR, 0);
+ ipic_set_priority(MPC83xx_IRQ_MU, 1);
+ ipic_set_priority(MPC83xx_IRQ_SBA, 2);
+ ipic_set_priority(MPC83xx_IRQ_DMA, 3);
+ ipic_set_priority(MPC83xx_IRQ_EXT4, 4);
+ ipic_set_priority(MPC83xx_IRQ_EXT5, 5);
+ ipic_set_priority(MPC83xx_IRQ_EXT6, 6);
+ ipic_set_priority(MPC83xx_IRQ_EXT7, 7);
+}
+
+void ipic_enable_mcp(enum ipic_mcp_irq mcp_irq)
+{
+ struct ipic *ipic = primary_ipic;
+ u32 temp;
+
+ temp = ipic_read(ipic->regs, IPIC_SERMR);
+ temp |= (1 << (31 - mcp_irq));
+ ipic_write(ipic->regs, IPIC_SERMR, temp);
+}
+
+void ipic_disable_mcp(enum ipic_mcp_irq mcp_irq)
+{
+ struct ipic *ipic = primary_ipic;
+ u32 temp;
+
+ temp = ipic_read(ipic->regs, IPIC_SERMR);
+ temp &= (1 << (31 - mcp_irq));
+ ipic_write(ipic->regs, IPIC_SERMR, temp);
+}
+
+u32 ipic_get_mcp_status(void)
+{
+ return ipic_read(primary_ipic->regs, IPIC_SERMR);
+}
+
+void ipic_clear_mcp_status(u32 mask)
+{
+ ipic_write(primary_ipic->regs, IPIC_SERMR, mask);
+}
+
+/* Return an interrupt vector or -1 if no interrupt is pending. */
+int ipic_get_irq(struct pt_regs *regs)
+{
+ int irq;
+
+ irq = ipic_read(primary_ipic->regs, IPIC_SIVCR) & 0x7f;
+
+ if (irq == 0) /* 0 --> no irq is pending */
+ irq = -1;
+
+ return irq;
+}
+
+static struct sysdev_class ipic_sysclass = {
+ set_kset_name("ipic"),
+};
+
+static struct sys_device device_ipic = {
+ .id = 0,
+ .cls = &ipic_sysclass,
+};
+
+static int __init init_ipic_sysfs(void)
+{
+ int rc;
+
+ if (!primary_ipic->regs)
+ return -ENODEV;
+ printk(KERN_DEBUG "Registering ipic with sysfs...\n");
+
+ rc = sysdev_class_register(&ipic_sysclass);
+ if (rc) {
+ printk(KERN_ERR "Failed registering ipic sys class\n");
+ return -ENODEV;
+ }
+ rc = sysdev_register(&device_ipic);
+ if (rc) {
+ printk(KERN_ERR "Failed registering ipic sys device\n");
+ return -ENODEV;
+ }
+ return 0;
+}
+
+subsys_initcall(init_ipic_sysfs);
diff --git a/arch/ppc/syslib/ipic.h b/arch/ppc/syslib/ipic.h
new file mode 100644
index 0000000000000..2b56a4fcf373e
--- /dev/null
+++ b/arch/ppc/syslib/ipic.h
@@ -0,0 +1,49 @@
+/*
+ * arch/ppc/kernel/ipic.h
+ *
+ * IPIC private definitions and structure.
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2005 Freescale Semiconductor, Inc
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+#ifndef __IPIC_H__
+#define __IPIC_H__
+
+#include <asm/ipic.h>
+
+#define MPC83xx_IPIC_SIZE (0x00100)
+
+/* System Global Interrupt Configuration Register */
+#define SICFR_IPSA 0x00010000
+#define SICFR_IPSD 0x00080000
+#define SICFR_MPSA 0x00200000
+#define SICFR_MPSB 0x00400000
+
+/* System External Interrupt Mask Register */
+#define SEMSR_SIRQ0 0x00008000
+
+/* System Error Control Register */
+#define SERCR_MCPR 0x00000001
+
+struct ipic {
+ volatile u32 __iomem *regs;
+ unsigned int irq_offset;
+};
+
+struct ipic_info {
+ u8 pend; /* pending register offset from base */
+ u8 mask; /* mask register offset from base */
+ u8 prio; /* priority register offset from base */
+ u8 force; /* force register offset from base */
+ u8 bit; /* register bit position (as per doc)
+ bit mask = 1 << (31 - bit) */
+ u8 prio_mask; /* priority mask value */
+};
+
+#endif /* __IPIC_H__ */
diff --git a/arch/ppc/syslib/m8260_setup.c b/arch/ppc/syslib/m8260_setup.c
index f3c12a51bf3e0..23ea3f694de20 100644
--- a/arch/ppc/syslib/m8260_setup.c
+++ b/arch/ppc/syslib/m8260_setup.c
@@ -167,18 +167,12 @@ m8260_show_cpuinfo(struct seq_file *m)
static void __init
m8260_init_IRQ(void)
{
- int i;
-
- for ( i = 0 ; i < NR_SIU_INTS ; i++ )
- irq_desc[i].handler = &cpm2_pic;
+ cpm2_init_IRQ();
/* Initialize the default interrupt mapping priorities,
* in case the boot rom changed something on us.
*/
- cpm2_immr->im_intctl.ic_sicr = 0;
cpm2_immr->im_intctl.ic_siprr = 0x05309770;
- cpm2_immr->im_intctl.ic_scprrh = 0x05309770;
- cpm2_immr->im_intctl.ic_scprrl = 0x05309770;
}
/*
diff --git a/arch/ppc/syslib/mpc52xx_devices.c b/arch/ppc/syslib/mpc52xx_devices.c
new file mode 100644
index 0000000000000..ad5182efca1dd
--- /dev/null
+++ b/arch/ppc/syslib/mpc52xx_devices.c
@@ -0,0 +1,318 @@
+/*
+ * arch/ppc/syslib/mpc52xx_devices.c
+ *
+ * Freescale MPC52xx device descriptions
+ *
+ *
+ * Maintainer : Sylvain Munaut <tnt@246tNt.com>
+ *
+ * Copyright (C) 2005 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 <linux/fsl_devices.h>
+#include <linux/resource.h>
+#include <asm/mpc52xx.h>
+#include <asm/ppc_sys.h>
+
+
+static u64 mpc52xx_dma_mask = 0xffffffffULL;
+
+static struct fsl_i2c_platform_data mpc52xx_fsl_i2c_pdata = {
+ .device_flags = FSL_I2C_DEV_CLOCK_5200,
+};
+
+
+/* We use relative offsets for IORESOURCE_MEM to be independent from the
+ * MBAR location at compile time
+ */
+
+/* TODO Add the BestComm initiator channel to the device definitions,
+ possibly using IORESOURCE_DMA. But that's when BestComm is ready ... */
+
+struct platform_device ppc_sys_platform_devices[] = {
+ [MPC52xx_MSCAN1] = {
+ .name = "mpc52xx-mscan",
+ .id = 0,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x0900,
+ .end = 0x097f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC52xx_MSCAN1_IRQ,
+ .end = MPC52xx_MSCAN1_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC52xx_MSCAN2] = {
+ .name = "mpc52xx-mscan",
+ .id = 1,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x0980,
+ .end = 0x09ff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC52xx_MSCAN2_IRQ,
+ .end = MPC52xx_MSCAN2_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC52xx_SPI] = {
+ .name = "mpc52xx-spi",
+ .id = -1,
+ .num_resources = 3,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x0f00,
+ .end = 0x0f1f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "modf",
+ .start = MPC52xx_SPI_MODF_IRQ,
+ .end = MPC52xx_SPI_MODF_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "spif",
+ .start = MPC52xx_SPI_SPIF_IRQ,
+ .end = MPC52xx_SPI_SPIF_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC52xx_USB] = {
+ .name = "ppc-soc-ohci",
+ .id = -1,
+ .num_resources = 2,
+ .dev.dma_mask = &mpc52xx_dma_mask,
+ .dev.coherent_dma_mask = 0xffffffffULL,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x1000,
+ .end = 0x10ff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC52xx_USB_IRQ,
+ .end = MPC52xx_USB_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC52xx_BDLC] = {
+ .name = "mpc52xx-bdlc",
+ .id = -1,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x1300,
+ .end = 0x130f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC52xx_BDLC_IRQ,
+ .end = MPC52xx_BDLC_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC52xx_PSC1] = {
+ .name = "mpc52xx-psc",
+ .id = 0,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x2000,
+ .end = 0x209f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC52xx_PSC1_IRQ,
+ .end = MPC52xx_PSC1_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC52xx_PSC2] = {
+ .name = "mpc52xx-psc",
+ .id = 1,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x2200,
+ .end = 0x229f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC52xx_PSC2_IRQ,
+ .end = MPC52xx_PSC2_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC52xx_PSC3] = {
+ .name = "mpc52xx-psc",
+ .id = 2,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x2400,
+ .end = 0x249f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC52xx_PSC3_IRQ,
+ .end = MPC52xx_PSC3_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC52xx_PSC4] = {
+ .name = "mpc52xx-psc",
+ .id = 3,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x2600,
+ .end = 0x269f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC52xx_PSC4_IRQ,
+ .end = MPC52xx_PSC4_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC52xx_PSC5] = {
+ .name = "mpc52xx-psc",
+ .id = 4,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x2800,
+ .end = 0x289f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC52xx_PSC5_IRQ,
+ .end = MPC52xx_PSC5_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC52xx_PSC6] = {
+ .name = "mpc52xx-psc",
+ .id = 5,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x2c00,
+ .end = 0x2c9f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC52xx_PSC6_IRQ,
+ .end = MPC52xx_PSC6_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC52xx_FEC] = {
+ .name = "mpc52xx-fec",
+ .id = -1,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x3000,
+ .end = 0x33ff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC52xx_FEC_IRQ,
+ .end = MPC52xx_FEC_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC52xx_ATA] = {
+ .name = "mpc52xx-ata",
+ .id = -1,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x3a00,
+ .end = 0x3aff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC52xx_ATA_IRQ,
+ .end = MPC52xx_ATA_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC52xx_I2C1] = {
+ .name = "fsl-i2c",
+ .id = 0,
+ .dev.platform_data = &mpc52xx_fsl_i2c_pdata,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x3d00,
+ .end = 0x3d1f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC52xx_I2C1_IRQ,
+ .end = MPC52xx_I2C1_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC52xx_I2C2] = {
+ .name = "fsl-i2c",
+ .id = 1,
+ .dev.platform_data = &mpc52xx_fsl_i2c_pdata,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x3d40,
+ .end = 0x3d5f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC52xx_I2C2_IRQ,
+ .end = MPC52xx_I2C2_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+};
+
+
+static int __init mach_mpc52xx_fixup(struct platform_device *pdev)
+{
+ ppc_sys_fixup_mem_resource(pdev, MPC52xx_MBAR);
+ return 0;
+}
+
+static int __init mach_mpc52xx_init(void)
+{
+ ppc_sys_device_fixup = mach_mpc52xx_fixup;
+ return 0;
+}
+
+postcore_initcall(mach_mpc52xx_init);
diff --git a/arch/ppc/syslib/mpc52xx_pci.c b/arch/ppc/syslib/mpc52xx_pci.c
new file mode 100644
index 0000000000000..c723efd954a6a
--- /dev/null
+++ b/arch/ppc/syslib/mpc52xx_pci.c
@@ -0,0 +1,235 @@
+/*
+ * arch/ppc/syslib/mpc52xx_pci.c
+ *
+ * PCI code for the Freescale MPC52xx embedded CPU.
+ *
+ *
+ * Maintainer : Sylvain Munaut <tnt@246tNt.com>
+ *
+ * Copyright (C) 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 <linux/config.h>
+
+#include <asm/pci.h>
+
+#include <asm/mpc52xx.h>
+#include "mpc52xx_pci.h"
+
+#include <asm/delay.h>
+
+
+static int
+mpc52xx_pci_read_config(struct pci_bus *bus, unsigned int devfn,
+ int offset, int len, u32 *val)
+{
+ struct pci_controller *hose = bus->sysdata;
+ u32 value;
+
+ if (ppc_md.pci_exclude_device)
+ if (ppc_md.pci_exclude_device(bus->number, devfn))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ out_be32(hose->cfg_addr,
+ (1 << 31) |
+ ((bus->number - hose->bus_offset) << 16) |
+ (devfn << 8) |
+ (offset & 0xfc));
+
+ value = in_le32(hose->cfg_data);
+
+ if (len != 4) {
+ value >>= ((offset & 0x3) << 3);
+ value &= 0xffffffff >> (32 - (len << 3));
+ }
+
+ *val = value;
+
+ out_be32(hose->cfg_addr, 0);
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+mpc52xx_pci_write_config(struct pci_bus *bus, unsigned int devfn,
+ int offset, int len, u32 val)
+{
+ struct pci_controller *hose = bus->sysdata;
+ u32 value, mask;
+
+ if (ppc_md.pci_exclude_device)
+ if (ppc_md.pci_exclude_device(bus->number, devfn))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ out_be32(hose->cfg_addr,
+ (1 << 31) |
+ ((bus->number - hose->bus_offset) << 16) |
+ (devfn << 8) |
+ (offset & 0xfc));
+
+ if (len != 4) {
+ value = in_le32(hose->cfg_data);
+
+ offset = (offset & 0x3) << 3;
+ mask = (0xffffffff >> (32 - (len << 3)));
+ mask <<= offset;
+
+ value &= ~mask;
+ val = value | ((val << offset) & mask);
+ }
+
+ out_le32(hose->cfg_data, val);
+
+ out_be32(hose->cfg_addr, 0);
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops mpc52xx_pci_ops = {
+ .read = mpc52xx_pci_read_config,
+ .write = mpc52xx_pci_write_config
+};
+
+
+static void __init
+mpc52xx_pci_setup(struct mpc52xx_pci __iomem *pci_regs)
+{
+
+ /* Setup control regs */
+ /* Nothing to do afaik */
+
+ /* Setup windows */
+ out_be32(&pci_regs->iw0btar, MPC52xx_PCI_IWBTAR_TRANSLATION(
+ MPC52xx_PCI_MEM_START + MPC52xx_PCI_MEM_OFFSET,
+ MPC52xx_PCI_MEM_START,
+ MPC52xx_PCI_MEM_SIZE ));
+
+ out_be32(&pci_regs->iw1btar, MPC52xx_PCI_IWBTAR_TRANSLATION(
+ MPC52xx_PCI_MMIO_START + MPC52xx_PCI_MEM_OFFSET,
+ MPC52xx_PCI_MMIO_START,
+ MPC52xx_PCI_MMIO_SIZE ));
+
+ out_be32(&pci_regs->iw2btar, MPC52xx_PCI_IWBTAR_TRANSLATION(
+ MPC52xx_PCI_IO_BASE,
+ MPC52xx_PCI_IO_START,
+ MPC52xx_PCI_IO_SIZE ));
+
+ out_be32(&pci_regs->iwcr, MPC52xx_PCI_IWCR_PACK(
+ ( MPC52xx_PCI_IWCR_ENABLE | /* iw0btar */
+ MPC52xx_PCI_IWCR_READ_MULTI |
+ MPC52xx_PCI_IWCR_MEM ),
+ ( MPC52xx_PCI_IWCR_ENABLE | /* iw1btar */
+ MPC52xx_PCI_IWCR_READ |
+ MPC52xx_PCI_IWCR_MEM ),
+ ( MPC52xx_PCI_IWCR_ENABLE | /* iw2btar */
+ MPC52xx_PCI_IWCR_IO )
+ ));
+
+
+ out_be32(&pci_regs->tbatr0,
+ MPC52xx_PCI_TBATR_ENABLE | MPC52xx_PCI_TARGET_IO );
+ out_be32(&pci_regs->tbatr1,
+ MPC52xx_PCI_TBATR_ENABLE | MPC52xx_PCI_TARGET_MEM );
+
+ out_be32(&pci_regs->tcr, MPC52xx_PCI_TCR_LD);
+
+ /* Reset the exteral bus ( internal PCI controller is NOT resetted ) */
+ /* 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);
+ out_be32(&pci_regs->gscr, tmp | MPC52xx_PCI_GSCR_PR);
+ udelay(50);
+ out_be32(&pci_regs->gscr, tmp);
+#endif
+}
+
+static void __init
+mpc52xx_pci_fixup_resources(struct pci_dev *dev)
+{
+ int i;
+
+ /* We don't rely on boot loader for PCI and resets all
+ devices */
+ for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
+ struct resource *res = &dev->resource[i];
+ if (res->end > res->start) { /* Only valid resources */
+ res->end -= res->start;
+ res->start = 0;
+ res->flags |= IORESOURCE_UNSET;
+ }
+ }
+
+ /* The PCI Host bridge of MPC52xx has a prefetch memory resource
+ fixed to 1Gb. Doesn't fit in the resource system so we remove it */
+ if ( (dev->vendor == PCI_VENDOR_ID_MOTOROLA) &&
+ (dev->device == PCI_DEVICE_ID_MOTOROLA_MPC5200) ) {
+ struct resource *res = &dev->resource[1];
+ res->start = res->end = res->flags = 0;
+ }
+}
+
+void __init
+mpc52xx_find_bridges(void)
+{
+ struct mpc52xx_pci __iomem *pci_regs;
+ struct pci_controller *hose;
+
+ pci_assign_all_busses = 1;
+
+ pci_regs = ioremap(MPC52xx_PA(MPC52xx_PCI_OFFSET), MPC52xx_PCI_SIZE);
+ if (!pci_regs)
+ return;
+
+ hose = pcibios_alloc_controller();
+ if (!hose) {
+ iounmap(pci_regs);
+ return;
+ }
+
+ ppc_md.pci_swizzle = common_swizzle;
+ ppc_md.pcibios_fixup_resources = mpc52xx_pci_fixup_resources;
+
+ hose->first_busno = 0;
+ hose->last_busno = 0xff;
+ hose->bus_offset = 0;
+ hose->ops = &mpc52xx_pci_ops;
+
+ mpc52xx_pci_setup(pci_regs);
+
+ hose->pci_mem_offset = MPC52xx_PCI_MEM_OFFSET;
+
+ isa_io_base =
+ (unsigned long) ioremap(MPC52xx_PCI_IO_BASE,
+ MPC52xx_PCI_IO_SIZE);
+ hose->io_base_virt = (void *) isa_io_base;
+
+ hose->cfg_addr = &pci_regs->car;
+ hose->cfg_data = (void __iomem *) isa_io_base;
+
+ /* Setup resources */
+ pci_init_resource(&hose->mem_resources[0],
+ MPC52xx_PCI_MEM_START,
+ MPC52xx_PCI_MEM_STOP,
+ IORESOURCE_MEM|IORESOURCE_PREFETCH,
+ "PCI prefetchable memory");
+
+ pci_init_resource(&hose->mem_resources[1],
+ MPC52xx_PCI_MMIO_START,
+ MPC52xx_PCI_MMIO_STOP,
+ IORESOURCE_MEM,
+ "PCI memory");
+
+ pci_init_resource(&hose->io_resource,
+ MPC52xx_PCI_IO_START,
+ MPC52xx_PCI_IO_STOP,
+ IORESOURCE_IO,
+ "PCI I/O");
+
+}
diff --git a/arch/ppc/syslib/mpc52xx_pci.h b/arch/ppc/syslib/mpc52xx_pci.h
new file mode 100644
index 0000000000000..04b509a02530d
--- /dev/null
+++ b/arch/ppc/syslib/mpc52xx_pci.h
@@ -0,0 +1,139 @@
+/*
+ * arch/ppc/syslib/mpc52xx_pci.h
+ *
+ * PCI Include file the Freescale MPC52xx embedded cpu chips
+ *
+ *
+ * Maintainer : Sylvain Munaut <tnt@246tNt.com>
+ *
+ * Inspired from code written by Dale Farnsworth <dfarnsworth@mvista.com>
+ * for the 2.4 kernel.
+ *
+ * Copyright (C) 2004 Sylvain Munaut <tnt@246tNt.com>
+ * Copyright (C) 2003 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 __SYSLIB_MPC52xx_PCI_H__
+#define __SYSLIB_MPC52xx_PCI_H__
+
+/* ======================================================================== */
+/* PCI windows config */
+/* ======================================================================== */
+
+/*
+ * Master windows : MPC52xx -> PCI
+ *
+ * 0x80000000 -> 0x9FFFFFFF PCI Mem prefetchable IW0BTAR
+ * 0xA0000000 -> 0xAFFFFFFF PCI Mem IW1BTAR
+ * 0xB0000000 -> 0xB0FFFFFF PCI IO IW2BTAR
+ *
+ * Slave windows : PCI -> MPC52xx
+ *
+ * 0xF0000000 -> 0xF003FFFF MPC52xx MBAR TBATR0
+ * 0x00000000 -> 0x3FFFFFFF MPC52xx local memory TBATR1
+ */
+
+#define MPC52xx_PCI_MEM_OFFSET 0x00000000 /* Offset for MEM MMIO */
+
+#define MPC52xx_PCI_MEM_START 0x80000000
+#define MPC52xx_PCI_MEM_SIZE 0x20000000
+#define MPC52xx_PCI_MEM_STOP (MPC52xx_PCI_MEM_START+MPC52xx_PCI_MEM_SIZE-1)
+
+#define MPC52xx_PCI_MMIO_START 0xa0000000
+#define MPC52xx_PCI_MMIO_SIZE 0x10000000
+#define MPC52xx_PCI_MMIO_STOP (MPC52xx_PCI_MMIO_START+MPC52xx_PCI_MMIO_SIZE-1)
+
+#define MPC52xx_PCI_IO_BASE 0xb0000000
+
+#define MPC52xx_PCI_IO_START 0x00000000
+#define MPC52xx_PCI_IO_SIZE 0x01000000
+#define MPC52xx_PCI_IO_STOP (MPC52xx_PCI_IO_START+MPC52xx_PCI_IO_SIZE-1)
+
+
+#define MPC52xx_PCI_TARGET_IO MPC52xx_MBAR
+#define MPC52xx_PCI_TARGET_MEM 0x00000000
+
+
+/* ======================================================================== */
+/* Structures mapping & Defines for PCI Unit */
+/* ======================================================================== */
+
+#define MPC52xx_PCI_GSCR_BM 0x40000000
+#define MPC52xx_PCI_GSCR_PE 0x20000000
+#define MPC52xx_PCI_GSCR_SE 0x10000000
+#define MPC52xx_PCI_GSCR_XLB2PCI_MASK 0x07000000
+#define MPC52xx_PCI_GSCR_XLB2PCI_SHIFT 24
+#define MPC52xx_PCI_GSCR_IPG2PCI_MASK 0x00070000
+#define MPC52xx_PCI_GSCR_IPG2PCI_SHIFT 16
+#define MPC52xx_PCI_GSCR_BME 0x00004000
+#define MPC52xx_PCI_GSCR_PEE 0x00002000
+#define MPC52xx_PCI_GSCR_SEE 0x00001000
+#define MPC52xx_PCI_GSCR_PR 0x00000001
+
+
+#define MPC52xx_PCI_IWBTAR_TRANSLATION(proc_ad,pci_ad,size) \
+ ( ( (proc_ad) & 0xff000000 ) | \
+ ( (((size) - 1) >> 8) & 0x00ff0000 ) | \
+ ( ((pci_ad) >> 16) & 0x0000ff00 ) )
+
+#define MPC52xx_PCI_IWCR_PACK(win0,win1,win2) (((win0) << 24) | \
+ ((win1) << 16) | \
+ ((win2) << 8))
+
+#define MPC52xx_PCI_IWCR_DISABLE 0x0
+#define MPC52xx_PCI_IWCR_ENABLE 0x1
+#define MPC52xx_PCI_IWCR_READ 0x0
+#define MPC52xx_PCI_IWCR_READ_LINE 0x2
+#define MPC52xx_PCI_IWCR_READ_MULTI 0x4
+#define MPC52xx_PCI_IWCR_MEM 0x0
+#define MPC52xx_PCI_IWCR_IO 0x8
+
+#define MPC52xx_PCI_TCR_P 0x01000000
+#define MPC52xx_PCI_TCR_LD 0x00010000
+
+#define MPC52xx_PCI_TBATR_DISABLE 0x0
+#define MPC52xx_PCI_TBATR_ENABLE 0x1
+
+
+#ifndef __ASSEMBLY__
+
+struct mpc52xx_pci {
+ u32 idr; /* PCI + 0x00 */
+ u32 scr; /* PCI + 0x04 */
+ u32 ccrir; /* PCI + 0x08 */
+ u32 cr1; /* PCI + 0x0C */
+ u32 bar0; /* PCI + 0x10 */
+ u32 bar1; /* PCI + 0x14 */
+ u8 reserved1[16]; /* PCI + 0x18 */
+ u32 ccpr; /* PCI + 0x28 */
+ u32 sid; /* PCI + 0x2C */
+ u32 erbar; /* PCI + 0x30 */
+ u32 cpr; /* PCI + 0x34 */
+ u8 reserved2[4]; /* PCI + 0x38 */
+ u32 cr2; /* PCI + 0x3C */
+ u8 reserved3[32]; /* PCI + 0x40 */
+ u32 gscr; /* PCI + 0x60 */
+ u32 tbatr0; /* PCI + 0x64 */
+ u32 tbatr1; /* PCI + 0x68 */
+ u32 tcr; /* PCI + 0x6C */
+ u32 iw0btar; /* PCI + 0x70 */
+ u32 iw1btar; /* PCI + 0x74 */
+ u32 iw2btar; /* PCI + 0x78 */
+ u8 reserved4[4]; /* PCI + 0x7C */
+ u32 iwcr; /* PCI + 0x80 */
+ u32 icr; /* PCI + 0x84 */
+ u32 isr; /* PCI + 0x88 */
+ u32 arb; /* PCI + 0x8C */
+ u8 reserved5[104]; /* PCI + 0x90 */
+ u32 car; /* PCI + 0xF8 */
+ u8 reserved6[4]; /* PCI + 0xFC */
+};
+
+#endif /* __ASSEMBLY__ */
+
+
+#endif /* __SYSLIB_MPC52xx_PCI_H__ */
diff --git a/arch/ppc/syslib/mpc52xx_pic.c b/arch/ppc/syslib/mpc52xx_pic.c
index 4de79d3b9bfe2..4c4497e62517d 100644
--- a/arch/ppc/syslib/mpc52xx_pic.c
+++ b/arch/ppc/syslib/mpc52xx_pic.c
@@ -33,8 +33,8 @@
#include <asm/mpc52xx.h>
-static struct mpc52xx_intr *intr;
-static struct mpc52xx_sdma *sdma;
+static struct mpc52xx_intr __iomem *intr;
+static struct mpc52xx_sdma __iomem *sdma;
static void
mpc52xx_ic_disable(unsigned int irq)
@@ -166,14 +166,11 @@ mpc52xx_ic_end(unsigned int irq)
}
static struct hw_interrupt_type mpc52xx_ic = {
- "MPC52xx",
- NULL, /* startup(irq) */
- NULL, /* shutdown(irq) */
- mpc52xx_ic_enable, /* enable(irq) */
- mpc52xx_ic_disable, /* disable(irq) */
- mpc52xx_ic_disable_and_ack, /* disable_and_ack(irq) */
- mpc52xx_ic_end, /* end(irq) */
- 0 /* set_affinity(irq, cpumask) SMP. */
+ .typename = " MPC52xx ",
+ .enable = mpc52xx_ic_enable,
+ .disable = mpc52xx_ic_disable,
+ .ack = mpc52xx_ic_disable_and_ack,
+ .end = mpc52xx_ic_end,
};
void __init
@@ -183,10 +180,8 @@ mpc52xx_init_irq(void)
u32 intr_ctrl;
/* Remap the necessary zones */
- intr = (struct mpc52xx_intr *)
- ioremap(MPC52xx_INTR, sizeof(struct mpc52xx_intr));
- sdma = (struct mpc52xx_sdma *)
- ioremap(MPC52xx_SDMA, sizeof(struct mpc52xx_sdma));
+ intr = ioremap(MPC52xx_PA(MPC52xx_INTR_OFFSET), MPC52xx_INTR_SIZE);
+ sdma = ioremap(MPC52xx_PA(MPC52xx_SDMA_OFFSET), MPC52xx_SDMA_SIZE);
if ((intr==NULL) || (sdma==NULL))
panic("Can't ioremap PIC/SDMA register for init_irq !");
diff --git a/arch/ppc/syslib/mpc52xx_setup.c b/arch/ppc/syslib/mpc52xx_setup.c
index 6bd014d7c9dce..bb2374585a7b9 100644
--- a/arch/ppc/syslib/mpc52xx_setup.c
+++ b/arch/ppc/syslib/mpc52xx_setup.c
@@ -23,7 +23,6 @@
#include <asm/time.h>
#include <asm/mpc52xx.h>
#include <asm/mpc52xx_psc.h>
-#include <asm/ocp.h>
#include <asm/pgtable.h>
#include <asm/ppcboot.h>
@@ -39,17 +38,14 @@ static int core_mult[] = { /* CPU Frequency multiplier, taken */
void
mpc52xx_restart(char *cmd)
{
- struct mpc52xx_gpt* gpt0 = (struct mpc52xx_gpt*) MPC52xx_GPTx(0);
+ struct mpc52xx_gpt __iomem *gpt0 = MPC52xx_VA(MPC52xx_GPTx_OFFSET(0));
local_irq_disable();
/* Turn on the watchdog and wait for it to expire. It effectively
does a reset */
- if (gpt0 != NULL) {
- out_be32(&gpt0->count, 0x000000ff);
- out_be32(&gpt0->mode, 0x00009004);
- } else
- printk(KERN_ERR "mpc52xx_restart: Unable to ioremap GPT0 registers, -> looping ...");
+ out_be32(&gpt0->count, 0x000000ff);
+ out_be32(&gpt0->mode, 0x00009004);
while (1);
}
@@ -80,8 +76,8 @@ mpc52xx_set_bat(void)
* mpc52xx_find_end_of_memory, and UARTs/GPIO access for debug
*/
mb();
- mtspr(DBAT2U, 0xf0001ffe);
- mtspr(DBAT2L, 0xf000002a);
+ mtspr(SPRN_DBAT2U, 0xf0001ffe);
+ mtspr(SPRN_DBAT2L, 0xf000002a);
mb();
}
@@ -95,14 +91,12 @@ mpc52xx_map_io(void)
#ifdef CONFIG_SERIAL_TEXT_DEBUG
-#ifdef MPC52xx_PF_CONSOLE_PORT
-#define MPC52xx_CONSOLE MPC52xx_PSCx(MPC52xx_PF_CONSOLE_PORT)
-#else
+#ifndef MPC52xx_PF_CONSOLE_PORT
#error "mpc52xx PSC for console not selected"
#endif
static void
-mpc52xx_psc_putc(struct mpc52xx_psc * psc, unsigned char c)
+mpc52xx_psc_putc(struct mpc52xx_psc __iomem *psc, unsigned char c)
{
while (!(in_be16(&psc->mpc52xx_psc_status) &
MPC52xx_PSC_SR_TXRDY));
@@ -112,8 +106,10 @@ mpc52xx_psc_putc(struct mpc52xx_psc * psc, unsigned char c)
void
mpc52xx_progress(char *s, unsigned short hex)
{
- struct mpc52xx_psc *psc = (struct mpc52xx_psc *)MPC52xx_CONSOLE;
char c;
+ struct mpc52xx_psc __iomem *psc;
+
+ psc = MPC52xx_VA(MPC52xx_PSCx_OFFSET(MPC52xx_PF_CONSOLE_PORT));
while ((c = *s++) != 0) {
if (c == '\n')
@@ -138,11 +134,11 @@ mpc52xx_find_end_of_memory(void)
* else get size from sdram config registers
*/
if (ramsize == 0) {
- struct mpc52xx_mmap_ctl *mmap_ctl;
+ struct mpc52xx_mmap_ctl __iomem *mmap_ctl;
u32 sdram_config_0, sdram_config_1;
/* Temp BAT2 mapping active when this is called ! */
- mmap_ctl = (struct mpc52xx_mmap_ctl*) MPC52xx_MMAP_CTL;
+ mmap_ctl = MPC52xx_VA(MPC52xx_MMAP_CTL_OFFSET);
sdram_config_0 = in_be32(&mmap_ctl->sdram0);
sdram_config_1 = in_be32(&mmap_ctl->sdram1);
@@ -169,13 +165,11 @@ mpc52xx_calibrate_decr(void)
/* if bootloader didn't pass bus frequencies, calculate them */
if (xlbfreq == 0) {
/* Get RTC & Clock manager modules */
- struct mpc52xx_rtc *rtc;
- struct mpc52xx_cdm *cdm;
+ struct mpc52xx_rtc __iomem *rtc;
+ struct mpc52xx_cdm __iomem *cdm;
- rtc = (struct mpc52xx_rtc*)
- ioremap(MPC52xx_RTC, sizeof(struct mpc52xx_rtc));
- cdm = (struct mpc52xx_cdm*)
- ioremap(MPC52xx_CDM, sizeof(struct mpc52xx_cdm));
+ rtc = ioremap(MPC52xx_PA(MPC52xx_RTC_OFFSET), MPC52xx_RTC_SIZE);
+ cdm = ioremap(MPC52xx_PA(MPC52xx_CDM_OFFSET), MPC52xx_CDM_SIZE);
if ((rtc==NULL) || (cdm==NULL))
panic("Can't ioremap RTC/CDM while computing bus freq");
@@ -212,8 +206,8 @@ mpc52xx_calibrate_decr(void)
__res.bi_pcifreq = pcifreq;
/* Release mapping */
- iounmap((void*)rtc);
- iounmap((void*)cdm);
+ iounmap(rtc);
+ iounmap(cdm);
}
divisor = 4;
@@ -222,11 +216,15 @@ mpc52xx_calibrate_decr(void)
tb_to_us = mulhwu_scale_factor(xlbfreq / divisor, 1000000);
}
+int mpc52xx_match_psc_function(int psc_idx, const char *func)
+{
+ struct mpc52xx_psc_func *cf = mpc52xx_psc_functions;
-void __init
-mpc52xx_add_board_devices(struct ocp_def board_ocp[]) {
- while (board_ocp->vendor != OCP_VENDOR_INVALID)
- if(ocp_add_one_device(board_ocp++))
- printk("mpc5200-ocp: Failed to add board device !\n");
-}
+ while ((cf->id != -1) && (cf->func != NULL)) {
+ if ((cf->id == psc_idx) && !strcmp(cf->func,func))
+ return 1;
+ cf++;
+ }
+ return 0;
+}
diff --git a/arch/ppc/syslib/mpc52xx_sys.c b/arch/ppc/syslib/mpc52xx_sys.c
new file mode 100644
index 0000000000000..9a0f90aa8aac8
--- /dev/null
+++ b/arch/ppc/syslib/mpc52xx_sys.c
@@ -0,0 +1,38 @@
+/*
+ * arch/ppc/syslib/mpc52xx_sys.c
+ *
+ * Freescale MPC52xx system descriptions
+ *
+ *
+ * Maintainer : Sylvain Munaut <tnt@246tNt.com>
+ *
+ * Copyright (C) 2005 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/ppc_sys.h>
+
+struct ppc_sys_spec *cur_ppc_sys_spec;
+struct ppc_sys_spec ppc_sys_specs[] = {
+ {
+ .ppc_sys_name = "5200",
+ .mask = 0xffff0000,
+ .value = 0x80110000,
+ .num_devices = 15,
+ .device_list = (enum ppc_sys_devices[])
+ {
+ MPC52xx_MSCAN1, MPC52xx_MSCAN2, MPC52xx_SPI,
+ MPC52xx_USB, MPC52xx_BDLC, MPC52xx_PSC1, MPC52xx_PSC2,
+ MPC52xx_PSC3, MPC52xx_PSC4, MPC52xx_PSC5, MPC52xx_PSC6,
+ MPC52xx_FEC, MPC52xx_ATA, MPC52xx_I2C1, MPC52xx_I2C2,
+ },
+ },
+ { /* default match */
+ .ppc_sys_name = "",
+ .mask = 0x00000000,
+ .value = 0x00000000,
+ },
+};
diff --git a/arch/ppc/syslib/mpc83xx_devices.c b/arch/ppc/syslib/mpc83xx_devices.c
new file mode 100644
index 0000000000000..5c1a919eaabfb
--- /dev/null
+++ b/arch/ppc/syslib/mpc83xx_devices.c
@@ -0,0 +1,237 @@
+/*
+ * arch/ppc/platforms/83xx/mpc83xx_devices.c
+ *
+ * MPC83xx Device descriptions
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2005 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/serial_8250.h>
+#include <linux/fsl_devices.h>
+#include <asm/mpc83xx.h>
+#include <asm/irq.h>
+#include <asm/ppc_sys.h>
+
+/* We use offsets for IORESOURCE_MEM since we do not know at compile time
+ * what IMMRBAR is, will get fixed up by mach_mpc83xx_fixup
+ */
+
+static struct gianfar_platform_data mpc83xx_tsec1_pdata = {
+ .device_flags = FSL_GIANFAR_DEV_HAS_GIGABIT |
+ FSL_GIANFAR_DEV_HAS_COALESCE | FSL_GIANFAR_DEV_HAS_RMON |
+ FSL_GIANFAR_DEV_HAS_MULTI_INTR,
+ .phy_reg_addr = 0x24000,
+};
+
+static struct gianfar_platform_data mpc83xx_tsec2_pdata = {
+ .device_flags = FSL_GIANFAR_DEV_HAS_GIGABIT |
+ FSL_GIANFAR_DEV_HAS_COALESCE | FSL_GIANFAR_DEV_HAS_RMON |
+ FSL_GIANFAR_DEV_HAS_MULTI_INTR,
+ .phy_reg_addr = 0x24000,
+};
+
+static struct fsl_i2c_platform_data mpc83xx_fsl_i2c1_pdata = {
+ .device_flags = FSL_I2C_DEV_SEPARATE_DFSRR,
+};
+
+static struct fsl_i2c_platform_data mpc83xx_fsl_i2c2_pdata = {
+ .device_flags = FSL_I2C_DEV_SEPARATE_DFSRR,
+};
+
+static struct plat_serial8250_port serial_platform_data[] = {
+ [0] = {
+ .mapbase = 0x4500,
+ .irq = MPC83xx_IRQ_UART1,
+ .iotype = UPIO_MEM,
+ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+ },
+ [1] = {
+ .mapbase = 0x4600,
+ .irq = MPC83xx_IRQ_UART2,
+ .iotype = UPIO_MEM,
+ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+ },
+};
+
+struct platform_device ppc_sys_platform_devices[] = {
+ [MPC83xx_TSEC1] = {
+ .name = "fsl-gianfar",
+ .id = 1,
+ .dev.platform_data = &mpc83xx_tsec1_pdata,
+ .num_resources = 4,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x24000,
+ .end = 0x24fff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "tx",
+ .start = MPC83xx_IRQ_TSEC1_TX,
+ .end = MPC83xx_IRQ_TSEC1_TX,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "rx",
+ .start = MPC83xx_IRQ_TSEC1_RX,
+ .end = MPC83xx_IRQ_TSEC1_RX,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "error",
+ .start = MPC83xx_IRQ_TSEC1_ERROR,
+ .end = MPC83xx_IRQ_TSEC1_ERROR,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC83xx_TSEC2] = {
+ .name = "fsl-gianfar",
+ .id = 2,
+ .dev.platform_data = &mpc83xx_tsec2_pdata,
+ .num_resources = 4,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x25000,
+ .end = 0x25fff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "tx",
+ .start = MPC83xx_IRQ_TSEC2_TX,
+ .end = MPC83xx_IRQ_TSEC2_TX,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "rx",
+ .start = MPC83xx_IRQ_TSEC2_RX,
+ .end = MPC83xx_IRQ_TSEC2_RX,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "error",
+ .start = MPC83xx_IRQ_TSEC2_ERROR,
+ .end = MPC83xx_IRQ_TSEC2_ERROR,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC83xx_IIC1] = {
+ .name = "fsl-i2c",
+ .id = 1,
+ .dev.platform_data = &mpc83xx_fsl_i2c1_pdata,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x3000,
+ .end = 0x30ff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC83xx_IRQ_IIC1,
+ .end = MPC83xx_IRQ_IIC1,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC83xx_IIC2] = {
+ .name = "fsl-i2c",
+ .id = 2,
+ .dev.platform_data = &mpc83xx_fsl_i2c2_pdata,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x3100,
+ .end = 0x31ff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC83xx_IRQ_IIC2,
+ .end = MPC83xx_IRQ_IIC2,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC83xx_DUART] = {
+ .name = "serial8250",
+ .id = 0,
+ .dev.platform_data = serial_platform_data,
+ },
+ [MPC83xx_SEC2] = {
+ .name = "fsl-sec2",
+ .id = 1,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x30000,
+ .end = 0x3ffff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC83xx_IRQ_SEC2,
+ .end = MPC83xx_IRQ_SEC2,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC83xx_USB2_DR] = {
+ .name = "fsl-usb2-dr",
+ .id = 1,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x22000,
+ .end = 0x22fff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC83xx_IRQ_USB2_DR,
+ .end = MPC83xx_IRQ_USB2_DR,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC83xx_USB2_MPH] = {
+ .name = "fsl-usb2-mph",
+ .id = 1,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x23000,
+ .end = 0x23fff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC83xx_IRQ_USB2_MPH,
+ .end = MPC83xx_IRQ_USB2_MPH,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+};
+
+static int __init mach_mpc83xx_fixup(struct platform_device *pdev)
+{
+ ppc_sys_fixup_mem_resource(pdev, immrbar);
+ return 0;
+}
+
+static int __init mach_mpc83xx_init(void)
+{
+ if (ppc_md.progress)
+ ppc_md.progress("mach_mpc83xx_init:enter", 0);
+ ppc_sys_device_fixup = mach_mpc83xx_fixup;
+ return 0;
+}
+
+postcore_initcall(mach_mpc83xx_init);
diff --git a/arch/ppc/syslib/mpc83xx_sys.c b/arch/ppc/syslib/mpc83xx_sys.c
new file mode 100644
index 0000000000000..29aa63350025c
--- /dev/null
+++ b/arch/ppc/syslib/mpc83xx_sys.c
@@ -0,0 +1,100 @@
+/*
+ * arch/ppc/platforms/83xx/mpc83xx_sys.c
+ *
+ * MPC83xx System descriptions
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2005 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <asm/ppc_sys.h>
+
+struct ppc_sys_spec *cur_ppc_sys_spec;
+struct ppc_sys_spec ppc_sys_specs[] = {
+ {
+ .ppc_sys_name = "8349E",
+ .mask = 0xFFFF0000,
+ .value = 0x80500000,
+ .num_devices = 8,
+ .device_list = (enum ppc_sys_devices[])
+ {
+ MPC83xx_TSEC1, MPC83xx_TSEC2, MPC83xx_IIC1,
+ MPC83xx_IIC2, MPC83xx_DUART, MPC83xx_SEC2,
+ MPC83xx_USB2_DR, MPC83xx_USB2_MPH
+ },
+ },
+ {
+ .ppc_sys_name = "8349",
+ .mask = 0xFFFF0000,
+ .value = 0x80510000,
+ .num_devices = 7,
+ .device_list = (enum ppc_sys_devices[])
+ {
+ MPC83xx_TSEC1, MPC83xx_TSEC2, MPC83xx_IIC1,
+ MPC83xx_IIC2, MPC83xx_DUART,
+ MPC83xx_USB2_DR, MPC83xx_USB2_MPH
+ },
+ },
+ {
+ .ppc_sys_name = "8347E",
+ .mask = 0xFFFF0000,
+ .value = 0x80520000,
+ .num_devices = 8,
+ .device_list = (enum ppc_sys_devices[])
+ {
+ MPC83xx_TSEC1, MPC83xx_TSEC2, MPC83xx_IIC1,
+ MPC83xx_IIC2, MPC83xx_DUART, MPC83xx_SEC2,
+ MPC83xx_USB2_DR, MPC83xx_USB2_MPH
+ },
+ },
+ {
+ .ppc_sys_name = "8347",
+ .mask = 0xFFFF0000,
+ .value = 0x80530000,
+ .num_devices = 7,
+ .device_list = (enum ppc_sys_devices[])
+ {
+ MPC83xx_TSEC1, MPC83xx_TSEC2, MPC83xx_IIC1,
+ MPC83xx_IIC2, MPC83xx_DUART,
+ MPC83xx_USB2_DR, MPC83xx_USB2_MPH
+ },
+ },
+ {
+ .ppc_sys_name = "8343E",
+ .mask = 0xFFFF0000,
+ .value = 0x80540000,
+ .num_devices = 7,
+ .device_list = (enum ppc_sys_devices[])
+ {
+ MPC83xx_TSEC1, MPC83xx_TSEC2, MPC83xx_IIC1,
+ MPC83xx_IIC2, MPC83xx_DUART, MPC83xx_SEC2,
+ MPC83xx_USB2_DR,
+ },
+ },
+ {
+ .ppc_sys_name = "8343",
+ .mask = 0xFFFF0000,
+ .value = 0x80550000,
+ .num_devices = 6,
+ .device_list = (enum ppc_sys_devices[])
+ {
+ MPC83xx_TSEC1, MPC83xx_TSEC2, MPC83xx_IIC1,
+ MPC83xx_IIC2, MPC83xx_DUART,
+ MPC83xx_USB2_DR,
+ },
+ },
+ { /* default match */
+ .ppc_sys_name = "",
+ .mask = 0x00000000,
+ .value = 0x00000000,
+ },
+};
diff --git a/arch/ppc/platforms/85xx/mpc85xx_devices.c b/arch/ppc/syslib/mpc85xx_devices.c
index a231795ee26f0..a231795ee26f0 100644
--- a/arch/ppc/platforms/85xx/mpc85xx_devices.c
+++ b/arch/ppc/syslib/mpc85xx_devices.c
diff --git a/arch/ppc/platforms/85xx/mpc85xx_sys.c b/arch/ppc/syslib/mpc85xx_sys.c
index 9ba0255fb061f..d806a92a9401b 100644
--- a/arch/ppc/platforms/85xx/mpc85xx_sys.c
+++ b/arch/ppc/syslib/mpc85xx_sys.c
@@ -21,7 +21,7 @@
struct ppc_sys_spec *cur_ppc_sys_spec;
struct ppc_sys_spec ppc_sys_specs[] = {
{
- .ppc_sys_name = "MPC8540",
+ .ppc_sys_name = "8540",
.mask = 0xFFFF0000,
.value = 0x80300000,
.num_devices = 10,
@@ -33,7 +33,7 @@ struct ppc_sys_spec ppc_sys_specs[] = {
},
},
{
- .ppc_sys_name = "MPC8560",
+ .ppc_sys_name = "8560",
.mask = 0xFFFF0000,
.value = 0x80700000,
.num_devices = 19,
@@ -49,7 +49,7 @@ struct ppc_sys_spec ppc_sys_specs[] = {
},
},
{
- .ppc_sys_name = "MPC8541",
+ .ppc_sys_name = "8541",
.mask = 0xFFFF0000,
.value = 0x80720000,
.num_devices = 13,
@@ -63,7 +63,7 @@ struct ppc_sys_spec ppc_sys_specs[] = {
},
},
{
- .ppc_sys_name = "MPC8541E",
+ .ppc_sys_name = "8541E",
.mask = 0xFFFF0000,
.value = 0x807A0000,
.num_devices = 14,
@@ -77,10 +77,10 @@ struct ppc_sys_spec ppc_sys_specs[] = {
},
},
{
- .ppc_sys_name = "MPC8555",
+ .ppc_sys_name = "8555",
.mask = 0xFFFF0000,
.value = 0x80710000,
- .num_devices = 20,
+ .num_devices = 19,
.device_list = (enum ppc_sys_devices[])
{
MPC85xx_TSEC1, MPC85xx_TSEC2, MPC85xx_IIC1,
@@ -88,16 +88,16 @@ struct ppc_sys_spec ppc_sys_specs[] = {
MPC85xx_PERFMON, MPC85xx_DUART,
MPC85xx_CPM_SPI, MPC85xx_CPM_I2C, MPC85xx_CPM_SCC1,
MPC85xx_CPM_SCC2, MPC85xx_CPM_SCC3,
- MPC85xx_CPM_FCC1, MPC85xx_CPM_FCC2, MPC85xx_CPM_FCC3,
+ MPC85xx_CPM_FCC1, MPC85xx_CPM_FCC2,
MPC85xx_CPM_SMC1, MPC85xx_CPM_SMC2,
MPC85xx_CPM_USB,
},
},
{
- .ppc_sys_name = "MPC8555E",
+ .ppc_sys_name = "8555E",
.mask = 0xFFFF0000,
.value = 0x80790000,
- .num_devices = 21,
+ .num_devices = 20,
.device_list = (enum ppc_sys_devices[])
{
MPC85xx_TSEC1, MPC85xx_TSEC2, MPC85xx_IIC1,
@@ -105,7 +105,7 @@ struct ppc_sys_spec ppc_sys_specs[] = {
MPC85xx_PERFMON, MPC85xx_DUART, MPC85xx_SEC2,
MPC85xx_CPM_SPI, MPC85xx_CPM_I2C, MPC85xx_CPM_SCC1,
MPC85xx_CPM_SCC2, MPC85xx_CPM_SCC3,
- MPC85xx_CPM_FCC1, MPC85xx_CPM_FCC2, MPC85xx_CPM_FCC3,
+ MPC85xx_CPM_FCC1, MPC85xx_CPM_FCC2,
MPC85xx_CPM_SMC1, MPC85xx_CPM_SMC2,
MPC85xx_CPM_USB,
},
diff --git a/arch/ppc/syslib/mv64360_pic.c b/arch/ppc/syslib/mv64360_pic.c
index 7a8d7085dd968..74d8996418e94 100644
--- a/arch/ppc/syslib/mv64360_pic.c
+++ b/arch/ppc/syslib/mv64360_pic.c
@@ -64,7 +64,7 @@ static irqreturn_t mv64360_pci_error_int_handler(int, void *, struct pt_regs *);
/* ========================== local declarations =========================== */
struct hw_interrupt_type mv64360_pic = {
- .typename = " mv64360_pic ",
+ .typename = " mv64360 ",
.enable = mv64360_unmask_irq,
.disable = mv64360_mask_irq,
.ack = mv64360_mask_irq,
@@ -155,9 +155,10 @@ mv64360_get_irq(struct pt_regs *regs)
*/
int cpu_nr = smp_processor_id();
if (cpu_nr == 1) {
- if (!(mv64x60_read(&bh, MV64360_IC_MAIN_CAUSE_LO) & (1 << 28)))
+ if (!(mv64x60_read(&bh, MV64360_IC_MAIN_CAUSE_LO) &
+ (1 << MV64x60_IRQ_DOORBELL)))
return -1;
- return 28;
+ return mv64360_irq_base + MV64x60_IRQ_DOORBELL;
}
#endif
@@ -171,7 +172,7 @@ mv64360_get_irq(struct pt_regs *regs)
if (irq == -1)
irq = -2; /* bogus interrupt, should never happen */
else {
- if ((irq >= 24) && (irq < 28)) {
+ if ((irq >= 24) && (irq < MV64x60_IRQ_DOORBELL)) {
irq_gpp = mv64x60_read(&bh,
MV64x60_GPP_INTR_CAUSE);
irq_gpp = __ilog2(irq_gpp &
@@ -217,8 +218,9 @@ mv64360_unmask_irq(unsigned int irq)
{
#ifdef CONFIG_SMP
/* second CPU gets only doorbell interrupts */
- if ((irq - mv64360_irq_base) == 28) {
- mv64x60_set_bits(&bh, MV64360_IC_CPU1_INTR_MASK_LO, (1 << 28));
+ if ((irq - mv64360_irq_base) == MV64x60_IRQ_DOORBELL) {
+ mv64x60_set_bits(&bh, MV64360_IC_CPU1_INTR_MASK_LO,
+ (1 << MV64x60_IRQ_DOORBELL));
return;
}
#endif
@@ -257,8 +259,9 @@ static void
mv64360_mask_irq(unsigned int irq)
{
#ifdef CONFIG_SMP
- if ((irq - mv64360_irq_base) == 28) {
- mv64x60_clr_bits(&bh, MV64360_IC_CPU1_INTR_MASK_LO, (1 << 28));
+ if ((irq - mv64360_irq_base) == MV64x60_IRQ_DOORBELL) {
+ mv64x60_clr_bits(&bh, MV64360_IC_CPU1_INTR_MASK_LO,
+ (1 << MV64x60_IRQ_DOORBELL));
return;
}
#endif
@@ -371,7 +374,7 @@ mv64360_register_hdlrs(void)
/* Clear old errors and register CPU interface error intr handler */
mv64x60_write(&bh, MV64x60_CPU_ERR_CAUSE, 0);
- if ((rc = request_irq(MV64x60_IRQ_CPU_ERR,
+ if ((rc = request_irq(MV64x60_IRQ_CPU_ERR + mv64360_irq_base,
mv64360_cpu_error_int_handler, SA_INTERRUPT, CPU_INTR_STR, 0)))
printk(KERN_WARNING "Can't register cpu error handler: %d", rc);
@@ -380,7 +383,7 @@ mv64360_register_hdlrs(void)
/* Clear old errors and register internal SRAM error intr handler */
mv64x60_write(&bh, MV64360_SRAM_ERR_CAUSE, 0);
- if ((rc = request_irq(MV64360_IRQ_SRAM_PAR_ERR,
+ if ((rc = request_irq(MV64360_IRQ_SRAM_PAR_ERR + mv64360_irq_base,
mv64360_sram_error_int_handler,SA_INTERRUPT,SRAM_INTR_STR, 0)))
printk(KERN_WARNING "Can't register SRAM error handler: %d",rc);
@@ -397,7 +400,8 @@ mv64360_register_hdlrs(void)
/* Clear old errors and register PCI 0 error intr handler */
mv64x60_write(&bh, MV64x60_PCI0_ERR_CAUSE, 0);
- if ((rc = request_irq(MV64360_IRQ_PCI0, mv64360_pci_error_int_handler,
+ if ((rc = request_irq(MV64360_IRQ_PCI0 + mv64360_irq_base,
+ mv64360_pci_error_int_handler,
SA_INTERRUPT, PCI0_INTR_STR, (void *)0)))
printk(KERN_WARNING "Can't register pci 0 error handler: %d",
rc);
@@ -407,7 +411,8 @@ mv64360_register_hdlrs(void)
/* Clear old errors and register PCI 1 error intr handler */
mv64x60_write(&bh, MV64x60_PCI1_ERR_CAUSE, 0);
- if ((rc = request_irq(MV64360_IRQ_PCI1, mv64360_pci_error_int_handler,
+ if ((rc = request_irq(MV64360_IRQ_PCI1 + mv64360_irq_base,
+ mv64360_pci_error_int_handler,
SA_INTERRUPT, PCI1_INTR_STR, (void *)1)))
printk(KERN_WARNING "Can't register pci 1 error handler: %d",
rc);
diff --git a/arch/ppc/syslib/mv64x60.c b/arch/ppc/syslib/mv64x60.c
index b06c8c762bb79..7b241e7876bda 100644
--- a/arch/ppc/syslib/mv64x60.c
+++ b/arch/ppc/syslib/mv64x60.c
@@ -314,15 +314,15 @@ static struct platform_device mpsc1_device = {
static struct resource mv64x60_eth_shared_resources[] = {
[0] = {
.name = "ethernet shared base",
- .start = MV64340_ETH_SHARED_REGS,
- .end = MV64340_ETH_SHARED_REGS +
- MV64340_ETH_SHARED_REGS_SIZE - 1,
+ .start = MV643XX_ETH_SHARED_REGS,
+ .end = MV643XX_ETH_SHARED_REGS +
+ MV643XX_ETH_SHARED_REGS_SIZE - 1,
.flags = IORESOURCE_MEM,
},
};
static struct platform_device mv64x60_eth_shared_device = {
- .name = MV64XXX_ETH_SHARED_NAME,
+ .name = MV643XX_ETH_SHARED_NAME,
.id = 0,
.num_resources = ARRAY_SIZE(mv64x60_eth_shared_resources),
.resource = mv64x60_eth_shared_resources,
@@ -338,10 +338,10 @@ static struct resource mv64x60_eth0_resources[] = {
},
};
-static struct mv64xxx_eth_platform_data eth0_pd;
+static struct mv643xx_eth_platform_data eth0_pd;
static struct platform_device eth0_device = {
- .name = MV64XXX_ETH_NAME,
+ .name = MV643XX_ETH_NAME,
.id = 0,
.num_resources = ARRAY_SIZE(mv64x60_eth0_resources),
.resource = mv64x60_eth0_resources,
@@ -361,10 +361,10 @@ static struct resource mv64x60_eth1_resources[] = {
},
};
-static struct mv64xxx_eth_platform_data eth1_pd;
+static struct mv643xx_eth_platform_data eth1_pd;
static struct platform_device eth1_device = {
- .name = MV64XXX_ETH_NAME,
+ .name = MV643XX_ETH_NAME,
.id = 1,
.num_resources = ARRAY_SIZE(mv64x60_eth1_resources),
.resource = mv64x60_eth1_resources,
@@ -384,10 +384,10 @@ static struct resource mv64x60_eth2_resources[] = {
},
};
-static struct mv64xxx_eth_platform_data eth2_pd;
+static struct mv643xx_eth_platform_data eth2_pd;
static struct platform_device eth2_device = {
- .name = MV64XXX_ETH_NAME,
+ .name = MV643XX_ETH_NAME,
.id = 2,
.num_resources = ARRAY_SIZE(mv64x60_eth2_resources),
.resource = mv64x60_eth2_resources,
diff --git a/arch/ppc/syslib/ppc4xx_pic.c b/arch/ppc/syslib/ppc4xx_pic.c
index 4ac2de28c28c9..08f06dd17e7ba 100644
--- a/arch/ppc/syslib/ppc4xx_pic.c
+++ b/arch/ppc/syslib/ppc4xx_pic.c
@@ -4,7 +4,7 @@
* Interrupt controller driver for PowerPC 4xx-based processors.
*
* Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
- * Copyright (c) 2004 Zultys Technologies
+ * Copyright (c) 2004, 2005 Zultys Technologies
*
* Based on original code by
* Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
@@ -29,8 +29,9 @@
/* See comment in include/arch-ppc/ppc4xx_pic.h
* for more info about these two variables
*/
-extern struct ppc4xx_uic_settings ppc4xx_core_uic_cfg[NR_UICS] __attribute__((weak));
-extern unsigned char ppc4xx_uic_ext_irq_cfg[] __attribute__((weak));
+extern struct ppc4xx_uic_settings ppc4xx_core_uic_cfg[NR_UICS]
+ __attribute__ ((weak));
+extern unsigned char ppc4xx_uic_ext_irq_cfg[] __attribute__ ((weak));
#define IRQ_MASK_UIC0(irq) (1 << (31 - (irq)))
#define IRQ_MASK_UICx(irq) (1 << (31 - ((irq) & 0x1f)))
@@ -48,6 +49,7 @@ static void ppc4xx_uic##n##_disable(unsigned int irq) \
{ \
ppc_cached_irq_mask[n] &= ~IRQ_MASK_UIC##n(irq); \
mtdcr(DCRN_UIC_ER(UIC##n), ppc_cached_irq_mask[n]); \
+ ACK_UIC##n##_PARENT \
} \
\
static void ppc4xx_uic##n##_ack(unsigned int irq) \
@@ -63,11 +65,11 @@ static void ppc4xx_uic##n##_end(unsigned int irq) \
{ \
unsigned int status = irq_desc[irq].status; \
u32 mask = IRQ_MASK_UIC##n(irq); \
- if (status & IRQ_LEVEL){ \
+ if (status & IRQ_LEVEL) { \
mtdcr(DCRN_UIC_SR(UIC##n), mask); \
ACK_UIC##n##_PARENT \
} \
- if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS))){ \
+ if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS))) { \
ppc_cached_irq_mask[n] |= mask; \
mtdcr(DCRN_UIC_ER(UIC##n), ppc_cached_irq_mask[n]); \
} \
@@ -86,7 +88,9 @@ static void ppc4xx_uic##n##_end(unsigned int irq) \
#define ACK_UIC0_PARENT mtdcr(DCRN_UIC_SR(UICB), UICB_UIC0NC);
#define ACK_UIC1_PARENT mtdcr(DCRN_UIC_SR(UICB), UICB_UIC1NC);
#define ACK_UIC2_PARENT mtdcr(DCRN_UIC_SR(UICB), UICB_UIC2NC);
-UIC_HANDLERS(0); UIC_HANDLERS(1); UIC_HANDLERS(2);
+UIC_HANDLERS(0);
+UIC_HANDLERS(1);
+UIC_HANDLERS(2);
static int ppc4xx_pic_get_irq(struct pt_regs *regs)
{
@@ -114,7 +118,8 @@ static void __init ppc4xx_pic_impl_init(void)
#elif NR_UICS == 2
#define ACK_UIC0_PARENT
#define ACK_UIC1_PARENT mtdcr(DCRN_UIC_SR(UIC0), UIC0_UIC1NC);
-UIC_HANDLERS(0); UIC_HANDLERS(1);
+UIC_HANDLERS(0);
+UIC_HANDLERS(1);
static int ppc4xx_pic_get_irq(struct pt_regs *regs)
{
@@ -143,18 +148,20 @@ static int ppc4xx_pic_get_irq(struct pt_regs *regs)
return uic0 ? 32 - ffs(uic0) : -1;
}
-static inline void ppc4xx_pic_impl_init(void){}
+static inline void ppc4xx_pic_impl_init(void)
+{
+}
#endif
static struct ppc4xx_uic_impl {
struct hw_interrupt_type decl;
- int base; /* Base DCR number */
+ int base; /* Base DCR number */
} __uic[] = {
- { .decl = DECLARE_UIC(0), .base = UIC0 },
+ { .decl = DECLARE_UIC(0), .base = UIC0 },
#if NR_UICS > 1
- { .decl = DECLARE_UIC(1), .base = UIC1 },
+ { .decl = DECLARE_UIC(1), .base = UIC1 },
#if NR_UICS > 2
- { .decl = DECLARE_UIC(2), .base = UIC2 },
+ { .decl = DECLARE_UIC(2), .base = UIC2 },
#endif
#endif
};
@@ -168,9 +175,9 @@ static inline int is_level_sensitive(int irq)
void __init ppc4xx_pic_init(void)
{
int i;
- unsigned char* eirqs = ppc4xx_uic_ext_irq_cfg;
+ unsigned char *eirqs = ppc4xx_uic_ext_irq_cfg;
- for (i = 0; i < NR_UICS; ++i){
+ for (i = 0; i < NR_UICS; ++i) {
int base = __uic[i].base;
/* Disable everything by default */
@@ -181,23 +188,23 @@ void __init ppc4xx_pic_init(void)
mtdcr(DCRN_UIC_CR(base), 0);
/* Configure polarity and triggering */
- if (ppc4xx_core_uic_cfg){
- struct ppc4xx_uic_settings* p = ppc4xx_core_uic_cfg + i;
+ if (ppc4xx_core_uic_cfg) {
+ struct ppc4xx_uic_settings *p = ppc4xx_core_uic_cfg + i;
u32 mask = p->ext_irq_mask;
u32 pr = mfdcr(DCRN_UIC_PR(base)) & mask;
u32 tr = mfdcr(DCRN_UIC_TR(base)) & mask;
/* "Fixed" interrupts (on-chip devices) */
- pr |= p->polarity & ~mask;
+ pr |= p->polarity & ~mask;
tr |= p->triggering & ~mask;
/* Merge external IRQs settings if board port
* provided them
*/
- if (eirqs && mask){
+ if (eirqs && mask) {
pr &= ~mask;
tr &= ~mask;
- while (mask){
+ while (mask) {
/* Extract current external IRQ mask */
u32 eirq_mask = 1 << __ilog2(mask);
@@ -227,8 +234,8 @@ void __init ppc4xx_pic_init(void)
ppc4xx_pic_impl_init();
/* Attach low-level handlers */
- for (i = 0; i < (NR_UICS << 5); ++i){
- irq_desc[i].handler = &__uic[i >> 5].decl;
+ for (i = 0; i < (NR_UICS << 5); ++i) {
+ irq_desc[i].handler = &__uic[i >> 5].decl;
if (is_level_sensitive(i))
irq_desc[i].status |= IRQ_LEVEL;
}
diff --git a/arch/ppc/syslib/ppc4xx_serial.c b/arch/ppc/syslib/ppc4xx_serial.c
deleted file mode 100644
index 998d033f7ac5f..0000000000000
--- a/arch/ppc/syslib/ppc4xx_serial.c
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * arch/ppc/syslib/ppc405_serial.c
- *
- * Author: MontaVista Software, Inc.
- * frank_rowand@mvista.com or source@mvista.com
- * debbie_chu@mvista.com
- *
- * This is a fairly standard 165xx type device that will eventually
- * be merged with other similar processor/boards. -- Dan
- *
- * 2000 (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.
- *
- * Console I/O support for Early kernel bringup.
- */
-
-#include <linux/config.h>
-
-#if defined(CONFIG_IBM405GP) || defined(CONFIG_IBM405CR)
-
-#ifdef CONFIG_KGDB
-#include <asm/kgdb.h>
-#include <linux/init.h>
-#endif
-
-#ifdef CONFIG_DEBUG_BRINGUP
-
-#include <linux/console.h>
-
-extern void ftr_reset_preferred_console(void);
-
-
-static int ppc405_sercons_setup(struct console *co, char *options)
-{
-#ifdef CONFIG_UART0_DEBUG_CONSOLE
- volatile unsigned char *uart_dll = (char *)0xef600300;
- volatile unsigned char *uart_fcr = (char *)0xef600302;
- volatile unsigned char *uart_lcr = (char *)0xef600303;
-#endif
-
-#ifdef CONFIG_UART1_DEBUG_CONSOLE
- volatile unsigned char *uart_dll = (char *)0xef600400;
- volatile unsigned char *uart_fcr = (char *)0xef600402;
- volatile unsigned char *uart_lcr = (char *)0xef600403;
-#endif
-
- *uart_lcr = *uart_lcr | 0x80; /* DLAB on */
-
-/* ftr revisit - there is no config option for this
-** also see include/asm-ppc/ppc405_serial.h
-**
-** #define CONFIG_IBM405GP_INTERNAL_CLOCK
-*/
-
-
-#ifdef CONFIG_IBM405GP_INTERNAL_CLOCK
- /* ftr revisit
- ** why is bit 19 of chcr0 (0x1000) being set?
- */
- /* 0x2a results in data corruption, kgdb works with 0x28 */
- *uart_dll = 0x28; /* 9600 baud */
- _put_CHCR0((_get_CHCR0() & 0xffffe000) | 0x103e);
-#else
- *uart_dll = 0x48; /* 9600 baud */
-#endif
- *uart_lcr = *uart_lcr & 0x7f; /* DLAB off */
-
- return 0;
-}
-
-
-/*
- * This is a bringup hack, writing directly to uart0 or uart1
- */
-
-static void
-ppc405_sercons_write(struct console *co, const char *ptr,
- unsigned nb)
-{
- int i;
-
-#ifdef CONFIG_UART0_DEBUG_CONSOLE
- volatile unsigned char *uart_xmit = (char *)0xef600300;
- volatile unsigned char *uart_lsr = (char *)0xef600305;
-#endif
-
-#ifdef CONFIG_UART1_DEBUG_CONSOLE
- volatile unsigned char *uart_xmit = (char *)0xef600400;
- volatile unsigned char *uart_lsr = (char *)0xef600405;
-#endif
-
- for (i = 0; i < nb; ++i) {
-
- /* wait for transmit reg (possibly fifo) to empty */
- while ((*uart_lsr & 0x40) == 0)
- ;
-
- *uart_xmit = (ptr[i] & 0xff);
-
- if (ptr[i] == '\n') {
-
- /* add a carriage return */
-
- /* wait for transmit reg (possibly fifo) to empty */
- while ((*uart_lsr & 0x40) == 0)
- ;
-
- *uart_xmit = '\r';
- }
- }
-
- return;
-}
-
-
-static int
-ppc405_sercons_read(struct console *co, char *ptr, unsigned nb)
-{
-#ifdef CONFIG_UART0_DEBUG_CONSOLE
- volatile unsigned char *uart_rcv = (char *)0xef600300;
- volatile unsigned char *uart_lsr = (char *)0xef600305;
-#endif
-
-#ifdef CONFIG_UART1_DEBUG_CONSOLE
- volatile unsigned char *uart_rcv = (char *)0xef600400;
- volatile unsigned char *uart_lsr = (char *)0xef600405;
-#endif
-
-
- /* ftr revisit: not tested */
-
- if (nb == 0)
- return(0);
-
- if (!ptr)
- return(-1);
-
- /* wait for receive reg (possibly fifo) to contain data */
- while ((*uart_lsr & 0x01) == 0)
- ;
-
- *ptr = *uart_rcv;
-
- return(1);
-}
-
-static struct console ppc405_sercons = {
- .name = "dbg_cons",
- .write = ppc405_console_write,
- .setup = ppc405_console_setup,
- .flags = CON_PRINTBUFFER,
- .index = -1,
-};
-
-void
-register_debug_console(void)
-{
- register_console(&ppc405_sercons);
-}
-
-void
-unregister_debug_console(void)
-{
- unregister_console(&ppc405_sercons);
-}
-
-#endif /* CONFIG_DEBUG_BRINGUP */
-
-#endif /* #if defined(CONFIG_IBM405GP) || defined(CONFIG_IBM405CR) */
diff --git a/arch/ppc/syslib/ppc83xx_setup.c b/arch/ppc/syslib/ppc83xx_setup.c
new file mode 100644
index 0000000000000..c28f9d679484f
--- /dev/null
+++ b/arch/ppc/syslib/ppc83xx_setup.c
@@ -0,0 +1,138 @@
+/*
+ * arch/ppc/syslib/ppc83xx_setup.c
+ *
+ * MPC83XX common board code
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2005 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/serial.h>
+#include <linux/tty.h> /* for linux/serial_core.h */
+#include <linux/serial_core.h>
+#include <linux/serial_8250.h>
+
+#include <asm/prom.h>
+#include <asm/time.h>
+#include <asm/mpc83xx.h>
+#include <asm/mmu.h>
+#include <asm/ppc_sys.h>
+#include <asm/kgdb.h>
+
+#include <syslib/ppc83xx_setup.h>
+
+phys_addr_t immrbar;
+
+/* Return the amount of memory */
+unsigned long __init
+mpc83xx_find_end_of_memory(void)
+{
+ bd_t *binfo;
+
+ binfo = (bd_t *) __res;
+
+ return binfo->bi_memsize;
+}
+
+long __init
+mpc83xx_time_init(void)
+{
+#define SPCR_OFFS 0x00000110
+#define SPCR_TBEN 0x00400000
+
+ bd_t *binfo = (bd_t *)__res;
+ u32 *spcr = ioremap(binfo->bi_immr_base + SPCR_OFFS, 4);
+
+ *spcr |= SPCR_TBEN;
+
+ iounmap(spcr);
+
+ return 0;
+}
+
+/* The decrementer counts at the system (internal) clock freq divided by 4 */
+void __init
+mpc83xx_calibrate_decr(void)
+{
+ bd_t *binfo = (bd_t *) __res;
+ unsigned int freq, divisor;
+
+ freq = binfo->bi_busfreq;
+ divisor = 4;
+ tb_ticks_per_jiffy = freq / HZ / divisor;
+ tb_to_us = mulhwu_scale_factor(freq / divisor, 1000000);
+}
+
+#ifdef CONFIG_SERIAL_8250
+void __init
+mpc83xx_early_serial_map(void)
+{
+#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+ struct uart_port serial_req;
+#endif
+ struct plat_serial8250_port *pdata;
+ bd_t *binfo = (bd_t *) __res;
+ pdata = (struct plat_serial8250_port *) ppc_sys_get_pdata(MPC83xx_DUART);
+
+ /* Setup serial port access */
+ pdata[0].uartclk = binfo->bi_busfreq;
+ pdata[0].mapbase += binfo->bi_immr_base;
+ pdata[0].membase = ioremap(pdata[0].mapbase, 0x100);
+
+#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+ memset(&serial_req, 0, sizeof (serial_req));
+ serial_req.iotype = SERIAL_IO_MEM;
+ serial_req.mapbase = pdata[0].mapbase;
+ serial_req.membase = pdata[0].membase;
+ serial_req.regshift = 0;
+
+ gen550_init(0, &serial_req);
+#endif
+
+ pdata[1].uartclk = binfo->bi_busfreq;
+ pdata[1].mapbase += binfo->bi_immr_base;
+ pdata[1].membase = ioremap(pdata[1].mapbase, 0x100);
+
+#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+ /* Assume gen550_init() doesn't modify serial_req */
+ serial_req.mapbase = pdata[1].mapbase;
+ serial_req.membase = pdata[1].membase;
+
+ gen550_init(1, &serial_req);
+#endif
+}
+#endif
+
+void
+mpc83xx_restart(char *cmd)
+{
+ local_irq_disable();
+ for(;;);
+}
+
+void
+mpc83xx_power_off(void)
+{
+ local_irq_disable();
+ for(;;);
+}
+
+void
+mpc83xx_halt(void)
+{
+ local_irq_disable();
+ for(;;);
+}
+
+/* PCI SUPPORT DOES NOT EXIT, MODEL after ppc85xx_setup.c */
diff --git a/arch/ppc/syslib/ppc83xx_setup.h b/arch/ppc/syslib/ppc83xx_setup.h
new file mode 100644
index 0000000000000..683f179b746ca
--- /dev/null
+++ b/arch/ppc/syslib/ppc83xx_setup.h
@@ -0,0 +1,53 @@
+/*
+ * arch/ppc/syslib/ppc83xx_setup.h
+ *
+ * MPC83XX common board definitions
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2005 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+#ifndef __PPC_SYSLIB_PPC83XX_SETUP_H
+#define __PPC_SYSLIB_PPC83XX_SETUP_H
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <asm/ppcboot.h>
+
+extern unsigned long mpc83xx_find_end_of_memory(void) __init;
+extern long mpc83xx_time_init(void) __init;
+extern void mpc83xx_calibrate_decr(void) __init;
+extern void mpc83xx_early_serial_map(void) __init;
+extern void mpc83xx_restart(char *cmd);
+extern void mpc83xx_power_off(void);
+extern void mpc83xx_halt(void);
+extern void mpc83xx_setup_hose(void) __init;
+
+/* PCI config */
+#if 0
+#define PCI1_CFG_ADDR_OFFSET (FIXME)
+#define PCI1_CFG_DATA_OFFSET (FIXME)
+
+#define PCI2_CFG_ADDR_OFFSET (FIXME)
+#define PCI2_CFG_DATA_OFFSET (FIXME)
+#endif
+
+/* Serial Config */
+#ifdef CONFIG_SERIAL_MANY_PORTS
+#define RS_TABLE_SIZE 64
+#else
+#define RS_TABLE_SIZE 2
+#endif
+
+#ifndef BASE_BAUD
+#define BASE_BAUD 115200
+#endif
+
+#endif /* __PPC_SYSLIB_PPC83XX_SETUP_H */
diff --git a/arch/ppc/syslib/todc_time.c b/arch/ppc/syslib/todc_time.c
index 0165e18341141..1323c641c19d6 100644
--- a/arch/ppc/syslib/todc_time.c
+++ b/arch/ppc/syslib/todc_time.c
@@ -287,6 +287,7 @@ todc_get_rtc_time(void)
limit = 1;
switch (todc_info->rtc_type) {
+ case TODC_TYPE_DS1553:
case TODC_TYPE_DS1557:
case TODC_TYPE_DS1743:
case TODC_TYPE_DS1746: /* XXXX BAD HACK -> FIX */
@@ -322,6 +323,7 @@ todc_get_rtc_time(void)
if (todc_info->rtc_type != TODC_TYPE_MC146818) {
switch (todc_info->rtc_type) {
+ case TODC_TYPE_DS1553:
case TODC_TYPE_DS1557:
case TODC_TYPE_DS1743:
case TODC_TYPE_DS1746: /* XXXX BAD HACK -> FIX */
@@ -418,6 +420,7 @@ static unsigned char __init todc_read_timereg(int addr)
unsigned char save_control = 0, val;
switch (todc_info->rtc_type) {
+ case TODC_TYPE_DS1553:
case TODC_TYPE_DS1557:
case TODC_TYPE_DS1746: /* XXXX BAD HACK -> FIX */
case TODC_TYPE_DS1747:
@@ -432,6 +435,7 @@ static unsigned char __init todc_read_timereg(int addr)
val = todc_read_val(addr);
switch (todc_info->rtc_type) {
+ case TODC_TYPE_DS1553:
case TODC_TYPE_DS1557:
case TODC_TYPE_DS1746: /* XXXX BAD HACK -> FIX */
case TODC_TYPE_DS1747:
diff --git a/arch/ppc/syslib/xilinx_pic.c b/arch/ppc/syslib/xilinx_pic.c
index 483d06d9a9bb5..e0bd66f0847a5 100644
--- a/arch/ppc/syslib/xilinx_pic.c
+++ b/arch/ppc/syslib/xilinx_pic.c
@@ -114,6 +114,14 @@ ppc4xx_pic_init(void)
{
int i;
+ /*
+ * NOTE: The assumption here is that NR_IRQS is 32 or less
+ * (NR_IRQS is 32 for PowerPC 405 cores by default).
+ */
+#if (NR_IRQS > 32)
+#error NR_IRQS > 32 not supported
+#endif
+
#if XPAR_XINTC_USE_DCR == 0
intc = ioremap(XPAR_INTC_0_BASEADDR, 32);
@@ -138,6 +146,12 @@ ppc4xx_pic_init(void)
ppc_md.get_irq = xilinx_pic_get_irq;
- for (i = 0; i < NR_IRQS; ++i)
+ for (i = 0; i < NR_IRQS; ++i) {
irq_desc[i].handler = &xilinx_intc;
+
+ if (XPAR_INTC_0_KIND_OF_INTR & (0x00000001 << i))
+ irq_desc[i].status &= ~IRQ_LEVEL;
+ else
+ irq_desc[i].status |= IRQ_LEVEL;
+ }
}
diff --git a/arch/ppc64/Kconfig b/arch/ppc64/Kconfig
index a7933ab62e986..15c4a1455caee 100644
--- a/arch/ppc64/Kconfig
+++ b/arch/ppc64/Kconfig
@@ -81,7 +81,6 @@ config PPC_PMAC
depends on PPC_MULTIPLATFORM
bool " Apple G5 based machines"
default y
- select ADB_PMU
select U3_DART
config PPC_MAPLE
@@ -194,7 +193,10 @@ config NR_CPUS
config HMT
bool "Hardware multithreading"
- depends on SMP && PPC_PSERIES
+ depends on SMP && PPC_PSERIES && BROKEN
+ help
+ This option enables hardware multithreading on RS64 cpus.
+ pSeries systems p620 and p660 have such a cpu type.
config DISCONTIGMEM
bool "Discontiguous Memory Support"
@@ -253,16 +255,21 @@ config MSCHUNKS
config PPC_RTAS
- bool "Proc interface to RTAS"
+ bool
depends on PPC_PSERIES
+ default y
+
+config RTAS_PROC
+ bool "Proc interface to RTAS"
+ depends on PPC_RTAS
config RTAS_FLASH
tristate "Firmware flash interface"
- depends on PPC_RTAS
+ depends on RTAS_PROC
config SCANLOG
tristate "Scanlog dump interface"
- depends on PPC_RTAS
+ depends on RTAS_PROC && PPC_PSERIES
config LPARCFG
tristate "LPAR Configuration Data"
@@ -271,6 +278,23 @@ config LPARCFG
Provide system capacity information via human readable
<key word>=<value> pairs through a /proc/ppc64/lparcfg interface.
+config SECCOMP
+ bool "Enable seccomp to safely compute untrusted bytecode"
+ depends on PROC_FS
+ default y
+ help
+ This kernel feature is useful for number crunching applications
+ that may need to compute untrusted bytecode during their
+ execution. By using pipes or other transports made available to
+ the process as file descriptors supporting the read/write
+ syscalls, it's possible to isolate those applications in
+ their own address space using seccomp. Once seccomp is
+ enabled via /proc/<pid>/seccomp, it cannot be disabled
+ and the task is only allowed to execute a few safe syscalls
+ defined by each seccomp mode.
+
+ If unsure, say Y. Only embedded should say N here.
+
endmenu
@@ -313,7 +337,7 @@ source "drivers/pci/Kconfig"
config HOTPLUG_CPU
bool "Support for hot-pluggable CPUs"
- depends on SMP && EXPERIMENTAL && PPC_PSERIES
+ depends on SMP && EXPERIMENTAL && (PPC_PSERIES || PPC_PMAC)
select HOTPLUG
---help---
Say Y here to be able to turn CPUs off and on.
diff --git a/arch/ppc64/Makefile b/arch/ppc64/Makefile
index e8f9cd714c4c7..d33e20bcc52f6 100644
--- a/arch/ppc64/Makefile
+++ b/arch/ppc64/Makefile
@@ -15,17 +15,38 @@
KERNELLOAD := 0xc000000000000000
+# Set default 32 bits cross compilers for vdso and boot wrapper
+CROSS32_COMPILE ?=
+
+CROSS32CC := $(CROSS32_COMPILE)gcc
+CROSS32AS := $(CROSS32_COMPILE)as
+CROSS32LD := $(CROSS32_COMPILE)ld
+CROSS32OBJCOPY := $(CROSS32_COMPILE)objcopy
+
+# If we have a biarch compiler, use it for 32 bits cross compile if
+# CROSS32_COMPILE wasn't explicitely defined, and add proper explicit
+# target type to target compilers
+
HAS_BIARCH := $(call cc-option-yn, -m64)
ifeq ($(HAS_BIARCH),y)
+ifeq ($(CROSS32_COMPILE),)
+CROSS32CC := $(CC) -m32
+CROSS32AS := $(AS) -a32
+CROSS32LD := $(LD) -m elf32ppc
+CROSS32OBJCOPY := $(OBJCOPY)
+endif
AS := $(AS) -a64
LD := $(LD) -m elf64ppc
CC := $(CC) -m64
endif
+export CROSS32CC CROSS32AS CROSS32LD CROSS32OBJCOPY
+
new_nm := $(shell if $(NM) --help 2>&1 | grep -- '--synthetic' > /dev/null; then echo y; else echo n; fi)
ifeq ($(new_nm),y)
NM := $(NM) --synthetic
+
endif
CHECKFLAGS += -m64 -D__powerpc__
@@ -65,14 +86,20 @@ boottarget-$(CONFIG_PPC_ISERIES) := vmlinux.sminitrd vmlinux.initrd vmlinux.sm
$(boottarget-y): vmlinux
$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
-bootimage-$(CONFIG_PPC_PSERIES) := zImage
-bootimage-$(CONFIG_PPC_MAPLE) := zImage
+bootimage-$(CONFIG_PPC_PSERIES) := $(boot)/zImage
+bootimage-$(CONFIG_PPC_PMAC) := vmlinux
+bootimage-$(CONFIG_PPC_MAPLE) := $(boot)/zImage
bootimage-$(CONFIG_PPC_ISERIES) := vmlinux
BOOTIMAGE := $(bootimage-y)
install: vmlinux
$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) $@
-all: $(BOOTIMAGE)
+defaultimage-$(CONFIG_PPC_PSERIES) := zImage
+defaultimage-$(CONFIG_PPC_PMAC) := vmlinux
+defaultimage-$(CONFIG_PPC_MAPLE) := zImage
+defaultimage-$(CONFIG_PPC_ISERIES) := vmlinux
+KBUILD_IMAGE := $(defaultimage-y)
+all: $(KBUILD_IMAGE)
archclean:
$(Q)$(MAKE) $(clean)=$(boot)
diff --git a/arch/ppc64/boot/Makefile b/arch/ppc64/boot/Makefile
index 9963fedcc192e..d3e1d6af92036 100644
--- a/arch/ppc64/boot/Makefile
+++ b/arch/ppc64/boot/Makefile
@@ -20,17 +20,11 @@
# CROSS32_COMPILE is setup as a prefix just like CROSS_COMPILE
# in the toplevel makefile.
-CROSS32_COMPILE ?=
-#CROSS32_COMPILE = /usr/local/ppc/bin/powerpc-linux-
-BOOTCC := $(CROSS32_COMPILE)gcc
HOSTCC := gcc
BOOTCFLAGS := $(HOSTCFLAGS) $(LINUXINCLUDE) -fno-builtin
-BOOTAS := $(CROSS32_COMPILE)as
BOOTAFLAGS := -D__ASSEMBLY__ $(BOOTCFLAGS) -traditional
-BOOTLD := $(CROSS32_COMPILE)ld
BOOTLFLAGS := -Ttext 0x00400000 -e _start -T $(srctree)/$(src)/zImage.lds
-BOOTOBJCOPY := $(CROSS32_COMPILE)objcopy
OBJCOPYFLAGS := contents,alloc,load,readonly,data
src-boot := crt0.S string.S prom.c main.c zlib.c imagesize.c div64.S
@@ -38,10 +32,10 @@ src-boot := $(addprefix $(obj)/, $(src-boot))
obj-boot := $(addsuffix .o, $(basename $(src-boot)))
quiet_cmd_bootcc = BOOTCC $@
- cmd_bootcc = $(BOOTCC) -Wp,-MD,$(depfile) $(BOOTCFLAGS) -c -o $@ $<
+ cmd_bootcc = $(CROSS32CC) -Wp,-MD,$(depfile) $(BOOTCFLAGS) -c -o $@ $<
quiet_cmd_bootas = BOOTAS $@
- cmd_bootas = $(BOOTCC) -Wp,-MD,$(depfile) $(BOOTAFLAGS) -c -o $@ $<
+ cmd_bootas = $(CROSS32CC) -Wp,-MD,$(depfile) $(BOOTAFLAGS) -c -o $@ $<
$(patsubst %.c,%.o, $(filter %.c, $(src-boot))): %.o: %.c
$(call if_changed_dep,bootcc)
@@ -77,15 +71,15 @@ vmlinux.strip: vmlinux FORCE
$(obj)/vmlinux.initrd: vmlinux.strip $(obj)/addRamDisk $(obj)/ramdisk.image.gz FORCE
$(call if_changed,ramdisk)
-addsection = $(BOOTOBJCOPY) $(1) \
+addsection = $(CROSS32OBJCOPY) $(1) \
--add-section=.kernel:$(strip $(patsubst $(obj)/kernel-%.o,%, $(1)))=$(patsubst %.o,%.gz, $(1)) \
--set-section-flags=.kernel:$(strip $(patsubst $(obj)/kernel-%.o,%, $(1)))=$(OBJCOPYFLAGS)
quiet_cmd_addnote = ADDNOTE $@
- cmd_addnote = $(BOOTLD) $(BOOTLFLAGS) -o $@ $(obj-boot) && $(obj)/addnote $@
+ cmd_addnote = $(CROSS32LD) $(BOOTLFLAGS) -o $@ $(obj-boot) && $(obj)/addnote $@
quiet_cmd_piggy = PIGGY $@
- cmd_piggy = $(obj)/piggyback $(@:.o=) < $< | $(BOOTAS) -o $@
+ cmd_piggy = $(obj)/piggyback $(@:.o=) < $< | $(CROSS32AS) -o $@
$(call gz-sec, $(required)): $(obj)/kernel-%.gz: % FORCE
$(call if_changed,gzip)
@@ -117,7 +111,7 @@ $(obj)/imagesize.c: vmlinux.strip
awk '{printf "unsigned long vmlinux_memsize = 0x%s;\n", substr($$1,8)}' \
>> $(obj)/imagesize.c
-install: $(CONFIGURE) $(obj)/$(BOOTIMAGE)
- sh -x $(srctree)/$(src)/install.sh "$(KERNELRELEASE)" "$(obj)/$(BOOTIMAGE)" "$(INSTALL_PATH)"
+install: $(CONFIGURE) $(BOOTIMAGE)
+ sh -x $(srctree)/$(src)/install.sh "$(KERNELRELEASE)" vmlinux System.map "$(INSTALL_PATH)" "$(BOOTIMAGE)"
clean-files := $(addprefix $(objtree)/, $(obj-boot) vmlinux.strip)
diff --git a/arch/ppc64/boot/install.sh b/arch/ppc64/boot/install.sh
index edc4f50b68970..955c5681db6c0 100644
--- a/arch/ppc64/boot/install.sh
+++ b/arch/ppc64/boot/install.sh
@@ -17,6 +17,7 @@
# $2 - kernel image file
# $3 - kernel map file
# $4 - default install path (blank if root directory)
+# $5 - kernel boot file, the zImage
#
# User may have a custom install script
@@ -27,7 +28,7 @@ if [ -x /sbin/installkernel ]; then exec /sbin/installkernel "$@"; fi
# Default install
# this should work for both the pSeries zImage and the iSeries vmlinux.sm
-image_name=`basename $2`
+image_name=`basename $5`
if [ -f $4/$image_name ]; then
mv $4/$image_name $4/$image_name.old
diff --git a/arch/ppc64/boot/main.c b/arch/ppc64/boot/main.c
index 4ce7f85bb2be6..b0fa86ad8b1be 100644
--- a/arch/ppc64/boot/main.c
+++ b/arch/ppc64/boot/main.c
@@ -112,7 +112,7 @@ void start(unsigned long a1, unsigned long a2, void *promptr)
if (getprop(chosen_handle, "stdin", &stdin, sizeof(stdin)) != 4)
exit();
- printf("zImage starting: loaded at 0x%x\n\r", (unsigned)_start);
+ printf("\n\rzImage starting: loaded at 0x%x\n\r", (unsigned)_start);
/*
* Now we try to claim some memory for the kernel itself
@@ -151,7 +151,7 @@ void start(unsigned long a1, unsigned long a2, void *promptr)
printf("initial ramdisk moving 0x%lx <- 0x%lx (%lx bytes)\n\r",
initrd.addr, (unsigned long)_initrd_start, initrd.size);
memmove((void *)initrd.addr, (void *)_initrd_start, initrd.size);
- printf("initrd head: 0x%lx\n", *((u32 *)initrd.addr));
+ printf("initrd head: 0x%lx\n\r", *((u32 *)initrd.addr));
}
/* Eventually gunzip the kernel */
@@ -200,7 +200,7 @@ void start(unsigned long a1, unsigned long a2, void *promptr)
vmlinux.addr += (unsigned long)elf64ph->p_offset;
vmlinux.size -= (unsigned long)elf64ph->p_offset;
- flush_cache((void *)vmlinux.addr, vmlinux.memsize);
+ flush_cache((void *)vmlinux.addr, vmlinux.size);
if (a1)
printf("initrd head: 0x%lx\n\r", *((u32 *)initrd.addr));
diff --git a/arch/ppc64/boot/no_initrd.c b/arch/ppc64/boot/no_initrd.c
deleted file mode 100644
index ed5dcdb1f4695..0000000000000
--- a/arch/ppc64/boot/no_initrd.c
+++ /dev/null
@@ -1,2 +0,0 @@
-char initrd_data[1];
-int initrd_len = 0;
diff --git a/arch/ppc64/boot/zImage.lds b/arch/ppc64/boot/zImage.lds
index 941ade38f08fb..8fe5e7071f542 100644
--- a/arch/ppc64/boot/zImage.lds
+++ b/arch/ppc64/boot/zImage.lds
@@ -1,4 +1,4 @@
-OUTPUT_ARCH(powerpc)
+OUTPUT_ARCH(powerpc:common)
SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib);
/* Do we need any of these for elf?
__DYNAMIC = 0; */
diff --git a/arch/ppc64/configs/g5_defconfig b/arch/ppc64/configs/g5_defconfig
index 39c0eb00ddd31..0f90df0b3f9c3 100644
--- a/arch/ppc64/configs/g5_defconfig
+++ b/arch/ppc64/configs/g5_defconfig
@@ -1,11 +1,12 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.9-rc3
-# Thu Oct 7 15:18:38 2004
+# Linux kernel version: 2.6.11
+# Thu Mar 10 16:47:04 2005
#
CONFIG_64BIT=y
CONFIG_MMU=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_GENERIC_ISA_DMA=y
CONFIG_HAVE_DEC_LOCK=y
CONFIG_EARLY_PRINTK=y
@@ -18,6 +19,7 @@ CONFIG_FORCE_MAX_ZONEORDER=13
#
CONFIG_EXPERIMENTAL=y
CONFIG_CLEAN_COMPILE=y
+CONFIG_LOCK_KERNEL=y
#
# General setup
@@ -25,36 +27,41 @@ CONFIG_CLEAN_COMPILE=y
CONFIG_LOCALVERSION=""
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
-# CONFIG_POSIX_MQUEUE is not set
+CONFIG_POSIX_MQUEUE=y
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
CONFIG_LOG_BUF_SHIFT=17
CONFIG_HOTPLUG=y
-# CONFIG_IKCONFIG is not set
+CONFIG_KOBJECT_UEVENT=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
# CONFIG_EMBEDDED is not set
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
#
# Loadable module support
#
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
-CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
CONFIG_OBSOLETE_MODPARM=y
-# CONFIG_MODVERSIONS is not set
-# CONFIG_KMOD is not set
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_KMOD=y
CONFIG_STOP_MACHINE=y
CONFIG_SYSVIPC_COMPAT=y
@@ -65,6 +72,7 @@ CONFIG_SYSVIPC_COMPAT=y
CONFIG_PPC_MULTIPLATFORM=y
# CONFIG_PPC_PSERIES is not set
CONFIG_PPC_PMAC=y
+# CONFIG_PPC_MAPLE is not set
CONFIG_PPC=y
CONFIG_PPC64=y
CONFIG_PPC_OF=y
@@ -75,12 +83,10 @@ CONFIG_BOOTX_TEXT=y
CONFIG_POWER4_ONLY=y
CONFIG_IOMMU_VMERGE=y
CONFIG_SMP=y
-CONFIG_IRQ_ALL_CPUS=y
CONFIG_NR_CPUS=2
# CONFIG_SCHED_SMT is not set
# CONFIG_PREEMPT is not set
-# CONFIG_PPC_RTAS is not set
-# CONFIG_LPARCFG is not set
+CONFIG_GENERIC_HARDIRQS=y
#
# General setup
@@ -94,9 +100,13 @@ CONFIG_PCI_NAMES=y
# CONFIG_HOTPLUG_CPU is not set
#
-# PCMCIA/CardBus support
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
#
-# CONFIG_PCMCIA is not set
#
# PCI Hotplug Support
@@ -139,14 +149,29 @@ CONFIG_FW_LOADER=y
# CONFIG_BLK_CPQ_CISS_DA is not set
# CONFIG_BLK_DEV_DAC960 is not set
# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
CONFIG_BLK_DEV_NBD=m
# CONFIG_BLK_DEV_SX8 is not set
# CONFIG_BLK_DEV_UB is not set
CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=65536
CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
#
# ATA/ATAPI/MFM/RLL support
@@ -161,11 +186,10 @@ 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=y
-CONFIG_BLK_DEV_IDEFLOPPY=y
+# 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
-# CONFIG_IDE_TASKFILE_IO is not set
#
# IDE chipset support/bugfixes
@@ -205,7 +229,6 @@ 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 is not set
-CONFIG_BLK_DEV_IDEDMA_PMAC_AUTO=y
# CONFIG_IDE_ARM is not set
CONFIG_BLK_DEV_IDEDMA=y
# CONFIG_IDEDMA_IVB is not set
@@ -240,6 +263,7 @@ CONFIG_SCSI_CONSTANTS=y
#
CONFIG_SCSI_SPI_ATTRS=y
# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
#
# SCSI low-level drivers
@@ -254,13 +278,16 @@ CONFIG_SCSI_SPI_ATTRS=y
# CONFIG_MEGARAID_NEWGEN is not set
# CONFIG_MEGARAID_LEGACY is not set
CONFIG_SCSI_SATA=y
+# CONFIG_SCSI_SATA_AHCI is not set
CONFIG_SCSI_SATA_SVW=y
# CONFIG_SCSI_ATA_PIIX is not set
# CONFIG_SCSI_SATA_NV is not set
# CONFIG_SCSI_SATA_PROMISE is not set
+# CONFIG_SCSI_SATA_QSTOR is not set
# CONFIG_SCSI_SATA_SX4 is not set
# CONFIG_SCSI_SATA_SIL is not set
# CONFIG_SCSI_SATA_SIS is not set
+# CONFIG_SCSI_SATA_ULI is not set
# CONFIG_SCSI_SATA_VIA is not set
# CONFIG_SCSI_SATA_VITESSE is not set
# CONFIG_SCSI_BUSLOGIC is not set
@@ -270,12 +297,9 @@ CONFIG_SCSI_SATA_SVW=y
# 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_SYM53C8XX_2 is not set
# CONFIG_SCSI_IPR is not set
# CONFIG_SCSI_QLOGIC_ISP is not set
# CONFIG_SCSI_QLOGIC_FC is not set
@@ -286,11 +310,9 @@ CONFIG_SCSI_QLA2XXX=y
# CONFIG_SCSI_QLA2300 is not set
# CONFIG_SCSI_QLA2322 is not set
# CONFIG_SCSI_QLA6312 is not set
-# CONFIG_SCSI_QLA6322 is not set
# CONFIG_SCSI_DC395x is not set
# CONFIG_SCSI_DC390T is not set
# CONFIG_SCSI_DEBUG is not set
-# CONFIG_SCSI_MAC53C94 is not set
#
# Multi-device support (RAID and LVM)
@@ -300,15 +322,16 @@ CONFIG_BLK_DEV_MD=y
CONFIG_MD_LINEAR=y
CONFIG_MD_RAID0=y
CONFIG_MD_RAID1=y
-# CONFIG_MD_RAID10 is not set
+CONFIG_MD_RAID10=m
CONFIG_MD_RAID5=y
-# CONFIG_MD_RAID6 is not set
-# CONFIG_MD_MULTIPATH is not set
+CONFIG_MD_RAID6=m
+CONFIG_MD_MULTIPATH=m
+CONFIG_MD_FAULTY=m
CONFIG_BLK_DEV_DM=y
-# CONFIG_DM_CRYPT is not set
-# CONFIG_DM_SNAPSHOT is not set
-# CONFIG_DM_MIRROR is not set
-# CONFIG_DM_ZERO is not set
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
#
# Fusion MPT device support
@@ -355,6 +378,7 @@ CONFIG_IEEE1394_RAWIO=y
#
CONFIG_ADB=y
CONFIG_ADB_PMU=y
+CONFIG_PMAC_SMU=y
# CONFIG_PMAC_PBOOK is not set
# CONFIG_PMAC_BACKLIGHT is not set
# CONFIG_INPUT_ADBHID is not set
@@ -386,6 +410,8 @@ CONFIG_INET_AH=m
CONFIG_INET_ESP=m
CONFIG_INET_IPCOMP=m
CONFIG_INET_TUNNEL=y
+CONFIG_IP_TCPDIAG=m
+# CONFIG_IP_TCPDIAG_IPV6 is not set
#
# IP: Virtual Server Configuration
@@ -398,61 +424,71 @@ CONFIG_NETFILTER=y
#
# IP: Netfilter Configuration
#
-CONFIG_IP_NF_CONNTRACK=y
-# CONFIG_IP_NF_CT_ACCT is not set
-# CONFIG_IP_NF_CT_PROTO_SCTP is not set
-# CONFIG_IP_NF_FTP is not set
-# CONFIG_IP_NF_IRC is not set
-# CONFIG_IP_NF_TFTP is not set
-# CONFIG_IP_NF_AMANDA is not set
-CONFIG_IP_NF_QUEUE=y
-CONFIG_IP_NF_IPTABLES=y
-CONFIG_IP_NF_MATCH_LIMIT=y
-CONFIG_IP_NF_MATCH_IPRANGE=y
-CONFIG_IP_NF_MATCH_MAC=y
-CONFIG_IP_NF_MATCH_PKTTYPE=y
-CONFIG_IP_NF_MATCH_MARK=y
-CONFIG_IP_NF_MATCH_MULTIPORT=y
-CONFIG_IP_NF_MATCH_TOS=y
-CONFIG_IP_NF_MATCH_RECENT=y
-CONFIG_IP_NF_MATCH_ECN=y
-CONFIG_IP_NF_MATCH_DSCP=y
-CONFIG_IP_NF_MATCH_AH_ESP=y
-CONFIG_IP_NF_MATCH_LENGTH=y
-CONFIG_IP_NF_MATCH_TTL=y
-CONFIG_IP_NF_MATCH_TCPMSS=y
-CONFIG_IP_NF_MATCH_HELPER=y
-CONFIG_IP_NF_MATCH_STATE=y
-CONFIG_IP_NF_MATCH_CONNTRACK=y
-CONFIG_IP_NF_MATCH_OWNER=y
-# 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_COMMENT is not set
-CONFIG_IP_NF_FILTER=y
-CONFIG_IP_NF_TARGET_REJECT=y
-CONFIG_IP_NF_TARGET_LOG=y
-CONFIG_IP_NF_TARGET_ULOG=y
-CONFIG_IP_NF_TARGET_TCPMSS=y
-CONFIG_IP_NF_NAT=y
+CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_CT_ACCT=y
+CONFIG_IP_NF_CONNTRACK_MARK=y
+CONFIG_IP_NF_CT_PROTO_SCTP=m
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_LIMIT=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_MAC=m
+CONFIG_IP_NF_MATCH_PKTTYPE=m
+CONFIG_IP_NF_MATCH_MARK=m
+CONFIG_IP_NF_MATCH_MULTIPORT=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH_ESP=m
+CONFIG_IP_NF_MATCH_LENGTH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_TCPMSS=m
+CONFIG_IP_NF_MATCH_HELPER=m
+CONFIG_IP_NF_MATCH_STATE=m
+CONFIG_IP_NF_MATCH_CONNTRACK=m
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_REALM=m
+CONFIG_IP_NF_MATCH_SCTP=m
+CONFIG_IP_NF_MATCH_COMMENT=m
+CONFIG_IP_NF_MATCH_CONNMARK=m
+CONFIG_IP_NF_MATCH_HASHLIMIT=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=m
+CONFIG_IP_NF_NAT=m
CONFIG_IP_NF_NAT_NEEDED=y
-CONFIG_IP_NF_TARGET_MASQUERADE=y
-CONFIG_IP_NF_TARGET_REDIRECT=y
-CONFIG_IP_NF_TARGET_NETMAP=y
-CONFIG_IP_NF_TARGET_SAME=y
-# CONFIG_IP_NF_NAT_SNMP_BASIC is not set
-CONFIG_IP_NF_MANGLE=y
-CONFIG_IP_NF_TARGET_TOS=y
-CONFIG_IP_NF_TARGET_ECN=y
-CONFIG_IP_NF_TARGET_DSCP=y
-CONFIG_IP_NF_TARGET_MARK=y
-CONFIG_IP_NF_TARGET_CLASSIFY=y
-# CONFIG_IP_NF_RAW is not set
-CONFIG_IP_NF_ARPTABLES=y
-CONFIG_IP_NF_ARPFILTER=y
-CONFIG_IP_NF_ARP_MANGLE=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
CONFIG_XFRM=y
-# CONFIG_XFRM_USER is not set
+CONFIG_XFRM_USER=m
#
# SCTP Configuration (EXPERIMENTAL)
@@ -471,13 +507,12 @@ CONFIG_LLC=y
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
#
# QoS and/or fair queueing
#
# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
+CONFIG_NET_CLS_ROUTE=y
#
# Network testing
@@ -587,7 +622,7 @@ CONFIG_INPUT=y
# Userland interfaces
#
CONFIG_INPUT_MOUSEDEV=y
-CONFIG_INPUT_MOUSEDEV_PSAUX=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
CONFIG_INPUT_JOYDEV=m
@@ -663,12 +698,16 @@ CONFIG_LEGACY_PTY_COUNT=256
#
# Ftape, the floppy tape device driver
#
-# CONFIG_AGP is not set
# CONFIG_DRM is not set
CONFIG_RAW_DRIVER=y
CONFIG_MAX_RAW_DEVS=256
#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
# I2C support
#
CONFIG_I2C=y
@@ -693,14 +732,17 @@ CONFIG_I2C_ALGOBIT=y
# CONFIG_I2C_I810 is not set
# CONFIG_I2C_ISA is not set
CONFIG_I2C_KEYWEST=y
+# CONFIG_I2C_MPC is not set
# CONFIG_I2C_NFORCE2 is not set
# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PIIX4 is not set
# CONFIG_I2C_PROSAVAGE is not set
# CONFIG_I2C_SAVAGE4 is not set
# CONFIG_SCx200_ACB is not set
# 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
@@ -712,20 +754,28 @@ CONFIG_I2C_KEYWEST=y
# CONFIG_I2C_SENSOR is not set
# CONFIG_SENSORS_ADM1021 is not set
# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ASB100 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
# CONFIG_SENSORS_LM75 is not set
# CONFIG_SENSORS_LM77 is not set
# CONFIG_SENSORS_LM78 is not set
# CONFIG_SENSORS_LM80 is not set
# CONFIG_SENSORS_LM83 is not set
# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_SIS5595 is not set
# CONFIG_SENSORS_SMSC47M1 is not set
# CONFIG_SENSORS_VIA686A is not set
# CONFIG_SENSORS_W83781D is not set
@@ -768,6 +818,7 @@ CONFIG_I2C_KEYWEST=y
#
CONFIG_FB=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
@@ -789,6 +840,7 @@ 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
@@ -814,6 +866,11 @@ CONFIG_LOGO=y
CONFIG_LOGO_LINUX_MONO=y
CONFIG_LOGO_LINUX_VGA16=y
CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=m
+CONFIG_BACKLIGHT_DEVICE=y
+CONFIG_LCD_CLASS_DEVICE=m
+CONFIG_LCD_DEVICE=y
#
# Sound
@@ -833,6 +890,8 @@ 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
@@ -841,7 +900,10 @@ CONFIG_USB_EHCI_HCD=y
# CONFIG_USB_EHCI_SPLIT_ISO is not set
# CONFIG_USB_EHCI_ROOT_HUB_TT 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
@@ -849,20 +911,24 @@ CONFIG_USB_OHCI_HCD=y
# CONFIG_USB_BLUETOOTH_TTY is not set
CONFIG_USB_ACM=m
CONFIG_USB_PRINTER=y
+
+#
+# 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_RW_DETECT is not set
+CONFIG_USB_STORAGE_RW_DETECT=y
CONFIG_USB_STORAGE_DATAFAB=y
CONFIG_USB_STORAGE_FREECOM=y
CONFIG_USB_STORAGE_ISD200=y
CONFIG_USB_STORAGE_DPCM=y
-CONFIG_USB_STORAGE_HP8200e=y
+# CONFIG_USB_STORAGE_USBAT is not set
CONFIG_USB_STORAGE_SDDR09=y
CONFIG_USB_STORAGE_SDDR55=y
CONFIG_USB_STORAGE_JUMPSHOT=y
#
-# USB Human Interface Devices (HID)
+# USB Input Devices
#
CONFIG_USB_HID=y
CONFIG_USB_HIDINPUT=y
@@ -885,7 +951,6 @@ CONFIG_USB_HIDDEV=y
#
# CONFIG_USB_MDC800 is not set
# CONFIG_USB_MICROTEK is not set
-# CONFIG_USB_HPUSBSCSI is not set
#
# USB Multimedia devices
@@ -897,12 +962,12 @@ CONFIG_USB_HIDDEV=y
#
#
-# USB Network adaptors
+# 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_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
CONFIG_USB_USBNET=m
#
@@ -914,6 +979,7 @@ CONFIG_USB_BELKIN=y
CONFIG_USB_GENESYS=y
CONFIG_USB_NET1080=y
CONFIG_USB_PL2301=y
+CONFIG_USB_KC2190=y
#
# Intelligent USB Devices/Gadgets
@@ -927,6 +993,7 @@ CONFIG_USB_CDCETHER=y
# USB Network Adapters
#
CONFIG_USB_AX8817X=y
+CONFIG_USB_MON=y
#
# USB port drivers
@@ -939,6 +1006,7 @@ 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=m
@@ -946,6 +1014,8 @@ CONFIG_USB_SERIAL_IPAQ=m
CONFIG_USB_SERIAL_IR=m
CONFIG_USB_SERIAL_EDGEPORT=m
CONFIG_USB_SERIAL_EDGEPORT_TI=m
+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=y
@@ -966,6 +1036,7 @@ CONFIG_USB_SERIAL_MCT_U232=m
CONFIG_USB_SERIAL_PL2303=m
CONFIG_USB_SERIAL_SAFE=m
CONFIG_USB_SERIAL_SAFE_PADDED=y
+CONFIG_USB_SERIAL_TI=m
CONFIG_USB_SERIAL_CYBERJACK=m
CONFIG_USB_SERIAL_XIRCOM=m
CONFIG_USB_SERIAL_OMNINET=m
@@ -976,42 +1047,73 @@ CONFIG_USB_EZUSB=y
#
# CONFIG_USB_EMI62 is not set
# CONFIG_USB_EMI26 is not set
-# CONFIG_USB_TIGL 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_TEST is not set
#
+# USB ATM/DSL drivers
+#
+
+#
# 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
+
+#
# File systems
#
CONFIG_EXT2_FS=y
CONFIG_EXT2_FS_XATTR=y
CONFIG_EXT2_FS_POSIX_ACL=y
-# CONFIG_EXT2_FS_SECURITY is not set
+CONFIG_EXT2_FS_SECURITY=y
CONFIG_EXT3_FS=y
CONFIG_EXT3_FS_XATTR=y
CONFIG_EXT3_FS_POSIX_ACL=y
-# CONFIG_EXT3_FS_SECURITY is not set
+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_REISERFS_FS=y
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
# CONFIG_JFS_FS is not set
CONFIG_FS_POSIX_ACL=y
-# CONFIG_XFS_FS is not set
+
+#
+# XFS support
+#
+CONFIG_XFS_FS=m
+CONFIG_XFS_EXPORT=y
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_QUOTA is not set
+CONFIG_XFS_SECURITY=y
+CONFIG_XFS_POSIX_ACL=y
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
CONFIG_AUTOFS_FS=m
# CONFIG_AUTOFS4_FS is not set
@@ -1019,8 +1121,9 @@ CONFIG_AUTOFS_FS=m
# CD-ROM/DVD Filesystems
#
CONFIG_ISO9660_FS=y
-# CONFIG_JOLIET is not set
-# CONFIG_ZISOFS is not set
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=y
CONFIG_UDF_FS=m
CONFIG_UDF_NLS=y
@@ -1044,6 +1147,8 @@ CONFIG_SYSFS=y
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
@@ -1053,8 +1158,8 @@ CONFIG_RAMFS=y
#
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_HFSPLUS_FS is not set
+CONFIG_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
@@ -1087,7 +1192,7 @@ CONFIG_RPCSEC_GSS_KRB5=y
CONFIG_CIFS=m
# CONFIG_CIFS_STATS is not set
# CONFIG_CIFS_XATTR is not set
-# CONFIG_CIFS_POSIX is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
# CONFIG_AFS_FS is not set
@@ -1117,7 +1222,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
@@ -1138,10 +1243,10 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# 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_CODEPAGE_1250=y
+CONFIG_NLS_CODEPAGE_1251=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
# CONFIG_NLS_ISO8859_2 is not set
# CONFIG_NLS_ISO8859_3 is not set
# CONFIG_NLS_ISO8859_4 is not set
@@ -1151,10 +1256,10 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_NLS_ISO8859_9 is not set
# CONFIG_NLS_ISO8859_13 is not set
# CONFIG_NLS_ISO8859_14 is not set
-# CONFIG_NLS_ISO8859_15 is not set
+CONFIG_NLS_ISO8859_15=y
# 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
@@ -1167,19 +1272,24 @@ CONFIG_OPROFILE=y
#
CONFIG_DEBUG_KERNEL=y
CONFIG_MAGIC_SYSRQ=y
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_SCHEDSTATS is not set
# CONFIG_DEBUG_SLAB 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=y
# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_KPROBES is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUGGER is not set
# CONFIG_PPCDBG is not set
CONFIG_IRQSTACKS=y
-# CONFIG_SCHEDSTATS is not set
#
# Security options
#
+# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
#
@@ -1193,7 +1303,8 @@ CONFIG_CRYPTO_MD5=y
CONFIG_CRYPTO_SHA1=m
CONFIG_CRYPTO_SHA256=m
CONFIG_CRYPTO_SHA512=m
-# CONFIG_CRYPTO_WP512 is not set
+CONFIG_CRYPTO_WP512=m
+# CONFIG_CRYPTO_TGR192 is not set
CONFIG_CRYPTO_DES=y
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_TWOFISH=m
@@ -1201,19 +1312,24 @@ CONFIG_CRYPTO_SERPENT=m
CONFIG_CRYPTO_AES=m
CONFIG_CRYPTO_CAST5=m
CONFIG_CRYPTO_CAST6=m
-# CONFIG_CRYPTO_TEA is not set
+CONFIG_CRYPTO_TEA=m
CONFIG_CRYPTO_ARC4=m
-# CONFIG_CRYPTO_KHAZAD is not set
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
CONFIG_CRYPTO_DEFLATE=m
CONFIG_CRYPTO_MICHAEL_MIC=m
-# CONFIG_CRYPTO_CRC32C is not set
+CONFIG_CRYPTO_CRC32C=m
CONFIG_CRYPTO_TEST=m
#
+# Hardware crypto devices
+#
+
+#
# Library routines
#
CONFIG_CRC_CCITT=m
CONFIG_CRC32=y
-# CONFIG_LIBCRC32C is not set
+CONFIG_LIBCRC32C=m
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=m
diff --git a/arch/ppc64/configs/iSeries_defconfig b/arch/ppc64/configs/iSeries_defconfig
index 0ee69246bab82..a39e9d2e25da1 100644
--- a/arch/ppc64/configs/iSeries_defconfig
+++ b/arch/ppc64/configs/iSeries_defconfig
@@ -1,9 +1,12 @@
#
# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-rc3-bk6
+# Wed Feb 9 23:34:52 2005
#
CONFIG_64BIT=y
CONFIG_MMU=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_GENERIC_ISA_DMA=y
CONFIG_HAVE_DEC_LOCK=y
CONFIG_EARLY_PRINTK=y
@@ -16,19 +19,20 @@ CONFIG_FORCE_MAX_ZONEORDER=13
#
CONFIG_EXPERIMENTAL=y
CONFIG_CLEAN_COMPILE=y
+CONFIG_LOCK_KERNEL=y
#
# General setup
#
+CONFIG_LOCALVERSION=""
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
CONFIG_POSIX_MQUEUE=y
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
-CONFIG_AUDIT=y
-CONFIG_AUDITSYSCALL=y
CONFIG_LOG_BUF_SHIFT=17
CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
# CONFIG_EMBEDDED is not set
@@ -37,12 +41,12 @@ CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
CONFIG_FUTEX=y
CONFIG_EPOLL=y
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
# CONFIG_TINY_SHMEM is not set
#
@@ -52,8 +56,9 @@ CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
CONFIG_OBSOLETE_MODPARM=y
-# CONFIG_MODVERSIONS is not set
-# CONFIG_KMOD is not set
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_KMOD=y
CONFIG_STOP_MACHINE=y
CONFIG_SYSVIPC_COMPAT=y
@@ -61,15 +66,17 @@ CONFIG_SYSVIPC_COMPAT=y
# Platform support
#
CONFIG_PPC_ISERIES=y
-# CONFIG_PPC_PSERIES is not set
+# CONFIG_PPC_MULTIPLATFORM is not set
CONFIG_PPC=y
CONFIG_PPC64=y
+CONFIG_IBMVIO=y
# CONFIG_POWER4_ONLY is not set
CONFIG_IOMMU_VMERGE=y
CONFIG_SMP=y
CONFIG_NR_CPUS=32
# CONFIG_SCHED_SMT is not set
# CONFIG_PREEMPT is not set
+CONFIG_GENERIC_HARDIRQS=y
CONFIG_MSCHUNKS=y
CONFIG_LPARCFG=y
@@ -82,12 +89,15 @@ CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
CONFIG_PCI_LEGACY_PROC=y
CONFIG_PCI_NAMES=y
-# CONFIG_HOTPLUG_CPU is not set
#
-# PCMCIA/CardBus support
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
#
-# CONFIG_PCMCIA is not set
#
# PCI Hotplug Support
@@ -128,13 +138,26 @@ CONFIG_FW_LOADER=m
# 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=m
# CONFIG_BLK_DEV_SX8 is not set
CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=65536
CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
#
# ATA/ATAPI/MFM/RLL support
@@ -169,6 +192,7 @@ CONFIG_SCSI_CONSTANTS=y
#
CONFIG_SCSI_SPI_ATTRS=y
CONFIG_SCSI_FC_ATTRS=y
+# CONFIG_SCSI_ISCSI_ATTRS is not set
#
# SCSI low-level drivers
@@ -191,6 +215,7 @@ CONFIG_SCSI_FC_ATTRS=y
# CONFIG_SCSI_GDTH is not set
# CONFIG_SCSI_IPS is not set
CONFIG_SCSI_IBMVSCSI=m
+# 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
@@ -203,7 +228,6 @@ CONFIG_SCSI_QLA2XXX=y
# CONFIG_SCSI_QLA2300 is not set
# CONFIG_SCSI_QLA2322 is not set
# CONFIG_SCSI_QLA6312 is not set
-# CONFIG_SCSI_QLA6322 is not set
# CONFIG_SCSI_DC395x is not set
# CONFIG_SCSI_DC390T is not set
# CONFIG_SCSI_DEBUG is not set
@@ -220,6 +244,7 @@ CONFIG_MD_RAID10=m
CONFIG_MD_RAID5=y
CONFIG_MD_RAID6=m
CONFIG_MD_MULTIPATH=m
+CONFIG_MD_FAULTY=m
CONFIG_BLK_DEV_DM=y
CONFIG_DM_CRYPT=m
CONFIG_DM_SNAPSHOT=m
@@ -271,6 +296,8 @@ CONFIG_INET_AH=m
CONFIG_INET_ESP=m
CONFIG_INET_IPCOMP=m
CONFIG_INET_TUNNEL=y
+CONFIG_IP_TCPDIAG=m
+# CONFIG_IP_TCPDIAG_IPV6 is not set
#
# IP: Virtual Server Configuration
@@ -284,6 +311,9 @@ CONFIG_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
@@ -308,8 +338,17 @@ CONFIG_IP_NF_MATCH_HELPER=m
CONFIG_IP_NF_MATCH_STATE=m
CONFIG_IP_NF_MATCH_CONNTRACK=m
CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_REALM=m
+CONFIG_IP_NF_MATCH_SCTP=m
+CONFIG_IP_NF_MATCH_COMMENT=m
+CONFIG_IP_NF_MATCH_CONNMARK=m
+CONFIG_IP_NF_MATCH_HASHLIMIT=m
CONFIG_IP_NF_FILTER=m
CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=m
CONFIG_IP_NF_NAT=m
CONFIG_IP_NF_NAT_NEEDED=y
CONFIG_IP_NF_TARGET_MASQUERADE=m
@@ -327,21 +366,13 @@ 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_LOG=m
-CONFIG_IP_NF_TARGET_ULOG=m
-CONFIG_IP_NF_TARGET_TCPMSS=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
-CONFIG_IP_NF_COMPAT_IPCHAINS=m
-CONFIG_IP_NF_COMPAT_IPFWADM=m
-CONFIG_IP_NF_TARGET_NOTRACK=m
-CONFIG_IP_NF_RAW=m
-CONFIG_IP_NF_MATCH_ADDRTYPE=m
-CONFIG_IP_NF_MATCH_REALM=m
-# CONFIG_IP_NF_CT_ACCT is not set
-CONFIG_IP_NF_MATCH_SCTP=m
-CONFIG_IP_NF_CT_PROTO_SCTP=m
CONFIG_XFRM=y
CONFIG_XFRM_USER=m
@@ -362,7 +393,6 @@ CONFIG_LLC=y
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
#
# QoS and/or fair queueing
@@ -425,19 +455,21 @@ CONFIG_E100=y
# CONFIG_EPIC100 is not set
# CONFIG_SUNDANCE is not set
# CONFIG_VIA_RHINE is not set
-# CONFIG_VIA_VELOCITY is not set
#
# Ethernet (1000 Mbit)
#
-# CONFIG_ACENIC is not set
+CONFIG_ACENIC=m
+# CONFIG_ACENIC_OMIT_TIGON_I is not set
# CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
+CONFIG_E1000=m
+# CONFIG_E1000_NAPI is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
# CONFIG_R8169 is not set
# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
# CONFIG_TIGON3 is not set
#
@@ -498,7 +530,7 @@ CONFIG_INPUT=y
# Userland interfaces
#
CONFIG_INPUT_MOUSEDEV=y
-CONFIG_INPUT_MOUSEDEV_PSAUX=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
@@ -511,11 +543,8 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
#
# CONFIG_GAMEPORT is not set
CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
+# CONFIG_SERIO is not set
# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PCIPS2 is not set
#
# Input Device Drivers
@@ -563,7 +592,6 @@ CONFIG_LEGACY_PTY_COUNT=256
#
# Ftape, the floppy tape device driver
#
-# CONFIG_AGP is not set
# CONFIG_DRM is not set
CONFIG_RAW_DRIVER=y
CONFIG_MAX_RAW_DEVS=256
@@ -606,6 +634,12 @@ CONFIG_MAX_RAW_DEVS=256
# USB support
#
# CONFIG_USB is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
#
# USB Gadget Support
@@ -613,16 +647,26 @@ CONFIG_MAX_RAW_DEVS=256
# CONFIG_USB_GADGET is not set
#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
# File systems
#
CONFIG_EXT2_FS=y
CONFIG_EXT2_FS_XATTR=y
CONFIG_EXT2_FS_POSIX_ACL=y
-# CONFIG_EXT2_FS_SECURITY is not set
+CONFIG_EXT2_FS_SECURITY=y
CONFIG_EXT3_FS=y
CONFIG_EXT3_FS_XATTR=y
CONFIG_EXT3_FS_POSIX_ACL=y
-# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_EXT3_FS_SECURITY=y
CONFIG_JBD=y
# CONFIG_JBD_DEBUG is not set
CONFIG_FS_MBCACHE=y
@@ -631,20 +675,27 @@ CONFIG_REISERFS_FS=y
# CONFIG_REISERFS_PROC_INFO is not set
CONFIG_REISERFS_FS_XATTR=y
CONFIG_REISERFS_FS_POSIX_ACL=y
-# CONFIG_REISERFS_FS_SECURITY is not set
+CONFIG_REISERFS_FS_SECURITY=y
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 is not set
-# CONFIG_XFS_SECURITY is not set
+CONFIG_XFS_SECURITY=y
CONFIG_XFS_POSIX_ACL=y
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
CONFIG_AUTOFS_FS=m
# CONFIG_AUTOFS4_FS is not set
@@ -652,8 +703,9 @@ CONFIG_AUTOFS_FS=m
# CD-ROM/DVD Filesystems
#
CONFIG_ISO9660_FS=y
-# CONFIG_JOLIET is not set
-# CONFIG_ZISOFS is not set
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=y
CONFIG_UDF_FS=m
CONFIG_UDF_NLS=y
@@ -675,8 +727,10 @@ CONFIG_PROC_KCORE=y
CONFIG_SYSFS=y
# CONFIG_DEVFS_FS is not set
CONFIG_DEVPTS_FS_XATTR=y
-# CONFIG_DEVPTS_FS_SECURITY is not set
+CONFIG_DEVPTS_FS_SECURITY=y
CONFIG_TMPFS=y
+CONFIG_TMPFS_XATTR=y
+CONFIG_TMPFS_SECURITY=y
# CONFIG_HUGETLBFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
@@ -721,6 +775,7 @@ CONFIG_CIFS=m
# CONFIG_CIFS_STATS is not set
CONFIG_CIFS_XATTR=y
CONFIG_CIFS_POSIX=y
+# CONFIG_CIFS_EXPERIMENTAL is not set
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
# CONFIG_AFS_FS is not set
@@ -795,19 +850,23 @@ CONFIG_OPROFILE=y
#
CONFIG_DEBUG_KERNEL=y
CONFIG_MAGIC_SYSRQ=y
+# CONFIG_SCHEDSTATS is not set
# CONFIG_DEBUG_SLAB 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=y
CONFIG_DEBUG_STACKOVERFLOW=y
+# CONFIG_KPROBES is not set
CONFIG_DEBUG_STACK_USAGE=y
# CONFIG_DEBUGGER is not set
# CONFIG_PPCDBG is not set
-# CONFIG_IRQSTACKS is not set
-# CONFIG_SCHEDSTATS is not set
+CONFIG_IRQSTACKS=y
#
# Security options
#
+# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
#
@@ -821,7 +880,7 @@ CONFIG_CRYPTO_MD5=y
CONFIG_CRYPTO_SHA1=m
CONFIG_CRYPTO_SHA256=m
CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_WHIRLPOOL=m
+CONFIG_CRYPTO_WP512=m
CONFIG_CRYPTO_DES=y
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_TWOFISH=m
@@ -832,12 +891,17 @@ CONFIG_CRYPTO_CAST6=m
CONFIG_CRYPTO_TEA=m
CONFIG_CRYPTO_ARC4=m
CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
CONFIG_CRYPTO_DEFLATE=m
CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_CRC32C=m
CONFIG_CRYPTO_TEST=m
#
+# Hardware crypto devices
+#
+
+#
# Library routines
#
CONFIG_CRC_CCITT=m
diff --git a/arch/ppc64/configs/maple_defconfig b/arch/ppc64/configs/maple_defconfig
index 65571a06fb400..cf527501915c6 100644
--- a/arch/ppc64/configs/maple_defconfig
+++ b/arch/ppc64/configs/maple_defconfig
@@ -1,11 +1,12 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.9
-# Wed Oct 20 15:39:14 2004
+# Linux kernel version: 2.6.11-rc3-bk6
+# Wed Feb 9 23:34:53 2005
#
CONFIG_64BIT=y
CONFIG_MMU=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_GENERIC_ISA_DMA=y
CONFIG_HAVE_DEC_LOCK=y
CONFIG_EARLY_PRINTK=y
@@ -18,6 +19,7 @@ CONFIG_FORCE_MAX_ZONEORDER=13
#
CONFIG_EXPERIMENTAL=y
CONFIG_CLEAN_COMPILE=y
+CONFIG_LOCK_KERNEL=y
#
# General setup
@@ -25,12 +27,12 @@ CONFIG_CLEAN_COMPILE=y
CONFIG_LOCALVERSION=""
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
-# CONFIG_POSIX_MQUEUE is not set
+CONFIG_POSIX_MQUEUE=y
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
-# CONFIG_AUDIT is not set
CONFIG_LOG_BUF_SHIFT=17
# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
# CONFIG_EMBEDDED is not set
@@ -39,12 +41,12 @@ CONFIG_KALLSYMS_ALL=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
CONFIG_FUTEX=y
CONFIG_EPOLL=y
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
# CONFIG_TINY_SHMEM is not set
#
@@ -52,9 +54,10 @@ CONFIG_SHMEM=y
#
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
-CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
CONFIG_OBSOLETE_MODPARM=y
-# CONFIG_MODVERSIONS is not set
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_KMOD=y
CONFIG_STOP_MACHINE=y
CONFIG_SYSVIPC_COMPAT=y
@@ -77,10 +80,10 @@ CONFIG_BOOTX_TEXT=y
CONFIG_POWER4_ONLY=y
CONFIG_IOMMU_VMERGE=y
CONFIG_SMP=y
-# CONFIG_IRQ_ALL_CPUS is not set
CONFIG_NR_CPUS=2
# CONFIG_SCHED_SMT is not set
# CONFIG_PREEMPT is not set
+CONFIG_GENERIC_HARDIRQS=y
#
# General setup
@@ -91,6 +94,20 @@ CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
CONFIG_PCI_LEGACY_PROC=y
CONFIG_PCI_NAMES=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
@@ -103,6 +120,7 @@ CONFIG_PROC_DEVICETREE=y
#
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
# CONFIG_DEBUG_DRIVER is not set
#
@@ -127,13 +145,26 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
# CONFIG_BLK_CPQ_CISS_DA is not set
# CONFIG_BLK_DEV_DAC960 is not set
# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
# CONFIG_BLK_DEV_LOOP is not set
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_SX8 is not set
# CONFIG_BLK_DEV_UB is not set
CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=8192
# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
#
# ATA/ATAPI/MFM/RLL support
@@ -151,7 +182,6 @@ CONFIG_BLK_DEV_IDECD=y
# CONFIG_BLK_DEV_IDETAPE is not set
# CONFIG_BLK_DEV_IDEFLOPPY is not set
CONFIG_IDE_TASK_IOCTL=y
-CONFIG_IDE_TASKFILE_IO=y
#
# IDE chipset support/bugfixes
@@ -250,6 +280,8 @@ CONFIG_IP_PNP_DHCP=y
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
# CONFIG_IPV6 is not set
# CONFIG_NETFILTER is not set
@@ -269,7 +301,6 @@ CONFIG_IP_PNP_DHCP=y
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
#
# QoS and/or fair queueing
@@ -330,7 +361,6 @@ CONFIG_AMD8111_ETH=y
# CONFIG_EPIC100 is not set
# CONFIG_SUNDANCE is not set
# CONFIG_VIA_RHINE is not set
-# CONFIG_VIA_VELOCITY is not set
#
# Ethernet (1000 Mbit)
@@ -344,6 +374,7 @@ CONFIG_E1000=y
# CONFIG_YELLOWFIN is not set
# CONFIG_R8169 is not set
# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
# CONFIG_TIGON3 is not set
#
@@ -461,7 +492,6 @@ CONFIG_LEGACY_PTY_COUNT=256
#
# Ftape, the floppy tape device driver
#
-# CONFIG_AGP is not set
# CONFIG_DRM is not set
# CONFIG_RAW_DRIVER is not set
@@ -489,6 +519,7 @@ CONFIG_I2C_AMD8111=y
# CONFIG_I2C_I801 is not set
# CONFIG_I2C_I810 is not set
# CONFIG_I2C_ISA is not set
+# 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
@@ -497,6 +528,7 @@ CONFIG_I2C_AMD8111=y
# 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
@@ -508,20 +540,25 @@ CONFIG_I2C_AMD8111=y
# CONFIG_I2C_SENSOR is not set
# CONFIG_SENSORS_ADM1021 is not set
# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ASB100 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_FSCHER is not set
# CONFIG_SENSORS_GL518SM is not set
# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
# CONFIG_SENSORS_LM75 is not set
# CONFIG_SENSORS_LM77 is not set
# CONFIG_SENSORS_LM78 is not set
# CONFIG_SENSORS_LM80 is not set
# CONFIG_SENSORS_LM83 is not set
# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
# CONFIG_SENSORS_SMSC47M1 is not set
# CONFIG_SENSORS_VIA686A is not set
# CONFIG_SENSORS_W83781D is not set
@@ -588,6 +625,8 @@ 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
@@ -597,6 +636,7 @@ CONFIG_USB_EHCI_SPLIT_ISO=y
CONFIG_USB_EHCI_ROOT_HUB_TT=y
CONFIG_USB_OHCI_HCD=y
CONFIG_USB_UHCI_HCD=y
+# CONFIG_USB_SL811_HCD is not set
#
# USB Device Class drivers
@@ -604,10 +644,14 @@ CONFIG_USB_UHCI_HCD=y
# CONFIG_USB_BLUETOOTH_TTY is not set
# CONFIG_USB_ACM is not set
# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
# CONFIG_USB_STORAGE is not set
#
-# USB Human Interface Devices (HID)
+# USB Input Devices
#
CONFIG_USB_HID=y
CONFIG_USB_HIDINPUT=y
@@ -637,7 +681,7 @@ CONFIG_USB_HIDINPUT=y
#
#
-# USB Network adaptors
+# USB Network Adapters
#
# CONFIG_USB_CATC is not set
# CONFIG_USB_KAWETH is not set
@@ -657,6 +701,7 @@ CONFIG_USB_SERIAL=y
CONFIG_USB_SERIAL_GENERIC=y
# CONFIG_USB_SERIAL_BELKIN is not set
# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
+CONFIG_USB_SERIAL_CYPRESS_M8=m
# CONFIG_USB_SERIAL_EMPEG is not set
# CONFIG_USB_SERIAL_FTDI_SIO is not set
# CONFIG_USB_SERIAL_VISOR is not set
@@ -664,6 +709,8 @@ CONFIG_USB_SERIAL_GENERIC=y
# 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=m
+CONFIG_USB_SERIAL_IPW=m
# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
CONFIG_USB_SERIAL_KEYSPAN=y
CONFIG_USB_SERIAL_KEYSPAN_MPR=y
@@ -683,6 +730,7 @@ CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
# CONFIG_USB_SERIAL_MCT_U232 is not set
# CONFIG_USB_SERIAL_PL2303 is not set
# CONFIG_USB_SERIAL_SAFE is not set
+CONFIG_USB_SERIAL_TI=m
# CONFIG_USB_SERIAL_CYBERJACK is not set
# CONFIG_USB_SERIAL_XIRCOM is not set
# CONFIG_USB_SERIAL_OMNINET is not set
@@ -693,22 +741,37 @@ CONFIG_USB_EZUSB=y
#
# CONFIG_USB_EMI62 is not set
# CONFIG_USB_EMI26 is not set
-# CONFIG_USB_TIGL 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_TEST is not set
#
+# USB ATM/DSL drivers
+#
+
+#
# 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
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -719,10 +782,15 @@ CONFIG_JBD=y
# CONFIG_JBD_DEBUG is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
# CONFIG_XFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
@@ -752,8 +820,10 @@ CONFIG_SYSFS=y
CONFIG_DEVPTS_FS_XATTR=y
# CONFIG_DEVPTS_FS_SECURITY is not set
CONFIG_TMPFS=y
-# CONFIG_HUGETLBFS is not set
-# CONFIG_HUGETLB_PAGE is not set
+CONFIG_TMPFS_XATTR=y
+CONFIG_TMPFS_SECURITY=y
+CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
CONFIG_RAMFS=y
#
@@ -766,7 +836,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
@@ -784,7 +854,6 @@ CONFIG_NFS_V4=y
CONFIG_ROOT_NFS=y
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
-# CONFIG_EXPORTFS is not set
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=y
CONFIG_RPCSEC_GSS_KRB5=y
@@ -869,21 +938,25 @@ CONFIG_NLS_UTF8=y
#
CONFIG_DEBUG_KERNEL=y
CONFIG_MAGIC_SYSRQ=y
+# CONFIG_SCHEDSTATS is not set
CONFIG_DEBUG_SLAB=y
CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_DEBUG_KOBJECT is not set
# CONFIG_DEBUG_INFO is not set
+CONFIG_DEBUG_FS=y
CONFIG_DEBUG_STACKOVERFLOW=y
+# CONFIG_KPROBES is not set
CONFIG_DEBUG_STACK_USAGE=y
CONFIG_DEBUGGER=y
CONFIG_XMON=y
CONFIG_XMON_DEFAULT=y
# CONFIG_PPCDBG is not set
# CONFIG_IRQSTACKS is not set
-# CONFIG_SCHEDSTATS is not set
#
# Security options
#
+# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
#
@@ -908,14 +981,20 @@ CONFIG_CRYPTO_DES=y
# 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=y
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
diff --git a/arch/ppc64/configs/pSeries_defconfig b/arch/ppc64/configs/pSeries_defconfig
index a56c5ee9caf03..4fecf237d5c9f 100644
--- a/arch/ppc64/configs/pSeries_defconfig
+++ b/arch/ppc64/configs/pSeries_defconfig
@@ -1,11 +1,12 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.9-rc2
-# Thu Sep 23 16:45:05 2004
+# Linux kernel version: 2.6.11-rc3-bk6
+# Wed Feb 9 23:34:54 2005
#
CONFIG_64BIT=y
CONFIG_MMU=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_GENERIC_ISA_DMA=y
CONFIG_HAVE_DEC_LOCK=y
CONFIG_EARLY_PRINTK=y
@@ -18,6 +19,7 @@ CONFIG_FORCE_MAX_ZONEORDER=13
#
CONFIG_EXPERIMENTAL=y
CONFIG_CLEAN_COMPILE=y
+CONFIG_LOCK_KERNEL=y
#
# General setup
@@ -28,10 +30,9 @@ CONFIG_SYSVIPC=y
CONFIG_POSIX_MQUEUE=y
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
-CONFIG_AUDIT=y
-CONFIG_AUDITSYSCALL=y
CONFIG_LOG_BUF_SHIFT=17
CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
# CONFIG_EMBEDDED is not set
@@ -40,12 +41,12 @@ CONFIG_KALLSYMS_ALL=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
CONFIG_FUTEX=y
CONFIG_EPOLL=y
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
# CONFIG_TINY_SHMEM is not set
#
@@ -55,8 +56,9 @@ CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
CONFIG_OBSOLETE_MODPARM=y
-# CONFIG_MODVERSIONS is not set
-# CONFIG_KMOD is not set
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_KMOD=y
CONFIG_STOP_MACHINE=y
CONFIG_SYSVIPC_COMPAT=y
@@ -67,22 +69,25 @@ CONFIG_SYSVIPC_COMPAT=y
CONFIG_PPC_MULTIPLATFORM=y
CONFIG_PPC_PSERIES=y
# CONFIG_PPC_PMAC is not set
+# CONFIG_PPC_MAPLE is not set
CONFIG_PPC=y
CONFIG_PPC64=y
CONFIG_PPC_OF=y
CONFIG_ALTIVEC=y
CONFIG_PPC_SPLPAR=y
+CONFIG_IBMVIO=y
+# CONFIG_U3_DART is not set
# CONFIG_BOOTX_TEXT is not set
# CONFIG_POWER4_ONLY is not set
CONFIG_IOMMU_VMERGE=y
CONFIG_SMP=y
-CONFIG_IRQ_ALL_CPUS=y
CONFIG_NR_CPUS=128
-# CONFIG_HMT is not set
CONFIG_DISCONTIGMEM=y
CONFIG_NUMA=y
CONFIG_SCHED_SMT=y
# CONFIG_PREEMPT is not set
+CONFIG_EEH=y
+CONFIG_GENERIC_HARDIRQS=y
CONFIG_PPC_RTAS=y
CONFIG_RTAS_FLASH=m
CONFIG_SCANLOG=m
@@ -100,9 +105,13 @@ CONFIG_PCI_NAMES=y
CONFIG_HOTPLUG_CPU=y
#
-# PCMCIA/CardBus support
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
#
-# CONFIG_PCMCIA is not set
#
# PCI Hotplug Support
@@ -110,7 +119,6 @@ CONFIG_HOTPLUG_CPU=y
CONFIG_HOTPLUG_PCI=m
# CONFIG_HOTPLUG_PCI_FAKE is not set
# CONFIG_HOTPLUG_PCI_CPCI is not set
-# CONFIG_HOTPLUG_PCI_PCIE is not set
# CONFIG_HOTPLUG_PCI_SHPC is not set
CONFIG_HOTPLUG_PCI_RPA=m
CONFIG_HOTPLUG_PCI_RPA_DLPAR=m
@@ -137,7 +145,14 @@ CONFIG_FW_LOADER=y
#
# Parallel port support
#
-# CONFIG_PARPORT is not set
+CONFIG_PARPORT=m
+CONFIG_PARPORT_PC=m
+CONFIG_PARPORT_PC_CML1=m
+# CONFIG_PARPORT_SERIAL is not set
+# CONFIG_PARPORT_PC_FIFO is not set
+# CONFIG_PARPORT_PC_SUPERIO is not set
+# CONFIG_PARPORT_OTHER is not set
+# CONFIG_PARPORT_1284 is not set
#
# Plug and Play support
@@ -147,18 +162,32 @@ CONFIG_FW_LOADER=y
# Block devices
#
CONFIG_BLK_DEV_FD=m
+# CONFIG_PARIDE is not set
# CONFIG_BLK_CPQ_DA is not set
# CONFIG_BLK_CPQ_CISS_DA is not set
# CONFIG_BLK_DEV_DAC960 is not set
# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
CONFIG_BLK_DEV_NBD=m
# CONFIG_BLK_DEV_SX8 is not set
# CONFIG_BLK_DEV_UB is not set
CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=65536
CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
#
# ATA/ATAPI/MFM/RLL support
@@ -177,7 +206,6 @@ CONFIG_BLK_DEV_IDECD=y
# CONFIG_BLK_DEV_IDEFLOPPY is not set
# CONFIG_BLK_DEV_IDESCSI is not set
# CONFIG_IDE_TASK_IOCTL is not set
-# CONFIG_IDE_TASKFILE_IO is not set
#
# IDE chipset support/bugfixes
@@ -247,6 +275,7 @@ CONFIG_SCSI_CONSTANTS=y
#
CONFIG_SCSI_SPI_ATTRS=y
CONFIG_SCSI_FC_ATTRS=y
+CONFIG_SCSI_ISCSI_ATTRS=m
#
# SCSI low-level drivers
@@ -269,15 +298,18 @@ CONFIG_SCSI_FC_ATTRS=y
# CONFIG_SCSI_GDTH is not set
# CONFIG_SCSI_IPS is not set
CONFIG_SCSI_IBMVSCSI=y
+# CONFIG_SCSI_INITIO is not set
# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_PPA is not set
+# CONFIG_SCSI_IMM is not set
CONFIG_SCSI_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=y
-# CONFIG_SCSI_IPR_TRACE is not set
-# CONFIG_SCSI_IPR_DUMP is not set
+CONFIG_SCSI_IPR_TRACE=y
+CONFIG_SCSI_IPR_DUMP=y
# CONFIG_SCSI_QLOGIC_ISP is not set
# CONFIG_SCSI_QLOGIC_FC is not set
# CONFIG_SCSI_QLOGIC_1280 is not set
@@ -287,7 +319,6 @@ CONFIG_SCSI_QLA22XX=m
CONFIG_SCSI_QLA2300=m
CONFIG_SCSI_QLA2322=m
CONFIG_SCSI_QLA6312=m
-CONFIG_SCSI_QLA6322=m
# CONFIG_SCSI_DC395x is not set
# CONFIG_SCSI_DC390T is not set
# CONFIG_SCSI_DEBUG is not set
@@ -304,6 +335,7 @@ CONFIG_MD_RAID10=m
CONFIG_MD_RAID5=y
CONFIG_MD_RAID6=m
CONFIG_MD_MULTIPATH=m
+CONFIG_MD_FAULTY=m
CONFIG_BLK_DEV_DM=y
CONFIG_DM_CRYPT=m
CONFIG_DM_SNAPSHOT=m
@@ -355,6 +387,8 @@ CONFIG_INET_AH=m
CONFIG_INET_ESP=m
CONFIG_INET_IPCOMP=m
CONFIG_INET_TUNNEL=y
+CONFIG_IP_TCPDIAG=m
+# CONFIG_IP_TCPDIAG_IPV6 is not set
#
# IP: Virtual Server Configuration
@@ -368,7 +402,8 @@ CONFIG_NETFILTER=y
# IP: Netfilter Configuration
#
CONFIG_IP_NF_CONNTRACK=m
-# CONFIG_IP_NF_CT_ACCT is not set
+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
@@ -397,6 +432,9 @@ CONFIG_IP_NF_MATCH_OWNER=m
CONFIG_IP_NF_MATCH_ADDRTYPE=m
CONFIG_IP_NF_MATCH_REALM=m
CONFIG_IP_NF_MATCH_SCTP=m
+CONFIG_IP_NF_MATCH_COMMENT=m
+CONFIG_IP_NF_MATCH_CONNMARK=m
+CONFIG_IP_NF_MATCH_HASHLIMIT=m
CONFIG_IP_NF_FILTER=m
CONFIG_IP_NF_TARGET_REJECT=m
CONFIG_IP_NF_TARGET_LOG=m
@@ -419,13 +457,13 @@ 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
-CONFIG_IP_NF_COMPAT_IPCHAINS=m
-CONFIG_IP_NF_COMPAT_IPFWADM=m
CONFIG_XFRM=y
CONFIG_XFRM_USER=m
@@ -446,7 +484,6 @@ CONFIG_LLC=y
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
#
# QoS and/or fair queueing
@@ -512,7 +549,6 @@ CONFIG_E100=y
# CONFIG_EPIC100 is not set
# CONFIG_SUNDANCE is not set
# CONFIG_VIA_RHINE is not set
-# CONFIG_VIA_VELOCITY is not set
#
# Ethernet (1000 Mbit)
@@ -527,6 +563,7 @@ CONFIG_E1000=y
# CONFIG_YELLOWFIN is not set
# CONFIG_R8169 is not set
# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
CONFIG_TIGON3=y
#
@@ -536,6 +573,7 @@ CONFIG_IXGB=m
# CONFIG_IXGB_NAPI is not set
CONFIG_S2IO=m
# CONFIG_S2IO_NAPI is not set
+# CONFIG_2BUFF_MODE is not set
#
# Token Ring devices
@@ -556,6 +594,7 @@ CONFIG_IBMOL=y
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
+# CONFIG_PLIP is not set
CONFIG_PPP=m
# CONFIG_PPP_MULTILINK is not set
# CONFIG_PPP_FILTER is not set
@@ -588,7 +627,7 @@ CONFIG_INPUT=y
# Userland interfaces
#
CONFIG_INPUT_MOUSEDEV=y
-CONFIG_INPUT_MOUSEDEV_PSAUX=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
@@ -605,7 +644,9 @@ 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 is not set
+CONFIG_SERIO_LIBPS2=y
# CONFIG_SERIO_RAW is not set
#
@@ -624,7 +665,7 @@ CONFIG_MOUSE_PS2=y
# CONFIG_INPUT_JOYSTICK is not set
# CONFIG_INPUT_TOUCHSCREEN is not set
CONFIG_INPUT_MISC=y
-# CONFIG_INPUT_PCSPKR is not set
+CONFIG_INPUT_PCSPKR=m
# CONFIG_INPUT_UINPUT is not set
#
@@ -653,6 +694,9 @@ CONFIG_SERIAL_ICOM=m
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_PRINTER is not set
+# CONFIG_PPDEV is not set
+# CONFIG_TIPAR is not set
CONFIG_HVC_CONSOLE=y
CONFIG_HVCS=m
@@ -674,7 +718,6 @@ CONFIG_HVCS=m
#
# Ftape, the floppy tape device driver
#
-# CONFIG_AGP is not set
# CONFIG_DRM is not set
CONFIG_RAW_DRIVER=y
CONFIG_MAX_RAW_DEVS=1024
@@ -703,7 +746,9 @@ CONFIG_I2C_ALGOBIT=y
# CONFIG_I2C_I801 is not set
# CONFIG_I2C_I810 is not set
# CONFIG_I2C_ISA is not set
+# CONFIG_I2C_MPC is not set
# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_PARPORT is not set
# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_PROSAVAGE is not set
# CONFIG_I2C_SAVAGE4 is not set
@@ -711,6 +756,7 @@ CONFIG_I2C_ALGOBIT=y
# CONFIG_I2C_SIS5595 is not set
# CONFIG_I2C_SIS630 is not set
# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_STUB is not set
# CONFIG_I2C_VIA is not set
# CONFIG_I2C_VIAPRO is not set
# CONFIG_I2C_VOODOO3 is not set
@@ -722,20 +768,25 @@ CONFIG_I2C_ALGOBIT=y
# CONFIG_I2C_SENSOR is not set
# CONFIG_SENSORS_ADM1021 is not set
# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ASB100 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_FSCHER is not set
# CONFIG_SENSORS_GL518SM is not set
# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
# CONFIG_SENSORS_LM75 is not set
# CONFIG_SENSORS_LM77 is not set
# CONFIG_SENSORS_LM78 is not set
# CONFIG_SENSORS_LM80 is not set
# CONFIG_SENSORS_LM83 is not set
# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
# CONFIG_SENSORS_SMSC47M1 is not set
# CONFIG_SENSORS_VIA686A is not set
# CONFIG_SENSORS_W83781D is not set
@@ -778,6 +829,7 @@ CONFIG_I2C_ALGOBIT=y
#
CONFIG_FB=y
CONFIG_FB_MODE_HELPERS=y
+# CONFIG_FB_TILEBLITTING is not set
# CONFIG_FB_CIRRUS is not set
# CONFIG_FB_PM2 is not set
# CONFIG_FB_CYBER2000 is not set
@@ -790,8 +842,7 @@ CONFIG_FB_OF=y
CONFIG_FB_MATROX=y
CONFIG_FB_MATROX_MILLENIUM=y
CONFIG_FB_MATROX_MYSTIQUE=y
-CONFIG_FB_MATROX_G450=y
-CONFIG_FB_MATROX_G100=y
+CONFIG_FB_MATROX_G=y
# CONFIG_FB_MATROX_I2C is not set
CONFIG_FB_MATROX_MULTIHEAD=y
# CONFIG_FB_RADEON_OLD is not set
@@ -800,6 +851,7 @@ 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
@@ -825,6 +877,11 @@ CONFIG_LOGO=y
CONFIG_LOGO_LINUX_MONO=y
CONFIG_LOGO_LINUX_VGA16=y
CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=m
+CONFIG_BACKLIGHT_DEVICE=y
+CONFIG_LCD_CLASS_DEVICE=m
+CONFIG_LCD_DEVICE=y
#
# Sound
@@ -844,6 +901,8 @@ 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
@@ -853,6 +912,7 @@ CONFIG_USB_EHCI_HCD=y
# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
CONFIG_USB_OHCI_HCD=y
# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
#
# USB Device Class drivers
@@ -860,6 +920,10 @@ CONFIG_USB_OHCI_HCD=y
# CONFIG_USB_BLUETOOTH_TTY is not set
# CONFIG_USB_ACM is not set
# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_DEBUG is not set
# CONFIG_USB_STORAGE_RW_DETECT is not set
@@ -873,7 +937,7 @@ CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_JUMPSHOT is not set
#
-# USB Human Interface Devices (HID)
+# USB Input Devices
#
CONFIG_USB_HID=y
CONFIG_USB_HIDINPUT=y
@@ -893,7 +957,6 @@ CONFIG_USB_HIDDEV=y
#
# CONFIG_USB_MDC800 is not set
# CONFIG_USB_MICROTEK is not set
-# CONFIG_USB_HPUSBSCSI is not set
#
# USB Multimedia devices
@@ -905,7 +968,7 @@ CONFIG_USB_HIDDEV=y
#
#
-# USB Network adaptors
+# USB Network Adapters
#
# CONFIG_USB_CATC is not set
# CONFIG_USB_KAWETH is not set
@@ -916,6 +979,7 @@ CONFIG_USB_HIDDEV=y
#
# USB port drivers
#
+# CONFIG_USB_USS720 is not set
#
# USB Serial Converter support
@@ -927,32 +991,51 @@ CONFIG_USB_HIDDEV=y
#
# CONFIG_USB_EMI62 is not set
# CONFIG_USB_EMI26 is not set
-# CONFIG_USB_TIGL 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_TEST is not set
#
+# USB ATM/DSL drivers
+#
+
+#
# USB Gadget Support
#
# 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
+
+#
# File systems
#
CONFIG_EXT2_FS=y
CONFIG_EXT2_FS_XATTR=y
CONFIG_EXT2_FS_POSIX_ACL=y
-# CONFIG_EXT2_FS_SECURITY is not set
+CONFIG_EXT2_FS_SECURITY=y
CONFIG_EXT3_FS=y
CONFIG_EXT3_FS_XATTR=y
CONFIG_EXT3_FS_POSIX_ACL=y
-# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_EXT3_FS_SECURITY=y
CONFIG_JBD=y
# CONFIG_JBD_DEBUG is not set
CONFIG_FS_MBCACHE=y
@@ -961,20 +1044,27 @@ CONFIG_REISERFS_FS=y
# CONFIG_REISERFS_PROC_INFO is not set
CONFIG_REISERFS_FS_XATTR=y
CONFIG_REISERFS_FS_POSIX_ACL=y
-# CONFIG_REISERFS_FS_SECURITY is not set
+CONFIG_REISERFS_FS_SECURITY=y
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 is not set
-# CONFIG_XFS_SECURITY is not set
+CONFIG_XFS_SECURITY=y
CONFIG_XFS_POSIX_ACL=y
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
CONFIG_AUTOFS_FS=m
# CONFIG_AUTOFS4_FS is not set
@@ -982,8 +1072,9 @@ CONFIG_AUTOFS_FS=m
# CD-ROM/DVD Filesystems
#
CONFIG_ISO9660_FS=y
-# CONFIG_JOLIET is not set
-# CONFIG_ZISOFS is not set
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=y
CONFIG_UDF_FS=m
CONFIG_UDF_NLS=y
@@ -1005,8 +1096,10 @@ CONFIG_PROC_KCORE=y
CONFIG_SYSFS=y
# CONFIG_DEVFS_FS is not set
CONFIG_DEVPTS_FS_XATTR=y
-# CONFIG_DEVPTS_FS_SECURITY is not set
+CONFIG_DEVPTS_FS_SECURITY=y
CONFIG_TMPFS=y
+CONFIG_TMPFS_XATTR=y
+CONFIG_TMPFS_SECURITY=y
CONFIG_HUGETLBFS=y
CONFIG_HUGETLB_PAGE=y
CONFIG_RAMFS=y
@@ -1035,13 +1128,13 @@ CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
CONFIG_NFS_V4=y
# CONFIG_NFS_DIRECTIO is not set
-CONFIG_NFSD=m
+CONFIG_NFSD=y
CONFIG_NFSD_V3=y
CONFIG_NFSD_V4=y
CONFIG_NFSD_TCP=y
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
-CONFIG_EXPORTFS=m
+CONFIG_EXPORTFS=y
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=y
CONFIG_RPCSEC_GSS_KRB5=y
@@ -1051,6 +1144,7 @@ CONFIG_CIFS=m
# CONFIG_CIFS_STATS is not set
CONFIG_CIFS_XATTR=y
CONFIG_CIFS_POSIX=y
+# CONFIG_CIFS_EXPERIMENTAL is not set
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
# CONFIG_AFS_FS is not set
@@ -1116,21 +1210,25 @@ CONFIG_OPROFILE=y
#
CONFIG_DEBUG_KERNEL=y
CONFIG_MAGIC_SYSRQ=y
+# CONFIG_SCHEDSTATS is not set
# CONFIG_DEBUG_SLAB 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=y
CONFIG_DEBUG_STACKOVERFLOW=y
+# CONFIG_KPROBES is not set
CONFIG_DEBUG_STACK_USAGE=y
CONFIG_DEBUGGER=y
CONFIG_XMON=y
CONFIG_XMON_DEFAULT=y
# CONFIG_PPCDBG is not set
CONFIG_IRQSTACKS=y
-# CONFIG_SCHEDSTATS is not set
#
# Security options
#
+# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
#
@@ -1144,7 +1242,7 @@ CONFIG_CRYPTO_MD5=y
CONFIG_CRYPTO_SHA1=m
CONFIG_CRYPTO_SHA256=m
CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_WHIRLPOOL=m
+CONFIG_CRYPTO_WP512=m
CONFIG_CRYPTO_DES=y
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_TWOFISH=m
@@ -1155,12 +1253,17 @@ CONFIG_CRYPTO_CAST6=m
CONFIG_CRYPTO_TEA=m
CONFIG_CRYPTO_ARC4=m
CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
CONFIG_CRYPTO_DEFLATE=m
CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_CRC32C=m
CONFIG_CRYPTO_TEST=m
#
+# Hardware crypto devices
+#
+
+#
# Library routines
#
CONFIG_CRC_CCITT=m
diff --git a/arch/ppc64/defconfig b/arch/ppc64/defconfig
index cdee0276b87e1..537b1cc82eab0 100644
--- a/arch/ppc64/defconfig
+++ b/arch/ppc64/defconfig
@@ -1,9 +1,12 @@
#
# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-rc3-bk6
+# Wed Feb 9 23:34:51 2005
#
CONFIG_64BIT=y
CONFIG_MMU=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_GENERIC_ISA_DMA=y
CONFIG_HAVE_DEC_LOCK=y
CONFIG_EARLY_PRINTK=y
@@ -16,27 +19,35 @@ CONFIG_FORCE_MAX_ZONEORDER=13
#
CONFIG_EXPERIMENTAL=y
CONFIG_CLEAN_COMPILE=y
-CONFIG_STANDALONE=y
+CONFIG_LOCK_KERNEL=y
#
# General setup
#
+CONFIG_LOCALVERSION=""
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
CONFIG_LOG_BUF_SHIFT=17
CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
# CONFIG_EMBEDDED is not set
CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
CONFIG_FUTEX=y
CONFIG_EPOLL=y
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+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
#
# Loadable module support
@@ -45,28 +56,40 @@ CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
CONFIG_OBSOLETE_MODPARM=y
-# CONFIG_MODVERSIONS is not set
-# CONFIG_KMOD is not set
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_KMOD=y
CONFIG_STOP_MACHINE=y
+CONFIG_SYSVIPC_COMPAT=y
#
# Platform support
#
# CONFIG_PPC_ISERIES is not set
+CONFIG_PPC_MULTIPLATFORM=y
CONFIG_PPC_PSERIES=y
+CONFIG_PPC_PMAC=y
+CONFIG_PPC_MAPLE=y
CONFIG_PPC=y
CONFIG_PPC64=y
CONFIG_PPC_OF=y
CONFIG_ALTIVEC=y
-# CONFIG_PPC_PMAC is not set
-# CONFIG_BOOTX_TEXT is not set
+CONFIG_PPC_SPLPAR=y
+CONFIG_IBMVIO=y
+CONFIG_U3_DART=y
+CONFIG_MPIC_BROKEN_U3=y
+CONFIG_PPC_PMAC64=y
+CONFIG_BOOTX_TEXT=y
# CONFIG_POWER4_ONLY is not set
-# CONFIG_IOMMU_VMERGE is not set
+CONFIG_IOMMU_VMERGE=y
CONFIG_SMP=y
-CONFIG_IRQ_ALL_CPUS=y
CONFIG_NR_CPUS=32
-# CONFIG_HMT is not set
-# CONFIG_DISCONTIGMEM is not set
+CONFIG_DISCONTIGMEM=y
+# CONFIG_NUMA is not set
+# CONFIG_SCHED_SMT is not set
+# CONFIG_PREEMPT is not set
+CONFIG_EEH=y
+CONFIG_GENERIC_HARDIRQS=y
CONFIG_PPC_RTAS=y
CONFIG_RTAS_FLASH=m
CONFIG_SCANLOG=m
@@ -78,14 +101,19 @@ CONFIG_LPARCFG=y
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-CONFIG_PCI_LEGACY_PROC=y
-CONFIG_PCI_NAMES=y
+CONFIG_BINFMT_MISC=m
+# CONFIG_PCI_LEGACY_PROC is not set
+# CONFIG_PCI_NAMES is not set
+CONFIG_HOTPLUG_CPU=y
#
-# PCMCIA/CardBus support
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
#
-# CONFIG_PCMCIA is not set
#
# PCI Hotplug Support
@@ -93,7 +121,6 @@ CONFIG_PCI_NAMES=y
CONFIG_HOTPLUG_PCI=m
# CONFIG_HOTPLUG_PCI_FAKE is not set
# CONFIG_HOTPLUG_PCI_CPCI is not set
-# CONFIG_HOTPLUG_PCI_PCIE is not set
# CONFIG_HOTPLUG_PCI_SHPC is not set
CONFIG_HOTPLUG_PCI_RPA=m
CONFIG_HOTPLUG_PCI_RPA_DLPAR=m
@@ -107,7 +134,9 @@ CONFIG_PROC_DEVICETREE=y
#
# Generic Driver Options
#
-CONFIG_FW_LOADER=m
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
# CONFIG_DEBUG_DRIVER is not set
#
@@ -118,7 +147,14 @@ CONFIG_FW_LOADER=m
#
# Parallel port support
#
-# CONFIG_PARPORT is not set
+CONFIG_PARPORT=m
+CONFIG_PARPORT_PC=m
+CONFIG_PARPORT_PC_CML1=m
+# CONFIG_PARPORT_SERIAL is not set
+# CONFIG_PARPORT_PC_FIFO is not set
+# CONFIG_PARPORT_PC_SUPERIO is not set
+# CONFIG_PARPORT_OTHER is not set
+# CONFIG_PARPORT_1284 is not set
#
# Plug and Play support
@@ -128,17 +164,32 @@ CONFIG_FW_LOADER=m
# Block devices
#
CONFIG_BLK_DEV_FD=y
+# CONFIG_PARIDE is not set
# CONFIG_BLK_CPQ_DA is not set
# CONFIG_BLK_CPQ_CISS_DA is not set
# CONFIG_BLK_DEV_DAC960 is not set
# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
CONFIG_BLK_DEV_NBD=m
-# CONFIG_BLK_DEV_CARMEL is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=65536
CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
#
# ATA/ATAPI/MFM/RLL support
@@ -149,15 +200,14 @@ 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_IDEDISK_STROKE is not set
CONFIG_BLK_DEV_IDECD=y
# 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
-# CONFIG_IDE_TASKFILE_IO is not set
#
# IDE chipset support/bugfixes
@@ -173,7 +223,6 @@ 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_ADMA=y
# CONFIG_BLK_DEV_AEC62XX is not set
# CONFIG_BLK_DEV_ALI15X3 is not set
CONFIG_BLK_DEV_AMD74XX=y
@@ -194,6 +243,11 @@ CONFIG_BLK_DEV_AMD74XX=y
# 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 is not set
+# CONFIG_IDE_ARM is not set
CONFIG_BLK_DEV_IDEDMA=y
# CONFIG_IDEDMA_IVB is not set
CONFIG_IDEDMA_AUTO=y
@@ -219,7 +273,6 @@ CONFIG_CHR_DEV_SG=y
# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
#
CONFIG_SCSI_MULTI_LUN=y
-CONFIG_SCSI_REPORT_LUNS=y
CONFIG_SCSI_CONSTANTS=y
# CONFIG_SCSI_LOGGING is not set
@@ -228,33 +281,52 @@ CONFIG_SCSI_CONSTANTS=y
#
CONFIG_SCSI_SPI_ATTRS=y
CONFIG_SCSI_FC_ATTRS=y
+CONFIG_SCSI_ISCSI_ATTRS=m
#
# SCSI low-level drivers
#
# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
# CONFIG_SCSI_ACARD is not set
# CONFIG_SCSI_AACRAID is not set
# CONFIG_SCSI_AIC7XXX is not set
# CONFIG_SCSI_AIC7XXX_OLD is not set
# CONFIG_SCSI_AIC79XX is not set
-# CONFIG_SCSI_ADVANSYS is not set
-# CONFIG_SCSI_MEGARAID is not set
-# CONFIG_SCSI_SATA is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+CONFIG_SCSI_SATA=y
+# CONFIG_SCSI_SATA_AHCI is not set
+CONFIG_SCSI_SATA_SVW=y
+# CONFIG_SCSI_ATA_PIIX is not set
+# CONFIG_SCSI_SATA_NV 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_SIS is not set
+# CONFIG_SCSI_SATA_ULI is not set
+# CONFIG_SCSI_SATA_VIA is not set
+# CONFIG_SCSI_SATA_VITESSE is not set
# CONFIG_SCSI_BUSLOGIC is not set
-# CONFIG_SCSI_CPQFCTS is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_EATA is not set
# CONFIG_SCSI_EATA_PIO is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
# CONFIG_SCSI_GDTH is not set
# CONFIG_SCSI_IPS is not set
+CONFIG_SCSI_IBMVSCSI=y
+# CONFIG_SCSI_INITIO is not set
# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_PPA is not set
+# CONFIG_SCSI_IMM is not set
CONFIG_SCSI_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=y
+CONFIG_SCSI_IPR_TRACE=y
+CONFIG_SCSI_IPR_DUMP=y
# CONFIG_SCSI_QLOGIC_ISP is not set
# CONFIG_SCSI_QLOGIC_FC is not set
# CONFIG_SCSI_QLOGIC_1280 is not set
@@ -264,10 +336,9 @@ CONFIG_SCSI_QLA22XX=m
CONFIG_SCSI_QLA2300=m
CONFIG_SCSI_QLA2322=m
CONFIG_SCSI_QLA6312=m
-CONFIG_SCSI_QLA6322=m
# CONFIG_SCSI_DC395x is not set
# CONFIG_SCSI_DC390T is not set
-# CONFIG_SCSI_DEBUG is not set
+CONFIG_SCSI_DEBUG=m
#
# Multi-device support (RAID and LVM)
@@ -277,11 +348,16 @@ CONFIG_BLK_DEV_MD=y
CONFIG_MD_LINEAR=y
CONFIG_MD_RAID0=y
CONFIG_MD_RAID1=y
+CONFIG_MD_RAID10=y
CONFIG_MD_RAID5=y
-CONFIG_MD_RAID6=y
-# CONFIG_MD_MULTIPATH is not set
+CONFIG_MD_RAID6=m
+CONFIG_MD_MULTIPATH=m
+CONFIG_MD_FAULTY=m
CONFIG_BLK_DEV_DM=y
CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
#
# Fusion MPT device support
@@ -291,15 +367,48 @@ CONFIG_DM_CRYPT=m
#
# IEEE 1394 (FireWire) support
#
-# CONFIG_IEEE1394 is not set
+CONFIG_IEEE1394=y
+
+#
+# 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
+
+#
+# Device Drivers
+#
+# CONFIG_IEEE1394_PCILYNX is not set
+CONFIG_IEEE1394_OHCI1394=y
+
+#
+# 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=y
+CONFIG_IEEE1394_CMP=m
+CONFIG_IEEE1394_AMDTP=m
#
# I2O device support
#
+# CONFIG_I2O is not set
#
# Macintosh device drivers
#
+CONFIG_ADB=y
+CONFIG_ADB_PMU=y
+# CONFIG_PMAC_PBOOK is not set
+# CONFIG_PMAC_BACKLIGHT is not set
+# CONFIG_INPUT_ADBHID is not set
+CONFIG_THERM_PM72=y
#
# Networking support
@@ -322,19 +431,19 @@ CONFIG_NET_IPIP=y
# CONFIG_NET_IPGRE is not set
# CONFIG_IP_MROUTE is not set
# CONFIG_ARPD is not set
-CONFIG_INET_ECN=y
CONFIG_SYN_COOKIES=y
CONFIG_INET_AH=m
CONFIG_INET_ESP=m
CONFIG_INET_IPCOMP=m
+CONFIG_INET_TUNNEL=y
+# CONFIG_IP_TCPDIAG is not set
+# CONFIG_IP_TCPDIAG_IPV6 is not set
#
# IP: Virtual Server Configuration
#
# CONFIG_IP_VS is not set
# CONFIG_IPV6 is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
CONFIG_NETFILTER=y
# CONFIG_NETFILTER_DEBUG is not set
@@ -342,6 +451,9 @@ CONFIG_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
@@ -366,8 +478,17 @@ CONFIG_IP_NF_MATCH_HELPER=m
CONFIG_IP_NF_MATCH_STATE=m
CONFIG_IP_NF_MATCH_CONNTRACK=m
CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_REALM=m
+CONFIG_IP_NF_MATCH_SCTP=m
+CONFIG_IP_NF_MATCH_COMMENT=m
+CONFIG_IP_NF_MATCH_CONNMARK=m
+CONFIG_IP_NF_MATCH_HASHLIMIT=m
CONFIG_IP_NF_FILTER=m
CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=m
CONFIG_IP_NF_NAT=m
CONFIG_IP_NF_NAT_NEEDED=y
CONFIG_IP_NF_TARGET_MASQUERADE=m
@@ -385,24 +506,24 @@ 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_LOG=m
-CONFIG_IP_NF_TARGET_ULOG=m
-CONFIG_IP_NF_TARGET_TCPMSS=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
-CONFIG_IP_NF_COMPAT_IPCHAINS=m
-CONFIG_IP_NF_COMPAT_IPFWADM=m
CONFIG_XFRM=y
CONFIG_XFRM_USER=m
#
# SCTP Configuration (EXPERIMENTAL)
#
-CONFIG_IPV6_SCTP__=y
# 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_LLC=y
# CONFIG_LLC2 is not set
# CONFIG_IPX is not set
@@ -412,36 +533,42 @@ CONFIG_LLC=y
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
#
# QoS and/or fair queueing
#
# CONFIG_NET_SCHED is not set
+CONFIG_NET_CLS_ROUTE=y
#
# Network testing
#
# CONFIG_NET_PKTGEN is not set
+CONFIG_NETPOLL=y
+CONFIG_NETPOLL_RX=y
+CONFIG_NETPOLL_TRAP=y
+CONFIG_NET_POLL_CONTROLLER=y
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
#
# ARCnet devices
#
# CONFIG_ARCNET is not set
-CONFIG_DUMMY=m
-CONFIG_BONDING=m
-# CONFIG_EQUALIZER is not set
-CONFIG_TUN=m
#
# Ethernet (10 or 100Mbit)
#
CONFIG_NET_ETHERNET=y
CONFIG_MII=y
-# CONFIG_OAKNET is not set
# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNGEM is not set
+CONFIG_SUNGEM=y
CONFIG_NET_VENDOR_3COM=y
CONFIG_VORTEX=y
# CONFIG_TYPHOON is not set
@@ -451,6 +578,7 @@ CONFIG_VORTEX=y
#
# CONFIG_NET_TULIP is not set
# CONFIG_HP100 is not set
+CONFIG_IBMVETH=m
CONFIG_NET_PCI=y
CONFIG_PCNET32=y
# CONFIG_AMD8111_ETH is not set
@@ -483,8 +611,8 @@ CONFIG_E1000=y
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
# CONFIG_R8169 is not set
-# CONFIG_SIS190 is not set
# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
CONFIG_TIGON3=y
#
@@ -492,59 +620,40 @@ CONFIG_TIGON3=y
#
CONFIG_IXGB=m
# CONFIG_IXGB_NAPI is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-CONFIG_IBMVETH=m
-CONFIG_PPP=m
-# CONFIG_PPP_MULTILINK is not set
-# CONFIG_PPP_FILTER is not set
-CONFIG_PPP_ASYNC=m
-CONFIG_PPP_SYNC_TTY=m
-CONFIG_PPP_DEFLATE=m
-CONFIG_PPP_BSDCOMP=m
-CONFIG_PPPOE=m
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
+# CONFIG_S2IO is not set
#
# Token Ring devices
#
CONFIG_TR=y
CONFIG_IBMOL=y
-# CONFIG_IBMLS is not set
# CONFIG_3C359 is not set
# CONFIG_TMS380TR is not set
-# CONFIG_NET_FC is not set
-# CONFIG_SHAPER is not set
-CONFIG_NETCONSOLE=y
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
#
-# IrDA (infrared) support
+# Wireless LAN (non-hamradio)
#
-# CONFIG_IRDA is not set
+# CONFIG_NET_RADIO is not set
#
-# Bluetooth support
+# Wan interfaces
#
-# CONFIG_BT is not set
-CONFIG_NETPOLL=y
-CONFIG_NETPOLL_RX=y
-CONFIG_NETPOLL_TRAP=y
-CONFIG_NET_POLL_CONTROLLER=y
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PLIP is not set
+CONFIG_PPP=m
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPPOE=m
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
+CONFIG_NETCONSOLE=y
#
# ISDN subsystem
@@ -565,12 +674,12 @@ CONFIG_INPUT=y
# Userland interfaces
#
CONFIG_INPUT_MOUSEDEV=y
-CONFIG_INPUT_MOUSEDEV_PSAUX=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_EVDEV=m
# CONFIG_INPUT_EVBUG is not set
#
@@ -582,7 +691,10 @@ 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 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
#
# Input Device Drivers
@@ -590,15 +702,17 @@ CONFIG_SERIO_I8042=y
CONFIG_INPUT_KEYBOARD=y
CONFIG_KEYBOARD_ATKBD=y
# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
# CONFIG_KEYBOARD_XTKBD is not set
# CONFIG_KEYBOARD_NEWTON is not set
CONFIG_INPUT_MOUSE=y
CONFIG_MOUSE_PS2=y
# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_VSXXXAA is not set
# CONFIG_INPUT_JOYSTICK is not set
# CONFIG_INPUT_TOUCHSCREEN is not set
CONFIG_INPUT_MISC=y
-CONFIG_INPUT_PCSPKR=y
+CONFIG_INPUT_PCSPKR=m
# CONFIG_INPUT_UINPUT is not set
#
@@ -623,16 +737,16 @@ CONFIG_SERIAL_8250_NR_UARTS=4
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_PMACZILOG is not set
+CONFIG_SERIAL_ICOM=m
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
+CONFIG_PRINTER=m
+# CONFIG_LP_CONSOLE is not set
+# CONFIG_PPDEV is not set
+# CONFIG_TIPAR is not set
CONFIG_HVC_CONSOLE=y
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_QIC02_TAPE is not set
+CONFIG_HVCS=m
#
# IPMI
@@ -652,7 +766,6 @@ CONFIG_HVC_CONSOLE=y
#
# Ftape, the floppy tape device driver
#
-# CONFIG_AGP is not set
# CONFIG_DRM is not set
CONFIG_RAW_DRIVER=y
CONFIG_MAX_RAW_DEVS=256
@@ -661,25 +774,30 @@ CONFIG_MAX_RAW_DEVS=256
# I2C support
#
CONFIG_I2C=y
-# CONFIG_I2C_CHARDEV is not set
+CONFIG_I2C_CHARDEV=y
#
# I2C Algorithms
#
CONFIG_I2C_ALGOBIT=y
# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
#
# I2C Hardware Bus support
#
# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
# CONFIG_I2C_ALI15X3 is not set
# CONFIG_I2C_AMD756 is not set
-# CONFIG_I2C_AMD8111 is not set
+CONFIG_I2C_AMD8111=y
# CONFIG_I2C_I801 is not set
# CONFIG_I2C_I810 is not set
# CONFIG_I2C_ISA is not set
+CONFIG_I2C_KEYWEST=y
+# CONFIG_I2C_MPC is not set
# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_PARPORT is not set
# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_PROSAVAGE is not set
# CONFIG_I2C_SAVAGE4 is not set
@@ -687,33 +805,61 @@ CONFIG_I2C_ALGOBIT=y
# 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
#
-# I2C Hardware Sensors Chip support
+# Hardware Sensors Chip support
#
# CONFIG_I2C_SENSOR is not set
# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ASB100 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_FSCHER is not set
# CONFIG_SENSORS_GL518SM is not set
# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
# CONFIG_SENSORS_LM83 is not set
# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
# CONFIG_SENSORS_VIA686A is not set
# CONFIG_SENSORS_W83781D is not set
# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+
+#
+# Other I2C Chip support
+#
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
# CONFIG_I2C_DEBUG_CHIP is not set
#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
# Misc devices
#
@@ -731,20 +877,28 @@ CONFIG_I2C_ALGOBIT=y
# Graphics support
#
CONFIG_FB=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 is not set
+# CONFIG_FB_PLATINUM is not set
+# CONFIG_FB_VALKYRIE is not set
# CONFIG_FB_CT65550 is not set
+# CONFIG_FB_ASILIANT is not set
# CONFIG_FB_IMSTT is not set
-# CONFIG_FB_S3TRIO is not set
# CONFIG_FB_VGA16 is not set
-# CONFIG_FB_RIVA is not set
+CONFIG_FB_RIVA=y
+CONFIG_FB_RIVA_I2C=y
+# CONFIG_FB_RIVA_DEBUG is not set
CONFIG_FB_MATROX=y
CONFIG_FB_MATROX_MILLENIUM=y
CONFIG_FB_MATROX_MYSTIQUE=y
-CONFIG_FB_MATROX_G450=y
-CONFIG_FB_MATROX_G100=y
-# CONFIG_FB_MATROX_I2C is not set
+CONFIG_FB_MATROX_G=y
+CONFIG_FB_MATROX_I2C=m
+CONFIG_FB_MATROX_MAVEN=m
CONFIG_FB_MATROX_MULTIHEAD=y
# CONFIG_FB_RADEON_OLD is not set
CONFIG_FB_RADEON=y
@@ -752,6 +906,7 @@ 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
@@ -764,10 +919,8 @@ CONFIG_FB_RADEON_I2C=y
# Console display driver support
#
# CONFIG_VGA_CONSOLE is not set
-# CONFIG_MDA_CONSOLE is not set
CONFIG_DUMMY_CONSOLE=y
CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_PCI_CONSOLE=y
# CONFIG_FONTS is not set
CONFIG_FONT_8x8=y
CONFIG_FONT_8x16=y
@@ -779,6 +932,11 @@ CONFIG_LOGO=y
CONFIG_LOGO_LINUX_MONO=y
CONFIG_LOGO_LINUX_VGA16=y
CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_DEVICE=y
+CONFIG_LCD_CLASS_DEVICE=y
+CONFIG_LCD_DEVICE=y
#
# Sound
@@ -797,13 +955,19 @@ CONFIG_USB=y
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
#
CONFIG_USB_EHCI_HCD=y
+# CONFIG_USB_EHCI_SPLIT_ISO is not set
+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
CONFIG_USB_OHCI_HCD=y
# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
#
# USB Device Class drivers
@@ -811,8 +975,13 @@ CONFIG_USB_OHCI_HCD=y
# CONFIG_USB_BLUETOOTH_TTY is not set
# CONFIG_USB_ACM is not set
# CONFIG_USB_PRINTER is not set
-CONFIG_USB_STORAGE=y
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=m
# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_RW_DETECT=y
# CONFIG_USB_STORAGE_DATAFAB is not set
# CONFIG_USB_STORAGE_FREECOM is not set
# CONFIG_USB_STORAGE_ISD200 is not set
@@ -823,7 +992,7 @@ CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_JUMPSHOT is not set
#
-# USB Human Interface Devices (HID)
+# USB Input Devices
#
CONFIG_USB_HID=y
CONFIG_USB_HIDINPUT=y
@@ -833,14 +1002,16 @@ CONFIG_USB_HIDDEV=y
# CONFIG_USB_WACOM is not set
# CONFIG_USB_KBTAB is not set
# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_EGALAX is not set
# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
#
# USB Imaging devices
#
# CONFIG_USB_MDC800 is not set
# CONFIG_USB_MICROTEK is not set
-# CONFIG_USB_HPUSBSCSI is not set
#
# USB Multimedia devices
@@ -852,17 +1023,18 @@ CONFIG_USB_HIDDEV=y
#
#
-# USB Network adaptors
+# USB Network Adapters
#
# CONFIG_USB_CATC is not set
# CONFIG_USB_KAWETH is not set
-# CONFIG_USB_PEGASUS is not set
+CONFIG_USB_PEGASUS=y
# CONFIG_USB_RTL8150 is not set
# CONFIG_USB_USBNET is not set
#
# USB port drivers
#
+# CONFIG_USB_USS720 is not set
#
# USB Serial Converter support
@@ -874,50 +1046,81 @@ CONFIG_USB_HIDDEV=y
#
# CONFIG_USB_EMI62 is not set
# CONFIG_USB_EMI26 is not set
-# CONFIG_USB_TIGL 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_TEST is not set
#
+# USB ATM/DSL drivers
+#
+
+#
# USB Gadget Support
#
# 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
+
+#
# File systems
#
CONFIG_EXT2_FS=y
CONFIG_EXT2_FS_XATTR=y
CONFIG_EXT2_FS_POSIX_ACL=y
-# CONFIG_EXT2_FS_SECURITY is not set
+CONFIG_EXT2_FS_SECURITY=y
CONFIG_EXT3_FS=y
CONFIG_EXT3_FS_XATTR=y
CONFIG_EXT3_FS_POSIX_ACL=y
-# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_EXT3_FS_SECURITY=y
CONFIG_JBD=y
# CONFIG_JBD_DEBUG is not set
CONFIG_FS_MBCACHE=y
CONFIG_REISERFS_FS=y
# CONFIG_REISERFS_CHECK is not set
# CONFIG_REISERFS_PROC_INFO is not set
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
CONFIG_JFS_FS=y
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 is not set
-# CONFIG_XFS_SECURITY is not set
+CONFIG_XFS_SECURITY=y
CONFIG_XFS_POSIX_ACL=y
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
# CONFIG_QUOTA is not set
-CONFIG_AUTOFS_FS=m
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=y
# CONFIG_AUTOFS4_FS is not set
#
@@ -927,6 +1130,7 @@ CONFIG_ISO9660_FS=y
# CONFIG_JOLIET is not set
# CONFIG_ZISOFS is not set
CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
#
# DOS/FAT/NT Filesystems
@@ -934,6 +1138,8 @@ CONFIG_UDF_FS=m
CONFIG_FAT_FS=y
CONFIG_MSDOS_FS=y
CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
# CONFIG_NTFS_FS is not set
#
@@ -941,10 +1147,13 @@ CONFIG_VFAT_FS=y
#
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
# CONFIG_DEVFS_FS is not set
CONFIG_DEVPTS_FS_XATTR=y
-# CONFIG_DEVPTS_FS_SECURITY is not set
+CONFIG_DEVPTS_FS_SECURITY=y
CONFIG_TMPFS=y
+CONFIG_TMPFS_XATTR=y
+CONFIG_TMPFS_SECURITY=y
CONFIG_HUGETLBFS=y
CONFIG_HUGETLB_PAGE=y
CONFIG_RAMFS=y
@@ -954,8 +1163,8 @@ CONFIG_RAMFS=y
#
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_HFSPLUS_FS is not set
+CONFIG_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
@@ -973,18 +1182,23 @@ CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
CONFIG_NFS_V4=y
# CONFIG_NFS_DIRECTIO is not set
-CONFIG_NFSD=y
+CONFIG_NFSD=m
CONFIG_NFSD_V3=y
CONFIG_NFSD_V4=y
CONFIG_NFSD_TCP=y
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
-CONFIG_EXPORTFS=y
+CONFIG_EXPORTFS=m
CONFIG_SUNRPC=y
-CONFIG_SUNRPC_GSS=m
-CONFIG_RPCSEC_GSS_KRB5=m
+CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
+CONFIG_RPCSEC_GSS_SPKM3=m
# CONFIG_SMB_FS is not set
CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+# CONFIG_CIFS_EXPERIMENTAL is not set
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
# CONFIG_AFS_FS is not set
@@ -992,51 +1206,66 @@ CONFIG_CIFS=m
#
# Partition Types
#
-# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
#
# Native Language Support
#
CONFIG_NLS=y
CONFIG_NLS_DEFAULT="iso8859-1"
-# CONFIG_NLS_CODEPAGE_437 is not set
-# CONFIG_NLS_CODEPAGE_737 is not set
-# CONFIG_NLS_CODEPAGE_775 is not set
-# CONFIG_NLS_CODEPAGE_850 is not set
-# CONFIG_NLS_CODEPAGE_852 is not set
-# CONFIG_NLS_CODEPAGE_855 is not set
-# CONFIG_NLS_CODEPAGE_857 is not set
-# CONFIG_NLS_CODEPAGE_860 is not set
-# CONFIG_NLS_CODEPAGE_861 is not set
-# CONFIG_NLS_CODEPAGE_862 is not set
-# CONFIG_NLS_CODEPAGE_863 is not set
-# CONFIG_NLS_CODEPAGE_864 is not set
-# CONFIG_NLS_CODEPAGE_865 is not set
-# CONFIG_NLS_CODEPAGE_866 is not set
-# CONFIG_NLS_CODEPAGE_869 is not set
-# CONFIG_NLS_CODEPAGE_936 is not set
-# CONFIG_NLS_CODEPAGE_950 is not set
-# CONFIG_NLS_CODEPAGE_932 is not set
-# CONFIG_NLS_CODEPAGE_949 is not set
-# CONFIG_NLS_CODEPAGE_874 is not set
-# CONFIG_NLS_ISO8859_8 is not set
-# CONFIG_NLS_CODEPAGE_1250 is not set
-# CONFIG_NLS_CODEPAGE_1251 is not set
-# CONFIG_NLS_ISO8859_1 is not set
-# CONFIG_NLS_ISO8859_2 is not set
-# CONFIG_NLS_ISO8859_3 is not set
-# CONFIG_NLS_ISO8859_4 is not set
-# CONFIG_NLS_ISO8859_5 is not set
-# CONFIG_NLS_ISO8859_6 is not set
-# CONFIG_NLS_ISO8859_7 is not set
-# CONFIG_NLS_ISO8859_9 is not set
-# CONFIG_NLS_ISO8859_13 is not set
-# CONFIG_NLS_ISO8859_14 is not set
-# CONFIG_NLS_ISO8859_15 is not set
-# CONFIG_NLS_KOI8_R is not set
-# CONFIG_NLS_KOI8_U is not set
-# CONFIG_NLS_UTF8 is not set
+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
#
# Profiling support
@@ -1048,19 +1277,26 @@ CONFIG_OPROFILE=y
# Kernel hacking
#
CONFIG_DEBUG_KERNEL=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB 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=y
CONFIG_DEBUG_STACKOVERFLOW=y
+# CONFIG_KPROBES is not set
CONFIG_DEBUG_STACK_USAGE=y
-# CONFIG_DEBUG_SLAB is not set
-CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUGGER=y
CONFIG_XMON=y
-CONFIG_XMON_DEFAULT=y
+# CONFIG_XMON_DEFAULT is not set
# CONFIG_PPCDBG is not set
-# CONFIG_DEBUG_INFO is not set
+CONFIG_IRQSTACKS=y
#
# Security options
#
+# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
#
@@ -1070,24 +1306,36 @@ CONFIG_CRYPTO=y
CONFIG_CRYPTO_HMAC=y
CONFIG_CRYPTO_NULL=m
CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_MD5=y
CONFIG_CRYPTO_SHA1=m
CONFIG_CRYPTO_SHA256=m
CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_DES=y
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_TWOFISH=m
CONFIG_CRYPTO_SERPENT=m
CONFIG_CRYPTO_AES=m
CONFIG_CRYPTO_CAST5=m
CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
CONFIG_CRYPTO_TEST=m
#
+# Hardware crypto devices
+#
+
+#
# Library routines
#
+CONFIG_CRC_CCITT=m
CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=m
diff --git a/arch/ppc64/kernel/LparData.c b/arch/ppc64/kernel/LparData.c
index bfda45cf801d3..badc5a4436148 100644
--- a/arch/ppc64/kernel/LparData.c
+++ b/arch/ppc64/kernel/LparData.c
@@ -45,7 +45,7 @@ struct HvReleaseData hvReleaseData = {
.xSize = sizeof(struct HvReleaseData),
.xVpdAreasPtrOffset = offsetof(struct naca_struct, xItVpdAreas),
.xSlicNacaAddr = &naca, /* 64-bit Naca address */
- .xMsNucDataOffset = 0x6000, /* offset of LparMap within loadarea (see head.S) */
+ .xMsNucDataOffset = 0x4800, /* offset of LparMap within loadarea (see head.S) */
.xTagsMode = 1, /* tags inactive */
.xAddressSize = 0, /* 64 bit */
.xNoSharedProcs = 0, /* shared processors */
@@ -224,6 +224,7 @@ struct ItVpdAreas itVpdAreas = {
};
struct msChunks msChunks;
+EXPORT_SYMBOL(msChunks);
/* Depending on whether this is called from iSeries or pSeries setup
* code, the location of the msChunks struct may or may not have
diff --git a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile
index 09ddd507418d1..96d90b0c5119e 100644
--- a/arch/ppc64/kernel/Makefile
+++ b/arch/ppc64/kernel/Makefile
@@ -11,7 +11,8 @@ obj-y := setup.o entry.o traps.o irq.o idle.o dma.o \
udbg.o binfmt_elf32.o sys_ppc32.o ioctl32.o \
ptrace32.o signal32.o rtc.o init_task.o \
lmb.o cputable.o cpu_setup_power4.o idle_power4.o \
- iommu.o sysfs.o
+ iommu.o sysfs.o vdso.o pmc.o
+obj-y += vdso32/ vdso64/
obj-$(CONFIG_PPC_OF) += of_device.o
@@ -30,7 +31,7 @@ obj-$(CONFIG_PPC_ISERIES) += iSeries_irq.o \
obj-$(CONFIG_PPC_MULTIPLATFORM) += nvram.o i8259.o prom_init.o prom.o mpic.o
obj-$(CONFIG_PPC_PSERIES) += pSeries_pci.o pSeries_lpar.o pSeries_hvCall.o \
- pSeries_nvram.o rtasd.o ras.o \
+ pSeries_nvram.o rtasd.o ras.o pSeries_reconfig.o \
xics.o rtas.o pSeries_setup.o pSeries_iommu.o
obj-$(CONFIG_EEH) += eeh.o
@@ -38,7 +39,7 @@ obj-$(CONFIG_PROC_FS) += proc_ppc64.o
obj-$(CONFIG_RTAS_FLASH) += rtas_flash.o
obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_MODULES) += module.o ppc_ksyms.o
-obj-$(CONFIG_PPC_RTAS) += rtas-proc.o
+obj-$(CONFIG_RTAS_PROC) += rtas-proc.o
obj-$(CONFIG_SCANLOG) += scanlog.o
obj-$(CONFIG_VIOPATH) += viopath.o
obj-$(CONFIG_LPARCFG) += lparcfg.o
diff --git a/arch/ppc64/kernel/align.c b/arch/ppc64/kernel/align.c
index 853b3ae7435c9..330e7ef814278 100644
--- a/arch/ppc64/kernel/align.c
+++ b/arch/ppc64/kernel/align.c
@@ -238,7 +238,7 @@ fix_alignment(struct pt_regs *regs)
dsisr = regs->dsisr;
- if (cur_cpu_spec->cpu_features & CPU_FTR_NODSISRALIGN) {
+ if (cpu_has_feature(CPU_FTR_NODSISRALIGN)) {
unsigned int real_instr;
if (__get_user(real_instr, (unsigned int __user *)regs->nip))
return 0;
@@ -273,7 +273,7 @@ fix_alignment(struct pt_regs *regs)
/* Verify the address of the operand */
if (user_mode(regs)) {
- if (verify_area((flags & ST? VERIFY_WRITE: VERIFY_READ), addr, nb))
+ if (!access_ok((flags & ST? VERIFY_WRITE: VERIFY_READ), addr, nb))
return -EFAULT; /* bad address */
}
diff --git a/arch/ppc64/kernel/asm-offsets.c b/arch/ppc64/kernel/asm-offsets.c
index 11a85558d0dac..0094ac79a18c6 100644
--- a/arch/ppc64/kernel/asm-offsets.c
+++ b/arch/ppc64/kernel/asm-offsets.c
@@ -22,6 +22,7 @@
#include <linux/types.h>
#include <linux/mman.h>
#include <linux/mm.h>
+#include <linux/time.h>
#include <linux/hardirq.h>
#include <asm/io.h>
#include <asm/page.h>
@@ -35,6 +36,8 @@
#include <asm/rtas.h>
#include <asm/cputable.h>
#include <asm/cache.h>
+#include <asm/systemcfg.h>
+#include <asm/compat.h>
#define DEFINE(sym, val) \
asm volatile("\n->" #sym " %0 " #val : : "i" (val))
@@ -167,5 +170,24 @@ int main(void)
DEFINE(CPU_SPEC_FEATURES, offsetof(struct cpu_spec, cpu_features));
DEFINE(CPU_SPEC_SETUP, offsetof(struct cpu_spec, cpu_setup));
+ /* systemcfg offsets for use by vdso */
+ DEFINE(CFG_TB_ORIG_STAMP, offsetof(struct systemcfg, tb_orig_stamp));
+ DEFINE(CFG_TB_TICKS_PER_SEC, offsetof(struct systemcfg, tb_ticks_per_sec));
+ DEFINE(CFG_TB_TO_XS, offsetof(struct systemcfg, tb_to_xs));
+ DEFINE(CFG_STAMP_XSEC, offsetof(struct systemcfg, stamp_xsec));
+ DEFINE(CFG_TB_UPDATE_COUNT, offsetof(struct systemcfg, tb_update_count));
+ DEFINE(CFG_TZ_MINUTEWEST, offsetof(struct systemcfg, tz_minuteswest));
+ DEFINE(CFG_TZ_DSTTIME, offsetof(struct systemcfg, tz_dsttime));
+ DEFINE(CFG_SYSCALL_MAP32, offsetof(struct systemcfg, syscall_map_32));
+ DEFINE(CFG_SYSCALL_MAP64, offsetof(struct systemcfg, syscall_map_64));
+
+ /* timeval/timezone offsets for use by vdso */
+ DEFINE(TVAL64_TV_SEC, offsetof(struct timeval, tv_sec));
+ DEFINE(TVAL64_TV_USEC, offsetof(struct timeval, tv_usec));
+ DEFINE(TVAL32_TV_SEC, offsetof(struct compat_timeval, tv_sec));
+ DEFINE(TVAL32_TV_USEC, offsetof(struct compat_timeval, tv_usec));
+ DEFINE(TZONE_TZ_MINWEST, offsetof(struct timezone, tz_minuteswest));
+ DEFINE(TZONE_TZ_DSTTIME, offsetof(struct timezone, tz_dsttime));
+
return 0;
}
diff --git a/arch/ppc64/kernel/cputable.c b/arch/ppc64/kernel/cputable.c
index 44fa14e4f511d..8644a8648058e 100644
--- a/arch/ppc64/kernel/cputable.c
+++ b/arch/ppc64/kernel/cputable.c
@@ -17,9 +17,12 @@
#include <linux/sched.h>
#include <linux/threads.h>
#include <linux/init.h>
+#include <linux/module.h>
+
#include <asm/cputable.h>
struct cpu_spec* cur_cpu_spec = NULL;
+EXPORT_SYMBOL(cur_cpu_spec);
/* NOTE:
* Unlike ppc32, ppc64 will only call this once for the boot CPU, it's
diff --git a/arch/ppc64/kernel/dma.c b/arch/ppc64/kernel/dma.c
index c08725182c21b..ce714c9271344 100644
--- a/arch/ppc64/kernel/dma.c
+++ b/arch/ppc64/kernel/dma.c
@@ -13,14 +13,23 @@
#include <asm/scatterlist.h>
#include <asm/bug.h>
-int dma_supported(struct device *dev, u64 mask)
+static struct dma_mapping_ops *get_dma_ops(struct device *dev)
{
if (dev->bus == &pci_bus_type)
- return pci_dma_supported(to_pci_dev(dev), mask);
+ return &pci_dma_ops;
#ifdef CONFIG_IBMVIO
if (dev->bus == &vio_bus_type)
- return vio_dma_supported(to_vio_dev(dev), mask);
-#endif /* CONFIG_IBMVIO */
+ return &vio_dma_ops;
+#endif
+ return NULL;
+}
+
+int dma_supported(struct device *dev, u64 mask)
+{
+ struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
+
+ if (dma_ops)
+ return dma_ops->dma_supported(dev, mask);
BUG();
return 0;
}
@@ -32,7 +41,7 @@ int dma_set_mask(struct device *dev, u64 dma_mask)
return pci_set_dma_mask(to_pci_dev(dev), dma_mask);
#ifdef CONFIG_IBMVIO
if (dev->bus == &vio_bus_type)
- return vio_set_dma_mask(to_vio_dev(dev), dma_mask);
+ return -EIO;
#endif /* CONFIG_IBMVIO */
BUG();
return 0;
@@ -40,14 +49,12 @@ int dma_set_mask(struct device *dev, u64 dma_mask)
EXPORT_SYMBOL(dma_set_mask);
void *dma_alloc_coherent(struct device *dev, size_t size,
- dma_addr_t *dma_handle, int flag)
+ dma_addr_t *dma_handle, unsigned int __nocast flag)
{
- if (dev->bus == &pci_bus_type)
- return pci_alloc_consistent(to_pci_dev(dev), size, dma_handle);
-#ifdef CONFIG_IBMVIO
- if (dev->bus == &vio_bus_type)
- return vio_alloc_consistent(to_vio_dev(dev), size, dma_handle);
-#endif /* CONFIG_IBMVIO */
+ struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
+
+ if (dma_ops)
+ return dma_ops->alloc_coherent(dev, size, dma_handle, flag);
BUG();
return NULL;
}
@@ -56,12 +63,10 @@ EXPORT_SYMBOL(dma_alloc_coherent);
void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
dma_addr_t dma_handle)
{
- if (dev->bus == &pci_bus_type)
- pci_free_consistent(to_pci_dev(dev), size, cpu_addr, dma_handle);
-#ifdef CONFIG_IBMVIO
- else if (dev->bus == &vio_bus_type)
- vio_free_consistent(to_vio_dev(dev), size, cpu_addr, dma_handle);
-#endif /* CONFIG_IBMVIO */
+ struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
+
+ if (dma_ops)
+ dma_ops->free_coherent(dev, size, cpu_addr, dma_handle);
else
BUG();
}
@@ -70,12 +75,10 @@ EXPORT_SYMBOL(dma_free_coherent);
dma_addr_t dma_map_single(struct device *dev, void *cpu_addr, size_t size,
enum dma_data_direction direction)
{
- if (dev->bus == &pci_bus_type)
- return pci_map_single(to_pci_dev(dev), cpu_addr, size, (int)direction);
-#ifdef CONFIG_IBMVIO
- if (dev->bus == &vio_bus_type)
- return vio_map_single(to_vio_dev(dev), cpu_addr, size, direction);
-#endif /* CONFIG_IBMVIO */
+ struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
+
+ if (dma_ops)
+ return dma_ops->map_single(dev, cpu_addr, size, direction);
BUG();
return (dma_addr_t)0;
}
@@ -84,12 +87,10 @@ EXPORT_SYMBOL(dma_map_single);
void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
enum dma_data_direction direction)
{
- if (dev->bus == &pci_bus_type)
- pci_unmap_single(to_pci_dev(dev), dma_addr, size, (int)direction);
-#ifdef CONFIG_IBMVIO
- else if (dev->bus == &vio_bus_type)
- vio_unmap_single(to_vio_dev(dev), dma_addr, size, direction);
-#endif /* CONFIG_IBMVIO */
+ struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
+
+ if (dma_ops)
+ dma_ops->unmap_single(dev, dma_addr, size, direction);
else
BUG();
}
@@ -99,12 +100,11 @@ dma_addr_t dma_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size,
enum dma_data_direction direction)
{
- if (dev->bus == &pci_bus_type)
- return pci_map_page(to_pci_dev(dev), page, offset, size, (int)direction);
-#ifdef CONFIG_IBMVIO
- if (dev->bus == &vio_bus_type)
- return vio_map_page(to_vio_dev(dev), page, offset, size, direction);
-#endif /* CONFIG_IBMVIO */
+ struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
+
+ if (dma_ops)
+ return dma_ops->map_single(dev,
+ (page_address(page) + offset), size, direction);
BUG();
return (dma_addr_t)0;
}
@@ -113,12 +113,10 @@ EXPORT_SYMBOL(dma_map_page);
void dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
enum dma_data_direction direction)
{
- if (dev->bus == &pci_bus_type)
- pci_unmap_page(to_pci_dev(dev), dma_address, size, (int)direction);
-#ifdef CONFIG_IBMVIO
- else if (dev->bus == &vio_bus_type)
- vio_unmap_page(to_vio_dev(dev), dma_address, size, direction);
-#endif /* CONFIG_IBMVIO */
+ struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
+
+ if (dma_ops)
+ dma_ops->unmap_single(dev, dma_address, size, direction);
else
BUG();
}
@@ -127,12 +125,10 @@ EXPORT_SYMBOL(dma_unmap_page);
int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
enum dma_data_direction direction)
{
- if (dev->bus == &pci_bus_type)
- return pci_map_sg(to_pci_dev(dev), sg, nents, (int)direction);
-#ifdef CONFIG_IBMVIO
- if (dev->bus == &vio_bus_type)
- return vio_map_sg(to_vio_dev(dev), sg, nents, direction);
-#endif /* CONFIG_IBMVIO */
+ struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
+
+ if (dma_ops)
+ return dma_ops->map_sg(dev, sg, nents, direction);
BUG();
return 0;
}
@@ -141,12 +137,10 @@ EXPORT_SYMBOL(dma_map_sg);
void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
enum dma_data_direction direction)
{
- if (dev->bus == &pci_bus_type)
- pci_unmap_sg(to_pci_dev(dev), sg, nhwentries, (int)direction);
-#ifdef CONFIG_IBMVIO
- else if (dev->bus == &vio_bus_type)
- vio_unmap_sg(to_vio_dev(dev), sg, nhwentries, direction);
-#endif /* CONFIG_IBMVIO */
+ struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
+
+ if (dma_ops)
+ dma_ops->unmap_sg(dev, sg, nhwentries, direction);
else
BUG();
}
diff --git a/arch/ppc64/kernel/eeh.c b/arch/ppc64/kernel/eeh.c
index 0f8d1c44a1d37..d63d41f3eecf7 100644
--- a/arch/ppc64/kernel/eeh.c
+++ b/arch/ppc64/kernel/eeh.c
@@ -824,7 +824,7 @@ void eeh_add_device_early(struct device_node *dn)
struct pci_controller *phb;
struct eeh_early_enable_info info;
- if (!dn || !eeh_subsystem_enabled)
+ if (!dn)
return;
phb = dn->phb;
if (NULL == phb || 0 == phb->buid) {
diff --git a/arch/ppc64/kernel/entry.S b/arch/ppc64/kernel/entry.S
index 0741f9e0ae40f..d3604056e1a9c 100644
--- a/arch/ppc64/kernel/entry.S
+++ b/arch/ppc64/kernel/entry.S
@@ -616,7 +616,7 @@ unrecov_restore:
bl .unrecoverable_exception
b unrecov_restore
-#ifdef CONFIG_PPC_PSERIES
+#ifdef CONFIG_PPC_RTAS
/*
* On CHRP, the Run-Time Abstraction Services (RTAS) have to be
* called with the MMU off.
@@ -753,7 +753,7 @@ _STATIC(rtas_restore_regs)
mtlr r0
blr /* return to caller */
-#endif /* CONFIG_PPC_PSERIES */
+#endif /* CONFIG_PPC_RTAS */
#ifdef CONFIG_PPC_MULTIPLATFORM
diff --git a/arch/ppc64/kernel/head.S b/arch/ppc64/kernel/head.S
index f62494bec4a9a..fe05f3fbf9d05 100644
--- a/arch/ppc64/kernel/head.S
+++ b/arch/ppc64/kernel/head.S
@@ -37,6 +37,7 @@
#include <asm/bug.h>
#include <asm/cputable.h>
#include <asm/setup.h>
+#include <asm/hvcall.h>
#ifdef CONFIG_PPC_ISERIES
#define DO_SOFT_DISABLE
@@ -45,7 +46,6 @@
/*
* hcall interface to pSeries LPAR
*/
-#define HVSC .long 0x44000022
#define H_SET_ASR 0x30
/*
@@ -54,7 +54,6 @@
* 0x0100 - 0x2fff : pSeries Interrupt prologs
* 0x3000 - 0x3fff : Interrupt support
* 0x4000 - 0x4fff : NACA
- * 0x5000 - 0x5fff : SystemCfg
* 0x6000 : iSeries and common interrupt prologs
* 0x9000 - 0x9fff : Initial segment table
*/
@@ -517,16 +516,7 @@ __end_interrupts:
.globl naca
naca:
.llong itVpdAreas
-#endif
-
- . = SYSTEMCFG_PHYS_ADDR
- .globl __start_systemcfg
-__start_systemcfg:
- . = (SYSTEMCFG_PHYS_ADDR + PAGE_SIZE)
- .globl __end_systemcfg
-__end_systemcfg:
-#ifdef CONFIG_PPC_ISERIES
/*
* The iSeries LPAR map is at this fixed address
* so that the HvReleaseData structure can address
@@ -536,6 +526,8 @@ __end_systemcfg:
* VSID generation algorithm. See include/asm/mmu_context.h.
*/
+ . = 0x4800
+
.llong 2 /* # ESIDs to be mapped by hypervisor */
.llong 1 /* # memory ranges to be mapped by hypervisor */
.llong STAB0_PAGE /* Page # of segment table within load area */
@@ -958,11 +950,12 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SLB)
* accessing a userspace segment (even from the kernel). We assume
* kernel addresses always have the high bit set.
*/
- rlwinm r4,r4,32-23,29,29 /* DSISR_STORE -> _PAGE_RW */
+ rlwinm r4,r4,32-25+9,31-9,31-9 /* DSISR_STORE -> _PAGE_RW */
rotldi r0,r3,15 /* Move high bit into MSR_PR posn */
orc r0,r12,r0 /* MSR_PR | ~high_bit */
rlwimi r4,r0,32-13,30,30 /* becomes _PAGE_USER access bit */
ori r4,r4,1 /* add _PAGE_PRESENT */
+ rlwimi r4,r5,22+2,31-2,31-2 /* Set _PAGE_EXEC if trap is 0x400 */
/*
* On iSeries, we soft-disable interrupts here, then
@@ -1264,10 +1257,6 @@ _STATIC(__start_initialization_iSeries)
addi r2,r2,0x4000
addi r2,r2,0x4000
- LOADADDR(r9,systemcfg)
- SET_REG_TO_CONST(r4, SYSTEMCFG_VIRT_ADDR)
- std r4,0(r9) /* set the systemcfg pointer */
-
bl .iSeries_early_setup
/* relocation is on at this point */
@@ -1772,7 +1761,7 @@ _GLOBAL(__secondary_start)
sc /* HvCall_setASR */
#else
/* set the ASR */
- li r3,SYSTEMCFG_PHYS_ADDR /* r3 = ptr to systemcfg */
+ ld r3,systemcfg@got(r2) /* r3 = ptr to systemcfg */
lwz r3,PLATFORM(r3) /* r3 = platform flags */
cmpldi r3,PLATFORM_PSERIES_LPAR
bne 98f
@@ -1861,12 +1850,6 @@ _STATIC(start_here_multiplatform)
ori r6,r6,MSR_RI
mtmsrd r6 /* RI on */
- /* setup the systemcfg pointer which is needed by *tab_initialize */
- LOADADDR(r6,systemcfg)
- sub r6,r6,r26 /* addr of the variable systemcfg */
- li r27,SYSTEMCFG_PHYS_ADDR
- std r27,0(r6) /* set the value of systemcfg */
-
#ifdef CONFIG_HMT
/* Start up the second thread on cpu 0 */
mfspr r3,PVR
@@ -1941,7 +1924,7 @@ _STATIC(start_here_multiplatform)
/* set the ASR */
ld r3,PACASTABREAL(r13)
ori r4,r3,1 /* turn on valid bit */
- li r3,SYSTEMCFG_PHYS_ADDR /* r3 = ptr to systemcfg */
+ ld r3,systemcfg@got(r2) /* r3 = ptr to systemcfg */
lwz r3,PLATFORM(r3) /* r3 = platform flags */
cmpldi r3,PLATFORM_PSERIES_LPAR
bne 98f
@@ -1960,7 +1943,7 @@ _STATIC(start_here_multiplatform)
mtasr r4 /* set the stab location */
99:
/* Set SDR1 (hash table pointer) */
- li r3,SYSTEMCFG_PHYS_ADDR /* r3 = ptr to systemcfg */
+ ld r3,systemcfg@got(r2) /* r3 = ptr to systemcfg */
lwz r3,PLATFORM(r3) /* r3 = platform flags */
/* Test if bit 0 is set (LPAR bit) */
andi. r3,r3,0x1
@@ -1998,11 +1981,6 @@ _STATIC(start_here_common)
li r3,0
bl .do_cpu_ftr_fixups
- /* setup the systemcfg pointer */
- LOADADDR(r9,systemcfg)
- SET_REG_TO_CONST(r8, SYSTEMCFG_VIRT_ADDR)
- std r8,0(r9)
-
LOADADDR(r26, boot_cpuid)
lwz r26,0(r26)
diff --git a/arch/ppc64/kernel/i8259.c b/arch/ppc64/kernel/i8259.c
index 9bea66770ab07..74dcfd68fc75c 100644
--- a/arch/ppc64/kernel/i8259.c
+++ b/arch/ppc64/kernel/i8259.c
@@ -131,14 +131,11 @@ static void i8259_end_irq(unsigned int irq)
}
struct hw_interrupt_type i8259_pic = {
- " i8259 ",
- NULL,
- NULL,
- i8259_unmask_irq,
- i8259_mask_irq,
- i8259_mask_and_ack_irq,
- i8259_end_irq,
- NULL
+ .typename = " i8259 ",
+ .enable = i8259_unmask_irq,
+ .disable = i8259_mask_irq,
+ .ack = i8259_mask_and_ack_irq,
+ .end = i8259_end_irq,
};
void __init i8259_init(int offset)
diff --git a/arch/ppc64/kernel/iSeries_htab.c b/arch/ppc64/kernel/iSeries_htab.c
index b1177b476cbdb..aa9e8fdd1a4fe 100644
--- a/arch/ppc64/kernel/iSeries_htab.c
+++ b/arch/ppc64/kernel/iSeries_htab.c
@@ -144,6 +144,10 @@ static long iSeries_hpte_updatepp(unsigned long slot, unsigned long newpp,
HvCallHpt_get(&hpte, slot);
if ((hpte.dw0.dw0.avpn == avpn) && (hpte.dw0.dw0.v)) {
+ /*
+ * Hypervisor expects bits as NPPP, which is
+ * different from how they are mapped in our PP.
+ */
HvCallHpt_setPp(slot, (newpp & 0x3) | ((newpp & 0x4) << 1));
iSeries_hunlock(slot);
return 0;
diff --git a/arch/ppc64/kernel/iSeries_pci.c b/arch/ppc64/kernel/iSeries_pci.c
index ffe54e1bd8971..bd4c2554f1a04 100644
--- a/arch/ppc64/kernel/iSeries_pci.c
+++ b/arch/ppc64/kernel/iSeries_pci.c
@@ -610,6 +610,10 @@ static int iSeries_pci_read_config(struct pci_bus *bus, unsigned int devfn,
if (node == NULL)
return PCIBIOS_DEVICE_NOT_FOUND;
+ if (offset > 255) {
+ *val = ~0;
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ }
fn = hv_cfg_read_func[(size - 1) & 3];
HvCall3Ret16(fn, &ret, node->DsaAddr.DsaAddr, offset, 0);
@@ -636,6 +640,8 @@ static int iSeries_pci_write_config(struct pci_bus *bus, unsigned int devfn,
if (node == NULL)
return PCIBIOS_DEVICE_NOT_FOUND;
+ if (offset > 255)
+ return PCIBIOS_BAD_REGISTER_NUMBER;
fn = hv_cfg_write_func[(size - 1) & 3];
ret = HvCall4(fn, node->DsaAddr.DsaAddr, offset, val, 0);
diff --git a/arch/ppc64/kernel/iSeries_setup.c b/arch/ppc64/kernel/iSeries_setup.c
index 7191f57d88563..da20120f22617 100644
--- a/arch/ppc64/kernel/iSeries_setup.c
+++ b/arch/ppc64/kernel/iSeries_setup.c
@@ -15,7 +15,7 @@
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
-
+
#undef DEBUG
#include <linux/config.h>
@@ -39,6 +39,7 @@
#include <asm/mmu_context.h>
#include <asm/cputable.h>
#include <asm/sections.h>
+#include <asm/iommu.h>
#include <asm/time.h>
#include "iSeries_setup.h"
@@ -57,6 +58,7 @@
#include <asm/iSeries/iSeries_proc.h>
#include <asm/iSeries/mf.h>
#include <asm/iSeries/HvLpEvent.h>
+#include <asm/iSeries/iSeries_irq.h>
extern void hvlog(char *fmt, ...);
@@ -72,7 +74,6 @@ extern void ppcdbg_initialize(void);
static void build_iSeries_Memory_Map(void);
static void setup_iSeries_cache_sizes(void);
static void iSeries_bolt_kernel(unsigned long saddr, unsigned long eaddr);
-extern void iSeries_setup_arch(void);
extern void iSeries_pci_final_fixup(void);
/* Global Variables */
@@ -108,8 +109,8 @@ struct MemoryBlock {
* and return the number of physical blocks and fill in the array of
* block data.
*/
-unsigned long iSeries_process_Condor_mainstore_vpd(struct MemoryBlock *mb_array,
- unsigned long max_entries)
+static unsigned long iSeries_process_Condor_mainstore_vpd(
+ struct MemoryBlock *mb_array, unsigned long max_entries)
{
unsigned long holeFirstChunk, holeSizeChunks;
unsigned long numMemoryBlocks = 1;
@@ -154,7 +155,7 @@ unsigned long iSeries_process_Condor_mainstore_vpd(struct MemoryBlock *mb_array,
#define MaxSegmentAdrRangeBlocks 128
#define MaxAreaRangeBlocks 4
-unsigned long iSeries_process_Regatta_mainstore_vpd(
+static unsigned long iSeries_process_Regatta_mainstore_vpd(
struct MemoryBlock *mb_array, unsigned long max_entries)
{
struct IoHriMainStoreSegment5 *msVpdP =
@@ -246,7 +247,7 @@ unsigned long iSeries_process_Regatta_mainstore_vpd(
printk(" Bitmap range: %016lx - %016lx\n"
" Absolute range: %016lx - %016lx\n",
mb_array[i].logicalStart,
- mb_array[i].logicalEnd,
+ mb_array[i].logicalEnd,
mb_array[i].absStart, mb_array[i].absEnd);
mb_array[i].absStart = addr_to_chunk(mb_array[i].absStart &
0x000fffffffffffff);
@@ -261,13 +262,13 @@ unsigned long iSeries_process_Regatta_mainstore_vpd(
return numSegmentBlocks;
}
-unsigned long iSeries_process_mainstore_vpd(struct MemoryBlock *mb_array,
+static unsigned long iSeries_process_mainstore_vpd(struct MemoryBlock *mb_array,
unsigned long max_entries)
{
unsigned long i;
unsigned long mem_blocks = 0;
- if (cur_cpu_spec->cpu_features & CPU_FTR_SLB)
+ if (cpu_has_feature(CPU_FTR_SLB))
mem_blocks = iSeries_process_Regatta_mainstore_vpd(mb_array,
max_entries);
else
@@ -284,7 +285,7 @@ unsigned long iSeries_process_mainstore_vpd(struct MemoryBlock *mb_array,
return mem_blocks;
}
-static void __init iSeries_parse_cmdline(void)
+static void __init iSeries_get_cmdline(void)
{
char *p, *q;
@@ -302,8 +303,10 @@ static void __init iSeries_parse_cmdline(void)
*p = 0;
}
-/*static*/ void __init iSeries_init_early(void)
+static void __init iSeries_init_early(void)
{
+ extern unsigned long memory_limit;
+
DBG(" -> iSeries_init_early()\n");
ppcdbg_initialize();
@@ -351,11 +354,36 @@ static void __init iSeries_parse_cmdline(void)
*/
build_iSeries_Memory_Map();
+ iSeries_get_cmdline();
+
+ /* Save unparsed command line copy for /proc/cmdline */
+ strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE);
+
+ /* Parse early parameters, in particular mem=x */
+ parse_early_param();
+
+ if (memory_limit) {
+ if (memory_limit < systemcfg->physicalMemorySize)
+ systemcfg->physicalMemorySize = memory_limit;
+ else {
+ printk("Ignoring mem=%lu >= ram_top.\n", memory_limit);
+ memory_limit = 0;
+ }
+ }
+
+ /* Bolt kernel mappings for all of memory (or just a bit if we've got a limit) */
+ iSeries_bolt_kernel(0, systemcfg->physicalMemorySize);
+
+ lmb_init();
+ lmb_add(0, systemcfg->physicalMemorySize);
+ lmb_analyze();
+ lmb_reserve(0, __pa(klimit));
+
/* Initialize machine-dependency vectors */
#ifdef CONFIG_SMP
smp_init_iSeries();
#endif
- if (itLpNaca.xPirEnvironMode == 0)
+ if (itLpNaca.xPirEnvironMode == 0)
piranha_simulator = 1;
/* Associate Lp Event Queue 0 with processor 0 */
@@ -376,30 +404,27 @@ static void __init iSeries_parse_cmdline(void)
initrd_start = initrd_end = 0;
#endif /* CONFIG_BLK_DEV_INITRD */
-
- iSeries_parse_cmdline();
-
DBG(" <- iSeries_init_early()\n");
}
/*
* The iSeries may have very large memories ( > 128 GB ) and a partition
* may get memory in "chunks" that may be anywhere in the 2**52 real
- * address space. The chunks are 256K in size. To map this to the
- * memory model Linux expects, the AS/400 specific code builds a
+ * address space. The chunks are 256K in size. To map this to the
+ * memory model Linux expects, the AS/400 specific code builds a
* translation table to translate what Linux thinks are "physical"
- * addresses to the actual real addresses. This allows us to make
+ * addresses to the actual real addresses. This allows us to make
* it appear to Linux that we have contiguous memory starting at
* physical address zero while in fact this could be far from the truth.
- * To avoid confusion, I'll let the words physical and/or real address
- * apply to the Linux addresses while I'll use "absolute address" to
+ * To avoid confusion, I'll let the words physical and/or real address
+ * apply to the Linux addresses while I'll use "absolute address" to
* refer to the actual hardware real address.
*
- * build_iSeries_Memory_Map gets information from the Hypervisor and
+ * build_iSeries_Memory_Map gets information from the Hypervisor and
* looks at the Main Store VPD to determine the absolute addresses
* of the memory that has been assigned to our partition and builds
* a table used to translate Linux's physical addresses to these
- * absolute addresses. Absolute addresses are needed when
+ * absolute addresses. Absolute addresses are needed when
* communicating with the hypervisor (e.g. to build HPT entries)
*/
@@ -428,13 +453,13 @@ static void __init build_iSeries_Memory_Map(void)
* otherwise, it might not be returned by PLIC as the first
* chunks
*/
-
+
loadAreaFirstChunk = (u32)addr_to_chunk(itLpNaca.xLoadAreaAddr);
loadAreaSize = itLpNaca.xLoadAreaChunks;
/*
- * Only add the pages already mapped here.
- * Otherwise we might add the hpt pages
+ * Only add the pages already mapped here.
+ * Otherwise we might add the hpt pages
* The rest of the pages of the load area
* aren't in the HPT yet and can still
* be assigned an arbitrary physical address
@@ -446,7 +471,7 @@ static void __init build_iSeries_Memory_Map(void)
/*
* TODO Do we need to do something if the HPT is in the 64MB load area?
- * This would be required if the itLpNaca.xLoadAreaChunks includes
+ * This would be required if the itLpNaca.xLoadAreaChunks includes
* the HPT size
*/
@@ -454,11 +479,11 @@ static void __init build_iSeries_Memory_Map(void)
" absolute addr = %016lx\n",
chunk_to_addr(loadAreaFirstChunk));
printk("Load area size %dK\n", loadAreaSize * 256);
-
+
for (nextPhysChunk = 0; nextPhysChunk < loadAreaSize; ++nextPhysChunk)
msChunks.abs[nextPhysChunk] =
loadAreaFirstChunk + nextPhysChunk;
-
+
/*
* Get absolute address of our HPT and remember it so
* we won't map it to any physical address
@@ -475,7 +500,7 @@ static void __init build_iSeries_Memory_Map(void)
num_ptegs = hptSizePages *
(PAGE_SIZE / (sizeof(HPTE) * HPTES_PER_GROUP));
htab_hash_mask = num_ptegs - 1;
-
+
/*
* The actual hashed page table is in the hypervisor,
* we have no direct access
@@ -533,20 +558,12 @@ static void __init build_iSeries_Memory_Map(void)
}
/*
- * main store size (in chunks) is
+ * main store size (in chunks) is
* totalChunks - hptSizeChunks
- * which should be equal to
+ * which should be equal to
* nextPhysChunk
*/
systemcfg->physicalMemorySize = chunk_to_addr(nextPhysChunk);
-
- /* Bolt kernel mappings for all of memory */
- iSeries_bolt_kernel(0, systemcfg->physicalMemorySize);
-
- lmb_init();
- lmb_add(0, systemcfg->physicalMemorySize);
- lmb_analyze(); /* ?? */
- lmb_reserve(0, __pa(klimit));
}
/*
@@ -633,6 +650,10 @@ static void __init iSeries_bolt_kernel(unsigned long saddr, unsigned long eaddr)
unsigned long vpn = va >> PAGE_SHIFT;
unsigned long slot = HvCallHpt_findValid(&hpte, vpn);
+ /* Make non-kernel text non-executable */
+ if (!in_kernel_text(ea))
+ mode_rw |= HW_NO_EXEC;
+
if (hpte.dw0.dw0.v) {
/* HPTE exists, so just bolt it */
HvCallHpt_setSwBits(slot, 0x10, 0);
@@ -650,7 +671,7 @@ extern unsigned long ppc_tb_freq;
/*
* Document me.
*/
-void __init iSeries_setup_arch(void)
+static void __init iSeries_setup_arch(void)
{
void *eventStack;
unsigned procIx = get_paca()->lppaca.dyn_hv_phys_proc_index;
@@ -669,14 +690,14 @@ void __init iSeries_setup_arch(void)
*/
eventStack = alloc_bootmem_pages(LpEventStackSize);
memset(eventStack, 0, LpEventStackSize);
-
+
/* Invoke the hypervisor to initialize the event stack */
HvCallEvent_setLpEventStack(0, eventStack, LpEventStackSize);
/* Initialize fields in our Lp Event Queue */
xItLpQueue.xSlicEventStackPtr = (char *)eventStack;
xItLpQueue.xSlicCurEventPtr = (char *)eventStack;
- xItLpQueue.xSlicLastValidEventPtr = (char *)eventStack +
+ xItLpQueue.xSlicLastValidEventPtr = (char *)eventStack +
(LpEventStackSize - LpEventMaxSize);
xItLpQueue.xIndex = 0;
@@ -694,7 +715,7 @@ void __init iSeries_setup_arch(void)
tbFreqMhzHundreths = (tbFreqHz / 10000) - (tbFreqMhz * 100);
ppc_tb_freq = tbFreqHz;
- printk("Max logical processors = %d\n",
+ printk("Max logical processors = %d\n",
itVpdAreas.xSlicMaxLogicalProcs);
printk("Max physical processors = %d\n",
itVpdAreas.xSlicMaxPhysicalProcs);
@@ -706,7 +727,7 @@ void __init iSeries_setup_arch(void)
printk("Processor version = %x\n", systemcfg->processor);
}
-void iSeries_get_cpuinfo(struct seq_file *m)
+static void iSeries_get_cpuinfo(struct seq_file *m)
{
seq_printf(m, "machine\t\t: 64-bit iSeries Logical Partition\n");
}
@@ -715,7 +736,7 @@ void iSeries_get_cpuinfo(struct seq_file *m)
* Document me.
* and Implement me.
*/
-int iSeries_get_irq(struct pt_regs *regs)
+static int iSeries_get_irq(struct pt_regs *regs)
{
/* -2 means ignore this interrupt */
return -2;
@@ -724,7 +745,7 @@ int iSeries_get_irq(struct pt_regs *regs)
/*
* Document me.
*/
-void iSeries_restart(char *cmd)
+static void iSeries_restart(char *cmd)
{
mf_reboot();
}
@@ -732,7 +753,7 @@ void iSeries_restart(char *cmd)
/*
* Document me.
*/
-void iSeries_power_off(void)
+static void iSeries_power_off(void)
{
mf_power_off();
}
@@ -740,14 +761,11 @@ void iSeries_power_off(void)
/*
* Document me.
*/
-void iSeries_halt(void)
+static void iSeries_halt(void)
{
mf_power_off();
}
-/* JDH Hack */
-unsigned long jdh_time = 0;
-
extern void setup_default_decr(void);
/*
@@ -758,17 +776,17 @@ extern void setup_default_decr(void);
* and sets up the kernel timer decrementer based on that value.
*
*/
-void __init iSeries_calibrate_decr(void)
+static void __init iSeries_calibrate_decr(void)
{
unsigned long cyclesPerUsec;
struct div_result divres;
-
+
/* Compute decrementer (and TB) frequency in cycles/sec */
cyclesPerUsec = ppc_tb_freq / 1000000;
/*
* Set the amount to refresh the decrementer by. This
- * is the number of decrementer ticks it takes for
+ * is the number of decrementer ticks it takes for
* 1/HZ seconds.
*/
tb_ticks_per_jiffy = ppc_tb_freq / HZ;
@@ -793,7 +811,7 @@ void __init iSeries_calibrate_decr(void)
setup_default_decr();
}
-void __init iSeries_progress(char * st, unsigned short code)
+static void __init iSeries_progress(char * st, unsigned short code)
{
printk("Progress: [%04x] - %s\n", (unsigned)code, st);
if (!piranha_simulator && mf_initialized) {
@@ -825,7 +843,7 @@ static void __init iSeries_fixup_klimit(void)
}
}
-int __init iSeries_src_init(void)
+static int __init iSeries_src_init(void)
{
/* clear the progress line */
ppc_md.progress(" ", 0xffff);
diff --git a/arch/ppc64/kernel/iSeries_setup.h b/arch/ppc64/kernel/iSeries_setup.h
index 098041b4c6120..c6eb29a245ac0 100644
--- a/arch/ppc64/kernel/iSeries_setup.h
+++ b/arch/ppc64/kernel/iSeries_setup.h
@@ -19,19 +19,8 @@
#ifndef __ISERIES_SETUP_H__
#define __ISERIES_SETUP_H__
-extern void iSeries_setup_arch(void);
-extern void iSeries_setup_residual(struct seq_file *m, int cpu_id);
-extern void iSeries_get_cpuinfo(struct seq_file *m);
-extern void iSeries_init_IRQ(void);
-extern int iSeries_get_irq(struct pt_regs *regs);
-extern void iSeries_restart(char *cmd);
-extern void iSeries_power_off(void);
-extern void iSeries_halt(void);
-extern void iSeries_time_init(void);
extern void iSeries_get_boot_time(struct rtc_time *tm);
extern int iSeries_set_rtc_time(struct rtc_time *tm);
extern void iSeries_get_rtc_time(struct rtc_time *tm);
-extern void iSeries_calibrate_decr(void);
-extern void iSeries_progress( char *, unsigned short );
#endif /* __ISERIES_SETUP_H__ */
diff --git a/arch/ppc64/kernel/idle.c b/arch/ppc64/kernel/idle.c
index 398b4682127bf..6abc621d3ba0c 100644
--- a/arch/ppc64/kernel/idle.c
+++ b/arch/ppc64/kernel/idle.c
@@ -293,6 +293,10 @@ static int native_idle(void)
power4_idle();
if (need_resched())
schedule();
+
+ if (cpu_is_offline(_smp_processor_id()) &&
+ system_state == SYSTEM_RUNNING)
+ cpu_die();
}
return 0;
}
diff --git a/arch/ppc64/kernel/ioctl32.c b/arch/ppc64/kernel/ioctl32.c
index 94d1a05b78392..a8005db23ec58 100644
--- a/arch/ppc64/kernel/ioctl32.c
+++ b/arch/ppc64/kernel/ioctl32.c
@@ -39,7 +39,6 @@ IOCTL_TABLE_START
#include <linux/compat_ioctl.h>
#define DECLARES
#include "compat_ioctl.c"
-COMPATIBLE_IOCTL(TCSBRKP)
COMPATIBLE_IOCTL(TIOCSTART)
COMPATIBLE_IOCTL(TIOCSTOP)
COMPATIBLE_IOCTL(TIOCSLTC)
diff --git a/arch/ppc64/kernel/iommu.c b/arch/ppc64/kernel/iommu.c
index 0f0ba6b649933..344164681d2ce 100644
--- a/arch/ppc64/kernel/iommu.c
+++ b/arch/ppc64/kernel/iommu.c
@@ -513,8 +513,8 @@ void iommu_unmap_single(struct iommu_table *tbl, dma_addr_t dma_handle,
* Returns the virtual address of the buffer and sets dma_handle
* to the dma address (mapping) of the first page.
*/
-void *iommu_alloc_consistent(struct iommu_table *tbl, size_t size,
- dma_addr_t *dma_handle)
+void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size,
+ dma_addr_t *dma_handle, unsigned int __nocast flag)
{
void *ret = NULL;
dma_addr_t mapping;
@@ -538,7 +538,7 @@ void *iommu_alloc_consistent(struct iommu_table *tbl, size_t size,
return NULL;
/* Alloc enough pages (and possibly more) */
- ret = (void *)__get_free_pages(GFP_ATOMIC, order);
+ ret = (void *)__get_free_pages(flag, order);
if (!ret)
return NULL;
memset(ret, 0, size);
@@ -553,7 +553,7 @@ void *iommu_alloc_consistent(struct iommu_table *tbl, size_t size,
return ret;
}
-void iommu_free_consistent(struct iommu_table *tbl, size_t size,
+void iommu_free_coherent(struct iommu_table *tbl, size_t size,
void *vaddr, dma_addr_t dma_handle)
{
unsigned int npages;
diff --git a/arch/ppc64/kernel/irq.c b/arch/ppc64/kernel/irq.c
index 3a0f67c189981..4fd7f203c1e3e 100644
--- a/arch/ppc64/kernel/irq.c
+++ b/arch/ppc64/kernel/irq.c
@@ -61,6 +61,7 @@ extern void iSeries_smp_message_recv( struct pt_regs * );
#endif
extern irq_desc_t irq_desc[NR_IRQS];
+EXPORT_SYMBOL(irq_desc);
int distribute_irqs = 1;
int __irq_offset_value;
@@ -115,6 +116,35 @@ skip:
return 0;
}
+#ifdef CONFIG_HOTPLUG_CPU
+void fixup_irqs(cpumask_t map)
+{
+ unsigned int irq;
+ static int warned;
+
+ for_each_irq(irq) {
+ cpumask_t mask;
+
+ if (irq_desc[irq].status & IRQ_PER_CPU)
+ continue;
+
+ cpus_and(mask, irq_affinity[irq], map);
+ if (any_online_cpu(mask) == NR_CPUS) {
+ printk("Breaking affinity for irq %i\n", irq);
+ mask = map;
+ }
+ if (irq_desc[irq].handler->set_affinity)
+ irq_desc[irq].handler->set_affinity(irq, mask);
+ else if (irq_desc[irq].action && !(warned++))
+ printk("Cannot set affinity for irq %i\n", irq);
+ }
+
+ local_irq_enable();
+ mdelay(1);
+ local_irq_disable();
+}
+#endif
+
extern int noirqdebug;
/*
diff --git a/arch/ppc64/kernel/kprobes.c b/arch/ppc64/kernel/kprobes.c
index 522e7742ac00c..103daaf735734 100644
--- a/arch/ppc64/kernel/kprobes.c
+++ b/arch/ppc64/kernel/kprobes.c
@@ -71,7 +71,11 @@ static inline void disarm_kprobe(struct kprobe *p, struct pt_regs *regs)
static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
{
regs->msr |= MSR_SE;
- regs->nip = (unsigned long)&p->ainsn.insn;
+ /*single step inline if it a breakpoint instruction*/
+ if (p->opcode == BREAKPOINT_INSTRUCTION)
+ regs->nip = (unsigned long)p->addr;
+ else
+ regs->nip = (unsigned long)&p->ainsn.insn;
}
static inline int kprobe_handler(struct pt_regs *regs)
@@ -80,15 +84,18 @@ static inline int kprobe_handler(struct pt_regs *regs)
int ret = 0;
unsigned int *addr = (unsigned int *)regs->nip;
- /* We're in an interrupt, but this is clear and BUG()-safe. */
- preempt_disable();
-
/* Check we're not actually recursing */
if (kprobe_running()) {
/* We *are* holding lock here, so this is safe.
Disarm the probe we just hit, and ignore it. */
p = get_kprobe(addr);
if (p) {
+ if (kprobe_status == KPROBE_HIT_SS) {
+ regs->msr &= ~MSR_SE;
+ regs->msr |= kprobe_saved_msr;
+ unlock_kprobes();
+ goto no_kprobe;
+ }
disarm_kprobe(p, regs);
ret = 1;
} else {
@@ -105,9 +112,17 @@ static inline int kprobe_handler(struct pt_regs *regs)
p = get_kprobe(addr);
if (!p) {
unlock_kprobes();
-#if 0
if (*addr != BREAKPOINT_INSTRUCTION) {
/*
+ * PowerPC has multiple variants of the "trap"
+ * instruction. If the current instruction is a
+ * trap variant, it could belong to someone else
+ */
+ kprobe_opcode_t cur_insn = *addr;
+ if (IS_TW(cur_insn) || IS_TD(cur_insn) ||
+ IS_TWI(cur_insn) || IS_TDI(cur_insn))
+ goto no_kprobe;
+ /*
* The breakpoint instruction was removed right
* after we hit it. Another cpu has removed
* either a probepoint or a debugger breakpoint
@@ -116,7 +131,6 @@ static inline int kprobe_handler(struct pt_regs *regs)
*/
ret = 1;
}
-#endif
/* Not one of ours: let kernel handle it */
goto no_kprobe;
}
@@ -124,18 +138,21 @@ static inline int kprobe_handler(struct pt_regs *regs)
kprobe_status = KPROBE_HIT_ACTIVE;
current_kprobe = p;
kprobe_saved_msr = regs->msr;
- if (p->pre_handler(p, regs)) {
+ if (p->pre_handler && p->pre_handler(p, regs))
/* handler has already set things up, so skip ss setup */
return 1;
- }
ss_probe:
prepare_singlestep(p, regs);
kprobe_status = KPROBE_HIT_SS;
+ /*
+ * This preempt_disable() matches the preempt_enable_no_resched()
+ * in post_kprobe_handler().
+ */
+ preempt_disable();
return 1;
no_kprobe:
- preempt_enable_no_resched();
return ret;
}
@@ -208,27 +225,35 @@ int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val,
void *data)
{
struct die_args *args = (struct die_args *)data;
+ int ret = NOTIFY_DONE;
+
+ /*
+ * Interrupts are not disabled here. We need to disable
+ * preemption, because kprobe_running() uses smp_processor_id().
+ */
+ preempt_disable();
switch (val) {
case DIE_IABR_MATCH:
case DIE_DABR_MATCH:
case DIE_BPT:
if (kprobe_handler(args->regs))
- return NOTIFY_STOP;
+ ret = NOTIFY_STOP;
break;
case DIE_SSTEP:
if (post_kprobe_handler(args->regs))
- return NOTIFY_STOP;
+ ret = NOTIFY_STOP;
break;
case DIE_GPF:
case DIE_PAGE_FAULT:
if (kprobe_running() &&
kprobe_fault_handler(args->regs, args->trapnr))
- return NOTIFY_STOP;
+ ret = NOTIFY_STOP;
break;
default:
break;
}
- return NOTIFY_DONE;
+ preempt_enable();
+ return ret;
}
int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
@@ -246,7 +271,6 @@ int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
void jprobe_return(void)
{
- preempt_enable_no_resched();
asm volatile("trap" ::: "memory");
}
diff --git a/arch/ppc64/kernel/lmb.c b/arch/ppc64/kernel/lmb.c
index 56d7ba87fe608..d6c6bd03d2a42 100644
--- a/arch/ppc64/kernel/lmb.c
+++ b/arch/ppc64/kernel/lmb.c
@@ -344,3 +344,29 @@ lmb_abs_to_phys(unsigned long aa)
return pa;
}
+
+/*
+ * Truncate the lmb list to memory_limit if it's set
+ * You must call lmb_analyze() after this.
+ */
+void __init lmb_enforce_memory_limit(void)
+{
+ extern unsigned long memory_limit;
+ unsigned long i, limit;
+ struct lmb_region *mem = &(lmb.memory);
+
+ if (! memory_limit)
+ return;
+
+ limit = memory_limit;
+ for (i = 0; i < mem->cnt; i++) {
+ if (limit > mem->region[i].size) {
+ limit -= mem->region[i].size;
+ continue;
+ }
+
+ mem->region[i].size = limit;
+ mem->cnt = i + 1;
+ break;
+ }
+}
diff --git a/arch/ppc64/kernel/lparcfg.c b/arch/ppc64/kernel/lparcfg.c
index 860dea50599b1..a8fd32df848b7 100644
--- a/arch/ppc64/kernel/lparcfg.c
+++ b/arch/ppc64/kernel/lparcfg.c
@@ -33,8 +33,9 @@
#include <asm/cputable.h>
#include <asm/rtas.h>
#include <asm/system.h>
+#include <asm/time.h>
-#define MODULE_VERS "1.5"
+#define MODULE_VERS "1.6"
#define MODULE_NAME "lparcfg"
/* #define LPARCFG_DEBUG */
@@ -214,13 +215,20 @@ static void h_pic(unsigned long *pool_idle_time, unsigned long *num_procs)
}
static unsigned long get_purr(void);
-/* ToDo: get sum of purr across all processors. The purr collection code
- * is coming, but at this time is still problematic, so for now this
- * function will return 0.
- */
+
+/* Track sum of all purrs across all processors. This is used to further */
+/* calculate usage values by different applications */
+
static unsigned long get_purr(void)
{
unsigned long sum_purr = 0;
+ int cpu;
+ struct cpu_usage *cu;
+
+ for_each_cpu(cpu) {
+ cu = &per_cpu(cpu_usage_array, cpu);
+ sum_purr += cu->current_tb;
+ }
return sum_purr;
}
diff --git a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S
index ce597ba033882..90b41f48d21c0 100644
--- a/arch/ppc64/kernel/misc.S
+++ b/arch/ppc64/kernel/misc.S
@@ -292,6 +292,26 @@ _GLOBAL(flush_dcache_phys_range)
isync
blr
+_GLOBAL(flush_inval_dcache_range)
+ ld r10,PPC64_CACHES@toc(r2)
+ lwz r7,DCACHEL1LINESIZE(r10) /* Get dcache line size */
+ addi r5,r7,-1
+ andc r6,r3,r5 /* round low to line bdy */
+ subf r8,r6,r4 /* compute length */
+ add r8,r8,r5 /* ensure we get enough */
+ lwz r9,DCACHEL1LOGLINESIZE(r10)/* Get log-2 of dcache line size */
+ srw. r8,r8,r9 /* compute line count */
+ beqlr /* nothing to do? */
+ sync
+ isync
+ mtctr r8
+0: dcbf 0,r6
+ add r6,r6,r7
+ bdnz 0b
+ sync
+ isync
+ blr
+
/*
* Flush a particular page from the data cache to RAM.
@@ -660,10 +680,6 @@ _GLOBAL(kernel_thread)
ld r30,-16(r1)
blr
-#ifndef CONFIG_PPC_PSERIES /* hack hack hack */
-#define ppc_rtas sys_ni_syscall
-#endif
-
/* Why isn't this a) automatic, b) written in 'C'? */
.balign 8
_GLOBAL(sys_call_table32)
@@ -939,6 +955,7 @@ _GLOBAL(sys_call_table32)
.llong .sys32_add_key
.llong .sys32_request_key
.llong .compat_sys_keyctl
+ .llong .compat_sys_waitid
.balign 8
_GLOBAL(sys_call_table)
@@ -1214,3 +1231,4 @@ _GLOBAL(sys_call_table)
.llong .sys_add_key
.llong .sys_request_key /* 270 */
.llong .sys_keyctl
+ .llong .sys_waitid
diff --git a/arch/ppc64/kernel/module.c b/arch/ppc64/kernel/module.c
index 5bccbc5f07485..c683bf88e6905 100644
--- a/arch/ppc64/kernel/module.c
+++ b/arch/ppc64/kernel/module.c
@@ -102,7 +102,8 @@ void *module_alloc(unsigned long size)
{
if (size == 0)
return NULL;
- return vmalloc(size);
+
+ return vmalloc_exec(size);
}
/* Free memory returned from module_alloc */
diff --git a/arch/ppc64/kernel/nvram.c b/arch/ppc64/kernel/nvram.c
index 241ba3aecd0cb..b9069c2d1933b 100644
--- a/arch/ppc64/kernel/nvram.c
+++ b/arch/ppc64/kernel/nvram.c
@@ -89,7 +89,7 @@ static ssize_t dev_nvram_read(struct file *file, char __user *buf,
return -ENODEV;
size = ppc_md.nvram_size();
- if (verify_area(VERIFY_WRITE, buf, count))
+ if (!access_ok(VERIFY_WRITE, buf, count))
return -EFAULT;
if (*ppos >= size)
return 0;
@@ -129,7 +129,7 @@ static ssize_t dev_nvram_write(struct file *file, const char __user *buf,
return -ENODEV;
size = ppc_md.nvram_size();
- if (verify_area(VERIFY_READ, buf, count))
+ if (!access_ok(VERIFY_READ, buf, count))
return -EFAULT;
if (*ppos >= size)
return 0;
@@ -507,8 +507,8 @@ static int nvram_scan_partitions(void)
struct nvram_partition * tmp_part;
unsigned char c_sum;
char * header;
- long size;
int total_size;
+ int err;
if (ppc_md.nvram_size == NULL)
return -ENODEV;
@@ -522,29 +522,37 @@ static int nvram_scan_partitions(void)
while (cur_index < total_size) {
- size = ppc_md.nvram_read(header, NVRAM_HEADER_LEN, &cur_index);
- if (size != NVRAM_HEADER_LEN) {
+ err = ppc_md.nvram_read(header, NVRAM_HEADER_LEN, &cur_index);
+ if (err != NVRAM_HEADER_LEN) {
printk(KERN_ERR "nvram_scan_partitions: Error parsing "
"nvram partitions\n");
- kfree(header);
- return size;
+ goto out;
}
cur_index -= NVRAM_HEADER_LEN; /* nvram_read will advance us */
memcpy(&phead, header, NVRAM_HEADER_LEN);
+ err = 0;
c_sum = nvram_checksum(&phead);
- if (c_sum != phead.checksum)
- printk(KERN_WARNING "WARNING: nvram partition checksum "
- "was %02x, should be %02x!\n", phead.checksum, c_sum);
-
+ if (c_sum != phead.checksum) {
+ printk(KERN_WARNING "WARNING: nvram partition checksum"
+ " was %02x, should be %02x!\n",
+ phead.checksum, c_sum);
+ printk(KERN_WARNING "Terminating nvram partition scan\n");
+ goto out;
+ }
+ if (!phead.length) {
+ printk(KERN_WARNING "WARNING: nvram corruption "
+ "detected: 0-length partition\n");
+ goto out;
+ }
tmp_part = (struct nvram_partition *)
kmalloc(sizeof(struct nvram_partition), GFP_KERNEL);
+ err = -ENOMEM;
if (!tmp_part) {
printk(KERN_ERR "nvram_scan_partitions: kmalloc failed\n");
- kfree(header);
- return -ENOMEM;
+ goto out;
}
memcpy(&tmp_part->header, &phead, NVRAM_HEADER_LEN);
@@ -553,9 +561,11 @@ static int nvram_scan_partitions(void)
cur_index += phead.length * NVRAM_BLOCK_LEN;
}
+ err = 0;
+ out:
kfree(header);
- return 0;
+ return err;
}
static int __init nvram_init(void)
diff --git a/arch/ppc64/kernel/pSeries_hvCall.S b/arch/ppc64/kernel/pSeries_hvCall.S
index df604cfcf9d4b..0715d30380199 100644
--- a/arch/ppc64/kernel/pSeries_hvCall.S
+++ b/arch/ppc64/kernel/pSeries_hvCall.S
@@ -1,7 +1,6 @@
/*
* arch/ppc64/kernel/pSeries_hvCall.S
*
- *
* This file contains the generic code to perform a call to the
* pSeries LPAR hypervisor.
* NOTE: this file will go away when we move to inline this work.
@@ -11,133 +10,114 @@
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
-#include <linux/sys.h>
-#include <asm/unistd.h>
-#include <asm/errno.h>
+#include <asm/hvcall.h>
#include <asm/processor.h>
-#include <asm/page.h>
-#include <asm/cache.h>
#include <asm/ppc_asm.h>
-/*
- * hcall interface to pSeries LPAR
- */
-#define HVSC .long 0x44000022
-
-/* long plpar_hcall(unsigned long opcode, R3
- unsigned long arg1, R4
- unsigned long arg2, R5
- unsigned long arg3, R6
- unsigned long arg4, R7
- unsigned long *out1, R8
- unsigned long *out2, R9
- unsigned long *out3); R10
- */
+#define STK_PARM(i) (48 + ((i)-3)*8)
.text
+
+/* long plpar_hcall(unsigned long opcode, R3
+ unsigned long arg1, R4
+ unsigned long arg2, R5
+ unsigned long arg3, R6
+ unsigned long arg4, R7
+ unsigned long *out1, R8
+ unsigned long *out2, R9
+ unsigned long *out3); R10
+ */
_GLOBAL(plpar_hcall)
mfcr r0
- std r0,-8(r1)
- stdu r1,-32(r1)
- std r8,-8(r1) /* Save out ptrs. */
- std r9,-16(r1)
- std r10,-24(r1)
-
- HVSC /* invoke the hypervisor */
+ std r8,STK_PARM(r8)(r1) /* Save out ptrs */
+ std r9,STK_PARM(r9)(r1)
+ std r10,STK_PARM(r10)(r1)
- ld r10,-8(r1) /* Fetch r4-r7 ret args. */
- std r4,0(r10)
- ld r10,-16(r1)
- std r5,0(r10)
- ld r10,-24(r1)
- std r6,0(r10)
+ stw r0,8(r1)
+
+ HVSC /* invoke the hypervisor */
+
+ lwz r0,8(r1)
+
+ ld r8,STK_PARM(r8)(r1) /* Fetch r4-r6 ret args */
+ ld r9,STK_PARM(r9)(r1)
+ ld r10,STK_PARM(r10)(r1)
+ std r4,0(r8)
+ std r5,0(r9)
+ std r6,0(r10)
- ld r1,0(r1)
- ld r0,-8(r1)
mtcrf 0xff,r0
- blr /* return r3 = status */
+ blr /* return r3 = status */
/* Simple interface with no output values (other than status) */
_GLOBAL(plpar_hcall_norets)
mfcr r0
- std r0,-8(r1)
- HVSC /* invoke the hypervisor */
- ld r0,-8(r1)
- mtcrf 0xff,r0
- blr /* return r3 = status */
-
+ stw r0,8(r1)
-/* long plpar_hcall_8arg_2ret(unsigned long opcode, R3
- unsigned long arg1, R4
- unsigned long arg2, R5
- unsigned long arg3, R6
- unsigned long arg4, R7
- unsigned long arg5, R8
- unsigned long arg6, R9
- unsigned long arg7, R10
- unsigned long arg8, 112(R1)
- unsigned long *out1); 120(R1)
+ HVSC /* invoke the hypervisor */
+ lwz r0,8(r1)
+ mtcrf 0xff,r0
+ blr /* return r3 = status */
+
+
+/* long plpar_hcall_8arg_2ret(unsigned long opcode, R3
+ unsigned long arg1, R4
+ unsigned long arg2, R5
+ unsigned long arg3, R6
+ unsigned long arg4, R7
+ unsigned long arg5, R8
+ unsigned long arg6, R9
+ unsigned long arg7, R10
+ unsigned long arg8, 112(R1)
+ unsigned long *out1); 120(R1)
*/
-
- .text
_GLOBAL(plpar_hcall_8arg_2ret)
mfcr r0
+ ld r11,STK_PARM(r11)(r1) /* put arg8 in R11 */
+ stw r0,8(r1)
- ld r11, 112(r1) /* put arg8 and out1 in R11 and R12 */
- ld r12, 120(r1)
-
- std r0,-8(r1)
- stdu r1,-32(r1)
-
- std r12,-8(r1) /* Save out ptr */
-
- HVSC /* invoke the hypervisor */
-
- ld r10,-8(r1) /* Fetch r4 ret arg */
- std r4,0(r10)
+ HVSC /* invoke the hypervisor */
- ld r1,0(r1)
- ld r0,-8(r1)
+ lwz r0,8(r1)
+ ld r10,STK_PARM(r12)(r1) /* Fetch r4 ret arg */
+ std r4,0(r10)
mtcrf 0xff,r0
- blr /* return r3 = status */
-
-
-/* long plpar_hcall_4out(unsigned long opcode, R3
- unsigned long arg1, R4
- unsigned long arg2, R5
- unsigned long arg3, R6
- unsigned long arg4, R7
- unsigned long *out1, (r4) R8
- unsigned long *out2, (r5) R9
- unsigned long *out3, (r6) R10
- unsigned long *out4); (r7) 112(R1). From Parameter save area.
+ blr /* return r3 = status */
+
+
+/* long plpar_hcall_4out(unsigned long opcode, R3
+ unsigned long arg1, R4
+ unsigned long arg2, R5
+ unsigned long arg3, R6
+ unsigned long arg4, R7
+ unsigned long *out1, R8
+ unsigned long *out2, R9
+ unsigned long *out3, R10
+ unsigned long *out4); 112(R1)
*/
_GLOBAL(plpar_hcall_4out)
mfcr r0
- std r0,-8(r1)
- ld r14,112(r1)
- stdu r1,-48(r1)
-
- std r8,32(r1) /* Save out ptrs. */
- std r9,24(r1)
- std r10,16(r1)
- std r14,8(r1)
-
- HVSC /* invoke the hypervisor */
-
- ld r14,32(r1) /* Fetch r4-r7 ret args. */
- std r4,0(r14)
- ld r14,24(r1)
- std r5,0(r14)
- ld r14,16(r1)
- std r6,0(r14)
- ld r14,8(r1)
- std r7,0(r14)
-
- ld r1,0(r1)
- ld r0,-8(r1)
+ stw r0,8(r1)
+
+ std r8,STK_PARM(r8)(r1) /* Save out ptrs */
+ std r9,STK_PARM(r9)(r1)
+ std r10,STK_PARM(r10)(r1)
+
+ HVSC /* invoke the hypervisor */
+
+ lwz r0,8(r1)
+
+ ld r8,STK_PARM(r8)(r1) /* Fetch r4-r7 ret args */
+ ld r9,STK_PARM(r9)(r1)
+ ld r10,STK_PARM(r10)(r1)
+ ld r11,STK_PARM(r11)(r1)
+ std r4,0(r8)
+ std r5,0(r9)
+ std r6,0(r10)
+ std r7,0(r11)
+
mtcrf 0xff,r0
- blr /* return r3 = status */
+ blr /* return r3 = status */
diff --git a/arch/ppc64/kernel/pSeries_iommu.c b/arch/ppc64/kernel/pSeries_iommu.c
index 5543aaa568e79..69130522a87e1 100644
--- a/arch/ppc64/kernel/pSeries_iommu.c
+++ b/arch/ppc64/kernel/pSeries_iommu.c
@@ -43,6 +43,7 @@
#include <asm/machdep.h>
#include <asm/abs_addr.h>
#include <asm/plpar_wrappers.h>
+#include <asm/pSeries_reconfig.h>
#include <asm/systemcfg.h>
#include "pci.h"
@@ -401,6 +402,8 @@ static void iommu_bus_setup_pSeriesLP(struct pci_bus *bus)
struct device_node *dn, *pdn;
unsigned int *dma_window = NULL;
+ DBG("iommu_bus_setup_pSeriesLP, bus %p, bus->self %p\n", bus, bus->self);
+
dn = pci_bus_to_OF_node(bus);
/* Find nearest ibm,dma-window, walking up the device tree */
@@ -455,6 +458,78 @@ static void iommu_dev_setup_pSeries(struct pci_dev *dev)
}
}
+static int iommu_reconfig_notifier(struct notifier_block *nb, unsigned long action, void *node)
+{
+ int err = NOTIFY_OK;
+ struct device_node *np = node;
+
+ switch (action) {
+ case PSERIES_RECONFIG_REMOVE:
+ if (np->iommu_table &&
+ get_property(np, "ibm,dma-window", NULL))
+ iommu_free_table(np);
+ break;
+ default:
+ err = NOTIFY_DONE;
+ break;
+ }
+ return err;
+}
+
+static struct notifier_block iommu_reconfig_nb = {
+ .notifier_call = iommu_reconfig_notifier,
+};
+
+static void iommu_dev_setup_pSeriesLP(struct pci_dev *dev)
+{
+ struct device_node *pdn, *dn;
+ struct iommu_table *tbl;
+ int *dma_window = NULL;
+
+ DBG("iommu_dev_setup_pSeriesLP, dev %p (%s)\n", dev, dev->pretty_name);
+
+ /* dev setup for LPAR is a little tricky, since the device tree might
+ * contain the dma-window properties per-device and not neccesarily
+ * for the bus. So we need to search upwards in the tree until we
+ * either hit a dma-window property, OR find a parent with a table
+ * already allocated.
+ */
+ dn = pci_device_to_OF_node(dev);
+
+ for (pdn = dn; pdn && !pdn->iommu_table; pdn = pdn->parent) {
+ dma_window = (unsigned int *)get_property(pdn, "ibm,dma-window", NULL);
+ if (dma_window)
+ break;
+ }
+
+ /* Check for parent == NULL so we don't try to setup the empty EADS
+ * slots on POWER4 machines.
+ */
+ if (dma_window == NULL || pdn->parent == NULL) {
+ /* Fall back to regular (non-LPAR) dev setup */
+ DBG("No dma window for device, falling back to regular setup\n");
+ iommu_dev_setup_pSeries(dev);
+ return;
+ } else {
+ DBG("Found DMA window, allocating table\n");
+ }
+
+ if (!pdn->iommu_table) {
+ /* iommu_table_setparms_lpar needs bussubno. */
+ pdn->bussubno = pdn->phb->bus->number;
+
+ tbl = (struct iommu_table *)kmalloc(sizeof(struct iommu_table),
+ GFP_KERNEL);
+
+ iommu_table_setparms_lpar(pdn->phb, pdn, tbl, dma_window);
+
+ pdn->iommu_table = iommu_init_table(tbl);
+ }
+
+ if (pdn != dn)
+ dn->iommu_table = pdn->iommu_table;
+}
+
static void iommu_bus_setup_null(struct pci_bus *b) { }
static void iommu_dev_setup_null(struct pci_dev *d) { }
@@ -479,13 +554,16 @@ void iommu_init_early_pSeries(void)
ppc_md.tce_free = tce_free_pSeriesLP;
}
ppc_md.iommu_bus_setup = iommu_bus_setup_pSeriesLP;
+ ppc_md.iommu_dev_setup = iommu_dev_setup_pSeriesLP;
} else {
ppc_md.tce_build = tce_build_pSeries;
ppc_md.tce_free = tce_free_pSeries;
ppc_md.iommu_bus_setup = iommu_bus_setup_pSeries;
+ ppc_md.iommu_dev_setup = iommu_dev_setup_pSeries;
}
- ppc_md.iommu_dev_setup = iommu_dev_setup_pSeries;
+
+ pSeries_reconfig_notifier_register(&iommu_reconfig_nb);
pci_iommu_init();
}
diff --git a/arch/ppc64/kernel/pSeries_lpar.c b/arch/ppc64/kernel/pSeries_lpar.c
index 624acf0c8cec6..6534812db437e 100644
--- a/arch/ppc64/kernel/pSeries_lpar.c
+++ b/arch/ppc64/kernel/pSeries_lpar.c
@@ -470,7 +470,7 @@ static void pSeries_lpar_hpte_updateboltedpp(unsigned long newpp,
slot = pSeries_lpar_hpte_find(vpn);
BUG_ON(slot == -1);
- flags = newpp & 3;
+ flags = newpp & 7;
lpar_rc = plpar_pte_protect(flags, slot, 0);
BUG_ON(lpar_rc != H_Success);
@@ -505,7 +505,7 @@ void pSeries_lpar_flush_hash_range(unsigned long context, unsigned long number,
int i;
unsigned long flags = 0;
struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch);
- int lock_tlbie = !(cur_cpu_spec->cpu_features & CPU_FTR_LOCKLESS_TLBIE);
+ int lock_tlbie = !cpu_has_feature(CPU_FTR_LOCKLESS_TLBIE);
if (lock_tlbie)
spin_lock_irqsave(&pSeries_lpar_tlbie_lock, flags);
diff --git a/arch/ppc64/kernel/pSeries_nvram.c b/arch/ppc64/kernel/pSeries_nvram.c
index 52aeefdeca864..18abfb1f4e248 100644
--- a/arch/ppc64/kernel/pSeries_nvram.c
+++ b/arch/ppc64/kernel/pSeries_nvram.c
@@ -11,14 +11,9 @@
* This perhaps should live in drivers/char
*/
-#include <linux/module.h>
#include <linux/types.h>
#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/miscdevice.h>
-#include <linux/fcntl.h>
-#include <linux/nvram.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
diff --git a/arch/ppc64/kernel/pSeries_pci.c b/arch/ppc64/kernel/pSeries_pci.c
index 8953e94889bab..0b1cca281408b 100644
--- a/arch/ppc64/kernel/pSeries_pci.c
+++ b/arch/ppc64/kernel/pSeries_pci.c
@@ -52,6 +52,16 @@ static int s7a_workaround;
extern struct mpic *pSeries_mpic;
+static int config_access_valid(struct device_node *dn, int where)
+{
+ if (where < 256)
+ return 1;
+ if (where < 4096 && dn->pci_ext_config_space)
+ return 1;
+
+ return 0;
+}
+
static int rtas_read_config(struct device_node *dn, int where, int size, u32 *val)
{
int returnval = -1;
@@ -60,10 +70,11 @@ static int rtas_read_config(struct device_node *dn, int where, int size, u32 *va
if (!dn)
return PCIBIOS_DEVICE_NOT_FOUND;
- if (where & (size - 1))
+ if (!config_access_valid(dn, where))
return PCIBIOS_BAD_REGISTER_NUMBER;
- addr = (dn->busno << 16) | (dn->devfn << 8) | where;
+ addr = ((where & 0xf00) << 20) | (dn->busno << 16) |
+ (dn->devfn << 8) | (where & 0xff);
buid = dn->phb->buid;
if (buid) {
ret = rtas_call(ibm_read_pci_config, 4, 2, &returnval,
@@ -108,10 +119,11 @@ static int rtas_write_config(struct device_node *dn, int where, int size, u32 va
if (!dn)
return PCIBIOS_DEVICE_NOT_FOUND;
- if (where & (size - 1))
+ if (!config_access_valid(dn, where))
return PCIBIOS_BAD_REGISTER_NUMBER;
- addr = (dn->busno << 16) | (dn->devfn << 8) | where;
+ addr = ((where & 0xf00) << 20) | (dn->busno << 16) |
+ (dn->devfn << 8) | (where & 0xff);
buid = dn->phb->buid;
if (buid) {
ret = rtas_call(ibm_write_pci_config, 5, 1, NULL, addr, buid >> 32, buid & 0xffffffff, size, (ulong) val);
@@ -412,16 +424,18 @@ struct pci_controller * __devinit init_phb_dynamic(struct device_node *dn)
unsigned int root_size_cells = 0;
struct pci_controller *phb;
struct pci_bus *bus;
+ int primary;
root_size_cells = prom_n_size_cells(root);
+ primary = list_empty(&hose_list);
phb = alloc_phb_dynamic(dn, root_size_cells);
if (!phb)
return NULL;
pci_process_bridge_OF_ranges(phb, dn);
- pci_setup_phb_io_dynamic(phb);
+ pci_setup_phb_io_dynamic(phb, primary);
of_node_put(root);
pci_devs_phb_init_dynamic(phb);
@@ -526,6 +540,9 @@ EXPORT_SYMBOL(pcibios_remove_root_bus);
static void __init pSeries_request_regions(void)
{
+ if (!isa_io_base)
+ return;
+
request_region(0x20,0x20,"pic1");
request_region(0xa0,0x20,"pic2");
request_region(0x00,0x20,"dma1");
diff --git a/arch/ppc64/kernel/pSeries_reconfig.c b/arch/ppc64/kernel/pSeries_reconfig.c
new file mode 100644
index 0000000000000..cb5443f2e49b8
--- /dev/null
+++ b/arch/ppc64/kernel/pSeries_reconfig.c
@@ -0,0 +1,434 @@
+/*
+ * pSeries_reconfig.c - support for dynamic reconfiguration (including PCI
+ * Hotplug and Dynamic Logical Partitioning on RPA platforms).
+ *
+ * Copyright (C) 2005 Nathan Lynch
+ * Copyright (C) 2005 IBM 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/kref.h>
+#include <linux/notifier.h>
+#include <linux/proc_fs.h>
+
+#include <asm/prom.h>
+#include <asm/pSeries_reconfig.h>
+#include <asm/uaccess.h>
+
+
+
+/*
+ * Routines for "runtime" addition and removal of device tree nodes.
+ */
+#ifdef CONFIG_PROC_DEVICETREE
+/*
+ * Add a node to /proc/device-tree.
+ */
+static void add_node_proc_entries(struct device_node *np)
+{
+ struct proc_dir_entry *ent;
+
+ ent = proc_mkdir(strrchr(np->full_name, '/') + 1, np->parent->pde);
+ if (ent)
+ proc_device_tree_add_node(np, ent);
+}
+
+static void remove_node_proc_entries(struct device_node *np)
+{
+ struct property *pp = np->properties;
+ struct device_node *parent = np->parent;
+
+ while (pp) {
+ remove_proc_entry(pp->name, np->pde);
+ pp = pp->next;
+ }
+
+ /* Assuming that symlinks have the same parent directory as
+ * np->pde.
+ */
+ if (np->name_link)
+ remove_proc_entry(np->name_link->name, parent->pde);
+ if (np->addr_link)
+ remove_proc_entry(np->addr_link->name, parent->pde);
+ if (np->pde)
+ remove_proc_entry(np->pde->name, parent->pde);
+}
+#else /* !CONFIG_PROC_DEVICETREE */
+static void add_node_proc_entries(struct device_node *np)
+{
+ return;
+}
+
+static void remove_node_proc_entries(struct device_node *np)
+{
+ return;
+}
+#endif /* CONFIG_PROC_DEVICETREE */
+
+/**
+ * derive_parent - basically like dirname(1)
+ * @path: the full_name of a node to be added to the tree
+ *
+ * Returns the node which should be the parent of the node
+ * described by path. E.g., for path = "/foo/bar", returns
+ * the node with full_name = "/foo".
+ */
+static struct device_node *derive_parent(const char *path)
+{
+ struct device_node *parent = NULL;
+ char *parent_path = "/";
+ size_t parent_path_len = strrchr(path, '/') - path + 1;
+
+ /* reject if path is "/" */
+ if (!strcmp(path, "/"))
+ return ERR_PTR(-EINVAL);
+
+ if (strrchr(path, '/') != path) {
+ parent_path = kmalloc(parent_path_len, GFP_KERNEL);
+ if (!parent_path)
+ return ERR_PTR(-ENOMEM);
+ strlcpy(parent_path, path, parent_path_len);
+ }
+ parent = of_find_node_by_path(parent_path);
+ if (!parent)
+ return ERR_PTR(-EINVAL);
+ if (strcmp(parent_path, "/"))
+ kfree(parent_path);
+ return parent;
+}
+
+static struct notifier_block *pSeries_reconfig_chain;
+
+int pSeries_reconfig_notifier_register(struct notifier_block *nb)
+{
+ return notifier_chain_register(&pSeries_reconfig_chain, nb);
+}
+
+void pSeries_reconfig_notifier_unregister(struct notifier_block *nb)
+{
+ notifier_chain_unregister(&pSeries_reconfig_chain, nb);
+}
+
+static int pSeries_reconfig_add_node(const char *path, struct property *proplist)
+{
+ struct device_node *np;
+ int err = -ENOMEM;
+
+ np = kcalloc(1, sizeof(*np), GFP_KERNEL);
+ if (!np)
+ goto out_err;
+
+ np->full_name = kmalloc(strlen(path) + 1, GFP_KERNEL);
+ if (!np->full_name)
+ goto out_err;
+
+ strcpy(np->full_name, path);
+
+ np->properties = proplist;
+ OF_MARK_DYNAMIC(np);
+ kref_init(&np->kref);
+
+ np->parent = derive_parent(path);
+ if (IS_ERR(np->parent)) {
+ err = PTR_ERR(np->parent);
+ goto out_err;
+ }
+
+ err = notifier_call_chain(&pSeries_reconfig_chain,
+ PSERIES_RECONFIG_ADD, np);
+ if (err == NOTIFY_BAD) {
+ printk(KERN_ERR "Failed to add device node %s\n", path);
+ err = -ENOMEM; /* For now, safe to assume kmalloc failure */
+ goto out_err;
+ }
+
+ of_attach_node(np);
+
+ add_node_proc_entries(np);
+
+ of_node_put(np->parent);
+
+ return 0;
+
+out_err:
+ if (np) {
+ of_node_put(np->parent);
+ kfree(np->full_name);
+ kfree(np);
+ }
+ return err;
+}
+
+static int pSeries_reconfig_remove_node(struct device_node *np)
+{
+ struct device_node *parent, *child;
+
+ parent = of_get_parent(np);
+ if (!parent)
+ return -EINVAL;
+
+ if ((child = of_get_next_child(np, NULL))) {
+ of_node_put(child);
+ return -EBUSY;
+ }
+
+ remove_node_proc_entries(np);
+
+ notifier_call_chain(&pSeries_reconfig_chain,
+ PSERIES_RECONFIG_REMOVE, np);
+ of_detach_node(np);
+
+ of_node_put(parent);
+ of_node_put(np); /* Must decrement the refcount */
+ return 0;
+}
+
+/*
+ * /proc/ppc64/ofdt - yucky binary interface for adding and removing
+ * OF device nodes. Should be deprecated as soon as we get an
+ * in-kernel wrapper for the RTAS ibm,configure-connector call.
+ */
+
+static void release_prop_list(const struct property *prop)
+{
+ struct property *next;
+ for (; prop; prop = next) {
+ next = prop->next;
+ kfree(prop->name);
+ kfree(prop->value);
+ kfree(prop);
+ }
+
+}
+
+/**
+ * parse_next_property - process the next property from raw input buffer
+ * @buf: input buffer, must be nul-terminated
+ * @end: end of the input buffer + 1, for validation
+ * @name: return value; set to property name in buf
+ * @length: return value; set to length of value
+ * @value: return value; set to the property value in buf
+ *
+ * Note that the caller must make copies of the name and value returned,
+ * this function does no allocation or copying of the data. Return value
+ * is set to the next name in buf, or NULL on error.
+ */
+static char * parse_next_property(char *buf, char *end, char **name, int *length,
+ unsigned char **value)
+{
+ char *tmp;
+
+ *name = buf;
+
+ tmp = strchr(buf, ' ');
+ if (!tmp) {
+ printk(KERN_ERR "property parse failed in %s at line %d\n",
+ __FUNCTION__, __LINE__);
+ return NULL;
+ }
+ *tmp = '\0';
+
+ if (++tmp >= end) {
+ printk(KERN_ERR "property parse failed in %s at line %d\n",
+ __FUNCTION__, __LINE__);
+ return NULL;
+ }
+
+ /* now we're on the length */
+ *length = -1;
+ *length = simple_strtoul(tmp, &tmp, 10);
+ if (*length == -1) {
+ printk(KERN_ERR "property parse failed in %s at line %d\n",
+ __FUNCTION__, __LINE__);
+ return NULL;
+ }
+ if (*tmp != ' ' || ++tmp >= end) {
+ printk(KERN_ERR "property parse failed in %s at line %d\n",
+ __FUNCTION__, __LINE__);
+ return NULL;
+ }
+
+ /* now we're on the value */
+ *value = tmp;
+ tmp += *length;
+ if (tmp > end) {
+ printk(KERN_ERR "property parse failed in %s at line %d\n",
+ __FUNCTION__, __LINE__);
+ return NULL;
+ }
+ else if (tmp < end && *tmp != ' ' && *tmp != '\0') {
+ printk(KERN_ERR "property parse failed in %s at line %d\n",
+ __FUNCTION__, __LINE__);
+ return NULL;
+ }
+ tmp++;
+
+ /* and now we should be on the next name, or the end */
+ return tmp;
+}
+
+static struct property *new_property(const char *name, const int length,
+ const unsigned char *value, struct property *last)
+{
+ struct property *new = kmalloc(sizeof(*new), GFP_KERNEL);
+
+ if (!new)
+ return NULL;
+ memset(new, 0, sizeof(*new));
+
+ if (!(new->name = kmalloc(strlen(name) + 1, GFP_KERNEL)))
+ goto cleanup;
+ if (!(new->value = kmalloc(length + 1, GFP_KERNEL)))
+ goto cleanup;
+
+ strcpy(new->name, name);
+ memcpy(new->value, value, length);
+ *(((char *)new->value) + length) = 0;
+ new->length = length;
+ new->next = last;
+ return new;
+
+cleanup:
+ if (new->name)
+ kfree(new->name);
+ if (new->value)
+ kfree(new->value);
+ kfree(new);
+ return NULL;
+}
+
+static int do_add_node(char *buf, size_t bufsize)
+{
+ char *path, *end, *name;
+ struct device_node *np;
+ struct property *prop = NULL;
+ unsigned char* value;
+ int length, rv = 0;
+
+ end = buf + bufsize;
+ path = buf;
+ buf = strchr(buf, ' ');
+ if (!buf)
+ return -EINVAL;
+ *buf = '\0';
+ buf++;
+
+ if ((np = of_find_node_by_path(path))) {
+ of_node_put(np);
+ return -EINVAL;
+ }
+
+ /* rv = build_prop_list(tmp, bufsize - (tmp - buf), &proplist); */
+ while (buf < end &&
+ (buf = parse_next_property(buf, end, &name, &length, &value))) {
+ struct property *last = prop;
+
+ prop = new_property(name, length, value, last);
+ if (!prop) {
+ rv = -ENOMEM;
+ prop = last;
+ goto out;
+ }
+ }
+ if (!buf) {
+ rv = -EINVAL;
+ goto out;
+ }
+
+ rv = pSeries_reconfig_add_node(path, prop);
+
+out:
+ if (rv)
+ release_prop_list(prop);
+ return rv;
+}
+
+static int do_remove_node(char *buf)
+{
+ struct device_node *node;
+ int rv = -ENODEV;
+
+ if ((node = of_find_node_by_path(buf)))
+ rv = pSeries_reconfig_remove_node(node);
+
+ of_node_put(node);
+ return rv;
+}
+
+/**
+ * ofdt_write - perform operations on the Open Firmware device tree
+ *
+ * @file: not used
+ * @buf: command and arguments
+ * @count: size of the command buffer
+ * @off: not used
+ *
+ * Operations supported at this time are addition and removal of
+ * whole nodes along with their properties. Operations on individual
+ * properties are not implemented (yet).
+ */
+static ssize_t ofdt_write(struct file *file, const char __user *buf, size_t count,
+ loff_t *off)
+{
+ int rv = 0;
+ char *kbuf;
+ char *tmp;
+
+ if (!(kbuf = kmalloc(count + 1, GFP_KERNEL))) {
+ rv = -ENOMEM;
+ goto out;
+ }
+ if (copy_from_user(kbuf, buf, count)) {
+ rv = -EFAULT;
+ goto out;
+ }
+
+ kbuf[count] = '\0';
+
+ tmp = strchr(kbuf, ' ');
+ if (!tmp) {
+ rv = -EINVAL;
+ goto out;
+ }
+ *tmp = '\0';
+ tmp++;
+
+ if (!strcmp(kbuf, "add_node"))
+ rv = do_add_node(tmp, count - (tmp - kbuf));
+ else if (!strcmp(kbuf, "remove_node"))
+ rv = do_remove_node(tmp);
+ else
+ rv = -EINVAL;
+out:
+ kfree(kbuf);
+ return rv ? rv : count;
+}
+
+static struct file_operations ofdt_fops = {
+ .write = ofdt_write
+};
+
+/* create /proc/ppc64/ofdt write-only by root */
+static int proc_ppc64_create_ofdt(void)
+{
+ struct proc_dir_entry *ent;
+
+ if (!(systemcfg->platform & PLATFORM_PSERIES))
+ return 0;
+
+ ent = create_proc_entry("ppc64/ofdt", S_IWUSR, NULL);
+ if (ent) {
+ ent->nlink = 1;
+ ent->data = NULL;
+ ent->size = 0;
+ ent->proc_fops = &ofdt_fops;
+ }
+
+ return 0;
+}
+__initcall(proc_ppc64_create_ofdt);
diff --git a/arch/ppc64/kernel/pSeries_setup.c b/arch/ppc64/kernel/pSeries_setup.c
index f603397b7b045..06536de512577 100644
--- a/arch/ppc64/kernel/pSeries_setup.c
+++ b/arch/ppc64/kernel/pSeries_setup.c
@@ -320,9 +320,10 @@ static void __init pSeries_discover_pic(void)
}
}
-static void pSeries_cpu_die(void)
+static void pSeries_mach_cpu_die(void)
{
local_irq_disable();
+ idle_task_exit();
/* Some hardware requires clearing the CPPR, while other hardware does not
* it is safe either way
*/
@@ -599,7 +600,7 @@ struct machdep_calls __initdata pSeries_md = {
.power_off = rtas_power_off,
.halt = rtas_halt,
.panic = rtas_os_term,
- .cpu_die = pSeries_cpu_die,
+ .cpu_die = pSeries_mach_cpu_die,
.get_boot_time = pSeries_get_boot_time,
.get_rtc_time = pSeries_get_rtc_time,
.set_rtc_time = pSeries_set_rtc_time,
diff --git a/arch/ppc64/kernel/pSeries_smp.c b/arch/ppc64/kernel/pSeries_smp.c
index 27ab1ed2c0401..c60d8cb2b84d2 100644
--- a/arch/ppc64/kernel/pSeries_smp.c
+++ b/arch/ppc64/kernel/pSeries_smp.c
@@ -44,6 +44,7 @@
#include <asm/system.h>
#include <asm/rtas.h>
#include <asm/plpar_wrappers.h>
+#include <asm/pSeries_reconfig.h>
#include "mpic.h"
@@ -53,8 +54,16 @@
#define DBG(fmt...)
#endif
+/*
+ * The primary thread of each non-boot processor is recorded here before
+ * smp init.
+ */
+static cpumask_t of_spin_map;
+
extern void pSeries_secondary_smp_init(unsigned long);
+#ifdef CONFIG_HOTPLUG_CPU
+
/* Get state of physical CPU.
* Return codes:
* 0 - The processor is in the RTAS stopped state
@@ -81,9 +90,6 @@ static int query_cpu_stopped(unsigned int pcpu)
return cpu_status;
}
-
-#ifdef CONFIG_HOTPLUG_CPU
-
int pSeries_cpu_disable(void)
{
systemcfg->processorCount--;
@@ -122,60 +128,134 @@ void pSeries_cpu_die(unsigned int cpu)
paca[cpu].cpu_start = 0;
}
-/* Search all cpu device nodes for an offline logical cpu. If a
- * device node has a "ibm,my-drc-index" property (meaning this is an
- * LPAR), paranoid-check whether we own the cpu. For each "thread"
- * of a cpu, if it is offline and has the same hw index as before,
- * grab that in preference.
+/*
+ * Update cpu_present_map and paca(s) for a new cpu node. The wrinkle
+ * here is that a cpu device node may represent up to two logical cpus
+ * in the SMT case. We must honor the assumption in other code that
+ * the logical ids for sibling SMT threads x and y are adjacent, such
+ * that x^1 == y and y^1 == x.
*/
-static unsigned int find_physical_cpu_to_start(unsigned int old_hwindex)
+static int pSeries_add_processor(struct device_node *np)
{
- struct device_node *np = NULL;
- unsigned int best = -1U;
+ unsigned int cpu;
+ cpumask_t candidate_map, tmp = CPU_MASK_NONE;
+ int err = -ENOSPC, len, nthreads, i;
+ u32 *intserv;
+
+ intserv = (u32 *)get_property(np, "ibm,ppc-interrupt-server#s", &len);
+ if (!intserv)
+ return 0;
- while ((np = of_find_node_by_type(np, "cpu"))) {
- int nr_threads, len;
- u32 *index = (u32 *)get_property(np, "ibm,my-drc-index", NULL);
- u32 *tid = (u32 *)
- get_property(np, "ibm,ppc-interrupt-server#s", &len);
+ nthreads = len / sizeof(u32);
+ for (i = 0; i < nthreads; i++)
+ cpu_set(i, tmp);
- if (!tid)
- tid = (u32 *)get_property(np, "reg", &len);
+ lock_cpu_hotplug();
- if (!tid)
- continue;
+ BUG_ON(!cpus_subset(cpu_present_map, cpu_possible_map));
- /* If there is a drc-index, make sure that we own
- * the cpu.
+ /* Get a bitmap of unoccupied slots. */
+ cpus_xor(candidate_map, cpu_possible_map, cpu_present_map);
+ if (cpus_empty(candidate_map)) {
+ /* If we get here, it most likely means that NR_CPUS is
+ * less than the partition's max processors setting.
*/
- if (index) {
- int state;
- int rc = rtas_get_sensor(9003, *index, &state);
- if (rc != 0 || state != 1)
- continue;
- }
+ printk(KERN_ERR "Cannot add cpu %s; this system configuration"
+ " supports %d logical cpus.\n", np->full_name,
+ cpus_weight(cpu_possible_map));
+ goto out_unlock;
+ }
- nr_threads = len / sizeof(u32);
+ while (!cpus_empty(tmp))
+ if (cpus_subset(tmp, candidate_map))
+ /* Found a range where we can insert the new cpu(s) */
+ break;
+ else
+ cpus_shift_left(tmp, tmp, nthreads);
+
+ if (cpus_empty(tmp)) {
+ printk(KERN_ERR "Unable to find space in cpu_present_map for"
+ " processor %s with %d thread(s)\n", np->name,
+ nthreads);
+ goto out_unlock;
+ }
+
+ for_each_cpu_mask(cpu, tmp) {
+ BUG_ON(cpu_isset(cpu, cpu_present_map));
+ cpu_set(cpu, cpu_present_map);
+ set_hard_smp_processor_id(cpu, *intserv++);
+ }
+ err = 0;
+out_unlock:
+ unlock_cpu_hotplug();
+ return err;
+}
+
+/*
+ * Update the present map for a cpu node which is going away, and set
+ * the hard id in the paca(s) to -1 to be consistent with boot time
+ * convention for non-present cpus.
+ */
+static void pSeries_remove_processor(struct device_node *np)
+{
+ unsigned int cpu;
+ int len, nthreads, i;
+ u32 *intserv;
+
+ intserv = (u32 *)get_property(np, "ibm,ppc-interrupt-server#s", &len);
+ if (!intserv)
+ return;
+
+ nthreads = len / sizeof(u32);
- while (nr_threads--) {
- if (0 == query_cpu_stopped(tid[nr_threads])) {
- best = tid[nr_threads];
- if (best == old_hwindex)
- goto out;
- }
+ lock_cpu_hotplug();
+ for (i = 0; i < nthreads; i++) {
+ for_each_present_cpu(cpu) {
+ if (get_hard_smp_processor_id(cpu) != intserv[i])
+ continue;
+ BUG_ON(cpu_online(cpu));
+ cpu_clear(cpu, cpu_present_map);
+ set_hard_smp_processor_id(cpu, -1);
+ break;
}
+ if (cpu == NR_CPUS)
+ printk(KERN_WARNING "Could not find cpu to remove "
+ "with physical id 0x%x\n", intserv[i]);
}
-out:
- of_node_put(np);
- return best;
+ unlock_cpu_hotplug();
}
+static int pSeries_smp_notifier(struct notifier_block *nb, unsigned long action, void *node)
+{
+ int err = NOTIFY_OK;
+
+ switch (action) {
+ case PSERIES_RECONFIG_ADD:
+ if (pSeries_add_processor(node))
+ err = NOTIFY_BAD;
+ break;
+ case PSERIES_RECONFIG_REMOVE:
+ pSeries_remove_processor(node);
+ break;
+ default:
+ err = NOTIFY_DONE;
+ break;
+ }
+ return err;
+}
+
+static struct notifier_block pSeries_smp_nb = {
+ .notifier_call = pSeries_smp_notifier,
+};
+
+#endif /* CONFIG_HOTPLUG_CPU */
+
/**
* smp_startup_cpu() - start the given cpu
*
- * At boot time, there is nothing to do. At run-time, call RTAS with
- * the appropriate start location, if the cpu is in the RTAS stopped
- * state.
+ * At boot time, there is nothing to do for primary threads which were
+ * started from Open Firmware. For anything else, call RTAS with the
+ * appropriate start location.
*
* Returns:
* 0 - failure
@@ -188,23 +268,15 @@ static inline int __devinit smp_startup_cpu(unsigned int lcpu)
pSeries_secondary_smp_init));
unsigned int pcpu;
- /* At boot time the cpus are already spinning in hold
- * loops, so nothing to do. */
- if (system_state < SYSTEM_RUNNING)
+ if (cpu_isset(lcpu, of_spin_map))
+ /* Already started by OF and sitting in spin loop */
return 1;
- pcpu = find_physical_cpu_to_start(get_hard_smp_processor_id(lcpu));
- if (pcpu == -1U) {
- printk(KERN_INFO "No more cpus available, failing\n");
- return 0;
- }
+ pcpu = get_hard_smp_processor_id(lcpu);
/* Fixup atomic count: it exited inside IRQ handler. */
paca[lcpu].__current->thread_info->preempt_count = 0;
- /* At boot this is done in prom.c. */
- paca[lcpu].hw_cpu_id = pcpu;
-
status = rtas_call(rtas_token("start-cpu"), 3, 1, NULL,
pcpu, start_here, lcpu);
if (status != 0) {
@@ -213,12 +285,6 @@ static inline int __devinit smp_startup_cpu(unsigned int lcpu)
}
return 1;
}
-#else /* ... CONFIG_HOTPLUG_CPU */
-static inline int __devinit smp_startup_cpu(unsigned int lcpu)
-{
- return 1;
-}
-#endif /* CONFIG_HOTPLUG_CPU */
static inline void smp_xics_do_message(int cpu, int msg)
{
@@ -258,6 +324,8 @@ static void __devinit smp_xics_setup_cpu(int cpu)
if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR)
vpa_init(cpu);
+ cpu_clear(cpu, of_spin_map);
+
/*
* Put the calling processor into the GIQ. This is really only
* necessary from a secondary thread as the OF start-cpu interface
@@ -307,6 +375,20 @@ static void __devinit smp_pSeries_kick_cpu(int nr)
paca[nr].cpu_start = 1;
}
+static int smp_pSeries_cpu_bootable(unsigned int nr)
+{
+ /* Special case - we inhibit secondary thread startup
+ * during boot if the user requests it. Odd-numbered
+ * cpus are assumed to be secondary threads.
+ */
+ if (system_state < SYSTEM_RUNNING &&
+ cur_cpu_spec->cpu_features & CPU_FTR_SMT &&
+ !smt_enabled_at_boot && nr % 2 != 0)
+ return 0;
+
+ return 1;
+}
+
static struct smp_ops_t pSeries_mpic_smp_ops = {
.message_pass = smp_mpic_message_pass,
.probe = smp_mpic_probe,
@@ -319,12 +401,13 @@ static struct smp_ops_t pSeries_xics_smp_ops = {
.probe = smp_xics_probe,
.kick_cpu = smp_pSeries_kick_cpu,
.setup_cpu = smp_xics_setup_cpu,
+ .cpu_bootable = smp_pSeries_cpu_bootable,
};
/* This is called very early */
void __init smp_init_pSeries(void)
{
- int ret, i;
+ int i;
DBG(" -> smp_init_pSeries()\n");
@@ -336,22 +419,26 @@ void __init smp_init_pSeries(void)
#ifdef CONFIG_HOTPLUG_CPU
smp_ops->cpu_disable = pSeries_cpu_disable;
smp_ops->cpu_die = pSeries_cpu_die;
+
+ /* Processors can be added/removed only on LPAR */
+ if (systemcfg->platform == PLATFORM_PSERIES_LPAR)
+ pSeries_reconfig_notifier_register(&pSeries_smp_nb);
#endif
- /* Start secondary threads on SMT systems; primary threads
- * are already in the running state.
- */
- for_each_present_cpu(i) {
- if (query_cpu_stopped(get_hard_smp_processor_id(i)) == 0) {
- printk("%16.16x : starting thread\n", i);
- DBG("%16.16x : starting thread\n", i);
- rtas_call(rtas_token("start-cpu"), 3, 1, &ret,
- get_hard_smp_processor_id(i),
- __pa((u32)*((unsigned long *)
- pSeries_secondary_smp_init)),
- i);
+ /* Mark threads which are still spinning in hold loops. */
+ if (cur_cpu_spec->cpu_features & CPU_FTR_SMT)
+ for_each_present_cpu(i) {
+ if (i % 2 == 0)
+ /*
+ * Even-numbered logical cpus correspond to
+ * primary threads.
+ */
+ cpu_set(i, of_spin_map);
}
- }
+ else
+ of_spin_map = cpu_present_map;
+
+ cpu_clear(boot_cpuid, of_spin_map);
/* Non-lpar has additional take/give timebase */
if (rtas_token("freeze-time-base") != RTAS_UNKNOWN_SERVICE) {
diff --git a/arch/ppc64/kernel/pacaData.c b/arch/ppc64/kernel/pacaData.c
index 0b18d17b94d4c..a3e0975c26c1a 100644
--- a/arch/ppc64/kernel/pacaData.c
+++ b/arch/ppc64/kernel/pacaData.c
@@ -20,9 +20,14 @@
#include <asm/iSeries/ItLpQueue.h>
#include <asm/paca.h>
-struct systemcfg *systemcfg;
+static union {
+ struct systemcfg data;
+ u8 page[PAGE_SIZE];
+} systemcfg_store __page_aligned;
+struct systemcfg *systemcfg = &systemcfg_store.data;
EXPORT_SYMBOL(systemcfg);
+
/* This symbol is provided by the linker - let it fill in the paca
* field correctly */
extern unsigned long __toc_start;
@@ -216,3 +221,4 @@ struct paca_struct paca[] = {
#endif
#endif
};
+EXPORT_SYMBOL(paca);
diff --git a/arch/ppc64/kernel/pci.c b/arch/ppc64/kernel/pci.c
index f7486bee078fc..fdd8f7869a68d 100644
--- a/arch/ppc64/kernel/pci.c
+++ b/arch/ppc64/kernel/pci.c
@@ -63,13 +63,15 @@ unsigned int pcibios_assign_all_busses(void)
* page is mapped and isa_io_limit prevents access to it.
*/
unsigned long isa_io_base; /* NULL if no ISA bus */
+EXPORT_SYMBOL(isa_io_base);
unsigned long pci_io_base;
+EXPORT_SYMBOL(pci_io_base);
void iSeries_pcibios_init(void);
LIST_HEAD(hose_list);
-struct pci_dma_ops pci_dma_ops;
+struct dma_mapping_ops pci_dma_ops;
EXPORT_SYMBOL(pci_dma_ops);
int global_phb_number; /* Global phb counter */
@@ -208,6 +210,11 @@ static int __init pcibios_init(void)
struct pci_controller *hose, *tmp;
struct pci_bus *bus;
+ /* For now, override phys_mem_access_prot. If we need it,
+ * later, we may move that initialization to each ppc_md
+ */
+ ppc_md.phys_mem_access_prot = pci_phys_mem_access_prot;
+
#ifdef CONFIG_PPC_ISERIES
iSeries_pcibios_init();
#endif
@@ -300,19 +307,15 @@ int pci_domain_nr(struct pci_bus *bus)
EXPORT_SYMBOL(pci_domain_nr);
-/* Set the name of the bus as it appears in /proc/bus/pci */
-int pci_name_bus(char *name, struct pci_bus *bus)
+/* Decide whether to display the domain number in /proc */
+int pci_proc_domain(struct pci_bus *bus)
{
-#ifndef CONFIG_PPC_ISERIES
+#ifdef CONFIG_PPC_ISERIES
+ return 0;
+#else
struct pci_controller *hose = pci_bus_to_host(bus);
-
- if (hose->buid)
- sprintf(name, "%04x:%02x", pci_domain_nr(bus), bus->number);
- else
+ return hose->buid;
#endif
- sprintf(name, "%02x", bus->number);
-
- return 0;
}
/*
@@ -332,25 +335,24 @@ int pci_name_bus(char *name, struct pci_bus *bus)
*
* Returns negative error code on failure, zero on success.
*/
-static __inline__ int __pci_mmap_make_offset(struct pci_dev *dev,
- struct vm_area_struct *vma,
- enum pci_mmap_state mmap_state)
+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_host(dev->bus);
- unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
unsigned long io_offset = 0;
int i, res_bit;
if (hose == 0)
- return -EINVAL; /* should never happen */
+ 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;
+ *offset += hose->pci_mem_offset;
res_bit = IORESOURCE_MEM;
} else {
io_offset = (unsigned long)hose->io_base_virt;
- offset += io_offset;
+ *offset += io_offset;
res_bit = IORESOURCE_IO;
}
@@ -371,50 +373,106 @@ static __inline__ int __pci_mmap_make_offset(struct pci_dev *dev,
continue;
/* In the range of this resource? */
- if (offset < (rp->start & PAGE_MASK) || offset > rp->end)
+ 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;
-
- vma->vm_pgoff = offset >> PAGE_SHIFT;
- return 0;
+ *offset += hose->io_base_phys - io_offset;
+ return rp;
}
- return -EINVAL;
-}
-
-/*
- * Set vm_flags of VMA, as appropriate for this architecture, for a pci device
- * mapping.
- */
-static __inline__ void __pci_mmap_set_flags(struct pci_dev *dev,
- struct vm_area_struct *vma,
- enum pci_mmap_state mmap_state)
-{
- vma->vm_flags |= VM_SHM | VM_LOCKED | VM_IO;
+ return NULL;
}
/*
* Set vm_page_prot of VMA, as appropriate for this architecture, for a pci
* device mapping.
*/
-static __inline__ void __pci_mmap_set_pgprot(struct pci_dev *dev,
- struct vm_area_struct *vma,
- enum pci_mmap_state mmap_state,
- int write_combine)
+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)
{
- long prot = pgprot_val(vma->vm_page_prot);
+ 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)
+ if (write_combine)
+ prot &= ~_PAGE_GUARDED;
+ else
prot |= _PAGE_GUARDED;
- vma->vm_page_prot = __pgprot(prot);
+
+ 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 offset,
+ unsigned long size,
+ pgprot_t protection)
+{
+ struct pci_dev *pdev = NULL;
+ struct resource *found = NULL;
+ unsigned long prot = pgprot_val(protection);
+ int i;
+
+ if (page_is_ram(offset >> PAGE_SHIFT))
+ 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
@@ -428,14 +486,19 @@ 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;
- ret = __pci_mmap_make_offset(dev, vma, mmap_state);
- if (ret < 0)
- return ret;
+ rp = __pci_mmap_make_offset(dev, &offset, mmap_state);
+ if (rp == NULL)
+ return -EINVAL;
- __pci_mmap_set_flags(dev, vma, mmap_state);
- __pci_mmap_set_pgprot(dev, vma, mmap_state, write_combine);
+ 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);
@@ -621,7 +684,8 @@ void __init pci_setup_phb_io(struct pci_controller *hose, int primary)
res->end += io_virt_offset;
}
-void __devinit pci_setup_phb_io_dynamic(struct pci_controller *hose)
+void __devinit pci_setup_phb_io_dynamic(struct pci_controller *hose,
+ int primary)
{
unsigned long size = hose->pci_io_size;
unsigned long io_virt_offset;
@@ -633,6 +697,9 @@ void __devinit pci_setup_phb_io_dynamic(struct pci_controller *hose)
hose->global_number, hose->io_base_phys,
(unsigned long) hose->io_base_virt);
+ if (primary)
+ pci_io_base = (unsigned long)hose->io_base_virt;
+
io_virt_offset = (unsigned long)hose->io_base_virt - pci_io_base;
res = &hose->io_resource;
res->start += io_virt_offset;
diff --git a/arch/ppc64/kernel/pci.h b/arch/ppc64/kernel/pci.h
index 28517c14015b9..0fd7d849aa77e 100644
--- a/arch/ppc64/kernel/pci.h
+++ b/arch/ppc64/kernel/pci.h
@@ -16,8 +16,7 @@ extern unsigned long isa_io_base;
extern void pci_setup_pci_controller(struct pci_controller *hose);
extern void pci_setup_phb_io(struct pci_controller *hose, int primary);
-
-extern void pci_setup_phb_io_dynamic(struct pci_controller *hose);
+extern void pci_setup_phb_io_dynamic(struct pci_controller *hose, int primary);
extern struct list_head hose_list;
diff --git a/arch/ppc64/kernel/pci_direct_iommu.c b/arch/ppc64/kernel/pci_direct_iommu.c
index 8faabca93b298..b8f7f58824f44 100644
--- a/arch/ppc64/kernel/pci_direct_iommu.c
+++ b/arch/ppc64/kernel/pci_direct_iommu.c
@@ -30,12 +30,12 @@
#include "pci.h"
-static void *pci_direct_alloc_consistent(struct pci_dev *hwdev, size_t size,
- dma_addr_t *dma_handle)
+static void *pci_direct_alloc_coherent(struct device *hwdev, size_t size,
+ dma_addr_t *dma_handle, unsigned int __nocast flag)
{
void *ret;
- ret = (void *)__get_free_pages(GFP_ATOMIC, get_order(size));
+ ret = (void *)__get_free_pages(flag, get_order(size));
if (ret != NULL) {
memset(ret, 0, size);
*dma_handle = virt_to_abs(ret);
@@ -43,24 +43,24 @@ static void *pci_direct_alloc_consistent(struct pci_dev *hwdev, size_t size,
return ret;
}
-static void pci_direct_free_consistent(struct pci_dev *hwdev, size_t size,
+static void pci_direct_free_coherent(struct device *hwdev, size_t size,
void *vaddr, dma_addr_t dma_handle)
{
free_pages((unsigned long)vaddr, get_order(size));
}
-static dma_addr_t pci_direct_map_single(struct pci_dev *hwdev, void *ptr,
+static dma_addr_t pci_direct_map_single(struct device *hwdev, void *ptr,
size_t size, enum dma_data_direction direction)
{
return virt_to_abs(ptr);
}
-static void pci_direct_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr,
+static void pci_direct_unmap_single(struct device *hwdev, dma_addr_t dma_addr,
size_t size, enum dma_data_direction direction)
{
}
-static int pci_direct_map_sg(struct pci_dev *hwdev, struct scatterlist *sg,
+static int pci_direct_map_sg(struct device *hwdev, struct scatterlist *sg,
int nents, enum dma_data_direction direction)
{
int i;
@@ -73,17 +73,23 @@ static int pci_direct_map_sg(struct pci_dev *hwdev, struct scatterlist *sg,
return nents;
}
-static void pci_direct_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg,
+static void pci_direct_unmap_sg(struct device *hwdev, struct scatterlist *sg,
int nents, enum dma_data_direction direction)
{
}
+static int pci_direct_dma_supported(struct device *dev, u64 mask)
+{
+ return mask < 0x100000000ull;
+}
+
void __init pci_direct_iommu_init(void)
{
- pci_dma_ops.pci_alloc_consistent = pci_direct_alloc_consistent;
- pci_dma_ops.pci_free_consistent = pci_direct_free_consistent;
- pci_dma_ops.pci_map_single = pci_direct_map_single;
- pci_dma_ops.pci_unmap_single = pci_direct_unmap_single;
- pci_dma_ops.pci_map_sg = pci_direct_map_sg;
- pci_dma_ops.pci_unmap_sg = pci_direct_unmap_sg;
+ pci_dma_ops.alloc_coherent = pci_direct_alloc_coherent;
+ pci_dma_ops.free_coherent = pci_direct_free_coherent;
+ pci_dma_ops.map_single = pci_direct_map_single;
+ pci_dma_ops.unmap_single = pci_direct_unmap_single;
+ pci_dma_ops.map_sg = pci_direct_map_sg;
+ pci_dma_ops.unmap_sg = pci_direct_unmap_sg;
+ pci_dma_ops.dma_supported = pci_direct_dma_supported;
}
diff --git a/arch/ppc64/kernel/pci_dn.c b/arch/ppc64/kernel/pci_dn.c
index 280b744fe64e3..ec345462afc3f 100644
--- a/arch/ppc64/kernel/pci_dn.c
+++ b/arch/ppc64/kernel/pci_dn.c
@@ -27,6 +27,7 @@
#include <asm/io.h>
#include <asm/prom.h>
#include <asm/pci-bridge.h>
+#include <asm/pSeries_reconfig.h>
#include "pci.h"
@@ -37,6 +38,7 @@
static void * __devinit update_dn_pci_info(struct device_node *dn, void *data)
{
struct pci_controller *phb = data;
+ int *type = (int *)get_property(dn, "ibm,pci-config-space-type", NULL);
u32 *regs;
dn->phb = phb;
@@ -46,6 +48,8 @@ static void * __devinit update_dn_pci_info(struct device_node *dn, void *data)
dn->busno = (regs[0] >> 16) & 0xff;
dn->devfn = (regs[0] >> 8) & 0xff;
}
+
+ dn->pci_ext_config_space = (type && *type == 1);
return NULL;
}
@@ -158,6 +162,25 @@ struct device_node *fetch_dev_dn(struct pci_dev *dev)
}
EXPORT_SYMBOL(fetch_dev_dn);
+static int pci_dn_reconfig_notifier(struct notifier_block *nb, unsigned long action, void *node)
+{
+ struct device_node *np = node;
+ int err = NOTIFY_OK;
+
+ switch (action) {
+ case PSERIES_RECONFIG_ADD:
+ update_dn_pci_info(np, np->parent->phb);
+ break;
+ default:
+ err = NOTIFY_DONE;
+ break;
+ }
+ return err;
+}
+
+static struct notifier_block pci_dn_reconfig_nb = {
+ .notifier_call = pci_dn_reconfig_notifier,
+};
/*
* Actually initialize the phbs.
@@ -170,4 +193,6 @@ void __init pci_devs_phb_init(void)
/* This must be done first so the device nodes have valid pci info! */
list_for_each_entry_safe(phb, tmp, &hose_list, list_node)
pci_devs_phb_init_dynamic(phb);
+
+ pSeries_reconfig_notifier_register(&pci_dn_reconfig_nb);
}
diff --git a/arch/ppc64/kernel/pci_iommu.c b/arch/ppc64/kernel/pci_iommu.c
index dd5ad02d7e08d..ef0a62b916be5 100644
--- a/arch/ppc64/kernel/pci_iommu.c
+++ b/arch/ppc64/kernel/pci_iommu.c
@@ -50,19 +50,23 @@
*/
#define PCI_GET_DN(dev) ((struct device_node *)((dev)->sysdata))
-static inline struct iommu_table *devnode_table(struct pci_dev *dev)
+static inline struct iommu_table *devnode_table(struct device *dev)
{
- if (!dev)
- dev = ppc64_isabridge_dev;
- if (!dev)
- return NULL;
+ struct pci_dev *pdev;
+
+ if (!dev) {
+ pdev = ppc64_isabridge_dev;
+ if (!pdev)
+ return NULL;
+ } else
+ pdev = to_pci_dev(dev);
#ifdef CONFIG_PPC_ISERIES
- return ISERIES_DEVNODE(dev)->iommu_table;
+ return ISERIES_DEVNODE(pdev)->iommu_table;
#endif /* CONFIG_PPC_ISERIES */
#ifdef CONFIG_PPC_MULTIPLATFORM
- return PCI_GET_DN(dev)->iommu_table;
+ return PCI_GET_DN(pdev)->iommu_table;
#endif /* CONFIG_PPC_MULTIPLATFORM */
}
@@ -71,16 +75,17 @@ static inline struct iommu_table *devnode_table(struct pci_dev *dev)
* Returns the virtual address of the buffer and sets dma_handle
* to the dma address (mapping) of the first page.
*/
-static void *pci_iommu_alloc_consistent(struct pci_dev *hwdev, size_t size,
- dma_addr_t *dma_handle)
+static void *pci_iommu_alloc_coherent(struct device *hwdev, size_t size,
+ dma_addr_t *dma_handle, unsigned int __nocast flag)
{
- return iommu_alloc_consistent(devnode_table(hwdev), size, dma_handle);
+ return iommu_alloc_coherent(devnode_table(hwdev), size, dma_handle,
+ flag);
}
-static void pci_iommu_free_consistent(struct pci_dev *hwdev, size_t size,
+static void pci_iommu_free_coherent(struct device *hwdev, size_t size,
void *vaddr, dma_addr_t dma_handle)
{
- iommu_free_consistent(devnode_table(hwdev), size, vaddr, dma_handle);
+ iommu_free_coherent(devnode_table(hwdev), size, vaddr, dma_handle);
}
/* Creates TCEs for a user provided buffer. The user buffer must be
@@ -89,46 +94,46 @@ static void pci_iommu_free_consistent(struct pci_dev *hwdev, size_t size,
* need not be page aligned, the dma_addr_t returned will point to the same
* byte within the page as vaddr.
*/
-static dma_addr_t pci_iommu_map_single(struct pci_dev *hwdev, void *vaddr,
+static dma_addr_t pci_iommu_map_single(struct device *hwdev, void *vaddr,
size_t size, enum dma_data_direction direction)
{
return iommu_map_single(devnode_table(hwdev), vaddr, size, direction);
}
-static void pci_iommu_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_handle,
+static void pci_iommu_unmap_single(struct device *hwdev, dma_addr_t dma_handle,
size_t size, enum dma_data_direction direction)
{
iommu_unmap_single(devnode_table(hwdev), dma_handle, size, direction);
}
-static int pci_iommu_map_sg(struct pci_dev *pdev, struct scatterlist *sglist,
+static int pci_iommu_map_sg(struct device *pdev, struct scatterlist *sglist,
int nelems, enum dma_data_direction direction)
{
- return iommu_map_sg(&pdev->dev, devnode_table(pdev), sglist,
+ return iommu_map_sg(pdev, devnode_table(pdev), sglist,
nelems, direction);
}
-static void pci_iommu_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist,
+static void pci_iommu_unmap_sg(struct device *pdev, struct scatterlist *sglist,
int nelems, enum dma_data_direction direction)
{
iommu_unmap_sg(devnode_table(pdev), sglist, nelems, direction);
}
/* We support DMA to/from any memory page via the iommu */
-static int pci_iommu_dma_supported(struct pci_dev *pdev, u64 mask)
+static int pci_iommu_dma_supported(struct device *dev, u64 mask)
{
return 1;
}
void pci_iommu_init(void)
{
- pci_dma_ops.pci_alloc_consistent = pci_iommu_alloc_consistent;
- pci_dma_ops.pci_free_consistent = pci_iommu_free_consistent;
- pci_dma_ops.pci_map_single = pci_iommu_map_single;
- pci_dma_ops.pci_unmap_single = pci_iommu_unmap_single;
- pci_dma_ops.pci_map_sg = pci_iommu_map_sg;
- pci_dma_ops.pci_unmap_sg = pci_iommu_unmap_sg;
- pci_dma_ops.pci_dma_supported = pci_iommu_dma_supported;
+ pci_dma_ops.alloc_coherent = pci_iommu_alloc_coherent;
+ pci_dma_ops.free_coherent = pci_iommu_free_coherent;
+ pci_dma_ops.map_single = pci_iommu_map_single;
+ pci_dma_ops.unmap_single = pci_iommu_unmap_single;
+ pci_dma_ops.map_sg = pci_iommu_map_sg;
+ pci_dma_ops.unmap_sg = pci_iommu_unmap_sg;
+ pci_dma_ops.dma_supported = pci_iommu_dma_supported;
}
diff --git a/arch/ppc64/kernel/pmac_feature.c b/arch/ppc64/kernel/pmac_feature.c
index 56686fc9df0db..7f1062d222c9e 100644
--- a/arch/ppc64/kernel/pmac_feature.c
+++ b/arch/ppc64/kernel/pmac_feature.c
@@ -220,6 +220,36 @@ static long __pmac g5_mpic_enable(struct device_node* node, long param, long val
return 0;
}
+static long __pmac g5_eth_phy_reset(struct device_node* node, long param, long value)
+{
+ struct macio_chip* macio = &macio_chips[0];
+ struct device_node *phy;
+ int need_reset;
+
+ /*
+ * We must not reset the combo PHYs, only the BCM5221 found in
+ * the iMac G5.
+ */
+ phy = of_get_next_child(node, NULL);
+ if (!phy)
+ return -ENODEV;
+ need_reset = device_is_compatible(phy, "B5221");
+ of_node_put(phy);
+ if (!need_reset)
+ return 0;
+
+ /* PHY reset is GPIO 29, not in device-tree unfortunately */
+ MACIO_OUT8(K2_GPIO_EXTINT_0 + 29,
+ KEYLARGO_GPIO_OUTPUT_ENABLE | KEYLARGO_GPIO_OUTOUT_DATA);
+ /* Thankfully, this is now always called at a time when we can
+ * schedule by sungem.
+ */
+ msleep(10);
+ MACIO_OUT8(K2_GPIO_EXTINT_0 + 29, 0);
+
+ return 0;
+}
+
#ifdef CONFIG_SMP
static long __pmac g5_reset_cpu(struct device_node* node, long param, long value)
{
@@ -306,6 +336,7 @@ static struct feature_table_entry g5_features[] __pmacdata = {
{ PMAC_FTR_ENABLE_MPIC, g5_mpic_enable },
{ PMAC_FTR_READ_GPIO, g5_read_gpio },
{ PMAC_FTR_WRITE_GPIO, g5_write_gpio },
+ { PMAC_FTR_GMAC_PHY_RESET, g5_eth_phy_reset },
#ifdef CONFIG_SMP
{ PMAC_FTR_RESET_CPU, g5_reset_cpu },
#endif /* CONFIG_SMP */
@@ -321,8 +352,16 @@ static struct pmac_mb_def pmac_mb_defs[] __pmacdata = {
PMAC_TYPE_POWERMAC_G5, g5_features,
0,
},
+ { "PowerMac8,1", "iMac G5",
+ PMAC_TYPE_IMAC_G5, g5_features,
+ 0,
+ },
+ { "PowerMac9,1", "PowerMac G5",
+ PMAC_TYPE_POWERMAC_G5_U3L, g5_features,
+ 0,
+ },
{ "RackMac3,1", "XServe G5",
- PMAC_TYPE_POWERMAC_G5, g5_features,
+ PMAC_TYPE_XSERVE_G5, g5_features,
0,
},
};
diff --git a/arch/ppc64/kernel/pmac_pci.c b/arch/ppc64/kernel/pmac_pci.c
index a0df4e8c0236b..71fe911ad1839 100644
--- a/arch/ppc64/kernel/pmac_pci.c
+++ b/arch/ppc64/kernel/pmac_pci.c
@@ -656,13 +656,32 @@ static int __init add_bridge(struct device_node *dev)
return 0;
}
+/*
+ * We use our own read_irq_line here because PCI_INTERRUPT_PIN is
+ * crap on some of Apple ASICs. We unconditionally use the Open Firmware
+ * interrupt number as this is always right.
+ */
+static int pmac_pci_read_irq_line(struct pci_dev *pci_dev)
+{
+ struct device_node *node;
+
+ node = pci_device_to_OF_node(pci_dev);
+ if (node == NULL)
+ return -1;
+ if (node->n_intrs == 0)
+ return -1;
+ pci_dev->irq = node->intrs[0].line;
+ pci_write_config_byte(pci_dev, PCI_INTERRUPT_LINE, pci_dev->irq);
+
+ return 0;
+}
void __init pmac_pcibios_fixup(void)
{
struct pci_dev *dev = NULL;
for_each_pci_dev(dev)
- pci_read_irq_line(dev);
+ pmac_pci_read_irq_line(dev);
}
static void __init pmac_fixup_phb_resources(void)
@@ -771,3 +790,4 @@ static void fixup_k2_sata(struct pci_dev* dev)
}
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SERVERWORKS, 0x0240, fixup_k2_sata);
+
diff --git a/arch/ppc64/kernel/pmac_setup.c b/arch/ppc64/kernel/pmac_setup.c
index 41fa6e95a06f9..6cf03d387b912 100644
--- a/arch/ppc64/kernel/pmac_setup.c
+++ b/arch/ppc64/kernel/pmac_setup.c
@@ -70,6 +70,7 @@
#include <asm/time.h>
#include <asm/of_device.h>
#include <asm/lmb.h>
+#include <asm/smu.h>
#include "pmac.h"
#include "mpic.h"
@@ -80,13 +81,20 @@
#define DBG(fmt...)
#endif
-
static int current_root_goodness = -1;
#define DEFAULT_ROOT_DEVICE Root_SDA1 /* sda1 - slightly silly choice */
extern int powersave_nap;
int sccdbg;
+sys_ctrler_t sys_ctrler;
+EXPORT_SYMBOL(sys_ctrler);
+
+#ifdef CONFIG_PMAC_SMU
+unsigned long smu_cmdbuf_abs;
+EXPORT_SYMBOL(smu_cmdbuf_abs);
+#endif
+
extern void udbg_init_scc(struct device_node *np);
void __pmac pmac_show_cpuinfo(struct seq_file *m)
@@ -155,8 +163,14 @@ void __init pmac_setup_arch(void)
/* We can NAP */
powersave_nap = 1;
- /* Initialize the PMU */
+#ifdef CONFIG_ADB_PMU
+ /* Initialize the PMU if any */
find_via_pmu();
+#endif
+#ifdef CONFIG_PMAC_SMU
+ /* Initialize the SMU if any */
+ smu_init();
+#endif
/* Init NVRAM access */
pmac_nvram_init();
@@ -216,12 +230,39 @@ void __pmac note_bootable_part(dev_t dev, int part, int goodness)
void __pmac pmac_restart(char *cmd)
{
- pmu_restart();
+ switch(sys_ctrler) {
+#ifdef CONFIG_ADB_PMU
+ case SYS_CTRLER_PMU:
+ pmu_restart();
+ break;
+#endif
+
+#ifdef CONFIG_PMAC_SMU
+ case SYS_CTRLER_SMU:
+ smu_restart();
+ break;
+#endif
+ default:
+ ;
+ }
}
void __pmac pmac_power_off(void)
{
- pmu_shutdown();
+ switch(sys_ctrler) {
+#ifdef CONFIG_ADB_PMU
+ case SYS_CTRLER_PMU:
+ pmu_shutdown();
+ break;
+#endif
+#ifdef CONFIG_PMAC_SMU
+ case SYS_CTRLER_SMU:
+ smu_shutdown();
+ break;
+#endif
+ default:
+ ;
+ }
}
void __pmac pmac_halt(void)
@@ -244,7 +285,6 @@ static void btext_putc(unsigned char c)
{
btext_drawchar(c);
}
-#endif /* CONFIG_BOOTX_TEXT */
static void __init init_boot_display(void)
{
@@ -280,6 +320,7 @@ static void __init init_boot_display(void)
return;
}
}
+#endif /* CONFIG_BOOTX_TEXT */
/*
* Early initialization.
@@ -426,7 +467,6 @@ static int __init pmac_probe(int platform)
{
if (platform != PLATFORM_POWERMAC)
return 0;
-
/*
* On U3, the DART (iommu) must be allocated now since it
* has an impact on htab_initialize (due to the large page it
@@ -435,10 +475,22 @@ static int __init pmac_probe(int platform)
*/
alloc_u3_dart_table();
+#ifdef CONFIG_PMAC_SMU
+ /*
+ * SMU based G5s need some memory below 2Gb, at least the current
+ * driver needs that. We have to allocate it now. We allocate 4k
+ * (1 small page) for now.
+ */
+ smu_cmdbuf_abs = lmb_alloc_base(4096, 4096, 0x80000000UL);
+#endif /* CONFIG_PMAC_SMU */
+
return 1;
}
struct machdep_calls __initdata pmac_md = {
+#ifdef CONFIG_HOTPLUG_CPU
+ .cpu_die = generic_mach_cpu_die,
+#endif
.probe = pmac_probe,
.setup_arch = pmac_setup_arch,
.init_early = pmac_init_early,
diff --git a/arch/ppc64/kernel/pmac_smp.c b/arch/ppc64/kernel/pmac_smp.c
index e0b37079943c5..c27588ede2fea 100644
--- a/arch/ppc64/kernel/pmac_smp.c
+++ b/arch/ppc64/kernel/pmac_smp.c
@@ -308,4 +308,9 @@ struct smp_ops_t core99_smp_ops __pmacdata = {
void __init pmac_setup_smp(void)
{
smp_ops = &core99_smp_ops;
+#ifdef CONFIG_HOTPLUG_CPU
+ smp_ops->cpu_enable = generic_cpu_enable;
+ smp_ops->cpu_disable = generic_cpu_disable;
+ smp_ops->cpu_die = generic_cpu_die;
+#endif
}
diff --git a/arch/ppc64/kernel/pmac_time.c b/arch/ppc64/kernel/pmac_time.c
index 06f379855e783..f24827581dd7c 100644
--- a/arch/ppc64/kernel/pmac_time.c
+++ b/arch/ppc64/kernel/pmac_time.c
@@ -6,6 +6,8 @@
*
* Paul Mackerras August 1996.
* Copyright (C) 1996 Paul Mackerras.
+ * Copyright (C) 2003-2005 Benjamin Herrenschmidt.
+ *
*/
#include <linux/config.h>
#include <linux/errno.h>
@@ -28,6 +30,7 @@
#include <asm/machdep.h>
#include <asm/time.h>
#include <asm/nvram.h>
+#include <asm/smu.h>
#undef DEBUG
@@ -55,54 +58,86 @@ extern void to_tm(int tim, struct rtc_time * tm);
void __pmac pmac_get_rtc_time(struct rtc_time *tm)
{
- struct adb_request req;
- unsigned int now;
-
- /* Get the time from the RTC */
- if (pmu_request(&req, NULL, 1, PMU_READ_RTC) < 0)
- return;
- 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];
- DBG("get: %u -> %u\n", (int)now, (int)(now - RTC_OFFSET));
- now -= RTC_OFFSET;
-
- to_tm(now, tm);
- tm->tm_year -= 1900;
- tm->tm_mon -= 1;
+ switch(sys_ctrler) {
+#ifdef CONFIG_ADB_PMU
+ case SYS_CTRLER_PMU: {
+ /* TODO: Move that to a function in the PMU driver */
+ struct adb_request req;
+ unsigned int now;
+
+ if (pmu_request(&req, NULL, 1, PMU_READ_RTC) < 0)
+ return;
+ pmu_wait_complete(&req);
+ if (req.reply_len != 4)
+ printk(KERN_ERR "pmac_get_rtc_time: PMU returned a %d"
+ " bytes reply\n", req.reply_len);
+ now = (req.reply[0] << 24) + (req.reply[1] << 16)
+ + (req.reply[2] << 8) + req.reply[3];
+ DBG("get: %u -> %u\n", (int)now, (int)(now - RTC_OFFSET));
+ now -= RTC_OFFSET;
+
+ to_tm(now, tm);
+ tm->tm_year -= 1900;
+ tm->tm_mon -= 1;
- DBG("-> tm_mday: %d, tm_mon: %d, tm_year: %d, %d:%02d:%02d\n",
- tm->tm_mday, tm->tm_mon, tm->tm_year,
- tm->tm_hour, tm->tm_min, tm->tm_sec);
+ DBG("-> tm_mday: %d, tm_mon: %d, tm_year: %d, %d:%02d:%02d\n",
+ tm->tm_mday, tm->tm_mon, tm->tm_year,
+ tm->tm_hour, tm->tm_min, tm->tm_sec);
+ break;
+ }
+#endif /* CONFIG_ADB_PMU */
+
+#ifdef CONFIG_PMAC_SMU
+ case SYS_CTRLER_SMU:
+ smu_get_rtc_time(tm);
+ break;
+#endif /* CONFIG_PMAC_SMU */
+ default:
+ ;
+ }
}
int __pmac pmac_set_rtc_time(struct rtc_time *tm)
{
- struct adb_request req;
- unsigned int nowtime;
-
- DBG("set: tm_mday: %d, tm_mon: %d, tm_year: %d, %d:%02d:%02d\n",
- tm->tm_mday, tm->tm_mon, tm->tm_year,
- tm->tm_hour, tm->tm_min, tm->tm_sec);
-
- nowtime = mktime(tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
- tm->tm_hour, tm->tm_min, tm->tm_sec);
- DBG("-> %u -> %u\n", (int)nowtime, (int)(nowtime + RTC_OFFSET));
- nowtime += RTC_OFFSET;
-
- if (pmu_request(&req, NULL, 5, PMU_SET_RTC,
- nowtime >> 24, nowtime >> 16, nowtime >> 8, nowtime) < 0)
+ switch(sys_ctrler) {
+#ifdef CONFIG_ADB_PMU
+ case SYS_CTRLER_PMU: {
+ /* TODO: Move that to a function in the PMU driver */
+ struct adb_request req;
+ unsigned int nowtime;
+
+ DBG("set: tm_mday: %d, tm_mon: %d, tm_year: %d,"
+ " %d:%02d:%02d\n",
+ tm->tm_mday, tm->tm_mon, tm->tm_year,
+ tm->tm_hour, tm->tm_min, tm->tm_sec);
+
+ nowtime = mktime(tm->tm_year + 1900, tm->tm_mon + 1,
+ tm->tm_mday, tm->tm_hour, tm->tm_min,
+ tm->tm_sec);
+
+ DBG("-> %u -> %u\n", (int)nowtime,
+ (int)(nowtime + RTC_OFFSET));
+ nowtime += RTC_OFFSET;
+
+ if (pmu_request(&req, NULL, 5, PMU_SET_RTC,
+ nowtime >> 24, nowtime >> 16,
+ nowtime >> 8, nowtime) < 0)
+ return -ENXIO;
+ pmu_wait_complete(&req);
+ if (req.reply_len != 0)
+ printk(KERN_ERR "pmac_set_rtc_time: PMU returned a %d"
+ " bytes reply\n", req.reply_len);
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 */
+
+#ifdef CONFIG_PMAC_SMU
+ case SYS_CTRLER_SMU:
+ return smu_set_rtc_time(tm);
+#endif /* CONFIG_PMAC_SMU */
+ default:
+ return -ENODEV;
+ }
}
void __init pmac_get_boot_time(struct rtc_time *tm)
diff --git a/arch/ppc64/kernel/pmc.c b/arch/ppc64/kernel/pmc.c
new file mode 100644
index 0000000000000..cd951cbd1e0d5
--- /dev/null
+++ b/arch/ppc64/kernel/pmc.c
@@ -0,0 +1,64 @@
+/*
+ * linux/arch/ppc64/kernel/pmc.c
+ *
+ * Copyright (C) 2004 David Gibson, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/spinlock.h>
+
+#include <asm/processor.h>
+#include <asm/pmc.h>
+
+/* Ensure exceptions are disabled */
+static void dummy_perf(struct pt_regs *regs)
+{
+ unsigned int mmcr0 = mfspr(SPRN_MMCR0);
+
+ mmcr0 &= ~(MMCR0_PMXE|MMCR0_PMAO);
+ mtspr(SPRN_MMCR0, mmcr0);
+}
+
+static spinlock_t pmc_owner_lock = SPIN_LOCK_UNLOCKED;
+static void *pmc_owner_caller; /* mostly for debugging */
+perf_irq_t perf_irq = dummy_perf;
+
+int reserve_pmc_hardware(perf_irq_t new_perf_irq)
+{
+ int err = 0;
+
+ spin_lock(&pmc_owner_lock);
+
+ if (pmc_owner_caller) {
+ printk(KERN_WARNING "reserve_pmc_hardware: "
+ "PMC hardware busy (reserved by caller %p)\n",
+ pmc_owner_caller);
+ err = -EBUSY;
+ goto out;
+ }
+
+ pmc_owner_caller = __builtin_return_address(0);
+ perf_irq = new_perf_irq ? : dummy_perf;
+
+ out:
+ spin_unlock(&pmc_owner_lock);
+ return err;
+}
+
+void release_pmc_hardware(void)
+{
+ spin_lock(&pmc_owner_lock);
+
+ WARN_ON(! pmc_owner_caller);
+
+ pmc_owner_caller = NULL;
+ perf_irq = dummy_perf;
+
+ spin_unlock(&pmc_owner_lock);
+}
diff --git a/arch/ppc64/kernel/ppc_ksyms.c b/arch/ppc64/kernel/ppc_ksyms.c
index 38c0398d823cc..6ced63a3439fb 100644
--- a/arch/ppc64/kernel/ppc_ksyms.c
+++ b/arch/ppc64/kernel/ppc_ksyms.c
@@ -8,49 +8,18 @@
*/
#include <linux/config.h>
#include <linux/module.h>
-#include <linux/threads.h>
-#include <linux/smp.h>
-#include <linux/elfcore.h>
-#include <linux/sched.h>
#include <linux/string.h>
-#include <linux/interrupt.h>
-#include <linux/spinlock.h>
#include <linux/console.h>
-#include <linux/irq.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/smp_lock.h>
-#include <linux/syscalls.h>
-#include <linux/bitops.h>
+#include <net/checksum.h>
-#include <asm/page.h>
-#include <asm/semaphore.h>
#include <asm/processor.h>
#include <asm/uaccess.h>
#include <asm/io.h>
-#include <asm/atomic.h>
-#include <asm/checksum.h>
-#include <asm/pgtable.h>
-#include <asm/prom.h>
#include <asm/system.h>
-#include <asm/pci-bridge.h>
-#include <asm/irq.h>
-#include <asm/dma.h>
-#include <asm/machdep.h>
#include <asm/hw_irq.h>
#include <asm/abs_addr.h>
#include <asm/cacheflush.h>
-#ifdef CONFIG_PPC_ISERIES
#include <asm/iSeries/HvCallSc.h>
-#include <asm/iSeries/LparData.h>
-#endif
-
-extern int do_signal(sigset_t *, struct pt_regs *);
-
-EXPORT_SYMBOL(do_signal);
-
-EXPORT_SYMBOL(isa_io_base);
-EXPORT_SYMBOL(pci_io_base);
EXPORT_SYMBOL(strcpy);
EXPORT_SYMBOL(strncpy);
@@ -65,10 +34,6 @@ EXPORT_SYMBOL(strnlen);
EXPORT_SYMBOL(strcmp);
EXPORT_SYMBOL(strncmp);
-EXPORT_SYMBOL(__down_interruptible);
-EXPORT_SYMBOL(__up);
-EXPORT_SYMBOL(__down);
-
EXPORT_SYMBOL(csum_partial);
EXPORT_SYMBOL(csum_partial_copy_generic);
EXPORT_SYMBOL(ip_fast_csum);
@@ -79,11 +44,6 @@ EXPORT_SYMBOL(__clear_user);
EXPORT_SYMBOL(__strncpy_from_user);
EXPORT_SYMBOL(__strnlen_user);
-EXPORT_SYMBOL(clear_user_page);
-
-#ifdef CONFIG_MSCHUNKS
-EXPORT_SYMBOL(msChunks);
-#endif
EXPORT_SYMBOL(reloc_offset);
#ifdef CONFIG_PPC_ISERIES
@@ -107,11 +67,7 @@ EXPORT_SYMBOL(_insw_ns);
EXPORT_SYMBOL(_outsw_ns);
EXPORT_SYMBOL(_insl_ns);
EXPORT_SYMBOL(_outsl_ns);
-EXPORT_SYMBOL(ioremap);
-EXPORT_SYMBOL(__ioremap);
-EXPORT_SYMBOL(iounmap);
-EXPORT_SYMBOL(start_thread);
EXPORT_SYMBOL(kernel_thread);
EXPORT_SYMBOL(giveup_fpu);
@@ -119,8 +75,7 @@ EXPORT_SYMBOL(giveup_fpu);
EXPORT_SYMBOL(giveup_altivec);
#endif
EXPORT_SYMBOL(flush_icache_range);
-EXPORT_SYMBOL(flush_icache_user_range);
-EXPORT_SYMBOL(flush_dcache_page);
+
#ifdef CONFIG_SMP
#ifdef CONFIG_PPC_ISERIES
EXPORT_SYMBOL(local_get_flags);
@@ -129,19 +84,6 @@ EXPORT_SYMBOL(local_irq_restore);
#endif
#endif
-EXPORT_SYMBOL(ppc_md);
-
-#ifdef CONFIG_PPC_MULTIPLATFORM
-EXPORT_SYMBOL(find_devices);
-EXPORT_SYMBOL(find_type_devices);
-EXPORT_SYMBOL(find_compatible_devices);
-EXPORT_SYMBOL(find_path_device);
-EXPORT_SYMBOL(device_is_compatible);
-EXPORT_SYMBOL(machine_is_compatible);
-EXPORT_SYMBOL(find_all_nodes);
-EXPORT_SYMBOL(get_property);
-#endif
-
EXPORT_SYMBOL(memcpy);
EXPORT_SYMBOL(memset);
EXPORT_SYMBOL(memmove);
@@ -150,10 +92,4 @@ EXPORT_SYMBOL(memcmp);
EXPORT_SYMBOL(memchr);
EXPORT_SYMBOL(timer_interrupt);
-EXPORT_SYMBOL(irq_desc);
-EXPORT_SYMBOL(get_wchan);
EXPORT_SYMBOL(console_drivers);
-
-EXPORT_SYMBOL(tb_ticks_per_usec);
-EXPORT_SYMBOL(paca);
-EXPORT_SYMBOL(cur_cpu_spec);
diff --git a/arch/ppc64/kernel/proc_ppc64.c b/arch/ppc64/kernel/proc_ppc64.c
index d3bd869faa95d..0914b0669b05e 100644
--- a/arch/ppc64/kernel/proc_ppc64.c
+++ b/arch/ppc64/kernel/proc_ppc64.c
@@ -41,20 +41,6 @@ static struct file_operations page_map_fops = {
.mmap = page_map_mmap
};
-#ifdef CONFIG_PPC_PSERIES
-/* routines for /proc/ppc64/ofdt */
-static ssize_t ofdt_write(struct file *, const char __user *, size_t, loff_t *);
-static void proc_ppc64_create_ofdt(void);
-static int do_remove_node(char *);
-static int do_add_node(char *, size_t);
-static void release_prop_list(const struct property *);
-static struct property *new_property(const char *, const int, const unsigned char *, struct property *);
-static char * parse_next_property(char *, char *, char **, int *, unsigned char**);
-static struct file_operations ofdt_fops = {
- .write = ofdt_write
-};
-#endif
-
/*
* Create the ppc64 and ppc64/rtas directories early. This allows us to
* assume that they have been previously created in drivers.
@@ -89,14 +75,9 @@ static int __init proc_ppc64_init(void)
return 1;
pde->nlink = 1;
pde->data = systemcfg;
- pde->size = 4096;
+ pde->size = PAGE_SIZE;
pde->proc_fops = &page_map_fops;
-#ifdef CONFIG_PPC_PSERIES
- if ((systemcfg->platform & PLATFORM_PSERIES))
- proc_ppc64_create_ofdt();
-#endif
-
return 0;
}
__initcall(proc_ppc64_init);
@@ -145,233 +126,3 @@ static int page_map_mmap( struct file *file, struct vm_area_struct *vma )
return 0;
}
-#ifdef CONFIG_PPC_PSERIES
-/* create /proc/ppc64/ofdt write-only by root */
-static void proc_ppc64_create_ofdt(void)
-{
- struct proc_dir_entry *ent;
-
- ent = create_proc_entry("ppc64/ofdt", S_IWUSR, NULL);
- if (ent) {
- ent->nlink = 1;
- ent->data = NULL;
- ent->size = 0;
- ent->proc_fops = &ofdt_fops;
- }
-}
-
-/**
- * ofdt_write - perform operations on the Open Firmware device tree
- *
- * @file: not used
- * @buf: command and arguments
- * @count: size of the command buffer
- * @off: not used
- *
- * Operations supported at this time are addition and removal of
- * whole nodes along with their properties. Operations on individual
- * properties are not implemented (yet).
- */
-static ssize_t ofdt_write(struct file *file, const char __user *buf, size_t count,
- loff_t *off)
-{
- int rv = 0;
- char *kbuf;
- char *tmp;
-
- if (!(kbuf = kmalloc(count + 1, GFP_KERNEL))) {
- rv = -ENOMEM;
- goto out;
- }
- if (copy_from_user(kbuf, buf, count)) {
- rv = -EFAULT;
- goto out;
- }
-
- kbuf[count] = '\0';
-
- tmp = strchr(kbuf, ' ');
- if (!tmp) {
- rv = -EINVAL;
- goto out;
- }
- *tmp = '\0';
- tmp++;
-
- if (!strcmp(kbuf, "add_node"))
- rv = do_add_node(tmp, count - (tmp - kbuf));
- else if (!strcmp(kbuf, "remove_node"))
- rv = do_remove_node(tmp);
- else
- rv = -EINVAL;
-out:
- kfree(kbuf);
- return rv ? rv : count;
-}
-
-static int do_remove_node(char *buf)
-{
- struct device_node *node;
- int rv = -ENODEV;
-
- if ((node = of_find_node_by_path(buf)))
- rv = of_remove_node(node);
-
- of_node_put(node);
- return rv;
-}
-
-static int do_add_node(char *buf, size_t bufsize)
-{
- char *path, *end, *name;
- struct device_node *np;
- struct property *prop = NULL;
- unsigned char* value;
- int length, rv = 0;
-
- end = buf + bufsize;
- path = buf;
- buf = strchr(buf, ' ');
- if (!buf)
- return -EINVAL;
- *buf = '\0';
- buf++;
-
- if ((np = of_find_node_by_path(path))) {
- of_node_put(np);
- return -EINVAL;
- }
-
- /* rv = build_prop_list(tmp, bufsize - (tmp - buf), &proplist); */
- while (buf < end &&
- (buf = parse_next_property(buf, end, &name, &length, &value))) {
- struct property *last = prop;
-
- prop = new_property(name, length, value, last);
- if (!prop) {
- rv = -ENOMEM;
- prop = last;
- goto out;
- }
- }
- if (!buf) {
- rv = -EINVAL;
- goto out;
- }
-
- rv = of_add_node(path, prop);
-
-out:
- if (rv)
- release_prop_list(prop);
- return rv;
-}
-
-static struct property *new_property(const char *name, const int length,
- const unsigned char *value, struct property *last)
-{
- struct property *new = kmalloc(sizeof(*new), GFP_KERNEL);
-
- if (!new)
- return NULL;
- memset(new, 0, sizeof(*new));
-
- if (!(new->name = kmalloc(strlen(name) + 1, GFP_KERNEL)))
- goto cleanup;
- if (!(new->value = kmalloc(length + 1, GFP_KERNEL)))
- goto cleanup;
-
- strcpy(new->name, name);
- memcpy(new->value, value, length);
- *(((char *)new->value) + length) = 0;
- new->length = length;
- new->next = last;
- return new;
-
-cleanup:
- if (new->name)
- kfree(new->name);
- if (new->value)
- kfree(new->value);
- kfree(new);
- return NULL;
-}
-
-/**
- * parse_next_property - process the next property from raw input buffer
- * @buf: input buffer, must be nul-terminated
- * @end: end of the input buffer + 1, for validation
- * @name: return value; set to property name in buf
- * @length: return value; set to length of value
- * @value: return value; set to the property value in buf
- *
- * Note that the caller must make copies of the name and value returned,
- * this function does no allocation or copying of the data. Return value
- * is set to the next name in buf, or NULL on error.
- */
-static char * parse_next_property(char *buf, char *end, char **name, int *length,
- unsigned char **value)
-{
- char *tmp;
-
- *name = buf;
-
- tmp = strchr(buf, ' ');
- if (!tmp) {
- printk(KERN_ERR "property parse failed in %s at line %d\n",
- __FUNCTION__, __LINE__);
- return NULL;
- }
- *tmp = '\0';
-
- if (++tmp >= end) {
- printk(KERN_ERR "property parse failed in %s at line %d\n",
- __FUNCTION__, __LINE__);
- return NULL;
- }
-
- /* now we're on the length */
- *length = -1;
- *length = simple_strtoul(tmp, &tmp, 10);
- if (*length == -1) {
- printk(KERN_ERR "property parse failed in %s at line %d\n",
- __FUNCTION__, __LINE__);
- return NULL;
- }
- if (*tmp != ' ' || ++tmp >= end) {
- printk(KERN_ERR "property parse failed in %s at line %d\n",
- __FUNCTION__, __LINE__);
- return NULL;
- }
-
- /* now we're on the value */
- *value = tmp;
- tmp += *length;
- if (tmp > end) {
- printk(KERN_ERR "property parse failed in %s at line %d\n",
- __FUNCTION__, __LINE__);
- return NULL;
- }
- else if (tmp < end && *tmp != ' ' && *tmp != '\0') {
- printk(KERN_ERR "property parse failed in %s at line %d\n",
- __FUNCTION__, __LINE__);
- return NULL;
- }
- tmp++;
-
- /* and now we should be on the next name, or the end */
- return tmp;
-}
-
-static void release_prop_list(const struct property *prop)
-{
- struct property *next;
- for (; prop; prop = next) {
- next = prop->next;
- kfree(prop->name);
- kfree(prop->value);
- kfree(prop);
- }
-
-}
-#endif /* defined(CONFIG_PPC_PSERIES) */
diff --git a/arch/ppc64/kernel/process.c b/arch/ppc64/kernel/process.c
index d1c152db959b9..8b06861227385 100644
--- a/arch/ppc64/kernel/process.c
+++ b/arch/ppc64/kernel/process.c
@@ -51,6 +51,7 @@
#include <asm/cputable.h>
#include <asm/sections.h>
#include <asm/tlbflush.h>
+#include <asm/time.h>
#ifndef CONFIG_SMP
struct task_struct *last_task_used_math = NULL;
@@ -168,6 +169,8 @@ int dump_task_altivec(struct pt_regs *regs, elf_vrregset_t *vrregs)
#endif /* CONFIG_ALTIVEC */
+DEFINE_PER_CPU(struct cpu_usage, cpu_usage_array);
+
struct task_struct *__switch_to(struct task_struct *prev,
struct task_struct *new)
{
@@ -206,6 +209,21 @@ struct task_struct *__switch_to(struct task_struct *prev,
new_thread = &new->thread;
old_thread = &current->thread;
+/* Collect purr utilization data per process and per processor wise */
+/* purr is nothing but processor time base */
+
+#if defined(CONFIG_PPC_PSERIES)
+ if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) {
+ struct cpu_usage *cu = &__get_cpu_var(cpu_usage_array);
+ long unsigned start_tb, current_tb;
+ start_tb = old_thread->start_tb;
+ cu->current_tb = current_tb = mfspr(SPRN_PURR);
+ old_thread->accum_tb += (current_tb - start_tb);
+ new_thread->start_tb = current_tb;
+ }
+#endif
+
+
local_irq_save(flags);
last = _switch(old_thread, new_thread);
@@ -388,12 +406,12 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
kregs = (struct pt_regs *) sp;
sp -= STACK_FRAME_OVERHEAD;
p->thread.ksp = sp;
- if (cur_cpu_spec->cpu_features & CPU_FTR_SLB) {
+ if (cpu_has_feature(CPU_FTR_SLB)) {
unsigned long sp_vsid = get_kernel_vsid(sp);
sp_vsid <<= SLB_VSID_SHIFT;
sp_vsid |= SLB_VSID_KERNEL;
- if (cur_cpu_spec->cpu_features & CPU_FTR_16M_PAGE)
+ if (cpu_has_feature(CPU_FTR_16M_PAGE))
sp_vsid |= SLB_VSID_L;
p->thread.ksp_vsid = sp_vsid;
@@ -469,6 +487,7 @@ void start_thread(struct pt_regs *regs, unsigned long fdptr, unsigned long sp)
current->thread.used_vr = 0;
#endif /* CONFIG_ALTIVEC */
}
+EXPORT_SYMBOL(start_thread);
int set_fpexc_mode(struct task_struct *tsk, unsigned int val)
{
@@ -607,6 +626,7 @@ unsigned long get_wchan(struct task_struct *p)
} while (count++ < 16);
return 0;
}
+EXPORT_SYMBOL(get_wchan);
void show_stack(struct task_struct *p, unsigned long *_sp)
{
diff --git a/arch/ppc64/kernel/prom.c b/arch/ppc64/kernel/prom.c
index eed1a707db882..1a5f59b769b91 100644
--- a/arch/ppc64/kernel/prom.c
+++ b/arch/ppc64/kernel/prom.c
@@ -27,11 +27,12 @@
#include <linux/spinlock.h>
#include <linux/types.h>
#include <linux/pci.h>
-#include <linux/proc_fs.h>
#include <linux/stringify.h>
#include <linux/delay.h>
#include <linux/initrd.h>
#include <linux/bitops.h>
+#include <linux/module.h>
+
#include <asm/prom.h>
#include <asm/rtas.h>
#include <asm/lmb.h>
@@ -51,6 +52,7 @@
#include <asm/btext.h>
#include <asm/sections.h>
#include <asm/machdep.h>
+#include <asm/pSeries_reconfig.h>
#ifdef DEBUG
#define DBG(fmt...) udbg_printf(fmt)
@@ -71,8 +73,8 @@ struct isa_reg_property {
};
-typedef unsigned long interpret_func(struct device_node *, unsigned long,
- int, int, int);
+typedef int interpret_func(struct device_node *, unsigned long *,
+ int, int, int);
extern struct rtas_t rtas;
extern struct lmb lmb;
@@ -101,6 +103,25 @@ static DEFINE_RWLOCK(devtree_lock);
struct device_node *of_chosen;
/*
+ * Wrapper for allocating memory for various data that needs to be
+ * attached to device nodes as they are processed at boot or when
+ * added to the device tree later (e.g. DLPAR). At boot there is
+ * already a region reserved so we just increment *mem_start by size;
+ * otherwise we call kmalloc.
+ */
+static void * prom_alloc(unsigned long size, unsigned long *mem_start)
+{
+ unsigned long tmp;
+
+ if (!mem_start)
+ return kmalloc(size, GFP_KERNEL);
+
+ tmp = *mem_start;
+ *mem_start += size;
+ return (void *)tmp;
+}
+
+/*
* Find the device_node with a given phandle.
*/
static struct device_node * find_phandle(phandle ph)
@@ -253,9 +274,9 @@ static int __devinit map_interrupt(unsigned int **irq, struct device_node **ictr
return nintrc;
}
-static unsigned long __init finish_node_interrupts(struct device_node *np,
- unsigned long mem_start,
- int measure_only)
+static int __devinit finish_node_interrupts(struct device_node *np,
+ unsigned long *mem_start,
+ int measure_only)
{
unsigned int *ints;
int intlen, intrcells, intrcount;
@@ -265,14 +286,16 @@ static unsigned long __init finish_node_interrupts(struct device_node *np,
ints = (unsigned int *) get_property(np, "interrupts", &intlen);
if (ints == NULL)
- return mem_start;
+ return 0;
intrcells = prom_n_intr_cells(np);
intlen /= intrcells * sizeof(unsigned int);
- np->intrs = (struct interrupt_info *) mem_start;
- mem_start += intlen * sizeof(struct interrupt_info);
+
+ np->intrs = prom_alloc(intlen * sizeof(*(np->intrs)), mem_start);
+ if (!np->intrs)
+ return -ENOMEM;
if (measure_only)
- return mem_start;
+ return 0;
intrcount = 0;
for (i = 0; i < intlen; ++i, ints += intrcells) {
@@ -313,42 +336,49 @@ static unsigned long __init finish_node_interrupts(struct device_node *np,
}
np->n_intrs = intrcount;
- return mem_start;
+ return 0;
}
-static unsigned long __init interpret_pci_props(struct device_node *np,
- unsigned long mem_start,
- int naddrc, int nsizec,
- int measure_only)
+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;
+ int i, l, n_addrs;
pci_addrs = (struct pci_reg_property *)
get_property(np, "assigned-addresses", &l);
- if (pci_addrs != 0 && l >= sizeof(struct pci_reg_property)) {
- i = 0;
- adr = (struct address_range *) mem_start;
- while ((l -= sizeof(struct pci_reg_property)) >= 0) {
- if (!measure_only) {
- adr[i].space = pci_addrs[i].addr.a_hi;
- adr[i].address = pci_addrs[i].addr.a_lo;
- adr[i].size = pci_addrs[i].size_lo;
- }
- ++i;
- }
- np->addrs = adr;
- np->n_addrs = i;
- mem_start += i * sizeof(struct address_range);
+ if (!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 mem_start;
+
+ return 0;
}
-static unsigned long __init interpret_dbdma_props(struct device_node *np,
- unsigned long mem_start,
- int naddrc, int nsizec,
- int measure_only)
+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;
@@ -369,7 +399,7 @@ static unsigned long __init interpret_dbdma_props(struct device_node *np,
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;
+ adr = (struct address_range *) (*mem_start);
while ((l -= sizeof(struct reg_property32)) >= 0) {
if (!measure_only) {
adr[i].space = 2;
@@ -380,16 +410,16 @@ static unsigned long __init interpret_dbdma_props(struct device_node *np,
}
np->addrs = adr;
np->n_addrs = i;
- mem_start += i * sizeof(struct address_range);
+ (*mem_start) += i * sizeof(struct address_range);
}
- return mem_start;
+ return 0;
}
-static unsigned long __init interpret_macio_props(struct device_node *np,
- unsigned long mem_start,
- int naddrc, int nsizec,
- int measure_only)
+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;
@@ -410,7 +440,7 @@ static unsigned long __init interpret_macio_props(struct device_node *np,
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;
+ adr = (struct address_range *) (*mem_start);
while ((l -= sizeof(struct reg_property32)) >= 0) {
if (!measure_only) {
adr[i].space = 2;
@@ -421,16 +451,16 @@ static unsigned long __init interpret_macio_props(struct device_node *np,
}
np->addrs = adr;
np->n_addrs = i;
- mem_start += i * sizeof(struct address_range);
+ (*mem_start) += i * sizeof(struct address_range);
}
- return mem_start;
+ return 0;
}
-static unsigned long __init interpret_isa_props(struct device_node *np,
- unsigned long mem_start,
- int naddrc, int nsizec,
- int measure_only)
+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;
@@ -439,7 +469,7 @@ static unsigned long __init interpret_isa_props(struct device_node *np,
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;
+ adr = (struct address_range *) (*mem_start);
while ((l -= sizeof(struct isa_reg_property)) >= 0) {
if (!measure_only) {
adr[i].space = rp[i].space;
@@ -450,16 +480,16 @@ static unsigned long __init interpret_isa_props(struct device_node *np,
}
np->addrs = adr;
np->n_addrs = i;
- mem_start += i * sizeof(struct address_range);
+ (*mem_start) += i * sizeof(struct address_range);
}
- return mem_start;
+ return 0;
}
-static unsigned long __init interpret_root_props(struct device_node *np,
- unsigned long mem_start,
- int naddrc, int nsizec,
- int measure_only)
+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;
@@ -469,7 +499,7 @@ static unsigned long __init interpret_root_props(struct device_node *np,
rp = (unsigned int *) get_property(np, "reg", &l);
if (rp != 0 && l >= rpsize) {
i = 0;
- adr = (struct address_range *) mem_start;
+ adr = (struct address_range *) (*mem_start);
while ((l -= rpsize) >= 0) {
if (!measure_only) {
adr[i].space = 0;
@@ -481,26 +511,30 @@ static unsigned long __init interpret_root_props(struct device_node *np,
}
np->addrs = adr;
np->n_addrs = i;
- mem_start += i * sizeof(struct address_range);
+ (*mem_start) += i * sizeof(struct address_range);
}
- return mem_start;
+ return 0;
}
-static unsigned long __init finish_node(struct device_node *np,
- unsigned long mem_start,
- interpret_func *ifunc,
- int naddrc, int nsizec,
- int measure_only)
+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;
+ int *ip, rc = 0;
/* get the device addresses and interrupts */
if (ifunc != NULL)
- mem_start = ifunc(np, mem_start, naddrc, nsizec, measure_only);
+ rc = ifunc(np, mem_start, naddrc, nsizec, measure_only);
+ if (rc)
+ goto out;
- mem_start = finish_node_interrupts(np, mem_start, measure_only);
+ 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);
@@ -536,11 +570,14 @@ static unsigned long __init finish_node(struct device_node *np,
|| !strcmp(np->type, "media-bay"))))
ifunc = NULL;
- for (child = np->child; child != NULL; child = child->sibling)
- mem_start = finish_node(child, mem_start, ifunc,
- naddrc, nsizec, measure_only);
-
- return mem_start;
+ for (child = np->child; child != NULL; child = child->sibling) {
+ rc = finish_node(child, mem_start, ifunc,
+ naddrc, nsizec, measure_only);
+ if (rc)
+ goto out;
+ }
+out:
+ return rc;
}
/**
@@ -552,7 +589,7 @@ static unsigned long __init finish_node(struct device_node *np,
*/
void __init finish_device_tree(void)
{
- unsigned long mem, size;
+ unsigned long start, end, size = 0;
DBG(" -> finish_device_tree\n");
@@ -565,10 +602,10 @@ void __init finish_device_tree(void)
virt_irq_init();
/* Finish device-tree (pre-parsing some properties etc...) */
- size = finish_node(allnodes, 0, NULL, 0, 0, 1);
- mem = (unsigned long)abs_to_virt(lmb_alloc(size, 128));
- if (finish_node(allnodes, mem, NULL, 0, 0, 0) != mem + size)
- BUG();
+ finish_node(allnodes, &size, NULL, 0, 0, 1);
+ end = start = (unsigned long)abs_to_virt(lmb_alloc(size, 128));
+ finish_node(allnodes, &end, NULL, 0, 0, 0);
+ BUG_ON(end != start + size);
DBG(" <- finish_device_tree\n");
}
@@ -875,6 +912,8 @@ static int __init early_init_dt_scan_chosen(unsigned long node,
const char *full_path, void *data)
{
u32 *prop;
+ u64 *prop64;
+ extern unsigned long memory_limit, tce_alloc_start, tce_alloc_end;
if (strcmp(full_path, "/chosen") != 0)
return 0;
@@ -891,7 +930,19 @@ static int __init early_init_dt_scan_chosen(unsigned long node,
if (get_flat_dt_prop(node, "linux,iommu-force-on", NULL) != NULL)
iommu_force_on = 1;
-#ifdef CONFIG_PPC_PSERIES
+ prop64 = (u64*)get_flat_dt_prop(node, "linux,memory-limit", NULL);
+ if (prop64)
+ memory_limit = *prop64;
+
+ prop64 = (u64*)get_flat_dt_prop(node, "linux,tce-alloc-start", NULL);
+ if (prop64)
+ tce_alloc_start = *prop64;
+
+ prop64 = (u64*)get_flat_dt_prop(node, "linux,tce-alloc-end", NULL);
+ if (prop64)
+ tce_alloc_end = *prop64;
+
+#ifdef CONFIG_PPC_RTAS
/* To help early debugging via the front panel, we retreive a minimal
* set of RTAS infos now if available
*/
@@ -907,7 +958,7 @@ static int __init early_init_dt_scan_chosen(unsigned long node,
rtas.size = *prop;
}
}
-#endif /* CONFIG_PPC_PSERIES */
+#endif /* CONFIG_PPC_RTAS */
/* break now */
return 1;
@@ -1030,6 +1081,7 @@ void __init early_init_devtree(void *params)
lmb_init();
scan_flat_dt(early_init_dt_scan_root, NULL);
scan_flat_dt(early_init_dt_scan_memory, NULL);
+ lmb_enforce_memory_limit();
lmb_analyze();
systemcfg->physicalMemorySize = lmb_phys_mem_size();
lmb_reserve(0, __pa(klimit));
@@ -1138,6 +1190,7 @@ find_devices(const char *name)
*prevp = NULL;
return head;
}
+EXPORT_SYMBOL(find_devices);
/**
* Construct and return a list of the device_nodes with a given type.
@@ -1157,6 +1210,7 @@ find_type_devices(const char *type)
*prevp = NULL;
return head;
}
+EXPORT_SYMBOL(find_type_devices);
/**
* Returns all nodes linked together
@@ -1174,6 +1228,7 @@ find_all_nodes(void)
*prevp = NULL;
return head;
}
+EXPORT_SYMBOL(find_all_nodes);
/** Checks if the given "compat" string matches one of the strings in
* the device's "compatible" property
@@ -1197,6 +1252,7 @@ device_is_compatible(struct device_node *device, const char *compat)
return 0;
}
+EXPORT_SYMBOL(device_is_compatible);
/**
@@ -1216,6 +1272,7 @@ machine_is_compatible(const char *compat)
}
return rc;
}
+EXPORT_SYMBOL(machine_is_compatible);
/**
* Construct and return a list of the device_nodes with a given type
@@ -1239,6 +1296,7 @@ find_compatible_devices(const char *type, const char *compat)
*prevp = NULL;
return head;
}
+EXPORT_SYMBOL(find_compatible_devices);
/**
* Find the device_node with a given full_name.
@@ -1253,6 +1311,7 @@ find_path_device(const char *path)
return np;
return NULL;
}
+EXPORT_SYMBOL(find_path_device);
/*******
*
@@ -1531,132 +1590,6 @@ void of_node_put(struct device_node *node)
}
EXPORT_SYMBOL(of_node_put);
-/**
- * derive_parent - basically like dirname(1)
- * @path: the full_name of a node to be added to the tree
- *
- * Returns the node which should be the parent of the node
- * described by path. E.g., for path = "/foo/bar", returns
- * the node with full_name = "/foo".
- */
-static struct device_node *derive_parent(const char *path)
-{
- struct device_node *parent = NULL;
- char *parent_path = "/";
- size_t parent_path_len = strrchr(path, '/') - path + 1;
-
- /* reject if path is "/" */
- if (!strcmp(path, "/"))
- return NULL;
-
- if (strrchr(path, '/') != path) {
- parent_path = kmalloc(parent_path_len, GFP_KERNEL);
- if (!parent_path)
- return NULL;
- strlcpy(parent_path, path, parent_path_len);
- }
- parent = of_find_node_by_path(parent_path);
- if (strcmp(parent_path, "/"))
- kfree(parent_path);
- return parent;
-}
-
-/*
- * Routines for "runtime" addition and removal of device tree nodes.
- */
-#ifdef CONFIG_PROC_DEVICETREE
-/*
- * Add a node to /proc/device-tree.
- */
-static void add_node_proc_entries(struct device_node *np)
-{
- struct proc_dir_entry *ent;
-
- ent = proc_mkdir(strrchr(np->full_name, '/') + 1, np->parent->pde);
- if (ent)
- proc_device_tree_add_node(np, ent);
-}
-
-static void remove_node_proc_entries(struct device_node *np)
-{
- struct property *pp = np->properties;
- struct device_node *parent = np->parent;
-
- while (pp) {
- remove_proc_entry(pp->name, np->pde);
- pp = pp->next;
- }
-
- /* Assuming that symlinks have the same parent directory as
- * np->pde.
- */
- if (np->name_link)
- remove_proc_entry(np->name_link->name, parent->pde);
- if (np->addr_link)
- remove_proc_entry(np->addr_link->name, parent->pde);
- if (np->pde)
- remove_proc_entry(np->pde->name, parent->pde);
-}
-#else /* !CONFIG_PROC_DEVICETREE */
-static void add_node_proc_entries(struct device_node *np)
-{
- return;
-}
-
-static void remove_node_proc_entries(struct device_node *np)
-{
- return;
-}
-#endif /* CONFIG_PROC_DEVICETREE */
-
-/*
- * Fix up n_intrs and intrs fields in a new device node
- *
- */
-static int of_finish_dynamic_node_interrupts(struct device_node *node)
-{
- int intrcells, intlen, i;
- unsigned *irq, *ints, virq;
- struct device_node *ic;
-
- ints = (unsigned int *)get_property(node, "interrupts", &intlen);
- intrcells = prom_n_intr_cells(node);
- intlen /= intrcells * sizeof(unsigned int);
- node->n_intrs = intlen;
- node->intrs = kmalloc(sizeof(struct interrupt_info) * intlen,
- GFP_KERNEL);
- if (!node->intrs)
- return -ENOMEM;
-
- for (i = 0; i < intlen; ++i) {
- int n, j;
- node->intrs[i].line = 0;
- node->intrs[i].sense = 1;
- n = map_interrupt(&irq, &ic, node, ints, intrcells);
- if (n <= 0)
- continue;
- virq = virt_irq_create_mapping(irq[0]);
- if (virq == NO_IRQ) {
- printk(KERN_CRIT "Could not allocate interrupt "
- "number for %s\n", node->full_name);
- return -ENOMEM;
- }
- node->intrs[i].line = irq_offset_up(virq);
- if (n > 1)
- node->intrs[i].sense = irq[1];
- if (n > 2) {
- printk(KERN_DEBUG "hmmm, got %d intr cells for %s:", n,
- node->full_name);
- for (j = 0; j < n; ++j)
- printk(" %d", irq[j]);
- printk("\n");
- }
- ints += intrcells;
- }
- return 0;
-}
-
-
/*
* Fix up the uninitialized fields in a new device node:
* name, type, n_addrs, addrs, n_intrs, intrs, and pci-specific fields
@@ -1668,10 +1601,11 @@ static int of_finish_dynamic_node_interrupts(struct device_node *node)
* This should probably be split up into smaller chunks.
*/
-static int of_finish_dynamic_node(struct device_node *node)
+static int of_finish_dynamic_node(struct device_node *node,
+ unsigned long *unused1, int unused2,
+ int unused3, int unused4)
{
struct device_node *parent = of_get_parent(node);
- u32 *regs;
int err = 0;
phandle *ibm_phandle;
@@ -1693,117 +1627,22 @@ static int of_finish_dynamic_node(struct device_node *node)
if ((ibm_phandle = (unsigned int *)get_property(node, "ibm,phandle", NULL)))
node->linux_phandle = *ibm_phandle;
- /* do the work of interpret_pci_props */
- if (parent->type && !strcmp(parent->type, "pci")) {
- struct address_range *adr;
- struct pci_reg_property *pci_addrs;
- int i, l;
-
- pci_addrs = (struct pci_reg_property *)
- get_property(node, "assigned-addresses", &l);
- if (pci_addrs != 0 && l >= sizeof(struct pci_reg_property)) {
- i = 0;
- adr = kmalloc(sizeof(struct address_range) *
- (l / sizeof(struct pci_reg_property)),
- GFP_KERNEL);
- if (!adr) {
- err = -ENOMEM;
- goto out;
- }
- while ((l -= sizeof(struct pci_reg_property)) >= 0) {
- adr[i].space = pci_addrs[i].addr.a_hi;
- adr[i].address = pci_addrs[i].addr.a_lo;
- adr[i].size = pci_addrs[i].size_lo;
- ++i;
- }
- node->addrs = adr;
- node->n_addrs = i;
- }
- }
-
- /* now do the work of finish_node_interrupts */
- if (get_property(node, "interrupts", NULL)) {
- err = of_finish_dynamic_node_interrupts(node);
- if (err) goto out;
- }
-
- /* now do the rough equivalent of update_dn_pci_info, this
- * probably is not correct for phb's, but should work for
- * IOAs and slots.
- */
-
- node->phb = parent->phb;
-
- regs = (u32 *)get_property(node, "reg", NULL);
- if (regs) {
- node->busno = (regs[0] >> 16) & 0xff;
- node->devfn = (regs[0] >> 8) & 0xff;
- }
-
out:
of_node_put(parent);
return err;
}
/*
- * Given a path and a property list, construct an OF device node, add
- * it to the device tree and global list, and place it in
- * /proc/device-tree. This function may sleep.
+ * Plug a device node into the tree and global list.
*/
-int of_add_node(const char *path, struct property *proplist)
+void of_attach_node(struct device_node *np)
{
- struct device_node *np;
- int err = 0;
-
- np = kmalloc(sizeof(struct device_node), GFP_KERNEL);
- if (!np)
- return -ENOMEM;
-
- memset(np, 0, sizeof(*np));
-
- np->full_name = kmalloc(strlen(path) + 1, GFP_KERNEL);
- if (!np->full_name) {
- kfree(np);
- return -ENOMEM;
- }
- strcpy(np->full_name, path);
-
- np->properties = proplist;
- OF_MARK_DYNAMIC(np);
- kref_init(&np->kref);
- of_node_get(np);
- np->parent = derive_parent(path);
- if (!np->parent) {
- kfree(np);
- return -EINVAL; /* could also be ENOMEM, though */
- }
-
- if (0 != (err = of_finish_dynamic_node(np))) {
- kfree(np);
- return err;
- }
-
write_lock(&devtree_lock);
np->sibling = np->parent->child;
np->allnext = allnodes;
np->parent->child = np;
allnodes = np;
write_unlock(&devtree_lock);
-
- add_node_proc_entries(np);
-
- of_node_put(np->parent);
- of_node_put(np);
- return 0;
-}
-
-/*
- * Prepare an OF node for removal from system
- */
-static void of_cleanup_node(struct device_node *np)
-{
- if (np->iommu_table && get_property(np, "ibm,dma-window", NULL))
- iommu_free_table(np);
}
/*
@@ -1811,23 +1650,14 @@ static void of_cleanup_node(struct device_node *np)
* a reference to the node. The memory associated with the node
* is not freed until its refcount goes to zero.
*/
-int of_remove_node(struct device_node *np)
+void of_detach_node(const struct device_node *np)
{
- struct device_node *parent, *child;
-
- parent = of_get_parent(np);
- if (!parent)
- return -EINVAL;
+ struct device_node *parent;
- if ((child = of_get_next_child(np, NULL))) {
- of_node_put(child);
- return -EBUSY;
- }
+ write_lock(&devtree_lock);
- of_cleanup_node(np);
+ parent = np->parent;
- write_lock(&devtree_lock);
- remove_node_proc_entries(np);
if (allnodes == np)
allnodes = np->allnext;
else {
@@ -1849,12 +1679,40 @@ int of_remove_node(struct device_node *np)
;
prevsib->sibling = np->sibling;
}
+
write_unlock(&devtree_lock);
- of_node_put(parent);
- of_node_put(np); /* Must decrement the refcount */
- return 0;
}
+static int prom_reconfig_notifier(struct notifier_block *nb, unsigned long action, void *node)
+{
+ int err;
+
+ switch (action) {
+ case PSERIES_RECONFIG_ADD:
+ err = finish_node(node, NULL, of_finish_dynamic_node, 0, 0, 0);
+ if (err < 0) {
+ printk(KERN_ERR "finish_node returned %d\n", err);
+ err = NOTIFY_BAD;
+ }
+ break;
+ default:
+ err = NOTIFY_DONE;
+ break;
+ }
+ return err;
+}
+
+static struct notifier_block prom_reconfig_nb = {
+ .notifier_call = prom_reconfig_notifier,
+ .priority = 10, /* This one needs to run first */
+};
+
+static int __init prom_reconfig_setup(void)
+{
+ return pSeries_reconfig_notifier_register(&prom_reconfig_nb);
+}
+__initcall(prom_reconfig_setup);
+
/*
* Find a property with a given name for a given node
* and return the value.
@@ -1872,6 +1730,7 @@ get_property(struct device_node *np, const char *name, int *lenp)
}
return NULL;
}
+EXPORT_SYMBOL(get_property);
/*
* Add a property to a node
diff --git a/arch/ppc64/kernel/prom_init.c b/arch/ppc64/kernel/prom_init.c
index e0e3e219dc8c0..8dffa9ae2623d 100644
--- a/arch/ppc64/kernel/prom_init.c
+++ b/arch/ppc64/kernel/prom_init.c
@@ -151,7 +151,6 @@ typedef u32 cell_t;
extern void __start(unsigned long r3, unsigned long r4, unsigned long r5);
-extern unsigned long reloc_offset(void);
extern void enter_prom(struct prom_args *args, unsigned long entry);
extern void copy_and_flush(unsigned long dest, unsigned long src,
unsigned long size, unsigned long offset);
@@ -178,6 +177,10 @@ static int __initdata of_platform;
static char __initdata prom_cmd_line[COMMAND_LINE_SIZE];
+static unsigned long __initdata prom_memory_limit;
+static unsigned long __initdata prom_tce_alloc_start;
+static unsigned long __initdata prom_tce_alloc_end;
+
static unsigned long __initdata alloc_top;
static unsigned long __initdata alloc_top_high;
static unsigned long __initdata alloc_bottom;
@@ -385,10 +388,70 @@ static int __init prom_setprop(phandle node, const char *pname,
(u32)(unsigned long) value, (u32) valuelen);
}
+/* We can't use the standard versions because of RELOC headaches. */
+#define isxdigit(c) (('0' <= (c) && (c) <= '9') \
+ || ('a' <= (c) && (c) <= 'f') \
+ || ('A' <= (c) && (c) <= 'F'))
+
+#define isdigit(c) ('0' <= (c) && (c) <= '9')
+#define islower(c) ('a' <= (c) && (c) <= 'z')
+#define toupper(c) (islower(c) ? ((c) - 'a' + 'A') : (c))
+
+unsigned long prom_strtoul(const char *cp, const char **endp)
+{
+ unsigned long result = 0, base = 10, value;
+
+ if (*cp == '0') {
+ base = 8;
+ cp++;
+ if (toupper(*cp) == 'X') {
+ cp++;
+ base = 16;
+ }
+ }
+
+ while (isxdigit(*cp) &&
+ (value = isdigit(*cp) ? *cp - '0' : toupper(*cp) - 'A' + 10) < base) {
+ result = result * base + value;
+ cp++;
+ }
+
+ if (endp)
+ *endp = cp;
+
+ return result;
+}
+
+unsigned long prom_memparse(const char *ptr, const char **retptr)
+{
+ unsigned long ret = prom_strtoul(ptr, retptr);
+ int shift = 0;
+
+ /*
+ * We can't use a switch here because GCC *may* generate a
+ * jump table which won't work, because we're not running at
+ * the address we're linked at.
+ */
+ if ('G' == **retptr || 'g' == **retptr)
+ shift = 30;
+
+ if ('M' == **retptr || 'm' == **retptr)
+ shift = 20;
+
+ if ('K' == **retptr || 'k' == **retptr)
+ shift = 10;
+
+ if (shift) {
+ ret <<= shift;
+ (*retptr)++;
+ }
+
+ return ret;
+}
/*
* Early parsing of the command line passed to the kernel, used for
- * the options that affect the iommu
+ * "mem=x" and the options that affect the iommu
*/
static void __init early_cmdline_parse(void)
{
@@ -419,6 +482,14 @@ static void __init early_cmdline_parse(void)
else if (!strncmp(opt, RELOC("force"), 5))
RELOC(iommu_force_on) = 1;
}
+
+ opt = strstr(RELOC(prom_cmd_line), RELOC("mem="));
+ if (opt) {
+ opt += 4;
+ RELOC(prom_memory_limit) = prom_memparse(opt, (const char **)&opt);
+ /* Align to 16 MB == size of large page */
+ RELOC(prom_memory_limit) = ALIGN(RELOC(prom_memory_limit), 0x1000000);
+ }
}
/*
@@ -665,26 +736,50 @@ static void __init prom_init_mem(void)
}
}
- /* Setup our top/bottom alloc points, that is top of RMO or top of
- * segment 0 when running non-LPAR
- */
- if ( RELOC(of_platform) == PLATFORM_PSERIES_LPAR )
- RELOC(alloc_top) = RELOC(rmo_top);
- else
- RELOC(alloc_top) = RELOC(rmo_top) = min(0x40000000ul, RELOC(ram_top));
RELOC(alloc_bottom) = PAGE_ALIGN(RELOC(klimit) - offset + 0x4000);
- RELOC(alloc_top_high) = RELOC(ram_top);
/* Check if we have an initrd after the kernel, if we do move our bottom
* point to after it
*/
if (RELOC(prom_initrd_start)) {
- if ((RELOC(prom_initrd_start) + RELOC(prom_initrd_end))
- > RELOC(alloc_bottom))
+ if (RELOC(prom_initrd_end) > RELOC(alloc_bottom))
RELOC(alloc_bottom) = PAGE_ALIGN(RELOC(prom_initrd_end));
}
+ /*
+ * If prom_memory_limit is set we reduce the upper limits *except* for
+ * alloc_top_high. This must be the real top of RAM so we can put
+ * TCE's up there.
+ */
+
+ RELOC(alloc_top_high) = RELOC(ram_top);
+
+ if (RELOC(prom_memory_limit)) {
+ if (RELOC(prom_memory_limit) <= RELOC(alloc_bottom)) {
+ prom_printf("Ignoring mem=%x <= alloc_bottom.\n",
+ RELOC(prom_memory_limit));
+ RELOC(prom_memory_limit) = 0;
+ } else if (RELOC(prom_memory_limit) >= RELOC(ram_top)) {
+ prom_printf("Ignoring mem=%x >= ram_top.\n",
+ RELOC(prom_memory_limit));
+ RELOC(prom_memory_limit) = 0;
+ } else {
+ RELOC(ram_top) = RELOC(prom_memory_limit);
+ RELOC(rmo_top) = min(RELOC(rmo_top), RELOC(prom_memory_limit));
+ }
+ }
+
+ /*
+ * Setup our top alloc point, that is top of RMO or top of
+ * segment 0 when running non-LPAR.
+ */
+ if ( RELOC(of_platform) == PLATFORM_PSERIES_LPAR )
+ RELOC(alloc_top) = RELOC(rmo_top);
+ else
+ RELOC(alloc_top) = RELOC(rmo_top) = min(0x40000000ul, RELOC(ram_top));
+
prom_printf("memory layout at init:\n");
+ prom_printf(" memory_limit : %x (16 MB aligned)\n", RELOC(prom_memory_limit));
prom_printf(" alloc_bottom : %x\n", RELOC(alloc_bottom));
prom_printf(" alloc_top : %x\n", RELOC(alloc_top));
prom_printf(" alloc_top_hi : %x\n", RELOC(alloc_top_high));
@@ -873,6 +968,16 @@ static void __init prom_initialize_tce_table(void)
reserve_mem(local_alloc_bottom, local_alloc_top - local_alloc_bottom);
+ if (RELOC(prom_memory_limit)) {
+ /*
+ * We align the start to a 16MB boundary so we can map the TCE area
+ * using large pages if possible. The end should be the top of RAM
+ * so no need to align it.
+ */
+ RELOC(prom_tce_alloc_start) = _ALIGN_DOWN(local_alloc_bottom, 0x1000000);
+ RELOC(prom_tce_alloc_end) = local_alloc_top;
+ }
+
/* Flag the first invalid entry */
prom_debug("ending prom_initialize_tce_table\n");
}
@@ -1686,9 +1791,21 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, unsigned long
*/
if (RELOC(ppc64_iommu_off))
prom_setprop(_prom->chosen, "linux,iommu-off", NULL, 0);
+
if (RELOC(iommu_force_on))
prom_setprop(_prom->chosen, "linux,iommu-force-on", NULL, 0);
+ if (RELOC(prom_memory_limit))
+ prom_setprop(_prom->chosen, "linux,memory-limit",
+ PTRRELOC(&prom_memory_limit), sizeof(RELOC(prom_memory_limit)));
+
+ if (RELOC(prom_tce_alloc_start)) {
+ prom_setprop(_prom->chosen, "linux,tce-alloc-start",
+ PTRRELOC(&prom_tce_alloc_start), sizeof(RELOC(prom_tce_alloc_start)));
+ prom_setprop(_prom->chosen, "linux,tce-alloc-end",
+ PTRRELOC(&prom_tce_alloc_end), sizeof(RELOC(prom_tce_alloc_end)));
+ }
+
/*
* Now finally create the flattened device-tree
*/
diff --git a/arch/ppc64/kernel/ptrace.c b/arch/ppc64/kernel/ptrace.c
index ac89fbdb65b44..354a287c67eb8 100644
--- a/arch/ppc64/kernel/ptrace.c
+++ b/arch/ppc64/kernel/ptrace.c
@@ -27,6 +27,7 @@
#include <linux/user.h>
#include <linux/security.h>
#include <linux/audit.h>
+#include <linux/seccomp.h>
#include <asm/uaccess.h>
#include <asm/page.h>
@@ -315,6 +316,8 @@ void do_syscall_trace_enter(struct pt_regs *regs)
void do_syscall_trace_leave(struct pt_regs *regs)
{
+ secure_computing(regs->gpr[0]);
+
if (unlikely(current->audit_context))
audit_syscall_exit(current, regs->result);
diff --git a/arch/ppc64/kernel/rtas.c b/arch/ppc64/kernel/rtas.c
index e3d7f833ba1d4..5575603def277 100644
--- a/arch/ppc64/kernel/rtas.c
+++ b/arch/ppc64/kernel/rtas.c
@@ -255,29 +255,59 @@ rtas_extended_busy_delay_time(int status)
return ms;
}
-int
-rtas_get_power_level(int powerdomain, int *level)
+int rtas_error_rc(int rtas_rc)
+{
+ int rc;
+
+ switch (rtas_rc) {
+ case -1: /* Hardware Error */
+ rc = -EIO;
+ break;
+ case -3: /* Bad indicator/domain/etc */
+ rc = -EINVAL;
+ break;
+ case -9000: /* Isolation error */
+ rc = -EFAULT;
+ break;
+ case -9001: /* Outstanding TCE/PTE */
+ rc = -EEXIST;
+ break;
+ case -9002: /* No usable slot */
+ rc = -ENODEV;
+ break;
+ default:
+ printk(KERN_ERR "%s: unexpected RTAS error %d\n",
+ __FUNCTION__, rtas_rc);
+ rc = -ERANGE;
+ break;
+ }
+ return rc;
+}
+
+int rtas_get_power_level(int powerdomain, int *level)
{
int token = rtas_token("get-power-level");
int rc;
if (token == RTAS_UNKNOWN_SERVICE)
- return RTAS_UNKNOWN_OP;
+ return -ENOENT;
while ((rc = rtas_call(token, 1, 2, level, powerdomain)) == RTAS_BUSY)
udelay(1);
+
+ if (rc < 0)
+ return rtas_error_rc(rc);
return rc;
}
-int
-rtas_set_power_level(int powerdomain, int level, int *setlevel)
+int rtas_set_power_level(int powerdomain, int level, int *setlevel)
{
int token = rtas_token("set-power-level");
unsigned int wait_time;
int rc;
if (token == RTAS_UNKNOWN_SERVICE)
- return RTAS_UNKNOWN_OP;
+ return -ENOENT;
while (1) {
rc = rtas_call(token, 2, 2, setlevel, powerdomain, level);
@@ -289,18 +319,20 @@ rtas_set_power_level(int powerdomain, int level, int *setlevel)
} else
break;
}
+
+ if (rc < 0)
+ return rtas_error_rc(rc);
return rc;
}
-int
-rtas_get_sensor(int sensor, int index, int *state)
+int rtas_get_sensor(int sensor, int index, int *state)
{
int token = rtas_token("get-sensor-state");
unsigned int wait_time;
int rc;
if (token == RTAS_UNKNOWN_SERVICE)
- return RTAS_UNKNOWN_OP;
+ return -ENOENT;
while (1) {
rc = rtas_call(token, 2, 2, state, sensor, index);
@@ -312,18 +344,20 @@ rtas_get_sensor(int sensor, int index, int *state)
} else
break;
}
+
+ if (rc < 0)
+ return rtas_error_rc(rc);
return rc;
}
-int
-rtas_set_indicator(int indicator, int index, int new_value)
+int rtas_set_indicator(int indicator, int index, int new_value)
{
int token = rtas_token("set-indicator");
unsigned int wait_time;
int rc;
if (token == RTAS_UNKNOWN_SERVICE)
- return RTAS_UNKNOWN_OP;
+ return -ENOENT;
while (1) {
rc = rtas_call(token, 3, 1, NULL, indicator, index, new_value);
@@ -337,6 +371,8 @@ rtas_set_indicator(int indicator, int index, int new_value)
break;
}
+ if (rc < 0)
+ return rtas_error_rc(rc);
return rc;
}
diff --git a/arch/ppc64/kernel/rtas_flash.c b/arch/ppc64/kernel/rtas_flash.c
index c0cefd3c93efd..3213837282ca4 100644
--- a/arch/ppc64/kernel/rtas_flash.c
+++ b/arch/ppc64/kernel/rtas_flash.c
@@ -224,7 +224,6 @@ static ssize_t rtas_flash_read(struct file *file, char *buf,
struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
struct rtas_update_flash_t *uf;
char msg[RTAS_MSG_MAXLEN];
- int error;
int msglen;
uf = (struct rtas_update_flash_t *) dp->data;
@@ -241,8 +240,7 @@ static ssize_t rtas_flash_read(struct file *file, char *buf,
if (ppos && *ppos != 0)
return 0; /* be cheap */
- error = verify_area(VERIFY_WRITE, buf, msglen);
- if (error)
+ if (!access_ok(VERIFY_WRITE, buf, msglen))
return -EINVAL;
if (copy_to_user(buf, msg, msglen))
@@ -365,7 +363,6 @@ static ssize_t manage_flash_read(struct file *file, char *buf,
struct rtas_manage_flash_t *args_buf;
char msg[RTAS_MSG_MAXLEN];
int msglen;
- int error;
args_buf = (struct rtas_manage_flash_t *) dp->data;
if (args_buf == NULL)
@@ -378,8 +375,7 @@ static ssize_t manage_flash_read(struct file *file, char *buf,
if (ppos && *ppos != 0)
return 0; /* be cheap */
- error = verify_area(VERIFY_WRITE, buf, msglen);
- if (error)
+ if (!access_ok(VERIFY_WRITE, buf, msglen))
return -EINVAL;
if (copy_to_user(buf, msg, msglen))
@@ -477,7 +473,6 @@ static ssize_t validate_flash_read(struct file *file, char *buf,
struct rtas_validate_flash_t *args_buf;
char msg[RTAS_MSG_MAXLEN];
int msglen;
- int error;
args_buf = (struct rtas_validate_flash_t *) dp->data;
@@ -488,8 +483,7 @@ static ssize_t validate_flash_read(struct file *file, char *buf,
if (msglen > count)
msglen = count;
- error = verify_area(VERIFY_WRITE, buf, msglen);
- if (error)
+ if (!access_ok(VERIFY_WRITE, buf, msglen))
return -EINVAL;
if (copy_to_user(buf, msg, msglen))
@@ -531,7 +525,7 @@ static ssize_t validate_flash_write(struct file *file, const char *buf,
args_buf->status = VALIDATE_INCOMPLETE;
}
- if (verify_area(VERIFY_READ, buf, count)) {
+ if (!access_ok(VERIFY_READ, buf, count)) {
rc = -EFAULT;
goto done;
}
diff --git a/arch/ppc64/kernel/rtasd.c b/arch/ppc64/kernel/rtasd.c
index e41a158972ad7..ff65dc33320ee 100644
--- a/arch/ppc64/kernel/rtasd.c
+++ b/arch/ppc64/kernel/rtasd.c
@@ -289,8 +289,7 @@ static ssize_t rtas_log_read(struct file * file, char __user * buf,
count = rtas_error_log_buffer_max;
- error = verify_area(VERIFY_WRITE, buf, count);
- if (error)
+ if (!access_ok(VERIFY_WRITE, buf, count))
return -EFAULT;
tmp = kmalloc(count, GFP_KERNEL);
@@ -347,7 +346,7 @@ static int enable_surveillance(int timeout)
if (error == 0)
return 0;
- if (error == RTAS_NO_SUCH_INDICATOR) {
+ if (error == -EINVAL) {
printk(KERN_INFO "rtasd: surveillance not supported\n");
return 0;
}
@@ -400,10 +399,33 @@ static void do_event_scan(int event_scan)
} while(error == 0);
}
+static void do_event_scan_all_cpus(long delay)
+{
+ int cpu;
+
+ lock_cpu_hotplug();
+ cpu = first_cpu(cpu_online_map);
+ for (;;) {
+ set_cpus_allowed(current, cpumask_of_cpu(cpu));
+ do_event_scan(rtas_token("event-scan"));
+ set_cpus_allowed(current, CPU_MASK_ALL);
+
+ /* Drop hotplug lock, and sleep for the specified delay */
+ unlock_cpu_hotplug();
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(delay);
+ lock_cpu_hotplug();
+
+ cpu = next_cpu(cpu, cpu_online_map);
+ if (cpu == NR_CPUS)
+ break;
+ }
+ unlock_cpu_hotplug();
+}
+
static int rtasd(void *unused)
{
unsigned int err_type;
- int cpu = 0;
int event_scan = rtas_token("event-scan");
int rc;
@@ -437,17 +459,7 @@ static int rtasd(void *unused)
}
/* First pass. */
- lock_cpu_hotplug();
- for_each_online_cpu(cpu) {
- DEBUG("scheduling on %d\n", cpu);
- set_cpus_allowed(current, cpumask_of_cpu(cpu));
- DEBUG("watchdog scheduled on cpu %d\n", smp_processor_id());
-
- do_event_scan(event_scan);
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(HZ);
- }
- unlock_cpu_hotplug();
+ do_event_scan_all_cpus(HZ);
if (surveillance_timeout != -1) {
DEBUG("enabling surveillance\n");
@@ -455,25 +467,11 @@ static int rtasd(void *unused)
DEBUG("surveillance enabled\n");
}
- lock_cpu_hotplug();
- cpu = first_cpu(cpu_online_map);
- for (;;) {
- set_cpus_allowed(current, cpumask_of_cpu(cpu));
- do_event_scan(event_scan);
- set_cpus_allowed(current, CPU_MASK_ALL);
-
- /* Drop hotplug lock, and sleep for a bit (at least
- * one second since some machines have problems if we
- * call event-scan too quickly). */
- unlock_cpu_hotplug();
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout((HZ*60/rtas_event_scan_rate) / 2);
- lock_cpu_hotplug();
-
- cpu = next_cpu(cpu, cpu_online_map);
- if (cpu == NR_CPUS)
- cpu = first_cpu(cpu_online_map);
- }
+ /* Delay should be at least one second since some
+ * machines have problems if we call event-scan too
+ * quickly. */
+ for (;;)
+ do_event_scan_all_cpus((HZ*60/rtas_event_scan_rate) / 2);
error:
/* Should delete proc entries */
diff --git a/arch/ppc64/kernel/rtc.c b/arch/ppc64/kernel/rtc.c
index f941278bd01ce..3e70b91375fcb 100644
--- a/arch/ppc64/kernel/rtc.c
+++ b/arch/ppc64/kernel/rtc.c
@@ -337,7 +337,7 @@ void iSeries_get_boot_time(struct rtc_time *tm)
}
#endif
-#ifdef CONFIG_PPC_PSERIES
+#ifdef CONFIG_PPC_RTAS
#define MAX_RTC_WAIT 5000 /* 5 sec */
#define RTAS_CLOCK_BUSY (-2)
void pSeries_get_boot_time(struct rtc_time *rtc_tm)
diff --git a/arch/ppc64/kernel/scanlog.c b/arch/ppc64/kernel/scanlog.c
index b61d90edd84c6..189b81a419871 100644
--- a/arch/ppc64/kernel/scanlog.c
+++ b/arch/ppc64/kernel/scanlog.c
@@ -73,7 +73,7 @@ static ssize_t scanlog_read(struct file *file, char *buf,
return -EINVAL;
}
- if (verify_area(VERIFY_WRITE, buf, count))
+ if (!access_ok(VERIFY_WRITE, buf, count))
return -EFAULT;
for (;;) {
diff --git a/arch/ppc64/kernel/semaphore.c b/arch/ppc64/kernel/semaphore.c
index d723632d59f34..a1c1db573e9c0 100644
--- a/arch/ppc64/kernel/semaphore.c
+++ b/arch/ppc64/kernel/semaphore.c
@@ -18,6 +18,8 @@
#include <linux/sched.h>
#include <linux/init.h>
+#include <linux/module.h>
+
#include <asm/atomic.h>
#include <asm/semaphore.h>
#include <asm/errno.h>
@@ -62,6 +64,7 @@ void __up(struct semaphore *sem)
__sem_update_count(sem, 1);
wake_up(&sem->wait);
}
+EXPORT_SYMBOL(__up);
/*
* Note that when we come in to __down or __down_interruptible,
@@ -99,6 +102,7 @@ void __sched __down(struct semaphore *sem)
*/
wake_up(&sem->wait);
}
+EXPORT_SYMBOL(__down);
int __sched __down_interruptible(struct semaphore * sem)
{
@@ -129,3 +133,4 @@ int __sched __down_interruptible(struct semaphore * sem)
wake_up(&sem->wait);
return retval;
}
+EXPORT_SYMBOL(__down_interruptible);
diff --git a/arch/ppc64/kernel/setup.c b/arch/ppc64/kernel/setup.c
index 870c69ee8c590..21c57f539c293 100644
--- a/arch/ppc64/kernel/setup.c
+++ b/arch/ppc64/kernel/setup.c
@@ -129,6 +129,7 @@ int ucache_bsize;
/* The main machine-dep calls structure
*/
struct machdep_calls ppc_md;
+EXPORT_SYMBOL(ppc_md);
#ifdef CONFIG_MAGIC_SYSRQ
unsigned long SYSRQ_KEY;
@@ -268,15 +269,9 @@ static void __init setup_cpu_maps(void)
nthreads = len / sizeof(u32);
for (j = 0; j < nthreads && cpu < NR_CPUS; j++) {
- /*
- * Only spin up secondary threads if SMT is enabled.
- * We must leave space in the logical map for the
- * threads.
- */
- if (j == 0 || smt_enabled_at_boot) {
- cpu_set(cpu, cpu_present_map);
- set_hard_smp_processor_id(cpu, intserv[j]);
- }
+ cpu_set(cpu, cpu_present_map);
+ set_hard_smp_processor_id(cpu, intserv[j]);
+
if (intserv[j] == boot_cpuid_phys)
swap_cpuid = cpu;
cpu_set(cpu, cpu_possible_map);
@@ -315,7 +310,7 @@ static void __init setup_cpu_maps(void)
maxcpus = ireg[num_addr_cell + num_size_cell];
/* Double maxcpus for processors which have SMT capability */
- if (cur_cpu_spec->cpu_features & CPU_FTR_SMT)
+ if (cpu_has_feature(CPU_FTR_SMT))
maxcpus *= 2;
if (maxcpus > NR_CPUS) {
@@ -339,7 +334,7 @@ static void __init setup_cpu_maps(void)
*/
for_each_cpu(cpu) {
cpu_set(cpu, cpu_sibling_map[cpu]);
- if (cur_cpu_spec->cpu_features & CPU_FTR_SMT)
+ if (cpu_has_feature(CPU_FTR_SMT))
cpu_set(cpu ^ 0x1, cpu_sibling_map[cpu]);
}
@@ -604,12 +599,12 @@ void __init setup_system(void)
*/
initialize_cache_info();
-#ifdef CONFIG_PPC_PSERIES
+#ifdef CONFIG_PPC_RTAS
/*
* Initialize RTAS if available
*/
rtas_initialize();
-#endif /* CONFIG_PPC_PSERIES */
+#endif /* CONFIG_PPC_RTAS */
/*
* Check if we have an initrd provided via the device-tree
@@ -641,12 +636,11 @@ void __init setup_system(void)
early_console_initialized = 1;
register_console(&udbg_console);
-#endif /* !CONFIG_PPC_ISERIES */
-
/* Save unparsed command line copy for /proc/cmdline */
strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE);
parse_early_param();
+#endif /* !CONFIG_PPC_ISERIES */
#if defined(CONFIG_SMP) && !defined(CONFIG_PPC_ISERIES)
/*
@@ -767,7 +761,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
seq_printf(m, "unknown (%08x)", pvr);
#ifdef CONFIG_ALTIVEC
- if (cur_cpu_spec->cpu_features & CPU_FTR_ALTIVEC)
+ if (cpu_has_feature(CPU_FTR_ALTIVEC))
seq_printf(m, ", altivec supported");
#endif /* CONFIG_ALTIVEC */
@@ -805,20 +799,31 @@ struct seq_operations cpuinfo_op = {
.show = show_cpuinfo,
};
-#if 0 /* XXX not currently used */
+/*
+ * These three variables are used to save values passed to us by prom_init()
+ * via the device tree. The TCE variables are needed because with a memory_limit
+ * in force we may need to explicitly map the TCE are at the top of RAM.
+ */
unsigned long memory_limit;
+unsigned long tce_alloc_start;
+unsigned long tce_alloc_end;
+#ifdef CONFIG_PPC_ISERIES
+/*
+ * On iSeries we just parse the mem=X option from the command line.
+ * On pSeries it's a bit more complicated, see prom_init_mem()
+ */
static int __init early_parsemem(char *p)
{
if (!p)
return 0;
- memory_limit = memparse(p, &p);
+ memory_limit = ALIGN(memparse(p, &p), PAGE_SIZE);
return 0;
}
early_param("mem", early_parsemem);
-#endif
+#endif /* CONFIG_PPC_ISERIES */
#ifdef CONFIG_PPC_MULTIPLATFORM
static int __init set_preferred_console(void)
@@ -990,6 +995,34 @@ static void __init emergency_stack_init(void)
}
/*
+ * Called from setup_arch to initialize the bitmap of available
+ * syscalls in the systemcfg page
+ */
+void __init setup_syscall_map(void)
+{
+ unsigned int i, count64 = 0, count32 = 0;
+ extern unsigned long *sys_call_table;
+ extern unsigned long *sys_call_table32;
+ extern unsigned long sys_ni_syscall;
+
+
+ for (i = 0; i < __NR_syscalls; i++) {
+ if (sys_call_table[i] == sys_ni_syscall)
+ continue;
+ count64++;
+ systemcfg->syscall_map_64[i >> 5] |= 0x80000000UL >> (i & 0x1f);
+ }
+ for (i = 0; i < __NR_syscalls; i++) {
+ if (sys_call_table32[i] == sys_ni_syscall)
+ continue;
+ count32++;
+ systemcfg->syscall_map_32[i >> 5] |= 0x80000000UL >> (i & 0x1f);
+ }
+ printk(KERN_INFO "Syscall map setup, %d 32 bits and %d 64 bits syscalls\n",
+ count32, count64);
+}
+
+/*
* Called into from start_kernel, after lock_kernel has been called.
* Initializes bootmem, which is unsed to manage page allocation until
* mem_init is called.
@@ -1027,6 +1060,9 @@ void __init setup_arch(char **cmdline_p)
/* set up the bootmem stuff with available memory */
do_init_bootmem();
+ /* initialize the syscall map in systemcfg */
+ setup_syscall_map();
+
ppc_md.setup_arch();
/* Select the correct idle loop for the platform. */
@@ -1335,6 +1371,12 @@ EXPORT_SYMBOL(check_legacy_ioport);
static int __init early_xmon(char *p)
{
/* ensure xmon is enabled */
+ if (p) {
+ if (strncmp(p, "on", 2) == 0)
+ xmon_init();
+ if (strncmp(p, "early", 5) != 0)
+ return 0;
+ }
xmon_init();
debugger(NULL);
@@ -1345,9 +1387,6 @@ early_param("xmon", early_xmon);
void cpu_die(void)
{
- idle_task_exit();
if (ppc_md.cpu_die)
ppc_md.cpu_die();
- local_irq_disable();
- for (;;);
}
diff --git a/arch/ppc64/kernel/signal.c b/arch/ppc64/kernel/signal.c
index bea0bbcfe20fb..a95a2b49a1d56 100644
--- a/arch/ppc64/kernel/signal.c
+++ b/arch/ppc64/kernel/signal.c
@@ -27,6 +27,8 @@
#include <linux/stddef.h>
#include <linux/elf.h>
#include <linux/ptrace.h>
+#include <linux/module.h>
+
#include <asm/sigcontext.h>
#include <asm/ucontext.h>
#include <asm/uaccess.h>
@@ -34,6 +36,7 @@
#include <asm/ppcdebug.h>
#include <asm/unistd.h>
#include <asm/cacheflush.h>
+#include <asm/vdso.h>
#define DEBUG_SIG 0
@@ -313,7 +316,7 @@ int sys_swapcontext(struct ucontext __user *old_ctx,
return -EINVAL;
if (old_ctx != NULL) {
- if (verify_area(VERIFY_WRITE, old_ctx, sizeof(*old_ctx))
+ if (!access_ok(VERIFY_WRITE, old_ctx, sizeof(*old_ctx))
|| setup_sigcontext(&old_ctx->uc_mcontext, regs, 0, NULL, 0)
|| __copy_to_user(&old_ctx->uc_sigmask,
&current->blocked, sizeof(sigset_t)))
@@ -321,7 +324,7 @@ int sys_swapcontext(struct ucontext __user *old_ctx,
}
if (new_ctx == NULL)
return 0;
- if (verify_area(VERIFY_READ, new_ctx, sizeof(*new_ctx))
+ if (!access_ok(VERIFY_READ, new_ctx, sizeof(*new_ctx))
|| __get_user(tmp, (u8 __user *) new_ctx)
|| __get_user(tmp, (u8 __user *) (new_ctx + 1) - 1))
return -EFAULT;
@@ -331,7 +334,7 @@ int sys_swapcontext(struct ucontext __user *old_ctx,
* image of the user's registers, we can't just return -EFAULT
* because the user's registers will be corrupted. For instance
* the NIP value may have been updated but not some of the
- * other registers. Given that we have done the verify_area
+ * other registers. Given that we have done the access_ok
* and successfully read the first and last bytes of the region
* above, this should only happen in an out-of-memory situation
* or if another thread unmaps the region containing the context.
@@ -363,7 +366,7 @@ int sys_rt_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5,
/* Always make any pending restarted system calls return -EINTR */
current_thread_info()->restart_block.fn = do_no_restart_syscall;
- if (verify_area(VERIFY_READ, uc, sizeof(*uc)))
+ if (!access_ok(VERIFY_READ, uc, sizeof(*uc)))
goto badframe;
if (__copy_from_user(&set, &uc->uc_sigmask, sizeof(set)))
@@ -403,7 +406,7 @@ static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info,
frame = get_sigframe(ka, regs, sizeof(*frame));
- if (verify_area(VERIFY_WRITE, frame, sizeof(*frame)))
+ if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
goto badframe;
err |= __put_user(&frame->info, &frame->pinfo);
@@ -426,10 +429,14 @@ static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info,
goto badframe;
/* Set up to return from userspace. */
- err |= setup_trampoline(__NR_rt_sigreturn, &frame->tramp[0]);
- if (err)
- goto badframe;
-
+ if (vdso64_rt_sigtramp && current->thread.vdso_base) {
+ regs->link = current->thread.vdso_base + vdso64_rt_sigtramp;
+ } else {
+ err |= setup_trampoline(__NR_rt_sigreturn, &frame->tramp[0]);
+ if (err)
+ goto badframe;
+ regs->link = (unsigned long) &frame->tramp[0];
+ }
funct_desc_ptr = (func_descr_t __user *) ka->sa.sa_handler;
/* Allocate a dummy caller frame for the signal handler. */
@@ -438,7 +445,6 @@ static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info,
/* Set up "regs" so we "return" to the signal handler. */
err |= get_user(regs->nip, &funct_desc_ptr->entry);
- regs->link = (unsigned long) &frame->tramp[0];
regs->gpr[1] = newsp;
err |= get_user(regs->gpr[2], &funct_desc_ptr->toc);
regs->gpr[3] = signr;
@@ -566,6 +572,4 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
return 0;
}
-
-
-
+EXPORT_SYMBOL(do_signal);
diff --git a/arch/ppc64/kernel/signal32.c b/arch/ppc64/kernel/signal32.c
index 145eac7ef8f4a..b0e167db6af9c 100644
--- a/arch/ppc64/kernel/signal32.c
+++ b/arch/ppc64/kernel/signal32.c
@@ -31,6 +31,7 @@
#include <asm/ppcdebug.h>
#include <asm/unistd.h>
#include <asm/cacheflush.h>
+#include <asm/vdso.h>
#define DEBUG_SIG 0
@@ -637,7 +638,7 @@ static int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,
/* create a stack frame for the caller of the handler */
newsp -= __SIGNAL_FRAMESIZE32 + 16;
- if (verify_area(VERIFY_WRITE, (void __user *)newsp, origsp - newsp))
+ if (!access_ok(VERIFY_WRITE, (void __user *)newsp, origsp - newsp))
goto badframe;
compat_from_sigset(&c_oldset, oldset);
@@ -656,18 +657,24 @@ static int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,
/* Save user registers on the stack */
frame = &rt_sf->uc.uc_mcontext;
- if (save_user_regs(regs, frame, __NR_rt_sigreturn))
- goto badframe;
-
if (put_user(regs->gpr[1], (unsigned long __user *)newsp))
goto badframe;
+
+ if (vdso32_rt_sigtramp && current->thread.vdso_base) {
+ if (save_user_regs(regs, frame, 0))
+ goto badframe;
+ regs->link = current->thread.vdso_base + vdso32_rt_sigtramp;
+ } else {
+ if (save_user_regs(regs, frame, __NR_rt_sigreturn))
+ goto badframe;
+ regs->link = (unsigned long) frame->tramp;
+ }
regs->gpr[1] = (unsigned long) newsp;
regs->gpr[3] = sig;
regs->gpr[4] = (unsigned long) &rt_sf->info;
regs->gpr[5] = (unsigned long) &rt_sf->uc;
regs->gpr[6] = (unsigned long) rt_sf;
regs->nip = (unsigned long) ka->sa.sa_handler;
- regs->link = (unsigned long) frame->tramp;
regs->trap = 0;
regs->result = 0;
@@ -721,7 +728,7 @@ long sys32_swapcontext(struct ucontext32 __user *old_ctx,
if (old_ctx != NULL) {
compat_from_sigset(&c_set, &current->blocked);
- if (verify_area(VERIFY_WRITE, old_ctx, sizeof(*old_ctx))
+ if (!access_ok(VERIFY_WRITE, old_ctx, sizeof(*old_ctx))
|| save_user_regs(regs, &old_ctx->uc_mcontext, 0)
|| __copy_to_user(&old_ctx->uc_sigmask, &c_set, sizeof(c_set))
|| __put_user((u32)(u64)&old_ctx->uc_mcontext, &old_ctx->uc_regs))
@@ -729,7 +736,7 @@ long sys32_swapcontext(struct ucontext32 __user *old_ctx,
}
if (new_ctx == NULL)
return 0;
- if (verify_area(VERIFY_READ, new_ctx, sizeof(*new_ctx))
+ if (!access_ok(VERIFY_READ, new_ctx, sizeof(*new_ctx))
|| __get_user(tmp, (u8 __user *) new_ctx)
|| __get_user(tmp, (u8 __user *) (new_ctx + 1) - 1))
return -EFAULT;
@@ -739,7 +746,7 @@ long sys32_swapcontext(struct ucontext32 __user *old_ctx,
* image of the user's registers, we can't just return -EFAULT
* because the user's registers will be corrupted. For instance
* the NIP value may have been updated but not some of the
- * other registers. Given that we have done the verify_area
+ * other registers. Given that we have done the access_ok
* and successfully read the first and last bytes of the region
* above, this should only happen in an out-of-memory situation
* or if another thread unmaps the region containing the context.
@@ -763,7 +770,7 @@ long sys32_rt_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8,
rt_sf = (struct rt_sigframe32 __user *)
(regs->gpr[1] + __SIGNAL_FRAMESIZE32 + 16);
- if (verify_area(VERIFY_READ, rt_sf, sizeof(*rt_sf)))
+ if (!access_ok(VERIFY_READ, rt_sf, sizeof(*rt_sf)))
goto bad;
if (do_setcontext32(&rt_sf->uc, regs, 1))
goto bad;
@@ -812,7 +819,7 @@ static int handle_signal32(unsigned long sig, struct k_sigaction *ka,
/* create a stack frame for the caller of the handler */
newsp -= __SIGNAL_FRAMESIZE32;
- if (verify_area(VERIFY_WRITE, (void __user *) newsp, origsp - newsp))
+ if (!access_ok(VERIFY_WRITE, (void __user *) newsp, origsp - newsp))
goto badframe;
#if _NSIG != 64
@@ -825,8 +832,15 @@ static int handle_signal32(unsigned long sig, struct k_sigaction *ka,
|| __put_user(sig, &sc->signal))
goto badframe;
- if (save_user_regs(regs, &frame->mctx, __NR_sigreturn))
- goto badframe;
+ if (vdso32_sigtramp && current->thread.vdso_base) {
+ if (save_user_regs(regs, &frame->mctx, 0))
+ goto badframe;
+ regs->link = current->thread.vdso_base + vdso32_sigtramp;
+ } else {
+ if (save_user_regs(regs, &frame->mctx, __NR_sigreturn))
+ goto badframe;
+ regs->link = (unsigned long) frame->mctx.tramp;
+ }
if (put_user(regs->gpr[1], (unsigned long __user *)newsp))
goto badframe;
@@ -834,7 +848,6 @@ static int handle_signal32(unsigned long sig, struct k_sigaction *ka,
regs->gpr[3] = sig;
regs->gpr[4] = (unsigned long) sc;
regs->nip = (unsigned long) ka->sa.sa_handler;
- regs->link = (unsigned long) frame->mctx.tramp;
regs->trap = 0;
regs->result = 0;
@@ -879,7 +892,7 @@ long sys32_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8,
restore_sigmask(&set);
sr = (struct mcontext32 __user *)(u64)sigctx.regs;
- if (verify_area(VERIFY_READ, sr, sizeof(*sr))
+ if (!access_ok(VERIFY_READ, sr, sizeof(*sr))
|| restore_user_regs(regs, sr, 1))
goto badframe;
diff --git a/arch/ppc64/kernel/smp.c b/arch/ppc64/kernel/smp.c
index 2eb4f5e6439c0..1c92da3e45250 100644
--- a/arch/ppc64/kernel/smp.c
+++ b/arch/ppc64/kernel/smp.c
@@ -30,6 +30,7 @@
#include <linux/err.h>
#include <linux/sysdev.h>
#include <linux/cpu.h>
+#include <linux/notifier.h>
#include <asm/ptrace.h>
#include <asm/atomic.h>
@@ -53,8 +54,6 @@
#define DBG(fmt...)
#endif
-int smp_threads_ready;
-
cpumask_t cpu_possible_map = CPU_MASK_NONE;
cpumask_t cpu_online_map = CPU_MASK_NONE;
cpumask_t cpu_sibling_map[NR_CPUS] = { [0 ... NR_CPUS-1] = CPU_MASK_NONE };
@@ -383,7 +382,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
* For now we leave it which means the time can be some
* number of msecs off until someone does a settimeofday()
*/
- do_gtod.tb_orig_stamp = tb_last_stamp;
+ do_gtod.varp->tb_orig_stamp = tb_last_stamp;
systemcfg->tb_orig_stamp = tb_last_stamp;
#endif
@@ -406,17 +405,95 @@ void __devinit smp_prepare_boot_cpu(void)
current_set[boot_cpuid] = current->thread_info;
}
+#ifdef CONFIG_HOTPLUG_CPU
+/* State of each CPU during hotplug phases */
+DEFINE_PER_CPU(int, cpu_state) = { 0 };
+
+int generic_cpu_disable(void)
+{
+ unsigned int cpu = smp_processor_id();
+
+ if (cpu == boot_cpuid)
+ return -EBUSY;
+
+ systemcfg->processorCount--;
+ cpu_clear(cpu, cpu_online_map);
+ fixup_irqs(cpu_online_map);
+ return 0;
+}
+
+int generic_cpu_enable(unsigned int cpu)
+{
+ /* Do the normal bootup if we haven't
+ * already bootstrapped. */
+ if (system_state != SYSTEM_RUNNING)
+ return -ENOSYS;
+
+ /* get the target out of it's holding state */
+ per_cpu(cpu_state, cpu) = CPU_UP_PREPARE;
+ wmb();
+
+ while (!cpu_online(cpu))
+ cpu_relax();
+
+ fixup_irqs(cpu_online_map);
+ /* counter the irq disable in fixup_irqs */
+ local_irq_enable();
+ return 0;
+}
+
+void generic_cpu_die(unsigned int cpu)
+{
+ int i;
+
+ for (i = 0; i < 100; i++) {
+ rmb();
+ if (per_cpu(cpu_state, cpu) == CPU_DEAD)
+ return;
+ msleep(100);
+ }
+ printk(KERN_ERR "CPU%d didn't die...\n", cpu);
+}
+
+void generic_mach_cpu_die(void)
+{
+ unsigned int cpu;
+
+ local_irq_disable();
+ cpu = smp_processor_id();
+ printk(KERN_DEBUG "CPU%d offline\n", cpu);
+ __get_cpu_var(cpu_state) = CPU_DEAD;
+ wmb();
+ while (__get_cpu_var(cpu_state) != CPU_UP_PREPARE)
+ cpu_relax();
+
+ flush_tlb_pending();
+ cpu_set(cpu, cpu_online_map);
+ local_irq_enable();
+}
+#endif
+
+static int __devinit cpu_enable(unsigned int cpu)
+{
+ if (smp_ops->cpu_enable)
+ return smp_ops->cpu_enable(cpu);
+
+ return -ENOSYS;
+}
+
int __devinit __cpu_up(unsigned int cpu)
{
int c;
- /* At boot, don't bother with non-present cpus -JSCHOPP */
- if (system_state < SYSTEM_RUNNING && !cpu_present(cpu))
- return -ENOENT;
+ if (!cpu_enable(cpu))
+ return 0;
+
+ if (smp_ops->cpu_bootable && !smp_ops->cpu_bootable(cpu))
+ return -EINVAL;
paca[cpu].default_decr = tb_ticks_per_jiffy / decr_overclock;
- if (!(cur_cpu_spec->cpu_features & CPU_FTR_SLB)) {
+ if (!cpu_has_feature(CPU_FTR_SLB)) {
void *tmp;
/* maximum of 48 CPUs on machines with a segment table */
@@ -526,14 +603,6 @@ void __init smp_cpus_done(unsigned int max_cpus)
smp_ops->setup_cpu(boot_cpuid);
set_cpus_allowed(current, old_mask);
-
- /*
- * We know at boot the maximum number of cpus we can add to
- * a partition and set cpu_possible_map accordingly. cpu_present_map
- * needs to match for the hotplug code to allow us to hot add
- * any offline cpus.
- */
- cpu_present_map = cpu_possible_map;
}
#ifdef CONFIG_HOTPLUG_CPU
diff --git a/arch/ppc64/kernel/sys_ppc32.c b/arch/ppc64/kernel/sys_ppc32.c
index b823869b0d725..7cf7a9600025b 100644
--- a/arch/ppc64/kernel/sys_ppc32.c
+++ b/arch/ppc64/kernel/sys_ppc32.c
@@ -241,7 +241,7 @@ int cp_compat_stat(struct kstat *stat, struct compat_stat __user *statbuf)
!new_valid_dev(stat->rdev))
return -EOVERFLOW;
- err = verify_area(VERIFY_WRITE, statbuf, sizeof(*statbuf));
+ err = access_ok(VERIFY_WRITE, statbuf, sizeof(*statbuf)) ? 0 : -EFAULT;
err |= __put_user(new_encode_dev(stat->dev), &statbuf->st_dev);
err |= __put_user(stat->ino, &statbuf->st_ino);
err |= __put_user(stat->mode, &statbuf->st_mode);
@@ -504,11 +504,11 @@ long sys32_ipc(u32 call, u32 first, u32 second, u32 third, compat_uptr_t ptr,
switch (call) {
case SEMTIMEDOP:
- if (third)
+ if (fifth)
/* sign extend semid */
return compat_sys_semtimedop((int)first,
compat_ptr(ptr), second,
- compat_ptr(third));
+ compat_ptr(fifth));
/* else fall through for normal semop() */
case SEMOP:
/* struct sembuf is the same on 32 and 64bit :)) */
@@ -1195,7 +1195,7 @@ unsigned long sys32_mmap2(unsigned long addr, size_t len,
int get_compat_timeval(struct timeval *tv, struct compat_timeval __user *ctv)
{
- return (verify_area(VERIFY_READ, ctv, sizeof(*ctv)) ||
+ return (!access_ok(VERIFY_READ, ctv, sizeof(*ctv)) ||
__get_user(tv->tv_sec, &ctv->tv_sec) ||
__get_user(tv->tv_usec, &ctv->tv_usec)) ? -EFAULT : 0;
}
@@ -1290,14 +1290,7 @@ long ppc32_timer_create(clockid_t clock,
if (ev32 == NULL)
return sys_timer_create(clock, NULL, timer_id);
- memset(&event, 0, sizeof(event));
- if (!access_ok(VERIFY_READ, ev32, sizeof(struct compat_sigevent))
- || __get_user(event.sigev_value.sival_int,
- &ev32->sigev_value.sival_int)
- || __get_user(event.sigev_signo, &ev32->sigev_signo)
- || __get_user(event.sigev_notify, &ev32->sigev_notify)
- || __get_user(event.sigev_notify_thread_id,
- &ev32->sigev_notify_thread_id))
+ if (get_compat_sigevent(&event, ev32))
return -EFAULT;
if (!access_ok(VERIFY_WRITE, timer_id, sizeof(timer_t)))
diff --git a/arch/ppc64/kernel/syscalls.c b/arch/ppc64/kernel/syscalls.c
index 365987190d71c..f2865ff8d2f93 100644
--- a/arch/ppc64/kernel/syscalls.c
+++ b/arch/ppc64/kernel/syscalls.c
@@ -256,6 +256,3 @@ void do_show_syscall_exit(unsigned long r3)
{
printk(" -> %lx, current=%p cpu=%d\n", r3, current, smp_processor_id());
}
-
-/* Only exists on P-series. */
-cond_syscall(ppc_rtas);
diff --git a/arch/ppc64/kernel/sysfs.c b/arch/ppc64/kernel/sysfs.c
index 4eacd4fe44114..0925694c3ce5e 100644
--- a/arch/ppc64/kernel/sysfs.c
+++ b/arch/ppc64/kernel/sysfs.c
@@ -18,7 +18,7 @@
#include <asm/systemcfg.h>
#include <asm/paca.h>
#include <asm/lppaca.h>
-
+#include <asm/machdep.h>
static DEFINE_PER_CPU(struct cpu, cpu_devices);
@@ -63,7 +63,7 @@ static int __init smt_setup(void)
unsigned int *val;
unsigned int cpu;
- if (!cur_cpu_spec->cpu_features & CPU_FTR_SMT)
+ if (!cpu_has_feature(CPU_FTR_SMT))
return 1;
options = find_path_device("/options");
@@ -86,7 +86,7 @@ static int __init setup_smt_snooze_delay(char *str)
unsigned int cpu;
int snooze;
- if (!cur_cpu_spec->cpu_features & CPU_FTR_SMT)
+ if (!cpu_has_feature(CPU_FTR_SMT))
return 1;
smt_snooze_cmdline = 1;
@@ -167,7 +167,7 @@ void ppc64_enable_pmcs(void)
* On SMT machines we have to set the run latch in the ctrl register
* in order to make PMC6 spin.
*/
- if (cur_cpu_spec->cpu_features & CPU_FTR_SMT) {
+ if (cpu_has_feature(CPU_FTR_SMT)) {
ctrl = mfspr(CTRLF);
ctrl |= RUNLATCH;
mtspr(CTRLT, ctrl);
@@ -266,7 +266,7 @@ static void register_cpu_online(unsigned int cpu)
struct sys_device *s = &c->sysdev;
#ifndef CONFIG_PPC_ISERIES
- if (cur_cpu_spec->cpu_features & CPU_FTR_SMT)
+ if (cpu_has_feature(CPU_FTR_SMT))
sysdev_create_file(s, &attr_smt_snooze_delay);
#endif
@@ -275,7 +275,7 @@ static void register_cpu_online(unsigned int cpu)
sysdev_create_file(s, &attr_mmcr0);
sysdev_create_file(s, &attr_mmcr1);
- if (cur_cpu_spec->cpu_features & CPU_FTR_MMCRA)
+ if (cpu_has_feature(CPU_FTR_MMCRA))
sysdev_create_file(s, &attr_mmcra);
sysdev_create_file(s, &attr_pmc1);
@@ -285,12 +285,12 @@ static void register_cpu_online(unsigned int cpu)
sysdev_create_file(s, &attr_pmc5);
sysdev_create_file(s, &attr_pmc6);
- if (cur_cpu_spec->cpu_features & CPU_FTR_PMC8) {
+ if (cpu_has_feature(CPU_FTR_PMC8)) {
sysdev_create_file(s, &attr_pmc7);
sysdev_create_file(s, &attr_pmc8);
}
- if (cur_cpu_spec->cpu_features & CPU_FTR_SMT)
+ if (cpu_has_feature(CPU_FTR_SMT))
sysdev_create_file(s, &attr_purr);
}
@@ -303,7 +303,7 @@ static void unregister_cpu_online(unsigned int cpu)
BUG_ON(c->no_control);
#ifndef CONFIG_PPC_ISERIES
- if (cur_cpu_spec->cpu_features & CPU_FTR_SMT)
+ if (cpu_has_feature(CPU_FTR_SMT))
sysdev_remove_file(s, &attr_smt_snooze_delay);
#endif
@@ -312,7 +312,7 @@ static void unregister_cpu_online(unsigned int cpu)
sysdev_remove_file(s, &attr_mmcr0);
sysdev_remove_file(s, &attr_mmcr1);
- if (cur_cpu_spec->cpu_features & CPU_FTR_MMCRA)
+ if (cpu_has_feature(CPU_FTR_MMCRA))
sysdev_remove_file(s, &attr_mmcra);
sysdev_remove_file(s, &attr_pmc1);
@@ -322,12 +322,12 @@ static void unregister_cpu_online(unsigned int cpu)
sysdev_remove_file(s, &attr_pmc5);
sysdev_remove_file(s, &attr_pmc6);
- if (cur_cpu_spec->cpu_features & CPU_FTR_PMC8) {
+ if (cpu_has_feature(CPU_FTR_PMC8)) {
sysdev_remove_file(s, &attr_pmc7);
sysdev_remove_file(s, &attr_pmc8);
}
- if (cur_cpu_spec->cpu_features & CPU_FTR_SMT)
+ if (cpu_has_feature(CPU_FTR_SMT))
sysdev_remove_file(s, &attr_purr);
}
#endif /* CONFIG_HOTPLUG_CPU */
@@ -413,9 +413,7 @@ static int __init topology_init(void)
* CPU. For instance, the boot cpu might never be valid
* for hotplugging.
*/
-#ifdef CONFIG_HOTPLUG_CPU
- if (systemcfg->platform != PLATFORM_PSERIES_LPAR)
-#endif
+ if (!ppc_md.cpu_die)
c->no_control = 1;
if (cpu_online(cpu) || (c->no_control == 0)) {
diff --git a/arch/ppc64/kernel/time.c b/arch/ppc64/kernel/time.c
index 3d88a7086ad57..77ded5a363b6d 100644
--- a/arch/ppc64/kernel/time.c
+++ b/arch/ppc64/kernel/time.c
@@ -85,9 +85,8 @@ static unsigned long first_settimeofday = 1;
unsigned long tb_ticks_per_jiffy;
unsigned long tb_ticks_per_usec = 100; /* sane default */
+EXPORT_SYMBOL(tb_ticks_per_usec);
unsigned long tb_ticks_per_sec;
-unsigned long next_xtime_sync_tb;
-unsigned long xtime_sync_interval;
unsigned long tb_to_xs;
unsigned tb_to_us;
unsigned long processor_freq;
@@ -158,8 +157,8 @@ static inline void __do_gettimeofday(struct timeval *tv, unsigned long tb_val)
* The conversion to microseconds at the end is done
* without a divide (and in fact, without a multiply)
*/
- tb_ticks = tb_val - do_gtod.tb_orig_stamp;
temp_varp = do_gtod.varp;
+ tb_ticks = tb_val - temp_varp->tb_orig_stamp;
temp_tb_to_xs = temp_varp->tb_to_xs;
temp_stamp_xsec = temp_varp->stamp_xsec;
tb_xsec = mulhdu( tb_ticks, temp_tb_to_xs );
@@ -185,17 +184,55 @@ static inline void timer_sync_xtime(unsigned long cur_tb)
{
struct timeval my_tv;
- if (cur_tb > next_xtime_sync_tb) {
- next_xtime_sync_tb = cur_tb + xtime_sync_interval;
- __do_gettimeofday(&my_tv, cur_tb);
+ __do_gettimeofday(&my_tv, cur_tb);
- if (xtime.tv_sec <= my_tv.tv_sec) {
- xtime.tv_sec = my_tv.tv_sec;
- xtime.tv_nsec = my_tv.tv_usec * 1000;
- }
+ if (xtime.tv_sec <= my_tv.tv_sec) {
+ xtime.tv_sec = my_tv.tv_sec;
+ xtime.tv_nsec = my_tv.tv_usec * 1000;
}
}
+/*
+ * When the timebase - tb_orig_stamp gets too big, we do a manipulation
+ * between tb_orig_stamp and stamp_xsec. The goal here is to keep the
+ * difference tb - tb_orig_stamp small enough to always fit inside a
+ * 32 bits number. This is a requirement of our fast 32 bits userland
+ * implementation in the vdso. If we "miss" a call to this function
+ * (interrupt latency, CPU locked in a spinlock, ...) and we end up
+ * with a too big difference, then the vdso will fallback to calling
+ * the syscall
+ */
+static __inline__ void timer_recalc_offset(unsigned long cur_tb)
+{
+ struct gettimeofday_vars * temp_varp;
+ unsigned temp_idx;
+ unsigned long offset, new_stamp_xsec, new_tb_orig_stamp;
+
+ if (((cur_tb - do_gtod.varp->tb_orig_stamp) & 0x80000000u) == 0)
+ return;
+
+ temp_idx = (do_gtod.var_idx == 0);
+ temp_varp = &do_gtod.vars[temp_idx];
+
+ new_tb_orig_stamp = cur_tb;
+ offset = new_tb_orig_stamp - do_gtod.varp->tb_orig_stamp;
+ new_stamp_xsec = do_gtod.varp->stamp_xsec + mulhdu(offset, do_gtod.varp->tb_to_xs);
+
+ temp_varp->tb_to_xs = do_gtod.varp->tb_to_xs;
+ temp_varp->tb_orig_stamp = new_tb_orig_stamp;
+ temp_varp->stamp_xsec = new_stamp_xsec;
+ mb();
+ do_gtod.varp = temp_varp;
+ do_gtod.var_idx = temp_idx;
+
+ ++(systemcfg->tb_update_count);
+ wmb();
+ systemcfg->tb_orig_stamp = new_tb_orig_stamp;
+ systemcfg->stamp_xsec = new_stamp_xsec;
+ wmb();
+ ++(systemcfg->tb_update_count);
+}
+
#ifdef CONFIG_SMP
unsigned long profile_pc(struct pt_regs *regs)
{
@@ -311,6 +348,7 @@ int timer_interrupt(struct pt_regs * regs)
if (cpu == boot_cpuid) {
write_seqlock(&xtime_lock);
tb_last_stamp = lpaca->next_jiffy_update_tb;
+ timer_recalc_offset(lpaca->next_jiffy_update_tb);
do_timer(regs);
timer_sync_xtime(lpaca->next_jiffy_update_tb);
timer_check_rtc();
@@ -334,6 +372,14 @@ int timer_interrupt(struct pt_regs * regs)
}
#endif
+/* collect purr register values often, for accurate calculations */
+#if defined(CONFIG_PPC_PSERIES)
+ if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) {
+ struct cpu_usage *cu = &__get_cpu_var(cpu_usage_array);
+ cu->current_tb = mfspr(SPRN_PURR);
+ }
+#endif
+
irq_exit();
return 1;
@@ -398,7 +444,9 @@ int do_settimeofday(struct timespec *tv)
time_maxerror = NTP_PHASE_LIMIT;
time_esterror = NTP_PHASE_LIMIT;
- delta_xsec = mulhdu( (tb_last_stamp-do_gtod.tb_orig_stamp), do_gtod.varp->tb_to_xs );
+ delta_xsec = mulhdu( (tb_last_stamp-do_gtod.varp->tb_orig_stamp),
+ do_gtod.varp->tb_to_xs );
+
new_xsec = (new_nsec * XSEC_PER_SEC) / NSEC_PER_SEC;
new_xsec += new_sec * XSEC_PER_SEC;
if ( new_xsec > delta_xsec ) {
@@ -411,7 +459,7 @@ int do_settimeofday(struct timespec *tv)
* before 1970 ... eg. we booted ten days ago, and we are setting
* the time to Jan 5, 1970 */
do_gtod.varp->stamp_xsec = new_xsec;
- do_gtod.tb_orig_stamp = tb_last_stamp;
+ do_gtod.varp->tb_orig_stamp = tb_last_stamp;
systemcfg->stamp_xsec = new_xsec;
systemcfg->tb_orig_stamp = tb_last_stamp;
}
@@ -464,9 +512,9 @@ void __init time_init(void)
xtime.tv_sec = mktime(tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
tm.tm_hour, tm.tm_min, tm.tm_sec);
tb_last_stamp = get_tb();
- do_gtod.tb_orig_stamp = tb_last_stamp;
do_gtod.varp = &do_gtod.vars[0];
do_gtod.var_idx = 0;
+ do_gtod.varp->tb_orig_stamp = tb_last_stamp;
do_gtod.varp->stamp_xsec = xtime.tv_sec * XSEC_PER_SEC;
do_gtod.tb_ticks_per_sec = tb_ticks_per_sec;
do_gtod.varp->tb_to_xs = tb_to_xs;
@@ -477,9 +525,6 @@ void __init time_init(void)
systemcfg->stamp_xsec = xtime.tv_sec * XSEC_PER_SEC;
systemcfg->tb_to_xs = tb_to_xs;
- xtime_sync_interval = tb_ticks_per_sec - (tb_ticks_per_sec/8);
- next_xtime_sync_tb = tb_last_stamp + xtime_sync_interval;
-
time_freq = 0;
xtime.tv_nsec = 0;
@@ -584,12 +629,12 @@ void ppc_adjtimex(void)
stamp_xsec which is the time (in 1/2^20 second units) corresponding to tb_orig_stamp. This
new value of stamp_xsec compensates for the change in frequency (implied by the new tb_to_xs)
which guarantees that the current time remains the same */
- tb_ticks = get_tb() - do_gtod.tb_orig_stamp;
+ write_seqlock_irqsave( &xtime_lock, flags );
+ tb_ticks = get_tb() - do_gtod.varp->tb_orig_stamp;
div128_by_32( 1024*1024, 0, new_tb_ticks_per_sec, &divres );
new_tb_to_xs = divres.result_low;
new_xsec = mulhdu( tb_ticks, new_tb_to_xs );
- write_seqlock_irqsave( &xtime_lock, flags );
old_xsec = mulhdu( tb_ticks, do_gtod.varp->tb_to_xs );
new_stamp_xsec = do_gtod.varp->stamp_xsec + old_xsec - new_xsec;
@@ -597,16 +642,12 @@ void ppc_adjtimex(void)
values in do_gettimeofday. We alternate the copies and as long as a reasonable time elapses between
changes, there will never be inconsistent values. ntpd has a minimum of one minute between updates */
- if (do_gtod.var_idx == 0) {
- temp_varp = &do_gtod.vars[1];
- temp_idx = 1;
- }
- else {
- temp_varp = &do_gtod.vars[0];
- temp_idx = 0;
- }
+ temp_idx = (do_gtod.var_idx == 0);
+ temp_varp = &do_gtod.vars[temp_idx];
+
temp_varp->tb_to_xs = new_tb_to_xs;
temp_varp->stamp_xsec = new_stamp_xsec;
+ temp_varp->tb_orig_stamp = do_gtod.varp->tb_orig_stamp;
mb();
do_gtod.varp = temp_varp;
do_gtod.var_idx = temp_idx;
diff --git a/arch/ppc64/kernel/traps.c b/arch/ppc64/kernel/traps.c
index bc245a22b435a..10fc61f3f6a43 100644
--- a/arch/ppc64/kernel/traps.c
+++ b/arch/ppc64/kernel/traps.c
@@ -41,6 +41,7 @@
#include <asm/rtas.h>
#include <asm/systemcfg.h>
#include <asm/machdep.h>
+#include <asm/pmc.h>
#ifdef CONFIG_DEBUGGER
int (*__debugger)(struct pt_regs *regs);
@@ -278,6 +279,9 @@ static void parse_fpe(struct pt_regs *regs)
* fault. Return zero on success.
*/
+#define INST_MFSPR_PVR 0x7c1f42a6
+#define INST_MFSPR_PVR_MASK 0xfc1fffff
+
#define INST_DCBA 0x7c0005ec
#define INST_DCBA_MASK 0x7c0007fe
@@ -296,6 +300,15 @@ static int emulate_instruction(struct pt_regs *regs)
if (get_user(instword, (unsigned int __user *)(regs->nip)))
return -EFAULT;
+ /* Emulate the mfspr rD, PVR. */
+ if ((instword & INST_MFSPR_PVR_MASK) == INST_MFSPR_PVR) {
+ unsigned int rd;
+
+ rd = (instword >> 21) & 0x1f;
+ regs->gpr[rd] = mfspr(SPRN_PVR);
+ return 0;
+ }
+
/* Emulating the dcba insn is just a no-op. */
if ((instword & INST_DCBA_MASK) == INST_DCBA) {
static int warned;
@@ -389,11 +402,6 @@ void program_check_exception(struct pt_regs *regs)
if (regs->msr & 0x100000) {
/* IEEE FP exception */
parse_fpe(regs);
-
- } else if (regs->msr & 0x40000) {
- /* Privileged instruction */
- _exception(SIGILL, regs, ILL_PRVOPC, regs->nip);
-
} else if (regs->msr & 0x20000) {
/* trap exception */
@@ -410,7 +418,7 @@ void program_check_exception(struct pt_regs *regs)
_exception(SIGTRAP, regs, TRAP_BRKPT, regs->nip);
} else {
- /* Illegal instruction; try to emulate it. */
+ /* Privileged or illegal instruction; try to emulate it. */
switch (emulate_instruction(regs)) {
case 0:
regs->nip += 4;
@@ -422,7 +430,12 @@ void program_check_exception(struct pt_regs *regs)
break;
default:
- _exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
+ if (regs->msr & 0x40000)
+ /* priveleged */
+ _exception(SIGILL, regs, ILL_PRVOPC, regs->nip);
+ else
+ /* illegal */
+ _exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
break;
}
}
@@ -450,18 +463,7 @@ void altivec_unavailable_exception(struct pt_regs *regs)
die("Unrecoverable VMX/Altivec Unavailable Exception", regs, SIGABRT);
}
-/* Ensure exceptions are disabled */
-static void dummy_perf(struct pt_regs *regs)
-{
- unsigned int mmcr0 = mfspr(SPRN_MMCR0);
-
- mmcr0 &= ~(MMCR0_PMXE|MMCR0_PMAO);
- mtspr(SPRN_MMCR0, mmcr0);
-}
-
-void (*perf_irq)(struct pt_regs *) = dummy_perf;
-
-EXPORT_SYMBOL(perf_irq);
+extern perf_irq_t perf_irq;
void performance_monitor_exception(struct pt_regs *regs)
{
diff --git a/arch/ppc64/kernel/vdso.c b/arch/ppc64/kernel/vdso.c
new file mode 100644
index 0000000000000..8c4597224b718
--- /dev/null
+++ b/arch/ppc64/kernel/vdso.c
@@ -0,0 +1,614 @@
+/*
+ * linux/arch/ppc64/kernel/vdso.c
+ *
+ * Copyright (C) 2004 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.
+ */
+
+#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/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+#include <linux/slab.h>
+#include <linux/user.h>
+#include <linux/elf.h>
+#include <linux/security.h>
+#include <linux/bootmem.h>
+
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/processor.h>
+#include <asm/mmu.h>
+#include <asm/mmu_context.h>
+#include <asm/machdep.h>
+#include <asm/cputable.h>
+#include <asm/sections.h>
+#include <asm/vdso.h>
+
+#undef DEBUG
+
+#ifdef DEBUG
+#define DBG(fmt...) printk(fmt)
+#else
+#define DBG(fmt...)
+#endif
+
+
+/*
+ * The vDSOs themselves are here
+ */
+extern char vdso64_start, vdso64_end;
+extern char vdso32_start, vdso32_end;
+
+static void *vdso64_kbase = &vdso64_start;
+static void *vdso32_kbase = &vdso32_start;
+
+unsigned int vdso64_pages;
+unsigned int vdso32_pages;
+
+/* Signal trampolines user addresses */
+
+unsigned long vdso64_rt_sigtramp;
+unsigned long vdso32_sigtramp;
+unsigned long vdso32_rt_sigtramp;
+
+/* Format of the patch table */
+struct vdso_patch_def
+{
+ u32 pvr_mask, pvr_value;
+ const char *gen_name;
+ const char *fix_name;
+};
+
+/* Table of functions to patch based on the CPU type/revision
+ *
+ * TODO: Improve by adding whole lists for each entry
+ */
+static struct vdso_patch_def vdso_patches[] = {
+ {
+ 0xffff0000, 0x003a0000, /* POWER5 */
+ "__kernel_sync_dicache", "__kernel_sync_dicache_p5"
+ },
+ {
+ 0xffff0000, 0x003b0000, /* POWER5 */
+ "__kernel_sync_dicache", "__kernel_sync_dicache_p5"
+ },
+};
+
+/*
+ * Some infos carried around for each of them during parsing at
+ * boot time.
+ */
+struct lib32_elfinfo
+{
+ Elf32_Ehdr *hdr; /* ptr to ELF */
+ Elf32_Sym *dynsym; /* ptr to .dynsym section */
+ unsigned long dynsymsize; /* size of .dynsym section */
+ char *dynstr; /* ptr to .dynstr section */
+ unsigned long text; /* offset of .text section in .so */
+};
+
+struct lib64_elfinfo
+{
+ Elf64_Ehdr *hdr;
+ Elf64_Sym *dynsym;
+ unsigned long dynsymsize;
+ char *dynstr;
+ unsigned long text;
+};
+
+
+#ifdef __DEBUG
+static void dump_one_vdso_page(struct page *pg, struct page *upg)
+{
+ printk("kpg: %p (c:%d,f:%08lx)", __va(page_to_pfn(pg) << PAGE_SHIFT),
+ page_count(pg),
+ pg->flags);
+ if (upg/* && pg != upg*/) {
+ printk(" upg: %p (c:%d,f:%08lx)", __va(page_to_pfn(upg) << PAGE_SHIFT),
+ page_count(upg),
+ upg->flags);
+ }
+ printk("\n");
+}
+
+static void dump_vdso_pages(struct vm_area_struct * vma)
+{
+ int i;
+
+ if (!vma || test_thread_flag(TIF_32BIT)) {
+ printk("vDSO32 @ %016lx:\n", (unsigned long)vdso32_kbase);
+ for (i=0; i<vdso32_pages; i++) {
+ struct page *pg = virt_to_page(vdso32_kbase + i*PAGE_SIZE);
+ struct page *upg = (vma && vma->vm_mm) ?
+ follow_page(vma->vm_mm, vma->vm_start + i*PAGE_SIZE, 0)
+ : NULL;
+ dump_one_vdso_page(pg, upg);
+ }
+ }
+ if (!vma || !test_thread_flag(TIF_32BIT)) {
+ printk("vDSO64 @ %016lx:\n", (unsigned long)vdso64_kbase);
+ for (i=0; i<vdso64_pages; i++) {
+ struct page *pg = virt_to_page(vdso64_kbase + i*PAGE_SIZE);
+ struct page *upg = (vma && vma->vm_mm) ?
+ follow_page(vma->vm_mm, vma->vm_start + i*PAGE_SIZE, 0)
+ : NULL;
+ dump_one_vdso_page(pg, upg);
+ }
+ }
+}
+#endif /* DEBUG */
+
+/*
+ * Keep a dummy vma_close for now, it will prevent VMA merging.
+ */
+static void vdso_vma_close(struct vm_area_struct * vma)
+{
+}
+
+/*
+ * Our nopage() function, maps in the actual vDSO kernel pages, they will
+ * be mapped read-only by do_no_page(), and eventually COW'ed, either
+ * right away for an initial write access, or by do_wp_page().
+ */
+static struct page * vdso_vma_nopage(struct vm_area_struct * vma,
+ unsigned long address, int *type)
+{
+ unsigned long offset = address - vma->vm_start;
+ struct page *pg;
+ void *vbase = test_thread_flag(TIF_32BIT) ? vdso32_kbase : vdso64_kbase;
+
+ DBG("vdso_vma_nopage(current: %s, address: %016lx, off: %lx)\n",
+ current->comm, address, offset);
+
+ if (address < vma->vm_start || address > vma->vm_end)
+ return NOPAGE_SIGBUS;
+
+ /*
+ * Last page is systemcfg, special handling here, no get_page() a
+ * this is a reserved page
+ */
+ if ((vma->vm_end - address) <= PAGE_SIZE)
+ return virt_to_page(systemcfg);
+
+ pg = virt_to_page(vbase + offset);
+ get_page(pg);
+ DBG(" ->page count: %d\n", page_count(pg));
+
+ return pg;
+}
+
+static struct vm_operations_struct vdso_vmops = {
+ .close = vdso_vma_close,
+ .nopage = vdso_vma_nopage,
+};
+
+/*
+ * This is called from binfmt_elf, we create the special vma for the
+ * vDSO and insert it into the mm struct tree
+ */
+int arch_setup_additional_pages(struct linux_binprm *bprm, int executable_stack)
+{
+ struct mm_struct *mm = current->mm;
+ struct vm_area_struct *vma;
+ unsigned long vdso_pages;
+ unsigned long vdso_base;
+
+ if (test_thread_flag(TIF_32BIT)) {
+ vdso_pages = vdso32_pages;
+ vdso_base = VDSO32_MBASE;
+ } else {
+ vdso_pages = vdso64_pages;
+ vdso_base = VDSO64_MBASE;
+ }
+
+ /* vDSO has a problem and was disabled, just don't "enable" it for the
+ * process
+ */
+ if (vdso_pages == 0) {
+ current->thread.vdso_base = 0;
+ return 0;
+ }
+ vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
+ if (vma == NULL)
+ return -ENOMEM;
+ if (security_vm_enough_memory(vdso_pages)) {
+ kmem_cache_free(vm_area_cachep, vma);
+ return -ENOMEM;
+ }
+ memset(vma, 0, sizeof(*vma));
+
+ /*
+ * pick a base address for the vDSO in process space. We have a default
+ * base of 1Mb on which we had a random offset up to 1Mb.
+ * XXX: Add possibility for a program header to specify that location
+ */
+ current->thread.vdso_base = vdso_base;
+ /* + ((unsigned long)vma & 0x000ff000); */
+
+ vma->vm_mm = mm;
+ vma->vm_start = current->thread.vdso_base;
+
+ /*
+ * the VMA size is one page more than the vDSO since systemcfg
+ * is mapped in the last one
+ */
+ vma->vm_end = vma->vm_start + ((vdso_pages + 1) << PAGE_SHIFT);
+
+ /*
+ * our vma flags don't have VM_WRITE so by default, the process isn't allowed
+ * to write those pages.
+ * gdb can break that with ptrace interface, and thus trigger COW on those
+ * pages but it's then your responsibility to never do that on the "data" page
+ * of the vDSO or you'll stop getting kernel updates and your nice userland
+ * gettimeofday will be totally dead. It's fine to use that for setting
+ * breakpoints in the vDSO code pages though
+ */
+ vma->vm_flags = VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC;
+ vma->vm_flags |= mm->def_flags;
+ vma->vm_page_prot = protection_map[vma->vm_flags & 0x7];
+ vma->vm_ops = &vdso_vmops;
+
+ down_write(&mm->mmap_sem);
+ insert_vm_struct(mm, vma);
+ mm->total_vm += (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
+ up_write(&mm->mmap_sem);
+
+ return 0;
+}
+
+static void * __init find_section32(Elf32_Ehdr *ehdr, const char *secname,
+ unsigned long *size)
+{
+ Elf32_Shdr *sechdrs;
+ unsigned int i;
+ char *secnames;
+
+ /* Grab section headers and strings so we can tell who is who */
+ sechdrs = (void *)ehdr + ehdr->e_shoff;
+ secnames = (void *)ehdr + sechdrs[ehdr->e_shstrndx].sh_offset;
+
+ /* Find the section they want */
+ for (i = 1; i < ehdr->e_shnum; i++) {
+ if (strcmp(secnames+sechdrs[i].sh_name, secname) == 0) {
+ if (size)
+ *size = sechdrs[i].sh_size;
+ return (void *)ehdr + sechdrs[i].sh_offset;
+ }
+ }
+ *size = 0;
+ return NULL;
+}
+
+static void * __init find_section64(Elf64_Ehdr *ehdr, const char *secname,
+ unsigned long *size)
+{
+ Elf64_Shdr *sechdrs;
+ unsigned int i;
+ char *secnames;
+
+ /* Grab section headers and strings so we can tell who is who */
+ sechdrs = (void *)ehdr + ehdr->e_shoff;
+ secnames = (void *)ehdr + sechdrs[ehdr->e_shstrndx].sh_offset;
+
+ /* Find the section they want */
+ for (i = 1; i < ehdr->e_shnum; i++) {
+ if (strcmp(secnames+sechdrs[i].sh_name, secname) == 0) {
+ if (size)
+ *size = sechdrs[i].sh_size;
+ return (void *)ehdr + sechdrs[i].sh_offset;
+ }
+ }
+ if (size)
+ *size = 0;
+ return NULL;
+}
+
+static Elf32_Sym * __init find_symbol32(struct lib32_elfinfo *lib, const char *symname)
+{
+ unsigned int i;
+ char name[32], *c;
+
+ for (i = 0; i < (lib->dynsymsize / sizeof(Elf32_Sym)); i++) {
+ if (lib->dynsym[i].st_name == 0)
+ continue;
+ strlcpy(name, lib->dynstr + lib->dynsym[i].st_name, 32);
+ c = strchr(name, '@');
+ if (c)
+ *c = 0;
+ if (strcmp(symname, name) == 0)
+ return &lib->dynsym[i];
+ }
+ return NULL;
+}
+
+static Elf64_Sym * __init find_symbol64(struct lib64_elfinfo *lib, const char *symname)
+{
+ unsigned int i;
+ char name[32], *c;
+
+ for (i = 0; i < (lib->dynsymsize / sizeof(Elf64_Sym)); i++) {
+ if (lib->dynsym[i].st_name == 0)
+ continue;
+ strlcpy(name, lib->dynstr + lib->dynsym[i].st_name, 32);
+ c = strchr(name, '@');
+ if (c)
+ *c = 0;
+ if (strcmp(symname, name) == 0)
+ return &lib->dynsym[i];
+ }
+ return NULL;
+}
+
+/* Note that we assume the section is .text and the symbol is relative to
+ * the library base
+ */
+static unsigned long __init find_function32(struct lib32_elfinfo *lib, const char *symname)
+{
+ Elf32_Sym *sym = find_symbol32(lib, symname);
+
+ if (sym == NULL) {
+ printk(KERN_WARNING "vDSO32: function %s not found !\n", symname);
+ return 0;
+ }
+ return sym->st_value - VDSO32_LBASE;
+}
+
+/* Note that we assume the section is .text and the symbol is relative to
+ * the library base
+ */
+static unsigned long __init find_function64(struct lib64_elfinfo *lib, const char *symname)
+{
+ Elf64_Sym *sym = find_symbol64(lib, symname);
+
+ if (sym == NULL) {
+ printk(KERN_WARNING "vDSO64: function %s not found !\n", symname);
+ return 0;
+ }
+#ifdef VDS64_HAS_DESCRIPTORS
+ return *((u64 *)(vdso64_kbase + sym->st_value - VDSO64_LBASE)) - VDSO64_LBASE;
+#else
+ return sym->st_value - VDSO64_LBASE;
+#endif
+}
+
+
+static __init int vdso_do_find_sections(struct lib32_elfinfo *v32,
+ struct lib64_elfinfo *v64)
+{
+ void *sect;
+
+ /*
+ * Locate symbol tables & text section
+ */
+
+ v32->dynsym = find_section32(v32->hdr, ".dynsym", &v32->dynsymsize);
+ v32->dynstr = find_section32(v32->hdr, ".dynstr", NULL);
+ if (v32->dynsym == NULL || v32->dynstr == NULL) {
+ printk(KERN_ERR "vDSO32: a required symbol section was not found\n");
+ return -1;
+ }
+ sect = find_section32(v32->hdr, ".text", NULL);
+ if (sect == NULL) {
+ printk(KERN_ERR "vDSO32: the .text section was not found\n");
+ return -1;
+ }
+ v32->text = sect - vdso32_kbase;
+
+ v64->dynsym = find_section64(v64->hdr, ".dynsym", &v64->dynsymsize);
+ v64->dynstr = find_section64(v64->hdr, ".dynstr", NULL);
+ if (v64->dynsym == NULL || v64->dynstr == NULL) {
+ printk(KERN_ERR "vDSO64: a required symbol section was not found\n");
+ return -1;
+ }
+ sect = find_section64(v64->hdr, ".text", NULL);
+ if (sect == NULL) {
+ printk(KERN_ERR "vDSO64: the .text section was not found\n");
+ return -1;
+ }
+ v64->text = sect - vdso64_kbase;
+
+ return 0;
+}
+
+static __init void vdso_setup_trampolines(struct lib32_elfinfo *v32,
+ struct lib64_elfinfo *v64)
+{
+ /*
+ * Find signal trampolines
+ */
+
+ vdso64_rt_sigtramp = find_function64(v64, "__kernel_sigtramp_rt64");
+ vdso32_sigtramp = find_function32(v32, "__kernel_sigtramp32");
+ vdso32_rt_sigtramp = find_function32(v32, "__kernel_sigtramp_rt32");
+}
+
+static __init int vdso_fixup_datapage(struct lib32_elfinfo *v32,
+ struct lib64_elfinfo *v64)
+{
+ Elf32_Sym *sym32;
+ Elf64_Sym *sym64;
+
+ sym32 = find_symbol32(v32, "__kernel_datapage_offset");
+ if (sym32 == NULL) {
+ printk(KERN_ERR "vDSO32: Can't find symbol __kernel_datapage_offset !\n");
+ return -1;
+ }
+ *((int *)(vdso32_kbase + (sym32->st_value - VDSO32_LBASE))) =
+ (vdso32_pages << PAGE_SHIFT) - (sym32->st_value - VDSO32_LBASE);
+
+ sym64 = find_symbol64(v64, "__kernel_datapage_offset");
+ if (sym64 == NULL) {
+ printk(KERN_ERR "vDSO64: Can't find symbol __kernel_datapage_offset !\n");
+ return -1;
+ }
+ *((int *)(vdso64_kbase + sym64->st_value - VDSO64_LBASE)) =
+ (vdso64_pages << PAGE_SHIFT) - (sym64->st_value - VDSO64_LBASE);
+
+ return 0;
+}
+
+static int vdso_do_func_patch32(struct lib32_elfinfo *v32,
+ struct lib64_elfinfo *v64,
+ const char *orig, const char *fix)
+{
+ Elf32_Sym *sym32_gen, *sym32_fix;
+
+ sym32_gen = find_symbol32(v32, orig);
+ if (sym32_gen == NULL) {
+ printk(KERN_ERR "vDSO32: Can't find symbol %s !\n", orig);
+ return -1;
+ }
+ sym32_fix = find_symbol32(v32, fix);
+ if (sym32_fix == NULL) {
+ printk(KERN_ERR "vDSO32: Can't find symbol %s !\n", fix);
+ return -1;
+ }
+ sym32_gen->st_value = sym32_fix->st_value;
+ sym32_gen->st_size = sym32_fix->st_size;
+ sym32_gen->st_info = sym32_fix->st_info;
+ sym32_gen->st_other = sym32_fix->st_other;
+ sym32_gen->st_shndx = sym32_fix->st_shndx;
+
+ return 0;
+}
+
+static int vdso_do_func_patch64(struct lib32_elfinfo *v32,
+ struct lib64_elfinfo *v64,
+ const char *orig, const char *fix)
+{
+ Elf64_Sym *sym64_gen, *sym64_fix;
+
+ sym64_gen = find_symbol64(v64, orig);
+ if (sym64_gen == NULL) {
+ printk(KERN_ERR "vDSO64: Can't find symbol %s !\n", orig);
+ return -1;
+ }
+ sym64_fix = find_symbol64(v64, fix);
+ if (sym64_fix == NULL) {
+ printk(KERN_ERR "vDSO64: Can't find symbol %s !\n", fix);
+ return -1;
+ }
+ sym64_gen->st_value = sym64_fix->st_value;
+ sym64_gen->st_size = sym64_fix->st_size;
+ sym64_gen->st_info = sym64_fix->st_info;
+ sym64_gen->st_other = sym64_fix->st_other;
+ sym64_gen->st_shndx = sym64_fix->st_shndx;
+
+ return 0;
+}
+
+static __init int vdso_fixup_alt_funcs(struct lib32_elfinfo *v32,
+ struct lib64_elfinfo *v64)
+{
+ u32 pvr;
+ int i;
+
+ pvr = mfspr(SPRN_PVR);
+ for (i = 0; i < ARRAY_SIZE(vdso_patches); i++) {
+ struct vdso_patch_def *patch = &vdso_patches[i];
+ int match = (pvr & patch->pvr_mask) == patch->pvr_value;
+
+ DBG("patch %d (mask: %x, pvr: %x) : %s\n",
+ i, patch->pvr_mask, patch->pvr_value, match ? "match" : "skip");
+
+ if (!match)
+ continue;
+
+ DBG("replacing %s with %s...\n", patch->gen_name, patch->fix_name);
+
+ /*
+ * Patch the 32 bits and 64 bits symbols. Note that we do not patch
+ * the "." symbol on 64 bits. It would be easy to do, but doesn't
+ * seem to be necessary, patching the OPD symbol is enough.
+ */
+ vdso_do_func_patch32(v32, v64, patch->gen_name, patch->fix_name);
+ vdso_do_func_patch64(v32, v64, patch->gen_name, patch->fix_name);
+ }
+
+ return 0;
+}
+
+
+static __init int vdso_setup(void)
+{
+ struct lib32_elfinfo v32;
+ struct lib64_elfinfo v64;
+
+ v32.hdr = vdso32_kbase;
+ v64.hdr = vdso64_kbase;
+
+ if (vdso_do_find_sections(&v32, &v64))
+ return -1;
+
+ if (vdso_fixup_datapage(&v32, &v64))
+ return -1;
+
+ if (vdso_fixup_alt_funcs(&v32, &v64))
+ return -1;
+
+ vdso_setup_trampolines(&v32, &v64);
+
+ return 0;
+}
+
+void __init vdso_init(void)
+{
+ int i;
+
+ vdso64_pages = (&vdso64_end - &vdso64_start) >> PAGE_SHIFT;
+ vdso32_pages = (&vdso32_end - &vdso32_start) >> PAGE_SHIFT;
+
+ DBG("vdso64_kbase: %p, 0x%x pages, vdso32_kbase: %p, 0x%x pages\n",
+ vdso64_kbase, vdso64_pages, vdso32_kbase, vdso32_pages);
+
+ /*
+ * Initialize the vDSO images in memory, that is do necessary
+ * fixups of vDSO symbols, locate trampolines, etc...
+ */
+ if (vdso_setup()) {
+ printk(KERN_ERR "vDSO setup failure, not enabled !\n");
+ /* XXX should free pages here ? */
+ vdso64_pages = vdso32_pages = 0;
+ return;
+ }
+
+ /* Make sure pages are in the correct state */
+ for (i = 0; i < vdso64_pages; i++) {
+ struct page *pg = virt_to_page(vdso64_kbase + i*PAGE_SIZE);
+ ClearPageReserved(pg);
+ get_page(pg);
+ }
+ for (i = 0; i < vdso32_pages; i++) {
+ struct page *pg = virt_to_page(vdso32_kbase + i*PAGE_SIZE);
+ ClearPageReserved(pg);
+ get_page(pg);
+ }
+}
+
+int in_gate_area_no_task(unsigned long addr)
+{
+ return 0;
+}
+
+int in_gate_area(struct task_struct *task, unsigned long addr)
+{
+ return 0;
+}
+
+struct vm_area_struct *get_gate_vma(struct task_struct *tsk)
+{
+ return NULL;
+}
+
diff --git a/arch/ppc64/kernel/vdso32/Makefile b/arch/ppc64/kernel/vdso32/Makefile
new file mode 100644
index 0000000000000..ede2f7e477c2a
--- /dev/null
+++ b/arch/ppc64/kernel/vdso32/Makefile
@@ -0,0 +1,36 @@
+
+# List of files in the vdso, has to be asm only for now
+
+obj-vdso32 = sigtramp.o gettimeofday.o datapage.o cacheflush.o
+
+# Build rules
+
+targets := $(obj-vdso32) vdso32.so
+obj-vdso32 := $(addprefix $(obj)/, $(obj-vdso32))
+
+
+EXTRA_CFLAGS := -shared -s -fno-common -fno-builtin
+EXTRA_CFLAGS += -nostdlib -Wl,-soname=linux-vdso32.so.1
+EXTRA_AFLAGS := -D__VDSO32__ -s
+
+obj-y += vdso32_wrapper.o
+extra-y += vdso32.lds
+CPPFLAGS_vdso32.lds += -P -C -U$(ARCH)
+
+# Force dependency (incbin is bad)
+$(obj)/vdso32_wrapper.o : $(obj)/vdso32.so
+
+# link rule for the .so file, .lds has to be first
+$(obj)/vdso32.so: $(src)/vdso32.lds $(obj-vdso32)
+ $(call if_changed,vdso32ld)
+
+# assembly rules for the .S files
+$(obj-vdso32): %.o: %.S
+ $(call if_changed_dep,vdso32as)
+
+# actual build commands
+quiet_cmd_vdso32ld = VDSO32L $@
+ cmd_vdso32ld = $(CROSS32CC) $(c_flags) -Wl,-T $^ -o $@
+quiet_cmd_vdso32as = VDSO32A $@
+ cmd_vdso32as = $(CROSS32CC) $(a_flags) -c -o $@ $<
+
diff --git a/arch/ppc64/kernel/vdso32/cacheflush.S b/arch/ppc64/kernel/vdso32/cacheflush.S
new file mode 100644
index 0000000000000..c74fddb6afd4d
--- /dev/null
+++ b/arch/ppc64/kernel/vdso32/cacheflush.S
@@ -0,0 +1,65 @@
+/*
+ * vDSO provided cache flush routines
+ *
+ * Copyright (C) 2004 Benjamin Herrenschmuidt (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
+ * 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/vdso.h>
+#include <asm/offsets.h>
+
+ .text
+
+/*
+ * Default "generic" version of __kernel_sync_dicache.
+ *
+ * void __kernel_sync_dicache(unsigned long start, unsigned long end)
+ *
+ * Flushes the data cache & invalidate the instruction cache for the
+ * provided range [start, end[
+ *
+ * Note: all CPUs supported by this kernel have a 128 bytes cache
+ * line size so we don't have to peek that info from the datapage
+ */
+V_FUNCTION_BEGIN(__kernel_sync_dicache)
+ .cfi_startproc
+ li r5,127
+ andc r6,r3,r5 /* round low to line bdy */
+ subf r8,r6,r4 /* compute length */
+ add r8,r8,r5 /* ensure we get enough */
+ srwi. r8,r8,7 /* compute line count */
+ beqlr /* nothing to do? */
+ mtctr r8
+ mr r3,r6
+1: dcbst 0,r3
+ addi r3,r3,128
+ bdnz 1b
+ sync
+ mtctr r8
+1: icbi 0,r6
+ addi r6,r6,128
+ bdnz 1b
+ isync
+ blr
+ .cfi_endproc
+V_FUNCTION_END(__kernel_sync_dicache)
+
+
+/*
+ * POWER5 version of __kernel_sync_dicache
+ */
+V_FUNCTION_BEGIN(__kernel_sync_dicache_p5)
+ .cfi_startproc
+ sync
+ isync
+ blr
+ .cfi_endproc
+V_FUNCTION_END(__kernel_sync_dicache_p5)
+
diff --git a/arch/ppc64/kernel/vdso32/datapage.S b/arch/ppc64/kernel/vdso32/datapage.S
new file mode 100644
index 0000000000000..29b6bd32e1f1a
--- /dev/null
+++ b/arch/ppc64/kernel/vdso32/datapage.S
@@ -0,0 +1,68 @@
+/*
+ * Access to the shared data page by the vDSO & syscall map
+ *
+ * Copyright (C) 2004 Benjamin Herrenschmuidt (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
+ * 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/offsets.h>
+#include <asm/unistd.h>
+#include <asm/vdso.h>
+
+ .text
+V_FUNCTION_BEGIN(__get_datapage)
+ .cfi_startproc
+ /* We don't want that exposed or overridable as we want other objects
+ * to be able to bl directly to here
+ */
+ .protected __get_datapage
+ .hidden __get_datapage
+
+ mflr r0
+ .cfi_register lr,r0
+
+ bcl 20,31,1f
+ .global __kernel_datapage_offset;
+__kernel_datapage_offset:
+ .long 0
+1:
+ mflr r3
+ mtlr r0
+ lwz r0,0(r3)
+ add r3,r0,r3
+ blr
+ .cfi_endproc
+V_FUNCTION_END(__get_datapage)
+
+/*
+ * void *__kernel_get_syscall_map(unsigned int *syscall_count) ;
+ *
+ * returns a pointer to the syscall map. the map is agnostic to the
+ * size of "long", unlike kernel bitops, it stores bits from top to
+ * bottom so that memory actually contains a linear bitmap
+ * check for syscall N by testing bit (0x80000000 >> (N & 0x1f)) of
+ * 32 bits int at N >> 5.
+ */
+V_FUNCTION_BEGIN(__kernel_get_syscall_map)
+ .cfi_startproc
+ mflr r12
+ .cfi_register lr,r12
+
+ mr r4,r3
+ bl __get_datapage@local
+ mtlr r12
+ addi r3,r3,CFG_SYSCALL_MAP32
+ cmpli cr0,r4,0
+ beqlr
+ li r0,__NR_syscalls
+ stw r0,0(r4)
+ blr
+ .cfi_endproc
+V_FUNCTION_END(__kernel_get_syscall_map)
diff --git a/arch/ppc64/kernel/vdso32/gettimeofday.S b/arch/ppc64/kernel/vdso32/gettimeofday.S
new file mode 100644
index 0000000000000..ca7f415195c40
--- /dev/null
+++ b/arch/ppc64/kernel/vdso32/gettimeofday.S
@@ -0,0 +1,139 @@
+/*
+ * Userland implementation of gettimeofday() for 32 bits processes in a
+ * ppc64 kernel for use in the vDSO
+ *
+ * Copyright (C) 2004 Benjamin Herrenschmuidt (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
+ * 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/vdso.h>
+#include <asm/offsets.h>
+#include <asm/unistd.h>
+
+ .text
+/*
+ * Exact prototype of gettimeofday
+ *
+ * int __kernel_gettimeofday(struct timeval *tv, struct timezone *tz);
+ *
+ */
+V_FUNCTION_BEGIN(__kernel_gettimeofday)
+ .cfi_startproc
+ mflr r12
+ .cfi_register lr,r12
+
+ mr r10,r3 /* r10 saves tv */
+ mr r11,r4 /* r11 saves tz */
+ bl __get_datapage@local /* get data page */
+ mr r9, r3 /* datapage ptr in r9 */
+ bl __do_get_xsec@local /* get xsec from tb & kernel */
+ bne- 2f /* out of line -> do syscall */
+
+ /* seconds are xsec >> 20 */
+ rlwinm r5,r4,12,20,31
+ rlwimi r5,r3,12,0,19
+ stw r5,TVAL32_TV_SEC(r10)
+
+ /* get remaining xsec and convert to usec. we scale
+ * up remaining xsec by 12 bits and get the top 32 bits
+ * of the multiplication
+ */
+ rlwinm r5,r4,12,0,19
+ lis r6,1000000@h
+ ori r6,r6,1000000@l
+ mulhwu r5,r5,r6
+ stw r5,TVAL32_TV_USEC(r10)
+
+ cmpli cr0,r11,0 /* check if tz is NULL */
+ beq 1f
+ lwz r4,CFG_TZ_MINUTEWEST(r9)/* fill tz */
+ lwz r5,CFG_TZ_DSTTIME(r9)
+ stw r4,TZONE_TZ_MINWEST(r11)
+ stw r5,TZONE_TZ_DSTTIME(r11)
+
+1: mtlr r12
+ blr
+
+2: mr r3,r10
+ mr r4,r11
+ li r0,__NR_gettimeofday
+ sc
+ b 1b
+ .cfi_endproc
+V_FUNCTION_END(__kernel_gettimeofday)
+
+/*
+ * This is the core of gettimeofday(), it returns the xsec
+ * value in r3 & r4 and expects the datapage ptr (non clobbered)
+ * in r9. clobbers r0,r4,r5,r6,r7,r8
+*/
+__do_get_xsec:
+ .cfi_startproc
+ /* Check for update count & load values. We use the low
+ * order 32 bits of the update count
+ */
+1: lwz r8,(CFG_TB_UPDATE_COUNT+4)(r9)
+ andi. r0,r8,1 /* pending update ? loop */
+ bne- 1b
+ xor r0,r8,r8 /* create dependency */
+ add r9,r9,r0
+
+ /* Load orig stamp (offset to TB) */
+ lwz r5,CFG_TB_ORIG_STAMP(r9)
+ lwz r6,(CFG_TB_ORIG_STAMP+4)(r9)
+
+ /* Get a stable TB value */
+2: mftbu r3
+ mftbl r4
+ mftbu r0
+ cmpl cr0,r3,r0
+ bne- 2b
+
+ /* Substract tb orig stamp. If the high part is non-zero, we jump to the
+ * slow path which call the syscall. If it's ok, then we have our 32 bits
+ * tb_ticks value in r7
+ */
+ subfc r7,r6,r4
+ subfe. r0,r5,r3
+ bne- 3f
+
+ /* Load scale factor & do multiplication */
+ lwz r5,CFG_TB_TO_XS(r9) /* load values */
+ lwz r6,(CFG_TB_TO_XS+4)(r9)
+ mulhwu r4,r7,r5
+ mulhwu r6,r7,r6
+ mullw r6,r7,r5
+ addc r6,r6,r0
+
+ /* At this point, we have the scaled xsec value in r4 + XER:CA
+ * we load & add the stamp since epoch
+ */
+ lwz r5,CFG_STAMP_XSEC(r9)
+ lwz r6,(CFG_STAMP_XSEC+4)(r9)
+ adde r4,r4,r6
+ addze r3,r5
+
+ /* We now have our result in r3,r4. We create a fake dependency
+ * on that result and re-check the counter
+ */
+ xor r0,r4,r4
+ add r9,r9,r0
+ lwz r0,(CFG_TB_UPDATE_COUNT+4)(r9)
+ cmpl cr0,r8,r0 /* check if updated */
+ bne- 1b
+
+ /* Warning ! The caller expects CR:EQ to be set to indicate a
+ * successful calculation (so it won't fallback to the syscall
+ * method). We have overriden that CR bit in the counter check,
+ * but fortunately, the loop exit condition _is_ CR:EQ set, so
+ * we can exit safely here. If you change this code, be careful
+ * of that side effect.
+ */
+3: blr
+ .cfi_endproc
diff --git a/arch/ppc64/kernel/vdso32/sigtramp.S b/arch/ppc64/kernel/vdso32/sigtramp.S
new file mode 100644
index 0000000000000..e04642781917b
--- /dev/null
+++ b/arch/ppc64/kernel/vdso32/sigtramp.S
@@ -0,0 +1,300 @@
+/*
+ * Signal trampolines for 32 bits processes in a ppc64 kernel for
+ * use in the vDSO
+ *
+ * Copyright (C) 2004 Benjamin Herrenschmuidt (benh@kernel.crashing.org), IBM Corp.
+ * Copyright (C) 2004 Alan Modra (amodra@au.ibm.com)), IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include <linux/config.h>
+#include <asm/processor.h>
+#include <asm/ppc_asm.h>
+#include <asm/unistd.h>
+#include <asm/vdso.h>
+
+ .text
+
+/* The nop here is a hack. The dwarf2 unwind routines subtract 1 from
+ the return address to get an address in the middle of the presumed
+ call instruction. Since we don't have a call here, we artifically
+ extend the range covered by the unwind info by adding a nop before
+ the real start. */
+ nop
+V_FUNCTION_BEGIN(__kernel_sigtramp32)
+.Lsig_start = . - 4
+ li r0,__NR_sigreturn
+ sc
+.Lsig_end:
+V_FUNCTION_END(__kernel_sigtramp32)
+
+.Lsigrt_start:
+ nop
+V_FUNCTION_BEGIN(__kernel_sigtramp_rt32)
+ li r0,__NR_rt_sigreturn
+ sc
+.Lsigrt_end:
+V_FUNCTION_END(__kernel_sigtramp_rt32)
+
+ .section .eh_frame,"a",@progbits
+
+/* Register r1 can be found at offset 4 of a pt_regs structure.
+ A pointer to the pt_regs is stored in memory at the old sp plus PTREGS. */
+#define cfa_save \
+ .byte 0x0f; /* DW_CFA_def_cfa_expression */ \
+ .uleb128 9f - 1f; /* length */ \
+1: \
+ .byte 0x71; .sleb128 PTREGS; /* DW_OP_breg1 */ \
+ .byte 0x06; /* DW_OP_deref */ \
+ .byte 0x23; .uleb128 RSIZE; /* DW_OP_plus_uconst */ \
+ .byte 0x06; /* DW_OP_deref */ \
+9:
+
+/* Register REGNO can be found at offset OFS of a pt_regs structure.
+ A pointer to the pt_regs is stored in memory at the old sp plus PTREGS. */
+#define rsave(regno, ofs) \
+ .byte 0x10; /* DW_CFA_expression */ \
+ .uleb128 regno; /* regno */ \
+ .uleb128 9f - 1f; /* length */ \
+1: \
+ .byte 0x71; .sleb128 PTREGS; /* DW_OP_breg1 */ \
+ .byte 0x06; /* DW_OP_deref */ \
+ .ifne ofs; \
+ .byte 0x23; .uleb128 ofs; /* DW_OP_plus_uconst */ \
+ .endif; \
+9:
+
+/* If msr bit 1<<25 is set, then VMX register REGNO is at offset REGNO*16
+ of the VMX reg struct. The VMX reg struct is at offset VREGS of
+ the pt_regs struct. This macro is for REGNO == 0, and contains
+ 'subroutines' that the other macros jump to. */
+#define vsave_msr0(regno) \
+ .byte 0x10; /* DW_CFA_expression */ \
+ .uleb128 regno + 77; /* regno */ \
+ .uleb128 9f - 1f; /* length */ \
+1: \
+ .byte 0x30 + regno; /* DW_OP_lit0 */ \
+2: \
+ .byte 0x40; /* DW_OP_lit16 */ \
+ .byte 0x1e; /* DW_OP_mul */ \
+3: \
+ .byte 0x71; .sleb128 PTREGS; /* DW_OP_breg1 */ \
+ .byte 0x06; /* DW_OP_deref */ \
+ .byte 0x12; /* DW_OP_dup */ \
+ .byte 0x23; /* DW_OP_plus_uconst */ \
+ .uleb128 33*RSIZE; /* msr offset */ \
+ .byte 0x06; /* DW_OP_deref */ \
+ .byte 0x0c; .long 1 << 25; /* DW_OP_const4u */ \
+ .byte 0x1a; /* DW_OP_and */ \
+ .byte 0x12; /* DW_OP_dup, ret 0 if bra taken */ \
+ .byte 0x30; /* DW_OP_lit0 */ \
+ .byte 0x29; /* DW_OP_eq */ \
+ .byte 0x28; .short 0x7fff; /* DW_OP_bra to end */ \
+ .byte 0x13; /* DW_OP_drop, pop the 0 */ \
+ .byte 0x23; .uleb128 VREGS; /* DW_OP_plus_uconst */ \
+ .byte 0x22; /* DW_OP_plus */ \
+ .byte 0x2f; .short 0x7fff; /* DW_OP_skip to end */ \
+9:
+
+/* If msr bit 1<<25 is set, then VMX register REGNO is at offset REGNO*16
+ of the VMX reg struct. REGNO is 1 thru 31. */
+#define vsave_msr1(regno) \
+ .byte 0x10; /* DW_CFA_expression */ \
+ .uleb128 regno + 77; /* regno */ \
+ .uleb128 9f - 1f; /* length */ \
+1: \
+ .byte 0x30 + regno; /* DW_OP_lit n */ \
+ .byte 0x2f; .short 2b - 9f; /* DW_OP_skip */ \
+9:
+
+/* If msr bit 1<<25 is set, then VMX register REGNO is at offset OFS of
+ the VMX save block. */
+#define vsave_msr2(regno, ofs) \
+ .byte 0x10; /* DW_CFA_expression */ \
+ .uleb128 regno + 77; /* regno */ \
+ .uleb128 9f - 1f; /* length */ \
+1: \
+ .byte 0x0a; .short ofs; /* DW_OP_const2u */ \
+ .byte 0x2f; .short 3b - 9f; /* DW_OP_skip */ \
+9:
+
+/* VMX register REGNO is at offset OFS of the VMX save area. */
+#define vsave(regno, ofs) \
+ .byte 0x10; /* DW_CFA_expression */ \
+ .uleb128 regno + 77; /* regno */ \
+ .uleb128 9f - 1f; /* length */ \
+1: \
+ .byte 0x71; .sleb128 PTREGS; /* DW_OP_breg1 */ \
+ .byte 0x06; /* DW_OP_deref */ \
+ .byte 0x23; .uleb128 VREGS; /* DW_OP_plus_uconst */ \
+ .byte 0x23; .uleb128 ofs; /* DW_OP_plus_uconst */ \
+9:
+
+/* This is where the pt_regs pointer can be found on the stack. */
+#define PTREGS 64+28
+
+/* Size of regs. */
+#define RSIZE 4
+
+/* This is the offset of the VMX regs. */
+#define VREGS 48*RSIZE+34*8
+
+/* Describe where general purpose regs are saved. */
+#define EH_FRAME_GEN \
+ cfa_save; \
+ rsave ( 0, 0*RSIZE); \
+ rsave ( 2, 2*RSIZE); \
+ rsave ( 3, 3*RSIZE); \
+ rsave ( 4, 4*RSIZE); \
+ rsave ( 5, 5*RSIZE); \
+ rsave ( 6, 6*RSIZE); \
+ rsave ( 7, 7*RSIZE); \
+ rsave ( 8, 8*RSIZE); \
+ rsave ( 9, 9*RSIZE); \
+ rsave (10, 10*RSIZE); \
+ rsave (11, 11*RSIZE); \
+ rsave (12, 12*RSIZE); \
+ rsave (13, 13*RSIZE); \
+ rsave (14, 14*RSIZE); \
+ rsave (15, 15*RSIZE); \
+ rsave (16, 16*RSIZE); \
+ rsave (17, 17*RSIZE); \
+ rsave (18, 18*RSIZE); \
+ rsave (19, 19*RSIZE); \
+ rsave (20, 20*RSIZE); \
+ rsave (21, 21*RSIZE); \
+ rsave (22, 22*RSIZE); \
+ rsave (23, 23*RSIZE); \
+ rsave (24, 24*RSIZE); \
+ rsave (25, 25*RSIZE); \
+ rsave (26, 26*RSIZE); \
+ rsave (27, 27*RSIZE); \
+ rsave (28, 28*RSIZE); \
+ rsave (29, 29*RSIZE); \
+ rsave (30, 30*RSIZE); \
+ rsave (31, 31*RSIZE); \
+ rsave (67, 32*RSIZE); /* ap, used as temp for nip */ \
+ rsave (65, 36*RSIZE); /* lr */ \
+ rsave (70, 38*RSIZE) /* cr */
+
+/* Describe where the FP regs are saved. */
+#define EH_FRAME_FP \
+ rsave (32, 48*RSIZE + 0*8); \
+ rsave (33, 48*RSIZE + 1*8); \
+ rsave (34, 48*RSIZE + 2*8); \
+ rsave (35, 48*RSIZE + 3*8); \
+ rsave (36, 48*RSIZE + 4*8); \
+ rsave (37, 48*RSIZE + 5*8); \
+ rsave (38, 48*RSIZE + 6*8); \
+ rsave (39, 48*RSIZE + 7*8); \
+ rsave (40, 48*RSIZE + 8*8); \
+ rsave (41, 48*RSIZE + 9*8); \
+ rsave (42, 48*RSIZE + 10*8); \
+ rsave (43, 48*RSIZE + 11*8); \
+ rsave (44, 48*RSIZE + 12*8); \
+ rsave (45, 48*RSIZE + 13*8); \
+ rsave (46, 48*RSIZE + 14*8); \
+ rsave (47, 48*RSIZE + 15*8); \
+ rsave (48, 48*RSIZE + 16*8); \
+ rsave (49, 48*RSIZE + 17*8); \
+ rsave (50, 48*RSIZE + 18*8); \
+ rsave (51, 48*RSIZE + 19*8); \
+ rsave (52, 48*RSIZE + 20*8); \
+ rsave (53, 48*RSIZE + 21*8); \
+ rsave (54, 48*RSIZE + 22*8); \
+ rsave (55, 48*RSIZE + 23*8); \
+ rsave (56, 48*RSIZE + 24*8); \
+ rsave (57, 48*RSIZE + 25*8); \
+ rsave (58, 48*RSIZE + 26*8); \
+ rsave (59, 48*RSIZE + 27*8); \
+ rsave (60, 48*RSIZE + 28*8); \
+ rsave (61, 48*RSIZE + 29*8); \
+ rsave (62, 48*RSIZE + 30*8); \
+ rsave (63, 48*RSIZE + 31*8)
+
+/* Describe where the VMX regs are saved. */
+#ifdef CONFIG_ALTIVEC
+#define EH_FRAME_VMX \
+ vsave_msr0 ( 0); \
+ vsave_msr1 ( 1); \
+ vsave_msr1 ( 2); \
+ vsave_msr1 ( 3); \
+ vsave_msr1 ( 4); \
+ vsave_msr1 ( 5); \
+ vsave_msr1 ( 6); \
+ vsave_msr1 ( 7); \
+ vsave_msr1 ( 8); \
+ vsave_msr1 ( 9); \
+ vsave_msr1 (10); \
+ vsave_msr1 (11); \
+ vsave_msr1 (12); \
+ vsave_msr1 (13); \
+ vsave_msr1 (14); \
+ vsave_msr1 (15); \
+ vsave_msr1 (16); \
+ vsave_msr1 (17); \
+ vsave_msr1 (18); \
+ vsave_msr1 (19); \
+ vsave_msr1 (20); \
+ vsave_msr1 (21); \
+ vsave_msr1 (22); \
+ vsave_msr1 (23); \
+ vsave_msr1 (24); \
+ vsave_msr1 (25); \
+ vsave_msr1 (26); \
+ vsave_msr1 (27); \
+ vsave_msr1 (28); \
+ vsave_msr1 (29); \
+ vsave_msr1 (30); \
+ vsave_msr1 (31); \
+ vsave_msr2 (33, 32*16+12); \
+ vsave (32, 32*16)
+#else
+#define EH_FRAME_VMX
+#endif
+
+.Lcie:
+ .long .Lcie_end - .Lcie_start
+.Lcie_start:
+ .long 0 /* CIE ID */
+ .byte 1 /* Version number */
+ .string "zR" /* NUL-terminated augmentation string */
+ .uleb128 4 /* Code alignment factor */
+ .sleb128 -4 /* Data alignment factor */
+ .byte 67 /* Return address register column, ap */
+ .uleb128 1 /* Augmentation value length */
+ .byte 0x1b /* DW_EH_PE_pcrel | DW_EH_PE_sdata4. */
+ .byte 0x0c,1,0 /* DW_CFA_def_cfa: r1 ofs 0 */
+ .balign 4
+.Lcie_end:
+
+ .long .Lfde0_end - .Lfde0_start
+.Lfde0_start:
+ .long .Lfde0_start - .Lcie /* CIE pointer. */
+ .long .Lsig_start - . /* PC start, length */
+ .long .Lsig_end - .Lsig_start
+ .uleb128 0 /* Augmentation */
+ EH_FRAME_GEN
+ EH_FRAME_FP
+ EH_FRAME_VMX
+ .balign 4
+.Lfde0_end:
+
+/* We have a different stack layout for rt_sigreturn. */
+#undef PTREGS
+#define PTREGS 64+16+128+20+28
+
+ .long .Lfde1_end - .Lfde1_start
+.Lfde1_start:
+ .long .Lfde1_start - .Lcie /* CIE pointer. */
+ .long .Lsigrt_start - . /* PC start, length */
+ .long .Lsigrt_end - .Lsigrt_start
+ .uleb128 0 /* Augmentation */
+ EH_FRAME_GEN
+ EH_FRAME_FP
+ EH_FRAME_VMX
+ .balign 4
+.Lfde1_end:
diff --git a/arch/ppc64/kernel/vdso32/vdso32.lds.S b/arch/ppc64/kernel/vdso32/vdso32.lds.S
new file mode 100644
index 0000000000000..cca27bd03a570
--- /dev/null
+++ b/arch/ppc64/kernel/vdso32/vdso32.lds.S
@@ -0,0 +1,111 @@
+
+/*
+ * This is the infamous ld script for the 32 bits vdso
+ * library
+ */
+#include <asm/vdso.h>
+
+/* Default link addresses for the vDSOs */
+OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", "elf32-powerpc")
+OUTPUT_ARCH(powerpc:common)
+ENTRY(_start)
+
+SECTIONS
+{
+ . = VDSO32_LBASE + SIZEOF_HEADERS;
+ .hash : { *(.hash) } :text
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .gnu.version : { *(.gnu.version) }
+ .gnu.version_d : { *(.gnu.version_d) }
+ .gnu.version_r : { *(.gnu.version_r) }
+
+ . = ALIGN (16);
+ .text :
+ {
+ *(.text .stub .text.* .gnu.linkonce.t.*)
+ }
+ PROVIDE (__etext = .);
+ PROVIDE (_etext = .);
+ PROVIDE (etext = .);
+
+ /* Other stuff is appended to the text segment: */
+ .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
+ .rodata1 : { *(.rodata1) }
+
+ .eh_frame_hdr : { *(.eh_frame_hdr) } :text :eh_frame_hdr
+ .eh_frame : { KEEP (*(.eh_frame)) } :text
+ .gcc_except_table : { *(.gcc_except_table) }
+ .fixup : { *(.fixup) }
+
+ .got ALIGN(4) : { *(.got.plt) *(.got) }
+
+ .dynamic : { *(.dynamic) } :text :dynamic
+
+ _end = .;
+ __end = .;
+ PROVIDE (end = .);
+
+
+ /* Stabs debugging sections are here too
+ */
+ .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) }
+ .debug 0 : { *(.debug) }
+ .line 0 : { *(.line) }
+
+ .debug_srcinfo 0 : { *(.debug_srcinfo) }
+ .debug_sfnames 0 : { *(.debug_sfnames) }
+
+ .debug_aranges 0 : { *(.debug_aranges) }
+ .debug_pubnames 0 : { *(.debug_pubnames) }
+
+ .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
+ .debug_abbrev 0 : { *(.debug_abbrev) }
+ .debug_line 0 : { *(.debug_line) }
+ .debug_frame 0 : { *(.debug_frame) }
+ .debug_str 0 : { *(.debug_str) }
+ .debug_loc 0 : { *(.debug_loc) }
+ .debug_macinfo 0 : { *(.debug_macinfo) }
+
+ .debug_weaknames 0 : { *(.debug_weaknames) }
+ .debug_funcnames 0 : { *(.debug_funcnames) }
+ .debug_typenames 0 : { *(.debug_typenames) }
+ .debug_varnames 0 : { *(.debug_varnames) }
+
+ /DISCARD/ : { *(.note.GNU-stack) }
+ /DISCARD/ : { *(.data .data.* .gnu.linkonce.d.* .sdata*) }
+ /DISCARD/ : { *(.bss .sbss .dynbss .dynsbss) }
+}
+
+
+PHDRS
+{
+ text PT_LOAD FILEHDR PHDRS FLAGS(5); /* PF_R|PF_X */
+ dynamic PT_DYNAMIC FLAGS(4); /* PF_R */
+ eh_frame_hdr 0x6474e550; /* PT_GNU_EH_FRAME, but ld doesn't match the name */
+}
+
+
+/*
+ * This controls what symbols we export from the DSO.
+ */
+VERSION
+{
+ VDSO_VERSION_STRING {
+ global:
+ __kernel_datapage_offset; /* Has to be there for the kernel to find it */
+ __kernel_get_syscall_map;
+ __kernel_gettimeofday;
+ __kernel_sync_dicache;
+ __kernel_sync_dicache_p5;
+ __kernel_sigtramp32;
+ __kernel_sigtramp_rt32;
+ local: *;
+ };
+}
diff --git a/arch/ppc64/kernel/vdso32/vdso32_wrapper.S b/arch/ppc64/kernel/vdso32/vdso32_wrapper.S
new file mode 100644
index 0000000000000..76ca28e09d295
--- /dev/null
+++ b/arch/ppc64/kernel/vdso32/vdso32_wrapper.S
@@ -0,0 +1,13 @@
+#include <linux/init.h>
+#include <asm/page.h>
+
+ .section ".data.page_aligned"
+
+ .globl vdso32_start, vdso32_end
+ .balign PAGE_SIZE
+vdso32_start:
+ .incbin "arch/ppc64/kernel/vdso32/vdso32.so"
+ .balign PAGE_SIZE
+vdso32_end:
+
+ .previous
diff --git a/arch/ppc64/kernel/vdso64/Makefile b/arch/ppc64/kernel/vdso64/Makefile
new file mode 100644
index 0000000000000..bd3f70b1a3849
--- /dev/null
+++ b/arch/ppc64/kernel/vdso64/Makefile
@@ -0,0 +1,35 @@
+# List of files in the vdso, has to be asm only for now
+
+obj-vdso64 = sigtramp.o gettimeofday.o datapage.o cacheflush.o
+
+# Build rules
+
+targets := $(obj-vdso64) vdso64.so
+obj-vdso64 := $(addprefix $(obj)/, $(obj-vdso64))
+
+EXTRA_CFLAGS := -shared -s -fno-common -fno-builtin
+EXTRA_CFLAGS += -nostdlib -Wl,-soname=linux-vdso64.so.1
+EXTRA_AFLAGS := -D__VDSO64__ -s
+
+obj-y += vdso64_wrapper.o
+extra-y += vdso64.lds
+CPPFLAGS_vdso64.lds += -P -C -U$(ARCH)
+
+# Force dependency (incbin is bad)
+$(obj)/vdso64_wrapper.o : $(obj)/vdso64.so
+
+# link rule for the .so file, .lds has to be first
+$(obj)/vdso64.so: $(src)/vdso64.lds $(obj-vdso64)
+ $(call if_changed,vdso64ld)
+
+# assembly rules for the .S files
+$(obj-vdso64): %.o: %.S
+ $(call if_changed_dep,vdso64as)
+
+# actual build commands
+quiet_cmd_vdso64ld = VDSO64L $@
+ cmd_vdso64ld = $(CC) $(c_flags) -Wl,-T $^ -o $@
+quiet_cmd_vdso64as = VDSO64A $@
+ cmd_vdso64as = $(CC) $(a_flags) -c -o $@ $<
+
+
diff --git a/arch/ppc64/kernel/vdso64/cacheflush.S b/arch/ppc64/kernel/vdso64/cacheflush.S
new file mode 100644
index 0000000000000..d9696ffcf3348
--- /dev/null
+++ b/arch/ppc64/kernel/vdso64/cacheflush.S
@@ -0,0 +1,64 @@
+/*
+ * vDSO provided cache flush routines
+ *
+ * Copyright (C) 2004 Benjamin Herrenschmuidt (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
+ * 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/vdso.h>
+#include <asm/offsets.h>
+
+ .text
+
+/*
+ * Default "generic" version of __kernel_sync_dicache.
+ *
+ * void __kernel_sync_dicache(unsigned long start, unsigned long end)
+ *
+ * Flushes the data cache & invalidate the instruction cache for the
+ * provided range [start, end[
+ *
+ * Note: all CPUs supported by this kernel have a 128 bytes cache
+ * line size so we don't have to peek that info from the datapage
+ */
+V_FUNCTION_BEGIN(__kernel_sync_dicache)
+ .cfi_startproc
+ li r5,127
+ andc r6,r3,r5 /* round low to line bdy */
+ subf r8,r6,r4 /* compute length */
+ add r8,r8,r5 /* ensure we get enough */
+ srwi. r8,r8,7 /* compute line count */
+ beqlr /* nothing to do? */
+ mtctr r8
+ mr r3,r6
+1: dcbst 0,r3
+ addi r3,r3,128
+ bdnz 1b
+ sync
+ mtctr r8
+1: icbi 0,r6
+ addi r6,r6,128
+ bdnz 1b
+ isync
+ blr
+ .cfi_endproc
+V_FUNCTION_END(__kernel_sync_dicache)
+
+
+/*
+ * POWER5 version of __kernel_sync_dicache
+ */
+V_FUNCTION_BEGIN(__kernel_sync_dicache_p5)
+ .cfi_startproc
+ sync
+ isync
+ blr
+ .cfi_endproc
+V_FUNCTION_END(__kernel_sync_dicache_p5)
diff --git a/arch/ppc64/kernel/vdso64/datapage.S b/arch/ppc64/kernel/vdso64/datapage.S
new file mode 100644
index 0000000000000..18afd971c9d97
--- /dev/null
+++ b/arch/ppc64/kernel/vdso64/datapage.S
@@ -0,0 +1,68 @@
+/*
+ * Access to the shared data page by the vDSO & syscall map
+ *
+ * Copyright (C) 2004 Benjamin Herrenschmuidt (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
+ * 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/offsets.h>
+#include <asm/unistd.h>
+#include <asm/vdso.h>
+
+ .text
+V_FUNCTION_BEGIN(__get_datapage)
+ .cfi_startproc
+ /* We don't want that exposed or overridable as we want other objects
+ * to be able to bl directly to here
+ */
+ .protected __get_datapage
+ .hidden __get_datapage
+
+ mflr r0
+ .cfi_register lr,r0
+
+ bcl 20,31,1f
+ .global __kernel_datapage_offset;
+__kernel_datapage_offset:
+ .long 0
+1:
+ mflr r3
+ mtlr r0
+ lwz r0,0(r3)
+ add r3,r0,r3
+ blr
+ .cfi_endproc
+V_FUNCTION_END(__get_datapage)
+
+/*
+ * void *__kernel_get_syscall_map(unsigned int *syscall_count) ;
+ *
+ * returns a pointer to the syscall map. the map is agnostic to the
+ * size of "long", unlike kernel bitops, it stores bits from top to
+ * bottom so that memory actually contains a linear bitmap
+ * check for syscall N by testing bit (0x80000000 >> (N & 0x1f)) of
+ * 32 bits int at N >> 5.
+ */
+V_FUNCTION_BEGIN(__kernel_get_syscall_map)
+ .cfi_startproc
+ mflr r12
+ .cfi_register lr,r12
+
+ mr r4,r3
+ bl V_LOCAL_FUNC(__get_datapage)
+ mtlr r12
+ addi r3,r3,CFG_SYSCALL_MAP64
+ cmpli cr0,r4,0
+ beqlr
+ li r0,__NR_syscalls
+ stw r0,0(r4)
+ blr
+ .cfi_endproc
+V_FUNCTION_END(__kernel_get_syscall_map)
diff --git a/arch/ppc64/kernel/vdso64/gettimeofday.S b/arch/ppc64/kernel/vdso64/gettimeofday.S
new file mode 100644
index 0000000000000..ed3f970ff05ed
--- /dev/null
+++ b/arch/ppc64/kernel/vdso64/gettimeofday.S
@@ -0,0 +1,91 @@
+/*
+ * Userland implementation of gettimeofday() for 64 bits processes in a
+ * ppc64 kernel for use in the vDSO
+ *
+ * Copyright (C) 2004 Benjamin Herrenschmuidt (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
+ * 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/vdso.h>
+#include <asm/offsets.h>
+
+ .text
+/*
+ * Exact prototype of gettimeofday
+ *
+ * int __kernel_gettimeofday(struct timeval *tv, struct timezone *tz);
+ *
+ */
+V_FUNCTION_BEGIN(__kernel_gettimeofday)
+ .cfi_startproc
+ mflr r12
+ .cfi_register lr,r12
+
+ mr r11,r3 /* r11 holds tv */
+ mr r10,r4 /* r10 holds tz */
+ bl V_LOCAL_FUNC(__get_datapage) /* get data page */
+ bl V_LOCAL_FUNC(__do_get_xsec) /* get xsec from tb & kernel */
+ lis r7,15 /* r7 = 1000000 = USEC_PER_SEC */
+ ori r7,r7,16960
+ rldicl r5,r4,44,20 /* r5 = sec = xsec / XSEC_PER_SEC */
+ rldicr r6,r5,20,43 /* r6 = sec * XSEC_PER_SEC */
+ std r5,TVAL64_TV_SEC(r11) /* store sec in tv */
+ subf r0,r6,r4 /* r0 = xsec = (xsec - r6) */
+ mulld r0,r0,r7 /* usec = (xsec * USEC_PER_SEC) / XSEC_PER_SEC */
+ rldicl r0,r0,44,20
+ cmpldi cr0,r10,0 /* check if tz is NULL */
+ std r0,TVAL64_TV_USEC(r11) /* store usec in tv */
+ beq 1f
+ lwz r4,CFG_TZ_MINUTEWEST(r3)/* fill tz */
+ lwz r5,CFG_TZ_DSTTIME(r3)
+ stw r4,TZONE_TZ_MINWEST(r10)
+ stw r5,TZONE_TZ_DSTTIME(r10)
+1: mtlr r12
+ li r3,0 /* always success */
+ blr
+ .cfi_endproc
+V_FUNCTION_END(__kernel_gettimeofday)
+
+
+/*
+ * This is the core of gettimeofday(), it returns the xsec
+ * value in r4 and expects the datapage ptr (non clobbered)
+ * in r3. clobbers r0,r4,r5,r6,r7,r8
+*/
+V_FUNCTION_BEGIN(__do_get_xsec)
+ .cfi_startproc
+ /* check for update count & load values */
+1: ld r7,CFG_TB_UPDATE_COUNT(r3)
+ andi. r0,r4,1 /* pending update ? loop */
+ bne- 1b
+ xor r0,r4,r4 /* create dependency */
+ add r3,r3,r0
+
+ /* Get TB & offset it */
+ mftb r8
+ ld r9,CFG_TB_ORIG_STAMP(r3)
+ subf r8,r9,r8
+
+ /* Scale result */
+ ld r5,CFG_TB_TO_XS(r3)
+ mulhdu r8,r8,r5
+
+ /* Add stamp since epoch */
+ ld r6,CFG_STAMP_XSEC(r3)
+ add r4,r6,r8
+
+ xor r0,r4,r4
+ add r3,r3,r0
+ ld r0,CFG_TB_UPDATE_COUNT(r3)
+ cmpld cr0,r0,r7 /* check if updated */
+ bne- 1b
+ blr
+ .cfi_endproc
+V_FUNCTION_END(__do_get_xsec)
diff --git a/arch/ppc64/kernel/vdso64/sigtramp.S b/arch/ppc64/kernel/vdso64/sigtramp.S
new file mode 100644
index 0000000000000..8ae8f205e4701
--- /dev/null
+++ b/arch/ppc64/kernel/vdso64/sigtramp.S
@@ -0,0 +1,294 @@
+/*
+ * Signal trampoline for 64 bits processes in a ppc64 kernel for
+ * use in the vDSO
+ *
+ * Copyright (C) 2004 Benjamin Herrenschmuidt (benh@kernel.crashing.org), IBM Corp.
+ * Copyright (C) 2004 Alan Modra (amodra@au.ibm.com)), IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include <linux/config.h>
+#include <asm/processor.h>
+#include <asm/ppc_asm.h>
+#include <asm/unistd.h>
+#include <asm/vdso.h>
+
+ .text
+
+/* The nop here is a hack. The dwarf2 unwind routines subtract 1 from
+ the return address to get an address in the middle of the presumed
+ call instruction. Since we don't have a call here, we artifically
+ extend the range covered by the unwind info by padding before the
+ real start. */
+ nop
+ .balign 8
+V_FUNCTION_BEGIN(__kernel_sigtramp_rt64)
+.Lsigrt_start = . - 4
+ addi r1, r1, __SIGNAL_FRAMESIZE
+ li r0,__NR_rt_sigreturn
+ sc
+.Lsigrt_end:
+V_FUNCTION_END(__kernel_sigtramp_rt64)
+/* The ".balign 8" above and the following zeros mimic the old stack
+ trampoline layout. The last magic value is the ucontext pointer,
+ chosen in such a way that older libgcc unwind code returns a zero
+ for a sigcontext pointer. */
+ .long 0,0,0
+ .quad 0,-21*8
+
+/* Register r1 can be found at offset 8 of a pt_regs structure.
+ A pointer to the pt_regs is stored in memory at the old sp plus PTREGS. */
+#define cfa_save \
+ .byte 0x0f; /* DW_CFA_def_cfa_expression */ \
+ .uleb128 9f - 1f; /* length */ \
+1: \
+ .byte 0x71; .sleb128 PTREGS; /* DW_OP_breg1 */ \
+ .byte 0x06; /* DW_OP_deref */ \
+ .byte 0x23; .uleb128 RSIZE; /* DW_OP_plus_uconst */ \
+ .byte 0x06; /* DW_OP_deref */ \
+9:
+
+/* Register REGNO can be found at offset OFS of a pt_regs structure.
+ A pointer to the pt_regs is stored in memory at the old sp plus PTREGS. */
+#define rsave(regno, ofs) \
+ .byte 0x10; /* DW_CFA_expression */ \
+ .uleb128 regno; /* regno */ \
+ .uleb128 9f - 1f; /* length */ \
+1: \
+ .byte 0x71; .sleb128 PTREGS; /* DW_OP_breg1 */ \
+ .byte 0x06; /* DW_OP_deref */ \
+ .ifne ofs; \
+ .byte 0x23; .uleb128 ofs; /* DW_OP_plus_uconst */ \
+ .endif; \
+9:
+
+/* If msr bit 1<<25 is set, then VMX register REGNO is at offset REGNO*16
+ of the VMX reg struct. A pointer to the VMX reg struct is at VREGS in
+ the pt_regs struct. This macro is for REGNO == 0, and contains
+ 'subroutines' that the other macros jump to. */
+#define vsave_msr0(regno) \
+ .byte 0x10; /* DW_CFA_expression */ \
+ .uleb128 regno + 77; /* regno */ \
+ .uleb128 9f - 1f; /* length */ \
+1: \
+ .byte 0x30 + regno; /* DW_OP_lit0 */ \
+2: \
+ .byte 0x40; /* DW_OP_lit16 */ \
+ .byte 0x1e; /* DW_OP_mul */ \
+3: \
+ .byte 0x71; .sleb128 PTREGS; /* DW_OP_breg1 */ \
+ .byte 0x06; /* DW_OP_deref */ \
+ .byte 0x12; /* DW_OP_dup */ \
+ .byte 0x23; /* DW_OP_plus_uconst */ \
+ .uleb128 33*RSIZE; /* msr offset */ \
+ .byte 0x06; /* DW_OP_deref */ \
+ .byte 0x0c; .long 1 << 25; /* DW_OP_const4u */ \
+ .byte 0x1a; /* DW_OP_and */ \
+ .byte 0x12; /* DW_OP_dup, ret 0 if bra taken */ \
+ .byte 0x30; /* DW_OP_lit0 */ \
+ .byte 0x29; /* DW_OP_eq */ \
+ .byte 0x28; .short 0x7fff; /* DW_OP_bra to end */ \
+ .byte 0x13; /* DW_OP_drop, pop the 0 */ \
+ .byte 0x23; .uleb128 VREGS; /* DW_OP_plus_uconst */ \
+ .byte 0x06; /* DW_OP_deref */ \
+ .byte 0x22; /* DW_OP_plus */ \
+ .byte 0x2f; .short 0x7fff; /* DW_OP_skip to end */ \
+9:
+
+/* If msr bit 1<<25 is set, then VMX register REGNO is at offset REGNO*16
+ of the VMX reg struct. REGNO is 1 thru 31. */
+#define vsave_msr1(regno) \
+ .byte 0x10; /* DW_CFA_expression */ \
+ .uleb128 regno + 77; /* regno */ \
+ .uleb128 9f - 1f; /* length */ \
+1: \
+ .byte 0x30 + regno; /* DW_OP_lit n */ \
+ .byte 0x2f; .short 2b - 9f; /* DW_OP_skip */ \
+9:
+
+/* If msr bit 1<<25 is set, then VMX register REGNO is at offset OFS of
+ the VMX save block. */
+#define vsave_msr2(regno, ofs) \
+ .byte 0x10; /* DW_CFA_expression */ \
+ .uleb128 regno + 77; /* regno */ \
+ .uleb128 9f - 1f; /* length */ \
+1: \
+ .byte 0x0a; .short ofs; /* DW_OP_const2u */ \
+ .byte 0x2f; .short 3b - 9f; /* DW_OP_skip */ \
+9:
+
+/* VMX register REGNO is at offset OFS of the VMX save area. */
+#define vsave(regno, ofs) \
+ .byte 0x10; /* DW_CFA_expression */ \
+ .uleb128 regno + 77; /* regno */ \
+ .uleb128 9f - 1f; /* length */ \
+1: \
+ .byte 0x71; .sleb128 PTREGS; /* DW_OP_breg1 */ \
+ .byte 0x06; /* DW_OP_deref */ \
+ .byte 0x23; .uleb128 VREGS; /* DW_OP_plus_uconst */ \
+ .byte 0x06; /* DW_OP_deref */ \
+ .byte 0x23; .uleb128 ofs; /* DW_OP_plus_uconst */ \
+9:
+
+/* This is where the pt_regs pointer can be found on the stack. */
+#define PTREGS 128+168+56
+
+/* Size of regs. */
+#define RSIZE 8
+
+/* This is the offset of the VMX reg pointer. */
+#define VREGS 48*RSIZE+33*8
+
+/* Describe where general purpose regs are saved. */
+#define EH_FRAME_GEN \
+ cfa_save; \
+ rsave ( 0, 0*RSIZE); \
+ rsave ( 2, 2*RSIZE); \
+ rsave ( 3, 3*RSIZE); \
+ rsave ( 4, 4*RSIZE); \
+ rsave ( 5, 5*RSIZE); \
+ rsave ( 6, 6*RSIZE); \
+ rsave ( 7, 7*RSIZE); \
+ rsave ( 8, 8*RSIZE); \
+ rsave ( 9, 9*RSIZE); \
+ rsave (10, 10*RSIZE); \
+ rsave (11, 11*RSIZE); \
+ rsave (12, 12*RSIZE); \
+ rsave (13, 13*RSIZE); \
+ rsave (14, 14*RSIZE); \
+ rsave (15, 15*RSIZE); \
+ rsave (16, 16*RSIZE); \
+ rsave (17, 17*RSIZE); \
+ rsave (18, 18*RSIZE); \
+ rsave (19, 19*RSIZE); \
+ rsave (20, 20*RSIZE); \
+ rsave (21, 21*RSIZE); \
+ rsave (22, 22*RSIZE); \
+ rsave (23, 23*RSIZE); \
+ rsave (24, 24*RSIZE); \
+ rsave (25, 25*RSIZE); \
+ rsave (26, 26*RSIZE); \
+ rsave (27, 27*RSIZE); \
+ rsave (28, 28*RSIZE); \
+ rsave (29, 29*RSIZE); \
+ rsave (30, 30*RSIZE); \
+ rsave (31, 31*RSIZE); \
+ rsave (67, 32*RSIZE); /* ap, used as temp for nip */ \
+ rsave (65, 36*RSIZE); /* lr */ \
+ rsave (70, 38*RSIZE) /* cr */
+
+/* Describe where the FP regs are saved. */
+#define EH_FRAME_FP \
+ rsave (32, 48*RSIZE + 0*8); \
+ rsave (33, 48*RSIZE + 1*8); \
+ rsave (34, 48*RSIZE + 2*8); \
+ rsave (35, 48*RSIZE + 3*8); \
+ rsave (36, 48*RSIZE + 4*8); \
+ rsave (37, 48*RSIZE + 5*8); \
+ rsave (38, 48*RSIZE + 6*8); \
+ rsave (39, 48*RSIZE + 7*8); \
+ rsave (40, 48*RSIZE + 8*8); \
+ rsave (41, 48*RSIZE + 9*8); \
+ rsave (42, 48*RSIZE + 10*8); \
+ rsave (43, 48*RSIZE + 11*8); \
+ rsave (44, 48*RSIZE + 12*8); \
+ rsave (45, 48*RSIZE + 13*8); \
+ rsave (46, 48*RSIZE + 14*8); \
+ rsave (47, 48*RSIZE + 15*8); \
+ rsave (48, 48*RSIZE + 16*8); \
+ rsave (49, 48*RSIZE + 17*8); \
+ rsave (50, 48*RSIZE + 18*8); \
+ rsave (51, 48*RSIZE + 19*8); \
+ rsave (52, 48*RSIZE + 20*8); \
+ rsave (53, 48*RSIZE + 21*8); \
+ rsave (54, 48*RSIZE + 22*8); \
+ rsave (55, 48*RSIZE + 23*8); \
+ rsave (56, 48*RSIZE + 24*8); \
+ rsave (57, 48*RSIZE + 25*8); \
+ rsave (58, 48*RSIZE + 26*8); \
+ rsave (59, 48*RSIZE + 27*8); \
+ rsave (60, 48*RSIZE + 28*8); \
+ rsave (61, 48*RSIZE + 29*8); \
+ rsave (62, 48*RSIZE + 30*8); \
+ rsave (63, 48*RSIZE + 31*8)
+
+/* Describe where the VMX regs are saved. */
+#ifdef CONFIG_ALTIVEC
+#define EH_FRAME_VMX \
+ vsave_msr0 ( 0); \
+ vsave_msr1 ( 1); \
+ vsave_msr1 ( 2); \
+ vsave_msr1 ( 3); \
+ vsave_msr1 ( 4); \
+ vsave_msr1 ( 5); \
+ vsave_msr1 ( 6); \
+ vsave_msr1 ( 7); \
+ vsave_msr1 ( 8); \
+ vsave_msr1 ( 9); \
+ vsave_msr1 (10); \
+ vsave_msr1 (11); \
+ vsave_msr1 (12); \
+ vsave_msr1 (13); \
+ vsave_msr1 (14); \
+ vsave_msr1 (15); \
+ vsave_msr1 (16); \
+ vsave_msr1 (17); \
+ vsave_msr1 (18); \
+ vsave_msr1 (19); \
+ vsave_msr1 (20); \
+ vsave_msr1 (21); \
+ vsave_msr1 (22); \
+ vsave_msr1 (23); \
+ vsave_msr1 (24); \
+ vsave_msr1 (25); \
+ vsave_msr1 (26); \
+ vsave_msr1 (27); \
+ vsave_msr1 (28); \
+ vsave_msr1 (29); \
+ vsave_msr1 (30); \
+ vsave_msr1 (31); \
+ vsave_msr2 (33, 32*16+12); \
+ vsave (32, 33*16)
+#else
+#define EH_FRAME_VMX
+#endif
+
+ .section .eh_frame,"a",@progbits
+.Lcie:
+ .long .Lcie_end - .Lcie_start
+.Lcie_start:
+ .long 0 /* CIE ID */
+ .byte 1 /* Version number */
+ .string "zR" /* NUL-terminated augmentation string */
+ .uleb128 4 /* Code alignment factor */
+ .sleb128 -8 /* Data alignment factor */
+ .byte 67 /* Return address register column, ap */
+ .uleb128 1 /* Augmentation value length */
+ .byte 0x14 /* DW_EH_PE_pcrel | DW_EH_PE_udata8. */
+ .byte 0x0c,1,0 /* DW_CFA_def_cfa: r1 ofs 0 */
+ .balign 8
+.Lcie_end:
+
+ .long .Lfde0_end - .Lfde0_start
+.Lfde0_start:
+ .long .Lfde0_start - .Lcie /* CIE pointer. */
+ .quad .Lsigrt_start - . /* PC start, length */
+ .quad .Lsigrt_end - .Lsigrt_start
+ .uleb128 0 /* Augmentation */
+ EH_FRAME_GEN
+ EH_FRAME_FP
+ EH_FRAME_VMX
+# Do we really need to describe the frame at this point? ie. will
+# we ever have some call chain that returns somewhere past the addi?
+# I don't think so, since gcc doesn't support async signals.
+# .byte 0x41 /* DW_CFA_advance_loc 1*4 */
+#undef PTREGS
+#define PTREGS 168+56
+# EH_FRAME_GEN
+# EH_FRAME_FP
+# EH_FRAME_VMX
+ .balign 8
+.Lfde0_end:
diff --git a/arch/ppc64/kernel/vdso64/vdso64.lds.S b/arch/ppc64/kernel/vdso64/vdso64.lds.S
new file mode 100644
index 0000000000000..942c815c7bc7a
--- /dev/null
+++ b/arch/ppc64/kernel/vdso64/vdso64.lds.S
@@ -0,0 +1,110 @@
+/*
+ * This is the infamous ld script for the 64 bits vdso
+ * library
+ */
+#include <asm/vdso.h>
+
+OUTPUT_FORMAT("elf64-powerpc", "elf64-powerpc", "elf64-powerpc")
+OUTPUT_ARCH(powerpc:common64)
+ENTRY(_start)
+
+SECTIONS
+{
+ . = VDSO64_LBASE + SIZEOF_HEADERS;
+ .hash : { *(.hash) } :text
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .gnu.version : { *(.gnu.version) }
+ .gnu.version_d : { *(.gnu.version_d) }
+ .gnu.version_r : { *(.gnu.version_r) }
+
+ . = ALIGN (16);
+ .text :
+ {
+ *(.text .stub .text.* .gnu.linkonce.t.*)
+ *(.sfpr .glink)
+ }
+ PROVIDE (__etext = .);
+ PROVIDE (_etext = .);
+ PROVIDE (etext = .);
+
+ /* Other stuff is appended to the text segment: */
+ .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
+ .rodata1 : { *(.rodata1) }
+ .eh_frame_hdr : { *(.eh_frame_hdr) } :text :eh_frame_hdr
+ .eh_frame : { KEEP (*(.eh_frame)) } :text
+ .gcc_except_table : { *(.gcc_except_table) }
+
+ .opd ALIGN(8) : { KEEP (*(.opd)) }
+ .got ALIGN(8) : { *(.got .toc) }
+ .rela.dyn ALIGN(8) : { *(.rela.dyn) }
+
+ .dynamic : { *(.dynamic) } :text :dynamic
+
+ _end = .;
+ PROVIDE (end = .);
+
+ /* Stabs debugging sections are here too
+ */
+ .stab 0 : { *(.stab) }
+ .stabstr 0 : { *(.stabstr) }
+ .stab.excl 0 : { *(.stab.excl) }
+ .stab.exclstr 0 : { *(.stab.exclstr) }
+ .stab.index 0 : { *(.stab.index) }
+ .stab.indexstr 0 : { *(.stab.indexstr) }
+ .comment 0 : { *(.comment) }
+ /* DWARF debug sectio/ns.
+ Symbols in the DWARF debugging sections are relative to the beginning
+ of the section so we begin them at 0. */
+ /* DWARF 1 */
+ .debug 0 : { *(.debug) }
+ .line 0 : { *(.line) }
+ /* GNU DWARF 1 extensions */
+ .debug_srcinfo 0 : { *(.debug_srcinfo) }
+ .debug_sfnames 0 : { *(.debug_sfnames) }
+ /* DWARF 1.1 and DWARF 2 */
+ .debug_aranges 0 : { *(.debug_aranges) }
+ .debug_pubnames 0 : { *(.debug_pubnames) }
+ /* DWARF 2 */
+ .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
+ .debug_abbrev 0 : { *(.debug_abbrev) }
+ .debug_line 0 : { *(.debug_line) }
+ .debug_frame 0 : { *(.debug_frame) }
+ .debug_str 0 : { *(.debug_str) }
+ .debug_loc 0 : { *(.debug_loc) }
+ .debug_macinfo 0 : { *(.debug_macinfo) }
+ /* SGI/MIPS DWARF 2 extensions */
+ .debug_weaknames 0 : { *(.debug_weaknames) }
+ .debug_funcnames 0 : { *(.debug_funcnames) }
+ .debug_typenames 0 : { *(.debug_typenames) }
+ .debug_varnames 0 : { *(.debug_varnames) }
+
+ /DISCARD/ : { *(.note.GNU-stack) }
+ /DISCARD/ : { *(.branch_lt) }
+ /DISCARD/ : { *(.data .data.* .gnu.linkonce.d.*) }
+ /DISCARD/ : { *(.bss .sbss .dynbss .dynsbss) }
+}
+
+PHDRS
+{
+ text PT_LOAD FILEHDR PHDRS FLAGS(5); /* PF_R|PF_X */
+ dynamic PT_DYNAMIC FLAGS(4); /* PF_R */
+ eh_frame_hdr 0x6474e550; /* PT_GNU_EH_FRAME, but ld doesn't match the name */
+}
+
+/*
+ * This controls what symbols we export from the DSO.
+ */
+VERSION
+{
+ VDSO_VERSION_STRING {
+ global:
+ __kernel_datapage_offset; /* Has to be there for the kernel to find it */
+ __kernel_get_syscall_map;
+ __kernel_gettimeofday;
+ __kernel_sync_dicache;
+ __kernel_sync_dicache_p5;
+ __kernel_sigtramp_rt64;
+ local: *;
+ };
+}
diff --git a/arch/ppc64/kernel/vdso64/vdso64_wrapper.S b/arch/ppc64/kernel/vdso64/vdso64_wrapper.S
new file mode 100644
index 0000000000000..771c2741c492e
--- /dev/null
+++ b/arch/ppc64/kernel/vdso64/vdso64_wrapper.S
@@ -0,0 +1,13 @@
+#include <linux/init.h>
+#include <asm/page.h>
+
+ .section ".data.page_aligned"
+
+ .globl vdso64_start, vdso64_end
+ .balign PAGE_SIZE
+vdso64_start:
+ .incbin "arch/ppc64/kernel/vdso64/vdso64.so"
+ .balign PAGE_SIZE
+vdso64_end:
+
+ .previous
diff --git a/arch/ppc64/kernel/vio.c b/arch/ppc64/kernel/vio.c
index 8adddd7ca1ad9..cdd830cb2768b 100644
--- a/arch/ppc64/kernel/vio.c
+++ b/arch/ppc64/kernel/vio.c
@@ -557,48 +557,61 @@ int vio_disable_interrupts(struct vio_dev *dev)
EXPORT_SYMBOL(vio_disable_interrupts);
#endif
-dma_addr_t vio_map_single(struct vio_dev *dev, void *vaddr,
+static dma_addr_t vio_map_single(struct device *dev, void *vaddr,
size_t size, enum dma_data_direction direction)
{
- return iommu_map_single(dev->iommu_table, vaddr, size, direction);
+ return iommu_map_single(to_vio_dev(dev)->iommu_table, vaddr, size,
+ direction);
}
-EXPORT_SYMBOL(vio_map_single);
-void vio_unmap_single(struct vio_dev *dev, dma_addr_t dma_handle,
+static void vio_unmap_single(struct device *dev, dma_addr_t dma_handle,
size_t size, enum dma_data_direction direction)
{
- iommu_unmap_single(dev->iommu_table, dma_handle, size, direction);
+ iommu_unmap_single(to_vio_dev(dev)->iommu_table, dma_handle, size,
+ direction);
}
-EXPORT_SYMBOL(vio_unmap_single);
-int vio_map_sg(struct vio_dev *vdev, struct scatterlist *sglist, int nelems,
- enum dma_data_direction direction)
+static int vio_map_sg(struct device *dev, struct scatterlist *sglist,
+ int nelems, enum dma_data_direction direction)
{
- return iommu_map_sg(&vdev->dev, vdev->iommu_table, sglist,
+ return iommu_map_sg(dev, to_vio_dev(dev)->iommu_table, sglist,
nelems, direction);
}
-EXPORT_SYMBOL(vio_map_sg);
-void vio_unmap_sg(struct vio_dev *vdev, struct scatterlist *sglist, int nelems,
- enum dma_data_direction direction)
+static void vio_unmap_sg(struct device *dev, struct scatterlist *sglist,
+ int nelems, enum dma_data_direction direction)
{
- iommu_unmap_sg(vdev->iommu_table, sglist, nelems, direction);
+ iommu_unmap_sg(to_vio_dev(dev)->iommu_table, sglist, nelems, direction);
}
-EXPORT_SYMBOL(vio_unmap_sg);
-void *vio_alloc_consistent(struct vio_dev *dev, size_t size,
- dma_addr_t *dma_handle)
+static void *vio_alloc_coherent(struct device *dev, size_t size,
+ dma_addr_t *dma_handle, unsigned int __nocast flag)
{
- return iommu_alloc_consistent(dev->iommu_table, size, dma_handle);
+ return iommu_alloc_coherent(to_vio_dev(dev)->iommu_table, size,
+ dma_handle, flag);
}
-EXPORT_SYMBOL(vio_alloc_consistent);
-void vio_free_consistent(struct vio_dev *dev, size_t size,
+static void vio_free_coherent(struct device *dev, size_t size,
void *vaddr, dma_addr_t dma_handle)
{
- iommu_free_consistent(dev->iommu_table, size, vaddr, dma_handle);
+ iommu_free_coherent(to_vio_dev(dev)->iommu_table, size, vaddr,
+ dma_handle);
}
-EXPORT_SYMBOL(vio_free_consistent);
+
+static int vio_dma_supported(struct device *dev, u64 mask)
+{
+ return 1;
+}
+
+struct dma_mapping_ops vio_dma_ops = {
+ .alloc_coherent = vio_alloc_coherent,
+ .free_coherent = vio_free_coherent,
+ .map_single = vio_map_single,
+ .unmap_single = vio_unmap_single,
+ .map_sg = vio_map_sg,
+ .unmap_sg = vio_unmap_sg,
+ .dma_supported = vio_dma_supported,
+};
static int vio_bus_match(struct device *dev, struct device_driver *drv)
{
diff --git a/arch/ppc64/kernel/viopath.c b/arch/ppc64/kernel/viopath.c
index 74f185ec91f8c..2ed8ee0756805 100644
--- a/arch/ppc64/kernel/viopath.c
+++ b/arch/ppc64/kernel/viopath.c
@@ -42,6 +42,7 @@
#include <asm/system.h>
#include <asm/uaccess.h>
+#include <asm/iSeries/HvTypes.h>
#include <asm/iSeries/LparData.h>
#include <asm/iSeries/HvLpEvent.h>
#include <asm/iSeries/HvLpConfig.h>
@@ -56,8 +57,8 @@
* But this allows for other support in the future.
*/
static struct viopathStatus {
- int isOpen:1; /* Did we open the path? */
- int isActive:1; /* Do we have a mon msg outstanding */
+ int isOpen; /* Did we open the path? */
+ int isActive; /* Do we have a mon msg outstanding */
int users[VIO_MAX_SUBTYPES];
HvLpInstanceId mSourceInst;
HvLpInstanceId mTargetInst;
@@ -79,12 +80,12 @@ static void handleMonitorEvent(struct HvLpEvent *event);
/*
* We use this structure to handle asynchronous responses. The caller
* blocks on the semaphore and the handler posts the semaphore. However,
- * if in_atomic() is true in the caller, then wait_atomic is used ...
+ * if system_state is not SYSTEM_RUNNING, then wait_atomic is used ...
*/
-struct doneAllocParms_t {
- struct semaphore *sem;
+struct alloc_parms {
+ struct semaphore sem;
int number;
- atomic_t *wait_atomic;
+ atomic_t wait_atomic;
int used_wait_atomic;
};
@@ -97,9 +98,9 @@ static u8 viomonseq = 22;
/* Our hosting logical partition. We get this at startup
* time, and different modules access this variable directly.
*/
-HvLpIndex viopath_hostLp = 0xff; /* HvLpIndexInvalid */
+HvLpIndex viopath_hostLp = HvLpIndexInvalid;
EXPORT_SYMBOL(viopath_hostLp);
-HvLpIndex viopath_ourLp = 0xff;
+HvLpIndex viopath_ourLp = HvLpIndexInvalid;
EXPORT_SYMBOL(viopath_ourLp);
/* For each kind of incoming event we set a pointer to a
@@ -200,7 +201,7 @@ EXPORT_SYMBOL(viopath_isactive);
/*
* We cache the source and target instance ids for each
- * partition.
+ * partition.
*/
HvLpInstanceId viopath_sourceinst(HvLpIndex lp)
{
@@ -450,36 +451,33 @@ static void vio_handleEvent(struct HvLpEvent *event, struct pt_regs *regs)
static void viopath_donealloc(void *parm, int number)
{
- struct doneAllocParms_t *parmsp = (struct doneAllocParms_t *)parm;
+ struct alloc_parms *parmsp = parm;
parmsp->number = number;
if (parmsp->used_wait_atomic)
- atomic_set(parmsp->wait_atomic, 0);
+ atomic_set(&parmsp->wait_atomic, 0);
else
- up(parmsp->sem);
+ up(&parmsp->sem);
}
static int allocateEvents(HvLpIndex remoteLp, int numEvents)
{
- struct doneAllocParms_t parms;
- DECLARE_MUTEX_LOCKED(Semaphore);
- atomic_t wait_atomic;
+ struct alloc_parms parms;
- if (in_atomic()) {
+ if (system_state != SYSTEM_RUNNING) {
parms.used_wait_atomic = 1;
- atomic_set(&wait_atomic, 1);
- parms.wait_atomic = &wait_atomic;
+ atomic_set(&parms.wait_atomic, 1);
} else {
parms.used_wait_atomic = 0;
- parms.sem = &Semaphore;
+ init_MUTEX_LOCKED(&parms.sem);
}
mf_allocate_lp_events(remoteLp, HvLpEvent_Type_VirtualIo, 250, /* It would be nice to put a real number here! */
numEvents, &viopath_donealloc, &parms);
- if (in_atomic()) {
- while (atomic_read(&wait_atomic))
+ if (system_state != SYSTEM_RUNNING) {
+ while (atomic_read(&parms.wait_atomic))
mb();
} else
- down(&Semaphore);
+ down(&parms.sem);
return parms.number;
}
@@ -558,8 +556,7 @@ int viopath_close(HvLpIndex remoteLp, int subtype, int numReq)
unsigned long flags;
int i;
int numOpen;
- struct doneAllocParms_t doneAllocParms;
- DECLARE_MUTEX_LOCKED(Semaphore);
+ struct alloc_parms parms;
if ((remoteLp >= HvMaxArchitectedLps) || (remoteLp == HvLpIndexInvalid))
return -EINVAL;
@@ -580,11 +577,11 @@ int viopath_close(HvLpIndex remoteLp, int subtype, int numReq)
spin_unlock_irqrestore(&statuslock, flags);
- doneAllocParms.used_wait_atomic = 0;
- doneAllocParms.sem = &Semaphore;
+ parms.used_wait_atomic = 0;
+ init_MUTEX_LOCKED(&parms.sem);
mf_deallocate_lp_events(remoteLp, HvLpEvent_Type_VirtualIo,
- numReq, &viopath_donealloc, &doneAllocParms);
- down(&Semaphore);
+ numReq, &viopath_donealloc, &parms);
+ down(&parms.sem);
spin_lock_irqsave(&statuslock, flags);
for (i = 0, numOpen = 0; i < VIO_MAX_SUBTYPES; i++)
diff --git a/arch/ppc64/kernel/xics.c b/arch/ppc64/kernel/xics.c
index 929dff19cfaec..eedd1d3c2a10a 100644
--- a/arch/ppc64/kernel/xics.c
+++ b/arch/ppc64/kernel/xics.c
@@ -654,7 +654,7 @@ void xics_migrate_irqs_away(void)
/* remove ourselves from the global interrupt queue */
status = rtas_set_indicator(GLOBAL_INTERRUPT_QUEUE,
(1UL << interrupt_server_size) - 1 - default_distrib_server, 0);
- WARN_ON(status != 0);
+ WARN_ON(status < 0);
/* Allow IPIs again... */
ops->cppr_info(cpu, DEFAULT_PRIORITY);
@@ -704,15 +704,8 @@ void xics_migrate_irqs_away(void)
virq, cpu);
/* Reset affinity to all cpus */
- xics_status[0] = default_distrib_server;
-
- status = rtas_call(ibm_set_xive, 3, 1, NULL, irq,
- xics_status[0], xics_status[1]);
- if (status)
- printk(KERN_ERR "migrate_irqs_away: irq=%d "
- "ibm,set-xive returns %d\n",
- virq, status);
-
+ desc->handler->set_affinity(virq, CPU_MASK_ALL);
+ irq_affinity[virq] = CPU_MASK_ALL;
unlock:
spin_unlock_irqrestore(&desc->lock, flags);
}
diff --git a/arch/ppc64/mm/fault.c b/arch/ppc64/mm/fault.c
index 2b383974a8f32..20b0f37e8bf8f 100644
--- a/arch/ppc64/mm/fault.c
+++ b/arch/ppc64/mm/fault.c
@@ -91,8 +91,9 @@ int do_page_fault(struct pt_regs *regs, unsigned long address,
struct mm_struct *mm = current->mm;
siginfo_t info;
unsigned long code = SEGV_MAPERR;
- unsigned long is_write = error_code & 0x02000000;
+ unsigned long is_write = error_code & DSISR_ISSTORE;
unsigned long trap = TRAP(regs);
+ unsigned long is_exec = trap == 0x400;
BUG_ON((trap == 0x380) || (trap == 0x480));
@@ -109,7 +110,7 @@ int do_page_fault(struct pt_regs *regs, unsigned long address,
if (!user_mode(regs) && (address >= TASK_SIZE))
return SIGSEGV;
- if (error_code & 0x00400000) {
+ if (error_code & DSISR_DABRMATCH) {
if (notify_die(DIE_DABR_MATCH, "dabr_match", regs, error_code,
11, SIGSEGV) == NOTIFY_STOP)
return 0;
@@ -199,16 +200,19 @@ int do_page_fault(struct pt_regs *regs, unsigned long address,
good_area:
code = SEGV_ACCERR;
+ if (is_exec) {
+ /* protection fault */
+ if (error_code & DSISR_PROTFAULT)
+ goto bad_area;
+ if (!(vma->vm_flags & VM_EXEC))
+ goto bad_area;
/* a write */
- if (is_write) {
+ } else if (is_write) {
if (!(vma->vm_flags & VM_WRITE))
goto bad_area;
/* a read */
} else {
- /* protection fault */
- if (error_code & 0x08000000)
- goto bad_area;
- if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
+ if (!(vma->vm_flags & VM_READ))
goto bad_area;
}
@@ -251,6 +255,12 @@ bad_area_nosemaphore:
return 0;
}
+ if (trap == 0x400 && (error_code & DSISR_PROTFAULT)
+ && printk_ratelimit())
+ printk(KERN_CRIT "kernel tried to execute NX-protected"
+ " page (%lx) - exploit attempt? (uid: %d)\n",
+ address, current->uid);
+
return SIGSEGV;
/*
diff --git a/arch/ppc64/mm/hash_low.S b/arch/ppc64/mm/hash_low.S
index 9a7652bc40049..8c0156a37001d 100644
--- a/arch/ppc64/mm/hash_low.S
+++ b/arch/ppc64/mm/hash_low.S
@@ -89,7 +89,7 @@ _GLOBAL(__hash_page)
/* Prepare new PTE value (turn access RW into DIRTY, then
* add BUSY,HASHPTE and ACCESSED)
*/
- rlwinm r30,r4,5,24,24 /* _PAGE_RW -> _PAGE_DIRTY */
+ rlwinm r30,r4,32-9+7,31-7,31-7 /* _PAGE_RW -> _PAGE_DIRTY */
or r30,r30,r31
ori r30,r30,_PAGE_BUSY | _PAGE_ACCESSED | _PAGE_HASHPTE
/* Write the linux PTE atomically (setting busy) */
@@ -112,11 +112,11 @@ _GLOBAL(__hash_page)
rldicl r5,r5,0,25 /* vsid & 0x0000007fffffffff */
rldicl r0,r3,64-12,48 /* (ea >> 12) & 0xffff */
xor r28,r5,r0
-
- /* Convert linux PTE bits into HW equivalents
- */
- andi. r3,r30,0x1fa /* Get basic set of flags */
- rlwinm r0,r30,32-2+1,30,30 /* _PAGE_RW -> _PAGE_USER (r0) */
+
+ /* Convert linux PTE bits into HW equivalents */
+ andi. r3,r30,0x1fe /* Get basic set of flags */
+ xori r3,r3,HW_NO_EXEC /* _PAGE_EXEC -> NOEXEC */
+ rlwinm r0,r30,32-9+1,30,30 /* _PAGE_RW -> _PAGE_USER (r0) */
rlwinm r4,r30,32-7+1,30,30 /* _PAGE_DIRTY -> _PAGE_USER (r4) */
and r0,r0,r4 /* _PAGE_RW & _PAGE_DIRTY -> r0 bit 30 */
andc r0,r30,r0 /* r0 = pte & ~r0 */
diff --git a/arch/ppc64/mm/hash_native.c b/arch/ppc64/mm/hash_native.c
index dfd24ad27b14a..144657e0c3d55 100644
--- a/arch/ppc64/mm/hash_native.c
+++ b/arch/ppc64/mm/hash_native.c
@@ -217,10 +217,10 @@ static long native_hpte_updatepp(unsigned long slot, unsigned long newpp,
}
/* Ensure it is out of the tlb too */
- if ((cur_cpu_spec->cpu_features & CPU_FTR_TLBIEL) && !large && local) {
+ if (cpu_has_feature(CPU_FTR_TLBIEL) && !large && local) {
tlbiel(va);
} else {
- int lock_tlbie = !(cur_cpu_spec->cpu_features & CPU_FTR_LOCKLESS_TLBIE);
+ int lock_tlbie = !cpu_has_feature(CPU_FTR_LOCKLESS_TLBIE);
if (lock_tlbie)
spin_lock(&native_tlbie_lock);
@@ -245,7 +245,7 @@ static void native_hpte_updateboltedpp(unsigned long newpp, unsigned long ea)
unsigned long vsid, va, vpn, flags = 0;
long slot;
HPTE *hptep;
- int lock_tlbie = !(cur_cpu_spec->cpu_features & CPU_FTR_LOCKLESS_TLBIE);
+ int lock_tlbie = !cpu_has_feature(CPU_FTR_LOCKLESS_TLBIE);
vsid = get_kernel_vsid(ea);
va = (vsid << 28) | (ea & 0x0fffffff);
@@ -273,7 +273,7 @@ static void native_hpte_invalidate(unsigned long slot, unsigned long va,
Hpte_dword0 dw0;
unsigned long avpn = va >> 23;
unsigned long flags;
- int lock_tlbie = !(cur_cpu_spec->cpu_features & CPU_FTR_LOCKLESS_TLBIE);
+ int lock_tlbie = !cpu_has_feature(CPU_FTR_LOCKLESS_TLBIE);
if (large)
avpn &= ~0x1UL;
@@ -292,7 +292,7 @@ static void native_hpte_invalidate(unsigned long slot, unsigned long va,
}
/* Invalidate the tlb */
- if ((cur_cpu_spec->cpu_features & CPU_FTR_TLBIEL) && !large && local) {
+ if (cpu_has_feature(CPU_FTR_TLBIEL) && !large && local) {
tlbiel(va);
} else {
if (lock_tlbie)
@@ -360,7 +360,7 @@ static void native_flush_hash_range(unsigned long context,
j++;
}
- if ((cur_cpu_spec->cpu_features & CPU_FTR_TLBIEL) && !large && local) {
+ if (cpu_has_feature(CPU_FTR_TLBIEL) && !large && local) {
asm volatile("ptesync":::"memory");
for (i = 0; i < j; i++)
@@ -368,7 +368,7 @@ static void native_flush_hash_range(unsigned long context,
asm volatile("ptesync":::"memory");
} else {
- int lock_tlbie = !(cur_cpu_spec->cpu_features & CPU_FTR_LOCKLESS_TLBIE);
+ int lock_tlbie = !cpu_has_feature(CPU_FTR_LOCKLESS_TLBIE);
if (lock_tlbie)
spin_lock(&native_tlbie_lock);
diff --git a/arch/ppc64/mm/hash_utils.c b/arch/ppc64/mm/hash_utils.c
index 9b01f6fb68257..e48be12f518c4 100644
--- a/arch/ppc64/mm/hash_utils.c
+++ b/arch/ppc64/mm/hash_utils.c
@@ -51,6 +51,7 @@
#include <asm/cacheflush.h>
#include <asm/cputable.h>
#include <asm/abs_addr.h>
+#include <asm/sections.h>
#ifdef DEBUG
#define DBG(fmt...) udbg_printf(fmt)
@@ -95,6 +96,7 @@ static inline void create_pte_mapping(unsigned long start, unsigned long end,
{
unsigned long addr;
unsigned int step;
+ unsigned long tmp_mode;
if (large)
step = 16*MB;
@@ -112,6 +114,13 @@ static inline void create_pte_mapping(unsigned long start, unsigned long end,
else
vpn = va >> PAGE_SHIFT;
+
+ tmp_mode = mode;
+
+ /* Make non-kernel text non-executable */
+ if (!in_kernel_text(addr))
+ tmp_mode = mode | HW_NO_EXEC;
+
hash = hpt_hash(vpn, large);
hpteg = ((hash & htab_hash_mask) * HPTES_PER_GROUP);
@@ -120,12 +129,12 @@ static inline void create_pte_mapping(unsigned long start, unsigned long end,
if (systemcfg->platform & PLATFORM_LPAR)
ret = pSeries_lpar_hpte_insert(hpteg, va,
virt_to_abs(addr) >> PAGE_SHIFT,
- 0, mode, 1, large);
+ 0, tmp_mode, 1, large);
else
#endif /* CONFIG_PPC_PSERIES */
ret = native_hpte_insert(hpteg, va,
virt_to_abs(addr) >> PAGE_SHIFT,
- 0, mode, 1, large);
+ 0, tmp_mode, 1, large);
if (ret == -1) {
ppc64_terminate_msg(0x20, "create_pte_mapping");
@@ -140,6 +149,8 @@ void __init htab_initialize(void)
unsigned long pteg_count;
unsigned long mode_rw;
int i, use_largepages = 0;
+ unsigned long base = 0, size = 0;
+ extern unsigned long tce_alloc_start, tce_alloc_end;
DBG(" -> htab_initialize()\n");
@@ -190,13 +201,11 @@ void __init htab_initialize(void)
* _NOT_ map it to avoid cache paradoxes as it's remapped non
* cacheable later on
*/
- if (cur_cpu_spec->cpu_features & CPU_FTR_16M_PAGE)
+ if (cpu_has_feature(CPU_FTR_16M_PAGE))
use_largepages = 1;
/* create bolted the linear mapping in the hash table */
for (i=0; i < lmb.memory.cnt; i++) {
- unsigned long base, size;
-
base = lmb.memory.region[i].physbase + KERNELBASE;
size = lmb.memory.region[i].size;
@@ -225,6 +234,25 @@ void __init htab_initialize(void)
#endif /* CONFIG_U3_DART */
create_pte_mapping(base, base + size, mode_rw, use_largepages);
}
+
+ /*
+ * If we have a memory_limit and we've allocated TCEs then we need to
+ * explicitly map the TCE area at the top of RAM. We also cope with the
+ * case that the TCEs start below memory_limit.
+ * tce_alloc_start/end are 16MB aligned so the mapping should work
+ * for either 4K or 16MB pages.
+ */
+ if (tce_alloc_start) {
+ tce_alloc_start += KERNELBASE;
+ tce_alloc_end += KERNELBASE;
+
+ if (base + size >= tce_alloc_start)
+ tce_alloc_start = base + size + 1;
+
+ create_pte_mapping(tce_alloc_start, tce_alloc_end,
+ mode_rw, use_largepages);
+ }
+
DBG(" <- htab_initialize()\n");
}
#undef KB
@@ -238,8 +266,6 @@ unsigned int hash_page_do_lazy_icache(unsigned int pp, pte_t pte, int trap)
{
struct page *page;
-#define PPC64_HWNOEXEC (1 << 2)
-
if (!pfn_valid(pte_pfn(pte)))
return pp;
@@ -251,7 +277,7 @@ unsigned int hash_page_do_lazy_icache(unsigned int pp, pte_t pte, int trap)
__flush_dcache_icache(page_address(page));
set_bit(PG_arch_1, &page->flags);
} else
- pp |= PPC64_HWNOEXEC;
+ pp |= HW_NO_EXEC;
}
return pp;
}
diff --git a/arch/ppc64/mm/hugetlbpage.c b/arch/ppc64/mm/hugetlbpage.c
index 3aa910f89369e..c62ddaff07209 100644
--- a/arch/ppc64/mm/hugetlbpage.c
+++ b/arch/ppc64/mm/hugetlbpage.c
@@ -149,11 +149,12 @@ static pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
}
static void set_huge_pte(struct mm_struct *mm, struct vm_area_struct *vma,
- struct page *page, pte_t *ptep, int write_access)
+ unsigned long addr, struct page *page,
+ pte_t *ptep, int write_access)
{
pte_t entry;
- mm->rss += (HPAGE_SIZE / PAGE_SIZE);
+ add_mm_counter(mm, rss, HPAGE_SIZE / PAGE_SIZE);
if (write_access) {
entry =
pte_mkwrite(pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
@@ -163,7 +164,7 @@ static void set_huge_pte(struct mm_struct *mm, struct vm_area_struct *vma,
entry = pte_mkyoung(entry);
entry = pte_mkhuge(entry);
- set_pte(ptep, entry);
+ set_pte_at(mm, addr, ptep, entry);
}
/*
@@ -315,8 +316,8 @@ int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src,
ptepage = pte_page(entry);
get_page(ptepage);
- dst->rss += (HPAGE_SIZE / PAGE_SIZE);
- set_pte(dst_pte, entry);
+ add_mm_counter(dst, rss, HPAGE_SIZE / PAGE_SIZE);
+ set_pte_at(dst, addr, dst_pte, entry);
addr += HPAGE_SIZE;
}
@@ -421,11 +422,11 @@ void unmap_hugepage_range(struct vm_area_struct *vma,
pte = *ptep;
page = pte_page(pte);
- pte_clear(ptep);
+ pte_clear(mm, addr, ptep);
put_page(page);
}
- mm->rss -= (end - start) >> PAGE_SHIFT;
+ add_mm_counter(mm, rss, -((end - start) >> PAGE_SHIFT));
flush_tlb_pending();
}
@@ -486,7 +487,7 @@ int hugetlb_prefault(struct address_space *mapping, struct vm_area_struct *vma)
goto out;
}
}
- set_huge_pte(mm, vma, page, pte, vma->vm_flags & VM_WRITE);
+ set_huge_pte(mm, vma, addr, page, pte, vma->vm_flags & VM_WRITE);
}
out:
spin_unlock(&mm->page_table_lock);
@@ -512,7 +513,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
vma = find_vma(mm, addr);
if (((TASK_SIZE - len) >= addr)
&& (!vma || (addr+len) <= vma->vm_start)
- && !is_hugepage_only_range(addr,len))
+ && !is_hugepage_only_range(mm, addr,len))
return addr;
}
start_addr = addr = mm->free_area_cache;
@@ -522,7 +523,7 @@ full_search:
while (TASK_SIZE - len >= addr) {
BUG_ON(vma && (addr >= vma->vm_end));
- if (touches_hugepage_low_range(addr, len)) {
+ if (touches_hugepage_low_range(mm, addr, len)) {
addr = ALIGN(addr+1, 1<<SID_SHIFT);
vma = find_vma(mm, addr);
continue;
@@ -583,7 +584,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
vma = find_vma(mm, addr);
if (TASK_SIZE - len >= addr &&
(!vma || addr + len <= vma->vm_start)
- && !is_hugepage_only_range(addr,len))
+ && !is_hugepage_only_range(mm, addr,len))
return addr;
}
@@ -596,7 +597,7 @@ try_again:
addr = (mm->free_area_cache - len) & PAGE_MASK;
do {
hugepage_recheck:
- if (touches_hugepage_low_range(addr, len)) {
+ if (touches_hugepage_low_range(mm, addr, len)) {
addr = (addr & ((~0) << SID_SHIFT)) - len;
goto hugepage_recheck;
} else if (touches_hugepage_high_range(addr, len)) {
@@ -709,7 +710,7 @@ unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
if (len & ~HPAGE_MASK)
return -EINVAL;
- if (!(cur_cpu_spec->cpu_features & CPU_FTR_16M_PAGE))
+ if (!cpu_has_feature(CPU_FTR_16M_PAGE))
return -EINVAL;
if (test_thread_flag(TIF_32BIT)) {
@@ -781,7 +782,6 @@ int hash_huge_page(struct mm_struct *mm, unsigned long access,
{
pte_t *ptep;
unsigned long va, vpn;
- int is_write;
pte_t old_pte, new_pte;
unsigned long hpteflags, prpn;
long slot;
@@ -808,8 +808,7 @@ int hash_huge_page(struct mm_struct *mm, unsigned long access,
* Check the user's access rights to the page. If access should be
* prevented then send the problem up to do_page_fault.
*/
- is_write = access & _PAGE_RW;
- if (unlikely(is_write && !(pte_val(*ptep) & _PAGE_RW)))
+ if (unlikely(access & ~pte_val(*ptep)))
goto out;
/*
* At this point, we have a pte (old_pte) which can be used to build
@@ -828,6 +827,8 @@ int hash_huge_page(struct mm_struct *mm, unsigned long access,
new_pte = old_pte;
hpteflags = 0x2 | (! (pte_val(new_pte) & _PAGE_RW));
+ /* _PAGE_EXEC -> HW_NO_EXEC since it's inverted */
+ hpteflags |= ((pte_val(new_pte) & _PAGE_EXEC) ? 0 : HW_NO_EXEC);
/* Check if pte already has an hpte (case 2) */
if (unlikely(pte_val(old_pte) & _PAGE_HASHPTE)) {
diff --git a/arch/ppc64/mm/init.c b/arch/ppc64/mm/init.c
index 4cb05a070c010..23813d03e1c42 100644
--- a/arch/ppc64/mm/init.c
+++ b/arch/ppc64/mm/init.c
@@ -38,6 +38,7 @@
#include <linux/highmem.h>
#include <linux/idr.h>
#include <linux/nodemask.h>
+#include <linux/module.h>
#include <asm/pgalloc.h>
#include <asm/page.h>
@@ -62,6 +63,7 @@
#include <asm/system.h>
#include <asm/iommu.h>
#include <asm/abs_addr.h>
+#include <asm/vdso.h>
int mem_init_done;
unsigned long ioremap_bot = IMALLOC_BASE;
@@ -153,7 +155,7 @@ static void map_io_page(unsigned long ea, unsigned long pa, int flags)
ptep = pte_alloc_kernel(&ioremap_mm, pmdp, ea);
pa = abs_to_phys(pa);
- set_pte(ptep, pfn_pte(pa >> PAGE_SHIFT, __pgprot(flags)));
+ set_pte_at(&ioremap_mm, ea, ptep, pfn_pte(pa >> PAGE_SHIFT, __pgprot(flags)));
spin_unlock(&ioremap_mm.page_table_lock);
} else {
unsigned long va, vpn, hash, hpteg;
@@ -286,7 +288,7 @@ int __ioremap_explicit(unsigned long pa, unsigned long ea,
static void unmap_im_area_pte(pmd_t *pmd, unsigned long address,
unsigned long size)
{
- unsigned long end;
+ unsigned long base, end;
pte_t *pte;
if (pmd_none(*pmd))
@@ -298,6 +300,7 @@ static void unmap_im_area_pte(pmd_t *pmd, unsigned long address,
}
pte = pte_offset_kernel(pmd, address);
+ base = address & PMD_MASK;
address &= ~PMD_MASK;
end = address + size;
if (end > PMD_SIZE)
@@ -305,7 +308,7 @@ static void unmap_im_area_pte(pmd_t *pmd, unsigned long address,
do {
pte_t page;
- page = ptep_get_and_clear(pte);
+ page = ptep_get_and_clear(&ioremap_mm, base + address, pte);
address += PAGE_SIZE;
pte++;
if (pte_none(page))
@@ -319,7 +322,7 @@ static void unmap_im_area_pte(pmd_t *pmd, unsigned long address,
static void unmap_im_area_pmd(pgd_t *dir, unsigned long address,
unsigned long size)
{
- unsigned long end;
+ unsigned long base, end;
pmd_t *pmd;
if (pgd_none(*dir))
@@ -331,13 +334,14 @@ static void unmap_im_area_pmd(pgd_t *dir, unsigned long address,
}
pmd = pmd_offset(dir, address);
+ base = address & PGDIR_MASK;
address &= ~PGDIR_MASK;
end = address + size;
if (end > PGDIR_SIZE)
end = PGDIR_SIZE;
do {
- unmap_im_area_pte(pmd, address, end - address);
+ unmap_im_area_pte(pmd, base + address, end - address);
address = (address + PMD_SIZE) & PMD_MASK;
pmd++;
} while (address < end);
@@ -441,6 +445,10 @@ int iounmap_explicit(volatile void __iomem *start, unsigned long size)
#endif
+EXPORT_SYMBOL(ioremap);
+EXPORT_SYMBOL(__ioremap);
+EXPORT_SYMBOL(iounmap);
+
void free_initmem(void)
{
unsigned long addr;
@@ -658,7 +666,6 @@ void __init paging_init(void)
free_area_init_node(0, &contig_page_data, zones_size,
__pa(PAGE_OFFSET) >> PAGE_SHIFT, zholes_size);
- mem_map = contig_page_data.node_mem_map;
}
#endif /* CONFIG_DISCONTIGMEM */
@@ -743,6 +750,8 @@ void __init mem_init(void)
#ifdef CONFIG_PPC_ISERIES
iommu_vio_init();
#endif
+ /* Initialize the vDSO */
+ vdso_init();
}
/*
@@ -752,18 +761,19 @@ void __init mem_init(void)
*/
void flush_dcache_page(struct page *page)
{
- if (cur_cpu_spec->cpu_features & CPU_FTR_COHERENT_ICACHE)
+ if (cpu_has_feature(CPU_FTR_COHERENT_ICACHE))
return;
/* avoid an atomic op if possible */
if (test_bit(PG_arch_1, &page->flags))
clear_bit(PG_arch_1, &page->flags);
}
+EXPORT_SYMBOL(flush_dcache_page);
void clear_user_page(void *page, unsigned long vaddr, struct page *pg)
{
clear_page(page);
- if (cur_cpu_spec->cpu_features & CPU_FTR_COHERENT_ICACHE)
+ if (cpu_has_feature(CPU_FTR_COHERENT_ICACHE))
return;
/*
* We shouldnt have to do this, but some versions of glibc
@@ -775,6 +785,7 @@ void clear_user_page(void *page, unsigned long vaddr, struct page *pg)
if (test_bit(PG_arch_1, &pg->flags))
clear_bit(PG_arch_1, &pg->flags);
}
+EXPORT_SYMBOL(clear_user_page);
void copy_user_page(void *vto, void *vfrom, unsigned long vaddr,
struct page *pg)
@@ -796,7 +807,7 @@ void copy_user_page(void *vto, void *vfrom, unsigned long vaddr,
return;
#endif
- if (cur_cpu_spec->cpu_features & CPU_FTR_COHERENT_ICACHE)
+ if (cpu_has_feature(CPU_FTR_COHERENT_ICACHE))
return;
/* avoid an atomic op if possible */
@@ -812,6 +823,7 @@ void flush_icache_user_range(struct vm_area_struct *vma, struct page *page,
maddr = (unsigned long)page_address(page) + (addr & ~PAGE_MASK);
flush_icache_range(maddr, maddr + len);
}
+EXPORT_SYMBOL(flush_icache_user_range);
/*
* This is called at the end of handling a user page fault, when the
@@ -832,8 +844,8 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long ea,
unsigned long flags;
/* handle i-cache coherency */
- if (!(cur_cpu_spec->cpu_features & CPU_FTR_COHERENT_ICACHE) &&
- !(cur_cpu_spec->cpu_features & CPU_FTR_NOEXECUTE)) {
+ if (!cpu_has_feature(CPU_FTR_COHERENT_ICACHE) &&
+ !cpu_has_feature(CPU_FTR_NOEXECUTE)) {
unsigned long pfn = pte_pfn(pte);
if (pfn_valid(pfn)) {
struct page *page = pfn_to_page(pfn);
@@ -900,3 +912,16 @@ void pgtable_cache_init(void)
if (!zero_cache)
panic("pgtable_cache_init(): could not create zero_cache!\n");
}
+
+pgprot_t phys_mem_access_prot(struct file *file, unsigned long addr,
+ unsigned long size, pgprot_t vma_prot)
+{
+ if (ppc_md.phys_mem_access_prot)
+ return ppc_md.phys_mem_access_prot(file, addr, size, vma_prot);
+
+ if (!page_is_ram(addr >> PAGE_SHIFT))
+ vma_prot = __pgprot(pgprot_val(vma_prot)
+ | _PAGE_GUARDED | _PAGE_NO_CACHE);
+ return vma_prot;
+}
+EXPORT_SYMBOL(phys_mem_access_prot);
diff --git a/arch/ppc64/mm/numa.c b/arch/ppc64/mm/numa.c
index 83d7ec3b7c104..ea862ec643d3a 100644
--- a/arch/ppc64/mm/numa.c
+++ b/arch/ppc64/mm/numa.c
@@ -40,7 +40,6 @@ int nr_cpus_in_node[MAX_NUMNODES] = { [0 ... (MAX_NUMNODES -1)] = 0};
struct pglist_data *node_data[MAX_NUMNODES];
bootmem_data_t __initdata plat_node_bdata[MAX_NUMNODES];
-static unsigned long node0_io_hole_size;
static int min_common_depth;
/*
@@ -49,7 +48,8 @@ static int min_common_depth;
*/
static struct {
unsigned long node_start_pfn;
- unsigned long node_spanned_pages;
+ unsigned long node_end_pfn;
+ unsigned long node_present_pages;
} init_node_data[MAX_NUMNODES] __initdata;
EXPORT_SYMBOL(node_data);
@@ -186,14 +186,36 @@ static int __init find_min_common_depth(void)
return depth;
}
-static unsigned long read_cell_ul(struct device_node *device, unsigned int **buf)
+static int __init get_mem_addr_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_addr_cells(memory);
+ return rc;
+}
+
+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 read_n_cells(int n, unsigned int **buf)
{
- int i;
unsigned long result = 0;
- i = prom_n_size_cells(device);
- /* bug on i>2 ?? */
- while (i--) {
+ while (n--) {
result = (result << 32) | **buf;
(*buf)++;
}
@@ -263,10 +285,40 @@ static int cpu_numa_callback(struct notifier_block *nfb,
return ret;
}
+/*
+ * Check and possibly modify a memory region to enforce the memory limit.
+ *
+ * Returns the size the region should have to enforce the memory limit.
+ * This will either be the original value of size, a truncated value,
+ * or zero. If the returned value of size is 0 the region should be
+ * discarded as it lies wholy above the memory limit.
+ */
+static unsigned long __init numa_enforce_memory_limit(unsigned long start, unsigned long size)
+{
+ /*
+ * We use lmb_end_of_DRAM() in here instead of memory_limit because
+ * we've already adjusted it for the limit and it takes care of
+ * having memory holes below the limit.
+ */
+ extern unsigned long memory_limit;
+
+ if (! memory_limit)
+ return size;
+
+ if (start + size <= lmb_end_of_DRAM())
+ return size;
+
+ if (start >= lmb_end_of_DRAM())
+ return 0;
+
+ return lmb_end_of_DRAM() - start;
+}
+
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 = 0;
long entries = lmb_end_of_DRAM() >> MEMORY_INCREMENT_SHIFT;
unsigned long i;
@@ -313,6 +365,8 @@ static int __init parse_numa_properties(void)
}
}
+ addr_cells = get_mem_addr_cells();
+ size_cells = get_mem_size_cells();
memory = NULL;
while ((memory = of_find_node_by_type(memory, "memory")) != NULL) {
unsigned long start;
@@ -329,8 +383,8 @@ static int __init parse_numa_properties(void)
ranges = memory->n_addrs;
new_range:
/* these are order-sensitive, and modify the buffer pointer */
- start = read_cell_ul(memory, &memcell_buf);
- size = read_cell_ul(memory, &memcell_buf);
+ start = read_n_cells(addr_cells, &memcell_buf);
+ size = read_n_cells(size_cells, &memcell_buf);
start = _ALIGN_DOWN(start, MEMORY_INCREMENT);
size = _ALIGN_UP(size, MEMORY_INCREMENT);
@@ -348,33 +402,38 @@ new_range:
if (max_domain < numa_domain)
max_domain = numa_domain;
- /*
- * For backwards compatibility, OF splits the first node
- * into two regions (the first being 0-4GB). Check for
- * this simple case and complain if there is a gap in
- * memory
+ if (! (size = numa_enforce_memory_limit(start, size))) {
+ if (--ranges)
+ goto new_range;
+ else
+ continue;
+ }
+
+ /*
+ * Initialize new node struct, or add to an existing one.
*/
- if (init_node_data[numa_domain].node_spanned_pages) {
- unsigned long shouldstart =
- init_node_data[numa_domain].node_start_pfn +
- init_node_data[numa_domain].node_spanned_pages;
- if (shouldstart != (start / PAGE_SIZE)) {
- /* Revert to non-numa for now */
- printk(KERN_ERR
- "WARNING: Unexpected node layout: "
- "region start %lx length %lx\n",
- start, size);
- printk(KERN_ERR "NUMA is disabled\n");
- goto err;
- }
- init_node_data[numa_domain].node_spanned_pages +=
+ if (init_node_data[numa_domain].node_end_pfn) {
+ if ((start / PAGE_SIZE) <
+ init_node_data[numa_domain].node_start_pfn)
+ init_node_data[numa_domain].node_start_pfn =
+ start / PAGE_SIZE;
+ if (((start / PAGE_SIZE) + (size / PAGE_SIZE)) >
+ init_node_data[numa_domain].node_end_pfn)
+ init_node_data[numa_domain].node_end_pfn =
+ (start / PAGE_SIZE) +
+ (size / PAGE_SIZE);
+
+ init_node_data[numa_domain].node_present_pages +=
size / PAGE_SIZE;
} else {
node_set_online(numa_domain);
init_node_data[numa_domain].node_start_pfn =
start / PAGE_SIZE;
- init_node_data[numa_domain].node_spanned_pages =
+ init_node_data[numa_domain].node_end_pfn =
+ init_node_data[numa_domain].node_start_pfn +
+ size / PAGE_SIZE;
+ init_node_data[numa_domain].node_present_pages =
size / PAGE_SIZE;
}
@@ -382,8 +441,7 @@ new_range:
numa_memory_lookup_table[i >> MEMORY_INCREMENT_SHIFT] =
numa_domain;
- ranges--;
- if (ranges)
+ if (--ranges)
goto new_range;
}
@@ -391,14 +449,6 @@ new_range:
node_set_online(i);
return 0;
-err:
- /* Something has gone wrong; revert any setup we've done */
- for_each_node(i) {
- node_set_offline(i);
- init_node_data[i].node_start_pfn = 0;
- init_node_data[i].node_spanned_pages = 0;
- }
- return -1;
}
static void __init setup_nonnuma(void)
@@ -426,12 +476,11 @@ static void __init setup_nonnuma(void)
node_set_online(0);
init_node_data[0].node_start_pfn = 0;
- init_node_data[0].node_spanned_pages = lmb_end_of_DRAM() / PAGE_SIZE;
+ init_node_data[0].node_end_pfn = lmb_end_of_DRAM() / PAGE_SIZE;
+ init_node_data[0].node_present_pages = total_ram / PAGE_SIZE;
for (i = 0 ; i < top_of_ram; i += MEMORY_INCREMENT)
numa_memory_lookup_table[i >> MEMORY_INCREMENT_SHIFT] = 0;
-
- node0_io_hole_size = top_of_ram - total_ram;
}
static void __init dump_numa_topology(void)
@@ -512,6 +561,8 @@ static unsigned long careful_allocation(int nid, unsigned long size,
void __init do_init_bootmem(void)
{
int nid;
+ int addr_cells, size_cells;
+ struct device_node *memory = NULL;
static struct notifier_block ppc64_numa_nb = {
.notifier_call = cpu_numa_callback,
.priority = 1 /* Must run before sched domains notifier. */
@@ -535,7 +586,7 @@ void __init do_init_bootmem(void)
unsigned long bootmap_pages;
start_paddr = init_node_data[nid].node_start_pfn * PAGE_SIZE;
- end_paddr = start_paddr + (init_node_data[nid].node_spanned_pages * PAGE_SIZE);
+ end_paddr = init_node_data[nid].node_end_pfn * PAGE_SIZE;
/* Allocate the node structure node local if possible */
NODE_DATA(nid) = (struct pglist_data *)careful_allocation(nid,
@@ -551,9 +602,9 @@ void __init do_init_bootmem(void)
NODE_DATA(nid)->node_start_pfn =
init_node_data[nid].node_start_pfn;
NODE_DATA(nid)->node_spanned_pages =
- init_node_data[nid].node_spanned_pages;
+ end_paddr - start_paddr;
- if (init_node_data[nid].node_spanned_pages == 0)
+ if (NODE_DATA(nid)->node_spanned_pages == 0)
continue;
dbg("start_paddr = %lx\n", start_paddr);
@@ -572,33 +623,53 @@ void __init do_init_bootmem(void)
start_paddr >> PAGE_SHIFT,
end_paddr >> PAGE_SHIFT);
- for (i = 0; i < lmb.memory.cnt; i++) {
- unsigned long physbase, size;
-
- physbase = lmb.memory.region[i].physbase;
- size = lmb.memory.region[i].size;
-
- if (physbase < end_paddr &&
- (physbase+size) > start_paddr) {
- /* overlaps */
- if (physbase < start_paddr) {
- size -= start_paddr - physbase;
- physbase = start_paddr;
- }
+ /*
+ * We need to do another scan of all memory sections to
+ * associate memory with the correct node.
+ */
+ addr_cells = get_mem_addr_cells();
+ size_cells = get_mem_size_cells();
+ memory = NULL;
+ while ((memory = of_find_node_by_type(memory, "memory")) != NULL) {
+ unsigned long mem_start, mem_size;
+ int numa_domain, ranges;
+ unsigned int *memcell_buf;
+ unsigned int len;
+
+ memcell_buf = (unsigned int *)get_property(memory, "reg", &len);
+ if (!memcell_buf || len <= 0)
+ continue;
+
+ ranges = memory->n_addrs; /* ranges in cell */
+new_range:
+ mem_start = read_n_cells(addr_cells, &memcell_buf);
+ mem_size = read_n_cells(size_cells, &memcell_buf);
+ numa_domain = numa_enabled ? of_node_numa_domain(memory) : 0;
- if (size > end_paddr - physbase)
- size = end_paddr - physbase;
+ if (numa_domain != nid)
+ continue;
- dbg("free_bootmem %lx %lx\n", physbase, size);
- free_bootmem_node(NODE_DATA(nid), physbase,
- size);
+ mem_size = numa_enforce_memory_limit(mem_start, mem_size);
+ if (mem_size) {
+ dbg("free_bootmem %lx %lx\n", mem_start, mem_size);
+ free_bootmem_node(NODE_DATA(nid), mem_start, mem_size);
}
+
+ if (--ranges) /* process all ranges in cell */
+ goto new_range;
}
+ /*
+ * Mark reserved regions on this node
+ */
for (i = 0; i < lmb.reserved.cnt; i++) {
unsigned long physbase = lmb.reserved.region[i].physbase;
unsigned long size = lmb.reserved.region[i].size;
+ if (pa_to_nid(physbase) != nid &&
+ pa_to_nid(physbase+size-1) != nid)
+ continue;
+
if (physbase < end_paddr &&
(physbase+size) > start_paddr) {
/* overlaps */
@@ -632,13 +703,12 @@ void __init paging_init(void)
unsigned long start_pfn;
unsigned long end_pfn;
- start_pfn = plat_node_bdata[nid].node_boot_start >> PAGE_SHIFT;
- end_pfn = plat_node_bdata[nid].node_low_pfn;
+ start_pfn = init_node_data[nid].node_start_pfn;
+ end_pfn = init_node_data[nid].node_end_pfn;
zones_size[ZONE_DMA] = end_pfn - start_pfn;
- zholes_size[ZONE_DMA] = 0;
- if (nid == 0)
- zholes_size[ZONE_DMA] = node0_io_hole_size >> PAGE_SHIFT;
+ zholes_size[ZONE_DMA] = zones_size[ZONE_DMA] -
+ init_node_data[nid].node_present_pages;
dbg("free_area_init node %d %lx %lx (hole: %lx)\n", nid,
zones_size[ZONE_DMA], start_pfn, zholes_size[ZONE_DMA]);
diff --git a/arch/ppc64/mm/slb.c b/arch/ppc64/mm/slb.c
index 12493cad3b68a..6a20773f695dd 100644
--- a/arch/ppc64/mm/slb.c
+++ b/arch/ppc64/mm/slb.c
@@ -51,7 +51,7 @@ static void slb_flush_and_rebolt(void)
WARN_ON(!irqs_disabled());
- if (cur_cpu_spec->cpu_features & CPU_FTR_16M_PAGE)
+ if (cpu_has_feature(CPU_FTR_16M_PAGE))
ksp_flags |= SLB_VSID_L;
ksp_esid_data = mk_esid_data(get_paca()->kstack, 2);
@@ -139,7 +139,7 @@ void slb_initialize(void)
unsigned long flags = SLB_VSID_KERNEL;
/* Invalidate the entire SLB (even slot 0) & all the ERATS */
- if (cur_cpu_spec->cpu_features & CPU_FTR_16M_PAGE)
+ if (cpu_has_feature(CPU_FTR_16M_PAGE))
flags |= SLB_VSID_L;
asm volatile("isync":::"memory");
diff --git a/arch/ppc64/mm/stab.c b/arch/ppc64/mm/stab.c
index 38155a2554dce..31491131d5e4a 100644
--- a/arch/ppc64/mm/stab.c
+++ b/arch/ppc64/mm/stab.c
@@ -227,7 +227,7 @@ void stab_initialize(unsigned long stab)
{
unsigned long vsid = get_kernel_vsid(KERNELBASE);
- if (cur_cpu_spec->cpu_features & CPU_FTR_SLB) {
+ if (cpu_has_feature(CPU_FTR_SLB)) {
slb_initialize();
} else {
asm volatile("isync; slbia; isync":::"memory");
diff --git a/arch/ppc64/mm/tlb.c b/arch/ppc64/mm/tlb.c
index aa2d76ca46f25..26f0172c4527b 100644
--- a/arch/ppc64/mm/tlb.c
+++ b/arch/ppc64/mm/tlb.c
@@ -74,20 +74,13 @@ void __pte_free_tlb(struct mmu_gather *tlb, struct page *ptepage)
* change the existing HPTE to read-only rather than removing it
* (if we remove it we should clear the _PTE_HPTEFLAGS bits).
*/
-void hpte_update(pte_t *ptep, unsigned long pte, int wrprot)
+void hpte_update(struct mm_struct *mm, unsigned long addr,
+ unsigned long pte, int wrprot)
{
- struct page *ptepage;
- struct mm_struct *mm;
- unsigned long addr;
int i;
unsigned long context = 0;
struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch);
- ptepage = virt_to_page(ptep);
- mm = (struct mm_struct *) ptepage->mapping;
- addr = ptepage->index +
- (((unsigned long)ptep & ~PAGE_MASK) * PTRS_PER_PTE);
-
if (REGION_ID(addr) == USER_REGION_ID)
context = mm->context.id;
i = batch->index;
diff --git a/arch/ppc64/oprofile/common.c b/arch/ppc64/oprofile/common.c
index a9a47caa55523..b28bfda23d944 100644
--- a/arch/ppc64/oprofile/common.c
+++ b/arch/ppc64/oprofile/common.c
@@ -15,6 +15,7 @@
#include <linux/errno.h>
#include <asm/ptrace.h>
#include <asm/system.h>
+#include <asm/pmc.h>
#include "op_impl.h"
@@ -22,9 +23,6 @@ extern struct op_ppc64_model op_model_rs64;
extern struct op_ppc64_model op_model_power4;
static struct op_ppc64_model *model;
-extern void (*perf_irq)(struct pt_regs *);
-static void (*save_perf_irq)(struct pt_regs *);
-
static struct op_counter_config ctr[OP_MAX_COUNTER];
static struct op_system_config sys;
@@ -35,11 +33,12 @@ static void op_handle_interrupt(struct pt_regs *regs)
static int op_ppc64_setup(void)
{
- /* Install our interrupt handler into the existing hook. */
- save_perf_irq = perf_irq;
- perf_irq = op_handle_interrupt;
+ int err;
- mb();
+ /* Grab the hardware */
+ err = reserve_pmc_hardware(op_handle_interrupt);
+ if (err)
+ return err;
/* Pre-compute the values to stuff in the hardware registers. */
model->reg_setup(ctr, &sys, model->num_counters);
@@ -52,10 +51,7 @@ static int op_ppc64_setup(void)
static void op_ppc64_shutdown(void)
{
- mb();
-
- /* Remove our interrupt handler. We may be removing this module. */
- perf_irq = save_perf_irq;
+ release_pmc_hardware();
}
static void op_ppc64_cpu_start(void *dummy)
diff --git a/arch/ppc64/oprofile/op_model_power4.c b/arch/ppc64/oprofile/op_model_power4.c
index b1ca798f4c290..3d103d66870dd 100644
--- a/arch/ppc64/oprofile/op_model_power4.c
+++ b/arch/ppc64/oprofile/op_model_power4.c
@@ -54,7 +54,7 @@ static void power4_reg_setup(struct op_counter_config *ctr,
*
* It has been verified to work on POWER5 so we enable it there.
*/
- if (cur_cpu_spec->cpu_features & CPU_FTR_MMCRA_SIHV)
+ if (cpu_has_feature(CPU_FTR_MMCRA_SIHV))
mmcra_has_sihv = 1;
/*
@@ -224,7 +224,7 @@ static unsigned long get_pc(struct pt_regs *regs)
if (mmcra & MMCRA_SIPR)
return pc;
-#ifdef CONFIG_PPC_PSERIES
+#ifdef CONFIG_PPC_RTAS
/* Were we in RTAS? */
if (pc >= rtas.base && pc < (rtas.base + rtas.size))
/* function descriptor madness */
diff --git a/arch/ppc64/oprofile/op_model_rs64.c b/arch/ppc64/oprofile/op_model_rs64.c
index b3cddb7e03d00..bcec506c266a8 100644
--- a/arch/ppc64/oprofile/op_model_rs64.c
+++ b/arch/ppc64/oprofile/op_model_rs64.c
@@ -114,7 +114,7 @@ static void rs64_cpu_setup(void *unused)
/* reset MMCR1, MMCRA */
mtspr(SPRN_MMCR1, 0);
- if (cur_cpu_spec->cpu_features & CPU_FTR_MMCRA)
+ if (cpu_has_feature(CPU_FTR_MMCRA))
mtspr(SPRN_MMCRA, 0);
mmcr0 |= MMCR0_FCM1|MMCR0_PMXE|MMCR0_FCECE;
diff --git a/arch/ppc64/xmon/xmon.c b/arch/ppc64/xmon/xmon.c
index b456e57636457..3c0ccb2623aeb 100644
--- a/arch/ppc64/xmon/xmon.c
+++ b/arch/ppc64/xmon/xmon.c
@@ -32,6 +32,7 @@
#include <asm/rtas.h>
#include <asm/sstep.h>
#include <asm/bug.h>
+#include <asm/hvcall.h>
#include "nonstdio.h"
#include "privinst.h"
@@ -725,7 +726,7 @@ static void insert_cpu_bpts(void)
{
if (dabr.enabled)
set_controlled_dabr(dabr.address | (dabr.enabled & 7));
- if (iabr && (cur_cpu_spec->cpu_features & CPU_FTR_IABR))
+ if (iabr && cpu_has_feature(CPU_FTR_IABR))
set_iabr(iabr->address
| (iabr->enabled & (BP_IABR|BP_IABR_TE)));
}
@@ -753,7 +754,7 @@ static void remove_bpts(void)
static void remove_cpu_bpts(void)
{
set_controlled_dabr(0);
- if ((cur_cpu_spec->cpu_features & CPU_FTR_IABR))
+ if (cpu_has_feature(CPU_FTR_IABR))
set_iabr(0);
}
@@ -1100,7 +1101,7 @@ bpt_cmds(void)
break;
case 'i': /* bi - hardware instr breakpoint */
- if (!(cur_cpu_spec->cpu_features & CPU_FTR_IABR)) {
+ if (!cpu_has_feature(CPU_FTR_IABR)) {
printf("Hardware instruction breakpoint "
"not supported on this cpu\n");
break;
@@ -2498,7 +2499,7 @@ void xmon_init(void)
void dump_segments(void)
{
- if (cur_cpu_spec->cpu_features & CPU_FTR_SLB)
+ if (cpu_has_feature(CPU_FTR_SLB))
dump_slb();
else
dump_stab();
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 8394c4e510733..ab79af84699ad 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -84,12 +84,12 @@ config NR_CPUS
approximately sixteen kilobytes to the kernel image.
config HOTPLUG_CPU
- bool "Support for hot-pluggable CPUs (EXPERIMENTAL)"
- depends on SMP && EXPERIMENTAL
+ bool "Support for hot-pluggable CPUs"
+ depends on SMP
select HOTPLUG
default n
help
- Say Y here to experiment with turning CPUs off and on. CPUs
+ Say Y here to be able to turn CPUs off and on. CPUs
can be controlled through /sys/devices/system/cpu/cpu#.
Say N if you want to disable CPU hotplug.
diff --git a/arch/s390/Makefile b/arch/s390/Makefile
index 344d3020543d5..3cd8dd25c9d73 100644
--- a/arch/s390/Makefile
+++ b/arch/s390/Makefile
@@ -66,7 +66,7 @@ cflags-$(CONFIG_WARN_STACK) += -mwarn-dynamicstack
cflags-$(CONFIG_WARN_STACK) += -mwarn-framesize=$(CONFIG_WARN_STACK_SIZE)
endif
-CFLAGS += -mbackchain $(cflags-y)
+CFLAGS += -mbackchain -msoft-float $(cflags-y)
CFLAGS += $(call cc-option,-finline-limit=10000)
CFLAGS += -pipe -fno-strength-reduce -Wno-sign-compare
AFLAGS += $(aflags-y)
diff --git a/arch/s390/defconfig b/arch/s390/defconfig
index b200a5173abf2..1358b42017014 100644
--- a/arch/s390/defconfig
+++ b/arch/s390/defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc2
-# Mon Jan 31 16:27:12 2005
+# Linux kernel version: 2.6.11
+# Wed Mar 2 16:57:55 2005
#
CONFIG_MMU=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
@@ -54,6 +54,7 @@ CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
#
# Base setup
@@ -67,7 +68,7 @@ CONFIG_KMOD=y
CONFIG_ARCH_S390_31=y
CONFIG_SMP=y
CONFIG_NR_CPUS=32
-# CONFIG_HOTPLUG_CPU is not set
+CONFIG_HOTPLUG_CPU=y
CONFIG_MATHEMU=y
#
@@ -419,6 +420,10 @@ CONFIG_JBD=y
CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
# CONFIG_XFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
diff --git a/arch/s390/kernel/compat_ioctl.c b/arch/s390/kernel/compat_ioctl.c
index 7c7ca191f7f4a..96571ff7115da 100644
--- a/arch/s390/kernel/compat_ioctl.c
+++ b/arch/s390/kernel/compat_ioctl.c
@@ -65,9 +65,6 @@ COMPATIBLE_IOCTL(BIODASDSATTR)
COMPATIBLE_IOCTL(TAPE390_DISPLAY)
#endif
-/* This one should be architecture independent */
-COMPATIBLE_IOCTL(TCSBRKP)
-
/* s390 doesn't need handlers here */
COMPATIBLE_IOCTL(TIOCGSERIAL)
COMPATIBLE_IOCTL(TIOCSSERIAL)
diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c
index 1bf2951d9c115..614056222875f 100644
--- a/arch/s390/kernel/compat_linux.c
+++ b/arch/s390/kernel/compat_linux.c
@@ -1019,7 +1019,7 @@ extern asmlinkage long
sys_timer_create(clockid_t, struct sigevent *, timer_t *);
asmlinkage long
-sys32_timer_create(clockid_t which_clock, struct sigevent32 *se32,
+sys32_timer_create(clockid_t which_clock, struct compat_sigevent *se32,
timer_t *timer_id)
{
struct sigevent se;
@@ -1030,16 +1030,7 @@ sys32_timer_create(clockid_t which_clock, struct sigevent32 *se32,
if (se32 == NULL)
return sys_timer_create(which_clock, NULL, timer_id);
- /* XXX: converting se32 to se is filthy because of the
- * two union members. For now it is ok, because the pointers
- * are not touched in kernel.
- */
- memset(&se, 0, sizeof(se));
- if (get_user(se.sigev_value.sival_int, &se32->sigev_value.sival_int) ||
- get_user(se.sigev_signo, &se32->sigev_signo) ||
- get_user(se.sigev_notify, &se32->sigev_notify) ||
- copy_from_user(&se._sigev_un._pad, &se32->_sigev_un._pad,
- sizeof(se._sigev_un._pad)))
+ if (get_compat_sigevent(&se, se32))
return -EFAULT;
old_fs = get_fs();
diff --git a/arch/s390/kernel/compat_linux.h b/arch/s390/kernel/compat_linux.h
index e95b0761d065f..bf33dcfec7dbd 100644
--- a/arch/s390/kernel/compat_linux.h
+++ b/arch/s390/kernel/compat_linux.h
@@ -29,11 +29,6 @@ struct old_sigaction32 {
__u32 sa_restorer; /* Another 32 bit pointer */
};
-typedef union sigval32 {
- int sival_int;
- __u32 sival_ptr;
-} sigval_t32;
-
typedef struct compat_siginfo {
int si_signo;
int si_errno;
@@ -52,7 +47,7 @@ typedef struct compat_siginfo {
struct {
timer_t _tid; /* timer id */
int _overrun; /* overrun count */
- sigval_t _sigval; /* same as below */
+ compat_sigval_t _sigval; /* same as below */
int _sys_private; /* not to be passed to user */
} _timer;
@@ -60,7 +55,7 @@ typedef struct compat_siginfo {
struct {
pid_t _pid; /* sender's pid */
uid_t _uid; /* sender's uid */
- sigval_t32 _sigval;
+ compat_sigval_t _sigval;
} _rt;
/* SIGCHLD */
@@ -199,22 +194,4 @@ struct ucontext32 {
compat_sigset_t uc_sigmask; /* mask last for extensibility */
};
-#define SIGEV_PAD_SIZE32 ((SIGEV_MAX_SIZE/sizeof(int)) - 3)
-struct sigevent32 {
- union {
- int sival_int;
- u32 sival_ptr;
- } sigev_value;
- int sigev_signo;
- int sigev_notify;
- union {
- int _pad[SIGEV_PAD_SIZE32];
- int _tid;
- struct {
- u32 *_function;
- u32 *_attribute;
- } _sigev_thread;
- } _sigev_un;
-};
-
#endif /* _ASM_S390X_S390_H */
diff --git a/arch/s390/kernel/compat_signal.c b/arch/s390/kernel/compat_signal.c
index b728e027bf6f0..d05d65ac96940 100644
--- a/arch/s390/kernel/compat_signal.c
+++ b/arch/s390/kernel/compat_signal.c
@@ -231,7 +231,7 @@ sys32_sigaction(int sig, const struct old_sigaction32 __user *act,
if (act) {
compat_old_sigset_t mask;
- if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
+ if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
__get_user(sa_handler, &act->sa_handler) ||
__get_user(sa_restorer, &act->sa_restorer))
return -EFAULT;
@@ -247,7 +247,7 @@ sys32_sigaction(int sig, const struct old_sigaction32 __user *act,
if (!ret && oact) {
sa_handler = (unsigned long) old_ka.sa.sa_handler;
sa_restorer = (unsigned long) old_ka.sa.sa_restorer;
- if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
+ if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
__put_user(sa_handler, &oact->sa_handler) ||
__put_user(sa_restorer, &oact->sa_restorer))
return -EFAULT;
@@ -416,7 +416,7 @@ asmlinkage long sys32_sigreturn(struct pt_regs *regs)
sigframe32 __user *frame = (sigframe32 __user *)regs->gprs[15];
sigset_t set;
- if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
+ if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
goto badframe;
if (__copy_from_user(&set.sig, &frame->sc.oldmask, _SIGMASK_COPY_SIZE32))
goto badframe;
@@ -446,7 +446,7 @@ asmlinkage long sys32_rt_sigreturn(struct pt_regs *regs)
int err;
mm_segment_t old_fs = get_fs();
- if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
+ if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
goto badframe;
if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
goto badframe;
diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S
index e5821311848c3..7a607b1d03808 100644
--- a/arch/s390/kernel/compat_wrapper.S
+++ b/arch/s390/kernel/compat_wrapper.S
@@ -1406,3 +1406,38 @@ compat_sys_mq_getsetattr_wrapper:
llgtr %r3,%r3 # struct compat_mq_attr *
llgtr %r4,%r4 # struct compat_mq_attr *
jg compat_sys_mq_getsetattr
+
+ .globl compat_sys_add_key_wrapper
+compat_sys_add_key_wrapper:
+ llgtr %r2,%r2 # const char *
+ llgtr %r3,%r3 # const char *
+ llgtr %r4,%r4 # const void *
+ llgfr %r5,%r5 # size_t
+ llgfr %r6,%r6 # (key_serial_t) u32
+ jg sys_add_key
+
+ .globl compat_sys_request_key_wrapper
+compat_sys_request_key_wrapper:
+ llgtr %r2,%r2 # const char *
+ llgtr %r3,%r3 # const char *
+ llgtr %r4,%r4 # const void *
+ llgfr %r5,%r5 # (key_serial_t) u32
+ jg sys_request_key
+
+ .globl sys32_remap_file_pages_wrapper
+sys32_remap_file_pages_wrapper:
+ llgfr %r2,%r2 # unsigned long
+ llgfr %r3,%r3 # unsigned long
+ llgfr %r4,%r4 # unsigned long
+ llgfr %r5,%r5 # unsigned long
+ llgfr %r6,%r6 # unsigned long
+ jg sys_remap_file_pages
+
+ .globl compat_sys_waitid_wrapper
+compat_sys_waitid_wrapper:
+ lgfr %r2,%r2 # int
+ lgfr %r3,%r3 # pid_t
+ llgtr %r4,%r4 # siginfo_emu31_t *
+ lgfr %r5,%r5 # int
+ llgtr %r6,%r6 # struct rusage_emu31 *
+ jg compat_sys_waitid
diff --git a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c
index 7cf71af8ad9ee..91f8ce5543d3b 100644
--- a/arch/s390/kernel/debug.c
+++ b/arch/s390/kernel/debug.c
@@ -931,11 +931,15 @@ int debug_register_view(debug_info_t * id, struct debug_view *view)
int rc = 0;
int i;
unsigned long flags;
- mode_t mode = S_IFREG | S_IRUSR | S_IWUSR;
+ mode_t mode = S_IFREG;
struct proc_dir_entry *pde;
if (!id)
goto out;
+ if (view->prolog_proc || view->format_proc || view->header_proc)
+ mode |= S_IRUSR;
+ if (view->input_proc)
+ mode |= S_IWUSR;
pde = create_proc_entry(view->name, mode, id->proc_root_entry);
if (!pde){
printk(KERN_WARNING "debug: create_proc_entry() failed! Cannot register view %s/%s\n", id->name,view->name);
@@ -958,10 +962,6 @@ int debug_register_view(debug_info_t * id, struct debug_view *view)
}
else {
id->views[i] = view;
- if (view->prolog_proc || view->format_proc || view->header_proc)
- mode |= S_IRUSR;
- if (view->input_proc)
- mode |= S_IWUSR;
pde->proc_fops = &debug_file_ops;
id->proc_entries[i] = pde;
}
diff --git a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c
index 59bfceabaebeb..480b6a5fef3ab 100644
--- a/arch/s390/kernel/irq.c
+++ b/arch/s390/kernel/irq.c
@@ -25,9 +25,8 @@ int show_interrupts(struct seq_file *p, void *v)
if (i == 0) {
seq_puts(p, " ");
- for (j=0; j<NR_CPUS; j++)
- if (cpu_online(j))
- seq_printf(p, "CPU%d ",j);
+ for_each_online_cpu(j)
+ seq_printf(p, "CPU%d ",j);
seq_putc(p, '\n');
}
@@ -36,9 +35,8 @@ int show_interrupts(struct seq_file *p, void *v)
#ifndef CONFIG_SMP
seq_printf(p, "%10u ", kstat_irqs(i));
#else
- for (j = 0; j < NR_CPUS; j++)
- if (cpu_online(j))
- seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
+ for_each_online_cpu(j)
+ seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
#endif
seq_putc(p, '\n');
diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c
index 5755530a50794..647233c02fc80 100644
--- a/arch/s390/kernel/ptrace.c
+++ b/arch/s390/kernel/ptrace.c
@@ -31,6 +31,7 @@
#include <linux/ptrace.h>
#include <linux/user.h>
#include <linux/security.h>
+#include <linux/audit.h>
#include <asm/segment.h>
#include <asm/page.h>
diff --git a/arch/s390/kernel/s390_ext.c b/arch/s390/kernel/s390_ext.c
index b61490bd14913..3bdd38ec71da4 100644
--- a/arch/s390/kernel/s390_ext.c
+++ b/arch/s390/kernel/s390_ext.c
@@ -114,6 +114,10 @@ void do_extint(struct pt_regs *regs, unsigned short code)
irq_enter();
asm volatile ("mc 0,0");
if (S390_lowcore.int_clock >= S390_lowcore.jiffy_timer)
+ /**
+ * Make sure that the i/o interrupt did not "overtake"
+ * the last HZ timer interrupt.
+ */
account_ticks(regs);
kstat_cpu(smp_processor_id()).irqs[EXTERNAL_INTERRUPT]++;
index = code & 0xff;
diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c
index 179db7e039d86..610c1d03e9757 100644
--- a/arch/s390/kernel/signal.c
+++ b/arch/s390/kernel/signal.c
@@ -116,7 +116,7 @@ sys_sigaction(int sig, const struct old_sigaction __user *act,
if (act) {
old_sigset_t mask;
- if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
+ if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
__get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
__get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
return -EFAULT;
@@ -128,7 +128,7 @@ sys_sigaction(int sig, const struct old_sigaction __user *act,
ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
if (!ret && oact) {
- if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
+ if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
__put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
__put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
return -EFAULT;
@@ -214,7 +214,7 @@ asmlinkage long sys_sigreturn(struct pt_regs *regs)
sigframe __user *frame = (sigframe __user *)regs->gprs[15];
sigset_t set;
- if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
+ if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
goto badframe;
if (__copy_from_user(&set.sig, &frame->sc.oldmask, _SIGMASK_COPY_SIZE))
goto badframe;
@@ -240,7 +240,7 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs)
rt_sigframe __user *frame = (rt_sigframe __user *)regs->gprs[15];
sigset_t set;
- if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
+ if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
goto badframe;
if (__copy_from_user(&set.sig, &frame->uc.uc_sigmask, sizeof(set)))
goto badframe;
@@ -282,7 +282,7 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
/* This is the X/Open sanctioned signal stack switching. */
if (ka->sa.sa_flags & SA_ONSTACK) {
- if (! on_sig_stack(sp))
+ if (! sas_ss_flags(sp))
sp = current->sas_ss_sp + current->sas_ss_size;
}
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index 24550d2cea8a3..fdfcf0488b49b 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -50,12 +50,9 @@ extern volatile int __cpu_logical_map[];
*/
struct _lowcore *lowcore_ptr[NR_CPUS];
-cycles_t cacheflush_time=0;
-int smp_threads_ready=0; /* Set when the idlers are all forked. */
cpumask_t cpu_online_map;
cpumask_t cpu_possible_map;
-unsigned long cache_decay_ticks = 0;
static struct task_struct *current_set[NR_CPUS];
@@ -212,29 +209,29 @@ EXPORT_SYMBOL(smp_call_function_on);
static inline void do_send_stop(void)
{
- int i, rc;
+ int cpu, rc;
/* stop all processors */
- for (i = 0; i < NR_CPUS; i++) {
- if (!cpu_online(i) || smp_processor_id() == i)
+ for_each_online_cpu(cpu) {
+ if (cpu == smp_processor_id())
continue;
do {
- rc = signal_processor(i, sigp_stop);
+ rc = signal_processor(cpu, sigp_stop);
} while (rc == sigp_busy);
}
}
static inline void do_store_status(void)
{
- int i, rc;
+ int cpu, rc;
/* store status of all processors in their lowcores (real 0) */
- for (i = 0; i < NR_CPUS; i++) {
- if (!cpu_online(i) || smp_processor_id() == i)
+ for_each_online_cpu(cpu) {
+ if (cpu == smp_processor_id())
continue;
do {
rc = signal_processor_p(
- (__u32)(unsigned long) lowcore_ptr[i], i,
+ (__u32)(unsigned long) lowcore_ptr[cpu], cpu,
sigp_store_status_at_address);
} while(rc == sigp_busy);
}
@@ -259,37 +256,41 @@ void smp_send_stop(void)
/*
* Reboot, halt and power_off routines for SMP.
*/
-static cpumask_t cpu_restart_map;
static void do_machine_restart(void * __unused)
{
+ int cpu;
static atomic_t cpuid = ATOMIC_INIT(-1);
- cpu_clear(smp_processor_id(), cpu_restart_map);
- if (atomic_compare_and_swap(-1, smp_processor_id(), &cpuid) == 0) {
- /* Wait for all other cpus to enter do_machine_restart. */
- while (!cpus_empty(cpu_restart_map))
+ if (atomic_compare_and_swap(-1, smp_processor_id(), &cpuid))
+ signal_processor(smp_processor_id(), sigp_stop);
+
+ /* Wait for all other cpus to enter stopped state */
+ for_each_online_cpu(cpu) {
+ if (cpu == smp_processor_id())
+ continue;
+ while(!smp_cpu_not_running(cpu))
cpu_relax();
- /* Store status of other cpus. */
- do_store_status();
- /*
- * Finally call reipl. Because we waited for all other
- * cpus to enter this function we know that they do
- * not hold any s390irq-locks (the cpus have been
- * interrupted by an external interrupt and s390irq
- * locks are always held disabled).
- */
- if (MACHINE_IS_VM)
- cpcmd ("IPL", NULL, 0);
- else
- reipl (0x10000 | S390_lowcore.ipl_device);
}
- signal_processor(smp_processor_id(), sigp_stop);
+
+ /* Store status of other cpus. */
+ do_store_status();
+
+ /*
+ * Finally call reipl. Because we waited for all other
+ * cpus to enter this function we know that they do
+ * not hold any s390irq-locks (the cpus have been
+ * interrupted by an external interrupt and s390irq
+ * locks are always held disabled).
+ */
+ if (MACHINE_IS_VM)
+ cpcmd ("IPL", NULL, 0);
+ else
+ reipl (0x10000 | S390_lowcore.ipl_device);
}
void machine_restart_smp(char * __unused)
{
- cpu_restart_map = cpu_online_map;
on_each_cpu(do_machine_restart, NULL, 0, 0);
}
@@ -384,16 +385,16 @@ static void smp_ext_bitcall(int cpu, ec_bit_sig sig)
*/
static void smp_ext_bitcall_others(ec_bit_sig sig)
{
- int i;
+ int cpu;
- for (i = 0; i < NR_CPUS; i++) {
- if (!cpu_online(i) || smp_processor_id() == i)
+ for_each_online_cpu(cpu) {
+ if (cpu == smp_processor_id())
continue;
/*
* Set signaling bit in lowcore of target cpu and kick it
*/
- set_bit(sig, (unsigned long *) &lowcore_ptr[i]->ext_call_fast);
- while (signal_processor(i, sigp_external_call) == sigp_busy)
+ set_bit(sig, (unsigned long *) &lowcore_ptr[cpu]->ext_call_fast);
+ while (signal_processor(cpu, sigp_external_call) == sigp_busy)
udelay(10);
}
}
@@ -497,7 +498,6 @@ __init smp_check_cpus(unsigned int max_cpus)
*/
boot_cpu_addr = S390_lowcore.cpu_data.cpu_addr;
- __cpu_logical_map[0] = boot_cpu_addr;
current_thread_info()->cpu = 0;
num_cpus = 1;
for (cpu = 0; cpu <= 65535 && num_cpus < max_cpus; cpu++) {
@@ -725,7 +725,7 @@ void
__cpu_die(unsigned int cpu)
{
/* Wait until target cpu is down */
- while (!cpu_stopped(cpu))
+ while (!smp_cpu_not_running(cpu))
cpu_relax();
printk("Processor %d spun down\n", cpu);
}
@@ -790,6 +790,7 @@ void __devinit smp_prepare_boot_cpu(void)
BUG_ON(smp_processor_id() != 0);
cpu_set(0, cpu_online_map);
+ cpu_set(0, cpu_present_map);
cpu_set(0, cpu_possible_map);
S390_lowcore.percpu_offset = __per_cpu_offset[0];
current_set[0] = current;
diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S
index ef4866fb568c3..515938628f82c 100644
--- a/arch/s390/kernel/syscalls.S
+++ b/arch/s390/kernel/syscalls.S
@@ -275,7 +275,7 @@ NI_SYSCALL /* reserved for vserver */
SYSCALL(s390_fadvise64_64,sys_ni_syscall,sys32_fadvise64_64_wrapper)
SYSCALL(sys_statfs64,sys_statfs64,compat_sys_statfs64_wrapper)
SYSCALL(sys_fstatfs64,sys_fstatfs64,compat_sys_fstatfs64_wrapper)
-NI_SYSCALL /* 267 new sys_remap_file_pages */
+SYSCALL(sys_remap_file_pages,sys_remap_file_pages,sys32_remap_file_pages_wrapper)
NI_SYSCALL /* 268 sys_mbind */
NI_SYSCALL /* 269 sys_get_mempolicy */
NI_SYSCALL /* 270 sys_set_mempolicy */
@@ -286,3 +286,7 @@ SYSCALL(sys_mq_timedreceive,sys_mq_timedreceive,compat_sys_mq_timedreceive_wrapp
SYSCALL(sys_mq_notify,sys_mq_notify,compat_sys_mq_notify_wrapper) /* 275 */
SYSCALL(sys_mq_getsetattr,sys_mq_getsetattr,compat_sys_mq_getsetattr_wrapper)
NI_SYSCALL /* reserved for kexec */
+SYSCALL(sys_add_key,sys_add_key,compat_sys_add_key_wrapper)
+SYSCALL(sys_request_key,sys_request_key,compat_sys_request_key_wrapper)
+SYSCALL(sys_keyctl,sys_keyctl,compat_sys_keyctl) /* 280 */
+SYSCALL(sys_waitid,sys_waitid,compat_sys_waitid_wrapper)
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
index 995e2cd38e773..061e81138dc21 100644
--- a/arch/s390/kernel/time.c
+++ b/arch/s390/kernel/time.c
@@ -168,8 +168,17 @@ void account_ticks(struct pt_regs *regs)
__u32 ticks, xticks;
/* Calculate how many ticks have passed. */
- if (S390_lowcore.int_clock < S390_lowcore.jiffy_timer)
+ if (S390_lowcore.int_clock < S390_lowcore.jiffy_timer) {
+ /*
+ * We have to program the clock comparator even if
+ * no tick has passed. That happens if e.g. an i/o
+ * interrupt wakes up an idle processor that has
+ * switched off its hz timer.
+ */
+ tmp = S390_lowcore.jiffy_timer + CPU_DEVIATION;
+ asm volatile ("SCKC %0" : : "m" (tmp));
return;
+ }
tmp = S390_lowcore.int_clock - S390_lowcore.jiffy_timer;
if (tmp >= 2*CLK_TICKS_PER_JIFFY) { /* more than two ticks ? */
ticks = __div(tmp, CLK_TICKS_PER_JIFFY) + 1;
diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c
index 63cdfec3ba99b..bb6cf02418a28 100644
--- a/arch/s390/kernel/vtime.c
+++ b/arch/s390/kernel/vtime.c
@@ -19,6 +19,7 @@
#include <linux/notifier.h>
#include <linux/kernel_stat.h>
#include <linux/rcupdate.h>
+#include <linux/posix-timers.h>
#include <asm/s390_ext.h>
#include <asm/timer.h>
@@ -69,6 +70,7 @@ void account_user_vtime(struct task_struct *tsk)
if (rcu_pending(smp_processor_id()))
rcu_check_callbacks(smp_processor_id(), rcu_user_flag);
scheduler_tick();
+ run_posix_cpu_timers(tsk);
}
/*
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
index d6bd3d4298601..80306bc8c799b 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -62,8 +62,8 @@ void bust_spinlocks(int yes)
oops_in_progress = 1;
} else {
int loglevel_save = console_loglevel;
- oops_in_progress = 0;
console_unblank();
+ oops_in_progress = 0;
/*
* OK, the message is on the console. Now we call printk()
* without oops_in_progress set so that printk will give klogd
@@ -87,6 +87,7 @@ static int __check_access_register(struct pt_regs *regs, int error_code)
if (areg == 0)
/* Access via access register 0 -> kernel address */
return 0;
+ save_access_regs(current->thread.acrs);
if (regs && areg < NUM_ACRS && current->thread.acrs[areg] <= 1)
/*
* access register contains 0 -> kernel address,
@@ -115,11 +116,11 @@ static inline int check_user_space(struct pt_regs *regs, int error_code)
* 3: Home Segment Table Descriptor
*/
int descriptor = S390_lowcore.trans_exc_code & 3;
- if (descriptor == 1) {
- save_access_regs(current->thread.acrs);
+ if (unlikely(descriptor == 1))
return __check_access_register(regs, error_code);
- }
- return descriptor >> 1;
+ if (descriptor == 2)
+ return current->thread.mm_segment.ar4;
+ return descriptor != 0;
}
/*
diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c
index 7240782d78239..8e723bc7f795c 100644
--- a/arch/s390/mm/init.c
+++ b/arch/s390/mm/init.c
@@ -145,7 +145,7 @@ void __init paging_init(void)
for (tmp = 0 ; tmp < PTRS_PER_PTE ; tmp++,pg_table++) {
pte = pfn_pte(pfn, PAGE_KERNEL);
if (pfn >= max_low_pfn)
- pte_clear(&pte);
+ pte_clear(&init_mm, 0, &pte);
set_pte(pg_table, pte);
pfn++;
}
@@ -229,7 +229,7 @@ void __init paging_init(void)
for (k = 0 ; k < PTRS_PER_PTE ; k++,pt_dir++) {
pte = pfn_pte(pfn, PAGE_KERNEL);
if (pfn >= max_low_pfn) {
- pte_clear(&pte);
+ pte_clear(&init_mm, 0, &pte);
continue;
}
set_pte(pt_dir, pte);
diff --git a/arch/s390/oprofile/Kconfig b/arch/s390/oprofile/Kconfig
index 34d6955fd7fd0..208220a5f23fc 100644
--- a/arch/s390/oprofile/Kconfig
+++ b/arch/s390/oprofile/Kconfig
@@ -1,16 +1,15 @@
menu "Profiling support"
- depends on EXPERIMENTAL
config PROFILING
- bool "Profiling support (EXPERIMENTAL)"
+ bool "Profiling support"
help
Say Y here to enable profiling support mechanisms used by
profilers such as readprofile or OProfile.
config OPROFILE
- tristate "OProfile system profiling (EXPERIMENTAL)"
+ tristate "OProfile system profiling"
depends on PROFILING
help
OProfile is a profiling system capable of profiling the
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index ec195d2b22e02..5effcd4d1cc19 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -25,6 +25,14 @@ config RWSEM_GENERIC_SPINLOCK
config RWSEM_XCHGADD_ALGORITHM
bool
+config GENERIC_HARDIRQS
+ bool
+ default y
+
+config GENERIC_IRQ_PROBE
+ bool
+ default y
+
config GENERIC_CALIBRATE_DELAY
bool
default y
@@ -755,7 +763,6 @@ source "drivers/pci/hotplug/Kconfig"
endmenu
-
menu "Executable file formats"
source "fs/Kconfig.binfmt"
diff --git a/arch/sh/Makefile b/arch/sh/Makefile
index 0c520643a5838..b5635635b5ee7 100644
--- a/arch/sh/Makefile
+++ b/arch/sh/Makefile
@@ -31,6 +31,13 @@ cflags-$(CONFIG_MORE_COMPILE_OPTIONS) += \
OBJCOPYFLAGS := -O binary -R .note -R .comment -R .stab -R .stabstr -S
#
+# arch/sh/defconfig doesn't reflect any real hardware, and as such should
+# never be used by anyone. Use a board-specific defconfig that has a
+# reasonable chance of being current instead.
+#
+KBUILD_DEFCONFIG := rts7751r2d_defconfig
+
+#
# Choosing incompatible machines durings configuration will result in
# error messages during linking.
#
diff --git a/arch/sh/boards/hp6xx/hp620/Makefile b/arch/sh/boards/hp6xx/hp620/Makefile
index b12378a125763..20691dbce3474 100644
--- a/arch/sh/boards/hp6xx/hp620/Makefile
+++ b/arch/sh/boards/hp6xx/hp620/Makefile
@@ -2,5 +2,5 @@
# Makefile for the HP620 specific parts of the kernel
#
-obj-y := mach.o
+obj-y := mach.o setup.o
diff --git a/arch/sh/boards/hp6xx/hp620/setup.c b/arch/sh/boards/hp6xx/hp620/setup.c
new file mode 100644
index 0000000000000..045fc5da7274e
--- /dev/null
+++ b/arch/sh/boards/hp6xx/hp620/setup.c
@@ -0,0 +1,45 @@
+/*
+ * 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/se/7300/io.c b/arch/sh/boards/se/7300/io.c
index 4e8939197e201..3c89def464803 100644
--- a/arch/sh/boards/se/7300/io.c
+++ b/arch/sh/boards/se/7300/io.c
@@ -1,12 +1,16 @@
/*
- * linux/arch/sh/boards/se/7300/io.c
+ * arch/sh/boards/se/7300/io.c
*
* Copyright (C) 2003 YOSHII Takashi <yoshii-takashi@hitachi-ul.co.jp>
+ * Based on arch/sh/kernel/io_shmse.c
+ *
+ * I/O routine for SH-Mobile3 73180 SolutionEngine.
+ *
*/
#include <linux/config.h>
#include <linux/kernel.h>
-#include <asm/se7300/se7300.h>
+#include <asm/mach/se7300.h>
#include <asm/io.h>
#define badio(fn, a) panic("bad i/o operation %s for %08lx.", #fn, a)
diff --git a/arch/sh/boards/sh03/rtc.c b/arch/sh/boards/sh03/rtc.c
index e5881b1877e3d..cbeca7037ba56 100644
--- a/arch/sh/boards/sh03/rtc.c
+++ b/arch/sh/boards/sh03/rtc.c
@@ -115,8 +115,6 @@ static int set_rtc_mmss(unsigned long nowtime)
real_minutes %= 60;
if (abs(real_minutes - cmos_minutes) < 30) {
- BIN_TO_BCD(real_seconds);
- BIN_TO_BCD(real_minutes);
ctrl_outb(real_seconds % 10, RTC_SEC1);
ctrl_outb(real_seconds / 10, RTC_SEC10);
ctrl_outb(real_minutes % 10, RTC_MIN1);
diff --git a/arch/sh/boards/snapgear/setup.c b/arch/sh/boards/snapgear/setup.c
index dc6607e5d62ed..08fc98342a0b3 100644
--- a/arch/sh/boards/snapgear/setup.c
+++ b/arch/sh/boards/snapgear/setup.c
@@ -27,6 +27,7 @@
#include <asm/mach/io.h>
#include <asm/irq.h>
#include <asm/io.h>
+#include <asm/cpu/timer.h>
extern void (*board_time_init)(void);
extern void secureedge5410_rtc_init(void);
@@ -111,11 +112,6 @@ static void __init init_snapgear_IRQ(void)
#endif
#define TMU_TSTR_INIT 1
#define TMU1_TCR_CALIB 0x0000
-#define TMU_TOCR 0xffd80000 /* Byte access */
-#define TMU_TSTR 0xffd80004 /* Byte access */
-#define TMU1_TCOR 0xffd80014 /* Long access */
-#define TMU1_TCNT 0xffd80018 /* Long access */
-#define TMU1_TCR 0xffd8001c /* Word access */
#ifdef FAST_POLL_INTR
diff --git a/arch/sh/configs/adx_defconfig b/arch/sh/configs/adx_defconfig
index 12b9e2980ed76..353bfdc457d48 100644
--- a/arch/sh/configs/adx_defconfig
+++ b/arch/sh/configs/adx_defconfig
@@ -1,15 +1,46 @@
#
-# Automatically generated by make menuconfig: don't edit
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-sh
+# Wed Mar 2 15:09:26 2005
#
CONFIG_SUPERH=y
CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
-# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+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_IKCONFIG is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+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
#
# Loadable module support
@@ -17,10 +48,13 @@ CONFIG_EXPERIMENTAL=y
# CONFIG_MODULES is not set
#
-# Processor type and features
+# System type
#
# CONFIG_SH_SOLUTION_ENGINE is not set
# CONFIG_SH_7751_SOLUTION_ENGINE is not set
+# CONFIG_SH_7300_SOLUTION_ENGINE is not set
+# CONFIG_SH_73180_SOLUTION_ENGINE is not set
+# 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
@@ -29,57 +63,115 @@ CONFIG_EXPERIMENTAL=y
# CONFIG_SH_CQREEK is not set
# CONFIG_SH_DMIDA is not set
# CONFIG_SH_EC3104 is not set
+# CONFIG_SH_SATURN is not set
# CONFIG_SH_DREAMCAST is not set
# CONFIG_SH_CAT68701 is not set
# CONFIG_SH_BIGSUR is not set
# CONFIG_SH_SH2000 is not set
CONFIG_SH_ADX=y
+# CONFIG_SH_MPC1211 is not set
+# CONFIG_SH_SH03 is not set
+# CONFIG_SH_SECUREEDGE5410 is not set
+# CONFIG_SH_HS7751RVOIP is not set
+# CONFIG_SH_RTS7751R2D is not set
+# CONFIG_SH_EDOSK7705 is not set
+# CONFIG_SH_SH4202_MICRODEV is not set
# CONFIG_SH_UNKNOWN is not set
-CONFIG_SH_RTC=y
+# CONFIG_CPU_SH2 is not set
+# CONFIG_CPU_SH3 is not set
+CONFIG_CPU_SH4=y
+# CONFIG_CPU_SUBTYPE_SH7604 is not set
+# 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 is not set
CONFIG_CPU_SUBTYPE_SH7750=y
# CONFIG_CPU_SUBTYPE_SH7751 is not set
+# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH73180 is not set
# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
-# CONFIG_CPU_SH3 is not set
-CONFIG_CPU_SH4=y
-CONFIG_CPU_LITTLE_ENDIAN=y
+# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
+CONFIG_MMU=y
+# CONFIG_CMDLINE_BOOL is not set
CONFIG_MEMORY_START=0x08000000
CONFIG_MEMORY_SIZE=0x00400000
CONFIG_MEMORY_SET=y
-# CONFIG_DISCONTIGMEM is not set
-
-#
-# General setup
-#
-CONFIG_ISA=y
-# CONFIG_EISA is not set
-# CONFIG_MCA is not set
-# CONFIG_SBUS is not set
-# CONFIG_NET is not set
+# CONFIG_MEMORY_OVERRIDE is not set
CONFIG_CF_ENABLER=y
# CONFIG_CF_AREA5 is not set
CONFIG_CF_AREA6=y
CONFIG_CF_BASE_ADDR=0xb8000000
-# CONFIG_HD64461 is not set
-# CONFIG_HD64465 is not set
+CONFIG_SH_RTC=y
+CONFIG_SH_FPU=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_SH_STORE_QUEUES is not set
+# CONFIG_SMP is not set
+CONFIG_SH_PCLK_CALC=y
+CONFIG_SH_PCLK_FREQ=50000000
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
# CONFIG_SH_DMA is not set
+
+#
+# Companion Chips
+#
+# CONFIG_HD6446X_SERIES is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
# CONFIG_PCI is not set
-# CONFIG_HOTPLUG is not set
-# CONFIG_PCMCIA is not set
-# CONFIG_SYSVIPC is not set
-# CONFIG_BSD_PROCESS_ACCT is not set
-# CONFIG_SYSCTL is not set
-CONFIG_KCORE_ELF=y
-# CONFIG_KCORE_AOUT is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_FLAT is not set
# CONFIG_BINFMT_MISC is not set
#
-# Parallel port support
+# SH initrd options
+#
+# CONFIG_EMBEDDED_RAMDISK is not set
+
+#
+# Device Drivers
#
-# CONFIG_PARPORT is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
#
# Memory Technology Devices (MTD)
@@ -87,190 +179,361 @@ CONFIG_BINFMT_ELF=y
# 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_DEV_XD is not set
-# CONFIG_PARIDE is not set
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_CISS_SCSI_TAPE is not set
-# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
# CONFIG_BLK_DEV_LOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
#
-# Multi-device support (RAID and LVM)
+# IO Schedulers
#
-# CONFIG_MD is not set
-# CONFIG_BLK_DEV_MD is not set
-# CONFIG_MD_LINEAR is not set
-# CONFIG_MD_RAID0 is not set
-# CONFIG_MD_RAID1 is not set
-# CONFIG_MD_RAID5 is not set
-# CONFIG_MD_MULTIPATH is not set
-# CONFIG_BLK_DEV_LVM is not set
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
#
-# ATA/IDE/MFM/RLL support
+# ATA/ATAPI/MFM/RLL support
#
CONFIG_IDE=y
+CONFIG_IDE_MAX_HWIFS=4
+CONFIG_BLK_DEV_IDE=y
#
-# IDE, ATA and ATAPI Block devices
+# Please see Documentation/ide.txt for help/info on IDE drives
#
-CONFIG_BLK_DEV_IDE=y
-# CONFIG_BLK_DEV_HD_IDE is not set
-# CONFIG_BLK_DEV_HD is not set
+# CONFIG_BLK_DEV_IDE_SATA is not set
CONFIG_BLK_DEV_IDEDISK=y
# CONFIG_IDEDISK_MULTI_MODE is not set
-# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set
-# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set
-# CONFIG_BLK_DEV_IDEDISK_IBM is not set
-# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set
-# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set
-# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set
-# CONFIG_BLK_DEV_IDEDISK_WD is not set
-# CONFIG_BLK_DEV_COMMERIAL is not set
-# CONFIG_BLK_DEV_TIVO 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
-# CONFIG_BLK_DEV_IDESCSI is not set
-# CONFIG_BLK_DEV_CMD640 is not set
-# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
-# CONFIG_BLK_DEV_ISAPNP is not set
-# CONFIG_IDE_CHIPSETS is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_IDE_SH=y
+# CONFIG_IDE_ARM is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
# CONFIG_IDEDMA_AUTO is not set
-# CONFIG_DMA_NONPCI is not set
-# CONFIG_BLK_DEV_ATARAID is not set
-# CONFIG_BLK_DEV_ATARAID_PDC is not set
-# CONFIG_BLK_DEV_ATARAID_HPT is not set
+# CONFIG_BLK_DEV_HD is not set
#
-# SCSI support
+# SCSI device support
#
# CONFIG_SCSI is not set
#
-# Old CD-ROM drivers (not SCSI, not IDE)
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Networking support
+#
+# CONFIG_NET is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+
+#
+# Telephony Support
#
-# CONFIG_CD_NO_IDESCSI is not set
+# CONFIG_PHONE is not set
#
-# Input core support
+# Input device support
#
-# CONFIG_INPUT is not set
-# CONFIG_INPUT_KEYBDEV is not set
-# CONFIG_INPUT_MOUSEDEV is not set
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
#
# Character devices
#
-# CONFIG_VT is not set
-# CONFIG_SERIAL is not set
-CONFIG_SH_SCI=y
-CONFIG_SERIAL_CONSOLE=y
-# CONFIG_UNIX98_PTYS is not set
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
#
-# Joysticks
+# Non-8250 serial port support
#
-# CONFIG_INPUT_GAMEPORT is not set
-# CONFIG_PSMOUSE is not set
+# CONFIG_SERIAL_SH_SCI is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
#
# Watchdog Cards
#
# CONFIG_WATCHDOG is not set
# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
#
# File systems
#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_REISERFS_CHECK is not set
-# CONFIG_REISERFS_PROC_INFO 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 is not set
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS 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
+
+#
+# Miscellaneous filesystems
+#
# CONFIG_ADFS_FS is not set
-# CONFIG_ADFS_FS_RW 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_EXT3_FS is not set
-# CONFIG_JBD is not set
-# CONFIG_JBD_DEBUG is not set
-# CONFIG_FAT_FS is not set
-# CONFIG_MSDOS_FS is not set
-# CONFIG_UMSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
# CONFIG_EFS_FS is not set
-# CONFIG_JFFS_FS is not set
-# CONFIG_JFFS2_FS is not set
# CONFIG_CRAMFS is not set
-# CONFIG_TMPFS is not set
-CONFIG_RAMFS=y
-# CONFIG_ISO9660_FS is not set
-# CONFIG_JOLIET is not set
-# CONFIG_ZISOFS is not set
-# CONFIG_MINIX_FS is not set
# CONFIG_VXFS_FS is not set
-# CONFIG_NTFS_FS is not set
-# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
-CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
-# CONFIG_DEVFS_MOUNT is not set
-# CONFIG_DEVFS_DEBUG is not set
-# CONFIG_DEVPTS_FS is not set
# CONFIG_QNX4FS_FS is not set
-# CONFIG_QNX4FS_RW is not set
-# CONFIG_ROMFS_FS is not set
-CONFIG_EXT2_FS=y
# CONFIG_SYSV_FS is not set
-# CONFIG_UDF_FS is not set
-# CONFIG_UDF_RW is not set
# CONFIG_UFS_FS is not set
-# CONFIG_UFS_FS_WRITE is not set
-# CONFIG_NCPFS_NLS is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_ZISOFS_FS is not set
-# CONFIG_ZLIB_FS_INFLATE is not set
#
# Partition Types
#
# CONFIG_PARTITION_ADVANCED is not set
CONFIG_MSDOS_PARTITION=y
-# CONFIG_SMB_NLS is not set
-# CONFIG_NLS is not set
#
-# Multimedia devices
+# Native Language Support
#
-# CONFIG_VIDEO_DEV is not set
+# CONFIG_NLS is not set
#
-# Sound
+# Profiling support
#
-# CONFIG_SOUND is not set
+# CONFIG_PROFILING is not set
#
# Kernel hacking
#
-# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_FRAME_POINTER is not set
CONFIG_SH_STANDARD_BIOS=y
-CONFIG_SH_EARLY_PRINTK=y
+# CONFIG_EARLY_SCIF_CONSOLE is not set
+# CONFIG_EARLY_PRINTK is not set
+# CONFIG_KGDB 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_CRC32 is not set
+# CONFIG_LIBCRC32C is not set
diff --git a/arch/sh/configs/cqreek_defconfig b/arch/sh/configs/cqreek_defconfig
index 8ca0baa85e7f4..614662ae5789e 100644
--- a/arch/sh/configs/cqreek_defconfig
+++ b/arch/sh/configs/cqreek_defconfig
@@ -1,15 +1,46 @@
#
-# Automatically generated by make menuconfig: don't edit
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-sh
+# Wed Mar 2 15:09:38 2005
#
CONFIG_SUPERH=y
CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
-# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+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_IKCONFIG is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+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
#
# Loadable module support
@@ -17,10 +48,13 @@ CONFIG_EXPERIMENTAL=y
# CONFIG_MODULES is not set
#
-# Processor type and features
+# System type
#
# CONFIG_SH_SOLUTION_ENGINE is not set
# CONFIG_SH_7751_SOLUTION_ENGINE is not set
+# CONFIG_SH_7300_SOLUTION_ENGINE is not set
+# CONFIG_SH_73180_SOLUTION_ENGINE is not set
+# 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
@@ -29,55 +63,110 @@ CONFIG_EXPERIMENTAL=y
CONFIG_SH_CQREEK=y
# CONFIG_SH_DMIDA is not set
# CONFIG_SH_EC3104 is not set
+# CONFIG_SH_SATURN is not set
# CONFIG_SH_DREAMCAST is not set
# CONFIG_SH_CAT68701 is not set
# CONFIG_SH_BIGSUR is not set
# CONFIG_SH_SH2000 is not set
# CONFIG_SH_ADX is not set
+# CONFIG_SH_MPC1211 is not set
+# CONFIG_SH_SH03 is not set
+# CONFIG_SH_SECUREEDGE5410 is not set
+# CONFIG_SH_HS7751RVOIP is not set
+# CONFIG_SH_RTS7751R2D is not set
+# CONFIG_SH_EDOSK7705 is not set
+# CONFIG_SH_SH4202_MICRODEV is not set
# CONFIG_SH_UNKNOWN is not set
-CONFIG_SH_RTC=y
+# CONFIG_CPU_SH2 is not set
+CONFIG_CPU_SH3=y
+# CONFIG_CPU_SH4 is not set
+# CONFIG_CPU_SUBTYPE_SH7604 is not set
+# 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=y
# CONFIG_CPU_SUBTYPE_SH7709 is not set
# CONFIG_CPU_SUBTYPE_SH7750 is not set
# CONFIG_CPU_SUBTYPE_SH7751 is not set
+# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH73180 is not set
# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
-CONFIG_CPU_SH3=y
-# CONFIG_CPU_SH4 is not set
-CONFIG_CPU_LITTLE_ENDIAN=y
+# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
+CONFIG_MMU=y
+# CONFIG_CMDLINE_BOOL is not set
CONFIG_MEMORY_START=0x0c000000
CONFIG_MEMORY_SIZE=0x00400000
-# CONFIG_DISCONTIGMEM is not set
+# CONFIG_MEMORY_OVERRIDE is not set
+CONFIG_SH_RTC=y
+CONFIG_SH_DSP=y
+CONFIG_SH_ADC=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
#
-# General setup
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
#
-CONFIG_ISA=y
-# CONFIG_EISA is not set
-# CONFIG_MCA is not set
-# CONFIG_SBUS is not set
-# CONFIG_NET is not set
-# CONFIG_CF_AREA5 is not set
-CONFIG_CF_AREA6=y
-CONFIG_CF_BASE_ADDR=0xb8000000
-# CONFIG_HD64461 is not set
-# CONFIG_HD64465 is not set
# CONFIG_SH_DMA is not set
+
+#
+# Companion Chips
+#
+# CONFIG_HD6446X_SERIES is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
# CONFIG_PCI is not set
-# CONFIG_HOTPLUG is not set
-# CONFIG_PCMCIA is not set
-# CONFIG_SYSVIPC is not set
-# CONFIG_BSD_PROCESS_ACCT is not set
-# CONFIG_SYSCTL is not set
-CONFIG_KCORE_ELF=y
-# CONFIG_KCORE_AOUT is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_FLAT is not set
# CONFIG_BINFMT_MISC is not set
#
-# Parallel port support
+# SH initrd options
#
-# CONFIG_PARPORT is not set
+# CONFIG_EMBEDDED_RAMDISK is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
#
# Memory Technology Devices (MTD)
@@ -85,190 +174,360 @@ CONFIG_BINFMT_ELF=y
# 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_DEV_XD is not set
-# CONFIG_PARIDE is not set
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_CISS_SCSI_TAPE is not set
-# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
# CONFIG_BLK_DEV_LOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
#
-# Multi-device support (RAID and LVM)
+# IO Schedulers
#
-# CONFIG_MD is not set
-# CONFIG_BLK_DEV_MD is not set
-# CONFIG_MD_LINEAR is not set
-# CONFIG_MD_RAID0 is not set
-# CONFIG_MD_RAID1 is not set
-# CONFIG_MD_RAID5 is not set
-# CONFIG_MD_MULTIPATH is not set
-# CONFIG_BLK_DEV_LVM is not set
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
#
-# ATA/IDE/MFM/RLL support
+# ATA/ATAPI/MFM/RLL support
#
CONFIG_IDE=y
+CONFIG_IDE_MAX_HWIFS=4
+CONFIG_BLK_DEV_IDE=y
#
-# IDE, ATA and ATAPI Block devices
+# Please see Documentation/ide.txt for help/info on IDE drives
#
-CONFIG_BLK_DEV_IDE=y
-# CONFIG_BLK_DEV_HD_IDE is not set
-# CONFIG_BLK_DEV_HD is not set
+# CONFIG_BLK_DEV_IDE_SATA is not set
CONFIG_BLK_DEV_IDEDISK=y
# CONFIG_IDEDISK_MULTI_MODE is not set
-# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set
-# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set
-# CONFIG_BLK_DEV_IDEDISK_IBM is not set
-# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set
-# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set
-# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set
-# CONFIG_BLK_DEV_IDEDISK_WD is not set
-# CONFIG_BLK_DEV_COMMERIAL is not set
-# CONFIG_BLK_DEV_TIVO 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
-# CONFIG_BLK_DEV_IDESCSI is not set
-# CONFIG_BLK_DEV_CMD640 is not set
-# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
-# CONFIG_BLK_DEV_ISAPNP is not set
-# CONFIG_IDE_CHIPSETS is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_IDE_SH=y
+# CONFIG_IDE_ARM is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
# CONFIG_IDEDMA_AUTO is not set
-# CONFIG_DMA_NONPCI is not set
-# CONFIG_BLK_DEV_ATARAID is not set
-# CONFIG_BLK_DEV_ATARAID_PDC is not set
-# CONFIG_BLK_DEV_ATARAID_HPT is not set
+# CONFIG_BLK_DEV_HD is not set
#
-# SCSI support
+# SCSI device support
#
# CONFIG_SCSI is not set
#
-# Old CD-ROM drivers (not SCSI, not IDE)
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
#
-# CONFIG_CD_NO_IDESCSI is not set
#
-# Input core support
+# Networking support
#
-# CONFIG_INPUT is not set
-# CONFIG_INPUT_KEYBDEV is not set
-# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_NET is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
#
# Character devices
#
-# CONFIG_VT is not set
-# CONFIG_SERIAL is not set
-CONFIG_SH_SCI=y
-CONFIG_SERIAL_CONSOLE=y
-# CONFIG_UNIX98_PTYS is not set
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
#
-# Joysticks
+# Serial drivers
#
-# CONFIG_INPUT_GAMEPORT is not set
-# CONFIG_PSMOUSE is not set
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_SH_SCI is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
#
# Watchdog Cards
#
# CONFIG_WATCHDOG is not set
# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
#
# File systems
#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_REISERFS_CHECK is not set
-# CONFIG_REISERFS_PROC_INFO 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 is not set
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS 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
+
+#
+# Miscellaneous filesystems
+#
# CONFIG_ADFS_FS is not set
-# CONFIG_ADFS_FS_RW 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_EXT3_FS is not set
-# CONFIG_JBD is not set
-# CONFIG_JBD_DEBUG is not set
-# CONFIG_FAT_FS is not set
-# CONFIG_MSDOS_FS is not set
-# CONFIG_UMSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
# CONFIG_EFS_FS is not set
-# CONFIG_JFFS_FS is not set
-# CONFIG_JFFS2_FS is not set
# CONFIG_CRAMFS is not set
-# CONFIG_TMPFS is not set
-CONFIG_RAMFS=y
-# CONFIG_ISO9660_FS is not set
-# CONFIG_JOLIET is not set
-# CONFIG_ZISOFS is not set
-# CONFIG_MINIX_FS is not set
# CONFIG_VXFS_FS is not set
-# CONFIG_NTFS_FS is not set
-# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
-CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
-# CONFIG_DEVFS_MOUNT is not set
-# CONFIG_DEVFS_DEBUG is not set
-# CONFIG_DEVPTS_FS is not set
# CONFIG_QNX4FS_FS is not set
-# CONFIG_QNX4FS_RW is not set
-# CONFIG_ROMFS_FS is not set
-CONFIG_EXT2_FS=y
# CONFIG_SYSV_FS is not set
-# CONFIG_UDF_FS is not set
-# CONFIG_UDF_RW is not set
# CONFIG_UFS_FS is not set
-# CONFIG_UFS_FS_WRITE is not set
-# CONFIG_NCPFS_NLS is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_ZISOFS_FS is not set
-# CONFIG_ZLIB_FS_INFLATE is not set
#
# Partition Types
#
# CONFIG_PARTITION_ADVANCED is not set
CONFIG_MSDOS_PARTITION=y
-# CONFIG_SMB_NLS is not set
-# CONFIG_NLS is not set
#
-# Multimedia devices
+# Native Language Support
#
-# CONFIG_VIDEO_DEV is not set
+# CONFIG_NLS is not set
#
-# Sound
+# Profiling support
#
-# CONFIG_SOUND is not set
+# CONFIG_PROFILING is not set
#
# Kernel hacking
#
-# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_FRAME_POINTER is not set
CONFIG_SH_STANDARD_BIOS=y
-CONFIG_SH_EARLY_PRINTK=y
+# CONFIG_EARLY_PRINTK is not set
+# CONFIG_KGDB 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_CRC32 is not set
+# CONFIG_LIBCRC32C is not set
diff --git a/arch/sh/configs/dreamcast_defconfig b/arch/sh/configs/dreamcast_defconfig
index ec2a0f3324cbd..776c1909bee31 100644
--- a/arch/sh/configs/dreamcast_defconfig
+++ b/arch/sh/configs/dreamcast_defconfig
@@ -1,36 +1,50 @@
#
# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-sh
+# Wed Mar 2 15:09:40 2005
#
CONFIG_SUPERH=y
CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
CONFIG_CLEAN_COMPILE=y
-# CONFIG_STANDALONE is not set
CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
#
# General setup
#
+CONFIG_LOCALVERSION=""
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
CONFIG_LOG_BUF_SHIFT=14
CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
# CONFIG_IKCONFIG is not set
CONFIG_EMBEDDED=y
CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
CONFIG_FUTEX=y
CONFIG_EPOLL=y
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
#
# Loadable module support
@@ -40,6 +54,7 @@ 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
#
@@ -47,6 +62,8 @@ CONFIG_KMOD=y
#
# CONFIG_SH_SOLUTION_ENGINE is not set
# CONFIG_SH_7751_SOLUTION_ENGINE is not set
+# CONFIG_SH_7300_SOLUTION_ENGINE is not set
+# CONFIG_SH_73180_SOLUTION_ENGINE is not set
# CONFIG_SH_7751_SYSTEMH is not set
# CONFIG_SH_STB1_HARP is not set
# CONFIG_SH_STB1_OVERDRIVE is not set
@@ -63,20 +80,29 @@ CONFIG_SH_DREAMCAST=y
# CONFIG_SH_SH2000 is not set
# CONFIG_SH_ADX is not set
# CONFIG_SH_MPC1211 is not set
+# CONFIG_SH_SH03 is not set
# CONFIG_SH_SECUREEDGE5410 is not set
+# CONFIG_SH_HS7751RVOIP is not set
+# CONFIG_SH_RTS7751R2D is not set
+# CONFIG_SH_EDOSK7705 is not set
+# CONFIG_SH_SH4202_MICRODEV is not set
# CONFIG_SH_UNKNOWN is not set
# CONFIG_CPU_SH2 is not set
# CONFIG_CPU_SH3 is not set
CONFIG_CPU_SH4=y
# CONFIG_CPU_SUBTYPE_SH7604 is not set
# 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 is not set
CONFIG_CPU_SUBTYPE_SH7750=y
# CONFIG_CPU_SUBTYPE_SH7751 is not set
# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH73180 is not set
# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
+# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
CONFIG_MMU=y
CONFIG_HUGETLB_PAGE_SIZE_64K=y
# CONFIG_HUGETLB_PAGE_SIZE_1MB is not set
@@ -85,6 +111,7 @@ CONFIG_MEMORY_START=0x0c000000
CONFIG_MEMORY_SIZE=0x01000000
CONFIG_MEMORY_SET=y
# CONFIG_MEMORY_OVERRIDE is not set
+CONFIG_SH_FPU=y
CONFIG_ZERO_PAGE_OFFSET=0x00001000
CONFIG_BOOT_LINK_OFFSET=0x00800000
CONFIG_CPU_LITTLE_ENDIAN=y
@@ -94,25 +121,36 @@ CONFIG_PREEMPT=y
CONFIG_SH_OCRAM=y
CONFIG_SH_STORE_QUEUES=y
# CONFIG_SMP is not set
+CONFIG_SH_PCLK_CALC=y
CONFIG_SH_PCLK_FREQ=49876504
#
# CPU Frequency scaling
#
CONFIG_CPU_FREQ=y
-# CONFIG_CPU_FREQ_PROC_INTF is not set
+# 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_24_API is not set
+# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set
CONFIG_CPU_FREQ_TABLE=y
CONFIG_SH_CPU_FREQ=y
+
+#
+# DMA support
+#
CONFIG_SH_DMA=y
CONFIG_NR_ONCHIP_DMA_CHANNELS=4
CONFIG_NR_DMA_CHANNELS_BOOL=y
CONFIG_NR_DMA_CHANNELS=9
+
+#
+# Companion Chips
+#
# CONFIG_HD6446X_SERIES is not set
#
@@ -126,9 +164,13 @@ CONFIG_PCI_LEGACY_PROC=y
CONFIG_PCI_NAMES=y
#
-# PCMCIA/CardBus support
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
#
-# CONFIG_PCMCIA is not set
#
# PCI Hotplug Support
@@ -143,12 +185,19 @@ CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
#
+# SH initrd options
+#
+# CONFIG_EMBEDDED_RAMDISK is not set
+
+#
# Device Drivers
#
#
# Generic Driver Options
#
+# CONFIG_STANDALONE is not set
+CONFIG_PREVENT_FIRMWARE_BUILD=y
# CONFIG_FW_LOADER is not set
#
@@ -173,12 +222,26 @@ CONFIG_BINFMT_ELF=y
# CONFIG_BLK_CPQ_CISS_DA is not set
# CONFIG_BLK_DEV_DAC960 is not set
# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
# CONFIG_BLK_DEV_LOOP 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=1024
CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
# CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
#
# ATA/ATAPI/MFM/RLL support
@@ -210,10 +273,6 @@ CONFIG_BLK_DEV_INITRD=y
# CONFIG_I2O is not set
#
-# Macintosh device drivers
-#
-
-#
# Networking support
#
CONFIG_NET=y
@@ -236,23 +295,24 @@ CONFIG_IP_PNP_DHCP=y
# CONFIG_NET_IPIP is not set
# CONFIG_NET_IPGRE is not set
# CONFIG_ARPD is not set
-# CONFIG_INET_ECN is not set
# CONFIG_SYN_COOKIES is not set
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
# CONFIG_IPV6 is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
# CONFIG_NETFILTER is not set
#
# SCTP Configuration (EXPERIMENTAL)
#
-CONFIG_IPV6_SCTP__=y
# CONFIG_IP_SCTP is not set
# CONFIG_ATM is not set
+# CONFIG_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
@@ -261,27 +321,32 @@ CONFIG_IPV6_SCTP__=y
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
#
# QoS and/or fair queueing
#
# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
#
# Network testing
#
# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
#
# ARCnet devices
#
# CONFIG_ARCNET is not set
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
#
# Ethernet (10 or 100Mbit)
@@ -292,6 +357,7 @@ CONFIG_MII=y
# CONFIG_HAPPYMEAL is not set
# CONFIG_SUNGEM is not set
# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_SMC91X is not set
#
# Tulip family network device support
@@ -316,7 +382,6 @@ CONFIG_8139TOO=y
# CONFIG_8139TOO_TUNE_TWISTER is not set
# CONFIG_8139TOO_8129 is not set
# CONFIG_8139_OLD_RX_RESET is not set
-CONFIG_8139_RXBUF_IDX=1
# CONFIG_SIS900 is not set
# CONFIG_EPIC100 is not set
# CONFIG_SUNDANCE is not set
@@ -333,50 +398,36 @@ CONFIG_8139_RXBUF_IDX=1
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
# CONFIG_R8169 is not set
-# CONFIG_SIS190 is not set
# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
# CONFIG_TIGON3 is not set
#
# Ethernet (10000 Mbit)
#
# CONFIG_IXGB is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
+# CONFIG_S2IO is not set
#
# Token Ring devices
#
# CONFIG_TR is not set
-# CONFIG_RCPCI is not set
-# CONFIG_SHAPER is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
+# Wireless LAN (non-hamradio)
#
-# CONFIG_IRDA is not set
+# CONFIG_NET_RADIO is not set
#
-# Bluetooth support
+# Wan interfaces
#
-# CONFIG_BT is not set
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
#
# ISDN subsystem
@@ -415,6 +466,8 @@ CONFIG_SERIO=y
# CONFIG_SERIO_SERPORT is not set
# CONFIG_SERIO_CT82C710 is not set
# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
#
# Input Device Drivers
@@ -422,6 +475,7 @@ CONFIG_SERIO=y
CONFIG_INPUT_KEYBOARD=y
CONFIG_KEYBOARD_ATKBD=y
# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
# CONFIG_KEYBOARD_XTKBD is not set
# CONFIG_KEYBOARD_NEWTON is not set
# CONFIG_KEYBOARD_MAPLE is not set
@@ -429,6 +483,7 @@ CONFIG_INPUT_MOUSE=y
CONFIG_MOUSE_PS2=y
# CONFIG_MOUSE_SERIAL is not set
# CONFIG_MOUSE_MAPLE 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
@@ -458,12 +513,6 @@ CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_QIC02_TAPE is not set
-
-#
# IPMI
#
# CONFIG_IPMI_HANDLER is not set
@@ -485,7 +534,6 @@ CONFIG_SH_WDT=y
#
# CONFIG_PCIPCWATCHDOG is not set
# CONFIG_WDTPCI is not set
-# CONFIG_NVRAM is not set
# CONFIG_RTC is not set
# CONFIG_GEN_RTC is not set
# CONFIG_DTLK is not set
@@ -495,8 +543,6 @@ CONFIG_SH_WDT=y
#
# Ftape, the floppy tape device driver
#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
# CONFIG_DRM is not set
# CONFIG_RAW_DRIVER is not set
@@ -506,6 +552,11 @@ CONFIG_SH_WDT=y
# CONFIG_I2C is not set
#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
# Misc devices
#
@@ -523,18 +574,22 @@ CONFIG_SH_WDT=y
# Graphics support
#
CONFIG_FB=y
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_CIRRUS is not set
# CONFIG_FB_PM2 is not set
# CONFIG_FB_CYBER2000 is not set
# CONFIG_FB_ASILIANT is not set
# CONFIG_FB_IMSTT is not set
CONFIG_FB_PVR2=y
-# CONFIG_FB_E1355 is not set
+# CONFIG_FB_EPSON1355 is not set
# CONFIG_FB_RIVA is not set
# CONFIG_FB_MATROX is not set
# CONFIG_FB_RADEON_OLD is not set
# CONFIG_FB_RADEON is not set
# CONFIG_FB_ATY128 is not set
# CONFIG_FB_ATY is not set
+# CONFIG_FB_SAVAGE is not set
# CONFIG_FB_SIS is not set
# CONFIG_FB_NEOMAGIC is not set
# CONFIG_FB_KYRO is not set
@@ -547,10 +602,8 @@ CONFIG_FB_PVR2=y
# Console display driver support
#
# CONFIG_VGA_CONSOLE is not set
-# CONFIG_MDA_CONSOLE is not set
CONFIG_DUMMY_CONSOLE=y
CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_PCI_CONSOLE=y
CONFIG_FONTS=y
CONFIG_FONT_8x8=y
CONFIG_FONT_8x16=y
@@ -571,6 +624,7 @@ CONFIG_LOGO=y
# CONFIG_LOGO_SUPERH_MONO is not set
# CONFIG_LOGO_SUPERH_VGA16 is not set
CONFIG_LOGO_SUPERH_CLUT224=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
# Sound
@@ -581,6 +635,12 @@ CONFIG_LOGO_SUPERH_CLUT224=y
# USB support
#
# CONFIG_USB is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
#
# USB Gadget Support
@@ -588,10 +648,14 @@ CONFIG_LOGO_SUPERH_CLUT224=y
# CONFIG_USB_GADGET is not set
#
-# Maple Bus input peripherals
+# MMC/SD Card support
#
-# CONFIG_MAPLE_KEYBOARD is not set
-# CONFIG_MAPLE_MOUSE is not set
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
#
# File systems
@@ -601,10 +665,15 @@ CONFIG_LOGO_SUPERH_CLUT224=y
# CONFIG_JBD is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
# CONFIG_XFS_FS is not set
# CONFIG_MINIX_FS is not set
CONFIG_ROMFS_FS=y
# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
@@ -617,7 +686,8 @@ CONFIG_ROMFS_FS=y
#
# DOS/FAT/NT Filesystems
#
-# CONFIG_FAT_FS is not set
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
# CONFIG_NTFS_FS is not set
#
@@ -625,11 +695,13 @@ CONFIG_ROMFS_FS=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=y
+# CONFIG_TMPFS_XATTR is not set
CONFIG_HUGETLBFS=y
CONFIG_HUGETLB_PAGE=y
CONFIG_RAMFS=y
@@ -662,9 +734,9 @@ CONFIG_NFS_V3=y
CONFIG_ROOT_NFS=y
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
-# CONFIG_EXPORTFS is not set
CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_GSS is not set
+# 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
@@ -691,15 +763,17 @@ CONFIG_OPROFILE=y
#
# Kernel hacking
#
-CONFIG_MAGIC_SYSRQ=y
-# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_DEBUG_PREEMPT=y
+# CONFIG_FRAME_POINTER is not set
# CONFIG_SH_STANDARD_BIOS is not set
+# CONFIG_EARLY_SCIF_CONSOLE is not set
# CONFIG_KGDB is not set
-# CONFIG_FRAME_POINTER is not set
#
# Security options
#
+# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
#
@@ -708,7 +782,13 @@ CONFIG_MAGIC_SYSRQ=y
# CONFIG_CRYPTO is not set
#
+# Hardware crypto devices
+#
+
+#
# Library routines
#
+# CONFIG_CRC_CCITT is not set
CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=y
diff --git a/arch/sh/configs/hp680_defconfig b/arch/sh/configs/hp680_defconfig
index 52b28cf0b3d35..c85d3655b53c2 100644
--- a/arch/sh/configs/hp680_defconfig
+++ b/arch/sh/configs/hp680_defconfig
@@ -1,36 +1,47 @@
#
# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-sh
+# Wed Mar 2 15:09:41 2005
#
CONFIG_SUPERH=y
CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
# CONFIG_CLEAN_COMPILE is not set
-# CONFIG_STANDALONE is not set
CONFIG_BROKEN=y
CONFIG_BROKEN_ON_SMP=y
#
# General setup
#
+CONFIG_LOCALVERSION=""
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_IKCONFIG is not set
# CONFIG_EMBEDDED is not set
CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
CONFIG_FUTEX=y
CONFIG_EPOLL=y
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+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
#
# Loadable module support
@@ -42,6 +53,8 @@ CONFIG_IOSCHED_DEADLINE=y
#
# CONFIG_SH_SOLUTION_ENGINE is not set
# CONFIG_SH_7751_SOLUTION_ENGINE is not set
+# CONFIG_SH_7300_SOLUTION_ENGINE is not set
+# CONFIG_SH_73180_SOLUTION_ENGINE is not set
# CONFIG_SH_7751_SYSTEMH is not set
# CONFIG_SH_STB1_HARP is not set
# CONFIG_SH_STB1_OVERDRIVE is not set
@@ -58,20 +71,29 @@ CONFIG_SH_HP680=y
# CONFIG_SH_SH2000 is not set
# CONFIG_SH_ADX is not set
# CONFIG_SH_MPC1211 is not set
+# CONFIG_SH_SH03 is not set
# CONFIG_SH_SECUREEDGE5410 is not set
+# CONFIG_SH_HS7751RVOIP is not set
+# CONFIG_SH_RTS7751R2D is not set
+# CONFIG_SH_EDOSK7705 is not set
+# CONFIG_SH_SH4202_MICRODEV is not set
# CONFIG_SH_UNKNOWN is not set
# CONFIG_CPU_SH2 is not set
CONFIG_CPU_SH3=y
# CONFIG_CPU_SH4 is not set
# CONFIG_CPU_SUBTYPE_SH7604 is not set
# 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
# CONFIG_CPU_SUBTYPE_SH7750 is not set
# CONFIG_CPU_SUBTYPE_SH7751 is not set
# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH73180 is not set
# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
+# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
CONFIG_MMU=y
# CONFIG_CMDLINE_BOOL is not set
CONFIG_MEMORY_START=0x0c000000
@@ -80,6 +102,7 @@ CONFIG_MEMORY_SET=y
# CONFIG_MEMORY_OVERRIDE is not set
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
@@ -89,9 +112,22 @@ CONFIG_CPU_LITTLE_ENDIAN=y
# 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
+
+#
+# CPU Frequency scaling
+#
# CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
# CONFIG_SH_DMA is not set
+
+#
+# Companion Chips
+#
CONFIG_HD6446X_SERIES=y
CONFIG_HD64461=y
# CONFIG_HD64465 is not set
@@ -102,7 +138,19 @@ CONFIG_HD64461_IRQ=36
# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
#
# CONFIG_PCI is not set
-# CONFIG_HOTPLUG is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
#
# Executable file formats
@@ -112,8 +160,20 @@ CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
#
+# SH initrd options
+#
+# CONFIG_EMBEDDED_RAMDISK is not set
+
+#
+# Device Drivers
+#
+
+#
# Generic Driver Options
#
+# CONFIG_STANDALONE is not set
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
#
# Memory Technology Devices (MTD)
@@ -126,40 +186,57 @@ CONFIG_BINFMT_ELF=y
# CONFIG_PARPORT is not set
#
+# Plug and Play support
+#
+
+#
# 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
+CONFIG_IDE_MAX_HWIFS=4
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_IDEDISK_STROKE is not set
# CONFIG_BLK_DEV_IDECD is not set
# CONFIG_BLK_DEV_IDETAPE is not set
# CONFIG_BLK_DEV_IDEFLOPPY is not set
# CONFIG_IDE_TASK_IOCTL is not set
-# CONFIG_IDE_TASKFILE_IO is not set
#
# IDE chipset support/bugfixes
#
CONFIG_IDE_GENERIC=y
+CONFIG_IDE_SH=y
+# CONFIG_IDE_ARM is not set
# CONFIG_BLK_DEV_IDEDMA is not set
# CONFIG_IDEDMA_AUTO is not set
-# CONFIG_DMA_NONPCI is not set
# CONFIG_BLK_DEV_HD is not set
#
@@ -173,19 +250,24 @@ CONFIG_IDE_GENERIC=y
# CONFIG_MD is not set
#
-# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
#
# CONFIG_IEEE1394 is not set
#
-# Networking support
+# I2O device support
#
-# CONFIG_NET is not set
#
-# Amateur Radio support
+# Networking support
#
-# CONFIG_HAMRADIO is not set
+# CONFIG_NET is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
#
# ISDN subsystem
@@ -222,6 +304,7 @@ 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
@@ -238,33 +321,125 @@ CONFIG_SERIO=y
CONFIG_VT=y
CONFIG_VT_CONSOLE=y
CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
#
-# Unix98 PTY support
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
#
-# CONFIG_UNIX98_PTYS is not set
-# CONFIG_PSMOUSE is not set
+# CONFIG_SERIAL_SH_SCI is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
#
# Watchdog Cards
#
# CONFIG_WATCHDOG is not set
# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
#
-# Serial drivers
+# Ftape, the floppy tape device driver
#
-# CONFIG_SERIAL_8250 is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
#
-# Non-8250 serial port support
+# I2C support
#
-# CONFIG_SERIAL_SH_SCI is not set
+# CONFIG_I2C is not set
#
-# I2C support
+# Dallas's 1-wire bus
#
-# CONFIG_I2C is not set
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_EPSON1355 is not set
+CONFIG_FB_HIT=y
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FONTS=y
+# CONFIG_FONT_8x8 is not set
+# CONFIG_FONT_8x16 is not set
+# CONFIG_FONT_6x11 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
+
+#
+# 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 is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
#
# File systems
@@ -275,10 +450,15 @@ CONFIG_EXT2_FS=y
# CONFIG_JBD is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
# CONFIG_XFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
@@ -291,7 +471,8 @@ CONFIG_EXT2_FS=y
#
# DOS/FAT/NT Filesystems
#
-# CONFIG_FAT_FS is not set
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
# CONFIG_NTFS_FS is not set
#
@@ -299,9 +480,11 @@ CONFIG_EXT2_FS=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
@@ -313,6 +496,7 @@ CONFIG_RAMFS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
# CONFIG_BEFS_FS is not set
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
@@ -335,60 +519,6 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_NLS is not set
#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-
-#
-# Graphics support
-#
-CONFIG_FB=y
-# CONFIG_FB_E1355 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_PCI_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=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
-
-#
-# Logo configuration
-#
-# CONFIG_LOGO is not set
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
# Profiling support
#
# CONFIG_PROFILING is not set
@@ -396,15 +526,15 @@ CONFIG_FONT_PEARL_8x8=y
#
# Kernel hacking
#
-# CONFIG_MAGIC_SYSRQ is not set
-# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_FRAME_POINTER is not set
# CONFIG_SH_STANDARD_BIOS is not set
# CONFIG_KGDB is not set
-# CONFIG_FRAME_POINTER is not set
#
# Security options
#
+# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
#
@@ -413,6 +543,12 @@ CONFIG_FONT_PEARL_8x8=y
# CONFIG_CRYPTO is not set
#
+# Hardware crypto devices
+#
+
+#
# Library routines
#
-# CONFIG_CRC32 is not set
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
diff --git a/arch/sh/configs/microdev_defconfig b/arch/sh/configs/microdev_defconfig
index e76a93a431e53..a3bd280b53d6c 100644
--- a/arch/sh/configs/microdev_defconfig
+++ b/arch/sh/configs/microdev_defconfig
@@ -1,9 +1,14 @@
#
# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-sh
+# Wed Mar 2 15:09:41 2005
#
CONFIG_SUPERH=y
CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
#
# Code maturity level options
@@ -11,10 +16,12 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_EXPERIMENTAL=y
CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
#
# General setup
#
+CONFIG_LOCALVERSION=""
CONFIG_SWAP=y
# CONFIG_SYSVIPC is not set
# CONFIG_POSIX_MQUEUE is not set
@@ -24,17 +31,20 @@ CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
CONFIG_LOG_BUF_SHIFT=14
CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
# CONFIG_IKCONFIG is not set
CONFIG_EMBEDDED=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
CONFIG_FUTEX=y
CONFIG_EPOLL=y
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
#
# Loadable module support
@@ -133,9 +143,13 @@ CONFIG_ISA=y
# CONFIG_PCI is not set
#
-# PCMCIA/CardBus support
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
#
-# CONFIG_PCMCIA is not set
CONFIG_PCMCIA_PROBE=y
#
@@ -185,12 +199,25 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
#
# CONFIG_BLK_DEV_FD is not set
# CONFIG_BLK_DEV_XD is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
# CONFIG_BLK_DEV_LOOP is not set
# CONFIG_BLK_DEV_NBD is not set
CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
# CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
#
# ATA/ATAPI/MFM/RLL support
@@ -209,7 +236,6 @@ CONFIG_BLK_DEV_IDECD=y
# CONFIG_BLK_DEV_IDETAPE is not set
# CONFIG_BLK_DEV_IDEFLOPPY is not set
# CONFIG_IDE_TASK_IOCTL is not set
-# CONFIG_IDE_TASKFILE_IO is not set
#
# IDE chipset support/bugfixes
@@ -275,6 +301,9 @@ CONFIG_IP_PNP_DHCP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
# CONFIG_IPV6 is not set
# CONFIG_NETFILTER is not set
@@ -294,7 +323,6 @@ CONFIG_IP_PNP_DHCP=y
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
#
# QoS and/or fair queueing
@@ -419,7 +447,6 @@ CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
-# CONFIG_QIC02_TAPE is not set
#
# IPMI
@@ -437,7 +464,6 @@ CONFIG_RTC=y
#
# Ftape, the floppy tape device driver
#
-# CONFIG_AGP is not set
# CONFIG_DRM is not set
# CONFIG_RAW_DRIVER is not set
@@ -478,6 +504,12 @@ CONFIG_RTC=y
#
# USB support
#
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
#
# USB Gadget Support
@@ -485,6 +517,16 @@ CONFIG_RTC=y
# CONFIG_USB_GADGET is not set
#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -498,10 +540,15 @@ CONFIG_JBD=y
CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
# CONFIG_XFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
@@ -533,6 +580,7 @@ CONFIG_DEVFS_MOUNT=y
CONFIG_DEVPTS_FS_XATTR=y
# CONFIG_DEVPTS_FS_SECURITY is not set
CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
# CONFIG_HUGETLBFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
@@ -565,10 +613,10 @@ CONFIG_NFS_V4=y
CONFIG_ROOT_NFS=y
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
-# CONFIG_EXPORTFS is not set
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
@@ -633,17 +681,17 @@ CONFIG_NLS_DEFAULT="iso8859-1"
#
# Kernel hacking
#
-CONFIG_MAGIC_SYSRQ=y
-# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_DEBUG_PREEMPT=y
+# CONFIG_FRAME_POINTER is not set
# CONFIG_SH_STANDARD_BIOS is not set
# CONFIG_EARLY_SCIF_CONSOLE is not set
# CONFIG_KGDB is not set
-# CONFIG_FRAME_POINTER is not set
#
# Security options
#
+# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
#
@@ -657,6 +705,7 @@ 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_DES=y
# CONFIG_CRYPTO_BLOWFISH is not set
# CONFIG_CRYPTO_TWOFISH is not set
@@ -667,12 +716,17 @@ CONFIG_CRYPTO_DES=y
# 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
diff --git a/arch/sh/configs/rts7751r2d_defconfig b/arch/sh/configs/rts7751r2d_defconfig
index 34fd8d1d40785..e43cf57326bda 100644
--- a/arch/sh/configs/rts7751r2d_defconfig
+++ b/arch/sh/configs/rts7751r2d_defconfig
@@ -1,21 +1,26 @@
#
# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-sh
+# Wed Mar 2 15:09:42 2005
#
CONFIG_SUPERH=y
CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
CONFIG_CLEAN_COMPILE=y
-CONFIG_STANDALONE=y
CONFIG_BROKEN_ON_SMP=y
#
# General setup
#
+CONFIG_LOCALVERSION=""
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
# CONFIG_POSIX_MQUEUE is not set
@@ -24,16 +29,20 @@ CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
CONFIG_LOG_BUF_SHIFT=14
CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
# CONFIG_IKCONFIG is not set
CONFIG_EMBEDDED=y
CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
CONFIG_FUTEX=y
CONFIG_EPOLL=y
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
#
# Loadable module support
@@ -42,6 +51,7 @@ CONFIG_MODULES=y
# CONFIG_MODULE_UNLOAD is not set
CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
# CONFIG_KMOD is not set
#
@@ -50,6 +60,7 @@ CONFIG_OBSOLETE_MODPARM=y
# CONFIG_SH_SOLUTION_ENGINE is not set
# CONFIG_SH_7751_SOLUTION_ENGINE is not set
# CONFIG_SH_7300_SOLUTION_ENGINE is not set
+# CONFIG_SH_73180_SOLUTION_ENGINE is not set
# CONFIG_SH_7751_SYSTEMH is not set
# CONFIG_SH_STB1_HARP is not set
# CONFIG_SH_STB1_OVERDRIVE is not set
@@ -66,9 +77,12 @@ CONFIG_OBSOLETE_MODPARM=y
# CONFIG_SH_SH2000 is not set
# CONFIG_SH_ADX is not set
# CONFIG_SH_MPC1211 is not set
+# CONFIG_SH_SH03 is not set
# CONFIG_SH_SECUREEDGE5410 is not set
# CONFIG_SH_HS7751RVOIP is not set
CONFIG_SH_RTS7751R2D=y
+# CONFIG_SH_EDOSK7705 is not set
+# CONFIG_SH_SH4202_MICRODEV is not set
# CONFIG_SH_UNKNOWN is not set
# CONFIG_CPU_SH2 is not set
# CONFIG_CPU_SH3 is not set
@@ -82,8 +96,10 @@ CONFIG_CPU_SH4=y
# CONFIG_CPU_SUBTYPE_SH7750 is not set
CONFIG_CPU_SUBTYPE_SH7751=y
# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH73180 is not set
# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
CONFIG_MMU=y
CONFIG_CMDLINE_BOOL=y
CONFIG_CMDLINE="mem=64M console=ttySC0,115200 root=/dev/hda1"
@@ -92,6 +108,7 @@ CONFIG_MEMORY_SIZE=0x04000000
CONFIG_MEMORY_SET=y
# CONFIG_MEMORY_OVERRIDE is not set
CONFIG_SH_RTC=y
+CONFIG_SH_FPU=y
CONFIG_ZERO_PAGE_OFFSET=0x00010000
CONFIG_BOOT_LINK_OFFSET=0x00800000
CONFIG_CPU_LITTLE_ENDIAN=y
@@ -128,7 +145,6 @@ CONFIG_RTC_9701JE=y
#
# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
#
-CONFIG_ISA=y
CONFIG_PCI=y
CONFIG_SH_PCIDMA_NONCOHERENT=y
CONFIG_PCI_AUTO=y
@@ -137,16 +153,13 @@ CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
CONFIG_PCI_NAMES=y
#
-# PCMCIA/CardBus support
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
#
-CONFIG_PCMCIA=m
-# CONFIG_PCMCIA_DEBUG is not set
-CONFIG_YENTA=m
-CONFIG_CARDBUS=y
-# CONFIG_I82092 is not set
-# CONFIG_I82365 is not set
-# CONFIG_TCIC is not set
-CONFIG_PCMCIA_PROBE=y
#
# PCI Hotplug Support
@@ -154,7 +167,6 @@ CONFIG_PCMCIA_PROBE=y
CONFIG_HOTPLUG_PCI=y
# CONFIG_HOTPLUG_PCI_FAKE is not set
# CONFIG_HOTPLUG_PCI_CPCI is not set
-# CONFIG_HOTPLUG_PCI_PCIE is not set
# CONFIG_HOTPLUG_PCI_SHPC is not set
#
@@ -171,6 +183,8 @@ CONFIG_BINFMT_ELF=y
#
# Generic Driver Options
#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
# CONFIG_FW_LOADER is not set
#
@@ -186,24 +200,35 @@ CONFIG_BINFMT_ELF=y
#
# Plug and Play support
#
-# CONFIG_PNP is not set
#
# Block devices
#
# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_DEV_XD is not set
# CONFIG_BLK_CPQ_DA is not set
# CONFIG_BLK_CPQ_CISS_DA is not set
# CONFIG_BLK_DEV_DAC960 is not set
# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
# CONFIG_BLK_DEV_LOOP is not set
# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_CARMEL is not set
+# CONFIG_BLK_DEV_SX8 is not set
CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_INITRAMFS_SOURCE=""
# CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
#
# ATA/ATAPI/MFM/RLL support
@@ -215,14 +240,13 @@ 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 is not set
# CONFIG_BLK_DEV_IDETAPE is not set
# CONFIG_BLK_DEV_IDEFLOPPY is not set
# CONFIG_IDE_TASK_IOCTL is not set
-# CONFIG_IDE_TASKFILE_IO is not set
#
# IDE chipset support/bugfixes
@@ -231,7 +255,6 @@ CONFIG_IDE_GENERIC=y
# CONFIG_BLK_DEV_IDEPCI is not set
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,11 +265,6 @@ CONFIG_IDE_SH=y
# 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
@@ -289,6 +307,9 @@ CONFIG_INET=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
# CONFIG_IPV6 is not set
# CONFIG_NETFILTER is not set
@@ -308,13 +329,12 @@ CONFIG_INET=y
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_FASTROUTE is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
#
# QoS and/or fair queueing
#
# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
#
# Network testing
@@ -345,38 +365,19 @@ CONFIG_MII=y
# CONFIG_HAPPYMEAL is not set
# CONFIG_SUNGEM is not set
# CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_LANCE is not set
-# CONFIG_NET_VENDOR_SMC is not set
-# CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_SMC91X is not set
#
# Tulip family network device support
#
# CONFIG_NET_TULIP is not set
-# CONFIG_AT1700 is not set
-# CONFIG_DEPCA is not set
# CONFIG_HP100 is not set
-CONFIG_NET_ISA=y
-# CONFIG_E2100 is not set
-# CONFIG_EWRK3 is not set
-# CONFIG_EEXPRESS is not set
-# CONFIG_EEXPRESS_PRO is not set
-# CONFIG_HPLAN_PLUS is not set
-# CONFIG_HPLAN is not set
-# CONFIG_LP486E is not set
-# CONFIG_ETH16I is not set
-CONFIG_NE2000=m
-# CONFIG_ZNET is not set
-# CONFIG_SEEQ8005 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_AC3200 is not set
-# CONFIG_APRICOT is not set
# CONFIG_B44 is not set
# CONFIG_FORCEDETH is not set
-# CONFIG_CS89x0 is not set
# CONFIG_DGRS is not set
# CONFIG_EEPRO100 is not set
# CONFIG_E100 is not set
@@ -394,7 +395,6 @@ CONFIG_8139TOO=y
# CONFIG_SUNDANCE is not set
# CONFIG_TLAN is not set
# CONFIG_VIA_RHINE is not set
-# CONFIG_NET_POCKET is not set
#
# Ethernet (1000 Mbit)
@@ -407,6 +407,7 @@ CONFIG_8139TOO=y
# CONFIG_YELLOWFIN is not set
# CONFIG_R8169 is not set
# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
# CONFIG_TIGON3 is not set
#
@@ -429,20 +430,10 @@ CONFIG_NET_RADIO=y
# Obsolete Wireless cards support (pre-802.11)
#
# CONFIG_STRIP is not set
-# CONFIG_ARLAN is not set
-# CONFIG_WAVELAN is not set
-# CONFIG_PCMCIA_WAVELAN is not set
-# CONFIG_PCMCIA_NETWAVE is not set
-
-#
-# Wireless 802.11 Frequency Hopping cards support
-#
-# CONFIG_PCMCIA_RAYCS is not set
#
# Wireless 802.11b ISA/PCI cards support
#
-# CONFIG_AIRO is not set
CONFIG_HERMES=m
# CONFIG_PLX_HERMES is not set
# CONFIG_TMD_HERMES is not set
@@ -450,24 +441,12 @@ CONFIG_HERMES=m
# CONFIG_ATMEL is not set
#
-# Wireless 802.11b Pcmcia/Cardbus cards support
-#
-CONFIG_PCMCIA_HERMES=m
-# CONFIG_AIRO_CS is not set
-# CONFIG_PCMCIA_WL3501 is not set
-
-#
# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
#
# CONFIG_PRISM54 is not set
CONFIG_NET_WIRELESS=y
#
-# PCMCIA network device support
-#
-# CONFIG_NET_PCMCIA is not set
-
-#
# Wan interfaces
#
# CONFIG_WAN is not set
@@ -527,7 +506,6 @@ CONFIG_SOUND_GAMEPORT=y
# CONFIG_UNIX98_PTYS is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
-# CONFIG_QIC02_TAPE is not set
#
# IPMI
@@ -547,14 +525,7 @@ CONFIG_LEGACY_PTY_COUNT=256
#
# Ftape, the floppy tape device driver
#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
# CONFIG_DRM is not set
-
-#
-# PCMCIA character devices
-#
-# CONFIG_SYNCLINK_CS is not set
# CONFIG_RAW_DRIVER is not set
#
@@ -563,6 +534,11 @@ CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_I2C is not set
#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
# Misc devices
#
@@ -611,37 +587,12 @@ CONFIG_SND_OPL3_LIB=m
# CONFIG_SND_MPU401 is not set
#
-# ISA devices
-#
-# CONFIG_SND_AD1848 is not set
-# CONFIG_SND_CS4231 is not set
-# CONFIG_SND_CS4232 is not set
-# CONFIG_SND_CS4236 is not set
-# CONFIG_SND_ES1688 is not set
-# CONFIG_SND_ES18XX is not set
-# CONFIG_SND_GUSCLASSIC is not set
-# CONFIG_SND_GUSEXTREME is not set
-# CONFIG_SND_GUSMAX is not set
-# CONFIG_SND_INTERWAVE is not set
-# CONFIG_SND_INTERWAVE_STB is not set
-# CONFIG_SND_OPTI92X_AD1848 is not set
-# CONFIG_SND_OPTI92X_CS4231 is not set
-# CONFIG_SND_OPTI93X is not set
-# CONFIG_SND_SB8 is not set
-# CONFIG_SND_SB16 is not set
-# CONFIG_SND_SBAWE is not set
-# CONFIG_SND_WAVEFRONT is not set
-# CONFIG_SND_CMI8330 is not set
-# CONFIG_SND_OPL3SA2 is not set
-# CONFIG_SND_SGALAXY is not set
-# CONFIG_SND_SSCAPE is not set
-
-#
# PCI devices
#
CONFIG_SND_AC97_CODEC=m
# CONFIG_SND_ALI5451 is not set
# CONFIG_SND_ATIIXP is not set
+# CONFIG_SND_ATIIXP_MODEM is not set
# CONFIG_SND_AU8810 is not set
# CONFIG_SND_AU8820 is not set
# CONFIG_SND_AU8830 is not set
@@ -650,6 +601,8 @@ CONFIG_SND_AC97_CODEC=m
# CONFIG_SND_CS46XX is not set
# CONFIG_SND_CS4281 is not set
# CONFIG_SND_EMU10K1 is not set
+# CONFIG_SND_EMU10K1X is not set
+# CONFIG_SND_CA0106 is not set
# CONFIG_SND_KORG1212 is not set
# CONFIG_SND_MIXART is not set
# CONFIG_SND_NM256 is not set
@@ -673,16 +626,10 @@ CONFIG_SND_YMFPCI=m
# CONFIG_SND_INTEL8X0M is not set
# CONFIG_SND_SONICVIBES is not set
# CONFIG_SND_VIA82XX is not set
+# CONFIG_SND_VIA82XX_MODEM is not set
# CONFIG_SND_VX222 is not set
#
-# PCMCIA devices
-#
-# CONFIG_SND_VXPOCKET is not set
-# CONFIG_SND_VXP440 is not set
-# CONFIG_SND_PDAUDIOCF is not set
-
-#
# Open Sound System
#
CONFIG_SOUND_PRIME=m
@@ -713,6 +660,12 @@ CONFIG_SOUND_VOYAGERGX=m
# USB support
#
# CONFIG_USB is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
#
# USB Gadget Support
@@ -720,6 +673,16 @@ CONFIG_SOUND_VOYAGERGX=m
# CONFIG_USB_GADGET is not set
#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -728,10 +691,15 @@ CONFIG_EXT2_FS=y
# CONFIG_JBD is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
# CONFIG_XFS_FS is not set
CONFIG_MINIX_FS=y
# CONFIG_ROMFS_FS is not set
# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
@@ -747,6 +715,8 @@ CONFIG_MINIX_FS=y
CONFIG_FAT_FS=y
CONFIG_MSDOS_FS=y
CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
# CONFIG_NTFS_FS is not set
#
@@ -783,7 +753,6 @@ CONFIG_RAMFS=y
#
# CONFIG_NFS_FS is not set
# CONFIG_NFSD is not set
-# CONFIG_EXPORTFS is not set
# CONFIG_SMB_FS is not set
# CONFIG_CIFS is not set
# CONFIG_NCP_FS is not set
@@ -824,6 +793,7 @@ CONFIG_NLS_CODEPAGE_932=y
# 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
@@ -848,17 +818,16 @@ CONFIG_OPROFILE=y
#
# Kernel hacking
#
-# CONFIG_MAGIC_SYSRQ is not set
-# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_FRAME_POINTER is not set
# CONFIG_SH_STANDARD_BIOS is not set
# CONFIG_EARLY_SCIF_CONSOLE is not set
# CONFIG_KGDB is not set
-# CONFIG_FRAME_POINTER is not set
#
# Security options
#
+# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
#
@@ -867,7 +836,12 @@ CONFIG_OPROFILE=y
# CONFIG_CRYPTO is not set
#
+# Hardware crypto devices
+#
+
+#
# Library routines
#
+# CONFIG_CRC_CCITT is not set
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
diff --git a/arch/sh/configs/se7300_defconfig b/arch/sh/configs/se7300_defconfig
index 842ca47a684ec..4b71cd692fa5f 100644
--- a/arch/sh/configs/se7300_defconfig
+++ b/arch/sh/configs/se7300_defconfig
@@ -1,24 +1,28 @@
#
# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-sh
+# Wed Mar 2 15:09:43 2005
#
CONFIG_SUPERH=y
CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
CONFIG_CLEAN_COMPILE=y
-CONFIG_STANDALONE=y
CONFIG_BROKEN_ON_SMP=y
#
# General setup
#
+CONFIG_LOCALVERSION=""
# CONFIG_SWAP is not set
# CONFIG_SYSVIPC is not set
-# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
@@ -29,11 +33,13 @@ CONFIG_EMBEDDED=y
# CONFIG_KALLSYMS is not set
# CONFIG_FUTEX is not set
# CONFIG_EPOLL is not set
-CONFIG_IOSCHED_NOOP=y
-# CONFIG_IOSCHED_AS is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ 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
#
# Loadable module support
@@ -46,6 +52,7 @@ CONFIG_IOSCHED_NOOP=y
# CONFIG_SH_SOLUTION_ENGINE is not set
# CONFIG_SH_7751_SOLUTION_ENGINE is not set
CONFIG_SH_7300_SOLUTION_ENGINE=y
+# CONFIG_SH_73180_SOLUTION_ENGINE is not set
# CONFIG_SH_7751_SYSTEMH is not set
# CONFIG_SH_STB1_HARP is not set
# CONFIG_SH_STB1_OVERDRIVE is not set
@@ -62,23 +69,29 @@ CONFIG_SH_7300_SOLUTION_ENGINE=y
# CONFIG_SH_SH2000 is not set
# CONFIG_SH_ADX is not set
# CONFIG_SH_MPC1211 is not set
+# CONFIG_SH_SH03 is not set
# CONFIG_SH_SECUREEDGE5410 is not set
# CONFIG_SH_HS7751RVOIP is not set
# CONFIG_SH_RTS7751R2D is not set
+# CONFIG_SH_EDOSK7705 is not set
+# CONFIG_SH_SH4202_MICRODEV is not set
# CONFIG_SH_UNKNOWN is not set
# CONFIG_CPU_SH2 is not set
CONFIG_CPU_SH3=y
# CONFIG_CPU_SH4 is not set
# CONFIG_CPU_SUBTYPE_SH7604 is not set
CONFIG_CPU_SUBTYPE_SH7300=y
+# 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 is not set
# CONFIG_CPU_SUBTYPE_SH7750 is not set
# CONFIG_CPU_SUBTYPE_SH7751 is not set
# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH73180 is not set
# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
CONFIG_MMU=y
CONFIG_CMDLINE_BOOL=y
CONFIG_CMDLINE="console=ttySC0,38400 root=/dev/ram0"
@@ -120,6 +133,19 @@ CONFIG_HEARTBEAT=y
# CONFIG_PCI is not set
#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+
+#
# Executable file formats
#
CONFIG_BINFMT_ELF=y
@@ -139,6 +165,9 @@ CONFIG_EMBEDDED_RAMDISK_IMAGE="ramdisk.gz"
#
# Generic Driver Options
#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
#
# Memory Technology Devices (MTD)
@@ -158,11 +187,23 @@ CONFIG_EMBEDDED_RAMDISK_IMAGE="ramdisk.gz"
# 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 is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
#
# ATA/ATAPI/MFM/RLL support
@@ -186,7 +227,6 @@ CONFIG_BLK_DEV_INITRD=y
#
# IEEE 1394 (FireWire) support
#
-# CONFIG_IEEE1394 is not set
#
# I2O device support
@@ -234,6 +274,8 @@ CONFIG_SERIO=y
# CONFIG_SERIO_I8042 is not set
# CONFIG_SERIO_SERPORT is not set
# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_LIBPS2 is not set
+# CONFIG_SERIO_RAW is not set
#
# Input Device Drivers
@@ -264,7 +306,6 @@ CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_UNIX98_PTYS is not set
# CONFIG_LEGACY_PTYS is not set
-# CONFIG_QIC02_TAPE is not set
#
# IPMI
@@ -274,6 +315,7 @@ CONFIG_IPMI_HANDLER=y
CONFIG_IPMI_DEVICE_INTERFACE=y
# CONFIG_IPMI_SI is not set
CONFIG_IPMI_WATCHDOG=y
+# CONFIG_IPMI_POWEROFF is not set
#
# Watchdog Cards
@@ -290,13 +332,10 @@ CONFIG_SOFT_WATCHDOG=y
# CONFIG_GEN_RTC is not set
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
#
# Ftape, the floppy tape device driver
#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
# CONFIG_DRM is not set
# CONFIG_RAW_DRIVER is not set
@@ -306,6 +345,11 @@ CONFIG_SOFT_WATCHDOG=y
# CONFIG_I2C is not set
#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
# Misc devices
#
@@ -331,6 +375,12 @@ CONFIG_SOFT_WATCHDOG=y
#
# USB support
#
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
#
# USB Gadget Support
@@ -338,6 +388,16 @@ CONFIG_SOFT_WATCHDOG=y
# CONFIG_USB_GADGET is not set
#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -346,10 +406,15 @@ CONFIG_EXT2_FS=y
# CONFIG_JBD is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
# CONFIG_XFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
@@ -362,7 +427,8 @@ CONFIG_EXT2_FS=y
#
# DOS/FAT/NT Filesystems
#
-# CONFIG_FAT_FS is not set
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
# CONFIG_NTFS_FS is not set
#
@@ -415,9 +481,8 @@ CONFIG_MSDOS_PARTITION=y
#
# Kernel hacking
#
-# CONFIG_MAGIC_SYSRQ is not set
-# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_FRAME_POINTER is not set
CONFIG_SH_STANDARD_BIOS=y
CONFIG_EARLY_PRINTK=y
CONFIG_KGDB=y
@@ -442,11 +507,11 @@ CONFIG_KGDB_DEFPARITY_N=y
# CONFIG_KGDB_DEFPARITY_O is not set
CONFIG_KGDB_DEFBITS_8=y
# CONFIG_KGDB_DEFBITS_7 is not set
-# CONFIG_FRAME_POINTER is not set
#
# Security options
#
+# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
#
@@ -455,7 +520,12 @@ CONFIG_KGDB_DEFBITS_8=y
# CONFIG_CRYPTO is not set
#
+# Hardware crypto devices
+#
+
+#
# Library routines
#
+# CONFIG_CRC_CCITT is not set
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
diff --git a/arch/sh/configs/se73180_defconfig b/arch/sh/configs/se73180_defconfig
index 1d5884dd9d048..d217e44c89a6a 100644
--- a/arch/sh/configs/se73180_defconfig
+++ b/arch/sh/configs/se73180_defconfig
@@ -1,24 +1,28 @@
#
# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-sh
+# Wed Mar 2 15:09:44 2005
#
CONFIG_SUPERH=y
CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
CONFIG_CLEAN_COMPILE=y
-CONFIG_STANDALONE=y
CONFIG_BROKEN_ON_SMP=y
#
# General setup
#
+CONFIG_LOCALVERSION=""
CONFIG_SWAP=y
# CONFIG_SYSVIPC is not set
-# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_SYSCTL is not set
# CONFIG_AUDIT is not set
@@ -29,11 +33,13 @@ CONFIG_EMBEDDED=y
# CONFIG_KALLSYMS is not set
# CONFIG_FUTEX is not set
# CONFIG_EPOLL is not set
-CONFIG_IOSCHED_NOOP=y
-# CONFIG_IOSCHED_AS is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ 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
#
# Loadable module support
@@ -42,6 +48,7 @@ CONFIG_MODULES=y
# CONFIG_MODULE_UNLOAD is not set
CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
# CONFIG_KMOD is not set
#
@@ -67,9 +74,12 @@ CONFIG_SH_73180_SOLUTION_ENGINE=y
# CONFIG_SH_SH2000 is not set
# CONFIG_SH_ADX is not set
# CONFIG_SH_MPC1211 is not set
+# CONFIG_SH_SH03 is not set
# CONFIG_SH_SECUREEDGE5410 is not set
# CONFIG_SH_HS7751RVOIP is not set
# CONFIG_SH_RTS7751R2D is not set
+# CONFIG_SH_EDOSK7705 is not set
+# CONFIG_SH_SH4202_MICRODEV is not set
# CONFIG_SH_UNKNOWN is not set
# CONFIG_CPU_SH2 is not set
# CONFIG_CPU_SH3 is not set
@@ -86,6 +96,7 @@ CONFIG_CPU_SH4=y
CONFIG_CPU_SUBTYPE_SH73180=y
# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
CONFIG_MMU=y
CONFIG_CMDLINE_BOOL=y
CONFIG_CMDLINE="console=ttySC0,38400 root=/dev/ram"
@@ -127,6 +138,19 @@ CONFIG_HEARTBEAT=y
# CONFIG_PCI is not set
#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+
+#
# Executable file formats
#
CONFIG_BINFMT_ELF=y
@@ -146,6 +170,9 @@ CONFIG_EMBEDDED_RAMDISK_IMAGE="ramdisk.gz"
#
# Generic Driver Options
#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
#
# Memory Technology Devices (MTD)
@@ -165,12 +192,24 @@ CONFIG_EMBEDDED_RAMDISK_IMAGE="ramdisk.gz"
# 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_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 is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
#
# ATA/ATAPI/MFM/RLL support
@@ -194,7 +233,6 @@ CONFIG_BLK_DEV_INITRD=y
#
# IEEE 1394 (FireWire) support
#
-# CONFIG_IEEE1394 is not set
#
# I2O device support
@@ -257,7 +295,6 @@ CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_UNIX98_PTYS is not set
# CONFIG_LEGACY_PTYS is not set
-# CONFIG_QIC02_TAPE is not set
#
# IPMI
@@ -279,13 +316,10 @@ CONFIG_WATCHDOG=y
# CONFIG_GEN_RTC is not set
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
#
# Ftape, the floppy tape device driver
#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
# CONFIG_DRM is not set
# CONFIG_RAW_DRIVER is not set
@@ -295,6 +329,11 @@ CONFIG_WATCHDOG=y
# CONFIG_I2C is not set
#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
# Misc devices
#
@@ -320,6 +359,12 @@ CONFIG_WATCHDOG=y
#
# USB support
#
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
#
# USB Gadget Support
@@ -327,6 +372,16 @@ CONFIG_WATCHDOG=y
# CONFIG_USB_GADGET is not set
#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -335,10 +390,15 @@ CONFIG_EXT2_FS=y
# CONFIG_JBD is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
# CONFIG_XFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
@@ -351,7 +411,8 @@ CONFIG_EXT2_FS=y
#
# DOS/FAT/NT Filesystems
#
-# CONFIG_FAT_FS is not set
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
# CONFIG_NTFS_FS is not set
#
@@ -364,6 +425,7 @@ CONFIG_DEVFS_FS=y
CONFIG_DEVFS_MOUNT=y
# CONFIG_DEVFS_DEBUG is not set
CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
# CONFIG_HUGETLBFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
@@ -404,18 +466,17 @@ CONFIG_MSDOS_PARTITION=y
#
# Kernel hacking
#
-# CONFIG_MAGIC_SYSRQ is not set
-# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_FRAME_POINTER is not set
CONFIG_SH_STANDARD_BIOS=y
# CONFIG_EARLY_SCIF_CONSOLE is not set
# CONFIG_EARLY_PRINTK is not set
# CONFIG_KGDB is not set
-# CONFIG_FRAME_POINTER is not set
#
# Security options
#
+# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
#
@@ -424,7 +485,12 @@ CONFIG_SH_STANDARD_BIOS=y
# CONFIG_CRYPTO is not set
#
+# Hardware crypto devices
+#
+
+#
# Library routines
#
+# CONFIG_CRC_CCITT is not set
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
diff --git a/arch/sh/configs/se7705_defconfig b/arch/sh/configs/se7705_defconfig
index bf48af3a20f89..e4a14602b169a 100644
--- a/arch/sh/configs/se7705_defconfig
+++ b/arch/sh/configs/se7705_defconfig
@@ -1,9 +1,14 @@
#
# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-sh
+# Wed Mar 2 15:09:45 2005
#
CONFIG_SUPERH=y
CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
#
# Code maturity level options
@@ -11,10 +16,12 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_EXPERIMENTAL=y
CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
#
# General setup
#
+CONFIG_LOCALVERSION=""
# CONFIG_SWAP is not set
# CONFIG_SYSVIPC is not set
# CONFIG_POSIX_MQUEUE is not set
@@ -23,16 +30,19 @@ CONFIG_BROKEN_ON_SMP=y
# CONFIG_AUDIT is not set
CONFIG_LOG_BUF_SHIFT=14
# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
# CONFIG_IKCONFIG is not set
CONFIG_EMBEDDED=y
# CONFIG_KALLSYMS is not set
CONFIG_FUTEX=y
CONFIG_EPOLL=y
-# CONFIG_IOSCHED_NOOP is not set
-CONFIG_IOSCHED_AS=y
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ 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
#
# Loadable module support
@@ -41,6 +51,7 @@ CONFIG_MODULES=y
# CONFIG_MODULE_UNLOAD is not set
CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_KMOD=y
#
@@ -66,6 +77,7 @@ CONFIG_SH_SOLUTION_ENGINE=y
# CONFIG_SH_SH2000 is not set
# CONFIG_SH_ADX is not set
# CONFIG_SH_MPC1211 is not set
+# CONFIG_SH_SH03 is not set
# CONFIG_SH_SECUREEDGE5410 is not set
# CONFIG_SH_HS7751RVOIP is not set
# CONFIG_SH_RTS7751R2D is not set
@@ -132,6 +144,19 @@ CONFIG_HEARTBEAT=y
# CONFIG_PCI is not set
#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+
+#
# Executable file formats
#
CONFIG_BINFMT_ELF=y
@@ -152,6 +177,7 @@ CONFIG_BINFMT_ELF=y
#
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
#
# Memory Technology Devices (MTD)
@@ -215,6 +241,7 @@ CONFIG_MTD_SUPERH_RESERVE=0x300000
# 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
@@ -241,12 +268,25 @@ CONFIG_MTD_SUPERH_RESERVE=0x300000
# Block devices
#
# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
# CONFIG_BLK_DEV_LOOP is not set
# CONFIG_BLK_DEV_NBD is not set
CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=8192
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 is not set
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_ATA_OVER_ETH is not set
#
# ATA/ATAPI/MFM/RLL support
@@ -302,6 +342,9 @@ CONFIG_IP_PNP_RARP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
# CONFIG_IPV6 is not set
# CONFIG_NETFILTER is not set
@@ -321,7 +364,6 @@ CONFIG_IP_PNP_RARP=y
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
#
# QoS and/or fair queueing
@@ -350,6 +392,7 @@ CONFIG_NETDEVICES=y
CONFIG_NET_ETHERNET=y
# CONFIG_MII is not set
CONFIG_STNIC=y
+# CONFIG_SMC91X is not set
#
# Ethernet (1000 Mbit)
@@ -417,6 +460,8 @@ CONFIG_SERIO=y
# CONFIG_SERIO_I8042 is not set
# CONFIG_SERIO_SERPORT is not set
# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_LIBPS2 is not set
+# CONFIG_SERIO_RAW is not set
#
# Input Device Drivers
@@ -447,7 +492,6 @@ CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
# CONFIG_LEGACY_PTYS is not set
-# CONFIG_QIC02_TAPE is not set
#
# IPMI
@@ -466,7 +510,6 @@ CONFIG_UNIX98_PTYS=y
#
# Ftape, the floppy tape device driver
#
-# CONFIG_AGP is not set
# CONFIG_DRM is not set
# CONFIG_RAW_DRIVER is not set
@@ -507,6 +550,12 @@ CONFIG_UNIX98_PTYS=y
#
# USB support
#
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
#
# USB Gadget Support
@@ -514,6 +563,16 @@ CONFIG_UNIX98_PTYS=y
# CONFIG_USB_GADGET is not set
#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -522,10 +581,15 @@ CONFIG_EXT2_FS=y
# CONFIG_JBD is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
# CONFIG_XFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
@@ -569,6 +633,7 @@ CONFIG_RAMFS=y
CONFIG_JFFS2_FS=y
CONFIG_JFFS2_FS_DEBUG=0
# CONFIG_JFFS2_FS_NAND is not set
+# CONFIG_JFFS2_FS_NOR_ECC is not set
# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
CONFIG_JFFS2_ZLIB=y
CONFIG_JFFS2_RTIME=y
@@ -590,9 +655,9 @@ CONFIG_NFS_FS=y
# CONFIG_NFSD is not set
CONFIG_ROOT_NFS=y
CONFIG_LOCKD=y
-# CONFIG_EXPORTFS is not set
CONFIG_SUNRPC=y
# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
# CONFIG_CIFS is not set
# CONFIG_NCP_FS is not set
@@ -618,16 +683,16 @@ CONFIG_MSDOS_PARTITION=y
#
# Kernel hacking
#
-# CONFIG_MAGIC_SYSRQ is not set
-# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_DEBUG_PREEMPT=y
+# CONFIG_FRAME_POINTER is not set
# CONFIG_SH_STANDARD_BIOS is not set
# CONFIG_KGDB is not set
-# CONFIG_FRAME_POINTER is not set
#
# Security options
#
+# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
#
@@ -636,6 +701,10 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_CRYPTO is not set
#
+# Hardware crypto devices
+#
+
+#
# Library routines
#
CONFIG_CRC_CCITT=y
diff --git a/arch/sh/configs/se7750_defconfig b/arch/sh/configs/se7750_defconfig
new file mode 100644
index 0000000000000..6dc31584752a7
--- /dev/null
+++ b/arch/sh/configs/se7750_defconfig
@@ -0,0 +1,713 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-sh
+# Wed Mar 2 15:09:46 2005
+#
+CONFIG_SUPERH=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+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
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODULE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# System type
+#
+CONFIG_SH_SOLUTION_ENGINE=y
+# CONFIG_SH_7751_SOLUTION_ENGINE is not set
+# CONFIG_SH_7300_SOLUTION_ENGINE is not set
+# CONFIG_SH_73180_SOLUTION_ENGINE is not set
+# 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 is not set
+# CONFIG_SH_HP690 is not set
+# CONFIG_SH_CQREEK is not set
+# CONFIG_SH_DMIDA is not set
+# CONFIG_SH_EC3104 is not set
+# CONFIG_SH_SATURN is not set
+# CONFIG_SH_DREAMCAST is not set
+# CONFIG_SH_CAT68701 is not set
+# CONFIG_SH_BIGSUR is not set
+# CONFIG_SH_SH2000 is not set
+# CONFIG_SH_ADX is not set
+# CONFIG_SH_MPC1211 is not set
+# CONFIG_SH_SH03 is not set
+# CONFIG_SH_SECUREEDGE5410 is not set
+# CONFIG_SH_HS7751RVOIP is not set
+# CONFIG_SH_RTS7751R2D is not set
+# CONFIG_SH_EDOSK7705 is not set
+# CONFIG_SH_SH4202_MICRODEV is not set
+# CONFIG_SH_UNKNOWN is not set
+# CONFIG_CPU_SH2 is not set
+# CONFIG_CPU_SH3 is not set
+CONFIG_CPU_SH4=y
+# CONFIG_CPU_SUBTYPE_SH7604 is not set
+# 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 is not set
+CONFIG_CPU_SUBTYPE_SH7750=y
+# CONFIG_CPU_SUBTYPE_SH7751 is not set
+# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH73180 is not set
+# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
+# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
+CONFIG_MMU=y
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=ttySC1,38400 root=/dev/nfs ip=bootp"
+CONFIG_MEMORY_START=0x0c000000
+CONFIG_MEMORY_SIZE=0x02000000
+CONFIG_MEMORY_SET=y
+# CONFIG_MEMORY_OVERRIDE is not set
+CONFIG_CF_ENABLER=y
+# CONFIG_CF_AREA5 is not set
+CONFIG_CF_AREA6=y
+CONFIG_CF_BASE_ADDR=0xb8000000
+CONFIG_SH_RTC=y
+CONFIG_SH_FPU=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_SH_STORE_QUEUES is not set
+# CONFIG_SMP is not set
+CONFIG_SH_PCLK_CALC=y
+CONFIG_SH_PCLK_FREQ=49876504
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
+# CONFIG_SH_DMA is not set
+
+#
+# Companion Chips
+#
+# CONFIG_HD6446X_SERIES is not set
+CONFIG_HEARTBEAT=y
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+# CONFIG_PCI is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_FLAT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_CONCAT is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS 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=y
+# 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_SOLUTIONENGINE=y
+CONFIG_MTD_SUPERH_RESERVE=0x00010000
+# CONFIG_MTD_MPC1211 is not set
+# CONFIG_MTD_RTS7751R2D 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
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND 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_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+CONFIG_STNIC=y
+# CONFIG_SMC91X 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
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Userland interfaces
+#
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_SERIO is not set
+# CONFIG_SERIO_I8042 is not set
+
+#
+# Input Device Drivers
+#
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_CONSOLE is not set
+CONFIG_SERIAL_8250_NR_UARTS=2
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_SH_WDT=y
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS 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_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_JFFS2_FS_NAND is not set
+# CONFIG_JFFS2_FS_NOR_ECC is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 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_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+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
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_FRAME_POINTER is not set
+# CONFIG_SH_STANDARD_BIOS is not set
+# CONFIG_EARLY_SCIF_CONSOLE is not set
+# CONFIG_KGDB 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_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/sh/configs/se7751_defconfig b/arch/sh/configs/se7751_defconfig
index 6501d94ff2833..1ce0289474595 100644
--- a/arch/sh/configs/se7751_defconfig
+++ b/arch/sh/configs/se7751_defconfig
@@ -1,34 +1,49 @@
#
# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-sh
+# Wed Mar 2 15:09:48 2005
#
CONFIG_SUPERH=y
CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
CONFIG_CLEAN_COMPILE=y
-CONFIG_STANDALONE=y
CONFIG_BROKEN_ON_SMP=y
#
# General setup
#
+CONFIG_LOCALVERSION=""
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
# CONFIG_IKCONFIG is not set
CONFIG_EMBEDDED=y
CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
CONFIG_FUTEX=y
CONFIG_EPOLL=y
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=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
#
# Loadable module support
@@ -37,6 +52,7 @@ CONFIG_MODULES=y
# CONFIG_MODULE_UNLOAD is not set
CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
# CONFIG_KMOD is not set
#
@@ -44,6 +60,8 @@ CONFIG_OBSOLETE_MODPARM=y
#
# CONFIG_SH_SOLUTION_ENGINE is not set
CONFIG_SH_7751_SOLUTION_ENGINE=y
+# CONFIG_SH_7300_SOLUTION_ENGINE is not set
+# CONFIG_SH_73180_SOLUTION_ENGINE is not set
# CONFIG_SH_7751_SYSTEMH is not set
# CONFIG_SH_STB1_HARP is not set
# CONFIG_SH_STB1_OVERDRIVE is not set
@@ -60,20 +78,29 @@ CONFIG_SH_7751_SOLUTION_ENGINE=y
# CONFIG_SH_SH2000 is not set
# CONFIG_SH_ADX is not set
# CONFIG_SH_MPC1211 is not set
+# CONFIG_SH_SH03 is not set
# CONFIG_SH_SECUREEDGE5410 is not set
+# CONFIG_SH_HS7751RVOIP is not set
+# CONFIG_SH_RTS7751R2D is not set
+# CONFIG_SH_EDOSK7705 is not set
+# CONFIG_SH_SH4202_MICRODEV is not set
# CONFIG_SH_UNKNOWN is not set
# CONFIG_CPU_SH2 is not set
# CONFIG_CPU_SH3 is not set
CONFIG_CPU_SH4=y
# CONFIG_CPU_SUBTYPE_SH7604 is not set
# 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 is not set
# CONFIG_CPU_SUBTYPE_SH7750 is not set
CONFIG_CPU_SUBTYPE_SH7751=y
# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH73180 is not set
# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
+# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
CONFIG_MMU=y
CONFIG_CMDLINE_BOOL=y
CONFIG_CMDLINE="console=ttySC1,38400"
@@ -82,6 +109,7 @@ CONFIG_MEMORY_SIZE=0x04000000
CONFIG_MEMORY_SET=y
# CONFIG_MEMORY_OVERRIDE is not set
CONFIG_SH_RTC=y
+CONFIG_SH_FPU=y
CONFIG_ZERO_PAGE_OFFSET=0x00010000
CONFIG_BOOT_LINK_OFFSET=0x00800000
CONFIG_CPU_LITTLE_ENDIAN=y
@@ -91,21 +119,48 @@ CONFIG_CPU_LITTLE_ENDIAN=y
# CONFIG_SH_OCRAM is not set
# CONFIG_SH_STORE_QUEUES is not set
# CONFIG_SMP is not set
+CONFIG_SH_PCLK_CALC=y
CONFIG_SH_PCLK_FREQ=60013568
+
+#
+# CPU Frequency scaling
+#
# CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
# CONFIG_SH_DMA is not set
#
+# Companion Chips
+#
+# CONFIG_HD6446X_SERIES is not set
+CONFIG_HEARTBEAT=y
+
+#
# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
#
CONFIG_PCI=y
# CONFIG_SH_PCIDMA_NONCOHERENT is not set
CONFIG_PCI_AUTO=y
CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
-CONFIG_PCI_DMA=y
# CONFIG_PCI_LEGACY_PROC is not set
# CONFIG_PCI_NAMES is not set
-# CONFIG_HOTPLUG is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
#
# Executable file formats
@@ -115,8 +170,20 @@ CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
#
+# SH initrd options
+#
+# CONFIG_EMBEDDED_RAMDISK is not set
+
+#
+# Device Drivers
+#
+
+#
# Generic Driver Options
#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
#
# Memory Technology Devices (MTD)
@@ -144,28 +211,43 @@ 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=y
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
#
# Mapping drivers for chip access
#
# CONFIG_MTD_COMPLEX_MAPPINGS is not set
# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_SOLUTIONENGINE is not set
# CONFIG_MTD_MPC1211 is not set
+# CONFIG_MTD_RTS7751R2D 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
@@ -185,6 +267,10 @@ CONFIG_MTD_RAM=y
# CONFIG_PARPORT is not set
#
+# Plug and Play support
+#
+
+#
# Block devices
#
# CONFIG_BLK_DEV_FD is not set
@@ -192,12 +278,26 @@ CONFIG_MTD_RAM=y
# CONFIG_BLK_CPQ_CISS_DA is not set
# CONFIG_BLK_DEV_DAC960 is not set
# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
# CONFIG_BLK_DEV_LOOP is not set
# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
# CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
#
# ATA/ATAPI/MFM/RLL support
@@ -215,11 +315,20 @@ CONFIG_BLK_DEV_INITRD=y
# CONFIG_MD is not set
#
-# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
#
# CONFIG_IEEE1394 is not set
#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
# Networking support
#
CONFIG_NET=y
@@ -243,19 +352,19 @@ CONFIG_IP_PNP_RARP=y
# CONFIG_NET_IPGRE is not set
# CONFIG_IP_MROUTE is not set
# CONFIG_ARPD is not set
-# CONFIG_INET_ECN is not set
# CONFIG_SYN_COOKIES is not set
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
#
# IP: Virtual Server Configuration
#
# CONFIG_IP_VS is not set
# CONFIG_IPV6 is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
CONFIG_NETFILTER=y
CONFIG_NETFILTER_DEBUG=y
@@ -263,19 +372,19 @@ CONFIG_NETFILTER_DEBUG=y
# IP: Netfilter Configuration
#
# CONFIG_IP_NF_CONNTRACK is not set
+# CONFIG_IP_NF_CONNTRACK_MARK is not set
CONFIG_IP_NF_QUEUE=y
# CONFIG_IP_NF_IPTABLES is not set
# CONFIG_IP_NF_ARPTABLES is not set
-# CONFIG_IP_NF_COMPAT_IPCHAINS is not set
-# CONFIG_IP_NF_COMPAT_IPFWADM is not set
#
# SCTP Configuration (EXPERIMENTAL)
#
-CONFIG_IPV6_SCTP__=y
# 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
@@ -284,24 +393,23 @@ CONFIG_IPV6_SCTP__=y
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_FASTROUTE is not set
-# CONFIG_NET_HW_FLOWCONTROL 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
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
@@ -309,6 +417,11 @@ CONFIG_NETDEVICES=y
# CONFIG_ETHERTAP is not set
#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
# Ethernet (10 or 100Mbit)
#
CONFIG_NET_ETHERNET=y
@@ -317,6 +430,7 @@ CONFIG_MII=y
# CONFIG_HAPPYMEAL is not set
# CONFIG_SUNGEM is not set
# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_SMC91X is not set
#
# Tulip family network device support
@@ -328,6 +442,7 @@ 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
@@ -352,55 +467,41 @@ CONFIG_PCNET32=y
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
# CONFIG_R8169 is not set
-# CONFIG_SIS190 is not set
# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
# CONFIG_TIGON3 is not set
#
# Ethernet (10000 Mbit)
#
# CONFIG_IXGB is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
+# CONFIG_S2IO is not set
#
# Token Ring devices
#
# CONFIG_TR is not set
-# CONFIG_RCPCI is not set
-# CONFIG_SHAPER is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
+# Wireless LAN (non-hamradio)
#
-# CONFIG_IRDA is not set
+# CONFIG_NET_RADIO is not set
#
-# Bluetooth support
+# Wan interfaces
#
-# CONFIG_BT is not set
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
#
# ISDN subsystem
#
-# CONFIG_ISDN_BOOL is not set
+# CONFIG_ISDN is not set
#
# Telephony Support
@@ -432,35 +533,54 @@ CONFIG_SOUND_GAMEPORT=y
# Character devices
#
# CONFIG_VT is not set
-# CONFIG_SERIAL is not set
-CONFIG_SH_SCI=y
-CONFIG_SERIAL_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
#
-# Unix 98 PTY support
+# Non-8250 serial port support
#
+# CONFIG_SERIAL_SH_SCI is not set
CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
-CONFIG_HEARTBEAT=y
-# CONFIG_PSMOUSE is not set
+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_SH_WDT is not set
-# CONFIG_RTC is not set
#
-# Serial drivers
+# PCI-based Watchdog Cards
#
-# CONFIG_SERIAL_8250 is not set
+# CONFIG_PCIPCWATCHDOG is not set
+# CONFIG_WDTPCI is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
#
-# Non-8250 serial port support
+# Ftape, the floppy tape device driver
#
-# CONFIG_SERIAL_SH_SCI is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
#
# I2C support
@@ -468,17 +588,59 @@ CONFIG_WATCHDOG=y
# CONFIG_I2C is not set
#
-# I2C Algorithms
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
#
#
-# I2C Hardware Bus support
+# USB Gadget Support
#
+# CONFIG_USB_GADGET is not set
#
-# I2C Hardware Sensors Chip support
+# MMC/SD Card support
#
-# CONFIG_I2C_SENSOR is not set
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
#
# File systems
@@ -489,10 +651,15 @@ CONFIG_EXT2_FS=y
# CONFIG_JBD is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
# CONFIG_XFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
@@ -505,7 +672,8 @@ CONFIG_EXT2_FS=y
#
# DOS/FAT/NT Filesystems
#
-# CONFIG_FAT_FS is not set
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
# CONFIG_NTFS_FS is not set
#
@@ -513,10 +681,12 @@ CONFIG_EXT2_FS=y
#
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS=y
# CONFIG_DEVPTS_FS_XATTR is not set
CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLBFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
@@ -526,6 +696,7 @@ CONFIG_RAMFS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
# CONFIG_BEFS_FS is not set
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
@@ -533,6 +704,11 @@ CONFIG_RAMFS=y
CONFIG_JFFS2_FS=y
CONFIG_JFFS2_FS_DEBUG=0
# CONFIG_JFFS2_FS_NAND is not set
+# CONFIG_JFFS2_FS_NOR_ECC is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
# CONFIG_CRAMFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_HPFS_FS is not set
@@ -545,12 +721,10 @@ CONFIG_JFFS2_FS_DEBUG=0
#
# CONFIG_NFS_FS is not set
# CONFIG_NFSD is not set
-# CONFIG_EXPORTFS is not set
# CONFIG_SMB_FS is not set
# CONFIG_CIFS is not set
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
# CONFIG_AFS_FS is not set
#
@@ -560,30 +734,9 @@ CONFIG_JFFS2_FS_DEBUG=0
CONFIG_MSDOS_PARTITION=y
#
-# Multimedia devices
+# Native Language Support
#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# Graphics support
-#
-# CONFIG_FB is not set
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-# CONFIG_USB is not set
-# CONFIG_USB_GADGET is not set
+# CONFIG_NLS is not set
#
# Profiling support
@@ -593,15 +746,16 @@ CONFIG_MSDOS_PARTITION=y
#
# Kernel hacking
#
-# CONFIG_MAGIC_SYSRQ is not set
-# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_FRAME_POINTER is not set
# CONFIG_SH_STANDARD_BIOS is not set
+# CONFIG_EARLY_SCIF_CONSOLE is not set
# CONFIG_KGDB is not set
-# CONFIG_FRAME_POINTER is not set
#
# Security options
#
+# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
#
@@ -610,8 +764,14 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_CRYPTO is not set
#
+# Hardware crypto devices
+#
+
+#
# Library routines
#
+# CONFIG_CRC_CCITT is not set
CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/sh/configs/sh03_defconfig b/arch/sh/configs/sh03_defconfig
index 100d08fbf9775..078f78c7fe53b 100644
--- a/arch/sh/configs/sh03_defconfig
+++ b/arch/sh/configs/sh03_defconfig
@@ -1,9 +1,14 @@
#
# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-sh
+# Wed Mar 2 15:09:49 2005
#
CONFIG_SUPERH=y
CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
#
# Code maturity level options
@@ -12,10 +17,12 @@ CONFIG_EXPERIMENTAL=y
# CONFIG_CLEAN_COMPILE is not set
CONFIG_BROKEN=y
CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
#
# General setup
#
+CONFIG_LOCALVERSION=""
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
CONFIG_POSIX_MQUEUE=y
@@ -25,17 +32,20 @@ CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
CONFIG_LOG_BUF_SHIFT=14
CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
# CONFIG_IKCONFIG is not set
# CONFIG_EMBEDDED is not set
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
CONFIG_FUTEX=y
CONFIG_EPOLL=y
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
#
# Loadable module support
@@ -45,6 +55,7 @@ CONFIG_MODULE_UNLOAD=y
CONFIG_MODULE_FORCE_UNLOAD=y
CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
+# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_KMOD=y
#
@@ -137,7 +148,6 @@ CONFIG_HEARTBEAT=y
#
# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
#
-CONFIG_ISA=y
CONFIG_PCI=y
CONFIG_SH_PCIDMA_NONCOHERENT=y
CONFIG_PCI_AUTO=y
@@ -146,16 +156,13 @@ CONFIG_PCI_LEGACY_PROC=y
CONFIG_PCI_NAMES=y
#
-# PCMCIA/CardBus support
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
#
-CONFIG_PCMCIA=m
-# CONFIG_PCMCIA_DEBUG is not set
-# CONFIG_YENTA is not set
-# CONFIG_PD6729 is not set
-# CONFIG_I82092 is not set
-# CONFIG_I82365 is not set
-# CONFIG_TCIC is not set
-CONFIG_PCMCIA_PROBE=y
#
# PCI Hotplug Support
@@ -163,7 +170,6 @@ CONFIG_PCMCIA_PROBE=y
CONFIG_HOTPLUG_PCI=m
# CONFIG_HOTPLUG_PCI_FAKE is not set
# CONFIG_HOTPLUG_PCI_CPCI is not set
-# CONFIG_HOTPLUG_PCI_PCIE is not set
# CONFIG_HOTPLUG_PCI_SHPC is not set
#
@@ -202,25 +208,36 @@ CONFIG_BINFMT_MISC=y
#
# Plug and Play support
#
-# CONFIG_PNP is not set
#
# Block devices
#
# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_DEV_XD is not set
# CONFIG_BLK_CPQ_DA is not set
# CONFIG_BLK_CPQ_CISS_DA is not set
# CONFIG_BLK_DEV_DAC960 is not set
# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
CONFIG_BLK_DEV_NBD=y
# CONFIG_BLK_DEV_SX8 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
+# CONFIG_ATA_OVER_ETH is not set
#
# ATA/ATAPI/MFM/RLL support
@@ -235,13 +252,11 @@ CONFIG_BLK_DEV_IDE=y
# CONFIG_BLK_DEV_IDE_SATA is not set
CONFIG_BLK_DEV_IDEDISK=y
CONFIG_IDEDISK_MULTI_MODE=y
-CONFIG_BLK_DEV_IDECS=m
CONFIG_BLK_DEV_IDECD=m
CONFIG_BLK_DEV_IDETAPE=m
CONFIG_BLK_DEV_IDEFLOPPY=m
# CONFIG_BLK_DEV_IDESCSI is not set
# CONFIG_IDE_TASK_IOCTL is not set
-# CONFIG_IDE_TASKFILE_IO is not set
#
# IDE chipset support/bugfixes
@@ -250,7 +265,6 @@ CONFIG_IDE_GENERIC=y
# CONFIG_BLK_DEV_IDEPCI is not set
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
@@ -283,46 +297,37 @@ CONFIG_CHR_DEV_SG=m
#
# CONFIG_SCSI_SPI_ATTRS is not set
# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
#
# SCSI low-level drivers
#
# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
# CONFIG_SCSI_3W_9XXX is not set
-# CONFIG_SCSI_7000FASST is not set
# CONFIG_SCSI_ACARD is not set
-# CONFIG_SCSI_AHA152X is not set
-# CONFIG_SCSI_AHA1542 is not set
# CONFIG_SCSI_AACRAID is not set
# CONFIG_SCSI_AIC7XXX is not set
# CONFIG_SCSI_AIC7XXX_OLD is not set
# CONFIG_SCSI_AIC79XX is not set
# CONFIG_SCSI_DPT_I2O is not set
# CONFIG_SCSI_ADVANSYS is not set
-# CONFIG_SCSI_IN2000 is not set
-# CONFIG_SCSI_MEGARAID is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
# CONFIG_SCSI_SATA is not set
# CONFIG_SCSI_BUSLOGIC is not set
# CONFIG_SCSI_CPQFCTS is not set
# CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_DTC3280 is not set
# CONFIG_SCSI_EATA is not set
# CONFIG_SCSI_EATA_PIO is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
# CONFIG_SCSI_GDTH is not set
-# CONFIG_SCSI_GENERIC_NCR5380 is not set
-# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
# CONFIG_SCSI_IPS is not set
# CONFIG_SCSI_INITIO is not set
# CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_NCR53C406A is not set
# CONFIG_SCSI_SYM53C8XX_2 is not set
# CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_PAS16 is not set
# CONFIG_SCSI_PCI2000 is not set
# CONFIG_SCSI_PCI2220I is not set
-# CONFIG_SCSI_PSI240I is not set
-# CONFIG_SCSI_QLOGIC_FAS is not set
# CONFIG_SCSI_QLOGIC_ISP is not set
# CONFIG_SCSI_QLOGIC_FC is not set
# CONFIG_SCSI_QLOGIC_1280 is not set
@@ -332,30 +337,12 @@ CONFIG_SCSI_QLA2XXX=m
# CONFIG_SCSI_QLA2300 is not set
# CONFIG_SCSI_QLA2322 is not set
# CONFIG_SCSI_QLA6312 is not set
-# CONFIG_SCSI_QLA6322 is not set
-# CONFIG_SCSI_SYM53C416 is not set
# CONFIG_SCSI_DC395x is not set
# CONFIG_SCSI_DC390T is not set
-# CONFIG_SCSI_T128 is not set
-# CONFIG_SCSI_U14_34F is not set
# CONFIG_SCSI_NSP32 is not set
# CONFIG_SCSI_DEBUG is not set
#
-# 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
-
-#
-# 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
@@ -403,6 +390,9 @@ CONFIG_IP_PNP_RARP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
# CONFIG_IPV6 is not set
# CONFIG_NETFILTER is not set
CONFIG_XFRM=y
@@ -424,7 +414,6 @@ CONFIG_XFRM=y
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
#
# QoS and/or fair queueing
@@ -461,27 +450,19 @@ CONFIG_MII=y
# CONFIG_HAPPYMEAL is not set
# CONFIG_SUNGEM is not set
# CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_LANCE is not set
-# CONFIG_NET_VENDOR_SMC is not set
-# CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_SMC91X is not set
#
# Tulip family network device support
#
# CONFIG_NET_TULIP is not set
-# CONFIG_AT1700 is not set
-# CONFIG_DEPCA is not set
# CONFIG_HP100 is not set
-# CONFIG_NET_ISA is not set
CONFIG_NET_PCI=y
# CONFIG_PCNET32 is not set
# CONFIG_AMD8111_ETH is not set
# CONFIG_ADAPTEC_STARFIRE is not set
-# CONFIG_AC3200 is not set
-# CONFIG_APRICOT is not set
# CONFIG_B44 is not set
# CONFIG_FORCEDETH is not set
-# CONFIG_CS89x0 is not set
# CONFIG_DGRS is not set
# CONFIG_EEPRO100 is not set
# CONFIG_E100 is not set
@@ -495,8 +476,6 @@ CONFIG_8139CP=y
# CONFIG_SUNDANCE is not set
# CONFIG_TLAN is not set
# CONFIG_VIA_RHINE is not set
-# CONFIG_VIA_VELOCITY is not set
-# CONFIG_NET_POCKET is not set
#
# Ethernet (1000 Mbit)
@@ -509,6 +488,7 @@ CONFIG_8139CP=y
# CONFIG_YELLOWFIN is not set
# CONFIG_R8169 is not set
# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
# CONFIG_TIGON3 is not set
#
@@ -528,11 +508,6 @@ CONFIG_8139CP=y
# CONFIG_NET_RADIO is not set
#
-# PCMCIA network device support
-#
-# CONFIG_NET_PCMCIA is not set
-
-#
# Wan interfaces
#
# CONFIG_WAN is not set
@@ -600,7 +575,6 @@ CONFIG_HW_CONSOLE=y
# Serial drivers
#
CONFIG_SERIAL_8250=m
-# CONFIG_SERIAL_8250_CS is not set
CONFIG_SERIAL_8250_NR_UARTS=4
# CONFIG_SERIAL_8250_EXTENDED is not set
@@ -614,7 +588,6 @@ CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
-# CONFIG_QIC02_TAPE is not set
#
# IPMI
@@ -634,13 +607,6 @@ CONFIG_WATCHDOG=y
CONFIG_SH_WDT=m
#
-# ISA-based Watchdog Cards
-#
-# CONFIG_PCWATCHDOG is not set
-# CONFIG_MIXCOMWD is not set
-# CONFIG_WDT is not set
-
-#
# PCI-based Watchdog Cards
#
# CONFIG_PCIPCWATCHDOG is not set
@@ -655,13 +621,7 @@ CONFIG_SH03_RTC=y
#
# Ftape, the floppy tape device driver
#
-# CONFIG_AGP is not set
# CONFIG_DRM is not set
-
-#
-# PCMCIA character devices
-#
-# CONFIG_SYNCLINK_CS is not set
# CONFIG_RAW_DRIVER is not set
#
@@ -697,7 +657,6 @@ CONFIG_SH03_RTC=y
# Console display driver support
#
# CONFIG_VGA_CONSOLE is not set
-# CONFIG_MDA_CONSOLE is not set
CONFIG_DUMMY_CONSOLE=y
#
@@ -709,6 +668,12 @@ CONFIG_DUMMY_CONSOLE=y
# USB support
#
# CONFIG_USB is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
#
# USB Gadget Support
@@ -716,6 +681,16 @@ CONFIG_DUMMY_CONSOLE=y
# CONFIG_USB_GADGET is not set
#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -732,10 +707,15 @@ CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
CONFIG_FS_POSIX_ACL=y
+
+#
+# XFS support
+#
# CONFIG_XFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
CONFIG_AUTOFS_FS=y
CONFIG_AUTOFS4_FS=y
@@ -768,6 +748,7 @@ CONFIG_SYSFS=y
# CONFIG_DEVFS_FS is not set
# CONFIG_DEVPTS_FS_XATTR is not set
CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
# CONFIG_HUGETLBFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
@@ -807,6 +788,7 @@ CONFIG_EXPORTFS=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
@@ -886,18 +868,18 @@ CONFIG_OPROFILE=m
#
# Kernel hacking
#
-# CONFIG_MAGIC_SYSRQ is not set
-# CONFIG_DEBUG_SPINLOCK is not set
-CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_DEBUG_PREEMPT=y
+# CONFIG_FRAME_POINTER is not set
CONFIG_SH_STANDARD_BIOS=y
# CONFIG_EARLY_SCIF_CONSOLE is not set
# CONFIG_EARLY_PRINTK is not set
# CONFIG_KGDB is not set
-# CONFIG_FRAME_POINTER is not set
#
# Security options
#
+# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
#
@@ -911,6 +893,7 @@ CONFIG_CRYPTO_MD5=y
CONFIG_CRYPTO_SHA1=y
# CONFIG_CRYPTO_SHA256 is not set
# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
CONFIG_CRYPTO_DES=y
# CONFIG_CRYPTO_BLOWFISH is not set
# CONFIG_CRYPTO_TWOFISH is not set
@@ -921,12 +904,17 @@ CONFIG_CRYPTO_DES=y
# 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=y
# 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=y
diff --git a/arch/sh/configs/snapgear_defconfig b/arch/sh/configs/snapgear_defconfig
index 25919849d5378..69cf02a24761f 100644
--- a/arch/sh/configs/snapgear_defconfig
+++ b/arch/sh/configs/snapgear_defconfig
@@ -1,34 +1,48 @@
#
# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-sh
+# Wed Mar 2 15:09:51 2005
#
CONFIG_SUPERH=y
CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
CONFIG_CLEAN_COMPILE=y
-CONFIG_STANDALONE=y
CONFIG_BROKEN_ON_SMP=y
#
# General setup
#
+CONFIG_LOCALVERSION=""
CONFIG_SWAP=y
# CONFIG_SYSVIPC is not set
+# CONFIG_POSIX_MQUEUE 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_KOBJECT_UEVENT=y
# CONFIG_IKCONFIG is not set
# CONFIG_EMBEDDED is not set
CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
CONFIG_FUTEX=y
CONFIG_EPOLL=y
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+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
#
# Loadable module support
@@ -40,6 +54,9 @@ CONFIG_IOSCHED_DEADLINE=y
#
# CONFIG_SH_SOLUTION_ENGINE is not set
# CONFIG_SH_7751_SOLUTION_ENGINE is not set
+# CONFIG_SH_7300_SOLUTION_ENGINE is not set
+# CONFIG_SH_73180_SOLUTION_ENGINE is not set
+# 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
@@ -55,19 +72,29 @@ CONFIG_IOSCHED_DEADLINE=y
# CONFIG_SH_SH2000 is not set
# CONFIG_SH_ADX is not set
# CONFIG_SH_MPC1211 is not set
+# CONFIG_SH_SH03 is not set
CONFIG_SH_SECUREEDGE5410=y
+# CONFIG_SH_HS7751RVOIP is not set
+# CONFIG_SH_RTS7751R2D is not set
+# CONFIG_SH_EDOSK7705 is not set
+# CONFIG_SH_SH4202_MICRODEV is not set
# CONFIG_SH_UNKNOWN is not set
# CONFIG_CPU_SH2 is not set
# CONFIG_CPU_SH3 is not set
CONFIG_CPU_SH4=y
# CONFIG_CPU_SUBTYPE_SH7604 is not set
# 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 is not set
# CONFIG_CPU_SUBTYPE_SH7750 is not set
CONFIG_CPU_SUBTYPE_SH7751=y
+# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH73180 is not set
# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
+# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
CONFIG_MMU=y
# CONFIG_CMDLINE_BOOL is not set
CONFIG_MEMORY_START=0x08000000
@@ -75,6 +102,7 @@ CONFIG_MEMORY_SIZE=0x01000000
CONFIG_MEMORY_SET=y
# CONFIG_MEMORY_OVERRIDE is not set
CONFIG_SH_RTC=y
+CONFIG_SH_FPU=y
CONFIG_ZERO_PAGE_OFFSET=0x00001000
CONFIG_BOOT_LINK_OFFSET=0x00800000
CONFIG_CPU_LITTLE_ENDIAN=y
@@ -84,11 +112,25 @@ CONFIG_CPU_LITTLE_ENDIAN=y
# CONFIG_SH_OCRAM is not set
# CONFIG_SH_STORE_QUEUES is not set
# CONFIG_SMP is not set
+CONFIG_SH_PCLK_CALC=y
CONFIG_SH_PCLK_FREQ=60013568
+
+#
+# CPU Frequency scaling
+#
# CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
CONFIG_SH_DMA=y
-CONFIG_NR_DMA_CHANNELS=8
-# CONFIG_DMA_PAGE_OPS is not set
+CONFIG_NR_ONCHIP_DMA_CHANNELS=4
+# CONFIG_NR_DMA_CHANNELS_BOOL is not set
+
+#
+# Companion Chips
+#
+# CONFIG_HD6446X_SERIES is not set
#
# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
@@ -97,10 +139,22 @@ CONFIG_PCI=y
# CONFIG_SH_PCIDMA_NONCOHERENT is not set
CONFIG_PCI_AUTO=y
CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
-CONFIG_PCI_DMA=y
# CONFIG_PCI_LEGACY_PROC is not set
CONFIG_PCI_NAMES=y
-# CONFIG_HOTPLUG is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
#
# Executable file formats
@@ -110,8 +164,20 @@ CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
#
+# SH initrd options
+#
+# CONFIG_EMBEDDED_RAMDISK is not set
+
+#
+# Device Drivers
+#
+
+#
# Generic Driver Options
#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
#
# Memory Technology Devices (MTD)
@@ -124,6 +190,10 @@ CONFIG_BINFMT_ELF=y
# CONFIG_PARPORT is not set
#
+# Plug and Play support
+#
+
+#
# Block devices
#
# CONFIG_BLK_DEV_FD is not set
@@ -131,12 +201,26 @@ CONFIG_BINFMT_ELF=y
# CONFIG_BLK_CPQ_CISS_DA is not set
# CONFIG_BLK_DEV_DAC960 is not set
# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
# CONFIG_BLK_DEV_LOOP is not set
# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
# CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
#
# ATA/ATAPI/MFM/RLL support
@@ -154,11 +238,20 @@ CONFIG_BLK_DEV_INITRD=y
# CONFIG_MD is not set
#
-# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
#
# CONFIG_IEEE1394 is not set
#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
# Networking support
#
CONFIG_NET=y
@@ -180,60 +273,69 @@ CONFIG_IP_PNP_DHCP=y
# CONFIG_NET_IPIP is not set
# CONFIG_NET_IPGRE is not set
# CONFIG_ARPD is not set
-# CONFIG_INET_ECN is not set
# CONFIG_SYN_COOKIES is not set
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
# CONFIG_IPV6 is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
# CONFIG_NETFILTER is not set
#
# SCTP Configuration (EXPERIMENTAL)
#
-CONFIG_IPV6_SCTP__=y
# CONFIG_IP_SCTP is not set
# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
# CONFIG_VLAN_8021Q is not set
-# CONFIG_LLC is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
#
# QoS and/or fair queueing
#
# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
#
# Network testing
#
# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
#
# ARCnet devices
#
# CONFIG_ARCNET is not set
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
#
# Ethernet (10 or 100Mbit)
#
CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
+CONFIG_MII=y
# CONFIG_STNIC is not set
# CONFIG_HAPPYMEAL is not set
# CONFIG_SUNGEM is not set
# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_SMC91X is not set
#
# Tulip family network device support
@@ -245,6 +347,7 @@ CONFIG_NET_PCI=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
@@ -273,49 +376,41 @@ CONFIG_8139TOO=y
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
# CONFIG_R8169 is not set
-# CONFIG_SIS190 is not set
# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
# CONFIG_TIGON3 is not set
#
# Ethernet (10000 Mbit)
#
# CONFIG_IXGB is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
+# CONFIG_S2IO is not set
#
-# Wireless LAN (non-hamradio)
+# Token Ring devices
#
-# CONFIG_NET_RADIO is not set
+# CONFIG_TR is not set
#
-# Token Ring devices (depends on LLC=y)
+# Wireless LAN (non-hamradio)
#
-# CONFIG_RCPCI is not set
-# CONFIG_SHAPER is not set
+# CONFIG_NET_RADIO is not set
#
# Wan interfaces
#
# CONFIG_WAN is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
+# 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
#
# ISDN subsystem
#
-# CONFIG_ISDN_BOOL is not set
+# CONFIG_ISDN is not set
#
# Telephony Support
@@ -344,7 +439,12 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
#
# CONFIG_GAMEPORT is not set
CONFIG_SOUND_GAMEPORT=y
-# CONFIG_SERIO is not set
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_RAW is not set
#
# Input Device Drivers
@@ -358,47 +458,110 @@ CONFIG_SOUND_GAMEPORT=y
#
# Character devices
#
-# CONFIG_VT is not set
-# CONFIG_SERIAL is not set
-CONFIG_SH_SCI=y
-CONFIG_SERIAL_CONSOLE=y
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
#
-# Unix 98 PTY support
+# Serial drivers
#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_SH_SCI is not set
CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
-# CONFIG_PSMOUSE is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
#
# Watchdog Cards
#
# CONFIG_WATCHDOG is not set
# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
#
-# Serial drivers
+# Ftape, the floppy tape device driver
#
-# CONFIG_SERIAL_8250 is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
#
-# Non-8250 serial port support
+# I2C support
#
-# CONFIG_SERIAL_SH_SCI is not set
+# CONFIG_I2C is not set
#
-# I2C support
+# Dallas's 1-wire bus
#
-# CONFIG_I2C is not set
+# CONFIG_W1 is not set
#
-# I2C Hardware Sensors Mainboard support
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
#
-# I2C Hardware Sensors Chip support
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
#
-# CONFIG_I2C_SENSOR is not set
+
+#
+# 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
#
# File systems
@@ -409,10 +572,15 @@ CONFIG_EXT2_FS=y
# CONFIG_JBD is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
# CONFIG_XFS_FS is not set
# CONFIG_MINIX_FS is not set
CONFIG_ROMFS_FS=y
# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
@@ -425,19 +593,24 @@ CONFIG_ROMFS_FS=y
#
# DOS/FAT/NT Filesystems
#
-# CONFIG_FAT_FS is not set
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
# CONFIG_NTFS_FS is not set
#
# Pseudo filesystems
#
CONFIG_PROC_FS=y
+# CONFIG_PROC_KCORE is not set
+CONFIG_SYSFS=y
CONFIG_DEVFS_FS=y
CONFIG_DEVFS_MOUNT=y
# CONFIG_DEVFS_DEBUG is not set
-CONFIG_DEVPTS_FS=y
# CONFIG_DEVPTS_FS_XATTR is not set
CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
#
@@ -446,6 +619,7 @@ CONFIG_RAMFS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
# CONFIG_BEFS_FS is not set
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
@@ -462,18 +636,18 @@ CONFIG_CRAMFS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
# CONFIG_NFSD is not set
CONFIG_ROOT_NFS=y
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
-# CONFIG_EXPORTFS is not set
CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_GSS is not set
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
# CONFIG_CIFS is not set
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
# CONFIG_AFS_FS is not set
#
@@ -483,48 +657,28 @@ CONFIG_SUNRPC=y
CONFIG_MSDOS_PARTITION=y
#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# Graphics support
+# Native Language Support
#
-# CONFIG_FB is not set
+# CONFIG_NLS is not set
#
-# Sound
+# Profiling support
#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-# CONFIG_USB is not set
-# CONFIG_USB_GADGET is not set
-
-#
-# Bluetooth support
-#
-# CONFIG_BT is not set
+# CONFIG_PROFILING is not set
#
# Kernel hacking
#
-# CONFIG_MAGIC_SYSRQ is not set
-# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_FRAME_POINTER is not set
# CONFIG_SH_STANDARD_BIOS is not set
+# CONFIG_EARLY_SCIF_CONSOLE is not set
# CONFIG_KGDB is not set
-# CONFIG_FRAME_POINTER is not set
#
# Security options
#
+# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
#
@@ -533,7 +687,13 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_CRYPTO is not set
#
+# Hardware crypto devices
+#
+
+#
# Library routines
#
-# CONFIG_CRC32 is not set
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=y
diff --git a/arch/sh/configs/systemh_defconfig b/arch/sh/configs/systemh_defconfig
index d34d9372a7941..431c9c9da1653 100644
--- a/arch/sh/configs/systemh_defconfig
+++ b/arch/sh/configs/systemh_defconfig
@@ -1,35 +1,48 @@
#
# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-sh
+# Wed Mar 2 15:09:53 2005
#
CONFIG_SUPERH=y
CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
# CONFIG_CLEAN_COMPILE is not set
-# CONFIG_STANDALONE is not set
CONFIG_BROKEN=y
CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
#
# General setup
#
+CONFIG_LOCALVERSION=""
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_IKCONFIG is not set
CONFIG_EMBEDDED=y
CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
CONFIG_FUTEX=y
CONFIG_EPOLL=y
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+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
#
# Loadable module support
@@ -39,6 +52,7 @@ 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
#
@@ -46,6 +60,8 @@ CONFIG_OBSOLETE_MODPARM=y
#
# CONFIG_SH_SOLUTION_ENGINE is not set
# CONFIG_SH_7751_SOLUTION_ENGINE is not set
+# CONFIG_SH_7300_SOLUTION_ENGINE is not set
+# CONFIG_SH_73180_SOLUTION_ENGINE is not set
CONFIG_SH_7751_SYSTEMH=y
# CONFIG_SH_STB1_HARP is not set
# CONFIG_SH_STB1_OVERDRIVE is not set
@@ -62,25 +78,36 @@ CONFIG_SH_7751_SYSTEMH=y
# CONFIG_SH_SH2000 is not set
# CONFIG_SH_ADX is not set
# CONFIG_SH_MPC1211 is not set
+# CONFIG_SH_SH03 is not set
# CONFIG_SH_SECUREEDGE5410 is not set
+# CONFIG_SH_HS7751RVOIP is not set
+# CONFIG_SH_RTS7751R2D is not set
+# CONFIG_SH_EDOSK7705 is not set
+# CONFIG_SH_SH4202_MICRODEV is not set
# CONFIG_SH_UNKNOWN is not set
# CONFIG_CPU_SH2 is not set
# CONFIG_CPU_SH3 is not set
CONFIG_CPU_SH4=y
# CONFIG_CPU_SUBTYPE_SH7604 is not set
# 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 is not set
# CONFIG_CPU_SUBTYPE_SH7750 is not set
CONFIG_CPU_SUBTYPE_SH7751=y
+# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH73180 is not set
# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
+# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
CONFIG_MMU=y
# CONFIG_CMDLINE_BOOL is not set
CONFIG_MEMORY_START=0x0c000000
CONFIG_MEMORY_SIZE=0x00400000
# CONFIG_MEMORY_OVERRIDE is not set
CONFIG_SH_RTC=y
+CONFIG_SH_FPU=y
CONFIG_ZERO_PAGE_OFFSET=0x00001000
CONFIG_BOOT_LINK_OFFSET=0x00800000
CONFIG_CPU_LITTLE_ENDIAN=y
@@ -90,21 +117,47 @@ CONFIG_PREEMPT=y
# CONFIG_SH_OCRAM is not set
# CONFIG_SH_STORE_QUEUES is not set
# CONFIG_SMP is not set
+CONFIG_SH_PCLK_CALC=y
CONFIG_SH_PCLK_FREQ=49876504
+
+#
+# CPU Frequency scaling
+#
# CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
# CONFIG_SH_DMA is not set
#
+# Companion Chips
+#
+# CONFIG_HD6446X_SERIES is not set
+
+#
# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
#
CONFIG_PCI=y
# CONFIG_SH_PCIDMA_NONCOHERENT is not set
CONFIG_PCI_AUTO=y
CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
-CONFIG_PCI_DMA=y
CONFIG_PCI_LEGACY_PROC=y
CONFIG_PCI_NAMES=y
-# CONFIG_HOTPLUG is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
#
# Executable file formats
@@ -114,8 +167,20 @@ CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
#
+# SH initrd options
+#
+# CONFIG_EMBEDDED_RAMDISK is not set
+
+#
+# Device Drivers
+#
+
+#
# Generic Driver Options
#
+# CONFIG_STANDALONE is not set
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
#
# Memory Technology Devices (MTD)
@@ -128,17 +193,35 @@ CONFIG_BINFMT_ELF=y
# 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 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=1024
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
@@ -156,19 +239,25 @@ CONFIG_BLK_DEV_INITRD=y
# CONFIG_MD is not set
#
-# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
#
# CONFIG_IEEE1394 is not set
#
-# Networking support
+# I2O device support
#
-# CONFIG_NET is not set
+# CONFIG_I2O is not set
#
-# Amateur Radio support
+# Networking support
#
-# CONFIG_HAMRADIO is not set
+# CONFIG_NET is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
#
# ISDN subsystem
@@ -198,6 +287,8 @@ CONFIG_SERIO=y
# CONFIG_SERIO_SERPORT is not set
# CONFIG_SERIO_CT82C710 is not set
# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_LIBPS2 is not set
+# CONFIG_SERIO_RAW is not set
#
# Input Device Drivers
@@ -207,50 +298,100 @@ CONFIG_SERIO=y
# Character devices
#
# CONFIG_VT is not set
-# CONFIG_SERIAL is not set
-CONFIG_SH_SCI=y
-CONFIG_SERIAL_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
#
-# Unix 98 PTY support
+# Serial drivers
#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_SH_SCI is not set
CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
-# CONFIG_PSMOUSE is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
#
# Watchdog Cards
#
# CONFIG_WATCHDOG is not set
# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
#
-# Serial drivers
+# Ftape, the floppy tape device driver
#
-# CONFIG_SERIAL_8250 is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
#
-# Non-8250 serial port support
+# I2C support
#
-# CONFIG_SERIAL_SH_SCI is not set
+# CONFIG_I2C is not set
#
-# I2C support
+# Dallas's 1-wire bus
#
-# CONFIG_I2C is not set
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
#
-# I2C Algorithms
+# USB support
+#
+# CONFIG_USB is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
#
#
-# I2C Hardware Bus support
+# USB Gadget Support
#
+# CONFIG_USB_GADGET is not set
#
-# I2C Hardware Sensors Chip support
+# MMC/SD Card support
#
-# CONFIG_I2C_SENSOR is not set
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
#
# File systems
@@ -260,10 +401,15 @@ CONFIG_UNIX98_PTY_COUNT=256
# CONFIG_JBD is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
# CONFIG_XFS_FS is not set
# CONFIG_MINIX_FS is not set
CONFIG_ROMFS_FS=y
# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
@@ -276,7 +422,8 @@ CONFIG_ROMFS_FS=y
#
# DOS/FAT/NT Filesystems
#
-# CONFIG_FAT_FS is not set
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
# CONFIG_NTFS_FS is not set
#
@@ -284,12 +431,13 @@ CONFIG_ROMFS_FS=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=y
# CONFIG_DEVPTS_FS_XATTR is not set
CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
# CONFIG_HUGETLBFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
@@ -300,6 +448,7 @@ CONFIG_RAMFS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
# CONFIG_BEFS_FS is not set
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
@@ -317,29 +466,9 @@ CONFIG_CRAMFS=y
CONFIG_MSDOS_PARTITION=y
#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-
-#
-# Graphics support
+# Native Language Support
#
-# CONFIG_FB is not set
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-# CONFIG_USB is not set
-# CONFIG_USB_GADGET is not set
+# CONFIG_NLS is not set
#
# Profiling support
@@ -349,15 +478,17 @@ CONFIG_MSDOS_PARTITION=y
#
# Kernel hacking
#
-# CONFIG_MAGIC_SYSRQ is not set
-# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_DEBUG_PREEMPT=y
+# CONFIG_FRAME_POINTER is not set
# CONFIG_SH_STANDARD_BIOS is not set
+# CONFIG_EARLY_SCIF_CONSOLE is not set
# CONFIG_KGDB is not set
-# CONFIG_FRAME_POINTER is not set
#
# Security options
#
+# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
#
@@ -366,7 +497,13 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_CRYPTO is not set
#
+# Hardware crypto devices
+#
+
+#
# Library routines
#
+# CONFIG_CRC_CCITT is not set
CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=y
diff --git a/arch/sh/defconfig b/arch/sh/defconfig
deleted file mode 100644
index ef852bbc926b3..0000000000000
--- a/arch/sh/defconfig
+++ /dev/null
@@ -1,372 +0,0 @@
-#
-# Automatically generated make config: don't edit
-#
-CONFIG_SUPERH=y
-CONFIG_UID16=y
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-
-#
-# Code maturity level options
-#
-# CONFIG_EXPERIMENTAL is not set
-CONFIG_CLEAN_COMPILE=y
-CONFIG_STANDALONE=y
-CONFIG_BROKEN_ON_SMP=y
-
-#
-# General setup
-#
-CONFIG_SWAP=y
-# CONFIG_SYSVIPC is not set
-# CONFIG_BSD_PROCESS_ACCT is not set
-# CONFIG_SYSCTL is not set
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_IKCONFIG is not set
-CONFIG_EMBEDDED=y
-CONFIG_KALLSYMS=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-
-#
-# Loadable module support
-#
-# CONFIG_MODULES is not set
-
-#
-# System type
-#
-# CONFIG_SH_SOLUTION_ENGINE is not set
-# CONFIG_SH_7751_SOLUTION_ENGINE is not set
-# 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 is not set
-# CONFIG_SH_HP690 is not set
-# CONFIG_SH_CQREEK is not set
-# CONFIG_SH_DMIDA is not set
-# CONFIG_SH_EC3104 is not set
-# CONFIG_SH_SATURN is not set
-# CONFIG_SH_DREAMCAST is not set
-# CONFIG_SH_CAT68701 is not set
-# CONFIG_SH_BIGSUR is not set
-# CONFIG_SH_SH2000 is not set
-# CONFIG_SH_ADX is not set
-# CONFIG_SH_MPC1211 is not set
-# CONFIG_SH_SECUREEDGE5410 is not set
-CONFIG_SH_UNKNOWN=y
-# CONFIG_CPU_SH2 is not set
-CONFIG_CPU_SH3=y
-# CONFIG_CPU_SH4 is not set
-# CONFIG_CPU_SUBTYPE_SH7604 is not set
-# CONFIG_CPU_SUBTYPE_SH7300 is not set
-# CONFIG_CPU_SUBTYPE_SH7707 is not set
-CONFIG_CPU_SUBTYPE_SH7708=y
-# CONFIG_CPU_SUBTYPE_SH7709 is not set
-# CONFIG_CPU_SUBTYPE_SH7750 is not set
-# CONFIG_CPU_SUBTYPE_SH7751 is not set
-# CONFIG_CPU_SUBTYPE_SH7760 is not set
-# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
-CONFIG_MMU=y
-# CONFIG_CMDLINE_BOOL is not set
-CONFIG_MEMORY_START=0x0c000000
-CONFIG_MEMORY_SIZE=0x00400000
-# CONFIG_MEMORY_OVERRIDE is not set
-CONFIG_CF_ENABLER=y
-# CONFIG_CF_AREA5 is not set
-CONFIG_CF_AREA6=y
-CONFIG_CF_BASE_ADDR=0xb8000000
-CONFIG_SH_RTC=y
-CONFIG_SH_DSP=y
-CONFIG_ZERO_PAGE_OFFSET=0x00001000
-CONFIG_BOOT_LINK_OFFSET=0x00800000
-CONFIG_CPU_LITTLE_ENDIAN=y
-# 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_FREQ=1193182
-# CONFIG_CPU_FREQ is not set
-# CONFIG_SH_DMA is not set
-
-#
-# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
-#
-# CONFIG_PCI is not set
-# CONFIG_HOTPLUG is not set
-
-#
-# Executable file formats
-#
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_FLAT is not set
-# CONFIG_BINFMT_MISC is not set
-
-#
-# Generic Driver Options
-#
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Block devices
-#
-# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_DEV_LOOP is not set
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=4096
-CONFIG_BLK_DEV_INITRD=y
-# CONFIG_LBD is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-CONFIG_IDE=y
-CONFIG_BLK_DEV_IDE=y
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
-CONFIG_BLK_DEV_IDEDISK=y
-# CONFIG_IDEDISK_MULTI_MODE is not set
-# CONFIG_IDEDISK_STROKE is not set
-# CONFIG_BLK_DEV_IDECD is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
-# CONFIG_IDE_TASK_IOCTL is not set
-
-#
-# IDE chipset support/bugfixes
-#
-CONFIG_IDE_GENERIC=y
-# CONFIG_BLK_DEV_IDEDMA is not set
-# CONFIG_IDEDMA_AUTO is not set
-# CONFIG_BLK_DEV_HD is not set
-
-#
-# SCSI device support
-#
-# CONFIG_SCSI is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Networking support
-#
-# CONFIG_NET is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# ISDN subsystem
-#
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-
-#
-# Userland interfaces
-#
-CONFIG_INPUT_MOUSEDEV=y
-CONFIG_INPUT_MOUSEDEV_PSAUX=y
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-CONFIG_SERIO_I8042=y
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-
-#
-# Input Device Drivers
-#
-CONFIG_INPUT_KEYBOARD=y
-CONFIG_KEYBOARD_ATKBD=y
-# CONFIG_KEYBOARD_SUNKBD is not set
-# CONFIG_KEYBOARD_XTKBD is not set
-# CONFIG_KEYBOARD_NEWTON is not set
-CONFIG_INPUT_MOUSE=y
-CONFIG_MOUSE_PS2=y
-# CONFIG_MOUSE_SERIAL is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Character devices
-#
-# CONFIG_VT is not set
-# CONFIG_SERIAL is not set
-CONFIG_SH_SCI=y
-CONFIG_SERIAL_CONSOLE=y
-
-#
-# Unix98 PTY support
-#
-# CONFIG_UNIX98_PTYS is not set
-# CONFIG_PSMOUSE is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_RTC is not set
-
-#
-# Serial drivers
-#
-# CONFIG_SERIAL_8250 is not set
-
-#
-# Non-8250 serial port support
-#
-# CONFIG_SERIAL_SH_SCI is not set
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_JBD is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-# CONFIG_XFS_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_QUOTA is not set
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_FAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-CONFIG_PROC_KCORE=y
-# CONFIG_TMPFS is not set
-# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-
-#
-# Native Language Support
-#
-# CONFIG_NLS is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-
-#
-# Graphics support
-#
-# CONFIG_FB is not set
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# Kernel hacking
-#
-# CONFIG_MAGIC_SYSRQ is not set
-# CONFIG_DEBUG_SPINLOCK is not set
-CONFIG_SH_STANDARD_BIOS=y
-CONFIG_EARLY_PRINTK=y
-# CONFIG_KGDB is not set
-# CONFIG_FRAME_POINTER is not set
-
-#
-# Security options
-#
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-# CONFIG_CRYPTO is not set
-
-#
-# Library routines
-#
-# CONFIG_CRC32 is not set
diff --git a/arch/sh/drivers/pci/fixups-sh03.c b/arch/sh/drivers/pci/fixups-sh03.c
index 5db5cb91c5698..57ac26c2171f7 100644
--- a/arch/sh/drivers/pci/fixups-sh03.c
+++ b/arch/sh/drivers/pci/fixups-sh03.c
@@ -46,11 +46,11 @@ static int sh03_pci_lookup_irq(struct pci_dev *dev, u8 slot, u8 pin)
/* now lookup the actual IRQ on a platform specific basis (pci-'platform'.c) */
irq = pcibios_map_platform_irq(slot, pin, dev);
if( irq < 0 ) {
- pr_debug("PCI: Error mapping IRQ on device %s\n", dev->slot_name);
+ pr_debug("PCI: Error mapping IRQ on device %s\n", pci_name(dev));
return irq;
}
- pr_debug("Setting IRQ for slot %s to %d\n", dev->slot_name, irq);
+ pr_debug("Setting IRQ for slot %s to %d\n", pci_name(dev), irq);
return irq;
}
diff --git a/arch/sh/drivers/pci/pci-sh7751.c b/arch/sh/drivers/pci/pci-sh7751.c
index 6d4c9f2b31e42..30b14ac7ae5a9 100644
--- a/arch/sh/drivers/pci/pci-sh7751.c
+++ b/arch/sh/drivers/pci/pci-sh7751.c
@@ -169,7 +169,7 @@ static void __init pci_fixup_ide_bases(struct pci_dev *d)
*/
if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE)
return;
- pr_debug("PCI: IDE base address fixup for %s\n", d->slot_name);
+ pr_debug("PCI: IDE base address fixup for %s\n", pci_name(d));
for(i=0; i<4; i++) {
struct resource *r = &d->resource[i];
if ((r->start & ~0x80) == 0x374) {
@@ -178,8 +178,8 @@ static void __init pci_fixup_ide_bases(struct pci_dev *d)
}
}
}
+
DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases);
-#endif
/*
* Called after each bus is probed, but before its children
@@ -401,11 +401,11 @@ static int sh7751_pci_lookup_irq(struct pci_dev *dev, u8 slot, u8 pin)
/* now lookup the actual IRQ on a platform specific basis (pci-'platform'.c) */
irq = pcibios_map_platform_irq(slot,pin);
if( irq < 0 ) {
- pr_debug("PCI: Error mapping IRQ on device %s\n", dev->slot_name);
+ pr_debug("PCI: Error mapping IRQ on device %s\n", pci_name(dev));
return irq;
}
-
- pr_debug("Setting IRQ for slot %s to %d\n", dev->slot_name, irq);
+
+ pr_debug("Setting IRQ for slot %s to %d\n", pci_name(dev), irq);
return irq;
}
diff --git a/arch/sh/drivers/pci/pci-st40.c b/arch/sh/drivers/pci/pci-st40.c
index 2688f4159764a..cb67521311566 100644
--- a/arch/sh/drivers/pci/pci-st40.c
+++ b/arch/sh/drivers/pci/pci-st40.c
@@ -246,7 +246,7 @@ static void __init pci_fixup_ide_bases(struct pci_dev *d)
*/
if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE)
return;
- printk("PCI: IDE base address fixup for %s\n", d->slot_name);
+ printk("PCI: IDE base address fixup for %s\n", pci_name(d));
for(i=0; i<4; i++) {
struct resource *r = &d->resource[i];
if ((r->start & ~0x80) == 0x374) {
diff --git a/arch/sh/kernel/cpu/sh4/sq.c b/arch/sh/kernel/cpu/sh4/sq.c
index 8ab1855ff9362..8437ea7430fe0 100644
--- a/arch/sh/kernel/cpu/sh4/sq.c
+++ b/arch/sh/kernel/cpu/sh4/sq.c
@@ -379,7 +379,7 @@ static int sq_mmap(struct file *file, struct vm_area_struct *vma)
map = __sq_alloc_mapping(vma->vm_start, offset, size, "Userspace");
- if (io_remap_page_range(vma, map->sq_addr, map->addr,
+ if (io_remap_pfn_range(vma, map->sq_addr, map->addr >> PAGE_SHIFT,
size, vma->vm_page_prot))
return -EAGAIN;
diff --git a/arch/sh/kernel/cpufreq.c b/arch/sh/kernel/cpufreq.c
index 85516164e866a..e0b384bef55f2 100644
--- a/arch/sh/kernel/cpufreq.c
+++ b/arch/sh/kernel/cpufreq.c
@@ -3,7 +3,7 @@
*
* cpufreq driver for the SuperH processors.
*
- * Copyright (C) 2002, 2003 Paul Mundt
+ * Copyright (C) 2002, 2003, 2004, 2005 Paul Mundt
* Copyright (C) 2002 M. R. Brown
*
* This program is free software; you can redistribute it and/or modify it
@@ -18,6 +18,7 @@
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/delay.h>
+#include <linux/cpumask.h>
#include <linux/smp.h>
#include <asm/processor.h>
@@ -46,9 +47,8 @@ struct clock_set {
#endif
};
-#define NR_CLOCK_SETS (sizeof(clock_sets) / sizeof(struct clock_set))
#define MIN_CLOCK_SET 0
-#define MAX_CLOCK_SET (NR_CLOCK_SETS - 1)
+#define MAX_CLOCK_SET (ARRAY_SIZE(clock_sets) - 1)
/*
* For the time being, we only support two frequencies, which in turn are
@@ -83,18 +83,16 @@ static void sh_cpufreq_update_clocks(unsigned int set)
static int sh_cpufreq_setstate(unsigned int cpu, unsigned int set)
{
unsigned short frqcr = ctrl_inw(FRQCR);
- unsigned long cpus_allowed;
+ cpumask_t cpus_allowed;
struct cpufreq_freqs freqs;
- int allowable_cpu_map;
if (!cpu_online(cpu))
return -ENODEV;
cpus_allowed = current->cpus_allowed;
- allowable_cpu_map = 1 << cpu;
- set_cpus_allowed(current, allowable_cpu_map);
-
- BUG_ON(!(allowable_cpu_map & (1 << smp_processor_id())));
+ set_cpus_allowed(current, cpumask_of_cpu(cpu));
+
+ BUG_ON(smp_processor_id() != cpu);
freqs.cpu = cpu;
freqs.old = current_cpu_data.cpu_clock / 1000;
@@ -134,7 +132,7 @@ static int sh_cpufreq_setstate(unsigned int cpu, unsigned int set)
set_cpus_allowed(current, cpus_allowed);
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
-
+
return 0;
}
diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c
index 9a7d936263fd9..54c171225b78d 100644
--- a/arch/sh/kernel/irq.c
+++ b/arch/sh/kernel/irq.c
@@ -40,58 +40,17 @@
#include <asm/irq.h>
#include <linux/irq.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
- }
-};
-
-/*
- * 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 enable_none(unsigned int irq) { }
-static unsigned int startup_none(unsigned int irq) { return 0; }
-static void disable_none(unsigned int irq) { }
-static void ack_none(unsigned int irq)
-{
/*
* 'what should we do if we get a hw irq event on an illegal vector'.
* each architecture has to answer this themselves, it doesn't deserve
* a generic callback i think.
*/
+void ack_bad_irq(unsigned int irq)
+{
printk("unexpected IRQ trap at vector %02x\n", irq);
}
-/* startup is the same as "enable", shutdown is same as "disable" */
-#define shutdown_none disable_none
-#define end_none enable_none
-
-struct hw_interrupt_type no_irq_type = {
- "none",
- startup_none,
- shutdown_none,
- enable_none,
- disable_none,
- ack_none,
- end_none
-};
-
-/*
- * Generic, controller-independent functions:
- */
-
#if defined(CONFIG_PROC_FS)
int show_interrupts(struct seq_file *p, void *v)
{
@@ -127,210 +86,13 @@ unlock:
}
#endif
-/*
- * This should really return information about whether
- * we should do bottom half handling etc. Right now we
- * end up _always_ checking the bottom half, which is a
- * waste of time and is not what some drivers would
- * prefer.
- */
-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, retval = 0;
-
- if (!(action->flags & SA_INTERRUPT))
- local_irq_enable();
-
- do {
- ret = action->handler(irq, action->dev_id, regs);
- if (ret == IRQ_HANDLED)
- status |= action->flags;
- retval |= ret;
- action = action->next;
- } while (action);
-
- if (status & SA_SAMPLE_RANDOM)
- add_interrupt_randomness(irq);
-
- local_irq_disable();
- return retval;
-}
-
-static void __report_bad_irq(int irq, irq_desc_t *desc, irqreturn_t action_ret)
-{
- struct irqaction *action;
-
- if (action_ret != IRQ_HANDLED && action_ret != IRQ_NONE) {
- printk(KERN_ERR "irq event %d: bogus return value %x\n",
- irq, action_ret);
- } else {
- printk(KERN_ERR "irq %d: nobody cared!\n", irq);
- }
- dump_stack();
- printk(KERN_ERR "handlers:\n");
- action = desc->action;
- do {
- printk(KERN_ERR "[<%p>]", action->handler);
- print_symbol(" (%s)",
- (unsigned long)action->handler);
- printk("\n");
- action = action->next;
- } while (action);
-}
-
-static void report_bad_irq(int irq, irq_desc_t *desc, irqreturn_t action_ret)
-{
- static int count = 100;
-
- if (count) {
- count--;
- __report_bad_irq(irq, desc, action_ret);
- }
-}
-
-static int noirqdebug;
-
-static int __init noirqdebug_setup(char *str)
-{
- noirqdebug = 1;
- printk("IRQ lockup detection disabled\n");
- return 1;
-}
-
-__setup("noirqdebug", noirqdebug_setup);
-
-/*
- * If 99,900 of the previous 100,000 interrupts have not been handled then
- * assume that the IRQ is stuck in some manner. Drop a diagnostic and try to
- * turn the IRQ off.
- *
- * (The other 100-of-100,000 interrupts may have been a correctly-functioning
- * device sharing an IRQ with the failing one)
- *
- * Called under desc->lock
- */
-static void note_interrupt(int irq, irq_desc_t *desc, irqreturn_t action_ret)
-{
- if (action_ret != IRQ_HANDLED) {
- desc->irqs_unhandled++;
- if (action_ret != IRQ_NONE)
- report_bad_irq(irq, desc, action_ret);
- }
-
- desc->irq_count++;
- if (desc->irq_count < 100000)
- return;
-
- desc->irq_count = 0;
- if (desc->irqs_unhandled > 99900) {
- /*
- * The interrupt is stuck
- */
- __report_bad_irq(irq, desc, action_ret);
- /*
- * Now kill the IRQ
- */
- printk(KERN_EMERG "Disabling IRQ #%d\n", irq);
- desc->status |= IRQ_DISABLED;
- desc->handler->disable(irq);
- }
- desc->irqs_unhandled = 0;
-}
-
-/*
- * 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.
- */
-inline void 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)
-{
- irq_desc_t *desc = irq_desc + irq;
- disable_irq_nosync(irq);
- if (desc->action)
- 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 | IRQ_INPROGRESS);
- 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("enable_irq() unbalanced from %p\n",
- __builtin_return_address(0));
- }
- spin_unlock_irqrestore(&desc->lock, flags);
-}
-
-/*
- * do_IRQ handles all normal device IRQ's.
- */
asmlinkage int do_IRQ(unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7,
struct pt_regs regs)
{
- /*
- * We ack quickly, we don't want the irq controller
- * thinking we're snobs just because some other CPU has
- * disabled global interrupts (we have already done the
- * INT_ACK cycles, it's too late to try to pretend to the
- * controller that we aren't taking the interrupt).
- *
- * 0 return value means that this irq is already being
- * handled by some other CPU. (or is disabled)
- */
int irq;
- irq_desc_t *desc;
- struct irqaction * action;
- unsigned int status;
irq_enter();
-
-#ifdef CONFIG_PREEMPT
- /*
- * At this point we're now about to actually call handlers,
- * and interrupts might get reenabled during them... bump
- * preempt_count to prevent any preemption while the handler
- * called here is pending...
- */
- preempt_disable();
-#endif
-
- /* Get IRQ number */
asm volatile("stc r2_bank, %0\n\t"
"shlr2 %0\n\t"
"shlr2 %0\n\t"
@@ -338,394 +100,7 @@ asmlinkage int do_IRQ(unsigned long r4, unsigned long r5,
"add #-16, %0\n\t"
:"=z" (irq));
irq = irq_demux(irq);
-
- kstat_this_cpu.irqs[irq]++;
- desc = irq_desc + irq;
- spin_lock(&desc->lock);
- 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 (likely(!(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 (unlikely(!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 do_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 (;;) {
- irqreturn_t action_ret;
-
- spin_unlock(&desc->lock);
- action_ret = handle_IRQ_event(irq, &regs, action);
- spin_lock(&desc->lock);
- if (!noirqdebug)
- note_interrupt(irq, desc, action_ret);
- if (likely(!(desc->status & IRQ_PENDING)))
- 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);
-
+ __do_IRQ(irq, &regs);
irq_exit();
-
-#ifdef CONFIG_PREEMPT
- /*
- * We're done with the handlers, interrupts should be
- * currently disabled; decrement preempt_count now so
- * as we return preemption may be allowed...
- */
- preempt_enable_no_resched();
-#endif
-
return 1;
}
-
-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;
-
- action = (struct irqaction *)
- kmalloc(sizeof(struct irqaction), GFP_ATOMIC);
- 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;
-
- 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)
- 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 it - 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);
- synchronize_irq(irq);
- kfree(action);
- return;
- }
- printk("Trying to free free IRQ%d\n",irq);
- spin_unlock_irqrestore(&desc->lock,flags);
- return;
- }
-}
-
-EXPORT_SYMBOL(free_irq);
-
-static DECLARE_MUTEX(probe_sem);
-
-/*
- * 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)
-{
- unsigned int i;
- irq_desc_t *desc;
- unsigned long val;
- unsigned long delay;
-
- down(&probe_sem);
- /*
- * 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 (!desc->action)
- desc->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)
- */
- 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++) {
- unsigned int status;
-
- desc = irq_desc + i;
-
- 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).
- */
-
-/*
- * probe_irq_mask - scan a bitmap of interrupt lines
- * @val: mask of interrupts to consider
- *
- * Scan the ISA bus interrupt lines and return a bitmap of
- * active interrupts. The interrupt probe logic state is then
- * returned to its previous value.
- *
- * Note: we need to scan all the irq's even though we will
- * only return ISA irq numbers - just so that we reset them
- * all to a known state.
- */
-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) {
- if (i < 16 && !(status & IRQ_WAITING))
- mask |= 1 << i;
-
- desc->status = status & ~IRQ_AUTODETECT;
- desc->handler->shutdown(i);
- }
- spin_unlock_irq(&desc->lock);
- }
- up(&probe_sem);
-
- return mask & val;
-}
-
-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);
- }
- up(&probe_sem);
-
- if (nr_irqs > 1)
- irq_found = -irq_found;
- return irq_found;
-}
-
-EXPORT_SYMBOL(probe_irq_off);
-
-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;
-}
-
-#if defined(CONFIG_PROC_FS) && defined(CONFIG_SYSCTL)
-
-void init_irq_proc(void)
-{
-}
-#endif
-
-/* Taken from the 2.5 alpha port */
-#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/sh/kernel/ptrace.c b/arch/sh/kernel/ptrace.c
index 35385c90064d8..1b0dfb4d8ea47 100644
--- a/arch/sh/kernel/ptrace.c
+++ b/arch/sh/kernel/ptrace.c
@@ -1,5 +1,4 @@
-/* $Id: ptrace.c,v 1.15 2004/05/07 05:32:05 sugioka Exp $
- *
+/*
* linux/arch/sh/kernel/ptrace.c
*
* Original x86 implementation:
diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c
index 16694472e7597..25b9d9ebe858b 100644
--- a/arch/sh/kernel/setup.c
+++ b/arch/sh/kernel/setup.c
@@ -43,7 +43,6 @@ extern void * __rd_start, * __rd_end;
*/
struct sh_cpuinfo boot_cpu_data = { CPU_SH_NONE, 0, 10000000, };
struct screen_info screen_info;
-unsigned char aux_device_present = 0xaa;
#if defined(CONFIG_SH_UNKNOWN)
struct sh_machine_vector sh_mv;
diff --git a/arch/sh/kernel/sh_ksyms.c b/arch/sh/kernel/sh_ksyms.c
index 4f371f6470a3d..6954fd62470ae 100644
--- a/arch/sh/kernel/sh_ksyms.c
+++ b/arch/sh/kernel/sh_ksyms.c
@@ -51,7 +51,6 @@ EXPORT_SYMBOL(strncat);
#ifdef CONFIG_PCI
EXPORT_SYMBOL(pci_alloc_consistent);
EXPORT_SYMBOL(pci_free_consistent);
-EXPORT_SYMBOL(pcibios_penalize_isa_irq);
#endif
/* mem exports */
@@ -65,13 +64,6 @@ EXPORT_SYMBOL(memmove);
EXPORT_SYMBOL(memcmp);
EXPORT_SYMBOL(memscan);
EXPORT_SYMBOL(__copy_user);
-
-#ifdef CONFIG_VT
-/* XXX: MRB-remove - what was screen_info changed to?
-EXPORT_SYMBOL(screen_info);
-*/
-#endif
-
EXPORT_SYMBOL(boot_cpu_data);
#ifdef CONFIG_MMU
diff --git a/arch/sh/kernel/signal.c b/arch/sh/kernel/signal.c
index 22e15018748ab..06f1b47eded96 100644
--- a/arch/sh/kernel/signal.c
+++ b/arch/sh/kernel/signal.c
@@ -1,5 +1,4 @@
-/* $Id: signal.c,v 1.21 2004/06/28 13:18:44 doyu Exp $
- *
+/*
* linux/arch/sh/kernel/signal.c
*
* Copyright (C) 1991, 1992 Linus Torvalds
@@ -100,7 +99,7 @@ sys_sigaction(int sig, const struct old_sigaction __user *act,
if (act) {
old_sigset_t mask;
- if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
+ if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
__get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
__get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
return -EFAULT;
@@ -112,7 +111,7 @@ sys_sigaction(int sig, const struct old_sigaction __user *act,
ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
if (!ret && oact) {
- if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
+ if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
__put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
__put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
return -EFAULT;
@@ -239,7 +238,7 @@ asmlinkage int sys_sigreturn(unsigned long r4, unsigned long r5,
sigset_t set;
int r0;
- if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
+ if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
goto badframe;
if (__get_user(set.sig[0], &frame->sc.oldmask)
@@ -273,7 +272,7 @@ asmlinkage int sys_rt_sigreturn(unsigned long r4, unsigned long r5,
stack_t st;
int r0;
- if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
+ if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
goto badframe;
if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
@@ -341,8 +340,10 @@ setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
static inline void __user *
get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
{
- if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! on_sig_stack(sp))
- sp = current->sas_ss_sp + current->sas_ss_size;
+ if (ka->sa.sa_flags & SA_ONSTACK) {
+ if (sas_ss_flags(sp) == 0)
+ sp = current->sas_ss_sp + current->sas_ss_size;
+ }
return (void __user *)((sp - frame_size) & -8ul);
}
diff --git a/arch/sh/kernel/smp.c b/arch/sh/kernel/smp.c
index ec6d54f05b26b..56a39d69e080d 100644
--- a/arch/sh/kernel/smp.c
+++ b/arch/sh/kernel/smp.c
@@ -34,14 +34,12 @@
* but is designed to be usable regardless if there's an MMU
* present or not.
*/
-int smp_threads_ready = 0;
struct sh_cpuinfo cpu_data[NR_CPUS];
extern void per_cpu_trap_init(void);
cpumask_t cpu_possible_map;
cpumask_t cpu_online_map;
-unsigned long cache_decay_ticks = HZ / 100;
static atomic_t cpus_booted = ATOMIC_INIT(0);
/* These are defined by the board-specific code. */
@@ -129,7 +127,6 @@ int start_secondary(void *unused)
void __init smp_cpus_done(unsigned int max_cpus)
{
- smp_threads_ready = 1;
smp_mb();
}
diff --git a/arch/sh/kernel/time.c b/arch/sh/kernel/time.c
index c417c84790621..df7a9b9d4cbff 100644
--- a/arch/sh/kernel/time.c
+++ b/arch/sh/kernel/time.c
@@ -33,6 +33,7 @@
#include <asm/machvec.h>
#include <asm/rtc.h>
#include <asm/freq.h>
+#include <asm/cpu/timer.h>
#ifdef CONFIG_SH_KGDB
#include <asm/kgdb.h>
#endif
@@ -46,40 +47,10 @@
#define TMU0_TCR_CALIB 0x0000
-#if defined(CONFIG_CPU_SH3)
-#if defined(CONFIG_CPU_SUBTYPE_SH7300)
-#define TMU_TSTR 0xA412FE92 /* Byte access */
-
-#define TMU0_TCOR 0xA412FE94 /* Long access */
-#define TMU0_TCNT 0xA412FE98 /* Long access */
-#define TMU0_TCR 0xA412FE9C /* Word access */
-
-#define TMU1_TCOR 0xA412FEA0 /* Long access */
-#define TMU1_TCNT 0xA412FEA4 /* Long access */
-#define TMU1_TCR 0xA412FEA8 /* Word access */
-
-#define FRQCR 0xA415FF80
-#else
-#define TMU_TOCR 0xfffffe90 /* Byte access */
-#define TMU_TSTR 0xfffffe92 /* Byte access */
-
-#define TMU0_TCOR 0xfffffe94 /* Long access */
-#define TMU0_TCNT 0xfffffe98 /* Long access */
-#define TMU0_TCR 0xfffffe9c /* Word access */
-#endif
-#elif defined(CONFIG_CPU_SH4)
-#define TMU_TOCR 0xffd80000 /* Byte access */
-#define TMU_TSTR 0xffd80004 /* Byte access */
-
-#define TMU0_TCOR 0xffd80008 /* Long access */
-#define TMU0_TCNT 0xffd8000c /* Long access */
-#define TMU0_TCR 0xffd80010 /* Word access */
-
#ifdef CONFIG_CPU_SUBTYPE_ST40STB1
#define CLOCKGEN_MEMCLKCR 0xbb040038
#define MEMCLKCR_RATIO_MASK 0x7
#endif /* CONFIG_CPU_SUBTYPE_ST40STB1 */
-#endif /* CONFIG_CPU_SH3 or CONFIG_CPU_SH4 */
extern unsigned long wall_jiffies;
#define TICK_SIZE (tick_nsec / 1000)
@@ -272,7 +243,7 @@ static inline void do_timer_interrupt(int irq, void *dev_id, struct pt_regs *reg
profile_tick(CPU_PROFILING, regs);
#ifdef CONFIG_HEARTBEAT
- if (sh_mv.mv_heartbeat != NULL)
+ if (sh_mv.mv_heartbeat != NULL)
sh_mv.mv_heartbeat();
#endif
diff --git a/arch/sh/mm/cache-sh4.c b/arch/sh/mm/cache-sh4.c
index a877087d00dae..ab833adf28c30 100644
--- a/arch/sh/mm/cache-sh4.c
+++ b/arch/sh/mm/cache-sh4.c
@@ -258,10 +258,16 @@ void flush_cache_mm(struct mm_struct *mm)
flush_cache_all();
}
-static void __flush_cache_page(struct vm_area_struct *vma,
- unsigned long address,
- unsigned long phys)
+/*
+ * Write back and invalidate I/D-caches for the page.
+ *
+ * ADDR: Virtual Address (U0 address)
+ * PFN: Physical page number
+ */
+void flush_cache_page(struct vm_area_struct *vma, unsigned long address, unsigned long pfn)
{
+ unsigned long phys = pfn << PAGE_SHIFT;
+
/* We only need to flush D-cache when we have alias */
if ((address^phys) & CACHE_ALIAS) {
/* Loop 4K of the D-cache */
@@ -342,32 +348,6 @@ void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
}
/*
- * Write back and invalidate I/D-caches for the page.
- *
- * ADDR: Virtual Address (U0 address)
- */
-void flush_cache_page(struct vm_area_struct *vma, unsigned long address)
-{
- pgd_t *dir;
- pmd_t *pmd;
- pte_t *pte;
- pte_t entry;
- unsigned long phys;
-
- dir = pgd_offset(vma->vm_mm, address);
- pmd = pmd_offset(dir, address);
- if (pmd_none(*pmd) || pmd_bad(*pmd))
- return;
- pte = pte_offset_kernel(pmd, address);
- entry = *pte;
- if (!(pte_val(entry) & _PAGE_PRESENT))
- return;
-
- phys = pte_val(entry)&PTE_PHYS_MASK;
- __flush_cache_page(vma, address, phys);
-}
-
-/*
* flush_icache_user_range
* @vma: VMA of the process
* @page: page
@@ -377,6 +357,6 @@ void flush_cache_page(struct vm_area_struct *vma, unsigned long address)
void flush_icache_user_range(struct vm_area_struct *vma,
struct page *page, unsigned long addr, int len)
{
- __flush_cache_page(vma, addr, PHYSADDR(page_address(page)));
+ flush_cache_page(vma, addr, page_to_pfn(page));
}
diff --git a/arch/sh/mm/cache-sh7705.c b/arch/sh/mm/cache-sh7705.c
index 3a0508bb46c77..ad8ed7d41e169 100644
--- a/arch/sh/mm/cache-sh7705.c
+++ b/arch/sh/mm/cache-sh7705.c
@@ -186,25 +186,9 @@ void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
*
* ADDRESS: Virtual Address (U0 address)
*/
-void flush_cache_page(struct vm_area_struct *vma, unsigned long address)
+void flush_cache_page(struct vm_area_struct *vma, unsigned long address, unsigned long pfn)
{
- pgd_t *dir;
- pmd_t *pmd;
- pte_t *pte;
- pte_t entry;
- unsigned long phys;
-
- dir = pgd_offset(vma->vm_mm, address);
- pmd = pmd_offset(dir, address);
- if (pmd_none(*pmd) || pmd_bad(*pmd))
- return;
- pte = pte_offset(pmd, address);
- entry = *pte;
- if (pte_none(entry) || !pte_present(entry))
- return;
-
- phys = pte_val(entry)&PTE_PHYS_MASK;
- __flush_dcache_page(phys);
+ __flush_dcache_page(pfn << PAGE_SHIFT);
}
/*
diff --git a/arch/sh/mm/hugetlbpage.c b/arch/sh/mm/hugetlbpage.c
index 4d5d687d1106c..1f897bab2318a 100644
--- a/arch/sh/mm/hugetlbpage.c
+++ b/arch/sh/mm/hugetlbpage.c
@@ -62,7 +62,7 @@ static void set_huge_pte(struct mm_struct *mm, struct vm_area_struct *vma,
unsigned long i;
pte_t entry;
- mm->rss += (HPAGE_SIZE / PAGE_SIZE);
+ add_mm_counter(mm, rss, HPAGE_SIZE / PAGE_SIZE);
if (write_access)
entry = pte_mkwrite(pte_mkdirty(mk_pte(page,
@@ -115,7 +115,7 @@ int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src,
pte_val(entry) += PAGE_SIZE;
dst_pte++;
}
- dst->rss += (HPAGE_SIZE / PAGE_SIZE);
+ add_mm_counter(dst, rss, HPAGE_SIZE / PAGE_SIZE);
addr += HPAGE_SIZE;
}
return 0;
@@ -202,11 +202,11 @@ void unmap_hugepage_range(struct vm_area_struct *vma,
page = pte_page(*pte);
put_page(page);
for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) {
- pte_clear(pte);
+ pte_clear(mm, address+(i*PAGE_SIZE), pte);
pte++;
}
}
- mm->rss -= (end - start) >> PAGE_SHIFT;
+ add_mm_counter(mm, rss, -((end - start) >> PAGE_SHIFT));
flush_tlb_range(vma, start, end);
}
diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c
index 030008e1fd6c0..4e9c854845a44 100644
--- a/arch/sh/mm/init.c
+++ b/arch/sh/mm/init.c
@@ -216,8 +216,6 @@ void __init paging_init(void)
#endif
NODE_DATA(0)->node_mem_map = NULL;
free_area_init_node(0, NODE_DATA(0), zones_size, __MEMORY_START >> PAGE_SHIFT, 0);
- /* XXX: MRB-remove - this doesn't seem sane, should this be done somewhere else ?*/
- mem_map = NODE_DATA(0)->node_mem_map;
#ifdef CONFIG_DISCONTIGMEM
/*
diff --git a/arch/sh/mm/pg-sh4.c b/arch/sh/mm/pg-sh4.c
index f6a76230872fb..e5907c7330e5c 100644
--- a/arch/sh/mm/pg-sh4.c
+++ b/arch/sh/mm/pg-sh4.c
@@ -56,7 +56,7 @@ void clear_user_page(void *to, unsigned long address, struct page *page)
local_irq_restore(flags);
update_mmu_cache(NULL, p3_addr, entry);
__clear_user_page((void *)p3_addr, to);
- pte_clear(pte);
+ pte_clear(&init_mm, p3_addr, pte);
up(&p3map_sem[(address & CACHE_ALIAS)>>12]);
}
}
@@ -95,7 +95,7 @@ void copy_user_page(void *to, void *from, unsigned long address,
local_irq_restore(flags);
update_mmu_cache(NULL, p3_addr, entry);
__copy_user_page((void *)p3_addr, from, to);
- pte_clear(pte);
+ pte_clear(&init_mm, p3_addr, pte);
up(&p3map_sem[(address & CACHE_ALIAS)>>12]);
}
}
@@ -103,11 +103,11 @@ void copy_user_page(void *to, void *from, unsigned long address,
/*
* For SH-4, we have our own implementation for ptep_get_and_clear
*/
-inline pte_t ptep_get_and_clear(pte_t *ptep)
+inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
{
pte_t pte = *ptep;
- pte_clear(ptep);
+ pte_clear(mm, addr, ptep);
if (!pte_not_present(pte)) {
unsigned long pfn = pte_pfn(pte);
if (pfn_valid(pfn)) {
diff --git a/arch/sh/mm/pg-sh7705.c b/arch/sh/mm/pg-sh7705.c
index 4a6eea8fb1e1c..ff9ece986cbcb 100644
--- a/arch/sh/mm/pg-sh7705.c
+++ b/arch/sh/mm/pg-sh7705.c
@@ -117,11 +117,11 @@ void copy_user_page(void *to, void *from, unsigned long address, struct page *pg
* For SH7705, we have our own implementation for ptep_get_and_clear
* Copied from pg-sh4.c
*/
-inline pte_t ptep_get_and_clear(pte_t *ptep)
+inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
{
pte_t pte = *ptep;
- pte_clear(ptep);
+ pte_clear(mm, addr, ptep);
if (!pte_not_present(pte)) {
unsigned long pfn = pte_pfn(pte);
if (pfn_valid(pfn)) {
diff --git a/arch/sh64/Kconfig b/arch/sh64/Kconfig
index 1fb7691e945e5..76eb81fba45e5 100644
--- a/arch/sh64/Kconfig
+++ b/arch/sh64/Kconfig
@@ -98,7 +98,12 @@ config BIG_ENDIAN
endchoice
+config SH_FPU
+ bool "FPU support"
+ default y
+
config SH64_FPU_DENORM_FLUSH
+ depends on SH_FPU
bool "Flush floating point denorms to zero"
choice
@@ -274,3 +279,15 @@ source "security/Kconfig"
source "crypto/Kconfig"
source "lib/Kconfig"
+
+#
+# Use the generic interrupt handling code in kernel/irq/:
+#
+config GENERIC_HARDIRQS
+ bool
+ default y
+
+config GENERIC_IRQ_PROBE
+ bool
+ default y
+
diff --git a/arch/sh64/Kconfig.debug b/arch/sh64/Kconfig.debug
index 530b3c650e862..26d842c071396 100644
--- a/arch/sh64/Kconfig.debug
+++ b/arch/sh64/Kconfig.debug
@@ -19,6 +19,13 @@ config SH64_PROC_ASIDS
config SH64_SR_WATCH
bool "Debug: set SR.WATCH to enable hardware watchpoints and trace"
+config POOR_MANS_STRACE
+ bool "Debug: enable rudimentary strace facility"
+ help
+ This option allows system calls to be traced to the console. It also
+ aids in detecting kernel stack underflow. It is useful for debugging
+ early-userland problems (e.g. init incurring fatal exceptions.)
+
config SH_ALPHANUMERIC
bool "Enable debug outputs to on-board alphanumeric display"
diff --git a/arch/sh64/Makefile b/arch/sh64/Makefile
index 62586a088a9dd..b4fd8e13fea99 100644
--- a/arch/sh64/Makefile
+++ b/arch/sh64/Makefile
@@ -11,13 +11,6 @@
# for "archclean" and "archdep" for cleaning up and making dependencies for
# this architecture
#
-# Note that top level Makefile automagically builds dependencies for SUBDIRS
-# but does not automagically clean SUBDIRS. Therefore "archclean" should clean
-# up all, "archdep" does nothing on added SUBDIRS.
-#
-ifndef include_config
--include .config
-endif
cpu-y := -mb
cpu-$(CONFIG_LITTLE_ENDIAN) := -ml
@@ -37,10 +30,17 @@ AFLAGS += -m5 -isa=sh64 -traditional
CFLAGS += $(cpu-y)
LDFLAGS_vmlinux += --defsym phys_stext=_stext-$(CONFIG_CACHED_MEMORY_OFFSET) \
- -e phys_stext
+ --defsym phys_stext_shmedia=phys_stext+1 \
+ -e phys_stext_shmedia
OBJCOPYFLAGS := -O binary -R .note -R .comment -R .stab -R .stabstr -S
+#
+# arch/sh64/defconfig never had any hope of being
+# frequently updated, so use one that does
+#
+KBUILD_DEFCONFIG := cayman_defconfig
+
ifdef LOADADDR
LINKFLAGS += -Ttext $(word 1,$(LOADADDR))
endif
@@ -52,7 +52,11 @@ machine-$(CONFIG_SH_ROMRAM) := romram
head-y := arch/$(ARCH)/kernel/head.o arch/$(ARCH)/kernel/init_task.o
-core-y += $(addprefix arch/$(ARCH)/, kernel/ mm/ mach-$(machine-y)/)
+core-y += arch/sh64/kernel/ arch/sh64/mm/
+
+ifneq ($(machine-y),)
+core-y += arch/sh64/mach-$(machine-y)/
+endif
LIBGCC := $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
libs-y += arch/$(ARCH)/lib/ $(LIBGCC)
@@ -92,7 +96,7 @@ define filechk_gen-syscalltab
echo "struct syscall_info {"; \
echo " const char *name;"; \
echo "} syscall_info_table[] = {"; \
- sed -e '/^.*\.long /!d;s//\t{ "/;s/\(\([^/]*\)\/\)\{1\}.*/\2/; \
+ sed -e '/^.*\.long /!d;s// { "/;s/\(\([^/]*\)\/\)\{1\}.*/\2/; \
s/[ \t]*$$//g;s/$$/" },/;s/\("\)sys_/\1/g'; \
echo "};"; \
echo ""; \
diff --git a/arch/sh64/configs/cayman_defconfig b/arch/sh64/configs/cayman_defconfig
index 2d1b41549a73f..48f27407d5e4b 100644
--- a/arch/sh64/configs/cayman_defconfig
+++ b/arch/sh64/configs/cayman_defconfig
@@ -1,11 +1,14 @@
#
# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11
+# Fri Feb 25 18:14:31 2005
#
CONFIG_SUPERH=y
CONFIG_SUPERH64=y
CONFIG_MMU=y
CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_LOG_BUF_SHIFT=14
#
@@ -13,12 +16,12 @@ CONFIG_LOG_BUF_SHIFT=14
#
CONFIG_EXPERIMENTAL=y
CONFIG_CLEAN_COMPILE=y
-CONFIG_STANDALONE=y
CONFIG_BROKEN_ON_SMP=y
#
# General setup
#
+CONFIG_LOCALVERSION=""
CONFIG_SWAP=y
# CONFIG_SYSVIPC is not set
CONFIG_POSIX_MQUEUE=y
@@ -26,16 +29,21 @@ CONFIG_POSIX_MQUEUE=y
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
# CONFIG_IKCONFIG 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_FUTEX=y
CONFIG_EPOLL=y
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
#
# Loadable module support
@@ -50,15 +58,12 @@ CONFIG_IOSCHED_CFQ=y
CONFIG_SH_CAYMAN=y
# CONFIG_SH_ROMRAM is not set
# CONFIG_SH_HARP is not set
-
-#
-# Processor type and features
-#
CONFIG_CPU_SH5=y
CONFIG_CPU_SUBTYPE_SH5_101=y
# CONFIG_CPU_SUBTYPE_SH5_103 is not set
CONFIG_LITTLE_ENDIAN=y
# CONFIG_BIG_ENDIAN is not set
+CONFIG_SH_FPU=y
# CONFIG_SH64_FPU_DENORM_FLUSH is not set
CONFIG_SH64_PGTABLE_2_LEVEL=y
# CONFIG_SH64_PGTABLE_3_LEVEL is not set
@@ -102,12 +107,27 @@ CONFIG_PREEMPT=y
#
# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
#
+CONFIG_SUPERHYWAY=y
CONFIG_PCI=y
CONFIG_SH_PCIDMA_NONCOHERENT=y
CONFIG_PCI_LEGACY_PROC=y
CONFIG_PCI_NAMES=y
#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
# Executable file formats
#
CONFIG_BINFMT_ELF=y
@@ -121,6 +141,10 @@ CONFIG_BINFMT_ELF=y
#
# Generic Driver Options
#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
#
# Memory Technology Devices (MTD)
@@ -144,14 +168,27 @@ CONFIG_BINFMT_ELF=y
# CONFIG_BLK_CPQ_CISS_DA is not set
# CONFIG_BLK_DEV_DAC960 is not set
# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_CARMEL is not set
+# CONFIG_BLK_DEV_SX8 is not set
CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_INITRAMFS_SOURCE=""
# CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
#
# ATA/ATAPI/MFM/RLL support
@@ -161,7 +198,74 @@ CONFIG_BLK_DEV_RAM_SIZE=4096
#
# SCSI device support
#
-# CONFIG_SCSI is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=y
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_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_ISP is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+CONFIG_SCSI_QLA2XXX=y
+# CONFIG_SCSI_QLA21XX is not set
+# CONFIG_SCSI_QLA22XX is not set
+# CONFIG_SCSI_QLA2300 is not set
+# CONFIG_SCSI_QLA2322 is not set
+# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
#
# Multi-device support (RAID and LVM)
@@ -171,6 +275,7 @@ CONFIG_BLK_DEV_RAM_SIZE=4096
#
# Fusion MPT device support
#
+# CONFIG_FUSION is not set
#
# IEEE 1394 (FireWire) support
@@ -209,6 +314,9 @@ CONFIG_IP_PNP=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
# CONFIG_IPV6 is not set
# CONFIG_NETFILTER is not set
@@ -228,12 +336,12 @@ CONFIG_IP_PNP=y
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
#
# QoS and/or fair queueing
#
# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
#
# Network testing
@@ -309,6 +417,7 @@ CONFIG_NET_PCI=y
# CONFIG_YELLOWFIN is not set
# CONFIG_R8169 is not set
# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
# CONFIG_TIGON3 is not set
#
@@ -335,6 +444,7 @@ CONFIG_NET_PCI=y
# 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
@@ -375,6 +485,8 @@ CONFIG_SERIO_I8042=y
CONFIG_SERIO_SERPORT=y
# CONFIG_SERIO_CT82C710 is not set
# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
#
# Input Device Drivers
@@ -416,7 +528,6 @@ CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
-# CONFIG_QIC02_TAPE is not set
#
# IPMI
@@ -449,8 +560,6 @@ CONFIG_WATCHDOG=y
#
# Ftape, the floppy tape device driver
#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
# CONFIG_DRM is not set
# CONFIG_RAW_DRIVER is not set
@@ -460,6 +569,11 @@ CONFIG_WATCHDOG=y
# CONFIG_I2C is not set
#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
# Misc devices
#
@@ -477,17 +591,21 @@ CONFIG_WATCHDOG=y
# Graphics support
#
CONFIG_FB=y
+CONFIG_FB_MODE_HELPERS=y
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_CIRRUS is not set
# CONFIG_FB_PM2 is not set
# CONFIG_FB_CYBER2000 is not set
# CONFIG_FB_ASILIANT is not set
# CONFIG_FB_IMSTT is not set
-# CONFIG_FB_E1355 is not set
+# CONFIG_FB_EPSON1355 is not set
# CONFIG_FB_RIVA is not set
# CONFIG_FB_MATROX is not set
# CONFIG_FB_RADEON_OLD is not set
# CONFIG_FB_RADEON is not set
# CONFIG_FB_ATY128 is not set
# CONFIG_FB_ATY is not set
+# CONFIG_FB_SAVAGE is not set
# CONFIG_FB_SIS is not set
# CONFIG_FB_NEOMAGIC is not set
CONFIG_FB_KYRO=y
@@ -500,10 +618,8 @@ CONFIG_FB_KYRO=y
# Console display driver support
#
# CONFIG_VGA_CONSOLE is not set
-# CONFIG_MDA_CONSOLE is not set
CONFIG_DUMMY_CONSOLE=y
CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_PCI_CONSOLE=y
CONFIG_FONTS=y
# CONFIG_FONT_8x8 is not set
CONFIG_FONT_8x16=y
@@ -524,6 +640,7 @@ CONFIG_LOGO=y
# CONFIG_LOGO_SUPERH_MONO is not set
# CONFIG_LOGO_SUPERH_VGA16 is not set
CONFIG_LOGO_SUPERH_CLUT224=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
# Sound
@@ -534,6 +651,12 @@ CONFIG_LOGO_SUPERH_CLUT224=y
# USB support
#
# CONFIG_USB is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
#
# USB Gadget Support
@@ -541,18 +664,38 @@ CONFIG_LOGO_SUPERH_CLUT224=y
# CONFIG_USB_GADGET is not set
#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
# File systems
#
CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_JBD is not set
+CONFIG_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
+
+#
+# XFS support
+#
# CONFIG_XFS_FS is not set
CONFIG_MINIX_FS=y
CONFIG_ROMFS_FS=y
# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
@@ -565,7 +708,8 @@ CONFIG_ROMFS_FS=y
#
# DOS/FAT/NT Filesystems
#
-# CONFIG_FAT_FS is not set
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
# CONFIG_NTFS_FS is not set
#
@@ -577,6 +721,7 @@ CONFIG_SYSFS=y
# CONFIG_DEVFS_FS is not set
# CONFIG_DEVPTS_FS_XATTR is not set
CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
CONFIG_HUGETLBFS=y
CONFIG_HUGETLB_PAGE=y
CONFIG_RAMFS=y
@@ -609,9 +754,9 @@ CONFIG_NFS_V3=y
CONFIG_ROOT_NFS=y
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
-# CONFIG_EXPORTFS is not set
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
@@ -621,8 +766,22 @@ CONFIG_SUNRPC=y
#
# Partition Types
#
-# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
#
# Native Language Support
@@ -630,21 +789,33 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_NLS is not set
#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
# Kernel hacking
#
+CONFIG_DEBUG_KERNEL=y
CONFIG_MAGIC_SYSRQ=y
+CONFIG_SCHEDSTATS=y
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_FS=y
+CONFIG_FRAME_POINTER=y
# CONFIG_EARLY_PRINTK is not set
# CONFIG_DEBUG_KERNEL_WITH_GDB_STUB is not set
-# CONFIG_SH64_PROC_TLB is not set
-# CONFIG_SH64_PROC_ASIDS is not set
+CONFIG_SH64_PROC_TLB=y
+CONFIG_SH64_PROC_ASIDS=y
CONFIG_SH64_SR_WATCH=y
+# CONFIG_POOR_MANS_STRACE is not set
# CONFIG_SH_ALPHANUMERIC is not set
# CONFIG_SH_NO_BSS_INIT is not set
-CONFIG_FRAME_POINTER=y
#
# Security options
#
+# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
#
@@ -653,7 +824,14 @@ CONFIG_FRAME_POINTER=y
# CONFIG_CRYPTO is not set
#
+# Hardware crypto devices
+#
+
+#
# Library routines
#
+# CONFIG_CRC_CCITT is not set
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
diff --git a/arch/sh64/defconfig b/arch/sh64/defconfig
deleted file mode 100644
index 8cfca490c2ed6..0000000000000
--- a/arch/sh64/defconfig
+++ /dev/null
@@ -1,667 +0,0 @@
-#
-# Automatically generated make config: don't edit
-#
-CONFIG_SUPERH=y
-CONFIG_SUPERH64=y
-CONFIG_MMU=y
-CONFIG_UID16=y
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-CONFIG_LOG_BUF_SHIFT=14
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
-CONFIG_STANDALONE=y
-CONFIG_BROKEN_ON_SMP=y
-
-#
-# General setup
-#
-CONFIG_SWAP=y
-# CONFIG_SYSVIPC is not set
-CONFIG_POSIX_MQUEUE=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
-# CONFIG_AUDIT is not set
-# CONFIG_HOTPLUG is not set
-# CONFIG_IKCONFIG is not set
-# CONFIG_EMBEDDED is not set
-CONFIG_KALLSYMS=y
-# CONFIG_KALLSYMS_EXTRA_PASS is not set
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-
-#
-# Loadable module support
-#
-# CONFIG_MODULES is not set
-
-#
-# System type
-#
-# CONFIG_SH_GENERIC is not set
-# CONFIG_SH_SIMULATOR is not set
-CONFIG_SH_CAYMAN=y
-# CONFIG_SH_ROMRAM is not set
-# CONFIG_SH_HARP is not set
-CONFIG_CPU_SH5=y
-CONFIG_CPU_SUBTYPE_SH5_101=y
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
-CONFIG_LITTLE_ENDIAN=y
-# CONFIG_BIG_ENDIAN is not set
-# CONFIG_SH64_FPU_DENORM_FLUSH is not set
-CONFIG_SH64_PGTABLE_2_LEVEL=y
-# CONFIG_SH64_PGTABLE_3_LEVEL is not set
-CONFIG_HUGETLB_PAGE_SIZE_64K=y
-# CONFIG_HUGETLB_PAGE_SIZE_1MB is not set
-# CONFIG_HUGETLB_PAGE_SIZE_512MB is not set
-CONFIG_SH64_USER_MISALIGNED_FIXUP=y
-
-#
-# Memory options
-#
-CONFIG_CACHED_MEMORY_OFFSET=0x20000000
-CONFIG_MEMORY_START=0x80000000
-CONFIG_MEMORY_SIZE_IN_MB=128
-
-#
-# Cache options
-#
-# CONFIG_DCACHE_DISABLED is not set
-CONFIG_DCACHE_WRITE_BACK=y
-# CONFIG_DCACHE_WRITE_THROUGH is not set
-# CONFIG_ICACHE_DISABLED is not set
-CONFIG_PCIDEVICE_MEMORY_START=C0000000
-CONFIG_DEVICE_MEMORY_START=E0000000
-CONFIG_FLASH_MEMORY_START=0x00000000
-CONFIG_PCI_BLOCK_START=0x40000000
-
-#
-# CPU Subtype specific options
-#
-CONFIG_SH64_ID2815_WORKAROUND=y
-
-#
-# Misc options
-#
-CONFIG_HEARTBEAT=y
-CONFIG_HDSP253_LED=y
-CONFIG_SH_DMA=y
-CONFIG_PREEMPT=y
-
-#
-# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
-#
-CONFIG_PCI=y
-CONFIG_SH_PCIDMA_NONCOHERENT=y
-CONFIG_PCI_LEGACY_PROC=y
-CONFIG_PCI_NAMES=y
-
-#
-# Executable file formats
-#
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_FLAT is not set
-# CONFIG_BINFMT_MISC is not set
-
-#
-# Device Drivers
-#
-
-#
-# Generic Driver Options
-#
-CONFIG_PREVENT_FIRMWARE_BUILD=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_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_UMEM is not set
-CONFIG_BLK_DEV_LOOP=y
-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_SX8 is not set
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=4096
-# CONFIG_BLK_DEV_INITRD is not set
-# CONFIG_LBD is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-# CONFIG_SCSI is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-
-#
-# IEEE 1394 (FireWire) support
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-
-#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-# CONFIG_NETLINK_DEV is not set
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP 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_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_IPV6 is not set
-# CONFIG_NETFILTER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
-CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
-# CONFIG_STNIC is not set
-# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNGEM is not set
-# CONFIG_NET_VENDOR_3COM is not set
-
-#
-# Tulip family network device support
-#
-CONFIG_NET_TULIP=y
-# CONFIG_DE2104X is not set
-CONFIG_TULIP=y
-# CONFIG_TULIP_MWI is not set
-# CONFIG_TULIP_MMIO is not set
-# CONFIG_TULIP_NAPI is not set
-# CONFIG_DE4X5 is not set
-# CONFIG_WINBOND_840 is not set
-# CONFIG_DM9102 is not set
-# CONFIG_HP100 is not set
-CONFIG_NET_PCI=y
-# CONFIG_PCNET32 is not set
-# CONFIG_AMD8111_ETH is not set
-# CONFIG_ADAPTEC_STARFIRE is not set
-# CONFIG_B44 is not set
-# CONFIG_FORCEDETH is not set
-# CONFIG_DGRS is not set
-# CONFIG_EEPRO100 is not set
-# CONFIG_E100 is not set
-# CONFIG_FEALNX is not set
-# CONFIG_NATSEMI is not set
-# CONFIG_NE2K_PCI is not set
-# CONFIG_8139CP is not set
-# CONFIG_8139TOO is not set
-# CONFIG_SIS900 is not set
-# CONFIG_EPIC100 is not set
-# CONFIG_SUNDANCE is not set
-# CONFIG_TLAN is not set
-# CONFIG_VIA_RHINE is not set
-# CONFIG_VIA_VELOCITY is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_TIGON3 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_IXGB is not set
-# CONFIG_S2IO is not set
-
-#
-# Token Ring devices
-#
-# CONFIG_TR is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-# CONFIG_SHAPER is not set
-# CONFIG_NETCONSOLE is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN is not set
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-
-#
-# Userland interfaces
-#
-CONFIG_INPUT_MOUSEDEV=y
-CONFIG_INPUT_MOUSEDEV_PSAUX=y
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-CONFIG_SERIO_I8042=y
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PCIPS2 is not set
-
-#
-# Input Device Drivers
-#
-CONFIG_INPUT_KEYBOARD=y
-CONFIG_KEYBOARD_ATKBD=y
-# CONFIG_KEYBOARD_SUNKBD is not set
-# CONFIG_KEYBOARD_LKKBD is not set
-# CONFIG_KEYBOARD_XTKBD is not set
-# CONFIG_KEYBOARD_NEWTON is not set
-CONFIG_INPUT_MOUSE=y
-CONFIG_MOUSE_PS2=y
-# CONFIG_MOUSE_SERIAL is not set
-# CONFIG_MOUSE_VSXXXAA is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Character devices
-#
-CONFIG_VT=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_SH_SCI=y
-CONFIG_SERIAL_SH_SCI_CONSOLE=y
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-CONFIG_UNIX98_PTYS=y
-CONFIG_LEGACY_PTYS=y
-CONFIG_LEGACY_PTY_COUNT=256
-# CONFIG_QIC02_TAPE is not set
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-CONFIG_WATCHDOG=y
-# CONFIG_WATCHDOG_NOWAYOUT is not set
-
-#
-# Watchdog Device Drivers
-#
-# CONFIG_SOFT_WATCHDOG is not set
-# CONFIG_SH_WDT is not set
-
-#
-# PCI-based Watchdog Cards
-#
-# CONFIG_PCIPCWATCHDOG is not set
-# CONFIG_WDTPCI is not set
-# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# Misc devices
-#
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# Graphics support
-#
-CONFIG_FB=y
-# CONFIG_FB_CIRRUS is not set
-# CONFIG_FB_PM2 is not set
-# CONFIG_FB_CYBER2000 is not set
-# CONFIG_FB_ASILIANT is not set
-# CONFIG_FB_IMSTT is not set
-# CONFIG_FB_E1355 is not set
-# CONFIG_FB_RIVA is not set
-# CONFIG_FB_MATROX is not set
-# CONFIG_FB_RADEON_OLD is not set
-# CONFIG_FB_RADEON is not set
-# CONFIG_FB_ATY128 is not set
-# CONFIG_FB_ATY is not set
-# CONFIG_FB_SIS is not set
-# CONFIG_FB_NEOMAGIC is not set
-CONFIG_FB_KYRO=y
-# CONFIG_FB_3DFX is not set
-# CONFIG_FB_VOODOO1 is not set
-# CONFIG_FB_TRIDENT is not set
-# CONFIG_FB_VIRTUAL is not set
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_MDA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_PCI_CONSOLE=y
-CONFIG_FONTS=y
-# CONFIG_FONT_8x8 is not set
-CONFIG_FONT_8x16=y
-# CONFIG_FONT_6x11 is not set
-# CONFIG_FONT_PEARL_8x8 is not set
-# CONFIG_FONT_ACORN_8x8 is not set
-# CONFIG_FONT_MINI_4x6 is not set
-# CONFIG_FONT_SUN8x16 is not set
-# CONFIG_FONT_SUN12x22 is not set
-
-#
-# Logo configuration
-#
-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_SUPERH_MONO is not set
-# CONFIG_LOGO_SUPERH_VGA16 is not set
-CONFIG_LOGO_SUPERH_CLUT224=y
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-# CONFIG_USB is not set
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_JBD is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-# CONFIG_XFS_FS is not set
-CONFIG_MINIX_FS=y
-CONFIG_ROMFS_FS=y
-# CONFIG_QUOTA is not set
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_FAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-CONFIG_PROC_KCORE=y
-CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-# CONFIG_DEVPTS_FS_XATTR is not set
-CONFIG_TMPFS=y
-CONFIG_HUGETLBFS=y
-CONFIG_HUGETLB_PAGE=y
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_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_V4 is not set
-# CONFIG_NFS_DIRECTIO is not set
-# CONFIG_NFSD is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-CONFIG_LOCKD_V4=y
-# CONFIG_EXPORTFS is not set
-CONFIG_SUNRPC=y
-# CONFIG_RPCSEC_GSS_KRB5 is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-
-#
-# Native Language Support
-#
-# CONFIG_NLS is not set
-
-#
-# Profiling support
-#
-CONFIG_PROFILING=y
-# CONFIG_OPROFILE is not set
-
-#
-# Kernel hacking
-#
-CONFIG_MAGIC_SYSRQ=y
-# CONFIG_EARLY_PRINTK is not set
-# CONFIG_DEBUG_KERNEL_WITH_GDB_STUB is not set
-# CONFIG_SH64_PROC_TLB is not set
-# CONFIG_SH64_PROC_ASIDS is not set
-CONFIG_SH64_SR_WATCH=y
-# CONFIG_SH_ALPHANUMERIC is not set
-# CONFIG_SH_NO_BSS_INIT is not set
-CONFIG_FRAME_POINTER=y
-
-#
-# Security options
-#
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-# CONFIG_CRYPTO is not set
-
-#
-# Library routines
-#
-# CONFIG_CRC16 is not set
-CONFIG_CRC32=y
-# CONFIG_LIBCRC32C is not set
diff --git a/arch/sh64/kernel/Makefile b/arch/sh64/kernel/Makefile
index 2f8d07746c616..5816657c079c5 100644
--- a/arch/sh64/kernel/Makefile
+++ b/arch/sh64/kernel/Makefile
@@ -13,7 +13,7 @@
# unless it's something special (ie not a .c file).
#
-extra-y := head.o init_task.o vmlinux.lds.s
+extra-y := head.o init_task.o vmlinux.lds
obj-y := process.o signal.o entry.o traps.o irq.o irq_intc.o \
ptrace.o setup.o time.o sys_sh64.o semaphore.o sh_ksyms.o \
@@ -22,17 +22,15 @@ obj-y := process.o signal.o entry.o traps.o irq.o irq_intc.o \
obj-$(CONFIG_HEARTBEAT) += led.o
obj-$(CONFIG_SH_ALPHANUMERIC) += alphanum.o
obj-$(CONFIG_SH_DMA) += dma.o
+obj-$(CONFIG_SH_FPU) += fpu.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
obj-$(CONFIG_KALLSYMS) += unwind.o
obj-$(CONFIG_PCI) += pci-dma.o pcibios.o
+obj-$(CONFIG_MODULES) += module.o
ifeq ($(CONFIG_PCI),y)
obj-$(CONFIG_CPU_SH5) += pci_sh5.o
endif
-ifndef CONFIG_NOFPU_SUPPORT
-obj-y += fpu.o
-endif
-
USE_STANDARD_AS_RULE := true
diff --git a/arch/sh64/kernel/dma.c b/arch/sh64/kernel/dma.c
index f5183b20ab040..09cd9f4670b5b 100644
--- a/arch/sh64/kernel/dma.c
+++ b/arch/sh64/kernel/dma.c
@@ -31,7 +31,7 @@ typedef struct {
} dma_info_t;
static dma_info_t dma_info[MAX_DMA_CHANNELS];
-extern spinlock_t dma_spin_lock;
+static DEFINE_SPINLOCK(dma_spin_lock);
/* arch/sh64/kernel/irq_intc.c */
extern void make_intc_irq(unsigned int irq);
diff --git a/arch/sh64/kernel/early_printk.c b/arch/sh64/kernel/early_printk.c
index 3d03ca737b360..8c8a76e180aab 100644
--- a/arch/sh64/kernel/early_printk.c
+++ b/arch/sh64/kernel/early_printk.c
@@ -16,8 +16,6 @@
#include <asm/io.h>
#include <asm/hardware.h>
-extern void cpu_relax(void);
-
#define SCIF_BASE_ADDR 0x01030000
#define SCIF_ADDR_SH5 PHYS_PERIPHERAL_BLOCK+SCIF_BASE_ADDR
diff --git a/arch/sh64/kernel/entry.S b/arch/sh64/kernel/entry.S
index 52dda3814bc5d..2e2cfe20b4261 100644
--- a/arch/sh64/kernel/entry.S
+++ b/arch/sh64/kernel/entry.S
@@ -6,7 +6,7 @@
* arch/sh64/kernel/entry.S
*
* Copyright (C) 2000, 2001 Paolo Alberelli
- * Copyright (C) 2004 Paul Mundt
+ * Copyright (C) 2004, 2005 Paul Mundt
* Copyright (C) 2003, 2004 Richard Curnow
*
*/
@@ -155,7 +155,7 @@ trap_jtable:
.long tlb_miss_store /* 0x0C0 */
.long do_address_error_load /* 0x0E0 */
.long do_address_error_store /* 0x100 */
-#ifndef CONFIG_NOFPU_SUPPORT
+#ifdef CONFIG_SH_FPU
.long do_fpu_error /* 0x120 */
#else
.long do_exception_error /* 0x120 */
@@ -237,6 +237,7 @@ LVBR_block:
.space 256, 0 /* Power-on class handler, */
/* not required here */
not_a_tlb_miss:
+ synco /* TAKum03020 (but probably a good idea anyway.) */
/* Save original stack pointer into KCR1 */
putcon SP, KCR1
@@ -278,6 +279,7 @@ not_a_tlb_miss:
* block making sure the final alignment is correct.
*/
tlb_miss:
+ synco /* TAKum03020 (but probably a good idea anyway.) */
putcon SP, KCR1
movi reg_save_area, SP
/* SP is guaranteed 32-byte aligned. */
@@ -393,6 +395,7 @@ fixup_to_invoke_general_handler:
/* VBR + 0x600 */
interrupt:
+ synco /* TAKum03020 (but probably a good idea anyway.) */
/* Save original stack pointer into KCR1 */
putcon SP, KCR1
@@ -429,6 +432,7 @@ LRESVEC_block:
* (this may need to be extended...)
*/
reset_or_panic:
+ synco /* TAKum03020 (but probably a good idea anyway.) */
putcon SP, DCR
/* First save r0-1 and tr0, as we need to use these */
movi resvec_save_area-CONFIG_CACHED_MEMORY_OFFSET, SP
@@ -481,6 +485,7 @@ single_step_panic:
.balign 256
debug_exception:
+ synco /* TAKum03020 (but probably a good idea anyway.) */
/*
* Single step/software_break_point first level handler.
* Called with MMU off, so the first thing we do is enable it
@@ -788,9 +793,7 @@ no_underflow:
! exceptions
add SP, ZERO, r14
-#define POOR_MANS_STRACE 0
-
-#if POOR_MANS_STRACE
+#ifdef CONFIG_POOR_MANS_STRACE
/* We've pushed all the registers now, so only r2-r4 hold anything
* useful. Move them into callee save registers */
or r2, ZERO, r28
@@ -811,7 +814,6 @@ no_underflow:
or r30, ZERO, r4
#endif
-
/* For syscall and debug race condition, get TRA now */
getcon TRA, r5
@@ -866,7 +868,7 @@ no_underflow:
*/
.global ret_from_irq
ret_from_irq:
-#if POOR_MANS_STRACE
+#ifdef CONFIG_POOR_MANS_STRACE
pta evt_debug_ret_from_irq, tr0
ori SP, 0, r2
blink tr0, LINK
@@ -884,7 +886,7 @@ ret_from_irq:
ret_from_exception:
preempt_stop()
-#if POOR_MANS_STRACE
+#ifdef CONFIG_POOR_MANS_STRACE
pta evt_debug_ret_from_exc, tr0
ori SP, 0, r2
blink tr0, LINK
@@ -1141,7 +1143,7 @@ call_do_page_fault:
fpu_error_or_IRQA:
pta its_IRQ, tr0
beqi/l r4, EVENT_INTERRUPT, tr0
-#ifndef CONFIG_NOFPU_SUPPORT
+#ifdef CONFIG_SH_FPU
movi do_fpu_state_restore, r6
#else
movi do_exception_error, r6
@@ -1152,7 +1154,7 @@ fpu_error_or_IRQA:
fpu_error_or_IRQB:
pta its_IRQ, tr0
beqi/l r4, EVENT_INTERRUPT, tr0
-#ifndef CONFIG_NOFPU_SUPPORT
+#ifdef CONFIG_SH_FPU
movi do_fpu_state_restore, r6
#else
movi do_exception_error, r6
@@ -1223,7 +1225,7 @@ syscall_bad:
syscall_ret:
st.q SP, FRAME_R(9), r2 /* Expecting SP back to BASIC frame */
-#if POOR_MANS_STRACE
+#ifdef CONFIG_POOR_MANS_STRACE
/* nothing useful in registers at this point */
movi evt_debug2, r5
@@ -1254,7 +1256,7 @@ ret_from_fork:
ptabs r5, tr0
blink tr0, LINK
-#if POOR_MANS_STRACE
+#ifdef CONFIG_POOR_MANS_STRACE
/* nothing useful in registers at this point */
movi evt_debug2, r5
diff --git a/arch/sh64/kernel/head.S b/arch/sh64/kernel/head.S
index 667aef4791636..cc0b628a9ea7a 100644
--- a/arch/sh64/kernel/head.S
+++ b/arch/sh64/kernel/head.S
@@ -96,8 +96,8 @@ empty_zero_page:
.long 0 /* RAMDISK_FLAGS */
.long 0x0200 /* ORIG_ROOT_DEV */
.long 1 /* LOADER_TYPE */
- .long 0x00360000 /* INITRD_START */
- .long 0x000a0000 /* INITRD_SIZE */
+ .long 0x00800000 /* INITRD_START */
+ .long 0x00800000 /* INITRD_SIZE */
.long 0
.text
@@ -310,7 +310,7 @@ hyperspace: /* ... that's the next instruction ! */
*/
movi fpu_in_use, r31 /* Temporary */
-#ifndef CONFIG_NOFPU_SUPPORT
+#ifdef CONFIG_SH_FPU
getcon SR, r21
movi SR_ENABLE_FPU, r22
and r21, r22, r22
diff --git a/arch/sh64/kernel/irq.c b/arch/sh64/kernel/irq.c
index b0f138f545a88..9fc2b71dbd84b 100644
--- a/arch/sh64/kernel/irq.c
+++ b/arch/sh64/kernel/irq.c
@@ -39,57 +39,11 @@
#include <asm/irq.h>
#include <linux/irq.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
- }
-};
-
-
-/*
- * 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 enable_none(unsigned int irq) { }
-static unsigned int startup_none(unsigned int irq) { return 0; }
-static void disable_none(unsigned int irq) { }
-static void ack_none(unsigned int irq)
+void ack_bad_irq(unsigned int irq)
{
-/*
- * 'what should we do if we get a hw irq event on an illegal vector'.
- * each architecture has to answer this themselves, it doesnt deserve
- * a generic callback i think.
- */
printk("unexpected IRQ trap at irq %02x\n", irq);
}
-/* startup is the same as "enable", shutdown is same as "disable" */
-#define shutdown_none disable_none
-#define end_none enable_none
-
-struct hw_interrupt_type no_irq_type = {
- "none",
- startup_none,
- shutdown_none,
- enable_none,
- disable_none,
- ack_none,
- end_none
-};
-
#if defined(CONFIG_PROC_FS)
int show_interrupts(struct seq_file *p, void *v)
{
@@ -139,584 +93,24 @@ asmlinkage void do_NMI(unsigned long vector_num, struct pt_regs * regs)
}
/*
- * This should really return information about whether
- * we should do bottom half handling etc. Right now we
- * end up _always_ checking the bottom half, which is a
- * waste of time and is not what some drivers would
- * prefer.
- */
-int handle_IRQ_event(unsigned int irq, struct pt_regs * regs, struct irqaction * action)
-{
- int status;
- int ret;
-
- status = 1; /* Force the "do bottom halves" bit */
-
- if (!(action->flags & SA_INTERRUPT))
- local_irq_enable();
-
- do {
- 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.
- */
-
-/**
- * disable_irq_nosync - disable an irq without waiting
- * @irq: Interrupt to disable
- *
- * Disable the selected interrupt line. Disables of an interrupt
- * stack. Unlike disable_irq(), this function does not ensure existing
- * instances of the IRQ handler have completed before returning.
- *
- * This function may be called from IRQ context.
- */
-void 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);
-}
-
-/**
- * disable_irq - disable an irq and wait for completion
- * @irq: Interrupt to disable
- *
- * Disable the selected interrupt line. Disables of an interrupt
- * stack. That is for two disables you need two enables. This
- * function waits for any pending IRQ handlers for this interrupt
- * to complete before returning. If you use this function while
- * holding a resource the IRQ handler may need you will deadlock.
- *
- * This function may be called - with care - from IRQ context.
- */
-void disable_irq(unsigned int irq)
-{
- disable_irq_nosync(irq);
- synchronize_irq(irq);
-}
-
-/**
- * enable_irq - enable interrupt handling on an irq
- * @irq: Interrupt to enable
- *
- * Re-enables the processing of interrupts on this IRQ line
- * providing no disable_irq calls are now in effect.
- *
- * This function may be called from IRQ context.
- */
-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("enable_irq() unbalanced from %p\n",
- __builtin_return_address(0));
- }
- spin_unlock_irqrestore(&desc->lock, flags);
-}
-
-/*
* do_IRQ handles all normal device IRQ's.
*/
asmlinkage int do_IRQ(unsigned long vector_num, struct pt_regs * regs)
{
- /*
- * We ack quickly, we don't want the irq controller
- * thinking we're snobs just because some other CPU has
- * disabled global interrupts (we have already done the
- * INT_ACK cycles, it's too late to try to pretend to the
- * controller that we aren't taking the interrupt).
- *
- * 0 return value means that this irq is already being
- * handled by some other CPU. (or is disabled)
- */
int irq;
- int cpu = smp_processor_id();
- irq_desc_t *desc = NULL;
- struct irqaction * action;
- unsigned int status;
irq_enter();
-#ifdef CONFIG_PREEMPT
- /*
- * At this point we're now about to actually call handlers,
- * and interrupts might get reenabled during them... bump
- * preempt_count to prevent any preemption while the handler
- * called here is pending...
- */
- preempt_disable();
-#endif
-
irq = irq_demux(vector_num);
- /*
- * Should never happen, if it does check
- * vectorN_to_IRQ[] against trap_jtable[].
- */
- if (irq == -1) {
+ if (irq >= 0) {
+ __do_IRQ(irq, regs);
+ } else {
printk("unexpected IRQ trap at vector %03lx\n", vector_num);
- goto out;
- }
-
- desc = irq_desc + irq;
-
- kstat_cpu(cpu).irqs[irq]++;
- spin_lock(&desc->lock);
- 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 | IRQ_INPROGRESS);
- 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 do_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))
- 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.
- */
- if (desc) {
- desc->handler->end(irq);
- spin_unlock(&desc->lock);
}
irq_exit();
-#ifdef CONFIG_PREEMPT
- /*
- * We're done with the handlers, interrupts should be
- * currently disabled; decrement preempt_count now so
- * as we return preemption may be allowed...
- */
- preempt_enable_no_resched();
-#endif
-
return 1;
}
-/**
- * request_irq - allocate an interrupt line
- * @irq: Interrupt line to allocate
- * @handler: Function to be called when the IRQ occurs
- * @irqflags: Interrupt type flags
- * @devname: An ascii name for the claiming device
- * @dev_id: A cookie passed back to the handler function
- *
- * This call allocates interrupt resources and enables the
- * interrupt line and IRQ handling. From the point this
- * call is made your handler function may be invoked. Since
- * your handler function must clear any interrupt the board
- * raises, you must take care both to initialise your hardware
- * and to set up the interrupt handler in the right order.
- *
- * Dev_id must be globally unique. Normally the address of the
- * device data structure is used as the cookie. Since the handler
- * receives this value it makes sense to use it.
- *
- * If your interrupt is shared you must pass a non NULL dev_id
- * as this is required when freeing the interrupt.
- *
- * Flags:
- *
- * SA_SHIRQ Interrupt is shared
- *
- * SA_INTERRUPT Disable local interrupts while processing
- *
- * SA_SAMPLE_RANDOM The interrupt can be used for entropy
- *
- */
-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 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) {
- if (!dev_id)
- printk("Bad boy: %s (at 0x%x) called us without a dev_id!\n", devname, (&irq)[-1]);
- }
-#endif
-
- if (irq >= NR_IRQS)
- return -EINVAL;
- if (!handler)
- return -EINVAL;
-
- 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;
-
- retval = setup_irq(irq, action);
- if (retval)
- kfree(action);
- return retval;
-}
-
-/**
- * free_irq - free an interrupt
- * @irq: Interrupt line to free
- * @dev_id: Device identity to free
- *
- * Remove an interrupt handler. The handler is removed and if the
- * interrupt line is no longer in use by any driver it is disabled.
- * On a shared IRQ the caller must ensure the interrupt is disabled
- * on the card it drives before calling this function. The function
- * does not return until any executing interrupts for this IRQ
- * have completed.
- *
- * This function may be called from interrupt context.
- *
- * Bugs: Attempting to free an irq in a handler for the same irq hangs
- * the machine.
- */
-void free_irq(unsigned int irq, void *dev_id)
-{
- irq_desc_t *desc;
- struct irqaction **p;
- unsigned long flags;
-
- if (irq >= NR_IRQS)
- 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 it - 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);
- kfree(action);
- return;
- }
- printk("Trying to free free IRQ%d\n",irq);
- spin_unlock_irqrestore(&desc->lock,flags);
- return;
- }
-}
-
-/*
- * 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.
- */
-
-/**
- * probe_irq_on - begin an interrupt autodetect
- *
- * Commence probing for an interrupt. The interrupts are scanned
- * and a mask of potential interrupt lines is returned.
- *
- */
-unsigned long probe_irq_on(void)
-{
- unsigned int i;
- irq_desc_t *desc;
- unsigned long val;
- unsigned long delay;
-
- /*
- * 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 */ synchronize_irq();
-
- /*
- * enable any unassigned irqs
- * (we must startup again here because if a longstanding irq
- * happened in the previous stage, it may have masked itself)
- */
- for (i = NR_IRQS-1; i >= 0; i--) {
- desc = irq_desc + 1;
-
- 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 */ synchronize_irq();
-
- /*
- * 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;
-}
-
-/*
- * Return the one interrupt that triggered (this can
- * handle any interrupt source).
- */
-
-/**
- * probe_irq_off - end an interrupt autodetect
- * @val: mask of potential interrupts (unused)
- *
- * Scans the unused interrupt lines and returns the line which
- * appears to have triggered the interrupt. If no interrupt was
- * found then zero is returned. If more than one interrupt is
- * found then minus the first candidate is returned to indicate
- * their is doubt.
- *
- * The interrupt probe logic state is returned to its previous
- * value.
- *
- * BUGS: When used in a module (which arguably shouldnt happen)
- * nothing prevents two IRQ probe callers from overlapping. The
- * results of this are non-optimal.
- */
-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))
- continue;
-
- 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;
-}
-
-int setup_irq(unsigned int irq, struct irqaction * new)
-{
- int shared = 0;
- unsigned long flags;
- struct irqaction *old, **p;
- irq_desc_t *desc = irq_desc + irq;
-
- /*
- * 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;
- desc->handler->startup(irq);
- }
- spin_unlock_irqrestore(&desc->lock,flags);
-
- /*
- * No PROC FS support for interrupts.
- * For improvements in this area please check
- * the i386 branch.
- */
- return 0;
-}
-
-#if defined(CONFIG_PROC_FS) && defined(CONFIG_SYSCTL)
-
-void init_irq_proc(void)
-{
- /*
- * No PROC FS support for interrupts.
- * For improvements in this area please check
- * the i386 branch.
- */
-}
-#endif
diff --git a/arch/sh64/kernel/module.c b/arch/sh64/kernel/module.c
new file mode 100644
index 0000000000000..2598f6b88b447
--- /dev/null
+++ b/arch/sh64/kernel/module.c
@@ -0,0 +1,161 @@
+/* Kernel module help for sh64.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the 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 2004 SuperH (UK) Ltd
+ Author: Richard Curnow
+
+ Based on the sh version, and on code from the sh64-specific parts of
+ modutils, originally written by Richard Curnow and Ben Gaster.
+
+*/
+#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(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_add(Elf32_Shdr *sechdrs,
+ const char *strtab,
+ unsigned int symindex,
+ unsigned int relsec,
+ struct module *me)
+{
+ unsigned int i;
+ Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
+ Elf32_Sym *sym;
+ Elf32_Addr relocation;
+ uint32_t *location;
+ int align;
+ int is_shmedia;
+
+ DEBUGP("Applying relocate section %u to %u\n", relsec,
+ sechdrs[relsec].sh_info);
+ for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
+ /* This is where to make the change */
+ location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
+ + rel[i].r_offset;
+ /* This is the symbol it is referring to. Note that all
+ undefined symbols have been resolved. */
+ sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
+ + ELF32_R_SYM(rel[i].r_info);
+ relocation = sym->st_value + rel[i].r_addend;
+ align = (int)location & 3;
+
+ /* For text addresses, bit2 of the st_other field indicates
+ * whether the symbol is SHmedia (1) or SHcompact (0). If
+ * SHmedia, the LSB of the symbol needs to be asserted
+ * for the CPU to be in SHmedia mode when it starts executing
+ * the branch target. */
+ is_shmedia = (sym->st_other & 4) ? 1 : 0;
+ if (is_shmedia) {
+ relocation |= 1;
+ }
+
+ switch (ELF32_R_TYPE(rel[i].r_info)) {
+ case R_SH_DIR32:
+ DEBUGP("R_SH_DIR32 @%08lx = %08lx\n", (unsigned long) location, (unsigned long) relocation);
+ *location += relocation;
+ break;
+ case R_SH_REL32:
+ DEBUGP("R_SH_REL32 @%08lx = %08lx\n", (unsigned long) location, (unsigned long) relocation);
+ relocation -= (Elf32_Addr) location;
+ *location += relocation;
+ break;
+ case R_SH_IMM_LOW16:
+ DEBUGP("R_SH_IMM_LOW16 @%08lx = %08lx\n", (unsigned long) location, (unsigned long) relocation);
+ *location = (*location & ~0x3fffc00) |
+ ((relocation & 0xffff) << 10);
+ break;
+ case R_SH_IMM_MEDLOW16:
+ DEBUGP("R_SH_IMM_MEDLOW16 @%08lx = %08lx\n", (unsigned long) location, (unsigned long) relocation);
+ *location = (*location & ~0x3fffc00) |
+ (((relocation >> 16) & 0xffff) << 10);
+ break;
+ case R_SH_IMM_LOW16_PCREL:
+ DEBUGP("R_SH_IMM_LOW16_PCREL @%08lx = %08lx\n", (unsigned long) location, (unsigned long) relocation);
+ relocation -= (Elf32_Addr) location;
+ *location = (*location & ~0x3fffc00) |
+ ((relocation & 0xffff) << 10);
+ break;
+ case R_SH_IMM_MEDLOW16_PCREL:
+ DEBUGP("R_SH_IMM_MEDLOW16_PCREL @%08lx = %08lx\n", (unsigned long) location, (unsigned long) relocation);
+ relocation -= (Elf32_Addr) location;
+ *location = (*location & ~0x3fffc00) |
+ (((relocation >> 16) & 0xffff) << 10);
+ break;
+ default:
+ printk(KERN_ERR "module %s: Unknown relocation: %u\n",
+ me->name, ELF32_R_TYPE(rel[i].r_info));
+ return -ENOEXEC;
+ }
+ }
+ 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: REL 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/sh64/kernel/pci_sh5.c b/arch/sh64/kernel/pci_sh5.c
index 368cab7a9ba96..6197879e8578e 100644
--- a/arch/sh64/kernel/pci_sh5.c
+++ b/arch/sh64/kernel/pci_sh5.c
@@ -39,7 +39,7 @@ static void __init pci_fixup_ide_bases(struct pci_dev *d)
*/
if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE)
return;
- printk("PCI: IDE base address fixup for %s\n", d->slot_name);
+ printk("PCI: IDE base address fixup for %s\n", pci_name(d));
for(i=0; i<4; i++) {
struct resource *r = &d->resource[i];
if ((r->start & ~0x80) == 0x374) {
diff --git a/arch/sh64/kernel/pcibios.c b/arch/sh64/kernel/pcibios.c
index bc4ef398771fe..4f707dfd5dc18 100644
--- a/arch/sh64/kernel/pcibios.c
+++ b/arch/sh64/kernel/pcibios.c
@@ -57,7 +57,7 @@ pcibios_update_resource(struct pci_dev *dev, struct resource *root,
pci_read_config_dword(dev, reg, &check);
if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) {
printk(KERN_ERR "PCI: Error while updating region "
- "%s/%d (%08x != %08x)\n", dev->slot_name, resource,
+ "%s/%d (%08x != %08x)\n", pci_name(dev), resource,
new, check);
}
}
@@ -125,7 +125,7 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
continue;
r = &dev->resource[idx];
if (!r->start && r->end) {
- printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", dev->slot_name);
+ printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", pci_name(dev));
return -EINVAL;
}
if (r->flags & IORESOURCE_IO)
diff --git a/arch/sh64/kernel/process.c b/arch/sh64/kernel/process.c
index e3f509ea6ec3b..efde41c0cd669 100644
--- a/arch/sh64/kernel/process.c
+++ b/arch/sh64/kernel/process.c
@@ -638,7 +638,6 @@ void free_task_struct(struct task_struct *p)
int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
{
/* A bit less processor dependent than older sh ... */
-
unsigned int reply;
static __inline__ _syscall2(int,clone,unsigned long,flags,unsigned long,newsp)
@@ -671,7 +670,7 @@ void exit_thread(void)
null it here, there is no other path through which it would get safely
nulled. */
-#ifndef CONFIG_NOFPU_SUPPORT
+#ifdef CONFIG_SH_FPU
if (last_task_used_math == current) {
last_task_used_math = NULL;
}
@@ -683,7 +682,7 @@ void flush_thread(void)
/* Called by fs/exec.c (flush_old_exec) to remove traces of a
* previously running executable. */
-#ifndef CONFIG_NOFPU_SUPPORT
+#ifdef CONFIG_SH_FPU
if (last_task_used_math == current) {
last_task_used_math = NULL;
}
@@ -709,7 +708,7 @@ void release_thread(struct task_struct *dead_task)
/* Fill in the fpu structure for a core dump.. */
int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu)
{
-#ifndef CONFIG_NOFPU_SUPPORT
+#ifdef CONFIG_SH_FPU
int fpvalid;
struct task_struct *tsk = current;
@@ -741,7 +740,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
struct pt_regs *childregs;
unsigned long long se; /* Sign extension */
-#ifndef CONFIG_NOFPU_SUPPORT
+#ifdef CONFIG_SH_FPU
if(last_task_used_math == current) {
grab_fpu();
fpsave(&current->thread.fpu.hard);
@@ -933,7 +932,7 @@ asids_proc_info(char *buf, char **start, off_t fpos, int length, int *eof, void
int len=0;
struct task_struct *p;
read_lock(&tasklist_lock);
- for_each_task(p) {
+ for_each_process(p) {
int pid = p->pid;
struct mm_struct *mm;
if (!pid) continue;
@@ -942,7 +941,7 @@ asids_proc_info(char *buf, char **start, off_t fpos, int length, int *eof, void
unsigned long asid, context;
context = mm->context;
asid = (context & 0xff);
- len += sprintf(buf+len, "%5d : %02x\n", pid, asid);
+ len += sprintf(buf+len, "%5d : %02lx\n", pid, asid);
} else {
len += sprintf(buf+len, "%5d : (none)\n", pid);
}
diff --git a/arch/sh64/kernel/ptrace.c b/arch/sh64/kernel/ptrace.c
index 27c1a32cc0ea3..800288c1562b4 100644
--- a/arch/sh64/kernel/ptrace.c
+++ b/arch/sh64/kernel/ptrace.c
@@ -123,9 +123,26 @@ put_fpu_long(struct task_struct *task, unsigned long addr, unsigned long data)
asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
{
struct task_struct *child;
+ extern void poke_real_address_q(unsigned long long addr, unsigned long long data);
+#define WPC_DBRMODE 0x0d104008
+ static int first_call = 1;
int ret;
lock_kernel();
+
+ if (first_call) {
+ /* Set WPC.DBRMODE to 0. This makes all debug events get
+ * delivered through RESVEC, i.e. into the handlers in entry.S.
+ * (If the kernel was downloaded using a remote gdb, WPC.DBRMODE
+ * would normally be left set to 1, which makes debug events get
+ * delivered through DBRVEC, i.e. into the remote gdb's
+ * handlers. This prevents ptrace getting them, and confuses
+ * the remote gdb.) */
+ printk("DBRMODE set to 0 to permit native debugging\n");
+ poke_real_address_q(WPC_DBRMODE, 0);
+ first_call = 0;
+ }
+
ret = -EPERM;
if (request == PTRACE_TRACEME) {
/* are we already being traced? */
diff --git a/arch/sh64/kernel/setup.c b/arch/sh64/kernel/setup.c
index ce76634d64065..c7a7b816a30f3 100644
--- a/arch/sh64/kernel/setup.c
+++ b/arch/sh64/kernel/setup.c
@@ -65,10 +65,6 @@
struct screen_info screen_info;
-/* On a PC this would be initialised as a result of the BIOS detecting the
- * mouse. */
-unsigned char aux_device_present = 0xaa;
-
#ifdef CONFIG_BLK_DEV_RAM
extern int rd_doload; /* 1 = load ramdisk, 0 = don't load */
extern int rd_prompt; /* 1 = prompt for ramdisk, 0 = don't prompt */
diff --git a/arch/sh64/kernel/sh_ksyms.c b/arch/sh64/kernel/sh_ksyms.c
index 36cd5de959bd7..0b5497d70bd37 100644
--- a/arch/sh64/kernel/sh_ksyms.c
+++ b/arch/sh64/kernel/sh_ksyms.c
@@ -19,6 +19,7 @@
#include <linux/in6.h>
#include <linux/interrupt.h>
#include <linux/smp_lock.h>
+#include <linux/tty.h>
#include <asm/semaphore.h>
#include <asm/processor.h>
@@ -50,7 +51,6 @@ EXPORT_SYMBOL(kernel_thread);
/* Networking helper routines. */
EXPORT_SYMBOL(csum_partial_copy);
-EXPORT_SYMBOL(strtok);
EXPORT_SYMBOL(strpbrk);
EXPORT_SYMBOL(strstr);
@@ -72,12 +72,18 @@ EXPORT_SYMBOL(strlen);
EXPORT_SYMBOL(flush_dcache_page);
+/* For ext3 */
+EXPORT_SYMBOL(sh64_page_clear);
+
/* Ugh. These come in from libgcc.a at link time. */
extern void __sdivsi3(void);
extern void __muldi3(void);
extern void __udivsi3(void);
+extern char __div_table;
EXPORT_SYMBOL(__sdivsi3);
EXPORT_SYMBOL(__muldi3);
EXPORT_SYMBOL(__udivsi3);
+EXPORT_SYMBOL(__div_table);
+
diff --git a/arch/sh64/kernel/signal.c b/arch/sh64/kernel/signal.c
index 608f6796a2e5c..45ad1026dde75 100644
--- a/arch/sh64/kernel/signal.c
+++ b/arch/sh64/kernel/signal.c
@@ -125,7 +125,7 @@ sys_sigaction(int sig, const struct old_sigaction __user *act,
if (act) {
old_sigset_t mask;
- if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
+ if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
__get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
__get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
return -EFAULT;
@@ -137,7 +137,7 @@ sys_sigaction(int sig, const struct old_sigaction __user *act,
ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
if (!ret && oact) {
- if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
+ if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
__put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
__put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
return -EFAULT;
@@ -178,7 +178,7 @@ struct rt_sigframe
long long retcode[2];
};
-#ifndef CONFIG_NOFPU_SUPPORT
+#ifdef CONFIG_SH_FPU
static inline int
restore_sigcontext_fpu(struct pt_regs *regs, struct sigcontext __user *sc)
{
@@ -293,7 +293,7 @@ asmlinkage int sys_sigreturn(unsigned long r2, unsigned long r3,
sigset_t set;
long long ret;
- if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
+ if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
goto badframe;
if (__get_user(set.sig[0], &frame->sc.oldmask)
@@ -330,7 +330,7 @@ asmlinkage int sys_rt_sigreturn(unsigned long r2, unsigned long r3,
stack_t __user st;
long long ret;
- if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
+ if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
goto badframe;
if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
@@ -634,11 +634,9 @@ give_sigsegv:
*/
static void
-handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,
- struct pt_regs * regs)
+handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
+ sigset_t *oldset, struct pt_regs * regs)
{
- struct k_sigaction *ka = &current->sighand->action[sig-1];
-
/* Are we from a system call? */
if (regs->syscall_nr >= 0) {
/* If so, check system call restarting.. */
@@ -666,9 +664,6 @@ handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,
else
setup_frame(sig, ka, oldset, regs);
- if (ka->sa.sa_flags & SA_ONESHOT)
- ka->sa.sa_handler = SIG_DFL;
-
if (!(ka->sa.sa_flags & SA_NODEFER)) {
spin_lock_irq(&current->sighand->siglock);
sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
@@ -691,6 +686,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
{
siginfo_t info;
int signr;
+ struct k_sigaction ka;
/*
* We want the common case to go fast, which
@@ -707,11 +703,11 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
if (!oldset)
oldset = &current->blocked;
- signr = get_signal_to_deliver(&info, regs, 0);
+ signr = get_signal_to_deliver(&info, &ka, regs, 0);
if (signr > 0) {
/* Whee! Actually deliver the signal. */
- handle_signal(signr, &info, oldset, regs);
+ handle_signal(signr, &info, &ka, oldset, regs);
return 1;
}
diff --git a/arch/sh64/kernel/switchto.S b/arch/sh64/kernel/switchto.S
index 24ef14c83be61..45b2d90eed7d1 100644
--- a/arch/sh64/kernel/switchto.S
+++ b/arch/sh64/kernel/switchto.S
@@ -27,7 +27,7 @@ sh64_switch_to:
r5 - &next->thread
Outgoing results
- r2 - last (=prev)
+ r2 - last (=prev) : this just stays in r2 throughout
Want to create a full (struct pt_regs) on the stack to allow backtracing
functions to work. However, we only need to populate the callee-save
@@ -188,7 +188,6 @@ sh64_switch_to:
! epilogue
ld.l r15, 0, r18
ld.l r15, 4, r14
- ori r4, 0, r2 ! last = prev
ptabs r18, tr0
movi FRAME_SIZE, r0
add r15, r0, r15
diff --git a/arch/sh64/kernel/sys_sh64.c b/arch/sh64/kernel/sys_sh64.c
index 6d99a970135a9..4546845b9caf4 100644
--- a/arch/sh64/kernel/sys_sh64.c
+++ b/arch/sh64/kernel/sys_sh64.c
@@ -284,3 +284,17 @@ asmlinkage int sys_uname(struct old_utsname * name)
return err?-EFAULT:0;
}
+/* Copy from mips version */
+asmlinkage long sys_shmatcall(int shmid, char __user *shmaddr,
+ int shmflg)
+{
+ unsigned long raddr;
+ int err;
+
+ err = do_shmat(shmid, shmaddr, shmflg, &raddr);
+ if (err)
+ return err;
+
+ err = raddr;
+ return err;
+}
diff --git a/arch/sh64/kernel/syscalls.S b/arch/sh64/kernel/syscalls.S
index 819e335af15be..8ed417df3dc64 100644
--- a/arch/sh64/kernel/syscalls.S
+++ b/arch/sh64/kernel/syscalls.S
@@ -268,7 +268,7 @@ sys_call_table:
.long sys_msgrcv
.long sys_msgget
.long sys_msgctl
- .long sys_ni_syscall /* sys_shmatcall */
+ .long sys_shmatcall
.long sys_shmdt /* 245 */
.long sys_shmget
.long sys_shmctl
@@ -337,4 +337,9 @@ sys_call_table:
.long sys_mq_timedreceive
.long sys_mq_notify
.long sys_mq_getsetattr /* 310 */
+ .long sys_ni_syscall /* Reserved for kexec */
+ .long sys_waitid
+ .long sys_add_key
+ .long sys_request_key
+ .long sys_keyctl /* 315 */
diff --git a/arch/sh64/kernel/time.c b/arch/sh64/kernel/time.c
index 9d73104f68177..6c84da3efc738 100644
--- a/arch/sh64/kernel/time.c
+++ b/arch/sh64/kernel/time.c
@@ -45,6 +45,7 @@
#define TMU_TOCR_INIT 0x00
#define TMU0_TCR_INIT 0x0020
#define TMU_TSTR_INIT 1
+#define TMU_TSTR_OFF 0
/* RCR1 Bits */
#define RCR1_CF 0x80 /* Carry Flag */
@@ -424,7 +425,7 @@ static __init unsigned int get_cpu_hz(void)
*/
register unsigned long long __rtc_irq_flag __asm__ ("r3");
- sti();
+ local_irq_enable();
do {} while (ctrl_inb(R64CNT) != 0);
ctrl_outb(RCR1_CIE, RCR1); /* Enable carry interrupt */
@@ -443,7 +444,7 @@ static __init unsigned int get_cpu_hz(void)
"getcon " __CTC ", %0\n\t"
: "=r"(ctc_val), "=r" (__dummy), "=r" (__rtc_irq_flag)
: "0" (0));
- cli();
+ local_irq_disable();
/*
* SH-3:
* CPU clock = 4 stages * loop
@@ -561,6 +562,7 @@ void __init time_init(void)
current_cpu_data.module_clock = module_clock;
/* Start TMU0 */
+ ctrl_outb(TMU_TSTR_OFF, TMU_TSTR);
ctrl_outb(TMU_TOCR_INIT, TMU_TOCR);
ctrl_outw(TMU0_TCR_INIT, TMU0_TCR);
ctrl_outl(interval, TMU0_TCOR);
diff --git a/arch/sh64/kernel/traps.c b/arch/sh64/kernel/traps.c
index b2b2bde303349..224b7f5b92246 100644
--- a/arch/sh64/kernel/traps.c
+++ b/arch/sh64/kernel/traps.c
@@ -30,6 +30,7 @@
#include <linux/kallsyms.h>
#include <linux/interrupt.h>
#include <linux/sysctl.h>
+#include <linux/module.h>
#include <asm/system.h>
#include <asm/uaccess.h>
@@ -286,6 +287,8 @@ void dump_stack(void)
{
show_task(NULL);
}
+/* Needed by any user of WARN_ON in view of the defn in include/asm-sh/bug.h */
+EXPORT_SYMBOL(dump_stack);
static void do_unhandled_exception(int trapnr, int signr, char *str, char *fn_name,
unsigned long error_code, struct pt_regs *regs, struct task_struct *tsk)
diff --git a/arch/sh64/lib/Makefile b/arch/sh64/lib/Makefile
index 0a2dc69bedd35..6a4cc3f9c0b12 100644
--- a/arch/sh64/lib/Makefile
+++ b/arch/sh64/lib/Makefile
@@ -15,5 +15,5 @@
# Panic should really be compiled as PIC
lib-y := udelay.o c-checksum.o dbg.o io.o panic.o memcpy.o copy_user_memcpy.o \
- page_copy.o page_clear.o
+ page_copy.o page_clear.o iomap.o
diff --git a/arch/sh64/lib/copy_user_memcpy.S b/arch/sh64/lib/copy_user_memcpy.S
index 5b6ca39234b84..2a62816d2ddd5 100644
--- a/arch/sh64/lib/copy_user_memcpy.S
+++ b/arch/sh64/lib/copy_user_memcpy.S
@@ -46,6 +46,11 @@
*/
+/* NOTE : Prefetches removed and allocos guarded by synco to avoid TAKum03020
+ * erratum. The first two prefetches are nop-ed out to avoid upsetting the
+ * instruction counts used in the jump address calculation.
+ * */
+
.section .text..SHmedia32,"ax"
.little
.balign 32
@@ -58,7 +63,7 @@ copy_user_memcpy:
#define LDUAL(P,O,D0,D1) ldlo.l P,O,D0; ldhi.l P,O+3,D1
#define STUAL(P,O,D0,D1) stlo.l P,O,D0; sthi.l P,O+3,D1
- ld.b r3,0,r63
+ nop ! ld.b r3,0,r63 ! TAKum03020
pta/l Large,tr0
movi 25,r0
bgeu/u r4,r0,tr0
@@ -108,7 +113,7 @@ L8_15: /* 8..15 byte memcpy cntd. */
/* 2 or 3 byte memcpy */
ld.b r3,0,r0
- ld.b r2,0,r63
+ nop ! ld.b r2,0,r63 ! TAKum03020
ld.b r3,1,r1
st.b r2,0,r0
pta/l L2_3,tr0
@@ -151,7 +156,7 @@ L8_15: /* 8..15 byte memcpy cntd. */
blink tr1,r63
Large:
- ld.b r2, 0, r63
+ ! ld.b r2, 0, r63 ! TAKum03020
pta/l Loop_ua, tr1
ori r3, -8, r7
sub r2, r7, r22
@@ -173,8 +178,7 @@ Large:
addi r6, -8, r21
Loop_line:
- ldx.q r22, r36, r63
- synco
+ ! ldx.q r22, r36, r63 ! TAKum03020
alloco r22, 32
synco
addi r22, 32, r22
diff --git a/arch/sh64/lib/dbg.c b/arch/sh64/lib/dbg.c
index d74913fe399cb..526fedae6db87 100644
--- a/arch/sh64/lib/dbg.c
+++ b/arch/sh64/lib/dbg.c
@@ -8,6 +8,7 @@
-- Copyright 2004 Richard Curnow (evt_debug etc)
--
--------------------------------------------------------------------------*/
+#include <linux/config.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/sched.h>
@@ -136,6 +137,8 @@ void print_itlb(void)
/* ======================================================================= */
+#ifdef CONFIG_POOR_MANS_STRACE
+
#include "syscalltab.h"
struct ring_node {
@@ -151,6 +154,17 @@ struct ring_node {
static struct ring_node event_ring[16];
static int event_ptr = 0;
+struct stored_syscall_data {
+ int pid;
+ int syscall_number;
+};
+
+#define N_STORED_SYSCALLS 16
+
+static struct stored_syscall_data stored_syscalls[N_STORED_SYSCALLS];
+static int syscall_next=0;
+static int syscall_next_print=0;
+
void evt_debug(int evt, int ret_addr, int event, int tra, struct pt_regs *regs)
{
int syscallno = tra & 0xff;
@@ -187,15 +201,35 @@ void evt_debug(int evt, int ret_addr, int event, int tra, struct pt_regs *regs)
event_ptr = (event_ptr + 1) & 15;
if ((event == 2) && (evt == 0x160)) {
- if (syscallno < NUM_SYSCALL_INFO_ENTRIES)
- printk("Task %d: %s()\n",
- current->pid,
- syscall_info_table[syscallno].name);
+ if (syscallno < NUM_SYSCALL_INFO_ENTRIES) {
+ /* Store the syscall information to print later. We
+ * can't print this now - currently we're running with
+ * SR.BL=1, so we can't take a tlbmiss (which could occur
+ * in the console drivers under printk).
+ *
+ * Just overwrite old entries on ring overflow - this
+ * is only for last-hope debugging. */
+ stored_syscalls[syscall_next].pid = current->pid;
+ stored_syscalls[syscall_next].syscall_number = syscallno;
+ syscall_next++;
+ syscall_next &= (N_STORED_SYSCALLS - 1);
+ }
+ }
+}
+
+static void drain_syscalls(void) {
+ while (syscall_next_print != syscall_next) {
+ printk("Task %d: %s()\n",
+ stored_syscalls[syscall_next_print].pid,
+ syscall_info_table[stored_syscalls[syscall_next_print].syscall_number].name);
+ syscall_next_print++;
+ syscall_next_print &= (N_STORED_SYSCALLS - 1);
}
}
void evt_debug2(unsigned int ret)
{
+ drain_syscalls();
printk("Task %d: syscall returns %08x\n", current->pid, ret);
}
@@ -231,6 +265,8 @@ void evt_debug_ret_from_exc(struct pt_regs *regs)
event_ptr = (event_ptr + 1) & 15;
}
+#endif /* CONFIG_POOR_MANS_STRACE */
+
/* ======================================================================= */
void show_excp_regs(char *from, int trapnr, int signr, struct pt_regs *regs)
diff --git a/arch/sh64/lib/io.c b/arch/sh64/lib/io.c
index 7e8af3a9e5d71..277e11b10c2b8 100644
--- a/arch/sh64/lib/io.c
+++ b/arch/sh64/lib/io.c
@@ -9,14 +9,12 @@
*/
#include <linux/config.h>
+#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/delay.h>
#include <asm/system.h>
#include <asm/processor.h>
#include <asm/io.h>
-#ifdef CONFIG_SH_CAYMAN
-#include <asm/cayman.h>
-#endif
/*
* readX/writeX() are used to access memory mapped devices. On some
@@ -25,71 +23,6 @@
* memory location directly.
*/
-#define dprintk(x...)
-
-static int io_addr(int x) {
- if (x < 0x400) {
-#ifdef CONFIG_SH_CAYMAN
- return (x << 2) | smsc_superio_virt;
-#else
- panic ("Illegal access to I/O port 0x%04x\n", x);
- return 0;
-#endif
- } else {
-#ifdef CONFIG_PCI
- return (x + pciio_virt);
-#else
- panic ("Illegal access to I/O port 0x%04x\n", x);
- return 0;
-#endif
- }
-}
-
-unsigned long inb(unsigned long port)
-{
- unsigned long r;
-
- r = ctrl_inb(io_addr(port));
- dprintk("inb(0x%x)=0x%x (0x%x)\n", port, r, io_addr(port));
- return r;
-}
-
-unsigned long inw(unsigned long port)
-{
- unsigned long r;
-
- r = ctrl_inw(io_addr(port));
- dprintk("inw(0x%x)=0x%x (0x%x)\n", port, r, io_addr(port));
- return r;
-}
-
-unsigned long inl(unsigned long port)
-{
- unsigned long r;
-
- r = ctrl_inl(io_addr(port));
- dprintk("inl(0x%x)=0x%x (0x%x)\n", port, r, io_addr(port));
- return r;
-}
-
-void outb(unsigned long value, unsigned long port)
-{
- dprintk("outb(0x%x,0x%x) (0x%x)\n", value, port, io_addr(port));
- ctrl_outb(value, io_addr(port));
-}
-
-void outw(unsigned long value, unsigned long port)
-{
- dprintk("outw(0x%x,0x%x) (0x%x)\n", value, port, io_addr(port));
- ctrl_outw(value, io_addr(port));
-}
-
-void outl(unsigned long value, unsigned long port)
-{
- dprintk("outw(0x%x,0x%x) (0x%x)\n", value, port, io_addr(port));
- ctrl_outl(value, io_addr(port));
-}
-
/* This is horrible at the moment - needs more work to do something sensible */
#define IO_DELAY()
@@ -185,7 +118,7 @@ void insl(unsigned long port, void *addr, unsigned long count)
}
}
-void memcpy_toio(unsigned long to, const void *from, long count)
+void memcpy_toio(void __iomem *to, const void *from, long count)
{
unsigned char *p = (unsigned char *) from;
@@ -195,7 +128,7 @@ void memcpy_toio(unsigned long to, const void *from, long count)
}
}
-void memcpy_fromio(void *to, unsigned long from, long count)
+void memcpy_fromio(void *to, void __iomem *from, long count)
{
int i;
unsigned char *p = (unsigned char *) to;
diff --git a/arch/sh64/lib/iomap.c b/arch/sh64/lib/iomap.c
new file mode 100644
index 0000000000000..83c5f0c04958c
--- /dev/null
+++ b/arch/sh64/lib/iomap.c
@@ -0,0 +1,55 @@
+/*
+ * arch/sh64/lib/iomap.c
+ *
+ * Generic sh64 iomap interface
+ *
+ * Copyright (C) 2004 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/config.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+
+void __iomem *__attribute__ ((weak))
+ioport_map(unsigned long port, unsigned int len)
+{
+ return (void __iomem *)port;
+}
+
+void ioport_unmap(void __iomem *addr)
+{
+ /* Nothing .. */
+}
+
+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 + pciio_virt, len);
+ if (flags & IORESOURCE_MEM)
+ return (void __iomem *)start;
+
+ /* What? */
+ return NULL;
+}
+
+void pci_iounmap(struct pci_dev *dev, void __iomem *addr)
+{
+ /* Nothing .. */
+}
+
+EXPORT_SYMBOL(ioport_map);
+EXPORT_SYMBOL(ioport_unmap);
+EXPORT_SYMBOL(pci_iomap);
+EXPORT_SYMBOL(pci_iounmap);
+
diff --git a/arch/sh64/lib/old-checksum.c b/arch/sh64/lib/old-checksum.c
deleted file mode 100644
index df741335d367b..0000000000000
--- a/arch/sh64/lib/old-checksum.c
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * FIXME: old compatibility stuff, will be removed soon.
- */
-
-#include <net/checksum.h>
-
-unsigned int csum_partial_copy( const char *src, char *dst, int len, int sum)
-{
- int src_err=0, dst_err=0;
-
- sum = csum_partial_copy_generic ( src, dst, len, sum, &src_err, &dst_err);
-
- if (src_err || dst_err)
- printk("old csum_partial_copy_fromuser(), tell mingo to convert me.\n");
-
- return sum;
-}
diff --git a/arch/sh64/lib/page_clear.S b/arch/sh64/lib/page_clear.S
index 2aadd2c0f483b..ac0111d669a32 100644
--- a/arch/sh64/lib/page_clear.S
+++ b/arch/sh64/lib/page_clear.S
@@ -17,6 +17,8 @@
Always clears 4096 bytes.
+ Note : alloco guarded by synco to avoid TAKum03020 erratum
+
*/
.section .text..SHmedia32,"ax"
@@ -34,6 +36,7 @@ sh64_page_clear:
add r2, r63, r6
1:
alloco r6, 0
+ synco ! TAKum03020
addi r6, 32, r6
bgt/l r7, r6, tr1
diff --git a/arch/sh64/lib/page_copy.S b/arch/sh64/lib/page_copy.S
index 804d2a00d04ab..e159c3cd2582e 100644
--- a/arch/sh64/lib/page_copy.S
+++ b/arch/sh64/lib/page_copy.S
@@ -39,12 +39,17 @@ sh64_page_copy:
pta 3f, tr3
ptabs r18, tr0
+#if 0
+ /* TAKum03020 */
ld.q r2, 0x00, r63
ld.q r2, 0x20, r63
ld.q r2, 0x40, r63
ld.q r2, 0x60, r63
+#endif
alloco r3, 0x00
+ synco ! TAKum03020
alloco r3, 0x20
+ synco ! TAKum03020
movi 3968, r6
add r3, r6, r6
@@ -60,11 +65,15 @@ sh64_page_copy:
because they overlap with the time spent waiting for prefetches to
complete. */
1:
+#if 0
+ /* TAKum03020 */
bge/u r3, r6, tr2 ! skip prefetch for last 4 lines
ldx.q r3, r22, r63 ! prefetch 4 lines hence
+#endif
2:
bge/u r3, r7, tr3 ! skip alloco for last 2 lines
alloco r3, 0x40 ! alloc destination line 2 lines ahead
+ synco ! TAKum03020
3:
ldx.q r3, r60, r36
ldx.q r3, r61, r37
diff --git a/arch/sh64/mach-cayman/Makefile b/arch/sh64/mach-cayman/Makefile
index 4a48b53fcf911..67a2258bf8c47 100644
--- a/arch/sh64/mach-cayman/Makefile
+++ b/arch/sh64/mach-cayman/Makefile
@@ -6,6 +6,6 @@
# unless it's something special (ie not a .c file).
#
-obj-y := setup.o irq.o
+obj-y := setup.o irq.o iomap.o
obj-$(CONFIG_HEARTBEAT) += led.o
diff --git a/arch/sh64/mach-cayman/iomap.c b/arch/sh64/mach-cayman/iomap.c
new file mode 100644
index 0000000000000..d6a538c707094
--- /dev/null
+++ b/arch/sh64/mach-cayman/iomap.c
@@ -0,0 +1,24 @@
+/*
+ * arch/sh64/mach-cayman/iomap.c
+ *
+ * Cayman iomap interface
+ *
+ * Copyright (C) 2004 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/config.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+#include <asm/cayman.h>
+
+void __iomem *ioport_map(unsigned long port, unsigned int len)
+{
+ if (port < 0x400)
+ return (void __iomem *)((port << 2) | smsc_superio_virt);
+
+ return (void __iomem *)port;
+}
+
diff --git a/arch/sh64/mach-cayman/irq.c b/arch/sh64/mach-cayman/irq.c
index 4de91077d9398..f797c84bfdd1e 100644
--- a/arch/sh64/mach-cayman/irq.c
+++ b/arch/sh64/mach-cayman/irq.c
@@ -64,11 +64,11 @@ static void enable_cayman_irq(unsigned int irq)
irq -= START_EXT_IRQS;
reg = EPLD_MASK_BASE + ((irq / 8) << 2);
bit = 1<<(irq % 8);
- save_and_cli(flags);
+ local_irq_save(flags);
mask = ctrl_inl(reg);
mask |= bit;
ctrl_outl(mask, reg);
- restore_flags(flags);
+ local_irq_restore(flags);
}
void disable_cayman_irq(unsigned int irq)
@@ -81,11 +81,11 @@ void disable_cayman_irq(unsigned int irq)
irq -= START_EXT_IRQS;
reg = EPLD_MASK_BASE + ((irq / 8) << 2);
bit = 1<<(irq % 8);
- save_and_cli(flags);
+ local_irq_save(flags);
mask = ctrl_inl(reg);
mask &= ~bit;
ctrl_outl(mask, reg);
- restore_flags(flags);
+ local_irq_restore(flags);
}
static void ack_cayman_irq(unsigned int irq)
diff --git a/arch/sh64/mach-cayman/setup.c b/arch/sh64/mach-cayman/setup.c
index 53dfd60995030..c793245629ad7 100644
--- a/arch/sh64/mach-cayman/setup.c
+++ b/arch/sh64/mach-cayman/setup.c
@@ -33,8 +33,6 @@
#include <asm/irq.h>
#include <asm/page.h>
-#define RES_COUNT(res) ((sizeof((res))/sizeof(struct resource)))
-
/*
* Platform Dependent Interrupt Priorities.
*/
@@ -86,10 +84,14 @@
#define SMSC_DEVICE_ID_INDEX 0x20
#define SMSC_DEVICE_REV_INDEX 0x21
#define SMSC_ACTIVATE_INDEX 0x30
+#define SMSC_PRIMARY_BASE_INDEX 0x60
+#define SMSC_SECONDARY_BASE_INDEX 0x62
#define SMSC_PRIMARY_INT_INDEX 0x70
#define SMSC_SECONDARY_INT_INDEX 0x72
-#define SMSC_KEYBOARD_DEVICE 7
+#define SMSC_IDE1_DEVICE 1
+#define SMSC_KEYBOARD_DEVICE 7
+#define SMSC_CONFIG_REGISTERS 8
#define SMSC_SUPERIO_READ_INDEXED(index) ({ \
outb((index), SMSC_INDEX_PORT_ADDR); \
@@ -98,6 +100,9 @@
outb((index), SMSC_INDEX_PORT_ADDR); \
outb((val), SMSC_DATA_PORT_ADDR); })
+#define IDE1_PRIMARY_BASE 0x01f0
+#define IDE1_SECONDARY_BASE 0x03f6
+
unsigned long smsc_superio_virt;
/*
@@ -125,13 +130,13 @@ struct sh64_platform platform_parms = {
.initial_root_dev = 0x0100,
.loader_type = 1,
.io_res_p = io_resources,
- .io_res_count = RES_COUNT(io_resources),
+ .io_res_count = ARRAY_SIZE(io_resources),
.kram_res_p = kram_resources,
- .kram_res_count = RES_COUNT(kram_resources),
+ .kram_res_count = ARRAY_SIZE(kram_resources),
.xram_res_p = xram_resources,
- .xram_res_count = RES_COUNT(xram_resources),
+ .xram_res_count = ARRAY_SIZE(xram_resources),
.rom_res_p = rom_resources,
- .rom_res_count = RES_COUNT(rom_resources),
+ .rom_res_count = ARRAY_SIZE(rom_resources),
};
int platform_int_priority[NR_INTC_IRQS] = {
@@ -175,6 +180,38 @@ static int __init smsc_superio_setup(void)
SMSC_SUPERIO_WRITE_INDEXED(1, SMSC_PRIMARY_INT_INDEX);
SMSC_SUPERIO_WRITE_INDEXED(12, SMSC_SECONDARY_INT_INDEX);
+#ifdef CONFIG_IDE
+ /*
+ * Only IDE1 exists on the Cayman
+ */
+
+ /* Power it on */
+ SMSC_SUPERIO_WRITE_INDEXED(1 << SMSC_IDE1_DEVICE, 0x22);
+
+ SMSC_SUPERIO_WRITE_INDEXED(SMSC_IDE1_DEVICE, SMCS_LOGICAL_DEV_INDEX);
+ SMSC_SUPERIO_WRITE_INDEXED(1, SMSC_ACTIVATE_INDEX);
+
+ SMSC_SUPERIO_WRITE_INDEXED(IDE1_PRIMARY_BASE >> 8,
+ SMSC_PRIMARY_BASE_INDEX + 0);
+ SMSC_SUPERIO_WRITE_INDEXED(IDE1_PRIMARY_BASE & 0xff,
+ SMSC_PRIMARY_BASE_INDEX + 1);
+
+ SMSC_SUPERIO_WRITE_INDEXED(IDE1_SECONDARY_BASE >> 8,
+ SMSC_SECONDARY_BASE_INDEX + 0);
+ SMSC_SUPERIO_WRITE_INDEXED(IDE1_SECONDARY_BASE & 0xff,
+ SMSC_SECONDARY_BASE_INDEX + 1);
+
+ SMSC_SUPERIO_WRITE_INDEXED(14, SMSC_PRIMARY_INT_INDEX);
+
+ SMSC_SUPERIO_WRITE_INDEXED(SMSC_CONFIG_REGISTERS,
+ SMCS_LOGICAL_DEV_INDEX);
+
+ SMSC_SUPERIO_WRITE_INDEXED(0x00, 0xc2); /* GP42 = nIDE1_OE */
+ SMSC_SUPERIO_WRITE_INDEXED(0x01, 0xc5); /* GP45 = IDE1_IRQ */
+ SMSC_SUPERIO_WRITE_INDEXED(0x00, 0xc6); /* GP46 = nIOROP */
+ SMSC_SUPERIO_WRITE_INDEXED(0x00, 0xc7); /* GP47 = nIOWOP */
+#endif
+
/* Exit the configuraton state */
outb(SMSC_EXIT_CONFIG_KEY, SMSC_CONFIG_PORT_ADDR);
diff --git a/arch/sh64/mm/cache.c b/arch/sh64/mm/cache.c
index 56fbbff5c1abe..3b87e25ea773b 100644
--- a/arch/sh64/mm/cache.c
+++ b/arch/sh64/mm/cache.c
@@ -114,6 +114,16 @@ int __init sh64_cache_init(void)
return 0;
}
+#ifdef CONFIG_DCACHE_DISABLED
+#define sh64_dcache_purge_all() do { } while (0)
+#define sh64_dcache_purge_coloured_phy_page(paddr, eaddr) do { } while (0)
+#define sh64_dcache_purge_user_range(mm, start, end) do { } while (0)
+#define sh64_dcache_purge_phy_page(paddr) do { } while (0)
+#define sh64_dcache_purge_virt_page(mm, eaddr) do { } while (0)
+#define sh64_dcache_purge_kernel_range(start, end) do { } while (0)
+#define sh64_dcache_wback_current_user_range(start, end) do { } while (0)
+#endif
+
/*##########################################################################*/
/* From here onwards, a rewrite of the implementation,
@@ -436,6 +446,7 @@ static void __inline__ sh64_dcache_purge_sets(int sets_to_purge_base, int n_sets
eaddr1 = eaddr0 + cpu_data->dcache.way_ofs * cpu_data->dcache.ways;
for (eaddr=eaddr0; eaddr<eaddr1; eaddr+=cpu_data->dcache.way_ofs) {
asm __volatile__ ("alloco %0, 0" : : "r" (eaddr));
+ asm __volatile__ ("synco"); /* TAKum03020 */
}
eaddr1 = eaddr0 + cpu_data->dcache.way_ofs * cpu_data->dcache.ways;
@@ -573,31 +584,6 @@ static void sh64_dcache_purge_phy_page(unsigned long paddr)
}
}
-static void sh64_dcache_purge_virt_page(struct mm_struct *mm, unsigned long eaddr)
-{
- unsigned long phys;
- pgd_t *pgd;
- pmd_t *pmd;
- pte_t *pte;
- pte_t entry;
-
- pgd = pgd_offset(mm, eaddr);
- pmd = pmd_offset(pgd, eaddr);
-
- if (pmd_none(*pmd) || pmd_bad(*pmd))
- return;
-
- pte = pte_offset_kernel(pmd, eaddr);
- entry = *pte;
-
- if (pte_none(entry) || !pte_present(entry))
- return;
-
- phys = pte_val(entry) & PAGE_MASK;
-
- sh64_dcache_purge_phy_page(phys);
-}
-
static void sh64_dcache_purge_user_page(struct mm_struct *mm, unsigned long eaddr)
{
pgd_t *pgd;
@@ -766,8 +752,6 @@ static void sh64_dcache_wback_current_user_range(unsigned long start, unsigned l
}
}
-#endif /* !CONFIG_DCACHE_DISABLED */
-
/****************************************************************************/
/* These *MUST* lie in an area of virtual address space that's otherwise unused. */
@@ -830,6 +814,8 @@ static void sh64_clear_user_page_coloured(void *to, unsigned long address)
sh64_teardown_dtlb_cache_slot();
}
+#endif /* !CONFIG_DCACHE_DISABLED */
+
/****************************************************************************/
/*##########################################################################
@@ -904,7 +890,7 @@ void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
/****************************************************************************/
-void flush_cache_page(struct vm_area_struct *vma, unsigned long eaddr)
+void flush_cache_page(struct vm_area_struct *vma, unsigned long eaddr, unsigned long pfn)
{
/* Invalidate any entries in either cache for the vma within the user
address space vma->vm_mm for the page starting at virtual address
@@ -915,7 +901,7 @@ void flush_cache_page(struct vm_area_struct *vma, unsigned long eaddr)
Note(1), this is called with mm->page_table_lock held.
*/
- sh64_dcache_purge_virt_page(vma->vm_mm, eaddr);
+ sh64_dcache_purge_phy_page(pfn << PAGE_SHIFT);
if (vma->vm_flags & VM_EXEC) {
sh64_icache_inv_user_page(vma, eaddr);
diff --git a/arch/sh64/mm/extable.c b/arch/sh64/mm/extable.c
index 802eff88b84b9..9da50e28b3fa6 100644
--- a/arch/sh64/mm/extable.c
+++ b/arch/sh64/mm/extable.c
@@ -15,7 +15,8 @@
#include <linux/module.h>
#include <asm/uaccess.h>
-extern unsigned long copy_user_memcpy, copy_user_memcpy_end, __copy_user_fixup;
+extern unsigned long copy_user_memcpy, copy_user_memcpy_end;
+extern void __copy_user_fixup(void);
static const struct exception_table_entry __copy_user_fixup_ex = {
.fixup = (unsigned long)&__copy_user_fixup,
diff --git a/arch/sh64/mm/fault.c b/arch/sh64/mm/fault.c
index d1190b4158d8a..a24932881dbb2 100644
--- a/arch/sh64/mm/fault.c
+++ b/arch/sh64/mm/fault.c
@@ -148,7 +148,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long writeaccess,
mm = tsk->mm;
/* Not an IO address, so reenable interrupts */
- sti();
+ local_irq_enable();
/*
* If we're in an interrupt or have no user
@@ -203,17 +203,17 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long writeaccess,
* we can handle it..
*/
good_area:
- if (writeaccess) {
- if (!(vma->vm_flags & VM_WRITE))
- goto bad_area;
- } else {
- if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
- goto bad_area;
- }
-
if (textaccess) {
if (!(vma->vm_flags & VM_EXEC))
goto bad_area;
+ } else {
+ if (writeaccess) {
+ if (!(vma->vm_flags & VM_WRITE))
+ goto bad_area;
+ } else {
+ if (!(vma->vm_flags & VM_READ))
+ goto bad_area;
+ }
}
/*
@@ -264,17 +264,28 @@ bad_area:
up_read(&mm->mmap_sem);
if (user_mode(regs)) {
- printk("user mode bad_area address=%08lx pid=%d (%s) pc=%08lx opcode=%08lx\n",
- address, current->pid, current->comm,
- (unsigned long) regs->pc,
- *(unsigned long *)(u32)(regs->pc & ~3));
- show_regs(regs);
+ static int count=0;
+ siginfo_t info;
+ if (count < 4) {
+ /* This is really to help debug faults when starting
+ * usermode, so only need a few */
+ count++;
+ printk("user mode bad_area address=%08lx pid=%d (%s) pc=%08lx\n",
+ address, current->pid, current->comm,
+ (unsigned long) regs->pc);
+#if 0
+ show_regs(regs);
+#endif
+ }
if (tsk->pid == 1) {
panic("INIT had user mode bad_area\n");
}
tsk->thread.address = address;
tsk->thread.error_code = writeaccess;
- force_sig(SIGSEGV, tsk);
+ info.si_signo = SIGSEGV;
+ info.si_errno = 0;
+ info.si_addr = (void *) address;
+ force_sig_info(SIGSEGV, &info, tsk);
return;
}
diff --git a/arch/sh64/mm/hugetlbpage.c b/arch/sh64/mm/hugetlbpage.c
index 50b25735fb93c..bcad2aefa4eea 100644
--- a/arch/sh64/mm/hugetlbpage.c
+++ b/arch/sh64/mm/hugetlbpage.c
@@ -62,7 +62,7 @@ static void set_huge_pte(struct mm_struct *mm, struct vm_area_struct *vma,
unsigned long i;
pte_t entry;
- mm->rss += (HPAGE_SIZE / PAGE_SIZE);
+ add_mm_counter(mm, rss, HPAGE_SIZE / PAGE_SIZE);
if (write_access)
entry = pte_mkwrite(pte_mkdirty(mk_pte(page,
@@ -115,7 +115,7 @@ int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src,
pte_val(entry) += PAGE_SIZE;
dst_pte++;
}
- dst->rss += (HPAGE_SIZE / PAGE_SIZE);
+ add_mm_counter(dst, rss, HPAGE_SIZE / PAGE_SIZE);
addr += HPAGE_SIZE;
}
return 0;
@@ -202,11 +202,11 @@ void unmap_hugepage_range(struct vm_area_struct *vma,
page = pte_page(*pte);
put_page(page);
for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) {
- pte_clear(pte);
+ pte_clear(mm, address+(i*PAGE_SIZE), pte);
pte++;
}
}
- mm->rss -= (end - start) >> PAGE_SHIFT;
+ add_mm_counter(mm, rss, -((end - start) >> PAGE_SHIFT));
flush_tlb_range(vma, start, end);
}
diff --git a/arch/sh64/mm/init.c b/arch/sh64/mm/init.c
index 09cd9c87907e8..a65e8bb2c3cc5 100644
--- a/arch/sh64/mm/init.c
+++ b/arch/sh64/mm/init.c
@@ -124,9 +124,6 @@ void __init paging_init(void)
zones_size[ZONE_DMA] = MAX_LOW_PFN - START_PFN;
NODE_DATA(0)->node_mem_map = NULL;
free_area_init_node(0, NODE_DATA(0), zones_size, __MEMORY_START >> PAGE_SHIFT, 0);
-
- /* XXX: MRB-remove - this doesn't seem sane, should this be done somewhere else ?*/
- mem_map = NODE_DATA(0)->node_mem_map;
}
void __init mem_init(void)
diff --git a/arch/sh64/mm/ioremap.c b/arch/sh64/mm/ioremap.c
index 8e05490251618..f4003da556bca 100644
--- a/arch/sh64/mm/ioremap.c
+++ b/arch/sh64/mm/ioremap.c
@@ -182,8 +182,8 @@ void iounmap(void *addr)
}
static struct resource shmedia_iomap = {
- .name = "shmedia_iomap",
- .start = IOBASE_VADDR,
+ .name = "shmedia_iomap",
+ .start = IOBASE_VADDR + PAGE_SIZE,
.end = IOBASE_END - 1,
};
@@ -400,7 +400,7 @@ static void shmedia_unmapioaddr(unsigned long vaddr)
return;
clear_page((void *)ptep);
- pte_clear(ptep);
+ pte_clear(&init_mm, vaddr, ptep);
}
unsigned long onchip_remap(unsigned long phys, unsigned long size, const char *name)
diff --git a/arch/sh64/mm/tlbmiss.c b/arch/sh64/mm/tlbmiss.c
index 69f686c885f12..c8615954aaa98 100644
--- a/arch/sh64/mm/tlbmiss.c
+++ b/arch/sh64/mm/tlbmiss.c
@@ -75,7 +75,6 @@ inline void __do_tlb_refill(unsigned long address,
/* Set PTEL register, set_pte has performed the sign extension */
ptel &= _PAGE_FLAGS_HARDWARE_MASK; /* drop software flags */
- ptel |= _PAGE_FLAGS_HARDWARE_DEFAULT; /* add default flags */
tlbp = is_text_not_data ? &(cpu_data->itlb) : &(cpu_data->dtlb);
next = tlbp->next;
diff --git a/arch/sh64/oprofile/op_model_null.c b/arch/sh64/oprofile/op_model_null.c
index f1c795fe9fb18..a845b088edb4f 100644
--- a/arch/sh64/oprofile/op_model_null.c
+++ b/arch/sh64/oprofile/op_model_null.c
@@ -12,7 +12,7 @@
#include <linux/init.h>
#include <linux/errno.h>
-int __init oprofile_arch_init(struct oprofile_operations **ops)
+int __init oprofile_arch_init(struct oprofile_operations *ops)
{
return -ENODEV;
}
diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c
index 21e4e6f8401c1..d0f2bd227c4ca 100644
--- a/arch/sparc/kernel/ioport.c
+++ b/arch/sparc/kernel/ioport.c
@@ -54,11 +54,11 @@ static void _sparc_free_io(struct resource *res);
/* This points to the next to use virtual memory for DVMA mappings */
static struct resource _sparc_dvma = {
- "sparc_dvma", DVMA_VADDR, DVMA_END - 1
+ .name = "sparc_dvma", .start = DVMA_VADDR, .end = DVMA_END - 1
};
/* This points to the start of I/O mappings, cluable from outside. */
/*ext*/ struct resource sparc_iomap = {
- "sparc_iomap", IOBASE_VADDR, IOBASE_END - 1
+ .name = "sparc_iomap", .start = IOBASE_VADDR, .end = IOBASE_END - 1
};
/*
diff --git a/arch/sparc/kernel/ptrace.c b/arch/sparc/kernel/ptrace.c
index 9cd81b47f0ee6..fc4ad69357b87 100644
--- a/arch/sparc/kernel/ptrace.c
+++ b/arch/sparc/kernel/ptrace.c
@@ -285,17 +285,17 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
s, (int) request, (int) pid, addr, data, addr2);
}
#endif
- if(request == PTRACE_TRACEME) {
- int ret;
+ if (request == PTRACE_TRACEME) {
+ int my_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);
+ my_ret = security_ptrace(current->parent, current);
+ if (my_ret) {
+ pt_error_return(regs, -my_ret);
goto out;
}
@@ -305,7 +305,7 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
goto out;
}
#ifndef ALLOW_INIT_TRACING
- if(pid == 1) {
+ if (pid == 1) {
/* Can't dork with init. */
pt_error_return(regs, EPERM);
goto out;
@@ -374,8 +374,8 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
struct pt_regs *cregs = child->thread.kregs;
int rval;
- rval = verify_area(VERIFY_WRITE, pregs, sizeof(struct pt_regs));
- if(rval) {
+ if (!access_ok(VERIFY_WRITE, pregs, sizeof(struct pt_regs))) {
+ rval = -EFAULT;
pt_error_return(regs, -rval);
goto out_tsk;
}
@@ -401,9 +401,8 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
/* Must be careful, tracing process can only set certain
* bits in the psr.
*/
- i = verify_area(VERIFY_READ, pregs, sizeof(struct pt_regs));
- if(i) {
- pt_error_return(regs, -i);
+ if (!access_ok(VERIFY_READ, pregs, sizeof(struct pt_regs))) {
+ pt_error_return(regs, EFAULT);
goto out_tsk;
}
__get_user(psr, (&pregs->psr));
@@ -413,7 +412,7 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
psr &= PSR_ICC;
cregs->psr &= ~PSR_ICC;
cregs->psr |= psr;
- if(!((pc | npc) & 3)) {
+ if (!((pc | npc) & 3)) {
cregs->pc = pc;
cregs->npc =npc;
}
@@ -439,8 +438,8 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
struct fps __user *fps = (struct fps __user *) addr;
int i;
- i = verify_area(VERIFY_WRITE, fps, sizeof(struct fps));
- if(i) {
+ if (!access_ok(VERIFY_WRITE, fps, sizeof(struct fps))) {
+ i = -EFAULT;
pt_error_return(regs, -i);
goto out_tsk;
}
@@ -474,8 +473,8 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
struct fps __user *fps = (struct fps __user *) addr;
int i;
- i = verify_area(VERIFY_READ, fps, sizeof(struct fps));
- if(i) {
+ if (!access_ok(VERIFY_READ, fps, sizeof(struct fps))) {
+ i = -EFAULT;
pt_error_return(regs, -i);
goto out_tsk;
}
diff --git a/arch/sparc/kernel/signal.c b/arch/sparc/kernel/signal.c
index ec74a93e65557..011ff35057a51 100644
--- a/arch/sparc/kernel/signal.c
+++ b/arch/sparc/kernel/signal.c
@@ -205,7 +205,7 @@ restore_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
set_used_math();
clear_tsk_thread_flag(current, TIF_USEDFPU);
- if (verify_area(VERIFY_READ, fpu, sizeof(*fpu)))
+ if (!access_ok(VERIFY_READ, fpu, sizeof(*fpu)))
return -EFAULT;
err = __copy_from_user(&current->thread.float_regs[0], &fpu->si_float_regs[0],
@@ -231,7 +231,7 @@ static inline void do_new_sigreturn (struct pt_regs *regs)
sf = (struct new_signal_frame __user *) regs->u_regs[UREG_FP];
/* 1. Make sure we are not getting garbage from the user */
- if (verify_area(VERIFY_READ, sf, sizeof(*sf)))
+ if (!access_ok(VERIFY_READ, sf, sizeof(*sf)))
goto segv_and_exit;
if (((unsigned long) sf) & 3)
@@ -297,7 +297,7 @@ asmlinkage void do_sigreturn(struct pt_regs *regs)
scptr = (struct sigcontext __user *) regs->u_regs[UREG_I0];
/* Check sanity of the user arg. */
- if (verify_area(VERIFY_READ, scptr, sizeof(struct sigcontext)) ||
+ if (!access_ok(VERIFY_READ, scptr, sizeof(struct sigcontext)) ||
(((unsigned long) scptr) & 3))
goto segv_and_exit;
@@ -356,7 +356,7 @@ asmlinkage void do_rt_sigreturn(struct pt_regs *regs)
synchronize_user_stack();
sf = (struct rt_signal_frame __user *) regs->u_regs[UREG_FP];
- if (verify_area(VERIFY_READ, sf, sizeof(*sf)) ||
+ if (!access_ok(VERIFY_READ, sf, sizeof(*sf)) ||
(((unsigned long) sf) & 0x03))
goto segv;
diff --git a/arch/sparc/kernel/smp.c b/arch/sparc/kernel/smp.c
index 6cd0307a6661d..c6e721d8f4772 100644
--- a/arch/sparc/kernel/smp.c
+++ b/arch/sparc/kernel/smp.c
@@ -36,15 +36,12 @@
volatile int smp_processors_ready = 0;
int smp_num_cpus = 1;
-int smp_threads_ready=0;
volatile unsigned long cpu_callin_map[NR_CPUS] __initdata = {0,};
unsigned char boot_cpu_id = 0;
unsigned char boot_cpu_id4 = 0; /* boot_cpu_id << 2 */
int smp_activated = 0;
volatile int __cpu_number_map[NR_CPUS];
volatile int __cpu_logical_map[NR_CPUS];
-cycles_t cacheflush_time = 0; /* XXX */
-unsigned long cache_decay_ticks = 100;
cpumask_t cpu_online_map = CPU_MASK_NONE;
cpumask_t phys_cpu_present_map = CPU_MASK_NONE;
diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c
index a7df400e9d484..f91b0e8d0dc84 100644
--- a/arch/sparc/kernel/sparc_ksyms.c
+++ b/arch/sparc/kernel/sparc_ksyms.c
@@ -164,6 +164,7 @@ EXPORT_SYMBOL(get_auxio);
#endif
EXPORT_SYMBOL(request_fast_irq);
EXPORT_SYMBOL(io_remap_page_range);
+EXPORT_SYMBOL(io_remap_pfn_range);
/* P3: iounit_xxx may be needed, sun4d users */
/* EXPORT_SYMBOL(iounit_map_dma_init); */
/* EXPORT_SYMBOL(iounit_map_dma_page); */
diff --git a/arch/sparc/kernel/sun4d_smp.c b/arch/sparc/kernel/sun4d_smp.c
index ea209f056f2f7..cc1fc898495c8 100644
--- a/arch/sparc/kernel/sun4d_smp.c
+++ b/arch/sparc/kernel/sun4d_smp.c
@@ -45,7 +45,6 @@ extern void calibrate_delay(void);
extern volatile int smp_processors_ready;
extern int smp_num_cpus;
static int smp_highest_cpu;
-extern int smp_threads_ready;
extern volatile unsigned long cpu_callin_map[NR_CPUS];
extern struct cpuinfo_sparc cpu_data[NR_CPUS];
extern unsigned char boot_cpu_id;
diff --git a/arch/sparc/kernel/sun4m_smp.c b/arch/sparc/kernel/sun4m_smp.c
index 8e10d9502dd4e..f113422a37276 100644
--- a/arch/sparc/kernel/sun4m_smp.c
+++ b/arch/sparc/kernel/sun4m_smp.c
@@ -41,7 +41,6 @@ extern void calibrate_delay(void);
extern volatile int smp_processors_ready;
extern int smp_num_cpus;
-extern int smp_threads_ready;
extern volatile unsigned long cpu_callin_map[NR_CPUS];
extern unsigned char boot_cpu_id;
extern int smp_activated;
diff --git a/arch/sparc/kernel/sys_sparc.c b/arch/sparc/kernel/sys_sparc.c
index 09a0db77ec901..0cdfc9d294b45 100644
--- a/arch/sparc/kernel/sys_sparc.c
+++ b/arch/sparc/kernel/sys_sparc.c
@@ -399,7 +399,7 @@ sparc_sigaction (int sig, const struct old_sigaction __user *act,
if (act) {
unsigned long mask;
- if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
+ if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
__get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
__get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
return -EFAULT;
@@ -417,7 +417,7 @@ sparc_sigaction (int sig, const struct old_sigaction __user *act,
* deadlock us if we held the signal lock on SMP. So for
* now I take the easy way out and do no locking.
*/
- if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
+ if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
__put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
__put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
return -EFAULT;
diff --git a/arch/sparc/kernel/sys_sunos.c b/arch/sparc/kernel/sys_sunos.c
index ad049c1f374b8..81c894acd0db6 100644
--- a/arch/sparc/kernel/sys_sunos.c
+++ b/arch/sparc/kernel/sys_sunos.c
@@ -1131,7 +1131,7 @@ sunos_sigaction(int sig, const struct old_sigaction __user *act,
if (act) {
old_sigset_t mask;
- if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
+ if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
__get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
__get_user(new_ka.sa.sa_flags, &act->sa_flags))
return -EFAULT;
@@ -1152,7 +1152,7 @@ sunos_sigaction(int sig, const struct old_sigaction __user *act,
* But then again we don't support SunOS lwp's anyways ;-)
*/
old_ka.sa.sa_flags ^= SUNOS_SV_INTERRUPT;
- if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
+ if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
__put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
__put_user(old_ka.sa.sa_flags, &oact->sa_flags))
return -EFAULT;
diff --git a/arch/sparc/kernel/unaligned.c b/arch/sparc/kernel/unaligned.c
index a40bbcfeb8988..a6330fbc9dd93 100644
--- a/arch/sparc/kernel/unaligned.c
+++ b/arch/sparc/kernel/unaligned.c
@@ -428,40 +428,35 @@ static inline int ok_for_user(struct pt_regs *regs, unsigned int insn,
enum direction dir)
{
unsigned int reg;
- int retval, check = (dir == load) ? VERIFY_READ : VERIFY_WRITE;
+ int check = (dir == load) ? VERIFY_READ : VERIFY_WRITE;
int size = ((insn >> 19) & 3) == 3 ? 8 : 4;
if ((regs->pc | regs->npc) & 3)
return 0;
- /* Must verify_area() in all the necessary places. */
+ /* Must access_ok() in all the necessary places. */
#define WINREG_ADDR(regnum) \
((void __user *)(((unsigned long *)regs->u_regs[UREG_FP])+(regnum)))
- retval = 0;
reg = (insn >> 25) & 0x1f;
if (reg >= 16) {
- retval = verify_area(check, WINREG_ADDR(reg - 16), size);
- if (retval)
- return retval;
+ if (!access_ok(check, WINREG_ADDR(reg - 16), size))
+ return -EFAULT;
}
reg = (insn >> 14) & 0x1f;
if (reg >= 16) {
- retval = verify_area(check, WINREG_ADDR(reg - 16), size);
- if (retval)
- return retval;
+ if (!access_ok(check, WINREG_ADDR(reg - 16), size))
+ return -EFAULT;
}
if (!(insn & 0x2000)) {
reg = (insn & 0x1f);
if (reg >= 16) {
- retval = verify_area(check, WINREG_ADDR(reg - 16),
- size);
- if (retval)
- return retval;
+ if (!access_ok(check, WINREG_ADDR(reg - 16), size))
+ return -EFAULT;
}
}
- return retval;
#undef WINREG_ADDR
+ return 0;
}
void user_mna_trap_fault(struct pt_regs *regs, unsigned int insn) __asm__ ("user_mna_trap_fault");
diff --git a/arch/sparc/mm/generic.c b/arch/sparc/mm/generic.c
index f4c6851b5c1a0..db27eee3bda19 100644
--- a/arch/sparc/mm/generic.c
+++ b/arch/sparc/mm/generic.c
@@ -47,7 +47,7 @@ static inline void forget_pte(pte_t page)
* They use a pgprot that sets PAGE_IO and does not check the
* mem_map table as this is independent of normal memory.
*/
-static inline void io_remap_pte_range(pte_t * pte, unsigned long address, unsigned long size,
+static inline void io_remap_pte_range(struct mm_struct *mm, pte_t * pte, unsigned long address, unsigned long size,
unsigned long offset, pgprot_t prot, int space)
{
unsigned long end;
@@ -58,7 +58,7 @@ static inline void io_remap_pte_range(pte_t * pte, unsigned long address, unsign
end = PMD_SIZE;
do {
pte_t oldpage = *pte;
- pte_clear(pte);
+ pte_clear(mm, address, pte);
set_pte(pte, mk_pte_io(offset, prot, space));
forget_pte(oldpage);
address += PAGE_SIZE;
@@ -67,7 +67,7 @@ static inline void io_remap_pte_range(pte_t * pte, unsigned long address, unsign
} while (address < end);
}
-static inline int io_remap_pmd_range(pmd_t * pmd, unsigned long address, unsigned long size,
+static inline int io_remap_pmd_range(struct mm_struct *mm, pmd_t * pmd, unsigned long address, unsigned long size,
unsigned long offset, pgprot_t prot, int space)
{
unsigned long end;
@@ -78,10 +78,10 @@ static inline int io_remap_pmd_range(pmd_t * pmd, unsigned long address, unsigne
end = PGDIR_SIZE;
offset -= address;
do {
- pte_t * pte = pte_alloc_map(current->mm, pmd, address);
+ pte_t * pte = pte_alloc_map(mm, pmd, address);
if (!pte)
return -ENOMEM;
- io_remap_pte_range(pte, address, end - address, address + offset, prot, space);
+ io_remap_pte_range(mm, pte, address, end - address, address + offset, prot, space);
address = (address + PMD_SIZE) & PMD_MASK;
pmd++;
} while (address < end);
@@ -107,7 +107,41 @@ int io_remap_page_range(struct vm_area_struct *vma, unsigned long from, unsigned
error = -ENOMEM;
if (!pmd)
break;
- error = io_remap_pmd_range(pmd, from, end - from, offset + from, prot, space);
+ error = io_remap_pmd_range(mm, pmd, from, end - from, offset + from, prot, space);
+ if (error)
+ break;
+ from = (from + PGDIR_SIZE) & PGDIR_MASK;
+ dir++;
+ }
+ spin_unlock(&mm->page_table_lock);
+
+ flush_tlb_range(vma, beg, end);
+ return error;
+}
+
+int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from,
+ unsigned long pfn, unsigned long size, pgprot_t prot)
+{
+ int error = 0;
+ pgd_t * dir;
+ unsigned long beg = from;
+ unsigned long end = from + size;
+ struct mm_struct *mm = vma->vm_mm;
+ int space = GET_IOSPACE(pfn);
+ unsigned long offset = GET_PFN(pfn) << PAGE_SHIFT;
+
+ prot = __pgprot(pg_iobits);
+ offset -= from;
+ dir = pgd_offset(mm, from);
+ flush_cache_range(vma, beg, end);
+
+ spin_lock(&mm->page_table_lock);
+ while (from < end) {
+ pmd_t *pmd = pmd_alloc(current->mm, dir, from);
+ error = -ENOMEM;
+ if (!pmd)
+ break;
+ error = io_remap_pmd_range(mm, pmd, from, end - from, offset + from, prot, space);
if (error)
break;
from = (from + PGDIR_SIZE) & PGDIR_MASK;
diff --git a/arch/sparc/mm/highmem.c b/arch/sparc/mm/highmem.c
index c85d4923dc336..4d8ed9c651823 100644
--- a/arch/sparc/mm/highmem.c
+++ b/arch/sparc/mm/highmem.c
@@ -88,7 +88,7 @@ void kunmap_atomic(void *kvaddr, enum km_type type)
* force other mappings to Oops if they'll try to access
* this pte without first remap it
*/
- pte_clear(kmap_pte-idx);
+ pte_clear(&init_mm, vaddr, kmap_pte-idx);
/* XXX Fix - Anton */
#if 0
__flush_tlb_one(vaddr);
diff --git a/arch/sparc/mm/init.c b/arch/sparc/mm/init.c
index 5249a377a71b7..a2dea69b2f072 100644
--- a/arch/sparc/mm/init.c
+++ b/arch/sparc/mm/init.c
@@ -59,9 +59,6 @@ unsigned long highstart_pfn, highend_pfn;
pte_t *kmap_pte;
pgprot_t kmap_prot;
-EXPORT_SYMBOL(kmap_prot);
-EXPORT_SYMBOL(kmap_pte);
-
#define kmap_get_fixmap_pte(vaddr) \
pte_offset_kernel(pmd_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr))
diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c
index 533946c574c76..8c66349f316b2 100644
--- a/arch/sparc/mm/srmmu.c
+++ b/arch/sparc/mm/srmmu.c
@@ -1003,8 +1003,7 @@ extern void viking_flush_cache_all(void);
extern void viking_flush_cache_mm(struct mm_struct *mm);
extern void viking_flush_cache_range(struct vm_area_struct *vma, unsigned long start,
unsigned long end);
-extern void viking_flush_cache_page(struct vm_area_struct *vma,
- unsigned long page);
+extern void viking_flush_cache_page(struct vm_area_struct *vma, unsigned long page);
extern void viking_flush_page_to_ram(unsigned long page);
extern void viking_flush_page_for_dma(unsigned long page);
extern void viking_flush_sig_insns(struct mm_struct *mm, unsigned long addr);
@@ -1344,7 +1343,6 @@ void __init srmmu_paging_init(void)
free_area_init_node(0, &contig_page_data, zones_size,
pfn_base, zholes_size);
- mem_map = contig_page_data.node_mem_map;
}
}
diff --git a/arch/sparc/mm/sun4c.c b/arch/sparc/mm/sun4c.c
index 6f91a3e2b5343..03342120f1f85 100644
--- a/arch/sparc/mm/sun4c.c
+++ b/arch/sparc/mm/sun4c.c
@@ -2117,7 +2117,6 @@ void __init sun4c_paging_init(void)
free_area_init_node(0, &contig_page_data, zones_size,
pfn_base, zholes_size);
- mem_map = contig_page_data.node_mem_map;
}
cnt = 0;
diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig
index edf1c6b0688da..46a6ad60a8f5a 100644
--- a/arch/sparc64/defconfig
+++ b/arch/sparc64/defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc4
-# Thu Feb 17 15:32:19 2005
+# Linux kernel version: 2.6.11
+# Sun Mar 6 20:47:29 2005
#
CONFIG_64BIT=y
CONFIG_MMU=y
@@ -368,6 +368,7 @@ 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
@@ -737,6 +738,7 @@ 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
@@ -747,6 +749,12 @@ 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
@@ -899,7 +907,6 @@ CONFIG_FORCEDETH=m
CONFIG_DGRS=m
CONFIG_EEPRO100=m
CONFIG_E100=m
-CONFIG_E100_NAPI=y
CONFIG_FEALNX=m
CONFIG_NATSEMI=m
CONFIG_NE2K_PCI=m
@@ -1171,6 +1178,7 @@ 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
@@ -1194,7 +1202,9 @@ 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
@@ -1208,6 +1218,7 @@ 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
@@ -1909,6 +1920,7 @@ CONFIG_CRYPTO_SHA1=y
CONFIG_CRYPTO_SHA256=m
CONFIG_CRYPTO_SHA512=m
CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
CONFIG_CRYPTO_DES=y
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_TWOFISH=m
diff --git a/arch/sparc64/kernel/binfmt_aout32.c b/arch/sparc64/kernel/binfmt_aout32.c
index cfa66aa59235e..b2854ef221d06 100644
--- a/arch/sparc64/kernel/binfmt_aout32.c
+++ b/arch/sparc64/kernel/binfmt_aout32.c
@@ -114,9 +114,9 @@ static int aout32_core_dump(long signr, struct pt_regs *regs, struct file *file)
/* make sure we actually have a data and stack area to dump */
set_fs(USER_DS);
- if (verify_area(VERIFY_READ, (void __user *) START_DATA(dump), dump.u_dsize))
+ if (!access_ok(VERIFY_READ, (void __user *) START_DATA(dump), dump.u_dsize))
dump.u_dsize = 0;
- if (verify_area(VERIFY_READ, (void __user *) START_STACK(dump), dump.u_ssize))
+ if (!access_ok(VERIFY_READ, (void __user *) START_STACK(dump), dump.u_ssize))
dump.u_ssize = 0;
set_fs(KERNEL_DS);
@@ -241,7 +241,7 @@ static int load_aout32_binary(struct linux_binprm * bprm, struct pt_regs * regs)
current->mm->brk = ex.a_bss +
(current->mm->start_brk = N_BSSADDR(ex));
- current->mm->rss = 0;
+ set_mm_counter(current->mm, rss, 0);
current->mm->mmap = NULL;
compute_creds(bprm);
current->flags &= ~PF_FORKNOEXEC;
diff --git a/arch/sparc64/kernel/central.c b/arch/sparc64/kernel/central.c
index a2707e75bde63..3d184a784968b 100644
--- a/arch/sparc64/kernel/central.c
+++ b/arch/sparc64/kernel/central.c
@@ -22,10 +22,11 @@ struct linux_fhc *fhc_list = NULL;
#define IS_CENTRAL_FHC(__fhc) ((__fhc) == central_bus->child)
-static inline unsigned long long_align(unsigned long addr)
+static void central_probe_failure(int line)
{
- return ((addr + (sizeof(unsigned long) - 1)) &
- ~(sizeof(unsigned long) - 1));
+ prom_printf("CENTRAL: Critical device probe failure at central.c:%d\n",
+ line);
+ prom_halt();
}
static void central_ranges_init(int cnode, struct linux_central *central)
@@ -65,7 +66,7 @@ static void adjust_regs(struct linux_prom_registers *regp, int nregs,
if (regp[regc].which_io == rangep[rngc].ot_child_space)
break; /* Fount it */
if (rngc == nranges) /* oops */
- prom_printf("adjust_regs: Could not find range with matching bus type...\n");
+ central_probe_failure(__LINE__);
regp[regc].which_io = rangep[rngc].ot_parent_space;
regp[regc].phys_addr -= rangep[rngc].ot_child_base;
regp[regc].phys_addr += rangep[rngc].ot_parent_base;
@@ -102,6 +103,13 @@ void * __init central_alloc_bootmem(unsigned long size)
return ret;
}
+static unsigned long prom_reg_to_paddr(struct linux_prom_registers *r)
+{
+ unsigned long ret = ((unsigned long) r->which_io) << 32;
+
+ return ret | (unsigned long) r->phys_addr;
+}
+
static void probe_other_fhcs(void)
{
struct linux_prom64_registers fpregs[6];
@@ -110,10 +118,8 @@ static void probe_other_fhcs(void)
node = prom_getchild(prom_root_node);
node = prom_searchsiblings(node, "fhc");
- if (node == 0) {
- prom_printf("FHC: Cannot find any toplevel firehose controllers.\n");
- prom_halt();
- }
+ if (node == 0)
+ central_probe_failure(__LINE__);
while (node) {
struct linux_fhc *fhc;
int board;
@@ -121,10 +127,8 @@ static void probe_other_fhcs(void)
fhc = (struct linux_fhc *)
central_alloc_bootmem(sizeof(struct linux_fhc));
- if (fhc == NULL) {
- prom_printf("probe_other_fhcs: Cannot alloc fhc.\n");
- prom_halt();
- }
+ if (fhc == NULL)
+ central_probe_failure(__LINE__);
/* Link it into the FHC chain. */
fhc->next = fhc_list;
@@ -140,10 +144,8 @@ static void probe_other_fhcs(void)
/* Non-central FHC's have 64-bit OBP format registers. */
if (prom_getproperty(node, "reg",
- (char *)&fpregs[0], sizeof(fpregs)) == -1) {
- prom_printf("FHC: Fatal error, cannot get fhc regs.\n");
- prom_halt();
- }
+ (char *)&fpregs[0], sizeof(fpregs)) == -1)
+ central_probe_failure(__LINE__);
/* Only central FHC needs special ranges applied. */
fhc->fhc_regs.pregs = fpregs[0].phys_addr;
@@ -196,28 +198,23 @@ static void probe_clock_board(struct linux_central *central,
int clknode, nslots, tmp, nregs;
clknode = prom_searchsiblings(prom_getchild(fnode), "clock-board");
- if (clknode == 0 || clknode == -1) {
- prom_printf("Critical error, central lacks clock-board.\n");
- prom_halt();
- }
+ if (clknode == 0 || clknode == -1)
+ central_probe_failure(__LINE__);
+
nregs = prom_getproperty(clknode, "reg", (char *)&cregs[0], sizeof(cregs));
- if (nregs == -1) {
- prom_printf("CENTRAL: Fatal error, cannot map clock-board regs.\n");
- prom_halt();
- }
+ if (nregs == -1)
+ central_probe_failure(__LINE__);
+
nregs /= sizeof(struct linux_prom_registers);
apply_fhc_ranges(fhc, &cregs[0], nregs);
apply_central_ranges(central, &cregs[0], nregs);
- central->cfreg = ((((unsigned long)cregs[0].which_io) << 32UL) |
- ((unsigned long)cregs[0].phys_addr));
- central->clkregs = ((((unsigned long)cregs[1].which_io) << 32UL) |
- ((unsigned long)cregs[1].phys_addr));
+ central->cfreg = prom_reg_to_paddr(&cregs[0]);
+ central->clkregs = prom_reg_to_paddr(&cregs[1]);
if (nregs == 2)
central->clkver = 0UL;
else
- central->clkver = ((((unsigned long)cregs[2].which_io) << 32UL) |
- ((unsigned long)cregs[2].phys_addr));
+ central->clkver = prom_reg_to_paddr(&cregs[2]);
tmp = upa_readb(central->clkregs + CLOCK_STAT1);
tmp &= 0xc0;
@@ -247,6 +244,18 @@ static void probe_clock_board(struct linux_central *central,
(central->clkver ? upa_readb(central->clkver) : 0x00));
}
+static void ZAP(unsigned long iclr, unsigned long imap)
+{
+ u32 imap_tmp;
+
+ upa_writel(0, iclr);
+ upa_readl(iclr);
+ imap_tmp = upa_readl(imap);
+ imap_tmp &= ~(0x80000000);
+ upa_writel(imap_tmp, imap);
+ upa_readl(imap);
+}
+
static void init_all_fhc_hw(void)
{
struct linux_fhc *fhc;
@@ -257,16 +266,6 @@ static void init_all_fhc_hw(void)
/* Clear all of the interrupt mapping registers
* just in case OBP left them in a foul state.
*/
-#define ZAP(ICLR, IMAP) \
-do { u32 imap_tmp; \
- upa_writel(0, (ICLR)); \
- upa_readl(ICLR); \
- imap_tmp = upa_readl(IMAP); \
- imap_tmp &= ~(0x80000000); \
- upa_writel(imap_tmp, (IMAP)); \
- upa_readl(IMAP); \
-} while (0)
-
ZAP(fhc->fhc_regs.ffregs + FHC_FFREGS_ICLR,
fhc->fhc_regs.ffregs + FHC_FFREGS_IMAP);
ZAP(fhc->fhc_regs.sregs + FHC_SREGS_ICLR,
@@ -276,8 +275,6 @@ do { u32 imap_tmp; \
ZAP(fhc->fhc_regs.tregs + FHC_TREGS_ICLR,
fhc->fhc_regs.tregs + FHC_TREGS_IMAP);
-#undef ZAP
-
/* Setup FHC control register. */
tmp = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_CTRL);
@@ -288,7 +285,8 @@ do { u32 imap_tmp; \
/* For all FHCs, clear the firmware synchronization
* line and both low power mode enables.
*/
- tmp &= ~(FHC_CONTROL_AOFF | FHC_CONTROL_BOFF | FHC_CONTROL_SLINE);
+ tmp &= ~(FHC_CONTROL_AOFF | FHC_CONTROL_BOFF |
+ FHC_CONTROL_SLINE);
upa_writel(tmp, fhc->fhc_regs.pregs + FHC_PREGS_CTRL);
upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_CTRL);
@@ -313,17 +311,13 @@ void central_probe(void)
/* Ok we got one, grab some memory for software state. */
central_bus = (struct linux_central *)
central_alloc_bootmem(sizeof(struct linux_central));
- if (central_bus == NULL) {
- prom_printf("central_probe: Cannot alloc central_bus.\n");
- prom_halt();
- }
+ if (central_bus == NULL)
+ central_probe_failure(__LINE__);
fhc = (struct linux_fhc *)
central_alloc_bootmem(sizeof(struct linux_fhc));
- if (fhc == NULL) {
- prom_printf("central_probe: Cannot alloc central fhc.\n");
- prom_halt();
- }
+ if (fhc == NULL)
+ central_probe_failure(__LINE__);
/* First init central. */
central_bus->child = fhc;
@@ -340,10 +334,9 @@ void central_probe(void)
fhc->parent = central_bus;
fnode = prom_searchsiblings(prom_getchild(cnode), "fhc");
- if (fnode == 0 || fnode == -1) {
- prom_printf("Critical error, central board lacks fhc.\n");
- prom_halt();
- }
+ if (fnode == 0 || fnode == -1)
+ central_probe_failure(__LINE__);
+
fhc->prom_node = fnode;
prom_getstring(fnode, "name", namebuf, sizeof(namebuf));
strcpy(fhc->prom_name, namebuf);
@@ -351,24 +344,17 @@ void central_probe(void)
fhc_ranges_init(fnode, fhc);
/* Now, map in FHC register set. */
- if (prom_getproperty(fnode, "reg", (char *)&fpregs[0], sizeof(fpregs)) == -1) {
- prom_printf("CENTRAL: Fatal error, cannot get fhc regs.\n");
- prom_halt();
- }
+ if (prom_getproperty(fnode, "reg", (char *)&fpregs[0], sizeof(fpregs)) == -1)
+ central_probe_failure(__LINE__);
+
apply_central_ranges(central_bus, &fpregs[0], 6);
- fhc->fhc_regs.pregs = ((((unsigned long)fpregs[0].which_io)<<32UL) |
- ((unsigned long)fpregs[0].phys_addr));
- fhc->fhc_regs.ireg = ((((unsigned long)fpregs[1].which_io)<<32UL) |
- ((unsigned long)fpregs[1].phys_addr));
- fhc->fhc_regs.ffregs = ((((unsigned long)fpregs[2].which_io)<<32UL) |
- ((unsigned long)fpregs[2].phys_addr));
- fhc->fhc_regs.sregs = ((((unsigned long)fpregs[3].which_io)<<32UL) |
- ((unsigned long)fpregs[3].phys_addr));
- fhc->fhc_regs.uregs = ((((unsigned long)fpregs[4].which_io)<<32UL) |
- ((unsigned long)fpregs[4].phys_addr));
- fhc->fhc_regs.tregs = ((((unsigned long)fpregs[5].which_io)<<32UL) |
- ((unsigned long)fpregs[5].phys_addr));
+ fhc->fhc_regs.pregs = prom_reg_to_paddr(&fpregs[0]);
+ fhc->fhc_regs.ireg = prom_reg_to_paddr(&fpregs[1]);
+ fhc->fhc_regs.ffregs = prom_reg_to_paddr(&fpregs[2]);
+ fhc->fhc_regs.sregs = prom_reg_to_paddr(&fpregs[3]);
+ fhc->fhc_regs.uregs = prom_reg_to_paddr(&fpregs[4]);
+ fhc->fhc_regs.tregs = prom_reg_to_paddr(&fpregs[5]);
/* Obtain board number from board status register, Central's
* FHC lacks "board#" property.
diff --git a/arch/sparc64/kernel/ioctl32.c b/arch/sparc64/kernel/ioctl32.c
index af8eb0b59b884..43fc3173d4806 100644
--- a/arch/sparc64/kernel/ioctl32.c
+++ b/arch/sparc64/kernel/ioctl32.c
@@ -475,7 +475,6 @@ IOCTL_TABLE_START
#include <linux/compat_ioctl.h>
#define DECLARES
#include "compat_ioctl.c"
-COMPATIBLE_IOCTL(TCSBRKP)
COMPATIBLE_IOCTL(TIOCSTART)
COMPATIBLE_IOCTL(TIOCSTOP)
COMPATIBLE_IOCTL(TIOCSLTC)
diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c
index 52f7bf9052a66..a38cb5036df06 100644
--- a/arch/sparc64/kernel/irq.c
+++ b/arch/sparc64/kernel/irq.c
@@ -1112,7 +1112,7 @@ void enable_prom_timer(void)
void init_irqwork_curcpu(void)
{
register struct irq_work_struct *workp asm("o2");
- unsigned long tmp;
+ register unsigned long tmp asm("o3");
int cpu = hard_smp_processor_id();
memset(__irq_work + cpu, 0, sizeof(*workp));
diff --git a/arch/sparc64/kernel/kprobes.c b/arch/sparc64/kernel/kprobes.c
index 7d97138f5d2e6..7066d7ba667a5 100644
--- a/arch/sparc64/kernel/kprobes.c
+++ b/arch/sparc64/kernel/kprobes.c
@@ -68,8 +68,14 @@ static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
current_kprobe_orig_tstate_pil = (regs->tstate & TSTATE_PIL);
regs->tstate |= TSTATE_PIL;
- regs->tpc = (unsigned long) &p->ainsn.insn[0];
- regs->tnpc = (unsigned long) &p->ainsn.insn[1];
+ /*single step inline, if it a breakpoint instruction*/
+ if (p->opcode == BREAKPOINT_INSTRUCTION) {
+ regs->tpc = (unsigned long) p->addr;
+ regs->tnpc = current_kprobe_orig_tnpc;
+ } else {
+ regs->tpc = (unsigned long) &p->ainsn.insn[0];
+ regs->tnpc = (unsigned long) &p->ainsn.insn[1];
+ }
}
static inline void disarm_kprobe(struct kprobe *p, struct pt_regs *regs)
@@ -97,6 +103,12 @@ static int kprobe_handler(struct pt_regs *regs)
*/
p = get_kprobe(addr);
if (p) {
+ if (kprobe_status == KPROBE_HIT_SS) {
+ regs->tstate = ((regs->tstate & ~TSTATE_PIL) |
+ current_kprobe_orig_tstate_pil);
+ unlock_kprobes();
+ goto no_kprobe;
+ }
disarm_kprobe(p, regs);
ret = 1;
} else {
@@ -128,7 +140,7 @@ static int kprobe_handler(struct pt_regs *regs)
kprobe_status = KPROBE_HIT_ACTIVE;
current_kprobe = p;
- if (p->pre_handler(p, regs))
+ if (p->pre_handler && p->pre_handler(p, regs))
return 1;
ss_probe:
diff --git a/arch/sparc64/kernel/module.c b/arch/sparc64/kernel/module.c
index a4ae2e3c44e34..6c83e372f75d8 100644
--- a/arch/sparc64/kernel/module.c
+++ b/arch/sparc64/kernel/module.c
@@ -17,108 +17,19 @@
#include <asm/processor.h>
#include <asm/spitfire.h>
-static struct vm_struct * modvmlist = NULL;
-
-static void module_unmap(void * addr)
-{
- struct vm_struct **p, *tmp;
- int i;
-
- if (!addr)
- return;
- if ((PAGE_SIZE-1) & (unsigned long) addr) {
- printk("Trying to unmap module with bad address (%p)\n", addr);
- return;
- }
-
- for (p = &modvmlist; (tmp = *p) != NULL; p = &tmp->next) {
- if (tmp->addr == addr) {
- *p = tmp->next;
- goto found;
- }
- }
- printk("Trying to unmap nonexistent module vm area (%p)\n", addr);
- return;
-
-found:
- unmap_vm_area(tmp);
-
- for (i = 0; i < tmp->nr_pages; i++) {
- if (unlikely(!tmp->pages[i]))
- BUG();
- __free_page(tmp->pages[i]);
- }
-
- kfree(tmp->pages);
- kfree(tmp);
-}
-
-
static void *module_map(unsigned long size)
{
- struct vm_struct **p, *tmp, *area;
- struct page **pages;
- void * addr;
- unsigned int nr_pages, array_size, i;
+ struct vm_struct *area;
size = PAGE_ALIGN(size);
if (!size || size > MODULES_LEN)
return NULL;
-
- addr = (void *) MODULES_VADDR;
- for (p = &modvmlist; (tmp = *p) != NULL; p = &tmp->next) {
- if (size + (unsigned long) addr < (unsigned long) tmp->addr)
- break;
- addr = (void *) (tmp->size + (unsigned long) tmp->addr);
- }
- if ((unsigned long) addr + size >= MODULES_END)
- return NULL;
-
- area = (struct vm_struct *) kmalloc(sizeof(*area), GFP_KERNEL);
+
+ area = __get_vm_area(size, VM_ALLOC, MODULES_VADDR, MODULES_END);
if (!area)
return NULL;
- area->size = size + PAGE_SIZE;
- area->addr = addr;
- area->next = *p;
- area->pages = NULL;
- area->nr_pages = 0;
- area->phys_addr = 0;
- *p = area;
-
- nr_pages = size >> PAGE_SHIFT;
- array_size = (nr_pages * sizeof(struct page *));
-
- area->nr_pages = nr_pages;
- area->pages = pages = kmalloc(array_size, GFP_KERNEL);
- if (!area->pages)
- goto fail;
-
- memset(area->pages, 0, array_size);
-
- for (i = 0; i < area->nr_pages; i++) {
- area->pages[i] = alloc_page(GFP_KERNEL);
- if (unlikely(!area->pages[i]))
- goto fail;
- }
-
- if (map_vm_area(area, PAGE_KERNEL, &pages)) {
- unmap_vm_area(area);
- goto fail;
- }
-
- return area->addr;
-
-fail:
- if (area->pages) {
- for (i = 0; i < area->nr_pages; i++) {
- if (area->pages[i])
- __free_page(area->pages[i]);
- }
- kfree(area->pages);
- }
- kfree(area);
- return NULL;
+ return __vmalloc_area(area, GFP_KERNEL, PAGE_KERNEL);
}
void *module_alloc(unsigned long size)
@@ -141,9 +52,7 @@ void *module_alloc(unsigned long size)
/* Free memory returned from module_core_alloc/module_init_alloc */
void module_free(struct module *mod, void *module_region)
{
- write_lock(&vmlist_lock);
- module_unmap(module_region);
- write_unlock(&vmlist_lock);
+ vfree(module_region);
/* FIXME: If module_region == mod->init_region, trim exception
table entries. */
}
diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c
index 2ffd1efefcc09..bba140d98b1b8 100644
--- a/arch/sparc64/kernel/pci.c
+++ b/arch/sparc64/kernel/pci.c
@@ -18,6 +18,7 @@
#include <asm/uaccess.h>
#include <asm/pbm.h>
+#include <asm/pgtable.h>
#include <asm/irq.h>
#include <asm/ebus.h>
#include <asm/isa.h>
@@ -734,12 +735,10 @@ static void __pci_mmap_set_flags(struct pci_dev *dev, struct vm_area_struct *vma
static void __pci_mmap_set_pgprot(struct pci_dev *dev, struct vm_area_struct *vma,
enum pci_mmap_state mmap_state)
{
- /* Our io_remap_page_range takes care of this, do nothing. */
+ /* Our io_remap_page_range/io_remap_pfn_range takes care of this,
+ do nothing. */
}
-extern int io_remap_page_range(struct vm_area_struct *vma, unsigned long from, unsigned long offset,
- unsigned long size, pgprot_t prot, int space);
-
/* 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.
@@ -761,10 +760,10 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
__pci_mmap_set_flags(dev, vma, mmap_state);
__pci_mmap_set_pgprot(dev, vma, mmap_state);
- ret = io_remap_page_range(vma, vma->vm_start,
- (vma->vm_pgoff << PAGE_SHIFT |
- (write_combine ? 0x1UL : 0x0UL)),
- vma->vm_end - vma->vm_start, vma->vm_page_prot, 0);
+ ret = io_remap_pfn_range(vma, vma->vm_start,
+ vma->vm_pgoff,
+ vma->vm_end - vma->vm_start,
+ vma->vm_page_prot);
if (ret)
return ret;
@@ -794,12 +793,6 @@ int pci_domain_nr(struct pci_bus *pbus)
}
EXPORT_SYMBOL(pci_domain_nr);
-int pci_name_bus(char *name, struct pci_bus *bus)
-{
- sprintf(name, "%04x:%02x", pci_domain_nr(bus), bus->number);
- return 0;
-}
-
int pcibios_prep_mwi(struct pci_dev *dev)
{
/* We set correct PCI_CACHE_LINE_SIZE register values for every
diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c
index 9f0a34f6d93f2..b495698858453 100644
--- a/arch/sparc64/kernel/pci_schizo.c
+++ b/arch/sparc64/kernel/pci_schizo.c
@@ -326,9 +326,9 @@ static int __init schizo_ino_to_pil(struct pci_dev *pdev, unsigned int ino)
return ret;
}
-static unsigned int __init schizo_irq_build(struct pci_pbm_info *pbm,
- struct pci_dev *pdev,
- unsigned int ino)
+static unsigned int schizo_irq_build(struct pci_pbm_info *pbm,
+ struct pci_dev *pdev,
+ unsigned int ino)
{
struct ino_bucket *bucket;
unsigned long imap, iclr;
@@ -382,19 +382,57 @@ static unsigned long stc_error_buf[128];
static unsigned long stc_tag_buf[16];
static unsigned long stc_line_buf[16];
-/* These offsets look weird because I keep in pbm->controller_regs
- * the second PROM register property minus 0x10000 which is the
- * base of the Safari and UPA64S registers of SCHIZO.
- */
-#define SCHIZO_PBM_A_REGS_OFF (0x600000UL - 0x400000UL)
-#define SCHIZO_PBM_B_REGS_OFF (0x700000UL - 0x400000UL)
+#define SCHIZO_UE_INO 0x30 /* Uncorrectable ECC error */
+#define SCHIZO_CE_INO 0x31 /* Correctable ECC error */
+#define SCHIZO_PCIERR_A_INO 0x32 /* PBM A PCI bus error */
+#define SCHIZO_PCIERR_B_INO 0x33 /* PBM B PCI bus error */
+#define SCHIZO_SERR_INO 0x34 /* Safari interface error */
+
+struct pci_pbm_info *pbm_for_ino(struct pci_controller_info *p, u32 ino)
+{
+ ino &= IMAP_INO;
+ if (p->pbm_A.ino_bitmap & (1UL << ino))
+ return &p->pbm_A;
+ if (p->pbm_B.ino_bitmap & (1UL << ino))
+ return &p->pbm_B;
+
+ printk("PCI%d: No ino_bitmap entry for ino[%x], bitmaps "
+ "PBM_A[%016lx] PBM_B[%016lx]",
+ p->index, ino,
+ p->pbm_A.ino_bitmap,
+ p->pbm_B.ino_bitmap);
+ printk("PCI%d: Using PBM_A, report this problem immediately.\n",
+ p->index);
+
+ return &p->pbm_A;
+}
-static void schizo_clear_other_err_intr(int irq)
+static void schizo_clear_other_err_intr(struct pci_controller_info *p, int irq)
{
- struct ino_bucket *bucket = __bucket(irq);
- unsigned long iclr = bucket->iclr;
+ struct pci_pbm_info *pbm;
+ struct ino_bucket *bucket;
+ unsigned long iclr;
+
+ /* Do not clear the interrupt for the other PCI bus.
+ *
+ * This "ACK both PBM IRQs" only needs to be performed
+ * for chip-wide error interrupts.
+ */
+ if ((irq & IMAP_INO) == SCHIZO_PCIERR_A_INO ||
+ (irq & IMAP_INO) == SCHIZO_PCIERR_B_INO)
+ return;
+
+ pbm = pbm_for_ino(p, irq);
+ if (pbm == &p->pbm_A)
+ pbm = &p->pbm_B;
+ else
+ pbm = &p->pbm_A;
+
+ irq = schizo_irq_build(pbm, NULL,
+ (pbm->portid << 6) | (irq & IMAP_INO));
+ bucket = __bucket(irq);
+ iclr = bucket->iclr;
- iclr += (SCHIZO_PBM_B_REGS_OFF - SCHIZO_PBM_A_REGS_OFF);
upa_writel(ICLR_IDLE, iclr);
}
@@ -728,7 +766,7 @@ static irqreturn_t schizo_ue_intr(int irq, void *dev_id, struct pt_regs *regs)
/* Interrogate IOMMU for error status. */
schizo_check_iommu_error(p, UE_ERR);
- schizo_clear_other_err_intr(irq);
+ schizo_clear_other_err_intr(p, irq);
return IRQ_HANDLED;
}
@@ -819,7 +857,7 @@ static irqreturn_t schizo_ce_intr(int irq, void *dev_id, struct pt_regs *regs)
printk("(none)");
printk("]\n");
- schizo_clear_other_err_intr(irq);
+ schizo_clear_other_err_intr(p, irq);
return IRQ_HANDLED;
}
@@ -856,9 +894,9 @@ static irqreturn_t schizo_ce_intr(int irq, void *dev_id, struct pt_regs *regs)
#define SCHIZO_PCICTRL_SBH_ERR (1UL << 35UL) /* Safari */
#define SCHIZO_PCICTRL_SERR (1UL << 34UL) /* Safari/Tomatillo */
#define SCHIZO_PCICTRL_PCISPD (1UL << 33UL) /* Safari */
-#define SCHIZO_PCICTRL_MRM_PREF (1UL << 28UL) /* Tomatillo */
-#define SCHIZO_PCICTRL_RDO_PREF (1UL << 27UL) /* Tomatillo */
-#define SCHIZO_PCICTRL_RDL_PREF (1UL << 26UL) /* Tomatillo */
+#define SCHIZO_PCICTRL_MRM_PREF (1UL << 30UL) /* Tomatillo */
+#define SCHIZO_PCICTRL_RDO_PREF (1UL << 29UL) /* Tomatillo */
+#define SCHIZO_PCICTRL_RDL_PREF (1UL << 28UL) /* Tomatillo */
#define SCHIZO_PCICTRL_PTO (3UL << 24UL) /* Safari/Tomatillo */
#define SCHIZO_PCICTRL_PTO_SHIFT 24UL
#define SCHIZO_PCICTRL_TRWSW (7UL << 21UL) /* Tomatillo */
@@ -1040,7 +1078,7 @@ static irqreturn_t schizo_pcierr_intr(int irq, void *dev_id, struct pt_regs *reg
if (error_bits & (SCHIZO_PCIAFSR_PPERR | SCHIZO_PCIAFSR_SPERR))
pci_scan_for_parity_error(p, pbm, pbm->pci_bus);
- schizo_clear_other_err_intr(irq);
+ schizo_clear_other_err_intr(p, irq);
return IRQ_HANDLED;
}
@@ -1097,7 +1135,7 @@ static irqreturn_t schizo_safarierr_intr(int irq, void *dev_id, struct pt_regs *
printk("PCI%d: Unexpected Safari/JBUS error interrupt, errlog[%016lx]\n",
p->index, errlog);
- schizo_clear_other_err_intr(irq);
+ schizo_clear_other_err_intr(p, irq);
return IRQ_HANDLED;
}
@@ -1105,7 +1143,7 @@ static irqreturn_t schizo_safarierr_intr(int irq, void *dev_id, struct pt_regs *
p->index);
schizo_check_iommu_error(p, SAFARI_ERR);
- schizo_clear_other_err_intr(irq);
+ schizo_clear_other_err_intr(p, irq);
return IRQ_HANDLED;
}
@@ -1120,26 +1158,6 @@ static irqreturn_t schizo_safarierr_intr(int irq, void *dev_id, struct pt_regs *
#define SCHIZO_SAFARI_IRQCTRL 0x10010UL
#define SCHIZO_SAFIRQCTRL_EN 0x8000000000000000UL
-#define SCHIZO_UE_INO 0x30 /* Uncorrectable ECC error */
-#define SCHIZO_CE_INO 0x31 /* Correctable ECC error */
-#define SCHIZO_PCIERR_A_INO 0x32 /* PBM A PCI bus error */
-#define SCHIZO_PCIERR_B_INO 0x33 /* PBM B PCI bus error */
-#define SCHIZO_SERR_INO 0x34 /* Safari interface error */
-
-struct pci_pbm_info *pbm_for_ino(struct pci_controller_info *p, u32 ino)
-{
- ino &= IMAP_INO;
- if (p->pbm_A.ino_bitmap & (1UL << ino))
- return &p->pbm_A;
- if (p->pbm_B.ino_bitmap & (1UL << ino))
- return &p->pbm_B;
- prom_printf("TOMATILLO%d: No entry in ino bitmap for %d\n",
- p->index, ino);
- prom_halt();
- /* NOTREACHED */
- return NULL;
-}
-
/* How the Tomatillo IRQs are routed around is pure guesswork here.
*
* All the Tomatillo devices I see in prtconf dumps seem to have only
@@ -1887,7 +1905,7 @@ static void __init schizo_pbm_hw_init(struct pci_pbm_info *pbm)
tmp &= ~SCHIZO_PCICTRL_PTO;
if (pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO &&
- pbm->chip_version == 0x2)
+ pbm->chip_version >= 0x2)
tmp |= 0x3UL << SCHIZO_PCICTRL_PTO_SHIFT;
else
tmp |= 0x1UL << SCHIZO_PCICTRL_PTO_SHIFT;
@@ -1895,8 +1913,16 @@ static void __init schizo_pbm_hw_init(struct pci_pbm_info *pbm)
if (!prom_getbool(pbm->prom_node, "no-bus-parking"))
tmp |= SCHIZO_PCICTRL_PARK;
+ if (pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO &&
+ pbm->chip_version <= 0x1)
+ tmp |= (1UL << 61);
+ else
+ tmp &= ~(1UL << 61);
+
if (pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO)
- tmp |= SCHIZO_PCICTRL_MRM_PREF;
+ tmp |= (SCHIZO_PCICTRL_MRM_PREF |
+ SCHIZO_PCICTRL_RDO_PREF |
+ SCHIZO_PCICTRL_RDL_PREF);
schizo_write(pbm->pbm_regs + SCHIZO_PCI_CTRL, tmp);
diff --git a/arch/sparc64/kernel/signal.c b/arch/sparc64/kernel/signal.c
index aa298d31d33c0..b27934671c353 100644
--- a/arch/sparc64/kernel/signal.c
+++ b/arch/sparc64/kernel/signal.c
@@ -53,7 +53,7 @@ asmlinkage void sparc64_set_context(struct pt_regs *regs)
flush_user_windows();
if (get_thread_wsaved() ||
(((unsigned long)ucp) & (sizeof(unsigned long)-1)) ||
- (!__access_ok((unsigned long)ucp, sizeof(*ucp))))
+ (!__access_ok(ucp, sizeof(*ucp))))
goto do_sigsegv;
grp = &ucp->uc_mcontext.mc_gregs;
err = __get_user(pc, &((*grp)[MC_PC]));
diff --git a/arch/sparc64/kernel/signal32.c b/arch/sparc64/kernel/signal32.c
index 4b060cacf9959..859255cf67622 100644
--- a/arch/sparc64/kernel/signal32.c
+++ b/arch/sparc64/kernel/signal32.c
@@ -104,7 +104,7 @@ typedef struct compat_siginfo{
struct {
timer_t _tid; /* timer id */
int _overrun; /* overrun count */
- sigval_t32 _sigval; /* same as below */
+ compat_sigval_t _sigval; /* same as below */
int _sys_private; /* not to be passed to user */
} _timer;
@@ -112,7 +112,7 @@ typedef struct compat_siginfo{
struct {
compat_pid_t _pid; /* sender's pid */
unsigned int _uid; /* sender's uid */
- sigval_t32 _sigval;
+ compat_sigval_t _sigval;
} _rt;
/* SIGCHLD */
@@ -351,7 +351,7 @@ void do_new_sigreturn32(struct pt_regs *regs)
sf = (struct new_signal_frame32 __user *) regs->u_regs[UREG_FP];
/* 1. Make sure we are not getting garbage from the user */
- if (verify_area(VERIFY_READ, sf, sizeof(*sf)) ||
+ if (!access_ok(VERIFY_READ, sf, sizeof(*sf)) ||
(((unsigned long) sf) & 3))
goto segv;
@@ -436,7 +436,7 @@ asmlinkage void do_sigreturn32(struct pt_regs *regs)
scptr = (struct sigcontext32 __user *)
(regs->u_regs[UREG_I0] & 0x00000000ffffffffUL);
/* Check sanity of the user arg. */
- if (verify_area(VERIFY_READ, scptr, sizeof(struct sigcontext32)) ||
+ if (!access_ok(VERIFY_READ, scptr, sizeof(struct sigcontext32)) ||
(((unsigned long) scptr) & 3))
goto segv;
@@ -504,7 +504,7 @@ asmlinkage void do_rt_sigreturn32(struct pt_regs *regs)
sf = (struct rt_signal_frame32 __user *) regs->u_regs[UREG_FP];
/* 1. Make sure we are not getting garbage from the user */
- if (verify_area(VERIFY_READ, sf, sizeof(*sf)) ||
+ if (!access_ok(VERIFY_READ, sf, sizeof(*sf)) ||
(((unsigned long) sf) & 3))
goto segv;
@@ -1102,7 +1102,7 @@ asmlinkage int svr4_setcontext(svr4_ucontext_t __user *c, struct pt_regs *regs)
goto sigsegv;
}
- if (!__access_ok((unsigned long)c, sizeof(*c))) {
+ if (!__access_ok(c, sizeof(*c))) {
/* Miguel, add nice debugging msg _here_. ;-) */
goto sigsegv;
}
diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c
index 474c4edd4d315..1441ef81b8abe 100644
--- a/arch/sparc64/kernel/smp.c
+++ b/arch/sparc64/kernel/smp.c
@@ -1055,9 +1055,6 @@ void __init smp_tick_init(void)
prof_counter(boot_cpu_id) = prof_multiplier(boot_cpu_id) = 1;
}
-cycles_t cacheflush_time;
-unsigned long cache_decay_ticks;
-
extern unsigned long cheetah_tune_scheduling(void);
static void __init smp_tune_scheduling(void)
@@ -1078,10 +1075,8 @@ static void __init smp_tune_scheduling(void)
* of moving a process from one cpu to another).
*/
printk("SMP: Calibrating ecache flush... ");
- if (tlb_type == cheetah || tlb_type == cheetah_plus) {
- cacheflush_time = cheetah_tune_scheduling();
- goto report;
- }
+ if (tlb_type == cheetah || tlb_type == cheetah_plus)
+ return;
cpu_find_by_instance(0, &cpu_node, NULL);
ecache_size = prom_getintdefault(cpu_node,
@@ -1124,24 +1119,8 @@ static void __init smp_tune_scheduling(void)
raw = (tick2 - tick1);
- /* Dampen it a little, considering two processes
- * sharing the cache and fitting.
- */
- cacheflush_time = (raw - (raw >> 2));
-
free_pages(orig_flush_base, order);
- } else {
- cacheflush_time = ((ecache_size << 2) +
- (ecache_size << 1));
}
-report:
- /* Convert ticks/sticks to jiffies. */
- cache_decay_ticks = cacheflush_time / timer_tick_offset;
- if (cache_decay_ticks < 1)
- cache_decay_ticks = 1;
-
- printk("Using heuristic of %ld cycles, %ld ticks.\n",
- cacheflush_time, cache_decay_ticks);
}
/* /proc/profile writes can call this, don't __init it please. */
diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c
index 686e45899bfce..3cec1ebb083b0 100644
--- a/arch/sparc64/kernel/sparc64_ksyms.c
+++ b/arch/sparc64/kernel/sparc64_ksyms.c
@@ -87,7 +87,10 @@ extern int svr4_setcontext(svr4_ucontext_t *uc, struct pt_regs *regs);
extern int compat_sys_ioctl(unsigned int fd, unsigned int cmd, u32 arg);
extern int (*handle_mathemu)(struct pt_regs *, struct fpustate *);
extern long sparc32_open(const char __user * filename, int flags, int mode);
-extern int io_remap_page_range(struct vm_area_struct *vma, unsigned long from, unsigned long offset, unsigned long size, pgprot_t prot, int space);
+extern int io_remap_page_range(struct vm_area_struct *vma, unsigned long from,
+ unsigned long offset, unsigned long size, pgprot_t prot, int space);
+extern int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from,
+ unsigned long pfn, unsigned long size, pgprot_t prot);
extern void (*prom_palette)(int);
extern int __ashrdi3(int, int);
@@ -254,6 +257,7 @@ EXPORT_SYMBOL(pci_dma_supported);
/* I/O device mmaping on Sparc64. */
EXPORT_SYMBOL(io_remap_page_range);
+EXPORT_SYMBOL(io_remap_pfn_range);
/* Solaris/SunOS binary compatibility */
EXPORT_SYMBOL(_sigpause_common);
diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c
index fdf3fea349612..a9fa9a47074d8 100644
--- a/arch/sparc64/kernel/sys_sparc32.c
+++ b/arch/sparc64/kernel/sys_sparc32.c
@@ -268,7 +268,7 @@ asmlinkage long compat_sys_ipc(u32 call, u32 first, u32 second, u32 third, compa
/* sign extend semid */
return compat_sys_semtimedop((int)first,
compat_ptr(ptr), second,
- compat_ptr(third));
+ compat_ptr(fifth));
/* else fall through for normal semop() */
case SEMOP:
/* struct sembuf is the same on 32 and 64bit :)) */
@@ -1087,7 +1087,7 @@ sys_timer_create(clockid_t which_clock,
timer_t __user *created_timer_id);
long
-sys32_timer_create(u32 clock, struct sigevent32 __user *se32,
+sys32_timer_create(u32 clock, struct compat_sigevent __user *se32,
timer_t __user *timer_id)
{
struct sigevent se;
@@ -1098,12 +1098,7 @@ sys32_timer_create(u32 clock, struct sigevent32 __user *se32,
if (se32 == NULL)
return sys_timer_create(clock, NULL, timer_id);
- memset(&se, 0, sizeof(struct sigevent));
- if (get_user(se.sigev_value.sival_int, &se32->sigev_value.sival_int) ||
- __get_user(se.sigev_signo, &se32->sigev_signo) ||
- __get_user(se.sigev_notify, &se32->sigev_notify) ||
- __copy_from_user(&se._sigev_un._pad, &se32->_sigev_un._pad,
- sizeof(se._sigev_un._pad)))
+ if (get_compat_sigevent(&se, se32))
return -EFAULT;
if (!access_ok(VERIFY_WRITE,timer_id,sizeof(timer_t)))
@@ -1121,34 +1116,3 @@ sys32_timer_create(u32 clock, struct sigevent32 __user *se32,
return err;
}
-
-asmlinkage long compat_sys_waitid(u32 which, u32 pid,
- struct compat_siginfo __user *uinfo,
- u32 options, struct compat_rusage __user *uru)
-{
- siginfo_t info;
- struct rusage ru;
- long ret;
- mm_segment_t old_fs = get_fs();
-
- memset(&info, 0, sizeof(info));
-
- set_fs (KERNEL_DS);
- ret = sys_waitid(which, pid, (siginfo_t __user *) &info,
- options,
- uru ? (struct rusage __user *) &ru : NULL);
- set_fs (old_fs);
-
- if (ret < 0 || info.si_signo == 0)
- return ret;
-
- if (uru) {
- ret = put_compat_rusage(&ru, uru);
- if (ret)
- return ret;
- }
-
- BUG_ON(info.si_code & __SI_MASK);
- info.si_code |= __SI_CHLD;
- return copy_siginfo_to_user32(uinfo, &info);
-}
diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c
index 5c341ece0ce48..6a717d4d2bc5d 100644
--- a/arch/sparc64/kernel/time.c
+++ b/arch/sparc64/kernel/time.c
@@ -779,6 +779,7 @@ void __init clock_probe(void)
strcmp(model, "mk48t59") &&
strcmp(model, "m5819") &&
strcmp(model, "m5819p") &&
+ strcmp(model, "m5823") &&
strcmp(model, "ds1287")) {
if (cbus != NULL) {
prom_printf("clock_probe: Central bus lacks timer chip.\n");
@@ -838,7 +839,8 @@ void __init clock_probe(void)
if (!strcmp(model, "ds1287") ||
!strcmp(model, "m5819") ||
- !strcmp(model, "m5819p")) {
+ !strcmp(model, "m5819p") ||
+ !strcmp(model, "m5823")) {
ds1287_regs = edev->resource[0].start;
} else {
mstk48t59_regs = edev->resource[0].start;
@@ -859,7 +861,8 @@ try_isa_clock:
}
if (!strcmp(model, "ds1287") ||
!strcmp(model, "m5819") ||
- !strcmp(model, "m5819p")) {
+ !strcmp(model, "m5819p") ||
+ !strcmp(model, "m5823")) {
ds1287_regs = isadev->resource.start;
} else {
mstk48t59_regs = isadev->resource.start;
diff --git a/arch/sparc64/mm/generic.c b/arch/sparc64/mm/generic.c
index 4f61c0a5ada1f..6b31f6117a950 100644
--- a/arch/sparc64/mm/generic.c
+++ b/arch/sparc64/mm/generic.c
@@ -20,16 +20,17 @@
*
* They use a pgprot that sets PAGE_IO and does not check the
* mem_map table as this is independent of normal memory.
- *
- * As a special hack if the lowest bit of offset is set the
- * side-effect bit will be turned off. This is used as a
- * performance improvement on FFB/AFB. -DaveM
*/
-static inline void io_remap_pte_range(pte_t * pte, unsigned long address, unsigned long size,
- unsigned long offset, pgprot_t prot, int space)
+static inline void io_remap_pte_range(struct mm_struct *mm, pte_t * pte,
+ unsigned long address,
+ unsigned long size,
+ unsigned long offset, pgprot_t prot,
+ int space)
{
unsigned long end;
+ /* clear hack bit that was used as a write_combine side-effect flag */
+ offset &= ~0x1UL;
address &= ~PMD_MASK;
end = address + size;
if (end > PMD_SIZE)
@@ -38,22 +39,22 @@ static inline void io_remap_pte_range(pte_t * pte, unsigned long address, unsign
pte_t entry;
unsigned long curend = address + PAGE_SIZE;
- entry = mk_pte_io((offset & ~(0x1UL)), prot, space);
+ entry = mk_pte_io(offset, prot, space);
if (!(address & 0xffff)) {
if (!(address & 0x3fffff) && !(offset & 0x3ffffe) && end >= address + 0x400000) {
- entry = mk_pte_io((offset & ~(0x1UL)),
+ entry = mk_pte_io(offset,
__pgprot(pgprot_val (prot) | _PAGE_SZ4MB),
space);
curend = address + 0x400000;
offset += 0x400000;
} else if (!(address & 0x7ffff) && !(offset & 0x7fffe) && end >= address + 0x80000) {
- entry = mk_pte_io((offset & ~(0x1UL)),
+ entry = mk_pte_io(offset,
__pgprot(pgprot_val (prot) | _PAGE_SZ512K),
space);
curend = address + 0x80000;
offset += 0x80000;
} else if (!(offset & 0xfffe) && end >= address + 0x10000) {
- entry = mk_pte_io((offset & ~(0x1UL)),
+ entry = mk_pte_io(offset,
__pgprot(pgprot_val (prot) | _PAGE_SZ64K),
space);
curend = address + 0x10000;
@@ -63,18 +64,16 @@ static inline void io_remap_pte_range(pte_t * pte, unsigned long address, unsign
} else
offset += PAGE_SIZE;
- if (offset & 0x1UL)
- pte_val(entry) &= ~(_PAGE_E);
do {
BUG_ON(!pte_none(*pte));
- set_pte(pte, entry);
+ set_pte_at(mm, address, pte, entry);
address += PAGE_SIZE;
pte++;
} while (address < curend);
} while (address < end);
}
-static inline int io_remap_pmd_range(pmd_t * pmd, unsigned long address, unsigned long size,
+static inline int io_remap_pmd_range(struct mm_struct *mm, pmd_t * pmd, unsigned long address, unsigned long size,
unsigned long offset, pgprot_t prot, int space)
{
unsigned long end;
@@ -85,10 +84,10 @@ static inline int io_remap_pmd_range(pmd_t * pmd, unsigned long address, unsigne
end = PGDIR_SIZE;
offset -= address;
do {
- pte_t * pte = pte_alloc_map(current->mm, pmd, address);
+ pte_t * pte = pte_alloc_map(mm, pmd, address);
if (!pte)
return -ENOMEM;
- io_remap_pte_range(pte, address, end - address, address + offset, prot, space);
+ io_remap_pte_range(mm, pte, address, end - address, address + offset, prot, space);
pte_unmap(pte);
address = (address + PMD_SIZE) & PMD_MASK;
pmd++;
@@ -96,7 +95,7 @@ static inline int io_remap_pmd_range(pmd_t * pmd, unsigned long address, unsigne
return 0;
}
-static inline int io_remap_pud_range(pud_t * pud, unsigned long address, unsigned long size,
+static inline int io_remap_pud_range(struct mm_struct *mm, pud_t * pud, unsigned long address, unsigned long size,
unsigned long offset, pgprot_t prot, int space)
{
unsigned long end;
@@ -107,10 +106,10 @@ static inline int io_remap_pud_range(pud_t * pud, unsigned long address, unsigne
end = PUD_SIZE;
offset -= address;
do {
- pmd_t *pmd = pmd_alloc(current->mm, pud, address);
+ pmd_t *pmd = pmd_alloc(mm, pud, address);
if (!pud)
return -ENOMEM;
- io_remap_pmd_range(pmd, address, end - address, address + offset, prot, space);
+ io_remap_pmd_range(mm, pmd, address, end - address, address + offset, prot, space);
address = (address + PUD_SIZE) & PUD_MASK;
pud++;
} while (address < end);
@@ -132,11 +131,45 @@ int io_remap_page_range(struct vm_area_struct *vma, unsigned long from, unsigned
spin_lock(&mm->page_table_lock);
while (from < end) {
+ pud_t *pud = pud_alloc(mm, dir, from);
+ error = -ENOMEM;
+ if (!pud)
+ break;
+ error = io_remap_pud_range(mm, pud, from, end - from, offset + from, prot, space);
+ if (error)
+ break;
+ from = (from + PGDIR_SIZE) & PGDIR_MASK;
+ dir++;
+ }
+ flush_tlb_range(vma, beg, end);
+ spin_unlock(&mm->page_table_lock);
+
+ return error;
+}
+
+int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from,
+ unsigned long pfn, unsigned long size, pgprot_t prot)
+{
+ int error = 0;
+ pgd_t * dir;
+ unsigned long beg = from;
+ unsigned long end = from + size;
+ struct mm_struct *mm = vma->vm_mm;
+ int space = GET_IOSPACE(pfn);
+ unsigned long offset = GET_PFN(pfn) << PAGE_SHIFT;
+
+ prot = __pgprot(pg_iobits);
+ offset -= from;
+ dir = pgd_offset(mm, from);
+ flush_cache_range(vma, beg, end);
+
+ spin_lock(&mm->page_table_lock);
+ while (from < end) {
pud_t *pud = pud_alloc(current->mm, dir, from);
error = -ENOMEM;
if (!pud)
break;
- error = io_remap_pud_range(pud, from, end - from, offset + from, prot, space);
+ error = io_remap_pud_range(mm, pud, from, end - from, offset + from, prot, space);
if (error)
break;
from = (from + PGDIR_SIZE) & PGDIR_MASK;
diff --git a/arch/sparc64/mm/hugetlbpage.c b/arch/sparc64/mm/hugetlbpage.c
index 5954cd7791fb0..ffa207795f1df 100644
--- a/arch/sparc64/mm/hugetlbpage.c
+++ b/arch/sparc64/mm/hugetlbpage.c
@@ -62,12 +62,13 @@ static pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
#define mk_pte_huge(entry) do { pte_val(entry) |= _PAGE_SZHUGE; } while (0)
static void set_huge_pte(struct mm_struct *mm, struct vm_area_struct *vma,
+ unsigned long addr,
struct page *page, pte_t * page_table, int write_access)
{
unsigned long i;
pte_t entry;
- mm->rss += (HPAGE_SIZE / PAGE_SIZE);
+ add_mm_counter(mm, rss, HPAGE_SIZE / PAGE_SIZE);
if (write_access)
entry = pte_mkwrite(pte_mkdirty(mk_pte(page,
@@ -78,8 +79,9 @@ static void set_huge_pte(struct mm_struct *mm, struct vm_area_struct *vma,
mk_pte_huge(entry);
for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) {
- set_pte(page_table, entry);
+ set_pte_at(mm, addr, page_table, entry);
page_table++;
+ addr += PAGE_SIZE;
pte_val(entry) += PAGE_SIZE;
}
@@ -116,12 +118,12 @@ int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src,
ptepage = pte_page(entry);
get_page(ptepage);
for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) {
- set_pte(dst_pte, entry);
+ set_pte_at(dst, addr, dst_pte, entry);
pte_val(entry) += PAGE_SIZE;
dst_pte++;
+ addr += PAGE_SIZE;
}
- dst->rss += (HPAGE_SIZE / PAGE_SIZE);
- addr += HPAGE_SIZE;
+ add_mm_counter(dst, rss, HPAGE_SIZE / PAGE_SIZE);
}
return 0;
@@ -207,11 +209,11 @@ void unmap_hugepage_range(struct vm_area_struct *vma,
page = pte_page(*pte);
put_page(page);
for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) {
- pte_clear(pte);
+ pte_clear(mm, address+(i*PAGE_SIZE), pte);
pte++;
}
}
- mm->rss -= (end - start) >> PAGE_SHIFT;
+ add_mm_counter(mm, rss, -((end - start) >> PAGE_SHIFT));
flush_tlb_range(vma, start, end);
}
@@ -261,7 +263,7 @@ int hugetlb_prefault(struct address_space *mapping, struct vm_area_struct *vma)
goto out;
}
}
- set_huge_pte(mm, vma, page, pte, vma->vm_flags & VM_WRITE);
+ set_huge_pte(mm, vma, addr, page, pte, vma->vm_flags & VM_WRITE);
}
out:
spin_unlock(&mm->page_table_lock);
diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c
index 5dc8b353b72a2..0e62b62c7dd44 100644
--- a/arch/sparc64/mm/init.c
+++ b/arch/sparc64/mm/init.c
@@ -431,7 +431,8 @@ static void inherit_prom_mappings(void)
if (tlb_type == spitfire)
val &= ~0x0003fe0000000000UL;
- set_pte (ptep, __pte(val | _PAGE_MODIFIED));
+ set_pte_at(&init_mm, vaddr,
+ ptep, __pte(val | _PAGE_MODIFIED));
trans[i].data += BASE_PAGE_SIZE;
}
}
@@ -1512,7 +1513,6 @@ void __init paging_init(void)
free_area_init_node(0, &contig_page_data, zones_size,
phys_base >> PAGE_SHIFT, zholes_size);
- mem_map = contig_page_data.node_mem_map;
}
device_scan();
diff --git a/arch/sparc64/mm/tlb.c b/arch/sparc64/mm/tlb.c
index f900be7beaddd..6255d6ef48eb0 100644
--- a/arch/sparc64/mm/tlb.c
+++ b/arch/sparc64/mm/tlb.c
@@ -41,24 +41,12 @@ void flush_tlb_pending(void)
}
}
-void tlb_batch_add(pte_t *ptep, pte_t orig)
+void tlb_batch_add(struct mm_struct *mm, unsigned long vaddr, pte_t *ptep, pte_t orig)
{
struct mmu_gather *mp = &__get_cpu_var(mmu_gathers);
- struct page *ptepage;
- struct mm_struct *mm;
- unsigned long vaddr, nr;
+ unsigned long nr;
- ptepage = virt_to_page(ptep);
- mm = (struct mm_struct *) ptepage->mapping;
-
- /* It is more efficient to let flush_tlb_kernel_range()
- * handle these cases.
- */
- if (mm == &init_mm)
- return;
-
- vaddr = ptepage->index +
- (((unsigned long)ptep & ~PAGE_MASK) * PTRS_PER_PTE);
+ vaddr &= PAGE_MASK;
if (pte_exec(orig))
vaddr |= 0x1UL;
diff --git a/arch/um/Kconfig b/arch/um/Kconfig
index f1b33a2383255..9a23df1821236 100644
--- a/arch/um/Kconfig
+++ b/arch/um/Kconfig
@@ -3,7 +3,7 @@ config GENERIC_HARDIRQS
bool
default y
-config USERMODE
+config UML
bool
default y
@@ -244,7 +244,6 @@ config KERNEL_HALF_GIGS
config HIGHMEM
bool "Highmem support"
- depends on BROKEN
config KERNEL_STACK_ORDER
int "Kernel stack size order"
diff --git a/arch/um/Kconfig.debug b/arch/um/Kconfig.debug
index a2d58306d18d3..b89989de364d1 100644
--- a/arch/um/Kconfig.debug
+++ b/arch/um/Kconfig.debug
@@ -8,7 +8,7 @@ config FRAME_POINTER
config PT_PROXY
bool "Enable ptrace proxy"
- depends on XTERM_CHAN && DEBUG_INFO
+ depends on XTERM_CHAN && DEBUG_INFO && MODE_TT
help
This option enables a debugging interface which allows gdb to debug
the kernel without needing to actually attach to kernel threads.
@@ -16,7 +16,7 @@ config PT_PROXY
config GPROF
bool "Enable gprof support"
- depends on DEBUG_INFO
+ depends on DEBUG_INFO && MODE_SKAS && !MODE_TT
help
This allows profiling of a User-Mode Linux kernel with the gprof
utility.
@@ -29,7 +29,7 @@ config GPROF
config GCOV
bool "Enable gcov support"
- depends on DEBUG_INFO
+ depends on DEBUG_INFO && MODE_SKAS
help
This option allows developers to retrieve coverage data from a UML
session.
@@ -40,4 +40,14 @@ config GCOV
If you're involved in UML kernel development and want to use gcov,
say Y. If you're unsure, say N.
+config SYSCALL_DEBUG
+ bool "Enable system call debugging"
+ default N
+ depends on DEBUG_INFO
+ help
+ This adds some system debugging to UML, including keeping a ring buffer
+ with recent system calls and some global and per-task statistics.
+
+ If unsure, say N
+
endmenu
diff --git a/arch/um/Kconfig_char b/arch/um/Kconfig_char
index fa34a9698586a..3e50fdb67626a 100644
--- a/arch/um/Kconfig_char
+++ b/arch/um/Kconfig_char
@@ -190,5 +190,19 @@ config HOSTAUDIO
tristate
default UML_SOUND
+config UML_RANDOM
+ tristate "Hardware random number generator"
+ help
+ This option enables UML's "hardware" random number generator. It
+ attaches itself to the host's /dev/random, supplying as much entropy
+ as the host has, rather than the small amount the UML gets from its
+ own drivers. It registers itself as a standard hardware random number
+ generator, major 10, minor 183, and the canonical device name is
+ /dev/hwrng.
+ The way to make use of this is to install the rng-tools package
+ (check your distro, or download from
+ http://sourceforge.net/projects/gkernel/). rngd periodically reads
+ /dev/hwrng and injects the entropy into /dev/random.
+
endmenu
diff --git a/arch/um/Makefile b/arch/um/Makefile
index df06d63a9bd7d..97bca6b5ca95b 100644
--- a/arch/um/Makefile
+++ b/arch/um/Makefile
@@ -182,13 +182,18 @@ $(ARCH_DIR)/include/uml-config.h : include/linux/autoconf.h
$(ARCH_DIR)/include/task.h: $(ARCH_DIR)/util/mk_task
$(call filechk,gen_header)
+$(ARCH_DIR)/include/user_constants.h: $(ARCH_DIR)/os/util/mk_user_constants
+ $(call filechk,gen_header)
+
$(ARCH_DIR)/include/kern_constants.h: $(ARCH_DIR)/util/mk_constants
$(call filechk,gen_header)
$(ARCH_DIR)/include/skas_ptregs.h: $(ARCH_DIR)/kernel/skas/util/mk_ptregs
$(call filechk,gen_header)
-$(ARCH_DIR)/util/mk_task $(ARCH_DIR)/util/mk_constants: $(ARCH_DIR)/util \
+$(ARCH_DIR)/os/util/mk_user_constants: $(ARCH_DIR)/os/util FORCE ;
+
+$(ARCH_DIR)/util/mk_task $(ARCH_DIR)/util/mk_constants: $(ARCH_DIR)/include/user_constants.h $(ARCH_DIR)/util \
FORCE ;
$(ARCH_DIR)/kernel/skas/util/mk_ptregs: $(ARCH_DIR)/kernel/skas/util FORCE ;
@@ -199,4 +204,7 @@ $(ARCH_DIR)/util: scripts_basic $(SYS_DIR)/sc.h FORCE
$(ARCH_DIR)/kernel/skas/util: scripts_basic FORCE
$(Q)$(MAKE) $(build)=$@
+$(ARCH_DIR)/os/util: scripts_basic FORCE
+ $(Q)$(MAKE) $(build)=$@
+
export SUBARCH USER_CFLAGS OS
diff --git a/arch/um/Makefile-skas b/arch/um/Makefile-skas
index 3c7d2a3005134..fd18ec572271b 100644
--- a/arch/um/Makefile-skas
+++ b/arch/um/Makefile-skas
@@ -3,10 +3,12 @@
# Licensed under the GPL
#
-PROFILE += -pg
+GPROF_OPT += -pg
+GCOV_OPT += -fprofile-arcs -ftest-coverage
-CFLAGS-$(CONFIG_GCOV) += -fprofile-arcs -ftest-coverage
-CFLAGS-$(CONFIG_GPROF) += $(PROFILE)
-LINK-$(CONFIG_GPROF) += $(PROFILE)
+CFLAGS-$(CONFIG_GCOV) += $(GCOV_OPT)
+CFLAGS-$(CONFIG_GPROF) += $(GPROF_OPT)
+LINK-$(CONFIG_GCOV) += $(GCOV_OPT)
+LINK-$(CONFIG_GPROF) += $(GPROF_OPT)
GEN_HEADERS += $(ARCH_DIR)/include/skas_ptregs.h
diff --git a/arch/um/Makefile-x86_64 b/arch/um/Makefile-x86_64
index 9638cac931650..a77971133e916 100644
--- a/arch/um/Makefile-x86_64
+++ b/arch/um/Makefile-x86_64
@@ -30,7 +30,3 @@ $(SYS_UTIL_DIR)/mk_thread: scripts_basic $(ARCH_SYMLINKS) $(GEN_HEADERS) FORCE
$(Q)$(MAKE) $(build)=$(SYS_UTIL_DIR) $@
CLEAN_FILES += $(SYS_HEADERS)
-
-LIBC_DIR := /usr/lib64
-
-export LIBC_DIR
diff --git a/arch/um/defconfig b/arch/um/defconfig
index 66f902a9907b1..fc3075c589d8c 100644
--- a/arch/um/defconfig
+++ b/arch/um/defconfig
@@ -1,13 +1,11 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.10-rc2-mm4
-# Wed Dec 1 13:45:40 2004
+# Linux kernel version: 2.6.12-rc1-bk1
+# Sun Mar 20 16:53:00 2005
#
CONFIG_GENERIC_HARDIRQS=y
-CONFIG_USERMODE=y
+CONFIG_UML=y
CONFIG_MMU=y
-# CONFIG_64_BIT is not set
-CONFIG_TOP_ADDR=0xc0000000
CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
@@ -17,12 +15,18 @@ CONFIG_GENERIC_CALIBRATE_DELAY=y
#
CONFIG_MODE_TT=y
CONFIG_MODE_SKAS=y
+# CONFIG_64_BIT is not set
+CONFIG_TOP_ADDR=0xc0000000
# CONFIG_3_LEVEL_PGTABLES is not set
+CONFIG_ARCH_HAS_SC_SIGNALS=y
+CONFIG_ARCH_REUSE_HOST_VSYSCALL_AREA=y
+CONFIG_LD_SCRIPT_STATIC=y
CONFIG_NET=y
CONFIG_BINFMT_ELF=y
CONFIG_BINFMT_MISC=m
CONFIG_HOSTFS=y
CONFIG_MCONSOLE=y
+# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_HOST_2G_2G is not set
# CONFIG_SMP is not set
CONFIG_NEST_LEVEL=0
@@ -49,7 +53,6 @@ CONFIG_BSD_PROCESS_ACCT=y
# CONFIG_BSD_PROCESS_ACCT_V3 is not set
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
# CONFIG_HOTPLUG is not set
CONFIG_KOBJECT_UEVENT=y
CONFIG_IKCONFIG=y
@@ -58,15 +61,16 @@ CONFIG_IKCONFIG_PROC=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
CONFIG_KALLSYMS_EXTRA_PASS=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
@@ -75,7 +79,6 @@ 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
@@ -84,6 +87,7 @@ CONFIG_KMOD=y
#
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
# CONFIG_DEBUG_DRIVER is not set
#
@@ -97,7 +101,7 @@ CONFIG_PORT_CHAN=y
CONFIG_PTY_CHAN=y
CONFIG_TTY_CHAN=y
CONFIG_XTERM_CHAN=y
-CONFIG_NOCONFIG_CHAN=y
+# CONFIG_NOCONFIG_CHAN is not set
CONFIG_CON_ZERO_CHAN="fd:0,fd:1"
CONFIG_CON_CHAN="xterm"
CONFIG_SSL_CHAN="pty"
@@ -108,17 +112,21 @@ CONFIG_LEGACY_PTY_COUNT=256
CONFIG_UML_SOUND=m
CONFIG_SOUND=m
CONFIG_HOSTAUDIO=m
+CONFIG_UML_RANDOM=y
#
-# Block Devices
+# Block devices
#
CONFIG_BLK_DEV_UBD=y
CONFIG_BLK_DEV_UBD_SYNC=y
CONFIG_BLK_DEV_COW_COMMON=y
CONFIG_BLK_DEV_LOOP=m
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
CONFIG_BLK_DEV_NBD=m
# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
#
# IO Schedulers
@@ -127,6 +135,7 @@ CONFIG_IOSCHED_NOOP=y
CONFIG_IOSCHED_AS=y
CONFIG_IOSCHED_DEADLINE=y
CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
CONFIG_NETDEVICES=y
#
@@ -196,10 +205,7 @@ CONFIG_IP_TCPDIAG=y
# Network testing
#
# CONFIG_NET_PKTGEN is not set
-# CONFIG_KGDBOE is not set
# CONFIG_NETPOLL is not set
-# CONFIG_NETPOLL_RX is not set
-# CONFIG_NETPOLL_TRAP is not set
# CONFIG_NET_POLL_CONTROLLER is not set
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
@@ -210,28 +216,6 @@ CONFIG_DUMMY=m
CONFIG_TUN=m
#
-# Ethernet (10 or 100Mbit)
-#
-# CONFIG_NET_ETHERNET 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
@@ -259,12 +243,15 @@ CONFIG_EXT3_FS=y
# CONFIG_EXT3_FS_XATTR is not set
CONFIG_JBD=y
# CONFIG_JBD_DEBUG is not set
-# CONFIG_REISER4_FS is not set
CONFIG_REISERFS_FS=y
# CONFIG_REISERFS_CHECK is not set
# CONFIG_REISERFS_PROC_INFO is not set
# CONFIG_REISERFS_FS_XATTR is not set
# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
# CONFIG_XFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
@@ -277,11 +264,6 @@ CONFIG_AUTOFS_FS=m
CONFIG_AUTOFS4_FS=m
#
-# Caches
-#
-# CONFIG_FSCACHE is not set
-
-#
# CD-ROM/DVD Filesystems
#
CONFIG_ISO9660_FS=m
@@ -331,7 +313,6 @@ CONFIG_RAMFS=y
#
# CONFIG_NFS_FS is not set
# CONFIG_NFSD is not set
-# CONFIG_EXPORTFS is not set
# CONFIG_SMB_FS is not set
# CONFIG_CIFS is not set
# CONFIG_NCP_FS is not set
@@ -400,10 +381,14 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_CRYPTO is not set
#
+# Hardware crypto devices
+#
+
+#
# Library routines
#
# CONFIG_CRC_CCITT is not set
-# CONFIG_CRC32 is not set
+CONFIG_CRC32=m
# CONFIG_LIBCRC32C is not set
#
@@ -415,15 +400,18 @@ CONFIG_NLS_DEFAULT="iso8859-1"
#
# Kernel hacking
#
+# CONFIG_PRINTK_TIME is not set
CONFIG_DEBUG_KERNEL=y
-# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_LOG_BUF_SHIFT=14
# CONFIG_SCHEDSTATS is not set
# CONFIG_DEBUG_SLAB is not set
# CONFIG_DEBUG_SPINLOCK is not set
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
# CONFIG_DEBUG_KOBJECT is not set
CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_FS is not set
CONFIG_FRAME_POINTER=y
CONFIG_PT_PROXY=y
# CONFIG_GPROF is not set
# CONFIG_GCOV is not set
+# CONFIG_SYSCALL_DEBUG is not set
diff --git a/arch/um/drivers/Makefile b/arch/um/drivers/Makefile
index e94da95ffdcfa..323f72c64cd20 100644
--- a/arch/um/drivers/Makefile
+++ b/arch/um/drivers/Makefile
@@ -3,8 +3,6 @@
# Licensed under the GPL
#
-CHAN_OBJS := chan_kern.o chan_user.o line.o
-
# pcap is broken in 2.5 because kbuild doesn't allow pcap.a to be linked
# in to pcap.o
@@ -20,7 +18,7 @@ ubd-objs := ubd_kern.o ubd_user.o
port-objs := port_kern.o port_user.o
harddog-objs := harddog_kern.o harddog_user.o
-obj-y := stdio_console.o fd.o $(CHAN_OBJS)
+obj-y := stdio_console.o fd.o chan_kern.o chan_user.o line.o
obj-$(CONFIG_SSL) += ssl.o
obj-$(CONFIG_STDERR_CONSOLE) += stderr_console.o
@@ -41,13 +39,8 @@ obj-$(CONFIG_TTY_CHAN) += tty.o
obj-$(CONFIG_XTERM_CHAN) += xterm.o xterm_kern.o
obj-$(CONFIG_UML_WATCHDOG) += harddog.o
obj-$(CONFIG_BLK_DEV_COW_COMMON) += cow_user.o
+obj-$(CONFIG_UML_RANDOM) += random.o
+USER_OBJS := fd.o null.o pty.o tty.o xterm.o
-USER_SINGLE_OBJS = $(foreach f,$(patsubst %.o,%,$(obj-y) $(obj-m)),$($(f)-objs))
-
-USER_OBJS := $(filter %_user.o,$(obj-y) $(obj-m) $(USER_SINGLE_OBJS)) fd.o \
- null.o pty.o tty.o xterm.o
-USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
-
-$(USER_OBJS) : %.o: %.c
- $(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
+include arch/um/scripts/Makefile.rules
diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c
index f30ae1b0bcc04..1f77deb3fd237 100644
--- a/arch/um/drivers/chan_kern.c
+++ b/arch/um/drivers/chan_kern.c
@@ -218,7 +218,6 @@ void enable_chan(struct list_head *chans, struct tty_struct *tty)
void close_chan(struct list_head *chans)
{
- struct list_head *ele;
struct chan *chan;
/* Close in reverse order as open in case more than one of them
@@ -226,8 +225,7 @@ void close_chan(struct list_head *chans)
* state. Then, the first one opened will have the original state,
* so it must be the last closed.
*/
- for(ele = chans->prev; ele != chans; ele = ele->prev){
- chan = list_entry(ele, struct chan, list);
+ list_for_each_entry_reverse(chan, chans, list) {
if(!chan->opened) continue;
if(chan->ops->close != NULL)
(*chan->ops->close)(chan->fd, chan->data);
@@ -250,11 +248,8 @@ int write_chan(struct list_head *chans, const char *buf, int len,
n = chan->ops->write(chan->fd, buf, len, chan->data);
if (chan->primary) {
ret = n;
- if ((ret == -EAGAIN) || ((ret >= 0) && (ret < len))){
+ if ((ret == -EAGAIN) || ((ret >= 0) && (ret < len)))
reactivate_fd(chan->fd, write_irq);
- if (ret == -EAGAIN)
- ret = 0;
- }
}
}
return(ret);
diff --git a/arch/um/drivers/cow_user.c b/arch/um/drivers/cow_user.c
index c43425c1ee1f2..a8ce6fc3ef26b 100644
--- a/arch/um/drivers/cow_user.c
+++ b/arch/um/drivers/cow_user.c
@@ -1,6 +1,9 @@
#include <stddef.h>
#include <string.h>
#include <errno.h>
+/* _XOPEN_SOURCE is needed for pread, but we define _GNU_SOURCE, which defines
+ * that.
+ */
#include <unistd.h>
#include <byteswap.h>
#include <sys/time.h>
diff --git a/arch/um/drivers/fd.c b/arch/um/drivers/fd.c
index 1c6daad921a24..f0b888f66e056 100644
--- a/arch/um/drivers/fd.c
+++ b/arch/um/drivers/fd.c
@@ -19,7 +19,7 @@ struct fd_chan {
char str[sizeof("1234567890\0")];
};
-void *fd_init(char *str, int device, struct chan_opts *opts)
+static void *fd_init(char *str, int device, struct chan_opts *opts)
{
struct fd_chan *data;
char *end;
@@ -43,7 +43,7 @@ void *fd_init(char *str, int device, struct chan_opts *opts)
return(data);
}
-int fd_open(int input, int output, int primary, void *d, char **dev_out)
+static int fd_open(int input, int output, int primary, void *d, char **dev_out)
{
struct fd_chan *data = d;
int err;
@@ -62,7 +62,7 @@ int fd_open(int input, int output, int primary, void *d, char **dev_out)
return(data->fd);
}
-void fd_close(int fd, void *d)
+static void fd_close(int fd, void *d)
{
struct fd_chan *data = d;
int err;
@@ -76,7 +76,7 @@ void fd_close(int fd, void *d)
}
}
-int fd_console_write(int fd, const char *buf, int n, void *d)
+static int fd_console_write(int fd, const char *buf, int n, void *d)
{
struct fd_chan *data = d;
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index d4286de17f070..6924f273ced9f 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -128,7 +128,7 @@ int line_write(struct tty_struct *tty, const unsigned char *buf, int len)
ret = buffer_data(line, buf, len);
err = flush_buffer(line);
local_irq_restore(flags);
- if(err <= 0)
+ if(err <= 0 && (err != -EAGAIN || !ret))
ret = err;
}
else {
diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c
index fe1e79a46c3f7..4eeaf88c1e97b 100644
--- a/arch/um/drivers/net_kern.c
+++ b/arch/um/drivers/net_kern.c
@@ -383,7 +383,6 @@ static int eth_configure(int n, void *init, char *mac,
save = lp->user[0];
*lp = ((struct uml_net_private)
{ .list = LIST_HEAD_INIT(lp->list),
- .lock = SPIN_LOCK_UNLOCKED,
.dev = dev,
.fd = -1,
.mac = { 0xfe, 0xfd, 0x0, 0x0, 0x0, 0x0},
@@ -400,6 +399,7 @@ static int eth_configure(int n, void *init, char *mac,
.user = { save } });
init_timer(&lp->tl);
+ spin_lock_init(&lp->lock);
lp->tl.function = uml_net_user_timer_expire;
if (lp->have_mac)
memcpy(lp->mac, device->mac, sizeof(lp->mac));
@@ -728,7 +728,8 @@ static void close_devices(void)
list_for_each(ele, &opened){
lp = list_entry(ele, struct uml_net_private, list);
- if(lp->close != NULL) (*lp->close)(lp->fd, &lp->user);
+ 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/null.c b/arch/um/drivers/null.c
index 66b2fbe3dfb2e..14cc5f78398ad 100644
--- a/arch/um/drivers/null.c
+++ b/arch/um/drivers/null.c
@@ -10,23 +10,24 @@
static int null_chan;
-void *null_init(char *str, int device, struct chan_opts *opts)
+static void *null_init(char *str, int device, struct chan_opts *opts)
{
return(&null_chan);
}
-int null_open(int input, int output, int primary, void *d, char **dev_out)
+static int null_open(int input, int output, int primary, void *d,
+ char **dev_out)
{
*dev_out = NULL;
return(os_open_file(DEV_NULL, of_rdwr(OPENFLAGS()), 0));
}
-int null_read(int fd, char *c_out, void *unused)
+static int null_read(int fd, char *c_out, void *unused)
{
return(-ENODEV);
}
-void null_free(void *data)
+static void null_free(void *data)
{
}
diff --git a/arch/um/drivers/port_kern.c b/arch/um/drivers/port_kern.c
index 14f66da4dc902..b5ee07472f79b 100644
--- a/arch/um/drivers/port_kern.c
+++ b/arch/um/drivers/port_kern.c
@@ -10,6 +10,7 @@
#include "linux/irq.h"
#include "linux/spinlock.h"
#include "linux/errno.h"
+#include "asm/atomic.h"
#include "asm/semaphore.h"
#include "asm/errno.h"
#include "kern_util.h"
@@ -22,8 +23,9 @@
struct port_list {
struct list_head list;
+ atomic_t wait_count;
int has_connection;
- struct semaphore sem;
+ struct completion done;
int port;
int fd;
spinlock_t lock;
@@ -66,10 +68,17 @@ static irqreturn_t pipe_interrupt(int irq, void *data, struct pt_regs *regs)
conn->fd = fd;
list_add(&conn->list, &conn->port->connections);
- up(&conn->port->sem);
+ complete(&conn->port->done);
return(IRQ_HANDLED);
}
+#define NO_WAITER_MSG \
+ "****\n" \
+ "There are currently no UML consoles waiting for port connections.\n" \
+ "Either disconnect from one to make it available or activate some more\n" \
+ "by enabling more consoles in the UML /etc/inittab.\n" \
+ "****\n"
+
static int port_accept(struct port_list *port)
{
struct connection *conn;
@@ -104,6 +113,10 @@ static int port_accept(struct port_list *port)
goto out_free;
}
+ if(atomic_read(&port->wait_count) == 0){
+ os_write_file(fd, NO_WAITER_MSG, sizeof(NO_WAITER_MSG));
+ printk("No one waiting for port\n");
+ }
list_add(&conn->list, &port->pending);
return(1);
@@ -182,14 +195,14 @@ void *port_data(int port_num)
*port = ((struct port_list)
{ .list = LIST_HEAD_INIT(port->list),
+ .wait_count = ATOMIC_INIT(0),
.has_connection = 0,
- .sem = __SEMAPHORE_INITIALIZER(port->sem,
- 0),
- .lock = SPIN_LOCK_UNLOCKED,
.port = port_num,
.fd = fd,
.pending = LIST_HEAD_INIT(port->pending),
.connections = LIST_HEAD_INIT(port->connections) });
+ spin_lock_init(&port->lock);
+ init_completion(&port->done);
list_add(&port->list, &ports);
found:
@@ -220,9 +233,11 @@ int port_wait(void *data)
struct port_list *port = dev->port;
int fd;
+ atomic_inc(&port->wait_count);
while(1){
- if(down_interruptible(&port->sem))
- return(-ERESTARTSYS);
+ fd = -ERESTARTSYS;
+ if(wait_for_completion_interruptible(&port->done))
+ goto out;
spin_lock(&port->lock);
@@ -254,8 +269,9 @@ int port_wait(void *data)
dev->helper_pid = conn->helper_pid;
dev->telnetd_pid = conn->telnetd_pid;
kfree(conn);
-
- return(fd);
+ out:
+ atomic_dec(&port->wait_count);
+ return fd;
}
void port_remove_dev(void *d)
@@ -291,14 +307,3 @@ static void free_port(void)
}
__uml_exitcall(free_port);
-
-/*
- * 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/port_user.c b/arch/um/drivers/port_user.c
index 996e817f3a3fe..14dd2002d2da6 100644
--- a/arch/um/drivers/port_user.c
+++ b/arch/um/drivers/port_user.c
@@ -28,7 +28,7 @@ struct port_chan {
char dev[sizeof("32768\0")];
};
-void *port_init(char *str, int device, struct chan_opts *opts)
+static void *port_init(char *str, int device, struct chan_opts *opts)
{
struct port_chan *data;
void *kern_data;
@@ -65,7 +65,7 @@ void *port_init(char *str, int device, struct chan_opts *opts)
return(NULL);
}
-void port_free(void *d)
+static void port_free(void *d)
{
struct port_chan *data = d;
@@ -73,7 +73,8 @@ void port_free(void *d)
kfree(data);
}
-int port_open(int input, int output, int primary, void *d, char **dev_out)
+static int port_open(int input, int output, int primary, void *d,
+ char **dev_out)
{
struct port_chan *data = d;
int fd, err;
@@ -92,7 +93,7 @@ int port_open(int input, int output, int primary, void *d, char **dev_out)
return(fd);
}
-void port_close(int fd, void *d)
+static void port_close(int fd, void *d)
{
struct port_chan *data = d;
@@ -100,7 +101,7 @@ void port_close(int fd, void *d)
os_close_file(fd);
}
-int port_console_write(int fd, const char *buf, int n, void *d)
+static int port_console_write(int fd, const char *buf, int n, void *d)
{
struct port_chan *data = d;
diff --git a/arch/um/drivers/pty.c b/arch/um/drivers/pty.c
index b5777e7b10eea..ed84d01df6cc9 100644
--- a/arch/um/drivers/pty.c
+++ b/arch/um/drivers/pty.c
@@ -22,7 +22,7 @@ struct pty_chan {
char dev_name[sizeof("/dev/pts/0123456\0")];
};
-void *pty_chan_init(char *str, int device, struct chan_opts *opts)
+static void *pty_chan_init(char *str, int device, struct chan_opts *opts)
{
struct pty_chan *data;
@@ -34,7 +34,8 @@ void *pty_chan_init(char *str, int device, struct chan_opts *opts)
return(data);
}
-int pts_open(int input, int output, int primary, void *d, char **dev_out)
+static int pts_open(int input, int output, int primary, void *d,
+ char **dev_out)
{
struct pty_chan *data = d;
char *dev;
@@ -63,7 +64,7 @@ int pts_open(int input, int output, int primary, void *d, char **dev_out)
return(fd);
}
-int getmaster(char *line)
+static int getmaster(char *line)
{
char *pty, *bank, *cp;
int master, err;
@@ -92,7 +93,8 @@ int getmaster(char *line)
return(-1);
}
-int pty_open(int input, int output, int primary, void *d, char **dev_out)
+static int pty_open(int input, int output, int primary, void *d,
+ char **dev_out)
{
struct pty_chan *data = d;
int fd, err;
@@ -115,7 +117,7 @@ int pty_open(int input, int output, int primary, void *d, char **dev_out)
return(fd);
}
-int pty_console_write(int fd, const char *buf, int n, void *d)
+static int pty_console_write(int fd, const char *buf, int n, void *d)
{
struct pty_chan *data = d;
diff --git a/arch/um/drivers/random.c b/arch/um/drivers/random.c
new file mode 100644
index 0000000000000..d43e9fab05a76
--- /dev/null
+++ b/arch/um/drivers/random.c
@@ -0,0 +1,122 @@
+/* Much of this ripped from hw_random.c */
+
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/delay.h>
+#include <asm/uaccess.h>
+#include "os.h"
+
+/*
+ * core module and version information
+ */
+#define RNG_VERSION "1.0.0"
+#define RNG_MODULE_NAME "random"
+#define RNG_DRIVER_NAME RNG_MODULE_NAME " virtual driver " RNG_VERSION
+#define PFX RNG_MODULE_NAME ": "
+
+#define RNG_MISCDEV_MINOR 183 /* official */
+
+static int random_fd = -1;
+
+static int rng_dev_open (struct inode *inode, struct file *filp)
+{
+ /* enforce read-only access to this chrdev */
+ if ((filp->f_mode & FMODE_READ) == 0)
+ return -EINVAL;
+ if (filp->f_mode & FMODE_WRITE)
+ return -EINVAL;
+
+ return 0;
+}
+
+static ssize_t rng_dev_read (struct file *filp, char __user *buf, size_t size,
+ loff_t * offp)
+{
+ u32 data;
+ int n, ret = 0, have_data;
+
+ while(size){
+ n = os_read_file(random_fd, &data, sizeof(data));
+ if(n > 0){
+ have_data = n;
+ while (have_data && size) {
+ if (put_user((u8)data, buf++)) {
+ ret = ret ? : -EFAULT;
+ break;
+ }
+ size--;
+ ret++;
+ have_data--;
+ data>>=8;
+ }
+ }
+ else if(n == -EAGAIN){
+ if (filp->f_flags & O_NONBLOCK)
+ return ret ? : -EAGAIN;
+
+ if(need_resched()){
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout(1);
+ }
+ }
+ else return n;
+ if (signal_pending (current))
+ return ret ? : -ERESTARTSYS;
+ }
+ return ret;
+}
+
+static struct file_operations rng_chrdev_ops = {
+ .owner = THIS_MODULE,
+ .open = rng_dev_open,
+ .read = rng_dev_read,
+};
+
+static struct miscdevice rng_miscdev = {
+ RNG_MISCDEV_MINOR,
+ RNG_MODULE_NAME,
+ &rng_chrdev_ops,
+};
+
+/*
+ * rng_init - initialize RNG module
+ */
+static int __init rng_init (void)
+{
+ int err;
+
+ err = os_open_file("/dev/random", of_read(OPENFLAGS()), 0);
+ if(err < 0)
+ goto out;
+
+ random_fd = err;
+
+ err = os_set_fd_block(random_fd, 0);
+ if(err)
+ goto err_out_cleanup_hw;
+
+ err = misc_register (&rng_miscdev);
+ if (err) {
+ printk (KERN_ERR PFX "misc device register failed\n");
+ goto err_out_cleanup_hw;
+ }
+
+ out:
+ return err;
+
+ err_out_cleanup_hw:
+ random_fd = -1;
+ goto out;
+}
+
+/*
+ * rng_cleanup - shutdown RNG module
+ */
+static void __exit rng_cleanup (void)
+{
+ misc_deregister (&rng_miscdev);
+}
+
+module_init (rng_init);
+module_exit (rng_cleanup);
diff --git a/arch/um/drivers/slip_user.c b/arch/um/drivers/slip_user.c
index 3d8d4ca360215..d94846b1b4cfd 100644
--- a/arch/um/drivers/slip_user.c
+++ b/arch/um/drivers/slip_user.c
@@ -108,6 +108,9 @@ static int slip_tramp(char **argv, int fd)
err = -EINVAL;
}
}
+
+ os_close_file(fds[0]);
+
return(err);
}
@@ -128,6 +131,7 @@ static int slip_open(void *data)
sfd = os_open_file(ptsname(mfd), of_rdwr(OPENFLAGS()), 0);
if(sfd < 0){
printk("Couldn't open tty for slip line, err = %d\n", -sfd);
+ os_close_file(mfd);
return(sfd);
}
if(set_up_tty(sfd)) return(-1);
@@ -175,7 +179,7 @@ static void slip_close(int fd, void *data)
sprintf(version_buf, "%d", UML_NET_VERSION);
- err = slip_tramp(argv, -1);
+ err = slip_tramp(argv, pri->slave);
if(err != 0)
printk("slip_tramp failed - errno = %d\n", -err);
diff --git a/arch/um/drivers/slirp_kern.c b/arch/um/drivers/slirp_kern.c
index 8dd1ea551049e..c9d6b52a831de 100644
--- a/arch/um/drivers/slirp_kern.c
+++ b/arch/um/drivers/slirp_kern.c
@@ -33,8 +33,11 @@ void slirp_init(struct net_device *dev, void *data)
dev->init = NULL;
dev->hard_header_len = 0;
- dev->addr_len = 4;
- dev->type = ARPHRD_ETHER;
+ dev->header_cache_update = NULL;
+ dev->hard_header_cache = NULL;
+ dev->hard_header = NULL;
+ dev->addr_len = 0;
+ dev->type = ARPHRD_SLIP;
dev->tx_queue_len = 256;
dev->flags = IFF_NOARP;
printk("SLIRP backend - command line:");
diff --git a/arch/um/drivers/tty.c b/arch/um/drivers/tty.c
index dd008aa8f5dd0..6fbb670ee2741 100644
--- a/arch/um/drivers/tty.c
+++ b/arch/um/drivers/tty.c
@@ -18,7 +18,7 @@ struct tty_chan {
struct termios tt;
};
-void *tty_chan_init(char *str, int device, struct chan_opts *opts)
+static void *tty_chan_init(char *str, int device, struct chan_opts *opts)
{
struct tty_chan *data;
@@ -38,7 +38,8 @@ void *tty_chan_init(char *str, int device, struct chan_opts *opts)
return(data);
}
-int tty_open(int input, int output, int primary, void *d, char **dev_out)
+static int tty_open(int input, int output, int primary, void *d,
+ char **dev_out)
{
struct tty_chan *data = d;
int fd, err;
@@ -59,7 +60,7 @@ int tty_open(int input, int output, int primary, void *d, char **dev_out)
return(fd);
}
-int tty_console_write(int fd, const char *buf, int n, void *d)
+static int tty_console_write(int fd, const char *buf, int n, void *d)
{
struct tty_chan *data = d;
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index 9b4820ec993a1..4d8b165bfa488 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -453,6 +453,22 @@ __uml_help(ubd_setup,
" an 's' will cause data to be written to disk on the host immediately.\n\n"
);
+static int udb_setup(char *str)
+{
+ printk("udb%s specified on command line is almost certainly a ubd -> "
+ "udb TYPO\n", str);
+ return(1);
+}
+
+__setup("udb", udb_setup);
+__uml_help(udb_setup,
+"udb\n"
+" This option is here solely to catch ubd -> udb typos, which can be\n\n"
+" to impossible to catch visually unless you specifically look for\n\n"
+" them. The only result of any option starting with 'udb' is an error\n\n"
+" in the boot output.\n\n"
+);
+
static int fakehd_set = 0;
static int fakehd(char *str)
{
@@ -605,7 +621,11 @@ static int ubd_open_dev(struct ubd *dev)
}
}
- if(dev->fd < 0) return(dev->fd);
+ if(dev->fd < 0){
+ printk("Failed to open '%s', errno = %d\n", dev->file,
+ -dev->fd);
+ return(dev->fd);
+ }
if(dev->cow.file != NULL){
err = -ENOMEM;
@@ -746,15 +766,9 @@ static int ubd_config(char *str)
static int ubd_get_config(char *name, char *str, int size, char **error_out)
{
struct ubd *dev;
- char *end;
int n, len = 0;
- n = simple_strtoul(name, &end, 0);
- if((*end != '\0') || (end == name)){
- *error_out = "ubd_get_config : didn't parse device number";
- return(-1);
- }
-
+ n = parse_unit(&name);
if((n >= MAX_DEV) || (n < 0)){
*error_out = "ubd_get_config : device number out of range";
return(-1);
diff --git a/arch/um/drivers/xterm.c b/arch/um/drivers/xterm.c
index c1c22e5fc3730..93dc1911363ff 100644
--- a/arch/um/drivers/xterm.c
+++ b/arch/um/drivers/xterm.c
@@ -31,6 +31,7 @@ struct xterm_chan {
int direct_rcv;
};
+/* Not static because it's called directly by the tt mode gdb code */
void *xterm_init(char *str, int device, struct chan_opts *opts)
{
struct xterm_chan *data;
@@ -83,8 +84,11 @@ __uml_setup("xterm=", xterm_setup,
" are 'xterm=gnome-terminal,-t,-x'.\n\n"
);
-/* XXX This badly needs some cleaning up in the error paths */
-int xterm_open(int input, int output, int primary, void *d, char **dev_out)
+/* XXX This badly needs some cleaning up in the error paths
+ * Not static because it's called directly by the tt mode gdb code
+ */
+int xterm_open(int input, int output, int primary, void *d,
+ char **dev_out)
{
struct xterm_chan *data = d;
unsigned long stack;
@@ -170,6 +174,7 @@ int xterm_open(int input, int output, int primary, void *d, char **dev_out)
return(new);
}
+/* Not static because it's called directly by the tt mode gdb code */
void xterm_close(int fd, void *d)
{
struct xterm_chan *data = d;
@@ -183,12 +188,12 @@ void xterm_close(int fd, void *d)
os_close_file(fd);
}
-void xterm_free(void *d)
+static void xterm_free(void *d)
{
free(d);
}
-int xterm_console_write(int fd, const char *buf, int n, void *d)
+static int xterm_console_write(int fd, const char *buf, int n, void *d)
{
struct xterm_chan *data = d;
diff --git a/arch/um/drivers/xterm_kern.c b/arch/um/drivers/xterm_kern.c
index afce46fa64d3b..7917b9d1cec8f 100644
--- a/arch/um/drivers/xterm_kern.c
+++ b/arch/um/drivers/xterm_kern.c
@@ -16,7 +16,7 @@
#include "xterm.h"
struct xterm_wait {
- struct semaphore sem;
+ struct completion ready;
int fd;
int pid;
int new_fd;
@@ -32,7 +32,7 @@ static irqreturn_t xterm_interrupt(int irq, void *data, struct pt_regs *regs)
return(IRQ_NONE);
xterm->new_fd = fd;
- up(&xterm->sem);
+ complete(&xterm->ready);
return(IRQ_HANDLED);
}
@@ -49,10 +49,10 @@ int xterm_fd(int socket, int *pid_out)
/* This is a locked semaphore... */
*data = ((struct xterm_wait)
- { .sem = __SEMAPHORE_INITIALIZER(data->sem, 0),
- .fd = socket,
+ { .fd = socket,
.pid = -1,
.new_fd = -1 });
+ init_completion(&data->ready);
err = um_request_irq(XTERM_IRQ, socket, IRQ_READ, xterm_interrupt,
SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM,
@@ -68,7 +68,7 @@ int xterm_fd(int socket, int *pid_out)
*
* XXX Note, if the xterm doesn't work for some reason (eg. DISPLAY
* isn't set) this will hang... */
- down(&data->sem);
+ wait_for_completion(&data->ready);
free_irq_by_irq_and_dev(XTERM_IRQ, data);
free_irq(XTERM_IRQ, data);
diff --git a/arch/um/include/choose-mode.h b/arch/um/include/choose-mode.h
index 959e6d2ef77b7..8e6b62f5e9ac2 100644
--- a/arch/um/include/choose-mode.h
+++ b/arch/um/include/choose-mode.h
@@ -21,6 +21,13 @@
#define CHOOSE_MODE_PROC(tt, skas, args...) \
CHOOSE_MODE(tt(args), skas(args))
+extern int mode_tt;
+static inline void *__choose_mode(void *tt, void *skas) {
+ return mode_tt ? tt : skas;
+}
+
+#define __CHOOSE_MODE(tt, skas) (*( (typeof(tt) *) __choose_mode(&(tt), &(skas))))
+
#endif
/*
diff --git a/arch/um/include/kern.h b/arch/um/include/kern.h
index 3e3aed19f54ce..1e3170768b5c2 100644
--- a/arch/um/include/kern.h
+++ b/arch/um/include/kern.h
@@ -26,6 +26,7 @@ extern void *malloc(int size);
extern void perror(char *err);
extern int kill(int pid, int sig);
extern int getuid(void);
+extern int getgid(void);
extern int pause(void);
extern int write(int, const void *, int);
extern int exit(int);
diff --git a/arch/um/include/registers.h b/arch/um/include/registers.h
index 87899df0072f8..8744abb5224f1 100644
--- a/arch/um/include/registers.h
+++ b/arch/um/include/registers.h
@@ -9,6 +9,8 @@
#include "sysdep/ptrace.h"
extern void init_thread_registers(union uml_pt_regs *to);
+extern int save_fp_registers(int pid, unsigned long *fp_regs);
+extern int restore_fp_registers(int pid, unsigned long *fp_regs);
extern void save_registers(int pid, union uml_pt_regs *regs);
extern void restore_registers(int pid, union uml_pt_regs *regs);
extern void init_registers(int pid);
diff --git a/arch/um/include/sysdep-i386/checksum.h b/arch/um/include/sysdep-i386/checksum.h
index 28032d6cd7a9f..3a2a45811aa3e 100644
--- a/arch/um/include/sysdep-i386/checksum.h
+++ b/arch/um/include/sysdep-i386/checksum.h
@@ -41,7 +41,7 @@ unsigned int csum_partial_copy_from(const unsigned char *src, unsigned char *dst
* passed in an incorrect kernel address to one of these functions.
*
* If you use these functions directly please don't forget the
- * verify_area().
+ * access_ok().
*/
static __inline__
diff --git a/arch/um/include/sysdep-i386/ptrace.h b/arch/um/include/sysdep-i386/ptrace.h
index dc126e5e25ac5..661d495e20448 100644
--- a/arch/um/include/sysdep-i386/ptrace.h
+++ b/arch/um/include/sysdep-i386/ptrace.h
@@ -7,12 +7,12 @@
#define __SYSDEP_I386_PTRACE_H
#include "uml-config.h"
+#include "user_constants.h"
-#ifdef UML_CONFIG_MODE_TT
-#include "sysdep/sc.h"
-#endif
+#define MAX_REG_NR (UM_FRAME_SIZE / sizeof(unsigned long))
+#define MAX_REG_OFFSET (UM_FRAME_SIZE)
-#ifdef UML_CONFIG_MODE_SKAS
+extern void update_debugregs(int seq);
/* syscall emulation path in ptrace */
@@ -24,9 +24,13 @@ void set_using_sysemu(int value);
int get_using_sysemu(void);
extern int sysemu_supported;
-#include "skas_ptregs.h"
+#ifdef UML_CONFIG_MODE_TT
+#include "sysdep/sc.h"
+#endif
-#define HOST_FRAME_SIZE 17
+#ifdef UML_CONFIG_MODE_SKAS
+
+#include "skas_ptregs.h"
#define REGS_IP(r) ((r)[HOST_IP])
#define REGS_SP(r) ((r)[HOST_SP])
@@ -89,39 +93,39 @@ extern int mode_tt;
#define UPT_SC(r) ((r)->tt.sc)
#define UPT_IP(r) \
- CHOOSE_MODE(SC_IP(UPT_SC(r)), REGS_IP((r)->skas.regs))
+ __CHOOSE_MODE(SC_IP(UPT_SC(r)), REGS_IP((r)->skas.regs))
#define UPT_SP(r) \
- CHOOSE_MODE(SC_SP(UPT_SC(r)), REGS_SP((r)->skas.regs))
+ __CHOOSE_MODE(SC_SP(UPT_SC(r)), REGS_SP((r)->skas.regs))
#define UPT_EFLAGS(r) \
- CHOOSE_MODE(SC_EFLAGS(UPT_SC(r)), REGS_EFLAGS((r)->skas.regs))
+ __CHOOSE_MODE(SC_EFLAGS(UPT_SC(r)), REGS_EFLAGS((r)->skas.regs))
#define UPT_EAX(r) \
- CHOOSE_MODE(SC_EAX(UPT_SC(r)), REGS_EAX((r)->skas.regs))
+ __CHOOSE_MODE(SC_EAX(UPT_SC(r)), REGS_EAX((r)->skas.regs))
#define UPT_EBX(r) \
- CHOOSE_MODE(SC_EBX(UPT_SC(r)), REGS_EBX((r)->skas.regs))
+ __CHOOSE_MODE(SC_EBX(UPT_SC(r)), REGS_EBX((r)->skas.regs))
#define UPT_ECX(r) \
- CHOOSE_MODE(SC_ECX(UPT_SC(r)), REGS_ECX((r)->skas.regs))
+ __CHOOSE_MODE(SC_ECX(UPT_SC(r)), REGS_ECX((r)->skas.regs))
#define UPT_EDX(r) \
- CHOOSE_MODE(SC_EDX(UPT_SC(r)), REGS_EDX((r)->skas.regs))
+ __CHOOSE_MODE(SC_EDX(UPT_SC(r)), REGS_EDX((r)->skas.regs))
#define UPT_ESI(r) \
- CHOOSE_MODE(SC_ESI(UPT_SC(r)), REGS_ESI((r)->skas.regs))
+ __CHOOSE_MODE(SC_ESI(UPT_SC(r)), REGS_ESI((r)->skas.regs))
#define UPT_EDI(r) \
- CHOOSE_MODE(SC_EDI(UPT_SC(r)), REGS_EDI((r)->skas.regs))
+ __CHOOSE_MODE(SC_EDI(UPT_SC(r)), REGS_EDI((r)->skas.regs))
#define UPT_EBP(r) \
- CHOOSE_MODE(SC_EBP(UPT_SC(r)), REGS_EBP((r)->skas.regs))
+ __CHOOSE_MODE(SC_EBP(UPT_SC(r)), REGS_EBP((r)->skas.regs))
#define UPT_ORIG_EAX(r) \
- CHOOSE_MODE((r)->tt.syscall, (r)->skas.syscall)
+ __CHOOSE_MODE((r)->tt.syscall, (r)->skas.syscall)
#define UPT_CS(r) \
- CHOOSE_MODE(SC_CS(UPT_SC(r)), REGS_CS((r)->skas.regs))
+ __CHOOSE_MODE(SC_CS(UPT_SC(r)), REGS_CS((r)->skas.regs))
#define UPT_SS(r) \
- CHOOSE_MODE(SC_SS(UPT_SC(r)), REGS_SS((r)->skas.regs))
+ __CHOOSE_MODE(SC_SS(UPT_SC(r)), REGS_SS((r)->skas.regs))
#define UPT_DS(r) \
- CHOOSE_MODE(SC_DS(UPT_SC(r)), REGS_DS((r)->skas.regs))
+ __CHOOSE_MODE(SC_DS(UPT_SC(r)), REGS_DS((r)->skas.regs))
#define UPT_ES(r) \
- CHOOSE_MODE(SC_ES(UPT_SC(r)), REGS_ES((r)->skas.regs))
+ __CHOOSE_MODE(SC_ES(UPT_SC(r)), REGS_ES((r)->skas.regs))
#define UPT_FS(r) \
- CHOOSE_MODE(SC_FS(UPT_SC(r)), REGS_FS((r)->skas.regs))
+ __CHOOSE_MODE(SC_FS(UPT_SC(r)), REGS_FS((r)->skas.regs))
#define UPT_GS(r) \
- CHOOSE_MODE(SC_GS(UPT_SC(r)), REGS_GS((r)->skas.regs))
+ __CHOOSE_MODE(SC_GS(UPT_SC(r)), REGS_GS((r)->skas.regs))
#define UPT_SYSCALL_ARG1(r) UPT_EBX(r)
#define UPT_SYSCALL_ARG2(r) UPT_ECX(r)
@@ -218,7 +222,7 @@ struct syscall_args {
REGS_SEGV_IS_FIXABLE(&r->skas))
#define UPT_FAULT_ADDR(r) \
- CHOOSE_MODE(SC_FAULT_ADDR(UPT_SC(r)), REGS_FAULT_ADDR(&r->skas))
+ __CHOOSE_MODE(SC_FAULT_ADDR(UPT_SC(r)), REGS_FAULT_ADDR(&r->skas))
#define UPT_FAULT_WRITE(r) \
CHOOSE_MODE(SC_FAULT_WRITE(UPT_SC(r)), REGS_FAULT_WRITE(&r->skas))
diff --git a/arch/um/include/sysdep-i386/ptrace_user.h b/arch/um/include/sysdep-i386/ptrace_user.h
index 271d9d79422af..eca8066e7a43b 100644
--- a/arch/um/include/sysdep-i386/ptrace_user.h
+++ b/arch/um/include/sysdep-i386/ptrace_user.h
@@ -6,6 +6,8 @@
#ifndef __SYSDEP_I386_PTRACE_USER_H__
#define __SYSDEP_I386_PTRACE_USER_H__
+#include <sys/ptrace.h>
+#include <linux/ptrace.h>
#include <asm/ptrace.h>
#define PT_OFFSET(r) ((r) * sizeof(long))
@@ -33,9 +35,6 @@
#define FP_FRAME_SIZE (27)
#define FPX_FRAME_SIZE (128)
-#define MAX_REG_OFFSET (FRAME_SIZE_OFFSET)
-#define MAX_REG_NR (FRAME_SIZE)
-
#ifdef PTRACE_GETREGS
#define UM_HAVE_GETREGS
#endif
@@ -60,6 +59,4 @@
#define UM_HAVE_SETFPXREGS
#endif
-extern void update_debugregs(int seq);
-
#endif
diff --git a/arch/um/include/sysdep-i386/sigcontext.h b/arch/um/include/sysdep-i386/sigcontext.h
index 887fdb61ed77c..dfee589de3608 100644
--- a/arch/um/include/sysdep-i386/sigcontext.h
+++ b/arch/um/include/sysdep-i386/sigcontext.h
@@ -6,7 +6,7 @@
#ifndef __SYS_SIGCONTEXT_I386_H
#define __SYS_SIGCONTEXT_I386_H
-#include "sc.h"
+#include <sysdep/sc.h>
#define IP_RESTART_SYSCALL(ip) ((ip) -= 2)
diff --git a/arch/um/include/sysdep-i386/syscalls.h b/arch/um/include/sysdep-i386/syscalls.h
index 36d9beec431b8..5db81ec9087d2 100644
--- a/arch/um/include/sysdep-i386/syscalls.h
+++ b/arch/um/include/sysdep-i386/syscalls.h
@@ -23,6 +23,9 @@ extern long sys_mmap2(unsigned long addr, unsigned long len,
unsigned long prot, unsigned long flags,
unsigned long fd, unsigned long pgoff);
+/* On i386 they choose a meaningless naming.*/
+#define __NR_kexec_load __NR_sys_kexec_load
+
#define ARCH_SYSCALLS \
[ __NR_waitpid ] = (syscall_handler_t *) sys_waitpid, \
[ __NR_break ] = (syscall_handler_t *) sys_ni_syscall, \
@@ -74,7 +77,7 @@ extern long sys_mmap2(unsigned long addr, unsigned long len,
[ __NR_fadvise64_64 ] = (syscall_handler_t *) sys_fadvise64_64, \
[ __NR_select ] = (syscall_handler_t *) old_select, \
[ __NR_vm86old ] = (syscall_handler_t *) sys_ni_syscall, \
- [ __NR_modify_ldt ] = (syscall_handler_t *) sys_modify_ldt, \
+ [ __NR_modify_ldt ] = (syscall_handler_t *) sys_modify_ldt, \
[ __NR_lchown32 ] = (syscall_handler_t *) sys_lchown, \
[ __NR_getuid32 ] = (syscall_handler_t *) sys_getuid, \
[ __NR_getgid32 ] = (syscall_handler_t *) sys_getgid, \
@@ -97,19 +100,16 @@ extern long sys_mmap2(unsigned long addr, unsigned long len,
[ __NR_pivot_root ] = (syscall_handler_t *) sys_pivot_root, \
[ __NR_mincore ] = (syscall_handler_t *) sys_mincore, \
[ __NR_madvise ] = (syscall_handler_t *) sys_madvise, \
- [ 222 ] = (syscall_handler_t *) sys_ni_syscall, \
+ [ 222 ] = (syscall_handler_t *) sys_ni_syscall, \
[ 223 ] = (syscall_handler_t *) sys_ni_syscall, \
[ __NR_set_thread_area ] = (syscall_handler_t *) sys_ni_syscall, \
[ __NR_get_thread_area ] = (syscall_handler_t *) sys_ni_syscall, \
- [ __NR_fadvise64 ] = (syscall_handler_t *) sys_fadvise64, \
[ 251 ] = (syscall_handler_t *) sys_ni_syscall, \
- [ __NR_remap_file_pages ] = (syscall_handler_t *) sys_remap_file_pages, \
- [ __NR_utimes ] = (syscall_handler_t *) sys_utimes, \
- [ __NR_vserver ] = (syscall_handler_t *) sys_ni_syscall,
-
+ [ 285 ] = (syscall_handler_t *) sys_ni_syscall,
+
/* 222 doesn't yet have a name in include/asm-i386/unistd.h */
-#define LAST_ARCH_SYSCALL __NR_vserver
+#define LAST_ARCH_SYSCALL 285
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
diff --git a/arch/um/include/sysdep-x86_64/checksum.h b/arch/um/include/sysdep-x86_64/checksum.h
index d57aa7f3130ea..572c6c19be33b 100644
--- a/arch/um/include/sysdep-x86_64/checksum.h
+++ b/arch/um/include/sysdep-x86_64/checksum.h
@@ -9,7 +9,7 @@
#include "linux/in6.h"
#include "asm/uaccess.h"
-extern unsigned int csum_partial_copy_from(const char *src, char *dst, int len,
+extern unsigned int csum_partial_copy_from(const unsigned char *src, unsigned char *dst, int len,
int sum, int *err_ptr);
extern unsigned csum_partial(const unsigned char *buff, unsigned len,
unsigned sum);
@@ -19,11 +19,11 @@ extern unsigned csum_partial(const unsigned char *buff, unsigned len,
* passed in an incorrect kernel address to one of these functions.
*
* If you use these functions directly please don't forget the
- * verify_area().
+ * access_ok().
*/
static __inline__
-unsigned int csum_partial_copy_nocheck(const char *src, char *dst,
+unsigned int csum_partial_copy_nocheck(const unsigned char *src, unsigned char *dst,
int len, int sum)
{
memcpy(dst, src, len);
@@ -31,7 +31,7 @@ unsigned int csum_partial_copy_nocheck(const char *src, char *dst,
}
static __inline__
-unsigned int csum_partial_copy_from_user(const char *src, char *dst,
+unsigned int csum_partial_copy_from_user(const unsigned char *src, unsigned char *dst,
int len, int sum, int *err_ptr)
{
return csum_partial_copy_from(src, dst, len, sum, err_ptr);
diff --git a/arch/um/include/sysdep-x86_64/ptrace.h b/arch/um/include/sysdep-x86_64/ptrace.h
index 64b1cc16752df..915c82daffbd6 100644
--- a/arch/um/include/sysdep-x86_64/ptrace.h
+++ b/arch/um/include/sysdep-x86_64/ptrace.h
@@ -8,6 +8,10 @@
#define __SYSDEP_X86_64_PTRACE_H
#include "uml-config.h"
+#include "user_constants.h"
+
+#define MAX_REG_OFFSET (UM_FRAME_SIZE)
+#define MAX_REG_NR ((MAX_REG_OFFSET) / sizeof(unsigned long))
#ifdef UML_CONFIG_MODE_TT
#include "sysdep/sc.h"
@@ -100,37 +104,37 @@ union uml_pt_regs {
/* XXX */
extern int mode_tt;
-#define UPT_RBX(r) CHOOSE_MODE(SC_RBX(UPT_SC(r)), REGS_RBX((r)->skas.regs))
-#define UPT_RCX(r) CHOOSE_MODE(SC_RCX(UPT_SC(r)), REGS_RCX((r)->skas.regs))
-#define UPT_RDX(r) CHOOSE_MODE(SC_RDX(UPT_SC(r)), REGS_RDX((r)->skas.regs))
-#define UPT_RSI(r) CHOOSE_MODE(SC_RSI(UPT_SC(r)), REGS_RSI((r)->skas.regs))
-#define UPT_RDI(r) CHOOSE_MODE(SC_RDI(UPT_SC(r)), REGS_RDI((r)->skas.regs))
-#define UPT_RBP(r) CHOOSE_MODE(SC_RBP(UPT_SC(r)), REGS_RBP((r)->skas.regs))
-#define UPT_RAX(r) CHOOSE_MODE(SC_RAX(UPT_SC(r)), REGS_RAX((r)->skas.regs))
-#define UPT_R8(r) CHOOSE_MODE(SC_R8(UPT_SC(r)), REGS_R8((r)->skas.regs))
-#define UPT_R9(r) CHOOSE_MODE(SC_R9(UPT_SC(r)), REGS_R9((r)->skas.regs))
-#define UPT_R10(r) CHOOSE_MODE(SC_R10(UPT_SC(r)), REGS_R10((r)->skas.regs))
-#define UPT_R11(r) CHOOSE_MODE(SC_R11(UPT_SC(r)), REGS_R11((r)->skas.regs))
-#define UPT_R12(r) CHOOSE_MODE(SC_R12(UPT_SC(r)), REGS_R12((r)->skas.regs))
-#define UPT_R13(r) CHOOSE_MODE(SC_R13(UPT_SC(r)), REGS_R13((r)->skas.regs))
-#define UPT_R14(r) CHOOSE_MODE(SC_R14(UPT_SC(r)), REGS_R14((r)->skas.regs))
-#define UPT_R15(r) CHOOSE_MODE(SC_R15(UPT_SC(r)), REGS_R15((r)->skas.regs))
-#define UPT_CS(r) CHOOSE_MODE(SC_CS(UPT_SC(r)), REGS_CS((r)->skas.regs))
-#define UPT_FS(r) CHOOSE_MODE(SC_FS(UPT_SC(r)), REGS_FS((r)->skas.regs))
-#define UPT_GS(r) CHOOSE_MODE(SC_GS(UPT_SC(r)), REGS_GS((r)->skas.regs))
-#define UPT_DS(r) CHOOSE_MODE(SC_DS(UPT_SC(r)), REGS_DS((r)->skas.regs))
-#define UPT_ES(r) CHOOSE_MODE(SC_ES(UPT_SC(r)), REGS_ES((r)->skas.regs))
-#define UPT_CS(r) CHOOSE_MODE(SC_CS(UPT_SC(r)), REGS_CS((r)->skas.regs))
+#define UPT_RBX(r) __CHOOSE_MODE(SC_RBX(UPT_SC(r)), REGS_RBX((r)->skas.regs))
+#define UPT_RCX(r) __CHOOSE_MODE(SC_RCX(UPT_SC(r)), REGS_RCX((r)->skas.regs))
+#define UPT_RDX(r) __CHOOSE_MODE(SC_RDX(UPT_SC(r)), REGS_RDX((r)->skas.regs))
+#define UPT_RSI(r) __CHOOSE_MODE(SC_RSI(UPT_SC(r)), REGS_RSI((r)->skas.regs))
+#define UPT_RDI(r) __CHOOSE_MODE(SC_RDI(UPT_SC(r)), REGS_RDI((r)->skas.regs))
+#define UPT_RBP(r) __CHOOSE_MODE(SC_RBP(UPT_SC(r)), REGS_RBP((r)->skas.regs))
+#define UPT_RAX(r) __CHOOSE_MODE(SC_RAX(UPT_SC(r)), REGS_RAX((r)->skas.regs))
+#define UPT_R8(r) __CHOOSE_MODE(SC_R8(UPT_SC(r)), REGS_R8((r)->skas.regs))
+#define UPT_R9(r) __CHOOSE_MODE(SC_R9(UPT_SC(r)), REGS_R9((r)->skas.regs))
+#define UPT_R10(r) __CHOOSE_MODE(SC_R10(UPT_SC(r)), REGS_R10((r)->skas.regs))
+#define UPT_R11(r) __CHOOSE_MODE(SC_R11(UPT_SC(r)), REGS_R11((r)->skas.regs))
+#define UPT_R12(r) __CHOOSE_MODE(SC_R12(UPT_SC(r)), REGS_R12((r)->skas.regs))
+#define UPT_R13(r) __CHOOSE_MODE(SC_R13(UPT_SC(r)), REGS_R13((r)->skas.regs))
+#define UPT_R14(r) __CHOOSE_MODE(SC_R14(UPT_SC(r)), REGS_R14((r)->skas.regs))
+#define UPT_R15(r) __CHOOSE_MODE(SC_R15(UPT_SC(r)), REGS_R15((r)->skas.regs))
+#define UPT_CS(r) __CHOOSE_MODE(SC_CS(UPT_SC(r)), REGS_CS((r)->skas.regs))
+#define UPT_FS(r) __CHOOSE_MODE(SC_FS(UPT_SC(r)), REGS_FS((r)->skas.regs))
+#define UPT_GS(r) __CHOOSE_MODE(SC_GS(UPT_SC(r)), REGS_GS((r)->skas.regs))
+#define UPT_DS(r) __CHOOSE_MODE(SC_DS(UPT_SC(r)), REGS_DS((r)->skas.regs))
+#define UPT_ES(r) __CHOOSE_MODE(SC_ES(UPT_SC(r)), REGS_ES((r)->skas.regs))
+#define UPT_CS(r) __CHOOSE_MODE(SC_CS(UPT_SC(r)), REGS_CS((r)->skas.regs))
#define UPT_ORIG_RAX(r) \
- CHOOSE_MODE((r)->tt.orig_rax, REGS_ORIG_RAX((r)->skas.regs))
+ __CHOOSE_MODE((r)->tt.orig_rax, REGS_ORIG_RAX((r)->skas.regs))
-#define UPT_IP(r) CHOOSE_MODE(SC_IP(UPT_SC(r)), REGS_IP((r)->skas.regs))
-#define UPT_SP(r) CHOOSE_MODE(SC_SP(UPT_SC(r)), REGS_SP((r)->skas.regs))
+#define UPT_IP(r) __CHOOSE_MODE(SC_IP(UPT_SC(r)), REGS_IP((r)->skas.regs))
+#define UPT_SP(r) __CHOOSE_MODE(SC_SP(UPT_SC(r)), REGS_SP((r)->skas.regs))
#define UPT_EFLAGS(r) \
- CHOOSE_MODE(SC_EFLAGS(UPT_SC(r)), REGS_EFLAGS((r)->skas.regs))
+ __CHOOSE_MODE(SC_EFLAGS(UPT_SC(r)), REGS_EFLAGS((r)->skas.regs))
#define UPT_SC(r) ((r)->tt.sc)
-#define UPT_SYSCALL_NR(r) CHOOSE_MODE((r)->tt.syscall, (r)->skas.syscall)
+#define UPT_SYSCALL_NR(r) __CHOOSE_MODE((r)->tt.syscall, (r)->skas.syscall)
extern int user_context(unsigned long sp);
@@ -238,13 +242,13 @@ struct syscall_args {
REGS_SEGV_IS_FIXABLE(&r->skas))
#define UPT_FAULT_ADDR(r) \
- CHOOSE_MODE(SC_FAULT_ADDR(UPT_SC(r)), REGS_FAULT_ADDR(&r->skas))
+ __CHOOSE_MODE(SC_FAULT_ADDR(UPT_SC(r)), REGS_FAULT_ADDR(&r->skas))
#define UPT_FAULT_WRITE(r) \
CHOOSE_MODE(SC_FAULT_WRITE(UPT_SC(r)), REGS_FAULT_WRITE(&r->skas))
-#define UPT_TRAP(r) CHOOSE_MODE(SC_TRAP_TYPE(UPT_SC(r)), REGS_TRAP(&r->skas))
-#define UPT_ERR(r) CHOOSE_MODE(SC_FAULT_TYPE(UPT_SC(r)), REGS_ERR(&r->skas))
+#define UPT_TRAP(r) __CHOOSE_MODE(SC_TRAP_TYPE(UPT_SC(r)), REGS_TRAP(&r->skas))
+#define UPT_ERR(r) __CHOOSE_MODE(SC_FAULT_TYPE(UPT_SC(r)), REGS_ERR(&r->skas))
#endif
diff --git a/arch/um/include/sysdep-x86_64/ptrace_user.h b/arch/um/include/sysdep-x86_64/ptrace_user.h
index 24cb4ee521be8..31729973fb14d 100644
--- a/arch/um/include/sysdep-x86_64/ptrace_user.h
+++ b/arch/um/include/sysdep-x86_64/ptrace_user.h
@@ -8,6 +8,8 @@
#define __SYSDEP_X86_64_PTRACE_USER_H__
#define __FRAME_OFFSETS
+#include <sys/ptrace.h>
+#include <linux/ptrace.h>
#include <asm/ptrace.h>
#undef __FRAME_OFFSETS
@@ -45,9 +47,6 @@
#define PT_ORIG_RAX_OFFSET (ORIG_RAX)
#define PT_ORIG_RAX(regs) ((regs)[PT_INDEX(ORIG_RAX)])
-#define MAX_REG_OFFSET (FRAME_SIZE)
-#define MAX_REG_NR ((MAX_REG_OFFSET) / sizeof(unsigned long))
-
/* x86_64 FC3 doesn't define this in /usr/include/linux/ptrace.h even though
* it's defined in the kernel's include/linux/ptrace.h. Additionally, use the
* 2.4 name and value for 2.4 host compatibility.
diff --git a/arch/um/include/sysdep-x86_64/sigcontext.h b/arch/um/include/sysdep-x86_64/sigcontext.h
index 6a0c346b64040..1e38a54ff4cf3 100644
--- a/arch/um/include/sysdep-x86_64/sigcontext.h
+++ b/arch/um/include/sysdep-x86_64/sigcontext.h
@@ -7,7 +7,7 @@
#ifndef __SYSDEP_X86_64_SIGCONTEXT_H
#define __SYSDEP_X86_64_SIGCONTEXT_H
-#include "sc.h"
+#include <sysdep/sc.h>
#define IP_RESTART_SYSCALL(ip) ((ip) -= 2)
diff --git a/arch/um/include/sysdep-x86_64/syscalls.h b/arch/um/include/sysdep-x86_64/syscalls.h
index 65fd494420f99..b187a4157ff36 100644
--- a/arch/um/include/sysdep-x86_64/syscalls.h
+++ b/arch/um/include/sysdep-x86_64/syscalls.h
@@ -71,12 +71,7 @@ extern syscall_handler_t sys_arch_prctl;
[ __NR_iopl ] = (syscall_handler_t *) sys_ni_syscall, \
[ __NR_set_thread_area ] = (syscall_handler_t *) sys_ni_syscall, \
[ __NR_get_thread_area ] = (syscall_handler_t *) sys_ni_syscall, \
- [ __NR_remap_file_pages ] = (syscall_handler_t *) sys_remap_file_pages, \
[ __NR_semtimedop ] = (syscall_handler_t *) sys_semtimedop, \
- [ __NR_fadvise64 ] = (syscall_handler_t *) sys_fadvise64, \
- [ 223 ] = (syscall_handler_t *) sys_ni_syscall, \
- [ __NR_utimes ] = (syscall_handler_t *) sys_utimes, \
- [ __NR_vserver ] = (syscall_handler_t *) sys_ni_syscall, \
[ 251 ] = (syscall_handler_t *) sys_ni_syscall,
#define LAST_ARCH_SYSCALL 251
diff --git a/arch/um/include/tlb.h b/arch/um/include/tlb.h
index ba230d8adf5c8..da1097285b8ca 100644
--- a/arch/um/include/tlb.h
+++ b/arch/um/include/tlb.h
@@ -6,9 +6,53 @@
#ifndef __TLB_H__
#define __TLB_H__
+#include "um_mmu.h"
+
+struct host_vm_op {
+ enum { MMAP, MUNMAP, MPROTECT } type;
+ union {
+ struct {
+ unsigned long addr;
+ unsigned long len;
+ unsigned int r:1;
+ unsigned int w:1;
+ unsigned int x:1;
+ int fd;
+ __u64 offset;
+ } mmap;
+ struct {
+ unsigned long addr;
+ unsigned long len;
+ } munmap;
+ struct {
+ unsigned long addr;
+ unsigned long len;
+ unsigned int r:1;
+ unsigned int w:1;
+ unsigned int x:1;
+ } mprotect;
+ } u;
+};
+
extern void mprotect_kernel_vm(int w);
extern void force_flush_all(void);
+extern void fix_range_common(struct mm_struct *mm, unsigned long start_addr,
+ unsigned long end_addr, int force, int data,
+ void (*do_ops)(int, struct host_vm_op *, int));
+extern int flush_tlb_kernel_range_common(unsigned long start,
+ unsigned long end);
+extern int add_mmap(unsigned long virt, unsigned long phys, unsigned long len,
+ int r, int w, int x, struct host_vm_op *ops, int index,
+ int last_filled, int data,
+ void (*do_ops)(int, struct host_vm_op *, int));
+extern int add_munmap(unsigned long addr, unsigned long len,
+ struct host_vm_op *ops, int index, int last_filled,
+ int data, void (*do_ops)(int, struct host_vm_op *, int));
+extern int add_mprotect(unsigned long addr, unsigned long len, int r, int w,
+ int x, struct host_vm_op *ops, int index,
+ int last_filled, int data,
+ void (*do_ops)(int, struct host_vm_op *, int));
#endif
/*
diff --git a/arch/um/include/um_mmu.h b/arch/um/include/um_mmu.h
index 5243f455fc3a7..0fa6432383002 100644
--- a/arch/um/include/um_mmu.h
+++ b/arch/um/include/um_mmu.h
@@ -6,22 +6,22 @@
#ifndef __ARCH_UM_MMU_H
#define __ARCH_UM_MMU_H
-#include "linux/config.h"
+#include "uml-config.h"
#include "choose-mode.h"
-#ifdef CONFIG_MODE_TT
+#ifdef UML_CONFIG_MODE_TT
#include "mmu-tt.h"
#endif
-#ifdef CONFIG_MODE_SKAS
+#ifdef UML_CONFIG_MODE_SKAS
#include "mmu-skas.h"
#endif
-typedef union {
-#ifdef CONFIG_MODE_TT
+typedef union mm_context {
+#ifdef UML_CONFIG_MODE_TT
struct mmu_context_tt tt;
#endif
-#ifdef CONFIG_MODE_SKAS
+#ifdef UML_CONFIG_MODE_SKAS
struct mmu_context_skas skas;
#endif
} mm_context_t;
diff --git a/arch/um/include/um_uaccess.h b/arch/um/include/um_uaccess.h
index 4eb302cbf8650..6e348cb6de24a 100644
--- a/arch/um/include/um_uaccess.h
+++ b/arch/um/include/um_uaccess.h
@@ -20,7 +20,8 @@
#define access_ok(type, addr, size) \
CHOOSE_MODE_PROC(access_ok_tt, access_ok_skas, type, addr, size)
-static inline int verify_area(int type, const void __user *addr, unsigned long size)
+/* this function will go away soon - use access_ok() instead */
+static inline int __deprecated verify_area(int type, const void __user *addr, unsigned long size)
{
return (CHOOSE_MODE_PROC(verify_area_tt, verify_area_skas, type, addr,
size));
diff --git a/arch/um/include/user_util.h b/arch/um/include/user_util.h
index 4fc088eb73fa8..103cd320386cf 100644
--- a/arch/um/include/user_util.h
+++ b/arch/um/include/user_util.h
@@ -67,7 +67,7 @@ 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 add_arg(char *cmd_line, char *arg);
+extern void add_arg(char *arg);
extern void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int));
extern void init_new_thread_signals(int altstack);
extern void do_exec(int old_pid, int new_pid);
diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile
index d3b16f2a426f4..dc796c1bf39ec 100644
--- a/arch/um/kernel/Makefile
+++ b/arch/um/kernel/Makefile
@@ -4,40 +4,55 @@
#
extra-y := vmlinux.lds
-clean-files := vmlinux.lds.S
+clean-files := vmlinux.lds.S config.tmp
obj-y = checksum.o config.o exec_kern.o exitcode.o \
helper.o init_task.o irq.o irq_user.o ksyms.o main.o mem.o mem_user.o \
physmem.o process.o process_kern.o ptrace.o reboot.o resource.o \
sigio_user.o sigio_kern.o signal_kern.o signal_user.o smp.o \
- syscall_kern.o syscall_user.o sysrq.o sys_call_table.o tempfile.o \
- time.o time_kern.o tlb.o trap_kern.o trap_user.o uaccess_user.o \
- um_arch.o umid.o user_util.o
+ syscall_kern.o sysrq.o sys_call_table.o tempfile.o time.o time_kern.o \
+ tlb.o trap_kern.o trap_user.o uaccess_user.o um_arch.o umid.o \
+ user_util.o
obj-$(CONFIG_BLK_DEV_INITRD) += initrd_kern.o initrd_user.o
obj-$(CONFIG_GPROF) += gprof_syms.o
obj-$(CONFIG_GCOV) += gmon_syms.o
obj-$(CONFIG_TTY_LOG) += tty_log.o
+obj-$(CONFIG_SYSCALL_DEBUG) += syscall_user.o
obj-$(CONFIG_MODE_TT) += tt/
obj-$(CONFIG_MODE_SKAS) += skas/
+# This needs be compiled with frame pointers regardless of how the rest of the
+# kernel is built.
+CFLAGS_frame.o := -fno-omit-frame-pointer
+
user-objs-$(CONFIG_TTY_LOG) += tty_log.o
-USER_OBJS := $(filter %_user.o,$(obj-y)) $(user-objs-y) config.o helper.o \
- main.o process.o tempfile.o time.o tty_log.o umid.o user_util.o frame.o
-USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
+USER_OBJS := $(user-objs-y) config.o helper.o main.o process.o tempfile.o \
+ time.o tty_log.o umid.o user_util.o frame.o
-CFLAGS_frame.o := -fno-omit-frame-pointer
+include arch/um/scripts/Makefile.rules
-$(USER_OBJS) : %.o: %.c
- $(CC) $(USER_CFLAGS) $(CFLAGS_$(notdir $@)) -c -o $@ $<
+targets += config.c
-QUOTE = 'my $$config=`cat $(TOPDIR)/.config`; $$config =~ s/"/\\"/g ; $$config =~ s/\n/\\n"\n"/g ; while(<STDIN>) { $$_ =~ s/CONFIG/$$config/; print $$_ }'
+# Be careful with the below Sed code - sed is pitfall-rich!
+# We use sed to lower build requirements, for "embedded" builders for instance.
-quiet_cmd_quote = QUOTE $@
-cmd_quote = $(PERL) -e $(QUOTE) < $< > $@
+$(obj)/config.tmp: $(objtree)/.config FORCE
+ $(call if_changed,quote1)
-targets += config.c
-$(obj)/config.c : $(src)/config.c.in $(TOPDIR)/.config FORCE
- $(call if_changed,quote)
+quiet_cmd_quote1 = QUOTE $@
+ cmd_quote1 = sed -e 's/"/\\"/g' -e 's/^/"/' -e 's/$$/\\n"/' \
+ $< > $@
+
+$(obj)/config.c: $(src)/config.c.in $(obj)/config.tmp FORCE
+ $(call if_changed,quote2)
+
+quiet_cmd_quote2 = QUOTE $@
+ cmd_quote2 = sed -e '/CONFIG/{' \
+ -e 's/"CONFIG"\;/""/' \
+ -e 'r $(obj)/config.tmp' \
+ -e 'a""\;' \
+ -e '}' \
+ $< > $@
diff --git a/arch/um/kernel/checksum.c b/arch/um/kernel/checksum.c
index b2fe269a6cc41..e69b2be951d14 100644
--- a/arch/um/kernel/checksum.c
+++ b/arch/um/kernel/checksum.c
@@ -6,40 +6,31 @@ unsigned int arch_csum_partial(const unsigned char *buff, int len, int sum);
unsigned int csum_partial(unsigned char *buff, int len, int sum)
{
- return arch_csum_partial(buff, len, sum);
+ return arch_csum_partial(buff, len, sum);
}
EXPORT_SYMBOL(csum_partial);
-unsigned int csum_partial_copy_to(const unsigned char *src, char __user *dst,
- int len, int sum, int *err_ptr)
+unsigned int csum_partial_copy_to(const unsigned char *src,
+ unsigned char __user *dst, int len, int sum,
+ int *err_ptr)
{
- if(copy_to_user(dst, src, len)){
- *err_ptr = -EFAULT;
- return(-1);
- }
+ if(copy_to_user(dst, src, len)){
+ *err_ptr = -EFAULT;
+ return(-1);
+ }
- return(arch_csum_partial(src, len, sum));
+ return(arch_csum_partial(src, len, sum));
}
-unsigned int csum_partial_copy_from(const unsigned char __user *src, char *dst,
- int len, int sum, int *err_ptr)
+unsigned int csum_partial_copy_from(const unsigned char __user *src,
+ unsigned char *dst, int len, int sum,
+ int *err_ptr)
{
- if(copy_from_user(dst, src, len)){
- *err_ptr = -EFAULT;
- return(-1);
- }
+ if(copy_from_user(dst, src, len)){
+ *err_ptr = -EFAULT;
+ return(-1);
+ }
- return arch_csum_partial(dst, len, sum);
+ return arch_csum_partial(dst, len, sum);
}
-
-/*
- * 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/gmon_syms.c b/arch/um/kernel/gmon_syms.c
index 6179f0183d2ff..2c86e7fdb0143 100644
--- a/arch/um/kernel/gmon_syms.c
+++ b/arch/um/kernel/gmon_syms.c
@@ -8,6 +8,20 @@
extern void __bb_init_func(void *);
EXPORT_SYMBOL(__bb_init_func);
+/* This is defined (and referred to in profiling stub code) only by some GCC
+ * versions in libgcov.
+ *
+ * Since SuSE backported the fix, we cannot handle it depending on GCC version.
+ * So, unconditinally export it. But also give it a weak declaration, which will
+ * be overriden by any other one.
+ */
+
+extern void __gcov_init(void *) __attribute__((weak));
+EXPORT_SYMBOL(__gcov_init);
+
+extern void __gcov_merge_add(void *) __attribute__((weak));
+EXPORT_SYMBOL(__gcov_merge_add);
+
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically
diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c
index 7a69ef0aebbd4..f156661781cb1 100644
--- a/arch/um/kernel/mem.c
+++ b/arch/um/kernel/mem.c
@@ -138,7 +138,7 @@ pgprot_t kmap_prot;
pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k(vaddr), (vaddr)),\
(vaddr)), (vaddr))
-void __init kmap_init(void)
+static void __init kmap_init(void)
{
unsigned long kmap_vstart;
diff --git a/arch/um/kernel/physmem.c b/arch/um/kernel/physmem.c
index 2853028657b36..420e6d51fa0f2 100644
--- a/arch/um/kernel/physmem.c
+++ b/arch/um/kernel/physmem.c
@@ -294,7 +294,6 @@ int init_maps(unsigned long physmem, unsigned long iomem, unsigned long highmem)
INIT_LIST_HEAD(&p->lru);
}
- mem_map = map;
max_mapnr = total_pages;
return(0);
}
diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c
index 7a2be31a97662..f76a2692adcae 100644
--- a/arch/um/kernel/process.c
+++ b/arch/um/kernel/process.c
@@ -12,11 +12,6 @@
#include <stdlib.h>
#include <setjmp.h>
#include <sys/time.h>
-#include <sys/ptrace.h>
-
-/*Userspace header, must be after sys/ptrace.h, and both must be included. */
-#include <linux/ptrace.h>
-
#include <sys/wait.h>
#include <sys/mman.h>
#include <asm/unistd.h>
@@ -28,7 +23,6 @@
#include "signal_kern.h"
#include "signal_user.h"
#include "sysdep/ptrace.h"
-#include "sysdep/ptrace_user.h"
#include "sysdep/sigcontext.h"
#include "irq_user.h"
#include "ptrace_user.h"
@@ -36,6 +30,7 @@
#include "init.h"
#include "os.h"
#include "uml-config.h"
+#include "ptrace_user.h"
#include "choose-mode.h"
#include "mode.h"
#ifdef UML_CONFIG_MODE_SKAS
@@ -259,7 +254,7 @@ static void __init check_sysemu(void)
panic("check_sysemu : expected SIGTRAP, "
"got status = %d", status);
- n = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_RET_OFFSET,
+ n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET,
os_getpid());
if(n < 0)
panic("check_sysemu : failed to modify system "
@@ -285,12 +280,12 @@ static void __init check_sysemu(void)
panic("check_ptrace : expected (SIGTRAP|SYSCALL_TRAP), "
"got status = %d", status);
- syscall = ptrace(PTRACE_PEEKUSER, pid, PT_SYSCALL_NR_OFFSET,
+ syscall = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_NR_OFFSET,
0);
if(syscall == __NR_getpid){
if (!count)
panic("check_ptrace : SYSEMU_SINGLESTEP doesn't singlestep");
- n = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_RET_OFFSET,
+ n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET,
os_getpid());
if(n < 0)
panic("check_sysemu : failed to modify system "
@@ -336,10 +331,10 @@ void __init check_ptrace(void)
panic("check_ptrace : expected SIGTRAP + 0x80, "
"got status = %d", status);
- syscall = ptrace(PTRACE_PEEKUSER, pid, PT_SYSCALL_NR_OFFSET,
+ syscall = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_NR_OFFSET,
0);
if(syscall == __NR_getpid){
- n = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET,
+ n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET,
__NR_getppid);
if(n < 0)
panic("check_ptrace : failed to modify system "
diff --git a/arch/um/kernel/process_kern.c b/arch/um/kernel/process_kern.c
index 8d003f351eb38..1d719d5b4bb95 100644
--- a/arch/um/kernel/process_kern.c
+++ b/arch/um/kernel/process_kern.c
@@ -21,6 +21,7 @@
#include "linux/spinlock.h"
#include "linux/proc_fs.h"
#include "linux/ptrace.h"
+#include "linux/random.h"
#include "asm/unistd.h"
#include "asm/mman.h"
#include "asm/segment.h"
@@ -479,6 +480,14 @@ int singlestepping(void * t)
return 2;
}
+unsigned long arch_align_stack(unsigned long sp)
+{
+ if (randomize_va_space)
+ sp -= get_random_int() % 8192;
+ return sp & ~0xf;
+}
+
+
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically
diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c
index a926d8a920d05..3a99ee6d94eb7 100644
--- a/arch/um/kernel/ptrace.c
+++ b/arch/um/kernel/ptrace.c
@@ -9,14 +9,15 @@
#include "linux/smp_lock.h"
#include "linux/security.h"
#include "linux/ptrace.h"
+#include "linux/audit.h"
#ifdef CONFIG_PROC_MM
#include "linux/proc_mm.h"
#endif
#include "asm/ptrace.h"
#include "asm/uaccess.h"
#include "kern_util.h"
-#include "ptrace_user.h"
#include "skas_ptrace.h"
+#include "sysdep/ptrace.h"
/*
* Called by kernel/ptrace.c when detaching..
@@ -336,11 +337,15 @@ void syscall_trace(union uml_pt_regs *regs, int entryexit)
if (unlikely(current->audit_context)) {
if (!entryexit)
- audit_syscall_entry(current, regs->orig_eax,
- regs->ebx, regs->ecx,
- regs->edx, regs->esi);
+ audit_syscall_entry(current,
+ UPT_SYSCALL_NR(&regs->regs),
+ UPT_SYSCALL_ARG1(&regs->regs),
+ UPT_SYSCALL_ARG2(&regs->regs),
+ UPT_SYSCALL_ARG3(&regs->regs),
+ UPT_SYSCALL_ARG4(&regs->regs));
else
- audit_syscall_exit(current, regs->eax);
+ audit_syscall_exit(current,
+ UPT_SYSCALL_RET(&regs->regs));
}
/* Fake a debug trap */
diff --git a/arch/um/kernel/sigio_user.c b/arch/um/kernel/sigio_user.c
index 82d19b451d5ea..668df13d8c9d6 100644
--- a/arch/um/kernel/sigio_user.c
+++ b/arch/um/kernel/sigio_user.c
@@ -108,12 +108,14 @@ static void tty_output(int master, int slave)
panic("check_sigio : write failed, errno = %d\n", errno);
while(((n = os_read_file(slave, buf, sizeof(buf))) > 0) && !got_sigio) ;
- if(got_sigio){
+ if (got_sigio) {
printk("Yes\n");
pty_output_sigio = 1;
+ } else if (n == -EAGAIN) {
+ printk("No, enabling workaround\n");
+ } else {
+ panic("check_sigio : read failed, err = %d\n", n);
}
- else if(n == -EAGAIN) printk("No, enabling workaround\n");
- else panic("check_sigio : read failed, err = %d\n", n);
}
static void tty_close(int master, int slave)
@@ -235,6 +237,8 @@ static int need_poll(int n)
return(0);
}
+/* Must be called with sigio_lock held, because it's needed by the marked
+ * critical section. */
static void update_thread(void)
{
unsigned long flags;
@@ -257,7 +261,7 @@ static void update_thread(void)
set_signals(flags);
return;
fail:
- sigio_lock();
+ /* Critical section start */
if(write_sigio_pid != -1)
os_kill_process(write_sigio_pid, 1);
write_sigio_pid = -1;
@@ -265,7 +269,7 @@ static void update_thread(void)
os_close_file(sigio_private[1]);
os_close_file(write_sigio_fds[0]);
os_close_file(write_sigio_fds[1]);
- sigio_unlock();
+ /* Critical section end */
set_signals(flags);
}
@@ -418,19 +422,10 @@ int read_sigio_fd(int fd)
static void sigio_cleanup(void)
{
- if(write_sigio_pid != -1)
+ if (write_sigio_pid != -1) {
os_kill_process(write_sigio_pid, 1);
+ write_sigio_pid = -1;
+ }
}
__uml_exitcall(sigio_cleanup);
-
-/*
- * 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 867dff0729342..d37d1bfcd6f73 100644
--- a/arch/um/kernel/skas/Makefile
+++ b/arch/um/kernel/skas/Makefile
@@ -6,10 +6,8 @@
obj-y := exec_kern.o mem.o mem_user.o mmu.o process.o process_kern.o \
syscall_kern.o syscall_user.o time.o tlb.o trap_user.o uaccess.o \
-USER_OBJS = $(filter %_user.o,$(obj-y)) process.o time.o
-USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
+subdir- := util
-$(USER_OBJS) : %.o: %.c
- $(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
+USER_OBJS := process.o time.o
-subdir- := util
+include arch/um/scripts/Makefile.rules
diff --git a/arch/um/kernel/skas/include/skas.h b/arch/um/kernel/skas/include/skas.h
index 1c7fcd3effc20..f0702c2c72042 100644
--- a/arch/um/kernel/skas/include/skas.h
+++ b/arch/um/kernel/skas/include/skas.h
@@ -22,14 +22,15 @@ 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 void map(int fd, unsigned long virt, unsigned long phys,
- unsigned long len, int r, int w, int x);
-extern int unmap(int fd, void *addr, int len);
+extern void map(int fd, unsigned long virt, unsigned long len, int r, int w,
+ int x, int phys_fd, unsigned long long offset);
+extern int unmap(int fd, void *addr, unsigned long len);
extern int protect(int fd, unsigned long addr, unsigned long len,
- int r, int w, int x, int must_succeed);
+ int r, int w, int x);
extern void user_signal(int sig, union uml_pt_regs *regs);
extern int new_mm(int from);
extern void start_userspace(int cpu);
+extern long execute_syscall_skas(void *r);
#endif
diff --git a/arch/um/kernel/skas/mem_user.c b/arch/um/kernel/skas/mem_user.c
index cfcfa0d60dfbd..1310bf1e88d18 100644
--- a/arch/um/kernel/skas/mem_user.c
+++ b/arch/um/kernel/skas/mem_user.c
@@ -5,23 +5,20 @@
#include <errno.h>
#include <sys/mman.h>
-#include <sys/ptrace.h>
#include "mem_user.h"
#include "mem.h"
#include "user.h"
#include "os.h"
#include "proc_mm.h"
-void map(int fd, unsigned long virt, unsigned long phys, unsigned long len,
- int r, int w, int x)
+void map(int fd, unsigned long virt, unsigned long len, int r, int w,
+ int x, int phys_fd, unsigned long long offset)
{
struct proc_mm_op map;
- __u64 offset;
- int prot, n, phys_fd;
+ int prot, n;
prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) |
(x ? PROT_EXEC : 0);
- phys_fd = phys_mapping(phys, &offset);
map = ((struct proc_mm_op) { .op = MM_MMAP,
.u =
@@ -39,7 +36,7 @@ void map(int fd, unsigned long virt, unsigned long phys, unsigned long len,
printk("map : /proc/mm map failed, err = %d\n", -n);
}
-int unmap(int fd, void *addr, int len)
+int unmap(int fd, void *addr, unsigned long len)
{
struct proc_mm_op unmap;
int n;
diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c
index db53368ec51a2..b4ffaaa81241d 100644
--- a/arch/um/kernel/skas/process.c
+++ b/arch/um/kernel/skas/process.c
@@ -10,8 +10,6 @@
#include <setjmp.h>
#include <sched.h>
#include <sys/wait.h>
-#include <sys/ptrace.h>
-#include <linux/ptrace.h>
#include <sys/mman.h>
#include <sys/user.h>
#include <asm/unistd.h>
@@ -62,7 +60,7 @@ static void handle_trap(int pid, union uml_pt_regs *regs, int local_using_sysemu
if (!local_using_sysemu)
{
- err = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET, __NR_getpid);
+ err = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET, __NR_getpid);
if(err < 0)
panic("handle_trap - nullifying syscall failed errno = %d\n",
errno);
@@ -139,17 +137,20 @@ 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.*/
- restore_registers(pid, regs);
-
- local_using_sysemu = get_using_sysemu();
+ while(1){
+ restore_registers(pid, regs);
- op = local_using_sysemu ? PTRACE_SYSEMU : PTRACE_SYSCALL;
- err = ptrace(op, pid, 0, 0);
+ /* 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);
- if(err)
- panic("userspace - PTRACE_%s failed, errno = %d\n",
- local_using_sysemu ? "SYSEMU" : "SYSCALL", errno);
- while(1){
CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED));
if(err < 0)
panic("userspace - waitpid failed, errno = %d\n",
@@ -187,19 +188,6 @@ void userspace(union uml_pt_regs *regs)
/* Avoid -ERESTARTSYS handling in host */
PT_SYSCALL_NR(regs->skas.regs) = -1;
}
-
- restore_registers(pid, regs);
-
- /*Now we ended the syscall, so re-read local_using_sysemu.*/
- 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 - PTRACE_%s failed, "
- "errno = %d\n",
- local_using_sysemu ? "SYSEMU" : "SYSCALL", errno);
}
}
diff --git a/arch/um/kernel/skas/syscall_user.c b/arch/um/kernel/skas/syscall_user.c
index b7fd594ebb1fc..2828e6e37721a 100644
--- a/arch/um/kernel/skas/syscall_user.c
+++ b/arch/um/kernel/skas/syscall_user.c
@@ -6,25 +6,30 @@
#include <stdlib.h>
#include <signal.h>
#include "kern_util.h"
+#include "uml-config.h"
#include "syscall_user.h"
#include "sysdep/ptrace.h"
#include "sysdep/sigcontext.h"
-
+#include "skas.h"
void handle_syscall(union uml_pt_regs *regs)
{
long result;
- int index;
+#if UML_CONFIG_SYSCALL_DEBUG
+ int index;
- index = record_syscall_start(UPT_SYSCALL_NR(regs));
+ index = record_syscall_start(UPT_SYSCALL_NR(regs));
+#endif
syscall_trace(regs, 0);
- result = execute_syscall(regs);
+ result = execute_syscall_skas(regs);
REGS_SET_SYSCALL_RETURN(regs->skas.regs, result);
syscall_trace(regs, 1);
- record_syscall_end(index, result);
+#if UML_CONFIG_SYSCALL_DEBUG
+ record_syscall_end(index, result);
+#endif
}
/*
diff --git a/arch/um/kernel/skas/tlb.c b/arch/um/kernel/skas/tlb.c
index 956fb0102a1ee..b8c5e71763d10 100644
--- a/arch/um/kernel/skas/tlb.c
+++ b/arch/um/kernel/skas/tlb.c
@@ -12,215 +12,74 @@
#include "asm/mmu.h"
#include "user_util.h"
#include "mem_user.h"
+#include "mem.h"
#include "skas.h"
#include "os.h"
+#include "tlb.h"
-static void fix_range(struct mm_struct *mm, unsigned long start_addr,
- unsigned long end_addr, int force)
+static void do_ops(int fd, struct host_vm_op *ops, int last)
{
- pgd_t *npgd;
- pud_t *npud;
- pmd_t *npmd;
- pte_t *npte;
- unsigned long addr, end;
- int r, w, x, err, fd;
-
- if(mm == NULL) return;
- fd = mm->context.skas.mm_fd;
- for(addr = start_addr; addr < end_addr;){
- npgd = pgd_offset(mm, addr);
- if(!pgd_present(*npgd)){
- if(force || pgd_newpage(*npgd)){
- end = addr + PGDIR_SIZE;
- if(end > end_addr)
- end = end_addr;
- err = unmap(fd, (void *) addr, end - addr);
- if(err < 0)
- panic("munmap failed, errno = %d\n",
- -err);
- pgd_mkuptodate(*npgd);
- }
- addr += PGDIR_SIZE;
- continue;
- }
-
- npud = pud_offset(npgd, addr);
- if(!pud_present(*npud)){
- if(force || pud_newpage(*npud)){
- end = addr + PUD_SIZE;
- if(end > end_addr)
- end = end_addr;
- err = unmap(fd, (void *) addr, end - addr);
- if(err < 0)
- panic("munmap failed, errno = %d\n",
- -err);
- pud_mkuptodate(*npud);
- }
- addr += PUD_SIZE;
- continue;
- }
-
- npmd = pmd_offset(npud, addr);
- if(!pmd_present(*npmd)){
- if(force || pmd_newpage(*npmd)){
- end = addr + PMD_SIZE;
- if(end > end_addr)
- end = end_addr;
- err = unmap(fd, (void *) addr, end - addr);
- if(err < 0)
- panic("munmap failed, errno = %d\n",
- -err);
- pmd_mkuptodate(*npmd);
- }
- addr += PMD_SIZE;
- continue;
+ struct host_vm_op *op;
+ int i;
+
+ for(i = 0; i <= last; i++){
+ op = &ops[i];
+ switch(op->type){
+ case MMAP:
+ map(fd, op->u.mmap.addr, op->u.mmap.len,
+ op->u.mmap.r, op->u.mmap.w, op->u.mmap.x,
+ op->u.mmap.fd, op->u.mmap.offset);
+ break;
+ case MUNMAP:
+ unmap(fd, (void *) op->u.munmap.addr,
+ op->u.munmap.len);
+ break;
+ case MPROTECT:
+ protect(fd, op->u.mprotect.addr, op->u.mprotect.len,
+ op->u.mprotect.r, op->u.mprotect.w,
+ op->u.mprotect.x);
+ break;
+ default:
+ printk("Unknown op type %d in do_ops\n", op->type);
+ break;
}
-
- npte = pte_offset_kernel(npmd, addr);
- r = pte_read(*npte);
- w = pte_write(*npte);
- x = pte_exec(*npte);
- if(!pte_dirty(*npte))
- w = 0;
- if(!pte_young(*npte)){
- r = 0;
- w = 0;
- }
- if(force || pte_newpage(*npte)){
- err = unmap(fd, (void *) addr, PAGE_SIZE);
- if(err < 0)
- panic("munmap failed, errno = %d\n", -err);
- if(pte_present(*npte))
- map(fd, addr, pte_val(*npte) & PAGE_MASK,
- PAGE_SIZE, r, w, x);
- }
- else if(pte_newprot(*npte))
- protect(fd, addr, PAGE_SIZE, r, w, x, 1);
-
- *npte = pte_mkuptodate(*npte);
- addr += PAGE_SIZE;
}
}
-void flush_tlb_kernel_range_skas(unsigned long start, unsigned long end)
+static void fix_range(struct mm_struct *mm, unsigned long start_addr,
+ unsigned long end_addr, int force)
{
- struct mm_struct *mm;
- pgd_t *pgd;
- pud_t *pud;
- pmd_t *pmd;
- pte_t *pte;
- unsigned long addr, last;
- int updated = 0, err;
+ int fd = mm->context.skas.mm_fd;
- mm = &init_mm;
- for(addr = start; addr < end;){
- pgd = pgd_offset(mm, addr);
- pud = pud_offset(pgd, addr);
- pmd = pmd_offset(pud, addr);
- if(!pgd_present(*pgd)){
- if(pgd_newpage(*pgd)){
- updated = 1;
- last = addr + PGDIR_SIZE;
- if(last > end)
- last = end;
- err = os_unmap_memory((void *) addr,
- last - addr);
- if(err < 0)
- panic("munmap failed, errno = %d\n",
- -err);
- }
- addr += PGDIR_SIZE;
- continue;
- }
-
- pud = pud_offset(pgd, addr);
- if(!pud_present(*pud)){
- if(pud_newpage(*pud)){
- updated = 1;
- last = addr + PUD_SIZE;
- if(last > end)
- last = end;
- err = os_unmap_memory((void *) addr,
- last - addr);
- if(err < 0)
- panic("munmap failed, errno = %d\n",
- -err);
- }
- addr += PUD_SIZE;
- continue;
- }
-
- pmd = pmd_offset(pud, addr);
- if(!pmd_present(*pmd)){
- if(pmd_newpage(*pmd)){
- updated = 1;
- last = addr + PMD_SIZE;
- if(last > end)
- last = end;
- err = os_unmap_memory((void *) addr,
- last - addr);
- if(err < 0)
- panic("munmap failed, errno = %d\n",
- -err);
- }
- addr += PMD_SIZE;
- continue;
- }
-
- pte = pte_offset_kernel(pmd, addr);
- if(!pte_present(*pte) || pte_newpage(*pte)){
- updated = 1;
- err = os_unmap_memory((void *) addr, PAGE_SIZE);
- if(err < 0)
- panic("munmap failed, errno = %d\n", -err);
- if(pte_present(*pte))
- map_memory(addr, pte_val(*pte) & PAGE_MASK,
- PAGE_SIZE, 1, 1, 1);
- }
- else if(pte_newprot(*pte)){
- updated = 1;
- protect_memory(addr, PAGE_SIZE, 1, 1, 1, 1);
- }
- addr += PAGE_SIZE;
- }
-}
-
-void flush_tlb_kernel_vm_skas(void)
-{
- flush_tlb_kernel_range_skas(start_vm, end_vm);
+ fix_range_common(mm, start_addr, end_addr, force, fd, do_ops);
}
void __flush_tlb_one_skas(unsigned long addr)
{
- flush_tlb_kernel_range_skas(addr, addr + PAGE_SIZE);
+ flush_tlb_kernel_range_common(addr, addr + PAGE_SIZE);
}
void flush_tlb_range_skas(struct vm_area_struct *vma, unsigned long start,
unsigned long end)
{
- if(vma->vm_mm == NULL)
- flush_tlb_kernel_range_skas(start, end);
- else fix_range(vma->vm_mm, start, end, 0);
+ if(vma->vm_mm == NULL)
+ flush_tlb_kernel_range_common(start, end);
+ else fix_range(vma->vm_mm, start, end, 0);
}
void flush_tlb_mm_skas(struct mm_struct *mm)
{
- flush_tlb_kernel_vm_skas();
- fix_range(mm, 0, host_task_size, 0);
+ /* Don't bother flushing if this address space is about to be
+ * destroyed.
+ */
+ if(atomic_read(&mm->mm_users) == 0)
+ return;
+
+ fix_range(mm, 0, host_task_size, 0);
+ flush_tlb_kernel_range_common(start_vm, end_vm);
}
void force_flush_all_skas(void)
{
- fix_range(current->mm, 0, host_task_size, 1);
+ fix_range(current->mm, 0, host_task_size, 1);
}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/skas/uaccess.c b/arch/um/kernel/skas/uaccess.c
index c8e5fe49583ae..7575ec489b630 100644
--- a/arch/um/kernel/skas/uaccess.c
+++ b/arch/um/kernel/skas/uaccess.c
@@ -61,7 +61,8 @@ static void do_buffer_op(void *jmpbuf, void *arg_ptr)
void *arg;
int *res;
- va_copy(args, *(va_list *)arg_ptr);
+ /* Some old gccs recognize __va_copy, but not va_copy */
+ __va_copy(args, *(va_list *)arg_ptr);
addr = va_arg(args, unsigned long);
len = va_arg(args, int);
is_write = va_arg(args, int);
diff --git a/arch/um/kernel/smp.c b/arch/um/kernel/smp.c
index e916391383cb1..72113b0a96e7b 100644
--- a/arch/um/kernel/smp.c
+++ b/arch/um/kernel/smp.c
@@ -41,15 +41,9 @@ EXPORT_SYMBOL(cpu_possible_map);
*/
struct cpuinfo_um cpu_data[NR_CPUS];
-/* Set when the idlers are all forked */
-int smp_threads_ready = 0;
-
/* A statistic, can be a little off */
int num_reschedules_sent = 0;
-/* Small, random number, never changed */
-unsigned long cache_decay_ticks = 5;
-
/* Not changed after boot */
struct task_struct *idle_threads[NR_CPUS];
diff --git a/arch/um/kernel/sys_call_table.c b/arch/um/kernel/sys_call_table.c
index eda45b82071c4..7fc06c85b29d9 100644
--- a/arch/um/kernel/sys_call_table.c
+++ b/arch/um/kernel/sys_call_table.c
@@ -31,7 +31,6 @@
extern syscall_handler_t sys_fork;
extern syscall_handler_t sys_execve;
extern syscall_handler_t um_time;
-extern syscall_handler_t um_mount;
extern syscall_handler_t um_stime;
extern syscall_handler_t sys_pipe;
extern syscall_handler_t sys_olduname;
@@ -48,7 +47,6 @@ extern syscall_handler_t sys_vfork;
extern syscall_handler_t old_select;
extern syscall_handler_t sys_modify_ldt;
extern syscall_handler_t sys_rt_sigsuspend;
-extern syscall_handler_t sys_vserver;
extern syscall_handler_t sys_mbind;
extern syscall_handler_t sys_get_mempolicy;
extern syscall_handler_t sys_set_mempolicy;
@@ -77,7 +75,7 @@ syscall_handler_t *sys_call_table[] = {
[ __NR_lchown ] = (syscall_handler_t *) sys_lchown16,
[ __NR_lseek ] = (syscall_handler_t *) sys_lseek,
[ __NR_getpid ] = (syscall_handler_t *) sys_getpid,
- [ __NR_mount ] = um_mount,
+ [ __NR_mount ] = (syscall_handler_t *) sys_mount,
[ __NR_setuid ] = (syscall_handler_t *) sys_setuid16,
[ __NR_getuid ] = (syscall_handler_t *) sys_getuid16,
[ __NR_ptrace ] = (syscall_handler_t *) sys_ptrace,
@@ -242,7 +240,8 @@ syscall_handler_t *sys_call_table[] = {
[ __NR_epoll_create ] = (syscall_handler_t *) sys_epoll_create,
[ __NR_epoll_ctl ] = (syscall_handler_t *) sys_epoll_ctl,
[ __NR_epoll_wait ] = (syscall_handler_t *) sys_epoll_wait,
- [ __NR_set_tid_address ] = (syscall_handler_t *) sys_set_tid_address,
+ [ __NR_remap_file_pages ] = (syscall_handler_t *) sys_remap_file_pages,
+ [ __NR_set_tid_address ] = (syscall_handler_t *) sys_set_tid_address,
[ __NR_timer_create ] = (syscall_handler_t *) sys_timer_create,
[ __NR_timer_settime ] = (syscall_handler_t *) sys_timer_settime,
[ __NR_timer_gettime ] = (syscall_handler_t *) sys_timer_gettime,
@@ -252,12 +251,10 @@ syscall_handler_t *sys_call_table[] = {
[ __NR_clock_gettime ] = (syscall_handler_t *) sys_clock_gettime,
[ __NR_clock_getres ] = (syscall_handler_t *) sys_clock_getres,
[ __NR_clock_nanosleep ] = (syscall_handler_t *) sys_clock_nanosleep,
- [ __NR_statfs64 ] = (syscall_handler_t *) sys_statfs64,
- [ __NR_fstatfs64 ] = (syscall_handler_t *) sys_fstatfs64,
[ __NR_tgkill ] = (syscall_handler_t *) sys_tgkill,
[ __NR_utimes ] = (syscall_handler_t *) sys_utimes,
- [ __NR_fadvise64_64 ] = (syscall_handler_t *) sys_fadvise64_64,
- [ __NR_vserver ] = (syscall_handler_t *) sys_vserver,
+ [ __NR_fadvise64 ] = (syscall_handler_t *) sys_fadvise64,
+ [ __NR_vserver ] = (syscall_handler_t *) sys_ni_syscall,
[ __NR_mbind ] = (syscall_handler_t *) sys_mbind,
[ __NR_get_mempolicy ] = (syscall_handler_t *) sys_get_mempolicy,
[ __NR_set_mempolicy ] = (syscall_handler_t *) sys_set_mempolicy,
@@ -267,14 +264,13 @@ syscall_handler_t *sys_call_table[] = {
[ __NR_mq_timedreceive ] = (syscall_handler_t *) sys_mq_timedreceive,
[ __NR_mq_notify ] = (syscall_handler_t *) sys_mq_notify,
[ __NR_mq_getsetattr ] = (syscall_handler_t *) sys_mq_getsetattr,
- [ __NR_sys_kexec_load ] = (syscall_handler_t *) sys_ni_syscall,
+ [ __NR_kexec_load ] = (syscall_handler_t *) sys_ni_syscall,
[ __NR_waitid ] = (syscall_handler_t *) sys_waitid,
- [ 285 ] = (syscall_handler_t *) sys_ni_syscall,
[ __NR_add_key ] = (syscall_handler_t *) sys_add_key,
[ __NR_request_key ] = (syscall_handler_t *) sys_request_key,
[ __NR_keyctl ] = (syscall_handler_t *) sys_keyctl,
ARCH_SYSCALLS
[ LAST_SYSCALL + 1 ... NR_syscalls ] =
- (syscall_handler_t *) sys_ni_syscall
+ (syscall_handler_t *) sys_ni_syscall
};
diff --git a/arch/um/kernel/syscall_kern.c b/arch/um/kernel/syscall_kern.c
index 93aab676469bf..42731e04f50fd 100644
--- a/arch/um/kernel/syscall_kern.c
+++ b/arch/um/kernel/syscall_kern.c
@@ -27,12 +27,6 @@
/* Unlocked, I don't care if this is a bit off */
int nsyscalls = 0;
-long um_mount(char __user * dev_name, char __user * dir_name,
- char __user * type, unsigned long new_flags, void __user * data)
-{
- return(sys_mount(dev_name, dir_name, type, new_flags, data));
-}
-
long sys_fork(void)
{
long ret;
@@ -154,11 +148,6 @@ long sys_olduname(struct oldold_utsname * name)
return error;
}
-long execute_syscall(void *r)
-{
- return(CHOOSE_MODE_PROC(execute_syscall_tt, execute_syscall_skas, r));
-}
-
DEFINE_SPINLOCK(syscall_lock);
static int syscall_index = 0;
diff --git a/arch/um/kernel/tlb.c b/arch/um/kernel/tlb.c
index 26f5d12d81f34..eda477edfdf5e 100644
--- a/arch/um/kernel/tlb.c
+++ b/arch/um/kernel/tlb.c
@@ -9,87 +9,361 @@
#include "asm/tlbflush.h"
#include "choose-mode.h"
#include "mode_kern.h"
+#include "user_util.h"
+#include "tlb.h"
+#include "mem.h"
+#include "mem_user.h"
+#include "os.h"
+
+#define ADD_ROUND(n, inc) (((n) + (inc)) & ~((inc) - 1))
+
+void fix_range_common(struct mm_struct *mm, unsigned long start_addr,
+ unsigned long end_addr, int force, int data,
+ void (*do_ops)(int, struct host_vm_op *, int))
+{
+ pgd_t *npgd;
+ pud_t *npud;
+ pmd_t *npmd;
+ pte_t *npte;
+ unsigned long addr, end;
+ int r, w, x;
+ struct host_vm_op ops[16];
+ int op_index = -1, last_op = sizeof(ops) / sizeof(ops[0]) - 1;
+
+ if(mm == NULL) return;
+
+ for(addr = start_addr; addr < end_addr;){
+ npgd = pgd_offset(mm, addr);
+ if(!pgd_present(*npgd)){
+ end = ADD_ROUND(addr, PGDIR_SIZE);
+ if(end > end_addr)
+ end = end_addr;
+ if(force || pgd_newpage(*npgd)){
+ op_index = add_munmap(addr, end - addr, ops,
+ op_index, last_op, data,
+ do_ops);
+ pgd_mkuptodate(*npgd);
+ }
+ addr = end;
+ continue;
+ }
+
+ npud = pud_offset(npgd, addr);
+ if(!pud_present(*npud)){
+ end = ADD_ROUND(addr, PUD_SIZE);
+ if(end > end_addr)
+ end = end_addr;
+ if(force || pud_newpage(*npud)){
+ op_index = add_munmap(addr, end - addr, ops,
+ op_index, last_op, data,
+ do_ops);
+ pud_mkuptodate(*npud);
+ }
+ addr = end;
+ continue;
+ }
+
+ npmd = pmd_offset(npud, addr);
+ if(!pmd_present(*npmd)){
+ end = ADD_ROUND(addr, PMD_SIZE);
+ if(end > end_addr)
+ end = end_addr;
+ if(force || pmd_newpage(*npmd)){
+ op_index = add_munmap(addr, end - addr, ops,
+ op_index, last_op, data,
+ do_ops);
+ pmd_mkuptodate(*npmd);
+ }
+ addr = end;
+ continue;
+ }
+
+ npte = pte_offset_kernel(npmd, addr);
+ r = pte_read(*npte);
+ w = pte_write(*npte);
+ x = pte_exec(*npte);
+ if(!pte_dirty(*npte))
+ w = 0;
+ if(!pte_young(*npte)){
+ r = 0;
+ w = 0;
+ }
+ if(force || pte_newpage(*npte)){
+ if(pte_present(*npte))
+ op_index = add_mmap(addr,
+ pte_val(*npte) & PAGE_MASK,
+ PAGE_SIZE, r, w, x, ops,
+ op_index, last_op, data,
+ do_ops);
+ else op_index = add_munmap(addr, PAGE_SIZE, ops,
+ op_index, last_op, data,
+ do_ops);
+ }
+ else if(pte_newprot(*npte))
+ op_index = add_mprotect(addr, PAGE_SIZE, r, w, x, ops,
+ op_index, last_op, data,
+ do_ops);
+
+ *npte = pte_mkuptodate(*npte);
+ addr += PAGE_SIZE;
+ }
+ (*do_ops)(data, ops, op_index);
+}
+
+int flush_tlb_kernel_range_common(unsigned long start, unsigned long end)
+{
+ struct mm_struct *mm;
+ pgd_t *pgd;
+ pud_t *pud;
+ pmd_t *pmd;
+ pte_t *pte;
+ unsigned long addr, last;
+ int updated = 0, err;
+
+ mm = &init_mm;
+ for(addr = start; addr < end;){
+ pgd = pgd_offset(mm, addr);
+ if(!pgd_present(*pgd)){
+ last = ADD_ROUND(addr, PGDIR_SIZE);
+ if(last > end)
+ last = end;
+ if(pgd_newpage(*pgd)){
+ updated = 1;
+ err = os_unmap_memory((void *) addr,
+ last - addr);
+ if(err < 0)
+ panic("munmap failed, errno = %d\n",
+ -err);
+ }
+ addr = last;
+ continue;
+ }
+
+ pud = pud_offset(pgd, addr);
+ if(!pud_present(*pud)){
+ last = ADD_ROUND(addr, PUD_SIZE);
+ if(last > end)
+ last = end;
+ if(pud_newpage(*pud)){
+ updated = 1;
+ err = os_unmap_memory((void *) addr,
+ last - addr);
+ if(err < 0)
+ panic("munmap failed, errno = %d\n",
+ -err);
+ }
+ addr = last;
+ continue;
+ }
+
+ pmd = pmd_offset(pud, addr);
+ if(!pmd_present(*pmd)){
+ last = ADD_ROUND(addr, PMD_SIZE);
+ if(last > end)
+ last = end;
+ if(pmd_newpage(*pmd)){
+ updated = 1;
+ err = os_unmap_memory((void *) addr,
+ last - addr);
+ if(err < 0)
+ panic("munmap failed, errno = %d\n",
+ -err);
+ }
+ addr = last;
+ continue;
+ }
+
+ pte = pte_offset_kernel(pmd, addr);
+ if(!pte_present(*pte) || pte_newpage(*pte)){
+ updated = 1;
+ err = os_unmap_memory((void *) addr,
+ PAGE_SIZE);
+ if(err < 0)
+ panic("munmap failed, errno = %d\n",
+ -err);
+ if(pte_present(*pte))
+ map_memory(addr,
+ pte_val(*pte) & PAGE_MASK,
+ PAGE_SIZE, 1, 1, 1);
+ }
+ else if(pte_newprot(*pte)){
+ updated = 1;
+ protect_memory(addr, PAGE_SIZE, 1, 1, 1, 1);
+ }
+ addr += PAGE_SIZE;
+ }
+ return(updated);
+}
void flush_tlb_page(struct vm_area_struct *vma, unsigned long address)
{
- address &= PAGE_MASK;
- flush_tlb_range(vma, address, address + PAGE_SIZE);
+ address &= PAGE_MASK;
+ flush_tlb_range(vma, address, address + PAGE_SIZE);
}
void flush_tlb_all(void)
{
- flush_tlb_mm(current->mm);
+ flush_tlb_mm(current->mm);
}
void flush_tlb_kernel_range(unsigned long start, unsigned long end)
{
- CHOOSE_MODE_PROC(flush_tlb_kernel_range_tt,
- flush_tlb_kernel_range_skas, start, end);
+ CHOOSE_MODE_PROC(flush_tlb_kernel_range_tt,
+ flush_tlb_kernel_range_common, start, end);
}
void flush_tlb_kernel_vm(void)
{
- CHOOSE_MODE(flush_tlb_kernel_vm_tt(), flush_tlb_kernel_vm_skas());
+ CHOOSE_MODE(flush_tlb_kernel_vm_tt(),
+ flush_tlb_kernel_range_common(start_vm, end_vm));
}
void __flush_tlb_one(unsigned long addr)
{
- CHOOSE_MODE_PROC(__flush_tlb_one_tt, __flush_tlb_one_skas, addr);
+ CHOOSE_MODE_PROC(__flush_tlb_one_tt, __flush_tlb_one_skas, addr);
}
void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
- unsigned long end)
+ unsigned long end)
{
- CHOOSE_MODE_PROC(flush_tlb_range_tt, flush_tlb_range_skas, vma, start,
- end);
+ CHOOSE_MODE_PROC(flush_tlb_range_tt, flush_tlb_range_skas, vma, start,
+ end);
}
void flush_tlb_mm(struct mm_struct *mm)
{
- CHOOSE_MODE_PROC(flush_tlb_mm_tt, flush_tlb_mm_skas, mm);
+ CHOOSE_MODE_PROC(flush_tlb_mm_tt, flush_tlb_mm_skas, mm);
}
void force_flush_all(void)
{
- CHOOSE_MODE(force_flush_all_tt(), force_flush_all_skas());
+ CHOOSE_MODE(force_flush_all_tt(), force_flush_all_skas());
}
pgd_t *pgd_offset_proc(struct mm_struct *mm, unsigned long address)
{
- return(pgd_offset(mm, address));
+ return(pgd_offset(mm, address));
}
pud_t *pud_offset_proc(pgd_t *pgd, unsigned long address)
{
- return(pud_offset(pgd, address));
+ return(pud_offset(pgd, address));
}
pmd_t *pmd_offset_proc(pud_t *pud, unsigned long address)
{
- return(pmd_offset(pud, address));
+ return(pmd_offset(pud, address));
}
pte_t *pte_offset_proc(pmd_t *pmd, unsigned long address)
{
- return(pte_offset_kernel(pmd, address));
+ return(pte_offset_kernel(pmd, address));
}
pte_t *addr_pte(struct task_struct *task, unsigned long addr)
{
- pgd_t *pgd = pgd_offset(task->mm, addr);
- pud_t *pud = pud_offset(pgd, addr);
- pmd_t *pmd = pmd_offset(pud, addr);
+ pgd_t *pgd = pgd_offset(task->mm, addr);
+ pud_t *pud = pud_offset(pgd, addr);
+ pmd_t *pmd = pmd_offset(pud, addr);
- return(pte_offset_map(pmd, addr));
+ return(pte_offset_map(pmd, addr));
}
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
+int add_mmap(unsigned long virt, unsigned long phys, unsigned long len,
+ int r, int w, int x, struct host_vm_op *ops, int index,
+ int last_filled, int data,
+ void (*do_ops)(int, struct host_vm_op *, int))
+{
+ __u64 offset;
+ struct host_vm_op *last;
+ int fd;
+
+ fd = phys_mapping(phys, &offset);
+ if(index != -1){
+ last = &ops[index];
+ if((last->type == MMAP) &&
+ (last->u.mmap.addr + last->u.mmap.len == virt) &&
+ (last->u.mmap.r == r) && (last->u.mmap.w == w) &&
+ (last->u.mmap.x == x) && (last->u.mmap.fd == fd) &&
+ (last->u.mmap.offset + last->u.mmap.len == offset)){
+ last->u.mmap.len += len;
+ return(index);
+ }
+ }
+
+ if(index == last_filled){
+ (*do_ops)(data, ops, last_filled);
+ index = -1;
+ }
+
+ ops[++index] = ((struct host_vm_op) { .type = MMAP,
+ .u = { .mmap = {
+ .addr = virt,
+ .len = len,
+ .r = r,
+ .w = w,
+ .x = x,
+ .fd = fd,
+ .offset = offset }
+ } });
+ return(index);
+}
+
+int add_munmap(unsigned long addr, unsigned long len, struct host_vm_op *ops,
+ int index, int last_filled, int data,
+ void (*do_ops)(int, struct host_vm_op *, int))
+{
+ struct host_vm_op *last;
+
+ if(index != -1){
+ last = &ops[index];
+ if((last->type == MUNMAP) &&
+ (last->u.munmap.addr + last->u.mmap.len == addr)){
+ last->u.munmap.len += len;
+ return(index);
+ }
+ }
+
+ if(index == last_filled){
+ (*do_ops)(data, ops, last_filled);
+ index = -1;
+ }
+
+ ops[++index] = ((struct host_vm_op) { .type = MUNMAP,
+ .u = { .munmap = {
+ .addr = addr,
+ .len = len } } });
+ return(index);
+}
+
+int add_mprotect(unsigned long addr, unsigned long len, int r, int w, int x,
+ struct host_vm_op *ops, int index, int last_filled, int data,
+ void (*do_ops)(int, struct host_vm_op *, int))
+{
+ struct host_vm_op *last;
+
+ if(index != -1){
+ last = &ops[index];
+ if((last->type == MPROTECT) &&
+ (last->u.mprotect.addr + last->u.mprotect.len == addr) &&
+ (last->u.mprotect.r == r) && (last->u.mprotect.w == w) &&
+ (last->u.mprotect.x == x)){
+ last->u.mprotect.len += len;
+ return(index);
+ }
+ }
+
+ if(index == last_filled){
+ (*do_ops)(data, ops, last_filled);
+ index = -1;
+ }
+
+ ops[++index] = ((struct host_vm_op) { .type = MPROTECT,
+ .u = { .mprotect = {
+ .addr = addr,
+ .len = len,
+ .r = r,
+ .w = w,
+ .x = x } } });
+ return(index);
+}
diff --git a/arch/um/kernel/trap_user.c b/arch/um/kernel/trap_user.c
index 0a3d279ce64f0..50a4042a509f9 100644
--- a/arch/um/kernel/trap_user.c
+++ b/arch/um/kernel/trap_user.c
@@ -8,7 +8,6 @@
#include <setjmp.h>
#include <signal.h>
#include <sys/time.h>
-#include <sys/ptrace.h>
#include <sys/wait.h>
#include <asm/page.h>
#include <asm/unistd.h>
diff --git a/arch/um/kernel/tt/Makefile b/arch/um/kernel/tt/Makefile
index 7c9eec5fded52..3d5177df3504c 100644
--- a/arch/um/kernel/tt/Makefile
+++ b/arch/um/kernel/tt/Makefile
@@ -12,21 +12,17 @@ obj-y = exec_kern.o exec_user.o gdb.o ksyms.o mem.o mem_user.o process_kern.o \
obj-$(CONFIG_PT_PROXY) += gdb_kern.o ptproxy/
-USER_OBJS := $(filter %_user.o,$(obj-y)) gdb.o time.o tracer.o
-USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
+USER_OBJS := gdb.o time.o tracer.o
+
+include arch/um/scripts/Makefile.rules
UNMAP_CFLAGS := $(patsubst -pg -DPROFILING,,$(USER_CFLAGS))
UNMAP_CFLAGS := $(patsubst -fprofile-arcs -ftest-coverage,,$(UNMAP_CFLAGS))
-$(USER_OBJS) : %.o: %.c
- $(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
-
-$(obj)/unmap.o: $(src)/unmap.c
- $(CC) $(UNMAP_CFLAGS) -c -o $@ $<
-
-LIBC_DIR ?= /usr/lib
+#XXX: partially copied from arch/um/scripts/Makefile.rules
+$(obj)/unmap.o: c_flags = -Wp,-MD,$(depfile) $(UNMAP_CFLAGS)
$(obj)/unmap_fin.o : $(obj)/unmap.o
- ld -r -o $(obj)/unmap_tmp.o $< -lc -L$(LIBC_DIR)
- objcopy $(obj)/unmap_tmp.o $@ -G switcheroo
+ $(LD) -r -o $(obj)/unmap_tmp.o $< $(shell $(CC) -print-file-name=libc.a)
+ $(OBJCOPY) $(obj)/unmap_tmp.o $@ -G switcheroo
diff --git a/arch/um/kernel/tt/exec_user.c b/arch/um/kernel/tt/exec_user.c
index 26a120a8415e7..a92c02ff2ce30 100644
--- a/arch/um/kernel/tt/exec_user.c
+++ b/arch/um/kernel/tt/exec_user.c
@@ -9,8 +9,6 @@
#include <sched.h>
#include <errno.h>
#include <sys/wait.h>
-#include <sys/ptrace.h>
-#include <linux/ptrace.h>
#include <signal.h>
#include "user_util.h"
#include "kern_util.h"
diff --git a/arch/um/kernel/tt/gdb.c b/arch/um/kernel/tt/gdb.c
index 22cbdbffbe3e6..19a0ad7b35b3c 100644
--- a/arch/um/kernel/tt/gdb.c
+++ b/arch/um/kernel/tt/gdb.c
@@ -8,8 +8,8 @@
#include <errno.h>
#include <string.h>
#include <signal.h>
-#include <sys/ptrace.h>
#include <sys/types.h>
+#include "ptrace_user.h"
#include "uml-config.h"
#include "kern_constants.h"
#include "chan_user.h"
diff --git a/arch/um/kernel/tt/include/tt.h b/arch/um/kernel/tt/include/tt.h
index 01c8601cda9a5..c667b67af405f 100644
--- a/arch/um/kernel/tt/include/tt.h
+++ b/arch/um/kernel/tt/include/tt.h
@@ -30,6 +30,7 @@ extern void do_syscall(void *task, int pid, int local_using_sysemu);
extern void do_sigtrap(void *task);
extern int is_valid_pid(int pid);
extern void remap_data(void *segment_start, void *segment_end, int w);
+extern long execute_syscall_tt(void *r);
#endif
diff --git a/arch/um/kernel/tt/mem.c b/arch/um/kernel/tt/mem.c
index 34090b8d29836..74346a04a2b28 100644
--- a/arch/um/kernel/tt/mem.c
+++ b/arch/um/kernel/tt/mem.c
@@ -15,7 +15,7 @@
void before_mem_tt(unsigned long brk_start)
{
- if(!jail || debug)
+ if(debug)
remap_data(UML_ROUND_DOWN(&_stext), UML_ROUND_UP(&_etext), 1);
remap_data(UML_ROUND_DOWN(&_sdata), UML_ROUND_UP(&_edata), 1);
remap_data(UML_ROUND_DOWN(&__bss_start), UML_ROUND_UP(&_end), 1);
diff --git a/arch/um/kernel/tt/process_kern.c b/arch/um/kernel/tt/process_kern.c
index 1f4d12b27195e..f19f7c18febe4 100644
--- a/arch/um/kernel/tt/process_kern.c
+++ b/arch/um/kernel/tt/process_kern.c
@@ -85,24 +85,6 @@ void *switch_to_tt(void *prev, void *next, void *last)
(prev_sched->exit_state == EXIT_DEAD))
os_kill_process(prev_sched->thread.mode.tt.extern_pid, 1);
- /* This works around a nasty race with 'jail'. If we are switching
- * between two threads of a threaded app and the incoming process
- * runs before the outgoing process reaches the read, and it makes
- * it all the way out to userspace, then it will have write-protected
- * the outgoing process stack. Then, when the outgoing process
- * returns from the write, it will segfault because it can no longer
- * write its own stack. So, in order to avoid that, the incoming
- * thread sits in a loop yielding until 'reading' is set. This
- * isn't entirely safe, since there may be a reschedule from a timer
- * happening between setting 'reading' and sleeping in read. But,
- * it should get a whole quantum in which to reach the read and sleep,
- * which should be enough.
- */
-
- if(jail){
- while(!reading) sched_yield();
- }
-
change_sig(SIGVTALRM, vtalrm);
change_sig(SIGALRM, alrm);
change_sig(SIGPROF, prof);
@@ -394,84 +376,6 @@ void init_idle_tt(void)
default_idle();
}
-/* Changed by jail_setup, which is a setup */
-int jail = 0;
-
-int __init jail_setup(char *line, int *add)
-{
- int ok = 1;
-
- if(jail) return(0);
-#ifdef CONFIG_SMP
- printf("'jail' may not used used in a kernel with CONFIG_SMP "
- "enabled\n");
- ok = 0;
-#endif
-#ifdef CONFIG_HOSTFS
- printf("'jail' may not used used in a kernel with CONFIG_HOSTFS "
- "enabled\n");
- ok = 0;
-#endif
-#ifdef CONFIG_MODULES
- printf("'jail' may not used used in a kernel with CONFIG_MODULES "
- "enabled\n");
- ok = 0;
-#endif
- if(!ok) exit(1);
-
- /* CAP_SYS_RAWIO controls the ability to open /dev/mem and /dev/kmem.
- * Removing it from the bounding set eliminates the ability of anything
- * to acquire it, and thus read or write kernel memory.
- */
- cap_lower(cap_bset, CAP_SYS_RAWIO);
- jail = 1;
- return(0);
-}
-
-__uml_setup("jail", jail_setup,
-"jail\n"
-" Enables the protection of kernel memory from processes.\n\n"
-);
-
-static void mprotect_kernel_mem(int w)
-{
- unsigned long start, end;
- int pages;
-
- if(!jail || (current == &init_task)) return;
-
- pages = (1 << CONFIG_KERNEL_STACK_ORDER);
-
- start = (unsigned long) current_thread + PAGE_SIZE;
- end = (unsigned long) current_thread + PAGE_SIZE * pages;
- protect_memory(uml_reserved, start - uml_reserved, 1, w, 1, 1);
- protect_memory(end, high_physmem - end, 1, w, 1, 1);
-
- start = (unsigned long) UML_ROUND_DOWN(&_stext);
- end = (unsigned long) UML_ROUND_UP(&_etext);
- protect_memory(start, end - start, 1, w, 1, 1);
-
- start = (unsigned long) UML_ROUND_DOWN(&_unprotected_end);
- end = (unsigned long) UML_ROUND_UP(&_edata);
- protect_memory(start, end - start, 1, w, 1, 1);
-
- start = (unsigned long) UML_ROUND_DOWN(&__bss_start);
- end = (unsigned long) UML_ROUND_UP(brk_start);
- protect_memory(start, end - start, 1, w, 1, 1);
-
- mprotect_kernel_vm(w);
-}
-
-void unprotect_kernel_mem(void)
-{
- mprotect_kernel_mem(1);
-}
-
-void protect_kernel_mem(void)
-{
- mprotect_kernel_mem(0);
-}
-
extern void start_kernel(void);
static int start_kernel_proc(void *unused)
diff --git a/arch/um/kernel/tt/ptproxy/Makefile b/arch/um/kernel/tt/ptproxy/Makefile
index 9f9daf5c17837..3ad5b774de595 100644
--- a/arch/um/kernel/tt/ptproxy/Makefile
+++ b/arch/um/kernel/tt/ptproxy/Makefile
@@ -5,7 +5,6 @@
obj-y = proxy.o ptrace.o sysdep.o wait.o
-USER_OBJS := $(foreach file,$(obj-y),$(src)/$(file))
+USER_OBJS := $(obj-y)
-$(USER_OBJS) : %.o: %.c
- $(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
+include arch/um/scripts/Makefile.rules
diff --git a/arch/um/kernel/tt/ptproxy/proxy.c b/arch/um/kernel/tt/ptproxy/proxy.c
index f41832c79f364..58800c50b10e5 100644
--- a/arch/um/kernel/tt/ptproxy/proxy.c
+++ b/arch/um/kernel/tt/ptproxy/proxy.c
@@ -18,9 +18,9 @@ Jeff Dike (jdike@karaya.com) : Modified for integration into uml
#include <termios.h>
#include <sys/wait.h>
#include <sys/types.h>
-#include <sys/ptrace.h>
#include <sys/ioctl.h>
#include <asm/unistd.h>
+#include "ptrace_user.h"
#include "ptproxy.h"
#include "sysdep.h"
diff --git a/arch/um/kernel/tt/ptproxy/ptrace.c b/arch/um/kernel/tt/ptproxy/ptrace.c
index 721d0a306fdea..528a5fc8d8879 100644
--- a/arch/um/kernel/tt/ptproxy/ptrace.c
+++ b/arch/um/kernel/tt/ptproxy/ptrace.c
@@ -12,9 +12,7 @@ Jeff Dike (jdike@karaya.com) : Modified for integration into uml
#include <signal.h>
#include <sys/types.h>
#include <sys/time.h>
-#include <sys/ptrace.h>
#include <sys/wait.h>
-#include <asm/ptrace.h>
#include "ptproxy.h"
#include "debug.h"
@@ -127,7 +125,7 @@ long proxy_ptrace(struct debugger *debugger, int arg1, pid_t arg2,
case PTRACE_PEEKDATA:
case PTRACE_PEEKTEXT:
- case PTRACE_PEEKUSER:
+ case PTRACE_PEEKUSR:
/* The value being read out could be -1, so we have to
* check errno to see if there's an error, and zero it
* beforehand so we're not faked out by an old error
@@ -144,11 +142,11 @@ long proxy_ptrace(struct debugger *debugger, int arg1, pid_t arg2,
case PTRACE_POKEDATA:
case PTRACE_POKETEXT:
- case PTRACE_POKEUSER:
+ case PTRACE_POKEUSR:
result = ptrace(arg1, child, arg3, arg4);
if(result == -1) return(-errno);
- if(arg1 == PTRACE_POKEUSER) ptrace_pokeuser(arg3, arg4);
+ if(arg1 == PTRACE_POKEUSR) ptrace_pokeuser(arg3, arg4);
return(result);
#ifdef UM_HAVE_SETFPREGS
diff --git a/arch/um/kernel/tt/ptproxy/sysdep.c b/arch/um/kernel/tt/ptproxy/sysdep.c
index 4545ea4f27e16..a5f0e01e214e5 100644
--- a/arch/um/kernel/tt/ptproxy/sysdep.c
+++ b/arch/um/kernel/tt/ptproxy/sysdep.c
@@ -11,7 +11,6 @@ terms and conditions.
#include <signal.h>
#include <errno.h>
#include <sys/types.h>
-#include <sys/ptrace.h>
#include <linux/unistd.h>
#include "ptrace_user.h"
#include "user_util.h"
@@ -20,21 +19,21 @@ terms and conditions.
int get_syscall(pid_t pid, long *arg1, long *arg2, long *arg3, long *arg4,
long *arg5)
{
- *arg1 = ptrace(PTRACE_PEEKUSER, pid, PT_SYSCALL_ARG1_OFFSET, 0);
- *arg2 = ptrace(PTRACE_PEEKUSER, pid, PT_SYSCALL_ARG2_OFFSET, 0);
- *arg3 = ptrace(PTRACE_PEEKUSER, pid, PT_SYSCALL_ARG3_OFFSET, 0);
- *arg4 = ptrace(PTRACE_PEEKUSER, pid, PT_SYSCALL_ARG4_OFFSET, 0);
- *arg5 = ptrace(PTRACE_PEEKUSER, pid, PT_SYSCALL_ARG5_OFFSET, 0);
- return(ptrace(PTRACE_PEEKUSER, pid, PT_SYSCALL_NR_OFFSET, 0));
+ *arg1 = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_ARG1_OFFSET, 0);
+ *arg2 = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_ARG2_OFFSET, 0);
+ *arg3 = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_ARG3_OFFSET, 0);
+ *arg4 = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_ARG4_OFFSET, 0);
+ *arg5 = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_ARG5_OFFSET, 0);
+ return(ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_NR_OFFSET, 0));
}
void syscall_cancel(pid_t pid, int result)
{
- if((ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET,
+ if((ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET,
__NR_getpid) < 0) ||
(ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) ||
(wait_for_stop(pid, SIGTRAP, PTRACE_SYSCALL, NULL) < 0) ||
- (ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_RET_OFFSET, result) < 0) ||
+ (ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET, result) < 0) ||
(ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0))
printk("ptproxy: couldn't cancel syscall: errno = %d\n",
errno);
@@ -42,7 +41,7 @@ void syscall_cancel(pid_t pid, int result)
void syscall_set_result(pid_t pid, long result)
{
- ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_RET_OFFSET, result);
+ ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET, result);
}
void syscall_continue(pid_t pid)
@@ -52,7 +51,7 @@ void syscall_continue(pid_t pid)
int syscall_pause(pid_t pid)
{
- if(ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET, __NR_pause) < 0){
+ if(ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET, __NR_pause) < 0){
printk("syscall_change - ptrace failed, errno = %d\n", errno);
return(-1);
}
diff --git a/arch/um/kernel/tt/ptproxy/wait.c b/arch/um/kernel/tt/ptproxy/wait.c
index fcb7ea50fc7e6..12f6319d8d769 100644
--- a/arch/um/kernel/tt/ptproxy/wait.c
+++ b/arch/um/kernel/tt/ptproxy/wait.c
@@ -9,14 +9,13 @@ terms and conditions.
#include <errno.h>
#include <signal.h>
#include <sys/wait.h>
-#include <sys/ptrace.h>
#include "ptproxy.h"
#include "sysdep.h"
#include "wait.h"
#include "user_util.h"
+#include "ptrace_user.h"
#include "sysdep/ptrace.h"
-#include "sysdep/ptrace_user.h"
#include "sysdep/sigcontext.h"
int proxy_wait_return(struct debugger *debugger, pid_t unused)
@@ -59,10 +58,10 @@ int real_wait_return(struct debugger *debugger)
pid = debugger->pid;
- ip = ptrace(PTRACE_PEEKUSER, pid, PT_IP_OFFSET, 0);
+ ip = ptrace(PTRACE_PEEKUSR, pid, PT_IP_OFFSET, 0);
IP_RESTART_SYSCALL(ip);
- if(ptrace(PTRACE_POKEUSER, pid, PT_IP_OFFSET, ip) < 0)
+ if(ptrace(PTRACE_POKEUSR, pid, PT_IP_OFFSET, ip) < 0)
tracer_panic("real_wait_return : Failed to restart system "
"call, errno = %d\n", errno);
diff --git a/arch/um/kernel/tt/syscall_kern.c b/arch/um/kernel/tt/syscall_kern.c
index c02e504e54c1b..2650a628719e4 100644
--- a/arch/um/kernel/tt/syscall_kern.c
+++ b/arch/um/kernel/tt/syscall_kern.c
@@ -22,8 +22,10 @@ long execute_syscall_tt(void *r)
long res;
int syscall;
+#ifdef CONFIG_SYSCALL_DEBUG
current->thread.nsyscalls++;
nsyscalls++;
+#endif
syscall = UPT_SYSCALL_NR(&regs->regs);
if((syscall >= NR_syscalls) || (syscall < 0))
diff --git a/arch/um/kernel/tt/syscall_user.c b/arch/um/kernel/tt/syscall_user.c
index 32fbe3248d2e1..e4e7e9c2224c9 100644
--- a/arch/um/kernel/tt/syscall_user.c
+++ b/arch/um/kernel/tt/syscall_user.c
@@ -6,7 +6,6 @@
#include <unistd.h>
#include <signal.h>
#include <errno.h>
-#include <sys/ptrace.h>
#include <asm/unistd.h>
#include "sysdep/ptrace.h"
#include "sigcontext.h"
@@ -22,15 +21,20 @@ void syscall_handler_tt(int sig, union uml_pt_regs *regs)
{
void *sc;
long result;
- int index, syscall;
+ int syscall;
+#ifdef UML_CONFIG_DEBUG_SYSCALL
+ int index;
+#endif
syscall = UPT_SYSCALL_NR(regs);
sc = UPT_SC(regs);
SC_START_SYSCALL(sc);
- index = record_syscall_start(syscall);
+#ifdef UML_CONFIG_DEBUG_SYSCALL
+ index = record_syscall_start(syscall);
+#endif
syscall_trace(regs, 0);
- result = execute_syscall(regs);
+ result = execute_syscall_tt(regs);
/* regs->sc may have changed while the system call ran (there may
* have been an interrupt or segfault), so it needs to be refreshed.
@@ -40,7 +44,9 @@ void syscall_handler_tt(int sig, union uml_pt_regs *regs)
SC_SET_SYSCALL_RETURN(sc, result);
syscall_trace(regs, 1);
- record_syscall_end(index, result);
+#ifdef UML_CONFIG_DEBUG_SYSCALL
+ record_syscall_end(index, result);
+#endif
}
void do_sigtrap(void *task)
@@ -66,7 +72,7 @@ void do_syscall(void *task, int pid, int local_using_sysemu)
return;
/* syscall number -1 in sysemu skips syscall restarting in host */
- if(ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET,
+ if(ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET,
local_using_sysemu ? -1 : __NR_getpid) < 0)
tracer_panic("do_syscall : Nullifying syscall failed, "
"errno = %d", errno);
diff --git a/arch/um/kernel/tt/tlb.c b/arch/um/kernel/tt/tlb.c
index 3bc35eea1da4a..203216ad86f1c 100644
--- a/arch/um/kernel/tt/tlb.c
+++ b/arch/um/kernel/tt/tlb.c
@@ -15,203 +15,55 @@
#include "user_util.h"
#include "mem_user.h"
#include "os.h"
+#include "tlb.h"
-static void fix_range(struct mm_struct *mm, unsigned long start_addr,
- unsigned long end_addr, int force)
+static void do_ops(int unused, struct host_vm_op *ops, int last)
{
- pgd_t *npgd;
- pud_t *npud;
- pmd_t *npmd;
- pte_t *npte;
- unsigned long addr, end;
- int r, w, x, err;
-
- if((current->thread.mode.tt.extern_pid != -1) &&
- (current->thread.mode.tt.extern_pid != os_getpid()))
- panic("fix_range fixing wrong address space, current = 0x%p",
- current);
- if(mm == NULL) return;
- for(addr=start_addr;addr<end_addr;){
- if(addr == TASK_SIZE){
- /* Skip over kernel text, kernel data, and physical
- * memory, which don't have ptes, plus kernel virtual
- * memory, which is flushed separately, and remap
- * the process stack. The only way to get here is
- * if (end_addr == STACK_TOP) > TASK_SIZE, which is
- * only true in the honeypot case.
- */
- addr = STACK_TOP - ABOVE_KMEM;
- continue;
- }
-
- npgd = pgd_offset(mm, addr);
- if(!pgd_present(*npgd)){
- if(force || pgd_newpage(*npgd)){
- end = addr + PGDIR_SIZE;
- if(end > end_addr)
- end = end_addr;
- err = os_unmap_memory((void *) addr,
- end - addr);
- if(err < 0)
- panic("munmap failed, errno = %d\n",
- -err);
- pgd_mkuptodate(*npgd);
- }
- addr += PGDIR_SIZE;
- continue;
- }
-
- npud = pud_offset(npgd, addr);
- if(!pud_present(*npud)){
- if(force || pud_newpage(*npud)){
- end = addr + PUD_SIZE;
- if(end > end_addr)
- end = end_addr;
- err = os_unmap_memory((void *) addr,
- end - addr);
- if(err < 0)
- panic("munmap failed, errno = %d\n",
- -err);
- pud_mkuptodate(*npud);
- }
- addr += PUD_SIZE;
- continue;
- }
-
- npmd = pmd_offset(npud, addr);
- if(!pmd_present(*npmd)){
- if(force || pmd_newpage(*npmd)){
- end = addr + PMD_SIZE;
- if(end > end_addr)
- end = end_addr;
- err = os_unmap_memory((void *) addr,
- end - addr);
- if(err < 0)
- panic("munmap failed, errno = %d\n",
- -err);
- pmd_mkuptodate(*npmd);
- }
- addr += PMD_SIZE;
- continue;
- }
-
- npte = pte_offset_kernel(npmd, addr);
- r = pte_read(*npte);
- w = pte_write(*npte);
- x = pte_exec(*npte);
- if(!pte_dirty(*npte))
- w = 0;
- if(!pte_young(*npte)){
- r = 0;
- w = 0;
+ struct host_vm_op *op;
+ int i;
+
+ for(i = 0; i <= last; i++){
+ op = &ops[i];
+ switch(op->type){
+ case MMAP:
+ os_map_memory((void *) op->u.mmap.addr, op->u.mmap.fd,
+ op->u.mmap.offset, op->u.mmap.len,
+ op->u.mmap.r, op->u.mmap.w,
+ op->u.mmap.x);
+ break;
+ case MUNMAP:
+ os_unmap_memory((void *) op->u.munmap.addr,
+ op->u.munmap.len);
+ break;
+ case MPROTECT:
+ protect_memory(op->u.mprotect.addr, op->u.munmap.len,
+ op->u.mprotect.r, op->u.mprotect.w,
+ op->u.mprotect.x, 1);
+ break;
+ default:
+ printk("Unknown op type %d in do_ops\n", op->type);
+ break;
}
- if(force || pte_newpage(*npte)){
- err = os_unmap_memory((void *) addr, PAGE_SIZE);
- if(err < 0)
- panic("munmap failed, errno = %d\n", -err);
- if(pte_present(*npte))
- map_memory(addr, pte_val(*npte) & PAGE_MASK,
- PAGE_SIZE, r, w, x);
- }
- else if(pte_newprot(*npte))
- protect_memory(addr, PAGE_SIZE, r, w, x, 1);
-
- *npte = pte_mkuptodate(*npte);
- addr += PAGE_SIZE;
}
}
-atomic_t vmchange_seq = ATOMIC_INIT(1);
-
-static void flush_kernel_vm_range(unsigned long start, unsigned long end,
- int update_seq)
+static void fix_range(struct mm_struct *mm, unsigned long start_addr,
+ unsigned long end_addr, int force)
{
- struct mm_struct *mm;
- pgd_t *pgd;
- pud_t *pud;
- pmd_t *pmd;
- pte_t *pte;
- unsigned long addr, last;
- int updated = 0, err;
-
- mm = &init_mm;
- for(addr = start; addr < end;){
- pgd = pgd_offset(mm, addr);
- if(!pgd_present(*pgd)){
- if(pgd_newpage(*pgd)){
- updated = 1;
- last = addr + PGDIR_SIZE;
- if(last > end)
- last = end;
- err = os_unmap_memory((void *) addr,
- last - addr);
- if(err < 0)
- panic("munmap failed, errno = %d\n",
- -err);
- }
- addr += PGDIR_SIZE;
- continue;
- }
+ if((current->thread.mode.tt.extern_pid != -1) &&
+ (current->thread.mode.tt.extern_pid != os_getpid()))
+ panic("fix_range fixing wrong address space, current = 0x%p",
+ current);
- pud = pud_offset(pgd, addr);
- if(!pud_present(*pud)){
- if(pud_newpage(*pud)){
- updated = 1;
- last = addr + PUD_SIZE;
- if(last > end)
- last = end;
- err = os_unmap_memory((void *) addr,
- last - addr);
- if(err < 0)
- panic("munmap failed, errno = %d\n",
- -err);
- }
- addr += PUD_SIZE;
- continue;
- }
-
- pmd = pmd_offset(pud, addr);
- if(!pmd_present(*pmd)){
- if(pmd_newpage(*pmd)){
- updated = 1;
- last = addr + PMD_SIZE;
- if(last > end)
- last = end;
- err = os_unmap_memory((void *) addr,
- last - addr);
- if(err < 0)
- panic("munmap failed, errno = %d\n",
- -err);
- }
- addr += PMD_SIZE;
- continue;
- }
-
- pte = pte_offset_kernel(pmd, addr);
- if(!pte_present(*pte) || pte_newpage(*pte)){
- updated = 1;
- err = os_unmap_memory((void *) addr,
- PAGE_SIZE);
- if(err < 0)
- panic("munmap failed, errno = %d\n",
- -err);
- if(pte_present(*pte))
- map_memory(addr,
- pte_val(*pte) & PAGE_MASK,
- PAGE_SIZE, 1, 1, 1);
- }
- else if(pte_newprot(*pte)){
- updated = 1;
- protect_memory(addr, PAGE_SIZE, 1, 1, 1, 1);
- }
- addr += PAGE_SIZE;
- }
- if(updated && update_seq) atomic_inc(&vmchange_seq);
+ fix_range_common(mm, start_addr, end_addr, force, 0, do_ops);
}
+atomic_t vmchange_seq = ATOMIC_INIT(1);
+
void flush_tlb_kernel_range_tt(unsigned long start, unsigned long end)
{
- flush_kernel_vm_range(start, end, 1);
+ if(flush_tlb_kernel_range_common(start, end))
+ atomic_inc(&vmchange_seq);
}
static void protect_vm_page(unsigned long addr, int w, int must_succeed)
@@ -268,8 +120,10 @@ void flush_tlb_range_tt(struct vm_area_struct *vma, unsigned long start,
/* Assumes that the range start ... end is entirely within
* either process memory or kernel vm
*/
- if((start >= start_vm) && (start < end_vm))
- flush_kernel_vm_range(start, end, 1);
+ if((start >= start_vm) && (start < end_vm)){
+ if(flush_tlb_kernel_range_common(start, end))
+ atomic_inc(&vmchange_seq);
+ }
else fix_range(vma->vm_mm, start, end, 0);
}
@@ -282,24 +136,14 @@ void flush_tlb_mm_tt(struct mm_struct *mm)
fix_range(mm, 0, STACK_TOP, 0);
seq = atomic_read(&vmchange_seq);
- if(current->thread.mode.tt.vm_seq == seq) return;
+ if(current->thread.mode.tt.vm_seq == seq)
+ return;
current->thread.mode.tt.vm_seq = seq;
- flush_kernel_vm_range(start_vm, end_vm, 0);
+ flush_tlb_kernel_range_common(start_vm, end_vm);
}
void force_flush_all_tt(void)
{
fix_range(current->mm, 0, STACK_TOP, 1);
- flush_kernel_vm_range(start_vm, end_vm, 0);
+ flush_tlb_kernel_range_common(start_vm, end_vm);
}
-
-/*
- * 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/tracer.c b/arch/um/kernel/tt/tracer.c
index 257a16e84da5b..7b5d937e59559 100644
--- a/arch/um/kernel/tt/tracer.c
+++ b/arch/um/kernel/tt/tracer.c
@@ -12,8 +12,6 @@
#include <sched.h>
#include <string.h>
#include <sys/mman.h>
-#include <sys/ptrace.h>
-#include <linux/ptrace.h>
#include <sys/time.h>
#include <sys/wait.h>
#include "user.h"
@@ -184,11 +182,13 @@ int tracing_pid = -1;
int tracer(int (*init_proc)(void *), void *sp)
{
void *task = NULL;
- unsigned long eip = 0;
int status, pid = 0, sig = 0, cont_type, tracing = 0, op = 0;
- int last_index, proc_id = 0, n, err, old_tracing = 0, strace = 0;
+ int proc_id = 0, n, err, old_tracing = 0, strace = 0;
int local_using_sysemu = 0;
-
+#ifdef UML_CONFIG_SYSCALL_DEBUG
+ unsigned long eip = 0;
+ int last_index;
+#endif
signal(SIGPIPE, SIG_IGN);
setup_tracer_winch();
tracing_pid = os_getpid();
@@ -279,22 +279,23 @@ int tracer(int (*init_proc)(void *), void *sp)
else if(WIFSTOPPED(status)){
proc_id = pid_to_processor_id(pid);
sig = WSTOPSIG(status);
+#ifdef UML_CONFIG_SYSCALL_DEBUG
if(signal_index[proc_id] == 1024){
signal_index[proc_id] = 0;
last_index = 1023;
}
else last_index = signal_index[proc_id] - 1;
- if(((sig == SIGPROF) || (sig == SIGVTALRM) ||
+ if(((sig == SIGPROF) || (sig == SIGVTALRM) ||
(sig == SIGALRM)) &&
(signal_record[proc_id][last_index].signal == sig)&&
(signal_record[proc_id][last_index].pid == pid))
signal_index[proc_id] = last_index;
signal_record[proc_id][signal_index[proc_id]].pid = pid;
gettimeofday(&signal_record[proc_id][signal_index[proc_id]].time, NULL);
- eip = ptrace(PTRACE_PEEKUSER, pid, PT_IP_OFFSET, 0);
+ eip = ptrace(PTRACE_PEEKUSR, pid, PT_IP_OFFSET, 0);
signal_record[proc_id][signal_index[proc_id]].addr = eip;
signal_record[proc_id][signal_index[proc_id]++].signal = sig;
-
+#endif
if(proc_id == -1){
sleeping_process_signal(pid, sig);
continue;
@@ -467,19 +468,6 @@ __uml_setup("debugtrace", uml_debugtrace_setup,
" the debug switch.\n\n"
);
-static int __init uml_honeypot_setup(char *line, int *add)
-{
- jail_setup("", add);
- honeypot = 1;
- return 0;
-}
-__uml_setup("honeypot", uml_honeypot_setup,
-"honeypot\n"
-" This makes UML put process stacks in the same location as they are\n"
-" on the host, allowing expoits such as stack smashes to work against\n"
-" UML. This implies 'jail'.\n\n"
-);
-
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically
diff --git a/arch/um/kernel/tt/trap_user.c b/arch/um/kernel/tt/trap_user.c
index 67fdef69d54ee..92a3820ca5439 100644
--- a/arch/um/kernel/tt/trap_user.c
+++ b/arch/um/kernel/tt/trap_user.c
@@ -20,8 +20,6 @@ void sig_handler_common_tt(int sig, void *sc_ptr)
struct signal_info *info;
int save_errno = errno, is_user;
- unprotect_kernel_mem();
-
/* 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,
* the process will die.
@@ -48,7 +46,6 @@ void sig_handler_common_tt(int sig, void *sc_ptr)
}
*r = save_regs;
errno = save_errno;
- if(is_user) protect_kernel_mem();
}
/*
diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c
index bffd8316f8923..5c49d88eed3d0 100644
--- a/arch/um/kernel/um_arch.c
+++ b/arch/um/kernel/um_arch.c
@@ -25,6 +25,7 @@
#include "asm/user.h"
#include "ubd_user.h"
#include "asm/current.h"
+#include "asm/setup.h"
#include "user_util.h"
#include "kern_util.h"
#include "kern.h"
@@ -40,6 +41,20 @@
#define DEFAULT_COMMAND_LINE "root=98:0"
+/* Changed in linux_main and setup_arch, which run before SMP is started */
+char command_line[COMMAND_LINE_SIZE] = { 0 };
+
+void add_arg(char *arg)
+{
+ if (strlen(command_line) + strlen(arg) + 1 > COMMAND_LINE_SIZE) {
+ printf("add_arg: Too many command line arguments!\n");
+ exit(1);
+ }
+ if(strlen(command_line) > 0)
+ strcat(command_line, " ");
+ strcat(command_line, arg);
+}
+
struct cpuinfo_um boot_cpu_data = {
.loops_per_jiffy = 0,
.ipi_pipe = { -1, -1 }
@@ -314,9 +329,11 @@ int linux_main(int argc, char **argv)
if((i == 1) && (argv[i][0] == ' ')) continue;
add = 1;
uml_checksetup(argv[i], &add);
- if(add) add_arg(saved_command_line, argv[i]);
+ if (add)
+ add_arg(argv[i]);
}
- if(have_root == 0) add_arg(saved_command_line, DEFAULT_COMMAND_LINE);
+ if(have_root == 0)
+ add_arg(DEFAULT_COMMAND_LINE);
mode_tt = force_tt ? 1 : !can_do_skas();
#ifndef CONFIG_MODE_TT
@@ -432,7 +449,7 @@ void __init setup_arch(char **cmdline_p)
{
notifier_chain_register(&panic_notifier_list, &panic_exit_notifier);
paging_init();
- strcpy(command_line, saved_command_line);
+ strlcpy(saved_command_line, command_line, COMMAND_LINE_SIZE);
*cmdline_p = command_line;
setup_hostinfo();
}
@@ -448,14 +465,3 @@ void __init check_bugs(void)
void apply_alternatives(void *start, void *end)
{
}
-
-/*
- * 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/user_util.c b/arch/um/kernel/user_util.c
index b2c7c5d2edf4d..954ff67cc8b3e 100644
--- a/arch/um/kernel/user_util.c
+++ b/arch/um/kernel/user_util.c
@@ -10,7 +10,6 @@
#include <setjmp.h>
#include <sys/mman.h>
#include <sys/stat.h>
-#include <sys/ptrace.h>
#include <sys/utsname.h>
#include <sys/param.h>
#include <sys/time.h>
@@ -29,23 +28,9 @@
#include "mem_user.h"
#include "init.h"
#include "helper.h"
+#include "ptrace_user.h"
#include "uml-config.h"
-#define COMMAND_LINE_SIZE _POSIX_ARG_MAX
-
-/* Changed in linux_main and setup_arch, which run before SMP is started */
-char command_line[COMMAND_LINE_SIZE] = { 0 };
-
-void add_arg(char *cmd_line, char *arg)
-{
- if (strlen(cmd_line) + strlen(arg) + 1 > COMMAND_LINE_SIZE) {
- printf("add_arg: Too much command line!\n");
- exit(1);
- }
- if(strlen(cmd_line) > 0) strcat(cmd_line, " ");
- strcat(cmd_line, arg);
-}
-
void stop(void)
{
while(1) sleep(1000000);
diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile
index f8378124be135..4ddf540284ce6 100644
--- a/arch/um/os-Linux/Makefile
+++ b/arch/um/os-Linux/Makefile
@@ -7,9 +7,7 @@ obj-y = elf_aux.o file.o process.o signal.o time.o tty.o user_syms.o drivers/ \
sys-$(SUBARCH)/
USER_OBJS := elf_aux.o file.o process.o signal.o time.o tty.o
-USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
-
-$(USER_OBJS) : %.o: %.c
- $(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
CFLAGS_user_syms.o += -DSUBARCH_$(SUBARCH)
+
+include arch/um/scripts/Makefile.rules
diff --git a/arch/um/os-Linux/drivers/Makefile b/arch/um/os-Linux/drivers/Makefile
index 52cae521eb65c..6c546dc9222bb 100644
--- a/arch/um/os-Linux/drivers/Makefile
+++ b/arch/um/os-Linux/drivers/Makefile
@@ -10,10 +10,4 @@ obj-y =
obj-$(CONFIG_UML_NET_ETHERTAP) += ethertap.o
obj-$(CONFIG_UML_NET_TUNTAP) += tuntap.o
-USER_SINGLE_OBJS = $(foreach f,$(patsubst %.o,%,$(obj-y)),$($(f)-objs))
-
-USER_OBJS = $(filter %_user.o,$(obj-y) $(USER_SINGLE_OBJS))
-USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
-
-$(USER_OBJS) : %.o: %.c
- $(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
+include arch/um/scripts/Makefile.rules
diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c
index 5d2c1a4d99a7d..ba9ca1cc790a5 100644
--- a/arch/um/os-Linux/process.c
+++ b/arch/um/os-Linux/process.c
@@ -8,9 +8,9 @@
#include <errno.h>
#include <signal.h>
#include <linux/unistd.h>
-#include <sys/ptrace.h>
#include <sys/mman.h>
#include <sys/wait.h>
+#include "ptrace_user.h"
#include "os.h"
#include "user.h"
#include "user_util.h"
diff --git a/arch/um/os-Linux/sys-i386/Makefile b/arch/um/os-Linux/sys-i386/Makefile
index bdfa841fca165..340ef26f5944c 100644
--- a/arch/um/os-Linux/sys-i386/Makefile
+++ b/arch/um/os-Linux/sys-i386/Makefile
@@ -5,7 +5,6 @@
obj-$(CONFIG_MODE_SKAS) = registers.o
-USER_OBJS := $(foreach file,$(obj-y),$(obj)/$(file))
+USER_OBJS := $(obj-y)
-$(USER_OBJS) : %.o: %.c
- $(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
+include arch/um/scripts/Makefile.rules
diff --git a/arch/um/os-Linux/sys-i386/registers.c b/arch/um/os-Linux/sys-i386/registers.c
index cbfbaf2ab78d8..148645b144805 100644
--- a/arch/um/os-Linux/sys-i386/registers.c
+++ b/arch/um/os-Linux/sys-i386/registers.c
@@ -5,7 +5,7 @@
#include <errno.h>
#include <string.h>
-#include <sys/ptrace.h>
+#include "sysdep/ptrace_user.h"
#include "sysdep/ptrace.h"
#include "uml-config.h"
#include "skas_ptregs.h"
@@ -27,6 +27,23 @@ void init_thread_registers(union uml_pt_regs *to)
memcpy(to->skas.xfp, exec_fpx_regs, sizeof(to->skas.xfp));
}
+/* XXX These need to use [GS]ETFPXREGS and copy_sc_{to,from}_user_skas needs
+ * to pass in a sufficiently large buffer
+ */
+int save_fp_registers(int pid, unsigned long *fp_regs)
+{
+ if(ptrace(PTRACE_GETFPREGS, pid, 0, fp_regs) < 0)
+ return(-errno);
+ return(0);
+}
+
+int restore_fp_registers(int pid, unsigned long *fp_regs)
+{
+ if(ptrace(PTRACE_SETFPREGS, pid, 0, fp_regs) < 0)
+ return(-errno);
+ return(0);
+}
+
static int move_registers(int pid, int int_op, union uml_pt_regs *regs,
int fp_op, unsigned long *fp_regs)
{
diff --git a/arch/um/os-Linux/sys-x86_64/Makefile b/arch/um/os-Linux/sys-x86_64/Makefile
index bdfa841fca165..340ef26f5944c 100644
--- a/arch/um/os-Linux/sys-x86_64/Makefile
+++ b/arch/um/os-Linux/sys-x86_64/Makefile
@@ -5,7 +5,6 @@
obj-$(CONFIG_MODE_SKAS) = registers.o
-USER_OBJS := $(foreach file,$(obj-y),$(obj)/$(file))
+USER_OBJS := $(obj-y)
-$(USER_OBJS) : %.o: %.c
- $(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
+include arch/um/scripts/Makefile.rules
diff --git a/arch/um/os-Linux/sys-x86_64/registers.c b/arch/um/os-Linux/sys-x86_64/registers.c
index 31b1f4fa67e0e..6286c974bbeb0 100644
--- a/arch/um/os-Linux/sys-x86_64/registers.c
+++ b/arch/um/os-Linux/sys-x86_64/registers.c
@@ -5,8 +5,7 @@
#include <errno.h>
#include <string.h>
-#include <sys/ptrace.h>
-#include "sysdep/ptrace.h"
+#include "ptrace_user.h"
#include "uml-config.h"
#include "skas_ptregs.h"
#include "registers.h"
diff --git a/arch/um/os-Linux/util/Makefile b/arch/um/os-Linux/util/Makefile
new file mode 100644
index 0000000000000..fb00ddf969bd9
--- /dev/null
+++ b/arch/um/os-Linux/util/Makefile
@@ -0,0 +1,4 @@
+hostprogs-y := mk_user_constants
+always := $(hostprogs-y)
+
+mk_user_constants-objs := mk_user_constants.o
diff --git a/arch/um/os-Linux/util/mk_user_constants.c b/arch/um/os-Linux/util/mk_user_constants.c
new file mode 100644
index 0000000000000..0933518aa8bd2
--- /dev/null
+++ b/arch/um/os-Linux/util/mk_user_constants.c
@@ -0,0 +1,29 @@
+#include <stdio.h>
+#include <asm/types.h>
+/* For some reason, x86_64 nowhere defines u64 and u32, even though they're
+ * used throughout the headers.
+ */
+typedef __u64 u64;
+typedef __u32 u32;
+#include <asm/user.h>
+
+int main(int argc, char **argv)
+{
+ printf("/*\n");
+ printf(" * Generated by mk_user_constants\n");
+ printf(" */\n");
+ printf("\n");
+ printf("#ifndef __UM_USER_CONSTANTS_H\n");
+ printf("#define __UM_USER_CONSTANTS_H\n");
+ printf("\n");
+ /* I'd like to use FRAME_SIZE from ptrace.h here, but that's wrong on
+ * x86_64 (216 vs 168 bytes). user_regs_struct is the correct size on
+ * both x86_64 and i386.
+ */
+ printf("#define UM_FRAME_SIZE %d\n", (int) sizeof(struct user_regs_struct));
+
+ printf("\n");
+ printf("#endif\n");
+
+ return(0);
+}
diff --git a/arch/um/scripts/Makefile.rules b/arch/um/scripts/Makefile.rules
new file mode 100644
index 0000000000000..143f6fea07632
--- /dev/null
+++ b/arch/um/scripts/Makefile.rules
@@ -0,0 +1,13 @@
+# ===========================================================================
+# arch/um: Generic definitions
+# ===========================================================================
+
+USER_SINGLE_OBJS = $(foreach f,$(patsubst %.o,%,$(obj-y) $(obj-m)),$($(f)-objs))
+USER_OBJS += $(filter %_user.o,$(obj-y) $(obj-m) $(USER_SINGLE_OBJS))
+
+USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
+
+$(USER_OBJS): c_flags = -Wp,-MD,$(depfile) $(USER_CFLAGS) $(CFLAGS_$(notdir $@))
+
+quiet_cmd_make_link = SYMLINK $@
+cmd_make_link = rm -f $@; ln -sf $(srctree)/arch/$(SUBARCH)/$($(notdir $@)-dir)/$(notdir $@) $@
diff --git a/arch/um/sys-i386/Makefile b/arch/um/sys-i386/Makefile
index 8a0994b696b00..71b47e6186051 100644
--- a/arch/um/sys-i386/Makefile
+++ b/arch/um/sys-i386/Makefile
@@ -5,7 +5,8 @@ obj-$(CONFIG_HIGHMEM) += highmem.o
obj-$(CONFIG_MODULES) += module.o
USER_OBJS := bugs.o ptrace_user.o sigcontext.o fault.o
-USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
+
+include arch/um/scripts/Makefile.rules
SYMLINKS = bitops.c semaphore.c highmem.c module.c
@@ -13,22 +14,16 @@ SYMLINKS = bitops.c semaphore.c highmem.c module.c
# complete paths like $(src)/$f.
clean-files := $(SYMLINKS)
-SYMLINKS := $(foreach f,$(SYMLINKS),$(src)/$f)
+targets += $(SYMLINKS)
+
+SYMLINKS := $(foreach f,$(SYMLINKS),$(obj)/$f)
bitops.c-dir = lib
semaphore.c-dir = kernel
highmem.c-dir = mm
module.c-dir = kernel
-define make_link
- -rm -f $1
- ln -sf $(TOPDIR)/arch/i386/$($(notdir $1)-dir)/$(notdir $1) $1
-endef
-
-$(USER_OBJS) : %.o: %.c
- $(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
-
-$(SYMLINKS):
- $(call make_link,$@)
+$(SYMLINKS): FORCE
+ $(call if_changed,make_link)
subdir- := util
diff --git a/arch/um/sys-i386/ldt.c b/arch/um/sys-i386/ldt.c
index e97b98806af79..31bcb2f997d4a 100644
--- a/arch/um/sys-i386/ldt.c
+++ b/arch/um/sys-i386/ldt.c
@@ -17,7 +17,7 @@ extern int modify_ldt(int func, void *ptr, unsigned long bytecount);
int sys_modify_ldt_tt(int func, void __user *ptr, unsigned long bytecount)
{
- if (verify_area(VERIFY_READ, ptr, bytecount))
+ if (!access_ok(VERIFY_READ, ptr, bytecount))
return -EFAULT;
return modify_ldt(func, ptr, bytecount);
diff --git a/arch/um/sys-i386/ptrace.c b/arch/um/sys-i386/ptrace.c
index c6a1bba337eac..e470d28cdf84e 100644
--- a/arch/um/sys-i386/ptrace.c
+++ b/arch/um/sys-i386/ptrace.c
@@ -10,7 +10,7 @@
#include "asm/ptrace.h"
#include "asm/uaccess.h"
#include "asm/unistd.h"
-#include "ptrace_user.h"
+#include "sysdep/ptrace.h"
#include "sysdep/sigcontext.h"
#include "sysdep/sc.h"
diff --git a/arch/um/sys-i386/ptrace_user.c b/arch/um/sys-i386/ptrace_user.c
index 69aa6d6d111cf..7c376c95de506 100644
--- a/arch/um/sys-i386/ptrace_user.c
+++ b/arch/um/sys-i386/ptrace_user.c
@@ -7,8 +7,8 @@
#include <errno.h>
#include <unistd.h>
#include <linux/stddef.h>
-#include <sys/ptrace.h>
-#include <asm/ptrace.h>
+#include "ptrace_user.h"
+/* Grr, asm/user.h includes asm/ptrace.h, so has to follow ptrace_user.h */
#include <asm/user.h>
#include "kern_util.h"
#include "sysdep/thread.h"
@@ -52,7 +52,7 @@ static void write_debugregs(int pid, unsigned long *regs)
nregs = sizeof(dummy->u_debugreg)/sizeof(dummy->u_debugreg[0]);
for(i = 0; i < nregs; i++){
if((i == 4) || (i == 5)) continue;
- if(ptrace(PTRACE_POKEUSER, pid, &dummy->u_debugreg[i],
+ if(ptrace(PTRACE_POKEUSR, pid, &dummy->u_debugreg[i],
regs[i]) < 0)
printk("write_debugregs - ptrace failed on "
"register %d, value = 0x%x, errno = %d\n", i,
@@ -68,7 +68,7 @@ static void read_debugregs(int pid, unsigned long *regs)
dummy = NULL;
nregs = sizeof(dummy->u_debugreg)/sizeof(dummy->u_debugreg[0]);
for(i = 0; i < nregs; i++){
- regs[i] = ptrace(PTRACE_PEEKUSER, pid,
+ regs[i] = ptrace(PTRACE_PEEKUSR, pid,
&dummy->u_debugreg[i], 0);
}
}
diff --git a/arch/um/sys-i386/signal.c b/arch/um/sys-i386/signal.c
index 0cb4c86b5c2b5..76ba87254b251 100644
--- a/arch/um/sys-i386/signal.c
+++ b/arch/um/sys-i386/signal.c
@@ -11,8 +11,8 @@
#include "asm/unistd.h"
#include "frame_kern.h"
#include "signal_user.h"
-#include "ptrace_user.h"
#include "sigcontext.h"
+#include "registers.h"
#include "mode.h"
#ifdef CONFIG_MODE_SKAS
@@ -51,7 +51,7 @@ static int copy_sc_from_user_skas(struct pt_regs *regs,
regs->regs.skas.fault_type = FAULT_WRITE(sc.err);
regs->regs.skas.trap_type = sc.trapno;
- err = ptrace_setfpregs(userspace_pid[0], fpregs);
+ err = restore_fp_registers(userspace_pid[0], fpregs);
if(err < 0){
printk("copy_sc_from_user_skas - PTRACE_SETFPREGS failed, "
"errno = %d\n", err);
@@ -90,7 +90,7 @@ int copy_sc_to_user_skas(struct sigcontext *to, struct _fpstate *to_fp,
sc.err = TO_SC_ERR(fault_type);
sc.trapno = regs->regs.skas.trap_type;
- err = ptrace_getfpregs(userspace_pid[0], fpregs);
+ err = save_fp_registers(userspace_pid[0], fpregs);
if(err < 0){
printk("copy_sc_to_user_skas - PTRACE_GETFPREGS failed, "
"errno = %d\n", err);
@@ -108,6 +108,15 @@ int copy_sc_to_user_skas(struct sigcontext *to, struct _fpstate *to_fp,
#endif
#ifdef CONFIG_MODE_TT
+
+/* These copy a sigcontext to/from userspace. They copy the fpstate pointer,
+ * blowing away the old, good one. So, that value is saved, and then restored
+ * after the sigcontext copy. In copy_from, the variable holding the saved
+ * fpstate pointer, and the sigcontext that it should be restored to are both
+ * in the kernel, so we can just restore using an assignment. In copy_to, the
+ * saved pointer is in the kernel, but the sigcontext is in userspace, so we
+ * copy_to_user it.
+ */
int copy_sc_from_user_tt(struct sigcontext *to, struct sigcontext *from,
int fpsize)
{
@@ -120,11 +129,9 @@ int copy_sc_from_user_tt(struct sigcontext *to, struct sigcontext *from,
sigs = to->oldmask;
err = copy_from_user(to, from, sizeof(*to));
to->oldmask = sigs;
- if(to_fp != NULL){
- err |= copy_from_user(&to->fpstate, &to_fp,
- sizeof(to->fpstate));
+ to->fpstate = to_fp;
+ if(to_fp != NULL)
err |= copy_from_user(to_fp, from_fp, fpsize);
- }
return(err);
}
@@ -138,8 +145,7 @@ int copy_sc_to_user_tt(struct sigcontext *to, struct _fpstate *fp,
from_fp = from->fpstate;
err = copy_to_user(to, from, sizeof(*to));
if(from_fp != NULL){
- err |= copy_to_user(&to->fpstate, &to_fp,
- sizeof(to->fpstate));
+ err |= copy_to_user(&to->fpstate, &to_fp, sizeof(to->fpstate));
err |= copy_to_user(to_fp, from_fp, fpsize);
}
return(err);
@@ -211,8 +217,8 @@ int setup_signal_stack_sc(unsigned long stack_top, int sig,
stack_top &= -8UL;
frame = (struct sigframe *) stack_top - 1;
- if(verify_area(VERIFY_WRITE, frame, sizeof(*frame)))
- return(1);
+ if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
+ return 1;
restorer = (void *) frame->retcode;
if(ka->sa.sa_flags & SA_RESTORER)
@@ -261,8 +267,8 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
stack_top &= -8UL;
frame = (struct rt_sigframe *) stack_top - 1;
- if(verify_area(VERIFY_WRITE, frame, sizeof(*frame)))
- return(1);
+ if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
+ return 1;
restorer = (void *) frame->retcode;
if(ka->sa.sa_flags & SA_RESTORER)
@@ -303,7 +309,7 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
long sys_sigreturn(struct pt_regs regs)
{
- unsigned long __user sp = PT_REGS_SP(&current->thread.regs);
+ unsigned long sp = PT_REGS_SP(&current->thread.regs);
struct sigframe __user *frame = (struct sigframe *)(sp - 8);
sigset_t set;
struct sigcontext __user *sc = &frame->sc;
diff --git a/arch/um/sys-i386/syscalls.c b/arch/um/sys-i386/syscalls.c
index dd58b5511e9b6..335e2d89504d8 100644
--- a/arch/um/sys-i386/syscalls.c
+++ b/arch/um/sys-i386/syscalls.c
@@ -88,7 +88,7 @@ long sys_clone(unsigned long clone_flags, unsigned long newsp,
* This is really horribly ugly.
*/
long sys_ipc (uint call, int first, int second,
- int third, void *__user ptr, long fifth)
+ int third, void __user *ptr, long fifth)
{
int version, ret;
@@ -175,7 +175,7 @@ long sys_sigaction(int sig, const struct old_sigaction __user *act,
if (act) {
old_sigset_t mask;
- if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
+ if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
__get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
__get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
return -EFAULT;
@@ -187,7 +187,7 @@ long sys_sigaction(int sig, const struct old_sigaction __user *act,
ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
if (!ret && oact) {
- if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
+ if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
__put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
__put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
return -EFAULT;
diff --git a/arch/um/sys-ppc/ptrace_user.c b/arch/um/sys-ppc/ptrace_user.c
index 654fddda06d3f..ff0b9c077a13c 100644
--- a/arch/um/sys-ppc/ptrace_user.c
+++ b/arch/um/sys-ppc/ptrace_user.c
@@ -1,4 +1,3 @@
-#include <sys/ptrace.h>
#include <errno.h>
#include <asm/ptrace.h>
#include "sysdep/ptrace.h"
@@ -8,7 +7,7 @@ int ptrace_getregs(long pid, unsigned long *regs_out)
int i;
for (i=0; i < sizeof(struct sys_pt_regs)/sizeof(PPC_REG); ++i) {
errno = 0;
- regs_out->regs[i] = ptrace(PTRACE_PEEKUSER, pid, i*4, 0);
+ regs_out->regs[i] = ptrace(PTRACE_PEEKUSR, pid, i*4, 0);
if (errno) {
return -errno;
}
@@ -21,7 +20,7 @@ int ptrace_setregs(long pid, unsigned long *regs_in)
int i;
for (i=0; i < sizeof(struct sys_pt_regs)/sizeof(PPC_REG); ++i) {
if (i != 34 /* FIXME: PT_ORIG_R3 */ && i <= PT_MQ) {
- if (ptrace(PTRACE_POKEUSER, pid, i*4, regs_in->regs[i]) < 0) {
+ if (ptrace(PTRACE_POKEUSR, pid, i*4, regs_in->regs[i]) < 0) {
return -errno;
}
}
diff --git a/arch/um/sys-x86_64/Makefile b/arch/um/sys-x86_64/Makefile
index 1ec504b768109..2129e3143559d 100644
--- a/arch/um/sys-x86_64/Makefile
+++ b/arch/um/sys-x86_64/Makefile
@@ -9,14 +9,20 @@ lib-y = bitops.o bugs.o csum-partial.o delay.o fault.o mem.o memcpy.o \
syscalls.o sysrq.o thunk.o
USER_OBJS := ptrace_user.o sigcontext.o
-USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
+
+include arch/um/scripts/Makefile.rules
SYMLINKS = bitops.c csum-copy.S csum-partial.c csum-wrappers.c memcpy.S \
semaphore.c thunk.S
-SYMLINKS := $(foreach f,$(SYMLINKS),$(src)/$f)
+# this needs to be before the foreach, because clean-files does not accept
+# complete paths like $(src)/$f.
clean-files := $(SYMLINKS)
+targets += $(SYMLINKS)
+
+SYMLINKS := $(foreach f,$(SYMLINKS),$(obj)/$f)
+
bitops.c-dir = lib
csum-copy.S-dir = lib
csum-partial.c-dir = lib
@@ -25,15 +31,7 @@ memcpy.S-dir = lib
semaphore.c-dir = kernel
thunk.S-dir = lib
-define make_link
- -rm -f $1
- ln -sf $(TOPDIR)/arch/x86_64/$($(notdir $1)-dir)/$(notdir $1) $1
-endef
-
-$(SYMLINKS):
- $(call make_link,$@)
-
-$(USER_OBJS) : %.o: %.c
- $(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
+$(SYMLINKS): FORCE
+ $(call if_changed,make_link)
CFLAGS_csum-partial.o := -Dcsum_partial=arch_csum_partial
diff --git a/arch/um/sys-x86_64/ptrace_user.c b/arch/um/sys-x86_64/ptrace_user.c
index e1f8bacc5f1ae..12e404c6fa467 100644
--- a/arch/um/sys-x86_64/ptrace_user.c
+++ b/arch/um/sys-x86_64/ptrace_user.c
@@ -6,9 +6,7 @@
#include <stddef.h>
#include <errno.h>
-#define __FRAME_OFFSETS
-#include <sys/ptrace.h>
-#include <asm/ptrace.h>
+#include "ptrace_user.h"
#include "user.h"
#include "kern_constants.h"
@@ -42,23 +40,12 @@ void arch_enter_kernel(void *task, int pid)
void arch_leave_kernel(void *task, int pid)
{
#ifdef UM_USER_CS
- if(ptrace(PTRACE_POKEUSER, pid, CS, UM_USER_CS) < 0)
- tracer_panic("POKEUSER CS failed");
+ if(ptrace(PTRACE_POKEUSR, pid, CS, UM_USER_CS) < 0)
+ printk("POKEUSR CS failed");
#endif
- if(ptrace(PTRACE_POKEUSER, pid, DS, __USER_DS) < 0)
- tracer_panic("POKEUSER DS failed");
- if(ptrace(PTRACE_POKEUSER, pid, ES, __USER_DS) < 0)
- tracer_panic("POKEUSER ES failed");
+ if(ptrace(PTRACE_POKEUSR, pid, DS, __USER_DS) < 0)
+ printk("POKEUSR DS failed");
+ if(ptrace(PTRACE_POKEUSR, pid, ES, __USER_DS) < 0)
+ printk("POKEUSR ES failed");
}
-
-/*
- * 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-x86_64/signal.c b/arch/um/sys-x86_64/signal.c
index a5682f1d020dd..5bc5a0d796e5d 100644
--- a/arch/um/sys-x86_64/signal.c
+++ b/arch/um/sys-x86_64/signal.c
@@ -237,7 +237,7 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
long sys_rt_sigreturn(struct pt_regs *regs)
{
- unsigned long __user sp = PT_REGS_SP(&current->thread.regs);
+ unsigned long sp = PT_REGS_SP(&current->thread.regs);
struct rt_sigframe __user *frame =
(struct rt_sigframe __user *)(sp - 8);
struct ucontext __user *uc = &frame->uc;
diff --git a/arch/um/sys-x86_64/syscalls.c b/arch/um/sys-x86_64/syscalls.c
index 4c61dcc0901ff..68205a03364ca 100644
--- a/arch/um/sys-x86_64/syscalls.c
+++ b/arch/um/sys-x86_64/syscalls.c
@@ -29,22 +29,18 @@ long sys_modify_ldt_tt(int func, void *ptr, unsigned long bytecount)
/* XXX This should check VERIFY_WRITE depending on func, check this
* in i386 as well.
*/
- if(verify_area(VERIFY_READ, ptr, bytecount))
- return(-EFAULT);
+ if (!access_ok(VERIFY_READ, ptr, bytecount))
+ return -EFAULT;
return(modify_ldt(func, ptr, bytecount));
}
#endif
#ifdef CONFIG_MODE_SKAS
-extern int userspace_pid;
-
-#ifndef __NR_mm_indirect
-#define __NR_mm_indirect 241
-#endif
+extern int userspace_pid[];
long sys_modify_ldt_skas(int func, void *ptr, unsigned long bytecount)
{
- unsigned long args[6];
+ struct ptrace_ldt ldt;
void *buf;
int res, n;
@@ -66,12 +62,11 @@ long sys_modify_ldt_skas(int func, void *ptr, unsigned long bytecount)
goto out;
}
- args[0] = func;
- args[1] = (unsigned long) buf;
- args[2] = bytecount;
- res = syscall(__NR_mm_indirect, &current->mm->context.u,
- __NR_modify_ldt, args);
-
+ ldt = ((struct ptrace_ldt) { .func = func,
+ .ptr = buf,
+ .bytecount = bytecount });
+#warning Need to look up userspace_pid by cpu
+ res = ptrace(PTRACE_LDT, userspace_pid[0], 0, (unsigned long) &ldt);
if(res < 0)
goto out;
diff --git a/arch/v850/kernel/setup.c b/arch/v850/kernel/setup.c
index dacc9b33145b1..c41d72b01b880 100644
--- a/arch/v850/kernel/setup.c
+++ b/arch/v850/kernel/setup.c
@@ -283,5 +283,4 @@ init_mem_alloc (unsigned long ram_start, unsigned long ram_len)
NODE_DATA(0)->node_mem_map = NULL;
free_area_init_node (0, NODE_DATA(0), zones_size,
ADDR_TO_PAGE (PAGE_OFFSET), 0);
- mem_map = NODE_DATA(0)->node_mem_map;
}
diff --git a/arch/v850/kernel/signal.c b/arch/v850/kernel/signal.c
index 9432ff84ac19b..37061e32e1a42 100644
--- a/arch/v850/kernel/signal.c
+++ b/arch/v850/kernel/signal.c
@@ -102,7 +102,7 @@ sys_sigaction(int sig, const struct old_sigaction *act,
if (act) {
old_sigset_t mask;
- if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
+ if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
__get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
__get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
return -EFAULT;
@@ -114,7 +114,7 @@ sys_sigaction(int sig, const struct old_sigaction *act,
ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
if (!ret && oact) {
- if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
+ if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
__put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
__put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
return -EFAULT;
@@ -178,7 +178,7 @@ asmlinkage int sys_sigreturn(struct pt_regs *regs)
sigset_t set;
int rval;
- if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
+ if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
goto badframe;
if (__get_user(set.sig[0], &frame->sc.oldmask)
@@ -209,7 +209,7 @@ asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
stack_t st;
int rval;
- if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
+ if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
goto badframe;
if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
diff --git a/arch/v850/kernel/syscalls.c b/arch/v850/kernel/syscalls.c
index ff47395ac8ea0..9224cb65f6ec8 100644
--- a/arch/v850/kernel/syscalls.c
+++ b/arch/v850/kernel/syscalls.c
@@ -62,7 +62,7 @@ sys_ipc (uint call, int first, int second, int third, void *ptr, long fifth)
if (!ptr)
break;
- if ((ret = verify_area (VERIFY_READ, ptr, sizeof(long)))
+ if ((ret = access_ok(VERIFY_READ, ptr, sizeof(long)) ? 0 : -EFAULT)
|| (ret = get_user(fourth.__pad, (void **)ptr)))
break;
ret = sys_semctl (first, second, third, fourth);
@@ -78,7 +78,7 @@ sys_ipc (uint call, int first, int second, int third, void *ptr, long fifth)
if (!ptr)
break;
- if ((ret = verify_area (VERIFY_READ, ptr, sizeof(tmp)))
+ if ((ret = access_ok(VERIFY_READ, ptr, sizeof(tmp)) ? 0 : -EFAULT)
|| (ret = copy_from_user(&tmp,
(struct ipc_kludge *) ptr,
sizeof (tmp))))
@@ -104,8 +104,8 @@ sys_ipc (uint call, int first, int second, int third, void *ptr, long fifth)
default: {
ulong raddr;
- if ((ret = verify_area(VERIFY_WRITE, (ulong*) third,
- sizeof(ulong))))
+ if ((ret = access_ok(VERIFY_WRITE, (ulong*) third,
+ sizeof(ulong)) ? 0 : -EFAULT))
break;
ret = do_shmat (first, (char *) ptr, second, &raddr);
if (ret)
diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig
index f7a85824d6f5a..80c38c5d71fe4 100644
--- a/arch/x86_64/Kconfig
+++ b/arch/x86_64/Kconfig
@@ -53,23 +53,6 @@ config EARLY_PRINTK
bool
default y
-config HPET_TIMER
- bool
- default y
- help
- Use the IA-PC HPET (High Precision Event Timer) to manage
- time in preference to the PIT and RTC, if a HPET is
- present. The HPET provides a stable time base on SMP
- systems, unlike the RTC, but it is more expensive to access,
- as it is off-chip. You can find the HPET spec at
- <http://www.intel.com/labs/platcomp/hpet/hpetspec.htm>.
-
- If unsure, say Y.
-
-config HPET_EMULATE_RTC
- bool "Provide RTC interrupt"
- depends on HPET_TIMER && RTC=y
-
config GENERIC_ISA_DMA
bool
default y
@@ -254,7 +237,7 @@ config PREEMPT_BKL
config SCHED_SMT
bool "SMT (Hyperthreading) scheduler support"
depends on SMP
- default off
+ default n
help
SMT scheduler support improves the CPU scheduler's decision making
when dealing with Intel Pentium 4 chips with HyperThreading at a
@@ -309,6 +292,21 @@ config NR_CPUS
This is purely to save memory - each supported CPU requires
memory in the static kernel configuration.
+config HPET_TIMER
+ bool
+ default y
+ help
+ Use the IA-PC HPET (High Precision Event Timer) to manage
+ time in preference to the PIT and RTC, if a HPET is
+ present. The HPET provides a stable time base on SMP
+ systems, unlike the TSC, but it is more expensive to access,
+ as it is off-chip. You can find the HPET spec at
+ <http://www.intel.com/labs/platcomp/hpet/hpetspec.htm>.
+
+config HPET_EMULATE_RTC
+ bool "Provide RTC interrupt"
+ depends on HPET_TIMER && RTC=y
+
config GART_IOMMU
bool "IOMMU support"
depends on PCI
@@ -350,6 +348,24 @@ config X86_MCE_INTEL
help
Additional support for intel specific MCE features such as
the thermal monitor.
+
+config SECCOMP
+ bool "Enable seccomp to safely compute untrusted bytecode"
+ depends on PROC_FS
+ default y
+ help
+ This kernel feature is useful for number crunching applications
+ that may need to compute untrusted bytecode during their
+ execution. By using pipes or other transports made available to
+ the process as file descriptors supporting the read/write
+ syscalls, it's possible to isolate those applications in
+ their own address space using seccomp. Once seccomp is
+ enabled via /proc/<pid>/seccomp, it cannot be disabled
+ and the task is only allowed to execute a few safe syscalls
+ defined by each seccomp mode.
+
+ If unsure, say Y. Only embedded should say N here.
+
endmenu
#
@@ -399,6 +415,8 @@ config UNORDERED_IO
from i386. Requires that the driver writer used memory barriers
properly.
+source "drivers/pci/pcie/Kconfig"
+
source "drivers/pci/Kconfig"
source "drivers/pcmcia/Kconfig"
diff --git a/arch/x86_64/defconfig b/arch/x86_64/defconfig
index 941e9b9300811..9ce51dee30b30 100644
--- a/arch/x86_64/defconfig
+++ b/arch/x86_64/defconfig
@@ -1,13 +1,14 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.10-bk7
-# Fri Jan 7 06:27:52 2005
+# Linux kernel version: 2.6.11-bk7
+# Sat Mar 12 23:43:44 2005
#
CONFIG_X86_64=y
CONFIG_64BIT=y
CONFIG_X86=y
CONFIG_MMU=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_X86_CMPXCHG=y
CONFIG_EARLY_PRINTK=y
CONFIG_HPET_TIMER=y
@@ -37,10 +38,12 @@ CONFIG_LOG_BUF_SHIFT=18
CONFIG_KOBJECT_UEVENT=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
+# CONFIG_CPUSETS is not set
# CONFIG_EMBEDDED is not set
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -50,6 +53,7 @@ CONFIG_CC_ALIGN_LABELS=0
CONFIG_CC_ALIGN_LOOPS=0
CONFIG_CC_ALIGN_JUMPS=0
# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
#
# Loadable module support
@@ -93,6 +97,7 @@ CONFIG_GART_IOMMU=y
CONFIG_SWIOTLB=y
CONFIG_X86_MCE=y
CONFIG_X86_MCE_INTEL=y
+CONFIG_SECCOMP=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
@@ -137,13 +142,13 @@ CONFIG_ACPI_SYSTEM=y
#
CONFIG_CPU_FREQ=y
# CONFIG_CPU_FREQ_DEBUG is not set
-CONFIG_CPU_FREQ_PROC_INTF=y
+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 is not set
CONFIG_CPU_FREQ_GOV_USERSPACE=y
-CONFIG_CPU_FREQ_24_API=y
CONFIG_CPU_FREQ_GOV_ONDEMAND=y
CONFIG_CPU_FREQ_TABLE=y
@@ -172,6 +177,20 @@ CONFIG_PCI_MSI=y
# CONFIG_PCI_NAMES is not set
#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
# Executable file formats / Emulations
#
CONFIG_BINFMT_ELF=y
@@ -191,6 +210,7 @@ CONFIG_UID16=y
#
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
# CONFIG_DEBUG_DRIVER is not set
#
@@ -216,6 +236,7 @@ CONFIG_BLK_DEV_FD=y
# CONFIG_BLK_CPQ_CISS_DA is not set
# CONFIG_BLK_DEV_DAC960 is not set
# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
# CONFIG_BLK_DEV_NBD is not set
@@ -236,6 +257,7 @@ CONFIG_IOSCHED_NOOP=y
CONFIG_IOSCHED_AS=y
CONFIG_IOSCHED_DEADLINE=y
CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
#
# ATA/ATAPI/MFM/RLL support
@@ -352,6 +374,7 @@ CONFIG_SCSI_SATA=y
CONFIG_SCSI_ATA_PIIX=y
# CONFIG_SCSI_SATA_NV is not set
# CONFIG_SCSI_SATA_PROMISE is not set
+# CONFIG_SCSI_SATA_QSTOR is not set
# CONFIG_SCSI_SATA_SX4 is not set
# CONFIG_SCSI_SATA_SIL is not set
# CONFIG_SCSI_SATA_SIS is not set
@@ -514,7 +537,7 @@ CONFIG_FORCEDETH=y
# CONFIG_NATSEMI is not set
# CONFIG_NE2K_PCI is not set
CONFIG_8139CP=m
-CONFIG_8139TOO=m
+CONFIG_8139TOO=y
# CONFIG_8139TOO_PIO is not set
# CONFIG_8139TOO_TUNE_TWISTER is not set
# CONFIG_8139TOO_8129 is not set
@@ -597,18 +620,6 @@ CONFIG_INPUT_EVDEV=y
# CONFIG_INPUT_EVBUG is not set
#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-CONFIG_SERIO_I8042=y
-# CONFIG_SERIO_SERPORT is not set
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PCIPS2 is not set
-# CONFIG_SERIO_RAW is not set
-
-#
# Input Device Drivers
#
CONFIG_INPUT_KEYBOARD=y
@@ -626,6 +637,19 @@ CONFIG_MOUSE_PS2=y
# CONFIG_INPUT_MISC is not set
#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
+#
# Character devices
#
CONFIG_VT=y
@@ -672,7 +696,6 @@ CONFIG_RTC=y
#
CONFIG_AGP=y
CONFIG_AGP_AMD64=y
-# CONFIG_AGP_INTEL_MCH is not set
# CONFIG_DRM is not set
# CONFIG_MWAVE is not set
CONFIG_RAW_DRIVER=y
@@ -683,6 +706,11 @@ CONFIG_MAX_RAW_DEVS=256
CONFIG_HANGCHECK_TIMER=y
#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
# I2C support
#
# CONFIG_I2C is not set
@@ -711,7 +739,7 @@ CONFIG_HANGCHECK_TIMER=y
# Graphics support
#
# CONFIG_FB is not set
-# CONFIG_VIDEO_SELECT is not set
+CONFIG_VIDEO_SELECT=y
#
# Console display driver support
@@ -779,6 +807,8 @@ CONFIG_USB_EHCI_HCD=y
# CONFIG_USB_EHCI_SPLIT_ISO is not set
# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
CONFIG_USB_UHCI_HCD=y
# CONFIG_USB_SL811_HCD is not set
@@ -801,7 +831,7 @@ CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_FREECOM is not set
# CONFIG_USB_STORAGE_ISD200 is not set
# CONFIG_USB_STORAGE_DPCM is not set
-# CONFIG_USB_STORAGE_HP8200e 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
@@ -827,7 +857,6 @@ CONFIG_USB_HIDINPUT=y
#
# CONFIG_USB_MDC800 is not set
# CONFIG_USB_MICROTEK is not set
-# CONFIG_USB_HPUSBSCSI is not set
#
# USB Multimedia devices
@@ -846,6 +875,7 @@ CONFIG_USB_HIDINPUT=y
# 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
@@ -861,7 +891,6 @@ CONFIG_USB_HIDINPUT=y
#
# CONFIG_USB_EMI62 is not set
# CONFIG_USB_EMI26 is not set
-# CONFIG_USB_TIGL is not set
# CONFIG_USB_AUERSWALD is not set
# CONFIG_USB_RIO500 is not set
# CONFIG_USB_LEGOTOWER is not set
@@ -870,6 +899,8 @@ CONFIG_USB_HIDINPUT=y
# 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_TEST is not set
#
@@ -918,6 +949,10 @@ CONFIG_REISERFS_FS_POSIX_ACL=y
# CONFIG_REISERFS_FS_SECURITY is not set
# CONFIG_JFS_FS is not set
CONFIG_FS_POSIX_ACL=y
+
+#
+# XFS support
+#
# CONFIG_XFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
@@ -1059,12 +1094,14 @@ CONFIG_OPROFILE=y
#
CONFIG_DEBUG_KERNEL=y
CONFIG_MAGIC_SYSRQ=y
+# CONFIG_PRINTK_TIME is not set
# CONFIG_SCHEDSTATS is not set
# CONFIG_DEBUG_SLAB is not set
# CONFIG_DEBUG_SPINLOCK is not set
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
# CONFIG_DEBUG_KOBJECT is not set
# CONFIG_DEBUG_INFO is not set
+CONFIG_DEBUG_FS=y
CONFIG_INIT_DEBUG=y
# CONFIG_IOMMU_DEBUG is not set
CONFIG_KPROBES=y
diff --git a/arch/x86_64/ia32/ia32_aout.c b/arch/x86_64/ia32/ia32_aout.c
index 2014f2113cd8a..1965efc974dc4 100644
--- a/arch/x86_64/ia32/ia32_aout.c
+++ b/arch/x86_64/ia32/ia32_aout.c
@@ -182,9 +182,9 @@ static int aout_core_dump(long signr, struct pt_regs * regs, struct file *file)
/* make sure we actually have a data and stack area to dump */
set_fs(USER_DS);
- if (verify_area(VERIFY_READ, (void *) (unsigned long)START_DATA(dump), dump.u_dsize << PAGE_SHIFT))
+ if (!access_ok(VERIFY_READ, (void *) (unsigned long)START_DATA(dump), dump.u_dsize << PAGE_SHIFT))
dump.u_dsize = 0;
- if (verify_area(VERIFY_READ, (void *) (unsigned long)START_STACK(dump), dump.u_ssize << PAGE_SHIFT))
+ if (!access_ok(VERIFY_READ, (void *) (unsigned long)START_STACK(dump), dump.u_ssize << PAGE_SHIFT))
dump.u_ssize = 0;
set_fs(KERNEL_DS);
@@ -313,7 +313,7 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
(current->mm->start_brk = N_BSSADDR(ex));
current->mm->free_area_cache = TASK_UNMAPPED_BASE;
- current->mm->rss = 0;
+ set_mm_counter(current->mm, rss, 0);
current->mm->mmap = NULL;
compute_creds(bprm);
current->flags &= ~PF_FORKNOEXEC;
diff --git a/arch/x86_64/ia32/ia32_signal.c b/arch/x86_64/ia32/ia32_signal.c
index 85534e58cbbf2..fbd09b5126ce4 100644
--- a/arch/x86_64/ia32/ia32_signal.c
+++ b/arch/x86_64/ia32/ia32_signal.c
@@ -49,12 +49,12 @@ int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
return -EFAULT;
/* If you change siginfo_t structure, please make sure that
- this code is fixed accordingly.
- It should never copy any pad contained in the structure
- to avoid security leaks, but must copy the generic
- 3 ints plus the relevant union member. */
- err = __put_user(from->si_signo, &to->si_signo);
- err |= __put_user(from->si_errno, &to->si_errno);
+ this code is fixed accordingly.
+ It should never copy any pad contained in the structure
+ to avoid security leaks, but must copy the generic
+ 3 ints plus the relevant union member. */
+ err = __put_user(from->si_signo, &to->si_signo);
+ err |= __put_user(from->si_errno, &to->si_errno);
err |= __put_user((short)from->si_code, &to->si_code);
if (from->si_code < 0) {
@@ -72,6 +72,7 @@ int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
err |= __put_user(from->si_utime, &to->si_utime);
err |= __put_user(from->si_stime, &to->si_stime);
err |= __put_user(from->si_status, &to->si_status);
+ /* FALL THROUGH */
default:
case __SI_KILL >> 16:
err |= __put_user(from->si_uid, &to->si_uid);
@@ -81,7 +82,8 @@ int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
break;
case __SI_TIMER >> 16:
err |= __put_user(from->si_overrun, &to->si_overrun);
- err |= __put_user(ptr_to_compat(from->si_ptr), &to->si_ptr);
+ err |= __put_user(ptr_to_compat(from->si_ptr),
+ &to->si_ptr);
break;
case __SI_RT >> 16: /* This is not generated by the kernel as of now. */
case __SI_MESGQ >> 16:
@@ -205,14 +207,14 @@ ia32_restore_sigcontext(struct pt_regs *regs, struct sigcontext_ia32 __user *sc,
sc, sc->err, sc->eip, sc->cs, sc->eflags);
#endif
#define COPY(x) { \
- unsigned int reg; \
+ unsigned int reg; \
err |= __get_user(reg, &sc->e ##x); \
regs->r ## x = reg; \
}
#define RELOAD_SEG(seg,mask) \
- { unsigned int cur; \
- unsigned short pre; \
+ { unsigned int cur; \
+ unsigned short pre; \
err |= __get_user(pre, &sc->seg); \
asm volatile("movl %%" #seg ",%0" : "=r" (cur)); \
pre |= mask; \
@@ -256,7 +258,7 @@ ia32_restore_sigcontext(struct pt_regs *regs, struct sigcontext_ia32 __user *sc,
err |= __get_user(tmp, &sc->fpstate);
buf = compat_ptr(tmp);
if (buf) {
- if (verify_area(VERIFY_READ, buf, sizeof(*buf)))
+ if (!access_ok(VERIFY_READ, buf, sizeof(*buf)))
goto badframe;
err |= restore_i387_ia32(current, buf, 0);
} else {
@@ -285,7 +287,7 @@ asmlinkage long sys32_sigreturn(struct pt_regs *regs)
sigset_t set;
unsigned int eax;
- if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
+ if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
goto badframe;
if (__get_user(set.sig[0], &frame->sc.oldmask)
|| (_COMPAT_NSIG_WORDS > 1
@@ -317,7 +319,7 @@ asmlinkage long sys32_rt_sigreturn(struct pt_regs *regs)
frame = (struct rt_sigframe __user *)(regs->rsp - 4);
- if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
+ if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
goto badframe;
if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
goto badframe;
@@ -377,19 +379,19 @@ ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc, struct _fpstate_ia32 __
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) {
+ if (current->ptrace & PT_PTRACED)
eflags &= ~TF_MASK;
- }
err |= __put_user((u32)eflags, &sc->eflags);
err |= __put_user((u32)regs->rsp, &sc->esp_at_signal);
tmp = save_i387_ia32(current, fpstate, regs, 0);
if (tmp < 0)
- err = -EFAULT;
+ err = -EFAULT;
else {
clear_used_math();
stts();
- err |= __put_user(ptr_to_compat(tmp ? fpstate : NULL), &sc->fpstate);
+ err |= __put_user(ptr_to_compat(tmp ? fpstate : NULL),
+ &sc->fpstate);
}
/* non-iBCS2 extensions.. */
@@ -439,7 +441,7 @@ void ia32_setup_frame(int sig, struct k_sigaction *ka,
{
struct exec_domain *ed = current_thread_info()->exec_domain;
- err |= __put_user((ed
+ err |= __put_user((ed
&& ed->signal_invmap
&& sig < 32
? ed->signal_invmap[sig]
@@ -449,7 +451,8 @@ void ia32_setup_frame(int sig, struct k_sigaction *ka,
if (err)
goto give_sigsegv;
- err |= ia32_setup_sigcontext(&frame->sc, &frame->fpstate, regs, set->sig[0]);
+ err |= ia32_setup_sigcontext(&frame->sc, &frame->fpstate, regs,
+ set->sig[0]);
if (err)
goto give_sigsegv;
@@ -528,10 +531,9 @@ void ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
goto give_sigsegv;
-
{
struct exec_domain *ed = current_thread_info()->exec_domain;
- err |= __put_user((ed
+ err |= __put_user((ed
&& ed->signal_invmap
&& sig < 32
? ed->signal_invmap[sig]
diff --git a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S
index a48e2fee6ca84..f3ca0db85b5b5 100644
--- a/arch/x86_64/ia32/ia32entry.S
+++ b/arch/x86_64/ia32/ia32entry.S
@@ -78,7 +78,7 @@ ENTRY(ia32_sysenter_target)
.quad 1b,ia32_badarg
.previous
GET_THREAD_INFO(%r10)
- testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),threadinfo_flags(%r10)
+ testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),threadinfo_flags(%r10)
jnz sysenter_tracesys
sysenter_do_call:
cmpl $(IA32_NR_syscalls),%eax
@@ -163,7 +163,7 @@ ENTRY(ia32_cstar_target)
.quad 1b,ia32_badarg
.previous
GET_THREAD_INFO(%r10)
- testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),threadinfo_flags(%r10)
+ testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),threadinfo_flags(%r10)
jnz cstar_tracesys
cstar_do_call:
cmpl $IA32_NR_syscalls,%eax
@@ -236,7 +236,7 @@ ENTRY(ia32_syscall)
this could be a problem. */
SAVE_ARGS 0,0,1
GET_THREAD_INFO(%r10)
- testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),threadinfo_flags(%r10)
+ testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),threadinfo_flags(%r10)
jnz ia32_tracesys
ia32_do_syscall:
cmpl $(IA32_NR_syscalls),%eax
@@ -590,7 +590,7 @@ ia32_sys_call_table:
.quad compat_sys_mq_notify
.quad compat_sys_mq_getsetattr
.quad quiet_ni_syscall /* reserved for kexec */
- .quad sys32_waitid
+ .quad compat_sys_waitid
.quad quiet_ni_syscall /* sys_altroot */
.quad sys_add_key
.quad sys_request_key
diff --git a/arch/x86_64/ia32/sys_ia32.c b/arch/x86_64/ia32/sys_ia32.c
index a8cb4f6bd25b1..68a9ab06ee7c2 100644
--- a/arch/x86_64/ia32/sys_ia32.c
+++ b/arch/x86_64/ia32/sys_ia32.c
@@ -65,7 +65,6 @@
#include <asm/types.h>
#include <asm/uaccess.h>
#include <asm/semaphore.h>
-#include <asm/ipc.h>
#include <asm/atomic.h>
#include <asm/ldt.h>
@@ -85,7 +84,7 @@ int cp_compat_stat(struct kstat *kbuf, struct compat_stat __user *ubuf)
return -EOVERFLOW;
if (kbuf->size >= 0x7fffffff)
return -EOVERFLOW;
- if (verify_area(VERIFY_WRITE, ubuf, sizeof(struct compat_stat)) ||
+ if (!access_ok(VERIFY_WRITE, ubuf, sizeof(struct compat_stat)) ||
__put_user (old_encode_dev(kbuf->dev), &ubuf->st_dev) ||
__put_user (kbuf->ino, &ubuf->st_ino) ||
__put_user (kbuf->mode, &ubuf->st_mode) ||
@@ -128,7 +127,7 @@ cp_stat64(struct stat64 __user *ubuf, struct kstat *stat)
typeof(ubuf->st_gid) gid = 0;
SET_UID(uid, stat->uid);
SET_GID(gid, stat->gid);
- if (verify_area(VERIFY_WRITE, ubuf, sizeof(struct stat64)) ||
+ if (!access_ok(VERIFY_WRITE, ubuf, sizeof(struct stat64)) ||
__put_user(huge_encode_dev(stat->dev), &ubuf->st_dev) ||
__put_user (stat->ino, &ubuf->__st_ino) ||
__put_user (stat->ino, &ubuf->st_ino) ||
@@ -262,7 +261,7 @@ sys32_rt_sigaction(int sig, struct sigaction32 __user *act,
if (act) {
compat_uptr_t handler, restorer;
- if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
+ if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
__get_user(handler, &act->sa_handler) ||
__get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
__get_user(restorer, &act->sa_restorer)||
@@ -301,7 +300,7 @@ sys32_rt_sigaction(int sig, struct sigaction32 __user *act,
set32.sig[1] = (old_ka.sa.sa_mask.sig[0] >> 32);
set32.sig[0] = old_ka.sa.sa_mask.sig[0];
}
- if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
+ if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
__put_user(ptr_to_compat(old_ka.sa.sa_handler), &oact->sa_handler) ||
__put_user(ptr_to_compat(old_ka.sa.sa_restorer), &oact->sa_restorer) ||
__put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||
@@ -322,7 +321,7 @@ sys32_sigaction (int sig, struct old_sigaction32 __user *act, struct old_sigacti
compat_old_sigset_t mask;
compat_uptr_t handler, restorer;
- if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
+ if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
__get_user(handler, &act->sa_handler) ||
__get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
__get_user(restorer, &act->sa_restorer) ||
@@ -338,7 +337,7 @@ sys32_sigaction (int sig, struct old_sigaction32 __user *act, struct old_sigacti
ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
if (!ret && oact) {
- if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
+ if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
__put_user(ptr_to_compat(old_ka.sa.sa_handler), &oact->sa_handler) ||
__put_user(ptr_to_compat(old_ka.sa.sa_restorer), &oact->sa_restorer) ||
__put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||
@@ -567,7 +566,7 @@ sys32_sysinfo(struct sysinfo32 __user *info)
s.freehigh >>= bitcount;
}
- if (verify_area(VERIFY_WRITE, info, sizeof(struct sysinfo32)) ||
+ if (!access_ok(VERIFY_WRITE, info, sizeof(struct sysinfo32)) ||
__put_user (s.uptime, &info->uptime) ||
__put_user (s.loads[0], &info->loads[0]) ||
__put_user (s.loads[1], &info->loads[1]) ||
@@ -782,7 +781,7 @@ sys32_adjtimex(struct timex32 __user *utp)
memset(&txc, 0, sizeof(struct timex));
- if(verify_area(VERIFY_READ, utp, sizeof(struct timex32)) ||
+ if (!access_ok(VERIFY_READ, utp, sizeof(struct timex32)) ||
__get_user(txc.modes, &utp->modes) ||
__get_user(txc.offset, &utp->offset) ||
__get_user(txc.freq, &utp->freq) ||
@@ -807,7 +806,7 @@ sys32_adjtimex(struct timex32 __user *utp)
ret = do_adjtimex(&txc);
- if(verify_area(VERIFY_WRITE, utp, sizeof(struct timex32)) ||
+ if (!access_ok(VERIFY_WRITE, utp, sizeof(struct timex32)) ||
__put_user(txc.modes, &utp->modes) ||
__put_user(txc.offset, &utp->offset) ||
__put_user(txc.freq, &utp->freq) ||
@@ -955,32 +954,6 @@ asmlinkage long sys32_clone(unsigned int clone_flags, unsigned int newsp,
return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid);
}
-asmlinkage long sys32_waitid(int which, compat_pid_t pid,
- compat_siginfo_t __user *uinfo, int options,
- struct compat_rusage __user *uru)
-{
- siginfo_t info;
- struct rusage ru;
- long ret;
- mm_segment_t old_fs = get_fs();
-
- info.si_signo = 0;
- set_fs (KERNEL_DS);
- ret = sys_waitid(which, pid, (siginfo_t __user *) &info, options,
- uru ? &ru : NULL);
- set_fs (old_fs);
-
- if (ret < 0 || info.si_signo == 0)
- return ret;
-
- if (uru && (ret = put_compat_rusage(&ru, uru)))
- return ret;
-
- BUG_ON(info.si_code & __SI_MASK);
- info.si_code |= __SI_CHLD;
- return copy_siginfo_to_user32(uinfo, &info);
-}
-
/*
* Some system calls that need sign extended arguments. This could be done by a generic wrapper.
*/
@@ -1019,31 +992,19 @@ asmlinkage long sys32_open(const char __user * filename, int flags, int mode)
return fd;
}
-struct sigevent32 {
- u32 sigev_value;
- u32 sigev_signo;
- u32 sigev_notify;
- u32 payload[(64 / 4) - 3];
-};
-
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 sigevent32 __user *se32, timer_t __user *timer_id)
+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));
- memset(&se, 0, sizeof(struct sigevent));
- if (get_user(se.sigev_value.sival_int, &se32->sigev_value) ||
- __get_user(se.sigev_signo, &se32->sigev_signo) ||
- __get_user(se.sigev_notify, &se32->sigev_notify) ||
- __copy_from_user(&se._sigev_un._pad, &se32->payload,
- sizeof(se32->payload)) ||
+ if (get_compat_sigevent(&se, se32) ||
copy_to_user(p, &se, sizeof(se)))
return -EFAULT;
}
diff --git a/arch/x86_64/kernel/acpi/sleep.c b/arch/x86_64/kernel/acpi/sleep.c
index eb4c73076e189..7a275de6df223 100644
--- a/arch/x86_64/kernel/acpi/sleep.c
+++ b/arch/x86_64/kernel/acpi/sleep.c
@@ -87,15 +87,6 @@ int acpi_save_state_mem (void)
return 0;
}
-/**
- * acpi_save_state_disk - save kernel state to disk
- *
- */
-int acpi_save_state_disk (void)
-{
- return 1;
-}
-
/*
* acpi_restore_state
*/
diff --git a/arch/x86_64/kernel/apic.c b/arch/x86_64/kernel/apic.c
index dbccec4894c0b..9826f03dc9a32 100644
--- a/arch/x86_64/kernel/apic.c
+++ b/arch/x86_64/kernel/apic.c
@@ -650,7 +650,7 @@ void __init init_apic_mappings(void)
#define APIC_DIVISOR 16
-void __setup_APIC_LVTT(unsigned int clocks)
+static void __setup_APIC_LVTT(unsigned int clocks)
{
unsigned int lvtt_value, tmp_value, ver;
@@ -723,7 +723,7 @@ static void setup_APIC_timer(unsigned int clocks)
#define TICK_COUNT 100000000
-int __init calibrate_APIC_clock(void)
+static int __init calibrate_APIC_clock(void)
{
int apic, apic_start, tsc, tsc_start;
int result;
diff --git a/arch/x86_64/kernel/asm-offsets.c b/arch/x86_64/kernel/asm-offsets.c
index 0c1de4a7a989b..35b4c3fcbb37f 100644
--- a/arch/x86_64/kernel/asm-offsets.c
+++ b/arch/x86_64/kernel/asm-offsets.c
@@ -62,8 +62,8 @@ int main(void)
offsetof (struct rt_sigframe32, uc.uc_mcontext));
BLANK();
#endif
- DEFINE(SIZEOF_PBE, sizeof(struct pbe));
DEFINE(pbe_address, offsetof(struct pbe, address));
DEFINE(pbe_orig_address, offsetof(struct pbe, orig_address));
+ DEFINE(pbe_next, offsetof(struct pbe, next));
return 0;
}
diff --git a/arch/x86_64/kernel/e820.c b/arch/x86_64/kernel/e820.c
index 5b65992b80d39..657003e461e67 100644
--- a/arch/x86_64/kernel/e820.c
+++ b/arch/x86_64/kernel/e820.c
@@ -507,21 +507,7 @@ void __init setup_memory_region(void)
void __init parse_memopt(char *p, char **from)
{
- /*
- * mem=XXX[kKmM] limits kernel memory to XXX+1MB
- *
- * It would be more logical to count from 0 instead of from
- * HIGH_MEMORY, but we keep that for now for i386 compatibility.
- *
- * No support for custom mapping like i386. The reason is
- * that we need to read the e820 map anyways to handle the
- * ACPI mappings in the direct map. Also on x86-64 there
- * should be always a good e820 map. This is only an upper
- * limit, you cannot force usage of memory not in e820.
- *
- * -AK
- */
- end_user_pfn = memparse(p, from) + HIGH_MEMORY;
+ end_user_pfn = memparse(p, from);
end_user_pfn >>= PAGE_SHIFT;
}
diff --git a/arch/x86_64/kernel/entry.S b/arch/x86_64/kernel/entry.S
index c261fdc1079e7..e126284db7a84 100644
--- a/arch/x86_64/kernel/entry.S
+++ b/arch/x86_64/kernel/entry.S
@@ -184,7 +184,7 @@ ENTRY(system_call)
movq %rax,ORIG_RAX-ARGOFFSET(%rsp)
movq %rcx,RIP-ARGOFFSET(%rsp)
GET_THREAD_INFO(%rcx)
- testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),threadinfo_flags(%rcx)
+ testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),threadinfo_flags(%rcx)
jnz tracesys
cmpq $__NR_syscall_max,%rax
ja badsys
@@ -516,13 +516,8 @@ retint_kernel:
bt $TIF_NEED_RESCHED,threadinfo_flags(%rcx)
jnc retint_restore_args
bt $9,EFLAGS-ARGOFFSET(%rsp) /* interrupts off? */
- jc retint_restore_args
- movl $PREEMPT_ACTIVE,threadinfo_preempt_count(%rcx)
- sti
- call schedule
- cli
- GET_THREAD_INFO(%rcx)
- movl $0,threadinfo_preempt_count(%rcx)
+ jnc retint_restore_args
+ call preempt_schedule_irq
jmp exit_intr
#endif
CFI_ENDPROC
diff --git a/arch/x86_64/kernel/head.S b/arch/x86_64/kernel/head.S
index 30e92ff8b3c07..b6d8725c1f611 100644
--- a/arch/x86_64/kernel/head.S
+++ b/arch/x86_64/kernel/head.S
@@ -26,6 +26,7 @@
.text
.code32
+ .globl startup_32
/* %bx: 1 if coming from smp trampoline on secondary cpu */
startup_32:
@@ -37,11 +38,13 @@ startup_32:
* There is no stack until we set one up.
*/
- movl %ebx,%ebp /* Save trampoline flag */
-
+ /* Initialize the %ds segment register */
movl $__KERNEL_DS,%eax
movl %eax,%ds
-
+
+ /* Load new GDT with the 64bit segments using 32bit descriptor */
+ lgdt pGDT32 - __START_KERNEL_map
+
/* If the CPU doesn't support CPUID this will double fault.
* Unfortunately it is hard to check for CPUID without a stack.
*/
@@ -57,16 +60,13 @@ startup_32:
btl $29, %edx
jnc no_long_mode
- movl %edx,%edi
-
/*
* Prepare for entering 64bits mode
*/
- /* Enable PAE mode and PGE */
+ /* Enable PAE mode */
xorl %eax, %eax
btsl $5, %eax
- btsl $7, %eax
movl %eax, %cr4
/* Setup early boot stage 4 level pagetables */
@@ -79,14 +79,6 @@ startup_32:
/* Enable Long Mode */
btsl $_EFER_LME, %eax
- /* Enable System Call */
- btsl $_EFER_SCE, %eax
-
- /* No Execute supported? */
- btl $20,%edi
- jnc 1f
- btsl $_EFER_NX, %eax
-1:
/* Make changes effective */
wrmsr
@@ -94,38 +86,69 @@ startup_32:
xorl %eax, %eax
btsl $31, %eax /* Enable paging and in turn activate Long Mode */
btsl $0, %eax /* Enable protected mode */
- btsl $1, %eax /* Enable MP */
- btsl $4, %eax /* Enable ET */
- btsl $5, %eax /* Enable NE */
- btsl $16, %eax /* Enable WP */
- btsl $18, %eax /* Enable AM */
/* Make changes effective */
movl %eax, %cr0
- jmp reach_compatibility_mode
-reach_compatibility_mode:
-
/*
* At this point we're in long mode but in 32bit compatibility mode
* with EFER.LME = 1, CS.L = 0, CS.D = 1 (and in turn
- * EFER.LMA = 1). Now we want to jump in 64bit mode, to do that we load
+ * EFER.LMA = 1). Now we want to jump in 64bit mode, to do that we use
* the new gdt/idt that has __KERNEL_CS with CS.L = 1.
*/
-
- testw %bp,%bp /* secondary CPU? */
- jnz second
-
- /* Load new GDT with the 64bit segment using 32bit descriptor */
- movl $(pGDT32 - __START_KERNEL_map), %eax
- lgdt (%eax)
-
-second:
- movl $(ljumpvector - __START_KERNEL_map), %eax
- /* Finally jump in 64bit mode */
- ljmp *(%eax)
+ ljmp $__KERNEL_CS, $(startup_64 - __START_KERNEL_map)
.code64
.org 0x100
-reach_long64:
+ .globl startup_64
+startup_64:
+ /* We come here either from startup_32
+ * or directly from a 64bit bootloader.
+ * Since we may have come directly from a bootloader we
+ * reload the page tables here.
+ */
+
+ /* Enable PAE mode and PGE */
+ xorq %rax, %rax
+ btsq $5, %rax
+ btsq $7, %rax
+ movq %rax, %cr4
+
+ /* Setup early boot stage 4 level pagetables. */
+ movq $(init_level4_pgt - __START_KERNEL_map), %rax
+ movq %rax, %cr3
+
+ /* Check if nx is implemented */
+ movl $0x80000001, %eax
+ cpuid
+ movl %edx,%edi
+
+ /* Setup EFER (Extended Feature Enable Register) */
+ movl $MSR_EFER, %ecx
+ rdmsr
+
+ /* Enable System Call */
+ btsl $_EFER_SCE, %eax
+
+ /* No Execute supported? */
+ btl $20,%edi
+ jnc 1f
+ btsl $_EFER_NX, %eax
+1:
+ /* Make changes effective */
+ wrmsr
+
+ /* Setup cr0 */
+ xorq %rax, %rax
+ btsq $31, %rax /* Enable paging */
+ btsq $0, %rax /* Enable protected mode */
+ btsq $1, %rax /* Enable MP */
+ btsq $4, %rax /* Enable ET */
+ btsq $5, %rax /* Enable NE */
+ btsq $16, %rax /* Enable WP */
+ btsq $18, %rax /* Enable AM */
+ /* Make changes effective */
+ movq %rax, %cr0
+
+ /* Setup a boot time stack */
movq init_rsp(%rip),%rsp
/* zero EFLAGS after setting rsp */
@@ -198,12 +221,12 @@ ENTRY(no_long_mode)
.org 0xf00
.globl pGDT32
pGDT32:
- .word gdt32_end-gdt_table32
- .long gdt_table32-__START_KERNEL_map
+ .word gdt_end-cpu_gdt_table
+ .long cpu_gdt_table-__START_KERNEL_map
.org 0xf10
ljumpvector:
- .long reach_long64-__START_KERNEL_map
+ .long startup_64-__START_KERNEL_map
.word __KERNEL_CS
ENTRY(stext)
@@ -334,12 +357,6 @@ gdt:
.endr
#endif
-ENTRY(gdt_table32)
- .quad 0x0000000000000000 /* This one is magic */
- .quad 0x0000000000000000 /* unused */
- .quad 0x00af9a000000ffff /* __KERNEL_CS */
-gdt32_end:
-
/* We need valid kernel segments for data and code in long mode too
* IRET will check the segment types kkeil 2000/10/28
* Also sysret mandates a special GDT layout
@@ -360,9 +377,8 @@ ENTRY(cpu_gdt_table)
.quad 0x00affa000000ffff /* __USER_CS */
.quad 0x00cf9a000000ffff /* __KERNEL32_CS */
.quad 0,0 /* TSS */
- .quad 0 /* LDT */
+ .quad 0,0 /* LDT */
.quad 0,0,0 /* three TLS descriptors */
- .quad 0 /* unused now */
.quad 0x00009a000000ffff /* __KERNEL16_CS - 16bit PM for S3 wakeup. */
/* base must be patched for real base address. */
gdt_end:
diff --git a/arch/x86_64/kernel/i8259.c b/arch/x86_64/kernel/i8259.c
index 8bc3d658efd6e..d527012460100 100644
--- a/arch/x86_64/kernel/i8259.c
+++ b/arch/x86_64/kernel/i8259.c
@@ -148,7 +148,7 @@ static void end_8259A_irq (unsigned int irq)
#define shutdown_8259A_irq disable_8259A_irq
-void mask_and_ack_8259A(unsigned int);
+static void mask_and_ack_8259A(unsigned int);
static unsigned int startup_8259A_irq(unsigned int irq)
{
@@ -272,7 +272,7 @@ static inline int i8259A_irq_real(unsigned int irq)
* first, _then_ send the EOI, and the order of EOI
* to the two 8259s is important!
*/
-void mask_and_ack_8259A(unsigned int irq)
+static void mask_and_ack_8259A(unsigned int irq)
{
unsigned int irqmask = 1 << irq;
unsigned long flags;
@@ -477,6 +477,7 @@ void reschedule_interrupt(void);
void call_function_interrupt(void);
void invalidate_interrupt(void);
void thermal_interrupt(void);
+void i8254_timer_resume(void);
static void setup_timer(void)
{
@@ -493,6 +494,11 @@ static int timer_resume(struct sys_device *dev)
return 0;
}
+void i8254_timer_resume(void)
+{
+ setup_timer();
+}
+
static struct sysdev_class timer_sysclass = {
set_kset_name("timer"),
.resume = timer_resume,
diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c
index a81bc8fe19334..adebe70c180ec 100644
--- a/arch/x86_64/kernel/io_apic.c
+++ b/arch/x86_64/kernel/io_apic.c
@@ -147,7 +147,7 @@ static void unmask_IO_APIC_irq (unsigned int irq)
spin_unlock_irqrestore(&ioapic_lock, flags);
}
-void clear_IO_APIC_pin(unsigned int apic, unsigned int pin)
+static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin)
{
struct IO_APIC_route_entry entry;
unsigned long flags;
@@ -185,8 +185,8 @@ static void clear_IO_APIC (void)
*/
#define MAX_PIRQS 8
-int pirq_entries [MAX_PIRQS];
-int pirqs_enabled;
+static int pirq_entries [MAX_PIRQS];
+static int pirqs_enabled;
int skip_ioapic_setup;
int ioapic_force;
@@ -707,7 +707,7 @@ static inline void ioapic_register_intr(int irq, int vector, unsigned long trigg
}
}
-void __init setup_IO_APIC_irqs(void)
+static void __init setup_IO_APIC_irqs(void)
{
struct IO_APIC_route_entry entry;
int apic, pin, idx, irq, first_notcon = 1, vector;
@@ -776,7 +776,7 @@ void __init setup_IO_APIC_irqs(void)
* Set up the 8259A-master output pin as broadcast to all
* CPUs.
*/
-void __init setup_ExtINT_IRQ0_pin(unsigned int pin, int vector)
+static void __init setup_ExtINT_IRQ0_pin(unsigned int pin, int vector)
{
struct IO_APIC_route_entry entry;
unsigned long flags;
@@ -948,6 +948,8 @@ void __apicdebuginit print_IO_APIC(void)
return;
}
+#if 0
+
static __apicdebuginit void print_APIC_bitfield (int base)
{
unsigned int v;
@@ -1090,6 +1092,8 @@ void __apicdebuginit print_PIC(void)
printk(KERN_DEBUG "... PIC ELCR: %04x\n", v);
}
+#endif /* 0 */
+
static void __init enable_IO_APIC(void)
{
union IO_APIC_reg_01 reg_01;
diff --git a/arch/x86_64/kernel/kprobes.c b/arch/x86_64/kernel/kprobes.c
index 131d24ef9a63d..4f2a852299b63 100644
--- a/arch/x86_64/kernel/kprobes.c
+++ b/arch/x86_64/kernel/kprobes.c
@@ -25,6 +25,8 @@
* interface to access function arguments.
* 2004-Oct Jim Keniston <kenistoj@us.ibm.com> and Prasanna S Panchamukhi
* <prasanna@in.ibm.com> adapted for x86_64
+ * 2005-Mar Roland McGrath <roland@redhat.com>
+ * Fixed to handle %rip-relative addressing mode correctly.
*/
#include <linux/config.h>
@@ -34,7 +36,7 @@
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/preempt.h>
-#include <linux/vmalloc.h>
+#include <linux/moduleloader.h>
#include <asm/pgtable.h>
#include <asm/kdebug.h>
@@ -86,9 +88,132 @@ int arch_prepare_kprobe(struct kprobe *p)
return 0;
}
+/*
+ * Determine if the instruction uses the %rip-relative addressing mode.
+ * If it does, return the address of the 32-bit displacement word.
+ * If not, return null.
+ */
+static inline s32 *is_riprel(u8 *insn)
+{
+#define W(row,b0,b1,b2,b3,b4,b5,b6,b7,b8,b9,ba,bb,bc,bd,be,bf) \
+ (((b0##UL << 0x0)|(b1##UL << 0x1)|(b2##UL << 0x2)|(b3##UL << 0x3) | \
+ (b4##UL << 0x4)|(b5##UL << 0x5)|(b6##UL << 0x6)|(b7##UL << 0x7) | \
+ (b8##UL << 0x8)|(b9##UL << 0x9)|(ba##UL << 0xa)|(bb##UL << 0xb) | \
+ (bc##UL << 0xc)|(bd##UL << 0xd)|(be##UL << 0xe)|(bf##UL << 0xf)) \
+ << (row % 64))
+ static const u64 onebyte_has_modrm[256 / 64] = {
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
+ /* ------------------------------- */
+ W(0x00, 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0)| /* 00 */
+ W(0x10, 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0)| /* 10 */
+ W(0x20, 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0)| /* 20 */
+ W(0x30, 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0), /* 30 */
+ W(0x40, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)| /* 40 */
+ W(0x50, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)| /* 50 */
+ W(0x60, 0,0,1,1,0,0,0,0,0,1,0,1,0,0,0,0)| /* 60 */
+ W(0x70, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), /* 70 */
+ W(0x80, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1)| /* 80 */
+ W(0x90, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)| /* 90 */
+ W(0xa0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)| /* a0 */
+ W(0xb0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), /* b0 */
+ W(0xc0, 1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,0)| /* c0 */
+ W(0xd0, 1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1)| /* d0 */
+ W(0xe0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)| /* e0 */
+ W(0xf0, 0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1) /* f0 */
+ /* ------------------------------- */
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
+ };
+ static const u64 twobyte_has_modrm[256 / 64] = {
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
+ /* ------------------------------- */
+ W(0x00, 1,1,1,1,0,0,0,0,0,0,0,0,0,1,0,1)| /* 0f */
+ W(0x10, 1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0)| /* 1f */
+ W(0x20, 1,1,1,1,1,0,1,0,1,1,1,1,1,1,1,1)| /* 2f */
+ W(0x30, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), /* 3f */
+ W(0x40, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1)| /* 4f */
+ W(0x50, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1)| /* 5f */
+ W(0x60, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1)| /* 6f */
+ W(0x70, 1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1), /* 7f */
+ W(0x80, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)| /* 8f */
+ W(0x90, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1)| /* 9f */
+ W(0xa0, 0,0,0,1,1,1,1,1,0,0,0,1,1,1,1,1)| /* af */
+ W(0xb0, 1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1), /* bf */
+ W(0xc0, 1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0)| /* cf */
+ W(0xd0, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1)| /* df */
+ W(0xe0, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1)| /* ef */
+ W(0xf0, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0) /* ff */
+ /* ------------------------------- */
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
+ };
+#undef W
+ int need_modrm;
+
+ /* Skip legacy instruction prefixes. */
+ while (1) {
+ switch (*insn) {
+ case 0x66:
+ case 0x67:
+ case 0x2e:
+ case 0x3e:
+ case 0x26:
+ case 0x64:
+ case 0x65:
+ case 0x36:
+ case 0xf0:
+ case 0xf3:
+ case 0xf2:
+ ++insn;
+ continue;
+ }
+ break;
+ }
+
+ /* Skip REX instruction prefix. */
+ if ((*insn & 0xf0) == 0x40)
+ ++insn;
+
+ if (*insn == 0x0f) { /* Two-byte opcode. */
+ ++insn;
+ need_modrm = test_bit(*insn, twobyte_has_modrm);
+ } else { /* One-byte opcode. */
+ need_modrm = test_bit(*insn, onebyte_has_modrm);
+ }
+
+ if (need_modrm) {
+ u8 modrm = *++insn;
+ if ((modrm & 0xc7) == 0x05) { /* %rip+disp32 addressing mode */
+ /* Displacement follows ModRM byte. */
+ return (s32 *) ++insn;
+ }
+ }
+
+ /* No %rip-relative addressing mode here. */
+ return NULL;
+}
+
void arch_copy_kprobe(struct kprobe *p)
{
+ s32 *ripdisp;
memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE);
+ ripdisp = is_riprel(p->ainsn.insn);
+ if (ripdisp) {
+ /*
+ * The copied instruction uses the %rip-relative
+ * addressing mode. Adjust the displacement for the
+ * difference between the original location of this
+ * instruction and the location of the copy that will
+ * actually be run. The tricky bit here is making sure
+ * that the sign extension happens correctly in this
+ * calculation, since we need a signed 32-bit result to
+ * be sign-extended to 64 bits when it's added to the
+ * %rip value and yield the same 64-bit result that the
+ * sign-extension of the original signed 32-bit
+ * displacement would have given.
+ */
+ s64 disp = (u8 *) p->addr + *ripdisp - (u8 *) p->ainsn.insn;
+ BUG_ON((s64) (s32) disp != disp); /* Sanity check. */
+ *ripdisp = disp;
+ }
}
void arch_remove_kprobe(struct kprobe *p)
@@ -108,8 +233,11 @@ static void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
{
regs->eflags |= TF_MASK;
regs->eflags &= ~IF_MASK;
-
- regs->rip = (unsigned long)p->ainsn.insn;
+ /*single step inline if the instruction is an int3*/
+ if (p->opcode == BREAKPOINT_INSTRUCTION)
+ regs->rip = (unsigned long)p->addr;
+ else
+ regs->rip = (unsigned long)p->ainsn.insn;
}
/*
@@ -131,6 +259,12 @@ int kprobe_handler(struct pt_regs *regs)
Disarm the probe we just hit, and ignore it. */
p = get_kprobe(addr);
if (p) {
+ if (kprobe_status == KPROBE_HIT_SS) {
+ regs->eflags &= ~TF_MASK;
+ regs->eflags |= kprobe_saved_rflags;
+ unlock_kprobes();
+ goto no_kprobe;
+ }
disarm_kprobe(p, regs);
ret = 1;
} else {
@@ -168,17 +302,16 @@ int kprobe_handler(struct pt_regs *regs)
if (is_IF_modifier(p->ainsn.insn))
kprobe_saved_rflags &= ~IF_MASK;
- if (p->pre_handler(p, regs)) {
+ if (p->pre_handler && p->pre_handler(p, regs))
/* handler has already set things up, so skip ss setup */
return 1;
- }
- ss_probe:
+ss_probe:
prepare_singlestep(p, regs);
kprobe_status = KPROBE_HIT_SS;
return 1;
- no_kprobe:
+no_kprobe:
preempt_enable_no_resched();
return ret;
}
@@ -439,8 +572,15 @@ static kprobe_opcode_t *get_insn_slot(void)
if (!kip) {
return NULL;
}
- kip->insns = (kprobe_opcode_t*) __vmalloc(PAGE_SIZE,
- GFP_KERNEL|__GFP_HIGHMEM, __pgprot(__PAGE_KERNEL_EXEC));
+
+ /*
+ * For the %rip-relative displacement fixups to be doable, we
+ * need our instruction copy to be within +/- 2GB of any data it
+ * might access via %rip. That is, within 2GB of where the
+ * kernel image and loaded module images reside. So we allocate
+ * a page in the module loading area.
+ */
+ kip->insns = module_alloc(PAGE_SIZE);
if (!kip->insns) {
kfree(kip);
return NULL;
@@ -481,7 +621,7 @@ static void free_insn_slot(kprobe_opcode_t *slot)
hlist_add_head(&kip->hlist,
&kprobe_insn_pages);
} else {
- vfree(kip->insns);
+ module_free(NULL, kip->insns);
kfree(kip);
}
}
diff --git a/arch/x86_64/kernel/module.c b/arch/x86_64/kernel/module.c
index d763d10c8afb9..c2ffea8845ede 100644
--- a/arch/x86_64/kernel/module.c
+++ b/arch/x86_64/kernel/module.c
@@ -29,107 +29,27 @@
#include <asm/pgtable.h>
#define DEBUGP(fmt...)
-
-static struct vm_struct *mod_vmlist;
void module_free(struct module *mod, void *module_region)
{
- struct vm_struct **prevp, *map;
- int i;
- unsigned long addr = (unsigned long)module_region;
-
- if (!addr)
- return;
- write_lock(&vmlist_lock);
- for (prevp = &mod_vmlist ; (map = *prevp) ; prevp = &map->next) {
- if ((unsigned long)map->addr == addr) {
- *prevp = map->next;
- goto found;
- }
- }
- write_unlock(&vmlist_lock);
- printk("Trying to unmap nonexistent module vm area (%lx)\n", addr);
- return;
- found:
- unmap_vm_area(map);
- write_unlock(&vmlist_lock);
- if (map->pages) {
- for (i = 0; i < map->nr_pages; i++)
- if (map->pages[i])
- __free_page(map->pages[i]);
- kfree(map->pages);
- }
- kfree(map);
+ vfree(module_region);
}
void *module_alloc(unsigned long size)
{
- struct vm_struct **p, *tmp, *area;
- struct page **pages;
- void *addr;
- unsigned int nr_pages, array_size, i;
+ struct vm_struct *area;
if (!size)
- return NULL;
+ return NULL;
size = PAGE_ALIGN(size);
if (size > MODULES_LEN)
return NULL;
- area = (struct vm_struct *) kmalloc(sizeof(*area), GFP_KERNEL);
+ area = __get_vm_area(size, VM_ALLOC, MODULES_VADDR, MODULES_END);
if (!area)
return NULL;
- memset(area, 0, sizeof(struct vm_struct));
-
- write_lock(&vmlist_lock);
- addr = (void *) MODULES_VADDR;
- for (p = &mod_vmlist; (tmp = *p); p = &tmp->next) {
- void *next;
- DEBUGP("vmlist %p %lu addr %p\n", tmp->addr, tmp->size, addr);
- if (size + (unsigned long) addr + PAGE_SIZE < (unsigned long) tmp->addr)
- break;
- next = (void *) (tmp->size + (unsigned long) tmp->addr);
- if (next > addr)
- addr = next;
- }
- if ((unsigned long)addr + size >= MODULES_END) {
- write_unlock(&vmlist_lock);
- kfree(area);
- return NULL;
- }
- DEBUGP("addr %p\n", addr);
-
- area->next = *p;
- *p = area;
- area->size = size + PAGE_SIZE;
- area->addr = addr;
- write_unlock(&vmlist_lock);
-
- nr_pages = size >> PAGE_SHIFT;
- array_size = (nr_pages * sizeof(struct page *));
-
- area->nr_pages = nr_pages;
- area->pages = pages = kmalloc(array_size, GFP_KERNEL);
- if (!area->pages)
- goto fail;
-
- memset(area->pages, 0, array_size);
- for (i = 0; i < nr_pages; i++) {
- area->pages[i] = alloc_page(GFP_KERNEL);
- if (area->pages[i] == NULL)
- goto fail;
- }
-
- if (map_vm_area(area, PAGE_KERNEL_EXEC, &pages))
- goto fail;
-
- memset(addr, 0, size);
- DEBUGP("module_alloc size %lu = %p\n", size, addr);
- return addr;
-
-fail:
- module_free(NULL, addr);
- return NULL;
+ return __vmalloc_area(area, GFP_KERNEL, PAGE_KERNEL_EXEC);
}
/* We don't need anything special. */
diff --git a/arch/x86_64/kernel/mpparse.c b/arch/x86_64/kernel/mpparse.c
index 7f5f57e547401..7ec031c6ca10f 100644
--- a/arch/x86_64/kernel/mpparse.c
+++ b/arch/x86_64/kernel/mpparse.c
@@ -46,7 +46,7 @@ unsigned char mp_bus_id_to_type [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1
int mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 };
cpumask_t pci_bus_to_cpumask [256] = { [0 ... 255] = CPU_MASK_ALL };
-int mp_current_pci_id = 0;
+static int mp_current_pci_id = 0;
/* I/O APIC entries */
struct mpc_config_ioapic mp_ioapics[MAX_IO_APICS];
@@ -708,7 +708,7 @@ void __init mp_register_lapic (
#define MP_ISA_BUS 0
#define MP_MAX_IOAPIC_PIN 127
-struct mp_ioapic_routing {
+static struct mp_ioapic_routing {
int apic_id;
int gsi_start;
int gsi_end;
diff --git a/arch/x86_64/kernel/msr.c b/arch/x86_64/kernel/msr.c
index 89ad3e72947f5..598953ab01543 100644
--- a/arch/x86_64/kernel/msr.c
+++ b/arch/x86_64/kernel/msr.c
@@ -255,7 +255,7 @@ static struct file_operations msr_fops = {
.open = msr_open,
};
-int __init msr_init(void)
+static int __init msr_init(void)
{
if (register_chrdev(MSR_MAJOR, "cpu/msr", &msr_fops)) {
printk(KERN_ERR "msr: unable to get major %d for msr\n",
@@ -266,7 +266,7 @@ int __init msr_init(void)
return 0;
}
-void __exit msr_exit(void)
+static void __exit msr_exit(void)
{
unregister_chrdev(MSR_MAJOR, "cpu/msr");
}
diff --git a/arch/x86_64/kernel/pci-gart.c b/arch/x86_64/kernel/pci-gart.c
index ca01bc2022457..49d5d5f137fa4 100644
--- a/arch/x86_64/kernel/pci-gart.c
+++ b/arch/x86_64/kernel/pci-gart.c
@@ -720,6 +720,7 @@ static __init int init_k8_gatt(struct agp_kern_info *info)
unsigned aper_base, new_aper_base;
unsigned aper_size, gatt_size, new_aper_size;
+ printk(KERN_INFO "PCI-DMA: Disabling AGP.\n");
aper_size = aper_base = info->aper_size = 0;
for_all_nb(dev) {
new_aper_base = read_aperture(dev, &new_aper_size);
@@ -789,7 +790,7 @@ static int __init pci_iommu_init(void)
/* Add other K8 AGP bridge drivers here */
no_agp = no_agp ||
(agp_amd64_init() < 0) ||
- (agp_copy_info(&info) < 0);
+ (agp_copy_info(agp_bridge, &info) < 0);
#endif
if (swiotlb) {
@@ -798,26 +799,15 @@ static int __init pci_iommu_init(void)
return -1;
}
- if (no_iommu || (!force_iommu && end_pfn < 0xffffffff>>PAGE_SHIFT) ||
- !iommu_aperture) {
+ if (no_iommu ||
+ (!force_iommu && end_pfn < 0xffffffff>>PAGE_SHIFT) ||
+ !iommu_aperture ||
+ (no_agp && init_k8_gatt(&info) < 0)) {
printk(KERN_INFO "PCI-DMA: Disabling IOMMU.\n");
no_iommu = 1;
return -1;
}
- if (no_agp) {
- int err = -1;
- printk(KERN_INFO "PCI-DMA: Disabling AGP.\n");
- no_agp = 1;
- if (force_iommu || end_pfn >= 0xffffffff>>PAGE_SHIFT)
- err = init_k8_gatt(&info);
- if (err < 0) {
- printk(KERN_INFO "PCI-DMA: Disabling IOMMU.\n");
- no_iommu = 1;
- return -1;
- }
- }
-
aper_size = info.aper_size * 1024 * 1024;
iommu_size = check_iommu_size(info.aper_base, aper_size);
iommu_pages = iommu_size >> PAGE_SHIFT;
diff --git a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c
index 3a3522b9c8857..171931ea7eaae 100644
--- a/arch/x86_64/kernel/process.c
+++ b/arch/x86_64/kernel/process.c
@@ -33,6 +33,7 @@
#include <linux/irq.h>
#include <linux/ptrace.h>
#include <linux/utsname.h>
+#include <linux/random.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
@@ -52,7 +53,7 @@ asmlinkage extern void ret_from_fork(void);
unsigned long kernel_thread_flags = CLONE_VM | CLONE_UNTRACED;
-atomic_t hlt_counter = ATOMIC_INIT(0);
+static atomic_t hlt_counter = ATOMIC_INIT(0);
unsigned long boot_option_idle_override = 0;
EXPORT_SYMBOL(boot_option_idle_override);
@@ -61,7 +62,7 @@ EXPORT_SYMBOL(boot_option_idle_override);
* Powermanagement idle function, if any..
*/
void (*pm_idle)(void);
-static cpumask_t cpu_idle_map;
+static DEFINE_PER_CPU(unsigned int, cpu_idle_state);
void disable_hlt(void)
{
@@ -124,20 +125,31 @@ static void poll_idle (void)
}
}
-
void cpu_idle_wait(void)
{
- int cpu;
- cpumask_t map;
+ unsigned int cpu, this_cpu = get_cpu();
+ cpumask_t map;
+
+ set_cpus_allowed(current, cpumask_of_cpu(this_cpu));
+ put_cpu();
+
+ cpus_clear(map);
+ for_each_online_cpu(cpu) {
+ per_cpu(cpu_idle_state, cpu) = 1;
+ cpu_set(cpu, map);
+ }
- for_each_online_cpu(cpu)
- cpu_set(cpu, cpu_idle_map);
+ __get_cpu_var(cpu_idle_state) = 0;
- wmb();
- do {
- ssleep(1);
- cpus_and(map, cpu_idle_map, cpu_online_map);
- } while (!cpus_empty(map));
+ wmb();
+ do {
+ ssleep(1);
+ for_each_online_cpu(cpu) {
+ if (cpu_isset(cpu, map) && !per_cpu(cpu_idle_state, cpu))
+ cpu_clear(cpu, map);
+ }
+ cpus_and(map, map, cpu_online_map);
+ } while (!cpus_empty(map));
}
EXPORT_SYMBOL_GPL(cpu_idle_wait);
@@ -149,21 +161,21 @@ EXPORT_SYMBOL_GPL(cpu_idle_wait);
*/
void cpu_idle (void)
{
- int cpu = smp_processor_id();
-
/* endless idle loop with no priority at all */
while (1) {
while (!need_resched()) {
void (*idle)(void);
- if (cpu_isset(cpu, cpu_idle_map))
- cpu_clear(cpu, cpu_idle_map);
+ if (__get_cpu_var(cpu_idle_state))
+ __get_cpu_var(cpu_idle_state) = 0;
+
rmb();
idle = pm_idle;
if (!idle)
idle = default_idle;
idle();
}
+
schedule();
}
}
@@ -749,3 +761,10 @@ int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs)
return 1;
}
+
+unsigned long arch_align_stack(unsigned long sp)
+{
+ if (randomize_va_space)
+ sp -= get_random_int() % 8192;
+ return sp & ~0xf;
+}
diff --git a/arch/x86_64/kernel/ptrace.c b/arch/x86_64/kernel/ptrace.c
index eaa7250152f56..0b7b101debdf4 100644
--- a/arch/x86_64/kernel/ptrace.c
+++ b/arch/x86_64/kernel/ptrace.c
@@ -17,6 +17,7 @@
#include <linux/user.h>
#include <linux/security.h>
#include <linux/audit.h>
+#include <linux/seccomp.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
@@ -521,6 +522,9 @@ static void syscall_trace(struct pt_regs *regs)
asmlinkage void syscall_trace_enter(struct pt_regs *regs)
{
+ /* do the secure computing check first */
+ secure_computing(regs->orig_rax);
+
if (unlikely(current->audit_context))
audit_syscall_entry(current, regs->orig_rax,
regs->rdi, regs->rsi,
diff --git a/arch/x86_64/kernel/semaphore.c b/arch/x86_64/kernel/semaphore.c
index 2bcd4a7ec38dd..48f7c18172b99 100644
--- a/arch/x86_64/kernel/semaphore.c
+++ b/arch/x86_64/kernel/semaphore.c
@@ -10,7 +10,7 @@
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
- * rw semaphores implemented November 1999 by Benjamin LaHaise <bcrl@redhat.com>
+ * rw semaphores implemented November 1999 by Benjamin LaHaise <bcrl@kvack.org>
*/
#include <linux/config.h>
#include <linux/sched.h>
diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c
index 96e4ca9b79ac8..e50fc41de6b95 100644
--- a/arch/x86_64/kernel/setup.c
+++ b/arch/x86_64/kernel/setup.c
@@ -65,7 +65,6 @@
struct cpuinfo_x86 boot_cpu_data;
unsigned long mmu_cr4_features;
-EXPORT_SYMBOL_GPL(mmu_cr4_features);
int acpi_disabled;
EXPORT_SYMBOL(acpi_disabled);
@@ -103,8 +102,6 @@ struct sys_desc_table_struct {
struct edid_info edid_info;
struct e820map e820;
-unsigned char aux_device_present;
-
extern int root_mountflags;
extern char _text, _etext, _edata, _end;
@@ -505,7 +502,6 @@ void __init setup_arch(char **cmdline_p)
drive_info = DRIVE_INFO;
screen_info = SCREEN_INFO;
edid_info = EDID_INFO;
- aux_device_present = AUX_DEVICE_INFO;
saved_video_mode = SAVED_VIDEO_MODE;
bootloader_type = LOADER_TYPE;
@@ -1081,6 +1077,8 @@ static int show_cpuinfo(struct seq_file *m, void *v)
"fid", /* frequency id control */
"vid", /* voltage id control */
"ttp", /* thermal trip */
+ "tm",
+ "stc"
};
diff --git a/arch/x86_64/kernel/signal.c b/arch/x86_64/kernel/signal.c
index 9cf7038272149..5ace32c6ac5c5 100644
--- a/arch/x86_64/kernel/signal.c
+++ b/arch/x86_64/kernel/signal.c
@@ -121,7 +121,7 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, unsigned
err |= __get_user(buf, &sc->fpstate);
if (buf) {
- if (verify_area(VERIFY_READ, buf, sizeof(*buf)))
+ if (!access_ok(VERIFY_READ, buf, sizeof(*buf)))
goto badframe;
err |= restore_i387(buf);
} else {
@@ -147,7 +147,7 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs)
unsigned long eax;
frame = (struct rt_sigframe __user *)(regs->rsp - 8);
- if (verify_area(VERIFY_READ, frame, sizeof(*frame))) {
+ if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) {
goto badframe;
}
if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) {
@@ -160,9 +160,8 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs)
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
- if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &eax)) {
+ if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &eax))
goto badframe;
- }
#ifdef DEBUG_SIG
printk("%d sigreturn rip:%lx rsp:%lx frame:%p rax:%lx\n",current->pid,regs.rip,regs.rsp,frame,eax);
@@ -253,28 +252,25 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
if (used_math()) {
fp = get_stack(ka, regs, sizeof(struct _fpstate));
- frame = (void __user *)round_down((unsigned long)fp - sizeof(struct rt_sigframe), 16) - 8;
+ frame = (void __user *)round_down(
+ (unsigned long)fp - sizeof(struct rt_sigframe), 16) - 8;
- if (!access_ok(VERIFY_WRITE, fp, sizeof(struct _fpstate))) {
- goto give_sigsegv;
- }
+ if (!access_ok(VERIFY_WRITE, fp, sizeof(struct _fpstate)))
+ goto give_sigsegv;
if (save_i387(fp) < 0)
err |= -1;
- } else {
+ } else
frame = get_stack(ka, regs, sizeof(struct rt_sigframe)) - 8;
- }
- if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) {
+ if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
goto give_sigsegv;
- }
if (ka->sa.sa_flags & SA_SIGINFO) {
err |= copy_siginfo_to_user(&frame->info, info);
- if (err) {
+ if (err)
goto give_sigsegv;
}
- }
/* Create the ucontext. */
err |= __put_user(0, &frame->uc.uc_flags);
@@ -288,9 +284,8 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
if (sizeof(*set) == 16) {
__put_user(set->sig[0], &frame->uc.uc_sigmask.sig[0]);
__put_user(set->sig[1], &frame->uc.uc_sigmask.sig[1]);
- } else {
- err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
- }
+ } else
+ err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
/* Set up to return from userspace. If provided, use a stub
already in userspace. */
@@ -302,9 +297,8 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
goto give_sigsegv;
}
- if (err) {
+ if (err)
goto give_sigsegv;
- }
#ifdef DEBUG_SIG
printk("%d old rip %lx old rsp %lx old rax %lx\n", current->pid,regs->rip,regs->rsp,regs->rax);
@@ -357,7 +351,8 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
sigset_t *oldset, struct pt_regs *regs)
{
#ifdef DEBUG_SIG
- printk("handle_signal pid:%d sig:%lu rip:%lx rsp:%lx regs=%p\n", current->pid, sig,
+ printk("handle_signal pid:%d sig:%lu rip:%lx rsp:%lx regs=%p\n",
+ current->pid, sig,
regs->rip, regs->rsp, regs);
#endif
@@ -375,10 +370,11 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
regs->rax = -EINTR;
break;
}
- /* fallthrough */
+ /* fallthrough */
case -ERESTARTNOINTR:
regs->rax = regs->orig_rax;
regs->rip -= 2;
+ break;
}
}
@@ -418,9 +414,8 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
* kernel mode. Just return without doing anything
* if so.
*/
- if ((regs->cs & 3) != 3) {
+ if ((regs->cs & 3) != 3)
return 1;
- }
if (try_to_freeze(0))
goto no_signal;
diff --git a/arch/x86_64/kernel/smp.c b/arch/x86_64/kernel/smp.c
index b183fafacd563..e3cdbf9a88bd7 100644
--- a/arch/x86_64/kernel/smp.c
+++ b/arch/x86_64/kernel/smp.c
@@ -25,6 +25,7 @@
#include <asm/pgalloc.h>
#include <asm/tlbflush.h>
#include <asm/mach_apic.h>
+#include <asm/mmu_context.h>
#include <asm/proto.h>
/*
@@ -41,7 +42,7 @@ static cpumask_t flush_cpumask;
static struct mm_struct * flush_mm;
static unsigned long flush_va;
static DEFINE_SPINLOCK(tlbstate_lock);
-#define FLUSH_ALL 0xffffffff
+#define FLUSH_ALL -1ULL
/*
* We cannot call mmdrop() because we are in interrupt context,
@@ -52,7 +53,7 @@ static inline void leave_mm (unsigned long cpu)
if (read_pda(mmu_state) == TLBSTATE_OK)
BUG();
clear_bit(cpu, &read_pda(active_mm)->cpu_vm_mask);
- __flush_tlb();
+ load_cr3(swapper_pg_dir);
}
/*
@@ -372,7 +373,10 @@ void smp_send_stop(void)
__smp_call_function(smp_really_stop_cpu, NULL, 0, 0);
if (!nolock)
spin_unlock(&call_lock);
- smp_stop_cpu();
+
+ local_irq_disable();
+ disable_local_APIC();
+ local_irq_enable();
}
/*
diff --git a/arch/x86_64/kernel/smpboot.c b/arch/x86_64/kernel/smpboot.c
index a7e2c3e95ea59..afd3600b919e5 100644
--- a/arch/x86_64/kernel/smpboot.c
+++ b/arch/x86_64/kernel/smpboot.c
@@ -70,9 +70,6 @@ static cpumask_t smp_commenced_mask;
/* Per CPU bogomips and other parameters */
struct cpuinfo_x86 cpu_data[NR_CPUS] __cacheline_aligned;
-/* Set when the idlers are all forked */
-int smp_threads_ready;
-
cpumask_t cpu_sibling_map[NR_CPUS] __cacheline_aligned;
/*
@@ -91,8 +88,6 @@ extern unsigned char trampoline_end [];
static unsigned long __init setup_trampoline(void)
{
void *tramp = __va(SMP_TRAMPOLINE_BASE);
- extern volatile __u32 tramp_gdt_ptr;
- tramp_gdt_ptr = __pa_symbol(&cpu_gdt_table);
memcpy(tramp, trampoline_data, trampoline_end - trampoline_data);
return virt_to_phys(tramp);
}
@@ -249,7 +244,7 @@ static void __init synchronize_tsc_ap (void)
static atomic_t init_deasserted;
-void __init smp_callin(void)
+static void __init smp_callin(void)
{
int cpuid, phys_id;
unsigned long timeout;
@@ -338,7 +333,7 @@ void __init smp_callin(void)
synchronize_tsc_ap();
}
-int cpucount;
+static int cpucount;
/*
* Activate a secondary processor.
@@ -661,9 +656,6 @@ static void __init do_boot_cpu (int apicid)
}
}
-cycles_t cacheflush_time;
-unsigned long cache_decay_ticks;
-
static void smp_tune_scheduling (void)
{
int cachesize; /* kB */
@@ -680,11 +672,6 @@ static void smp_tune_scheduling (void)
*/
if (!cpu_khz) {
- /*
- * this basically disables processor-affinity
- * scheduling on SMP without a TSC.
- */
- cacheflush_time = 0;
return;
} else {
cachesize = boot_cpu_data.x86_cache_size;
@@ -692,17 +679,7 @@ static void smp_tune_scheduling (void)
cachesize = 16; /* Pentiums, 2x8kB cache */
bandwidth = 100;
}
-
- cacheflush_time = (cpu_khz>>10) * (cachesize<<10) / bandwidth;
}
-
- cache_decay_ticks = (long)cacheflush_time/cpu_khz * HZ / 1000;
-
- printk(KERN_INFO "per-CPU timeslice cutoff: %ld.%02ld usecs.\n",
- (long)cacheflush_time/(cpu_khz/1000),
- ((long)cacheflush_time*100/(cpu_khz/1000)) % 100);
- printk(KERN_INFO "task migration cache decay timeout: %ld msecs.\n",
- (cache_decay_ticks + 1) * 1000 / HZ);
}
/*
@@ -739,6 +716,7 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
printk(KERN_NOTICE "SMP motherboard not detected.\n");
io_apic_irqs = 0;
cpu_online_map = cpumask_of_cpu(0);
+ cpu_set(0, cpu_sibling_map[0]);
phys_cpu_present_map = physid_mask_of_physid(0);
if (APIC_init_uniprocessor())
printk(KERN_NOTICE "Local APIC not detected."
@@ -765,6 +743,7 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
printk(KERN_ERR "... forcing use of dummy APIC emulation. (tell your hw vendor)\n");
io_apic_irqs = 0;
cpu_online_map = cpumask_of_cpu(0);
+ cpu_set(0, cpu_sibling_map[0]);
phys_cpu_present_map = physid_mask_of_physid(0);
disable_apic = 1;
goto smp_done;
@@ -780,6 +759,7 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
printk(KERN_INFO "SMP mode deactivated, forcing use of dummy APIC emulation.\n");
io_apic_irqs = 0;
cpu_online_map = cpumask_of_cpu(0);
+ cpu_set(0, cpu_sibling_map[0]);
phys_cpu_present_map = physid_mask_of_physid(0);
disable_apic = 1;
goto smp_done;
diff --git a/arch/x86_64/kernel/suspend_asm.S b/arch/x86_64/kernel/suspend_asm.S
index 633a86901f8ef..53f8e1659511f 100644
--- a/arch/x86_64/kernel/suspend_asm.S
+++ b/arch/x86_64/kernel/suspend_asm.S
@@ -54,16 +54,10 @@ ENTRY(swsusp_arch_resume)
movq %rax, %cr4; # turn PGE back on
movq pagedir_nosave(%rip), %rdx
- /* compute the limit */
- movl nr_copy_pages(%rip), %eax
- testl %eax, %eax
- jz done
- movq %rdx,%r8
- movl $SIZEOF_PBE,%r9d
- mul %r9 # with rax, clobbers rdx
- movq %r8, %rdx
- addq %r8, %rax
loop:
+ testq %rdx, %rdx
+ jz done
+
/* get addresses from the pbe and copy the page */
movq pbe_address(%rdx), %rsi
movq pbe_orig_address(%rdx), %rdi
@@ -72,16 +66,24 @@ loop:
movsq
/* progress to the next pbe */
- addq $SIZEOF_PBE, %rdx
- cmpq %rax, %rdx
- jb loop
+ movq pbe_next(%rdx), %rdx
+ jmp loop
done:
+ /* Flush TLB, including "global" things (vmalloc) */
+ movq mmu_cr4_features(%rip), %rax
+ movq %rax, %rdx
+ andq $~(1<<7), %rdx; # PGE
+ movq %rdx, %cr4; # turn off PGE
+ movq %cr3, %rcx; # flush TLB
+ movq %rcx, %cr3
+ movq %rax, %cr4; # turn PGE back on
+
movl $24, %eax
movl %eax, %ds
movq saved_context_esp(%rip), %rsp
movq saved_context_ebp(%rip), %rbp
- movq saved_context_eax(%rip), %rax
+ /* Don't restore %rax, it must be 0 anyway */
movq saved_context_ebx(%rip), %rbx
movq saved_context_ecx(%rip), %rcx
movq saved_context_edx(%rip), %rdx
@@ -96,5 +98,7 @@ done:
movq saved_context_r14(%rip), %r14
movq saved_context_r15(%rip), %r15
pushq saved_context_eflags(%rip) ; popfq
- call swsusp_restore
+
+ xorq %rax, %rax
+
ret
diff --git a/arch/x86_64/kernel/sys_x86_64.c b/arch/x86_64/kernel/sys_x86_64.c
index 38a286ca3bf5f..477d8be57d64f 100644
--- a/arch/x86_64/kernel/sys_x86_64.c
+++ b/arch/x86_64/kernel/sys_x86_64.c
@@ -18,7 +18,6 @@
#include <linux/personality.h>
#include <asm/uaccess.h>
-#include <asm/ipc.h>
#include <asm/ia32.h>
/*
@@ -38,7 +37,7 @@ asmlinkage long sys_pipe(int __user *fildes)
return error;
}
-long sys_mmap(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags,
+asmlinkage long sys_mmap(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags,
unsigned long fd, unsigned long off)
{
long error;
diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c
index b0df27f80baca..3bafe438fa750 100644
--- a/arch/x86_64/kernel/time.c
+++ b/arch/x86_64/kernel/time.c
@@ -46,7 +46,7 @@ EXPORT_SYMBOL(jiffies_64);
#ifdef CONFIG_CPU_FREQ
static void cpufreq_delayed_get(void);
#endif
-
+extern void i8254_timer_resume(void);
extern int using_apic_timer;
DEFINE_SPINLOCK(rtc_lock);
@@ -58,7 +58,7 @@ static int notsc __initdata = 0;
#undef HPET_HACK_ENABLE_DANGEROUS
unsigned int cpu_khz; /* TSC clocks / usec, not used here */
-unsigned long hpet_period; /* fsecs / HPET clock */
+static unsigned long hpet_period; /* fsecs / HPET clock */
unsigned long hpet_tick; /* HPET clocks / interrupt */
unsigned long vxtime_hz = PIT_TICK_RATE;
int report_lost_ticks; /* command line option */
@@ -551,11 +551,10 @@ unsigned long get_cmos_time(void)
BCD_TO_BIN(year);
/*
- * This will work up to Dec 31, 2069.
+ * x86-64 systems only exists since 2002.
+ * This will work up to Dec 31, 2100
*/
-
- if ((year += 1900) < 1970)
- year += 100;
+ year += 2000;
return mktime(year, mon, day, hour, min, sec);
}
@@ -980,6 +979,8 @@ static int timer_resume(struct sys_device *dev)
if (vxtime.hpet_address)
hpet_reenable();
+ else
+ i8254_timer_resume();
sec = ctime + clock_cmos_diff;
write_seqlock_irqsave(&xtime_lock,flags);
diff --git a/arch/x86_64/kernel/trampoline.S b/arch/x86_64/kernel/trampoline.S
index 5ae9f853b3935..6d9c9a8e7d0ea 100644
--- a/arch/x86_64/kernel/trampoline.S
+++ b/arch/x86_64/kernel/trampoline.S
@@ -37,7 +37,6 @@ r_base = .
mov %cs, %ax # Code and data in the same place
mov %ax, %ds
- mov $1, %bx # Flag an SMP trampoline
cli # We should be safe anyway
movl $0xA5A5A5A5, trampoline_data - r_base
@@ -46,31 +45,20 @@ r_base = .
lidt idt_48 - r_base # load idt with 0, 0
lgdt gdt_48 - r_base # load gdt with whatever is appropriate
- movw $__KERNEL_DS,%ax
- movw %ax,%ds
- movw %ax,%es
-
xor %ax, %ax
inc %ax # protected mode (PE) bit
lmsw %ax # into protected mode
- jmp flush_instr
-flush_instr:
- ljmpl $__KERNEL32_CS, $0x00100000
- # jump to startup_32 in arch/x86_64/kernel/head.S
+ # flaush prefetch and jump to startup_32 in arch/x86_64/kernel/head.S
+ ljmpl $__KERNEL32_CS, $(startup_32-__START_KERNEL_map)
+ # Careful these need to be in the same 64K segment as the above;
idt_48:
.word 0 # idt limit = 0
.word 0, 0 # idt base = 0L
gdt_48:
- .short 0x0800 # gdt limit = 2048, 256 GDT entries
- .globl tramp_gdt_ptr
-tramp_gdt_ptr:
- .long 0 # gdt base = gdt (first SMP CPU)
- # this is filled in by C because the 64bit
- # linker doesn't support absolute 32bit
- # relocations.
-
+ .short __KERNEL32_CS + 7 # gdt limit
+ .long cpu_gdt_table-__START_KERNEL_map
.globl trampoline_end
trampoline_end:
diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c
index 72e672ef3260f..d87ac6496cc2a 100644
--- a/arch/x86_64/kernel/traps.c
+++ b/arch/x86_64/kernel/traps.c
@@ -124,10 +124,10 @@ unsigned long *in_exception_stack(int cpu, unsigned long stack)
int k;
for (k = 0; k < N_EXCEPTION_STACKS; k++) {
struct tss_struct *tss = &per_cpu(init_tss, cpu);
- unsigned long end = tss->ist[k] + EXCEPTION_STKSZ;
+ unsigned long start = tss->ist[k] - EXCEPTION_STKSZ;
- if (stack >= tss->ist[k] && stack <= end)
- return (unsigned long *)end;
+ if (stack >= start && stack < tss->ist[k])
+ return (unsigned long *)tss->ist[k];
}
return NULL;
}
@@ -348,7 +348,6 @@ void oops_end(void)
die_owner = -1;
bust_spinlocks(0);
spin_unlock(&die_lock);
- local_irq_enable(); /* make sure back scroll still works */
if (panic_on_oops)
panic("Oops");
}
@@ -617,15 +616,6 @@ asmlinkage void default_do_nmi(struct pt_regs *regs)
mem_parity_error(reason, regs);
if (reason & 0x40)
io_check_error(reason, regs);
-
- /*
- * Reassert NMI in case it became active meanwhile
- * as it's edge-triggered.
- */
- outb(0x8f, 0x70);
- inb(0x71); /* dummy */
- outb(0x0f, 0x70);
- inb(0x71); /* dummy */
}
asmlinkage void do_int3(struct pt_regs * regs, long error_code)
diff --git a/arch/x86_64/kernel/vmlinux.lds.S b/arch/x86_64/kernel/vmlinux.lds.S
index 65108e17effae..59ebd5beda874 100644
--- a/arch/x86_64/kernel/vmlinux.lds.S
+++ b/arch/x86_64/kernel/vmlinux.lds.S
@@ -7,11 +7,12 @@
OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")
OUTPUT_ARCH(i386:x86-64)
-ENTRY(_start)
+ENTRY(phys_startup_64)
jiffies_64 = jiffies;
SECTIONS
{
. = 0xffffffff80100000;
+ phys_startup_64 = startup_64 - LOAD_OFFSET;
_text = .; /* Text and read-only data */
.text : {
*(.text)
diff --git a/arch/x86_64/kernel/vsyscall.S b/arch/x86_64/kernel/vsyscall.S
deleted file mode 100644
index 3bd9a27c7eede..0000000000000
--- a/arch/x86_64/kernel/vsyscall.S
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Code for the vsyscall page. This version uses the syscall instruction.
- */
-
-#include <asm/ia32_unistd.h>
-#include <asm/offset.h>
-
- .text
- .globl __kernel_vsyscall
- .type __kernel_vsyscall,@function
-__kernel_vsyscall:
-.LSTART_vsyscall:
- push %ebp
-.Lpush_ebp:
- movl %ecx, %ebp
- syscall
- popl %ebp
-.Lpop_ebp:
- ret
-.LEND_vsyscall:
- .size __kernel_vsyscall,.-.LSTART_vsyscall
-
- .balign 32
- .globl __kernel_sigreturn
- .type __kernel_sigreturn,@function
-__kernel_sigreturn:
-.LSTART_sigreturn:
- popl %eax
- movl $__NR_ia32_sigreturn, %eax
- syscall
-.LEND_sigreturn:
- .size __kernel_sigreturn,.-.LSTART_sigreturn
-
- .balign 32
- .globl __kernel_rt_sigreturn
- .type __kernel_rt_sigreturn,@function
-__kernel_rt_sigreturn:
-.LSTART_rt_sigreturn:
- movl $__NR_ia32_rt_sigreturn, %eax
- syscall
-.LEND_rt_sigreturn:
- .size __kernel_rt_sigreturn,.-.LSTART_rt_sigreturn
-
- .section .eh_frame,"a",@progbits
-.LSTARTFRAME:
- .long .LENDCIE-.LSTARTCIE
-.LSTARTCIE:
- .long 0 /* CIE ID */
- .byte 1 /* Version number */
- .string "zR" /* NUL-terminated augmentation string */
- .uleb128 1 /* Code alignment factor */
- .sleb128 -4 /* Data alignment factor */
- .byte 8 /* Return address register column */
- .uleb128 1 /* Augmentation value length */
- .byte 0x1b /* DW_EH_PE_pcrel|DW_EH_PE_sdata4. */
- .byte 0x0c /* DW_CFA_def_cfa */
- .uleb128 4
- .uleb128 4
- .byte 0x88 /* DW_CFA_offset, column 0x8 */
- .uleb128 1
- .align 4
-.LENDCIE:
-
- .long .LENDFDE1-.LSTARTFDE1 /* Length FDE */
-.LSTARTFDE1:
- .long .LSTARTFDE1-.LSTARTFRAME /* CIE pointer */
- .long .LSTART_vsyscall-. /* PC-relative start address */
- .long .LEND_vsyscall-.LSTART_vsyscall
- .uleb128 0 /* Augmentation length */
- /* What follows are the instructions for the table generation.
- We have to record all changes of the stack pointer. */
- .byte 0x40 + .Lpush_ebp-.LSTART_vsyscall /* DW_CFA_advance_loc */
- .byte 0x0e /* DW_CFA_def_cfa_offset */
- .uleb128 8
- .byte 0x85, 0x02 /* DW_CFA_offset %ebp -8 */
- .byte 0x40 + .Lpop_ebp-.Lpush_ebp /* DW_CFA_advance_loc */
- .byte 0xc5 /* DW_CFA_restore %ebp */
- .byte 0x0e /* DW_CFA_def_cfa_offset */
- .uleb128 4
- .align 4
-.LENDFDE1:
-
- .long .LENDFDE2-.LSTARTFDE2 /* Length FDE */
-.LSTARTFDE2:
- .long .LSTARTFDE2-.LSTARTFRAME /* CIE pointer */
- /* HACK: The dwarf2 unwind routines will subtract 1 from the
- return address to get an address in the middle of the
- presumed call instruction. Since we didn't get here via
- a call, we need to include the nop before the real start
- to make up for it. */
- .long .LSTART_sigreturn-1-. /* PC-relative start address */
- .long .LEND_sigreturn-.LSTART_sigreturn+1
- .uleb128 0 /* Augmentation length */
- /* What follows are the instructions for the table generation.
- We record the locations of each register saved. This is
- complicated by the fact that the "CFA" is always assumed to
- be the value of the stack pointer in the caller. This means
- that we must define the CFA of this body of code to be the
- saved value of the stack pointer in the sigcontext. Which
- also means that there is no fixed relation to the other
- saved registers, which means that we must use DW_CFA_expression
- to compute their addresses. It also means that when we
- adjust the stack with the popl, we have to do it all over again. */
-
-#define do_cfa_expr(offset) \
- .byte 0x0f; /* DW_CFA_def_cfa_expression */ \
- .uleb128 1f-0f; /* length */ \
-0: .byte 0x74; /* DW_OP_breg4 */ \
- .sleb128 offset; /* offset */ \
- .byte 0x06; /* DW_OP_deref */ \
-1:
-
-#define do_expr(regno, offset) \
- .byte 0x10; /* DW_CFA_expression */ \
- .uleb128 regno; /* regno */ \
- .uleb128 1f-0f; /* length */ \
-0: .byte 0x74; /* DW_OP_breg4 */ \
- .sleb128 offset; /* offset */ \
-1:
-
- do_cfa_expr(IA32_SIGCONTEXT_esp+4)
- do_expr(0, IA32_SIGCONTEXT_eax+4)
- do_expr(1, IA32_SIGCONTEXT_ecx+4)
- do_expr(2, IA32_SIGCONTEXT_edx+4)
- do_expr(3, IA32_SIGCONTEXT_ebx+4)
- do_expr(5, IA32_SIGCONTEXT_ebp+4)
- do_expr(6, IA32_SIGCONTEXT_esi+4)
- do_expr(7, IA32_SIGCONTEXT_edi+4)
- do_expr(8, IA32_SIGCONTEXT_eip+4)
-
- .byte 0x42 /* DW_CFA_advance_loc 2 -- nop; popl eax. */
-
- do_cfa_expr(IA32_SIGCONTEXT_esp)
- do_expr(0, IA32_SIGCONTEXT_eax)
- do_expr(1, IA32_SIGCONTEXT_ecx)
- do_expr(2, IA32_SIGCONTEXT_edx)
- do_expr(3, IA32_SIGCONTEXT_ebx)
- do_expr(5, IA32_SIGCONTEXT_ebp)
- do_expr(6, IA32_SIGCONTEXT_esi)
- do_expr(7, IA32_SIGCONTEXT_edi)
- do_expr(8, IA32_SIGCONTEXT_eip)
-
- .align 4
-.LENDFDE2:
-
- .long .LENDFDE3-.LSTARTFDE3 /* Length FDE */
-.LSTARTFDE3:
- .long .LSTARTFDE3-.LSTARTFRAME /* CIE pointer */
- /* HACK: See above wrt unwind library assumptions. */
- .long .LSTART_rt_sigreturn-1-. /* PC-relative start address */
- .long .LEND_rt_sigreturn-.LSTART_rt_sigreturn+1
- .uleb128 0 /* Augmentation */
- /* What follows are the instructions for the table generation.
- We record the locations of each register saved. This is
- slightly less complicated than the above, since we don't
- modify the stack pointer in the process. */
-
- do_cfa_expr(IA32_RT_SIGFRAME_sigcontext-4 + IA32_SIGCONTEXT_esp)
- do_expr(0, IA32_RT_SIGFRAME_sigcontext-4 + IA32_SIGCONTEXT_eax)
- do_expr(1, IA32_RT_SIGFRAME_sigcontext-4 + IA32_SIGCONTEXT_ecx)
- do_expr(2, IA32_RT_SIGFRAME_sigcontext-4 + IA32_SIGCONTEXT_edx)
- do_expr(3, IA32_RT_SIGFRAME_sigcontext-4 + IA32_SIGCONTEXT_ebx)
- do_expr(5, IA32_RT_SIGFRAME_sigcontext-4 + IA32_SIGCONTEXT_ebp)
- do_expr(6, IA32_RT_SIGFRAME_sigcontext-4 + IA32_SIGCONTEXT_esi)
- do_expr(7, IA32_RT_SIGFRAME_sigcontext-4 + IA32_SIGCONTEXT_edi)
- do_expr(8, IA32_RT_SIGFRAME_sigcontext-4 + IA32_SIGCONTEXT_eip)
-
- .align 4
-.LENDFDE3:
diff --git a/arch/x86_64/kernel/vsyscall.c b/arch/x86_64/kernel/vsyscall.c
index f28a07c77b485..b4b8dc59663ad 100644
--- a/arch/x86_64/kernel/vsyscall.c
+++ b/arch/x86_64/kernel/vsyscall.c
@@ -9,30 +9,14 @@
* a different vsyscall implementation for Linux/IA32 and for the name.
*
* vsyscall 1 is located at -10Mbyte, vsyscall 2 is located
- * at virtual address -10Mbyte+1024bytes etc... There are at max 8192
+ * at virtual address -10Mbyte+1024bytes etc... There are at max 4
* vsyscalls. One vsyscall can reserve more than 1 slot to avoid
- * jumping out of line if necessary.
+ * jumping out of line if necessary. We cannot add more with this
+ * mechanism because older kernels won't return -ENOSYS.
+ * If we want more than four we need a vDSO.
*
- * Note: the concept clashes with user mode linux. If you use UML just
- * set the kernel.vsyscall sysctl to 0.
- */
-
-/*
- * TODO 2001-03-20:
- *
- * 1) make page fault handler detect faults on page1-page-last of the vsyscall
- * virtual space, and make it increase %rip and write -ENOSYS in %rax (so
- * we'll be able to upgrade to a new glibc without upgrading kernel after
- * we add more vsyscalls.
- * 2) Possibly we need a fixmap table for the vsyscalls too if we want
- * to avoid SIGSEGV and we want to return -EFAULT from the vsyscalls as well.
- * Can we segfault inside a "syscall"? We can fix this anytime and those fixes
- * won't be visible for userspace. Not fixing this is a noop for correct programs,
- * broken programs will segfault and there's no security risk until we choose to
- * fix it.
- *
- * These are not urgent things that we need to address only before shipping the first
- * production binary kernels.
+ * Note: the concept clashes with user mode linux. If you use UML and
+ * want per guest time just set the kernel.vsyscall64 sysctl to 0.
*/
#include <linux/time.h>
@@ -41,6 +25,7 @@
#include <linux/timer.h>
#include <linux/seqlock.h>
#include <linux/jiffies.h>
+#include <linux/sysctl.h>
#include <asm/vsyscall.h>
#include <asm/pgtable.h>
@@ -62,8 +47,7 @@ static force_inline void timeval_normalize(struct timeval * tv)
time_t __sec;
__sec = tv->tv_usec / 1000000;
- if (__sec)
- {
+ if (__sec) {
tv->tv_usec %= 1000000;
tv->tv_sec += __sec;
}
@@ -84,10 +68,11 @@ static force_inline void do_vgettimeofday(struct timeval * tv)
if (__vxtime.mode == VXTIME_TSC) {
sync_core();
rdtscll(t);
- if (t < __vxtime.last_tsc) t = __vxtime.last_tsc;
+ if (t < __vxtime.last_tsc)
+ t = __vxtime.last_tsc;
usec += ((t - __vxtime.last_tsc) *
__vxtime.tsc_quot) >> 32;
- /* See comment in x86_64 do_gettimeofday. */
+ /* See comment in x86_64 do_gettimeofday. */
} else {
usec += ((readl((void *)fix_to_virt(VSYSCALL_HPET) + 0xf0) -
__vxtime.last) * __vxtime.quot) >> 32;
@@ -101,14 +86,13 @@ 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)
{
- *tz = __sys_tz;
+ *tz = __sys_tz;
}
-
static force_inline int gettimeofday(struct timeval *tv, struct timezone *tz)
{
int ret;
- asm volatile("syscall"
+ asm volatile("vsysc2: syscall"
: "=a" (ret)
: "0" (__NR_gettimeofday),"D" (tv),"S" (tz) : __syscall_clobber );
return ret;
@@ -117,7 +101,7 @@ static force_inline int gettimeofday(struct timeval *tv, struct timezone *tz)
static force_inline long time_syscall(long *t)
{
long secs;
- asm volatile("syscall"
+ asm volatile("vsysc1: syscall"
: "=a" (secs)
: "0" (__NR_time),"D" (t) : __syscall_clobber);
return secs;
@@ -126,7 +110,7 @@ static force_inline long time_syscall(long *t)
static int __vsyscall(0) vgettimeofday(struct timeval * tv, struct timezone * tz)
{
if (unlikely(!__sysctl_vsyscall))
- return gettimeofday(tv,tz);
+ return gettimeofday(tv,tz);
if (tv)
do_vgettimeofday(tv);
if (tz)
@@ -153,9 +137,71 @@ static long __vsyscall(2) venosys_0(void)
static long __vsyscall(3) venosys_1(void)
{
return -ENOSYS;
+}
+
+#ifdef CONFIG_SYSCTL
+
+#define SYSCALL 0x050f
+#define NOP2 0x9090
+/*
+ * NOP out syscall in vsyscall page when not needed.
+ */
+static int vsyscall_sysctl_change(ctl_table *ctl, int write, struct file * filp,
+ void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+ extern u16 vsysc1, vsysc2;
+ u16 *map1, *map2;
+ int ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos);
+ if (!write)
+ return ret;
+ /* gcc has some trouble with __va(__pa()), so just do it this
+ way. */
+ map1 = ioremap(__pa_symbol(&vsysc1), 2);
+ if (!map1)
+ return -ENOMEM;
+ map2 = ioremap(__pa_symbol(&vsysc2), 2);
+ if (!map2) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ if (!sysctl_vsyscall) {
+ *map1 = SYSCALL;
+ *map2 = SYSCALL;
+ } else {
+ *map1 = NOP2;
+ *map2 = NOP2;
+ }
+ iounmap(map2);
+out:
+ iounmap(map1);
+ return ret;
}
+static int vsyscall_sysctl_nostrat(ctl_table *t, int __user *name, int nlen,
+ void __user *oldval, size_t __user *oldlenp,
+ void __user *newval, size_t newlen,
+ void **context)
+{
+ return -ENOSYS;
+}
+
+static ctl_table kernel_table2[] = {
+ { .ctl_name = 99, .procname = "vsyscall64",
+ .data = &sysctl_vsyscall, .maxlen = sizeof(int), .mode = 0644,
+ .strategy = vsyscall_sysctl_nostrat,
+ .proc_handler = vsyscall_sysctl_change },
+ { 0, }
+};
+
+static ctl_table kernel_root_table2[] = {
+ { .ctl_name = CTL_KERN, .procname = "kernel", .mode = 0555,
+ .child = kernel_table2 },
+ { 0 },
+};
+
+#endif
+
static void __init map_vsyscall(void)
{
extern char __vsyscall_0;
@@ -166,13 +212,13 @@ static void __init map_vsyscall(void)
static int __init vsyscall_init(void)
{
- BUG_ON(((unsigned long) &vgettimeofday !=
- VSYSCALL_ADDR(__NR_vgettimeofday)));
+ BUG_ON(((unsigned long) &vgettimeofday !=
+ VSYSCALL_ADDR(__NR_vgettimeofday)));
BUG_ON((unsigned long) &vtime != VSYSCALL_ADDR(__NR_vtime));
BUG_ON((VSYSCALL_ADDR(0) != __fix_to_virt(VSYSCALL_FIRST_PAGE)));
map_vsyscall();
- sysctl_vsyscall = 1;
-
+ sysctl_vsyscall = 1;
+ register_sysctl_table(kernel_root_table2, 0);
return 0;
}
diff --git a/arch/x86_64/kernel/x8664_ksyms.c b/arch/x86_64/kernel/x8664_ksyms.c
index a6396131eae56..88626e626886e 100644
--- a/arch/x86_64/kernel/x8664_ksyms.c
+++ b/arch/x86_64/kernel/x8664_ksyms.c
@@ -103,7 +103,6 @@ EXPORT_SYMBOL(pci_free_consistent);
#endif
#ifdef CONFIG_PCI
-EXPORT_SYMBOL(pcibios_penalize_isa_irq);
EXPORT_SYMBOL(pci_mem_start);
#endif
@@ -217,7 +216,6 @@ EXPORT_SYMBOL(__supported_pte_mask);
#ifdef CONFIG_SMP
EXPORT_SYMBOL(flush_tlb_page);
-EXPORT_SYMBOL_GPL(flush_tlb_all);
#endif
EXPORT_SYMBOL(cpu_khz);
diff --git a/arch/x86_64/lib/bitops.c b/arch/x86_64/lib/bitops.c
index 994d766503dd9..a29fb75b33ac4 100644
--- a/arch/x86_64/lib/bitops.c
+++ b/arch/x86_64/lib/bitops.c
@@ -1,4 +1,3 @@
-#include <linux/module.h>
#include <linux/bitops.h>
#undef find_first_zero_bit
@@ -134,6 +133,8 @@ long find_next_bit(const unsigned long * addr, long size, long offset)
return (offset + set + res);
}
+#include <linux/module.h>
+
EXPORT_SYMBOL(find_next_bit);
EXPORT_SYMBOL(find_first_bit);
EXPORT_SYMBOL(find_first_zero_bit);
diff --git a/arch/x86_64/lib/delay.c b/arch/x86_64/lib/delay.c
index 05689cc549017..6e2d66472eb19 100644
--- a/arch/x86_64/lib/delay.c
+++ b/arch/x86_64/lib/delay.c
@@ -21,7 +21,7 @@ int x86_udelay_tsc = 0; /* Delay via TSC */
void __delay(unsigned long loops)
{
- unsigned long bclock, now;
+ unsigned bclock, now;
rdtscl(bclock);
do
diff --git a/arch/x86_64/lib/getuser.S b/arch/x86_64/lib/getuser.S
index 61a1f75aba878..f94ea8a440515 100644
--- a/arch/x86_64/lib/getuser.S
+++ b/arch/x86_64/lib/getuser.S
@@ -2,6 +2,7 @@
* __get_user functions.
*
* (C) Copyright 1998 Linus Torvalds
+ * (C) Copyright 2005 Andi Kleen
*
* These functions have a non-standard call interface
* to make them more efficient, especially as they
@@ -12,12 +13,14 @@
/*
* __get_user_X
*
- * Inputs: %rax contains the address
+ * Inputs: %rcx contains the address.
+ * The register is modified, but all changes are undone
+ * before returning because the C code doesn't know about it.
*
* Outputs: %rax is error code (0 or -EFAULT)
* %rdx contains zero-extended value
*
- * %rbx is destroyed.
+ * %r8 is destroyed.
*
* These functions should not modify any other registers,
* as they get called from within inline assembly.
@@ -33,52 +36,60 @@
.p2align 4
.globl __get_user_1
__get_user_1:
- GET_THREAD_INFO(%rbx)
- cmpq threadinfo_addr_limit(%rbx),%rax
+ GET_THREAD_INFO(%r8)
+ cmpq threadinfo_addr_limit(%r8),%rcx
jae bad_get_user
-1: movzb (%rax),%edx
- xorq %rax,%rax
+1: movzb (%rcx),%edx
+ xorl %eax,%eax
ret
.p2align 4
.globl __get_user_2
__get_user_2:
- GET_THREAD_INFO(%rbx)
- addq $1,%rax
- jc bad_get_user
- cmpq threadinfo_addr_limit(%rbx),%rax
- jae bad_get_user
-2: movzwl -1(%rax),%edx
- xorq %rax,%rax
+ GET_THREAD_INFO(%r8)
+ addq $1,%rcx
+ jc 20f
+ cmpq threadinfo_addr_limit(%r8),%rcx
+ jae 20f
+ decq %rcx
+2: movzwl (%rcx),%edx
+ xorl %eax,%eax
ret
+20: decq %rcx
+ jmp bad_get_user
.p2align 4
.globl __get_user_4
__get_user_4:
- GET_THREAD_INFO(%rbx)
- addq $3,%rax
- jc bad_get_user
- cmpq threadinfo_addr_limit(%rbx),%rax
- jae bad_get_user
-3: movl -3(%rax),%edx
- xorq %rax,%rax
+ GET_THREAD_INFO(%r8)
+ addq $3,%rcx
+ jc 30f
+ cmpq threadinfo_addr_limit(%r8),%rcx
+ jae 30f
+ subq $3,%rcx
+3: movl (%rcx),%edx
+ xorl %eax,%eax
ret
+30: subq $3,%rcx
+ jmp bad_get_user
.p2align 4
.globl __get_user_8
__get_user_8:
- GET_THREAD_INFO(%rbx)
- addq $7,%rax
+ GET_THREAD_INFO(%r8)
+ addq $7,%rcx
jc bad_get_user
- cmpq threadinfo_addr_limit(%rbx),%rax
+ cmpq threadinfo_addr_limit(%r8),%rcx
jae bad_get_user
-4: movq -7(%rax),%rdx
- xorq %rax,%rax
+ subq $7,%rcx
+4: movq (%rcx),%rdx
+ xorl %eax,%eax
ret
+40: subq $7,%rcx
+ jmp bad_get_user
-ENTRY(bad_get_user)
bad_get_user:
- xorq %rdx,%rdx
+ xorl %edx,%edx
movq $(-EFAULT),%rax
ret
diff --git a/arch/x86_64/lib/putuser.S b/arch/x86_64/lib/putuser.S
index 4d287ceeab73c..0dee1fdcb1628 100644
--- a/arch/x86_64/lib/putuser.S
+++ b/arch/x86_64/lib/putuser.S
@@ -2,80 +2,81 @@
* __put_user functions.
*
* (C) Copyright 1998 Linus Torvalds
+ * (C) Copyright 2005 Andi Kleen
*
* These functions have a non-standard call interface
- * to make them more efficient.
+ * to make them more efficient, especially as they
+ * return an error value in addition to the "real"
+ * return value.
*/
/*
* __put_user_X
*
- * Inputs: %rax contains the address
- * %rdx contains the value
+ * Inputs: %rcx contains the address
+ * %rdx contains new value
*
* Outputs: %rax is error code (0 or -EFAULT)
- * %rbx is corrupted (will contain "current_task").
+ *
+ * %r8 is destroyed.
*
* These functions should not modify any other registers,
* as they get called from within inline assembly.
*/
-/* FIXME: putuser.S should be really merged with getuser.S, and preprocessor should be used to keep code duplication lower */
-
#include <linux/linkage.h>
#include <asm/page.h>
#include <asm/errno.h>
#include <asm/offset.h>
#include <asm/thread_info.h>
-.text
-.p2align
+ .text
+ .p2align 4
.globl __put_user_1
__put_user_1:
- GET_THREAD_INFO(%rbx)
- cmpq threadinfo_addr_limit(%rbx),%rax
+ GET_THREAD_INFO(%r8)
+ cmpq threadinfo_addr_limit(%r8),%rcx
jae bad_put_user
-1: movb %dl,(%rax)
- xorq %rax,%rax
+1: movb %dl,(%rcx)
+ xorl %eax,%eax
ret
-.p2align
+ .p2align 4
.globl __put_user_2
__put_user_2:
- GET_THREAD_INFO(%rbx)
- addq $1,%rax
- jc bad_put_user
- cmpq threadinfo_addr_limit(%rbx),%rax
- jae bad_put_user
-2: movw %dx,-1(%rax)
- xorq %rax,%rax
+ GET_THREAD_INFO(%r8)
+ addq $1,%rcx
+ jc bad_put_user
+ cmpq threadinfo_addr_limit(%r8),%rcx
+ jae bad_put_user
+2: movw %dx,-1(%rcx)
+ xorl %eax,%eax
ret
-.p2align
+ .p2align 4
.globl __put_user_4
__put_user_4:
- GET_THREAD_INFO(%rbx)
- addq $3,%rax
- jc bad_put_user
- cmpq threadinfo_addr_limit(%rbx),%rax
- jae bad_put_user
-3: movl %edx,-3(%rax)
- xorq %rax,%rax
+ GET_THREAD_INFO(%r8)
+ addq $3,%rcx
+ jc bad_put_user
+ cmpq threadinfo_addr_limit(%r8),%rcx
+ jae bad_put_user
+3: movl %edx,-3(%rcx)
+ xorl %eax,%eax
ret
-.p2align
+ .p2align 4
.globl __put_user_8
__put_user_8:
- GET_THREAD_INFO(%rbx)
- addq $7,%rax
- jc bad_put_user
- cmpq threadinfo_addr_limit(%rbx),%rax
- jae bad_put_user
-4: movq %rdx,-7(%rax)
- xorq %rax,%rax
+ GET_THREAD_INFO(%r8)
+ addq $7,%rcx
+ jc bad_put_user
+ cmpq threadinfo_addr_limit(%r8),%rcx
+ jae bad_put_user
+4: movq %rdx,-7(%rcx)
+ xorl %eax,%eax
ret
-ENTRY(bad_put_user)
bad_put_user:
movq $(-EFAULT),%rax
ret
@@ -84,5 +85,5 @@ bad_put_user:
.quad 1b,bad_put_user
.quad 2b,bad_put_user
.quad 3b,bad_put_user
- .quad 4b,bad_put_user
+ .quad 4b,bad_put_user
.previous
diff --git a/arch/x86_64/mm/extable.c b/arch/x86_64/mm/extable.c
index 7e039db623a03..2d78f9fb40354 100644
--- a/arch/x86_64/mm/extable.c
+++ b/arch/x86_64/mm/extable.c
@@ -33,26 +33,3 @@ search_extable(const struct exception_table_entry *first,
}
return NULL;
}
-
-/* When an exception handler is in an non standard section (like __init)
- the fixup table can end up unordered. Fix that here. */
-void sort_extable(struct exception_table_entry *start,
- struct exception_table_entry *finish)
-{
- struct exception_table_entry *e;
- int change;
-
- /* The input is near completely presorted, which makes bubble sort the
- best (and simplest) sort algorithm. */
- do {
- change = 0;
- for (e = start+1; e < finish; e++) {
- if (e->insn < e[-1].insn) {
- struct exception_table_entry tmp = e[-1];
- e[-1] = e[0];
- e[0] = tmp;
- change = 1;
- }
- }
- } while (change != 0);
-}
diff --git a/arch/x86_64/mm/ioremap.c b/arch/x86_64/mm/ioremap.c
index 911262d8ca199..74ec8554b195d 100644
--- a/arch/x86_64/mm/ioremap.c
+++ b/arch/x86_64/mm/ioremap.c
@@ -18,6 +18,9 @@
#include <asm/tlbflush.h>
#include <asm/proto.h>
+#define ISA_START_ADDRESS 0xa0000
+#define ISA_END_ADDRESS 0x100000
+
static inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned long size,
unsigned long phys_addr, unsigned long flags)
{
@@ -172,7 +175,7 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l
/*
* Don't remap the low PCI/ISA area, it's always mapped..
*/
- if (phys_addr >= 0xA0000 && last_addr < 0x100000)
+ if (phys_addr >= ISA_START_ADDRESS && last_addr < ISA_END_ADDRESS)
return (__force void __iomem *)phys_to_virt(phys_addr);
#ifndef CONFIG_DISCONTIGMEM
@@ -252,6 +255,9 @@ void iounmap(volatile void __iomem *addr)
if (addr <= high_memory)
return;
+ if (addr >= phys_to_virt(ISA_START_ADDRESS) &&
+ addr < phys_to_virt(ISA_END_ADDRESS))
+ return;
write_lock(&vmlist_lock);
for (p = vmlist, pprev = &vmlist; p != NULL; pprev = &p->next, p = *pprev)
@@ -267,8 +273,8 @@ void iounmap(volatile void __iomem *addr)
p->phys_addr + p->size - 1 < virt_to_phys(high_memory)) {
/* p->size includes the guard page, but cpa doesn't like that */
change_page_attr(virt_to_page(__va(p->phys_addr)),
- (p->size - PAGE_SIZE) >> PAGE_SHIFT,
- PAGE_KERNEL);
+ p->size >> PAGE_SHIFT,
+ PAGE_KERNEL);
global_flush_tlb();
}
out_unlock:
diff --git a/arch/x86_64/mm/srat.c b/arch/x86_64/mm/srat.c
index c0622bd41617f..5d01b31472e1f 100644
--- a/arch/x86_64/mm/srat.c
+++ b/arch/x86_64/mm/srat.c
@@ -23,7 +23,7 @@ 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] __initdata = { [0 ... 255] = 0xff };
+static __u8 pxm2node[256] = { [0 ... 255] = 0xff };
static __init int setup_node(int pxm)
{
diff --git a/arch/x86_64/pci/k8-bus.c b/arch/x86_64/pci/k8-bus.c
index d1c728acddd76..62349c78db574 100644
--- a/arch/x86_64/pci/k8-bus.c
+++ b/arch/x86_64/pci/k8-bus.c
@@ -29,7 +29,7 @@ __init static int
fill_mp_bus_to_cpumask(void)
{
struct pci_dev *nb_dev = NULL;
- int i, j;
+ int i, j, printed;
u32 ldtbus, nid;
static int lbnr[3] = {
LDT_BUS_NUMBER_REGISTER_0,
@@ -60,11 +60,15 @@ fill_mp_bus_to_cpumask(void)
}
/* quick sanity check */
+ printed = 0;
for (i = 0; i < 256; i++) {
if (cpus_empty(pci_bus_to_cpumask[i])) {
- printk(KERN_ERR
- "k8-bus.c: bus %i has empty cpu mask\n", i);
pci_bus_to_cpumask[i] = CPU_MASK_ALL;
+ if (printed)
+ continue;
+ printk(KERN_ERR
+ "k8-bus.c: some busses have empty cpu mask\n");
+ printed = 1;
}
}
diff --git a/arch/x86_64/pci/mmconfig.c b/arch/x86_64/pci/mmconfig.c
index 142b9befee3fa..b693c232fd073 100644
--- a/arch/x86_64/pci/mmconfig.c
+++ b/arch/x86_64/pci/mmconfig.c
@@ -17,12 +17,13 @@ u32 pci_mmcfg_base_addr;
/* Static virtual mapping of the MMCONFIG aperture */
char *pci_mmcfg_virt;
-static inline char *pci_dev_base(int bus, int devfn)
+static inline char *pci_dev_base(unsigned int bus, unsigned int devfn)
{
return pci_mmcfg_virt + ((bus << 20) | (devfn << 12));
}
-static int pci_mmcfg_read(int seg, int bus, int devfn, int reg, int len, u32 *value)
+static int pci_mmcfg_read(unsigned int seg, unsigned int bus,
+ unsigned int devfn, int reg, int len, u32 *value)
{
char *addr = pci_dev_base(bus, devfn);
@@ -44,7 +45,8 @@ static int pci_mmcfg_read(int seg, int bus, int devfn, int reg, int len, u32 *va
return 0;
}
-static int pci_mmcfg_write(int seg, int bus, int devfn, int reg, int len, u32 value)
+static int pci_mmcfg_write(unsigned int seg, unsigned int bus,
+ unsigned int devfn, int reg, int len, u32 value)
{
char *addr = pci_dev_base(bus,devfn);
diff --git a/crypto/Kconfig b/crypto/Kconfig
index a477f2a3275e9..536754faf4d27 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -79,6 +79,19 @@ config CRYPTO_WP512
See also:
<http://planeta.terra.com.br/informatica/paulobarreto/WhirlpoolPage.html>
+config CRYPTO_TGR192
+ tristate "Tiger digest algorithms"
+ depends on CRYPTO
+ help
+ Tiger hash algorithm 192, 160 and 128-bit hashes
+
+ Tiger is a hash function optimized for 64-bit processors while
+ still having decent performance on 32-bit processors.
+ Tiger was developed by Ross Anderson and Eli Biham.
+
+ See also:
+ <http://www.cs.technion.ac.il/~biham/Reports/Tiger/>.
+
config CRYPTO_DES
tristate "DES and Triple DES EDE cipher algorithms"
depends on CRYPTO
diff --git a/crypto/Makefile b/crypto/Makefile
index 96467bfd7b2e8..d287b9e60c472 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -15,6 +15,7 @@ obj-$(CONFIG_CRYPTO_SHA1) += sha1.o
obj-$(CONFIG_CRYPTO_SHA256) += sha256.o
obj-$(CONFIG_CRYPTO_SHA512) += sha512.o
obj-$(CONFIG_CRYPTO_WP512) += wp512.o
+obj-$(CONFIG_CRYPTO_TGR192) += tgr192.o
obj-$(CONFIG_CRYPTO_DES) += des.o
obj-$(CONFIG_CRYPTO_BLOWFISH) += blowfish.o
obj-$(CONFIG_CRYPTO_TWOFISH) += twofish.o
diff --git a/crypto/aes.c b/crypto/aes.c
index 94b89a9c74938..d0dd7c3c52780 100644
--- a/crypto/aes.c
+++ b/crypto/aes.c
@@ -64,23 +64,6 @@
#define AES_BLOCK_SIZE 16
-static inline
-u32 generic_rotr32 (const u32 x, const unsigned bits)
-{
- const unsigned n = bits % 32;
- return (x >> n) | (x << (32 - n));
-}
-
-static inline
-u32 generic_rotl32 (const u32 x, const unsigned bits)
-{
- const unsigned n = bits % 32;
- return (x << n) | (x >> (32 - n));
-}
-
-#define rotl generic_rotl32
-#define rotr generic_rotr32
-
/*
* #define byte(x, nr) ((unsigned char)((x) >> (nr*8)))
*/
@@ -191,26 +174,26 @@ gen_tabs (void)
t = p;
fl_tab[0][i] = t;
- fl_tab[1][i] = rotl (t, 8);
- fl_tab[2][i] = rotl (t, 16);
- fl_tab[3][i] = rotl (t, 24);
+ fl_tab[1][i] = rol32(t, 8);
+ fl_tab[2][i] = rol32(t, 16);
+ fl_tab[3][i] = rol32(t, 24);
t = ((u32) ff_mult (2, p)) |
((u32) p << 8) |
((u32) p << 16) | ((u32) ff_mult (3, p) << 24);
ft_tab[0][i] = t;
- ft_tab[1][i] = rotl (t, 8);
- ft_tab[2][i] = rotl (t, 16);
- ft_tab[3][i] = rotl (t, 24);
+ ft_tab[1][i] = rol32(t, 8);
+ ft_tab[2][i] = rol32(t, 16);
+ ft_tab[3][i] = rol32(t, 24);
p = isb_tab[i];
t = p;
il_tab[0][i] = t;
- il_tab[1][i] = rotl (t, 8);
- il_tab[2][i] = rotl (t, 16);
- il_tab[3][i] = rotl (t, 24);
+ il_tab[1][i] = rol32(t, 8);
+ il_tab[2][i] = rol32(t, 16);
+ il_tab[3][i] = rol32(t, 24);
t = ((u32) ff_mult (14, p)) |
((u32) ff_mult (9, p) << 8) |
@@ -218,9 +201,9 @@ gen_tabs (void)
((u32) ff_mult (11, p) << 24);
it_tab[0][i] = t;
- it_tab[1][i] = rotl (t, 8);
- it_tab[2][i] = rotl (t, 16);
- it_tab[3][i] = rotl (t, 24);
+ it_tab[1][i] = rol32(t, 8);
+ it_tab[2][i] = rol32(t, 16);
+ it_tab[3][i] = rol32(t, 24);
}
}
@@ -232,14 +215,14 @@ gen_tabs (void)
w = star_x(v); \
t = w ^ (x); \
(y) = u ^ v ^ w; \
- (y) ^= rotr(u ^ t, 8) ^ \
- rotr(v ^ t, 16) ^ \
- rotr(t,24)
+ (y) ^= ror32(u ^ t, 8) ^ \
+ ror32(v ^ t, 16) ^ \
+ ror32(t,24)
/* initialise the key schedule from the user supplied key */
#define loop4(i) \
-{ t = rotr(t, 8); t = ls_box(t) ^ rco_tab[i]; \
+{ t = ror32(t, 8); t = ls_box(t) ^ rco_tab[i]; \
t ^= E_KEY[4 * i]; E_KEY[4 * i + 4] = t; \
t ^= E_KEY[4 * i + 1]; E_KEY[4 * i + 5] = t; \
t ^= E_KEY[4 * i + 2]; E_KEY[4 * i + 6] = t; \
@@ -247,7 +230,7 @@ gen_tabs (void)
}
#define loop6(i) \
-{ t = rotr(t, 8); t = ls_box(t) ^ rco_tab[i]; \
+{ t = ror32(t, 8); t = ls_box(t) ^ rco_tab[i]; \
t ^= E_KEY[6 * i]; E_KEY[6 * i + 6] = t; \
t ^= E_KEY[6 * i + 1]; E_KEY[6 * i + 7] = t; \
t ^= E_KEY[6 * i + 2]; E_KEY[6 * i + 8] = t; \
@@ -257,7 +240,7 @@ gen_tabs (void)
}
#define loop8(i) \
-{ t = rotr(t, 8); ; t = ls_box(t) ^ rco_tab[i]; \
+{ t = ror32(t, 8); ; t = ls_box(t) ^ rco_tab[i]; \
t ^= E_KEY[8 * i]; E_KEY[8 * i + 8] = t; \
t ^= E_KEY[8 * i + 1]; E_KEY[8 * i + 9] = t; \
t ^= E_KEY[8 * i + 2]; E_KEY[8 * i + 10] = t; \
diff --git a/crypto/blowfish.c b/crypto/blowfish.c
index 83d575557c57e..a8b29d54e7d81 100644
--- a/crypto/blowfish.c
+++ b/crypto/blowfish.c
@@ -349,8 +349,8 @@ static void encrypt_block(struct bf_ctx *bctx, u32 *dst, u32 *src)
static void bf_encrypt(void *ctx, u8 *dst, const u8 *src)
{
- const u32 *in_blk = (const u32 *)src;
- u32 *const out_blk = (u32 *)dst;
+ const __be32 *in_blk = (const __be32 *)src;
+ __be32 *const out_blk = (__be32 *)dst;
u32 in32[2], out32[2];
in32[0] = be32_to_cpu(in_blk[0]);
@@ -362,8 +362,8 @@ static void bf_encrypt(void *ctx, u8 *dst, const u8 *src)
static void bf_decrypt(void *ctx, u8 *dst, const u8 *src)
{
- const u32 *in_blk = (const u32 *)src;
- u32 *const out_blk = (u32 *)dst;
+ const __be32 *in_blk = (const __be32 *)src;
+ __be32 *const out_blk = (__be32 *)dst;
const u32 *P = ((struct bf_ctx *)ctx)->p;
const u32 *S = ((struct bf_ctx *)ctx)->s;
u32 yl = be32_to_cpu(in_blk[0]);
diff --git a/crypto/cast5.c b/crypto/cast5.c
index 83911e20c5436..bc42f42b4fe30 100644
--- a/crypto/cast5.c
+++ b/crypto/cast5.c
@@ -567,14 +567,11 @@ static const u32 sb8[256] = {
0xeaee6801, 0x8db2a283, 0xea8bf59e
};
-
-#define rol(n,x) ( ((x) << (n)) | ((x) >> (32-(n))) )
-
-#define F1(D,m,r) ( (I = ((m) + (D))), (I=rol((r),I)), \
+#define F1(D,m,r) ( (I = ((m) + (D))), (I=rol32(I,(r))), \
(((s1[I >> 24] ^ s2[(I>>16)&0xff]) - s3[(I>>8)&0xff]) + s4[I&0xff]) )
-#define F2(D,m,r) ( (I = ((m) ^ (D))), (I=rol((r),I)), \
+#define F2(D,m,r) ( (I = ((m) ^ (D))), (I=rol32(I,(r))), \
(((s1[I >> 24] - s2[(I>>16)&0xff]) + s3[(I>>8)&0xff]) ^ s4[I&0xff]) )
-#define F3(D,m,r) ( (I = ((m) - (D))), (I=rol((r),I)), \
+#define F3(D,m,r) ( (I = ((m) - (D))), (I=rol32(I,(r))), \
(((s1[I >> 24] + s2[(I>>16)&0xff]) ^ s3[(I>>8)&0xff]) - s4[I&0xff]) )
diff --git a/crypto/cast6.c b/crypto/cast6.c
index 66f683b354694..3eb0810734233 100644
--- a/crypto/cast6.c
+++ b/crypto/cast6.c
@@ -33,13 +33,11 @@ struct cast6_ctx {
u8 Kr[12][4];
};
-#define rol(n,x) ( ((x) << (n)) | ((x) >> (32-(n))) )
-
-#define F1(D,r,m) ( (I = ((m) + (D))), (I=rol((r),I)), \
+#define F1(D,r,m) ( (I = ((m) + (D))), (I=rol32(I,(r))), \
(((s1[I >> 24] ^ s2[(I>>16)&0xff]) - s3[(I>>8)&0xff]) + s4[I&0xff]) )
-#define F2(D,r,m) ( (I = ((m) ^ (D))), (I=rol((r),I)), \
+#define F2(D,r,m) ( (I = ((m) ^ (D))), (I=rol32(I,(r))), \
(((s1[I >> 24] - s2[(I>>16)&0xff]) + s3[(I>>8)&0xff]) ^ s4[I&0xff]) )
-#define F3(D,r,m) ( (I = ((m) - (D))), (I=rol((r),I)), \
+#define F3(D,r,m) ( (I = ((m) - (D))), (I=rol32(I,(r))), \
(((s1[I >> 24] + s2[(I>>16)&0xff]) ^ s3[(I>>8)&0xff]) - s4[I&0xff]) )
static const u32 s1[256] = {
diff --git a/crypto/cipher.c b/crypto/cipher.c
index 6ab56eb3502c8..f434ce7c2d0b3 100644
--- a/crypto/cipher.c
+++ b/crypto/cipher.c
@@ -11,18 +11,20 @@
* any later version.
*
*/
+#include <linux/compiler.h>
#include <linux/kernel.h>
#include <linux/crypto.h>
#include <linux/errno.h>
#include <linux/mm.h>
#include <linux/slab.h>
+#include <linux/string.h>
#include <asm/scatterlist.h>
#include "internal.h"
#include "scatterwalk.h"
typedef void (cryptfn_t)(void *, u8 *, const u8 *);
typedef void (procfn_t)(struct crypto_tfm *, u8 *,
- u8*, cryptfn_t, int enc, void *, int);
+ u8*, cryptfn_t, void *);
static inline void xor_64(u8 *a, const u8 *b)
{
@@ -37,7 +39,47 @@ static inline void xor_128(u8 *a, const u8 *b)
((u32 *)a)[2] ^= ((u32 *)b)[2];
((u32 *)a)[3] ^= ((u32 *)b)[3];
}
+
+static inline void *prepare_src(struct scatter_walk *walk, int bsize,
+ void *tmp, int in_place)
+{
+ void *src = walk->data;
+ int n = bsize;
+
+ if (unlikely(scatterwalk_across_pages(walk, bsize))) {
+ src = tmp;
+ n = scatterwalk_copychunks(src, walk, bsize, 0);
+ }
+ scatterwalk_advance(walk, n);
+ return src;
+}
+
+static inline void *prepare_dst(struct scatter_walk *walk, int bsize,
+ void *tmp, int in_place)
+{
+ void *dst = walk->data;
+
+ if (unlikely(scatterwalk_across_pages(walk, bsize)) || in_place)
+ dst = tmp;
+ return dst;
+}
+
+static inline void complete_src(struct scatter_walk *walk, int bsize,
+ void *src, int in_place)
+{
+}
+static inline void complete_dst(struct scatter_walk *walk, int bsize,
+ void *dst, int in_place)
+{
+ int n = bsize;
+
+ if (unlikely(scatterwalk_across_pages(walk, bsize)))
+ n = scatterwalk_copychunks(dst, walk, bsize, 1);
+ else if (in_place)
+ memcpy(walk->data, dst, bsize);
+ scatterwalk_advance(walk, n);
+}
/*
* Generic encrypt/decrypt wrapper for ciphers, handles operations across
@@ -48,7 +90,7 @@ static int crypt(struct crypto_tfm *tfm,
struct scatterlist *dst,
struct scatterlist *src,
unsigned int nbytes, cryptfn_t crfn,
- procfn_t prfn, int enc, void *info)
+ procfn_t prfn, void *info)
{
struct scatter_walk walk_in, walk_out;
const unsigned int bsize = crypto_tfm_alg_blocksize(tfm);
@@ -72,20 +114,26 @@ static int crypt(struct crypto_tfm *tfm,
scatterwalk_map(&walk_in, 0);
scatterwalk_map(&walk_out, 1);
- src_p = scatterwalk_whichbuf(&walk_in, bsize, tmp_src);
- dst_p = scatterwalk_whichbuf(&walk_out, bsize, tmp_dst);
- in_place = scatterwalk_samebuf(&walk_in, &walk_out,
- src_p, dst_p);
- nbytes -= bsize;
+ in_place = scatterwalk_samebuf(&walk_in, &walk_out);
- scatterwalk_copychunks(src_p, &walk_in, bsize, 0);
+ do {
+ src_p = prepare_src(&walk_in, bsize, tmp_src,
+ in_place);
+ dst_p = prepare_dst(&walk_out, bsize, tmp_dst,
+ in_place);
- prfn(tfm, dst_p, src_p, crfn, enc, info, in_place);
+ prfn(tfm, dst_p, src_p, crfn, info);
- scatterwalk_done(&walk_in, 0, nbytes);
+ complete_src(&walk_in, bsize, src_p, in_place);
+ complete_dst(&walk_out, bsize, dst_p, in_place);
+
+ nbytes -= bsize;
+ } while (nbytes &&
+ !scatterwalk_across_pages(&walk_in, bsize) &&
+ !scatterwalk_across_pages(&walk_out, bsize));
- scatterwalk_copychunks(dst_p, &walk_out, bsize, 1);
+ scatterwalk_done(&walk_in, 0, nbytes);
scatterwalk_done(&walk_out, 1, nbytes);
if (!nbytes)
@@ -95,33 +143,28 @@ static int crypt(struct crypto_tfm *tfm,
}
}
-static void cbc_process(struct crypto_tfm *tfm, u8 *dst, u8 *src,
- cryptfn_t fn, int enc, void *info, int in_place)
+static void cbc_process_encrypt(struct crypto_tfm *tfm, u8 *dst, u8 *src,
+ cryptfn_t fn, void *info)
{
u8 *iv = info;
-
- /* Null encryption */
- if (!iv)
- return;
-
- if (enc) {
- tfm->crt_u.cipher.cit_xor_block(iv, src);
- fn(crypto_tfm_ctx(tfm), dst, iv);
- memcpy(iv, dst, crypto_tfm_alg_blocksize(tfm));
- } else {
- u8 stack[in_place ? crypto_tfm_alg_blocksize(tfm) : 0];
- u8 *buf = in_place ? stack : dst;
-
- fn(crypto_tfm_ctx(tfm), buf, src);
- tfm->crt_u.cipher.cit_xor_block(buf, iv);
- memcpy(iv, src, crypto_tfm_alg_blocksize(tfm));
- if (buf != dst)
- memcpy(dst, buf, crypto_tfm_alg_blocksize(tfm));
- }
+
+ tfm->crt_u.cipher.cit_xor_block(iv, src);
+ fn(crypto_tfm_ctx(tfm), dst, iv);
+ memcpy(iv, dst, crypto_tfm_alg_blocksize(tfm));
+}
+
+static void cbc_process_decrypt(struct crypto_tfm *tfm, u8 *dst, u8 *src,
+ cryptfn_t fn, void *info)
+{
+ u8 *iv = info;
+
+ fn(crypto_tfm_ctx(tfm), dst, src);
+ tfm->crt_u.cipher.cit_xor_block(dst, iv);
+ memcpy(iv, src, crypto_tfm_alg_blocksize(tfm));
}
static void ecb_process(struct crypto_tfm *tfm, u8 *dst, u8 *src,
- cryptfn_t fn, int enc, void *info, int in_place)
+ cryptfn_t fn, void *info)
{
fn(crypto_tfm_ctx(tfm), dst, src);
}
@@ -144,7 +187,7 @@ static int ecb_encrypt(struct crypto_tfm *tfm,
{
return crypt(tfm, dst, src, nbytes,
tfm->__crt_alg->cra_cipher.cia_encrypt,
- ecb_process, 1, NULL);
+ ecb_process, NULL);
}
static int ecb_decrypt(struct crypto_tfm *tfm,
@@ -154,7 +197,7 @@ static int ecb_decrypt(struct crypto_tfm *tfm,
{
return crypt(tfm, dst, src, nbytes,
tfm->__crt_alg->cra_cipher.cia_decrypt,
- ecb_process, 1, NULL);
+ ecb_process, NULL);
}
static int cbc_encrypt(struct crypto_tfm *tfm,
@@ -164,7 +207,7 @@ static int cbc_encrypt(struct crypto_tfm *tfm,
{
return crypt(tfm, dst, src, nbytes,
tfm->__crt_alg->cra_cipher.cia_encrypt,
- cbc_process, 1, tfm->crt_cipher.cit_iv);
+ cbc_process_encrypt, tfm->crt_cipher.cit_iv);
}
static int cbc_encrypt_iv(struct crypto_tfm *tfm,
@@ -174,7 +217,7 @@ static int cbc_encrypt_iv(struct crypto_tfm *tfm,
{
return crypt(tfm, dst, src, nbytes,
tfm->__crt_alg->cra_cipher.cia_encrypt,
- cbc_process, 1, iv);
+ cbc_process_encrypt, iv);
}
static int cbc_decrypt(struct crypto_tfm *tfm,
@@ -184,7 +227,7 @@ static int cbc_decrypt(struct crypto_tfm *tfm,
{
return crypt(tfm, dst, src, nbytes,
tfm->__crt_alg->cra_cipher.cia_decrypt,
- cbc_process, 0, tfm->crt_cipher.cit_iv);
+ cbc_process_decrypt, tfm->crt_cipher.cit_iv);
}
static int cbc_decrypt_iv(struct crypto_tfm *tfm,
@@ -194,7 +237,7 @@ static int cbc_decrypt_iv(struct crypto_tfm *tfm,
{
return crypt(tfm, dst, src, nbytes,
tfm->__crt_alg->cra_cipher.cia_decrypt,
- cbc_process, 0, iv);
+ cbc_process_decrypt, iv);
}
static int nocrypt(struct crypto_tfm *tfm,
diff --git a/crypto/michael_mic.c b/crypto/michael_mic.c
index 08a8dbb3feb6a..a470bcb3693ea 100644
--- a/crypto/michael_mic.c
+++ b/crypto/michael_mic.c
@@ -24,18 +24,6 @@ struct michael_mic_ctx {
};
-static inline u32 rotl(u32 val, int bits)
-{
- return (val << bits) | (val >> (32 - bits));
-}
-
-
-static inline u32 rotr(u32 val, int bits)
-{
- return (val >> bits) | (val << (32 - bits));
-}
-
-
static inline u32 xswap(u32 val)
{
return ((val & 0x00ff00ff) << 8) | ((val & 0xff00ff00) >> 8);
@@ -44,13 +32,13 @@ static inline u32 xswap(u32 val)
#define michael_block(l, r) \
do { \
- r ^= rotl(l, 17); \
+ r ^= rol32(l, 17); \
l += r; \
r ^= xswap(l); \
l += r; \
- r ^= rotl(l, 3); \
+ r ^= rol32(l, 3); \
l += r; \
- r ^= rotr(l, 2); \
+ r ^= ror32(l, 2); \
l += r; \
} while (0)
diff --git a/crypto/scatterwalk.c b/crypto/scatterwalk.c
index f6a5c9e5b2e09..50c9461e8cc6a 100644
--- a/crypto/scatterwalk.c
+++ b/crypto/scatterwalk.c
@@ -17,6 +17,7 @@
#include <linux/mm.h>
#include <linux/pagemap.h>
#include <linux/highmem.h>
+#include <asm/bug.h>
#include <asm/scatterlist.h>
#include "internal.h"
#include "scatterwalk.h"
@@ -28,16 +29,6 @@ enum km_type crypto_km_types[] = {
KM_SOFTIRQ1,
};
-void *scatterwalk_whichbuf(struct scatter_walk *walk, unsigned int nbytes, void *scratch)
-{
- if (nbytes <= walk->len_this_page &&
- (((unsigned long)walk->data) & (PAGE_CACHE_SIZE - 1)) + nbytes <=
- PAGE_CACHE_SIZE)
- return walk->data;
- else
- return scratch;
-}
-
static void memcpy_dir(void *buf, void *sgdata, size_t nbytes, int out)
{
if (out)
@@ -55,6 +46,8 @@ void scatterwalk_start(struct scatter_walk *walk, struct scatterlist *sg)
walk->page = sg->page;
walk->len_this_segment = sg->length;
+ BUG_ON(!sg->length);
+
rest_of_page = PAGE_CACHE_SIZE - (sg->offset & (PAGE_CACHE_SIZE - 1));
walk->len_this_page = min(sg->length, rest_of_page);
walk->offset = sg->offset;
@@ -65,13 +58,17 @@ void scatterwalk_map(struct scatter_walk *walk, int out)
walk->data = crypto_kmap(walk->page, out) + walk->offset;
}
-static void scatterwalk_pagedone(struct scatter_walk *walk, int out,
- unsigned int more)
+static inline void scatterwalk_unmap(struct scatter_walk *walk, int out)
{
/* walk->data may be pointing the first byte of the next page;
however, we know we transfered at least one byte. So,
walk->data - 1 will be a virtual address in the mapped page. */
+ crypto_kunmap(walk->data - 1, out);
+}
+static void scatterwalk_pagedone(struct scatter_walk *walk, int out,
+ unsigned int more)
+{
if (out)
flush_dcache_page(walk->page);
@@ -91,7 +88,7 @@ static void scatterwalk_pagedone(struct scatter_walk *walk, int out,
void scatterwalk_done(struct scatter_walk *walk, int out, int more)
{
- crypto_kunmap(walk->data, out);
+ scatterwalk_unmap(walk, out);
if (walk->len_this_page == 0 || !more)
scatterwalk_pagedone(walk, out, more);
}
@@ -103,22 +100,16 @@ void scatterwalk_done(struct scatter_walk *walk, int out, int more)
int scatterwalk_copychunks(void *buf, struct scatter_walk *walk,
size_t nbytes, int out)
{
- if (buf != walk->data) {
- while (nbytes > walk->len_this_page) {
- memcpy_dir(buf, walk->data, walk->len_this_page, out);
- buf += walk->len_this_page;
- nbytes -= walk->len_this_page;
-
- crypto_kunmap(walk->data, out);
- scatterwalk_pagedone(walk, out, 1);
- scatterwalk_map(walk, out);
- }
-
- memcpy_dir(buf, walk->data, nbytes, out);
- }
-
- walk->offset += nbytes;
- walk->len_this_page -= nbytes;
- walk->len_this_segment -= nbytes;
- return 0;
+ do {
+ memcpy_dir(buf, walk->data, walk->len_this_page, out);
+ buf += walk->len_this_page;
+ nbytes -= walk->len_this_page;
+
+ scatterwalk_unmap(walk, out);
+ scatterwalk_pagedone(walk, out, 1);
+ scatterwalk_map(walk, out);
+ } while (nbytes > walk->len_this_page);
+
+ memcpy_dir(buf, walk->data, nbytes, out);
+ return nbytes;
}
diff --git a/crypto/scatterwalk.h b/crypto/scatterwalk.h
index b16446519017f..02aa56c649b48 100644
--- a/crypto/scatterwalk.h
+++ b/crypto/scatterwalk.h
@@ -34,15 +34,27 @@ static inline struct scatterlist *sg_next(struct scatterlist *sg)
}
static inline int scatterwalk_samebuf(struct scatter_walk *walk_in,
- struct scatter_walk *walk_out,
- void *src_p, void *dst_p)
+ struct scatter_walk *walk_out)
{
return walk_in->page == walk_out->page &&
- walk_in->offset == walk_out->offset &&
- walk_in->data == src_p && walk_out->data == dst_p;
+ walk_in->offset == walk_out->offset;
+}
+
+static inline int scatterwalk_across_pages(struct scatter_walk *walk,
+ unsigned int nbytes)
+{
+ return nbytes > walk->len_this_page;
+}
+
+static inline void scatterwalk_advance(struct scatter_walk *walk,
+ unsigned int nbytes)
+{
+ walk->data += nbytes;
+ walk->offset += nbytes;
+ walk->len_this_page -= nbytes;
+ walk->len_this_segment -= nbytes;
}
-void *scatterwalk_whichbuf(struct scatter_walk *walk, unsigned int nbytes, void *scratch);
void scatterwalk_start(struct scatter_walk *walk, struct scatterlist *sg);
int scatterwalk_copychunks(void *buf, struct scatter_walk *walk, size_t nbytes, int out);
void scatterwalk_map(struct scatter_walk *walk, int out);
diff --git a/crypto/serpent.c b/crypto/serpent.c
index 4c95ba9c50d32..7d152e89016fa 100644
--- a/crypto/serpent.c
+++ b/crypto/serpent.c
@@ -31,11 +31,9 @@
#define SERPENT_BLOCK_SIZE 16
#define PHI 0x9e3779b9UL
-#define ROL(x,r) ((x) = ((x) << (r)) | ((x) >> (32-(r))))
-#define ROR(x,r) ((x) = ((x) >> (r)) | ((x) << (32-(r))))
#define keyiter(a,b,c,d,i,j) \
- b ^= d; b ^= c; b ^= a; b ^= PHI ^ i; ROL(b,11); k[j] = b;
+ b ^= d; b ^= c; b ^= a; b ^= PHI ^ i; b = rol32(b,11); k[j] = b;
#define loadkeys(x0,x1,x2,x3,i) \
x0=k[i]; x1=k[i+1]; x2=k[i+2]; x3=k[i+3];
@@ -48,24 +46,24 @@
x1 ^= k[4*(i)+1]; x0 ^= k[4*(i)+0];
#define LK(x0,x1,x2,x3,x4,i) \
- ROL(x0,13); \
- ROL(x2,3); x1 ^= x0; x4 = x0 << 3; \
+ x0=rol32(x0,13);\
+ x2=rol32(x2,3); x1 ^= x0; x4 = x0 << 3; \
x3 ^= x2; x1 ^= x2; \
- ROL(x1,1); x3 ^= x4; \
- ROL(x3,7); x4 = x1; \
+ x1=rol32(x1,1); x3 ^= x4; \
+ x3=rol32(x3,7); x4 = x1; \
x0 ^= x1; x4 <<= 7; x2 ^= x3; \
x0 ^= x3; x2 ^= x4; x3 ^= k[4*i+3]; \
- x1 ^= k[4*i+1]; ROL(x0,5); ROL(x2,22); \
+ x1 ^= k[4*i+1]; x0=rol32(x0,5); x2=rol32(x2,22);\
x0 ^= k[4*i+0]; x2 ^= k[4*i+2];
#define KL(x0,x1,x2,x3,x4,i) \
x0 ^= k[4*i+0]; x1 ^= k[4*i+1]; x2 ^= k[4*i+2]; \
- x3 ^= k[4*i+3]; ROR(x0,5); ROR(x2,22); \
+ x3 ^= k[4*i+3]; x0=ror32(x0,5); x2=ror32(x2,22);\
x4 = x1; x2 ^= x3; x0 ^= x3; \
- x4 <<= 7; x0 ^= x1; ROR(x1,1); \
- x2 ^= x4; ROR(x3,7); x4 = x0 << 3; \
- x1 ^= x0; x3 ^= x4; ROR(x0,13); \
- x1 ^= x2; x3 ^= x2; ROR(x2,3);
+ x4 <<= 7; x0 ^= x1; x1=ror32(x1,1); \
+ x2 ^= x4; x3=ror32(x3,7); x4 = x0 << 3; \
+ x1 ^= x0; x3 ^= x4; x0=ror32(x0,13);\
+ x1 ^= x2; x3 ^= x2; x2=ror32(x2,3);
#define S0(x0,x1,x2,x3,x4) \
x4 = x3; \
diff --git a/crypto/sha1.c b/crypto/sha1.c
index 012d872d4477a..4016f3b8ce9b6 100644
--- a/crypto/sha1.c
+++ b/crypto/sha1.c
@@ -4,8 +4,7 @@
* SHA1 Secure Hash Algorithm.
*
* Derived from cryptoapi implementation, adapted for in-place
- * scatterlist interface. Originally based on the public domain
- * implementation written by Steve Reid.
+ * scatterlist interface.
*
* Copyright (c) Alan Smithee.
* Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk>
@@ -13,7 +12,7 @@
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
+ * Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
*/
@@ -21,89 +20,19 @@
#include <linux/module.h>
#include <linux/mm.h>
#include <linux/crypto.h>
+#include <linux/cryptohash.h>
#include <asm/scatterlist.h>
#include <asm/byteorder.h>
#define SHA1_DIGEST_SIZE 20
#define SHA1_HMAC_BLOCK_SIZE 64
-static inline u32 rol(u32 value, u32 bits)
-{
- return (((value) << (bits)) | ((value) >> (32 - (bits))));
-}
-
-/* blk0() and blk() perform the initial expand. */
-/* I got the idea of expanding during the round function from SSLeay */
-# define blk0(i) block32[i]
-
-#define blk(i) (block32[i&15] = rol(block32[(i+13)&15]^block32[(i+8)&15] \
- ^block32[(i+2)&15]^block32[i&15],1))
-
-/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
-#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5); \
- w=rol(w,30);
-#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5); \
- w=rol(w,30);
-#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
-#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5); \
- w=rol(w,30);
-#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
-
struct sha1_ctx {
u64 count;
u32 state[5];
u8 buffer[64];
};
-/* Hash a single 512-bit block. This is the core of the algorithm. */
-static void sha1_transform(u32 *state, const u8 *in)
-{
- u32 a, b, c, d, e;
- u32 block32[16];
-
- /* convert/copy data to workspace */
- for (a = 0; a < sizeof(block32)/sizeof(u32); a++)
- block32[a] = be32_to_cpu (((const u32 *)in)[a]);
-
- /* Copy context->state[] to working vars */
- a = state[0];
- b = state[1];
- c = state[2];
- d = state[3];
- e = state[4];
-
- /* 4 rounds of 20 operations each. Loop unrolled. */
- R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
- R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
- R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
- R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
- R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
- R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
- R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
- R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
- R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
- R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
- R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
- R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
- R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
- R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
- R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
- R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
- R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
- R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
- R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
- R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
- /* Add the working vars back into context.state[] */
- state[0] += a;
- state[1] += b;
- state[2] += c;
- state[3] += d;
- state[4] += e;
- /* Wipe variables */
- a = b = c = d = e = 0;
- memset (block32, 0x00, sizeof block32);
-}
-
static void sha1_init(void *ctx)
{
struct sha1_ctx *sctx = ctx;
@@ -120,19 +49,21 @@ 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];
j = (sctx->count >> 3) & 0x3f;
sctx->count += len << 3;
if ((j + len) > 63) {
memcpy(&sctx->buffer[j], data, (i = 64-j));
- sha1_transform(sctx->state, sctx->buffer);
+ sha_transform(sctx->state, sctx->buffer, temp);
for ( ; i + 63 < len; i += 64) {
- sha1_transform(sctx->state, &data[i]);
+ sha_transform(sctx->state, &data[i], temp);
}
j = 0;
}
else i = 0;
+ memset(temp, 0, sizeof(temp));
memcpy(&sctx->buffer[j], &data[i], len - i);
}
diff --git a/crypto/sha256.c b/crypto/sha256.c
index 39f5a654709e1..c78da50a9b7a4 100644
--- a/crypto/sha256.c
+++ b/crypto/sha256.c
@@ -42,15 +42,10 @@ static inline u32 Maj(u32 x, u32 y, u32 z)
return (x & y) | (z & (x | y));
}
-static inline u32 RORu32(u32 x, u32 y)
-{
- return (x >> y) | (x << (32 - y));
-}
-
-#define e0(x) (RORu32(x, 2) ^ RORu32(x,13) ^ RORu32(x,22))
-#define e1(x) (RORu32(x, 6) ^ RORu32(x,11) ^ RORu32(x,25))
-#define s0(x) (RORu32(x, 7) ^ RORu32(x,18) ^ (x >> 3))
-#define s1(x) (RORu32(x,17) ^ RORu32(x,19) ^ (x >> 10))
+#define e0(x) (ror32(x, 2) ^ ror32(x,13) ^ ror32(x,22))
+#define e1(x) (ror32(x, 6) ^ ror32(x,11) ^ ror32(x,25))
+#define s0(x) (ror32(x, 7) ^ ror32(x,18) ^ (x >> 3))
+#define s1(x) (ror32(x,17) ^ ror32(x,19) ^ (x >> 10))
#define H0 0x6a09e667
#define H1 0xbb67ae85
@@ -63,7 +58,7 @@ static inline u32 RORu32(u32 x, u32 y)
static inline void LOAD_OP(int I, u32 *W, const u8 *input)
{
- W[I] = __be32_to_cpu( ((u32*)(input))[I] );
+ W[I] = __be32_to_cpu( ((__be32*)(input))[I] );
}
static inline void BLEND_OP(int I, u32 *W)
diff --git a/crypto/sha512.c b/crypto/sha512.c
index 2403bb94675aa..c663438322e9b 100644
--- a/crypto/sha512.c
+++ b/crypto/sha512.c
@@ -105,7 +105,7 @@ static const u64 sha512_K[80] = {
static inline void LOAD_OP(int I, u64 *W, const u8 *input)
{
- W[I] = __be64_to_cpu( ((u64*)(input))[I] );
+ W[I] = __be64_to_cpu( ((__be64*)(input))[I] );
}
static inline void BLEND_OP(int I, u64 *W)
diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c
index a685df621731c..92b0352c8e92f 100644
--- a/crypto/tcrypt.c
+++ b/crypto/tcrypt.c
@@ -695,6 +695,9 @@ do_test(void)
test_hash("wp512", wp512_tv_template, WP512_TEST_VECTORS);
test_hash("wp384", wp384_tv_template, WP384_TEST_VECTORS);
test_hash("wp256", wp256_tv_template, WP256_TEST_VECTORS);
+ test_hash("tgr192", tgr192_tv_template, TGR192_TEST_VECTORS);
+ test_hash("tgr160", tgr160_tv_template, TGR160_TEST_VECTORS);
+ test_hash("tgr128", tgr128_tv_template, TGR128_TEST_VECTORS);
test_deflate();
test_crc32c();
#ifdef CONFIG_CRYPTO_HMAC
@@ -832,6 +835,19 @@ do_test(void)
test_cipher ("anubis", MODE_CBC, DECRYPT, anubis_cbc_dec_tv_template, ANUBIS_CBC_ENC_TEST_VECTORS);
break;
+ case 27:
+ test_hash("tgr192", tgr192_tv_template, TGR192_TEST_VECTORS);
+ break;
+
+ case 28:
+
+ test_hash("tgr160", tgr160_tv_template, TGR160_TEST_VECTORS);
+ break;
+
+ case 29:
+ test_hash("tgr128", tgr128_tv_template, TGR128_TEST_VECTORS);
+ break;
+
#ifdef CONFIG_CRYPTO_HMAC
case 100:
test_hmac("md5", hmac_md5_tv_template, HMAC_MD5_TEST_VECTORS);
diff --git a/crypto/tcrypt.h b/crypto/tcrypt.h
index df08d0d8c6bd1..a3097afae5932 100644
--- a/crypto/tcrypt.h
+++ b/crypto/tcrypt.h
@@ -553,6 +553,137 @@ static struct hash_testvec wp256_tv_template[] = {
},
};
+/*
+ * TIGER test vectors from Tiger website
+ */
+#define TGR192_TEST_VECTORS 6
+
+static struct hash_testvec tgr192_tv_template[] = {
+ {
+ .plaintext = "",
+ .psize = 0,
+ .digest = { 0x24, 0xf0, 0x13, 0x0c, 0x63, 0xac, 0x93, 0x32,
+ 0x16, 0x16, 0x6e, 0x76, 0xb1, 0xbb, 0x92, 0x5f,
+ 0xf3, 0x73, 0xde, 0x2d, 0x49, 0x58, 0x4e, 0x7a },
+ }, {
+ .plaintext = "abc",
+ .psize = 3,
+ .digest = { 0xf2, 0x58, 0xc1, 0xe8, 0x84, 0x14, 0xab, 0x2a,
+ 0x52, 0x7a, 0xb5, 0x41, 0xff, 0xc5, 0xb8, 0xbf,
+ 0x93, 0x5f, 0x7b, 0x95, 0x1c, 0x13, 0x29, 0x51 },
+ }, {
+ .plaintext = "Tiger",
+ .psize = 5,
+ .digest = { 0x9f, 0x00, 0xf5, 0x99, 0x07, 0x23, 0x00, 0xdd,
+ 0x27, 0x6a, 0xbb, 0x38, 0xc8, 0xeb, 0x6d, 0xec,
+ 0x37, 0x79, 0x0c, 0x11, 0x6f, 0x9d, 0x2b, 0xdf },
+ }, {
+ .plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-",
+ .psize = 64,
+ .digest = { 0x87, 0xfb, 0x2a, 0x90, 0x83, 0x85, 0x1c, 0xf7,
+ 0x47, 0x0d, 0x2c, 0xf8, 0x10, 0xe6, 0xdf, 0x9e,
+ 0xb5, 0x86, 0x44, 0x50, 0x34, 0xa5, 0xa3, 0x86 },
+ }, {
+ .plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZ=abcdefghijklmnopqrstuvwxyz+0123456789",
+ .psize = 64,
+ .digest = { 0x46, 0x7d, 0xb8, 0x08, 0x63, 0xeb, 0xce, 0x48,
+ 0x8d, 0xf1, 0xcd, 0x12, 0x61, 0x65, 0x5d, 0xe9,
+ 0x57, 0x89, 0x65, 0x65, 0x97, 0x5f, 0x91, 0x97 },
+ }, {
+ .plaintext = "Tiger - A Fast New Hash Function, "
+ "by Ross Anderson and Eli Biham, "
+ "proceedings of Fast Software Encryption 3, "
+ "Cambridge, 1996.",
+ .psize = 125,
+ .digest = { 0x3d, 0x9a, 0xeb, 0x03, 0xd1, 0xbd, 0x1a, 0x63,
+ 0x57, 0xb2, 0x77, 0x4d, 0xfd, 0x6d, 0x5b, 0x24,
+ 0xdd, 0x68, 0x15, 0x1d, 0x50, 0x39, 0x74, 0xfc },
+ },
+};
+
+#define TGR160_TEST_VECTORS 6
+
+static struct hash_testvec tgr160_tv_template[] = {
+ {
+ .plaintext = "",
+ .psize = 0,
+ .digest = { 0x24, 0xf0, 0x13, 0x0c, 0x63, 0xac, 0x93, 0x32,
+ 0x16, 0x16, 0x6e, 0x76, 0xb1, 0xbb, 0x92, 0x5f,
+ 0xf3, 0x73, 0xde, 0x2d },
+ }, {
+ .plaintext = "abc",
+ .psize = 3,
+ .digest = { 0xf2, 0x58, 0xc1, 0xe8, 0x84, 0x14, 0xab, 0x2a,
+ 0x52, 0x7a, 0xb5, 0x41, 0xff, 0xc5, 0xb8, 0xbf,
+ 0x93, 0x5f, 0x7b, 0x95 },
+ }, {
+ .plaintext = "Tiger",
+ .psize = 5,
+ .digest = { 0x9f, 0x00, 0xf5, 0x99, 0x07, 0x23, 0x00, 0xdd,
+ 0x27, 0x6a, 0xbb, 0x38, 0xc8, 0xeb, 0x6d, 0xec,
+ 0x37, 0x79, 0x0c, 0x11 },
+ }, {
+ .plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-",
+ .psize = 64,
+ .digest = { 0x87, 0xfb, 0x2a, 0x90, 0x83, 0x85, 0x1c, 0xf7,
+ 0x47, 0x0d, 0x2c, 0xf8, 0x10, 0xe6, 0xdf, 0x9e,
+ 0xb5, 0x86, 0x44, 0x50 },
+ }, {
+ .plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZ=abcdefghijklmnopqrstuvwxyz+0123456789",
+ .psize = 64,
+ .digest = { 0x46, 0x7d, 0xb8, 0x08, 0x63, 0xeb, 0xce, 0x48,
+ 0x8d, 0xf1, 0xcd, 0x12, 0x61, 0x65, 0x5d, 0xe9,
+ 0x57, 0x89, 0x65, 0x65 },
+ }, {
+ .plaintext = "Tiger - A Fast New Hash Function, "
+ "by Ross Anderson and Eli Biham, "
+ "proceedings of Fast Software Encryption 3, "
+ "Cambridge, 1996.",
+ .psize = 125,
+ .digest = { 0x3d, 0x9a, 0xeb, 0x03, 0xd1, 0xbd, 0x1a, 0x63,
+ 0x57, 0xb2, 0x77, 0x4d, 0xfd, 0x6d, 0x5b, 0x24,
+ 0xdd, 0x68, 0x15, 0x1d },
+ },
+};
+
+#define TGR128_TEST_VECTORS 6
+
+static struct hash_testvec tgr128_tv_template[] = {
+ {
+ .plaintext = "",
+ .psize = 0,
+ .digest = { 0x24, 0xf0, 0x13, 0x0c, 0x63, 0xac, 0x93, 0x32,
+ 0x16, 0x16, 0x6e, 0x76, 0xb1, 0xbb, 0x92, 0x5f },
+ }, {
+ .plaintext = "abc",
+ .psize = 3,
+ .digest = { 0xf2, 0x58, 0xc1, 0xe8, 0x84, 0x14, 0xab, 0x2a,
+ 0x52, 0x7a, 0xb5, 0x41, 0xff, 0xc5, 0xb8, 0xbf },
+ }, {
+ .plaintext = "Tiger",
+ .psize = 5,
+ .digest = { 0x9f, 0x00, 0xf5, 0x99, 0x07, 0x23, 0x00, 0xdd,
+ 0x27, 0x6a, 0xbb, 0x38, 0xc8, 0xeb, 0x6d, 0xec },
+ }, {
+ .plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-",
+ .psize = 64,
+ .digest = { 0x87, 0xfb, 0x2a, 0x90, 0x83, 0x85, 0x1c, 0xf7,
+ 0x47, 0x0d, 0x2c, 0xf8, 0x10, 0xe6, 0xdf, 0x9e },
+ }, {
+ .plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZ=abcdefghijklmnopqrstuvwxyz+0123456789",
+ .psize = 64,
+ .digest = { 0x46, 0x7d, 0xb8, 0x08, 0x63, 0xeb, 0xce, 0x48,
+ 0x8d, 0xf1, 0xcd, 0x12, 0x61, 0x65, 0x5d, 0xe9 },
+ }, {
+ .plaintext = "Tiger - A Fast New Hash Function, "
+ "by Ross Anderson and Eli Biham, "
+ "proceedings of Fast Software Encryption 3, "
+ "Cambridge, 1996.",
+ .psize = 125,
+ .digest = { 0x3d, 0x9a, 0xeb, 0x03, 0xd1, 0xbd, 0x1a, 0x63,
+ 0x57, 0xb2, 0x77, 0x4d, 0xfd, 0x6d, 0x5b, 0x24 },
+ },
+};
#ifdef CONFIG_CRYPTO_HMAC
/*
diff --git a/crypto/tea.c b/crypto/tea.c
index 588a143c1f084..03c23cbd3afa1 100644
--- a/crypto/tea.c
+++ b/crypto/tea.c
@@ -31,8 +31,8 @@
#define XTEA_ROUNDS 32
#define XTEA_DELTA 0x9e3779b9
-#define u32_in(x) le32_to_cpu(*(const u32 *)(x))
-#define u32_out(to, from) (*(u32 *)(to) = cpu_to_le32(from))
+#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];
diff --git a/crypto/tgr192.c b/crypto/tgr192.c
new file mode 100644
index 0000000000000..f0a45cf716d07
--- /dev/null
+++ b/crypto/tgr192.c
@@ -0,0 +1,735 @@
+/*
+ * Cryptographic API.
+ *
+ * Tiger hashing Algorithm
+ *
+ * Copyright (C) 1998 Free Software Foundation, Inc.
+ *
+ * The Tiger algorithm was developed by Ross Anderson and Eli Biham.
+ * It was optimized for 64-bit processors while still delievering
+ * decent performance on 32 and 16-bit processors.
+ *
+ * This version is derived from the GnuPG implementation and the
+ * Tiger-Perl interface written by Rafael Sevilla
+ *
+ * Adapted for Linux Kernel Crypto by Aaron Grothe
+ * ajgrothe@yahoo.com, February 22, 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 of the License, or
+ * (at your option) any later version.
+ *
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <asm/scatterlist.h>
+#include <linux/crypto.h>
+
+#define TGR192_DIGEST_SIZE 24
+#define TGR160_DIGEST_SIZE 20
+#define TGR128_DIGEST_SIZE 16
+
+#define TGR192_BLOCK_SIZE 64
+
+struct tgr192_ctx {
+ u64 a, b, c;
+ u8 hash[64];
+ int count;
+ u32 nblocks;
+};
+
+static const u64 sbox1[256] = {
+ 0x02aab17cf7e90c5eULL, 0xac424b03e243a8ecULL, 0x72cd5be30dd5fcd3ULL,
+ 0x6d019b93f6f97f3aULL, 0xcd9978ffd21f9193ULL, 0x7573a1c9708029e2ULL,
+ 0xb164326b922a83c3ULL, 0x46883eee04915870ULL, 0xeaace3057103ece6ULL,
+ 0xc54169b808a3535cULL, 0x4ce754918ddec47cULL, 0x0aa2f4dfdc0df40cULL,
+ 0x10b76f18a74dbefaULL, 0xc6ccb6235ad1ab6aULL, 0x13726121572fe2ffULL,
+ 0x1a488c6f199d921eULL, 0x4bc9f9f4da0007caULL, 0x26f5e6f6e85241c7ULL,
+ 0x859079dbea5947b6ULL, 0x4f1885c5c99e8c92ULL, 0xd78e761ea96f864bULL,
+ 0x8e36428c52b5c17dULL, 0x69cf6827373063c1ULL, 0xb607c93d9bb4c56eULL,
+ 0x7d820e760e76b5eaULL, 0x645c9cc6f07fdc42ULL, 0xbf38a078243342e0ULL,
+ 0x5f6b343c9d2e7d04ULL, 0xf2c28aeb600b0ec6ULL, 0x6c0ed85f7254bcacULL,
+ 0x71592281a4db4fe5ULL, 0x1967fa69ce0fed9fULL, 0xfd5293f8b96545dbULL,
+ 0xc879e9d7f2a7600bULL, 0x860248920193194eULL, 0xa4f9533b2d9cc0b3ULL,
+ 0x9053836c15957613ULL, 0xdb6dcf8afc357bf1ULL, 0x18beea7a7a370f57ULL,
+ 0x037117ca50b99066ULL, 0x6ab30a9774424a35ULL, 0xf4e92f02e325249bULL,
+ 0x7739db07061ccae1ULL, 0xd8f3b49ceca42a05ULL, 0xbd56be3f51382f73ULL,
+ 0x45faed5843b0bb28ULL, 0x1c813d5c11bf1f83ULL, 0x8af0e4b6d75fa169ULL,
+ 0x33ee18a487ad9999ULL, 0x3c26e8eab1c94410ULL, 0xb510102bc0a822f9ULL,
+ 0x141eef310ce6123bULL, 0xfc65b90059ddb154ULL, 0xe0158640c5e0e607ULL,
+ 0x884e079826c3a3cfULL, 0x930d0d9523c535fdULL, 0x35638d754e9a2b00ULL,
+ 0x4085fccf40469dd5ULL, 0xc4b17ad28be23a4cULL, 0xcab2f0fc6a3e6a2eULL,
+ 0x2860971a6b943fcdULL, 0x3dde6ee212e30446ULL, 0x6222f32ae01765aeULL,
+ 0x5d550bb5478308feULL, 0xa9efa98da0eda22aULL, 0xc351a71686c40da7ULL,
+ 0x1105586d9c867c84ULL, 0xdcffee85fda22853ULL, 0xccfbd0262c5eef76ULL,
+ 0xbaf294cb8990d201ULL, 0xe69464f52afad975ULL, 0x94b013afdf133e14ULL,
+ 0x06a7d1a32823c958ULL, 0x6f95fe5130f61119ULL, 0xd92ab34e462c06c0ULL,
+ 0xed7bde33887c71d2ULL, 0x79746d6e6518393eULL, 0x5ba419385d713329ULL,
+ 0x7c1ba6b948a97564ULL, 0x31987c197bfdac67ULL, 0xde6c23c44b053d02ULL,
+ 0x581c49fed002d64dULL, 0xdd474d6338261571ULL, 0xaa4546c3e473d062ULL,
+ 0x928fce349455f860ULL, 0x48161bbacaab94d9ULL, 0x63912430770e6f68ULL,
+ 0x6ec8a5e602c6641cULL, 0x87282515337ddd2bULL, 0x2cda6b42034b701bULL,
+ 0xb03d37c181cb096dULL, 0xe108438266c71c6fULL, 0x2b3180c7eb51b255ULL,
+ 0xdf92b82f96c08bbcULL, 0x5c68c8c0a632f3baULL, 0x5504cc861c3d0556ULL,
+ 0xabbfa4e55fb26b8fULL, 0x41848b0ab3baceb4ULL, 0xb334a273aa445d32ULL,
+ 0xbca696f0a85ad881ULL, 0x24f6ec65b528d56cULL, 0x0ce1512e90f4524aULL,
+ 0x4e9dd79d5506d35aULL, 0x258905fac6ce9779ULL, 0x2019295b3e109b33ULL,
+ 0xf8a9478b73a054ccULL, 0x2924f2f934417eb0ULL, 0x3993357d536d1bc4ULL,
+ 0x38a81ac21db6ff8bULL, 0x47c4fbf17d6016bfULL, 0x1e0faadd7667e3f5ULL,
+ 0x7abcff62938beb96ULL, 0xa78dad948fc179c9ULL, 0x8f1f98b72911e50dULL,
+ 0x61e48eae27121a91ULL, 0x4d62f7ad31859808ULL, 0xeceba345ef5ceaebULL,
+ 0xf5ceb25ebc9684ceULL, 0xf633e20cb7f76221ULL, 0xa32cdf06ab8293e4ULL,
+ 0x985a202ca5ee2ca4ULL, 0xcf0b8447cc8a8fb1ULL, 0x9f765244979859a3ULL,
+ 0xa8d516b1a1240017ULL, 0x0bd7ba3ebb5dc726ULL, 0xe54bca55b86adb39ULL,
+ 0x1d7a3afd6c478063ULL, 0x519ec608e7669eddULL, 0x0e5715a2d149aa23ULL,
+ 0x177d4571848ff194ULL, 0xeeb55f3241014c22ULL, 0x0f5e5ca13a6e2ec2ULL,
+ 0x8029927b75f5c361ULL, 0xad139fabc3d6e436ULL, 0x0d5df1a94ccf402fULL,
+ 0x3e8bd948bea5dfc8ULL, 0xa5a0d357bd3ff77eULL, 0xa2d12e251f74f645ULL,
+ 0x66fd9e525e81a082ULL, 0x2e0c90ce7f687a49ULL, 0xc2e8bcbeba973bc5ULL,
+ 0x000001bce509745fULL, 0x423777bbe6dab3d6ULL, 0xd1661c7eaef06eb5ULL,
+ 0xa1781f354daacfd8ULL, 0x2d11284a2b16affcULL, 0xf1fc4f67fa891d1fULL,
+ 0x73ecc25dcb920adaULL, 0xae610c22c2a12651ULL, 0x96e0a810d356b78aULL,
+ 0x5a9a381f2fe7870fULL, 0xd5ad62ede94e5530ULL, 0xd225e5e8368d1427ULL,
+ 0x65977b70c7af4631ULL, 0x99f889b2de39d74fULL, 0x233f30bf54e1d143ULL,
+ 0x9a9675d3d9a63c97ULL, 0x5470554ff334f9a8ULL, 0x166acb744a4f5688ULL,
+ 0x70c74caab2e4aeadULL, 0xf0d091646f294d12ULL, 0x57b82a89684031d1ULL,
+ 0xefd95a5a61be0b6bULL, 0x2fbd12e969f2f29aULL, 0x9bd37013feff9fe8ULL,
+ 0x3f9b0404d6085a06ULL, 0x4940c1f3166cfe15ULL, 0x09542c4dcdf3defbULL,
+ 0xb4c5218385cd5ce3ULL, 0xc935b7dc4462a641ULL, 0x3417f8a68ed3b63fULL,
+ 0xb80959295b215b40ULL, 0xf99cdaef3b8c8572ULL, 0x018c0614f8fcb95dULL,
+ 0x1b14accd1a3acdf3ULL, 0x84d471f200bb732dULL, 0xc1a3110e95e8da16ULL,
+ 0x430a7220bf1a82b8ULL, 0xb77e090d39df210eULL, 0x5ef4bd9f3cd05e9dULL,
+ 0x9d4ff6da7e57a444ULL, 0xda1d60e183d4a5f8ULL, 0xb287c38417998e47ULL,
+ 0xfe3edc121bb31886ULL, 0xc7fe3ccc980ccbefULL, 0xe46fb590189bfd03ULL,
+ 0x3732fd469a4c57dcULL, 0x7ef700a07cf1ad65ULL, 0x59c64468a31d8859ULL,
+ 0x762fb0b4d45b61f6ULL, 0x155baed099047718ULL, 0x68755e4c3d50baa6ULL,
+ 0xe9214e7f22d8b4dfULL, 0x2addbf532eac95f4ULL, 0x32ae3909b4bd0109ULL,
+ 0x834df537b08e3450ULL, 0xfa209da84220728dULL, 0x9e691d9b9efe23f7ULL,
+ 0x0446d288c4ae8d7fULL, 0x7b4cc524e169785bULL, 0x21d87f0135ca1385ULL,
+ 0xcebb400f137b8aa5ULL, 0x272e2b66580796beULL, 0x3612264125c2b0deULL,
+ 0x057702bdad1efbb2ULL, 0xd4babb8eacf84be9ULL, 0x91583139641bc67bULL,
+ 0x8bdc2de08036e024ULL, 0x603c8156f49f68edULL, 0xf7d236f7dbef5111ULL,
+ 0x9727c4598ad21e80ULL, 0xa08a0896670a5fd7ULL, 0xcb4a8f4309eba9cbULL,
+ 0x81af564b0f7036a1ULL, 0xc0b99aa778199abdULL, 0x959f1ec83fc8e952ULL,
+ 0x8c505077794a81b9ULL, 0x3acaaf8f056338f0ULL, 0x07b43f50627a6778ULL,
+ 0x4a44ab49f5eccc77ULL, 0x3bc3d6e4b679ee98ULL, 0x9cc0d4d1cf14108cULL,
+ 0x4406c00b206bc8a0ULL, 0x82a18854c8d72d89ULL, 0x67e366b35c3c432cULL,
+ 0xb923dd61102b37f2ULL, 0x56ab2779d884271dULL, 0xbe83e1b0ff1525afULL,
+ 0xfb7c65d4217e49a9ULL, 0x6bdbe0e76d48e7d4ULL, 0x08df828745d9179eULL,
+ 0x22ea6a9add53bd34ULL, 0xe36e141c5622200aULL, 0x7f805d1b8cb750eeULL,
+ 0xafe5c7a59f58e837ULL, 0xe27f996a4fb1c23cULL, 0xd3867dfb0775f0d0ULL,
+ 0xd0e673de6e88891aULL, 0x123aeb9eafb86c25ULL, 0x30f1d5d5c145b895ULL,
+ 0xbb434a2dee7269e7ULL, 0x78cb67ecf931fa38ULL, 0xf33b0372323bbf9cULL,
+ 0x52d66336fb279c74ULL, 0x505f33ac0afb4eaaULL, 0xe8a5cd99a2cce187ULL,
+ 0x534974801e2d30bbULL, 0x8d2d5711d5876d90ULL, 0x1f1a412891bc038eULL,
+ 0xd6e2e71d82e56648ULL, 0x74036c3a497732b7ULL, 0x89b67ed96361f5abULL,
+ 0xffed95d8f1ea02a2ULL, 0xe72b3bd61464d43dULL, 0xa6300f170bdc4820ULL,
+ 0xebc18760ed78a77aULL
+};
+
+static const u64 sbox2[256] = {
+ 0xe6a6be5a05a12138ULL, 0xb5a122a5b4f87c98ULL, 0x563c6089140b6990ULL,
+ 0x4c46cb2e391f5dd5ULL, 0xd932addbc9b79434ULL, 0x08ea70e42015aff5ULL,
+ 0xd765a6673e478cf1ULL, 0xc4fb757eab278d99ULL, 0xdf11c6862d6e0692ULL,
+ 0xddeb84f10d7f3b16ULL, 0x6f2ef604a665ea04ULL, 0x4a8e0f0ff0e0dfb3ULL,
+ 0xa5edeef83dbcba51ULL, 0xfc4f0a2a0ea4371eULL, 0xe83e1da85cb38429ULL,
+ 0xdc8ff882ba1b1ce2ULL, 0xcd45505e8353e80dULL, 0x18d19a00d4db0717ULL,
+ 0x34a0cfeda5f38101ULL, 0x0be77e518887caf2ULL, 0x1e341438b3c45136ULL,
+ 0xe05797f49089ccf9ULL, 0xffd23f9df2591d14ULL, 0x543dda228595c5cdULL,
+ 0x661f81fd99052a33ULL, 0x8736e641db0f7b76ULL, 0x15227725418e5307ULL,
+ 0xe25f7f46162eb2faULL, 0x48a8b2126c13d9feULL, 0xafdc541792e76eeaULL,
+ 0x03d912bfc6d1898fULL, 0x31b1aafa1b83f51bULL, 0xf1ac2796e42ab7d9ULL,
+ 0x40a3a7d7fcd2ebacULL, 0x1056136d0afbbcc5ULL, 0x7889e1dd9a6d0c85ULL,
+ 0xd33525782a7974aaULL, 0xa7e25d09078ac09bULL, 0xbd4138b3eac6edd0ULL,
+ 0x920abfbe71eb9e70ULL, 0xa2a5d0f54fc2625cULL, 0xc054e36b0b1290a3ULL,
+ 0xf6dd59ff62fe932bULL, 0x3537354511a8ac7dULL, 0xca845e9172fadcd4ULL,
+ 0x84f82b60329d20dcULL, 0x79c62ce1cd672f18ULL, 0x8b09a2add124642cULL,
+ 0xd0c1e96a19d9e726ULL, 0x5a786a9b4ba9500cULL, 0x0e020336634c43f3ULL,
+ 0xc17b474aeb66d822ULL, 0x6a731ae3ec9baac2ULL, 0x8226667ae0840258ULL,
+ 0x67d4567691caeca5ULL, 0x1d94155c4875adb5ULL, 0x6d00fd985b813fdfULL,
+ 0x51286efcb774cd06ULL, 0x5e8834471fa744afULL, 0xf72ca0aee761ae2eULL,
+ 0xbe40e4cdaee8e09aULL, 0xe9970bbb5118f665ULL, 0x726e4beb33df1964ULL,
+ 0x703b000729199762ULL, 0x4631d816f5ef30a7ULL, 0xb880b5b51504a6beULL,
+ 0x641793c37ed84b6cULL, 0x7b21ed77f6e97d96ULL, 0x776306312ef96b73ULL,
+ 0xae528948e86ff3f4ULL, 0x53dbd7f286a3f8f8ULL, 0x16cadce74cfc1063ULL,
+ 0x005c19bdfa52c6ddULL, 0x68868f5d64d46ad3ULL, 0x3a9d512ccf1e186aULL,
+ 0x367e62c2385660aeULL, 0xe359e7ea77dcb1d7ULL, 0x526c0773749abe6eULL,
+ 0x735ae5f9d09f734bULL, 0x493fc7cc8a558ba8ULL, 0xb0b9c1533041ab45ULL,
+ 0x321958ba470a59bdULL, 0x852db00b5f46c393ULL, 0x91209b2bd336b0e5ULL,
+ 0x6e604f7d659ef19fULL, 0xb99a8ae2782ccb24ULL, 0xccf52ab6c814c4c7ULL,
+ 0x4727d9afbe11727bULL, 0x7e950d0c0121b34dULL, 0x756f435670ad471fULL,
+ 0xf5add442615a6849ULL, 0x4e87e09980b9957aULL, 0x2acfa1df50aee355ULL,
+ 0xd898263afd2fd556ULL, 0xc8f4924dd80c8fd6ULL, 0xcf99ca3d754a173aULL,
+ 0xfe477bacaf91bf3cULL, 0xed5371f6d690c12dULL, 0x831a5c285e687094ULL,
+ 0xc5d3c90a3708a0a4ULL, 0x0f7f903717d06580ULL, 0x19f9bb13b8fdf27fULL,
+ 0xb1bd6f1b4d502843ULL, 0x1c761ba38fff4012ULL, 0x0d1530c4e2e21f3bULL,
+ 0x8943ce69a7372c8aULL, 0xe5184e11feb5ce66ULL, 0x618bdb80bd736621ULL,
+ 0x7d29bad68b574d0bULL, 0x81bb613e25e6fe5bULL, 0x071c9c10bc07913fULL,
+ 0xc7beeb7909ac2d97ULL, 0xc3e58d353bc5d757ULL, 0xeb017892f38f61e8ULL,
+ 0xd4effb9c9b1cc21aULL, 0x99727d26f494f7abULL, 0xa3e063a2956b3e03ULL,
+ 0x9d4a8b9a4aa09c30ULL, 0x3f6ab7d500090fb4ULL, 0x9cc0f2a057268ac0ULL,
+ 0x3dee9d2dedbf42d1ULL, 0x330f49c87960a972ULL, 0xc6b2720287421b41ULL,
+ 0x0ac59ec07c00369cULL, 0xef4eac49cb353425ULL, 0xf450244eef0129d8ULL,
+ 0x8acc46e5caf4deb6ULL, 0x2ffeab63989263f7ULL, 0x8f7cb9fe5d7a4578ULL,
+ 0x5bd8f7644e634635ULL, 0x427a7315bf2dc900ULL, 0x17d0c4aa2125261cULL,
+ 0x3992486c93518e50ULL, 0xb4cbfee0a2d7d4c3ULL, 0x7c75d6202c5ddd8dULL,
+ 0xdbc295d8e35b6c61ULL, 0x60b369d302032b19ULL, 0xce42685fdce44132ULL,
+ 0x06f3ddb9ddf65610ULL, 0x8ea4d21db5e148f0ULL, 0x20b0fce62fcd496fULL,
+ 0x2c1b912358b0ee31ULL, 0xb28317b818f5a308ULL, 0xa89c1e189ca6d2cfULL,
+ 0x0c6b18576aaadbc8ULL, 0xb65deaa91299fae3ULL, 0xfb2b794b7f1027e7ULL,
+ 0x04e4317f443b5bebULL, 0x4b852d325939d0a6ULL, 0xd5ae6beefb207ffcULL,
+ 0x309682b281c7d374ULL, 0xbae309a194c3b475ULL, 0x8cc3f97b13b49f05ULL,
+ 0x98a9422ff8293967ULL, 0x244b16b01076ff7cULL, 0xf8bf571c663d67eeULL,
+ 0x1f0d6758eee30da1ULL, 0xc9b611d97adeb9b7ULL, 0xb7afd5887b6c57a2ULL,
+ 0x6290ae846b984fe1ULL, 0x94df4cdeacc1a5fdULL, 0x058a5bd1c5483affULL,
+ 0x63166cc142ba3c37ULL, 0x8db8526eb2f76f40ULL, 0xe10880036f0d6d4eULL,
+ 0x9e0523c9971d311dULL, 0x45ec2824cc7cd691ULL, 0x575b8359e62382c9ULL,
+ 0xfa9e400dc4889995ULL, 0xd1823ecb45721568ULL, 0xdafd983b8206082fULL,
+ 0xaa7d29082386a8cbULL, 0x269fcd4403b87588ULL, 0x1b91f5f728bdd1e0ULL,
+ 0xe4669f39040201f6ULL, 0x7a1d7c218cf04adeULL, 0x65623c29d79ce5ceULL,
+ 0x2368449096c00bb1ULL, 0xab9bf1879da503baULL, 0xbc23ecb1a458058eULL,
+ 0x9a58df01bb401eccULL, 0xa070e868a85f143dULL, 0x4ff188307df2239eULL,
+ 0x14d565b41a641183ULL, 0xee13337452701602ULL, 0x950e3dcf3f285e09ULL,
+ 0x59930254b9c80953ULL, 0x3bf299408930da6dULL, 0xa955943f53691387ULL,
+ 0xa15edecaa9cb8784ULL, 0x29142127352be9a0ULL, 0x76f0371fff4e7afbULL,
+ 0x0239f450274f2228ULL, 0xbb073af01d5e868bULL, 0xbfc80571c10e96c1ULL,
+ 0xd267088568222e23ULL, 0x9671a3d48e80b5b0ULL, 0x55b5d38ae193bb81ULL,
+ 0x693ae2d0a18b04b8ULL, 0x5c48b4ecadd5335fULL, 0xfd743b194916a1caULL,
+ 0x2577018134be98c4ULL, 0xe77987e83c54a4adULL, 0x28e11014da33e1b9ULL,
+ 0x270cc59e226aa213ULL, 0x71495f756d1a5f60ULL, 0x9be853fb60afef77ULL,
+ 0xadc786a7f7443dbfULL, 0x0904456173b29a82ULL, 0x58bc7a66c232bd5eULL,
+ 0xf306558c673ac8b2ULL, 0x41f639c6b6c9772aULL, 0x216defe99fda35daULL,
+ 0x11640cc71c7be615ULL, 0x93c43694565c5527ULL, 0xea038e6246777839ULL,
+ 0xf9abf3ce5a3e2469ULL, 0x741e768d0fd312d2ULL, 0x0144b883ced652c6ULL,
+ 0xc20b5a5ba33f8552ULL, 0x1ae69633c3435a9dULL, 0x97a28ca4088cfdecULL,
+ 0x8824a43c1e96f420ULL, 0x37612fa66eeea746ULL, 0x6b4cb165f9cf0e5aULL,
+ 0x43aa1c06a0abfb4aULL, 0x7f4dc26ff162796bULL, 0x6cbacc8e54ed9b0fULL,
+ 0xa6b7ffefd2bb253eULL, 0x2e25bc95b0a29d4fULL, 0x86d6a58bdef1388cULL,
+ 0xded74ac576b6f054ULL, 0x8030bdbc2b45805dULL, 0x3c81af70e94d9289ULL,
+ 0x3eff6dda9e3100dbULL, 0xb38dc39fdfcc8847ULL, 0x123885528d17b87eULL,
+ 0xf2da0ed240b1b642ULL, 0x44cefadcd54bf9a9ULL, 0x1312200e433c7ee6ULL,
+ 0x9ffcc84f3a78c748ULL, 0xf0cd1f72248576bbULL, 0xec6974053638cfe4ULL,
+ 0x2ba7b67c0cec4e4cULL, 0xac2f4df3e5ce32edULL, 0xcb33d14326ea4c11ULL,
+ 0xa4e9044cc77e58bcULL, 0x5f513293d934fcefULL, 0x5dc9645506e55444ULL,
+ 0x50de418f317de40aULL, 0x388cb31a69dde259ULL, 0x2db4a83455820a86ULL,
+ 0x9010a91e84711ae9ULL, 0x4df7f0b7b1498371ULL, 0xd62a2eabc0977179ULL,
+ 0x22fac097aa8d5c0eULL
+};
+
+static const u64 sbox3[256] = {
+ 0xf49fcc2ff1daf39bULL, 0x487fd5c66ff29281ULL, 0xe8a30667fcdca83fULL,
+ 0x2c9b4be3d2fcce63ULL, 0xda3ff74b93fbbbc2ULL, 0x2fa165d2fe70ba66ULL,
+ 0xa103e279970e93d4ULL, 0xbecdec77b0e45e71ULL, 0xcfb41e723985e497ULL,
+ 0xb70aaa025ef75017ULL, 0xd42309f03840b8e0ULL, 0x8efc1ad035898579ULL,
+ 0x96c6920be2b2abc5ULL, 0x66af4163375a9172ULL, 0x2174abdcca7127fbULL,
+ 0xb33ccea64a72ff41ULL, 0xf04a4933083066a5ULL, 0x8d970acdd7289af5ULL,
+ 0x8f96e8e031c8c25eULL, 0xf3fec02276875d47ULL, 0xec7bf310056190ddULL,
+ 0xf5adb0aebb0f1491ULL, 0x9b50f8850fd58892ULL, 0x4975488358b74de8ULL,
+ 0xa3354ff691531c61ULL, 0x0702bbe481d2c6eeULL, 0x89fb24057deded98ULL,
+ 0xac3075138596e902ULL, 0x1d2d3580172772edULL, 0xeb738fc28e6bc30dULL,
+ 0x5854ef8f63044326ULL, 0x9e5c52325add3bbeULL, 0x90aa53cf325c4623ULL,
+ 0xc1d24d51349dd067ULL, 0x2051cfeea69ea624ULL, 0x13220f0a862e7e4fULL,
+ 0xce39399404e04864ULL, 0xd9c42ca47086fcb7ULL, 0x685ad2238a03e7ccULL,
+ 0x066484b2ab2ff1dbULL, 0xfe9d5d70efbf79ecULL, 0x5b13b9dd9c481854ULL,
+ 0x15f0d475ed1509adULL, 0x0bebcd060ec79851ULL, 0xd58c6791183ab7f8ULL,
+ 0xd1187c5052f3eee4ULL, 0xc95d1192e54e82ffULL, 0x86eea14cb9ac6ca2ULL,
+ 0x3485beb153677d5dULL, 0xdd191d781f8c492aULL, 0xf60866baa784ebf9ULL,
+ 0x518f643ba2d08c74ULL, 0x8852e956e1087c22ULL, 0xa768cb8dc410ae8dULL,
+ 0x38047726bfec8e1aULL, 0xa67738b4cd3b45aaULL, 0xad16691cec0dde19ULL,
+ 0xc6d4319380462e07ULL, 0xc5a5876d0ba61938ULL, 0x16b9fa1fa58fd840ULL,
+ 0x188ab1173ca74f18ULL, 0xabda2f98c99c021fULL, 0x3e0580ab134ae816ULL,
+ 0x5f3b05b773645abbULL, 0x2501a2be5575f2f6ULL, 0x1b2f74004e7e8ba9ULL,
+ 0x1cd7580371e8d953ULL, 0x7f6ed89562764e30ULL, 0xb15926ff596f003dULL,
+ 0x9f65293da8c5d6b9ULL, 0x6ecef04dd690f84cULL, 0x4782275fff33af88ULL,
+ 0xe41433083f820801ULL, 0xfd0dfe409a1af9b5ULL, 0x4325a3342cdb396bULL,
+ 0x8ae77e62b301b252ULL, 0xc36f9e9f6655615aULL, 0x85455a2d92d32c09ULL,
+ 0xf2c7dea949477485ULL, 0x63cfb4c133a39ebaULL, 0x83b040cc6ebc5462ULL,
+ 0x3b9454c8fdb326b0ULL, 0x56f56a9e87ffd78cULL, 0x2dc2940d99f42bc6ULL,
+ 0x98f7df096b096e2dULL, 0x19a6e01e3ad852bfULL, 0x42a99ccbdbd4b40bULL,
+ 0xa59998af45e9c559ULL, 0x366295e807d93186ULL, 0x6b48181bfaa1f773ULL,
+ 0x1fec57e2157a0a1dULL, 0x4667446af6201ad5ULL, 0xe615ebcacfb0f075ULL,
+ 0xb8f31f4f68290778ULL, 0x22713ed6ce22d11eULL, 0x3057c1a72ec3c93bULL,
+ 0xcb46acc37c3f1f2fULL, 0xdbb893fd02aaf50eULL, 0x331fd92e600b9fcfULL,
+ 0xa498f96148ea3ad6ULL, 0xa8d8426e8b6a83eaULL, 0xa089b274b7735cdcULL,
+ 0x87f6b3731e524a11ULL, 0x118808e5cbc96749ULL, 0x9906e4c7b19bd394ULL,
+ 0xafed7f7e9b24a20cULL, 0x6509eadeeb3644a7ULL, 0x6c1ef1d3e8ef0edeULL,
+ 0xb9c97d43e9798fb4ULL, 0xa2f2d784740c28a3ULL, 0x7b8496476197566fULL,
+ 0x7a5be3e6b65f069dULL, 0xf96330ed78be6f10ULL, 0xeee60de77a076a15ULL,
+ 0x2b4bee4aa08b9bd0ULL, 0x6a56a63ec7b8894eULL, 0x02121359ba34fef4ULL,
+ 0x4cbf99f8283703fcULL, 0x398071350caf30c8ULL, 0xd0a77a89f017687aULL,
+ 0xf1c1a9eb9e423569ULL, 0x8c7976282dee8199ULL, 0x5d1737a5dd1f7abdULL,
+ 0x4f53433c09a9fa80ULL, 0xfa8b0c53df7ca1d9ULL, 0x3fd9dcbc886ccb77ULL,
+ 0xc040917ca91b4720ULL, 0x7dd00142f9d1dcdfULL, 0x8476fc1d4f387b58ULL,
+ 0x23f8e7c5f3316503ULL, 0x032a2244e7e37339ULL, 0x5c87a5d750f5a74bULL,
+ 0x082b4cc43698992eULL, 0xdf917becb858f63cULL, 0x3270b8fc5bf86ddaULL,
+ 0x10ae72bb29b5dd76ULL, 0x576ac94e7700362bULL, 0x1ad112dac61efb8fULL,
+ 0x691bc30ec5faa427ULL, 0xff246311cc327143ULL, 0x3142368e30e53206ULL,
+ 0x71380e31e02ca396ULL, 0x958d5c960aad76f1ULL, 0xf8d6f430c16da536ULL,
+ 0xc8ffd13f1be7e1d2ULL, 0x7578ae66004ddbe1ULL, 0x05833f01067be646ULL,
+ 0xbb34b5ad3bfe586dULL, 0x095f34c9a12b97f0ULL, 0x247ab64525d60ca8ULL,
+ 0xdcdbc6f3017477d1ULL, 0x4a2e14d4decad24dULL, 0xbdb5e6d9be0a1eebULL,
+ 0x2a7e70f7794301abULL, 0xdef42d8a270540fdULL, 0x01078ec0a34c22c1ULL,
+ 0xe5de511af4c16387ULL, 0x7ebb3a52bd9a330aULL, 0x77697857aa7d6435ULL,
+ 0x004e831603ae4c32ULL, 0xe7a21020ad78e312ULL, 0x9d41a70c6ab420f2ULL,
+ 0x28e06c18ea1141e6ULL, 0xd2b28cbd984f6b28ULL, 0x26b75f6c446e9d83ULL,
+ 0xba47568c4d418d7fULL, 0xd80badbfe6183d8eULL, 0x0e206d7f5f166044ULL,
+ 0xe258a43911cbca3eULL, 0x723a1746b21dc0bcULL, 0xc7caa854f5d7cdd3ULL,
+ 0x7cac32883d261d9cULL, 0x7690c26423ba942cULL, 0x17e55524478042b8ULL,
+ 0xe0be477656a2389fULL, 0x4d289b5e67ab2da0ULL, 0x44862b9c8fbbfd31ULL,
+ 0xb47cc8049d141365ULL, 0x822c1b362b91c793ULL, 0x4eb14655fb13dfd8ULL,
+ 0x1ecbba0714e2a97bULL, 0x6143459d5cde5f14ULL, 0x53a8fbf1d5f0ac89ULL,
+ 0x97ea04d81c5e5b00ULL, 0x622181a8d4fdb3f3ULL, 0xe9bcd341572a1208ULL,
+ 0x1411258643cce58aULL, 0x9144c5fea4c6e0a4ULL, 0x0d33d06565cf620fULL,
+ 0x54a48d489f219ca1ULL, 0xc43e5eac6d63c821ULL, 0xa9728b3a72770dafULL,
+ 0xd7934e7b20df87efULL, 0xe35503b61a3e86e5ULL, 0xcae321fbc819d504ULL,
+ 0x129a50b3ac60bfa6ULL, 0xcd5e68ea7e9fb6c3ULL, 0xb01c90199483b1c7ULL,
+ 0x3de93cd5c295376cULL, 0xaed52edf2ab9ad13ULL, 0x2e60f512c0a07884ULL,
+ 0xbc3d86a3e36210c9ULL, 0x35269d9b163951ceULL, 0x0c7d6e2ad0cdb5faULL,
+ 0x59e86297d87f5733ULL, 0x298ef221898db0e7ULL, 0x55000029d1a5aa7eULL,
+ 0x8bc08ae1b5061b45ULL, 0xc2c31c2b6c92703aULL, 0x94cc596baf25ef42ULL,
+ 0x0a1d73db22540456ULL, 0x04b6a0f9d9c4179aULL, 0xeffdafa2ae3d3c60ULL,
+ 0xf7c8075bb49496c4ULL, 0x9cc5c7141d1cd4e3ULL, 0x78bd1638218e5534ULL,
+ 0xb2f11568f850246aULL, 0xedfabcfa9502bc29ULL, 0x796ce5f2da23051bULL,
+ 0xaae128b0dc93537cULL, 0x3a493da0ee4b29aeULL, 0xb5df6b2c416895d7ULL,
+ 0xfcabbd25122d7f37ULL, 0x70810b58105dc4b1ULL, 0xe10fdd37f7882a90ULL,
+ 0x524dcab5518a3f5cULL, 0x3c9e85878451255bULL, 0x4029828119bd34e2ULL,
+ 0x74a05b6f5d3ceccbULL, 0xb610021542e13ecaULL, 0x0ff979d12f59e2acULL,
+ 0x6037da27e4f9cc50ULL, 0x5e92975a0df1847dULL, 0xd66de190d3e623feULL,
+ 0x5032d6b87b568048ULL, 0x9a36b7ce8235216eULL, 0x80272a7a24f64b4aULL,
+ 0x93efed8b8c6916f7ULL, 0x37ddbff44cce1555ULL, 0x4b95db5d4b99bd25ULL,
+ 0x92d3fda169812fc0ULL, 0xfb1a4a9a90660bb6ULL, 0x730c196946a4b9b2ULL,
+ 0x81e289aa7f49da68ULL, 0x64669a0f83b1a05fULL, 0x27b3ff7d9644f48bULL,
+ 0xcc6b615c8db675b3ULL, 0x674f20b9bcebbe95ULL, 0x6f31238275655982ULL,
+ 0x5ae488713e45cf05ULL, 0xbf619f9954c21157ULL, 0xeabac46040a8eae9ULL,
+ 0x454c6fe9f2c0c1cdULL, 0x419cf6496412691cULL, 0xd3dc3bef265b0f70ULL,
+ 0x6d0e60f5c3578a9eULL
+};
+
+static const u64 sbox4[256] = {
+ 0x5b0e608526323c55ULL, 0x1a46c1a9fa1b59f5ULL, 0xa9e245a17c4c8ffaULL,
+ 0x65ca5159db2955d7ULL, 0x05db0a76ce35afc2ULL, 0x81eac77ea9113d45ULL,
+ 0x528ef88ab6ac0a0dULL, 0xa09ea253597be3ffULL, 0x430ddfb3ac48cd56ULL,
+ 0xc4b3a67af45ce46fULL, 0x4ececfd8fbe2d05eULL, 0x3ef56f10b39935f0ULL,
+ 0x0b22d6829cd619c6ULL, 0x17fd460a74df2069ULL, 0x6cf8cc8e8510ed40ULL,
+ 0xd6c824bf3a6ecaa7ULL, 0x61243d581a817049ULL, 0x048bacb6bbc163a2ULL,
+ 0xd9a38ac27d44cc32ULL, 0x7fddff5baaf410abULL, 0xad6d495aa804824bULL,
+ 0xe1a6a74f2d8c9f94ULL, 0xd4f7851235dee8e3ULL, 0xfd4b7f886540d893ULL,
+ 0x247c20042aa4bfdaULL, 0x096ea1c517d1327cULL, 0xd56966b4361a6685ULL,
+ 0x277da5c31221057dULL, 0x94d59893a43acff7ULL, 0x64f0c51ccdc02281ULL,
+ 0x3d33bcc4ff6189dbULL, 0xe005cb184ce66af1ULL, 0xff5ccd1d1db99beaULL,
+ 0xb0b854a7fe42980fULL, 0x7bd46a6a718d4b9fULL, 0xd10fa8cc22a5fd8cULL,
+ 0xd31484952be4bd31ULL, 0xc7fa975fcb243847ULL, 0x4886ed1e5846c407ULL,
+ 0x28cddb791eb70b04ULL, 0xc2b00be2f573417fULL, 0x5c9590452180f877ULL,
+ 0x7a6bddfff370eb00ULL, 0xce509e38d6d9d6a4ULL, 0xebeb0f00647fa702ULL,
+ 0x1dcc06cf76606f06ULL, 0xe4d9f28ba286ff0aULL, 0xd85a305dc918c262ULL,
+ 0x475b1d8732225f54ULL, 0x2d4fb51668ccb5feULL, 0xa679b9d9d72bba20ULL,
+ 0x53841c0d912d43a5ULL, 0x3b7eaa48bf12a4e8ULL, 0x781e0e47f22f1ddfULL,
+ 0xeff20ce60ab50973ULL, 0x20d261d19dffb742ULL, 0x16a12b03062a2e39ULL,
+ 0x1960eb2239650495ULL, 0x251c16fed50eb8b8ULL, 0x9ac0c330f826016eULL,
+ 0xed152665953e7671ULL, 0x02d63194a6369570ULL, 0x5074f08394b1c987ULL,
+ 0x70ba598c90b25ce1ULL, 0x794a15810b9742f6ULL, 0x0d5925e9fcaf8c6cULL,
+ 0x3067716cd868744eULL, 0x910ab077e8d7731bULL, 0x6a61bbdb5ac42f61ULL,
+ 0x93513efbf0851567ULL, 0xf494724b9e83e9d5ULL, 0xe887e1985c09648dULL,
+ 0x34b1d3c675370cfdULL, 0xdc35e433bc0d255dULL, 0xd0aab84234131be0ULL,
+ 0x08042a50b48b7eafULL, 0x9997c4ee44a3ab35ULL, 0x829a7b49201799d0ULL,
+ 0x263b8307b7c54441ULL, 0x752f95f4fd6a6ca6ULL, 0x927217402c08c6e5ULL,
+ 0x2a8ab754a795d9eeULL, 0xa442f7552f72943dULL, 0x2c31334e19781208ULL,
+ 0x4fa98d7ceaee6291ULL, 0x55c3862f665db309ULL, 0xbd0610175d53b1f3ULL,
+ 0x46fe6cb840413f27ULL, 0x3fe03792df0cfa59ULL, 0xcfe700372eb85e8fULL,
+ 0xa7be29e7adbce118ULL, 0xe544ee5cde8431ddULL, 0x8a781b1b41f1873eULL,
+ 0xa5c94c78a0d2f0e7ULL, 0x39412e2877b60728ULL, 0xa1265ef3afc9a62cULL,
+ 0xbcc2770c6a2506c5ULL, 0x3ab66dd5dce1ce12ULL, 0xe65499d04a675b37ULL,
+ 0x7d8f523481bfd216ULL, 0x0f6f64fcec15f389ULL, 0x74efbe618b5b13c8ULL,
+ 0xacdc82b714273e1dULL, 0xdd40bfe003199d17ULL, 0x37e99257e7e061f8ULL,
+ 0xfa52626904775aaaULL, 0x8bbbf63a463d56f9ULL, 0xf0013f1543a26e64ULL,
+ 0xa8307e9f879ec898ULL, 0xcc4c27a4150177ccULL, 0x1b432f2cca1d3348ULL,
+ 0xde1d1f8f9f6fa013ULL, 0x606602a047a7ddd6ULL, 0xd237ab64cc1cb2c7ULL,
+ 0x9b938e7225fcd1d3ULL, 0xec4e03708e0ff476ULL, 0xfeb2fbda3d03c12dULL,
+ 0xae0bced2ee43889aULL, 0x22cb8923ebfb4f43ULL, 0x69360d013cf7396dULL,
+ 0x855e3602d2d4e022ULL, 0x073805bad01f784cULL, 0x33e17a133852f546ULL,
+ 0xdf4874058ac7b638ULL, 0xba92b29c678aa14aULL, 0x0ce89fc76cfaadcdULL,
+ 0x5f9d4e0908339e34ULL, 0xf1afe9291f5923b9ULL, 0x6e3480f60f4a265fULL,
+ 0xeebf3a2ab29b841cULL, 0xe21938a88f91b4adULL, 0x57dfeff845c6d3c3ULL,
+ 0x2f006b0bf62caaf2ULL, 0x62f479ef6f75ee78ULL, 0x11a55ad41c8916a9ULL,
+ 0xf229d29084fed453ULL, 0x42f1c27b16b000e6ULL, 0x2b1f76749823c074ULL,
+ 0x4b76eca3c2745360ULL, 0x8c98f463b91691bdULL, 0x14bcc93cf1ade66aULL,
+ 0x8885213e6d458397ULL, 0x8e177df0274d4711ULL, 0xb49b73b5503f2951ULL,
+ 0x10168168c3f96b6bULL, 0x0e3d963b63cab0aeULL, 0x8dfc4b5655a1db14ULL,
+ 0xf789f1356e14de5cULL, 0x683e68af4e51dac1ULL, 0xc9a84f9d8d4b0fd9ULL,
+ 0x3691e03f52a0f9d1ULL, 0x5ed86e46e1878e80ULL, 0x3c711a0e99d07150ULL,
+ 0x5a0865b20c4e9310ULL, 0x56fbfc1fe4f0682eULL, 0xea8d5de3105edf9bULL,
+ 0x71abfdb12379187aULL, 0x2eb99de1bee77b9cULL, 0x21ecc0ea33cf4523ULL,
+ 0x59a4d7521805c7a1ULL, 0x3896f5eb56ae7c72ULL, 0xaa638f3db18f75dcULL,
+ 0x9f39358dabe9808eULL, 0xb7defa91c00b72acULL, 0x6b5541fd62492d92ULL,
+ 0x6dc6dee8f92e4d5bULL, 0x353f57abc4beea7eULL, 0x735769d6da5690ceULL,
+ 0x0a234aa642391484ULL, 0xf6f9508028f80d9dULL, 0xb8e319a27ab3f215ULL,
+ 0x31ad9c1151341a4dULL, 0x773c22a57bef5805ULL, 0x45c7561a07968633ULL,
+ 0xf913da9e249dbe36ULL, 0xda652d9b78a64c68ULL, 0x4c27a97f3bc334efULL,
+ 0x76621220e66b17f4ULL, 0x967743899acd7d0bULL, 0xf3ee5bcae0ed6782ULL,
+ 0x409f753600c879fcULL, 0x06d09a39b5926db6ULL, 0x6f83aeb0317ac588ULL,
+ 0x01e6ca4a86381f21ULL, 0x66ff3462d19f3025ULL, 0x72207c24ddfd3bfbULL,
+ 0x4af6b6d3e2ece2ebULL, 0x9c994dbec7ea08deULL, 0x49ace597b09a8bc4ULL,
+ 0xb38c4766cf0797baULL, 0x131b9373c57c2a75ULL, 0xb1822cce61931e58ULL,
+ 0x9d7555b909ba1c0cULL, 0x127fafdd937d11d2ULL, 0x29da3badc66d92e4ULL,
+ 0xa2c1d57154c2ecbcULL, 0x58c5134d82f6fe24ULL, 0x1c3ae3515b62274fULL,
+ 0xe907c82e01cb8126ULL, 0xf8ed091913e37fcbULL, 0x3249d8f9c80046c9ULL,
+ 0x80cf9bede388fb63ULL, 0x1881539a116cf19eULL, 0x5103f3f76bd52457ULL,
+ 0x15b7e6f5ae47f7a8ULL, 0xdbd7c6ded47e9ccfULL, 0x44e55c410228bb1aULL,
+ 0xb647d4255edb4e99ULL, 0x5d11882bb8aafc30ULL, 0xf5098bbb29d3212aULL,
+ 0x8fb5ea14e90296b3ULL, 0x677b942157dd025aULL, 0xfb58e7c0a390acb5ULL,
+ 0x89d3674c83bd4a01ULL, 0x9e2da4df4bf3b93bULL, 0xfcc41e328cab4829ULL,
+ 0x03f38c96ba582c52ULL, 0xcad1bdbd7fd85db2ULL, 0xbbb442c16082ae83ULL,
+ 0xb95fe86ba5da9ab0ULL, 0xb22e04673771a93fULL, 0x845358c9493152d8ULL,
+ 0xbe2a488697b4541eULL, 0x95a2dc2dd38e6966ULL, 0xc02c11ac923c852bULL,
+ 0x2388b1990df2a87bULL, 0x7c8008fa1b4f37beULL, 0x1f70d0c84d54e503ULL,
+ 0x5490adec7ece57d4ULL, 0x002b3c27d9063a3aULL, 0x7eaea3848030a2bfULL,
+ 0xc602326ded2003c0ULL, 0x83a7287d69a94086ULL, 0xc57a5fcb30f57a8aULL,
+ 0xb56844e479ebe779ULL, 0xa373b40f05dcbce9ULL, 0xd71a786e88570ee2ULL,
+ 0x879cbacdbde8f6a0ULL, 0x976ad1bcc164a32fULL, 0xab21e25e9666d78bULL,
+ 0x901063aae5e5c33cULL, 0x9818b34448698d90ULL, 0xe36487ae3e1e8abbULL,
+ 0xafbdf931893bdcb4ULL, 0x6345a0dc5fbbd519ULL, 0x8628fe269b9465caULL,
+ 0x1e5d01603f9c51ecULL, 0x4de44006a15049b7ULL, 0xbf6c70e5f776cbb1ULL,
+ 0x411218f2ef552bedULL, 0xcb0c0708705a36a3ULL, 0xe74d14754f986044ULL,
+ 0xcd56d9430ea8280eULL, 0xc12591d7535f5065ULL, 0xc83223f1720aef96ULL,
+ 0xc3a0396f7363a51fULL
+};
+
+
+static void tgr192_round(u64 * ra, u64 * rb, u64 * rc, u64 x, int mul)
+{
+ u64 a = *ra;
+ u64 b = *rb;
+ u64 c = *rc;
+
+ c ^= x;
+ a -= sbox1[c & 0xff] ^ sbox2[(c >> 16) & 0xff]
+ ^ sbox3[(c >> 32) & 0xff] ^ sbox4[(c >> 48) & 0xff];
+ b += sbox4[(c >> 8) & 0xff] ^ sbox3[(c >> 24) & 0xff]
+ ^ sbox2[(c >> 40) & 0xff] ^ sbox1[(c >> 56) & 0xff];
+ b *= mul;
+
+ *ra = a;
+ *rb = b;
+ *rc = c;
+}
+
+
+static void tgr192_pass(u64 * ra, u64 * rb, u64 * rc, u64 * x, int mul)
+{
+ u64 a = *ra;
+ u64 b = *rb;
+ u64 c = *rc;
+
+ tgr192_round(&a, &b, &c, x[0], mul);
+ tgr192_round(&b, &c, &a, x[1], mul);
+ tgr192_round(&c, &a, &b, x[2], mul);
+ tgr192_round(&a, &b, &c, x[3], mul);
+ tgr192_round(&b, &c, &a, x[4], mul);
+ tgr192_round(&c, &a, &b, x[5], mul);
+ tgr192_round(&a, &b, &c, x[6], mul);
+ tgr192_round(&b, &c, &a, x[7], mul);
+
+ *ra = a;
+ *rb = b;
+ *rc = c;
+}
+
+
+static void tgr192_key_schedule(u64 * x)
+{
+ x[0] -= x[7] ^ 0xa5a5a5a5a5a5a5a5ULL;
+ x[1] ^= x[0];
+ x[2] += x[1];
+ x[3] -= x[2] ^ ((~x[1]) << 19);
+ x[4] ^= x[3];
+ x[5] += x[4];
+ x[6] -= x[5] ^ ((~x[4]) >> 23);
+ x[7] ^= x[6];
+ x[0] += x[7];
+ x[1] -= x[0] ^ ((~x[7]) << 19);
+ x[2] ^= x[1];
+ x[3] += x[2];
+ x[4] -= x[3] ^ ((~x[2]) >> 23);
+ x[5] ^= x[4];
+ x[6] += x[5];
+ x[7] -= x[6] ^ 0x0123456789abcdefULL;
+}
+
+
+/****************
+ * Transform the message DATA which consists of 512 bytes (8 words)
+ */
+
+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) );
+ }
+
+ /* save */
+ a = aa = tctx->a;
+ b = bb = tctx->b;
+ c = cc = tctx->c;
+
+ tgr192_pass(&a, &b, &c, x, 5);
+ tgr192_key_schedule(x);
+ tgr192_pass(&c, &a, &b, x, 7);
+ tgr192_key_schedule(x);
+ tgr192_pass(&b, &c, &a, x, 9);
+
+
+ /* feedforward */
+ a ^= aa;
+ b -= bb;
+ c += cc;
+ /* store */
+ tctx->a = a;
+ tctx->b = b;
+ tctx->c = c;
+}
+
+static void tgr192_init(void *ctx)
+{
+ struct tgr192_ctx *tctx = ctx;
+
+ memset (tctx->hash, 0, 64);
+ tctx->a = 0x0123456789abcdefULL;
+ tctx->b = 0xfedcba9876543210ULL;
+ tctx->c = 0xf096a5b4c3b2e187ULL;
+ tctx->nblocks = 0;
+ tctx->count = 0;
+}
+
+
+/* Update the message digest with the contents
+ * of INBUF with length INLEN. */
+static void tgr192_update(void *ctx, const u8 * inbuf, unsigned int len)
+{
+ struct tgr192_ctx *tctx = ctx;
+
+ if (tctx->count == 64) { /* flush the buffer */
+ tgr192_transform(tctx, tctx->hash);
+ tctx->count = 0;
+ tctx->nblocks++;
+ }
+ if (!inbuf) {
+ return;
+ }
+ if (tctx->count) {
+ for (; len && tctx->count < 64; len--) {
+ tctx->hash[tctx->count++] = *inbuf++;
+ }
+ tgr192_update(tctx, NULL, 0);
+ if (!len) {
+ return;
+ }
+
+ }
+
+ while (len >= 64) {
+ tgr192_transform(tctx, inbuf);
+ tctx->count = 0;
+ tctx->nblocks++;
+ len -= 64;
+ inbuf += 64;
+ }
+ for (; len && tctx->count < 64; len--) {
+ tctx->hash[tctx->count++] = *inbuf++;
+ }
+}
+
+
+
+/* The routine terminates the computation */
+static void tgr192_final(void *ctx, u8 * out)
+{
+ struct tgr192_ctx *tctx = ctx;
+ u32 t, msb, lsb;
+ u8 *p;
+ int i, j;
+
+ tgr192_update(tctx, NULL, 0); /* flush */ ;
+
+ msb = 0;
+ t = tctx->nblocks;
+ if ((lsb = t << 6) < t) { /* multiply by 64 to make a byte count */
+ msb++;
+ }
+ msb += t >> 26;
+ t = lsb;
+ if ((lsb = t + tctx->count) < t) { /* add the count */
+ msb++;
+ }
+ t = lsb;
+ if ((lsb = t << 3) < t) { /* multiply by 8 to make a bit count */
+ msb++;
+ }
+ msb += t >> 29;
+
+ if (tctx->count < 56) { /* enough room */
+ tctx->hash[tctx->count++] = 0x01; /* pad */
+ while (tctx->count < 56) {
+ tctx->hash[tctx->count++] = 0; /* pad */
+ }
+ } else { /* need one extra block */
+ tctx->hash[tctx->count++] = 0x01; /* pad character */
+ while (tctx->count < 64) {
+ tctx->hash[tctx->count++] = 0;
+ }
+ tgr192_update(tctx, NULL, 0); /* flush */ ;
+ 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;
+ 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;
+ }
+}
+
+static void tgr160_final(void *ctx, u8 * out)
+{
+ struct tgr192_ctx *wctx = ctx;
+ u8 D[64];
+
+ tgr192_final(wctx, D);
+ memcpy(out, D, TGR160_DIGEST_SIZE);
+ memset(D, 0, TGR192_DIGEST_SIZE);
+}
+
+static void tgr128_final(void *ctx, u8 * out)
+{
+ struct tgr192_ctx *wctx = ctx;
+ u8 D[64];
+
+ tgr192_final(wctx, D);
+ memcpy(out, D, TGR128_DIGEST_SIZE);
+ memset(D, 0, TGR192_DIGEST_SIZE);
+}
+
+static struct crypto_alg tgr192 = {
+ .cra_name = "tgr192",
+ .cra_flags = CRYPTO_ALG_TYPE_DIGEST,
+ .cra_blocksize = TGR192_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct tgr192_ctx),
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(tgr192.cra_list),
+ .cra_u = {.digest = {
+ .dia_digestsize = TGR192_DIGEST_SIZE,
+ .dia_init = tgr192_init,
+ .dia_update = tgr192_update,
+ .dia_final = tgr192_final}}
+};
+
+static struct crypto_alg tgr160 = {
+ .cra_name = "tgr160",
+ .cra_flags = CRYPTO_ALG_TYPE_DIGEST,
+ .cra_blocksize = TGR192_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct tgr192_ctx),
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(tgr160.cra_list),
+ .cra_u = {.digest = {
+ .dia_digestsize = TGR160_DIGEST_SIZE,
+ .dia_init = tgr192_init,
+ .dia_update = tgr192_update,
+ .dia_final = tgr160_final}}
+};
+
+static struct crypto_alg tgr128 = {
+ .cra_name = "tgr128",
+ .cra_flags = CRYPTO_ALG_TYPE_DIGEST,
+ .cra_blocksize = TGR192_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct tgr192_ctx),
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(tgr128.cra_list),
+ .cra_u = {.digest = {
+ .dia_digestsize = TGR128_DIGEST_SIZE,
+ .dia_init = tgr192_init,
+ .dia_update = tgr192_update,
+ .dia_final = tgr128_final}}
+};
+
+static int __init init(void)
+{
+ int ret = 0;
+
+ ret = crypto_register_alg(&tgr192);
+
+ if (ret < 0) {
+ goto out;
+ }
+
+ ret = crypto_register_alg(&tgr160);
+ if (ret < 0) {
+ crypto_unregister_alg(&tgr192);
+ goto out;
+ }
+
+ ret = crypto_register_alg(&tgr128);
+ if (ret < 0) {
+ crypto_unregister_alg(&tgr192);
+ crypto_unregister_alg(&tgr160);
+ }
+ out:
+ return ret;
+}
+
+static void __exit fini(void)
+{
+ crypto_unregister_alg(&tgr192);
+ crypto_unregister_alg(&tgr160);
+ crypto_unregister_alg(&tgr128);
+}
+
+MODULE_ALIAS("tgr160");
+MODULE_ALIAS("tgr128");
+
+module_init(init);
+module_exit(fini);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Tiger Message Digest Algorithm");
diff --git a/drivers/Makefile b/drivers/Makefile
index 04fba9e5009b4..15681de688f48 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -47,8 +47,8 @@ obj-$(CONFIG_PARIDE) += block/paride/
obj-$(CONFIG_TC) += tc/
obj-$(CONFIG_USB) += usb/
obj-$(CONFIG_USB_GADGET) += usb/gadget/
-obj-$(CONFIG_INPUT) += input/
obj-$(CONFIG_GAMEPORT) += input/gameport/
+obj-$(CONFIG_INPUT) += input/
obj-$(CONFIG_I2O) += message/
obj-$(CONFIG_I2C) += i2c/
obj-$(CONFIG_W1) += w1/
@@ -61,5 +61,6 @@ obj-$(CONFIG_EISA) += eisa/
obj-$(CONFIG_CPU_FREQ) += cpufreq/
obj-$(CONFIG_MMC) += mmc/
obj-$(CONFIG_INFINIBAND) += infiniband/
+obj-$(CONFIG_BLK_DEV_SGIIOC4) += sn/
obj-y += firmware/
obj-$(CONFIG_CRYPTO) += crypto/
diff --git a/drivers/acorn/char/i2c.c b/drivers/acorn/char/i2c.c
index e01e4fd5f5d64..c22bb9dca1ec9 100644
--- a/drivers/acorn/char/i2c.c
+++ b/drivers/acorn/char/i2c.c
@@ -313,7 +313,7 @@ static struct i2c_algo_bit_data ioc_data = {
static int ioc_client_reg(struct i2c_client *client)
{
- if (client->id == I2C_DRIVERID_PCF8583 &&
+ if (client->driver->id == I2C_DRIVERID_PCF8583 &&
client->addr == 0x50) {
struct rtc_tm rtctm;
unsigned int year;
diff --git a/drivers/acorn/char/pcf8583.c b/drivers/acorn/char/pcf8583.c
index ad768a18780fb..ad7ae7ab89204 100644
--- a/drivers/acorn/char/pcf8583.c
+++ b/drivers/acorn/char/pcf8583.c
@@ -51,7 +51,6 @@ pcf8583_attach(struct i2c_adapter *adap, int addr, int kind)
return -ENOMEM;
memset(c, 0, sizeof(*c));
- c->id = pcf8583_driver.id;
c->addr = addr;
c->adapter = adap;
c->driver = &pcf8583_driver;
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 76d3f2b141929..894128bffc58c 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -45,16 +45,18 @@ config ACPI_BOOT
depends on ACPI || X86_HT
default y
+if ACPI
+
config ACPI_INTERPRETER
bool
- depends on ACPI
depends on !IA64_SGI_SN
default y
+if ACPI_INTERPRETER
+
config ACPI_SLEEP
bool "Sleep States (EXPERIMENTAL)"
- depends on X86 && ACPI
- depends on ACPI_INTERPRETER
+ depends on X86
depends on EXPERIMENTAL && PM
default y
---help---
@@ -81,7 +83,6 @@ config ACPI_SLEEP_PROC_FS
config ACPI_AC
tristate "AC Adapter"
depends on X86
- depends on ACPI_INTERPRETER
default m
help
This driver adds support for the AC Adapter object, which indicates
@@ -91,7 +92,6 @@ config ACPI_AC
config ACPI_BATTERY
tristate "Battery"
depends on X86
- depends on ACPI_INTERPRETER
default m
help
This driver adds support for battery information through
@@ -100,7 +100,6 @@ config ACPI_BATTERY
config ACPI_BUTTON
tristate "Button"
- depends on ACPI_INTERPRETER
depends on !IA64_SGI_SN
default m
help
@@ -112,7 +111,6 @@ config ACPI_BUTTON
config ACPI_VIDEO
tristate "Video"
- depends on ACPI_INTERPRETER
depends on EXPERIMENTAL
depends on !IA64_SGI_SN
default m
@@ -127,7 +125,6 @@ config ACPI_VIDEO
config ACPI_FAN
tristate "Fan"
- depends on ACPI_INTERPRETER
depends on !IA64_SGI_SN
default m
help
@@ -136,7 +133,6 @@ config ACPI_FAN
config ACPI_PROCESSOR
tristate "Processor"
- depends on ACPI_INTERPRETER
depends on !IA64_SGI_SN
default m
help
@@ -165,7 +161,6 @@ config ACPI_THERMAL
config ACPI_NUMA
bool "NUMA support"
- depends on ACPI_INTERPRETER
depends on NUMA
depends on (IA64 || X86_64)
default y if IA64_GENERIC || IA64_SGI_SN2
@@ -173,7 +168,6 @@ config ACPI_NUMA
config ACPI_ASUS
tristate "ASUS/Medion Laptop Extras"
depends on X86
- depends on ACPI_INTERPRETER
default m
---help---
This driver provides support for extra features of ACPI-compatible
@@ -203,7 +197,6 @@ config ACPI_ASUS
config ACPI_IBM
tristate "IBM ThinkPad Laptop Extras"
depends on X86
- depends on ACPI_INTERPRETER
default m
---help---
This is a Linux ACPI driver for the IBM ThinkPad laptops. It adds
@@ -217,7 +210,6 @@ config ACPI_IBM
config ACPI_TOSHIBA
tristate "Toshiba Laptop Extras"
depends on X86
- depends on ACPI_INTERPRETER
default m
---help---
This driver adds support for access to certain system settings
@@ -244,7 +236,7 @@ config ACPI_TOSHIBA
config ACPI_CUSTOM_DSDT
bool "Include Custom DSDT"
- depends on ACPI_INTERPRETER && !STANDALONE
+ depends on !STANDALONE
default n
help
Thist option is to load a custom ACPI DSDT
@@ -271,7 +263,6 @@ config ACPI_BLACKLIST_YEAR
config ACPI_DEBUG
bool "Debug Statements"
- depends on ACPI_INTERPRETER
depends on !IA64_SGI_SN
default n
help
@@ -281,14 +272,12 @@ config ACPI_DEBUG
config ACPI_BUS
bool
- depends on ACPI_INTERPRETER
depends on !IA64_SGI_SN
default y
config ACPI_EC
bool
depends on X86
- depends on ACPI_INTERPRETER
default y
help
This driver is required on some systems for the proper operation of
@@ -297,28 +286,27 @@ config ACPI_EC
config ACPI_POWER
bool
- depends on ACPI_INTERPRETER
depends on !IA64_SGI_SN
default y
config ACPI_PCI
bool
- depends on ACPI_INTERPRETER
depends on !IA64_SGI_SN
default PCI
config ACPI_SYSTEM
bool
- depends on ACPI_INTERPRETER
depends on !IA64_SGI_SN
default y
help
This driver will enable your system to shut down using ACPI, and
dump your ACPI DSDT table using /proc/acpi/dsdt.
+endif # ACPI_INTERPRETER
+
config X86_PM_TIMER
bool "Power Management Timer Support"
- depends on X86 && ACPI
+ depends on X86
depends on ACPI_BOOT && EXPERIMENTAL
depends on !X86_64
default n
@@ -337,10 +325,12 @@ config X86_PM_TIMER
config ACPI_CONTAINER
tristate "ACPI0004,PNP0A05 and PNP0A06 Container Driver (EXPERIMENTAL)"
- depends on ACPI && EXPERIMENTAL
+ depends on EXPERIMENTAL
default (ACPI_HOTPLUG_MEMORY || ACPI_HOTPLUG_CPU || ACPI_HOTPLUG_IO)
---help---
This is the ACPI generic container driver which supports
ACPI0004, PNP0A05 and PNP0A06 devices
+endif # ACPI
+
endmenu
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
index b4c265837da1f..a4750192a3199 100644
--- a/drivers/acpi/pci_irq.c
+++ b/drivers/acpi/pci_irq.c
@@ -460,7 +460,7 @@ void
acpi_pci_irq_disable (
struct pci_dev *dev)
{
- u32 gsi = 0;
+ int gsi = 0;
u8 pin = 0;
int edge_level = ACPI_LEVEL_SENSITIVE;
int active_high_low = ACPI_ACTIVE_LOW;
@@ -487,10 +487,10 @@ acpi_pci_irq_disable (
* If no PRT entry was found, we'll try to derive an IRQ from the
* device's parent bridge.
*/
- if (!gsi)
+ if (gsi < 0)
gsi = acpi_pci_irq_derive(dev, pin,
&edge_level, &active_high_low);
- if (!gsi)
+ if (gsi < 0)
return_VOID;
/*
diff --git a/drivers/acpi/sleep/proc.c b/drivers/acpi/sleep/proc.c
index 607cfddc753a6..fd7c5a0649afd 100644
--- a/drivers/acpi/sleep/proc.c
+++ b/drivers/acpi/sleep/proc.c
@@ -84,10 +84,11 @@ static int acpi_system_alarm_seq_show(struct seq_file *seq, void *offset)
u32 sec, min, hr;
u32 day, mo, yr;
unsigned char rtc_control = 0;
+ unsigned long flags;
ACPI_FUNCTION_TRACE("acpi_system_alarm_seq_show");
- spin_lock(&rtc_lock);
+ spin_lock_irqsave(&rtc_lock, flags);
sec = CMOS_READ(RTC_SECONDS_ALARM);
min = CMOS_READ(RTC_MINUTES_ALARM);
@@ -109,7 +110,7 @@ static int acpi_system_alarm_seq_show(struct seq_file *seq, void *offset)
else
yr = CMOS_READ(RTC_YEAR);
- spin_unlock(&rtc_lock);
+ spin_unlock_irqrestore(&rtc_lock, flags);
if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
BCD_TO_BIN(sec);
diff --git a/drivers/atm/ambassador.c b/drivers/atm/ambassador.c
index 3870e3787b7b4..c46d9520c5a75 100644
--- a/drivers/atm/ambassador.c
+++ b/drivers/atm/ambassador.c
@@ -296,16 +296,16 @@ static inline void __init show_version (void) {
#endif
#define UCODE2(x) #x
-static u32 __initdata ucode_start =
+static u32 __devinitdata ucode_start =
#include UCODE(start)
;
-static region __initdata ucode_regions[] = {
+static region __devinitdata ucode_regions[] = {
#include UCODE(regions)
{ 0, 0 }
};
-static u32 __initdata ucode_data[] = {
+static u32 __devinitdata ucode_data[] = {
#include UCODE(data)
0xdeadbeef
};
@@ -345,7 +345,7 @@ static inline u32 rd_plain (const amb_dev * dev, size_t addr) {
}
static inline void wr_mem (const amb_dev * dev, size_t addr, u32 data) {
- u32 be = cpu_to_be32 (data);
+ __be32 be = cpu_to_be32 (data);
PRINTD (DBG_FLOW|DBG_REGS, "wr: %08zx <- %08x b[%08x]", addr, data, be);
#ifdef AMB_MMIO
dev->membase[addr / sizeof(u32)] = be;
@@ -356,9 +356,9 @@ static inline void wr_mem (const amb_dev * dev, size_t addr, u32 data) {
static inline u32 rd_mem (const amb_dev * dev, size_t addr) {
#ifdef AMB_MMIO
- u32 be = dev->membase[addr / sizeof(u32)];
+ __be32 be = dev->membase[addr / sizeof(u32)];
#else
- u32 be = inl (dev->iobase + addr);
+ __be32 be = inl (dev->iobase + addr);
#endif
u32 data = be32_to_cpu (be);
PRINTD (DBG_FLOW|DBG_REGS, "rd: %08zx -> %08x b[%08x]", addr, data, be);
@@ -1539,7 +1539,7 @@ static void do_housekeeping (unsigned long arg) {
/********** creation of communication queues **********/
-static int __init create_queues (amb_dev * dev, unsigned int cmds,
+static int __devinit create_queues (amb_dev * dev, unsigned int cmds,
unsigned int txs, unsigned int * rxs,
unsigned int * rx_buffer_sizes) {
unsigned char pool;
@@ -1769,7 +1769,7 @@ static int decode_loader_result (loader_command cmd, u32 result)
return res;
}
-static int __init do_loader_command (volatile loader_block * lb,
+static int __devinit do_loader_command (volatile loader_block * lb,
const amb_dev * dev, loader_command cmd) {
unsigned long timeout;
@@ -1825,7 +1825,7 @@ static int __init do_loader_command (volatile loader_block * lb,
/* loader: determine loader version */
-static int __init get_loader_version (loader_block * lb,
+static int __devinit get_loader_version (loader_block * lb,
const amb_dev * dev, u32 * version) {
int res;
@@ -1841,7 +1841,7 @@ static int __init get_loader_version (loader_block * lb,
/* loader: write memory data blocks */
-static int __init loader_write (loader_block * lb,
+static int __devinit loader_write (loader_block * lb,
const amb_dev * dev, const u32 * data,
u32 address, unsigned int count) {
unsigned int i;
@@ -1860,7 +1860,7 @@ static int __init loader_write (loader_block * lb,
/* loader: verify memory data blocks */
-static int __init loader_verify (loader_block * lb,
+static int __devinit loader_verify (loader_block * lb,
const amb_dev * dev, const u32 * data,
u32 address, unsigned int count) {
unsigned int i;
@@ -1885,7 +1885,7 @@ static int __init loader_verify (loader_block * lb,
/* loader: start microcode */
-static int __init loader_start (loader_block * lb,
+static int __devinit loader_start (loader_block * lb,
const amb_dev * dev, u32 address) {
PRINTD (DBG_FLOW|DBG_LOAD, "loader_start");
@@ -1961,7 +1961,7 @@ static int amb_reset (amb_dev * dev, int diags) {
/********** transfer and start the microcode **********/
-static int __init ucode_init (loader_block * lb, amb_dev * dev) {
+static int __devinit ucode_init (loader_block * lb, amb_dev * dev) {
unsigned int i = 0;
unsigned int total = 0;
const u32 * pointer = ucode_data;
@@ -2007,11 +2007,11 @@ static int __init ucode_init (loader_block * lb, amb_dev * dev) {
/********** give adapter parameters **********/
-static inline u32 bus_addr(void * addr) {
+static inline __be32 bus_addr(void * addr) {
return cpu_to_be32 (virt_to_bus (addr));
}
-static int __init amb_talk (amb_dev * dev) {
+static int __devinit amb_talk (amb_dev * dev) {
adap_talk_block a;
unsigned char pool;
unsigned long timeout;
@@ -2058,7 +2058,7 @@ static int __init amb_talk (amb_dev * dev) {
}
// get microcode version
-static void __init amb_ucode_version (amb_dev * dev) {
+static void __devinit amb_ucode_version (amb_dev * dev) {
u32 major;
u32 minor;
command cmd;
@@ -2085,7 +2085,7 @@ static u8 bit_swap (u8 byte)
}
// get end station address
-static void __init amb_esi (amb_dev * dev, u8 * esi) {
+static void __devinit amb_esi (amb_dev * dev, u8 * esi) {
u32 lower4;
u16 upper2;
command cmd;
@@ -2131,7 +2131,7 @@ static void fixup_plx_window (amb_dev *dev, loader_block *lb)
return;
}
-static int __init amb_init (amb_dev * dev)
+static int __devinit amb_init (amb_dev * dev)
{
loader_block lb;
@@ -2447,7 +2447,7 @@ static int __init amb_module_init (void)
amb_check_args();
// get the juice
- return pci_module_init(&amb_driver);
+ return pci_register_driver(&amb_driver);
}
/********** module exit **********/
diff --git a/drivers/atm/ambassador.h b/drivers/atm/ambassador.h
index 3892dcf9dc2ea..84a93063cfe1a 100644
--- a/drivers/atm/ambassador.h
+++ b/drivers/atm/ambassador.h
@@ -342,21 +342,21 @@ typedef struct {
#define MAX_TRANSFER_DATA 11
typedef struct {
- u32 address;
- u32 count;
- u32 data[MAX_TRANSFER_DATA];
+ __be32 address;
+ __be32 count;
+ __be32 data[MAX_TRANSFER_DATA];
} transfer_block;
typedef struct {
- u32 result;
- u32 command;
+ __be32 result;
+ __be32 command;
union {
transfer_block transfer;
- u32 version;
- u32 start;
- u32 data[MAX_COMMAND_DATA];
+ __be32 version;
+ __be32 start;
+ __be32 data[MAX_COMMAND_DATA];
} payload;
- u32 valid;
+ __be32 valid;
} loader_block;
/* command queue */
@@ -366,46 +366,46 @@ typedef struct {
typedef struct {
union {
struct {
- u32 vc;
- u32 flags;
- u32 rate;
+ __be32 vc;
+ __be32 flags;
+ __be32 rate;
} open;
struct {
- u32 vc;
- u32 rate;
+ __be32 vc;
+ __be32 rate;
} modify_rate;
struct {
- u32 vc;
- u32 flags;
+ __be32 vc;
+ __be32 flags;
} modify_flags;
struct {
- u32 vc;
+ __be32 vc;
} close;
struct {
- u32 lower4;
- u32 upper2;
+ __be32 lower4;
+ __be32 upper2;
} bia;
struct {
- u32 address;
+ __be32 address;
} suni;
struct {
- u32 major;
- u32 minor;
+ __be32 major;
+ __be32 minor;
} version;
struct {
- u32 read;
- u32 write;
+ __be32 read;
+ __be32 write;
} speed;
struct {
- u32 flags;
+ __be32 flags;
} flush;
struct {
- u32 address;
- u32 data;
+ __be32 address;
+ __be32 data;
} memory;
- u32 par[3];
+ __be32 par[3];
} args;
- u32 request;
+ __be32 request;
} command;
/* transmit queues and associated structures */
@@ -417,8 +417,8 @@ typedef struct {
/* TX is described by 1+ tx_frags followed by a tx_frag_end */
typedef struct {
- u32 bytes;
- u32 address;
+ __be32 bytes;
+ __be32 address;
} tx_frag;
/* apart from handle the fields here are for the adapter to play with
@@ -452,9 +452,9 @@ typedef union {
/* this "points" to the sequence of fragments and trailer */
typedef struct {
- u16 vc;
- u16 tx_descr_length;
- u32 tx_descr_addr;
+ __be16 vc;
+ __be16 tx_descr_length;
+ __be32 tx_descr_addr;
} tx_in;
/* handle is the handle from tx_in */
@@ -471,17 +471,17 @@ typedef struct {
typedef struct {
u32 handle;
- u16 vc;
- u16 lec_id; // unused
- u16 status;
- u16 length;
+ __be16 vc;
+ __be16 lec_id; // unused
+ __be16 status;
+ __be16 length;
} rx_out;
/* buffer supply structure */
typedef struct {
u32 handle;
- u32 host_address;
+ __be32 host_address;
} rx_in;
/* This first structure is the area in host memory where the adapter
@@ -495,22 +495,22 @@ typedef struct {
adapter. */
typedef struct {
- u32 command_start; /* SRB commands completions */
- u32 command_end; /* SRB commands completions */
- u32 tx_start;
- u32 tx_end;
- u32 txcom_start; /* tx completions */
- u32 txcom_end; /* tx completions */
+ __be32 command_start; /* SRB commands completions */
+ __be32 command_end; /* SRB commands completions */
+ __be32 tx_start;
+ __be32 tx_end;
+ __be32 txcom_start; /* tx completions */
+ __be32 txcom_end; /* tx completions */
struct {
- u32 buffer_start;
- u32 buffer_end;
+ __be32 buffer_start;
+ __be32 buffer_end;
u32 buffer_q_get;
u32 buffer_q_end;
u32 buffer_aptr;
- u32 rx_start; /* rx completions */
- u32 rx_end;
+ __be32 rx_start; /* rx completions */
+ __be32 rx_end;
u32 rx_ptr;
- u32 buffer_size; /* size of host buffer */
+ __be32 buffer_size; /* size of host buffer */
} rec_struct[NUM_RX_POOLS];
#ifdef AMB_NEW_MICROCODE
u16 init_flags;
diff --git a/drivers/atm/atmtcp.c b/drivers/atm/atmtcp.c
index 436b83a1b6187..f2f01cb82cb4f 100644
--- a/drivers/atm/atmtcp.c
+++ b/drivers/atm/atmtcp.c
@@ -67,7 +67,7 @@ static int atmtcp_send_control(struct atm_vcc *vcc,int type,
*(struct atm_vcc **) &new_msg->vcc = vcc;
old_test = test_bit(flag,&vcc->flags);
out_vcc->push(out_vcc,skb);
- add_wait_queue(vcc->sk->sk_sleep, &wait);
+ add_wait_queue(sk_atm(vcc)->sk_sleep, &wait);
while (test_bit(flag,&vcc->flags) == old_test) {
mb();
out_vcc = PRIV(vcc->dev) ? PRIV(vcc->dev)->vcc : NULL;
@@ -79,7 +79,7 @@ static int atmtcp_send_control(struct atm_vcc *vcc,int type,
schedule();
}
set_current_state(TASK_RUNNING);
- remove_wait_queue(vcc->sk->sk_sleep, &wait);
+ remove_wait_queue(sk_atm(vcc)->sk_sleep, &wait);
return error;
}
@@ -91,7 +91,7 @@ static int atmtcp_recv_control(const struct atmtcp_control *msg)
vcc->vpi = msg->addr.sap_addr.vpi;
vcc->vci = msg->addr.sap_addr.vci;
vcc->qos = msg->qos;
- vcc->sk->sk_err = -msg->result;
+ sk_atm(vcc)->sk_err = -msg->result;
switch (msg->type) {
case ATMTCP_CTRL_OPEN:
change_bit(ATM_VF_READY,&vcc->flags);
@@ -104,7 +104,7 @@ static int atmtcp_recv_control(const struct atmtcp_control *msg)
msg->type);
return -EINVAL;
}
- wake_up(vcc->sk->sk_sleep);
+ wake_up(sk_atm(vcc)->sk_sleep);
return 0;
}
@@ -135,7 +135,7 @@ static int atmtcp_v_open(struct atm_vcc *vcc)
clear_bit(ATM_VF_READY,&vcc->flags); /* just in case ... */
error = atmtcp_send_control(vcc,ATMTCP_CTRL_OPEN,&msg,ATM_VF_READY);
if (error) return error;
- return -vcc->sk->sk_err;
+ return -sk_atm(vcc)->sk_err;
}
@@ -267,7 +267,7 @@ static void atmtcp_c_close(struct atm_vcc *vcc)
walk = atm_sk(s);
if (walk->dev != atmtcp_dev)
continue;
- wake_up(walk->sk->sk_sleep);
+ wake_up(s->sk_sleep);
}
}
read_unlock(&vcc_sklist_lock);
@@ -417,7 +417,7 @@ static int atmtcp_attach(struct atm_vcc *vcc,int itf)
}
PRIV(dev)->vcc = vcc;
vcc->dev = &atmtcp_control_dev;
- vcc_insert_socket(vcc->sk);
+ vcc_insert_socket(sk_atm(vcc));
set_bit(ATM_VF_META,&vcc->flags);
set_bit(ATM_VF_READY,&vcc->flags);
vcc->dev_data = dev;
diff --git a/drivers/atm/firestream.c b/drivers/atm/firestream.c
index b5cd8619205e5..101f0cc33d103 100644
--- a/drivers/atm/firestream.c
+++ b/drivers/atm/firestream.c
@@ -2034,7 +2034,7 @@ static int __init firestream_init_module (void)
int error;
func_enter ();
- error = pci_module_init(&firestream_driver);
+ error = pci_register_driver(&firestream_driver);
func_exit ();
return error;
}
diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c
index 3ad3d9e9ab054..196b336446275 100644
--- a/drivers/atm/fore200e.c
+++ b/drivers/atm/fore200e.c
@@ -96,10 +96,6 @@
#define FORE200E_NEXT_ENTRY(index, modulo) (index = ++(index) % (modulo))
-
-#define MSECS(ms) (((ms)*HZ/1000)+1)
-
-
#if 1
#define ASSERT(expr) if (!(expr)) { \
printk(FORE200E "assertion failed! %s[%d]: %s\n", \
@@ -114,7 +110,7 @@
static const struct atmdev_ops fore200e_ops;
static const struct fore200e_bus fore200e_bus[];
-static struct fore200e* fore200e_boards = NULL;
+static LIST_HEAD(fore200e_boards);
MODULE_AUTHOR("Christophe Lizzi - credits to Uwe Dannowski and Heikki Vatiainen");
@@ -246,7 +242,7 @@ fore200e_chunk_free(struct fore200e* fore200e, struct chunk* chunk)
static void
fore200e_spin(int msecs)
{
- unsigned long timeout = jiffies + MSECS(msecs);
+ unsigned long timeout = jiffies + msecs_to_jiffies(msecs);
while (time_before(jiffies, timeout));
}
@@ -254,7 +250,7 @@ fore200e_spin(int msecs)
static int
fore200e_poll(struct fore200e* fore200e, volatile u32* addr, u32 val, int msecs)
{
- unsigned long timeout = jiffies + MSECS(msecs);
+ unsigned long timeout = jiffies + msecs_to_jiffies(msecs);
int ok;
mb();
@@ -278,7 +274,7 @@ fore200e_poll(struct fore200e* fore200e, volatile u32* addr, u32 val, int msecs)
static int
fore200e_io_poll(struct fore200e* fore200e, volatile u32 __iomem *addr, u32 val, int msecs)
{
- unsigned long timeout = jiffies + MSECS(msecs);
+ unsigned long timeout = jiffies + msecs_to_jiffies(msecs);
int ok;
do {
@@ -637,39 +633,6 @@ fore200e_pca_configure(struct fore200e* fore200e)
}
-static struct fore200e* __init
-fore200e_pca_detect(const struct fore200e_bus* bus, int index)
-{
- struct fore200e* fore200e;
- struct pci_dev* pci_dev = NULL;
- int count = index;
-
- do {
- pci_dev = pci_find_device(PCI_VENDOR_ID_FORE, PCI_DEVICE_ID_FORE_PCA200E, pci_dev);
- if (pci_dev == NULL)
- return NULL;
- } while (count--);
-
- if (pci_enable_device(pci_dev))
- return NULL;
-
- fore200e = fore200e_kmalloc(sizeof(struct fore200e), GFP_KERNEL);
- if (fore200e == NULL)
- return NULL;
-
- fore200e->bus = bus;
- fore200e->bus_dev = pci_dev;
- fore200e->irq = pci_dev->irq;
- fore200e->phys_base = pci_resource_start(pci_dev, 0);
-
- sprintf(fore200e->name, "%s-%d", bus->model_name, index - 1);
-
- pci_set_master(pci_dev);
-
- return fore200e;
-}
-
-
static int __init
fore200e_pca_prom_read(struct fore200e* fore200e, struct prom_data* prom)
{
@@ -1027,7 +990,7 @@ fore200e_tx_irq(struct fore200e* fore200e)
/* when a vcc is closed, some PDUs may be still pending in the tx queue.
if the same vcc is immediately re-opened, those pending PDUs must
not be popped after the completion of their emission, as they refer
- to the prior incarnation of that vcc. otherwise, vcc->sk->sk_wmem_alloc
+ to the prior incarnation of that vcc. otherwise, sk_atm(vcc)->sk_wmem_alloc
would be decremented by the size of the (unrelated) skb, possibly
leading to a negative sk->sk_wmem_alloc count, ultimately freezing the vcc.
we thus bind the tx entry to the current incarnation of the vcc
@@ -1054,8 +1017,8 @@ fore200e_tx_irq(struct fore200e* fore200e)
}
#if 1
/* race fixed by the above incarnation mechanism, but... */
- if (atomic_read(&vcc->sk->sk_wmem_alloc) < 0) {
- atomic_set(&vcc->sk->sk_wmem_alloc, 0);
+ if (atomic_read(&sk_atm(vcc)->sk_wmem_alloc) < 0) {
+ atomic_set(&sk_atm(vcc)->sk_wmem_alloc, 0);
}
#endif
/* check error condition */
@@ -1258,12 +1221,12 @@ fore200e_push_rpd(struct fore200e* fore200e, struct atm_vcc* vcc, struct rpd* rp
return -ENOMEM;
}
- ASSERT(atomic_read(&vcc->sk->sk_wmem_alloc) >= 0);
+ ASSERT(atomic_read(&sk_atm(vcc)->sk_wmem_alloc) >= 0);
vcc->push(vcc, skb);
atomic_inc(&vcc->stats->rx);
- ASSERT(atomic_read(&vcc->sk->sk_wmem_alloc) >= 0);
+ ASSERT(atomic_read(&sk_atm(vcc)->sk_wmem_alloc) >= 0);
return 0;
}
@@ -1700,7 +1663,7 @@ fore200e_send(struct atm_vcc *vcc, struct sk_buff *skb)
unsigned long flags;
ASSERT(vcc);
- ASSERT(atomic_read(&vcc->sk->sk_wmem_alloc) >= 0);
+ ASSERT(atomic_read(&sk_atm(vcc)->sk_wmem_alloc) >= 0);
ASSERT(fore200e);
ASSERT(fore200e_vcc);
@@ -2596,7 +2559,7 @@ static int __init
fore200e_monitor_getc(struct fore200e* fore200e)
{
struct cp_monitor __iomem * monitor = fore200e->cp_monitor;
- unsigned long timeout = jiffies + MSECS(50);
+ unsigned long timeout = jiffies + msecs_to_jiffies(50);
int c;
while (time_before(jiffies, timeout)) {
@@ -2768,20 +2731,107 @@ fore200e_init(struct fore200e* fore200e)
return 0;
}
+
+static int __devinit
+fore200e_pca_detect(struct pci_dev *pci_dev, const struct pci_device_id *pci_ent)
+{
+ const struct fore200e_bus* bus = (struct fore200e_bus*) pci_ent->driver_data;
+ struct fore200e* fore200e;
+ int err = 0;
+ static int index = 0;
+
+ if (pci_enable_device(pci_dev)) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ fore200e = fore200e_kmalloc(sizeof(struct fore200e), GFP_KERNEL);
+ if (fore200e == NULL) {
+ err = -ENOMEM;
+ goto out_disable;
+ }
+
+ fore200e->bus = bus;
+ fore200e->bus_dev = pci_dev;
+ fore200e->irq = pci_dev->irq;
+ fore200e->phys_base = pci_resource_start(pci_dev, 0);
+
+ sprintf(fore200e->name, "%s-%d", bus->model_name, index - 1);
+
+ pci_set_master(pci_dev);
+
+ printk(FORE200E "device %s found at 0x%lx, IRQ %s\n",
+ fore200e->bus->model_name,
+ fore200e->phys_base, fore200e_irq_itoa(fore200e->irq));
+
+ sprintf(fore200e->name, "%s-%d", bus->model_name, index);
+
+ err = fore200e_init(fore200e);
+ if (err < 0) {
+ fore200e_shutdown(fore200e);
+ goto out_free;
+ }
+
+ ++index;
+ pci_set_drvdata(pci_dev, fore200e);
+
+out:
+ return err;
+
+out_free:
+ kfree(fore200e);
+out_disable:
+ pci_disable_device(pci_dev);
+ goto out;
+}
+
+
+static void __devexit fore200e_pca_remove_one(struct pci_dev *pci_dev)
+{
+ struct fore200e *fore200e;
+
+ fore200e = pci_get_drvdata(pci_dev);
+
+ list_del(&fore200e->entry);
+
+ fore200e_shutdown(fore200e);
+ kfree(fore200e);
+ pci_disable_device(pci_dev);
+}
+
+
+#ifdef CONFIG_ATM_FORE200E_PCA
+static struct pci_device_id fore200e_pca_tbl[] = {
+ { PCI_VENDOR_ID_FORE, PCI_DEVICE_ID_FORE_PCA200E, PCI_ANY_ID, PCI_ANY_ID,
+ 0, 0, (unsigned long) &fore200e_bus[0] },
+ { 0, }
+};
+
+MODULE_DEVICE_TABLE(pci, fore200e_pca_tbl);
+
+static struct pci_driver fore200e_pca_driver = {
+ .name = "fore_200e",
+ .probe = fore200e_pca_detect,
+ .remove = __devexit_p(fore200e_pca_remove_one),
+ .id_table = fore200e_pca_tbl,
+};
+#endif
+
+
static int __init
fore200e_module_init(void)
{
const struct fore200e_bus* bus;
struct fore200e* fore200e;
- int index, link;
+ int index;
printk(FORE200E "FORE Systems 200E-series ATM driver - version " FORE200E_VERSION "\n");
/* for each configured bus interface */
- for (link = 0, bus = fore200e_bus; bus->model_name; bus++) {
+ for (bus = fore200e_bus; bus->model_name; bus++) {
/* detect all boards present on that bus */
- for (index = 0; (fore200e = bus->detect(bus, index)); index++) {
+ for (index = 0; bus->detect && (fore200e = bus->detect(bus, index)); index++) {
printk(FORE200E "device %s found at 0x%lx, IRQ %s\n",
fore200e->bus->model_name,
@@ -2795,15 +2845,18 @@ fore200e_module_init(void)
break;
}
- link++;
-
- fore200e->next = fore200e_boards;
- fore200e_boards = fore200e;
+ list_add(&fore200e->entry, &fore200e_boards);
}
}
- if (link)
- return 0;
+#ifdef CONFIG_ATM_FORE200E_PCA
+ if (!pci_module_init(&fore200e_pca_driver))
+ return 0;
+#endif
+
+ if (!list_empty(&fore200e_boards))
+ return 0;
+
return -ENODEV;
}
@@ -2811,11 +2864,14 @@ fore200e_module_init(void)
static void __exit
fore200e_module_cleanup(void)
{
- while (fore200e_boards) {
- struct fore200e* fore200e = fore200e_boards;
+ struct fore200e *fore200e, *next;
+#ifdef CONFIG_ATM_FORE200E_PCA
+ pci_unregister_driver(&fore200e_pca_driver);
+#endif
+
+ list_for_each_entry_safe(fore200e, next, &fore200e_boards, entry) {
fore200e_shutdown(fore200e);
- fore200e_boards = fore200e->next;
kfree(fore200e);
}
DPRINTK(1, "module being removed\n");
@@ -3150,7 +3206,7 @@ static const struct fore200e_bus fore200e_bus[] = {
fore200e_pca_dma_sync_for_device,
fore200e_pca_dma_chunk_alloc,
fore200e_pca_dma_chunk_free,
- fore200e_pca_detect,
+ NULL,
fore200e_pca_configure,
fore200e_pca_map,
fore200e_pca_reset,
diff --git a/drivers/atm/fore200e.h b/drivers/atm/fore200e.h
index 492f7f549ebb2..2558eb8532354 100644
--- a/drivers/atm/fore200e.h
+++ b/drivers/atm/fore200e.h
@@ -841,7 +841,7 @@ typedef struct fore200e_vc_map {
/* per-device data */
typedef struct fore200e {
- struct fore200e* next; /* next device */
+ struct list_head entry; /* next device */
const struct fore200e_bus* bus; /* bus-dependent code and data */
union fore200e_regs regs; /* bus-dependent registers */
struct atm_dev* atm_dev; /* ATM device */
diff --git a/drivers/atm/he.c b/drivers/atm/he.c
index f20bfdf7309ee..c2c31a5f4513a 100644
--- a/drivers/atm/he.c
+++ b/drivers/atm/he.c
@@ -2610,7 +2610,7 @@ he_close(struct atm_vcc *vcc)
* TBRQ, the host issues the close command to the adapter.
*/
- while (((tx_inuse = atomic_read(&vcc->sk->sk_wmem_alloc)) > 0) &&
+ while (((tx_inuse = atomic_read(&sk_atm(vcc)->sk_wmem_alloc)) > 0) &&
(retry < MAX_RETRY)) {
msleep(sleep);
if (sleep < 250)
@@ -3079,7 +3079,7 @@ static struct pci_driver he_driver = {
static int __init he_init(void)
{
- return pci_module_init(&he_driver);
+ return pci_register_driver(&he_driver);
}
static void __exit he_cleanup(void)
diff --git a/drivers/atm/horizon.c b/drivers/atm/horizon.c
index 801d059667a8e..924a2c8988bd6 100644
--- a/drivers/atm/horizon.c
+++ b/drivers/atm/horizon.c
@@ -2938,7 +2938,7 @@ static int __init hrz_module_init (void) {
hrz_check_args();
// get the juice
- return pci_module_init(&hrz_driver);
+ return pci_register_driver(&hrz_driver);
}
/********** module exit **********/
diff --git a/drivers/atm/idt77252.c b/drivers/atm/idt77252.c
index 3d8764ab28257..baaf1a3d2242f 100644
--- a/drivers/atm/idt77252.c
+++ b/drivers/atm/idt77252.c
@@ -727,10 +727,11 @@ push_on_scq(struct idt77252_dev *card, struct vc_map *vc, struct sk_buff *skb)
spin_lock_irqsave(&vc->lock, flags);
if (vc->estimator) {
struct atm_vcc *vcc = vc->tx_vcc;
+ struct sock *sk = sk_atm(vcc);
vc->estimator->cells += (skb->len + 47) / 48;
- if (atomic_read(&vcc->sk->sk_wmem_alloc) >
- (vcc->sk->sk_sndbuf >> 1)) {
+ if (atomic_read(&sk->sk_wmem_alloc) >
+ (sk->sk_sndbuf >> 1)) {
u32 cps = vc->estimator->maxcps;
vc->estimator->cps = cps;
@@ -1325,7 +1326,7 @@ idt77252_rx_raw(struct idt77252_dev *card)
goto drop;
}
- if ((vcc->sk != NULL) && !atm_charge(vcc, sb->truesize)) {
+ if (!atm_charge(vcc, sb->truesize)) {
RXPRINTK("%s: atm_charge() dropped AAL0 packets.\n",
card->name);
dev_kfree_skb(sb);
@@ -2029,7 +2030,7 @@ idt77252_send_oam(struct atm_vcc *vcc, void *cell, int flags)
atomic_inc(&vcc->stats->tx_err);
return -ENOMEM;
}
- atomic_add(skb->truesize, &vcc->sk->sk_wmem_alloc);
+ atomic_add(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc);
memcpy(skb_put(skb, 52), cell, 52);
diff --git a/drivers/atm/iphase.c b/drivers/atm/iphase.c
index ce9202eed9349..a43575acb2c1d 100644
--- a/drivers/atm/iphase.c
+++ b/drivers/atm/iphase.c
@@ -1778,16 +1778,18 @@ static int open_tx(struct atm_vcc *vcc)
if (ia_vcc->pcr < iadev->rate_limit)
skb_queue_head_init (&ia_vcc->txing_skb);
if (ia_vcc->pcr < iadev->rate_limit) {
- if (vcc->qos.txtp.max_sdu != 0) {
+ struct sock *sk = sk_atm(vcc);
+
+ if (vcc->qos.txtp.max_sdu != 0) {
if (ia_vcc->pcr > 60000)
- vcc->sk->sk_sndbuf = vcc->qos.txtp.max_sdu * 5;
+ sk->sk_sndbuf = vcc->qos.txtp.max_sdu * 5;
else if (ia_vcc->pcr > 2000)
- vcc->sk->sk_sndbuf = vcc->qos.txtp.max_sdu * 4;
+ sk->sk_sndbuf = vcc->qos.txtp.max_sdu * 4;
else
- vcc->sk->sk_sndbuf = vcc->qos.txtp.max_sdu * 3;
+ sk->sk_sndbuf = vcc->qos.txtp.max_sdu * 3;
}
else
- vcc->sk->sk_sndbuf = 24576;
+ sk->sk_sndbuf = 24576;
}
vc = (struct main_vc *)iadev->MAIN_VC_TABLE_ADDR;
@@ -3244,8 +3246,8 @@ static void __devexit ia_remove_one(struct pci_dev *pdev)
iadev_count--;
ia_dev[iadev_count] = NULL;
_ia_dev[iadev_count] = NULL;
+ IF_EVENT(printk("deregistering iav at (itf:%d)\n", dev->number);)
atm_dev_deregister(dev);
- IF_EVENT(printk("iav deregistered at (itf:%d)\n", dev->number);)
iounmap(iadev->base);
pci_disable_device(pdev);
@@ -3274,7 +3276,7 @@ static int __init ia_module_init(void)
{
int ret;
- ret = pci_module_init(&ia_driver);
+ ret = pci_register_driver(&ia_driver);
if (ret >= 0) {
ia_timer.expires = jiffies + 3*HZ;
add_timer(&ia_timer);
diff --git a/drivers/atm/lanai.c b/drivers/atm/lanai.c
index c5c4a89bc3ef0..1aecc509ab5c5 100644
--- a/drivers/atm/lanai.c
+++ b/drivers/atm/lanai.c
@@ -61,6 +61,7 @@
#include <asm/byteorder.h>
#include <linux/spinlock.h>
#include <linux/pci.h>
+#include <linux/dma-mapping.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
@@ -566,7 +567,7 @@ static int __init sram_test_word(
return -EIO;
}
-static int __init sram_test_pass(const struct lanai_dev *lanai, u32 pattern)
+static int __devinit sram_test_pass(const struct lanai_dev *lanai, u32 pattern)
{
int offset, result = 0;
for (offset = 0; offset < SRAM_BYTES && result == 0; offset += 4)
@@ -574,7 +575,7 @@ static int __init sram_test_pass(const struct lanai_dev *lanai, u32 pattern)
return result;
}
-static int __init sram_test_and_clear(const struct lanai_dev *lanai)
+static int __devinit sram_test_and_clear(const struct lanai_dev *lanai)
{
#ifdef FULL_MEMORY_TEST
int result;
@@ -650,7 +651,7 @@ static inline u32 cardvcc_read(const struct lanai_vcc *lvcc,
enum lanai_vcc_offset offset)
{
u32 val;
- APRINTK(lvcc->vbase != 0, "cardvcc_read: unbound vcc!\n");
+ APRINTK(lvcc->vbase != NULL, "cardvcc_read: unbound vcc!\n");
val= readl(lvcc->vbase + offset);
RWDEBUG("VR vci=%04d 0x%02X = 0x%08X\n",
lvcc->vci, (int) offset, val);
@@ -660,7 +661,7 @@ static inline u32 cardvcc_read(const struct lanai_vcc *lvcc,
static inline void cardvcc_write(const struct lanai_vcc *lvcc,
u32 val, enum lanai_vcc_offset offset)
{
- APRINTK(lvcc->vbase != 0, "cardvcc_write: unbound vcc!\n");
+ APRINTK(lvcc->vbase != NULL, "cardvcc_write: unbound vcc!\n");
APRINTK((val & ~0xFFFF) == 0,
"cardvcc_write: bad val 0x%X (vci=%d, addr=0x%02X)\n",
(unsigned int) val, lvcc->vci, (unsigned int) offset);
@@ -748,7 +749,7 @@ static void host_vcc_start_tx(const struct lanai_vcc *lvcc)
/* Shutdown receiving on card */
static void lanai_shutdown_rx_vci(const struct lanai_vcc *lvcc)
{
- if (lvcc->vbase == 0) /* We were never bound to a VCI */
+ if (lvcc->vbase == NULL) /* We were never bound to a VCI */
return;
/* 15.1.1 - set to trashing, wait one cell time (15us) */
cardvcc_write(lvcc,
@@ -779,7 +780,7 @@ static void lanai_shutdown_tx_vci(struct lanai_dev *lanai,
int read, write, lastread = -1;
APRINTK(!in_interrupt(),
"lanai_shutdown_tx_vci called w/o process context!\n");
- if (lvcc->vbase == 0) /* We were never bound to a VCI */
+ if (lvcc->vbase == NULL) /* We were never bound to a VCI */
return;
/* 15.2.1 - wait for queue to drain */
while ((skb = skb_dequeue(&lvcc->tx.backlog)) != NULL)
@@ -860,7 +861,7 @@ static inline void aal0_buffer_free(struct lanai_dev *lanai)
#ifndef READ_EEPROM
/* Stub functions to use if EEPROM reading is disabled */
-static int __init eeprom_read(struct lanai_dev *lanai)
+static int __devinit eeprom_read(struct lanai_dev *lanai)
{
printk(KERN_INFO DEV_LABEL "(itf %d): *NOT* reading EEPROM\n",
lanai->number);
@@ -868,7 +869,7 @@ static int __init eeprom_read(struct lanai_dev *lanai)
return 0;
}
-static int __init eeprom_validate(struct lanai_dev *lanai)
+static int __devinit eeprom_validate(struct lanai_dev *lanai)
{
lanai->serialno = 0;
lanai->magicno = EEPROM_MAGIC_VALUE;
@@ -877,7 +878,7 @@ static int __init eeprom_validate(struct lanai_dev *lanai)
#else /* READ_EEPROM */
-static int __init eeprom_read(struct lanai_dev *lanai)
+static int __devinit eeprom_read(struct lanai_dev *lanai)
{
int i, address;
u8 data;
@@ -953,7 +954,7 @@ static inline u32 eeprom_be4(const struct lanai_dev *lanai, int address)
}
/* Checksum/validate EEPROM contents */
-static int __init eeprom_validate(struct lanai_dev *lanai)
+static int __devinit eeprom_validate(struct lanai_dev *lanai)
{
int i, s;
u32 v;
@@ -1449,7 +1450,7 @@ static void vcc_rx_aal0(struct lanai_dev *lanai)
#include <linux/vmalloc.h>
#endif
-static int __init vcc_table_allocate(struct lanai_dev *lanai)
+static int __devinit vcc_table_allocate(struct lanai_dev *lanai)
{
#ifdef VCCTABLE_GETFREEPAGE
APRINTK((lanai->num_vci) * sizeof(struct lanai_vcc *) <= PAGE_SIZE,
@@ -1544,7 +1545,7 @@ static int lanai_setup_tx_vci(struct lanai_dev *lanai, struct lanai_vcc *lvcc,
static inline void host_vcc_bind(struct lanai_dev *lanai,
struct lanai_vcc *lvcc, vci_t vci)
{
- if (lvcc->vbase != 0)
+ if (lvcc->vbase != NULL)
return; /* We already were bound in the other direction */
DPRINTK("Binding vci %d\n", vci);
#ifdef USE_POWERDOWN
@@ -1562,7 +1563,7 @@ static inline void host_vcc_bind(struct lanai_dev *lanai,
static inline void host_vcc_unbind(struct lanai_dev *lanai,
struct lanai_vcc *lvcc)
{
- if (lvcc->vbase == 0)
+ if (lvcc->vbase == NULL)
return; /* This vcc was never bound */
DPRINTK("Unbinding vci %d\n", lvcc->vci);
lvcc->vbase = NULL;
@@ -1596,7 +1597,7 @@ static void lanai_reset(struct lanai_dev *lanai)
/*
* Allocate service buffer and tell card about it
*/
-static int __init service_buffer_allocate(struct lanai_dev *lanai)
+static int __devinit service_buffer_allocate(struct lanai_dev *lanai)
{
lanai_buf_allocate(&lanai->service, SERVICE_ENTRIES * 4, 8,
lanai->pci);
@@ -1952,7 +1953,7 @@ static int check_board_id_and_rev(const char *name, u32 val, int *revp)
/* -------------------- PCI INITIALIZATION/SHUTDOWN: */
-static int __init lanai_pci_start(struct lanai_dev *lanai)
+static int __devinit lanai_pci_start(struct lanai_dev *lanai)
{
struct pci_dev *pci = lanai->pci;
int result;
@@ -1964,7 +1965,7 @@ static int __init lanai_pci_start(struct lanai_dev *lanai)
return -ENXIO;
}
pci_set_master(pci);
- if (pci_set_dma_mask(pci, 0xFFFFFFFF) != 0) {
+ if (pci_set_dma_mask(pci, DMA_32BIT_MASK) != 0) {
printk(KERN_WARNING DEV_LABEL
"(itf %d): No suitable DMA available.\n", lanai->number);
return -EBUSY;
@@ -2148,7 +2149,7 @@ static inline void lanai_cbr_shutdown(struct lanai_dev *lanai)
/* -------------------- OPERATIONS: */
/* setup a newly detected device */
-static int __init lanai_dev_open(struct atm_dev *atmdev)
+static int __devinit lanai_dev_open(struct atm_dev *atmdev)
{
struct lanai_dev *lanai = (struct lanai_dev *) atmdev->dev_data;
unsigned long raw_base;
@@ -2179,7 +2180,7 @@ static int __init lanai_dev_open(struct atm_dev *atmdev)
goto error;
raw_base = lanai->pci->resource[0].start;
lanai->base = (bus_addr_t) ioremap(raw_base, LANAI_MAPPING_SIZE);
- if (lanai->base == 0) {
+ if (lanai->base == NULL) {
printk(KERN_ERR DEV_LABEL ": couldn't remap I/O space\n");
goto error_pci;
}
@@ -2333,7 +2334,7 @@ static void lanai_close(struct atm_vcc *atmvcc)
}
if (lvcc->tx.atmvcc == atmvcc) {
if (atmvcc == lanai->cbrvcc) {
- if (lvcc->vbase != 0)
+ if (lvcc->vbase != NULL)
lanai_cbr_shutdown(lanai);
lanai->cbrvcc = NULL;
}
@@ -2524,7 +2525,7 @@ static int lanai_send(struct atm_vcc *atmvcc, struct sk_buff *skb)
struct lanai_vcc *lvcc = (struct lanai_vcc *) atmvcc->dev_data;
struct lanai_dev *lanai = (struct lanai_dev *) atmvcc->dev->dev_data;
unsigned long flags;
- if (unlikely(lvcc == NULL || lvcc->vbase == 0 ||
+ if (unlikely(lvcc == NULL || lvcc->vbase == NULL ||
lvcc->tx.atmvcc != atmvcc))
goto einval;
#ifdef DEBUG
@@ -2746,7 +2747,7 @@ static int __init lanai_module_init(void)
{
int x;
- x = pci_module_init(&lanai_driver);
+ x = pci_register_driver(&lanai_driver);
if (x != 0)
printk(KERN_ERR DEV_LABEL ": no adapter found\n");
return x;
diff --git a/drivers/atm/nicstar.c b/drivers/atm/nicstar.c
index d99aede28a51a..85bf5c8442b00 100644
--- a/drivers/atm/nicstar.c
+++ b/drivers/atm/nicstar.c
@@ -350,7 +350,7 @@ static void __devexit nicstar_remove_one(struct pci_dev *pcidev)
kfree(card->rsq.org);
kfree(card->tsq.org);
free_irq(card->pcidev->irq, card);
- iounmap((void *) card->membase);
+ iounmap(card->membase);
kfree(card);
}
@@ -381,7 +381,7 @@ static int __init nicstar_init(void)
XPRINTK("nicstar: nicstar_init() called.\n");
- error = pci_module_init(&nicstar_driver);
+ error = pci_register_driver(&nicstar_driver);
TXPRINTK("nicstar: TX debug enabled.\n");
RXPRINTK("nicstar: RX debug enabled.\n");
@@ -976,7 +976,7 @@ static void __devinit ns_init_card_error(ns_dev *card, int error)
}
if (error >= 4)
{
- iounmap((void *) card->membase);
+ iounmap(card->membase);
}
if (error >= 3)
{
diff --git a/drivers/atm/nicstar.h b/drivers/atm/nicstar.h
index a7eaee736ef8d..ea83c46c8ba58 100644
--- a/drivers/atm/nicstar.h
+++ b/drivers/atm/nicstar.h
@@ -739,8 +739,8 @@ typedef struct skb_pool
typedef struct vc_map
{
- volatile int tx:1; /* TX vc? */
- volatile int rx:1; /* RX vc? */
+ volatile unsigned int tx:1; /* TX vc? */
+ volatile unsigned int rx:1; /* RX vc? */
struct atm_vcc *tx_vcc, *rx_vcc;
struct sk_buff *rx_iov; /* RX iovector skb */
scq_info *scq; /* To keep track of the SCQ */
diff --git a/drivers/atm/zatm.c b/drivers/atm/zatm.c
index 2d26075eafde6..47a800519ad01 100644
--- a/drivers/atm/zatm.c
+++ b/drivers/atm/zatm.c
@@ -411,7 +411,7 @@ printk("[-3..0] 0x%08lx 0x%08lx 0x%08lx 0x%08lx\n",((unsigned *) skb->data)[-3],
#if 0
printk("dummy: 0x%08lx, 0x%08lx\n",dummy[0],dummy[1]);
#endif
- size = error ? 0 : ntohs(((u16 *) skb->data)[cells*
+ size = error ? 0 : ntohs(((__be16 *) skb->data)[cells*
ATM_CELL_PAYLOAD/sizeof(u16)-3]);
EVENT("got skb 0x%lx, size %d\n",(unsigned long) skb,size);
chan = (here[3] & uPD98401_AAL5_CHAN) >>
@@ -1090,7 +1090,7 @@ static irqreturn_t zatm_int(int irq,void *dev_id,struct pt_regs *regs)
/*----------------------------- (E)EPROM access -----------------------------*/
-static void __init eprom_set(struct zatm_dev *zatm_dev,unsigned long value,
+static void __devinit eprom_set(struct zatm_dev *zatm_dev,unsigned long value,
unsigned short cmd)
{
int error;
@@ -1101,7 +1101,7 @@ static void __init eprom_set(struct zatm_dev *zatm_dev,unsigned long value,
}
-static unsigned long __init eprom_get(struct zatm_dev *zatm_dev,
+static unsigned long __devinit eprom_get(struct zatm_dev *zatm_dev,
unsigned short cmd)
{
unsigned int value;
@@ -1114,7 +1114,7 @@ static unsigned long __init eprom_get(struct zatm_dev *zatm_dev,
}
-static void __init eprom_put_bits(struct zatm_dev *zatm_dev,
+static void __devinit eprom_put_bits(struct zatm_dev *zatm_dev,
unsigned long data,int bits,unsigned short cmd)
{
unsigned long value;
@@ -1129,7 +1129,7 @@ static void __init eprom_put_bits(struct zatm_dev *zatm_dev,
}
-static void __init eprom_get_byte(struct zatm_dev *zatm_dev,
+static void __devinit eprom_get_byte(struct zatm_dev *zatm_dev,
unsigned char *byte,unsigned short cmd)
{
int i;
@@ -1145,7 +1145,7 @@ static void __init eprom_get_byte(struct zatm_dev *zatm_dev,
}
-static unsigned char __init eprom_try_esi(struct atm_dev *dev,
+static unsigned char __devinit eprom_try_esi(struct atm_dev *dev,
unsigned short cmd,int offset,int swap)
{
unsigned char buf[ZEPROM_SIZE];
@@ -1166,7 +1166,7 @@ static unsigned char __init eprom_try_esi(struct atm_dev *dev,
}
-static void __init eprom_get_esi(struct atm_dev *dev)
+static void __devinit eprom_get_esi(struct atm_dev *dev)
{
if (eprom_try_esi(dev,ZEPROM_V1_REG,ZEPROM_V1_ESI_OFF,1)) return;
(void) eprom_try_esi(dev,ZEPROM_V2_REG,ZEPROM_V2_ESI_OFF,0);
@@ -1639,7 +1639,7 @@ static struct pci_driver zatm_driver = {
static int __init zatm_init_module(void)
{
- return pci_module_init(&zatm_driver);
+ return pci_register_driver(&zatm_driver);
}
module_init(zatm_init_module);
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index 3da24059bdf1f..f4fa27315fb4b 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -65,7 +65,7 @@ static struct sysfs_ops driver_sysfs_ops = {
static void driver_release(struct kobject * kobj)
{
struct device_driver * drv = to_driver(kobj);
- up(&drv->unload_sem);
+ complete(&drv->unloaded);
}
static struct kobj_type ktype_driver = {
@@ -465,6 +465,7 @@ int bus_add_device(struct device * dev)
up_write(&dev->bus->subsys.rwsem);
device_add_attrs(bus, dev);
sysfs_create_link(&bus->devices.kobj, &dev->kobj, dev->bus_id);
+ sysfs_create_link(&dev->kobj, &dev->bus->subsys.kset.kobj, "bus");
}
return error;
}
@@ -481,6 +482,7 @@ int bus_add_device(struct device * dev)
void bus_remove_device(struct device * dev)
{
if (dev->bus) {
+ sysfs_remove_link(&dev->kobj, "bus");
sysfs_remove_link(&dev->bus->devices.kobj, dev->bus_id);
device_remove_attrs(dev->bus, dev);
down_write(&dev->bus->subsys.rwsem);
diff --git a/drivers/base/class.c b/drivers/base/class.c
index e22fa1fdf74a6..6bf650fce78cf 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -15,6 +15,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/string.h>
+#include <linux/kdev_t.h>
#include "base.h"
#define to_class_attr(_attr) container_of(_attr, struct class_attribute, attr)
@@ -139,6 +140,7 @@ int class_register(struct class * cls)
INIT_LIST_HEAD(&cls->children);
INIT_LIST_HEAD(&cls->interfaces);
+ init_MUTEX(&cls->sem);
error = kobject_set_name(&cls->subsys.kset.kobj, "%s", cls->name);
if (error)
return error;
@@ -195,33 +197,6 @@ void class_device_remove_bin_file(struct class_device *class_dev,
sysfs_remove_bin_file(&class_dev->kobj, attr);
}
-static int class_device_dev_link(struct class_device * class_dev)
-{
- if (class_dev->dev)
- return sysfs_create_link(&class_dev->kobj,
- &class_dev->dev->kobj, "device");
- return 0;
-}
-
-static void class_device_dev_unlink(struct class_device * class_dev)
-{
- sysfs_remove_link(&class_dev->kobj, "device");
-}
-
-static int class_device_driver_link(struct class_device * class_dev)
-{
- if ((class_dev->dev) && (class_dev->dev->driver))
- return sysfs_create_link(&class_dev->kobj,
- &class_dev->dev->driver->kobj, "driver");
- return 0;
-}
-
-static void class_device_driver_unlink(struct class_device * class_dev)
-{
- sysfs_remove_link(&class_dev->kobj, "driver");
-}
-
-
static ssize_t
class_device_attr_show(struct kobject * kobj, struct attribute * attr,
char * buf)
@@ -298,9 +273,9 @@ static int class_hotplug(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);
- int retval = 0;
int i = 0;
int length = 0;
+ int retval = 0;
pr_debug("%s - name = %s\n", __FUNCTION__, class_dev->class_id);
@@ -313,26 +288,34 @@ static int class_hotplug(struct kset *kset, struct kobject *kobj, char **envp,
&length, "PHYSDEVPATH=%s", path);
kfree(path);
- /* 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 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);
+ }
+
+ if (MAJOR(class_dev->devt)) {
+ add_hotplug_env_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "MAJOR=%u", MAJOR(class_dev->devt));
- /* terminate, set to next free slot, shrink available space */
- envp[i] = NULL;
- envp = &envp[i];
- num_envp -= i;
- buffer = &buffer[length];
- buffer_size -= length;
+ add_hotplug_env_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "MINOR=%u", MINOR(class_dev->devt));
}
+ /* terminate, set to next free slot, shrink available space */
+ envp[i] = NULL;
+ envp = &envp[i];
+ num_envp -= i;
+ buffer = &buffer[length];
+ buffer_size -= length;
+
if (class_dev->class->hotplug) {
/* have the bus specific function add its stuff */
retval = class_dev->class->hotplug (class_dev, envp, num_envp,
@@ -388,6 +371,12 @@ static void class_device_remove_attrs(struct class_device * cd)
}
}
+static ssize_t show_dev(struct class_device *class_dev, char *buf)
+{
+ return print_dev_t(buf, class_dev->devt);
+}
+static CLASS_DEVICE_ATTR(dev, S_IRUGO, show_dev, NULL);
+
void class_device_initialize(struct class_device *class_dev)
{
kobj_set_kset_s(class_dev, class_obj_subsys);
@@ -425,16 +414,21 @@ int class_device_add(struct class_device *class_dev)
/* now take care of our own registration */
if (parent) {
- down_write(&parent->subsys.rwsem);
+ down(&parent->sem);
list_add_tail(&class_dev->node, &parent->children);
list_for_each_entry(class_intf, &parent->interfaces, node)
if (class_intf->add)
class_intf->add(class_dev);
- up_write(&parent->subsys.rwsem);
+ up(&parent->sem);
}
+
+ if (MAJOR(class_dev->devt))
+ class_device_create_file(class_dev, &class_device_attr_dev);
+
class_device_add_attrs(class_dev);
- class_device_dev_link(class_dev);
- class_device_driver_link(class_dev);
+ if (class_dev->dev)
+ sysfs_create_link(&class_dev->kobj,
+ &class_dev->dev->kobj, "device");
register_done:
if (error && parent)
@@ -455,16 +449,16 @@ void class_device_del(struct class_device *class_dev)
struct class_interface * class_intf;
if (parent) {
- down_write(&parent->subsys.rwsem);
+ down(&parent->sem);
list_del_init(&class_dev->node);
list_for_each_entry(class_intf, &parent->interfaces, node)
if (class_intf->remove)
class_intf->remove(class_dev);
- up_write(&parent->subsys.rwsem);
+ up(&parent->sem);
}
- class_device_dev_unlink(class_dev);
- class_device_driver_unlink(class_dev);
+ if (class_dev->dev)
+ sysfs_remove_link(&class_dev->kobj, "device");
class_device_remove_attrs(class_dev);
kobject_del(&class_dev->kobj);
@@ -516,8 +510,8 @@ void class_device_put(struct class_device *class_dev)
int class_interface_register(struct class_interface *class_intf)
{
- struct class * parent;
- struct class_device * class_dev;
+ struct class *parent;
+ struct class_device *class_dev;
if (!class_intf || !class_intf->class)
return -ENODEV;
@@ -526,14 +520,13 @@ int class_interface_register(struct class_interface *class_intf)
if (!parent)
return -EINVAL;
- down_write(&parent->subsys.rwsem);
+ down(&parent->sem);
list_add_tail(&class_intf->node, &parent->interfaces);
-
if (class_intf->add) {
list_for_each_entry(class_dev, &parent->children, node)
class_intf->add(class_dev);
}
- up_write(&parent->subsys.rwsem);
+ up(&parent->sem);
return 0;
}
@@ -546,14 +539,13 @@ void class_interface_unregister(struct class_interface *class_intf)
if (!parent)
return;
- down_write(&parent->subsys.rwsem);
+ down(&parent->sem);
list_del_init(&class_intf->node);
-
if (class_intf->remove) {
list_for_each_entry(class_dev, &parent->children, node)
class_intf->remove(class_dev);
}
- up_write(&parent->subsys.rwsem);
+ up(&parent->sem);
class_put(parent);
}
diff --git a/drivers/base/class_simple.c b/drivers/base/class_simple.c
index 682e73bd3f498..27699eb20a372 100644
--- a/drivers/base/class_simple.c
+++ b/drivers/base/class_simple.c
@@ -10,18 +10,15 @@
#include <linux/config.h>
#include <linux/device.h>
-#include <linux/kdev_t.h>
#include <linux/err.h>
struct class_simple {
- struct class_device_attribute attr;
struct class class;
};
#define to_class_simple(d) container_of(d, struct class_simple, 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)
@@ -35,12 +32,6 @@ static void release_simple_dev(struct class_device *class_dev)
kfree(s_dev);
}
-static ssize_t show_dev(struct class_device *class_dev, char *buf)
-{
- struct simple_dev *s_dev = to_simple_dev(class_dev);
- return print_dev_t(buf, s_dev->dev);
-}
-
static void class_simple_release(struct class *class)
{
struct class_simple *cs = to_class_simple(class);
@@ -75,12 +66,6 @@ struct class_simple *class_simple_create(struct module *owner, char *name)
cs->class.class_release = class_simple_release;
cs->class.release = release_simple_dev;
- cs->attr.attr.name = "dev";
- cs->attr.attr.mode = S_IRUGO;
- cs->attr.attr.owner = owner;
- cs->attr.show = show_dev;
- cs->attr.store = NULL;
-
retval = class_register(&cs->class);
if (retval)
goto error;
@@ -143,7 +128,7 @@ struct class_device *class_simple_device_add(struct class_simple *cs, dev_t dev,
}
memset(s_dev, 0x00, sizeof(*s_dev));
- s_dev->dev = dev;
+ s_dev->class_dev.devt = dev;
s_dev->class_dev.dev = device;
s_dev->class_dev.class = &cs->class;
@@ -154,8 +139,6 @@ struct class_device *class_simple_device_add(struct class_simple *cs, dev_t dev,
if (retval)
goto error;
- class_device_create_file(&s_dev->class_dev, &cs->attr);
-
spin_lock(&simple_dev_list_lock);
list_add(&s_dev->node, &simple_dev_list);
spin_unlock(&simple_dev_list_lock);
@@ -200,7 +183,7 @@ void class_simple_device_remove(dev_t dev)
spin_lock(&simple_dev_list_lock);
list_for_each_entry(s_dev, &simple_dev_list, node) {
- if (s_dev->dev == dev) {
+ if (s_dev->class_dev.devt == dev) {
found = 1;
break;
}
diff --git a/drivers/base/dmapool.c b/drivers/base/dmapool.c
index 55cdd46f5e50b..f48833df61a29 100644
--- a/drivers/base/dmapool.c
+++ b/drivers/base/dmapool.c
@@ -156,7 +156,7 @@ dma_pool_create (const char *name, struct device *dev,
static struct dma_page *
-pool_alloc_page (struct dma_pool *pool, int mem_flags)
+pool_alloc_page (struct dma_pool *pool, unsigned int __nocast mem_flags)
{
struct dma_page *page;
int mapsize;
diff --git a/drivers/base/driver.c b/drivers/base/driver.c
index 9556f912f960f..3b269f7e52135 100644
--- a/drivers/base/driver.c
+++ b/drivers/base/driver.c
@@ -79,14 +79,14 @@ void put_driver(struct device_driver * drv)
* since most of the things we have to do deal with the bus
* structures.
*
- * The one interesting aspect is that we initialize @drv->unload_sem
- * to a locked state here. It will be unlocked when the driver
- * reference count reaches 0.
+ * The one interesting aspect is that we setup @drv->unloaded
+ * as a completion that gets complete when the driver reference
+ * count reaches 0.
*/
int driver_register(struct device_driver * drv)
{
INIT_LIST_HEAD(&drv->devices);
- init_MUTEX_LOCKED(&drv->unload_sem);
+ init_completion(&drv->unloaded);
return bus_add_driver(drv);
}
@@ -97,7 +97,7 @@ int driver_register(struct device_driver * drv)
*
* Again, we pass off most of the work to the bus-level call.
*
- * Though, once that is done, we attempt to take @drv->unload_sem.
+ * Though, once that is done, we wait until @drv->unloaded is completed.
* This will block until the driver refcount reaches 0, and it is
* released. Only modular drivers will call this function, and we
* have to guarantee that it won't complete, letting the driver
@@ -107,8 +107,7 @@ int driver_register(struct device_driver * drv)
void driver_unregister(struct device_driver * drv)
{
bus_remove_driver(drv);
- down(&drv->unload_sem);
- up(&drv->unload_sem);
+ wait_for_completion(&drv->unloaded);
}
/**
diff --git a/drivers/base/map.c b/drivers/base/map.c
index aab93fc2a31bb..2f455d86793c8 100644
--- a/drivers/base/map.c
+++ b/drivers/base/map.c
@@ -25,7 +25,7 @@ struct kobj_map {
int (*lock)(dev_t, void *);
void *data;
} *probes[255];
- struct rw_semaphore *sem;
+ struct semaphore *sem;
};
int kobj_map(struct kobj_map *domain, dev_t dev, unsigned long range,
@@ -53,7 +53,7 @@ int kobj_map(struct kobj_map *domain, dev_t dev, unsigned long range,
p->range = range;
p->data = data;
}
- down_write(domain->sem);
+ down(domain->sem);
for (i = 0, p -= n; i < n; i++, p++, index++) {
struct probe **s = &domain->probes[index % 255];
while (*s && (*s)->range < range)
@@ -61,7 +61,7 @@ int kobj_map(struct kobj_map *domain, dev_t dev, unsigned long range,
p->next = *s;
*s = p;
}
- up_write(domain->sem);
+ up(domain->sem);
return 0;
}
@@ -75,7 +75,7 @@ void kobj_unmap(struct kobj_map *domain, dev_t dev, unsigned long range)
if (n > 255)
n = 255;
- down_write(domain->sem);
+ down(domain->sem);
for (i = 0; i < n; i++, index++) {
struct probe **s;
for (s = &domain->probes[index % 255]; *s; s = &(*s)->next) {
@@ -88,7 +88,7 @@ void kobj_unmap(struct kobj_map *domain, dev_t dev, unsigned long range)
}
}
}
- up_write(domain->sem);
+ up(domain->sem);
kfree(found);
}
@@ -99,7 +99,7 @@ struct kobject *kobj_lookup(struct kobj_map *domain, dev_t dev, int *index)
unsigned long best = ~0UL;
retry:
- down_read(domain->sem);
+ down(domain->sem);
for (p = domain->probes[MAJOR(dev) % 255]; p; p = p->next) {
struct kobject *(*probe)(dev_t, int *, void *);
struct module *owner;
@@ -120,7 +120,7 @@ retry:
module_put(owner);
continue;
}
- up_read(domain->sem);
+ up(domain->sem);
kobj = probe(dev, index, data);
/* Currently ->owner protects _only_ ->probe() itself. */
module_put(owner);
@@ -128,12 +128,11 @@ retry:
return kobj;
goto retry;
}
- up_read(domain->sem);
+ up(domain->sem);
return NULL;
}
-struct kobj_map *kobj_map_init(kobj_probe_t *base_probe,
- struct subsystem *s)
+struct kobj_map *kobj_map_init(kobj_probe_t *base_probe, struct semaphore *sem)
{
struct kobj_map *p = kmalloc(sizeof(struct kobj_map), GFP_KERNEL);
struct probe *base = kmalloc(sizeof(struct probe), GFP_KERNEL);
@@ -151,6 +150,6 @@ struct kobj_map *kobj_map_init(kobj_probe_t *base_probe,
base->get = base_probe;
for (i = 0; i < 255; i++)
p->probes[i] = base;
- p->sem = &s->rwsem;
+ p->sem = sem;
return p;
}
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index c8c87cebcbc12..996cbb4d50878 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -131,7 +131,7 @@ int platform_device_register(struct platform_device * pdev)
pdev->dev.bus = &platform_bus_type;
if (pdev->id != -1)
- snprintf(pdev->dev.bus_id, BUS_ID_SIZE, "%s%u", pdev->name, pdev->id);
+ snprintf(pdev->dev.bus_id, BUS_ID_SIZE, "%s.%u", pdev->name, pdev->id);
else
strlcpy(pdev->dev.bus_id, pdev->name, BUS_ID_SIZE);
diff --git a/drivers/base/power/suspend.c b/drivers/base/power/suspend.c
index 8e1ace2d817e2..a0b5cf689e639 100644
--- a/drivers/base/power/suspend.c
+++ b/drivers/base/power/suspend.c
@@ -134,6 +134,8 @@ int device_power_down(pm_message_t state)
Done:
return error;
Error:
+ printk(KERN_ERR "Could not power down device %s: "
+ "error %d\n", kobject_name(&dev->kobj), error);
dpm_power_up();
goto Done;
}
diff --git a/drivers/base/sys.c b/drivers/base/sys.c
index c3a99df3c883d..cff5a6a2c7841 100644
--- a/drivers/base/sys.c
+++ b/drivers/base/sys.c
@@ -79,7 +79,7 @@ EXPORT_SYMBOL_GPL(sysdev_remove_file);
/*
* declare system_subsys
*/
-decl_subsys(system, &ktype_sysdev, NULL);
+static decl_subsys(system, &ktype_sysdev, NULL);
int sysdev_class_register(struct sysdev_class * cls)
{
@@ -102,7 +102,8 @@ EXPORT_SYMBOL_GPL(sysdev_class_register);
EXPORT_SYMBOL_GPL(sysdev_class_unregister);
-static LIST_HEAD(global_drivers);
+static LIST_HEAD(sysdev_drivers);
+static DECLARE_MUTEX(sysdev_drivers_lock);
/**
* sysdev_driver_register - Register auxillary driver
@@ -112,14 +113,14 @@ static LIST_HEAD(global_drivers);
* If @cls is valid, then @drv is inserted into @cls->drivers to be
* called on each operation on devices of that class. The refcount
* of @cls is incremented.
- * Otherwise, @drv is inserted into global_drivers, and called for
+ * Otherwise, @drv is inserted into sysdev_drivers, and called for
* each device.
*/
int sysdev_driver_register(struct sysdev_class * cls,
struct sysdev_driver * drv)
{
- down_write(&system_subsys.rwsem);
+ down(&sysdev_drivers_lock);
if (cls && kset_get(&cls->kset)) {
list_add_tail(&drv->entry, &cls->drivers);
@@ -130,8 +131,8 @@ int sysdev_driver_register(struct sysdev_class * cls,
drv->add(dev);
}
} else
- list_add_tail(&drv->entry, &global_drivers);
- up_write(&system_subsys.rwsem);
+ list_add_tail(&drv->entry, &sysdev_drivers);
+ up(&sysdev_drivers_lock);
return 0;
}
@@ -144,7 +145,7 @@ int sysdev_driver_register(struct sysdev_class * cls,
void sysdev_driver_unregister(struct sysdev_class * cls,
struct sysdev_driver * drv)
{
- down_write(&system_subsys.rwsem);
+ down(&sysdev_drivers_lock);
list_del_init(&drv->entry);
if (cls) {
if (drv->remove) {
@@ -154,7 +155,7 @@ void sysdev_driver_unregister(struct sysdev_class * cls,
}
kset_put(&cls->kset);
}
- up_write(&system_subsys.rwsem);
+ up(&sysdev_drivers_lock);
}
EXPORT_SYMBOL_GPL(sysdev_driver_register);
@@ -193,13 +194,13 @@ int sysdev_register(struct sys_device * sysdev)
if (!error) {
struct sysdev_driver * drv;
- down_write(&system_subsys.rwsem);
+ down(&sysdev_drivers_lock);
/* Generic notification is implicit, because it's that
* code that should have called us.
*/
/* Notify global drivers */
- list_for_each_entry(drv, &global_drivers, entry) {
+ list_for_each_entry(drv, &sysdev_drivers, entry) {
if (drv->add)
drv->add(sysdev);
}
@@ -209,7 +210,7 @@ int sysdev_register(struct sys_device * sysdev)
if (drv->add)
drv->add(sysdev);
}
- up_write(&system_subsys.rwsem);
+ up(&sysdev_drivers_lock);
}
return error;
}
@@ -218,8 +219,8 @@ void sysdev_unregister(struct sys_device * sysdev)
{
struct sysdev_driver * drv;
- down_write(&system_subsys.rwsem);
- list_for_each_entry(drv, &global_drivers, entry) {
+ down(&sysdev_drivers_lock);
+ list_for_each_entry(drv, &sysdev_drivers, entry) {
if (drv->remove)
drv->remove(sysdev);
}
@@ -228,7 +229,7 @@ void sysdev_unregister(struct sys_device * sysdev)
if (drv->remove)
drv->remove(sysdev);
}
- up_write(&system_subsys.rwsem);
+ up(&sysdev_drivers_lock);
kobject_unregister(&sysdev->kobj);
}
@@ -255,7 +256,7 @@ void sysdev_shutdown(void)
pr_debug("Shutting Down System Devices\n");
- down_write(&system_subsys.rwsem);
+ down(&sysdev_drivers_lock);
list_for_each_entry_reverse(cls, &system_subsys.kset.list,
kset.kobj.entry) {
struct sys_device * sysdev;
@@ -268,7 +269,7 @@ void sysdev_shutdown(void)
pr_debug(" %s\n", kobject_name(&sysdev->kobj));
/* Call global drivers first. */
- list_for_each_entry(drv, &global_drivers, entry) {
+ list_for_each_entry(drv, &sysdev_drivers, entry) {
if (drv->shutdown)
drv->shutdown(sysdev);
}
@@ -284,7 +285,7 @@ void sysdev_shutdown(void)
cls->shutdown(sysdev);
}
}
- up_write(&system_subsys.rwsem);
+ up(&sysdev_drivers_lock);
}
@@ -319,7 +320,7 @@ int sysdev_suspend(u32 state)
pr_debug(" %s\n", kobject_name(&sysdev->kobj));
/* Call global drivers first. */
- list_for_each_entry(drv, &global_drivers, entry) {
+ list_for_each_entry(drv, &sysdev_drivers, entry) {
if (drv->suspend)
drv->suspend(sysdev, state);
}
@@ -375,7 +376,7 @@ int sysdev_resume(void)
}
/* Call global drivers. */
- list_for_each_entry(drv, &global_drivers, entry) {
+ list_for_each_entry(drv, &sysdev_drivers, entry) {
if (drv->resume)
drv->resume(sysdev);
}
diff --git a/drivers/base/transport_class.c b/drivers/base/transport_class.c
index 3bae11c64a855..6c2b447a33365 100644
--- a/drivers/base/transport_class.c
+++ b/drivers/base/transport_class.c
@@ -145,6 +145,20 @@ void transport_setup_device(struct device *dev)
}
EXPORT_SYMBOL_GPL(transport_setup_device);
+static int transport_add_class_device(struct attribute_container *cont,
+ struct device *dev,
+ struct class_device *classdev)
+{
+ int error = attribute_container_add_class_device(classdev);
+ struct transport_container *tcont =
+ attribute_container_to_transport_container(cont);
+
+ if (!error && tcont->statistics)
+ error = sysfs_create_group(&classdev->kobj, tcont->statistics);
+
+ return error;
+}
+
/**
* transport_add_device - declare a new dev for transport class association
@@ -159,8 +173,7 @@ EXPORT_SYMBOL_GPL(transport_setup_device);
void transport_add_device(struct device *dev)
{
- attribute_container_device_trigger(dev,
- attribute_container_add_class_device_adapter);
+ attribute_container_device_trigger(dev, transport_add_class_device);
}
EXPORT_SYMBOL_GPL(transport_add_device);
@@ -197,13 +210,18 @@ static int transport_remove_classdev(struct attribute_container *cont,
struct device *dev,
struct class_device *classdev)
{
+ struct transport_container *tcont =
+ attribute_container_to_transport_container(cont);
struct transport_class *tclass = class_to_transport_class(cont->class);
if (tclass->remove)
tclass->remove(dev);
- if (tclass->remove != anon_transport_dummy_function)
+ if (tclass->remove != anon_transport_dummy_function) {
+ if (tcont->statistics)
+ sysfs_remove_group(&classdev->kobj, tcont->statistics);
attribute_container_class_device_del(classdev);
+ }
return 0;
}
diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c
index 2c0946c49d5d9..423bbf2000d2f 100644
--- a/drivers/block/DAC960.c
+++ b/drivers/block/DAC960.c
@@ -2700,10 +2700,8 @@ DAC960_DetectController(struct pci_dev *PCI_Device,
Controller->PCIDevice = PCI_Device;
strcpy(Controller->FullModelName, "DAC960");
- if (pci_enable_device(PCI_Device)) {
- kfree(Controller);
+ if (pci_enable_device(PCI_Device))
goto Failure;
- }
switch (Controller->HardwareType)
{
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index 7f3574ecd26a8..e83a1e2e8b15c 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -6,7 +6,7 @@ menu "Block devices"
config BLK_DEV_FD
tristate "Normal floppy disk support"
- depends on (!ARCH_S390 && !M68K && !IA64 && !USERMODE) || Q40 || (SUN3X && BROKEN)
+ depends on (!ARCH_S390 && !M68K && !IA64 && !UML) || Q40 || (SUN3X && BROKEN)
---help---
If you want to use the floppy disk drive(s) of your PC under Linux,
say Y. Information about this driver, especially important for IBM
@@ -42,7 +42,7 @@ config MAC_FLOPPY
config BLK_DEV_PS2
tristate "PS/2 ESDI hard disk support"
- depends on MCA && MCA_LEGACY
+ depends on MCA && MCA_LEGACY && BROKEN
help
Say Y here if you have a PS/2 machine with a MCA bus and an ESDI
hard disk.
@@ -210,7 +210,7 @@ config BLK_DEV_UMEM
config BLK_DEV_UBD
bool "Virtual block device"
- depends on USERMODE
+ depends on UML
---help---
The User-Mode Linux port includes a driver called UBD which will let
you access arbitrary files on the host computer as block devices.
@@ -243,7 +243,7 @@ config BLK_DEV_COW_COMMON
config MMAPPER
tristate "Example IO memory driver (BROKEN)"
- depends on USERMODE && BROKEN
+ depends on UML && BROKEN
---help---
The User-Mode Linux port can provide support for IO Memory
emulation with this option. This allows a host file to be
@@ -455,7 +455,7 @@ config INITRAMFS_ROOT_GID
#for instance.
config LBD
bool "Support for Large Block Devices"
- depends on X86 || MIPS32 || PPC32 || ARCH_S390_31 || SUPERH || USERMODE
+ depends on X86 || MIPS32 || PPC32 || ARCH_S390_31 || SUPERH || UML
help
Say Y here if you want to attach large (bigger than 2TB) discs to
your machine, or if you want to have a raid or loopback device
@@ -463,7 +463,7 @@ config LBD
config CDROM_PKTCDVD
tristate "Packet writing on CD/DVD media"
- depends on !USERMODE
+ depends on !UML
help
If you have a CDROM drive that supports packet writing, say Y to
include preliminary support. It should work with any MMC/Mt Fuji
diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h
index 2f4eafa741935..db78f826d40c5 100644
--- a/drivers/block/aoe/aoe.h
+++ b/drivers/block/aoe/aoe.h
@@ -143,7 +143,6 @@ void aoedisk_rm_sysfs(struct aoedev *d);
int aoechr_init(void);
void aoechr_exit(void);
void aoechr_error(char *);
-void aoechr_hdump(char *, int len);
void aoecmd_work(struct aoedev *d);
void aoecmd_cfg(ushort, unsigned char);
diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c
index 7736a44fbd752..63561b280bc5e 100644
--- a/drivers/block/aoe/aoeblk.c
+++ b/drivers/block/aoe/aoeblk.c
@@ -28,7 +28,8 @@ static ssize_t aoedisk_show_mac(struct gendisk * disk, char *page)
{
struct aoedev *d = disk->private_data;
- return snprintf(page, PAGE_SIZE, "%012llx\n", mac_addr(d->addr));
+ return snprintf(page, PAGE_SIZE, "%012llx\n",
+ (unsigned long long)mac_addr(d->addr));
}
static ssize_t aoedisk_show_netif(struct gendisk * disk, char *page)
{
@@ -241,7 +242,8 @@ aoeblk_gdalloc(void *vp)
aoedisk_add_sysfs(d);
printk(KERN_INFO "aoe: %012llx e%lu.%lu v%04x has %llu "
- "sectors\n", mac_addr(d->addr), d->aoemajor, d->aoeminor,
+ "sectors\n", (unsigned long long)mac_addr(d->addr),
+ d->aoemajor, d->aoeminor,
d->fw_ver, (long long)d->ssize);
}
diff --git a/drivers/block/aoe/aoechr.c b/drivers/block/aoe/aoechr.c
index 8155a4ae747a6..14aeca3e2e8c5 100644
--- a/drivers/block/aoe/aoechr.c
+++ b/drivers/block/aoe/aoechr.c
@@ -99,41 +99,6 @@ bail: spin_unlock_irqrestore(&emsgs_lock, flags);
up(&emsgs_sema);
}
-#define PERLINE 16
-void
-aoechr_hdump(char *buf, int n)
-{
- int bufsiz;
- char *fbuf;
- int linelen;
- char *p, *e, *fp;
-
- bufsiz = n * 3; /* 2 hex digits and a space */
- bufsiz += n / PERLINE + 1; /* the newline characters */
- bufsiz += 1; /* the final '\0' */
-
- fbuf = kmalloc(bufsiz, GFP_ATOMIC);
- if (!fbuf) {
- printk(KERN_INFO
- "%s: cannot allocate memory\n",
- __FUNCTION__);
- return;
- }
-
- for (p = buf; n <= 0;) {
- linelen = n > PERLINE ? PERLINE : n;
- n -= linelen;
-
- fp = fbuf;
- for (e=p+linelen; p<e; p++)
- fp += sprintf(fp, "%2.2X ", *p & 255);
- sprintf(fp, "\n");
- aoechr_error(fbuf);
- }
-
- kfree(fbuf);
-}
-
static ssize_t
aoechr_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offp)
{
@@ -178,13 +143,13 @@ aoechr_rel(struct inode *inode, struct file *filp)
static ssize_t
aoechr_read(struct file *filp, char __user *buf, size_t cnt, loff_t *off)
{
- int n;
+ unsigned long n;
char *mp;
struct ErrMsg *em;
ssize_t len;
ulong flags;
- n = (int) filp->private_data;
+ n = (unsigned long) filp->private_data;
switch (n) {
case MINOR_ERR:
spin_lock_irqsave(&emsgs_lock, flags);
@@ -233,7 +198,7 @@ loop:
}
}
-struct file_operations aoe_fops = {
+static struct file_operations aoe_fops = {
.write = aoechr_write,
.read = aoechr_read,
.open = aoechr_open,
diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c
index 9ac1a58e78332..fb6d942a45656 100644
--- a/drivers/block/aoe/aoecmd.c
+++ b/drivers/block/aoe/aoecmd.c
@@ -416,7 +416,9 @@ aoecmd_ata_rsp(struct sk_buff *skb)
if (ahin->cmdstat & 0xa9) { /* these bits cleared on success */
printk(KERN_CRIT "aoe: aoecmd_ata_rsp: ata error cmd=%2.2Xh "
- "stat=%2.2Xh\n", ahout->cmdstat, ahin->cmdstat);
+ "stat=%2.2Xh from e%ld.%ld\n",
+ ahout->cmdstat, ahin->cmdstat,
+ d->aoemajor, d->aoeminor);
if (buf)
buf->flags |= BUFFL_FAIL;
} else {
@@ -458,8 +460,8 @@ aoecmd_ata_rsp(struct sk_buff *skb)
if (buf) {
buf->nframesout -= 1;
if (buf->nframesout == 0 && buf->resid == 0) {
- n = !(buf->flags & BUFFL_FAIL);
- bio_endio(buf->bio, buf->bio->bi_size, 0);
+ n = (buf->flags & BUFFL_FAIL) ? -EIO : 0;
+ bio_endio(buf->bio, buf->bio->bi_size, n);
mempool_free(buf, d->bufpool);
}
}
diff --git a/drivers/block/as-iosched.c b/drivers/block/as-iosched.c
index fb625b49b8319..a9575bb58a5e1 100644
--- a/drivers/block/as-iosched.c
+++ b/drivers/block/as-iosched.c
@@ -25,7 +25,7 @@
#define REQ_ASYNC 0
/*
- * See Documentation/as-iosched.txt
+ * See Documentation/block/as-iosched.txt
*/
/*
@@ -1463,35 +1463,36 @@ static void as_add_request(struct as_data *ad, struct as_rq *arq)
arq->state = AS_RQ_QUEUED;
}
-/*
- * requeue the request. The request has not been completed, nor is it a
- * new request, so don't touch accounting.
- */
-static void as_requeue_request(request_queue_t *q, struct request *rq)
+static void as_deactivate_request(request_queue_t *q, struct request *rq)
{
struct as_data *ad = q->elevator->elevator_data;
struct as_rq *arq = RQ_DATA(rq);
if (arq) {
- if (arq->state != AS_RQ_REMOVED) {
- printk("arq->state %d\n", arq->state);
- WARN_ON(1);
+ if (arq->state == AS_RQ_REMOVED) {
+ arq->state = AS_RQ_DISPATCHED;
+ if (arq->io_context && arq->io_context->aic)
+ atomic_inc(&arq->io_context->aic->nr_dispatched);
}
-
- arq->state = AS_RQ_DISPATCHED;
- if (arq->io_context && arq->io_context->aic)
- atomic_inc(&arq->io_context->aic->nr_dispatched);
} else
WARN_ON(blk_fs_request(rq)
&& (!(rq->flags & (REQ_HARDBARRIER|REQ_SOFTBARRIER))) );
- list_add(&rq->queuelist, ad->dispatch);
-
/* Stop anticipating - let this request get through */
as_antic_stop(ad);
}
/*
+ * requeue the request. The request has not been completed, nor is it a
+ * new request, so don't touch accounting.
+ */
+static void as_requeue_request(request_queue_t *q, struct request *rq)
+{
+ as_deactivate_request(q, rq);
+ list_add(&rq->queuelist, &q->queue_head);
+}
+
+/*
* Account a request that is inserted directly onto the dispatch queue.
* arq->io_context->aic->nr_dispatched should not need to be incremented
* because only new requests should come through here: requeues go through
@@ -2080,6 +2081,7 @@ static struct elevator_type iosched_as = {
.elevator_add_req_fn = as_insert_request,
.elevator_remove_req_fn = as_remove_request,
.elevator_requeue_req_fn = as_requeue_request,
+ .elevator_deactivate_req_fn = as_deactivate_request,
.elevator_queue_empty_fn = as_queue_empty,
.elevator_completed_req_fn = as_completed_request,
.elevator_former_req_fn = as_former_request,
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 967c0f31edead..8f7c1a1ed7f44 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -46,14 +46,14 @@
#include <linux/completion.h>
#define CCISS_DRIVER_VERSION(maj,min,submin) ((maj<<16)|(min<<8)|(submin))
-#define DRIVER_NAME "HP CISS Driver (v 2.6.4)"
-#define DRIVER_VERSION CCISS_DRIVER_VERSION(2,6,4)
+#define DRIVER_NAME "HP CISS Driver (v 2.6.6)"
+#define DRIVER_VERSION CCISS_DRIVER_VERSION(2,6,6)
/* Embedded module documentation macros - see modules.h */
MODULE_AUTHOR("Hewlett-Packard Company");
-MODULE_DESCRIPTION("Driver for HP Controller SA5xxx SA6xxx version 2.6.4");
+MODULE_DESCRIPTION("Driver for HP Controller SA5xxx SA6xxx version 2.6.6");
MODULE_SUPPORTED_DEVICE("HP SA5i SA5i+ SA532 SA5300 SA5312 SA641 SA642 SA6400"
- " SA6i P600");
+ " SA6i P600 P800 E400");
MODULE_LICENSE("GPL");
#include "cciss_cmd.h"
@@ -61,7 +61,7 @@ MODULE_LICENSE("GPL");
#include <linux/cciss_ioctl.h>
/* define the PCI info for the cards we can control */
-const struct pci_device_id cciss_pci_device_id[] = {
+static const struct pci_device_id cciss_pci_device_id[] = {
{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISS,
0x0E11, 0x4070, 0, 0, 0},
{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSB,
@@ -82,6 +82,10 @@ const struct pci_device_id cciss_pci_device_id[] = {
0x0E11, 0x4091, 0, 0, 0},
{ PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSA,
0x103C, 0x3225, 0, 0, 0},
+ { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSB,
+ 0x103c, 0x3223, 0, 0, 0},
+ { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSB,
+ 0x103c, 0x3231, 0, 0, 0},
{0,}
};
MODULE_DEVICE_TABLE(pci, cciss_pci_device_id);
@@ -103,6 +107,8 @@ static struct board_type products[] = {
{ 0x409D0E11, "Smart Array 6400 EM", &SA5_access},
{ 0x40910E11, "Smart Array 6i", &SA5_access},
{ 0x3225103C, "Smart Array P600", &SA5_access},
+ { 0x3223103C, "Smart Array P800", &SA5_access},
+ { 0x3231103C, "Smart Array E400", &SA5_access},
};
/* How long to wait (in millesconds) for board to go into simple mode */
@@ -114,7 +120,11 @@ static struct board_type products[] = {
#define READ_AHEAD 1024
#define NR_CMDS 384 /* #commands that can be outstanding */
-#define MAX_CTLR 8
+#define MAX_CTLR 32
+
+/* Originally cciss driver only supports 8 major numbers */
+#define MAX_CTLR_ORIG 8
+
#define CCISS_DMA_MASK 0xFFFFFFFF /* 32 bit DMA */
@@ -294,7 +304,7 @@ cciss_proc_write(struct file *file, const char __user *buffer,
if (copy_from_user(cmd, buffer, count)) return -EFAULT;
cmd[count] = '\0';
len = strlen(cmd); // above 3 lines ensure safety
- if (cmd[len-1] == '\n')
+ if (len && cmd[len-1] == '\n')
cmd[--len] = '\0';
# ifdef CONFIG_CISS_SCSI_TAPE
if (strcmp("engage scsi", cmd)==0) {
@@ -2080,6 +2090,9 @@ static void do_cciss_request(request_queue_t *q)
drive_info_struct *drv;
int i, dir;
+ /* We call start_io here in case there is a command waiting on the
+ * queue that has not been sent.
+ */
if (blk_queue_plugged(q))
goto startio;
@@ -2168,6 +2181,9 @@ queue:
full:
blk_stop_queue(q);
startio:
+ /* We will already have the driver lock here so not need
+ * to lock it.
+ */
start_io(h);
}
@@ -2177,7 +2193,8 @@ static irqreturn_t do_cciss_intr(int irq, void *dev_id, struct pt_regs *regs)
CommandList_struct *c;
unsigned long flags;
__u32 a, a1;
-
+ int j;
+ int start_queue = h->next_to_run;
/* Is this interrupt for us? */
if (( h->access.intr_pending(h) == 0) || (h->interrupts_enabled == 0))
@@ -2224,13 +2241,50 @@ static irqreturn_t do_cciss_intr(int irq, void *dev_id, struct pt_regs *regs)
}
}
- /*
- * See if we can queue up some more IO
+ /* check to see if we have maxed out the number of commands that can
+ * be placed on the queue. If so then exit. We do this check here
+ * in case the interrupt we serviced was from an ioctl and did not
+ * free any new commands.
*/
- blk_start_queue(h->queue);
+ if ((find_first_zero_bit(h->cmd_pool_bits, NR_CMDS)) == NR_CMDS)
+ goto cleanup;
+
+ /* We have room on the queue for more commands. Now we need to queue
+ * them up. We will also keep track of the next queue to run so
+ * that every queue gets a chance to be started first.
+ */
+ for (j=0; j < NWD; j++){
+ int curr_queue = (start_queue + j) % NWD;
+ /* make sure the disk has been added and the drive is real
+ * because this can be called from the middle of init_one.
+ */
+ if(!(h->gendisk[curr_queue]->queue) ||
+ !(h->drv[curr_queue].heads))
+ continue;
+ blk_start_queue(h->gendisk[curr_queue]->queue);
+
+ /* check to see if we have maxed out the number of commands
+ * that can be placed on the queue.
+ */
+ if ((find_first_zero_bit(h->cmd_pool_bits, NR_CMDS)) == NR_CMDS)
+ {
+ if (curr_queue == start_queue){
+ h->next_to_run = (start_queue + 1) % NWD;
+ goto cleanup;
+ } else {
+ h->next_to_run = curr_queue;
+ goto cleanup;
+ }
+ } else {
+ curr_queue = (curr_queue + 1) % NWD;
+ }
+ }
+
+cleanup:
spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
return IRQ_HANDLED;
}
+
/*
* We cannot read the structure directly, for portablity we must use
* the io functions.
@@ -2644,7 +2698,7 @@ static int alloc_cciss_hba(void)
}
}
printk(KERN_WARNING "cciss: This driver supports a maximum"
- " of 8 controllers.\n");
+ " of %d controllers.\n", MAX_CTLR);
goto out;
Enomem:
printk(KERN_ERR "cciss: out of memory.\n");
@@ -2676,13 +2730,14 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
request_queue_t *q;
int i;
int j;
+ int rc;
printk(KERN_DEBUG "cciss: Device 0x%x has been found at"
" bus %d dev %d func %d\n",
pdev->device, pdev->bus->number, PCI_SLOT(pdev->devfn),
PCI_FUNC(pdev->devfn));
i = alloc_cciss_hba();
- if( i < 0 )
+ if(i < 0)
return (-1);
if (cciss_pci_init(hba[i], pdev) != 0)
goto clean1;
@@ -2701,11 +2756,24 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
goto clean1;
}
- if (register_blkdev(COMPAQ_CISS_MAJOR+i, hba[i]->devname)) {
- printk(KERN_ERR "cciss: Unable to register device %s\n",
- hba[i]->devname);
+ /*
+ * register with the major number, or get a dynamic major number
+ * by passing 0 as argument. This is done for greater than
+ * 8 controller support.
+ */
+ if (i < MAX_CTLR_ORIG)
+ hba[i]->major = MAJOR_NR + i;
+ rc = register_blkdev(hba[i]->major, hba[i]->devname);
+ if(rc == -EBUSY || rc == -EINVAL) {
+ printk(KERN_ERR
+ "cciss: Unable to get major number %d for %s "
+ "on hba %d\n", hba[i]->major, hba[i]->devname, i);
goto clean1;
}
+ else {
+ if (i >= MAX_CTLR_ORIG)
+ hba[i]->major = rc;
+ }
/* make sure the board interrupts are off */
hba[i]->access.set_intr_mask(hba[i], CCISS_INTR_OFF);
@@ -2776,7 +2844,7 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
sprintf(disk->disk_name, "cciss/c%dd%d", i, j);
sprintf(disk->devfs_name, "cciss/host%d/target%d", i, j);
- disk->major = COMPAQ_CISS_MAJOR + i;
+ disk->major = hba[i]->major;
disk->first_minor = j << NWD_SHIFT;
disk->fops = &cciss_fops;
disk->queue = hba[i]->queue;
@@ -2805,7 +2873,7 @@ clean4:
hba[i]->errinfo_pool_dhandle);
free_irq(hba[i]->intr, hba[i]);
clean2:
- unregister_blkdev(COMPAQ_CISS_MAJOR+i, hba[i]->devname);
+ unregister_blkdev(hba[i]->major, hba[i]->devname);
clean1:
release_io_mem(hba[i]);
free_hba(i);
@@ -2847,7 +2915,7 @@ static void __devexit cciss_remove_one (struct pci_dev *pdev)
pci_set_drvdata(pdev, NULL);
iounmap(hba[i]->vaddr);
cciss_unregister_scsi(i); /* unhook from SCSI subsystem */
- unregister_blkdev(COMPAQ_CISS_MAJOR+i, hba[i]->devname);
+ unregister_blkdev(hba[i]->major, hba[i]->devname);
remove_proc_entry(hba[i]->devname, proc_cciss);
/* remove it from the disk list */
@@ -2878,7 +2946,7 @@ static struct pci_driver cciss_pci_driver = {
* This is it. Register the PCI driver information for the cards we control
* the OS will call our registered routines when it finds one of our cards.
*/
-int __init cciss_init(void)
+static int __init cciss_init(void)
{
printk(KERN_INFO DRIVER_NAME "\n");
@@ -2886,12 +2954,7 @@ int __init cciss_init(void)
return pci_module_init(&cciss_pci_driver);
}
-static int __init init_cciss_module(void)
-{
- return ( cciss_init());
-}
-
-static void __exit cleanup_cciss_module(void)
+static void __exit cciss_cleanup(void)
{
int i;
@@ -2909,5 +2972,5 @@ static void __exit cleanup_cciss_module(void)
remove_proc_entry("cciss", proc_root_driver);
}
-module_init(init_cciss_module);
-module_exit(cleanup_cciss_module);
+module_init(cciss_init);
+module_exit(cciss_cleanup);
diff --git a/drivers/block/cciss.h b/drivers/block/cciss.h
index 8ab689c21e499..8fb19206eddb2 100644
--- a/drivers/block/cciss.h
+++ b/drivers/block/cciss.h
@@ -13,6 +13,8 @@
#define IO_OK 0
#define IO_ERROR 1
+#define MAJOR_NR COMPAQ_CISS_MAJOR
+
struct ctlr_info;
typedef struct ctlr_info ctlr_info_t;
@@ -50,6 +52,7 @@ struct ctlr_info
CfgTable_struct __iomem *cfgtable;
unsigned int intr;
int interrupts_enabled;
+ int major;
int max_commands;
int commands_outstanding;
int max_outstanding; /* Debug */
@@ -81,6 +84,11 @@ struct ctlr_info
int nr_frees;
int busy_configuring;
+ /* This element holds the zero based queue number of the last
+ * queue to be started. It is used for fairness.
+ */
+ int next_to_run;
+
// Disk structures we need to pass back
struct gendisk *gendisk[NWD];
#ifdef CONFIG_CISS_SCSI_TAPE
diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c
index 6f6bc09fa19fd..f16e3caed58a3 100644
--- a/drivers/block/cciss_scsi.c
+++ b/drivers/block/cciss_scsi.c
@@ -53,9 +53,7 @@ static int sendcmd(
int cmd_type);
-const char *cciss_scsi_info(struct Scsi_Host *sa);
-
-int cciss_scsi_proc_info(
+static int cciss_scsi_proc_info(
struct Scsi_Host *sh,
char *buffer, /* data buffer */
char **start, /* where data in buffer starts */
@@ -63,7 +61,7 @@ int cciss_scsi_proc_info(
int length, /* length of data in buffer */
int func); /* 0 == read, 1 == write */
-int cciss_scsi_queue_command (struct scsi_cmnd *cmd,
+static int cciss_scsi_queue_command (struct scsi_cmnd *cmd,
void (* done)(struct scsi_cmnd *));
static struct cciss_scsi_hba_t ccissscsi[MAX_CTLR] = {
@@ -717,8 +715,6 @@ cciss_scsi_detect(int ctlr)
return 0;
}
-static void __exit cleanup_cciss_module(void);
-
static void
cciss_unmap_one(struct pci_dev *pdev,
CommandList_struct *cp,
@@ -1119,7 +1115,7 @@ cciss_scsi_user_command(int ctlr, int hostno, char *buffer, int length)
}
-int
+static int
cciss_scsi_proc_info(struct Scsi_Host *sh,
char *buffer, /* data buffer */
char **start, /* where data in buffer starts */
@@ -1154,29 +1150,6 @@ cciss_scsi_proc_info(struct Scsi_Host *sh,
buffer, length);
}
-/* this is via the generic proc support */
-const char *
-cciss_scsi_info(struct Scsi_Host *sa)
-{
- static char buf[300];
- ctlr_info_t *ci;
-
- /* probably need to work on putting a bit more info in here... */
- /* this is output via the /proc filesystem. */
-
- ci = (ctlr_info_t *) sa->hostdata[0];
-
- sprintf(buf, "%s %c%c%c%c\n",
- ci->product_name,
- ci->firm_ver[0],
- ci->firm_ver[1],
- ci->firm_ver[2],
- ci->firm_ver[3]);
-
- return buf;
-}
-
-
/* cciss_scatter_gather takes a struct scsi_cmnd, (cmd), and does the pci
dma mapping and fills in the scatter gather entries of the
cciss command, cp. */
@@ -1230,7 +1203,7 @@ cciss_scatter_gather(struct pci_dev *pdev,
}
-int
+static int
cciss_scsi_queue_command (struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *))
{
ctlr_info_t **c;
diff --git a/drivers/block/cciss_scsi.h b/drivers/block/cciss_scsi.h
index 51f1a9b404462..5e7e06c07d6c8 100644
--- a/drivers/block/cciss_scsi.h
+++ b/drivers/block/cciss_scsi.h
@@ -39,7 +39,6 @@
#define SCSI_CCISS_CAN_QUEUE 2
/*
- info: cciss_scsi_info, \
Note, cmd_per_lun could give us some trouble, so I'm setting it very low.
Likewise, SCSI_CCISS_CAN_QUEUE is set very conservatively.
diff --git a/drivers/block/cfq-iosched.c b/drivers/block/cfq-iosched.c
index 12fb10aa186e2..0ef7a0065ece2 100644
--- a/drivers/block/cfq-iosched.c
+++ b/drivers/block/cfq-iosched.c
@@ -607,10 +607,7 @@ out:
return NULL;
}
-/*
- * make sure the service time gets corrected on reissue of this request
- */
-static void cfq_requeue_request(request_queue_t *q, struct request *rq)
+static void cfq_deactivate_request(request_queue_t *q, struct request *rq)
{
struct cfq_rq *crq = RQ_DATA(rq);
@@ -627,6 +624,14 @@ static void cfq_requeue_request(request_queue_t *q, struct request *rq)
cfqq->cfqd->rq_in_driver--;
}
}
+}
+
+/*
+ * make sure the service time gets corrected on reissue of this request
+ */
+static void cfq_requeue_request(request_queue_t *q, struct request *rq)
+{
+ cfq_deactivate_request(q, rq);
list_add(&rq->queuelist, &q->queue_head);
}
@@ -1790,7 +1795,7 @@ static struct sysfs_ops cfq_sysfs_ops = {
.store = cfq_attr_store,
};
-struct kobj_type cfq_ktype = {
+static struct kobj_type cfq_ktype = {
.sysfs_ops = &cfq_sysfs_ops,
.default_attrs = default_attrs,
};
@@ -1804,6 +1809,7 @@ static struct elevator_type iosched_cfq = {
.elevator_add_req_fn = cfq_insert_request,
.elevator_remove_req_fn = cfq_remove_request,
.elevator_requeue_req_fn = cfq_requeue_request,
+ .elevator_deactivate_req_fn = cfq_deactivate_request,
.elevator_queue_empty_fn = cfq_queue_empty,
.elevator_completed_req_fn = cfq_completed_request,
.elevator_former_req_fn = cfq_former_request,
@@ -1819,7 +1825,7 @@ static struct elevator_type iosched_cfq = {
.elevator_owner = THIS_MODULE,
};
-int cfq_init(void)
+static int __init cfq_init(void)
{
int ret;
diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c
index a231daff00250..cf1822a6361ce 100644
--- a/drivers/block/cpqarray.c
+++ b/drivers/block/cpqarray.c
@@ -97,7 +97,7 @@ static struct board_type products[] = {
};
/* define the PCI info for the PCI cards this driver can control */
-const struct pci_device_id cpqarray_pci_device_id[] =
+static const struct pci_device_id cpqarray_pci_device_id[] =
{
{ PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_COMPAQ_42XX,
0x0E11, 0x4058, 0, 0, 0}, /* SA431 */
@@ -135,7 +135,6 @@ static struct gendisk *ida_gendisk[MAX_CTLR][NWD];
/* Debug Extra Paranoid... */
#define DBGPX(s) do { } while(0)
-int cpqarray_init_step2(void);
static int cpqarray_pci_init(ctlr_info_t *c, struct pci_dev *pdev);
static void __iomem *remap_pci_mem(ulong base, ulong size);
static int cpqarray_eisa_detect(void);
@@ -312,14 +311,6 @@ static int ida_proc_get_info(char *buffer, char **start, off_t offset, int lengt
module_param_array(eisa, int, NULL, 0);
-/* This is a bit of a hack,
- * necessary to support both eisa and pci
- */
-int __init cpqarray_init(void)
-{
- return (cpqarray_init_step2());
-}
-
static void release_io_mem(ctlr_info_t *c)
{
/* if IO mem was not protected do nothing */
@@ -560,7 +551,7 @@ static struct pci_driver cpqarray_pci_driver = {
* This is it. Find all the controllers and register them.
* returns the number of block devices registered.
*/
-int __init cpqarray_init_step2(void)
+static int __init cpqarray_init(void)
{
int num_cntlrs_reg = 0;
int i;
diff --git a/drivers/block/deadline-iosched.c b/drivers/block/deadline-iosched.c
index 820baa66291b8..d63d34c671f7a 100644
--- a/drivers/block/deadline-iosched.c
+++ b/drivers/block/deadline-iosched.c
@@ -19,7 +19,7 @@
#include <linux/rbtree.h>
/*
- * See Documentation/deadline-iosched.txt
+ * 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! */
@@ -909,7 +909,7 @@ static struct sysfs_ops deadline_sysfs_ops = {
.store = deadline_attr_store,
};
-struct kobj_type deadline_ktype = {
+static struct kobj_type deadline_ktype = {
.sysfs_ops = &deadline_sysfs_ops,
.default_attrs = default_attrs,
};
diff --git a/drivers/block/elevator.c b/drivers/block/elevator.c
index 35f4079b04d66..6b79b43146220 100644
--- a/drivers/block/elevator.c
+++ b/drivers/block/elevator.c
@@ -92,7 +92,7 @@ inline int elv_try_last_merge(request_queue_t *q, struct bio *bio)
}
EXPORT_SYMBOL(elv_try_last_merge);
-struct elevator_type *elevator_find(const char *name)
+static struct elevator_type *elevator_find(const char *name)
{
struct elevator_type *e = NULL;
struct list_head *entry;
@@ -220,7 +220,7 @@ void elevator_exit(elevator_t *e)
kfree(e);
}
-int elevator_global_init(void)
+static int elevator_global_init(void)
{
return 0;
}
@@ -255,8 +255,16 @@ void elv_merge_requests(request_queue_t *q, struct request *rq,
e->ops->elevator_merge_req_fn(q, rq, next);
}
-void elv_requeue_request(request_queue_t *q, struct request *rq)
+/*
+ * For careful internal use by the block layer. Essentially the same as
+ * a requeue in that it tells the io scheduler that this request is not
+ * active in the driver or hardware anymore, but we don't want the request
+ * added back to the scheduler. Function is not exported.
+ */
+void elv_deactivate_request(request_queue_t *q, struct request *rq)
{
+ elevator_t *e = q->elevator;
+
/*
* it already went through dequeue, we need to decrement the
* in_flight count again
@@ -264,6 +272,24 @@ void elv_requeue_request(request_queue_t *q, struct request *rq)
if (blk_account_rq(rq))
q->in_flight--;
+ rq->flags &= ~REQ_STARTED;
+
+ if (e->ops->elevator_deactivate_req_fn)
+ e->ops->elevator_deactivate_req_fn(q, rq);
+}
+
+void elv_requeue_request(request_queue_t *q, struct request *rq)
+{
+ elv_deactivate_request(q, rq);
+
+ /*
+ * 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;
+ }
+
/*
* if iosched has an explicit requeue hook, then use that. otherwise
* just put the request at the front of the queue
@@ -320,7 +346,21 @@ void elv_add_request(request_queue_t *q, struct request *rq, int where,
static inline struct request *__elv_next_request(request_queue_t *q)
{
- return q->elevator->ops->elevator_next_req_fn(q);
+ struct request *rq = q->elevator->ops->elevator_next_req_fn(q);
+
+ /*
+ * if this is a barrier write and the device has to issue a
+ * flush sequence to support it, check how far we are
+ */
+ if (rq && blk_fs_request(rq) && blk_barrier_rq(rq)) {
+ BUG_ON(q->ordered == QUEUE_ORDERED_NONE);
+
+ if (q->ordered == QUEUE_ORDERED_FLUSH &&
+ !blk_barrier_preflush(rq))
+ rq = blk_start_pre_flush(q, rq);
+ }
+
+ return rq;
}
struct request *elv_next_request(request_queue_t *q)
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index bce3fc0e6e4f3..42dfa281a880f 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -4217,7 +4217,7 @@ static struct kobject *floppy_find(dev_t dev, int *part, void *data)
return get_disk(disks[drive]);
}
-int __init floppy_init(void)
+static int __init floppy_init(void)
{
int i, unit, drive;
int err, dr;
@@ -4370,6 +4370,10 @@ int __init floppy_init(void)
goto out_flush_work;
}
+ err = platform_device_register(&floppy_device);
+ if (err)
+ goto out_flush_work;
+
for (drive = 0; drive < N_DRIVE; drive++) {
if (!(allowed_drive_mask & (1 << drive)))
continue;
@@ -4379,23 +4383,12 @@ int __init floppy_init(void)
disks[drive]->private_data = (void *)(long)drive;
disks[drive]->queue = floppy_queue;
disks[drive]->flags |= GENHD_FL_REMOVABLE;
+ disks[drive]->driverfs_dev = &floppy_device.dev;
add_disk(disks[drive]);
}
- err = platform_device_register(&floppy_device);
- if (err)
- goto out_del_disk;
-
return 0;
-out_del_disk:
- for (drive = 0; drive < N_DRIVE; drive++) {
- if (!(allowed_drive_mask & (1 << drive)))
- continue;
- if (fdc_state[FDC(drive)].version == FDC_NONE)
- continue;
- del_gendisk(disks[drive]);
- }
out_flush_work:
flush_scheduled_work();
if (usage_count)
@@ -4558,7 +4551,7 @@ static void floppy_release_irq_and_dma(void)
#ifdef MODULE
-char *floppy;
+static char *floppy;
static void unregister_devfs_entries(int drive)
{
@@ -4600,7 +4593,6 @@ void cleanup_module(void)
int drive;
init_completion(&device_release);
- platform_device_unregister(&floppy_device);
blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256);
unregister_blkdev(FLOPPY_MAJOR, "fd");
@@ -4614,6 +4606,7 @@ void cleanup_module(void)
}
put_disk(disks[drive]);
}
+ platform_device_unregister(&floppy_device);
devfs_remove("floppy");
del_timer_sync(&fd_timeout);
diff --git a/drivers/block/genhd.c b/drivers/block/genhd.c
index aee126315447c..ab4db71375e08 100644
--- a/drivers/block/genhd.c
+++ b/drivers/block/genhd.c
@@ -302,7 +302,7 @@ static struct kobject *base_probe(dev_t dev, int *part, void *data)
static int __init genhd_device_init(void)
{
- bdev_map = kobj_map_init(base_probe, &block_subsys);
+ bdev_map = kobj_map_init(base_probe, &block_subsys_sem);
blk_dev_init();
subsystem_register(&block_subsys);
return 0;
@@ -430,43 +430,58 @@ static int block_hotplug_filter(struct kset *kset, struct kobject *kobj)
static int block_hotplug(struct kset *kset, struct kobject *kobj, char **envp,
int num_envp, char *buffer, int buffer_size)
{
- struct device *dev = NULL;
struct kobj_type *ktype = get_ktype(kobj);
+ struct device *physdev;
+ struct gendisk *disk;
+ struct hd_struct *part;
int length = 0;
int i = 0;
- /* get physical device backing disk or partition */
if (ktype == &ktype_block) {
- struct gendisk *disk = container_of(kobj, struct gendisk, kobj);
- dev = disk->driverfs_dev;
+ disk = container_of(kobj, struct gendisk, kobj);
+ add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size,
+ &length, "MINOR=%u", disk->first_minor);
} else if (ktype == &ktype_part) {
- struct gendisk *disk = container_of(kobj->parent, struct gendisk, kobj);
- dev = disk->driverfs_dev;
- }
+ 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);
+ } else
+ return 0;
- if (dev) {
- /* add physical device, backing this device */
- char *path = kobject_get_path(&dev->kobj, GFP_KERNEL);
+ add_hotplug_env_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);
kfree(path);
- /* add bus name of physical device */
- if (dev->bus)
+ if (physdev->bus)
add_hotplug_env_var(envp, num_envp, &i,
buffer, buffer_size, &length,
- "PHYSDEVBUS=%s", dev->bus->name);
+ "PHYSDEVBUS=%s",
+ physdev->bus->name);
- /* add driver name of physical device */
- if (dev->driver)
+ if (physdev->driver)
add_hotplug_env_var(envp, num_envp, &i,
buffer, buffer_size, &length,
- "PHYSDEVDRIVER=%s", dev->driver->name);
-
- envp[i] = NULL;
+ "PHYSDEVDRIVER=%s",
+ physdev->driver->name);
}
+ /* terminate, set to next free slot, shrink available space */
+ envp[i] = NULL;
+ envp = &envp[i];
+ num_envp -= i;
+ buffer = &buffer[length];
+ buffer_size -= length;
+
return 0;
}
@@ -660,9 +675,10 @@ int invalidate_partition(struct gendisk *disk, int index)
{
int res = 0;
struct block_device *bdev = bdget_disk(disk, index);
- if (bdev)
+ if (bdev) {
res = __invalidate_device(bdev, 1);
- bdput(bdev);
+ bdput(bdev);
+ }
return res;
}
diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
index 3994af7e555b1..02242e8ba9968 100644
--- a/drivers/block/ll_rw_blk.c
+++ b/drivers/block/ll_rw_blk.c
@@ -238,7 +238,7 @@ void blk_queue_make_request(request_queue_t * q, make_request_fn * mfn)
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.memory_backed = 0;
+ q->backing_dev_info.capabilities = BDI_CAP_MAP_COPY;
blk_queue_max_sectors(q, MAX_SECTORS);
blk_queue_hardsect_size(q, 512);
blk_queue_dma_alignment(q, 511);
@@ -267,6 +267,25 @@ void blk_queue_make_request(request_queue_t * q, make_request_fn * mfn)
EXPORT_SYMBOL(blk_queue_make_request);
+static inline void rq_init(request_queue_t *q, struct request *rq)
+{
+ INIT_LIST_HEAD(&rq->queuelist);
+
+ rq->errors = 0;
+ rq->rq_status = RQ_ACTIVE;
+ rq->bio = rq->biotail = NULL;
+ rq->buffer = NULL;
+ rq->ref_count = 1;
+ rq->q = q;
+ rq->waiting = NULL;
+ rq->special = NULL;
+ rq->data_len = 0;
+ rq->data = NULL;
+ rq->sense = NULL;
+ rq->end_io = NULL;
+ rq->end_io_data = NULL;
+}
+
/**
* blk_queue_ordered - does this queue support ordered writes
* @q: the request queue
@@ -281,10 +300,26 @@ EXPORT_SYMBOL(blk_queue_make_request);
**/
void blk_queue_ordered(request_queue_t *q, int flag)
{
- if (flag)
- set_bit(QUEUE_FLAG_ORDERED, &q->queue_flags);
- else
- clear_bit(QUEUE_FLAG_ORDERED, &q->queue_flags);
+ 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;
+ }
}
EXPORT_SYMBOL(blk_queue_ordered);
@@ -306,6 +341,169 @@ void blk_queue_issue_flush_fn(request_queue_t *q, issue_flush_fn *iff)
EXPORT_SYMBOL(blk_queue_issue_flush_fn);
+/*
+ * Cache flushing for ordered writes handling
+ */
+static void blk_pre_flush_end_io(struct request *flush_rq)
+{
+ struct request *rq = flush_rq->end_io_data;
+ request_queue_t *q = rq->q;
+
+ 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);
+ }
+}
+
+static void blk_post_flush_end_io(struct request *flush_rq)
+{
+ struct request *rq = flush_rq->end_io_data;
+ request_queue_t *q = rq->q;
+
+ rq->flags |= REQ_BAR_POSTFLUSH;
+
+ q->end_flush_fn(q, flush_rq);
+ clear_bit(QUEUE_FLAG_FLUSH, &q->queue_flags);
+ q->request_fn(q);
+}
+
+struct request *blk_start_pre_flush(request_queue_t *q, struct request *rq)
+{
+ struct request *flush_rq = q->flush_rq;
+
+ BUG_ON(!blk_barrier_rq(rq));
+
+ if (test_and_set_bit(QUEUE_FLAG_FLUSH, &q->queue_flags))
+ return NULL;
+
+ 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;
+
+ /*
+ * 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;
+ }
+
+ /*
+ * some drivers dequeue requests right away, some only after io
+ * completion. make sure the request is dequeued.
+ */
+ if (!list_empty(&rq->queuelist))
+ blkdev_dequeue_request(rq);
+
+ elv_deactivate_request(q, rq);
+
+ flush_rq->end_io_data = rq;
+ flush_rq->end_io = blk_pre_flush_end_io;
+
+ __elv_add_request(q, flush_rq, ELEVATOR_INSERT_FRONT, 0);
+ return flush_rq;
+}
+
+static void blk_start_post_flush(request_queue_t *q, struct request *rq)
+{
+ struct request *flush_rq = q->flush_rq;
+
+ BUG_ON(!blk_barrier_rq(rq));
+
+ 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;
+
+ if (q->prepare_flush_fn(q, flush_rq)) {
+ flush_rq->end_io_data = rq;
+ flush_rq->end_io = blk_post_flush_end_io;
+
+ __elv_add_request(q, flush_rq, ELEVATOR_INSERT_FRONT, 0);
+ q->request_fn(q);
+ }
+}
+
+static inline int blk_check_end_barrier(request_queue_t *q, struct request *rq,
+ int sectors)
+{
+ if (sectors > rq->nr_sectors)
+ sectors = rq->nr_sectors;
+
+ rq->nr_sectors -= sectors;
+ return rq->nr_sectors;
+}
+
+static int __blk_complete_barrier_rq(request_queue_t *q, struct request *rq,
+ int sectors, int queue_locked)
+{
+ 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;
+
+ if (!blk_check_end_barrier(q, rq, sectors)) {
+ unsigned long flags = 0;
+
+ if (!queue_locked)
+ spin_lock_irqsave(q->queue_lock, flags);
+
+ blk_start_post_flush(q, rq);
+
+ if (!queue_locked)
+ spin_unlock_irqrestore(q->queue_lock, flags);
+ }
+
+ 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)
+{
+ return __blk_complete_barrier_rq(q, rq, sectors, 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)
+{
+ return __blk_complete_barrier_rq(q, rq, sectors, 1);
+}
+EXPORT_SYMBOL(blk_complete_barrier_rq_locked);
+
/**
* blk_queue_bounce_limit - set bounce buffer limit for queue
* @q: the request queue for the device
@@ -618,6 +816,7 @@ fail:
* blk_queue_init_tags - initialize the queue tag info
* @q: the request queue for the device
* @depth: the maximum queue depth supported
+ * @tags: the tag to use
**/
int blk_queue_init_tags(request_queue_t *q, int depth,
struct blk_queue_tag *tags)
@@ -1428,6 +1627,8 @@ 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);
}
@@ -1739,21 +1940,8 @@ rq_starved:
if (ioc_batching(q, ioc))
ioc->nr_batch_requests--;
- INIT_LIST_HEAD(&rq->queuelist);
-
- rq->errors = 0;
- rq->rq_status = RQ_ACTIVE;
- rq->bio = rq->biotail = NULL;
- rq->buffer = NULL;
- rq->ref_count = 1;
- rq->q = q;
+ rq_init(q, rq);
rq->rl = rl;
- rq->waiting = NULL;
- rq->special = NULL;
- rq->data_len = 0;
- rq->data = NULL;
- rq->sense = NULL;
-
out:
put_io_context(ioc);
return rq;
@@ -1963,7 +2151,7 @@ EXPORT_SYMBOL(blk_rq_map_user);
/**
* blk_rq_unmap_user - unmap a request with user data
* @rq: request to be unmapped
- * @ubuf: user buffer
+ * @bio: bio for the request
* @ulen: length of user buffer
*
* Description:
@@ -2018,11 +2206,11 @@ int blk_execute_rq(request_queue_t *q, struct gendisk *bd_disk,
}
rq->flags |= REQ_NOMERGE;
- if (!rq->waiting)
- rq->waiting = &wait;
+ rq->waiting = &wait;
+ rq->end_io = blk_end_sync_rq;
elv_add_request(q, rq, ELEVATOR_INSERT_BACK, 1);
generic_unplug_device(q);
- wait_for_completion(rq->waiting);
+ wait_for_completion(&wait);
rq->waiting = NULL;
if (rq->errors)
@@ -2171,7 +2359,7 @@ void disk_round_stats(struct gendisk *disk)
/*
* queue lock must be held
*/
-void __blk_put_request(request_queue_t *q, struct request *req)
+static void __blk_put_request(request_queue_t *q, struct request *req)
{
struct request_list *rl = req->rl;
@@ -2219,6 +2407,25 @@ void blk_put_request(struct request *req)
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)
+{
+ struct completion *waiting = rq->waiting;
+
+ rq->waiting = NULL;
+ __blk_put_request(rq->q, rq);
+
+ /*
+ * complete last, if this is a stack request the process (and thus
+ * the rq pointer) could be invalid right after this complete()
+ */
+ complete(waiting);
+}
+EXPORT_SYMBOL(blk_end_sync_rq);
+
+/**
* blk_congestion_wait - wait for a queue to become uncongested
* @rw: READ or WRITE
* @timeout: timeout in jiffies
@@ -2371,7 +2578,7 @@ static int __make_request(request_queue_t *q, struct bio *bio)
spin_lock_prefetch(q->queue_lock);
barrier = bio_barrier(bio);
- if (barrier && !(q->queue_flags & (1 << QUEUE_FLAG_ORDERED))) {
+ if (barrier && (q->ordered == QUEUE_ORDERED_NONE)) {
err = -EOPNOTSUPP;
goto end_io;
}
@@ -2978,7 +3185,6 @@ EXPORT_SYMBOL(end_that_request_chunk);
void end_that_request_last(struct request *req)
{
struct gendisk *disk = req->rq_disk;
- struct completion *waiting = req->waiting;
if (unlikely(laptop_mode) && blk_fs_request(req))
laptop_io_completion();
@@ -2998,10 +3204,10 @@ void end_that_request_last(struct request *req)
disk_round_stats(disk);
disk->in_flight--;
}
- __blk_put_request(req->q, req);
- /* Do this LAST! The structure may be freed immediately afterwards */
- if (waiting)
- complete(waiting);
+ if (req->end_io)
+ req->end_io(req);
+ else
+ __blk_put_request(req->q, req);
}
EXPORT_SYMBOL(end_that_request_last);
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 3efc2ea7ad643..6f011d0d8e97a 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -39,6 +39,11 @@
* Support up to 256 loop devices
* Heinz Mauelshagen <mge@sistina.com>, Feb 2002
*
+ * Support for falling back on the write file operation when the address space
+ * operations prepare_write and/or commit_write are not available on the
+ * backing filesystem.
+ * Anton Altaparmakov, 16 Feb 2005
+ *
* Still To Fix:
* - Advisory locking is ignored here.
* - Should use an own CAP_* category instead of CAP_SYS_ADMIN
@@ -67,6 +72,8 @@
#include <linux/writeback.h>
#include <linux/buffer_head.h> /* for invalidate_bdev() */
#include <linux/completion.h>
+#include <linux/highmem.h>
+#include <linux/gfp.h>
#include <asm/uaccess.h>
@@ -127,7 +134,7 @@ static int transfer_xor(struct loop_device *lo, int cmd,
static int xor_init(struct loop_device *lo, const struct loop_info64 *info)
{
- if (info->lo_encrypt_key_size <= 0)
+ if (unlikely(info->lo_encrypt_key_size <= 0))
return -EINVAL;
return 0;
}
@@ -173,7 +180,7 @@ figure_loop_size(struct loop_device *lo)
loff_t size = get_loop_size(lo, lo->lo_backing_file);
sector_t x = (sector_t)size;
- if ((loff_t)x != size)
+ if (unlikely((loff_t)x != size))
return -EFBIG;
set_capacity(disks[lo->lo_number], x);
@@ -186,23 +193,27 @@ lo_do_transfer(struct loop_device *lo, int cmd,
struct page *lpage, unsigned loffs,
int size, sector_t rblock)
{
- if (!lo->transfer)
+ if (unlikely(!lo->transfer))
return 0;
return lo->transfer(lo, cmd, rpage, roffs, lpage, loffs, size, rblock);
}
-static int
-do_lo_send(struct loop_device *lo, struct bio_vec *bvec, int bsize, loff_t pos)
+/**
+ * do_lo_send_aops - helper for writing data to a loop device
+ *
+ * This is the fast version for backing filesystems which implement the address
+ * space operations prepare_write and commit_write.
+ */
+static int do_lo_send_aops(struct loop_device *lo, struct bio_vec *bvec,
+ int bsize, loff_t pos, struct page *page)
{
struct file *file = lo->lo_backing_file; /* kudos to NFsckingS */
struct address_space *mapping = file->f_mapping;
struct address_space_operations *aops = mapping->a_ops;
- struct page *page;
pgoff_t index;
- unsigned size, offset, bv_offs;
- int len;
- int ret = 0;
+ unsigned offset, bv_offs;
+ int len, ret = 0;
down(&mapping->host->i_sem);
index = pos >> PAGE_CACHE_SHIFT;
@@ -211,23 +222,22 @@ do_lo_send(struct loop_device *lo, struct bio_vec *bvec, int bsize, loff_t pos)
len = bvec->bv_len;
while (len > 0) {
sector_t IV;
+ unsigned size;
int transfer_result;
IV = ((sector_t)index << (PAGE_CACHE_SHIFT - 9))+(offset >> 9);
-
size = PAGE_CACHE_SIZE - offset;
if (size > len)
size = len;
-
page = grab_cache_page(mapping, index);
- if (!page)
+ if (unlikely(!page))
goto fail;
- if (aops->prepare_write(file, page, offset, offset+size))
+ if (unlikely(aops->prepare_write(file, page, offset,
+ offset + size)))
goto unlock;
transfer_result = lo_do_transfer(lo, WRITE, page, offset,
- bvec->bv_page, bv_offs,
- size, IV);
- if (transfer_result) {
+ bvec->bv_page, bv_offs, size, IV);
+ if (unlikely(transfer_result)) {
char *kaddr;
/*
@@ -241,9 +251,10 @@ do_lo_send(struct loop_device *lo, struct bio_vec *bvec, int bsize, loff_t pos)
kunmap_atomic(kaddr, KM_USER0);
}
flush_dcache_page(page);
- if (aops->commit_write(file, page, offset, offset+size))
+ if (unlikely(aops->commit_write(file, page, offset,
+ offset + size)))
goto unlock;
- if (transfer_result)
+ if (unlikely(transfer_result))
goto unlock;
bv_offs += size;
len -= size;
@@ -253,32 +264,125 @@ do_lo_send(struct loop_device *lo, struct bio_vec *bvec, int bsize, loff_t pos)
unlock_page(page);
page_cache_release(page);
}
- up(&mapping->host->i_sem);
out:
+ up(&mapping->host->i_sem);
return ret;
-
unlock:
unlock_page(page);
page_cache_release(page);
fail:
- up(&mapping->host->i_sem);
ret = -1;
goto out;
}
-static int
-lo_send(struct loop_device *lo, struct bio *bio, int bsize, loff_t pos)
+/**
+ * __do_lo_send_write - helper for writing data to a loop device
+ *
+ * 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,
+ u8 __user *buf, const int len, loff_t pos)
{
+ ssize_t bw;
+ mm_segment_t old_fs = get_fs();
+
+ set_fs(get_ds());
+ bw = file->f_op->write(file, buf, len, &pos);
+ set_fs(old_fs);
+ if (likely(bw == len))
+ return 0;
+ printk(KERN_ERR "loop: Write error at byte offset %llu, length %i.\n",
+ (unsigned long long)pos, len);
+ if (bw >= 0)
+ bw = -EIO;
+ return bw;
+}
+
+/**
+ * do_lo_send_direct_write - helper for writing data to a loop device
+ *
+ * This is the fast, non-transforming version for backing filesystems which do
+ * not implement the address space operations prepare_write and commit_write.
+ * It uses the write file operation which should be present on all writeable
+ * filesystems.
+ */
+static int do_lo_send_direct_write(struct loop_device *lo,
+ struct bio_vec *bvec, int bsize, loff_t pos, struct page *page)
+{
+ ssize_t bw = __do_lo_send_write(lo->lo_backing_file,
+ (u8 __user *)kmap(bvec->bv_page) + bvec->bv_offset,
+ bvec->bv_len, pos);
+ kunmap(bvec->bv_page);
+ cond_resched();
+ return bw;
+}
+
+/**
+ * do_lo_send_write - helper for writing data to a loop device
+ *
+ * This is the slow, transforming version for filesystems which do not
+ * implement the address space operations prepare_write and commit_write. It
+ * uses the write file operation which should be present on all writeable
+ * filesystems.
+ *
+ * Using fops->write is slower than using aops->{prepare,commit}_write in the
+ * transforming case because we need to double buffer the data as we cannot do
+ * the transformations in place as we do not have direct access to the
+ * destination pages of the backing file.
+ */
+static int do_lo_send_write(struct loop_device *lo, struct bio_vec *bvec,
+ int bsize, loff_t pos, struct page *page)
+{
+ int ret = lo_do_transfer(lo, WRITE, page, 0, bvec->bv_page,
+ bvec->bv_offset, bvec->bv_len, pos >> 9);
+ if (likely(!ret))
+ return __do_lo_send_write(lo->lo_backing_file,
+ (u8 __user *)page_address(page), bvec->bv_len,
+ pos);
+ printk(KERN_ERR "loop: Transfer error at byte offset %llu, "
+ "length %i.\n", (unsigned long long)pos, bvec->bv_len);
+ if (ret > 0)
+ ret = -EIO;
+ return ret;
+}
+
+static int lo_send(struct loop_device *lo, struct bio *bio, int bsize,
+ loff_t pos)
+{
+ int (*do_lo_send)(struct loop_device *, struct bio_vec *, int, loff_t,
+ struct page *page);
struct bio_vec *bvec;
+ struct page *page = NULL;
int i, ret = 0;
+ do_lo_send = do_lo_send_aops;
+ if (!(lo->lo_flags & LO_FLAGS_USE_AOPS)) {
+ do_lo_send = do_lo_send_direct_write;
+ if (lo->transfer != transfer_none) {
+ page = alloc_page(GFP_NOIO | __GFP_HIGHMEM);
+ if (unlikely(!page))
+ goto fail;
+ kmap(page);
+ do_lo_send = do_lo_send_write;
+ }
+ }
bio_for_each_segment(bvec, bio, i) {
- ret = do_lo_send(lo, bvec, bsize, pos);
+ ret = do_lo_send(lo, bvec, bsize, pos, page);
if (ret < 0)
break;
pos += bvec->bv_len;
}
+ if (page) {
+ kunmap(page);
+ __free_page(page);
+ }
+out:
return ret;
+fail:
+ printk(KERN_ERR "loop: Failed to allocate temporary page for write.\n");
+ ret = -ENOMEM;
+ goto out;
}
struct lo_read_data {
@@ -584,7 +688,7 @@ static int loop_change_fd(struct loop_device *lo, struct file *lo_file,
/* the loop device has to be read-only */
error = -EINVAL;
- if (lo->lo_flags != LO_FLAGS_READ_ONLY)
+ if (!(lo->lo_flags & LO_FLAGS_READ_ONLY))
goto out;
error = -EBADF;
@@ -683,8 +787,9 @@ static int loop_set_fd(struct loop_device *lo, struct file *lo_file,
*/
if (!file->f_op->sendfile)
goto out_putf;
-
- if (!aops->prepare_write || !aops->commit_write)
+ if (aops->prepare_write && aops->commit_write)
+ lo_flags |= LO_FLAGS_USE_AOPS;
+ if (!(lo_flags & LO_FLAGS_USE_AOPS) && !file->f_op->write)
lo_flags |= LO_FLAGS_READ_ONLY;
lo_blocksize = inode->i_blksize;
@@ -1137,7 +1242,7 @@ int loop_unregister_transfer(int number)
EXPORT_SYMBOL(loop_register_transfer);
EXPORT_SYMBOL(loop_unregister_transfer);
-int __init loop_init(void)
+static int __init loop_init(void)
{
int i;
@@ -1212,7 +1317,7 @@ out_mem1:
return -ENOMEM;
}
-void loop_exit(void)
+static void loop_exit(void)
{
int i;
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index 2f5cc3e251c60..7c7ed041c28ce 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -38,7 +38,7 @@
* 03-06-24 Cleanup PARANOIA usage & code. <ldl@aros.net>
* 04-02-19 Remove PARANOIA, plus various cleanups (Paul Clements)
* possible FIXME: make set_sock / set_blksize / set_size / do_it one syscall
- * why not: would need verify_area and friends, would share yet another
+ * why not: would need access_ok and friends, would share yet another
* structure with userland
*/
@@ -315,7 +315,7 @@ static inline int sock_recv_bvec(struct socket *sock, struct bio_vec *bvec)
}
/* NULL returned = something went wrong, inform userspace */
-struct request *nbd_read_stat(struct nbd_device *lo)
+static struct request *nbd_read_stat(struct nbd_device *lo)
{
int result;
struct nbd_reply reply;
@@ -377,7 +377,7 @@ harderror:
return NULL;
}
-void nbd_do_it(struct nbd_device *lo)
+static void nbd_do_it(struct nbd_device *lo)
{
struct request *req;
@@ -388,7 +388,7 @@ void nbd_do_it(struct nbd_device *lo)
return;
}
-void nbd_clear_que(struct nbd_device *lo)
+static void nbd_clear_que(struct nbd_device *lo)
{
struct request *req;
diff --git a/drivers/block/paride/pcd.c b/drivers/block/paride/pcd.c
index c4d537874d6f2..7289f67e95687 100644
--- a/drivers/block/paride/pcd.c
+++ b/drivers/block/paride/pcd.c
@@ -142,26 +142,6 @@ enum {D_PRT, D_PRO, D_UNI, D_MOD, D_SLV, D_DLY};
static spinlock_t pcd_lock;
-#ifndef MODULE
-
-#include "setup.h"
-
-static STT pcd_stt[6] = {
- {"drive0", 6, drive0},
- {"drive1", 6, drive1},
- {"drive2", 6, drive2},
- {"drive3", 6, drive3},
- {"disable", 1, &disable},
- {"nice", 1, &nice}
-};
-
-void pcd_setup(char *str, int *ints)
-{
- generic_setup(pcd_stt, 6, str);
-}
-
-#endif
-
module_param(verbose, bool, 0644);
module_param(major, int, 0);
module_param(name, charp, 0);
@@ -218,7 +198,7 @@ struct pcd_unit {
struct gendisk *disk;
};
-struct pcd_unit pcd[PCD_UNITS];
+static struct pcd_unit pcd[PCD_UNITS];
static char pcd_scratch[64];
static char pcd_buffer[2048]; /* raw block buffer */
diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c
index 4390587b34132..202a5a74ad37b 100644
--- a/drivers/block/paride/pd.c
+++ b/drivers/block/paride/pd.c
@@ -157,27 +157,6 @@ enum {D_PRT, D_PRO, D_UNI, D_MOD, D_GEO, D_SBY, D_DLY, D_SLV};
static DEFINE_SPINLOCK(pd_lock);
-#ifndef MODULE
-
-#include "setup.h"
-
-static STT pd_stt[7] = {
- {"drive0", 8, drive0},
- {"drive1", 8, drive1},
- {"drive2", 8, drive2},
- {"drive3", 8, drive3},
- {"disable", 1, &disable},
- {"cluster", 1, &cluster},
- {"nice", 1, &nice}
-};
-
-void pd_setup(char *str, int *ints)
-{
- generic_setup(pd_stt, 7, str);
-}
-
-#endif
-
module_param(verbose, bool, 0);
module_param(major, int, 0);
module_param(name, charp, 0);
@@ -255,7 +234,7 @@ struct pd_unit {
struct gendisk *gd;
};
-struct pd_unit pd[PD_UNITS];
+static struct pd_unit pd[PD_UNITS];
static char pd_scratch[512]; /* scratch block buffer */
@@ -743,6 +722,7 @@ static int pd_special_command(struct pd_unit *disk,
rq.rq_disk = disk->gd;
rq.ref_count = 1;
rq.waiting = &wait;
+ rq.end_io = blk_end_sync_rq;
blk_insert_request(disk->gd->queue, &rq, 0, func, 0);
wait_for_completion(&wait);
rq.waiting = NULL;
diff --git a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c
index a1355ceaa2c2b..060b1f2a91ddc 100644
--- a/drivers/block/paride/pf.c
+++ b/drivers/block/paride/pf.c
@@ -156,27 +156,6 @@ enum {D_PRT, D_PRO, D_UNI, D_MOD, D_SLV, D_LUN, D_DLY};
static spinlock_t pf_spin_lock;
-#ifndef MODULE
-
-#include "setup.h"
-
-static STT pf_stt[7] = {
- {"drive0", 7, drive0},
- {"drive1", 7, drive1},
- {"drive2", 7, drive2},
- {"drive3", 7, drive3},
- {"disable", 1, &disable},
- {"cluster", 1, &cluster},
- {"nice", 1, &nice}
-};
-
-void pf_setup(char *str, int *ints)
-{
- generic_setup(pf_stt, 7, str);
-}
-
-#endif
-
module_param(verbose, bool, 0644);
module_param(major, int, 0);
module_param(name, charp, 0);
@@ -256,7 +235,7 @@ struct pf_unit {
struct gendisk *disk;
};
-struct pf_unit units[PF_UNITS];
+static struct pf_unit units[PF_UNITS];
static int pf_identify(struct pf_unit *pf);
static void pf_lock(struct pf_unit *pf, int func);
@@ -290,7 +269,7 @@ static struct block_device_operations pf_fops = {
.media_changed = pf_check_media,
};
-void pf_init_units(void)
+static void __init pf_init_units(void)
{
struct pf_unit *pf;
int unit;
diff --git a/drivers/block/paride/pg.c b/drivers/block/paride/pg.c
index dd8c4d9546ed5..dbeb107bb9710 100644
--- a/drivers/block/paride/pg.c
+++ b/drivers/block/paride/pg.c
@@ -165,25 +165,6 @@ enum {D_PRT, D_PRO, D_UNI, D_MOD, D_SLV, D_DLY};
#include <asm/uaccess.h>
-#ifndef MODULE
-
-#include "setup.h"
-
-static STT pg_stt[5] = {
- {"drive0", 6, drive0},
- {"drive1", 6, drive1},
- {"drive2", 6, drive2},
- {"drive3", 6, drive3},
- {"disable", 1, &disable}
-};
-
-void pg_setup(char *str, int *ints)
-{
- generic_setup(pg_stt, 5, str);
-}
-
-#endif
-
module_param(verbose, bool, 0644);
module_param(major, int, 0);
module_param(name, charp, 0);
@@ -235,7 +216,7 @@ struct pg {
char name[PG_NAMELEN]; /* pg0, pg1, ... */
};
-struct pg devices[PG_UNITS];
+static struct pg devices[PG_UNITS];
static int pg_identify(struct pg *dev, int log);
diff --git a/drivers/block/paride/pt.c b/drivers/block/paride/pt.c
index e37f8b18c23db..8fbd6922fe0d4 100644
--- a/drivers/block/paride/pt.c
+++ b/drivers/block/paride/pt.c
@@ -149,26 +149,6 @@ static int (*drives[4])[6] = {&drive0, &drive1, &drive2, &drive3};
#include <asm/uaccess.h>
-#ifndef MODULE
-
-#include "setup.h"
-
-static STT pt_stt[5] = {
- {"drive0", 6, drive0},
- {"drive1", 6, drive1},
- {"drive2", 6, drive2},
- {"drive3", 6, drive3},
- {"disable", 1, &disable}
-};
-
-void
-pt_setup(char *str, int *ints)
-{
- generic_setup(pt_stt, 5, str);
-}
-
-#endif
-
module_param(verbose, bool, 0);
module_param(major, int, 0);
module_param(name, charp, 0);
@@ -246,7 +226,7 @@ struct pt_unit {
static int pt_identify(struct pt_unit *tape);
-struct pt_unit pt[PT_UNITS];
+static struct pt_unit pt[PT_UNITS];
static char pt_scratch[512]; /* scratch block buffer */
diff --git a/drivers/block/paride/setup.h b/drivers/block/paride/setup.h
deleted file mode 100644
index 85d1c440b2831..0000000000000
--- a/drivers/block/paride/setup.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- setup.h (c) 1997-8 Grant R. Guenther <grant@torque.net>
- Under the terms of the GNU General Public License.
-
- This is a table driven setup function for kernel modules
- using the module.variable=val,... command line notation.
-
-*/
-
-/* Changes:
-
- 1.01 GRG 1998.05.05 Allow negative and defaulted values
-
-*/
-
-#include <linux/ctype.h>
-#include <linux/string.h>
-
-struct setup_tab_t {
-
- char *tag; /* variable name */
- int size; /* number of elements in array */
- int *iv; /* pointer to variable */
-};
-
-typedef struct setup_tab_t STT;
-
-/* t is a table that describes the variables that can be set
- by gen_setup
- n is the number of entries in the table
- ss is a string of the form:
-
- <tag>=[<val>,...]<val>
-*/
-
-static void generic_setup( STT t[], int n, char *ss )
-
-{ int j,k, sgn;
-
- k = 0;
- for (j=0;j<n;j++) {
- k = strlen(t[j].tag);
- if (strncmp(ss,t[j].tag,k) == 0) break;
- }
- if (j == n) return;
-
- if (ss[k] == 0) {
- t[j].iv[0] = 1;
- return;
- }
-
- if (ss[k] != '=') return;
- ss += (k+1);
-
- k = 0;
- while (ss && (k < t[j].size)) {
- if (!*ss) break;
- sgn = 1;
- if (*ss == '-') { ss++; sgn = -1; }
- if (!*ss) break;
- if (isdigit(*ss))
- t[j].iv[k] = sgn * simple_strtoul(ss,NULL,0);
- k++;
- if ((ss = strchr(ss,',')) != NULL) ss++;
- }
-}
-
-/* end of setup.h */
-
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index 7590000b94570..1a1fa3ccb9137 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -219,7 +219,7 @@ static int pkt_grow_pktlist(struct pktcdvd_device *pd, int nr_packets)
return 1;
}
-static void *pkt_rb_alloc(int gfp_mask, void *data)
+static void *pkt_rb_alloc(unsigned int __nocast gfp_mask, void *data)
{
return kmalloc(sizeof(struct pkt_rb_node), gfp_mask);
}
@@ -375,6 +375,7 @@ static int pkt_generic_packet(struct pktcdvd_device *pd, struct packet_command *
rq->ref_count++;
rq->flags |= REQ_NOMERGE;
rq->waiting = &wait;
+ rq->end_io = blk_end_sync_rq;
elv_add_request(q, rq, ELEVATOR_INSERT_BACK, 1);
generic_unplug_device(q);
wait_for_completion(&wait);
@@ -1420,8 +1421,8 @@ static int pkt_set_write_settings(struct pktcdvd_device *pd)
char buffer[128];
int ret, size;
- /* doesn't apply to DVD+RW */
- if (pd->mmc3_profile == 0x1a)
+ /* doesn't apply to DVD+RW or DVD-RAM */
+ if ((pd->mmc3_profile == 0x1a) || (pd->mmc3_profile == 0x12))
return 0;
memset(buffer, 0, sizeof(buffer));
@@ -1535,6 +1536,7 @@ static int pkt_good_disc(struct pktcdvd_device *pd, disc_information *di)
break;
case 0x1a: /* DVD+RW */
case 0x13: /* DVD-RW */
+ case 0x12: /* DVD-RAM */
return 0;
default:
printk("pktcdvd: Wrong disc profile (%x)\n", pd->mmc3_profile);
@@ -1600,6 +1602,9 @@ static int pkt_probe_settings(struct pktcdvd_device *pd)
case 0x13: /* DVD-RW */
printk("pktcdvd: inserted media is DVD-RW\n");
break;
+ case 0x12: /* DVD-RAM */
+ printk("pktcdvd: inserted media is DVD-RAM\n");
+ break;
default:
printk("pktcdvd: inserted media is CD-R%s\n", di.erasable ? "W" : "");
break;
@@ -1892,6 +1897,7 @@ static int pkt_open_write(struct pktcdvd_device *pd)
switch (pd->mmc3_profile) {
case 0x13: /* DVD-RW */
case 0x1a: /* DVD+RW */
+ case 0x12: /* DVD-RAM */
DPRINTK("pktcdvd: write speed %ukB/s\n", write_speed);
break;
default:
@@ -2053,7 +2059,7 @@ static int pkt_close(struct inode *inode, struct file *file)
}
-static void *psd_pool_alloc(int gfp_mask, void *data)
+static void *psd_pool_alloc(unsigned int __nocast gfp_mask, void *data)
{
return kmalloc(sizeof(struct packet_stacked_data), gfp_mask);
}
@@ -2623,7 +2629,7 @@ static struct miscdevice pkt_misc = {
.fops = &pkt_ctl_fops
};
-static int pkt_init(void)
+static int __init pkt_init(void)
{
int ret;
@@ -2659,7 +2665,7 @@ out2:
return ret;
}
-static void pkt_exit(void)
+static void __exit pkt_exit(void)
{
remove_proc_entry("pktcdvd", proc_root_driver);
misc_deregister(&pkt_misc);
diff --git a/drivers/block/rd.c b/drivers/block/rd.c
index 80848c2a7bbed..145c1fbffe013 100644
--- a/drivers/block/rd.c
+++ b/drivers/block/rd.c
@@ -86,7 +86,7 @@ int rd_size = CONFIG_BLK_DEV_RAM_SIZE; /* Size of the RAM disks */
* behaviour. The default is still BLOCK_SIZE (needed by rd_load_image that
* supposes the filesystem in the image uses a BLOCK_SIZE blocksize).
*/
-int rd_blocksize = BLOCK_SIZE; /* blocksize of the RAM disks */
+static int rd_blocksize = BLOCK_SIZE; /* blocksize of the RAM disks */
/*
* Copyright (C) 2000 Linus Torvalds.
@@ -325,7 +325,7 @@ static int rd_ioctl(struct inode *inode, struct file *file,
*/
static struct backing_dev_info rd_backing_dev_info = {
.ra_pages = 0, /* No readahead */
- .memory_backed = 1, /* Does not contribute to dirty memory */
+ .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK | BDI_CAP_MAP_COPY,
.unplug_io_fn = default_unplug_io_fn,
};
@@ -336,7 +336,7 @@ static struct backing_dev_info rd_backing_dev_info = {
*/
static struct backing_dev_info rd_file_backing_dev_info = {
.ra_pages = 0, /* No readahead */
- .memory_backed = 0, /* Does contribute to dirty memory */
+ .capabilities = BDI_CAP_MAP_COPY, /* Does contribute to dirty memory */
.unplug_io_fn = default_unplug_io_fn,
};
diff --git a/drivers/block/ub.c b/drivers/block/ub.c
index acea9f08ea447..ce42889f98fbd 100644
--- a/drivers/block/ub.c
+++ b/drivers/block/ub.c
@@ -300,6 +300,7 @@ struct ub_dev {
/*
*/
+static void ub_cleanup(struct ub_dev *sc);
static int ub_bd_rq_fn_1(struct ub_dev *sc, struct request *rq);
static int ub_cmd_build_block(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
struct request *rq);
@@ -478,24 +479,55 @@ static int ub_id_get(void)
static void ub_id_put(int id)
{
+ unsigned long flags;
if (id < 0 || id >= UB_MAX_HOSTS) {
printk(KERN_ERR DRV_NAME ": bad host ID %d\n", id);
return;
}
+
+ spin_lock_irqsave(&ub_lock, flags);
if (ub_hostv[id] == 0) {
+ spin_unlock_irqrestore(&ub_lock, flags);
printk(KERN_ERR DRV_NAME ": freeing free host ID %d\n", id);
return;
}
ub_hostv[id] = 0;
+ spin_unlock_irqrestore(&ub_lock, flags);
+}
+
+/*
+ * Downcount for deallocation. This rides on two assumptions:
+ * - once something is poisoned, its refcount cannot grow
+ * - opens cannot happen at this time (del_gendisk was done)
+ * If the above is true, we can drop the lock, which we need for
+ * blk_cleanup_queue(): the silly thing may attempt to sleep.
+ * [Actually, it never needs to sleep for us, but it calls might_sleep()]
+ */
+static void ub_put(struct ub_dev *sc)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&ub_lock, flags);
+ --sc->openc;
+ if (sc->openc == 0 && atomic_read(&sc->poison)) {
+ spin_unlock_irqrestore(&ub_lock, flags);
+ ub_cleanup(sc);
+ } else {
+ spin_unlock_irqrestore(&ub_lock, flags);
+ }
}
/*
* Final cleanup and deallocation.
- * This must be called with ub_lock taken.
*/
static void ub_cleanup(struct ub_dev *sc)
{
+ request_queue_t *q;
+
+ /* I don't think queue can be NULL. But... Stolen from sx8.c */
+ if ((q = sc->disk->queue) != NULL)
+ blk_cleanup_queue(q);
/*
* If we zero disk->private_data BEFORE put_disk, we have to check
@@ -1526,11 +1558,7 @@ static int ub_bd_open(struct inode *inode, struct file *filp)
return 0;
err_open:
- spin_lock_irqsave(&ub_lock, flags);
- --sc->openc;
- if (sc->openc == 0 && atomic_read(&sc->poison))
- ub_cleanup(sc);
- spin_unlock_irqrestore(&ub_lock, flags);
+ ub_put(sc);
return rc;
}
@@ -1540,15 +1568,8 @@ static int ub_bd_release(struct inode *inode, struct file *filp)
{
struct gendisk *disk = inode->i_bdev->bd_disk;
struct ub_dev *sc = disk->private_data;
- unsigned long flags;
- spin_lock_irqsave(&ub_lock, flags);
- --sc->openc;
- if (sc->openc == 0)
- sc->first_open = 0;
- if (sc->openc == 0 && atomic_read(&sc->poison))
- ub_cleanup(sc);
- spin_unlock_irqrestore(&ub_lock, flags);
+ ub_put(sc);
return 0;
}
@@ -2043,9 +2064,7 @@ err_diag:
usb_set_intfdata(intf, NULL);
// usb_put_intf(sc->intf);
usb_put_dev(sc->dev);
- spin_lock_irq(&ub_lock);
ub_id_put(sc->id);
- spin_unlock_irq(&ub_lock);
err_id:
kfree(sc);
err_core:
@@ -2056,10 +2075,18 @@ static void ub_disconnect(struct usb_interface *intf)
{
struct ub_dev *sc = usb_get_intfdata(intf);
struct gendisk *disk = sc->disk;
- request_queue_t *q = disk->queue;
unsigned long flags;
/*
+ * Prevent ub_bd_release from pulling the rug from under us.
+ * XXX This is starting to look like a kref.
+ * XXX Why not to take this ref at probe time?
+ */
+ spin_lock_irqsave(&ub_lock, flags);
+ sc->openc++;
+ spin_unlock_irqrestore(&ub_lock, flags);
+
+ /*
* Fence stall clearnings, operations triggered by unlinkings and so on.
* We do not attempt to unlink any URBs, because we do not trust the
* unlink paths in HC drivers. Also, we get -84 upon disconnect anyway.
@@ -2095,17 +2122,18 @@ static void ub_disconnect(struct usb_interface *intf)
spin_unlock_irqrestore(&sc->lock, flags);
/*
- * Unregister the upper layer, this waits for all commands to end.
+ * Unregister the upper layer.
*/
if (disk->flags & GENHD_FL_UP)
del_gendisk(disk);
- if (q)
- blk_cleanup_queue(q);
+ /*
+ * I wish I could do:
+ * set_bit(QUEUE_FLAG_DEAD, &q->queue_flags);
+ * As it is, we rely on our internal poisoning and let
+ * the upper levels to spin furiously failing all the I/O.
+ */
/*
- * We really expect blk_cleanup_queue() to wait, so no amount
- * of paranoya is too much.
- *
* Taking a lock on a structure which is about to be freed
* is very nonsensual. Here it is largely a way to do a debug freeze,
* and a bracket which shows where the nonsensual code segment ends.
@@ -2139,13 +2167,10 @@ static void ub_disconnect(struct usb_interface *intf)
usb_put_dev(sc->dev);
sc->dev = NULL;
- spin_lock_irqsave(&ub_lock, flags);
- if (sc->openc == 0)
- ub_cleanup(sc);
- spin_unlock_irqrestore(&ub_lock, flags);
+ ub_put(sc);
}
-struct usb_driver ub_driver = {
+static struct usb_driver ub_driver = {
.owner = THIS_MODULE,
.name = "ub",
.probe = ub_probe,
diff --git a/drivers/block/umem.c b/drivers/block/umem.c
index 86a21e456d8e4..0c4c121d2e796 100644
--- a/drivers/block/umem.c
+++ b/drivers/block/umem.c
@@ -1181,7 +1181,7 @@ static struct pci_driver mm_pci_driver = {
-----------------------------------------------------------------------------------
*/
-int __init mm_init(void)
+static int __init mm_init(void)
{
int retval, i;
int err;
@@ -1232,7 +1232,7 @@ out:
-- mm_cleanup
-----------------------------------------------------------------------------------
*/
-void __exit mm_cleanup(void)
+static void __exit mm_cleanup(void)
{
int i;
diff --git a/drivers/block/viodasd.c b/drivers/block/viodasd.c
index fbc95a96f6e26..46e56a25d2c88 100644
--- a/drivers/block/viodasd.c
+++ b/drivers/block/viodasd.c
@@ -250,7 +250,6 @@ static int viodasd_release(struct inode *ino, struct file *fil)
static int viodasd_ioctl(struct inode *ino, struct file *fil,
unsigned int cmd, unsigned long arg)
{
- int err;
unsigned char sectors;
unsigned char heads;
unsigned short cylinders;
@@ -263,9 +262,8 @@ static int viodasd_ioctl(struct inode *ino, struct file *fil,
geo = (struct hd_geometry *)arg;
if (geo == NULL)
return -EINVAL;
- err = verify_area(VERIFY_WRITE, geo, sizeof(*geo));
- if (err)
- return err;
+ if (!access_ok(VERIFY_WRITE, geo, sizeof(*geo)))
+ return -EFAULT;
gendisk = ino->i_bdev->bd_disk;
d = gendisk->private_data;
sectors = d->sectors;
diff --git a/drivers/block/xd.c b/drivers/block/xd.c
index 3fbadc82ad43c..1676033da6c6f 100644
--- a/drivers/block/xd.c
+++ b/drivers/block/xd.c
@@ -67,7 +67,7 @@ static int xd[5] = { -1,-1,-1,-1, };
/* Above may need to be increased if a problem with the 2nd drive detection
(ST11M controller) or resetting a controller (WD) appears */
-XD_INFO xd_info[XD_MAXDRIVES];
+static XD_INFO xd_info[XD_MAXDRIVES];
/* If you try this driver and find that your card is not detected by the driver at bootup, you need to add your BIOS
signature and details to the following list of signatures. A BIOS signature is a string embedded into the first
diff --git a/drivers/bluetooth/bfusb.c b/drivers/bluetooth/bfusb.c
index 913f49e56a931..c42d7e6ac1c58 100644
--- a/drivers/bluetooth/bfusb.c
+++ b/drivers/bluetooth/bfusb.c
@@ -63,7 +63,7 @@ MODULE_DEVICE_TABLE(usb, bfusb_table);
#define BFUSB_MAX_BLOCK_SIZE 256
-#define BFUSB_BLOCK_TIMEOUT (HZ * 3)
+#define BFUSB_BLOCK_TIMEOUT 3000
#define BFUSB_TX_PROCESS 1
#define BFUSB_TX_WAKEUP 2
@@ -582,7 +582,7 @@ static int bfusb_load_firmware(struct bfusb *bfusb, unsigned char *firmware, int
pipe = usb_sndctrlpipe(bfusb->udev, 0);
if (usb_control_msg(bfusb->udev, pipe, USB_REQ_SET_CONFIGURATION,
- 0, 1, 0, NULL, 0, HZ * USB_CTRL_SET_TIMEOUT) < 0) {
+ 0, 1, 0, NULL, 0, USB_CTRL_SET_TIMEOUT) < 0) {
BT_ERR("Can't change to loading configuration");
return -EBUSY;
}
@@ -623,7 +623,7 @@ static int bfusb_load_firmware(struct bfusb *bfusb, unsigned char *firmware, int
pipe = usb_sndctrlpipe(bfusb->udev, 0);
if ((err = usb_control_msg(bfusb->udev, pipe, USB_REQ_SET_CONFIGURATION,
- 0, 2, 0, NULL, 0, HZ * USB_CTRL_SET_TIMEOUT)) < 0) {
+ 0, 2, 0, NULL, 0, USB_CTRL_SET_TIMEOUT)) < 0) {
BT_ERR("Can't change to running configuration");
goto error;
}
@@ -641,7 +641,7 @@ error:
pipe = usb_sndctrlpipe(bfusb->udev, 0);
usb_control_msg(bfusb->udev, pipe, USB_REQ_SET_CONFIGURATION,
- 0, 0, 0, NULL, 0, HZ * USB_CTRL_SET_TIMEOUT);
+ 0, 0, 0, NULL, 0, USB_CTRL_SET_TIMEOUT);
return err;
}
diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c
index 3b6df314ab040..e481cc411b5db 100644
--- a/drivers/bluetooth/bluecard_cs.c
+++ b/drivers/bluetooth/bluecard_cs.c
@@ -35,6 +35,7 @@
#include <linux/ioport.h>
#include <linux/spinlock.h>
#include <linux/moduleparam.h>
+#include <linux/wait.h>
#include <linux/skbuff.h>
#include <asm/io.h>
@@ -289,8 +290,9 @@ static void bluecard_write_wakeup(bluecard_info_t *info)
clear_bit(ready_bit, &(info->tx_state));
if (skb->pkt_type & 0x80) {
+ DECLARE_WAIT_QUEUE_HEAD(wq);
+ DEFINE_WAIT(wait);
- wait_queue_head_t wait;
unsigned char baud_reg;
switch (skb->pkt_type) {
@@ -311,8 +313,9 @@ static void bluecard_write_wakeup(bluecard_info_t *info)
}
/* Wait until the command reaches the baseband */
- init_waitqueue_head(&wait);
- interruptible_sleep_on_timeout(&wait, HZ / 10);
+ prepare_to_wait(&wq, &wait, TASK_INTERRUPTIBLE);
+ schedule_timeout(HZ/10);
+ finish_wait(&wq, &wait);
/* Set baud on baseband */
info->ctrl_reg &= ~0x03;
@@ -324,8 +327,9 @@ static void bluecard_write_wakeup(bluecard_info_t *info)
outb(info->ctrl_reg, iobase + REG_CONTROL);
/* Wait before the next HCI packet can be send */
- interruptible_sleep_on_timeout(&wait, HZ);
-
+ prepare_to_wait(&wq, &wait, TASK_INTERRUPTIBLE);
+ schedule_timeout(HZ);
+ finish_wait(&wq, &wait);
}
if (len == skb->len) {
diff --git a/drivers/bluetooth/hci_bcsp.c b/drivers/bluetooth/hci_bcsp.c
index 846cdffc4964d..c0ed213fc857d 100644
--- a/drivers/bluetooth/hci_bcsp.c
+++ b/drivers/bluetooth/hci_bcsp.c
@@ -28,7 +28,7 @@
* $Id: hci_bcsp.c,v 1.2 2002/09/26 05:05:14 maxk Exp $
*/
-#define VERSION "0.1"
+#define VERSION "0.2"
#include <linux/config.h>
#include <linux/module.h>
@@ -62,6 +62,8 @@
#define BT_DMP( A... )
#endif
+static int hciextn = 1;
+
/* ---- BCSP CRC calculation ---- */
/* Table for calculating CRC for polynomial 0x1021, LSB processed first,
@@ -158,12 +160,13 @@ static int bcsp_enqueue(struct hci_uart *hu, struct sk_buff *skb)
case HCI_SCODATA_PKT:
skb_queue_tail(&bcsp->unrel, skb);
break;
-
+
default:
BT_ERR("Unknown packet type");
kfree_skb(skb);
break;
}
+
return 0;
}
@@ -171,7 +174,7 @@ static struct sk_buff *bcsp_prepare_pkt(struct bcsp_struct *bcsp, u8 *data,
int len, int pkt_type)
{
struct sk_buff *nskb;
- u8 hdr[4], chan;
+ u8 hdr[4], chan;
int rel, i;
#ifdef CONFIG_BT_HCIUART_BCSP_TXCRC
@@ -204,6 +207,19 @@ static struct sk_buff *bcsp_prepare_pkt(struct bcsp_struct *bcsp, u8 *data,
return NULL;
}
+ if (hciextn && chan == 5) {
+ struct hci_command_hdr *hdr = (struct hci_command_hdr *) data;
+
+ if (hci_opcode_ogf(__le16_to_cpu(hdr->opcode)) == OGF_VENDOR_CMD) {
+ u8 desc = *(data + HCI_COMMAND_HDR_SIZE);
+ if ((desc & 0xf0) == 0xc0) {
+ data += HCI_COMMAND_HDR_SIZE + 1;
+ len -= HCI_COMMAND_HDR_SIZE + 1;
+ chan = desc & 0x0f;
+ }
+ }
+ }
+
/* Max len of packet: (original len +4(bcsp hdr) +2(crc))*2
(because bytes 0xc0 and 0xdb are escaped, worst case is
when the packet is all made of 0xc0 and 0xdb :) )
@@ -226,19 +242,18 @@ static struct sk_buff *bcsp_prepare_pkt(struct bcsp_struct *bcsp, u8 *data,
BT_DBG("Sending packet with seqno %u", bcsp->msgq_txseq);
bcsp->msgq_txseq = ++(bcsp->msgq_txseq) & 0x07;
}
-#ifdef CONFIG_BT_HCIUART_BCSP_TXCRC
+#ifdef CONFIG_BT_HCIUART_BCSP_TXCRC
hdr[0] |= 0x40;
#endif
- hdr[1] = (len << 4) & 0xFF;
- hdr[1] |= chan;
- hdr[2] = len >> 4;
- hdr[3] = ~(hdr[0] + hdr[1] + hdr[2]);
+ hdr[1] = ((len << 4) & 0xff) | chan;
+ hdr[2] = len >> 4;
+ hdr[3] = ~(hdr[0] + hdr[1] + hdr[2]);
/* Put BCSP header */
for (i = 0; i < 4; i++) {
bcsp_slip_one_byte(nskb, hdr[i]);
-#ifdef CONFIG_BT_HCIUART_BCSP_TXCRC
+#ifdef CONFIG_BT_HCIUART_BCSP_TXCRC
bcsp_crc_update(&bcsp_txmsg_crc, hdr[i]);
#endif
}
@@ -246,7 +261,7 @@ static struct sk_buff *bcsp_prepare_pkt(struct bcsp_struct *bcsp, u8 *data,
/* Put payload */
for (i = 0; i < len; i++) {
bcsp_slip_one_byte(nskb, data[i]);
-#ifdef CONFIG_BT_HCIUART_BCSP_TXCRC
+#ifdef CONFIG_BT_HCIUART_BCSP_TXCRC
bcsp_crc_update(&bcsp_txmsg_crc, data[i]);
#endif
}
@@ -487,14 +502,30 @@ static inline void bcsp_complete_rx_pkt(struct hci_uart *hu)
pass_up = 0;
if (!pass_up) {
- if ((bcsp->rx_skb->data[1] & 0x0f) != 0 &&
- (bcsp->rx_skb->data[1] & 0x0f) != 1) {
- BT_ERR ("Packet for unknown channel (%u %s)",
- bcsp->rx_skb->data[1] & 0x0f,
- bcsp->rx_skb->data[0] & 0x80 ?
- "reliable" : "unreliable");
- }
- kfree_skb(bcsp->rx_skb);
+ struct hci_event_hdr hdr;
+ u8 desc = (bcsp->rx_skb->data[1] & 0x0f);
+
+ if (desc != 0 && desc != 1) {
+ if (hciextn) {
+ desc |= 0xc0;
+ skb_pull(bcsp->rx_skb, 4);
+ memcpy(skb_push(bcsp->rx_skb, 1), &desc, 1);
+
+ hdr.evt = 0xff;
+ hdr.plen = bcsp->rx_skb->len;
+ memcpy(skb_push(bcsp->rx_skb, HCI_EVENT_HDR_SIZE), &hdr, HCI_EVENT_HDR_SIZE);
+ bcsp->rx_skb->pkt_type = HCI_EVENT_PKT;
+
+ hci_recv_frame(bcsp->rx_skb);
+ } else {
+ BT_ERR ("Packet for unknown channel (%u %s)",
+ bcsp->rx_skb->data[1] & 0x0f,
+ bcsp->rx_skb->data[0] & 0x80 ?
+ "reliable" : "unreliable");
+ kfree_skb(bcsp->rx_skb);
+ }
+ } else
+ kfree_skb(bcsp->rx_skb);
} else {
/* Pull out BCSP hdr */
skb_pull(bcsp->rx_skb, 4);
@@ -713,3 +744,6 @@ int bcsp_deinit(void)
{
return hci_uart_unregister_proto(&bcsp);
}
+
+module_param(hciextn, bool, 0644);
+MODULE_PARM_DESC(hciextn, "Convert HCI Extensions into BCSP packets");
diff --git a/drivers/bluetooth/hci_usb.c b/drivers/bluetooth/hci_usb.c
index 4c8e968651f07..b120ecf7b8c96 100644
--- a/drivers/bluetooth/hci_usb.c
+++ b/drivers/bluetooth/hci_usb.c
@@ -888,7 +888,7 @@ static int hci_usb_probe(struct usb_interface *intf, const struct usb_device_id
isoc_ifnum = 1;
#ifdef CONFIG_BT_HCIUSB_SCO
- if (isoc && !(id->driver_info & HCI_BROKEN_ISOC))
+ if (isoc && !(id->driver_info & (HCI_BROKEN_ISOC | HCI_SNIFFER)))
isoc_iface = usb_ifnum_to_if(udev, isoc_ifnum);
if (isoc_iface) {
diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c
index 3b9f7a5344975..3256192dcde8f 100644
--- a/drivers/bluetooth/hci_vhci.c
+++ b/drivers/bluetooth/hci_vhci.c
@@ -157,7 +157,7 @@ static ssize_t hci_vhci_chr_write(struct file * file, const char __user * buf,
{
struct hci_vhci_struct *hci_vhci = (struct hci_vhci_struct *) file->private_data;
- if (verify_area(VERIFY_READ, buf, count))
+ if (!access_ok(VERIFY_READ, buf, count))
return -EFAULT;
return hci_vhci_get_user(hci_vhci, buf, count);
@@ -222,7 +222,7 @@ static ssize_t hci_vhci_chr_read(struct file * file, char __user * buf, size_t c
continue;
}
- if (!verify_area(VERIFY_WRITE, buf, count))
+ if (access_ok(VERIFY_WRITE, buf, count))
ret = hci_vhci_put_user(hci_vhci, skb, buf, count);
else
ret = -EFAULT;
@@ -308,12 +308,13 @@ static int hci_vhci_chr_open(struct inode *inode, struct file * file)
static int hci_vhci_chr_close(struct inode *inode, struct file *file)
{
struct hci_vhci_struct *hci_vhci = (struct hci_vhci_struct *) file->private_data;
+ struct hci_dev *hdev = hci_vhci->hdev;
- if (hci_unregister_dev(hci_vhci->hdev) < 0) {
- BT_ERR("Can't unregister HCI device %s", hci_vhci->hdev->name);
+ if (hci_unregister_dev(hdev) < 0) {
+ BT_ERR("Can't unregister HCI device %s", hdev->name);
}
- hci_free_dev(hci_vhci->hdev);
+ hci_free_dev(hdev);
file->private_data = NULL;
return 0;
diff --git a/drivers/cdrom/Kconfig b/drivers/cdrom/Kconfig
index 455a9a19ff198..ff5652d40619e 100644
--- a/drivers/cdrom/Kconfig
+++ b/drivers/cdrom/Kconfig
@@ -103,60 +103,14 @@ config SBPCD
To compile this driver as a module, choose M here: the
module will be called sbpcd.
-config MCD
- tristate "Mitsumi (standard) [no XA/Multisession] CDROM support"
- depends on CD_NO_IDESCSI && BROKEN
- ---help---
- This is the older of the two drivers for the older Mitsumi models
- LU-005, FX-001 and FX-001D. This is not the right driver for the
- FX-001DE and the triple or quad speed models (all these are
- IDE/ATAPI models). Please also the file
- <file:Documentation/cdrom/mcd>.
-
- With the old LU-005 model, the whole drive chassis slides out for cd
- insertion. The FX-xxx models use a motorized tray type mechanism.
- Note that this driver does not support XA or MultiSession CDs
- (PhotoCDs). There is a new driver (next question) which can do
- this. If you want that one, say N here.
-
- If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM
- file system support" below, because that's the file system used on
- CD-ROMs.
-
- To compile this driver as a module, choose M here: the
- module will be called mcd.
-
-config MCD_IRQ
- int "MCD IRQ"
- depends on MCD
- default "11"
- help
- This allows you to specify the default value of the IRQ used by the
- driver. This setting can be overridden by passing the "mcd="
- parameter to the kernel at boot time (or at module load time if you
- said M to "Standard Mitsumi CD-ROM support").
-
-config MCD_BASE
- hex "MCD I/O base"
- depends on MCD
- default "300"
- help
- This allows you to specify the default value of the I/O base address
- used by the driver. This setting can be overridden by passing the
- "mcd=" parameter to the kernel at boot time (or at module load time
- if you said M to "Standard Mitsumi CD-ROM support").
-
config MCDX
- tristate "Mitsumi [XA/MultiSession] CDROM support"
+ tristate "Mitsumi CDROM support"
depends on CD_NO_IDESCSI
---help---
- Use this driver if you want to be able to read XA or MultiSession
- CDs (PhotoCDs) as well as ordinary CDs with your Mitsumi LU-005,
- FX-001 or FX-001D CD-ROM drive. In addition, this driver uses much
- less kernel memory than the old one, if that is a concern. This
- driver is able to support more than one drive, but each drive needs
- a separate interface card. Please read the file
- <file:Documentation/cdrom/mcdx>.
+ Use this driver if you want to be able to use your Mitsumi LU-005,
+ FX-001 or FX-001D CD-ROM drive.
+
+ Please read the file <file:Documentation/cdrom/mcdx>.
If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM
file system support" below, because that's the file system used on
diff --git a/drivers/cdrom/Makefile b/drivers/cdrom/Makefile
index 4a8351753e07c..d1d1e5a4be73b 100644
--- a/drivers/cdrom/Makefile
+++ b/drivers/cdrom/Makefile
@@ -15,7 +15,6 @@ obj-$(CONFIG_CDU31A) += cdu31a.o cdrom.o
obj-$(CONFIG_CM206) += cm206.o cdrom.o
obj-$(CONFIG_GSCD) += gscd.o
obj-$(CONFIG_ISP16_CDI) += isp16.o
-obj-$(CONFIG_MCD) += mcd.o cdrom.o
obj-$(CONFIG_MCDX) += mcdx.o cdrom.o
obj-$(CONFIG_OPTCD) += optcd.o
obj-$(CONFIG_SBPCD) += sbpcd.o cdrom.o
diff --git a/drivers/cdrom/cdu31a.c b/drivers/cdrom/cdu31a.c
index d729ae4b3f15f..647a71b12a2a3 100644
--- a/drivers/cdrom/cdu31a.c
+++ b/drivers/cdrom/cdu31a.c
@@ -148,10 +148,10 @@
* Ondrej Zary <rainbow@rainbow-software.org>
*/
-#include <linux/major.h>
+#define DEBUG 1
+#include <linux/major.h>
#include <linux/module.h>
-
#include <linux/errno.h>
#include <linux/signal.h>
#include <linux/sched.h>
@@ -166,13 +166,13 @@
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/interrupt.h>
+#include <linux/cdrom.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/dma.h>
-#include <linux/cdrom.h>
#include "cdu31a.h"
#define MAJOR_NR CDU31A_CDROM_MAJOR
@@ -180,10 +180,7 @@
#define CDU31A_MAX_CONSECUTIVE_ATTENTIONS 10
-#define DEBUG 1
-
-/* Define the following if you have data corruption problems. */
-#undef SONY_POLL_EACH_BYTE
+#define PFX "CDU31A: "
/*
** Edit the following data to change interrupts, DMA channels, etc.
@@ -267,14 +264,7 @@ static int sony_toc_read = 0; /* Has the TOC been read for
static struct s_sony_subcode last_sony_subcode; /* Points to the last
subcode address read */
-static volatile int sony_inuse = 0; /* Is the drive in use? Only one operation
- at a time allowed */
-
-static DECLARE_WAIT_QUEUE_HEAD(sony_wait); /* Things waiting for the drive */
-
-static struct task_struct *has_cd_task = NULL; /* The task that is currently
- using the CDROM drive, or
- NULL if none. */
+static DECLARE_MUTEX(sony_sem); /* Semaphore for drive hardware access */
static int is_double_speed = 0; /* does the drive support double speed ? */
@@ -303,6 +293,7 @@ module_param(cdu31a_irq, int, 0);
/* The interrupt handler will wake this queue up when it gets an
interrupts. */
DECLARE_WAIT_QUEUE_HEAD(cdu31a_irq_wait);
+static int irq_flag = 0;
static int curr_control_reg = 0; /* Current value of the control register */
@@ -344,13 +335,16 @@ static int scd_media_changed(struct cdrom_device_info *cdi, int disc_nr)
*/
static int scd_drive_status(struct cdrom_device_info *cdi, int slot_nr)
{
- if (CDSL_CURRENT != slot_nr) {
+ if (CDSL_CURRENT != slot_nr)
/* we have no changer support */
return -EINVAL;
- }
- if (scd_spinup() == 0) {
+ if (sony_spun_up)
+ return CDS_DISC_OK;
+ if (down_interruptible(&sony_sem))
+ return -ERESTARTSYS;
+ if (scd_spinup() == 0)
sony_spun_up = 1;
- }
+ up(&sony_sem);
return sony_spun_up ? CDS_DISC_OK : CDS_DRIVE_NOT_READY;
}
@@ -376,17 +370,31 @@ static inline void disable_interrupts(void)
*/
static inline void sony_sleep(void)
{
- unsigned long flags;
-
if (cdu31a_irq <= 0) {
yield();
} else { /* Interrupt driven */
+ DEFINE_WAIT(w);
+ int first = 1;
- save_flags(flags);
- cli();
- enable_interrupts();
- interruptible_sleep_on(&cdu31a_irq_wait);
- restore_flags(flags);
+ while (1) {
+ prepare_to_wait(&cdu31a_irq_wait, &w,
+ TASK_INTERRUPTIBLE);
+ if (first) {
+ enable_interrupts();
+ first = 0;
+ }
+
+ if (irq_flag != 0)
+ break;
+ if (!signal_pending(current)) {
+ schedule();
+ continue;
+ } else
+ disable_interrupts();
+ break;
+ }
+ finish_wait(&cdu31a_irq_wait, &w);
+ irq_flag = 0;
}
}
@@ -397,37 +405,37 @@ static inline void sony_sleep(void)
*/
static inline int is_attention(void)
{
- return ((inb(sony_cd_status_reg) & SONY_ATTN_BIT) != 0);
+ return (inb(sony_cd_status_reg) & SONY_ATTN_BIT) != 0;
}
static inline int is_busy(void)
{
- return ((inb(sony_cd_status_reg) & SONY_BUSY_BIT) != 0);
+ return (inb(sony_cd_status_reg) & SONY_BUSY_BIT) != 0;
}
static inline int is_data_ready(void)
{
- return ((inb(sony_cd_status_reg) & SONY_DATA_RDY_BIT) != 0);
+ return (inb(sony_cd_status_reg) & SONY_DATA_RDY_BIT) != 0;
}
static inline int is_data_requested(void)
{
- return ((inb(sony_cd_status_reg) & SONY_DATA_REQUEST_BIT) != 0);
+ return (inb(sony_cd_status_reg) & SONY_DATA_REQUEST_BIT) != 0;
}
static inline int is_result_ready(void)
{
- return ((inb(sony_cd_status_reg) & SONY_RES_RDY_BIT) != 0);
+ return (inb(sony_cd_status_reg) & SONY_RES_RDY_BIT) != 0;
}
static inline int is_param_write_rdy(void)
{
- return ((inb(sony_cd_fifost_reg) & SONY_PARAM_WRITE_RDY_BIT) != 0);
+ return (inb(sony_cd_fifost_reg) & SONY_PARAM_WRITE_RDY_BIT) != 0;
}
static inline int is_result_reg_not_empty(void)
{
- return ((inb(sony_cd_fifost_reg) & SONY_RES_REG_NOT_EMP_BIT) != 0);
+ return (inb(sony_cd_fifost_reg) & SONY_RES_REG_NOT_EMP_BIT) != 0;
}
static inline void reset_drive(void)
@@ -445,6 +453,8 @@ static int scd_reset(struct cdrom_device_info *cdi)
{
unsigned long retry_count;
+ if (down_interruptible(&sony_sem))
+ return -ERESTARTSYS;
reset_drive();
retry_count = jiffies + SONY_RESET_TIMEOUT;
@@ -452,6 +462,7 @@ static int scd_reset(struct cdrom_device_info *cdi)
sony_sleep();
}
+ up(&sony_sem);
return 0;
}
@@ -478,17 +489,17 @@ static inline void clear_param_reg(void)
static inline unsigned char read_status_register(void)
{
- return (inb(sony_cd_status_reg));
+ return inb(sony_cd_status_reg);
}
static inline unsigned char read_result_register(void)
{
- return (inb(sony_cd_result_reg));
+ return inb(sony_cd_result_reg);
}
static inline unsigned char read_data_register(void)
{
- return (inb(sony_cd_read_reg));
+ return inb(sony_cd_read_reg);
}
static inline void write_param(unsigned char param)
@@ -527,15 +538,17 @@ static irqreturn_t cdu31a_interrupt(int irq, void *dev_id, struct pt_regs *regs)
/* If something was waiting, wake it up now. */
if (waitqueue_active(&cdu31a_irq_wait)) {
disable_interrupts();
- wake_up(&cdu31a_irq_wait);
+ irq_flag = 1;
+ wake_up_interruptible(&cdu31a_irq_wait);
}
} else if (waitqueue_active(&cdu31a_irq_wait)) {
disable_interrupts();
- wake_up(&cdu31a_irq_wait);
+ irq_flag = 1;
+ wake_up_interruptible(&cdu31a_irq_wait);
} else {
disable_interrupts();
- printk
- ("CDU31A: Got an interrupt but nothing was waiting\n");
+ printk(KERN_NOTICE PFX
+ "Got an interrupt but nothing was waiting\n");
}
return IRQ_HANDLED;
}
@@ -610,8 +623,8 @@ static void set_drive_params(int want_doublespeed)
do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD,
params, 2, res_reg, &res_size);
if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20)) {
- printk(" Unable to set spin-down time: 0x%2.2x\n",
- res_reg[1]);
+ printk(KERN_NOTICE PFX
+ "Unable to set spin-down time: 0x%2.2x\n", res_reg[1]);
}
params[0] = SONY_SD_MECH_CONTROL;
@@ -627,8 +640,8 @@ static void set_drive_params(int want_doublespeed)
do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD,
params, 2, res_reg, &res_size);
if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20)) {
- printk(" Unable to set mechanical parameters: 0x%2.2x\n",
- res_reg[1]);
+ printk(KERN_NOTICE PFX "Unable to set mechanical "
+ "parameters: 0x%2.2x\n", res_reg[1]);
}
}
@@ -643,7 +656,10 @@ static int scd_select_speed(struct cdrom_device_info *cdi, int speed)
else
sony_speed = speed - 1;
+ if (down_interruptible(&sony_sem))
+ return -ERESTARTSYS;
set_drive_params(sony_speed);
+ up(&sony_sem);
return 0;
}
@@ -658,7 +674,10 @@ static int scd_lock_door(struct cdrom_device_info *cdi, int lock)
} else {
is_auto_eject = 0;
}
+ if (down_interruptible(&sony_sem))
+ return -ERESTARTSYS;
set_drive_params(sony_speed);
+ up(&sony_sem);
return 0;
}
@@ -672,7 +691,7 @@ static void restart_on_error(void)
unsigned long retry_count;
- printk("cdu31a: Resetting drive on error\n");
+ printk(KERN_NOTICE PFX "Resetting drive on error\n");
reset_drive();
retry_count = jiffies + SONY_RESET_TIMEOUT;
while (time_before(jiffies, retry_count) && (!is_attention())) {
@@ -681,7 +700,7 @@ static void restart_on_error(void)
set_drive_params(sony_speed);
do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg, &res_size);
if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20)) {
- printk("cdu31a: Unable to spin up drive: 0x%2.2x\n",
+ printk(KERN_NOTICE PFX "Unable to spin up drive: 0x%2.2x\n",
res_reg[1]);
}
@@ -741,9 +760,7 @@ get_result(unsigned char *result_buffer, unsigned int *result_size)
while (handle_sony_cd_attention());
}
if (is_busy() || (!(is_result_ready()))) {
-#if DEBUG
- printk("CDU31A timeout out %d\n", __LINE__);
-#endif
+ pr_debug(PFX "timeout out %d\n", __LINE__);
result_buffer[0] = 0x20;
result_buffer[1] = SONY_TIMEOUT_OP_ERR;
*result_size = 2;
@@ -794,10 +811,8 @@ get_result(unsigned char *result_buffer, unsigned int *result_size)
retry_count--;
}
if (!is_result_ready()) {
-#if DEBUG
- printk("CDU31A timeout out %d\n",
+ pr_debug(PFX "timeout out %d\n",
__LINE__);
-#endif
result_buffer[0] = 0x20;
result_buffer[1] =
SONY_TIMEOUT_OP_ERR;
@@ -823,10 +838,8 @@ get_result(unsigned char *result_buffer, unsigned int *result_size)
retry_count--;
}
if (!is_result_ready()) {
-#if DEBUG
- printk("CDU31A timeout out %d\n",
+ pr_debug(PFX "timeout out %d\n",
__LINE__);
-#endif
result_buffer[0] = 0x20;
result_buffer[1] =
SONY_TIMEOUT_OP_ERR;
@@ -857,38 +870,12 @@ do_sony_cd_cmd(unsigned char cmd,
unsigned char *result_buffer, unsigned int *result_size)
{
unsigned long retry_count;
- int num_retries;
- int recursive_call;
- unsigned long flags;
-
-
- save_flags(flags);
- cli();
- if (current != has_cd_task) { /* Allow recursive calls to this routine */
- while (sony_inuse) {
- interruptible_sleep_on(&sony_wait);
- if (signal_pending(current)) {
- result_buffer[0] = 0x20;
- result_buffer[1] = SONY_SIGNAL_OP_ERR;
- *result_size = 2;
- restore_flags(flags);
- return;
- }
- }
- sony_inuse = 1;
- has_cd_task = current;
- recursive_call = 0;
- } else {
- recursive_call = 1;
- }
+ int num_retries = 0;
- num_retries = 0;
retry_cd_operation:
while (handle_sony_cd_attention());
- sti();
-
retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
while (time_before(jiffies, retry_count) && (is_busy())) {
sony_sleep();
@@ -896,9 +883,7 @@ retry_cd_operation:
while (handle_sony_cd_attention());
}
if (is_busy()) {
-#if DEBUG
- printk("CDU31A timeout out %d\n", __LINE__);
-#endif
+ pr_debug(PFX "timeout out %d\n", __LINE__);
result_buffer[0] = 0x20;
result_buffer[1] = SONY_TIMEOUT_OP_ERR;
*result_size = 2;
@@ -918,14 +903,6 @@ retry_cd_operation:
msleep(100);
goto retry_cd_operation;
}
-
- if (!recursive_call) {
- has_cd_task = NULL;
- sony_inuse = 0;
- wake_up_interruptible(&sony_wait);
- }
-
- restore_flags(flags);
}
@@ -945,21 +922,18 @@ static int handle_sony_cd_attention(void)
volatile int val;
-#if 0*DEBUG
- printk("Entering handle_sony_cd_attention\n");
+#if 0
+ pr_debug(PFX "Entering %s\n", __FUNCTION__);
#endif
if (is_attention()) {
if (num_consecutive_attentions >
CDU31A_MAX_CONSECUTIVE_ATTENTIONS) {
- printk
- ("cdu31a: Too many consecutive attentions: %d\n",
- num_consecutive_attentions);
+ printk(KERN_NOTICE PFX "Too many consecutive "
+ "attentions: %d\n", num_consecutive_attentions);
num_consecutive_attentions = 0;
-#if DEBUG
- printk("Leaving handle_sony_cd_attention at %d\n",
+ pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__,
__LINE__);
-#endif
- return (0);
+ return 0;
}
clear_attention();
@@ -999,11 +973,8 @@ static int handle_sony_cd_attention(void)
}
num_consecutive_attentions++;
-#if DEBUG
- printk("Leaving handle_sony_cd_attention at %d\n",
- __LINE__);
-#endif
- return (1);
+ pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__);
+ return 1;
} else if (abort_read_started) {
while (is_result_reg_not_empty()) {
val = read_result_register();
@@ -1015,18 +986,15 @@ static int handle_sony_cd_attention(void)
val = read_data_register();
}
abort_read_started = 0;
-#if DEBUG
- printk("Leaving handle_sony_cd_attention at %d\n",
- __LINE__);
-#endif
- return (1);
+ pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__);
+ return 1;
}
num_consecutive_attentions = 0;
-#if 0*DEBUG
- printk("Leaving handle_sony_cd_attention at %d\n", __LINE__);
+#if 0
+ pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__);
#endif
- return (0);
+ return 0;
}
@@ -1038,14 +1006,14 @@ static inline unsigned int int_to_bcd(unsigned int val)
retval = (val / 10) << 4;
retval = retval | val % 10;
- return (retval);
+ return retval;
}
/* Convert from BCD to an integer from 0-99 */
static unsigned int bcd_to_int(unsigned int bcd)
{
- return ((((bcd >> 4) & 0x0f) * 10) + (bcd & 0x0f));
+ return (((bcd >> 4) & 0x0f) * 10) + (bcd & 0x0f);
}
@@ -1105,9 +1073,7 @@ start_request(unsigned int sector, unsigned int nsect)
unsigned long retry_count;
-#if DEBUG
- printk("Entering start_request\n");
-#endif
+ pr_debug(PFX "Entering %s\n", __FUNCTION__);
log_to_msf(sector, params);
size_to_buf(nsect, &params[3]);
@@ -1125,11 +1091,10 @@ start_request(unsigned int sector, unsigned int nsect)
}
if (is_busy()) {
- printk("CDU31A: Timeout while waiting to issue command\n");
-#if DEBUG
- printk("Leaving start_request at %d\n", __LINE__);
-#endif
- return (1);
+ printk(KERN_NOTICE PFX "Timeout while waiting "
+ "to issue command\n");
+ pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__);
+ return 1;
} else {
/* Issue the command */
clear_result_ready();
@@ -1140,14 +1105,10 @@ start_request(unsigned int sector, unsigned int nsect)
sony_blocks_left = nsect * 4;
sony_next_block = sector * 4;
-#if DEBUG
- printk("Leaving start_request at %d\n", __LINE__);
-#endif
- return (0);
+ pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__);
+ return 0;
}
-#if DEBUG
- printk("Leaving start_request at %d\n", __LINE__);
-#endif
+ pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__);
}
/* Abort a pending read operation. Clear all the drive status variables. */
@@ -1160,7 +1121,7 @@ static void abort_read(void)
do_sony_cd_cmd(SONY_ABORT_CMD, NULL, 0, result_reg, &result_size);
if ((result_reg[0] & 0xf0) == 0x20) {
- printk("CDU31A: Error aborting read, %s error\n",
+ printk(KERN_ERR PFX "Aborting read, %s error\n",
translate_error(result_reg[1]));
}
@@ -1181,15 +1142,9 @@ static void abort_read(void)
pending read operation. */
static void handle_abort_timeout(unsigned long data)
{
- unsigned long flags;
-
-#if DEBUG
- printk("Entering handle_abort_timeout\n");
-#endif
- save_flags(flags);
- cli();
+ pr_debug(PFX "Entering %s\n", __FUNCTION__);
/* If it is in use, ignore it. */
- if (!sony_inuse) {
+ if (down_trylock(&sony_sem) == 0) {
/* We can't use abort_read(), because it will sleep
or schedule in the timer interrupt. Just start
the operation, finish it on the next access to
@@ -1200,20 +1155,16 @@ static void handle_abort_timeout(unsigned long data)
sony_blocks_left = 0;
abort_read_started = 1;
+ up(&sony_sem);
}
- restore_flags(flags);
-#if DEBUG
- printk("Leaving handle_abort_timeout\n");
-#endif
+ pr_debug(PFX "Leaving %s\n", __FUNCTION__);
}
/* Actually get one sector of data from the drive. */
static void
input_data_sector(char *buffer)
{
-#if DEBUG
- printk("Entering input_data_sector\n");
-#endif
+ pr_debug(PFX "Entering %s\n", __FUNCTION__);
/* If an XA disk on a CDU31A, skip the first 12 bytes of data from
the disk. The real data is after that. We can use audio_buffer. */
@@ -1229,9 +1180,7 @@ input_data_sector(char *buffer)
if (sony_xa_mode)
insb(sony_cd_read_reg, audio_buffer, CD_XA_TAIL);
-#if DEBUG
- printk("Leaving input_data_sector\n");
-#endif
+ pr_debug(PFX "Leaving %s\n", __FUNCTION__);
}
/* read data from the drive. Note the nsect must be <= 4. */
@@ -1243,9 +1192,7 @@ read_data_block(char *buffer,
{
unsigned long retry_count;
-#if DEBUG
- printk("Entering read_data_block\n");
-#endif
+ pr_debug(PFX "Entering %s\n", __FUNCTION__);
res_reg[0] = 0;
res_reg[1] = 0;
@@ -1262,18 +1209,15 @@ read_data_block(char *buffer,
if (is_result_ready()) {
get_result(res_reg, res_size);
if ((res_reg[0] & 0xf0) != 0x20) {
- printk
- ("CDU31A: Got result that should have been error: %d\n",
- res_reg[0]);
+ printk(KERN_NOTICE PFX "Got result that should"
+ " have been error: %d\n", res_reg[0]);
res_reg[0] = 0x20;
res_reg[1] = SONY_BAD_DATA_ERR;
*res_size = 2;
}
abort_read();
} else {
-#if DEBUG
- printk("CDU31A timeout out %d\n", __LINE__);
-#endif
+ pr_debug(PFX "timeout out %d\n", __LINE__);
res_reg[0] = 0x20;
res_reg[1] = SONY_TIMEOUT_OP_ERR;
*res_size = 2;
@@ -1294,9 +1238,7 @@ read_data_block(char *buffer,
}
if (!is_result_ready()) {
-#if DEBUG
- printk("CDU31A timeout out %d\n", __LINE__);
-#endif
+ pr_debug(PFX "timeout out %d\n", __LINE__);
res_reg[0] = 0x20;
res_reg[1] = SONY_TIMEOUT_OP_ERR;
*res_size = 2;
@@ -1315,9 +1257,8 @@ read_data_block(char *buffer,
SONY_RECOV_LECC_ERR_BLK_STAT)) {
/* nothing here */
} else {
- printk
- ("CDU31A: Data block error: 0x%x\n",
- res_reg[0]);
+ printk(KERN_ERR PFX "Data block "
+ "error: 0x%x\n", res_reg[0]);
res_reg[0] = 0x20;
res_reg[1] = SONY_BAD_DATA_ERR;
*res_size = 2;
@@ -1330,9 +1271,8 @@ read_data_block(char *buffer,
} else if ((res_reg[0] & 0xf0) != 0x20) {
/* The drive gave me bad status, I don't know what to do.
Reset the driver and return an error. */
- printk
- ("CDU31A: Invalid block status: 0x%x\n",
- res_reg[0]);
+ printk(KERN_ERR PFX "Invalid block "
+ "status: 0x%x\n", res_reg[0]);
restart_on_error();
res_reg[0] = 0x20;
res_reg[1] = SONY_BAD_DATA_ERR;
@@ -1340,9 +1280,7 @@ read_data_block(char *buffer,
}
}
}
-#if DEBUG
- printk("Leaving read_data_block at %d\n", __LINE__);
-#endif
+ pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__);
}
@@ -1359,32 +1297,14 @@ static void do_cdu31a_request(request_queue_t * q)
int block, nblock, num_retries;
unsigned char res_reg[12];
unsigned int res_size;
- unsigned long flags;
+ pr_debug(PFX "Entering %s\n", __FUNCTION__);
-#if DEBUG
- printk("Entering do_cdu31a_request\n");
-#endif
-
- /*
- * Make sure no one else is using the driver; wait for them
- * to finish if it is so.
- */
- save_flags(flags);
- cli();
- while (sony_inuse) {
- interruptible_sleep_on(&sony_wait);
- if (signal_pending(current)) {
- restore_flags(flags);
-#if DEBUG
- printk("Leaving do_cdu31a_request at %d\n",
- __LINE__);
-#endif
- return;
- }
+ spin_unlock_irq(q->queue_lock);
+ if (down_interruptible(&sony_sem)) {
+ spin_lock_irq(q->queue_lock);
+ return;
}
- sony_inuse = 1;
- has_cd_task = current;
/* Get drive status before doing anything. */
while (handle_sony_cd_attention());
@@ -1392,10 +1312,6 @@ static void do_cdu31a_request(request_queue_t * q)
/* Make sure we have a valid TOC. */
sony_get_toc();
- /*
- * jens: driver has lots of races
- */
- spin_unlock_irq(q->queue_lock);
/* Make sure the timer is cancelled. */
del_timer(&cdu31a_abort_timer);
@@ -1414,12 +1330,10 @@ static void do_cdu31a_request(request_queue_t * q)
block = req->sector;
nblock = req->nr_sectors;
-#if DEBUG
- printk("CDU31A: request at block %d, length %d blocks\n",
+ pr_debug(PFX "request at block %d, length %d blocks\n",
block, nblock);
-#endif
if (!sony_toc_read) {
- printk("CDU31A: TOC not read\n");
+ printk(KERN_NOTICE PFX "TOC not read\n");
end_request(req, 0);
continue;
}
@@ -1431,14 +1345,13 @@ static void do_cdu31a_request(request_queue_t * q)
end_request(req, 0);
continue;
}
- if (rq_data_dir(req) != READ)
- panic("CDU31A: Unknown cmd");
+
/*
* If the block address is invalid or the request goes beyond the end of
* the media, return an error.
*/
if (((block + nblock) / 4) >= sony_toc.lead_out_start_lba) {
- printk("CDU31A: Request past end of media\n");
+ printk(KERN_NOTICE PFX "Request past end of media\n");
end_request(req, 0);
continue;
}
@@ -1451,7 +1364,7 @@ static void do_cdu31a_request(request_queue_t * q)
while (handle_sony_cd_attention());
if (!sony_toc_read) {
- printk("CDU31A: TOC not read\n");
+ printk(KERN_NOTICE PFX "TOC not read\n");
end_request(req, 0);
continue;
}
@@ -1468,18 +1381,16 @@ static void do_cdu31a_request(request_queue_t * q)
the driver, abort the current operation and start a
new one. */
else if (block != sony_next_block) {
-#if DEBUG
- printk("CDU31A Warning: Read for block %d, expected %d\n",
+ pr_debug(PFX "Read for block %d, expected %d\n",
block, sony_next_block);
-#endif
abort_read();
if (!sony_toc_read) {
- printk("CDU31A: TOC not read\n");
+ printk(KERN_NOTICE PFX "TOC not read\n");
end_request(req, 0);
continue;
}
if (start_request(block / 4, nblock / 4)) {
- printk("CDU31a: start request failed\n");
+ printk(KERN_NOTICE PFX "start request failed\n");
end_request(req, 0);
continue;
}
@@ -1507,13 +1418,12 @@ static void do_cdu31a_request(request_queue_t * q)
do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg,
&res_size);
} else {
- printk("CDU31A: %s error for block %d, nblock %d\n",
+ printk(KERN_NOTICE PFX "%s error for block %d, nblock %d\n",
translate_error(res_reg[1]), block, nblock);
}
goto try_read_again;
}
end_do_cdu31a_request:
- spin_lock_irq(q->queue_lock);
#if 0
/* After finished, cancel any pending operations. */
abort_read();
@@ -1524,13 +1434,9 @@ static void do_cdu31a_request(request_queue_t * q)
add_timer(&cdu31a_abort_timer);
#endif
- has_cd_task = NULL;
- sony_inuse = 0;
- wake_up_interruptible(&sony_wait);
- restore_flags(flags);
-#if DEBUG
- printk("Leaving do_cdu31a_request at %d\n", __LINE__);
-#endif
+ up(&sony_sem);
+ spin_lock_irq(q->queue_lock);
+ pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__);
}
@@ -1549,9 +1455,7 @@ static void sony_get_toc(void)
int mint = 99;
int maxt = 0;
-#if DEBUG
- printk("Entering sony_get_toc\n");
-#endif
+ pr_debug(PFX "Entering %s\n", __FUNCTION__);
num_spin_ups = 0;
if (!sony_toc_read) {
@@ -1602,16 +1506,12 @@ static void sony_get_toc(void)
/* This seems to slow things down enough to make it work. This
* appears to be a problem in do_sony_cd_cmd. This printk seems
* to address the symptoms... -Erik */
-#if DEBUG
- printk("cdu31a: Trying session %d\n", session);
-#endif
+ pr_debug(PFX "Trying session %d\n", session);
parms[0] = session;
do_sony_cd_cmd(SONY_READ_TOC_SPEC_CMD,
parms, 1, res_reg, &res_size);
-#if DEBUG
- printk("%2.2x %2.2x\n", res_reg[0], res_reg[1]);
-#endif
+ pr_debug(PFX "%2.2x %2.2x\n", res_reg[0], res_reg[1]);
if ((res_size < 2)
|| ((res_reg[0] & 0xf0) == 0x20)) {
@@ -1621,9 +1521,7 @@ static void sony_get_toc(void)
("Yikes! Couldn't read any sessions!");
break;
}
-#if DEBUG
- printk("Reading session %d\n", session);
-#endif
+ pr_debug(PFX "Reading session %d\n", session);
parms[0] = session;
do_sony_cd_cmd(SONY_REQ_TOC_DATA_SPEC_CMD,
@@ -1634,8 +1532,8 @@ static void sony_get_toc(void)
if ((res_size < 2)
|| ((single_toc.exec_status[0] & 0xf0) ==
0x20)) {
- printk
- ("cdu31a: Error reading session %d: %x %s\n",
+ printk(KERN_ERR PFX "Error reading "
+ "session %d: %x %s\n",
session, single_toc.exec_status[0],
translate_error(single_toc.
exec_status[1]));
@@ -1643,29 +1541,27 @@ static void sony_get_toc(void)
set. */
return;
}
-#if DEBUG
- printk
- ("add0 %01x, con0 %01x, poi0 %02x, 1st trk %d, dsktyp %x, dum0 %x\n",
+ pr_debug(PFX "add0 %01x, con0 %01x, poi0 %02x, "
+ "1st trk %d, dsktyp %x, dum0 %x\n",
single_toc.address0, single_toc.control0,
single_toc.point0,
bcd_to_int(single_toc.first_track_num),
single_toc.disk_type, single_toc.dummy0);
- printk
- ("add1 %01x, con1 %01x, poi1 %02x, lst trk %d, dummy1 %x, dum2 %x\n",
+ pr_debug(PFX "add1 %01x, con1 %01x, poi1 %02x, "
+ "lst trk %d, dummy1 %x, dum2 %x\n",
single_toc.address1, single_toc.control1,
single_toc.point1,
bcd_to_int(single_toc.last_track_num),
single_toc.dummy1, single_toc.dummy2);
- printk
- ("add2 %01x, con2 %01x, poi2 %02x leadout start min %d, sec %d, frame %d\n",
+ pr_debug(PFX "add2 %01x, con2 %01x, poi2 %02x "
+ "leadout start min %d, sec %d, frame %d\n",
single_toc.address2, single_toc.control2,
single_toc.point2,
bcd_to_int(single_toc.lead_out_start_msf[0]),
bcd_to_int(single_toc.lead_out_start_msf[1]),
bcd_to_int(single_toc.lead_out_start_msf[2]));
if (res_size > 18 && single_toc.pointb0 > 0xaf)
- printk
- ("addb0 %01x, conb0 %01x, poib0 %02x, nextsession min %d, sec %d, frame %d\n"
+ pr_debug(PFX "addb0 %01x, conb0 %01x, poib0 %02x, nextsession min %d, sec %d, frame %d\n"
"#mode5_ptrs %02d, max_start_outer_leadout_msf min %d, sec %d, frame %d\n",
single_toc.addressb0,
single_toc.controlb0,
@@ -1690,8 +1586,7 @@ static void sony_get_toc(void)
max_start_outer_leadout_msf
[2]));
if (res_size > 27 && single_toc.pointb1 > 0xaf)
- printk
- ("addb1 %01x, conb1 %01x, poib1 %02x, %x %x %x %x #skipint_ptrs %d, #skiptrkassign %d %x\n",
+ pr_debug(PFX "addb1 %01x, conb1 %01x, poib1 %02x, %x %x %x %x #skipint_ptrs %d, #skiptrkassign %d %x\n",
single_toc.addressb1,
single_toc.controlb1,
single_toc.pointb1,
@@ -1703,8 +1598,7 @@ static void sony_get_toc(void)
single_toc.num_skip_track_assignments,
single_toc.dummyb0_2);
if (res_size > 36 && single_toc.pointb2 > 0xaf)
- printk
- ("addb2 %01x, conb2 %01x, poib2 %02x, %02x %02x %02x %02x %02x %02x %02x\n",
+ pr_debug(PFX "addb2 %01x, conb2 %01x, poib2 %02x, %02x %02x %02x %02x %02x %02x %02x\n",
single_toc.addressb2,
single_toc.controlb2,
single_toc.pointb2,
@@ -1716,8 +1610,7 @@ static void sony_get_toc(void)
single_toc.tracksb2[5],
single_toc.tracksb2[6]);
if (res_size > 45 && single_toc.pointb3 > 0xaf)
- printk
- ("addb3 %01x, conb3 %01x, poib3 %02x, %02x %02x %02x %02x %02x %02x %02x\n",
+ pr_debug(PFX "addb3 %01x, conb3 %01x, poib3 %02x, %02x %02x %02x %02x %02x %02x %02x\n",
single_toc.addressb3,
single_toc.controlb3,
single_toc.pointb3,
@@ -1729,8 +1622,7 @@ static void sony_get_toc(void)
single_toc.tracksb3[5],
single_toc.tracksb3[6]);
if (res_size > 54 && single_toc.pointb4 > 0xaf)
- printk
- ("addb4 %01x, conb4 %01x, poib4 %02x, %02x %02x %02x %02x %02x %02x %02x\n",
+ pr_debug(PFX "addb4 %01x, conb4 %01x, poib4 %02x, %02x %02x %02x %02x %02x %02x %02x\n",
single_toc.addressb4,
single_toc.controlb4,
single_toc.pointb4,
@@ -1742,8 +1634,7 @@ static void sony_get_toc(void)
single_toc.tracksb4[5],
single_toc.tracksb4[6]);
if (res_size > 63 && single_toc.pointc0 > 0xaf)
- printk
- ("addc0 %01x, conc0 %01x, poic0 %02x, %02x %02x %02x %02x %02x %02x %02x\n",
+ pr_debug(PFX "addc0 %01x, conc0 %01x, poic0 %02x, %02x %02x %02x %02x %02x %02x %02x\n",
single_toc.addressc0,
single_toc.controlc0,
single_toc.pointc0,
@@ -1754,7 +1645,6 @@ static void sony_get_toc(void)
single_toc.dummyc0[4],
single_toc.dummyc0[5],
single_toc.dummyc0[6]);
-#endif
#undef DEBUG
#define DEBUG 0
@@ -1823,8 +1713,8 @@ static void sony_get_toc(void)
res_size += 9;
}
#if DEBUG
- printk
- ("start track lba %u, leadout start lba %u\n",
+ printk(PRINT_INFO PFX "start track lba %u, "
+ "leadout start lba %u\n",
single_toc.start_track_lba,
single_toc.lead_out_start_lba);
{
@@ -1836,8 +1726,7 @@ static void sony_get_toc(void)
-
bcd_to_int(single_toc.
first_track_num); i++) {
- printk
- ("trk %02d: add 0x%01x, con 0x%01x, track %02d, start min %02d, sec %02d, frame %02d\n",
+ printk(KERN_INFO PFX "trk %02d: add 0x%01x, con 0x%01x, track %02d, start min %02d, sec %02d, frame %02d\n",
i,
single_toc.tracks[i].address,
single_toc.tracks[i].control,
@@ -1870,8 +1759,8 @@ static void sony_get_toc(void)
tracks[i].
track);
}
- printk
- ("min track number %d, max track number %d\n",
+ printk(KERN_INFO PFX "min track number %d, "
+ "max track number %d\n",
mint, maxt);
}
#endif
@@ -1976,8 +1865,8 @@ static void sony_get_toc(void)
/* Let's not get carried away... */
if (session > 40) {
- printk("cdu31a: too many sessions: %d\n",
- session);
+ printk(KERN_NOTICE PFX "too many sessions: "
+ "%d\n", session);
break;
}
session++;
@@ -1995,17 +1884,13 @@ static void sony_get_toc(void)
sony_toc.lead_out_start_msf[2];
sony_toc_read = 1;
-#undef DEBUG
-#if DEBUG
- printk
- ("Disk session %d, start track: %d, stop track: %d\n",
+
+ pr_debug(PFX "Disk session %d, start track: %d, "
+ "stop track: %d\n",
session, single_toc.start_track_lba,
single_toc.lead_out_start_lba);
-#endif
}
-#if DEBUG
- printk("Leaving sony_get_toc\n");
-#endif
+ pr_debug(PFX "Leaving %s\n", __FUNCTION__);
}
@@ -2019,8 +1904,12 @@ static int scd_get_last_session(struct cdrom_device_info *cdi,
if (ms_info == NULL)
return 1;
- if (!sony_toc_read)
+ if (!sony_toc_read) {
+ if (down_interruptible(&sony_sem))
+ return -ERESTARTSYS;
sony_get_toc();
+ up(&sony_sem);
+ }
ms_info->addr_format = CDROM_LBA;
ms_info->addr.lba = sony_toc.start_track_lba;
@@ -2060,7 +1949,7 @@ static int read_subcode(void)
0, (unsigned char *) &last_sony_subcode, &res_size);
if ((res_size < 2)
|| ((last_sony_subcode.exec_status[0] & 0xf0) == 0x20)) {
- printk("Sony CDROM error %s (read_subcode)\n",
+ printk(KERN_ERR PFX "Sony CDROM error %s (read_subcode)\n",
translate_error(last_sony_subcode.exec_status[1]));
return -EIO;
}
@@ -2098,8 +1987,11 @@ scd_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)
unsigned int res_size;
memset(mcn->medium_catalog_number, 0, 14);
+ if (down_interruptible(&sony_sem))
+ return -ERESTARTSYS;
do_sony_cd_cmd(SONY_REQ_UPC_EAN_CMD,
NULL, 0, resbuffer, &res_size);
+ up(&sony_sem);
if ((res_size < 2) || ((resbuffer[0] & 0xf0) == 0x20));
else {
/* packed bcd to single ASCII digits */
@@ -2228,8 +2120,8 @@ read_audio_data(char *buffer, unsigned char res_reg[], int *res_size)
}
/* Invalid data from the drive. Shut down the operation. */
else if ((res_reg[0] & 0xf0) != 0x20) {
- printk
- ("CDU31A: Got result that should have been error: %d\n",
+ printk(KERN_WARNING PFX "Got result that "
+ "should have been error: %d\n",
res_reg[0]);
res_reg[0] = 0x20;
res_reg[1] = SONY_BAD_DATA_ERR;
@@ -2237,9 +2129,7 @@ read_audio_data(char *buffer, unsigned char res_reg[], int *res_size)
}
abort_read();
} else {
-#if DEBUG
- printk("CDU31A timeout out %d\n", __LINE__);
-#endif
+ pr_debug(PFX "timeout out %d\n", __LINE__);
res_reg[0] = 0x20;
res_reg[1] = SONY_TIMEOUT_OP_ERR;
*res_size = 2;
@@ -2269,10 +2159,7 @@ read_audio_data(char *buffer, unsigned char res_reg[], int *res_size)
}
if (!is_result_ready()) {
-#if DEBUG
- printk("CDU31A timeout out %d\n",
- __LINE__);
-#endif
+ pr_debug(PFX "timeout out %d\n", __LINE__);
res_reg[0] = 0x20;
res_reg[1] = SONY_TIMEOUT_OP_ERR;
*res_size = 2;
@@ -2290,7 +2177,7 @@ read_audio_data(char *buffer, unsigned char res_reg[], int *res_size)
|| (res_reg[0] == SONY_NO_ERR_DETECTION_STAT)) {
/* Ok, nothing to do. */
} else {
- printk("CDU31A: Data block error: 0x%x\n",
+ printk(KERN_ERR PFX "Data block error: 0x%x\n",
res_reg[0]);
res_reg[0] = 0x20;
res_reg[1] = SONY_BAD_DATA_ERR;
@@ -2299,7 +2186,7 @@ read_audio_data(char *buffer, unsigned char res_reg[], int *res_size)
} else if ((res_reg[0] & 0xf0) != 0x20) {
/* The drive gave me bad status, I don't know what to do.
Reset the driver and return an error. */
- printk("CDU31A: Invalid block status: 0x%x\n",
+ printk(KERN_NOTICE PFX "Invalid block status: 0x%x\n",
res_reg[0]);
restart_on_error();
res_reg[0] = 0x20;
@@ -2318,28 +2205,11 @@ static int read_audio(struct cdrom_read_audio *ra)
unsigned char res_reg[12];
unsigned int res_size;
unsigned int cframe;
- unsigned long flags;
-
- /*
- * Make sure no one else is using the driver; wait for them
- * to finish if it is so.
- */
- save_flags(flags);
- cli();
- while (sony_inuse) {
- interruptible_sleep_on(&sony_wait);
- if (signal_pending(current)) {
- restore_flags(flags);
- return -EAGAIN;
- }
- }
- sony_inuse = 1;
- has_cd_task = current;
- restore_flags(flags);
- if (!sony_spun_up) {
+ if (down_interruptible(&sony_sem))
+ return -ERESTARTSYS;
+ if (!sony_spun_up)
scd_spinup();
- }
/* Set the drive to do raw operations. */
params[0] = SONY_SD_DECODE_PARAM;
@@ -2347,9 +2217,10 @@ static int read_audio(struct cdrom_read_audio *ra)
do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD,
params, 2, res_reg, &res_size);
if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20)) {
- printk("CDU31A: Unable to set decode params: 0x%2.2x\n",
+ printk(KERN_ERR PFX "Unable to set decode params: 0x%2.2x\n",
res_reg[1]);
- return -EIO;
+ retval = -EIO;
+ goto out_up;
}
/* From here down, we have to goto exit_read_audio instead of returning
@@ -2368,8 +2239,8 @@ static int read_audio(struct cdrom_read_audio *ra)
read_audio_data(audio_buffer, res_reg, &res_size);
if ((res_reg[0] & 0xf0) == 0x20) {
if (res_reg[1] == SONY_BAD_DATA_ERR) {
- printk
- ("CDU31A: Data error on audio sector %d\n",
+ printk(KERN_ERR PFX "Data error on audio "
+ "sector %d\n",
ra->addr.lba + cframe);
} else if (res_reg[1] == SONY_ILL_TRACK_R_ERR) {
/* Illegal track type, change track types and start over. */
@@ -2384,8 +2255,8 @@ static int read_audio(struct cdrom_read_audio *ra)
2, res_reg, &res_size);
if ((res_size < 2)
|| ((res_reg[0] & 0xf0) == 0x20)) {
- printk
- ("CDU31A: Unable to set decode params: 0x%2.2x\n",
+ printk(KERN_ERR PFX "Unable to set "
+ "decode params: 0x%2.2x\n",
res_reg[1]);
retval = -EIO;
goto exit_read_audio;
@@ -2407,13 +2278,12 @@ static int read_audio(struct cdrom_read_audio *ra)
if ((res_reg[0] & 0xf0) == 0x20) {
if (res_reg[1] ==
SONY_BAD_DATA_ERR) {
- printk
- ("CDU31A: Data error on audio sector %d\n",
+ printk(KERN_ERR PFX "Data error"
+ " on audio sector %d\n",
ra->addr.lba +
cframe);
} else {
- printk
- ("CDU31A: Error reading audio data on sector %d: %s\n",
+ printk(KERN_ERR PFX "Error reading audio data on sector %d: %s\n",
ra->addr.lba + cframe,
translate_error
(res_reg[1]));
@@ -2429,8 +2299,8 @@ static int read_audio(struct cdrom_read_audio *ra)
goto exit_read_audio;
}
} else {
- printk
- ("CDU31A: Error reading audio data on sector %d: %s\n",
+ printk(KERN_ERR PFX "Error reading audio "
+ "data on sector %d: %s\n",
ra->addr.lba + cframe,
translate_error(res_reg[1]));
retval = -EIO;
@@ -2448,7 +2318,7 @@ static int read_audio(struct cdrom_read_audio *ra)
get_result(res_reg, &res_size);
if ((res_reg[0] & 0xf0) == 0x20) {
- printk("CDU31A: Error return from audio read: %s\n",
+ printk(KERN_ERR PFX "Error return from audio read: %s\n",
translate_error(res_reg[1]));
retval = -EIO;
goto exit_read_audio;
@@ -2466,16 +2336,15 @@ static int read_audio(struct cdrom_read_audio *ra)
do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD,
params, 2, res_reg, &res_size);
if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20)) {
- printk("CDU31A: Unable to reset decode params: 0x%2.2x\n",
+ printk(KERN_ERR PFX "Unable to reset decode params: 0x%2.2x\n",
res_reg[1]);
- return -EIO;
+ retval = -EIO;
}
- has_cd_task = NULL;
- sony_inuse = 0;
- wake_up_interruptible(&sony_wait);
+ out_up:
+ up(&sony_sem);
- return (retval);
+ return retval;
}
static int
@@ -2488,7 +2357,7 @@ do_sony_cd_cmd_chk(const char *name,
do_sony_cd_cmd(cmd, params, num_params, result_buffer,
result_size);
if ((*result_size < 2) || ((result_buffer[0] & 0xf0) == 0x20)) {
- printk("Sony CDROM error %s (CDROM%s)\n",
+ printk(KERN_ERR PFX "Error %s (CDROM%s)\n",
translate_error(result_buffer[1]), name);
return -EIO;
}
@@ -2501,6 +2370,10 @@ do_sony_cd_cmd_chk(const char *name,
*/
static int scd_tray_move(struct cdrom_device_info *cdi, int position)
{
+ int retval;
+
+ if (down_interruptible(&sony_sem))
+ return -ERESTARTSYS;
if (position == 1 /* open tray */ ) {
unsigned char res_reg[12];
unsigned int res_size;
@@ -2511,13 +2384,15 @@ static int scd_tray_move(struct cdrom_device_info *cdi, int position)
&res_size);
sony_audio_status = CDROM_AUDIO_INVALID;
- return do_sony_cd_cmd_chk("EJECT", SONY_EJECT_CMD, NULL, 0,
+ retval = do_sony_cd_cmd_chk("EJECT", SONY_EJECT_CMD, NULL, 0,
res_reg, &res_size);
} else {
if (0 == scd_spinup())
sony_spun_up = 1;
- return 0;
+ retval = 0;
}
+ up(&sony_sem);
+ return retval;
}
/*
@@ -2529,12 +2404,13 @@ static int scd_audio_ioctl(struct cdrom_device_info *cdi,
unsigned char res_reg[12];
unsigned int res_size;
unsigned char params[7];
- int i;
-
+ int i, retval;
+ if (down_interruptible(&sony_sem))
+ return -ERESTARTSYS;
switch (cmd) {
case CDROMSTART: /* Spin up the drive */
- return do_sony_cd_cmd_chk("START", SONY_SPIN_UP_CMD, NULL,
+ retval = do_sony_cd_cmd_chk("START", SONY_SPIN_UP_CMD, NULL,
0, res_reg, &res_size);
break;
@@ -2547,28 +2423,33 @@ static int scd_audio_ioctl(struct cdrom_device_info *cdi,
* already not spinning.
*/
sony_audio_status = CDROM_AUDIO_NO_STATUS;
- return do_sony_cd_cmd_chk("STOP", SONY_SPIN_DOWN_CMD, NULL,
+ retval = do_sony_cd_cmd_chk("STOP", SONY_SPIN_DOWN_CMD, NULL,
0, res_reg, &res_size);
+ break;
case CDROMPAUSE: /* Pause the drive */
if (do_sony_cd_cmd_chk
("PAUSE", SONY_AUDIO_STOP_CMD, NULL, 0, res_reg,
- &res_size))
- return -EIO;
+ &res_size)) {
+ retval = -EIO;
+ break;
+ }
/* Get the current position and save it for resuming */
if (read_subcode() < 0) {
- return -EIO;
+ retval = -EIO;
+ break;
}
cur_pos_msf[0] = last_sony_subcode.abs_msf[0];
cur_pos_msf[1] = last_sony_subcode.abs_msf[1];
cur_pos_msf[2] = last_sony_subcode.abs_msf[2];
sony_audio_status = CDROM_AUDIO_PAUSED;
- return 0;
+ retval = 0;
break;
case CDROMRESUME: /* Start the drive after being paused */
if (sony_audio_status != CDROM_AUDIO_PAUSED) {
- return -EINVAL;
+ retval = -EINVAL;
+ break;
}
do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg,
@@ -2584,10 +2465,13 @@ static int scd_audio_ioctl(struct cdrom_device_info *cdi,
params[0] = 0x03;
if (do_sony_cd_cmd_chk
("RESUME", SONY_AUDIO_PLAYBACK_CMD, params, 7, res_reg,
- &res_size) < 0)
- return -EIO;
+ &res_size) < 0) {
+ retval = -EIO;
+ break;
+ }
sony_audio_status = CDROM_AUDIO_PLAY;
- return 0;
+ retval = 0;
+ break;
case CDROMPLAYMSF: /* Play starting at the given MSF address. */
do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg,
@@ -2601,15 +2485,18 @@ static int scd_audio_ioctl(struct cdrom_device_info *cdi,
params[0] = 0x03;
if (do_sony_cd_cmd_chk
("PLAYMSF", SONY_AUDIO_PLAYBACK_CMD, params, 7,
- res_reg, &res_size) < 0)
- return -EIO;
+ res_reg, &res_size) < 0) {
+ retval = -EIO;
+ break;
+ }
/* Save the final position for pauses and resumes */
final_pos_msf[0] = bcd_to_int(params[4]);
final_pos_msf[1] = bcd_to_int(params[5]);
final_pos_msf[2] = bcd_to_int(params[6]);
sony_audio_status = CDROM_AUDIO_PLAY;
- return 0;
+ retval = 0;
+ break;
case CDROMREADTOCHDR: /* Read the table of contents header */
{
@@ -2617,14 +2504,16 @@ static int scd_audio_ioctl(struct cdrom_device_info *cdi,
sony_get_toc();
if (!sony_toc_read) {
- return -EIO;
+ retval = -EIO;
+ break;
}
hdr = (struct cdrom_tochdr *) arg;
hdr->cdth_trk0 = sony_toc.first_track_num;
hdr->cdth_trk1 = sony_toc.last_track_num;
}
- return 0;
+ retval = 0;
+ break;
case CDROMREADTOCENTRY: /* Read a given table of contents entry */
{
@@ -2634,14 +2523,16 @@ static int scd_audio_ioctl(struct cdrom_device_info *cdi,
sony_get_toc();
if (!sony_toc_read) {
- return -EIO;
+ retval = -EIO;
+ break;
}
entry = (struct cdrom_tocentry *) arg;
track_idx = find_track(entry->cdte_track);
if (track_idx < 0) {
- return -EINVAL;
+ retval = -EINVAL;
+ break;
}
entry->cdte_adr =
@@ -2662,7 +2553,7 @@ static int scd_audio_ioctl(struct cdrom_device_info *cdi,
*(msf_val + 2);
}
}
- return 0;
+ retval = 0;
break;
case CDROMPLAYTRKIND: /* Play a track. This currently ignores index. */
@@ -2672,18 +2563,21 @@ static int scd_audio_ioctl(struct cdrom_device_info *cdi,
sony_get_toc();
if (!sony_toc_read) {
- return -EIO;
+ retval = -EIO;
+ break;
}
if ((ti->cdti_trk0 < sony_toc.first_track_num)
|| (ti->cdti_trk0 > sony_toc.last_track_num)
|| (ti->cdti_trk1 < ti->cdti_trk0)) {
- return -EINVAL;
+ retval = -EINVAL;
+ break;
}
track_idx = find_track(ti->cdti_trk0);
if (track_idx < 0) {
- return -EINVAL;
+ retval = -EINVAL;
+ break;
}
params[1] =
int_to_bcd(sony_toc.tracks[track_idx].
@@ -2705,7 +2599,8 @@ static int scd_audio_ioctl(struct cdrom_device_info *cdi,
track_idx = find_track(ti->cdti_trk1 + 1);
}
if (track_idx < 0) {
- return -EINVAL;
+ retval = -EINVAL;
+ break;
}
params[4] =
int_to_bcd(sony_toc.tracks[track_idx].
@@ -2726,14 +2621,16 @@ static int scd_audio_ioctl(struct cdrom_device_info *cdi,
if ((res_size < 2)
|| ((res_reg[0] & 0xf0) == 0x20)) {
- printk("Params: %x %x %x %x %x %x %x\n",
+ printk(KERN_ERR PFX
+ "Params: %x %x %x %x %x %x %x\n",
params[0], params[1], params[2],
params[3], params[4], params[5],
params[6]);
- printk
- ("Sony CDROM error %s (CDROMPLAYTRKIND)\n",
+ printk(KERN_ERR PFX
+ "Error %s (CDROMPLAYTRKIND)\n",
translate_error(res_reg[1]));
- return -EIO;
+ retval = -EIO;
+ break;
}
/* Save the final position for pauses and resumes */
@@ -2741,7 +2638,8 @@ static int scd_audio_ioctl(struct cdrom_device_info *cdi,
final_pos_msf[1] = bcd_to_int(params[5]);
final_pos_msf[2] = bcd_to_int(params[6]);
sony_audio_status = CDROM_AUDIO_PLAY;
- return 0;
+ retval = 0;
+ break;
}
case CDROMVOLCTRL: /* Volume control. What volume does this change, anyway? */
@@ -2752,25 +2650,32 @@ static int scd_audio_ioctl(struct cdrom_device_info *cdi,
params[0] = SONY_SD_AUDIO_VOLUME;
params[1] = volctrl->channel0;
params[2] = volctrl->channel1;
- return do_sony_cd_cmd_chk("VOLCTRL",
+ retval = do_sony_cd_cmd_chk("VOLCTRL",
SONY_SET_DRIVE_PARAM_CMD,
params, 3, res_reg,
&res_size);
+ break;
}
case CDROMSUBCHNL: /* Get subchannel info */
- return sony_get_subchnl_info((struct cdrom_subchnl *) arg);
+ retval = sony_get_subchnl_info((struct cdrom_subchnl *) arg);
+ break;
default:
- return -EINVAL;
+ retval = -EINVAL;
+ break;
}
+ up(&sony_sem);
+ return retval;
}
static int scd_dev_ioctl(struct cdrom_device_info *cdi,
unsigned int cmd, unsigned long arg)
{
void __user *argp = (void __user *)arg;
- int i;
+ int retval;
+ if (down_interruptible(&sony_sem))
+ return -ERESTARTSYS;
switch (cmd) {
case CDROMREADAUDIO: /* Read 2352 byte audio tracks and 2340 byte
raw data tracks. */
@@ -2780,33 +2685,38 @@ static int scd_dev_ioctl(struct cdrom_device_info *cdi,
sony_get_toc();
if (!sony_toc_read) {
- return -EIO;
+ retval = -EIO;
+ break;
}
- if (copy_from_user(&ra, argp, sizeof(ra)))
- return -EFAULT;
+ if (copy_from_user(&ra, argp, sizeof(ra))) {
+ retval = -EFAULT;
+ break;
+ }
if (ra.nframes == 0) {
- return 0;
+ retval = 0;
+ break;
}
- i = verify_area(VERIFY_WRITE, ra.buf,
- CD_FRAMESIZE_RAW * ra.nframes);
- if (i < 0)
- return i;
+ if (!access_ok(VERIFY_WRITE, ra.buf,
+ CD_FRAMESIZE_RAW * ra.nframes))
+ return -EFAULT;
if (ra.addr_format == CDROM_LBA) {
if ((ra.addr.lba >=
sony_toc.lead_out_start_lba)
|| (ra.addr.lba + ra.nframes >=
sony_toc.lead_out_start_lba)) {
- return -EINVAL;
+ retval = -EINVAL;
+ break;
}
} else if (ra.addr_format == CDROM_MSF) {
if ((ra.addr.msf.minute >= 75)
|| (ra.addr.msf.second >= 60)
|| (ra.addr.msf.frame >= 75)) {
- return -EINVAL;
+ retval = -EINVAL;
+ break;
}
ra.addr.lba = ((ra.addr.msf.minute * 4500)
@@ -2816,7 +2726,8 @@ static int scd_dev_ioctl(struct cdrom_device_info *cdi,
sony_toc.lead_out_start_lba)
|| (ra.addr.lba + ra.nframes >=
sony_toc.lead_out_start_lba)) {
- return -EINVAL;
+ retval = -EINVAL;
+ break;
}
/* I know, this can go negative on an unsigned. However,
@@ -2824,17 +2735,21 @@ static int scd_dev_ioctl(struct cdrom_device_info *cdi,
so this should compensate and allow direct msf access. */
ra.addr.lba -= LOG_START_OFFSET;
} else {
- return -EINVAL;
+ retval = -EINVAL;
+ break;
}
- return (read_audio(&ra));
+ retval = read_audio(&ra);
+ break;
}
- return 0;
+ retval = 0;
break;
default:
- return -EINVAL;
+ retval = -EINVAL;
}
+ up(&sony_sem);
+ return retval;
}
static int scd_spinup(void)
@@ -2851,7 +2766,7 @@ static int scd_spinup(void)
/* The drive sometimes returns error 0. I don't know why, but ignore
it. It seems to mean the drive has already done the operation. */
if ((res_size < 2) || ((res_reg[0] != 0) && (res_reg[1] != 0))) {
- printk("Sony CDROM %s error (scd_open, spin up)\n",
+ printk(KERN_ERR PFX "%s error (scd_open, spin up)\n",
translate_error(res_reg[1]));
return 1;
}
@@ -2875,7 +2790,7 @@ static int scd_spinup(void)
goto respinup_on_open;
}
- printk("Sony CDROM error %s (scd_open, read toc)\n",
+ printk(KERN_ERR PFX "Error %s (scd_open, read toc)\n",
translate_error(res_reg[1]));
do_sony_cd_cmd(SONY_SPIN_DOWN_CMD, NULL, 0, res_reg,
&res_size);
@@ -2921,9 +2836,8 @@ static int scd_open(struct cdrom_device_info *cdi, int purpose)
params, 2, res_reg, &res_size);
if ((res_size < 2)
|| ((res_reg[0] & 0xf0) == 0x20)) {
- printk
- ("CDU31A: Unable to set XA params: 0x%2.2x\n",
- res_reg[1]);
+ printk(KERN_WARNING PFX "Unable to set "
+ "XA params: 0x%2.2x\n", res_reg[1]);
}
sony_xa_mode = 1;
}
@@ -2935,9 +2849,8 @@ static int scd_open(struct cdrom_device_info *cdi, int purpose)
params, 2, res_reg, &res_size);
if ((res_size < 2)
|| ((res_reg[0] & 0xf0) == 0x20)) {
- printk
- ("CDU31A: Unable to reset XA params: 0x%2.2x\n",
- res_reg[1]);
+ printk(KERN_WARNING PFX "Unable to reset "
+ "XA params: 0x%2.2x\n", res_reg[1]);
}
sony_xa_mode = 0;
}
@@ -3009,6 +2922,8 @@ static int scd_block_release(struct inode *inode, struct file *file)
static int scd_block_ioctl(struct inode *inode, struct file *file,
unsigned cmd, unsigned long arg)
{
+ int retval;
+
/* The eject and close commands should be handled by Uniform CD-ROM
* driver - but I always got hard lockup instead of eject
* until I put this here.
@@ -3016,12 +2931,15 @@ static int scd_block_ioctl(struct inode *inode, struct file *file,
switch (cmd) {
case CDROMEJECT:
scd_lock_door(&scd_info, 0);
- return scd_tray_move(&scd_info, 1);
+ retval = scd_tray_move(&scd_info, 1);
+ break;
case CDROMCLOSETRAY:
- return scd_tray_move(&scd_info, 0);
+ retval = scd_tray_move(&scd_info, 0);
+ break;
default:
- return cdrom_ioctl(file, &scd_info, inode, cmd, arg);
+ retval = cdrom_ioctl(file, &scd_info, inode, cmd, arg);
}
+ return retval;
}
static int scd_block_media_changed(struct gendisk *disk)
@@ -3114,7 +3032,6 @@ out_err:
#ifndef MODULE
/*
* Set up base I/O and interrupts, called from main.c.
-
*/
static int __init cdu31a_setup(char *strings)
@@ -3133,7 +3050,7 @@ static int __init cdu31a_setup(char *strings)
if (strcmp(strings, "PAS") == 0) {
sony_pas_init = 1;
} else {
- printk("CDU31A: Unknown interface type: %s\n",
+ printk(KERN_NOTICE PFX "Unknown interface type: %s\n",
strings);
}
}
@@ -3225,9 +3142,8 @@ int __init cdu31a_init(void)
if (request_irq
(cdu31a_irq, cdu31a_interrupt, SA_INTERRUPT,
"cdu31a", NULL)) {
- printk
- ("Unable to grab IRQ%d for the CDU31A driver\n",
- cdu31a_irq);
+ printk(KERN_WARNING PFX "Unable to grab IRQ%d for "
+ "the CDU31A driver\n", cdu31a_irq);
cdu31a_irq = 0;
}
}
@@ -3262,8 +3178,8 @@ int __init cdu31a_init(void)
strcat(msg, buf);
}
strcat(msg, "\n");
- printk("%s",msg);
-
+ printk(KERN_INFO PFX "%s",msg);
+
cdu31a_queue = blk_init_queue(do_cdu31a_request, &cdu31a_lock);
if (!cdu31a_queue)
goto errout0;
@@ -3280,18 +3196,18 @@ int __init cdu31a_init(void)
add_disk(disk);
disk_changed = 1;
- return (0);
+ return 0;
err:
blk_cleanup_queue(cdu31a_queue);
errout0:
if (cdu31a_irq)
free_irq(cdu31a_irq, NULL);
- printk("Unable to register CDU-31a with Uniform cdrom driver\n");
+ printk(KERN_ERR PFX "Unable to register with Uniform cdrom driver\n");
put_disk(disk);
errout1:
if (unregister_blkdev(MAJOR_NR, "cdu31a")) {
- printk("Can't unregister block device for cdu31a\n");
+ printk(KERN_WARNING PFX "Can't unregister block device\n");
}
errout2:
release_region(cdu31a_port, 4);
@@ -3305,12 +3221,12 @@ void __exit cdu31a_exit(void)
del_gendisk(scd_gendisk);
put_disk(scd_gendisk);
if (unregister_cdrom(&scd_info)) {
- printk
- ("Can't unregister cdu31a from Uniform cdrom driver\n");
+ printk(KERN_WARNING PFX "Can't unregister from Uniform "
+ "cdrom driver\n");
return;
}
if ((unregister_blkdev(MAJOR_NR, "cdu31a") == -EINVAL)) {
- printk("Can't unregister cdu31a\n");
+ printk(KERN_WARNING PFX "Can't unregister\n");
return;
}
@@ -3320,7 +3236,7 @@ void __exit cdu31a_exit(void)
free_irq(cdu31a_irq, NULL);
release_region(cdu31a_port, 4);
- printk(KERN_INFO "cdu31a module released.\n");
+ printk(KERN_INFO PFX "module released.\n");
}
#ifdef MODULE
diff --git a/drivers/cdrom/mcd.c b/drivers/cdrom/mcd.c
deleted file mode 100644
index 55db09b9cfdfc..0000000000000
--- a/drivers/cdrom/mcd.c
+++ /dev/null
@@ -1,1565 +0,0 @@
-/*
- linux/kernel/blk_drv/mcd.c - Mitsumi CDROM driver
-
- Copyright (C) 1992 Martin Harriss
- Portions Copyright (C) 2001 Red Hat
-
- martin@bdsi.com (no longer valid - where are you now, Martin?)
-
- This program is free software; you can redistribute 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.
-
- HISTORY
-
- 0.1 First attempt - internal use only
- 0.2 Cleaned up delays and use of timer - alpha release
- 0.3 Audio support added
- 0.3.1 Changes for mitsumi CRMC LU005S march version
- (stud11@cc4.kuleuven.ac.be)
- 0.3.2 bug fixes to the ioctls and merged with ALPHA0.99-pl12
- (Jon Tombs <jon@robots.ox.ac.uk>)
- 0.3.3 Added more #defines and mcd_setup()
- (Jon Tombs <jon@gtex02.us.es>)
-
- October 1993 Bernd Huebner and Ruediger Helsch, Unifix Software GmbH,
- Braunschweig, Germany: rework to speed up data read operation.
- Also enabled definition of irq and address from bootstrap, using the
- environment.
- November 93 added code for FX001 S,D (single & double speed).
- February 94 added code for broken M 5/6 series of 16-bit single speed.
-
-
- 0.4
- Added support for loadable MODULEs, so mcd can now also be loaded by
- insmod and removed by rmmod during runtime.
- Werner Zimmermann (zimmerma@rz.fht-esslingen.de), Mar. 26, 95
-
- 0.5
- I added code for FX001 D to drop from double speed to single speed
- when encountering errors... this helps with some "problematic" CD's
- that are supposedly "OUT OF TOLERANCE" (but are really shitty presses!)
- severely scratched, or possibly slightly warped! I have noticed that
- the Mitsumi 2x/4x drives are just less tolerant and the firmware is
- not smart enough to drop speed, so let's just kludge it with software!
- ****** THE 4X SPEED MITSUMI DRIVES HAVE THE SAME PROBLEM!!!!!! ******
- Anyone want to "DONATE" one to me?! ;) I hear sometimes they are
- even WORSE! ;)
- ** HINT... HINT... TAKE NOTES MITSUMI This could save some hassles with
- certain "large" CD's that have data on the outside edge in your
- DOS DRIVERS .... Accuracy counts... speed is secondary ;)
- 17 June 95 Modifications By Andrew J. Kroll <ag784@freenet.buffalo.edu>
- 07 July 1995 Modifications by Andrew J. Kroll
-
- Bjorn Ekwall <bj0rn@blox.se> added unregister_blkdev to mcd_init()
-
- Michael K. Johnson <johnsonm@redhat.com> added retries on open
- for slow drives which take a while to recognize that they contain
- a CD.
-
- November 1997 -- ported to the Uniform CD-ROM driver by Erik Andersen.
- March 1999 -- made io base and irq CONFIG_ options (Tigran Aivazian).
-
- November 1999 -- Make kernel-parameter implementation work with 2.3.x
- Removed init_module & cleanup_module in favor of
- module_init & module_exit.
- Torben Mathiasen <tmm@image.dk>
-
- September 2001 - Reformatted and cleaned up the code
- Alan Cox <alan@redhat.com>
-*/
-
-#include <linux/module.h>
-
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/signal.h>
-#include <linux/mm.h>
-#include <linux/timer.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/devfs_fs_kernel.h>
-#include <linux/cdrom.h>
-#include <linux/ioport.h>
-#include <linux/string.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/config.h>
-
-/* #define REALLY_SLOW_IO */
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/current.h>
-#include <asm/uaccess.h>
-#include <linux/blkdev.h>
-
-#include "mcd.h"
-
-/* I added A flag to drop to 1x speed if too many errors 0 = 1X ; 1 = 2X */
-static int mcdDouble;
-
-/* How many sectors to hold at 1x speed counter */
-static int mcd1xhold;
-
-/* Is the drive connected properly and responding?? */
-static int mcdPresent;
-static struct request_queue *mcd_queue;
-
-#define MAJOR_NR MITSUMI_CDROM_MAJOR
-#define QUEUE (mcd_queue)
-#define CURRENT elv_next_request(mcd_queue)
-
-#define QUICK_LOOP_DELAY udelay(45) /* use udelay */
-#define QUICK_LOOP_COUNT 20
-
-static int current_valid(void)
-{
- return CURRENT &&
- CURRENT->cmd == READ &&
- CURRENT->sector != -1;
-}
-
-#define MFL_STATUSorDATA (MFL_STATUS | MFL_DATA)
-#define MCD_BUF_SIZ 16
-static volatile int mcd_transfer_is_active;
-static char mcd_buf[2048 * MCD_BUF_SIZ]; /* buffer for block size conversion */
-static volatile int mcd_buf_bn[MCD_BUF_SIZ], mcd_next_bn;
-static volatile int mcd_buf_in, mcd_buf_out = -1;
-static volatile int mcd_error;
-static int mcd_open_count;
-enum mcd_state_e {
- MCD_S_IDLE, /* 0 */
- MCD_S_START, /* 1 */
- MCD_S_MODE, /* 2 */
- MCD_S_READ, /* 3 */
- MCD_S_DATA, /* 4 */
- MCD_S_STOP, /* 5 */
- MCD_S_STOPPING /* 6 */
-};
-static volatile enum mcd_state_e mcd_state = MCD_S_IDLE;
-static int mcd_mode = -1;
-static int MCMD_DATA_READ = MCMD_PLAY_READ;
-
-#define READ_TIMEOUT 3000
-
-int mitsumi_bug_93_wait;
-
-static short mcd_port = CONFIG_MCD_BASE; /* used as "mcd" by "insmod" */
-static int mcd_irq = CONFIG_MCD_IRQ; /* must directly follow mcd_port */
-
-static int McdTimeout, McdTries;
-static DECLARE_WAIT_QUEUE_HEAD(mcd_waitq);
-
-static struct mcd_DiskInfo DiskInfo;
-static struct mcd_Toc Toc[MAX_TRACKS];
-static struct mcd_Play_msf mcd_Play;
-
-static int audioStatus;
-static char mcdDiskChanged;
-static char tocUpToDate;
-static char mcdVersion;
-
-static void mcd_transfer(void);
-static void mcd_poll(unsigned long dummy);
-static void mcd_invalidate_buffers(void);
-static void hsg2msf(long hsg, struct msf *msf);
-static void bin2bcd(unsigned char *p);
-static int bcd2bin(unsigned char bcd);
-static int mcdStatus(void);
-static void sendMcdCmd(int cmd, struct mcd_Play_msf *params);
-static int getMcdStatus(int timeout);
-static int GetQChannelInfo(struct mcd_Toc *qp);
-static int updateToc(void);
-static int GetDiskInfo(void);
-static int GetToc(void);
-static int getValue(unsigned char *result);
-static int mcd_open(struct cdrom_device_info *cdi, int purpose);
-static void mcd_release(struct cdrom_device_info *cdi);
-static int mcd_media_changed(struct cdrom_device_info *cdi, int disc_nr);
-static int mcd_tray_move(struct cdrom_device_info *cdi, int position);
-static DEFINE_SPINLOCK(mcd_spinlock);
-static int mcd_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
- void *arg);
-static int mcd_drive_status(struct cdrom_device_info *cdi, int slot_nr);
-
-static struct timer_list mcd_timer = TIMER_INITIALIZER(NULL, 0, 0);
-
-static struct cdrom_device_ops mcd_dops = {
- .open = mcd_open,
- .release = mcd_release,
- .drive_status = mcd_drive_status,
- .media_changed = mcd_media_changed,
- .tray_move = mcd_tray_move,
- .audio_ioctl = mcd_audio_ioctl,
- .capability = CDC_OPEN_TRAY | CDC_MEDIA_CHANGED |
- CDC_PLAY_AUDIO | CDC_DRIVE_STATUS,
-};
-
-static struct cdrom_device_info mcd_info = {
- .ops = &mcd_dops,
- .speed = 2,
- .capacity = 1,
- .name = "mcd",
-};
-
-static int mcd_block_open(struct inode *inode, struct file *file)
-{
- return cdrom_open(&mcd_info, inode, file);
-}
-
-static int mcd_block_release(struct inode *inode, struct file *file)
-{
- return cdrom_release(&mcd_info, file);
-}
-
-static int mcd_block_ioctl(struct inode *inode, struct file *file,
- unsigned cmd, unsigned long arg)
-{
- return cdrom_ioctl(file, &mcd_info, inode, cmd, arg);
-}
-
-static int mcd_block_media_changed(struct gendisk *disk)
-{
- return cdrom_media_changed(&mcd_info);
-}
-
-static struct block_device_operations mcd_bdops =
-{
- .owner = THIS_MODULE,
- .open = mcd_block_open,
- .release = mcd_block_release,
- .ioctl = mcd_block_ioctl,
- .media_changed = mcd_block_media_changed,
-};
-
-static struct gendisk *mcd_gendisk;
-
-static int __init mcd_setup(char *str)
-{
- int ints[9];
-
- (void) get_options(str, ARRAY_SIZE(ints), ints);
-
- if (ints[0] > 0)
- mcd_port = ints[1];
- if (ints[0] > 1)
- mcd_irq = ints[2];
- if (ints[0] > 2)
- mitsumi_bug_93_wait = ints[3];
-
- return 1;
-}
-
-__setup("mcd=", mcd_setup);
-
-#ifdef MODULE
-static int __init param_set_mcd(const char *val, struct kernel_param *kp)
-{
- mcd_setup(val);
- return 0;
-}
-module_param_call(mcd, param_set_mcd, NULL, NULL, 0);
-#endif
-
-static int mcd_media_changed(struct cdrom_device_info *cdi, int disc_nr)
-{
- return 0;
-}
-
-
-/*
- * Do a 'get status' command and get the result. Only use from the top half
- * because it calls 'getMcdStatus' which sleeps.
- */
-
-static int statusCmd(void)
-{
- int st = -1, retry;
-
- for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++) {
- /* send get-status cmd */
- outb(MCMD_GET_STATUS, MCDPORT(0));
-
- st = getMcdStatus(MCD_STATUS_DELAY);
- if (st != -1)
- break;
- }
-
- return st;
-}
-
-
-/*
- * Send a 'Play' command and get the status. Use only from the top half.
- */
-
-static int mcdPlay(struct mcd_Play_msf *arg)
-{
- int retry, st = -1;
-
- for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++) {
- sendMcdCmd(MCMD_PLAY_READ, arg);
- st = getMcdStatus(2 * MCD_STATUS_DELAY);
- if (st != -1)
- break;
- }
-
- return st;
-}
-
-
-static int mcd_tray_move(struct cdrom_device_info *cdi, int position)
-{
- int i;
- if (position) {
- /* Eject */
- /* all drives can at least stop! */
- if (audioStatus == CDROM_AUDIO_PLAY) {
- outb(MCMD_STOP, MCDPORT(0));
- i = getMcdStatus(MCD_STATUS_DELAY);
- }
-
- audioStatus = CDROM_AUDIO_NO_STATUS;
-
- outb(MCMD_EJECT, MCDPORT(0));
- /*
- * the status (i) shows failure on all but the FX drives.
- * But nothing we can do about that in software!
- * So just read the status and forget it. - Jon.
- */
- i = getMcdStatus(MCD_STATUS_DELAY);
- return 0;
- } else
- return -EINVAL;
-}
-
-long msf2hsg(struct msf *mp)
-{
- return bcd2bin(mp->frame) + bcd2bin(mp->sec) * 75 + bcd2bin(mp->min) * 4500 - 150;
-}
-
-
-int mcd_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
- void *arg)
-{
- int i, st;
- struct mcd_Toc qInfo;
- struct cdrom_ti *ti;
- struct cdrom_tochdr *tocHdr;
- struct cdrom_msf *msf;
- struct cdrom_subchnl *subchnl;
- struct cdrom_tocentry *entry;
- struct mcd_Toc *tocPtr;
- struct cdrom_volctrl *volctrl;
-
- st = statusCmd();
- if (st < 0)
- return -EIO;
-
- if (!tocUpToDate) {
- i = updateToc();
- if (i < 0)
- return i; /* error reading TOC */
- }
-
- switch (cmd) {
- case CDROMSTART: /* Spin up the drive */
- /* Don't think we can do this. Even if we could,
- * I think the drive times out and stops after a while
- * anyway. For now, ignore it.
- */
-
- return 0;
-
- case CDROMSTOP: /* Spin down the drive */
- outb(MCMD_STOP, MCDPORT(0));
- i = getMcdStatus(MCD_STATUS_DELAY);
-
- /* should we do anything if it fails? */
-
- audioStatus = CDROM_AUDIO_NO_STATUS;
- return 0;
-
- case CDROMPAUSE: /* Pause the drive */
- if (audioStatus != CDROM_AUDIO_PLAY)
- return -EINVAL;
-
- outb(MCMD_STOP, MCDPORT(0));
- i = getMcdStatus(MCD_STATUS_DELAY);
-
- if (GetQChannelInfo(&qInfo) < 0) {
- /* didn't get q channel info */
-
- audioStatus = CDROM_AUDIO_NO_STATUS;
- return 0;
- }
-
- mcd_Play.start = qInfo.diskTime; /* remember restart point */
-
- audioStatus = CDROM_AUDIO_PAUSED;
- return 0;
-
- case CDROMRESUME: /* Play it again, Sam */
- if (audioStatus != CDROM_AUDIO_PAUSED)
- return -EINVAL;
-
- /* restart the drive at the saved position. */
-
- i = mcdPlay(&mcd_Play);
- if (i < 0) {
- audioStatus = CDROM_AUDIO_ERROR;
- return -EIO;
- }
-
- audioStatus = CDROM_AUDIO_PLAY;
- return 0;
-
- case CDROMPLAYTRKIND: /* Play a track. This currently ignores index. */
-
- ti = (struct cdrom_ti *) arg;
-
- if (ti->cdti_trk0 < DiskInfo.first
- || ti->cdti_trk0 > DiskInfo.last
- || ti->cdti_trk1 < ti->cdti_trk0) {
- return -EINVAL;
- }
-
- if (ti->cdti_trk1 > DiskInfo.last)
- ti->cdti_trk1 = DiskInfo.last;
-
- mcd_Play.start = Toc[ti->cdti_trk0].diskTime;
- mcd_Play.end = Toc[ti->cdti_trk1 + 1].diskTime;
-
-#ifdef MCD_DEBUG
- printk("play: %02x:%02x.%02x to %02x:%02x.%02x\n",
- mcd_Play.start.min, mcd_Play.start.sec,
- mcd_Play.start.frame, mcd_Play.end.min,
- mcd_Play.end.sec, mcd_Play.end.frame);
-#endif
-
- i = mcdPlay(&mcd_Play);
- if (i < 0) {
- audioStatus = CDROM_AUDIO_ERROR;
- return -EIO;
- }
-
- audioStatus = CDROM_AUDIO_PLAY;
- return 0;
-
- case CDROMPLAYMSF: /* Play starting at the given MSF address. */
-
- if (audioStatus == CDROM_AUDIO_PLAY) {
- outb(MCMD_STOP, MCDPORT(0));
- i = getMcdStatus(MCD_STATUS_DELAY);
- audioStatus = CDROM_AUDIO_NO_STATUS;
- }
-
- msf = (struct cdrom_msf *) arg;
-
- /* convert to bcd */
-
- bin2bcd(&msf->cdmsf_min0);
- bin2bcd(&msf->cdmsf_sec0);
- bin2bcd(&msf->cdmsf_frame0);
- bin2bcd(&msf->cdmsf_min1);
- bin2bcd(&msf->cdmsf_sec1);
- bin2bcd(&msf->cdmsf_frame1);
-
- mcd_Play.start.min = msf->cdmsf_min0;
- mcd_Play.start.sec = msf->cdmsf_sec0;
- mcd_Play.start.frame = msf->cdmsf_frame0;
- mcd_Play.end.min = msf->cdmsf_min1;
- mcd_Play.end.sec = msf->cdmsf_sec1;
- mcd_Play.end.frame = msf->cdmsf_frame1;
-
-#ifdef MCD_DEBUG
- printk("play: %02x:%02x.%02x to %02x:%02x.%02x\n",
- mcd_Play.start.min, mcd_Play.start.sec,
- mcd_Play.start.frame, mcd_Play.end.min,
- mcd_Play.end.sec, mcd_Play.end.frame);
-#endif
-
- i = mcdPlay(&mcd_Play);
- if (i < 0) {
- audioStatus = CDROM_AUDIO_ERROR;
- return -EIO;
- }
-
- audioStatus = CDROM_AUDIO_PLAY;
- return 0;
-
- case CDROMREADTOCHDR: /* Read the table of contents header */
- tocHdr = (struct cdrom_tochdr *) arg;
- tocHdr->cdth_trk0 = DiskInfo.first;
- tocHdr->cdth_trk1 = DiskInfo.last;
- return 0;
-
- case CDROMREADTOCENTRY: /* Read an entry in the table of contents */
- entry = (struct cdrom_tocentry *) arg;
- if (entry->cdte_track == CDROM_LEADOUT)
- tocPtr = &Toc[DiskInfo.last - DiskInfo.first + 1];
-
- else if (entry->cdte_track > DiskInfo.last
- || entry->cdte_track < DiskInfo.first)
- return -EINVAL;
-
- else
- tocPtr = &Toc[entry->cdte_track];
-
- entry->cdte_adr = tocPtr->ctrl_addr;
- entry->cdte_ctrl = tocPtr->ctrl_addr >> 4;
-
- if (entry->cdte_format == CDROM_LBA)
- entry->cdte_addr.lba = msf2hsg(&tocPtr->diskTime);
-
- else if (entry->cdte_format == CDROM_MSF) {
- entry->cdte_addr.msf.minute =
- bcd2bin(tocPtr->diskTime.min);
- entry->cdte_addr.msf.second =
- bcd2bin(tocPtr->diskTime.sec);
- entry->cdte_addr.msf.frame =
- bcd2bin(tocPtr->diskTime.frame);
- }
-
- else
- return -EINVAL;
-
- return 0;
-
- case CDROMSUBCHNL: /* Get subchannel info */
-
- subchnl = (struct cdrom_subchnl *) arg;
- if (GetQChannelInfo(&qInfo) < 0)
- return -EIO;
-
- subchnl->cdsc_audiostatus = audioStatus;
- subchnl->cdsc_adr = qInfo.ctrl_addr;
- subchnl->cdsc_ctrl = qInfo.ctrl_addr >> 4;
- subchnl->cdsc_trk = bcd2bin(qInfo.track);
- subchnl->cdsc_ind = bcd2bin(qInfo.pointIndex);
- subchnl->cdsc_absaddr.msf.minute = bcd2bin(qInfo.diskTime.min);
- subchnl->cdsc_absaddr.msf.second = bcd2bin(qInfo.diskTime.sec);
- subchnl->cdsc_absaddr.msf.frame = bcd2bin(qInfo.diskTime.frame);
- subchnl->cdsc_reladdr.msf.minute = bcd2bin(qInfo.trackTime.min);
- subchnl->cdsc_reladdr.msf.second = bcd2bin(qInfo.trackTime.sec);
- subchnl->cdsc_reladdr.msf.frame = bcd2bin(qInfo.trackTime.frame);
- return (0);
-
- case CDROMVOLCTRL: /* Volume control */
- volctrl = (struct cdrom_volctrl *) arg;
- outb(MCMD_SET_VOLUME, MCDPORT(0));
- outb(volctrl->channel0, MCDPORT(0));
- outb(255, MCDPORT(0));
- outb(volctrl->channel1, MCDPORT(0));
- outb(255, MCDPORT(0));
-
- i = getMcdStatus(MCD_STATUS_DELAY);
- if (i < 0)
- return -EIO;
-
- {
- char a, b, c, d;
-
- getValue(&a);
- getValue(&b);
- getValue(&c);
- getValue(&d);
- }
-
- return 0;
-
- default:
- return -EINVAL;
- }
-}
-
-/*
- * Take care of the different block sizes between cdrom and Linux.
- * When Linux gets variable block sizes this will probably go away.
- */
-
-static void mcd_transfer(void)
-{
- if (!current_valid())
- return;
-
- while (CURRENT->nr_sectors) {
- int bn = CURRENT->sector / 4;
- int i;
- for (i = 0; i < MCD_BUF_SIZ && mcd_buf_bn[i] != bn; ++i)
- ;
- if (i < MCD_BUF_SIZ) {
- int offs =(i * 4 + (CURRENT->sector & 3)) * 512;
- int nr_sectors = 4 - (CURRENT->sector & 3);
- if (mcd_buf_out != i) {
- mcd_buf_out = i;
- if (mcd_buf_bn[i] != bn) {
- mcd_buf_out = -1;
- continue;
- }
- }
- if (nr_sectors > CURRENT->nr_sectors)
- nr_sectors = CURRENT->nr_sectors;
- memcpy(CURRENT->buffer, mcd_buf + offs, nr_sectors * 512);
- CURRENT->nr_sectors -= nr_sectors;
- CURRENT->sector += nr_sectors;
- CURRENT->buffer += nr_sectors * 512;
- } else {
- mcd_buf_out = -1;
- break;
- }
- }
-}
-
-
-/*
- * We only seem to get interrupts after an error.
- * Just take the interrupt and clear out the status reg.
- */
-
-static irqreturn_t mcd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
- int st;
-
- st = inb(MCDPORT(1)) & 0xFF;
- test1(printk("<int1-%02X>", st));
- if (!(st & MFL_STATUS)) {
- st = inb(MCDPORT(0)) & 0xFF;
- test1(printk("<int0-%02X>", st));
- if ((st & 0xFF) != 0xFF)
- mcd_error = st ? st & 0xFF : -1;
- }
- return IRQ_HANDLED;
-}
-
-
-static void do_mcd_request(request_queue_t * q)
-{
- test2(printk(" do_mcd_request(%ld+%ld)\n", CURRENT->sector,
- CURRENT->nr_sectors));
-
- mcd_transfer_is_active = 1;
- while (current_valid()) {
- mcd_transfer();
- if (CURRENT->nr_sectors == 0) {
- end_request(CURRENT, 1);
- } else {
- mcd_buf_out = -1; /* Want to read a block not in buffer */
- if (mcd_state == MCD_S_IDLE) {
- if (!tocUpToDate) {
- if (updateToc() < 0) {
- while (current_valid())
- end_request(CURRENT, 0);
- break;
- }
- }
- mcd_state = MCD_S_START;
- McdTries = 5;
- mcd_timer.function = mcd_poll;
- mod_timer(&mcd_timer, jiffies + 1);
- }
- break;
- }
- }
- mcd_transfer_is_active = 0;
- test2(printk(" do_mcd_request ends\n"));
-}
-
-
-
-static void mcd_poll(unsigned long dummy)
-{
- int st;
-
-
- if (mcd_error) {
- if (mcd_error & 0xA5) {
- printk(KERN_ERR "mcd: I/O error 0x%02x", mcd_error);
- if (mcd_error & 0x80)
- printk(" (Door open)");
- if (mcd_error & 0x20)
- printk(" (Disk changed)");
- if (mcd_error & 0x04) {
- printk(" (Read error)"); /* Bitch about the problem. */
-
- /* Time to get fancy! If at 2x speed and 1 error, drop to 1x speed! */
- /* Interesting how it STAYS at MCD_RETRY_ATTEMPTS on first error! */
- /* But I find that rather HANDY!!! */
- /* Neat! it REALLY WORKS on those LOW QUALITY CD's!!! Smile! :) */
- /* AJK [06/17/95] */
-
- /* Slap the CD down to single speed! */
- if (mcdDouble == 1
- && McdTries == MCD_RETRY_ATTEMPTS
- && MCMD_DATA_READ == MCMD_2X_READ) {
- MCMD_DATA_READ = MCMD_PLAY_READ; /* Uhhh, Ummmm, muhuh-huh! */
- mcd1xhold = SINGLE_HOLD_SECTORS; /* Hey Beavis! */
- printk(" Speed now 1x"); /* Pull my finger! */
- }
- }
- printk("\n");
- mcd_invalidate_buffers();
-#ifdef WARN_IF_READ_FAILURE
- if (McdTries == MCD_RETRY_ATTEMPTS)
- printk(KERN_ERR "mcd: read of block %d failed\n",
- mcd_next_bn);
-#endif
- if (!McdTries--) {
- /* Nuts! This cd is ready for recycling! */
- /* When WAS the last time YOU cleaned it CORRECTLY?! */
- printk(KERN_ERR "mcd: read of block %d failed, giving up\n",
- mcd_next_bn);
- if (mcd_transfer_is_active) {
- McdTries = 0;
- goto ret;
- }
- if (current_valid())
- end_request(CURRENT, 0);
- McdTries = MCD_RETRY_ATTEMPTS;
- }
- }
- mcd_error = 0;
- mcd_state = MCD_S_STOP;
- }
- /* Switch back to Double speed if enough GOOD sectors were read! */
-
- /* Are we a double speed with a crappy CD?! */
- if (mcdDouble == 1 && McdTries == MCD_RETRY_ATTEMPTS
- && MCMD_DATA_READ == MCMD_PLAY_READ) {
- /* We ARE a double speed and we ARE bitching! */
- if (mcd1xhold == 0) { /* Okay, Like are we STILL at single speed? *//* We need to switch back to double speed now... */
- MCMD_DATA_READ = MCMD_2X_READ; /* Uhhh... BACK You GO! */
- printk(KERN_INFO "mcd: Switching back to 2X speed!\n"); /* Tell 'em! */
- } else
- mcd1xhold--; /* No?! Count down the good reads some more... */
- /* and try, try again! */
- }
-
-immediately:
- switch (mcd_state) {
- case MCD_S_IDLE:
- test3(printk("MCD_S_IDLE\n"));
- goto out;
-
- case MCD_S_START:
- test3(printk("MCD_S_START\n"));
- outb(MCMD_GET_STATUS, MCDPORT(0));
- mcd_state = mcd_mode == 1 ? MCD_S_READ : MCD_S_MODE;
- McdTimeout = 3000;
- break;
-
- case MCD_S_MODE:
- test3(printk("MCD_S_MODE\n"));
- if ((st = mcdStatus()) != -1) {
- if (st & MST_DSK_CHG) {
- mcdDiskChanged = 1;
- tocUpToDate = 0;
- mcd_invalidate_buffers();
- }
-
-set_mode_immediately:
- if ((st & MST_DOOR_OPEN) || !(st & MST_READY)) {
- mcdDiskChanged = 1;
- tocUpToDate = 0;
- if (mcd_transfer_is_active) {
- mcd_state = MCD_S_START;
- goto immediately;
- }
- printk(KERN_INFO);
- printk((st & MST_DOOR_OPEN) ?
- "mcd: door open\n" :
- "mcd: disk removed\n");
- mcd_state = MCD_S_IDLE;
- while (current_valid())
- end_request(CURRENT, 0);
- goto out;
- }
- outb(MCMD_SET_MODE, MCDPORT(0));
- outb(1, MCDPORT(0));
- mcd_mode = 1;
- mcd_state = MCD_S_READ;
- McdTimeout = 3000;
- }
- break;
-
- case MCD_S_READ:
- test3(printk("MCD_S_READ\n"));
- if ((st = mcdStatus()) != -1) {
- if (st & MST_DSK_CHG) {
- mcdDiskChanged = 1;
- tocUpToDate = 0;
- mcd_invalidate_buffers();
- }
-
-read_immediately:
- if ((st & MST_DOOR_OPEN) || !(st & MST_READY)) {
- mcdDiskChanged = 1;
- tocUpToDate = 0;
- if (mcd_transfer_is_active) {
- mcd_state = MCD_S_START;
- goto immediately;
- }
- printk(KERN_INFO);
- printk((st & MST_DOOR_OPEN) ?
- "mcd: door open\n" :
- "mcd: disk removed\n");
- mcd_state = MCD_S_IDLE;
- while (current_valid())
- end_request(CURRENT, 0);
- goto out;
- }
-
- if (current_valid()) {
- struct mcd_Play_msf msf;
- mcd_next_bn = CURRENT->sector / 4;
- hsg2msf(mcd_next_bn, &msf.start);
- msf.end.min = ~0;
- msf.end.sec = ~0;
- msf.end.frame = ~0;
- sendMcdCmd(MCMD_DATA_READ, &msf);
- mcd_state = MCD_S_DATA;
- McdTimeout = READ_TIMEOUT;
- } else {
- mcd_state = MCD_S_STOP;
- goto immediately;
- }
-
- }
- break;
-
- case MCD_S_DATA:
- test3(printk("MCD_S_DATA\n"));
- st = inb(MCDPORT(1)) & (MFL_STATUSorDATA);
-data_immediately:
- test5(printk("Status %02x\n", st))
- switch (st) {
- case MFL_DATA:
-#ifdef WARN_IF_READ_FAILURE
- if (McdTries == 5)
- printk(KERN_WARNING "mcd: read of block %d failed\n",
- mcd_next_bn);
-#endif
- if (!McdTries--) {
- printk(KERN_ERR "mcd: read of block %d failed, giving up\n", mcd_next_bn);
- if (mcd_transfer_is_active) {
- McdTries = 0;
- break;
- }
- if (current_valid())
- end_request(CURRENT, 0);
- McdTries = 5;
- }
- mcd_state = MCD_S_START;
- McdTimeout = READ_TIMEOUT;
- goto immediately;
-
- case MFL_STATUSorDATA:
- break;
-
- default:
- McdTries = 5;
- if (!current_valid() && mcd_buf_in == mcd_buf_out) {
- mcd_state = MCD_S_STOP;
- goto immediately;
- }
- mcd_buf_bn[mcd_buf_in] = -1;
- insb(MCDPORT(0), mcd_buf + 2048 * mcd_buf_in,
- 2048);
- mcd_buf_bn[mcd_buf_in] = mcd_next_bn++;
- if (mcd_buf_out == -1)
- mcd_buf_out = mcd_buf_in;
- mcd_buf_in = mcd_buf_in + 1 == MCD_BUF_SIZ ? 0 : mcd_buf_in + 1;
- if (!mcd_transfer_is_active) {
- while (current_valid()) {
- mcd_transfer();
- if (CURRENT->nr_sectors == 0)
- end_request(CURRENT, 1);
- else
- break;
- }
- }
-
- if (current_valid()
- && (CURRENT->sector / 4 < mcd_next_bn ||
- CURRENT->sector / 4 > mcd_next_bn + 16)) {
- mcd_state = MCD_S_STOP;
- goto immediately;
- }
- McdTimeout = READ_TIMEOUT;
- {
- int count = QUICK_LOOP_COUNT;
- while (count--) {
- QUICK_LOOP_DELAY;
- if ((st = (inb(MCDPORT(1))) & (MFL_STATUSorDATA)) != (MFL_STATUSorDATA)) {
- test4(printk(" %d ", QUICK_LOOP_COUNT - count));
- goto data_immediately;
- }
- }
- test4(printk("ended "));
- }
- break;
- }
- break;
-
- case MCD_S_STOP:
- test3(printk("MCD_S_STOP\n"));
- if (!mitsumi_bug_93_wait)
- goto do_not_work_around_mitsumi_bug_93_1;
-
- McdTimeout = mitsumi_bug_93_wait;
- mcd_state = 9 + 3 + 1;
- break;
-
- case 9 + 3 + 1:
- if (McdTimeout)
- break;
-
-do_not_work_around_mitsumi_bug_93_1:
- outb(MCMD_STOP, MCDPORT(0));
- if ((inb(MCDPORT(1)) & MFL_STATUSorDATA) == MFL_STATUS) {
- int i = 4096;
- do {
- inb(MCDPORT(0));
- } while ((inb(MCDPORT(1)) & MFL_STATUSorDATA) == MFL_STATUS && --i);
- outb(MCMD_STOP, MCDPORT(0));
- if ((inb(MCDPORT(1)) & MFL_STATUSorDATA) == MFL_STATUS) {
- i = 4096;
- do {
- inb(MCDPORT(0));
- } while ((inb(MCDPORT(1)) & MFL_STATUSorDATA) == MFL_STATUS && --i);
- outb(MCMD_STOP, MCDPORT(0));
- }
- }
-
- mcd_state = MCD_S_STOPPING;
- McdTimeout = 1000;
- break;
-
- case MCD_S_STOPPING:
- test3(printk("MCD_S_STOPPING\n"));
- if ((st = mcdStatus()) == -1 && McdTimeout)
- break;
-
- if ((st != -1) && (st & MST_DSK_CHG)) {
- mcdDiskChanged = 1;
- tocUpToDate = 0;
- mcd_invalidate_buffers();
- }
- if (!mitsumi_bug_93_wait)
- goto do_not_work_around_mitsumi_bug_93_2;
-
- McdTimeout = mitsumi_bug_93_wait;
- mcd_state = 9 + 3 + 2;
- break;
-
- case 9 + 3 + 2:
- if (McdTimeout)
- break;
- st = -1;
-
-do_not_work_around_mitsumi_bug_93_2:
- test3(printk("CURRENT_VALID %d mcd_mode %d\n", current_valid(),
- mcd_mode));
- if (current_valid()) {
- if (st != -1) {
- if (mcd_mode == 1)
- goto read_immediately;
- else
- goto set_mode_immediately;
- } else {
- mcd_state = MCD_S_START;
- McdTimeout = 1;
- }
- } else {
- mcd_state = MCD_S_IDLE;
- goto out;
- }
- break;
- default:
- printk(KERN_ERR "mcd: invalid state %d\n", mcd_state);
- goto out;
- }
-ret:
- if (!McdTimeout--) {
- printk(KERN_WARNING "mcd: timeout in state %d\n", mcd_state);
- mcd_state = MCD_S_STOP;
- }
- mcd_timer.function = mcd_poll;
- mod_timer(&mcd_timer, jiffies + 1);
-out:
- return;
-}
-
-static void mcd_invalidate_buffers(void)
-{
- int i;
- for (i = 0; i < MCD_BUF_SIZ; ++i)
- mcd_buf_bn[i] = -1;
- mcd_buf_out = -1;
-}
-
-/*
- * Open the device special file. Check that a disk is in.
- */
-static int mcd_open(struct cdrom_device_info *cdi, int purpose)
-{
- int st, count = 0;
- if (mcdPresent == 0)
- return -ENXIO; /* no hardware */
-
- if (mcd_open_count || mcd_state != MCD_S_IDLE)
- goto bump_count;
-
- mcd_invalidate_buffers();
- do {
- st = statusCmd(); /* check drive status */
- if (st == -1)
- goto err_out; /* drive doesn't respond */
- if ((st & MST_READY) == 0) /* no disk? wait a sec... */
- msleep(1000);
-
- } while (((st & MST_READY) == 0) && count++ < MCD_RETRY_ATTEMPTS);
-
- if (updateToc() < 0)
- goto err_out;
-
-bump_count:
- ++mcd_open_count;
- return 0;
-
-err_out:
- return -EIO;
-}
-
-
-/*
- * On close, we flush all mcd blocks from the buffer cache.
- */
-static void mcd_release(struct cdrom_device_info *cdi)
-{
- if (!--mcd_open_count) {
- mcd_invalidate_buffers();
- }
-}
-
-/*
- * Test for presence of drive and initialize it. Called at boot time.
- */
-
-int __init mcd_init(void)
-{
- struct gendisk *disk = alloc_disk(1);
- int count;
- unsigned char result[3];
- char msg[80];
-
- if (!disk) {
- printk(KERN_INFO "mcd: can't allocated disk.\n");
- return -ENOMEM;
- }
- if (mcd_port <= 0 || mcd_irq <= 0) {
- printk(KERN_INFO "mcd: not probing.\n");
- put_disk(disk);
- return -EIO;
- }
- if (register_blkdev(MAJOR_NR, "mcd")) {
- put_disk(disk);
- return -EIO;
- }
- if (!request_region(mcd_port, 4, "mcd")) {
- printk(KERN_ERR "mcd: Initialization failed, I/O port (%X) already in use\n", mcd_port);
- goto out_region;
- }
-
- mcd_queue = blk_init_queue(do_mcd_request, &mcd_spinlock);
- if (!mcd_queue)
- goto out_queue;
-
- /* check for card */
-
- outb(0, MCDPORT(1)); /* send reset */
- for (count = 0; count < 2000000; count++)
- (void) inb(MCDPORT(1)); /* delay a bit */
-
- outb(0x40, MCDPORT(0)); /* send get-stat cmd */
- for (count = 0; count < 2000000; count++)
- if (!(inb(MCDPORT(1)) & MFL_STATUS))
- break;
-
- if (count >= 2000000) {
- printk(KERN_INFO "mcd: initialisation failed - No mcd device at 0x%x irq %d\n",
- mcd_port, mcd_irq);
- goto out_probe;
- }
- count = inb(MCDPORT(0)); /* pick up the status */
-
- outb(MCMD_GET_VERSION, MCDPORT(0));
- for (count = 0; count < 3; count++)
- if (getValue(result + count)) {
- printk(KERN_ERR "mcd: mitsumi get version failed at 0x%x\n",
- mcd_port);
- goto out_probe;
- }
-
- if (result[0] == result[1] && result[1] == result[2])
- goto out_probe;
-
- mcdVersion = result[2];
-
- if (mcdVersion >= 4)
- outb(4, MCDPORT(2)); /* magic happens */
-
- /* don't get the IRQ until we know for sure the drive is there */
-
- if (request_irq(mcd_irq, mcd_interrupt, SA_INTERRUPT, "Mitsumi CD", NULL)) {
- printk(KERN_ERR "mcd: Unable to get IRQ%d for Mitsumi CD-ROM\n", mcd_irq);
- goto out_probe;
- }
-
- if (result[1] == 'D') {
- MCMD_DATA_READ = MCMD_2X_READ;
- /* Added flag to drop to 1x speed if too many errors */
- mcdDouble = 1;
- } else
- mcd_info.speed = 1;
- sprintf(msg, " mcd: Mitsumi %s Speed CD-ROM at port=0x%x,"
- " irq=%d\n", mcd_info.speed == 1 ? "Single" : "Double",
- mcd_port, mcd_irq);
-
- outb(MCMD_CONFIG_DRIVE, MCDPORT(0));
- outb(0x02, MCDPORT(0));
- outb(0x00, MCDPORT(0));
- getValue(result);
-
- outb(MCMD_CONFIG_DRIVE, MCDPORT(0));
- outb(0x10, MCDPORT(0));
- outb(0x04, MCDPORT(0));
- getValue(result);
-
- mcd_invalidate_buffers();
- mcdPresent = 1;
-
- disk->major = MAJOR_NR;
- disk->first_minor = 0;
- sprintf(disk->disk_name, "mcd");
- disk->fops = &mcd_bdops;
- disk->flags = GENHD_FL_CD;
- mcd_gendisk = disk;
-
- if (register_cdrom(&mcd_info) != 0) {
- printk(KERN_ERR "mcd: Unable to register Mitsumi CD-ROM.\n");
- goto out_cdrom;
- }
- disk->queue = mcd_queue;
- add_disk(disk);
- printk(msg);
- return 0;
-
-out_cdrom:
- free_irq(mcd_irq, NULL);
-out_queue:
- release_region(mcd_port, 4);
-out_probe:
- blk_cleanup_queue(mcd_queue);
-out_region:
- unregister_blkdev(MAJOR_NR, "mcd");
- put_disk(disk);
- return -EIO;
-}
-
-
-static void hsg2msf(long hsg, struct msf *msf)
-{
- hsg += 150;
- msf->min = hsg / 4500;
- hsg %= 4500;
- msf->sec = hsg / 75;
- msf->frame = hsg % 75;
-
- bin2bcd(&msf->min); /* convert to BCD */
- bin2bcd(&msf->sec);
- bin2bcd(&msf->frame);
-}
-
-
-static void bin2bcd(unsigned char *p)
-{
- int u, t;
-
- u = *p % 10;
- t = *p / 10;
- *p = u | (t << 4);
-}
-
-static int bcd2bin(unsigned char bcd)
-{
- return (bcd >> 4) * 10 + (bcd & 0xF);
-}
-
-
-/*
- * See if a status is ready from the drive and return it
- * if it is ready.
- */
-
-static int mcdStatus(void)
-{
- int i;
- int st;
-
- st = inb(MCDPORT(1)) & MFL_STATUS;
- if (!st) {
- i = inb(MCDPORT(0)) & 0xFF;
- return i;
- } else
- return -1;
-}
-
-
-/*
- * Send a play or read command to the drive
- */
-
-static void sendMcdCmd(int cmd, struct mcd_Play_msf *params)
-{
- outb(cmd, MCDPORT(0));
- outb(params->start.min, MCDPORT(0));
- outb(params->start.sec, MCDPORT(0));
- outb(params->start.frame, MCDPORT(0));
- outb(params->end.min, MCDPORT(0));
- outb(params->end.sec, MCDPORT(0));
- outb(params->end.frame, MCDPORT(0));
-}
-
-
-/*
- * Timer interrupt routine to test for status ready from the drive.
- * (see the next routine)
- */
-
-static void mcdStatTimer(unsigned long dummy)
-{
- if (!(inb(MCDPORT(1)) & MFL_STATUS)) {
- wake_up(&mcd_waitq);
- return;
- }
-
- McdTimeout--;
- if (McdTimeout <= 0) {
- wake_up(&mcd_waitq);
- return;
- }
- mcd_timer.function = mcdStatTimer;
- mod_timer(&mcd_timer, jiffies + 1);
-}
-
-
-/*
- * Wait for a status to be returned from the drive. The actual test
- * (see routine above) is done by the timer interrupt to avoid
- * excessive rescheduling.
- */
-
-static int getMcdStatus(int timeout)
-{
- int st;
-
- McdTimeout = timeout;
- mcd_timer.function = mcdStatTimer;
- mod_timer(&mcd_timer, jiffies + 1);
- sleep_on(&mcd_waitq);
- if (McdTimeout <= 0)
- return -1;
-
- st = inb(MCDPORT(0)) & 0xFF;
- if (st == 0xFF)
- return -1;
-
- if ((st & MST_BUSY) == 0 && audioStatus == CDROM_AUDIO_PLAY)
- /* XXX might be an error? look at q-channel? */
- audioStatus = CDROM_AUDIO_COMPLETED;
-
- if (st & MST_DSK_CHG) {
- mcdDiskChanged = 1;
- tocUpToDate = 0;
- audioStatus = CDROM_AUDIO_NO_STATUS;
- }
-
- return st;
-}
-
-
-/* gives current state of the drive This function is quite unreliable,
- and should probably be rewritten by someone, eventually... */
-
-int mcd_drive_status(struct cdrom_device_info *cdi, int slot_nr)
-{
- int st;
-
- st = statusCmd(); /* check drive status */
- if (st == -1)
- return -EIO; /* drive doesn't respond */
- if ((st & MST_READY))
- return CDS_DISC_OK;
- if ((st & MST_DOOR_OPEN))
- return CDS_TRAY_OPEN;
- if ((st & MST_DSK_CHG))
- return CDS_NO_DISC;
- if ((st & MST_BUSY))
- return CDS_DRIVE_NOT_READY;
- return -EIO;
-}
-
-
-/*
- * Read a value from the drive.
- */
-
-static int getValue(unsigned char *result)
-{
- int count;
- int s;
-
- for (count = 0; count < 2000; count++)
- if (!(inb(MCDPORT(1)) & MFL_STATUS))
- break;
-
- if (count >= 2000) {
- printk("mcd: getValue timeout\n");
- return -1;
- }
-
- s = inb(MCDPORT(0)) & 0xFF;
- *result = (unsigned char) s;
- return 0;
-}
-
-/*
- * Read the current Q-channel info. Also used for reading the
- * table of contents.
- */
-
-int GetQChannelInfo(struct mcd_Toc *qp)
-{
- unsigned char notUsed;
- int retry;
-
- for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++) {
- outb(MCMD_GET_Q_CHANNEL, MCDPORT(0));
- if (getMcdStatus(MCD_STATUS_DELAY) != -1)
- break;
- }
-
- if (retry >= MCD_RETRY_ATTEMPTS)
- return -1;
-
- if (getValue(&qp->ctrl_addr) < 0)
- return -1;
- if (getValue(&qp->track) < 0)
- return -1;
- if (getValue(&qp->pointIndex) < 0)
- return -1;
- if (getValue(&qp->trackTime.min) < 0)
- return -1;
- if (getValue(&qp->trackTime.sec) < 0)
- return -1;
- if (getValue(&qp->trackTime.frame) < 0)
- return -1;
- if (getValue(&notUsed) < 0)
- return -1;
- if (getValue(&qp->diskTime.min) < 0)
- return -1;
- if (getValue(&qp->diskTime.sec) < 0)
- return -1;
- if (getValue(&qp->diskTime.frame) < 0)
- return -1;
-
- return 0;
-}
-
-/*
- * Read the table of contents (TOC) and TOC header if necessary
- */
-
-static int updateToc(void)
-{
- if (tocUpToDate)
- return 0;
-
- if (GetDiskInfo() < 0)
- return -EIO;
-
- if (GetToc() < 0)
- return -EIO;
-
- tocUpToDate = 1;
- return 0;
-}
-
-/*
- * Read the table of contents header
- */
-
-static int GetDiskInfo(void)
-{
- int retry;
-
- for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++) {
- outb(MCMD_GET_DISK_INFO, MCDPORT(0));
- if (getMcdStatus(MCD_STATUS_DELAY) != -1)
- break;
- }
-
- if (retry >= MCD_RETRY_ATTEMPTS)
- return -1;
-
- if (getValue(&DiskInfo.first) < 0)
- return -1;
- if (getValue(&DiskInfo.last) < 0)
- return -1;
-
- DiskInfo.first = bcd2bin(DiskInfo.first);
- DiskInfo.last = bcd2bin(DiskInfo.last);
-
-#ifdef MCD_DEBUG
- printk
- ("Disk Info: first %d last %d length %02x:%02x.%02x first %02x:%02x.%02x\n",
- DiskInfo.first, DiskInfo.last, DiskInfo.diskLength.min,
- DiskInfo.diskLength.sec, DiskInfo.diskLength.frame,
- DiskInfo.firstTrack.min, DiskInfo.firstTrack.sec,
- DiskInfo.firstTrack.frame);
-#endif
-
- if (getValue(&DiskInfo.diskLength.min) < 0)
- return -1;
- if (getValue(&DiskInfo.diskLength.sec) < 0)
- return -1;
- if (getValue(&DiskInfo.diskLength.frame) < 0)
- return -1;
- if (getValue(&DiskInfo.firstTrack.min) < 0)
- return -1;
- if (getValue(&DiskInfo.firstTrack.sec) < 0)
- return -1;
- if (getValue(&DiskInfo.firstTrack.frame) < 0)
- return -1;
-
- return 0;
-}
-
-/*
- * Read the table of contents (TOC)
- */
-
-static int GetToc(void)
-{
- int i, px;
- int limit;
- int retry;
- struct mcd_Toc qInfo;
-
- for (i = 0; i < MAX_TRACKS; i++)
- Toc[i].pointIndex = 0;
-
- i = DiskInfo.last + 3;
-
- for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++) {
- outb(MCMD_STOP, MCDPORT(0));
- if (getMcdStatus(MCD_STATUS_DELAY) != -1)
- break;
- }
-
- if (retry >= MCD_RETRY_ATTEMPTS)
- return -1;
-
- for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++) {
- outb(MCMD_SET_MODE, MCDPORT(0));
- outb(0x05, MCDPORT(0)); /* mode: toc */
- mcd_mode = 0x05;
- if (getMcdStatus(MCD_STATUS_DELAY) != -1)
- break;
- }
-
- if (retry >= MCD_RETRY_ATTEMPTS)
- return -1;
-
- for (limit = 300; limit > 0; limit--) {
- if (GetQChannelInfo(&qInfo) < 0)
- break;
-
- px = bcd2bin(qInfo.pointIndex);
- if (px > 0 && px < MAX_TRACKS && qInfo.track == 0)
- if (Toc[px].pointIndex == 0) {
- Toc[px] = qInfo;
- i--;
- }
-
- if (i <= 0)
- break;
- }
-
- Toc[DiskInfo.last + 1].diskTime = DiskInfo.diskLength;
-
- for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++) {
- outb(MCMD_SET_MODE, MCDPORT(0));
- outb(0x01, MCDPORT(0));
- mcd_mode = 1;
- if (getMcdStatus(MCD_STATUS_DELAY) != -1)
- break;
- }
-
-#ifdef MCD_DEBUG
- for (i = 1; i <= DiskInfo.last; i++)
- printk
- ("i = %2d ctl-adr = %02X track %2d px %02X %02X:%02X.%02X %02X:%02X.%02X\n",
- i, Toc[i].ctrl_addr, Toc[i].track, Toc[i].pointIndex,
- Toc[i].trackTime.min, Toc[i].trackTime.sec,
- Toc[i].trackTime.frame, Toc[i].diskTime.min,
- Toc[i].diskTime.sec, Toc[i].diskTime.frame);
- for (i = 100; i < 103; i++)
- printk
- ("i = %2d ctl-adr = %02X track %2d px %02X %02X:%02X.%02X %02X:%02X.%02X\n",
- i, Toc[i].ctrl_addr, Toc[i].track, Toc[i].pointIndex,
- Toc[i].trackTime.min, Toc[i].trackTime.sec,
- Toc[i].trackTime.frame, Toc[i].diskTime.min,
- Toc[i].diskTime.sec, Toc[i].diskTime.frame);
-#endif
-
- return limit > 0 ? 0 : -1;
-}
-
-void __exit mcd_exit(void)
-{
- del_gendisk(mcd_gendisk);
- put_disk(mcd_gendisk);
- if (unregister_cdrom(&mcd_info)) {
- printk(KERN_WARNING "Can't unregister cdrom mcd\n");
- return;
- }
- free_irq(mcd_irq, NULL);
- release_region(mcd_port, 4);
- if (unregister_blkdev(MAJOR_NR, "mcd")) {
- printk(KERN_WARNING "Can't unregister major mcd\n");
- return;
- }
- blk_cleanup_queue(mcd_queue);
- del_timer_sync(&mcd_timer);
-}
-
-#ifdef MODULE
-module_init(mcd_init);
-#endif
-module_exit(mcd_exit);
-
-MODULE_AUTHOR("Martin Harriss");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_BLOCKDEV_MAJOR(MITSUMI_CDROM_MAJOR);
diff --git a/drivers/cdrom/mcd.h b/drivers/cdrom/mcd.h
deleted file mode 100644
index 1e36c4192bb06..0000000000000
--- a/drivers/cdrom/mcd.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Definitions for a Mitsumi CD-ROM interface
- *
- * Copyright (C) 1992 Martin Harriss
- *
- * martin@bdsi.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.
- *
- */
-
-/* Increase this if you get lots of timeouts */
-#define MCD_STATUS_DELAY 1000
-
-/* number of times to retry a command before giving up */
-#define MCD_RETRY_ATTEMPTS 10
-
-/* port access macro */
-#define MCDPORT(x) (mcd_port + (x))
-
-/* How many sectors to read at 1x when an error at 2x speed occurs. */
-/* You can change this to anything from 2 to 32767, but 30 seems to */
-/* work best for me. I have found that when the drive has problems */
-/* reading one sector, it will have troubles reading the next few. */
-#define SINGLE_HOLD_SECTORS 30
-
-#define MCMD_2X_READ 0xC1 /* Double Speed Read DON'T TOUCH! */
-
-/* status bits */
-
-#define MST_CMD_CHECK 0x01 /* command error */
-#define MST_BUSY 0x02 /* now playing */
-#define MST_READ_ERR 0x04 /* read error */
-#define MST_DSK_TYPE 0x08
-#define MST_SERVO_CHECK 0x10
-#define MST_DSK_CHG 0x20 /* disk removed or changed */
-#define MST_READY 0x40 /* disk in the drive */
-#define MST_DOOR_OPEN 0x80 /* door is open */
-
-/* flag bits */
-
-#define MFL_DATA 0x02 /* data available */
-#define MFL_STATUS 0x04 /* status available */
-
-/* commands */
-
-#define MCMD_GET_DISK_INFO 0x10 /* read info from disk */
-#define MCMD_GET_Q_CHANNEL 0x20 /* read info from q channel */
-#define MCMD_GET_STATUS 0x40
-#define MCMD_SET_MODE 0x50
-#define MCMD_SOFT_RESET 0x60
-#define MCMD_STOP 0x70 /* stop play */
-#define MCMD_CONFIG_DRIVE 0x90
-#define MCMD_SET_VOLUME 0xAE /* set audio level */
-#define MCMD_PLAY_READ 0xC0 /* play or read data */
-#define MCMD_GET_VERSION 0xDC
-#define MCMD_EJECT 0xF6 /* eject (FX drive) */
-
-/* borrowed from hd.c */
-
-#define MAX_TRACKS 104
-
-struct msf {
- unsigned char min;
- unsigned char sec;
- unsigned char frame;
-};
-
-struct mcd_Play_msf {
- struct msf start;
- struct msf end;
-};
-
-struct mcd_DiskInfo {
- unsigned char first;
- unsigned char last;
- struct msf diskLength;
- struct msf firstTrack;
-};
-
-struct mcd_Toc {
- unsigned char ctrl_addr;
- unsigned char track;
- unsigned char pointIndex;
- struct msf trackTime;
- struct msf diskTime;
-};
-
-#define test1(x)
-#define test2(x)
-#define test3(x)
-#define test4(x)
-#define test5(x)
-
diff --git a/drivers/cdrom/sbpcd.c b/drivers/cdrom/sbpcd.c
index 31e563f976c1f..fc2c433f6a29b 100644
--- a/drivers/cdrom/sbpcd.c
+++ b/drivers/cdrom/sbpcd.c
@@ -4266,9 +4266,9 @@ static int sbpcd_dev_ioctl(struct cdrom_device_info *cdi, u_int cmd,
sizeof(struct cdrom_read_audio)))
RETURN_UP(-EFAULT);
if (read_audio.nframes < 0 || read_audio.nframes>current_drive->sbp_audsiz) RETURN_UP(-EINVAL);
- i=verify_area(VERIFY_WRITE, read_audio.buf,
- read_audio.nframes*CD_FRAMESIZE_RAW);
- if (i) RETURN_UP(i);
+ if (!access_ok(VERIFY_WRITE, read_audio.buf,
+ read_audio.nframes*CD_FRAMESIZE_RAW))
+ RETURN_UP(-EFAULT);
if (read_audio.addr_format==CDROM_MSF) /* MSF-bin specification of where to start */
block=msf2lba(&read_audio.addr.msf.minute);
diff --git a/drivers/cdrom/sjcd.c b/drivers/cdrom/sjcd.c
index f444b2548479e..4e7a342ec36ff 100644
--- a/drivers/cdrom/sjcd.c
+++ b/drivers/cdrom/sjcd.c
@@ -831,8 +831,8 @@ static int sjcd_ioctl(struct inode *ip, struct file *fp,
printk("SJCD: ioctl: playmsf\n");
#endif
if ((s =
- verify_area(VERIFY_READ, argp,
- sizeof(sjcd_msf))) == 0) {
+ access_ok(VERIFY_READ, argp, sizeof(sjcd_msf))
+ ? 0 : -EFAULT) == 0) {
if (sjcd_audio_status == CDROM_AUDIO_PLAY) {
sjcd_send_cmd(SCMD_PAUSE);
(void) sjcd_receive_status();
@@ -888,8 +888,8 @@ static int sjcd_ioctl(struct inode *ip, struct file *fp,
printk("SJCD: ioctl: readtocentry\n");
#endif
if ((s =
- verify_area(VERIFY_WRITE, argp,
- sizeof(toc_entry))) == 0) {
+ access_ok(VERIFY_WRITE, argp, sizeof(toc_entry))
+ ? 0 : -EFAULT) == 0) {
struct sjcd_hw_disk_info *tp;
if (copy_from_user(&toc_entry, argp,
@@ -943,8 +943,8 @@ static int sjcd_ioctl(struct inode *ip, struct file *fp,
printk("SJCD: ioctl: subchnl\n");
#endif
if ((s =
- verify_area(VERIFY_WRITE, argp,
- sizeof(subchnl))) == 0) {
+ access_ok(VERIFY_WRITE, argp, sizeof(subchnl))
+ ? 0 : -EFAULT) == 0) {
struct sjcd_hw_qinfo q_info;
if (copy_from_user(&subchnl, argp,
@@ -1002,8 +1002,8 @@ static int sjcd_ioctl(struct inode *ip, struct file *fp,
printk("SJCD: ioctl: volctrl\n");
#endif
if ((s =
- verify_area(VERIFY_READ, argp,
- sizeof(vol_ctrl))) == 0) {
+ access_ok(VERIFY_READ, argp, sizeof(vol_ctrl))
+ ? 0 : -EFAULT) == 0) {
unsigned char dummy[4];
if (copy_from_user(&vol_ctrl, argp,
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index e2579ef904625..096a1202ea077 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -59,7 +59,7 @@ config VT_CONSOLE
config HW_CONSOLE
bool
- depends on VT && !S390 && !USERMODE
+ depends on VT && !S390 && !UML
default y
config SERIAL_NONSTANDARD
@@ -148,26 +148,9 @@ config DIGIEPCA
you have a card like this, say Y here and read the file
<file:Documentation/digiepca.txt>.
- NOTE: There is another, separate driver for the Digiboard PC boards:
- "Digiboard PC/Xx Support" below. You should (and can) only select
- one of the two drivers.
-
To compile this driver as a module, choose M here: the
module will be called epca.
-config DIGI
- tristate "Digiboard PC/Xx Support"
- depends on SERIAL_NONSTANDARD && DIGIEPCA=n && BROKEN_ON_SMP
- help
- This is a driver for the Digiboard PC/Xe, PC/Xi, and PC/Xeve cards
- that give you many serial ports. You would need something like this
- to connect more than two modems to your Linux box, for instance in
- order to become a dial-in server. If you have a card like that, say
- Y here and read the file <file:Documentation/digiboard.txt>.
-
- To compile this driver as a module, choose M here: the
- module will be called pcxx.
-
config ESPSERIAL
tristate "Hayes ESP serial port support"
depends on SERIAL_NONSTANDARD && ISA && BROKEN_ON_SMP
@@ -264,7 +247,7 @@ config RISCOM8
config SPECIALIX
tristate "Specialix IO8+ card support"
- depends on SERIAL_NONSTANDARD && BROKEN_ON_SMP
+ depends on SERIAL_NONSTANDARD
help
This is a driver for the Specialix IO8+ multiport card (both the
ISA and the PCI version) which gives you many serial ports. You
@@ -288,7 +271,7 @@ config SPECIALIX_RTSCTS
config SX
tristate "Specialix SX (and SI) card support"
- depends on SERIAL_NONSTANDARD && BROKEN_ON_SMP
+ depends on SERIAL_NONSTANDARD
help
This is a driver for the SX and SI multiport serial cards.
Please read the file <file:Documentation/sx.txt> for details.
@@ -782,6 +765,10 @@ config S3C2410_RTC
Samsung S3C2410. This can provide periodic interrupt rates
from 1Hz to 64Hz for user programs, and wakeup from Alarm.
+config RTC_VR41XX
+ tristate "NEC VR4100 series Real Time Clock Support"
+ depends on CPU_VR41XX
+
config COBALT_LCD
bool "Support for Cobalt LCD"
depends on MIPS_COBALT
@@ -839,6 +826,10 @@ config SONYPI
To compile this driver as a module, choose M here: the
module will be called sonypi.
+config TANBAC_TB0219
+ tristate "TANBAC TB0219 base board support"
+ depends TANBAC_TB0229
+
menu "Ftape, the floppy tape device driver"
@@ -991,5 +982,7 @@ config MMTIMER
The mmtimer device allows direct userspace access to the
Altix system timer.
+source "drivers/char/tpm/Kconfig"
+
endmenu
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index a68bd73dbd896..54ed76af1a478 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -25,7 +25,6 @@ obj-$(CONFIG_SERIAL167) += serial167.o
obj-$(CONFIG_CYCLADES) += cyclades.o
obj-$(CONFIG_STALLION) += stallion.o
obj-$(CONFIG_ISTALLION) += istallion.o
-obj-$(CONFIG_DIGI) += pcxx.o
obj-$(CONFIG_DIGIEPCA) += epca.o
obj-$(CONFIG_SPECIALIX) += specialix.o
obj-$(CONFIG_MOXA_INTELLIO) += moxa.o
@@ -64,6 +63,7 @@ obj-$(CONFIG_SGI_DS1286) += ds1286.o
obj-$(CONFIG_SGI_IP27_RTC) += ip27-rtc.o
obj-$(CONFIG_DS1302) += ds1302.o
obj-$(CONFIG_S3C2410_RTC) += s3c2410-rtc.o
+obj-$(CONFIG_RTC_VR41XX) += vr41xx_rtc.o
ifeq ($(CONFIG_GENERIC_NVRAM),y)
obj-$(CONFIG_NVRAM) += generic_nvram.o
else
@@ -73,13 +73,13 @@ obj-$(CONFIG_TOSHIBA) += toshiba.o
obj-$(CONFIG_I8K) += i8k.o
obj-$(CONFIG_DS1620) += ds1620.o
obj-$(CONFIG_HW_RANDOM) += hw_random.o
-obj-$(CONFIG_QIC02_TAPE) += tpqic02.o
obj-$(CONFIG_FTAPE) += ftape/
obj-$(CONFIG_COBALT_LCD) += lcd.o
obj-$(CONFIG_PPDEV) += ppdev.o
obj-$(CONFIG_NWBUTTON) += nwbutton.o
obj-$(CONFIG_NWFLASH) += nwflash.o
obj-$(CONFIG_SCx200_GPIO) += scx200_gpio.o
+obj-$(CONFIG_TANBAC_TB0219) += tb0219.o
obj-$(CONFIG_WATCHDOG) += watchdog/
obj-$(CONFIG_MWAVE) += mwave/
@@ -89,7 +89,7 @@ obj-$(CONFIG_PCMCIA) += pcmcia/
obj-$(CONFIG_IPMI_HANDLER) += ipmi/
obj-$(CONFIG_HANGCHECK_TIMER) += hangcheck-timer.o
-
+obj-$(CONFIG_TCG_TPM) += tpm/
# Files generated that shall be removed upon make clean
clean-files := consolemap_deftbl.c defkeymap.c qtronixmap.c
diff --git a/drivers/char/agp/Kconfig b/drivers/char/agp/Kconfig
index 4e673b0d6fe3e..7f8c1b53b754e 100644
--- a/drivers/char/agp/Kconfig
+++ b/drivers/char/agp/Kconfig
@@ -1,6 +1,6 @@
config AGP
tristate "/dev/agpgart (AGP Support)" if !GART_IOMMU
- depends on ALPHA || IA64 || PPC32 || X86
+ depends on ALPHA || IA64 || PPC || X86
default y if GART_IOMMU
---help---
AGP (Accelerated Graphics Port) is a bus system mainly used to
@@ -78,7 +78,7 @@ config AGP_AMD64
config AGP_INTEL
tristate "Intel 440LX/BX/GX, I8xx and E7x05 chipset support"
- depends on AGP && X86 && !X86_64
+ depends on AGP && X86
help
This option gives you AGP support for the GLX component of XFree86 4.x
on Intel 440LX/BX/GX, 815, 820, 830, 840, 845, 850, 860, 875,
@@ -89,16 +89,6 @@ config AGP_INTEL
use GLX or DRI, or if you have any Intel integrated graphics
chipsets. If unsure, say Y.
-config AGP_INTEL_MCH
- tristate "Intel i865 chipset support"
- depends on AGP && X86
- help
- This option gives you AGP support for the GLX component of XFree86 4.x
- on Intel chipsets that support Intel EM64T processors.
-
- You should say Y here if you use XFree86 3.3.6 or 4.x and want to
- use GLX or DRI. If unsure, say Y.
-
config AGP_NVIDIA
tristate "NVIDIA nForce/nForce2 chipset support"
depends on AGP && X86 && !X86_64
@@ -156,11 +146,11 @@ config AGP_ALPHA_CORE
default AGP
config AGP_UNINORTH
- tristate "Apple UniNorth AGP support"
+ tristate "Apple UniNorth & U3 AGP support"
depends on AGP && PPC_PMAC
help
This option gives you AGP support for Apple machines with a
- UniNorth bridge.
+ UniNorth or U3 (Apple G5) bridge.
config AGP_EFFICEON
tristate "Transmeta Efficeon support"
@@ -172,3 +162,10 @@ config AGP_EFFICEON
You should say Y here if you use XFree86 3.3.6 or 4.x and want to
use GLX or DRI. If unsure, say Y.
+config AGP_SGI_TIOCA
+ tristate "SGI TIO chipset AGP support"
+ depends on AGP && (IA64_SGI_SN2 || IA64_GENERIC)
+ help
+ This option gives you AGP GART support for the SGI TIO chipset
+ for IA64 processors.
+
diff --git a/drivers/char/agp/Makefile b/drivers/char/agp/Makefile
index 0014bf49a39e3..d33a22f2fa0b9 100644
--- a/drivers/char/agp/Makefile
+++ b/drivers/char/agp/Makefile
@@ -9,11 +9,10 @@ obj-$(CONFIG_AGP_ALPHA_CORE) += alpha-agp.o
obj-$(CONFIG_AGP_EFFICEON) += efficeon-agp.o
obj-$(CONFIG_AGP_HP_ZX1) += hp-agp.o
obj-$(CONFIG_AGP_I460) += i460-agp.o
-obj-$(CONFIG_AGP_INTEL_MCH) += intel-mch-agp.o
obj-$(CONFIG_AGP_INTEL) += intel-agp.o
obj-$(CONFIG_AGP_NVIDIA) += nvidia-agp.o
+obj-$(CONFIG_AGP_SGI_TIOCA) += sgi-agp.o
obj-$(CONFIG_AGP_SIS) += sis-agp.o
obj-$(CONFIG_AGP_SWORKS) += sworks-agp.o
obj-$(CONFIG_AGP_UNINORTH) += uninorth-agp.o
obj-$(CONFIG_AGP_VIA) += via-agp.o
-
diff --git a/drivers/char/agp/agp.h b/drivers/char/agp/agp.h
index aaa2df812d305..ad9c11391d811 100644
--- a/drivers/char/agp/agp.h
+++ b/drivers/char/agp/agp.h
@@ -1,5 +1,6 @@
/*
* AGPGART
+ * Copyright (C) 2004 Silicon Graphics, Inc.
* Copyright (C) 2002-2004 Dave Jones
* Copyright (C) 1999 Jeff Hartmann
* Copyright (C) 1999 Precision Insight, Inc.
@@ -100,18 +101,19 @@ struct agp_bridge_driver {
struct gatt_mask *masks;
int (*fetch_size)(void);
int (*configure)(void);
- void (*agp_enable)(u32);
+ void (*agp_enable)(struct agp_bridge_data *, u32);
void (*cleanup)(void);
void (*tlb_flush)(struct agp_memory *);
- unsigned long (*mask_memory)(unsigned long, int);
+ unsigned long (*mask_memory)(struct agp_bridge_data *,
+ unsigned long, int);
void (*cache_flush)(void);
- int (*create_gatt_table)(void);
- int (*free_gatt_table)(void);
+ int (*create_gatt_table)(struct agp_bridge_data *);
+ int (*free_gatt_table)(struct agp_bridge_data *);
int (*insert_memory)(struct agp_memory *, off_t, int);
int (*remove_memory)(struct agp_memory *, off_t, int);
struct agp_memory *(*alloc_by_type) (size_t, int);
void (*free_by_type)(struct agp_memory *);
- void *(*agp_alloc_page)(void);
+ void *(*agp_alloc_page)(struct agp_bridge_data *);
void (*agp_destroy_page)(void *);
};
@@ -137,8 +139,10 @@ struct agp_bridge_data {
int max_memory_agp; /* in number of pages */
int aperture_size_idx;
int capndx;
+ int flags;
char major_version;
char minor_version;
+ struct list_head list;
};
#define KB(x) ((x) * 1024)
@@ -243,24 +247,26 @@ int agp_frontend_initialize(void);
void agp_frontend_cleanup(void);
/* Generic routines. */
-void agp_generic_enable(u32 mode);
-int agp_generic_create_gatt_table(void);
-int agp_generic_free_gatt_table(void);
+void agp_generic_enable(struct agp_bridge_data *bridge, u32 mode);
+int agp_generic_create_gatt_table(struct agp_bridge_data *bridge);
+int agp_generic_free_gatt_table(struct agp_bridge_data *bridge);
struct agp_memory *agp_create_memory(int scratch_pages);
int agp_generic_insert_memory(struct agp_memory *mem, off_t pg_start, int type);
int agp_generic_remove_memory(struct agp_memory *mem, off_t pg_start, int type);
struct agp_memory *agp_generic_alloc_by_type(size_t page_count, int type);
void agp_generic_free_by_type(struct agp_memory *curr);
-void *agp_generic_alloc_page(void);
+void *agp_generic_alloc_page(struct agp_bridge_data *bridge);
void agp_generic_destroy_page(void *addr);
void agp_free_key(int key);
int agp_num_entries(void);
-u32 agp_collect_device_status(u32 mode, u32 command);
+u32 agp_collect_device_status(struct agp_bridge_data *bridge, u32 mode, u32 command);
void agp_device_command(u32 command, int agp_v3);
int agp_3_5_enable(struct agp_bridge_data *bridge);
void global_cache_flush(void);
void get_agp_version(struct agp_bridge_data *bridge);
-unsigned long agp_generic_mask_memory(unsigned long addr, int type);
+unsigned long agp_generic_mask_memory(struct agp_bridge_data *bridge,
+ unsigned long addr, int type);
+struct agp_bridge_data *agp_generic_find_bridge(struct pci_dev *pdev);
/* generic routines for agp>=3 */
int agp3_generic_fetch_size(void);
@@ -315,4 +321,11 @@ extern int agp_try_unsupported_boot;
#define AGPCTRL_APERENB (1<<8)
#define AGPCTRL_GTLBEN (1<<7)
+#define AGP2_RESERVED_MASK 0x00fffcc8
+#define AGP3_RESERVED_MASK 0x00ff00c4
+
+#define AGP_ERRATA_FASTWRITES 1<<0
+#define AGP_ERRATA_SBA 1<<1
+#define AGP_ERRATA_1X 1<<2
+
#endif /* _AGP_BACKEND_PRIV_H */
diff --git a/drivers/char/agp/ali-agp.c b/drivers/char/agp/ali-agp.c
index d5bce320e432a..c86a22c5499be 100644
--- a/drivers/char/agp/ali-agp.c
+++ b/drivers/char/agp/ali-agp.c
@@ -139,9 +139,9 @@ static void m1541_cache_flush(void)
}
}
-static void *m1541_alloc_page(void)
+static void *m1541_alloc_page(struct agp_bridge_data *bridge)
{
- void *addr = agp_generic_alloc_page();
+ void *addr = agp_generic_alloc_page(agp_bridge);
u32 temp;
if (!addr)
@@ -398,7 +398,7 @@ static int __init agp_ali_init(void)
{
if (agp_off)
return -EINVAL;
- return pci_module_init(&agp_ali_pci_driver);
+ return pci_register_driver(&agp_ali_pci_driver);
}
static void __exit agp_ali_cleanup(void)
diff --git a/drivers/char/agp/alpha-agp.c b/drivers/char/agp/alpha-agp.c
index 8b7ed6b86b397..a072d32005a46 100644
--- a/drivers/char/agp/alpha-agp.c
+++ b/drivers/char/agp/alpha-agp.c
@@ -76,11 +76,12 @@ static void alpha_core_agp_tlbflush(struct agp_memory *mem)
alpha_mv.mv_pci_tbi(agp->hose, 0, -1);
}
-static void alpha_core_agp_enable(u32 mode)
+static void alpha_core_agp_enable(struct agp_bridge_data *bridge, u32 mode)
{
- alpha_agp_info *agp = agp_bridge->dev_private_data;
+ alpha_agp_info *agp = bridge->dev_private_data;
- agp->mode.lw = agp_collect_device_status(mode, agp->capability.lw);
+ agp->mode.lw = agp_collect_device_status(bridge, mode,
+ agp->capability.lw);
agp->mode.bits.enable = 1;
agp->ops->configure(agp);
diff --git a/drivers/char/agp/amd-k7-agp.c b/drivers/char/agp/amd-k7-agp.c
index 52c25243e2fec..f1ea87ea6b65b 100644
--- a/drivers/char/agp/amd-k7-agp.c
+++ b/drivers/char/agp/amd-k7-agp.c
@@ -132,7 +132,7 @@ static int amd_create_gatt_pages(int nr_tables)
#define GET_GATT(addr) (amd_irongate_private.gatt_pages[\
GET_PAGE_DIR_IDX(addr)]->remapped)
-static int amd_create_gatt_table(void)
+static int amd_create_gatt_table(struct agp_bridge_data *bridge)
{
struct aper_size_info_lvl2 *value;
struct amd_page_map page_dir;
@@ -175,7 +175,7 @@ static int amd_create_gatt_table(void)
return 0;
}
-static int amd_free_gatt_table(void)
+static int amd_free_gatt_table(struct agp_bridge_data *bridge)
{
struct amd_page_map page_dir;
@@ -314,7 +314,8 @@ static int amd_insert_memory(struct agp_memory *mem, off_t pg_start, int type)
for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr;
cur_gatt = GET_GATT(addr);
- writel(agp_generic_mask_memory(mem->memory[i], mem->type), cur_gatt+GET_GATT_OFF(addr));
+ writel(agp_generic_mask_memory(agp_bridge,
+ mem->memory[i], mem->type), cur_gatt+GET_GATT_OFF(addr));
readl(cur_gatt+GET_GATT_OFF(addr)); /* PCI Posting. */
}
amd_irongate_tlbflush(mem);
@@ -421,6 +422,53 @@ static int __devinit agp_amdk7_probe(struct pci_dev *pdev,
bridge->dev = pdev;
bridge->capndx = cap_ptr;
+ /* 751 Errata (22564_B-1.PDF)
+ erratum 20: strobe glitch with Nvidia NV10 GeForce cards.
+ system controller may experience noise due to strong drive strengths
+ */
+ if (agp_bridge->dev->device == PCI_DEVICE_ID_AMD_FE_GATE_7006) {
+ u8 cap_ptr=0;
+ struct pci_dev *gfxcard=NULL;
+ while (!cap_ptr) {
+ gfxcard = pci_get_class(PCI_CLASS_DISPLAY_VGA<<8, gfxcard);
+ if (!gfxcard) {
+ printk (KERN_INFO PFX "Couldn't find an AGP VGA controller.\n");
+ return -ENODEV;
+ }
+ cap_ptr = pci_find_capability(gfxcard, PCI_CAP_ID_AGP);
+ if (!cap_ptr) {
+ pci_dev_put(gfxcard);
+ continue;
+ }
+ }
+
+ /* With so many variants of NVidia cards, it's simpler just
+ to blacklist them all, and then whitelist them as needed
+ (if necessary at all). */
+ if (gfxcard->vendor == PCI_VENDOR_ID_NVIDIA) {
+ agp_bridge->flags |= AGP_ERRATA_1X;
+ printk (KERN_INFO PFX "AMD 751 chipset with NVidia GeForce detected. Forcing to 1X due to errata.\n");
+ }
+ pci_dev_put(gfxcard);
+ }
+
+ /* 761 Errata (23613_F.pdf)
+ * Revisions B0/B1 were a disaster.
+ * erratum 44: SYSCLK/AGPCLK skew causes 2X failures -- Force mode to 1X
+ * erratum 45: Timing problem prevents fast writes -- Disable fast write.
+ * erratum 46: Setup violation on AGP SBA pins - Disable side band addressing.
+ * With this lot disabled, we should prevent lockups. */
+ if (agp_bridge->dev->device == PCI_DEVICE_ID_AMD_FE_GATE_700E) {
+ u8 revision=0;
+ pci_read_config_byte(pdev, PCI_REVISION_ID, &revision);
+ if (revision == 0x10 || revision == 0x11) {
+ agp_bridge->flags = AGP_ERRATA_FASTWRITES;
+ agp_bridge->flags |= AGP_ERRATA_SBA;
+ agp_bridge->flags |= AGP_ERRATA_1X;
+ printk (KERN_INFO PFX "AMD 761 chipset with errata detected - disabling AGP fast writes & SBA and forcing to 1X.\n");
+ }
+ }
+
/* Fill in the mode register */
pci_read_config_dword(pdev,
bridge->capndx+PCI_AGP_STATUS,
@@ -480,7 +528,7 @@ static int __init agp_amdk7_init(void)
{
if (agp_off)
return -EINVAL;
- return pci_module_init(&agp_amdk7_pci_driver);
+ return pci_register_driver(&agp_amdk7_pci_driver);
}
static void __exit agp_amdk7_cleanup(void)
diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c
index eca1c4f7add8a..905f0629c44f2 100644
--- a/drivers/char/agp/amd64-agp.c
+++ b/drivers/char/agp/amd64-agp.c
@@ -106,7 +106,8 @@ static int amd64_insert_memory(struct agp_memory *mem, off_t pg_start, int type)
}
for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
- tmp = agp_bridge->driver->mask_memory(mem->memory[i], mem->type);
+ tmp = agp_bridge->driver->mask_memory(agp_bridge,
+ mem->memory[i], mem->type);
BUG_ON(tmp & 0xffffff0000000ffcULL);
pte = (tmp & 0x000000ff00000000ULL) >> 28;
@@ -709,7 +710,7 @@ int __init agp_amd64_init(void)
if (agp_off)
return -EINVAL;
- if (pci_module_init(&agp_amd64_pci_driver) > 0) {
+ if (pci_register_driver(&agp_amd64_pci_driver) > 0) {
struct pci_dev *dev;
if (!agp_try_unsupported && !agp_try_unsupported_boot) {
printk(KERN_INFO PFX "No supported AGP bridge found.\n");
diff --git a/drivers/char/agp/ati-agp.c b/drivers/char/agp/ati-agp.c
index ab17cfdd66299..757dde006fc96 100644
--- a/drivers/char/agp/ati-agp.c
+++ b/drivers/char/agp/ati-agp.c
@@ -291,7 +291,8 @@ static int ati_insert_memory(struct agp_memory * mem,
for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr;
cur_gatt = GET_GATT(addr);
- writel(agp_bridge->driver->mask_memory(mem->memory[i], mem->type), cur_gatt+GET_GATT_OFF(addr));
+ writel(agp_bridge->driver->mask_memory(agp_bridge,
+ mem->memory[i], mem->type), cur_gatt+GET_GATT_OFF(addr));
readl(cur_gatt+GET_GATT_OFF(addr)); /* PCI Posting. */
}
agp_bridge->driver->tlb_flush(mem);
@@ -319,7 +320,7 @@ static int ati_remove_memory(struct agp_memory * mem, off_t pg_start,
return 0;
}
-static int ati_create_gatt_table(void)
+static int ati_create_gatt_table(struct agp_bridge_data *bridge)
{
struct aper_size_info_lvl2 *value;
ati_page_map page_dir;
@@ -380,7 +381,7 @@ static int ati_create_gatt_table(void)
return 0;
}
-static int ati_free_gatt_table(void)
+static int ati_free_gatt_table(struct agp_bridge_data *bridge)
{
ati_page_map page_dir;
@@ -531,7 +532,7 @@ static int __init agp_ati_init(void)
{
if (agp_off)
return -EINVAL;
- return pci_module_init(&agp_ati_pci_driver);
+ return pci_register_driver(&agp_ati_pci_driver);
}
static void __exit agp_ati_cleanup(void)
diff --git a/drivers/char/agp/backend.c b/drivers/char/agp/backend.c
index 9eeaeea49a6c1..c3442f3c64803 100644
--- a/drivers/char/agp/backend.c
+++ b/drivers/char/agp/backend.c
@@ -1,5 +1,6 @@
/*
* AGPGART driver backend routines.
+ * Copyright (C) 2004 Silicon Graphics, Inc.
* Copyright (C) 2002-2003 Dave Jones.
* Copyright (C) 1999 Jeff Hartmann.
* Copyright (C) 1999 Precision Insight, Inc.
@@ -18,12 +19,12 @@
* 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
- * JEFF HARTMANN, DAVE JONES, OR ANY OTHER CONTRIBUTORS 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
+ * JEFF HARTMANN, DAVE JONES, OR ANY OTHER CONTRIBUTORS 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.
*
- * TODO:
+ * TODO:
* - Allocate more than order 0 pages to avoid too much linear map splitting.
*/
#include <linux/module.h>
@@ -42,34 +43,39 @@
* fix some real stupidity. It's only by chance we can bump
* past 0.99 at all due to some boolean logic error. */
#define AGPGART_VERSION_MAJOR 0
-#define AGPGART_VERSION_MINOR 100
+#define AGPGART_VERSION_MINOR 101
static struct agp_version agp_current_version =
{
.major = AGPGART_VERSION_MAJOR,
.minor = AGPGART_VERSION_MINOR,
};
-static int agp_count=0;
+struct agp_bridge_data *(*agp_find_bridge)(struct pci_dev *) =
+ &agp_generic_find_bridge;
-struct agp_bridge_data agp_bridge_dummy = { .type = NOT_SUPPORTED };
-struct agp_bridge_data *agp_bridge = &agp_bridge_dummy;
+struct agp_bridge_data *agp_bridge;
+LIST_HEAD(agp_bridges);
EXPORT_SYMBOL(agp_bridge);
-
+EXPORT_SYMBOL(agp_bridges);
+EXPORT_SYMBOL(agp_find_bridge);
/**
- * agp_backend_acquire - attempt to acquire the agp backend.
+ * agp_backend_acquire - attempt to acquire an agp backend.
*
- * returns -EBUSY if agp is in use,
- * returns 0 if the caller owns the agp backend
*/
-int agp_backend_acquire(void)
+struct agp_bridge_data *agp_backend_acquire(struct pci_dev *pdev)
{
- if (agp_bridge->type == NOT_SUPPORTED)
- return -EINVAL;
- if (atomic_read(&agp_bridge->agp_in_use))
- return -EBUSY;
- atomic_inc(&agp_bridge->agp_in_use);
- return 0;
+ struct agp_bridge_data *bridge;
+
+ bridge = agp_find_bridge(pdev);
+
+ if (!bridge)
+ return NULL;
+
+ if (atomic_read(&bridge->agp_in_use))
+ return NULL;
+ atomic_inc(&bridge->agp_in_use);
+ return bridge;
}
EXPORT_SYMBOL(agp_backend_acquire);
@@ -82,10 +88,11 @@ EXPORT_SYMBOL(agp_backend_acquire);
*
* (Ensure that all memory it bound is unbound.)
*/
-void agp_backend_release(void)
+void agp_backend_release(struct agp_bridge_data *bridge)
{
- if (agp_bridge->type != NOT_SUPPORTED)
- atomic_dec(&agp_bridge->agp_in_use);
+
+ if (bridge)
+ atomic_dec(&bridge->agp_in_use);
}
EXPORT_SYMBOL(agp_backend_release);
@@ -121,7 +128,6 @@ static int agp_find_max(void)
(maxes_table[index].agp - maxes_table[index - 1].agp)) /
(maxes_table[index].mem - maxes_table[index - 1].mem);
- printk(KERN_INFO PFX "Maximum main memory to use for agp memory: %ldM\n", result);
result = result << (20 - PAGE_SHIFT);
return result;
}
@@ -135,7 +141,7 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge)
bridge->version = &agp_current_version;
if (bridge->driver->needs_scratch_page) {
- void *addr = bridge->driver->agp_alloc_page();
+ void *addr = bridge->driver->agp_alloc_page(bridge);
if (!addr) {
printk(KERN_ERR PFX "unable to get memory for scratch page.\n");
@@ -144,7 +150,7 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge)
bridge->scratch_page_real = virt_to_phys(addr);
bridge->scratch_page =
- bridge->driver->mask_memory(bridge->scratch_page_real, 0);
+ bridge->driver->mask_memory(bridge, bridge->scratch_page_real, 0);
}
size_value = bridge->driver->fetch_size();
@@ -153,14 +159,14 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge)
rc = -EINVAL;
goto err_out;
}
- if (bridge->driver->create_gatt_table()) {
+ if (bridge->driver->create_gatt_table(bridge)) {
printk(KERN_ERR PFX
"unable to get memory for graphics translation table.\n");
rc = -ENOMEM;
goto err_out;
}
got_gatt = 1;
-
+
bridge->key_list = vmalloc(PAGE_SIZE * 4);
if (bridge->key_list == NULL) {
printk(KERN_ERR PFX "error allocating memory for key lists.\n");
@@ -168,7 +174,7 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge)
goto err_out;
}
got_keylist = 1;
-
+
/* FIXME vmalloc'd memory not guaranteed contiguous */
memset(bridge->key_list, 0, PAGE_SIZE * 4);
@@ -178,9 +184,6 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge)
goto err_out;
}
- printk(KERN_INFO PFX "AGP aperture is %dM @ 0x%lx\n",
- size_value, bridge->gart_bus_addr);
-
return 0;
err_out:
@@ -188,7 +191,7 @@ err_out:
bridge->driver->agp_destroy_page(
phys_to_virt(bridge->scratch_page_real));
if (got_gatt)
- bridge->driver->free_gatt_table();
+ bridge->driver->free_gatt_table(bridge);
if (got_keylist) {
vfree(bridge->key_list);
bridge->key_list = NULL;
@@ -202,7 +205,7 @@ static void agp_backend_cleanup(struct agp_bridge_data *bridge)
if (bridge->driver->cleanup)
bridge->driver->cleanup();
if (bridge->driver->free_gatt_table)
- bridge->driver->free_gatt_table();
+ bridge->driver->free_gatt_table(bridge);
if (bridge->key_list) {
vfree(bridge->key_list);
bridge->key_list = NULL;
@@ -214,16 +217,35 @@ static void agp_backend_cleanup(struct agp_bridge_data *bridge)
phys_to_virt(bridge->scratch_page_real));
}
-/* XXX Kludge alert: agpgart isn't ready for multiple bridges yet */
+/* When we remove the global variable agp_bridge from all drivers
+ * then agp_alloc_bridge and agp_generic_find_bridge need to be updated
+ */
+
struct agp_bridge_data *agp_alloc_bridge(void)
{
- return agp_bridge;
+ struct agp_bridge_data *bridge = kmalloc(sizeof(*bridge), GFP_KERNEL);
+
+ if (!bridge)
+ return NULL;
+
+ memset(bridge, 0, sizeof(*bridge));
+ atomic_set(&bridge->agp_in_use, 0);
+ atomic_set(&bridge->current_memory_agp, 0);
+
+ if (list_empty(&agp_bridges))
+ agp_bridge = bridge;
+
+ return bridge;
}
EXPORT_SYMBOL(agp_alloc_bridge);
void agp_put_bridge(struct agp_bridge_data *bridge)
{
+ kfree(bridge);
+
+ if (list_empty(&agp_bridges))
+ agp_bridge = NULL;
}
EXPORT_SYMBOL(agp_put_bridge);
@@ -240,40 +262,38 @@ int agp_add_bridge(struct agp_bridge_data *bridge)
return -EINVAL;
}
- if (agp_count) {
- printk (KERN_INFO PFX
- "Only one agpgart device currently supported.\n");
- return -ENODEV;
- }
-
/* Grab reference on the chipset driver. */
if (!try_module_get(bridge->driver->owner)) {
printk (KERN_INFO PFX "Couldn't lock chipset driver.\n");
return -EINVAL;
}
- bridge->type = SUPPORTED;
-
- error = agp_backend_initialize(agp_bridge);
+ error = agp_backend_initialize(bridge);
if (error) {
printk (KERN_INFO PFX "agp_backend_initialize() failed.\n");
goto err_out;
}
- error = agp_frontend_initialize();
- if (error) {
- printk (KERN_INFO PFX "agp_frontend_initialize() failed.\n");
- goto frontend_err;
+ if (list_empty(&agp_bridges)) {
+ error = agp_frontend_initialize();
+ if (error) {
+ printk (KERN_INFO PFX "agp_frontend_initialize() failed.\n");
+ goto frontend_err;
+ }
+
+ printk(KERN_INFO PFX "AGP aperture is %dM @ 0x%lx\n",
+ bridge->driver->fetch_size(), bridge->gart_bus_addr);
+
}
- agp_count++;
+ list_add(&bridge->list, &agp_bridges);
return 0;
frontend_err:
- agp_backend_cleanup(agp_bridge);
+ agp_backend_cleanup(bridge);
err_out:
- bridge->type = NOT_SUPPORTED;
module_put(bridge->driver->owner);
+ agp_put_bridge(bridge);
return error;
}
EXPORT_SYMBOL_GPL(agp_add_bridge);
@@ -281,10 +301,10 @@ EXPORT_SYMBOL_GPL(agp_add_bridge);
void agp_remove_bridge(struct agp_bridge_data *bridge)
{
- bridge->type = NOT_SUPPORTED;
- agp_frontend_cleanup();
agp_backend_cleanup(bridge);
- agp_count--;
+ list_del(&bridge->list);
+ if (list_empty(&agp_bridges))
+ agp_frontend_cleanup();
module_put(bridge->driver->owner);
}
EXPORT_SYMBOL_GPL(agp_remove_bridge);
diff --git a/drivers/char/agp/efficeon-agp.c b/drivers/char/agp/efficeon-agp.c
index 3346da4724ff7..52c0a097118cd 100644
--- a/drivers/char/agp/efficeon-agp.c
+++ b/drivers/char/agp/efficeon-agp.c
@@ -148,7 +148,7 @@ static int efficeon_configure(void)
return 0;
}
-static int efficeon_free_gatt_table(void)
+static int efficeon_free_gatt_table(struct agp_bridge_data *bridge)
{
int index, freed = 0;
@@ -183,7 +183,7 @@ static int efficeon_free_gatt_table(void)
#define GET_GATT(addr) (efficeon_private.gatt_pages[\
GET_PAGE_DIR_IDX(addr)]->remapped)
-static int efficeon_create_gatt_table(void)
+static int efficeon_create_gatt_table(struct agp_bridge_data *bridge)
{
int index;
const int pati = EFFICEON_PATI;
@@ -209,7 +209,7 @@ static int efficeon_create_gatt_table(void)
page = get_zeroed_page(GFP_KERNEL);
if (!page) {
- efficeon_free_gatt_table();
+ efficeon_free_gatt_table(agp_bridge);
return -ENOMEM;
}
SetPageReserved(virt_to_page((char *)page));
@@ -448,7 +448,7 @@ static int __init agp_efficeon_init(void)
return 0;
agp_initialised=1;
- return pci_module_init(&agp_efficeon_pci_driver);
+ return pci_register_driver(&agp_efficeon_pci_driver);
}
static void __exit agp_efficeon_cleanup(void)
diff --git a/drivers/char/agp/frontend.c b/drivers/char/agp/frontend.c
index 471748a713325..f633623ac802f 100644
--- a/drivers/char/agp/frontend.c
+++ b/drivers/char/agp/frontend.c
@@ -1,5 +1,6 @@
/*
* AGPGART driver frontend
+ * Copyright (C) 2004 Silicon Graphics, Inc.
* Copyright (C) 2002-2003 Dave Jones
* Copyright (C) 1999 Jeff Hartmann
* Copyright (C) 1999 Precision Insight, Inc.
@@ -18,9 +19,9 @@
* 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
- * JEFF HARTMANN, OR ANY OTHER CONTRIBUTORS 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
+ * JEFF HARTMANN, OR ANY OTHER CONTRIBUTORS 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.
*
*/
@@ -152,8 +153,8 @@ static void agp_add_seg_to_client(struct agp_client *client,
/* Originally taken from linux/mm/mmap.c from the array
* protection_map.
- * The original really should be exported to modules, or
- * some routine which does the conversion for you
+ * The original really should be exported to modules, or
+ * some routine which does the conversion for you
*/
static const pgprot_t my_protect_map[16] =
@@ -285,8 +286,8 @@ void agp_remove_file_private(struct agp_file_private * priv)
/* End - File flag list routines */
-/*
- * Wrappers for agp_free_memory & agp_allocate_memory
+/*
+ * Wrappers for agp_free_memory & agp_allocate_memory
* These make sure that internal lists are kept updated.
*/
static void agp_free_memory_wrap(struct agp_memory *memory)
@@ -299,7 +300,7 @@ static struct agp_memory *agp_allocate_memory_wrap(size_t pg_count, u32 type)
{
struct agp_memory *memory;
- memory = agp_allocate_memory(pg_count, type);
+ memory = agp_allocate_memory(agp_bridge, pg_count, type);
if (memory == NULL)
return NULL;
@@ -420,7 +421,7 @@ static int agp_remove_controller(struct agp_controller *controller)
if (agp_fe.current_controller == controller) {
agp_fe.current_controller = NULL;
agp_fe.backend_acquired = FALSE;
- agp_backend_release();
+ agp_backend_release(agp_bridge);
}
kfree(controller);
return 0;
@@ -468,10 +469,10 @@ static void agp_controller_release_current(struct agp_controller *controller,
agp_fe.current_controller = NULL;
agp_fe.used_by_controller = FALSE;
- agp_backend_release();
+ agp_backend_release(agp_bridge);
}
-/*
+/*
* Routines for managing client lists -
* These routines are for managing the list of auth'ed clients.
*/
@@ -605,7 +606,7 @@ static int agp_mmap(struct file *file, struct vm_area_struct *vma)
if (!(test_bit(AGP_FF_IS_VALID, &priv->access_flags)))
goto out_eperm;
- agp_copy_info(&kerninfo);
+ agp_copy_info(agp_bridge, &kerninfo);
size = vma->vm_end - vma->vm_start;
current_size = kerninfo.aper_size;
current_size = current_size * 0x100000;
@@ -627,7 +628,7 @@ static int agp_mmap(struct file *file, struct vm_area_struct *vma)
DBG("client vm_ops=%p", kerninfo.vm_ops);
if (kerninfo.vm_ops) {
vma->vm_ops = kerninfo.vm_ops;
- } else if (remap_pfn_range(vma, vma->vm_start,
+ } else if (io_remap_pfn_range(vma, vma->vm_start,
(kerninfo.aper_base + offset) >> PAGE_SHIFT,
size, vma->vm_page_prot)) {
goto out_again;
@@ -643,7 +644,7 @@ static int agp_mmap(struct file *file, struct vm_area_struct *vma)
DBG("controller vm_ops=%p", kerninfo.vm_ops);
if (kerninfo.vm_ops) {
vma->vm_ops = kerninfo.vm_ops;
- } else if (remap_pfn_range(vma, vma->vm_start,
+ } else if (io_remap_pfn_range(vma, vma->vm_start,
kerninfo.aper_base >> PAGE_SHIFT,
size, vma->vm_page_prot)) {
goto out_again;
@@ -757,7 +758,7 @@ static int agpioc_info_wrap(struct agp_file_private *priv, void __user *arg)
struct agp_info userinfo;
struct agp_kern_info kerninfo;
- agp_copy_info(&kerninfo);
+ agp_copy_info(agp_bridge, &kerninfo);
userinfo.version.major = kerninfo.version.major;
userinfo.version.minor = kerninfo.version.minor;
@@ -777,7 +778,6 @@ static int agpioc_info_wrap(struct agp_file_private *priv, void __user *arg)
static int agpioc_acquire_wrap(struct agp_file_private *priv)
{
- int ret;
struct agp_controller *controller;
DBG("");
@@ -788,11 +788,15 @@ static int agpioc_acquire_wrap(struct agp_file_private *priv)
if (agp_fe.current_controller != NULL)
return -EBUSY;
- ret = agp_backend_acquire();
- if (ret == 0)
- agp_fe.backend_acquired = TRUE;
- else
- return ret;
+ if(!agp_bridge)
+ return -ENODEV;
+
+ if (atomic_read(&agp_bridge->agp_in_use))
+ return -EBUSY;
+
+ atomic_inc(&agp_bridge->agp_in_use);
+
+ agp_fe.backend_acquired = TRUE;
controller = agp_find_controller_by_pid(priv->my_pid);
@@ -803,7 +807,7 @@ static int agpioc_acquire_wrap(struct agp_file_private *priv)
if (controller == NULL) {
agp_fe.backend_acquired = FALSE;
- agp_backend_release();
+ agp_backend_release(agp_bridge);
return -ENOMEM;
}
agp_insert_controller(controller);
@@ -830,7 +834,7 @@ static int agpioc_setup_wrap(struct agp_file_private *priv, void __user *arg)
if (copy_from_user(&mode, arg, sizeof(struct agp_setup)))
return -EFAULT;
- agp_enable(mode.agp_mode);
+ agp_enable(agp_bridge, mode.agp_mode);
return 0;
}
@@ -993,24 +997,24 @@ static int agp_ioctl(struct inode *inode, struct file *file,
if ((agp_fe.current_controller == NULL) &&
(cmd != AGPIOC_ACQUIRE)) {
ret_val = -EINVAL;
- goto ioctl_out;
+ goto ioctl_out;
}
if ((agp_fe.backend_acquired != TRUE) &&
(cmd != AGPIOC_ACQUIRE)) {
ret_val = -EBUSY;
- goto ioctl_out;
+ goto ioctl_out;
}
if (cmd != AGPIOC_ACQUIRE) {
if (!(test_bit(AGP_FF_IS_CONTROLLER, &curr_priv->access_flags))) {
ret_val = -EPERM;
- goto ioctl_out;
+ goto ioctl_out;
}
/* Use the original pid of the controller,
* in case it's threaded */
if (agp_fe.current_controller->pid != curr_priv->my_pid) {
ret_val = -EBUSY;
- goto ioctl_out;
+ goto ioctl_out;
}
}
@@ -1022,35 +1026,35 @@ static int agp_ioctl(struct inode *inode, struct file *file,
case AGPIOC_ACQUIRE:
ret_val = agpioc_acquire_wrap(curr_priv);
break;
-
+
case AGPIOC_RELEASE:
ret_val = agpioc_release_wrap(curr_priv);
break;
-
+
case AGPIOC_SETUP:
ret_val = agpioc_setup_wrap(curr_priv, (void __user *) arg);
break;
-
+
case AGPIOC_RESERVE:
ret_val = agpioc_reserve_wrap(curr_priv, (void __user *) arg);
break;
-
+
case AGPIOC_PROTECT:
ret_val = agpioc_protect_wrap(curr_priv);
break;
-
+
case AGPIOC_ALLOCATE:
ret_val = agpioc_allocate_wrap(curr_priv, (void __user *) arg);
break;
-
+
case AGPIOC_DEALLOCATE:
ret_val = agpioc_deallocate_wrap(curr_priv, (int) arg);
break;
-
+
case AGPIOC_BIND:
ret_val = agpioc_bind_wrap(curr_priv, (void __user *) arg);
break;
-
+
case AGPIOC_UNBIND:
ret_val = agpioc_unbind_wrap(curr_priv, (void __user *) arg);
break;
diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c
index d62a51d6be65b..c321a924e38a8 100644
--- a/drivers/char/agp/generic.c
+++ b/drivers/char/agp/generic.c
@@ -1,6 +1,7 @@
/*
* AGPGART driver.
- * Copyright (C) 2002-2004 Dave Jones.
+ * Copyright (C) 2004 Silicon Graphics, Inc.
+ * Copyright (C) 2002-2005 Dave Jones.
* Copyright (C) 1999 Jeff Hartmann.
* Copyright (C) 1999 Precision Insight, Inc.
* Copyright (C) 1999 Xi Graphics, Inc.
@@ -35,6 +36,7 @@
#include <linux/pm.h>
#include <linux/agp_backend.h>
#include <linux/vmalloc.h>
+#include <linux/dma-mapping.h>
#include <linux/mm.h>
#include <asm/io.h>
#include <asm/cacheflush.h>
@@ -139,19 +141,19 @@ void agp_free_memory(struct agp_memory *curr)
{
size_t i;
- if ((agp_bridge->type == NOT_SUPPORTED) || (curr == NULL))
+ if (curr == NULL)
return;
if (curr->is_bound == TRUE)
agp_unbind_memory(curr);
if (curr->type != 0) {
- agp_bridge->driver->free_by_type(curr);
+ curr->bridge->driver->free_by_type(curr);
return;
}
if (curr->page_count != 0) {
for (i = 0; i < curr->page_count; i++) {
- agp_bridge->driver->agp_destroy_page(phys_to_virt(curr->memory[i]));
+ curr->bridge->driver->agp_destroy_page(phys_to_virt(curr->memory[i]));
}
}
agp_free_key(curr->key);
@@ -173,20 +175,23 @@ EXPORT_SYMBOL(agp_free_memory);
*
* It returns NULL whenever memory is unavailable.
*/
-struct agp_memory *agp_allocate_memory(size_t page_count, u32 type)
+struct agp_memory *agp_allocate_memory(struct agp_bridge_data *bridge,
+ size_t page_count, u32 type)
{
int scratch_pages;
struct agp_memory *new;
size_t i;
- if (agp_bridge->type == NOT_SUPPORTED)
+ if (!bridge)
return NULL;
- if ((atomic_read(&agp_bridge->current_memory_agp) + page_count) > agp_bridge->max_memory_agp)
+ if ((atomic_read(&bridge->current_memory_agp) + page_count) > bridge->max_memory_agp)
return NULL;
if (type != 0) {
- new = agp_bridge->driver->alloc_by_type(page_count, type);
+ new = bridge->driver->alloc_by_type(page_count, type);
+ if (new)
+ new->bridge = bridge;
return new;
}
@@ -198,7 +203,7 @@ struct agp_memory *agp_allocate_memory(size_t page_count, u32 type)
return NULL;
for (i = 0; i < page_count; i++) {
- void *addr = agp_bridge->driver->agp_alloc_page();
+ void *addr = bridge->driver->agp_alloc_page(bridge);
if (addr == NULL) {
agp_free_memory(new);
@@ -207,6 +212,7 @@ struct agp_memory *agp_allocate_memory(size_t page_count, u32 type)
new->memory[i] = virt_to_phys(addr);
new->page_count++;
}
+ new->bridge = bridge;
flush_agp_mappings();
@@ -289,6 +295,19 @@ int agp_num_entries(void)
EXPORT_SYMBOL_GPL(agp_num_entries);
+static int check_bridge_mode(struct pci_dev *dev)
+{
+ u32 agp3;
+ u8 cap_ptr;
+
+ cap_ptr = pci_find_capability(dev, PCI_CAP_ID_AGP);
+ pci_read_config_dword(dev, cap_ptr+AGPSTAT, &agp3);
+ if (agp3 & AGPSTAT_MODE_3_0)
+ return 1;
+ return 0;
+}
+
+
/**
* agp_copy_info - copy bridge state information
*
@@ -297,35 +316,36 @@ EXPORT_SYMBOL_GPL(agp_num_entries);
* This function copies information about the agp bridge device and the state of
* the agp backend into an agp_kern_info pointer.
*/
-int agp_copy_info(struct agp_kern_info *info)
+int agp_copy_info(struct agp_bridge_data *bridge, struct agp_kern_info *info)
{
memset(info, 0, sizeof(struct agp_kern_info));
- if (!agp_bridge || agp_bridge->type == NOT_SUPPORTED ||
- !agp_bridge->version) {
+ if (!bridge) {
info->chipset = NOT_SUPPORTED;
return -EIO;
}
- info->version.major = agp_bridge->version->major;
- info->version.minor = agp_bridge->version->minor;
- info->chipset = agp_bridge->type;
- info->device = agp_bridge->dev;
- info->mode = agp_bridge->mode;
- info->aper_base = agp_bridge->gart_bus_addr;
+ info->version.major = bridge->version->major;
+ info->version.minor = bridge->version->minor;
+ info->chipset = SUPPORTED;
+ info->device = bridge->dev;
+ if (check_bridge_mode(bridge->dev))
+ info->mode = bridge->mode & ~AGP3_RESERVED_MASK;
+ else
+ info->mode = bridge->mode & ~AGP2_RESERVED_MASK;
+ info->mode = bridge->mode;
+ info->aper_base = bridge->gart_bus_addr;
info->aper_size = agp_return_size();
- info->max_memory = agp_bridge->max_memory_agp;
- info->current_memory = atomic_read(&agp_bridge->current_memory_agp);
- info->cant_use_aperture = agp_bridge->driver->cant_use_aperture;
- info->vm_ops = agp_bridge->vm_ops;
+ info->max_memory = bridge->max_memory_agp;
+ info->current_memory = atomic_read(&bridge->current_memory_agp);
+ info->cant_use_aperture = bridge->driver->cant_use_aperture;
+ info->vm_ops = bridge->vm_ops;
info->page_mask = ~0UL;
return 0;
}
EXPORT_SYMBOL(agp_copy_info);
-
/* End - Routine to copy over information structure */
-
/*
* Routines for handling swapping of agp_memory into the GATT -
* These routines take agp_memory and insert them into the GATT.
@@ -345,7 +365,7 @@ int agp_bind_memory(struct agp_memory *curr, off_t pg_start)
{
int ret_val;
- if ((agp_bridge->type == NOT_SUPPORTED) || (curr == NULL))
+ if (curr == NULL)
return -EINVAL;
if (curr->is_bound == TRUE) {
@@ -353,10 +373,10 @@ int agp_bind_memory(struct agp_memory *curr, off_t pg_start)
return -EINVAL;
}
if (curr->is_flushed == FALSE) {
- agp_bridge->driver->cache_flush();
+ curr->bridge->driver->cache_flush();
curr->is_flushed = TRUE;
}
- ret_val = agp_bridge->driver->insert_memory(curr, pg_start, curr->type);
+ ret_val = curr->bridge->driver->insert_memory(curr, pg_start, curr->type);
if (ret_val != 0)
return ret_val;
@@ -380,7 +400,7 @@ int agp_unbind_memory(struct agp_memory *curr)
{
int ret_val;
- if ((agp_bridge->type == NOT_SUPPORTED) || (curr == NULL))
+ if (curr == NULL)
return -EINVAL;
if (curr->is_bound != TRUE) {
@@ -388,7 +408,7 @@ int agp_unbind_memory(struct agp_memory *curr)
return -EINVAL;
}
- ret_val = agp_bridge->driver->remove_memory(curr, curr->pg_start, curr->type);
+ ret_val = curr->bridge->driver->remove_memory(curr, curr->pg_start, curr->type);
if (ret_val != 0)
return ret_val;
@@ -403,71 +423,133 @@ EXPORT_SYMBOL(agp_unbind_memory);
/* Generic Agp routines - Start */
-static void agp_v2_parse_one(u32 *mode, u32 *cmd, u32 *tmp)
+static void agp_v2_parse_one(u32 *requested_mode, u32 *bridge_agpstat, u32 *vga_agpstat)
{
+ u32 tmp;
+
+ if (*requested_mode & AGP2_RESERVED_MASK) {
+ printk (KERN_INFO PFX "reserved bits set in mode 0x%x. Fixed.\n", *requested_mode);
+ *requested_mode &= ~AGP2_RESERVED_MASK;
+ }
+
+ /* Check the speed bits make sense. Only one should be set. */
+ tmp = *requested_mode & 7;
+ switch (tmp) {
+ case 0:
+ printk (KERN_INFO PFX "%s tried to set rate=x0. Setting to x1 mode.\n", current->comm);
+ *requested_mode |= AGPSTAT2_1X;
+ break;
+ case 1:
+ case 2:
+ break;
+ case 3:
+ *requested_mode &= ~(AGPSTAT2_1X); /* rate=2 */
+ break;
+ case 4:
+ break;
+ case 5:
+ case 6:
+ case 7:
+ *requested_mode &= ~(AGPSTAT2_1X|AGPSTAT2_2X); /* rate=4*/
+ break;
+ }
+
/* disable SBA if it's not supported */
- if (!((*cmd & AGPSTAT_SBA) && (*tmp & AGPSTAT_SBA) && (*mode & AGPSTAT_SBA)))
- *cmd &= ~AGPSTAT_SBA;
+ if (!((*bridge_agpstat & AGPSTAT_SBA) && (*vga_agpstat & AGPSTAT_SBA) && (*requested_mode & AGPSTAT_SBA)))
+ *bridge_agpstat &= ~AGPSTAT_SBA;
- /* Set speed */
- if (!((*cmd & AGPSTAT2_4X) && (*tmp & AGPSTAT2_4X) && (*mode & AGPSTAT2_4X)))
- *cmd &= ~AGPSTAT2_4X;
+ /* Set rate */
+ if (!((*bridge_agpstat & AGPSTAT2_4X) && (*vga_agpstat & AGPSTAT2_4X) && (*requested_mode & AGPSTAT2_4X)))
+ *bridge_agpstat &= ~AGPSTAT2_4X;
- if (!((*cmd & AGPSTAT2_2X) && (*tmp & AGPSTAT2_2X) && (*mode & AGPSTAT2_2X)))
- *cmd &= ~AGPSTAT2_2X;
+ if (!((*bridge_agpstat & AGPSTAT2_2X) && (*vga_agpstat & AGPSTAT2_2X) && (*requested_mode & AGPSTAT2_2X)))
+ *bridge_agpstat &= ~AGPSTAT2_2X;
- if (!((*cmd & AGPSTAT2_1X) && (*tmp & AGPSTAT2_1X) && (*mode & AGPSTAT2_1X)))
- *cmd &= ~AGPSTAT2_1X;
+ if (!((*bridge_agpstat & AGPSTAT2_1X) && (*vga_agpstat & AGPSTAT2_1X) && (*requested_mode & AGPSTAT2_1X)))
+ *bridge_agpstat &= ~AGPSTAT2_1X;
/* Now we know what mode it should be, clear out the unwanted bits. */
- if (*cmd & AGPSTAT2_4X)
- *cmd &= ~(AGPSTAT2_1X | AGPSTAT2_2X); /* 4X */
+ if (*bridge_agpstat & AGPSTAT2_4X)
+ *bridge_agpstat &= ~(AGPSTAT2_1X | AGPSTAT2_2X); /* 4X */
+
+ if (*bridge_agpstat & AGPSTAT2_2X)
+ *bridge_agpstat &= ~(AGPSTAT2_1X | AGPSTAT2_4X); /* 2X */
+
+ if (*bridge_agpstat & AGPSTAT2_1X)
+ *bridge_agpstat &= ~(AGPSTAT2_2X | AGPSTAT2_4X); /* 1X */
- if (*cmd & AGPSTAT2_2X)
- *cmd &= ~(AGPSTAT2_1X | AGPSTAT2_4X); /* 2X */
+ /* Apply any errata. */
+ if (agp_bridge->flags & AGP_ERRATA_FASTWRITES)
+ *bridge_agpstat &= ~AGPSTAT_FW;
- if (*cmd & AGPSTAT2_1X)
- *cmd &= ~(AGPSTAT2_2X | AGPSTAT2_4X); /* 1X */
+ if (agp_bridge->flags & AGP_ERRATA_SBA)
+ *bridge_agpstat &= ~AGPSTAT_SBA;
+
+ if (agp_bridge->flags & AGP_ERRATA_1X) {
+ *bridge_agpstat &= ~(AGPSTAT2_2X | AGPSTAT2_4X);
+ *bridge_agpstat |= AGPSTAT2_1X;
+ }
+
+ /* If we've dropped down to 1X, disable fast writes. */
+ if (*bridge_agpstat & AGPSTAT2_1X)
+ *bridge_agpstat &= ~AGPSTAT_FW;
}
/*
- * mode = requested mode.
- * cmd = PCI_AGP_STATUS from agp bridge.
- * tmp = PCI_AGP_STATUS from graphic card.
+ * requested_mode = Mode requested by (typically) X.
+ * bridge_agpstat = PCI_AGP_STATUS from agp bridge.
+ * vga_agpstat = PCI_AGP_STATUS from graphic card.
*/
-static void agp_v3_parse_one(u32 *mode, u32 *cmd, u32 *tmp)
+static void agp_v3_parse_one(u32 *requested_mode, u32 *bridge_agpstat, u32 *vga_agpstat)
{
- u32 origcmd=*cmd, origtmp=*tmp;
+ u32 origbridge=*bridge_agpstat, origvga=*vga_agpstat;
+ u32 tmp;
+
+ if (*requested_mode & AGP3_RESERVED_MASK) {
+ printk (KERN_INFO PFX "reserved bits set in mode 0x%x. Fixed.\n", *requested_mode);
+ *requested_mode &= ~AGP3_RESERVED_MASK;
+ }
+
+ /* Check the speed bits make sense. */
+ tmp = *requested_mode & 7;
+ if (tmp == 0) {
+ printk (KERN_INFO PFX "%s tried to set rate=x0. Setting to AGP3 x4 mode.\n", current->comm);
+ *requested_mode |= AGPSTAT3_4X;
+ }
+ if (tmp >= 3) {
+ printk (KERN_INFO PFX "%s tried to set rate=x%d. Setting to AGP3 x8 mode.\n", current->comm, tmp * 4);
+ *requested_mode = (*requested_mode & ~7) | AGPSTAT3_8X;
+ }
/* ARQSZ - Set the value to the maximum one.
* Don't allow the mode register to override values. */
- *cmd = ((*cmd & ~AGPSTAT_ARQSZ) |
- max_t(u32,(*cmd & AGPSTAT_ARQSZ),(*tmp & AGPSTAT_ARQSZ)));
+ *bridge_agpstat = ((*bridge_agpstat & ~AGPSTAT_ARQSZ) |
+ max_t(u32,(*bridge_agpstat & AGPSTAT_ARQSZ),(*vga_agpstat & AGPSTAT_ARQSZ)));
/* Calibration cycle.
* Don't allow the mode register to override values. */
- *cmd = ((*cmd & ~AGPSTAT_CAL_MASK) |
- min_t(u32,(*cmd & AGPSTAT_CAL_MASK),(*tmp & AGPSTAT_CAL_MASK)));
+ *bridge_agpstat = ((*bridge_agpstat & ~AGPSTAT_CAL_MASK) |
+ min_t(u32,(*bridge_agpstat & AGPSTAT_CAL_MASK),(*vga_agpstat & AGPSTAT_CAL_MASK)));
/* SBA *must* be supported for AGP v3 */
- *cmd |= AGPSTAT_SBA;
+ *bridge_agpstat |= AGPSTAT_SBA;
/*
* Set speed.
* Check for invalid speeds. This can happen when applications
* written before the AGP 3.0 standard pass AGP2.x modes to AGP3 hardware
*/
- if (*mode & AGPSTAT_MODE_3_0) {
+ if (*requested_mode & AGPSTAT_MODE_3_0) {
/*
- * Caller hasn't a clue what its doing. We are in 3.0 mode,
+ * Caller hasn't a clue what it is doing. Bridge is in 3.0 mode,
* have been passed a 3.0 mode, but with 2.x speed bits set.
* AGP2.x 4x -> AGP3.0 4x.
*/
- if (*mode & AGPSTAT2_4X) {
+ if (*requested_mode & AGPSTAT2_4X) {
printk (KERN_INFO PFX "%s passes broken AGP3 flags (%x). Fixed.\n",
- current->comm, *mode);
- *mode &= ~AGPSTAT2_4X;
- *mode |= AGPSTAT3_4X;
+ current->comm, *requested_mode);
+ *requested_mode &= ~AGPSTAT2_4X;
+ *requested_mode |= AGPSTAT3_4X;
}
} else {
/*
@@ -476,27 +558,27 @@ static void agp_v3_parse_one(u32 *mode, u32 *cmd, u32 *tmp)
* Convert AGP 1x,2x,4x -> AGP 3.0 4x.
*/
printk (KERN_INFO PFX "%s passes broken AGP2 flags (%x) in AGP3 mode. Fixed.\n",
- current->comm, *mode);
- *mode &= ~(AGPSTAT2_4X | AGPSTAT2_2X | AGPSTAT2_1X);
- *mode |= AGPSTAT3_4X;
+ current->comm, *requested_mode);
+ *requested_mode &= ~(AGPSTAT2_4X | AGPSTAT2_2X | AGPSTAT2_1X);
+ *requested_mode |= AGPSTAT3_4X;
}
- if (*mode & AGPSTAT3_8X) {
- if (!(*cmd & AGPSTAT3_8X)) {
- *cmd &= ~(AGPSTAT3_8X | AGPSTAT3_RSVD);
- *cmd |= AGPSTAT3_4X;
+ if (*requested_mode & AGPSTAT3_8X) {
+ if (!(*bridge_agpstat & AGPSTAT3_8X)) {
+ *bridge_agpstat &= ~(AGPSTAT3_8X | AGPSTAT3_RSVD);
+ *bridge_agpstat |= AGPSTAT3_4X;
printk ("%s requested AGPx8 but bridge not capable.\n", current->comm);
return;
}
- if (!(*tmp & AGPSTAT3_8X)) {
- *cmd &= ~(AGPSTAT3_8X | AGPSTAT3_RSVD);
- *cmd |= AGPSTAT3_4X;
+ if (!(*vga_agpstat & AGPSTAT3_8X)) {
+ *bridge_agpstat &= ~(AGPSTAT3_8X | AGPSTAT3_RSVD);
+ *bridge_agpstat |= AGPSTAT3_4X;
printk ("%s requested AGPx8 but graphic card not capable.\n", current->comm);
return;
}
/* All set, bridge & device can do AGP x8*/
- *cmd &= ~(AGPSTAT3_4X | AGPSTAT3_RSVD);
- return;
+ *bridge_agpstat &= ~(AGPSTAT3_4X | AGPSTAT3_RSVD);
+ goto done;
} else {
@@ -505,71 +587,97 @@ static void agp_v3_parse_one(u32 *mode, u32 *cmd, u32 *tmp)
* If the hardware can't do x4, we're up shit creek, and never
* should have got this far.
*/
- *cmd &= ~(AGPSTAT3_8X | AGPSTAT3_RSVD);
- if ((*cmd & AGPSTAT3_4X) && (*tmp & AGPSTAT3_4X))
- *cmd |= AGPSTAT3_4X;
+ *bridge_agpstat &= ~(AGPSTAT3_8X | AGPSTAT3_RSVD);
+ if ((*bridge_agpstat & AGPSTAT3_4X) && (*vga_agpstat & AGPSTAT3_4X))
+ *bridge_agpstat |= AGPSTAT3_4X;
else {
printk (KERN_INFO PFX "Badness. Don't know which AGP mode to set. "
- "[cmd:%x tmp:%x fell back to:- cmd:%x tmp:%x]\n",
- origcmd, origtmp, *cmd, *tmp);
- if (!(*cmd & AGPSTAT3_4X))
+ "[bridge_agpstat:%x vga_agpstat:%x fell back to:- bridge_agpstat:%x vga_agpstat:%x]\n",
+ origbridge, origvga, *bridge_agpstat, *vga_agpstat);
+ if (!(*bridge_agpstat & AGPSTAT3_4X))
printk (KERN_INFO PFX "Bridge couldn't do AGP x4.\n");
- if (!(*tmp & AGPSTAT3_4X))
+ if (!(*vga_agpstat & AGPSTAT3_4X))
printk (KERN_INFO PFX "Graphic card couldn't do AGP x4.\n");
+ return;
}
}
+
+done:
+ /* Apply any errata. */
+ if (agp_bridge->flags & AGP_ERRATA_FASTWRITES)
+ *bridge_agpstat &= ~AGPSTAT_FW;
+
+ if (agp_bridge->flags & AGP_ERRATA_SBA)
+ *bridge_agpstat &= ~AGPSTAT_SBA;
+
+ if (agp_bridge->flags & AGP_ERRATA_1X) {
+ *bridge_agpstat &= ~(AGPSTAT2_2X | AGPSTAT2_4X);
+ *bridge_agpstat |= AGPSTAT2_1X;
+ }
}
-//FIXME: This doesn't smell right.
-//We need a function we pass an agp_device to.
-u32 agp_collect_device_status(u32 mode, u32 cmd)
+
+/**
+ * agp_collect_device_status - determine correct agp_cmd from various agp_stat's
+ * @bridge: an agp_bridge_data struct allocated for the AGP host bridge.
+ * @requested_mode: requested agp_stat from userspace (Typically from X)
+ * @bridge_agpstat: current agp_stat from AGP bridge.
+ *
+ * This function will hunt for an AGP graphics card, and try to match
+ * the requested mode to the capabilities of both the bridge and the card.
+ */
+u32 agp_collect_device_status(struct agp_bridge_data *bridge, u32 requested_mode, u32 bridge_agpstat)
{
struct pci_dev *device = NULL;
+ u32 vga_agpstat;
u8 cap_ptr;
- u32 tmp;
- u32 agp3;
- for_each_pci_dev(device) {
+ for (;;) {
+ device = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, device);
+ if (!device) {
+ printk (KERN_INFO PFX "Couldn't find an AGP VGA controller.\n");
+ return 0;
+ }
cap_ptr = pci_find_capability(device, PCI_CAP_ID_AGP);
- if (!cap_ptr)
- continue;
-
- //FIXME: We should probably skip anything here that
- // isn't an AGP graphic card.
- /*
- * Ok, here we have a AGP device. Disable impossible
- * settings, and adjust the readqueue to the minimum.
- */
- pci_read_config_dword(device, cap_ptr+PCI_AGP_STATUS, &tmp);
-
- /* adjust RQ depth */
- cmd = ((cmd & ~AGPSTAT_RQ_DEPTH) |
- min_t(u32, (mode & AGPSTAT_RQ_DEPTH),
- min_t(u32, (cmd & AGPSTAT_RQ_DEPTH), (tmp & AGPSTAT_RQ_DEPTH))));
+ if (cap_ptr)
+ break;
+ }
- /* disable FW if it's not supported */
- if (!((cmd & AGPSTAT_FW) && (tmp & AGPSTAT_FW) && (mode & AGPSTAT_FW)))
- cmd &= ~AGPSTAT_FW;
+ /*
+ * Ok, here we have a AGP device. Disable impossible
+ * settings, and adjust the readqueue to the minimum.
+ */
+ pci_read_config_dword(device, cap_ptr+PCI_AGP_STATUS, &vga_agpstat);
+
+ /* adjust RQ depth */
+ bridge_agpstat = ((bridge_agpstat & ~AGPSTAT_RQ_DEPTH) |
+ min_t(u32, (requested_mode & AGPSTAT_RQ_DEPTH),
+ min_t(u32, (bridge_agpstat & AGPSTAT_RQ_DEPTH), (vga_agpstat & AGPSTAT_RQ_DEPTH))));
+
+ /* disable FW if it's not supported */
+ if (!((bridge_agpstat & AGPSTAT_FW) &&
+ (vga_agpstat & AGPSTAT_FW) &&
+ (requested_mode & AGPSTAT_FW)))
+ bridge_agpstat &= ~AGPSTAT_FW;
+
+ /* Check to see if we are operating in 3.0 mode */
+ if (check_bridge_mode(agp_bridge->dev))
+ agp_v3_parse_one(&requested_mode, &bridge_agpstat, &vga_agpstat);
+ else
+ agp_v2_parse_one(&requested_mode, &bridge_agpstat, &vga_agpstat);
- /* Check to see if we are operating in 3.0 mode */
- pci_read_config_dword(device, cap_ptr+AGPSTAT, &agp3);
- if (agp3 & AGPSTAT_MODE_3_0) {
- agp_v3_parse_one(&mode, &cmd, &tmp);
- } else {
- agp_v2_parse_one(&mode, &cmd, &tmp);
- }
- }
- return cmd;
+ pci_dev_put(device);
+ return bridge_agpstat;
}
EXPORT_SYMBOL(agp_collect_device_status);
-void agp_device_command(u32 command, int agp_v3)
+void agp_device_command(u32 bridge_agpstat, int agp_v3)
{
struct pci_dev *device = NULL;
int mode;
- mode = command & 0x7;
+ mode = bridge_agpstat & 0x7;
if (agp_v3)
mode *= 4;
@@ -580,7 +688,7 @@ void agp_device_command(u32 command, int agp_v3)
printk(KERN_INFO PFX "Putting AGP V%d device at %s into %dx mode\n",
agp_v3 ? 3 : 2, pci_name(device), mode);
- pci_write_config_dword(device, agp + PCI_AGP_COMMAND, command);
+ pci_write_config_dword(device, agp + PCI_AGP_COMMAND, bridge_agpstat);
}
}
EXPORT_SYMBOL(agp_device_command);
@@ -591,52 +699,53 @@ void get_agp_version(struct agp_bridge_data *bridge)
u32 ncapid;
/* Exit early if already set by errata workarounds. */
- if (agp_bridge->major_version != 0)
+ if (bridge->major_version != 0)
return;
- pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx, &ncapid);
- agp_bridge->major_version = (ncapid >> AGP_MAJOR_VERSION_SHIFT) & 0xf;
- agp_bridge->minor_version = (ncapid >> AGP_MINOR_VERSION_SHIFT) & 0xf;
+ pci_read_config_dword(bridge->dev, bridge->capndx, &ncapid);
+ bridge->major_version = (ncapid >> AGP_MAJOR_VERSION_SHIFT) & 0xf;
+ bridge->minor_version = (ncapid >> AGP_MINOR_VERSION_SHIFT) & 0xf;
}
EXPORT_SYMBOL(get_agp_version);
-void agp_generic_enable(u32 mode)
+void agp_generic_enable(struct agp_bridge_data *bridge, u32 requested_mode)
{
- u32 command, temp;
- u32 agp3;
+ u32 bridge_agpstat, temp;
get_agp_version(agp_bridge);
printk(KERN_INFO PFX "Found an AGP %d.%d compliant device at %s.\n",
agp_bridge->major_version,
agp_bridge->minor_version,
- agp_bridge->dev->slot_name);
+ pci_name(agp_bridge->dev));
pci_read_config_dword(agp_bridge->dev,
- agp_bridge->capndx + PCI_AGP_STATUS, &command);
+ agp_bridge->capndx + PCI_AGP_STATUS, &bridge_agpstat);
- command = agp_collect_device_status(mode, command);
- command |= AGPSTAT_AGP_ENABLE;
+ bridge_agpstat = agp_collect_device_status(agp_bridge, requested_mode, bridge_agpstat);
+ if (bridge_agpstat == 0)
+ /* Something bad happened. FIXME: Return error code? */
+ return;
- /* Do AGP version specific frobbing. */
- if(agp_bridge->major_version >= 3) {
- pci_read_config_dword(agp_bridge->dev,
- agp_bridge->capndx+AGPSTAT, &agp3);
+ bridge_agpstat |= AGPSTAT_AGP_ENABLE;
- /* Check to see if we are operating in 3.0 mode */
- if (agp3 & AGPSTAT_MODE_3_0) {
+ /* Do AGP version specific frobbing. */
+ if (bridge->major_version >= 3) {
+ if (check_bridge_mode(bridge->dev)) {
/* If we have 3.5, we can do the isoch stuff. */
- if (agp_bridge->minor_version >= 5)
- agp_3_5_enable(agp_bridge);
- agp_device_command(command, TRUE);
+ if (bridge->minor_version >= 5)
+ agp_3_5_enable(bridge);
+ agp_device_command(bridge_agpstat, TRUE);
return;
} else {
/* Disable calibration cycle in RX91<1> when not in AGP3.0 mode of operation.*/
- command &= ~(7<<10) ;
- pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx+AGPCTRL, &temp);
+ bridge_agpstat &= ~(7<<10) ;
+ pci_read_config_dword(bridge->dev,
+ bridge->capndx+AGPCTRL, &temp);
temp |= (1<<9);
- pci_write_config_dword(agp_bridge->dev, agp_bridge->capndx+AGPCTRL, temp);
+ pci_write_config_dword(bridge->dev,
+ bridge->capndx+AGPCTRL, temp);
printk (KERN_INFO PFX "Device is in legacy mode,"
" falling back to 2.x\n");
@@ -644,12 +753,12 @@ void agp_generic_enable(u32 mode)
}
/* AGP v<3 */
- agp_device_command(command, FALSE);
+ agp_device_command(bridge_agpstat, FALSE);
}
EXPORT_SYMBOL(agp_generic_enable);
-int agp_generic_create_gatt_table(void)
+int agp_generic_create_gatt_table(struct agp_bridge_data *bridge)
{
char *table;
char *table_end;
@@ -661,17 +770,17 @@ int agp_generic_create_gatt_table(void)
struct page *page;
/* The generic routines can't handle 2 level gatt's */
- if (agp_bridge->driver->size_type == LVL2_APER_SIZE)
+ if (bridge->driver->size_type == LVL2_APER_SIZE)
return -EINVAL;
table = NULL;
- i = agp_bridge->aperture_size_idx;
- temp = agp_bridge->current_size;
+ i = bridge->aperture_size_idx;
+ temp = bridge->current_size;
size = page_order = num_entries = 0;
- if (agp_bridge->driver->size_type != FIXED_APER_SIZE) {
+ if (bridge->driver->size_type != FIXED_APER_SIZE) {
do {
- switch (agp_bridge->driver->size_type) {
+ switch (bridge->driver->size_type) {
case U8_APER_SIZE:
size = A_SIZE_8(temp)->size;
page_order =
@@ -702,29 +811,29 @@ int agp_generic_create_gatt_table(void)
if (table == NULL) {
i++;
- switch (agp_bridge->driver->size_type) {
+ switch (bridge->driver->size_type) {
case U8_APER_SIZE:
- agp_bridge->current_size = A_IDX8(agp_bridge);
+ bridge->current_size = A_IDX8(bridge);
break;
case U16_APER_SIZE:
- agp_bridge->current_size = A_IDX16(agp_bridge);
+ bridge->current_size = A_IDX16(bridge);
break;
case U32_APER_SIZE:
- agp_bridge->current_size = A_IDX32(agp_bridge);
+ bridge->current_size = A_IDX32(bridge);
break;
/* This case will never really happen. */
case FIXED_APER_SIZE:
case LVL2_APER_SIZE:
default:
- agp_bridge->current_size =
- agp_bridge->current_size;
+ bridge->current_size =
+ bridge->current_size;
break;
}
- temp = agp_bridge->current_size;
+ temp = bridge->current_size;
} else {
- agp_bridge->aperture_size_idx = i;
+ bridge->aperture_size_idx = i;
}
- } while (!table && (i < agp_bridge->driver->num_aperture_sizes));
+ } while (!table && (i < bridge->driver->num_aperture_sizes));
} else {
size = ((struct aper_size_info_fixed *) temp)->size;
page_order = ((struct aper_size_info_fixed *) temp)->page_order;
@@ -740,15 +849,15 @@ int agp_generic_create_gatt_table(void)
for (page = virt_to_page(table); page <= virt_to_page(table_end); page++)
SetPageReserved(page);
- agp_bridge->gatt_table_real = (u32 *) table;
+ bridge->gatt_table_real = (u32 *) table;
agp_gatt_table = (void *)table;
- agp_bridge->driver->cache_flush();
- agp_bridge->gatt_table = ioremap_nocache(virt_to_phys(table),
+ bridge->driver->cache_flush();
+ bridge->gatt_table = ioremap_nocache(virt_to_phys(table),
(PAGE_SIZE * (1 << page_order)));
- agp_bridge->driver->cache_flush();
+ bridge->driver->cache_flush();
- if (agp_bridge->gatt_table == NULL) {
+ if (bridge->gatt_table == NULL) {
for (page = virt_to_page(table); page <= virt_to_page(table_end); page++)
ClearPageReserved(page);
@@ -756,28 +865,28 @@ int agp_generic_create_gatt_table(void)
return -ENOMEM;
}
- agp_bridge->gatt_bus_addr = virt_to_phys(agp_bridge->gatt_table_real);
+ bridge->gatt_bus_addr = virt_to_phys(bridge->gatt_table_real);
/* AK: bogus, should encode addresses > 4GB */
for (i = 0; i < num_entries; i++) {
- writel(agp_bridge->scratch_page, agp_bridge->gatt_table+i);
- readl(agp_bridge->gatt_table+i); /* PCI Posting. */
+ writel(bridge->scratch_page, bridge->gatt_table+i);
+ readl(bridge->gatt_table+i); /* PCI Posting. */
}
return 0;
}
EXPORT_SYMBOL(agp_generic_create_gatt_table);
-int agp_generic_free_gatt_table(void)
+int agp_generic_free_gatt_table(struct agp_bridge_data *bridge)
{
int page_order;
char *table, *table_end;
void *temp;
struct page *page;
- temp = agp_bridge->current_size;
+ temp = bridge->current_size;
- switch (agp_bridge->driver->size_type) {
+ switch (bridge->driver->size_type) {
case U8_APER_SIZE:
page_order = A_SIZE_8(temp)->page_order;
break;
@@ -803,19 +912,19 @@ int agp_generic_free_gatt_table(void)
* called, then all agp memory is deallocated and removed
* from the table. */
- iounmap(agp_bridge->gatt_table);
- table = (char *) agp_bridge->gatt_table_real;
+ iounmap(bridge->gatt_table);
+ table = (char *) bridge->gatt_table_real;
table_end = table + ((PAGE_SIZE * (1 << page_order)) - 1);
for (page = virt_to_page(table); page <= virt_to_page(table_end); page++)
ClearPageReserved(page);
- free_pages((unsigned long) agp_bridge->gatt_table_real, page_order);
+ free_pages((unsigned long) bridge->gatt_table_real, page_order);
agp_gatt_table = NULL;
- agp_bridge->gatt_table = NULL;
- agp_bridge->gatt_table_real = NULL;
- agp_bridge->gatt_bus_addr = 0;
+ bridge->gatt_table = NULL;
+ bridge->gatt_table_real = NULL;
+ bridge->gatt_bus_addr = 0;
return 0;
}
@@ -828,10 +937,15 @@ int agp_generic_insert_memory(struct agp_memory * mem, off_t pg_start, int type)
size_t i;
off_t j;
void *temp;
+ struct agp_bridge_data *bridge;
- temp = agp_bridge->current_size;
+ bridge = mem->bridge;
+ if (!bridge)
+ return -EINVAL;
- switch (agp_bridge->driver->size_type) {
+ temp = bridge->current_size;
+
+ switch (bridge->driver->size_type) {
case U8_APER_SIZE:
num_entries = A_SIZE_8(temp)->num_entries;
break;
@@ -868,22 +982,22 @@ int agp_generic_insert_memory(struct agp_memory * mem, off_t pg_start, int type)
j = pg_start;
while (j < (pg_start + mem->page_count)) {
- if (!PGE_EMPTY(agp_bridge, readl(agp_bridge->gatt_table+j)))
+ if (!PGE_EMPTY(bridge, readl(bridge->gatt_table+j)))
return -EBUSY;
j++;
}
if (mem->is_flushed == FALSE) {
- agp_bridge->driver->cache_flush();
+ bridge->driver->cache_flush();
mem->is_flushed = TRUE;
}
for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
- writel(agp_bridge->driver->mask_memory(mem->memory[i], mem->type), agp_bridge->gatt_table+j);
- readl(agp_bridge->gatt_table+j); /* PCI Posting. */
+ writel(bridge->driver->mask_memory(bridge, mem->memory[i], mem->type), bridge->gatt_table+j);
+ readl(bridge->gatt_table+j); /* PCI Posting. */
}
- agp_bridge->driver->tlb_flush(mem);
+ bridge->driver->tlb_flush(mem);
return 0;
}
EXPORT_SYMBOL(agp_generic_insert_memory);
@@ -892,6 +1006,11 @@ EXPORT_SYMBOL(agp_generic_insert_memory);
int agp_generic_remove_memory(struct agp_memory *mem, off_t pg_start, int type)
{
size_t i;
+ struct agp_bridge_data *bridge;
+
+ bridge = mem->bridge;
+ if (!bridge)
+ return -EINVAL;
if (type != 0 || mem->type != 0) {
/* The generic routines know nothing of memory types */
@@ -900,12 +1019,12 @@ int agp_generic_remove_memory(struct agp_memory *mem, off_t pg_start, int type)
/* AK: bogus, should encode addresses > 4GB */
for (i = pg_start; i < (mem->page_count + pg_start); i++) {
- writel(agp_bridge->scratch_page, agp_bridge->gatt_table+i);
- readl(agp_bridge->gatt_table+i); /* PCI Posting. */
+ writel(bridge->scratch_page, bridge->gatt_table+i);
+ readl(bridge->gatt_table+i); /* PCI Posting. */
}
global_cache_flush();
- agp_bridge->driver->tlb_flush(mem);
+ bridge->driver->tlb_flush(mem);
return 0;
}
EXPORT_SYMBOL(agp_generic_remove_memory);
@@ -920,9 +1039,7 @@ EXPORT_SYMBOL(agp_generic_alloc_by_type);
void agp_generic_free_by_type(struct agp_memory *curr)
{
- if (curr->memory != NULL)
- vfree(curr->memory);
-
+ vfree(curr->memory);
agp_free_key(curr->key);
kfree(curr);
}
@@ -936,7 +1053,7 @@ EXPORT_SYMBOL(agp_generic_free_by_type);
* against a maximum value.
*/
-void *agp_generic_alloc_page(void)
+void *agp_generic_alloc_page(struct agp_bridge_data *bridge)
{
struct page * page;
@@ -978,14 +1095,25 @@ EXPORT_SYMBOL(agp_generic_destroy_page);
*
* @mode: agp mode register value to configure with.
*/
-void agp_enable(u32 mode)
+void agp_enable(struct agp_bridge_data *bridge, u32 mode)
{
- if (agp_bridge->type == NOT_SUPPORTED)
+ if (!bridge)
return;
- agp_bridge->driver->agp_enable(mode);
+ bridge->driver->agp_enable(bridge, mode);
}
EXPORT_SYMBOL(agp_enable);
+/* When we remove the global variable agp_bridge from all drivers
+ * then agp_alloc_bridge and agp_generic_find_bridge need to be updated
+ */
+
+struct agp_bridge_data *agp_generic_find_bridge(struct pci_dev *pdev)
+{
+ if (list_empty(&agp_bridges))
+ return NULL;
+
+ return agp_bridge;
+}
static void ipi_handler(void *null)
{
@@ -999,11 +1127,12 @@ void global_cache_flush(void)
}
EXPORT_SYMBOL(global_cache_flush);
-unsigned long agp_generic_mask_memory(unsigned long addr, int type)
+unsigned long agp_generic_mask_memory(struct agp_bridge_data *bridge,
+ unsigned long addr, int type)
{
/* memory type is ignored in the generic routine */
- if (agp_bridge->driver->masks)
- return addr | agp_bridge->driver->masks[0].mask;
+ if (bridge->driver->masks)
+ return addr | bridge->driver->masks[0].mask;
else
return addr;
}
diff --git a/drivers/char/agp/hp-agp.c b/drivers/char/agp/hp-agp.c
index 3f8c2d41b0ee2..6052bfa04c728 100644
--- a/drivers/char/agp/hp-agp.c
+++ b/drivers/char/agp/hp-agp.c
@@ -289,7 +289,7 @@ hp_zx1_tlbflush (struct agp_memory *mem)
}
static int
-hp_zx1_create_gatt_table (void)
+hp_zx1_create_gatt_table (struct agp_bridge_data *bridge)
{
struct _hp_private *hp = &hp_private;
int i;
@@ -317,7 +317,7 @@ hp_zx1_create_gatt_table (void)
}
static int
-hp_zx1_free_gatt_table (void)
+hp_zx1_free_gatt_table (struct agp_bridge_data *bridge)
{
struct _hp_private *hp = &hp_private;
@@ -367,7 +367,9 @@ hp_zx1_insert_memory (struct agp_memory *mem, off_t pg_start, int type)
for (k = 0;
k < hp->io_pages_per_kpage;
k++, j++, paddr += hp->io_page_size) {
- hp->gatt[j] = agp_bridge->driver->mask_memory(paddr, type);
+ hp->gatt[j] =
+ agp_bridge->driver->mask_memory(agp_bridge,
+ paddr, type);
}
}
@@ -396,19 +398,20 @@ hp_zx1_remove_memory (struct agp_memory *mem, off_t pg_start, int type)
}
static unsigned long
-hp_zx1_mask_memory (unsigned long addr, int type)
+hp_zx1_mask_memory (struct agp_bridge_data *bridge,
+ unsigned long addr, int type)
{
return HP_ZX1_PDIR_VALID_BIT | addr;
}
static void
-hp_zx1_enable (u32 mode)
+hp_zx1_enable (struct agp_bridge_data *bridge, u32 mode)
{
struct _hp_private *hp = &hp_private;
u32 command;
command = readl(hp->lba_regs+hp->lba_cap_offset+PCI_AGP_STATUS);
- command = agp_collect_device_status(mode, command);
+ command = agp_collect_device_status(bridge, mode, command);
command |= 0x00000100;
writel(command, hp->lba_regs+hp->lba_cap_offset+PCI_AGP_COMMAND);
diff --git a/drivers/char/agp/i460-agp.c b/drivers/char/agp/i460-agp.c
index c55fa1df610c2..adbea896c0d2e 100644
--- a/drivers/char/agp/i460-agp.c
+++ b/drivers/char/agp/i460-agp.c
@@ -233,7 +233,7 @@ static int i460_configure (void)
return 0;
}
-static int i460_create_gatt_table (void)
+static int i460_create_gatt_table (struct agp_bridge_data *bridge)
{
int page_order, num_entries, i;
void *temp;
@@ -258,7 +258,7 @@ static int i460_create_gatt_table (void)
return 0;
}
-static int i460_free_gatt_table (void)
+static int i460_free_gatt_table (struct agp_bridge_data *bridge)
{
int num_entries, i;
void *temp;
@@ -314,7 +314,8 @@ static int i460_insert_memory_small_io_page (struct agp_memory *mem,
for (i = 0, j = io_pg_start; i < mem->page_count; i++) {
paddr = mem->memory[i];
for (k = 0; k < I460_IOPAGES_PER_KPAGE; k++, j++, paddr += io_page_size)
- WR_GATT(j, agp_bridge->driver->mask_memory(paddr, mem->type));
+ WR_GATT(j, agp_bridge->driver->mask_memory(agp_bridge,
+ paddr, mem->type));
}
WR_FLUSH_GATT(j - 1);
return 0;
@@ -427,7 +428,8 @@ static int i460_insert_memory_large_io_page (struct agp_memory *mem,
if (i460_alloc_large_page(lp) < 0)
return -ENOMEM;
pg = lp - i460.lp_desc;
- WR_GATT(pg, agp_bridge->driver->mask_memory(lp->paddr, 0));
+ WR_GATT(pg, agp_bridge->driver->mask_memory(agp_bridge,
+ lp->paddr, 0));
WR_FLUSH_GATT(pg);
}
@@ -508,12 +510,12 @@ static int i460_remove_memory (struct agp_memory *mem,
* Let's just hope nobody counts on the allocated AGP memory being there before bind time
* (I don't think current drivers do)...
*/
-static void *i460_alloc_page (void)
+static void *i460_alloc_page (struct agp_bridge_data *bridge)
{
void *page;
if (I460_IO_PAGE_SHIFT <= PAGE_SHIFT)
- page = agp_generic_alloc_page();
+ page = agp_generic_alloc_page(agp_bridge);
else
/* Returning NULL would cause problems */
/* AK: really dubious code. */
@@ -529,10 +531,11 @@ static void i460_destroy_page (void *page)
#endif /* I460_LARGE_IO_PAGES */
-static unsigned long i460_mask_memory (unsigned long addr, int type)
+static unsigned long i460_mask_memory (struct agp_bridge_data *bridge,
+ unsigned long addr, int type)
{
/* Make sure the returned address is a valid GATT entry */
- return agp_bridge->driver->masks[0].mask
+ return bridge->driver->masks[0].mask
| (((addr & ~((1 << I460_IO_PAGE_SHIFT) - 1)) & 0xffffff000) >> 12);
}
@@ -624,7 +627,7 @@ static int __init agp_intel_i460_init(void)
{
if (agp_off)
return -EINVAL;
- return pci_module_init(&agp_intel_i460_pci_driver);
+ return pci_register_driver(&agp_intel_i460_pci_driver);
}
static void __exit agp_intel_i460_cleanup(void)
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c
index 06e791f3b65de..8c7d727432bb5 100644
--- a/drivers/char/agp/intel-agp.c
+++ b/drivers/char/agp/intel-agp.c
@@ -150,7 +150,7 @@ static void intel_i810_tlbflush(struct agp_memory *mem)
return;
}
-static void intel_i810_agp_enable(u32 mode)
+static void intel_i810_agp_enable(struct agp_bridge_data *bridge, u32 mode)
{
return;
}
@@ -229,8 +229,9 @@ static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start,
insert:
global_cache_flush();
for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
- writel(agp_bridge->driver->mask_memory(mem->memory[i], mem->type),
- intel_i810_private.registers+I810_PTE_BASE+(j*4));
+ writel(agp_bridge->driver->mask_memory(agp_bridge,
+ mem->memory[i], mem->type),
+ intel_i810_private.registers+I810_PTE_BASE+(j*4));
readl(intel_i810_private.registers+I810_PTE_BASE+(j*4)); /* PCI Posting. */
}
global_cache_flush();
@@ -268,7 +269,7 @@ static struct agp_memory *alloc_agpphysmem_i8xx(size_t pg_count, int type)
return NULL;
switch (pg_count) {
- case 1: addr = agp_bridge->driver->agp_alloc_page();
+ case 1: addr = agp_bridge->driver->agp_alloc_page(agp_bridge);
break;
case 4:
/* kludge to get 4 physical pages for ARGB cursor */
@@ -337,10 +338,11 @@ static void intel_i810_free_by_type(struct agp_memory *curr)
kfree(curr);
}
-static unsigned long intel_i810_mask_memory(unsigned long addr, int type)
+static unsigned long intel_i810_mask_memory(struct agp_bridge_data *bridge,
+ unsigned long addr, int type)
{
/* Type checking must be done elsewhere */
- return addr | agp_bridge->driver->masks[type].mask;
+ return addr | bridge->driver->masks[type].mask;
}
static struct aper_size_info_fixed intel_i830_sizes[] =
@@ -447,7 +449,7 @@ static void intel_i830_init_gtt_entries(void)
/* The intel i830 automatically initializes the agp aperture during POST.
* Use the memory already set aside for in the GTT.
*/
-static int intel_i830_create_gatt_table(void)
+static int intel_i830_create_gatt_table(struct agp_bridge_data *bridge)
{
int page_order;
struct aper_size_info_fixed *size;
@@ -482,7 +484,7 @@ static int intel_i830_create_gatt_table(void)
/* Return the gatt table to a sane state. Use the top of stolen
* memory for the GTT.
*/
-static int intel_i830_free_gatt_table(void)
+static int intel_i830_free_gatt_table(struct agp_bridge_data *bridge)
{
return 0;
}
@@ -582,8 +584,9 @@ static int intel_i830_insert_entries(struct agp_memory *mem,off_t pg_start, int
global_cache_flush(); /* FIXME: Necessary ?*/
for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
- writel(agp_bridge->driver->mask_memory(mem->memory[i], mem->type),
- intel_i830_private.registers+I810_PTE_BASE+(j*4));
+ writel(agp_bridge->driver->mask_memory(agp_bridge,
+ mem->memory[i], mem->type),
+ intel_i830_private.registers+I810_PTE_BASE+(j*4));
readl(intel_i830_private.registers+I810_PTE_BASE+(j*4)); /* PCI Posting. */
}
@@ -691,7 +694,8 @@ static int intel_i915_insert_entries(struct agp_memory *mem,off_t pg_start,
global_cache_flush();
for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
- writel(agp_bridge->driver->mask_memory(mem->memory[i], mem->type), intel_i830_private.gtt+j);
+ writel(agp_bridge->driver->mask_memory(agp_bridge,
+ mem->memory[i], mem->type), intel_i830_private.gtt+j);
readl(intel_i830_private.gtt+j); /* PCI Posting. */
}
@@ -743,7 +747,7 @@ static int intel_i915_fetch_size(void)
/* The intel i915 automatically initializes the agp aperture during POST.
* Use the memory already set aside for in the GTT.
*/
-static int intel_i915_create_gatt_table(void)
+static int intel_i915_create_gatt_table(struct agp_bridge_data *bridge)
{
int page_order;
struct aper_size_info_fixed *size;
@@ -1758,6 +1762,8 @@ static int agp_intel_resume(struct pci_dev *pdev)
intel_i915_configure();
else if (bridge->driver == &intel_830_driver)
intel_i830_configure();
+ else if (bridge->driver == &intel_810_driver)
+ intel_i810_configure();
return 0;
}
@@ -1810,7 +1816,9 @@ static struct pci_driver agp_intel_pci_driver = {
static int __init agp_intel_init(void)
{
- return pci_module_init(&agp_intel_pci_driver);
+ if (agp_off)
+ return -EINVAL;
+ return pci_register_driver(&agp_intel_pci_driver);
}
static void __exit agp_intel_cleanup(void)
diff --git a/drivers/char/agp/intel-mch-agp.c b/drivers/char/agp/intel-mch-agp.c
deleted file mode 100644
index 5902726d8884b..0000000000000
--- a/drivers/char/agp/intel-mch-agp.c
+++ /dev/null
@@ -1,643 +0,0 @@
-/*
- * Intel MCH AGPGART routines.
- */
-
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/agp_backend.h>
-#include "agp.h"
-
-
-#define AGP_DCACHE_MEMORY 1
-#define AGP_PHYS_MEMORY 2
-
-static struct gatt_mask intel_i810_masks[] =
-{
- {.mask = I810_PTE_VALID, .type = 0},
- {.mask = (I810_PTE_VALID | I810_PTE_LOCAL), .type = AGP_DCACHE_MEMORY},
- {.mask = I810_PTE_VALID, .type = 0}
-};
-
-static void intel_i810_tlbflush(struct agp_memory *mem)
-{
- return;
-}
-
-static void intel_i810_agp_enable(u32 mode)
-{
- return;
-}
-
-
-/*
- * The i810/i830 requires a physical address to program its mouse
- * pointer into hardware.
- * However the Xserver still writes to it through the agp aperture.
- */
-static struct agp_memory *alloc_agpphysmem_i8xx(size_t pg_count, int type)
-{
- struct agp_memory *new;
- void *addr;
-
- if (pg_count != 1)
- return NULL;
-
- addr = agp_bridge->driver->agp_alloc_page();
- if (addr == NULL)
- return NULL;
-
- new = agp_create_memory(1);
- if (new == NULL)
- return NULL;
-
- new->memory[0] = virt_to_phys(addr);
- new->page_count = 1;
- new->num_scratch_pages = 1;
- new->type = AGP_PHYS_MEMORY;
- new->physical = new->memory[0];
- return new;
-}
-
-static void intel_i810_free_by_type(struct agp_memory *curr)
-{
- agp_free_key(curr->key);
- if(curr->type == AGP_PHYS_MEMORY) {
- agp_bridge->driver->agp_destroy_page(phys_to_virt(curr->memory[0]));
- vfree(curr->memory);
- }
- kfree(curr);
-}
-
-static unsigned long intel_i810_mask_memory(unsigned long addr, int type)
-{
- /* Type checking must be done elsewhere */
- return addr | agp_bridge->driver->masks[type].mask;
-}
-
-static struct aper_size_info_fixed intel_i830_sizes[] =
-{
- {128, 32768, 5},
- /* The 64M mode still requires a 128k gatt */
- {64, 16384, 5}
-};
-
-static struct _intel_i830_private {
- struct pci_dev *i830_dev; /* device one */
- volatile u8 __iomem *registers;
- int gtt_entries;
-} intel_i830_private;
-
-static void intel_i830_init_gtt_entries(void)
-{
- u16 gmch_ctrl;
- int gtt_entries;
- u8 rdct;
- int local = 0;
- static const int ddt[4] = { 0, 16, 32, 64 };
-
- pci_read_config_word(agp_bridge->dev,I830_GMCH_CTRL,&gmch_ctrl);
-
- if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82830_HB ||
- agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82845G_HB) {
- switch (gmch_ctrl & I830_GMCH_GMS_MASK) {
- case I830_GMCH_GMS_STOLEN_512:
- gtt_entries = KB(512) - KB(132);
- break;
- case I830_GMCH_GMS_STOLEN_1024:
- gtt_entries = MB(1) - KB(132);
- break;
- case I830_GMCH_GMS_STOLEN_8192:
- gtt_entries = MB(8) - KB(132);
- break;
- case I830_GMCH_GMS_LOCAL:
- rdct = readb(intel_i830_private.registers+I830_RDRAM_CHANNEL_TYPE);
- gtt_entries = (I830_RDRAM_ND(rdct) + 1) *
- MB(ddt[I830_RDRAM_DDT(rdct)]);
- local = 1;
- break;
- default:
- gtt_entries = 0;
- break;
- }
- } else {
- switch (gmch_ctrl & I830_GMCH_GMS_MASK) {
- case I855_GMCH_GMS_STOLEN_1M:
- gtt_entries = MB(1) - KB(132);
- break;
- case I855_GMCH_GMS_STOLEN_4M:
- gtt_entries = MB(4) - KB(132);
- break;
- case I855_GMCH_GMS_STOLEN_8M:
- gtt_entries = MB(8) - KB(132);
- break;
- case I855_GMCH_GMS_STOLEN_16M:
- gtt_entries = MB(16) - KB(132);
- break;
- case I855_GMCH_GMS_STOLEN_32M:
- gtt_entries = MB(32) - KB(132);
- break;
- default:
- gtt_entries = 0;
- break;
- }
- }
- if (gtt_entries > 0)
- printk(KERN_INFO PFX "Detected %dK %s memory.\n",
- gtt_entries / KB(1), local ? "local" : "stolen");
- else
- printk(KERN_INFO PFX
- "No pre-allocated video memory detected.\n");
- gtt_entries /= KB(4);
-
- intel_i830_private.gtt_entries = gtt_entries;
-}
-
-/* The intel i830 automatically initializes the agp aperture during POST.
- * Use the memory already set aside for in the GTT.
- */
-static int intel_i830_create_gatt_table(void)
-{
- int page_order;
- struct aper_size_info_fixed *size;
- int num_entries;
- u32 temp;
-
- size = agp_bridge->current_size;
- page_order = size->page_order;
- num_entries = size->num_entries;
- agp_bridge->gatt_table_real = NULL;
-
- pci_read_config_dword(intel_i830_private.i830_dev,I810_MMADDR,&temp);
- temp &= 0xfff80000;
-
- intel_i830_private.registers = (volatile u8 __iomem*) ioremap(temp,128 * 4096);
- if (!intel_i830_private.registers)
- return -ENOMEM;
-
- temp = readl(intel_i830_private.registers+I810_PGETBL_CTL) & 0xfffff000;
- global_cache_flush(); /* FIXME: ?? */
-
- /* we have to call this as early as possible after the MMIO base address is known */
- intel_i830_init_gtt_entries();
-
- agp_bridge->gatt_table = NULL;
-
- agp_bridge->gatt_bus_addr = temp;
-
- return 0;
-}
-
-/* Return the gatt table to a sane state. Use the top of stolen
- * memory for the GTT.
- */
-static int intel_i830_free_gatt_table(void)
-{
- return 0;
-}
-
-static int intel_i830_fetch_size(void)
-{
- u16 gmch_ctrl;
- struct aper_size_info_fixed *values;
-
- values = A_SIZE_FIX(agp_bridge->driver->aperture_sizes);
-
- if (agp_bridge->dev->device != PCI_DEVICE_ID_INTEL_82830_HB &&
- agp_bridge->dev->device != PCI_DEVICE_ID_INTEL_82845G_HB) {
- /* 855GM/852GM/865G has 128MB aperture size */
- agp_bridge->previous_size = agp_bridge->current_size = (void *) values;
- agp_bridge->aperture_size_idx = 0;
- return values[0].size;
- }
-
- pci_read_config_word(agp_bridge->dev,I830_GMCH_CTRL,&gmch_ctrl);
-
- if ((gmch_ctrl & I830_GMCH_MEM_MASK) == I830_GMCH_MEM_128M) {
- agp_bridge->previous_size = agp_bridge->current_size = (void *) values;
- agp_bridge->aperture_size_idx = 0;
- return values[0].size;
- } else {
- agp_bridge->previous_size = agp_bridge->current_size = (void *) values;
- agp_bridge->aperture_size_idx = 1;
- return values[1].size;
- }
-
- return 0;
-}
-
-static int intel_i830_configure(void)
-{
- struct aper_size_info_fixed *current_size;
- u32 temp;
- u16 gmch_ctrl;
- int i;
-
- current_size = A_SIZE_FIX(agp_bridge->current_size);
-
- pci_read_config_dword(intel_i830_private.i830_dev,I810_GMADDR,&temp);
- agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
-
- pci_read_config_word(agp_bridge->dev,I830_GMCH_CTRL,&gmch_ctrl);
- gmch_ctrl |= I830_GMCH_ENABLED;
- pci_write_config_word(agp_bridge->dev,I830_GMCH_CTRL,gmch_ctrl);
-
- writel(agp_bridge->gatt_bus_addr|I810_PGETBL_ENABLED, intel_i830_private.registers+I810_PGETBL_CTL);
- readl(intel_i830_private.registers+I810_PGETBL_CTL); /* PCI Posting. */
-
- if (agp_bridge->driver->needs_scratch_page) {
- for (i = intel_i830_private.gtt_entries; i < current_size->num_entries; i++) {
- writel(agp_bridge->scratch_page, intel_i830_private.registers+I810_PTE_BASE+(i*4));
- readl(intel_i830_private.registers+I810_PTE_BASE+(i*4)); /* PCI Posting. */
- }
- }
- global_cache_flush();
- return 0;
-}
-
-static void intel_i830_cleanup(void)
-{
- iounmap((void __iomem *) intel_i830_private.registers);
-}
-
-static int intel_i830_insert_entries(struct agp_memory *mem,off_t pg_start,
- int type)
-{
- int i,j,num_entries;
- void *temp;
-
- temp = agp_bridge->current_size;
- num_entries = A_SIZE_FIX(temp)->num_entries;
-
- if (pg_start < intel_i830_private.gtt_entries) {
- printk (KERN_DEBUG PFX "pg_start == 0x%.8lx,intel_i830_private.gtt_entries == 0x%.8x\n",
- pg_start,intel_i830_private.gtt_entries);
-
- printk (KERN_INFO PFX "Trying to insert into local/stolen memory\n");
- return -EINVAL;
- }
-
- if ((pg_start + mem->page_count) > num_entries)
- return -EINVAL;
-
- /* The i830 can't check the GTT for entries since its read only,
- * depend on the caller to make the correct offset decisions.
- */
-
- if ((type != 0 && type != AGP_PHYS_MEMORY) ||
- (mem->type != 0 && mem->type != AGP_PHYS_MEMORY))
- return -EINVAL;
-
- global_cache_flush(); /* FIXME: ?? */
-
- for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
- writel(agp_bridge->driver->mask_memory(mem->memory[i], mem->type),
- intel_i830_private.registers+I810_PTE_BASE+(j*4));
- readl(intel_i830_private.registers+I810_PTE_BASE+(j*4)); /* PCI Posting. */
- }
-
- global_cache_flush();
-
- agp_bridge->driver->tlb_flush(mem);
-
- return 0;
-}
-
-static int intel_i830_remove_entries(struct agp_memory *mem,off_t pg_start,
- int type)
-{
- int i;
-
- global_cache_flush();
-
- if (pg_start < intel_i830_private.gtt_entries) {
- printk (KERN_INFO PFX "Trying to disable local/stolen memory\n");
- return -EINVAL;
- }
-
- for (i = pg_start; i < (mem->page_count + pg_start); i++) {
- writel(agp_bridge->scratch_page, intel_i830_private.registers+I810_PTE_BASE+(i*4));
- readl(intel_i830_private.registers+I810_PTE_BASE+(i*4)); /* PCI Posting. */
- }
-
- global_cache_flush();
- agp_bridge->driver->tlb_flush(mem);
- return 0;
-}
-
-static struct agp_memory *intel_i830_alloc_by_type(size_t pg_count,int type)
-{
- if (type == AGP_PHYS_MEMORY)
- return alloc_agpphysmem_i8xx(pg_count, type);
-
- /* always return NULL for other allocation types for now */
- return NULL;
-}
-
-static int intel_8xx_fetch_size(void)
-{
- u8 temp;
- int i;
- struct aper_size_info_8 *values;
-
- pci_read_config_byte(agp_bridge->dev, INTEL_APSIZE, &temp);
-
- values = A_SIZE_8(agp_bridge->driver->aperture_sizes);
-
- for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) {
- if (temp == values[i].size_value) {
- agp_bridge->previous_size =
- agp_bridge->current_size = (void *) (values + i);
- agp_bridge->aperture_size_idx = i;
- return values[i].size;
- }
- }
- return 0;
-}
-
-static void intel_8xx_tlbflush(struct agp_memory *mem)
-{
- u32 temp;
- pci_read_config_dword(agp_bridge->dev, INTEL_AGPCTRL, &temp);
- pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, temp & ~(1 << 7));
- pci_read_config_dword(agp_bridge->dev, INTEL_AGPCTRL, &temp);
- pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, temp | (1 << 7));
-}
-
-static void intel_8xx_cleanup(void)
-{
- u16 temp;
- struct aper_size_info_8 *previous_size;
-
- previous_size = A_SIZE_8(agp_bridge->previous_size);
- pci_read_config_word(agp_bridge->dev, INTEL_NBXCFG, &temp);
- pci_write_config_word(agp_bridge->dev, INTEL_NBXCFG, temp & ~(1 << 9));
- pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, previous_size->size_value);
-}
-
-static int intel_845_configure(void)
-{
- u32 temp;
- u8 temp2;
- struct aper_size_info_8 *current_size;
-
- current_size = A_SIZE_8(agp_bridge->current_size);
-
- /* aperture size */
- pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
-
- /* address to map to */
- pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
- agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
-
- /* attbase - aperture base */
- pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
-
- /* agpctrl */
- pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
-
- /* agpm */
- pci_read_config_byte(agp_bridge->dev, INTEL_I845_AGPM, &temp2);
- pci_write_config_byte(agp_bridge->dev, INTEL_I845_AGPM, temp2 | (1 << 1));
- /* clear any possible error conditions */
- pci_write_config_word(agp_bridge->dev, INTEL_I845_ERRSTS, 0x001c);
- return 0;
-}
-
-
-/* Setup function */
-static struct gatt_mask intel_generic_masks[] =
-{
- {.mask = 0x00000017, .type = 0}
-};
-
-static struct aper_size_info_8 intel_8xx_sizes[7] =
-{
- {256, 65536, 6, 0},
- {128, 32768, 5, 32},
- {64, 16384, 4, 48},
- {32, 8192, 3, 56},
- {16, 4096, 2, 60},
- {8, 2048, 1, 62},
- {4, 1024, 0, 63}
-};
-
-static struct agp_bridge_driver intel_830_driver = {
- .owner = THIS_MODULE,
- .aperture_sizes = intel_i830_sizes,
- .size_type = FIXED_APER_SIZE,
- .num_aperture_sizes = 2,
- .needs_scratch_page = TRUE,
- .configure = intel_i830_configure,
- .fetch_size = intel_i830_fetch_size,
- .cleanup = intel_i830_cleanup,
- .tlb_flush = intel_i810_tlbflush,
- .mask_memory = intel_i810_mask_memory,
- .masks = intel_i810_masks,
- .agp_enable = intel_i810_agp_enable,
- .cache_flush = global_cache_flush,
- .create_gatt_table = intel_i830_create_gatt_table,
- .free_gatt_table = intel_i830_free_gatt_table,
- .insert_memory = intel_i830_insert_entries,
- .remove_memory = intel_i830_remove_entries,
- .alloc_by_type = intel_i830_alloc_by_type,
- .free_by_type = intel_i810_free_by_type,
- .agp_alloc_page = agp_generic_alloc_page,
- .agp_destroy_page = agp_generic_destroy_page,
-};
-
-static struct agp_bridge_driver intel_845_driver = {
- .owner = THIS_MODULE,
- .aperture_sizes = intel_8xx_sizes,
- .size_type = U8_APER_SIZE,
- .num_aperture_sizes = 7,
- .configure = intel_845_configure,
- .fetch_size = intel_8xx_fetch_size,
- .cleanup = intel_8xx_cleanup,
- .tlb_flush = intel_8xx_tlbflush,
- .mask_memory = agp_generic_mask_memory,
- .masks = intel_generic_masks,
- .agp_enable = agp_generic_enable,
- .cache_flush = global_cache_flush,
- .create_gatt_table = agp_generic_create_gatt_table,
- .free_gatt_table = agp_generic_free_gatt_table,
- .insert_memory = agp_generic_insert_memory,
- .remove_memory = agp_generic_remove_memory,
- .alloc_by_type = agp_generic_alloc_by_type,
- .free_by_type = agp_generic_free_by_type,
- .agp_alloc_page = agp_generic_alloc_page,
- .agp_destroy_page = agp_generic_destroy_page,
-};
-
-
-static int find_i830(u16 device)
-{
- struct pci_dev *i830_dev;
-
- i830_dev = pci_get_device(PCI_VENDOR_ID_INTEL, device, NULL);
- if (i830_dev && PCI_FUNC(i830_dev->devfn) != 0) {
- i830_dev = pci_get_device(PCI_VENDOR_ID_INTEL,
- device, i830_dev);
- }
-
- if (!i830_dev)
- return 0;
-
- intel_i830_private.i830_dev = i830_dev;
- return 1;
-}
-
-static int __devinit agp_intelmch_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent)
-{
- struct agp_bridge_data *bridge;
- struct resource *r;
- char *name = "(unknown)";
- u8 cap_ptr = 0;
-
- cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
- if (!cap_ptr)
- return -ENODEV;
-
- bridge = agp_alloc_bridge();
- if (!bridge)
- return -ENOMEM;
-
- switch (pdev->device) {
- case PCI_DEVICE_ID_INTEL_82865_HB:
- if (find_i830(PCI_DEVICE_ID_INTEL_82865_IG)) {
- bridge->driver = &intel_830_driver;
- } else {
- bridge->driver = &intel_845_driver;
- }
- name = "865";
- break;
- case PCI_DEVICE_ID_INTEL_82875_HB:
- bridge->driver = &intel_845_driver;
- name = "i875";
- break;
-
- default:
- printk(KERN_ERR PFX "Unsupported Intel chipset (device id: %04x)\n",
- pdev->device);
- return -ENODEV;
- };
-
- bridge->dev = pdev;
- bridge->capndx = cap_ptr;
-
- if (bridge->driver == &intel_830_driver)
- bridge->dev_private_data = &intel_i830_private;
-
- printk(KERN_INFO PFX "Detected an Intel %s Chipset.\n", name);
-
- /*
- * The following fixes the case where the BIOS has "forgotten" to
- * provide an address range for the GART.
- * 20030610 - hamish@zot.org
- */
- r = &pdev->resource[0];
- if (!r->start && r->end) {
- if(pci_assign_resource(pdev, 0)) {
- printk(KERN_ERR PFX "could not assign resource 0\n");
- return -ENODEV;
- }
- }
-
- /*
- * If the device has not been properly setup, the following will catch
- * the problem and should stop the system from crashing.
- * 20030610 - hamish@zot.org
- */
- if (pci_enable_device(pdev)) {
- printk(KERN_ERR PFX "Unable to Enable PCI device\n");
- return -ENODEV;
- }
-
- /* Fill in the mode register */
- if (cap_ptr) {
- pci_read_config_dword(pdev,
- bridge->capndx+PCI_AGP_STATUS,
- &bridge->mode);
- }
-
- pci_set_drvdata(pdev, bridge);
- return agp_add_bridge(bridge);
-}
-
-static void __devexit agp_intelmch_remove(struct pci_dev *pdev)
-{
- struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
-
- agp_remove_bridge(bridge);
- if (intel_i830_private.i830_dev)
- pci_dev_put(intel_i830_private.i830_dev);
- agp_put_bridge(bridge);
-}
-
-static int agp_intelmch_resume(struct pci_dev *pdev)
-{
- struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
-
- pci_restore_state(pdev);
-
- if (bridge->driver == &intel_845_driver)
- intel_845_configure();
-
- return 0;
-}
-
-static struct pci_device_id agp_intelmch_pci_table[] = {
- {
- .class = (PCI_CLASS_BRIDGE_HOST << 8),
- .class_mask = ~0,
- .vendor = PCI_VENDOR_ID_INTEL,
- .device = PCI_DEVICE_ID_INTEL_82865_HB,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- },
- {
- .class = (PCI_CLASS_BRIDGE_HOST << 8),
- .class_mask = ~0,
- .vendor = PCI_VENDOR_ID_INTEL,
- .device = PCI_DEVICE_ID_INTEL_82875_HB,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- },
- { }
-};
-
-MODULE_DEVICE_TABLE(pci, agp_intelmch_pci_table);
-
-static struct pci_driver agp_intelmch_pci_driver = {
- .name = "agpgart-intel-mch",
- .id_table = agp_intelmch_pci_table,
- .probe = agp_intelmch_probe,
- .remove = agp_intelmch_remove,
- .resume = agp_intelmch_resume,
-};
-
-/* intel_agp_init() must not be declared static for explicit
- early initialization to work (ie i810fb) */
-int __init agp_intelmch_init(void)
-{
- static int agp_initialised=0;
-
- if (agp_initialised == 1)
- return 0;
- agp_initialised=1;
-
- return pci_module_init(&agp_intelmch_pci_driver);
-}
-
-static void __exit agp_intelmch_cleanup(void)
-{
- pci_unregister_driver(&agp_intelmch_pci_driver);
-}
-
-module_init(agp_intelmch_init);
-module_exit(agp_intelmch_cleanup);
-
-MODULE_AUTHOR("Dave Jones <davej@codemonkey.org.uk>");
-MODULE_LICENSE("GPL");
-
diff --git a/drivers/char/agp/nvidia-agp.c b/drivers/char/agp/nvidia-agp.c
index 936d366d72a2a..4f7a3e8bc9199 100644
--- a/drivers/char/agp/nvidia-agp.c
+++ b/drivers/char/agp/nvidia-agp.c
@@ -215,7 +215,8 @@ static int nvidia_insert_memory(struct agp_memory *mem, off_t pg_start, int type
mem->is_flushed = TRUE;
}
for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
- writel(agp_bridge->driver->mask_memory(mem->memory[i], mem->type),
+ writel(agp_bridge->driver->mask_memory(agp_bridge,
+ mem->memory[i], mem->type),
agp_bridge->gatt_table+nvidia_private.pg_offset+j);
readl(agp_bridge->gatt_table+nvidia_private.pg_offset+j); /* PCI Posting. */
}
@@ -407,7 +408,7 @@ static int __init agp_nvidia_init(void)
{
if (agp_off)
return -EINVAL;
- return pci_module_init(&agp_nvidia_pci_driver);
+ return pci_register_driver(&agp_nvidia_pci_driver);
}
static void __exit agp_nvidia_cleanup(void)
diff --git a/drivers/char/agp/sgi-agp.c b/drivers/char/agp/sgi-agp.c
new file mode 100644
index 0000000000000..4b3eda2679761
--- /dev/null
+++ b/drivers/char/agp/sgi-agp.c
@@ -0,0 +1,331 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2003-2005 Silicon Graphics, Inc. All Rights Reserved.
+ */
+
+/*
+ * SGI TIOCA AGPGART routines.
+ *
+ */
+
+#include <linux/acpi.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/agp_backend.h>
+#include <asm/sn/addrs.h>
+#include <asm/sn/pcidev.h>
+#include <asm/sn/pcibus_provider_defs.h>
+#include <asm/sn/tioca_provider.h>
+#include "agp.h"
+
+extern int agp_memory_reserved;
+extern uint32_t tioca_gart_found;
+extern struct list_head tioca_list;
+static struct agp_bridge_data **sgi_tioca_agp_bridges;
+
+/*
+ * The aperature size and related information is set up at TIOCA init time.
+ * Values for this table will be extracted and filled in at
+ * sgi_tioca_fetch_size() time.
+ */
+
+static struct aper_size_info_fixed sgi_tioca_sizes[] = {
+ {0, 0, 0},
+};
+
+static void *sgi_tioca_alloc_page(struct agp_bridge_data *bridge)
+{
+ struct page *page;
+ int nid;
+ struct tioca_kernel *info =
+ (struct tioca_kernel *)bridge->dev_private_data;
+
+ nid = info->ca_closest_node;
+ page = alloc_pages_node(nid, GFP_KERNEL, 0);
+ if (page == NULL) {
+ return 0;
+ }
+
+ get_page(page);
+ SetPageLocked(page);
+ atomic_inc(&agp_bridge->current_memory_agp);
+ return page_address(page);
+}
+
+/*
+ * Flush GART tlb's. Cannot selectively flush based on memory so the mem
+ * arg is ignored.
+ */
+
+static void sgi_tioca_tlbflush(struct agp_memory *mem)
+{
+ tioca_tlbflush(mem->bridge->dev_private_data);
+}
+
+/*
+ * Given an address of a host physical page, turn it into a valid gart
+ * entry.
+ */
+static unsigned long
+sgi_tioca_mask_memory(struct agp_bridge_data *bridge,
+ unsigned long addr, int type)
+{
+ return tioca_physpage_to_gart(addr);
+}
+
+static void sgi_tioca_agp_enable(struct agp_bridge_data *bridge, u32 mode)
+{
+ tioca_fastwrite_enable(bridge->dev_private_data);
+}
+
+/*
+ * sgi_tioca_configure() doesn't have anything to do since the base CA driver
+ * has alreay set up the GART.
+ */
+
+static int sgi_tioca_configure(void)
+{
+ return 0;
+}
+
+/*
+ * Determine gfx aperature size. This has already been determined by the
+ * CA driver init, so just need to set agp_bridge values accordingly.
+ */
+
+static int sgi_tioca_fetch_size(void)
+{
+ struct tioca_kernel *info =
+ (struct tioca_kernel *)agp_bridge->dev_private_data;
+
+ sgi_tioca_sizes[0].size = info->ca_gfxap_size / MB(1);
+ sgi_tioca_sizes[0].num_entries = info->ca_gfxgart_entries;
+
+ return sgi_tioca_sizes[0].size;
+}
+
+static int sgi_tioca_create_gatt_table(struct agp_bridge_data *bridge)
+{
+ struct tioca_kernel *info =
+ (struct tioca_kernel *)bridge->dev_private_data;
+
+ bridge->gatt_table_real = (u32 *) info->ca_gfxgart;
+ bridge->gatt_table = bridge->gatt_table_real;
+ bridge->gatt_bus_addr = info->ca_gfxgart_base;
+
+ return 0;
+}
+
+static int sgi_tioca_free_gatt_table(struct agp_bridge_data *bridge)
+{
+ return 0;
+}
+
+static int sgi_tioca_insert_memory(struct agp_memory *mem, off_t pg_start,
+ int type)
+{
+ int num_entries;
+ size_t i;
+ off_t j;
+ void *temp;
+ struct agp_bridge_data *bridge;
+
+ bridge = mem->bridge;
+ if (!bridge)
+ return -EINVAL;
+
+ temp = bridge->current_size;
+
+ switch (bridge->driver->size_type) {
+ case U8_APER_SIZE:
+ num_entries = A_SIZE_8(temp)->num_entries;
+ break;
+ case U16_APER_SIZE:
+ num_entries = A_SIZE_16(temp)->num_entries;
+ break;
+ case U32_APER_SIZE:
+ num_entries = A_SIZE_32(temp)->num_entries;
+ break;
+ case FIXED_APER_SIZE:
+ num_entries = A_SIZE_FIX(temp)->num_entries;
+ break;
+ case LVL2_APER_SIZE:
+ return -EINVAL;
+ break;
+ default:
+ num_entries = 0;
+ break;
+ }
+
+ num_entries -= agp_memory_reserved / PAGE_SIZE;
+ if (num_entries < 0)
+ num_entries = 0;
+
+ if (type != 0 || mem->type != 0) {
+ return -EINVAL;
+ }
+
+ if ((pg_start + mem->page_count) > num_entries)
+ return -EINVAL;
+
+ j = pg_start;
+
+ while (j < (pg_start + mem->page_count)) {
+ if (*(bridge->gatt_table + j))
+ return -EBUSY;
+ j++;
+ }
+
+ if (mem->is_flushed == FALSE) {
+ bridge->driver->cache_flush();
+ mem->is_flushed = TRUE;
+ }
+
+ for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
+ *(bridge->gatt_table + j) =
+ bridge->driver->mask_memory(bridge, mem->memory[i],
+ mem->type);
+ }
+
+ bridge->driver->tlb_flush(mem);
+ return 0;
+}
+
+static int sgi_tioca_remove_memory(struct agp_memory *mem, off_t pg_start,
+ int type)
+{
+ size_t i;
+ struct agp_bridge_data *bridge;
+
+ bridge = mem->bridge;
+ if (!bridge)
+ return -EINVAL;
+
+ if (type != 0 || mem->type != 0) {
+ return -EINVAL;
+ }
+
+ for (i = pg_start; i < (mem->page_count + pg_start); i++) {
+ *(bridge->gatt_table + i) = 0;
+ }
+
+ bridge->driver->tlb_flush(mem);
+ return 0;
+}
+
+static void sgi_tioca_cache_flush(void)
+{
+}
+
+/*
+ * Cleanup. Nothing to do as the CA driver owns the GART.
+ */
+
+static void sgi_tioca_cleanup(void)
+{
+}
+
+static struct agp_bridge_data *sgi_tioca_find_bridge(struct pci_dev *pdev)
+{
+ struct agp_bridge_data *bridge;
+
+ list_for_each_entry(bridge, &agp_bridges, list) {
+ if (bridge->dev->bus == pdev->bus)
+ break;
+ }
+ return bridge;
+}
+
+struct agp_bridge_driver sgi_tioca_driver = {
+ .owner = THIS_MODULE,
+ .size_type = U16_APER_SIZE,
+ .configure = sgi_tioca_configure,
+ .fetch_size = sgi_tioca_fetch_size,
+ .cleanup = sgi_tioca_cleanup,
+ .tlb_flush = sgi_tioca_tlbflush,
+ .mask_memory = sgi_tioca_mask_memory,
+ .agp_enable = sgi_tioca_agp_enable,
+ .cache_flush = sgi_tioca_cache_flush,
+ .create_gatt_table = sgi_tioca_create_gatt_table,
+ .free_gatt_table = sgi_tioca_free_gatt_table,
+ .insert_memory = sgi_tioca_insert_memory,
+ .remove_memory = sgi_tioca_remove_memory,
+ .alloc_by_type = agp_generic_alloc_by_type,
+ .free_by_type = agp_generic_free_by_type,
+ .agp_alloc_page = sgi_tioca_alloc_page,
+ .agp_destroy_page = agp_generic_destroy_page,
+ .cant_use_aperture = 1,
+ .needs_scratch_page = 0,
+ .num_aperture_sizes = 1,
+};
+
+static int __devinit agp_sgi_init(void)
+{
+ unsigned int j;
+ struct tioca_kernel *info;
+ struct pci_dev *pdev = NULL;
+
+ if (tioca_gart_found)
+ printk(KERN_INFO PFX "SGI TIO CA GART driver initialized.\n");
+ else
+ return 0;
+
+ sgi_tioca_agp_bridges =
+ (struct agp_bridge_data **)kmalloc(tioca_gart_found *
+ sizeof(struct agp_bridge_data *),
+ GFP_KERNEL);
+
+ j = 0;
+ list_for_each_entry(info, &tioca_list, ca_list) {
+ struct list_head *tmp;
+ list_for_each(tmp, info->ca_devices) {
+ u8 cap_ptr;
+ pdev = pci_dev_b(tmp);
+ if (pdev->class != (PCI_CLASS_DISPLAY_VGA << 8))
+ continue;
+ cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
+ if (!cap_ptr)
+ continue;
+ }
+ sgi_tioca_agp_bridges[j] = agp_alloc_bridge();
+ printk(KERN_INFO PFX "bridge %d = 0x%p\n", j,
+ sgi_tioca_agp_bridges[j]);
+ if (sgi_tioca_agp_bridges[j]) {
+ sgi_tioca_agp_bridges[j]->dev = pdev;
+ sgi_tioca_agp_bridges[j]->dev_private_data = info;
+ sgi_tioca_agp_bridges[j]->driver = &sgi_tioca_driver;
+ sgi_tioca_agp_bridges[j]->gart_bus_addr =
+ info->ca_gfxap_base;
+ sgi_tioca_agp_bridges[j]->mode = (0x7D << 24) | /* 126 requests */
+ (0x1 << 9) | /* SBA supported */
+ (0x1 << 5) | /* 64-bit addresses supported */
+ (0x1 << 4) | /* FW supported */
+ (0x1 << 3) | /* AGP 3.0 mode */
+ 0x2; /* 8x transfer only */
+ sgi_tioca_agp_bridges[j]->current_size =
+ sgi_tioca_agp_bridges[j]->previous_size =
+ (void *)&sgi_tioca_sizes[0];
+ agp_add_bridge(sgi_tioca_agp_bridges[j]);
+ }
+ j++;
+ }
+
+ agp_find_bridge = &sgi_tioca_find_bridge;
+ return 0;
+}
+
+static void __devexit agp_sgi_cleanup(void)
+{
+ if(sgi_tioca_agp_bridges)
+ kfree(sgi_tioca_agp_bridges);
+ sgi_tioca_agp_bridges=NULL;
+}
+
+module_init(agp_sgi_init);
+module_exit(agp_sgi_cleanup);
+
+MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/char/agp/sis-agp.c b/drivers/char/agp/sis-agp.c
index e70999aa88891..cfccacb2a647f 100644
--- a/drivers/char/agp/sis-agp.c
+++ b/drivers/char/agp/sis-agp.c
@@ -1,5 +1,5 @@
/*
- * SiS AGPGART routines.
+ * SiS AGPGART routines.
*/
#include <linux/module.h>
@@ -70,7 +70,7 @@ static void sis_cleanup(void)
(previous_size->size_value & ~(0x03)));
}
-static void sis_delayed_enable(u32 mode)
+static void sis_delayed_enable(struct agp_bridge_data *bridge, u32 mode)
{
struct pci_dev *device = NULL;
u32 command;
@@ -79,10 +79,10 @@ static void sis_delayed_enable(u32 mode)
printk(KERN_INFO PFX "Found an AGP %d.%d compliant device at %s.\n",
agp_bridge->major_version,
agp_bridge->minor_version,
- agp_bridge->dev->slot_name);
+ pci_name(agp_bridge->dev));
pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx + PCI_AGP_STATUS, &command);
- command = agp_collect_device_status(mode, command);
+ command = agp_collect_device_status(bridge, mode, command);
command |= AGPSTAT_AGP_ENABLE;
rate = (command & 0x7) << 2;
@@ -99,9 +99,9 @@ static void sis_delayed_enable(u32 mode)
/*
* Weird: on some sis chipsets any rate change in the target
* command register triggers a 5ms screwup during which the master
- * cannot be configured
+ * cannot be configured
*/
- if (device->device == agp_bridge->dev->device) {
+ if (device->device == bridge->dev->device) {
printk(KERN_INFO PFX "SiS delay workaround: giving bridge time to recover.\n");
msleep(10);
}
@@ -342,7 +342,7 @@ static int __init agp_sis_init(void)
{
if (agp_off)
return -EINVAL;
- return pci_module_init(&agp_sis_pci_driver);
+ return pci_register_driver(&agp_sis_pci_driver);
}
static void __exit agp_sis_cleanup(void)
diff --git a/drivers/char/agp/sworks-agp.c b/drivers/char/agp/sworks-agp.c
index 44b24fa6f2a57..bb338d9134e0f 100644
--- a/drivers/char/agp/sworks-agp.c
+++ b/drivers/char/agp/sworks-agp.c
@@ -141,7 +141,7 @@ static int serverworks_create_gatt_pages(int nr_tables)
#define GET_GATT_OFF(addr) ((addr & 0x003ff000) >> 12)
#endif
-static int serverworks_create_gatt_table(void)
+static int serverworks_create_gatt_table(struct agp_bridge_data *bridge)
{
struct aper_size_info_lvl2 *value;
struct serverworks_page_map page_dir;
@@ -192,7 +192,7 @@ static int serverworks_create_gatt_table(void)
return 0;
}
-static int serverworks_free_gatt_table(void)
+static int serverworks_free_gatt_table(struct agp_bridge_data *bridge)
{
struct serverworks_page_map page_dir;
@@ -341,7 +341,7 @@ static int serverworks_insert_memory(struct agp_memory *mem,
for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr;
cur_gatt = SVRWRKS_GET_GATT(addr);
- writel(agp_bridge->driver->mask_memory(mem->memory[i], mem->type), cur_gatt+GET_GATT_OFF(addr));
+ writel(agp_bridge->driver->mask_memory(agp_bridge, mem->memory[i], mem->type), cur_gatt+GET_GATT_OFF(addr));
}
serverworks_tlbflush(mem);
return 0;
@@ -387,15 +387,15 @@ static struct aper_size_info_lvl2 serverworks_sizes[7] =
{32, 8192, 0xfe000000}
};
-static void serverworks_agp_enable(u32 mode)
+static void serverworks_agp_enable(struct agp_bridge_data *bridge, u32 mode)
{
u32 command;
pci_read_config_dword(serverworks_private.svrwrks_dev,
- agp_bridge->capndx + PCI_AGP_STATUS,
+ bridge->capndx + PCI_AGP_STATUS,
&command);
- command = agp_collect_device_status(mode, command);
+ command = agp_collect_device_status(bridge, mode, command);
command &= ~0x10; /* disable FW */
command &= ~0x08;
@@ -403,7 +403,7 @@ static void serverworks_agp_enable(u32 mode)
command |= 0x100;
pci_write_config_dword(serverworks_private.svrwrks_dev,
- agp_bridge->capndx + PCI_AGP_COMMAND,
+ bridge->capndx + PCI_AGP_COMMAND,
command);
agp_device_command(command, 0);
@@ -541,7 +541,7 @@ static int __init agp_serverworks_init(void)
{
if (agp_off)
return -EINVAL;
- return pci_module_init(&agp_serverworks_pci_driver);
+ return pci_register_driver(&agp_serverworks_pci_driver);
}
static void __exit agp_serverworks_cleanup(void)
diff --git a/drivers/char/agp/uninorth-agp.c b/drivers/char/agp/uninorth-agp.c
index 4eb72b7107db7..0f248239b4ba5 100644
--- a/drivers/char/agp/uninorth-agp.c
+++ b/drivers/char/agp/uninorth-agp.c
@@ -6,10 +6,26 @@
#include <linux/init.h>
#include <linux/pagemap.h>
#include <linux/agp_backend.h>
+#include <linux/delay.h>
#include <asm/uninorth.h>
#include <asm/pci-bridge.h>
+#include <asm/prom.h>
#include "agp.h"
+/*
+ * NOTES for uninorth3 (G5 AGP) supports :
+ *
+ * There maybe also possibility to have bigger cache line size for
+ * agp (see pmac_pci.c and look for cache line). Need to be investigated
+ * by someone.
+ *
+ * PAGE size are hardcoded but this may change, see asm/page.h.
+ *
+ * Jerome Glisse <j.glisse@gmail.com>
+ */
+static int uninorth_rev;
+static int is_u3;
+
static int uninorth_fetch_size(void)
{
int i;
@@ -39,26 +55,39 @@ static int uninorth_fetch_size(void)
static void uninorth_tlbflush(struct agp_memory *mem)
{
+ u32 ctrl = UNI_N_CFG_GART_ENABLE;
+
+ if (is_u3)
+ ctrl |= U3_N_CFG_GART_PERFRD;
pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL,
- UNI_N_CFG_GART_ENABLE | UNI_N_CFG_GART_INVAL);
- pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL,
- UNI_N_CFG_GART_ENABLE);
- pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL,
- UNI_N_CFG_GART_ENABLE | UNI_N_CFG_GART_2xRESET);
- pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL,
- UNI_N_CFG_GART_ENABLE);
+ ctrl | UNI_N_CFG_GART_INVAL);
+ pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL, ctrl);
+
+ if (uninorth_rev <= 0x30) {
+ pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL,
+ ctrl | UNI_N_CFG_GART_2xRESET);
+ pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL,
+ ctrl);
+ }
}
static void uninorth_cleanup(void)
{
- pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL,
- UNI_N_CFG_GART_ENABLE | UNI_N_CFG_GART_INVAL);
- pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL,
- 0);
- pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL,
- UNI_N_CFG_GART_2xRESET);
- pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL,
- 0);
+ u32 tmp;
+
+ pci_read_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL, &tmp);
+ if (!(tmp & UNI_N_CFG_GART_ENABLE))
+ return;
+ tmp |= UNI_N_CFG_GART_INVAL;
+ pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL, tmp);
+ pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL, 0);
+
+ if (uninorth_rev <= 0x30) {
+ pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL,
+ UNI_N_CFG_GART_2xRESET);
+ pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL,
+ 0);
+ }
}
static int uninorth_configure(void)
@@ -81,8 +110,21 @@ static int uninorth_configure(void)
* the AGP aperture isn't mapped at bus physical address 0
*/
agp_bridge->gart_bus_addr = 0;
+#ifdef CONFIG_PPC64
+ /* Assume U3 or later on PPC64 systems */
+ /* high 4 bits of GART physical address go in UNI_N_CFG_AGP_BASE */
+ pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_AGP_BASE,
+ (agp_bridge->gatt_bus_addr >> 32) & 0xf);
+#else
pci_write_config_dword(agp_bridge->dev,
UNI_N_CFG_AGP_BASE, agp_bridge->gart_bus_addr);
+#endif
+
+ if (is_u3) {
+ pci_write_config_dword(agp_bridge->dev,
+ UNI_N_CFG_GART_DUMMY_PAGE,
+ agp_bridge->scratch_page_real >> 12);
+ }
return 0;
}
@@ -105,13 +147,14 @@ static int uninorth_insert_memory(struct agp_memory *mem, off_t pg_start,
j = pg_start;
while (j < (pg_start + mem->page_count)) {
- if (!PGE_EMPTY(agp_bridge, agp_bridge->gatt_table[j]))
+ if (agp_bridge->gatt_table[j])
return -EBUSY;
j++;
}
for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
- agp_bridge->gatt_table[j] = cpu_to_le32((mem->memory[i] & 0xfffff000) | 0x00000001UL);
+ agp_bridge->gatt_table[j] =
+ cpu_to_le32((mem->memory[i] & 0xFFFFF000UL) | 0x1UL);
flush_dcache_range((unsigned long)__va(mem->memory[i]),
(unsigned long)__va(mem->memory[i])+0x1000);
}
@@ -124,38 +167,173 @@ static int uninorth_insert_memory(struct agp_memory *mem, off_t pg_start,
return 0;
}
-static void uninorth_agp_enable(u32 mode)
+static int u3_insert_memory(struct agp_memory *mem, off_t pg_start, int type)
+{
+ int i, num_entries;
+ void *temp;
+ u32 *gp;
+
+ temp = agp_bridge->current_size;
+ num_entries = A_SIZE_32(temp)->num_entries;
+
+ if (type != 0 || mem->type != 0)
+ /* We know nothing of memory types */
+ return -EINVAL;
+ if ((pg_start + mem->page_count) > num_entries)
+ return -EINVAL;
+
+ gp = (u32 *) &agp_bridge->gatt_table[pg_start];
+ for (i = 0; i < mem->page_count; ++i) {
+ if (gp[i]) {
+ printk("u3_insert_memory: entry 0x%x occupied (%x)\n",
+ i, gp[i]);
+ return -EBUSY;
+ }
+ }
+
+ for (i = 0; i < mem->page_count; i++) {
+ gp[i] = (mem->memory[i] >> PAGE_SHIFT) | 0x80000000UL;
+ flush_dcache_range((unsigned long)__va(mem->memory[i]),
+ (unsigned long)__va(mem->memory[i])+0x1000);
+ }
+ mb();
+ flush_dcache_range((unsigned long)gp, (unsigned long) &gp[i]);
+ uninorth_tlbflush(mem);
+
+ return 0;
+}
+
+int u3_remove_memory(struct agp_memory *mem, off_t pg_start, int type)
{
- u32 command, scratch;
+ size_t i;
+ u32 *gp;
+
+ if (type != 0 || mem->type != 0)
+ /* We know nothing of memory types */
+ return -EINVAL;
+
+ gp = (u32 *) &agp_bridge->gatt_table[pg_start];
+ for (i = 0; i < mem->page_count; ++i)
+ gp[i] = 0;
+ mb();
+ flush_dcache_range((unsigned long)gp, (unsigned long) &gp[i]);
+ uninorth_tlbflush(mem);
+
+ return 0;
+}
+
+static void uninorth_agp_enable(struct agp_bridge_data *bridge, u32 mode)
+{
+ u32 command, scratch, status;
int timeout;
- pci_read_config_dword(agp_bridge->dev,
- agp_bridge->capndx + PCI_AGP_STATUS,
- &command);
+ pci_read_config_dword(bridge->dev,
+ bridge->capndx + PCI_AGP_STATUS,
+ &status);
- command = agp_collect_device_status(mode, command);
- command |= 0x100;
+ command = agp_collect_device_status(bridge, mode, status);
+ command |= PCI_AGP_COMMAND_AGP;
+
+ if (uninorth_rev == 0x21) {
+ /*
+ * Darwin disable AGP 4x on this revision, thus we
+ * may assume it's broken. This is an AGP2 controller.
+ */
+ command &= ~AGPSTAT2_4X;
+ }
+
+ if ((uninorth_rev >= 0x30) && (uninorth_rev <= 0x33)) {
+ /*
+ * We need to to set REQ_DEPTH to 7 for U3 versions 1.0, 2.1,
+ * 2.2 and 2.3, Darwin do so.
+ */
+ if ((command >> AGPSTAT_RQ_DEPTH_SHIFT) > 7)
+ command = (command & ~AGPSTAT_RQ_DEPTH)
+ | (7 << AGPSTAT_RQ_DEPTH_SHIFT);
+ }
uninorth_tlbflush(NULL);
timeout = 0;
do {
- pci_write_config_dword(agp_bridge->dev,
- agp_bridge->capndx + PCI_AGP_COMMAND,
+ pci_write_config_dword(bridge->dev,
+ bridge->capndx + PCI_AGP_COMMAND,
command);
- pci_read_config_dword(agp_bridge->dev,
- agp_bridge->capndx + PCI_AGP_COMMAND,
+ pci_read_config_dword(bridge->dev,
+ bridge->capndx + PCI_AGP_COMMAND,
&scratch);
- } while ((scratch & 0x100) == 0 && ++timeout < 1000);
- if ((scratch & 0x100) == 0)
+ } while ((scratch & PCI_AGP_COMMAND_AGP) == 0 && ++timeout < 1000);
+ if ((scratch & PCI_AGP_COMMAND_AGP) == 0)
printk(KERN_ERR PFX "failed to write UniNorth AGP command reg\n");
- agp_device_command(command, 0);
+ if (uninorth_rev >= 0x30) {
+ /* This is an AGP V3 */
+ agp_device_command(command, (status & AGPSTAT_MODE_3_0));
+ } else {
+ /* AGP V2 */
+ agp_device_command(command, 0);
+ }
uninorth_tlbflush(NULL);
}
-static int uninorth_create_gatt_table(void)
+#ifdef CONFIG_PM
+static int agp_uninorth_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+ u32 cmd;
+ u8 agp;
+ struct pci_dev *device = NULL;
+
+ if (state != PMSG_SUSPEND)
+ return 0;
+
+ /* turn off AGP on the video chip, if it was enabled */
+ for_each_pci_dev(device) {
+ /* Don't touch the bridge yet, device first */
+ if (device == pdev)
+ continue;
+ /* Only deal with devices on the same bus here, no Mac has a P2P
+ * bridge on the AGP port, and mucking around the entire PCI
+ * tree is source of problems on some machines because of a bug
+ * in some versions of pci_find_capability() when hitting a dead
+ * device
+ */
+ if (device->bus != pdev->bus)
+ continue;
+ agp = pci_find_capability(device, PCI_CAP_ID_AGP);
+ if (!agp)
+ continue;
+ pci_read_config_dword(device, agp + PCI_AGP_COMMAND, &cmd);
+ if (!(cmd & PCI_AGP_COMMAND_AGP))
+ continue;
+ printk("uninorth-agp: disabling AGP on device %s\n",
+ pci_name(device));
+ cmd &= ~PCI_AGP_COMMAND_AGP;
+ pci_write_config_dword(device, agp + PCI_AGP_COMMAND, cmd);
+ }
+
+ /* turn off AGP on the bridge */
+ agp = pci_find_capability(pdev, PCI_CAP_ID_AGP);
+ pci_read_config_dword(pdev, agp + PCI_AGP_COMMAND, &cmd);
+ if (cmd & PCI_AGP_COMMAND_AGP) {
+ printk("uninorth-agp: disabling AGP on bridge %s\n",
+ pci_name(pdev));
+ cmd &= ~PCI_AGP_COMMAND_AGP;
+ pci_write_config_dword(pdev, agp + PCI_AGP_COMMAND, cmd);
+ }
+ /* turn off the GART */
+ uninorth_cleanup();
+
+ return 0;
+}
+
+static int agp_uninorth_resume(struct pci_dev *pdev)
+{
+ return 0;
+}
+#endif
+
+static int uninorth_create_gatt_table(struct agp_bridge_data *bridge)
{
char *table;
char *table_end;
@@ -167,12 +345,12 @@ static int uninorth_create_gatt_table(void)
struct page *page;
/* We can't handle 2 level gatt's */
- if (agp_bridge->driver->size_type == LVL2_APER_SIZE)
+ if (bridge->driver->size_type == LVL2_APER_SIZE)
return -EINVAL;
table = NULL;
- i = agp_bridge->aperture_size_idx;
- temp = agp_bridge->current_size;
+ i = bridge->aperture_size_idx;
+ temp = bridge->current_size;
size = page_order = num_entries = 0;
do {
@@ -184,11 +362,11 @@ static int uninorth_create_gatt_table(void)
if (table == NULL) {
i++;
- agp_bridge->current_size = A_IDX32(agp_bridge);
+ bridge->current_size = A_IDX32(bridge);
} else {
- agp_bridge->aperture_size_idx = i;
+ bridge->aperture_size_idx = i;
}
- } while (!table && (i < agp_bridge->driver->num_aperture_sizes));
+ } while (!table && (i < bridge->driver->num_aperture_sizes));
if (table == NULL)
return -ENOMEM;
@@ -198,28 +376,26 @@ static int uninorth_create_gatt_table(void)
for (page = virt_to_page(table); page <= virt_to_page(table_end); page++)
SetPageReserved(page);
- agp_bridge->gatt_table_real = (u32 *) table;
- agp_bridge->gatt_table = (u32 *)table;
- agp_bridge->gatt_bus_addr = virt_to_phys(table);
+ bridge->gatt_table_real = (u32 *) table;
+ bridge->gatt_table = (u32 *)table;
+ bridge->gatt_bus_addr = virt_to_phys(table);
- for (i = 0; i < num_entries; i++) {
- agp_bridge->gatt_table[i] =
- (unsigned long) agp_bridge->scratch_page;
- }
+ for (i = 0; i < num_entries; i++)
+ bridge->gatt_table[i] = 0;
flush_dcache_range((unsigned long)table, (unsigned long)table_end);
return 0;
}
-static int uninorth_free_gatt_table(void)
+static int uninorth_free_gatt_table(struct agp_bridge_data *bridge)
{
int page_order;
char *table, *table_end;
void *temp;
struct page *page;
- temp = agp_bridge->current_size;
+ temp = bridge->current_size;
page_order = A_SIZE_32(temp)->page_order;
/* Do not worry about freeing memory, because if this is
@@ -227,13 +403,13 @@ static int uninorth_free_gatt_table(void)
* from the table.
*/
- table = (char *) agp_bridge->gatt_table_real;
+ table = (char *) bridge->gatt_table_real;
table_end = table + ((PAGE_SIZE * (1 << page_order)) - 1);
for (page = virt_to_page(table); page <= virt_to_page(table_end); page++)
ClearPageReserved(page);
- free_pages((unsigned long) agp_bridge->gatt_table_real, page_order);
+ free_pages((unsigned long) bridge->gatt_table_real, page_order);
return 0;
}
@@ -258,6 +434,22 @@ static struct aper_size_info_32 uninorth_sizes[7] =
{4, 1024, 0, 1}
};
+/*
+ * Not sure that u3 supports that high aperture sizes but it
+ * would strange if it did not :)
+ */
+static struct aper_size_info_32 u3_sizes[8] =
+{
+ {512, 131072, 7, 128},
+ {256, 65536, 6, 64},
+ {128, 32768, 5, 32},
+ {64, 16384, 4, 16},
+ {32, 8192, 3, 8},
+ {16, 4096, 2, 4},
+ {8, 2048, 1, 2},
+ {4, 1024, 0, 1}
+};
+
struct agp_bridge_driver uninorth_agp_driver = {
.owner = THIS_MODULE,
.aperture_sizes = (void *)uninorth_sizes,
@@ -282,6 +474,31 @@ struct agp_bridge_driver uninorth_agp_driver = {
.cant_use_aperture = 1,
};
+struct agp_bridge_driver u3_agp_driver = {
+ .owner = THIS_MODULE,
+ .aperture_sizes = (void *)u3_sizes,
+ .size_type = U32_APER_SIZE,
+ .num_aperture_sizes = 8,
+ .configure = uninorth_configure,
+ .fetch_size = uninorth_fetch_size,
+ .cleanup = uninorth_cleanup,
+ .tlb_flush = uninorth_tlbflush,
+ .mask_memory = agp_generic_mask_memory,
+ .masks = NULL,
+ .cache_flush = null_cache_flush,
+ .agp_enable = uninorth_agp_enable,
+ .create_gatt_table = uninorth_create_gatt_table,
+ .free_gatt_table = uninorth_free_gatt_table,
+ .insert_memory = u3_insert_memory,
+ .remove_memory = u3_remove_memory,
+ .alloc_by_type = agp_generic_alloc_by_type,
+ .free_by_type = agp_generic_free_by_type,
+ .agp_alloc_page = agp_generic_alloc_page,
+ .agp_destroy_page = agp_generic_destroy_page,
+ .cant_use_aperture = 1,
+ .needs_scratch_page = 1,
+};
+
static struct agp_device_ids uninorth_agp_device_ids[] __devinitdata = {
{
.device_id = PCI_DEVICE_ID_APPLE_UNI_N_AGP,
@@ -299,6 +516,18 @@ static struct agp_device_ids uninorth_agp_device_ids[] __devinitdata = {
.device_id = PCI_DEVICE_ID_APPLE_UNI_N_AGP2,
.chipset_name = "UniNorth 2",
},
+ {
+ .device_id = PCI_DEVICE_ID_APPLE_U3_AGP,
+ .chipset_name = "U3",
+ },
+ {
+ .device_id = PCI_DEVICE_ID_APPLE_U3L_AGP,
+ .chipset_name = "U3L",
+ },
+ {
+ .device_id = PCI_DEVICE_ID_APPLE_U3H_AGP,
+ .chipset_name = "U3H",
+ },
};
static int __devinit agp_uninorth_probe(struct pci_dev *pdev,
@@ -306,6 +535,7 @@ static int __devinit agp_uninorth_probe(struct pci_dev *pdev,
{
struct agp_device_ids *devs = uninorth_agp_device_ids;
struct agp_bridge_data *bridge;
+ struct device_node *uninorth_node;
u8 cap_ptr;
int j;
@@ -327,13 +557,36 @@ static int __devinit agp_uninorth_probe(struct pci_dev *pdev,
return -ENODEV;
found:
+ /* Set revision to 0 if we could not read it. */
+ uninorth_rev = 0;
+ is_u3 = 0;
+ /* Locate core99 Uni-N */
+ uninorth_node = of_find_node_by_name(NULL, "uni-n");
+ /* Locate G5 u3 */
+ if (uninorth_node == NULL) {
+ is_u3 = 1;
+ uninorth_node = of_find_node_by_name(NULL, "u3");
+ }
+ if (uninorth_node) {
+ int *revprop = (int *)
+ get_property(uninorth_node, "device-rev", NULL);
+ if (revprop != NULL)
+ uninorth_rev = *revprop & 0x3f;
+ of_node_put(uninorth_node);
+ }
+
bridge = agp_alloc_bridge();
if (!bridge)
return -ENOMEM;
- bridge->driver = &uninorth_agp_driver;
+ if (is_u3)
+ bridge->driver = &u3_agp_driver;
+ else
+ bridge->driver = &uninorth_agp_driver;
+
bridge->dev = pdev;
bridge->capndx = cap_ptr;
+ bridge->flags = AGP_ERRATA_FASTWRITES;
/* Fill in the mode register */
pci_read_config_dword(pdev, cap_ptr+PCI_AGP_STATUS, &bridge->mode);
@@ -369,13 +622,17 @@ static struct pci_driver agp_uninorth_pci_driver = {
.id_table = agp_uninorth_pci_table,
.probe = agp_uninorth_probe,
.remove = agp_uninorth_remove,
+#ifdef CONFIG_PM
+ .suspend = agp_uninorth_suspend,
+ .resume = agp_uninorth_resume,
+#endif
};
static int __init agp_uninorth_init(void)
{
if (agp_off)
return -EINVAL;
- return pci_module_init(&agp_uninorth_pci_driver);
+ return pci_register_driver(&agp_uninorth_pci_driver);
}
static void __exit agp_uninorth_cleanup(void)
diff --git a/drivers/char/agp/via-agp.c b/drivers/char/agp/via-agp.c
index b15dcd941bb0d..e1451dd9b6a7c 100644
--- a/drivers/char/agp/via-agp.c
+++ b/drivers/char/agp/via-agp.c
@@ -1,5 +1,5 @@
/*
- * VIA AGPGART routines.
+ * VIA AGPGART routines.
*/
#include <linux/types.h>
@@ -36,6 +36,7 @@ static int via_fetch_size(void)
return values[i].size;
}
}
+ printk(KERN_ERR PFX "Unknown aperture size from AGP bridge (0x%x)\n", temp);
return 0;
}
@@ -78,12 +79,17 @@ static void via_cleanup(void)
static void via_tlbflush(struct agp_memory *mem)
{
- pci_write_config_dword(agp_bridge->dev, VIA_GARTCTRL, 0x0000008f);
- pci_write_config_dword(agp_bridge->dev, VIA_GARTCTRL, 0x0000000f);
+ u32 temp;
+
+ pci_read_config_dword(agp_bridge->dev, VIA_GARTCTRL, &temp);
+ temp |= (1<<7);
+ pci_write_config_dword(agp_bridge->dev, VIA_GARTCTRL, temp);
+ temp &= ~(1<<7);
+ pci_write_config_dword(agp_bridge->dev, VIA_GARTCTRL, temp);
}
-static struct aper_size_info_8 via_generic_sizes[7] =
+static struct aper_size_info_8 via_generic_sizes[9] =
{
{256, 65536, 6, 0},
{128, 32768, 5, 128},
@@ -91,7 +97,9 @@ static struct aper_size_info_8 via_generic_sizes[7] =
{32, 8192, 3, 224},
{16, 4096, 2, 240},
{8, 2048, 1, 248},
- {4, 1024, 0, 252}
+ {4, 1024, 0, 252},
+ {2, 512, 0, 254},
+ {1, 256, 0, 255}
};
@@ -121,7 +129,7 @@ static int via_configure_agp3(void)
{
u32 temp;
struct aper_size_info_16 *current_size;
-
+
current_size = A_SIZE_16(agp_bridge->current_size);
/* address to map too */
@@ -132,13 +140,13 @@ static int via_configure_agp3(void)
pci_write_config_dword(agp_bridge->dev, VIA_AGP3_ATTBASE,
agp_bridge->gatt_bus_addr & 0xfffff000);
- /* 1. Enable GTLB in RX90<7>, all AGP aperture access needs to fetch
+ /* 1. Enable GTLB in RX90<7>, all AGP aperture access needs to fetch
* translation table first.
* 2. Enable AGP aperture in RX91<0>. This bit controls the enabling of the
* graphics AGP aperture for the AGP3.0 port.
*/
pci_read_config_dword(agp_bridge->dev, VIA_AGP3_GARTCTRL, &temp);
- pci_write_config_dword(agp_bridge->dev, VIA_AGP3_GARTCTRL, temp | (3<<7));
+ pci_write_config_dword(agp_bridge->dev, VIA_AGP3_GARTCTRL, temp | (3<<7));
return 0;
}
@@ -189,7 +197,7 @@ struct agp_bridge_driver via_driver = {
.owner = THIS_MODULE,
.aperture_sizes = via_generic_sizes,
.size_type = U8_APER_SIZE,
- .num_aperture_sizes = 7,
+ .num_aperture_sizes = 9,
.configure = via_configure,
.fetch_size = via_fetch_size,
.cleanup = via_cleanup,
@@ -440,10 +448,10 @@ static void __devexit agp_via_remove(struct pci_dev *pdev)
#ifdef CONFIG_PM
-static int agp_via_suspend(struct pci_dev *pdev, u32 state)
+static int agp_via_suspend(struct pci_dev *pdev, pm_message_t state)
{
pci_save_state (pdev);
- pci_set_power_state (pdev, 3);
+ pci_set_power_state (pdev, PCI_D3hot);
return 0;
}
@@ -452,7 +460,7 @@ static int agp_via_resume(struct pci_dev *pdev)
{
struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
- pci_set_power_state (pdev, 0);
+ pci_set_power_state (pdev, PCI_D0);
pci_restore_state(pdev);
if (bridge->driver == &via_agp3_driver)
@@ -525,7 +533,7 @@ static int __init agp_via_init(void)
{
if (agp_off)
return -EINVAL;
- return pci_module_init(&agp_via_pci_driver);
+ return pci_register_driver(&agp_via_pci_driver);
}
static void __exit agp_via_cleanup(void)
diff --git a/drivers/char/console_macros.h b/drivers/char/console_macros.h
deleted file mode 100644
index 93b5d23fa1375..0000000000000
--- a/drivers/char/console_macros.h
+++ /dev/null
@@ -1,71 +0,0 @@
-#define cons_num (vc_cons[currcons].d->vc_num)
-#define video_scan_lines (vc_cons[currcons].d->vc_scan_lines)
-#define sw (vc_cons[currcons].d->vc_sw)
-#define screenbuf (vc_cons[currcons].d->vc_screenbuf)
-#define screenbuf_size (vc_cons[currcons].d->vc_screenbuf_size)
-#define origin (vc_cons[currcons].d->vc_origin)
-#define scr_top (vc_cons[currcons].d->vc_scr_top)
-#define visible_origin (vc_cons[currcons].d->vc_visible_origin)
-#define scr_end (vc_cons[currcons].d->vc_scr_end)
-#define pos (vc_cons[currcons].d->vc_pos)
-#define top (vc_cons[currcons].d->vc_top)
-#define bottom (vc_cons[currcons].d->vc_bottom)
-#define x (vc_cons[currcons].d->vc_x)
-#define y (vc_cons[currcons].d->vc_y)
-#define vc_state (vc_cons[currcons].d->vc_state)
-#define npar (vc_cons[currcons].d->vc_npar)
-#define par (vc_cons[currcons].d->vc_par)
-#define ques (vc_cons[currcons].d->vc_ques)
-#define attr (vc_cons[currcons].d->vc_attr)
-#define saved_x (vc_cons[currcons].d->vc_saved_x)
-#define saved_y (vc_cons[currcons].d->vc_saved_y)
-#define translate (vc_cons[currcons].d->vc_translate)
-#define G0_charset (vc_cons[currcons].d->vc_G0_charset)
-#define G1_charset (vc_cons[currcons].d->vc_G1_charset)
-#define saved_G0 (vc_cons[currcons].d->vc_saved_G0)
-#define saved_G1 (vc_cons[currcons].d->vc_saved_G1)
-#define utf (vc_cons[currcons].d->vc_utf)
-#define utf_count (vc_cons[currcons].d->vc_utf_count)
-#define utf_char (vc_cons[currcons].d->vc_utf_char)
-#define video_erase_char (vc_cons[currcons].d->vc_video_erase_char)
-#define disp_ctrl (vc_cons[currcons].d->vc_disp_ctrl)
-#define toggle_meta (vc_cons[currcons].d->vc_toggle_meta)
-#define decscnm (vc_cons[currcons].d->vc_decscnm)
-#define decom (vc_cons[currcons].d->vc_decom)
-#define decawm (vc_cons[currcons].d->vc_decawm)
-#define deccm (vc_cons[currcons].d->vc_deccm)
-#define decim (vc_cons[currcons].d->vc_decim)
-#define deccolm (vc_cons[currcons].d->vc_deccolm)
-#define need_wrap (vc_cons[currcons].d->vc_need_wrap)
-#define kmalloced (vc_cons[currcons].d->vc_kmalloced)
-#define report_mouse (vc_cons[currcons].d->vc_report_mouse)
-#define color (vc_cons[currcons].d->vc_color)
-#define s_color (vc_cons[currcons].d->vc_s_color)
-#define def_color (vc_cons[currcons].d->vc_def_color)
-#define foreground (color & 0x0f)
-#define background (color & 0xf0)
-#define charset (vc_cons[currcons].d->vc_charset)
-#define s_charset (vc_cons[currcons].d->vc_s_charset)
-#define intensity (vc_cons[currcons].d->vc_intensity)
-#define underline (vc_cons[currcons].d->vc_underline)
-#define blink (vc_cons[currcons].d->vc_blink)
-#define reverse (vc_cons[currcons].d->vc_reverse)
-#define s_intensity (vc_cons[currcons].d->vc_s_intensity)
-#define s_underline (vc_cons[currcons].d->vc_s_underline)
-#define s_blink (vc_cons[currcons].d->vc_s_blink)
-#define s_reverse (vc_cons[currcons].d->vc_s_reverse)
-#define ulcolor (vc_cons[currcons].d->vc_ulcolor)
-#define halfcolor (vc_cons[currcons].d->vc_halfcolor)
-#define tab_stop (vc_cons[currcons].d->vc_tab_stop)
-#define palette (vc_cons[currcons].d->vc_palette)
-#define bell_pitch (vc_cons[currcons].d->vc_bell_pitch)
-#define bell_duration (vc_cons[currcons].d->vc_bell_duration)
-#define cursor_type (vc_cons[currcons].d->vc_cursor_type)
-#define display_fg (vc_cons[currcons].d->vc_display_fg)
-#define complement_mask (vc_cons[currcons].d->vc_complement_mask)
-#define s_complement_mask (vc_cons[currcons].d->vc_s_complement_mask)
-#define hi_font_mask (vc_cons[currcons].d->vc_hi_font_mask)
-
-#define vcmode (vt_cons[currcons]->vc_mode)
-
-#define structsize (sizeof(struct vc_data) + sizeof(struct vt_struct))
diff --git a/drivers/char/consolemap.c b/drivers/char/consolemap.c
index 6f96e3ce081c9..406dea914635f 100644
--- a/drivers/char/consolemap.c
+++ b/drivers/char/consolemap.c
@@ -208,9 +208,9 @@ static void set_inverse_transl(struct vc_data *conp, struct uni_pagedir *p, int
}
}
-unsigned short *set_translate(int m,int currcons)
+unsigned short *set_translate(int m, struct vc_data *vc)
{
- inv_translate[currcons] = m;
+ inv_translate[vc->vc_num] = m;
return translations[m];
}
@@ -262,9 +262,8 @@ int con_set_trans_old(unsigned char __user * arg)
int i;
unsigned short *p = translations[USER_MAP];
- i = verify_area(VERIFY_READ, arg, E_TABSZ);
- if (i)
- return i;
+ if (!access_ok(VERIFY_READ, arg, E_TABSZ))
+ return -EFAULT;
for (i=0; i<E_TABSZ ; i++) {
unsigned char uc;
@@ -281,9 +280,8 @@ int con_get_trans_old(unsigned char __user * arg)
int i, ch;
unsigned short *p = translations[USER_MAP];
- i = verify_area(VERIFY_WRITE, arg, E_TABSZ);
- if (i)
- return i;
+ if (!access_ok(VERIFY_WRITE, arg, E_TABSZ))
+ return -EFAULT;
for (i=0; i<E_TABSZ ; i++)
{
@@ -298,9 +296,8 @@ int con_set_trans_new(ushort __user * arg)
int i;
unsigned short *p = translations[USER_MAP];
- i = verify_area(VERIFY_READ, arg, E_TABSZ*sizeof(unsigned short));
- if (i)
- return i;
+ if (!access_ok(VERIFY_READ, arg, E_TABSZ*sizeof(unsigned short)))
+ return -EFAULT;
for (i=0; i<E_TABSZ ; i++) {
unsigned short us;
@@ -317,9 +314,8 @@ int con_get_trans_new(ushort __user * arg)
int i;
unsigned short *p = translations[USER_MAP];
- i = verify_area(VERIFY_WRITE, arg, E_TABSZ*sizeof(unsigned short));
- if (i)
- return i;
+ if (!access_ok(VERIFY_WRITE, arg, E_TABSZ*sizeof(unsigned short)))
+ return -EFAULT;
for (i=0; i<E_TABSZ ; i++)
__put_user(p[i], arg+i);
@@ -362,15 +358,16 @@ static void con_release_unimap(struct uni_pagedir *p)
}
}
-void con_free_unimap(int con)
+void con_free_unimap(struct vc_data *vc)
{
struct uni_pagedir *p;
- struct vc_data *conp = vc_cons[con].d;
-
- p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc;
- if (!p) return;
- *conp->vc_uni_pagedir_loc = 0;
- if (--p->refcount) return;
+
+ p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
+ if (!p)
+ return;
+ *vc->vc_uni_pagedir_loc = 0;
+ if (--p->refcount)
+ return;
con_release_unimap(p);
kfree(p);
}
@@ -442,12 +439,11 @@ con_insert_unipair(struct uni_pagedir *p, u_short unicode, u_short fontpos)
}
/* ui is a leftover from using a hashtable, but might be used again */
-int con_clear_unimap(int con, struct unimapinit *ui)
+int con_clear_unimap(struct vc_data *vc, struct unimapinit *ui)
{
struct uni_pagedir *p, *q;
- struct vc_data *conp = vc_cons[con].d;
- p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc;
+ p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
if (p && p->readonly) return -EIO;
if (!p || --p->refcount) {
q = (struct uni_pagedir *)kmalloc(sizeof(*p), GFP_KERNEL);
@@ -457,7 +453,7 @@ int con_clear_unimap(int con, struct unimapinit *ui)
}
memset(q, 0, sizeof(*q));
q->refcount=1;
- *conp->vc_uni_pagedir_loc = (unsigned long)q;
+ *vc->vc_uni_pagedir_loc = (unsigned long)q;
} else {
if (p == dflt) dflt = NULL;
p->refcount++;
@@ -467,14 +463,12 @@ int con_clear_unimap(int con, struct unimapinit *ui)
return 0;
}
-int
-con_set_unimap(int con, ushort ct, struct unipair __user *list)
+int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
{
int err = 0, err1, i;
struct uni_pagedir *p, *q;
- struct vc_data *conp = vc_cons[con].d;
- p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc;
+ p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
if (p->readonly) return -EIO;
if (!ct) return 0;
@@ -483,10 +477,10 @@ con_set_unimap(int con, ushort ct, struct unipair __user *list)
int j, k;
u16 **p1, *p2, l;
- err1 = con_clear_unimap(con, NULL);
+ err1 = con_clear_unimap(vc, NULL);
if (err1) return err1;
- q = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc;
+ q = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
for (i = 0, l = 0; i < 32; i++)
if ((p1 = p->uni_pgdir[i]))
for (j = 0; j < 32; j++)
@@ -496,7 +490,7 @@ con_set_unimap(int con, ushort ct, struct unipair __user *list)
err1 = con_insert_unipair(q, l, p2[k]);
if (err1) {
p->refcount++;
- *conp->vc_uni_pagedir_loc = (unsigned long)p;
+ *vc->vc_uni_pagedir_loc = (unsigned long)p;
con_release_unimap(q);
kfree(q);
return err1;
@@ -515,11 +509,11 @@ con_set_unimap(int con, ushort ct, struct unipair __user *list)
list++;
}
- if (con_unify_unimap(conp, p))
+ if (con_unify_unimap(vc, p))
return err;
for (i = 0; i <= 3; i++)
- set_inverse_transl(conp, p, i); /* Update all inverse translations */
+ set_inverse_transl(vc, p, i); /* Update all inverse translations */
return err;
}
@@ -529,20 +523,18 @@ con_set_unimap(int con, ushort ct, struct unipair __user *list)
with. This routine is executed at sys_setup time, and when the
PIO_FONTRESET ioctl is called. */
-int
-con_set_default_unimap(int con)
+int con_set_default_unimap(struct vc_data *vc)
{
int i, j, err = 0, err1;
u16 *q;
struct uni_pagedir *p;
- struct vc_data *conp = vc_cons[con].d;
-
+
if (dflt) {
- p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc;
+ p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
if (p == dflt)
return 0;
dflt->refcount++;
- *conp->vc_uni_pagedir_loc = (unsigned long)dflt;
+ *vc->vc_uni_pagedir_loc = (unsigned long)dflt;
if (p && --p->refcount) {
con_release_unimap(p);
kfree(p);
@@ -552,10 +544,10 @@ con_set_default_unimap(int con)
/* The default font is always 256 characters */
- err = con_clear_unimap(con,NULL);
+ err = con_clear_unimap(vc, NULL);
if (err) return err;
- p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc;
+ p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
q = dfont_unitable;
for (i = 0; i < 256; i++)
@@ -565,47 +557,42 @@ con_set_default_unimap(int con)
err = err1;
}
- if (con_unify_unimap(conp, p)) {
- dflt = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc;
+ if (con_unify_unimap(vc, p)) {
+ dflt = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
return err;
}
for (i = 0; i <= 3; i++)
- set_inverse_transl(conp, p, i); /* Update all inverse translations */
+ set_inverse_transl(vc, p, i); /* Update all inverse translations */
dflt = p;
return err;
}
EXPORT_SYMBOL(con_set_default_unimap);
-int
-con_copy_unimap(int dstcon, int srccon)
+int con_copy_unimap(struct vc_data *dst_vc, struct vc_data *src_vc)
{
- struct vc_data *sconp = vc_cons[srccon].d;
- struct vc_data *dconp = vc_cons[dstcon].d;
struct uni_pagedir *q;
-
- if (!vc_cons_allocated(srccon) || !*sconp->vc_uni_pagedir_loc)
+
+ if (!*src_vc->vc_uni_pagedir_loc)
return -EINVAL;
- if (*dconp->vc_uni_pagedir_loc == *sconp->vc_uni_pagedir_loc)
+ if (*dst_vc->vc_uni_pagedir_loc == *src_vc->vc_uni_pagedir_loc)
return 0;
- con_free_unimap(dstcon);
- q = (struct uni_pagedir *)*sconp->vc_uni_pagedir_loc;
+ con_free_unimap(dst_vc);
+ q = (struct uni_pagedir *)*src_vc->vc_uni_pagedir_loc;
q->refcount++;
- *dconp->vc_uni_pagedir_loc = (long)q;
+ *dst_vc->vc_uni_pagedir_loc = (long)q;
return 0;
}
-int
-con_get_unimap(int con, ushort ct, ushort __user *uct, struct unipair __user *list)
+int con_get_unimap(struct vc_data *vc, ushort ct, ushort __user *uct, struct unipair __user *list)
{
int i, j, k, ect;
u16 **p1, *p2;
struct uni_pagedir *p;
- struct vc_data *conp = vc_cons[con].d;
ect = 0;
- if (*conp->vc_uni_pagedir_loc) {
- p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc;
+ if (*vc->vc_uni_pagedir_loc) {
+ p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
for (i = 0; i < 32; i++)
if ((p1 = p->uni_pgdir[i]))
for (j = 0; j < 32; j++)
@@ -625,12 +612,12 @@ con_get_unimap(int con, ushort ct, ushort __user *uct, struct unipair __user *li
return ((ect <= ct) ? 0 : -ENOMEM);
}
-void con_protect_unimap(int con, int rdonly)
+void con_protect_unimap(struct vc_data *vc, int rdonly)
{
- struct uni_pagedir *p = (struct uni_pagedir *)
- *vc_cons[con].d->vc_uni_pagedir_loc;
+ struct uni_pagedir *p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
- if (p) p->readonly = rdonly;
+ if (p)
+ p->readonly = rdonly;
}
int
@@ -679,7 +666,7 @@ console_map_init(void)
for (i = 0; i < MAX_NR_CONSOLES; i++)
if (vc_cons_allocated(i) && !*vc_cons[i].d->vc_uni_pagedir_loc)
- con_set_default_unimap(i);
+ con_set_default_unimap(vc_cons[i].d);
}
EXPORT_SYMBOL(con_copy_unimap);
diff --git a/drivers/char/digi_bios.h b/drivers/char/digi_bios.h
deleted file mode 100644
index 93e4608bd7228..0000000000000
--- a/drivers/char/digi_bios.h
+++ /dev/null
@@ -1,177 +0,0 @@
-/* DigiBoard PCXX Bios */
-
-static unsigned char pcxx_bios[] __initdata = {
- 0x28,0x43,0x29,0x20,0x43,0x6f,0x70,0x79,0x72,0x69,0x67,0x68,
- 0x74,0x20,0x31,0x39,0x39,0x34,0x2c,0x20,0x44,0x69,0x67,0x69,
- 0x42,0x6f,0x61,0x72,0x64,0x20,0x49,0x6e,0x63,0x2e,0x00,0x00,
- 0x8a,0xf8,0x8a,0xf8,0x15,0xf9,0x8a,0xf8,0x8a,0xf8,0x8a,0xf8,
- 0x8a,0xf8,0x8a,0xf8,0xbc,0xf8,0x8a,0xf8,0x96,0xf8,0x96,0xf8,
- 0x96,0xf8,0x96,0xf8,0x96,0xf8,0x96,0xf8,0x8a,0xf8,0x8a,0xf8,
- 0x96,0xf8,0x96,0xf8,0x8a,0xf8,0xad,0xf8,0xb0,0xf8,0x8a,0xf8,
- 0x8a,0xf8,0x8a,0xf8,0x8a,0xf8,0x8a,0xf8,0x8a,0xf8,0x8a,0xf8,
- 0x8a,0xf8,0x8a,0xf8,0x8a,0xf8,0x04,0x02,0x00,0x02,0x14,0x02,
- 0x10,0x02,0x24,0x02,0x20,0x02,0x34,0x02,0x30,0x02,0x44,0x02,
- 0x40,0x02,0x54,0x02,0x50,0x02,0x64,0x02,0x60,0x02,0x74,0x02,
- 0x70,0x02,0x04,0x01,0x00,0x01,0x1e,0x2e,0x8e,0x1e,0x22,0xf8,
- 0xfe,0x06,0x70,0x00,0x1f,0xcf,0x1e,0x50,0x52,0x2e,0x8e,0x1e,
- 0x22,0xf8,0xfe,0x06,0x71,0x00,0xb8,0x00,0x80,0xba,0x22,0xff,
- 0xef,0x5a,0x58,0x1f,0xcf,0xb4,0x80,0xcf,0x1e,0x2e,0x8e,0x1e,
- 0x22,0xf8,0xfe,0x06,0x2b,0x00,0x1f,0xcf,0x1e,0x52,0x50,0x2e,
- 0x8e,0x1e,0x22,0xf8,0xcd,0x16,0xfe,0x06,0x2a,0x00,0x80,0x3e,
- 0x2a,0x00,0x12,0x72,0x39,0xc6,0x06,0x2a,0x00,0x00,0xfe,0x06,
- 0x29,0x00,0x80,0x3e,0x29,0x00,0x3c,0x72,0x29,0xc6,0x06,0x29,
- 0x00,0x00,0xfe,0x06,0x28,0x00,0x80,0x3e,0x28,0x00,0x3c,0x72,
- 0x19,0xc6,0x06,0x28,0x00,0x00,0xfe,0x06,0x27,0x00,0x80,0x3e,
- 0x27,0x00,0x18,0x72,0x09,0xc6,0x06,0x27,0x00,0x00,0xff,0x06,
- 0x25,0x00,0xba,0x22,0xff,0xb8,0x00,0x80,0xef,0x58,0x5a,0x1f,
- 0xcf,0x60,0x1e,0x06,0xfc,0x2e,0x8e,0x06,0x22,0xf8,0x2e,0x8e,
- 0x1e,0x22,0xf8,0x8d,0x36,0x40,0x00,0xad,0x3c,0x3f,0x7f,0x22,
- 0x3c,0x1f,0x7f,0x22,0x32,0xe4,0xd1,0xe0,0x3d,0x16,0x00,0x90,
- 0x73,0x14,0xbb,0x56,0xf9,0x03,0xd8,0x2e,0xff,0x17,0x8d,0x36,
- 0x40,0x00,0xb0,0x00,0x89,0x04,0x07,0x1f,0x61,0xcf,0xb4,0x80,
- 0xeb,0xf0,0xcd,0x15,0xeb,0xec,0x6c,0xf9,0x79,0xf9,0xb9,0xf9,
- 0xd3,0xf9,0xd8,0xf9,0xe1,0xf9,0xe9,0xf9,0xf2,0xf9,0xfa,0xf9,
- 0xfd,0xf9,0x2a,0xfa,0xe4,0x00,0x24,0xf7,0xe6,0x00,0x0c,0x08,
- 0xe6,0x00,0xb4,0x00,0xc3,0x1e,0xad,0x8b,0xd8,0xad,0x8e,0xdb,
- 0x8b,0xf0,0x33,0xdb,0x8b,0x07,0x3d,0x4f,0x53,0x75,0x2a,0x8a,
- 0x47,0x02,0x32,0xe4,0x86,0xc4,0x8b,0xc8,0x32,0xc0,0x02,0x07,
- 0x43,0xe2,0xfb,0x0a,0xc0,0x75,0x16,0x8c,0xd9,0x1f,0x89,0x0e,
- 0x2e,0x00,0x89,0x36,0x2c,0x00,0x8d,0x1e,0x02,0x00,0xc7,0x07,
- 0x45,0x4d,0x32,0xe4,0xc3,0x1f,0xb4,0x80,0xc3,0xad,0x8b,0xd8,
- 0xad,0x8b,0xd0,0xad,0x8e,0xc0,0xad,0x8b,0xf8,0xad,0x8b,0xc8,
- 0x8b,0xf2,0x1e,0x8e,0xdb,0xf3,0xa4,0x1f,0x32,0xe4,0xc3,0xea,
- 0xf0,0xff,0x00,0xf0,0xad,0x8b,0xd0,0xec,0x88,0x04,0x32,0xe4,
- 0xc3,0xad,0x8b,0xd0,0xac,0xee,0x32,0xe4,0xc3,0xad,0x8b,0xd0,
- 0xed,0x89,0x04,0x32,0xe4,0xc3,0xad,0x8b,0xd0,0xad,0xef,0x32,
- 0xe4,0xc3,0xb4,0x80,0xc3,0xac,0x3c,0x12,0x7f,0x25,0xfe,0xc8,
- 0x32,0xe4,0xd1,0xe0,0x8d,0x1e,0x66,0xf8,0x03,0xd8,0x2e,0x8b,
- 0x17,0xec,0xac,0x3c,0x0f,0x7f,0x10,0x3c,0x00,0x74,0x03,0xee,
- 0x90,0x90,0xec,0x8b,0xfe,0x1e,0x07,0xaa,0x32,0xe4,0xc3,0xb4,
- 0x80,0xc3,0xac,0x3c,0x12,0x7f,0x1f,0xfe,0xc8,0x32,0xe4,0xd1,
- 0xe0,0x8d,0x1e,0x66,0xf8,0x03,0xd8,0x2e,0x8b,0x17,0xec,0xac,
- 0x3c,0x0f,0x7f,0x0a,0x3c,0x00,0x74,0x01,0xee,0xac,0xee,0x32,
- 0xe4,0xc3,0xb4,0x80,0xc3,0xfc,0x8e,0xc0,0xb8,0xff,0xff,0x8b,
- 0xcb,0x33,0xff,0xf3,0xab,0x8b,0xcb,0x33,0xff,0xf3,0xaf,0xe3,
- 0x01,0xc3,0x8b,0xcb,0xbf,0x00,0x00,0x26,0x89,0x3d,0x83,0xc7,
- 0x02,0xe2,0xf8,0xbe,0x00,0x00,0x8b,0xcb,0x26,0x8b,0x3c,0x3b,
- 0xfe,0x74,0x01,0xc3,0x83,0xc6,0x02,0x83,0xc7,0x02,0xe2,0xf0,
- 0x33,0xc0,0x8b,0xcb,0x33,0xff,0xf3,0xab,0x8b,0xcb,0x33,0xff,
- 0xf3,0xaf,0xc3,0x32,0xc0,0x26,0x80,0x3e,0x23,0x00,0x00,0x74,
- 0x02,0x0c,0x01,0x26,0xf7,0x06,0x20,0x00,0x0f,0x00,0x74,0x02,
- 0x0c,0x02,0x26,0xf7,0x06,0x20,0x00,0xf0,0x00,0x74,0x02,0x0c,
- 0x04,0x26,0xf7,0x06,0x20,0x00,0x00,0xff,0x74,0x02,0x0c,0x08,
- 0x26,0xa2,0x24,0x00,0xb8,0x00,0x40,0xba,0x5e,0xff,0xef,0xba,
- 0x66,0xff,0xef,0xba,0x52,0xff,0xb8,0x63,0x0e,0xef,0xba,0x56,
- 0xff,0xb8,0x05,0xe0,0xef,0xba,0x28,0xff,0xb8,0xfc,0x00,0xef,
- 0xb8,0x00,0x02,0x26,0xa3,0x2e,0x00,0xb8,0x04,0x00,0x26,0xa3,
- 0x2c,0x00,0xb0,0xc3,0xe6,0x08,0x8a,0xd8,0xe4,0x08,0x3a,0xc3,
- 0x75,0x06,0x26,0xc6,0x06,0xb4,0x00,0x01,0xb0,0x00,0xe6,0x00,
- 0xfc,0x8d,0x3e,0x00,0x00,0xb8,0x47,0x44,0xab,0xb8,0xff,0xff,
- 0xab,0xab,0xab,0xb8,0x42,0x49,0xab,0xb8,0x4f,0x53,0xab,0xb8,
- 0x58,0x69,0x26,0x80,0x3e,0x10,0x00,0x04,0x74,0x0e,0xb8,0x58,
- 0x65,0x26,0x80,0x3e,0x10,0x00,0x03,0x74,0x03,0xb8,0x58,0x74,
- 0xab,0x8d,0x36,0xfe,0xff,0x8a,0x04,0x8d,0x36,0xff,0xff,0x8a,
- 0x24,0xab,0xfb,0x26,0x81,0x0e,0x12,0x00,0x00,0x08,0x06,0x1f,
- 0xa1,0x00,0x00,0x8b,0x1e,0x02,0x00,0x3d,0x44,0x47,0x75,0x0b,
- 0x26,0x81,0x0e,0x12,0x00,0x00,0x10,0xff,0x2e,0x2c,0x00,0x81,
- 0xfb,0x45,0x4d,0x75,0xe3,0x26,0x81,0x0e,0x12,0x00,0x00,0x20,
- 0xff,0x2e,0x2c,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
- 0xff,0xff,0xff,0xff,0xfa,0xba,0xa8,0xff,0xb8,0xba,0x81,0xef,
- 0xba,0xa4,0xff,0xb8,0x3a,0x00,0xef,0x90,0xe4,0x00,0xa8,0x60,
- 0x75,0x0c,0x24,0x06,0x74,0x14,0x3c,0x02,0x74,0x1c,0x3c,0x04,
- 0x74,0x24,0xbb,0x38,0xc0,0xbe,0xf8,0x81,0xbf,0xba,0xa0,0xeb,
- 0x22,0x90,0xbb,0x38,0xf0,0xbe,0xf8,0x41,0xbf,0xba,0x81,0xeb,
- 0x16,0x90,0xbb,0x38,0xf0,0xbe,0xf8,0xe1,0xbf,0xba,0x88,0xeb,
- 0x0a,0x90,0xbb,0x38,0xc0,0xbe,0xf8,0x41,0xbf,0xba,0x81,0xba,
- 0xa0,0xff,0x8b,0xc3,0xef,0xba,0xa2,0xff,0xb8,0xf8,0x0f,0xef,
- 0xba,0xa6,0xff,0x8b,0xc6,0xef,0xba,0xa8,0xff,0x8b,0xc7,0xef,
- 0x8c,0xc8,0x8e,0xd8,0xe4,0x00,0x24,0x06,0x74,0x17,0xbb,0x00,
- 0x80,0xbd,0xc0,0xe0,0x3c,0x02,0x74,0x5a,0xbd,0xc0,0xc0,0x3c,
- 0x04,0x74,0x53,0xbd,0xc0,0x80,0xeb,0x4e,0x90,0xb9,0x08,0x00,
- 0xb8,0x00,0x80,0x8e,0xc0,0x26,0xa3,0x00,0x00,0x05,0x00,0x10,
- 0xe2,0xf5,0xbd,0xc0,0xf0,0xbb,0x00,0x7c,0xb8,0x00,0xe0,0x8e,
- 0xc0,0x26,0x8b,0x0e,0x00,0x00,0x3b,0xc8,0x75,0x28,0xbb,0x00,
- 0x80,0xbd,0xc0,0xe0,0xb8,0x00,0xc0,0x8e,0xc0,0x26,0x8b,0x0e,
- 0x00,0x00,0x3b,0xc8,0x75,0x14,0xbd,0xc0,0xc0,0xb8,0x00,0x80,
- 0x8e,0xc0,0x26,0x8b,0x0e,0x00,0x00,0x3b,0xc8,0x75,0x03,0xbd,
- 0xc0,0x80,0x8c,0xc8,0x8e,0xd0,0xbc,0xed,0xfc,0x8b,0xc5,0x25,
- 0x00,0xf0,0xe9,0x6c,0xfd,0xb4,0x00,0x74,0x06,0xb4,0xff,0xeb,
- 0x02,0xe5,0xfc,0x8e,0xc5,0x2e,0x89,0x2e,0x22,0xf8,0xe4,0x00,
- 0x24,0x16,0x26,0xa2,0x11,0x00,0x26,0x83,0x0e,0x12,0x00,0x01,
- 0x80,0xfc,0x00,0x74,0x06,0x26,0x83,0x0e,0x14,0x00,0x01,0x26,
- 0xc7,0x06,0x18,0x00,0x40,0x00,0x26,0xc6,0x06,0x10,0x00,0x03,
- 0xa8,0x10,0x74,0x06,0x26,0xc6,0x06,0x10,0x00,0x04,0xb8,0x00,
- 0x00,0x8e,0xc0,0xb8,0xaa,0x55,0x26,0xa3,0x00,0x00,0x26,0xc7,
- 0x06,0x02,0x00,0x00,0x00,0x26,0xc7,0x06,0x04,0x00,0x00,0x00,
- 0x8b,0xcd,0x81,0xe1,0x00,0xf0,0x8e,0xc1,0x26,0x8b,0x1e,0x00,
- 0x00,0x3b,0xc3,0x75,0x13,0x8e,0xc5,0x26,0xc6,0x06,0x10,0x00,
- 0x05,0xb8,0x40,0x00,0x8e,0xd0,0xbc,0x00,0x04,0xe9,0x99,0x00,
- 0x8c,0xc8,0x8e,0xd0,0xbc,0x7c,0xfd,0xb8,0x00,0x00,0xbb,0x00,
- 0x20,0xe9,0xdd,0xfc,0xb4,0x00,0x74,0x06,0xb4,0xff,0xeb,0x02,
- 0x74,0xfd,0x8e,0xc5,0x80,0xfc,0x00,0x74,0x08,0x26,0x83,0x0e,
- 0x14,0x00,0x02,0xeb,0x0d,0x26,0xc7,0x06,0x16,0x00,0x10,0x00,
- 0x26,0x83,0x0e,0x12,0x00,0x02,0xb8,0x40,0x00,0x8e,0xd0,0xbc,
- 0x00,0x04,0xe4,0x00,0xa8,0x60,0x75,0x07,0xba,0xa2,0xff,0xb8,
- 0xfc,0x0f,0xef,0xb8,0x00,0x04,0x8e,0xc0,0xb8,0xaa,0x55,0x26,
- 0xa3,0x00,0x00,0x26,0xc7,0x06,0x02,0x00,0x00,0x00,0x26,0xc7,
- 0x06,0x04,0x00,0x00,0x00,0xb9,0x00,0x00,0x8e,0xc1,0x26,0x8b,
- 0x1e,0x00,0x00,0x3b,0xc3,0x75,0x02,0xeb,0x24,0x8e,0xc5,0x26,
- 0x83,0x0e,0x12,0x00,0x04,0xb8,0x00,0x04,0xbb,0x00,0x60,0x06,
- 0xe8,0x66,0xfc,0x07,0x75,0x09,0x26,0xc7,0x06,0x16,0x00,0x40,
- 0x00,0xeb,0x06,0x26,0x83,0x0e,0x14,0x00,0x04,0x8e,0xc5,0x8c,
- 0xc0,0x3d,0xc0,0xf0,0x75,0x03,0xe9,0x9f,0x00,0x3d,0xc0,0x80,
- 0x74,0x62,0x3d,0xc0,0xc0,0x74,0x23,0x26,0x83,0x0e,0x12,0x00,
- 0x08,0xb8,0x00,0xf0,0xbb,0x00,0x7c,0x06,0xe8,0x2e,0xfc,0x07,
- 0x75,0x08,0x26,0x83,0x06,0x18,0x00,0x40,0xeb,0x06,0x26,0x83,
- 0x0e,0x14,0x00,0x08,0xeb,0x72,0xb9,0x03,0x00,0xb8,0x00,0xd0,
- 0xba,0x08,0x00,0xbb,0x00,0x80,0x3d,0x00,0xf0,0x75,0x03,0xbb,
- 0x00,0x7c,0x26,0x09,0x16,0x12,0x00,0x06,0x50,0x51,0xe8,0xfc,
- 0xfb,0x59,0x58,0x07,0x75,0x0f,0x26,0x83,0x06,0x18,0x00,0x40,
- 0xd1,0xe2,0x05,0x00,0x10,0xe2,0xd8,0xeb,0x05,0x26,0x09,0x16,
- 0x14,0x00,0xeb,0x38,0xb9,0x07,0x00,0xb8,0x00,0x90,0xba,0x08,
- 0x00,0xbb,0x00,0x80,0x3d,0x00,0xf0,0x75,0x03,0xbb,0x00,0x7c,
- 0x26,0x09,0x16,0x12,0x00,0x06,0x50,0x51,0xe8,0xc2,0xfb,0x59,
- 0x58,0x07,0x75,0x0f,0x26,0x83,0x06,0x18,0x00,0x40,0xd1,0xe2,
- 0x05,0x00,0x10,0xe2,0xd8,0xeb,0x05,0x26,0x09,0x16,0x14,0x00,
- 0x26,0xa1,0x18,0x00,0x2d,0x10,0x00,0x26,0xa3,0x1a,0x00,0x06,
- 0xfc,0x33,0xff,0x8e,0xc7,0xb9,0x00,0x02,0xb8,0x00,0xf0,0xf3,
- 0xab,0x33,0xff,0xbe,0x24,0xf8,0xb9,0x20,0x00,0xa5,0x47,0x47,
- 0xe2,0xfb,0xbe,0x64,0xf8,0xb9,0xe0,0x00,0x8b,0x1c,0x26,0x89,
- 0x1d,0x83,0xc7,0x04,0xe2,0xf8,0x07,0xba,0x28,0xff,0xb8,0xfd,
- 0x00,0xef,0xba,0x32,0xff,0xb8,0x0d,0x00,0xef,0xba,0x34,0xff,
- 0xb8,0x0f,0x00,0xef,0xba,0x36,0xff,0xb8,0x0e,0x00,0xef,0xba,
- 0x38,0xff,0xb8,0x19,0x00,0xef,0xba,0x3a,0xff,0xb8,0x18,0x00,
- 0xef,0xba,0x3c,0xff,0xb8,0x0b,0x00,0xef,0xba,0x3e,0xff,0xb8,
- 0x1a,0x00,0xef,0x8d,0x3e,0x90,0x00,0x8d,0x36,0x66,0xf8,0xb9,
- 0x10,0x00,0xf3,0xa5,0x8d,0x3e,0xb0,0x00,0x8d,0x36,0x86,0xf8,
- 0xb9,0x02,0x00,0xf3,0xa5,0xb9,0x10,0x00,0x8d,0x36,0x90,0x00,
- 0x83,0xc6,0x1e,0x26,0x8b,0x14,0xb3,0x10,0x32,0xc0,0xec,0xb0,
- 0x0c,0xee,0x8a,0xc3,0x8a,0xc3,0xee,0x83,0xee,0x02,0x26,0x8b,
- 0x14,0xfe,0xcb,0xe2,0xeb,0xb9,0x10,0x00,0x8d,0x36,0x90,0x00,
- 0x26,0x8b,0x14,0xb3,0x01,0xbf,0x00,0x80,0xb0,0x0c,0xee,0xf6,
- 0xe8,0xec,0x3a,0xc3,0x75,0x0e,0xd1,0xc7,0x26,0x09,0x3e,0x20,
- 0x00,0x26,0xfe,0x06,0x22,0x00,0xeb,0x07,0x33,0xc0,0x26,0x89,
- 0x04,0xd1,0xc7,0x83,0xc6,0x02,0x26,0x8b,0x14,0xfe,0xc3,0xe2,
- 0xd7,0x26,0xc6,0x06,0x23,0x00,0x01,0x8d,0x36,0xb0,0x00,0x26,
- 0x8b,0x14,0x32,0xc0,0xee,0xb0,0x0c,0xee,0xb0,0x5a,0xee,0xb0,
- 0x0c,0xee,0xf6,0xe8,0xec,0x3c,0x5a,0x74,0x14,0x26,0xc7,0x06,
- 0xb0,0x00,0x00,0x00,0x26,0xc7,0x06,0xb2,0x00,0x00,0x00,0x26,
- 0xc6,0x06,0x23,0x00,0x00,0xe9,0xd3,0xfa,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0xea,0x00,0xfc,0x00,0xf0,0x4d,0x2f,0x50,
- 0x43,0x2f,0x58,0x2a,0x39,0x34,0x34,0x31
-};
-
-
diff --git a/drivers/char/digi_fep.h b/drivers/char/digi_fep.h
deleted file mode 100644
index 7a84759e812f3..0000000000000
--- a/drivers/char/digi_fep.h
+++ /dev/null
@@ -1,517 +0,0 @@
-/* DigiBoard PCXX Bios */
-
-static unsigned char pcxx_cook[] __initdata = {
- 0x4f,0x53,0x18,0x80,0xe9,0xbf,0x15,0x00,0x40,0x28,0x23,0x29,
- 0x46,0x45,0x50,0x4f,0x53,0x20,0x37,0x2e,0x30,0x38,0x20,0x34,
- 0x2f,0x32,0x30,0x2f,0x39,0x35,0x00,0x40,0x28,0x23,0x29,0x28,
- 0x43,0x29,0x43,0x6f,0x70,0x79,0x72,0x69,0x67,0x68,0x74,0x20,
- 0x31,0x39,0x38,0x39,0x2d,0x31,0x39,0x39,0x35,0x20,0x44,0x69,
- 0x67,0x69,0x42,0x6f,0x61,0x72,0x64,0x20,0x49,0x6e,0x63,0x2e,
- 0x00,0xcb,0x0c,0xcb,0x0c,0xe2,0x0c,0xcb,0x0c,0xcb,0x0c,0xcb,
- 0x0c,0xcb,0x0c,0xcb,0x0c,0x57,0x0c,0xcb,0x0c,0xcb,0x0c,0xcb,
- 0x0c,0x53,0x0b,0xcb,0x0c,0xcb,0x0c,0x42,0x0b,0xcb,0x0c,0xcb,
- 0x0c,0x12,0x0d,0xcb,0x0c,0xcb,0x0c,0xcb,0x0c,0xcb,0x0c,0xcb,
- 0x0c,0xcb,0x0c,0xcb,0x0c,0xcb,0x0c,0xcb,0x0c,0xcb,0x0c,0xcb,
- 0x0c,0xcb,0x0c,0xcb,0x0c,0x00,0x10,0x80,0x10,0x00,0x11,0x80,
- 0x11,0x00,0x12,0x80,0x12,0x00,0x13,0x80,0x13,0x00,0x14,0x80,
- 0x14,0x00,0x15,0x80,0x15,0x00,0x16,0x80,0x16,0x00,0x17,0x80,
- 0x17,0x78,0x0b,0xb9,0x0b,0x50,0x0c,0xb9,0x0b,0x8d,0x0b,0x8d,
- 0x0b,0x8d,0x0b,0x8d,0x0b,0xc0,0x0b,0xc0,0x0b,0xc0,0x0b,0xc0,
- 0x0b,0x8d,0x0b,0x8d,0x0b,0x8d,0x0b,0x8d,0x0b,0x50,0x0c,0xb9,
- 0x0b,0x50,0x0c,0xb9,0x0b,0x8d,0x0b,0x8d,0x0b,0x8d,0x0b,0x8d,
- 0x0b,0xc0,0x0b,0xc0,0x0b,0xc0,0x0b,0xc0,0x0b,0x8d,0x0b,0x8d,
- 0x0b,0x8d,0x0b,0x8d,0x0b,0x94,0x0b,0x94,0x0b,0x94,0x0b,0x94,
- 0x0b,0x94,0x0b,0x94,0x0b,0x94,0x0b,0x94,0x0b,0x94,0x0b,0x94,
- 0x0b,0x94,0x0b,0x94,0x0b,0x94,0x0b,0x94,0x0b,0x94,0x0b,0x94,
- 0x0b,0x94,0x0b,0x94,0x0b,0x94,0x0b,0x94,0x0b,0x94,0x0b,0x94,
- 0x0b,0x94,0x0b,0x94,0x0b,0x94,0x0b,0x94,0x0b,0x94,0x0b,0x94,
- 0x0b,0x94,0x0b,0x94,0x0b,0x94,0x0b,0x94,0x0b,0x16,0x00,0xfe,
- 0x11,0xfe,0x0b,0x2c,0x08,0xb5,0x06,0xfe,0x05,0x7e,0x04,0xfe,
- 0x02,0x7e,0x01,0xbe,0x00,0x7e,0x00,0x5e,0x00,0x2e,0x00,0x16,
- 0x00,0x0a,0x00,0x04,0x00,0x16,0x00,0x02,0x00,0x01,0x00,0x00,
- 0x00,0x0e,0x00,0x06,0x00,0x7e,0x04,0xfe,0x02,0x7e,0x01,0xbe,
- 0x00,0x7e,0x00,0x5e,0x00,0x2e,0x00,0x16,0x00,0x0a,0x00,0x04,
- 0x00,0x18,0x00,0x86,0x13,0x03,0x0d,0xdf,0x08,0x41,0x07,0x81,
- 0x06,0xe0,0x04,0x3f,0x03,0x9f,0x01,0xce,0x00,0x89,0x00,0x66,
- 0x00,0x32,0x00,0x18,0x00,0x0b,0x00,0x0b,0x00,0x18,0x00,0x0b,
- 0x00,0x0b,0x00,0x0b,0x00,0x41,0x07,0x81,0x06,0xe0,0x04,0x3f,
- 0x03,0x9f,0x01,0xce,0x00,0x89,0x00,0x66,0x00,0x32,0x00,0x18,
- 0x00,0x0b,0x00,0x0b,0x00,0x00,0x80,0x40,0xc0,0x1f,0x3f,0x7f,
- 0xff,0x00,0x04,0x02,0x06,0x08,0x0c,0x0a,0x0e,0x00,0x04,0x02,
- 0x06,0x08,0x0c,0x0a,0x0e,0xa0,0x08,0xa0,0x08,0xa0,0x08,0xa0,
- 0x08,0xa0,0x08,0xa0,0x08,0xa0,0x08,0xa0,0x08,0x1e,0x06,0x3e,
- 0x06,0xef,0x06,0xf8,0x05,0x0e,0x06,0x55,0x07,0xa0,0x08,0xa0,
- 0x08,0xa0,0x08,0xa0,0x08,0xa0,0x08,0xa0,0x08,0xa0,0x08,0xa0,
- 0x08,0xa0,0x08,0xa0,0x08,0xa0,0x08,0xa0,0x08,0xa0,0x08,0xa0,
- 0x08,0xa0,0x08,0xa0,0x08,0xa0,0x08,0xa0,0x08,0x9d,0x08,0x9d,
- 0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,
- 0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,
- 0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,
- 0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,
- 0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,
- 0x08,0x9d,0x08,0xa1,0x05,0xa1,0x05,0xa1,0x05,0xa1,0x05,0xa1,
- 0x05,0xa1,0x05,0xa1,0x05,0xa1,0x05,0xa1,0x05,0xa1,0x05,0xa1,
- 0x05,0xa1,0x05,0xa1,0x05,0xa1,0x05,0xa1,0x05,0xa1,0x05,0xa1,
- 0x05,0xa1,0x05,0xa1,0x05,0xa1,0x05,0xa1,0x05,0xa1,0x05,0xa1,
- 0x05,0xa1,0x05,0xa1,0x05,0xa1,0x05,0x9d,0x08,0x9d,0x08,0x9d,
- 0x08,0x9d,0x08,0x9d,0x08,0x5b,0x05,0xea,0x05,0xea,0x05,0xea,
- 0x05,0xea,0x05,0xea,0x05,0xea,0x05,0xea,0x05,0xea,0x05,0xea,
- 0x05,0xea,0x05,0xea,0x05,0xea,0x05,0xea,0x05,0xea,0x05,0xea,
- 0x05,0xea,0x05,0xea,0x05,0xea,0x05,0xea,0x05,0xea,0x05,0xea,
- 0x05,0xea,0x05,0xea,0x05,0xea,0x05,0xea,0x05,0xea,0x05,0x69,
- 0x05,0x77,0x05,0x85,0x05,0x93,0x05,0xa0,0x08,0xa0,0x08,0xa0,
- 0x08,0xa0,0x08,0xa0,0x08,0xa0,0x08,0xa0,0x08,0xa0,0x08,0xa0,
- 0x08,0xa0,0x08,0xa0,0x08,0xa0,0x08,0xa0,0x08,0xa0,0x08,0xa0,
- 0x08,0xa0,0x08,0xa0,0x08,0xa0,0x08,0xa0,0x08,0xa0,0x08,0xa0,
- 0x08,0xa0,0x08,0xa0,0x08,0xa0,0x08,0xa0,0x08,0xa0,0x08,0xa0,
- 0x08,0xa0,0x08,0xa0,0x08,0xa0,0x08,0xa0,0x08,0xa0,0x08,0xa0,
- 0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,
- 0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,
- 0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,
- 0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,
- 0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,
- 0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,
- 0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,
- 0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,
- 0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,
- 0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,
- 0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,
- 0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,
- 0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,
- 0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,
- 0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,
- 0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,0x08,0x9d,
- 0x08,0x00,0x00,0xfa,0x8a,0x5c,0x50,0xf6,0xc3,0x0e,0x75,0x3c,
- 0xf6,0xc3,0x40,0x75,0x16,0xf6,0xc3,0x10,0x74,0x26,0xf6,0xc3,
- 0x01,0x75,0x13,0xf6,0xc3,0x20,0x75,0x15,0xc7,0x04,0xb6,0x04,
- 0xe9,0xcf,0x00,0x8b,0x44,0x02,0x89,0x04,0xff,0xe0,0xc7,0x04,
- 0x03,0x05,0xe9,0x0e,0x01,0xc7,0x04,0x66,0x08,0xe9,0x6a,0x04,
- 0xf6,0xc3,0x20,0x74,0x1a,0xc7,0x04,0xb3,0x08,0xe9,0xab,0x04,
- 0x8b,0x54,0x20,0xec,0x8a,0xc8,0xf6,0xc3,0x02,0x75,0x42,0xf6,
- 0xc3,0x08,0x75,0x0e,0xeb,0x69,0x90,0xc7,0x04,0x20,0x04,0xfb,
- 0x81,0xc6,0x80,0x00,0xff,0x24,0xf6,0xc1,0x04,0x74,0x27,0x80,
- 0x64,0x50,0xf7,0xf6,0x44,0x51,0x02,0x74,0x13,0xf6,0x44,0x29,
- 0x10,0x74,0x0d,0x8a,0x44,0x5d,0x83,0xc2,0x02,0xee,0x83,0xea,
- 0x02,0xe9,0x49,0x04,0x8a,0x44,0x5c,0x83,0xc2,0x02,0xee,0x83,
- 0xea,0x02,0xe9,0x3c,0x04,0xf6,0x44,0x50,0x04,0x75,0x28,0x83,
- 0x7c,0x24,0xff,0x74,0x1f,0xa1,0x00,0x0e,0x2b,0x44,0x26,0x3d,
- 0x64,0x00,0x77,0x14,0xb0,0x05,0xee,0x8a,0x44,0x75,0x24,0xef,
- 0x88,0x44,0x75,0xee,0x80,0x64,0x50,0xfd,0x80,0x64,0x4b,0xfd,
- 0xe9,0x0e,0x04,0xb0,0x01,0xee,0x90,0x90,0x90,0xec,0xa8,0x01,
- 0x74,0x25,0xb0,0x05,0xee,0x8a,0x44,0x75,0x0c,0x10,0x88,0x44,
- 0x75,0xee,0xa1,0x00,0x0e,0x03,0x44,0x24,0x89,0x44,0x26,0x80,
- 0x64,0x50,0xfb,0x80,0x64,0x4b,0xfb,0x80,0x4c,0x50,0x02,0x80,
- 0x4c,0x4b,0x02,0xe9,0xdb,0x03,0xfa,0x8b,0x54,0x20,0xec,0x8a,
- 0xc8,0x22,0x44,0x52,0x3a,0x44,0x53,0x75,0x19,0x8b,0x7c,0x0c,
- 0x3b,0x7c,0x0a,0x74,0x18,0x8e,0x44,0x08,0x26,0x8a,0x05,0x47,
- 0x23,0x7c,0x0e,0x89,0x7c,0x0c,0x83,0xc2,0x02,0xee,0xfb,0x81,
- 0xc6,0x80,0x00,0xff,0x24,0xb0,0x01,0xee,0x90,0x90,0x90,0xec,
- 0xa8,0x01,0x74,0x0c,0x80,0x64,0x50,0xef,0x80,0x64,0x4b,0xef,
- 0xc7,0x04,0xc3,0x03,0xfb,0x81,0xc6,0x80,0x00,0xff,0x24,0xfa,
- 0x8b,0x54,0x20,0xec,0x8a,0xc8,0x22,0x44,0x52,0x3a,0x44,0x53,
- 0x75,0x3a,0x8b,0x7c,0x0c,0x3b,0x7c,0x0a,0x74,0x1b,0x8e,0x44,
- 0x08,0x26,0x8a,0x05,0x47,0x23,0x7c,0x0e,0x89,0x7c,0x0c,0x8a,
- 0xd8,0x22,0x5c,0x62,0x32,0xff,0x03,0xdb,0x2e,0xff,0xa7,0xc1,
- 0x01,0xb0,0x01,0xee,0x90,0x90,0x90,0xec,0xa8,0x01,0x74,0x0c,
- 0x80,0x64,0x50,0xef,0x80,0x64,0x4b,0xef,0xc7,0x04,0xc3,0x03,
- 0xf6,0xc1,0x01,0x75,0x07,0xfb,0x81,0xc6,0x80,0x00,0xff,0x24,
- 0xe9,0x61,0x03,0xf6,0x44,0x2a,0x01,0x75,0x03,0xe9,0x39,0x03,
- 0xb0,0x27,0xeb,0x42,0x90,0xf6,0x44,0x2a,0x01,0x75,0x03,0xe9,
- 0x2b,0x03,0xb0,0x28,0xeb,0x34,0x90,0xf6,0x44,0x2a,0x01,0x75,
- 0x03,0xe9,0x1d,0x03,0xb0,0x21,0xeb,0x26,0x90,0xf6,0x44,0x2a,
- 0x01,0x75,0x03,0xe9,0x0f,0x03,0xb0,0x29,0xeb,0x18,0x90,0xf6,
- 0x44,0x2a,0x01,0x75,0x03,0xe9,0x01,0x03,0xb0,0x5e,0xeb,0x0a,
- 0x90,0xf6,0x44,0x2a,0x01,0x75,0x03,0xe9,0xf3,0x02,0x88,0x44,
- 0x61,0xb0,0x5c,0x83,0xc2,0x02,0xee,0x83,0xea,0x02,0x80,0x4c,
- 0x50,0x40,0xc7,0x04,0xc6,0x05,0xc7,0x44,0x02,0xc6,0x05,0xe9,
- 0xcb,0x02,0xfa,0x8b,0x54,0x20,0xec,0x8a,0xc8,0x22,0x44,0x52,
- 0x3a,0x44,0x53,0x75,0x12,0x80,0x64,0x50,0xbf,0xc7,0x04,0x03,
- 0x05,0x83,0x44,0x30,0x02,0x8a,0x44,0x61,0xe9,0xb9,0x02,0xe9,
- 0xa7,0x02,0xf6,0x44,0x2a,0x02,0x75,0x03,0xe9,0xaa,0x02,0x2c,
- 0x20,0xe9,0xa5,0x02,0x83,0xc2,0x02,0xee,0x83,0xea,0x02,0xf6,
- 0x44,0x2b,0x40,0x75,0x03,0xe9,0x89,0x02,0xb8,0x7f,0x00,0xe9,
- 0x9b,0x01,0x83,0xc2,0x02,0xee,0x83,0xea,0x02,0xf6,0x44,0x2b,
- 0x80,0x75,0xed,0xe9,0x73,0x02,0x83,0xc2,0x02,0xee,0x83,0xea,
- 0x02,0xf7,0x44,0x30,0xff,0xff,0x74,0x03,0xff,0x4c,0x30,0xf6,
- 0x44,0x2b,0x20,0x75,0x03,0xe9,0x59,0x02,0xb8,0x02,0x00,0xe9,
- 0x6b,0x01,0xb3,0x18,0x22,0x5c,0x2b,0x75,0x16,0x83,0xc2,0x02,
- 0xee,0x83,0xea,0x02,0x8b,0x44,0x30,0x05,0x08,0x00,0x25,0xf8,
- 0xff,0x89,0x44,0x30,0xe9,0x36,0x02,0x80,0xfb,0x18,0x75,0x57,
- 0xb0,0x20,0x83,0xc2,0x02,0xee,0x83,0xea,0x02,0x8b,0x44,0x30,
- 0x8b,0xd8,0x05,0x08,0x00,0x25,0xf8,0xff,0x89,0x44,0x30,0x2b,
- 0xc3,0x48,0x74,0x38,0x89,0x44,0x32,0x80,0x4c,0x50,0x40,0xc7,
- 0x44,0x02,0x8f,0x06,0xc7,0x04,0x8f,0x06,0xe9,0x02,0x02,0xfa,
- 0x8b,0x54,0x20,0xec,0x8a,0xc8,0x22,0x44,0x52,0x3a,0x44,0x53,
- 0x75,0x16,0xb0,0x20,0x83,0xc2,0x02,0xee,0x83,0xea,0x02,0xff,
- 0x4c,0x32,0x75,0x08,0x80,0x64,0x50,0xbf,0xc7,0x04,0x03,0x05,
- 0xe9,0xda,0x01,0x83,0xc2,0x02,0xee,0x83,0xea,0x02,0x80,0xfb,
- 0x08,0x75,0x18,0x8b,0x44,0x30,0x8b,0xd8,0x05,0x08,0x00,0x25,
- 0xf8,0xff,0x89,0x44,0x30,0x2b,0xc3,0x3d,0x05,0x00,0x7c,0xdc,
- 0xe9,0xce,0x00,0x8b,0x44,0x30,0x8b,0xd8,0x05,0x08,0x00,0x25,
- 0xf8,0xff,0x89,0x44,0x30,0xb8,0x02,0x00,0xe9,0xba,0x00,0xf6,
- 0x44,0x2a,0x20,0x75,0x43,0xf6,0x44,0x2a,0x04,0x74,0x42,0xf6,
- 0x44,0x2a,0x10,0x74,0x07,0xf7,0x44,0x30,0xff,0xff,0x74,0x30,
- 0xb0,0x0d,0x83,0xc2,0x02,0xee,0x83,0xea,0x02,0x80,0x4c,0x50,
- 0x40,0xc7,0x04,0x21,0x07,0xc7,0x44,0x02,0x21,0x07,0xe9,0x70,
- 0x01,0xfa,0x8b,0x54,0x20,0xec,0x8a,0xc8,0x22,0x44,0x52,0x3a,
- 0x44,0x53,0x75,0x1c,0x80,0x64,0x50,0xbf,0xc7,0x04,0x03,0x05,
- 0xb0,0x0a,0xeb,0x2b,0x90,0xb0,0x0a,0x83,0xc2,0x02,0xee,0x83,
- 0xea,0x02,0xf6,0x44,0x2b,0x01,0x75,0x03,0xe9,0x42,0x01,0xb8,
- 0x05,0x00,0xeb,0x55,0x90,0xf6,0x44,0x2a,0x08,0x75,0xe2,0xf6,
- 0x44,0x2a,0x10,0x74,0x06,0x83,0x7c,0x30,0x00,0x74,0x13,0x83,
- 0xc2,0x02,0xee,0x83,0xea,0x02,0xb3,0x06,0x22,0x5c,0x2b,0x75,
- 0x08,0xc7,0x44,0x30,0x00,0x00,0xe9,0x14,0x01,0x80,0xfb,0x02,
- 0x75,0x14,0x8b,0x44,0x30,0xc1,0xe8,0x04,0x05,0x03,0x00,0x3d,
- 0x06,0x00,0x72,0x14,0xb8,0x06,0x00,0xeb,0x0f,0x90,0x80,0xfb,
- 0x04,0x75,0x06,0xb8,0x05,0x00,0xeb,0x04,0x90,0xb8,0x09,0x00,
- 0xc7,0x44,0x30,0x00,0x00,0xf6,0x44,0x2a,0x40,0x74,0x45,0x3d,
- 0x20,0x00,0x77,0x40,0xbb,0x01,0x00,0x3d,0x03,0x00,0x7e,0x03,
- 0xbb,0x02,0x00,0x89,0x5c,0x32,0x80,0x4c,0x50,0x40,0xc7,0x44,
- 0x02,0xd2,0x07,0xc7,0x04,0xd2,0x07,0xe9,0xbf,0x00,0xfa,0x8b,
- 0x54,0x20,0xec,0x8a,0xc8,0x22,0x44,0x52,0x3a,0x44,0x53,0x75,
- 0x10,0x8a,0x44,0x60,0x83,0xc2,0x02,0xee,0x83,0xea,0x02,0x83,
- 0x6c,0x32,0x01,0x7e,0x50,0xe9,0x9d,0x00,0x05,0x06,0x00,0x03,
- 0xc0,0x89,0x44,0x32,0x80,0x4c,0x50,0x40,0xc7,0x44,0x02,0x0c,
- 0x08,0xc7,0x04,0x0c,0x08,0xe9,0x85,0x00,0xfa,0x8b,0x54,0x20,
- 0xec,0x8a,0xc8,0xb0,0x01,0xee,0x90,0x90,0x90,0xec,0xa8,0x01,
- 0x74,0x0f,0xa1,0x00,0x0e,0x01,0x44,0x32,0xc7,0x44,0x02,0x30,
- 0x08,0xc7,0x04,0x30,0x08,0xeb,0x62,0x90,0x8b,0x54,0x20,0xec,
- 0x8a,0xc8,0xa1,0x00,0x0e,0x2b,0x44,0x32,0x3d,0xe8,0x03,0x77,
- 0xec,0x80,0x64,0x50,0xbf,0xc7,0x04,0x03,0x05,0xeb,0x46,0x90,
- 0xb0,0x01,0xee,0x90,0x90,0x90,0xec,0xa8,0x01,0x74,0x3a,0x80,
- 0x64,0x50,0xef,0x80,0x64,0x4b,0xef,0xc7,0x04,0xb3,0x08,0xeb,
- 0x2c,0x90,0xfa,0x8b,0x54,0x20,0xec,0x8a,0xc8,0x22,0x44,0x52,
- 0x3a,0x44,0x53,0x75,0x1c,0x8b,0x7c,0x0c,0x3b,0x7c,0x0a,0x74,
- 0xcf,0x8e,0x44,0x08,0x26,0x8a,0x05,0x47,0x23,0x7c,0x0e,0x89,
- 0x7c,0x0c,0x83,0xc2,0x02,0xee,0x83,0xea,0x02,0xf6,0xc1,0x01,
- 0x75,0x26,0xfb,0x81,0xc6,0x80,0x00,0xff,0x24,0xff,0x44,0x30,
- 0x83,0xc2,0x02,0xee,0x83,0xea,0x02,0xf6,0xc1,0x01,0x75,0x10,
- 0xfb,0x81,0xc6,0x80,0x00,0xff,0x24,0xfa,0x8b,0x54,0x20,0xec,
- 0xa8,0x01,0x74,0xda,0xc6,0x44,0x49,0x02,0x8b,0x7c,0x12,0x8e,
- 0x44,0x10,0xb0,0x01,0xee,0x90,0x90,0x90,0xec,0x8a,0xe0,0x90,
- 0xb0,0x30,0xee,0x83,0xc2,0x02,0x90,0xec,0x83,0xea,0x02,0x23,
- 0x44,0x34,0xff,0x64,0x06,0xb3,0x1c,0x22,0x5c,0x51,0x75,0x1a,
- 0xf6,0x44,0x29,0x04,0x74,0x21,0xf6,0x44,0x29,0x20,0x75,0x2b,
- 0x80,0x7c,0x5e,0x00,0x75,0x1d,0xc7,0x44,0x06,0x58,0x0a,0xe9,
- 0x56,0x01,0xf6,0xc3,0x10,0x75,0x2e,0xf6,0xc3,0x04,0x75,0x74,
- 0xeb,0x6b,0x90,0xc7,0x44,0x06,0x62,0x0a,0xe9,0x4b,0x01,0xc7,
- 0x44,0x06,0x53,0x0a,0xe9,0x34,0x01,0x80,0x7c,0x5e,0x00,0x75,
- 0x08,0xc7,0x44,0x06,0xca,0x09,0xe9,0x9d,0x00,0xc7,0x44,0x06,
- 0xc5,0x09,0xe9,0x90,0x00,0x0a,0xc0,0x74,0x2a,0xfe,0x4c,0x63,
- 0x74,0x1a,0x80,0xe3,0xef,0x75,0xc4,0xf6,0x44,0x29,0x04,0x74,
- 0x21,0xf6,0x44,0x29,0x20,0x75,0x21,0x80,0x7c,0x5e,0x00,0x75,
- 0x18,0xe9,0x00,0x01,0x80,0x64,0x51,0xef,0x80,0xe3,0xef,0x75,
- 0xa6,0xeb,0x85,0x80,0x64,0x51,0xef,0xe9,0x06,0x01,0xe9,0xf5,
- 0x00,0xe9,0xe3,0x00,0x80,0x7c,0x5e,0x00,0x75,0x4f,0xeb,0x52,
- 0x90,0x80,0x64,0x51,0xf7,0xe9,0xe2,0x00,0x80,0x64,0x53,0x3f,
- 0x80,0x64,0x54,0xfe,0x80,0x4c,0x58,0x01,0x80,0x64,0x51,0xfb,
- 0xf6,0x44,0x29,0x40,0x75,0x2c,0x3a,0x44,0x5d,0x74,0x27,0x3a,
- 0x44,0x5c,0x74,0x22,0xf6,0x44,0x29,0x20,0x74,0x0a,0x3a,0x44,
- 0x5a,0x74,0x17,0x3a,0x44,0x5b,0x74,0x12,0xf6,0x44,0x5e,0xff,
- 0x74,0x09,0x3a,0x44,0x5e,0x75,0x04,0x80,0x4c,0x51,0x08,0xe9,
- 0xa0,0x00,0xe9,0xab,0x00,0x3a,0x44,0x5e,0x74,0x7d,0x3a,0x44,
- 0x5c,0x74,0x3d,0x3a,0x44,0x5d,0x74,0x55,0x3a,0x44,0x5a,0x74,
- 0x08,0x3a,0x44,0x5b,0x74,0x18,0xe9,0x81,0x00,0xf6,0x44,0x53,
- 0x40,0x74,0x07,0x80,0x64,0x53,0xbf,0xe9,0x82,0x00,0x3a,0x44,
- 0x5b,0x74,0x03,0xeb,0x7b,0x90,0x80,0x4c,0x53,0x40,0xf6,0x44,
- 0x29,0x08,0x74,0x70,0x80,0x4c,0x51,0x04,0xc7,0x44,0x06,0xe1,
- 0x08,0xeb,0x65,0x90,0xf6,0x44,0x53,0x80,0x74,0x0f,0x80,0x64,
- 0x53,0x7f,0x80,0x64,0x54,0xfe,0x80,0x4c,0x58,0x01,0xeb,0x50,
- 0x90,0x3a,0x44,0x5d,0x74,0x03,0xeb,0x48,0x90,0x80,0x4c,0x53,
- 0x80,0x80,0x4c,0x54,0x01,0x80,0x4c,0x58,0x01,0xf6,0x44,0x29,
- 0x08,0x74,0x35,0x80,0x4c,0x51,0x04,0xc7,0x44,0x06,0xe1,0x08,
- 0xeb,0x2a,0x90,0x80,0x4c,0x51,0x08,0xc7,0x44,0x06,0xe1,0x08,
- 0xeb,0x10,0x90,0x3a,0x44,0x5e,0x74,0xef,0x3a,0x44,0x5c,0x74,
- 0xaf,0x3a,0x44,0x5d,0x74,0xc7,0x3d,0xff,0x00,0x73,0x26,0xaa,
- 0x23,0x7c,0x16,0x3b,0x7c,0x14,0x74,0x4f,0xec,0xa8,0x01,0x74,
- 0x03,0xe9,0x4e,0xfe,0x89,0x7c,0x12,0x2b,0x7c,0x14,0x23,0x7c,
- 0x16,0x3b,0x7c,0x1c,0x73,0x46,0xfb,0x81,0xc6,0x80,0x00,0xff,
- 0x24,0x0a,0xe4,0x75,0x1e,0xb3,0x0c,0x22,0x5c,0x28,0x80,0xfb,
- 0x08,0x75,0xcc,0xaa,0x23,0x7c,0x16,0x3b,0x7c,0x14,0x74,0x1b,
- 0xaa,0x23,0x7c,0x16,0x3b,0x7c,0x14,0x74,0x12,0xeb,0xc1,0xf6,
- 0x44,0x28,0x04,0x75,0xbb,0xf6,0x44,0x28,0x08,0x75,0x50,0x32,
- 0xc0,0xeb,0xa8,0x4f,0x23,0x7c,0x16,0x89,0x7c,0x12,0xc6,0x44,
- 0x59,0x01,0xeb,0xa4,0xf6,0x44,0x51,0x02,0x74,0x07,0xfb,0x81,
- 0xc6,0x80,0x00,0xff,0x24,0x80,0x4c,0x51,0x02,0xb0,0x05,0xee,
- 0xb0,0x82,0x22,0x44,0x5f,0xf6,0xd0,0x22,0x44,0x75,0x88,0x44,
- 0x75,0xee,0xf6,0x44,0x29,0x10,0x74,0x10,0x80,0x4c,0x54,0x04,
- 0x80,0x4c,0x58,0x04,0x80,0x74,0x50,0x08,0xc7,0x04,0xc3,0x03,
- 0xfb,0x81,0xc6,0x80,0x00,0xff,0x24,0x26,0xc6,0x05,0xff,0x47,
- 0x23,0x7c,0x16,0x3b,0x7c,0x14,0x74,0xa7,0x32,0xff,0xf6,0x44,
- 0x29,0x80,0x74,0x0a,0x8a,0xdc,0xc0,0xeb,0x04,0x2e,0x8a,0xbf,
- 0xb1,0x01,0x26,0x88,0x3d,0x47,0x23,0x7c,0x16,0x3b,0x7c,0x14,
- 0x74,0x89,0xaa,0x23,0x7c,0x16,0x3b,0x7c,0x14,0x74,0x80,0xe9,
- 0x2e,0xff,0x1e,0x2e,0x8e,0x1e,0xc1,0x03,0xff,0x06,0x1c,0x0e,
- 0x60,0xbe,0x00,0x14,0xeb,0x0f,0x90,0x1e,0x2e,0x8e,0x1e,0xc1,
- 0x03,0xff,0x06,0x1a,0x0e,0x60,0xbe,0x00,0x10,0xb9,0x08,0x00,
- 0x8b,0x54,0x20,0xb0,0x03,0xee,0x90,0x90,0x32,0xff,0xec,0x8a,
- 0xd8,0x02,0xd8,0x2e,0xff,0xa7,0xa9,0x00,0x81,0xc6,0x00,0x01,
- 0x8b,0x54,0x20,0x0b,0xd2,0xe0,0xe4,0xb8,0x00,0x80,0xba,0x22,
- 0xff,0xef,0x61,0x1f,0xcf,0x81,0xce,0x80,0x00,0x8b,0x54,0x20,
- 0xff,0x06,0x20,0x0e,0xb0,0x01,0xee,0x8a,0x44,0x71,0x24,0xe7,
- 0x88,0x44,0x71,0xee,0xc6,0x44,0x49,0x02,0x80,0x4c,0x50,0x20,
- 0xc7,0x04,0xc3,0x03,0x81,0xe6,0x7f,0xff,0x8b,0x54,0x20,0xeb,
- 0xae,0x81,0xce,0x80,0x00,0x8b,0x54,0x20,0xff,0x06,0x22,0x0e,
- 0xec,0x0a,0xc0,0x79,0x7a,0x80,0x4c,0x51,0x10,0xc7,0x44,0x06,
- 0xe1,0x08,0xc6,0x44,0x63,0x04,0xf6,0x44,0x51,0x04,0x74,0x08,
- 0x80,0x64,0x51,0xfb,0x80,0x64,0x53,0x3f,0xf6,0x44,0x28,0x01,
- 0x75,0x59,0xf6,0x44,0x28,0x02,0x75,0x4f,0x8b,0x7c,0x12,0x8c,
- 0xc3,0x8e,0x44,0x10,0xf6,0x44,0x28,0x08,0x74,0x1e,0xb0,0xff,
- 0xaa,0x23,0x7c,0x16,0x3b,0x7c,0x14,0x74,0x26,0x32,0xc0,0xf6,
- 0x44,0x29,0x80,0x74,0x02,0xb0,0x10,0xaa,0x23,0x7c,0x16,0x3b,
- 0x7c,0x14,0x74,0x13,0x32,0xc0,0xaa,0x23,0x7c,0x16,0x3b,0x7c,
- 0x14,0x74,0x08,0x8e,0xc3,0x89,0x7c,0x12,0xeb,0x15,0x90,0x8e,
- 0xc3,0x4f,0x23,0x7c,0x16,0x89,0x7c,0x12,0xc6,0x44,0x59,0x01,
- 0xeb,0x05,0x90,0x80,0x4c,0x4f,0x01,0xb0,0x10,0xee,0x81,0xe6,
- 0x7f,0xff,0x8b,0x54,0x20,0xe9,0x17,0xff,0xff,0x06,0x1e,0x0e,
- 0xe9,0x10,0xff,0x1e,0x2e,0x8e,0x1e,0xc1,0x03,0x50,0x52,0x55,
- 0x8b,0xec,0x8b,0x46,0x08,0xa3,0x12,0x0e,0x32,0xe4,0xa0,0x22,
- 0x0c,0xa3,0x10,0x0e,0xff,0x06,0x00,0x0e,0x83,0x06,0x0e,0x0e,
- 0x0a,0x83,0x3e,0x04,0x0e,0x00,0x74,0x31,0x8b,0x16,0x00,0x0e,
- 0x2b,0x16,0x02,0x0e,0x3b,0x16,0x04,0x0e,0x72,0x23,0x8b,0x16,
- 0x00,0x0e,0x89,0x16,0x02,0x0e,0x8b,0x16,0x18,0x0d,0x3b,0x16,
- 0x1a,0x0d,0x74,0x11,0x80,0x3e,0x10,0x0c,0x01,0x74,0x16,0xb0,
- 0x00,0x90,0xe6,0x00,0x0c,0x08,0x90,0xe6,0x00,0xb8,0x00,0x80,
- 0xba,0x22,0xff,0xef,0x5d,0x5a,0x58,0x1f,0xcf,0xb0,0x80,0xe6,
- 0x00,0xa0,0x11,0x0c,0x0c,0x10,0xa2,0x11,0x0c,0xeb,0xe6,0x1e,
- 0x2e,0x8e,0x1e,0xc1,0x03,0xff,0x06,0x28,0x0e,0x55,0x8b,0xec,
- 0x8b,0x6e,0x02,0x89,0x2e,0x16,0x0e,0x5d,0x1f,0xcf,0x1e,0x2e,
- 0x8e,0x1e,0xc1,0x03,0xff,0x06,0x24,0x0e,0x55,0x8b,0xec,0x8b,
- 0x6e,0x02,0x89,0x2e,0x14,0x0e,0x5d,0x80,0x3e,0x10,0x0c,0x01,
- 0x75,0x12,0x50,0xa0,0x11,0x0c,0x0c,0x01,0xa2,0x11,0x0c,0xe4,
- 0x00,0x90,0x90,0x24,0x7f,0xe6,0x00,0x58,0x1f,0xcf,0x1e,0x06,
- 0x60,0xb8,0x00,0x80,0xba,0x22,0xff,0xef,0x2e,0x8e,0x1e,0xc1,
- 0x03,0x2e,0x8e,0x06,0xc1,0x03,0x2e,0xff,0x06,0x30,0x0d,0xfc,
- 0xff,0x26,0x2e,0x0e,0x00,0x00,0xfb,0x40,0x43,0x41,0x42,0x46,
- 0x47,0x45,0xeb,0xf6,0xc3,0x00,0x00,0x8f,0x06,0x2e,0x0e,0x2e,
- 0xff,0x06,0x3d,0x0d,0xb8,0x00,0x00,0xba,0x58,0xff,0xef,0xb8,
- 0x00,0xe0,0xba,0x5e,0xff,0xef,0x61,0x07,0x1f,0xcf,0xc2,0xfe,
- 0xff,0x8b,0x7c,0x0a,0x2b,0x7c,0x0c,0x23,0x7c,0x0e,0x3b,0x7c,
- 0x18,0x77,0x2e,0xc6,0x44,0x4d,0x00,0x80,0x4c,0x4f,0x02,0xeb,
- 0x5a,0x90,0x8b,0x7c,0x0a,0x3b,0x7c,0x0c,0x75,0x1b,0x8b,0x3e,
- 0x10,0x0d,0x3b,0x3e,0x12,0x0d,0x75,0x53,0xf6,0x44,0x4b,0xff,
- 0x75,0x4d,0xc6,0x44,0x4c,0x00,0x80,0x4c,0x4f,0x04,0xeb,0x43,
- 0x90,0xf6,0x44,0x50,0x10,0x75,0x3c,0xeb,0x09,0x90,0x8b,0x7c,
- 0x0a,0x2b,0x7c,0x0c,0x74,0x31,0x80,0x4c,0x50,0x10,0x80,0x4c,
- 0x4b,0x10,0xc7,0x04,0xc3,0x03,0xeb,0x23,0x90,0xfa,0x8b,0x36,
- 0x08,0x0e,0x8b,0x54,0x20,0xec,0x8a,0xf8,0x8a,0x5c,0x54,0x32,
- 0xfb,0xf6,0x44,0x4d,0xff,0x75,0x8e,0xf6,0x44,0x4c,0xff,0x75,
- 0xa1,0xf6,0x44,0x50,0x10,0x74,0xc7,0xec,0x32,0xc3,0x22,0xf8,
- 0x83,0x2e,0x10,0x0e,0x01,0x78,0x05,0xd0,0x6c,0x49,0x72,0x45,
- 0x8b,0x7c,0x12,0x2b,0x7c,0x14,0x74,0x22,0x80,0x7c,0x4e,0x00,
- 0x74,0x1c,0x23,0x7c,0x16,0x03,0xff,0x3b,0x7c,0x16,0x73,0x43,
- 0x8b,0x0e,0x0e,0x0e,0x2b,0x4c,0x6e,0x3b,0x4c,0x22,0x73,0x37,
- 0x80,0x7c,0x49,0x00,0x74,0x31,0xf6,0x44,0x51,0x02,0x75,0x3c,
- 0xec,0x32,0xc3,0x22,0xf8,0x80,0xe7,0x38,0xfb,0x89,0x1e,0x30,
- 0x0e,0xbe,0x00,0x10,0xff,0x14,0xeb,0x61,0x90,0xb0,0x01,0xee,
- 0x8a,0x44,0x71,0x0c,0x10,0x88,0x44,0x71,0xee,0x80,0x64,0x50,
- 0xdf,0xc7,0x04,0xc3,0x03,0xeb,0xa5,0xc6,0x44,0x4e,0x00,0x8b,
- 0x0e,0x0e,0x0e,0x89,0x4c,0x6e,0x80,0x4c,0x4f,0x08,0xeb,0xbe,
- 0x8b,0x7c,0x12,0x2b,0x7c,0x14,0x23,0x7c,0x16,0x3b,0x7c,0x1a,
- 0x73,0xb6,0x80,0x64,0x51,0xfd,0xf6,0x44,0x29,0x10,0x74,0x10,
- 0x80,0x64,0x54,0xfb,0x80,0x4c,0x58,0x04,0x80,0x74,0x50,0x08,
- 0xc7,0x04,0xc3,0x03,0xb0,0x05,0xee,0xb0,0x82,0x22,0x44,0x5f,
- 0x0a,0x44,0x75,0x88,0x44,0x75,0xee,0xeb,0x8b,0xfa,0x8b,0x36,
- 0x08,0x0e,0x8b,0x1e,0x30,0x0e,0x8a,0xcb,0xe5,0x80,0x23,0x44,
- 0x2e,0x74,0x02,0xf6,0xd1,0x80,0xe1,0x40,0x0a,0xf9,0x8a,0xdf,
- 0x22,0x5c,0x55,0x30,0x5c,0x54,0x32,0xfb,0x88,0x7c,0x55,0x0a,
- 0x5c,0x58,0x88,0x5c,0x58,0x22,0x5c,0x56,0x75,0x24,0x80,0x7c,
- 0x4f,0x00,0x75,0x22,0xfb,0x03,0x74,0x1e,0x89,0x36,0x08,0x0e,
- 0xff,0x06,0x26,0x0e,0x8b,0x3e,0x12,0x0d,0x3b,0x3e,0x10,0x0d,
- 0x75,0x46,0xbe,0x00,0x10,0xff,0x14,0xe9,0xd3,0xfe,0x80,0x4c,
- 0x4f,0x20,0x8b,0x3e,0x18,0x0d,0x8a,0x44,0x48,0x8a,0x64,0x4f,
- 0x89,0x85,0x00,0x08,0x8a,0x44,0x54,0x8a,0x64,0x57,0x89,0x85,
- 0x02,0x08,0x83,0xc7,0x04,0x81,0xe7,0xfc,0x03,0x3b,0x3e,0x1a,
- 0x0d,0x74,0x13,0x88,0x44,0x57,0xc6,0x44,0x4f,0x00,0x8a,0x44,
- 0x56,0xf6,0xd0,0x20,0x44,0x58,0x89,0x3e,0x18,0x0d,0xeb,0xa4,
- 0xff,0x06,0x2c,0x0e,0xbe,0x00,0x10,0xff,0x14,0xfa,0x8b,0x3e,
- 0x12,0x0d,0x81,0xc7,0x00,0x04,0x8a,0x5d,0x01,0x83,0xe3,0x0f,
- 0x03,0xdb,0x2e,0x8b,0xb7,0x89,0x00,0x8b,0x54,0x20,0x0b,0xd2,
- 0x74,0x0d,0x8a,0x1d,0x83,0xe3,0x1f,0x03,0xdb,0xfa,0x2e,0xff,
- 0xa7,0x9c,0x0f,0xff,0x06,0x2a,0x0e,0x8b,0x3e,0x12,0x0d,0x8b,
- 0x36,0x18,0x0d,0x8b,0x9d,0x00,0x04,0x89,0x9c,0x00,0x08,0x8b,
- 0x9d,0x02,0x04,0x89,0x9c,0x02,0x08,0x83,0xc6,0x04,0x81,0xe6,
- 0xfc,0x03,0x3b,0x36,0x1a,0x0d,0x74,0x04,0x89,0x36,0x18,0x0d,
- 0xfb,0x8b,0x3e,0x12,0x0d,0x83,0xc7,0x04,0x81,0xe7,0xfc,0x03,
- 0x89,0x3e,0x12,0x0d,0xbe,0x00,0x10,0xff,0x14,0xe9,0x1d,0xfe,
- 0xdc,0x0f,0xe4,0x0f,0xec,0x0f,0x0d,0x10,0x1c,0x10,0x57,0x0f,
- 0x2f,0x10,0x57,0x0f,0x3b,0x10,0x54,0x10,0x83,0x10,0xcf,0x10,
- 0xdb,0x10,0xe4,0x10,0xeb,0x10,0x35,0x11,0x7d,0x11,0x83,0x11,
- 0xa1,0x11,0xb9,0x11,0xf2,0x11,0x38,0x12,0x03,0x13,0x0c,0x13,
- 0x57,0x0f,0x57,0x0f,0x57,0x0f,0x57,0x0f,0x57,0x0f,0x57,0x0f,
- 0x57,0x0f,0x57,0x0f,0x8b,0x45,0x02,0x89,0x44,0x1a,0xeb,0xa0,
- 0x8b,0x45,0x02,0x89,0x44,0x1c,0xeb,0x98,0x8b,0x45,0x02,0x8b,
- 0x5c,0x0a,0x2b,0x5c,0x0c,0x23,0x5c,0x0e,0x8b,0x4c,0x0a,0x2b,
- 0xc8,0x23,0x4c,0x0e,0x3b,0xd9,0x76,0x06,0x23,0x44,0x0e,0x89,
- 0x44,0x0c,0xe9,0x77,0xff,0x80,0x4c,0x53,0x80,0x80,0x4c,0x54,
- 0x01,0x80,0x4c,0x58,0x01,0xe9,0x68,0xff,0x80,0x64,0x53,0x3f,
- 0x80,0x64,0x54,0xfe,0x80,0x4c,0x58,0x01,0x80,0x64,0x51,0xfb,
- 0xe9,0x55,0xff,0x8b,0x45,0x02,0x88,0x44,0x5a,0x88,0x64,0x5b,
- 0xe9,0x49,0xff,0x8b,0x45,0x02,0x0b,0xc0,0x74,0x03,0x89,0x44,
- 0x24,0x80,0x4c,0x50,0x04,0x80,0x4c,0x4b,0x04,0xc7,0x04,0xc3,
- 0x03,0xe9,0x30,0xff,0x8b,0x5d,0x02,0xf6,0xd7,0x22,0x7c,0x54,
- 0x0a,0xdf,0x8a,0x44,0x54,0x32,0xc3,0x24,0x82,0x30,0x44,0x54,
- 0xb0,0x05,0xee,0x8a,0x44,0x75,0x32,0xd8,0x8a,0x7c,0x5f,0xf6,
- 0xd7,0x22,0xdf,0x80,0xe3,0x82,0x32,0xc3,0x88,0x44,0x75,0xee,
- 0xe9,0x01,0xff,0x8b,0x5d,0x02,0xf6,0xc7,0x04,0x75,0x08,0x80,
- 0x64,0x53,0x3f,0x80,0x64,0x51,0xfb,0x8a,0x44,0x29,0x32,0xc7,
- 0xa8,0x10,0x74,0x0e,0xf6,0x44,0x51,0x02,0x74,0x08,0x80,0x74,
- 0x50,0x08,0xc7,0x04,0xc3,0x03,0x88,0x5c,0x28,0x88,0x7c,0x29,
- 0xb4,0x60,0xf6,0xc3,0x10,0x74,0x03,0x80,0xcc,0x10,0x8a,0x44,
- 0x62,0xf6,0xc3,0x20,0x74,0x02,0x24,0x7f,0x89,0x44,0x34,0xc7,
- 0x44,0x06,0xe1,0x08,0xe9,0xb5,0xfe,0x8b,0x45,0x02,0x88,0x44,
- 0x5c,0x88,0x64,0x5d,0xe9,0xa9,0xfe,0x8b,0x45,0x02,0x89,0x44,
- 0x18,0xe9,0xa0,0xfe,0xff,0x1e,0x24,0x0d,0xe9,0x99,0xfe,0xf6,
- 0x44,0x51,0x02,0x75,0x41,0x8b,0x44,0x12,0x2b,0x44,0x14,0x23,
- 0x44,0x16,0x3b,0x44,0x1a,0x72,0x33,0x80,0x4c,0x51,0x02,0xf6,
- 0x44,0x29,0x10,0x74,0x10,0x80,0x4c,0x54,0x04,0x80,0x4c,0x58,
- 0x04,0x80,0x74,0x50,0x08,0xc7,0x04,0xc3,0x03,0xf6,0x44,0x5f,
- 0x82,0x74,0x13,0xb0,0x05,0xee,0x8a,0x44,0x75,0xb4,0x82,0x22,
- 0x64,0x5f,0xf6,0xd4,0x22,0xc4,0x88,0x44,0x75,0xee,0xe9,0x4f,
- 0xfe,0xf6,0x44,0x51,0x02,0x74,0x3f,0x8b,0x44,0x12,0x2b,0x44,
- 0x14,0x23,0x44,0x16,0x3b,0x44,0x1c,0x73,0xe9,0x80,0x64,0x51,
- 0xfd,0xf6,0x44,0x29,0x10,0x74,0x10,0x80,0x64,0x54,0xfb,0x80,
- 0x4c,0x58,0x04,0x80,0x74,0x50,0x08,0xc7,0x04,0xc3,0x03,0xf6,
- 0x44,0x5f,0x02,0x74,0x11,0xb0,0x05,0xee,0x8a,0x44,0x75,0xb4,
- 0x82,0x22,0x64,0x5f,0x0a,0xc4,0x88,0x44,0x75,0xee,0xe9,0x07,
- 0xfe,0xe8,0x8a,0x02,0xe9,0x01,0xfe,0x8b,0x45,0x02,0xbb,0x10,
- 0x27,0xf7,0xe3,0xbb,0x0f,0x00,0xf7,0xf3,0xa3,0x06,0x0e,0xba,
- 0x52,0xff,0xef,0xba,0x50,0xff,0xb8,0x00,0x00,0xef,0xe9,0xe3,
- 0xfd,0x8b,0x45,0x02,0x3a,0x06,0x22,0x0c,0x72,0x0c,0x3b,0x06,
- 0x1a,0x0c,0x77,0x06,0xe8,0xab,0x01,0xe9,0xce,0xfd,0xe9,0x9e,
- 0xfd,0x8b,0x45,0x02,0x88,0x44,0x2a,0x88,0x64,0x2b,0x0b,0xc0,
- 0x75,0x07,0x80,0x64,0x50,0xfe,0xeb,0x10,0x90,0xf6,0x44,0x50,
- 0x01,0x75,0x09,0x80,0x4c,0x50,0x01,0xc7,0x44,0x30,0x00,0x00,
- 0xa8,0x80,0x75,0x07,0xc6,0x44,0x60,0x00,0xeb,0x05,0x90,0xc6,
- 0x44,0x60,0x7f,0xc7,0x04,0xc3,0x03,0xe9,0x92,0xfd,0x8b,0x5d,
- 0x02,0xf6,0xd7,0x22,0x7c,0x5f,0x0a,0xdf,0x8a,0xfb,0x88,0x5c,
- 0x5f,0x8a,0x44,0x52,0x8a,0x64,0x53,0x8b,0xcb,0x33,0xc8,0x81,
- 0xe1,0x38,0x38,0x33,0xc1,0x88,0x44,0x52,0x88,0x64,0x53,0xb0,
- 0x05,0xee,0xf6,0xd3,0x22,0x5c,0x54,0xf6,0x44,0x51,0x02,0x75,
- 0x02,0x0a,0xdf,0x8a,0x44,0x75,0x32,0xd8,0x80,0xe3,0x82,0x32,
- 0xc3,0x88,0x44,0x75,0xee,0xe9,0x4c,0xfd,0x8b,0x5d,0x02,0x88,
- 0x5c,0x2c,0x88,0x7c,0x2d,0x8b,0xcb,0x83,0xe3,0x0f,0x03,0xdb,
- 0x80,0x3e,0x10,0x0c,0x01,0x75,0x1f,0xa1,0x0e,0x0c,0x86,0xe0,
- 0x3d,0x32,0x31,0x73,0x15,0xf6,0xc5,0x04,0x75,0x08,0x2e,0x8b,
- 0x9f,0x69,0x01,0xeb,0x1b,0x90,0x2e,0x8b,0x9f,0x89,0x01,0xeb,
- 0x13,0x90,0xf6,0xc5,0x04,0x75,0x08,0x2e,0x8b,0x9f,0x29,0x01,
- 0xeb,0x06,0x90,0x2e,0x8b,0x9f,0x49,0x01,0xb0,0x0c,0xee,0x8a,
- 0xc3,0x88,0x44,0x7c,0xee,0xb0,0x0d,0x90,0x90,0xee,0x8a,0xc7,
- 0x88,0x44,0x7d,0xee,0xb0,0x04,0xee,0xb0,0x44,0xf6,0xc1,0x40,
- 0x74,0x0c,0xf6,0xc1,0x80,0x74,0x05,0x04,0x04,0xeb,0x03,0x90,
- 0x0c,0x08,0xf6,0xc5,0x01,0x74,0x09,0x0c,0x01,0xf6,0xc5,0x02,
- 0x75,0x02,0x0c,0x02,0x88,0x44,0x74,0xee,0xb0,0x03,0x90,0x90,
- 0xee,0x8a,0xd9,0x80,0xe3,0x30,0xc0,0xeb,0x04,0x32,0xff,0x2e,
- 0x8a,0xa7,0xa9,0x01,0x8a,0x44,0x73,0x24,0x3f,0x0a,0xc4,0x88,
- 0x44,0x73,0xee,0x90,0x90,0xb0,0x05,0xee,0xd0,0xec,0x8a,0x44,
- 0x75,0x24,0x9f,0x0a,0xc4,0x88,0x44,0x75,0xee,0x2e,0x8a,0x87,
- 0xad,0x01,0x88,0x44,0x62,0xf6,0x44,0x28,0x20,0x74,0x02,0x24,
- 0x7f,0x88,0x44,0x34,0xe9,0x81,0xfc,0x8a,0x45,0x02,0x88,0x44,
- 0x5e,0xe9,0x78,0xfc,0x8b,0x45,0x02,0xba,0x5a,0xff,0xef,0x9c,
- 0xff,0x36,0x26,0x0d,0xff,0x36,0x24,0x0d,0x1e,0x06,0x60,0x8b,
- 0x36,0x0a,0x0e,0xc7,0x04,0x3f,0x0d,0xe9,0x5a,0xfc,0xb8,0x00,
- 0x00,0x8e,0xc0,0x8b,0xf0,0x8b,0xf8,0x2e,0x8b,0x9c,0x49,0x00,
- 0x83,0xc6,0x02,0x26,0x89,0x1d,0x26,0x8c,0x4d,0x02,0x83,0xc7,
- 0x04,0x81,0xff,0x80,0x00,0x72,0xe8,0x26,0xc7,0x05,0xcb,0x0c,
- 0x26,0x8c,0x4d,0x02,0x83,0xc7,0x04,0x81,0xff,0x00,0x04,0x72,
- 0xee,0xc3,0xc1,0xe0,0x06,0x8b,0xd8,0x8c,0xda,0x81,0xc2,0x00,
- 0x04,0x8b,0xfa,0x8a,0x0e,0x22,0x0c,0xb5,0x00,0xbe,0x00,0x10,
- 0x33,0xc0,0x89,0x44,0x0a,0x89,0x44,0x0c,0x89,0x44,0x12,0x89,
- 0x44,0x14,0x81,0xc6,0x80,0x00,0xe2,0xee,0x89,0x36,0x0a,0x0e,
- 0xb8,0x01,0x00,0x8b,0xd0,0xb3,0x00,0x8a,0x0e,0x22,0x0c,0xb5,
- 0x00,0xbe,0x00,0x10,0x2b,0xda,0x72,0x29,0x89,0x44,0x16,0x81,
- 0xc6,0x80,0x00,0xe2,0xf3,0x8a,0x0e,0x22,0x0c,0xb5,0x00,0xbe,
- 0x00,0x10,0x2b,0xda,0x72,0x13,0x89,0x44,0x0e,0x81,0xc6,0x80,
- 0x00,0xe2,0xf3,0x8b,0xd0,0x03,0xc0,0x81,0xfa,0x00,0x02,0x72,
- 0xca,0x8a,0x0e,0x22,0x0c,0xb5,0x00,0xbe,0x00,0x10,0x89,0x7c,
- 0x10,0x8b,0x44,0x16,0x03,0xf8,0x8b,0xd7,0xc1,0xe0,0x04,0x48,
- 0x89,0x44,0x16,0x81,0xc6,0x80,0x00,0xe2,0xe9,0x8a,0x0e,0x22,
- 0x0c,0xb5,0x00,0xbe,0x00,0x10,0x89,0x7c,0x08,0x8b,0x44,0x0e,
- 0x03,0xf8,0x8b,0xd7,0xc1,0xe0,0x04,0x48,0x89,0x44,0x0e,0x81,
- 0xc6,0x80,0x00,0xe2,0xe9,0xc3,0xc7,0x04,0x20,0x04,0xc7,0x44,
- 0x06,0xe1,0x08,0x8b,0xc6,0x2d,0x00,0x10,0xb1,0x80,0xf6,0xf1,
- 0x88,0x44,0x48,0xc7,0x44,0x0a,0x00,0x00,0xc7,0x44,0x0c,0x00,
- 0x00,0xc7,0x44,0x12,0x00,0x00,0xc7,0x44,0x14,0x00,0x00,0xc7,
- 0x44,0x18,0x00,0x00,0xc7,0x44,0x1a,0x00,0x00,0xc7,0x44,0x1c,
- 0xff,0xff,0x8a,0x5c,0x48,0x83,0xe3,0x0f,0x03,0xdb,0x8b,0x97,
- 0x90,0x0c,0x89,0x54,0x20,0xb8,0x01,0x00,0x8a,0x4c,0x48,0xd3,
- 0xe0,0x89,0x44,0x2e,0xc7,0x44,0x24,0x19,0x00,0xc7,0x44,0x26,
- 0x00,0x00,0xc6,0x44,0x4a,0x00,0xc7,0x44,0x30,0x00,0x00,0xc7,
- 0x44,0x32,0x00,0x00,0xc6,0x44,0x4c,0x00,0xc6,0x44,0x4d,0x00,
- 0xc6,0x44,0x4e,0x00,0xc6,0x44,0x4f,0x00,0xc6,0x44,0x50,0x00,
- 0xc6,0x44,0x4b,0x00,0xc6,0x44,0x51,0x00,0xc6,0x44,0x28,0x00,
- 0xc6,0x44,0x29,0x00,0xc6,0x44,0x2a,0x00,0xc6,0x44,0x2b,0x00,
- 0xc6,0x44,0x54,0x00,0xc6,0x44,0x57,0x00,0xc6,0x44,0x55,0x00,
- 0xc6,0x44,0x56,0x00,0xc6,0x44,0x58,0x00,0xc6,0x44,0x52,0x04,
- 0xc6,0x44,0x53,0x04,0xc6,0x44,0x5f,0x00,0xc6,0x44,0x2c,0x3d,
- 0xc6,0x44,0x2d,0x00,0xc7,0x44,0x34,0xff,0x60,0xc6,0x44,0x62,
- 0xff,0xc6,0x44,0x5d,0x13,0xc6,0x44,0x5c,0x11,0xc6,0x44,0x5e,
- 0x00,0xc6,0x44,0x60,0x23,0xc6,0x44,0x61,0x23,0x0b,0xd2,0x75,
- 0x03,0xe9,0xd9,0x00,0xb0,0x09,0xee,0x8a,0x4c,0x48,0xb0,0x80,
- 0xd2,0xe8,0xee,0xc6,0x44,0x70,0x00,0xb0,0x01,0xee,0xb0,0x11,
- 0x88,0x44,0x71,0xee,0xb0,0x02,0x90,0x90,0xee,0x8a,0x44,0x48,
- 0xc0,0xe0,0x03,0x24,0xf0,0x88,0x44,0x72,0xee,0xb0,0x03,0x90,
- 0x90,0xee,0xb0,0xc0,0x88,0x44,0x73,0xee,0xb0,0x04,0x90,0x90,
- 0xee,0xb0,0x44,0x88,0x44,0x74,0xee,0xb0,0x05,0x90,0xee,0xb0,
- 0x60,0x88,0x44,0x75,0xee,0xc6,0x44,0x76,0x00,0xc6,0x44,0x77,
- 0x00,0xc6,0x44,0x78,0x00,0xb0,0x09,0xee,0xb0,0x09,0x88,0x44,
- 0x79,0xee,0xc6,0x44,0x7a,0x00,0xb0,0x0b,0xee,0xb0,0x52,0x88,
- 0x44,0x7b,0xee,0x80,0x3e,0x10,0x0c,0x01,0x75,0x21,0xa1,0x0e,
- 0x0c,0x86,0xe0,0x3d,0x32,0x31,0x73,0x17,0xb0,0x0c,0xee,0xb0,
- 0x18,0x88,0x44,0x7c,0xee,0xb0,0x0d,0x90,0x90,0xee,0xb0,0x00,
- 0x88,0x44,0x7d,0xee,0xeb,0x15,0x90,0xb0,0x0c,0xee,0xb0,0x16,
- 0x88,0x44,0x7c,0xee,0xb0,0x0d,0x90,0x90,0xee,0xb0,0x00,0x88,
- 0x44,0x7d,0xee,0xb0,0x0e,0x90,0x90,0xee,0xb0,0x03,0x88,0x44,
- 0x7e,0xee,0xb0,0x0f,0x90,0x90,0xee,0xb0,0x80,0x88,0x44,0x7f,
- 0xee,0xb0,0x03,0x90,0x90,0xee,0x8a,0x44,0x73,0x0c,0x01,0x88,
- 0x44,0x73,0xee,0x90,0x90,0xb0,0x05,0xee,0x8a,0x44,0x75,0x0c,
- 0x08,0x88,0x44,0x75,0xee,0xc3,0xfa,0x8c,0xd8,0x25,0x00,0xf0,
- 0x8e,0xd0,0xbc,0xfe,0x1f,0x8c,0xd8,0x25,0x00,0xf0,0x8e,0xd8,
- 0x80,0x3e,0x40,0x0d,0x01,0x75,0x51,0xa1,0x0e,0x0c,0x86,0xe0,
- 0x3d,0x30,0x32,0x73,0x47,0x8b,0x1e,0x20,0x0c,0x8a,0x16,0x23,
- 0x0c,0xc6,0x06,0x23,0x0c,0x00,0x83,0xfb,0x00,0x74,0x07,0xfe,
- 0xca,0xc6,0x06,0x23,0x0c,0x01,0x88,0x16,0x22,0x0c,0xbe,0x10,
- 0x0c,0xbf,0x90,0x0c,0xb9,0x08,0x00,0x1e,0x07,0xfc,0xf3,0xa5,
- 0xbf,0xa0,0x0c,0xb8,0x00,0x00,0xb9,0x08,0x00,0xf3,0xab,0xc7,
- 0x06,0x1a,0x0c,0x70,0x00,0xa0,0x40,0x0d,0xa2,0x10,0x0c,0xc6,
- 0x06,0x11,0x0c,0x00,0x2e,0x8c,0x1e,0xc1,0x03,0xc7,0x06,0x18,
- 0x0e,0x02,0x00,0xe8,0xec,0xfc,0xc7,0x06,0x24,0x0d,0x5a,0x0d,
- 0x8c,0x0e,0x26,0x0d,0xc7,0x06,0x18,0x0e,0x06,0x00,0xa1,0x1a,
- 0x0c,0xe8,0x0a,0xfd,0xc7,0x06,0x18,0x0e,0x0a,0x00,0xbe,0x00,
- 0x10,0xc7,0x44,0x1e,0x80,0x00,0xe8,0xa5,0xfd,0x81,0xc6,0x80,
- 0x00,0x81,0xfe,0x00,0x18,0x72,0xee,0xa0,0x22,0x0c,0xb4,0x80,
- 0xf6,0xe4,0xbe,0x00,0x10,0x03,0xf0,0x89,0x36,0x0a,0x0e,0x29,
- 0x44,0x9e,0xc7,0x06,0x00,0x0e,0x00,0x00,0xc7,0x06,0x02,0x0e,
- 0x00,0x00,0xc7,0x06,0x04,0x0e,0x00,0x00,0xc7,0x06,0x06,0x0e,
- 0x9a,0x02,0xba,0x52,0xff,0xa1,0x06,0x0e,0xef,0xba,0x50,0xff,
- 0xb8,0x00,0x00,0xef,0xba,0x56,0xff,0xb8,0x05,0xe0,0xef,0xba,
- 0x5e,0xff,0xb8,0x00,0x40,0xef,0xba,0x66,0xff,0xb8,0x00,0x40,
- 0xef,0xc7,0x06,0x10,0x0d,0x00,0x00,0xc7,0x06,0x12,0x0d,0x00,
- 0x00,0xc7,0x06,0x14,0x0d,0x00,0x04,0xc7,0x06,0x16,0x0d,0xfc,
- 0x03,0xc7,0x06,0x18,0x0d,0x00,0x00,0xc7,0x06,0x1a,0x0d,0x00,
- 0x00,0xc7,0x06,0x1c,0x0d,0x00,0x08,0xc7,0x06,0x1e,0x0d,0xfc,
- 0x03,0xb0,0x00,0x90,0xe6,0x00,0xc7,0x06,0x18,0x0e,0x32,0x00,
- 0xba,0x38,0xff,0xb8,0x11,0x00,0xef,0xba,0x3a,0xff,0xb8,0x08,
- 0x00,0xef,0xba,0x3c,0xff,0xb8,0x08,0x00,0xef,0xba,0x3e,0xff,
- 0xb8,0x08,0x00,0x80,0x3e,0x22,0x0c,0x08,0x76,0x03,0xb8,0x12,
- 0x00,0xef,0xba,0x32,0xff,0xb8,0x05,0x00,0xef,0xba,0x28,0xff,
- 0xb8,0x6c,0x00,0xef,0xba,0x22,0xff,0xb8,0x00,0x80,0xef,0xc7,
- 0x06,0x18,0x0e,0x33,0x00,0xc7,0x06,0x20,0x0d,0x4f,0x00,0xc7,
- 0x06,0x21,0x0d,0x53,0x00,0x8b,0x36,0x0a,0x0e,0xc7,0x04,0x3c,
- 0x0d,0xc7,0x06,0x08,0x0e,0x00,0x10,0xe9,0x63,0xf6,0x40,0x28,
- 0x23,0x29,0x20,0x24,0x49,0x64,0x3a,0x20,0x78,0x61,0x63,0x6f,
- 0x6f,0x6b,0x2e,0x61,0x73,0x6d,0x2c,0x76,0x20,0x37,0x2e,0x32,
- 0x35,0x20,0x31,0x39,0x39,0x35,0x2f,0x30,0x31,0x2f,0x31,0x32,
- 0x20,0x32,0x30,0x3a,0x35,0x39,0x3a,0x32,0x31,0x20,0x6d,0x69,
- 0x6c,0x74,0x20,0x45,0x78,0x70,0x20,0x24,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
-};
-
diff --git a/drivers/char/drm/Kconfig b/drivers/char/drm/Kconfig
index 4caf68304849d..d9a0299346787 100644
--- a/drivers/char/drm/Kconfig
+++ b/drivers/char/drm/Kconfig
@@ -18,7 +18,7 @@ config DRM
config DRM_TDFX
tristate "3dfx Banshee/Voodoo3+"
- depends on DRM
+ depends on DRM && PCI
help
Choose this option if you have a 3dfx Banshee or Voodoo3 (or later),
graphics card. If M is selected, the module will be called tdfx.
diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h
index ab61660e6581a..21f4c54e1a8d7 100644
--- a/drivers/char/drm/drmP.h
+++ b/drivers/char/drm/drmP.h
@@ -422,7 +422,7 @@ typedef struct drm_file {
unsigned long ioctl_count;
struct drm_file *next;
struct drm_file *prev;
- struct drm_device *dev;
+ struct drm_head *head;
int remove_auth_on_close;
unsigned long lock_count;
void *driver_priv;
@@ -497,6 +497,7 @@ typedef struct drm_agp_head {
DRM_AGP_KERN agp_info; /**< AGP device information */
drm_agp_mem_t *memory; /**< memory entries */
unsigned long mode; /**< AGP mode */
+ struct agp_bridge_data *bridge;
int enabled; /**< whether the AGP bus as been enabled */
int acquired; /**< whether the AGP device has been acquired */
unsigned long base;
@@ -592,19 +593,31 @@ struct drm_driver {
struct file_operations fops;
struct pci_driver pci_driver;
};
+
/**
- * DRM device structure.
+ * DRM head structure. This structure represent a video head on a card
+ * that may contain multiple heads. Embed one per head of these in the
+ * private drm_device structure.
+ */
+typedef struct drm_head {
+ int minor; /**< Minor device number */
+ struct drm_device *dev;
+ struct proc_dir_entry *dev_root; /**< proc directory entry */
+ dev_t device; /**< Device number for mknod */
+ struct class_device *dev_class;
+} drm_head_t;
+
+/**
+ * DRM device structure. This structure represent a complete card that
+ * may contain multiple heads.
*/
typedef struct drm_device {
char *unique; /**< Unique identifier: e.g., busid */
int unique_len; /**< Length of unique field */
- dev_t device; /**< Device number for mknod */
char *devname; /**< For /proc/interrupts */
- int minor; /**< Minor device number */
int if_version; /**< Highest interface version set */
int blocked; /**< Blocked due to VC switch? */
- struct proc_dir_entry *root; /**< Root for this device's entries */
/** \name Locks */
/*@{*/
@@ -720,17 +733,9 @@ typedef struct drm_device {
struct drm_driver *driver;
drm_local_map_t *agp_buffer_map;
+ drm_head_t primary; /**< primary screen head */
} drm_device_t;
-typedef struct drm_minor {
- enum {
- DRM_MINOR_FREE = 0,
- DRM_MINOR_PRIMARY,
- } type;
- drm_device_t *dev;
- struct proc_dir_entry *dev_root; /**< proc directory entry */
-} drm_minor_t;
-
static __inline__ int drm_core_check_feature(struct drm_device *dev, int feature)
{
return ((dev->driver->driver_features & feature) ? 1 : 0);
@@ -807,7 +812,7 @@ extern void *drm_ioremap_nocache(unsigned long offset, unsigned long size,
drm_device_t *dev);
extern void drm_ioremapfree(void *pt, unsigned long size, drm_device_t *dev);
-extern DRM_AGP_MEM *drm_alloc_agp(int pages, u32 type);
+extern DRM_AGP_MEM *drm_alloc_agp(struct agp_bridge_data *bridge, int pages, u32 type);
extern int drm_free_agp(DRM_AGP_MEM *handle, int pages);
extern int drm_bind_agp(DRM_AGP_MEM *handle, unsigned int start);
extern int drm_unbind_agp(DRM_AGP_MEM *handle);
@@ -930,10 +935,10 @@ extern int drm_vblank_wait(drm_device_t *dev, unsigned int *vbl_seq);
extern void drm_vbl_send_signals( drm_device_t *dev );
/* AGP/GART support (drm_agpsupport.h) */
-extern drm_agp_head_t *drm_agp_init(void);
+extern drm_agp_head_t *drm_agp_init(drm_device_t *dev);
extern int drm_agp_acquire(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
-extern void drm_agp_do_release(void);
+extern void drm_agp_do_release(drm_device_t *dev);
extern int drm_agp_release(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern int drm_agp_enable(struct inode *inode, struct file *filp,
@@ -948,18 +953,20 @@ extern int drm_agp_unbind(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern int drm_agp_bind(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
-extern DRM_AGP_MEM *drm_agp_allocate_memory(size_t pages, u32 type);
+extern DRM_AGP_MEM *drm_agp_allocate_memory(struct agp_bridge_data *bridge, size_t pages, u32 type);
extern int drm_agp_free_memory(DRM_AGP_MEM *handle);
extern int drm_agp_bind_memory(DRM_AGP_MEM *handle, off_t start);
extern int drm_agp_unbind_memory(DRM_AGP_MEM *handle);
/* Stub support (drm_stub.h) */
-extern int drm_probe(struct pci_dev *pdev, const struct pci_device_id *ent, struct drm_driver *driver);
-
-extern int drm_put_minor(drm_device_t *dev);
+extern int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
+ struct drm_driver *driver);
+extern int drm_put_dev(drm_device_t * dev);
+extern int drm_get_head(drm_device_t * dev, drm_head_t *head);
+extern int drm_put_head(drm_head_t * head);
extern unsigned int drm_debug;
extern unsigned int drm_cards_limit;
-extern drm_minor_t *drm_minors;
+extern drm_head_t **drm_heads;
extern struct drm_sysfs_class *drm_class;
extern struct proc_dir_entry *drm_proc_root;
diff --git a/drivers/char/drm/drm_agpsupport.c b/drivers/char/drm/drm_agpsupport.c
index ea3ed218c280d..8d94c0b5fa44f 100644
--- a/drivers/char/drm/drm_agpsupport.c
+++ b/drivers/char/drm/drm_agpsupport.c
@@ -52,7 +52,7 @@ int drm_agp_info(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
DRM_AGP_KERN *kern;
drm_agp_info_t info;
@@ -91,15 +91,14 @@ int drm_agp_acquire(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
- int retcode;
+ drm_device_t *dev = priv->head->dev;
if (!dev->agp)
return -ENODEV;
if (dev->agp->acquired)
return -EBUSY;
- if ((retcode = agp_backend_acquire()))
- return retcode;
+ if (!(dev->agp->bridge = agp_backend_acquire(dev->pdev)))
+ return -ENODEV;
dev->agp->acquired = 1;
return 0;
}
@@ -119,11 +118,11 @@ int drm_agp_release(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
if (!dev->agp || !dev->agp->acquired)
return -EINVAL;
- agp_backend_release();
+ agp_backend_release(dev->agp->bridge);
dev->agp->acquired = 0;
return 0;
@@ -134,9 +133,9 @@ int drm_agp_release(struct inode *inode, struct file *filp,
*
* Calls agp_backend_release().
*/
-void drm_agp_do_release(void)
+void drm_agp_do_release(drm_device_t *dev)
{
- agp_backend_release();
+ agp_backend_release(dev->agp->bridge);
}
/**
@@ -155,7 +154,7 @@ int drm_agp_enable(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
drm_agp_mode_t mode;
if (!dev->agp || !dev->agp->acquired)
@@ -165,7 +164,7 @@ int drm_agp_enable(struct inode *inode, struct file *filp,
return -EFAULT;
dev->agp->mode = mode.mode;
- agp_enable(mode.mode);
+ agp_enable(dev->agp->bridge, mode.mode);
dev->agp->base = dev->agp->agp_info.aper_base;
dev->agp->enabled = 1;
return 0;
@@ -187,7 +186,7 @@ int drm_agp_alloc(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
drm_agp_buffer_t request;
drm_agp_mem_t *entry;
DRM_AGP_MEM *memory;
@@ -207,7 +206,7 @@ int drm_agp_alloc(struct inode *inode, struct file *filp,
pages = (request.size + PAGE_SIZE - 1) / PAGE_SIZE;
type = (u32) request.type;
- if (!(memory = drm_alloc_agp(pages, type))) {
+ if (!(memory = drm_alloc_agp(dev->agp->bridge, pages, type))) {
drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
return -ENOMEM;
}
@@ -272,7 +271,7 @@ int drm_agp_unbind(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
drm_agp_binding_t request;
drm_agp_mem_t *entry;
int ret;
@@ -308,7 +307,7 @@ int drm_agp_bind(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
drm_agp_binding_t request;
drm_agp_mem_t *entry;
int retcode;
@@ -349,7 +348,7 @@ int drm_agp_free(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
drm_agp_buffer_t request;
drm_agp_mem_t *entry;
@@ -381,14 +380,24 @@ int drm_agp_free(struct inode *inode, struct file *filp,
* \return pointer to a drm_agp_head structure.
*
*/
-drm_agp_head_t *drm_agp_init(void)
+drm_agp_head_t *drm_agp_init(drm_device_t *dev)
{
drm_agp_head_t *head = NULL;
if (!(head = drm_alloc(sizeof(*head), DRM_MEM_AGPLISTS)))
return NULL;
memset((void *)head, 0, sizeof(*head));
- agp_copy_info(&head->agp_info);
+ head->bridge = agp_find_bridge(dev->pdev);
+ if (!head->bridge) {
+ if (!(head->bridge = agp_backend_acquire(dev->pdev))) {
+ drm_free(head, sizeof(*head), DRM_MEM_AGPLISTS);
+ return NULL;
+ }
+ agp_copy_info(head->bridge, &head->agp_info);
+ agp_backend_release(head->bridge);
+ } else {
+ agp_copy_info(head->bridge, &head->agp_info);
+ }
if (head->agp_info.chipset == NOT_SUPPORTED) {
drm_free(head, sizeof(*head), DRM_MEM_AGPLISTS);
return NULL;
@@ -406,9 +415,9 @@ drm_agp_head_t *drm_agp_init(void)
}
/** Calls agp_allocate_memory() */
-DRM_AGP_MEM *drm_agp_allocate_memory(size_t pages, u32 type)
+DRM_AGP_MEM *drm_agp_allocate_memory(struct agp_bridge_data *bridge, size_t pages, u32 type)
{
- return agp_allocate_memory(pages, type);
+ return agp_allocate_memory(bridge, pages, type);
}
/** Calls agp_free_memory() */
diff --git a/drivers/char/drm/drm_auth.c b/drivers/char/drm/drm_auth.c
index 777c631cad60e..b428761c4e913 100644
--- a/drivers/char/drm/drm_auth.c
+++ b/drivers/char/drm/drm_auth.c
@@ -176,7 +176,7 @@ int drm_getmagic(struct inode *inode, struct file *filp,
static drm_magic_t sequence = 0;
static DEFINE_SPINLOCK(lock);
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
drm_auth_t auth;
/* Find unique magic */
@@ -214,7 +214,7 @@ int drm_authmagic(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
drm_auth_t auth;
drm_file_t *file;
diff --git a/drivers/char/drm/drm_bufs.c b/drivers/char/drm/drm_bufs.c
index 78320ace41bae..4113bcba67fe0 100644
--- a/drivers/char/drm/drm_bufs.c
+++ b/drivers/char/drm/drm_bufs.c
@@ -77,7 +77,7 @@ int drm_addmap( struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg )
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
drm_map_t *map;
drm_map_t __user *argp = (void __user *)arg;
drm_map_list_t *list;
@@ -221,7 +221,7 @@ int drm_rmmap(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
struct list_head *list;
drm_map_list_t *r_list = NULL;
drm_vma_entry_t *pt, *prev;
@@ -349,7 +349,7 @@ int drm_addbufs_agp( struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg )
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
drm_device_dma_t *dma = dev->dma;
drm_buf_desc_t request;
drm_buf_entry_t *entry;
@@ -514,7 +514,7 @@ int drm_addbufs_pci( struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg )
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
drm_device_dma_t *dma = dev->dma;
drm_buf_desc_t request;
int count;
@@ -744,7 +744,7 @@ int drm_addbufs_sg( struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg )
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
drm_device_dma_t *dma = dev->dma;
drm_buf_desc_t __user *argp = (void __user *)arg;
drm_buf_desc_t request;
@@ -925,7 +925,7 @@ int drm_addbufs( struct inode *inode, struct file *filp,
{
drm_buf_desc_t request;
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
return -EINVAL;
@@ -967,7 +967,7 @@ int drm_infobufs( struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg )
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
drm_device_dma_t *dma = dev->dma;
drm_buf_info_t request;
drm_buf_info_t __user *argp = (void __user *)arg;
@@ -1052,7 +1052,7 @@ int drm_markbufs( struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg )
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
drm_device_dma_t *dma = dev->dma;
drm_buf_desc_t request;
int order;
@@ -1101,7 +1101,7 @@ int drm_freebufs( struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg )
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
drm_device_dma_t *dma = dev->dma;
drm_buf_free_t request;
int i;
@@ -1158,7 +1158,7 @@ int drm_mapbufs( struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg )
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
drm_device_dma_t *dma = dev->dma;
drm_buf_map_t __user *argp = (void __user *)arg;
int retcode = 0;
diff --git a/drivers/char/drm/drm_context.c b/drivers/char/drm/drm_context.c
index 3a7637c5109e9..f15c86c578757 100644
--- a/drivers/char/drm/drm_context.c
+++ b/drivers/char/drm/drm_context.c
@@ -208,7 +208,7 @@ int drm_getsareactx(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
drm_ctx_priv_map_t __user *argp = (void __user *)arg;
drm_ctx_priv_map_t request;
drm_map_t *map;
@@ -247,7 +247,7 @@ int drm_setsareactx(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
drm_ctx_priv_map_t request;
drm_map_t *map = NULL;
drm_map_list_t *r_list = NULL;
@@ -395,7 +395,7 @@ int drm_addctx( struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg )
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
drm_ctx_list_t * ctx_entry;
drm_ctx_t __user *argp = (void __user *)arg;
drm_ctx_t ctx;
@@ -489,7 +489,7 @@ int drm_switchctx( struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg )
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
drm_ctx_t ctx;
if ( copy_from_user( &ctx, (drm_ctx_t __user *)arg, sizeof(ctx) ) )
@@ -514,7 +514,7 @@ int drm_newctx( struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg )
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
drm_ctx_t ctx;
if ( copy_from_user( &ctx, (drm_ctx_t __user *)arg, sizeof(ctx) ) )
@@ -541,7 +541,7 @@ int drm_rmctx( struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg )
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
drm_ctx_t ctx;
if ( copy_from_user( &ctx, (drm_ctx_t __user *)arg, sizeof(ctx) ) )
diff --git a/drivers/char/drm/drm_core.h b/drivers/char/drm/drm_core.h
index d4c612e2e5ab9..cc97bb906dda2 100644
--- a/drivers/char/drm/drm_core.h
+++ b/drivers/char/drm/drm_core.h
@@ -20,15 +20,15 @@
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
-#define DRIVER_AUTHOR "Gareth Hughes, Leif Delgass, José Fonseca, Jon Smirl"
+#define CORE_AUTHOR "Gareth Hughes, Leif Delgass, José Fonseca, Jon Smirl"
-#define DRIVER_NAME "drm"
-#define DRIVER_DESC "DRM shared core routines"
-#define DRIVER_DATE "20040925"
+#define CORE_NAME "drm"
+#define CORE_DESC "DRM shared core routines"
+#define CORE_DATE "20040925"
#define DRM_IF_MAJOR 1
#define DRM_IF_MINOR 2
-#define DRIVER_MAJOR 1
-#define DRIVER_MINOR 0
-#define DRIVER_PATCHLEVEL 0
+#define CORE_MAJOR 1
+#define CORE_MINOR 0
+#define CORE_PATCHLEVEL 0
diff --git a/drivers/char/drm/drm_drv.c b/drivers/char/drm/drm_drv.c
index 5845d986e6ecd..1e37ed0c6b8d7 100644
--- a/drivers/char/drm/drm_drv.c
+++ b/drivers/char/drm/drm_drv.c
@@ -15,10 +15,6 @@
* #define DRIVER_DESC "Matrox G200/G400"
* #define DRIVER_DATE "20001127"
*
- * #define DRIVER_MAJOR 2
- * #define DRIVER_MINOR 0
- * #define DRIVER_PATCHLEVEL 2
- *
* #define DRIVER_IOCTL_COUNT DRM_ARRAY_SIZE( mga_ioctls )
*
* #define drm_x mga_##x
@@ -144,23 +140,17 @@ int drm_takedown( drm_device_t *dev )
if (dev->driver->pretakedown)
dev->driver->pretakedown(dev);
+ if (dev->unique) {
+ drm_free(dev->unique, strlen(dev->unique) + 1, DRM_MEM_DRIVER);
+ dev->unique = NULL;
+ dev->unique_len = 0;
+ }
+
if ( dev->irq_enabled ) drm_irq_uninstall( dev );
down( &dev->struct_sem );
del_timer( &dev->timer );
- if ( dev->devname ) {
- drm_free( dev->devname, strlen( dev->devname ) + 1,
- DRM_MEM_DRIVER );
- dev->devname = NULL;
- }
-
- if ( dev->unique ) {
- drm_free( dev->unique, strlen( dev->unique ) + 1,
- DRM_MEM_DRIVER );
- dev->unique = NULL;
- dev->unique_len = 0;
- }
/* Clear pid list */
for ( i = 0 ; i < DRM_HASH_SIZE ; i++ ) {
for ( pt = dev->magiclist[i].head ; pt ; pt = next ) {
@@ -185,7 +175,7 @@ int drm_takedown( drm_device_t *dev )
}
dev->agp->memory = NULL;
- if ( dev->agp->acquired ) drm_agp_do_release();
+ if ( dev->agp->acquired ) drm_agp_do_release(dev);
dev->agp->acquired = 0;
dev->agp->enabled = 0;
@@ -307,7 +297,7 @@ int drm_init( struct drm_driver *driver )
while ((pdev = pci_get_subsys(pid->vendor, pid->device, pid->subvendor, pid->subdevice, pdev)) != NULL) {
/* stealth mode requires a manual probe */
pci_dev_get(pdev);
- drm_probe(pdev, pid, driver);
+ drm_get_dev(pdev, pid, driver);
}
}
return 0;
@@ -351,7 +341,8 @@ static void drm_cleanup( drm_device_t *dev )
if (dev->driver->postcleanup)
dev->driver->postcleanup(dev);
- if ( drm_put_minor(dev) )
+ drm_put_head(&dev->primary);
+ if ( drm_put_dev(dev) )
DRM_ERROR( "Cannot unload module\n" );
}
@@ -359,19 +350,19 @@ void drm_exit (struct drm_driver *driver)
{
int i;
drm_device_t *dev = NULL;
- drm_minor_t *minor;
+ drm_head_t *head;
DRM_DEBUG( "\n" );
for (i = 0; i < drm_cards_limit; i++) {
- minor = &drm_minors[i];
- if (!minor->dev)
+ head = drm_heads[i];
+ if (!head)
continue;
- if (minor->dev->driver!=driver)
+ if (!head->dev)
continue;
-
- dev = minor->dev;
-
+ if (head->dev->driver!=driver)
+ continue;
+ dev=head->dev;
}
if (dev) {
/* release the pci driver */
@@ -379,7 +370,6 @@ void drm_exit (struct drm_driver *driver)
pci_dev_put(dev->pdev);
drm_cleanup(dev);
}
-
DRM_INFO( "Module unloaded\n" );
}
EXPORT_SYMBOL(drm_exit);
@@ -395,9 +385,9 @@ static int __init drm_core_init(void)
int ret = -ENOMEM;
drm_cards_limit = (drm_cards_limit < DRM_MAX_MINOR + 1 ? drm_cards_limit : DRM_MAX_MINOR + 1);
- drm_minors = drm_calloc(drm_cards_limit,
- sizeof(*drm_minors), DRM_MEM_STUB);
- if(!drm_minors)
+ drm_heads = drm_calloc(drm_cards_limit,
+ sizeof(*drm_heads), DRM_MEM_STUB);
+ if(!drm_heads)
goto err_p1;
if (register_chrdev(DRM_MAJOR, "drm", &drm_stub_fops))
@@ -418,18 +408,14 @@ static int __init drm_core_init(void)
}
DRM_INFO( "Initialized %s %d.%d.%d %s\n",
- DRIVER_NAME,
- DRIVER_MAJOR,
- DRIVER_MINOR,
- DRIVER_PATCHLEVEL,
- DRIVER_DATE
- );
+ CORE_NAME, CORE_MAJOR, CORE_MINOR, CORE_PATCHLEVEL,
+ CORE_DATE);
return 0;
err_p3:
drm_sysfs_destroy(drm_class);
err_p2:
unregister_chrdev(DRM_MAJOR, "drm");
- drm_free(drm_minors, sizeof(*drm_minors) * drm_cards_limit, DRM_MEM_STUB);
+ drm_free(drm_heads, sizeof(*drm_heads) * drm_cards_limit, DRM_MEM_STUB);
err_p1:
return ret;
}
@@ -441,7 +427,7 @@ static void __exit drm_core_exit (void)
unregister_chrdev(DRM_MAJOR, "drm");
- drm_free(drm_minors, sizeof(*drm_minors) *
+ drm_free(drm_heads, sizeof(*drm_heads) *
drm_cards_limit, DRM_MEM_STUB);
}
@@ -465,7 +451,7 @@ int drm_version( struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg )
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
drm_version_t __user *argp = (void __user *)arg;
drm_version_t version;
int ret;
@@ -500,7 +486,7 @@ int drm_ioctl( struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg )
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
drm_ioctl_desc_t *ioctl;
drm_ioctl_t *func;
unsigned int nr = DRM_IOCTL_NR(cmd);
@@ -511,7 +497,7 @@ int drm_ioctl( struct inode *inode, struct file *filp,
++priv->ioctl_count;
DRM_DEBUG( "pid=%d, cmd=0x%02x, nr=0x%02x, dev 0x%lx, auth=%d\n",
- current->pid, cmd, nr, (long)old_encode_dev(dev->device),
+ current->pid, cmd, nr, (long)old_encode_dev(priv->head->device),
priv->authenticated );
if (nr < DRIVER_IOCTL_COUNT)
diff --git a/drivers/char/drm/drm_fops.c b/drivers/char/drm/drm_fops.c
index e967efbbe0547..906794247aeb8 100644
--- a/drivers/char/drm/drm_fops.c
+++ b/drivers/char/drm/drm_fops.c
@@ -143,8 +143,10 @@ int drm_open( struct inode *inode, struct file *filp )
if (!((minor >= 0) && (minor < drm_cards_limit)))
return -ENODEV;
- dev = drm_minors[minor].dev;
- if (!dev)
+ if (!drm_heads[minor])
+ return -ENODEV;
+
+ if (!(dev = drm_heads[minor]->dev))
return -ENODEV;
retcode = drm_open_helper( inode, filp, dev );
@@ -181,7 +183,7 @@ int drm_release( struct inode *inode, struct file *filp )
int retcode = 0;
lock_kernel();
- dev = priv->dev;
+ dev = priv->head->dev;
DRM_DEBUG( "open_count = %d\n", dev->open_count );
@@ -193,7 +195,7 @@ int drm_release( struct inode *inode, struct file *filp )
*/
DRM_DEBUG( "pid = %d, device = 0x%lx, open_count = %d\n",
- current->pid, (long)old_encode_dev(dev->device), dev->open_count );
+ current->pid, (long)old_encode_dev(priv->head->device), dev->open_count );
if ( priv->lock_count && dev->lock.hw_lock &&
_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) &&
@@ -358,7 +360,7 @@ int drm_open_helper(struct inode *inode, struct file *filp, drm_device_t *dev)
priv->uid = current->euid;
priv->pid = current->pid;
priv->minor = minor;
- priv->dev = dev;
+ priv->head = drm_heads[minor];
priv->ioctl_count = 0;
priv->authenticated = capable(CAP_SYS_ADMIN);
priv->lock_count = 0;
@@ -412,10 +414,10 @@ out_free:
int drm_flush(struct file *filp)
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n",
- current->pid, (long)old_encode_dev(dev->device), dev->open_count);
+ current->pid, (long)old_encode_dev(priv->head->device), dev->open_count);
return 0;
}
EXPORT_SYMBOL(drm_flush);
@@ -424,10 +426,10 @@ EXPORT_SYMBOL(drm_flush);
int drm_fasync(int fd, struct file *filp, int on)
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
int retcode;
- DRM_DEBUG("fd = %d, device = 0x%lx\n", fd, (long)old_encode_dev(dev->device));
+ 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;
diff --git a/drivers/char/drm/drm_ioctl.c b/drivers/char/drm/drm_ioctl.c
index 6168509742948..39afda0ccabe3 100644
--- a/drivers/char/drm/drm_ioctl.c
+++ b/drivers/char/drm/drm_ioctl.c
@@ -53,7 +53,7 @@ int drm_getunique(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
drm_unique_t __user *argp = (void __user *)arg;
drm_unique_t u;
@@ -87,7 +87,7 @@ int drm_setunique(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
drm_unique_t u;
int domain, bus, slot, func, ret;
@@ -173,7 +173,7 @@ int drm_getmap( struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg )
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
drm_map_t __user *argp = (void __user *)arg;
drm_map_t map;
drm_map_list_t *r_list = NULL;
@@ -233,7 +233,7 @@ int drm_getclient( struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg )
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
drm_client_t __user *argp = (void __user *)arg;
drm_client_t client;
drm_file_t *pt;
@@ -277,7 +277,7 @@ int drm_getstats( struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg )
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
drm_stats_t stats;
int i;
@@ -326,6 +326,8 @@ int drm_setversion(DRM_IOCTL_ARGS)
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;
diff --git a/drivers/char/drm/drm_irq.c b/drivers/char/drm/drm_irq.c
index 0547a90b0f349..2e236ebcf27b3 100644
--- a/drivers/char/drm/drm_irq.c
+++ b/drivers/char/drm/drm_irq.c
@@ -54,7 +54,7 @@ int drm_irq_by_busid(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
drm_irq_busid_t __user *argp = (void __user *)arg;
drm_irq_busid_t p;
@@ -196,7 +196,7 @@ int drm_control( struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg )
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
drm_control_t ctl;
/* if we haven't irq we fallback for compatibility reasons - this used to be a separate function in drm_dma.h */
@@ -243,7 +243,7 @@ int drm_control( struct inode *inode, struct file *filp,
int drm_wait_vblank( DRM_IOCTL_ARGS )
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
drm_wait_vblank_t __user *argp = (void __user *)data;
drm_wait_vblank_t vblwait;
struct timeval now;
diff --git a/drivers/char/drm/drm_lock.c b/drivers/char/drm/drm_lock.c
index e511464bfd02f..d0d6fc6616253 100644
--- a/drivers/char/drm/drm_lock.c
+++ b/drivers/char/drm/drm_lock.c
@@ -50,7 +50,7 @@ int drm_lock( struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg )
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
DECLARE_WAITQUEUE( entry, current );
drm_lock_t lock;
int ret = 0;
@@ -145,7 +145,7 @@ int drm_unlock( struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg )
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
drm_lock_t lock;
if ( copy_from_user( &lock, (drm_lock_t __user *)arg, sizeof(lock) ) )
diff --git a/drivers/char/drm/drm_memory.c b/drivers/char/drm/drm_memory.c
index 81f109b38eef2..7f53f756c0521 100644
--- a/drivers/char/drm/drm_memory.c
+++ b/drivers/char/drm/drm_memory.c
@@ -155,9 +155,9 @@ void drm_free_pages(unsigned long address, int order, int area)
#if __OS_HAS_AGP
/** Wrapper around agp_allocate_memory() */
-DRM_AGP_MEM *drm_alloc_agp(int pages, u32 type)
+DRM_AGP_MEM *drm_alloc_agp(struct agp_bridge_data *bridge, int pages, u32 type)
{
- return drm_agp_allocate_memory(pages, type);
+ return drm_agp_allocate_memory(bridge, pages, type);
}
/** Wrapper around agp_free_memory() */
diff --git a/drivers/char/drm/drm_os_linux.h b/drivers/char/drm/drm_os_linux.h
index 3247e14b564fd..b14cd370dea5e 100644
--- a/drivers/char/drm/drm_os_linux.h
+++ b/drivers/char/drm/drm_os_linux.h
@@ -35,7 +35,7 @@
#define DRM_MEMORYBARRIER() mb()
/** DRM device local declaration */
#define DRM_DEVICE drm_file_t *priv = filp->private_data; \
- drm_device_t *dev = priv->dev
+ drm_device_t *dev = priv->head->dev
/** IRQ handler arguments and return type and values */
#define DRM_IRQ_ARGS int irq, void *arg, struct pt_regs *regs
@@ -89,7 +89,7 @@ static __inline__ int mtrr_del (int reg, unsigned long base,
copy_to_user(arg1, arg2, arg3)
/* Macros for copyfrom user, but checking readability only once */
#define DRM_VERIFYAREA_READ( uaddr, size ) \
- verify_area( VERIFY_READ, uaddr, size )
+ (access_ok( VERIFY_READ, uaddr, size ) ? 0 : -EFAULT)
#define DRM_COPY_FROM_USER_UNCHECKED(arg1, arg2, arg3) \
__copy_from_user(arg1, arg2, arg3)
#define DRM_COPY_TO_USER_UNCHECKED(arg1, arg2, arg3) \
diff --git a/drivers/char/drm/drm_pciids.h b/drivers/char/drm/drm_pciids.h
index 5d10ae302b75b..54a2914e3a321 100644
--- a/drivers/char/drm/drm_pciids.h
+++ b/drivers/char/drm/drm_pciids.h
@@ -50,6 +50,7 @@
{0x1002, 0x5158, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV200}, \
{0x1002, 0x5159, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \
{0x1002, 0x515A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \
+ {0x1002, 0x515E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \
{0x1002, 0x5168, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
{0x1002, 0x5169, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
{0x1002, 0x516A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
@@ -65,7 +66,7 @@
{0x1002, 0x5963, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
{0x1002, 0x5964, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
{0x1002, 0x5968, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
- {0x1002, 0x5969, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
+ {0x1002, 0x5969, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \
{0x1002, 0x596A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
{0x1002, 0x596B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
{0x1002, 0x5c61, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280|CHIP_IS_MOBILITY}, \
@@ -218,6 +219,6 @@
{0x8086, 0x3582, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
{0x8086, 0x2572, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
{0x8086, 0x2582, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
- {0x8086, 0x2982, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+ {0x8086, 0x2592, 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 6906f70662fa4..6e06e8c6a5167 100644
--- a/drivers/char/drm/drm_proc.c
+++ b/drivers/char/drm/drm_proc.c
@@ -175,10 +175,10 @@ static int drm_name_info(char *buf, char **start, off_t offset, int request,
*eof = 0;
if (dev->unique) {
- DRM_PROC_PRINT("%s 0x%lx %s\n",
- dev->driver->pci_driver.name, (long)old_encode_dev(dev->device), dev->unique);
+ DRM_PROC_PRINT("%s %s %s\n",
+ dev->driver->pci_driver.name, pci_name(dev->pdev), dev->unique);
} else {
- DRM_PROC_PRINT("%s 0x%lx\n", dev->driver->pci_driver.name, (long)old_encode_dev(dev->device));
+ DRM_PROC_PRINT("%s %s\n", dev->driver->pci_driver.name, pci_name(dev->pdev));
}
if (len > request + offset) return request;
diff --git a/drivers/char/drm/drm_scatter.c b/drivers/char/drm/drm_scatter.c
index 5611bada92c85..54fddb6ea2d13 100644
--- a/drivers/char/drm/drm_scatter.c
+++ b/drivers/char/drm/drm_scatter.c
@@ -65,7 +65,7 @@ int drm_sg_alloc( struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg )
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
drm_scatter_gather_t __user *argp = (void __user *)arg;
drm_scatter_gather_t request;
drm_sg_mem_t *entry;
@@ -205,7 +205,7 @@ int drm_sg_free( struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg )
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
drm_scatter_gather_t request;
drm_sg_mem_t *entry;
diff --git a/drivers/char/drm/drm_stub.c b/drivers/char/drm/drm_stub.c
index 1ff42134ebaae..8ccbdef7bb3ec 100644
--- a/drivers/char/drm/drm_stub.c
+++ b/drivers/char/drm/drm_stub.c
@@ -40,16 +40,16 @@ unsigned int drm_cards_limit = 16; /* Enough for one machine */
unsigned int drm_debug = 0; /* 1 to enable debug output */
EXPORT_SYMBOL(drm_debug);
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_AUTHOR( CORE_AUTHOR );
+MODULE_DESCRIPTION( CORE_DESC );
MODULE_LICENSE("GPL and additional rights");
-MODULE_PARM_DESC(drm_cards_limit, "Maximum number of graphics cards");
-MODULE_PARM_DESC(drm_debug, "Enable debug output");
+MODULE_PARM_DESC(cards_limit, "Maximum number of graphics cards");
+MODULE_PARM_DESC(debug, "Enable debug output");
module_param_named(cards_limit, drm_cards_limit, int, 0444);
module_param_named(debug, drm_debug, int, 0666);
-drm_minor_t *drm_minors;
+drm_head_t **drm_heads;
struct drm_sysfs_class *drm_class;
struct proc_dir_entry *drm_proc_root;
@@ -91,7 +91,7 @@ static int drm_fill_in_dev(drm_device_t *dev, struct pci_dev *pdev, const struct
goto error_out_unreg;
if (drm_core_has_AGP(dev)) {
- dev->agp = drm_agp_init();
+ dev->agp = drm_agp_init(dev);
if (drm_core_check_feature(dev, DRIVER_REQUIRE_AGP) && (dev->agp == NULL)) {
DRM_ERROR( "Cannot initialize the agpgart module.\n" );
retcode = -EINVAL;
@@ -112,12 +112,6 @@ static int drm_fill_in_dev(drm_device_t *dev, struct pci_dev *pdev, const struct
goto error_out_unreg;
}
- dev->device = MKDEV(DRM_MAJOR, dev->minor );
-
- /* postinit is a required function to display the signon banner */
- if ((retcode = dev->driver->postinit(dev, ent->driver_data)))
- goto error_out_unreg;
-
return 0;
error_out_unreg:
@@ -146,8 +140,10 @@ int drm_stub_open(struct inode *inode, struct file *filp)
if (!((minor >= 0) && (minor < drm_cards_limit)))
return -ENODEV;
- dev = drm_minors[minor].dev;
- if (!dev)
+ if (!drm_heads[minor])
+ return -ENODEV;
+
+ if (!(dev = drm_heads[minor]->dev))
return -ENODEV;
old_fops = filp->f_op;
@@ -161,10 +157,11 @@ int drm_stub_open(struct inode *inode, struct file *filp)
return err;
}
+
/**
- * Get a device minor number.
+ * Register.
*
- * \param pdev PCI device structure
+ * \param pdev - PCI device structure
* \param ent entry from the PCI ID table with device type flags
* \return zero on success or a negative number on failure.
*
@@ -172,50 +169,86 @@ int drm_stub_open(struct inode *inode, struct file *filp)
* then register the character device and inter module information.
* Try and register, if we fail to register, backout previous work.
*/
-int drm_probe(struct pci_dev *pdev, const struct pci_device_id *ent, struct drm_driver *driver)
+int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
+ struct drm_driver *driver)
{
- struct class_device *dev_class;
drm_device_t *dev;
int ret;
- int minor;
- drm_minor_t *minors = &drm_minors[0];
DRM_DEBUG("\n");
- for (minor = 0; minor < drm_cards_limit; minor++, minors++) {
- if (minors->type == DRM_MINOR_FREE) {
+ dev = drm_calloc(1, sizeof(*dev), DRM_MEM_STUB);
+ if (!dev)
+ return -ENOMEM;
- DRM_DEBUG("assigning minor %d\n", minor);
- dev = drm_calloc(1, sizeof(*dev), DRM_MEM_STUB);
- if (!dev)
- return -ENOMEM;
+ pci_enable_device(pdev);
- *minors = (drm_minor_t){.dev = dev, .type=DRM_MINOR_PRIMARY};
- dev->minor = minor;
+ if ((ret = drm_fill_in_dev(dev, pdev, ent, driver))) {
+ printk(KERN_ERR "DRM: Fill_in_dev failed.\n");
+ goto err_g1;
+ }
+ if ((ret = drm_get_head(dev, &dev->primary)))
+ goto err_g1;
- pci_enable_device(pdev);
+ /* 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;
- if ((ret=drm_fill_in_dev(dev, pdev, ent, driver))) {
- printk(KERN_ERR "DRM: Fill_in_dev failed.\n");
- goto err_g1;
- }
- if ((ret = drm_proc_init(dev, minor, drm_proc_root, &minors->dev_root))) {
+ return 0;
+
+err_g1:
+ drm_free(dev, sizeof(*dev), DRM_MEM_STUB);
+ return ret;
+}
+EXPORT_SYMBOL(drm_get_dev);
+
+/**
+ * Get a secondary minor number.
+ *
+ * \param dev device data structure
+ * \param sec-minor structure to hold the assigned minor
+ * \return negative number on failure.
+ *
+ * Search an empty entry and initialize it to the given parameters, and
+ * create the proc init entry via proc_init(). This routines assigns
+ * minor numbers to secondary heads of multi-headed cards
+ */
+int drm_get_head(drm_device_t *dev, drm_head_t *head)
+{
+ drm_head_t **heads = drm_heads;
+ int ret;
+ int minor;
+
+ DRM_DEBUG("\n");
+
+ for (minor = 0; minor < drm_cards_limit; minor++, heads++) {
+ if (!*heads) {
+
+ *head = (drm_head_t) {
+ .dev = dev,
+ .device = MKDEV(DRM_MAJOR, minor),
+ .minor = minor,
+ };
+
+ if ((ret = drm_proc_init(dev, minor, drm_proc_root, &head->dev_root))) {
printk (KERN_ERR "DRM: Failed to initialize /proc/dri.\n");
goto err_g1;
}
- dev_class = drm_sysfs_device_add(drm_class,
- MKDEV(DRM_MAJOR,
- minor),
- &pdev->dev,
- "card%d", minor);
- if (IS_ERR(dev_class)) {
+ head->dev_class = drm_sysfs_device_add(drm_class,
+ MKDEV(DRM_MAJOR,
+ minor),
+ &dev->pdev->dev,
+ "card%d", minor);
+ if (IS_ERR(head->dev_class)) {
printk(KERN_ERR "DRM: Error sysfs_device_add.\n");
- ret = PTR_ERR(dev_class);
+ ret = PTR_ERR(head->dev_class);
goto err_g2;
}
-
+ *heads = head;
+
DRM_DEBUG("new minor assigned %d\n", minor);
return 0;
}
@@ -223,36 +256,63 @@ int drm_probe(struct pci_dev *pdev, const struct pci_device_id *ent, struct drm_
DRM_ERROR("out of minors\n");
return -ENOMEM;
err_g2:
- drm_proc_cleanup(minor, drm_proc_root, minors->dev_root);
+ drm_proc_cleanup(minor, drm_proc_root, head->dev_root);
err_g1:
- *minors = (drm_minor_t){.dev = NULL, .type = DRM_MINOR_FREE};
- drm_free(dev, sizeof(*dev), DRM_MEM_STUB);
+ *head = (drm_head_t) {.dev = NULL};
return ret;
}
-EXPORT_SYMBOL(drm_probe);
/**
* Put a device minor number.
*
- * \param minor minor number.
- * \return always zero.
+ * \param dev device data structure
+ * \return always zero
*
- * Cleans up the proc resources. If a minor is zero then release the foreign
- * "drm" data, otherwise unregisters the "drm" data, frees the stub list and
- * unregisters the character device.
+ * Cleans up the proc resources. If it is the last minor then release the foreign
+ * "drm" data, otherwise unregisters the "drm" data, frees the dev list and
+ * unregisters the character device.
*/
-int drm_put_minor(drm_device_t *dev)
+int drm_put_dev(drm_device_t * dev)
{
- drm_minor_t *minors = &drm_minors[dev->minor];
+ DRM_DEBUG("release primary %s\n", dev->driver->pci_driver.name);
+
+ if (dev->unique) {
+ drm_free(dev->unique, strlen(dev->unique) + 1, DRM_MEM_DRIVER);
+ dev->unique = NULL;
+ dev->unique_len = 0;
+ }
+ if (dev->devname) {
+ drm_free(dev->devname, strlen(dev->devname) + 1,
+ DRM_MEM_DRIVER);
+ dev->devname = NULL;
+ }
+ drm_free(dev, sizeof(*dev), DRM_MEM_STUB);
+ return 0;
+}
+
+/**
+ * Put a secondary minor number.
+ *
+ * \param sec_minor - structure to be released
+ * \return always zero
+ *
+ * Cleans up the proc resources. Not legal for this to be the
+ * last minor released.
+ *
+ */
+int drm_put_head(drm_head_t *head)
+{
+ int minor = head->minor;
- DRM_DEBUG("release minor %d\n", dev->minor);
+ DRM_DEBUG("release secondary minor %d\n", minor);
- drm_proc_cleanup(dev->minor, drm_proc_root, minors->dev_root);
- drm_sysfs_device_remove(MKDEV(DRM_MAJOR, dev->minor));
+ drm_proc_cleanup(minor, drm_proc_root, head->dev_root);
+ drm_sysfs_device_remove(MKDEV(DRM_MAJOR, head->minor));
- *minors = (drm_minor_t){.dev = NULL, .type = DRM_MINOR_FREE};
- drm_free(dev, sizeof(*dev), DRM_MEM_STUB);
+ *head = (drm_head_t){.dev = NULL};
+
+ drm_heads[minor] = NULL;
return 0;
}
diff --git a/drivers/char/drm/drm_sysfs.c b/drivers/char/drm/drm_sysfs.c
index 6c9a830bac1be..2fc10c4bbcdfd 100644
--- a/drivers/char/drm/drm_sysfs.c
+++ b/drivers/char/drm/drm_sysfs.c
@@ -55,8 +55,8 @@ static void drm_sysfs_class_release(struct class *class)
/* Display the version of drm_core. This doesn't work right in current design */
static ssize_t version_show(struct class *dev, char *buf)
{
- return sprintf(buf, "%s %d.%d.%d %s\n", DRIVER_NAME, DRIVER_MAJOR,
- DRIVER_MINOR, DRIVER_PATCHLEVEL, DRIVER_DATE);
+ return sprintf(buf, "%s %d.%d.%d %s\n", CORE_NAME, CORE_MAJOR,
+ CORE_MINOR, CORE_PATCHLEVEL, CORE_DATE);
}
static CLASS_ATTR(version, S_IRUGO, version_show, NULL);
diff --git a/drivers/char/drm/drm_vm.c b/drivers/char/drm/drm_vm.c
index f10ad6cfa904b..fc72f30f312b9 100644
--- a/drivers/char/drm/drm_vm.c
+++ b/drivers/char/drm/drm_vm.c
@@ -54,7 +54,7 @@ static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma,
unsigned long address)
{
drm_file_t *priv = vma->vm_file->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
drm_map_t *map = NULL;
drm_map_list_t *r_list;
struct list_head *list;
@@ -166,7 +166,7 @@ static __inline__ struct page *drm_do_vm_shm_nopage(struct vm_area_struct *vma,
void drm_vm_shm_close(struct vm_area_struct *vma)
{
drm_file_t *priv = vma->vm_file->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
drm_vma_entry_t *pt, *prev, *next;
drm_map_t *map;
drm_map_list_t *r_list;
@@ -246,7 +246,7 @@ static __inline__ struct page *drm_do_vm_dma_nopage(struct vm_area_struct *vma,
unsigned long address)
{
drm_file_t *priv = vma->vm_file->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
drm_device_dma_t *dma = dev->dma;
unsigned long offset;
unsigned long page_nr;
@@ -281,7 +281,7 @@ static __inline__ struct page *drm_do_vm_sg_nopage(struct vm_area_struct *vma,
{
drm_map_t *map = (drm_map_t *)vma->vm_private_data;
drm_file_t *priv = vma->vm_file->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
drm_sg_mem_t *entry = dev->sg;
unsigned long offset;
unsigned long map_offset;
@@ -402,7 +402,7 @@ static struct vm_operations_struct drm_vm_sg_ops = {
void drm_vm_open(struct vm_area_struct *vma)
{
drm_file_t *priv = vma->vm_file->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
drm_vma_entry_t *vma_entry;
DRM_DEBUG("0x%08lx,0x%08lx\n",
@@ -431,7 +431,7 @@ void drm_vm_open(struct vm_area_struct *vma)
void drm_vm_close(struct vm_area_struct *vma)
{
drm_file_t *priv = vma->vm_file->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
drm_vma_entry_t *pt, *prev;
DRM_DEBUG("0x%08lx,0x%08lx\n",
@@ -471,7 +471,7 @@ int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma)
unsigned long length = vma->vm_end - vma->vm_start;
lock_kernel();
- dev = priv->dev;
+ dev = priv->head->dev;
dma = dev->dma;
DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n",
vma->vm_start, vma->vm_end, VM_OFFSET(vma));
@@ -528,7 +528,7 @@ EXPORT_SYMBOL(drm_core_get_reg_ofs);
int drm_mmap(struct file *filp, struct vm_area_struct *vma)
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
drm_map_t *map = NULL;
drm_map_list_t *r_list;
unsigned long offset = 0;
@@ -625,12 +625,12 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
#endif
offset = dev->driver->get_reg_ofs(dev);
#ifdef __sparc__
- if (io_remap_page_range(DRM_RPR_ARG(vma) vma->vm_start,
- VM_OFFSET(vma) + offset,
+ if (io_remap_pfn_range(DRM_RPR_ARG(vma) vma->vm_start,
+ (VM_OFFSET(vma) + offset) >> PAGE_SHIFT,
vma->vm_end - vma->vm_start,
- vma->vm_page_prot, 0))
+ vma->vm_page_prot))
#else
- if (remap_pfn_range(DRM_RPR_ARG(vma) vma->vm_start,
+ if (io_remap_pfn_range(vma, vma->vm_start,
(VM_OFFSET(vma) + offset) >> PAGE_SHIFT,
vma->vm_end - vma->vm_start,
vma->vm_page_prot))
diff --git a/drivers/char/drm/i810_dma.c b/drivers/char/drm/i810_dma.c
index 3d6200ccd7017..24857cc6c23b3 100644
--- a/drivers/char/drm/i810_dma.c
+++ b/drivers/char/drm/i810_dma.c
@@ -50,26 +50,6 @@
#define up_write up
#endif
-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 }
-};
-
-int i810_max_ioctl = DRM_ARRAY_SIZE(i810_ioctls);
-
static drm_buf_t *i810_freelist_get(drm_device_t *dev)
{
drm_device_dma_t *dma = dev->dma;
@@ -128,7 +108,7 @@ int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
drm_i810_buf_priv_t *buf_priv;
lock_kernel();
- dev = priv->dev;
+ dev = priv->head->dev;
dev_priv = dev->dev_private;
buf = dev_priv->mmap_buffer;
buf_priv = buf->dev_private;
@@ -139,7 +119,7 @@ int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
buf_priv->currently_mapped = I810_BUF_MAPPED;
unlock_kernel();
- if (remap_pfn_range(DRM_RPR_ARG(vma) vma->vm_start,
+ if (io_remap_pfn_range(vma, vma->vm_start,
VM_OFFSET(vma) >> PAGE_SHIFT,
vma->vm_end - vma->vm_start,
vma->vm_page_prot)) return -EAGAIN;
@@ -149,7 +129,7 @@ int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
static int i810_map_buffer(drm_buf_t *buf, struct file *filp)
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
drm_i810_buf_priv_t *buf_priv = buf->dev_private;
drm_i810_private_t *dev_priv = dev->dev_private;
struct file_operations *old_fops;
@@ -229,7 +209,7 @@ static int i810_dma_get_buffer(drm_device_t *dev, drm_i810_dma_t *d,
return retcode;
}
-int i810_dma_cleanup(drm_device_t *dev)
+static int i810_dma_cleanup(drm_device_t *dev)
{
drm_device_dma_t *dma = dev->dma;
@@ -455,7 +435,7 @@ static int i810_dma_initialize(drm_device_t *dev,
* If it isn't then we have a v1.1 client. Fix up params.
* If it is, then we have a 1.2 client... get the rest of the data.
*/
-int i810_dma_init_compat(drm_i810_init_t *init, unsigned long arg)
+static int i810_dma_init_compat(drm_i810_init_t *init, unsigned long arg)
{
/* Get v1.1 init data */
@@ -487,11 +467,11 @@ int i810_dma_init_compat(drm_i810_init_t *init, unsigned long arg)
return 0;
}
-int i810_dma_init(struct inode *inode, struct file *filp,
+static int i810_dma_init(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
drm_i810_private_t *dev_priv;
drm_i810_init_t init;
int retcode = 0;
@@ -942,7 +922,7 @@ static void i810_dma_dispatch_flip( drm_device_t *dev )
}
-void i810_dma_quiescent(drm_device_t *dev)
+static void i810_dma_quiescent(drm_device_t *dev)
{
drm_i810_private_t *dev_priv = dev->dev_private;
RING_LOCALS;
@@ -1027,7 +1007,7 @@ int i810_flush_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
LOCK_TEST_WITH_RETURN(dev, filp);
@@ -1036,11 +1016,11 @@ int i810_flush_ioctl(struct inode *inode, struct file *filp,
}
-int i810_dma_vertex(struct inode *inode, struct file *filp,
+static int i810_dma_vertex(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
drm_device_dma_t *dma = dev->dma;
drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
u32 *hw_status = dev_priv->hw_status_page;
@@ -1073,11 +1053,11 @@ int i810_dma_vertex(struct inode *inode, struct file *filp,
-int i810_clear_bufs(struct inode *inode, struct file *filp,
+static int i810_clear_bufs(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
drm_i810_clear_t clear;
if (copy_from_user(&clear, (drm_i810_clear_t __user *)arg, sizeof(clear)))
@@ -1096,11 +1076,11 @@ int i810_clear_bufs(struct inode *inode, struct file *filp,
return 0;
}
-int i810_swap_bufs(struct inode *inode, struct file *filp,
+static int i810_swap_bufs(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
DRM_DEBUG("i810_swap_bufs\n");
@@ -1110,11 +1090,11 @@ int i810_swap_bufs(struct inode *inode, struct file *filp,
return 0;
}
-int i810_getage(struct inode *inode, struct file *filp, unsigned int cmd,
+static int i810_getage(struct inode *inode, struct file *filp, unsigned int cmd,
unsigned long arg)
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
u32 *hw_status = dev_priv->hw_status_page;
drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
@@ -1124,11 +1104,11 @@ int i810_getage(struct inode *inode, struct file *filp, unsigned int cmd,
return 0;
}
-int i810_getbuf(struct inode *inode, struct file *filp, unsigned int cmd,
+static int i810_getbuf(struct inode *inode, struct file *filp, unsigned int cmd,
unsigned long arg)
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
int retcode = 0;
drm_i810_dma_t d;
drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
@@ -1155,17 +1135,15 @@ int i810_getbuf(struct inode *inode, struct file *filp, unsigned int cmd,
return retcode;
}
-int i810_copybuf(struct inode *inode,
- struct file *filp,
- unsigned int cmd,
- unsigned long arg)
+static int i810_copybuf(struct inode *inode,
+ struct file *filp, unsigned int cmd, unsigned long arg)
{
/* Never copy - 2.4.x doesn't need it */
return 0;
}
-int i810_docopy(struct inode *inode, struct file *filp, unsigned int cmd,
- unsigned long arg)
+static int i810_docopy(struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg)
{
/* Never copy - 2.4.x doesn't need it */
return 0;
@@ -1234,11 +1212,11 @@ static void i810_dma_dispatch_mc(drm_device_t *dev, drm_buf_t *buf, int used,
ADVANCE_LP_RING();
}
-int i810_dma_mc(struct inode *inode, struct file *filp,
+static int i810_dma_mc(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
drm_device_dma_t *dma = dev->dma;
drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
u32 *hw_status = dev_priv->hw_status_page;
@@ -1265,21 +1243,21 @@ int i810_dma_mc(struct inode *inode, struct file *filp,
return 0;
}
-int i810_rstatus(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
+static int i810_rstatus(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
return (int)(((u32 *)(dev_priv->hw_status_page))[4]);
}
-int i810_ov0_info(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
+static int i810_ov0_info(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
drm_i810_overlay_t data;
@@ -1290,11 +1268,11 @@ int i810_ov0_info(struct inode *inode, struct file *filp,
return 0;
}
-int i810_fstatus(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
+static int i810_fstatus(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
LOCK_TEST_WITH_RETURN(dev, filp);
@@ -1302,11 +1280,11 @@ int i810_fstatus(struct inode *inode, struct file *filp,
return I810_READ(0x30008);
}
-int i810_ov0_flip(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
+static int i810_ov0_flip(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
LOCK_TEST_WITH_RETURN(dev, filp);
@@ -1330,7 +1308,7 @@ static void i810_do_init_pageflip( drm_device_t *dev )
dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
}
-int i810_do_cleanup_pageflip( drm_device_t *dev )
+static int i810_do_cleanup_pageflip( drm_device_t *dev )
{
drm_i810_private_t *dev_priv = dev->dev_private;
@@ -1342,11 +1320,11 @@ int i810_do_cleanup_pageflip( drm_device_t *dev )
return 0;
}
-int i810_flip_bufs(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
+static int i810_flip_bufs(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
drm_i810_private_t *dev_priv = dev->dev_private;
DRM_DEBUG("%s\n", __FUNCTION__);
@@ -1365,6 +1343,16 @@ void i810_driver_pretakedown(drm_device_t *dev)
i810_dma_cleanup( dev );
}
+void i810_driver_prerelease(drm_device_t *dev, DRMFILE filp)
+{
+ if (dev->dev_private) {
+ drm_i810_private_t *dev_priv = dev->dev_private;
+ if (dev_priv->page_flipping) {
+ i810_do_cleanup_pageflip(dev);
+ }
+ }
+}
+
void i810_driver_release(drm_device_t *dev, struct file *filp)
{
i810_reclaim_buffers(dev, filp);
@@ -1376,4 +1364,22 @@ int i810_driver_dma_quiescent(drm_device_t *dev)
return 0;
}
+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 }
+};
+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 2929ad27789dc..ff51b3259af92 100644
--- a/drivers/char/drm/i810_drv.c
+++ b/drivers/char/drm/i810_drv.c
@@ -53,7 +53,7 @@ static int postinit( struct drm_device *dev, unsigned long flags )
DRIVER_MINOR,
DRIVER_PATCHLEVEL,
DRIVER_DATE,
- dev->minor,
+ dev->primary.minor,
pci_pretty_name(dev->pdev)
);
return 0;
@@ -83,6 +83,7 @@ static struct drm_driver driver = {
.driver_features = 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,
.release = i810_driver_release,
.dma_quiescent = i810_driver_dma_quiescent,
.reclaim_buffers = i810_reclaim_buffers,
diff --git a/drivers/char/drm/i810_drv.h b/drivers/char/drm/i810_drv.h
index 49b3c95e0c6db..fa23ca454e579 100644
--- a/drivers/char/drm/i810_drv.h
+++ b/drivers/char/drm/i810_drv.h
@@ -114,57 +114,13 @@ typedef struct drm_i810_private {
} drm_i810_private_t;
/* i810_dma.c */
-extern int i810_dma_schedule(drm_device_t *dev, int locked);
-extern int i810_getbuf(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
-extern int i810_dma_init(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
-extern int i810_dma_cleanup(drm_device_t *dev);
-extern int i810_flush_ioctl(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
extern void i810_reclaim_buffers(drm_device_t *dev, struct file *filp);
-extern int i810_getage(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
extern int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma);
-/* Obsolete:
- */
-extern int i810_copybuf(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
-/* Obsolete:
- */
-extern int i810_docopy(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
-
-extern int i810_rstatus(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
-extern int i810_ov0_info(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
-extern int i810_fstatus(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
-extern int i810_ov0_flip(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
-extern int i810_dma_mc(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
-
-
-extern void i810_dma_quiescent(drm_device_t *dev);
-
-extern int i810_dma_vertex(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
-
-extern int i810_swap_bufs(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
-
-extern int i810_clear_bufs(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
-
-extern int i810_flip_bufs(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
-
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);
#define I810_BASE(reg) ((unsigned long) \
dev_priv->mmio_map->handle)
diff --git a/drivers/char/drm/i830_dma.c b/drivers/char/drm/i830_dma.c
index 9afb67705a721..98adccf8e4341 100644
--- a/drivers/char/drm/i830_dma.c
+++ b/drivers/char/drm/i830_dma.c
@@ -52,42 +52,6 @@
#define up_write up
#endif
-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 }
-};
-
-int i830_max_ioctl = DRM_ARRAY_SIZE(i830_ioctls);
-
-static inline void i830_print_status_page(drm_device_t *dev)
-{
- drm_device_dma_t *dma = dev->dma;
- drm_i830_private_t *dev_priv = dev->dev_private;
- u32 *temp = dev_priv->hw_status_page;
- int i;
-
- DRM_DEBUG( "hw_status: Interrupt Status : %x\n", temp[0]);
- DRM_DEBUG( "hw_status: LpRing Head ptr : %x\n", temp[1]);
- DRM_DEBUG( "hw_status: IRing Head ptr : %x\n", temp[2]);
- DRM_DEBUG( "hw_status: Reserved : %x\n", temp[3]);
- DRM_DEBUG( "hw_status: Driver Counter : %d\n", temp[5]);
- for(i = 9; i < dma->buf_count + 9; i++) {
- DRM_DEBUG( "buffer status idx : %d used: %d\n", i - 9, temp[i]);
- }
-}
-
static drm_buf_t *i830_freelist_get(drm_device_t *dev)
{
drm_device_dma_t *dma = dev->dma;
@@ -146,7 +110,7 @@ int i830_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
drm_i830_buf_priv_t *buf_priv;
lock_kernel();
- dev = priv->dev;
+ dev = priv->head->dev;
dev_priv = dev->dev_private;
buf = dev_priv->mmap_buffer;
buf_priv = buf->dev_private;
@@ -157,7 +121,7 @@ int i830_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
buf_priv->currently_mapped = I830_BUF_MAPPED;
unlock_kernel();
- if (remap_pfn_range(DRM_RPR_ARG(vma) vma->vm_start,
+ if (io_remap_pfn_range(vma, vma->vm_start,
VM_OFFSET(vma) >> PAGE_SHIFT,
vma->vm_end - vma->vm_start,
vma->vm_page_prot)) return -EAGAIN;
@@ -167,7 +131,7 @@ int i830_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
static int i830_map_buffer(drm_buf_t *buf, struct file *filp)
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
drm_i830_buf_priv_t *buf_priv = buf->dev_private;
drm_i830_private_t *dev_priv = dev->dev_private;
struct file_operations *old_fops;
@@ -247,7 +211,7 @@ static int i830_dma_get_buffer(drm_device_t *dev, drm_i830_dma_t *d,
return retcode;
}
-int i830_dma_cleanup(drm_device_t *dev)
+static int i830_dma_cleanup(drm_device_t *dev)
{
drm_device_dma_t *dma = dev->dma;
@@ -479,11 +443,11 @@ static int i830_dma_initialize(drm_device_t *dev,
return 0;
}
-int i830_dma_init(struct inode *inode, struct file *filp,
+static int i830_dma_init(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
drm_i830_private_t *dev_priv;
drm_i830_init_t init;
int retcode = 0;
@@ -1252,7 +1216,7 @@ static void i830_dma_dispatch_vertex(drm_device_t *dev,
}
-void i830_dma_quiescent(drm_device_t *dev)
+static void i830_dma_quiescent(drm_device_t *dev)
{
drm_i830_private_t *dev_priv = dev->dev_private;
RING_LOCALS;
@@ -1329,11 +1293,11 @@ void i830_reclaim_buffers(drm_device_t *dev, struct file *filp)
}
}
-int i830_flush_ioctl(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
+static int i830_flush_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
LOCK_TEST_WITH_RETURN(dev, filp);
@@ -1341,11 +1305,11 @@ int i830_flush_ioctl(struct inode *inode, struct file *filp,
return 0;
}
-int i830_dma_vertex(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
+static int i830_dma_vertex(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
drm_device_dma_t *dma = dev->dma;
drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private;
u32 *hw_status = dev_priv->hw_status_page;
@@ -1373,11 +1337,11 @@ int i830_dma_vertex(struct inode *inode, struct file *filp,
return 0;
}
-int i830_clear_bufs(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
+static int i830_clear_bufs(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
drm_i830_clear_t clear;
if (copy_from_user(&clear, (drm_i830_clear_t __user *)arg, sizeof(clear)))
@@ -1397,11 +1361,11 @@ int i830_clear_bufs(struct inode *inode, struct file *filp,
return 0;
}
-int i830_swap_bufs(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
+static int i830_swap_bufs(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
DRM_DEBUG("i830_swap_bufs\n");
@@ -1425,7 +1389,7 @@ static void i830_do_init_pageflip( drm_device_t *dev )
dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
}
-int i830_do_cleanup_pageflip( drm_device_t *dev )
+static int i830_do_cleanup_pageflip( drm_device_t *dev )
{
drm_i830_private_t *dev_priv = dev->dev_private;
@@ -1437,11 +1401,11 @@ int i830_do_cleanup_pageflip( drm_device_t *dev )
return 0;
}
-int i830_flip_bufs(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
+static int i830_flip_bufs(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
drm_i830_private_t *dev_priv = dev->dev_private;
DRM_DEBUG("%s\n", __FUNCTION__);
@@ -1455,11 +1419,11 @@ int i830_flip_bufs(struct inode *inode, struct file *filp,
return 0;
}
-int i830_getage(struct inode *inode, struct file *filp, unsigned int cmd,
- unsigned long arg)
+static int i830_getage(struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg)
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private;
u32 *hw_status = dev_priv->hw_status_page;
drm_i830_sarea_t *sarea_priv = (drm_i830_sarea_t *)
@@ -1469,11 +1433,11 @@ int i830_getage(struct inode *inode, struct file *filp, unsigned int cmd,
return 0;
}
-int i830_getbuf(struct inode *inode, struct file *filp, unsigned int cmd,
- unsigned long arg)
+static int i830_getbuf(struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg)
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
int retcode = 0;
drm_i830_dma_t d;
drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private;
@@ -1501,28 +1465,26 @@ int i830_getbuf(struct inode *inode, struct file *filp, unsigned int cmd,
return retcode;
}
-int i830_copybuf(struct inode *inode,
- struct file *filp,
- unsigned int cmd,
- unsigned long arg)
+static int i830_copybuf(struct inode *inode,
+ struct file *filp, unsigned int cmd, unsigned long arg)
{
/* Never copy - 2.4.x doesn't need it */
return 0;
}
-int i830_docopy(struct inode *inode, struct file *filp, unsigned int cmd,
- unsigned long arg)
+static int i830_docopy(struct inode *inode, struct file *filp, unsigned int cmd,
+ unsigned long arg)
{
return 0;
}
-int i830_getparam( struct inode *inode, struct file *filp, unsigned int cmd,
- unsigned long arg )
+static int i830_getparam( struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg )
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
drm_i830_private_t *dev_priv = dev->dev_private;
drm_i830_getparam_t param;
int value;
@@ -1552,11 +1514,11 @@ int i830_getparam( struct inode *inode, struct file *filp, unsigned int cmd,
}
-int i830_setparam( struct inode *inode, struct file *filp, unsigned int cmd,
- unsigned long arg )
+static int i830_setparam( struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg )
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
drm_i830_private_t *dev_priv = dev->dev_private;
drm_i830_setparam_t param;
@@ -1585,6 +1547,16 @@ void i830_driver_pretakedown(drm_device_t *dev)
i830_dma_cleanup( dev );
}
+void i830_driver_prerelease(drm_device_t *dev, DRMFILE filp)
+{
+ if (dev->dev_private) {
+ drm_i830_private_t *dev_priv = dev->dev_private;
+ if (dev_priv->page_flipping) {
+ i830_do_cleanup_pageflip(dev);
+ }
+ }
+}
+
void i830_driver_release(drm_device_t *dev, struct file *filp)
{
i830_reclaim_buffers(dev, filp);
@@ -1596,3 +1568,21 @@ int i830_driver_dma_quiescent(drm_device_t *dev)
return 0;
}
+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 }
+};
+
+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 da41a973a9a8e..aa80ad6a5ee01 100644
--- a/drivers/char/drm/i830_drv.c
+++ b/drivers/char/drm/i830_drv.c
@@ -54,7 +54,7 @@ int postinit( struct drm_device *dev, unsigned long flags )
DRIVER_MINOR,
DRIVER_PATCHLEVEL,
DRIVER_DATE,
- dev->minor,
+ dev->primary.minor,
pci_pretty_name(dev->pdev)
);
return 0;
@@ -87,6 +87,7 @@ static struct drm_driver driver = {
#endif
.dev_priv_size = sizeof(drm_i830_buf_priv_t),
.pretakedown = i830_driver_pretakedown,
+ .prerelease = i830_driver_prerelease,
.release = i830_driver_release,
.dma_quiescent = i830_driver_dma_quiescent,
.reclaim_buffers = i830_reclaim_buffers,
diff --git a/drivers/char/drm/i830_drv.h b/drivers/char/drm/i830_drv.h
index 0535cb9e5bbe5..d4b2d093d6abe 100644
--- a/drivers/char/drm/i830_drv.h
+++ b/drivers/char/drm/i830_drv.h
@@ -120,51 +120,16 @@ typedef struct drm_i830_private {
} drm_i830_private_t;
- /* i830_dma.c */
-extern int i830_dma_schedule(drm_device_t *dev, int locked);
-extern int i830_getbuf(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
-extern int i830_dma_init(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
-extern int i830_dma_cleanup(drm_device_t *dev);
-extern int i830_flush_ioctl(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
+/* i830_dma.c */
extern void i830_reclaim_buffers(drm_device_t *dev, struct file *filp);
-extern int i830_getage(struct inode *inode, struct file *filp, unsigned int cmd,
- unsigned long arg);
-extern int i830_mmap_buffers(struct file *filp, struct vm_area_struct *vma);
-extern int i830_copybuf(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
-extern int i830_docopy(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
-
-extern void i830_dma_quiescent(drm_device_t *dev);
-
-extern int i830_dma_vertex(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
-
-extern int i830_swap_bufs(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
-
-extern int i830_clear_bufs(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
-extern int i830_flip_bufs(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
-
-extern int i830_getparam( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg );
-
-extern int i830_setparam( struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg );
+extern int i830_mmap_buffers(struct file *filp, struct vm_area_struct *vma);
/* i830_irq.c */
extern int i830_irq_emit( struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg );
extern int i830_irq_wait( struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg );
-extern int i830_wait_irq(drm_device_t *dev, int irq_nr);
-extern int i830_emit_irq(drm_device_t *dev);
extern irqreturn_t i830_driver_irq_handler( DRM_IRQ_ARGS );
extern void i830_driver_irq_preinstall( drm_device_t *dev );
@@ -173,6 +138,7 @@ 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_dma_quiescent(drm_device_t *dev);
+extern void i830_driver_prerelease(drm_device_t *dev, DRMFILE filp);
#define I830_BASE(reg) ((unsigned long) \
dev_priv->mmio_map->handle)
diff --git a/drivers/char/drm/i830_irq.c b/drivers/char/drm/i830_irq.c
index 097744550650a..6d7729ffe2dc1 100644
--- a/drivers/char/drm/i830_irq.c
+++ b/drivers/char/drm/i830_irq.c
@@ -123,7 +123,7 @@ int i830_irq_emit( struct inode *inode, struct file *filp, unsigned int cmd,
unsigned long arg )
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
drm_i830_private_t *dev_priv = dev->dev_private;
drm_i830_irq_emit_t emit;
int result;
@@ -155,7 +155,7 @@ int i830_irq_wait( struct inode *inode, struct file *filp, unsigned int cmd,
unsigned long arg )
{
drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->dev;
+ drm_device_t *dev = priv->head->dev;
drm_i830_private_t *dev_priv = dev->dev_private;
drm_i830_irq_wait_t irqwait;
diff --git a/drivers/char/drm/i915_drv.c b/drivers/char/drm/i915_drv.c
index 8967805213c8f..002b7082e21b0 100644
--- a/drivers/char/drm/i915_drv.c
+++ b/drivers/char/drm/i915_drv.c
@@ -29,7 +29,7 @@ int postinit( struct drm_device *dev, unsigned long flags )
DRIVER_MINOR,
DRIVER_PATCHLEVEL,
DRIVER_DATE,
- dev->minor,
+ dev->primary.minor,
pci_pretty_name(dev->pdev)
);
return 0;
diff --git a/drivers/char/drm/mga_dma.c b/drivers/char/drm/mga_dma.c
index 5e3c3133d9b5f..832eaf8a5068d 100644
--- a/drivers/char/drm/mga_dma.c
+++ b/drivers/char/drm/mga_dma.c
@@ -41,6 +41,7 @@
#define MGA_DEFAULT_USEC_TIMEOUT 10000
#define MGA_FREELIST_DEBUG 0
+static int mga_do_cleanup_dma( drm_device_t *dev );
/* ================================================================
* Engine control
@@ -68,25 +69,7 @@ int mga_do_wait_for_idle( drm_mga_private_t *dev_priv )
return DRM_ERR(EBUSY);
}
-int mga_do_dma_idle( drm_mga_private_t *dev_priv )
-{
- u32 status = 0;
- int i;
- DRM_DEBUG( "\n" );
-
- for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
- status = MGA_READ( MGA_STATUS ) & MGA_DMA_IDLE_MASK;
- if ( status == MGA_ENDPRDMASTS ) return 0;
- DRM_UDELAY( 1 );
- }
-
-#if MGA_DMA_DEBUG
- DRM_ERROR( "failed! status=0x%08x\n", status );
-#endif
- return DRM_ERR(EBUSY);
-}
-
-int mga_do_dma_reset( drm_mga_private_t *dev_priv )
+static int mga_do_dma_reset( drm_mga_private_t *dev_priv )
{
drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
drm_mga_primary_buffer_t *primary = &dev_priv->prim;
@@ -110,44 +93,6 @@ int mga_do_dma_reset( drm_mga_private_t *dev_priv )
return 0;
}
-int mga_do_engine_reset( drm_mga_private_t *dev_priv )
-{
- DRM_DEBUG( "\n" );
-
- /* Okay, so we've completely screwed up and locked the engine.
- * How about we clean up after ourselves?
- */
- MGA_WRITE( MGA_RST, MGA_SOFTRESET );
- DRM_UDELAY( 15 ); /* Wait at least 10 usecs */
- MGA_WRITE( MGA_RST, 0 );
-
- /* Initialize the registers that get clobbered by the soft
- * reset. Many of the core register values survive a reset,
- * but the drawing registers are basically all gone.
- *
- * 3D clients should probably die after calling this. The X
- * server should reset the engine state to known values.
- */
-#if 0
- MGA_WRITE( MGA_PRIMPTR,
- virt_to_bus((void *)dev_priv->prim.status_page) |
- MGA_PRIMPTREN0 |
- MGA_PRIMPTREN1 );
-#endif
-
- MGA_WRITE( MGA_ICLEAR, MGA_SOFTRAPICLR );
- MGA_WRITE( MGA_IEN, MGA_SOFTRAPIEN );
-
- /* The primary DMA stream should look like new right about now.
- */
- mga_do_dma_reset( dev_priv );
-
- /* This bad boy will never fail.
- */
- return 0;
-}
-
-
/* ================================================================
* Primary DMA stream
*/
@@ -625,7 +570,7 @@ static int mga_do_init_dma( drm_device_t *dev, drm_mga_init_t *init )
return 0;
}
-int mga_do_cleanup_dma( drm_device_t *dev )
+static int mga_do_cleanup_dma( drm_device_t *dev )
{
DRM_DEBUG( "\n" );
diff --git a/drivers/char/drm/mga_drv.c b/drivers/char/drm/mga_drv.c
index bc5fb9db6a2ac..22dab3e9d92a0 100644
--- a/drivers/char/drm/mga_drv.c
+++ b/drivers/char/drm/mga_drv.c
@@ -51,7 +51,7 @@ static int postinit( struct drm_device *dev, unsigned long flags )
DRIVER_MINOR,
DRIVER_PATCHLEVEL,
DRIVER_DATE,
- dev->minor,
+ dev->primary.minor,
pci_pretty_name(dev->pdev)
);
return 0;
diff --git a/drivers/char/drm/mga_drv.h b/drivers/char/drm/mga_drv.h
index 3d8e9aefd8d21..1d84a1eb34dbb 100644
--- a/drivers/char/drm/mga_drv.h
+++ b/drivers/char/drm/mga_drv.h
@@ -121,10 +121,6 @@ extern void mga_driver_pretakedown(drm_device_t *dev);
extern int mga_driver_dma_quiescent(drm_device_t *dev);
extern int mga_do_wait_for_idle( drm_mga_private_t *dev_priv );
-extern int mga_do_dma_idle( drm_mga_private_t *dev_priv );
-extern int mga_do_dma_reset( drm_mga_private_t *dev_priv );
-extern int mga_do_engine_reset( drm_mga_private_t *dev_priv );
-extern int mga_do_cleanup_dma( drm_device_t *dev );
extern void mga_do_dma_flush( drm_mga_private_t *dev_priv );
extern void mga_do_dma_wrap_start( drm_mga_private_t *dev_priv );
@@ -132,15 +128,6 @@ extern void mga_do_dma_wrap_end( drm_mga_private_t *dev_priv );
extern int mga_freelist_put( drm_device_t *dev, drm_buf_t *buf );
- /* mga_state.c */
-extern int mga_dma_clear( DRM_IOCTL_ARGS );
-extern int mga_dma_swap( DRM_IOCTL_ARGS );
-extern int mga_dma_vertex( DRM_IOCTL_ARGS );
-extern int mga_dma_indices( DRM_IOCTL_ARGS );
-extern int mga_dma_iload( DRM_IOCTL_ARGS );
-extern int mga_dma_blit( DRM_IOCTL_ARGS );
-extern int mga_getparam( DRM_IOCTL_ARGS );
-
/* mga_warp.c */
extern int mga_warp_install_microcode( drm_mga_private_t *dev_priv );
extern int mga_warp_init( drm_mga_private_t *dev_priv );
diff --git a/drivers/char/drm/mga_state.c b/drivers/char/drm/mga_state.c
index dbc878f84bb6c..3c7a8f5ba5013 100644
--- a/drivers/char/drm/mga_state.c
+++ b/drivers/char/drm/mga_state.c
@@ -37,21 +37,6 @@
#include "mga_drm.h"
#include "mga_drv.h"
-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 },
-};
-
-int mga_max_ioctl = DRM_ARRAY_SIZE(mga_ioctls);
-
/* ================================================================
* DMA hardware state programming functions
*/
@@ -893,7 +878,7 @@ static void mga_dma_dispatch_blit( drm_device_t *dev,
*
*/
-int mga_dma_clear( DRM_IOCTL_ARGS )
+static int mga_dma_clear( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
drm_mga_private_t *dev_priv = dev->dev_private;
@@ -918,7 +903,7 @@ int mga_dma_clear( DRM_IOCTL_ARGS )
return 0;
}
-int mga_dma_swap( DRM_IOCTL_ARGS )
+static int mga_dma_swap( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
drm_mga_private_t *dev_priv = dev->dev_private;
@@ -940,7 +925,7 @@ int mga_dma_swap( DRM_IOCTL_ARGS )
return 0;
}
-int mga_dma_vertex( DRM_IOCTL_ARGS )
+static int mga_dma_vertex( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
drm_mga_private_t *dev_priv = dev->dev_private;
@@ -979,7 +964,7 @@ int mga_dma_vertex( DRM_IOCTL_ARGS )
return 0;
}
-int mga_dma_indices( DRM_IOCTL_ARGS )
+static int mga_dma_indices( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
drm_mga_private_t *dev_priv = dev->dev_private;
@@ -1018,7 +1003,7 @@ int mga_dma_indices( DRM_IOCTL_ARGS )
return 0;
}
-int mga_dma_iload( DRM_IOCTL_ARGS )
+static int mga_dma_iload( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
drm_device_dma_t *dma = dev->dma;
@@ -1060,7 +1045,7 @@ int mga_dma_iload( DRM_IOCTL_ARGS )
return 0;
}
-int mga_dma_blit( DRM_IOCTL_ARGS )
+static int mga_dma_blit( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
drm_mga_private_t *dev_priv = dev->dev_private;
@@ -1089,7 +1074,7 @@ int mga_dma_blit( DRM_IOCTL_ARGS )
return 0;
}
-int mga_getparam( DRM_IOCTL_ARGS )
+static int mga_getparam( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
drm_mga_private_t *dev_priv = dev->dev_private;
@@ -1121,3 +1106,18 @@ int mga_getparam( DRM_IOCTL_ARGS )
return 0;
}
+
+drm_ioctl_desc_t mga_ioctls[] = {
+ [DRM_IOCTL_NR(DRM_MGA_INIT)] = { mga_dma_init, 1, 1 },
+ [DRM_IOCTL_NR(DRM_MGA_FLUSH)] = { mga_dma_flush, 1, 0 },
+ [DRM_IOCTL_NR(DRM_MGA_RESET)] = { mga_dma_reset, 1, 0 },
+ [DRM_IOCTL_NR(DRM_MGA_SWAP)] = { mga_dma_swap, 1, 0 },
+ [DRM_IOCTL_NR(DRM_MGA_CLEAR)] = { mga_dma_clear, 1, 0 },
+ [DRM_IOCTL_NR(DRM_MGA_VERTEX)] = { mga_dma_vertex, 1, 0 },
+ [DRM_IOCTL_NR(DRM_MGA_INDICES)] = { mga_dma_indices, 1, 0 },
+ [DRM_IOCTL_NR(DRM_MGA_ILOAD)] = { mga_dma_iload, 1, 0 },
+ [DRM_IOCTL_NR(DRM_MGA_BLIT)] = { mga_dma_blit, 1, 0 },
+ [DRM_IOCTL_NR(DRM_MGA_GETPARAM)]= { mga_getparam, 1, 0 },
+};
+
+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 379f8323061a9..08ed8d01d9d95 100644
--- a/drivers/char/drm/r128_cce.c
+++ b/drivers/char/drm/r128_cce.c
@@ -80,7 +80,7 @@ static u32 r128_cce_microcode[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
-int R128_READ_PLL(drm_device_t *dev, int addr)
+static int R128_READ_PLL(drm_device_t *dev, int addr)
{
drm_r128_private_t *dev_priv = dev->dev_private;
@@ -808,7 +808,7 @@ static int r128_freelist_init( drm_device_t *dev )
}
#endif
-drm_buf_t *r128_freelist_get( drm_device_t *dev )
+static drm_buf_t *r128_freelist_get( drm_device_t *dev )
{
drm_device_dma_t *dma = dev->dma;
drm_r128_private_t *dev_priv = dev->dev_private;
diff --git a/drivers/char/drm/r128_drv.c b/drivers/char/drm/r128_drv.c
index 9983241054b9e..ced63810237b0 100644
--- a/drivers/char/drm/r128_drv.c
+++ b/drivers/char/drm/r128_drv.c
@@ -45,7 +45,7 @@ static int postinit( struct drm_device *dev, unsigned long flags )
DRIVER_MINOR,
DRIVER_PATCHLEVEL,
DRIVER_DATE,
- dev->minor,
+ dev->primary.minor,
pci_pretty_name(dev->pdev)
);
return 0;
diff --git a/drivers/char/drm/r128_drv.h b/drivers/char/drm/r128_drv.h
index e04d87dfb0640..cf1aa5df459e0 100644
--- a/drivers/char/drm/r128_drv.h
+++ b/drivers/char/drm/r128_drv.h
@@ -139,27 +139,13 @@ extern int r128_cce_idle( DRM_IOCTL_ARGS );
extern int r128_engine_reset( DRM_IOCTL_ARGS );
extern int r128_fullscreen( DRM_IOCTL_ARGS );
extern int r128_cce_buffers( DRM_IOCTL_ARGS );
-extern int r128_getparam( DRM_IOCTL_ARGS );
extern void r128_freelist_reset( drm_device_t *dev );
-extern drm_buf_t *r128_freelist_get( drm_device_t *dev );
extern int r128_wait_ring( drm_r128_private_t *dev_priv, int n );
extern int r128_do_cce_idle( drm_r128_private_t *dev_priv );
extern int r128_do_cleanup_cce( drm_device_t *dev );
-extern int r128_do_cleanup_pageflip( drm_device_t *dev );
-
- /* r128_state.c */
-extern int r128_cce_clear( DRM_IOCTL_ARGS );
-extern int r128_cce_swap( DRM_IOCTL_ARGS );
-extern int r128_cce_flip( DRM_IOCTL_ARGS );
-extern int r128_cce_vertex( DRM_IOCTL_ARGS );
-extern int r128_cce_indices( DRM_IOCTL_ARGS );
-extern int r128_cce_blit( DRM_IOCTL_ARGS );
-extern int r128_cce_depth( DRM_IOCTL_ARGS );
-extern int r128_cce_stipple( DRM_IOCTL_ARGS );
-extern int r128_cce_indirect( DRM_IOCTL_ARGS );
extern int r128_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence);
@@ -406,8 +392,6 @@ do { \
R128_WRITE(R128_CLOCK_CNTL_DATA, (val)); \
} while (0)
-extern int R128_READ_PLL(drm_device_t *dev, int addr);
-
#define CCE_PACKET0( reg, n ) (R128_CCE_PACKET0 | \
((n) << 16) | ((reg) >> 2))
diff --git a/drivers/char/drm/r128_state.c b/drivers/char/drm/r128_state.c
index 60c7743122bdc..38b3cbd0bbba4 100644
--- a/drivers/char/drm/r128_state.c
+++ b/drivers/char/drm/r128_state.c
@@ -32,27 +32,6 @@
#include "r128_drm.h"
#include "r128_drv.h"
-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 },
-};
-
-int r128_max_ioctl = DRM_ARRAY_SIZE(r128_ioctls);
/* ================================================================
* CCE hardware state programming functions
@@ -1281,7 +1260,7 @@ static void r128_cce_dispatch_stipple( drm_device_t *dev, u32 *stipple )
* IOCTL functions
*/
-int r128_cce_clear( DRM_IOCTL_ARGS )
+static int r128_cce_clear( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
drm_r128_private_t *dev_priv = dev->dev_private;
@@ -1349,7 +1328,7 @@ int r128_do_cleanup_pageflip( drm_device_t *dev )
* They can & should be intermixed to support multiple 3d windows.
*/
-int r128_cce_flip( DRM_IOCTL_ARGS )
+static int r128_cce_flip( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
drm_r128_private_t *dev_priv = dev->dev_private;
@@ -1368,7 +1347,7 @@ int r128_cce_flip( DRM_IOCTL_ARGS )
return 0;
}
-int r128_cce_swap( DRM_IOCTL_ARGS )
+static int r128_cce_swap( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
drm_r128_private_t *dev_priv = dev->dev_private;
@@ -1390,7 +1369,7 @@ int r128_cce_swap( DRM_IOCTL_ARGS )
return 0;
}
-int r128_cce_vertex( DRM_IOCTL_ARGS )
+static int r128_cce_vertex( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
drm_r128_private_t *dev_priv = dev->dev_private;
@@ -1450,7 +1429,7 @@ int r128_cce_vertex( DRM_IOCTL_ARGS )
return 0;
}
-int r128_cce_indices( DRM_IOCTL_ARGS )
+static int r128_cce_indices( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
drm_r128_private_t *dev_priv = dev->dev_private;
@@ -1522,7 +1501,7 @@ int r128_cce_indices( DRM_IOCTL_ARGS )
return 0;
}
-int r128_cce_blit( DRM_IOCTL_ARGS )
+static int r128_cce_blit( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
drm_device_dma_t *dma = dev->dma;
@@ -1552,7 +1531,7 @@ int r128_cce_blit( DRM_IOCTL_ARGS )
return ret;
}
-int r128_cce_depth( DRM_IOCTL_ARGS )
+static int r128_cce_depth( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
drm_r128_private_t *dev_priv = dev->dev_private;
@@ -1582,7 +1561,7 @@ int r128_cce_depth( DRM_IOCTL_ARGS )
return ret;
}
-int r128_cce_stipple( DRM_IOCTL_ARGS )
+static int r128_cce_stipple( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
drm_r128_private_t *dev_priv = dev->dev_private;
@@ -1606,7 +1585,7 @@ int r128_cce_stipple( DRM_IOCTL_ARGS )
return 0;
}
-int r128_cce_indirect( DRM_IOCTL_ARGS )
+static int r128_cce_indirect( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
drm_r128_private_t *dev_priv = dev->dev_private;
@@ -1682,7 +1661,7 @@ int r128_cce_indirect( DRM_IOCTL_ARGS )
return 0;
}
-int r128_getparam( DRM_IOCTL_ARGS )
+static int r128_getparam( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
drm_r128_private_t *dev_priv = dev->dev_private;
@@ -1730,3 +1709,24 @@ void r128_driver_pretakedown(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 },
+};
+
+int r128_max_ioctl = DRM_ARRAY_SIZE(r128_ioctls);
diff --git a/drivers/char/drm/radeon_cp.c b/drivers/char/drm/radeon_cp.c
index 9176d9d8e3ffd..20bcf872b3488 100644
--- a/drivers/char/drm/radeon_cp.c
+++ b/drivers/char/drm/radeon_cp.c
@@ -35,6 +35,7 @@
#define RADEON_FIFO_DEBUG 0
+static int radeon_do_cleanup_cp( drm_device_t *dev );
/* CP microcode (from ATI) */
static u32 R200_cp_microcode[][2] = {
@@ -815,7 +816,7 @@ static u32 R300_cp_microcode[][2] = {
{ 0000000000, 0000000000 },
};
-int RADEON_READ_PLL(drm_device_t *dev, int addr)
+static int RADEON_READ_PLL(drm_device_t *dev, int addr)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -1538,7 +1539,7 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
return 0;
}
-int radeon_do_cleanup_cp( drm_device_t *dev )
+static int radeon_do_cleanup_cp( drm_device_t *dev )
{
drm_radeon_private_t *dev_priv = dev->dev_private;
DRM_DEBUG( "\n" );
diff --git a/drivers/char/drm/radeon_drm.h b/drivers/char/drm/radeon_drm.h
index f51c119177f93..c1e62d047989a 100644
--- a/drivers/char/drm/radeon_drm.h
+++ b/drivers/char/drm/radeon_drm.h
@@ -146,8 +146,14 @@
#define RADEON_EMIT_PP_TEX_SIZE_2 75
#define R200_EMIT_RB3D_BLENDCOLOR 76
#define R200_EMIT_TCL_POINT_SPRITE_CNTL 77
-#define RADEON_MAX_STATE_PACKETS 78
-
+#define RADEON_EMIT_PP_CUBIC_FACES_0 78
+#define RADEON_EMIT_PP_CUBIC_OFFSETS_T0 79
+#define RADEON_EMIT_PP_CUBIC_FACES_1 80
+#define RADEON_EMIT_PP_CUBIC_OFFSETS_T1 81
+#define RADEON_EMIT_PP_CUBIC_FACES_2 82
+#define RADEON_EMIT_PP_CUBIC_OFFSETS_T2 83
+#define R200_EMIT_PP_TRI_PERF_CNTL 84
+#define RADEON_MAX_STATE_PACKETS 85
/* Commands understood by cmd_buffer ioctl. More can be added but
* obviously these can't be removed or changed:
diff --git a/drivers/char/drm/radeon_drv.c b/drivers/char/drm/radeon_drv.c
index bb4e06fb5e057..7b983d96e53b7 100644
--- a/drivers/char/drm/radeon_drv.c
+++ b/drivers/char/drm/radeon_drv.c
@@ -46,7 +46,7 @@ static int postinit( struct drm_device *dev, unsigned long flags )
DRIVER_MINOR,
DRIVER_PATCHLEVEL,
DRIVER_DATE,
- dev->minor,
+ dev->primary.minor,
pci_pretty_name(dev->pdev)
);
return 0;
diff --git a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h
index ce4ea6969ea5f..5837098afae81 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 "20050125"
+#define DRIVER_DATE "20050311"
/* Interface history:
*
@@ -78,9 +78,13 @@
* - Add hyperz support, add hyperz flags to clear ioctl.
* 1.14- Add support for color tiling
* - Add R100/R200 surface allocation/free support
+ * 1.15- Add support for texture micro tiling
+ * - Add support for r100 cube maps
+ * 1.16- Add R200_EMIT_PP_TRI_PERF_CNTL packet to support brilinear
+ * texture filtering on r200
*/
#define DRIVER_MAJOR 1
-#define DRIVER_MINOR 14
+#define DRIVER_MINOR 16
#define DRIVER_PATCHLEVEL 0
#define GET_RING_HEAD(dev_priv) DRM_READ32( (dev_priv)->ring_rptr, 0 )
@@ -284,42 +288,20 @@ extern drm_buf_t *radeon_freelist_get( drm_device_t *dev );
extern int radeon_wait_ring( drm_radeon_private_t *dev_priv, int n );
extern int radeon_do_cp_idle( drm_radeon_private_t *dev_priv );
-extern int radeon_do_cleanup_cp( drm_device_t *dev );
-extern int radeon_do_cleanup_pageflip( drm_device_t *dev );
extern int radeon_driver_preinit(struct drm_device *dev, unsigned long flags);
extern int radeon_driver_postcleanup(struct drm_device *dev);
- /* radeon_state.c */
-extern int radeon_cp_clear( DRM_IOCTL_ARGS );
-extern int radeon_cp_swap( DRM_IOCTL_ARGS );
-extern int radeon_cp_vertex( DRM_IOCTL_ARGS );
-extern int radeon_cp_indices( DRM_IOCTL_ARGS );
-extern int radeon_cp_texture( DRM_IOCTL_ARGS );
-extern int radeon_cp_stipple( DRM_IOCTL_ARGS );
-extern int radeon_cp_indirect( DRM_IOCTL_ARGS );
-extern int radeon_cp_vertex2( DRM_IOCTL_ARGS );
-extern int radeon_cp_cmdbuf( DRM_IOCTL_ARGS );
-extern int radeon_cp_getparam( DRM_IOCTL_ARGS );
-extern int radeon_cp_setparam( DRM_IOCTL_ARGS );
-extern int radeon_cp_flip( DRM_IOCTL_ARGS );
-
extern int radeon_mem_alloc( DRM_IOCTL_ARGS );
extern int radeon_mem_free( DRM_IOCTL_ARGS );
extern int radeon_mem_init_heap( DRM_IOCTL_ARGS );
extern void radeon_mem_takedown( struct mem_block **heap );
extern void radeon_mem_release( DRMFILE filp, struct mem_block *heap );
-extern int radeon_surface_alloc(DRM_IOCTL_ARGS);
-extern int radeon_surface_free(DRM_IOCTL_ARGS);
/* radeon_irq.c */
extern int radeon_irq_emit( DRM_IOCTL_ARGS );
extern int radeon_irq_wait( DRM_IOCTL_ARGS );
-extern int radeon_emit_and_wait_irq(drm_device_t *dev);
-extern int radeon_wait_irq(drm_device_t *dev, int swi_nr);
-extern int radeon_emit_irq(drm_device_t *dev);
-
extern void radeon_do_release(drm_device_t *dev);
extern int radeon_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence);
extern irqreturn_t radeon_driver_irq_handler( DRM_IRQ_ARGS );
@@ -672,6 +654,8 @@ extern int radeon_postcleanup( struct drm_device *dev );
# define RADEON_3D_DRAW_IMMD 0x00002900
# define RADEON_3D_DRAW_INDX 0x00002A00
# define RADEON_3D_LOAD_VBPNTR 0x00002F00
+# define RADEON_MPEG_IDCT_MACROBLOCK 0x00003000
+# define RADEON_MPEG_IDCT_MACROBLOCK_REV 0x00003100
# define RADEON_3D_CLEAR_ZMASK 0x00003200
# define RADEON_3D_CLEAR_HIZ 0x00003700
# define RADEON_CNTL_HOSTDATA_BLT 0x00009400
@@ -817,6 +801,12 @@ extern int radeon_postcleanup( struct drm_device *dev );
#define RADEON_PP_TEX_SIZE_1 0x1d0c
#define RADEON_PP_TEX_SIZE_2 0x1d14
+#define RADEON_PP_CUBIC_FACES_0 0x1d24
+#define RADEON_PP_CUBIC_FACES_1 0x1d28
+#define RADEON_PP_CUBIC_FACES_2 0x1d2c
+#define RADEON_PP_CUBIC_OFFSET_T0_0 0x1dd0 /* bits [31:5] */
+#define RADEON_PP_CUBIC_OFFSET_T1_0 0x1e00
+#define RADEON_PP_CUBIC_OFFSET_T2_0 0x1e14
#define SE_VAP_CNTL__TCL_ENA_MASK 0x00000001
#define SE_VAP_CNTL__FORCE_W_TO_ONE_MASK 0x00010000
@@ -834,6 +824,8 @@ extern int radeon_postcleanup( struct drm_device *dev );
#define R200_SE_TCL_POINT_SPRITE_CNTL 0x22c4
+#define R200_PP_TRI_PERF 0x2cf8
+
/* Constants */
#define RADEON_MAX_USEC_TIMEOUT 100000 /* 100 ms */
@@ -860,9 +852,6 @@ do { \
RADEON_WRITE( RADEON_CLOCK_CNTL_DATA, (val) ); \
} while (0)
-extern int RADEON_READ_PLL( drm_device_t *dev, int addr );
-
-
#define CP_PACKET0( reg, n ) \
(RADEON_CP_PACKET0 | ((n) << 16) | ((reg) >> 2))
#define CP_PACKET0_TABLE( reg, n ) \
diff --git a/drivers/char/drm/radeon_irq.c b/drivers/char/drm/radeon_irq.c
index b7deca73b0a94..5b18bee6492e8 100644
--- a/drivers/char/drm/radeon_irq.c
+++ b/drivers/char/drm/radeon_irq.c
@@ -93,7 +93,7 @@ static __inline__ void radeon_acknowledge_irqs(drm_radeon_private_t *dev_priv)
RADEON_WRITE( RADEON_GEN_INT_STATUS, tmp );
}
-int radeon_emit_irq(drm_device_t *dev)
+static int radeon_emit_irq(drm_device_t *dev)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
unsigned int ret;
@@ -112,7 +112,7 @@ int radeon_emit_irq(drm_device_t *dev)
}
-int radeon_wait_irq(drm_device_t *dev, int swi_nr)
+static int radeon_wait_irq(drm_device_t *dev, int swi_nr)
{
drm_radeon_private_t *dev_priv =
(drm_radeon_private_t *)dev->dev_private;
@@ -134,12 +134,6 @@ int radeon_wait_irq(drm_device_t *dev, int swi_nr)
return ret;
}
-int radeon_emit_and_wait_irq(drm_device_t *dev)
-{
- return radeon_wait_irq( dev, radeon_emit_irq(dev) );
-}
-
-
int radeon_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence)
{
drm_radeon_private_t *dev_priv =
diff --git a/drivers/char/drm/radeon_state.c b/drivers/char/drm/radeon_state.c
index b8d38e106708d..1f79e249146c9 100644
--- a/drivers/char/drm/radeon_state.c
+++ b/drivers/char/drm/radeon_state.c
@@ -33,38 +33,6 @@
#include "radeon_drm.h"
#include "radeon_drv.h"
-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 }
-};
-
-int radeon_max_ioctl = DRM_ARRAY_SIZE(radeon_ioctls);
-
/* ================================================================
* Helper functions for client state checking and fixup
*/
@@ -158,6 +126,22 @@ static __inline__ int radeon_check_and_fixup_packets( drm_radeon_private_t *dev_
break;
}
+ case RADEON_EMIT_PP_CUBIC_OFFSETS_T0:
+ case RADEON_EMIT_PP_CUBIC_OFFSETS_T1:
+ case RADEON_EMIT_PP_CUBIC_OFFSETS_T2:{
+ int i;
+ for (i = 0; i < 5; i++) {
+ if (radeon_check_and_fixup_offset(dev_priv,
+ filp_priv,
+ &data[i])) {
+ DRM_ERROR
+ ("Invalid R100 cubic texture offset\n");
+ return DRM_ERR(EINVAL);
+ }
+ }
+ }
+ break;
+
case RADEON_EMIT_RB3D_COLORPITCH:
case RADEON_EMIT_RE_LINE_PATTERN:
case RADEON_EMIT_SE_LINE_WIDTH:
@@ -219,6 +203,10 @@ static __inline__ int radeon_check_and_fixup_packets( drm_radeon_private_t *dev_
case RADEON_EMIT_PP_TEX_SIZE_2:
case R200_EMIT_RB3D_BLENDCOLOR:
case R200_EMIT_TCL_POINT_SPRITE_CNTL:
+ case RADEON_EMIT_PP_CUBIC_FACES_0:
+ case RADEON_EMIT_PP_CUBIC_FACES_1:
+ case RADEON_EMIT_PP_CUBIC_FACES_2:
+ case R200_EMIT_PP_TRI_PERF_CNTL:
/* These packets don't contain memory offsets */
break;
@@ -573,6 +561,13 @@ static struct {
{ RADEON_PP_TEX_SIZE_2, 2, "RADEON_PP_TEX_SIZE_2" },
{ R200_RB3D_BLENDCOLOR, 3, "R200_RB3D_BLENDCOLOR" },
{ R200_SE_TCL_POINT_SPRITE_CNTL, 1, "R200_SE_TCL_POINT_SPRITE_CNTL" },
+ { RADEON_PP_CUBIC_FACES_0, 1, "RADEON_PP_CUBIC_FACES_0"},
+ { RADEON_PP_CUBIC_OFFSET_T0_0, 5, "RADEON_PP_CUBIC_OFFSET_T0_0"},
+ { RADEON_PP_CUBIC_FACES_1, 1, "RADEON_PP_CUBIC_FACES_1"},
+ { RADEON_PP_CUBIC_OFFSET_T1_0, 5, "RADEON_PP_CUBIC_OFFSET_T1_0"},
+ { 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"},
};
@@ -1514,6 +1509,7 @@ static int radeon_cp_dispatch_texture( DRMFILE filp,
int size, dwords, tex_width, blit_width;
u32 height;
int i;
+ u32 texpitch, microtile;
RING_LOCALS;
DRM_GET_PRIV_WITH_RETURN( filp_priv, filp );
@@ -1576,6 +1572,16 @@ static int radeon_cp_dispatch_texture( DRMFILE filp,
DRM_ERROR( "invalid texture format %d\n", tex->format );
return DRM_ERR(EINVAL);
}
+ texpitch = tex->pitch;
+ if ((texpitch << 22) & RADEON_DST_TILE_MICRO) {
+ microtile = 1;
+ if (tex_width < 64) {
+ texpitch &= ~(RADEON_DST_TILE_MICRO >> 22);
+ /* we got tiled coordinates, untile them */
+ image->x *= 2;
+ }
+ }
+ else microtile = 0;
DRM_DEBUG("tex=%dx%d blit=%d\n", tex_width, tex->height, blit_width );
@@ -1628,7 +1634,7 @@ static int radeon_cp_dispatch_texture( DRMFILE filp,
RADEON_GMC_CLR_CMP_CNTL_DIS |
RADEON_GMC_WR_MSK_DIS);
- buffer[2] = (tex->pitch << 22) | (tex->offset >> 10);
+ buffer[2] = (texpitch << 22) | (tex->offset >> 10);
buffer[3] = 0xffffffff;
buffer[4] = 0xffffffff;
buffer[5] = (image->y << 16) | image->x;
@@ -1636,30 +1642,110 @@ static int radeon_cp_dispatch_texture( DRMFILE filp,
buffer[7] = dwords;
buffer += 8;
- if ( tex_width >= 32 ) {
- /* 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);
+
+
+ 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,
+ since minimum tex pitch is 64 bytes and we need this to match
+ the texture width, otherwise the blitter will tile it wrong.
+ Thus, tiling manually in this case. Additionally, need to special
+ case tex height = 1, since our actual image will have height 2
+ and we need to ensure we don't read beyond the texture size
+ 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);
+ }
+ } 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);
+ }
+ }
+ } 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);
+ }
+ } 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);
+ }
+ buffer += 4;
+ data += tex_width;
+ }
+ } else if (tex_width == 32) {
+ /* 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);
+ }
+ 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);
+ }
+ 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);
+ }
+ 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);
+ }
+ data += 16;
+ buffer += 16;
+ }
}
- } 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 );
+ }
+ else {
+ if (tex_width >= 32) {
+ /* 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);
}
- buffer += 8;
- data += tex_width;
+ } 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);
+ }
+ buffer += 8;
+ data += tex_width;
+ }
}
}
@@ -1842,7 +1928,7 @@ static int free_surface(DRMFILE filp, drm_radeon_private_t *dev_priv, int lower)
dev_priv->surfaces[s->surface_index].refcount--;
if (dev_priv->surfaces[s->surface_index].refcount == 0)
dev_priv->surfaces[s->surface_index].flags = 0;
- s->filp = 0;
+ s->filp = NULL;
radeon_apply_surface_regs(s->surface_index, dev_priv);
return 0;
}
@@ -1864,7 +1950,7 @@ static void radeon_surfaces_release(DRMFILE filp, drm_radeon_private_t *dev_priv
/* ================================================================
* IOCTL functions
*/
-int radeon_surface_alloc(DRM_IOCTL_ARGS)
+static int radeon_surface_alloc(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -1884,7 +1970,7 @@ int radeon_surface_alloc(DRM_IOCTL_ARGS)
return 0;
}
-int radeon_surface_free(DRM_IOCTL_ARGS)
+static int radeon_surface_free(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -1904,7 +1990,7 @@ int radeon_surface_free(DRM_IOCTL_ARGS)
return 0;
}
-int radeon_cp_clear( DRM_IOCTL_ARGS )
+static int radeon_cp_clear( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -1961,7 +2047,7 @@ static int radeon_do_init_pageflip( drm_device_t *dev )
/* Called whenever a client dies, from drm_release.
* NOTE: Lock isn't necessarily held when this is called!
*/
-int radeon_do_cleanup_pageflip( drm_device_t *dev )
+static int radeon_do_cleanup_pageflip( drm_device_t *dev )
{
drm_radeon_private_t *dev_priv = dev->dev_private;
DRM_DEBUG( "\n" );
@@ -1976,7 +2062,7 @@ int radeon_do_cleanup_pageflip( drm_device_t *dev )
/* Swapping and flipping are different operations, need different ioctls.
* They can & should be intermixed to support multiple 3d windows.
*/
-int radeon_cp_flip( DRM_IOCTL_ARGS )
+static int radeon_cp_flip( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -1995,7 +2081,7 @@ int radeon_cp_flip( DRM_IOCTL_ARGS )
return 0;
}
-int radeon_cp_swap( DRM_IOCTL_ARGS )
+static int radeon_cp_swap( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -2016,7 +2102,7 @@ int radeon_cp_swap( DRM_IOCTL_ARGS )
return 0;
}
-int radeon_cp_vertex( DRM_IOCTL_ARGS )
+static int radeon_cp_vertex( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -2101,7 +2187,7 @@ int radeon_cp_vertex( DRM_IOCTL_ARGS )
return 0;
}
-int radeon_cp_indices( DRM_IOCTL_ARGS )
+static int radeon_cp_indices( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -2203,7 +2289,7 @@ int radeon_cp_indices( DRM_IOCTL_ARGS )
return 0;
}
-int radeon_cp_texture( DRM_IOCTL_ARGS )
+static int radeon_cp_texture( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -2234,7 +2320,7 @@ int radeon_cp_texture( DRM_IOCTL_ARGS )
return ret;
}
-int radeon_cp_stipple( DRM_IOCTL_ARGS )
+static int radeon_cp_stipple( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -2257,7 +2343,7 @@ int radeon_cp_stipple( DRM_IOCTL_ARGS )
return 0;
}
-int radeon_cp_indirect( DRM_IOCTL_ARGS )
+static int radeon_cp_indirect( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -2332,7 +2418,7 @@ int radeon_cp_indirect( DRM_IOCTL_ARGS )
return 0;
}
-int radeon_cp_vertex2( DRM_IOCTL_ARGS )
+static int radeon_cp_vertex2( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -2661,7 +2747,7 @@ static int radeon_emit_wait( drm_device_t *dev, int flags )
return 0;
}
-int radeon_cp_cmdbuf( DRM_IOCTL_ARGS )
+static int radeon_cp_cmdbuf( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -2702,8 +2788,10 @@ 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, cmdbuf.buf, cmdbuf.bufsz))
+ if (DRM_COPY_FROM_USER(kbuf, cmdbuf.buf, cmdbuf.bufsz)) {
+ drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER);
return DRM_ERR(EFAULT);
+ }
cmdbuf.buf = kbuf;
}
@@ -2813,7 +2901,7 @@ err:
-int radeon_cp_getparam( DRM_IOCTL_ARGS )
+static int radeon_cp_getparam( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -2887,7 +2975,7 @@ int radeon_cp_getparam( DRM_IOCTL_ARGS )
return 0;
}
-int radeon_cp_setparam( DRM_IOCTL_ARGS ) {
+static int radeon_cp_setparam( DRM_IOCTL_ARGS ) {
DRM_DEVICE;
drm_radeon_private_t *dev_priv = dev->dev_private;
drm_file_t *filp_priv;
@@ -2980,3 +3068,35 @@ void radeon_driver_free_filp_priv(drm_device_t *dev, drm_file_t *filp_priv)
drm_free(radeon_priv, sizeof(*radeon_priv), DRM_MEM_FILES);
}
+
+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 }
+};
+
+int radeon_max_ioctl = DRM_ARRAY_SIZE(radeon_ioctls);
diff --git a/drivers/char/drm/sis_drv.c b/drivers/char/drm/sis_drv.c
index 35a90638efa4a..f441714faae36 100644
--- a/drivers/char/drm/sis_drv.c
+++ b/drivers/char/drm/sis_drv.c
@@ -40,7 +40,7 @@ static int postinit( struct drm_device *dev, unsigned long flags )
DRIVER_MINOR,
DRIVER_PATCHLEVEL,
DRIVER_DATE,
- dev->minor,
+ dev->primary.minor,
pci_pretty_name(dev->pdev)
);
return 0;
diff --git a/drivers/char/drm/sis_drv.h b/drivers/char/drm/sis_drv.h
index 7232b8f3ff584..5be36b5caec99 100644
--- a/drivers/char/drm/sis_drv.h
+++ b/drivers/char/drm/sis_drv.h
@@ -46,13 +46,6 @@ typedef struct drm_sis_private {
memHeap_t *FBHeap;
} drm_sis_private_t;
-extern int sis_fb_alloc( DRM_IOCTL_ARGS );
-extern int sis_fb_free( DRM_IOCTL_ARGS );
-extern int sis_ioctl_agp_init( DRM_IOCTL_ARGS );
-extern int sis_ioctl_agp_alloc( DRM_IOCTL_ARGS );
-extern int sis_ioctl_agp_free( DRM_IOCTL_ARGS );
-extern int sis_fb_init( DRM_IOCTL_ARGS );
-
extern int sis_init_context(drm_device_t *dev, int context);
extern int sis_final_context(drm_device_t *dev, int context);
diff --git a/drivers/char/drm/sis_ds.c b/drivers/char/drm/sis_ds.c
index 1b471be5f9e44..e37ed8ce48dff 100644
--- a/drivers/char/drm/sis_ds.c
+++ b/drivers/char/drm/sis_ds.c
@@ -194,32 +194,6 @@ int mmBlockInHeap(memHeap_t *heap, PMemBlock b)
return 0;
}
-/* Kludgey workaround for existing i810 server. Remove soon.
- */
-memHeap_t *mmAddRange( memHeap_t *heap,
- int ofs,
- int size )
-{
- PMemBlock blocks;
- blocks = (TMemBlock *)drm_calloc(2, sizeof(TMemBlock), DRM_MEM_DRIVER);
- if (blocks != NULL) {
- blocks[0].size = size;
- blocks[0].free = 1;
- blocks[0].ofs = ofs;
- blocks[0].next = &blocks[1];
-
- /* Discontinuity - stops JoinBlock from trying to join
- * non-adjacent ranges.
- */
- blocks[1].size = 0;
- blocks[1].free = 0;
- blocks[1].ofs = ofs+size;
- blocks[1].next = (PMemBlock)heap;
- return (memHeap_t *)blocks;
- } else
- return heap;
-}
-
static TMemBlock* SliceBlock(TMemBlock *p,
int startofs, int size,
int reserved, int alignment)
@@ -325,61 +299,3 @@ int mmFreeMem(PMemBlock b)
return 0;
}
-int mmReserveMem(memHeap_t *heap, int offset,int size)
-{
- int endofs;
- TMemBlock *p;
-
- if (heap == NULL || size <= 0)
- return -1;
-
- endofs = offset + size;
- p = (TMemBlock *)heap;
- while (p && p->ofs <= offset) {
- if (ISFREE(p) && endofs <= (p->ofs+p->size)) {
- SliceBlock(p,offset,size,1,1);
- return 0;
- }
- p = p->next;
- }
- return -1;
-}
-
-int mmFreeReserved(memHeap_t *heap, int offset)
-{
- TMemBlock *p,*prev;
-
- if (heap == NULL)
- return -1;
-
- p = (TMemBlock *)heap;
- prev = NULL;
- while (p != NULL && p->ofs != offset) {
- prev = p;
- p = p->next;
- }
- if (p == NULL || !p->reserved)
- return -1;
-
- p->free = 1;
- p->reserved = 0;
- Join2Blocks(p);
- if (prev != NULL)
- Join2Blocks(prev);
- return 0;
-}
-
-void mmDestroy(memHeap_t *heap)
-{
- TMemBlock *p,*q;
-
- if (heap == NULL)
- return;
-
- p = (TMemBlock *)heap;
- while (p != NULL) {
- q = p->next;
- drm_free(p, sizeof(TMemBlock), DRM_MEM_DRIVER);
- p = q;
- }
-}
diff --git a/drivers/char/drm/sis_ds.h b/drivers/char/drm/sis_ds.h
index c3addb526a4e5..171ee75afa57f 100644
--- a/drivers/char/drm/sis_ds.h
+++ b/drivers/char/drm/sis_ds.h
@@ -115,10 +115,6 @@ static __inline__ void mmMarkReserved(PMemBlock b)
*/
memHeap_t *mmInit( int ofs, int size );
-memHeap_t *mmAddRange( memHeap_t *heap,
- int ofs,
- int size );
-
/*
* Allocate 'size' bytes with 2^align2 bytes alignment,
* restrict the search to free memory after 'startSearch'
@@ -143,21 +139,6 @@ int mmBlockInHeap( PMemBlock heap, PMemBlock b );
*/
int mmFreeMem( PMemBlock b );
-/*
- * Reserve 'size' bytes block start at offset
- * This is used to prevent allocation of memory already used
- * by the X server for the front buffer, pixmaps, and cursor
- * input: size, offset
- * output: 0 if OK, -1 if error
- */
-int mmReserveMem( memHeap_t *heap, int offset,int size );
-int mmFreeReserved( memHeap_t *heap, int offset );
-
-/*
- * destroy MM
- */
-void mmDestroy( memHeap_t *mmInit );
-
/* For debuging purpose. */
void mmDumpMemInfo( memHeap_t *mmInit );
diff --git a/drivers/char/drm/sis_mm.c b/drivers/char/drm/sis_mm.c
index 3038e055523d4..6610c5576d226 100644
--- a/drivers/char/drm/sis_mm.c
+++ b/drivers/char/drm/sis_mm.c
@@ -36,17 +36,6 @@
#include <video/sisfb.h>
#endif
-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 }
-};
-
-int sis_max_ioctl = DRM_ARRAY_SIZE(sis_ioctls);
-
#define MAX_CONTEXT 100
#define VIDEO_TYPE 0
#define AGP_TYPE 1
@@ -91,12 +80,12 @@ static int del_alloc_set(int context, int type, unsigned int val)
/* fb management via fb device */
#if defined(__linux__) && defined(CONFIG_FB_SIS)
-int sis_fb_init( DRM_IOCTL_ARGS )
+static int sis_fb_init( DRM_IOCTL_ARGS )
{
return 0;
}
-int sis_fb_alloc( DRM_IOCTL_ARGS )
+static int sis_fb_alloc( DRM_IOCTL_ARGS )
{
drm_sis_mem_t fb;
struct sis_memreq req;
@@ -129,7 +118,7 @@ int sis_fb_alloc( DRM_IOCTL_ARGS )
return retval;
}
-int sis_fb_free( DRM_IOCTL_ARGS )
+static int sis_fb_free( DRM_IOCTL_ARGS )
{
drm_sis_mem_t fb;
int retval = 0;
@@ -160,7 +149,7 @@ int sis_fb_free( DRM_IOCTL_ARGS )
* X driver/sisfb HW- Command-
* framebuffer memory DRI heap Cursor queue
*/
-int sis_fb_init( DRM_IOCTL_ARGS )
+static int sis_fb_init( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
drm_sis_private_t *dev_priv = dev->dev_private;
@@ -186,7 +175,7 @@ int sis_fb_init( DRM_IOCTL_ARGS )
return 0;
}
-int sis_fb_alloc( DRM_IOCTL_ARGS )
+static int sis_fb_alloc( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
drm_sis_private_t *dev_priv = dev->dev_private;
@@ -223,7 +212,7 @@ int sis_fb_alloc( DRM_IOCTL_ARGS )
return retval;
}
-int sis_fb_free( DRM_IOCTL_ARGS )
+static int sis_fb_free( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
drm_sis_private_t *dev_priv = dev->dev_private;
@@ -250,7 +239,7 @@ int sis_fb_free( DRM_IOCTL_ARGS )
/* agp memory management */
-int sis_ioctl_agp_init( DRM_IOCTL_ARGS )
+static int sis_ioctl_agp_init( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
drm_sis_private_t *dev_priv = dev->dev_private;
@@ -276,7 +265,7 @@ int sis_ioctl_agp_init( DRM_IOCTL_ARGS )
return 0;
}
-int sis_ioctl_agp_alloc( DRM_IOCTL_ARGS )
+static int sis_ioctl_agp_alloc( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
drm_sis_private_t *dev_priv = dev->dev_private;
@@ -313,7 +302,7 @@ int sis_ioctl_agp_alloc( DRM_IOCTL_ARGS )
return retval;
}
-int sis_ioctl_agp_free( DRM_IOCTL_ARGS )
+static int sis_ioctl_agp_free( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
drm_sis_private_t *dev_priv = dev->dev_private;
@@ -414,3 +403,15 @@ int sis_final_context(struct drm_device *dev, int context)
return 1;
}
+
+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 }
+};
+
+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 9dc2f649a84e0..0e7943e6efea5 100644
--- a/drivers/char/drm/tdfx_drv.c
+++ b/drivers/char/drm/tdfx_drv.c
@@ -44,7 +44,7 @@ static int postinit( struct drm_device *dev, unsigned long flags )
DRIVER_MINOR,
DRIVER_PATCHLEVEL,
DRIVER_DATE,
- dev->minor,
+ dev->primary.minor,
pci_pretty_name(dev->pdev)
);
return 0;
diff --git a/drivers/char/esp.c b/drivers/char/esp.c
index fb681990a84d8..9f53d2fcc360d 100644
--- a/drivers/char/esp.c
+++ b/drivers/char/esp.c
@@ -129,8 +129,6 @@ static struct tty_driver *esp_driver;
#undef SERIAL_DEBUG_OPEN
#undef SERIAL_DEBUG_FLOW
-#define _INLINE_ inline
-
#if defined(MODULE) && defined(SERIAL_DEBUG_MCOUNT)
#define DBG_CNT(s) printk("(%s): [%x] refc=%d, serc=%d, ttyc=%d -> %s\n", \
tty->name, (info->flags), serial_driver.refcount,info->count,tty->count,s)
@@ -211,15 +209,14 @@ static void rs_stop(struct tty_struct *tty)
if (serial_paranoia_check(info, tty->name, "rs_stop"))
return;
-
- save_flags(flags); cli();
+
+ spin_lock_irqsave(&info->lock, flags);
if (info->IER & UART_IER_THRI) {
info->IER &= ~UART_IER_THRI;
serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK);
serial_out(info, UART_ESI_CMD2, info->IER);
}
-
- restore_flags(flags);
+ spin_unlock_irqrestore(&info->lock, flags);
}
static void rs_start(struct tty_struct *tty)
@@ -230,13 +227,13 @@ static void rs_start(struct tty_struct *tty)
if (serial_paranoia_check(info, tty->name, "rs_start"))
return;
- save_flags(flags); cli();
+ spin_lock_irqsave(&info->lock, flags);
if (info->xmit_cnt && info->xmit_buf && !(info->IER & UART_IER_THRI)) {
info->IER |= UART_IER_THRI;
serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK);
serial_out(info, UART_ESI_CMD2, info->IER);
}
- restore_flags(flags);
+ spin_unlock_irqrestore(&info->lock, flags);
}
/*
@@ -264,34 +261,41 @@ static void rs_start(struct tty_struct *tty)
* This routine is used by the interrupt handler to schedule
* processing in the software interrupt portion of the driver.
*/
-static _INLINE_ void rs_sched_event(struct esp_struct *info,
+static inline void rs_sched_event(struct esp_struct *info,
int event)
{
info->event |= 1 << event;
schedule_work(&info->tqueue);
}
-static _INLINE_ struct esp_pio_buffer *get_pio_buffer(void)
+static DEFINE_SPINLOCK(pio_lock);
+
+static inline struct esp_pio_buffer *get_pio_buffer(void)
{
struct esp_pio_buffer *buf;
+ unsigned long flags;
+ spin_lock_irqsave(&pio_lock, flags);
if (free_pio_buf) {
buf = free_pio_buf;
free_pio_buf = buf->next;
} else {
buf = kmalloc(sizeof(struct esp_pio_buffer), GFP_ATOMIC);
}
-
+ spin_unlock_irqrestore(&pio_lock, flags);
return buf;
}
-static _INLINE_ void release_pio_buffer(struct esp_pio_buffer *buf)
+static inline void release_pio_buffer(struct esp_pio_buffer *buf)
{
+ unsigned long flags;
+ spin_lock_irqsave(&pio_lock, flags);
buf->next = free_pio_buf;
free_pio_buf = buf;
+ spin_unlock_irqrestore(&pio_lock, flags);
}
-static _INLINE_ void receive_chars_pio(struct esp_struct *info, int num_bytes)
+static inline void receive_chars_pio(struct esp_struct *info, int num_bytes)
{
struct tty_struct *tty = info->tty;
int i;
@@ -311,8 +315,6 @@ static _INLINE_ void receive_chars_pio(struct esp_struct *info, int num_bytes)
return;
}
- sti();
-
status_mask = (info->read_status_mask >> 2) & 0x07;
for (i = 0; i < num_bytes - 1; i += 2) {
@@ -329,8 +331,6 @@ static _INLINE_ void receive_chars_pio(struct esp_struct *info, int num_bytes)
(serial_in(info, UART_ESI_RWS) >> 3) & status_mask;
}
- cli();
-
/* make sure everything is still ok since interrupts were enabled */
tty = info->tty;
@@ -371,7 +371,7 @@ static _INLINE_ void receive_chars_pio(struct esp_struct *info, int num_bytes)
release_pio_buffer(err_buf);
}
-static _INLINE_ void receive_chars_dma(struct esp_struct *info, int num_bytes)
+static inline void receive_chars_dma(struct esp_struct *info, int num_bytes)
{
unsigned long flags;
info->stat_flags &= ~ESP_STAT_RX_TIMEOUT;
@@ -390,7 +390,7 @@ static _INLINE_ void receive_chars_dma(struct esp_struct *info, int num_bytes)
serial_out(info, UART_ESI_CMD1, ESI_START_DMA_RX);
}
-static _INLINE_ void receive_chars_dma_done(struct esp_struct *info,
+static inline void receive_chars_dma_done(struct esp_struct *info,
int status)
{
struct tty_struct *tty = info->tty;
@@ -450,7 +450,9 @@ static _INLINE_ void receive_chars_dma_done(struct esp_struct *info,
dma_bytes = 0;
}
-static _INLINE_ void transmit_chars_pio(struct esp_struct *info,
+/* Caller must hold info->lock */
+
+static inline void transmit_chars_pio(struct esp_struct *info,
int space_avail)
{
int i;
@@ -478,8 +480,6 @@ static _INLINE_ void transmit_chars_pio(struct esp_struct *info,
info->xmit_tail = (info->xmit_tail + space_avail) &
(ESP_XMIT_SIZE - 1);
- sti();
-
for (i = 0; i < space_avail - 1; i += 2) {
outw(*((unsigned short *)(pio_buf->data + i)),
info->port + UART_ESI_TX);
@@ -489,8 +489,6 @@ static _INLINE_ void transmit_chars_pio(struct esp_struct *info,
serial_out(info, UART_ESI_TX,
pio_buf->data[space_avail - 1]);
- cli();
-
if (info->xmit_cnt) {
serial_out(info, UART_ESI_CMD1, ESI_NO_COMMAND);
serial_out(info, UART_ESI_CMD1, ESI_GET_TX_AVAIL);
@@ -520,7 +518,8 @@ static _INLINE_ void transmit_chars_pio(struct esp_struct *info,
release_pio_buffer(pio_buf);
}
-static _INLINE_ void transmit_chars_dma(struct esp_struct *info, int num_bytes)
+/* Caller must hold info->lock */
+static inline void transmit_chars_dma(struct esp_struct *info, int num_bytes)
{
unsigned long flags;
@@ -567,7 +566,7 @@ static _INLINE_ void transmit_chars_dma(struct esp_struct *info, int num_bytes)
serial_out(info, UART_ESI_CMD1, ESI_START_DMA_TX);
}
-static _INLINE_ void transmit_chars_dma_done(struct esp_struct *info)
+static inline void transmit_chars_dma_done(struct esp_struct *info)
{
int num_bytes;
unsigned long flags;
@@ -601,7 +600,7 @@ static _INLINE_ void transmit_chars_dma_done(struct esp_struct *info)
}
}
-static _INLINE_ void check_modem_status(struct esp_struct *info)
+static inline void check_modem_status(struct esp_struct *info)
{
int status;
@@ -654,10 +653,10 @@ static irqreturn_t rs_interrupt_single(int irq, void *dev_id,
err_status = 0;
scratch = serial_in(info, UART_ESI_SID);
- cli();
+ spin_lock(&info->lock);
if (!info->tty) {
- sti();
+ spin_unlock(&info->lock);
return IRQ_NONE;
}
@@ -740,7 +739,7 @@ static irqreturn_t rs_interrupt_single(int irq, void *dev_id,
#ifdef SERIAL_DEBUG_INTR
printk("end.\n");
#endif
- sti();
+ spin_unlock(&info->lock);
return IRQ_HANDLED;
}
@@ -789,10 +788,12 @@ static void do_serial_hangup(void *private_)
* figure out the appropriate timeout for an interrupt chain, routines
* to initialize and startup a serial port, and routines to shutdown a
* serial port. Useful stuff like that.
+ *
+ * Caller should hold lock
* ---------------------------------------------------------------
*/
-static _INLINE_ void esp_basic_init(struct esp_struct * info)
+static inline void esp_basic_init(struct esp_struct * info)
{
/* put ESPC in enhanced mode */
serial_out(info, UART_ESI_CMD1, ESI_SET_MODE);
@@ -859,13 +860,13 @@ static int startup(struct esp_struct * info)
int retval=0;
unsigned int num_chars;
- save_flags(flags); cli();
+ spin_lock_irqsave(&info->lock, flags);
if (info->flags & ASYNC_INITIALIZED)
goto out;
if (!info->xmit_buf) {
- info->xmit_buf = (unsigned char *)get_zeroed_page(GFP_KERNEL);
+ info->xmit_buf = (unsigned char *)get_zeroed_page(GFP_ATOMIC);
retval = -ENOMEM;
if (!info->xmit_buf)
goto out;
@@ -901,6 +902,8 @@ static int startup(struct esp_struct * info)
if (info->stat_flags & ESP_STAT_NEVER_DMA)
info->stat_flags |= ESP_STAT_USE_PIO;
+ spin_unlock_irqrestore(&info->lock, flags);
+
/*
* Allocate the IRQ
*/
@@ -915,7 +918,7 @@ static int startup(struct esp_struct * info)
&info->tty->flags);
retval = 0;
}
- goto out;
+ goto out_unlocked;
}
if (!(info->stat_flags & ESP_STAT_USE_PIO) && !dma_buffer) {
@@ -935,6 +938,8 @@ static int startup(struct esp_struct * info)
}
info->MCR = UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2;
+
+ spin_lock_irqsave(&info->lock, flags);
serial_out(info, UART_ESI_CMD1, ESI_WRITE_UART);
serial_out(info, UART_ESI_CMD2, UART_MCR);
serial_out(info, UART_ESI_CMD2, info->MCR);
@@ -951,6 +956,7 @@ static int startup(struct esp_struct * info)
if (info->tty)
clear_bit(TTY_IO_ERROR, &info->tty->flags);
info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
+ spin_unlock_irqrestore(&info->lock, flags);
/*
* Set up the tty->alt_speed kludge
@@ -970,10 +976,12 @@ static int startup(struct esp_struct * info)
* set the speed of the serial port
*/
change_speed(info);
-
info->flags |= ASYNC_INITIALIZED;
- retval = 0;
-out: restore_flags(flags);
+ return 0;
+
+out:
+ spin_unlock_irqrestore(&info->lock, flags);
+out_unlocked:
return retval;
}
@@ -993,8 +1001,7 @@ static void shutdown(struct esp_struct * info)
info->irq);
#endif
- save_flags(flags); cli(); /* Disable interrupts */
-
+ spin_lock_irqsave(&info->lock, flags);
/*
* clear delta_msr_wait queue to avoid mem leaks: we may free the irq
* here so the queue might never be waken up
@@ -1003,7 +1010,7 @@ static void shutdown(struct esp_struct * info)
wake_up_interruptible(&info->break_wait);
/* stop a DMA transfer on the port being closed */
-
+ /* DMA lock is higher priority always */
if (info->stat_flags & (ESP_STAT_DMA_RX | ESP_STAT_DMA_TX)) {
f=claim_dma_lock();
disable_dma(dma);
@@ -1058,7 +1065,7 @@ static void shutdown(struct esp_struct * info)
set_bit(TTY_IO_ERROR, &info->tty->flags);
info->flags &= ~ASYNC_INITIALIZED;
- restore_flags(flags);
+ spin_unlock_irqrestore(&info->lock, flags);
}
/*
@@ -1172,7 +1179,7 @@ static void change_speed(struct esp_struct *info)
if (I_IXOFF(info->tty))
flow1 |= 0x81;
- save_flags(flags); cli();
+ spin_lock_irqsave(&info->lock, flags);
/* set baud */
serial_out(info, UART_ESI_CMD1, ESI_SET_BAUD);
serial_out(info, UART_ESI_CMD2, quot >> 8);
@@ -1219,7 +1226,7 @@ static void change_speed(struct esp_struct *info)
serial_out(info, UART_ESI_CMD2, info->config.flow_on >> 8);
serial_out(info, UART_ESI_CMD2, info->config.flow_on);
- restore_flags(flags);
+ spin_unlock_irqrestore(&info->lock, flags);
}
static void rs_put_char(struct tty_struct *tty, unsigned char ch)
@@ -1233,16 +1240,13 @@ static void rs_put_char(struct tty_struct *tty, unsigned char ch)
if (!tty || !info->xmit_buf)
return;
- save_flags(flags); cli();
- if (info->xmit_cnt >= ESP_XMIT_SIZE - 1) {
- restore_flags(flags);
- return;
+ spin_lock_irqsave(&info->lock, flags);
+ if (info->xmit_cnt < ESP_XMIT_SIZE - 1) {
+ info->xmit_buf[info->xmit_head++] = ch;
+ info->xmit_head &= ESP_XMIT_SIZE-1;
+ info->xmit_cnt++;
}
-
- info->xmit_buf[info->xmit_head++] = ch;
- info->xmit_head &= ESP_XMIT_SIZE-1;
- info->xmit_cnt++;
- restore_flags(flags);
+ spin_unlock_irqrestore(&info->lock, flags);
}
static void rs_flush_chars(struct tty_struct *tty)
@@ -1253,16 +1257,18 @@ static void rs_flush_chars(struct tty_struct *tty)
if (serial_paranoia_check(info, tty->name, "rs_flush_chars"))
return;
+ spin_lock_irqsave(&info->lock, flags);
+
if (info->xmit_cnt <= 0 || tty->stopped || !info->xmit_buf)
- return;
+ goto out;
- save_flags(flags); cli();
if (!(info->IER & UART_IER_THRI)) {
info->IER |= UART_IER_THRI;
serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK);
serial_out(info, UART_ESI_CMD2, info->IER);
}
- restore_flags(flags);
+out:
+ spin_unlock_irqrestore(&info->lock, flags);
}
static int rs_write(struct tty_struct * tty,
@@ -1305,7 +1311,7 @@ static int rs_write(struct tty_struct * tty,
ret += c;
}
- save_flags(flags); cli();
+ spin_lock_irqsave(&info->lock, flags);
if (info->xmit_cnt && !tty->stopped && !(info->IER & UART_IER_THRI)) {
info->IER |= UART_IER_THRI;
@@ -1313,7 +1319,7 @@ static int rs_write(struct tty_struct * tty,
serial_out(info, UART_ESI_CMD2, info->IER);
}
- restore_flags(flags);
+ spin_unlock_irqrestore(&info->lock, flags);
return ret;
}
@@ -1321,12 +1327,17 @@ static int rs_write_room(struct tty_struct *tty)
{
struct esp_struct *info = (struct esp_struct *)tty->driver_data;
int ret;
+ unsigned long flags;
if (serial_paranoia_check(info, tty->name, "rs_write_room"))
return 0;
+
+ spin_lock_irqsave(&info->lock, flags);
+
ret = ESP_XMIT_SIZE - info->xmit_cnt - 1;
if (ret < 0)
ret = 0;
+ spin_unlock_irqrestore(&info->lock, flags);
return ret;
}
@@ -1342,12 +1353,13 @@ static int rs_chars_in_buffer(struct tty_struct *tty)
static void rs_flush_buffer(struct tty_struct *tty)
{
struct esp_struct *info = (struct esp_struct *)tty->driver_data;
+ unsigned long flags;
if (serial_paranoia_check(info, tty->name, "rs_flush_buffer"))
return;
- cli();
+ spin_lock_irqsave(&info->lock, flags);
info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
- sti();
+ spin_unlock_irqrestore(&info->lock, flags);
tty_wakeup(tty);
}
@@ -1362,6 +1374,7 @@ static void rs_flush_buffer(struct tty_struct *tty)
static void rs_throttle(struct tty_struct * tty)
{
struct esp_struct *info = (struct esp_struct *)tty->driver_data;
+ unsigned long flags;
#ifdef SERIAL_DEBUG_THROTTLE
char buf[64];
@@ -1371,19 +1384,20 @@ static void rs_throttle(struct tty_struct * tty)
if (serial_paranoia_check(info, tty->name, "rs_throttle"))
return;
-
- cli();
+
+ spin_lock_irqsave(&info->lock, flags);
info->IER &= ~UART_IER_RDI;
serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK);
serial_out(info, UART_ESI_CMD2, info->IER);
serial_out(info, UART_ESI_CMD1, ESI_SET_RX_TIMEOUT);
serial_out(info, UART_ESI_CMD2, 0x00);
- sti();
+ spin_unlock_irqrestore(&info->lock, flags);
}
static void rs_unthrottle(struct tty_struct * tty)
{
struct esp_struct *info = (struct esp_struct *)tty->driver_data;
+ unsigned long flags;
#ifdef SERIAL_DEBUG_THROTTLE
char buf[64];
@@ -1394,13 +1408,13 @@ static void rs_unthrottle(struct tty_struct * tty)
if (serial_paranoia_check(info, tty->name, "rs_unthrottle"))
return;
- cli();
+ spin_lock_irqsave(&info->lock, flags);
info->IER |= UART_IER_RDI;
serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK);
serial_out(info, UART_ESI_CMD2, info->IER);
serial_out(info, UART_ESI_CMD1, ESI_SET_RX_TIMEOUT);
serial_out(info, UART_ESI_CMD2, info->config.rx_timeout);
- sti();
+ spin_unlock_irqrestore(&info->lock, flags);
}
/*
@@ -1573,6 +1587,7 @@ static int set_esp_config(struct esp_struct * info,
unsigned int change_dma;
int retval = 0;
struct esp_struct *current_async;
+ unsigned long flags;
/* Perhaps a non-sysadmin user should be able to do some of these */
/* operations. I haven't decided yet. */
@@ -1628,12 +1643,14 @@ static int set_esp_config(struct esp_struct * info,
/* all ports must use the same DMA channel */
+ spin_lock_irqsave(&info->lock, flags);
current_async = ports;
while (current_async) {
esp_basic_init(current_async);
current_async = current_async->next_port;
}
+ spin_unlock_irqrestore(&info->lock, flags);
} else {
/* DMA mode to PIO mode only */
@@ -1641,8 +1658,10 @@ static int set_esp_config(struct esp_struct * info,
return -EBUSY;
shutdown(info);
+ spin_lock_irqsave(&info->lock, flags);
info->stat_flags |= ESP_STAT_NEVER_DMA;
esp_basic_init(info);
+ spin_unlock_irqrestore(&info->lock, flags);
}
}
@@ -1654,13 +1673,14 @@ static int set_esp_config(struct esp_struct * info,
info->config.flow_off = new_config.flow_off;
info->config.flow_on = new_config.flow_on;
- save_flags(flags); cli();
+
+ spin_lock_irqsave(&info->lock, flags);
serial_out(info, UART_ESI_CMD1, ESI_SET_FLOW_LVL);
serial_out(info, UART_ESI_CMD2, new_config.flow_off >> 8);
serial_out(info, UART_ESI_CMD2, new_config.flow_off);
serial_out(info, UART_ESI_CMD2, new_config.flow_on >> 8);
serial_out(info, UART_ESI_CMD2, new_config.flow_on);
- restore_flags(flags);
+ spin_unlock_irqrestore(&info->lock, flags);
}
if ((new_config.rx_trigger != info->config.rx_trigger) ||
@@ -1669,7 +1689,7 @@ static int set_esp_config(struct esp_struct * info,
info->config.rx_trigger = new_config.rx_trigger;
info->config.tx_trigger = new_config.tx_trigger;
- save_flags(flags); cli();
+ spin_lock_irqsave(&info->lock, flags);
serial_out(info, UART_ESI_CMD1, ESI_SET_TRIGGER);
serial_out(info, UART_ESI_CMD2,
new_config.rx_trigger >> 8);
@@ -1677,14 +1697,14 @@ static int set_esp_config(struct esp_struct * info,
serial_out(info, UART_ESI_CMD2,
new_config.tx_trigger >> 8);
serial_out(info, UART_ESI_CMD2, new_config.tx_trigger);
- restore_flags(flags);
+ spin_unlock_irqrestore(&info->lock, flags);
}
if (new_config.rx_timeout != info->config.rx_timeout) {
unsigned long flags;
info->config.rx_timeout = new_config.rx_timeout;
- save_flags(flags); cli();
+ spin_lock_irqsave(&info->lock, flags);
if (info->IER & UART_IER_RDI) {
serial_out(info, UART_ESI_CMD1,
@@ -1693,7 +1713,7 @@ static int set_esp_config(struct esp_struct * info,
new_config.rx_timeout);
}
- restore_flags(flags);
+ spin_unlock_irqrestore(&info->lock, flags);
}
if (!(info->flags & ASYNC_INITIALIZED))
@@ -1716,11 +1736,12 @@ static int get_lsr_info(struct esp_struct * info, unsigned int __user *value)
{
unsigned char status;
unsigned int result;
+ unsigned long flags;
- cli();
+ spin_lock_irqsave(&info->lock, flags);
serial_out(info, UART_ESI_CMD1, ESI_GET_UART_STAT);
status = serial_in(info, UART_ESI_STAT1);
- sti();
+ spin_unlock_irqrestore(&info->lock, flags);
result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0);
return put_user(result,value);
}
@@ -1730,6 +1751,7 @@ static int esp_tiocmget(struct tty_struct *tty, struct file *file)
{
struct esp_struct * info = (struct esp_struct *)tty->driver_data;
unsigned char control, status;
+ unsigned long flags;
if (serial_paranoia_check(info, tty->name, __FUNCTION__))
return -ENODEV;
@@ -1737,10 +1759,12 @@ static int esp_tiocmget(struct tty_struct *tty, struct file *file)
return -EIO;
control = info->MCR;
- cli();
+
+ spin_lock_irqsave(&info->lock, flags);
serial_out(info, UART_ESI_CMD1, ESI_GET_UART_STAT);
status = serial_in(info, UART_ESI_STAT2);
- sti();
+ spin_unlock_irqrestore(&info->lock, flags);
+
return ((control & UART_MCR_RTS) ? TIOCM_RTS : 0)
| ((control & UART_MCR_DTR) ? TIOCM_DTR : 0)
| ((status & UART_MSR_DCD) ? TIOCM_CAR : 0)
@@ -1753,13 +1777,14 @@ static int esp_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear)
{
struct esp_struct * info = (struct esp_struct *)tty->driver_data;
+ unsigned long flags;
if (serial_paranoia_check(info, tty->name, __FUNCTION__))
return -ENODEV;
if (tty->flags & (1 << TTY_IO_ERROR))
return -EIO;
- cli();
+ spin_lock_irqsave(&info->lock, flags);
if (set & TIOCM_RTS)
info->MCR |= UART_MCR_RTS;
@@ -1774,7 +1799,8 @@ static int esp_tiocmset(struct tty_struct *tty, struct file *file,
serial_out(info, UART_ESI_CMD1, ESI_WRITE_UART);
serial_out(info, UART_ESI_CMD2, UART_MCR);
serial_out(info, UART_ESI_CMD2, info->MCR);
- sti();
+
+ spin_unlock_irqrestore(&info->lock, flags);
return 0;
}
@@ -1789,17 +1815,20 @@ static void esp_break(struct tty_struct *tty, int break_state)
if (serial_paranoia_check(info, tty->name, "esp_break"))
return;
- save_flags(flags); cli();
if (break_state == -1) {
+ spin_lock_irqsave(&info->lock, flags);
serial_out(info, UART_ESI_CMD1, ESI_ISSUE_BREAK);
serial_out(info, UART_ESI_CMD2, 0x01);
+ spin_unlock_irqrestore(&info->lock, flags);
+ /* FIXME - new style wait needed here */
interruptible_sleep_on(&info->break_wait);
} else {
+ spin_lock_irqsave(&info->lock, flags);
serial_out(info, UART_ESI_CMD1, ESI_ISSUE_BREAK);
serial_out(info, UART_ESI_CMD2, 0x00);
+ spin_unlock_irqrestore(&info->lock, flags);
}
- restore_flags(flags);
}
static int rs_ioctl(struct tty_struct *tty, struct file * file,
@@ -1809,6 +1838,7 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
struct async_icount cprev, cnow; /* kernel counter temps */
struct serial_icounter_struct __user *p_cuser; /* user space */
void __user *argp = (void __user *)arg;
+ unsigned long flags;
if (serial_paranoia_check(info, tty->name, "rs_ioctl"))
return -ENODEV;
@@ -1849,17 +1879,18 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
* Caller should use TIOCGICOUNT to see which one it was
*/
case TIOCMIWAIT:
- cli();
+ spin_lock_irqsave(&info->lock, flags);
cprev = info->icount; /* note the counters on entry */
- sti();
+ spin_unlock_irqrestore(&info->lock, flags);
while (1) {
+ /* FIXME: convert to new style wakeup */
interruptible_sleep_on(&info->delta_msr_wait);
/* see if a signal did it */
if (signal_pending(current))
return -ERESTARTSYS;
- cli();
+ spin_lock_irqsave(&info->lock, flags);
cnow = info->icount; /* atomic copy */
- sti();
+ spin_unlock_irqrestore(&info->lock, flags);
if (cnow.rng == cprev.rng &&
cnow.dsr == cprev.dsr &&
cnow.dcd == cprev.dcd &&
@@ -1886,9 +1917,9 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
* RI where only 0->1 is counted.
*/
case TIOCGICOUNT:
- cli();
+ spin_lock_irqsave(&info->lock, flags);
cnow = info->icount;
- sti();
+ spin_unlock_irqrestore(&info->lock, flags);
p_cuser = argp;
if (put_user(cnow.cts, &p_cuser->cts) ||
put_user(cnow.dsr, &p_cuser->dsr) ||
@@ -1911,53 +1942,42 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios)
{
struct esp_struct *info = (struct esp_struct *)tty->driver_data;
+ unsigned long flags;
if ( (tty->termios->c_cflag == old_termios->c_cflag)
&& ( RELEVANT_IFLAG(tty->termios->c_iflag)
== RELEVANT_IFLAG(old_termios->c_iflag)))
- return;
+ return;
change_speed(info);
+ spin_lock_irqsave(&info->lock, flags);
+
/* Handle transition to B0 status */
if ((old_termios->c_cflag & CBAUD) &&
!(tty->termios->c_cflag & CBAUD)) {
info->MCR &= ~(UART_MCR_DTR|UART_MCR_RTS);
- cli();
serial_out(info, UART_ESI_CMD1, ESI_WRITE_UART);
serial_out(info, UART_ESI_CMD2, UART_MCR);
serial_out(info, UART_ESI_CMD2, info->MCR);
- sti();
}
/* Handle transition away from B0 status */
if (!(old_termios->c_cflag & CBAUD) &&
(tty->termios->c_cflag & CBAUD)) {
info->MCR |= (UART_MCR_DTR | UART_MCR_RTS);
- cli();
serial_out(info, UART_ESI_CMD1, ESI_WRITE_UART);
serial_out(info, UART_ESI_CMD2, UART_MCR);
serial_out(info, UART_ESI_CMD2, info->MCR);
- sti();
}
+ spin_unlock_irqrestore(&info->lock, flags);
+
/* Handle turning of CRTSCTS */
if ((old_termios->c_cflag & CRTSCTS) &&
!(tty->termios->c_cflag & CRTSCTS)) {
rs_start(tty);
}
-
-#if 0
- /*
- * No need to wake up processes in open wait, since they
- * sample the CLOCAL flag once, and don't recheck it.
- * XXX It's not clear whether the current behavior is correct
- * or not. Hence, this may change.....
- */
- if (!(old_termios->c_cflag & CLOCAL) &&
- (tty->termios->c_cflag & CLOCAL))
- wake_up_interruptible(&info->open_wait);
-#endif
}
/*
@@ -1978,7 +1998,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
if (!info || serial_paranoia_check(info, tty->name, "rs_close"))
return;
- save_flags(flags); cli();
+ spin_lock_irqsave(&info->lock, flags);
if (tty_hung_up_p(filp)) {
DBG_CNT("before DEC-hung");
@@ -2010,6 +2030,8 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
goto out;
}
info->flags |= ASYNC_CLOSING;
+
+ spin_unlock_irqrestore(&info->lock, flags);
/*
* Now we wait for the transmit buffer to clear; and we notify
* the line discipline to only process XON/XOFF characters.
@@ -2027,6 +2049,8 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
info->IER &= ~UART_IER_RDI;
info->read_status_mask &= ~UART_LSR_DR;
if (info->flags & ASYNC_INITIALIZED) {
+
+ spin_lock_irqsave(&info->lock, flags);
serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK);
serial_out(info, UART_ESI_CMD2, info->IER);
@@ -2034,6 +2058,8 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
serial_out(info, UART_ESI_CMD1, ESI_SET_RX_TIMEOUT);
serial_out(info, UART_ESI_CMD2, 0x00);
+ spin_unlock_irqrestore(&info->lock, flags);
+
/*
* Before we drop DTR, make sure the UART transmitter
* has completely drained; this is especially
@@ -2057,8 +2083,10 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
}
info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
wake_up_interruptible(&info->close_wait);
+ return;
+
out:
- restore_flags(flags);
+ spin_unlock_irqrestore(&info->lock, flags);
}
static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
@@ -2076,12 +2104,14 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
if (!char_time)
char_time = 1;
- save_flags(flags); cli();
+ spin_lock_irqsave(&info->lock, flags);
serial_out(info, UART_ESI_CMD1, ESI_NO_COMMAND);
serial_out(info, UART_ESI_CMD1, ESI_GET_TX_AVAIL);
while ((serial_in(info, UART_ESI_STAT1) != 0x03) ||
(serial_in(info, UART_ESI_STAT2) != 0xff)) {
+
+ spin_unlock_irqrestore(&info->lock, flags);
msleep_interruptible(jiffies_to_msecs(char_time));
if (signal_pending(current))
@@ -2090,11 +2120,11 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
if (timeout && time_after(jiffies, orig_jiffies + timeout))
break;
+ spin_lock_irqsave(&info->lock, flags);
serial_out(info, UART_ESI_CMD1, ESI_NO_COMMAND);
serial_out(info, UART_ESI_CMD1, ESI_GET_TX_AVAIL);
}
-
- restore_flags(flags);
+ spin_unlock_irqrestore(&info->lock, flags);
set_current_state(TASK_RUNNING);
}
@@ -2174,15 +2204,11 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
printk("block_til_ready before block: ttys%d, count = %d\n",
info->line, info->count);
#endif
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&info->lock, flags);
if (!tty_hung_up_p(filp))
info->count--;
- restore_flags(flags);
info->blocked_open++;
while (1) {
- save_flags(flags);
- cli();
if ((tty->termios->c_cflag & CBAUD)) {
unsigned int scratch;
@@ -2194,7 +2220,6 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
serial_out(info, UART_ESI_CMD2,
scratch | UART_MCR_DTR | UART_MCR_RTS);
}
- restore_flags(flags);
set_current_state(TASK_INTERRUPTIBLE);
if (tty_hung_up_p(filp) ||
!(info->flags & ASYNC_INITIALIZED)) {
@@ -2224,13 +2249,16 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
printk("block_til_ready blocking: ttys%d, count = %d\n",
info->line, info->count);
#endif
+ spin_unlock_irqrestore(&info->lock, flags);
schedule();
+ spin_lock_irqsave(&info->lock, flags);
}
set_current_state(TASK_RUNNING);
remove_wait_queue(&info->open_wait, &wait);
if (!tty_hung_up_p(filp))
info->count++;
info->blocked_open--;
+ spin_unlock_irqrestore(&info->lock, flags);
#ifdef SERIAL_DEBUG_OPEN
printk("block_til_ready after blocking: ttys%d, count = %d\n",
info->line, info->count);
@@ -2251,6 +2279,7 @@ static int esp_open(struct tty_struct *tty, struct file * filp)
{
struct esp_struct *info;
int retval, line;
+ unsigned long flags;
line = tty->index;
if ((line < 0) || (line >= NR_PORTS))
@@ -2271,6 +2300,7 @@ static int esp_open(struct tty_struct *tty, struct file * filp)
#ifdef SERIAL_DEBUG_OPEN
printk("esp_open %s, count = %d\n", tty->name, info->count);
#endif
+ spin_lock_irqsave(&info->lock, flags);
info->count++;
tty->driver_data = info;
info->tty = tty;
@@ -2317,7 +2347,7 @@ static int esp_open(struct tty_struct *tty, struct file * filp)
* driver.
*/
-static _INLINE_ void show_serial_version(void)
+static inline void show_serial_version(void)
{
printk(KERN_INFO "%s version %s (DMA %u)\n",
serial_name, serial_version, dma);
@@ -2327,7 +2357,7 @@ static _INLINE_ void show_serial_version(void)
* This routine is called by espserial_init() to initialize a specific serial
* port.
*/
-static _INLINE_ int autoconfig(struct esp_struct * info)
+static inline int autoconfig(struct esp_struct * info)
{
int port_detected = 0;
unsigned long flags;
@@ -2335,8 +2365,7 @@ static _INLINE_ int autoconfig(struct esp_struct * info)
if (!request_region(info->port, REGION_SIZE, "esp serial"))
return -EIO;
- save_flags(flags); cli();
-
+ spin_lock_irqsave(&info->lock, flags);
/*
* Check for ESP card
*/
@@ -2372,7 +2401,7 @@ static _INLINE_ int autoconfig(struct esp_struct * info)
if (!port_detected)
release_region(info->port, REGION_SIZE);
- restore_flags(flags);
+ spin_unlock_irqrestore(&info->lock, flags);
return (port_detected);
}
@@ -2513,6 +2542,7 @@ 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);
@@ -2563,18 +2593,14 @@ static int __init espserial_init(void)
static void __exit espserial_exit(void)
{
- unsigned long flags;
int e1;
struct esp_struct *temp_async;
struct esp_pio_buffer *pio_buf;
/* printk("Unloading %s: version %s\n", serial_name, serial_version); */
- save_flags(flags);
- cli();
if ((e1 = tty_unregister_driver(esp_driver)))
printk("SERIAL: failed to unregister serial driver (%d)\n",
e1);
- restore_flags(flags);
put_tty_driver(esp_driver);
while (ports) {
diff --git a/drivers/char/fep.h b/drivers/char/fep.h
deleted file mode 100644
index a941cc3a2906f..0000000000000
--- a/drivers/char/fep.h
+++ /dev/null
@@ -1,168 +0,0 @@
-
-#define CSTART 0x400L
-#define CMAX 0x800L
-#define ISTART 0x800L
-#define IMAX 0xC00L
-#define CIN 0xD10L
-#define GLOBAL 0xD10L
-#define EIN 0xD18L
-#define FEPSTAT 0xD20L
-#define CHANSTRUCT 0x1000L
-#define RXTXBUF 0x4000L
-
-
-struct global_data {
- volatile ushort cin;
- volatile ushort cout;
- volatile ushort cstart;
- volatile ushort cmax;
- volatile ushort ein;
- volatile ushort eout;
- volatile ushort istart;
- volatile ushort imax;
-};
-
-
-struct board_chan {
- int filler1;
- int filler2;
- volatile ushort tseg;
- volatile ushort tin;
- volatile ushort tout;
- volatile ushort tmax;
-
- volatile ushort rseg;
- volatile ushort rin;
- volatile ushort rout;
- volatile ushort rmax;
-
- volatile ushort tlow;
- volatile ushort rlow;
- volatile ushort rhigh;
- volatile ushort incr;
-
- volatile ushort etime;
- volatile ushort edelay;
- volatile unchar *dev;
-
- volatile ushort iflag;
- volatile ushort oflag;
- volatile ushort cflag;
- volatile ushort gmask;
-
- volatile ushort col;
- volatile ushort delay;
- volatile ushort imask;
- volatile ushort tflush;
-
- int filler3;
- int filler4;
- int filler5;
- int filler6;
-
- volatile unchar num;
- volatile unchar ract;
- volatile unchar bstat;
- volatile unchar tbusy;
- volatile unchar iempty;
- volatile unchar ilow;
- volatile unchar idata;
- volatile unchar eflag;
-
- volatile unchar tflag;
- volatile unchar rflag;
- volatile unchar xmask;
- volatile unchar xval;
- volatile unchar mstat;
- volatile unchar mchange;
- volatile unchar mint;
- volatile unchar lstat;
-
- volatile unchar mtran;
- volatile unchar orun;
- volatile unchar startca;
- volatile unchar stopca;
- volatile unchar startc;
- volatile unchar stopc;
- volatile unchar vnext;
- volatile unchar hflow;
-
- volatile unchar fillc;
- volatile unchar ochar;
- volatile unchar omask;
-
- unchar filler7;
- unchar filler8[28];
-};
-
-
-#define SRXLWATER 0xE0
-#define SRXHWATER 0xE1
-#define STOUT 0xE2
-#define PAUSETX 0xE3
-#define RESUMETX 0xE4
-#define SAUXONOFFC 0xE6
-#define SENDBREAK 0xE8
-#define SETMODEM 0xE9
-#define SETIFLAGS 0xEA
-#define SONOFFC 0xEB
-#define STXLWATER 0xEC
-#define PAUSERX 0xEE
-#define RESUMERX 0xEF
-#define SETBUFFER 0xF2
-#define SETCOOKED 0xF3
-#define SETHFLOW 0xF4
-#define SETCTRLFLAGS 0xF5
-#define SETVNEXT 0xF6
-
-
-#define BREAK_IND 0x01
-#define LOWTX_IND 0x02
-#define EMPTYTX_IND 0x04
-#define DATA_IND 0x08
-#define MODEMCHG_IND 0x20
-
-
-#define RTS 0x02
-#define CD 0x08
-#define DSR 0x10
-#define CTS 0x20
-#define RI 0x40
-#define DTR 0x80
-
- /* These are termios bits as the FEP understands them */
-
-/* c_cflag bit meaning */
-#define FEP_CBAUD 0000017
-#define FEP_B0 0000000 /* hang up */
-#define FEP_B50 0000001
-#define FEP_B75 0000002
-#define FEP_B110 0000003
-#define FEP_B134 0000004
-#define FEP_B150 0000005
-#define FEP_B200 0000006
-#define FEP_B300 0000007
-#define FEP_B600 0000010
-#define FEP_B1200 0000011
-#define FEP_B1800 0000012
-#define FEP_B2400 0000013
-#define FEP_B4800 0000014
-#define FEP_B9600 0000015
-#define FEP_B19200 0000016
-#define FEP_B38400 0000017
-#define FEP_EXTA FEP_B19200
-#define FEP_EXTB FEP_B38400
-#define FEP_CSIZE 0000060
-#define FEP_CS5 0000000
-#define FEP_CS6 0000020
-#define FEP_CS7 0000040
-#define FEP_CS8 0000060
-#define FEP_CSTOPB 0000100
-#define FEP_CREAD 0000200
-#define FEP_PARENB 0000400
-#define FEP_PARODD 0001000
-#define FEP_HUPCL 0002000
-#define FEP_CLOCAL 0004000
-#define FEP_CIBAUD 03600000 /* input baud rate (not used) */
-#define FEP_CRTSCTS 020000000000 /* flow control */
-
diff --git a/drivers/char/ftape/lowlevel/fdc-io.c b/drivers/char/ftape/lowlevel/fdc-io.c
index f589e7e98d363..1704a2a57048b 100644
--- a/drivers/char/ftape/lowlevel/fdc-io.c
+++ b/drivers/char/ftape/lowlevel/fdc-io.c
@@ -387,7 +387,8 @@ int fdc_interrupt_wait(unsigned int time)
set_current_state(TASK_INTERRUPTIBLE);
add_wait_queue(&ftape_wait_intr, &wait);
- while (!ft_interrupt_seen && (current->state == TASK_INTERRUPTIBLE)) {
+ while (!ft_interrupt_seen && timeout) {
+ set_current_state(TASK_INTERRUPTIBLE);
timeout = schedule_timeout(timeout);
}
diff --git a/drivers/char/generic_nvram.c b/drivers/char/generic_nvram.c
index b4d657d02d441..1b5e01e6e1299 100644
--- a/drivers/char/generic_nvram.c
+++ b/drivers/char/generic_nvram.c
@@ -51,7 +51,7 @@ static ssize_t read_nvram(struct file *file, char __user *buf,
unsigned int i;
char __user *p = buf;
- if (verify_area(VERIFY_WRITE, buf, count))
+ if (!access_ok(VERIFY_WRITE, buf, count))
return -EFAULT;
if (*ppos >= NVRAM_SIZE)
return 0;
@@ -69,7 +69,7 @@ static ssize_t write_nvram(struct file *file, const char __user *buf,
const char __user *p = buf;
char c;
- if (verify_area(VERIFY_READ, buf, count))
+ if (!access_ok(VERIFY_READ, buf, count))
return -EFAULT;
if (*ppos >= NVRAM_SIZE)
return 0;
diff --git a/drivers/char/generic_serial.c b/drivers/char/generic_serial.c
index 71435d1cb069e..5c8600b8dbe6b 100644
--- a/drivers/char/generic_serial.c
+++ b/drivers/char/generic_serial.c
@@ -26,6 +26,7 @@
#include <linux/mm.h>
#include <linux/generic_serial.h>
#include <linux/interrupt.h>
+#include <linux/tty_flip.h>
#include <linux/delay.h>
#include <asm/semaphore.h>
#include <asm/uaccess.h>
@@ -45,8 +46,8 @@ static int gs_debug;
#define func_enter() gs_dprintk (GS_DEBUG_FLOW, "gs: enter %s\n", __FUNCTION__)
#define func_exit() gs_dprintk (GS_DEBUG_FLOW, "gs: exit %s\n", __FUNCTION__)
-
-#ifdef NEW_WRITE_LOCKING
+#define NEW_WRITE_LOCKING 1
+#if NEW_WRITE_LOCKING
#define DECL /* Nothing */
#define LOCKIT down (& port->port_write_sem);
#define RELEASEIT up (&port->port_write_sem);
@@ -208,7 +209,7 @@ int gs_write(struct tty_struct * tty,
if (!port || !port->xmit_buf || !tmp_buf)
return -EIO;
- save_flags(flags);
+ local_save_flags(flags);
while (1) {
cli();
c = count;
@@ -227,14 +228,14 @@ int gs_write(struct tty_struct * tty,
/* Can't copy more? break out! */
if (c <= 0) {
- restore_flags(flags);
+ local_restore_flags(flags);
break;
}
memcpy(port->xmit_buf + port->xmit_head, buf, c);
port->xmit_head = ((port->xmit_head + c) &
(SERIAL_XMIT_SIZE-1));
port->xmit_cnt += c;
- restore_flags(flags);
+ local_restore_flags(flags);
buf += c;
count -= c;
total += c;
@@ -380,9 +381,9 @@ void gs_flush_buffer(struct tty_struct *tty)
if (!port) return;
/* XXX Would the write semaphore do? */
- save_flags(flags); cli();
+ spin_lock_irqsave (&port->driver_lock, flags);
port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
- restore_flags(flags);
+ spin_unlock_irqrestore (&port->driver_lock, flags);
wake_up_interruptible(&tty->write_wait);
tty_wakeup(tty);
@@ -468,8 +469,7 @@ static void gs_shutdown_port (struct gs_port *port)
if (!(port->flags & ASYNC_INITIALIZED))
return;
- save_flags (flags);
- cli ();
+ spin_lock_irqsave(&port->driver_lock, flags);
if (port->xmit_buf) {
free_page((unsigned long) port->xmit_buf);
@@ -482,7 +482,7 @@ static void gs_shutdown_port (struct gs_port *port)
port->rd->shutdown_port (port);
port->flags &= ~ASYNC_INITIALIZED;
- restore_flags (flags);
+ spin_unlock_irqrestore(&port->driver_lock, flags);
func_exit();
}
@@ -519,6 +519,7 @@ int gs_block_til_ready(void *port_, struct file * filp)
int do_clocal = 0;
int CD;
struct tty_struct *tty;
+ unsigned long flags;
func_enter ();
@@ -570,10 +571,11 @@ int gs_block_til_ready(void *port_, struct file * filp)
add_wait_queue(&port->open_wait, &wait);
gs_dprintk (GS_DEBUG_BTR, "after add waitq.\n");
- cli();
- if (!tty_hung_up_p(filp))
+ spin_lock_irqsave(&port->driver_lock, flags);
+ if (!tty_hung_up_p(filp)) {
port->count--;
- sti();
+ }
+ spin_unlock_irqrestore(&port->driver_lock, flags);
port->blocked_open++;
while (1) {
CD = port->rd->get_CD (port);
@@ -602,8 +604,9 @@ int gs_block_til_ready(void *port_, struct file * filp)
port->blocked_open);
set_current_state (TASK_RUNNING);
remove_wait_queue(&port->open_wait, &wait);
- if (!tty_hung_up_p(filp))
+ if (!tty_hung_up_p(filp)) {
port->count++;
+ }
port->blocked_open--;
if (retval)
return retval;
@@ -633,27 +636,29 @@ void gs_close(struct tty_struct * tty, struct file * filp)
port->tty = tty;
}
- save_flags(flags); cli();
+ spin_lock_irqsave(&port->driver_lock, flags);
if (tty_hung_up_p(filp)) {
- restore_flags(flags);
- port->rd->hungup (port);
+ spin_unlock_irqrestore(&port->driver_lock, flags);
+ if (port->rd->hungup)
+ port->rd->hungup (port);
func_exit ();
return;
}
if ((tty->count == 1) && (port->count != 1)) {
- printk(KERN_ERR "gs: gs_close: bad port count;"
- " tty->count is 1, port count is %d\n", port->count);
+ printk(KERN_ERR "gs: gs_close port %p: bad port count;"
+ " tty->count is 1, port count is %d\n", port, port->count);
port->count = 1;
}
if (--port->count < 0) {
- printk(KERN_ERR "gs: gs_close: bad port count: %d\n", port->count);
+ printk(KERN_ERR "gs: gs_close port %p: bad port count: %d\n", port, port->count);
port->count = 0;
}
+
if (port->count) {
- gs_dprintk(GS_DEBUG_CLOSE, "gs_close: count: %d\n", port->count);
- restore_flags(flags);
+ gs_dprintk(GS_DEBUG_CLOSE, "gs_close port %p: count: %d\n", port, port->count);
+ spin_unlock_irqrestore(&port->driver_lock, flags);
func_exit ();
return;
}
@@ -675,16 +680,17 @@ void gs_close(struct tty_struct * tty, struct file * filp)
*/
port->rd->disable_rx_interrupts (port);
+ spin_unlock_irqrestore(&port->driver_lock, flags);
/* close has no way of returning "EINTR", so discard return value */
if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
- gs_wait_tx_flushed (port, port->closing_wait);
+ gs_wait_tx_flushed (port, port->closing_wait);
port->flags &= ~GS_ACTIVE;
if (tty->driver->flush_buffer)
tty->driver->flush_buffer(tty);
-
+
tty_ldisc_flush(tty);
tty->closing = 0;
@@ -695,14 +701,15 @@ void gs_close(struct tty_struct * tty, struct file * filp)
if (port->blocked_open) {
if (port->close_delay) {
+ spin_unlock_irqrestore(&port->driver_lock, flags);
msleep_interruptible(jiffies_to_msecs(port->close_delay));
+ spin_lock_irqsave(&port->driver_lock, flags);
}
wake_up_interruptible(&port->open_wait);
}
port->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING | ASYNC_INITIALIZED);
wake_up_interruptible(&port->close_wait);
- restore_flags(flags);
func_exit ();
}
@@ -727,6 +734,12 @@ void gs_set_termios (struct tty_struct * tty,
port = tty->driver_data;
if (!port) return;
+ if (!port->tty) {
+ /* This seems to happen when this is called after gs_close. */
+ gs_dprintk (GS_DEBUG_TERMIOS, "gs: Odd: port->tty is NULL\n");
+ port->tty = tty;
+ }
+
tiosp = tty->termios;
@@ -821,7 +834,7 @@ void gs_set_termios (struct tty_struct * tty,
if (!(old_termios->c_cflag & CLOCAL) &&
(tty->termios->c_cflag & CLOCAL))
- wake_up_interruptible(&info->open_wait);
+ wake_up_interruptible(&port->gs.open_wait);
#endif
func_exit();
@@ -836,56 +849,56 @@ int gs_init_port(struct gs_port *port)
unsigned long flags;
unsigned long page;
- save_flags (flags);
- if (!tmp_buf) {
- page = get_zeroed_page(GFP_KERNEL);
+ func_enter ();
- cli (); /* Don't expect this to make a difference. */
+ if (!tmp_buf) {
+ page = get_zeroed_page(GFP_KERNEL);
+ spin_lock_irqsave (&port->driver_lock, flags); /* Don't expect this to make a difference. */
if (tmp_buf)
free_page(page);
else
tmp_buf = (unsigned char *) page;
- restore_flags (flags);
-
+ spin_unlock_irqrestore (&port->driver_lock, flags);
if (!tmp_buf) {
+ func_exit ();
return -ENOMEM;
}
}
- if (port->flags & ASYNC_INITIALIZED)
+ if (port->flags & ASYNC_INITIALIZED) {
+ func_exit ();
return 0;
-
+ }
if (!port->xmit_buf) {
/* We may sleep in get_zeroed_page() */
unsigned long tmp;
tmp = get_zeroed_page(GFP_KERNEL);
-
- /* Spinlock? */
- cli ();
+ spin_lock_irqsave (&port->driver_lock, flags);
if (port->xmit_buf)
free_page (tmp);
else
port->xmit_buf = (unsigned char *) tmp;
- restore_flags (flags);
-
- if (!port->xmit_buf)
+ spin_unlock_irqrestore(&port->driver_lock, flags);
+ if (!port->xmit_buf) {
+ func_exit ();
return -ENOMEM;
+ }
}
- cli();
-
+ spin_lock_irqsave (&port->driver_lock, flags);
if (port->tty)
clear_bit(TTY_IO_ERROR, &port->tty->flags);
-
+ init_MUTEX(&port->port_write_sem);
port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
-
+ spin_unlock_irqrestore(&port->driver_lock, flags);
gs_set_termios(port->tty, NULL);
-
+ spin_lock_irqsave (&port->driver_lock, flags);
port->flags |= ASYNC_INITIALIZED;
port->flags &= ~GS_TX_INTEN;
- restore_flags(flags);
+ spin_unlock_irqrestore(&port->driver_lock, flags);
+ func_exit ();
return 0;
}
@@ -956,13 +969,15 @@ int gs_getserial(struct gs_port *port, struct serial_struct __user *sp)
void gs_got_break(struct gs_port *port)
{
+ func_enter ();
+
+ tty_insert_flip_char(port->tty, 0, TTY_BREAK);
+ tty_schedule_flip(port->tty);
if (port->flags & ASYNC_SAK) {
do_SAK (port->tty);
}
- *(port->tty->flip.flag_buf_ptr) = TTY_BREAK;
- port->tty->flip.flag_buf_ptr++;
- port->tty->flip.char_buf_ptr++;
- port->tty->flip.count++;
+
+ func_exit ();
}
diff --git a/drivers/char/hp600_keyb.c b/drivers/char/hp600_keyb.c
deleted file mode 100644
index 71d70dfd4121e..0000000000000
--- a/drivers/char/hp600_keyb.c
+++ /dev/null
@@ -1,340 +0,0 @@
-/*
- * $Id$
- * Copyright (C) 2000 YAEGASHI Takeshi
- * HP600 keyboard scan routine and translation table
- * Copyright (C) 2000 Niibe Yutaka
- * HP620 keyboard translation table
- */
-
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/init.h>
-#include <linux/module.h>
-
-#include <asm/machvec.h>
-#include <asm/delay.h>
-#include <asm/io.h>
-#include "scan_keyb.h"
-
-#define PCDR 0xa4000124
-#define PDDR 0xa4000126
-#define PEDR 0xa4000128
-#define PFDR 0xa400012a
-#define PGDR 0xa400012c
-#define PHDR 0xa400012e
-#define PJDR 0xa4000130
-#define PKDR 0xa4000132
-#define PLDR 0xa4000134
-
-static const unsigned char hp620_japanese_table[] = {
- /* PTD1 */
- 0x0a, 0x0b, 0x0c, 0x00, 0x00, 0x0e, 0x00, 0x00,
- 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
- /* PTD5 */
- 0x18, 0x19, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
- /* PTD7 */
- 0x26, 0x1a, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25,
- /* PTE0 */
- 0x27, 0x1b, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x2a, 0x0f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
- /* PTE1 */
- 0x35, 0x28, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x70, 0x3a, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x34,
- /* PTE3 */
- 0x48, 0x4d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x2d, 0x2e, 0x7b, 0x30, 0x31, 0x32, 0x33,
- /* PTE6 */
- 0x4b, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x2c, 0x38, 0x00, 0x39, 0x79, 0x7d, 0x73,
- /* PTE7 */
- 0x41, 0x42, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40,
- /* **** */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-};
-
-
-static const unsigned char hp680_japanese_table[] = {
- /* PTD1 */
- 0x3a, 0x70, 0x29, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x3b, 0x3c, 0x3d, 0x42, 0x41, 0x40, 0x3e, 0x3f,
- /* PTD5 */
- 0x35, 0x28, 0x1c, 0x00, 0x2c, 0x00, 0x00, 0x00,
- 0x2d, 0x2e, 0x2f, 0x34, 0x33, 0x32, 0x30, 0x31,
- /* PTD7 */
- 0x50, 0x4d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x38, 0x7b,
- /* PTE0 */
- 0x00, 0x00, 0x00, 0x00, 0xdb, 0x00, 0x00, 0x00,
- 0x1d, 0x00, 0x39, 0x53, 0x73, 0xf9, 0x00, 0x00,
- /* PTE1 */
- 0x27, 0x1b, 0x2b, 0x00, 0x1e, 0x00, 0x00, 0x00,
- 0x1f, 0x20, 0x21, 0x26, 0x25, 0x24, 0x22, 0x23,
- /* PTE3 */
- 0x48, 0x7d, 0x36, 0x00, 0x0f, 0x00, 0x00, 0x00,
- 0x00, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- /* PTE6 */
- 0x19, 0x1a, 0x0e, 0x00, 0x10, 0x00, 0x00, 0x00,
- 0x11, 0x12, 0x13, 0x18, 0x17, 0x16, 0x14, 0x15,
- /* PTE7 */
- 0x0b, 0x0c, 0x0d, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x03, 0x04, 0x05, 0x0a, 0x09, 0x08, 0x06, 0x07,
- /* **** */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-};
-
-
-static int hp620_japanese_scan_kbd(unsigned char *s)
-{
- int i;
- unsigned char matrix_switch[] = {
- 0xfd, 0xff, /* PTD1 */
- 0xdf, 0xff, /* PTD5 */
- 0x7f, 0xff, /* PTD7 */
- 0xff, 0xfe, /* PTE0 */
- 0xff, 0xfd, /* PTE1 */
- 0xff, 0xf7, /* PTE3 */
- 0xff, 0xbf, /* PTE6 */
- 0xff, 0x7f, /* PTE7 */
- }, *t=matrix_switch;
-
- for(i=0; i<8; i++) {
- ctrl_outb(*t++, PDDR);
- ctrl_outb(*t++, PEDR);
- udelay(50);
- *s++=ctrl_inb(PCDR);
- *s++=ctrl_inb(PFDR);
- }
-
- ctrl_outb(0xff, PDDR);
- ctrl_outb(0xff, PEDR);
-
- *s++=ctrl_inb(PGDR);
- *s++=ctrl_inb(PHDR);
-
- return 0;
-}
-
-
-static int hp680_japanese_scan_kbd(unsigned char *s)
-{
- int i;
- unsigned char matrix_switch[] = {
- 0xfd, 0xff, /* PTD1 */
- 0xdf, 0xff, /* PTD5 */
- 0x7f, 0xff, /* PTD7 */
- 0xff, 0xfe, /* PTE0 */
- 0xff, 0xfd, /* PTE1 */
- 0xff, 0xf7, /* PTE3 */
- 0xff, 0xbf, /* PTE6 */
- 0xff, 0x7f, /* PTE7 */
- }, *t=matrix_switch;
-
- for(i=0; i<8; i++) {
- ctrl_outb(*t++, PDDR);
- ctrl_outb(*t++, PEDR);
- *s++=ctrl_inb(PCDR);
- *s++=ctrl_inb(PFDR);
- }
-
- ctrl_outb(0xff, PDDR);
- ctrl_outb(0xff, PEDR);
-
- *s++=ctrl_inb(PGDR);
- *s++=ctrl_inb(PHDR);
-
- return 0;
-}
-
-
-void __init hp600_kbd_init_hw(void)
-{
- scan_kbd_init();
-
- if (MACH_HP620)
- register_scan_keyboard(hp620_japanese_scan_kbd,
- hp620_japanese_table, 18);
- else if (MACH_HP680 || MACH_HP690)
- register_scan_keyboard(hp680_japanese_scan_kbd,
- hp680_japanese_table, 18);
-
- printk(KERN_INFO "HP600 matrix scan keyboard registered\n");
-}
-
-/****************************************************************
-HP Jornada 690(Japanese version) keyboard scan matrix
-
- PTC7 PTC6 PTC5 PTC4 PTC3 PTC2 PTC1 PTC0
-PTD1 REC Escape on/off Han/Zen Hira Eisu
-PTD5 REC Z on/off Enter : /
-PTD7 REC Right Down
-PTE0 REC Windows on/off
-PTE1 REC A on/off ] [ ;
-PTE3 REC Tab on/off ShirtR \ Up
-PTE6 REC Q on/off BS @ P
-PTE7 REC 1 on/off ^ - 0
-
- PTF7 PTF6 PTF5 PTF4 PTF3 PTF2 PTF1 PTF0
-PTD1 F5 F4 F6 F7 F8 F3 F2 F1
-PTD5 N B M , . V C X
-PTD7 Muhen Alt Left
-PTE0 Henkan _ Del Space Ctrl
-PTE1 H G J K L F D S
-PTE3 ShiftL
-PTE6 Y T U I O R E W
-PTE7 6 5 7 8 9 4 3 2
-
- PTG5 PTG4 PTG3 PTG0 PTH0
-* REC REW FWW Cover on/off
-
-
- 7 6 5 4 3 2 1 0
-C: 0xffff 0xdf IP IP IP IP IP IP IP IP
-D: 0x6786 0x59 O I O IP I F O I
-E: 0x5045 0x00 O O F F O F O O
-F: 0xffff 0xff IP IP IP IP IP IP IP IP
-G: 0xaffe 0xfd I I IP IP IP IP IP I
-H: 0x70f2 0x49 O IP F F IP IP F I
-J: 0x0704 0x22 F F O IP F F O F
-K: 0x0100 0x10 F F F O F F F F
-L: 0x0c3c 0x26 F F IP F F IP IP F
-
-****************************************************************/
-
-/****************************************************************
-HP Jornada 620(Japanese version) keyboard scan matrix
-
- PTC7 PTC6 PTC5 PTC4 PTC3 PTC2 PTC1 PTC0
-PTD1 EREC BS Ctrl on/off - 0 9
-PTD5 EREC BS Ctrl on/off ^ P O
-PTD7 EREC BS Ctrl on/off ] @ L
-PTE0 EREC BS Ctrl on/off Han/Zen [ ;
-PTE1 EREC BS Ctrl on/off Enter : /
-PTE3 EREC BS Ctrl on/off Right Up
-PTE6 EREC BS Ctrl on/off Down Left
-PTE7 EREC BS Ctrl on/off F8 F7
-
- PTF7 PTF6 PTF5 PTF4 PTF3 PTF2 PTF1 PTF0
-PTD1 8 7 6 5 4 3 2 1
-PTD5 I U Y T R E W Q
-PTD7 K J H G F D S A
-PTE0 ESC Tab Shift
-PTE1 . V Caps Hira
-PTE3 , M N B Muhen C X
-PTE6 _ \ Henkan Space Alt Z
-PTE7 F6 F5 F4 F3 F2 F1 REC
-
- PTH0
-* on/off
-
- 7 6 5 4 3 2 1 0
-C: 0xffff 0xff IP IP IP IP IP IP IP IP
-D: 0x4404 0xaf O F O F F F O F
-E: 0x5045 0xff O O F F O F O O
-F: 0xffff 0xff IP IP IP IP IP IP IP IP
-G: 0xd5ff 0x00 IP O O O IP IP IP IP
-H: 0x63ff 0xd1 O I F IP IP IP IP IP
-J: 0x0004 0x02 F F F F F F O F
-K: 0x0401 0xff F F O F F F F O
-L: 0x0c00 0x20 F F IP F F F F F
-
-ADCSR: 0x08
-ADCR: 0x3f
-
- ****************************************************************/
-
-/****************************************************************
-Japanese 109 keyboard scan code layout
-
- E02A- E1-
-01 3B 3C 3D 3E 3F 40 41 42 43 44 57 58 E037 46 1045
-
-29 02 03 04 05 06 07 08 09 0A 0B 0C 0D 7D 0E E052 E047 E049 45 E035 37 4A
-0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C E053 E04F E051 47 48 49 4E
-3A 1E 1F 20 21 22 23 24 25 26 27 28 2B 4B 4C 4D
-2A 2C 2D 2E 2F 30 31 32 33 34 35 73 36 E048 4F 50 51 E0-
-1D DB 38 7B 39 79 70 E038 DC DD E01D E04B E050 E04D 52 53 1C
-
-****************************************************************/
-
-#if 0
-int __init hp620_keyboard_test(void)
-{
- int i;
- unsigned char s[18];
- unsigned long a, b, c, d;
-
- printk("PCCR: %04lx, PCDR: %02lx\n",
- ctrl_inw(0xa4000104), ctrl_inb(0xa4000124));
- printk("PDCR: %04lx, PDDR: %02lx\n",
- ctrl_inw(0xa4000106), ctrl_inb(0xa4000126));
- printk("PECR: %04lx, PEDR: %02lx\n",
- ctrl_inw(0xa4000108), ctrl_inb(0xa4000128));
- printk("PFCR: %04lx, PFDR: %02lx\n",
- ctrl_inw(0xa400010a), ctrl_inb(0xa400012a));
- printk("PGCR: %04lx, PGDR: %02lx\n",
- ctrl_inw(0xa400010c), ctrl_inb(0xa400012c));
- printk("PHCR: %04lx, PHDR: %02lx\n",
- ctrl_inw(0xa400010e), ctrl_inb(0xa400012e));
- printk("PJCR: %04lx, PJDR: %02lx\n",
- ctrl_inw(0xa4000110), ctrl_inb(0xa4000130));
- printk("PKCR: %04lx, PKDR: %02lx\n",
- ctrl_inw(0xa4000112), ctrl_inb(0xa4000132));
- printk("PLCR: %04lx, PLDR: %02lx\n",
- ctrl_inw(0xa4000114), ctrl_inb(0xa4000134));
-
- printk("ADCSR: %02lx, ADCR: %02lx\n",
- ctrl_inb(0xa4000090), ctrl_inb(0xa4000092));
-
- ctrl_inb(0xa4000004);
- ctrl_inb(0xa4000006);
- ctrl_inb(0xa4000008);
- ctrl_outb(0, 0xa4000004);
- ctrl_outb(0, 0xa4000006);
- ctrl_outb(0, 0xa4000008);
- ctrl_outb(0, 0xa4000090);
- ctrl_outb(0x3b, 0xa4000090);
-
- while(1) {
- hp620_japanese_scan_kbd(s);
- for(i=0; i<18; i+=2)
- printk("%02x%02x ", s[i], s[i+1]);
-
-#if 0
- ctrl_outb(~2, PJDR);
- printk("%02lx%02lx ", ctrl_inb(PCDR), ctrl_inb(PFDR));
- ctrl_outb(0xff, PJDR);
- ctrl_outb(~1, PKDR);
- printk("%02lx%02lx ", ctrl_inb(PCDR), ctrl_inb(PFDR));
- ctrl_outb(~32, PKDR);
- printk("%02lx%02lx ", ctrl_inb(PCDR), ctrl_inb(PFDR));
- ctrl_outb(0xff, PKDR);
-#endif
-
- printk("%02lx%02lx%02lx%02lx ", a, b, c, d);
- if(ctrl_inb(0xa4000090)&0x80) {
- a=ctrl_inb(0xa4000080);
- b=ctrl_inb(0xa4000084);
- c=ctrl_inb(0xa4000088);
- d=ctrl_inb(0xa400008c);
- ctrl_outb(0x3b, 0xa4000090);
- }
- printk("%02lx%02lx%02lx ",
- ctrl_inb(0xa4000004),
- ctrl_inb(0xa4000006),
- ctrl_inb(0xa4000008));
-
- printk("\n");
- }
-
- return 0;
-}
-module_init(keyboard_probe);
-#endif
-
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c
index a266632e9b70b..5ec732e6ca922 100644
--- a/drivers/char/hpet.c
+++ b/drivers/char/hpet.c
@@ -76,6 +76,7 @@ struct hpet_dev {
struct hpets {
struct hpets *hp_next;
struct hpet __iomem *hp_hpet;
+ unsigned long hp_hpet_phys;
struct time_interpolator *hp_interpolator;
unsigned long hp_period;
unsigned long hp_delta;
@@ -265,7 +266,7 @@ static int hpet_mmap(struct file *file, struct vm_area_struct *vma)
return -EINVAL;
devp = file->private_data;
- addr = (unsigned long)devp->hd_hpet;
+ addr = devp->hd_hpets->hp_hpet_phys;
if (addr & (PAGE_SIZE - 1))
return -ENOSYS;
@@ -274,7 +275,7 @@ static int hpet_mmap(struct file *file, struct vm_area_struct *vma)
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
addr = __pa(addr);
- if (remap_pfn_range(vma, vma->vm_start, addr >> PAGE_SHIFT,
+ if (io_remap_pfn_range(vma, vma->vm_start, addr >> PAGE_SHIFT,
PAGE_SIZE, vma->vm_page_prot)) {
printk(KERN_ERR "remap_pfn_range failed in hpet.c\n");
return -EAGAIN;
@@ -795,6 +796,7 @@ int hpet_alloc(struct hpet_data *hdp)
hpetp->hp_which = hpet_nhpet++;
hpetp->hp_hpet = hdp->hd_address;
+ hpetp->hp_hpet_phys = hdp->hd_phys_address;
hpetp->hp_ntimer = hdp->hd_nirqs;
diff --git a/drivers/char/hvsi.c b/drivers/char/hvsi.c
index 07d7e212bb187..f1f1192ba2b50 100644
--- a/drivers/char/hvsi.c
+++ b/drivers/char/hvsi.c
@@ -631,27 +631,10 @@ static int __init poll_for_state(struct hvsi_struct *hp, int state)
/* wait for irq handler to change our state */
static int wait_for_state(struct hvsi_struct *hp, int state)
{
- unsigned long end_jiffies = jiffies + HVSI_TIMEOUT;
- unsigned long timeout;
int ret = 0;
- DECLARE_WAITQUEUE(myself, current);
- set_current_state(TASK_INTERRUPTIBLE);
- add_wait_queue(&hp->stateq, &myself);
-
- for (;;) {
- set_current_state(TASK_INTERRUPTIBLE);
- if (hp->state == state)
- break;
- timeout = end_jiffies - jiffies;
- if (time_after(jiffies, end_jiffies)) {
- ret = -EIO;
- break;
- }
- schedule_timeout(timeout);
- }
- remove_wait_queue(&hp->stateq, &myself);
- set_current_state(TASK_RUNNING);
+ if (!wait_event_timeout(hp->stateq, (hp->state == state), HVSI_TIMEOUT))
+ ret = -EIO;
return ret;
}
@@ -868,24 +851,7 @@ static int hvsi_open(struct tty_struct *tty, struct file *filp)
/* wait for hvsi_write_worker to empty hp->outbuf */
static void hvsi_flush_output(struct hvsi_struct *hp)
{
- unsigned long end_jiffies = jiffies + HVSI_TIMEOUT;
- unsigned long timeout;
-
- DECLARE_WAITQUEUE(myself, current);
- set_current_state(TASK_UNINTERRUPTIBLE);
- add_wait_queue(&hp->emptyq, &myself);
-
- for (;;) {
- set_current_state(TASK_UNINTERRUPTIBLE);
- if (hp->n_outbuf <= 0)
- break;
- timeout = end_jiffies - jiffies;
- if (time_after(jiffies, end_jiffies))
- break;
- schedule_timeout(timeout);
- }
- remove_wait_queue(&hp->emptyq, &myself);
- set_current_state(TASK_RUNNING);
+ wait_event_timeout(hp->emptyq, (hp->n_outbuf <= 0), HVSI_TIMEOUT);
/* 'writer' could still be pending if it didn't see n_outbuf = 0 yet */
cancel_delayed_work(&hp->writer);
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index fe02300e621c6..a6606a1aced72 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -612,6 +612,7 @@ int ipmi_create_user(unsigned int if_num,
unsigned long flags;
ipmi_user_t new_user;
int rv = 0;
+ ipmi_smi_t intf;
/* There is no module usecount here, because it's not
required. Since this can only be used by and called from
@@ -646,19 +647,29 @@ int ipmi_create_user(unsigned int if_num,
goto out_unlock;
}
+ intf = ipmi_interfaces[if_num];
+
new_user->handler = handler;
new_user->handler_data = handler_data;
- new_user->intf = ipmi_interfaces[if_num];
+ new_user->intf = intf;
new_user->gets_events = 0;
- if (!try_module_get(new_user->intf->handlers->owner)) {
+ if (!try_module_get(intf->handlers->owner)) {
rv = -ENODEV;
goto out_unlock;
}
- write_lock_irqsave(&new_user->intf->users_lock, flags);
- list_add_tail(&new_user->link, &new_user->intf->users);
- write_unlock_irqrestore(&new_user->intf->users_lock, flags);
+ if (intf->handlers->inc_usecount) {
+ rv = intf->handlers->inc_usecount(intf->send_info);
+ if (rv) {
+ module_put(intf->handlers->owner);
+ goto out_unlock;
+ }
+ }
+
+ write_lock_irqsave(&intf->users_lock, flags);
+ list_add_tail(&new_user->link, &intf->users);
+ write_unlock_irqrestore(&intf->users_lock, flags);
out_unlock:
if (rv) {
@@ -729,8 +740,11 @@ int ipmi_destroy_user(ipmi_user_t user)
down_read(&interfaces_sem);
write_lock_irqsave(&intf->users_lock, flags);
rv = ipmi_destroy_user_nolock(user);
- if (!rv)
+ if (!rv) {
module_put(intf->handlers->owner);
+ if (intf->handlers->dec_usecount)
+ intf->handlers->dec_usecount(intf->send_info);
+ }
write_unlock_irqrestore(&intf->users_lock, flags);
up_read(&interfaces_sem);
@@ -1629,6 +1643,7 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
void *send_info,
unsigned char version_major,
unsigned char version_minor,
+ unsigned char slave_addr,
ipmi_smi_t *intf)
{
int i, j;
@@ -1664,7 +1679,10 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
new_intf->intf_num = i;
new_intf->version_major = version_major;
new_intf->version_minor = version_minor;
- new_intf->my_address = IPMI_BMC_SLAVE_ADDR;
+ if (slave_addr == 0)
+ new_intf->my_address = IPMI_BMC_SLAVE_ADDR;
+ else
+ new_intf->my_address = slave_addr;
new_intf->my_lun = 2; /* the SMS LUN. */
rwlock_init(&(new_intf->users_lock));
INIT_LIST_HEAD(&(new_intf->users));
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index 82f0ed43ea32a..29de259a981e5 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -176,6 +176,9 @@ struct smi_info
unsigned char ipmi_version_major;
unsigned char ipmi_version_minor;
+ /* Slave address, could be reported from DMI. */
+ unsigned char slave_addr;
+
/* Counters and things for the proc filesystem. */
spinlock_t count_lock;
unsigned long short_timeouts;
@@ -407,7 +410,7 @@ static void handle_transaction_done(struct smi_info *smi_info)
/* Error fetching flags, just give up for
now. */
smi_info->si_state = SI_NORMAL;
- } else if (len < 3) {
+ } else if (len < 4) {
/* Hmm, no flags. That's technically illegal, but
don't use uninitialized data. */
smi_info->si_state = SI_NORMAL;
@@ -897,21 +900,23 @@ static struct smi_info *smi_infos[SI_MAX_DRIVERS] =
#define DEFAULT_REGSPACING 1
static int si_trydefaults = 1;
-static char *si_type[SI_MAX_PARMS] = { NULL, NULL, NULL, NULL };
+static char *si_type[SI_MAX_PARMS];
#define MAX_SI_TYPE_STR 30
static char si_type_str[MAX_SI_TYPE_STR];
-static unsigned long addrs[SI_MAX_PARMS] = { 0, 0, 0, 0 };
-static int num_addrs = 0;
-static unsigned int ports[SI_MAX_PARMS] = { 0, 0, 0, 0 };
-static int num_ports = 0;
-static int irqs[SI_MAX_PARMS] = { 0, 0, 0, 0 };
-static int num_irqs = 0;
-static int regspacings[SI_MAX_PARMS] = { 0, 0, 0, 0 };
+static unsigned long addrs[SI_MAX_PARMS];
+static int num_addrs;
+static unsigned int ports[SI_MAX_PARMS];
+static int num_ports;
+static int irqs[SI_MAX_PARMS];
+static int num_irqs;
+static int regspacings[SI_MAX_PARMS];
static int num_regspacings = 0;
-static int regsizes[SI_MAX_PARMS] = { 0, 0, 0, 0 };
+static int regsizes[SI_MAX_PARMS];
static int num_regsizes = 0;
-static int regshifts[SI_MAX_PARMS] = { 0, 0, 0, 0 };
+static int regshifts[SI_MAX_PARMS];
static int num_regshifts = 0;
+static int slave_addrs[SI_MAX_PARMS];
+static int num_slave_addrs = 0;
module_param_named(trydefaults, si_trydefaults, bool, 0);
@@ -955,6 +960,12 @@ MODULE_PARM_DESC(regshifts, "The amount to shift the data read from the."
" IPMI register, in bits. For instance, if the data"
" is read from a 32-bit word and the IPMI data is in"
" bit 8-15, then the shift would be 8");
+module_param_array(slave_addrs, int, &num_slave_addrs, 0);
+MODULE_PARM_DESC(slave_addrs, "Set the default IPMB slave address for"
+ " the controller. Normally this is 0x20, but can be"
+ " overridden by this parm. This is an array indexed"
+ " by interface number.");
+
#define IPMI_MEM_ADDR_SPACE 1
#define IPMI_IO_ADDR_SPACE 2
@@ -1466,6 +1477,11 @@ static int try_init_acpi(int intf_num, struct smi_info **new_info)
if (!is_new_interface(-1, addr_space, spmi->addr.address))
return -ENODEV;
+ if (!spmi->addr.register_bit_width) {
+ acpi_failure = 1;
+ return -ENODEV;
+ }
+
/* Figure out the interface type. */
switch (spmi->InterfaceType)
{
@@ -1542,7 +1558,6 @@ static int try_init_acpi(int intf_num, struct smi_info **new_info)
#endif
#ifdef CONFIG_X86
-
typedef struct dmi_ipmi_data
{
u8 type;
@@ -1550,21 +1565,26 @@ typedef struct dmi_ipmi_data
unsigned long base_addr;
u8 irq;
u8 offset;
-}dmi_ipmi_data_t;
+ u8 slave_addr;
+} dmi_ipmi_data_t;
+
+static dmi_ipmi_data_t dmi_data[SI_MAX_DRIVERS];
+static int dmi_data_entries;
typedef struct dmi_header
{
u8 type;
u8 length;
u16 handle;
-}dmi_header_t;
+} dmi_header_t;
-static int decode_dmi(dmi_header_t *dm, dmi_ipmi_data_t *ipmi_data)
+static int decode_dmi(dmi_header_t *dm, int intf_num)
{
u8 *data = (u8 *)dm;
unsigned long base_addr;
u8 reg_spacing;
u8 len = dm->length;
+ dmi_ipmi_data_t *ipmi_data = dmi_data+intf_num;
ipmi_data->type = data[4];
@@ -1608,22 +1628,26 @@ static int decode_dmi(dmi_header_t *dm, dmi_ipmi_data_t *ipmi_data)
ipmi_data->offset = 1;
}
- if (is_new_interface(-1, ipmi_data->addr_space,ipmi_data->base_addr))
+ ipmi_data->slave_addr = data[6];
+
+ if (is_new_interface(-1, ipmi_data->addr_space,ipmi_data->base_addr)) {
+ dmi_data_entries++;
return 0;
+ }
memset(ipmi_data, 0, sizeof(dmi_ipmi_data_t));
return -1;
}
-static int dmi_table(u32 base, int len, int num,
- dmi_ipmi_data_t *ipmi_data)
+static int dmi_table(u32 base, int len, int num)
{
u8 *buf;
struct dmi_header *dm;
u8 *data;
int i=1;
int status=-1;
+ int intf_num = 0;
buf = ioremap(base, len);
if(buf==NULL)
@@ -1639,9 +1663,10 @@ static int dmi_table(u32 base, int len, int num,
break;
if (dm->type == 38) {
- if (decode_dmi(dm, ipmi_data) == 0) {
- status = 0;
- break;
+ if (decode_dmi(dm, intf_num) == 0) {
+ intf_num++;
+ if (intf_num >= SI_MAX_DRIVERS)
+ break;
}
}
@@ -1666,7 +1691,7 @@ inline static int dmi_checksum(u8 *buf)
return (sum==0);
}
-static int dmi_iterator(dmi_ipmi_data_t *ipmi_data)
+static int dmi_decode(void)
{
u8 buf[15];
u32 fp=0xF0000;
@@ -1684,7 +1709,7 @@ static int dmi_iterator(dmi_ipmi_data_t *ipmi_data)
u16 len=buf[7]<<8|buf[6];
u32 base=buf[11]<<24|buf[10]<<16|buf[9]<<8|buf[8];
- if(dmi_table(base, len, num, ipmi_data) == 0)
+ if(dmi_table(base, len, num) == 0)
return 0;
}
fp+=16;
@@ -1696,16 +1721,13 @@ static int dmi_iterator(dmi_ipmi_data_t *ipmi_data)
static int try_init_smbios(int intf_num, struct smi_info **new_info)
{
struct smi_info *info;
- dmi_ipmi_data_t ipmi_data;
+ dmi_ipmi_data_t *ipmi_data = dmi_data+intf_num;
char *io_type;
- int status;
-
- status = dmi_iterator(&ipmi_data);
- if (status < 0)
+ if (intf_num >= dmi_data_entries)
return -ENODEV;
- switch(ipmi_data.type) {
+ switch(ipmi_data->type) {
case 0x01: /* KCS */
si_type[intf_num] = "kcs";
break;
@@ -1716,7 +1738,6 @@ static int try_init_smbios(int intf_num, struct smi_info **new_info)
si_type[intf_num] = "bt";
break;
default:
- printk("ipmi_si: Unknown SMBIOS SI type.\n");
return -EIO;
}
@@ -1727,15 +1748,15 @@ static int try_init_smbios(int intf_num, struct smi_info **new_info)
}
memset(info, 0, sizeof(*info));
- if (ipmi_data.addr_space == 1) {
+ if (ipmi_data->addr_space == 1) {
io_type = "memory";
info->io_setup = mem_setup;
- addrs[intf_num] = ipmi_data.base_addr;
+ addrs[intf_num] = ipmi_data->base_addr;
info->io.info = &(addrs[intf_num]);
- } else if (ipmi_data.addr_space == 2) {
+ } else if (ipmi_data->addr_space == 2) {
io_type = "I/O";
info->io_setup = port_setup;
- ports[intf_num] = ipmi_data.base_addr;
+ ports[intf_num] = ipmi_data->base_addr;
info->io.info = &(ports[intf_num]);
} else {
kfree(info);
@@ -1743,20 +1764,23 @@ static int try_init_smbios(int intf_num, struct smi_info **new_info)
return -EIO;
}
- regspacings[intf_num] = ipmi_data.offset;
+ regspacings[intf_num] = ipmi_data->offset;
info->io.regspacing = regspacings[intf_num];
if (!info->io.regspacing)
info->io.regspacing = DEFAULT_REGSPACING;
info->io.regsize = DEFAULT_REGSPACING;
info->io.regshift = regshifts[intf_num];
- irqs[intf_num] = ipmi_data.irq;
+ info->slave_addr = ipmi_data->slave_addr;
+
+ irqs[intf_num] = ipmi_data->irq;
*new_info = info;
printk("ipmi_si: Found SMBIOS-specified state machine at %s"
- " address 0x%lx\n",
- io_type, (unsigned long)ipmi_data.base_addr);
+ " address 0x%lx, slave address 0x%x\n",
+ io_type, (unsigned long)ipmi_data->base_addr,
+ ipmi_data->slave_addr);
return 0;
}
#endif /* CONFIG_X86 */
@@ -2121,6 +2145,7 @@ static int init_one_smi(int intf_num, struct smi_info **smi)
new_smi,
new_smi->ipmi_version_major,
new_smi->ipmi_version_minor,
+ new_smi->slave_addr,
&(new_smi->intf));
if (rv) {
printk(KERN_ERR
@@ -2222,6 +2247,10 @@ static __init int init_ipmi_si(void)
printk(", BT version %s", bt_smi_handlers.version);
printk("\n");
+#ifdef CONFIG_X86
+ dmi_decode();
+#endif
+
rv = init_one_smi(0, &(smi_infos[pos]));
if (rv && !ports[0] && si_trydefaults) {
/* If we are trying defaults and the initial port is
diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c
index 2ccde4de37cc2..601c7fccb4cfb 100644
--- a/drivers/char/isicom.c
+++ b/drivers/char/isicom.c
@@ -151,9 +151,6 @@ MODULE_DEVICE_TABLE(pci, isicom_pci_tbl);
static int prev_card = 3; /* start servicing isi_card[0] */
static struct tty_driver *isicom_normal;
-static struct isi_board isi_card[BOARD_COUNT];
-static struct isi_port isi_ports[PORT_COUNT];
-
static struct timer_list tx;
static char re_schedule = 1;
#ifdef ISICOM_DEBUG
@@ -210,6 +207,9 @@ struct isi_port {
int xmit_cnt;
};
+static struct isi_board isi_card[BOARD_COUNT];
+static struct isi_port isi_ports[PORT_COUNT];
+
/*
* Locking functions for card level locking. We need to own both
* the kernel lock for the card and have the card in a position that
@@ -381,7 +381,7 @@ static struct file_operations ISILoad_fops = {
.ioctl = ISILoad_ioctl,
};
-struct miscdevice isiloader_device = {
+static struct miscdevice isiloader_device = {
ISILOAD_MISC_MINOR, "isictl", &ISILoad_fops
};
@@ -1271,7 +1271,7 @@ static void isicom_shutdown_port(struct isi_port * port)
}
port->flags &= ~ASYNC_INITIALIZED;
/* 3rd October 2000 : Vinayak P Risbud */
- port->tty = 0;
+ port->tty = NULL;
spin_unlock_irqrestore(&card->card_lock, flags);
/*Fix done by Anil .S on 30-04-2001
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c
index 06b4572fa74a9..21aed0e8779de 100644
--- a/drivers/char/istallion.c
+++ b/drivers/char/istallion.c
@@ -41,6 +41,7 @@
#include <linux/init.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/device.h>
+#include <linux/wait.h>
#include <asm/io.h>
#include <asm/uaccess.h>
@@ -1068,11 +1069,10 @@ static int stli_open(struct tty_struct *tty, struct file *filp)
tty->driver_data = portp;
portp->refcount++;
- while (test_bit(ST_INITIALIZING, &portp->state)) {
- if (signal_pending(current))
- return(-ERESTARTSYS);
- interruptible_sleep_on(&portp->raw_wait);
- }
+ wait_event_interruptible(portp->raw_wait,
+ !test_bit(ST_INITIALIZING, &portp->state));
+ if (signal_pending(current))
+ return(-ERESTARTSYS);
if ((portp->flags & ASYNC_INITIALIZED) == 0) {
set_bit(ST_INITIALIZING, &portp->state);
@@ -1275,12 +1275,11 @@ static int stli_rawopen(stlibrd_t *brdp, stliport_t *portp, unsigned long arg, i
* order of opens and closes may not be preserved across shared
* memory, so we must wait until it is complete.
*/
- while (test_bit(ST_CLOSING, &portp->state)) {
- if (signal_pending(current)) {
- restore_flags(flags);
- return(-ERESTARTSYS);
- }
- interruptible_sleep_on(&portp->raw_wait);
+ wait_event_interruptible(portp->raw_wait,
+ !test_bit(ST_CLOSING, &portp->state));
+ if (signal_pending(current)) {
+ restore_flags(flags);
+ return -ERESTARTSYS;
}
/*
@@ -1309,13 +1308,10 @@ static int stli_rawopen(stlibrd_t *brdp, stliport_t *portp, unsigned long arg, i
*/
rc = 0;
set_bit(ST_OPENING, &portp->state);
- while (test_bit(ST_OPENING, &portp->state)) {
- if (signal_pending(current)) {
- rc = -ERESTARTSYS;
- break;
- }
- interruptible_sleep_on(&portp->raw_wait);
- }
+ wait_event_interruptible(portp->raw_wait,
+ !test_bit(ST_OPENING, &portp->state));
+ if (signal_pending(current))
+ rc = -ERESTARTSYS;
restore_flags(flags);
if ((rc == 0) && (portp->rc != 0))
@@ -1352,12 +1348,11 @@ static int stli_rawclose(stlibrd_t *brdp, stliport_t *portp, unsigned long arg,
* occurs on this port.
*/
if (wait) {
- while (test_bit(ST_CLOSING, &portp->state)) {
- if (signal_pending(current)) {
- restore_flags(flags);
- return(-ERESTARTSYS);
- }
- interruptible_sleep_on(&portp->raw_wait);
+ wait_event_interruptible(portp->raw_wait,
+ !test_bit(ST_CLOSING, &portp->state));
+ if (signal_pending(current)) {
+ restore_flags(flags);
+ return -ERESTARTSYS;
}
}
@@ -1385,13 +1380,10 @@ static int stli_rawclose(stlibrd_t *brdp, stliport_t *portp, unsigned long arg,
* to come back.
*/
rc = 0;
- while (test_bit(ST_CLOSING, &portp->state)) {
- if (signal_pending(current)) {
- rc = -ERESTARTSYS;
- break;
- }
- interruptible_sleep_on(&portp->raw_wait);
- }
+ wait_event_interruptible(portp->raw_wait,
+ !test_bit(ST_CLOSING, &portp->state));
+ if (signal_pending(current))
+ rc = -ERESTARTSYS;
restore_flags(flags);
if ((rc == 0) && (portp->rc != 0))
@@ -1420,22 +1412,20 @@ static int stli_cmdwait(stlibrd_t *brdp, stliport_t *portp, unsigned long cmd, v
save_flags(flags);
cli();
- while (test_bit(ST_CMDING, &portp->state)) {
- if (signal_pending(current)) {
- restore_flags(flags);
- return(-ERESTARTSYS);
- }
- interruptible_sleep_on(&portp->raw_wait);
+ wait_event_interruptible(portp->raw_wait,
+ !test_bit(ST_CMDING, &portp->state));
+ if (signal_pending(current)) {
+ restore_flags(flags);
+ return -ERESTARTSYS;
}
stli_sendcmd(brdp, portp, cmd, arg, size, copyback);
- while (test_bit(ST_CMDING, &portp->state)) {
- if (signal_pending(current)) {
- restore_flags(flags);
- return(-ERESTARTSYS);
- }
- interruptible_sleep_on(&portp->raw_wait);
+ wait_event_interruptible(portp->raw_wait,
+ !test_bit(ST_CMDING, &portp->state));
+ if (signal_pending(current)) {
+ restore_flags(flags);
+ return -ERESTARTSYS;
}
restore_flags(flags);
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c
index 48db369a93846..3ce51c6a1b182 100644
--- a/drivers/char/keyboard.c
+++ b/drivers/char/keyboard.c
@@ -141,7 +141,7 @@ static struct ledptr {
/* Simple translation table for the SysRq keys */
#ifdef CONFIG_MAGIC_SYSRQ
-unsigned char kbd_sysrq_xlate[KEY_MAX] =
+unsigned char kbd_sysrq_xlate[KEY_MAX + 1] =
"\000\0331234567890-=\177\t" /* 0x00 - 0x0f */
"qwertyuiop[]\r\000as" /* 0x10 - 0x1f */
"dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */
@@ -173,7 +173,7 @@ int getkeycode(unsigned int scancode)
if (!dev)
return -ENODEV;
- if (scancode < 0 || scancode >= dev->keycodemax)
+ if (scancode >= dev->keycodemax)
return -EINVAL;
return INPUT_KEYCODE(dev, scancode);
@@ -183,7 +183,7 @@ int setkeycode(unsigned int scancode, unsigned int keycode)
{
struct list_head * node;
struct input_dev *dev = NULL;
- int i, oldkey;
+ unsigned int i, oldkey;
list_for_each(node,&kbd_handler.h_list) {
struct input_handle *handle = to_handle_h(node);
@@ -196,7 +196,11 @@ int setkeycode(unsigned int scancode, unsigned int keycode)
if (!dev)
return -ENODEV;
- if (scancode < 0 || scancode >= dev->keycodemax)
+ if (scancode >= dev->keycodemax)
+ return -EINVAL;
+ if (keycode > KEY_MAX)
+ return -EINVAL;
+ if (keycode < 0 || keycode > KEY_MAX)
return -EINVAL;
oldkey = SET_INPUT_KEYCODE(dev, scancode, keycode);
@@ -353,7 +357,7 @@ static void to_utf8(struct vc_data *vc, ushort c)
*/
void compute_shiftstate(void)
{
- int i, j, k, sym, val;
+ unsigned int i, j, k, sym, val;
shift_state = 0;
memset(shift_down, 0, sizeof(shift_down));
@@ -394,7 +398,7 @@ void compute_shiftstate(void)
static unsigned char handle_diacr(struct vc_data *vc, unsigned char ch)
{
int d = diacr;
- int i;
+ unsigned int i;
diacr = 0;
@@ -534,12 +538,12 @@ static void fn_send_intr(struct vc_data *vc, struct pt_regs *regs)
static void fn_scroll_forw(struct vc_data *vc, struct pt_regs *regs)
{
- scrollfront(0);
+ scrollfront(vc, 0);
}
static void fn_scroll_back(struct vc_data *vc, struct pt_regs *regs)
{
- scrollback(0);
+ scrollback(vc, 0);
}
static void fn_show_mem(struct vc_data *vc, struct pt_regs *regs)
@@ -579,7 +583,7 @@ static void fn_SAK(struct vc_data *vc, struct pt_regs *regs)
*/
if (tty)
do_SAK(tty);
- reset_vc(fg_console);
+ reset_vc(vc);
}
static void fn_null(struct vc_data *vc, struct pt_regs *regs)
@@ -929,7 +933,7 @@ static void kbd_refresh_leds(struct input_handle *handle)
#if defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(CONFIG_ALPHA) ||\
defined(CONFIG_MIPS) || defined(CONFIG_PPC) || defined(CONFIG_SPARC32) ||\
defined(CONFIG_SPARC64) || defined(CONFIG_PARISC) || defined(CONFIG_SUPERH) ||\
- (defined(CONFIG_ARM) && defined(CONFIG_KEYBOARD_ATKBD) && !defined(CONFIG_RPC))
+ (defined(CONFIG_ARM) && defined(CONFIG_KEYBOARD_ATKBD) && !defined(CONFIG_ARCH_RPC))
#define HW_RAW(dev) (test_bit(EV_MSC, dev->evbit) && test_bit(MSC_RAW, dev->mscbit) &&\
((dev)->id.bustype == BUS_I8042) && ((dev)->id.vendor == 0x0001) && ((dev)->id.product == 0x0001))
diff --git a/drivers/char/lp.c b/drivers/char/lp.c
index 92a54cb659d68..4dee945031d45 100644
--- a/drivers/char/lp.c
+++ b/drivers/char/lp.c
@@ -12,7 +12,7 @@
* "lp=" command line parameters added by Grant Guenther, grant@torque.net
* lp_read (Status readback) support added by Carsten Gross,
* carsten@sol.wohnheim.uni-ulm.de
- * Support for parport by Philip Blundell <Philip.Blundell@pobox.com>
+ * Support for parport by Philip Blundell <philb@gnu.org>
* Parport sharing hacking by Andrea Arcangeli
* Fixed kernel_(to/from)_user memory copy to check for errors
* by Riccardo Facchetti <fizban@tin.it>
@@ -127,6 +127,7 @@
#include <linux/poll.h>
#include <linux/console.h>
#include <linux/device.h>
+#include <linux/wait.h>
#include <linux/parport.h>
#undef LP_STATS
@@ -218,6 +219,7 @@ static int lp_reset(int minor)
static void lp_error (int minor)
{
+ DEFINE_WAIT(wait);
int polling;
if (LP_F(minor) & LP_ABORT)
@@ -225,8 +227,9 @@ static void lp_error (int minor)
polling = lp_table[minor].dev->port->irq == PARPORT_IRQ_NONE;
if (polling) lp_release_parport (&lp_table[minor]);
- interruptible_sleep_on_timeout (&lp_table[minor].waitq,
- LP_TIMEOUT_POLLED);
+ prepare_to_wait(&lp_table[minor].waitq, &wait, TASK_INTERRUPTIBLE);
+ schedule_timeout(LP_TIMEOUT_POLLED);
+ finish_wait(&lp_table[minor].waitq, &wait);
if (polling) lp_claim_parport_or_block (&lp_table[minor]);
else parport_yield_blocking (lp_table[minor].dev);
}
@@ -314,12 +317,14 @@ static ssize_t lp_write(struct file * file, const char __user * buf,
if (copy_size > LP_BUFFER_SIZE)
copy_size = LP_BUFFER_SIZE;
- if (copy_from_user (kbuf, buf, copy_size))
- return -EFAULT;
-
if (down_interruptible (&lp_table[minor].port_mutex))
return -EINTR;
+ if (copy_from_user (kbuf, buf, copy_size)) {
+ retv = -EFAULT;
+ goto out_unlock;
+ }
+
/* Claim Parport or sleep until it becomes available
*/
lp_claim_parport_or_block (&lp_table[minor]);
@@ -398,7 +403,7 @@ static ssize_t lp_write(struct file * file, const char __user * buf,
lp_table[minor].current_mode = IEEE1284_MODE_COMPAT;
lp_release_parport (&lp_table[minor]);
}
-
+out_unlock:
up (&lp_table[minor].port_mutex);
return retv;
@@ -410,6 +415,7 @@ static ssize_t lp_write(struct file * file, const char __user * buf,
static ssize_t lp_read(struct file * file, char __user * buf,
size_t count, loff_t *ppos)
{
+ DEFINE_WAIT(wait);
unsigned int minor=iminor(file->f_dentry->d_inode);
struct parport *port = lp_table[minor].dev->port;
ssize_t retval = 0;
@@ -458,9 +464,11 @@ static ssize_t lp_read(struct file * file, char __user * buf,
retval = -EIO;
goto out;
}
- } else
- interruptible_sleep_on_timeout (&lp_table[minor].waitq,
- LP_TIMEOUT_POLLED);
+ } else {
+ prepare_to_wait(&lp_table[minor].waitq, &wait, TASK_INTERRUPTIBLE);
+ schedule_timeout(LP_TIMEOUT_POLLED);
+ finish_wait(&lp_table[minor].waitq, &wait);
+ }
if (signal_pending (current)) {
retval = -ERESTARTSYS;
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index 840a0afaeb1b2..947cb3cef8167 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -23,6 +23,7 @@
#include <linux/devfs_fs_kernel.h>
#include <linux/ptrace.h>
#include <linux/device.h>
+#include <linux/backing-dev.h>
#include <asm/uaccess.h>
#include <asm/io.h>
@@ -76,14 +77,6 @@ static inline int uncached_access(struct file *file, unsigned long addr)
* On ia64, we ignore O_SYNC because we cannot tolerate memory attribute aliases.
*/
return !(efi_mem_attributes(addr) & EFI_MEMORY_WB);
-#elif defined(CONFIG_PPC64)
- /* On PPC64, we always do non-cacheable access to the IO hole and
- * cacheable elsewhere. Cache paradox can checkstop the CPU and
- * the high_memory heuristic below is wrong on machines with memory
- * above the IO hole... Ah, and of course, XFree86 doesn't pass
- * O_SYNC when mapping us to tap IO space. Surprised ?
- */
- return !page_is_ram(addr >> PAGE_SHIFT);
#else
/*
* Accessing memory above the top the kernel knows about or through a file pointer
@@ -111,39 +104,6 @@ static inline int valid_phys_addr_range(unsigned long addr, size_t *count)
}
#endif
-static ssize_t do_write_mem(void *p, unsigned long realp,
- const char __user * buf, size_t count, loff_t *ppos)
-{
- ssize_t written;
- unsigned long copied;
-
- written = 0;
-#if defined(__sparc__) || (defined(__mc68000__) && defined(CONFIG_MMU))
- /* we don't have page 0 mapped on sparc and m68k.. */
- if (realp < PAGE_SIZE) {
- unsigned long sz = PAGE_SIZE-realp;
- if (sz > count) sz = count;
- /* Hmm. Do something? */
- buf+=sz;
- p+=sz;
- count-=sz;
- written+=sz;
- }
-#endif
- copied = copy_from_user(p, buf, count);
- if (copied) {
- ssize_t ret = written + (count - copied);
-
- if (ret)
- return ret;
- return -EFAULT;
- }
- written += count;
- *ppos += written;
- return written;
-}
-
-
/*
* This funcion reads the *physical* memory. The f_pos points directly to the
* memory location.
@@ -152,15 +112,16 @@ static ssize_t read_mem(struct file * file, char __user * buf,
size_t count, loff_t *ppos)
{
unsigned long p = *ppos;
- ssize_t read;
+ ssize_t read, sz;
+ char *ptr;
if (!valid_phys_addr_range(p, &count))
return -EFAULT;
read = 0;
-#if defined(__sparc__) || (defined(__mc68000__) && defined(CONFIG_MMU))
+#ifdef __ARCH_HAS_NO_PAGE_ZERO_MAPPED
/* we don't have page 0 mapped on sparc and m68k.. */
if (p < PAGE_SIZE) {
- unsigned long sz = PAGE_SIZE-p;
+ sz = PAGE_SIZE - p;
if (sz > count)
sz = count;
if (sz > 0) {
@@ -173,9 +134,33 @@ static ssize_t read_mem(struct file * file, char __user * buf,
}
}
#endif
- if (copy_to_user(buf, __va(p), count))
- return -EFAULT;
- read += count;
+
+ while (count > 0) {
+ /*
+ * Handle first page in case it's not aligned
+ */
+ if (-p & (PAGE_SIZE - 1))
+ sz = -p & (PAGE_SIZE - 1);
+ else
+ sz = PAGE_SIZE;
+
+ sz = min_t(unsigned long, sz, count);
+
+ /*
+ * On ia64 if a page has been mapped somewhere as
+ * uncached, then it must also be accessed uncached
+ * by the kernel or data corruption may occur
+ */
+ ptr = xlate_dev_mem_ptr(p);
+
+ if (copy_to_user(buf, ptr, sz))
+ return -EFAULT;
+ buf += sz;
+ p += sz;
+ count -= sz;
+ read += sz;
+ }
+
*ppos += read;
return read;
}
@@ -184,15 +169,75 @@ static ssize_t write_mem(struct file * file, const char __user * buf,
size_t count, loff_t *ppos)
{
unsigned long p = *ppos;
+ ssize_t written, sz;
+ unsigned long copied;
+ void *ptr;
if (!valid_phys_addr_range(p, &count))
return -EFAULT;
- return do_write_mem(__va(p), p, buf, count, ppos);
+
+ written = 0;
+
+#ifdef __ARCH_HAS_NO_PAGE_ZERO_MAPPED
+ /* we don't have page 0 mapped on sparc and m68k.. */
+ if (p < PAGE_SIZE) {
+ unsigned long sz = PAGE_SIZE - p;
+ if (sz > count)
+ sz = count;
+ /* Hmm. Do something? */
+ buf += sz;
+ p += sz;
+ count -= sz;
+ written += sz;
+ }
+#endif
+
+ while (count > 0) {
+ /*
+ * Handle first page in case it's not aligned
+ */
+ if (-p & (PAGE_SIZE - 1))
+ sz = -p & (PAGE_SIZE - 1);
+ else
+ sz = PAGE_SIZE;
+
+ sz = min_t(unsigned long, sz, count);
+
+ /*
+ * On ia64 if a page has been mapped somewhere as
+ * uncached, then it must also be accessed uncached
+ * by the kernel or data corruption may occur
+ */
+ ptr = xlate_dev_mem_ptr(p);
+
+ copied = copy_from_user(ptr, buf, sz);
+ if (copied) {
+ ssize_t ret;
+
+ ret = written + (sz - copied);
+ if (ret)
+ return ret;
+ return -EFAULT;
+ }
+ buf += sz;
+ p += sz;
+ count -= sz;
+ written += sz;
+ }
+
+ *ppos += written;
+ return written;
}
static int mmap_mem(struct file * file, struct vm_area_struct * vma)
{
-#ifdef pgprot_noncached
+#if defined(__HAVE_PHYS_MEM_ACCESS_PROT)
+ unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+
+ vma->vm_page_prot = phys_mem_access_prot(file, offset,
+ vma->vm_end - vma->vm_start,
+ vma->vm_page_prot);
+#elif defined(pgprot_noncached)
unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
int uncached;
@@ -211,6 +256,23 @@ static int mmap_mem(struct file * file, struct vm_area_struct * vma)
return 0;
}
+static int mmap_kmem(struct file * file, struct vm_area_struct * vma)
+{
+ unsigned long long val;
+ /*
+ * RED-PEN: on some architectures there is more mapped memory
+ * than available in mem_map which pfn_valid checks
+ * for. Perhaps should add a new macro here.
+ *
+ * RED-PEN: vmalloc is not supported right now.
+ */
+ if (!pfn_valid(vma->vm_pgoff))
+ return -EIO;
+ val = (u64)vma->vm_pgoff << PAGE_SHIFT;
+ vma->vm_pgoff = __pa(val) >> PAGE_SHIFT;
+ return mmap_mem(file, vma);
+}
+
extern long vread(char *buf, char *addr, unsigned long count);
extern long vwrite(char *buf, char *addr, unsigned long count);
@@ -221,33 +283,55 @@ static ssize_t read_kmem(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
unsigned long p = *ppos;
- ssize_t read = 0;
- ssize_t virtr = 0;
+ ssize_t low_count, read, sz;
char * kbuf; /* k-addr because vread() takes vmlist_lock rwlock */
-
+
+ read = 0;
if (p < (unsigned long) high_memory) {
- read = count;
+ low_count = count;
if (count > (unsigned long) high_memory - p)
- read = (unsigned long) high_memory - p;
+ low_count = (unsigned long) high_memory - p;
-#if defined(__sparc__) || (defined(__mc68000__) && defined(CONFIG_MMU))
+#ifdef __ARCH_HAS_NO_PAGE_ZERO_MAPPED
/* we don't have page 0 mapped on sparc and m68k.. */
- if (p < PAGE_SIZE && read > 0) {
+ if (p < PAGE_SIZE && low_count > 0) {
size_t tmp = PAGE_SIZE - p;
- if (tmp > read) tmp = read;
+ if (tmp > low_count) tmp = low_count;
if (clear_user(buf, tmp))
return -EFAULT;
buf += tmp;
p += tmp;
- read -= tmp;
+ read += tmp;
+ low_count -= tmp;
count -= tmp;
}
#endif
- if (copy_to_user(buf, (char *)p, read))
- return -EFAULT;
- p += read;
- buf += read;
- count -= read;
+ while (low_count > 0) {
+ /*
+ * Handle first page in case it's not aligned
+ */
+ if (-p & (PAGE_SIZE - 1))
+ sz = -p & (PAGE_SIZE - 1);
+ else
+ sz = PAGE_SIZE;
+
+ sz = min_t(unsigned long, sz, low_count);
+
+ /*
+ * On ia64 if a page has been mapped somewhere as
+ * uncached, then it must also be accessed uncached
+ * by the kernel or data corruption may occur
+ */
+ kbuf = xlate_dev_kmem_ptr((char *)p);
+
+ if (copy_to_user(buf, kbuf, sz))
+ return -EFAULT;
+ buf += sz;
+ p += sz;
+ read += sz;
+ low_count -= sz;
+ count -= sz;
+ }
}
if (count > 0) {
@@ -268,15 +352,79 @@ static ssize_t read_kmem(struct file *file, char __user *buf,
}
count -= len;
buf += len;
- virtr += len;
+ read += len;
p += len;
}
free_page((unsigned long)kbuf);
}
*ppos = p;
- return virtr + read;
+ return read;
+}
+
+
+static inline ssize_t
+do_write_kmem(void *p, unsigned long realp, const char __user * buf,
+ size_t count, loff_t *ppos)
+{
+ ssize_t written, sz;
+ unsigned long copied;
+
+ written = 0;
+#ifdef __ARCH_HAS_NO_PAGE_ZERO_MAPPED
+ /* we don't have page 0 mapped on sparc and m68k.. */
+ if (realp < PAGE_SIZE) {
+ unsigned long sz = PAGE_SIZE - realp;
+ if (sz > count)
+ sz = count;
+ /* Hmm. Do something? */
+ buf += sz;
+ p += sz;
+ realp += sz;
+ count -= sz;
+ written += sz;
+ }
+#endif
+
+ while (count > 0) {
+ char *ptr;
+ /*
+ * Handle first page in case it's not aligned
+ */
+ if (-realp & (PAGE_SIZE - 1))
+ sz = -realp & (PAGE_SIZE - 1);
+ else
+ sz = PAGE_SIZE;
+
+ sz = min_t(unsigned long, sz, count);
+
+ /*
+ * On ia64 if a page has been mapped somewhere as
+ * uncached, then it must also be accessed uncached
+ * by the kernel or data corruption may occur
+ */
+ ptr = xlate_dev_kmem_ptr(p);
+
+ copied = copy_from_user(ptr, buf, sz);
+ if (copied) {
+ ssize_t ret;
+
+ ret = written + (sz - copied);
+ if (ret)
+ return ret;
+ return -EFAULT;
+ }
+ buf += sz;
+ p += sz;
+ realp += sz;
+ count -= sz;
+ written += sz;
+ }
+
+ *ppos += written;
+ return written;
}
+
/*
* This function writes to the *virtual* memory as seen by the kernel.
*/
@@ -295,7 +443,7 @@ static ssize_t write_kmem(struct file * file, const char __user * buf,
if (count > (unsigned long) high_memory - p)
wrote = (unsigned long) high_memory - p;
- written = do_write_mem((void*)p, p, buf, wrote, ppos);
+ written = do_write_kmem((void*)p, p, buf, wrote, ppos);
if (written != wrote)
return written;
wrote = written;
@@ -343,7 +491,7 @@ static ssize_t read_port(struct file * file, char __user * buf,
unsigned long i = *ppos;
char __user *tmp = buf;
- if (verify_area(VERIFY_WRITE,buf,count))
+ if (!access_ok(VERIFY_WRITE, buf, count))
return -EFAULT;
while (count-- > 0 && i < 65536) {
if (__put_user(inb(i),tmp) < 0)
@@ -361,7 +509,7 @@ static ssize_t write_port(struct file * file, const char __user * buf,
unsigned long i = *ppos;
const char __user * tmp = buf;
- if (verify_area(VERIFY_READ,buf,count))
+ if (!access_ok(VERIFY_READ,buf,count))
return -EFAULT;
while (count-- > 0 && i < 65536) {
char c;
@@ -567,7 +715,6 @@ static int open_port(struct inode * inode, struct file * filp)
return capable(CAP_SYS_RAWIO) ? 0 : -EPERM;
}
-#define mmap_kmem mmap_mem
#define zero_lseek null_lseek
#define full_lseek null_lseek
#define write_zero write_null
@@ -613,6 +760,10 @@ static struct file_operations zero_fops = {
.mmap = mmap_zero,
};
+static struct backing_dev_info zero_bdi = {
+ .capabilities = BDI_CAP_MAP_COPY,
+};
+
static struct file_operations full_fops = {
.llseek = full_lseek,
.read = read_full,
@@ -659,6 +810,7 @@ static int memory_open(struct inode * inode, struct file * filp)
break;
#endif
case 5:
+ filp->f_mapping->backing_dev_info = &zero_bdi;
filp->f_op = &zero_fops;
break;
case 7:
diff --git a/drivers/char/mmtimer.c b/drivers/char/mmtimer.c
index 3539b4acfc94d..58eddfdd3110a 100644
--- a/drivers/char/mmtimer.c
+++ b/drivers/char/mmtimer.c
@@ -71,11 +71,6 @@ static struct file_operations mmtimer_fops = {
};
/*
- * Comparators and their associated info. Shub has
- * three comparison registers.
- */
-
-/*
* We only have comparison registers RTC1-4 currently available per
* node. RTC0 is used by SAL.
*/
@@ -174,14 +169,10 @@ static void inline mmtimer_setup_int_2(u64 expires)
* This function must be called with interrupts disabled and preemption off
* in order to insure that the setup succeeds in a deterministic time frame.
* It will check if the interrupt setup succeeded.
- * mmtimer_setup will return the cycles that we were too late if the
- * initialization failed.
*/
static int inline mmtimer_setup(int comparator, unsigned long expires)
{
- long diff;
-
switch (comparator) {
case 0:
mmtimer_setup_int_0(expires);
@@ -194,17 +185,14 @@ static int inline mmtimer_setup(int comparator, unsigned long expires)
break;
}
/* We might've missed our expiration time */
- diff = rtc_time() - expires;
- if (diff > 0) {
- if (mmtimer_int_pending(comparator)) {
- /* We'll get an interrupt for this once we're done */
- return 0;
- }
- /* Looks like we missed it */
- return diff;
- }
+ if (rtc_time() < expires)
+ return 1;
- return 0;
+ /*
+ * If an interrupt is already pending then its okay
+ * if not then we failed
+ */
+ return mmtimer_int_pending(comparator);
}
static int inline mmtimer_disable_int(long nasid, int comparator)
@@ -376,7 +364,7 @@ static int sgi_clock_period;
static struct timespec sgi_clock_offset;
static int sgi_clock_period;
-static int sgi_clock_get(struct timespec *tp)
+static int sgi_clock_get(clockid_t clockid, struct timespec *tp)
{
u64 nsec;
@@ -387,7 +375,7 @@ static int sgi_clock_get(struct timespec *tp)
return 0;
};
-static int sgi_clock_set(struct timespec *tp)
+static int sgi_clock_set(clockid_t clockid, struct timespec *tp)
{
u64 nsec;
@@ -418,19 +406,19 @@ static int inline reschedule_periodic_timer(mmtimer_t *x)
int n;
struct k_itimer *t = x->timer;
- t->it_timer.magic = x->i;
+ t->it.mmtimer.clock = x->i;
t->it_overrun--;
n = 0;
do {
- t->it_timer.expires += t->it_incr << n;
+ t->it.mmtimer.expires += t->it.mmtimer.incr << n;
t->it_overrun += 1 << n;
n++;
if (n > 20)
return 1;
- } while (mmtimer_setup(x->i, t->it_timer.expires));
+ } while (!mmtimer_setup(x->i, t->it.mmtimer.expires));
return 0;
}
@@ -466,7 +454,7 @@ mmtimer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
spin_lock(&base[i].lock);
if (base[i].cpu == smp_processor_id()) {
if (base[i].timer)
- expires = base[i].timer->it_timer.expires;
+ expires = base[i].timer->it.mmtimer.expires;
/* expires test won't work with shared irqs */
if ((mmtimer_int_pending(i) > 0) ||
(expires && (expires < rtc_time()))) {
@@ -503,7 +491,7 @@ void mmtimer_tasklet(unsigned long data) {
t->it_overrun++;
}
- if(t->it_incr) {
+ if(t->it.mmtimer.incr) {
/* Periodic timer */
if (reschedule_periodic_timer(x)) {
printk(KERN_WARNING "mmtimer: unable to reschedule\n");
@@ -511,7 +499,7 @@ void mmtimer_tasklet(unsigned long data) {
}
} else {
/* Ensure we don't false trigger in mmtimer_interrupt */
- t->it_timer.expires = 0;
+ t->it.mmtimer.expires = 0;
}
t->it_overrun_last = t->it_overrun;
out:
@@ -522,7 +510,7 @@ out:
static int sgi_timer_create(struct k_itimer *timer)
{
/* Insure that a newly created timer is off */
- timer->it_timer.magic = TIMER_OFF;
+ timer->it.mmtimer.clock = TIMER_OFF;
return 0;
}
@@ -533,8 +521,8 @@ static int sgi_timer_create(struct k_itimer *timer)
*/
static int sgi_timer_del(struct k_itimer *timr)
{
- int i = timr->it_timer.magic;
- cnodeid_t nodeid = timr->it_timer.data;
+ int i = timr->it.mmtimer.clock;
+ cnodeid_t nodeid = timr->it.mmtimer.node;
mmtimer_t *t = timers + nodeid * NUM_COMPARATORS +i;
unsigned long irqflags;
@@ -542,8 +530,8 @@ static int sgi_timer_del(struct k_itimer *timr)
spin_lock_irqsave(&t->lock, irqflags);
mmtimer_disable_int(cnodeid_to_nasid(nodeid),i);
t->timer = NULL;
- timr->it_timer.magic = TIMER_OFF;
- timr->it_timer.expires = 0;
+ timr->it.mmtimer.clock = TIMER_OFF;
+ timr->it.mmtimer.expires = 0;
spin_unlock_irqrestore(&t->lock, irqflags);
}
return 0;
@@ -556,7 +544,7 @@ static int sgi_timer_del(struct k_itimer *timr)
static void sgi_timer_get(struct k_itimer *timr, struct itimerspec *cur_setting)
{
- if (timr->it_timer.magic == TIMER_OFF) {
+ if (timr->it.mmtimer.clock == TIMER_OFF) {
cur_setting->it_interval.tv_nsec = 0;
cur_setting->it_interval.tv_sec = 0;
cur_setting->it_value.tv_nsec = 0;
@@ -564,8 +552,8 @@ static void sgi_timer_get(struct k_itimer *timr, struct itimerspec *cur_setting)
return;
}
- ns_to_timespec(cur_setting->it_interval, timr->it_incr * sgi_clock_period);
- ns_to_timespec(cur_setting->it_value, (timr->it_timer.expires - rtc_time())* sgi_clock_period);
+ ns_to_timespec(cur_setting->it_interval, timr->it.mmtimer.incr * sgi_clock_period);
+ ns_to_timespec(cur_setting->it_value, (timr->it.mmtimer.expires - rtc_time())* sgi_clock_period);
return;
}
@@ -594,9 +582,15 @@ static int sgi_timer_set(struct k_itimer *timr, int flags,
if (flags & TIMER_ABSTIME) {
struct timespec n;
+ unsigned long now;
getnstimeofday(&n);
- when -= timespec_to_ns(n);
+ now = timespec_to_ns(n);
+ if (when > now)
+ when -= now;
+ else
+ /* Fire the timer immediately */
+ when = 0;
}
/*
@@ -638,19 +632,19 @@ retry:
base[i].timer = timr;
base[i].cpu = smp_processor_id();
- timr->it_timer.magic = i;
- timr->it_timer.data = nodeid;
- timr->it_incr = period;
- timr->it_timer.expires = when;
+ timr->it.mmtimer.clock = i;
+ timr->it.mmtimer.node = nodeid;
+ timr->it.mmtimer.incr = period;
+ timr->it.mmtimer.expires = when;
if (period == 0) {
- if (mmtimer_setup(i, when)) {
+ if (!mmtimer_setup(i, when)) {
mmtimer_disable_int(-1, i);
posix_timer_event(timr, 0);
- timr->it_timer.expires = 0;
+ timr->it.mmtimer.expires = 0;
}
} else {
- timr->it_timer.expires -= period;
+ timr->it.mmtimer.expires -= period;
if (reschedule_periodic_timer(base+i))
err = -EINVAL;
}
diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c
index 10ba9bfb5d2c3..7c24fbe831f83 100644
--- a/drivers/char/moxa.c
+++ b/drivers/char/moxa.c
@@ -3090,6 +3090,7 @@ static int moxaloadc320(int cardno, void __iomem *baseAddr, int len, int *numPor
return (0);
}
+#if 0
long MoxaPortGetCurBaud(int port)
{
@@ -3097,6 +3098,7 @@ long MoxaPortGetCurBaud(int port)
return (0);
return (moxaCurBaud[port]);
}
+#endif /* 0 */
static void MoxaSetFifo(int port, int enable)
{
diff --git a/drivers/char/mwave/smapi.c b/drivers/char/mwave/smapi.c
index 08ef7cabdd259..6187fd14b3fe5 100644
--- a/drivers/char/mwave/smapi.c
+++ b/drivers/char/mwave/smapi.c
@@ -54,11 +54,11 @@
static unsigned short g_usSmapiPort = 0;
-int smapi_request(unsigned short inBX, unsigned short inCX,
- unsigned short inDI, unsigned short inSI,
- unsigned short *outAX, unsigned short *outBX,
- unsigned short *outCX, unsigned short *outDX,
- unsigned short *outDI, unsigned short *outSI)
+static int smapi_request(unsigned short inBX, unsigned short inCX,
+ unsigned short inDI, unsigned short inSI,
+ unsigned short *outAX, unsigned short *outBX,
+ unsigned short *outCX, unsigned short *outDX,
+ unsigned short *outDI, unsigned short *outSI)
{
unsigned short myoutAX = 2, *pmyoutAX = &myoutAX;
unsigned short myoutBX = 3, *pmyoutBX = &myoutBX;
@@ -511,8 +511,8 @@ int smapi_set_DSP_power_state(BOOLEAN bOn)
return bRC;
}
-
-int SmapiQuerySystemID(void)
+#if 0
+static int SmapiQuerySystemID(void)
{
int bRC = -EIO;
unsigned short usAX = 0xffff, usBX = 0xffff, usCX = 0xffff,
@@ -531,7 +531,7 @@ int SmapiQuerySystemID(void)
return bRC;
}
-
+#endif /* 0 */
int smapi_init(void)
{
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c
index 367f12d6ce7b9..7a245068e3e55 100644
--- a/drivers/char/mxser.c
+++ b/drivers/char/mxser.c
@@ -179,7 +179,7 @@ static int mxser_numports[] = {
#define UART_TYPE_NUM 2
-unsigned int Gmoxa_uart_id[UART_TYPE_NUM] = {
+static const unsigned int Gmoxa_uart_id[UART_TYPE_NUM] = {
MOXA_MUST_MU150_HWID,
MOXA_MUST_MU860_HWID
};
@@ -197,7 +197,7 @@ struct mxpciuart_info {
long max_baud;
};
-struct mxpciuart_info Gpci_uart_info[UART_INFO_NUM] = {
+static const struct mxpciuart_info Gpci_uart_info[UART_INFO_NUM] = {
{MOXA_OTHER_UART, 16, 16, 16, 14, 14, 1, 921600L},
{MOXA_MUST_MU150_HWID, 64, 64, 64, 48, 48, 16, 230400L},
{MOXA_MUST_MU860_HWID, 128, 128, 128, 96, 96, 32, 921600L}
@@ -548,7 +548,6 @@ static void process_txrx_fifo(struct mxser_struct *info)
static int mxser_initbrd(int board, struct mxser_hwconf *hwconf)
{
struct mxser_struct *info;
- unsigned long flags;
int retval;
int i, n;
@@ -3167,22 +3166,5 @@ static void mxser_normal_mode(int port)
outb(0x00, port + 4);
}
-// added by James 03-05-2004.
-// for secure device server:
-// stat = 1, the port8 DTR is set to ON.
-// stat = 0, the port8 DTR is set to OFF.
-void SDS_PORT8_DTR(int stat)
-{
- int _sds_oldmcr;
- _sds_oldmcr = inb(mxvar_table[7].base + UART_MCR); // get old MCR
- if (stat == 1) {
- outb(_sds_oldmcr | 0x01, mxvar_table[7].base + UART_MCR); // set DTR ON
- }
- if (stat == 0) {
- outb(_sds_oldmcr & 0xfe, mxvar_table[7].base + UART_MCR); // set DTR OFF
- }
- return;
-}
-
module_init(mxser_module_init);
module_exit(mxser_module_exit);
diff --git a/drivers/char/n_hdlc.c b/drivers/char/n_hdlc.c
index 24ccc233b2139..b3dbff1cf967b 100644
--- a/drivers/char/n_hdlc.c
+++ b/drivers/char/n_hdlc.c
@@ -575,7 +575,6 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file,
__u8 __user *buf, size_t nr)
{
struct n_hdlc *n_hdlc = tty2n_hdlc(tty);
- int error;
int ret;
struct n_hdlc_buf *rbuf;
@@ -587,11 +586,10 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file,
return -EIO;
/* verify user access to buffer */
- error = verify_area (VERIFY_WRITE, buf, nr);
- if (error != 0) {
- printk(KERN_WARNING"%s(%d) n_hdlc_tty_read() can't verify user "
- "buffer\n",__FILE__,__LINE__);
- return (error);
+ if (!access_ok(VERIFY_WRITE, buf, nr)) {
+ printk(KERN_WARNING "%s(%d) n_hdlc_tty_read() can't verify user "
+ "buffer\n", __FILE__, __LINE__);
+ return -EFAULT;
}
for (;;) {
diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c
index ae09412cc3179..edba5a35bf217 100644
--- a/drivers/char/n_tty.c
+++ b/drivers/char/n_tty.c
@@ -606,9 +606,11 @@ static inline void n_tty_receive_overrun(struct tty_struct *tty)
char buf[64];
tty->num_overrun++;
- if (time_before(tty->overrun_time, jiffies - HZ)) {
- printk(KERN_WARNING "%s: %d input overrun(s)\n", tty_name(tty, buf),
- tty->num_overrun);
+ if (time_before(tty->overrun_time, jiffies - HZ) ||
+ time_after(tty->overrun_time, jiffies)) {
+ printk(KERN_WARNING "%s: %d input overrun(s)\n",
+ tty_name(tty, buf),
+ tty->num_overrun);
tty->overrun_time = jiffies;
tty->num_overrun = 0;
}
diff --git a/drivers/char/nwflash.c b/drivers/char/nwflash.c
index 62c67cde853b8..ca41d62b1d9d7 100644
--- a/drivers/char/nwflash.c
+++ b/drivers/char/nwflash.c
@@ -182,7 +182,7 @@ static ssize_t flash_write(struct file *file, const char __user *buf,
if (count > gbFlashSize - p)
count = gbFlashSize - p;
- if (verify_area(VERIFY_READ, buf, count))
+ if (!access_ok(VERIFY_READ, buf, count))
return -EFAULT;
/*
diff --git a/drivers/char/pcxx.c b/drivers/char/pcxx.c
deleted file mode 100644
index b20a94194ca3c..0000000000000
--- a/drivers/char/pcxx.c
+++ /dev/null
@@ -1,2353 +0,0 @@
-/*
- * linux/drivers/char/pcxx.c
- *
- * Written by Troy De Jongh, November, 1994
- *
- * Copyright (C) 1994,1995 Troy De Jongh
- * This software may be used and distributed according to the terms
- * of the GNU General Public License.
- *
- * This driver is for the DigiBoard PC/Xe and PC/Xi line of products.
- *
- * This driver does NOT support DigiBoard's fastcook FEP option and
- * does not support the transparent print (i.e. digiprint) option.
- *
- * This Driver is currently maintained by Christoph Lameter (christoph@lameter.com)
- *
- * Please contact digi for support issues at digilnux@dgii.com.
- * Some more information can be found at
- * http://lameter.com/digi.
- *
- * 1.5.2 Fall 1995 Bug fixes by David Nugent
- * 1.5.3 March 9, 1996 Christoph Lameter: Fixed 115.2K Support. Memory
- * allocation harmonized with 1.3.X Series.
- * 1.5.4 March 30, 1996 Christoph Lameter: Fixup for 1.3.81. Use init_bh
- * instead of direct assignment to kernel arrays.
- * 1.5.5 April 5, 1996 Major device numbers corrected.
- * Mike McLagan<mike.mclagan@linux.org>: Add setup
- * variable handling, instead of using the old pcxxconfig.h
- * 1.5.6 April 16, 1996 Christoph Lameter: Pointer cleanup, macro cleanup.
- * Call out devices changed to /dev/cudxx.
- * 1.5.7 July 22, 1996 Martin Mares: CLOCAL fix, pcxe_table clearing.
- * David Nugent: Bug in pcxe_open.
- * Brian J. Murrell: Modem Control fixes, Majors correctly assigned
- * 1.6.1 April 6, 1997 Bernhard Kaindl: fixed virtual memory access for 2.1
- * i386-kernels and use on other archtitectures, Allowing use
- * as module, added module parameters, added switch to enable
- * verbose messages to assist user during card configuration.
- * Currently only tested on a PC/Xi card, but should work on Xe
- * and Xeve also.
- * 1.6.2 August, 7, 2000: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
- * get rid of panics, release previously allocated resources
- * 1.6.3 August, 23, 2000: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
- * cleaned up wrt verify_area.
- * Christoph Lameter: Update documentation, email addresses
- * and URLs. Remove some obsolete code.
- *
- */
-
-#include <linux/module.h>
-#include <linux/mm.h>
-#include <linux/ioport.h>
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/interrupt.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/major.h>
-#include <linux/string.h>
-#include <linux/fcntl.h>
-#include <linux/ptrace.h>
-#include <linux/delay.h>
-#include <linux/serial.h>
-#include <linux/tty_driver.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/bitops.h>
-
-#ifndef MODULE
-#include <linux/ctype.h> /* We only need it for parsing the "digi="-line */
-#endif
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/semaphore.h>
-
-#define VERSION "1.6.3"
-
-#include "digi.h"
-#include "fep.h"
-#include "pcxx.h"
-#include "digi_fep.h"
-#include "digi_bios.h"
-
-/*
- * Define one default setting if no digi= config line is used.
- * Default is altpin = disabled, 16 ports, I/O 200h, Memory 0D0000h
- */
-static struct board_info boards[MAX_DIGI_BOARDS] = { {
-/* Board is enabled */ ENABLED,
-/* Type is auto-detected */ 0,
-/* altping is disabled */ DISABLED,
-/* number of ports = 16 */ 16,
-/* io address is 0x200 */ 0x200,
-/* card memory at 0xd0000 */ 0xd0000,
-/* first minor device no. */ 0
-} };
-
-static int verbose = 0;
-static int debug = 0;
-
-#ifdef MODULE
-/* Variables for insmod */
-static int io[] = {0, 0, 0, 0};
-static int membase[] = {0, 0, 0, 0};
-static int memsize[] = {0, 0, 0, 0};
-static int altpin[] = {0, 0, 0, 0};
-static int numports[] = {0, 0, 0, 0};
-
-MODULE_AUTHOR("Bernhard Kaindl");
-MODULE_DESCRIPTION("Digiboard PC/X{i,e,eve} driver");
-MODULE_LICENSE("GPL");
-module_param(verbose, bool, 0644);
-module_param(debug, bool, 0644);
-module_param_array(io, int, NULL, 0);
-module_param_array(membase, int, NULL, 0);
-module_param_array(memsize, int, NULL, 0);
-module_param_array(altpin, int, NULL, 0);
-module_param_array(numports, int, NULL, 0);
-
-#endif /* MODULE */
-
-static int numcards = 1;
-static int nbdevs = 0;
-
-static struct channel *digi_channels;
-
-int pcxx_ncook=sizeof(pcxx_cook);
-int pcxx_nbios=sizeof(pcxx_bios);
-
-#define pcxxassert(x, msg) if(!(x)) pcxx_error(__LINE__, msg)
-
-#define FEPTIMEOUT 200000
-#define SERIAL_TYPE_NORMAL 1
-#define PCXE_EVENT_HANGUP 1
-
-static struct tty_driver *pcxe_driver;
-
-static struct timer_list pcxx_timer;
-
-static void pcxxpoll(unsigned long dummy);
-static void fepcmd(struct channel *, int, int, int, int, int);
-static void pcxe_put_char(struct tty_struct *, unsigned char);
-static void pcxe_flush_chars(struct tty_struct *);
-static void pcxx_error(int, char *);
-static void pcxe_close(struct tty_struct *, struct file *);
-static int pcxe_ioctl(struct tty_struct *, struct file *, unsigned int, unsigned long);
-static void pcxe_set_termios(struct tty_struct *, struct termios *);
-static int pcxe_write(struct tty_struct *, const unsigned char *, int);
-static int pcxe_write_room(struct tty_struct *);
-static int pcxe_chars_in_buffer(struct tty_struct *);
-static void pcxe_flush_buffer(struct tty_struct *);
-static void doevent(int);
-static void receive_data(struct channel *);
-static void pcxxparam(struct tty_struct *, struct channel *ch);
-static void do_softint(void *);
-static inline void pcxe_sched_event(struct channel *, int);
-static void pcxe_start(struct tty_struct *);
-static void pcxe_stop(struct tty_struct *);
-static void pcxe_throttle(struct tty_struct *);
-static void pcxe_unthrottle(struct tty_struct *);
-static void digi_send_break(struct channel *ch, int msec);
-static void shutdown(struct channel *);
-static void setup_empty_event(struct tty_struct *tty, struct channel *ch);
-static inline void memwinon(struct board_info *b, unsigned int win);
-static inline void memwinoff(struct board_info *b, unsigned int win);
-static inline void globalwinon(struct channel *ch);
-static inline void rxwinon(struct channel *ch);
-static inline void txwinon(struct channel *ch);
-static inline void memoff(struct channel *ch);
-static inline void assertgwinon(struct channel *ch);
-static inline void assertmemoff(struct channel *ch);
-static int pcxe_tiocmget(struct tty_struct *tty, struct file *file);
-static int pcxe_tiocmset(struct tty_struct *tty, struct file *file,
- unsigned int set, unsigned int clear);
-
-#define TZ_BUFSZ 4096
-
-/* function definitions */
-
-/*****************************************************************************/
-
-static void cleanup_board_resources(void)
-{
- int crd, i;
- struct board_info *bd;
- struct channel *ch;
-
- for(crd = 0; crd < numcards; crd++) {
- bd = &boards[crd];
- ch = digi_channels + bd->first_minor;
-
- if (bd->region)
- release_region(bd->port, 4);
-
- for(i = 0; i < bd->numports; i++, ch++)
- if (ch->tmp_buf)
- kfree(ch->tmp_buf);
- }
-}
-
-static void __exit pcxe_cleanup(void)
-{
-
- unsigned long flags;
- int e1;
-
- printk(KERN_NOTICE "Unloading PC/Xx version %s\n", VERSION);
-
- save_flags(flags);
- cli();
- del_timer_sync(&pcxx_timer);
-
- if ((e1 = tty_unregister_driver(pcxe_driver)))
- printk("SERIAL: failed to unregister serial driver (%d)\n", e1);
-
- put_tty_driver(pcxe_driver);
- cleanup_board_resources();
- kfree(digi_channels);
- restore_flags(flags);
-}
-
-static inline struct channel *chan(register struct tty_struct *tty)
-{
- if (tty) {
- register struct channel *ch=(struct channel *)tty->driver_data;
- if (ch >= digi_channels && ch < digi_channels+nbdevs) {
- if (ch->magic==PCXX_MAGIC)
- return ch;
- }
- }
- return NULL;
-}
-
-/* These inline routines are to turn board memory on and off */
-static inline void memwinon(struct board_info *b, unsigned int win)
-{
- if(b->type == PCXEVE)
- outb_p(FEPWIN|win, b->port+1);
- else
- outb_p(inb(b->port)|FEPMEM, b->port);
-}
-
-static inline void memwinoff(struct board_info *b, unsigned int win)
-{
- outb_p(inb(b->port)&~FEPMEM, b->port);
- if(b->type == PCXEVE)
- outb_p(0, b->port + 1);
-}
-
-static inline void globalwinon(struct channel *ch)
-{
- if(ch->board->type == PCXEVE)
- outb_p(FEPWIN, ch->board->port+1);
- else
- outb_p(FEPMEM, ch->board->port);
-}
-
-static inline void rxwinon(struct channel *ch)
-{
- if(ch->rxwin == 0)
- outb_p(FEPMEM, ch->board->port);
- else
- outb_p(ch->rxwin, ch->board->port+1);
-}
-
-static inline void txwinon(struct channel *ch)
-{
- if(ch->txwin == 0)
- outb_p(FEPMEM, ch->board->port);
- else
- outb_p(ch->txwin, ch->board->port+1);
-}
-
-static inline void memoff(struct channel *ch)
-{
- outb_p(0, ch->board->port);
- if(ch->board->type == PCXEVE)
- outb_p(0, ch->board->port+1);
-}
-
-static inline void assertgwinon(struct channel *ch)
-{
- if(ch->board->type != PCXEVE)
- pcxxassert(inb(ch->board->port) & FEPMEM, "Global memory off");
-}
-
-static inline void assertmemoff(struct channel *ch)
-{
- if(ch->board->type != PCXEVE)
- pcxxassert(!(inb(ch->board->port) & FEPMEM), "Memory on");
-}
-
-static inline void pcxe_sched_event(struct channel *info, int event)
-{
- info->event |= 1 << event;
- schedule_work(&info->tqueue);
-}
-
-static void pcxx_error(int line, char *msg)
-{
- printk("pcxx_error (DigiBoard): line=%d %s\n", line, msg);
-}
-
-static int pcxx_waitcarrier(struct tty_struct *tty,struct file *filp,struct channel *info)
-{
- DECLARE_WAITQUEUE(wait, current);
- int retval = 0;
- int do_clocal = 0;
-
- if (tty->termios->c_cflag & CLOCAL)
- do_clocal = 1;
-
- /*
- * Block waiting for the carrier detect and the line to become free
- */
-
- retval = 0;
- add_wait_queue(&info->open_wait, &wait);
- info->count--;
- info->blocked_open++;
-
- for (;;) {
- cli();
- globalwinon(info);
- info->omodem |= DTR|RTS;
- fepcmd(info, SETMODEM, DTR|RTS, 0, 10, 1);
- memoff(info);
- sti();
- set_current_state(TASK_INTERRUPTIBLE);
- if(tty_hung_up_p(filp) || (info->asyncflags & ASYNC_INITIALIZED) == 0) {
- if(info->asyncflags & ASYNC_HUP_NOTIFY)
- retval = -EAGAIN;
- else
- retval = -ERESTARTSYS;
- break;
- }
- if ((info->asyncflags & ASYNC_CLOSING) == 0 &&
- (do_clocal || (info->imodem & info->dcd)))
- break;
- if(signal_pending(current)) {
- retval = -ERESTARTSYS;
- break;
- }
- schedule();
- }
- current->state = TASK_RUNNING;
- remove_wait_queue(&info->open_wait, &wait);
-
- if(!tty_hung_up_p(filp))
- info->count++;
- info->blocked_open--;
-
- return retval;
-}
-
-
-int pcxe_open(struct tty_struct *tty, struct file * filp)
-{
- volatile struct board_chan *bc;
- struct channel *ch;
- unsigned long flags;
- int line;
- int boardnum;
- int retval;
-
- line = tty->index;
-
- if(line < 0 || line >= nbdevs) {
- printk("line out of range in pcxe_open\n");
- tty->driver_data = NULL;
- return(-ENODEV);
- }
-
- for(boardnum=0;boardnum<numcards;boardnum++)
- if ((line >= boards[boardnum].first_minor) &&
- (line < boards[boardnum].first_minor + boards[boardnum].numports))
- break;
-
- if(boardnum >= numcards || boards[boardnum].status == DISABLED ||
- (line - boards[boardnum].first_minor) >= boards[boardnum].numports) {
- tty->driver_data = NULL; /* Mark this device as 'down' */
- return(-ENODEV);
- }
-
- ch = digi_channels+line;
-
- if(ch->brdchan == 0) {
- tty->driver_data = NULL;
- return(-ENODEV);
- }
-
- /*
- * If the device is in the middle of being closed, then block
- * until it's done, and then try again.
- */
- if(ch->asyncflags & ASYNC_CLOSING) {
- interruptible_sleep_on(&ch->close_wait);
- if(ch->asyncflags & ASYNC_HUP_NOTIFY)
- return -EAGAIN;
- else
- return -ERESTARTSYS;
- }
-
- save_flags(flags);
- cli();
- ch->count++;
- tty->driver_data = ch;
- ch->tty = tty;
-
- if ((ch->asyncflags & ASYNC_INITIALIZED) == 0) {
- unsigned int head;
-
- globalwinon(ch);
- ch->statusflags = 0;
- bc=ch->brdchan;
- ch->imodem = bc->mstat;
- head = bc->rin;
- bc->rout = head;
- ch->tty = tty;
- pcxxparam(tty,ch);
- ch->imodem = bc->mstat;
- bc->idata = 1;
- ch->omodem = DTR|RTS;
- fepcmd(ch, SETMODEM, DTR|RTS, 0, 10, 1);
- memoff(ch);
- ch->asyncflags |= ASYNC_INITIALIZED;
- }
- restore_flags(flags);
-
- if(ch->asyncflags & ASYNC_CLOSING) {
- interruptible_sleep_on(&ch->close_wait);
- if(ch->asyncflags & ASYNC_HUP_NOTIFY)
- return -EAGAIN;
- else
- return -ERESTARTSYS;
- }
-
- if (!(filp->f_flags & O_NONBLOCK)) {
- /* this has to be set in order for the "block until
- * CD" code to work correctly. i'm not sure under
- * what circumstances asyncflags should be set to
- * ASYNC_NORMAL_ACTIVE though
- * brian@ilinx.com
- */
- ch->asyncflags |= ASYNC_NORMAL_ACTIVE;
- if ((retval = pcxx_waitcarrier(tty, filp, ch)) != 0)
- return retval;
- }
- ch->asyncflags |= ASYNC_NORMAL_ACTIVE;
-
- return 0;
-}
-
-static void shutdown(struct channel *info)
-{
- unsigned long flags;
- volatile struct board_chan *bc;
- struct tty_struct *tty;
-
- if (!(info->asyncflags & ASYNC_INITIALIZED))
- return;
-
- save_flags(flags);
- cli();
- globalwinon(info);
-
- bc = info->brdchan;
- if(bc)
- bc->idata = 0;
-
- tty = info->tty;
-
- /*
- * If we're a modem control device and HUPCL is on, drop RTS & DTR.
- */
- if(tty->termios->c_cflag & HUPCL) {
- info->omodem &= ~(RTS|DTR);
- fepcmd(info, SETMODEM, 0, DTR|RTS, 10, 1);
- }
-
- memoff(info);
- info->asyncflags &= ~ASYNC_INITIALIZED;
- restore_flags(flags);
-}
-
-
-static void pcxe_close(struct tty_struct * tty, struct file * filp)
-{
- struct channel *info;
-
- if ((info=chan(tty))!=NULL) {
- unsigned long flags;
- save_flags(flags);
- cli();
-
- if(tty_hung_up_p(filp)) {
- /* flag that somebody is done with this module */
- restore_flags(flags);
- return;
- }
- /* this check is in serial.c, it won't hurt to do it here too */
- if ((tty->count == 1) && (info->count != 1)) {
- /*
- * Uh, oh. tty->count is 1, which means that the tty
- * structure will be freed. Info->count should always
- * be one in these conditions. If it's greater than
- * one, we've got real problems, since it means the
- * serial port won't be shutdown.
- */
- printk("pcxe_close: bad serial port count; tty->count is 1, info->count is %d\n", info->count);
- info->count = 1;
- }
- if (info->count-- > 1) {
- restore_flags(flags);
- return;
- }
- if (info->count < 0) {
- info->count = 0;
- }
-
- info->asyncflags |= ASYNC_CLOSING;
-
- tty->closing = 1;
- if(info->asyncflags & ASYNC_INITIALIZED) {
- setup_empty_event(tty,info);
- tty_wait_until_sent(tty, 3000); /* 30 seconds timeout */
- }
-
- if(tty->driver->flush_buffer)
- tty->driver->flush_buffer(tty);
- tty_ldisc_flush(tty);
- shutdown(info);
- tty->closing = 0;
- info->event = 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->asyncflags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
- wake_up_interruptible(&info->close_wait);
- restore_flags(flags);
- }
-}
-
-
-void pcxe_hangup(struct tty_struct *tty)
-{
- struct channel *ch;
-
- if ((ch=chan(tty))!=NULL) {
- unsigned long flags;
-
- save_flags(flags);
- cli();
- shutdown(ch);
- ch->event = 0;
- ch->count = 0;
- ch->tty = NULL;
- ch->asyncflags &= ~ASYNC_NORMAL_ACTIVE;
- wake_up_interruptible(&ch->open_wait);
- restore_flags(flags);
- }
-}
-
-
-
-static int pcxe_write(struct tty_struct * tty, const unsigned char *buf, int count)
-{
- struct channel *ch;
- volatile struct board_chan *bc;
- int total, remain, size, stlen;
- unsigned int head, tail;
- unsigned long flags;
- /* printk("Entering pcxe_write()\n"); */
-
- if ((ch=chan(tty))==NULL)
- return 0;
-
- bc = ch->brdchan;
- size = ch->txbufsize;
-
- /*
- * All data is now local
- */
-
- total = 0;
- save_flags(flags);
- cli();
- globalwinon(ch);
- head = bc->tin & (size - 1);
- tail = bc->tout;
- if (tail != bc->tout)
- tail = bc->tout;
- tail &= (size - 1);
- if (head >= tail) {
- remain = size - (head - tail) - 1;
- stlen = size - head;
- }
- else {
- remain = tail - head - 1;
- stlen = remain;
- }
- count = min(remain, count);
-
- txwinon(ch);
- while (count > 0) {
- stlen = min(count, stlen);
- memcpy(ch->txptr + head, buf, stlen);
- buf += stlen;
- count -= stlen;
- total += stlen;
- head += stlen;
- if (head >= size) {
- head = 0;
- stlen = tail;
- }
- }
- ch->statusflags |= TXBUSY;
- globalwinon(ch);
- bc->tin = head;
- if ((ch->statusflags & LOWWAIT) == 0) {
- ch->statusflags |= LOWWAIT;
- bc->ilow = 1;
- }
- memoff(ch);
- restore_flags(flags);
-
- return(total);
-}
-
-
-static void pcxe_put_char(struct tty_struct *tty, unsigned char c)
-{
- pcxe_write(tty, &c, 1);
- return;
-}
-
-
-static int pcxe_write_room(struct tty_struct *tty)
-{
- struct channel *ch;
- int remain;
-
- remain = 0;
- if ((ch=chan(tty))!=NULL) {
- volatile struct board_chan *bc;
- unsigned int head, tail;
- unsigned long flags;
-
- save_flags(flags);
- cli();
- globalwinon(ch);
-
- bc = ch->brdchan;
- head = bc->tin & (ch->txbufsize - 1);
- tail = bc->tout;
- if (tail != bc->tout)
- tail = bc->tout;
- tail &= (ch->txbufsize - 1);
-
- if((remain = tail - head - 1) < 0 )
- remain += ch->txbufsize;
-
- if (remain && (ch->statusflags & LOWWAIT) == 0) {
- ch->statusflags |= LOWWAIT;
- bc->ilow = 1;
- }
- memoff(ch);
- restore_flags(flags);
- }
-
- return remain;
-}
-
-
-static int pcxe_chars_in_buffer(struct tty_struct *tty)
-{
- int chars;
- unsigned int ctail, head, tail;
- int remain;
- unsigned long flags;
- struct channel *ch;
- volatile struct board_chan *bc;
-
- if ((ch=chan(tty))==NULL)
- return(0);
-
- save_flags(flags);
- cli();
- globalwinon(ch);
-
- bc = ch->brdchan;
- tail = bc->tout;
- head = bc->tin;
- ctail = ch->mailbox->cout;
- if(tail == head && ch->mailbox->cin == ctail && bc->tbusy == 0)
- chars = 0;
- else {
- head = bc->tin & (ch->txbufsize - 1);
- tail &= (ch->txbufsize - 1);
- if((remain = tail - head - 1) < 0 )
- remain += ch->txbufsize;
-
- chars = (int)(ch->txbufsize - remain);
-
- /*
- * Make it possible to wakeup anything waiting for output
- * in tty_ioctl.c, etc.
- */
- if(!(ch->statusflags & EMPTYWAIT))
- setup_empty_event(tty,ch);
- }
-
- memoff(ch);
- restore_flags(flags);
-
- return(chars);
-}
-
-
-static void pcxe_flush_buffer(struct tty_struct *tty)
-{
- unsigned int tail;
- volatile struct board_chan *bc;
- struct channel *ch;
- unsigned long flags;
-
- if ((ch=chan(tty))==NULL)
- return;
-
- save_flags(flags);
- cli();
-
- globalwinon(ch);
- bc = ch->brdchan;
- tail = bc->tout;
- fepcmd(ch, STOUT, (unsigned) tail, 0, 0, 0);
-
- memoff(ch);
- restore_flags(flags);
-
- tty_wakeup(tty);
-}
-
-static void pcxe_flush_chars(struct tty_struct *tty)
-{
- struct channel * ch;
-
- if ((ch=chan(tty))!=NULL) {
- unsigned long flags;
-
- save_flags(flags);
- cli();
- if ((ch->statusflags & TXBUSY) && !(ch->statusflags & EMPTYWAIT))
- setup_empty_event(tty,ch);
- restore_flags(flags);
- }
-}
-
-#ifndef MODULE
-
-/*
- * Driver setup function when linked into the kernel to optionally parse multible
- * "digi="-lines and initialize the driver at boot time. No probing.
- */
-void __init pcxx_setup(char *str, int *ints)
-{
-
- struct board_info board;
- int i, j, last;
- char *temp, *t2;
- unsigned len;
-
- numcards=0;
-
- memset(&board, 0, sizeof(board));
-
- for(last=0,i=1;i<=ints[0];i++)
- switch(i)
- {
- case 1:
- board.status = ints[i];
- last = i;
- break;
-
- case 2:
- board.type = ints[i];
- last = i;
- break;
-
- case 3:
- board.altpin = ints[i];
- last = i;
- break;
-
- case 4:
- board.numports = ints[i];
- last = i;
- break;
-
- case 5:
- board.port = ints[i];
- last = i;
- break;
-
- case 6:
- board.membase = ints[i];
- last = i;
- break;
-
- default:
- printk("PC/Xx: Too many integer parms\n");
- return;
- }
-
- while (str && *str)
- {
- /* find the next comma or terminator */
- temp = str;
- while (*temp && (*temp != ','))
- temp++;
-
- if (!*temp)
- temp = NULL;
- else
- *temp++ = 0;
-
- i = last + 1;
-
- switch(i)
- {
- case 1:
- len = strlen(str);
- if (strncmp("Disable", str, len) == 0)
- board.status = 0;
- else
- if (strncmp("Enable", str, len) == 0)
- board.status = 1;
- else
- {
- printk("PC/Xx: Invalid status %s\n", str);
- return;
- }
- last = i;
- break;
-
- case 2:
- for(j=0;j<PCXX_NUM_TYPES;j++)
- if (strcmp(board_desc[j], str) == 0)
- break;
-
- if (i<PCXX_NUM_TYPES)
- board.type = j;
- else
- {
- printk("PC/Xx: Invalid board name: %s\n", str);
- return;
- }
- last = i;
- break;
-
- case 3:
- len = strlen(str);
- if (strncmp("Disable", str, len) == 0)
- board.altpin = 0;
- else
- if (strncmp("Enable", str, len) == 0)
- board.altpin = 1;
- else
- {
- printk("PC/Xx: Invalid altpin %s\n", str);
- return;
- }
- last = i;
- break;
-
- case 4:
- t2 = str;
- while (isdigit(*t2))
- t2++;
-
- if (*t2)
- {
- printk("PC/Xx: Invalid port count %s\n", str);
- return;
- }
-
- board.numports = simple_strtoul(str, NULL, 0);
- last = i;
- break;
-
- case 5:
- t2 = str;
- while (isxdigit(*t2))
- t2++;
-
- if (*t2)
- {
- printk("PC/Xx: Invalid io port address %s\n", str);
- return;
- }
-
- board.port = simple_strtoul(str, NULL, 16);
- last = i;
- break;
-
- case 6:
- t2 = str;
- while (isxdigit(*t2))
- t2++;
-
- if (*t2)
- {
- printk("PC/Xx: Invalid memory base %s\n", str);
- return;
- }
-
- board.membase = simple_strtoul(str, NULL, 16);
- last = i;
- break;
-
- default:
- printk("PC/Xx: Too many string parms\n");
- return;
- }
- str = temp;
- }
-
- if (last < 6)
- {
- printk("PC/Xx: Insufficient parms specified\n");
- return;
- }
-
- /* I should REALLY validate the stuff here */
-
- memcpy(&boards[numcards],&board, sizeof(board));
- printk("PC/Xx: Added board %i, %s %s %i ports at 0x%4.4X base 0x%6.6X\n",
- numcards, board_desc[board.type], board_mem[board.type],
- board.numports, board.port, (unsigned int) board.membase);
-
- /* keep track of my initial minor number */
- if (numcards)
- boards[numcards].first_minor = boards[numcards-1].first_minor + boards[numcards-1].numports;
- else
- boards[numcards].first_minor = 0;
-
- /* yeha! string parameter was successful! */
- numcards++;
-}
-#endif
-
-static struct tty_operations pcxe_ops = {
- .open = pcxe_open,
- .close = pcxe_close,
- .write = pcxe_write,
- .put_char = pcxe_put_char,
- .flush_chars = pcxe_flush_chars,
- .write_room = pcxe_write_room,
- .chars_in_buffer = pcxe_chars_in_buffer,
- .flush_buffer = pcxe_flush_buffer,
- .ioctl = pcxe_ioctl,
- .throttle = pcxe_throttle,
- .unthrottle = pcxe_unthrottle,
- .set_termios = pcxe_set_termios,
- .stop = pcxe_stop,
- .start = pcxe_start,
- .hangup = pcxe_hangup,
- .tiocmget = pcxe_tiocmget,
- .tiocmset = pcxe_tiocmset,
-};
-
-/*
- * function to initialize the driver with the given parameters, which are either
- * the default values from this file or the parameters given at boot.
- */
-static int __init pcxe_init(void)
-{
- ulong memory_seg=0, memory_size=0;
- int lowwater, enabled_cards=0, i, crd, shrinkmem=0, topwin = 0xff00L, botwin=0x100L;
- int ret = -ENOMEM;
- unchar *fepos, *memaddr, *bios, v;
- volatile struct global_data *gd;
- volatile struct board_chan *bc;
- struct board_info *bd;
- struct channel *ch;
-
- printk(KERN_NOTICE "Digiboard PC/X{i,e,eve} driver v%s\n", VERSION);
-
-#ifdef MODULE
- for (i = 0; i < MAX_DIGI_BOARDS; i++) {
- if (io[i]) {
- numcards = 0;
- break;
- }
- }
- if (numcards == 0) {
- int first_minor = 0;
-
- for (i = 0; i < MAX_DIGI_BOARDS; i++) {
- if (io[i] == 0) {
- boards[i].port = 0;
- boards[i].status = DISABLED;
- }
- else {
- boards[i].port = (ushort)io[i];
- boards[i].status = ENABLED;
- boards[i].first_minor = first_minor;
- numcards=i+1;
- }
- if (membase[i])
- boards[i].membase = (ulong)membase[i];
- else
- boards[i].membase = 0xD0000;
-
- if (memsize[i])
- boards[i].memsize = (ulong)(memsize[i] * 1024);
- else
- boards[i].memsize = 0;
-
- if (altpin[i])
- boards[i].altpin = ON;
- else
- boards[i].altpin = OFF;
-
- if (numports[i])
- boards[i].numports = (ushort)numports[i];
- else
- boards[i].numports = 16;
-
- boards[i].region = NULL;
- first_minor += boards[i].numports;
- }
- }
-#endif
-
- if (numcards <= 0)
- {
- printk("PC/Xx: No cards configured, driver not active.\n");
- return -EIO;
- }
-#if 1
- if (debug)
- for (i = 0; i < numcards; i++) {
- printk("Card %d:status=%d, port=0x%x, membase=0x%lx, memsize=0x%lx, altpin=%d, numports=%d, first_minor=%d\n",
- i+1,
- boards[i].status,
- boards[i].port,
- boards[i].membase,
- boards[i].memsize,
- boards[i].altpin,
- boards[i].numports,
- boards[i].first_minor);
- }
-#endif
-
- for (i=0;i<numcards;i++)
- nbdevs += boards[i].numports;
-
- if (nbdevs <= 0)
- {
- printk("PC/Xx: No devices activated, driver not active.\n");
- return -EIO;
- }
-
- pcxe_driver = alloc_tty_driver(nbdevs);
- if (!pcxe_driver)
- return -ENOMEM;
-
- /*
- * this turns out to be more memory efficient, as there are no
- * unused spaces.
- */
- digi_channels = kmalloc(sizeof(struct channel) * nbdevs, GFP_KERNEL);
- if (!digi_channels) {
- printk(KERN_ERR "Unable to allocate digi_channel struct\n");
- put_tty_driver(pcxe_driver);
- return -ENOMEM;
- }
- memset(digi_channels, 0, sizeof(struct channel) * nbdevs);
-
- init_timer(&pcxx_timer);
- pcxx_timer.function = pcxxpoll;
-
- pcxe_driver->owner = THIS_MODULE;
- pcxe_driver->name = "ttyD";
- pcxe_driver->devfs_name = "pcxe/";
- pcxe_driver->major = DIGI_MAJOR;
- pcxe_driver->minor_start = 0;
- pcxe_driver->type = TTY_DRIVER_TYPE_SERIAL;
- pcxe_driver->subtype = SERIAL_TYPE_NORMAL;
- pcxe_driver->init_termios = tty_std_termios;
- pcxe_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL;
- pcxe_driver->flags = TTY_DRIVER_REAL_RAW;
- tty_set_operations(pcxe_driver, &pcxe_ops);
-
- for(crd=0; crd < numcards; crd++) {
- bd = &boards[crd];
- outb(FEPRST, bd->port);
- mdelay(1);
-
- for(i=0; (inb(bd->port) & FEPMASK) != FEPRST; i++) {
- if(i > 100) {
- printk("PC/Xx: Board not found at port 0x%x! Check switch settings.\n",
- bd->port);
- bd->status = DISABLED;
- break;
- }
-#ifdef MODULE
- schedule();
-#endif
- mdelay(10);
- }
- if(bd->status == DISABLED)
- continue;
-
- v = inb(bd->port);
-
- if((v & 0x1) == 0x1) {
- if((v & 0x30) == 0) { /* PC/Xi 64K card */
- memory_seg = 0xf000;
- memory_size = 0x10000;
- }
-
- if((v & 0x30) == 0x10) { /* PC/Xi 128K card */
- memory_seg = 0xe000;
- memory_size = 0x20000;
- }
-
- if((v & 0x30) == 0x20) { /* PC/Xi 256K card */
- memory_seg = 0xc000;
- memory_size = 0x40000;
- }
-
- if((v & 0x30) == 0x30) { /* PC/Xi 512K card */
- memory_seg = 0x8000;
- memory_size = 0x80000;
- }
- bd->type = PCXI;
- } else {
- if((v & 0x1) == 0x1) {
- bd->status = DISABLED; /* PC/Xm unsupported card */
- printk("PC/Xx: PC/Xm at 0x%x not supported!!\n", bd->port);
- continue;
- } else {
- if(v & 0xC0) {
- topwin = 0x1f00L;
- outb((((ulong)bd->membase>>8) & 0xe0) | 0x10, bd->port+2);
- outb(((ulong)bd->membase>>16) & 0xff, bd->port+3);
- bd->type = PCXEVE; /* PC/Xe 8K card */
- } else {
- bd->type = PCXE; /* PC/Xe 64K card */
- }
-
- memory_seg = 0xf000;
- memory_size = 0x10000;
- }
- }
- if (verbose)
- printk("Configuring card %d as a %s %ldK card. io=0x%x, mem=%lx-%lx\n",
- crd+1, board_desc[bd->type], memory_size/1024,
- bd->port,bd->membase,bd->membase+memory_size-1);
-
- if (boards[crd].memsize == 0)
- boards[crd].memsize = memory_size;
- else
- if (boards[crd].memsize != memory_size) {
- printk("PC/Xx: memory size mismatch:supplied=%lx(%ldK) probed=%ld(%ldK)\n",
- boards[crd].memsize, boards[crd].memsize / 1024,
- memory_size, memory_size / 1024);
- continue;
- }
-
- memaddr = (unchar *)phys_to_virt(bd->membase);
-
- if (verbose)
- printk("Resetting board and testing memory access:");
-
- outb(FEPRST|FEPMEM, bd->port);
-
- for(i=0; (inb(bd->port) & FEPMASK) != (FEPRST|FEPMEM); i++) {
- if(i > 1000) {
- printk("\nPC/Xx: %s not resetting at port 0x%x! Check switch settings.\n",
- board_desc[bd->type], bd->port);
- bd->status = DISABLED;
- break;
- }
-#ifdef MODULE
- schedule();
-#endif
- mdelay(1);
- }
- if(bd->status == DISABLED)
- continue;
-
- memwinon(bd,0);
- *(ulong *)(memaddr + botwin) = 0xa55a3cc3;
- *(ulong *)(memaddr + topwin) = 0x5aa5c33c;
-
- if(*(ulong *)(memaddr + botwin) != 0xa55a3cc3 ||
- *(ulong *)(memaddr + topwin) != 0x5aa5c33c) {
- printk("PC/Xx: Failed memory test at %lx for %s at port %x, check switch settings.\n",
- bd->membase, board_desc[bd->type], bd->port);
- bd->status = DISABLED;
- continue;
- }
- if (verbose)
- printk(" done.\n");
-
- for(i=0; i < 16; i++) {
- memaddr[MISCGLOBAL+i] = 0;
- }
-
- if(bd->type == PCXI || bd->type == PCXE) {
- bios = memaddr + BIOSCODE + ((0xf000 - memory_seg) << 4);
-
- if (verbose)
- printk("Downloading BIOS to 0x%lx:", virt_to_phys(bios));
-
- memcpy(bios, pcxx_bios, pcxx_nbios);
-
- if (verbose)
- printk(" done.\n");
-
- outb(FEPMEM, bd->port);
-
- if (verbose)
- printk("Waiting for BIOS to become ready");
-
- for(i=1; i <= 30; i++) {
- if(*(ushort *)((ulong)memaddr + MISCGLOBAL) == *(ushort *)"GD" ) {
- goto load_fep;
- }
- if (verbose) {
- printk(".");
- if (i % 50 == 0)
- printk("\n");
- }
-#ifdef MODULE
- schedule();
-#endif
- mdelay(50);
- }
-
- printk("\nPC/Xx: BIOS download failed for board at 0x%x(addr=%lx-%lx)!\n",
- bd->port, bd->membase, bd->membase+bd->memsize);
- bd->status = DISABLED;
- continue;
- }
-
- if(bd->type == PCXEVE) {
- bios = memaddr + (BIOSCODE & 0x1fff);
- memwinon(bd,0xff);
-
- memcpy(bios, pcxx_bios, pcxx_nbios);
-
- outb(FEPCLR, bd->port);
- memwinon(bd,0);
-
- for(i=0; i <= 1000; i++) {
- if(*(ushort *)((ulong)memaddr + MISCGLOBAL) == *(ushort *)"GD" ) {
- goto load_fep;
- }
- if (verbose) {
- printk(".");
- if (i % 50 == 0)
- printk("\n");
- }
-#ifdef MODULE
- schedule();
-#endif
- mdelay(10);
- }
-
- printk("\nPC/Xx: BIOS download failed on the %s at 0x%x!\n",
- board_desc[bd->type], bd->port);
- bd->status = DISABLED;
- continue;
- }
-
-load_fep:
- fepos = memaddr + FEPCODE;
- if(bd->type == PCXEVE)
- fepos = memaddr + (FEPCODE & 0x1fff);
-
- if (verbose)
- printk(" ok.\nDownloading FEP/OS to 0x%lx:", virt_to_phys(fepos));
-
- memwinon(bd, (FEPCODE >> 13));
- memcpy(fepos, pcxx_cook, pcxx_ncook);
- memwinon(bd, 0);
-
- if (verbose)
- printk(" done.\n");
-
- *(ushort *)((ulong)memaddr + MBOX + 0) = 2;
- *(ushort *)((ulong)memaddr + MBOX + 2) = memory_seg + FEPCODESEG;
- *(ushort *)((ulong)memaddr + MBOX + 4) = 0;
- *(ushort *)((ulong)memaddr + MBOX + 6) = FEPCODESEG;
- *(ushort *)((ulong)memaddr + MBOX + 8) = 0;
- *(ushort *)((ulong)memaddr + MBOX + 10) = pcxx_ncook;
-
- outb(FEPMEM|FEPINT, bd->port);
- outb(FEPMEM, bd->port);
-
- for(i=0; *(ushort *)((ulong)memaddr + MBOX); i++) {
- if(i > 2000) {
- printk("PC/Xx: Command failed for the %s at 0x%x!\n",
- board_desc[bd->type], bd->port);
- bd->status = DISABLED;
- break;
- }
-#ifdef MODULE
- schedule();
-#endif
- mdelay(1);
- }
-
- if(bd->status == DISABLED)
- continue;
-
- if (verbose)
- printk("Waiting for FEP/OS to become ready");
-
- *(ushort *)(memaddr + FEPSTAT) = 0;
- *(ushort *)(memaddr + MBOX + 0) = 1;
- *(ushort *)(memaddr + MBOX + 2) = FEPCODESEG;
- *(ushort *)(memaddr + MBOX + 4) = 0x4L;
-
- outb(FEPINT, bd->port);
- outb(FEPCLR, bd->port);
- memwinon(bd, 0);
-
- for(i=1; *(ushort *)((ulong)memaddr + FEPSTAT) != *(ushort *)"OS"; i++) {
- if(i > 1000) {
- printk("\nPC/Xx: FEP/OS download failed on the %s at 0x%x!\n",
- board_desc[bd->type], bd->port);
- bd->status = DISABLED;
- break;
- }
- if (verbose) {
- printk(".");
- if (i % 50 == 0)
- printk("\n%5d",i/50);
- }
-#ifdef MODULE
- schedule();
-#endif
- mdelay(1);
- }
- if(bd->status == DISABLED)
- continue;
-
- if (verbose)
- printk(" ok.\n");
-
- ch = digi_channels+bd->first_minor;
- pcxxassert(ch < digi_channels+nbdevs, "ch out of range");
-
- bc = (volatile struct board_chan *)((ulong)memaddr + CHANSTRUCT);
- gd = (volatile struct global_data *)((ulong)memaddr + GLOBAL);
-
- if((bd->type == PCXEVE) && (*(ushort *)((ulong)memaddr+NPORT) < 3))
- shrinkmem = 1;
-
- bd->region = request_region(bd->port, 4, "PC/Xx");
-
- if (!bd->region) {
- printk(KERN_ERR "I/O port 0x%x is already used\n", bd->port);
- ret = -EBUSY;
- goto cleanup_boards;
- }
-
- for(i=0; i < bd->numports; i++, ch++, bc++) {
- if(((ushort *)((ulong)memaddr + PORTBASE))[i] == 0) {
- ch->brdchan = 0;
- continue;
- }
- ch->brdchan = bc;
- ch->mailbox = gd;
- INIT_WORK(&ch->tqueue, do_softint, ch);
- ch->board = &boards[crd];
-#ifdef DEFAULT_HW_FLOW
- ch->digiext.digi_flags = RTSPACE|CTSPACE;
-#endif
- if(boards[crd].altpin) {
- ch->dsr = CD;
- ch->dcd = DSR;
- ch->digiext.digi_flags |= DIGI_ALTPIN;
- } else {
- ch->dcd = CD;
- ch->dsr = DSR;
- }
-
- ch->magic = PCXX_MAGIC;
- ch->boardnum = crd;
- ch->channelnum = i;
-
- ch->dev = bd->first_minor + i;
- ch->tty = 0;
-
- if(shrinkmem) {
- fepcmd(ch, SETBUFFER, 32, 0, 0, 0);
- shrinkmem = 0;
- }
-
- if(bd->type != PCXEVE) {
- ch->txptr = memaddr+((bc->tseg-memory_seg) << 4);
- ch->rxptr = memaddr+((bc->rseg-memory_seg) << 4);
- ch->txwin = ch->rxwin = 0;
- } else {
- ch->txptr = memaddr+(((bc->tseg-memory_seg) << 4) & 0x1fff);
- ch->txwin = FEPWIN | ((bc->tseg-memory_seg) >> 9);
- ch->rxptr = memaddr+(((bc->rseg-memory_seg) << 4) & 0x1fff);
- ch->rxwin = FEPWIN | ((bc->rseg-memory_seg) >>9 );
- }
-
- ch->txbufsize = bc->tmax + 1;
- ch->rxbufsize = bc->rmax + 1;
- ch->tmp_buf = kmalloc(ch->txbufsize,GFP_KERNEL);
- init_MUTEX(&ch->tmp_buf_sem);
-
- if (!ch->tmp_buf) {
- printk(KERN_ERR "Unable to allocate memory for temp buffers\n");
- goto cleanup_boards;
- }
-
- lowwater = ch->txbufsize >= 2000 ? 1024 : ch->txbufsize/2;
- fepcmd(ch, STXLWATER, lowwater, 0, 10, 0);
- fepcmd(ch, SRXLWATER, ch->rxbufsize/4, 0, 10, 0);
- fepcmd(ch, SRXHWATER, 3 * ch->rxbufsize/4, 0, 10, 0);
-
- bc->edelay = 100;
- bc->idata = 1;
-
- ch->startc = bc->startc;
- ch->stopc = bc->stopc;
- ch->startca = bc->startca;
- ch->stopca = bc->stopca;
-
- ch->fepcflag = 0;
- ch->fepiflag = 0;
- ch->fepoflag = 0;
- ch->fepstartc = 0;
- ch->fepstopc = 0;
- ch->fepstartca = 0;
- ch->fepstopca = 0;
-
- ch->close_delay = 50;
- ch->count = 0;
- ch->blocked_open = 0;
- init_waitqueue_head(&ch->open_wait);
- init_waitqueue_head(&ch->close_wait);
- ch->asyncflags = 0;
- }
-
- if (verbose)
- printk("Card No. %d ready: %s (%s) I/O=0x%x Mem=0x%lx Ports=%d\n",
- crd+1, board_desc[bd->type], board_mem[bd->type], bd->port,
- bd->membase, bd->numports);
- else
- printk("PC/Xx: %s (%s) I/O=0x%x Mem=0x%lx Ports=%d\n",
- board_desc[bd->type], board_mem[bd->type], bd->port,
- bd->membase, bd->numports);
-
- memwinoff(bd, 0);
- enabled_cards++;
- }
-
- if (enabled_cards <= 0) {
- printk(KERN_NOTICE "PC/Xx: No cards enabled, no driver.\n");
- ret = -EIO;
- goto cleanup_boards;
- }
-
- ret = tty_register_driver(pcxe_driver);
- if(ret) {
- printk(KERN_ERR "Couldn't register PC/Xe driver\n");
- goto cleanup_boards;
- }
-
- /*
- * Start up the poller to check for events on all enabled boards
- */
- mod_timer(&pcxx_timer, HZ/25);
-
- if (verbose)
- printk(KERN_NOTICE "PC/Xx: Driver with %d card(s) ready.\n", enabled_cards);
-
- return 0;
-cleanup_boards:
- cleanup_board_resources();
- kfree(digi_channels);
- put_tty_driver(pcxe_driver);
- return ret;
-}
-
-module_init(pcxe_init)
-module_exit(pcxe_cleanup)
-
-static void pcxxpoll(unsigned long dummy)
-{
- unsigned long flags;
- int crd;
- volatile unsigned int head, tail;
- struct channel *ch;
- struct board_info *bd;
-
- save_flags(flags);
- cli();
-
- for(crd=0; crd < numcards; crd++) {
- bd = &boards[crd];
-
- ch = digi_channels+bd->first_minor;
-
- if(bd->status == DISABLED)
- continue;
-
- assertmemoff(ch);
-
- globalwinon(ch);
- head = ch->mailbox->ein;
- tail = ch->mailbox->eout;
-
- if(head != tail)
- doevent(crd);
-
- memoff(ch);
- }
-
- mod_timer(&pcxx_timer, jiffies + HZ/25);
- restore_flags(flags);
-}
-
-static void doevent(int crd)
-{
- volatile struct board_info *bd;
- static struct tty_struct *tty;
- volatile struct board_chan *bc;
- volatile unchar *eventbuf;
- volatile unsigned int head;
- volatile unsigned int tail;
- struct channel *ch;
- struct channel *chan0;
- int channel, event, mstat, lstat;
-
- bd = &boards[crd];
-
- chan0 = digi_channels+bd->first_minor;
- pcxxassert(chan0 < digi_channels+nbdevs, "ch out of range");
-
-
- assertgwinon(chan0);
-
- while ((tail = chan0->mailbox->eout) != (head = chan0->mailbox->ein)) {
- assertgwinon(chan0);
- eventbuf = (volatile unchar *)phys_to_virt(bd->membase + tail + ISTART);
- channel = eventbuf[0];
- event = eventbuf[1];
- mstat = eventbuf[2];
- lstat = eventbuf[3];
-
- ch=chan0+channel;
-
- if ((unsigned)channel >= bd->numports || !ch) {
- printk("physmem=%lx, tail=%x, head=%x\n", bd->membase, tail, head);
- printk("doevent(%x) channel %x, event %x, mstat %x, lstat %x\n",
- crd, (unsigned)channel, event, (unsigned)mstat, lstat);
- if(channel >= bd->numports)
- ch = chan0;
- bc = ch->brdchan;
- goto next;
- }
- if ((bc = ch->brdchan) == NULL)
- goto next;
-
- if (event & DATA_IND) {
- receive_data(ch);
- assertgwinon(ch);
- }
-
- if (event & MODEMCHG_IND) {
- ch->imodem = mstat;
- if (ch->asyncflags & ASYNC_NORMAL_ACTIVE) {
- if (ch->asyncflags & ASYNC_CHECK_CD) {
- if (mstat & ch->dcd) {
- wake_up_interruptible(&ch->open_wait);
- } else {
- pcxe_sched_event(ch, PCXE_EVENT_HANGUP);
- }
- }
- }
- }
-
- tty = ch->tty;
-
- if (tty) {
-
- if (event & BREAK_IND) {
- tty->flip.count++;
- *tty->flip.flag_buf_ptr++ = TTY_BREAK;
- *tty->flip.char_buf_ptr++ = 0;
-#if 0
- if (ch->asyncflags & ASYNC_SAK)
- do_SAK(tty);
-#endif
- tty_schedule_flip(tty);
- }
-
- if (event & LOWTX_IND) {
- if (ch->statusflags & LOWWAIT) {
- ch->statusflags &= ~LOWWAIT;
- tty_wakeup(tty);
- }
- }
-
- if (event & EMPTYTX_IND) {
- ch->statusflags &= ~TXBUSY;
- if (ch->statusflags & EMPTYWAIT) {
- ch->statusflags &= ~EMPTYWAIT;
- tty_wakeup(tty);
- }
- }
- }
-
- next:
- globalwinon(ch);
- if(!bc) printk("bc == NULL in doevent!\n");
- else bc->idata = 1;
-
- chan0->mailbox->eout = (tail+4) & (IMAX-ISTART-4);
- globalwinon(chan0);
- }
-
-}
-
-
-static void
-fepcmd(struct channel *ch, int cmd, int word_or_byte, int byte2, int ncmds,
- int bytecmd)
-{
- unchar *memaddr;
- unsigned int head, tail;
- long count;
- int n;
-
- if(ch->board->status == DISABLED)
- return;
-
- assertgwinon(ch);
-
- memaddr = (unchar *)phys_to_virt(ch->board->membase);
- head = ch->mailbox->cin;
-
- if(head >= (CMAX-CSTART) || (head & 03)) {
- printk("line %d: Out of range, cmd=%x, head=%x\n", __LINE__, cmd, head);
- return;
- }
-
- if(bytecmd) {
- *(unchar *)(memaddr+head+CSTART+0) = cmd;
-
- *(unchar *)(memaddr+head+CSTART+1) = ch->dev - ch->board->first_minor;
-
- *(unchar *)(memaddr+head+CSTART+2) = word_or_byte;
- *(unchar *)(memaddr+head+CSTART+3) = byte2;
- } else {
- *(unchar *)(memaddr+head+CSTART+0) = cmd;
-
- *(unchar *)(memaddr+head+CSTART+1) = ch->dev - ch->board->first_minor;
- *(ushort*)(memaddr+head+CSTART+2) = word_or_byte;
- }
-
- head = (head+4) & (CMAX-CSTART-4);
- ch->mailbox->cin = head;
-
- count = FEPTIMEOUT;
-
- while(1) {
- count--;
- if(count == 0) {
- printk("Fep not responding in fepcmd()\n");
- return;
- }
-
- head = ch->mailbox->cin;
- tail = ch->mailbox->cout;
-
- n = (head-tail) & (CMAX-CSTART-4);
-
- if(n <= ncmds * (sizeof(short)*4))
- break;
- /* Seems not to be good here: schedule(); */
- }
-}
-
-
-static unsigned termios2digi_c(struct channel *ch, unsigned cflag)
-{
- unsigned res = 0;
- if (cflag & CBAUDEX)
- {
- ch->digiext.digi_flags |= DIGI_FAST;
- res |= FEP_HUPCL;
- /* This gets strange but if we don't do this we will get 78600
- * instead of 115200. 57600 is mapped to 50 baud yielding 57600 in
- * FAST mode. 115200 is mapped to 75. We need to map it to 110 to
- * do 115K
- */
- if (cflag & B115200) res|=1;
- }
- else ch->digiext.digi_flags &= ~DIGI_FAST;
- res |= cflag & (CBAUD | PARODD | PARENB | CSTOPB | CSIZE | CLOCAL);
- return res;
-}
-
-static unsigned termios2digi_i(struct channel *ch, unsigned iflag)
-{
- unsigned res = iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK|ISTRIP|IXON|IXANY|IXOFF);
-
- if(ch->digiext.digi_flags & DIGI_AIXON)
- res |= IAIXON;
- return res;
-}
-
-static unsigned termios2digi_h(struct channel *ch, unsigned cflag)
-{
- unsigned res = 0;
-
- if(cflag & CRTSCTS) {
- ch->digiext.digi_flags |= (RTSPACE|CTSPACE);
- res |= (CTS | RTS);
- }
- if(ch->digiext.digi_flags & RTSPACE)
- res |= RTS;
- if(ch->digiext.digi_flags & DTRPACE)
- res |= DTR;
- if(ch->digiext.digi_flags & CTSPACE)
- res |= CTS;
- if(ch->digiext.digi_flags & DSRPACE)
- res |= ch->dsr;
- if(ch->digiext.digi_flags & DCDPACE)
- res |= ch->dcd;
-
- if (res & RTS)
- ch->digiext.digi_flags |= RTSPACE;
- if (res & CTS)
- ch->digiext.digi_flags |= CTSPACE;
-
- return res;
-}
-
-static void pcxxparam(struct tty_struct *tty, struct channel *ch)
-{
- volatile struct board_chan *bc;
- unsigned int head;
- unsigned mval, hflow, cflag, iflag;
- struct termios *ts;
-
- bc = ch->brdchan;
- assertgwinon(ch);
- ts = tty->termios;
-
- if((ts->c_cflag & CBAUD) == 0) {
- head = bc->rin;
- bc->rout = head;
- head = bc->tin;
- fepcmd(ch, STOUT, (unsigned) head, 0, 0, 0);
- mval = 0;
- } else {
-
- cflag = termios2digi_c(ch, ts->c_cflag);
-
- if(cflag != ch->fepcflag) {
- ch->fepcflag = cflag;
- fepcmd(ch, SETCTRLFLAGS, (unsigned) cflag, 0, 0, 0);
- }
-
- if(cflag & CLOCAL)
- ch->asyncflags &= ~ASYNC_CHECK_CD;
- else {
- ch->asyncflags |= ASYNC_CHECK_CD;
- }
-
- mval = DTR | RTS;
- }
-
- iflag = termios2digi_i(ch, ts->c_iflag);
-
- if(iflag != ch->fepiflag) {
- ch->fepiflag = iflag;
- fepcmd(ch, SETIFLAGS, (unsigned int) ch->fepiflag, 0, 0, 0);
- }
-
- bc->mint = ch->dcd;
- if((ts->c_cflag & CLOCAL) || (ch->digiext.digi_flags & DIGI_FORCEDCD))
- if(ch->digiext.digi_flags & DIGI_FORCEDCD)
- bc->mint = 0;
-
- ch->imodem = bc->mstat;
-
- hflow = termios2digi_h(ch, ts->c_cflag);
-
- if(hflow != ch->hflow) {
- ch->hflow = hflow;
- fepcmd(ch, SETHFLOW, hflow, 0xff, 0, 1);
- }
-
- /* mval ^= ch->modemfake & (mval ^ ch->modem); */
-
- if(ch->omodem != mval) {
- ch->omodem = mval;
- fepcmd(ch, SETMODEM, mval, RTS|DTR, 0, 1);
- }
-
- if(ch->startc != ch->fepstartc || ch->stopc != ch->fepstopc) {
- ch->fepstartc = ch->startc;
- ch->fepstopc = ch->stopc;
- fepcmd(ch, SONOFFC, ch->fepstartc, ch->fepstopc, 0, 1);
- }
-
- if(ch->startca != ch->fepstartca || ch->stopca != ch->fepstopca) {
- ch->fepstartca = ch->startca;
- ch->fepstopca = ch->stopca;
- fepcmd(ch, SAUXONOFFC, ch->fepstartca, ch->fepstopca, 0, 1);
- }
-}
-
-
-static void receive_data(struct channel *ch)
-{
- volatile struct board_chan *bc;
- struct tty_struct *tty;
- unsigned int tail, head, wrapmask;
- int n;
- int piece;
- struct termios *ts=0;
- unchar *rptr;
- int rc;
- int wrapgap;
-
- globalwinon(ch);
-
- if (ch->statusflags & RXSTOPPED)
- return;
-
- tty = ch->tty;
- if(tty)
- ts = tty->termios;
-
- bc = ch->brdchan;
-
- if(!bc) {
- printk("bc is NULL in receive_data!\n");
- return;
- }
-
- wrapmask = ch->rxbufsize - 1;
-
- head = bc->rin;
- head &= wrapmask;
- tail = bc->rout & wrapmask;
-
- n = (head-tail) & wrapmask;
-
- if(n == 0)
- return;
-
- /*
- * If CREAD bit is off or device not open, set TX tail to head
- */
- if(!tty || !ts || !(ts->c_cflag & CREAD)) {
- bc->rout = head;
- return;
- }
-
- if(tty->flip.count == TTY_FLIPBUF_SIZE) {
- /* printk("tty->flip.count = TTY_FLIPBUF_SIZE\n"); */
- return;
- }
-
- if(bc->orun) {
- bc->orun = 0;
- printk("overrun! DigiBoard device %s\n", tty->name);
- }
-
- rxwinon(ch);
- rptr = tty->flip.char_buf_ptr;
- rc = tty->flip.count;
- while(n > 0) {
- wrapgap = (head >= tail) ? head - tail : ch->rxbufsize - tail;
- piece = (wrapgap < n) ? wrapgap : n;
-
- /*
- * Make sure we don't overflow the buffer
- */
-
- if ((rc + piece) > TTY_FLIPBUF_SIZE)
- piece = TTY_FLIPBUF_SIZE - rc;
-
- if (piece == 0)
- break;
-
- memcpy(rptr, ch->rxptr + tail, piece);
- rptr += piece;
- rc += piece;
- tail = (tail + piece) & wrapmask;
- n -= piece;
- }
- tty->flip.count = rc;
- tty->flip.char_buf_ptr = rptr;
- globalwinon(ch);
- bc->rout = tail;
-
- /* Must be called with global data */
- tty_schedule_flip(ch->tty);
- return;
-}
-
-
-static int pcxe_tiocmget(struct tty_struct *tty, struct file *file)
-{
- struct channel *ch = (struct channel *) tty->driver_data;
- volatile struct board_chan *bc;
- unsigned long flags;
- int mflag = 0;
- int mstat;
-
- if(ch)
- bc = ch->brdchan;
- else {
- printk("ch is NULL in %s!\n", __FUNCTION__);
- return(-EINVAL);
- }
-
- save_flags(flags);
- cli();
- globalwinon(ch);
- mstat = bc->mstat;
- memoff(ch);
- restore_flags(flags);
-
- if(mstat & DTR)
- mflag |= TIOCM_DTR;
- if(mstat & RTS)
- mflag |= TIOCM_RTS;
- if(mstat & CTS)
- mflag |= TIOCM_CTS;
- if(mstat & ch->dsr)
- mflag |= TIOCM_DSR;
- if(mstat & RI)
- mflag |= TIOCM_RI;
- if(mstat & ch->dcd)
- mflag |= TIOCM_CD;
-
- return mflag;
-}
-
-
-static int pcxe_tiocmset(struct tty_struct *tty, struct file *file,
- unsigned int set, unsigned int clear)
-{
- struct channel *ch = (struct channel *) tty->driver_data;
- volatile struct board_chan *bc;
- unsigned long flags;
-
- if(ch)
- bc = ch->brdchan;
- else {
- printk("ch is NULL in %s!\n", __FUNCTION__);
- return(-EINVAL);
- }
-
- save_flags(flags);
- cli();
- /*
- * I think this modemfake stuff is broken. It doesn't
- * correctly reflect the behaviour desired by the TIOCM*
- * ioctls. Therefore this is probably broken.
- */
- if (set & TIOCM_DTR) {
- ch->modemfake |= DTR;
- ch->modem |= DTR;
- }
- if (set & TIOCM_RTS) {
- ch->modemfake |= RTS;
- ch->modem |= RTS;
- }
-
- if (clear & TIOCM_DTR) {
- ch->modemfake |= DTR;
- ch->modem &= ~DTR;
- }
- if (clear & TIOCM_RTS) {
- ch->modemfake |= RTS;
- ch->modem &= ~RTS;
- }
- globalwinon(ch);
- pcxxparam(tty,ch);
- memoff(ch);
- restore_flags(flags);
- return 0;
-}
-
-
-static int pcxe_ioctl(struct tty_struct *tty, struct file * file,
- unsigned int cmd, unsigned long arg)
-{
- struct channel *ch = (struct channel *) tty->driver_data;
- volatile struct board_chan *bc;
- int retval;
- unsigned int mflag, mstat;
- unsigned char startc, stopc;
- unsigned long flags;
- digiflow_t dflow;
-
- if(ch)
- bc = ch->brdchan;
- else {
- printk("ch is NULL in pcxe_ioctl!\n");
- return(-EINVAL);
- }
-
- save_flags(flags);
-
- switch(cmd) {
- case TCSBRK: /* SVID version: non-zero arg --> no break */
- retval = tty_check_change(tty);
- if(retval)
- return retval;
- setup_empty_event(tty,ch);
- tty_wait_until_sent(tty, 0);
- if(!arg)
- digi_send_break(ch, HZ/4); /* 1/4 second */
- return 0;
-
- case TCSBRKP: /* support for POSIX tcsendbreak() */
- retval = tty_check_change(tty);
- if(retval)
- return retval;
- setup_empty_event(tty,ch);
- tty_wait_until_sent(tty, 0);
- digi_send_break(ch, arg ? arg*(HZ/10) : HZ/4);
- return 0;
-
- case TIOCGSOFTCAR:
- return put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned int *)arg);
-
- case TIOCSSOFTCAR:
- {
- unsigned int value;
- if (get_user(value, (unsigned int *) arg))
- return -EFAULT;
- tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) | (value ? CLOCAL : 0));
- }
- return 0;
-
- case TIOCMODG:
- mflag = pcxe_tiocmget(tty, file);
- if (put_user(mflag, (unsigned int *) arg))
- return -EFAULT;
- break;
-
- case TIOCMODS:
- if (get_user(mstat, (unsigned int *) arg))
- return -EFAULT;
- return pcxe_tiocmset(tty, file, mstat, ~mstat);
-
- case TIOCSDTR:
- cli();
- ch->omodem |= DTR;
- globalwinon(ch);
- fepcmd(ch, SETMODEM, DTR, 0, 10, 1);
- memoff(ch);
- restore_flags(flags);
- break;
-
- case TIOCCDTR:
- ch->omodem &= ~DTR;
- cli();
- globalwinon(ch);
- fepcmd(ch, SETMODEM, 0, DTR, 10, 1);
- memoff(ch);
- restore_flags(flags);
- break;
-
- case DIGI_GETA:
- if (copy_to_user((char*)arg, &ch->digiext, sizeof(digi_t)))
- return -EFAULT;
- break;
-
- case DIGI_SETAW:
- case DIGI_SETAF:
- if(cmd == DIGI_SETAW) {
- setup_empty_event(tty,ch);
- tty_wait_until_sent(tty, 0);
- }
- else {
- tty_ldisc_flush(tty);
- }
-
- /* Fall Thru */
-
- case DIGI_SETA:
- if (copy_from_user(&ch->digiext, (char*)arg, sizeof(digi_t)))
- return -EFAULT;
-#ifdef DEBUG_IOCTL
- printk("ioctl(DIGI_SETA): flags = %x\n", ch->digiext.digi_flags);
-#endif
-
- if(ch->digiext.digi_flags & DIGI_ALTPIN) {
- ch->dcd = DSR;
- ch->dsr = CD;
- } else {
- ch->dcd = CD;
- ch->dsr = DSR;
- }
-
- cli();
- globalwinon(ch);
- pcxxparam(tty,ch);
- memoff(ch);
- restore_flags(flags);
- break;
-
- case DIGI_GETFLOW:
- case DIGI_GETAFLOW:
- cli();
- globalwinon(ch);
- if(cmd == DIGI_GETFLOW) {
- dflow.startc = bc->startc;
- dflow.stopc = bc->stopc;
- } else {
- dflow.startc = bc->startca;
- dflow.stopc = bc->stopca;
- }
- memoff(ch);
- restore_flags(flags);
-
- if (copy_to_user((char*)arg, &dflow, sizeof(dflow)))
- return -EFAULT;
- break;
-
- case DIGI_SETAFLOW:
- case DIGI_SETFLOW:
- if(cmd == DIGI_SETFLOW) {
- startc = ch->startc;
- stopc = ch->stopc;
- } else {
- startc = ch->startca;
- stopc = ch->stopca;
- }
-
- if (copy_from_user(&dflow, (char*)arg, sizeof(dflow)))
- return -EFAULT;
-
- if(dflow.startc != startc || dflow.stopc != stopc) {
- cli();
- globalwinon(ch);
-
- if(cmd == DIGI_SETFLOW) {
- ch->fepstartc = ch->startc = dflow.startc;
- ch->fepstopc = ch->stopc = dflow.stopc;
- fepcmd(ch,SONOFFC,ch->fepstartc,ch->fepstopc,0, 1);
- } else {
- ch->fepstartca = ch->startca = dflow.startc;
- ch->fepstopca = ch->stopca = dflow.stopc;
- fepcmd(ch, SAUXONOFFC, ch->fepstartca, ch->fepstopca, 0, 1);
- }
-
- if(ch->statusflags & TXSTOPPED)
- pcxe_start(tty);
-
- memoff(ch);
- restore_flags(flags);
- }
- break;
-
- default:
- return -ENOIOCTLCMD;
- }
-
- return 0;
-}
-
-static void pcxe_set_termios(struct tty_struct *tty, struct termios *old_termios)
-{
- struct channel *info;
-
- if ((info=chan(tty))!=NULL) {
- unsigned long flags;
- save_flags(flags);
- cli();
- globalwinon(info);
- pcxxparam(tty,info);
- memoff(info);
-
- if ((old_termios->c_cflag & CRTSCTS) &&
- ((tty->termios->c_cflag & CRTSCTS) == 0))
- tty->hw_stopped = 0;
- if(!(old_termios->c_cflag & CLOCAL) &&
- (tty->termios->c_cflag & CLOCAL))
- wake_up_interruptible(&info->open_wait);
- restore_flags(flags);
- }
-}
-
-
-
-static void do_softint(void *private_)
-{
- struct channel *info = (struct channel *) private_;
-
- if(info && info->magic == PCXX_MAGIC) {
- struct tty_struct *tty = info->tty;
- if (tty && tty->driver_data) {
- if(test_and_clear_bit(PCXE_EVENT_HANGUP, &info->event)) {
- tty_hangup(tty);
- wake_up_interruptible(&info->open_wait);
- info->asyncflags &= ~ASYNC_NORMAL_ACTIVE;
- }
- }
- }
-}
-
-
-static void pcxe_stop(struct tty_struct *tty)
-{
- struct channel *info;
-
- if ((info=chan(tty))!=NULL) {
- unsigned long flags;
- save_flags(flags);
- cli();
- if ((info->statusflags & TXSTOPPED) == 0) {
- globalwinon(info);
- fepcmd(info, PAUSETX, 0, 0, 0, 0);
- info->statusflags |= TXSTOPPED;
- memoff(info);
- }
- restore_flags(flags);
- }
-}
-
-static void pcxe_throttle(struct tty_struct * tty)
-{
- struct channel *info;
-
- if ((info=chan(tty))!=NULL) {
- unsigned long flags;
- save_flags(flags);
- cli();
- if ((info->statusflags & RXSTOPPED) == 0) {
- globalwinon(info);
- fepcmd(info, PAUSERX, 0, 0, 0, 0);
- info->statusflags |= RXSTOPPED;
- memoff(info);
- }
- restore_flags(flags);
- }
-}
-
-static void pcxe_unthrottle(struct tty_struct *tty)
-{
- struct channel *info;
-
- if ((info=chan(tty)) != NULL) {
- unsigned long flags;
-
- /* Just in case output was resumed because of a change in Digi-flow */
- save_flags(flags);
- cli();
- if(info->statusflags & RXSTOPPED) {
- volatile struct board_chan *bc;
- globalwinon(info);
- bc = info->brdchan;
- fepcmd(info, RESUMERX, 0, 0, 0, 0);
- info->statusflags &= ~RXSTOPPED;
- memoff(info);
- }
- restore_flags(flags);
- }
-}
-
-
-static void pcxe_start(struct tty_struct *tty)
-{
- struct channel *info;
-
- if ((info=chan(tty))!=NULL) {
- unsigned long flags;
-
- save_flags(flags);
- cli();
- /* Just in case output was resumed because of a change in Digi-flow */
- if(info->statusflags & TXSTOPPED) {
- volatile struct board_chan *bc;
- globalwinon(info);
- bc = info->brdchan;
- if(info->statusflags & LOWWAIT)
- bc->ilow = 1;
- fepcmd(info, RESUMETX, 0, 0, 0, 0);
- info->statusflags &= ~TXSTOPPED;
- memoff(info);
- }
- restore_flags(flags);
- }
-}
-
-
-void digi_send_break(struct channel *ch, int msec)
-{
- unsigned long flags;
-
- save_flags(flags);
- cli();
- globalwinon(ch);
-
- /*
- * Maybe I should send an infinite break here, schedule() for
- * msec amount of time, and then stop the break. This way,
- * the user can't screw up the FEP by causing digi_send_break()
- * to be called (i.e. via an ioctl()) more than once in msec amount
- * of time. Try this for now...
- */
-
- fepcmd(ch, SENDBREAK, msec, 0, 10, 0);
- memoff(ch);
-
- restore_flags(flags);
-}
-
-static void setup_empty_event(struct tty_struct *tty, struct channel *ch)
-{
- volatile struct board_chan *bc;
- unsigned long flags;
-
- save_flags(flags);
- cli();
- globalwinon(ch);
- ch->statusflags |= EMPTYWAIT;
- bc = ch->brdchan;
- bc->iempty = 1;
- memoff(ch);
- restore_flags(flags);
-}
diff --git a/drivers/char/pcxx.h b/drivers/char/pcxx.h
deleted file mode 100644
index af105c43475c5..0000000000000
--- a/drivers/char/pcxx.h
+++ /dev/null
@@ -1,128 +0,0 @@
-#define FEPCODESEG 0x0200L
-#define FEPCODE 0x2000L
-#define BIOSCODE 0xf800L
-
-#define MISCGLOBAL 0x0C00L
-#define NPORT 0x0C22L
-#define MBOX 0x0C40L
-#define PORTBASE 0x0C90L
-
-#define FEPCLR 0x00
-#define FEPMEM 0x02
-#define FEPRST 0x04
-#define FEPINT 0x08
-#define FEPMASK 0x0e
-#define FEPWIN 0x80
-
-/* Maximum Number of Boards supported */
-#define MAX_DIGI_BOARDS 4
-
-#define PCXX_NUM_TYPES 4
-
-#define PCXI 0
-#define PCXE 1
-#define PCXEVE 2
-#define PCXEM 3
-
-static char *board_desc[] = {
- "PC/Xi",
- "PC/Xe",
- "PC/Xeve",
- "PC/Xem",
-};
-
-static char *board_mem[] = {
- "64k",
- "64k",
- "8k",
- "32k",
-};
-#define STARTC 021
-#define STOPC 023
-#define IAIXON 0x2000
-
-
-struct board_info {
- unchar status;
- unchar type;
- unchar altpin;
- ushort numports;
- ushort port;
- ulong membase;
- ulong memsize;
- ushort first_minor;
- void *region;
-};
-
-
-#define TXSTOPPED 0x01
-#define LOWWAIT 0x02
-#define EMPTYWAIT 0x04
-#define RXSTOPPED 0x08
-#define TXBUSY 0x10
-
-#define DISABLED 0
-#define ENABLED 1
-#define OFF 0
-#define ON 1
-
-#define FEPTIMEOUT 200000
-#define SERIAL_TYPE_NORMAL 1
-#define PCXE_EVENT_HANGUP 1
-#define PCXX_MAGIC 0x5c6df104L
-
-struct channel {
- /* --------- Board/channel information ---------- */
- long magic;
- unchar boardnum;
- unchar channelnum;
- uint dev;
- struct tty_struct *tty;
- struct board_info *board;
- volatile struct board_chan *brdchan;
- volatile struct global_data *mailbox;
- int asyncflags;
- int count;
- int blocked_open;
- int close_delay;
- unsigned long event;
- wait_queue_head_t open_wait;
- wait_queue_head_t close_wait;
- struct work_struct tqueue;
- /* ------------ Async control data ------------- */
- unchar modemfake; /* Modem values to be forced */
- unchar modem; /* Force values */
- ulong statusflags;
- unchar omodem; /* FEP output modem status */
- unchar imodem; /* FEP input modem status */
- unchar hflow;
- unchar dsr;
- unchar dcd;
- unchar stopc;
- unchar startc;
- unchar stopca;
- unchar startca;
- unchar fepstopc;
- unchar fepstartc;
- unchar fepstopca;
- unchar fepstartca;
- ushort fepiflag;
- ushort fepcflag;
- ushort fepoflag;
- /* ---------- Transmit/receive system ---------- */
- unchar txwin;
- unchar rxwin;
- ushort txbufsize;
- ushort rxbufsize;
- unchar *txptr;
- unchar *rxptr;
- unchar *tmp_buf; /* Temp buffer */
- struct semaphore tmp_buf_sem;
- /* ---- Termios data ---- */
- ulong c_iflag;
- ulong c_cflag;
- ulong c_lflag;
- ulong c_oflag;
- struct digi_struct digiext;
- ulong dummy[8];
-};
diff --git a/drivers/char/pty.c b/drivers/char/pty.c
index 22e6caadcddf9..da32889d22c09 100644
--- a/drivers/char/pty.c
+++ b/drivers/char/pty.c
@@ -149,13 +149,15 @@ static int pty_write_room(struct tty_struct *tty)
static int pty_chars_in_buffer(struct tty_struct *tty)
{
struct tty_struct *to = tty->link;
+ ssize_t (*chars_in_buffer)(struct tty_struct *);
int count;
- if (!to || !to->ldisc.chars_in_buffer)
+ /* We should get the line discipline lock for "tty->link" */
+ if (!to || !(chars_in_buffer = to->ldisc.chars_in_buffer))
return 0;
/* The ldisc must report 0 if no characters available to be read */
- count = to->ldisc.chars_in_buffer(to);
+ count = chars_in_buffer(to);
if (tty->driver->subtype == PTY_TYPE_SLAVE) return count;
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 0fcbfa3a77dfc..ad9b52c2ae3c5 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -218,13 +218,6 @@
* Any flaws in the design are solely my responsibility, and should
* not be attributed to the Phil, Colin, or any of authors of PGP.
*
- * The code for SHA transform was taken from Peter Gutmann's
- * implementation, which has been placed in the public domain.
- * The code for MD5 transform was taken from Colin Plumb's
- * implementation, which has been placed in the public domain.
- * The MD5 cryptographic checksum was devised by Ronald Rivest, and is
- * documented in RFC 1321, "The MD5 Message Digest Algorithm".
- *
* Further background information on this topic may be obtained from
* RFC 1750, "Randomness Recommendations for Security", by Donald
* Eastlake, Steve Crocker, and Jeff Schiller.
@@ -242,11 +235,11 @@
#include <linux/poll.h>
#include <linux/init.h>
#include <linux/fs.h>
-#include <linux/workqueue.h>
#include <linux/genhd.h>
#include <linux/interrupt.h>
#include <linux/spinlock.h>
#include <linux/percpu.h>
+#include <linux/cryptohash.h>
#include <asm/processor.h>
#include <asm/uaccess.h>
@@ -256,10 +249,9 @@
/*
* Configuration information
*/
-#define DEFAULT_POOL_SIZE 512
-#define SECONDARY_POOL_SIZE 128
-#define BATCH_ENTROPY_SIZE 256
-#define USE_SHA
+#define INPUT_POOL_WORDS 128
+#define OUTPUT_POOL_WORDS 32
+#define SEC_XFER_SIZE 512
/*
* The minimum number of bits of entropy before we wake up a read on
@@ -279,7 +271,7 @@ static int random_write_wakeup_thresh = 128;
* samples to avoid wasting CPU time and reduce lock contention.
*/
-static int trickle_thresh = DEFAULT_POOL_SIZE * 7;
+static int trickle_thresh = INPUT_POOL_WORDS * 28;
static DEFINE_PER_CPU(int, trickle_count) = 0;
@@ -295,42 +287,37 @@ static struct poolinfo {
int poolwords;
int tap1, tap2, tap3, tap4, tap5;
} poolinfo_table[] = {
+ /* x^128 + x^103 + x^76 + x^51 +x^25 + x + 1 -- 105 */
+ { 128, 103, 76, 51, 25, 1 },
+ /* x^32 + x^26 + x^20 + x^14 + x^7 + x + 1 -- 15 */
+ { 32, 26, 20, 14, 7, 1 },
+#if 0
/* x^2048 + x^1638 + x^1231 + x^819 + x^411 + x + 1 -- 115 */
{ 2048, 1638, 1231, 819, 411, 1 },
/* x^1024 + x^817 + x^615 + x^412 + x^204 + x + 1 -- 290 */
{ 1024, 817, 615, 412, 204, 1 },
-#if 0 /* Alternate polynomial */
+
/* x^1024 + x^819 + x^616 + x^410 + x^207 + x^2 + 1 -- 115 */
{ 1024, 819, 616, 410, 207, 2 },
-#endif
/* x^512 + x^411 + x^308 + x^208 + x^104 + x + 1 -- 225 */
{ 512, 411, 308, 208, 104, 1 },
-#if 0 /* Alternates */
+
/* x^512 + x^409 + x^307 + x^206 + x^102 + x^2 + 1 -- 95 */
{ 512, 409, 307, 206, 102, 2 },
/* x^512 + x^409 + x^309 + x^205 + x^103 + x^2 + 1 -- 95 */
{ 512, 409, 309, 205, 103, 2 },
-#endif
/* x^256 + x^205 + x^155 + x^101 + x^52 + x + 1 -- 125 */
{ 256, 205, 155, 101, 52, 1 },
- /* x^128 + x^103 + x^76 + x^51 +x^25 + x + 1 -- 105 */
- { 128, 103, 76, 51, 25, 1 },
-#if 0 /* Alternate polynomial */
/* x^128 + x^103 + x^78 + x^51 + x^27 + x^2 + 1 -- 70 */
{ 128, 103, 78, 51, 27, 2 },
-#endif
/* x^64 + x^52 + x^39 + x^26 + x^14 + x + 1 -- 15 */
{ 64, 52, 39, 26, 14, 1 },
-
- /* x^32 + x^26 + x^20 + x^14 + x^7 + x + 1 -- 15 */
- { 32, 26, 20, 14, 7, 1 },
-
- { 0, 0, 0, 0, 0, 0 },
+#endif
};
#define POOLBITS poolwords*32
@@ -380,104 +367,20 @@ static struct poolinfo {
*/
/*
- * Linux 2.2 compatibility
- */
-#ifndef DECLARE_WAITQUEUE
-#define DECLARE_WAITQUEUE(WAIT, PTR) struct wait_queue WAIT = { PTR, NULL }
-#endif
-#ifndef DECLARE_WAIT_QUEUE_HEAD
-#define DECLARE_WAIT_QUEUE_HEAD(WAIT) struct wait_queue *WAIT
-#endif
-
-/*
* Static global variables
*/
-static struct entropy_store *random_state; /* The default global store */
-static struct entropy_store *sec_random_state; /* secondary store */
-static struct entropy_store *urandom_state; /* For urandom */
static DECLARE_WAIT_QUEUE_HEAD(random_read_wait);
static DECLARE_WAIT_QUEUE_HEAD(random_write_wait);
-/*
- * Forward procedure declarations
- */
-#ifdef CONFIG_SYSCTL
-static void sysctl_init_random(struct entropy_store *random_state);
-#endif
-
-/*****************************************************************
- *
- * Utility functions, with some ASM defined functions for speed
- * purposes
- *
- *****************************************************************/
-
-/*
- * Unfortunately, while the GCC optimizer for the i386 understands how
- * to optimize a static rotate left of x bits, it doesn't know how to
- * deal with a variable rotate of x bits. So we use a bit of asm magic.
- */
-#if (!defined (__i386__))
-static inline __u32 rotate_left(int i, __u32 word)
-{
- return (word << i) | (word >> (32 - i));
-}
-#else
-static inline __u32 rotate_left(int i, __u32 word)
-{
- __asm__("roll %%cl,%0"
- :"=r" (word)
- :"0" (word),"c" (i));
- return word;
-}
-#endif
-
-/*
- * More asm magic....
- *
- * For entropy estimation, we need to do an integral base 2
- * logarithm.
- *
- * Note the "12bits" suffix - this is used for numbers between
- * 0 and 4095 only. This allows a few shortcuts.
- */
-#if 0 /* Slow but clear version */
-static inline __u32 int_ln_12bits(__u32 word)
-{
- __u32 nbits = 0;
-
- while (word >>= 1)
- nbits++;
- return nbits;
-}
-#else /* Faster (more clever) version, courtesy Colin Plumb */
-static inline __u32 int_ln_12bits(__u32 word)
-{
- /* Smear msbit right to make an n-bit mask */
- word |= word >> 8;
- word |= word >> 4;
- word |= word >> 2;
- word |= word >> 1;
- /* Remove one bit to make this a logarithm */
- word >>= 1;
- /* Count the bits set in the word */
- word -= (word >> 1) & 0x555;
- word = (word & 0x333) + ((word >> 2) & 0x333);
- word += (word >> 4);
- word += (word >> 8);
- return word & 15;
-}
-#endif
-
#if 0
static int debug = 0;
module_param(debug, bool, 0644);
#define DEBUG_ENT(fmt, arg...) do { if (debug) \
printk(KERN_DEBUG "random %04d %04d %04d: " \
fmt,\
- random_state->entropy_count,\
- sec_random_state->entropy_count,\
- urandom_state->entropy_count,\
+ input_pool.entropy_count,\
+ blocking_pool.entropy_count,\
+ nonblocking_pool.entropy_count,\
## arg); } while (0)
#else
#define DEBUG_ENT(fmt, arg...) do {} while (0)
@@ -490,11 +393,14 @@ module_param(debug, bool, 0644);
*
**********************************************************************/
+struct entropy_store;
struct entropy_store {
/* mostly-read data: */
- struct poolinfo poolinfo;
+ struct poolinfo *poolinfo;
__u32 *pool;
const char *name;
+ int limit;
+ struct entropy_store *pull;
/* read-write data: */
spinlock_t lock ____cacheline_aligned_in_smp;
@@ -503,57 +409,34 @@ struct entropy_store {
int input_rotate;
};
-/*
- * Initialize the entropy store. The input argument is the size of
- * the random pool.
- *
- * Returns an negative error if there is a problem.
- */
-static int create_entropy_store(int size, const char *name,
- struct entropy_store **ret_bucket)
-{
- struct entropy_store *r;
- struct poolinfo *p;
- int poolwords;
-
- poolwords = (size + 3) / 4; /* Convert bytes->words */
- /* The pool size must be a multiple of 16 32-bit words */
- poolwords = ((poolwords + 15) / 16) * 16;
+static __u32 input_pool_data[INPUT_POOL_WORDS];
+static __u32 blocking_pool_data[OUTPUT_POOL_WORDS];
+static __u32 nonblocking_pool_data[OUTPUT_POOL_WORDS];
- for (p = poolinfo_table; p->poolwords; p++) {
- if (poolwords == p->poolwords)
- break;
- }
- if (p->poolwords == 0)
- return -EINVAL;
-
- r = kmalloc(sizeof(struct entropy_store), GFP_KERNEL);
- if (!r)
- return -ENOMEM;
-
- memset (r, 0, sizeof(struct entropy_store));
- r->poolinfo = *p;
+static struct entropy_store input_pool = {
+ .poolinfo = &poolinfo_table[0],
+ .name = "input",
+ .limit = 1,
+ .lock = SPIN_LOCK_UNLOCKED,
+ .pool = input_pool_data
+};
- r->pool = kmalloc(POOLBYTES, GFP_KERNEL);
- if (!r->pool) {
- kfree(r);
- return -ENOMEM;
- }
- memset(r->pool, 0, POOLBYTES);
- spin_lock_init(&r->lock);
- r->name = name;
- *ret_bucket = r;
- return 0;
-}
+static struct entropy_store blocking_pool = {
+ .poolinfo = &poolinfo_table[1],
+ .name = "blocking",
+ .limit = 1,
+ .pull = &input_pool,
+ .lock = SPIN_LOCK_UNLOCKED,
+ .pool = blocking_pool_data
+};
-/* Clear the entropy pool and associated counters. */
-static void clear_entropy_store(struct entropy_store *r)
-{
- r->add_ptr = 0;
- r->entropy_count = 0;
- r->input_rotate = 0;
- memset(r->pool, 0, r->poolinfo.POOLBYTES);
-}
+static struct entropy_store nonblocking_pool = {
+ .poolinfo = &poolinfo_table[1],
+ .name = "nonblocking",
+ .pull = &input_pool,
+ .lock = SPIN_LOCK_UNLOCKED,
+ .pool = nonblocking_pool_data
+};
/*
* This function adds a byte into the entropy "pool". It does not
@@ -573,16 +456,16 @@ static void __add_entropy_words(struct entropy_store *r, const __u32 *in,
0xedb88320, 0xd6d6a3e8, 0x9b64c2b0, 0xa00ae278 };
unsigned long i, add_ptr, tap1, tap2, tap3, tap4, tap5;
int new_rotate, input_rotate;
- int wordmask = r->poolinfo.poolwords - 1;
+ int wordmask = r->poolinfo->poolwords - 1;
__u32 w, next_w;
unsigned long flags;
/* Taps are constant, so we can load them without holding r->lock. */
- tap1 = r->poolinfo.tap1;
- tap2 = r->poolinfo.tap2;
- tap3 = r->poolinfo.tap3;
- tap4 = r->poolinfo.tap4;
- tap5 = r->poolinfo.tap5;
+ tap1 = r->poolinfo->tap1;
+ tap2 = r->poolinfo->tap2;
+ tap3 = r->poolinfo->tap3;
+ tap4 = r->poolinfo->tap4;
+ tap5 = r->poolinfo->tap5;
next_w = *in++;
spin_lock_irqsave(&r->lock, flags);
@@ -591,7 +474,7 @@ static void __add_entropy_words(struct entropy_store *r, const __u32 *in,
add_ptr = r->add_ptr;
while (nwords--) {
- w = rotate_left(input_rotate, next_w);
+ w = rol32(next_w, input_rotate);
if (nwords > 0)
next_w = *in++;
i = add_ptr = (add_ptr - 1) & wordmask;
@@ -648,8 +531,8 @@ static void credit_entropy_store(struct entropy_store *r, int nbits)
DEBUG_ENT("negative entropy/overflow (%d+%d)\n",
r->entropy_count, nbits);
r->entropy_count = 0;
- } else if (r->entropy_count + nbits > r->poolinfo.POOLBITS) {
- r->entropy_count = r->poolinfo.POOLBITS;
+ } else if (r->entropy_count + nbits > r->poolinfo->POOLBITS) {
+ r->entropy_count = r->poolinfo->POOLBITS;
} else {
r->entropy_count += nbits;
if (nbits)
@@ -660,118 +543,6 @@ static void credit_entropy_store(struct entropy_store *r, int nbits)
spin_unlock_irqrestore(&r->lock, flags);
}
-/**********************************************************************
- *
- * Entropy batch input management
- *
- * We batch entropy to be added to avoid increasing interrupt latency
- *
- **********************************************************************/
-
-struct sample {
- __u32 data[2];
- int credit;
-};
-
-static struct sample *batch_entropy_pool, *batch_entropy_copy;
-static int batch_head, batch_tail;
-static DEFINE_SPINLOCK(batch_lock);
-
-static int batch_max;
-static void batch_entropy_process(void *private_);
-static DECLARE_WORK(batch_work, batch_entropy_process, NULL);
-
-/* note: the size must be a power of 2 */
-static int __init batch_entropy_init(int size, struct entropy_store *r)
-{
- batch_entropy_pool = kmalloc(size*sizeof(struct sample), GFP_KERNEL);
- if (!batch_entropy_pool)
- return -1;
- batch_entropy_copy = kmalloc(size*sizeof(struct sample), GFP_KERNEL);
- if (!batch_entropy_copy) {
- kfree(batch_entropy_pool);
- return -1;
- }
- batch_head = batch_tail = 0;
- batch_work.data = r;
- batch_max = size;
- return 0;
-}
-
-/*
- * Changes to the entropy data is put into a queue rather than being added to
- * the entropy counts directly. This is presumably to avoid doing heavy
- * hashing calculations during an interrupt in add_timer_randomness().
- * Instead, the entropy is only added to the pool by keventd.
- */
-static void batch_entropy_store(u32 a, u32 b, int num)
-{
- int new;
- unsigned long flags;
-
- if (!batch_max)
- return;
-
- spin_lock_irqsave(&batch_lock, flags);
-
- batch_entropy_pool[batch_head].data[0] = a;
- batch_entropy_pool[batch_head].data[1] = b;
- batch_entropy_pool[batch_head].credit = num;
-
- if (((batch_head - batch_tail) & (batch_max - 1)) >= (batch_max / 2))
- schedule_delayed_work(&batch_work, 1);
-
- new = (batch_head + 1) & (batch_max - 1);
- if (new == batch_tail)
- DEBUG_ENT("batch entropy buffer full\n");
- else
- batch_head = new;
-
- spin_unlock_irqrestore(&batch_lock, flags);
-}
-
-/*
- * Flush out the accumulated entropy operations, adding entropy to the passed
- * store (normally random_state). If that store has enough entropy, alternate
- * between randomizing the data of the primary and secondary stores.
- */
-static void batch_entropy_process(void *private_)
-{
- struct entropy_store *r = (struct entropy_store *) private_, *p;
- int max_entropy = r->poolinfo.POOLBITS;
- unsigned head, tail;
-
- /* Mixing into the pool is expensive, so copy over the batch
- * data and release the batch lock. The pool is at least half
- * full, so don't worry too much about copying only the used
- * part.
- */
- spin_lock_irq(&batch_lock);
-
- memcpy(batch_entropy_copy, batch_entropy_pool,
- batch_max * sizeof(struct sample));
-
- head = batch_head;
- tail = batch_tail;
- batch_tail = batch_head;
-
- spin_unlock_irq(&batch_lock);
-
- p = r;
- while (head != tail) {
- if (r->entropy_count >= max_entropy) {
- r = (r == sec_random_state) ? random_state :
- sec_random_state;
- max_entropy = r->poolinfo.POOLBITS;
- }
- add_entropy_words(r, batch_entropy_copy[tail].data, 2);
- credit_entropy_store(r, batch_entropy_copy[tail].credit);
- tail = (tail + 1) & (batch_max - 1);
- }
- if (p->entropy_count >= random_read_wakeup_thresh)
- wake_up_interruptible(&random_read_wait);
-}
-
/*********************************************************************
*
* Entropy input management
@@ -786,7 +557,6 @@ struct timer_rand_state {
};
static struct timer_rand_state input_timer_state;
-static struct timer_rand_state extract_timer_state;
static struct timer_rand_state *irq_timer_state[NR_IRQS];
/*
@@ -801,26 +571,33 @@ static struct timer_rand_state *irq_timer_state[NR_IRQS];
*/
static void add_timer_randomness(struct timer_rand_state *state, unsigned num)
{
- cycles_t data;
- long delta, delta2, delta3, time;
- int entropy = 0;
+ struct {
+ cycles_t cycles;
+ long jiffies;
+ unsigned num;
+ } sample;
+ long delta, delta2, delta3;
preempt_disable();
/* if over the trickle threshold, use only 1 in 4096 samples */
- if (random_state->entropy_count > trickle_thresh &&
+ if (input_pool.entropy_count > trickle_thresh &&
(__get_cpu_var(trickle_count)++ & 0xfff))
goto out;
+ sample.jiffies = jiffies;
+ sample.cycles = get_cycles();
+ sample.num = num;
+ add_entropy_words(&input_pool, (u32 *)&sample, sizeof(sample)/4);
+
/*
* Calculate number of bits of randomness we probably added.
* We take into account the first, second and third-order deltas
* in order to make our estimate.
*/
- time = jiffies;
if (!state->dont_count_entropy) {
- delta = time - state->last_time;
- state->last_time = time;
+ delta = sample.jiffies - state->last_time;
+ state->last_time = sample.jiffies;
delta2 = delta - state->last_delta;
state->last_delta = delta;
@@ -844,23 +621,13 @@ static void add_timer_randomness(struct timer_rand_state *state, unsigned num)
* Round down by 1 bit on general principles,
* and limit entropy entimate to 12 bits.
*/
- delta >>= 1;
- delta &= (1 << 12) - 1;
-
- entropy = int_ln_12bits(delta);
+ credit_entropy_store(&input_pool,
+ min_t(int, fls(delta>>1), 11));
}
- /*
- * Use get_cycles() if implemented, otherwise fall back to
- * jiffies.
- */
- data = get_cycles();
- if (data)
- num ^= (u32)((data >> 31) >> 1);
- else
- data = time;
+ if(input_pool.entropy_count >= random_read_wakeup_thresh)
+ wake_up_interruptible(&random_read_wait);
- batch_entropy_store(num, data, entropy);
out:
preempt_enable();
}
@@ -902,391 +669,7 @@ void add_disk_randomness(struct gendisk *disk)
EXPORT_SYMBOL(add_disk_randomness);
-/******************************************************************
- *
- * Hash function definition
- *
- *******************************************************************/
-
-/*
- * This chunk of code defines a function
- * void HASH_TRANSFORM(__u32 digest[HASH_BUFFER_SIZE + HASH_EXTRA_SIZE],
- * __u32 const data[16])
- *
- * The function hashes the input data to produce a digest in the first
- * HASH_BUFFER_SIZE words of the digest[] array, and uses HASH_EXTRA_SIZE
- * more words for internal purposes. (This buffer is exported so the
- * caller can wipe it once rather than this code doing it each call,
- * and tacking it onto the end of the digest[] array is the quick and
- * dirty way of doing it.)
- *
- * It so happens that MD5 and SHA share most of the initial vector
- * used to initialize the digest[] array before the first call:
- * 1) 0x67452301
- * 2) 0xefcdab89
- * 3) 0x98badcfe
- * 4) 0x10325476
- * 5) 0xc3d2e1f0 (SHA only)
- *
- * For /dev/random purposes, the length of the data being hashed is
- * fixed in length, so appending a bit count in the usual way is not
- * cryptographically necessary.
- */
-
-#ifdef USE_SHA
-
-#define HASH_BUFFER_SIZE 5
-#define HASH_EXTRA_SIZE 80
-#define HASH_TRANSFORM SHATransform
-
-/* Various size/speed tradeoffs are available. Choose 0..3. */
-#define SHA_CODE_SIZE 0
-
-/*
- * SHA transform algorithm, taken from code written by Peter Gutmann,
- * and placed in the public domain.
- */
-
-/* The SHA f()-functions. */
-
-#define f1(x,y,z) (z ^ (x & (y ^ z))) /* Rounds 0-19: x ? y : z */
-#define f2(x,y,z) (x ^ y ^ z) /* Rounds 20-39: XOR */
-#define f3(x,y,z) ((x & y) + (z & (x ^ y))) /* Rounds 40-59: majority */
-#define f4(x,y,z) (x ^ y ^ z) /* Rounds 60-79: XOR */
-
-/* The SHA Mysterious Constants */
-
-#define K1 0x5A827999L /* Rounds 0-19: sqrt(2) * 2^30 */
-#define K2 0x6ED9EBA1L /* Rounds 20-39: sqrt(3) * 2^30 */
-#define K3 0x8F1BBCDCL /* Rounds 40-59: sqrt(5) * 2^30 */
-#define K4 0xCA62C1D6L /* Rounds 60-79: sqrt(10) * 2^30 */
-
-#define ROTL(n,X) (((X) << n ) | ((X) >> (32 - n)))
-
-#define subRound(a, b, c, d, e, f, k, data) \
- (e += ROTL(5, a) + f(b, c, d) + k + data, b = ROTL(30, b))
-
-static void SHATransform(__u32 digest[85], __u32 const data[16])
-{
- __u32 A, B, C, D, E; /* Local vars */
- __u32 TEMP;
- int i;
-#define W (digest + HASH_BUFFER_SIZE) /* Expanded data array */
-
- /*
- * Do the preliminary expansion of 16 to 80 words. Doing it
- * out-of-line line this is faster than doing it in-line on
- * register-starved machines like the x86, and not really any
- * slower on real processors.
- */
- memcpy(W, data, 16*sizeof(__u32));
- for (i = 0; i < 64; i++) {
- TEMP = W[i] ^ W[i+2] ^ W[i+8] ^ W[i+13];
- W[i+16] = ROTL(1, TEMP);
- }
-
- /* Set up first buffer and local data buffer */
- A = digest[ 0 ];
- B = digest[ 1 ];
- C = digest[ 2 ];
- D = digest[ 3 ];
- E = digest[ 4 ];
-
- /* Heavy mangling, in 4 sub-rounds of 20 iterations each. */
-#if SHA_CODE_SIZE == 0
- /*
- * Approximately 50% of the speed of the largest version, but
- * takes up 1/16 the space. Saves about 6k on an i386 kernel.
- */
- for (i = 0; i < 80; i++) {
- if (i < 40) {
- if (i < 20)
- TEMP = f1(B, C, D) + K1;
- else
- TEMP = f2(B, C, D) + K2;
- } else {
- if (i < 60)
- TEMP = f3(B, C, D) + K3;
- else
- TEMP = f4(B, C, D) + K4;
- }
- TEMP += ROTL(5, A) + E + W[i];
- E = D; D = C; C = ROTL(30, B); B = A; A = TEMP;
- }
-#elif SHA_CODE_SIZE == 1
- for (i = 0; i < 20; i++) {
- TEMP = f1(B, C, D) + K1 + ROTL(5, A) + E + W[i];
- E = D; D = C; C = ROTL(30, B); B = A; A = TEMP;
- }
- for (; i < 40; i++) {
- TEMP = f2(B, C, D) + K2 + ROTL(5, A) + E + W[i];
- E = D; D = C; C = ROTL(30, B); B = A; A = TEMP;
- }
- for (; i < 60; i++) {
- TEMP = f3(B, C, D) + K3 + ROTL(5, A) + E + W[i];
- E = D; D = C; C = ROTL(30, B); B = A; A = TEMP;
- }
- for (; i < 80; i++) {
- TEMP = f4(B, C, D) + K4 + ROTL(5, A) + E + W[i];
- E = D; D = C; C = ROTL(30, B); B = A; A = TEMP;
- }
-#elif SHA_CODE_SIZE == 2
- for (i = 0; i < 20; i += 5) {
- subRound(A, B, C, D, E, f1, K1, W[i ]);
- subRound(E, A, B, C, D, f1, K1, W[i+1]);
- subRound(D, E, A, B, C, f1, K1, W[i+2]);
- subRound(C, D, E, A, B, f1, K1, W[i+3]);
- subRound(B, C, D, E, A, f1, K1, W[i+4]);
- }
- for (; i < 40; i += 5) {
- subRound(A, B, C, D, E, f2, K2, W[i ]);
- subRound(E, A, B, C, D, f2, K2, W[i+1]);
- subRound(D, E, A, B, C, f2, K2, W[i+2]);
- subRound(C, D, E, A, B, f2, K2, W[i+3]);
- subRound(B, C, D, E, A, f2, K2, W[i+4]);
- }
- for (; i < 60; i += 5) {
- subRound(A, B, C, D, E, f3, K3, W[i ]);
- subRound(E, A, B, C, D, f3, K3, W[i+1]);
- subRound(D, E, A, B, C, f3, K3, W[i+2]);
- subRound(C, D, E, A, B, f3, K3, W[i+3]);
- subRound(B, C, D, E, A, f3, K3, W[i+4]);
- }
- for (; i < 80; i += 5) {
- subRound(A, B, C, D, E, f4, K4, W[i ]);
- subRound(E, A, B, C, D, f4, K4, W[i+1]);
- subRound(D, E, A, B, C, f4, K4, W[i+2]);
- subRound(C, D, E, A, B, f4, K4, W[i+3]);
- subRound(B, C, D, E, A, f4, K4, W[i+4]);
- }
-#elif SHA_CODE_SIZE == 3 /* Really large version */
- subRound(A, B, C, D, E, f1, K1, W[ 0]);
- subRound(E, A, B, C, D, f1, K1, W[ 1]);
- subRound(D, E, A, B, C, f1, K1, W[ 2]);
- subRound(C, D, E, A, B, f1, K1, W[ 3]);
- subRound(B, C, D, E, A, f1, K1, W[ 4]);
- subRound(A, B, C, D, E, f1, K1, W[ 5]);
- subRound(E, A, B, C, D, f1, K1, W[ 6]);
- subRound(D, E, A, B, C, f1, K1, W[ 7]);
- subRound(C, D, E, A, B, f1, K1, W[ 8]);
- subRound(B, C, D, E, A, f1, K1, W[ 9]);
- subRound(A, B, C, D, E, f1, K1, W[10]);
- subRound(E, A, B, C, D, f1, K1, W[11]);
- subRound(D, E, A, B, C, f1, K1, W[12]);
- subRound(C, D, E, A, B, f1, K1, W[13]);
- subRound(B, C, D, E, A, f1, K1, W[14]);
- subRound(A, B, C, D, E, f1, K1, W[15]);
- subRound(E, A, B, C, D, f1, K1, W[16]);
- subRound(D, E, A, B, C, f1, K1, W[17]);
- subRound(C, D, E, A, B, f1, K1, W[18]);
- subRound(B, C, D, E, A, f1, K1, W[19]);
-
- subRound(A, B, C, D, E, f2, K2, W[20]);
- subRound(E, A, B, C, D, f2, K2, W[21]);
- subRound(D, E, A, B, C, f2, K2, W[22]);
- subRound(C, D, E, A, B, f2, K2, W[23]);
- subRound(B, C, D, E, A, f2, K2, W[24]);
- subRound(A, B, C, D, E, f2, K2, W[25]);
- subRound(E, A, B, C, D, f2, K2, W[26]);
- subRound(D, E, A, B, C, f2, K2, W[27]);
- subRound(C, D, E, A, B, f2, K2, W[28]);
- subRound(B, C, D, E, A, f2, K2, W[29]);
- subRound(A, B, C, D, E, f2, K2, W[30]);
- subRound(E, A, B, C, D, f2, K2, W[31]);
- subRound(D, E, A, B, C, f2, K2, W[32]);
- subRound(C, D, E, A, B, f2, K2, W[33]);
- subRound(B, C, D, E, A, f2, K2, W[34]);
- subRound(A, B, C, D, E, f2, K2, W[35]);
- subRound(E, A, B, C, D, f2, K2, W[36]);
- subRound(D, E, A, B, C, f2, K2, W[37]);
- subRound(C, D, E, A, B, f2, K2, W[38]);
- subRound(B, C, D, E, A, f2, K2, W[39]);
-
- subRound(A, B, C, D, E, f3, K3, W[40]);
- subRound(E, A, B, C, D, f3, K3, W[41]);
- subRound(D, E, A, B, C, f3, K3, W[42]);
- subRound(C, D, E, A, B, f3, K3, W[43]);
- subRound(B, C, D, E, A, f3, K3, W[44]);
- subRound(A, B, C, D, E, f3, K3, W[45]);
- subRound(E, A, B, C, D, f3, K3, W[46]);
- subRound(D, E, A, B, C, f3, K3, W[47]);
- subRound(C, D, E, A, B, f3, K3, W[48]);
- subRound(B, C, D, E, A, f3, K3, W[49]);
- subRound(A, B, C, D, E, f3, K3, W[50]);
- subRound(E, A, B, C, D, f3, K3, W[51]);
- subRound(D, E, A, B, C, f3, K3, W[52]);
- subRound(C, D, E, A, B, f3, K3, W[53]);
- subRound(B, C, D, E, A, f3, K3, W[54]);
- subRound(A, B, C, D, E, f3, K3, W[55]);
- subRound(E, A, B, C, D, f3, K3, W[56]);
- subRound(D, E, A, B, C, f3, K3, W[57]);
- subRound(C, D, E, A, B, f3, K3, W[58]);
- subRound(B, C, D, E, A, f3, K3, W[59]);
-
- subRound(A, B, C, D, E, f4, K4, W[60]);
- subRound(E, A, B, C, D, f4, K4, W[61]);
- subRound(D, E, A, B, C, f4, K4, W[62]);
- subRound(C, D, E, A, B, f4, K4, W[63]);
- subRound(B, C, D, E, A, f4, K4, W[64]);
- subRound(A, B, C, D, E, f4, K4, W[65]);
- subRound(E, A, B, C, D, f4, K4, W[66]);
- subRound(D, E, A, B, C, f4, K4, W[67]);
- subRound(C, D, E, A, B, f4, K4, W[68]);
- subRound(B, C, D, E, A, f4, K4, W[69]);
- subRound(A, B, C, D, E, f4, K4, W[70]);
- subRound(E, A, B, C, D, f4, K4, W[71]);
- subRound(D, E, A, B, C, f4, K4, W[72]);
- subRound(C, D, E, A, B, f4, K4, W[73]);
- subRound(B, C, D, E, A, f4, K4, W[74]);
- subRound(A, B, C, D, E, f4, K4, W[75]);
- subRound(E, A, B, C, D, f4, K4, W[76]);
- subRound(D, E, A, B, C, f4, K4, W[77]);
- subRound(C, D, E, A, B, f4, K4, W[78]);
- subRound(B, C, D, E, A, f4, K4, W[79]);
-#else
-#error Illegal SHA_CODE_SIZE
-#endif
-
- /* Build message digest */
- digest[0] += A;
- digest[1] += B;
- digest[2] += C;
- digest[3] += D;
- digest[4] += E;
-
- /* W is wiped by the caller */
-#undef W
-}
-
-#undef ROTL
-#undef f1
-#undef f2
-#undef f3
-#undef f4
-#undef K1
-#undef K2
-#undef K3
-#undef K4
-#undef subRound
-
-#else /* !USE_SHA - Use MD5 */
-
-#define HASH_BUFFER_SIZE 4
-#define HASH_EXTRA_SIZE 0
-#define HASH_TRANSFORM MD5Transform
-
-/*
- * MD5 transform algorithm, taken from code written by Colin Plumb,
- * and put into the public domain
- */
-
-/* The four core functions - F1 is optimized somewhat */
-
-/* #define F1(x, y, z) (x & y | ~x & z) */
-#define F1(x, y, z) (z ^ (x & (y ^ z)))
-#define F2(x, y, z) F1(z, x, y)
-#define F3(x, y, z) (x ^ y ^ z)
-#define F4(x, y, z) (y ^ (x | ~z))
-
-/* This is the central step in the MD5 algorithm. */
-#define MD5STEP(f, w, x, y, z, data, s) \
- (w += f(x, y, z) + data, w = w << s | w >> (32 - s), w += x )
-
-/*
- * The core of the MD5 algorithm, this alters an existing MD5 hash to
- * reflect the addition of 16 longwords of new data. MD5Update blocks
- * the data and converts bytes into longwords for this routine.
- */
-static void MD5Transform(__u32 buf[HASH_BUFFER_SIZE], __u32 const in[16])
-{
- __u32 a, b, c, d;
-
- a = buf[0];
- b = buf[1];
- c = buf[2];
- d = buf[3];
-
- MD5STEP(F1, a, b, c, d, in[ 0]+0xd76aa478, 7);
- MD5STEP(F1, d, a, b, c, in[ 1]+0xe8c7b756, 12);
- MD5STEP(F1, c, d, a, b, in[ 2]+0x242070db, 17);
- MD5STEP(F1, b, c, d, a, in[ 3]+0xc1bdceee, 22);
- MD5STEP(F1, a, b, c, d, in[ 4]+0xf57c0faf, 7);
- MD5STEP(F1, d, a, b, c, in[ 5]+0x4787c62a, 12);
- MD5STEP(F1, c, d, a, b, in[ 6]+0xa8304613, 17);
- MD5STEP(F1, b, c, d, a, in[ 7]+0xfd469501, 22);
- MD5STEP(F1, a, b, c, d, in[ 8]+0x698098d8, 7);
- MD5STEP(F1, d, a, b, c, in[ 9]+0x8b44f7af, 12);
- MD5STEP(F1, c, d, a, b, in[10]+0xffff5bb1, 17);
- MD5STEP(F1, b, c, d, a, in[11]+0x895cd7be, 22);
- MD5STEP(F1, a, b, c, d, in[12]+0x6b901122, 7);
- MD5STEP(F1, d, a, b, c, in[13]+0xfd987193, 12);
- MD5STEP(F1, c, d, a, b, in[14]+0xa679438e, 17);
- MD5STEP(F1, b, c, d, a, in[15]+0x49b40821, 22);
-
- MD5STEP(F2, a, b, c, d, in[ 1]+0xf61e2562, 5);
- MD5STEP(F2, d, a, b, c, in[ 6]+0xc040b340, 9);
- MD5STEP(F2, c, d, a, b, in[11]+0x265e5a51, 14);
- MD5STEP(F2, b, c, d, a, in[ 0]+0xe9b6c7aa, 20);
- MD5STEP(F2, a, b, c, d, in[ 5]+0xd62f105d, 5);
- MD5STEP(F2, d, a, b, c, in[10]+0x02441453, 9);
- MD5STEP(F2, c, d, a, b, in[15]+0xd8a1e681, 14);
- MD5STEP(F2, b, c, d, a, in[ 4]+0xe7d3fbc8, 20);
- MD5STEP(F2, a, b, c, d, in[ 9]+0x21e1cde6, 5);
- MD5STEP(F2, d, a, b, c, in[14]+0xc33707d6, 9);
- MD5STEP(F2, c, d, a, b, in[ 3]+0xf4d50d87, 14);
- MD5STEP(F2, b, c, d, a, in[ 8]+0x455a14ed, 20);
- MD5STEP(F2, a, b, c, d, in[13]+0xa9e3e905, 5);
- MD5STEP(F2, d, a, b, c, in[ 2]+0xfcefa3f8, 9);
- MD5STEP(F2, c, d, a, b, in[ 7]+0x676f02d9, 14);
- MD5STEP(F2, b, c, d, a, in[12]+0x8d2a4c8a, 20);
-
- MD5STEP(F3, a, b, c, d, in[ 5]+0xfffa3942, 4);
- MD5STEP(F3, d, a, b, c, in[ 8]+0x8771f681, 11);
- MD5STEP(F3, c, d, a, b, in[11]+0x6d9d6122, 16);
- MD5STEP(F3, b, c, d, a, in[14]+0xfde5380c, 23);
- MD5STEP(F3, a, b, c, d, in[ 1]+0xa4beea44, 4);
- MD5STEP(F3, d, a, b, c, in[ 4]+0x4bdecfa9, 11);
- MD5STEP(F3, c, d, a, b, in[ 7]+0xf6bb4b60, 16);
- MD5STEP(F3, b, c, d, a, in[10]+0xbebfbc70, 23);
- MD5STEP(F3, a, b, c, d, in[13]+0x289b7ec6, 4);
- MD5STEP(F3, d, a, b, c, in[ 0]+0xeaa127fa, 11);
- MD5STEP(F3, c, d, a, b, in[ 3]+0xd4ef3085, 16);
- MD5STEP(F3, b, c, d, a, in[ 6]+0x04881d05, 23);
- MD5STEP(F3, a, b, c, d, in[ 9]+0xd9d4d039, 4);
- MD5STEP(F3, d, a, b, c, in[12]+0xe6db99e5, 11);
- MD5STEP(F3, c, d, a, b, in[15]+0x1fa27cf8, 16);
- MD5STEP(F3, b, c, d, a, in[ 2]+0xc4ac5665, 23);
-
- MD5STEP(F4, a, b, c, d, in[ 0]+0xf4292244, 6);
- MD5STEP(F4, d, a, b, c, in[ 7]+0x432aff97, 10);
- MD5STEP(F4, c, d, a, b, in[14]+0xab9423a7, 15);
- MD5STEP(F4, b, c, d, a, in[ 5]+0xfc93a039, 21);
- MD5STEP(F4, a, b, c, d, in[12]+0x655b59c3, 6);
- MD5STEP(F4, d, a, b, c, in[ 3]+0x8f0ccc92, 10);
- MD5STEP(F4, c, d, a, b, in[10]+0xffeff47d, 15);
- MD5STEP(F4, b, c, d, a, in[ 1]+0x85845dd1, 21);
- MD5STEP(F4, a, b, c, d, in[ 8]+0x6fa87e4f, 6);
- MD5STEP(F4, d, a, b, c, in[15]+0xfe2ce6e0, 10);
- MD5STEP(F4, c, d, a, b, in[ 6]+0xa3014314, 15);
- MD5STEP(F4, b, c, d, a, in[13]+0x4e0811a1, 21);
- MD5STEP(F4, a, b, c, d, in[ 4]+0xf7537e82, 6);
- MD5STEP(F4, d, a, b, c, in[11]+0xbd3af235, 10);
- MD5STEP(F4, c, d, a, b, in[ 2]+0x2ad7d2bb, 15);
- MD5STEP(F4, b, c, d, a, in[ 9]+0xeb86d391, 21);
-
- buf[0] += a;
- buf[1] += b;
- buf[2] += c;
- buf[3] += d;
-}
-
-#undef F1
-#undef F2
-#undef F3
-#undef F4
-#undef MD5STEP
-
-#endif /* !USE_SHA */
+#define EXTRACT_SIZE 10
/*********************************************************************
*
@@ -1294,157 +677,174 @@ static void MD5Transform(__u32 buf[HASH_BUFFER_SIZE], __u32 const in[16])
*
*********************************************************************/
-#define EXTRACT_ENTROPY_USER 1
-#define EXTRACT_ENTROPY_SECONDARY 2
-#define EXTRACT_ENTROPY_LIMIT 4
-#define TMP_BUF_SIZE (HASH_BUFFER_SIZE + HASH_EXTRA_SIZE)
-#define SEC_XFER_SIZE (TMP_BUF_SIZE*4)
-
static ssize_t extract_entropy(struct entropy_store *r, void * buf,
- size_t nbytes, int flags);
+ size_t nbytes, int min, int rsvd);
/*
* This utility inline function is responsible for transfering entropy
* from the primary pool to the secondary extraction pool. We make
* sure we pull enough for a 'catastrophic reseed'.
*/
-static inline void xfer_secondary_pool(struct entropy_store *r,
- size_t nbytes, __u32 *tmp)
+static void xfer_secondary_pool(struct entropy_store *r, size_t nbytes)
{
- if (r->entropy_count < nbytes * 8 &&
- r->entropy_count < r->poolinfo.POOLBITS) {
+ __u32 tmp[OUTPUT_POOL_WORDS];
+
+ if (r->pull && r->entropy_count < nbytes * 8 &&
+ r->entropy_count < r->poolinfo->POOLBITS) {
int bytes = max_t(int, random_read_wakeup_thresh / 8,
- min_t(int, nbytes, TMP_BUF_SIZE));
+ min_t(int, nbytes, sizeof(tmp)));
+ int rsvd = r->limit ? 0 : random_read_wakeup_thresh/4;
DEBUG_ENT("going to reseed %s with %d bits "
"(%d of %d requested)\n",
r->name, bytes * 8, nbytes * 8, r->entropy_count);
- bytes=extract_entropy(random_state, tmp, bytes,
- EXTRACT_ENTROPY_LIMIT);
+ bytes=extract_entropy(r->pull, tmp, bytes,
+ random_read_wakeup_thresh / 8, rsvd);
add_entropy_words(r, tmp, (bytes + 3) / 4);
credit_entropy_store(r, bytes*8);
}
}
/*
- * This function extracts randomness from the "entropy pool", and
- * returns it in a buffer. This function computes how many remaining
- * bits of entropy are left in the pool, but it does not restrict the
- * number of bytes that are actually obtained. If the EXTRACT_ENTROPY_USER
- * flag is given, then the buf pointer is assumed to be in user space.
+ * These functions extracts randomness from the "entropy pool", and
+ * returns it in a buffer.
*
- * If the EXTRACT_ENTROPY_SECONDARY flag is given, then we are actually
- * extracting entropy from the secondary pool, and can refill from the
- * primary pool if needed.
+ * The min parameter specifies the minimum amount we can pull before
+ * failing to avoid races that defeat catastrophic reseeding while the
+ * reserved parameter indicates how much entropy we must leave in the
+ * pool after each pull to avoid starving other readers.
*
* Note: extract_entropy() assumes that .poolwords is a multiple of 16 words.
*/
-static ssize_t extract_entropy(struct entropy_store *r, void * buf,
- size_t nbytes, int flags)
-{
- ssize_t ret, i;
- __u32 tmp[TMP_BUF_SIZE], data[16];
- __u32 x;
- unsigned long cpuflags;
- /* Redundant, but just in case... */
- if (r->entropy_count > r->poolinfo.POOLBITS)
- r->entropy_count = r->poolinfo.POOLBITS;
+static size_t account(struct entropy_store *r, size_t nbytes, int min,
+ int reserved)
+{
+ unsigned long flags;
- if (flags & EXTRACT_ENTROPY_SECONDARY)
- xfer_secondary_pool(r, nbytes, tmp);
+ BUG_ON(r->entropy_count > r->poolinfo->POOLBITS);
/* Hold lock while accounting */
- spin_lock_irqsave(&r->lock, cpuflags);
+ spin_lock_irqsave(&r->lock, flags);
DEBUG_ENT("trying to extract %d bits from %s\n",
nbytes * 8, r->name);
- if (flags & EXTRACT_ENTROPY_LIMIT && nbytes >= r->entropy_count / 8)
- nbytes = r->entropy_count / 8;
+ /* Can we pull enough? */
+ if (r->entropy_count / 8 < min + reserved) {
+ nbytes = 0;
+ } else {
+ /* If limited, never pull more than available */
+ if (r->limit && nbytes + reserved >= r->entropy_count / 8)
+ nbytes = r->entropy_count/8 - reserved;
- if (r->entropy_count / 8 >= nbytes)
- r->entropy_count -= nbytes*8;
- else
- r->entropy_count = 0;
+ if(r->entropy_count / 8 >= nbytes + reserved)
+ r->entropy_count -= nbytes*8;
+ else
+ r->entropy_count = reserved;
- if (r->entropy_count < random_write_wakeup_thresh)
- wake_up_interruptible(&random_write_wait);
+ if (r->entropy_count < random_write_wakeup_thresh)
+ wake_up_interruptible(&random_write_wait);
+ }
DEBUG_ENT("debiting %d entropy credits from %s%s\n",
- nbytes * 8, r->name,
- flags & EXTRACT_ENTROPY_LIMIT ? "" : " (unlimited)");
+ nbytes * 8, r->name, r->limit ? "" : " (unlimited)");
+
+ spin_unlock_irqrestore(&r->lock, flags);
+
+ return nbytes;
+}
- spin_unlock_irqrestore(&r->lock, cpuflags);
+static void extract_buf(struct entropy_store *r, __u8 *out)
+{
+ int i, x;
+ __u32 data[16], buf[5 + SHA_WORKSPACE_WORDS];
+
+ sha_init(buf);
+ /*
+ * As we hash the pool, we mix intermediate values of
+ * the hash back into the pool. This eliminates
+ * backtracking attacks (where the attacker knows
+ * the state of the pool plus the current outputs, and
+ * attempts to find previous ouputs), unless the hash
+ * function can be inverted.
+ */
+ for (i = 0, x = 0; i < r->poolinfo->poolwords; i += 16, x+=2) {
+ sha_transform(buf, (__u8 *)r->pool+i, buf + 5);
+ add_entropy_words(r, &buf[x % 5], 1);
+ }
+
+ /*
+ * To avoid duplicates, we atomically extract a
+ * portion of the pool while mixing, and hash one
+ * final time.
+ */
+ __add_entropy_words(r, &buf[x % 5], 1, data);
+ sha_transform(buf, (__u8 *)data, buf + 5);
+
+ /*
+ * In case the hash function has some recognizable
+ * output pattern, we fold it in half.
+ */
+
+ buf[0] ^= buf[3];
+ buf[1] ^= buf[4];
+ buf[0] ^= rol32(buf[3], 16);
+ memcpy(out, buf, EXTRACT_SIZE);
+ memset(buf, 0, sizeof(buf));
+}
+
+static ssize_t extract_entropy(struct entropy_store *r, void * buf,
+ size_t nbytes, int min, int reserved)
+{
+ ssize_t ret = 0, i;
+ __u8 tmp[EXTRACT_SIZE];
+
+ xfer_secondary_pool(r, nbytes);
+ nbytes = account(r, nbytes, min, reserved);
- ret = 0;
while (nbytes) {
- /*
- * Check if we need to break out or reschedule....
- */
- if ((flags & EXTRACT_ENTROPY_USER) && need_resched()) {
+ extract_buf(r, tmp);
+ i = min_t(int, nbytes, EXTRACT_SIZE);
+ memcpy(buf, tmp, i);
+ nbytes -= i;
+ buf += i;
+ ret += i;
+ }
+
+ /* Wipe data just returned from memory */
+ memset(tmp, 0, sizeof(tmp));
+
+ return ret;
+}
+
+static ssize_t extract_entropy_user(struct entropy_store *r, void __user *buf,
+ size_t nbytes)
+{
+ ssize_t ret = 0, i;
+ __u8 tmp[EXTRACT_SIZE];
+
+ xfer_secondary_pool(r, nbytes);
+ nbytes = account(r, nbytes, 0, 0);
+
+ while (nbytes) {
+ if (need_resched()) {
if (signal_pending(current)) {
if (ret == 0)
ret = -ERESTARTSYS;
break;
}
-
schedule();
}
- /* Hash the pool to get the output */
- tmp[0] = 0x67452301;
- tmp[1] = 0xefcdab89;
- tmp[2] = 0x98badcfe;
- tmp[3] = 0x10325476;
-#ifdef USE_SHA
- tmp[4] = 0xc3d2e1f0;
-#endif
- /*
- * As we hash the pool, we mix intermediate values of
- * the hash back into the pool. This eliminates
- * backtracking attacks (where the attacker knows
- * the state of the pool plus the current outputs, and
- * attempts to find previous ouputs), unless the hash
- * function can be inverted.
- */
- for (i = 0, x = 0; i < r->poolinfo.poolwords; i += 16, x+=2) {
- HASH_TRANSFORM(tmp, r->pool+i);
- add_entropy_words(r, &tmp[x%HASH_BUFFER_SIZE], 1);
+ extract_buf(r, tmp);
+ i = min_t(int, nbytes, EXTRACT_SIZE);
+ if (copy_to_user(buf, tmp, i)) {
+ ret = -EFAULT;
+ break;
}
- /*
- * To avoid duplicates, we atomically extract a
- * portion of the pool while mixing, and hash one
- * final time.
- */
- __add_entropy_words(r, &tmp[x%HASH_BUFFER_SIZE], 1, data);
- HASH_TRANSFORM(tmp, data);
-
- /*
- * In case the hash function has some recognizable
- * output pattern, we fold it in half.
- */
- for (i = 0; i < HASH_BUFFER_SIZE/2; i++)
- tmp[i] ^= tmp[i + (HASH_BUFFER_SIZE+1)/2];
-#if HASH_BUFFER_SIZE & 1 /* There's a middle word to deal with */
- x = tmp[HASH_BUFFER_SIZE/2];
- x ^= (x >> 16); /* Fold it in half */
- ((__u16 *)tmp)[HASH_BUFFER_SIZE-1] = (__u16)x;
-#endif
-
- /* Copy data to destination buffer */
- i = min(nbytes, HASH_BUFFER_SIZE*sizeof(__u32)/2);
- if (flags & EXTRACT_ENTROPY_USER) {
- i -= copy_to_user(buf, (__u8 const *)tmp, i);
- if (!i) {
- ret = -EFAULT;
- break;
- }
- } else
- memcpy(buf, (__u8 const *)tmp, i);
-
nbytes -= i;
buf += i;
ret += i;
@@ -1463,91 +863,41 @@ static ssize_t extract_entropy(struct entropy_store *r, void * buf,
*/
void get_random_bytes(void *buf, int nbytes)
{
- struct entropy_store *r = urandom_state;
- int flags = EXTRACT_ENTROPY_SECONDARY;
-
- if (!r)
- r = sec_random_state;
- if (!r) {
- r = random_state;
- flags = 0;
- }
- if (!r) {
- printk(KERN_NOTICE "get_random_bytes called before "
- "random driver initialization\n");
- return;
- }
- extract_entropy(r, (char *) buf, nbytes, flags);
+ extract_entropy(&nonblocking_pool, buf, nbytes, 0, 0);
}
EXPORT_SYMBOL(get_random_bytes);
-/*********************************************************************
- *
- * Functions to interface with Linux
- *
- *********************************************************************/
-
/*
- * Initialize the random pool with standard stuff.
+ * init_std_data - initialize pool with system data
+ *
+ * @r: pool to initialize
*
- * NOTE: This is an OS-dependent function.
+ * This function clears the pool's entropy count and mixes some system
+ * data into the pool to prepare it for use. The pool is not cleared
+ * as that can only decrease the entropy in the pool.
*/
static void init_std_data(struct entropy_store *r)
{
struct timeval tv;
- __u32 words[2];
- char *p;
- int i;
+ unsigned long flags;
- do_gettimeofday(&tv);
- words[0] = tv.tv_sec;
- words[1] = tv.tv_usec;
- add_entropy_words(r, words, 2);
+ spin_lock_irqsave(&r->lock, flags);
+ r->entropy_count = 0;
+ spin_unlock_irqrestore(&r->lock, flags);
- /*
- * This doesn't lock system.utsname. However, we are generating
- * entropy so a race with a name set here is fine.
- */
- p = (char *) &system_utsname;
- for (i = sizeof(system_utsname) / sizeof(words); i; i--) {
- memcpy(words, p, sizeof(words));
- add_entropy_words(r, words, sizeof(words)/4);
- p += sizeof(words);
- }
+ do_gettimeofday(&tv);
+ add_entropy_words(r, (__u32 *)&tv, sizeof(tv)/4);
+ add_entropy_words(r, (__u32 *)&system_utsname,
+ sizeof(system_utsname)/4);
}
static int __init rand_initialize(void)
{
- int i;
-
- if (create_entropy_store(DEFAULT_POOL_SIZE, "primary", &random_state))
- goto err;
- if (batch_entropy_init(BATCH_ENTROPY_SIZE, random_state))
- goto err;
- if (create_entropy_store(SECONDARY_POOL_SIZE, "secondary",
- &sec_random_state))
- goto err;
- if (create_entropy_store(SECONDARY_POOL_SIZE, "urandom",
- &urandom_state))
- goto err;
- clear_entropy_store(random_state);
- clear_entropy_store(sec_random_state);
- clear_entropy_store(urandom_state);
- init_std_data(random_state);
- init_std_data(sec_random_state);
- init_std_data(urandom_state);
-#ifdef CONFIG_SYSCTL
- sysctl_init_random(random_state);
-#endif
- for (i = 0; i < NR_IRQS; i++)
- irq_timer_state[i] = NULL;
- memset(&input_timer_state, 0, sizeof(struct timer_rand_state));
- memset(&extract_timer_state, 0, sizeof(struct timer_rand_state));
- extract_timer_state.dont_count_entropy = 1;
+ init_std_data(&input_pool);
+ init_std_data(&blocking_pool);
+ init_std_data(&nonblocking_pool);
return 0;
-err:
- return -1;
}
module_init(rand_initialize);
@@ -1587,7 +937,6 @@ void rand_initialize_disk(struct gendisk *disk)
static ssize_t
random_read(struct file * file, char __user * buf, size_t nbytes, loff_t *ppos)
{
- DECLARE_WAITQUEUE(wait, current);
ssize_t n, retval = 0, count = 0;
if (nbytes == 0)
@@ -1600,10 +949,7 @@ random_read(struct file * file, char __user * buf, size_t nbytes, loff_t *ppos)
DEBUG_ENT("reading %d bits\n", n*8);
- n = extract_entropy(sec_random_state, buf, n,
- EXTRACT_ENTROPY_USER |
- EXTRACT_ENTROPY_LIMIT |
- EXTRACT_ENTROPY_SECONDARY);
+ n = extract_entropy_user(&blocking_pool, buf, n);
DEBUG_ENT("read got %d bits (%d still needed)\n",
n*8, (nbytes-n)*8);
@@ -1613,20 +959,20 @@ random_read(struct file * file, char __user * buf, size_t nbytes, loff_t *ppos)
retval = -EAGAIN;
break;
}
+
+ DEBUG_ENT("sleeping?\n");
+
+ wait_event_interruptible(random_read_wait,
+ input_pool.entropy_count >=
+ random_read_wakeup_thresh);
+
+ DEBUG_ENT("awake\n");
+
if (signal_pending(current)) {
retval = -ERESTARTSYS;
break;
}
- set_current_state(TASK_INTERRUPTIBLE);
- add_wait_queue(&random_read_wait, &wait);
-
- if (sec_random_state->entropy_count / 8 == 0)
- schedule();
-
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&random_read_wait, &wait);
-
continue;
}
@@ -1654,15 +1000,7 @@ static ssize_t
urandom_read(struct file * file, char __user * buf,
size_t nbytes, loff_t *ppos)
{
- int flags = EXTRACT_ENTROPY_USER;
- unsigned long cpuflags;
-
- spin_lock_irqsave(&random_state->lock, cpuflags);
- if (random_state->entropy_count > random_state->poolinfo.POOLBITS)
- flags |= EXTRACT_ENTROPY_SECONDARY;
- spin_unlock_irqrestore(&random_state->lock, cpuflags);
-
- return extract_entropy(urandom_state, buf, nbytes, flags);
+ return extract_entropy_user(&nonblocking_pool, buf, nbytes);
}
static unsigned int
@@ -1673,9 +1011,9 @@ random_poll(struct file *file, poll_table * wait)
poll_wait(file, &random_read_wait, wait);
poll_wait(file, &random_write_wait, wait);
mask = 0;
- if (random_state->entropy_count >= random_read_wakeup_thresh)
+ if (input_pool.entropy_count >= random_read_wakeup_thresh)
mask |= POLLIN | POLLRDNORM;
- if (random_state->entropy_count < random_write_wakeup_thresh)
+ if (input_pool.entropy_count < random_write_wakeup_thresh)
mask |= POLLOUT | POLLWRNORM;
return mask;
}
@@ -1701,7 +1039,7 @@ random_write(struct file * file, const char __user * buffer,
c -= bytes;
p += bytes;
- add_entropy_words(random_state, buf, (bytes + 3) / 4);
+ add_entropy_words(&input_pool, buf, (bytes + 3) / 4);
}
if (p == buffer) {
return (ssize_t)ret;
@@ -1723,7 +1061,7 @@ random_ioctl(struct inode * inode, struct file * file,
switch (cmd) {
case RNDGETENTCNT:
- ent_count = random_state->entropy_count;
+ ent_count = input_pool.entropy_count;
if (put_user(ent_count, p))
return -EFAULT;
return 0;
@@ -1732,12 +1070,12 @@ random_ioctl(struct inode * inode, struct file * file,
return -EPERM;
if (get_user(ent_count, p))
return -EFAULT;
- credit_entropy_store(random_state, ent_count);
+ credit_entropy_store(&input_pool, ent_count);
/*
* Wake up waiting processes if we have enough
* entropy.
*/
- if (random_state->entropy_count >= random_read_wakeup_thresh)
+ if (input_pool.entropy_count >= random_read_wakeup_thresh)
wake_up_interruptible(&random_read_wait);
return 0;
case RNDADDENTROPY:
@@ -1753,25 +1091,22 @@ random_ioctl(struct inode * inode, struct file * file,
size, &file->f_pos);
if (retval < 0)
return retval;
- credit_entropy_store(random_state, ent_count);
+ credit_entropy_store(&input_pool, ent_count);
/*
* Wake up waiting processes if we have enough
* entropy.
*/
- if (random_state->entropy_count >= random_read_wakeup_thresh)
+ if (input_pool.entropy_count >= random_read_wakeup_thresh)
wake_up_interruptible(&random_read_wait);
return 0;
case RNDZAPENTCNT:
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
- random_state->entropy_count = 0;
- return 0;
case RNDCLEARPOOL:
- /* Clear the entropy pool and associated counters. */
+ /* Clear the entropy pool counters. */
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
- clear_entropy_store(random_state);
- init_std_data(random_state);
+ init_std_data(&input_pool);
+ init_std_data(&blocking_pool);
+ init_std_data(&nonblocking_pool);
return 0;
default:
return -EINVAL;
@@ -1822,8 +1157,9 @@ EXPORT_SYMBOL(generate_random_uuid);
#include <linux/sysctl.h>
-static int min_read_thresh, max_read_thresh;
-static int min_write_thresh, max_write_thresh;
+static int min_read_thresh = 8, min_write_thresh;
+static int max_read_thresh = INPUT_POOL_WORDS * 32;
+static int max_write_thresh = INPUT_POOL_WORDS * 32;
static char sysctl_bootid[16];
/*
@@ -1891,7 +1227,7 @@ static int uuid_strategy(ctl_table *table, int __user *name, int nlen,
return 1;
}
-static int sysctl_poolsize = DEFAULT_POOL_SIZE;
+static int sysctl_poolsize = INPUT_POOL_WORDS * 32;
ctl_table random_table[] = {
{
.ctl_name = RANDOM_POOLSIZE,
@@ -1907,6 +1243,7 @@ ctl_table random_table[] = {
.maxlen = sizeof(int),
.mode = 0444,
.proc_handler = &proc_dointvec,
+ .data = &input_pool.entropy_count,
},
{
.ctl_name = RANDOM_READ_THRESH,
@@ -1949,14 +1286,6 @@ ctl_table random_table[] = {
},
{ .ctl_name = 0 }
};
-
-static void sysctl_init_random(struct entropy_store *random_state)
-{
- min_read_thresh = 8;
- min_write_thresh = 0;
- max_read_thresh = max_write_thresh = random_state->poolinfo.POOLBITS;
- random_table[1].data = &random_state->entropy_count;
-}
#endif /* CONFIG_SYSCTL */
/********************************************************************
@@ -1965,7 +1294,6 @@ static void sysctl_init_random(struct entropy_store *random_state)
*
********************************************************************/
-#ifdef CONFIG_INET
/*
* TCP initial sequence number picking. This uses the random number
* generator to pick an initial secret value. This value is hashed
@@ -1996,47 +1324,6 @@ static void sysctl_init_random(struct entropy_store *random_state)
#define K2 013240474631UL
#define K3 015666365641UL
-/*
- * Basic cut-down MD4 transform. Returns only 32 bits of result.
- */
-static __u32 halfMD4Transform (__u32 const buf[4], __u32 const in[8])
-{
- __u32 a = buf[0], b = buf[1], c = buf[2], d = buf[3];
-
- /* Round 1 */
- ROUND(F, a, b, c, d, in[0] + K1, 3);
- ROUND(F, d, a, b, c, in[1] + K1, 7);
- ROUND(F, c, d, a, b, in[2] + K1, 11);
- ROUND(F, b, c, d, a, in[3] + K1, 19);
- ROUND(F, a, b, c, d, in[4] + K1, 3);
- ROUND(F, d, a, b, c, in[5] + K1, 7);
- ROUND(F, c, d, a, b, in[6] + K1, 11);
- ROUND(F, b, c, d, a, in[7] + K1, 19);
-
- /* Round 2 */
- ROUND(G, a, b, c, d, in[1] + K2, 3);
- ROUND(G, d, a, b, c, in[3] + K2, 5);
- ROUND(G, c, d, a, b, in[5] + K2, 9);
- ROUND(G, b, c, d, a, in[7] + K2, 13);
- ROUND(G, a, b, c, d, in[0] + K2, 3);
- ROUND(G, d, a, b, c, in[2] + K2, 5);
- ROUND(G, c, d, a, b, in[4] + K2, 9);
- ROUND(G, b, c, d, a, in[6] + K2, 13);
-
- /* Round 3 */
- ROUND(H, a, b, c, d, in[3] + K3, 3);
- ROUND(H, d, a, b, c, in[7] + K3, 9);
- ROUND(H, c, d, a, b, in[2] + K3, 11);
- ROUND(H, b, c, d, a, in[6] + K3, 15);
- ROUND(H, a, b, c, d, in[1] + K3, 3);
- ROUND(H, d, a, b, c, in[5] + K3, 9);
- ROUND(H, c, d, a, b, in[0] + K3, 11);
- ROUND(H, b, c, d, a, in[4] + K3, 15);
-
- return buf[1] + b; /* "most hashed" word */
- /* Alternative: return sum of all words? */
-}
-
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
static __u32 twothirdsMD4Transform (__u32 const buf[4], __u32 const in[12])
@@ -2202,6 +1489,31 @@ __u32 secure_tcpv6_sequence_number(__u32 *saddr, __u32 *daddr,
EXPORT_SYMBOL(secure_tcpv6_sequence_number);
#endif
+/* The code below is shamelessly stolen from secure_tcp_sequence_number().
+ * All blames to Andrey V. Savochkin <saw@msu.ru>.
+ */
+__u32 secure_ip_id(__u32 daddr)
+{
+ struct keydata *keyptr;
+ __u32 hash[4];
+
+ keyptr = get_keyptr();
+
+ /*
+ * Pick a unique starting offset for each IP destination.
+ * The dest ip address is placed in the starting vector,
+ * which is then hashed with random data.
+ */
+ hash[0] = daddr;
+ hash[1] = keyptr->secret[9];
+ hash[2] = keyptr->secret[10];
+ hash[3] = keyptr->secret[11];
+
+ return half_md4_transform(hash, keyptr->secret);
+}
+
+#ifdef CONFIG_INET
+
__u32 secure_tcp_sequence_number(__u32 saddr, __u32 daddr,
__u16 sport, __u16 dport)
{
@@ -2221,7 +1533,7 @@ __u32 secure_tcp_sequence_number(__u32 saddr, __u32 daddr,
hash[2]=(sport << 16) + dport;
hash[3]=keyptr->secret[11];
- seq = halfMD4Transform(hash, keyptr->secret) & HASH_MASK;
+ seq = half_md4_transform(hash, keyptr->secret) & HASH_MASK;
seq += keyptr->count;
/*
* As close as possible to RFC 793, which
@@ -2242,28 +1554,7 @@ __u32 secure_tcp_sequence_number(__u32 saddr, __u32 daddr,
EXPORT_SYMBOL(secure_tcp_sequence_number);
-/* The code below is shamelessly stolen from secure_tcp_sequence_number().
- * All blames to Andrey V. Savochkin <saw@msu.ru>.
- */
-__u32 secure_ip_id(__u32 daddr)
-{
- struct keydata *keyptr;
- __u32 hash[4];
- keyptr = get_keyptr();
-
- /*
- * Pick a unique starting offset for each IP destination.
- * The dest ip address is placed in the starting vector,
- * which is then hashed with random data.
- */
- hash[0] = daddr;
- hash[1] = keyptr->secret[9];
- hash[2] = keyptr->secret[10];
- hash[3] = keyptr->secret[11];
-
- return halfMD4Transform(hash, keyptr->secret);
-}
/* Generate secure starting point for ephemeral TCP port search */
u32 secure_tcp_port_ephemeral(__u32 saddr, __u32 daddr, __u16 dport)
@@ -2280,106 +1571,59 @@ u32 secure_tcp_port_ephemeral(__u32 saddr, __u32 daddr, __u16 dport)
hash[2] = dport ^ keyptr->secret[10];
hash[3] = keyptr->secret[11];
- return halfMD4Transform(hash, keyptr->secret);
+ return half_md4_transform(hash, keyptr->secret);
}
-#ifdef CONFIG_SYN_COOKIES
-/*
- * Secure SYN cookie computation. This is the algorithm worked out by
- * Dan Bernstein and Eric Schenk.
- *
- * For linux I implement the 1 minute counter by looking at the jiffies clock.
- * The count is passed in as a parameter, so this code doesn't much care.
- */
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+u32 secure_tcpv6_port_ephemeral(const __u32 *saddr, const __u32 *daddr, __u16 dport)
+{
+ struct keydata *keyptr = get_keyptr();
+ u32 hash[12];
-#define COOKIEBITS 24 /* Upper bits store count */
-#define COOKIEMASK (((__u32)1 << COOKIEBITS) - 1)
+ memcpy(hash, saddr, 16);
+ hash[4] = dport;
+ memcpy(&hash[5],keyptr->secret,sizeof(__u32) * 7);
-static int syncookie_init;
-static __u32 syncookie_secret[2][16-3+HASH_BUFFER_SIZE];
+ return twothirdsMD4Transform(daddr, hash);
+}
+EXPORT_SYMBOL(secure_tcpv6_port_ephemeral);
+#endif
-__u32 secure_tcp_syn_cookie(__u32 saddr, __u32 daddr, __u16 sport,
- __u16 dport, __u32 sseq, __u32 count, __u32 data)
-{
- __u32 tmp[16 + HASH_BUFFER_SIZE + HASH_EXTRA_SIZE];
- __u32 seq;
+#endif /* CONFIG_INET */
- /*
- * Pick two random secrets the first time we need a cookie.
- */
- if (syncookie_init == 0) {
- get_random_bytes(syncookie_secret, sizeof(syncookie_secret));
- syncookie_init = 1;
- }
+/*
+ * Get a random word for internal kernel use only. Similar to urandom but
+ * with the goal of minimal entropy pool depletion. As a result, the random
+ * value is not cryptographically secure but for several uses the cost of
+ * depleting entropy is too high
+ */
+unsigned int get_random_int(void)
+{
/*
- * Compute the secure sequence number.
- * The output should be:
- * HASH(sec1,saddr,sport,daddr,dport,sec1) + sseq + (count * 2^24)
- * + (HASH(sec2,saddr,sport,daddr,dport,count,sec2) % 2^24).
- * Where sseq is their sequence number and count increases every
- * minute by 1.
- * As an extra hack, we add a small "data" value that encodes the
- * MSS into the second hash value.
+ * Use IP's RNG. It suits our purpose perfectly: it re-keys itself
+ * every second, from the entropy pool (and thus creates a limited
+ * drain on it), and uses halfMD4Transform within the second. We
+ * also mix it with jiffies and the PID:
*/
-
- memcpy(tmp + 3, syncookie_secret[0], sizeof(syncookie_secret[0]));
- tmp[0]=saddr;
- tmp[1]=daddr;
- tmp[2]=(sport << 16) + dport;
- HASH_TRANSFORM(tmp+16, tmp);
- seq = tmp[17] + sseq + (count << COOKIEBITS);
-
- memcpy(tmp + 3, syncookie_secret[1], sizeof(syncookie_secret[1]));
- tmp[0]=saddr;
- tmp[1]=daddr;
- tmp[2]=(sport << 16) + dport;
- tmp[3] = count; /* minute counter */
- HASH_TRANSFORM(tmp + 16, tmp);
-
- /* Add in the second hash and the data */
- return seq + ((tmp[17] + data) & COOKIEMASK);
+ return secure_ip_id(current->pid + jiffies);
}
/*
- * This retrieves the small "data" value from the syncookie.
- * If the syncookie is bad, the data returned will be out of
- * range. This must be checked by the caller.
+ * randomize_range() returns a start address such that
*
- * The count value used to generate the cookie must be within
- * "maxdiff" if the current (passed-in) "count". The return value
- * is (__u32)-1 if this test fails.
+ * [...... <range> .....]
+ * start end
+ *
+ * a <range> with size "len" starting at the return value is inside in the
+ * area defined by [start, end], but is otherwise randomized.
*/
-__u32 check_tcp_syn_cookie(__u32 cookie, __u32 saddr, __u32 daddr, __u16 sport,
- __u16 dport, __u32 sseq, __u32 count, __u32 maxdiff)
+unsigned long
+randomize_range(unsigned long start, unsigned long end, unsigned long len)
{
- __u32 tmp[16 + HASH_BUFFER_SIZE + HASH_EXTRA_SIZE];
- __u32 diff;
-
- if (syncookie_init == 0)
- return (__u32)-1; /* Well, duh! */
-
- /* Strip away the layers from the cookie */
- memcpy(tmp + 3, syncookie_secret[0], sizeof(syncookie_secret[0]));
- tmp[0]=saddr;
- tmp[1]=daddr;
- tmp[2]=(sport << 16) + dport;
- HASH_TRANSFORM(tmp + 16, tmp);
- cookie -= tmp[17] + sseq;
- /* Cookie is now reduced to (count * 2^24) ^ (hash % 2^24) */
-
- diff = (count - (cookie >> COOKIEBITS)) & ((__u32)-1 >> COOKIEBITS);
- if (diff >= maxdiff)
- return (__u32)-1;
-
- memcpy(tmp+3, syncookie_secret[1], sizeof(syncookie_secret[1]));
- tmp[0] = saddr;
- tmp[1] = daddr;
- tmp[2] = (sport << 16) + dport;
- tmp[3] = count - diff; /* minute counter */
- HASH_TRANSFORM(tmp + 16, tmp);
-
- return (cookie - tmp[17]) & COOKIEMASK; /* Leaving the data behind */
+ unsigned long range = end - len - start;
+
+ if (end <= start + len)
+ return 0;
+ return PAGE_ALIGN(get_random_int() % range + start);
}
-#endif
-#endif /* CONFIG_INET */
diff --git a/drivers/char/rio/rio_linux.c b/drivers/char/rio/rio_linux.c
index 75f0b826b65be..a91ae271cf0ad 100644
--- a/drivers/char/rio/rio_linux.c
+++ b/drivers/char/rio/rio_linux.c
@@ -681,8 +681,9 @@ static int rio_ioctl (struct tty_struct * tty, struct file * filp,
}
break;
case TIOCGSERIAL:
- if ((rc = verify_area(VERIFY_WRITE, (void *) arg,
- sizeof(struct serial_struct))) == 0)
+ 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:
@@ -711,8 +712,9 @@ static int rio_ioctl (struct tty_struct * tty, struct file * filp,
}
break;
case TIOCSSERIAL:
- if ((rc = verify_area(VERIFY_READ, (void *) arg,
- sizeof(struct serial_struct))) == 0)
+ 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
@@ -722,8 +724,10 @@ static int rio_ioctl (struct tty_struct * tty, struct file * filp,
* #if 0 disablement predates this comment.
*/
case TIOCMGET:
- if ((rc = verify_area(VERIFY_WRITE, (void *) arg,
- sizeof(unsigned int))) == 0) {
+ rc = -EFAULT;
+ if (access_ok(VERIFY_WRITE, (void *) arg,
+ sizeof(unsigned int))) {
+ rc = 0;
ival = rio_getsignals(port);
put_user(ival, (unsigned int *) arg);
}
diff --git a/drivers/char/rio/riocmd.c b/drivers/char/rio/riocmd.c
index 8f70185f192af..533085ec6f1bb 100644
--- a/drivers/char/rio/riocmd.c
+++ b/drivers/char/rio/riocmd.c
@@ -84,9 +84,7 @@ static struct IdentifyRta IdRta;
static struct KillNeighbour KillUnit;
int
-RIOFoadRta(HostP, MapP)
-struct Host * HostP;
-struct Map * MapP;
+RIOFoadRta(struct Host *HostP, struct Map *MapP)
{
struct CmdBlk *CmdBlkP;
@@ -117,9 +115,7 @@ struct Map * MapP;
}
int
-RIOZombieRta(HostP, MapP)
-struct Host * HostP;
-struct Map * MapP;
+RIOZombieRta(struct Host *HostP, struct Map *MapP)
{
struct CmdBlk *CmdBlkP;
@@ -150,10 +146,8 @@ struct Map * MapP;
}
int
-RIOCommandRta(p, RtaUnique, func)
-struct rio_info * p;
-uint RtaUnique;
-int (* func)( struct Host *HostP, struct Map *MapP );
+RIOCommandRta(struct rio_info *p, uint RtaUnique,
+ int (* func)(struct Host *HostP, struct Map *MapP))
{
uint Host;
@@ -195,9 +189,7 @@ int (* func)( struct Host *HostP, struct Map *MapP );
int
-RIOIdentifyRta(p, arg)
-struct rio_info * p;
-caddr_t arg;
+RIOIdentifyRta(struct rio_info *p, caddr_t arg)
{
uint Host;
@@ -263,9 +255,7 @@ caddr_t arg;
int
-RIOKillNeighbour(p, arg)
-struct rio_info * p;
-caddr_t arg;
+RIOKillNeighbour(struct rio_info *p, caddr_t arg)
{
uint Host;
uint ID;
@@ -329,10 +319,7 @@ caddr_t arg;
}
int
-RIOSuspendBootRta(HostP, ID, Link)
-struct Host *HostP;
-int ID;
-int Link;
+RIOSuspendBootRta(struct Host *HostP, int ID, int Link)
{
struct CmdBlk *CmdBlkP;
@@ -363,8 +350,7 @@ int Link;
}
int
-RIOFoadWakeup(p)
-struct rio_info * p;
+RIOFoadWakeup(struct rio_info *p)
{
int port;
register struct Port *PortP;
@@ -398,11 +384,7 @@ struct rio_info * p;
** Incoming command on the COMMAND_RUP to be processed.
*/
static int
-RIOCommandRup(p, Rup, HostP, PacketP)
-struct rio_info * p;
-uint Rup;
-struct Host *HostP;
-PKT *PacketP;
+RIOCommandRup(struct rio_info *p, uint Rup, struct Host *HostP, PKT *PacketP)
{
struct PktCmd *PktCmdP = (struct PktCmd *)PacketP->data;
struct Port *PortP;
@@ -619,7 +601,7 @@ PKT *PacketP;
** Allocate an empty command block.
*/
struct CmdBlk *
-RIOGetCmdBlk()
+RIOGetCmdBlk(void)
{
struct CmdBlk *CmdBlkP;
@@ -634,8 +616,7 @@ RIOGetCmdBlk()
** Return a block to the head of the free list.
*/
void
-RIOFreeCmdBlk(CmdBlkP)
-struct CmdBlk *CmdBlkP;
+RIOFreeCmdBlk(struct CmdBlk *CmdBlkP)
{
sysfree((void *)CmdBlkP, sizeof(struct CmdBlk));
}
@@ -645,10 +626,7 @@ struct CmdBlk *CmdBlkP;
** a given rup.
*/
int
-RIOQueueCmdBlk(HostP, Rup, CmdBlkP)
-struct Host *HostP;
-uint Rup;
-struct CmdBlk *CmdBlkP;
+RIOQueueCmdBlk(struct Host *HostP, uint Rup, struct CmdBlk *CmdBlkP)
{
struct CmdBlk **Base;
struct UnixRup *UnixRupP;
@@ -679,7 +657,6 @@ struct CmdBlk *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!
@@ -737,9 +714,7 @@ struct CmdBlk *CmdBlkP;
** must be called at splrio() or higher.
*/
void
-RIOPollHostCommands(p, HostP)
-struct rio_info * p;
-struct Host * HostP;
+RIOPollHostCommands(struct rio_info *p, struct Host *HostP)
{
register struct CmdBlk *CmdBlkP;
register struct UnixRup *UnixRupP;
@@ -918,9 +893,7 @@ struct Host * HostP;
}
int
-RIOWFlushMark(iPortP, CmdBlkP)
-int iPortP;
-struct CmdBlk *CmdBlkP;
+RIOWFlushMark(int iPortP, struct CmdBlk *CmdBlkP)
{
struct Port * PortP = (struct Port *)iPortP;
unsigned long flags;
@@ -936,9 +909,7 @@ struct CmdBlk *CmdBlkP;
}
int
-RIORFlushEnable(iPortP, CmdBlkP)
-int iPortP;
-struct CmdBlk *CmdBlkP;
+RIORFlushEnable(int iPortP, struct CmdBlk *CmdBlkP)
{
struct Port * PortP = (struct Port *)iPortP;
PKT *PacketP;
@@ -965,9 +936,7 @@ struct CmdBlk *CmdBlkP;
}
int
-RIOUnUse(iPortP, CmdBlkP)
-int iPortP;
-struct CmdBlk *CmdBlkP;
+RIOUnUse(int iPortP, struct CmdBlk *CmdBlkP)
{
struct Port * PortP = (struct Port *)iPortP;
unsigned long flags;
@@ -1009,9 +978,7 @@ struct CmdBlk *CmdBlkP;
}
void
-ShowPacket(Flags, PacketP)
-uint Flags;
-struct PKT *PacketP;
+ShowPacket(uint Flags, struct PKT *PacketP)
{
}
diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c
index 3f2bb4f9a84f9..ff4f098048655 100644
--- a/drivers/char/rtc.c
+++ b/drivers/char/rtc.c
@@ -73,6 +73,7 @@
#include <linux/init.h>
#include <linux/poll.h>
#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
#include <linux/spinlock.h>
#include <linux/sysctl.h>
#include <linux/wait.h>
@@ -151,8 +152,7 @@ static void set_rtc_irq_bit(unsigned char bit);
static void mask_rtc_irq_bit(unsigned char bit);
#endif
-static int rtc_read_proc(char *page, char **start, off_t off,
- int count, int *eof, void *data);
+static int rtc_proc_open(struct inode *inode, struct file *file);
/*
* Bits in rtc_status. (6 bits of room for future expansion)
@@ -871,11 +871,18 @@ static struct file_operations rtc_fops = {
.fasync = rtc_fasync,
};
-static struct miscdevice rtc_dev=
-{
- RTC_MINOR,
- "rtc",
- &rtc_fops
+static struct miscdevice rtc_dev = {
+ .minor = RTC_MINOR,
+ .name = "rtc",
+ .fops = &rtc_fops,
+};
+
+static struct file_operations rtc_proc_fops = {
+ .owner = THIS_MODULE,
+ .open = rtc_proc_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
};
#if defined(RTC_IRQ) && !defined(__sparc__)
@@ -884,6 +891,7 @@ static irqreturn_t (*rtc_int_handler_ptr)(int irq, void *dev_id, struct pt_regs
static int __init rtc_init(void)
{
+ struct proc_dir_entry *ent;
#if defined(__alpha__) || defined(__mips__)
unsigned int year, ctrl;
unsigned long uip_watchdog;
@@ -974,7 +982,9 @@ no_irq:
release_region(RTC_PORT(0), RTC_IO_EXTENT);
return -ENODEV;
}
- if (!create_proc_read_entry ("driver/rtc", 0, NULL, rtc_read_proc, NULL)) {
+
+ ent = create_proc_entry("driver/rtc", 0, NULL);
+ if (!ent) {
#ifdef RTC_IRQ
free_irq(RTC_IRQ, NULL);
#endif
@@ -982,6 +992,7 @@ no_irq:
misc_deregister(&rtc_dev);
return -ENOMEM;
}
+ ent->proc_fops = &rtc_proc_fops;
#if defined(__alpha__) || defined(__mips__)
rtc_freq = HZ;
@@ -1119,11 +1130,10 @@ static void rtc_dropped_irq(unsigned long data)
* Info exported via "/proc/driver/rtc".
*/
-static int rtc_proc_output (char *buf)
+static int rtc_proc_show(struct seq_file *seq, void *v)
{
#define YN(bit) ((ctrl & bit) ? "yes" : "no")
#define NY(bit) ((ctrl & bit) ? "no" : "yes")
- char *p;
struct rtc_time tm;
unsigned char batt, ctrl;
unsigned long freq;
@@ -1134,7 +1144,6 @@ static int rtc_proc_output (char *buf)
freq = rtc_freq;
spin_unlock_irq(&rtc_lock);
- p = buf;
rtc_get_rtc_time(&tm);
@@ -1142,12 +1151,12 @@ static int rtc_proc_output (char *buf)
* There is no way to tell if the luser has the RTC set for local
* time or for Universal Standard Time (GMT). Probably local though.
*/
- p += sprintf(p,
- "rtc_time\t: %02d:%02d:%02d\n"
- "rtc_date\t: %04d-%02d-%02d\n"
- "rtc_epoch\t: %04lu\n",
- tm.tm_hour, tm.tm_min, tm.tm_sec,
- tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, epoch);
+ seq_printf(seq,
+ "rtc_time\t: %02d:%02d:%02d\n"
+ "rtc_date\t: %04d-%02d-%02d\n"
+ "rtc_epoch\t: %04lu\n",
+ tm.tm_hour, tm.tm_min, tm.tm_sec,
+ tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, epoch);
get_rtc_alm_time(&tm);
@@ -1156,57 +1165,50 @@ static int rtc_proc_output (char *buf)
* match any value for that particular field. Values that are
* greater than a valid time, but less than 0xc0 shouldn't appear.
*/
- p += sprintf(p, "alarm\t\t: ");
+ seq_puts(seq, "alarm\t\t: ");
if (tm.tm_hour <= 24)
- p += sprintf(p, "%02d:", tm.tm_hour);
+ seq_printf(seq, "%02d:", tm.tm_hour);
else
- p += sprintf(p, "**:");
+ seq_puts(seq, "**:");
if (tm.tm_min <= 59)
- p += sprintf(p, "%02d:", tm.tm_min);
+ seq_printf(seq, "%02d:", tm.tm_min);
else
- p += sprintf(p, "**:");
+ seq_puts(seq, "**:");
if (tm.tm_sec <= 59)
- p += sprintf(p, "%02d\n", tm.tm_sec);
+ seq_printf(seq, "%02d\n", tm.tm_sec);
else
- p += sprintf(p, "**\n");
-
- p += sprintf(p,
- "DST_enable\t: %s\n"
- "BCD\t\t: %s\n"
- "24hr\t\t: %s\n"
- "square_wave\t: %s\n"
- "alarm_IRQ\t: %s\n"
- "update_IRQ\t: %s\n"
- "periodic_IRQ\t: %s\n"
- "periodic_freq\t: %ld\n"
- "batt_status\t: %s\n",
- YN(RTC_DST_EN),
- NY(RTC_DM_BINARY),
- YN(RTC_24H),
- YN(RTC_SQWE),
- YN(RTC_AIE),
- YN(RTC_UIE),
- YN(RTC_PIE),
- freq,
- batt ? "okay" : "dead");
-
- return p - buf;
+ seq_puts(seq, "**\n");
+
+ seq_printf(seq,
+ "DST_enable\t: %s\n"
+ "BCD\t\t: %s\n"
+ "24hr\t\t: %s\n"
+ "square_wave\t: %s\n"
+ "alarm_IRQ\t: %s\n"
+ "update_IRQ\t: %s\n"
+ "periodic_IRQ\t: %s\n"
+ "periodic_freq\t: %ld\n"
+ "batt_status\t: %s\n",
+ YN(RTC_DST_EN),
+ NY(RTC_DM_BINARY),
+ YN(RTC_24H),
+ YN(RTC_SQWE),
+ YN(RTC_AIE),
+ YN(RTC_UIE),
+ YN(RTC_PIE),
+ freq,
+ batt ? "okay" : "dead");
+
+ return 0;
#undef YN
#undef NY
}
-static int rtc_read_proc(char *page, char **start, off_t off,
- int count, int *eof, void *data)
+static int rtc_proc_open(struct inode *inode, struct file *file)
{
- int len = rtc_proc_output (page);
- if (len <= off+count) *eof = 1;
- *start = page + off;
- len -= off;
- if (len>count) len = count;
- if (len<0) len = 0;
- return len;
+ return single_open(file, rtc_proc_show, NULL);
}
void rtc_get_rtc_time(struct rtc_time *rtc_tm)
diff --git a/drivers/char/s3c2410-rtc.c b/drivers/char/s3c2410-rtc.c
index b953eaa20de0d..ec666395a26cb 100644
--- a/drivers/char/s3c2410-rtc.c
+++ b/drivers/char/s3c2410-rtc.c
@@ -13,6 +13,7 @@
* 08-Nov-2004 BJD Initial creation
* 12-Nov-2004 BJD Added periodic IRQ and PM code
* 22-Nov-2004 BJD Sign-test on alarm code to check for <0
+ * 10-Mar-2005 LCVR Changed S3C2410_VA_RTC to S3C24XX_VA_RTC
*/
#include <linux/module.h>
@@ -38,8 +39,8 @@
/* need this for the RTC_AF definitions */
#include <linux/mc146818rtc.h>
-#undef S3C2410_VA_RTC
-#define S3C2410_VA_RTC s3c2410_rtc_base
+#undef S3C24XX_VA_RTC
+#define S3C24XX_VA_RTC s3c2410_rtc_base
static struct resource *s3c2410_rtc_mem;
diff --git a/drivers/char/selection.c b/drivers/char/selection.c
index 791b1fc1f4a0c..16d630f58bb49 100644
--- a/drivers/char/selection.c
+++ b/drivers/char/selection.c
@@ -43,15 +43,13 @@ static char *sel_buffer;
from interrupt (via scrollback/front) */
/* set reverse video on characters s-e of console with selection. */
-inline static void
-highlight(const int s, const int e)
+static inline void highlight(const int s, const int e)
{
invert_screen(sel_cons, s, e-s+2, 1);
}
/* use complementary color to show the pointer */
-inline static void
-highlight_pointer(const int where)
+static inline void highlight_pointer(const int where)
{
complement_pos(sel_cons, where);
}
@@ -122,7 +120,7 @@ int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *t
{ unsigned short xs, ys, xe, ye;
- if (verify_area(VERIFY_READ, sel, sizeof(*sel)))
+ if (!access_ok(VERIFY_READ, sel, sizeof(*sel)))
return -EFAULT;
__get_user(xs, &sel->xs);
__get_user(ys, &sel->ys);
@@ -277,7 +275,7 @@ int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *t
*/
int paste_selection(struct tty_struct *tty)
{
- struct vt_struct *vt = (struct vt_struct *) tty->driver_data;
+ struct vc_data *vc = (struct vc_data *)tty->driver_data;
int pasted = 0, count;
struct tty_ldisc *ld;
DECLARE_WAITQUEUE(wait, current);
@@ -288,7 +286,7 @@ int paste_selection(struct tty_struct *tty)
ld = tty_ldisc_ref_wait(tty);
- add_wait_queue(&vt->paste_wait, &wait);
+ add_wait_queue(&vc->paste_wait, &wait);
while (sel_buffer && sel_buffer_lth > pasted) {
set_current_state(TASK_INTERRUPTIBLE);
if (test_bit(TTY_THROTTLED, &tty->flags)) {
@@ -300,7 +298,7 @@ int paste_selection(struct tty_struct *tty)
tty->ldisc.receive_buf(tty, sel_buffer + pasted, NULL, count);
pasted += count;
}
- remove_wait_queue(&vt->paste_wait, &wait);
+ remove_wait_queue(&vc->paste_wait, &wait);
current->state = TASK_RUNNING;
tty_ldisc_deref(ld);
diff --git a/drivers/char/snsc.c b/drivers/char/snsc.c
index 9d027ec553852..ffb9143376bb4 100644
--- a/drivers/char/snsc.c
+++ b/drivers/char/snsc.c
@@ -192,8 +192,8 @@ scdrv_read(struct file *file, char __user *buf, size_t count, loff_t *f_pos)
}
len = CHUNKSIZE;
- add_wait_queue(&sd->sd_rq, &wait);
set_current_state(TASK_INTERRUPTIBLE);
+ add_wait_queue(&sd->sd_rq, &wait);
spin_unlock_irqrestore(&sd->sd_rlock, flags);
schedule_timeout(SCDRV_TIMEOUT);
@@ -288,8 +288,8 @@ scdrv_write(struct file *file, const char __user *buf,
return -EAGAIN;
}
- add_wait_queue(&sd->sd_wq, &wait);
set_current_state(TASK_INTERRUPTIBLE);
+ add_wait_queue(&sd->sd_wq, &wait);
spin_unlock_irqrestore(&sd->sd_wlock, flags);
schedule_timeout(SCDRV_TIMEOUT);
diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c
index 5a33227cc388e..c789d5ceac761 100644
--- a/drivers/char/specialix.c
+++ b/drivers/char/specialix.c
@@ -66,7 +66,7 @@
*
*/
-#define VERSION "1.10"
+#define VERSION "1.11"
/*
@@ -99,6 +99,44 @@
#include "cd1865.h"
+/*
+ This driver can spew a whole lot of debugging output at you. If you
+ need maximum performance, you should disable the DEBUG define. To
+ aid in debugging in the field, I'm leaving the compile-time debug
+ features enabled, and disable them "runtime". That allows me to
+ instruct people with problems to enable debugging without requiring
+ them to recompile...
+*/
+#define DEBUG
+
+static int sx_debug;
+static int sx_rxfifo = SPECIALIX_RXFIFO;
+
+#ifdef DEBUG
+#define dprintk(f, str...) if (sx_debug & f) printk (str)
+#else
+#define dprintk(f, str...) /* nothing */
+#endif
+
+#define SX_DEBUG_FLOW 0x0001
+#define SX_DEBUG_DATA 0x0002
+#define SX_DEBUG_PROBE 0x0004
+#define SX_DEBUG_CHAN 0x0008
+#define SX_DEBUG_INIT 0x0010
+#define SX_DEBUG_RX 0x0020
+#define SX_DEBUG_TX 0x0040
+#define SX_DEBUG_IRQ 0x0080
+#define SX_DEBUG_OPEN 0x0100
+#define SX_DEBUG_TERMIOS 0x0200
+#define SX_DEBUG_SIGNALS 0x0400
+#define SX_DEBUG_FIFO 0x0800
+
+
+#define func_enter() dprintk (SX_DEBUG_FLOW, "io8: enter %s\n",__FUNCTION__)
+#define func_exit() dprintk (SX_DEBUG_FLOW, "io8: exit %s\n", __FUNCTION__)
+
+#define jiffies_from_ms(a) ((((a) * HZ)/1000)+1)
+
/* Configurable options: */
@@ -110,6 +148,12 @@
requiring attention, the timer doesn't help either. */
#undef SPECIALIX_TIMER
+#ifdef SPECIALIX_TIMER
+static int sx_poll = HZ;
+#endif
+
+
+
/*
* The following defines are mostly for testing purposes. But if you need
* some nice reporting in your syslog, you can define them also.
@@ -254,11 +298,17 @@ static inline void sx_out_off(struct specialix_board * bp, unsigned short reg,
/* Wait for Channel Command Register ready */
static inline void sx_wait_CCR(struct specialix_board * bp)
{
- unsigned long delay;
-
- for (delay = SX_CCR_TIMEOUT; delay; delay--)
- if (!sx_in(bp, CD186x_CCR))
+ unsigned long delay, flags;
+ unsigned char ccr;
+
+ for (delay = SX_CCR_TIMEOUT; delay; delay--) {
+ spin_lock_irqsave(&bp->lock, flags);
+ ccr = sx_in(bp, CD186x_CCR);
+ spin_unlock_irqrestore(&bp->lock, flags);
+ if (!ccr)
return;
+ udelay (1);
+ }
printk(KERN_ERR "sx%d: Timeout waiting for CCR.\n", board_No(bp));
}
@@ -268,10 +318,17 @@ static inline void sx_wait_CCR(struct specialix_board * bp)
static inline void sx_wait_CCR_off(struct specialix_board * bp)
{
unsigned long delay;
+ unsigned char crr;
+ unsigned long flags;
- for (delay = SX_CCR_TIMEOUT; delay; delay--)
- if (!sx_in_off(bp, CD186x_CCR))
+ for (delay = SX_CCR_TIMEOUT; delay; delay--) {
+ spin_lock_irqsave(&bp->lock, flags);
+ crr = sx_in_off(bp, CD186x_CCR);
+ spin_unlock_irqrestore(&bp->lock, flags);
+ if (!crr)
return;
+ udelay (1);
+ }
printk(KERN_ERR "sx%d: Timeout waiting for CCR.\n", board_No(bp));
}
@@ -315,10 +372,11 @@ static inline void sx_long_delay(unsigned long delay)
/* Set the IRQ using the RTS lines that run to the PAL on the board.... */
-int sx_set_irq ( struct specialix_board *bp)
+static int sx_set_irq ( struct specialix_board *bp)
{
int virq;
int i;
+ unsigned long flags;
if (bp->flags & SX_BOARD_IS_PCI)
return 1;
@@ -331,11 +389,12 @@ int sx_set_irq ( struct specialix_board *bp)
default: printk (KERN_ERR "Speclialix: cannot set irq to %d.\n", bp->irq);
return 0;
}
-
+ spin_lock_irqsave(&bp->lock, flags);
for (i=0;i<2;i++) {
sx_out(bp, CD186x_CAR, i);
sx_out(bp, CD186x_MSVRTS, ((virq >> i) & 0x1)? MSVR_RTS:0);
}
+ spin_unlock_irqrestore(&bp->lock, flags);
return 1;
}
@@ -346,14 +405,14 @@ static int sx_init_CD186x(struct specialix_board * bp)
unsigned long flags;
int scaler;
int rv = 1;
-
- save_flags(flags); cli();
+ func_enter();
sx_wait_CCR_off(bp); /* Wait for CCR ready */
+ spin_lock_irqsave(&bp->lock, flags);
sx_out_off(bp, CD186x_CCR, CCR_HARDRESET); /* Reset CD186x chip */
- sti();
+ spin_unlock_irqrestore(&bp->lock, flags);
sx_long_delay(HZ/20); /* Delay 0.05 sec */
- cli();
+ spin_lock_irqsave(&bp->lock, flags);
sx_out_off(bp, CD186x_GIVR, SX_ID); /* Set ID for this chip */
sx_out_off(bp, CD186x_GICR, 0); /* Clear all bits */
sx_out_off(bp, CD186x_PILR1, SX_ACK_MINT); /* Prio for modem intr */
@@ -367,6 +426,7 @@ static int sx_init_CD186x(struct specialix_board * bp)
sx_out_off(bp, CD186x_PPRH, scaler >> 8);
sx_out_off(bp, CD186x_PPRL, scaler & 0xff);
+ spin_unlock_irqrestore(&bp->lock, flags);
if (!sx_set_irq (bp)) {
/* Figure out how to pass this along... */
@@ -374,21 +434,25 @@ static int sx_init_CD186x(struct specialix_board * bp)
rv = 0;
}
- restore_flags(flags);
+ func_exit();
return rv;
}
-int read_cross_byte (struct specialix_board *bp, int reg, int bit)
+static int read_cross_byte (struct specialix_board *bp, int reg, int bit)
{
int i;
int t;
+ unsigned long flags;
+ spin_lock_irqsave(&bp->lock, flags);
for (i=0, t=0;i<8;i++) {
sx_out_off (bp, CD186x_CAR, i);
if (sx_in_off (bp, reg) & bit)
t |= 1 << i;
}
+ spin_unlock_irqrestore(&bp->lock, flags);
+
return t;
}
@@ -396,15 +460,22 @@ int read_cross_byte (struct specialix_board *bp, int reg, int bit)
#ifdef SPECIALIX_TIMER
void missed_irq (unsigned long data)
{
- if (sx_in ((struct specialix_board *)data, CD186x_SRSR) &
+ unsigned char irq;
+ unsigned long flags;
+ struct specialix_board *bp = (struct specialix_board *)data;
+
+ spin_lock_irqsave(&bp->lock, flags);
+ irq = sx_in ((struct specialix_board *)data, CD186x_SRSR) &
(SRSR_RREQint |
SRSR_TREQint |
- SRSR_MREQint)) {
+ SRSR_MREQint);
+ spin_unlock_irqrestore(&bp->lock, flags);
+ if (irq) {
printk (KERN_INFO "Missed interrupt... Calling int from timer. \n");
sx_interrupt (((struct specialix_board *)data)->irq,
- NULL, NULL);
+ (void*)data, NULL);
}
- missed_irq_timer.expires = jiffies + HZ;
+ missed_irq_timer.expires = jiffies + sx_poll;
add_timer (&missed_irq_timer);
}
#endif
@@ -422,8 +493,12 @@ static int sx_probe(struct specialix_board *bp)
int rev;
int chip;
- if (sx_check_io_range(bp))
+ func_enter();
+
+ if (sx_check_io_range(bp)) {
+ func_exit();
return 1;
+ }
/* Are the I/O ports here ? */
sx_out_off(bp, CD186x_PPRL, 0x5a);
@@ -438,6 +513,7 @@ static int sx_probe(struct specialix_board *bp)
if ((val1 != 0x5a) || (val2 != 0xa5)) {
printk(KERN_INFO "sx%d: specialix IO8+ Board at 0x%03x not found.\n",
board_No(bp), bp->base);
+ func_exit();
return 1;
}
@@ -445,10 +521,9 @@ static int sx_probe(struct specialix_board *bp)
identification */
val1 = read_cross_byte (bp, CD186x_MSVR, MSVR_DSR);
val2 = read_cross_byte (bp, CD186x_MSVR, MSVR_RTS);
-#ifdef SPECIALIX_DEBUG
- printk (KERN_DEBUG "sx%d: DSR lines are: %02x, rts lines are: %02x\n",
+ dprintk (SX_DEBUG_INIT, "sx%d: DSR lines are: %02x, rts lines are: %02x\n",
board_No(bp), val1, val2);
-#endif
+
/* They managed to switch the bit order between the docs and
the IO8+ card. The new PCI card now conforms to old docs.
They changed the PCI docs to reflect the situation on the
@@ -457,6 +532,7 @@ static int sx_probe(struct specialix_board *bp)
if (val1 != val2) {
printk(KERN_INFO "sx%d: specialix IO8+ ID %02x at 0x%03x not found (%02x).\n",
board_No(bp), val2, bp->base, val1);
+ func_exit();
return 1;
}
@@ -473,21 +549,19 @@ static int sx_probe(struct specialix_board *bp)
sx_long_delay(HZ/20);
irqs = probe_irq_off(irqs);
-#if SPECIALIX_DEBUG > 2
- printk (KERN_DEBUG "SRSR = %02x, ", sx_in(bp, CD186x_SRSR));
- printk ( "TRAR = %02x, ", sx_in(bp, CD186x_TRAR));
- printk ( "GIVR = %02x, ", sx_in(bp, CD186x_GIVR));
- printk ( "GICR = %02x, ", sx_in(bp, CD186x_GICR));
- printk ( "\n");
-#endif
+ dprintk (SX_DEBUG_INIT, "SRSR = %02x, ", sx_in(bp, CD186x_SRSR));
+ dprintk (SX_DEBUG_INIT, "TRAR = %02x, ", sx_in(bp, CD186x_TRAR));
+ dprintk (SX_DEBUG_INIT, "GIVR = %02x, ", sx_in(bp, CD186x_GIVR));
+ dprintk (SX_DEBUG_INIT, "GICR = %02x, ", sx_in(bp, CD186x_GICR));
+ dprintk (SX_DEBUG_INIT, "\n");
+
/* Reset CD186x again */
if (!sx_init_CD186x(bp)) {
/* Hmmm. This is dead code anyway. */
}
-#if SPECIALIX_DEBUG > 2
- printk (KERN_DEBUG "val1 = %02x, val2 = %02x, val3 = %02x.\n",
+
+ dprintk (SX_DEBUG_INIT "val1 = %02x, val2 = %02x, val3 = %02x.\n",
val1, val2, val3);
-#endif
}
@@ -495,6 +569,7 @@ static int sx_probe(struct specialix_board *bp)
if (irqs <= 0) {
printk(KERN_ERR "sx%d: Can't find IRQ for specialix IO8+ board at 0x%03x.\n",
board_No(bp), bp->base);
+ func_exit();
return 1;
}
#endif
@@ -504,6 +579,7 @@ static int sx_probe(struct specialix_board *bp)
#endif
/* Reset CD186x again */
if (!sx_init_CD186x(bp)) {
+ func_exit();
return -EIO;
}
@@ -528,15 +604,13 @@ static int sx_probe(struct specialix_board *bp)
default:chip=-1;rev='x';
}
-#if SPECIALIX_DEBUG > 2
- printk (KERN_DEBUG " GFCR = 0x%02x\n", sx_in_off(bp, CD186x_GFRCR) );
-#endif
+ dprintk (SX_DEBUG_INIT, " GFCR = 0x%02x\n", sx_in_off(bp, CD186x_GFRCR) );
#ifdef SPECIALIX_TIMER
init_timer (&missed_irq_timer);
missed_irq_timer.function = missed_irq;
missed_irq_timer.data = (unsigned long) bp;
- missed_irq_timer.expires = jiffies + HZ;
+ missed_irq_timer.expires = jiffies + sx_poll;
add_timer (&missed_irq_timer);
#endif
@@ -545,6 +619,7 @@ static int sx_probe(struct specialix_board *bp)
bp->base, bp->irq,
chip, rev);
+ func_exit();
return 0;
}
@@ -555,8 +630,12 @@ static int sx_probe(struct specialix_board *bp)
static inline void sx_mark_event(struct specialix_port * port, int event)
{
+ func_enter();
+
set_bit(event, &port->event);
schedule_work(&port->tqueue);
+
+ func_exit();
}
@@ -564,12 +643,17 @@ static inline struct specialix_port * sx_get_port(struct specialix_board * bp,
unsigned char const * what)
{
unsigned char channel;
- struct specialix_port * port;
-
+ struct specialix_port * port = NULL;
+
channel = sx_in(bp, CD186x_GICR) >> GICR_CHAN_OFF;
+ dprintk (SX_DEBUG_CHAN, "channel: %d\n", channel);
if (channel < CD186x_NCH) {
port = &sx_port[board_No(bp) * SX_NPORT + channel];
+ dprintk (SX_DEBUG_CHAN, "port: %d %p flags: 0x%x\n",board_No(bp) * SX_NPORT + channel, port, port->flags & ASYNC_INITIALIZED);
+
if (port->flags & ASYNC_INITIALIZED) {
+ dprintk (SX_DEBUG_CHAN, "port: %d %p\n", channel, port);
+ func_exit();
return port;
}
}
@@ -586,43 +670,51 @@ static inline void sx_receive_exc(struct specialix_board * bp)
unsigned char status;
unsigned char ch;
- if (!(port = sx_get_port(bp, "Receive")))
- return;
+ func_enter();
- tty = port->tty;
- 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));
+ port = sx_get_port(bp, "Receive");
+ if (!port) {
+ dprintk (SX_DEBUG_RX, "Hmm, couldn't find port.\n");
+ func_exit();
return;
}
+ tty = port->tty;
+ dprintk (SX_DEBUG_RX, "port: %p count: %d BUFF_SIZE: %d\n",
+ port, tty->flip.count, TTY_FLIPBUF_SIZE);
-#ifdef SX_REPORT_OVERRUN
status = sx_in(bp, CD186x_RCSR);
+
+ dprintk (SX_DEBUG_RX, "status: 0x%x\n", status);
if (status & RCSR_OE) {
port->overrun++;
-#if SPECIALIX_DEBUG
- printk(KERN_DEBUG "sx%d: port %d: Overrun. Total %ld overruns.\n",
+ dprintk(SX_DEBUG_FIFO, "sx%d: port %d: Overrun. Total %ld overruns.\n",
board_No(bp), port_No(port), port->overrun);
-#endif
}
status &= port->mark_mask;
-#else
- status = sx_in(bp, CD186x_RCSR) & port->mark_mask;
-#endif
+
+ /* 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) {
+ dprintk(SX_DEBUG_FIFO, "sx%d: port %d: Working around flip buffer overflow.\n",
+ board_No(bp), port_No(port));
+ func_exit();
+ return;
+ }
+
ch = sx_in(bp, CD186x_RDR);
if (!status) {
+ func_exit();
return;
}
if (status & RCSR_TOUT) {
printk(KERN_INFO "sx%d: port %d: Receiver timeout. Hardware problems ?\n",
board_No(bp), port_No(port));
+ func_exit();
return;
} else if (status & RCSR_BREAK) {
-#ifdef SPECIALIX_DEBUG
- printk(KERN_DEBUG "sx%d: port %d: Handling break...\n",
+ dprintk(SX_DEBUG_RX, "sx%d: port %d: Handling break...\n",
board_No(bp), port_No(port));
-#endif
*tty->flip.flag_buf_ptr++ = TTY_BREAK;
if (port->flags & ASYNC_SAK)
do_SAK(tty);
@@ -642,6 +734,8 @@ static inline void sx_receive_exc(struct specialix_board * bp)
*tty->flip.char_buf_ptr++ = ch;
tty->flip.count++;
schedule_delayed_work(&tty->flip.work, 1);
+
+ func_exit();
}
@@ -650,17 +744,19 @@ static inline void sx_receive(struct specialix_board * bp)
struct specialix_port *port;
struct tty_struct *tty;
unsigned char count;
+
+ func_enter();
- if (!(port = sx_get_port(bp, "Receive")))
+ if (!(port = sx_get_port(bp, "Receive"))) {
+ dprintk (SX_DEBUG_RX, "Hmm, couldn't find port.\n");
+ func_exit();
return;
-
+ }
tty = port->tty;
count = sx_in(bp, CD186x_RDCR);
-
-#ifdef SX_REPORT_FIFO
+ dprintk (SX_DEBUG_RX, "port: %p: count: %d\n", port, count);
port->hits[count > 8 ? 9 : count]++;
-#endif
while (count--) {
if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
@@ -673,6 +769,8 @@ static inline void sx_receive(struct specialix_board * bp)
tty->flip.count++;
}
schedule_delayed_work(&tty->flip.work, 1);
+
+ func_exit();
}
@@ -681,11 +779,13 @@ static inline void sx_transmit(struct specialix_board * bp)
struct specialix_port *port;
struct tty_struct *tty;
unsigned char count;
-
-
- if (!(port = sx_get_port(bp, "Transmit")))
+
+ func_enter();
+ if (!(port = sx_get_port(bp, "Transmit"))) {
+ func_exit();
return;
-
+ }
+ dprintk (SX_DEBUG_TX, "port: %p\n", port);
tty = port->tty;
if (port->IER & IER_TXEMPTY) {
@@ -693,6 +793,7 @@ static inline void sx_transmit(struct specialix_board * bp)
sx_out(bp, CD186x_CAR, port_No(port));
port->IER &= ~IER_TXEMPTY;
sx_out(bp, CD186x_IER, port->IER);
+ func_exit();
return;
}
@@ -701,6 +802,7 @@ static inline void sx_transmit(struct specialix_board * bp)
sx_out(bp, CD186x_CAR, port_No(port));
port->IER &= ~IER_TXRDY;
sx_out(bp, CD186x_IER, port->IER);
+ func_exit();
return;
}
@@ -725,6 +827,8 @@ static inline void sx_transmit(struct specialix_board * bp)
sx_out(bp, CD186x_CCR, CCR_CORCHG2);
port->break_length = 0;
}
+
+ func_exit();
return;
}
@@ -743,6 +847,8 @@ static inline void sx_transmit(struct specialix_board * bp)
}
if (port->xmit_cnt <= port->wakeup_chars)
sx_mark_event(port, RS_EVENT_WRITE_WAKEUP);
+
+ func_exit();
}
@@ -751,10 +857,9 @@ static inline void sx_check_modem(struct specialix_board * bp)
struct specialix_port *port;
struct tty_struct *tty;
unsigned char mcr;
+ int msvr_cd;
-#ifdef SPECIALIX_DEBUG
- printk (KERN_DEBUG "Modem intr. ");
-#endif
+ dprintk (SX_DEBUG_SIGNALS, "Modem intr. ");
if (!(port = sx_get_port(bp, "Modem")))
return;
@@ -764,18 +869,13 @@ static inline void sx_check_modem(struct specialix_board * bp)
printk ("mcr = %02x.\n", mcr);
if ((mcr & MCR_CDCHG)) {
-#ifdef SPECIALIX_DEBUG
- printk (KERN_DEBUG "CD just changed... ");
-#endif
- if (sx_in(bp, CD186x_MSVR) & MSVR_CD) {
-#ifdef SPECIALIX_DEBUG
- printk ( "Waking up guys in open.\n");
-#endif
+ dprintk (SX_DEBUG_SIGNALS, "CD just changed... ");
+ msvr_cd = sx_in(bp, CD186x_MSVR) & MSVR_CD;
+ if (msvr_cd) {
+ dprintk (SX_DEBUG_SIGNALS, "Waking up guys in open.\n");
wake_up_interruptible(&port->open_wait);
} else {
-#ifdef SPECIALIX_DEBUG
- printk ( "Sending HUP.\n");
-#endif
+ dprintk (SX_DEBUG_SIGNALS, "Sending HUP.\n");
schedule_work(&port->tqueue_hangup);
}
}
@@ -820,13 +920,18 @@ static irqreturn_t sx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
struct specialix_board *bp;
unsigned long loop = 0;
int saved_reg;
+ unsigned long flags;
+
+ func_enter();
bp = dev_id;
-
+ spin_lock_irqsave(&bp->lock, flags);
+
+ dprintk (SX_DEBUG_FLOW, "enter %s port %d room: %ld\n", __FUNCTION__, port_No(sx_get_port(bp, "INT")), SERIAL_XMIT_SIZE - sx_get_port(bp, "ITN")->xmit_cnt - 1);
if (!bp || !(bp->flags & SX_BOARD_ACTIVE)) {
-#ifdef SPECIALIX_DEBUG
- printk (KERN_DEBUG "sx: False interrupt. irq %d.\n", irq);
-#endif
+ dprintk (SX_DEBUG_IRQ, "sx: False interrupt. irq %d.\n", irq);
+ spin_unlock_irqrestore(&bp->lock, flags);
+ func_exit();
return IRQ_NONE;
}
@@ -844,8 +949,8 @@ static irqreturn_t sx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
else if (ack == (SX_ID | GIVR_IT_REXC))
sx_receive_exc(bp);
else
- printk(KERN_ERR "sx%d: Bad receive ack 0x%02x.\n",
- board_No(bp), ack);
+ printk(KERN_ERR "sx%d: status: 0x%x Bad receive ack 0x%02x.\n",
+ board_No(bp), status, ack);
} else if (status & SRSR_TREQint) {
ack = sx_in(bp, CD186x_TRAR);
@@ -853,16 +958,16 @@ static irqreturn_t sx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (ack == (SX_ID | GIVR_IT_TX))
sx_transmit(bp);
else
- printk(KERN_ERR "sx%d: Bad transmit ack 0x%02x.\n",
- board_No(bp), ack);
+ printk(KERN_ERR "sx%d: status: 0x%x Bad transmit ack 0x%02x. port: %d\n",
+ board_No(bp), status, ack, port_No (sx_get_port (bp, "Int")));
} else if (status & SRSR_MREQint) {
ack = sx_in(bp, CD186x_MRAR);
if (ack == (SX_ID | GIVR_IT_MODEM))
sx_check_modem(bp);
else
- printk(KERN_ERR "sx%d: Bad modem ack 0x%02x.\n",
- board_No(bp), ack);
+ printk(KERN_ERR "sx%d: status: 0x%x Bad modem ack 0x%02x.\n",
+ board_No(bp), status, ack);
}
@@ -870,6 +975,8 @@ static irqreturn_t sx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
}
bp->reg = saved_reg;
outb (bp->reg, bp->base + SX_ADDR_REG);
+ spin_unlock_irqrestore(&bp->lock, flags);
+ func_exit();
return IRQ_HANDLED;
}
@@ -878,23 +985,39 @@ static irqreturn_t sx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
* Routines for open & close processing.
*/
-void turn_ints_off (struct specialix_board *bp)
+static void turn_ints_off (struct specialix_board *bp)
{
+ unsigned long flags;
+
+ func_enter();
if (bp->flags & SX_BOARD_IS_PCI) {
/* This was intended for enabeling the interrupt on the
* PCI card. However it seems that it's already enabled
* and as PCI interrupts can be shared, there is no real
* reason to have to turn it off. */
}
+
+ spin_lock_irqsave(&bp->lock, flags);
(void) sx_in_off (bp, 0); /* Turn off interrupts. */
+ spin_unlock_irqrestore(&bp->lock, flags);
+
+ func_exit();
}
-void turn_ints_on (struct specialix_board *bp)
+static void turn_ints_on (struct specialix_board *bp)
{
+ unsigned long flags;
+
+ func_enter();
+
if (bp->flags & SX_BOARD_IS_PCI) {
/* play with the PCI chip. See comment above. */
}
+ spin_lock_irqsave(&bp->lock, flags);
(void) sx_in (bp, 0); /* Turn ON interrupts. */
+ spin_unlock_irqrestore(&bp->lock, flags);
+
+ func_exit();
}
@@ -924,18 +1047,23 @@ static inline int sx_setup_board(struct specialix_board * bp)
/* Called with disabled interrupts */
static inline void sx_shutdown_board(struct specialix_board *bp)
{
- if (!(bp->flags & SX_BOARD_ACTIVE))
+ func_enter();
+
+ if (!(bp->flags & SX_BOARD_ACTIVE)) {
+ func_exit();
return;
-
+ }
+
bp->flags &= ~SX_BOARD_ACTIVE;
-#if SPECIALIX_DEBUG > 2
- printk ("Freeing IRQ%d for board %d.\n", bp->irq, board_No (bp));
-#endif
+ dprintk (SX_DEBUG_IRQ, "Freeing IRQ%d for board %d.\n",
+ bp->irq, board_No (bp));
free_irq(bp->irq, bp);
turn_ints_off (bp);
+
+ func_exit();
}
@@ -951,13 +1079,19 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p
unsigned char cor1 = 0, cor3 = 0;
unsigned char mcor1 = 0, mcor2 = 0;
static unsigned long again;
-
- if (!(tty = port->tty) || !tty->termios)
+ unsigned long flags;
+
+ func_enter();
+
+ if (!(tty = port->tty) || !tty->termios) {
+ func_exit();
return;
+ }
port->IER = 0;
port->COR2 = 0;
/* Select port on the board */
+ spin_lock_irqsave(&bp->lock, flags);
sx_out(bp, CD186x_CAR, port_No(port));
/* The Specialix board doens't implement the RTS lines.
@@ -966,9 +1100,8 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p
port->MSVR = MSVR_DTR | (sx_in(bp, CD186x_MSVR) & MSVR_RTS);
else
port->MSVR = (sx_in(bp, CD186x_MSVR) & MSVR_RTS);
-#ifdef DEBUG_SPECIALIX
- printk (KERN_DEBUG "sx: got MSVR=%02x.\n", port->MSVR);
-#endif
+ spin_unlock_irqrestore(&bp->lock, flags);
+ dprintk (SX_DEBUG_TERMIOS, "sx: got MSVR=%02x.\n", port->MSVR);
baud = C_BAUD(tty);
if (baud & CBAUDEX) {
@@ -988,17 +1121,15 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p
if (!baud_table[baud]) {
/* Drop DTR & exit */
-#ifdef SPECIALIX_DEBUG
- printk (KERN_DEBUG "Dropping DTR... Hmm....\n");
-#endif
+ dprintk (SX_DEBUG_TERMIOS, "Dropping DTR... Hmm....\n");
if (!SX_CRTSCTS (tty)) {
port -> MSVR &= ~ MSVR_DTR;
+ spin_lock_irqsave(&bp->lock, flags);
sx_out(bp, CD186x_MSVR, port->MSVR );
+ spin_unlock_irqrestore(&bp->lock, flags);
}
-#ifdef DEBUG_SPECIALIX
else
- printk (KERN_DEBUG "Can't drop DTR: no DTR.\n");
-#endif
+ dprintk (SX_DEBUG_TERMIOS, "Can't drop DTR: no DTR.\n");
return;
} else {
/* Set DTR on */
@@ -1037,12 +1168,12 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p
port_No (port), tmp);
}
}
-
+ spin_lock_irqsave(&bp->lock, flags);
sx_out(bp, CD186x_RBPRH, (tmp >> 8) & 0xff);
sx_out(bp, CD186x_TBPRH, (tmp >> 8) & 0xff);
sx_out(bp, CD186x_RBPRL, tmp & 0xff);
sx_out(bp, CD186x_TBPRL, tmp & 0xff);
-
+ spin_unlock_irqrestore(&bp->lock, flags);
if (port->custom_divisor) {
baud = (SX_OSCFREQ + port->custom_divisor/2) / port->custom_divisor;
baud = ( baud + 5 ) / 10;
@@ -1057,8 +1188,9 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p
/* Receiver timeout will be transmission time for 1.5 chars */
tmp = (SPECIALIX_TPS + SPECIALIX_TPS/2 + baud/2) / baud;
tmp = (tmp > 0xff) ? 0xff : tmp;
+ spin_lock_irqsave(&bp->lock, flags);
sx_out(bp, CD186x_RTPR, tmp);
-
+ spin_unlock_irqrestore(&bp->lock, flags);
switch (C_CSIZE(tty)) {
case CS5:
cor1 |= COR1_5BITS;
@@ -1105,7 +1237,9 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p
port->IER |= IER_DSR | IER_CTS;
mcor1 |= MCOR1_DSRZD | MCOR1_CTSZD;
mcor2 |= MCOR2_DSROD | MCOR2_CTSOD;
+ spin_lock_irqsave(&bp->lock, flags);
tty->hw_stopped = !(sx_in(bp, CD186x_MSVR) & (MSVR_CTS|MSVR_DSR));
+ spin_unlock_irqrestore(&bp->lock, flags);
#else
port->COR2 |= COR2_CTSAE;
#endif
@@ -1117,10 +1251,12 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p
cor3 |= (COR3_FCT | COR3_SCDE);
if (I_IXANY(tty))
port->COR2 |= COR2_IXM;
+ spin_lock_irqsave(&bp->lock, flags);
sx_out(bp, CD186x_SCHR1, START_CHAR(tty));
sx_out(bp, CD186x_SCHR2, STOP_CHAR(tty));
sx_out(bp, CD186x_SCHR3, START_CHAR(tty));
sx_out(bp, CD186x_SCHR4, STOP_CHAR(tty));
+ spin_unlock_irqrestore(&bp->lock, flags);
}
if (!C_CLOCAL(tty)) {
/* Enable CD check */
@@ -1134,27 +1270,33 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p
port->IER |= IER_RXD;
/* Set input FIFO size (1-8 bytes) */
- cor3 |= SPECIALIX_RXFIFO;
+ cor3 |= sx_rxfifo;
/* Setting up CD186x channel registers */
+ spin_lock_irqsave(&bp->lock, flags);
sx_out(bp, CD186x_COR1, cor1);
sx_out(bp, CD186x_COR2, port->COR2);
sx_out(bp, CD186x_COR3, cor3);
+ spin_unlock_irqrestore(&bp->lock, flags);
/* Make CD186x know about registers change */
sx_wait_CCR(bp);
+ spin_lock_irqsave(&bp->lock, flags);
sx_out(bp, CD186x_CCR, CCR_CORCHG1 | CCR_CORCHG2 | CCR_CORCHG3);
/* Setting up modem option registers */
-#ifdef DEBUG_SPECIALIX
- printk ("Mcor1 = %02x, mcor2 = %02x.\n", mcor1, mcor2);
-#endif
+ dprintk (SX_DEBUG_TERMIOS, "Mcor1 = %02x, mcor2 = %02x.\n", mcor1, mcor2);
sx_out(bp, CD186x_MCOR1, mcor1);
sx_out(bp, CD186x_MCOR2, mcor2);
+ spin_unlock_irqrestore(&bp->lock, flags);
/* Enable CD186x transmitter & receiver */
sx_wait_CCR(bp);
+ spin_lock_irqsave(&bp->lock, flags);
sx_out(bp, CD186x_CCR, CCR_TXEN | CCR_RXEN);
/* Enable interrupts */
sx_out(bp, CD186x_IER, port->IER);
/* And finally set the modem lines... */
sx_out(bp, CD186x_MSVR, port->MSVR);
+ spin_unlock_irqrestore(&bp->lock, flags);
+
+ func_exit();
}
@@ -1162,37 +1304,44 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p
static int sx_setup_port(struct specialix_board *bp, struct specialix_port *port)
{
unsigned long flags;
-
- if (port->flags & ASYNC_INITIALIZED)
+
+ func_enter();
+
+ if (port->flags & ASYNC_INITIALIZED) {
+ func_exit();
return 0;
+ }
if (!port->xmit_buf) {
/* We may sleep in get_zeroed_page() */
unsigned long tmp;
- if (!(tmp = get_zeroed_page(GFP_KERNEL)))
+ if (!(tmp = get_zeroed_page(GFP_KERNEL))) {
+ func_exit();
return -ENOMEM;
+ }
if (port->xmit_buf) {
free_page(tmp);
+ func_exit();
return -ERESTARTSYS;
}
port->xmit_buf = (unsigned char *) tmp;
}
- save_flags(flags); cli();
-
+ spin_lock_irqsave(&port->lock, flags);
+
if (port->tty)
clear_bit(TTY_IO_ERROR, &port->tty->flags);
-
- if (port->count == 1)
- bp->count++;
-
+
port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
sx_change_speed(bp, port);
port->flags |= ASYNC_INITIALIZED;
+
+ spin_unlock_irqrestore(&port->lock, flags);
+
- restore_flags(flags);
+ func_exit();
return 0;
}
@@ -1201,62 +1350,54 @@ static int sx_setup_port(struct specialix_board *bp, struct specialix_port *port
static void sx_shutdown_port(struct specialix_board *bp, struct specialix_port *port)
{
struct tty_struct *tty;
+ int i;
+ unsigned long flags;
- if (!(port->flags & ASYNC_INITIALIZED))
+ func_enter();
+
+ if (!(port->flags & ASYNC_INITIALIZED)) {
+ func_exit();
return;
+ }
-#ifdef SX_REPORT_OVERRUN
- printk(KERN_INFO "sx%d: port %d: Total %ld overruns were detected.\n",
- board_No(bp), port_No(port), port->overrun);
-#endif
-#ifdef SX_REPORT_FIFO
- {
- int i;
-
- printk(KERN_INFO "sx%d: port %d: FIFO hits [ ",
- board_No(bp), port_No(port));
+ if (sx_debug & SX_DEBUG_FIFO) {
+ dprintk(SX_DEBUG_FIFO, "sx%d: port %d: %ld overruns, FIFO hits [ ",
+ board_No(bp), port_No(port), port->overrun);
for (i = 0; i < 10; i++) {
- printk("%ld ", port->hits[i]);
+ dprintk(SX_DEBUG_FIFO, "%ld ", port->hits[i]);
}
- printk("].\n");
+ dprintk(SX_DEBUG_FIFO, "].\n");
}
-#endif
+
if (port->xmit_buf) {
free_page((unsigned long) port->xmit_buf);
port->xmit_buf = NULL;
}
/* Select port */
+ spin_lock_irqsave(&bp->lock, flags);
sx_out(bp, CD186x_CAR, port_No(port));
if (!(tty = port->tty) || C_HUPCL(tty)) {
/* Drop DTR */
sx_out(bp, CD186x_MSVDTR, 0);
}
-
+ spin_unlock_irqrestore(&bp->lock, flags);
/* Reset port */
sx_wait_CCR(bp);
+ spin_lock_irqsave(&bp->lock, flags);
sx_out(bp, CD186x_CCR, CCR_SOFTRESET);
/* Disable all interrupts from this port */
port->IER = 0;
sx_out(bp, CD186x_IER, port->IER);
-
+ spin_unlock_irqrestore(&bp->lock, flags);
if (tty)
set_bit(TTY_IO_ERROR, &tty->flags);
port->flags &= ~ASYNC_INITIALIZED;
- if (--bp->count < 0) {
- printk(KERN_ERR "sx%d: sx_shutdown_port: bad board count: %d\n",
- board_No(bp), bp->count);
- bp->count = 0;
- }
-
- /*
- * If this is the last opened port on the board
- * shutdown whole board
- */
if (!bp->count)
sx_shutdown_board(bp);
+ func_exit();
}
@@ -1268,6 +1409,9 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
int retval;
int do_clocal = 0;
int CD;
+ unsigned long flags;
+
+ func_enter();
/*
* If the device is in the middle of being closed, then block
@@ -1275,10 +1419,13 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
*/
if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) {
interruptible_sleep_on(&port->close_wait);
- if (port->flags & ASYNC_HUP_NOTIFY)
+ if (port->flags & ASYNC_HUP_NOTIFY) {
+ func_exit();
return -EAGAIN;
- else
+ } else {
+ func_exit();
return -ERESTARTSYS;
+ }
}
/*
@@ -1288,6 +1435,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
if ((filp->f_flags & O_NONBLOCK) ||
(tty->flags & (1 << TTY_IO_ERROR))) {
port->flags |= ASYNC_NORMAL_ACTIVE;
+ func_exit();
return 0;
}
@@ -1303,13 +1451,14 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
*/
retval = 0;
add_wait_queue(&port->open_wait, &wait);
- cli();
- if (!tty_hung_up_p(filp))
+ spin_lock_irqsave(&port->lock, flags);
+ if (!tty_hung_up_p(filp)) {
port->count--;
- sti();
+ }
+ spin_unlock_irqrestore(&port->lock, flags);
port->blocked_open++;
while (1) {
- cli();
+ spin_lock_irqsave(&bp->lock, flags);
sx_out(bp, CD186x_CAR, port_No(port));
CD = sx_in(bp, CD186x_MSVR) & MSVR_CD;
if (SX_CRTSCTS (tty)) {
@@ -1320,8 +1469,8 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
/* Activate DTR */
port->MSVR |= MSVR_DTR;
sx_out (bp, CD186x_MSVR, port->MSVR);
- }
- sti();
+ }
+ spin_unlock_irqrestore(&bp->lock, flags);
set_current_state(TASK_INTERRUPTIBLE);
if (tty_hung_up_p(filp) ||
!(port->flags & ASYNC_INITIALIZED)) {
@@ -1340,15 +1489,22 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
}
schedule();
}
- current->state = TASK_RUNNING;
+
+ set_current_state(TASK_RUNNING);
remove_wait_queue(&port->open_wait, &wait);
- if (!tty_hung_up_p(filp))
+ spin_lock_irqsave(&port->lock, flags);
+ if (!tty_hung_up_p(filp)) {
port->count++;
+ }
port->blocked_open--;
- if (retval)
+ spin_unlock_irqrestore(&port->lock, flags);
+ if (retval) {
+ func_exit();
return retval;
-
+ }
+
port->flags |= ASYNC_NORMAL_ACTIVE;
+ func_exit();
return 0;
}
@@ -1359,36 +1515,55 @@ static int sx_open(struct tty_struct * tty, struct file * filp)
int error;
struct specialix_port * port;
struct specialix_board * bp;
-
+ int i;
+ unsigned long flags;
+
+ func_enter();
+
board = SX_BOARD(tty->index);
- if (board >= SX_NBOARD || !(sx_board[board].flags & SX_BOARD_PRESENT))
+ if (board >= SX_NBOARD || !(sx_board[board].flags & SX_BOARD_PRESENT)) {
+ func_exit();
return -ENODEV;
+ }
bp = &sx_board[board];
port = sx_port + board * SX_NPORT + SX_PORT(tty->index);
+ port->overrun = 0;
+ for (i = 0; i < 10; i++)
+ port->hits[i]=0;
-#ifdef DEBUG_SPECIALIX
- printk (KERN_DEBUG "Board = %d, bp = %p, port = %p, portno = %d.\n",
+ dprintk (SX_DEBUG_OPEN, "Board = %d, bp = %p, port = %p, portno = %d.\n",
board, bp, port, SX_PORT(tty->index));
-#endif
- if (sx_paranoia_check(port, tty->name, "sx_open"))
+ if (sx_paranoia_check(port, tty->name, "sx_open")) {
+ func_enter();
return -ENODEV;
+ }
- if ((error = sx_setup_board(bp)))
+ if ((error = sx_setup_board(bp))) {
+ func_exit();
return error;
+ }
+ spin_lock_irqsave(&bp->lock, flags);
port->count++;
+ bp->count++;
tty->driver_data = port;
port->tty = tty;
+ spin_unlock_irqrestore(&bp->lock, flags);
- if ((error = sx_setup_port(bp, port)))
+ if ((error = sx_setup_port(bp, port))) {
+ func_enter();
return error;
+ }
- if ((error = block_til_ready(tty, filp, port)))
+ if ((error = block_til_ready(tty, filp, port))) {
+ func_enter();
return error;
+ }
+ func_exit();
return 0;
}
@@ -1400,12 +1575,16 @@ static void sx_close(struct tty_struct * tty, struct file * filp)
unsigned long flags;
unsigned long timeout;
- if (!port || sx_paranoia_check(port, tty->name, "close"))
+ func_enter();
+ if (!port || sx_paranoia_check(port, tty->name, "close")) {
+ func_exit();
return;
-
- save_flags(flags); cli();
+ }
+ spin_lock_irqsave(&port->lock, flags);
+
if (tty_hung_up_p(filp)) {
- restore_flags(flags);
+ spin_unlock_irqrestore(&port->lock, flags);
+ func_exit();
return;
}
@@ -1416,13 +1595,14 @@ static void sx_close(struct tty_struct * tty, struct file * filp)
board_No(bp), port->count);
port->count = 1;
}
- if (--port->count < 0) {
- printk(KERN_ERR "sx%d: sx_close: bad port count for tty%d: %d\n",
- board_No(bp), port_No(port), port->count);
- port->count = 0;
- }
- if (port->count) {
- restore_flags(flags);
+
+ if (port->count > 1) {
+ port->count--;
+ bp->count--;
+
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ func_exit();
return;
}
port->flags |= ASYNC_CLOSING;
@@ -1431,20 +1611,26 @@ static void sx_close(struct tty_struct * tty, struct file * filp)
* the line discipline to only process XON/XOFF characters.
*/
tty->closing = 1;
- if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
+ spin_unlock_irqrestore(&port->lock, flags);
+ dprintk (SX_DEBUG_OPEN, "Closing\n");
+ if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE) {
tty_wait_until_sent(tty, port->closing_wait);
+ }
/*
* At this point we stop accepting input. To do this, we
* disable the receive line status interrupts, and tell the
* interrupt driver to stop checking the data ready bit in the
* line status register.
*/
+ dprintk (SX_DEBUG_OPEN, "Closed\n");
port->IER &= ~IER_RXD;
if (port->flags & ASYNC_INITIALIZED) {
port->IER &= ~IER_TXRDY;
port->IER |= IER_TXEMPTY;
+ spin_lock_irqsave(&bp->lock, flags);
sx_out(bp, CD186x_CAR, port_No(port));
sx_out(bp, CD186x_IER, port->IER);
+ spin_unlock_irqrestore(&bp->lock, flags);
/*
* Before we drop DTR, make sure the UART transmitter
* has completely drained; this is especially
@@ -1452,6 +1638,7 @@ static void sx_close(struct tty_struct * tty, struct file * filp)
*/
timeout = jiffies+HZ;
while(port->IER & IER_TXEMPTY) {
+ set_current_state (TASK_INTERRUPTIBLE);
msleep_interruptible(jiffies_to_msecs(port->timeout));
if (time_after(jiffies, timeout)) {
printk (KERN_INFO "Timeout waiting for close\n");
@@ -1460,13 +1647,27 @@ static void sx_close(struct tty_struct * tty, struct file * filp)
}
}
+
+ if (--bp->count < 0) {
+ printk(KERN_ERR "sx%d: sx_shutdown_port: bad board count: %d port: %d\n",
+ board_No(bp), bp->count, tty->index);
+ bp->count = 0;
+ }
+ if (--port->count < 0) {
+ printk(KERN_ERR "sx%d: sx_close: bad port count for tty%d: %d\n",
+ board_No(bp), port_No(port), port->count);
+ port->count = 0;
+ }
+
sx_shutdown_port(bp, port);
if (tty->driver->flush_buffer)
tty->driver->flush_buffer(tty);
tty_ldisc_flush(tty);
+ spin_lock_irqsave(&port->lock, flags);
tty->closing = 0;
port->event = 0;
port->tty = NULL;
+ spin_unlock_irqrestore(&port->lock, flags);
if (port->blocked_open) {
if (port->close_delay) {
msleep_interruptible(jiffies_to_msecs(port->close_delay));
@@ -1475,7 +1676,8 @@ static void sx_close(struct tty_struct * tty, struct file * filp)
}
port->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
wake_up_interruptible(&port->close_wait);
- restore_flags(flags);
+
+ func_exit();
}
@@ -1486,42 +1688,48 @@ static int sx_write(struct tty_struct * tty,
struct specialix_board *bp;
int c, total = 0;
unsigned long flags;
-
- if (sx_paranoia_check(port, tty->name, "sx_write"))
+
+ func_enter();
+ if (sx_paranoia_check(port, tty->name, "sx_write")) {
+ func_exit();
return 0;
+ }
bp = port_Board(port);
- if (!tty || !port->xmit_buf || !tmp_buf)
+ if (!tty || !port->xmit_buf || !tmp_buf) {
+ func_exit();
return 0;
+ }
- save_flags(flags);
while (1) {
- cli();
+ spin_lock_irqsave(&port->lock, flags);
c = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
SERIAL_XMIT_SIZE - port->xmit_head));
if (c <= 0) {
- restore_flags(flags);
+ spin_unlock_irqrestore(&port->lock, flags);
break;
}
memcpy(port->xmit_buf + port->xmit_head, buf, c);
port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
port->xmit_cnt += c;
- restore_flags(flags);
+ spin_unlock_irqrestore(&port->lock, flags);
buf += c;
count -= c;
total += c;
}
- cli();
+ spin_lock_irqsave(&bp->lock, flags);
if (port->xmit_cnt && !tty->stopped && !tty->hw_stopped &&
!(port->IER & IER_TXRDY)) {
port->IER |= IER_TXRDY;
sx_out(bp, CD186x_CAR, port_No(port));
sx_out(bp, CD186x_IER, port->IER);
}
- restore_flags(flags);
+ spin_unlock_irqrestore(&bp->lock, flags);
+ func_exit();
+
return total;
}
@@ -1530,24 +1738,36 @@ static void sx_put_char(struct tty_struct * tty, unsigned char ch)
{
struct specialix_port *port = (struct specialix_port *)tty->driver_data;
unsigned long flags;
+ struct specialix_board * bp;
- if (sx_paranoia_check(port, tty->name, "sx_put_char"))
- return;
+ func_enter();
- if (!tty || !port->xmit_buf)
+ if (sx_paranoia_check(port, tty->name, "sx_put_char")) {
+ func_exit();
return;
-
- save_flags(flags); cli();
-
- if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1) {
- restore_flags(flags);
+ }
+ dprintk (SX_DEBUG_TX, "check tty: %p %p\n", tty, port->xmit_buf);
+ if (!tty || !port->xmit_buf) {
+ func_exit();
return;
}
+ bp = port_Board(port);
+ spin_lock_irqsave(&port->lock, flags);
+ dprintk (SX_DEBUG_TX, "xmit_cnt: %d xmit_buf: %p\n", port->xmit_cnt, port->xmit_buf);
+ if ((port->xmit_cnt >= SERIAL_XMIT_SIZE - 1) || (!port->xmit_buf)) {
+ spin_unlock_irqrestore(&port->lock, flags);
+ dprintk (SX_DEBUG_TX, "Exit size\n");
+ func_exit();
+ return;
+ }
+ dprintk (SX_DEBUG_TX, "Handle xmit: %p %p\n", port, port->xmit_buf);
port->xmit_buf[port->xmit_head++] = ch;
port->xmit_head &= SERIAL_XMIT_SIZE - 1;
port->xmit_cnt++;
- restore_flags(flags);
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ func_exit();
}
@@ -1555,19 +1775,26 @@ static void sx_flush_chars(struct tty_struct * tty)
{
struct specialix_port *port = (struct specialix_port *)tty->driver_data;
unsigned long flags;
-
- if (sx_paranoia_check(port, tty->name, "sx_flush_chars"))
+ struct specialix_board * bp = port_Board(port);
+
+ func_enter();
+
+ if (sx_paranoia_check(port, tty->name, "sx_flush_chars")) {
+ func_exit();
return;
-
+ }
if (port->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
- !port->xmit_buf)
+ !port->xmit_buf) {
+ func_exit();
return;
-
- save_flags(flags); cli();
+ }
+ spin_lock_irqsave(&bp->lock, flags);
port->IER |= IER_TXRDY;
sx_out(port_Board(port), CD186x_CAR, port_No(port));
sx_out(port_Board(port), CD186x_IER, port->IER);
- restore_flags(flags);
+ spin_unlock_irqrestore(&bp->lock, flags);
+
+ func_exit();
}
@@ -1575,13 +1802,19 @@ static int sx_write_room(struct tty_struct * tty)
{
struct specialix_port *port = (struct specialix_port *)tty->driver_data;
int ret;
-
- if (sx_paranoia_check(port, tty->name, "sx_write_room"))
+
+ func_enter();
+
+ if (sx_paranoia_check(port, tty->name, "sx_write_room")) {
+ func_exit();
return 0;
+ }
ret = SERIAL_XMIT_SIZE - port->xmit_cnt - 1;
if (ret < 0)
ret = 0;
+
+ func_exit();
return ret;
}
@@ -1589,10 +1822,14 @@ static int sx_write_room(struct tty_struct * tty)
static int sx_chars_in_buffer(struct tty_struct *tty)
{
struct specialix_port *port = (struct specialix_port *)tty->driver_data;
-
- if (sx_paranoia_check(port, tty->name, "sx_chars_in_buffer"))
- return 0;
+
+ func_enter();
+ if (sx_paranoia_check(port, tty->name, "sx_chars_in_buffer")) {
+ func_exit();
+ return 0;
+ }
+ func_exit();
return port->xmit_cnt;
}
@@ -1601,16 +1838,22 @@ static void sx_flush_buffer(struct tty_struct *tty)
{
struct specialix_port *port = (struct specialix_port *)tty->driver_data;
unsigned long flags;
-
- if (sx_paranoia_check(port, tty->name, "sx_flush_buffer"))
+ struct specialix_board * bp;
+
+ func_enter();
+
+ if (sx_paranoia_check(port, tty->name, "sx_flush_buffer")) {
+ func_exit();
return;
+ }
- save_flags(flags); cli();
+ bp = port_Board(port);
+ spin_lock_irqsave(&port->lock, flags);
port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
- restore_flags(flags);
-
+ spin_unlock_irqrestore(&port->lock, flags);
tty_wakeup(tty);
- wake_up_interruptible(&tty->write_wait);
+
+ func_exit();
}
@@ -1622,19 +1865,21 @@ static int sx_tiocmget(struct tty_struct *tty, struct file *file)
unsigned int result;
unsigned long flags;
- if (sx_paranoia_check(port, tty->name, __FUNCTION__))
+ func_enter();
+
+ if (sx_paranoia_check(port, tty->name, __FUNCTION__)) {
+ func_exit();
return -ENODEV;
+ }
bp = port_Board(port);
- save_flags(flags); cli();
+ spin_lock_irqsave (&bp->lock, flags);
sx_out(bp, CD186x_CAR, port_No(port));
status = sx_in(bp, CD186x_MSVR);
- restore_flags(flags);
-#ifdef DEBUG_SPECIALIX
- printk (KERN_DEBUG "Got msvr[%d] = %02x, car = %d.\n",
+ spin_unlock_irqrestore(&bp->lock, flags);
+ dprintk (SX_DEBUG_INIT, "Got msvr[%d] = %02x, car = %d.\n",
port_No(port), status, sx_in (bp, CD186x_CAR));
- printk (KERN_DEBUG "sx_port = %p, port = %p\n", sx_port, port);
-#endif
+ dprintk (SX_DEBUG_INIT, "sx_port = %p, port = %p\n", sx_port, port);
if (SX_CRTSCTS(port->tty)) {
result = /* (status & MSVR_RTS) ? */ TIOCM_DTR /* : 0) */
| ((status & MSVR_DTR) ? TIOCM_RTS : 0)
@@ -1649,6 +1894,8 @@ static int sx_tiocmget(struct tty_struct *tty, struct file *file)
| ((status & MSVR_CTS) ? TIOCM_CTS : 0);
}
+ func_exit();
+
return result;
}
@@ -1660,12 +1907,16 @@ static int sx_tiocmset(struct tty_struct *tty, struct file *file,
unsigned long flags;
struct specialix_board *bp;
- if (sx_paranoia_check(port, tty->name, __FUNCTION__))
+ func_enter();
+
+ if (sx_paranoia_check(port, tty->name, __FUNCTION__)) {
+ func_exit();
return -ENODEV;
+ }
bp = port_Board(port);
- save_flags(flags); cli();
+ spin_lock_irqsave(&port->lock, flags);
/* if (set & TIOCM_RTS)
port->MSVR |= MSVR_RTS; */
/* if (set & TIOCM_DTR)
@@ -1690,10 +1941,12 @@ static int sx_tiocmset(struct tty_struct *tty, struct file *file,
if (clear & TIOCM_DTR)
port->MSVR &= ~MSVR_DTR;
}
-
+ spin_lock_irqsave(&bp->lock, flags);
sx_out(bp, CD186x_CAR, port_No(port));
sx_out(bp, CD186x_MSVR, port->MSVR);
- restore_flags(flags);
+ spin_unlock_irqrestore(&bp->lock, flags);
+ spin_unlock_irqrestore(&port->lock, flags);
+ func_exit();
return 0;
}
@@ -1703,17 +1956,25 @@ static inline void sx_send_break(struct specialix_port * port, unsigned long len
struct specialix_board *bp = port_Board(port);
unsigned long flags;
- save_flags(flags); cli();
+ func_enter();
+
+ spin_lock_irqsave (&port->lock, flags);
port->break_length = SPECIALIX_TPS / HZ * length;
port->COR2 |= COR2_ETC;
port->IER |= IER_TXRDY;
+ spin_lock_irqsave(&bp->lock, flags);
sx_out(bp, CD186x_CAR, port_No(port));
sx_out(bp, CD186x_COR2, port->COR2);
sx_out(bp, CD186x_IER, port->IER);
+ spin_unlock_irqrestore(&bp->lock, flags);
+ spin_unlock_irqrestore (&port->lock, flags);
sx_wait_CCR(bp);
+ spin_lock_irqsave(&bp->lock, flags);
sx_out(bp, CD186x_CCR, CCR_CORCHG2);
+ spin_unlock_irqrestore(&bp->lock, flags);
sx_wait_CCR(bp);
- restore_flags(flags);
+
+ func_exit();
}
@@ -1723,10 +1984,19 @@ static inline int sx_set_serial_info(struct specialix_port * port,
struct serial_struct tmp;
struct specialix_board *bp = port_Board(port);
int change_speed;
- unsigned long flags;
-
- if (copy_from_user(&tmp, newinfo, sizeof(tmp)))
+
+ func_enter();
+ /*
+ error = verify_area(VERIFY_READ, (void *) newinfo, sizeof(tmp));
+ if (error) {
+ func_exit();
+ return error;
+ }
+ */
+ if (copy_from_user(&tmp, newinfo, sizeof(tmp))) {
+ func_enter();
return -EFAULT;
+ }
#if 0
if ((tmp.irq != bp->irq) ||
@@ -1735,8 +2005,10 @@ static inline int sx_set_serial_info(struct specialix_port * port,
(tmp.baud_base != (SX_OSCFREQ + CD186x_TPC/2) / CD186x_TPC) ||
(tmp.custom_divisor != 0) ||
(tmp.xmit_fifo_size != CD186x_NFIFO) ||
- (tmp.flags & ~SPECIALIX_LEGAL_FLAGS))
+ (tmp.flags & ~SPECIALIX_LEGAL_FLAGS)) {
+ func_exit();
return -EINVAL;
+ }
#endif
change_speed = ((port->flags & ASYNC_SPD_MASK) !=
@@ -1747,8 +2019,10 @@ static inline int sx_set_serial_info(struct specialix_port * port,
if ((tmp.close_delay != port->close_delay) ||
(tmp.closing_wait != port->closing_wait) ||
((tmp.flags & ~ASYNC_USR_MASK) !=
- (port->flags & ~ASYNC_USR_MASK)))
+ (port->flags & ~ASYNC_USR_MASK))) {
+ func_exit();
return -EPERM;
+ }
port->flags = ((port->flags & ~ASYNC_USR_MASK) |
(tmp.flags & ASYNC_USR_MASK));
port->custom_divisor = tmp.custom_divisor;
@@ -1760,10 +2034,9 @@ static inline int sx_set_serial_info(struct specialix_port * port,
port->custom_divisor = tmp.custom_divisor;
}
if (change_speed) {
- save_flags(flags); cli();
sx_change_speed(bp, port);
- restore_flags(flags);
}
+ func_exit();
return 0;
}
@@ -1773,7 +2046,16 @@ static inline int sx_get_serial_info(struct specialix_port * port,
{
struct serial_struct tmp;
struct specialix_board *bp = port_Board(port);
+ // int error;
+ func_enter();
+
+ /*
+ error = verify_area(VERIFY_WRITE, (void *) retinfo, sizeof(tmp));
+ if (error)
+ return error;
+ */
+
memset(&tmp, 0, sizeof(tmp));
tmp.type = PORT_CIRRUS;
tmp.line = port - sx_port;
@@ -1785,8 +2067,12 @@ static inline int sx_get_serial_info(struct specialix_port * port,
tmp.closing_wait = port->closing_wait * HZ/100;
tmp.custom_divisor = port->custom_divisor;
tmp.xmit_fifo_size = CD186x_NFIFO;
- if (copy_to_user(retinfo, &tmp, sizeof(tmp)))
+ if (copy_to_user(retinfo, &tmp, sizeof(tmp))) {
+ func_exit();
return -EFAULT;
+ }
+
+ func_exit();
return 0;
}
@@ -1797,44 +2083,63 @@ static int sx_ioctl(struct tty_struct * tty, struct file * filp,
struct specialix_port *port = (struct specialix_port *)tty->driver_data;
int retval;
void __user *argp = (void __user *)arg;
-
- if (sx_paranoia_check(port, tty->name, "sx_ioctl"))
+
+ func_enter();
+
+ if (sx_paranoia_check(port, tty->name, "sx_ioctl")) {
+ func_exit();
return -ENODEV;
+ }
switch (cmd) {
case TCSBRK: /* SVID version: non-zero arg --> no break */
retval = tty_check_change(tty);
- if (retval)
+ if (retval) {
+ func_exit();
return retval;
+ }
tty_wait_until_sent(tty, 0);
if (!arg)
sx_send_break(port, HZ/4); /* 1/4 second */
return 0;
case TCSBRKP: /* support for POSIX tcsendbreak() */
retval = tty_check_change(tty);
- if (retval)
+ if (retval) {
+ func_exit();
return retval;
+ }
tty_wait_until_sent(tty, 0);
sx_send_break(port, arg ? arg*(HZ/10) : HZ/4);
+ func_exit();
return 0;
case TIOCGSOFTCAR:
- if (put_user(C_CLOCAL(tty)?1:0, (unsigned long __user *)argp))
- return -EFAULT;
+ if (put_user(C_CLOCAL(tty)?1:0, (unsigned long __user *)argp)) {
+ func_exit();
+ return -EFAULT;
+ }
+ func_exit();
return 0;
case TIOCSSOFTCAR:
- if (get_user(arg, (unsigned long __user *) argp))
- return -EFAULT;
+ if (get_user(arg, (unsigned long __user *) argp)) {
+ func_exit();
+ return -EFAULT;
+ }
tty->termios->c_cflag =
((tty->termios->c_cflag & ~CLOCAL) |
(arg ? CLOCAL : 0));
+ func_exit();
return 0;
- case TIOCGSERIAL:
+ case TIOCGSERIAL:
+ func_exit();
return sx_get_serial_info(port, argp);
case TIOCSSERIAL:
+ func_exit();
return sx_set_serial_info(port, argp);
default:
+ func_exit();
return -ENOIOCTLCMD;
}
+ func_exit();
return 0;
}
@@ -1844,14 +2149,16 @@ static void sx_throttle(struct tty_struct * tty)
struct specialix_port *port = (struct specialix_port *)tty->driver_data;
struct specialix_board *bp;
unsigned long flags;
-
- if (sx_paranoia_check(port, tty->name, "sx_throttle"))
+
+ func_enter();
+
+ if (sx_paranoia_check(port, tty->name, "sx_throttle")) {
+ func_exit();
return;
+ }
bp = port_Board(port);
- save_flags(flags); cli();
-
/* Use DTR instead of RTS ! */
if (SX_CRTSCTS (tty))
port->MSVR &= ~MSVR_DTR;
@@ -1863,14 +2170,22 @@ static void sx_throttle(struct tty_struct * tty)
printk (KERN_ERR "sx%d: Need to throttle, but can't (hardware hs is off)\n",
port_No (port));
}
+ spin_lock_irqsave(&bp->lock, flags);
sx_out(bp, CD186x_CAR, port_No(port));
+ spin_unlock_irqrestore(&bp->lock, flags);
if (I_IXOFF(tty)) {
+ spin_unlock_irqrestore(&bp->lock, flags);
sx_wait_CCR(bp);
+ spin_lock_irqsave(&bp->lock, flags);
sx_out(bp, CD186x_CCR, CCR_SSCH2);
+ spin_unlock_irqrestore(&bp->lock, flags);
sx_wait_CCR(bp);
}
+ spin_lock_irqsave(&bp->lock, flags);
sx_out(bp, CD186x_MSVR, port->MSVR);
- restore_flags(flags);
+ spin_unlock_irqrestore(&bp->lock, flags);
+
+ func_exit();
}
@@ -1879,26 +2194,39 @@ static void sx_unthrottle(struct tty_struct * tty)
struct specialix_port *port = (struct specialix_port *)tty->driver_data;
struct specialix_board *bp;
unsigned long flags;
+
+ func_enter();
- if (sx_paranoia_check(port, tty->name, "sx_unthrottle"))
+ if (sx_paranoia_check(port, tty->name, "sx_unthrottle")) {
+ func_exit();
return;
+ }
bp = port_Board(port);
- save_flags(flags); cli();
+ spin_lock_irqsave(&port->lock, flags);
/* XXXX Use DTR INSTEAD???? */
if (SX_CRTSCTS(tty)) {
port->MSVR |= MSVR_DTR;
} /* Else clause: see remark in "sx_throttle"... */
-
+ spin_lock_irqsave(&bp->lock, flags);
sx_out(bp, CD186x_CAR, port_No(port));
+ spin_unlock_irqrestore(&bp->lock, flags);
if (I_IXOFF(tty)) {
+ spin_unlock_irqrestore(&port->lock, flags);
sx_wait_CCR(bp);
+ spin_lock_irqsave(&bp->lock, flags);
sx_out(bp, CD186x_CCR, CCR_SSCH1);
+ spin_unlock_irqrestore(&bp->lock, flags);
sx_wait_CCR(bp);
+ spin_lock_irqsave(&port->lock, flags);
}
+ spin_lock_irqsave(&bp->lock, flags);
sx_out(bp, CD186x_MSVR, port->MSVR);
- restore_flags(flags);
+ spin_unlock_irqrestore(&bp->lock, flags);
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ func_exit();
}
@@ -1907,17 +2235,25 @@ static void sx_stop(struct tty_struct * tty)
struct specialix_port *port = (struct specialix_port *)tty->driver_data;
struct specialix_board *bp;
unsigned long flags;
-
- if (sx_paranoia_check(port, tty->name, "sx_stop"))
- return;
+
+ func_enter();
+ if (sx_paranoia_check(port, tty->name, "sx_stop")) {
+ func_exit();
+ return;
+ }
+
bp = port_Board(port);
- save_flags(flags); cli();
+ spin_lock_irqsave(&port->lock, flags);
port->IER &= ~IER_TXRDY;
+ spin_lock_irqsave(&bp->lock, flags);
sx_out(bp, CD186x_CAR, port_No(port));
sx_out(bp, CD186x_IER, port->IER);
- restore_flags(flags);
+ spin_unlock_irqrestore(&bp->lock, flags);
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ func_exit();
}
@@ -1926,19 +2262,27 @@ static void sx_start(struct tty_struct * tty)
struct specialix_port *port = (struct specialix_port *)tty->driver_data;
struct specialix_board *bp;
unsigned long flags;
+
+ func_enter();
- if (sx_paranoia_check(port, tty->name, "sx_start"))
+ if (sx_paranoia_check(port, tty->name, "sx_start")) {
+ func_exit();
return;
+ }
bp = port_Board(port);
- save_flags(flags); cli();
+ spin_lock_irqsave(&port->lock, flags);
if (port->xmit_cnt && port->xmit_buf && !(port->IER & IER_TXRDY)) {
port->IER |= IER_TXRDY;
+ spin_lock_irqsave(&bp->lock, flags);
sx_out(bp, CD186x_CAR, port_No(port));
sx_out(bp, CD186x_IER, port->IER);
+ spin_unlock_irqrestore(&bp->lock, flags);
}
- restore_flags(flags);
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ func_exit();
}
@@ -1956,9 +2300,13 @@ static void do_sx_hangup(void *private_)
struct specialix_port *port = (struct specialix_port *) private_;
struct tty_struct *tty;
+ func_enter();
+
tty = port->tty;
if (tty)
tty_hangup(tty); /* FIXME: module removal race here */
+
+ func_exit();
}
@@ -1966,18 +2314,33 @@ static void sx_hangup(struct tty_struct * tty)
{
struct specialix_port *port = (struct specialix_port *)tty->driver_data;
struct specialix_board *bp;
-
- if (sx_paranoia_check(port, tty->name, "sx_hangup"))
+ unsigned long flags;
+
+ func_enter();
+
+ if (sx_paranoia_check(port, tty->name, "sx_hangup")) {
+ func_exit();
return;
+ }
bp = port_Board(port);
sx_shutdown_port(bp, port);
+ spin_lock_irqsave(&port->lock, flags);
port->event = 0;
+ bp->count -= port->count;
+ if (bp->count < 0) {
+ printk(KERN_ERR "sx%d: sx_hangup: bad board count: %d port: %d\n",
+ board_No(bp), bp->count, tty->index);
+ bp->count = 0;
+ }
port->count = 0;
port->flags &= ~ASYNC_NORMAL_ACTIVE;
port->tty = NULL;
+ spin_unlock_irqrestore(&port->lock, flags);
wake_up_interruptible(&port->open_wait);
+
+ func_exit();
}
@@ -1985,6 +2348,7 @@ static void sx_set_termios(struct tty_struct * tty, struct termios * old_termios
{
struct specialix_port *port = (struct specialix_port *)tty->driver_data;
unsigned long flags;
+ struct specialix_board * bp;
if (sx_paranoia_check(port, tty->name, "sx_set_termios"))
return;
@@ -1993,9 +2357,10 @@ static void sx_set_termios(struct tty_struct * tty, struct termios * old_termios
tty->termios->c_iflag == old_termios->c_iflag)
return;
- save_flags(flags); cli();
+ bp = port_Board(port);
+ spin_lock_irqsave(&port->lock, flags);
sx_change_speed(port_Board(port), port);
- restore_flags(flags);
+ spin_unlock_irqrestore(&port->lock, flags);
if ((old_termios->c_cflag & CRTSCTS) &&
!(tty->termios->c_cflag & CRTSCTS)) {
@@ -2009,12 +2374,20 @@ static void do_softint(void *private_)
{
struct specialix_port *port = (struct specialix_port *) private_;
struct tty_struct *tty;
-
- if(!(tty = port->tty))
+
+ func_enter();
+
+ if(!(tty = port->tty)) {
+ func_exit();
return;
+ }
+
+ if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &port->event)) {
+ tty_wakeup(tty);
+ //wake_up_interruptible(&tty->write_wait);
+ }
- if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &port->event))
- tty_wakeup(tty);
+ func_exit();
}
static struct tty_operations sx_ops = {
@@ -2042,15 +2415,19 @@ static int sx_init_drivers(void)
int error;
int i;
+ func_enter();
+
specialix_driver = alloc_tty_driver(SX_NBOARD * SX_NPORT);
if (!specialix_driver) {
printk(KERN_ERR "sx: Couldn't allocate tty_driver.\n");
+ func_exit();
return 1;
}
if (!(tmp_buf = (unsigned char *) get_zeroed_page(GFP_KERNEL))) {
printk(KERN_ERR "sx: Couldn't get free page.\n");
put_tty_driver(specialix_driver);
+ func_exit();
return 1;
}
specialix_driver->owner = THIS_MODULE;
@@ -2069,6 +2446,7 @@ static int sx_init_drivers(void)
free_page((unsigned long)tmp_buf);
printk(KERN_ERR "sx: Couldn't register specialix IO8+ driver, error = %d\n",
error);
+ func_exit();
return 1;
}
memset(sx_port, 0, sizeof(sx_port));
@@ -2080,47 +2458,23 @@ static int sx_init_drivers(void)
sx_port[i].closing_wait = 3000 * HZ/100;
init_waitqueue_head(&sx_port[i].open_wait);
init_waitqueue_head(&sx_port[i].close_wait);
+ spin_lock_init(&sx_port[i].lock);
}
+ func_exit();
return 0;
}
-
static void sx_release_drivers(void)
{
+ func_enter();
+
free_page((unsigned long)tmp_buf);
tty_unregister_driver(specialix_driver);
put_tty_driver(specialix_driver);
+ func_exit();
}
-
-#ifndef MODULE
-/*
- * Called at boot time.
- *
- * You can specify IO base for up to SX_NBOARD cards,
- * using line "specialix=0xiobase1,0xiobase2,.." at LILO prompt.
- * Note that there will be no probing at default
- * addresses in this case.
- *
- */
-void specialix_setup(char *str, int * ints)
-{
- int i;
-
- for (i=0;i<SX_NBOARD;i++) {
- sx_board[i].base = 0;
- }
-
- for (i = 1; i <= ints[0]; i++) {
- if (i&1)
- sx_board[i/2].base = ints[i];
- else
- sx_board[i/2 -1].irq = ints[i];
- }
-}
-#endif
-
/*
* This routine must be called by kernel at boot time
*/
@@ -2129,6 +2483,8 @@ static int __init specialix_init(void)
int i;
int found = 0;
+ func_enter();
+
printk(KERN_INFO "sx: Specialix IO8+ driver v" VERSION ", (c) R.E.Wolff 1997/1998.\n");
printk(KERN_INFO "sx: derived from work (c) D.Gorodchanin 1994-1996.\n");
#ifdef CONFIG_SPECIALIX_RTSCTS
@@ -2137,8 +2493,13 @@ static int __init specialix_init(void)
printk (KERN_INFO "sx: DTR/RTS pin is RTS when CRTSCTS is on.\n");
#endif
- if (sx_init_drivers())
+ for (i = 0; i < SX_NBOARD; i++)
+ sx_board[i].lock = SPIN_LOCK_UNLOCKED;
+
+ if (sx_init_drivers()) {
+ func_exit();
return -EIO;
+ }
for (i = 0; i < SX_NBOARD; i++)
if (sx_board[i].base && !sx_probe(&sx_board[i]))
@@ -2176,18 +2537,25 @@ static int __init specialix_init(void)
if (!found) {
sx_release_drivers();
printk(KERN_INFO "sx: No specialix IO8+ boards detected.\n");
+ func_exit();
return -EIO;
}
+ func_exit();
return 0;
}
-int iobase[SX_NBOARD] = {0,};
+static int iobase[SX_NBOARD] = {0,};
-int irq [SX_NBOARD] = {0,};
+static int irq [SX_NBOARD] = {0,};
module_param_array(iobase, int, NULL, 0);
module_param_array(irq, int, NULL, 0);
+module_param(sx_debug, int, 0);
+module_param(sx_rxfifo, int, 0);
+#ifdef SPECIALIX_TIMER
+module_param(sx_poll, int, 0);
+#endif
/*
* You can setup up to 4 boards.
@@ -2202,13 +2570,20 @@ static int __init specialix_init_module(void)
{
int i;
+ 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];
sx_board[i].irq = irq[i];
+ sx_board[i].count= 0;
}
}
+ func_exit();
+
return specialix_init();
}
@@ -2216,6 +2591,8 @@ static void __exit specialix_exit_module(void)
{
int i;
+ func_enter();
+
sx_release_drivers();
for (i = 0; i < SX_NBOARD; i++)
if (sx_board[i].flags & SX_BOARD_PRESENT)
@@ -2223,7 +2600,8 @@ static void __exit specialix_exit_module(void)
#ifdef SPECIALIX_TIMER
del_timer (&missed_irq_timer);
#endif
-
+
+ func_exit();
}
module_init(specialix_init_module);
diff --git a/drivers/char/specialix_io8.h b/drivers/char/specialix_io8.h
index 948ab1489e7a0..895bd90de3631 100644
--- a/drivers/char/specialix_io8.h
+++ b/drivers/char/specialix_io8.h
@@ -93,9 +93,11 @@ struct specialix_board {
unsigned long flags;
unsigned short base;
unsigned char irq;
- signed char count;
+ //signed char count;
+ int count;
unsigned char DTR;
int reg;
+ spinlock_t lock;
};
#define SX_BOARD_PRESENT 0x00000001
@@ -129,12 +131,9 @@ struct specialix_port {
unsigned char IER;
unsigned char MSVR;
unsigned char COR2;
-#ifdef SX_REPORT_OVERRUN
unsigned long overrun;
-#endif
-#ifdef SX_REPORT_FIFO
unsigned long hits[10];
-#endif
+ spinlock_t lock;
};
#endif /* __KERNEL__ */
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c
index 9a204da534460..de166608c59e5 100644
--- a/drivers/char/stallion.c
+++ b/drivers/char/stallion.c
@@ -174,14 +174,6 @@ static stlport_t stl_dummyport;
*/
static char stl_unwanted[SC26198_RXFIFOSIZE];
-/*
- * Keep track of what interrupts we have requested for us.
- * We don't need to request an interrupt twice if it is being
- * shared with another Stallion board.
- */
-static int stl_gotintrs[STL_MAXBRDS];
-static int stl_numintrs;
-
/*****************************************************************************/
static stlbrd_t *stl_brds[STL_MAXBRDS];
@@ -240,13 +232,12 @@ static char *stl_brdnames[] = {
/*****************************************************************************/
-#ifdef MODULE
/*
* Define some string labels for arguments passed from the module
* load line. These allow for easy board definitions, and easy
* modification of the io, memory and irq resoucres.
*/
-
+static int stl_nargs = 0;
static char *board0[4];
static char *board1[4];
static char *board2[4];
@@ -307,17 +298,15 @@ MODULE_AUTHOR("Greg Ungerer");
MODULE_DESCRIPTION("Stallion Multiport Serial Driver");
MODULE_LICENSE("GPL");
-MODULE_PARM(board0, "1-4s");
+module_param_array(board0, charp, &stl_nargs, 0);
MODULE_PARM_DESC(board0, "Board 0 config -> name[,ioaddr[,ioaddr2][,irq]]");
-MODULE_PARM(board1, "1-4s");
+module_param_array(board1, charp, &stl_nargs, 0);
MODULE_PARM_DESC(board1, "Board 1 config -> name[,ioaddr[,ioaddr2][,irq]]");
-MODULE_PARM(board2, "1-4s");
+module_param_array(board2, charp, &stl_nargs, 0);
MODULE_PARM_DESC(board2, "Board 2 config -> name[,ioaddr[,ioaddr2][,irq]]");
-MODULE_PARM(board3, "1-4s");
+module_param_array(board3, charp, &stl_nargs, 0);
MODULE_PARM_DESC(board3, "Board 3 config -> name[,ioaddr[,ioaddr2][,irq]]");
-#endif
-
/*****************************************************************************/
/*
@@ -472,12 +461,10 @@ static unsigned int stl_baudrates[] = {
* Declare all those functions in this driver!
*/
-#ifdef MODULE
static void stl_argbrds(void);
static int stl_parsebrd(stlconf_t *confp, char **argp);
static unsigned long stl_atol(char *str);
-#endif
int stl_init(void);
static int stl_open(struct tty_struct *tty, struct file *filp);
@@ -504,7 +491,6 @@ static int stl_readproc(char *page, char **start, off_t off, int count, int *eof
static int stl_brdinit(stlbrd_t *brdp);
static int stl_initports(stlbrd_t *brdp, stlpanel_t *panelp);
-static int stl_mapirq(int irq, char *name);
static int stl_getserial(stlport_t *portp, struct serial_struct __user *sp);
static int stl_setserial(stlport_t *portp, struct serial_struct __user *sp);
static int stl_getbrdstats(combrd_t __user *bp);
@@ -513,11 +499,11 @@ static int stl_clrportstats(stlport_t *portp, comstats_t __user *cp);
static int stl_getportstruct(stlport_t __user *arg);
static int stl_getbrdstruct(stlbrd_t __user *arg);
static int stl_waitcarrier(stlport_t *portp, struct file *filp);
-static void stl_eiointr(stlbrd_t *brdp);
-static void stl_echatintr(stlbrd_t *brdp);
-static void stl_echmcaintr(stlbrd_t *brdp);
-static void stl_echpciintr(stlbrd_t *brdp);
-static void stl_echpci64intr(stlbrd_t *brdp);
+static int stl_eiointr(stlbrd_t *brdp);
+static int stl_echatintr(stlbrd_t *brdp);
+static int stl_echmcaintr(stlbrd_t *brdp);
+static int stl_echpciintr(stlbrd_t *brdp);
+static int stl_echpci64intr(stlbrd_t *brdp);
static void stl_offintr(void *private);
static void *stl_memalloc(int len);
static stlbrd_t *stl_allocbrd(void);
@@ -735,8 +721,6 @@ static struct file_operations stl_fsiomem = {
static struct class_simple *stallion_class;
-#ifdef MODULE
-
/*
* Loadable module initialization stuff.
*/
@@ -807,6 +791,9 @@ static void __exit stallion_module_exit(void)
for (i = 0; (i < stl_nrbrds); i++) {
if ((brdp = stl_brds[i]) == (stlbrd_t *) NULL)
continue;
+
+ free_irq(brdp->irq, brdp);
+
for (j = 0; (j < STL_MAXPANELS); j++) {
panelp = brdp->panels[j];
if (panelp == (stlpanel_t *) NULL)
@@ -832,9 +819,6 @@ static void __exit stallion_module_exit(void)
stl_brds[i] = (stlbrd_t *) NULL;
}
- for (i = 0; (i < stl_numintrs); i++)
- free_irq(stl_gotintrs[i], NULL);
-
restore_flags(flags);
}
@@ -851,15 +835,13 @@ static void stl_argbrds(void)
{
stlconf_t conf;
stlbrd_t *brdp;
- int nrargs, i;
+ int i;
#ifdef DEBUG
printk("stl_argbrds()\n");
#endif
- nrargs = sizeof(stl_brdsp) / sizeof(char **);
-
- for (i = stl_nrbrds; (i < nrargs); i++) {
+ for (i = stl_nrbrds; (i < stl_nargs); i++) {
memset(&conf, 0, sizeof(conf));
if (stl_parsebrd(&conf, stl_brdsp[i]) == 0)
continue;
@@ -959,8 +941,6 @@ static int stl_parsebrd(stlconf_t *confp, char **argp)
return(1);
}
-#endif
-
/*****************************************************************************/
/*
@@ -1992,23 +1972,14 @@ stl_readdone:
static irqreturn_t stl_intr(int irq, void *dev_id, struct pt_regs *regs)
{
- stlbrd_t *brdp;
- int i;
- int handled = 0;
+ stlbrd_t *brdp = (stlbrd_t *) dev_id;
#ifdef DEBUG
- printk("stl_intr(irq=%d,regs=%x)\n", irq, (int) regs);
+ printk("stl_intr(brdp=%x,irq=%d,regs=%x)\n", (int) brdp, irq,
+ (int) regs);
#endif
- for (i = 0; (i < stl_nrbrds); i++) {
- if ((brdp = stl_brds[i]) == (stlbrd_t *) NULL)
- continue;
- if (brdp->state == 0)
- continue;
- handled = 1;
- (* brdp->isr)(brdp);
- }
- return IRQ_RETVAL(handled);
+ return IRQ_RETVAL((* brdp->isr)(brdp));
}
/*****************************************************************************/
@@ -2017,15 +1988,19 @@ static irqreturn_t stl_intr(int irq, void *dev_id, struct pt_regs *regs)
* Interrupt service routine for EasyIO board types.
*/
-static void stl_eiointr(stlbrd_t *brdp)
+static int stl_eiointr(stlbrd_t *brdp)
{
stlpanel_t *panelp;
unsigned int iobase;
+ int handled = 0;
panelp = brdp->panels[0];
iobase = panelp->iobase;
- while (inb(brdp->iostatus) & EIO_INTRPEND)
+ while (inb(brdp->iostatus) & EIO_INTRPEND) {
+ handled = 1;
(* panelp->isr)(panelp, iobase);
+ }
+ return handled;
}
/*****************************************************************************/
@@ -2034,15 +2009,17 @@ static void stl_eiointr(stlbrd_t *brdp)
* Interrupt service routine for ECH-AT board types.
*/
-static void stl_echatintr(stlbrd_t *brdp)
+static int stl_echatintr(stlbrd_t *brdp)
{
stlpanel_t *panelp;
unsigned int ioaddr;
int bnknr;
+ int handled = 0;
outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
while (inb(brdp->iostatus) & ECH_INTRPEND) {
+ handled = 1;
for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) {
ioaddr = brdp->bnkstataddr[bnknr];
if (inb(ioaddr) & ECH_PNLINTRPEND) {
@@ -2053,6 +2030,8 @@ static void stl_echatintr(stlbrd_t *brdp)
}
outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
+
+ return handled;
}
/*****************************************************************************/
@@ -2061,13 +2040,15 @@ static void stl_echatintr(stlbrd_t *brdp)
* Interrupt service routine for ECH-MCA board types.
*/
-static void stl_echmcaintr(stlbrd_t *brdp)
+static int stl_echmcaintr(stlbrd_t *brdp)
{
stlpanel_t *panelp;
unsigned int ioaddr;
int bnknr;
+ int handled = 0;
while (inb(brdp->iostatus) & ECH_INTRPEND) {
+ handled = 1;
for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) {
ioaddr = brdp->bnkstataddr[bnknr];
if (inb(ioaddr) & ECH_PNLINTRPEND) {
@@ -2076,6 +2057,7 @@ static void stl_echmcaintr(stlbrd_t *brdp)
}
}
}
+ return handled;
}
/*****************************************************************************/
@@ -2084,11 +2066,12 @@ static void stl_echmcaintr(stlbrd_t *brdp)
* Interrupt service routine for ECH-PCI board types.
*/
-static void stl_echpciintr(stlbrd_t *brdp)
+static int stl_echpciintr(stlbrd_t *brdp)
{
stlpanel_t *panelp;
unsigned int ioaddr;
int bnknr, recheck;
+ int handled = 0;
while (1) {
recheck = 0;
@@ -2099,11 +2082,13 @@ static void stl_echpciintr(stlbrd_t *brdp)
panelp = brdp->bnk2panel[bnknr];
(* panelp->isr)(panelp, (ioaddr & 0xfffc));
recheck++;
+ handled = 1;
}
}
if (! recheck)
break;
}
+ return handled;
}
/*****************************************************************************/
@@ -2112,13 +2097,15 @@ static void stl_echpciintr(stlbrd_t *brdp)
* Interrupt service routine for ECH-8/64-PCI board types.
*/
-static void stl_echpci64intr(stlbrd_t *brdp)
+static int stl_echpci64intr(stlbrd_t *brdp)
{
stlpanel_t *panelp;
unsigned int ioaddr;
int bnknr;
+ int handled = 0;
while (inb(brdp->ioctrl) & 0x1) {
+ handled = 1;
for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) {
ioaddr = brdp->bnkstataddr[bnknr];
if (inb(ioaddr) & ECH_PNLINTRPEND) {
@@ -2127,6 +2114,8 @@ static void stl_echpci64intr(stlbrd_t *brdp)
}
}
}
+
+ return handled;
}
/*****************************************************************************/
@@ -2174,39 +2163,6 @@ static void stl_offintr(void *private)
/*****************************************************************************/
/*
- * Map in interrupt vector to this driver. Check that we don't
- * already have this vector mapped, we might be sharing this
- * interrupt across multiple boards.
- */
-
-static int __init stl_mapirq(int irq, char *name)
-{
- int rc, i;
-
-#ifdef DEBUG
- printk("stl_mapirq(irq=%d,name=%s)\n", irq, name);
-#endif
-
- rc = 0;
- for (i = 0; (i < stl_numintrs); i++) {
- if (stl_gotintrs[i] == irq)
- break;
- }
- if (i >= stl_numintrs) {
- if (request_irq(irq, stl_intr, SA_SHIRQ, name, NULL) != 0) {
- printk("STALLION: failed to register interrupt "
- "routine for %s irq=%d\n", name, irq);
- rc = -ENODEV;
- } else {
- stl_gotintrs[stl_numintrs++] = irq;
- }
- }
- return(rc);
-}
-
-/*****************************************************************************/
-
-/*
* Initialize all the ports on a panel.
*/
@@ -2389,7 +2345,13 @@ static inline int stl_initeio(stlbrd_t *brdp)
brdp->nrpanels = 1;
brdp->state |= BRD_FOUND;
brdp->hwid = status;
- rc = stl_mapirq(brdp->irq, name);
+ if (request_irq(brdp->irq, stl_intr, SA_SHIRQ, name, brdp) != 0) {
+ printk("STALLION: failed to register interrupt "
+ "routine for %s irq=%d\n", name, brdp->irq);
+ rc = -ENODEV;
+ } else {
+ rc = 0;
+ }
return(rc);
}
@@ -2594,7 +2556,14 @@ static inline int stl_initech(stlbrd_t *brdp)
outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
brdp->state |= BRD_FOUND;
- i = stl_mapirq(brdp->irq, name);
+ if (request_irq(brdp->irq, stl_intr, SA_SHIRQ, name, brdp) != 0) {
+ printk("STALLION: failed to register interrupt "
+ "routine for %s irq=%d\n", name, brdp->irq);
+ i = -ENODEV;
+ } else {
+ i = 0;
+ }
+
return(i);
}
@@ -2807,9 +2776,7 @@ static inline int stl_initbrds(void)
*/
for (i = 0; (i < stl_nrbrds); i++) {
confp = &stl_brdconf[i];
-#ifdef MODULE
stl_parsebrd(confp, stl_brdsp[i]);
-#endif
if ((brdp = stl_allocbrd()) == (stlbrd_t *) NULL)
return(-ENOMEM);
brdp->brdnr = i;
@@ -2825,9 +2792,7 @@ static inline int stl_initbrds(void)
* Find any dynamically supported boards. That is via module load
* line options or auto-detected on the PCI bus.
*/
-#ifdef MODULE
stl_argbrds();
-#endif
#ifdef CONFIG_PCI
stl_findpcibrds();
#endif
diff --git a/drivers/char/sx.c b/drivers/char/sx.c
index 533d286d76ff0..3ad758a9a1dc1 100644
--- a/drivers/char/sx.c
+++ b/drivers/char/sx.c
@@ -4,7 +4,7 @@
* This driver will also support the older SI, and XIO cards.
*
*
- * (C) 1998 - 2000 R.E.Wolff@BitWizard.nl
+ * (C) 1998 - 2004 R.E.Wolff@BitWizard.nl
*
* Simon Allen (simonallen@cix.compulink.co.uk) wrote a previous
* version of this driver. Some fragments may have been copied. (none
@@ -354,13 +354,13 @@ static int si1_probe_addrs[]= { 0xd0000};
Some architectures may need more. */
static int sx_irqmask = -1;
-MODULE_PARM(sx_probe_addrs, "i");
-MODULE_PARM(si_probe_addrs, "i");
-MODULE_PARM(sx_poll, "i");
-MODULE_PARM(sx_slowpoll, "i");
-MODULE_PARM(sx_maxints, "i");
-MODULE_PARM(sx_debug, "i");
-MODULE_PARM(sx_irqmask, "i");
+module_param_array(sx_probe_addrs, int, NULL, 0);
+module_param_array(si_probe_addrs, int, NULL, 0);
+module_param(sx_poll, int, 0);
+module_param(sx_slowpoll, int, 0);
+module_param(sx_maxints, int, 0);
+module_param(sx_debug, int, 0);
+module_param(sx_irqmask, int, 0);
MODULE_LICENSE("GPL");
@@ -396,7 +396,7 @@ static struct real_driver sx_real_driver = {
-#define func_enter() sx_dprintk (SX_DEBUG_FLOW, "sx: enter %s\b",__FUNCTION__)
+#define func_enter() sx_dprintk (SX_DEBUG_FLOW, "sx: enter %s\n",__FUNCTION__)
#define func_exit() sx_dprintk (SX_DEBUG_FLOW, "sx: exit %s\n", __FUNCTION__)
#define func_enter2() sx_dprintk (SX_DEBUG_FLOW, "sx: enter %s (port %d)\n", \
@@ -1158,7 +1158,6 @@ static inline void sx_check_modem_signals (struct sx_port *port)
if (hi_state & ST_BREAK) {
hi_state &= ~ST_BREAK;
sx_dprintk (SX_DEBUG_MODEMSIGNALS, "got a break.\n");
-
sx_write_channel_byte (port, hi_state, hi_state);
gs_got_break (&port->gs);
}
@@ -1206,7 +1205,7 @@ static irqreturn_t sx_interrupt (int irq, void *ptr, struct pt_regs *regs)
struct sx_port *port;
int i;
- /* func_enter (); */
+ func_enter ();
sx_dprintk (SX_DEBUG_FLOW, "sx: enter sx_interrupt (%d/%d)\n", irq, board->irq);
/* AAargh! The order in which to do these things is essential and
@@ -1297,7 +1296,7 @@ static irqreturn_t sx_interrupt (int irq, void *ptr, struct pt_regs *regs)
clear_bit (SX_BOARD_INTR_LOCK, &board->locks);
sx_dprintk (SX_DEBUG_FLOW, "sx: exit sx_interrupt (%d/%d)\n", irq, board->irq);
- /* func_exit (); */
+ func_exit ();
return IRQ_HANDLED;
}
@@ -1428,6 +1427,7 @@ static int sx_open (struct tty_struct * tty, struct file * filp)
{
struct sx_port *port;
int retval, line;
+ unsigned long flags;
func_enter();
@@ -1449,9 +1449,12 @@ static int sx_open (struct tty_struct * tty, struct file * filp)
sx_dprintk (SX_DEBUG_OPEN, "port = %p c_dcd = %d\n", port, port->c_dcd);
+ spin_lock_irqsave(&port->gs.driver_lock, flags);
+
tty->driver_data = port;
port->gs.tty = tty;
port->gs.count++;
+ spin_unlock_irqrestore(&port->gs.driver_lock, flags);
sx_dprintk (SX_DEBUG_OPEN, "starting port\n");
@@ -1466,7 +1469,8 @@ static int sx_open (struct tty_struct * tty, struct file * filp)
}
port->gs.flags |= GS_ACTIVE;
- sx_setsignals (port, 1,1);
+ if (port->gs.count <= 1)
+ sx_setsignals (port, 1,1);
#if 0
if (sx_debug & SX_DEBUG_OPEN)
@@ -1476,10 +1480,14 @@ static int sx_open (struct tty_struct * tty, struct file * filp)
my_hd_io (port->board->base + port->ch_base, sizeof (*port));
#endif
- if (sx_send_command (port, HS_LOPEN, -1, HS_IDLE_OPEN) != 1) {
- printk (KERN_ERR "sx: Card didn't respond to LOPEN command.\n");
- port->gs.count--;
- return -EIO;
+ if (port->gs.count <= 1) {
+ if (sx_send_command (port, HS_LOPEN, -1, HS_IDLE_OPEN) != 1) {
+ printk (KERN_ERR "sx: Card didn't respond to LOPEN command.\n");
+ spin_lock_irqsave(&port->gs.driver_lock, flags);
+ port->gs.count--;
+ spin_unlock_irqrestore(&port->gs.driver_lock, flags);
+ return -EIO;
+ }
}
retval = gs_block_til_ready(port, filp);
@@ -1497,6 +1505,7 @@ static int sx_open (struct tty_struct * tty, struct file * filp)
port->c_dcd = sx_get_CD (port);
sx_dprintk (SX_DEBUG_OPEN, "at open: cd=%d\n", port->c_dcd);
+
func_exit();
return 0;
@@ -1515,13 +1524,9 @@ static void sx_close (void *ptr)
sx_reconfigure_port(port);
sx_send_command (port, HS_CLOSE, 0, 0);
- while (to-- && (sx_read_channel_byte (port, hi_hstat) != HS_IDLE_CLOSED)) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout (1);
- if (signal_pending (current))
- break;
- }
- current->state = TASK_RUNNING;
+ while (to-- && (sx_read_channel_byte (port, hi_hstat) != HS_IDLE_CLOSED))
+ if (msleep_interruptible(10))
+ break;
if (sx_read_channel_byte (port, hi_hstat) != HS_IDLE_CLOSED) {
if (sx_send_command (port, HS_FORCE_CLOSED, -1, HS_IDLE_CLOSED) != 1) {
printk (KERN_ERR
@@ -1535,7 +1540,8 @@ static void sx_close (void *ptr)
if(port->gs.count) {
sx_dprintk(SX_DEBUG_CLOSE, "WARNING port count:%d\n", port->gs.count);
- port->gs.count = 0;
+ //printk ("%s SETTING port count to zero: %p count: %d\n", __FUNCTION__, port, port->gs.count);
+ //port->gs.count = 0;
}
func_exit ();
@@ -1751,12 +1757,16 @@ static void sx_break (struct tty_struct * tty, int flag)
struct sx_port *port = tty->driver_data;
int rv;
+ func_enter ();
+
if (flag)
rv = sx_send_command (port, HS_START, -1, HS_IDLE_BREAK);
else
rv = sx_send_command (port, HS_STOP, -1, HS_IDLE_OPEN);
if (rv != 1) printk (KERN_ERR "sx: couldn't send break (%x).\n",
read_sx_byte (port->board, CHAN_OFFSET (port, hi_hstat)));
+
+ func_exit ();
}
@@ -2105,7 +2115,7 @@ static int probe_sx (struct sx_board *board)
}
if (((vpdp.uniqid >> 24) & SX_UNIQUEID_MASK) == SX_ISA_UNIQUEID1) {
- if (board->hw_base & 0x8000) {
+ if (((unsigned long)board->hw_base) & 0x8000) {
printk (KERN_WARNING "sx: Warning: There may be hardware problems with the card at %lx.\n", board->hw_base);
printk (KERN_WARNING "sx: Read sx.txt for more info.\n");
}
@@ -2154,6 +2164,7 @@ static int probe_si (struct sx_board *board)
}
for (i=0;i<8;i++) {
if ((read_sx_byte (board, SI2_ISA_ID_BASE+7-i) & 7) != i) {
+ func_exit ();
return 0;
}
}
@@ -2168,11 +2179,13 @@ static int probe_si (struct sx_board *board)
/* This should be an SI1 board, which has this
location writable... */
if (read_sx_byte (board, SI2_ISA_ID_BASE) != 0x10)
+ func_exit ();
return 0;
} else {
/* This should be an SI2 board, which has the bottom
3 bits non-writable... */
if (read_sx_byte (board, SI2_ISA_ID_BASE) == 0x10)
+ func_exit ();
return 0;
}
@@ -2185,11 +2198,13 @@ static int probe_si (struct sx_board *board)
/* This should be an SI1 board, which has this
location writable... */
if (read_sx_byte (board, SI2_ISA_ID_BASE) != 0x10)
+ func_exit();
return 0;
} else {
/* This should be an SI2 board, which has the bottom
3 bits non-writable... */
if (read_sx_byte (board, SI2_ISA_ID_BASE) == 0x10)
+ func_exit ();
return 0;
}
@@ -2306,6 +2321,7 @@ static int sx_init_portstructs (int nboards, int nports)
#ifdef NEW_WRITE_LOCKING
port->gs.port_write_sem = MUTEX;
#endif
+ port->gs.driver_lock = SPIN_LOCK_UNLOCKED;
/*
* Initializing wait queue
*/
@@ -2477,7 +2493,7 @@ static int __init sx_init(void)
found++;
fix_sx_pci (pdev, board);
} else
- iounmap(board->base);
+ iounmap(board->base2);
}
#endif
diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c
index dc0af4ea75a25..ec949e4c070fd 100644
--- a/drivers/char/synclinkmp.c
+++ b/drivers/char/synclinkmp.c
@@ -1,5 +1,5 @@
/*
- * $Id: synclinkmp.c,v 4.29 2004/08/27 20:06:41 paulkf Exp $
+ * $Id: synclinkmp.c,v 4.34 2005/03/04 15:07:10 paulkf Exp $
*
* Device driver for Microgate SyncLink Multiport
* high speed multiprotocol serial adapter.
@@ -487,7 +487,7 @@ module_param_array(maxframe, int, NULL, 0);
module_param_array(dosyncppp, int, NULL, 0);
static char *driver_name = "SyncLink MultiPort driver";
-static char *driver_version = "$Revision: 4.29 $";
+static char *driver_version = "$Revision: 4.34 $";
static int synclinkmp_init_one(struct pci_dev *dev,const struct pci_device_id *ent);
static void synclinkmp_remove_one(struct pci_dev *dev);
@@ -2313,7 +2313,7 @@ void isr_rxrdy(SLMP_INFO * info)
tty_flip_buffer_push(tty);
}
-void isr_txeom(SLMP_INFO * info, unsigned char status)
+static void isr_txeom(SLMP_INFO * info, unsigned char status)
{
if ( debug_level >= DEBUG_LEVEL_ISR )
printk("%s(%d):%s isr_txeom status=%02x\n",
@@ -3815,7 +3815,7 @@ void add_device(SLMP_INFO *info)
*
* Return Value: pointer to SLMP_INFO if success, otherwise NULL
*/
-SLMP_INFO *alloc_dev(int adapter_num, int port_num, struct pci_dev *pdev)
+static SLMP_INFO *alloc_dev(int adapter_num, int port_num, struct pci_dev *pdev)
{
SLMP_INFO *info;
@@ -4528,7 +4528,7 @@ void async_mode(SLMP_INFO *info)
* 07..05 Reserved, must be 0
* 04..00 RRC<4..0> Rx FIFO trigger active 0x00 = 1 byte
*/
- write_reg(info, TRC0, 0x00);
+ write_reg(info, RRC, 0x00);
/* TRC0 Transmit Ready Control 0
*
@@ -5205,7 +5205,7 @@ int irq_test(SLMP_INFO *info)
/* initialize individual SCA device (2 ports)
*/
-int sca_init(SLMP_INFO *info)
+static int sca_init(SLMP_INFO *info)
{
/* set wait controller to single mem partition (low), no wait states */
write_reg(info, PABR0, 0); /* wait controller addr boundary 0 */
diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c
index 057eaf87b9b28..f59f7cbd525bc 100644
--- a/drivers/char/sysrq.c
+++ b/drivers/char/sysrq.c
@@ -31,19 +31,16 @@
#include <linux/suspend.h>
#include <linux/writeback.h>
#include <linux/buffer_head.h> /* for fsync_bdev() */
-
+#include <linux/swap.h>
#include <linux/spinlock.h>
+#include <linux/vt_kern.h>
+#include <linux/workqueue.h>
#include <asm/ptrace.h>
-extern void reset_vc(unsigned int);
-
/* Whether we react on sysrq keys or just ignore them */
int sysrq_enabled = 1;
-/* Machine specific power off function */
-void (*sysrq_power_off)(void);
-
/* Loglevel sysrq handler */
static void sysrq_handle_loglevel(int key, struct pt_regs *pt_regs,
struct tty_struct *tty)
@@ -58,6 +55,7 @@ static struct sysrq_key_op sysrq_loglevel_op = {
.handler = sysrq_handle_loglevel,
.help_msg = "loglevel0-8",
.action_msg = "Changing Loglevel",
+ .enable_mask = SYSRQ_ENABLE_LOG,
};
@@ -68,12 +66,13 @@ static void sysrq_handle_SAK(int key, struct pt_regs *pt_regs,
{
if (tty)
do_SAK(tty);
- reset_vc(fg_console);
+ reset_vc(vc_cons[fg_console].d);
}
static struct sysrq_key_op sysrq_SAK_op = {
.handler = sysrq_handle_SAK,
.help_msg = "saK",
.action_msg = "SAK",
+ .enable_mask = SYSRQ_ENABLE_KEYBOARD,
};
#endif
@@ -91,6 +90,7 @@ static struct sysrq_key_op sysrq_unraw_op = {
.handler = sysrq_handle_unraw,
.help_msg = "unRaw",
.action_msg = "Keyboard mode set to XLATE",
+ .enable_mask = SYSRQ_ENABLE_KEYBOARD,
};
#endif /* CONFIG_VT */
@@ -106,6 +106,7 @@ static struct sysrq_key_op sysrq_reboot_op = {
.handler = sysrq_handle_reboot,
.help_msg = "reBoot",
.action_msg = "Resetting",
+ .enable_mask = SYSRQ_ENABLE_BOOT,
};
static void sysrq_handle_sync(int key, struct pt_regs *pt_regs,
@@ -118,6 +119,7 @@ static struct sysrq_key_op sysrq_sync_op = {
.handler = sysrq_handle_sync,
.help_msg = "Sync",
.action_msg = "Emergency Sync",
+ .enable_mask = SYSRQ_ENABLE_SYNC,
};
static void sysrq_handle_mountro(int key, struct pt_regs *pt_regs,
@@ -130,6 +132,7 @@ static struct sysrq_key_op sysrq_mountro_op = {
.handler = sysrq_handle_mountro,
.help_msg = "Unmount",
.action_msg = "Emergency Remount R/O",
+ .enable_mask = SYSRQ_ENABLE_REMOUNT,
};
/* END SYNC SYSRQ HANDLERS BLOCK */
@@ -147,6 +150,7 @@ static struct sysrq_key_op sysrq_showregs_op = {
.handler = sysrq_handle_showregs,
.help_msg = "showPc",
.action_msg = "Show Regs",
+ .enable_mask = SYSRQ_ENABLE_DUMP,
};
@@ -159,6 +163,7 @@ static struct sysrq_key_op sysrq_showstate_op = {
.handler = sysrq_handle_showstate,
.help_msg = "showTasks",
.action_msg = "Show State",
+ .enable_mask = SYSRQ_ENABLE_DUMP,
};
@@ -171,6 +176,7 @@ static struct sysrq_key_op sysrq_showmem_op = {
.handler = sysrq_handle_showmem,
.help_msg = "showMem",
.action_msg = "Show Memory",
+ .enable_mask = SYSRQ_ENABLE_DUMP,
};
/* SHOW SYSRQ HANDLERS BLOCK */
@@ -201,6 +207,25 @@ static struct sysrq_key_op sysrq_term_op = {
.handler = sysrq_handle_term,
.help_msg = "tErm",
.action_msg = "Terminate All Tasks",
+ .enable_mask = SYSRQ_ENABLE_SIGNAL,
+};
+
+static void moom_callback(void *ignored)
+{
+ out_of_memory(GFP_KERNEL);
+}
+
+static DECLARE_WORK(moom_work, moom_callback, NULL);
+
+static void sysrq_handle_moom(int key, struct pt_regs *pt_regs,
+ struct tty_struct *tty)
+{
+ schedule_work(&moom_work);
+}
+static struct sysrq_key_op sysrq_moom_op = {
+ .handler = sysrq_handle_moom,
+ .help_msg = "Full",
+ .action_msg = "Manual OOM execution",
};
static void sysrq_handle_kill(int key, struct pt_regs *pt_regs,
@@ -213,6 +238,7 @@ static struct sysrq_key_op sysrq_kill_op = {
.handler = sysrq_handle_kill,
.help_msg = "kIll",
.action_msg = "Kill All Tasks",
+ .enable_mask = SYSRQ_ENABLE_SIGNAL,
};
/* END SIGNAL SYSRQ HANDLERS BLOCK */
@@ -225,7 +251,8 @@ static void sysrq_handle_unrt(int key, struct pt_regs *pt_regs,
static struct sysrq_key_op sysrq_unrt_op = {
.handler = sysrq_handle_unrt,
.help_msg = "Nice",
- .action_msg = "Nice All RT Tasks"
+ .action_msg = "Nice All RT Tasks",
+ .enable_mask = SYSRQ_ENABLE_RTNICE,
};
/* Key Operations table and lock */
@@ -249,7 +276,7 @@ static struct sysrq_key_op *sysrq_key_table[SYSRQ_KEY_TABLE_LENGTH] = {
/* c */ NULL,
/* d */ NULL,
/* e */ &sysrq_term_op,
-/* f */ NULL,
+/* f */ &sysrq_moom_op,
/* g */ NULL,
/* h */ NULL,
/* i */ &sysrq_kill_op,
@@ -321,7 +348,7 @@ void __sysrq_put_key_op (int key, struct sysrq_key_op *op_p) {
* as they are inside of the lock
*/
-void __handle_sysrq(int key, struct pt_regs *pt_regs, struct tty_struct *tty)
+void __handle_sysrq(int key, struct pt_regs *pt_regs, struct tty_struct *tty, int check_mask)
{
struct sysrq_key_op *op_p;
int orig_log_level;
@@ -335,9 +362,16 @@ void __handle_sysrq(int key, struct pt_regs *pt_regs, struct tty_struct *tty)
op_p = __sysrq_get_key_op(key);
if (op_p) {
- printk ("%s\n", op_p->action_msg);
- console_loglevel = orig_log_level;
- op_p->handler(key, pt_regs, tty);
+ /* Should we check for enabled operations (/proc/sysrq-trigger should not)
+ * and is the invoked operation enabled? */
+ if (!check_mask || sysrq_enabled == 1 ||
+ (sysrq_enabled & op_p->enable_mask)) {
+ printk ("%s\n", op_p->action_msg);
+ console_loglevel = orig_log_level;
+ op_p->handler(key, pt_regs, tty);
+ }
+ else
+ printk("This sysrq operation is disabled.\n");
} else {
printk("HELP : ");
/* Only print the help msg once per handler */
@@ -362,7 +396,7 @@ void handle_sysrq(int key, struct pt_regs *pt_regs, struct tty_struct *tty)
{
if (!sysrq_enabled)
return;
- __handle_sysrq(key, pt_regs, tty);
+ __handle_sysrq(key, pt_regs, tty, 1);
}
int __sysrq_swap_key_ops(int key, struct sysrq_key_op *insert_op_p,
diff --git a/drivers/char/tb0219.c b/drivers/char/tb0219.c
new file mode 100644
index 0000000000000..5413f2908859d
--- /dev/null
+++ b/drivers/char/tb0219.c
@@ -0,0 +1,347 @@
+/*
+ * Driver for TANBAC TB0219 base board.
+ *
+ * Copyright (C) 2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <linux/device.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/module.h>
+
+#include <asm/io.h>
+#include <asm/reboot.h>
+
+MODULE_AUTHOR("Yoichi Yuasa <yuasa@hh.iij4u.or.jp>");
+MODULE_DESCRIPTION("TANBAC TB0219 base board driver");
+MODULE_LICENSE("GPL");
+
+static int major; /* default is dynamic major device number */
+module_param(major, int, 0);
+MODULE_PARM_DESC(major, "Major device number");
+
+static void (*old_machine_restart)(char *command);
+static void __iomem *tb0219_base;
+static spinlock_t tb0219_lock;
+
+#define tb0219_read(offset) readw(tb0219_base + (offset))
+#define tb0219_write(offset, value) writew((value), tb0219_base + (offset))
+
+#define TB0219_START 0x0a000000UL
+#define TB0219_SIZE 0x20UL
+
+#define TB0219_LED 0x00
+#define TB0219_GPIO_INPUT 0x02
+#define TB0219_GPIO_OUTPUT 0x04
+#define TB0219_DIP_SWITCH 0x06
+#define TB0219_MISC 0x08
+#define TB0219_RESET 0x0e
+#define TB0219_PCI_SLOT1_IRQ_STATUS 0x10
+#define TB0219_PCI_SLOT2_IRQ_STATUS 0x12
+#define TB0219_PCI_SLOT3_IRQ_STATUS 0x14
+
+typedef enum {
+ TYPE_LED,
+ TYPE_GPIO_OUTPUT,
+} tb0219_type_t;
+
+/*
+ * Minor device number
+ * 0 = 7 segment LED
+ *
+ * 16 = GPIO IN 0
+ * 17 = GPIO IN 1
+ * 18 = GPIO IN 2
+ * 19 = GPIO IN 3
+ * 20 = GPIO IN 4
+ * 21 = GPIO IN 5
+ * 22 = GPIO IN 6
+ * 23 = GPIO IN 7
+ *
+ * 32 = GPIO OUT 0
+ * 33 = GPIO OUT 1
+ * 34 = GPIO OUT 2
+ * 35 = GPIO OUT 3
+ * 36 = GPIO OUT 4
+ * 37 = GPIO OUT 5
+ * 38 = GPIO OUT 6
+ * 39 = GPIO OUT 7
+ *
+ * 48 = DIP switch 1
+ * 49 = DIP switch 2
+ * 50 = DIP switch 3
+ * 51 = DIP switch 4
+ * 52 = DIP switch 5
+ * 53 = DIP switch 6
+ * 54 = DIP switch 7
+ * 55 = DIP switch 8
+ */
+
+static inline char get_led(void)
+{
+ return (char)tb0219_read(TB0219_LED);
+}
+
+static inline char get_gpio_input_pin(unsigned int pin)
+{
+ uint16_t values;
+
+ values = tb0219_read(TB0219_GPIO_INPUT);
+ if (values & (1 << pin))
+ return '1';
+
+ return '0';
+}
+
+static inline char get_gpio_output_pin(unsigned int pin)
+{
+ uint16_t values;
+
+ values = tb0219_read(TB0219_GPIO_OUTPUT);
+ if (values & (1 << pin))
+ return '1';
+
+ return '0';
+}
+
+static inline char get_dip_switch(unsigned int pin)
+{
+ uint16_t values;
+
+ values = tb0219_read(TB0219_DIP_SWITCH);
+ if (values & (1 << pin))
+ return '1';
+
+ return '0';
+}
+
+static inline int set_led(char command)
+{
+ tb0219_write(TB0219_LED, command);
+
+ return 0;
+}
+
+static inline int set_gpio_output_pin(unsigned int pin, char command)
+{
+ unsigned long flags;
+ uint16_t value;
+
+ if (command != '0' && command != '1')
+ return -EINVAL;
+
+ spin_lock_irqsave(&tb0219_lock, flags);
+ value = tb0219_read(TB0219_GPIO_OUTPUT);
+ if (command == '0')
+ value &= ~(1 << pin);
+ else
+ value |= 1 << pin;
+ tb0219_write(TB0219_GPIO_OUTPUT, value);
+ spin_unlock_irqrestore(&tb0219_lock, flags);
+
+ return 0;
+
+}
+
+static ssize_t tanbac_tb0219_read(struct file *file, char __user *buf, size_t len,
+ loff_t *ppos)
+{
+ unsigned int minor;
+ char value;
+
+ minor = iminor(file->f_dentry->d_inode);
+ switch (minor) {
+ case 0:
+ value = get_led();
+ break;
+ case 16 ... 23:
+ value = get_gpio_input_pin(minor - 16);
+ break;
+ case 32 ... 39:
+ value = get_gpio_output_pin(minor - 32);
+ break;
+ case 48 ... 55:
+ value = get_dip_switch(minor - 48);
+ break;
+ default:
+ return -EBADF;
+ }
+
+ if (len <= 0)
+ return -EFAULT;
+
+ if (put_user(value, buf))
+ return -EFAULT;
+
+ return 1;
+}
+
+static ssize_t tanbac_tb0219_write(struct file *file, const char __user *data,
+ size_t len, loff_t *ppos)
+{
+ unsigned int minor;
+ tb0219_type_t type;
+ size_t i;
+ int retval = 0;
+ char c;
+
+ minor = iminor(file->f_dentry->d_inode);
+ switch (minor) {
+ case 0:
+ type = TYPE_LED;
+ break;
+ case 32 ... 39:
+ type = TYPE_GPIO_OUTPUT;
+ break;
+ default:
+ return -EBADF;
+ }
+
+ for (i = 0; i < len; i++) {
+ if (get_user(c, data + i))
+ return -EFAULT;
+
+ switch (type) {
+ case TYPE_LED:
+ retval = set_led(c);
+ break;
+ case TYPE_GPIO_OUTPUT:
+ retval = set_gpio_output_pin(minor - 32, c);
+ break;
+ }
+
+ if (retval < 0)
+ break;
+ }
+
+ return i;
+}
+
+static int tanbac_tb0219_open(struct inode *inode, struct file *file)
+{
+ unsigned int minor;
+
+ minor = iminor(inode);
+ switch (minor) {
+ case 0:
+ case 16 ... 23:
+ case 32 ... 39:
+ case 48 ... 55:
+ return nonseekable_open(inode, file);
+ default:
+ break;
+ }
+
+ return -EBADF;
+}
+
+static int tanbac_tb0219_release(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
+static struct file_operations tb0219_fops = {
+ .owner = THIS_MODULE,
+ .read = tanbac_tb0219_read,
+ .write = tanbac_tb0219_write,
+ .open = tanbac_tb0219_open,
+ .release = tanbac_tb0219_release,
+};
+
+static void tb0219_restart(char *command)
+{
+ tb0219_write(TB0219_RESET, 0);
+}
+
+static int tb0219_probe(struct device *dev)
+{
+ int retval;
+
+ if (request_mem_region(TB0219_START, TB0219_SIZE, "TB0219") == NULL)
+ return -EBUSY;
+
+ tb0219_base = ioremap(TB0219_START, TB0219_SIZE);
+ if (tb0219_base == NULL) {
+ release_mem_region(TB0219_START, TB0219_SIZE);
+ return -ENOMEM;
+ }
+
+ retval = register_chrdev(major, "TB0219", &tb0219_fops);
+ if (retval < 0) {
+ iounmap(tb0219_base);
+ tb0219_base = NULL;
+ release_mem_region(TB0219_START, TB0219_SIZE);
+ return retval;
+ }
+
+ spin_lock_init(&tb0219_lock);
+
+ old_machine_restart = _machine_restart;
+ _machine_restart = tb0219_restart;
+
+ if (major == 0) {
+ major = retval;
+ printk(KERN_INFO "TB0219: major number %d\n", major);
+ }
+
+ return 0;
+}
+
+static int tb0219_remove(struct device *dev)
+{
+ _machine_restart = old_machine_restart;
+
+ iounmap(tb0219_base);
+ tb0219_base = NULL;
+
+ release_mem_region(TB0219_START, TB0219_SIZE);
+
+ return 0;
+}
+
+static struct platform_device *tb0219_platform_device;
+
+static struct device_driver tb0219_device_driver = {
+ .name = "TB0219",
+ .bus = &platform_bus_type,
+ .probe = tb0219_probe,
+ .remove = tb0219_remove,
+};
+
+static int __devinit tanbac_tb0219_init(void)
+{
+ int retval;
+
+ tb0219_platform_device = platform_device_register_simple("TB0219", -1, NULL, 0);
+ if (IS_ERR(tb0219_platform_device))
+ return PTR_ERR(tb0219_platform_device);
+
+ retval = driver_register(&tb0219_device_driver);
+ if (retval < 0)
+ platform_device_unregister(tb0219_platform_device);
+
+ return retval;
+}
+
+static void __devexit tanbac_tb0219_exit(void)
+{
+ driver_unregister(&tb0219_device_driver);
+
+ platform_device_unregister(tb0219_platform_device);
+}
+
+module_init(tanbac_tb0219_init);
+module_exit(tanbac_tb0219_exit);
diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig
new file mode 100644
index 0000000000000..7a969778915af
--- /dev/null
+++ b/drivers/char/tpm/Kconfig
@@ -0,0 +1,39 @@
+#
+# TPM device configuration
+#
+
+menu "TPM devices"
+
+config TCG_TPM
+ tristate "TPM Hardware Support"
+ depends on EXPERIMENTAL && PCI
+ ---help---
+ If you have a TPM security chip in your system, which
+ implements the Trusted Computing Group's specification,
+ say Yes and it will be accessible from within Linux. For
+ more information see <http://www.trustedcomputinggroup.org>.
+ An implementation of the Trusted Software Stack (TSS), the
+ userspace enablement piece of the specification, can be
+ obtained at: <http://sourceforge.net/projects/trousers>. To
+ compile this driver as a module, choose M here; the module
+ will be called tpm. If unsure, say N.
+
+config TCG_NSC
+ tristate "National Semiconductor TPM Interface"
+ depends on TCG_TPM
+ ---help---
+ If you have a TPM security chip from National Semicondutor
+ say Yes and it will be accessible from within Linux. To
+ compile this driver as a module, choose M here; the module
+ will be called tpm_nsc.
+
+config TCG_ATMEL
+ tristate "Atmel TPM Interface"
+ depends on TCG_TPM
+ ---help---
+ If you have a TPM security chip from Atmel say Yes and it
+ will be accessible from within Linux. To compile this driver
+ as a module, choose M here; the module will be called tpm_atmel.
+
+endmenu
+
diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile
new file mode 100644
index 0000000000000..736d3df266f5b
--- /dev/null
+++ b/drivers/char/tpm/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for the kernel tpm device drivers.
+#
+obj-$(CONFIG_TCG_TPM) += tpm.o
+obj-$(CONFIG_TCG_NSC) += tpm_nsc.o
+obj-$(CONFIG_TCG_ATMEL) += tpm_atmel.o
+
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
new file mode 100644
index 0000000000000..8318268169d67
--- /dev/null
+++ b/drivers/char/tpm/tpm.c
@@ -0,0 +1,697 @@
+/*
+ * Copyright (C) 2004 IBM Corporation
+ *
+ * Authors:
+ * Leendert van Doorn <leendert@watson.ibm.com>
+ * Dave Safford <safford@watson.ibm.com>
+ * Reiner Sailer <sailer@watson.ibm.com>
+ * Kylene Hall <kjhall@us.ibm.com>
+ *
+ * Maintained by: <tpmdd_devel@lists.sourceforge.net>
+ *
+ * Device driver for TCG/TCPA TPM (trusted platform module).
+ * Specifications at www.trustedcomputinggroup.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, version 2 of the
+ * License.
+ *
+ * Note, the TPM chip is not interrupt driven (only polling)
+ * and can have very long timeouts (minutes!). Hence the unusual
+ * calls to schedule_timeout.
+ *
+ */
+
+#include <linux/sched.h>
+#include <linux/poll.h>
+#include <linux/spinlock.h>
+#include "tpm.h"
+
+#define TPM_MINOR 224 /* officially assigned */
+
+#define TPM_BUFSIZE 2048
+
+/* PCI configuration addresses */
+#define PCI_GEN_PMCON_1 0xA0
+#define PCI_GEN1_DEC 0xE4
+#define PCI_LPC_EN 0xE6
+#define PCI_GEN2_DEC 0xEC
+
+static LIST_HEAD(tpm_chip_list);
+static DEFINE_SPINLOCK(driver_lock);
+static int dev_mask[32];
+
+static void user_reader_timeout(unsigned long ptr)
+{
+ struct tpm_chip *chip = (struct tpm_chip *) ptr;
+
+ down(&chip->buffer_mutex);
+ atomic_set(&chip->data_pending, 0);
+ memset(chip->data_buffer, 0, TPM_BUFSIZE);
+ up(&chip->buffer_mutex);
+}
+
+void tpm_time_expired(unsigned long ptr)
+{
+ int *exp = (int *) ptr;
+ *exp = 1;
+}
+
+EXPORT_SYMBOL_GPL(tpm_time_expired);
+
+/*
+ * Initialize the LPC bus and enable the TPM ports
+ */
+int tpm_lpc_bus_init(struct pci_dev *pci_dev, u16 base)
+{
+ u32 lpcenable, tmp;
+ int is_lpcm = 0;
+
+ switch (pci_dev->vendor) {
+ case PCI_VENDOR_ID_INTEL:
+ switch (pci_dev->device) {
+ case PCI_DEVICE_ID_INTEL_82801CA_12:
+ case PCI_DEVICE_ID_INTEL_82801DB_12:
+ is_lpcm = 1;
+ break;
+ }
+ /* init ICH (enable LPC) */
+ pci_read_config_dword(pci_dev, PCI_GEN1_DEC, &lpcenable);
+ lpcenable |= 0x20000000;
+ pci_write_config_dword(pci_dev, PCI_GEN1_DEC, lpcenable);
+
+ if (is_lpcm) {
+ pci_read_config_dword(pci_dev, PCI_GEN1_DEC,
+ &lpcenable);
+ if ((lpcenable & 0x20000000) == 0) {
+ dev_err(&pci_dev->dev,
+ "cannot enable LPC\n");
+ return -ENODEV;
+ }
+ }
+
+ /* initialize TPM registers */
+ pci_read_config_dword(pci_dev, PCI_GEN2_DEC, &tmp);
+
+ if (!is_lpcm)
+ tmp = (tmp & 0xFFFF0000) | (base & 0xFFF0);
+ else
+ tmp =
+ (tmp & 0xFFFF0000) | (base & 0xFFF0) |
+ 0x00000001;
+
+ pci_write_config_dword(pci_dev, PCI_GEN2_DEC, tmp);
+
+ if (is_lpcm) {
+ pci_read_config_dword(pci_dev, PCI_GEN_PMCON_1,
+ &tmp);
+ tmp |= 0x00000004; /* enable CLKRUN */
+ pci_write_config_dword(pci_dev, PCI_GEN_PMCON_1,
+ tmp);
+ }
+ tpm_write_index(0x0D, 0x55); /* unlock 4F */
+ tpm_write_index(0x0A, 0x00); /* int disable */
+ tpm_write_index(0x08, base); /* base addr lo */
+ tpm_write_index(0x09, (base & 0xFF00) >> 8); /* base addr hi */
+ tpm_write_index(0x0D, 0xAA); /* lock 4F */
+ break;
+ case PCI_VENDOR_ID_AMD:
+ /* nothing yet */
+ break;
+ }
+
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(tpm_lpc_bus_init);
+
+/*
+ * Internal kernel interface to transmit TPM commands
+ */
+static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf,
+ size_t bufsiz)
+{
+ ssize_t len;
+ u32 count;
+ __be32 *native_size;
+
+ native_size = (__force __be32 *) (buf + 2);
+ count = be32_to_cpu(*native_size);
+
+ if (count == 0)
+ return -ENODATA;
+ if (count > bufsiz) {
+ dev_err(&chip->pci_dev->dev,
+ "invalid count value %x %x \n", count, bufsiz);
+ return -E2BIG;
+ }
+
+ down(&chip->tpm_mutex);
+
+ if ((len = chip->vendor->send(chip, (u8 *) buf, count)) < 0) {
+ dev_err(&chip->pci_dev->dev,
+ "tpm_transmit: tpm_send: error %d\n", len);
+ return len;
+ }
+
+ down(&chip->timer_manipulation_mutex);
+ chip->time_expired = 0;
+ init_timer(&chip->device_timer);
+ chip->device_timer.function = tpm_time_expired;
+ chip->device_timer.expires = jiffies + 2 * 60 * HZ;
+ chip->device_timer.data = (unsigned long) &chip->time_expired;
+ add_timer(&chip->device_timer);
+ up(&chip->timer_manipulation_mutex);
+
+ do {
+ u8 status = inb(chip->vendor->base + 1);
+ if ((status & chip->vendor->req_complete_mask) ==
+ chip->vendor->req_complete_val) {
+ down(&chip->timer_manipulation_mutex);
+ del_singleshot_timer_sync(&chip->device_timer);
+ up(&chip->timer_manipulation_mutex);
+ goto out_recv;
+ }
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(TPM_TIMEOUT);
+ rmb();
+ } while (!chip->time_expired);
+
+
+ chip->vendor->cancel(chip);
+ dev_err(&chip->pci_dev->dev, "Time expired\n");
+ up(&chip->tpm_mutex);
+ return -EIO;
+
+out_recv:
+ len = chip->vendor->recv(chip, (u8 *) buf, bufsiz);
+ if (len < 0)
+ dev_err(&chip->pci_dev->dev,
+ "tpm_transmit: tpm_recv: error %d\n", len);
+ up(&chip->tpm_mutex);
+ return len;
+}
+
+#define TPM_DIGEST_SIZE 20
+#define CAP_PCR_RESULT_SIZE 18
+static u8 cap_pcr[] = {
+ 0, 193, /* TPM_TAG_RQU_COMMAND */
+ 0, 0, 0, 22, /* length */
+ 0, 0, 0, 101, /* TPM_ORD_GetCapability */
+ 0, 0, 0, 5,
+ 0, 0, 0, 4,
+ 0, 0, 1, 1
+};
+
+#define READ_PCR_RESULT_SIZE 30
+static u8 pcrread[] = {
+ 0, 193, /* TPM_TAG_RQU_COMMAND */
+ 0, 0, 0, 14, /* length */
+ 0, 0, 0, 21, /* TPM_ORD_PcrRead */
+ 0, 0, 0, 0 /* PCR index */
+};
+
+static ssize_t show_pcrs(struct device *dev, char *buf)
+{
+ u8 data[READ_PCR_RESULT_SIZE];
+ ssize_t len;
+ int i, j, index, num_pcrs;
+ char *str = buf;
+
+ struct tpm_chip *chip =
+ pci_get_drvdata(container_of(dev, struct pci_dev, dev));
+ if (chip == NULL)
+ return -ENODEV;
+
+ memcpy(data, cap_pcr, sizeof(cap_pcr));
+ if ((len = tpm_transmit(chip, data, sizeof(data)))
+ < CAP_PCR_RESULT_SIZE)
+ return len;
+
+ num_pcrs = be32_to_cpu(*((__force __be32 *) (data + 14)));
+
+ for (i = 0; i < num_pcrs; i++) {
+ memcpy(data, pcrread, sizeof(pcrread));
+ index = cpu_to_be32(i);
+ memcpy(data + 10, &index, 4);
+ if ((len = tpm_transmit(chip, data, sizeof(data)))
+ < READ_PCR_RESULT_SIZE)
+ return len;
+ str += sprintf(str, "PCR-%02d: ", i);
+ for (j = 0; j < TPM_DIGEST_SIZE; j++)
+ str += sprintf(str, "%02X ", *(data + 10 + j));
+ str += sprintf(str, "\n");
+ }
+ return str - buf;
+}
+
+static DEVICE_ATTR(pcrs, S_IRUGO, show_pcrs, NULL);
+
+#define READ_PUBEK_RESULT_SIZE 314
+static u8 readpubek[] = {
+ 0, 193, /* TPM_TAG_RQU_COMMAND */
+ 0, 0, 0, 30, /* length */
+ 0, 0, 0, 124, /* TPM_ORD_ReadPubek */
+};
+
+static ssize_t show_pubek(struct device *dev, char *buf)
+{
+ u8 data[READ_PUBEK_RESULT_SIZE];
+ ssize_t len;
+ __be32 *native_val;
+ int i;
+ char *str = buf;
+
+ struct tpm_chip *chip =
+ pci_get_drvdata(container_of(dev, struct pci_dev, dev));
+ if (chip == NULL)
+ return -ENODEV;
+
+ memcpy(data, readpubek, sizeof(readpubek));
+ memset(data + sizeof(readpubek), 0, 20); /* zero nonce */
+
+ if ((len = tpm_transmit(chip, data, sizeof(data))) <
+ READ_PUBEK_RESULT_SIZE)
+ return len;
+
+ /*
+ ignore header 10 bytes
+ algorithm 32 bits (1 == RSA )
+ encscheme 16 bits
+ sigscheme 16 bits
+ parameters (RSA 12->bytes: keybit, #primes, expbit)
+ keylenbytes 32 bits
+ 256 byte modulus
+ ignore checksum 20 bytes
+ */
+
+ native_val = (__force __be32 *) (data + 34);
+
+ str +=
+ sprintf(str,
+ "Algorithm: %02X %02X %02X %02X\nEncscheme: %02X %02X\n"
+ "Sigscheme: %02X %02X\nParameters: %02X %02X %02X %02X"
+ " %02X %02X %02X %02X %02X %02X %02X %02X\n"
+ "Modulus length: %d\nModulus: \n",
+ data[10], data[11], data[12], data[13], data[14],
+ data[15], data[16], data[17], data[22], data[23],
+ data[24], data[25], data[26], data[27], data[28],
+ data[29], data[30], data[31], data[32], data[33],
+ be32_to_cpu(*native_val)
+ );
+
+ for (i = 0; i < 256; i++) {
+ str += sprintf(str, "%02X ", data[i + 39]);
+ if ((i + 1) % 16 == 0)
+ str += sprintf(str, "\n");
+ }
+ return str - buf;
+}
+
+static DEVICE_ATTR(pubek, S_IRUGO, show_pubek, NULL);
+
+#define CAP_VER_RESULT_SIZE 18
+static u8 cap_version[] = {
+ 0, 193, /* TPM_TAG_RQU_COMMAND */
+ 0, 0, 0, 18, /* length */
+ 0, 0, 0, 101, /* TPM_ORD_GetCapability */
+ 0, 0, 0, 6,
+ 0, 0, 0, 0
+};
+
+#define CAP_MANUFACTURER_RESULT_SIZE 18
+static u8 cap_manufacturer[] = {
+ 0, 193, /* TPM_TAG_RQU_COMMAND */
+ 0, 0, 0, 22, /* length */
+ 0, 0, 0, 101, /* TPM_ORD_GetCapability */
+ 0, 0, 0, 5,
+ 0, 0, 0, 4,
+ 0, 0, 1, 3
+};
+
+static ssize_t show_caps(struct device *dev, char *buf)
+{
+ u8 data[READ_PUBEK_RESULT_SIZE];
+ ssize_t len;
+ char *str = buf;
+
+ struct tpm_chip *chip =
+ pci_get_drvdata(container_of(dev, struct pci_dev, dev));
+ if (chip == NULL)
+ return -ENODEV;
+
+ memcpy(data, cap_manufacturer, sizeof(cap_manufacturer));
+
+ if ((len = tpm_transmit(chip, data, sizeof(data))) <
+ CAP_MANUFACTURER_RESULT_SIZE)
+ return len;
+
+ str += sprintf(str, "Manufacturer: 0x%x\n",
+ be32_to_cpu(*(data + 14)));
+
+ memcpy(data, cap_version, sizeof(cap_version));
+
+ if ((len = tpm_transmit(chip, data, sizeof(data))) <
+ CAP_VER_RESULT_SIZE)
+ return len;
+
+ str +=
+ sprintf(str, "TCG version: %d.%d\nFirmware version: %d.%d\n",
+ (int) data[14], (int) data[15], (int) data[16],
+ (int) data[17]);
+
+ return str - buf;
+}
+
+static DEVICE_ATTR(caps, S_IRUGO, show_caps, NULL);
+
+/*
+ * Device file system interface to the TPM
+ */
+int tpm_open(struct inode *inode, struct file *file)
+{
+ int rc = 0, minor = iminor(inode);
+ struct tpm_chip *chip = NULL, *pos;
+
+ spin_lock(&driver_lock);
+
+ list_for_each_entry(pos, &tpm_chip_list, list) {
+ if (pos->vendor->miscdev.minor == minor) {
+ chip = pos;
+ break;
+ }
+ }
+
+ if (chip == NULL) {
+ rc = -ENODEV;
+ goto err_out;
+ }
+
+ if (chip->num_opens) {
+ dev_dbg(&chip->pci_dev->dev,
+ "Another process owns this TPM\n");
+ rc = -EBUSY;
+ goto err_out;
+ }
+
+ chip->num_opens++;
+ pci_dev_get(chip->pci_dev);
+
+ spin_unlock(&driver_lock);
+
+ chip->data_buffer = kmalloc(TPM_BUFSIZE * sizeof(u8), GFP_KERNEL);
+ if (chip->data_buffer == NULL) {
+ chip->num_opens--;
+ pci_dev_put(chip->pci_dev);
+ return -ENOMEM;
+ }
+
+ atomic_set(&chip->data_pending, 0);
+
+ file->private_data = chip;
+ return 0;
+
+err_out:
+ spin_unlock(&driver_lock);
+ return rc;
+}
+
+EXPORT_SYMBOL_GPL(tpm_open);
+
+int tpm_release(struct inode *inode, struct file *file)
+{
+ struct tpm_chip *chip = file->private_data;
+
+ file->private_data = NULL;
+
+ spin_lock(&driver_lock);
+ chip->num_opens--;
+ spin_unlock(&driver_lock);
+
+ down(&chip->timer_manipulation_mutex);
+ if (timer_pending(&chip->user_read_timer))
+ del_singleshot_timer_sync(&chip->user_read_timer);
+ else if (timer_pending(&chip->device_timer))
+ del_singleshot_timer_sync(&chip->device_timer);
+ up(&chip->timer_manipulation_mutex);
+
+ kfree(chip->data_buffer);
+ atomic_set(&chip->data_pending, 0);
+
+ pci_dev_put(chip->pci_dev);
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(tpm_release);
+
+ssize_t tpm_write(struct file * file, const char __user * buf,
+ size_t size, loff_t * off)
+{
+ struct tpm_chip *chip = file->private_data;
+ int in_size = size, out_size;
+
+ /* cannot perform a write until the read has cleared
+ either via tpm_read or a user_read_timer timeout */
+ while (atomic_read(&chip->data_pending) != 0) {
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(TPM_TIMEOUT);
+ }
+
+ down(&chip->buffer_mutex);
+
+ if (in_size > TPM_BUFSIZE)
+ in_size = TPM_BUFSIZE;
+
+ if (copy_from_user
+ (chip->data_buffer, (void __user *) buf, in_size)) {
+ up(&chip->buffer_mutex);
+ return -EFAULT;
+ }
+
+ /* atomic tpm command send and result receive */
+ out_size = tpm_transmit(chip, chip->data_buffer, TPM_BUFSIZE);
+
+ atomic_set(&chip->data_pending, out_size);
+ up(&chip->buffer_mutex);
+
+ /* Set a timeout by which the reader must come claim the result */
+ down(&chip->timer_manipulation_mutex);
+ init_timer(&chip->user_read_timer);
+ chip->user_read_timer.function = user_reader_timeout;
+ chip->user_read_timer.data = (unsigned long) chip;
+ chip->user_read_timer.expires = jiffies + (60 * HZ);
+ add_timer(&chip->user_read_timer);
+ up(&chip->timer_manipulation_mutex);
+
+ return in_size;
+}
+
+EXPORT_SYMBOL_GPL(tpm_write);
+
+ssize_t tpm_read(struct file * file, char __user * buf,
+ size_t size, loff_t * off)
+{
+ struct tpm_chip *chip = file->private_data;
+ int ret_size = -ENODATA;
+
+ if (atomic_read(&chip->data_pending) != 0) { /* Result available */
+ down(&chip->timer_manipulation_mutex);
+ del_singleshot_timer_sync(&chip->user_read_timer);
+ up(&chip->timer_manipulation_mutex);
+
+ down(&chip->buffer_mutex);
+
+ ret_size = atomic_read(&chip->data_pending);
+ atomic_set(&chip->data_pending, 0);
+
+ if (ret_size == 0) /* timeout just occurred */
+ ret_size = -ETIME;
+ else if (ret_size > 0) { /* relay data */
+ if (size < ret_size)
+ ret_size = size;
+
+ if (copy_to_user((void __user *) buf,
+ chip->data_buffer, ret_size)) {
+ ret_size = -EFAULT;
+ }
+ }
+ up(&chip->buffer_mutex);
+ }
+
+ return ret_size;
+}
+
+EXPORT_SYMBOL_GPL(tpm_read);
+
+void __devexit tpm_remove(struct pci_dev *pci_dev)
+{
+ struct tpm_chip *chip = pci_get_drvdata(pci_dev);
+
+ if (chip == NULL) {
+ dev_err(&pci_dev->dev, "No device data found\n");
+ return;
+ }
+
+ spin_lock(&driver_lock);
+
+ list_del(&chip->list);
+
+ spin_unlock(&driver_lock);
+
+ pci_set_drvdata(pci_dev, NULL);
+ misc_deregister(&chip->vendor->miscdev);
+
+ device_remove_file(&pci_dev->dev, &dev_attr_pubek);
+ device_remove_file(&pci_dev->dev, &dev_attr_pcrs);
+ device_remove_file(&pci_dev->dev, &dev_attr_caps);
+
+ pci_disable_device(pci_dev);
+
+ dev_mask[chip->dev_num / 32] &= !(1 << (chip->dev_num % 32));
+
+ kfree(chip);
+
+ pci_dev_put(pci_dev);
+}
+
+EXPORT_SYMBOL_GPL(tpm_remove);
+
+static u8 savestate[] = {
+ 0, 193, /* TPM_TAG_RQU_COMMAND */
+ 0, 0, 0, 10, /* blob length (in bytes) */
+ 0, 0, 0, 152 /* TPM_ORD_SaveState */
+};
+
+/*
+ * We are about to suspend. Save the TPM state
+ * so that it can be restored.
+ */
+int tpm_pm_suspend(struct pci_dev *pci_dev, u32 pm_state)
+{
+ struct tpm_chip *chip = pci_get_drvdata(pci_dev);
+ if (chip == NULL)
+ return -ENODEV;
+
+ tpm_transmit(chip, savestate, sizeof(savestate));
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(tpm_pm_suspend);
+
+/*
+ * Resume from a power safe. The BIOS already restored
+ * the TPM state.
+ */
+int tpm_pm_resume(struct pci_dev *pci_dev)
+{
+ struct tpm_chip *chip = pci_get_drvdata(pci_dev);
+
+ if (chip == NULL)
+ return -ENODEV;
+
+ spin_lock(&driver_lock);
+ tpm_lpc_bus_init(pci_dev, chip->vendor->base);
+ spin_unlock(&driver_lock);
+
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(tpm_pm_resume);
+
+/*
+ * Called from tpm_<specific>.c probe function only for devices
+ * the driver has determined it should claim. Prior to calling
+ * this function the specific probe function has called pci_enable_device
+ * upon errant exit from this function specific probe function should call
+ * pci_disable_device
+ */
+int tpm_register_hardware(struct pci_dev *pci_dev,
+ struct tpm_vendor_specific *entry)
+{
+ char devname[7];
+ struct tpm_chip *chip;
+ int i, j;
+
+ /* Driver specific per-device data */
+ chip = kmalloc(sizeof(*chip), GFP_KERNEL);
+ if (chip == NULL)
+ return -ENOMEM;
+
+ memset(chip, 0, sizeof(struct tpm_chip));
+
+ init_MUTEX(&chip->buffer_mutex);
+ init_MUTEX(&chip->tpm_mutex);
+ init_MUTEX(&chip->timer_manipulation_mutex);
+ INIT_LIST_HEAD(&chip->list);
+
+ chip->vendor = entry;
+
+ chip->dev_num = -1;
+
+ for (i = 0; i < 32; i++)
+ for (j = 0; j < 8; j++)
+ if ((dev_mask[i] & (1 << j)) == 0) {
+ chip->dev_num = i * 32 + j;
+ dev_mask[i] |= 1 << j;
+ goto dev_num_search_complete;
+ }
+
+dev_num_search_complete:
+ if (chip->dev_num < 0) {
+ dev_err(&pci_dev->dev,
+ "No available tpm device numbers\n");
+ kfree(chip);
+ return -ENODEV;
+ } else if (chip->dev_num == 0)
+ chip->vendor->miscdev.minor = TPM_MINOR;
+ else
+ chip->vendor->miscdev.minor = MISC_DYNAMIC_MINOR;
+
+ snprintf(devname, sizeof(devname), "%s%d", "tpm", chip->dev_num);
+ chip->vendor->miscdev.name = devname;
+
+ chip->vendor->miscdev.dev = &(pci_dev->dev);
+ chip->pci_dev = pci_dev_get(pci_dev);
+
+ if (misc_register(&chip->vendor->miscdev)) {
+ dev_err(&chip->pci_dev->dev,
+ "unable to misc_register %s, minor %d\n",
+ chip->vendor->miscdev.name,
+ chip->vendor->miscdev.minor);
+ pci_dev_put(pci_dev);
+ kfree(chip);
+ dev_mask[i] &= !(1 << j);
+ return -ENODEV;
+ }
+
+ pci_set_drvdata(pci_dev, chip);
+
+ list_add(&chip->list, &tpm_chip_list);
+
+ device_create_file(&pci_dev->dev, &dev_attr_pubek);
+ device_create_file(&pci_dev->dev, &dev_attr_pcrs);
+ device_create_file(&pci_dev->dev, &dev_attr_caps);
+
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(tpm_register_hardware);
+
+static int __init init_tpm(void)
+{
+ return 0;
+}
+
+static void __exit cleanup_tpm(void)
+{
+
+}
+
+module_init(init_tpm);
+module_exit(cleanup_tpm);
+
+MODULE_AUTHOR("Leendert van Doorn (leendert@watson.ibm.com)");
+MODULE_DESCRIPTION("TPM Driver");
+MODULE_VERSION("2.0");
+MODULE_LICENSE("GPL");
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
new file mode 100644
index 0000000000000..575cf5aed41a5
--- /dev/null
+++ b/drivers/char/tpm/tpm.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2004 IBM Corporation
+ *
+ * Authors:
+ * Leendert van Doorn <leendert@watson.ibm.com>
+ * Dave Safford <safford@watson.ibm.com>
+ * Reiner Sailer <sailer@watson.ibm.com>
+ * Kylene Hall <kjhall@us.ibm.com>
+ *
+ * Maintained by: <tpmdd_devel@lists.sourceforge.net>
+ *
+ * Device driver for TCG/TCPA TPM (trusted platform module).
+ * Specifications at www.trustedcomputinggroup.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, version 2 of the
+ * License.
+ *
+ */
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+
+#define TPM_TIMEOUT msecs_to_jiffies(5)
+
+/* TPM addresses */
+#define TPM_ADDR 0x4E
+#define TPM_DATA 0x4F
+
+struct tpm_chip;
+
+struct tpm_vendor_specific {
+ u8 req_complete_mask;
+ u8 req_complete_val;
+ u16 base; /* TPM base address */
+
+ int (*recv) (struct tpm_chip *, u8 *, size_t);
+ int (*send) (struct tpm_chip *, u8 *, size_t);
+ void (*cancel) (struct tpm_chip *);
+ struct miscdevice miscdev;
+};
+
+struct tpm_chip {
+ struct pci_dev *pci_dev; /* PCI device stuff */
+
+ int dev_num; /* /dev/tpm# */
+ int num_opens; /* only one allowed */
+ int time_expired;
+
+ /* Data passed to and from the tpm via the read/write calls */
+ u8 *data_buffer;
+ atomic_t data_pending;
+ struct semaphore buffer_mutex;
+
+ struct timer_list user_read_timer; /* user needs to claim result */
+ struct semaphore tpm_mutex; /* tpm is processing */
+ struct timer_list device_timer; /* tpm is processing */
+ struct semaphore timer_manipulation_mutex;
+
+ struct tpm_vendor_specific *vendor;
+
+ struct list_head list;
+};
+
+static inline int tpm_read_index(int index)
+{
+ outb(index, TPM_ADDR);
+ return inb(TPM_DATA) & 0xFF;
+}
+
+static inline void tpm_write_index(int index, int value)
+{
+ outb(index, TPM_ADDR);
+ outb(value & 0xFF, TPM_DATA);
+}
+
+extern void tpm_time_expired(unsigned long);
+extern int tpm_lpc_bus_init(struct pci_dev *, u16);
+
+extern int tpm_register_hardware(struct pci_dev *,
+ struct tpm_vendor_specific *);
+extern int tpm_open(struct inode *, struct file *);
+extern int tpm_release(struct inode *, struct file *);
+extern ssize_t tpm_write(struct file *, const char __user *, size_t,
+ loff_t *);
+extern ssize_t tpm_read(struct file *, char __user *, size_t, loff_t *);
+extern void __devexit tpm_remove(struct pci_dev *);
+extern int tpm_pm_suspend(struct pci_dev *, u32);
+extern int tpm_pm_resume(struct pci_dev *);
diff --git a/drivers/char/tpm/tpm_atmel.c b/drivers/char/tpm/tpm_atmel.c
new file mode 100644
index 0000000000000..f9333e729b623
--- /dev/null
+++ b/drivers/char/tpm/tpm_atmel.c
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2004 IBM Corporation
+ *
+ * Authors:
+ * Leendert van Doorn <leendert@watson.ibm.com>
+ * Dave Safford <safford@watson.ibm.com>
+ * Reiner Sailer <sailer@watson.ibm.com>
+ * Kylene Hall <kjhall@us.ibm.com>
+ *
+ * Maintained by: <tpmdd_devel@lists.sourceforge.net>
+ *
+ * Device driver for TCG/TCPA TPM (trusted platform module).
+ * Specifications at www.trustedcomputinggroup.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, version 2 of the
+ * License.
+ *
+ */
+
+#include "tpm.h"
+
+/* Atmel definitions */
+#define TPM_ATML_BASE 0x400
+
+/* write status bits */
+#define ATML_STATUS_ABORT 0x01
+#define ATML_STATUS_LASTBYTE 0x04
+
+/* read status bits */
+#define ATML_STATUS_BUSY 0x01
+#define ATML_STATUS_DATA_AVAIL 0x02
+#define ATML_STATUS_REWRITE 0x04
+
+
+static int tpm_atml_recv(struct tpm_chip *chip, u8 * buf, size_t count)
+{
+ u8 status, *hdr = buf;
+ u32 size;
+ int i;
+ __be32 *native_size;
+
+ /* start reading header */
+ if (count < 6)
+ return -EIO;
+
+ for (i = 0; i < 6; i++) {
+ status = inb(chip->vendor->base + 1);
+ if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
+ dev_err(&chip->pci_dev->dev,
+ "error reading header\n");
+ return -EIO;
+ }
+ *buf++ = inb(chip->vendor->base);
+ }
+
+ /* size of the data received */
+ native_size = (__force __be32 *) (hdr + 2);
+ size = be32_to_cpu(*native_size);
+
+ if (count < size) {
+ dev_err(&chip->pci_dev->dev,
+ "Recv size(%d) less than available space\n", size);
+ for (; i < size; i++) { /* clear the waiting data anyway */
+ status = inb(chip->vendor->base + 1);
+ if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
+ dev_err(&chip->pci_dev->dev,
+ "error reading data\n");
+ return -EIO;
+ }
+ }
+ return -EIO;
+ }
+
+ /* read all the data available */
+ for (; i < size; i++) {
+ status = inb(chip->vendor->base + 1);
+ if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
+ dev_err(&chip->pci_dev->dev,
+ "error reading data\n");
+ return -EIO;
+ }
+ *buf++ = inb(chip->vendor->base);
+ }
+
+ /* make sure data available is gone */
+ status = inb(chip->vendor->base + 1);
+ if (status & ATML_STATUS_DATA_AVAIL) {
+ dev_err(&chip->pci_dev->dev, "data available is stuck\n");
+ return -EIO;
+ }
+
+ return size;
+}
+
+static int tpm_atml_send(struct tpm_chip *chip, u8 * buf, size_t count)
+{
+ int i;
+
+ dev_dbg(&chip->pci_dev->dev, "tpm_atml_send: ");
+ for (i = 0; i < count; i++) {
+ dev_dbg(&chip->pci_dev->dev, "0x%x(%d) ", buf[i], buf[i]);
+ outb(buf[i], chip->vendor->base);
+ }
+
+ return count;
+}
+
+static void tpm_atml_cancel(struct tpm_chip *chip)
+{
+ outb(ATML_STATUS_ABORT, chip->vendor->base + 1);
+}
+
+static struct file_operations atmel_ops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .open = tpm_open,
+ .read = tpm_read,
+ .write = tpm_write,
+ .release = tpm_release,
+};
+
+static struct tpm_vendor_specific tpm_atmel = {
+ .recv = tpm_atml_recv,
+ .send = tpm_atml_send,
+ .cancel = tpm_atml_cancel,
+ .req_complete_mask = ATML_STATUS_BUSY | ATML_STATUS_DATA_AVAIL,
+ .req_complete_val = ATML_STATUS_DATA_AVAIL,
+ .base = TPM_ATML_BASE,
+ .miscdev = { .fops = &atmel_ops, },
+};
+
+static int __devinit tpm_atml_init(struct pci_dev *pci_dev,
+ const struct pci_device_id *pci_id)
+{
+ u8 version[4];
+ int rc = 0;
+
+ if (pci_enable_device(pci_dev))
+ return -EIO;
+
+ if (tpm_lpc_bus_init(pci_dev, TPM_ATML_BASE)) {
+ rc = -ENODEV;
+ goto out_err;
+ }
+
+ /* verify that it is an Atmel part */
+ if (tpm_read_index(4) != 'A' || tpm_read_index(5) != 'T'
+ || tpm_read_index(6) != 'M' || tpm_read_index(7) != 'L') {
+ rc = -ENODEV;
+ goto out_err;
+ }
+
+ /* query chip for its version number */
+ if ((version[0] = tpm_read_index(0x00)) != 0xFF) {
+ version[1] = tpm_read_index(0x01);
+ version[2] = tpm_read_index(0x02);
+ version[3] = tpm_read_index(0x03);
+ } else {
+ dev_info(&pci_dev->dev, "version query failed\n");
+ rc = -ENODEV;
+ goto out_err;
+ }
+
+ if ((rc = tpm_register_hardware(pci_dev, &tpm_atmel)) < 0)
+ goto out_err;
+
+ dev_info(&pci_dev->dev,
+ "Atmel TPM version %d.%d.%d.%d\n", version[0], version[1],
+ version[2], version[3]);
+
+ return 0;
+out_err:
+ pci_disable_device(pci_dev);
+ return rc;
+}
+
+static struct pci_device_id tpm_pci_tbl[] __devinitdata = {
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0)},
+ {PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_LPC)},
+ {0,}
+};
+
+MODULE_DEVICE_TABLE(pci, tpm_pci_tbl);
+
+static struct pci_driver atmel_pci_driver = {
+ .name = "tpm_atmel",
+ .id_table = tpm_pci_tbl,
+ .probe = tpm_atml_init,
+ .remove = __devexit_p(tpm_remove),
+ .suspend = tpm_pm_suspend,
+ .resume = tpm_pm_resume,
+};
+
+static int __init init_atmel(void)
+{
+ return pci_register_driver(&atmel_pci_driver);
+}
+
+static void __exit cleanup_atmel(void)
+{
+ pci_unregister_driver(&atmel_pci_driver);
+}
+
+module_init(init_atmel);
+module_exit(cleanup_atmel);
+
+MODULE_AUTHOR("Leendert van Doorn (leendert@watson.ibm.com)");
+MODULE_DESCRIPTION("TPM Driver");
+MODULE_VERSION("2.0");
+MODULE_LICENSE("GPL");
diff --git a/drivers/char/tpm/tpm_nsc.c b/drivers/char/tpm/tpm_nsc.c
new file mode 100644
index 0000000000000..9cce833a09237
--- /dev/null
+++ b/drivers/char/tpm/tpm_nsc.c
@@ -0,0 +1,373 @@
+/*
+ * Copyright (C) 2004 IBM Corporation
+ *
+ * Authors:
+ * Leendert van Doorn <leendert@watson.ibm.com>
+ * Dave Safford <safford@watson.ibm.com>
+ * Reiner Sailer <sailer@watson.ibm.com>
+ * Kylene Hall <kjhall@us.ibm.com>
+ *
+ * Maintained by: <tpmdd_devel@lists.sourceforge.net>
+ *
+ * Device driver for TCG/TCPA TPM (trusted platform module).
+ * Specifications at www.trustedcomputinggroup.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, version 2 of the
+ * License.
+ *
+ */
+
+#include "tpm.h"
+
+/* National definitions */
+#define TPM_NSC_BASE 0x360
+#define TPM_NSC_IRQ 0x07
+
+#define NSC_LDN_INDEX 0x07
+#define NSC_SID_INDEX 0x20
+#define NSC_LDC_INDEX 0x30
+#define NSC_DIO_INDEX 0x60
+#define NSC_CIO_INDEX 0x62
+#define NSC_IRQ_INDEX 0x70
+#define NSC_ITS_INDEX 0x71
+
+#define NSC_STATUS 0x01
+#define NSC_COMMAND 0x01
+#define NSC_DATA 0x00
+
+/* status bits */
+#define NSC_STATUS_OBF 0x01 /* output buffer full */
+#define NSC_STATUS_IBF 0x02 /* input buffer full */
+#define NSC_STATUS_F0 0x04 /* F0 */
+#define NSC_STATUS_A2 0x08 /* A2 */
+#define NSC_STATUS_RDY 0x10 /* ready to receive command */
+#define NSC_STATUS_IBR 0x20 /* ready to receive data */
+
+/* command bits */
+#define NSC_COMMAND_NORMAL 0x01 /* normal mode */
+#define NSC_COMMAND_EOC 0x03
+#define NSC_COMMAND_CANCEL 0x22
+
+/*
+ * Wait for a certain status to appear
+ */
+static int wait_for_stat(struct tpm_chip *chip, u8 mask, u8 val, u8 * data)
+{
+ int expired = 0;
+ struct timer_list status_timer =
+ TIMER_INITIALIZER(tpm_time_expired, jiffies + 10 * HZ,
+ (unsigned long) &expired);
+
+ /* status immediately available check */
+ *data = inb(chip->vendor->base + NSC_STATUS);
+ if ((*data & mask) == val)
+ return 0;
+
+ /* wait for status */
+ add_timer(&status_timer);
+ do {
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(TPM_TIMEOUT);
+ *data = inb(chip->vendor->base + 1);
+ if ((*data & mask) == val) {
+ del_singleshot_timer_sync(&status_timer);
+ return 0;
+ }
+ }
+ while (!expired);
+
+ return -EBUSY;
+}
+
+static int nsc_wait_for_ready(struct tpm_chip *chip)
+{
+ int status;
+ int expired = 0;
+ struct timer_list status_timer =
+ TIMER_INITIALIZER(tpm_time_expired, jiffies + 100,
+ (unsigned long) &expired);
+
+ /* status immediately available check */
+ status = inb(chip->vendor->base + NSC_STATUS);
+ if (status & NSC_STATUS_OBF)
+ status = inb(chip->vendor->base + NSC_DATA);
+ if (status & NSC_STATUS_RDY)
+ return 0;
+
+ /* wait for status */
+ add_timer(&status_timer);
+ do {
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(TPM_TIMEOUT);
+ status = inb(chip->vendor->base + NSC_STATUS);
+ if (status & NSC_STATUS_OBF)
+ status = inb(chip->vendor->base + NSC_DATA);
+ if (status & NSC_STATUS_RDY) {
+ del_singleshot_timer_sync(&status_timer);
+ return 0;
+ }
+ }
+ while (!expired);
+
+ dev_info(&chip->pci_dev->dev, "wait for ready failed\n");
+ return -EBUSY;
+}
+
+
+static int tpm_nsc_recv(struct tpm_chip *chip, u8 * buf, size_t count)
+{
+ u8 *buffer = buf;
+ u8 data, *p;
+ u32 size;
+ __be32 *native_size;
+
+ if (count < 6)
+ return -EIO;
+
+ if (wait_for_stat(chip, NSC_STATUS_F0, NSC_STATUS_F0, &data) < 0) {
+ dev_err(&chip->pci_dev->dev, "F0 timeout\n");
+ return -EIO;
+ }
+ if ((data =
+ inb(chip->vendor->base + NSC_DATA)) != NSC_COMMAND_NORMAL) {
+ dev_err(&chip->pci_dev->dev, "not in normal mode (0x%x)\n",
+ data);
+ return -EIO;
+ }
+
+ /* read the whole packet */
+ for (p = buffer; p < &buffer[count]; p++) {
+ if (wait_for_stat
+ (chip, NSC_STATUS_OBF, NSC_STATUS_OBF, &data) < 0) {
+ dev_err(&chip->pci_dev->dev,
+ "OBF timeout (while reading data)\n");
+ return -EIO;
+ }
+ if (data & NSC_STATUS_F0)
+ break;
+ *p = inb(chip->vendor->base + NSC_DATA);
+ }
+
+ if ((data & NSC_STATUS_F0) == 0) {
+ dev_err(&chip->pci_dev->dev, "F0 not set\n");
+ return -EIO;
+ }
+ if ((data = inb(chip->vendor->base + NSC_DATA)) != NSC_COMMAND_EOC) {
+ dev_err(&chip->pci_dev->dev,
+ "expected end of command(0x%x)\n", data);
+ return -EIO;
+ }
+
+ native_size = (__force __be32 *) (buf + 2);
+ size = be32_to_cpu(*native_size);
+
+ if (count < size)
+ return -EIO;
+
+ return size;
+}
+
+static int tpm_nsc_send(struct tpm_chip *chip, u8 * buf, size_t count)
+{
+ u8 data;
+ int i;
+
+ /*
+ * If we hit the chip with back to back commands it locks up
+ * and never set IBF. Hitting it with this "hammer" seems to
+ * fix it. Not sure why this is needed, we followed the flow
+ * chart in the manual to the letter.
+ */
+ outb(NSC_COMMAND_CANCEL, chip->vendor->base + NSC_COMMAND);
+
+ if (nsc_wait_for_ready(chip) != 0)
+ return -EIO;
+
+ if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) {
+ dev_err(&chip->pci_dev->dev, "IBF timeout\n");
+ return -EIO;
+ }
+
+ outb(NSC_COMMAND_NORMAL, chip->vendor->base + NSC_COMMAND);
+ if (wait_for_stat(chip, NSC_STATUS_IBR, NSC_STATUS_IBR, &data) < 0) {
+ dev_err(&chip->pci_dev->dev, "IBR timeout\n");
+ return -EIO;
+ }
+
+ for (i = 0; i < count; i++) {
+ if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) {
+ dev_err(&chip->pci_dev->dev,
+ "IBF timeout (while writing data)\n");
+ return -EIO;
+ }
+ outb(buf[i], chip->vendor->base + NSC_DATA);
+ }
+
+ if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) {
+ dev_err(&chip->pci_dev->dev, "IBF timeout\n");
+ return -EIO;
+ }
+ outb(NSC_COMMAND_EOC, chip->vendor->base + NSC_COMMAND);
+
+ return count;
+}
+
+static void tpm_nsc_cancel(struct tpm_chip *chip)
+{
+ outb(NSC_COMMAND_CANCEL, chip->vendor->base + NSC_COMMAND);
+}
+
+static struct file_operations nsc_ops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .open = tpm_open,
+ .read = tpm_read,
+ .write = tpm_write,
+ .release = tpm_release,
+};
+
+static struct tpm_vendor_specific tpm_nsc = {
+ .recv = tpm_nsc_recv,
+ .send = tpm_nsc_send,
+ .cancel = tpm_nsc_cancel,
+ .req_complete_mask = NSC_STATUS_OBF,
+ .req_complete_val = NSC_STATUS_OBF,
+ .base = TPM_NSC_BASE,
+ .miscdev = { .fops = &nsc_ops, },
+
+};
+
+static int __devinit tpm_nsc_init(struct pci_dev *pci_dev,
+ const struct pci_device_id *pci_id)
+{
+ int rc = 0;
+
+ if (pci_enable_device(pci_dev))
+ return -EIO;
+
+ if (tpm_lpc_bus_init(pci_dev, TPM_NSC_BASE)) {
+ rc = -ENODEV;
+ goto out_err;
+ }
+
+ /* verify that it is a National part (SID) */
+ if (tpm_read_index(NSC_SID_INDEX) != 0xEF) {
+ rc = -ENODEV;
+ goto out_err;
+ }
+
+ dev_dbg(&pci_dev->dev, "NSC TPM detected\n");
+ dev_dbg(&pci_dev->dev,
+ "NSC LDN 0x%x, SID 0x%x, SRID 0x%x\n",
+ tpm_read_index(0x07), tpm_read_index(0x20),
+ tpm_read_index(0x27));
+ dev_dbg(&pci_dev->dev,
+ "NSC SIOCF1 0x%x SIOCF5 0x%x SIOCF6 0x%x SIOCF8 0x%x\n",
+ tpm_read_index(0x21), tpm_read_index(0x25),
+ tpm_read_index(0x26), tpm_read_index(0x28));
+ dev_dbg(&pci_dev->dev, "NSC IO Base0 0x%x\n",
+ (tpm_read_index(0x60) << 8) | tpm_read_index(0x61));
+ dev_dbg(&pci_dev->dev, "NSC IO Base1 0x%x\n",
+ (tpm_read_index(0x62) << 8) | tpm_read_index(0x63));
+ dev_dbg(&pci_dev->dev, "NSC Interrupt number and wakeup 0x%x\n",
+ tpm_read_index(0x70));
+ dev_dbg(&pci_dev->dev, "NSC IRQ type select 0x%x\n",
+ tpm_read_index(0x71));
+ dev_dbg(&pci_dev->dev,
+ "NSC DMA channel select0 0x%x, select1 0x%x\n",
+ tpm_read_index(0x74), tpm_read_index(0x75));
+ dev_dbg(&pci_dev->dev,
+ "NSC Config "
+ "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
+ tpm_read_index(0xF0), tpm_read_index(0xF1),
+ tpm_read_index(0xF2), tpm_read_index(0xF3),
+ tpm_read_index(0xF4), tpm_read_index(0xF5),
+ tpm_read_index(0xF6), tpm_read_index(0xF7),
+ tpm_read_index(0xF8), tpm_read_index(0xF9));
+
+ dev_info(&pci_dev->dev,
+ "NSC PC21100 TPM revision %d\n",
+ tpm_read_index(0x27) & 0x1F);
+
+ if (tpm_read_index(NSC_LDC_INDEX) == 0)
+ dev_info(&pci_dev->dev, ": NSC TPM not active\n");
+
+ /* select PM channel 1 */
+ tpm_write_index(NSC_LDN_INDEX, 0x12);
+ tpm_read_index(NSC_LDN_INDEX);
+
+ /* disable the DPM module */
+ tpm_write_index(NSC_LDC_INDEX, 0);
+ tpm_read_index(NSC_LDC_INDEX);
+
+ /* set the data register base addresses */
+ tpm_write_index(NSC_DIO_INDEX, TPM_NSC_BASE >> 8);
+ tpm_write_index(NSC_DIO_INDEX + 1, TPM_NSC_BASE);
+ tpm_read_index(NSC_DIO_INDEX);
+ tpm_read_index(NSC_DIO_INDEX + 1);
+
+ /* set the command register base addresses */
+ tpm_write_index(NSC_CIO_INDEX, (TPM_NSC_BASE + 1) >> 8);
+ tpm_write_index(NSC_CIO_INDEX + 1, (TPM_NSC_BASE + 1));
+ tpm_read_index(NSC_DIO_INDEX);
+ tpm_read_index(NSC_DIO_INDEX + 1);
+
+ /* set the interrupt number to be used for the host interface */
+ tpm_write_index(NSC_IRQ_INDEX, TPM_NSC_IRQ);
+ tpm_write_index(NSC_ITS_INDEX, 0x00);
+ tpm_read_index(NSC_IRQ_INDEX);
+
+ /* enable the DPM module */
+ tpm_write_index(NSC_LDC_INDEX, 0x01);
+ tpm_read_index(NSC_LDC_INDEX);
+
+ if ((rc = tpm_register_hardware(pci_dev, &tpm_nsc)) < 0)
+ goto out_err;
+
+ return 0;
+
+out_err:
+ pci_disable_device(pci_dev);
+ return rc;
+}
+
+static struct pci_device_id tpm_pci_tbl[] __devinitdata = {
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0)},
+ {PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_LPC)},
+ {0,}
+};
+
+MODULE_DEVICE_TABLE(pci, tpm_pci_tbl);
+
+static struct pci_driver nsc_pci_driver = {
+ .name = "tpm_nsc",
+ .id_table = tpm_pci_tbl,
+ .probe = tpm_nsc_init,
+ .remove = __devexit_p(tpm_remove),
+ .suspend = tpm_pm_suspend,
+ .resume = tpm_pm_resume,
+};
+
+static int __init init_nsc(void)
+{
+ return pci_register_driver(&nsc_pci_driver);
+}
+
+static void __exit cleanup_nsc(void)
+{
+ pci_unregister_driver(&nsc_pci_driver);
+}
+
+module_init(init_nsc);
+module_exit(cleanup_nsc);
+
+MODULE_AUTHOR("Leendert van Doorn (leendert@watson.ibm.com)");
+MODULE_DESCRIPTION("TPM Driver");
+MODULE_VERSION("2.0");
+MODULE_LICENSE("GPL");
diff --git a/drivers/char/tpqic02.c b/drivers/char/tpqic02.c
deleted file mode 100644
index d812253b44732..0000000000000
--- a/drivers/char/tpqic02.c
+++ /dev/null
@@ -1,2812 +0,0 @@
-/* $Id: tpqic02.c,v 1.10 1997/01/26 07:13:20 davem Exp $
- *
- * Driver for tape drive support for Linux-i386
- *
- * Copyright (c) 1992--1996 by H. H. Bergman. All rights reserved.
- * Current e-mail address: hennus@cybercomm.nl
- *
- * Distribution of this program in executable form is only allowed if
- * all of the corresponding source files are made available through the same
- * medium at no extra cost.
- *
- * I will not accept any responsibility for damage caused directly or
- * indirectly by this program, or code derived from this program.
- *
- * Use this code at your own risk. Don't blame me if it destroys your data!
- * Make sure you have a backup before you try this code.
- *
- * If you make changes to my code and redistribute it in source or binary
- * form you must make it clear to even casual users of your code that you
- * have modified my code, clearly point out what the changes exactly are
- * (preferably in the form of a context diff file), how to undo your changes,
- * where the original can be obtained, and that complaints/requests about the
- * modified code should be directed to you instead of me.
- *
- * This driver was partially inspired by the 'wt' driver in the 386BSD
- * source distribution, which carries the following copyright notice:
- *
- * Copyright (c) 1991 The Regents of the University of California.
- * All rights reserved.
- *
- * You are not allowed to change this line nor the text above.
- *
- * 2001/02/26 Minor s/suser/capable/
- *
- * 1996/10/10 Emerald changes
- *
- * 1996/05/21 Misc changes+merges+cleanups + I/O reservations
- *
- * 1996/05/20 Module support patches submitted by Brian McCauley.
- *
- * 1994/05/03 Initial attempt at Mountain support for the Mountain 7150.
- * Based on patches provided by Erik Jacobson. Still incomplete, I suppose.
- *
- * 1994/02/07 Archive changes & some cleanups by Eddy Olk.
- *
- * 1994/01/19 Speed measuring stuff moved from aperf.h to delay.h.
- * BogoMips (tm) introduced by Linus.
- *
- * 1993/01/25 Kernel udelay. Eof fixups.
- *
- * 1992/09/19 Some changes based on patches by Eddy Olk to support
- * Archive SC402/SC499R controller cards.
- *
- * 1992/05/27 First release.
- *
- * 1992/05/26 Initial version. Copyright H. H. Bergman 1992
- */
-
-/* After the legalese, now the important bits:
- *
- * This is a driver for the Wangtek 5150 tape drive with
- * a QIC-02 controller for ISA-PC type computers.
- * Hopefully it will work with other QIC-02 tape drives as well.
- *
- * Make sure your setup matches the configuration parameters.
- * Also, be careful to avoid IO conflicts with other devices!
- */
-
-
-/*
-#define TDEBUG
-*/
-
-#define REALLY_SLOW_IO /* it sure is ... */
-
-#include <linux/module.h>
-
-#include <linux/config.h>
-
-#include <linux/interrupt.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/major.h>
-#include <linux/errno.h>
-#include <linux/mtio.h>
-#include <linux/fcntl.h>
-#include <linux/delay.h>
-#include <linux/ioport.h>
-#include <linux/tpqic02.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/smp_lock.h>
-#include <linux/devfs_fs_kernel.h>
-#include <linux/device.h>
-
-#include <asm/dma.h>
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-
-/* check existence of required configuration parameters */
-#if !defined(QIC02_CMD_PORT) || !defined(QIC02_TAPE_IRQ) || !defined(QIC02_TAPE_DMA)
-# error qic02_tape configuration error
-#endif
-
-
-#define TPQIC02_NAME "tpqic02"
-
-/* Linux outb() commands have (value,port) as parameters.
- * One might expect (port,value) instead, so beware!
- */
-
-#ifdef CONFIG_QIC02_DYNCONF
-/* This holds the dynamic configuration info for the interface
- * card+drive info if runtime configuration has been selected.
- */
-
-static struct mtconfiginfo qic02_tape_dynconf = {
- /* user settable */
- 0, 0, BOGUS_IRQ, 0, 0, TPQD_DEFAULT_FLAGS,
-};
-static struct qic02_ccb qic02_tape_ccb; /* private stuff */
-
-#else
-
-static unsigned long qic02_tape_debug = TPQD_DEFAULT_FLAGS;
-
-# if ((QIC02_TAPE_IFC!=WANGTEK) && (QIC02_TAPE_IFC!=ARCHIVE) && (QIC02_TAPE_IFC!=MOUNTAIN))
-# error No valid interface card specified
-# endif
-#endif /* CONFIG_QIC02_DYNCONF */
-
-static int ctlbits; /* control reg bits for tape interface */
-
-static wait_queue_head_t qic02_tape_transfer; /* sync rw with interrupts */
-
-static struct mtget ioctl_status; /* current generic status */
-
-static struct tpstatus tperror; /* last drive status */
-
-static char rcs_revision[] = "$Revision: 1.10 $";
-static char rcs_date[] = "$Date: 1997/01/26 07:13:20 $";
-
-/* Flag bits for status and outstanding requests.
- * (Could all be put in one bit-field-struct.)
- * Some variables need `volatile' because they may be modified
- * by an interrupt.
- */
-static flag status_dead = YES; /* device is legally dead until proven alive */
-static flag status_zombie = YES; /* it's `zombie' until irq/dma allocated */
-
-static flag status_bytes_wr = NO; /* write FM at close or not */
-static flag status_bytes_rd = NO; /* (rd|wr) used for rewinding */
-
-static volatile unsigned long status_cmd_pending; /* cmd in progress */
-static flag status_expect_int = NO; /* ready for interrupts */
-static flag status_timer_on = NO; /* using time-out */
-static int status_error; /* int handler may detect error */
-static flag status_eof_detected = NO; /* end of file */
-static flag status_eom_detected = NO; /* end of recorded media */
-static flag status_eot_detected = NO; /* end of tape */
-static flag doing_read = NO;
-static flag doing_write = NO;
-
-static unsigned long dma_bytes_todo;
-static unsigned long dma_bytes_done;
-static volatile unsigned dma_mode; /* !=0 also means DMA in use */
-static flag need_rewind = YES;
-
-static int current_type;
-static int extra_blocks_left = BLOCKS_BEYOND_EW;
-static struct timer_list tp_timer;
-
-static unsigned long tape_open; /* Guard open one only */
-static DECLARE_MUTEX(tape_op); /* Serialize tape operations */
-
-/* return_*_eof:
- * NO: not at EOF,
- * YES: tell app EOF was reached (return 0).
- *
- * return_*_eof==YES && reported_*_eof==NO ==>
- * return current buffer, next time(s) return EOF.
- *
- * return_*_eof==YES && reported_*_eof==YES ==>
- * at EOF and application knows it, so we can
- * move on to the next file.
- *
- */
-
-static flag return_read_eof = NO; /* set to signal app EOF was reached */
-static flag return_write_eof = NO;
-static flag reported_read_eof = NO; /* set when we've done that */
-static flag reported_write_eof = NO;
-
-
-/* This is for doing `mt seek <blocknr>' */
-static char seek_addr_buf[AR_SEEK_BUF_SIZE];
-
-
-/* In write mode, we have to write a File Mark after the last block written,
- * when the tape device is closed. Tape repositioning and reading in write
- * mode is allowed as long as no actual writing has been done. After writing
- * the File Mark, repositioning and reading are allowed again.
- */
-static int mode_access; /* access mode: READ or WRITE */
-
-static int qic02_get_resources(void);
-static void qic02_release_resources(void);
-
-/* This is a pointer to the actual kernel buffer where the interrupt routines
- * read from/write to. It is needed because the DMA channels 1 and 3 cannot
- * always access the user buffers. [The kernel buffer must reside in the
- * lower 16MBytes of system memory because of the DMA controller.] The user
- * must ensure that a large enough buffer is passed to the kernel, in order
- * to reduce tape repositioning wear and tear.
- */
-static void *buffaddr; /* virtual address of buffer */
-
-/* This translates minor numbers to the corresponding recording format: */
-static const char *format_names[] = {
- "not set", /* for dumb drives unable to handle format selection */
- "11", /* extinct */
- "24",
- "120",
- "150",
- "300", /* untested. */
- "600" /* untested. */
-};
-
-static struct class_simple *tpqic02_class;
-
-
-/* `exception_list' is needed for exception status reporting.
- * Exceptions 1..14 are defined by QIC-02 rev F.
- * The drive status is matched sequentially to each entry,
- * ignoring irrelevant bits, until a match is found. If no
- * match is found, exception number 0 is used. (That should of
- * course never happen...) The original table was based on the
- * "Exception Status Summary" in QIC-02 rev F, but some changes
- * were required to make it work with real-world drives.
- *
- * Exception 2 (CNI) is changed to also cover status 0x00e0 (mask USL),
- * Exception 4 (EOM) is changed to also cover status 0x8288 (mask EOR),
- * Exception 11 (FIL) is changed to also cover status 0x0089 (mask EOM).
- * Exception 15 (EOR) is added for seek-to-end-of-data (catch EOR),
- * Exception 16 (BOM) is added for beginning-of-media (catch BOM).
- *
- * Had to swap EXC_NDRV and EXC_NCART to ensure that extended EXC_NCART
- * (because of the incorrect Wangtek status code) doesn't catch the
- * EXC_NDRV first.
- */
-static struct exception_list_type {
- unsigned short mask, code;
- const char *msg;
- /* EXC_nr attribute should match with tpqic02.h */
-} exception_list[] = {
- { 0, 0, "Unknown exception status code", /* extra: 0 */ },
- { ~(0), TP_ST0 | TP_CNI | TP_USL | TP_WRP, "Drive not online" /* 1 */ }, /* Drive presence goes before cartridge presence. */
- { ~(TP_WRP | TP_USL), TP_ST0 | TP_CNI,
- /* My Wangtek 5150EQ sometimes reports a status code
- * of 0x00e0, which is not a valid exception code, but
- * I think it should be recognized as "NO CARTRIDGE".
- */
- "Cartridge not in place" /* 2 */ },
- { (unsigned short) ~(TP_ST1 | TP_BOM), (TP_ST0 | TP_WRP), "Write protected cartridge" /* 3 */ },
- { (unsigned short) ~(TP_ST1 | TP_EOR), (TP_ST0 | TP_EOM), "End of media" /* 4 */ },
- { ~TP_WRP, TP_ST0 | TP_UDA | TP_ST1 | TP_BOM, "Read or Write abort. Rewind tape." /* 5 */ },
- { ~TP_WRP, TP_ST0 | TP_UDA, "Read error. Bad block transferred." /* 6 */ },
- { ~TP_WRP, TP_ST0 | TP_UDA | TP_BNL, "Read error. Filler block transferred." /* 7 */ },
- { ~TP_WRP, TP_ST0 | TP_UDA | TP_BNL | TP_ST1 | TP_NDT, "Read error. No data detected." /* 8 */ },
- { ~TP_WRP, TP_ST0 | TP_EOM | TP_UDA | TP_BNL | TP_ST1 | TP_NDT, "Read error. No data detected. EOM." /* 9 */ },
- { ~(TP_WRP | TP_MBD | TP_PAR | TP_EOR), TP_ST0 | TP_UDA | TP_BNL | TP_ST1 | TP_NDT | TP_BOM, "Read error. No data detected. BOM." /* 10 */ },
- { ~(TP_WRP | TP_EOM), TP_ST0 | TP_FIL,
- /* Status 0x0089 (EOM & FM) is viewed as an FM,
- * because it can only happen during a read.
- * EOM is checked separately for an FM condition.
- */
- "File mark detected" /* 11 */ },
- { ~(TP_ST0 | TP_CNI | TP_USL | TP_WRP | TP_BOM), TP_ST1 | TP_ILL, "Illegal command" /* 12 */ },
- { ~(TP_ST0 | TP_CNI | TP_USL | TP_WRP | TP_BOM), TP_ST1 | TP_POR, "Reset occurred" /* 13 */ },
- { ~TP_WRP, TP_ST0 | TP_FIL | TP_MBD, /* NOTE: ST1 not set! */ "Marginal block detected" /* 14 */ },
- { ~(TP_ST0 | TP_WRP | TP_EOM | TP_UDA | TP_BNL | TP_FIL | TP_NDT), TP_ST1 | TP_EOR, /********** Is the extra TP_NDT really needed Eddy? **********/ "End of recorded media" /* extra: 15 */ },
- /* 15 is returned when SEEKEOD completes successfully */
- { ~(TP_WRP | TP_ST0), TP_ST1 | TP_BOM, "Beginning of media" /* extra: 16 */ }
-};
-
-#define NR_OF_EXC (sizeof(exception_list)/sizeof(struct exception_list_type))
-
-/* Compare expected struct size and actual struct size. This
- * is useful to catch programs compiled with old #includes.
- */
-#define CHECK_IOC_SIZE(structure) \
- if (_IOC_SIZE(iocmd) != sizeof(struct structure)) { \
- tpqputs(TPQD_ALWAYS, "sizeof(struct " #structure \
- ") does not match!"); \
- return -EFAULT; \
- } \
-
-static void tpqputs(unsigned long flags, const char *s)
-{
- if ((flags & TPQD_ALWAYS) || (flags & QIC02_TAPE_DEBUG))
- printk(TPQIC02_NAME ": %s\n", s);
-} /* tpqputs */
-
-
-/* Init control register bits on interface card.
- * For Archive, interrupts must be enabled explicitly.
- * Wangtek interface card requires ONLINE to be set, Archive SC402/SC499R
- * cards keep it active all the time.
- */
-
-static void ifc_init(void)
-{
- if (QIC02_TAPE_IFC == WANGTEK) { /* || (QIC02_TAPE_IFC == EVEREX) */
- ctlbits = WT_CTL_ONLINE; /* online */
- outb_p(ctlbits, QIC02_CTL_PORT);
- } else if (QIC02_TAPE_IFC == ARCHIVE) {
- ctlbits = 0; /* no interrupts yet */
- outb_p(ctlbits, QIC02_CTL_PORT);
- outb_p(0, AR_RESET_DMA_PORT); /* dummy write to reset DMA */
- } else { /* MOUNTAIN */
-
- ctlbits = MTN_CTL_ONLINE; /* online, and logic enabled */
- outb_p(ctlbits, QIC02_CTL_PORT);
- }
-} /* ifc_init */
-
-
-static void report_qic_exception(unsigned n)
-{
- if (n >= NR_OF_EXC) {
- tpqputs(TPQD_ALWAYS, "Oops -- report_qic_exception");
- n = 0;
- }
- if (TPQDBG(SENSE_TEXT) || n == 0)
- printk(TPQIC02_NAME ": sense: %s\n", exception_list[n].msg);
-} /* report_qic_exception */
-
-
-/* Try to map the drive-exception bits `s' to a predefined "exception number",
- * by comparing the significant exception bits for each entry in the
- * exception table (`exception_list[]').
- * It is assumed that s!=0.
- */
-static int decode_qic_exception_nr(unsigned s)
-{
- int i;
-
- for (i = 1; i < NR_OF_EXC; i++) {
- if ((s & exception_list[i].mask) == exception_list[i].code) {
- return i;
- }
- }
- printk(TPQIC02_NAME ": decode_qic_exception_nr: exception(%x) not recognized\n", s);
- return 0;
-} /* decode_qic_exception_nr */
-
-
-
-/* Perform appropriate action for certain exceptions.
- * should return a value to indicate stop/continue (in case of bad blocks)
- */
-static void handle_qic_exception(int exnr, int exbits)
-{
- if (exnr == EXC_NCART) {
- /* Cartridge was changed. Redo sense().
- * EXC_NCART should be handled in open().
- * It is not permitted to remove the tape while
- * the tape driver has open files.
- */
- need_rewind = YES;
- status_eof_detected = NO;
- status_eom_detected = NO;
- } else if (exnr == EXC_XFILLER) {
- tpqputs(TPQD_ALWAYS,
- "[Bad block -- filler data transferred.]");
- } else if (exnr == EXC_XBAD) {
- tpqputs(TPQD_ALWAYS, "[CRC failed!]");
- } else if (exnr == EXC_MARGINAL) {
- /* A marginal block behaves much like a FM.
- * User may continue reading, if desired.
- */
- tpqputs(TPQD_ALWAYS, "[Marginal block]");
- doing_read = NO;
- } else if (exnr == EXC_FM) {
- doing_read = NO;
- }
-} /* handle_qic_exception */
-
-
-static inline int is_exception(void)
-{
- return (inb(QIC02_STAT_PORT) & QIC02_STAT_EXCEPTION) == 0;
-} /* is_exception */
-
-
-/* Reset the tape drive and controller.
- * When reset fails, it marks the drive as dead and all
- * requests (except reset) are to be ignored (ENXIO).
- */
-static int tape_reset(int verbose)
-{
- ifc_init(); /* reset interface card */
-
- /* assert reset */
- if (QIC02_TAPE_IFC == MOUNTAIN) {
- outb_p(ctlbits & ~MTN_QIC02_CTL_RESET_NOT, QIC02_CTL_PORT);
- } else { /* WANGTEK, ARCHIVE */
-
- outb_p(ctlbits | QIC02_CTL_RESET, QIC02_CTL_PORT);
- }
-
- /* Next, we need to wait >=25 usec. */
- udelay(30);
-
- /* after reset, we will be at BOT (modulo an automatic rewind) */
- status_eof_detected = NO;
- status_eom_detected = NO;
- status_cmd_pending = 0;
- need_rewind = YES;
- doing_read = doing_write = NO;
- ioctl_status.mt_fileno = ioctl_status.mt_blkno = 0;
-
- /* de-assert reset */
- if (QIC02_TAPE_IFC == MOUNTAIN) {
- outb_p(ctlbits | MTN_QIC02_CTL_RESET_NOT, QIC02_CTL_PORT);
- } else {
- outb_p(ctlbits & ~QIC02_CTL_RESET, QIC02_CTL_PORT);
- }
-
- /* KLUDGE FOR G++ BUG */
- {
- int stat = inb_p(QIC02_STAT_PORT);
- status_dead = ((stat & QIC02_STAT_RESETMASK) != QIC02_STAT_RESETVAL);
- }
- /* if successful, inb(STAT) returned RESETVAL */
- if (status_dead == YES)
- printk(TPQIC02_NAME ": reset failed!\n");
- else if (verbose)
- printk(TPQIC02_NAME ": reset successful\n");
-
- return (status_dead == YES) ? TE_DEAD : TE_OK;
-} /* tape_reset */
-
-
-
-/* Notify tape drive of a new command. It only waits for the
- * command to be accepted, not for the actual command to complete.
- *
- * Before calling this routine, QIC02_CMD_PORT must have been loaded
- * with the command to be executed.
- * After this routine, the exception bit must be checked.
- * This routine is also used by rdstatus(), so in that case, any exception
- * must be ignored (`ignore_ex' flag).
- */
-static int notify_cmd(char cmd, short ignore_ex)
-{
- int i;
-
- outb_p(cmd, QIC02_CMD_PORT); /* output the command */
-
- /* wait 1 usec before asserting /REQUEST */
- udelay(1);
-
- if ((!ignore_ex) && is_exception()) {
- tpqputs(TPQD_ALWAYS, "*** exception detected in notify_cmd");
- /** force a reset here **/
- if (tape_reset(1) == TE_DEAD)
- return TE_DEAD;
- if (is_exception()) {
- tpqputs(TPQD_ALWAYS, "exception persists after reset.");
- tpqputs(TPQD_ALWAYS, " ^ exception ignored.");
- }
- }
-
- outb_p(ctlbits | QIC02_CTL_REQUEST, QIC02_CTL_PORT); /* set request bit */
- i = TAPE_NOTIFY_TIMEOUT;
- /* The specs say this takes about 500 usec, but there is no upper limit!
- * If the drive were busy retensioning or something like that,
- * it could be *much* longer!
- */
- while ((inb_p(QIC02_STAT_PORT) & QIC02_STAT_READY) && (--i > 0))
- udelay(1);
- /* wait for ready */
- if (i == 0) {
- tpqputs(TPQD_ALWAYS, "timed out waiting for ready in notify_cmd");
- status_dead = YES;
- return TE_TIM;
- }
-
- outb_p(ctlbits & ~QIC02_CTL_REQUEST, QIC02_CTL_PORT); /* reset request bit */
- i = TAPE_NOTIFY_TIMEOUT;
- /* according to the specs this one should never time-out */
- while (((inb_p(QIC02_STAT_PORT) & QIC02_STAT_READY) == 0) && (--i > 0))
- udelay(1);
- /* wait for not ready */
- if (i == 0) {
- tpqputs(TPQD_ALWAYS, "timed out waiting for !ready in notify_cmd");
- status_dead = YES;
- return TE_TIM;
- }
- /* command accepted */
- return TE_OK;
-} /* notify_cmd */
-
-
-
-/* Wait for a command to complete, with timeout */
-static int wait_for_ready(time_t timeout)
-{
- int stat;
- unsigned long spin_t;
-
- /* Wait for ready or exception, without driving the loadavg up too much.
- * In most cases, the tape drive already has READY asserted,
- * so optimize for that case.
- *
- * First, busy wait a few usec:
- */
- spin_t = 50;
- while (((stat = inb_p(QIC02_STAT_PORT) & QIC02_STAT_MASK) == QIC02_STAT_MASK) && (--spin_t > 0))
- udelay(1);
- if ((stat & QIC02_STAT_READY) == 0)
- return TE_OK; /* covers 99.99% of all calls */
-
- /* Then use schedule() a few times */
- spin_t = 3; /* max 0.03 sec busy waiting */
- if (spin_t > timeout)
- spin_t = timeout;
- timeout -= spin_t;
- spin_t += jiffies;
-
- /* FIXME...*/
- while (((stat = inb_p(QIC02_STAT_PORT) & QIC02_STAT_MASK) == QIC02_STAT_MASK) && time_before(jiffies, spin_t))
- {
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1); /* don't waste all the CPU time */
- }
- if ((stat & QIC02_STAT_READY) == 0)
- return TE_OK;
-
- /* If we reach this point, we probably need to wait much longer, or
- * an exception occurred. Either case is not very time-critical.
- * Check the status port only a few times every second.
- * A interval of less than 0.10 sec will not be noticed by the user,
- * more than 0.40 sec may give noticeable delays.
- */
- spin_t += timeout;
- TPQDEB({printk("wait_for_ready: additional timeout: %d\n", spin_t);})
-
- /* not ready and no exception && timeout not expired yet */
- while (((stat = inb_p(QIC02_STAT_PORT) & QIC02_STAT_MASK) == QIC02_STAT_MASK) && time_before(jiffies, spin_t)) {
- /* be `nice` to other processes on long operations... */
- /* nap 0.30 sec between checks, */
- /* but could be woken up earlier by signals... */
- msleep_interruptible(300);
- }
-
- /* don't use jiffies for this test because it may have changed by now */
- if ((stat & QIC02_STAT_MASK) == QIC02_STAT_MASK) {
- tpqputs(TPQD_ALWAYS, "wait_for_ready() timed out");
- return TE_TIM;
- }
-
- if ((stat & QIC02_STAT_EXCEPTION) == 0) {
- tpqputs(TPQD_ALWAYS, "exception detected after waiting_for_ready");
- return TE_EX;
- } else {
- return TE_OK;
- }
-} /* wait_for_ready */
-
-
-
-/* Send some data to the drive */
-static int send_qic02_data(char sb[], unsigned size, int ignore_ex)
-{
- int i, stat;
-
- for (i = 0; i < size; i++) {
- stat = wait_for_ready(TIM_S);
- if (stat != TE_OK)
- return stat;
-
- stat = notify_cmd(sb[i], ignore_ex);
- if (stat != TE_OK)
- return stat;
- }
- return TE_OK;
-
-} /* send_qic02_data */
-
-
-/* Send a QIC-02 command (`cmd') to the tape drive, with
- * a time-out (`timeout').
- * This one is also used by tp_sense(), so we must have
- * a flag to disable exception checking (`ignore_ex').
- *
- * On entry, the controller is supposed to be READY.
- */
-static int send_qic02_cmd(int cmd, time_t timeout, int ignore_ex)
-{
- int stat;
-
- stat = inb_p(QIC02_STAT_PORT);
- if ((stat & QIC02_STAT_EXCEPTION) == 0) { /* if exception */
- tpqputs(TPQD_ALWAYS, "send_qic02_cmd: Exception!");
- return TE_EX;
- }
- if (stat & QIC02_STAT_READY) { /* if not ready */
- tpqputs(TPQD_ALWAYS, "send_qic02_cmd: not Ready!");
- return TE_ERR;
- }
-
- /* assert(ready & !exception) */
-
- /* Remember current command for later re-use with dma transfers.
- * (For reading/writing multiple blocks.)
- */
- status_cmd_pending = cmd;
-
- stat = notify_cmd(cmd, ignore_ex); /* tell drive new command was loaded, */
- /* inherit exception check. */
- if (TP_HAVE_SEEK && (cmd == AR_QCMDV_SEEK_BLK)) {
- /* This one needs to send 3 more bytes, MSB first */
- stat = send_qic02_data(seek_addr_buf, sizeof(seek_addr_buf), ignore_ex);
- }
-
- if (stat != TE_OK) {
- tpqputs(TPQD_ALWAYS, "send_qic02_cmd failed");
- }
- return stat;
-} /* send_qic02_cmd */
-
-
-
-/* Get drive status. Assume drive is ready or has exception set.
- * (or will be in <1000 usec.)
- * Extra parameters added because of 'Read Extended Status 3' command.
- */
-static int rdstatus(char *stp, unsigned size, char qcmd)
-{
- int s, n;
- char *q = stp;
-
- /* Try to busy-wait a few (700) usec, after that de-schedule.
- *
- * The problem is, if we don't de-schedule, performance will
- * drop to zero when the drive is not responding and if we
- * de-schedule immediately, we waste a lot of time because a
- * task switch is much longer than we usually have to wait here.
- */
- n = 700;
- while ((n > 0) && ((inb_p(QIC02_STAT_PORT) & QIC02_STAT_MASK) == QIC02_STAT_MASK))
- {
- udelay(1);
- n--; /* wait for ready or exception or timeout */
- }
- if (n == 0) {
- /* n (above) should be chosen such that on your machine
- * you rarely ever see the message below, and it should
- * be small enough to give reasonable response time.]
- */
- /* FIXME */
- tpqputs(TPQD_ALWAYS, "waiting looong in rdstatus() -- drive dead?");
- while ((inb_p(QIC02_STAT_PORT) & QIC02_STAT_MASK) == QIC02_STAT_MASK)
- {
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
- }
- tpqputs(TPQD_ALWAYS, "finished waiting in rdstatus()");
- }
-
- (void) notify_cmd(qcmd, 1); /* send read status command */
- /* ignore return code -- should always be ok, STAT may contain
- * exception flag from previous exception which we are trying to clear.
- */
-
- if (TP_DIAGS(current_type))
- printk(TPQIC02_NAME ": reading status bytes: ");
-
- for (q = stp; q < stp + size; q++) {
- do
- s = inb_p(QIC02_STAT_PORT);
- while ((s & QIC02_STAT_MASK) == QIC02_STAT_MASK); /* wait for ready or exception */
-
- if ((s & QIC02_STAT_EXCEPTION) == 0) { /* if exception */
- tpqputs(TPQD_ALWAYS, "rdstatus: exception error");
- ioctl_status.mt_erreg = 0; /* dunno... */
- return TE_NS; /* error, shouldn't happen... */
- }
-
- *q = inb_p(QIC02_DATA_PORT); /* read status byte */
-
- if (TP_DIAGS(current_type))
- printk("[%1zd]=0x%x ", q - stp, (unsigned) (*q) & 0xff);
-
- outb_p(ctlbits | QIC02_CTL_REQUEST, QIC02_CTL_PORT); /* set request */
-
- while ((inb_p(QIC02_STAT_PORT) & QIC02_STAT_READY) == 0)
- cpu_relax(); /* wait for not ready */
-
- udelay(22); /* delay >20 usec */
-
- outb_p(ctlbits & ~QIC02_CTL_REQUEST, QIC02_CTL_PORT); /* un-set request */
-
- }
-
- /* Specs say we should wait for READY here.
- * My drive doesn't seem to need it here yet, but others do?
- */
- while (inb_p(QIC02_STAT_PORT) & QIC02_STAT_READY)
- cpu_relax();
- /* wait for ready */
-
- if (TP_DIAGS(current_type))
- printk("\n");
-
- return TE_OK;
-} /* rdstatus */
-
-
-
-/* Get standard status (6 bytes).
- * The `.dec' and `.urc' fields are in MSB-first byte-order,
- * so they have to be swapped first.
- */
-static int get_status(volatile struct tpstatus *stp)
-{
- int stat = rdstatus((char *) stp, TPSTATSIZE, QCMD_RD_STAT);
- stp->dec = be16_to_cpu(stp->dec);
- stp->urc = be16_to_cpu(stp->urc);
- return stat;
-} /* get_status */
-
-
-#if 0
-/* This fails for my Wangtek drive */
-/* get "Extended Status Register 3" (64 bytes)
- *
- * If the meaning of the returned bytes were known, the MT_TYPE
- * identifier could be used to decode them, since they are
- * "vendor unique". :-(
- */
-static int get_ext_status3(void)
-{
- char vus[64]; /* vendor unique status */
- int stat, i;
-
- tpqputs(TPQD_ALWAYS, "Attempting to read Extended Status 3...");
- stat = rdstatus(vus, sizeof(vus), QCMD_RD_STAT_X3);
- if (stat != TE_OK)
- return stat;
-
- tpqputs(TPQD_ALWAYS, "Returned status bytes:");
- for (i = 0; i < sizeof(vus); i++) {
- if (i % 8 == 0)
- printk("\n" TPQIC02_NAME ": %2d:");
- printk(" %2x", vus[i] & 0xff);
- }
- printk("\n");
-
- return TE_OK;
-} /* get_ext_status3 */
-#endif
-
-
-/* Read drive status and set generic status too.
- * NOTE: Once we do a tp_sense(), read/write transfers are killed.
- */
-static int tp_sense(int ignore)
-{
- unsigned err = 0, exnr = 0, gs = 0;
- static void finish_rw(int cmd);
-
- if (TPQDBG(SENSE_TEXT))
- printk(TPQIC02_NAME ": tp_sense(ignore=0x%x) enter\n", ignore);
-
- /* sense() is not allowed during a read or write cycle */
- if (doing_write == YES)
- tpqputs(TPQD_ALWAYS, "Warning: File Mark inserted because of sense() request");
- /* The extra test is to avoid calling finish_rw during booting */
- if ((doing_read != NO) || (doing_write != NO))
- finish_rw(QCMD_RD_STAT);
-
- if (get_status(&tperror) != TE_OK) {
- tpqputs(TPQD_ALWAYS, "tp_sense: could not read tape drive status");
- return TE_ERR;
- }
-
- err = tperror.exs; /* get exception status bits */
- if (err & (TP_ST0 | TP_ST1))
- printk(TPQIC02_NAME ": tp_sense: status: %x, error count: %d, underruns: %d\n",
- tperror.exs, tperror.dec, tperror.urc);
- else if ((tperror.dec != 0) || (tperror.urc != 0) || TPQDBG(SENSE_CNTS))
- printk(TPQIC02_NAME ": tp_sense: no hard errors, soft error count: %d, underruns: %d\n", tperror.dec, tperror.urc);
-
- /* Set generic status. HP-UX defines these, but some extra would
- * be useful. Problem is to remain compatible. [Do we want to be
- * compatible??]
- */
- if (err & TP_ST0) {
- if (err & TP_CNI) /* no cartridge */
- gs |= GMT_DR_OPEN(-1);
- if (status_dead == NO)
- gs |= GMT_ONLINE(-1); /* always online */
- if (err & TP_USL) /* not online */
- gs &= ~GMT_ONLINE(-1);
- if (err & TP_WRP)
- gs |= GMT_WR_PROT(-1);
- if (err & TP_EOM) { /* end of media */
- gs |= GMT_EOT(-1); /* not sure this is correct for writes */
- status_eom_detected = YES;
- /* I don't know whether drive always reports EOF at or before EOM. */
- status_eof_detected = YES;
- }
- /** if (err & TP_UDA) "Unrecoverable data error" **/
- /** if (err & TP_BNL) "Bad block not located" **/
- if (err & TP_FIL) {
- gs |= GMT_EOF(-1);
- status_eof_detected = YES;
- }
- }
- if (err & TP_ST1) {
- /** if (err & TP_ILL) "Illegal command" **/
- /** if (err & TP_NDT) "No data detected" **/
- /** if (err & TP_MBD) "Marginal block detected" **/
- if (err & TP_BOM)
- gs |= GMT_BOT(-1); /* beginning of tape */
- }
- ioctl_status.mt_gstat = gs;
- ioctl_status.mt_dsreg = tperror.exs; /* "drive status" */
- ioctl_status.mt_erreg = tperror.dec; /* "sense key error" */
-
- if (err & (TP_ST0 | TP_ST1)) {
- /* My Wangtek occasionally reports `status' 1212 which should be ignored. */
- exnr = decode_qic_exception_nr(err);
- handle_qic_exception(exnr, err); /* update driver state wrt drive status */
- report_qic_exception(exnr);
- }
- err &= ~ignore; /* mask unwanted errors -- not the correct way, use exception nrs?? */
- if (((err & TP_ST0) && (err & REPORT_ERR0)) ||
- ((err & TP_ST1) && (err & REPORT_ERR1)))
- return TE_ERR;
- return TE_OK;
-} /* tp_sense */
-
-
-
-/* Wait for a wind or rewind operation to finish or
- * to time-out. (May take very long).
- */
-static int wait_for_rewind(time_t timeout)
-{
- int stat;
-
- stat = inb(QIC02_STAT_PORT) & QIC02_STAT_MASK;
- if (TPQDBG(REWIND))
- printk(TPQIC02_NAME ": Waiting for (re-)wind to finish: stat=0x%x\n", stat);
-
- stat = wait_for_ready(timeout);
-
- if (stat != TE_OK) {
- tpqputs(TPQD_ALWAYS, "(re-) winding failed\n");
- }
- return stat;
-} /* wait_for_rewind */
-
-
-
-/* Perform a full QIC02 command, and wait for completion,
- * check status when done. Complain about exceptions.
- *
- * This function should return an OS error code when
- * something goes wrong, 0 otherwise.
- */
-static int ll_do_qic_cmd(int cmd, time_t timeout)
-{
- int stat;
-
- if (status_dead == YES) {
- tpqputs(TPQD_ALWAYS, "Drive is dead. Do a `mt reset`.");
- return -ENXIO; /* User should do an MTRESET. */
- }
-
- stat = wait_for_ready(timeout); /* wait for ready or exception */
- if (stat == TE_EX) {
- if (tp_sense(TP_WRP | TP_BOM | TP_EOM | TP_FIL) != TE_OK)
- return -EIO;
- /* else nothing to worry about, I hope */
- stat = TE_OK;
- }
- if (stat != TE_OK) {
- printk(TPQIC02_NAME ": ll_do_qic_cmd(%x, %ld) failed\n", cmd, (long) timeout);
- return -EIO;
- }
-#ifdef OBSOLETE
- /* wait for ready since it may not be active immediately after reading status */
- while ((inb_p(QIC02_STAT_PORT) & QIC02_STAT_READY) != 0)
- cpu_relax();
-#endif
-
- stat = send_qic02_cmd(cmd, timeout, 0); /* (checks for exceptions) */
-
- if (cmd == QCMD_RD_FM) {
- status_eof_detected = NO;
- ioctl_status.mt_fileno++;
- /* Should update block count as well, but can't.
- * Can do a `read address' for some drives, when MTNOP is done.
- */
- } else if (cmd == QCMD_WRT_FM) {
- status_eof_detected = NO;
- ioctl_status.mt_fileno++;
- } else if ((cmd == QCMD_REWIND) || (cmd == QCMD_ERASE)
- || (cmd == QCMD_RETEN)) {
- status_eof_detected = NO;
- status_eom_detected = NO;
- status_eot_detected = NO;
- need_rewind = NO;
- ioctl_status.mt_fileno = ioctl_status.mt_blkno = 0;
- extra_blocks_left = BLOCKS_BEYOND_EW;
- return_write_eof = NO;
- return_read_eof = NO;
- reported_read_eof = NO;
- reported_write_eof = NO;
- }
- /* sense() will set eof/eom as required */
- if (stat == TE_EX) {
- if (tp_sense(TP_WRP | TP_BOM | TP_EOM | TP_FIL) != TE_OK) {
- printk(TPQIC02_NAME ": Exception persist in ll_do_qic_cmd[1](%x, %ld)", cmd, (long) timeout);
- status_dead = YES;
- return -ENXIO;
- /* if rdstatus fails too, we're in trouble */
- }
- } else if (stat != TE_OK) {
- printk(TPQIC02_NAME ": ll_do_qic_cmd: send_qic02_cmd failed, stat = 0x%x\n", stat);
- return -EIO; /*** -EIO is probably not always appropriate */
- }
-
- if (timeout == TIM_R)
- stat = wait_for_rewind(timeout);
- else
- stat = wait_for_ready(timeout);
-
- if (stat == TE_EX) {
- if (tp_sense((cmd == QCMD_SEEK_EOD ? /*****************************/
- TP_EOR | TP_NDT | TP_UDA | TP_BNL | TP_WRP |
- TP_BOM | TP_EOM | TP_FIL : TP_WRP | TP_BOM |
- TP_EOM | TP_FIL)) != TE_OK) {
- printk(TPQIC02_NAME ": Exception persist in ll_do_qic_cmd[2](%x, %ld)\n", cmd, (long) timeout);
- if (cmd != QCMD_RD_FM)
- status_dead = YES;
- return -ENXIO;
- /* if rdstatus fails too, we're in trouble */
- }
- } else if (stat != TE_OK) {
- printk(TPQIC02_NAME ": ll_do_qic_cmd %x: wait failed, stat == 0x%x\n", cmd, stat);
- return -EIO;
- }
- return 0;
-} /* ll_do_qic_cmd */
-
-
-/*
- * Problem: What to do when the user cancels a read/write operation
- * in-progress?
- *
- * "Deactivating ONLINE during a READ also causes the"
- * "tape to be rewound to BOT." Ditto for WRITEs, except
- * a FM is written first. "The host may alternatively terminate
- * the READ/WRITE command by issuing a RFM/WFM command."
- *
- * For READs:
- * Neither option will leave the tape positioned where it was.
- * Another (better?) solution is to terminate the READ by two
- * subsequent sense() operations, the first to stop the current
- * READ cycle, the second to clear the `Illegal command' exception,
- * because the QIC-02 specs didn't anticipate this. This is
- * delayed until actually needed, so a tar listing can be aborted
- * by the user and continued later.
- * If anybody has a better solution, let me know! [Also, let me
- * know if your drive (mine is a Wangtek5150EQ) does not accept
- * this sequence for canceling the read-cycle.]
- *
- * For WRITEs it's simple: Just do a WRITE_FM, leaving the tape
- * positioned after the FM.
- */
-
-static void terminate_read(int cmd)
-{
- if (doing_read != YES)
- return;
-
- doing_read = NO;
-
- if (cmd == QCMD_RD_FM)
- return;
-
- /* if the command is a RFM, there is no need to do this
- * because a RFM will legally terminate the read-cycle.
- */
- tpqputs(TPQD_ALWAYS, "terminating pending read-cycle");
-
- /* I'm not too sure about this part -- hhb */
- if (QIC02_TAPE_IFC == MOUNTAIN) {
- /* Mountain reference says can terminate by de-asserting online */
- ctlbits &= ~MTN_QIC02_CTL_ONLINE;
- }
-
- if (tp_sense(TP_FIL | TP_EOM | TP_WRP) != TE_OK) {
- tpqputs(TPQD_ALWAYS, "finish_rw[read1]: ignore the 2 lines above");
- if (is_exception()) {
- if (tp_sense(TP_ILL | TP_FIL | TP_EOM | TP_WRP) != TE_OK)
- tpqputs(TPQD_ALWAYS,"finish_rw[read2]: read cycle error");
- }
- }
-} /* terminate_read */
-
-
-static void terminate_write(int cmd)
-{
- int stat;
-
- if (doing_write != YES)
- return;
-
- doing_write = NO;
- /* Finish writing by appending a FileMark at the end. */
- if (cmd != QCMD_WRT_FM) {
- /* finish off write cycle */
- stat = ll_do_qic_cmd(QCMD_WRT_FM, TIM_M);
- if (stat != TE_OK)
- tpqputs(TPQD_ALWAYS, "Couldn't finish write cycle properly");
- (void) tp_sense(0);
- }
- /* If there is an EOF token waiting to be returned to
- * the (writing) application, discard it now.
- * We could be at EOT, so don't reset return_write_eof.
- */
- reported_write_eof = YES;
-} /* terminate_write */
-
-
-/* terminate read or write cycle because of command `cmd' */
-static void finish_rw(int cmd)
-{
- if (wait_for_ready(TIM_S) != TE_OK) {
- tpqputs(TPQD_ALWAYS, "error: drive not ready in finish_rw() !");
- return;
- }
- terminate_read(cmd);
- terminate_write(cmd);
-} /* finish_rw */
-
-
-/* Perform a QIC command through ll_do_qic_cmd().
- * If necessary, rewind the tape first.
- * Return an OS error code if something goes wrong, 0 if all is well.
- */
-static int do_qic_cmd(int cmd, time_t timeout)
-{
- int stat;
-
-
- finish_rw(cmd);
-
- if (need_rewind) {
- tpqputs(TPQD_REWIND, "Rewinding tape...");
- stat = ll_do_qic_cmd(QCMD_REWIND, TIM_R);
- if (stat != 0) {
- printk(TPQIC02_NAME ": rewind failed in do_qic_cmd(). stat=0x%2x", stat);
- return stat;
- }
- need_rewind = NO;
- if (cmd == QCMD_REWIND) /* don't wind beyond BOT ;-) */
- return 0;
- }
-
- return ll_do_qic_cmd(cmd, timeout);
-} /* do_qic_cmd */
-
-
-/* Not all ioctls are supported for all drives. Some rely on
- * optional QIC-02 commands. Check tpqic02.h for configuration.
- * Some of these commands may require ONLINE to be active.
- */
-static int do_ioctl_cmd(int cmd)
-{
- int stat;
-
- /* It is not permitted to read or wind the tape after bytes have
- * been written. It is not permitted to write the tape while in
- * read mode.
- * We try to be kind and allow reading again after writing a FM...
- */
-
- switch (cmd) {
- case MTRESET:
- /* reset verbose */
- return (tape_reset(1) == TE_OK) ? 0 : -EIO;
-
- case MTFSF:
- tpqputs(TPQD_IOCTLS, "MTFSF forward searching filemark");
- if ((mode_access == WRITE) && status_bytes_wr)
- return -EACCES;
- return do_qic_cmd(QCMD_RD_FM, TIM_F);
-
- case MTBSF:
- if (TP_HAVE_BSF) {
- tpqputs(TPQD_IOCTLS, "MTBSF backward searching filemark -- optional command");
- if ((mode_access == WRITE) && status_bytes_wr)
- return -EACCES;
- stat = do_qic_cmd(QCMD_RD_FM_BCK, TIM_F);
- } else {
- stat = -ENXIO;
- }
- status_eom_detected = status_eof_detected = NO;
- return stat;
-
- case MTFSR:
- if (TP_HAVE_FSR) { /* This is an optional QIC-02 command */
- tpqputs(TPQD_IOCTLS, "MTFSR forward space record");
- if ((mode_access == WRITE) && status_bytes_wr)
- return -EACCES;
- stat = do_qic_cmd(QCMD_SPACE_FWD, TIM_F);
- } else {
- /**** fake it by doing a read data block command? ******/
- tpqputs(TPQD_IOCTLS, "MTFSR not supported");
- stat = -ENXIO;
- }
- return stat;
-
- case MTBSR:
- if (TP_HAVE_BSR) { /* This is an optional QIC-02 command */
- /* we need this for appending files with GNU tar!! */
- tpqputs(TPQD_IOCTLS, "MTFSR backward space record");
- if ((mode_access == WRITE) && status_bytes_wr)
- return -EACCES;
- stat = do_qic_cmd(QCMD_SPACE_BCK, TIM_F);
- } else {
- tpqputs(TPQD_IOCTLS, "MTBSR not supported");
- stat = -ENXIO;
- }
- status_eom_detected = status_eof_detected = NO;
- return stat;
-
- case MTWEOF:
- tpqputs(TPQD_IOCTLS, "MTWEOF write eof mark");
- /* Plain GNU mt(1) 2.2 uses read-only mode for writing FM. :-( */
- if (mode_access == READ)
- return -EACCES;
-
- /* allow tape movement after writing FM */
- status_bytes_rd = status_bytes_wr; /* Kludge-O-Matic */
- status_bytes_wr = NO;
- return do_qic_cmd(QCMD_WRT_FM, TIM_M);
- /* not sure what to do with status_bytes when WFM should fail */
-
- case MTREW:
- tpqputs(TPQD_IOCTLS, "MTREW rewinding tape");
- if ((mode_access == WRITE) && status_bytes_wr)
- return -EACCES;
- status_eom_detected = status_eof_detected = NO;
- return do_qic_cmd(QCMD_REWIND, TIM_R);
-
- case MTOFFL:
- tpqputs(TPQD_IOCTLS, "MTOFFL rewinding & going offline");
- /* Doing a drive select will clear (unlock) the current drive.
- * But that requires support for multiple drives and locking.
- */
- if ((mode_access == WRITE) && status_bytes_wr)
- return -EACCES;
- status_eom_detected = status_eof_detected = NO;
- /**** do rewind depending on minor bits??? ***/
- stat = do_qic_cmd(QCMD_REWIND, TIM_R);
- return stat;
-
- case MTNOP:
- tpqputs(TPQD_IOCTLS, "MTNOP setting status only");
- /********** should do `read position' for drives that support it **********/
- return (tp_sense(-1) == TE_OK) ? 0 : -EIO; /**** check return codes ****/
-
- case MTRETEN:
- tpqputs(TPQD_IOCTLS, "MTRETEN retension tape");
- if ((mode_access == WRITE) && status_bytes_wr)
- return -EACCES;
- status_eom_detected = status_eof_detected = NO;
- return do_qic_cmd(QCMD_RETEN, TIM_R);
-
- case MTBSFM:
- /* Think think is like MTBSF, except that
- * we shouldn't skip the FM. Tricky.
- * Maybe use RD_FM_BCK, then do a SPACE_FWD?
- */
- tpqputs(TPQD_IOCTLS, "MTBSFM not supported");
- if ((mode_access == WRITE) && status_bytes_wr)
- return -EACCES;
- return -ENXIO;
-
- case MTFSFM:
- /* I think this is like MTFSF, except that
- * we shouldn't skip the FM. Tricky.
- * Maybe use QCMD_RD_DATA until we get a TP_FIL exception?
- * But then the FM will have been skipped...
- * Maybe use RD_FM, then RD_FM_BCK, but not all
- * drives will support that!
- */
- tpqputs(TPQD_IOCTLS, "MTFSFM not supported");
- if ((mode_access == WRITE) && status_bytes_wr)
- return -EACCES;
- return -ENXIO;
-
- case MTEOM:
- /* This should leave the tape ready for appending
- * another file to the end, such that it would append
- * after the last FM on tape.
- */
- tpqputs(TPQD_IOCTLS, "MTEOM search for End Of recorded Media");
- if ((mode_access == WRITE) && status_bytes_wr)
- return -EACCES;
- if (TP_HAVE_EOD) {
- /* Use faster seeking when possible.
- * This requires the absence of data beyond the EOM.
- * It seems that my drive does not always perform the
- * SEEK_EOD correctly, unless it is preceded by a
- * rewind command.
- */
-# if 0
- status_eom_detected = status_eof_detected = NO;
-# endif
- stat = do_qic_cmd(QCMD_REWIND, TIM_R);
- if (stat)
- return stat;
- stat = do_qic_cmd(QCMD_SEEK_EOD, TIM_F);
- /* After a successful seek, TP_EOR should be returned */
- } else {
- /* else just seek until the drive returns exception "No Data" */
- stat = 0;
- while ((stat == 0) && (!status_eom_detected)) {
- stat = do_qic_cmd(QCMD_RD_FM, TIM_F); /***** should use MTFSFM here???? ******/
- }
- if (tperror.exs & TP_NDT)
- return 0;
- }
- return stat;
-
- case MTERASE:
- tpqputs(TPQD_IOCTLS, "MTERASE -- ERASE TAPE !");
- if ((tperror.exs & TP_ST0) && (tperror.exs & TP_WRP)) {
- tpqputs(TPQD_ALWAYS, "Cartridge is write-protected.");
- return -EACCES;
- } else {
- time_t t = jiffies;
-
- /* Plain GNU mt(1) 2.2 erases a tape in O_RDONLY. :-( */
- if (mode_access == READ)
- return -EACCES;
-
- /* FIXME */
- /* give user a few seconds to pull out tape */
- while (jiffies - t < 4 * HZ)
- schedule();
- }
-
- /* don't bother writing filemark first */
- status_eom_detected = status_eof_detected = NO;
- return do_qic_cmd(QCMD_ERASE, TIM_R);
-
- case MTRAS1:
- if (TP_HAVE_RAS1) {
- tpqputs(TPQD_IOCTLS, "MTRAS1: non-destructive self test");
- stat = do_qic_cmd(QCMD_SELF_TST1, TIM_R);
- if (stat != 0) {
- tpqputs(TPQD_ALWAYS, "RAS1 failed");
- return stat;
- }
- return (tp_sense(0) == TE_OK) ? 0 : -EIO; /* get_ext_status3(); */
- }
- tpqputs(TPQD_IOCTLS, "RAS1 not supported");
- return -ENXIO;
-
- case MTRAS2:
- if (TP_HAVE_RAS2) {
- tpqputs(TPQD_IOCTLS, "MTRAS2: destructive self test");
- stat = do_qic_cmd(QCMD_SELF_TST2, TIM_R);
- if (stat != 0) {
- tpqputs(TPQD_ALWAYS, "RAS2 failed");
- return stat;
- }
- return (tp_sense(0) == TE_OK) ? 0 : -EIO; /* get_ext_status3(); */
- }
- tpqputs(TPQD_IOCTLS, "RAS2 not supported");
- return -ENXIO;
-
- case MTSEEK:
- if (TP_HAVE_SEEK && (QIC02_TAPE_IFC == ARCHIVE)) {
- tpqputs(TPQD_IOCTLS, "MTSEEK seeking block");
- if ((mode_access == WRITE) && status_bytes_wr)
- return -EACCES;
- /* NOTE: address (24 bits) is in seek_addr_buf[] */
- return do_qic_cmd(AR_QCMDV_SEEK_BLK, TIM_F);
- } else
- return -ENOTTY;
-
- default:
- return -ENOTTY;
- }
-} /* do_ioctl_cmd */
-
-
-/* dma_transfer(): This routine is called for every 512 bytes to be read
- * from/written to the tape controller. Speed is important here!
- * (There must be enough time left for the hd controller!)
- * The dma lock protects the DMA controller
- *
- * This routine merely does the least possible to keep
- * the transfers going:
- * - set the DMA count register for the next 512 bytes
- * - adjust the DMA address and page registers
- * - adjust the timeout
- * - tell the tape controller to start transferring
- * We assume the dma address and mode are, and remain, valid.
- */
-static inline void dma_transfer(void)
-{
- unsigned long flags;
-
- if (QIC02_TAPE_IFC == WANGTEK) /* or EVEREX */
- outb_p(WT_CTL_ONLINE, QIC02_CTL_PORT); /* back to normal */
- else if (QIC02_TAPE_IFC == ARCHIVE)
- outb_p(0, AR_RESET_DMA_PORT);
- else /* QIC02_TAPE_IFC == MOUNTAIN */
- outb_p(ctlbits, QIC02_CTL_PORT);
-
-
- flags = claim_dma_lock();
- clear_dma_ff(QIC02_TAPE_DMA);
- set_dma_mode(QIC02_TAPE_DMA, dma_mode);
- set_dma_addr(QIC02_TAPE_DMA, isa_virt_to_bus(buffaddr) + dma_bytes_done);
- set_dma_count(QIC02_TAPE_DMA, TAPE_BLKSIZE);
-
- /* start tape DMA controller */
- if (QIC02_TAPE_IFC == WANGTEK) /* or EVEREX */
- outb_p(WT_CTL_DMA | WT_CTL_ONLINE, QIC02_CTL_PORT); /* trigger DMA transfer */
-
- else if (QIC02_TAPE_IFC == ARCHIVE) {
- outb_p(AR_CTL_IEN | AR_CTL_DNIEN, QIC02_CTL_PORT); /* enable interrupts again */
- outb_p(0, AR_START_DMA_PORT); /* start DMA transfer */
- /* In dma_end() AR_RESET_DMA_PORT is written too. */
-
- } else { /* QIC02_TAPE_IFC == MOUNTAIN */
-
- inb(MTN_R_DESELECT_DMA_PORT);
- outb_p(ctlbits | (MTN_CTL_EXC_IEN | MTN_CTL_DNIEN),
- QIC02_CTL_PORT);
- outb_p(0, MTN_W_SELECT_DMA_PORT); /* start DMA transfer */
- if (dma_mode == DMA_MODE_WRITE)
- outb_p(0, MTN_W_DMA_WRITE_PORT); /* start DMA transfer */
- }
-
- /* start computer DMA controller */
- enable_dma(QIC02_TAPE_DMA);
-
- release_dma_lock(flags);
-
- /* block transfer should start now, jumping to the
- * interrupt routine when done or an exception was detected.
- */
-} /* dma_transfer */
-
-
-/* start_dma() sets a DMA transfer up between the tape controller and
- * the kernel qic02_tape_buf buffer.
- * Normally bytes_todo==dma_bytes_done at the end of a DMA transfer. If not,
- * a filemark was read, or an attempt to write beyond the End Of Tape
- * was made. [Or some other bad thing happened.]
- * Must do a sense() before returning error.
- */
-static int start_dma(short mode, unsigned long bytes_todo)
-/* assume 'bytes_todo'>0 */
-{
- int stat;
-
- tpqputs(TPQD_DEBUG, "start_dma() enter");
- TPQDEB( {printk(TPQIC02_NAME ": doing_read==%d, doing_write==%d\n",
- doing_read, doing_write);})
-
- dma_bytes_done = 0;
- dma_bytes_todo = bytes_todo;
- status_error = NO;
- /* dma_mode!=0 indicates that the dma controller is in use */
- dma_mode = (mode == WRITE) ? DMA_MODE_WRITE : DMA_MODE_READ;
-
- /* Only give READ/WRITE DATA command to tape drive if we haven't
- * done that already. Otherwise the drive will rewind to the beginning
- * of the current file on tape. Any QIC command given other than
- * R/W FM will break the read/write transfer cycle.
- * do_qic_cmd() will terminate doing_{read,write}
- */
- if ((doing_read == NO) && (doing_write == NO)) {
- /* First, we have to clear the status -- maybe remove TP_FIL???
- */
-
-#if 0
- /* Next dummy get status is to make sure CNI is valid,
- since we're only just starting a read/write it doesn't
- matter some exceptions are cleared by reading the status;
- we're only interested in CNI and WRP. -Eddy */
- get_status(&tperror);
-#else
- /* TP_CNI should now be handled in open(). -Hennus */
-#endif
-
- stat = tp_sense(((mode == WRITE) ? 0 : TP_WRP) | TP_BOM | TP_FIL);
- if (stat != TE_OK)
- return stat;
-
-#ifdef OBSOLETE
- /************* not needed iff rd_status() would wait for ready!!!!!! **********/
- if (wait_for_ready(TIM_S) != TE_OK) { /*** not sure this is needed ***/
- tpqputs(TPQD_ALWAYS, "wait_for_ready failed in start_dma");
- return -EIO;
- }
-#endif
-
- if (QIC02_TAPE_IFC == MOUNTAIN) {
- /* Set control bits to select ONLINE during command */
- ctlbits |= MTN_QIC02_CTL_ONLINE;
- }
-
- /* Tell the controller the data direction */
-
- /* r/w, timeout medium, check exceptions, sets status_cmd_pending. */
- stat = send_qic02_cmd((mode == WRITE) ? QCMD_WRT_DATA : QCMD_RD_DATA, TIM_M, 0);
- if (stat != TE_OK) {
- printk(TPQIC02_NAME ": start_dma: init %s failed\n", (mode == WRITE) ? "write" : "read");
- (void) tp_sense(0);
- return stat;
- }
-
- /* Do this last, because sense() will clear the doing_{read,write}
- * flags, causing trouble next time around.
- */
- if (wait_for_ready(TIM_M) != TE_OK)
- return -EIO;
- switch (mode) {
- case READ:
- doing_read = YES;
- break;
- case WRITE:
- doing_write = YES;
- break;
- default:
- printk(TPQIC02_NAME ": requested unknown mode %d\n", mode);
- panic(TPQIC02_NAME ": invalid mode in start_dma()");
- }
-
- } else if (is_exception()) {
- /* This is for Archive drives, to handle reads with 0 bytes
- * left for the last read request.
- *
- * ******** this also affects EOF/EOT handling! ************
- */
- tpqputs(TPQD_ALWAYS, "detected exception in start_dma() while transfer in progress");
- status_error = YES;
- return TE_END;
- }
-
-
- status_expect_int = YES;
-
- /* This assumes tape is already positioned, but these
- * semi-'intelligent' drives are unpredictable...
- */
- TIMERON(TIM_M * 2);
-
- /* initiate first data block read from/write to the tape controller */
-
- dma_transfer();
-
- TPQPUTS("start_dma() end");
- return TE_OK;
-} /* start_dma */
-
-
-/* This cleans up after the dma transfer has completed
- * (or failed). If an exception occurred, a sense()
- * must be done. If the exception was caused by a FM,
- * sense() will set `status_eof_detected' and
- * `status_eom_detected', as required.
- */
-static void end_dma(unsigned long *bytes_done)
-{
- int stat = TE_OK;
- unsigned long flags;
-
- TIMEROFF;
-
- TPQPUTS("end_dma() enter");
-
- flags = claim_dma_lock();
-
- disable_dma(QIC02_TAPE_DMA);
- clear_dma_ff(QIC02_TAPE_DMA);
-
- release_dma_lock(flags);
-
- if (QIC02_TAPE_IFC == WANGTEK) /* or EVEREX */
- outb_p(WT_CTL_ONLINE, QIC02_CTL_PORT); /* back to normal */
- else if (QIC02_TAPE_IFC == ARCHIVE)
- outb_p(0, AR_RESET_DMA_PORT);
- else { /* QIC02_TAPE_IFC == MOUNTAIN */
- /* Clear control bits, de-select ONLINE during tp_sense */
- ctlbits &= ~MTN_QIC02_CTL_ONLINE;
- }
-
- stat = wait_for_ready(TIM_M);
- if (status_error || (stat != TE_OK)) {
- tpqputs(TPQD_DMAX, "DMA transfer exception");
- stat = tp_sense((dma_mode == READ) ? TP_WRP : 0);
- /* no return here -- got to clean up first! */
- } else { /* if (QIC02_TAPE_IFC == MOUNTAIN) */
- outb_p(ctlbits, QIC02_CTL_PORT);
- }
-
- if (QIC02_TAPE_IFC == MOUNTAIN)
- inb(MTN_R_DESELECT_DMA_PORT);
-
- /* take the tape controller offline */
-
- /* finish off DMA stuff */
-
-
- dma_mode = 0;
- /* Note: The drive is left on-line, ready for the next
- * data transfer.
- * If the next command to the drive does not continue
- * the pending cycle, it must do 2 sense()s first.
- */
-
- *bytes_done = dma_bytes_done;
- status_expect_int = NO;
- ioctl_status.mt_blkno += (dma_bytes_done / TAPE_BLKSIZE);
-
- TPQPUTS("end_dma() exit");
- /*** could return stat here ***/
-} /* end_dma */
-
-/*********** Below are the (public) OS-interface procedures ***********/
-
-
-/* qic02_tape_times_out() is called when a DMA transfer doesn't complete
- * quickly enough. Usually this means there is something seriously wrong
- * with the hardware/software, but it could just be that the controller
- * has decided to do a long rewind, just when I didn't expect it.
- * Just try again.
- */
-static void qic02_tape_times_out(unsigned long dummy)
-{
- printk("time-out in %s driver\n", TPQIC02_NAME);
- if ((status_cmd_pending > 0) || dma_mode) {
- /* takes tooo long, shut it down */
- status_dead = YES;
- status_cmd_pending = 0;
- status_timer_on = NO;
- status_expect_int = NO;
- status_error = YES;
- if (dma_mode) {
- dma_mode = 0; /* signal end to read/write routine */
- wake_up(&qic02_tape_transfer);
- }
- }
-} /* qic02_tape_times_out */
-
-/*
- * Interrupt handling:
- *
- * 1) Interrupt is generated iff at the end of
- * a 512-DMA-block transfer.
- * 2) EXCEPTION is not raised unless something
- * is wrong or EOT/FM is detected.
- * 3) FM EXCEPTION is set *after* the last byte has
- * been transferred by DMA. By the time the interrupt
- * is handled, the EXCEPTION may already be set.
- *
- * So,
- * 1) On EXCEPTION, assume data has been transferred, so
- * continue as usual, but set a flag to indicate the
- * exception was detected.
- * Do a sense status when the flag is found set.
- * 2) Do not attempt to continue a transfer after an exception.
- * [??? What about marginal blocks???????]
- */
-
-
-/* qic02_tape_interrupt() is called when the tape controller completes
- * a DMA transfer.
- * We are not allowed to sleep here!
- *
- * Check if the transfer was successful, check if we need to transfer
- * more. If the buffer contains enough data/is empty enough, signal the
- * read/write() thread to copy to/from user space.
- * When we are finished, set flags to indicate end, disable timer.
- * NOTE: This *must* be fast!
- */
-static irqreturn_t qic02_tape_interrupt(int irq, void *dev_id,
- struct pt_regs *regs)
-{
- int stat, r, i;
- unsigned long flags;
-
- TIMEROFF;
-
- if (status_expect_int) {
-#ifdef WANT_EXTRA_FULL_DEBUGGING
- if (TP_DIAGS(current_type))
- printk("@");
-#endif
- stat = inb(QIC02_STAT_PORT); /* Knock, knock */
- if (QIC02_TAPE_IFC == ARCHIVE) { /* "Who's there?" */
- if (((stat & (AR_STAT_DMADONE)) == 0) &&
- ((stat & (QIC02_STAT_EXCEPTION)) != 0)) {
- TIMERCONT;
- return IRQ_NONE;/* "Linux with IRQ sharing" */
- }
- }
-
- if ((stat & QIC02_STAT_EXCEPTION) == 0) { /* exception occurred */
- /* Possible causes for an exception during a transfer:
- * - during a write-cycle: end of tape (EW) hole detected.
- * - during a read-cycle: filemark or EOD detected.
- * - something went wrong
- * So don't continue with the next block.
- */
- tpqputs(TPQD_ALWAYS, "isr: exception on tape controller");
- printk(" status %02x\n", stat);
- status_error = TE_EX;
-
- dma_bytes_done += TAPE_BLKSIZE;
-
- dma_mode = 0; /* wake up rw() */
- status_expect_int = NO;
- wake_up(&qic02_tape_transfer);
- return IRQ_HANDLED;
- }
- /* return if tape controller not ready, or
- * if dma channel hasn't finished last byte yet.
- */
- r = 0;
-
- /* Skip next ready check for Archive controller because
- * it may be busy reading ahead. Weird. --hhb
- */
- if (QIC02_TAPE_IFC == WANGTEK) /* I think this is a drive-dependency, not IFC -- hhb */
- if (stat & QIC02_STAT_READY) { /* not ready */
- tpqputs(TPQD_ALWAYS, "isr: ? Tape controller not ready");
- r = 1;
- }
-
- flags = claim_dma_lock();
-
- if ((i = get_dma_residue(QIC02_TAPE_DMA)) != 0) {
- printk(TPQIC02_NAME ": dma_residue == %x !!!\n", i);
- r = 1; /* big trouble, but can't do much about it... */
- }
-
- release_dma_lock(flags);
-
- if (r)
- return IRQ_HANDLED;
-
- /* finish DMA cycle */
-
- /* no errors detected, continue */
- dma_bytes_done += TAPE_BLKSIZE;
- if (dma_bytes_done >= dma_bytes_todo) {
- /* finished! Wakeup rw() */
- dma_mode = 0;
- status_expect_int = NO;
- TPQPUTS("isr: dma_bytes_done");
- wake_up(&qic02_tape_transfer);
- } else {
- /* start next transfer, account for track-switching time */
- mod_timer(&tp_timer, jiffies + 6 * HZ);
- dma_transfer();
- }
- } else {
- printk(TPQIC02_NAME ": Unexpected interrupt, stat == %x\n", inb(QIC02_STAT_PORT));
- }
- return IRQ_HANDLED;
-} /* qic02_tape_interrupt */
-
-
-/* read/write routines:
- * This code copies between a kernel buffer and a user buffer. The
- * actual data transfer is done using DMA and interrupts. Time-outs
- * are also used.
- *
- * When a filemark is read, we return '0 bytes read' and continue with the
- * next file after that.
- * When EOM is read, we return '0 bytes read' twice.
- * When the EOT marker is detected on writes, '0 bytes read' should be
- * returned twice. If user program does a MTNOP after that, 2 additional
- * blocks may be written. ------- FIXME: Implement this correctly *************************************************
- *
- * Only read/writes in multiples of 512 bytes are accepted.
- * When no bytes are available, we sleep() until they are. The controller will
- * generate an interrupt, and we (should) get a wake_up() call.
- *
- * Simple buffering is used. User program should ensure that a large enough
- * buffer is used. Usually the drive does some buffering as well (something
- * like 4k or so).
- *
- * Scott S. Bertilson suggested to continue filling the user buffer, rather
- * than waste time on a context switch, when the kernel buffer fills up.
- */
-
-/*
- * Problem: tar(1) doesn't always read the entire file. Sometimes the entire file
- * has been read, but the EOF token is never returned to tar(1), simply because
- * tar(1) knows it has already read all of the data it needs. So we must use
- * open/release to reset the `reported_read_eof' flag. If we don't, the next read
- * request would return the EOF flag for the previous file.
- */
-
-static ssize_t qic02_tape_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos)
-{
- int type = iminor(filp->f_dentry->d_inode);
- unsigned short flags = filp->f_flags;
- unsigned long bytes_todo, bytes_done, total_bytes_done = 0;
- int stat;
-
- if (status_zombie == YES) {
- tpqputs(TPQD_ALWAYS, "configs not set");
- return -ENXIO;
- }
-
- if (TP_DIAGS(current_type))
- printk(TPQIC02_NAME ": request READ, minor=%x, buf=%p, count=%lx, pos=%Lx, flags=%x\n", type, buf,
- (long) count, filp->f_pos, flags);
-
- if (count % TAPE_BLKSIZE) { /* Only allow mod 512 bytes at a time. */
- tpqputs(TPQD_BLKSZ, "Wrong block size");
- return -EINVAL;
- }
-
- /* Just assume everything is ok. Controller will scream if not. */
-
- if (status_bytes_wr) { /* Once written, no more reads, 'till after WFM. */
- return -EACCES;
- }
-
- /* This is rather ugly because it has to implement a finite state
- * machine in order to handle the EOF situations properly.
- */
- while ((signed) count >= 0) {
- bytes_done = 0;
- /* see how much fits in the kernel buffer */
- bytes_todo = TPQBUF_SIZE;
- if (bytes_todo > count) {
- bytes_todo = count;
- }
-
- /* Must ensure that user program sees exactly one EOF token (==0) */
- if (return_read_eof == YES) {
- if (TPQDBG(DEBUG)) {
- printk("read: return_read_eof==%d, reported_read_eof==%d, total_bytes_done==%lu\n", return_read_eof, reported_read_eof, total_bytes_done);
- }
-
- if (reported_read_eof == NO) {
- /* have not yet returned EOF to user program */
- if (total_bytes_done > 0) {
- return total_bytes_done; /* next time return EOF */
- } else {
- reported_read_eof = YES; /* move on next time */
- return 0; /* return EOF */
- }
- } else {
- /* Application program has already received EOF
- * (above), now continue with next file on tape,
- * if possible.
- * When the FM is reached, EXCEPTION is set,
- * causing a sense(). Subsequent read/writes will
- * continue after the FM.
- */
- /*********** ?????????? this should check for (EOD|NDT), not EOM, 'cause we can read past EW: ************/
- if (status_eom_detected) {
- /* If EOM, nothing left to read, so keep returning EOFs.
- *** should probably set some flag to avoid clearing
- *** status_eom_detected through ioctls or something
- */
- return 0;
- } else {
- /* just eof, there may be more files ahead... */
- return_read_eof = NO;
- reported_read_eof = NO;
- status_eof_detected = NO; /* reset this too */
- /*fall through */
- }
- }
- }
-
- if (bytes_todo == 0) {
- return total_bytes_done;
- }
-
- if (bytes_todo > 0) {
- /* start reading data */
- if (is_exception()) {
- tpqputs(TPQD_DMAX, "is_exception() before start_dma()!");
- }
-
-/******************************************************************
- ***** if start_dma() fails because the head is positioned 0 bytes
- ***** before the FM, (causing EXCEPTION to be set) return_read_eof should
- ***** be set to YES, and we should return total_bytes_done, rather than -ENXIO.
- ***** The app should recognize this as an EOF condition.
- ***************************************************************************/
- stat = start_dma(READ, bytes_todo);
- if (stat == TE_OK) {
- /* Wait for transfer to complete, interrupt should wake us */
-
- wait_event(qic02_tape_transfer, dma_mode != 0);
-
- if (status_error)
- return_read_eof = YES;
-
- } else if (stat != TE_END) {
- /* should do sense() on error here */
-#if 0
- return -ENXIO;
-#else
- printk("Trouble: stat==%02x\n", stat);
- return_read_eof = YES;
- /*************** check EOF/EOT handling!!!!!! **/
-#endif
- }
- end_dma(&bytes_done);
- if (bytes_done > bytes_todo) {
- tpqputs(TPQD_ALWAYS, "read: Oops, read more bytes than requested");
- return -EIO;
- }
- /* copy buffer to user-space in one go */
- if (bytes_done > 0) {
- if (copy_to_user(buf, buffaddr, bytes_done))
- return -EFAULT;
- }
-#if 1
- /* Checks Ton's patch below */
- if ((return_read_eof == NO) && (status_eof_detected == YES)) {
- printk(TPQIC02_NAME ": read(): return_read_eof=%d, status_eof_detected=YES. return_read_eof:=YES\n",
- return_read_eof);
- }
-#endif
- if ((bytes_todo != bytes_done) || (status_eof_detected == YES)) {
- /* EOF or EOM detected. return EOF next time. */
- return_read_eof = YES;
- }
-
- }
- /* else: ignore read request for 0 bytes */
- if (bytes_done > 0) {
- status_bytes_rd = YES;
- buf += bytes_done;
- *ppos += bytes_done;
- total_bytes_done += bytes_done;
- count -= bytes_done;
- }
- }
- tpqputs(TPQD_ALWAYS, "read request for <0 bytes");
- return -EINVAL;
-} /* qic02_tape_read */
-
-
-
-/* The drive detects near-EOT by means of the holes in the tape.
- * When the holes are detected, there is some space left. The drive
- * reports this as a TP_EOM exception. After clearing the exception,
- * the drive should accept two extra blocks.
- *
- * It seems there are some archiver programs that would like to use the
- * extra space for writing a continuation marker. The driver should return
- * end-of-file to the user program on writes, when the holes are detected.
- * If the user-program wants to use the extra space, it should use the
- * MTNOP ioctl() to get the generic status register and may then continue
- * writing (max 1kB). ----------- doesn't work yet...............
- *
- * EOF behaviour on writes:
- * If there is enough room, write all of the data.
- * If there is insufficient room, write as much as will fit and
- * return the amount written. If the requested amount differs from the
- * written amount, the application program should recognize that as the
- * end of file. Subsequent writes will return -ENOSPC.
- * Unless the minor bits specify a rewind-on-close, the tape will not
- * be rewound when it is full. The user-program should do that, if desired.
- * If the driver were to do that automatically, a user-program could be
- * confused about the EOT/BOT condition after re-opening the tape device.
- *
- * Multiple volume support: Tar closes the tape device before prompting for
- * the next tape. The user may then insert a new tape and tar will open the
- * tape device again. The driver will detect an exception status in (No Cartridge)
- * and force a rewind. After that tar may continue writing.
- */
-static ssize_t qic02_tape_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
-{
- int type = iminor(filp->f_dentry->d_inode);
- unsigned short flags = filp->f_flags;
- unsigned long bytes_todo, bytes_done, total_bytes_done = 0;
-
- if (status_zombie == YES) {
- tpqputs(TPQD_ALWAYS, "configs not set");
- return -ENXIO;
- }
-
- if (TP_DIAGS(current_type)) {
- printk(TPQIC02_NAME ": request WRITE, minor=%x, buf=%p, count=%lx, pos=%Lx, flags=%x\n",
- type, buf, (long) count, filp->f_pos, flags);
- }
-
- if (count % TAPE_BLKSIZE) { /* only allow mod 512 bytes at a time */
- tpqputs(TPQD_BLKSZ, "Wrong block size");
- return -EINVAL;
- }
-
- if (mode_access == READ) {
- tpqputs(TPQD_ALWAYS, "Not in write mode");
- return -EACCES;
- }
-
- /* open() does a sense() and we can assume the tape isn't changed
- * between open() and release(), so the tperror.exs bits will still
- * be valid.
- */
- if ((tperror.exs & TP_ST0) && (tperror.exs & TP_WRP)) {
- tpqputs(TPQD_ALWAYS, "Cartridge is write-protected.");
- return -EACCES; /* don't even try when write protected */
- }
-
- if (doing_read == YES) {
- terminate_read(0);
- }
-
- while ((signed) count >= 0) {
- /* see how much fits in the kernel buffer */
- bytes_done = 0;
- bytes_todo = TPQBUF_SIZE;
- if (bytes_todo > count) {
- bytes_todo = count;
- }
-
- if (return_write_eof == YES) {
- /* return_write_eof should be reset on reverse tape movements. */
-
- if (reported_write_eof == NO) {
- if (bytes_todo > 0) {
- tpqputs(TPQD_ALWAYS, "partial write");
- /* partial write signals EOF to user program */
- }
- reported_write_eof = YES;
- return total_bytes_done;
- } else {
- return -ENOSPC; /* return error */
- }
- }
-
- /* Quit when done. */
- if (bytes_todo == 0) {
- return total_bytes_done;
- }
-
- /* copy from user to DMA buffer and initiate transfer. */
- if (bytes_todo > 0) {
- if (copy_from_user(buffaddr, buf, bytes_todo))
- return -EFAULT;
-
-/****************** similar problem with read() at FM could happen here at EOT.
- ******************/
-
-/***** if at EOT, 0 bytes can be written. start_dma() will
- ***** fail and write() will return ENXIO error
- *****/
- if (start_dma(WRITE, bytes_todo) != TE_OK) {
- tpqputs(TPQD_ALWAYS, "write: start_dma() failed");
- /* should do sense() on error here */
- return -ENXIO;
- /*********** FIXTHIS **************/
- }
-
- /* Wait for write to complete, interrupt should wake us. */
- wait_event(qic02_tape_transfer, (status_error == 0 && dma_mode != 0));
-
- end_dma(&bytes_done);
- if (bytes_done > bytes_todo) {
- tpqputs(TPQD_ALWAYS, "write: Oops, wrote more bytes than requested");
- return -EIO;
- }
- /* If the dma-transfer was aborted because of an exception,
- * status_error will have been set in the interrupt handler.
- * Then end_dma() will do a sense().
- * If the exception was EXC_EOM, the EW-hole was encountered
- * and two more blocks could be written. For the time being we'll
- * just consider this to be the EOT.
- * Otherwise, something Bad happened, such as the maximum number
- * of block-rewrites was exceeded. [e.g. A very bad spot on tape was
- * encountered. Normally short dropouts are compensated for by
- * rewriting the block in error, up to 16 times. I'm not sure
- * QIC-24 drives can do this.]
- */
- if (status_error) {
- if (status_eom_detected == YES) {
- tpqputs(TPQD_ALWAYS, "write: EW detected");
- return_write_eof = YES;
- } else {
- /* probably EXC_RWA */
- tpqputs(TPQD_ALWAYS, "write: dma: error in writing");
- return -EIO;
- }
- }
- if (bytes_todo != bytes_done) {
- /* EOF or EOM detected. return EOT next time. */
- return_write_eof = YES;
- }
- }
- /* else: ignore write request for 0 bytes. */
-
- if (bytes_done > 0) {
- status_bytes_wr = YES;
- buf += bytes_done;
- *ppos += bytes_done;
- total_bytes_done += bytes_done;
- count -= bytes_done;
- }
- }
-
- tpqputs(TPQD_ALWAYS, "write request for <0 bytes");
- if (TPQDBG(DEBUG)) {
- printk(TPQIC02_NAME ": status_bytes_wr %x, buf %p"
- ", total_bytes_done %lx, count %lx\n",
- status_bytes_wr, buf, total_bytes_done,
- (long) count);
- }
- return -EINVAL;
-} /* qic02_tape_write */
-
-
-
-/* qic02_tape_open()
- * We allow the device to be opened, even if it is marked 'dead' because
- * we want to be able to reset the tape device without rebooting.
- * Only one open tape file at a time, except when minor=255.
- * Minor 255 is only allowed for resetting and always returns <0.
- *
- * The density command is only allowed when TP_BOM is set. Thus, remember
- * the most recently used minor bits. When they are different from the
- * remembered values, rewind the tape and set the required density.
- * Don't rewind if the minor bits specify density 0.
- */
-
-static int qic02_tape_open(struct inode *inode, struct file *filp)
-{
- static int qic02_tape_open_no_use_count(struct inode *,
- struct file *);
- int open_error;
-
- open_error = qic02_tape_open_no_use_count(inode, filp);
- return open_error;
-}
-
-static int qic02_tape_open_no_use_count(struct inode *inode,
- struct file *filp)
-{
- int type = iminor(inode);
- unsigned short flags = filp->f_flags;
- unsigned short dens = 0;
- int s;
-
-
- if (TP_DIAGS(type)) {
- printk("qic02_tape_open: dev=tpqic2(%d), flags=%x ",
- type, flags);
- }
-
- if (type == 255) { /* special case for resetting */
- if (capable(CAP_SYS_ADMIN)) {
- return (tape_reset(1) == TE_OK) ? -EAGAIN : -ENXIO;
- } else {
- return -EPERM;
- }
- }
-
- if (status_dead == YES) {
- /* Allow `mt reset' ioctl() even when already open()ed. */
- return 0;
- }
-
- if(test_and_set_bit(0, &tape_open))
- return -EBUSY;
-
- if (status_zombie == YES) {
- /* no irq/dma/port stuff allocated yet, no reset done
- * yet, so return until MTSETCONFIG has been done.
- */
- return 0;
- }
-
- status_bytes_rd = NO;
- status_bytes_wr = NO;
-
- return_read_eof = NO; /********????????????????*****/
- return_write_eof = (status_eot_detected) ? YES : NO;
-
- /* Clear this in case user app close()d before reading EOF token */
- status_eof_detected = NO;
-
- reported_read_eof = NO;
- reported_write_eof = NO;
-
-
- switch (flags & O_ACCMODE) {
- case O_RDONLY:
- mode_access = READ;
- break;
- case O_WRONLY: /* Fallthru... Strictly speaking this is not correct... */
- case O_RDWR: /* Reads are allowed as long as nothing is written */
- mode_access = WRITE;
- break;
- }
-
- /* This is to avoid tape-changed problems (TP_CNI exception).
- *
- * Since removing the cartridge will not raise an exception,
- * we always do a tp_sense() to make sure we have the proper
- * CNI status, the 2150L may need an additional sense.... - Eddy
- */
- s = tp_sense(TP_WRP | TP_EOM | TP_BOM | TP_CNI | TP_EOR);
-
- if (s == TE_OK) {
- /* Try to clear cartridge-changed status for Archive-2150L */
- if ((tperror.exs & TP_ST0) && (tperror.exs & TP_CNI)) {
- s = tp_sense(TP_WRP | TP_EOM | TP_BOM | TP_CNI | TP_EOR);
- }
- }
-
- if (s != TE_OK) {
- tpqputs(TPQD_ALWAYS, "open: sense() failed");
- clear_bit(0, &tape_open);
- return -EIO;
- }
-
- /* exception bits should be up-to-date now, so check for
- * tape presence and exit if absent.
- * Even `mt stat' will fail without a tape.
- */
- if ((tperror.exs & TP_ST0) && (tperror.exs & TP_CNI)) {
- tpqputs(TPQD_ALWAYS, "No tape present.");
- clear_bit(0, &tape_open);
- return -EIO;
- }
-
- /* At this point we can assume that a tape is present and
- * that it will remain present until release() is called.
- */
-
- /* not allowed to do QCMD_DENS_* unless tape is rewound */
- if ((TP_DENS(type) != 0) && (TP_DENS(current_type) != TP_DENS(type))) {
- /* force rewind if minor bits have changed,
- * i.e. user wants to use tape in different format.
- * [assuming single drive operation]
- */
- if (TP_HAVE_DENS) {
- tpqputs(TPQD_REWIND, "Density minor bits have changed. Forcing rewind.");
- need_rewind = YES;
- }
- } else {
- /* density bits still the same, but TP_DIAGS bit
- * may have changed.
- */
- current_type = type;
- }
-
- if (need_rewind == YES) {
-/***************** CHECK THIS!!!!!!!! **********/
- s = do_qic_cmd(QCMD_REWIND, TIM_R);
- if (s != 0) {
- tpqputs(TPQD_ALWAYS, "open: rewind failed");
- return -EIO;
- }
- }
-
-
-/* Note: After a reset command, the controller will rewind the tape
- * just before performing any tape movement operation! ************ SO SET need_rewind flag!!!!!
- */
- if (status_dead == YES) {
- tpqputs(TPQD_ALWAYS, "open: tape dead, attempting reset");
- if (tape_reset(1) != TE_OK) {
- return -ENXIO;
- } else {
- status_dead = NO;
- if (tp_sense(~(TP_ST1 | TP_ILL)) != TE_OK) {
- tpqputs(TPQD_ALWAYS, "open: tp_sense() failed\n");
- status_dead = YES; /* try reset next time */
- return -EIO;
- }
- }
- }
-
- /* things should be ok, once we get here */
-
-
- /* set density: only allowed when TP_BOM status bit is set,
- * so we must have done a rewind by now. If not, just skip over.
- * Only give set density command when minor bits have changed.
- */
- if (TP_DENS(current_type) == TP_DENS(type)) {
- return 0;
- }
-
- current_type = type;
- need_rewind = NO;
- if (TP_HAVE_DENS) {
- dens = TP_DENS(type);
- }
-
- if (dens < sizeof(format_names) / sizeof(char *))
- printk(TPQIC02_NAME ": format: %s%s\n", (dens != 0) ? "QIC-" : "", format_names[dens]);
- else
- tpqputs(TPQD_REWIND, "Wait for retensioning...");
-
- switch (TP_DENS(type)) {
- case 0: /* Minor 0 is for drives without set-density support */
- s = 0;
- break;
- case 1:
- s = do_qic_cmd(QCMD_DENS_11, TIM_S);
- break;
- case 2:
- s = do_qic_cmd(QCMD_DENS_24, TIM_S);
- break;
- case 3:
- s = do_qic_cmd(QCMD_DENS_120, TIM_S);
- break;
- case 4:
- s = do_qic_cmd(QCMD_DENS_150, TIM_S);
- break;
- case 5:
- s = do_qic_cmd(QCMD_DENS_300, TIM_S);
- break;
- case 6:
- s = do_qic_cmd(QCMD_DENS_600, TIM_S);
- break;
- default: /* otherwise do a retension before anything else */
- s = do_qic_cmd(QCMD_RETEN, TIM_R);
- }
- if (s != 0) {
- status_dead = YES; /* force reset */
- current_type = 0;/* earlier 0xff80 */
- return -EIO;
- }
-
- return 0;
-} /* qic02_tape_open */
-
-
-static int qic02_tape_release(struct inode *inode, struct file *filp)
-{
- int type = iminor(inode);
-
- if (TP_DIAGS(type)) {
- printk("qic02_tape_release: dev=tpqic2(%d)\n", type);
- }
-
- if (status_zombie == NO) { /* don't rewind in zombie mode */
- /* Terminate any pending write cycle. Terminating the read-cycle
- * is delayed until it is required to do so for a new command.
- */
- terminate_write(-1);
-
- if (status_dead == YES) {
- tpqputs(TPQD_ALWAYS, "release: device dead!?");
- }
-
- /* Rewind only if minor number requires it AND
- * read/writes have been done. ************* IS THIS CORRECT??????????
- */
- if (TP_REWCLOSE(type) && (status_bytes_rd | status_bytes_wr)) {
- tpqputs(TPQD_REWIND, "release: Doing rewind...");
- (void) do_qic_cmd(QCMD_REWIND, TIM_R);
- }
- }
- clear_bit(0, &tape_open);
- return 0;
-} /* qic02_tape_release */
-
-
-#ifdef CONFIG_QIC02_DYNCONF
-/* Set masks etc. based on the interface card type. */
-static int update_ifc_masks(int ifc)
-{
- QIC02_TAPE_IFC = ifc;
-
- if ((QIC02_TAPE_IFC == WANGTEK) || (QIC02_TAPE_IFC == EVEREX)) {
- QIC02_STAT_PORT = QIC02_TAPE_PORT;
- QIC02_CTL_PORT = QIC02_TAPE_PORT;
- QIC02_CMD_PORT = QIC02_TAPE_PORT + 1;
- QIC02_DATA_PORT = QIC02_TAPE_PORT + 1;
- QIC02_STAT_READY = WT_QIC02_STAT_READY;
- QIC02_STAT_EXCEPTION = WT_QIC02_STAT_EXCEPTION;
- QIC02_STAT_MASK = WT_QIC02_STAT_MASK;
-
- QIC02_STAT_RESETMASK = WT_QIC02_STAT_RESETMASK;
- QIC02_STAT_RESETVAL = WT_QIC02_STAT_RESETVAL;
-
- QIC02_CTL_RESET = WT_QIC02_CTL_RESET;
- QIC02_CTL_REQUEST = WT_QIC02_CTL_REQUEST;
-
- if (QIC02_TAPE_DMA == 3) {
- WT_CTL_DMA = WT_CTL_DMA3;
- } else if (QIC02_TAPE_DMA == 1) {
- WT_CTL_DMA = WT_CTL_DMA1;
- } else {
- tpqputs(TPQD_ALWAYS,
- "Unsupported or incorrect DMA channel");
- return -EIO;
- }
-
- if (QIC02_TAPE_IFC == EVEREX) {
- /* Everex is a special case for Wangtek (actually
- * it's the other way 'round, but I saw Wangtek first)
- */
- if (QIC02_TAPE_DMA == 3) {
- WT_CTL_DMA = WT_CTL_DMA1;
- }
-
- /* Fixup the kernel copy of the IFC type to that
- * we don't have to distinguish between Wangtek and
- * and Everex at runtime.
- */
- QIC02_TAPE_IFC = WANGTEK;
- }
- } else if (QIC02_TAPE_IFC == ARCHIVE) {
- QIC02_STAT_PORT = QIC02_TAPE_PORT + 1;
- QIC02_CTL_PORT = QIC02_TAPE_PORT + 1;
- QIC02_CMD_PORT = QIC02_TAPE_PORT;
- QIC02_DATA_PORT = QIC02_TAPE_PORT;
- QIC02_STAT_READY = AR_QIC02_STAT_READY;
- QIC02_STAT_EXCEPTION = AR_QIC02_STAT_EXCEPTION;
- QIC02_STAT_MASK = AR_QIC02_STAT_MASK;
-
- QIC02_STAT_RESETMASK = AR_QIC02_STAT_RESETMASK;
- QIC02_STAT_RESETVAL = AR_QIC02_STAT_RESETVAL;
-
- QIC02_CTL_RESET = AR_QIC02_CTL_RESET;
- QIC02_CTL_REQUEST = AR_QIC02_CTL_REQUEST;
-
- if (QIC02_TAPE_DMA > 3) {
- tpqputs(TPQD_ALWAYS,
- "Unsupported or incorrect DMA channel");
- return -EIO;
- }
- } else if (QIC02_TAPE_IFC == MOUNTAIN) {
- QIC02_STAT_PORT = QIC02_TAPE_PORT + 1;
- QIC02_CTL_PORT = QIC02_TAPE_PORT + 1;
- QIC02_CMD_PORT = QIC02_TAPE_PORT;
- QIC02_DATA_PORT = QIC02_TAPE_PORT;
-
- QIC02_STAT_READY = MTN_QIC02_STAT_READY;
- QIC02_STAT_EXCEPTION = MTN_QIC02_STAT_EXCEPTION;
- QIC02_STAT_MASK = MTN_QIC02_STAT_MASK;
-
- QIC02_STAT_RESETMASK = MTN_QIC02_STAT_RESETMASK;
- QIC02_STAT_RESETVAL = MTN_QIC02_STAT_RESETVAL;
-
- QIC02_CTL_RESET = MTN_QIC02_CTL_RESET;
- QIC02_CTL_REQUEST = MTN_QIC02_CTL_REQUEST;
-
- if (QIC02_TAPE_DMA > 3) {
- tpqputs(TPQD_ALWAYS,
- "Unsupported or incorrect DMA channel");
- return -EIO;
- }
- } else {
- tpqputs(TPQD_ALWAYS, "Invalid interface type");
- return -ENXIO;
- }
- return qic02_get_resources();
-} /* update_ifc_masks */
-#endif
-
-
-/* ioctl allows user programs to rewind the tape and stuff like that */
-static int qic02_tape_ioctl(struct inode *inode, struct file *filp, unsigned int iocmd, unsigned long ioarg)
-{
- int error;
- int c;
- struct mtop operation;
- unsigned char blk_addr[6];
- struct mtpos ioctl_tell;
- void __user *argp = (void __user *)ioarg;
-
-
- if (TP_DIAGS(current_type))
- printk(TPQIC02_NAME ": ioctl(%4x, %4lx)\n", iocmd, ioarg);
-
- if (!inode)
- return -EINVAL;
-
- /* check iocmd first */
-
- c = _IOC_NR(iocmd);
-
-#ifdef CONFIG_QIC02_DYNCONF
- if (c == _IOC_NR(MTIOCGETCONFIG)) {
- CHECK_IOC_SIZE(mtconfiginfo);
-
- if (copy_to_user(argp, &qic02_tape_dynconf, sizeof(qic02_tape_dynconf)))
- return -EFAULT;
- return 0;
- } else if (c == _IOC_NR(MTIOCSETCONFIG)) {
- /* One should always do a MTIOCGETCONFIG first, then update
- * user-settings, then write back with MTIOCSETCONFIG.
- * The qic02conf program should re-open() the device before actual
- * use, to make sure everything is initialized.
- */
-
- CHECK_IOC_SIZE(mtconfiginfo);
-
- if (!capable(CAP_SYS_RAWIO))
- return -EPERM;
-
- if (doing_read != NO || doing_write != NO)
- return -EBUSY;
-
- if (status_zombie == NO)
- qic02_release_resources(); /* and go zombie */
-
- /* copy struct from user space to kernel space */
- if (copy_from_user(&qic02_tape_dynconf, argp, sizeof(qic02_tape_dynconf)))
- return -EFAULT;
-
- return update_ifc_masks(qic02_tape_dynconf.ifc_type);
- }
- if (status_zombie == YES) {
- tpqputs(TPQD_ALWAYS, "Configs not set");
- return -ENXIO;
- }
-#endif
- if (c == _IOC_NR(MTIOCTOP)) {
- CHECK_IOC_SIZE(mtop);
-
- /* copy mtop struct from user space to kernel space */
- if (copy_from_user(&operation, argp, sizeof(operation)))
- return -EFAULT;
-
- /* ---note: mt_count is signed, negative seeks must be
- * --- translated to seeks in opposite direction!
- * (only needed for Sun-programs, I think.)
- */
- /* ---note: MTFSF with count 0 should position the
- * --- tape at the beginning of the current file.
- */
-
- if (TP_DIAGS(current_type))
- printk("OP op=%4x, count=%4x\n", operation.mt_op, operation.mt_count);
-
- if (operation.mt_count < 0)
- tpqputs(TPQD_ALWAYS, "Warning: negative mt_count ignored");
-
- ioctl_status.mt_resid = operation.mt_count;
- if (operation.mt_op == MTSEEK) {
- if (!TP_HAVE_SEEK)
- return -ENOTTY;
-
- seek_addr_buf[0] = (operation.mt_count >> 16) & 0xff;
- seek_addr_buf[1] = (operation.mt_count >> 8) & 0xff;
- seek_addr_buf[2] = (operation.mt_count) & 0xff;
- if (operation.mt_count >> 24)
- return -EINVAL;
-
- if ((error = do_ioctl_cmd(operation.mt_op)) != 0)
- return error;
-
- ioctl_status.mt_resid = 0;
- } else {
- while (operation.mt_count > 0) {
- operation.mt_count--;
- if ((error = do_ioctl_cmd(operation.mt_op)) != 0)
- return error;
-
- ioctl_status.mt_resid = operation.mt_count;
- }
- }
- return 0;
-
- } else if (c == _IOC_NR(MTIOCGET)) {
- if (TP_DIAGS(current_type))
- printk("GET ");
-
- CHECK_IOC_SIZE(mtget);
-
- /* It appears (gmt(1)) that it is normal behaviour to
- * first set the status with MTNOP, and then to read
- * it out with MTIOCGET
- */
-
- /* copy results to user space */
- if (copy_to_user(argp, &ioctl_status, sizeof(ioctl_status)))
- return -EFAULT;
- return 0;
- } else if (TP_HAVE_TELL && (c == _IOC_NR(MTIOCPOS))) {
- if (TP_DIAGS(current_type))
- printk("POS ");
-
- CHECK_IOC_SIZE(mtpos);
-
- tpqputs(TPQD_IOCTLS, "MTTELL reading block address");
- if (doing_read == YES || doing_write == YES)
- finish_rw(AR_QCMDV_TELL_BLK);
-
- c = rdstatus((char *) blk_addr, sizeof(blk_addr), AR_QCMDV_TELL_BLK);
- if (c != TE_OK)
- return -EIO;
-
- ioctl_tell.mt_blkno = (blk_addr[3] << 16) | (blk_addr[4] << 8) | blk_addr[5];
-
- /* copy results to user space */
- if (copy_to_user(argp, &ioctl_tell, sizeof(ioctl_tell)))
- return -EFAULT;
- return 0;
-
- } else
- return -ENOTTY; /* Other cmds not supported. */
-} /* qic02_tape_ioctl */
-
-
-static ssize_t qic02_do_tape_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos)
-{
- int err;
-
- down(&tape_op);
- err = qic02_tape_read(filp, buf, count, ppos);
- up(&tape_op);
-
- return err;
-}
-
-static ssize_t qic02_do_tape_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
-{
- int err;
-
- down(&tape_op);
- err = qic02_tape_write(filp, buf, count, ppos);
- up(&tape_op);
-
- return err;
-}
-
-static int qic02_do_tape_ioctl(struct inode *inode, struct file *filp, unsigned int iocmd, unsigned long ioarg)
-{
- int err;
-
- down(&tape_op);
- err = qic02_tape_ioctl(inode, filp, iocmd, ioarg);
- up(&tape_op);
-
- return err;
-}
-
-/* These are (most) of the interface functions: */
-static struct file_operations qic02_tape_fops = {
- .owner = THIS_MODULE,
- .llseek = no_llseek,
- .read = qic02_do_tape_read,
- .write = qic02_do_tape_write,
- .ioctl = qic02_do_tape_ioctl,
- .open = qic02_tape_open,
- .release = qic02_tape_release,
-};
-
-
-static void qic02_release_resources(void)
-{
- free_irq(QIC02_TAPE_IRQ, NULL);
- free_dma(QIC02_TAPE_DMA);
- release_region(QIC02_TAPE_PORT, QIC02_TAPE_PORT_RANGE);
- if (buffaddr)
- free_pages((unsigned long) buffaddr, get_order(TPQBUF_SIZE));
- buffaddr = NULL; /* Better to cause a panic than overwite someone else */
- status_zombie = YES;
-} /* qic02_release_resources */
-
-
-static int qic02_get_resources(void)
-{
- /* First perform some checks. If one of them fails,
- * the tape driver will not be registered to the system.
- */
-
- /* for DYNCONF, allocating IO, DMA and IRQ should not be done until
- * the config parameters have been set using MTSETCONFIG.
- */
-
- /* Grab the IO region. */
- if (!request_region(QIC02_TAPE_PORT, QIC02_TAPE_PORT_RANGE, TPQIC02_NAME)) {
- printk(TPQIC02_NAME ": IO space at 0x%x [%d ports] already reserved\n",
- QIC02_TAPE_PORT, QIC02_TAPE_PORT_RANGE);
- return -ENXIO;
- }
-
- /* get IRQ */
- if (request_irq(QIC02_TAPE_IRQ, qic02_tape_interrupt, SA_INTERRUPT, "QIC-02", NULL)) {
- printk(TPQIC02_NAME ": can't allocate IRQ%d for QIC-02 tape\n", QIC02_TAPE_IRQ);
- release_region(QIC02_TAPE_PORT, QIC02_TAPE_PORT_RANGE);
- return -EBUSY;
- }
-
- /* After IRQ, allocate DMA channel */
- if (request_dma(QIC02_TAPE_DMA, "QIC-02")) {
- printk(TPQIC02_NAME ": can't allocate DMA%d for QIC-02 tape\n", QIC02_TAPE_DMA);
- free_irq(QIC02_TAPE_IRQ, NULL);
- release_region(QIC02_TAPE_PORT, QIC02_TAPE_PORT_RANGE);
- return -EBUSY;
- }
-
- /* Setup the page-address for the dma transfer. */
- buffaddr = (void *) __get_dma_pages(GFP_KERNEL, get_order(TPQBUF_SIZE));
- if (!buffaddr) {
- qic02_release_resources();
- return -EBUSY; /* Not ideal, EAGAIN perhaps? */
- }
-
- memset(buffaddr, 0, TPQBUF_SIZE);
-
- printk(TPQIC02_NAME ": Settings: IRQ %d, DMA %d, IO 0x%x, IFC %s\n",
- QIC02_TAPE_IRQ, QIC02_TAPE_DMA, ((QIC02_TAPE_IFC == ARCHIVE)
- || (QIC02_TAPE_IFC ==
- MOUNTAIN)) ?
- QIC02_CMD_PORT : QIC02_STAT_PORT,
- (QIC02_TAPE_IFC ==
- MOUNTAIN) ? "Mountain" : ((QIC02_TAPE_IFC ==
- ARCHIVE) ? "Archive" :
- "Wangtek"));
-
- if (tape_reset(0) != TE_OK || tp_sense(TP_WRP | TP_POR | TP_CNI) != TE_OK) {
- /* No drive detected, so vanish */
- tpqputs(TPQD_ALWAYS, "No drive detected -- releasing IO/IRQ/DMA.");
- status_dead = YES;
- qic02_release_resources();
- return -EIO;
- }
-
- /* All should be ok now */
- status_zombie = NO;
- return 0;
-} /* qic02_get_resources */
-
-int __init qic02_tape_init(void)
-{
- if (TPSTATSIZE != 6) {
- printk(TPQIC02_NAME ": internal error: tpstatus struct incorrect!\n");
- return -ENODEV;
- }
- if ((TPQBUF_SIZE < 512) || (TPQBUF_SIZE >= 0x10000)) {
- printk(TPQIC02_NAME ": internal error: DMA buffer size out of range\n");
- return -ENODEV;
- }
-
- current_type = 0;
-
-#ifndef CONFIG_QIC02_DYNCONF
- printk(TPQIC02_NAME ": IRQ %d, DMA %d, IO 0x%x, IFC %s, %s, %s\n",
- QIC02_TAPE_IRQ, QIC02_TAPE_DMA,
-# if QIC02_TAPE_IFC == WANGTEK
- QIC02_STAT_PORT, "Wangtek",
-# elif QIC02_TAPE_IFC == ARCHIVE
- QIC02_CMD_PORT, "Archive",
-# elif QIC02_TAPE_IFC == MOUNTAIN
- QIC02_CMD_PORT, "Mountain",
-# else
-# error
-# endif
- rcs_revision, rcs_date);
- if (qic02_get_resources())
- return -ENODEV;
-#else
- printk(TPQIC02_NAME ": Runtime config, %s, %s\n", rcs_revision, rcs_date);
-#endif
- printk(TPQIC02_NAME ": DMA buffers: %u blocks\n", NR_BLK_BUF);
- /* If we got this far, install driver functions */
- if (register_chrdev(QIC02_TAPE_MAJOR, TPQIC02_NAME, &qic02_tape_fops))
- {
- printk(TPQIC02_NAME ": Unable to get chrdev major %d\n", QIC02_TAPE_MAJOR);
-#ifndef CONFIG_QIC02_DYNCONF
- qic02_release_resources();
-#endif
- return -ENODEV;
- }
-
- tpqic02_class = class_simple_create(THIS_MODULE, TPQIC02_NAME);
- class_simple_device_add(tpqic02_class, MKDEV(QIC02_TAPE_MAJOR, 2), NULL, "ntpqic11");
- devfs_mk_cdev(MKDEV(QIC02_TAPE_MAJOR, 2),
- S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP, "ntpqic11");
- class_simple_device_add(tpqic02_class, MKDEV(QIC02_TAPE_MAJOR, 3), NULL, "tpqic11");
- devfs_mk_cdev(MKDEV(QIC02_TAPE_MAJOR, 3),
- S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP, "tpqic11");
-
- class_simple_device_add(tpqic02_class, MKDEV(QIC02_TAPE_MAJOR, 4), NULL, "ntpqic24");
- devfs_mk_cdev(MKDEV(QIC02_TAPE_MAJOR, 4),
- S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP, "ntpqic24");
- class_simple_device_add(tpqic02_class, MKDEV(QIC02_TAPE_MAJOR, 5), NULL, "tpqic24");
- devfs_mk_cdev(MKDEV(QIC02_TAPE_MAJOR, 5),
- S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP, "tpqic24");
-
- class_simple_device_add(tpqic02_class, MKDEV(QIC02_TAPE_MAJOR, 6), NULL, "ntpqic20");
- devfs_mk_cdev(MKDEV(QIC02_TAPE_MAJOR, 6),
- S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP, "ntpqic120");
- class_simple_device_add(tpqic02_class, MKDEV(QIC02_TAPE_MAJOR, 7), NULL, "tpqic20");
- devfs_mk_cdev(MKDEV(QIC02_TAPE_MAJOR, 7),
- S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP, "tpqic120");
-
- class_simple_device_add(tpqic02_class, MKDEV(QIC02_TAPE_MAJOR, 8), NULL, "ntpqic50");
- devfs_mk_cdev(MKDEV(QIC02_TAPE_MAJOR, 8),
- S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP, "ntpqic150");
- class_simple_device_add(tpqic02_class, MKDEV(QIC02_TAPE_MAJOR, 9), NULL, "tpqic50");
- devfs_mk_cdev(MKDEV(QIC02_TAPE_MAJOR, 9),
- S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP, "tpqic150");
-
- init_waitqueue_head(&qic02_tape_transfer);
- /* prepare timer */
- TIMEROFF;
- init_timer(&tp_timer);
- tp_timer.function = qic02_tape_times_out;
-
-#ifndef CONFIG_QIC02_DYNCONF
- if (tape_reset(0) != TE_OK || tp_sense(TP_WRP | TP_POR | TP_CNI) != TE_OK) {
- /* No drive detected, so vanish */
- tpqputs(TPQD_ALWAYS, "No drive detected -- driver going on vacation...");
- qic02_release_resources();
- status_dead = YES;
- return -ENODEV;
- } else {
- if (is_exception()) {
- tpqputs(TPQD_ALWAYS, "exception detected\n");
- (void) tp_sense(TP_WRP | TP_POR | TP_CNI);
- }
- }
-#endif
-
- /* initialize generic status for ioctl requests */
-
- ioctl_status.mt_type = QIC02_TAPE_DRIVE; /* MT_IS* id nr */
-
- ioctl_status.mt_resid = 0; /* ---residual count */
- ioctl_status.mt_gstat = 0; /* ---generic status */
- ioctl_status.mt_erreg = 0; /* not used */
- ioctl_status.mt_fileno = 0; /* number of current file on tape */
- ioctl_status.mt_blkno = 0; /* number of current (logical) block */
-
- return 0;
-} /* qic02_tape_init */
-
-static void qic02_module_exit(void)
-{
- unregister_chrdev(QIC02_TAPE_MAJOR, TPQIC02_NAME);
- if (status_zombie == NO)
- qic02_release_resources();
-
- devfs_remove("ntpqic11");
- class_simple_device_remove(MKDEV(QIC02_TAPE_MAJOR, 2));
- devfs_remove("tpqic11");
- class_simple_device_remove(MKDEV(QIC02_TAPE_MAJOR, 3));
- devfs_remove("ntpqic24");
- class_simple_device_remove(MKDEV(QIC02_TAPE_MAJOR, 4));
- devfs_remove("tpqic24");
- class_simple_device_remove(MKDEV(QIC02_TAPE_MAJOR, 5));
- devfs_remove("ntpqic120");
- class_simple_device_remove(MKDEV(QIC02_TAPE_MAJOR, 6));
- devfs_remove("tpqic120");
- class_simple_device_remove(MKDEV(QIC02_TAPE_MAJOR, 7));
- devfs_remove("ntpqic150");
- class_simple_device_remove(MKDEV(QIC02_TAPE_MAJOR, 8));
- devfs_remove("tpqic150");
- class_simple_device_remove(MKDEV(QIC02_TAPE_MAJOR, 9));
-
- class_simple_destroy(tpqic02_class);
-}
-
-static int qic02_module_init(void)
-{
- int retval;
- retval = qic02_tape_init();
-# ifdef CONFIG_QIC02_DYNCONF
- /* This allows the dynamic config program to setup the card
- * by presetting qic02_tape_dynconf via insmod
- */
- if (!retval && qic02_tape_dynconf.ifc_type) {
- retval = update_ifc_masks(qic02_tape_dynconf.ifc_type);
- if (retval) {
- qic02_module_exit();
- }
- }
-# endif
- return retval;
-}
-
-MODULE_LICENSE("GPL");
-
-module_init(qic02_module_init);
-module_exit(qic02_module_exit);
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 33637e313e70e..06e5a3f1836db 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -1789,7 +1789,6 @@ retry_open:
}
#ifdef CONFIG_VT
if (device == MKDEV(TTY_MAJOR,0)) {
- extern int fg_console;
extern struct tty_driver *console_driver;
driver = console_driver;
index = fg_console;
@@ -2016,11 +2015,10 @@ static int tiocswinsz(struct tty_struct *tty, struct tty_struct *real_tty,
return 0;
#ifdef CONFIG_VT
if (tty->driver->type == TTY_DRIVER_TYPE_CONSOLE) {
- unsigned int currcons = tty->index;
int rc;
acquire_console_sem();
- rc = vc_resize(currcons, tmp_ws.ws_col, tmp_ws.ws_row);
+ rc = vc_resize(tty->driver_data, tmp_ws.ws_col, tmp_ws.ws_row);
release_console_sem();
if (rc)
return -ENXIO;
@@ -2632,6 +2630,7 @@ static void initialize_tty_struct(struct tty_struct *tty)
tty->magic = TTY_MAGIC;
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);
diff --git a/drivers/char/vc_screen.c b/drivers/char/vc_screen.c
index 55971a272eadd..7abe405b8657c 100644
--- a/drivers/char/vc_screen.c
+++ b/drivers/char/vc_screen.c
@@ -52,14 +52,17 @@ vcs_size(struct inode *inode)
int size;
int minor = iminor(inode);
int currcons = minor & 127;
+ struct vc_data *vc;
+
if (currcons == 0)
currcons = fg_console;
else
currcons--;
if (!vc_cons_allocated(currcons))
return -ENXIO;
+ vc = vc_cons[currcons].d;
- size = vc_cons[currcons].d->vc_rows * vc_cons[currcons].d->vc_cols;
+ size = vc->vc_rows * vc->vc_cols;
if (minor & 128)
size = 2*size + HEADER_SIZE;
@@ -442,7 +445,7 @@ vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
buf += orig_count;
pos += orig_count;
if (org0)
- update_region(currcons, (unsigned long)(org0), org-org0);
+ update_region(vc, (unsigned long)(org0), org - org0);
}
*ppos += written;
ret = written;
diff --git a/drivers/char/vr41xx_rtc.c b/drivers/char/vr41xx_rtc.c
new file mode 100644
index 0000000000000..a6dbe4da030c7
--- /dev/null
+++ b/drivers/char/vr41xx_rtc.c
@@ -0,0 +1,709 @@
+/*
+ * Driver for NEC VR4100 series Real Time Clock unit.
+ *
+ * Copyright (C) 2003-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <linux/device.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/irq.h>
+#include <linux/mc146818rtc.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/poll.h>
+#include <linux/rtc.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+#include <linux/wait.h>
+
+#include <asm/div64.h>
+#include <asm/io.h>
+#include <asm/time.h>
+#include <asm/uaccess.h>
+#include <asm/vr41xx/vr41xx.h>
+
+MODULE_AUTHOR("Yoichi Yuasa <yuasa@hh.iij4u.or.jp>");
+MODULE_DESCRIPTION("NEC VR4100 series RTC driver");
+MODULE_LICENSE("GPL");
+
+#define RTC1_TYPE1_START 0x0b0000c0UL
+#define RTC1_TYPE1_END 0x0b0000dfUL
+#define RTC2_TYPE1_START 0x0b0001c0UL
+#define RTC2_TYPE1_END 0x0b0001dfUL
+
+#define RTC1_TYPE2_START 0x0f000100UL
+#define RTC1_TYPE2_END 0x0f00011fUL
+#define RTC2_TYPE2_START 0x0f000120UL
+#define RTC2_TYPE2_END 0x0f00013fUL
+
+#define RTC1_SIZE 0x20
+#define RTC2_SIZE 0x20
+
+/* RTC 1 registers */
+#define ETIMELREG 0x00
+#define ETIMEMREG 0x02
+#define ETIMEHREG 0x04
+/* RFU */
+#define ECMPLREG 0x08
+#define ECMPMREG 0x0a
+#define ECMPHREG 0x0c
+/* RFU */
+#define RTCL1LREG 0x10
+#define RTCL1HREG 0x12
+#define RTCL1CNTLREG 0x14
+#define RTCL1CNTHREG 0x16
+#define RTCL2LREG 0x18
+#define RTCL2HREG 0x1a
+#define RTCL2CNTLREG 0x1c
+#define RTCL2CNTHREG 0x1e
+
+/* RTC 2 registers */
+#define TCLKLREG 0x00
+#define TCLKHREG 0x02
+#define TCLKCNTLREG 0x04
+#define TCLKCNTHREG 0x06
+/* RFU */
+#define RTCINTREG 0x1e
+ #define TCLOCK_INT 0x08
+ #define RTCLONG2_INT 0x04
+ #define RTCLONG1_INT 0x02
+ #define ELAPSEDTIME_INT 0x01
+
+#define RTC_FREQUENCY 32768
+#define MAX_PERIODIC_RATE 6553
+#define MAX_USER_PERIODIC_RATE 64
+
+static void __iomem *rtc1_base;
+static void __iomem *rtc2_base;
+
+#define rtc1_read(offset) readw(rtc1_base + (offset))
+#define rtc1_write(offset, value) writew((value), rtc1_base + (offset))
+
+#define rtc2_read(offset) readw(rtc2_base + (offset))
+#define rtc2_write(offset, value) writew((value), rtc2_base + (offset))
+
+static unsigned long epoch = 1970; /* Jan 1 1970 00:00:00 */
+
+static spinlock_t rtc_task_lock;
+static wait_queue_head_t rtc_wait;
+static unsigned long rtc_irq_data;
+static struct fasync_struct *rtc_async_queue;
+static rtc_task_t *rtc_callback;
+static char rtc_name[] = "RTC";
+static unsigned long periodic_frequency;
+static unsigned long periodic_count;
+
+typedef enum {
+ RTC_RELEASE,
+ RTC_OPEN,
+} rtc_status_t;
+
+static rtc_status_t rtc_status;
+
+typedef enum {
+ FUNCTION_RTC_IOCTL,
+ FUNCTION_RTC_CONTROL,
+} rtc_callfrom_t;
+
+struct resource rtc_resource[2] = {
+ { .name = rtc_name,
+ .flags = IORESOURCE_MEM, },
+ { .name = rtc_name,
+ .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;
+ unsigned long second_low, second_mid, second_high;
+
+ do {
+ first_low = rtc1_read(ETIMELREG);
+ first_mid = rtc1_read(ETIMEMREG);
+ first_high = rtc1_read(ETIMEHREG);
+ second_low = rtc1_read(ETIMELREG);
+ second_mid = rtc1_read(ETIMEMREG);
+ second_high = rtc1_read(ETIMEHREG);
+ } while (first_low != second_low || first_mid != second_mid ||
+ first_high != second_high);
+
+ return (first_high << 17) | (first_mid << 1) | (first_low >> 15);
+}
+
+static inline void write_elapsed_second(unsigned long sec)
+{
+ spin_lock_irq(&rtc_lock);
+
+ rtc1_write(ETIMELREG, (uint16_t)(sec << 15));
+ rtc1_write(ETIMEMREG, (uint16_t)(sec >> 1));
+ rtc1_write(ETIMEHREG, (uint16_t)(sec >> 17));
+
+ spin_unlock_irq(&rtc_lock);
+}
+
+static void set_alarm(struct rtc_time *time)
+{
+ unsigned long alarm_sec;
+
+ alarm_sec = mktime(time->tm_year + 1900, time->tm_mon + 1, time->tm_mday,
+ time->tm_hour, time->tm_min, time->tm_sec);
+
+ spin_lock_irq(&rtc_lock);
+
+ rtc1_write(ECMPLREG, (uint16_t)(alarm_sec << 15));
+ rtc1_write(ECMPMREG, (uint16_t)(alarm_sec >> 1));
+ rtc1_write(ECMPHREG, (uint16_t)(alarm_sec >> 17));
+
+ spin_unlock_irq(&rtc_lock);
+}
+
+static void read_alarm(struct rtc_time *time)
+{
+ unsigned long low, mid, high;
+
+ spin_lock_irq(&rtc_lock);
+
+ low = rtc1_read(ECMPLREG);
+ mid = rtc1_read(ECMPMREG);
+ high = rtc1_read(ECMPHREG);
+
+ spin_unlock_irq(&rtc_lock);
+
+ to_tm((high << 17) | (mid << 1) | (low >> 15), time);
+ time->tm_year -= 1900;
+}
+
+static void read_time(struct rtc_time *time)
+{
+ unsigned long epoch_sec, elapsed_sec;
+
+ epoch_sec = mktime(epoch, 1, 1, 0, 0, 0);
+ elapsed_sec = read_elapsed_second();
+
+ to_tm(epoch_sec + elapsed_sec, time);
+ time->tm_year -= 1900;
+}
+
+static void set_time(struct rtc_time *time)
+{
+ unsigned long epoch_sec, current_sec;
+
+ epoch_sec = mktime(epoch, 1, 1, 0, 0, 0);
+ current_sec = mktime(time->tm_year + 1900, time->tm_mon + 1, time->tm_mday,
+ time->tm_hour, time->tm_min, time->tm_sec);
+
+ write_elapsed_second(current_sec - epoch_sec);
+}
+
+static ssize_t rtc_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
+{
+ DECLARE_WAITQUEUE(wait, current);
+ unsigned long irq_data;
+ int retval = 0;
+
+ if (count != sizeof(unsigned int) && count != sizeof(unsigned long))
+ return -EINVAL;
+
+ add_wait_queue(&rtc_wait, &wait);
+
+ do {
+ __set_current_state(TASK_INTERRUPTIBLE);
+
+ spin_lock_irq(&rtc_lock);
+ irq_data = rtc_irq_data;
+ rtc_irq_data = 0;
+ spin_unlock_irq(&rtc_lock);
+
+ if (irq_data != 0)
+ break;
+
+ if (file->f_flags & O_NONBLOCK) {
+ retval = -EAGAIN;
+ break;
+ }
+
+ if (signal_pending(current)) {
+ retval = -ERESTARTSYS;
+ break;
+ }
+ } while (1);
+
+ if (retval == 0) {
+ if (count == sizeof(unsigned int)) {
+ retval = put_user(irq_data, (unsigned int __user *)buf);
+ if (retval == 0)
+ retval = sizeof(unsigned int);
+ } else {
+ retval = put_user(irq_data, (unsigned long __user *)buf);
+ if (retval == 0)
+ retval = sizeof(unsigned long);
+ }
+
+ }
+
+ __set_current_state(TASK_RUNNING);
+ remove_wait_queue(&rtc_wait, &wait);
+
+ return retval;
+}
+
+static unsigned int rtc_poll(struct file *file, struct poll_table_struct *table)
+{
+ poll_wait(file, &rtc_wait, table);
+
+ if (rtc_irq_data != 0)
+ return POLLIN | POLLRDNORM;
+
+ return 0;
+}
+
+static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, rtc_callfrom_t from)
+{
+ struct rtc_time time;
+ unsigned long count;
+
+ switch (cmd) {
+ case RTC_AIE_ON:
+ enable_irq(ELAPSEDTIME_IRQ);
+ break;
+ case RTC_AIE_OFF:
+ disable_irq(ELAPSEDTIME_IRQ);
+ break;
+ case RTC_PIE_ON:
+ enable_irq(RTCLONG1_IRQ);
+ break;
+ case RTC_PIE_OFF:
+ disable_irq(RTCLONG1_IRQ);
+ break;
+ case RTC_ALM_SET:
+ if (copy_from_user(&time, (struct rtc_time __user *)arg,
+ sizeof(struct rtc_time)))
+ return -EFAULT;
+
+ set_alarm(&time);
+ break;
+ case RTC_ALM_READ:
+ memset(&time, 0, sizeof(struct rtc_time));
+ read_alarm(&time);
+ break;
+ case RTC_RD_TIME:
+ memset(&time, 0, sizeof(struct rtc_time));
+ read_time(&time);
+ if (copy_to_user((void __user *)arg, &time, sizeof(struct rtc_time)))
+ return -EFAULT;
+ break;
+ case RTC_SET_TIME:
+ if (capable(CAP_SYS_TIME) == 0)
+ return -EACCES;
+
+ if (copy_from_user(&time, (struct rtc_time __user *)arg,
+ sizeof(struct rtc_time)))
+ return -EFAULT;
+
+ set_time(&time);
+ break;
+ case RTC_IRQP_READ:
+ return put_user(periodic_frequency, (unsigned long __user *)arg);
+ break;
+ case RTC_IRQP_SET:
+ if (arg > MAX_PERIODIC_RATE)
+ return -EINVAL;
+
+ if (from == FUNCTION_RTC_IOCTL && arg > MAX_USER_PERIODIC_RATE &&
+ capable(CAP_SYS_RESOURCE) == 0)
+ return -EACCES;
+
+ periodic_frequency = arg;
+
+ count = RTC_FREQUENCY;
+ do_div(count, arg);
+
+ periodic_count = count;
+
+ spin_lock_irq(&rtc_lock);
+
+ rtc1_write(RTCL1LREG, count);
+ rtc1_write(RTCL1HREG, count >> 16);
+
+ spin_unlock_irq(&rtc_lock);
+ break;
+ case RTC_EPOCH_READ:
+ return put_user(epoch, (unsigned long __user *)arg);
+ case RTC_EPOCH_SET:
+ /* Doesn't support before 1900 */
+ if (arg < 1900)
+ return -EINVAL;
+
+ if (capable(CAP_SYS_TIME) == 0)
+ return -EACCES;
+
+ epoch = arg;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ return rtc_do_ioctl(cmd, arg, FUNCTION_RTC_IOCTL);
+}
+
+static int rtc_open(struct inode *inode, struct file *file)
+{
+ spin_lock_irq(&rtc_lock);
+
+ if (rtc_status == RTC_OPEN) {
+ spin_unlock_irq(&rtc_lock);
+ return -EBUSY;
+ }
+
+ rtc_status = RTC_OPEN;
+ rtc_irq_data = 0;
+
+ spin_unlock_irq(&rtc_lock);
+
+ return 0;
+}
+
+static int rtc_release(struct inode *inode, struct file *file)
+{
+ if (file->f_flags & FASYNC)
+ (void)fasync_helper(-1, file, 0, &rtc_async_queue);
+
+ spin_lock_irq(&rtc_lock);
+
+ rtc1_write(ECMPLREG, 0);
+ rtc1_write(ECMPMREG, 0);
+ rtc1_write(ECMPHREG, 0);
+ rtc1_write(RTCL1LREG, 0);
+ rtc1_write(RTCL1HREG, 0);
+
+ rtc_status = RTC_RELEASE;
+
+ spin_unlock_irq(&rtc_lock);
+
+ disable_irq(ELAPSEDTIME_IRQ);
+ disable_irq(RTCLONG1_IRQ);
+
+ return 0;
+}
+
+static int rtc_fasync(int fd, struct file *file, int on)
+{
+ return fasync_helper(fd, file, on, &rtc_async_queue);
+}
+
+static struct file_operations rtc_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .read = rtc_read,
+ .poll = rtc_poll,
+ .ioctl = rtc_ioctl,
+ .open = rtc_open,
+ .release = rtc_release,
+ .fasync = rtc_fasync,
+};
+
+static irqreturn_t elapsedtime_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ spin_lock(&rtc_lock);
+ rtc2_write(RTCINTREG, ELAPSEDTIME_INT);
+
+ rtc_irq_data += 0x100;
+ rtc_irq_data &= ~0xff;
+ rtc_irq_data |= RTC_AF;
+ spin_unlock(&rtc_lock);
+
+ spin_lock(&rtc_lock);
+ if (rtc_callback)
+ rtc_callback->func(rtc_callback->private_data);
+ spin_unlock(&rtc_lock);
+
+ wake_up_interruptible(&rtc_wait);
+
+ kill_fasync(&rtc_async_queue, SIGIO, POLL_IN);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t rtclong1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ unsigned long count = periodic_count;
+
+ spin_lock(&rtc_lock);
+ rtc2_write(RTCINTREG, RTCLONG1_INT);
+
+ rtc1_write(RTCL1LREG, count);
+ rtc1_write(RTCL1HREG, count >> 16);
+
+ rtc_irq_data += 0x100;
+ rtc_irq_data &= ~0xff;
+ rtc_irq_data |= RTC_PF;
+ spin_unlock(&rtc_lock);
+
+ spin_lock(&rtc_task_lock);
+ if (rtc_callback)
+ rtc_callback->func(rtc_callback->private_data);
+ spin_unlock(&rtc_task_lock);
+
+ wake_up_interruptible(&rtc_wait);
+
+ kill_fasync(&rtc_async_queue, SIGIO, POLL_IN);
+
+ return IRQ_HANDLED;
+}
+
+int rtc_register(rtc_task_t *task)
+{
+ if (task == NULL || task->func == NULL)
+ return -EINVAL;
+
+ spin_lock_irq(&rtc_lock);
+ if (rtc_status == RTC_OPEN) {
+ spin_unlock_irq(&rtc_lock);
+ return -EBUSY;
+ }
+
+ spin_lock(&rtc_task_lock);
+ if (rtc_callback != NULL) {
+ spin_unlock(&rtc_task_lock);
+ spin_unlock_irq(&rtc_task_lock);
+ return -EBUSY;
+ }
+
+ rtc_callback = task;
+ spin_unlock(&rtc_task_lock);
+
+ rtc_status = RTC_OPEN;
+
+ spin_unlock_irq(&rtc_lock);
+
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(rtc_register);
+
+int rtc_unregister(rtc_task_t *task)
+{
+ spin_lock_irq(&rtc_task_lock);
+ if (task == NULL || rtc_callback != task) {
+ spin_unlock_irq(&rtc_task_lock);
+ return -ENXIO;
+ }
+
+ spin_lock(&rtc_lock);
+
+ rtc1_write(ECMPLREG, 0);
+ rtc1_write(ECMPMREG, 0);
+ rtc1_write(ECMPHREG, 0);
+ rtc1_write(RTCL1LREG, 0);
+ rtc1_write(RTCL1HREG, 0);
+
+ rtc_status = RTC_RELEASE;
+
+ spin_unlock(&rtc_lock);
+
+ rtc_callback = NULL;
+
+ spin_unlock_irq(&rtc_task_lock);
+
+ disable_irq(ELAPSEDTIME_IRQ);
+ disable_irq(RTCLONG1_IRQ);
+
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(rtc_unregister);
+
+int rtc_control(rtc_task_t *task, unsigned int cmd, unsigned long arg)
+{
+ int retval = 0;
+
+ spin_lock_irq(&rtc_task_lock);
+
+ if (rtc_callback != task)
+ retval = -ENXIO;
+ else
+ rtc_do_ioctl(cmd, arg, FUNCTION_RTC_CONTROL);
+
+ spin_unlock_irq(&rtc_task_lock);
+
+ return retval;
+}
+
+EXPORT_SYMBOL_GPL(rtc_control);
+
+static struct miscdevice rtc_miscdevice = {
+ .minor = RTC_MINOR,
+ .name = rtc_name,
+ .fops = &rtc_fops,
+};
+
+static int rtc_probe(struct device *dev)
+{
+ struct platform_device *pdev;
+ unsigned int irq;
+ int retval;
+
+ pdev = to_platform_device(dev);
+ if (pdev->num_resources != 2)
+ return -EBUSY;
+
+ rtc1_base = ioremap(pdev->resource[0].start, RTC1_SIZE);
+ if (rtc1_base == NULL)
+ return -EBUSY;
+
+ rtc2_base = ioremap(pdev->resource[1].start, RTC2_SIZE);
+ if (rtc2_base == NULL) {
+ iounmap(rtc1_base);
+ rtc1_base = NULL;
+ return -EBUSY;
+ }
+
+ retval = misc_register(&rtc_miscdevice);
+ if (retval < 0) {
+ iounmap(rtc1_base);
+ iounmap(rtc2_base);
+ rtc1_base = NULL;
+ rtc2_base = NULL;
+ return retval;
+ }
+
+ spin_lock_irq(&rtc_lock);
+
+ rtc1_write(ECMPLREG, 0);
+ rtc1_write(ECMPMREG, 0);
+ rtc1_write(ECMPHREG, 0);
+ rtc1_write(RTCL1LREG, 0);
+ rtc1_write(RTCL1HREG, 0);
+
+ rtc_status = RTC_RELEASE;
+ rtc_irq_data = 0;
+
+ spin_unlock_irq(&rtc_lock);
+
+ init_waitqueue_head(&rtc_wait);
+
+ irq = ELAPSEDTIME_IRQ;
+ retval = request_irq(irq, elapsedtime_interrupt, SA_INTERRUPT,
+ "elapsed_time", NULL);
+ if (retval == 0) {
+ irq = RTCLONG1_IRQ;
+ retval = request_irq(irq, rtclong1_interrupt, SA_INTERRUPT,
+ "rtclong1", NULL);
+ }
+
+ if (retval < 0) {
+ printk(KERN_ERR "rtc: IRQ%d is busy\n", irq);
+ if (irq == RTCLONG1_IRQ)
+ free_irq(ELAPSEDTIME_IRQ, NULL);
+ iounmap(rtc1_base);
+ iounmap(rtc2_base);
+ rtc1_base = NULL;
+ rtc2_base = NULL;
+ return retval;
+ }
+
+ disable_irq(ELAPSEDTIME_IRQ);
+ disable_irq(RTCLONG1_IRQ);
+
+ spin_lock_init(&rtc_task_lock);
+
+ printk(KERN_INFO "rtc: Real Time Clock of NEC VR4100 series\n");
+
+ return 0;
+}
+
+static int rtc_remove(struct device *dev)
+{
+ int retval;
+
+ retval = misc_deregister(&rtc_miscdevice);
+ if (retval < 0)
+ return retval;
+
+ free_irq(ELAPSEDTIME_IRQ, NULL);
+ free_irq(RTCLONG1_IRQ, NULL);
+ if (rtc1_base != NULL)
+ iounmap(rtc1_base);
+ if (rtc2_base != NULL)
+ iounmap(rtc2_base);
+
+ return 0;
+}
+
+static struct platform_device *rtc_platform_device;
+
+static struct device_driver rtc_device_driver = {
+ .name = rtc_name,
+ .bus = &platform_bus_type,
+ .probe = rtc_probe,
+ .remove = rtc_remove,
+};
+
+static int __devinit vr41xx_rtc_init(void)
+{
+ int retval;
+
+ switch (current_cpu_data.cputype) {
+ case CPU_VR4111:
+ case CPU_VR4121:
+ rtc_resource[0].start = RTC1_TYPE1_START;
+ rtc_resource[0].end = RTC1_TYPE1_END;
+ rtc_resource[1].start = RTC2_TYPE1_START;
+ rtc_resource[1].end = RTC2_TYPE1_END;
+ break;
+ case CPU_VR4122:
+ case CPU_VR4131:
+ case CPU_VR4133:
+ rtc_resource[0].start = RTC1_TYPE2_START;
+ rtc_resource[0].end = RTC1_TYPE2_END;
+ rtc_resource[1].start = RTC2_TYPE2_START;
+ rtc_resource[1].end = RTC2_TYPE2_END;
+ break;
+ default:
+ return -ENODEV;
+ break;
+ }
+
+ rtc_platform_device = platform_device_register_simple("RTC", -1, rtc_resource, RTC_NUM_RESOURCES);
+ if (IS_ERR(rtc_platform_device))
+ return PTR_ERR(rtc_platform_device);
+
+ retval = driver_register(&rtc_device_driver);
+ if (retval < 0)
+ platform_device_unregister(rtc_platform_device);
+
+ return retval;
+}
+
+static void __devexit vr41xx_rtc_exit(void)
+{
+ driver_unregister(&rtc_device_driver);
+
+ platform_device_unregister(rtc_platform_device);
+}
+
+module_init(vr41xx_rtc_init);
+module_exit(vr41xx_rtc_exit);
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index 261599fd095a6..e5ef1dfc54826 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -98,8 +98,6 @@
#include <asm/system.h>
#include <asm/uaccess.h>
-#include "console_macros.h"
-
const struct consw *conswitchp;
@@ -135,17 +133,18 @@ static const struct consw *con_driver_map[MAX_NR_CONSOLES];
#endif
static int con_open(struct tty_struct *, struct file *);
-static void vc_init(unsigned int console, unsigned int rows,
+static void vc_init(struct vc_data *vc, unsigned int rows,
unsigned int cols, int do_clear);
static void gotoxy(struct vc_data *vc, int new_x, int new_y);
-static void save_cur(int currcons);
-static void reset_terminal(int currcons, int do_clear);
+static void save_cur(struct vc_data *vc);
+static void reset_terminal(struct vc_data *vc, int do_clear);
static void con_flush_chars(struct tty_struct *tty);
static void set_vesa_blanking(char __user *p);
static void set_cursor(struct vc_data *vc);
static void hide_cursor(struct vc_data *vc);
static void console_callback(void *ignored);
static void blank_screen_t(unsigned long dummy);
+static void set_palette(struct vc_data *vc);
static int printable; /* Is console ready for printing? */
@@ -214,22 +213,14 @@ enum {
* Low-Level Functions
*/
-#define IS_FG (currcons == fg_console)
-#define IS_FG_VC(vc) (vc == vc_cons[fg_console].d)
-
-#define IS_VISIBLE CON_IS_VISIBLE(vc_cons[currcons].d)
+#define IS_FG(vc) ((vc)->vc_num == fg_console)
#ifdef VT_BUF_VRAM_ONLY
-#define DO_UPDATE 0
-#define DO_UPDATE_VC(vc) 0
+#define DO_UPDATE(vc) 0
#else
-#define DO_UPDATE IS_VISIBLE
-#define DO_UPDATE_VC(vc) CON_IS_VISIBLE(vc)
+#define DO_UPDATE(vc) CON_IS_VISIBLE(vc)
#endif
-static int pm_con_request(struct pm_dev *dev, pm_request_t rqst, void *data);
-static struct pm_dev *pm_con;
-
static inline unsigned short *screenpos(struct vc_data *vc, int offset, int viewed)
{
unsigned short *p;
@@ -254,39 +245,38 @@ void schedule_console_callback(void)
schedule_work(&console_work);
}
-static void scrup(int currcons, unsigned int t, unsigned int b, int nr)
+static void scrup(struct vc_data *vc, unsigned int t, unsigned int b, int nr)
{
unsigned short *d, *s;
if (t+nr >= b)
nr = b - t - 1;
- if (b > vc_cons[currcons].d->vc_rows || t >= b || nr < 1)
+ if (b > vc->vc_rows || t >= b || nr < 1)
return;
- if (IS_VISIBLE && sw->con_scroll(vc_cons[currcons].d, t, b, SM_UP, nr))
+ if (CON_IS_VISIBLE(vc) && vc->vc_sw->con_scroll(vc, t, b, SM_UP, nr))
return;
- d = (unsigned short *) (origin+vc_cons[currcons].d->vc_size_row*t);
- s = (unsigned short *) (origin+vc_cons[currcons].d->vc_size_row*(t+nr));
- scr_memmovew(d, s, (b-t-nr) * vc_cons[currcons].d->vc_size_row);
- scr_memsetw(d + (b-t-nr) * vc_cons[currcons].d->vc_cols, video_erase_char,
- vc_cons[currcons].d->vc_size_row * nr);
+ d = (unsigned short *)(vc->vc_origin + vc->vc_size_row * t);
+ s = (unsigned short *)(vc->vc_origin + vc->vc_size_row * (t + nr));
+ scr_memmovew(d, s, (b - t - nr) * vc->vc_size_row);
+ scr_memsetw(d + (b - t - nr) * vc->vc_cols, vc->vc_video_erase_char,
+ vc->vc_size_row * nr);
}
-static void
-scrdown(int currcons, unsigned int t, unsigned int b, int nr)
+static void scrdown(struct vc_data *vc, unsigned int t, unsigned int b, int nr)
{
unsigned short *s;
unsigned int step;
if (t+nr >= b)
nr = b - t - 1;
- if (b > vc_cons[currcons].d->vc_rows || t >= b || nr < 1)
+ if (b > vc->vc_rows || t >= b || nr < 1)
return;
- if (IS_VISIBLE && sw->con_scroll(vc_cons[currcons].d, t, b, SM_DOWN, nr))
+ if (CON_IS_VISIBLE(vc) && vc->vc_sw->con_scroll(vc, t, b, SM_DOWN, nr))
return;
- s = (unsigned short *) (origin+vc_cons[currcons].d->vc_size_row*t);
- step = vc_cons[currcons].d->vc_cols * nr;
- scr_memmovew(s + step, s, (b-t-nr)*vc_cons[currcons].d->vc_size_row);
- scr_memsetw(s, video_erase_char, 2*step);
+ s = (unsigned short *)(vc->vc_origin + vc->vc_size_row * t);
+ step = vc->vc_cols * nr;
+ scr_memmovew(s + step, s, (b - t - nr) * vc->vc_size_row);
+ scr_memsetw(s, vc->vc_video_erase_char, 2 * step);
}
static void do_update_region(struct vc_data *vc, unsigned long start, int count)
@@ -335,23 +325,23 @@ static void do_update_region(struct vc_data *vc, unsigned long start, int count)
#endif
}
-void update_region(int currcons, unsigned long start, int count)
+void update_region(struct vc_data *vc, unsigned long start, int count)
{
WARN_CONSOLE_UNLOCKED();
- if (DO_UPDATE) {
- hide_cursor(vc_cons[currcons].d);
- do_update_region(vc_cons[currcons].d, start, count);
- set_cursor(vc_cons[currcons].d);
+ if (DO_UPDATE(vc)) {
+ hide_cursor(vc);
+ do_update_region(vc, start, count);
+ set_cursor(vc);
}
}
/* Structure of attributes is hardware-dependent */
-static u8 build_attr(int currcons, u8 _color, u8 _intensity, u8 _blink, u8 _underline, u8 _reverse)
+static u8 build_attr(struct vc_data *vc, u8 _color, u8 _intensity, u8 _blink, u8 _underline, u8 _reverse)
{
- if (sw->con_build_attr)
- return sw->con_build_attr(vc_cons[currcons].d, _color, _intensity, _blink, _underline, _reverse);
+ if (vc->vc_sw->con_build_attr)
+ return vc->vc_sw->con_build_attr(vc, _color, _intensity, _blink, _underline, _reverse);
#ifndef VT_BUF_VRAM_ONLY
/*
@@ -365,23 +355,23 @@ static u8 build_attr(int currcons, u8 _color, u8 _intensity, u8 _blink, u8 _unde
* Bit 7 : blink
*/
{
- u8 a = color;
- if (!vc_cons[currcons].d->vc_can_do_color)
+ u8 a = vc->vc_color;
+ if (!vc->vc_can_do_color)
return _intensity |
(_underline ? 4 : 0) |
(_reverse ? 8 : 0) |
(_blink ? 0x80 : 0);
if (_underline)
- a = (a & 0xf0) | ulcolor;
+ a = (a & 0xf0) | vc->vc_ulcolor;
else if (_intensity == 0)
- a = (a & 0xf0) | halfcolor;
+ a = (a & 0xf0) | vc->vc_ulcolor;
if (_reverse)
a = ((a) & 0x88) | ((((a) >> 4) | ((a) << 4)) & 0x77);
if (_blink)
a ^= 0x80;
if (_intensity == 2)
a ^= 0x08;
- if (hi_font_mask == 0x100)
+ if (vc->vc_hi_font_mask == 0x100)
a <<= 1;
return a;
}
@@ -390,10 +380,10 @@ static u8 build_attr(int currcons, u8 _color, u8 _intensity, u8 _blink, u8 _unde
#endif
}
-static void update_attr(int currcons)
+static void update_attr(struct vc_data *vc)
{
- attr = build_attr(currcons, color, intensity, blink, underline, reverse ^ decscnm);
- video_erase_char = (build_attr(currcons, color, 1, blink, 0, decscnm) << 8) | ' ';
+ vc->vc_attr = build_attr(vc, vc->vc_color, vc->vc_intensity, vc->vc_blink, vc->vc_underline, vc->vc_reverse ^ vc->vc_decscnm);
+ vc->vc_video_erase_char = (build_attr(vc, vc->vc_color, 1, vc->vc_blink, 0, vc->vc_decscnm) << 8) | ' ';
}
/* Note: inverting the screen twice should revert to the original state */
@@ -437,7 +427,7 @@ void invert_screen(struct vc_data *vc, int offset, int count, int viewed)
}
}
#endif
- if (DO_UPDATE_VC(vc))
+ if (DO_UPDATE(vc))
do_update_region(vc, (unsigned long) p, count);
}
@@ -452,7 +442,7 @@ void complement_pos(struct vc_data *vc, int offset)
if (p) {
scr_writew(old, p);
- if (DO_UPDATE_VC(vc))
+ if (DO_UPDATE(vc))
vc->vc_sw->con_putc(vc, old, oldy, oldx);
}
if (offset == -1)
@@ -463,7 +453,7 @@ void complement_pos(struct vc_data *vc, int offset)
old = scr_readw(p);
new = old ^ vc->vc_complement_mask;
scr_writew(new, p);
- if (DO_UPDATE_VC(vc)) {
+ if (DO_UPDATE(vc)) {
oldx = (offset >> 1) % vc->vc_cols;
oldy = (offset >> 1) / vc->vc_cols;
vc->vc_sw->con_putc(vc, new, oldy, oldx);
@@ -471,48 +461,46 @@ void complement_pos(struct vc_data *vc, int offset)
}
}
-static void insert_char(int currcons, unsigned int nr)
+static void insert_char(struct vc_data *vc, unsigned int nr)
{
- unsigned short *p, *q = (unsigned short *) pos;
+ unsigned short *p, *q = (unsigned short *)vc->vc_pos;
- p = q + vc_cons[currcons].d->vc_cols - nr - x;
+ p = q + vc->vc_cols - nr - vc->vc_x;
while (--p >= q)
scr_writew(scr_readw(p), p + nr);
- scr_memsetw(q, video_erase_char, nr*2);
- need_wrap = 0;
- if (DO_UPDATE) {
- unsigned short oldattr = attr;
- sw->con_bmove(vc_cons[currcons].d,y,x,y,x+nr,1,
- vc_cons[currcons].d->vc_cols-x-nr);
- attr = video_erase_char >> 8;
+ scr_memsetw(q, vc->vc_video_erase_char, nr * 2);
+ vc->vc_need_wrap = 0;
+ if (DO_UPDATE(vc)) {
+ unsigned short oldattr = vc->vc_attr;
+ vc->vc_sw->con_bmove(vc, vc->vc_y, vc->vc_x, vc->vc_y, vc->vc_x + nr, 1,
+ vc->vc_cols - vc->vc_x - nr);
+ vc->vc_attr = vc->vc_video_erase_char >> 8;
while (nr--)
- sw->con_putc(vc_cons[currcons].d,
- video_erase_char,y,x+nr);
- attr = oldattr;
+ vc->vc_sw->con_putc(vc, vc->vc_video_erase_char, vc->vc_y, vc->vc_x + nr);
+ vc->vc_attr = oldattr;
}
}
-static void delete_char(int currcons, unsigned int nr)
+static void delete_char(struct vc_data *vc, unsigned int nr)
{
- unsigned int i = x;
- unsigned short *p = (unsigned short *) pos;
+ unsigned int i = vc->vc_x;
+ unsigned short *p = (unsigned short *)vc->vc_pos;
- while (++i <= vc_cons[currcons].d->vc_cols - nr) {
+ while (++i <= vc->vc_cols - nr) {
scr_writew(scr_readw(p+nr), p);
p++;
}
- scr_memsetw(p, video_erase_char, nr*2);
- need_wrap = 0;
- if (DO_UPDATE) {
- unsigned short oldattr = attr;
- sw->con_bmove(vc_cons[currcons].d, y, x+nr, y, x, 1,
- vc_cons[currcons].d->vc_cols-x-nr);
- attr = video_erase_char >> 8;
+ scr_memsetw(p, vc->vc_video_erase_char, nr * 2);
+ vc->vc_need_wrap = 0;
+ if (DO_UPDATE(vc)) {
+ unsigned short oldattr = vc->vc_attr;
+ vc->vc_sw->con_bmove(vc, vc->vc_y, vc->vc_x + nr, vc->vc_y, vc->vc_x, 1,
+ vc->vc_cols - vc->vc_x - nr);
+ vc->vc_attr = vc->vc_video_erase_char >> 8;
while (nr--)
- sw->con_putc(vc_cons[currcons].d,
- video_erase_char, y,
- vc_cons[currcons].d->vc_cols-1-nr);
- attr = oldattr;
+ vc->vc_sw->con_putc(vc, vc->vc_video_erase_char, vc->vc_y,
+ vc->vc_cols - 1 - nr);
+ vc->vc_attr = oldattr;
}
}
@@ -531,7 +519,7 @@ static void add_softcursor(struct vc_data *vc)
if ((type & 0x20) && ((softcursor_original & 0x7000) == (i & 0x7000))) i ^= 0x7000;
if ((type & 0x40) && ((i & 0x700) == ((i & 0x7000) >> 4))) i ^= 0x0700;
scr_writew(i, (u16 *) vc->vc_pos);
- if (DO_UPDATE_VC(vc))
+ if (DO_UPDATE(vc))
vc->vc_sw->con_putc(vc, i, vc->vc_y, vc->vc_x);
}
@@ -539,7 +527,7 @@ static void hide_softcursor(struct vc_data *vc)
{
if (softcursor_original != -1) {
scr_writew(softcursor_original, (u16 *)vc->vc_pos);
- if (DO_UPDATE_VC(vc))
+ if (DO_UPDATE(vc))
vc->vc_sw->con_putc(vc, softcursor_original,
vc->vc_y, vc->vc_x);
softcursor_original = -1;
@@ -556,8 +544,8 @@ static void hide_cursor(struct vc_data *vc)
static void set_cursor(struct vc_data *vc)
{
- if (!IS_FG_VC(vc) || console_blanked ||
- vc->vc_vt->vc_mode == KD_GRAPHICS)
+ if (!IS_FG(vc) || console_blanked ||
+ vc->vc_mode == KD_GRAPHICS)
return;
if (vc->vc_deccm) {
if (vc == sel_cons)
@@ -569,98 +557,93 @@ static void set_cursor(struct vc_data *vc)
hide_cursor(vc);
}
-static void set_origin(int currcons)
+static void set_origin(struct vc_data *vc)
{
WARN_CONSOLE_UNLOCKED();
- if (!IS_VISIBLE ||
- !sw->con_set_origin ||
- !sw->con_set_origin(vc_cons[currcons].d))
- origin = (unsigned long) screenbuf;
- visible_origin = origin;
- scr_end = origin + screenbuf_size;
- pos = origin + vc_cons[currcons].d->vc_size_row*y + 2*x;
+ if (!CON_IS_VISIBLE(vc) ||
+ !vc->vc_sw->con_set_origin ||
+ !vc->vc_sw->con_set_origin(vc))
+ vc->vc_origin = (unsigned long)vc->vc_screenbuf;
+ vc->vc_visible_origin = vc->vc_origin;
+ vc->vc_scr_end = vc->vc_origin + vc->vc_screenbuf_size;
+ vc->vc_pos = vc->vc_origin + vc->vc_size_row * vc->vc_y + 2 * vc->vc_x;
}
-static inline void save_screen(int currcons)
+static inline void save_screen(struct vc_data *vc)
{
WARN_CONSOLE_UNLOCKED();
- if (sw->con_save_screen)
- sw->con_save_screen(vc_cons[currcons].d);
+ if (vc->vc_sw->con_save_screen)
+ vc->vc_sw->con_save_screen(vc);
}
/*
* Redrawing of screen
*/
-static void clear_buffer_attributes(int currcons)
+static void clear_buffer_attributes(struct vc_data *vc)
{
- unsigned short *p = (unsigned short *) origin;
- int count = screenbuf_size/2;
- int mask = hi_font_mask | 0xff;
+ unsigned short *p = (unsigned short *)vc->vc_origin;
+ int count = vc->vc_screenbuf_size / 2;
+ int mask = vc->vc_hi_font_mask | 0xff;
for (; count > 0; count--, p++) {
- scr_writew((scr_readw(p)&mask) | (video_erase_char&~mask), p);
+ scr_writew((scr_readw(p)&mask) | (vc->vc_video_erase_char & ~mask), p);
}
}
-void redraw_screen(int new_console, int is_switch)
+void redraw_screen(struct vc_data *vc, int is_switch)
{
- int redraw = 1;
- int currcons, old_console;
+ int redraw = 0;
WARN_CONSOLE_UNLOCKED();
- if (!vc_cons_allocated(new_console)) {
+ if (!vc) {
/* strange ... */
/* printk("redraw_screen: tty %d not allocated ??\n", new_console+1); */
return;
}
if (is_switch) {
- currcons = fg_console;
- hide_cursor(vc_cons[currcons].d);
- if (fg_console != new_console) {
- struct vc_data **display = vc_cons[new_console].d->vc_display_fg;
- old_console = (*display) ? (*display)->vc_num : fg_console;
- *display = vc_cons[new_console].d;
- fg_console = new_console;
- currcons = old_console;
- if (!IS_VISIBLE) {
- save_screen(currcons);
- set_origin(currcons);
- }
- currcons = new_console;
- if (old_console == new_console)
- redraw = 0;
+ struct vc_data *old_vc = vc_cons[fg_console].d;
+ if (old_vc == vc)
+ return;
+ if (!CON_IS_VISIBLE(vc))
+ redraw = 1;
+ *vc->vc_display_fg = vc;
+ fg_console = vc->vc_num;
+ hide_cursor(old_vc);
+ if (!CON_IS_VISIBLE(old_vc)) {
+ save_screen(old_vc);
+ set_origin(old_vc);
}
} else {
- currcons = new_console;
- hide_cursor(vc_cons[currcons].d);
+ hide_cursor(vc);
+ redraw = 1;
}
if (redraw) {
int update;
- int old_was_color = vc_cons[currcons].d->vc_can_do_color;
+ int old_was_color = vc->vc_can_do_color;
- set_origin(currcons);
- update = sw->con_switch(vc_cons[currcons].d);
- set_palette(currcons);
+ set_origin(vc);
+ update = vc->vc_sw->con_switch(vc);
+ set_palette(vc);
/*
* If console changed from mono<->color, the best we can do
* is to clear the buffer attributes. As it currently stands,
* rebuilding new attributes from the old buffer is not doable
* without overly complex code.
*/
- if (old_was_color != vc_cons[currcons].d->vc_can_do_color) {
- update_attr(currcons);
- clear_buffer_attributes(currcons);
+ if (old_was_color != vc->vc_can_do_color) {
+ update_attr(vc);
+ clear_buffer_attributes(vc);
}
- if (update && vcmode != KD_GRAPHICS)
- do_update_region(vc_cons[currcons].d, origin, screenbuf_size/2);
+ if (update && vc->vc_mode != KD_GRAPHICS)
+ do_update_region(vc, vc->vc_origin, vc->vc_screenbuf_size / 2);
}
- set_cursor(vc_cons[currcons].d);
+ set_cursor(vc);
if (is_switch) {
set_leds();
compute_shiftstate();
@@ -676,31 +659,30 @@ int vc_cons_allocated(unsigned int i)
return (i < MAX_NR_CONSOLES && vc_cons[i].d);
}
-static void visual_init(int currcons, int init)
+static void visual_init(struct vc_data *vc, int num, int init)
{
- /* ++Geert: sw->con_init determines console size */
- if (sw)
- module_put(sw->owner);
- sw = conswitchp;
+ /* ++Geert: vc->vc_sw->con_init determines console size */
+ if (vc->vc_sw)
+ module_put(vc->vc_sw->owner);
+ vc->vc_sw = conswitchp;
#ifndef VT_SINGLE_DRIVER
- if (con_driver_map[currcons])
- sw = con_driver_map[currcons];
+ if (con_driver_map[num])
+ vc->vc_sw = con_driver_map[num];
#endif
- __module_get(sw->owner);
- cons_num = currcons;
- display_fg = &master_display_fg;
- vc_cons[currcons].d->vc_uni_pagedir_loc = &vc_cons[currcons].d->vc_uni_pagedir;
- vc_cons[currcons].d->vc_uni_pagedir = 0;
- hi_font_mask = 0;
- complement_mask = 0;
- vc_cons[currcons].d->vc_can_do_color = 0;
- sw->con_init(vc_cons[currcons].d, init);
- if (!complement_mask)
- complement_mask =
- vc_cons[currcons].d->vc_can_do_color ? 0x7700 : 0x0800;
- s_complement_mask = complement_mask;
- vc_cons[currcons].d->vc_size_row = vc_cons[currcons].d->vc_cols<<1;
- screenbuf_size = vc_cons[currcons].d->vc_rows * vc_cons[currcons].d->vc_size_row;
+ __module_get(vc->vc_sw->owner);
+ vc->vc_num = num;
+ vc->vc_display_fg = &master_display_fg;
+ vc->vc_uni_pagedir_loc = &vc->vc_uni_pagedir;
+ vc->vc_uni_pagedir = 0;
+ vc->vc_hi_font_mask = 0;
+ vc->vc_complement_mask = 0;
+ vc->vc_can_do_color = 0;
+ vc->vc_sw->con_init(vc, init);
+ if (!vc->vc_complement_mask)
+ vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800;
+ vc->vc_s_complement_mask = vc->vc_complement_mask;
+ vc->vc_size_row = vc->vc_cols << 1;
+ vc->vc_screenbuf_size = vc->vc_rows * vc->vc_size_row;
}
int vc_allocate(unsigned int currcons) /* return 0 on success */
@@ -710,7 +692,7 @@ int vc_allocate(unsigned int currcons) /* return 0 on success */
if (currcons >= MAX_NR_CONSOLES)
return -ENXIO;
if (!vc_cons[currcons].d) {
- long p, q;
+ struct vc_data *vc;
/* prevent users from taking too much memory */
if (currcons >= MAX_NR_USER_CONSOLES && !capable(CAP_SYS_RESOURCE))
@@ -722,43 +704,33 @@ int vc_allocate(unsigned int currcons) /* return 0 on success */
/* although the numbers above are not valid since long ago, the
point is still up-to-date and the comment still has its value
even if only as a historical artifact. --mj, July 1998 */
- p = (long) kmalloc(structsize, GFP_KERNEL);
- if (!p)
+ vc = kmalloc(sizeof(struct vc_data), GFP_KERNEL);
+ if (!vc)
return -ENOMEM;
- memset((void *)p, 0, structsize);
- vc_cons[currcons].d = (struct vc_data *)p;
- vt_cons[currcons] = (struct vt_struct *)(p+sizeof(struct vc_data));
- vc_cons[currcons].d->vc_vt = vt_cons[currcons];
- visual_init(currcons, 1);
- if (!*vc_cons[currcons].d->vc_uni_pagedir_loc)
- con_set_default_unimap(currcons);
- q = (long)kmalloc(screenbuf_size, GFP_KERNEL);
- if (!q) {
- kfree((char *) p);
+ memset(vc, 0, sizeof(*vc));
+ vc_cons[currcons].d = vc;
+ visual_init(vc, currcons, 1);
+ if (!*vc->vc_uni_pagedir_loc)
+ con_set_default_unimap(vc);
+ vc->vc_screenbuf = kmalloc(vc->vc_screenbuf_size, GFP_KERNEL);
+ if (!vc->vc_screenbuf) {
+ kfree(vc);
vc_cons[currcons].d = NULL;
- vt_cons[currcons] = NULL;
return -ENOMEM;
}
- screenbuf = (unsigned short *) q;
- kmalloced = 1;
- vc_init(currcons, vc_cons[currcons].d->vc_rows, vc_cons[currcons].d->vc_cols, 1);
-
- if (!pm_con) {
- pm_con = pm_register(PM_SYS_DEV,
- PM_SYS_VGA,
- pm_con_request);
- }
+ vc->vc_kmalloced = 1;
+ vc_init(vc, vc->vc_rows, vc->vc_cols, 1);
}
return 0;
}
-inline int resize_screen(int currcons, int width, int height)
+static inline int resize_screen(struct vc_data *vc, int width, int height)
{
/* Resizes the resolution of the display adapater */
int err = 0;
- if (vcmode != KD_GRAPHICS && sw->con_resize)
- err = sw->con_resize(vc_cons[currcons].d, width, height);
+ if (vc->vc_mode != KD_GRAPHICS && vc->vc_sw->con_resize)
+ err = vc->vc_sw->con_resize(vc, width, height);
return err;
}
@@ -769,7 +741,7 @@ inline int resize_screen(int currcons, int width, int height)
*/
#define VC_RESIZE_MAXCOL (32767)
#define VC_RESIZE_MAXROW (32767)
-int vc_resize(int currcons, unsigned int cols, unsigned int lines)
+int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines)
{
unsigned long old_origin, new_origin, new_scr_end, rlth, rrem, err = 0;
unsigned int old_cols, old_rows, old_row_size, old_screen_size;
@@ -778,87 +750,87 @@ int vc_resize(int currcons, unsigned int cols, unsigned int lines)
WARN_CONSOLE_UNLOCKED();
- if (!vc_cons_allocated(currcons))
+ if (!vc)
return -ENXIO;
if (cols > VC_RESIZE_MAXCOL || lines > VC_RESIZE_MAXROW)
return -EINVAL;
- new_cols = (cols ? cols : vc_cons[currcons].d->vc_cols);
- new_rows = (lines ? lines : vc_cons[currcons].d->vc_rows);
+ new_cols = (cols ? cols : vc->vc_cols);
+ new_rows = (lines ? lines : vc->vc_rows);
new_row_size = new_cols << 1;
new_screen_size = new_row_size * new_rows;
- if (new_cols == vc_cons[currcons].d->vc_cols && new_rows == vc_cons[currcons].d->vc_rows)
+ if (new_cols == vc->vc_cols && new_rows == vc->vc_rows)
return 0;
newscreen = (unsigned short *) kmalloc(new_screen_size, GFP_USER);
if (!newscreen)
return -ENOMEM;
- old_rows = vc_cons[currcons].d->vc_rows;
- old_cols = vc_cons[currcons].d->vc_cols;
- old_row_size = vc_cons[currcons].d->vc_size_row;
- old_screen_size = screenbuf_size;
+ old_rows = vc->vc_rows;
+ old_cols = vc->vc_cols;
+ old_row_size = vc->vc_size_row;
+ old_screen_size = vc->vc_screenbuf_size;
- err = resize_screen(currcons, new_cols, new_rows);
+ err = resize_screen(vc, new_cols, new_rows);
if (err) {
kfree(newscreen);
return err;
}
- vc_cons[currcons].d->vc_rows = new_rows;
- vc_cons[currcons].d->vc_cols = new_cols;
- vc_cons[currcons].d->vc_size_row = new_row_size;
- screenbuf_size = new_screen_size;
+ vc->vc_rows = new_rows;
+ vc->vc_cols = new_cols;
+ vc->vc_size_row = new_row_size;
+ vc->vc_screenbuf_size = new_screen_size;
rlth = min(old_row_size, new_row_size);
rrem = new_row_size - rlth;
- old_origin = origin;
+ old_origin = vc->vc_origin;
new_origin = (long) newscreen;
new_scr_end = new_origin + new_screen_size;
if (new_rows < old_rows)
old_origin += (old_rows - new_rows) * old_row_size;
- update_attr(currcons);
+ update_attr(vc);
- while (old_origin < scr_end) {
+ while (old_origin < vc->vc_scr_end) {
scr_memcpyw((unsigned short *) new_origin, (unsigned short *) old_origin, rlth);
if (rrem)
- scr_memsetw((void *)(new_origin + rlth), video_erase_char, rrem);
+ scr_memsetw((void *)(new_origin + rlth), vc->vc_video_erase_char, rrem);
old_origin += old_row_size;
new_origin += new_row_size;
}
if (new_scr_end > new_origin)
- scr_memsetw((void *) new_origin, video_erase_char, new_scr_end - new_origin);
- if (kmalloced)
- kfree(screenbuf);
- screenbuf = newscreen;
- kmalloced = 1;
- screenbuf_size = new_screen_size;
- set_origin(currcons);
+ scr_memsetw((void *)new_origin, vc->vc_video_erase_char, new_scr_end - new_origin);
+ if (vc->vc_kmalloced)
+ kfree(vc->vc_screenbuf);
+ vc->vc_screenbuf = newscreen;
+ vc->vc_kmalloced = 1;
+ vc->vc_screenbuf_size = new_screen_size;
+ set_origin(vc);
/* do part of a reset_terminal() */
- top = 0;
- bottom = vc_cons[currcons].d->vc_rows;
- gotoxy(vc_cons[currcons].d, x, y);
- save_cur(currcons);
+ vc->vc_top = 0;
+ vc->vc_bottom = vc->vc_rows;
+ gotoxy(vc, vc->vc_x, vc->vc_y);
+ save_cur(vc);
- if (vc_cons[currcons].d->vc_tty) {
- struct winsize ws, *cws = &vc_cons[currcons].d->vc_tty->winsize;
+ if (vc->vc_tty) {
+ struct winsize ws, *cws = &vc->vc_tty->winsize;
memset(&ws, 0, sizeof(ws));
- ws.ws_row = vc_cons[currcons].d->vc_rows;
- ws.ws_col = vc_cons[currcons].d->vc_cols;
- ws.ws_ypixel = video_scan_lines;
+ ws.ws_row = vc->vc_rows;
+ ws.ws_col = vc->vc_cols;
+ ws.ws_ypixel = vc->vc_scan_lines;
if ((ws.ws_row != cws->ws_row || ws.ws_col != cws->ws_col) &&
- vc_cons[currcons].d->vc_tty->pgrp > 0)
- kill_pg(vc_cons[currcons].d->vc_tty->pgrp, SIGWINCH, 1);
+ vc->vc_tty->pgrp > 0)
+ kill_pg(vc->vc_tty->pgrp, SIGWINCH, 1);
*cws = ws;
}
- if (IS_VISIBLE)
- update_screen(currcons);
+ if (CON_IS_VISIBLE(vc))
+ update_screen(vc);
return err;
}
@@ -868,12 +840,13 @@ void vc_disallocate(unsigned int currcons)
WARN_CONSOLE_UNLOCKED();
if (vc_cons_allocated(currcons)) {
- sw->con_deinit(vc_cons[currcons].d);
- if (kmalloced)
- kfree(screenbuf);
- if (currcons >= MIN_NR_CONSOLES)
- kfree(vc_cons[currcons].d);
- vc_cons[currcons].d = NULL;
+ struct vc_data *vc = vc_cons[currcons].d;
+ vc->vc_sw->con_deinit(vc);
+ if (vc->vc_kmalloced)
+ kfree(vc->vc_screenbuf);
+ if (currcons >= MIN_NR_CONSOLES)
+ kfree(vc);
+ vc_cons[currcons].d = NULL;
}
}
@@ -881,9 +854,9 @@ void vc_disallocate(unsigned int currcons)
* VT102 emulator
*/
-#define set_kbd(x) set_vc_kbd_mode(kbd_table+currcons,x)
-#define clr_kbd(x) clr_vc_kbd_mode(kbd_table+currcons,x)
-#define is_kbd(x) vc_kbd_mode(kbd_table+currcons,x)
+#define set_kbd(vc, x) set_vc_kbd_mode(kbd_table + (vc)->vc_num, (x))
+#define clr_kbd(vc, x) clr_vc_kbd_mode(kbd_table + (vc)->vc_num, (x))
+#define is_kbd(vc, x) vc_kbd_mode(kbd_table + (vc)->vc_num, (x))
#define decarm VC_REPEAT
#define decckm VC_CKMODE
@@ -943,272 +916,268 @@ static void gotoxy(struct vc_data *vc, int new_x, int new_y)
}
/* for absolute user moves, when decom is set */
-static void gotoxay(int currcons, int new_x, int new_y)
+static void gotoxay(struct vc_data *vc, int new_x, int new_y)
{
- gotoxy(vc_cons[currcons].d, new_x, decom ? (top+new_y) : new_y);
+ gotoxy(vc, new_x, vc->vc_decom ? (vc->vc_top + new_y) : new_y);
}
-void scrollback(int lines)
+void scrollback(struct vc_data *vc, int lines)
{
- int currcons = fg_console;
-
if (!lines)
- lines = vc_cons[currcons].d->vc_rows/2;
+ lines = vc->vc_rows / 2;
scrolldelta(-lines);
}
-void scrollfront(int lines)
+void scrollfront(struct vc_data *vc, int lines)
{
- int currcons = fg_console;
-
if (!lines)
- lines = vc_cons[currcons].d->vc_rows/2;
+ lines = vc->vc_rows / 2;
scrolldelta(lines);
}
-static void lf(int currcons)
+static void lf(struct vc_data *vc)
{
/* don't scroll if above bottom of scrolling region, or
* if below scrolling region
*/
- if (y+1 == bottom)
- scrup(currcons,top,bottom,1);
- else if (y < vc_cons[currcons].d->vc_rows-1) {
- y++;
- pos += vc_cons[currcons].d->vc_size_row;
+ if (vc->vc_y + 1 == vc->vc_bottom)
+ scrup(vc, vc->vc_top, vc->vc_bottom, 1);
+ else if (vc->vc_y < vc->vc_rows - 1) {
+ vc->vc_y++;
+ vc->vc_pos += vc->vc_size_row;
}
- need_wrap = 0;
+ vc->vc_need_wrap = 0;
}
-static void ri(int currcons)
+static void ri(struct vc_data *vc)
{
/* don't scroll if below top of scrolling region, or
* if above scrolling region
*/
- if (y == top)
- scrdown(currcons,top,bottom,1);
- else if (y > 0) {
- y--;
- pos -= vc_cons[currcons].d->vc_size_row;
+ if (vc->vc_y == vc->vc_top)
+ scrdown(vc, vc->vc_top, vc->vc_bottom, 1);
+ else if (vc->vc_y > 0) {
+ vc->vc_y--;
+ vc->vc_pos -= vc->vc_size_row;
}
- need_wrap = 0;
+ vc->vc_need_wrap = 0;
}
-static inline void cr(int currcons)
+static inline void cr(struct vc_data *vc)
{
- pos -= x<<1;
- need_wrap = x = 0;
+ vc->vc_pos -= vc->vc_x << 1;
+ vc->vc_need_wrap = vc->vc_x = 0;
}
-static inline void bs(int currcons)
+static inline void bs(struct vc_data *vc)
{
- if (x) {
- pos -= 2;
- x--;
- need_wrap = 0;
+ if (vc->vc_x) {
+ vc->vc_pos -= 2;
+ vc->vc_x--;
+ vc->vc_need_wrap = 0;
}
}
-static inline void del(int currcons)
+static inline void del(struct vc_data *vc)
{
/* ignored */
}
-static void csi_J(int currcons, int vpar)
+static void csi_J(struct vc_data *vc, int vpar)
{
unsigned int count;
unsigned short * start;
switch (vpar) {
case 0: /* erase from cursor to end of display */
- count = (scr_end-pos)>>1;
- start = (unsigned short *) pos;
- if (DO_UPDATE) {
+ count = (vc->vc_scr_end - vc->vc_pos) >> 1;
+ start = (unsigned short *)vc->vc_pos;
+ if (DO_UPDATE(vc)) {
/* do in two stages */
- sw->con_clear(vc_cons[currcons].d, y, x, 1,
- vc_cons[currcons].d->vc_cols-x);
- sw->con_clear(vc_cons[currcons].d, y+1, 0,
- vc_cons[currcons].d->vc_rows-y-1,
- vc_cons[currcons].d->vc_cols);
+ vc->vc_sw->con_clear(vc, vc->vc_y, vc->vc_x, 1,
+ vc->vc_cols - vc->vc_x);
+ vc->vc_sw->con_clear(vc, vc->vc_y + 1, 0,
+ vc->vc_rows - vc->vc_y - 1,
+ vc->vc_cols);
}
break;
case 1: /* erase from start to cursor */
- count = ((pos-origin)>>1)+1;
- start = (unsigned short *) origin;
- if (DO_UPDATE) {
+ count = ((vc->vc_pos - vc->vc_origin) >> 1) + 1;
+ start = (unsigned short *)vc->vc_origin;
+ if (DO_UPDATE(vc)) {
/* do in two stages */
- sw->con_clear(vc_cons[currcons].d, 0, 0, y,
- vc_cons[currcons].d->vc_cols);
- sw->con_clear(vc_cons[currcons].d, y, 0, 1,
- x + 1);
+ vc->vc_sw->con_clear(vc, 0, 0, vc->vc_y,
+ vc->vc_cols);
+ vc->vc_sw->con_clear(vc, vc->vc_y, 0, 1,
+ vc->vc_x + 1);
}
break;
case 2: /* erase whole display */
- count = vc_cons[currcons].d->vc_cols * vc_cons[currcons].d->vc_rows;
- start = (unsigned short *) origin;
- if (DO_UPDATE)
- sw->con_clear(vc_cons[currcons].d, 0, 0,
- vc_cons[currcons].d->vc_rows,
- vc_cons[currcons].d->vc_cols);
+ count = vc->vc_cols * vc->vc_rows;
+ start = (unsigned short *)vc->vc_origin;
+ if (DO_UPDATE(vc))
+ vc->vc_sw->con_clear(vc, 0, 0,
+ vc->vc_rows,
+ vc->vc_cols);
break;
default:
return;
}
- scr_memsetw(start, video_erase_char, 2*count);
- need_wrap = 0;
+ scr_memsetw(start, vc->vc_video_erase_char, 2 * count);
+ vc->vc_need_wrap = 0;
}
-static void csi_K(int currcons, int vpar)
+static void csi_K(struct vc_data *vc, int vpar)
{
unsigned int count;
unsigned short * start;
switch (vpar) {
case 0: /* erase from cursor to end of line */
- count = vc_cons[currcons].d->vc_cols-x;
- start = (unsigned short *) pos;
- if (DO_UPDATE)
- sw->con_clear(vc_cons[currcons].d, y, x, 1,
- vc_cons[currcons].d->vc_cols-x);
+ count = vc->vc_cols - vc->vc_x;
+ start = (unsigned short *)vc->vc_pos;
+ if (DO_UPDATE(vc))
+ vc->vc_sw->con_clear(vc, vc->vc_y, vc->vc_x, 1,
+ vc->vc_cols - vc->vc_x);
break;
case 1: /* erase from start of line to cursor */
- start = (unsigned short *) (pos - (x<<1));
- count = x+1;
- if (DO_UPDATE)
- sw->con_clear(vc_cons[currcons].d, y, 0, 1,
- x + 1);
+ start = (unsigned short *)(vc->vc_pos - (vc->vc_x << 1));
+ count = vc->vc_x + 1;
+ if (DO_UPDATE(vc))
+ vc->vc_sw->con_clear(vc, vc->vc_y, 0, 1,
+ vc->vc_x + 1);
break;
case 2: /* erase whole line */
- start = (unsigned short *) (pos - (x<<1));
- count = vc_cons[currcons].d->vc_cols;
- if (DO_UPDATE)
- sw->con_clear(vc_cons[currcons].d, y, 0, 1,
- vc_cons[currcons].d->vc_cols);
+ start = (unsigned short *)(vc->vc_pos - (vc->vc_x << 1));
+ count = vc->vc_cols;
+ if (DO_UPDATE(vc))
+ vc->vc_sw->con_clear(vc, vc->vc_y, 0, 1,
+ vc->vc_cols);
break;
default:
return;
}
- scr_memsetw(start, video_erase_char, 2 * count);
- need_wrap = 0;
+ scr_memsetw(start, vc->vc_video_erase_char, 2 * count);
+ vc->vc_need_wrap = 0;
}
-static void csi_X(int currcons, int vpar) /* erase the following vpar positions */
+static void csi_X(struct vc_data *vc, int vpar) /* erase the following vpar positions */
{ /* not vt100? */
int count;
if (!vpar)
vpar++;
- count = (vpar > vc_cons[currcons].d->vc_cols-x) ? (vc_cons[currcons].d->vc_cols-x) : vpar;
+ count = (vpar > vc->vc_cols - vc->vc_x) ? (vc->vc_cols - vc->vc_x) : vpar;
- scr_memsetw((unsigned short *) pos, video_erase_char, 2 * count);
- if (DO_UPDATE)
- sw->con_clear(vc_cons[currcons].d, y, x, 1, count);
- need_wrap = 0;
+ scr_memsetw((unsigned short *)vc->vc_pos, vc->vc_video_erase_char, 2 * count);
+ if (DO_UPDATE(vc))
+ vc->vc_sw->con_clear(vc, vc->vc_y, vc->vc_x, 1, count);
+ vc->vc_need_wrap = 0;
}
-static void default_attr(int currcons)
+static void default_attr(struct vc_data *vc)
{
- intensity = 1;
- underline = 0;
- reverse = 0;
- blink = 0;
- color = def_color;
+ vc->vc_intensity = 1;
+ vc->vc_underline = 0;
+ vc->vc_reverse = 0;
+ vc->vc_blink = 0;
+ vc->vc_color = vc->vc_def_color;
}
/* console_sem is held */
-static void csi_m(int currcons)
+static void csi_m(struct vc_data *vc)
{
int i;
- for (i=0;i<=npar;i++)
- switch (par[i]) {
+ for (i = 0; i <= vc->vc_npar; i++)
+ switch (vc->vc_par[i]) {
case 0: /* all attributes off */
- default_attr(currcons);
+ default_attr(vc);
break;
case 1:
- intensity = 2;
+ vc->vc_intensity = 2;
break;
case 2:
- intensity = 0;
+ vc->vc_intensity = 0;
break;
case 4:
- underline = 1;
+ vc->vc_underline = 1;
break;
case 5:
- blink = 1;
+ vc->vc_blink = 1;
break;
case 7:
- reverse = 1;
+ vc->vc_reverse = 1;
break;
case 10: /* ANSI X3.64-1979 (SCO-ish?)
* Select primary font, don't display
* control chars if defined, don't set
* bit 8 on output.
*/
- translate = set_translate(charset == 0
- ? G0_charset
- : G1_charset,currcons);
- disp_ctrl = 0;
- toggle_meta = 0;
+ vc->vc_translate = set_translate(vc->vc_charset == 0
+ ? vc->vc_G0_charset
+ : vc->vc_G1_charset, vc);
+ vc->vc_disp_ctrl = 0;
+ vc->vc_toggle_meta = 0;
break;
case 11: /* ANSI X3.64-1979 (SCO-ish?)
* Select first alternate font, lets
* chars < 32 be displayed as ROM chars.
*/
- translate = set_translate(IBMPC_MAP,currcons);
- disp_ctrl = 1;
- toggle_meta = 0;
+ vc->vc_translate = set_translate(IBMPC_MAP, vc);
+ vc->vc_disp_ctrl = 1;
+ vc->vc_toggle_meta = 0;
break;
case 12: /* ANSI X3.64-1979 (SCO-ish?)
* Select second alternate font, toggle
* high bit before displaying as ROM char.
*/
- translate = set_translate(IBMPC_MAP,currcons);
- disp_ctrl = 1;
- toggle_meta = 1;
+ vc->vc_translate = set_translate(IBMPC_MAP, vc);
+ vc->vc_disp_ctrl = 1;
+ vc->vc_toggle_meta = 1;
break;
case 21:
case 22:
- intensity = 1;
+ vc->vc_intensity = 1;
break;
case 24:
- underline = 0;
+ vc->vc_underline = 0;
break;
case 25:
- blink = 0;
+ vc->vc_blink = 0;
break;
case 27:
- reverse = 0;
+ vc->vc_reverse = 0;
break;
case 38: /* ANSI X3.64-1979 (SCO-ish?)
* Enables underscore, white foreground
* with white underscore (Linux - use
* default foreground).
*/
- color = (def_color & 0x0f) | background;
- underline = 1;
+ vc->vc_color = (vc->vc_def_color & 0x0f) | (vc->vc_color & 0xf0);
+ vc->vc_underline = 1;
break;
case 39: /* ANSI X3.64-1979 (SCO-ish?)
* Disable underline option.
* Reset colour to default? It did this
* before...
*/
- color = (def_color & 0x0f) | background;
- underline = 0;
+ vc->vc_color = (vc->vc_def_color & 0x0f) | (vc->vc_color & 0xf0);
+ vc->vc_underline = 0;
break;
case 49:
- color = (def_color & 0xf0) | foreground;
+ vc->vc_color = (vc->vc_def_color & 0xf0) | (vc->vc_color & 0x0f);
break;
default:
- if (par[i] >= 30 && par[i] <= 37)
- color = color_table[par[i]-30]
- | background;
- else if (par[i] >= 40 && par[i] <= 47)
- color = (color_table[par[i]-40]<<4)
- | foreground;
+ if (vc->vc_par[i] >= 30 && vc->vc_par[i] <= 37)
+ vc->vc_color = color_table[vc->vc_par[i] - 30]
+ | (vc->vc_color & 0xf0);
+ else if (vc->vc_par[i] >= 40 && vc->vc_par[i] <= 47)
+ vc->vc_color = (color_table[vc->vc_par[i] - 40] << 4)
+ | (vc->vc_color & 0x0f);
break;
}
- update_attr(currcons);
+ update_attr(vc);
}
static void respond_string(const char *p, struct tty_struct *tty)
@@ -1220,11 +1189,11 @@ static void respond_string(const char *p, struct tty_struct *tty)
con_schedule_flip(tty);
}
-static void cursor_report(int currcons, struct tty_struct *tty)
+static void cursor_report(struct vc_data *vc, struct tty_struct *tty)
{
char buf[40];
- sprintf(buf, "\033[%d;%dR", y + (decom ? top+1 : 1), x+1);
+ sprintf(buf, "\033[%d;%dR", vc->vc_y + (vc->vc_decom ? vc->vc_top + 1 : 1), vc->vc_x + 1);
respond_string(buf, tty);
}
@@ -1250,130 +1219,132 @@ void mouse_report(struct tty_struct *tty, int butt, int mrx, int mry)
/* invoked via ioctl(TIOCLINUX) and through set_selection */
int mouse_reporting(void)
{
- int currcons = fg_console;
-
- return report_mouse;
+ return vc_cons[fg_console].d->vc_report_mouse;
}
/* console_sem is held */
-static void set_mode(int currcons, int on_off)
+static void set_mode(struct vc_data *vc, int on_off)
{
int i;
- for (i=0; i<=npar; i++)
- if (ques) switch(par[i]) { /* DEC private modes set/reset */
+ for (i = 0; i <= vc->vc_npar; i++)
+ if (vc->vc_ques) {
+ switch(vc->vc_par[i]) { /* DEC private modes set/reset */
case 1: /* Cursor keys send ^[Ox/^[[x */
if (on_off)
- set_kbd(decckm);
+ set_kbd(vc, decckm);
else
- clr_kbd(decckm);
+ clr_kbd(vc, decckm);
break;
case 3: /* 80/132 mode switch unimplemented */
- deccolm = on_off;
+ vc->vc_deccolm = on_off;
#if 0
- (void) vc_resize(deccolm ? 132 : 80, vc_cons[currcons].d->vc_rows);
+ vc_resize(deccolm ? 132 : 80, vc->vc_rows);
/* this alone does not suffice; some user mode
utility has to change the hardware regs */
#endif
break;
case 5: /* Inverted screen on/off */
- if (decscnm != on_off) {
- decscnm = on_off;
- invert_screen(vc_cons[currcons].d, 0, screenbuf_size, 0);
- update_attr(currcons);
+ if (vc->vc_decscnm != on_off) {
+ vc->vc_decscnm = on_off;
+ invert_screen(vc, 0, vc->vc_screenbuf_size, 0);
+ update_attr(vc);
}
break;
case 6: /* Origin relative/absolute */
- decom = on_off;
- gotoxay(currcons,0,0);
+ vc->vc_decom = on_off;
+ gotoxay(vc, 0, 0);
break;
case 7: /* Autowrap on/off */
- decawm = on_off;
+ vc->vc_decawm = on_off;
break;
case 8: /* Autorepeat on/off */
if (on_off)
- set_kbd(decarm);
+ set_kbd(vc, decarm);
else
- clr_kbd(decarm);
+ clr_kbd(vc, decarm);
break;
case 9:
- report_mouse = on_off ? 1 : 0;
+ vc->vc_report_mouse = on_off ? 1 : 0;
break;
case 25: /* Cursor on/off */
- deccm = on_off;
+ vc->vc_deccm = on_off;
break;
case 1000:
- report_mouse = on_off ? 2 : 0;
+ vc->vc_report_mouse = on_off ? 2 : 0;
break;
- } else switch(par[i]) { /* ANSI modes set/reset */
+ }
+ } else {
+ switch(vc->vc_par[i]) { /* ANSI modes set/reset */
case 3: /* Monitor (display ctrls) */
- disp_ctrl = on_off;
+ vc->vc_disp_ctrl = on_off;
break;
case 4: /* Insert Mode on/off */
- decim = on_off;
+ vc->vc_decim = on_off;
break;
case 20: /* Lf, Enter == CrLf/Lf */
if (on_off)
- set_kbd(lnm);
+ set_kbd(vc, lnm);
else
- clr_kbd(lnm);
+ clr_kbd(vc, lnm);
break;
+ }
}
}
/* console_sem is held */
-static void setterm_command(int currcons)
+static void setterm_command(struct vc_data *vc)
{
- switch(par[0]) {
+ switch(vc->vc_par[0]) {
case 1: /* set color for underline mode */
- if (vc_cons[currcons].d->vc_can_do_color &&
- par[1] < 16) {
- ulcolor = color_table[par[1]];
- if (underline)
- update_attr(currcons);
+ if (vc->vc_can_do_color &&
+ vc->vc_par[1] < 16) {
+ vc->vc_ulcolor = color_table[vc->vc_par[1]];
+ if (vc->vc_underline)
+ update_attr(vc);
}
break;
case 2: /* set color for half intensity mode */
- if (vc_cons[currcons].d->vc_can_do_color &&
- par[1] < 16) {
- halfcolor = color_table[par[1]];
- if (intensity == 0)
- update_attr(currcons);
+ if (vc->vc_can_do_color &&
+ vc->vc_par[1] < 16) {
+ vc->vc_halfcolor = color_table[vc->vc_par[1]];
+ if (vc->vc_intensity == 0)
+ update_attr(vc);
}
break;
case 8: /* store colors as defaults */
- def_color = attr;
- if (hi_font_mask == 0x100)
- def_color >>= 1;
- default_attr(currcons);
- update_attr(currcons);
+ vc->vc_def_color = vc->vc_attr;
+ if (vc->vc_hi_font_mask == 0x100)
+ vc->vc_def_color >>= 1;
+ default_attr(vc);
+ update_attr(vc);
break;
case 9: /* set blanking interval */
- blankinterval = ((par[1] < 60) ? par[1] : 60) * 60 * HZ;
+ blankinterval = ((vc->vc_par[1] < 60) ? vc->vc_par[1] : 60) * 60 * HZ;
poke_blanked_console();
break;
case 10: /* set bell frequency in Hz */
- if (npar >= 1)
- bell_pitch = par[1];
+ if (vc->vc_npar >= 1)
+ vc->vc_bell_pitch = vc->vc_par[1];
else
- bell_pitch = DEFAULT_BELL_PITCH;
+ vc->vc_bell_pitch = DEFAULT_BELL_PITCH;
break;
case 11: /* set bell duration in msec */
- if (npar >= 1)
- bell_duration = (par[1] < 2000) ?
- par[1]*HZ/1000 : 0;
+ if (vc->vc_npar >= 1)
+ vc->vc_bell_duration = (vc->vc_par[1] < 2000) ?
+ vc->vc_par[1] * HZ / 1000 : 0;
else
- bell_duration = DEFAULT_BELL_DURATION;
+ vc->vc_bell_duration = DEFAULT_BELL_DURATION;
break;
case 12: /* bring specified console to the front */
- if (par[1] >= 1 && vc_cons_allocated(par[1]-1))
- set_console(par[1] - 1);
+ if (vc->vc_par[1] >= 1 && vc_cons_allocated(vc->vc_par[1] - 1))
+ set_console(vc->vc_par[1] - 1);
break;
case 13: /* unblank the screen */
poke_blanked_console();
break;
case 14: /* set vesa powerdown interval */
- vesa_off_interval = ((par[1] < 60) ? par[1] : 60) * 60 * HZ;
+ vesa_off_interval = ((vc->vc_par[1] < 60) ? vc->vc_par[1] : 60) * 60 * HZ;
break;
case 15: /* activate the previous console */
set_console(last_console);
@@ -1382,77 +1353,77 @@ static void setterm_command(int currcons)
}
/* console_sem is held */
-static void csi_at(int currcons, unsigned int nr)
+static void csi_at(struct vc_data *vc, unsigned int nr)
{
- if (nr > vc_cons[currcons].d->vc_cols - x)
- nr = vc_cons[currcons].d->vc_cols - x;
+ if (nr > vc->vc_cols - vc->vc_x)
+ nr = vc->vc_cols - vc->vc_x;
else if (!nr)
nr = 1;
- insert_char(currcons, nr);
+ insert_char(vc, nr);
}
/* console_sem is held */
-static void csi_L(int currcons, unsigned int nr)
+static void csi_L(struct vc_data *vc, unsigned int nr)
{
- if (nr > vc_cons[currcons].d->vc_rows - y)
- nr = vc_cons[currcons].d->vc_rows - y;
+ if (nr > vc->vc_rows - vc->vc_y)
+ nr = vc->vc_rows - vc->vc_y;
else if (!nr)
nr = 1;
- scrdown(currcons,y,bottom,nr);
- need_wrap = 0;
+ scrdown(vc, vc->vc_y, vc->vc_bottom, nr);
+ vc->vc_need_wrap = 0;
}
/* console_sem is held */
-static void csi_P(int currcons, unsigned int nr)
+static void csi_P(struct vc_data *vc, unsigned int nr)
{
- if (nr > vc_cons[currcons].d->vc_cols - x)
- nr = vc_cons[currcons].d->vc_cols - x;
+ if (nr > vc->vc_cols - vc->vc_x)
+ nr = vc->vc_cols - vc->vc_x;
else if (!nr)
nr = 1;
- delete_char(currcons, nr);
+ delete_char(vc, nr);
}
/* console_sem is held */
-static void csi_M(int currcons, unsigned int nr)
+static void csi_M(struct vc_data *vc, unsigned int nr)
{
- if (nr > vc_cons[currcons].d->vc_rows - y)
- nr = vc_cons[currcons].d->vc_rows - y;
+ if (nr > vc->vc_rows - vc->vc_y)
+ nr = vc->vc_rows - vc->vc_y;
else if (!nr)
nr=1;
- scrup(currcons,y,bottom,nr);
- need_wrap = 0;
+ scrup(vc, vc->vc_y, vc->vc_bottom, nr);
+ vc->vc_need_wrap = 0;
}
/* console_sem is held (except via vc_init->reset_terminal */
-static void save_cur(int currcons)
+static void save_cur(struct vc_data *vc)
{
- saved_x = x;
- saved_y = y;
- s_intensity = intensity;
- s_underline = underline;
- s_blink = blink;
- s_reverse = reverse;
- s_charset = charset;
- s_color = color;
- saved_G0 = G0_charset;
- saved_G1 = G1_charset;
+ vc->vc_saved_x = vc->vc_x;
+ vc->vc_saved_y = vc->vc_y;
+ vc->vc_s_intensity = vc->vc_intensity;
+ vc->vc_s_underline = vc->vc_underline;
+ vc->vc_s_blink = vc->vc_blink;
+ vc->vc_s_reverse = vc->vc_reverse;
+ vc->vc_s_charset = vc->vc_charset;
+ vc->vc_s_color = vc->vc_color;
+ vc->vc_saved_G0 = vc->vc_G0_charset;
+ vc->vc_saved_G1 = vc->vc_G1_charset;
}
/* console_sem is held */
-static void restore_cur(int currcons)
-{
- gotoxy(vc_cons[currcons].d,saved_x,saved_y);
- intensity = s_intensity;
- underline = s_underline;
- blink = s_blink;
- reverse = s_reverse;
- charset = s_charset;
- color = s_color;
- G0_charset = saved_G0;
- G1_charset = saved_G1;
- translate = set_translate(charset ? G1_charset : G0_charset,currcons);
- update_attr(currcons);
- need_wrap = 0;
+static void restore_cur(struct vc_data *vc)
+{
+ gotoxy(vc, vc->vc_saved_x, vc->vc_saved_y);
+ vc->vc_intensity = vc->vc_s_intensity;
+ vc->vc_underline = vc->vc_s_underline;
+ vc->vc_blink = vc->vc_s_blink;
+ vc->vc_reverse = vc->vc_s_reverse;
+ vc->vc_charset = vc->vc_s_charset;
+ vc->vc_color = vc->vc_s_color;
+ vc->vc_G0_charset = vc->vc_saved_G0;
+ vc->vc_G1_charset = vc->vc_saved_G1;
+ vc->vc_translate = set_translate(vc->vc_charset ? vc->vc_G1_charset : vc->vc_G0_charset, vc);
+ update_attr(vc);
+ vc->vc_need_wrap = 0;
}
enum { ESnormal, ESesc, ESsquare, ESgetpars, ESgotpars, ESfunckey,
@@ -1460,64 +1431,64 @@ enum { ESnormal, ESesc, ESsquare, ESgetpars, ESgotpars, ESfunckey,
ESpalette };
/* console_sem is held (except via vc_init()) */
-static void reset_terminal(int currcons, int do_clear)
-{
- top = 0;
- bottom = vc_cons[currcons].d->vc_rows;
- vc_state = ESnormal;
- ques = 0;
- translate = set_translate(LAT1_MAP,currcons);
- G0_charset = LAT1_MAP;
- G1_charset = GRAF_MAP;
- charset = 0;
- need_wrap = 0;
- report_mouse = 0;
- utf = 0;
- utf_count = 0;
-
- disp_ctrl = 0;
- toggle_meta = 0;
-
- decscnm = 0;
- decom = 0;
- decawm = 1;
- deccm = 1;
- decim = 0;
-
- set_kbd(decarm);
- clr_kbd(decckm);
- clr_kbd(kbdapplic);
- clr_kbd(lnm);
- kbd_table[currcons].lockstate = 0;
- kbd_table[currcons].slockstate = 0;
- kbd_table[currcons].ledmode = LED_SHOW_FLAGS;
- kbd_table[currcons].ledflagstate = kbd_table[currcons].default_ledflagstate;
+static void reset_terminal(struct vc_data *vc, int do_clear)
+{
+ vc->vc_top = 0;
+ vc->vc_bottom = vc->vc_rows;
+ vc->vc_state = ESnormal;
+ vc->vc_ques = 0;
+ vc->vc_translate = set_translate(LAT1_MAP, vc);
+ vc->vc_G0_charset = LAT1_MAP;
+ vc->vc_G1_charset = GRAF_MAP;
+ vc->vc_charset = 0;
+ vc->vc_need_wrap = 0;
+ vc->vc_report_mouse = 0;
+ vc->vc_utf = 0;
+ vc->vc_utf_count = 0;
+
+ vc->vc_disp_ctrl = 0;
+ vc->vc_toggle_meta = 0;
+
+ vc->vc_decscnm = 0;
+ vc->vc_decom = 0;
+ vc->vc_decawm = 1;
+ vc->vc_deccm = 1;
+ vc->vc_decim = 0;
+
+ set_kbd(vc, decarm);
+ clr_kbd(vc, decckm);
+ clr_kbd(vc, kbdapplic);
+ clr_kbd(vc, lnm);
+ kbd_table[vc->vc_num].lockstate = 0;
+ kbd_table[vc->vc_num].slockstate = 0;
+ kbd_table[vc->vc_num].ledmode = LED_SHOW_FLAGS;
+ kbd_table[vc->vc_num].ledflagstate = kbd_table[vc->vc_num].default_ledflagstate;
/* do not do set_leds here because this causes an endless tasklet loop
when the keyboard hasn't been initialized yet */
- cursor_type = CUR_DEFAULT;
- complement_mask = s_complement_mask;
+ vc->vc_cursor_type = CUR_DEFAULT;
+ vc->vc_complement_mask = vc->vc_s_complement_mask;
- default_attr(currcons);
- update_attr(currcons);
+ default_attr(vc);
+ update_attr(vc);
- tab_stop[0] = 0x01010100;
- tab_stop[1] =
- tab_stop[2] =
- tab_stop[3] =
- tab_stop[4] = 0x01010101;
+ vc->vc_tab_stop[0] = 0x01010100;
+ vc->vc_tab_stop[1] =
+ vc->vc_tab_stop[2] =
+ vc->vc_tab_stop[3] =
+ vc->vc_tab_stop[4] = 0x01010101;
- bell_pitch = DEFAULT_BELL_PITCH;
- bell_duration = DEFAULT_BELL_DURATION;
+ vc->vc_bell_pitch = DEFAULT_BELL_PITCH;
+ vc->vc_bell_duration = DEFAULT_BELL_DURATION;
- gotoxy(vc_cons[currcons].d, 0, 0);
- save_cur(currcons);
+ gotoxy(vc, 0, 0);
+ save_cur(vc);
if (do_clear)
- csi_J(currcons,2);
+ csi_J(vc, 2);
}
/* console_sem is held */
-static void do_con_trol(struct tty_struct *tty, unsigned int currcons, int c)
+static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c)
{
/*
* Control characters can be used in the _middle_
@@ -1527,360 +1498,371 @@ static void do_con_trol(struct tty_struct *tty, unsigned int currcons, int c)
case 0:
return;
case 7:
- if (bell_duration)
- kd_mksound(bell_pitch, bell_duration);
+ if (vc->vc_bell_duration)
+ kd_mksound(vc->vc_bell_pitch, vc->vc_bell_duration);
return;
case 8:
- bs(currcons);
+ bs(vc);
return;
case 9:
- pos -= (x << 1);
- while (x < vc_cons[currcons].d->vc_cols - 1) {
- x++;
- if (tab_stop[x >> 5] & (1 << (x & 31)))
+ vc->vc_pos -= (vc->vc_x << 1);
+ while (vc->vc_x < vc->vc_cols - 1) {
+ vc->vc_x++;
+ if (vc->vc_tab_stop[vc->vc_x >> 5] & (1 << (vc->vc_x & 31)))
break;
}
- pos += (x << 1);
+ vc->vc_pos += (vc->vc_x << 1);
return;
case 10: case 11: case 12:
- lf(currcons);
- if (!is_kbd(lnm))
+ lf(vc);
+ if (!is_kbd(vc, lnm))
return;
case 13:
- cr(currcons);
+ cr(vc);
return;
case 14:
- charset = 1;
- translate = set_translate(G1_charset,currcons);
- disp_ctrl = 1;
+ vc->vc_charset = 1;
+ vc->vc_translate = set_translate(vc->vc_G1_charset, vc);
+ vc->vc_disp_ctrl = 1;
return;
case 15:
- charset = 0;
- translate = set_translate(G0_charset,currcons);
- disp_ctrl = 0;
+ vc->vc_charset = 0;
+ vc->vc_translate = set_translate(vc->vc_G0_charset, vc);
+ vc->vc_disp_ctrl = 0;
return;
case 24: case 26:
- vc_state = ESnormal;
+ vc->vc_state = ESnormal;
return;
case 27:
- vc_state = ESesc;
+ vc->vc_state = ESesc;
return;
case 127:
- del(currcons);
+ del(vc);
return;
case 128+27:
- vc_state = ESsquare;
+ vc->vc_state = ESsquare;
return;
}
- switch(vc_state) {
+ switch(vc->vc_state) {
case ESesc:
- vc_state = ESnormal;
+ vc->vc_state = ESnormal;
switch (c) {
case '[':
- vc_state = ESsquare;
+ vc->vc_state = ESsquare;
return;
case ']':
- vc_state = ESnonstd;
+ vc->vc_state = ESnonstd;
return;
case '%':
- vc_state = ESpercent;
+ vc->vc_state = ESpercent;
return;
case 'E':
- cr(currcons);
- lf(currcons);
+ cr(vc);
+ lf(vc);
return;
case 'M':
- ri(currcons);
+ ri(vc);
return;
case 'D':
- lf(currcons);
+ lf(vc);
return;
case 'H':
- tab_stop[x >> 5] |= (1 << (x & 31));
+ vc->vc_tab_stop[vc->vc_x >> 5] |= (1 << (vc->vc_x & 31));
return;
case 'Z':
respond_ID(tty);
return;
case '7':
- save_cur(currcons);
+ save_cur(vc);
return;
case '8':
- restore_cur(currcons);
+ restore_cur(vc);
return;
case '(':
- vc_state = ESsetG0;
+ vc->vc_state = ESsetG0;
return;
case ')':
- vc_state = ESsetG1;
+ vc->vc_state = ESsetG1;
return;
case '#':
- vc_state = EShash;
+ vc->vc_state = EShash;
return;
case 'c':
- reset_terminal(currcons,1);
+ reset_terminal(vc, 1);
return;
case '>': /* Numeric keypad */
- clr_kbd(kbdapplic);
+ clr_kbd(vc, kbdapplic);
return;
case '=': /* Appl. keypad */
- set_kbd(kbdapplic);
+ set_kbd(vc, kbdapplic);
return;
}
return;
case ESnonstd:
if (c=='P') { /* palette escape sequence */
- for (npar=0; npar<NPAR; npar++)
- par[npar] = 0 ;
- npar = 0 ;
- vc_state = ESpalette;
+ for (vc->vc_npar = 0; vc->vc_npar < NPAR; vc->vc_npar++)
+ vc->vc_par[vc->vc_npar] = 0;
+ vc->vc_npar = 0;
+ vc->vc_state = ESpalette;
return;
} else if (c=='R') { /* reset palette */
- reset_palette(currcons);
- vc_state = ESnormal;
+ reset_palette(vc);
+ vc->vc_state = ESnormal;
} else
- vc_state = ESnormal;
+ vc->vc_state = ESnormal;
return;
case ESpalette:
if ( (c>='0'&&c<='9') || (c>='A'&&c<='F') || (c>='a'&&c<='f') ) {
- par[npar++] = (c>'9' ? (c&0xDF)-'A'+10 : c-'0') ;
- if (npar==7) {
- int i = par[0]*3, j = 1;
- palette[i] = 16*par[j++];
- palette[i++] += par[j++];
- palette[i] = 16*par[j++];
- palette[i++] += par[j++];
- palette[i] = 16*par[j++];
- palette[i] += par[j];
- set_palette(currcons);
- vc_state = ESnormal;
+ vc->vc_par[vc->vc_npar++] = (c > '9' ? (c & 0xDF) - 'A' + 10 : c - '0');
+ if (vc->vc_npar == 7) {
+ int i = vc->vc_par[0] * 3, j = 1;
+ vc->vc_palette[i] = 16 * vc->vc_par[j++];
+ vc->vc_palette[i++] += vc->vc_par[j++];
+ vc->vc_palette[i] = 16 * vc->vc_par[j++];
+ vc->vc_palette[i++] += vc->vc_par[j++];
+ vc->vc_palette[i] = 16 * vc->vc_par[j++];
+ vc->vc_palette[i] += vc->vc_par[j];
+ set_palette(vc);
+ vc->vc_state = ESnormal;
}
} else
- vc_state = ESnormal;
+ vc->vc_state = ESnormal;
return;
case ESsquare:
- for(npar = 0 ; npar < NPAR ; npar++)
- par[npar] = 0;
- npar = 0;
- vc_state = ESgetpars;
+ for (vc->vc_npar = 0; vc->vc_npar < NPAR; vc->vc_npar++)
+ vc->vc_par[vc->vc_npar] = 0;
+ vc->vc_npar = 0;
+ vc->vc_state = ESgetpars;
if (c == '[') { /* Function key */
- vc_state=ESfunckey;
+ vc->vc_state=ESfunckey;
return;
}
- ques = (c=='?');
- if (ques)
+ vc->vc_ques = (c == '?');
+ if (vc->vc_ques)
return;
case ESgetpars:
- if (c==';' && npar<NPAR-1) {
- npar++;
+ if (c == ';' && vc->vc_npar < NPAR - 1) {
+ vc->vc_npar++;
return;
} else if (c>='0' && c<='9') {
- par[npar] *= 10;
- par[npar] += c-'0';
+ vc->vc_par[vc->vc_npar] *= 10;
+ vc->vc_par[vc->vc_npar] += c - '0';
return;
- } else vc_state=ESgotpars;
+ } else
+ vc->vc_state = ESgotpars;
case ESgotpars:
- vc_state = ESnormal;
+ vc->vc_state = ESnormal;
switch(c) {
case 'h':
- set_mode(currcons,1);
+ set_mode(vc, 1);
return;
case 'l':
- set_mode(currcons,0);
+ set_mode(vc, 0);
return;
case 'c':
- if (ques) {
- if (par[0])
- cursor_type = par[0] | (par[1]<<8) | (par[2]<<16);
+ if (vc->vc_ques) {
+ if (vc->vc_par[0])
+ vc->vc_cursor_type = vc->vc_par[0] | (vc->vc_par[1] << 8) | (vc->vc_par[2] << 16);
else
- cursor_type = CUR_DEFAULT;
+ vc->vc_cursor_type = CUR_DEFAULT;
return;
}
break;
case 'm':
- if (ques) {
+ if (vc->vc_ques) {
clear_selection();
- if (par[0])
- complement_mask = par[0]<<8 | par[1];
+ if (vc->vc_par[0])
+ vc->vc_complement_mask = vc->vc_par[0] << 8 | vc->vc_par[1];
else
- complement_mask = s_complement_mask;
+ vc->vc_complement_mask = vc->vc_s_complement_mask;
return;
}
break;
case 'n':
- if (!ques) {
- if (par[0] == 5)
+ if (!vc->vc_ques) {
+ if (vc->vc_par[0] == 5)
status_report(tty);
- else if (par[0] == 6)
- cursor_report(currcons,tty);
+ else if (vc->vc_par[0] == 6)
+ cursor_report(vc, tty);
}
return;
}
- if (ques) {
- ques = 0;
+ if (vc->vc_ques) {
+ vc->vc_ques = 0;
return;
}
switch(c) {
case 'G': case '`':
- if (par[0]) par[0]--;
- gotoxy(vc_cons[currcons].d, par[0], y);
+ if (vc->vc_par[0])
+ vc->vc_par[0]--;
+ gotoxy(vc, vc->vc_par[0], vc->vc_y);
return;
case 'A':
- if (!par[0]) par[0]++;
- gotoxy(vc_cons[currcons].d, x, y-par[0]);
+ if (!vc->vc_par[0])
+ vc->vc_par[0]++;
+ gotoxy(vc, vc->vc_x, vc->vc_y - vc->vc_par[0]);
return;
case 'B': case 'e':
- if (!par[0]) par[0]++;
- gotoxy(vc_cons[currcons].d, x, y+par[0]);
+ if (!vc->vc_par[0])
+ vc->vc_par[0]++;
+ gotoxy(vc, vc->vc_x, vc->vc_y + vc->vc_par[0]);
return;
case 'C': case 'a':
- if (!par[0]) par[0]++;
- gotoxy(vc_cons[currcons].d, x+par[0], y);
+ if (!vc->vc_par[0])
+ vc->vc_par[0]++;
+ gotoxy(vc, vc->vc_x + vc->vc_par[0], vc->vc_y);
return;
case 'D':
- if (!par[0]) par[0]++;
- gotoxy(vc_cons[currcons].d, x-par[0], y);
+ if (!vc->vc_par[0])
+ vc->vc_par[0]++;
+ gotoxy(vc, vc->vc_x - vc->vc_par[0], vc->vc_y);
return;
case 'E':
- if (!par[0]) par[0]++;
- gotoxy(vc_cons[currcons].d, 0, y+par[0]);
+ if (!vc->vc_par[0])
+ vc->vc_par[0]++;
+ gotoxy(vc, 0, vc->vc_y + vc->vc_par[0]);
return;
case 'F':
- if (!par[0]) par[0]++;
- gotoxy(vc_cons[currcons].d, 0, y-par[0]);
+ if (!vc->vc_par[0])
+ vc->vc_par[0]++;
+ gotoxy(vc, 0, vc->vc_y - vc->vc_par[0]);
return;
case 'd':
- if (par[0]) par[0]--;
- gotoxay(currcons,x,par[0]);
+ if (vc->vc_par[0])
+ vc->vc_par[0]--;
+ gotoxay(vc, vc->vc_x ,vc->vc_par[0]);
return;
case 'H': case 'f':
- if (par[0]) par[0]--;
- if (par[1]) par[1]--;
- gotoxay(currcons,par[1],par[0]);
+ if (vc->vc_par[0])
+ vc->vc_par[0]--;
+ if (vc->vc_par[1])
+ vc->vc_par[1]--;
+ gotoxay(vc, vc->vc_par[1], vc->vc_par[0]);
return;
case 'J':
- csi_J(currcons,par[0]);
+ csi_J(vc, vc->vc_par[0]);
return;
case 'K':
- csi_K(currcons,par[0]);
+ csi_K(vc, vc->vc_par[0]);
return;
case 'L':
- csi_L(currcons,par[0]);
+ csi_L(vc, vc->vc_par[0]);
return;
case 'M':
- csi_M(currcons,par[0]);
+ csi_M(vc, vc->vc_par[0]);
return;
case 'P':
- csi_P(currcons,par[0]);
+ csi_P(vc, vc->vc_par[0]);
return;
case 'c':
- if (!par[0])
+ if (!vc->vc_par[0])
respond_ID(tty);
return;
case 'g':
- if (!par[0])
- tab_stop[x >> 5] &= ~(1 << (x & 31));
- else if (par[0] == 3) {
- tab_stop[0] =
- tab_stop[1] =
- tab_stop[2] =
- tab_stop[3] =
- tab_stop[4] = 0;
+ if (!vc->vc_par[0])
+ vc->vc_tab_stop[vc->vc_x >> 5] &= ~(1 << (vc->vc_x & 31));
+ else if (vc->vc_par[0] == 3) {
+ vc->vc_tab_stop[0] =
+ vc->vc_tab_stop[1] =
+ vc->vc_tab_stop[2] =
+ vc->vc_tab_stop[3] =
+ vc->vc_tab_stop[4] = 0;
}
return;
case 'm':
- csi_m(currcons);
+ csi_m(vc);
return;
case 'q': /* DECLL - but only 3 leds */
/* map 0,1,2,3 to 0,1,2,4 */
- if (par[0] < 4)
- setledstate(kbd_table + currcons,
- (par[0] < 3) ? par[0] : 4);
+ if (vc->vc_par[0] < 4)
+ setledstate(kbd_table + vc->vc_num,
+ (vc->vc_par[0] < 3) ? vc->vc_par[0] : 4);
return;
case 'r':
- if (!par[0])
- par[0]++;
- if (!par[1])
- par[1] = vc_cons[currcons].d->vc_rows;
+ if (!vc->vc_par[0])
+ vc->vc_par[0]++;
+ if (!vc->vc_par[1])
+ vc->vc_par[1] = vc->vc_rows;
/* Minimum allowed region is 2 lines */
- if (par[0] < par[1] &&
- par[1] <= vc_cons[currcons].d->vc_rows) {
- top=par[0]-1;
- bottom=par[1];
- gotoxay(currcons,0,0);
+ if (vc->vc_par[0] < vc->vc_par[1] &&
+ vc->vc_par[1] <= vc->vc_rows) {
+ vc->vc_top = vc->vc_par[0] - 1;
+ vc->vc_bottom = vc->vc_par[1];
+ gotoxay(vc, 0, 0);
}
return;
case 's':
- save_cur(currcons);
+ save_cur(vc);
return;
case 'u':
- restore_cur(currcons);
+ restore_cur(vc);
return;
case 'X':
- csi_X(currcons, par[0]);
+ csi_X(vc, vc->vc_par[0]);
return;
case '@':
- csi_at(currcons,par[0]);
+ csi_at(vc, vc->vc_par[0]);
return;
case ']': /* setterm functions */
- setterm_command(currcons);
+ setterm_command(vc);
return;
}
return;
case ESpercent:
- vc_state = ESnormal;
+ vc->vc_state = ESnormal;
switch (c) {
case '@': /* defined in ISO 2022 */
- utf = 0;
+ vc->vc_utf = 0;
return;
case 'G': /* prelim official escape code */
case '8': /* retained for compatibility */
- utf = 1;
+ vc->vc_utf = 1;
return;
}
return;
case ESfunckey:
- vc_state = ESnormal;
+ vc->vc_state = ESnormal;
return;
case EShash:
- vc_state = ESnormal;
+ vc->vc_state = ESnormal;
if (c == '8') {
/* DEC screen alignment test. kludge :-) */
- video_erase_char =
- (video_erase_char & 0xff00) | 'E';
- csi_J(currcons, 2);
- video_erase_char =
- (video_erase_char & 0xff00) | ' ';
- do_update_region(vc_cons[currcons].d, origin, screenbuf_size/2);
+ vc->vc_video_erase_char =
+ (vc->vc_video_erase_char & 0xff00) | 'E';
+ csi_J(vc, 2);
+ vc->vc_video_erase_char =
+ (vc->vc_video_erase_char & 0xff00) | ' ';
+ do_update_region(vc, vc->vc_origin, vc->vc_screenbuf_size / 2);
}
return;
case ESsetG0:
if (c == '0')
- G0_charset = GRAF_MAP;
+ vc->vc_G0_charset = GRAF_MAP;
else if (c == 'B')
- G0_charset = LAT1_MAP;
+ vc->vc_G0_charset = LAT1_MAP;
else if (c == 'U')
- G0_charset = IBMPC_MAP;
+ vc->vc_G0_charset = IBMPC_MAP;
else if (c == 'K')
- G0_charset = USER_MAP;
- if (charset == 0)
- translate = set_translate(G0_charset,currcons);
- vc_state = ESnormal;
+ vc->vc_G0_charset = USER_MAP;
+ if (vc->vc_charset == 0)
+ vc->vc_translate = set_translate(vc->vc_G0_charset, vc);
+ vc->vc_state = ESnormal;
return;
case ESsetG1:
if (c == '0')
- G1_charset = GRAF_MAP;
+ vc->vc_G1_charset = GRAF_MAP;
else if (c == 'B')
- G1_charset = LAT1_MAP;
+ vc->vc_G1_charset = LAT1_MAP;
else if (c == 'U')
- G1_charset = IBMPC_MAP;
+ vc->vc_G1_charset = IBMPC_MAP;
else if (c == 'K')
- G1_charset = USER_MAP;
- if (charset == 1)
- translate = set_translate(G1_charset,currcons);
- vc_state = ESnormal;
+ vc->vc_G1_charset = USER_MAP;
+ if (vc->vc_charset == 1)
+ vc->vc_translate = set_translate(vc->vc_G1_charset, vc);
+ vc->vc_state = ESnormal;
return;
default:
- vc_state = ESnormal;
+ vc->vc_state = ESnormal;
}
}
@@ -1903,7 +1885,7 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co
#define FLUSH do { } while(0);
#else
#define FLUSH if (draw_x >= 0) { \
- sw->con_putcs(vc_cons[currcons].d, (u16 *)draw_from, (u16 *)draw_to-(u16 *)draw_from, y, draw_x); \
+ vc->vc_sw->con_putcs(vc, (u16 *)draw_from, (u16 *)draw_to - (u16 *)draw_from, vc->vc_y, draw_x); \
draw_x = -1; \
}
#endif
@@ -1911,7 +1893,7 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co
int c, tc, ok, n = 0, draw_x = -1;
unsigned int currcons;
unsigned long draw_from = 0, draw_to = 0;
- struct vt_struct *vt;
+ struct vc_data *vc;
u16 himask, charmask;
const unsigned char *orig_buf = NULL;
int orig_count;
@@ -1922,14 +1904,14 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co
might_sleep();
acquire_console_sem();
- vt = tty->driver_data;
- if (vt == NULL) {
+ vc = tty->driver_data;
+ if (vc == NULL) {
printk(KERN_ERR "vt: argh, driver_data is NULL !\n");
release_console_sem();
return 0;
}
- currcons = vt->vc_num;
+ currcons = vc->vc_num;
if (!vc_cons_allocated(currcons)) {
/* could this happen? */
static int error = 0;
@@ -1954,19 +1936,19 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co
acquire_console_sem();
- vt = tty->driver_data;
- if (vt == NULL) {
+ vc = tty->driver_data;
+ if (vc == NULL) {
printk(KERN_ERR "vt: argh, driver_data _became_ NULL !\n");
release_console_sem();
goto out;
}
- himask = hi_font_mask;
+ himask = vc->vc_hi_font_mask;
charmask = himask ? 0x1ff : 0xff;
/* undraw cursor first */
- if (IS_FG)
- hide_cursor(vc_cons[currcons].d);
+ if (IS_FG(vc))
+ hide_cursor(vc);
while (!tty->stopped && count) {
int orig = *buf;
@@ -1976,44 +1958,44 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co
count--;
/* Do no translation at all in control states */
- if (vc_state != ESnormal) {
+ if (vc->vc_state != ESnormal) {
tc = c;
- } else if (utf) {
+ } else if (vc->vc_utf) {
/* Combine UTF-8 into Unicode */
/* Incomplete characters silently ignored */
if(c > 0x7f) {
- if (utf_count > 0 && (c & 0xc0) == 0x80) {
- utf_char = (utf_char << 6) | (c & 0x3f);
- utf_count--;
- if (utf_count == 0)
- tc = c = utf_char;
+ if (vc->vc_utf_count > 0 && (c & 0xc0) == 0x80) {
+ vc->vc_utf_char = (vc->vc_utf_char << 6) | (c & 0x3f);
+ vc->vc_utf_count--;
+ if (vc->vc_utf_count == 0)
+ tc = c = vc->vc_utf_char;
else continue;
} else {
if ((c & 0xe0) == 0xc0) {
- utf_count = 1;
- utf_char = (c & 0x1f);
+ vc->vc_utf_count = 1;
+ vc->vc_utf_char = (c & 0x1f);
} else if ((c & 0xf0) == 0xe0) {
- utf_count = 2;
- utf_char = (c & 0x0f);
+ vc->vc_utf_count = 2;
+ vc->vc_utf_char = (c & 0x0f);
} else if ((c & 0xf8) == 0xf0) {
- utf_count = 3;
- utf_char = (c & 0x07);
+ vc->vc_utf_count = 3;
+ vc->vc_utf_char = (c & 0x07);
} else if ((c & 0xfc) == 0xf8) {
- utf_count = 4;
- utf_char = (c & 0x03);
+ vc->vc_utf_count = 4;
+ vc->vc_utf_char = (c & 0x03);
} else if ((c & 0xfe) == 0xfc) {
- utf_count = 5;
- utf_char = (c & 0x01);
+ vc->vc_utf_count = 5;
+ vc->vc_utf_char = (c & 0x01);
} else
- utf_count = 0;
+ vc->vc_utf_count = 0;
continue;
}
} else {
tc = c;
- utf_count = 0;
+ vc->vc_utf_count = 0;
}
} else { /* no utf */
- tc = translate[toggle_meta ? (c|0x80) : c];
+ tc = vc->vc_translate[vc->vc_toggle_meta ? (c | 0x80) : c];
}
/* If the original code was a control character we
@@ -2027,18 +2009,18 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co
* direct-to-font zone in UTF-8 mode.
*/
ok = tc && (c >= 32 ||
- (!utf && !(((disp_ctrl ? CTRL_ALWAYS
- : CTRL_ACTION) >> c) & 1)))
- && (c != 127 || disp_ctrl)
+ (!vc->vc_utf && !(((vc->vc_disp_ctrl ? CTRL_ALWAYS
+ : CTRL_ACTION) >> c) & 1)))
+ && (c != 127 || vc->vc_disp_ctrl)
&& (c != 128+27);
- if (vc_state == ESnormal && ok) {
+ if (vc->vc_state == ESnormal && ok) {
/* Now try to find out how to display it */
- tc = conv_uni_to_pc(vc_cons[currcons].d, tc);
+ tc = conv_uni_to_pc(vc, tc);
if ( tc == -4 ) {
/* If we got -4 (not found) then see if we have
defined a replacement character (U+FFFD) */
- tc = conv_uni_to_pc(vc_cons[currcons].d, 0xfffd);
+ tc = conv_uni_to_pc(vc, 0xfffd);
/* One reason for the -4 can be that we just
did a clear_unimap();
@@ -2052,33 +2034,33 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co
if (tc & ~charmask)
continue; /* Conversion failed */
- if (need_wrap || decim)
+ if (vc->vc_need_wrap || vc->vc_decim)
FLUSH
- if (need_wrap) {
- cr(currcons);
- lf(currcons);
+ if (vc->vc_need_wrap) {
+ cr(vc);
+ lf(vc);
}
- if (decim)
- insert_char(currcons, 1);
+ if (vc->vc_decim)
+ insert_char(vc, 1);
scr_writew(himask ?
- ((attr << 8) & ~himask) + ((tc & 0x100) ? himask : 0) + (tc & 0xff) :
- (attr << 8) + tc,
- (u16 *) pos);
- if (DO_UPDATE && draw_x < 0) {
- draw_x = x;
- draw_from = pos;
+ ((vc->vc_attr << 8) & ~himask) + ((tc & 0x100) ? himask : 0) + (tc & 0xff) :
+ (vc->vc_attr << 8) + tc,
+ (u16 *) vc->vc_pos);
+ if (DO_UPDATE(vc) && draw_x < 0) {
+ draw_x = vc->vc_x;
+ draw_from = vc->vc_pos;
}
- if (x == vc_cons[currcons].d->vc_cols - 1) {
- need_wrap = decawm;
- draw_to = pos+2;
+ if (vc->vc_x == vc->vc_cols - 1) {
+ vc->vc_need_wrap = vc->vc_decawm;
+ draw_to = vc->vc_pos + 2;
} else {
- x++;
- draw_to = (pos+=2);
+ vc->vc_x++;
+ draw_to = (vc->vc_pos += 2);
}
continue;
}
FLUSH
- do_con_trol(tty, currcons, orig);
+ do_con_trol(tty, vc, orig);
}
FLUSH
console_conditional_schedule();
@@ -2106,7 +2088,7 @@ static void console_callback(void *ignored)
if (want_console != fg_console &&
vc_cons_allocated(want_console)) {
hide_cursor(vc_cons[fg_console].d);
- change_console(want_console);
+ change_console(vc_cons[want_console].d);
/* we only changed when the console had already
been allocated - a new console is not created
in an interrupt routine */
@@ -2118,10 +2100,10 @@ static void console_callback(void *ignored)
poke_blanked_console();
}
if (scrollback_delta) {
- int currcons = fg_console;
+ struct vc_data *vc = vc_cons[fg_console].d;
clear_selection();
- if (vcmode == KD_TEXT)
- sw->con_scrolldelta(vc_cons[currcons].d, scrollback_delta);
+ if (vc->vc_mode == KD_TEXT)
+ vc->vc_sw->con_scrolldelta(vc, scrollback_delta);
scrollback_delta = 0;
}
if (blank_timer_expired) {
@@ -2148,9 +2130,9 @@ struct tty_driver *console_driver;
* The console must be locked when we get here.
*/
-void vt_console_print(struct console *co, const char *b, unsigned count)
+static void vt_console_print(struct console *co, const char *b, unsigned count)
{
- int currcons = fg_console;
+ struct vc_data *vc = vc_cons[fg_console].d;
unsigned char c;
static unsigned long printing;
const ushort *start;
@@ -2162,76 +2144,73 @@ void vt_console_print(struct console *co, const char *b, unsigned count)
return;
if (kmsg_redirect && vc_cons_allocated(kmsg_redirect - 1))
- currcons = kmsg_redirect - 1;
+ vc = vc_cons[kmsg_redirect - 1].d;
/* read `x' only after setting currcons properly (otherwise
the `x' macro will read the x of the foreground console). */
- myx = x;
+ myx = vc->vc_x;
- if (!vc_cons_allocated(currcons)) {
+ if (!vc_cons_allocated(fg_console)) {
/* impossible */
/* printk("vt_console_print: tty %d not allocated ??\n", currcons+1); */
goto quit;
}
- if (vcmode != KD_TEXT)
+ if (vc->vc_mode != KD_TEXT)
goto quit;
/* undraw cursor first */
- if (IS_FG)
- hide_cursor(vc_cons[currcons].d);
+ if (IS_FG(vc))
+ hide_cursor(vc);
- start = (ushort *)pos;
+ start = (ushort *)vc->vc_pos;
/* Contrived structure to try to emulate original need_wrap behaviour
* Problems caused when we have need_wrap set on '\n' character */
while (count--) {
c = *b++;
- if (c == 10 || c == 13 || c == 8 || need_wrap) {
+ if (c == 10 || c == 13 || c == 8 || vc->vc_need_wrap) {
if (cnt > 0) {
- if (IS_VISIBLE)
- sw->con_putcs(vc_cons[currcons].d, start, cnt, y, x);
- x += cnt;
- if (need_wrap)
- x--;
+ if (CON_IS_VISIBLE(vc))
+ vc->vc_sw->con_putcs(vc, start, cnt, vc->vc_y, vc->vc_x);
+ vc->vc_x += cnt;
+ if (vc->vc_need_wrap)
+ vc->vc_x--;
cnt = 0;
}
if (c == 8) { /* backspace */
- bs(currcons);
- start = (ushort *)pos;
- myx = x;
+ bs(vc);
+ start = (ushort *)vc->vc_pos;
+ myx = vc->vc_x;
continue;
}
if (c != 13)
- lf(currcons);
- cr(currcons);
- start = (ushort *)pos;
- myx = x;
+ lf(vc);
+ cr(vc);
+ start = (ushort *)vc->vc_pos;
+ myx = vc->vc_x;
if (c == 10 || c == 13)
continue;
}
- scr_writew((attr << 8) + c, (unsigned short *) pos);
+ scr_writew((vc->vc_attr << 8) + c, (unsigned short *)vc->vc_pos);
cnt++;
- if (myx == vc_cons[currcons].d->vc_cols - 1) {
- need_wrap = 1;
+ if (myx == vc->vc_cols - 1) {
+ vc->vc_need_wrap = 1;
continue;
}
- pos+=2;
+ vc->vc_pos += 2;
myx++;
}
if (cnt > 0) {
- if (IS_VISIBLE)
- sw->con_putcs(vc_cons[currcons].d, start, cnt, y, x);
- x += cnt;
- if (x == vc_cons[currcons].d->vc_cols) {
- x--;
- need_wrap = 1;
+ if (CON_IS_VISIBLE(vc))
+ vc->vc_sw->con_putcs(vc, start, cnt, vc->vc_y, vc->vc_x);
+ vc->vc_x += cnt;
+ if (vc->vc_x == vc->vc_cols) {
+ vc->vc_x--;
+ vc->vc_need_wrap = 1;
}
}
- set_cursor(vc_cons[currcons].d);
-
- if (!oops_in_progress)
- poke_blanked_console();
+ set_cursor(vc);
quit:
clear_bit(0, &printing);
@@ -2243,7 +2222,7 @@ static struct tty_driver *vt_console_device(struct console *c, int *index)
return console_driver;
}
-struct console vt_console_driver = {
+static struct console vt_console_driver = {
.name = "tty",
.write = vt_console_print,
.device = vt_console_device,
@@ -2333,7 +2312,7 @@ int tioclinux(struct tty_struct *tty, unsigned long arg)
if (get_user(lines, (s32 __user *)(p+4))) {
ret = -EFAULT;
} else {
- scrollfront(lines);
+ scrollfront(vc_cons[fg_console].d, lines);
ret = 0;
}
break;
@@ -2395,9 +2374,9 @@ static void con_throttle(struct tty_struct *tty)
static void con_unthrottle(struct tty_struct *tty)
{
- struct vt_struct *vt = tty->driver_data;
+ struct vc_data *vc = tty->driver_data;
- wake_up_interruptible(&vt->paste_wait);
+ wake_up_interruptible(&vc->paste_wait);
}
/*
@@ -2432,16 +2411,16 @@ static void con_start(struct tty_struct *tty)
static void con_flush_chars(struct tty_struct *tty)
{
- struct vt_struct *vt;
+ struct vc_data *vc;
if (in_interrupt()) /* from flush_to_ldisc */
return;
/* if we race with con_close(), vt may be null */
acquire_console_sem();
- vt = tty->driver_data;
- if (vt)
- set_cursor(vc_cons[vt->vc_num].d);
+ vc = tty->driver_data;
+ if (vc)
+ set_cursor(vc);
release_console_sem();
}
@@ -2457,9 +2436,9 @@ static int con_open(struct tty_struct *tty, struct file *filp)
if (tty->count == 1) {
ret = vc_allocate(currcons);
if (ret == 0) {
- vt_cons[currcons]->vc_num = currcons;
- tty->driver_data = vt_cons[currcons];
- vc_cons[currcons].d->vc_tty = tty;
+ struct vc_data *vc = vc_cons[currcons].d;
+ tty->driver_data = vc;
+ vc->vc_tty = tty;
if (!tty->winsize.ws_row && !tty->winsize.ws_col) {
tty->winsize.ws_row = vc_cons[currcons].d->vc_rows;
@@ -2486,11 +2465,10 @@ static void con_close(struct tty_struct *tty, struct file *filp)
down(&tty_sem);
acquire_console_sem();
if (tty && tty->count == 1) {
- struct vt_struct *vt;
+ struct vc_data *vc = tty->driver_data;
- vt = tty->driver_data;
- if (vt)
- vc_cons[vt->vc_num].d->vc_tty = NULL;
+ if (vc)
+ vc->vc_tty = NULL;
tty->driver_data = NULL;
release_console_sem();
vcs_remove_devfs(tty);
@@ -2505,29 +2483,29 @@ static void con_close(struct tty_struct *tty, struct file *filp)
up(&tty_sem);
}
-static void vc_init(unsigned int currcons, unsigned int rows,
- unsigned int cols, int do_clear)
+static void vc_init(struct vc_data *vc, unsigned int rows,
+ unsigned int cols, int do_clear)
{
int j, k ;
- vc_cons[currcons].d->vc_cols = cols;
- vc_cons[currcons].d->vc_rows = rows;
- vc_cons[currcons].d->vc_size_row = cols<<1;
- screenbuf_size = vc_cons[currcons].d->vc_rows * vc_cons[currcons].d->vc_size_row;
+ vc->vc_cols = cols;
+ vc->vc_rows = rows;
+ vc->vc_size_row = cols << 1;
+ vc->vc_screenbuf_size = vc->vc_rows * vc->vc_size_row;
- set_origin(currcons);
- pos = origin;
- reset_vc(currcons);
+ set_origin(vc);
+ vc->vc_pos = vc->vc_origin;
+ reset_vc(vc);
for (j=k=0; j<16; j++) {
- vc_cons[currcons].d->vc_palette[k++] = default_red[j] ;
- vc_cons[currcons].d->vc_palette[k++] = default_grn[j] ;
- vc_cons[currcons].d->vc_palette[k++] = default_blu[j] ;
+ vc->vc_palette[k++] = default_red[j] ;
+ vc->vc_palette[k++] = default_grn[j] ;
+ vc->vc_palette[k++] = default_blu[j] ;
}
- def_color = 0x07; /* white */
- ulcolor = 0x0f; /* bold white */
- halfcolor = 0x08; /* grey */
- init_waitqueue_head(&vt_cons[currcons]->paste_wait);
- reset_terminal(currcons, do_clear);
+ vc->vc_def_color = 0x07; /* white */
+ vc->vc_ulcolor = 0x0f; /* bold white */
+ vc->vc_halfcolor = 0x08; /* grey */
+ init_waitqueue_head(&vc->paste_wait);
+ reset_terminal(vc, do_clear);
}
/*
@@ -2539,6 +2517,7 @@ static void vc_init(unsigned int currcons, unsigned int rows,
static int __init con_init(void)
{
const char *display_desc = NULL;
+ struct vc_data *vc;
unsigned int currcons = 0;
acquire_console_sem();
@@ -2562,27 +2541,23 @@ static int __init con_init(void)
* kmalloc is not running yet - we use the bootmem allocator.
*/
for (currcons = 0; currcons < MIN_NR_CONSOLES; currcons++) {
- vc_cons[currcons].d = (struct vc_data *)
- alloc_bootmem(sizeof(struct vc_data));
- vt_cons[currcons] = (struct vt_struct *)
- alloc_bootmem(sizeof(struct vt_struct));
- vc_cons[currcons].d->vc_vt = vt_cons[currcons];
- visual_init(currcons, 1);
- screenbuf = (unsigned short *) alloc_bootmem(screenbuf_size);
- kmalloced = 0;
- vc_init(currcons, vc_cons[currcons].d->vc_rows, vc_cons[currcons].d->vc_cols,
- currcons || !sw->con_save_screen);
+ vc_cons[currcons].d = vc = alloc_bootmem(sizeof(struct vc_data));
+ visual_init(vc, currcons, 1);
+ vc->vc_screenbuf = (unsigned short *)alloc_bootmem(vc->vc_screenbuf_size);
+ vc->vc_kmalloced = 0;
+ vc_init(vc, vc->vc_rows, vc->vc_cols,
+ currcons || !vc->vc_sw->con_save_screen);
}
currcons = fg_console = 0;
- master_display_fg = vc_cons[currcons].d;
- set_origin(currcons);
- save_screen(currcons);
- gotoxy(vc_cons[currcons].d, x, y);
- csi_J(currcons, 0);
- update_screen(fg_console);
+ master_display_fg = vc = vc_cons[currcons].d;
+ set_origin(vc);
+ save_screen(vc);
+ gotoxy(vc, vc->vc_x, vc->vc_y);
+ csi_J(vc, 0);
+ update_screen(vc);
printk("Console: %s %s %dx%d",
- vc_cons[currcons].d->vc_can_do_color ? "colour" : "mono",
- display_desc, vc_cons[currcons].d->vc_cols, vc_cons[currcons].d->vc_rows);
+ vc->vc_can_do_color ? "colour" : "mono",
+ display_desc, vc->vc_cols, vc->vc_rows);
printable = 1;
printk("\n");
@@ -2676,37 +2651,37 @@ int take_over_console(const struct consw *csw, int first, int last, int deflt)
for (i = first; i <= last; i++) {
int old_was_color;
- int currcons = i;
+ struct vc_data *vc = vc_cons[i].d;
if (con_driver_map[i])
module_put(con_driver_map[i]->owner);
__module_get(owner);
con_driver_map[i] = csw;
- if (!vc_cons[i].d || !vc_cons[i].d->vc_sw)
+ if (!vc || !vc->vc_sw)
continue;
j = i;
- if (IS_VISIBLE)
- save_screen(i);
- old_was_color = vc_cons[i].d->vc_can_do_color;
- vc_cons[i].d->vc_sw->con_deinit(vc_cons[i].d);
- origin = (unsigned long) screenbuf;
- visible_origin = origin;
- scr_end = origin + screenbuf_size;
- pos = origin + vc_cons[currcons].d->vc_size_row*y + 2*x;
- visual_init(i, 0);
- update_attr(i);
+ if (CON_IS_VISIBLE(vc))
+ save_screen(vc);
+ old_was_color = vc->vc_can_do_color;
+ vc->vc_sw->con_deinit(vc);
+ vc->vc_origin = (unsigned long)vc->vc_screenbuf;
+ vc->vc_visible_origin = vc->vc_origin;
+ vc->vc_scr_end = vc->vc_origin + vc->vc_screenbuf_size;
+ vc->vc_pos = vc->vc_origin + vc->vc_size_row * vc->vc_y + 2 * vc->vc_x;
+ visual_init(vc, i, 0);
+ update_attr(vc);
/* If the console changed between mono <-> color, then
* the attributes in the screenbuf will be wrong. The
* following resets all attributes to something sane.
*/
- if (old_was_color != vc_cons[i].d->vc_can_do_color)
- clear_buffer_attributes(i);
+ if (old_was_color != vc->vc_can_do_color)
+ clear_buffer_attributes(vc);
- if (IS_VISIBLE)
- update_screen(i);
+ if (CON_IS_VISIBLE(vc))
+ update_screen(vc);
}
printk("Console: switching ");
if (!deflt)
@@ -2773,7 +2748,7 @@ static void vesa_powerdown(void)
void do_blank_screen(int entering_gfx)
{
- int currcons = fg_console;
+ struct vc_data *vc = vc_cons[fg_console].d;
int i;
WARN_CONSOLE_UNLOCKED();
@@ -2792,30 +2767,30 @@ void do_blank_screen(int entering_gfx)
/* entering graphics mode? */
if (entering_gfx) {
- hide_cursor(vc_cons[currcons].d);
- save_screen(currcons);
- sw->con_blank(vc_cons[currcons].d, -1, 1);
+ hide_cursor(vc);
+ save_screen(vc);
+ vc->vc_sw->con_blank(vc, -1, 1);
console_blanked = fg_console + 1;
- set_origin(currcons);
+ set_origin(vc);
return;
}
/* don't blank graphics */
- if (vcmode != KD_TEXT) {
+ if (vc->vc_mode != KD_TEXT) {
console_blanked = fg_console + 1;
return;
}
- hide_cursor(vc_cons[currcons].d);
+ hide_cursor(vc);
del_timer_sync(&console_timer);
blank_timer_expired = 0;
- save_screen(currcons);
+ save_screen(vc);
/* In case we need to reset origin, blanking hook returns 1 */
- i = sw->con_blank(vc_cons[currcons].d, 1, 0);
+ i = vc->vc_sw->con_blank(vc, 1, 0);
console_blanked = fg_console + 1;
if (i)
- set_origin(currcons);
+ set_origin(vc);
if (console_blank_hook && console_blank_hook(1))
return;
@@ -2826,7 +2801,7 @@ void do_blank_screen(int entering_gfx)
}
if (vesa_blank_mode)
- sw->con_blank(vc_cons[currcons].d, vesa_blank_mode + 1, 0);
+ vc->vc_sw->con_blank(vc, vesa_blank_mode + 1, 0);
}
EXPORT_SYMBOL(do_blank_screen);
@@ -2835,7 +2810,14 @@ EXPORT_SYMBOL(do_blank_screen);
*/
void do_unblank_screen(int leaving_gfx)
{
- int currcons;
+ struct vc_data *vc;
+
+ /* This should now always be called from a "sane" (read: can schedule)
+ * context for the sake of the low level drivers, except in the special
+ * case of oops_in_progress
+ */
+ if (!oops_in_progress)
+ might_sleep();
WARN_CONSOLE_UNLOCKED();
@@ -2847,8 +2829,8 @@ void do_unblank_screen(int leaving_gfx)
printk("unblank_screen: tty %d not allocated ??\n", fg_console+1);
return;
}
- currcons = fg_console;
- if (vcmode != KD_TEXT)
+ vc = vc_cons[fg_console].d;
+ if (vc->vc_mode != KD_TEXT)
return; /* but leave console_blanked != 0 */
if (blankinterval) {
@@ -2857,13 +2839,13 @@ void do_unblank_screen(int leaving_gfx)
}
console_blanked = 0;
- if (sw->con_blank(vc_cons[currcons].d, 0, leaving_gfx))
+ if (vc->vc_sw->con_blank(vc, 0, leaving_gfx))
/* Low-level driver cannot restore -> do it ourselves */
- update_screen(fg_console);
+ update_screen(vc);
if (console_blank_hook)
console_blank_hook(0);
- set_palette(currcons);
- set_cursor(vc_cons[fg_console].d);
+ set_palette(vc);
+ set_cursor(vc);
}
EXPORT_SYMBOL(do_unblank_screen);
@@ -2893,13 +2875,21 @@ void poke_blanked_console(void)
{
WARN_CONSOLE_UNLOCKED();
+ /* Add this so we quickly catch whoever might call us in a non
+ * safe context. Nowadays, unblank_screen() isn't to be called in
+ * atomic contexts and is allowed to schedule (with the special case
+ * of oops_in_progress, but that isn't of any concern for this
+ * function. --BenH.
+ */
+ might_sleep();
+
/* This isn't perfectly race free, but a race here would be mostly harmless,
* at worse, we'll do a spurrious blank and it's unlikely
*/
del_timer(&console_timer);
blank_timer_expired = 0;
- if (ignore_poke || !vt_cons[fg_console] || vt_cons[fg_console]->vc_mode == KD_GRAPHICS)
+ if (ignore_poke || !vc_cons[fg_console].d || vc_cons[fg_console].d->vc_mode == KD_GRAPHICS)
return;
if (console_blanked)
unblank_screen();
@@ -2913,12 +2903,12 @@ void poke_blanked_console(void)
* Palettes
*/
-void set_palette(int currcons)
+static void set_palette(struct vc_data *vc)
{
WARN_CONSOLE_UNLOCKED();
- if (vcmode != KD_GRAPHICS)
- sw->con_set_palette(vc_cons[currcons].d, color_table);
+ if (vc->vc_mode != KD_GRAPHICS)
+ vc->vc_sw->con_set_palette(vc, color_table);
}
static int set_get_cmap(unsigned char __user *arg, int set)
@@ -2945,7 +2935,7 @@ static int set_get_cmap(unsigned char __user *arg, int set)
vc_cons[i].d->vc_palette[k++] = default_grn[j];
vc_cons[i].d->vc_palette[k++] = default_blu[j];
}
- set_palette(i);
+ set_palette(vc_cons[i].d);
}
}
return 0;
@@ -2978,15 +2968,15 @@ int con_get_cmap(unsigned char __user *arg)
return rc;
}
-void reset_palette(int currcons)
+void reset_palette(struct vc_data *vc)
{
int j, k;
for (j=k=0; j<16; j++) {
- palette[k++] = default_red[j];
- palette[k++] = default_grn[j];
- palette[k++] = default_blu[j];
+ vc->vc_palette[k++] = default_red[j];
+ vc->vc_palette[k++] = default_grn[j];
+ vc->vc_palette[k++] = default_blu[j];
}
- set_palette(currcons);
+ set_palette(vc);
}
/*
@@ -3004,13 +2994,13 @@ void reset_palette(int currcons)
#define max_font_size 65536
-int con_font_get(int currcons, struct console_font_op *op)
+static int con_font_get(struct vc_data *vc, struct console_font_op *op)
{
struct console_font font;
int rc = -EINVAL;
int c;
- if (vt_cons[currcons]->vc_mode != KD_TEXT)
+ if (vc->vc_mode != KD_TEXT)
return -EINVAL;
if (op->data) {
@@ -3021,8 +3011,8 @@ int con_font_get(int currcons, struct console_font_op *op)
font.data = NULL;
acquire_console_sem();
- if (sw->con_font_get)
- rc = sw->con_font_get(vc_cons[currcons].d, &font);
+ if (vc->vc_sw->con_font_get)
+ rc = vc->vc_sw->con_font_get(vc, &font);
else
rc = -ENOSYS;
release_console_sem();
@@ -3059,13 +3049,13 @@ out:
return rc;
}
-int con_font_set(int currcons, struct console_font_op *op)
+static int con_font_set(struct vc_data *vc, struct console_font_op *op)
{
struct console_font font;
int rc = -EINVAL;
int size;
- if (vt_cons[currcons]->vc_mode != KD_TEXT)
+ if (vc->vc_mode != KD_TEXT)
return -EINVAL;
if (!op->data)
return -EINVAL;
@@ -3107,8 +3097,8 @@ int con_font_set(int currcons, struct console_font_op *op)
return -EFAULT;
}
acquire_console_sem();
- if (sw->con_font_set)
- rc = sw->con_font_set(vc_cons[currcons].d, &font, op->flags);
+ if (vc->vc_sw->con_font_set)
+ rc = vc->vc_sw->con_font_set(vc, &font, op->flags);
else
rc = -ENOSYS;
release_console_sem();
@@ -3116,14 +3106,14 @@ int con_font_set(int currcons, struct console_font_op *op)
return rc;
}
-int con_font_default(int currcons, struct console_font_op *op)
+static int con_font_default(struct vc_data *vc, struct console_font_op *op)
{
struct console_font font = {.width = op->width, .height = op->height};
char name[MAX_FONT_NAME];
char *s = name;
int rc;
- if (vt_cons[currcons]->vc_mode != KD_TEXT)
+ if (vc->vc_mode != KD_TEXT)
return -EINVAL;
if (!op->data)
@@ -3134,8 +3124,8 @@ int con_font_default(int currcons, struct console_font_op *op)
name[MAX_FONT_NAME - 1] = 0;
acquire_console_sem();
- if (sw->con_font_default)
- rc = sw->con_font_default(vc_cons[currcons].d, &font, s);
+ if (vc->vc_sw->con_font_default)
+ rc = vc->vc_sw->con_font_default(vc, &font, s);
else
rc = -ENOSYS;
release_console_sem();
@@ -3146,40 +3136,38 @@ int con_font_default(int currcons, struct console_font_op *op)
return rc;
}
-int con_font_copy(int currcons, struct console_font_op *op)
+static int con_font_copy(struct vc_data *vc, struct console_font_op *op)
{
int con = op->height;
- struct vc_data *vc;
int rc;
- if (vt_cons[currcons]->vc_mode != KD_TEXT)
+ if (vc->vc_mode != KD_TEXT)
return -EINVAL;
acquire_console_sem();
- vc = vc_cons[currcons].d;
- if (!sw->con_font_copy)
+ if (!vc->vc_sw->con_font_copy)
rc = -ENOSYS;
else if (con < 0 || !vc_cons_allocated(con))
rc = -ENOTTY;
else if (con == vc->vc_num) /* nothing to do */
rc = 0;
else
- rc = sw->con_font_copy(vc, con);
+ rc = vc->vc_sw->con_font_copy(vc, con);
release_console_sem();
return rc;
}
-int con_font_op(int currcons, struct console_font_op *op)
+int con_font_op(struct vc_data *vc, struct console_font_op *op)
{
switch (op->op) {
case KD_FONT_OP_SET:
- return con_font_set(currcons, op);
+ return con_font_set(vc, op);
case KD_FONT_OP_GET:
- return con_font_get(currcons, op);
+ return con_font_get(vc, op);
case KD_FONT_OP_SET_DEFAULT:
- return con_font_default(currcons, op);
+ return con_font_default(vc, op);
case KD_FONT_OP_COPY:
- return con_font_copy(currcons, op);
+ return con_font_copy(vc, op);
}
return -ENOSYS;
}
@@ -3233,24 +3221,6 @@ void vcs_scr_writew(struct vc_data *vc, u16 val, u16 *org)
}
}
-static int pm_con_request(struct pm_dev *dev, pm_request_t rqst, void *data)
-{
- switch (rqst)
- {
- case PM_RESUME:
- acquire_console_sem();
- unblank_screen();
- release_console_sem();
- break;
- case PM_SUSPEND:
- acquire_console_sem();
- do_blank_screen(0);
- release_console_sem();
- break;
- }
- return 0;
-}
-
/*
* Visible symbols for modules
*/
@@ -3265,7 +3235,6 @@ EXPORT_SYMBOL(vc_resize);
EXPORT_SYMBOL(fg_console);
EXPORT_SYMBOL(console_blank_hook);
EXPORT_SYMBOL(console_blanked);
-EXPORT_SYMBOL(vt_cons);
EXPORT_SYMBOL(vc_cons);
#ifndef VT_SINGLE_DRIVER
EXPORT_SYMBOL(take_over_console);
diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c
index ad3a5d3d394c2..5d386f4bea49f 100644
--- a/drivers/char/vt_ioctl.c
+++ b/drivers/char/vt_ioctl.c
@@ -33,7 +33,7 @@
#include <linux/kbd_diacr.h>
#include <linux/selection.h>
-char vt_dont_switch;
+static char vt_dont_switch;
extern struct tty_driver *console_driver;
#define VT_IS_IN_USE(i) (console_driver->ttys[i] && console_driver->ttys[i]->count)
@@ -52,17 +52,12 @@ extern struct tty_driver *console_driver;
* to the current console is done by the main ioctl code.
*/
-struct vt_struct *vt_cons[MAX_NR_CONSOLES];
-
-/* Keyboard type: Default is KB_101, but can be set by machine
- * specific code.
- */
-unsigned char keyboard_type = KB_101;
-
#ifdef CONFIG_X86
#include <linux/syscalls.h>
#endif
+static void complete_change_console(struct vc_data *vc);
+
/*
* these are the valid i/o ports we're allowed to change. they map all the
* video ports
@@ -311,7 +306,7 @@ do_fontx_ioctl(int cmd, struct consolefontdesc __user *user_cfd, int perm, struc
op->height = cfdarg.charheight;
op->charcount = cfdarg.charcount;
op->data = cfdarg.chardata;
- return con_font_op(fg_console, op);
+ return con_font_op(vc_cons[fg_console].d, op);
case GIO_FONTX: {
op->op = KD_FONT_OP_GET;
op->flags = KD_FONT_FLAG_OLD;
@@ -319,7 +314,7 @@ do_fontx_ioctl(int cmd, struct consolefontdesc __user *user_cfd, int perm, struc
op->height = cfdarg.charheight;
op->charcount = cfdarg.charcount;
op->data = cfdarg.chardata;
- i = con_font_op(fg_console, op);
+ i = con_font_op(vc_cons[fg_console].d, op);
if (i)
return i;
cfdarg.charheight = op->height;
@@ -333,27 +328,25 @@ do_fontx_ioctl(int cmd, struct consolefontdesc __user *user_cfd, int perm, struc
}
static inline int
-do_unimap_ioctl(int cmd, struct unimapdesc __user *user_ud, int perm, unsigned int console)
+do_unimap_ioctl(int cmd, struct unimapdesc __user *user_ud, int perm, struct vc_data *vc)
{
struct unimapdesc tmp;
- int i = 0;
if (copy_from_user(&tmp, user_ud, sizeof tmp))
return -EFAULT;
- if (tmp.entries) {
- i = verify_area(VERIFY_WRITE, tmp.entries,
- tmp.entry_ct*sizeof(struct unipair));
- if (i) return i;
- }
+ if (tmp.entries)
+ if (!access_ok(VERIFY_WRITE, tmp.entries,
+ tmp.entry_ct*sizeof(struct unipair)))
+ return -EFAULT;
switch (cmd) {
case PIO_UNIMAP:
if (!perm)
return -EPERM;
- return con_set_unimap(console, tmp.entry_ct, tmp.entries);
+ return con_set_unimap(vc, tmp.entry_ct, tmp.entries);
case GIO_UNIMAP:
- if (!perm && fg_console != console)
+ if (!perm && fg_console != vc->vc_num)
return -EPERM;
- return con_get_unimap(console, tmp.entry_ct, &(user_ud->entry_ct), tmp.entries);
+ return con_get_unimap(vc, tmp.entry_ct, &(user_ud->entry_ct), tmp.entries);
}
return 0;
}
@@ -365,8 +358,7 @@ do_unimap_ioctl(int cmd, struct unimapdesc __user *user_ud, int perm, unsigned i
int vt_ioctl(struct tty_struct *tty, struct file * file,
unsigned int cmd, unsigned long arg)
{
- struct vt_struct *vt = (struct vt_struct *)tty->driver_data;
- struct vc_data *vc = vc_cons[vt->vc_num].d;
+ struct vc_data *vc = (struct vc_data *)tty->driver_data;
struct console_font_op op; /* used in multiple places here */
struct kbd_struct * kbd;
unsigned int console;
@@ -374,7 +366,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
void __user *up = (void __user *)arg;
int i, perm;
- console = vt->vc_num;
+ console = vc->vc_num;
if (!vc_cons_allocated(console)) /* impossible? */
return -ENOIOCTLCMD;
@@ -419,7 +411,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
/*
* this is naive.
*/
- ucval = keyboard_type;
+ ucval = KB_101;
goto setchar;
/*
@@ -487,9 +479,9 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
default:
return -EINVAL;
}
- if (vt_cons[console]->vc_mode == (unsigned char) arg)
+ if (vc->vc_mode == (unsigned char) arg)
return 0;
- vt_cons[console]->vc_mode = (unsigned char) arg;
+ vc->vc_mode = (unsigned char) arg;
if (console != fg_console)
return 0;
/*
@@ -504,7 +496,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
return 0;
case KDGETMODE:
- ucval = vt_cons[console]->vc_mode;
+ ucval = vc->vc_mode;
goto setint;
case KDMAPDISP:
@@ -667,12 +659,12 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
if (tmp.mode != VT_AUTO && tmp.mode != VT_PROCESS)
return -EINVAL;
acquire_console_sem();
- vt_cons[console]->vt_mode = tmp;
+ vc->vt_mode = tmp;
/* the frsig is ignored, so we set it to 0 */
- vt_cons[console]->vt_mode.frsig = 0;
- vt_cons[console]->vt_pid = current->pid;
+ vc->vt_mode.frsig = 0;
+ vc->vt_pid = current->pid;
/* no switch is required -- saw@shade.msu.ru */
- vt_cons[console]->vt_newvt = -1;
+ vc->vt_newvt = -1;
release_console_sem();
return 0;
}
@@ -683,7 +675,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
int rc;
acquire_console_sem();
- memcpy(&tmp, &vt_cons[console]->vt_mode, sizeof(struct vt_mode));
+ memcpy(&tmp, &vc->vt_mode, sizeof(struct vt_mode));
release_console_sem();
rc = copy_to_user(up, &tmp, sizeof(struct vt_mode));
@@ -761,31 +753,29 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
case VT_RELDISP:
if (!perm)
return -EPERM;
- if (vt_cons[console]->vt_mode.mode != VT_PROCESS)
+ if (vc->vt_mode.mode != VT_PROCESS)
return -EINVAL;
/*
* Switching-from response
*/
- if (vt_cons[console]->vt_newvt >= 0)
- {
+ if (vc->vt_newvt >= 0) {
if (arg == 0)
/*
* Switch disallowed, so forget we were trying
* to do it.
*/
- vt_cons[console]->vt_newvt = -1;
+ vc->vt_newvt = -1;
- else
- {
+ else {
/*
* The current vt has been released, so
* complete the switch.
*/
int newvt;
acquire_console_sem();
- newvt = vt_cons[console]->vt_newvt;
- vt_cons[console]->vt_newvt = -1;
+ newvt = vc->vt_newvt;
+ vc->vt_newvt = -1;
i = vc_allocate(newvt);
if (i) {
release_console_sem();
@@ -796,7 +786,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
* make sure we are atomic with respect to
* other console switches..
*/
- complete_change_console(newvt);
+ complete_change_console(vc_cons[newvt].d);
release_console_sem();
}
}
@@ -852,7 +842,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
return -EFAULT;
for (i = 0; i < MAX_NR_CONSOLES; i++) {
acquire_console_sem();
- vc_resize(i, cc, ll);
+ vc_resize(vc_cons[i].d, cc, ll);
release_console_sem();
}
return 0;
@@ -864,7 +854,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
ushort ll,cc,vlin,clin,vcol,ccol;
if (!perm)
return -EPERM;
- if (verify_area(VERIFY_READ, vtconsize,
+ if (!access_ok(VERIFY_READ, vtconsize,
sizeof(struct vt_consize)))
return -EFAULT;
__get_user(ll, &vtconsize->v_rows);
@@ -900,7 +890,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
vc_cons[i].d->vc_scan_lines = vlin;
if (clin)
vc_cons[i].d->vc_font.height = clin;
- vc_resize(i, cc, ll);
+ vc_resize(vc_cons[i].d, cc, ll);
release_console_sem();
}
return 0;
@@ -915,7 +905,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
op.height = 0;
op.charcount = 256;
op.data = up;
- return con_font_op(fg_console, &op);
+ return con_font_op(vc_cons[fg_console].d, &op);
}
case GIO_FONT: {
@@ -925,7 +915,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
op.height = 32;
op.charcount = 256;
op.data = up;
- return con_font_op(fg_console, &op);
+ return con_font_op(vc_cons[fg_console].d, &op);
}
case PIO_CMAP:
@@ -953,9 +943,10 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
{
op.op = KD_FONT_OP_SET_DEFAULT;
op.data = NULL;
- i = con_font_op(fg_console, &op);
- if (i) return i;
- con_set_default_unimap(fg_console);
+ i = con_font_op(vc_cons[fg_console].d, &op);
+ if (i)
+ return i;
+ con_set_default_unimap(vc_cons[fg_console].d);
return 0;
}
#endif
@@ -966,7 +957,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
return -EFAULT;
if (!perm && op.op != KD_FONT_OP_GET)
return -EPERM;
- i = con_font_op(console, &op);
+ i = con_font_op(vc, &op);
if (i) return i;
if (copy_to_user(up, &op, sizeof(op)))
return -EFAULT;
@@ -995,13 +986,13 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
return -EPERM;
i = copy_from_user(&ui, up, sizeof(struct unimapinit));
if (i) return -EFAULT;
- con_clear_unimap(console, &ui);
+ con_clear_unimap(vc, &ui);
return 0;
}
case PIO_UNIMAP:
case GIO_UNIMAP:
- return do_unimap_ioctl(cmd, up, perm, console);
+ return do_unimap_ioctl(cmd, up, perm, vc);
case VT_LOCKSWITCH:
if (!capable(CAP_SYS_TTY_CONFIG))
@@ -1054,25 +1045,25 @@ int vt_waitactive(int vt)
#define vt_wake_waitactive() wake_up(&vt_activate_queue)
-void reset_vc(unsigned int new_console)
+void reset_vc(struct vc_data *vc)
{
- vt_cons[new_console]->vc_mode = KD_TEXT;
- kbd_table[new_console].kbdmode = VC_XLATE;
- vt_cons[new_console]->vt_mode.mode = VT_AUTO;
- vt_cons[new_console]->vt_mode.waitv = 0;
- vt_cons[new_console]->vt_mode.relsig = 0;
- vt_cons[new_console]->vt_mode.acqsig = 0;
- vt_cons[new_console]->vt_mode.frsig = 0;
- vt_cons[new_console]->vt_pid = -1;
- vt_cons[new_console]->vt_newvt = -1;
+ vc->vc_mode = KD_TEXT;
+ kbd_table[vc->vc_num].kbdmode = VC_XLATE;
+ vc->vt_mode.mode = VT_AUTO;
+ vc->vt_mode.waitv = 0;
+ vc->vt_mode.relsig = 0;
+ vc->vt_mode.acqsig = 0;
+ vc->vt_mode.frsig = 0;
+ vc->vt_pid = -1;
+ vc->vt_newvt = -1;
if (!in_interrupt()) /* Via keyboard.c:SAK() - akpm */
- reset_palette(new_console) ;
+ reset_palette(vc);
}
/*
* Performs the back end of a vt switch
*/
-void complete_change_console(unsigned int new_console)
+static void complete_change_console(struct vc_data *vc)
{
unsigned char old_vc_mode;
@@ -1083,8 +1074,8 @@ void complete_change_console(unsigned int new_console)
* KD_TEXT mode or vice versa, which means we need to blank or
* unblank the screen later.
*/
- old_vc_mode = vt_cons[fg_console]->vc_mode;
- switch_screen(new_console);
+ old_vc_mode = vc_cons[fg_console].d->vc_mode;
+ switch_screen(vc);
/*
* This can't appear below a successful kill_proc(). If it did,
@@ -1096,9 +1087,8 @@ void complete_change_console(unsigned int new_console)
* To account for this we duplicate this code below only if the
* controlling process is gone and we've called reset_vc.
*/
- if (old_vc_mode != vt_cons[new_console]->vc_mode)
- {
- if (vt_cons[new_console]->vc_mode == KD_TEXT)
+ if (old_vc_mode != vc->vc_mode) {
+ if (vc->vc_mode == KD_TEXT)
do_unblank_screen(1);
else
do_blank_screen(1);
@@ -1109,17 +1099,13 @@ void complete_change_console(unsigned int new_console)
* telling it that it has acquired. Also check if it has died and
* clean up (similar to logic employed in change_console())
*/
- if (vt_cons[new_console]->vt_mode.mode == VT_PROCESS)
- {
+ if (vc->vt_mode.mode == VT_PROCESS) {
/*
* Send the signal as privileged - kill_proc() will
* tell us if the process has gone or something else
* is awry
*/
- if (kill_proc(vt_cons[new_console]->vt_pid,
- vt_cons[new_console]->vt_mode.acqsig,
- 1) != 0)
- {
+ if (kill_proc(vc->vt_pid, vc->vt_mode.acqsig, 1) != 0) {
/*
* The controlling process has died, so we revert back to
* normal operation. In this case, we'll also change back
@@ -1129,11 +1115,10 @@ void complete_change_console(unsigned int new_console)
* this outside of VT_PROCESS but there is no single process
* to account for and tracking tty count may be undesirable.
*/
- reset_vc(new_console);
+ reset_vc(vc);
- if (old_vc_mode != vt_cons[new_console]->vc_mode)
- {
- if (vt_cons[new_console]->vc_mode == KD_TEXT)
+ if (old_vc_mode != vc->vc_mode) {
+ if (vc->vc_mode == KD_TEXT)
do_unblank_screen(1);
else
do_blank_screen(1);
@@ -1151,11 +1136,11 @@ void complete_change_console(unsigned int new_console)
/*
* Performs the front-end of a vt switch
*/
-void change_console(unsigned int new_console)
+void change_console(struct vc_data *new_vc)
{
- if ((new_console == fg_console) || (vt_dont_switch))
- return;
- if (!vc_cons_allocated(new_console))
+ struct vc_data *vc;
+
+ if (!new_vc || new_vc->vc_num == fg_console || vt_dont_switch)
return;
/*
@@ -1173,23 +1158,20 @@ void change_console(unsigned int new_console)
* the user waits just the right amount of time :-) and revert the
* vt to auto control.
*/
- if (vt_cons[fg_console]->vt_mode.mode == VT_PROCESS)
- {
+ vc = vc_cons[fg_console].d;
+ if (vc->vt_mode.mode == VT_PROCESS) {
/*
* Send the signal as privileged - kill_proc() will
* tell us if the process has gone or something else
* is awry
*/
- if (kill_proc(vt_cons[fg_console]->vt_pid,
- vt_cons[fg_console]->vt_mode.relsig,
- 1) == 0)
- {
+ if (kill_proc(vc->vt_pid, vc->vt_mode.relsig, 1) == 0) {
/*
* It worked. Mark the vt to switch to and
* return. The process needs to send us a
* VT_RELDISP ioctl to complete the switch.
*/
- vt_cons[fg_console]->vt_newvt = new_console;
+ vc->vt_newvt = new_vc->vc_num;
return;
}
@@ -1202,7 +1184,7 @@ void change_console(unsigned int new_console)
* this outside of VT_PROCESS but there is no single process
* to account for and tracking tty count may be undesirable.
*/
- reset_vc(fg_console);
+ reset_vc(vc);
/*
* Fall through to normal (VT_AUTO) handling of the switch...
@@ -1212,8 +1194,8 @@ void change_console(unsigned int new_console)
/*
* Ignore all switches in KD_GRAPHICS+VT_AUTO mode
*/
- if (vt_cons[fg_console]->vc_mode == KD_GRAPHICS)
+ if (vc->vc_mode == KD_GRAPHICS)
return;
- complete_change_console(new_console);
+ complete_change_console(new_vc);
}
diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig
index d117e2b33ef21..06a31da2381c4 100644
--- a/drivers/char/watchdog/Kconfig
+++ b/drivers/char/watchdog/Kconfig
@@ -268,12 +268,12 @@ config SC1200_WDT
config SCx200_WDT
tristate "National Semiconductor SCx200 Watchdog"
- depends on WATCHDOG && X86 && PCI
+ depends on WATCHDOG && SCx200 && PCI
help
Enable the built-in watchdog timer support on the National
Semiconductor SCx200 processors.
- If compiled as a module, it will be called scx200_watchdog.
+ If compiled as a module, it will be called scx200_wdt.
config 60XX_WDT
tristate "SBC-60XX Watchdog Timer"
diff --git a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile
index 41e2f94829505..1cd27efa35c17 100644
--- a/drivers/char/watchdog/Makefile
+++ b/drivers/char/watchdog/Makefile
@@ -2,11 +2,6 @@
# Makefile for the WatchDog device drivers.
#
-# Only one watchdog can succeed. We probe the hardware watchdog
-# drivers first, then the softdog driver. This means if your hardware
-# watchdog dies or is 'borrowed' for some reason the software watchdog
-# still gives you some cover.
-
obj-$(CONFIG_PCWATCHDOG) += pcwd.o
obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o
obj-$(CONFIG_ADVANTECH_WDT) += advantechwdt.o
@@ -24,7 +19,6 @@ obj-$(CONFIG_SH_WDT) += shwdt.o
obj-$(CONFIG_S3C2410_WATCHDOG) += s3c2410_wdt.o
obj-$(CONFIG_SA1100_WATCHDOG) += sa1100_wdt.o
obj-$(CONFIG_EUROTECH_WDT) += eurotechwdt.o
-obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o
obj-$(CONFIG_W83877F_WDT) += w83877f_wdt.o
obj-$(CONFIG_W83627HF_WDT) += w83627hf_wdt.o
obj-$(CONFIG_SC520_WDT) += sc520_wdt.o
@@ -39,3 +33,10 @@ obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.o
obj-$(CONFIG_IXP4XX_WATCHDOG) += ixp4xx_wdt.o
obj-$(CONFIG_IXP2000_WATCHDOG) += ixp2000_wdt.o
obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o
+
+# Only one watchdog can succeed. We probe the hardware watchdog
+# drivers first, then the softdog driver. This means if your hardware
+# watchdog dies or is 'borrowed' for some reason the software watchdog
+# still gives you some cover.
+
+obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o
diff --git a/drivers/char/watchdog/machzwd.c b/drivers/char/watchdog/machzwd.c
index a70dd81f4d1bc..9da395fa7794f 100644
--- a/drivers/char/watchdog/machzwd.c
+++ b/drivers/char/watchdog/machzwd.c
@@ -488,7 +488,7 @@ out:
}
-void __exit zf_exit(void)
+static void __exit zf_exit(void)
{
zf_timer_off();
diff --git a/drivers/char/watchdog/pcwd_pci.c b/drivers/char/watchdog/pcwd_pci.c
index 7216e4836193f..8ce0666273265 100644
--- a/drivers/char/watchdog/pcwd_pci.c
+++ b/drivers/char/watchdog/pcwd_pci.c
@@ -48,8 +48,8 @@
#include <asm/io.h>
/* Module and version information */
-#define WATCHDOG_VERSION "1.00"
-#define WATCHDOG_DATE "12 Jun 2004"
+#define WATCHDOG_VERSION "1.01"
+#define WATCHDOG_DATE "15 Mar 2005"
#define WATCHDOG_DRIVER_NAME "PCI-PC Watchdog"
#define WATCHDOG_NAME "pcwd_pci"
#define PFX WATCHDOG_NAME ": "
@@ -659,7 +659,7 @@ static int __init pcipcwd_init_module(void)
{
spin_lock_init (&pcipcwd_private.io_lock);
- return pci_module_init(&pcipcwd_driver);
+ return pci_register_driver(&pcipcwd_driver);
}
static void __exit pcipcwd_cleanup_module(void)
diff --git a/drivers/char/watchdog/pcwd_usb.c b/drivers/char/watchdog/pcwd_usb.c
index 42bce3eea236e..1127201d73b89 100644
--- a/drivers/char/watchdog/pcwd_usb.c
+++ b/drivers/char/watchdog/pcwd_usb.c
@@ -56,8 +56,8 @@
/* Module and Version Information */
-#define DRIVER_VERSION "1.00"
-#define DRIVER_DATE "12 Jun 2004"
+#define DRIVER_VERSION "1.01"
+#define DRIVER_DATE "15 Mar 2005"
#define DRIVER_AUTHOR "Wim Van Sebroeck <wim@iguana.be>"
#define DRIVER_DESC "Berkshire USB-PC Watchdog driver"
#define DRIVER_LICENSE "GPL"
@@ -227,7 +227,7 @@ static int usb_pcwd_send_command(struct usb_pcwd_private *usb_pcwd, unsigned cha
if (usb_control_msg(usb_pcwd->udev, usb_sndctrlpipe(usb_pcwd->udev, 0),
HID_REQ_SET_REPORT, HID_DT_REPORT,
0x0200, usb_pcwd->interface_number, buf, sizeof(buf),
- HZ) != sizeof(buf)) {
+ USB_COMMAND_TIMEOUT) != sizeof(buf)) {
dbg("usb_pcwd_send_command: error in usb_control_msg for cmd 0x%x 0x%x 0x%x\n", cmd, *msb, *lsb);
}
/* wait till the usb card processed the command,
diff --git a/drivers/char/watchdog/s3c2410_wdt.c b/drivers/char/watchdog/s3c2410_wdt.c
index 47480f8c7b428..1699d2c28ce5e 100644
--- a/drivers/char/watchdog/s3c2410_wdt.c
+++ b/drivers/char/watchdog/s3c2410_wdt.c
@@ -26,6 +26,10 @@
* 05-Oct-2004 BJD Added semaphore init to stop crashes on open
* Fixed tmr_count / wdt_count confusion
* Added configurable debug
+ *
+ * 11-Jan-2004 BJD Fixed divide-by-2 in timeout code
+ *
+ * 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA
*/
#include <linux/module.h>
@@ -48,8 +52,8 @@
#include <asm/arch/map.h>
#include <asm/hardware/clock.h>
-#undef S3C2410_VA_WATCHDOG
-#define S3C2410_VA_WATCHDOG (0)
+#undef S3C24XX_VA_WATCHDOG
+#define S3C24XX_VA_WATCHDOG (0)
#include <asm/arch/regs-watchdog.h>
@@ -163,11 +167,7 @@ static int s3c2410wdt_set_heartbeat(int timeout)
if (timeout < 1)
return -EINVAL;
- /* I think someone must have missed a divide-by-2 in the 2410,
- * as a divisor of 128 gives half the calculated delay...
- */
-
- freq /= 128/2;
+ freq /= 128;
count = timeout * freq;
DBG("%s: count=%d, timeout=%d, freq=%d\n",
diff --git a/drivers/char/watchdog/sa1100_wdt.c b/drivers/char/watchdog/sa1100_wdt.c
index 394ee7ac76123..34e8f7b15e30a 100644
--- a/drivers/char/watchdog/sa1100_wdt.c
+++ b/drivers/char/watchdog/sa1100_wdt.c
@@ -35,7 +35,7 @@
#include <asm/bitops.h>
#include <asm/uaccess.h>
-#define OSCR_FREQ 3686400
+#define OSCR_FREQ CLOCK_TICK_RATE
#define SA1100_CLOSE_MAGIC (0x5afc4453)
static unsigned long sa1100wdt_users;
diff --git a/drivers/char/watchdog/sc1200wdt.c b/drivers/char/watchdog/sc1200wdt.c
index d17d485fb7c60..24401e84729e7 100644
--- a/drivers/char/watchdog/sc1200wdt.c
+++ b/drivers/char/watchdog/sc1200wdt.c
@@ -74,9 +74,9 @@ static char banner[] __initdata = KERN_INFO PFX SC1200_MODULE_VER;
static int timeout = 1;
static int io = -1;
static int io_len = 2; /* for non plug and play */
-struct semaphore open_sem;
+static struct semaphore open_sem;
static char expect_close;
-spinlock_t sc1200wdt_lock; /* io port access serialisation */
+static spinlock_t sc1200wdt_lock; /* io port access serialisation */
#if defined CONFIG_PNP
static int isapnp = 1;
@@ -335,7 +335,7 @@ static int __init sc1200wdt_probe(void)
#if defined CONFIG_PNP
-struct pnp_device_id scl200wdt_pnp_devices[] = {
+static struct pnp_device_id scl200wdt_pnp_devices[] = {
/* National Semiconductor PC87307/PC97307 watchdog component */
{.id = "NSC0800", .driver_data = 0},
{.id = ""},
diff --git a/drivers/char/watchdog/scx200_wdt.c b/drivers/char/watchdog/scx200_wdt.c
index 0c47a43068e6a..b569670e4ed53 100644
--- a/drivers/char/watchdog/scx200_wdt.c
+++ b/drivers/char/watchdog/scx200_wdt.c
@@ -4,7 +4,7 @@
Copyright (c) 2001,2002 Christer Weinigel <wingel@nano-system.com>
- Som code taken from:
+ Some code taken from:
National Semiconductor PC87307/PC97307 (ala SC1200) WDT driver
(c) Copyright 2002 Zwane Mwaikambo <zwane@commfireservices.com>
@@ -64,7 +64,7 @@ static char expect_close;
static void scx200_wdt_ping(void)
{
- outw(wdto_restart, SCx200_CB_BASE + SCx200_WDT_WDTO);
+ outw(wdto_restart, scx200_cb_base + SCx200_WDT_WDTO);
}
static void scx200_wdt_update_margin(void)
@@ -78,9 +78,9 @@ static void scx200_wdt_enable(void)
printk(KERN_DEBUG NAME ": enabling watchdog timer, wdto_restart = %d\n",
wdto_restart);
- outw(0, SCx200_CB_BASE + SCx200_WDT_WDTO);
- outb(SCx200_WDT_WDSTS_WDOVF, SCx200_CB_BASE + SCx200_WDT_WDSTS);
- outw(W_ENABLE, SCx200_CB_BASE + SCx200_WDT_WDCNFG);
+ outw(0, scx200_cb_base + SCx200_WDT_WDTO);
+ outb(SCx200_WDT_WDSTS_WDOVF, scx200_cb_base + SCx200_WDT_WDSTS);
+ outw(W_ENABLE, scx200_cb_base + SCx200_WDT_WDCNFG);
scx200_wdt_ping();
}
@@ -89,9 +89,9 @@ static void scx200_wdt_disable(void)
{
printk(KERN_DEBUG NAME ": disabling watchdog timer\n");
- outw(0, SCx200_CB_BASE + SCx200_WDT_WDTO);
- outb(SCx200_WDT_WDSTS_WDOVF, SCx200_CB_BASE + SCx200_WDT_WDSTS);
- outw(W_DISABLE, SCx200_CB_BASE + SCx200_WDT_WDCNFG);
+ outw(0, scx200_cb_base + SCx200_WDT_WDTO);
+ outb(SCx200_WDT_WDSTS_WDOVF, scx200_cb_base + SCx200_WDT_WDSTS);
+ outw(W_DISABLE, scx200_cb_base + SCx200_WDT_WDCNFG);
}
static int scx200_wdt_open(struct inode *inode, struct file *file)
@@ -217,28 +217,14 @@ static struct miscdevice scx200_wdt_miscdev = {
static int __init scx200_wdt_init(void)
{
int r;
- static struct pci_device_id ns_sc[] = {
- { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SCx200_BRIDGE) },
- { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SC1100_BRIDGE) },
- { },
- };
printk(KERN_DEBUG NAME ": NatSemi SCx200 Watchdog Driver\n");
- /*
- * First check that this really is a NatSemi SCx200 CPU or a Geode
- * SC1100 processor
- */
- if (!pci_dev_present(ns_sc))
- return -ENODEV;
-
- /* More sanity checks, verify that the configuration block is there */
- if (!scx200_cb_probe(SCx200_CB_BASE)) {
- printk(KERN_WARNING NAME ": no configuration block found\n");
+ /* check that we have found the configuration block */
+ if (!scx200_cb_present())
return -ENODEV;
- }
- if (!request_region(SCx200_CB_BASE + SCx200_WDT_OFFSET,
+ if (!request_region(scx200_cb_base + SCx200_WDT_OFFSET,
SCx200_WDT_SIZE,
"NatSemi SCx200 Watchdog")) {
printk(KERN_WARNING NAME ": watchdog I/O region busy\n");
@@ -252,7 +238,7 @@ static int __init scx200_wdt_init(void)
r = misc_register(&scx200_wdt_miscdev);
if (r) {
- release_region(SCx200_CB_BASE + SCx200_WDT_OFFSET,
+ release_region(scx200_cb_base + SCx200_WDT_OFFSET,
SCx200_WDT_SIZE);
return r;
}
@@ -261,7 +247,7 @@ static int __init scx200_wdt_init(void)
if (r) {
printk(KERN_ERR NAME ": unable to register reboot notifier");
misc_deregister(&scx200_wdt_miscdev);
- release_region(SCx200_CB_BASE + SCx200_WDT_OFFSET,
+ release_region(scx200_cb_base + SCx200_WDT_OFFSET,
SCx200_WDT_SIZE);
return r;
}
@@ -273,7 +259,7 @@ static void __exit scx200_wdt_cleanup(void)
{
unregister_reboot_notifier(&scx200_wdt_notifier);
misc_deregister(&scx200_wdt_miscdev);
- release_region(SCx200_CB_BASE + SCx200_WDT_OFFSET,
+ release_region(scx200_cb_base + SCx200_WDT_OFFSET,
SCx200_WDT_SIZE);
}
diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig
index ffe3d0439d868..95882bb1950e3 100644
--- a/drivers/cpufreq/Kconfig
+++ b/drivers/cpufreq/Kconfig
@@ -13,9 +13,13 @@ config CPU_FREQ
If in doubt, say N.
+if CPU_FREQ
+
+config CPU_FREQ_TABLE
+ def_tristate m
+
config CPU_FREQ_DEBUG
bool "Enable CPUfreq debugging"
- depends on CPU_FREQ
help
Say Y here to enable CPUfreq subsystem (including drivers)
debugging. You will need to activate it via the kernel
@@ -29,7 +33,7 @@ config CPU_FREQ_DEBUG
config CPU_FREQ_STAT
tristate "CPU frequency translation statistics"
- depends on CPU_FREQ && CPU_FREQ_TABLE
+ select CPU_FREQ_TABLE
default y
help
This driver exports CPU frequency statistics information through sysfs
@@ -37,17 +41,15 @@ config CPU_FREQ_STAT
config CPU_FREQ_STAT_DETAILS
bool "CPU frequency translation statistics details"
- depends on CPU_FREQ && CPU_FREQ_STAT
- default n
+ depends on CPU_FREQ_STAT
help
This will show detail CPU frequency translation table in sysfs file
system
choice
prompt "Default CPUFreq governor"
- depends on CPU_FREQ
- default CPU_FREQ_DEFAULT_GOV_PERFORMANCE if !CPU_FREQ_SA1100 && !CPU_FREQ_SA1110
default CPU_FREQ_DEFAULT_GOV_USERSPACE if CPU_FREQ_SA1100 || CPU_FREQ_SA1110
+ default CPU_FREQ_DEFAULT_GOV_PERFORMANCE
help
This option sets which CPUFreq governor shall be loaded at
startup. If in doubt, select 'performance'.
@@ -73,7 +75,6 @@ endchoice
config CPU_FREQ_GOV_PERFORMANCE
tristate "'performance' governor"
- depends on CPU_FREQ
help
This cpufreq governor sets the frequency statically to the
highest available CPU frequency.
@@ -82,7 +83,6 @@ config CPU_FREQ_GOV_PERFORMANCE
config CPU_FREQ_GOV_POWERSAVE
tristate "'powersave' governor"
- depends on CPU_FREQ
help
This cpufreq governor sets the frequency statically to the
lowest available CPU frequency.
@@ -91,7 +91,6 @@ config CPU_FREQ_GOV_POWERSAVE
config CPU_FREQ_GOV_USERSPACE
tristate "'userspace' governor for userspace frequency scaling"
- depends on CPU_FREQ
help
Enable this cpufreq governor when you either want to set the
CPU frequency manually or when an userspace program shall
@@ -104,7 +103,6 @@ config CPU_FREQ_GOV_USERSPACE
config CPU_FREQ_GOV_ONDEMAND
tristate "'ondemand' cpufreq policy governor"
- depends on CPU_FREQ
help
'ondemand' - This driver adds a dynamic cpufreq policy governor.
The governor does a periodic polling and
@@ -116,3 +114,5 @@ config CPU_FREQ_GOV_ONDEMAND
For details, take a look at linux/Documentation/cpu-freq.
If in doubt, say N.
+
+endif # CPU_FREQ
diff --git a/drivers/cpufreq/proc_intf.c b/drivers/cpufreq/proc_intf.c
deleted file mode 100644
index e69de29bb2d1d..0000000000000
--- a/drivers/cpufreq/proc_intf.c
+++ /dev/null
diff --git a/drivers/eisa/pci_eisa.c b/drivers/eisa/pci_eisa.c
index 043c73ad5d65d..9e913629ef39a 100644
--- a/drivers/eisa/pci_eisa.c
+++ b/drivers/eisa/pci_eisa.c
@@ -59,7 +59,8 @@ static struct pci_driver pci_eisa_driver = {
static int __init pci_eisa_init_module (void)
{
- return pci_module_init (&pci_eisa_driver);
+ return pci_register_driver (&pci_eisa_driver);
}
device_initcall(pci_eisa_init_module);
+MODULE_DEVICE_TABLE(pci, pci_eisa_pci_tbl);
diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
index 9dc51ffef7016..0287ff65963be 100644
--- a/drivers/firmware/efivars.c
+++ b/drivers/firmware/efivars.c
@@ -665,14 +665,22 @@ efivars_init(void)
{
efi_status_t status = EFI_NOT_FOUND;
efi_guid_t vendor_guid;
- efi_char16_t *variable_name = kmalloc(1024, GFP_KERNEL);
+ efi_char16_t *variable_name;
struct subsys_attribute *attr;
unsigned long variable_name_size = 1024;
- int i, rc = 0, error = 0;
+ int i, error = 0;
if (!efi_enabled)
return -ENODEV;
+ variable_name = kmalloc(variable_name_size, GFP_KERNEL);
+ if (!variable_name) {
+ printk(KERN_ERR "efivars: Memory allocation failed.\n");
+ return -ENOMEM;
+ }
+
+ memset(variable_name, 0, variable_name_size);
+
printk(KERN_INFO "EFI Variables Facility v%s %s\n", EFIVARS_VERSION,
EFIVARS_DATE);
@@ -680,21 +688,27 @@ efivars_init(void)
* For now we'll register the efi subsys within this driver
*/
- rc = firmware_register(&efi_subsys);
+ error = firmware_register(&efi_subsys);
- if (rc)
- return rc;
+ if (error) {
+ printk(KERN_ERR "efivars: Firmware registration failed with error %d.\n", error);
+ goto out_free;
+ }
kset_set_kset_s(&vars_subsys, efi_subsys);
- subsystem_register(&vars_subsys);
+
+ error = subsystem_register(&vars_subsys);
+
+ if (error) {
+ printk(KERN_ERR "efivars: Subsystem registration failed with error %d.\n", error);
+ goto out_firmware_unregister;
+ }
/*
* Per EFI spec, the maximum storage allocated for both
* the variable name and variable data is 1024 bytes.
*/
- memset(variable_name, 0, 1024);
-
do {
variable_name_size = 1024;
@@ -734,8 +748,20 @@ efivars_init(void)
error = subsys_create_file(&efi_subsys, attr);
}
+ if (error)
+ printk(KERN_ERR "efivars: Sysfs attribute export failed with error %d.\n", error);
+ else
+ goto out_free;
+
+ subsystem_unregister(&vars_subsys);
+
+out_firmware_unregister:
+ firmware_unregister(&efi_subsys);
+
+out_free:
kfree(variable_name);
- return 0;
+
+ return error;
}
static void __exit
diff --git a/drivers/i2c/algos/i2c-algo-ite.c b/drivers/i2c/algos/i2c-algo-ite.c
index 1b2c67c7fd1b9..ffd87404b0a0e 100644
--- a/drivers/i2c/algos/i2c-algo-ite.c
+++ b/drivers/i2c/algos/i2c-algo-ite.c
@@ -490,7 +490,7 @@ static int iic_readbytes(struct i2c_adapter *i2c_adap, char *buf, int count,
* condition.
*/
#if 0
-static int iic_combined_transaction(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num)
+static int iic_combined_transaction(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
{
int i;
struct i2c_msg *pmsg;
@@ -600,7 +600,7 @@ static inline int iic_doAddress(struct i2c_algo_iic_data *adap,
* verify that the bus is not busy or in some unknown state.
*/
static int iic_xfer(struct i2c_adapter *i2c_adap,
- struct i2c_msg msgs[],
+ struct i2c_msg *msgs,
int num)
{
struct i2c_algo_iic_data *adap = i2c_adap->algo_data;
diff --git a/drivers/i2c/algos/i2c-algo-pca.c b/drivers/i2c/algos/i2c-algo-pca.c
index a8724ac9282d7..c3d912cbbbc33 100644
--- a/drivers/i2c/algos/i2c-algo-pca.c
+++ b/drivers/i2c/algos/i2c-algo-pca.c
@@ -178,7 +178,7 @@ static void pca_reset(struct i2c_algo_pca_data *adap)
}
static int pca_xfer(struct i2c_adapter *i2c_adap,
- struct i2c_msg msgs[],
+ struct i2c_msg *msgs,
int num)
{
struct i2c_algo_pca_data *adap = i2c_adap->algo_data;
@@ -186,6 +186,7 @@ static int pca_xfer(struct i2c_adapter *i2c_adap,
int curmsg;
int numbytes = 0;
int state;
+ int ret;
state = pca_status(adap);
if ( state != 0xF8 ) {
@@ -218,6 +219,7 @@ static int pca_xfer(struct i2c_adapter *i2c_adap,
}
curmsg = 0;
+ ret = -EREMOTEIO;
while (curmsg < num) {
state = pca_status(adap);
@@ -251,7 +253,7 @@ static int pca_xfer(struct i2c_adapter *i2c_adap,
case 0x20: /* SLA+W has been transmitted; NOT ACK has been received */
DEB2("NOT ACK received after SLA+W\n");
pca_stop(adap);
- return -EREMOTEIO;
+ goto out;
case 0x40: /* SLA+R has been transmitted; ACK has been received */
pca_rx_ack(adap, msg->len > 1);
@@ -263,7 +265,7 @@ static int pca_xfer(struct i2c_adapter *i2c_adap,
numbytes++;
pca_rx_ack(adap, numbytes < msg->len - 1);
break;
- }
+ }
curmsg++; numbytes = 0;
if (curmsg == num)
pca_stop(adap);
@@ -274,15 +276,15 @@ static int pca_xfer(struct i2c_adapter *i2c_adap,
case 0x48: /* SLA+R has been transmitted; NOT ACK has been received */
DEB2("NOT ACK received after SLA+R\n");
pca_stop(adap);
- return -EREMOTEIO;
+ goto out;
case 0x30: /* Data byte in I2CDAT has been transmitted; NOT ACK has been received */
DEB2("NOT ACK received after data byte\n");
- return -EREMOTEIO;
+ goto out;
case 0x38: /* Arbitration lost during SLA+W, SLA+R or data bytes */
DEB2("Arbitration lost\n");
- return -EREMOTEIO;
+ goto out;
case 0x58: /* Data byte has been received; NOT ACK has been returned */
if ( numbytes == msg->len - 1 ) {
@@ -297,21 +299,21 @@ static int pca_xfer(struct i2c_adapter *i2c_adap,
"Not final byte. numbytes %d. len %d\n",
numbytes, msg->len);
pca_stop(adap);
- return -EREMOTEIO;
+ goto out;
}
break;
case 0x70: /* Bus error - SDA stuck low */
DEB2("BUS ERROR - SDA Stuck low\n");
pca_reset(adap);
- return -EREMOTEIO;
+ goto out;
case 0x90: /* Bus error - SCL stuck low */
DEB2("BUS ERROR - SCL Stuck low\n");
pca_reset(adap);
- return -EREMOTEIO;
+ goto out;
case 0x00: /* Bus error during master or slave mode due to illegal START or STOP condition */
DEB2("BUS ERROR - Illegal START or STOP\n");
pca_reset(adap);
- return -EREMOTEIO;
+ goto out;
default:
printk(KERN_ERR DRIVER ": unhandled SIO state 0x%02x\n", state);
break;
@@ -319,11 +321,13 @@ static int pca_xfer(struct i2c_adapter *i2c_adap,
}
- DEB1(KERN_CRIT "}}} transfered %d messages. "
+ ret = curmsg;
+ out:
+ DEB1(KERN_CRIT "}}} transfered %d/%d messages. "
"status is %#04x. control is %#04x\n",
- num, pca_status(adap),
+ curmsg, num, pca_status(adap),
pca_get_con(adap));
- return curmsg;
+ return ret;
}
static u32 pca_func(struct i2c_adapter *adap)
diff --git a/drivers/i2c/algos/i2c-algo-pcf.c b/drivers/i2c/algos/i2c-algo-pcf.c
index fbbe1d2bdcc42..66e681cb33d1e 100644
--- a/drivers/i2c/algos/i2c-algo-pcf.c
+++ b/drivers/i2c/algos/i2c-algo-pcf.c
@@ -332,7 +332,7 @@ static inline int pcf_doAddress(struct i2c_algo_pcf_data *adap,
}
static int pcf_xfer(struct i2c_adapter *i2c_adap,
- struct i2c_msg msgs[],
+ struct i2c_msg *msgs,
int num)
{
struct i2c_algo_pcf_data *adap = i2c_adap->algo_data;
diff --git a/drivers/i2c/algos/i2c-algo-sgi.c b/drivers/i2c/algos/i2c-algo-sgi.c
index b4e0a065b78b2..422721b241e5a 100644
--- a/drivers/i2c/algos/i2c-algo-sgi.c
+++ b/drivers/i2c/algos/i2c-algo-sgi.c
@@ -131,7 +131,7 @@ static int i2c_write(struct i2c_algo_sgi_data *adap, unsigned char *buf,
return 0;
}
-static int sgi_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[],
+static int sgi_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs,
int num)
{
struct i2c_algo_sgi_data *adap = i2c_adap->algo_data;
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 3d06bf980a3f9..34ff2ecad216f 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -287,7 +287,7 @@ config I2C_PARPORT_LIGHT
config I2C_PIIX4
tristate "Intel PIIX4"
- depends on I2C && PCI && EXPERIMENTAL && !64BIT
+ depends on I2C && PCI && EXPERIMENTAL
help
If you say yes to this option, support will be included for the Intel
PIIX4 family of mainboard I2C interfaces. Specifically, the following
@@ -486,4 +486,14 @@ config I2C_PCA_ISA
This driver can also be built as a module. If so, the module
will be called i2c-pca-isa.
+config I2C_MV64XXX
+ tristate "Marvell mv64xxx I2C Controller"
+ depends on I2C && MV64X60 && EXPERIMENTAL
+ help
+ If you say yes to this option, support will be included for the
+ built-in I2C interface on the Marvell 64xxx line of host bridges.
+
+ This driver can also be built as a module. If so, the module
+ will be called i2c-mv64xxx.
+
endmenu
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index e5f4b1e507d43..42d6d814da726 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -21,6 +21,7 @@ obj-$(CONFIG_I2C_IXP2000) += i2c-ixp2000.o
obj-$(CONFIG_I2C_IXP4XX) += i2c-ixp4xx.o
obj-$(CONFIG_I2C_KEYWEST) += i2c-keywest.o
obj-$(CONFIG_I2C_MPC) += i2c-mpc.o
+obj-$(CONFIG_I2C_MV64XXX) += i2c-mv64xxx.o
obj-$(CONFIG_I2C_NFORCE2) += i2c-nforce2.o
obj-$(CONFIG_I2C_PARPORT) += i2c-parport.o
obj-$(CONFIG_I2C_PARPORT_LIGHT) += i2c-parport-light.o
diff --git a/drivers/i2c/busses/i2c-au1550.c b/drivers/i2c/busses/i2c-au1550.c
index c43353aa3d204..75831a20b0bd2 100644
--- a/drivers/i2c/busses/i2c-au1550.c
+++ b/drivers/i2c/busses/i2c-au1550.c
@@ -253,7 +253,7 @@ i2c_write(struct i2c_au1550_data *adap, unsigned char *buf,
}
static int
-au1550_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num)
+au1550_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
{
struct i2c_au1550_data *adap = i2c_adap->algo_data;
struct i2c_msg *p;
diff --git a/drivers/i2c/busses/i2c-elektor.c b/drivers/i2c/busses/i2c-elektor.c
index 2fda2b8448a6b..96fc7d72904bc 100644
--- a/drivers/i2c/busses/i2c-elektor.c
+++ b/drivers/i2c/busses/i2c-elektor.c
@@ -183,6 +183,7 @@ static struct i2c_algo_pcf_data pcf_isa_data = {
static struct i2c_adapter pcf_isa_ops = {
.owner = THIS_MODULE,
+ .class = I2C_CLASS_HWMON,
.id = I2C_HW_P_ELEK,
.algo_data = &pcf_isa_data,
.name = "PCF8584 ISA adapter",
diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c
index 8168f2d3b922b..17326cdd68d74 100644
--- a/drivers/i2c/busses/i2c-ibm_iic.c
+++ b/drivers/i2c/busses/i2c-ibm_iic.c
@@ -549,7 +549,7 @@ static inline int iic_address_neq(const struct i2c_msg* p1,
* Generic master transfer entrypoint.
* Returns the number of processed messages or error (<0)
*/
-static int iic_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
+static int iic_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
{
struct ibm_iic_private* dev = (struct ibm_iic_private*)(i2c_get_adapdata(adap));
volatile struct iic_regs __iomem *iic = dev->vaddr;
diff --git a/drivers/i2c/busses/i2c-iop3xx.c b/drivers/i2c/busses/i2c-iop3xx.c
index 961241b19f886..c961ba4cfb325 100644
--- a/drivers/i2c/busses/i2c-iop3xx.c
+++ b/drivers/i2c/busses/i2c-iop3xx.c
@@ -361,7 +361,7 @@ iop3xx_i2c_handle_msg(struct i2c_adapter *i2c_adap, struct i2c_msg* pmsg)
* master_xfer() - main read/write entry
*/
static int
-iop3xx_i2c_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[],
+iop3xx_i2c_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs,
int num)
{
struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data;
diff --git a/drivers/i2c/busses/i2c-ixp4xx.c b/drivers/i2c/busses/i2c-ixp4xx.c
index d8bfd59c1dc06..8c55eafc3a097 100644
--- a/drivers/i2c/busses/i2c-ixp4xx.c
+++ b/drivers/i2c/busses/i2c-ixp4xx.c
@@ -133,8 +133,8 @@ static int ixp4xx_i2c_probe(struct device *dev)
drv_data->algo_data.mdelay = 10;
drv_data->algo_data.timeout = 100;
- drv_data->adapter.id = I2C_HW_B_IXP4XX,
- drv_data->adapter.algo_data = &drv_data->algo_data,
+ drv_data->adapter.id = I2C_HW_B_IXP4XX;
+ drv_data->adapter.algo_data = &drv_data->algo_data;
drv_data->adapter.dev.parent = &plat_dev->dev;
diff --git a/drivers/i2c/busses/i2c-keywest.c b/drivers/i2c/busses/i2c-keywest.c
index bc94b8cd36a5a..dd0d4c463146b 100644
--- a/drivers/i2c/busses/i2c-keywest.c
+++ b/drivers/i2c/busses/i2c-keywest.c
@@ -399,7 +399,7 @@ keywest_smbus_xfer( struct i2c_adapter* adap,
*/
static int
keywest_xfer( struct i2c_adapter *adap,
- struct i2c_msg msgs[],
+ struct i2c_msg *msgs,
int num)
{
struct keywest_chan* chan = i2c_get_adapdata(adap);
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
index 67d6e7d299a2d..75b8d867dae11 100644
--- a/drivers/i2c/busses/i2c-mpc.c
+++ b/drivers/i2c/busses/i2c-mpc.c
@@ -233,7 +233,7 @@ static int mpc_read(struct mpc_i2c *i2c, int target,
return length;
}
-static int mpc_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
+static int mpc_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
{
struct i2c_msg *pmsg;
int i;
diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c
new file mode 100644
index 0000000000000..db88a12439562
--- /dev/null
+++ b/drivers/i2c/busses/i2c-mv64xxx.c
@@ -0,0 +1,596 @@
+/*
+ * 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).
+ *
+ * Author: Mark A. Greer <mgreer@mvista.com>
+ *
+ * 2005 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/mv643xx.h>
+#include <asm/io.h>
+
+/* Register defines */
+#define MV64XXX_I2C_REG_SLAVE_ADDR 0x00
+#define MV64XXX_I2C_REG_DATA 0x04
+#define MV64XXX_I2C_REG_CONTROL 0x08
+#define MV64XXX_I2C_REG_STATUS 0x0c
+#define MV64XXX_I2C_REG_BAUD 0x0c
+#define MV64XXX_I2C_REG_EXT_SLAVE_ADDR 0x10
+#define MV64XXX_I2C_REG_SOFT_RESET 0x1c
+
+#define MV64XXX_I2C_REG_CONTROL_ACK 0x00000004
+#define MV64XXX_I2C_REG_CONTROL_IFLG 0x00000008
+#define MV64XXX_I2C_REG_CONTROL_STOP 0x00000010
+#define MV64XXX_I2C_REG_CONTROL_START 0x00000020
+#define MV64XXX_I2C_REG_CONTROL_TWSIEN 0x00000040
+#define MV64XXX_I2C_REG_CONTROL_INTEN 0x00000080
+
+/* Ctlr status values */
+#define MV64XXX_I2C_STATUS_BUS_ERR 0x00
+#define MV64XXX_I2C_STATUS_MAST_START 0x08
+#define MV64XXX_I2C_STATUS_MAST_REPEAT_START 0x10
+#define MV64XXX_I2C_STATUS_MAST_WR_ADDR_ACK 0x18
+#define MV64XXX_I2C_STATUS_MAST_WR_ADDR_NO_ACK 0x20
+#define MV64XXX_I2C_STATUS_MAST_WR_ACK 0x28
+#define MV64XXX_I2C_STATUS_MAST_WR_NO_ACK 0x30
+#define MV64XXX_I2C_STATUS_MAST_LOST_ARB 0x38
+#define MV64XXX_I2C_STATUS_MAST_RD_ADDR_ACK 0x40
+#define MV64XXX_I2C_STATUS_MAST_RD_ADDR_NO_ACK 0x48
+#define MV64XXX_I2C_STATUS_MAST_RD_DATA_ACK 0x50
+#define MV64XXX_I2C_STATUS_MAST_RD_DATA_NO_ACK 0x58
+#define MV64XXX_I2C_STATUS_MAST_WR_ADDR_2_ACK 0xd0
+#define MV64XXX_I2C_STATUS_MAST_WR_ADDR_2_NO_ACK 0xd8
+#define MV64XXX_I2C_STATUS_MAST_RD_ADDR_2_ACK 0xe0
+#define MV64XXX_I2C_STATUS_MAST_RD_ADDR_2_NO_ACK 0xe8
+#define MV64XXX_I2C_STATUS_NO_STATUS 0xf8
+
+/* Driver states */
+enum {
+ MV64XXX_I2C_STATE_INVALID,
+ MV64XXX_I2C_STATE_IDLE,
+ MV64XXX_I2C_STATE_WAITING_FOR_START_COND,
+ MV64XXX_I2C_STATE_WAITING_FOR_ADDR_1_ACK,
+ 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 */
+enum {
+ MV64XXX_I2C_ACTION_INVALID,
+ MV64XXX_I2C_ACTION_CONTINUE,
+ MV64XXX_I2C_ACTION_SEND_START,
+ MV64XXX_I2C_ACTION_SEND_ADDR_1,
+ MV64XXX_I2C_ACTION_SEND_ADDR_2,
+ MV64XXX_I2C_ACTION_SEND_DATA,
+ MV64XXX_I2C_ACTION_RCV_DATA,
+ MV64XXX_I2C_ACTION_RCV_DATA_STOP,
+ MV64XXX_I2C_ACTION_SEND_STOP,
+};
+
+struct mv64xxx_i2c_data {
+ int irq;
+ u32 state;
+ u32 action;
+ u32 cntl_bits;
+ void __iomem *reg_base;
+ u32 reg_base_p;
+ u32 addr1;
+ u32 addr2;
+ u32 bytes_left;
+ u32 byte_posn;
+ u32 block;
+ int rc;
+ u32 freq_m;
+ u32 freq_n;
+ wait_queue_head_t waitq;
+ spinlock_t lock;
+ struct i2c_msg *msg;
+ struct i2c_adapter adapter;
+};
+
+/*
+ *****************************************************************************
+ *
+ * Finite State Machine & Interrupt Routines
+ *
+ *****************************************************************************
+ */
+static void
+mv64xxx_i2c_fsm(struct mv64xxx_i2c_data *drv_data, u32 status)
+{
+ /*
+ * If state is idle, then this is likely the remnants of an old
+ * operation that driver has given up on or the user has killed.
+ * If so, issue the stop condition and go to idle.
+ */
+ if (drv_data->state == MV64XXX_I2C_STATE_IDLE) {
+ drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP;
+ 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 */
+ case MV64XXX_I2C_STATUS_MAST_START: /* 0x08 */
+ case MV64XXX_I2C_STATUS_MAST_REPEAT_START: /* 0x10 */
+ drv_data->action = MV64XXX_I2C_ACTION_SEND_ADDR_1;
+ drv_data->state = MV64XXX_I2C_STATE_WAITING_FOR_ADDR_1_ACK;
+ break;
+
+ /* Performing a write */
+ case MV64XXX_I2C_STATUS_MAST_WR_ADDR_ACK: /* 0x18 */
+ if (drv_data->msg->flags & I2C_M_TEN) {
+ drv_data->action = MV64XXX_I2C_ACTION_SEND_ADDR_2;
+ drv_data->state =
+ MV64XXX_I2C_STATE_WAITING_FOR_ADDR_2_ACK;
+ break;
+ }
+ /* 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) {
+ 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;
+
+ /* Performing a read */
+ case MV64XXX_I2C_STATUS_MAST_RD_ADDR_ACK: /* 40 */
+ if (drv_data->msg->flags & I2C_M_TEN) {
+ drv_data->action = MV64XXX_I2C_ACTION_SEND_ADDR_2;
+ drv_data->state =
+ MV64XXX_I2C_STATE_WAITING_FOR_ADDR_2_ACK;
+ break;
+ }
+ /* FALLTHRU */
+ case MV64XXX_I2C_STATUS_MAST_RD_ADDR_2_ACK: /* 0xe0 */
+ if (drv_data->bytes_left == 0) {
+ drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP;
+ drv_data->state = MV64XXX_I2C_STATE_IDLE;
+ break;
+ }
+ /* FALLTHRU */
+ case MV64XXX_I2C_STATUS_MAST_RD_DATA_ACK: /* 0x50 */
+ if (status != MV64XXX_I2C_STATUS_MAST_RD_DATA_ACK)
+ drv_data->action = MV64XXX_I2C_ACTION_CONTINUE;
+ else {
+ drv_data->action = MV64XXX_I2C_ACTION_RCV_DATA;
+ drv_data->bytes_left--;
+ }
+ drv_data->state = MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_DATA;
+
+ if (drv_data->bytes_left == 1)
+ drv_data->cntl_bits &= ~MV64XXX_I2C_REG_CONTROL_ACK;
+ break;
+
+ case MV64XXX_I2C_STATUS_MAST_RD_DATA_NO_ACK: /* 0x58 */
+ drv_data->action = MV64XXX_I2C_ACTION_RCV_DATA_STOP;
+ drv_data->state = MV64XXX_I2C_STATE_IDLE;
+ break;
+
+ case MV64XXX_I2C_STATUS_MAST_WR_ADDR_NO_ACK: /* 0x20 */
+ case MV64XXX_I2C_STATUS_MAST_WR_NO_ACK: /* 30 */
+ case MV64XXX_I2C_STATUS_MAST_RD_ADDR_NO_ACK: /* 48 */
+ /* Doesn't seem to be a device at other end */
+ drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP;
+ drv_data->state = MV64XXX_I2C_STATE_IDLE;
+ drv_data->rc = -ENODEV;
+ break;
+
+ default:
+ dev_err(&drv_data->adapter.dev,
+ "mv64xxx_i2c_fsm: Ctlr Error -- state: 0x%x, "
+ "status: 0x%x, addr: 0x%x, flags: 0x%x\n",
+ drv_data->state, status, drv_data->msg->addr,
+ drv_data->msg->flags);
+ drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP;
+ drv_data->state = MV64XXX_I2C_STATE_IDLE;
+ drv_data->rc = -EIO;
+ }
+}
+
+static void
+mv64xxx_i2c_do_action(struct mv64xxx_i2c_data *drv_data)
+{
+ switch(drv_data->action) {
+ case MV64XXX_I2C_ACTION_CONTINUE:
+ writel(drv_data->cntl_bits,
+ drv_data->reg_base + MV64XXX_I2C_REG_CONTROL);
+ break;
+
+ case MV64XXX_I2C_ACTION_SEND_START:
+ writel(drv_data->cntl_bits | MV64XXX_I2C_REG_CONTROL_START,
+ drv_data->reg_base + MV64XXX_I2C_REG_CONTROL);
+ break;
+
+ case MV64XXX_I2C_ACTION_SEND_ADDR_1:
+ writel(drv_data->addr1,
+ drv_data->reg_base + MV64XXX_I2C_REG_DATA);
+ writel(drv_data->cntl_bits,
+ drv_data->reg_base + MV64XXX_I2C_REG_CONTROL);
+ break;
+
+ case MV64XXX_I2C_ACTION_SEND_ADDR_2:
+ writel(drv_data->addr2,
+ drv_data->reg_base + MV64XXX_I2C_REG_DATA);
+ writel(drv_data->cntl_bits,
+ drv_data->reg_base + MV64XXX_I2C_REG_CONTROL);
+ break;
+
+ case MV64XXX_I2C_ACTION_SEND_DATA:
+ writel(drv_data->msg->buf[drv_data->byte_posn++],
+ drv_data->reg_base + MV64XXX_I2C_REG_DATA);
+ writel(drv_data->cntl_bits,
+ drv_data->reg_base + MV64XXX_I2C_REG_CONTROL);
+ break;
+
+ case MV64XXX_I2C_ACTION_RCV_DATA:
+ drv_data->msg->buf[drv_data->byte_posn++] =
+ readl(drv_data->reg_base + MV64XXX_I2C_REG_DATA);
+ writel(drv_data->cntl_bits,
+ drv_data->reg_base + MV64XXX_I2C_REG_CONTROL);
+ break;
+
+ case MV64XXX_I2C_ACTION_RCV_DATA_STOP:
+ drv_data->msg->buf[drv_data->byte_posn++] =
+ readl(drv_data->reg_base + MV64XXX_I2C_REG_DATA);
+ drv_data->cntl_bits &= ~MV64XXX_I2C_REG_CONTROL_INTEN;
+ writel(drv_data->cntl_bits | MV64XXX_I2C_REG_CONTROL_STOP,
+ drv_data->reg_base + MV64XXX_I2C_REG_CONTROL);
+ drv_data->block = 0;
+ wake_up_interruptible(&drv_data->waitq);
+ break;
+
+ case MV64XXX_I2C_ACTION_INVALID:
+ default:
+ dev_err(&drv_data->adapter.dev,
+ "mv64xxx_i2c_do_action: Invalid action: %d\n",
+ drv_data->action);
+ drv_data->rc = -EIO;
+ /* FALLTHRU */
+ case MV64XXX_I2C_ACTION_SEND_STOP:
+ drv_data->cntl_bits &= ~MV64XXX_I2C_REG_CONTROL_INTEN;
+ writel(drv_data->cntl_bits | MV64XXX_I2C_REG_CONTROL_STOP,
+ drv_data->reg_base + MV64XXX_I2C_REG_CONTROL);
+ drv_data->block = 0;
+ wake_up_interruptible(&drv_data->waitq);
+ break;
+ }
+}
+
+static int
+mv64xxx_i2c_intr(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct mv64xxx_i2c_data *drv_data = dev_id;
+ unsigned long flags;
+ u32 status;
+ int rc = IRQ_NONE;
+
+ spin_lock_irqsave(&drv_data->lock, flags);
+ while (readl(drv_data->reg_base + MV64XXX_I2C_REG_CONTROL) &
+ MV64XXX_I2C_REG_CONTROL_IFLG) {
+ status = readl(drv_data->reg_base + MV64XXX_I2C_REG_STATUS);
+ mv64xxx_i2c_fsm(drv_data, status);
+ mv64xxx_i2c_do_action(drv_data);
+ rc = IRQ_HANDLED;
+ }
+ spin_unlock_irqrestore(&drv_data->lock, flags);
+
+ return rc;
+}
+
+/*
+ *****************************************************************************
+ *
+ * I2C Msg Execution Routines
+ *
+ *****************************************************************************
+ */
+static void
+mv64xxx_i2c_prepare_for_io(struct mv64xxx_i2c_data *drv_data,
+ struct i2c_msg *msg)
+{
+ u32 dir = 0;
+
+ drv_data->msg = msg;
+ drv_data->byte_posn = 0;
+ drv_data->bytes_left = msg->len;
+ drv_data->rc = 0;
+ drv_data->cntl_bits = MV64XXX_I2C_REG_CONTROL_ACK |
+ MV64XXX_I2C_REG_CONTROL_INTEN | MV64XXX_I2C_REG_CONTROL_TWSIEN;
+
+ if (msg->flags & I2C_M_RD)
+ dir = 1;
+
+ if (msg->flags & I2C_M_REV_DIR_ADDR)
+ dir ^= 1;
+
+ if (msg->flags & I2C_M_TEN) {
+ drv_data->addr1 = 0xf0 | (((u32)msg->addr & 0x300) >> 7) | dir;
+ drv_data->addr2 = (u32)msg->addr & 0xff;
+ } else {
+ drv_data->addr1 = ((u32)msg->addr & 0x7f) << 1 | dir;
+ drv_data->addr2 = 0;
+ }
+}
+
+static void
+mv64xxx_i2c_wait_for_completion(struct mv64xxx_i2c_data *drv_data)
+{
+ long time_left;
+ unsigned long flags;
+ char abort = 0;
+
+ time_left = wait_event_interruptible_timeout(drv_data->waitq,
+ !drv_data->block, msecs_to_jiffies(drv_data->adapter.timeout));
+
+ spin_lock_irqsave(&drv_data->lock, flags);
+ if (!time_left) { /* Timed out */
+ drv_data->rc = -ETIMEDOUT;
+ abort = 1;
+ } else if (time_left < 0) { /* Interrupted/Error */
+ drv_data->rc = time_left; /* errno value */
+ abort = 1;
+ }
+
+ if (abort && drv_data->block) {
+ drv_data->state = MV64XXX_I2C_STATE_ABORTING;
+ 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) {
+ drv_data->state = MV64XXX_I2C_STATE_IDLE;
+ dev_err(&drv_data->adapter.dev,
+ "mv64xxx: I2C bus locked\n");
+ }
+ } else
+ spin_unlock_irqrestore(&drv_data->lock, flags);
+}
+
+static int
+mv64xxx_i2c_execute_msg(struct mv64xxx_i2c_data *drv_data, struct i2c_msg *msg)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&drv_data->lock, flags);
+ mv64xxx_i2c_prepare_for_io(drv_data, msg);
+
+ if (unlikely(msg->flags & I2C_M_NOSTART)) { /* Skip start/addr phases */
+ if (drv_data->msg->flags & I2C_M_RD) {
+ /* No action to do, wait for slave to send a byte */
+ drv_data->action = MV64XXX_I2C_ACTION_CONTINUE;
+ drv_data->state =
+ MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_DATA;
+ } 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_START;
+ drv_data->state = MV64XXX_I2C_STATE_WAITING_FOR_START_COND;
+ }
+
+ drv_data->block = 1;
+ mv64xxx_i2c_do_action(drv_data);
+ spin_unlock_irqrestore(&drv_data->lock, flags);
+
+ mv64xxx_i2c_wait_for_completion(drv_data);
+ return drv_data->rc;
+}
+
+/*
+ *****************************************************************************
+ *
+ * I2C Core Support Routines (Interface to higher level I2C code)
+ *
+ *****************************************************************************
+ */
+static u32
+mv64xxx_i2c_functionality(struct i2c_adapter *adap)
+{
+ return I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR | I2C_FUNC_SMBUS_EMUL;
+}
+
+static int
+mv64xxx_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
+{
+ struct mv64xxx_i2c_data *drv_data = i2c_get_adapdata(adap);
+ int i, rc = 0;
+
+ for (i=0; i<num; i++)
+ if ((rc = mv64xxx_i2c_execute_msg(drv_data, &msgs[i])) != 0)
+ break;
+
+ return rc;
+}
+
+static struct i2c_algorithm mv64xxx_i2c_algo = {
+ .name = MV64XXX_I2C_CTLR_NAME " algorithm",
+ .id = I2C_ALGO_MV64XXX,
+ .master_xfer = mv64xxx_i2c_xfer,
+ .functionality = mv64xxx_i2c_functionality,
+};
+
+/*
+ *****************************************************************************
+ *
+ * Driver Interface & Early Init Routines
+ *
+ *****************************************************************************
+ */
+static void __devinit
+mv64xxx_i2c_hw_init(struct mv64xxx_i2c_data *drv_data)
+{
+ writel(0, drv_data->reg_base + MV64XXX_I2C_REG_SOFT_RESET);
+ writel((((drv_data->freq_m & 0xf) << 3) | (drv_data->freq_n & 0x7)),
+ drv_data->reg_base + MV64XXX_I2C_REG_BAUD);
+ writel(0, drv_data->reg_base + MV64XXX_I2C_REG_SLAVE_ADDR);
+ writel(0, drv_data->reg_base + MV64XXX_I2C_REG_EXT_SLAVE_ADDR);
+ writel(MV64XXX_I2C_REG_CONTROL_TWSIEN | MV64XXX_I2C_REG_CONTROL_STOP,
+ drv_data->reg_base + MV64XXX_I2C_REG_CONTROL);
+ drv_data->state = MV64XXX_I2C_STATE_IDLE;
+}
+
+static int __devinit
+mv64xxx_i2c_map_regs(struct platform_device *pd,
+ struct mv64xxx_i2c_data *drv_data)
+{
+ struct resource *r;
+
+ if ((r = platform_get_resource(pd, IORESOURCE_MEM, 0)) &&
+ request_mem_region(r->start, MV64XXX_I2C_REG_BLOCK_SIZE,
+ drv_data->adapter.name)) {
+
+ drv_data->reg_base = ioremap(r->start,
+ MV64XXX_I2C_REG_BLOCK_SIZE);
+ drv_data->reg_base_p = r->start;
+ } else
+ return -ENOMEM;
+
+ return 0;
+}
+
+static void __devexit
+mv64xxx_i2c_unmap_regs(struct mv64xxx_i2c_data *drv_data)
+{
+ if (drv_data->reg_base) {
+ iounmap(drv_data->reg_base);
+ release_mem_region(drv_data->reg_base_p,
+ MV64XXX_I2C_REG_BLOCK_SIZE);
+ }
+
+ drv_data->reg_base = NULL;
+ drv_data->reg_base_p = 0;
+}
+
+static int __devinit
+mv64xxx_i2c_probe(struct device *dev)
+{
+ struct platform_device *pd = to_platform_device(dev);
+ struct mv64xxx_i2c_data *drv_data;
+ struct mv64xxx_i2c_pdata *pdata = dev->platform_data;
+ int rc;
+
+ if ((pd->id != 0) || !pdata)
+ return -ENODEV;
+
+ drv_data = kmalloc(sizeof(struct mv64xxx_i2c_data), GFP_KERNEL);
+
+ if (!drv_data)
+ return -ENOMEM;
+
+ memset(drv_data, 0, sizeof(struct mv64xxx_i2c_data));
+
+ if (mv64xxx_i2c_map_regs(pd, drv_data)) {
+ rc = -ENODEV;
+ goto exit_kfree;
+ }
+
+ strncpy(drv_data->adapter.name, MV64XXX_I2C_CTLR_NAME " adapter",
+ I2C_NAME_SIZE);
+
+ init_waitqueue_head(&drv_data->waitq);
+ spin_lock_init(&drv_data->lock);
+
+ drv_data->freq_m = pdata->freq_m;
+ drv_data->freq_n = pdata->freq_n;
+ drv_data->irq = platform_get_irq(pd, 0);
+ drv_data->adapter.id = I2C_ALGO_MV64XXX | I2C_HW_MV64XXX;
+ drv_data->adapter.algo = &mv64xxx_i2c_algo;
+ drv_data->adapter.timeout = pdata->timeout;
+ drv_data->adapter.retries = pdata->retries;
+ dev_set_drvdata(dev, drv_data);
+ i2c_set_adapdata(&drv_data->adapter, drv_data);
+
+ if (request_irq(drv_data->irq, mv64xxx_i2c_intr, 0,
+ MV64XXX_I2C_CTLR_NAME, drv_data)) {
+
+ dev_err(dev, "mv64xxx: Can't register intr handler "
+ "irq: %d\n", drv_data->irq);
+ rc = -EINVAL;
+ goto exit_unmap_regs;
+ } else if ((rc = i2c_add_adapter(&drv_data->adapter)) != 0) {
+ dev_err(dev, "mv64xxx: Can't add i2c adapter, rc: %d\n", -rc);
+ goto exit_free_irq;
+ }
+
+ mv64xxx_i2c_hw_init(drv_data);
+
+ return 0;
+
+ exit_free_irq:
+ free_irq(drv_data->irq, drv_data);
+ exit_unmap_regs:
+ mv64xxx_i2c_unmap_regs(drv_data);
+ exit_kfree:
+ kfree(drv_data);
+ return rc;
+}
+
+static int __devexit
+mv64xxx_i2c_remove(struct device *dev)
+{
+ struct mv64xxx_i2c_data *drv_data = dev_get_drvdata(dev);
+ int rc;
+
+ rc = i2c_del_adapter(&drv_data->adapter);
+ free_irq(drv_data->irq, drv_data);
+ mv64xxx_i2c_unmap_regs(drv_data);
+ kfree(drv_data);
+
+ return rc;
+}
+
+static struct device_driver mv64xxx_i2c_driver = {
+ .name = MV64XXX_I2C_CTLR_NAME,
+ .bus = &platform_bus_type,
+ .probe = mv64xxx_i2c_probe,
+ .remove = mv64xxx_i2c_remove,
+};
+
+static int __init
+mv64xxx_i2c_init(void)
+{
+ return driver_register(&mv64xxx_i2c_driver);
+}
+
+static void __exit
+mv64xxx_i2c_exit(void)
+{
+ driver_unregister(&mv64xxx_i2c_driver);
+}
+
+module_init(mv64xxx_i2c_init);
+module_exit(mv64xxx_i2c_exit);
+
+MODULE_AUTHOR("Mark A. Greer <mgreer@mvista.com>");
+MODULE_DESCRIPTION("Marvell mv64xxx host bridge i2c ctlr driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/i2c/busses/i2c-nforce2.c b/drivers/i2c/busses/i2c-nforce2.c
index b2b6081327d88..6d13127c8c4e1 100644
--- a/drivers/i2c/busses/i2c-nforce2.c
+++ b/drivers/i2c/busses/i2c-nforce2.c
@@ -29,9 +29,10 @@
nForce2 Ultra 400 MCP 0084
nForce3 Pro150 MCP 00D4
nForce3 250Gb MCP 00E4
+ nForce4 MCP 0052
- This driver supports the 2 SMBuses that are included in the MCP2 of the
- nForce2 chipset.
+ This driver supports the 2 SMBuses that are included in the MCP of the
+ nForce2/3/4 chipsets.
*/
/* Note: we assume there can only be one nForce2, with two SMBus interfaces */
@@ -295,6 +296,7 @@ static struct pci_device_id nforce2_ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_SMBUS) },
{ 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) },
{ 0 }
};
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
index 9cb69744a71b1..0ac72c935e752 100644
--- a/drivers/i2c/busses/i2c-s3c2410.c
+++ b/drivers/i2c/busses/i2c-s3c2410.c
@@ -483,7 +483,7 @@ static int s3c24xx_i2c_set_master(struct s3c24xx_i2c *i2c)
* this starts an i2c transfer
*/
-static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c, struct i2c_msg msgs[], int num)
+static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c, struct i2c_msg *msgs, int num)
{
unsigned long timeout;
int ret;
@@ -534,7 +534,7 @@ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c, struct i2c_msg msgs[], in
*/
static int s3c24xx_i2c_xfer(struct i2c_adapter *adap,
- struct i2c_msg msgs[], int num)
+ struct i2c_msg *msgs, int num)
{
struct s3c24xx_i2c *i2c = (struct s3c24xx_i2c *)adap->algo_data;
int retry;
@@ -569,6 +569,7 @@ static struct s3c24xx_i2c s3c24xx_i2c = {
.name = "s3c2410-i2c",
.algo = &s3c24xx_i2c_algorithm,
.retries = 2,
+ .class = I2C_CLASS_HWMON,
},
};
diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
index 1c4ba56199087..824c62d3a66c5 100644
--- a/drivers/i2c/chips/Kconfig
+++ b/drivers/i2c/chips/Kconfig
@@ -63,7 +63,7 @@ config SENSORS_ASB100
will be called asb100.
config SENSORS_DS1621
- tristate "Dallas Semiconductor DS1621 and DS1625"
+ tristate "Dallas Semiconductor DS1621 and DS1625"
depends on I2C && EXPERIMENTAL
select I2C_SENSOR
help
@@ -84,6 +84,17 @@ config SENSORS_FSCHER
This driver can also be built as a module. If so, the module
will be called fscher.
+config SENSORS_FSCPOS
+ tristate "FSC Poseidon"
+ depends on I2C && EXPERIMENTAL
+ select I2C_SENSOR
+ help
+ If you say yes here you get support for Fujitsu Siemens
+ Computers Poseidon sensor chips.
+
+ This driver can also be built as a module. If so, the module
+ will be called fscpos.
+
config SENSORS_GL518SM
tristate "Genesys Logic GL518SM"
depends on I2C && EXPERIMENTAL
@@ -95,6 +106,17 @@ config SENSORS_GL518SM
This driver can also be built as a module. If so, the module
will be called gl518sm.
+config SENSORS_GL520SM
+ tristate "Genesys Logic GL520SM"
+ depends on I2C && EXPERIMENTAL
+ select I2C_SENSOR
+ help
+ If you say yes here you get support for Genesys Logic GL520SM
+ sensor chips.
+
+ This driver can also be built as a module. If so, the module
+ will be called gl520sm.
+
config SENSORS_IT87
tristate "ITE IT87xx and compatibles"
depends on I2C && EXPERIMENTAL
@@ -251,6 +273,18 @@ config SENSORS_SMSC47B397
This driver can also be built as a module. If so, the module
will be called smsc47b397.
+config SENSORS_SIS5595
+ tristate "Silicon Integrated Systems Corp. SiS5595"
+ depends on I2C && PCI && EXPERIMENTAL
+ select I2C_SENSOR
+ select I2C_ISA
+ help
+ If you say yes here you get support for the integrated sensors in
+ SiS5595 South Bridges.
+
+ This driver can also be built as a module. If so, the module
+ will be called sis5595.
+
config SENSORS_SMSC47M1
tristate "SMSC LPC47M10x and compatibles"
depends on I2C && EXPERIMENTAL
@@ -304,6 +338,7 @@ config SENSORS_W83627HF
tristate "Winbond W83627HF, W83627THF, W83637HF, W83697HF"
depends on I2C && EXPERIMENTAL
select I2C_SENSOR
+ select I2C_ISA
help
If you say yes here you get support for the Winbond W836X7 series
of sensor chips: the W83627HF, W83627THF, W83637HF, and the W83697HF
@@ -371,4 +406,13 @@ config ISP1301_OMAP
This driver can also be built as a module. If so, the module
will be called isp1301_omap.
+config SENSORS_M41T00
+ tristate "ST M41T00 RTC chip"
+ depends on I2C && PPC32
+ help
+ If you say yes here you get support for the ST M41T00 RTC chip.
+
+ This driver can also be built as a module. If so, the module
+ will be called m41t00.
+
endmenu
diff --git a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile
index 74dd56873a8bd..a6db6f39476c2 100644
--- a/drivers/i2c/chips/Makefile
+++ b/drivers/i2c/chips/Makefile
@@ -14,7 +14,9 @@ obj-$(CONFIG_SENSORS_ADM1031) += adm1031.o
obj-$(CONFIG_SENSORS_DS1621) += ds1621.o
obj-$(CONFIG_SENSORS_EEPROM) += eeprom.o
obj-$(CONFIG_SENSORS_FSCHER) += fscher.o
+obj-$(CONFIG_SENSORS_FSCPOS) += fscpos.o
obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o
+obj-$(CONFIG_SENSORS_GL520SM) += gl520sm.o
obj-$(CONFIG_SENSORS_IT87) += it87.o
obj-$(CONFIG_SENSORS_LM63) += lm63.o
obj-$(CONFIG_SENSORS_LM75) += lm75.o
@@ -26,10 +28,12 @@ obj-$(CONFIG_SENSORS_LM85) += lm85.o
obj-$(CONFIG_SENSORS_LM87) += lm87.o
obj-$(CONFIG_SENSORS_LM90) += lm90.o
obj-$(CONFIG_SENSORS_MAX1619) += max1619.o
+obj-$(CONFIG_SENSORS_M41T00) += m41t00.o
obj-$(CONFIG_SENSORS_PC87360) += pc87360.o
obj-$(CONFIG_SENSORS_PCF8574) += pcf8574.o
obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o
obj-$(CONFIG_SENSORS_RTC8564) += rtc8564.o
+obj-$(CONFIG_SENSORS_SIS5595) += sis5595.o
obj-$(CONFIG_SENSORS_SMSC47B397)+= smsc47b397.o
obj-$(CONFIG_SENSORS_SMSC47M1) += smsc47m1.o
obj-$(CONFIG_SENSORS_VIA686A) += via686a.o
diff --git a/drivers/i2c/chips/adm1021.c b/drivers/i2c/chips/adm1021.c
index 714b4aba99cbb..5dd7f64fdddd4 100644
--- a/drivers/i2c/chips/adm1021.c
+++ b/drivers/i2c/chips/adm1021.c
@@ -23,6 +23,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
+#include <linux/jiffies.h>
#include <linux/i2c.h>
#include <linux/i2c-sensor.h>
@@ -147,8 +148,6 @@ static struct i2c_driver adm1021_driver = {
.detach_client = adm1021_detach_client,
};
-static int adm1021_id;
-
#define show(value) \
static ssize_t show_##value(struct device *dev, char *buf) \
{ \
@@ -299,8 +298,6 @@ static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind)
/* Fill in the remaining client fields and put it into the global list */
strlcpy(new_client->name, type_name, I2C_NAME_SIZE);
data->type = kind;
-
- new_client->id = adm1021_id++;
data->valid = 0;
init_MUTEX(&data->update_lock);
@@ -373,8 +370,8 @@ static struct adm1021_data *adm1021_update_device(struct device *dev)
down(&data->update_lock);
- if ((jiffies - data->last_updated > HZ + HZ / 2) ||
- (jiffies < data->last_updated) || !data->valid) {
+ if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
+ || !data->valid) {
dev_dbg(&client->dev, "Starting adm1021 update\n");
data->temp_input = adm1021_read_value(client, ADM1021_REG_TEMP);
diff --git a/drivers/i2c/chips/adm1025.c b/drivers/i2c/chips/adm1025.c
index 4f410885bff0d..d9053e37ea2b5 100644
--- a/drivers/i2c/chips/adm1025.c
+++ b/drivers/i2c/chips/adm1025.c
@@ -49,6 +49,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
+#include <linux/jiffies.h>
#include <linux/i2c.h>
#include <linux/i2c-sensor.h>
#include <linux/i2c-vid.h>
@@ -148,12 +149,6 @@ struct adm1025_data {
};
/*
- * Internal variables
- */
-
-static int adm1025_id;
-
-/*
* Sysfs stuff
*/
@@ -397,7 +392,6 @@ static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind)
/* We can fill in the remaining client fields */
strlcpy(new_client->name, name, I2C_NAME_SIZE);
- new_client->id = adm1025_id++;
data->valid = 0;
init_MUTEX(&data->update_lock);
@@ -512,9 +506,7 @@ static struct adm1025_data *adm1025_update_device(struct device *dev)
down(&data->update_lock);
- if ((jiffies - data->last_updated > HZ * 2) ||
- (jiffies < data->last_updated) ||
- !data->valid) {
+ if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) {
int i;
dev_dbg(&client->dev, "Updating data.\n");
diff --git a/drivers/i2c/chips/adm1026.c b/drivers/i2c/chips/adm1026.c
index 58f8acd00b6ef..1a0f4f2220330 100644
--- a/drivers/i2c/chips/adm1026.c
+++ b/drivers/i2c/chips/adm1026.c
@@ -27,6 +27,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
+#include <linux/jiffies.h>
#include <linux/i2c.h>
#include <linux/i2c-sensor.h>
#include <linux/i2c-vid.h>
@@ -313,8 +314,6 @@ static struct i2c_driver adm1026_driver = {
.detach_client = adm1026_detach_client,
};
-static int adm1026_id;
-
int adm1026_attach_adapter(struct i2c_adapter *adapter)
{
if (!(adapter->class & I2C_CLASS_HWMON)) {
@@ -363,49 +362,47 @@ void adm1026_init_client(struct i2c_client *client)
int value, i;
struct adm1026_data *data = i2c_get_clientdata(client);
- dev_dbg(&client->dev,"(%d): Initializing device\n", client->id);
+ dev_dbg(&client->dev, "Initializing device\n");
/* Read chip config */
data->config1 = adm1026_read_value(client, ADM1026_REG_CONFIG1);
data->config2 = adm1026_read_value(client, ADM1026_REG_CONFIG2);
data->config3 = adm1026_read_value(client, ADM1026_REG_CONFIG3);
/* Inform user of chip config */
- dev_dbg(&client->dev, "(%d): ADM1026_REG_CONFIG1 is: 0x%02x\n",
- client->id, data->config1);
+ dev_dbg(&client->dev, "ADM1026_REG_CONFIG1 is: 0x%02x\n",
+ data->config1);
if ((data->config1 & CFG1_MONITOR) == 0) {
- dev_dbg(&client->dev, "(%d): Monitoring not currently "
- "enabled.\n", client->id);
+ dev_dbg(&client->dev, "Monitoring not currently "
+ "enabled.\n");
}
if (data->config1 & CFG1_INT_ENABLE) {
- dev_dbg(&client->dev, "(%d): SMBALERT interrupts are "
- "enabled.\n", client->id);
+ dev_dbg(&client->dev, "SMBALERT interrupts are "
+ "enabled.\n");
}
if (data->config1 & CFG1_AIN8_9) {
- dev_dbg(&client->dev, "(%d): in8 and in9 enabled. "
- "temp3 disabled.\n", client->id);
+ dev_dbg(&client->dev, "in8 and in9 enabled. "
+ "temp3 disabled.\n");
} else {
- dev_dbg(&client->dev, "(%d): temp3 enabled. in8 and "
- "in9 disabled.\n", client->id);
+ dev_dbg(&client->dev, "temp3 enabled. in8 and "
+ "in9 disabled.\n");
}
if (data->config1 & CFG1_THERM_HOT) {
- dev_dbg(&client->dev, "(%d): Automatic THERM, PWM, "
- "and temp limits enabled.\n", client->id);
+ dev_dbg(&client->dev, "Automatic THERM, PWM, "
+ "and temp limits enabled.\n");
}
value = data->config3;
if (data->config3 & CFG3_GPIO16_ENABLE) {
- dev_dbg(&client->dev, "(%d): GPIO16 enabled. THERM"
- "pin disabled.\n", client->id);
+ dev_dbg(&client->dev, "GPIO16 enabled. THERM"
+ "pin disabled.\n");
} else {
- dev_dbg(&client->dev, "(%d): THERM pin enabled. "
- "GPIO16 disabled.\n", client->id);
+ dev_dbg(&client->dev, "THERM pin enabled. "
+ "GPIO16 disabled.\n");
}
if (data->config3 & CFG3_VREF_250) {
- dev_dbg(&client->dev, "(%d): Vref is 2.50 Volts.\n",
- client->id);
+ dev_dbg(&client->dev, "Vref is 2.50 Volts.\n");
} else {
- dev_dbg(&client->dev, "(%d): Vref is 1.82 Volts.\n",
- client->id);
+ dev_dbg(&client->dev, "Vref is 1.82 Volts.\n");
}
/* Read and pick apart the existing GPIO configuration */
value = 0;
@@ -423,12 +420,11 @@ void adm1026_init_client(struct i2c_client *client)
adm1026_print_gpio(client);
/* If the user asks us to reprogram the GPIO config, then
- * do it now. But only if this is the first ADM1026.
+ * do it now.
*/
- if (client->id == 0
- && (gpio_input[0] != -1 || gpio_output[0] != -1
+ if (gpio_input[0] != -1 || gpio_output[0] != -1
|| gpio_inverted[0] != -1 || gpio_normal[0] != -1
- || gpio_fan[0] != -1)) {
+ || gpio_fan[0] != -1) {
adm1026_fixup_gpio(client);
}
@@ -448,8 +444,7 @@ void adm1026_init_client(struct i2c_client *client)
value = adm1026_read_value(client, ADM1026_REG_CONFIG1);
/* Set MONITOR, clear interrupt acknowledge and s/w reset */
value = (value | CFG1_MONITOR) & (~CFG1_INT_CLEAR & ~CFG1_RESET);
- dev_dbg(&client->dev, "(%d): Setting CONFIG to: 0x%02x\n",
- client->id, value);
+ dev_dbg(&client->dev, "Setting CONFIG to: 0x%02x\n", value);
data->config1 = value;
adm1026_write_value(client, ADM1026_REG_CONFIG1, value);
@@ -467,31 +462,30 @@ void adm1026_print_gpio(struct i2c_client *client)
struct adm1026_data *data = i2c_get_clientdata(client);
int i;
- dev_dbg(&client->dev, "(%d): GPIO config is:", client->id);
+ dev_dbg(&client->dev, "GPIO config is:");
for (i = 0;i <= 7;++i) {
if (data->config2 & (1 << i)) {
- dev_dbg(&client->dev, "\t(%d): %sGP%s%d\n", client->id,
+ dev_dbg(&client->dev, "\t%sGP%s%d\n",
data->gpio_config[i] & 0x02 ? "" : "!",
data->gpio_config[i] & 0x01 ? "OUT" : "IN",
i);
} else {
- dev_dbg(&client->dev, "\t(%d): FAN%d\n",
- client->id, i);
+ dev_dbg(&client->dev, "\tFAN%d\n", i);
}
}
for (i = 8;i <= 15;++i) {
- dev_dbg(&client->dev, "\t(%d): %sGP%s%d\n", client->id,
+ dev_dbg(&client->dev, "\t%sGP%s%d\n",
data->gpio_config[i] & 0x02 ? "" : "!",
data->gpio_config[i] & 0x01 ? "OUT" : "IN",
i);
}
if (data->config3 & CFG3_GPIO16_ENABLE) {
- dev_dbg(&client->dev, "\t(%d): %sGP%s16\n", client->id,
+ dev_dbg(&client->dev, "\t%sGP%s16\n",
data->gpio_config[16] & 0x02 ? "" : "!",
data->gpio_config[16] & 0x01 ? "OUT" : "IN");
} else {
/* GPIO16 is THERM */
- dev_dbg(&client->dev, "\t(%d): THERM\n", client->id);
+ dev_dbg(&client->dev, "\tTHERM\n");
}
}
@@ -580,10 +574,9 @@ static struct adm1026_data *adm1026_update_device(struct device *dev)
down(&data->update_lock);
if (!data->valid
- || (jiffies - data->last_reading > ADM1026_DATA_INTERVAL)) {
+ || time_after(jiffies, data->last_reading + ADM1026_DATA_INTERVAL)) {
/* Things that change quickly */
- dev_dbg(&client->dev,"(%d): Reading sensor values\n",
- client->id);
+ dev_dbg(&client->dev,"Reading sensor values\n");
for (i = 0;i <= 16;++i) {
data->in[i] =
adm1026_read_value(client, ADM1026_REG_IN[i]);
@@ -628,11 +621,10 @@ static struct adm1026_data *adm1026_update_device(struct device *dev)
data->last_reading = jiffies;
}; /* last_reading */
- if (!data->valid || (jiffies - data->last_config >
- ADM1026_CONFIG_INTERVAL)) {
+ if (!data->valid ||
+ time_after(jiffies, data->last_config + ADM1026_CONFIG_INTERVAL)) {
/* Things that don't change often */
- dev_dbg(&client->dev, "(%d): Reading config values\n",
- client->id);
+ dev_dbg(&client->dev, "Reading config values\n");
for (i = 0;i <= 16;++i) {
data->in_min[i] = adm1026_read_value(client,
ADM1026_REG_IN_MIN[i]);
@@ -712,8 +704,7 @@ static struct adm1026_data *adm1026_update_device(struct device *dev)
data->last_config = jiffies;
}; /* last_config */
- dev_dbg(&client->dev, "(%d): Setting VID from GPIO11-15.\n",
- client->id);
+ dev_dbg(&client->dev, "Setting VID from GPIO11-15.\n");
data->vid = (data->gpio >> 11) & 0x1f;
data->valid = 1;
up(&data->update_lock);
@@ -1608,16 +1599,10 @@ int adm1026_detect(struct i2c_adapter *adapter, int address,
strlcpy(new_client->name, type_name, I2C_NAME_SIZE);
/* Fill in the remaining client fields */
- new_client->id = adm1026_id++;
data->type = kind;
data->valid = 0;
init_MUTEX(&data->update_lock);
- dev_dbg(&new_client->dev, "(%d): Assigning ID %d to %s at %d,0x%02x\n",
- new_client->id, new_client->id, new_client->name,
- i2c_adapter_id(new_client->adapter),
- new_client->addr);
-
/* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(new_client)))
goto exitfree;
diff --git a/drivers/i2c/chips/adm1031.c b/drivers/i2c/chips/adm1031.c
index 69f4d1e29a616..fc516c389bb53 100644
--- a/drivers/i2c/chips/adm1031.c
+++ b/drivers/i2c/chips/adm1031.c
@@ -24,6 +24,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
+#include <linux/jiffies.h>
#include <linux/i2c.h>
#include <linux/i2c-sensor.h>
@@ -110,8 +111,6 @@ static struct i2c_driver adm1031_driver = {
.detach_client = adm1031_detach_client,
};
-static int adm1031_id;
-
static inline u8 adm1031_read_value(struct i2c_client *client, u8 reg)
{
return i2c_smbus_read_byte_data(client, reg);
@@ -781,8 +780,6 @@ static int adm1031_detect(struct i2c_adapter *adapter, int address, int kind)
data->chip_type = kind;
strlcpy(new_client->name, name, I2C_NAME_SIZE);
-
- new_client->id = adm1031_id++;
data->valid = 0;
init_MUTEX(&data->update_lock);
@@ -888,8 +885,8 @@ static struct adm1031_data *adm1031_update_device(struct device *dev)
down(&data->update_lock);
- if ((jiffies - data->last_updated > HZ + HZ / 2) ||
- (jiffies < data->last_updated) || !data->valid) {
+ if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
+ || !data->valid) {
dev_dbg(&client->dev, "Starting adm1031 update\n");
for (chan = 0;
diff --git a/drivers/i2c/chips/asb100.c b/drivers/i2c/chips/asb100.c
index 7c6d896e96d79..a02d17236e047 100644
--- a/drivers/i2c/chips/asb100.c
+++ b/drivers/i2c/chips/asb100.c
@@ -36,17 +36,12 @@
asb100 7 3 1 4 0x31 0x0694 yes no
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/slab.h>
-#include <linux/ioport.h>
-#include <linux/types.h>
#include <linux/i2c.h>
#include <linux/i2c-sensor.h>
#include <linux/i2c-vid.h>
#include <linux/init.h>
-#include <asm/errno.h>
-#include <asm/io.h>
#include "lm75.h"
/*
@@ -970,8 +965,8 @@ static struct asb100_data *asb100_update_device(struct device *dev)
down(&data->update_lock);
- if (time_after(jiffies - data->last_updated, (unsigned long)(HZ+HZ/2))
- || time_before(jiffies, data->last_updated) || !data->valid) {
+ if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
+ || !data->valid) {
dev_dbg(&client->dev, "starting device update...\n");
diff --git a/drivers/i2c/chips/ds1621.c b/drivers/i2c/chips/ds1621.c
index 753bfc6a31772..213c717a756bf 100644
--- a/drivers/i2c/chips/ds1621.c
+++ b/drivers/i2c/chips/ds1621.c
@@ -24,6 +24,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
+#include <linux/jiffies.h>
#include <linux/i2c.h>
#include <linux/i2c-sensor.h>
#include "lm75.h"
@@ -95,8 +96,6 @@ static struct i2c_driver ds1621_driver = {
.detach_client = ds1621_detach_client,
};
-static int ds1621_id;
-
/* All registers are word-sized, except for the configuration register.
DS1621 uses a high-byte first convention, which is exactly opposite to
the usual practice. */
@@ -236,8 +235,6 @@ int ds1621_detect(struct i2c_adapter *adapter, int address,
/* Fill in remaining client fields and put it into the global list */
strlcpy(new_client->name, "ds1621", I2C_NAME_SIZE);
-
- new_client->id = ds1621_id++;
data->valid = 0;
init_MUTEX(&data->update_lock);
@@ -288,8 +285,8 @@ static struct ds1621_data *ds1621_update_client(struct device *dev)
down(&data->update_lock);
- if ((jiffies - data->last_updated > HZ + HZ / 2) ||
- (jiffies < data->last_updated) || !data->valid) {
+ if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
+ || !data->valid) {
dev_dbg(&client->dev, "Starting ds1621 update\n");
diff --git a/drivers/i2c/chips/eeprom.c b/drivers/i2c/chips/eeprom.c
index 31ea1300ec9c7..f126d011cfee2 100644
--- a/drivers/i2c/chips/eeprom.c
+++ b/drivers/i2c/chips/eeprom.c
@@ -32,6 +32,7 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/sched.h>
+#include <linux/jiffies.h>
#include <linux/i2c.h>
#include <linux/i2c-sensor.h>
@@ -86,8 +87,7 @@ static void eeprom_update_client(struct i2c_client *client, u8 slice)
down(&data->update_lock);
if (!(data->valid & (1 << slice)) ||
- (jiffies - data->last_updated[slice] > 300 * HZ) ||
- (jiffies < data->last_updated[slice])) {
+ time_after(jiffies, data->last_updated[slice] + 300 * HZ)) {
dev_dbg(&client->dev, "Starting eeprom update, slice %u\n", slice);
if (i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_I2C_BLOCK)) {
@@ -130,7 +130,8 @@ static ssize_t eeprom_read(struct kobject *kobj, char *buf, loff_t off, size_t c
/* Hide Vaio security settings to regular users (16 first bytes) */
if (data->nature == VAIO && off < 16 && !capable(CAP_SYS_ADMIN)) {
- int in_row1 = 16 - off;
+ size_t in_row1 = 16 - off;
+ in_row1 = min(in_row1, count);
memset(buf, 0, in_row1);
if (count - in_row1 > 0)
memcpy(buf + in_row1, &data->data[16], count - in_row1);
diff --git a/drivers/i2c/chips/fscher.c b/drivers/i2c/chips/fscher.c
index f8e18c9ae8427..ad6a0a7467801 100644
--- a/drivers/i2c/chips/fscher.c
+++ b/drivers/i2c/chips/fscher.c
@@ -30,6 +30,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
+#include <linux/jiffies.h>
#include <linux/i2c.h>
#include <linux/i2c-sensor.h>
@@ -151,12 +152,6 @@ struct fscher_data {
};
/*
- * Internal variables
- */
-
-static int fscher_id;
-
-/*
* Sysfs stuff
*/
@@ -337,7 +332,6 @@ static int fscher_detect(struct i2c_adapter *adapter, int address, int kind)
/* Fill in the remaining client fields and put it into the
* global list */
strlcpy(new_client->name, "fscher", I2C_NAME_SIZE);
- new_client->id = fscher_id++;
data->valid = 0;
init_MUTEX(&data->update_lock);
@@ -418,8 +412,7 @@ static struct fscher_data *fscher_update_device(struct device *dev)
down(&data->update_lock);
- if ((jiffies - data->last_updated > 2 * HZ) ||
- (jiffies < data->last_updated) || !data->valid) {
+ if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) {
dev_dbg(&client->dev, "Starting fscher update\n");
diff --git a/drivers/i2c/chips/fscpos.c b/drivers/i2c/chips/fscpos.c
new file mode 100644
index 0000000000000..09216d3711d93
--- /dev/null
+++ b/drivers/i2c/chips/fscpos.c
@@ -0,0 +1,631 @@
+/*
+ fscpos.c - Kernel module for hardware monitoring with FSC Poseidon chips
+ Copyright (C) 2004, 2005 Stefan Ott <stefan@desire.ch>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/*
+ fujitsu siemens poseidon chip,
+ module based on the old fscpos module by Hermann Jung <hej@odn.de> and
+ the fscher module by Reinhard Nissl <rnissl@gmx.de>
+
+ original module based on lm80.c
+ Copyright (C) 1998, 1999 Frodo Looijaard <frodol@dds.nl>
+ and Philip Edelbrock <phil@netroedge.com>
+
+ Thanks to Jean Delvare for reviewing my code and suggesting a lot of
+ improvements.
+*/
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/i2c-sensor.h>
+#include <linux/init.h>
+
+/*
+ * Addresses to scan
+ */
+static unsigned short normal_i2c[] = { 0x73, I2C_CLIENT_END };
+static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
+
+/*
+ * Insmod parameters
+ */
+SENSORS_INSMOD_1(fscpos);
+
+/*
+ * The FSCPOS registers
+ */
+
+/* chip identification */
+#define FSCPOS_REG_IDENT_0 0x00
+#define FSCPOS_REG_IDENT_1 0x01
+#define FSCPOS_REG_IDENT_2 0x02
+#define FSCPOS_REG_REVISION 0x03
+
+/* global control and status */
+#define FSCPOS_REG_EVENT_STATE 0x04
+#define FSCPOS_REG_CONTROL 0x05
+
+/* watchdog */
+#define FSCPOS_REG_WDOG_PRESET 0x28
+#define FSCPOS_REG_WDOG_STATE 0x23
+#define FSCPOS_REG_WDOG_CONTROL 0x21
+
+/* voltages */
+#define FSCPOS_REG_VOLT_12 0x45
+#define FSCPOS_REG_VOLT_5 0x42
+#define FSCPOS_REG_VOLT_BATT 0x48
+
+/* fans - the chip does not support minimum speed for fan2 */
+static u8 FSCPOS_REG_PWM[] = { 0x55, 0x65 };
+static u8 FSCPOS_REG_FAN_ACT[] = { 0x0e, 0x6b, 0xab };
+static u8 FSCPOS_REG_FAN_STATE[] = { 0x0d, 0x62, 0xa2 };
+static u8 FSCPOS_REG_FAN_RIPPLE[] = { 0x0f, 0x6f, 0xaf };
+
+/* temperatures */
+static u8 FSCPOS_REG_TEMP_ACT[] = { 0x64, 0x32, 0x35 };
+static u8 FSCPOS_REG_TEMP_STATE[] = { 0x71, 0x81, 0x91 };
+
+/*
+ * Functions declaration
+ */
+static int fscpos_attach_adapter(struct i2c_adapter *adapter);
+static int fscpos_detect(struct i2c_adapter *adapter, int address, int kind);
+static int fscpos_detach_client(struct i2c_client *client);
+
+static int fscpos_read_value(struct i2c_client *client, u8 register);
+static int fscpos_write_value(struct i2c_client *client, u8 register, u8 value);
+static struct fscpos_data *fscpos_update_device(struct device *dev);
+static void fscpos_init_client(struct i2c_client *client);
+
+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",
+ .id = I2C_DRIVERID_FSCPOS,
+ .flags = I2C_DF_NOTIFY,
+ .attach_adapter = fscpos_attach_adapter,
+ .detach_client = fscpos_detach_client,
+};
+
+/*
+ * Client data (each client gets its own)
+ */
+struct fscpos_data {
+ struct i2c_client client;
+ struct semaphore update_lock;
+ char valid; /* 0 until following fields are valid */
+ unsigned long last_updated; /* In jiffies */
+
+ /* register values */
+ u8 revision; /* revision of chip */
+ u8 global_event; /* global event status */
+ u8 global_control; /* global control register */
+ u8 wdog_control; /* watchdog control */
+ u8 wdog_state; /* watchdog status */
+ u8 wdog_preset; /* watchdog preset */
+ u8 volt[3]; /* 12, 5, battery current */
+ u8 temp_act[3]; /* temperature */
+ u8 temp_status[3]; /* status of sensor */
+ u8 fan_act[3]; /* fans revolutions per second */
+ u8 fan_status[3]; /* fan status */
+ u8 pwm[2]; /* fan min value for rps */
+ u8 fan_ripple[3]; /* divider for rps */
+};
+
+/* Temperature */
+#define TEMP_FROM_REG(val) (((val) - 128) * 1000)
+
+static ssize_t show_temp_input(struct fscpos_data *data, char *buf, int nr)
+{
+ return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_act[nr - 1]));
+}
+
+static ssize_t show_temp_status(struct fscpos_data *data, char *buf, int nr)
+{
+ /* bits 2..7 reserved => mask with 0x03 */
+ return sprintf(buf, "%u\n", data->temp_status[nr - 1] & 0x03);
+}
+
+static ssize_t show_temp_reset(struct fscpos_data *data, char *buf, int nr)
+{
+ return sprintf(buf, "1\n");
+}
+
+static ssize_t set_temp_reset(struct i2c_client *client, struct fscpos_data
+ *data, const char *buf, size_t count, int nr, int reg)
+{
+ unsigned long v = simple_strtoul(buf, NULL, 10);
+ if (v != 1) {
+ dev_err(&client->dev, "temp_reset value %ld not supported. "
+ "Use 1 to reset the alarm!\n", v);
+ return -EINVAL;
+ }
+
+ dev_info(&client->dev, "You used the temp_reset feature which has not "
+ "been proplerly tested. Please report your "
+ "experience to the module author.\n");
+
+ /* Supported value: 2 (clears the status) */
+ fscpos_write_value(client, FSCPOS_REG_TEMP_STATE[nr], 2);
+ return count;
+}
+
+/* Fans */
+#define RPM_FROM_REG(val) ((val) * 60)
+
+static ssize_t show_fan_status(struct fscpos_data *data, char *buf, int nr)
+{
+ /* bits 0..1, 3..7 reserved => mask with 0x04 */
+ return sprintf(buf, "%u\n", data->fan_status[nr - 1] & 0x04);
+}
+
+static ssize_t show_fan_input(struct fscpos_data *data, char *buf, int nr)
+{
+ return sprintf(buf, "%u\n", RPM_FROM_REG(data->fan_act[nr - 1]));
+}
+
+static ssize_t show_fan_ripple(struct fscpos_data *data, char *buf, int nr)
+{
+ /* bits 2..7 reserved => mask with 0x03 */
+ return sprintf(buf, "%u\n", data->fan_ripple[nr - 1] & 0x03);
+}
+
+static ssize_t set_fan_ripple(struct i2c_client *client, struct fscpos_data
+ *data, const char *buf, size_t count, int nr, int reg)
+{
+ /* supported values: 2, 4, 8 */
+ unsigned long v = simple_strtoul(buf, NULL, 10);
+
+ switch (v) {
+ case 2: v = 1; break;
+ case 4: v = 2; break;
+ case 8: v = 3; break;
+ default:
+ dev_err(&client->dev, "fan_ripple value %ld not supported. "
+ "Must be one of 2, 4 or 8!\n", v);
+ return -EINVAL;
+ }
+
+ /* bits 2..7 reserved => mask with 0x03 */
+ data->fan_ripple[nr - 1] &= ~0x03;
+ data->fan_ripple[nr - 1] |= v;
+
+ fscpos_write_value(client, reg, data->fan_ripple[nr - 1]);
+ return count;
+}
+
+static ssize_t show_pwm(struct fscpos_data *data, char *buf, int nr)
+{
+ return sprintf(buf, "%u\n", data->pwm[nr - 1]);
+}
+
+static ssize_t set_pwm(struct i2c_client *client, struct fscpos_data *data,
+ const char *buf, size_t count, int nr, int reg)
+{
+ unsigned long v = simple_strtoul(buf, NULL, 10);
+
+ /* Range: 0..255 */
+ if (v < 0) v = 0;
+ if (v > 255) v = 255;
+
+ data->pwm[nr - 1] = v;
+ fscpos_write_value(client, reg, data->pwm[nr - 1]);
+ return count;
+}
+
+static void reset_fan_alarm(struct i2c_client *client, int nr)
+{
+ fscpos_write_value(client, FSCPOS_REG_FAN_STATE[nr], 4);
+}
+
+/* Volts */
+#define VOLT_FROM_REG(val, mult) ((val) * (mult) / 255)
+
+static ssize_t show_volt_12(struct device *dev, char *buf)
+{
+ struct fscpos_data *data = fscpos_update_device(dev);
+ return sprintf(buf, "%u\n", VOLT_FROM_REG(data->volt[0], 14200));
+}
+
+static ssize_t show_volt_5(struct device *dev, char *buf)
+{
+ struct fscpos_data *data = fscpos_update_device(dev);
+ return sprintf(buf, "%u\n", VOLT_FROM_REG(data->volt[1], 6600));
+}
+
+static ssize_t show_volt_batt(struct device *dev, char *buf)
+{
+ struct fscpos_data *data = fscpos_update_device(dev);
+ return sprintf(buf, "%u\n", VOLT_FROM_REG(data->volt[2], 3300));
+}
+
+/* Watchdog */
+static ssize_t show_wdog_control(struct fscpos_data *data, char *buf)
+{
+ /* bits 0..3 reserved, bit 6 write only => mask with 0xb0 */
+ return sprintf(buf, "%u\n", data->wdog_control & 0xb0);
+}
+
+static ssize_t set_wdog_control(struct i2c_client *client, struct fscpos_data
+ *data, const char *buf, size_t count, int reg)
+{
+ /* bits 0..3 reserved => mask with 0xf0 */
+ unsigned long v = simple_strtoul(buf, NULL, 10) & 0xf0;
+ data->wdog_control &= ~0xf0;
+ data->wdog_control |= v;
+
+ fscpos_write_value(client, reg, data->wdog_control);
+ return count;
+}
+
+static ssize_t show_wdog_state(struct fscpos_data *data, char *buf)
+{
+ /* bits 0, 2..7 reserved => mask with 0x02 */
+ return sprintf(buf, "%u\n", data->wdog_state & 0x02);
+}
+
+static ssize_t set_wdog_state(struct i2c_client *client, struct fscpos_data
+ *data, const char *buf, size_t count, int reg)
+{
+ unsigned long v = simple_strtoul(buf, NULL, 10) & 0x02;
+
+ /* Valid values: 2 (clear) */
+ if (v != 2) {
+ dev_err(&client->dev, "wdog_state value %ld not supported. "
+ "Must be 2 to clear the state!\n", v);
+ return -EINVAL;
+ }
+
+ data->wdog_state &= ~v;
+
+ fscpos_write_value(client, reg, v);
+ return count;
+}
+
+static ssize_t show_wdog_preset(struct fscpos_data *data, char *buf)
+{
+ return sprintf(buf, "%u\n", data->wdog_preset);
+}
+
+static ssize_t set_wdog_preset(struct i2c_client *client, struct fscpos_data
+ *data, const char *buf, size_t count, int reg)
+{
+ data->wdog_preset = simple_strtoul(buf, NULL, 10) & 0xff;
+
+ fscpos_write_value(client, reg, data->wdog_preset);
+ return count;
+}
+
+/* Event */
+static ssize_t show_event(struct device *dev, char *buf)
+{
+ /* bits 5..7 reserved => mask with 0x1f */
+ struct fscpos_data *data = fscpos_update_device(dev);
+ return sprintf(buf, "%u\n", data->global_event & 0x9b);
+}
+
+/*
+ * Sysfs stuff
+ */
+#define create_getter(kind, sub) \
+ static ssize_t sysfs_show_##kind##sub(struct device *dev, char *buf) \
+ { \
+ struct fscpos_data *data = fscpos_update_device(dev); \
+ return show_##kind##sub(data, buf); \
+ }
+
+#define create_getter_n(kind, offset, sub) \
+ static ssize_t sysfs_show_##kind##offset##sub(struct device *dev, char\
+ *buf) \
+ { \
+ struct fscpos_data *data = fscpos_update_device(dev); \
+ return show_##kind##sub(data, buf, offset); \
+ }
+
+#define create_setter(kind, sub, reg) \
+ static ssize_t sysfs_set_##kind##sub (struct device *dev, const char \
+ *buf, size_t count) \
+ { \
+ struct i2c_client *client = to_i2c_client(dev); \
+ struct fscpos_data *data = i2c_get_clientdata(client); \
+ return set_##kind##sub(client, data, buf, count, reg); \
+ }
+
+#define create_setter_n(kind, offset, sub, reg) \
+ static ssize_t sysfs_set_##kind##offset##sub (struct device *dev, \
+ const char *buf, size_t count) \
+ { \
+ struct i2c_client *client = to_i2c_client(dev); \
+ struct fscpos_data *data = i2c_get_clientdata(client); \
+ return set_##kind##sub(client, data, buf, count, offset, reg);\
+ }
+
+#define create_sysfs_device_ro(kind, sub, offset) \
+ static DEVICE_ATTR(kind##offset##sub, S_IRUGO, \
+ sysfs_show_##kind##offset##sub, NULL);
+
+#define create_sysfs_device_rw(kind, sub, offset) \
+ static DEVICE_ATTR(kind##offset##sub, S_IRUGO | S_IWUSR, \
+ sysfs_show_##kind##offset##sub, sysfs_set_##kind##offset##sub);
+
+#define sysfs_ro_n(kind, sub, offset) \
+ create_getter_n(kind, offset, sub); \
+ create_sysfs_device_ro(kind, sub, offset);
+
+#define sysfs_rw_n(kind, sub, offset, reg) \
+ create_getter_n(kind, offset, sub); \
+ create_setter_n(kind, offset, sub, reg); \
+ create_sysfs_device_rw(kind, sub, offset);
+
+#define sysfs_rw(kind, sub, reg) \
+ create_getter(kind, sub); \
+ create_setter(kind, sub, reg); \
+ create_sysfs_device_rw(kind, sub,);
+
+#define sysfs_fan_with_min(offset, reg_status, reg_ripple, reg_min) \
+ sysfs_fan(offset, reg_status, reg_ripple); \
+ sysfs_rw_n(pwm,, offset, reg_min);
+
+#define sysfs_fan(offset, reg_status, reg_ripple) \
+ sysfs_ro_n(fan, _input, offset); \
+ sysfs_ro_n(fan, _status, offset); \
+ sysfs_rw_n(fan, _ripple, offset, reg_ripple);
+
+#define sysfs_temp(offset, reg_status) \
+ sysfs_ro_n(temp, _input, offset); \
+ sysfs_ro_n(temp, _status, offset); \
+ sysfs_rw_n(temp, _reset, offset, reg_status);
+
+#define sysfs_watchdog(reg_wdog_preset, reg_wdog_state, reg_wdog_control) \
+ sysfs_rw(wdog, _control, reg_wdog_control); \
+ sysfs_rw(wdog, _preset, reg_wdog_preset); \
+ sysfs_rw(wdog, _state, reg_wdog_state);
+
+sysfs_fan_with_min(1, FSCPOS_REG_FAN_STATE[0], FSCPOS_REG_FAN_RIPPLE[0],
+ FSCPOS_REG_PWM[0]);
+sysfs_fan_with_min(2, FSCPOS_REG_FAN_STATE[1], FSCPOS_REG_FAN_RIPPLE[1],
+ FSCPOS_REG_PWM[1]);
+sysfs_fan(3, FSCPOS_REG_FAN_STATE[2], FSCPOS_REG_FAN_RIPPLE[2]);
+
+sysfs_temp(1, FSCPOS_REG_TEMP_STATE[0]);
+sysfs_temp(2, FSCPOS_REG_TEMP_STATE[1]);
+sysfs_temp(3, FSCPOS_REG_TEMP_STATE[2]);
+
+sysfs_watchdog(FSCPOS_REG_WDOG_PRESET, FSCPOS_REG_WDOG_STATE,
+ FSCPOS_REG_WDOG_CONTROL);
+
+static DEVICE_ATTR(event, S_IRUGO, show_event, NULL);
+static DEVICE_ATTR(in0_input, S_IRUGO, show_volt_12, NULL);
+static DEVICE_ATTR(in1_input, S_IRUGO, show_volt_5, NULL);
+static DEVICE_ATTR(in2_input, S_IRUGO, show_volt_batt, NULL);
+
+static int fscpos_attach_adapter(struct i2c_adapter *adapter)
+{
+ if (!(adapter->class & I2C_CLASS_HWMON))
+ return 0;
+ return i2c_detect(adapter, &addr_data, fscpos_detect);
+}
+
+int fscpos_detect(struct i2c_adapter *adapter, int address, int kind)
+{
+ struct i2c_client *new_client;
+ struct fscpos_data *data;
+ int err = 0;
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+ goto exit;
+
+ /*
+ * OK. For now, we presume we have a valid client. We now create the
+ * client structure, even though we cannot fill it completely yet.
+ * But it allows us to access fscpos_{read,write}_value.
+ */
+
+ if (!(data = kmalloc(sizeof(struct fscpos_data), GFP_KERNEL))) {
+ err = -ENOMEM;
+ goto exit;
+ }
+ memset(data, 0, sizeof(struct fscpos_data));
+
+ new_client = &data->client;
+ i2c_set_clientdata(new_client, data);
+ new_client->addr = address;
+ new_client->adapter = adapter;
+ new_client->driver = &fscpos_driver;
+ new_client->flags = 0;
+
+ /* Do the remaining detection unless force or force_fscpos parameter */
+ if (kind < 0) {
+ if ((fscpos_read_value(new_client, FSCPOS_REG_IDENT_0)
+ != 0x50) /* 'P' */
+ || (fscpos_read_value(new_client, FSCPOS_REG_IDENT_1)
+ != 0x45) /* 'E' */
+ || (fscpos_read_value(new_client, FSCPOS_REG_IDENT_2)
+ != 0x47))/* 'G' */
+ {
+ dev_dbg(&new_client->dev, "fscpos detection failed\n");
+ goto exit_free;
+ }
+ }
+
+ /* Fill in the remaining client fields and put it in the global list */
+ strlcpy(new_client->name, "fscpos", I2C_NAME_SIZE);
+
+ data->valid = 0;
+ init_MUTEX(&data->update_lock);
+
+ /* Tell the I2C layer a new client has arrived */
+ if ((err = i2c_attach_client(new_client)))
+ goto exit_free;
+
+ /* Inizialize the fscpos chip */
+ fscpos_init_client(new_client);
+
+ /* Announce that the chip was found */
+ dev_info(&new_client->dev, "Found fscpos chip, rev %u\n", data->revision);
+
+ /* Register sysfs hooks */
+ device_create_file(&new_client->dev, &dev_attr_event);
+ device_create_file(&new_client->dev, &dev_attr_in0_input);
+ device_create_file(&new_client->dev, &dev_attr_in1_input);
+ device_create_file(&new_client->dev, &dev_attr_in2_input);
+ device_create_file(&new_client->dev, &dev_attr_wdog_control);
+ device_create_file(&new_client->dev, &dev_attr_wdog_preset);
+ device_create_file(&new_client->dev, &dev_attr_wdog_state);
+ device_create_file(&new_client->dev, &dev_attr_temp1_input);
+ device_create_file(&new_client->dev, &dev_attr_temp1_status);
+ device_create_file(&new_client->dev, &dev_attr_temp1_reset);
+ device_create_file(&new_client->dev, &dev_attr_temp2_input);
+ device_create_file(&new_client->dev, &dev_attr_temp2_status);
+ device_create_file(&new_client->dev, &dev_attr_temp2_reset);
+ device_create_file(&new_client->dev, &dev_attr_temp3_input);
+ device_create_file(&new_client->dev, &dev_attr_temp3_status);
+ device_create_file(&new_client->dev, &dev_attr_temp3_reset);
+ device_create_file(&new_client->dev, &dev_attr_fan1_input);
+ device_create_file(&new_client->dev, &dev_attr_fan1_status);
+ device_create_file(&new_client->dev, &dev_attr_fan1_ripple);
+ device_create_file(&new_client->dev, &dev_attr_pwm1);
+ device_create_file(&new_client->dev, &dev_attr_fan2_input);
+ device_create_file(&new_client->dev, &dev_attr_fan2_status);
+ device_create_file(&new_client->dev, &dev_attr_fan2_ripple);
+ device_create_file(&new_client->dev, &dev_attr_pwm2);
+ device_create_file(&new_client->dev, &dev_attr_fan3_input);
+ device_create_file(&new_client->dev, &dev_attr_fan3_status);
+ device_create_file(&new_client->dev, &dev_attr_fan3_ripple);
+
+ return 0;
+
+exit_free:
+ kfree(data);
+exit:
+ return err;
+}
+
+static int fscpos_detach_client(struct i2c_client *client)
+{
+ int err;
+
+ if ((err = i2c_detach_client(client))) {
+ dev_err(&client->dev, "Client deregistration failed, client"
+ " not detached.\n");
+ return err;
+ }
+ kfree(i2c_get_clientdata(client));
+ return 0;
+}
+
+static int fscpos_read_value(struct i2c_client *client, u8 reg)
+{
+ dev_dbg(&client->dev, "Read reg 0x%02x\n", reg);
+ return i2c_smbus_read_byte_data(client, reg);
+}
+
+static int fscpos_write_value(struct i2c_client *client, u8 reg, u8 value)
+{
+ dev_dbg(&client->dev, "Write reg 0x%02x, val 0x%02x\n", reg, value);
+ return i2c_smbus_write_byte_data(client, reg, value);
+}
+
+/* Called when we have found a new FSCPOS chip */
+static void fscpos_init_client(struct i2c_client *client)
+{
+ struct fscpos_data *data = i2c_get_clientdata(client);
+
+ /* read revision from chip */
+ data->revision = fscpos_read_value(client, FSCPOS_REG_REVISION);
+}
+
+static struct fscpos_data *fscpos_update_device(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct fscpos_data *data = i2c_get_clientdata(client);
+
+ down(&data->update_lock);
+
+ if ((jiffies - data->last_updated > 2 * HZ) ||
+ (jiffies < data->last_updated) || !data->valid) {
+ int i;
+
+ dev_dbg(&client->dev, "Starting fscpos update\n");
+
+ for (i = 0; i < 3; i++) {
+ data->temp_act[i] = fscpos_read_value(client,
+ FSCPOS_REG_TEMP_ACT[i]);
+ data->temp_status[i] = fscpos_read_value(client,
+ FSCPOS_REG_TEMP_STATE[i]);
+ data->fan_act[i] = fscpos_read_value(client,
+ FSCPOS_REG_FAN_ACT[i]);
+ data->fan_status[i] = fscpos_read_value(client,
+ FSCPOS_REG_FAN_STATE[i]);
+ data->fan_ripple[i] = fscpos_read_value(client,
+ FSCPOS_REG_FAN_RIPPLE[i]);
+ if (i < 2) {
+ /* fan2_min is not supported by the chip */
+ data->pwm[i] = fscpos_read_value(client,
+ FSCPOS_REG_PWM[i]);
+ }
+ /* reset fan status if speed is back to > 0 */
+ if (data->fan_status[i] != 0 && data->fan_act[i] > 0) {
+ reset_fan_alarm(client, i);
+ }
+ }
+
+ data->volt[0] = fscpos_read_value(client, FSCPOS_REG_VOLT_12);
+ data->volt[1] = fscpos_read_value(client, FSCPOS_REG_VOLT_5);
+ data->volt[2] = fscpos_read_value(client, FSCPOS_REG_VOLT_BATT);
+
+ data->wdog_preset = fscpos_read_value(client,
+ FSCPOS_REG_WDOG_PRESET);
+ data->wdog_state = fscpos_read_value(client,
+ FSCPOS_REG_WDOG_STATE);
+ data->wdog_control = fscpos_read_value(client,
+ FSCPOS_REG_WDOG_CONTROL);
+
+ data->global_event = fscpos_read_value(client,
+ FSCPOS_REG_EVENT_STATE);
+
+ data->last_updated = jiffies;
+ data->valid = 1;
+ }
+ up(&data->update_lock);
+ return data;
+}
+
+static int __init sm_fscpos_init(void)
+{
+ return i2c_add_driver(&fscpos_driver);
+}
+
+static void __exit sm_fscpos_exit(void)
+{
+ i2c_del_driver(&fscpos_driver);
+}
+
+MODULE_AUTHOR("Stefan Ott <stefan@desire.ch> based on work from Hermann Jung "
+ "<hej@odn.de>, Frodo Looijaard <frodol@dds.nl>"
+ " and Philip Edelbrock <phil@netroedge.com>");
+MODULE_DESCRIPTION("fujitsu siemens poseidon chip driver");
+MODULE_LICENSE("GPL");
+
+module_init(sm_fscpos_init);
+module_exit(sm_fscpos_exit);
diff --git a/drivers/i2c/chips/gl518sm.c b/drivers/i2c/chips/gl518sm.c
index c4e914ba2a3be..a9c40b6f8342f 100644
--- a/drivers/i2c/chips/gl518sm.c
+++ b/drivers/i2c/chips/gl518sm.c
@@ -40,6 +40,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
+#include <linux/jiffies.h>
#include <linux/i2c.h>
#include <linux/i2c-sensor.h>
@@ -159,12 +160,6 @@ static struct i2c_driver gl518_driver = {
};
/*
- * Internal variables
- */
-
-static int gl518_id;
-
-/*
* Sysfs stuff
*/
@@ -396,7 +391,6 @@ static int gl518_detect(struct i2c_adapter *adapter, int address, int kind)
/* Fill in the remaining client fields */
strlcpy(new_client->name, "gl518sm", I2C_NAME_SIZE);
- new_client->id = gl518_id++;
data->type = kind;
data->valid = 0;
init_MUTEX(&data->update_lock);
@@ -512,8 +506,8 @@ static struct gl518_data *gl518_update_device(struct device *dev)
down(&data->update_lock);
- if ((jiffies - data->last_updated > HZ + HZ / 2) ||
- (jiffies < data->last_updated) || !data->valid) {
+ if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
+ || !data->valid) {
dev_dbg(&client->dev, "Starting gl518 update\n");
data->alarms = gl518_read_value(client, GL518_REG_INT);
diff --git a/drivers/i2c/chips/gl520sm.c b/drivers/i2c/chips/gl520sm.c
new file mode 100644
index 0000000000000..652603775772f
--- /dev/null
+++ b/drivers/i2c/chips/gl520sm.c
@@ -0,0 +1,754 @@
+/*
+ gl520sm.c - Part of lm_sensors, Linux kernel modules for hardware
+ monitoring
+ Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl>,
+ Kyösti Mälkki <kmalkki@cc.hut.fi>
+ Copyright (c) 2005 Maarten Deprez <maartendeprez@users.sourceforge.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/i2c-sensor.h>
+#include <linux/i2c-vid.h>
+
+/* Type of the extra sensor */
+static unsigned short extra_sensor_type;
+module_param(extra_sensor_type, ushort, 0);
+MODULE_PARM_DESC(extra_sensor_type, "Type of extra sensor (0=autodetect, 1=temperature, 2=voltage)");
+
+/* Addresses to scan */
+static unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END };
+static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
+
+/* Insmod parameters */
+SENSORS_INSMOD_1(gl520sm);
+
+/* Many GL520 constants specified below
+One of the inputs can be configured as either temp or voltage.
+That's why _TEMP2 and _IN4 access the same register
+*/
+
+/* The GL520 registers */
+#define GL520_REG_CHIP_ID 0x00
+#define GL520_REG_REVISION 0x01
+#define GL520_REG_CONF 0x03
+#define GL520_REG_MASK 0x11
+
+#define GL520_REG_VID_INPUT 0x02
+
+#define GL520_REG_IN0_INPUT 0x15
+#define GL520_REG_IN0_LIMIT 0x0c
+#define GL520_REG_IN0_MIN GL520_REG_IN0_LIMIT
+#define GL520_REG_IN0_MAX GL520_REG_IN0_LIMIT
+
+#define GL520_REG_IN1_INPUT 0x14
+#define GL520_REG_IN1_LIMIT 0x09
+#define GL520_REG_IN1_MIN GL520_REG_IN1_LIMIT
+#define GL520_REG_IN1_MAX GL520_REG_IN1_LIMIT
+
+#define GL520_REG_IN2_INPUT 0x13
+#define GL520_REG_IN2_LIMIT 0x0a
+#define GL520_REG_IN2_MIN GL520_REG_IN2_LIMIT
+#define GL520_REG_IN2_MAX GL520_REG_IN2_LIMIT
+
+#define GL520_REG_IN3_INPUT 0x0d
+#define GL520_REG_IN3_LIMIT 0x0b
+#define GL520_REG_IN3_MIN GL520_REG_IN3_LIMIT
+#define GL520_REG_IN3_MAX GL520_REG_IN3_LIMIT
+
+#define GL520_REG_IN4_INPUT 0x0e
+#define GL520_REG_IN4_MAX 0x17
+#define GL520_REG_IN4_MIN 0x18
+
+#define GL520_REG_TEMP1_INPUT 0x04
+#define GL520_REG_TEMP1_MAX 0x05
+#define GL520_REG_TEMP1_MAX_HYST 0x06
+
+#define GL520_REG_TEMP2_INPUT 0x0e
+#define GL520_REG_TEMP2_MAX 0x17
+#define GL520_REG_TEMP2_MAX_HYST 0x18
+
+#define GL520_REG_FAN_INPUT 0x07
+#define GL520_REG_FAN_MIN 0x08
+#define GL520_REG_FAN_DIV 0x0f
+#define GL520_REG_FAN_OFF GL520_REG_FAN_DIV
+
+#define GL520_REG_ALARMS 0x12
+#define GL520_REG_BEEP_MASK 0x10
+#define GL520_REG_BEEP_ENABLE GL520_REG_CONF
+
+/*
+ * Function declarations
+ */
+
+static int gl520_attach_adapter(struct i2c_adapter *adapter);
+static int gl520_detect(struct i2c_adapter *adapter, int address, int kind);
+static void gl520_init_client(struct i2c_client *client);
+static int gl520_detach_client(struct i2c_client *client);
+static int gl520_read_value(struct i2c_client *client, u8 reg);
+static int gl520_write_value(struct i2c_client *client, u8 reg, u16 value);
+static struct gl520_data *gl520_update_device(struct device *dev);
+
+/* Driver data */
+static struct i2c_driver gl520_driver = {
+ .owner = THIS_MODULE,
+ .name = "gl520sm",
+ .id = I2C_DRIVERID_GL520,
+ .flags = I2C_DF_NOTIFY,
+ .attach_adapter = gl520_attach_adapter,
+ .detach_client = gl520_detach_client,
+};
+
+/* Client data */
+struct gl520_data {
+ struct i2c_client client;
+ struct semaphore update_lock;
+ char valid; /* zero until the following fields are valid */
+ unsigned long last_updated; /* in jiffies */
+
+ u8 vid;
+ u8 vrm;
+ u8 in_input[5]; /* [0] = VVD */
+ u8 in_min[5]; /* [0] = VDD */
+ u8 in_max[5]; /* [0] = VDD */
+ u8 fan_input[2];
+ u8 fan_min[2];
+ u8 fan_div[2];
+ u8 fan_off;
+ u8 temp_input[2];
+ u8 temp_max[2];
+ u8 temp_max_hyst[2];
+ u8 alarms;
+ u8 beep_enable;
+ u8 beep_mask;
+ u8 alarm_mask;
+ u8 two_temps;
+};
+
+/*
+ * Sysfs stuff
+ */
+
+#define sysfs_r(type, n, item, reg) \
+static ssize_t get_##type##item (struct gl520_data *, char *, int); \
+static ssize_t get_##type##n##item (struct device *, char *); \
+static ssize_t get_##type##n##item (struct device *dev, char *buf) \
+{ \
+ struct gl520_data *data = gl520_update_device(dev); \
+ return get_##type##item(data, buf, (n)); \
+}
+
+#define sysfs_w(type, n, item, reg) \
+static ssize_t set_##type##item (struct i2c_client *, struct gl520_data *, const char *, size_t, int, int); \
+static ssize_t set_##type##n##item (struct device *, const char *, size_t); \
+static ssize_t set_##type##n##item (struct device *dev, const char *buf, size_t count) \
+{ \
+ struct i2c_client *client = to_i2c_client(dev); \
+ struct gl520_data *data = i2c_get_clientdata(client); \
+ return set_##type##item(client, data, buf, count, (n), reg); \
+}
+
+#define sysfs_rw_n(type, n, item, reg) \
+sysfs_r(type, n, item, reg) \
+sysfs_w(type, n, item, reg) \
+static DEVICE_ATTR(type##n##item, S_IRUGO | S_IWUSR, get_##type##n##item, set_##type##n##item);
+
+#define sysfs_ro_n(type, n, item, reg) \
+sysfs_r(type, n, item, reg) \
+static DEVICE_ATTR(type##n##item, S_IRUGO, get_##type##n##item, NULL);
+
+#define sysfs_rw(type, item, reg) \
+sysfs_r(type, 0, item, reg) \
+sysfs_w(type, 0, item, reg) \
+static DEVICE_ATTR(type##item, S_IRUGO | S_IWUSR, get_##type##0##item, set_##type##0##item);
+
+#define sysfs_ro(type, item, reg) \
+sysfs_r(type, 0, item, reg) \
+static DEVICE_ATTR(type##item, S_IRUGO, get_##type##0##item, NULL);
+
+
+#define sysfs_vid(n) \
+sysfs_ro_n(cpu, n, _vid, GL520_REG_VID_INPUT)
+
+#define device_create_file_vid(client, n) \
+device_create_file(&client->dev, &dev_attr_cpu##n##_vid)
+
+#define sysfs_in(n) \
+sysfs_ro_n(in, n, _input, GL520_REG_IN##n##INPUT) \
+sysfs_rw_n(in, n, _min, GL520_REG_IN##n##_MIN) \
+sysfs_rw_n(in, n, _max, GL520_REG_IN##n##_MAX) \
+
+#define device_create_file_in(client, n) \
+({device_create_file(&client->dev, &dev_attr_in##n##_input); \
+device_create_file(&client->dev, &dev_attr_in##n##_min); \
+device_create_file(&client->dev, &dev_attr_in##n##_max);})
+
+#define sysfs_fan(n) \
+sysfs_ro_n(fan, n, _input, GL520_REG_FAN_INPUT) \
+sysfs_rw_n(fan, n, _min, GL520_REG_FAN_MIN) \
+sysfs_rw_n(fan, n, _div, GL520_REG_FAN_DIV)
+
+#define device_create_file_fan(client, n) \
+({device_create_file(&client->dev, &dev_attr_fan##n##_input); \
+device_create_file(&client->dev, &dev_attr_fan##n##_min); \
+device_create_file(&client->dev, &dev_attr_fan##n##_div);})
+
+#define sysfs_fan_off(n) \
+sysfs_rw_n(fan, n, _off, GL520_REG_FAN_OFF) \
+
+#define device_create_file_fan_off(client, n) \
+device_create_file(&client->dev, &dev_attr_fan##n##_off)
+
+#define sysfs_temp(n) \
+sysfs_ro_n(temp, n, _input, GL520_REG_TEMP##n##_INPUT) \
+sysfs_rw_n(temp, n, _max, GL520_REG_TEMP##n##_MAX) \
+sysfs_rw_n(temp, n, _max_hyst, GL520_REG_TEMP##n##_MAX_HYST)
+
+#define device_create_file_temp(client, n) \
+({device_create_file(&client->dev, &dev_attr_temp##n##_input); \
+device_create_file(&client->dev, &dev_attr_temp##n##_max); \
+device_create_file(&client->dev, &dev_attr_temp##n##_max_hyst);})
+
+#define sysfs_alarms() \
+sysfs_ro(alarms, , GL520_REG_ALARMS) \
+sysfs_rw(beep_enable, , GL520_REG_BEEP_ENABLE) \
+sysfs_rw(beep_mask, , GL520_REG_BEEP_MASK)
+
+#define device_create_file_alarms(client) \
+({device_create_file(&client->dev, &dev_attr_alarms); \
+device_create_file(&client->dev, &dev_attr_beep_enable); \
+device_create_file(&client->dev, &dev_attr_beep_mask);})
+
+
+sysfs_vid(0)
+
+sysfs_in(0)
+sysfs_in(1)
+sysfs_in(2)
+sysfs_in(3)
+sysfs_in(4)
+
+sysfs_fan(1)
+sysfs_fan(2)
+sysfs_fan_off(1)
+
+sysfs_temp(1)
+sysfs_temp(2)
+
+sysfs_alarms()
+
+
+static ssize_t get_cpu_vid(struct gl520_data *data, char *buf, int n)
+{
+ return sprintf(buf, "%u\n", vid_from_reg(data->vid, data->vrm));
+}
+
+#define VDD_FROM_REG(val) (((val)*95+2)/4)
+#define VDD_TO_REG(val) (SENSORS_LIMIT((((val)*4+47)/95),0,255))
+
+#define IN_FROM_REG(val) ((val)*19)
+#define IN_TO_REG(val) (SENSORS_LIMIT((((val)+9)/19),0,255))
+
+static ssize_t get_in_input(struct gl520_data *data, char *buf, int n)
+{
+ u8 r = data->in_input[n];
+
+ if (n == 0)
+ return sprintf(buf, "%d\n", VDD_FROM_REG(r));
+ else
+ return sprintf(buf, "%d\n", IN_FROM_REG(r));
+}
+
+static ssize_t get_in_min(struct gl520_data *data, char *buf, int n)
+{
+ u8 r = data->in_min[n];
+
+ if (n == 0)
+ return sprintf(buf, "%d\n", VDD_FROM_REG(r));
+ else
+ return sprintf(buf, "%d\n", IN_FROM_REG(r));
+}
+
+static ssize_t get_in_max(struct gl520_data *data, char *buf, int n)
+{
+ u8 r = data->in_max[n];
+
+ if (n == 0)
+ return sprintf(buf, "%d\n", VDD_FROM_REG(r));
+ else
+ return sprintf(buf, "%d\n", IN_FROM_REG(r));
+}
+
+static ssize_t set_in_min(struct i2c_client *client, struct gl520_data *data, const char *buf, size_t count, int n, int reg)
+{
+ long v = simple_strtol(buf, NULL, 10);
+ u8 r;
+
+ if (n == 0)
+ r = VDD_TO_REG(v);
+ else
+ r = IN_TO_REG(v);
+
+ data->in_min[n] = r;
+
+ if (n < 4)
+ gl520_write_value(client, reg, (gl520_read_value(client, reg) & ~0xff) | r);
+ else
+ gl520_write_value(client, reg, r);
+
+ return count;
+}
+
+static ssize_t set_in_max(struct i2c_client *client, struct gl520_data *data, const char *buf, size_t count, int n, int reg)
+{
+ long v = simple_strtol(buf, NULL, 10);
+ u8 r;
+
+ if (n == 0)
+ r = VDD_TO_REG(v);
+ else
+ r = IN_TO_REG(v);
+
+ data->in_max[n] = r;
+
+ if (n < 4)
+ gl520_write_value(client, reg, (gl520_read_value(client, reg) & ~0xff00) | (r << 8));
+ else
+ gl520_write_value(client, reg, r);
+
+ return count;
+}
+
+#define DIV_FROM_REG(val) (1 << (val))
+#define FAN_FROM_REG(val,div) ((val)==0 ? 0 : (480000/((val) << (div))))
+#define FAN_TO_REG(val,div) ((val)<=0?0:SENSORS_LIMIT((480000 + ((val) << ((div)-1))) / ((val) << (div)), 1, 255));
+
+static ssize_t get_fan_input(struct gl520_data *data, char *buf, int n)
+{
+ return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_input[n - 1], data->fan_div[n - 1]));
+}
+
+static ssize_t get_fan_min(struct gl520_data *data, char *buf, int n)
+{
+ return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[n - 1], data->fan_div[n - 1]));
+}
+
+static ssize_t get_fan_div(struct gl520_data *data, char *buf, int n)
+{
+ return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[n - 1]));
+}
+
+static ssize_t get_fan_off(struct gl520_data *data, char *buf, int n)
+{
+ return sprintf(buf, "%d\n", data->fan_off);
+}
+
+static ssize_t set_fan_min(struct i2c_client *client, struct gl520_data *data, const char *buf, size_t count, int n, int reg)
+{
+ unsigned long v = simple_strtoul(buf, NULL, 10);
+ u8 r = FAN_TO_REG(v, data->fan_div[n - 1]);
+
+ data->fan_min[n - 1] = r;
+
+ if (n == 1)
+ gl520_write_value(client, reg, (gl520_read_value(client, reg) & ~0xff00) | (r << 8));
+ else
+ gl520_write_value(client, reg, (gl520_read_value(client, reg) & ~0xff) | r);
+
+ data->beep_mask = gl520_read_value(client, GL520_REG_BEEP_MASK);
+ if (data->fan_min[n - 1] == 0)
+ data->alarm_mask &= (n == 1) ? ~0x20 : ~0x40;
+ else
+ data->alarm_mask |= (n == 1) ? 0x20 : 0x40;
+ data->beep_mask &= data->alarm_mask;
+ gl520_write_value(client, GL520_REG_BEEP_MASK, data->beep_mask);
+
+ return count;
+}
+
+static ssize_t set_fan_div(struct i2c_client *client, struct gl520_data *data, const char *buf, size_t count, int n, int reg)
+{
+ unsigned long v = simple_strtoul(buf, NULL, 10);
+ u8 r;
+
+ switch (v) {
+ case 1: r = 0; break;
+ case 2: r = 1; break;
+ case 4: r = 2; break;
+ case 8: r = 3; break;
+ default:
+ dev_err(&client->dev, "fan_div value %ld not supported. Choose one of 1, 2, 4 or 8!\n", v);
+ return -EINVAL;
+ }
+
+ data->fan_div[n - 1] = r;
+
+ if (n == 1)
+ gl520_write_value(client, reg, (gl520_read_value(client, reg) & ~0xc0) | (r << 6));
+ else
+ gl520_write_value(client, reg, (gl520_read_value(client, reg) & ~0x30) | (r << 4));
+
+ return count;
+}
+
+static ssize_t set_fan_off(struct i2c_client *client, struct gl520_data *data, const char *buf, size_t count, int n, int reg)
+{
+ u8 r = simple_strtoul(buf, NULL, 10)?1:0;
+
+ data->fan_off = r;
+ gl520_write_value(client, reg, (gl520_read_value(client, reg) & ~0x0c) | (r << 2));
+
+ return count;
+}
+
+#define TEMP_FROM_REG(val) (((val) - 130) * 1000)
+#define TEMP_TO_REG(val) (SENSORS_LIMIT(((((val)<0?(val)-500:(val)+500) / 1000)+130),0,255))
+
+static ssize_t get_temp_input(struct gl520_data *data, char *buf, int n)
+{
+ return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_input[n - 1]));
+}
+
+static ssize_t get_temp_max(struct gl520_data *data, char *buf, int n)
+{
+ return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[n - 1]));
+}
+
+static ssize_t get_temp_max_hyst(struct gl520_data *data, char *buf, int n)
+{
+ return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max_hyst[n - 1]));
+}
+
+static ssize_t set_temp_max(struct i2c_client *client, struct gl520_data *data, const char *buf, size_t count, int n, int reg)
+{
+ long v = simple_strtol(buf, NULL, 10);
+ u8 r = TEMP_TO_REG(v);
+
+ data->temp_max[n - 1] = r;
+ gl520_write_value(client, reg, r);
+
+ return count;
+}
+
+static ssize_t set_temp_max_hyst(struct i2c_client *client, struct gl520_data *data, const char *buf, size_t count, int n, int reg)
+{
+ long v = simple_strtol(buf, NULL, 10);
+ u8 r = TEMP_TO_REG(v);
+
+ data->temp_max_hyst[n - 1] = r;
+ gl520_write_value(client, reg, r);
+
+ return count;
+}
+
+static ssize_t get_alarms(struct gl520_data *data, char *buf, int n)
+{
+ return sprintf(buf, "%d\n", data->alarms);
+}
+
+static ssize_t get_beep_enable(struct gl520_data *data, char *buf, int n)
+{
+ return sprintf(buf, "%d\n", data->beep_enable);
+}
+
+static ssize_t get_beep_mask(struct gl520_data *data, char *buf, int n)
+{
+ return sprintf(buf, "%d\n", data->beep_mask);
+}
+
+static ssize_t set_beep_enable(struct i2c_client *client, struct gl520_data *data, const char *buf, size_t count, int n, int reg)
+{
+ u8 r = simple_strtoul(buf, NULL, 10)?0:1;
+
+ data->beep_enable = !r;
+ gl520_write_value(client, reg, (gl520_read_value(client, reg) & ~0x04) | (r << 2));
+
+ return count;
+}
+
+static ssize_t set_beep_mask(struct i2c_client *client, struct gl520_data *data, const char *buf, size_t count, int n, int reg)
+{
+ u8 r = simple_strtoul(buf, NULL, 10) & data->alarm_mask;
+
+ data->beep_mask = r;
+ gl520_write_value(client, reg, r);
+
+ return count;
+}
+
+
+/*
+ * Real code
+ */
+
+static int gl520_attach_adapter(struct i2c_adapter *adapter)
+{
+ if (!(adapter->class & I2C_CLASS_HWMON))
+ return 0;
+ return i2c_detect(adapter, &addr_data, gl520_detect);
+}
+
+static int gl520_detect(struct i2c_adapter *adapter, int address, int kind)
+{
+ struct i2c_client *new_client;
+ struct gl520_data *data;
+ int err = 0;
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
+ I2C_FUNC_SMBUS_WORD_DATA))
+ goto exit;
+
+ /* OK. For now, we presume we have a valid client. We now create the
+ client structure, even though we cannot fill it completely yet.
+ But it allows us to access gl520_{read,write}_value. */
+
+ if (!(data = kmalloc(sizeof(struct gl520_data), GFP_KERNEL))) {
+ err = -ENOMEM;
+ goto exit;
+ }
+ memset(data, 0, sizeof(struct gl520_data));
+
+ new_client = &data->client;
+ i2c_set_clientdata(new_client, data);
+ new_client->addr = address;
+ new_client->adapter = adapter;
+ new_client->driver = &gl520_driver;
+ new_client->flags = 0;
+
+ /* Determine the chip type. */
+ if (kind < 0) {
+ if ((gl520_read_value(new_client, GL520_REG_CHIP_ID) != 0x20) ||
+ ((gl520_read_value(new_client, GL520_REG_REVISION) & 0x7f) != 0x00) ||
+ ((gl520_read_value(new_client, GL520_REG_CONF) & 0x80) != 0x00)) {
+ dev_dbg(&new_client->dev, "Unknown chip type, skipping\n");
+ goto exit_free;
+ }
+ }
+
+ /* Fill in the remaining client fields */
+ strlcpy(new_client->name, "gl520sm", I2C_NAME_SIZE);
+ data->valid = 0;
+ init_MUTEX(&data->update_lock);
+
+ /* Tell the I2C layer a new client has arrived */
+ if ((err = i2c_attach_client(new_client)))
+ goto exit_free;
+
+ /* Initialize the GL520SM chip */
+ gl520_init_client(new_client);
+
+ /* Register sysfs hooks */
+ device_create_file_vid(new_client, 0);
+
+ device_create_file_in(new_client, 0);
+ device_create_file_in(new_client, 1);
+ device_create_file_in(new_client, 2);
+ device_create_file_in(new_client, 3);
+ if (!data->two_temps)
+ device_create_file_in(new_client, 4);
+
+ device_create_file_fan(new_client, 1);
+ device_create_file_fan(new_client, 2);
+ device_create_file_fan_off(new_client, 1);
+
+ device_create_file_temp(new_client, 1);
+ if (data->two_temps)
+ device_create_file_temp(new_client, 2);
+
+ device_create_file_alarms(new_client);
+
+ return 0;
+
+exit_free:
+ kfree(data);
+exit:
+ return err;
+}
+
+
+/* Called when we have found a new GL520SM. */
+static void gl520_init_client(struct i2c_client *client)
+{
+ struct gl520_data *data = i2c_get_clientdata(client);
+ u8 oldconf, conf;
+
+ conf = oldconf = gl520_read_value(client, GL520_REG_CONF);
+
+ data->alarm_mask = 0xff;
+ data->vrm = i2c_which_vrm();
+
+ if (extra_sensor_type == 1)
+ conf &= ~0x10;
+ else if (extra_sensor_type == 2)
+ conf |= 0x10;
+ data->two_temps = !(conf & 0x10);
+
+ /* If IRQ# is disabled, we can safely force comparator mode */
+ if (!(conf & 0x20))
+ conf &= 0xf7;
+
+ /* Enable monitoring if needed */
+ conf |= 0x40;
+
+ if (conf != oldconf)
+ gl520_write_value(client, GL520_REG_CONF, conf);
+
+ gl520_update_device(&(client->dev));
+
+ if (data->fan_min[0] == 0)
+ data->alarm_mask &= ~0x20;
+ if (data->fan_min[1] == 0)
+ data->alarm_mask &= ~0x40;
+
+ data->beep_mask &= data->alarm_mask;
+ gl520_write_value(client, GL520_REG_BEEP_MASK, data->beep_mask);
+}
+
+static int gl520_detach_client(struct i2c_client *client)
+{
+ int err;
+
+ if ((err = i2c_detach_client(client))) {
+ dev_err(&client->dev, "Client deregistration failed, "
+ "client not detached.\n");
+ return err;
+ }
+
+ kfree(i2c_get_clientdata(client));
+ return 0;
+}
+
+
+/* Registers 0x07 to 0x0c are word-sized, others are byte-sized
+ GL520 uses a high-byte first convention */
+static int gl520_read_value(struct i2c_client *client, u8 reg)
+{
+ if ((reg >= 0x07) && (reg <= 0x0c))
+ return swab16(i2c_smbus_read_word_data(client, reg));
+ else
+ return i2c_smbus_read_byte_data(client, reg);
+}
+
+static int gl520_write_value(struct i2c_client *client, u8 reg, u16 value)
+{
+ if ((reg >= 0x07) && (reg <= 0x0c))
+ return i2c_smbus_write_word_data(client, reg, swab16(value));
+ else
+ return i2c_smbus_write_byte_data(client, reg, value);
+}
+
+
+static struct gl520_data *gl520_update_device(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct gl520_data *data = i2c_get_clientdata(client);
+ int val;
+
+ down(&data->update_lock);
+
+ if ((jiffies - data->last_updated > 2 * HZ) ||
+ (jiffies < data->last_updated) || !data->valid) {
+
+ dev_dbg(&client->dev, "Starting gl520sm update\n");
+
+ data->alarms = gl520_read_value(client, GL520_REG_ALARMS);
+ data->beep_mask = gl520_read_value(client, GL520_REG_BEEP_MASK);
+ data->vid = gl520_read_value(client, GL520_REG_VID_INPUT) & 0x1f;
+
+ val = gl520_read_value(client, GL520_REG_IN0_LIMIT);
+ data->in_min[0] = val & 0xff;
+ data->in_max[0] = (val >> 8) & 0xff;
+ val = gl520_read_value(client, GL520_REG_IN1_LIMIT);
+ data->in_min[1] = val & 0xff;
+ data->in_max[1] = (val >> 8) & 0xff;
+ val = gl520_read_value(client, GL520_REG_IN2_LIMIT);
+ data->in_min[2] = val & 0xff;
+ data->in_max[2] = (val >> 8) & 0xff;
+ val = gl520_read_value(client, GL520_REG_IN3_LIMIT);
+ data->in_min[3] = val & 0xff;
+ data->in_max[3] = (val >> 8) & 0xff;
+
+ val = gl520_read_value(client, GL520_REG_FAN_INPUT);
+ data->fan_input[0] = (val >> 8) & 0xff;
+ data->fan_input[1] = val & 0xff;
+
+ val = gl520_read_value(client, GL520_REG_FAN_MIN);
+ data->fan_min[0] = (val >> 8) & 0xff;
+ data->fan_min[1] = val & 0xff;
+
+ data->temp_input[0] = gl520_read_value(client, GL520_REG_TEMP1_INPUT);
+ data->temp_max[0] = gl520_read_value(client, GL520_REG_TEMP1_MAX);
+ data->temp_max_hyst[0] = gl520_read_value(client, GL520_REG_TEMP1_MAX_HYST);
+
+ val = gl520_read_value(client, GL520_REG_FAN_DIV);
+ data->fan_div[0] = (val >> 6) & 0x03;
+ data->fan_div[1] = (val >> 4) & 0x03;
+ data->fan_off = (val >> 2) & 0x01;
+
+ data->alarms &= data->alarm_mask;
+
+ val = gl520_read_value(client, GL520_REG_CONF);
+ data->beep_enable = !((val >> 2) & 1);
+
+ data->in_input[0] = gl520_read_value(client, GL520_REG_IN0_INPUT);
+ data->in_input[1] = gl520_read_value(client, GL520_REG_IN1_INPUT);
+ data->in_input[2] = gl520_read_value(client, GL520_REG_IN2_INPUT);
+ data->in_input[3] = gl520_read_value(client, GL520_REG_IN3_INPUT);
+
+ /* Temp1 and Vin4 are the same input */
+ if (data->two_temps) {
+ data->temp_input[1] = gl520_read_value(client, GL520_REG_TEMP2_INPUT);
+ data->temp_max[1] = gl520_read_value(client, GL520_REG_TEMP2_MAX);
+ data->temp_max_hyst[1] = gl520_read_value(client, GL520_REG_TEMP2_MAX_HYST);
+ } else {
+ data->in_input[4] = gl520_read_value(client, GL520_REG_IN4_INPUT);
+ data->in_min[4] = gl520_read_value(client, GL520_REG_IN4_MIN);
+ data->in_max[4] = gl520_read_value(client, GL520_REG_IN4_MAX);
+ }
+
+ data->last_updated = jiffies;
+ data->valid = 1;
+ }
+
+ up(&data->update_lock);
+
+ return data;
+}
+
+
+static int __init sensors_gl520sm_init(void)
+{
+ return i2c_add_driver(&gl520_driver);
+}
+
+static void __exit sensors_gl520sm_exit(void)
+{
+ i2c_del_driver(&gl520_driver);
+}
+
+
+MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, "
+ "Kyösti Mälkki <kmalkki@cc.hut.fi>, "
+ "Maarten Deprez <maartendeprez@users.sourceforge.net>");
+MODULE_DESCRIPTION("GL520SM driver");
+MODULE_LICENSE("GPL");
+
+module_init(sensors_gl520sm_init);
+module_exit(sensors_gl520sm_exit);
diff --git a/drivers/i2c/chips/isp1301_omap.c b/drivers/i2c/chips/isp1301_omap.c
index d7fec78faca81..7f29a8aff1656 100644
--- a/drivers/i2c/chips/isp1301_omap.c
+++ b/drivers/i2c/chips/isp1301_omap.c
@@ -1503,7 +1503,6 @@ static int isp1301_probe(struct i2c_adapter *bus, int address, int kind)
isp->client.addr = address;
i2c_set_clientdata(&isp->client, isp);
isp->client.adapter = bus;
- isp->client.id = 1301;
isp->client.driver = &isp1301_driver;
strlcpy(isp->client.name, DRIVER_NAME, I2C_NAME_SIZE);
i2c = &isp->client;
diff --git a/drivers/i2c/chips/it87.c b/drivers/i2c/chips/it87.c
index 8988f4fa9169f..e62c2e390076b 100644
--- a/drivers/i2c/chips/it87.c
+++ b/drivers/i2c/chips/it87.c
@@ -35,6 +35,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
+#include <linux/jiffies.h>
#include <linux/i2c.h>
#include <linux/i2c-sensor.h>
#include <linux/i2c-vid.h>
@@ -104,6 +105,9 @@ superio_exit(void)
/* Update battery voltage after every reading if true */
static int update_vbat;
+/* Not all BIOSes properly configure the PWM registers */
+static int fix_pwm_polarity;
+
/* Chip Type */
static u16 chip_type;
@@ -224,6 +228,7 @@ static int it87_read_value(struct i2c_client *client, u8 register);
static int it87_write_value(struct i2c_client *client, u8 register,
u8 value);
static struct it87_data *it87_update_device(struct device *dev);
+static int it87_check_pwm(struct i2c_client *client);
static void it87_init_client(struct i2c_client *client, struct it87_data *data);
@@ -718,7 +723,6 @@ int it87_detect(struct i2c_adapter *adapter, int address, int kind)
const char *name = "";
int is_isa = i2c_is_isa_adapter(adapter);
int enable_pwm_interface;
- int tmp;
if (!is_isa &&
!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
@@ -822,20 +826,12 @@ int it87_detect(struct i2c_adapter *adapter, int address, int kind)
if ((err = i2c_attach_client(new_client)))
goto ERROR2;
+ /* Check PWM configuration */
+ enable_pwm_interface = it87_check_pwm(new_client);
+
/* Initialize the IT87 chip */
it87_init_client(new_client, data);
- /* Some BIOSes fail to correctly configure the IT87 fans. All fans off
- * and polarity set to active low is sign that this is the case so we
- * disable pwm control to protect the user. */
- enable_pwm_interface = 1;
- tmp = it87_read_value(new_client, IT87_REG_FAN_CTL);
- if ((tmp & 0x87) == 0) {
- enable_pwm_interface = 0;
- dev_info(&new_client->dev,
- "detected broken BIOS defaults, disabling pwm interface");
- }
-
/* Register sysfs hooks */
device_create_file(&new_client->dev, &dev_attr_in0_input);
device_create_file(&new_client->dev, &dev_attr_in1_input);
@@ -966,6 +962,56 @@ static int it87_write_value(struct i2c_client *client, u8 reg, u8 value)
return i2c_smbus_write_byte_data(client, reg, value);
}
+/* Return 1 if and only if the PWM interface is safe to use */
+static int it87_check_pwm(struct i2c_client *client)
+{
+ /* Some BIOSes fail to correctly configure the IT87 fans. All fans off
+ * and polarity set to active low is sign that this is the case so we
+ * disable pwm control to protect the user. */
+ int tmp = it87_read_value(client, IT87_REG_FAN_CTL);
+ if ((tmp & 0x87) == 0) {
+ if (fix_pwm_polarity) {
+ /* The user asks us to attempt a chip reconfiguration.
+ * This means switching to active high polarity and
+ * inverting all fan speed values. */
+ int i;
+ u8 pwm[3];
+
+ for (i = 0; i < 3; i++)
+ pwm[i] = it87_read_value(client,
+ IT87_REG_PWM(i));
+
+ /* If any fan is in automatic pwm mode, the polarity
+ * might be correct, as suspicious as it seems, so we
+ * better don't change anything (but still disable the
+ * PWM interface). */
+ if (!((pwm[0] | pwm[1] | pwm[2]) & 0x80)) {
+ dev_info(&client->dev, "Reconfiguring PWM to "
+ "active high polarity\n");
+ it87_write_value(client, IT87_REG_FAN_CTL,
+ tmp | 0x87);
+ for (i = 0; i < 3; i++)
+ it87_write_value(client,
+ IT87_REG_PWM(i),
+ 0x7f & ~pwm[i]);
+ return 1;
+ }
+
+ dev_info(&client->dev, "PWM configuration is "
+ "too broken to be fixed\n");
+ }
+
+ dev_info(&client->dev, "Detected broken BIOS "
+ "defaults, disabling PWM interface\n");
+ return 0;
+ } else if (fix_pwm_polarity) {
+ dev_info(&client->dev, "PWM configuration looks "
+ "sane, won't touch\n");
+ }
+
+ return 1;
+}
+
/* Called when we have found a new IT87. */
static void it87_init_client(struct i2c_client *client, struct it87_data *data)
{
@@ -1038,8 +1084,8 @@ static struct it87_data *it87_update_device(struct device *dev)
down(&data->update_lock);
- if ((jiffies - data->last_updated > HZ + HZ / 2) ||
- (jiffies < data->last_updated) || !data->valid) {
+ if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
+ || !data->valid) {
if (update_vbat) {
/* Cleared after each update, so reenable. Value
@@ -1126,6 +1172,8 @@ MODULE_AUTHOR("Chris Gauthron <chrisg@0-in.com>");
MODULE_DESCRIPTION("IT8705F, IT8712F, Sis950 driver");
module_param(update_vbat, bool, 0);
MODULE_PARM_DESC(update_vbat, "Update vbat if set else return powerup value");
+module_param(fix_pwm_polarity, bool, 0);
+MODULE_PARM_DESC(fix_pwm_polarity, "Force PWM polarity to active high (DANGEROUS)");
MODULE_LICENSE("GPL");
module_init(sm_it87_init);
diff --git a/drivers/i2c/chips/lm63.c b/drivers/i2c/chips/lm63.c
index e42401eeb4577..a8cf806ee5c05 100644
--- a/drivers/i2c/chips/lm63.c
+++ b/drivers/i2c/chips/lm63.c
@@ -41,6 +41,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
+#include <linux/jiffies.h>
#include <linux/i2c.h>
#include <linux/i2c-sensor.h>
@@ -492,9 +493,7 @@ static struct lm63_data *lm63_update_device(struct device *dev)
down(&data->update_lock);
- if ((jiffies - data->last_updated > HZ) ||
- (jiffies < data->last_updated) ||
- !data->valid) {
+ if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
if (data->config & 0x04) { /* tachometer enabled */
/* order matters for fan1_input */
data->fan1_input = i2c_smbus_read_byte_data(client,
diff --git a/drivers/i2c/chips/lm75.c b/drivers/i2c/chips/lm75.c
index a5d32245f623c..6605397e5425b 100644
--- a/drivers/i2c/chips/lm75.c
+++ b/drivers/i2c/chips/lm75.c
@@ -22,6 +22,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
+#include <linux/jiffies.h>
#include <linux/i2c.h>
#include <linux/i2c-sensor.h>
#include "lm75.h"
@@ -73,8 +74,6 @@ static struct i2c_driver lm75_driver = {
.detach_client = lm75_detach_client,
};
-static int lm75_id;
-
#define show(value) \
static ssize_t show_##value(struct device *dev, char *buf) \
{ \
@@ -196,8 +195,6 @@ static int lm75_detect(struct i2c_adapter *adapter, int address, int kind)
/* Fill in the remaining client fields and put it into the global list */
strlcpy(new_client->name, name, I2C_NAME_SIZE);
-
- new_client->id = lm75_id++;
data->valid = 0;
init_MUTEX(&data->update_lock);
@@ -263,8 +260,8 @@ static struct lm75_data *lm75_update_device(struct device *dev)
down(&data->update_lock);
- if ((jiffies - data->last_updated > HZ + HZ / 2) ||
- (jiffies < data->last_updated) || !data->valid) {
+ if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
+ || !data->valid) {
dev_dbg(&client->dev, "Starting lm75 update\n");
data->temp_input = lm75_read_value(client, LM75_REG_TEMP);
diff --git a/drivers/i2c/chips/lm77.c b/drivers/i2c/chips/lm77.c
index 71cf3799c4f9d..26a0c4a11e621 100644
--- a/drivers/i2c/chips/lm77.c
+++ b/drivers/i2c/chips/lm77.c
@@ -29,6 +29,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
+#include <linux/jiffies.h>
#include <linux/i2c.h>
#include <linux/i2c-sensor.h>
@@ -81,8 +82,6 @@ static struct i2c_driver lm77_driver = {
.detach_client = lm77_detach_client,
};
-static int lm77_id;
-
/* straight from the datasheet */
#define LM77_TEMP_MIN (-55000)
#define LM77_TEMP_MAX 125000
@@ -295,8 +294,6 @@ static int lm77_detect(struct i2c_adapter *adapter, int address, int kind)
/* Fill in the remaining client fields and put it into the global list */
strlcpy(new_client->name, name, I2C_NAME_SIZE);
-
- new_client->id = lm77_id++;
data->valid = 0;
init_MUTEX(&data->update_lock);
@@ -364,8 +361,8 @@ static struct lm77_data *lm77_update_device(struct device *dev)
down(&data->update_lock);
- if ((jiffies - data->last_updated > HZ + HZ / 2) ||
- (jiffies < data->last_updated) || !data->valid) {
+ if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
+ || !data->valid) {
dev_dbg(&client->dev, "Starting lm77 update\n");
data->temp_input =
LM77_TEMP_FROM_REG(lm77_read_value(client,
diff --git a/drivers/i2c/chips/lm78.c b/drivers/i2c/chips/lm78.c
index 640aa01cd7903..1e0950d8d2c6c 100644
--- a/drivers/i2c/chips/lm78.c
+++ b/drivers/i2c/chips/lm78.c
@@ -22,6 +22,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
+#include <linux/jiffies.h>
#include <linux/i2c.h>
#include <linux/i2c-sensor.h>
#include <asm/io.h>
@@ -81,9 +82,8 @@ static inline u8 IN_TO_REG(unsigned long val)
static inline u8 FAN_TO_REG(long rpm, int div)
{
- if (rpm == 0)
+ if (rpm <= 0)
return 255;
- rpm = SENSORS_LIMIT(rpm, 1, 1000000);
return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 254);
}
@@ -94,15 +94,15 @@ static inline int FAN_FROM_REG(u8 val, int div)
/* TEMP: mC (-128C to +127C)
REG: 1C/bit, two's complement */
-static inline u8 TEMP_TO_REG(int val)
+static inline s8 TEMP_TO_REG(int val)
{
int nval = SENSORS_LIMIT(val, -128000, 127000) ;
- return nval<0 ? (nval-500)/1000+0x100 : (nval+500)/1000;
+ return nval<0 ? (nval-500)/1000 : (nval+500)/1000;
}
-static inline int TEMP_FROM_REG(u8 val)
+static inline int TEMP_FROM_REG(s8 val)
{
- return (val>=0x80 ? val-0x100 : val) * 1000;
+ return val * 1000;
}
/* VID: mV
@@ -112,16 +112,6 @@ static inline int VID_FROM_REG(u8 val)
return val==0x1f ? 0 : val>=0x10 ? 5100-val*100 : 2050-val*50;
}
-/* ALARMS: chip-specific bitmask
- REG: (same) */
-#define ALARMS_FROM_REG(val) (val)
-
-/* FAN DIV: 1, 2, 4, or 8 (defaults to 2)
- REG: 0, 1, 2, or 3 (respectively) (defaults to 1) */
-static inline u8 DIV_TO_REG(int val)
-{
- return val==8 ? 3 : val==4 ? 2 : val==1 ? 0 : 1;
-}
#define DIV_FROM_REG(val) (1 << (val))
/* There are some complications in a module like this. First off, LM78 chips
@@ -157,9 +147,9 @@ struct lm78_data {
u8 in_min[7]; /* Register value */
u8 fan[3]; /* Register value */
u8 fan_min[3]; /* Register value */
- u8 temp; /* Register value */
- u8 temp_over; /* Register value */
- u8 temp_hyst; /* Register value */
+ s8 temp; /* Register value */
+ s8 temp_over; /* Register value */
+ s8 temp_hyst; /* Register value */
u8 fan_div[3]; /* Register encoding, shifted right */
u8 vid; /* Register encoding, combined */
u16 alarms; /* Register encoding, combined */
@@ -357,7 +347,17 @@ static ssize_t set_fan_div(struct device *dev, const char *buf,
DIV_FROM_REG(data->fan_div[nr]));
unsigned long val = simple_strtoul(buf, NULL, 10);
int reg = lm78_read_value(client, LM78_REG_VID_FANDIV);
- data->fan_div[nr] = DIV_TO_REG(val);
+ 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);
+ return -EINVAL;
+ }
+
switch (nr) {
case 0:
reg = (reg & 0xcf) | (data->fan_div[nr] << 4);
@@ -430,7 +430,7 @@ static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
static ssize_t show_alarms(struct device *dev, char *buf)
{
struct lm78_data *data = lm78_update_device(dev);
- return sprintf(buf, "%d\n", ALARMS_FROM_REG(data->alarms));
+ return sprintf(buf, "%u\n", data->alarms);
}
static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
@@ -633,17 +633,15 @@ static int lm78_detach_client(struct i2c_client *client)
{
int err;
- /* release ISA region first */
- if(i2c_is_isa_client(client))
- release_region(client->addr, LM78_EXTENT);
-
- /* now it's safe to scrap the rest */
if ((err = i2c_detach_client(client))) {
dev_err(&client->dev,
"Client deregistration failed, client not detached.\n");
return err;
}
+ if(i2c_is_isa_client(client))
+ release_region(client->addr, LM78_EXTENT);
+
kfree(i2c_get_clientdata(client));
return 0;
@@ -653,9 +651,7 @@ static int lm78_detach_client(struct i2c_client *client)
We don't want to lock the whole ISA bus, so we lock each client
separately.
We ignore the LM78 BUSY flag at this moment - it could lead to deadlocks,
- would slow down the LM78 access and should not be necessary.
- There are some ugly typecasts here, but the good new is - they should
- nowhere else be necessary! */
+ would slow down the LM78 access and should not be necessary. */
static int lm78_read_value(struct i2c_client *client, u8 reg)
{
int res;
@@ -709,8 +705,8 @@ static struct lm78_data *lm78_update_device(struct device *dev)
down(&data->update_lock);
- if ((jiffies - data->last_updated > HZ + HZ / 2) ||
- (jiffies < data->last_updated) || !data->valid) {
+ if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
+ || !data->valid) {
dev_dbg(&client->dev, "Starting lm78 update\n");
diff --git a/drivers/i2c/chips/lm80.c b/drivers/i2c/chips/lm80.c
index c13d515c54ec5..0df1fffddd194 100644
--- a/drivers/i2c/chips/lm80.c
+++ b/drivers/i2c/chips/lm80.c
@@ -25,6 +25,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
+#include <linux/jiffies.h>
#include <linux/i2c.h>
#include <linux/i2c-sensor.h>
@@ -99,10 +100,7 @@ static inline long TEMP_FROM_REG(u16 temp)
#define TEMP_LIMIT_TO_REG(val) SENSORS_LIMIT((val)<0?\
((val)-500)/1000:((val)+500)/1000,0,255)
-#define ALARMS_FROM_REG(val) (val)
-
#define DIV_FROM_REG(val) (1 << (val))
-#define DIV_TO_REG(val) ((val)==8?3:(val)==4?2:(val)==1?0:1)
/*
* Client data (each client gets its own)
@@ -141,12 +139,6 @@ static int lm80_read_value(struct i2c_client *client, u8 reg);
static int lm80_write_value(struct i2c_client *client, u8 reg, u8 value);
/*
- * Internal variables
- */
-
-static int lm80_id;
-
-/*
* Driver data (common to all clients)
*/
@@ -269,7 +261,17 @@ static ssize_t set_fan_div(struct device *dev, const char *buf,
DIV_FROM_REG(data->fan_div[nr]));
val = simple_strtoul(buf, NULL, 10);
- data->fan_div[nr] = DIV_TO_REG(val);
+
+ 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);
+ return -EINVAL;
+ }
reg = (lm80_read_value(client, LM80_REG_FANDIV) & ~(3 << (2 * (nr + 1))))
| (data->fan_div[nr] << (2 * (nr + 1)));
@@ -327,7 +329,7 @@ set_temp(os_hyst, temp_os_hyst, LM80_REG_TEMP_OS_HYST);
static ssize_t show_alarms(struct device *dev, char *buf)
{
struct lm80_data *data = lm80_update_device(dev);
- return sprintf(buf, "%d\n", ALARMS_FROM_REG(data->alarms));
+ return sprintf(buf, "%u\n", data->alarms);
}
static DEVICE_ATTR(in0_min, S_IWUSR | S_IRUGO, show_in_min0, set_in_min0);
@@ -425,8 +427,6 @@ int lm80_detect(struct i2c_adapter *adapter, int address, int kind)
/* Fill in the remaining client fields and put it into the global list */
strlcpy(new_client->name, name, I2C_NAME_SIZE);
-
- new_client->id = lm80_id++;
data->valid = 0;
init_MUTEX(&data->update_lock);
@@ -530,9 +530,7 @@ static struct lm80_data *lm80_update_device(struct device *dev)
down(&data->update_lock);
- if ((jiffies - data->last_updated > 2 * HZ) ||
- (jiffies < data->last_updated) || !data->valid) {
-
+ if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) {
dev_dbg(&client->dev, "Starting lm80 update\n");
for (i = 0; i <= 6; i++) {
data->in[i] =
diff --git a/drivers/i2c/chips/lm83.c b/drivers/i2c/chips/lm83.c
index 552321e05a2fd..6a4c345325a0f 100644
--- a/drivers/i2c/chips/lm83.c
+++ b/drivers/i2c/chips/lm83.c
@@ -31,6 +31,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
+#include <linux/jiffies.h>
#include <linux/i2c.h>
#include <linux/i2c-sensor.h>
@@ -150,12 +151,6 @@ struct lm83_data {
};
/*
- * Internal variables
- */
-
-static int lm83_id;
-
-/*
* Sysfs stuff
*/
@@ -312,7 +307,6 @@ static int lm83_detect(struct i2c_adapter *adapter, int address, int kind)
/* We can fill in the remaining client fields */
strlcpy(new_client->name, name, I2C_NAME_SIZE);
- new_client->id = lm83_id++;
data->valid = 0;
init_MUTEX(&data->update_lock);
@@ -369,9 +363,7 @@ static struct lm83_data *lm83_update_device(struct device *dev)
down(&data->update_lock);
- if ((jiffies - data->last_updated > HZ * 2) ||
- (jiffies < data->last_updated) ||
- !data->valid) {
+ if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) {
int nr;
dev_dbg(&client->dev, "Updating lm83 data.\n");
diff --git a/drivers/i2c/chips/lm85.c b/drivers/i2c/chips/lm85.c
index 7b1a773bc8f28..d17aba4e42fcd 100644
--- a/drivers/i2c/chips/lm85.c
+++ b/drivers/i2c/chips/lm85.c
@@ -27,6 +27,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
+#include <linux/jiffies.h>
#include <linux/i2c.h>
#include <linux/i2c-sensor.h>
#include <linux/i2c-vid.h>
@@ -389,9 +390,6 @@ static struct i2c_driver lm85_driver = {
.detach_client = lm85_detach_client,
};
-/* Unique ID assigned to each LM85 detected */
-static int lm85_id;
-
/* 4 Fans */
static ssize_t show_fan(struct device *dev, char *buf, int nr)
@@ -1148,16 +1146,10 @@ int lm85_detect(struct i2c_adapter *adapter, int address,
strlcpy(new_client->name, type_name, I2C_NAME_SIZE);
/* Fill in the remaining client fields */
- new_client->id = lm85_id++;
data->type = kind;
data->valid = 0;
init_MUTEX(&data->update_lock);
- dev_dbg(&adapter->dev, "Assigning ID %d to %s at %d,0x%02x\n",
- new_client->id, new_client->name,
- i2c_adapter_id(new_client->adapter),
- new_client->addr);
-
/* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(new_client)))
goto ERROR1;
@@ -1363,7 +1355,7 @@ static struct lm85_data *lm85_update_device(struct device *dev)
down(&data->update_lock);
if ( !data->valid ||
- (jiffies - data->last_reading > LM85_DATA_INTERVAL ) ) {
+ time_after(jiffies, data->last_reading + LM85_DATA_INTERVAL) ) {
/* Things that change quickly */
dev_dbg(&client->dev, "Reading sensor values\n");
@@ -1417,7 +1409,7 @@ static struct lm85_data *lm85_update_device(struct device *dev)
}; /* last_reading */
if ( !data->valid ||
- (jiffies - data->last_config > LM85_CONFIG_INTERVAL) ) {
+ time_after(jiffies, data->last_config + LM85_CONFIG_INTERVAL) ) {
/* Things that don't change often */
dev_dbg(&client->dev, "Reading config values\n");
diff --git a/drivers/i2c/chips/lm87.c b/drivers/i2c/chips/lm87.c
index 7da39fe229266..8b9e2de21bff7 100644
--- a/drivers/i2c/chips/lm87.c
+++ b/drivers/i2c/chips/lm87.c
@@ -56,6 +56,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
+#include <linux/jiffies.h>
#include <linux/i2c.h>
#include <linux/i2c-sensor.h>
#include <linux/i2c-vid.h>
@@ -203,12 +204,6 @@ struct lm87_data {
};
/*
- * Internal variables
- */
-
-static int lm87_id;
-
-/*
* Sysfs stuff
*/
@@ -569,7 +564,6 @@ static int lm87_detect(struct i2c_adapter *adapter, int address, int kind)
/* We can fill in the remaining client fields */
strlcpy(new_client->name, "lm87", I2C_NAME_SIZE);
- new_client->id = lm87_id++;
data->valid = 0;
init_MUTEX(&data->update_lock);
@@ -720,9 +714,7 @@ static struct lm87_data *lm87_update_device(struct device *dev)
down(&data->update_lock);
- if (jiffies - data->last_updated > HZ
- || jiffies < data->last_updated
- || !data->valid) {
+ if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
int i, j;
dev_dbg(&client->dev, "Updating data.\n");
diff --git a/drivers/i2c/chips/lm90.c b/drivers/i2c/chips/lm90.c
index ba7c450e8874d..7540b230173e8 100644
--- a/drivers/i2c/chips/lm90.c
+++ b/drivers/i2c/chips/lm90.c
@@ -66,6 +66,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
+#include <linux/jiffies.h>
#include <linux/i2c.h>
#include <linux/i2c-sensor.h>
@@ -190,12 +191,6 @@ struct lm90_data {
};
/*
- * Internal variables
- */
-
-static int lm90_id;
-
-/*
* Sysfs stuff
*/
@@ -427,7 +422,6 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind)
/* We can fill in the remaining client fields */
strlcpy(new_client->name, name, I2C_NAME_SIZE);
- new_client->id = lm90_id++;
data->valid = 0;
init_MUTEX(&data->update_lock);
@@ -495,9 +489,7 @@ static struct lm90_data *lm90_update_device(struct device *dev)
down(&data->update_lock);
- if ((jiffies - data->last_updated > HZ * 2) ||
- (jiffies < data->last_updated) ||
- !data->valid) {
+ if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) {
u8 oldh, newh;
dev_dbg(&client->dev, "Updating lm90 data.\n");
diff --git a/drivers/i2c/chips/m41t00.c b/drivers/i2c/chips/m41t00.c
new file mode 100644
index 0000000000000..de270e920207a
--- /dev/null
+++ b/drivers/i2c/chips/m41t00.c
@@ -0,0 +1,247 @@
+/*
+ * drivers/i2c/chips/m41t00.c
+ *
+ * I2C client/driver for the ST M41T00 Real-Time Clock chip.
+ *
+ * Author: Mark A. Greer <mgreer@mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+/*
+ * This i2c client/driver wedges between the drivers/char/genrtc.c RTC
+ * interface and the SMBus interface of the i2c subsystem.
+ * It would be more efficient to use i2c msgs/i2c_transfer directly but, as
+ * recommened in .../Documentation/i2c/writing-clients section
+ * "Sending and receiving", using SMBus level communication is preferred.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/rtc.h>
+#include <linux/bcd.h>
+
+#include <asm/time.h>
+#include <asm/rtc.h>
+
+#define M41T00_DRV_NAME "m41t00"
+
+static DECLARE_MUTEX(m41t00_mutex);
+
+static struct i2c_driver m41t00_driver;
+static struct i2c_client *save_client;
+
+static unsigned short ignore[] = { I2C_CLIENT_END };
+static unsigned short normal_addr[] = { 0x68, I2C_CLIENT_END };
+
+static struct i2c_client_address_data addr_data = {
+ .normal_i2c = normal_addr,
+ .normal_i2c_range = ignore,
+ .probe = ignore,
+ .probe_range = ignore,
+ .ignore = ignore,
+ .ignore_range = ignore,
+ .force = ignore,
+};
+
+ulong
+m41t00_get_rtc_time(void)
+{
+ s32 sec, min, hour, day, mon, year;
+ s32 sec1, min1, hour1, day1, mon1, year1;
+ ulong limit = 10;
+
+ sec = min = hour = day = mon = year = 0;
+ sec1 = min1 = hour1 = day1 = mon1 = year1 = 0;
+
+ down(&m41t00_mutex);
+ do {
+ if (((sec = i2c_smbus_read_byte_data(save_client, 0)) >= 0)
+ && ((min = i2c_smbus_read_byte_data(save_client, 1))
+ >= 0)
+ && ((hour = i2c_smbus_read_byte_data(save_client, 2))
+ >= 0)
+ && ((day = i2c_smbus_read_byte_data(save_client, 4))
+ >= 0)
+ && ((mon = i2c_smbus_read_byte_data(save_client, 5))
+ >= 0)
+ && ((year = i2c_smbus_read_byte_data(save_client, 6))
+ >= 0)
+ && ((sec == sec1) && (min == min1) && (hour == hour1)
+ && (day == day1) && (mon == mon1)
+ && (year == year1)))
+
+ break;
+
+ sec1 = sec;
+ min1 = min;
+ hour1 = hour;
+ day1 = day;
+ mon1 = mon;
+ year1 = year;
+ } while (--limit > 0);
+ up(&m41t00_mutex);
+
+ if (limit == 0) {
+ dev_warn(&save_client->dev,
+ "m41t00: can't read rtc chip\n");
+ sec = min = hour = day = mon = year = 0;
+ }
+
+ sec &= 0x7f;
+ min &= 0x7f;
+ hour &= 0x3f;
+ day &= 0x3f;
+ mon &= 0x1f;
+ year &= 0xff;
+
+ BCD_TO_BIN(sec);
+ BCD_TO_BIN(min);
+ BCD_TO_BIN(hour);
+ BCD_TO_BIN(day);
+ BCD_TO_BIN(mon);
+ BCD_TO_BIN(year);
+
+ year += 1900;
+ if (year < 1970)
+ year += 100;
+
+ return mktime(year, mon, day, hour, min, sec);
+}
+
+static void
+m41t00_set_tlet(ulong arg)
+{
+ struct rtc_time tm;
+ ulong nowtime = *(ulong *)arg;
+
+ to_tm(nowtime, &tm);
+ tm.tm_year = (tm.tm_year - 1900) % 100;
+
+ BIN_TO_BCD(tm.tm_sec);
+ BIN_TO_BCD(tm.tm_min);
+ BIN_TO_BCD(tm.tm_hour);
+ BIN_TO_BCD(tm.tm_mon);
+ BIN_TO_BCD(tm.tm_mday);
+ BIN_TO_BCD(tm.tm_year);
+
+ down(&m41t00_mutex);
+ if ((i2c_smbus_write_byte_data(save_client, 0, tm.tm_sec & 0x7f) < 0)
+ || (i2c_smbus_write_byte_data(save_client, 1, tm.tm_min & 0x7f)
+ < 0)
+ || (i2c_smbus_write_byte_data(save_client, 2, tm.tm_hour & 0x7f)
+ < 0)
+ || (i2c_smbus_write_byte_data(save_client, 4, tm.tm_mday & 0x7f)
+ < 0)
+ || (i2c_smbus_write_byte_data(save_client, 5, tm.tm_mon & 0x7f)
+ < 0)
+ || (i2c_smbus_write_byte_data(save_client, 6, tm.tm_year & 0x7f)
+ < 0))
+
+ dev_warn(&save_client->dev,"m41t00: can't write to rtc chip\n");
+
+ up(&m41t00_mutex);
+ return;
+}
+
+ulong new_time;
+
+DECLARE_TASKLET_DISABLED(m41t00_tasklet, m41t00_set_tlet, (ulong)&new_time);
+
+int
+m41t00_set_rtc_time(ulong nowtime)
+{
+ new_time = nowtime;
+
+ if (in_interrupt())
+ tasklet_schedule(&m41t00_tasklet);
+ else
+ m41t00_set_tlet((ulong)&new_time);
+
+ return 0;
+}
+
+/*
+ *****************************************************************************
+ *
+ * Driver Interface
+ *
+ *****************************************************************************
+ */
+static int
+m41t00_probe(struct i2c_adapter *adap, int addr, int kind)
+{
+ struct i2c_client *client;
+ int rc;
+
+ client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ if (!client)
+ return -ENOMEM;
+
+ memset(client, 0, sizeof(struct i2c_client));
+ strncpy(client->name, M41T00_DRV_NAME, I2C_NAME_SIZE);
+ client->id = m41t00_driver.id;
+ client->flags = I2C_DF_NOTIFY;
+ client->addr = addr;
+ client->adapter = adap;
+ client->driver = &m41t00_driver;
+
+ if ((rc = i2c_attach_client(client)) != 0) {
+ kfree(client);
+ return rc;
+ }
+
+ save_client = client;
+ return 0;
+}
+
+static int
+m41t00_attach(struct i2c_adapter *adap)
+{
+ return i2c_probe(adap, &addr_data, m41t00_probe);
+}
+
+static int
+m41t00_detach(struct i2c_client *client)
+{
+ int rc;
+
+ if ((rc = i2c_detach_client(client)) == 0) {
+ kfree(i2c_get_clientdata(client));
+ tasklet_kill(&m41t00_tasklet);
+ }
+ return rc;
+}
+
+static struct i2c_driver m41t00_driver = {
+ .owner = THIS_MODULE,
+ .name = M41T00_DRV_NAME,
+ .id = I2C_DRIVERID_STM41T00,
+ .flags = I2C_DF_NOTIFY,
+ .attach_adapter = m41t00_attach,
+ .detach_client = m41t00_detach,
+};
+
+static int __init
+m41t00_init(void)
+{
+ return i2c_add_driver(&m41t00_driver);
+}
+
+static void __exit
+m41t00_exit(void)
+{
+ i2c_del_driver(&m41t00_driver);
+ return;
+}
+
+module_init(m41t00_init);
+module_exit(m41t00_exit);
+
+MODULE_AUTHOR("Mark A. Greer <mgreer@mvista.com>");
+MODULE_DESCRIPTION("ST Microelectronics M41T00 RTC I2C Client Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/i2c/chips/max1619.c b/drivers/i2c/chips/max1619.c
index bc7e22f0ccd52..e6f080163b82e 100644
--- a/drivers/i2c/chips/max1619.c
+++ b/drivers/i2c/chips/max1619.c
@@ -30,6 +30,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
+#include <linux/jiffies.h>
#include <linux/i2c.h>
#include <linux/i2c-sensor.h>
@@ -117,12 +118,6 @@ struct max1619_data {
};
/*
- * Internal variables
- */
-
-static int max1619_id;
-
-/*
* Sysfs stuff
*/
@@ -267,7 +262,6 @@ static int max1619_detect(struct i2c_adapter *adapter, int address, int kind)
/* We can fill in the remaining client fields */
strlcpy(new_client->name, name, I2C_NAME_SIZE);
- new_client->id = max1619_id++;
data->valid = 0;
init_MUTEX(&data->update_lock);
@@ -331,10 +325,7 @@ static struct max1619_data *max1619_update_device(struct device *dev)
down(&data->update_lock);
- if ((jiffies - data->last_updated > HZ * 2) ||
- (jiffies < data->last_updated) ||
- !data->valid) {
-
+ if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) {
dev_dbg(&client->dev, "Updating max1619 data.\n");
data->temp_input1 = i2c_smbus_read_byte_data(client,
MAX1619_REG_R_LOCAL_TEMP);
diff --git a/drivers/i2c/chips/pc87360.c b/drivers/i2c/chips/pc87360.c
index 6979341e98dcd..bc15f70efe133 100644
--- a/drivers/i2c/chips/pc87360.c
+++ b/drivers/i2c/chips/pc87360.c
@@ -37,6 +37,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
+#include <linux/jiffies.h>
#include <linux/i2c.h>
#include <linux/i2c-sensor.h>
#include <linux/i2c-vid.h>
@@ -1174,8 +1175,7 @@ static struct pc87360_data *pc87360_update_device(struct device *dev)
down(&data->update_lock);
- if ((jiffies - data->last_updated > HZ * 2)
- || (jiffies < data->last_updated) || !data->valid) {
+ if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) {
dev_dbg(&client->dev, "Data update\n");
/* Fans */
diff --git a/drivers/i2c/chips/pcf8574.c b/drivers/i2c/chips/pcf8574.c
index 7943938583b8e..ea68e6d16d5df 100644
--- a/drivers/i2c/chips/pcf8574.c
+++ b/drivers/i2c/chips/pcf8574.c
@@ -77,8 +77,6 @@ static struct i2c_driver pcf8574_driver = {
.detach_client = pcf8574_detach_client,
};
-static int pcf8574_id;
-
/* following are the sysfs callback functions */
static ssize_t show_read(struct device *dev, char *buf)
{
@@ -159,8 +157,6 @@ int pcf8574_detect(struct i2c_adapter *adapter, int address, int kind)
/* Fill in the remaining client fields and put it into the global list */
strlcpy(new_client->name, client_name, I2C_NAME_SIZE);
-
- new_client->id = pcf8574_id++;
init_MUTEX(&data->update_lock);
/* Tell the I2C layer a new client has arrived */
diff --git a/drivers/i2c/chips/pcf8591.c b/drivers/i2c/chips/pcf8591.c
index 8f3b8588cc271..6c7dc052bacd3 100644
--- a/drivers/i2c/chips/pcf8591.c
+++ b/drivers/i2c/chips/pcf8591.c
@@ -98,8 +98,6 @@ static struct i2c_driver pcf8591_driver = {
.detach_client = pcf8591_detach_client,
};
-static int pcf8591_id;
-
/* following are the sysfs callback functions */
#define show_in_channel(channel) \
static ssize_t show_in##channel##_input(struct device *dev, char *buf) \
@@ -201,8 +199,6 @@ int pcf8591_detect(struct i2c_adapter *adapter, int address, int kind)
/* Fill in the remaining client fields and put it into the global
list */
strlcpy(new_client->name, "pcf8591", I2C_NAME_SIZE);
-
- new_client->id = pcf8591_id++;
init_MUTEX(&data->update_lock);
/* Tell the I2C layer a new client has arrived */
diff --git a/drivers/i2c/chips/rtc8564.c b/drivers/i2c/chips/rtc8564.c
index acfd3f8041799..5a9deddb626b3 100644
--- a/drivers/i2c/chips/rtc8564.c
+++ b/drivers/i2c/chips/rtc8564.c
@@ -89,7 +89,7 @@ static int rtc8564_read(struct i2c_client *client, unsigned char adr,
_DBG(1, "client=%p, adr=%d, buf=%p, len=%d", client, adr, buf, len);
- if (!buf || !client) {
+ if (!buf) {
ret = -EINVAL;
goto done;
}
@@ -111,7 +111,7 @@ static int rtc8564_write(struct i2c_client *client, unsigned char adr,
struct i2c_msg wr;
int i;
- if (!client || !data || len > 15) {
+ if (!data || len > 15) {
ret = -EINVAL;
goto done;
}
@@ -163,14 +163,12 @@ 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->id = rtc8564_driver.id;
new_client->flags = I2C_CLIENT_ALLOW_USE | I2C_DF_NOTIFY;
new_client->addr = addr;
new_client->adapter = adap;
new_client->driver = &rtc8564_driver;
_DBG(1, "client=%p", new_client);
- _DBG(1, "client.id=%d", new_client->id);
/* init ctrl1 reg */
data[0] = 0;
@@ -222,7 +220,7 @@ static int rtc8564_get_datetime(struct i2c_client *client, struct rtc_tm *dt)
_DBG(1, "client=%p, dt=%p", client, dt);
- if (!dt || !client)
+ if (!dt)
return -EINVAL;
memset(buf, 0, sizeof(buf));
@@ -256,7 +254,7 @@ rtc8564_set_datetime(struct i2c_client *client, struct rtc_tm *dt, int datetoo)
_DBG(1, "client=%p, dt=%p", client, dt);
- if (!dt || !client)
+ if (!dt)
return -EINVAL;
_DBGRTCTM(2, *dt);
@@ -295,7 +293,7 @@ static int rtc8564_get_ctrl(struct i2c_client *client, unsigned int *ctrl)
{
struct rtc8564_data *data = i2c_get_clientdata(client);
- if (!ctrl || !client)
+ if (!ctrl)
return -1;
*ctrl = data->ctrl;
@@ -307,7 +305,7 @@ static int rtc8564_set_ctrl(struct i2c_client *client, unsigned int *ctrl)
struct rtc8564_data *data = i2c_get_clientdata(client);
unsigned char buf[2];
- if (!ctrl || !client)
+ if (!ctrl)
return -1;
buf[0] = *ctrl & 0xff;
@@ -320,7 +318,7 @@ static int rtc8564_set_ctrl(struct i2c_client *client, unsigned int *ctrl)
static int rtc8564_read_mem(struct i2c_client *client, struct mem *mem)
{
- if (!mem || !client)
+ if (!mem)
return -EINVAL;
return rtc8564_read(client, mem->loc, mem->data, mem->nr);
@@ -329,7 +327,7 @@ static int rtc8564_read_mem(struct i2c_client *client, struct mem *mem)
static int rtc8564_write_mem(struct i2c_client *client, struct mem *mem)
{
- if (!mem || !client)
+ if (!mem)
return -EINVAL;
return rtc8564_write(client, mem->loc, mem->data, mem->nr);
diff --git a/drivers/i2c/chips/sis5595.c b/drivers/i2c/chips/sis5595.c
new file mode 100644
index 0000000000000..178f01fb4fb43
--- /dev/null
+++ b/drivers/i2c/chips/sis5595.c
@@ -0,0 +1,794 @@
+/*
+ sis5595.c - Part of lm_sensors, Linux kernel modules
+ for hardware monitoring
+
+ Copyright (C) 1998 - 2001 Frodo Looijaard <frodol@dds.nl>,
+ Kyösti Mälkki <kmalkki@cc.hut.fi>, and
+ Mark D. Studebaker <mdsxyz123@yahoo.com>
+ Ported to Linux 2.6 by Aurelien Jarno <aurelien@aurel32.net> with
+ the help of Jean Delvare <khali@linux-fr.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/*
+ SiS southbridge has a LM78-like chip integrated on the same IC.
+ This driver is a customized copy of lm78.c
+
+ Supports following revisions:
+ Version PCI ID PCI Revision
+ 1 1039/0008 AF or less
+ 2 1039/0008 B0 or greater
+
+ Note: these chips contain a 0008 device which is incompatible with the
+ 5595. We recognize these by the presence of the listed
+ "blacklist" PCI ID and refuse to load.
+
+ NOT SUPPORTED PCI ID BLACKLIST PCI ID
+ 540 0008 0540
+ 550 0008 0550
+ 5513 0008 5511
+ 5581 0008 5597
+ 5582 0008 5597
+ 5597 0008 5597
+ 5598 0008 5597/5598
+ 630 0008 0630
+ 645 0008 0645
+ 730 0008 0730
+ 735 0008 0735
+*/
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <linux/i2c.h>
+#include <linux/i2c-sensor.h>
+#include <linux/init.h>
+#include <asm/io.h>
+
+
+/* If force_addr is set to anything different from 0, we forcibly enable
+ the device at the given address. */
+static u16 force_addr;
+module_param(force_addr, ushort, 0);
+MODULE_PARM_DESC(force_addr,
+ "Initialize the base address of the sensors");
+
+/* Addresses to scan.
+ Note that we can't determine the ISA address until we have initialized
+ our module */
+static unsigned short normal_i2c[] = { I2C_CLIENT_END };
+static unsigned int normal_isa[] = { 0x0000, I2C_CLIENT_ISA_END };
+
+/* Insmod parameters */
+SENSORS_INSMOD_1(sis5595);
+
+/* Many SIS5595 constants specified below */
+
+/* Length of ISA address segment */
+#define SIS5595_EXTENT 8
+/* PCI Config Registers */
+#define SIS5595_REVISION_REG 0x08
+#define SIS5595_BASE_REG 0x68
+#define SIS5595_PIN_REG 0x7A
+#define SIS5595_ENABLE_REG 0x7B
+
+/* Where are the ISA address/data registers relative to the base address */
+#define SIS5595_ADDR_REG_OFFSET 5
+#define SIS5595_DATA_REG_OFFSET 6
+
+/* The SIS5595 registers */
+#define SIS5595_REG_IN_MAX(nr) (0x2b + (nr) * 2)
+#define SIS5595_REG_IN_MIN(nr) (0x2c + (nr) * 2)
+#define SIS5595_REG_IN(nr) (0x20 + (nr))
+
+#define SIS5595_REG_FAN_MIN(nr) (0x3b + (nr))
+#define SIS5595_REG_FAN(nr) (0x28 + (nr))
+
+/* On the first version of the chip, the temp registers are separate.
+ On the second version,
+ TEMP pin is shared with IN4, configured in PCI register 0x7A.
+ The registers are the same as well.
+ OVER and HYST are really MAX and MIN. */
+
+#define REV2MIN 0xb0
+#define SIS5595_REG_TEMP (( data->revision) >= REV2MIN) ? \
+ SIS5595_REG_IN(4) : 0x27
+#define SIS5595_REG_TEMP_OVER (( data->revision) >= REV2MIN) ? \
+ SIS5595_REG_IN_MAX(4) : 0x39
+#define SIS5595_REG_TEMP_HYST (( data->revision) >= REV2MIN) ? \
+ SIS5595_REG_IN_MIN(4) : 0x3a
+
+#define SIS5595_REG_CONFIG 0x40
+#define SIS5595_REG_ALARM1 0x41
+#define SIS5595_REG_ALARM2 0x42
+#define SIS5595_REG_FANDIV 0x47
+
+/* Conversions. Limit checking is only done on the TO_REG
+ variants. */
+
+/* IN: mV, (0V to 4.08V)
+ REG: 16mV/bit */
+static inline u8 IN_TO_REG(unsigned long val)
+{
+ unsigned long nval = SENSORS_LIMIT(val, 0, 4080);
+ return (nval + 8) / 16;
+}
+#define IN_FROM_REG(val) ((val) * 16)
+
+static inline u8 FAN_TO_REG(long rpm, int div)
+{
+ if (rpm <= 0)
+ return 255;
+ return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 254);
+}
+
+static inline int FAN_FROM_REG(u8 val, int div)
+{
+ return val==0 ? -1 : val==255 ? 0 : 1350000/(val*div);
+}
+
+/* TEMP: mC (-54.12C to +157.53C)
+ REG: 0.83C/bit + 52.12, two's complement */
+static inline int TEMP_FROM_REG(s8 val)
+{
+ return val * 830 + 52120;
+}
+static inline s8 TEMP_TO_REG(int val)
+{
+ int nval = SENSORS_LIMIT(val, -54120, 157530) ;
+ return nval<0 ? (nval-5212-415)/830 : (nval-5212+415)/830;
+}
+
+/* FAN DIV: 1, 2, 4, or 8 (defaults to 2)
+ REG: 0, 1, 2, or 3 (respectively) (defaults to 1) */
+static inline u8 DIV_TO_REG(int val)
+{
+ return val==8 ? 3 : val==4 ? 2 : val==1 ? 0 : 1;
+}
+#define DIV_FROM_REG(val) (1 << (val))
+
+/* For the SIS5595, we need to keep some data in memory. That
+ data is pointed to by sis5595_list[NR]->data. The structure itself is
+ dynamically allocated, at the time when the new sis5595 client is
+ allocated. */
+struct sis5595_data {
+ struct i2c_client client;
+ struct semaphore lock;
+
+ struct semaphore update_lock;
+ char valid; /* !=0 if following fields are valid */
+ unsigned long last_updated; /* In jiffies */
+ char maxins; /* == 3 if temp enabled, otherwise == 4 */
+ u8 revision; /* Reg. value */
+
+ u8 in[5]; /* Register value */
+ u8 in_max[5]; /* Register value */
+ u8 in_min[5]; /* Register value */
+ u8 fan[2]; /* Register value */
+ u8 fan_min[2]; /* Register value */
+ s8 temp; /* Register value */
+ s8 temp_over; /* Register value */
+ s8 temp_hyst; /* Register value */
+ u8 fan_div[2]; /* Register encoding, shifted right */
+ u16 alarms; /* Register encoding, combined */
+};
+
+static struct pci_dev *s_bridge; /* pointer to the (only) sis5595 */
+
+static int sis5595_attach_adapter(struct i2c_adapter *adapter);
+static int sis5595_detect(struct i2c_adapter *adapter, int address, int kind);
+static int sis5595_detach_client(struct i2c_client *client);
+
+static int sis5595_read_value(struct i2c_client *client, u8 register);
+static int sis5595_write_value(struct i2c_client *client, u8 register, u8 value);
+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",
+ .id = I2C_DRIVERID_SIS5595,
+ .flags = I2C_DF_NOTIFY,
+ .attach_adapter = sis5595_attach_adapter,
+ .detach_client = sis5595_detach_client,
+};
+
+/* 4 Voltages */
+static ssize_t show_in(struct device *dev, char *buf, int nr)
+{
+ struct sis5595_data *data = sis5595_update_device(dev);
+ return sprintf(buf, "%d\n", IN_FROM_REG(data->in[nr]));
+}
+
+static ssize_t show_in_min(struct device *dev, char *buf, int nr)
+{
+ struct sis5595_data *data = sis5595_update_device(dev);
+ return sprintf(buf, "%d\n", IN_FROM_REG(data->in_min[nr]));
+}
+
+static ssize_t show_in_max(struct device *dev, char *buf, int nr)
+{
+ struct sis5595_data *data = sis5595_update_device(dev);
+ return sprintf(buf, "%d\n", IN_FROM_REG(data->in_max[nr]));
+}
+
+static ssize_t set_in_min(struct device *dev, const char *buf,
+ size_t count, int nr)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct sis5595_data *data = i2c_get_clientdata(client);
+ unsigned long val = simple_strtoul(buf, NULL, 10);
+ data->in_min[nr] = IN_TO_REG(val);
+ sis5595_write_value(client, SIS5595_REG_IN_MIN(nr), data->in_min[nr]);
+ return count;
+}
+
+static ssize_t set_in_max(struct device *dev, const char *buf,
+ size_t count, int nr)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct sis5595_data *data = i2c_get_clientdata(client);
+ unsigned long val = simple_strtoul(buf, NULL, 10);
+ data->in_max[nr] = IN_TO_REG(val);
+ sis5595_write_value(client, SIS5595_REG_IN_MAX(nr), data->in_max[nr]);
+ return count;
+}
+
+#define show_in_offset(offset) \
+static ssize_t \
+ show_in##offset (struct device *dev, char *buf) \
+{ \
+ return show_in(dev, buf, offset); \
+} \
+static DEVICE_ATTR(in##offset##_input, S_IRUGO, \
+ show_in##offset, NULL); \
+static ssize_t \
+ show_in##offset##_min (struct device *dev, char *buf) \
+{ \
+ return show_in_min(dev, buf, offset); \
+} \
+static ssize_t \
+ show_in##offset##_max (struct device *dev, char *buf) \
+{ \
+ return show_in_max(dev, buf, offset); \
+} \
+static ssize_t set_in##offset##_min (struct device *dev, \
+ const char *buf, size_t count) \
+{ \
+ return set_in_min(dev, buf, count, offset); \
+} \
+static ssize_t set_in##offset##_max (struct device *dev, \
+ const char *buf, size_t count) \
+{ \
+ return set_in_max(dev, buf, count, offset); \
+} \
+static DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \
+ show_in##offset##_min, set_in##offset##_min); \
+static DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \
+ show_in##offset##_max, set_in##offset##_max);
+
+show_in_offset(0);
+show_in_offset(1);
+show_in_offset(2);
+show_in_offset(3);
+show_in_offset(4);
+
+/* Temperature */
+static ssize_t show_temp(struct device *dev, char *buf)
+{
+ struct sis5595_data *data = sis5595_update_device(dev);
+ return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp));
+}
+
+static ssize_t show_temp_over(struct device *dev, char *buf)
+{
+ struct sis5595_data *data = sis5595_update_device(dev);
+ return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_over));
+}
+
+static ssize_t set_temp_over(struct device *dev, const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct sis5595_data *data = i2c_get_clientdata(client);
+ long val = simple_strtol(buf, NULL, 10);
+ data->temp_over = TEMP_TO_REG(val);
+ sis5595_write_value(client, SIS5595_REG_TEMP_OVER, data->temp_over);
+ return count;
+}
+
+static ssize_t show_temp_hyst(struct device *dev, char *buf)
+{
+ struct sis5595_data *data = sis5595_update_device(dev);
+ return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_hyst));
+}
+
+static ssize_t set_temp_hyst(struct device *dev, const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct sis5595_data *data = i2c_get_clientdata(client);
+ long val = simple_strtol(buf, NULL, 10);
+ data->temp_hyst = TEMP_TO_REG(val);
+ sis5595_write_value(client, SIS5595_REG_TEMP_HYST, data->temp_hyst);
+ return count;
+}
+
+static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL);
+static DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR,
+ show_temp_over, set_temp_over);
+static DEVICE_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR,
+ show_temp_hyst, set_temp_hyst);
+
+/* 2 Fans */
+static ssize_t show_fan(struct device *dev, char *buf, int nr)
+{
+ struct sis5595_data *data = sis5595_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, char *buf, int nr)
+{
+ struct sis5595_data *data = sis5595_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 set_fan_min(struct device *dev, const char *buf,
+ size_t count, int nr)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct sis5595_data *data = i2c_get_clientdata(client);
+ unsigned long val = simple_strtoul(buf, NULL, 10);
+ data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
+ sis5595_write_value(client, SIS5595_REG_FAN_MIN(nr), data->fan_min[nr]);
+ return count;
+}
+
+static ssize_t show_fan_div(struct device *dev, char *buf, int nr)
+{
+ struct sis5595_data *data = sis5595_update_device(dev);
+ return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr]) );
+}
+
+/* Note: we save and restore the fan minimum here, because its value is
+ determined in part by the fan divisor. This follows the principle of
+ least suprise; the user doesn't expect the fan minimum to change just
+ because the divisor changed. */
+static ssize_t set_fan_div(struct device *dev, const char *buf,
+ size_t count, int nr)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct sis5595_data *data = i2c_get_clientdata(client);
+ unsigned long min = FAN_FROM_REG(data->fan_min[nr],
+ DIV_FROM_REG(data->fan_div[nr]));
+ unsigned long val = simple_strtoul(buf, NULL, 10);
+ int reg = sis5595_read_value(client, SIS5595_REG_FANDIV);
+ 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);
+ return -EINVAL;
+ }
+
+ switch (nr) {
+ case 0:
+ reg = (reg & 0xcf) | (data->fan_div[nr] << 4);
+ break;
+ case 1:
+ reg = (reg & 0x3f) | (data->fan_div[nr] << 6);
+ break;
+ }
+ sis5595_write_value(client, SIS5595_REG_FANDIV, reg);
+ data->fan_min[nr] =
+ FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr]));
+ sis5595_write_value(client, SIS5595_REG_FAN_MIN(nr), data->fan_min[nr]);
+ return count;
+}
+
+#define show_fan_offset(offset) \
+static ssize_t show_fan_##offset (struct device *dev, char *buf) \
+{ \
+ return show_fan(dev, buf, offset - 1); \
+} \
+static ssize_t show_fan_##offset##_min (struct device *dev, char *buf) \
+{ \
+ return show_fan_min(dev, buf, offset - 1); \
+} \
+static ssize_t show_fan_##offset##_div (struct device *dev, char *buf) \
+{ \
+ return show_fan_div(dev, buf, offset - 1); \
+} \
+static ssize_t set_fan_##offset##_min (struct device *dev, \
+ const char *buf, size_t count) \
+{ \
+ return set_fan_min(dev, buf, count, offset - 1); \
+} \
+static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan_##offset, NULL);\
+static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \
+ show_fan_##offset##_min, set_fan_##offset##_min);
+
+show_fan_offset(1);
+show_fan_offset(2);
+
+static ssize_t set_fan_1_div(struct device *dev, const char *buf,
+ size_t count)
+{
+ return set_fan_div(dev, buf, count, 0) ;
+}
+
+static ssize_t set_fan_2_div(struct device *dev, const char *buf,
+ size_t count)
+{
+ return set_fan_div(dev, buf, count, 1) ;
+}
+static DEVICE_ATTR(fan1_div, S_IRUGO | S_IWUSR,
+ show_fan_1_div, set_fan_1_div);
+static DEVICE_ATTR(fan2_div, S_IRUGO | S_IWUSR,
+ show_fan_2_div, set_fan_2_div);
+
+/* Alarms */
+static ssize_t show_alarms(struct device *dev, char *buf)
+{
+ struct sis5595_data *data = sis5595_update_device(dev);
+ return sprintf(buf, "%d\n", data->alarms);
+}
+static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
+
+/* This is called when the module is loaded */
+static int sis5595_attach_adapter(struct i2c_adapter *adapter)
+{
+ if (!(adapter->class & I2C_CLASS_HWMON))
+ return 0;
+ return i2c_detect(adapter, &addr_data, sis5595_detect);
+}
+
+int sis5595_detect(struct i2c_adapter *adapter, int address, int kind)
+{
+ int err = 0;
+ int i;
+ struct i2c_client *new_client;
+ struct sis5595_data *data;
+ char val;
+ u16 a;
+
+ /* Make sure we are probing the ISA bus!! */
+ if (!i2c_is_isa_adapter(adapter))
+ goto exit;
+
+ if (force_addr)
+ address = force_addr & ~(SIS5595_EXTENT - 1);
+ /* Reserve the ISA region */
+ if (!request_region(address, SIS5595_EXTENT, sis5595_driver.name)) {
+ err = -EBUSY;
+ goto exit;
+ }
+ if (force_addr) {
+ dev_warn(&adapter->dev, "forcing ISA address 0x%04X\n", address);
+ if (PCIBIOS_SUCCESSFUL !=
+ pci_write_config_word(s_bridge, SIS5595_BASE_REG, address))
+ goto exit_release;
+ if (PCIBIOS_SUCCESSFUL !=
+ pci_read_config_word(s_bridge, SIS5595_BASE_REG, &a))
+ goto exit_release;
+ if ((a & ~(SIS5595_EXTENT - 1)) != address)
+ /* doesn't work for some chips? */
+ goto exit_release;
+ }
+
+ if (PCIBIOS_SUCCESSFUL !=
+ pci_read_config_byte(s_bridge, SIS5595_ENABLE_REG, &val)) {
+ goto exit_release;
+ }
+ if ((val & 0x80) == 0) {
+ if (PCIBIOS_SUCCESSFUL !=
+ pci_write_config_byte(s_bridge, SIS5595_ENABLE_REG,
+ val | 0x80))
+ goto exit_release;
+ if (PCIBIOS_SUCCESSFUL !=
+ pci_read_config_byte(s_bridge, SIS5595_ENABLE_REG, &val))
+ goto exit_release;
+ if ((val & 0x80) == 0)
+ /* doesn't work for some chips! */
+ goto exit_release;
+ }
+
+ if (!(data = kmalloc(sizeof(struct sis5595_data), GFP_KERNEL))) {
+ err = -ENOMEM;
+ goto exit_release;
+ }
+ memset(data, 0, sizeof(struct sis5595_data));
+
+ new_client = &data->client;
+ new_client->addr = address;
+ init_MUTEX(&data->lock);
+ i2c_set_clientdata(new_client, data);
+ new_client->adapter = adapter;
+ new_client->driver = &sis5595_driver;
+ new_client->flags = 0;
+
+ /* Check revision and pin registers to determine whether 4 or 5 voltages */
+ pci_read_config_byte(s_bridge, SIS5595_REVISION_REG, &(data->revision));
+ /* 4 voltages, 1 temp */
+ data->maxins = 3;
+ if (data->revision >= REV2MIN) {
+ pci_read_config_byte(s_bridge, SIS5595_PIN_REG, &val);
+ if (!(val & 0x80))
+ /* 5 voltages, no temps */
+ data->maxins = 4;
+ }
+
+ /* Fill in the remaining client fields and put it into the global list */
+ strlcpy(new_client->name, "sis5595", I2C_NAME_SIZE);
+
+ data->valid = 0;
+ init_MUTEX(&data->update_lock);
+
+ /* Tell the I2C layer a new client has arrived */
+ if ((err = i2c_attach_client(new_client)))
+ goto exit_free;
+
+ /* Initialize the SIS5595 chip */
+ sis5595_init_client(new_client);
+
+ /* A few vars need to be filled upon startup */
+ for (i = 0; i < 2; i++) {
+ data->fan_min[i] = sis5595_read_value(new_client,
+ SIS5595_REG_FAN_MIN(i));
+ }
+
+ /* Register sysfs hooks */
+ device_create_file(&new_client->dev, &dev_attr_in0_input);
+ device_create_file(&new_client->dev, &dev_attr_in0_min);
+ device_create_file(&new_client->dev, &dev_attr_in0_max);
+ device_create_file(&new_client->dev, &dev_attr_in1_input);
+ device_create_file(&new_client->dev, &dev_attr_in1_min);
+ device_create_file(&new_client->dev, &dev_attr_in1_max);
+ device_create_file(&new_client->dev, &dev_attr_in2_input);
+ device_create_file(&new_client->dev, &dev_attr_in2_min);
+ device_create_file(&new_client->dev, &dev_attr_in2_max);
+ device_create_file(&new_client->dev, &dev_attr_in3_input);
+ device_create_file(&new_client->dev, &dev_attr_in3_min);
+ device_create_file(&new_client->dev, &dev_attr_in3_max);
+ if (data->maxins == 4) {
+ 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);
+ }
+ device_create_file(&new_client->dev, &dev_attr_fan1_input);
+ device_create_file(&new_client->dev, &dev_attr_fan1_min);
+ device_create_file(&new_client->dev, &dev_attr_fan1_div);
+ device_create_file(&new_client->dev, &dev_attr_fan2_input);
+ device_create_file(&new_client->dev, &dev_attr_fan2_min);
+ device_create_file(&new_client->dev, &dev_attr_fan2_div);
+ device_create_file(&new_client->dev, &dev_attr_alarms);
+ if (data->maxins == 3) {
+ device_create_file(&new_client->dev, &dev_attr_temp1_input);
+ device_create_file(&new_client->dev, &dev_attr_temp1_max);
+ device_create_file(&new_client->dev, &dev_attr_temp1_max_hyst);
+ }
+ return 0;
+
+exit_free:
+ kfree(data);
+exit_release:
+ release_region(address, SIS5595_EXTENT);
+exit:
+ return err;
+}
+
+static int sis5595_detach_client(struct i2c_client *client)
+{
+ int err;
+
+ if ((err = i2c_detach_client(client))) {
+ dev_err(&client->dev,
+ "Client deregistration failed, client not detached.\n");
+ return err;
+ }
+
+ if (i2c_is_isa_client(client))
+ release_region(client->addr, SIS5595_EXTENT);
+
+ kfree(i2c_get_clientdata(client));
+
+ return 0;
+}
+
+
+/* ISA access must be locked explicitly. */
+static int sis5595_read_value(struct i2c_client *client, u8 reg)
+{
+ int res;
+
+ struct sis5595_data *data = i2c_get_clientdata(client);
+ down(&data->lock);
+ outb_p(reg, client->addr + SIS5595_ADDR_REG_OFFSET);
+ res = inb_p(client->addr + SIS5595_DATA_REG_OFFSET);
+ up(&data->lock);
+ return res;
+}
+
+static int sis5595_write_value(struct i2c_client *client, u8 reg, u8 value)
+{
+ struct sis5595_data *data = i2c_get_clientdata(client);
+ down(&data->lock);
+ outb_p(reg, client->addr + SIS5595_ADDR_REG_OFFSET);
+ outb_p(value, client->addr + SIS5595_DATA_REG_OFFSET);
+ up(&data->lock);
+ return 0;
+}
+
+/* Called when we have found a new SIS5595. */
+static void sis5595_init_client(struct i2c_client *client)
+{
+ u8 config = sis5595_read_value(client, SIS5595_REG_CONFIG);
+ if (!(config & 0x01))
+ sis5595_write_value(client, SIS5595_REG_CONFIG,
+ (config & 0xf7) | 0x01);
+}
+
+static struct sis5595_data *sis5595_update_device(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct sis5595_data *data = i2c_get_clientdata(client);
+ int i;
+
+ down(&data->update_lock);
+
+ if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
+ || !data->valid) {
+
+ for (i = 0; i <= data->maxins; i++) {
+ data->in[i] =
+ sis5595_read_value(client, SIS5595_REG_IN(i));
+ data->in_min[i] =
+ sis5595_read_value(client,
+ SIS5595_REG_IN_MIN(i));
+ data->in_max[i] =
+ sis5595_read_value(client,
+ SIS5595_REG_IN_MAX(i));
+ }
+ for (i = 0; i < 2; i++) {
+ data->fan[i] =
+ sis5595_read_value(client, SIS5595_REG_FAN(i));
+ data->fan_min[i] =
+ sis5595_read_value(client,
+ SIS5595_REG_FAN_MIN(i));
+ }
+ if (data->maxins == 3) {
+ data->temp =
+ sis5595_read_value(client, SIS5595_REG_TEMP);
+ data->temp_over =
+ sis5595_read_value(client, SIS5595_REG_TEMP_OVER);
+ data->temp_hyst =
+ sis5595_read_value(client, SIS5595_REG_TEMP_HYST);
+ }
+ i = sis5595_read_value(client, SIS5595_REG_FANDIV);
+ data->fan_div[0] = (i >> 4) & 0x03;
+ data->fan_div[1] = i >> 6;
+ data->alarms =
+ sis5595_read_value(client, SIS5595_REG_ALARM1) |
+ (sis5595_read_value(client, SIS5595_REG_ALARM2) << 8);
+ data->last_updated = jiffies;
+ data->valid = 1;
+ }
+
+ up(&data->update_lock);
+
+ return data;
+}
+
+static struct pci_device_id sis5595_pci_ids[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503) },
+ { 0, }
+};
+
+MODULE_DEVICE_TABLE(pci, sis5595_pci_ids);
+
+static int blacklist[] __devinitdata = {
+ PCI_DEVICE_ID_SI_540,
+ PCI_DEVICE_ID_SI_550,
+ PCI_DEVICE_ID_SI_630,
+ PCI_DEVICE_ID_SI_645,
+ PCI_DEVICE_ID_SI_730,
+ PCI_DEVICE_ID_SI_735,
+ PCI_DEVICE_ID_SI_5511, /* 5513 chip has the 0008 device but
+ that ID shows up in other chips so we
+ use the 5511 ID for recognition */
+ PCI_DEVICE_ID_SI_5597,
+ PCI_DEVICE_ID_SI_5598,
+ 0 };
+
+static int __devinit sis5595_pci_probe(struct pci_dev *dev,
+ const struct pci_device_id *id)
+{
+ u16 val;
+ int *i;
+ int addr = 0;
+
+ for (i = blacklist; *i != 0; i++) {
+ struct pci_dev *dev;
+ dev = pci_get_device(PCI_VENDOR_ID_SI, *i, NULL);
+ if (dev) {
+ dev_err(&dev->dev, "Looked for SIS5595 but found unsupported device %.4x\n", *i);
+ pci_dev_put(dev);
+ return -ENODEV;
+ }
+ }
+
+ if (PCIBIOS_SUCCESSFUL !=
+ pci_read_config_word(dev, SIS5595_BASE_REG, &val))
+ return -ENODEV;
+
+ addr = val & ~(SIS5595_EXTENT - 1);
+ if (addr == 0 && force_addr == 0) {
+ dev_err(&dev->dev, "Base address not set - upgrade BIOS or use force_addr=0xaddr\n");
+ return -ENODEV;
+ }
+ if (force_addr)
+ addr = force_addr; /* so detect will get called */
+
+ if (!addr) {
+ dev_err(&dev->dev,"No SiS 5595 sensors found.\n");
+ return -ENODEV;
+ }
+ normal_isa[0] = addr;
+
+ s_bridge = pci_dev_get(dev);
+ if (i2c_add_driver(&sis5595_driver)) {
+ 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 struct pci_driver sis5595_pci_driver = {
+ .name = "sis5595",
+ .id_table = sis5595_pci_ids,
+ .probe = sis5595_pci_probe,
+};
+
+static int __init sm_sis5595_init(void)
+{
+ return pci_register_driver(&sis5595_pci_driver);
+}
+
+static void __exit sm_sis5595_exit(void)
+{
+ pci_unregister_driver(&sis5595_pci_driver);
+ if (s_bridge != NULL) {
+ i2c_del_driver(&sis5595_driver);
+ pci_dev_put(s_bridge);
+ s_bridge = NULL;
+ }
+}
+
+MODULE_AUTHOR("Aurelien Jarno <aurelien@aurel32.net>");
+MODULE_DESCRIPTION("SiS 5595 Sensor device");
+MODULE_LICENSE("GPL");
+
+module_init(sm_sis5595_init);
+module_exit(sm_sis5595_exit);
diff --git a/drivers/i2c/chips/smsc47b397.c b/drivers/i2c/chips/smsc47b397.c
index aab9f246d7e2a..1119c76791d9e 100644
--- a/drivers/i2c/chips/smsc47b397.c
+++ b/drivers/i2c/chips/smsc47b397.c
@@ -29,6 +29,7 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/ioport.h>
+#include <linux/jiffies.h>
#include <linux/i2c.h>
#include <linux/i2c-sensor.h>
#include <linux/init.h>
@@ -130,9 +131,7 @@ static struct smsc47b397_data *smsc47b397_update_device(struct device *dev)
down(&data->update_lock);
- if (time_after(jiffies - data->last_updated, (unsigned long)HZ)
- || time_before(jiffies, data->last_updated) || !data->valid) {
-
+ if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
dev_dbg(&client->dev, "starting device update...\n");
/* 4 temperature inputs, 4 fan inputs */
diff --git a/drivers/i2c/chips/smsc47m1.c b/drivers/i2c/chips/smsc47m1.c
index c9f0d2b5c967a..8d22390378d79 100644
--- a/drivers/i2c/chips/smsc47m1.c
+++ b/drivers/i2c/chips/smsc47m1.c
@@ -28,6 +28,7 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/ioport.h>
+#include <linux/jiffies.h>
#include <linux/i2c.h>
#include <linux/i2c-sensor.h>
#include <linux/init.h>
@@ -108,7 +109,6 @@ superio_exit(void)
struct smsc47m1_data {
struct i2c_client client;
struct semaphore lock;
- int sysctl_id;
struct semaphore update_lock;
unsigned long last_updated; /* In jiffies */
@@ -133,8 +133,6 @@ static struct smsc47m1_data *smsc47m1_update_device(struct device *dev,
int init);
-static int smsc47m1_id;
-
static struct i2c_driver smsc47m1_driver = {
.owner = THIS_MODULE,
.name = "smsc47m1",
@@ -420,8 +418,6 @@ static int smsc47m1_detect(struct i2c_adapter *adapter, int address, int kind)
new_client->flags = 0;
strlcpy(new_client->name, "smsc47m1", I2C_NAME_SIZE);
-
- new_client->id = smsc47m1_id++;
init_MUTEX(&data->update_lock);
/* If no function is properly configured, there's no point in
@@ -532,8 +528,7 @@ static struct smsc47m1_data *smsc47m1_update_device(struct device *dev,
down(&data->update_lock);
- if ((jiffies - data->last_updated > HZ + HZ / 2) ||
- (jiffies < data->last_updated) || init) {
+ if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || init) {
int i;
for (i = 0; i < 2; i++) {
diff --git a/drivers/i2c/chips/via686a.c b/drivers/i2c/chips/via686a.c
index cacc2578fa040..e6978b2682b8d 100644
--- a/drivers/i2c/chips/via686a.c
+++ b/drivers/i2c/chips/via686a.c
@@ -35,6 +35,7 @@
#include <linux/slab.h>
#include <linux/pci.h>
#include <linux/delay.h>
+#include <linux/jiffies.h>
#include <linux/i2c.h>
#include <linux/i2c-sensor.h>
#include <linux/init.h>
@@ -726,9 +727,8 @@ static struct via686a_data *via686a_update_device(struct device *dev)
down(&data->update_lock);
- if ((jiffies - data->last_updated > HZ + HZ / 2) ||
- (jiffies < data->last_updated) || !data->valid) {
-
+ if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
+ || !data->valid) {
for (i = 0; i <= 4; i++) {
data->in[i] =
via686a_read_value(client, VIA686A_REG_IN(i));
diff --git a/drivers/i2c/chips/w83627hf.c b/drivers/i2c/chips/w83627hf.c
index 697cd43823774..986dba3f0a727 100644
--- a/drivers/i2c/chips/w83627hf.c
+++ b/drivers/i2c/chips/w83627hf.c
@@ -40,6 +40,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
+#include <linux/jiffies.h>
#include <linux/i2c.h>
#include <linux/i2c-sensor.h>
#include <linux/i2c-vid.h>
@@ -1321,6 +1322,27 @@ static void w83627hf_init_client(struct i2c_client *client)
data->pwmenable[2] = 1;
if(init) {
+ /* Enable temp2 */
+ tmp = w83627hf_read_value(client, W83781D_REG_TEMP2_CONFIG);
+ if (tmp & 0x01) {
+ dev_warn(&client->dev, "Enabling temp2, readings "
+ "might not make sense\n");
+ w83627hf_write_value(client, W83781D_REG_TEMP2_CONFIG,
+ tmp & 0xfe);
+ }
+
+ /* Enable temp3 */
+ if (type != w83697hf) {
+ tmp = w83627hf_read_value(client,
+ W83781D_REG_TEMP3_CONFIG);
+ if (tmp & 0x01) {
+ dev_warn(&client->dev, "Enabling temp3, "
+ "readings might not make sense\n");
+ w83627hf_write_value(client,
+ W83781D_REG_TEMP3_CONFIG, tmp & 0xfe);
+ }
+ }
+
if (type == w83627hf) {
/* enable PWM2 control (can't hurt since PWM reg
should have been reset to 0xff) */
@@ -1350,8 +1372,8 @@ static struct w83627hf_data *w83627hf_update_device(struct device *dev)
down(&data->update_lock);
- if ((jiffies - data->last_updated > HZ + HZ / 2) ||
- (jiffies < data->last_updated) || !data->valid) {
+ if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
+ || !data->valid) {
for (i = 0; i <= 8; i++) {
/* skip missing sensors */
if (((data->type == w83697hf) && (i == 1)) ||
diff --git a/drivers/i2c/chips/w83781d.c b/drivers/i2c/chips/w83781d.c
index 06d5bd672ab8e..e893229239d07 100644
--- a/drivers/i2c/chips/w83781d.c
+++ b/drivers/i2c/chips/w83781d.c
@@ -39,6 +39,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
+#include <linux/jiffies.h>
#include <linux/i2c.h>
#include <linux/i2c-sensor.h>
#include <linux/i2c-vid.h>
@@ -1562,11 +1563,28 @@ w83781d_init_client(struct i2c_client *client)
}
#endif /* W83781D_RT */
- if (init) {
+ if (init && type != as99127f) {
+ /* Enable temp2 */
+ tmp = w83781d_read_value(client, W83781D_REG_TEMP2_CONFIG);
+ if (tmp & 0x01) {
+ dev_warn(&client->dev, "Enabling temp2, readings "
+ "might not make sense\n");
+ w83781d_write_value(client, W83781D_REG_TEMP2_CONFIG,
+ tmp & 0xfe);
+ }
+
+ /* Enable temp3 */
if (type != w83783s && type != w83697hf) {
- w83781d_write_value(client, W83781D_REG_TEMP3_CONFIG,
- 0x00);
+ tmp = w83781d_read_value(client,
+ W83781D_REG_TEMP3_CONFIG);
+ if (tmp & 0x01) {
+ dev_warn(&client->dev, "Enabling temp3, "
+ "readings might not make sense\n");
+ w83781d_write_value(client,
+ W83781D_REG_TEMP3_CONFIG, tmp & 0xfe);
+ }
}
+
if (type != w83781d) {
/* enable comparator mode for temp2 and temp3 so
alarm indication will work correctly */
@@ -1592,9 +1610,8 @@ static struct w83781d_data *w83781d_update_device(struct device *dev)
down(&data->update_lock);
- if (time_after
- (jiffies - data->last_updated, (unsigned long) (HZ + HZ / 2))
- || time_before(jiffies, data->last_updated) || !data->valid) {
+ if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
+ || !data->valid) {
dev_dbg(dev, "Starting device update\n");
for (i = 0; i <= 8; i++) {
diff --git a/drivers/i2c/chips/w83l785ts.c b/drivers/i2c/chips/w83l785ts.c
index 66b3b8da02f73..59bbc5881fa60 100644
--- a/drivers/i2c/chips/w83l785ts.c
+++ b/drivers/i2c/chips/w83l785ts.c
@@ -35,6 +35,7 @@
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/slab.h>
+#include <linux/jiffies.h>
#include <linux/i2c.h>
#include <linux/i2c-sensor.h>
@@ -114,12 +115,6 @@ struct w83l785ts_data {
};
/*
- * Internal variables
- */
-
-static int w83l785ts_id = 0;
-
-/*
* Sysfs stuff
*/
@@ -229,7 +224,6 @@ static int w83l785ts_detect(struct i2c_adapter *adapter, int address, int kind)
/* We can fill in the remaining client fields. */
strlcpy(new_client->name, "w83l785ts", I2C_NAME_SIZE);
- new_client->id = w83l785ts_id++;
data->valid = 0;
init_MUTEX(&data->update_lock);
@@ -301,9 +295,7 @@ static struct w83l785ts_data *w83l785ts_update_device(struct device *dev)
down(&data->update_lock);
- if (!data->valid
- || (jiffies - data->last_updated > HZ * 2)
- || (jiffies < data->last_updated)) {
+ if (!data->valid || time_after(jiffies, data->last_updated + HZ * 2)) {
dev_dbg(&client->dev, "Updating w83l785ts data.\n");
data->temp = w83l785ts_read_value(client,
W83L785TS_REG_TEMP, data->temp);
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 42776f1a82c84..56a67457341d4 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -38,12 +38,43 @@ static LIST_HEAD(drivers);
static DECLARE_MUTEX(core_lists);
static DEFINE_IDR(i2c_adapter_idr);
-int i2c_device_probe(struct device *dev)
+/* match always succeeds, as we want the probe() to tell if we really accept this match */
+static int i2c_device_match(struct device *dev, struct device_driver *drv)
+{
+ return 1;
+}
+
+static int i2c_bus_suspend(struct device * dev, pm_message_t state)
+{
+ int rc = 0;
+
+ if (dev->driver && dev->driver->suspend)
+ rc = dev->driver->suspend(dev,state,0);
+ return rc;
+}
+
+static int i2c_bus_resume(struct device * dev)
+{
+ int rc = 0;
+
+ if (dev->driver && dev->driver->resume)
+ rc = dev->driver->resume(dev,0);
+ return rc;
+}
+
+static 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;
}
-int i2c_device_remove(struct device *dev)
+static int i2c_device_remove(struct device *dev)
{
return 0;
}
@@ -523,38 +554,6 @@ void i2c_clients_command(struct i2c_adapter *adap, unsigned int cmd, void *arg)
up(&adap->clist_lock);
}
-
-/* match always succeeds, as we want the probe() to tell if we really accept this match */
-static int i2c_device_match(struct device *dev, struct device_driver *drv)
-{
- return 1;
-}
-
-static int i2c_bus_suspend(struct device * dev, u32 state)
-{
- int rc = 0;
-
- if (dev->driver && dev->driver->suspend)
- rc = dev->driver->suspend(dev,state,0);
- return rc;
-}
-
-static int i2c_bus_resume(struct device * dev)
-{
- int rc = 0;
-
- if (dev->driver && dev->driver->resume)
- rc = dev->driver->resume(dev,0);
- return rc;
-}
-
-struct bus_type i2c_bus_type = {
- .name = "i2c",
- .match = i2c_device_match,
- .suspend = i2c_bus_suspend,
- .resume = i2c_bus_resume,
-};
-
static int __init i2c_init(void)
{
int retval;
@@ -583,7 +582,7 @@ module_exit(i2c_exit);
* ----------------------------------------------------
*/
-int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg msgs[],int num)
+int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num)
{
int ret;
@@ -860,7 +859,7 @@ crc8(u16 data)
/* CRC over count bytes in the first array plus the bytes in the rest
array if it is non-null. rest[0] is the (length of rest) - 1
and is included. */
-u8 i2c_smbus_partial_pec(u8 crc, int count, u8 *first, u8 *rest)
+static u8 i2c_smbus_partial_pec(u8 crc, int count, u8 *first, u8 *rest)
{
int i;
@@ -872,7 +871,7 @@ u8 i2c_smbus_partial_pec(u8 crc, int count, u8 *first, u8 *rest)
return crc;
}
-u8 i2c_smbus_pec(int count, u8 *first, u8 *rest)
+static u8 i2c_smbus_pec(int count, u8 *first, u8 *rest)
{
return i2c_smbus_partial_pec(0, count, first, rest);
}
@@ -880,8 +879,8 @@ u8 i2c_smbus_pec(int count, u8 *first, u8 *rest)
/* Returns new "size" (transaction type)
Note that we convert byte to byte_data and byte_data to word_data
rather than invent new xxx_PEC transactions. */
-int i2c_smbus_add_pec(u16 addr, u8 command, int size,
- union i2c_smbus_data *data)
+static int i2c_smbus_add_pec(u16 addr, u8 command, int size,
+ union i2c_smbus_data *data)
{
u8 buf[3];
@@ -910,8 +909,8 @@ int i2c_smbus_add_pec(u16 addr, u8 command, int size,
return size;
}
-int i2c_smbus_check_pec(u16 addr, u8 command, int size, u8 partial,
- union i2c_smbus_data *data)
+static int i2c_smbus_check_pec(u16 addr, u8 command, int size, u8 partial,
+ union i2c_smbus_data *data)
{
u8 buf[3], rpec, cpec;
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
index b829c571fc270..86c4d0149e825 100644
--- a/drivers/i2c/i2c-dev.c
+++ b/drivers/i2c/i2c-dev.c
@@ -55,7 +55,7 @@ struct i2c_dev {
static struct i2c_dev *i2c_dev_array[I2C_MINORS];
static DEFINE_SPINLOCK(i2c_dev_array_lock);
-struct i2c_dev *i2c_dev_get_by_minor(unsigned index)
+static struct i2c_dev *i2c_dev_get_by_minor(unsigned index)
{
struct i2c_dev *i2c_dev;
@@ -65,7 +65,7 @@ struct i2c_dev *i2c_dev_get_by_minor(unsigned index)
return i2c_dev;
}
-struct i2c_dev *i2c_dev_get_by_adapter(struct i2c_adapter *adap)
+static struct i2c_dev *i2c_dev_get_by_adapter(struct i2c_adapter *adap)
{
struct i2c_dev *i2c_dev = NULL;
@@ -108,13 +108,6 @@ static void return_i2c_dev(struct i2c_dev *i2c_dev)
spin_unlock(&i2c_dev_array_lock);
}
-static ssize_t show_dev(struct class_device *class_dev, char *buf)
-{
- struct i2c_dev *i2c_dev = to_i2c_dev(class_dev);
- return print_dev_t(buf, MKDEV(I2C_MAJOR, i2c_dev->minor));
-}
-static CLASS_DEVICE_ATTR(dev, S_IRUGO, show_dev, NULL);
-
static ssize_t show_adapter_name(struct class_device *class_dev, char *buf)
{
struct i2c_dev *i2c_dev = to_i2c_dev(class_dev);
@@ -173,8 +166,8 @@ static ssize_t i2cdev_write (struct file *file, const char __user *buf, size_t c
return ret;
}
-int i2cdev_ioctl (struct inode *inode, struct file *file, unsigned int cmd,
- unsigned long arg)
+static int i2cdev_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
{
struct i2c_client *client = (struct i2c_client *)file->private_data;
struct i2c_rdwr_ioctl_data rdwr_arg;
@@ -451,11 +444,11 @@ static int i2cdev_attach_adapter(struct i2c_adapter *adap)
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)
goto error;
- class_device_create_file(&i2c_dev->class_dev, &class_device_attr_dev);
class_device_create_file(&i2c_dev->class_dev, &class_device_attr_name);
return 0;
error:
@@ -507,7 +500,6 @@ static struct i2c_driver i2cdev_driver = {
static struct i2c_client i2cdev_client_template = {
.name = "I2C /dev entry",
- .id = 1,
.addr = -1,
.driver = &i2cdev_driver,
};
diff --git a/drivers/i2c/i2c-sensor-detect.c b/drivers/i2c/i2c-sensor-detect.c
index 44a4a3546ad76..f99a8161a9f14 100644
--- a/drivers/i2c/i2c-sensor-detect.c
+++ b/drivers/i2c/i2c-sensor-detect.c
@@ -19,17 +19,10 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/ctype.h>
-#include <linux/sysctl.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
#include <linux/i2c.h>
#include <linux/i2c-sensor.h>
-#include <asm/uaccess.h>
static unsigned short empty[] = {I2C_CLIENT_END};
static unsigned int empty_isa[] = {I2C_CLIENT_ISA_END};
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig
index 5a21d809c43ac..3ac0a535b4aa2 100644
--- a/drivers/ide/Kconfig
+++ b/drivers/ide/Kconfig
@@ -150,7 +150,6 @@ config BLK_DEV_IDEDISK
config IDEDISK_MULTI_MODE
bool "Use multi-mode by default"
- depends on BLK_DEV_IDEDISK
help
If you get this error, try to say Y here:
diff --git a/drivers/ide/arm/icside.c b/drivers/ide/arm/icside.c
index e63ff1db270dd..308897e57e4db 100644
--- a/drivers/ide/arm/icside.c
+++ b/drivers/ide/arm/icside.c
@@ -713,7 +713,7 @@ static int __devinit
icside_probe(struct expansion_card *ec, const struct ecard_id *id)
{
struct icside_state *state;
- void *idmem;
+ void __iomem *idmem;
int ret;
ret = ecard_request_resources(ec);
diff --git a/drivers/ide/arm/rapide.c b/drivers/ide/arm/rapide.c
index b0a115d1aea9b..3058217767d62 100644
--- a/drivers/ide/arm/rapide.c
+++ b/drivers/ide/arm/rapide.c
@@ -17,7 +17,7 @@
* Something like this really should be in generic code, but isn't.
*/
static ide_hwif_t *
-rapide_locate_hwif(void __iomem *base, void *ctrl, unsigned int sz, int irq)
+rapide_locate_hwif(void __iomem *base, void __iomem *ctrl, unsigned int sz, int irq)
{
unsigned long port = (unsigned long)base;
ide_hwif_t *hwif;
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index a4ad198c4e25d..4b96aa193161f 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -324,6 +324,33 @@
#include "ide-cd.h"
+static DECLARE_MUTEX(idecd_ref_sem);
+
+#define to_ide_cd(obj) container_of(obj, struct cdrom_info, kref)
+
+#define ide_cd_g(disk) ((disk)->private_data)
+
+static struct cdrom_info *ide_cd_get(struct gendisk *disk)
+{
+ struct cdrom_info *cd = NULL;
+
+ down(&idecd_ref_sem);
+ cd = ide_cd_g(disk);
+ if (cd)
+ kref_get(&cd->kref);
+ up(&idecd_ref_sem);
+ return cd;
+}
+
+static void ide_cd_release(struct kref *);
+
+static void ide_cd_put(struct cdrom_info *cd)
+{
+ down(&idecd_ref_sem);
+ kref_put(&cd->kref, ide_cd_release);
+ up(&idecd_ref_sem);
+}
+
/****************************************************************************
* Generic packet command support and error handling routines.
*/
@@ -3088,7 +3115,6 @@ int ide_cdrom_setup (ide_drive_t *drive)
drive->queue->unplug_delay = 1;
drive->special.all = 0;
- drive->ready_stat = 0;
CDROM_STATE_FLAGS(drive)->media_changed = 1;
CDROM_STATE_FLAGS(drive)->toc_valid = 0;
@@ -3226,14 +3252,27 @@ static
int ide_cdrom_cleanup(ide_drive_t *drive)
{
struct cdrom_info *info = drive->driver_data;
- struct cdrom_device_info *devinfo = &info->devinfo;
- struct gendisk *g = drive->disk;
if (ide_unregister_subdriver(drive)) {
printk(KERN_ERR "%s: %s: failed to ide_unregister_subdriver\n",
__FUNCTION__, drive->name);
return 1;
}
+
+ del_gendisk(drive->disk);
+
+ ide_cd_put(info);
+
+ return 0;
+}
+
+static void ide_cd_release(struct kref *kref)
+{
+ struct cdrom_info *info = to_ide_cd(kref);
+ struct cdrom_device_info *devinfo = &info->devinfo;
+ ide_drive_t *drive = info->drive;
+ struct gendisk *g = drive->disk;
+
if (info->buffer != NULL)
kfree(info->buffer);
if (info->toc != NULL)
@@ -3241,56 +3280,36 @@ int ide_cdrom_cleanup(ide_drive_t *drive)
if (info->changer_info != NULL)
kfree(info->changer_info);
if (devinfo->handle == drive && unregister_cdrom(devinfo))
- printk(KERN_ERR "%s: ide_cdrom_cleanup failed to unregister device from the cdrom driver.\n", drive->name);
- kfree(info);
+ printk(KERN_ERR "%s: %s failed to unregister device from the cdrom "
+ "driver.\n", __FUNCTION__, drive->name);
drive->driver_data = NULL;
blk_queue_prep_rq(drive->queue, NULL);
- del_gendisk(g);
+ g->private_data = NULL;
g->fops = ide_fops;
- return 0;
+ kfree(info);
}
static int ide_cdrom_attach (ide_drive_t *drive);
-/*
- * Power Management state machine.
- *
- * We don't do much for CDs right now.
- */
-
-static void ide_cdrom_complete_power_step (ide_drive_t *drive, struct request *rq, u8 stat, u8 error)
-{
-}
-
-static ide_startstop_t ide_cdrom_start_power_step (ide_drive_t *drive, struct request *rq)
+#ifdef CONFIG_PROC_FS
+static int proc_idecd_read_capacity
+ (char *page, char **start, off_t off, int count, int *eof, void *data)
{
- ide_task_t *args = rq->special;
-
- memset(args, 0, sizeof(*args));
-
- switch (rq->pm->pm_step) {
- case ide_pm_state_start_suspend:
- break;
+ ide_drive_t*drive = (ide_drive_t *)data;
+ int len;
- case ide_pm_state_start_resume: /* Resume step 1 (restore DMA) */
- /*
- * Right now, all we do is call hwif->ide_dma_check(drive),
- * we could be smarter and check for current xfer_speed
- * in struct drive etc...
- * Also, this step could be implemented as a generic helper
- * as most subdrivers will use it.
- */
- if ((drive->id->capability & 1) == 0)
- break;
- if (HWIF(drive)->ide_dma_check == NULL)
- break;
- HWIF(drive)->ide_dma_check(drive);
- break;
- }
- rq->pm->pm_step = ide_pm_state_completed;
- return ide_stopped;
+ len = sprintf(page,"%llu\n", (long long)ide_cdrom_capacity(drive));
+ PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
}
+static ide_proc_entry_t idecd_proc[] = {
+ { "capacity", S_IFREG|S_IRUGO, proc_idecd_read_capacity, NULL },
+ { NULL, 0, NULL, NULL }
+};
+#else
+# define idecd_proc NULL
+#endif
+
static ide_driver_t ide_cdrom_driver = {
.owner = THIS_MODULE,
.name = "ide-cdrom",
@@ -3300,18 +3319,26 @@ static ide_driver_t ide_cdrom_driver = {
.supports_dsc_overlap = 1,
.cleanup = ide_cdrom_cleanup,
.do_request = ide_do_rw_cdrom,
- .capacity = ide_cdrom_capacity,
+ .end_request = ide_end_request,
+ .error = __ide_error,
+ .abort = __ide_abort,
+ .proc = idecd_proc,
.attach = ide_cdrom_attach,
.drives = LIST_HEAD_INIT(ide_cdrom_driver.drives),
- .start_power_step = ide_cdrom_start_power_step,
- .complete_power_step = ide_cdrom_complete_power_step,
};
static int idecd_open(struct inode * inode, struct file * file)
{
- ide_drive_t *drive = inode->i_bdev->bd_disk->private_data;
- struct cdrom_info *info = drive->driver_data;
+ struct gendisk *disk = inode->i_bdev->bd_disk;
+ struct cdrom_info *info;
+ ide_drive_t *drive;
int rc = -ENOMEM;
+
+ if (!(info = ide_cd_get(disk)))
+ return -ENXIO;
+
+ drive = info->drive;
+
drive->usage++;
if (!info->buffer)
@@ -3319,16 +3346,24 @@ static int idecd_open(struct inode * inode, struct file * file)
GFP_KERNEL|__GFP_REPEAT);
if (!info->buffer || (rc = cdrom_open(&info->devinfo, inode, file)))
drive->usage--;
+
+ if (rc < 0)
+ ide_cd_put(info);
+
return rc;
}
static int idecd_release(struct inode * inode, struct file * file)
{
- ide_drive_t *drive = inode->i_bdev->bd_disk->private_data;
- struct cdrom_info *info = drive->driver_data;
+ struct gendisk *disk = inode->i_bdev->bd_disk;
+ struct cdrom_info *info = ide_cd_g(disk);
+ ide_drive_t *drive = info->drive;
cdrom_release (&info->devinfo, file);
drive->usage--;
+
+ ide_cd_put(info);
+
return 0;
}
@@ -3336,27 +3371,27 @@ static int idecd_ioctl (struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
struct block_device *bdev = inode->i_bdev;
- ide_drive_t *drive = bdev->bd_disk->private_data;
- int err = generic_ide_ioctl(file, bdev, cmd, arg);
- if (err == -EINVAL) {
- struct cdrom_info *info = drive->driver_data;
+ struct cdrom_info *info = ide_cd_g(bdev->bd_disk);
+ int err;
+
+ err = generic_ide_ioctl(info->drive, file, bdev, cmd, arg);
+ if (err == -EINVAL)
err = cdrom_ioctl(file, &info->devinfo, inode, cmd, arg);
- }
+
return err;
}
static int idecd_media_changed(struct gendisk *disk)
{
- ide_drive_t *drive = disk->private_data;
- struct cdrom_info *info = drive->driver_data;
+ struct cdrom_info *info = ide_cd_g(disk);
return cdrom_media_changed(&info->devinfo);
}
static int idecd_revalidate_disk(struct gendisk *disk)
{
- ide_drive_t *drive = disk->private_data;
+ struct cdrom_info *info = ide_cd_g(disk);
struct request_sense sense;
- cdrom_read_toc(drive, &sense);
+ cdrom_read_toc(info->drive, &sense);
return 0;
}
@@ -3410,7 +3445,12 @@ static int ide_cdrom_attach (ide_drive_t *drive)
goto failed;
}
memset(info, 0, sizeof (struct cdrom_info));
+
+ kref_init(&info->kref);
+
+ info->drive = drive;
drive->driver_data = info;
+
DRIVER(drive)->busy++;
g->minors = 1;
snprintf(g->devfs_name, sizeof(g->devfs_name),
@@ -3437,6 +3477,7 @@ static int ide_cdrom_attach (ide_drive_t *drive)
cdrom_read_toc(drive, &sense);
g->fops = &idecd_ops;
+ g->private_data = info;
g->flags |= GENHD_FL_REMOVABLE;
add_disk(g);
return 0;
diff --git a/drivers/ide/ide-cd.h b/drivers/ide/ide-cd.h
index 20a01dfa004c7..171c65eb31385 100644
--- a/drivers/ide/ide-cd.h
+++ b/drivers/ide/ide-cd.h
@@ -460,6 +460,8 @@ struct atapi_changer_info {
/* Extra per-device info for cdrom drives. */
struct cdrom_info {
+ ide_drive_t *drive;
+ struct kref kref;
/* Buffer for table of contents. NULL if we haven't allocated
a TOC buffer for this device yet. */
diff --git a/drivers/ide/ide-default.c b/drivers/ide/ide-default.c
index 99fc59db01883..8b0c8520f7ce6 100644
--- a/drivers/ide/ide-default.c
+++ b/drivers/ide/ide-default.c
@@ -38,6 +38,12 @@
static int idedefault_attach(ide_drive_t *drive);
+static ide_startstop_t idedefault_do_request(ide_drive_t *drive, struct request *rq, sector_t block)
+{
+ ide_end_request(drive, 0, 0);
+ return ide_stopped;
+}
+
/*
* IDE subdriver functions, registered with ide.c
*/
@@ -47,6 +53,10 @@ ide_driver_t idedefault_driver = {
.version = IDEDEFAULT_VERSION,
.attach = idedefault_attach,
.cleanup = ide_unregister_subdriver,
+ .do_request = idedefault_do_request,
+ .end_request = ide_end_request,
+ .error = __ide_error,
+ .abort = __ide_abort,
.drives = LIST_HEAD_INIT(idedefault_driver.drives)
};
@@ -57,13 +67,6 @@ static int idedefault_attach (ide_drive_t *drive)
"driver with ide.c\n", drive->name);
return 1;
}
-
- /* For the sake of the request layer, we must make sure we have a
- * correct ready_stat value, that is 0 for ATAPI devices or we will
- * fail any request like Power Management
- */
- if (drive->media != ide_disk)
- drive->ready_stat = 0;
return 0;
}
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index 0c7632c7374b0..9636135ee0779 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -71,6 +71,38 @@
#include <asm/io.h>
#include <asm/div64.h>
+struct ide_disk_obj {
+ ide_drive_t *drive;
+ struct kref kref;
+};
+
+static DECLARE_MUTEX(idedisk_ref_sem);
+
+#define to_ide_disk(obj) container_of(obj, struct ide_disk_obj, kref)
+
+#define ide_disk_g(disk) ((disk)->private_data)
+
+static struct ide_disk_obj *ide_disk_get(struct gendisk *disk)
+{
+ struct ide_disk_obj *idkp = NULL;
+
+ down(&idedisk_ref_sem);
+ idkp = ide_disk_g(disk);
+ if (idkp)
+ kref_get(&idkp->kref);
+ up(&idedisk_ref_sem);
+ return idkp;
+}
+
+static void ide_disk_release(struct kref *);
+
+static void ide_disk_put(struct ide_disk_obj *idkp)
+{
+ down(&idedisk_ref_sem);
+ kref_put(&idkp->kref, ide_disk_release);
+ up(&idedisk_ref_sem);
+}
+
/*
* lba_capacity_is_ok() performs a sanity check on the claimed "lba_capacity"
* value for this drive (from its reported identification information).
@@ -119,9 +151,8 @@ static int lba_capacity_is_ok (struct hd_driveid *id)
/*
* __ide_do_rw_disk() issues READ and WRITE commands to a disk,
* using LBA if supported, or CHS otherwise, to address sectors.
- * It also takes care of issuing special DRIVE_CMDs.
*/
-ide_startstop_t __ide_do_rw_disk (ide_drive_t *drive, struct request *rq, sector_t block)
+static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq, sector_t block)
{
ide_hwif_t *hwif = HWIF(drive);
unsigned int dma = drive->using_dma;
@@ -134,6 +165,8 @@ ide_startstop_t __ide_do_rw_disk (ide_drive_t *drive, struct request *rq, sector
if (hwif->no_lba48_dma && lba48 && dma) {
if (block + rq->nr_sectors > 1ULL << 28)
dma = 0;
+ else
+ lba48 = 0;
}
if (!dma) {
@@ -147,7 +180,7 @@ ide_startstop_t __ide_do_rw_disk (ide_drive_t *drive, struct request *rq, sector
/* FIXME: SELECT_MASK(drive, 0) ? */
if (drive->select.b.lba) {
- if (drive->addressing == 1) {
+ if (lba48) {
task_ioreg_t tasklets[10];
pr_debug("%s: LBA=0x%012llx\n", drive->name, block);
@@ -256,7 +289,6 @@ ide_startstop_t __ide_do_rw_disk (ide_drive_t *drive, struct request *rq, sector
return pre_task_out_intr(drive, rq);
}
}
-EXPORT_SYMBOL_GPL(__ide_do_rw_disk);
/*
* 268435455 == 137439 MB or 28bit limit
@@ -281,9 +313,9 @@ static ide_startstop_t ide_do_rw_disk (ide_drive_t *drive, struct request *rq, s
block, rq->nr_sectors, (unsigned long)rq->buffer);
if (hwif->rw_disk)
- return hwif->rw_disk(drive, rq, block);
- else
- return __ide_do_rw_disk(drive, rq, block);
+ hwif->rw_disk(drive, rq);
+
+ return __ide_do_rw_disk(drive, rq, block);
}
/*
@@ -516,75 +548,6 @@ static sector_t idedisk_capacity (ide_drive_t *drive)
return drive->capacity64 - drive->sect0;
}
-#define IS_PDC4030_DRIVE 0
-
-static ide_startstop_t idedisk_special (ide_drive_t *drive)
-{
- special_t *s = &drive->special;
-
- if (s->b.set_geometry) {
- s->b.set_geometry = 0;
- if (!IS_PDC4030_DRIVE) {
- ide_task_t args;
- memset(&args, 0, sizeof(ide_task_t));
- args.tfRegister[IDE_NSECTOR_OFFSET] = drive->sect;
- args.tfRegister[IDE_SECTOR_OFFSET] = drive->sect;
- args.tfRegister[IDE_LCYL_OFFSET] = drive->cyl;
- args.tfRegister[IDE_HCYL_OFFSET] = drive->cyl>>8;
- args.tfRegister[IDE_SELECT_OFFSET] = ((drive->head-1)|drive->select.all)&0xBF;
- args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SPECIFY;
- args.command_type = IDE_DRIVE_TASK_NO_DATA;
- args.handler = &set_geometry_intr;
- do_rw_taskfile(drive, &args);
- }
- } else if (s->b.recalibrate) {
- s->b.recalibrate = 0;
- if (!IS_PDC4030_DRIVE) {
- ide_task_t args;
- memset(&args, 0, sizeof(ide_task_t));
- args.tfRegister[IDE_NSECTOR_OFFSET] = drive->sect;
- args.tfRegister[IDE_COMMAND_OFFSET] = WIN_RESTORE;
- args.command_type = IDE_DRIVE_TASK_NO_DATA;
- args.handler = &recal_intr;
- do_rw_taskfile(drive, &args);
- }
- } else if (s->b.set_multmode) {
- s->b.set_multmode = 0;
- if (drive->mult_req > drive->id->max_multsect)
- drive->mult_req = drive->id->max_multsect;
- if (!IS_PDC4030_DRIVE) {
- ide_task_t args;
- memset(&args, 0, sizeof(ide_task_t));
- args.tfRegister[IDE_NSECTOR_OFFSET] = drive->mult_req;
- args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SETMULT;
- args.command_type = IDE_DRIVE_TASK_NO_DATA;
- args.handler = &set_multmode_intr;
- do_rw_taskfile(drive, &args);
- }
- } else if (s->all) {
- int special = s->all;
- s->all = 0;
- printk(KERN_ERR "%s: bad special flag: 0x%02x\n", drive->name, special);
- return ide_stopped;
- }
- return IS_PDC4030_DRIVE ? ide_stopped : ide_started;
-}
-
-static void idedisk_pre_reset (ide_drive_t *drive)
-{
- int legacy = (drive->id->cfs_enable_2 & 0x0400) ? 0 : 1;
-
- drive->special.all = 0;
- drive->special.b.set_geometry = legacy;
- drive->special.b.recalibrate = legacy;
- if (OK_TO_RESET_CONTROLLER)
- drive->mult_count = 0;
- if (!drive->keep_settings && !drive->using_dma)
- drive->mult_req = 0;
- if (drive->mult_req != drive->mult_count)
- drive->special.b.set_multmode = 1;
-}
-
#ifdef CONFIG_PROC_FS
static int smart_enable(ide_drive_t *drive)
@@ -648,6 +611,16 @@ static int proc_idedisk_read_cache
PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
}
+static int proc_idedisk_read_capacity
+ (char *page, char **start, off_t off, int count, int *eof, void *data)
+{
+ ide_drive_t*drive = (ide_drive_t *)data;
+ int len;
+
+ len = sprintf(page,"%llu\n", (long long)idedisk_capacity(drive));
+ PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
+}
+
static int proc_idedisk_read_smart_thresholds
(char *page, char **start, off_t off, int count, int *eof, void *data)
{
@@ -688,6 +661,7 @@ static int proc_idedisk_read_smart_values
static ide_proc_entry_t idedisk_proc[] = {
{ "cache", S_IFREG|S_IRUGO, proc_idedisk_read_cache, NULL },
+ { "capacity", S_IFREG|S_IRUGO, proc_idedisk_read_capacity, NULL },
{ "geometry", S_IFREG|S_IRUGO, proc_ide_read_geometry, NULL },
{ "smart_values", S_IFREG|S_IRUSR, proc_idedisk_read_smart_values, NULL },
{ "smart_thresholds", S_IFREG|S_IRUSR, proc_idedisk_read_smart_thresholds, NULL },
@@ -700,18 +674,51 @@ static ide_proc_entry_t idedisk_proc[] = {
#endif /* CONFIG_PROC_FS */
-static int idedisk_issue_flush(request_queue_t *q, struct gendisk *disk,
- sector_t *error_sector)
+static void idedisk_end_flush(request_queue_t *q, struct request *flush_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;
- struct request *rq;
- int ret;
if (!drive->wcache)
return 0;
- rq = blk_get_request(q, WRITE, __GFP_WAIT);
-
memset(rq->cmd, 0, sizeof(rq->cmd));
if (ide_id_has_flush_cache_ext(drive->id) &&
@@ -723,6 +730,22 @@ static int idedisk_issue_flush(request_queue_t *q, struct gendisk *disk,
rq->flags |= REQ_DRIVE_TASK | REQ_SOFTBARRIER;
rq->buffer = rq->cmd;
+ return 1;
+}
+
+static int idedisk_issue_flush(request_queue_t *q, struct gendisk *disk,
+ sector_t *error_sector)
+{
+ ide_drive_t *drive = q->queuedata;
+ struct request *rq;
+ int ret;
+
+ if (!drive->wcache)
+ return 0;
+
+ rq = blk_get_request(q, WRITE, __GFP_WAIT);
+
+ idedisk_prepare_flush(q, rq);
ret = blk_execute_rq(q, disk, rq);
@@ -854,90 +877,6 @@ static void idedisk_add_settings(ide_drive_t *drive)
ide_add_setting(drive, "max_failures", SETTING_RW, -1, -1, TYPE_INT, 0, 65535, 1, 1, &drive->max_failures, NULL);
}
-/*
- * Power Management state machine. This one is rather trivial for now,
- * we should probably add more, like switching back to PIO on suspend
- * to help some BIOSes, re-do the door locking on resume, etc...
- */
-
-enum {
- idedisk_pm_flush_cache = ide_pm_state_start_suspend,
- idedisk_pm_standby,
-
- idedisk_pm_idle = ide_pm_state_start_resume,
- idedisk_pm_restore_dma,
-};
-
-static void idedisk_complete_power_step (ide_drive_t *drive, struct request *rq, u8 stat, u8 error)
-{
- switch (rq->pm->pm_step) {
- case idedisk_pm_flush_cache: /* Suspend step 1 (flush cache) complete */
- if (rq->pm->pm_state == 4)
- rq->pm->pm_step = ide_pm_state_completed;
- else
- rq->pm->pm_step = idedisk_pm_standby;
- break;
- case idedisk_pm_standby: /* Suspend step 2 (standby) complete */
- rq->pm->pm_step = ide_pm_state_completed;
- break;
- case idedisk_pm_idle: /* Resume step 1 (idle) complete */
- rq->pm->pm_step = idedisk_pm_restore_dma;
- break;
- }
-}
-
-static ide_startstop_t idedisk_start_power_step (ide_drive_t *drive, struct request *rq)
-{
- ide_task_t *args = rq->special;
-
- memset(args, 0, sizeof(*args));
-
- switch (rq->pm->pm_step) {
- case idedisk_pm_flush_cache: /* Suspend step 1 (flush cache) */
- /* Not supported? Switch to next step now. */
- if (!drive->wcache || !ide_id_has_flush_cache(drive->id)) {
- idedisk_complete_power_step(drive, rq, 0, 0);
- return ide_stopped;
- }
- if (ide_id_has_flush_cache_ext(drive->id))
- args->tfRegister[IDE_COMMAND_OFFSET] = WIN_FLUSH_CACHE_EXT;
- else
- args->tfRegister[IDE_COMMAND_OFFSET] = WIN_FLUSH_CACHE;
- args->command_type = IDE_DRIVE_TASK_NO_DATA;
- args->handler = &task_no_data_intr;
- return do_rw_taskfile(drive, args);
-
- case idedisk_pm_standby: /* Suspend step 2 (standby) */
- args->tfRegister[IDE_COMMAND_OFFSET] = WIN_STANDBYNOW1;
- args->command_type = IDE_DRIVE_TASK_NO_DATA;
- args->handler = &task_no_data_intr;
- return do_rw_taskfile(drive, args);
-
- case idedisk_pm_idle: /* Resume step 1 (idle) */
- args->tfRegister[IDE_COMMAND_OFFSET] = WIN_IDLEIMMEDIATE;
- args->command_type = IDE_DRIVE_TASK_NO_DATA;
- args->handler = task_no_data_intr;
- return do_rw_taskfile(drive, args);
-
- case idedisk_pm_restore_dma: /* Resume step 2 (restore DMA) */
- /*
- * Right now, all we do is call hwif->ide_dma_check(drive),
- * we could be smarter and check for current xfer_speed
- * in struct drive etc...
- * Also, this step could be implemented as a generic helper
- * as most subdrivers will use it
- */
- if ((drive->id->capability & 1) == 0)
- break;
- if (HWIF(drive)->ide_dma_check == NULL)
- break;
- HWIF(drive)->ide_dma_check(drive);
- break;
- }
- rq->pm->pm_step = ide_pm_state_completed;
- return ide_stopped;
-}
-
static void idedisk_setup (ide_drive_t *drive)
{
struct hd_driveid *id = drive->id;
@@ -976,28 +915,6 @@ static void idedisk_setup (ide_drive_t *drive)
printk(KERN_INFO "%s: max request size: %dKiB\n", drive->name, drive->queue->max_sectors / 2);
- /* Extract geometry if we did not already have one for the drive */
- if (!drive->cyl || !drive->head || !drive->sect) {
- drive->cyl = drive->bios_cyl = id->cyls;
- drive->head = drive->bios_head = id->heads;
- drive->sect = drive->bios_sect = id->sectors;
- }
-
- /* Handle logical geometry translation by the drive */
- if ((id->field_valid & 1) && id->cur_cyls &&
- id->cur_heads && (id->cur_heads <= 16) && id->cur_sectors) {
- drive->cyl = id->cur_cyls;
- drive->head = id->cur_heads;
- drive->sect = id->cur_sectors;
- }
-
- /* Use physical geometry if what we have still makes no sense */
- if (drive->head > 16 && id->heads && id->heads <= 16) {
- drive->cyl = id->cyls;
- drive->head = id->heads;
- drive->sect = id->sectors;
- }
-
/* calculate drive capacity, and select LBA if possible */
init_idedisk_capacity (drive);
@@ -1061,21 +978,6 @@ static void idedisk_setup (ide_drive_t *drive)
ide_dma_verbose(drive);
printk("\n");
- drive->mult_count = 0;
- if (id->max_multsect) {
-#ifdef CONFIG_IDEDISK_MULTI_MODE
- id->multsect = ((id->max_multsect/2) > 1) ? id->max_multsect : 0;
- id->multsect_valid = id->multsect ? 1 : 0;
- drive->mult_req = id->multsect_valid ? id->max_multsect : INITIAL_MULT_COUNT;
- drive->special.b.set_multmode = drive->mult_req ? 1 : 0;
-#else /* original, pre IDE-NFG, per request of AC */
- drive->mult_req = INITIAL_MULT_COUNT;
- if (drive->mult_req > id->max_multsect)
- drive->mult_req = id->max_multsect;
- if (drive->mult_req || ((id->multsect_valid & 1) && id->multsect))
- drive->special.b.set_multmode = 1;
-#endif /* CONFIG_IDEDISK_MULTI_MODE */
- }
drive->no_io_32bit = id->dword_io ? 1 : 0;
/* write cache enabled? */
@@ -1100,10 +1002,12 @@ static void idedisk_setup (ide_drive_t *drive)
barrier = 0;
}
- printk(KERN_DEBUG "%s: cache flushes %ssupported\n",
+ printk(KERN_INFO "%s: cache flushes %ssupported\n",
drive->name, barrier ? "" : "not ");
if (barrier) {
- blk_queue_ordered(drive->queue, 1);
+ 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);
}
}
@@ -1119,14 +1023,30 @@ static void ide_cacheflush_p(ide_drive_t *drive)
static int idedisk_cleanup (ide_drive_t *drive)
{
+ struct ide_disk_obj *idkp = drive->driver_data;
struct gendisk *g = drive->disk;
+
ide_cacheflush_p(drive);
if (ide_unregister_subdriver(drive))
return 1;
del_gendisk(g);
+
+ ide_disk_put(idkp);
+
+ return 0;
+}
+
+static void ide_disk_release(struct kref *kref)
+{
+ struct ide_disk_obj *idkp = to_ide_disk(kref);
+ ide_drive_t *drive = idkp->drive;
+ struct gendisk *g = drive->disk;
+
+ drive->driver_data = NULL;
drive->devfs_name[0] = '\0';
+ g->private_data = NULL;
g->fops = ide_fops;
- return 0;
+ kfree(idkp);
}
static int idedisk_attach(ide_drive_t *drive);
@@ -1156,7 +1076,7 @@ static void ide_device_shutdown(struct device *dev)
}
printk("Shutdown: %s\n", drive->name);
- dev->bus->suspend(dev, PM_SUSPEND_STANDBY);
+ dev->bus->suspend(dev, PMSG_SUSPEND);
}
/*
@@ -1174,19 +1094,25 @@ static ide_driver_t idedisk_driver = {
.supports_dsc_overlap = 0,
.cleanup = idedisk_cleanup,
.do_request = ide_do_rw_disk,
- .pre_reset = idedisk_pre_reset,
- .capacity = idedisk_capacity,
- .special = idedisk_special,
+ .end_request = ide_end_request,
+ .error = __ide_error,
+ .abort = __ide_abort,
.proc = idedisk_proc,
.attach = idedisk_attach,
.drives = LIST_HEAD_INIT(idedisk_driver.drives),
- .start_power_step = idedisk_start_power_step,
- .complete_power_step = idedisk_complete_power_step,
};
static int idedisk_open(struct inode *inode, struct file *filp)
{
- ide_drive_t *drive = inode->i_bdev->bd_disk->private_data;
+ struct gendisk *disk = inode->i_bdev->bd_disk;
+ struct ide_disk_obj *idkp;
+ ide_drive_t *drive;
+
+ if (!(idkp = ide_disk_get(disk)))
+ return -ENXIO;
+
+ drive = idkp->drive;
+
drive->usage++;
if (drive->removable && drive->usage == 1) {
ide_task_t args;
@@ -1208,7 +1134,10 @@ static int idedisk_open(struct inode *inode, struct file *filp)
static int idedisk_release(struct inode *inode, struct file *filp)
{
- ide_drive_t *drive = inode->i_bdev->bd_disk->private_data;
+ struct gendisk *disk = inode->i_bdev->bd_disk;
+ struct ide_disk_obj *idkp = ide_disk_g(disk);
+ ide_drive_t *drive = idkp->drive;
+
if (drive->usage == 1)
ide_cacheflush_p(drive);
if (drive->removable && drive->usage == 1) {
@@ -1221,6 +1150,9 @@ static int idedisk_release(struct inode *inode, struct file *filp)
drive->doorlocking = 0;
}
drive->usage--;
+
+ ide_disk_put(idkp);
+
return 0;
}
@@ -1228,12 +1160,14 @@ static int idedisk_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
struct block_device *bdev = inode->i_bdev;
- return generic_ide_ioctl(file, bdev, cmd, arg);
+ struct ide_disk_obj *idkp = ide_disk_g(bdev->bd_disk);
+ return generic_ide_ioctl(idkp->drive, file, bdev, cmd, arg);
}
static int idedisk_media_changed(struct gendisk *disk)
{
- ide_drive_t *drive = disk->private_data;
+ struct ide_disk_obj *idkp = ide_disk_g(disk);
+ ide_drive_t *drive = idkp->drive;
/* do not scan partitions twice if this is a removable device */
if (drive->attach) {
@@ -1246,8 +1180,8 @@ static int idedisk_media_changed(struct gendisk *disk)
static int idedisk_revalidate_disk(struct gendisk *disk)
{
- ide_drive_t *drive = disk->private_data;
- set_capacity(disk, idedisk_capacity(drive));
+ struct ide_disk_obj *idkp = ide_disk_g(disk);
+ set_capacity(disk, idedisk_capacity(idkp->drive));
return 0;
}
@@ -1264,6 +1198,7 @@ MODULE_DESCRIPTION("ATA DISK Driver");
static int idedisk_attach(ide_drive_t *drive)
{
+ struct ide_disk_obj *idkp;
struct gendisk *g = drive->disk;
/* strstr("foo", "") is non-NULL */
@@ -1274,10 +1209,22 @@ static int idedisk_attach(ide_drive_t *drive)
if (drive->media != ide_disk)
goto failed;
+ idkp = kmalloc(sizeof(*idkp), GFP_KERNEL);
+ if (!idkp)
+ goto failed;
+
if (ide_register_subdriver(drive, &idedisk_driver)) {
printk (KERN_ERR "ide-disk: %s: Failed to register the driver with ide.c\n", drive->name);
- goto failed;
+ goto out_free_idkp;
}
+
+ memset(idkp, 0, sizeof(*idkp));
+
+ kref_init(&idkp->kref);
+
+ idkp->drive = drive;
+ drive->driver_data = idkp;
+
DRIVER(drive)->busy++;
idedisk_setup(drive);
if ((!drive->head || drive->head > 16) && !drive->select.b.lba) {
@@ -1293,8 +1240,11 @@ static int idedisk_attach(ide_drive_t *drive)
g->flags = drive->removable ? GENHD_FL_REMOVABLE : 0;
set_capacity(g, idedisk_capacity(drive));
g->fops = &idedisk_ops;
+ g->private_data = idkp;
add_disk(g);
return 0;
+out_free_idkp:
+ kfree(idkp);
failed:
return 1;
}
diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c
index 416a8a488c803..0e9421b57cc5a 100644
--- a/drivers/ide/ide-floppy.c
+++ b/drivers/ide/ide-floppy.c
@@ -274,8 +274,9 @@ typedef struct {
* driver due to an interrupt or a timer event is stored in a variable
* of type idefloppy_floppy_t, defined below.
*/
-typedef struct {
- ide_drive_t *drive;
+typedef struct ide_floppy_obj {
+ ide_drive_t *drive;
+ struct kref kref;
/* Current packet command */
idefloppy_pc_t *pc;
@@ -514,6 +515,33 @@ typedef struct {
u8 reserved[4];
} idefloppy_mode_parameter_header_t;
+static DECLARE_MUTEX(idefloppy_ref_sem);
+
+#define to_ide_floppy(obj) container_of(obj, struct ide_floppy_obj, kref)
+
+#define ide_floppy_g(disk) ((disk)->private_data)
+
+static struct ide_floppy_obj *ide_floppy_get(struct gendisk *disk)
+{
+ struct ide_floppy_obj *floppy = NULL;
+
+ down(&idefloppy_ref_sem);
+ floppy = ide_floppy_g(disk);
+ if (floppy)
+ kref_get(&floppy->kref);
+ up(&idefloppy_ref_sem);
+ return floppy;
+}
+
+static void ide_floppy_release(struct kref *);
+
+static void ide_floppy_put(struct ide_floppy_obj *floppy)
+{
+ down(&idefloppy_ref_sem);
+ kref_put(&floppy->kref, ide_floppy_release);
+ up(&idefloppy_ref_sem);
+}
+
/*
* Too bad. The drive wants to send us data which we are not ready to accept.
* Just throw it away.
@@ -1792,10 +1820,6 @@ static void idefloppy_setup (ide_drive_t *drive, idefloppy_floppy_t *floppy)
struct idefloppy_id_gcw gcw;
*((u16 *) &gcw) = drive->id->config;
- drive->driver_data = floppy;
- drive->ready_stat = 0;
- memset(floppy, 0, sizeof(idefloppy_floppy_t));
- floppy->drive = drive;
floppy->pc = floppy->pc_stack;
if (gcw.drq_type == 1)
set_bit(IDEFLOPPY_DRQ_INTERRUPT, &floppy->flags);
@@ -1839,16 +1863,40 @@ static int idefloppy_cleanup (ide_drive_t *drive)
if (ide_unregister_subdriver(drive))
return 1;
- drive->driver_data = NULL;
- kfree(floppy);
+
del_gendisk(g);
- g->fops = ide_fops;
+
+ ide_floppy_put(floppy);
+
return 0;
}
+static void ide_floppy_release(struct kref *kref)
+{
+ struct ide_floppy_obj *floppy = to_ide_floppy(kref);
+ ide_drive_t *drive = floppy->drive;
+ struct gendisk *g = drive->disk;
+
+ drive->driver_data = NULL;
+ g->private_data = NULL;
+ g->fops = ide_fops;
+ kfree(floppy);
+}
+
#ifdef CONFIG_PROC_FS
+static int proc_idefloppy_read_capacity
+ (char *page, char **start, off_t off, int count, int *eof, void *data)
+{
+ ide_drive_t*drive = (ide_drive_t *)data;
+ int len;
+
+ len = sprintf(page,"%llu\n", (long long)idefloppy_capacity(drive));
+ PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
+}
+
static ide_proc_entry_t idefloppy_proc[] = {
+ { "capacity", S_IFREG|S_IRUGO, proc_idefloppy_read_capacity, NULL },
{ "geometry", S_IFREG|S_IRUGO, proc_ide_read_geometry, NULL },
{ NULL, 0, NULL, NULL }
};
@@ -1874,7 +1922,8 @@ static ide_driver_t idefloppy_driver = {
.cleanup = idefloppy_cleanup,
.do_request = idefloppy_do_request,
.end_request = idefloppy_do_end_request,
- .capacity = idefloppy_capacity,
+ .error = __ide_error,
+ .abort = __ide_abort,
.proc = idefloppy_proc,
.attach = idefloppy_attach,
.drives = LIST_HEAD_INIT(idefloppy_driver.drives),
@@ -1882,14 +1931,21 @@ static ide_driver_t idefloppy_driver = {
static int idefloppy_open(struct inode *inode, struct file *filp)
{
- ide_drive_t *drive = inode->i_bdev->bd_disk->private_data;
- idefloppy_floppy_t *floppy = drive->driver_data;
+ struct gendisk *disk = inode->i_bdev->bd_disk;
+ struct ide_floppy_obj *floppy;
+ ide_drive_t *drive;
idefloppy_pc_t pc;
+ int ret = 0;
- drive->usage++;
-
debug_log(KERN_INFO "Reached idefloppy_open\n");
+ if (!(floppy = ide_floppy_get(disk)))
+ return -ENXIO;
+
+ drive = floppy->drive;
+
+ drive->usage++;
+
if (drive->usage == 1) {
clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags);
/* Just in case */
@@ -1909,13 +1965,15 @@ static int idefloppy_open(struct inode *inode, struct file *filp)
*/
) {
drive->usage--;
- return -EIO;
+ ret = -EIO;
+ goto out_put_floppy;
}
if (floppy->wp && (filp->f_mode & 2)) {
drive->usage--;
- return -EROFS;
- }
+ ret = -EROFS;
+ goto out_put_floppy;
+ }
set_bit(IDEFLOPPY_MEDIA_CHANGED, &floppy->flags);
/* IOMEGA Clik! drives do not support lock/unlock commands */
if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) {
@@ -1925,21 +1983,26 @@ static int idefloppy_open(struct inode *inode, struct file *filp)
check_disk_change(inode->i_bdev);
} else if (test_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags)) {
drive->usage--;
- return -EBUSY;
+ ret = -EBUSY;
+ goto out_put_floppy;
}
return 0;
+
+out_put_floppy:
+ ide_floppy_put(floppy);
+ return ret;
}
static int idefloppy_release(struct inode *inode, struct file *filp)
{
- ide_drive_t *drive = inode->i_bdev->bd_disk->private_data;
+ struct gendisk *disk = inode->i_bdev->bd_disk;
+ struct ide_floppy_obj *floppy = ide_floppy_g(disk);
+ ide_drive_t *drive = floppy->drive;
idefloppy_pc_t pc;
debug_log(KERN_INFO "Reached idefloppy_release\n");
if (drive->usage == 1) {
- idefloppy_floppy_t *floppy = drive->driver_data;
-
/* IOMEGA Clik! drives do not support lock/unlock commands */
if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) {
idefloppy_create_prevent_cmd(&pc, 0);
@@ -1949,6 +2012,9 @@ static int idefloppy_release(struct inode *inode, struct file *filp)
clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags);
}
drive->usage--;
+
+ ide_floppy_put(floppy);
+
return 0;
}
@@ -1956,10 +2022,10 @@ static int idefloppy_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
struct block_device *bdev = inode->i_bdev;
- ide_drive_t *drive = bdev->bd_disk->private_data;
- idefloppy_floppy_t *floppy = drive->driver_data;
+ struct ide_floppy_obj *floppy = ide_floppy_g(bdev->bd_disk);
+ ide_drive_t *drive = floppy->drive;
void __user *argp = (void __user *)arg;
- int err = generic_ide_ioctl(file, bdev, cmd, arg);
+ int err = generic_ide_ioctl(drive, file, bdev, cmd, arg);
int prevent = (arg) ? 1 : 0;
idefloppy_pc_t pc;
if (err != -EINVAL)
@@ -2020,8 +2086,8 @@ static int idefloppy_ioctl(struct inode *inode, struct file *file,
static int idefloppy_media_changed(struct gendisk *disk)
{
- ide_drive_t *drive = disk->private_data;
- idefloppy_floppy_t *floppy = drive->driver_data;
+ struct ide_floppy_obj *floppy = ide_floppy_g(disk);
+ ide_drive_t *drive = floppy->drive;
/* do not scan partitions twice if this is a removable device */
if (drive->attach) {
@@ -2033,8 +2099,8 @@ static int idefloppy_media_changed(struct gendisk *disk)
static int idefloppy_revalidate_disk(struct gendisk *disk)
{
- ide_drive_t *drive = disk->private_data;
- set_capacity(disk, idefloppy_capacity(drive));
+ struct ide_floppy_obj *floppy = ide_floppy_g(disk);
+ set_capacity(disk, idefloppy_capacity(floppy->drive));
return 0;
}
@@ -2074,6 +2140,15 @@ static int idefloppy_attach (ide_drive_t *drive)
kfree (floppy);
goto failed;
}
+
+ memset(floppy, 0, sizeof(*floppy));
+
+ kref_init(&floppy->kref);
+
+ floppy->drive = drive;
+
+ drive->driver_data = floppy;
+
DRIVER(drive)->busy++;
idefloppy_setup (drive, floppy);
DRIVER(drive)->busy--;
@@ -2082,6 +2157,7 @@ static int idefloppy_attach (ide_drive_t *drive)
strcpy(g->devfs_name, drive->devfs_name);
g->flags = drive->removable ? GENHD_FL_REMOVABLE : 0;
g->fops = &idefloppy_ops;
+ g->private_data = floppy;
drive->attach = 1;
add_disk(g);
return 0;
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
index 3cf32f23bea2d..65f5267992dc9 100644
--- a/drivers/ide/ide-io.c
+++ b/drivers/ide/ide-io.c
@@ -55,62 +55,8 @@
#include <asm/io.h>
#include <asm/bitops.h>
-static void ide_fill_flush_cmd(ide_drive_t *drive, struct request *rq)
-{
- char *buf = rq->cmd;
-
- /*
- * reuse cdb space for ata command
- */
- memset(buf, 0, sizeof(rq->cmd));
-
- rq->flags |= REQ_DRIVE_TASK | REQ_STARTED;
- rq->buffer = buf;
- rq->buffer[0] = WIN_FLUSH_CACHE;
-
- if (ide_id_has_flush_cache_ext(drive->id) &&
- (drive->capacity64 >= (1UL << 28)))
- rq->buffer[0] = WIN_FLUSH_CACHE_EXT;
-}
-
-/*
- * preempt pending requests, and store this cache flush for immediate
- * execution
- */
-static struct request *ide_queue_flush_cmd(ide_drive_t *drive,
- struct request *rq, int post)
-{
- struct request *flush_rq = &HWGROUP(drive)->wrq;
-
- /*
- * write cache disabled, clear the barrier bit and treat it like
- * an ordinary write
- */
- if (!drive->wcache) {
- rq->flags |= REQ_BAR_PREFLUSH;
- return rq;
- }
-
- ide_init_drive_cmd(flush_rq);
- ide_fill_flush_cmd(drive, flush_rq);
-
- flush_rq->special = rq;
- flush_rq->nr_sectors = rq->nr_sectors;
-
- if (!post) {
- drive->doing_barrier = 1;
- flush_rq->flags |= REQ_BAR_PREFLUSH;
- blkdev_dequeue_request(rq);
- } else
- flush_rq->flags |= REQ_BAR_POSTFLUSH;
-
- __elv_add_request(drive->queue, flush_rq, ELEVATOR_INSERT_FRONT, 0);
- HWGROUP(drive)->rq = NULL;
- return flush_rq;
-}
-
-static int __ide_end_request(ide_drive_t *drive, struct request *rq,
- int uptodate, int nr_sectors)
+int __ide_end_request(ide_drive_t *drive, struct request *rq, int uptodate,
+ int nr_sectors)
{
int ret = 1;
@@ -148,6 +94,7 @@ static int __ide_end_request(ide_drive_t *drive, struct request *rq,
}
return ret;
}
+EXPORT_SYMBOL(__ide_end_request);
/**
* ide_end_request - complete an IDE I/O
@@ -172,23 +119,109 @@ int ide_end_request (ide_drive_t *drive, int uptodate, int nr_sectors)
if (!nr_sectors)
nr_sectors = rq->hard_cur_sectors;
- if (!blk_barrier_rq(rq) || !drive->wcache)
+ 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);
- else {
- struct request *flush_rq = &HWGROUP(drive)->wrq;
-
- flush_rq->nr_sectors -= nr_sectors;
- if (!flush_rq->nr_sectors) {
- ide_queue_flush_cmd(drive, rq, 1);
- ret = 0;
- }
- }
spin_unlock_irqrestore(&ide_lock, flags);
return ret;
}
EXPORT_SYMBOL(ide_end_request);
+/*
+ * Power Management state machine. This one is rather trivial for now,
+ * we should probably add more, like switching back to PIO on suspend
+ * to help some BIOSes, re-do the door locking on resume, etc...
+ */
+
+enum {
+ ide_pm_flush_cache = ide_pm_state_start_suspend,
+ idedisk_pm_standby,
+
+ idedisk_pm_idle = ide_pm_state_start_resume,
+ ide_pm_restore_dma,
+};
+
+static void ide_complete_power_step(ide_drive_t *drive, struct request *rq, u8 stat, u8 error)
+{
+ if (drive->media != ide_disk)
+ return;
+
+ switch (rq->pm->pm_step) {
+ case ide_pm_flush_cache: /* Suspend step 1 (flush cache) complete */
+ if (rq->pm->pm_state == 4)
+ rq->pm->pm_step = ide_pm_state_completed;
+ else
+ rq->pm->pm_step = idedisk_pm_standby;
+ break;
+ case idedisk_pm_standby: /* Suspend step 2 (standby) complete */
+ rq->pm->pm_step = ide_pm_state_completed;
+ break;
+ case idedisk_pm_idle: /* Resume step 1 (idle) complete */
+ rq->pm->pm_step = ide_pm_restore_dma;
+ break;
+ }
+}
+
+static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *rq)
+{
+ ide_task_t *args = rq->special;
+
+ memset(args, 0, sizeof(*args));
+
+ if (drive->media != ide_disk) {
+ /* skip idedisk_pm_idle for ATAPI devices */
+ if (rq->pm->pm_step == idedisk_pm_idle)
+ rq->pm->pm_step = ide_pm_restore_dma;
+ }
+
+ switch (rq->pm->pm_step) {
+ case ide_pm_flush_cache: /* Suspend step 1 (flush cache) */
+ if (drive->media != ide_disk)
+ break;
+ /* Not supported? Switch to next step now. */
+ if (!drive->wcache || !ide_id_has_flush_cache(drive->id)) {
+ ide_complete_power_step(drive, rq, 0, 0);
+ return ide_stopped;
+ }
+ if (ide_id_has_flush_cache_ext(drive->id))
+ args->tfRegister[IDE_COMMAND_OFFSET] = WIN_FLUSH_CACHE_EXT;
+ else
+ args->tfRegister[IDE_COMMAND_OFFSET] = WIN_FLUSH_CACHE;
+ args->command_type = IDE_DRIVE_TASK_NO_DATA;
+ args->handler = &task_no_data_intr;
+ return do_rw_taskfile(drive, args);
+
+ case idedisk_pm_standby: /* Suspend step 2 (standby) */
+ args->tfRegister[IDE_COMMAND_OFFSET] = WIN_STANDBYNOW1;
+ args->command_type = IDE_DRIVE_TASK_NO_DATA;
+ args->handler = &task_no_data_intr;
+ return do_rw_taskfile(drive, args);
+
+ case idedisk_pm_idle: /* Resume step 1 (idle) */
+ args->tfRegister[IDE_COMMAND_OFFSET] = WIN_IDLEIMMEDIATE;
+ args->command_type = IDE_DRIVE_TASK_NO_DATA;
+ args->handler = task_no_data_intr;
+ return do_rw_taskfile(drive, args);
+
+ case ide_pm_restore_dma: /* Resume step 2 (restore DMA) */
+ /*
+ * Right now, all we do is call hwif->ide_dma_check(drive),
+ * we could be smarter and check for current xfer_speed
+ * in struct drive etc...
+ */
+ if ((drive->id->capability & 1) == 0)
+ break;
+ if (drive->hwif->ide_dma_check == NULL)
+ break;
+ drive->hwif->ide_dma_check(drive);
+ break;
+ }
+ rq->pm->pm_step = ide_pm_state_completed;
+ return ide_stopped;
+}
+
/**
* ide_complete_pm_request - end the current Power Management request
* @drive: target drive
@@ -253,79 +286,6 @@ u64 ide_get_error_location(ide_drive_t *drive, char *args)
}
EXPORT_SYMBOL(ide_get_error_location);
-static void ide_complete_barrier(ide_drive_t *drive, struct request *rq,
- int error)
-{
- struct request *real_rq = rq->special;
- int good_sectors, bad_sectors;
- sector_t sector;
-
- if (!error) {
- if (blk_barrier_postflush(rq)) {
- /*
- * this completes the barrier write
- */
- __ide_end_request(drive, real_rq, 1, real_rq->hard_nr_sectors);
- drive->doing_barrier = 0;
- } else {
- /*
- * just indicate that we did the pre flush
- */
- real_rq->flags |= REQ_BAR_PREFLUSH;
- elv_requeue_request(drive->queue, real_rq);
- }
- /*
- * all is fine, return
- */
- return;
- }
-
- /*
- * we need to end real_rq, but it's not on the queue currently.
- * put it back on the queue, so we don't have to special case
- * anything else for completing it
- */
- if (!blk_barrier_postflush(rq))
- elv_requeue_request(drive->queue, real_rq);
-
- /*
- * drive aborted flush command, assume FLUSH_CACHE_* doesn't
- * work and disable barrier support
- */
- if (error & ABRT_ERR) {
- printk(KERN_ERR "%s: barrier support doesn't work\n", drive->name);
- __ide_end_request(drive, real_rq, -EOPNOTSUPP, real_rq->hard_nr_sectors);
- blk_queue_ordered(drive->queue, 0);
- blk_queue_issue_flush_fn(drive->queue, NULL);
- } else {
- /*
- * find out what part of the request failed
- */
- good_sectors = 0;
- if (blk_barrier_postflush(rq)) {
- sector = ide_get_error_location(drive, rq->buffer);
-
- if ((sector >= real_rq->hard_sector) &&
- (sector < real_rq->hard_sector + real_rq->hard_nr_sectors))
- good_sectors = sector - real_rq->hard_sector;
- } else
- sector = real_rq->hard_sector;
-
- bad_sectors = real_rq->hard_nr_sectors - good_sectors;
- if (good_sectors)
- __ide_end_request(drive, real_rq, 1, good_sectors);
- if (bad_sectors)
- __ide_end_request(drive, real_rq, 0, bad_sectors);
-
- printk(KERN_ERR "%s: failed barrier write: "
- "sector=%Lx(good=%d/bad=%d)\n",
- drive->name, (unsigned long long)sector,
- good_sectors, bad_sectors);
- }
-
- drive->doing_barrier = 0;
-}
-
/**
* ide_end_drive_cmd - end an explicit drive command
* @drive: command
@@ -409,7 +369,7 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err)
printk("%s: complete_power_step(step: %d, stat: %x, err: %x)\n",
drive->name, rq->pm->pm_step, stat, err);
#endif
- DRIVER(drive)->complete_power_step(drive, rq, stat, err);
+ ide_complete_power_step(drive, rq, stat, err);
if (rq->pm->pm_step == ide_pm_state_completed)
ide_complete_pm_request(drive, rq);
return;
@@ -417,11 +377,8 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err)
spin_lock_irqsave(&ide_lock, flags);
blkdev_dequeue_request(rq);
-
- if (blk_barrier_preflush(rq) || blk_barrier_postflush(rq))
- ide_complete_barrier(drive, rq, err);
-
HWGROUP(drive)->rq = NULL;
+ rq->errors = err;
end_that_request_last(rq);
spin_unlock_irqrestore(&ide_lock, flags);
}
@@ -536,6 +493,8 @@ __ide_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err)
return ide_atapi_error(drive, rq, stat, err);
}
+EXPORT_SYMBOL_GPL(__ide_error);
+
/**
* ide_error - handle an error on the IDE
* @drive: drive the error occurred on
@@ -580,6 +539,8 @@ ide_startstop_t __ide_abort(ide_drive_t *drive, struct request *rq)
return ide_stopped;
}
+EXPORT_SYMBOL_GPL(__ide_abort);
+
/**
* ide_abort - abort pending IDE operatins
* @drive: drive the error occurred on
@@ -668,6 +629,65 @@ static ide_startstop_t drive_cmd_intr (ide_drive_t *drive)
return ide_stopped;
}
+static void ide_init_specify_cmd(ide_drive_t *drive, ide_task_t *task)
+{
+ task->tfRegister[IDE_NSECTOR_OFFSET] = drive->sect;
+ task->tfRegister[IDE_SECTOR_OFFSET] = drive->sect;
+ task->tfRegister[IDE_LCYL_OFFSET] = drive->cyl;
+ task->tfRegister[IDE_HCYL_OFFSET] = drive->cyl>>8;
+ task->tfRegister[IDE_SELECT_OFFSET] = ((drive->head-1)|drive->select.all)&0xBF;
+ task->tfRegister[IDE_COMMAND_OFFSET] = WIN_SPECIFY;
+
+ task->handler = &set_geometry_intr;
+}
+
+static void ide_init_restore_cmd(ide_drive_t *drive, ide_task_t *task)
+{
+ task->tfRegister[IDE_NSECTOR_OFFSET] = drive->sect;
+ task->tfRegister[IDE_COMMAND_OFFSET] = WIN_RESTORE;
+
+ task->handler = &recal_intr;
+}
+
+static void ide_init_setmult_cmd(ide_drive_t *drive, ide_task_t *task)
+{
+ task->tfRegister[IDE_NSECTOR_OFFSET] = drive->mult_req;
+ task->tfRegister[IDE_COMMAND_OFFSET] = WIN_SETMULT;
+
+ task->handler = &set_multmode_intr;
+}
+
+static ide_startstop_t ide_disk_special(ide_drive_t *drive)
+{
+ special_t *s = &drive->special;
+ ide_task_t args;
+
+ memset(&args, 0, sizeof(ide_task_t));
+ args.command_type = IDE_DRIVE_TASK_NO_DATA;
+
+ if (s->b.set_geometry) {
+ s->b.set_geometry = 0;
+ ide_init_specify_cmd(drive, &args);
+ } else if (s->b.recalibrate) {
+ s->b.recalibrate = 0;
+ ide_init_restore_cmd(drive, &args);
+ } else if (s->b.set_multmode) {
+ s->b.set_multmode = 0;
+ if (drive->mult_req > drive->id->max_multsect)
+ drive->mult_req = drive->id->max_multsect;
+ ide_init_setmult_cmd(drive, &args);
+ } else if (s->all) {
+ int special = s->all;
+ s->all = 0;
+ printk(KERN_ERR "%s: bad special flag: 0x%02x\n", drive->name, special);
+ return ide_stopped;
+ }
+
+ do_rw_taskfile(drive, &args);
+
+ return ide_started;
+}
+
/**
* do_special - issue some special commands
* @drive: drive the command is for
@@ -689,9 +709,14 @@ static ide_startstop_t do_special (ide_drive_t *drive)
if (HWIF(drive)->tuneproc != NULL)
HWIF(drive)->tuneproc(drive, drive->tune_req);
return ide_stopped;
+ } else {
+ if (drive->media == ide_disk)
+ return ide_disk_special(drive);
+
+ s->all = 0;
+ drive->mult_req = 0;
+ return ide_stopped;
}
- else
- return DRIVER(drive)->special(drive);
}
void ide_map_sg(ide_drive_t *drive, struct request *rq)
@@ -906,7 +931,7 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
printk("%s: start_power_step(step: %d)\n",
drive->name, rq->pm->pm_step);
#endif
- startstop = DRIVER(drive)->start_power_step(drive, rq);
+ startstop = ide_start_power_step(drive, rq);
if (startstop == ide_stopped &&
rq->pm->pm_step == ide_pm_state_completed)
ide_complete_pm_request(drive, rq);
@@ -963,7 +988,7 @@ repeat:
* though that is 3 requests, it must be seen as a single transaction.
* we must not preempt this drive until that is complete
*/
- if (drive->doing_barrier) {
+ if (blk_queue_flushing(drive->queue)) {
/*
* small race where queue could get replugged during
* the 3-request flush cycle, just yank the plug since
@@ -1128,13 +1153,6 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
}
/*
- * if rq is a barrier write, issue pre cache flush if not
- * already done
- */
- if (blk_barrier_rq(rq) && !blk_barrier_preflush(rq))
- rq = ide_queue_flush_cmd(drive, rq, 0);
-
- /*
* Sanity: don't accept a request that isn't a PM request
* if we are currently power managed. This is very important as
* blk_stop_queue() doesn't prevent the elv_next_request()
@@ -1163,14 +1181,14 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
* happens anyway when any interrupt comes in, IDE or otherwise
* -- the kernel masks the IRQ while it is being handled.
*/
- if (hwif->irq != masked_irq)
+ if (masked_irq != IDE_NO_IRQ && hwif->irq != masked_irq)
disable_irq_nosync(hwif->irq);
spin_unlock(&ide_lock);
local_irq_enable();
/* allow other IRQs while we start this request */
startstop = start_request(drive, rq);
spin_lock_irq(&ide_lock);
- if (hwif->irq != masked_irq)
+ if (masked_irq != IDE_NO_IRQ && hwif->irq != masked_irq)
enable_irq(hwif->irq);
if (startstop == ide_stopped)
hwgroup->busy = 0;
@@ -1607,6 +1625,7 @@ int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t actio
if (must_wait) {
rq->ref_count++;
rq->waiting = &wait;
+ rq->end_io = blk_end_sync_rq;
}
spin_lock_irqsave(&ide_lock, flags);
diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c
index 31448ab8dbad8..53024942a7ebf 100644
--- a/drivers/ide/ide-iops.c
+++ b/drivers/ide/ide-iops.c
@@ -1107,9 +1107,27 @@ static void check_dma_crc(ide_drive_t *drive)
#endif
}
+static void ide_disk_pre_reset(ide_drive_t *drive)
+{
+ int legacy = (drive->id->cfs_enable_2 & 0x0400) ? 0 : 1;
+
+ drive->special.all = 0;
+ drive->special.b.set_geometry = legacy;
+ drive->special.b.recalibrate = legacy;
+ if (OK_TO_RESET_CONTROLLER)
+ drive->mult_count = 0;
+ if (!drive->keep_settings && !drive->using_dma)
+ drive->mult_req = 0;
+ if (drive->mult_req != drive->mult_count)
+ drive->special.b.set_multmode = 1;
+}
+
static void pre_reset(ide_drive_t *drive)
{
- DRIVER(drive)->pre_reset(drive);
+ if (drive->media == ide_disk)
+ ide_disk_pre_reset(drive);
+ else
+ drive->post_reset = 1;
if (!drive->keep_settings) {
if (drive->using_dma) {
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index 417783f90fae0..cb158558d2012 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -74,7 +74,55 @@ static void generic_id(ide_drive_t *drive)
drive->id->cur_heads = drive->head;
drive->id->cur_sectors = drive->sect;
}
-
+
+static void ide_disk_init_chs(ide_drive_t *drive)
+{
+ struct hd_driveid *id = drive->id;
+
+ /* Extract geometry if we did not already have one for the drive */
+ if (!drive->cyl || !drive->head || !drive->sect) {
+ drive->cyl = drive->bios_cyl = id->cyls;
+ drive->head = drive->bios_head = id->heads;
+ drive->sect = drive->bios_sect = id->sectors;
+ }
+
+ /* Handle logical geometry translation by the drive */
+ if ((id->field_valid & 1) && id->cur_cyls &&
+ id->cur_heads && (id->cur_heads <= 16) && id->cur_sectors) {
+ drive->cyl = id->cur_cyls;
+ drive->head = id->cur_heads;
+ drive->sect = id->cur_sectors;
+ }
+
+ /* Use physical geometry if what we have still makes no sense */
+ if (drive->head > 16 && id->heads && id->heads <= 16) {
+ drive->cyl = id->cyls;
+ drive->head = id->heads;
+ drive->sect = id->sectors;
+ }
+}
+
+static void ide_disk_init_mult_count(ide_drive_t *drive)
+{
+ struct hd_driveid *id = drive->id;
+
+ drive->mult_count = 0;
+ if (id->max_multsect) {
+#ifdef CONFIG_IDEDISK_MULTI_MODE
+ id->multsect = ((id->max_multsect/2) > 1) ? id->max_multsect : 0;
+ id->multsect_valid = id->multsect ? 1 : 0;
+ drive->mult_req = id->multsect_valid ? id->max_multsect : INITIAL_MULT_COUNT;
+ drive->special.b.set_multmode = drive->mult_req ? 1 : 0;
+#else /* original, pre IDE-NFG, per request of AC */
+ drive->mult_req = INITIAL_MULT_COUNT;
+ if (drive->mult_req > id->max_multsect)
+ drive->mult_req = id->max_multsect;
+ if (drive->mult_req || ((id->multsect_valid & 1) && id->multsect))
+ drive->special.b.set_multmode = 1;
+#endif
+ }
+}
+
/**
* drive_is_flashcard - check for compact flash
* @drive: drive to check
@@ -221,6 +269,8 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd)
}
printk (" drive\n");
drive->media = type;
+ /* an ATAPI device ignores DRDY */
+ drive->ready_stat = 0;
return;
}
@@ -588,8 +638,16 @@ static inline u8 probe_for_drive (ide_drive_t *drive)
if(!drive->present)
return 0;
/* The drive wasn't being helpful. Add generic info only */
- if(!drive->id_read)
+ if (drive->id_read == 0) {
generic_id(drive);
+ return 1;
+ }
+
+ if (drive->media == ide_disk) {
+ ide_disk_init_chs(drive);
+ ide_disk_init_mult_count(drive);
+ }
+
return drive->present;
}
diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c
index 0344ce8f6ef46..30e9611fc728d 100644
--- a/drivers/ide/ide-proc.c
+++ b/drivers/ide/ide-proc.c
@@ -269,14 +269,12 @@ parse_error:
int proc_ide_read_capacity
(char *page, char **start, off_t off, int count, int *eof, void *data)
{
- ide_drive_t *drive = (ide_drive_t *) data;
- int len;
-
- len = sprintf(page,"%llu\n",
- (long long) (DRIVER(drive)->capacity(drive)));
+ int len = sprintf(page,"%llu\n", (long long)0x7fffffff);
PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
}
+EXPORT_SYMBOL_GPL(proc_ide_read_capacity);
+
int proc_ide_read_geometry
(char *page, char **start, off_t off, int count, int *eof, void *data)
{
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
index 147b80ac66e7c..913d762c5220d 100644
--- a/drivers/ide/ide-tape.c
+++ b/drivers/ide/ide-tape.c
@@ -781,8 +781,10 @@ typedef struct {
* driver due to an interrupt or a timer event is stored in a variable
* of type idetape_tape_t, defined below.
*/
-typedef struct {
- ide_drive_t *drive;
+typedef struct ide_tape_obj {
+ ide_drive_t *drive;
+ struct kref kref;
+
/*
* Since a typical character device operation requires more
* than one packet command, we provide here enough memory
@@ -1007,6 +1009,33 @@ typedef struct {
int debug_level;
} idetape_tape_t;
+static DECLARE_MUTEX(idetape_ref_sem);
+
+#define to_ide_tape(obj) container_of(obj, struct ide_tape_obj, kref)
+
+#define ide_tape_g(disk) ((disk)->private_data)
+
+static struct ide_tape_obj *ide_tape_get(struct gendisk *disk)
+{
+ struct ide_tape_obj *tape = NULL;
+
+ down(&idetape_ref_sem);
+ tape = ide_tape_g(disk);
+ if (tape)
+ kref_get(&tape->kref);
+ up(&idetape_ref_sem);
+ return tape;
+}
+
+static void ide_tape_release(struct kref *);
+
+static void ide_tape_put(struct ide_tape_obj *tape)
+{
+ down(&idetape_ref_sem);
+ kref_put(&tape->kref, ide_tape_release);
+ up(&idetape_ref_sem);
+}
+
/*
* Tape door status
*/
@@ -1093,15 +1122,6 @@ enum {
#define IDETAPE_ERROR_EOD 103
/*
- * idetape_chrdev_t provides the link between out character device
- * interface and our block device interface and the corresponding
- * ide_drive_t structure.
- */
-typedef struct {
- ide_drive_t *drive;
-} idetape_chrdev_t;
-
-/*
* The following is used to format the general configuration word of
* the ATAPI IDENTIFY DEVICE command.
*/
@@ -1257,7 +1277,21 @@ typedef struct {
* The variables below are used for the character device interface.
* Additional state variables are defined in our ide_drive_t structure.
*/
-static idetape_chrdev_t idetape_chrdevs[MAX_HWIFS * MAX_DRIVES];
+static struct ide_tape_obj * idetape_devs[MAX_HWIFS * MAX_DRIVES];
+
+#define ide_tape_f(file) ((file)->private_data)
+
+static struct ide_tape_obj *ide_tape_chrdev_get(unsigned int i)
+{
+ struct ide_tape_obj *tape = NULL;
+
+ down(&idetape_ref_sem);
+ tape = idetape_devs[i];
+ if (tape)
+ kref_get(&tape->kref);
+ up(&idetape_ref_sem);
+ return tape;
+}
/*
* Function declarations
@@ -2428,6 +2462,11 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
if (!drive->dsc_overlap && !(rq->cmd[0] & REQ_IDETAPE_PC2))
set_bit(IDETAPE_IGNORE_DSC, &tape->flags);
+ if (drive->post_reset == 1) {
+ set_bit(IDETAPE_IGNORE_DSC, &tape->flags);
+ drive->post_reset = 0;
+ }
+
if (tape->tape_still_time > 100 && tape->tape_still_time < 200)
tape->measure_insert_time = 1;
if (time_after(jiffies, tape->insert_time))
@@ -2720,6 +2759,7 @@ static void idetape_wait_for_request (ide_drive_t *drive, struct request *rq)
}
#endif /* IDETAPE_DEBUG_BUGS */
rq->waiting = &wait;
+ rq->end_io = blk_end_sync_rq;
spin_unlock_irq(&tape->spinlock);
wait_for_completion(&wait);
/* The stage and its struct request have been deallocated */
@@ -3558,16 +3598,6 @@ static int idetape_blkdev_ioctl(ide_drive_t *drive, unsigned int cmd, unsigned l
}
/*
- * idetape_pre_reset is called before an ATAPI/ATA software reset.
- */
-static void idetape_pre_reset (ide_drive_t *drive)
-{
- idetape_tape_t *tape = drive->driver_data;
- if (tape != NULL)
- set_bit(IDETAPE_IGNORE_DSC, &tape->flags);
-}
-
-/*
* idetape_space_over_filemarks is now a bit more complicated than just
* passing the command to the tape since we may have crossed some
* filemarks during our pipelined read-ahead mode.
@@ -3673,8 +3703,8 @@ static int idetape_space_over_filemarks (ide_drive_t *drive,short mt_op,int mt_c
static ssize_t idetape_chrdev_read (struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
- ide_drive_t *drive = file->private_data;
- idetape_tape_t *tape = drive->driver_data;
+ struct ide_tape_obj *tape = ide_tape_f(file);
+ ide_drive_t *drive = tape->drive;
ssize_t bytes_read,temp, actually_read = 0, rc;
#if IDETAPE_DEBUG_LOG
@@ -3732,8 +3762,8 @@ finish:
static ssize_t idetape_chrdev_write (struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
- ide_drive_t *drive = file->private_data;
- idetape_tape_t *tape = drive->driver_data;
+ struct ide_tape_obj *tape = ide_tape_f(file);
+ ide_drive_t *drive = tape->drive;
ssize_t retval, actually_written = 0;
/* The drive is write protected. */
@@ -4035,8 +4065,8 @@ static int idetape_mtioctop (ide_drive_t *drive,short mt_op,int mt_count)
*/
static int idetape_chrdev_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
- ide_drive_t *drive = file->private_data;
- idetape_tape_t *tape = drive->driver_data;
+ struct ide_tape_obj *tape = ide_tape_f(file);
+ ide_drive_t *drive = tape->drive;
struct mtop mtop;
struct mtget mtget;
struct mtpos mtpos;
@@ -4100,24 +4130,37 @@ static int idetape_chrdev_open (struct inode *inode, struct file *filp)
idetape_pc_t pc;
int retval;
- nonseekable_open(inode, filp);
+ /*
+ * We really want to do nonseekable_open(inode, filp); here, but some
+ * versions of tar incorrectly call lseek on tapes and bail out if that
+ * fails. So we disallow pread() and pwrite(), but permit lseeks.
+ */
+ filp->f_mode &= ~(FMODE_PREAD | FMODE_PWRITE);
+
#if IDETAPE_DEBUG_LOG
printk(KERN_INFO "ide-tape: Reached idetape_chrdev_open\n");
#endif /* IDETAPE_DEBUG_LOG */
if (i >= MAX_HWIFS * MAX_DRIVES)
return -ENXIO;
- drive = idetape_chrdevs[i].drive;
- tape = drive->driver_data;
- filp->private_data = drive;
- if (test_and_set_bit(IDETAPE_BUSY, &tape->flags))
- return -EBUSY;
+ if (!(tape = ide_tape_chrdev_get(i)))
+ return -ENXIO;
+
+ drive = tape->drive;
+
+ filp->private_data = tape;
+
+ if (test_and_set_bit(IDETAPE_BUSY, &tape->flags)) {
+ retval = -EBUSY;
+ goto out_put_tape;
+ }
+
retval = idetape_wait_ready(drive, 60 * HZ);
if (retval) {
clear_bit(IDETAPE_BUSY, &tape->flags);
printk(KERN_ERR "ide-tape: %s: drive not ready\n", tape->name);
- return retval;
+ goto out_put_tape;
}
idetape_read_position(drive);
@@ -4141,7 +4184,8 @@ static int idetape_chrdev_open (struct inode *inode, struct file *filp)
if ((filp->f_flags & O_ACCMODE) == O_WRONLY ||
(filp->f_flags & O_ACCMODE) == O_RDWR) {
clear_bit(IDETAPE_BUSY, &tape->flags);
- return -EROFS;
+ retval = -EROFS;
+ goto out_put_tape;
}
}
@@ -4159,6 +4203,10 @@ static int idetape_chrdev_open (struct inode *inode, struct file *filp)
idetape_restart_speed_control(drive);
tape->restart_speed_control_req = 0;
return 0;
+
+out_put_tape:
+ ide_tape_put(tape);
+ return retval;
}
static void idetape_write_release (ide_drive_t *drive, unsigned int minor)
@@ -4182,8 +4230,8 @@ static void idetape_write_release (ide_drive_t *drive, unsigned int minor)
*/
static int idetape_chrdev_release (struct inode *inode, struct file *filp)
{
- ide_drive_t *drive = filp->private_data;
- idetape_tape_t *tape;
+ struct ide_tape_obj *tape = ide_tape_f(filp);
+ ide_drive_t *drive = tape->drive;
idetape_pc_t pc;
unsigned int minor = iminor(inode);
@@ -4217,6 +4265,7 @@ static int idetape_chrdev_release (struct inode *inode, struct file *filp)
}
}
clear_bit(IDETAPE_BUSY, &tape->flags);
+ ide_tape_put(tape);
unlock_kernel();
return 0;
}
@@ -4527,11 +4576,7 @@ static void idetape_setup (ide_drive_t *drive, idetape_tape_t *tape, int minor)
int stage_size;
struct sysinfo si;
- memset(tape, 0, sizeof (idetape_tape_t));
spin_lock_init(&tape->spinlock);
- drive->driver_data = tape;
- /* An ATAPI device ignores DRDY */
- drive->ready_stat = 0;
drive->dsc_overlap = 1;
#ifdef CONFIG_BLK_DEV_IDEPCI
if (HWIF(drive)->pci_dev != NULL) {
@@ -4549,7 +4594,6 @@ static void idetape_setup (ide_drive_t *drive, idetape_tape_t *tape, int minor)
/* Seagate Travan drives do not support DSC overlap. */
if (strstr(drive->id->model, "Seagate STT3401"))
drive->dsc_overlap = 0;
- tape->drive = drive;
tape->minor = minor;
tape->name[0] = 'h';
tape->name[1] = 't';
@@ -4630,7 +4674,6 @@ static void idetape_setup (ide_drive_t *drive, idetape_tape_t *tape, int minor)
static int idetape_cleanup (ide_drive_t *drive)
{
idetape_tape_t *tape = drive->driver_data;
- int minor = tape->minor;
unsigned long flags;
spin_lock_irqsave(&ide_lock, flags);
@@ -4639,17 +4682,30 @@ static int idetape_cleanup (ide_drive_t *drive)
spin_unlock_irqrestore(&ide_lock, flags);
return 1;
}
- idetape_chrdevs[minor].drive = NULL;
+
spin_unlock_irqrestore(&ide_lock, flags);
DRIVER(drive)->busy = 0;
(void) ide_unregister_subdriver(drive);
+
+ ide_tape_put(tape);
+
+ return 0;
+}
+
+static void ide_tape_release(struct kref *kref)
+{
+ struct ide_tape_obj *tape = to_ide_tape(kref);
+ ide_drive_t *drive = tape->drive;
+ struct gendisk *g = drive->disk;
+
drive->driver_data = NULL;
devfs_remove("%s/mt", drive->devfs_name);
devfs_remove("%s/mtn", drive->devfs_name);
- devfs_unregister_tape(drive->disk->number);
- kfree (tape);
- drive->disk->fops = ide_fops;
- return 0;
+ devfs_unregister_tape(g->number);
+ idetape_devs[tape->minor] = NULL;
+ g->private_data = NULL;
+ g->fops = ide_fops;
+ kfree(tape);
}
#ifdef CONFIG_PROC_FS
@@ -4667,6 +4723,7 @@ static int proc_idetape_read_name
}
static ide_proc_entry_t idetape_proc[] = {
+ { "capacity", S_IFREG|S_IRUGO, proc_ide_read_capacity, NULL },
{ "name", S_IFREG|S_IRUGO, proc_idetape_read_name, NULL },
{ NULL, 0, NULL, NULL }
};
@@ -4692,7 +4749,8 @@ static ide_driver_t idetape_driver = {
.cleanup = idetape_cleanup,
.do_request = idetape_do_request,
.end_request = idetape_end_request,
- .pre_reset = idetape_pre_reset,
+ .error = __ide_error,
+ .abort = __ide_abort,
.proc = idetape_proc,
.attach = idetape_attach,
.drives = LIST_HEAD_INIT(idetape_driver.drives),
@@ -4712,15 +4770,30 @@ static struct file_operations idetape_fops = {
static int idetape_open(struct inode *inode, struct file *filp)
{
- ide_drive_t *drive = inode->i_bdev->bd_disk->private_data;
+ struct gendisk *disk = inode->i_bdev->bd_disk;
+ struct ide_tape_obj *tape;
+ ide_drive_t *drive;
+
+ if (!(tape = ide_tape_get(disk)))
+ return -ENXIO;
+
+ drive = tape->drive;
+
drive->usage++;
+
return 0;
}
static int idetape_release(struct inode *inode, struct file *filp)
{
- ide_drive_t *drive = inode->i_bdev->bd_disk->private_data;
+ struct gendisk *disk = inode->i_bdev->bd_disk;
+ struct ide_tape_obj *tape = ide_tape_g(disk);
+ ide_drive_t *drive = tape->drive;
+
drive->usage--;
+
+ ide_tape_put(tape);
+
return 0;
}
@@ -4728,8 +4801,9 @@ static int idetape_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
struct block_device *bdev = inode->i_bdev;
- ide_drive_t *drive = bdev->bd_disk->private_data;
- int err = generic_ide_ioctl(file, bdev, cmd, arg);
+ struct ide_tape_obj *tape = ide_tape_g(bdev->bd_disk);
+ ide_drive_t *drive = tape->drive;
+ int err = generic_ide_ioctl(drive, file, bdev, cmd, arg);
if (err == -EINVAL)
err = idetape_blkdev_ioctl(drive, cmd, arg);
return err;
@@ -4745,6 +4819,7 @@ static struct block_device_operations idetape_block_ops = {
static int idetape_attach (ide_drive_t *drive)
{
idetape_tape_t *tape;
+ struct gendisk *g = drive->disk;
int minor;
if (!strstr("ide-tape", drive->driver_req))
@@ -4775,10 +4850,22 @@ static int idetape_attach (ide_drive_t *drive)
kfree(tape);
goto failed;
}
- for (minor = 0; idetape_chrdevs[minor].drive != NULL; minor++)
+
+ memset(tape, 0, sizeof(*tape));
+
+ kref_init(&tape->kref);
+
+ tape->drive = drive;
+
+ drive->driver_data = tape;
+
+ down(&idetape_ref_sem);
+ for (minor = 0; idetape_devs[minor]; minor++)
;
+ idetape_devs[minor] = tape;
+ up(&idetape_ref_sem);
+
idetape_setup(drive, tape, minor);
- idetape_chrdevs[minor].drive = drive;
devfs_mk_cdev(MKDEV(HWIF(drive)->major, minor),
S_IFCHR | S_IRUGO | S_IWUGO,
@@ -4787,8 +4874,10 @@ static int idetape_attach (ide_drive_t *drive)
S_IFCHR | S_IRUGO | S_IWUGO,
"%s/mtn", drive->devfs_name);
- drive->disk->number = devfs_register_tape(drive->devfs_name);
- drive->disk->fops = &idetape_block_ops;
+ g->number = devfs_register_tape(drive->devfs_name);
+ g->fops = &idetape_block_ops;
+ g->private_data = tape;
+
return 0;
failed:
return 1;
diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c
index f7687df7cb6eb..246a1a1bd4657 100644
--- a/drivers/ide/ide-taskfile.c
+++ b/drivers/ide/ide-taskfile.c
@@ -181,8 +181,6 @@ ide_startstop_t set_multmode_intr (ide_drive_t *drive)
return ide_stopped;
}
-EXPORT_SYMBOL(set_multmode_intr);
-
/*
* set_geometry_intr() is invoked on completion of a WIN_SPECIFY cmd.
*/
@@ -207,8 +205,6 @@ ide_startstop_t set_geometry_intr (ide_drive_t *drive)
return ide_started;
}
-EXPORT_SYMBOL(set_geometry_intr);
-
/*
* recal_intr() is invoked on completion of a WIN_RESTORE (recalibrate) cmd.
*/
@@ -222,8 +218,6 @@ ide_startstop_t recal_intr (ide_drive_t *drive)
return ide_stopped;
}
-EXPORT_SYMBOL(recal_intr);
-
/*
* Handler for commands without a data phase
*/
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index 15b643afc1180..20da2d61b200f 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -197,7 +197,6 @@ ide_hwif_t ide_hwifs[MAX_HWIFS]; /* master data repository */
EXPORT_SYMBOL(ide_hwifs);
extern ide_driver_t idedefault_driver;
-static void setup_driver_defaults(ide_driver_t *driver);
/*
* Do not even *think* about calling this!
@@ -301,8 +300,6 @@ static void __init init_ide_data (void)
return; /* already initialized */
magic_cookie = 0;
- setup_driver_defaults(&idedefault_driver);
-
/* Initialise all interface structures */
for (index = 0; index < MAX_HWIFS; ++index) {
hwif = &ide_hwifs[index];
@@ -417,11 +414,6 @@ struct seq_operations ide_drivers_op = {
#ifdef CONFIG_PROC_FS
struct proc_dir_entry *proc_ide_root;
-
-static ide_proc_entry_t generic_subdriver_entries[] = {
- { "capacity", S_IFREG|S_IRUGO, proc_ide_read_capacity, NULL },
- { NULL, 0, NULL, NULL }
-};
#endif
static struct resource* hwif_request_region(ide_hwif_t *hwif,
@@ -1422,10 +1414,9 @@ static int generic_ide_resume(struct device *dev)
return ide_do_drive_cmd(drive, &rq, ide_head_wait);
}
-int generic_ide_ioctl(struct file *file, struct block_device *bdev,
+int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device *bdev,
unsigned int cmd, unsigned long arg)
{
- ide_drive_t *drive = bdev->bd_disk->private_data;
ide_settings_t *setting;
int err = 0;
void __user *p = (void __user *)arg;
@@ -1751,6 +1742,8 @@ static int __init ide_setup(char *s)
case -4: /* "cdrom" */
drive->present = 1;
drive->media = ide_cdrom;
+ /* an ATAPI device ignores DRDY */
+ drive->ready_stat = 0;
hwif->noprobe = 0;
goto done;
case -5: /* "serialize" */
@@ -1777,6 +1770,7 @@ static int __init ide_setup(char *s)
goto done;
case 3: /* cyl,head,sect */
drive->media = ide_disk;
+ drive->ready_stat = READY_STAT;
drive->cyl = drive->bios_cyl = vals[0];
drive->head = drive->bios_head = vals[1];
drive->sect = drive->bios_sect = vals[2];
@@ -2022,68 +2016,6 @@ static void __init probe_for_hwifs (void)
#endif
}
-static ide_startstop_t default_do_request (ide_drive_t *drive, struct request *rq, sector_t block)
-{
- ide_end_request(drive, 0, 0);
- return ide_stopped;
-}
-
-static int default_end_request (ide_drive_t *drive, int uptodate, int nr_sects)
-{
- return ide_end_request(drive, uptodate, nr_sects);
-}
-
-static ide_startstop_t
-default_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err)
-{
- return __ide_error(drive, rq, stat, err);
-}
-
-static void default_pre_reset (ide_drive_t *drive)
-{
-}
-
-static sector_t default_capacity (ide_drive_t *drive)
-{
- return 0x7fffffff;
-}
-
-static ide_startstop_t default_special (ide_drive_t *drive)
-{
- special_t *s = &drive->special;
-
- s->all = 0;
- drive->mult_req = 0;
- return ide_stopped;
-}
-
-static ide_startstop_t default_abort(ide_drive_t *drive, struct request *rq)
-{
- return __ide_abort(drive, rq);
-}
-
-static ide_startstop_t default_start_power_step(ide_drive_t *drive,
- struct request *rq)
-{
- rq->pm->pm_step = ide_pm_state_completed;
- return ide_stopped;
-}
-
-static void setup_driver_defaults (ide_driver_t *d)
-{
- BUG_ON(d->attach == NULL || d->cleanup == NULL);
-
- if (d->do_request == NULL) d->do_request = default_do_request;
- if (d->end_request == NULL) d->end_request = default_end_request;
- if (d->error == NULL) d->error = default_error;
- if (d->abort == NULL) d->abort = default_abort;
- if (d->pre_reset == NULL) d->pre_reset = default_pre_reset;
- if (d->capacity == NULL) d->capacity = default_capacity;
- if (d->special == NULL) d->special = default_special;
- if (d->start_power_step == NULL)
- d->start_power_step = default_start_power_step;
-}
-
int ide_register_subdriver(ide_drive_t *drive, ide_driver_t *driver)
{
unsigned long flags;
@@ -2109,10 +2041,8 @@ int ide_register_subdriver(ide_drive_t *drive, ide_driver_t *driver)
drive->nice1 = 1;
}
#ifdef CONFIG_PROC_FS
- if (drive->driver != &idedefault_driver) {
- ide_add_proc_entries(drive->proc, generic_subdriver_entries, drive);
+ if (drive->driver != &idedefault_driver)
ide_add_proc_entries(drive->proc, driver->proc, drive);
- }
#endif
return 0;
}
@@ -2146,7 +2076,6 @@ int ide_unregister_subdriver (ide_drive_t *drive)
}
#ifdef CONFIG_PROC_FS
ide_remove_proc_entries(drive->proc, DRIVER(drive)->proc);
- ide_remove_proc_entries(drive->proc, generic_subdriver_entries);
#endif
auto_remove_settings(drive);
drive->driver = &idedefault_driver;
@@ -2185,8 +2114,6 @@ int ide_register_driver(ide_driver_t *driver)
struct list_head *list_loop;
struct list_head *tmp_storage;
- setup_driver_defaults(driver);
-
spin_lock(&drivers_lock);
list_add(&driver->drivers, &drivers);
spin_unlock(&drivers_lock);
diff --git a/drivers/ide/pci/cs5520.c b/drivers/ide/pci/cs5520.c
index 5cc037e10b29c..7dc24682d197d 100644
--- a/drivers/ide/pci/cs5520.c
+++ b/drivers/ide/pci/cs5520.c
@@ -47,6 +47,7 @@
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/ide.h>
+#include <linux/dma-mapping.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -227,7 +228,7 @@ static int __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_devic
return 1;
}
pci_set_master(dev);
- if (pci_set_dma_mask(dev, 0xFFFFFFFF)) {
+ if (pci_set_dma_mask(dev, DMA_32BIT_MASK)) {
printk(KERN_WARNING "cs5520: No suitable DMA available.\n");
return -ENODEV;
}
diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c
index f3594e458b769..c8ee0b8c02926 100644
--- a/drivers/ide/pci/hpt366.c
+++ b/drivers/ide/pci/hpt366.c
@@ -1018,32 +1018,25 @@ static void hpt372n_set_clock(ide_drive_t *drive, int mode)
}
/**
- * hpt372n_rw_disk - wrapper for I/O
+ * hpt372n_rw_disk - prepare for I/O
* @drive: drive for command
* @rq: block request structure
- * @block: block number
- *
- * This is called when a disk I/O is issued to the 372N instead
- * of the default functionality. We need it because of the clock
- * switching
*
+ * This is called when a disk I/O is issued to the 372N.
+ * We need it because of the clock switching.
*/
-
-static ide_startstop_t hpt372n_rw_disk(ide_drive_t *drive, struct request *rq, sector_t block)
+
+static void hpt372n_rw_disk(ide_drive_t *drive, struct request *rq)
{
+ ide_hwif_t *hwif = drive->hwif;
int wantclock;
-
- if(rq_data_dir(rq) == READ)
- wantclock = 0x21;
- else
- wantclock = 0x23;
-
- if(HWIF(drive)->config_data != wantclock)
- {
+
+ wantclock = rq_data_dir(rq) ? 0x23 : 0x21;
+
+ if (hwif->config_data != wantclock) {
hpt372n_set_clock(drive, wantclock);
- HWIF(drive)->config_data = wantclock;
+ hwif->config_data = wantclock;
}
- return __ide_do_rw_disk(drive, rq, block);
}
/*
diff --git a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c
index f95ff716809e3..4651a22bf12e9 100644
--- a/drivers/ide/pci/sgiioc4.c
+++ b/drivers/ide/pci/sgiioc4.c
@@ -34,6 +34,7 @@
#include <linux/mm.h>
#include <linux/ioport.h>
#include <linux/blkdev.h>
+#include <linux/ioc4_common.h>
#include <asm/io.h>
#include <linux/ide.h>
@@ -684,23 +685,14 @@ pci_init_sgiioc4(struct pci_dev *dev, ide_pci_device_t * d)
unsigned int class_rev;
int ret;
- ret = pci_enable_device(dev);
- if (ret < 0) {
- printk(KERN_ERR
- "Failed to enable device %s at slot %s\n",
- d->name, dev->slot_name);
- goto out;
- }
- pci_set_master(dev);
-
pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
class_rev &= 0xff;
printk(KERN_INFO "%s: IDE controller at PCI slot %s, revision %d\n",
- d->name, dev->slot_name, class_rev);
+ d->name, pci_name(dev), class_rev);
if (class_rev < IOC4_SUPPORTED_FIRMWARE_REV) {
printk(KERN_ERR "Skipping %s IDE controller in slot %s: "
"firmware is obsolete - please upgrade to revision"
- "46 or higher\n", d->name, dev->slot_name);
+ "46 or higher\n", d->name, pci_name(dev));
ret = -EAGAIN;
goto out;
}
@@ -722,34 +714,15 @@ static ide_pci_device_t sgiioc4_chipsets[] __devinitdata = {
}
};
-static int __devinit
-sgiioc4_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+int
+ioc4_ide_attach_one(struct pci_dev *dev, const struct pci_device_id *id)
{
- pci_init_sgiioc4(dev, &sgiioc4_chipsets[id->driver_data]);
- return 0;
+ return pci_init_sgiioc4(dev, &sgiioc4_chipsets[id->driver_data]);
}
-static struct pci_device_id sgiioc4_pci_tbl[] = {
- {PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC4, PCI_ANY_ID,
- PCI_ANY_ID, 0x0b4000, 0xFFFFFF, 0},
- {0}
-};
-MODULE_DEVICE_TABLE(pci, sgiioc4_pci_tbl);
-
-static struct pci_driver __devinitdata driver = {
- .name = "SGI-IOC4_IDE",
- .id_table = sgiioc4_pci_tbl,
- .probe = sgiioc4_init_one,
-};
-
-static int __devinit
-sgiioc4_ide_init(void)
-{
- return ide_pci_register_driver(&driver);
-}
-
-module_init(sgiioc4_ide_init);
MODULE_AUTHOR("Aniket Malatpure - Silicon Graphics Inc. (SGI)");
-MODULE_DESCRIPTION("PCI driver module for SGI IOC4 Base-IO Card");
+MODULE_DESCRIPTION("IDE PCI driver module for SGI IOC4 Base-IO Card");
MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(ioc4_ide_attach_one);
diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c
index 9c7ea648d471a..6dc273a81327a 100644
--- a/drivers/ide/ppc/pmac.c
+++ b/drivers/ide/ppc/pmac.c
@@ -68,6 +68,7 @@ typedef struct pmac_ide_hwif {
struct device_node* node;
struct macio_dev *mdev;
u32 timings[4];
+ volatile u32 __iomem * *kauai_fcr;
#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
/* Those fields are duplicating what is in hwif. We currently
* can't use the hwif ones because of some assumptions that are
@@ -89,7 +90,8 @@ enum {
controller_kl_ata3, /* KeyLargo ATA-3 */
controller_kl_ata4, /* KeyLargo ATA-4 */
controller_un_ata6, /* UniNorth2 ATA-6 */
- controller_k2_ata6 /* K2 ATA-6 */
+ controller_k2_ata6, /* K2 ATA-6 */
+ controller_sh_ata6, /* Shasta ATA-6 */
};
static const char* model_name[] = {
@@ -99,6 +101,7 @@ static const char* model_name[] = {
"KeyLargo ATA-4", /* KeyLargo ATA-4 (UDMA/66) */
"UniNorth ATA-6", /* UniNorth2 ATA-6 (UDMA/100) */
"K2 ATA-6", /* K2 ATA-6 (UDMA/100) */
+ "Shasta ATA-6", /* Shasta ATA-6 (UDMA/133) */
};
/*
@@ -122,6 +125,15 @@ static const char* model_name[] = {
#define IDE_SYSCLK_NS 30 /* 33Mhz cell */
#define IDE_SYSCLK_66_NS 15 /* 66Mhz cell */
+/* 133Mhz cell, found in shasta.
+ * See comments about 100 Mhz Uninorth 2...
+ * Note that PIO_MASK and MDMA_MASK seem to overlap
+ */
+#define TR_133_PIOREG_PIO_MASK 0xff000fff
+#define TR_133_PIOREG_MDMA_MASK 0x00fff800
+#define TR_133_UDMAREG_UDMA_MASK 0x0003ffff
+#define TR_133_UDMAREG_UDMA_EN 0x00000001
+
/* 100Mhz cell, found in Uninorth 2. I don't have much infos about
* this one yet, it appears as a pci device (106b/0033) on uninorth
* internal PCI bus and it's clock is controlled like gem or fw. It
@@ -209,6 +221,13 @@ static const char* model_name[] = {
#define IDE_INTR_DMA 0x80000000
#define IDE_INTR_DEVICE 0x40000000
+/*
+ * FCR Register on Kauai. Not sure what bit 0x4 is ...
+ */
+#define KAUAI_FCR_UATA_MAGIC 0x00000004
+#define KAUAI_FCR_UATA_RESET_N 0x00000002
+#define KAUAI_FCR_UATA_ENABLE 0x00000001
+
#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
/* Rounded Multiword DMA timings
@@ -322,6 +341,48 @@ static struct kauai_timing kauai_udma_timings[] __pmacdata =
{ 0 , 0 },
};
+static struct kauai_timing shasta_pio_timings[] __pmacdata =
+{
+ { 930 , 0x08000fff },
+ { 600 , 0x0A000c97 },
+ { 383 , 0x07000712 },
+ { 360 , 0x040003cd },
+ { 330 , 0x040003cd },
+ { 300 , 0x040003cd },
+ { 270 , 0x040003cd },
+ { 240 , 0x040003cd },
+ { 239 , 0x040003cd },
+ { 180 , 0x0400028b },
+ { 120 , 0x0400010a }
+};
+
+static struct kauai_timing shasta_mdma_timings[] __pmacdata =
+{
+ { 1260 , 0x00fff000 },
+ { 480 , 0x00820800 },
+ { 360 , 0x00820800 },
+ { 270 , 0x00820800 },
+ { 240 , 0x00820800 },
+ { 210 , 0x00820800 },
+ { 180 , 0x00820800 },
+ { 150 , 0x0028b000 },
+ { 120 , 0x001ca000 },
+ { 0 , 0 },
+};
+
+static struct kauai_timing shasta_udma133_timings[] __pmacdata =
+{
+ { 120 , 0x00035901, },
+ { 90 , 0x000348b1, },
+ { 60 , 0x00033881, },
+ { 45 , 0x00033861, },
+ { 30 , 0x00033841, },
+ { 20 , 0x00033031, },
+ { 15 , 0x00033021, },
+ { 0 , 0 },
+};
+
+
static inline u32
kauai_lookup_timing(struct kauai_timing* table, int cycle_time)
{
@@ -547,7 +608,9 @@ pmac_ide_do_update_timings(ide_drive_t *drive)
if (pmif == NULL)
return;
- if (pmif->kind == controller_un_ata6 || pmif->kind == controller_k2_ata6)
+ if (pmif->kind == controller_sh_ata6 ||
+ pmif->kind == controller_un_ata6 ||
+ pmif->kind == controller_k2_ata6)
pmac_ide_kauai_selectproc(drive);
else
pmac_ide_selectproc(drive);
@@ -665,6 +728,14 @@ pmac_ide_tuneproc(ide_drive_t *drive, u8 pio)
pio = ide_get_best_pio_mode(drive, pio, 4, &d);
switch (pmif->kind) {
+ case controller_sh_ata6: {
+ /* 133Mhz cell */
+ u32 tr = kauai_lookup_timing(shasta_pio_timings, d.cycle_time);
+ if (tr == 0)
+ return;
+ *timings = ((*timings) & ~TR_133_PIOREG_PIO_MASK) | tr;
+ break;
+ }
case controller_un_ata6:
case controller_k2_ata6: {
/* 100Mhz cell */
@@ -776,6 +847,26 @@ set_timings_udma_ata6(u32 *pio_timings, u32 *ultra_timings, u8 speed)
}
/*
+ * Calculate Shasta ATA/133 UDMA timings
+ */
+static int __pmac
+set_timings_udma_shasta(u32 *pio_timings, u32 *ultra_timings, u8 speed)
+{
+ struct ide_timing *t = ide_timing_find_mode(speed);
+ u32 tr;
+
+ if (speed > XFER_UDMA_6 || t == NULL)
+ return 1;
+ tr = kauai_lookup_timing(shasta_udma133_timings, (int)t->udma);
+ if (tr == 0)
+ return 1;
+ *ultra_timings = ((*ultra_timings) & ~TR_133_UDMAREG_UDMA_MASK) | tr;
+ *ultra_timings = (*ultra_timings) | TR_133_UDMAREG_UDMA_EN;
+
+ return 0;
+}
+
+/*
* Calculate MDMA timings for all cells
*/
static int __pmac
@@ -803,6 +894,7 @@ set_timings_mdma(ide_drive_t *drive, int intf_type, u32 *timings, u32 *timings2,
cycleTime = 150;
/* Get the proper timing array for this controller */
switch(intf_type) {
+ case controller_sh_ata6:
case controller_un_ata6:
case controller_k2_ata6:
break;
@@ -836,6 +928,14 @@ set_timings_mdma(ide_drive_t *drive, int intf_type, u32 *timings, u32 *timings2,
#endif
}
switch(intf_type) {
+ case controller_sh_ata6: {
+ /* 133Mhz cell */
+ u32 tr = kauai_lookup_timing(shasta_mdma_timings, cycleTime);
+ if (tr == 0)
+ return 1;
+ *timings = ((*timings) & ~TR_133_PIOREG_MDMA_MASK) | tr;
+ *timings2 = (*timings2) & ~TR_133_UDMAREG_UDMA_EN;
+ }
case controller_un_ata6:
case controller_k2_ata6: {
/* 100Mhz cell */
@@ -930,9 +1030,13 @@ pmac_ide_tune_chipset (ide_drive_t *drive, byte speed)
switch(speed) {
#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
+ case XFER_UDMA_6:
+ if (pmif->kind != controller_sh_ata6)
+ return 1;
case XFER_UDMA_5:
if (pmif->kind != controller_un_ata6 &&
- pmif->kind != controller_k2_ata6)
+ pmif->kind != controller_k2_ata6 &&
+ pmif->kind != controller_sh_ata6)
return 1;
case XFER_UDMA_4:
case XFER_UDMA_3:
@@ -946,6 +1050,8 @@ pmac_ide_tune_chipset (ide_drive_t *drive, byte speed)
else if (pmif->kind == controller_un_ata6
|| pmif->kind == controller_k2_ata6)
ret = set_timings_udma_ata6(timings, timings2, speed);
+ else if (pmif->kind == controller_sh_ata6)
+ ret = set_timings_udma_shasta(timings, timings2, speed);
else
ret = 1;
break;
@@ -992,6 +1098,10 @@ sanitize_timings(pmac_ide_hwif_t *pmif)
unsigned int value, value2 = 0;
switch(pmif->kind) {
+ case controller_sh_ata6:
+ value = 0x0a820c97;
+ value2 = 0x00033031;
+ break;
case controller_un_ata6:
case controller_k2_ata6:
value = 0x08618a92;
@@ -1098,8 +1208,16 @@ pmac_ide_do_suspend(ide_hwif_t *hwif)
if (pmif->mediabay)
return 0;
- /* Disable the bus */
- ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, pmif->node, pmif->aapl_bus_id, 0);
+ /* Kauai has bus control FCRs directly here */
+ if (pmif->kauai_fcr) {
+ u32 fcr = readl(pmif->kauai_fcr);
+ fcr &= ~(KAUAI_FCR_UATA_RESET_N | KAUAI_FCR_UATA_ENABLE);
+ writel(fcr, pmif->kauai_fcr);
+ }
+
+ /* Disable the bus on older machines and the cell on kauai */
+ ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, pmif->node, pmif->aapl_bus_id,
+ 0);
return 0;
}
@@ -1119,6 +1237,13 @@ pmac_ide_do_resume(ide_hwif_t *hwif)
msleep(10);
ppc_md.feature_call(PMAC_FTR_IDE_RESET, pmif->node, pmif->aapl_bus_id, 0);
msleep(jiffies_to_msecs(IDE_WAKEUP_DELAY));
+
+ /* Kauai has it different */
+ if (pmif->kauai_fcr) {
+ u32 fcr = readl(pmif->kauai_fcr);
+ fcr |= KAUAI_FCR_UATA_RESET_N | KAUAI_FCR_UATA_ENABLE;
+ writel(fcr, pmif->kauai_fcr);
+ }
}
/* Sanitize drive timings */
@@ -1142,7 +1267,9 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif)
pmif->cable_80 = 0;
pmif->broken_dma = pmif->broken_dma_warn = 0;
- if (device_is_compatible(np, "kauai-ata"))
+ if (device_is_compatible(np, "shasta-ata"))
+ pmif->kind = controller_sh_ata6;
+ else if (device_is_compatible(np, "kauai-ata"))
pmif->kind = controller_un_ata6;
else if (device_is_compatible(np, "K2-UATA"))
pmif->kind = controller_k2_ata6;
@@ -1163,11 +1290,25 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif)
/* Get cable type from device-tree */
if (pmif->kind == controller_kl_ata4 || pmif->kind == controller_un_ata6
- || pmif->kind == controller_k2_ata6) {
+ || pmif->kind == controller_k2_ata6
+ || pmif->kind == controller_sh_ata6) {
char* cable = get_property(np, "cable-type", NULL);
if (cable && !strncmp(cable, "80-", 3))
pmif->cable_80 = 1;
}
+ /* G5's seem to have incorrect cable type in device-tree. Let's assume
+ * they have a 80 conductor cable, this seem to be always the case unless
+ * the user mucked around
+ */
+ if (device_is_compatible(np, "K2-UATA") ||
+ device_is_compatible(np, "shasta-ata"))
+ pmif->cable_80 = 1;
+
+ /* On Kauai-type controllers, we make sure the FCR is correct */
+ if (pmif->kauai_fcr)
+ writel(KAUAI_FCR_UATA_MAGIC |
+ KAUAI_FCR_UATA_RESET_N |
+ KAUAI_FCR_UATA_ENABLE, pmif->kauai_fcr);
pmif->mediabay = 0;
@@ -1217,7 +1358,9 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif)
hwif->drives[0].unmask = 1;
hwif->drives[1].unmask = 1;
hwif->tuneproc = pmac_ide_tuneproc;
- if (pmif->kind == controller_un_ata6 || pmif->kind == controller_k2_ata6)
+ if (pmif->kind == controller_un_ata6
+ || pmif->kind == controller_k2_ata6
+ || pmif->kind == controller_sh_ata6)
hwif->selectproc = pmac_ide_kauai_selectproc;
else
hwif->selectproc = pmac_ide_selectproc;
@@ -1327,6 +1470,7 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_match *match)
pmif->node = mdev->ofdev.node;
pmif->regbase = regbase;
pmif->irq = irq;
+ pmif->kauai_fcr = NULL;
#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
if (macio_resource_count(mdev) >= 2) {
if (macio_request_resource(mdev, 1, "ide-pmac (dma)"))
@@ -1440,13 +1584,9 @@ pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id)
pmif->regbase = (unsigned long) base + 0x2000;
#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
pmif->dma_regs = base + 0x1000;
-#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
-
- /* We use the OF node irq mapping */
- if (np->n_intrs == 0)
- pmif->irq = pdev->irq;
- else
- pmif->irq = np->intrs[0].line;
+#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
+ pmif->kauai_fcr = base;
+ pmif->irq = pdev->irq;
pci_set_drvdata(pdev, hwif);
@@ -1530,6 +1670,8 @@ static struct pci_device_id pmac_ide_pci_match[] = {
{ PCI_VENDOR_ID_APPLE, PCI_DEVIEC_ID_APPLE_UNI_N_ATA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{ PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_IPID_ATA100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{ PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_K2_ATA100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_SH_ATA,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
};
static struct pci_driver pmac_ide_pci_driver = {
@@ -1539,6 +1681,7 @@ static struct pci_driver pmac_ide_pci_driver = {
.suspend = pmac_ide_pci_suspend,
.resume = pmac_ide_pci_resume,
};
+MODULE_DEVICE_TABLE(pci, pmac_ide_pci_match);
void __init
pmac_ide_probe(void)
@@ -1737,10 +1880,15 @@ pmac_ide_udma_enable(ide_drive_t *drive, u16 mode)
timing_local[1] = *timings2;
/* Calculate timings for interface */
- if (pmif->kind == controller_un_ata6 || pmif->kind == controller_k2_ata6)
+ if (pmif->kind == controller_un_ata6
+ || pmif->kind == controller_k2_ata6)
ret = set_timings_udma_ata6( &timing_local[0],
&timing_local[1],
mode);
+ else if (pmif->kind == controller_sh_ata6)
+ ret = set_timings_udma_shasta( &timing_local[0],
+ &timing_local[1],
+ mode);
else
ret = set_timings_udma_ata4(&timing_local[0], mode);
if (ret)
@@ -1791,14 +1939,19 @@ pmac_ide_dma_check(ide_drive_t *drive)
short mode;
map = XFER_MWDMA;
- if (pmif->kind == controller_kl_ata4 || pmif->kind == controller_un_ata6
- || pmif->kind == controller_k2_ata6) {
+ if (pmif->kind == controller_kl_ata4
+ || pmif->kind == controller_un_ata6
+ || pmif->kind == controller_k2_ata6
+ || pmif->kind == controller_sh_ata6) {
map |= XFER_UDMA;
if (pmif->cable_80) {
map |= XFER_UDMA_66;
if (pmif->kind == controller_un_ata6 ||
- pmif->kind == controller_k2_ata6)
+ pmif->kind == controller_k2_ata6 ||
+ pmif->kind == controller_sh_ata6)
map |= XFER_UDMA_100;
+ if (pmif->kind == controller_sh_ata6)
+ map |= XFER_UDMA_133;
}
}
mode = ide_find_best_mode(drive, map);
@@ -2028,6 +2181,11 @@ pmac_ide_setup_dma(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif)
hwif->atapi_dma = 1;
switch(pmif->kind) {
+ case controller_sh_ata6:
+ hwif->ultra_mask = pmif->cable_80 ? 0x7f : 0x07;
+ hwif->mwdma_mask = 0x07;
+ hwif->swdma_mask = 0x00;
+ break;
case controller_un_ata6:
case controller_k2_ata6:
hwif->ultra_mask = pmif->cable_80 ? 0x3f : 0x07;
diff --git a/drivers/ieee1394/Kconfig b/drivers/ieee1394/Kconfig
index f2ae812892552..78b201fb5e8ab 100644
--- a/drivers/ieee1394/Kconfig
+++ b/drivers/ieee1394/Kconfig
@@ -5,6 +5,7 @@ menu "IEEE 1394 (FireWire) support"
config IEEE1394
tristate "IEEE 1394 (FireWire) support"
depends on PCI || BROKEN
+ select NET
help
IEEE 1394 describes a high performance serial bus, which is also
known as FireWire(tm) or i.Link(tm) and is used for connecting all
diff --git a/drivers/ieee1394/amdtp.c b/drivers/ieee1394/amdtp.c
index 6ba5de706fae4..84ae027b021a1 100644
--- a/drivers/ieee1394/amdtp.c
+++ b/drivers/ieee1394/amdtp.c
@@ -286,7 +286,7 @@ static struct hpsb_highlevel amdtp_highlevel;
#define OHCI1394_CONTEXT_DEAD 0x00000800
#define OHCI1394_CONTEXT_ACTIVE 0x00000400
-void ohci1394_start_it_ctx(struct ti_ohci *ohci, int ctx,
+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);
@@ -298,13 +298,13 @@ void ohci1394_start_it_ctx(struct ti_ohci *ohci, int ctx,
OHCI1394_CONTEXT_RUN);
}
-void ohci1394_wake_it_ctx(struct ti_ohci *ohci, int ctx)
+static void ohci1394_wake_it_ctx(struct ti_ohci *ohci, int ctx)
{
reg_write(ohci, OHCI1394_IsoXmitContextControlSet + ctx * 16,
OHCI1394_CONTEXT_WAKE);
}
-void ohci1394_stop_it_ctx(struct ti_ohci *ohci, int ctx, int synchronous)
+static void ohci1394_stop_it_ctx(struct ti_ohci *ohci, int ctx, int synchronous)
{
u32 control;
int wait;
@@ -530,7 +530,7 @@ static __inline__ int fraction_ceil(struct fraction *frac)
return frac->integer + (frac->numerator > 0 ? 1 : 0);
}
-void packet_initialize(struct packet *p, struct packet *next)
+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
@@ -559,7 +559,7 @@ void packet_initialize(struct packet *p, struct packet *next)
p->db->payload_desc.status = 0;
}
-struct packet_list *packet_list_alloc(struct stream *s)
+static struct packet_list *packet_list_alloc(struct stream *s)
{
int i;
struct packet_list *pl;
@@ -588,7 +588,7 @@ struct packet_list *packet_list_alloc(struct stream *s)
return pl;
}
-void packet_list_free(struct packet_list *pl, struct stream *s)
+static void packet_list_free(struct packet_list *pl, struct stream *s)
{
int i;
@@ -1010,7 +1010,7 @@ static int stream_configure(struct stream *s, int cmd, struct amdtp_ioctl *cfg)
return 0;
}
-struct stream *stream_alloc(struct amdtp_host *host)
+static struct stream *stream_alloc(struct amdtp_host *host)
{
struct stream *s;
unsigned long flags;
@@ -1062,7 +1062,7 @@ struct stream *stream_alloc(struct amdtp_host *host)
return s;
}
-void stream_free(struct stream *s)
+static void stream_free(struct stream *s)
{
unsigned long flags;
diff --git a/drivers/ieee1394/config_roms.c b/drivers/ieee1394/config_roms.c
index 530f853f03cee..1017fd7172486 100644
--- a/drivers/ieee1394/config_roms.c
+++ b/drivers/ieee1394/config_roms.c
@@ -67,8 +67,8 @@ int hpsb_default_host_entry(struct hpsb_host *host)
ret = csr1212_associate_keyval(vend_id, text);
csr1212_release_keyval(text);
ret |= csr1212_attach_keyval_to_directory(root, vend_id);
+ csr1212_release_keyval(vend_id);
if (ret != CSR1212_SUCCESS) {
- csr1212_release_keyval(vend_id);
csr1212_destroy_csr(host->csr.rom);
return -ENOMEM;
}
diff --git a/drivers/ieee1394/csr1212.c b/drivers/ieee1394/csr1212.c
index 931464b6ce9ea..7c4330e2e875b 100644
--- a/drivers/ieee1394/csr1212.c
+++ b/drivers/ieee1394/csr1212.c
@@ -87,7 +87,8 @@ static const u_int8_t csr1212_key_id_type_map[0x30] = {
static inline void free_keyval(struct csr1212_keyval *kv)
{
- if (kv->key.type == CSR1212_KV_TYPE_LEAF)
+ if ((kv->key.type == CSR1212_KV_TYPE_LEAF) &&
+ (kv->key.id != CSR1212_KV_ID_EXTENDED_ROM))
CSR1212_FREE(kv->value.leaf.data);
CSR1212_FREE(kv);
@@ -155,7 +156,7 @@ static inline struct csr1212_keyval *csr1212_find_keyval_offset(struct csr1212_k
{
struct csr1212_keyval *kv;
- for (kv = kv_list; kv != NULL; kv = kv->next) {
+ for (kv = kv_list->next; kv && (kv != kv_list); kv = kv->next) {
if (kv->offset == offset)
return kv;
}
@@ -181,9 +182,9 @@ struct csr1212_csr *csr1212_create_csr(struct csr1212_bus_ops *ops,
return NULL;
}
- /* The keyval key id is not used for the root node, but a valid key id
- * that can be used for a directory needs to be passed to
- * csr1212_new_directory(). */
+ /* The keyval key id is not used for the root node, but a valid key id
+ * that can be used for a directory needs to be passed to
+ * csr1212_new_directory(). */
csr->root_kv = csr1212_new_directory(CSR1212_KV_ID_VENDOR);
if (!csr->root_kv) {
CSR1212_FREE(csr->cache_head);
@@ -709,7 +710,7 @@ void _csr1212_destroy_keyval(struct csr1212_keyval *kv)
tail->next = k->value.directory.dentries_head;
k->value.directory.dentries_head->prev = tail;
tail = k->value.directory.dentries_tail;
- }
+ }
}
free_keyval(k);
k = a;
@@ -796,7 +797,8 @@ static int csr1212_append_new_cache(struct csr1212_csr *csr, size_t romsize)
return CSR1212_ENOMEM;
}
cache->ext_rom->offset = csr_addr - CSR1212_REGISTER_SPACE_BASE;
- cache->ext_rom->value.leaf.len = 0;
+ cache->ext_rom->value.leaf.len = -1;
+ cache->ext_rom->value.leaf.data = cache->data;
/* Add cache to tail of cache list */
cache->prev = csr->cache_tail;
@@ -864,20 +866,20 @@ static int csr1212_generate_layout_subdir(struct csr1212_keyval *dir,
default:
case CSR1212_KV_TYPE_IMMEDIATE:
case CSR1212_KV_TYPE_CSR_OFFSET:
- continue;
+ break;
case CSR1212_KV_TYPE_LEAF:
case CSR1212_KV_TYPE_DIRECTORY:
/* Remove from list */
- if (dkv->prev)
+ if (dkv->prev && (dkv->prev->next == dkv))
dkv->prev->next = dkv->next;
- if (dkv->next)
+ if (dkv->next && (dkv->next->prev == dkv))
dkv->next->prev = dkv->prev;
- if (dkv == *layout_tail)
- *layout_tail = dkv->prev;
+ //if (dkv == *layout_tail)
+ // *layout_tail = dkv->prev;
/* Special case: Extended ROM leafs */
if (dkv->key.id == CSR1212_KV_ID_EXTENDED_ROM) {
- dkv->value.leaf.len = 0; /* initialize to zero */
+ dkv->value.leaf.len = -1;
/* Don't add Extended ROM leafs in the layout list,
* they are handled differently. */
break;
@@ -919,8 +921,8 @@ size_t csr1212_generate_layout_order(struct csr1212_keyval *kv)
}
struct csr1212_keyval *csr1212_generate_positions(struct csr1212_csr_rom_cache *cache,
- struct csr1212_keyval *start_kv,
- int start_pos)
+ struct csr1212_keyval *start_kv,
+ int start_pos)
{
struct csr1212_keyval *kv = start_kv;
struct csr1212_keyval *okv = start_kv;
@@ -930,7 +932,10 @@ struct csr1212_keyval *csr1212_generate_positions(struct csr1212_csr_rom_cache *
cache->layout_head = kv;
while(kv && pos < cache->size) {
- kv->offset = cache->offset + pos;
+ /* Special case: Extended ROM leafs */
+ if (kv->key.id != CSR1212_KV_ID_EXTENDED_ROM) {
+ kv->offset = cache->offset + pos;
+ }
switch(kv->key.type) {
case CSR1212_KV_TYPE_LEAF:
@@ -1090,6 +1095,9 @@ int csr1212_generate_csr_image(struct csr1212_csr *csr)
bi->crc_length = bi->length;
bi->crc = csr1212_crc16(bi->data, bi->crc_length);
+ csr->root_kv->next = NULL;
+ csr->root_kv->prev = NULL;
+
agg_size = csr1212_generate_layout_order(csr->root_kv);
init_offset = csr->bus_info_len;
@@ -1158,6 +1166,17 @@ int csr1212_generate_csr_image(struct csr1212_csr *csr)
/* Copy the data into the cache buffer */
csr1212_fill_cache(cache);
+
+ if (cache != csr->cache_head) {
+ /* Set the length and CRC of the extended ROM. */
+ struct csr1212_keyval_img *kvi =
+ (struct csr1212_keyval_img*)cache->data;
+
+ kvi->length = CSR1212_CPU_TO_BE16(bytes_to_quads(cache->len) - 1);
+ kvi->crc = csr1212_crc16(kvi->data,
+ bytes_to_quads(cache->len) - 1);
+
+ }
}
return CSR1212_SUCCESS;
@@ -1174,11 +1193,6 @@ int csr1212_read(struct csr1212_csr *csr, u_int32_t offset, void *buffer, u_int3
&cache->data[bytes_to_quads(offset - cache->offset)],
len);
return CSR1212_SUCCESS;
- } else if (((offset < cache->offset) &&
- ((offset + len) >= cache->offset)) ||
- ((offset >= cache->offset) &&
- ((offset + len) > (cache->offset + cache->size)))) {
- return CSR1212_EINVAL;
}
}
return CSR1212_ENOENT;
@@ -1227,8 +1241,8 @@ static int csr1212_parse_bus_info_block(struct csr1212_csr *csr)
return CSR1212_EINVAL;
#if 0
- /* Apparently there are too many differnt wrong implementations of the
- * CRC algorithm that verifying them is moot. */
+ /* Apparently there are too many differnt wrong implementations of the
+ * CRC algorithm that verifying them is moot. */
if ((csr1212_crc16(bi->data, bi->crc_length) != bi->crc) &&
(csr1212_msft_crc16(bi->data, bi->crc_length) != bi->crc))
return CSR1212_EINVAL;
@@ -1249,10 +1263,9 @@ static int csr1212_parse_bus_info_block(struct csr1212_csr *csr)
return CSR1212_SUCCESS;
}
-static inline int csr1212_parse_dir_entry(struct csr1212_keyval *dir,
- csr1212_quad_t ki,
- u_int32_t kv_pos,
- struct csr1212_csr_rom_cache *cache)
+static int csr1212_parse_dir_entry(struct csr1212_keyval *dir,
+ csr1212_quad_t ki,
+ u_int32_t kv_pos)
{
int ret = CSR1212_SUCCESS;
struct csr1212_keyval *k = NULL;
@@ -1291,7 +1304,7 @@ static inline int csr1212_parse_dir_entry(struct csr1212_keyval *dir,
goto fail;
}
- k = csr1212_find_keyval_offset(cache->layout_head, offset);
+ k = csr1212_find_keyval_offset(dir, offset);
if (k)
break; /* Found it. */
@@ -1309,11 +1322,10 @@ static inline int csr1212_parse_dir_entry(struct csr1212_keyval *dir,
k->valid = 0; /* Contents not read yet so it's not valid. */
k->offset = offset;
- k->prev = cache->layout_tail;
- k->next = NULL;
- if (cache->layout_tail)
- cache->layout_tail->next = k;
- cache->layout_tail = k;
+ k->prev = dir;
+ k->next = dir->next;
+ dir->next->prev = k;
+ dir->next = k;
}
ret = csr1212_attach_keyval_to_directory(dir, k);
@@ -1325,6 +1337,7 @@ fail:
return ret;
}
+
int csr1212_parse_keyval(struct csr1212_keyval *kv,
struct csr1212_csr_rom_cache *cache)
{
@@ -1338,8 +1351,8 @@ int csr1212_parse_keyval(struct csr1212_keyval *kv,
kvi_len = CSR1212_BE16_TO_CPU(kvi->length);
#if 0
- /* Apparently there are too many differnt wrong implementations of the
- * CRC algorithm that verifying them is moot. */
+ /* Apparently there are too many differnt wrong implementations of the
+ * CRC algorithm that verifying them is moot. */
if ((csr1212_crc16(kvi->data, kvi_len) != kvi->crc) &&
(csr1212_msft_crc16(kvi->data, kvi_len) != kvi->crc)) {
ret = CSR1212_EINVAL;
@@ -1353,22 +1366,19 @@ int csr1212_parse_keyval(struct csr1212_keyval *kv,
csr1212_quad_t ki = kvi->data[i];
/* Some devices put null entries in their unit
- * directories. If we come across such and entry,
+ * directories. If we come across such an entry,
* then skip it. */
if (ki == 0x0)
continue;
ret = csr1212_parse_dir_entry(kv, ki,
(kv->offset +
- quads_to_bytes(i + 1)),
- cache);
+ quads_to_bytes(i + 1)));
}
kv->value.directory.len = kvi_len;
break;
case CSR1212_KV_TYPE_LEAF:
- if (kv->key.id == CSR1212_KV_ID_EXTENDED_ROM) {
- kv->value.leaf.data = cache->data;
- } else {
+ 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)
{
@@ -1399,7 +1409,6 @@ int _csr1212_read_keyval(struct csr1212_csr *csr, struct csr1212_keyval *kv)
u_int32_t *cache_ptr;
u_int16_t kv_len = 0;
-
if (!csr || !kv)
return CSR1212_EINVAL;
@@ -1413,7 +1422,7 @@ int _csr1212_read_keyval(struct csr1212_csr *csr, struct csr1212_keyval *kv)
if (!cache) {
csr1212_quad_t q;
- struct csr1212_csr_rom_cache *nc;
+ u_int32_t cache_size;
/* Only create a new cache for Extended ROM leaves. */
if (kv->key.id != CSR1212_KV_ID_EXTENDED_ROM)
@@ -1425,12 +1434,20 @@ int _csr1212_read_keyval(struct csr1212_csr *csr, struct csr1212_keyval *kv)
return CSR1212_EIO;
}
- kv->value.leaf.len = quads_to_bytes(CSR1212_BE32_TO_CPU(q)>>16);
+ kv->value.leaf.len = CSR1212_BE32_TO_CPU(q) >> 16;
+
+ cache_size = (quads_to_bytes(kv->value.leaf.len + 1) +
+ (csr->max_rom - 1)) & ~(csr->max_rom - 1);
- nc = csr1212_rom_cache_malloc(kv->offset, kv->value.leaf.len);
- cache->next = nc;
- nc->prev = cache;
- csr->cache_tail = nc;
+ cache = csr1212_rom_cache_malloc(kv->offset, cache_size);
+ if (!cache)
+ return CSR1212_ENOMEM;
+
+ kv->value.leaf.data = &cache->data[1];
+ csr->cache_tail->next = cache;
+ cache->prev = csr->cache_tail;
+ cache->next = NULL;
+ csr->cache_tail = cache;
cache->filled_head =
CSR1212_MALLOC(sizeof(struct csr1212_cache_region));
if (!cache->filled_head) {
@@ -1443,6 +1460,10 @@ int _csr1212_read_keyval(struct csr1212_csr *csr, struct csr1212_keyval *kv)
cache->filled_head->next = NULL;
cache->filled_head->prev = NULL;
cache->data[0] = q;
+
+ /* Don't read the entire extended ROM now. Pieces of it will
+ * be read when entries inside it are read. */
+ return csr1212_parse_keyval(kv, cache);
}
cache_index = kv->offset - cache->offset;
@@ -1548,6 +1569,7 @@ int _csr1212_read_keyval(struct csr1212_csr *csr, struct csr1212_keyval *kv)
int csr1212_parse_csr(struct csr1212_csr *csr)
{
static const int mr_map[] = { 4, 64, 1024, 0 };
+ struct csr1212_dentry *dentry;
int ret;
if (!csr || !csr->ops->bus_read)
@@ -1570,7 +1592,21 @@ int csr1212_parse_csr(struct csr1212_csr *csr)
csr->bus_info_len;
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);
+ /* 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 (ret != CSR1212_SUCCESS)
+ return ret;
+ }
+ }
+
return CSR1212_SUCCESS;
}
diff --git a/drivers/ieee1394/dma.c b/drivers/ieee1394/dma.c
index 4bc2eab69e14a..758819d1999dd 100644
--- a/drivers/ieee1394/dma.c
+++ b/drivers/ieee1394/dma.c
@@ -127,16 +127,12 @@ void dma_region_free(struct dma_region *dma)
dma->dev = NULL;
}
- if (dma->sglist) {
- vfree(dma->sglist);
- dma->sglist = NULL;
- }
+ vfree(dma->sglist);
+ dma->sglist = NULL;
- if (dma->kvirt) {
- vfree(dma->kvirt);
- dma->kvirt = NULL;
- dma->n_pages = 0;
- }
+ vfree(dma->kvirt);
+ dma->kvirt = NULL;
+ dma->n_pages = 0;
}
/* find the scatterlist index and remaining offset corresponding to a
diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c
index f800900845755..68c7a5f07842d 100644
--- a/drivers/ieee1394/dv1394.c
+++ b/drivers/ieee1394/dv1394.c
@@ -1277,7 +1277,7 @@ static void do_dv1394_shutdown(struct video_card *video, int free_dv_buf)
error-prone code in dv1394.
*/
-int dv1394_mmap(struct file *file, struct vm_area_struct *vma)
+static int dv1394_mmap(struct file *file, struct vm_area_struct *vma)
{
struct video_card *video = file_to_video_card(file);
int retval = -EINVAL;
@@ -2343,6 +2343,8 @@ static void dv1394_remove_host (struct hpsb_host *host)
dv1394_un_init(video);
} while (video != NULL);
+ class_simple_device_remove(MKDEV(
+ IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_DV1394 * 16 + (id<<2)));
devfs_remove("ieee1394/dv/host%d/NTSC", id);
devfs_remove("ieee1394/dv/host%d/PAL", id);
devfs_remove("ieee1394/dv/host%d", id);
@@ -2359,6 +2361,9 @@ static void dv1394_add_host (struct hpsb_host *host)
ohci = (struct ti_ohci *)host->hostdata;
+ class_simple_device_add(hpsb_protocol_class, MKDEV(
+ IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_DV1394 * 16 + (id<<2)),
+ NULL, "dv1394-%d", id);
devfs_mk_dir("ieee1394/dv/host%d", id);
devfs_mk_dir("ieee1394/dv/host%d/NTSC", id);
devfs_mk_dir("ieee1394/dv/host%d/PAL", id);
@@ -2526,7 +2531,7 @@ static int handle_dv1394_init(struct file *file, unsigned int cmd, unsigned long
mm_segment_t old_fs;
int ret;
- if (file->f_op->ioctl != dv1394_ioctl)
+ if (file->f_op->unlocked_ioctl != dv1394_ioctl)
return -EFAULT;
if (copy_from_user(&dv32, (void __user *)arg, sizeof(dv32)))
@@ -2542,8 +2547,7 @@ static int handle_dv1394_init(struct file *file, unsigned int cmd, unsigned long
old_fs = get_fs();
set_fs(KERNEL_DS);
- ret = dv1394_ioctl(file,
- DV1394_IOC_INIT, (unsigned long)&dv);
+ ret = dv1394_ioctl(file, DV1394_IOC_INIT, (unsigned long)&dv);
set_fs(old_fs);
return ret;
@@ -2556,13 +2560,12 @@ static int handle_dv1394_get_status(struct file *file, unsigned int cmd, unsigne
mm_segment_t old_fs;
int ret;
- if (file->f_op->ioctl != dv1394_ioctl)
+ if (file->f_op->unlocked_ioctl != dv1394_ioctl)
return -EFAULT;
old_fs = get_fs();
set_fs(KERNEL_DS);
- ret = dv1394_ioctl(file,
- DV1394_IOC_GET_STATUS, (unsigned long)&dv);
+ ret = dv1394_ioctl(file, DV1394_IOC_GET_STATUS, (unsigned long)&dv);
set_fs(old_fs);
if (!ret) {
@@ -2590,7 +2593,6 @@ static int handle_dv1394_get_status(struct file *file, unsigned int cmd, unsigne
static long dv1394_compat_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
- int err;
switch (cmd) {
case DV1394_IOC_SHUTDOWN:
case DV1394_IOC_SUBMIT_FRAMES:
diff --git a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c
index 9b01d57486e3f..654da76bf8114 100644
--- a/drivers/ieee1394/eth1394.c
+++ b/drivers/ieee1394/eth1394.c
@@ -89,7 +89,7 @@
#define TRACE() printk(KERN_ERR "%s:%s[%d] ---- TRACE\n", driver_name, __FUNCTION__, __LINE__)
static char version[] __devinitdata =
- "$Rev: 1224 $ Ben Collins <bcollins@debian.org>";
+ "$Rev: 1247 $ Ben Collins <bcollins@debian.org>";
struct fragment_info {
struct list_head list;
@@ -165,8 +165,7 @@ MODULE_LICENSE("GPL");
/* The max_partial_datagrams parameter is the maximum number of fragmented
* datagrams per node that eth1394 will keep in memory. Providing an upper
* bound allows us to limit the amount of memory that partial datagrams
- * consume in the event that some partial datagrams are never completed. This
- * should probably change to a sysctl item or the like if possible.
+ * consume in the event that some partial datagrams are never completed.
*/
static int max_partial_datagrams = 25;
module_param(max_partial_datagrams, int, S_IRUGO | S_IWUSR);
@@ -186,7 +185,7 @@ static void ether1394_header_cache_update(struct hh_cache *hh,
unsigned char * haddr);
static int ether1394_mac_addr(struct net_device *dev, void *p);
-static inline void purge_partial_datagram(struct list_head *old);
+static void purge_partial_datagram(struct list_head *old);
static int ether1394_tx(struct sk_buff *skb, struct net_device *dev);
static void ether1394_iso(struct hpsb_iso *iso);
@@ -289,7 +288,7 @@ static int ether1394_change_mtu(struct net_device *dev, int new_mtu)
return 0;
}
-static inline void purge_partial_datagram(struct list_head *old)
+static void purge_partial_datagram(struct list_head *old)
{
struct partial_datagram *pd = list_entry(old, struct partial_datagram, list);
struct list_head *lh, *n;
@@ -449,7 +448,7 @@ static int eth1394_update(struct unit_directory *ud)
if (!node_info) {
kfree(node);
return -ENOMEM;
- }
+ }
spin_lock_init(&node_info->pdg.lock);
INIT_LIST_HEAD(&node_info->pdg.list);
@@ -626,7 +625,7 @@ static void ether1394_add_host (struct hpsb_host *host)
goto out;
}
- ETH1394_PRINT (KERN_ERR, dev->name, "IEEE-1394 IPv4 over 1394 Ethernet (fw-host%d)\n",
+ ETH1394_PRINT (KERN_INFO, dev->name, "IEEE-1394 IPv4 over 1394 Ethernet (fw-host%d)\n",
host->id);
hi->host = host;
@@ -1187,7 +1186,7 @@ static int ether1394_data_handler(struct net_device *dev, int srcid, int destid,
lh = find_partial_datagram(pdgl, dgl);
if (lh == NULL) {
- if (pdg->sz == max_partial_datagrams) {
+ while (pdg->sz >= max_partial_datagrams) {
/* remove the oldest */
purge_partial_datagram(pdgl->prev);
pdg->sz--;
@@ -1583,7 +1582,7 @@ static inline void ether1394_dg_complete(struct packet_task *ptask, int fail)
struct sk_buff *skb = ptask->skb;
struct net_device *dev = skb->dev;
struct eth1394_priv *priv = netdev_priv(dev);
- unsigned long flags;
+ unsigned long flags;
/* Statistics */
spin_lock_irqsave(&priv->lock, flags);
@@ -1771,7 +1770,7 @@ fail:
static void ether1394_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
{
strcpy (info->driver, driver_name);
- strcpy (info->version, "$Rev: 1224 $");
+ strcpy (info->version, "$Rev: 1247 $");
/* FIXME XXX provide sane businfo */
strcpy (info->bus_info, "ieee1394");
}
diff --git a/drivers/ieee1394/highlevel.c b/drivers/ieee1394/highlevel.c
index 24c1746c8b734..997e1bf6297f8 100644
--- a/drivers/ieee1394/highlevel.c
+++ b/drivers/ieee1394/highlevel.c
@@ -173,18 +173,6 @@ void hpsb_set_hostinfo_key(struct hpsb_highlevel *hl, struct hpsb_host *host, un
}
-unsigned long hpsb_get_hostinfo_key(struct hpsb_highlevel *hl, struct hpsb_host *host)
-{
- struct hl_host_info *hi;
-
- hi = hl_get_hostinfo(hl, host);
- if (hi)
- return hi->key;
-
- return 0;
-}
-
-
void *hpsb_get_hostinfo_bykey(struct hpsb_highlevel *hl, unsigned long key)
{
struct hl_host_info *hi;
@@ -206,26 +194,6 @@ void *hpsb_get_hostinfo_bykey(struct hpsb_highlevel *hl, unsigned long key)
}
-struct hpsb_host *hpsb_get_host_bykey(struct hpsb_highlevel *hl, unsigned long key)
-{
- struct hl_host_info *hi;
- struct hpsb_host *host = NULL;
-
- if (!hl)
- return NULL;
-
- read_lock(&hl->host_info_lock);
- list_for_each_entry(hi, &hl->host_info_list, list) {
- if (hi->key == key) {
- host = hi->host;
- break;
- }
- }
- read_unlock(&hl->host_info_lock);
-
- return host;
-}
-
static int highlevel_for_each_host_reg(struct hpsb_host *host, void *__data)
{
struct hpsb_highlevel *hl = __data;
@@ -416,7 +384,7 @@ int hpsb_register_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host,
}
as = (struct hpsb_address_serve *)
- kmalloc(sizeof(struct hpsb_address_serve), GFP_KERNEL);
+ kmalloc(sizeof(struct hpsb_address_serve), GFP_ATOMIC);
if (as == NULL) {
return 0;
}
diff --git a/drivers/ieee1394/ieee1394.h b/drivers/ieee1394/ieee1394.h
index 9834efc4edd45..b634a9bb365c9 100644
--- a/drivers/ieee1394/ieee1394.h
+++ b/drivers/ieee1394/ieee1394.h
@@ -77,6 +77,30 @@ extern const char *hpsb_speedto_str[];
#define SELFID_PORT_NONE 0x0
+/* 1394a PHY bitmasks */
+#define PHY_00_PHYSICAL_ID 0xFC
+#define PHY_00_R 0x02 /* Root */
+#define PHY_00_PS 0x01 /* Power Status*/
+#define PHY_01_RHB 0x80 /* Root Hold-Off */
+#define PHY_01_IBR 0x80 /* Initiate Bus Reset */
+#define PHY_01_GAP_COUNT 0x3F
+#define PHY_02_EXTENDED 0xE0 /* 0x7 for 1394a-compliant PHY */
+#define PHY_02_TOTAL_PORTS 0x1F
+#define PHY_03_MAX_SPEED 0xE0
+#define PHY_03_DELAY 0x0F
+#define PHY_04_LCTRL 0x80 /* Link Active Report Control */
+#define PHY_04_CONTENDER 0x40
+#define PHY_04_JITTER 0x38
+#define PHY_04_PWR_CLASS 0x07 /* Power Class */
+#define PHY_05_WATCHDOG 0x80
+#define PHY_05_ISBR 0x40 /* Initiate Short Bus Reset */
+#define PHY_05_LOOP 0x20 /* Loop Detect */
+#define PHY_05_PWR_FAIL 0x10 /* Cable Power Failure Detect */
+#define PHY_05_TIMEOUT 0x08 /* Arbitration State Machine Timeout */
+#define PHY_05_PORT_EVENT 0x04 /* Port Event Detect */
+#define PHY_05_ENAB_ACCEL 0x02 /* Enable Arbitration Acceleration */
+#define PHY_05_ENAB_MULTI 0x01 /* Ena. Multispeed Packet Concatenation */
+
#include <asm/byteorder.h>
#ifdef __BIG_ENDIAN_BITFIELD
diff --git a/drivers/ieee1394/ieee1394_core.c b/drivers/ieee1394/ieee1394_core.c
index 9a3c58654267d..1c5845f7e4ab3 100644
--- a/drivers/ieee1394/ieee1394_core.c
+++ b/drivers/ieee1394/ieee1394_core.c
@@ -56,11 +56,18 @@ static int disable_nodemgr = 0;
module_param(disable_nodemgr, int, 0444);
MODULE_PARM_DESC(disable_nodemgr, "Disable nodemgr functionality.");
+/* Disable Isochronous Resource Manager functionality */
+int hpsb_disable_irm = 0;
+module_param_named(disable_irm, hpsb_disable_irm, bool, 0);
+MODULE_PARM_DESC(disable_irm,
+ "Disable Isochronous Resource Manager functionality.");
+
/* We are GPL, so treat us special */
MODULE_LICENSE("GPL");
/* Some globals used */
const char *hpsb_speedto_str[] = { "S100", "S200", "S400", "S800", "S1600", "S3200" };
+struct class_simple *hpsb_protocol_class;
#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
static void dump_packet(const char *text, quadlet_t *data, int size)
@@ -79,6 +86,7 @@ static void dump_packet(const char *text, quadlet_t *data, int size)
#define dump_packet(x,y,z)
#endif
+static void abort_requests(struct hpsb_host *host);
static void queue_packet_complete(struct hpsb_packet *packet);
@@ -512,6 +520,7 @@ int hpsb_send_packet(struct hpsb_packet *packet)
if (!packet->no_waiter || packet->expect_response) {
atomic_inc(&packet->refcnt);
+ packet->sendtime = jiffies;
skb_queue_tail(&host->pending_packet_queue, packet->skb);
}
@@ -939,7 +948,7 @@ void hpsb_packet_received(struct hpsb_host *host, quadlet_t *data, size_t size,
}
-void abort_requests(struct hpsb_host *host)
+static void abort_requests(struct hpsb_host *host)
{
struct hpsb_packet *packet;
struct sk_buff *skb;
@@ -1002,7 +1011,7 @@ void abort_timedouts(unsigned long __opaque)
* the stack. */
static int khpsbpkt_pid = -1, khpsbpkt_kill;
static DECLARE_COMPLETION(khpsbpkt_complete);
-struct sk_buff_head hpsbpkt_queue;
+static struct sk_buff_head hpsbpkt_queue;
static DECLARE_MUTEX_LOCKED(khpsbpkt_sig);
@@ -1030,15 +1039,19 @@ static int hpsbpkt_thread(void *__hi)
daemonize("khpsbpkt");
- while (!down_interruptible(&khpsbpkt_sig)) {
- if (khpsbpkt_kill)
+ while (1) {
+ if (down_interruptible(&khpsbpkt_sig)) {
+ if (current->flags & PF_FREEZE) {
+ refrigerator(0);
+ continue;
+ }
+ printk("khpsbpkt: received unexpected signal?!\n" );
break;
-
- if (current->flags & PF_FREEZE) {
- refrigerator(0);
- continue;
}
+ if (khpsbpkt_kill)
+ break;
+
while ((skb = skb_dequeue(&hpsbpkt_queue)) != NULL) {
packet = (struct hpsb_packet *)skb->data;
@@ -1054,7 +1067,6 @@ static int hpsbpkt_thread(void *__hi)
complete_and_exit(&khpsbpkt_complete, 0);
}
-
static int __init ieee1394_init(void)
{
int i, ret;
@@ -1109,18 +1121,33 @@ static int __init ieee1394_init(void)
if (ret < 0)
goto release_all_bus;
+ hpsb_protocol_class = class_simple_create(THIS_MODULE, "ieee1394_protocol");
+ if (IS_ERR(hpsb_protocol_class)) {
+ ret = PTR_ERR(hpsb_protocol_class);
+ goto release_class_host;
+ }
+
ret = init_csr();
if (ret) {
HPSB_INFO("init csr failed");
ret = -ENOMEM;
- goto release_class;
+ goto release_class_protocol;
}
if (disable_nodemgr) {
- HPSB_INFO("nodemgr functionality disabled");
+ HPSB_INFO("nodemgr and IRM functionality disabled");
+ /* We shouldn't contend for IRM with nodemgr disabled, since
+ nodemgr implements functionality required of ieee1394a-2000
+ IRMs */
+ hpsb_disable_irm = 1;
+
return 0;
}
+ if (hpsb_disable_irm) {
+ HPSB_INFO("IRM functionality disabled");
+ }
+
ret = init_ieee1394_nodemgr();
if (ret < 0) {
HPSB_INFO("init nodemgr failed");
@@ -1131,7 +1158,9 @@ static int __init ieee1394_init(void)
cleanup_csr:
cleanup_csr();
-release_class:
+release_class_protocol:
+ class_simple_destroy(hpsb_protocol_class);
+release_class_host:
class_unregister(&hpsb_host_class);
release_all_bus:
for (i = 0; fw_bus_attrs[i]; i++)
@@ -1160,6 +1189,7 @@ static void __exit ieee1394_cleanup(void)
cleanup_csr();
+ class_simple_destroy(hpsb_protocol_class);
class_unregister(&hpsb_host_class);
for (i = 0; fw_bus_attrs[i]; i++)
bus_remove_file(&ieee1394_bus_type, fw_bus_attrs[i]);
@@ -1191,6 +1221,7 @@ EXPORT_SYMBOL(hpsb_update_config_rom_image);
/** ieee1394_core.c **/
EXPORT_SYMBOL(hpsb_speedto_str);
+EXPORT_SYMBOL(hpsb_protocol_class);
EXPORT_SYMBOL(hpsb_set_packet_complete_task);
EXPORT_SYMBOL(hpsb_alloc_packet);
EXPORT_SYMBOL(hpsb_free_packet);
@@ -1203,6 +1234,7 @@ EXPORT_SYMBOL(hpsb_selfid_received);
EXPORT_SYMBOL(hpsb_selfid_complete);
EXPORT_SYMBOL(hpsb_packet_sent);
EXPORT_SYMBOL(hpsb_packet_received);
+EXPORT_SYMBOL_GPL(hpsb_disable_irm);
/** ieee1394_transactions.c **/
EXPORT_SYMBOL(hpsb_get_tlabel);
@@ -1217,8 +1249,6 @@ EXPORT_SYMBOL(hpsb_make_isopacket);
EXPORT_SYMBOL(hpsb_read);
EXPORT_SYMBOL(hpsb_write);
EXPORT_SYMBOL(hpsb_lock);
-EXPORT_SYMBOL(hpsb_lock64);
-EXPORT_SYMBOL(hpsb_send_gasp);
EXPORT_SYMBOL(hpsb_packet_success);
/** highlevel.c **/
@@ -1230,28 +1260,18 @@ EXPORT_SYMBOL(hpsb_allocate_and_register_addrspace);
EXPORT_SYMBOL(hpsb_listen_channel);
EXPORT_SYMBOL(hpsb_unlisten_channel);
EXPORT_SYMBOL(hpsb_get_hostinfo);
-EXPORT_SYMBOL(hpsb_get_host_bykey);
EXPORT_SYMBOL(hpsb_create_hostinfo);
EXPORT_SYMBOL(hpsb_destroy_hostinfo);
EXPORT_SYMBOL(hpsb_set_hostinfo_key);
-EXPORT_SYMBOL(hpsb_get_hostinfo_key);
EXPORT_SYMBOL(hpsb_get_hostinfo_bykey);
EXPORT_SYMBOL(hpsb_set_hostinfo);
-EXPORT_SYMBOL(highlevel_read);
-EXPORT_SYMBOL(highlevel_write);
-EXPORT_SYMBOL(highlevel_lock);
-EXPORT_SYMBOL(highlevel_lock64);
EXPORT_SYMBOL(highlevel_add_host);
EXPORT_SYMBOL(highlevel_remove_host);
EXPORT_SYMBOL(highlevel_host_reset);
/** nodemgr.c **/
-EXPORT_SYMBOL(hpsb_guid_get_entry);
-EXPORT_SYMBOL(hpsb_nodeid_get_entry);
EXPORT_SYMBOL(hpsb_node_fill_packet);
-EXPORT_SYMBOL(hpsb_node_read);
EXPORT_SYMBOL(hpsb_node_write);
-EXPORT_SYMBOL(hpsb_node_lock);
EXPORT_SYMBOL(hpsb_register_protocol);
EXPORT_SYMBOL(hpsb_unregister_protocol);
EXPORT_SYMBOL(ieee1394_bus_type);
@@ -1295,27 +1315,14 @@ EXPORT_SYMBOL(hpsb_iso_recv_flush);
EXPORT_SYMBOL(csr1212_create_csr);
EXPORT_SYMBOL(csr1212_init_local_csr);
EXPORT_SYMBOL(csr1212_new_immediate);
-EXPORT_SYMBOL(csr1212_new_leaf);
-EXPORT_SYMBOL(csr1212_new_csr_offset);
EXPORT_SYMBOL(csr1212_new_directory);
EXPORT_SYMBOL(csr1212_associate_keyval);
EXPORT_SYMBOL(csr1212_attach_keyval_to_directory);
-EXPORT_SYMBOL(csr1212_new_extended_immediate);
-EXPORT_SYMBOL(csr1212_new_extended_leaf);
-EXPORT_SYMBOL(csr1212_new_descriptor_leaf);
-EXPORT_SYMBOL(csr1212_new_textual_descriptor_leaf);
EXPORT_SYMBOL(csr1212_new_string_descriptor_leaf);
-EXPORT_SYMBOL(csr1212_new_icon_descriptor_leaf);
-EXPORT_SYMBOL(csr1212_new_modifiable_descriptor_leaf);
-EXPORT_SYMBOL(csr1212_new_keyword_leaf);
EXPORT_SYMBOL(csr1212_detach_keyval_from_directory);
-EXPORT_SYMBOL(csr1212_disassociate_keyval);
EXPORT_SYMBOL(csr1212_release_keyval);
EXPORT_SYMBOL(csr1212_destroy_csr);
EXPORT_SYMBOL(csr1212_read);
-EXPORT_SYMBOL(csr1212_generate_positions);
-EXPORT_SYMBOL(csr1212_generate_layout_order);
-EXPORT_SYMBOL(csr1212_fill_cache);
EXPORT_SYMBOL(csr1212_generate_csr_image);
EXPORT_SYMBOL(csr1212_parse_keyval);
EXPORT_SYMBOL(csr1212_parse_csr);
diff --git a/drivers/ieee1394/ieee1394_core.h b/drivers/ieee1394/ieee1394_core.h
index 8e4b62c23bd3f..c4b4408e2e050 100644
--- a/drivers/ieee1394/ieee1394_core.h
+++ b/drivers/ieee1394/ieee1394_core.h
@@ -89,7 +89,6 @@ static inline struct hpsb_packet *driver_packet(struct list_head *l)
}
void abort_timedouts(unsigned long __opaque);
-void abort_requests(struct hpsb_host *host);
struct hpsb_packet *hpsb_alloc_packet(size_t data_size);
void hpsb_free_packet(struct hpsb_packet *packet);
@@ -219,9 +218,11 @@ static inline unsigned char ieee1394_file_to_instance(struct file *file)
return file->f_dentry->d_inode->i_cindex;
}
+extern int hpsb_disable_irm;
/* Our sysfs bus entry */
extern struct bus_type ieee1394_bus_type;
extern struct class hpsb_host_class;
+extern struct class_simple *hpsb_protocol_class;
#endif /* _IEEE1394_CORE_H */
diff --git a/drivers/ieee1394/ieee1394_transactions.c b/drivers/ieee1394/ieee1394_transactions.c
index 60da23ba33ad0..09908b9564d8b 100644
--- a/drivers/ieee1394/ieee1394_transactions.c
+++ b/drivers/ieee1394/ieee1394_transactions.c
@@ -566,34 +566,6 @@ hpsb_lock_fail:
return retval;
}
-int hpsb_lock64(struct hpsb_host *host, nodeid_t node, unsigned int generation,
- u64 addr, int extcode, octlet_t *data, octlet_t arg)
-{
- struct hpsb_packet *packet;
- int retval = 0;
-
- BUG_ON(in_interrupt()); // We can't be called in an interrupt, yet
-
- packet = hpsb_make_lock64packet(host, node, addr, extcode, data, arg);
- if (!packet)
- return -ENOMEM;
-
- packet->generation = generation;
- retval = hpsb_send_packet_and_wait(packet);
- if (retval < 0)
- goto hpsb_lock64_fail;
-
- retval = hpsb_packet_success(packet);
-
- if (retval == 0)
- *data = (u64)packet->data[1] << 32 | packet->data[0];
-
-hpsb_lock64_fail:
- hpsb_free_tlabel(packet);
- hpsb_free_packet(packet);
-
- return retval;
-}
int hpsb_send_gasp(struct hpsb_host *host, int channel, unsigned int generation,
quadlet_t *buffer, size_t length, u32 specifier_id,
diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c
index 21472e9bdfa67..a1e30a66297bc 100644
--- a/drivers/ieee1394/nodemgr.c
+++ b/drivers/ieee1394/nodemgr.c
@@ -23,6 +23,7 @@
#include "ieee1394_types.h"
#include "ieee1394.h"
+#include "ieee1394_core.h"
#include "hosts.h"
#include "ieee1394_transactions.h"
#include "highlevel.h"
@@ -146,7 +147,7 @@ static void ne_cls_release(struct class_device *class_dev)
put_device(&container_of((class_dev), struct node_entry, class_dev)->device);
}
-struct class nodemgr_ne_class = {
+static struct class nodemgr_ne_class = {
.name = "ieee1394_node",
.release = ne_cls_release,
};
@@ -158,7 +159,7 @@ static void ud_cls_release(struct class_device *class_dev)
/* The name here is only so that unit directory hotplug works with old
* style hotplug, which only ever did unit directories anyway. */
-struct class nodemgr_ud_class = {
+static struct class nodemgr_ud_class = {
.name = "ieee1394",
.release = ud_cls_release,
.hotplug = nodemgr_hotplug,
@@ -831,6 +832,31 @@ static struct node_entry *find_entry_by_nodeid(struct hpsb_host *host, nodeid_t
}
+static void nodemgr_register_device(struct node_entry *ne,
+ struct unit_directory *ud, struct device *parent)
+{
+ memcpy(&ud->device, &nodemgr_dev_template_ud,
+ sizeof(ud->device));
+
+ ud->device.parent = parent;
+
+ snprintf(ud->device.bus_id, BUS_ID_SIZE, "%s-%u",
+ ne->device.bus_id, ud->id);
+
+ ud->class_dev.dev = &ud->device;
+ ud->class_dev.class = &nodemgr_ud_class;
+ snprintf(ud->class_dev.class_id, BUS_ID_SIZE, "%s-%u",
+ ne->device.bus_id, ud->id);
+
+ device_register(&ud->device);
+ class_device_register(&ud->class_dev);
+ get_device(&ud->device);
+
+ if (ud->vendor_oui)
+ device_create_file(&ud->device, &dev_attr_ud_vendor_oui);
+ nodemgr_create_ud_dev_files(ud);
+}
+
/* This implementation currently only scans the config rom and its
* immediate unit directories looking for software_id and
@@ -840,7 +866,7 @@ static struct unit_directory *nodemgr_process_unit_directory
unsigned int *id, struct unit_directory *parent)
{
struct unit_directory *ud;
- struct unit_directory *ud_temp = NULL;
+ struct unit_directory *ud_child = NULL;
struct csr1212_dentry *dentry;
struct csr1212_keyval *kv;
u8 last_key_id = 0;
@@ -907,42 +933,61 @@ static struct unit_directory *nodemgr_process_unit_directory
break;
case CSR1212_KV_ID_DEPENDENT_INFO:
- if (kv->key.type == CSR1212_KV_TYPE_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);
+ if (!ud_child)
+ goto unit_directory_error;
+ memcpy(ud_child, ud, sizeof(struct unit_directory));
+ nodemgr_register_device(ne, ud_child, &ne->device);
+ ud_child = NULL;
+
+ ud->id = (*id)++;
+ }
+ ud->lun = kv->value.immediate;
+ ud->flags |= UNIT_DIRECTORY_HAS_LUN;
+
+ /* Logical Unit Directory */
+ } else if (kv->key.type == CSR1212_KV_TYPE_DIRECTORY) {
/* This should really be done in SBP2 as this is
- * doing SBP2 specific parsing. */
+ * doing SBP2 specific parsing.
+ */
+
+ /* first register the parent unit */
ud->flags |= UNIT_DIRECTORY_HAS_LUN_DIRECTORY;
- ud_temp = nodemgr_process_unit_directory(hi, ne, kv, id,
- parent);
+ if (ud->device.bus != &ieee1394_bus_type)
+ nodemgr_register_device(ne, ud, &ne->device);
+
+ /* process the child unit */
+ ud_child = nodemgr_process_unit_directory(hi, ne, kv, id, ud);
- if (ud_temp == NULL)
+ if (ud_child == NULL)
break;
-
- /* inherit unspecified values */
- if ((ud->flags & UNIT_DIRECTORY_VENDOR_ID) &&
- !(ud_temp->flags & UNIT_DIRECTORY_VENDOR_ID))
- {
- ud_temp->flags |= UNIT_DIRECTORY_VENDOR_ID;
- ud_temp->vendor_id = ud->vendor_id;
- ud_temp->vendor_oui = ud->vendor_oui;
- }
+
+ /* inherit unspecified values so hotplug picks it up */
if ((ud->flags & UNIT_DIRECTORY_MODEL_ID) &&
- !(ud_temp->flags & UNIT_DIRECTORY_MODEL_ID))
+ !(ud_child->flags & UNIT_DIRECTORY_MODEL_ID))
{
- ud_temp->flags |= UNIT_DIRECTORY_MODEL_ID;
- ud_temp->model_id = ud->model_id;
+ ud_child->flags |= UNIT_DIRECTORY_MODEL_ID;
+ ud_child->model_id = ud->model_id;
}
if ((ud->flags & UNIT_DIRECTORY_SPECIFIER_ID) &&
- !(ud_temp->flags & UNIT_DIRECTORY_SPECIFIER_ID))
+ !(ud_child->flags & UNIT_DIRECTORY_SPECIFIER_ID))
{
- ud_temp->flags |= UNIT_DIRECTORY_SPECIFIER_ID;
- ud_temp->specifier_id = ud->specifier_id;
+ ud_child->flags |= UNIT_DIRECTORY_SPECIFIER_ID;
+ ud_child->specifier_id = ud->specifier_id;
}
if ((ud->flags & UNIT_DIRECTORY_VERSION) &&
- !(ud_temp->flags & UNIT_DIRECTORY_VERSION))
+ !(ud_child->flags & UNIT_DIRECTORY_VERSION))
{
- ud_temp->flags |= UNIT_DIRECTORY_VERSION;
- ud_temp->version = ud->version;
+ ud_child->flags |= UNIT_DIRECTORY_VERSION;
+ ud_child->version = ud->version;
}
+
+ /* register the child unit */
+ ud_child->flags |= UNIT_DIRECTORY_LUN_DIRECTORY;
+ nodemgr_register_device(ne, ud_child, &ud->device);
}
break;
@@ -952,31 +997,10 @@ static struct unit_directory *nodemgr_process_unit_directory
}
last_key_id = kv->key.id;
}
-
- memcpy(&ud->device, &nodemgr_dev_template_ud,
- sizeof(ud->device));
-
- if (parent) {
- ud->flags |= UNIT_DIRECTORY_LUN_DIRECTORY;
- ud->device.parent = &parent->device;
- } else
- ud->device.parent = &ne->device;
-
- snprintf(ud->device.bus_id, BUS_ID_SIZE, "%s-%u",
- ne->device.bus_id, ud->id);
-
- ud->class_dev.dev = &ud->device;
- ud->class_dev.class = &nodemgr_ud_class;
- snprintf(ud->class_dev.class_id, BUS_ID_SIZE, "%s-%u",
- ne->device.bus_id, ud->id);
-
- device_register(&ud->device);
- class_device_register(&ud->class_dev);
- get_device(&ud->device);
-
- if (ud->vendor_oui)
- device_create_file(&ud->device, &dev_attr_ud_vendor_oui);
- nodemgr_create_ud_dev_files(ud);
+
+ /* do not process child units here and only if not already registered */
+ if (!parent && ud->device.bus != &ieee1394_bus_type)
+ nodemgr_register_device(ne, ud, &ne->device);
return ud;
@@ -1141,6 +1165,13 @@ static void nodemgr_update_node(struct node_entry *ne, struct csr1212_csr *csr,
/* Mark the node as new, so it gets re-probed */
ne->needs_probe = 1;
+ } else {
+ /* old cache is valid, so update its generation */
+ struct nodemgr_csr_info *ci = ne->csr->private;
+ ci->generation = generation;
+ /* free the partially filled now unneeded new cache */
+ kfree(csr->private);
+ csr1212_destroy_csr(csr);
}
if (ne->in_limbo)
@@ -1253,7 +1284,7 @@ static void nodemgr_suspend_ne(struct node_entry *ne)
if (ud->device.driver &&
(!ud->device.driver->suspend ||
- ud->device.driver->suspend(&ud->device, 0, 0)))
+ ud->device.driver->suspend(&ud->device, PMSG_SUSPEND, 0)))
device_release_driver(&ud->device);
}
up_write(&ne->device.bus->subsys.rwsem);
@@ -1431,7 +1462,7 @@ static int nodemgr_check_irm_capability(struct hpsb_host *host, int cycles)
quadlet_t bc;
int status;
- if (host->is_irm)
+ if (hpsb_disable_irm || host->is_irm)
return 1;
status = hpsb_read(host, LOCAL_BUS | (host->irm_id),
@@ -1553,29 +1584,6 @@ caught_signal:
complete_and_exit(&hi->exited, 0);
}
-struct node_entry *hpsb_guid_get_entry(u64 guid)
-{
- struct node_entry *ne;
-
- down(&nodemgr_serialize);
- ne = find_entry_by_guid(guid);
- up(&nodemgr_serialize);
-
- return ne;
-}
-
-struct node_entry *hpsb_nodeid_get_entry(struct hpsb_host *host, nodeid_t nodeid)
-{
- struct node_entry *ne;
-
- down(&nodemgr_serialize);
- ne = find_entry_by_nodeid(host, nodeid);
- up(&nodemgr_serialize);
-
- return ne;
-}
-
-
int nodemgr_for_each_host(void *__data, int (*cb)(struct hpsb_host *, void *))
{
struct class *class = &hpsb_host_class;
@@ -1618,16 +1626,6 @@ void hpsb_node_fill_packet(struct node_entry *ne, struct hpsb_packet *pkt)
pkt->node_id = ne->nodeid;
}
-int hpsb_node_read(struct node_entry *ne, u64 addr,
- quadlet_t *buffer, size_t length)
-{
- unsigned int generation = ne->generation;
-
- barrier();
- return hpsb_read(ne->host, ne->nodeid, generation,
- addr, buffer, length);
-}
-
int hpsb_node_write(struct node_entry *ne, u64 addr,
quadlet_t *buffer, size_t length)
{
@@ -1638,16 +1636,6 @@ int hpsb_node_write(struct node_entry *ne, u64 addr,
addr, buffer, length);
}
-int hpsb_node_lock(struct node_entry *ne, u64 addr,
- int extcode, quadlet_t *data, quadlet_t arg)
-{
- unsigned int generation = ne->generation;
-
- barrier();
- return hpsb_lock(ne->host, ne->nodeid, generation,
- addr, extcode, data, arg);
-}
-
static void nodemgr_add_host(struct hpsb_host *host)
{
struct host_info *hi;
diff --git a/drivers/ieee1394/nodemgr.h b/drivers/ieee1394/nodemgr.h
index f27ea3a257509..3a2f0c02fd081 100644
--- a/drivers/ieee1394/nodemgr.h
+++ b/drivers/ieee1394/nodemgr.h
@@ -51,6 +51,7 @@ struct bus_options {
#define UNIT_DIRECTORY_VERSION 0x08
#define UNIT_DIRECTORY_HAS_LUN_DIRECTORY 0x10
#define UNIT_DIRECTORY_LUN_DIRECTORY 0x20
+#define UNIT_DIRECTORY_HAS_LUN 0x40
/*
* A unit directory corresponds to a protocol supported by the
@@ -82,6 +83,7 @@ struct unit_directory {
struct class_device class_dev;
struct csr1212_keyval *ud_kv;
+ u32 lun; /* logical unit number immediate value */
};
struct node_entry {
diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c
index 7c3f6e7bcdf70..97ff364c04341 100644
--- a/drivers/ieee1394/ohci1394.c
+++ b/drivers/ieee1394/ohci1394.c
@@ -162,7 +162,7 @@ printk(level "%s: " fmt "\n" , OHCI1394_DRIVER_NAME , ## args)
printk(level "%s: fw-host%d: " fmt "\n" , OHCI1394_DRIVER_NAME, ohci->host->id , ## args)
static char version[] __devinitdata =
- "$Rev: 1223 $ Ben Collins <bcollins@debian.org>";
+ "$Rev: 1250 $ Ben Collins <bcollins@debian.org>";
/* Module Parameters */
static int phys_dma = 1;
@@ -482,7 +482,9 @@ static void ohci_initialize(struct ti_ohci *ohci)
/* Put some defaults to these undefined bus options */
buf = reg_read(ohci, OHCI1394_BusOptions);
- buf |= 0xE0000000; /* Enable IRMC, CMC and ISC */
+ buf |= 0x60000000; /* Enable CMC and ISC */
+ if (!hpsb_disable_irm)
+ buf |= 0x80000000; /* Enable IRMC */
buf &= ~0x00ff0000; /* XXX: Set cyc_clk_acc to zero for now */
buf &= ~0x18000000; /* Disable PMC and BMC */
reg_write(ohci, OHCI1394_BusOptions, buf);
@@ -497,10 +499,12 @@ static void ohci_initialize(struct ti_ohci *ohci)
reg_write(ohci, OHCI1394_LinkControlClear, 0xffffffff);
/* Enable cycle timer and cycle master and set the IRM
- * contender bit in our self ID packets. */
- reg_write(ohci, OHCI1394_LinkControlSet, OHCI1394_LinkControl_CycleTimerEnable |
+ * contender bit in our self ID packets if appropriate. */
+ reg_write(ohci, OHCI1394_LinkControlSet,
+ OHCI1394_LinkControl_CycleTimerEnable |
OHCI1394_LinkControl_CycleMaster);
- set_phy_reg_mask(ohci, 4, 0xc0);
+ set_phy_reg_mask(ohci, 4, PHY_04_LCTRL |
+ (hpsb_disable_irm ? 0 : PHY_04_CONTENDER));
/* Set up self-id dma buffer */
reg_write(ohci, OHCI1394_SelfIDBuffer, ohci->selfid_buf_bus);
@@ -515,12 +519,6 @@ static void ohci_initialize(struct ti_ohci *ohci)
/* Now get our max packet size */
ohci->max_packet_size =
1<<(((reg_read(ohci, OHCI1394_BusOptions)>>12)&0xf)+1);
-
- if (ohci->max_packet_size < 512) {
- HPSB_ERR("warning: Invalid max packet size of %d, setting to 512",
- ohci->max_packet_size);
- ohci->max_packet_size = 512;
- }
/* Don't accept phy packets into AR request context */
reg_write(ohci, OHCI1394_LinkControlClear, 0x00000400);
@@ -540,6 +538,11 @@ static void ohci_initialize(struct ti_ohci *ohci)
/* Initialize AT dma */
initialize_dma_trm_ctx(&ohci->at_req_context);
initialize_dma_trm_ctx(&ohci->at_resp_context);
+
+ /* Initialize IR Legacy DMA */
+ ohci->ir_legacy_channels = 0;
+ initialize_dma_rcv_ctx(&ohci->ir_legacy_context, 1);
+ DBGMSG("ISO receive legacy context activated");
/*
* Accept AT requests from all nodes. This probably
@@ -1037,22 +1040,6 @@ static int ohci_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg)
return -EFAULT;
}
- /* activate the legacy IR context */
- if (ohci->ir_legacy_context.ohci == NULL) {
- if (alloc_dma_rcv_ctx(ohci, &ohci->ir_legacy_context,
- DMA_CTX_ISO, 0, IR_NUM_DESC,
- IR_BUF_SIZE, IR_SPLIT_BUF_SIZE,
- OHCI1394_IsoRcvContextBase) < 0) {
- PRINT(KERN_ERR, "%s: failed to allocate an IR context",
- __FUNCTION__);
- return -ENOMEM;
- }
- ohci->ir_legacy_channels = 0;
- initialize_dma_rcv_ctx(&ohci->ir_legacy_context, 1);
-
- DBGMSG("ISO receive legacy context activated");
- }
-
mask = (u64)0x1<<arg;
spin_lock_irqsave(&ohci->IR_channel_lock, flags);
@@ -1114,12 +1101,6 @@ static int ohci_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg)
spin_unlock_irqrestore(&ohci->IR_channel_lock, flags);
DBGMSG("Listening disabled on channel %d", arg);
-
- if (ohci->ir_legacy_channels == 0) {
- stop_dma_rcv_ctx(&ohci->ir_legacy_context);
- free_dma_rcv_ctx(&ohci->ir_legacy_context);
- DBGMSG("ISO receive legacy context deactivated");
- }
break;
}
default:
@@ -2545,6 +2526,10 @@ static void insert_dma_buffer(struct dma_rcv_ctx *d, int idx)
idx = (idx + d->num_desc - 1 ) % d->num_desc;
d->prg_cpu[idx]->branchAddress |= le32_to_cpu(0x00000001);
+ /* To avoid a race, ensure 1394 interface hardware sees the inserted
+ * context program descriptors before it sees the wakeup bit set. */
+ wmb();
+
/* wake up the dma context if necessary */
if (!(reg_read(ohci, d->ctrlSet) & 0x400)) {
PRINT(KERN_INFO,
@@ -2919,7 +2904,9 @@ alloc_dma_rcv_ctx(struct ti_ohci *ohci, struct dma_rcv_ctx *d,
enum context_type type, int ctx, int num_desc,
int buf_size, int split_buf_size, int context_base)
{
- int i;
+ int i, len;
+ static int num_allocs;
+ static char pool_name[20];
d->ohci = ohci;
d->type = type;
@@ -2963,9 +2950,19 @@ alloc_dma_rcv_ctx(struct ti_ohci *ohci, struct dma_rcv_ctx *d,
free_dma_rcv_ctx(d);
return -ENOMEM;
}
-
- d->prg_pool = pci_pool_create("ohci1394 rcv prg", ohci->dev,
+
+ len = sprintf(pool_name, "ohci1394_rcv_prg");
+ sprintf(pool_name+len, "%d", num_allocs);
+ d->prg_pool = pci_pool_create(pool_name, ohci->dev,
sizeof(struct dma_cmd), 4, 0);
+ if(d->prg_pool == NULL)
+ {
+ PRINT(KERN_ERR, "pci_pool_create failed for %s", pool_name);
+ free_dma_rcv_ctx(d);
+ return -ENOMEM;
+ }
+ num_allocs++;
+
OHCI_DMA_ALLOC("dma_rcv prg pool");
for (i=0; i<d->num_desc; i++) {
@@ -3058,7 +3055,9 @@ alloc_dma_trm_ctx(struct ti_ohci *ohci, struct dma_trm_ctx *d,
enum context_type type, int ctx, int num_desc,
int context_base)
{
- int i;
+ int i, len;
+ static char pool_name[20];
+ static int num_allocs=0;
d->ohci = ohci;
d->type = type;
@@ -3080,8 +3079,17 @@ alloc_dma_trm_ctx(struct ti_ohci *ohci, struct dma_trm_ctx *d,
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));
- d->prg_pool = pci_pool_create("ohci1394 trm prg", ohci->dev,
+ len = sprintf(pool_name, "ohci1394_trm_prg");
+ sprintf(pool_name+len, "%d", num_allocs);
+ d->prg_pool = pci_pool_create(pool_name, ohci->dev,
sizeof(struct at_dma_prg), 4, 0);
+ if (d->prg_pool == NULL) {
+ PRINT(KERN_ERR, "pci_pool_create failed for %s", pool_name);
+ free_dma_trm_ctx(d);
+ return -ENOMEM;
+ }
+ num_allocs++;
+
OHCI_DMA_ALLOC("dma_rcv prg pool");
for (i = 0; i < d->num_desc; i++) {
@@ -3353,10 +3361,19 @@ static int __devinit ohci1394_pci_probe(struct pci_dev *dev,
ohci->ISO_channel_usage = 0;
spin_lock_init(&ohci->IR_channel_lock);
- /* the IR DMA context is allocated on-demand; mark it inactive */
- ohci->ir_legacy_context.ohci = NULL;
+ /* Allocate the IR DMA context right here so we don't have
+ * to do it in interrupt path - note that this doesn't
+ * waste much memory and avoids the jugglery required to
+ * allocate it in IRQ path. */
+ if (alloc_dma_rcv_ctx(ohci, &ohci->ir_legacy_context,
+ DMA_CTX_ISO, 0, IR_NUM_DESC,
+ IR_BUF_SIZE, IR_SPLIT_BUF_SIZE,
+ OHCI1394_IsoRcvContextBase) < 0) {
+ FAIL(-ENOMEM, "Cannot allocate IR Legacy DMA context");
+ }
- /* same for the IT DMA context */
+ /* We hopefully don't have to pre-allocate IT DMA like we did
+ * for IR DMA above. Allocate it on-demand and mark inactive. */
ohci->it_legacy_context.ohci = NULL;
if (request_irq(dev->irq, ohci_irq_handler, SA_SHIRQ,
@@ -3396,6 +3413,7 @@ static void ohci1394_pci_remove(struct pci_dev *pdev)
switch (ohci->init_state) {
case OHCI_INIT_DONE:
+ stop_dma_rcv_ctx(&ohci->ir_legacy_context);
hpsb_remove_host(ohci->host);
/* Clear out BUS Options */
@@ -3445,6 +3463,10 @@ static void ohci1394_pci_remove(struct pci_dev *pdev)
/* Free IT dma */
free_dma_trm_ctx(&ohci->it_legacy_context);
+ /* Free IR legacy dma */
+ free_dma_rcv_ctx(&ohci->ir_legacy_context);
+
+
case OHCI_INIT_HAVE_SELFID_BUFFER:
pci_free_consistent(ohci->dev, OHCI1394_SI_DMA_BUF_SIZE,
ohci->selfid_buf_cpu,
@@ -3510,7 +3532,7 @@ static int ohci1394_pci_resume (struct pci_dev *pdev)
}
-static int ohci1394_pci_suspend (struct pci_dev *pdev, u32 state)
+static int ohci1394_pci_suspend (struct pci_dev *pdev, pm_message_t state)
{
#ifdef CONFIG_PMAC_PBOOK
{
@@ -3676,7 +3698,7 @@ static void __exit ohci1394_cleanup (void)
static int __init ohci1394_init(void)
{
- return pci_module_init(&ohci1394_pci_driver);
+ return pci_register_driver(&ohci1394_pci_driver);
}
module_init(ohci1394_init);
diff --git a/drivers/ieee1394/pcilynx.c b/drivers/ieee1394/pcilynx.c
index 4bd76bf7d479a..a261d2b0e5ac7 100644
--- a/drivers/ieee1394/pcilynx.c
+++ b/drivers/ieee1394/pcilynx.c
@@ -1,5 +1,5 @@
/*
- * ti_pcilynx.c - Texas Instruments PCILynx driver
+ * pcilynx.c - Texas Instruments PCILynx driver
* Copyright (C) 1999,2000 Andreas Bombe <andreas.bombe@munich.netsurf.de>,
* Stephan Linz <linz@mazet.de>
* Manfred Weihs <weihs@ict.tuwien.ac.at>
@@ -384,7 +384,8 @@ static quadlet_t generate_own_selfid(struct ti_lynx *lynx,
lsid = 0x80400000 | ((phyreg[0] & 0xfc) << 22);
lsid |= (phyreg[1] & 0x3f) << 16; /* gap count */
lsid |= (phyreg[2] & 0xc0) << 8; /* max speed */
- lsid |= (phyreg[6] & 0x01) << 11; /* contender (phy dependent) */
+ if (!hpsb_disable_irm)
+ lsid |= (phyreg[6] & 0x01) << 11; /* contender (phy dependent) */
/* lsid |= 1 << 11; *//* set contender (hack) */
lsid |= (phyreg[6] & 0x10) >> 3; /* initiated reset */
@@ -500,7 +501,7 @@ static void send_next(struct ti_lynx *lynx, int what)
pcl.async_error_next = PCL_NEXT_INVALID;
pcl.pcl_status = 0;
pcl.buffer[0].control = packet->speed_code << 14 | packet->header_size;
-#ifdef __BIG_ENDIAN
+#ifndef __BIG_ENDIAN
pcl.buffer[0].control |= PCL_BIGENDIAN;
#endif
pcl.buffer[0].pointer = d->header_dma;
@@ -1521,10 +1522,6 @@ static int __devinit add_card(struct pci_dev *dev,
int i;
int error;
- /* needed for i2c communication with serial eeprom */
- struct i2c_adapter i2c_adapter;
- struct i2c_algo_bit_data i2c_adapter_data;
-
error = -ENXIO;
if (pci_set_dma_mask(dev, 0xffffffff))
@@ -1697,7 +1694,7 @@ static int __devinit add_card(struct pci_dev *dev,
pcl.async_error_next = PCL_NEXT_INVALID;
pcl.buffer[0].control = PCL_CMD_RCV | 16;
-#ifdef __BIG_ENDIAN
+#ifndef __BIG_ENDIAN
pcl.buffer[0].control |= PCL_BIGENDIAN;
#endif
pcl.buffer[1].control = PCL_LAST_BUFF | 4080;
@@ -1779,26 +1776,40 @@ static int __devinit add_card(struct pci_dev *dev,
| LINK_CONTROL_TX_ASYNC_EN | LINK_CONTROL_RX_ASYNC_EN
| LINK_CONTROL_RESET_TX | LINK_CONTROL_RESET_RX);
- if (!lynx->phyic.reg_1394a) {
- /* attempt to enable contender bit -FIXME- would this work
- * elsewhere? */
- reg_set_bits(lynx, GPIO_CTRL_A, 0x1);
- reg_write(lynx, GPIO_DATA_BASE + 0x3c, 0x1);
- } else {
- /* set the contender and LCtrl bit in the extended PHY register
- * set. (Should check that bis 0,1,2 (=0xE0) is set
- * in register 2?)
- */
- i = get_phy_reg(lynx, 4);
- if (i != -1) set_phy_reg(lynx, 4, i | 0xc0);
- }
-
-
+ if (!lynx->phyic.reg_1394a) {
+ if (!hpsb_disable_irm) {
+ /* attempt to enable contender bit -FIXME- would this
+ * work elsewhere? */
+ reg_set_bits(lynx, GPIO_CTRL_A, 0x1);
+ reg_write(lynx, GPIO_DATA_BASE + 0x3c, 0x1);
+ }
+ } else {
+ /* set the contender (if appropriate) and LCtrl bit in the
+ * extended PHY register set. (Should check that PHY_02_EXTENDED
+ * is set in register 2?)
+ */
+ i = get_phy_reg(lynx, 4);
+ i |= PHY_04_LCTRL;
+ if (hpsb_disable_irm)
+ i &= !PHY_04_CONTENDER;
+ else
+ i |= PHY_04_CONTENDER;
+ if (i != -1) set_phy_reg(lynx, 4, i);
+ }
+
if (!skip_eeprom)
{
- i2c_adapter = bit_ops;
+ /* needed for i2c communication with serial eeprom */
+ struct i2c_adapter *i2c_ad;
+ struct i2c_algo_bit_data i2c_adapter_data;
+
+ error = -ENOMEM;
+ i2c_ad = kmalloc(sizeof(struct i2c_adapter), SLAB_KERNEL);
+ if (!i2c_ad) FAIL("failed to allocate I2C adapter memory");
+
+ memcpy(i2c_ad, &bit_ops, sizeof(struct i2c_adapter));
i2c_adapter_data = bit_data;
- i2c_adapter.algo_data = &i2c_adapter_data;
+ i2c_ad->algo_data = &i2c_adapter_data;
i2c_adapter_data.data = lynx;
PRINTD(KERN_DEBUG, lynx->id,"original eeprom control: %d",
@@ -1808,8 +1819,9 @@ static int __devinit add_card(struct pci_dev *dev,
lynx->i2c_driven_state = 0x00000070;
reg_write(lynx, SERIAL_EEPROM_CONTROL, lynx->i2c_driven_state);
- if (i2c_bit_add_bus(&i2c_adapter) < 0)
+ if (i2c_bit_add_bus(i2c_ad) < 0)
{
+ kfree(i2c_ad);
error = -ENXIO;
FAIL("unable to register i2c");
}
@@ -1825,13 +1837,13 @@ static int __devinit add_card(struct pci_dev *dev,
#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
union i2c_smbus_data data;
- if (i2c_smbus_xfer(&i2c_adapter, 80, 0, I2C_SMBUS_WRITE, 0, I2C_SMBUS_BYTE,NULL))
+ if (i2c_smbus_xfer(i2c_ad, 80, 0, I2C_SMBUS_WRITE, 0, I2C_SMBUS_BYTE,NULL))
PRINT(KERN_ERR, lynx->id,"eeprom read start has failed");
else
{
u16 addr;
for (addr=0x00; addr < 0x100; addr++) {
- if (i2c_smbus_xfer(&i2c_adapter, 80, 0, I2C_SMBUS_READ, 0, I2C_SMBUS_BYTE,& data)) {
+ if (i2c_smbus_xfer(i2c_ad, 80, 0, I2C_SMBUS_READ, 0, I2C_SMBUS_BYTE,& data)) {
PRINT(KERN_ERR, lynx->id, "unable to read i2c %x", addr);
break;
}
@@ -1843,7 +1855,7 @@ static int __devinit add_card(struct pci_dev *dev,
/* we use i2c_transfer, because i2c_smbus_read_block_data does not work properly and we
do it more efficiently in one transaction rather then using several reads */
- if (i2c_transfer(&i2c_adapter, msg, 2) < 0) {
+ if (i2c_transfer(i2c_ad, msg, 2) < 0) {
PRINT(KERN_ERR, lynx->id, "unable to read bus info block from i2c");
} else {
int i;
@@ -1863,13 +1875,15 @@ static int __devinit add_card(struct pci_dev *dev,
{
PRINT(KERN_DEBUG, lynx->id, "read a valid bus info block from");
} else {
+ kfree(i2c_ad);
error = -ENXIO;
FAIL("read something from serial eeprom, but it does not seem to be a valid bus info block");
}
}
- i2c_bit_del_bus(&i2c_adapter);
+ i2c_bit_del_bus(i2c_ad);
+ kfree(i2c_ad);
}
}
@@ -1938,7 +1952,7 @@ static int __init pcilynx_init(void)
}
#endif
- ret = pci_module_init(&lynx_pci_driver);
+ ret = pci_register_driver(&lynx_pci_driver);
if (ret < 0) {
PRINT_G(KERN_ERR, "PCI module init failed");
goto free_char_dev;
diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c
index 674dd23e55857..6a08a8982ea82 100644
--- a/drivers/ieee1394/raw1394.c
+++ b/drivers/ieee1394/raw1394.c
@@ -75,58 +75,60 @@ static DEFINE_SPINLOCK(host_info_lock);
static atomic_t internal_generation = ATOMIC_INIT(0);
static atomic_t iso_buffer_size;
-static const int iso_buffer_max = 4 * 1024 * 1024; /* 4 MB */
+static const int iso_buffer_max = 4 * 1024 * 1024; /* 4 MB */
static struct hpsb_highlevel raw1394_highlevel;
-static int arm_read (struct hpsb_host *host, int nodeid, quadlet_t *buffer,
- u64 addr, size_t length, u16 flags);
-static int arm_write (struct hpsb_host *host, int nodeid, int destid,
- quadlet_t *data, u64 addr, size_t length, u16 flags);
-static int arm_lock (struct hpsb_host *host, int nodeid, quadlet_t *store,
- u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode, u16 flags);
-static int arm_lock64 (struct hpsb_host *host, int nodeid, octlet_t *store,
- u64 addr, octlet_t data, octlet_t arg, int ext_tcode, u16 flags);
+static int arm_read(struct hpsb_host *host, int nodeid, quadlet_t * buffer,
+ u64 addr, size_t length, u16 flags);
+static int arm_write(struct hpsb_host *host, int nodeid, int destid,
+ quadlet_t * data, u64 addr, size_t length, u16 flags);
+static int arm_lock(struct hpsb_host *host, int nodeid, quadlet_t * store,
+ u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode,
+ u16 flags);
+static int arm_lock64(struct hpsb_host *host, int nodeid, octlet_t * store,
+ u64 addr, octlet_t data, octlet_t arg, int ext_tcode,
+ u16 flags);
static struct hpsb_address_ops arm_ops = {
- .read = arm_read,
- .write = arm_write,
- .lock = arm_lock,
- .lock64 = arm_lock64,
+ .read = arm_read,
+ .write = arm_write,
+ .lock = arm_lock,
+ .lock64 = arm_lock64,
};
static void queue_complete_cb(struct pending_request *req);
static struct pending_request *__alloc_pending_request(int flags)
{
- struct pending_request *req;
+ struct pending_request *req;
- req = (struct pending_request *)kmalloc(sizeof(struct pending_request),
- flags);
- if (req != NULL) {
- memset(req, 0, sizeof(struct pending_request));
- INIT_LIST_HEAD(&req->list);
- }
+ req = (struct pending_request *)kmalloc(sizeof(struct pending_request),
+ flags);
+ if (req != NULL) {
+ memset(req, 0, sizeof(struct pending_request));
+ INIT_LIST_HEAD(&req->list);
+ }
- return req;
+ return req;
}
static inline struct pending_request *alloc_pending_request(void)
{
- return __alloc_pending_request(SLAB_KERNEL);
+ return __alloc_pending_request(SLAB_KERNEL);
}
static void free_pending_request(struct pending_request *req)
{
- if (req->ibs) {
- if (atomic_dec_and_test(&req->ibs->refcount)) {
- atomic_sub(req->ibs->data_size, &iso_buffer_size);
- kfree(req->ibs);
- }
- } else if (req->free_data) {
- kfree(req->data);
- }
- hpsb_free_packet(req->packet);
- kfree(req);
+ if (req->ibs) {
+ if (atomic_dec_and_test(&req->ibs->refcount)) {
+ atomic_sub(req->ibs->data_size, &iso_buffer_size);
+ kfree(req->ibs);
+ }
+ } else if (req->free_data) {
+ kfree(req->data);
+ }
+ hpsb_free_packet(req->packet);
+ kfree(req);
}
/* fi->reqlists_lock must be taken */
@@ -134,494 +136,505 @@ static void __queue_complete_req(struct pending_request *req)
{
struct file_info *fi = req->file_info;
list_del(&req->list);
- list_add_tail(&req->list, &fi->req_complete);
+ list_add_tail(&req->list, &fi->req_complete);
up(&fi->complete_sem);
- wake_up_interruptible(&fi->poll_wait_complete);
+ wake_up_interruptible(&fi->poll_wait_complete);
}
static void queue_complete_req(struct pending_request *req)
{
- unsigned long flags;
- struct file_info *fi = req->file_info;
+ unsigned long flags;
+ struct file_info *fi = req->file_info;
- spin_lock_irqsave(&fi->reqlists_lock, flags);
+ spin_lock_irqsave(&fi->reqlists_lock, flags);
__queue_complete_req(req);
- spin_unlock_irqrestore(&fi->reqlists_lock, flags);
+ spin_unlock_irqrestore(&fi->reqlists_lock, flags);
}
static void queue_complete_cb(struct pending_request *req)
{
- struct hpsb_packet *packet = req->packet;
- int rcode = (packet->header[1] >> 12) & 0xf;
-
- switch (packet->ack_code) {
- case ACKX_NONE:
- case ACKX_SEND_ERROR:
- req->req.error = RAW1394_ERROR_SEND_ERROR;
- break;
- case ACKX_ABORTED:
- req->req.error = RAW1394_ERROR_ABORTED;
- break;
- case ACKX_TIMEOUT:
- req->req.error = RAW1394_ERROR_TIMEOUT;
- break;
- default:
- req->req.error = (packet->ack_code << 16) | rcode;
- break;
- }
-
- if (!((packet->ack_code == ACK_PENDING) && (rcode == RCODE_COMPLETE))) {
- req->req.length = 0;
- }
-
- if ((req->req.type == RAW1394_REQ_ASYNC_READ) ||
+ struct hpsb_packet *packet = req->packet;
+ int rcode = (packet->header[1] >> 12) & 0xf;
+
+ switch (packet->ack_code) {
+ case ACKX_NONE:
+ case ACKX_SEND_ERROR:
+ req->req.error = RAW1394_ERROR_SEND_ERROR;
+ break;
+ case ACKX_ABORTED:
+ req->req.error = RAW1394_ERROR_ABORTED;
+ break;
+ case ACKX_TIMEOUT:
+ req->req.error = RAW1394_ERROR_TIMEOUT;
+ break;
+ default:
+ req->req.error = (packet->ack_code << 16) | rcode;
+ break;
+ }
+
+ if (!((packet->ack_code == ACK_PENDING) && (rcode == RCODE_COMPLETE))) {
+ req->req.length = 0;
+ }
+
+ if ((req->req.type == RAW1394_REQ_ASYNC_READ) ||
(req->req.type == RAW1394_REQ_ASYNC_WRITE) ||
(req->req.type == RAW1394_REQ_ASYNC_STREAM) ||
(req->req.type == RAW1394_REQ_LOCK) ||
(req->req.type == RAW1394_REQ_LOCK64))
- hpsb_free_tlabel(packet);
+ hpsb_free_tlabel(packet);
- queue_complete_req(req);
+ queue_complete_req(req);
}
-
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);
+ struct host_info *hi;
+ unsigned long flags;
- if (hi != NULL) {
- INIT_LIST_HEAD(&hi->list);
- hi->host = host;
- INIT_LIST_HEAD(&hi->file_info_list);
+ hi = (struct host_info *)kmalloc(sizeof(struct host_info), GFP_KERNEL);
- spin_lock_irqsave(&host_info_lock, flags);
- list_add_tail(&hi->list, &host_info_list);
- host_count++;
- spin_unlock_irqrestore(&host_info_lock, flags);
- }
+ if (hi != NULL) {
+ INIT_LIST_HEAD(&hi->list);
+ hi->host = host;
+ INIT_LIST_HEAD(&hi->file_info_list);
+
+ spin_lock_irqsave(&host_info_lock, flags);
+ list_add_tail(&hi->list, &host_info_list);
+ host_count++;
+ spin_unlock_irqrestore(&host_info_lock, flags);
+ }
- atomic_inc(&internal_generation);
+ atomic_inc(&internal_generation);
}
-
static struct host_info *find_host_info(struct hpsb_host *host)
{
- struct host_info *hi;
+ struct host_info *hi;
- list_for_each_entry(hi, &host_info_list, list)
- if (hi->host == host)
- return hi;
+ list_for_each_entry(hi, &host_info_list, list)
+ if (hi->host == host)
+ return hi;
- return NULL;
+ return NULL;
}
static void remove_host(struct hpsb_host *host)
{
- struct host_info *hi;
- unsigned long flags;
-
- spin_lock_irqsave(&host_info_lock, flags);
- hi = find_host_info(host);
-
- if (hi != NULL) {
- list_del(&hi->list);
- host_count--;
- /*
- FIXME: address ranges should be removed
- and fileinfo states should be initialized
- (including setting generation to
- internal-generation ...)
- */
- }
- spin_unlock_irqrestore(&host_info_lock, flags);
-
- if (hi == NULL) {
- printk(KERN_ERR "raw1394: attempt to remove unknown host "
- "0x%p\n", host);
- return;
- }
-
- kfree(hi);
-
- atomic_inc(&internal_generation);
+ struct host_info *hi;
+ unsigned long flags;
+
+ spin_lock_irqsave(&host_info_lock, flags);
+ hi = find_host_info(host);
+
+ if (hi != NULL) {
+ list_del(&hi->list);
+ host_count--;
+ /*
+ FIXME: address ranges should be removed
+ and fileinfo states should be initialized
+ (including setting generation to
+ internal-generation ...)
+ */
+ }
+ spin_unlock_irqrestore(&host_info_lock, flags);
+
+ if (hi == NULL) {
+ printk(KERN_ERR "raw1394: attempt to remove unknown host "
+ "0x%p\n", host);
+ return;
+ }
+
+ kfree(hi);
+
+ atomic_inc(&internal_generation);
}
static void host_reset(struct hpsb_host *host)
{
- unsigned long flags;
- struct host_info *hi;
- struct file_info *fi;
- struct pending_request *req;
-
- spin_lock_irqsave(&host_info_lock, flags);
- hi = find_host_info(host);
-
- if (hi != NULL) {
- list_for_each_entry(fi, &hi->file_info_list, list) {
- if (fi->notification == RAW1394_NOTIFY_ON) {
- req = __alloc_pending_request(SLAB_ATOMIC);
-
- if (req != NULL) {
- req->file_info = fi;
- req->req.type = RAW1394_REQ_BUS_RESET;
- req->req.generation = get_hpsb_generation(host);
- req->req.misc = (host->node_id << 16)
- | host->node_count;
- if (fi->protocol_version > 3) {
- req->req.misc |= (NODEID_TO_NODE(host->irm_id)
- << 8);
- }
-
- queue_complete_req(req);
- }
- }
- }
- }
- spin_unlock_irqrestore(&host_info_lock, flags);
+ unsigned long flags;
+ struct host_info *hi;
+ struct file_info *fi;
+ struct pending_request *req;
+
+ spin_lock_irqsave(&host_info_lock, flags);
+ hi = find_host_info(host);
+
+ if (hi != NULL) {
+ list_for_each_entry(fi, &hi->file_info_list, list) {
+ if (fi->notification == RAW1394_NOTIFY_ON) {
+ req = __alloc_pending_request(SLAB_ATOMIC);
+
+ if (req != NULL) {
+ req->file_info = fi;
+ req->req.type = RAW1394_REQ_BUS_RESET;
+ req->req.generation =
+ get_hpsb_generation(host);
+ req->req.misc = (host->node_id << 16)
+ | host->node_count;
+ if (fi->protocol_version > 3) {
+ req->req.misc |=
+ (NODEID_TO_NODE
+ (host->irm_id)
+ << 8);
+ }
+
+ queue_complete_req(req);
+ }
+ }
+ }
+ }
+ spin_unlock_irqrestore(&host_info_lock, flags);
}
-static void iso_receive(struct hpsb_host *host, int channel, quadlet_t *data,
- size_t length)
+static void iso_receive(struct hpsb_host *host, int channel, quadlet_t * data,
+ size_t length)
{
- unsigned long flags;
- struct host_info *hi;
- struct file_info *fi;
- struct pending_request *req, *req_next;
- struct iso_block_store *ibs = NULL;
- LIST_HEAD(reqs);
-
- if ((atomic_read(&iso_buffer_size) + length) > iso_buffer_max) {
- HPSB_INFO("dropped iso packet");
- return;
- }
-
- spin_lock_irqsave(&host_info_lock, flags);
- hi = find_host_info(host);
-
- if (hi != NULL) {
+ unsigned long flags;
+ struct host_info *hi;
+ struct file_info *fi;
+ struct pending_request *req, *req_next;
+ struct iso_block_store *ibs = NULL;
+ LIST_HEAD(reqs);
+
+ if ((atomic_read(&iso_buffer_size) + length) > iso_buffer_max) {
+ HPSB_INFO("dropped iso packet");
+ return;
+ }
+
+ spin_lock_irqsave(&host_info_lock, flags);
+ hi = find_host_info(host);
+
+ if (hi != NULL) {
list_for_each_entry(fi, &hi->file_info_list, list) {
- if (!(fi->listen_channels & (1ULL << channel)))
- continue;
-
- req = __alloc_pending_request(SLAB_ATOMIC);
- if (!req) break;
-
- if (!ibs) {
- ibs = kmalloc(sizeof(struct iso_block_store)
- + length, SLAB_ATOMIC);
- if (!ibs) {
- kfree(req);
- break;
- }
-
- atomic_add(length, &iso_buffer_size);
- atomic_set(&ibs->refcount, 0);
- ibs->data_size = length;
- memcpy(ibs->data, data, length);
- }
-
- atomic_inc(&ibs->refcount);
-
- req->file_info = fi;
- req->ibs = ibs;
- req->data = ibs->data;
- req->req.type = RAW1394_REQ_ISO_RECEIVE;
- req->req.generation = get_hpsb_generation(host);
- req->req.misc = 0;
- req->req.recvb = ptr2int(fi->iso_buffer);
- req->req.length = min(length, fi->iso_buffer_length);
-
- list_add_tail(&req->list, &reqs);
- }
- }
- spin_unlock_irqrestore(&host_info_lock, flags);
+ if (!(fi->listen_channels & (1ULL << channel)))
+ continue;
+
+ req = __alloc_pending_request(SLAB_ATOMIC);
+ if (!req)
+ break;
+
+ if (!ibs) {
+ ibs = kmalloc(sizeof(struct iso_block_store)
+ + length, SLAB_ATOMIC);
+ if (!ibs) {
+ kfree(req);
+ break;
+ }
+
+ atomic_add(length, &iso_buffer_size);
+ atomic_set(&ibs->refcount, 0);
+ ibs->data_size = length;
+ memcpy(ibs->data, data, length);
+ }
+
+ atomic_inc(&ibs->refcount);
+
+ req->file_info = fi;
+ req->ibs = ibs;
+ req->data = ibs->data;
+ req->req.type = RAW1394_REQ_ISO_RECEIVE;
+ req->req.generation = get_hpsb_generation(host);
+ req->req.misc = 0;
+ req->req.recvb = ptr2int(fi->iso_buffer);
+ req->req.length = min(length, fi->iso_buffer_length);
+
+ list_add_tail(&req->list, &reqs);
+ }
+ }
+ spin_unlock_irqrestore(&host_info_lock, flags);
list_for_each_entry_safe(req, req_next, &reqs, list)
- queue_complete_req(req);
+ queue_complete_req(req);
}
static void fcp_request(struct hpsb_host *host, int nodeid, int direction,
- int cts, u8 *data, size_t length)
+ int cts, u8 * data, size_t length)
{
- unsigned long flags;
- struct host_info *hi;
- struct file_info *fi;
- struct pending_request *req, *req_next;
- struct iso_block_store *ibs = NULL;
- LIST_HEAD(reqs);
-
- if ((atomic_read(&iso_buffer_size) + length) > iso_buffer_max) {
- HPSB_INFO("dropped fcp request");
- return;
- }
-
- spin_lock_irqsave(&host_info_lock, flags);
- hi = find_host_info(host);
-
- if (hi != NULL) {
+ unsigned long flags;
+ struct host_info *hi;
+ struct file_info *fi;
+ struct pending_request *req, *req_next;
+ struct iso_block_store *ibs = NULL;
+ LIST_HEAD(reqs);
+
+ if ((atomic_read(&iso_buffer_size) + length) > iso_buffer_max) {
+ HPSB_INFO("dropped fcp request");
+ return;
+ }
+
+ spin_lock_irqsave(&host_info_lock, flags);
+ hi = find_host_info(host);
+
+ if (hi != NULL) {
list_for_each_entry(fi, &hi->file_info_list, list) {
- if (!fi->fcp_buffer)
- continue;
-
- req = __alloc_pending_request(SLAB_ATOMIC);
- if (!req) break;
-
- if (!ibs) {
- ibs = kmalloc(sizeof(struct iso_block_store)
- + length, SLAB_ATOMIC);
- if (!ibs) {
- kfree(req);
- break;
- }
-
- atomic_add(length, &iso_buffer_size);
- atomic_set(&ibs->refcount, 0);
- ibs->data_size = length;
- memcpy(ibs->data, data, length);
- }
-
- atomic_inc(&ibs->refcount);
-
- req->file_info = fi;
- req->ibs = ibs;
- req->data = ibs->data;
- req->req.type = RAW1394_REQ_FCP_REQUEST;
- req->req.generation = get_hpsb_generation(host);
- req->req.misc = nodeid | (direction << 16);
- req->req.recvb = ptr2int(fi->fcp_buffer);
- req->req.length = length;
-
- list_add_tail(&req->list, &reqs);
- }
- }
- spin_unlock_irqrestore(&host_info_lock, flags);
+ if (!fi->fcp_buffer)
+ continue;
+
+ req = __alloc_pending_request(SLAB_ATOMIC);
+ if (!req)
+ break;
+
+ if (!ibs) {
+ ibs = kmalloc(sizeof(struct iso_block_store)
+ + length, SLAB_ATOMIC);
+ if (!ibs) {
+ kfree(req);
+ break;
+ }
+
+ atomic_add(length, &iso_buffer_size);
+ atomic_set(&ibs->refcount, 0);
+ ibs->data_size = length;
+ memcpy(ibs->data, data, length);
+ }
+
+ atomic_inc(&ibs->refcount);
+
+ req->file_info = fi;
+ req->ibs = ibs;
+ req->data = ibs->data;
+ req->req.type = RAW1394_REQ_FCP_REQUEST;
+ req->req.generation = get_hpsb_generation(host);
+ req->req.misc = nodeid | (direction << 16);
+ req->req.recvb = ptr2int(fi->fcp_buffer);
+ req->req.length = length;
+
+ list_add_tail(&req->list, &reqs);
+ }
+ }
+ spin_unlock_irqrestore(&host_info_lock, flags);
list_for_each_entry_safe(req, req_next, &reqs, list)
- queue_complete_req(req);
+ queue_complete_req(req);
}
-
-static ssize_t raw1394_read(struct file *file, char __user *buffer, size_t count,
- loff_t *offset_is_ignored)
+static ssize_t raw1394_read(struct file *file, char __user * buffer,
+ size_t count, loff_t * offset_is_ignored)
{
- struct file_info *fi = (struct file_info *)file->private_data;
- struct list_head *lh;
- struct pending_request *req;
-
- if (count != sizeof(struct raw1394_request)) {
- return -EINVAL;
- }
-
- if (!access_ok(VERIFY_WRITE, buffer, count)) {
- return -EFAULT;
- }
-
- if (file->f_flags & O_NONBLOCK) {
- if (down_trylock(&fi->complete_sem)) {
- return -EAGAIN;
- }
- } else {
- if (down_interruptible(&fi->complete_sem)) {
- return -ERESTARTSYS;
- }
- }
-
- spin_lock_irq(&fi->reqlists_lock);
- lh = fi->req_complete.next;
- list_del(lh);
- spin_unlock_irq(&fi->reqlists_lock);
-
- req = list_entry(lh, struct pending_request, list);
-
- if (req->req.length) {
- if (copy_to_user(int2ptr(req->req.recvb), req->data,
- req->req.length)) {
- req->req.error = RAW1394_ERROR_MEMFAULT;
- }
- }
- __copy_to_user(buffer, &req->req, sizeof(req->req));
-
- free_pending_request(req);
- return sizeof(struct raw1394_request);
-}
+ struct file_info *fi = (struct file_info *)file->private_data;
+ struct list_head *lh;
+ struct pending_request *req;
+ ssize_t ret;
+
+ if (count != sizeof(struct raw1394_request)) {
+ return -EINVAL;
+ }
+
+ if (!access_ok(VERIFY_WRITE, buffer, count)) {
+ return -EFAULT;
+ }
+
+ if (file->f_flags & O_NONBLOCK) {
+ if (down_trylock(&fi->complete_sem)) {
+ return -EAGAIN;
+ }
+ } else {
+ if (down_interruptible(&fi->complete_sem)) {
+ return -ERESTARTSYS;
+ }
+ }
+ spin_lock_irq(&fi->reqlists_lock);
+ lh = fi->req_complete.next;
+ list_del(lh);
+ spin_unlock_irq(&fi->reqlists_lock);
+
+ req = list_entry(lh, struct pending_request, list);
+
+ if (req->req.length) {
+ if (copy_to_user(int2ptr(req->req.recvb), req->data,
+ req->req.length)) {
+ req->req.error = RAW1394_ERROR_MEMFAULT;
+ }
+ }
+ if (copy_to_user(buffer, &req->req, sizeof(req->req))) {
+ ret = -EFAULT;
+ goto out;
+ }
+
+ ret = (ssize_t) sizeof(struct raw1394_request);
+ out:
+ free_pending_request(req);
+ return ret;
+}
static int state_opened(struct file_info *fi, struct pending_request *req)
{
- if (req->req.type == RAW1394_REQ_INITIALIZE) {
- switch (req->req.misc) {
- case RAW1394_KERNELAPI_VERSION:
- case 3:
- fi->state = initialized;
- fi->protocol_version = req->req.misc;
- req->req.error = RAW1394_ERROR_NONE;
- req->req.generation = atomic_read(&internal_generation);
- break;
-
- default:
- req->req.error = RAW1394_ERROR_COMPAT;
- req->req.misc = RAW1394_KERNELAPI_VERSION;
- }
- } else {
- req->req.error = RAW1394_ERROR_STATE_ORDER;
- }
-
- req->req.length = 0;
- queue_complete_req(req);
- return sizeof(struct raw1394_request);
+ if (req->req.type == RAW1394_REQ_INITIALIZE) {
+ switch (req->req.misc) {
+ case RAW1394_KERNELAPI_VERSION:
+ case 3:
+ fi->state = initialized;
+ fi->protocol_version = req->req.misc;
+ req->req.error = RAW1394_ERROR_NONE;
+ req->req.generation = atomic_read(&internal_generation);
+ break;
+
+ default:
+ req->req.error = RAW1394_ERROR_COMPAT;
+ req->req.misc = RAW1394_KERNELAPI_VERSION;
+ }
+ } else {
+ req->req.error = RAW1394_ERROR_STATE_ORDER;
+ }
+
+ req->req.length = 0;
+ queue_complete_req(req);
+ return sizeof(struct raw1394_request);
}
static int state_initialized(struct file_info *fi, struct pending_request *req)
{
- struct host_info *hi;
- struct raw1394_khost_list *khl;
-
- if (req->req.generation != atomic_read(&internal_generation)) {
- req->req.error = RAW1394_ERROR_GENERATION;
- req->req.generation = atomic_read(&internal_generation);
- req->req.length = 0;
- queue_complete_req(req);
- return sizeof(struct raw1394_request);
- }
-
- switch (req->req.type) {
- case RAW1394_REQ_LIST_CARDS:
- spin_lock_irq(&host_info_lock);
- khl = kmalloc(sizeof(struct raw1394_khost_list) * host_count,
- SLAB_ATOMIC);
-
- if (khl != NULL) {
- req->req.misc = host_count;
- req->data = (quadlet_t *)khl;
-
- list_for_each_entry(hi, &host_info_list, list) {
- khl->nodes = hi->host->node_count;
- strcpy(khl->name, hi->host->driver->name);
- khl++;
- }
- }
- spin_unlock_irq(&host_info_lock);
-
- if (khl != NULL) {
- req->req.error = RAW1394_ERROR_NONE;
- req->req.length = min(req->req.length,
- (u32)(sizeof(struct raw1394_khost_list)
- * req->req.misc));
- req->free_data = 1;
- } else {
- return -ENOMEM;
- }
- break;
-
- case RAW1394_REQ_SET_CARD:
- spin_lock_irq(&host_info_lock);
- if (req->req.misc < host_count) {
+ struct host_info *hi;
+ struct raw1394_khost_list *khl;
+
+ if (req->req.generation != atomic_read(&internal_generation)) {
+ req->req.error = RAW1394_ERROR_GENERATION;
+ req->req.generation = atomic_read(&internal_generation);
+ req->req.length = 0;
+ queue_complete_req(req);
+ return sizeof(struct raw1394_request);
+ }
+
+ switch (req->req.type) {
+ case RAW1394_REQ_LIST_CARDS:
+ spin_lock_irq(&host_info_lock);
+ khl = kmalloc(sizeof(struct raw1394_khost_list) * host_count,
+ SLAB_ATOMIC);
+
+ if (khl != NULL) {
+ req->req.misc = host_count;
+ req->data = (quadlet_t *) khl;
+
+ list_for_each_entry(hi, &host_info_list, list) {
+ khl->nodes = hi->host->node_count;
+ strcpy(khl->name, hi->host->driver->name);
+ khl++;
+ }
+ }
+ spin_unlock_irq(&host_info_lock);
+
+ if (khl != NULL) {
+ req->req.error = RAW1394_ERROR_NONE;
+ req->req.length = min(req->req.length,
+ (u32) (sizeof
+ (struct raw1394_khost_list)
+ * req->req.misc));
+ req->free_data = 1;
+ } else {
+ return -ENOMEM;
+ }
+ break;
+
+ case RAW1394_REQ_SET_CARD:
+ spin_lock_irq(&host_info_lock);
+ if (req->req.misc < host_count) {
list_for_each_entry(hi, &host_info_list, list) {
if (!req->req.misc--)
break;
}
- get_device(&hi->host->device); // XXX Need to handle failure case
- list_add_tail(&fi->list, &hi->file_info_list);
- fi->host = hi->host;
- fi->state = connected;
-
- req->req.error = RAW1394_ERROR_NONE;
- req->req.generation = get_hpsb_generation(fi->host);
- req->req.misc = (fi->host->node_id << 16)
- | fi->host->node_count;
- if (fi->protocol_version > 3) {
- req->req.misc |= NODEID_TO_NODE(fi->host->irm_id) << 8;
- }
- } else {
- req->req.error = RAW1394_ERROR_INVALID_ARG;
- }
+ get_device(&hi->host->device); // XXX Need to handle failure case
+ list_add_tail(&fi->list, &hi->file_info_list);
+ fi->host = hi->host;
+ fi->state = connected;
+
+ req->req.error = RAW1394_ERROR_NONE;
+ req->req.generation = get_hpsb_generation(fi->host);
+ req->req.misc = (fi->host->node_id << 16)
+ | fi->host->node_count;
+ if (fi->protocol_version > 3) {
+ req->req.misc |=
+ NODEID_TO_NODE(fi->host->irm_id) << 8;
+ }
+ } else {
+ req->req.error = RAW1394_ERROR_INVALID_ARG;
+ }
spin_unlock_irq(&host_info_lock);
- req->req.length = 0;
- break;
+ req->req.length = 0;
+ break;
- default:
- req->req.error = RAW1394_ERROR_STATE_ORDER;
- req->req.length = 0;
- break;
- }
+ default:
+ req->req.error = RAW1394_ERROR_STATE_ORDER;
+ req->req.length = 0;
+ break;
+ }
- queue_complete_req(req);
- return sizeof(struct raw1394_request);
+ queue_complete_req(req);
+ return sizeof(struct raw1394_request);
}
static void handle_iso_listen(struct file_info *fi, struct pending_request *req)
{
- int channel = req->req.misc;
-
- spin_lock_irq(&host_info_lock);
- if ((channel > 63) || (channel < -64)) {
- req->req.error = RAW1394_ERROR_INVALID_ARG;
- } else if (channel >= 0) {
- /* allocate channel req.misc */
- if (fi->listen_channels & (1ULL << channel)) {
- req->req.error = RAW1394_ERROR_ALREADY;
- } else {
- if (hpsb_listen_channel(&raw1394_highlevel, fi->host, channel)) {
+ int channel = req->req.misc;
+
+ spin_lock_irq(&host_info_lock);
+ if ((channel > 63) || (channel < -64)) {
+ req->req.error = RAW1394_ERROR_INVALID_ARG;
+ } else if (channel >= 0) {
+ /* allocate channel req.misc */
+ if (fi->listen_channels & (1ULL << channel)) {
+ req->req.error = RAW1394_ERROR_ALREADY;
+ } else {
+ if (hpsb_listen_channel
+ (&raw1394_highlevel, fi->host, channel)) {
req->req.error = RAW1394_ERROR_ALREADY;
} else {
fi->listen_channels |= 1ULL << channel;
fi->iso_buffer = int2ptr(req->req.recvb);
fi->iso_buffer_length = req->req.length;
}
- }
- } else {
- /* deallocate channel (one's complement neg) req.misc */
- channel = ~channel;
-
- if (fi->listen_channels & (1ULL << channel)) {
- hpsb_unlisten_channel(&raw1394_highlevel, fi->host, channel);
- fi->listen_channels &= ~(1ULL << channel);
- } else {
- req->req.error = RAW1394_ERROR_INVALID_ARG;
- }
- }
-
- req->req.length = 0;
- queue_complete_req(req);
- spin_unlock_irq(&host_info_lock);
+ }
+ } else {
+ /* deallocate channel (one's complement neg) req.misc */
+ channel = ~channel;
+
+ if (fi->listen_channels & (1ULL << channel)) {
+ hpsb_unlisten_channel(&raw1394_highlevel, fi->host,
+ channel);
+ fi->listen_channels &= ~(1ULL << channel);
+ } else {
+ req->req.error = RAW1394_ERROR_INVALID_ARG;
+ }
+ }
+
+ req->req.length = 0;
+ queue_complete_req(req);
+ spin_unlock_irq(&host_info_lock);
}
static void handle_fcp_listen(struct file_info *fi, struct pending_request *req)
{
- if (req->req.misc) {
- if (fi->fcp_buffer) {
- req->req.error = RAW1394_ERROR_ALREADY;
- } else {
- fi->fcp_buffer = int2ptr(req->req.recvb);
- }
- } else {
- if (!fi->fcp_buffer) {
- req->req.error = RAW1394_ERROR_ALREADY;
- } else {
- fi->fcp_buffer = NULL;
- }
- }
-
- req->req.length = 0;
- queue_complete_req(req);
-}
+ if (req->req.misc) {
+ if (fi->fcp_buffer) {
+ req->req.error = RAW1394_ERROR_ALREADY;
+ } else {
+ fi->fcp_buffer = int2ptr(req->req.recvb);
+ }
+ } else {
+ if (!fi->fcp_buffer) {
+ req->req.error = RAW1394_ERROR_ALREADY;
+ } else {
+ fi->fcp_buffer = NULL;
+ }
+ }
+ req->req.length = 0;
+ queue_complete_req(req);
+}
static int handle_async_request(struct file_info *fi,
- struct pending_request *req, int node)
+ struct pending_request *req, int node)
{
- struct hpsb_packet *packet = NULL;
- u64 addr = req->req.address & 0xffffffffffffULL;
+ struct hpsb_packet *packet = NULL;
+ u64 addr = req->req.address & 0xffffffffffffULL;
- switch (req->req.type) {
- case RAW1394_REQ_ASYNC_READ:
+ switch (req->req.type) {
+ case RAW1394_REQ_ASYNC_READ:
DBGMSG("read_request called");
- packet = hpsb_make_readpacket(fi->host, node, addr, req->req.length);
+ packet =
+ hpsb_make_readpacket(fi->host, node, addr, req->req.length);
if (!packet)
return -ENOMEM;
@@ -631,7 +644,7 @@ static int handle_async_request(struct file_info *fi,
else
req->data = packet->data;
- break;
+ break;
case RAW1394_REQ_ASYNC_WRITE:
DBGMSG("write_request called");
@@ -642,1105 +655,1207 @@ static int handle_async_request(struct file_info *fi,
return -ENOMEM;
if (req->req.length == 4) {
- if (copy_from_user(&packet->header[3], int2ptr(req->req.sendb),
- req->req.length))
+ if (copy_from_user
+ (&packet->header[3], int2ptr(req->req.sendb),
+ req->req.length))
req->req.error = RAW1394_ERROR_MEMFAULT;
} else {
- if (copy_from_user(packet->data, int2ptr(req->req.sendb),
- req->req.length))
+ if (copy_from_user
+ (packet->data, int2ptr(req->req.sendb),
+ req->req.length))
req->req.error = RAW1394_ERROR_MEMFAULT;
}
req->req.length = 0;
- break;
+ break;
case RAW1394_REQ_ASYNC_STREAM:
DBGMSG("stream_request called");
- packet = hpsb_make_streampacket(fi->host, NULL, req->req.length, node & 0x3f/*channel*/,
- (req->req.misc >> 16) & 0x3, req->req.misc & 0xf);
+ packet =
+ hpsb_make_streampacket(fi->host, NULL, req->req.length,
+ node & 0x3f /*channel */ ,
+ (req->req.misc >> 16) & 0x3,
+ req->req.misc & 0xf);
if (!packet)
return -ENOMEM;
if (copy_from_user(packet->data, int2ptr(req->req.sendb),
- req->req.length))
+ req->req.length))
req->req.error = RAW1394_ERROR_MEMFAULT;
req->req.length = 0;
break;
- case RAW1394_REQ_LOCK:
- DBGMSG("lock_request called");
- if ((req->req.misc == EXTCODE_FETCH_ADD)
- || (req->req.misc == EXTCODE_LITTLE_ADD)) {
- if (req->req.length != 4) {
- req->req.error = RAW1394_ERROR_INVALID_ARG;
- break;
- }
- } else {
- if (req->req.length != 8) {
- req->req.error = RAW1394_ERROR_INVALID_ARG;
- break;
- }
- }
-
- packet = hpsb_make_lockpacket(fi->host, node, addr,
- req->req.misc, NULL, 0);
- if (!packet) return -ENOMEM;
-
- if (copy_from_user(packet->data, int2ptr(req->req.sendb),
- req->req.length)) {
- req->req.error = RAW1394_ERROR_MEMFAULT;
- break;
- }
-
- req->data = packet->data;
- req->req.length = 4;
- break;
-
- case RAW1394_REQ_LOCK64:
- DBGMSG("lock64_request called");
- if ((req->req.misc == EXTCODE_FETCH_ADD)
- || (req->req.misc == EXTCODE_LITTLE_ADD)) {
- if (req->req.length != 8) {
- req->req.error = RAW1394_ERROR_INVALID_ARG;
- break;
- }
- } else {
- if (req->req.length != 16) {
- req->req.error = RAW1394_ERROR_INVALID_ARG;
- break;
- }
- }
- packet = hpsb_make_lock64packet(fi->host, node, addr,
- req->req.misc, NULL, 0);
- if (!packet) return -ENOMEM;
-
- if (copy_from_user(packet->data, int2ptr(req->req.sendb),
- req->req.length)) {
- req->req.error = RAW1394_ERROR_MEMFAULT;
- break;
- }
-
- req->data = packet->data;
- req->req.length = 8;
- break;
-
- default:
- req->req.error = RAW1394_ERROR_STATE_ORDER;
- }
-
- req->packet = packet;
-
- if (req->req.error) {
- req->req.length = 0;
- queue_complete_req(req);
- return sizeof(struct raw1394_request);
- }
-
- hpsb_set_packet_complete_task(packet, (void(*)(void*))queue_complete_cb, req);
-
- spin_lock_irq(&fi->reqlists_lock);
- list_add_tail(&req->list, &fi->req_pending);
- spin_unlock_irq(&fi->reqlists_lock);
+ case RAW1394_REQ_LOCK:
+ DBGMSG("lock_request called");
+ if ((req->req.misc == EXTCODE_FETCH_ADD)
+ || (req->req.misc == EXTCODE_LITTLE_ADD)) {
+ if (req->req.length != 4) {
+ req->req.error = RAW1394_ERROR_INVALID_ARG;
+ break;
+ }
+ } else {
+ if (req->req.length != 8) {
+ req->req.error = RAW1394_ERROR_INVALID_ARG;
+ break;
+ }
+ }
+
+ packet = hpsb_make_lockpacket(fi->host, node, addr,
+ req->req.misc, NULL, 0);
+ if (!packet)
+ return -ENOMEM;
+
+ if (copy_from_user(packet->data, int2ptr(req->req.sendb),
+ req->req.length)) {
+ req->req.error = RAW1394_ERROR_MEMFAULT;
+ break;
+ }
+
+ req->data = packet->data;
+ req->req.length = 4;
+ break;
+
+ case RAW1394_REQ_LOCK64:
+ DBGMSG("lock64_request called");
+ if ((req->req.misc == EXTCODE_FETCH_ADD)
+ || (req->req.misc == EXTCODE_LITTLE_ADD)) {
+ if (req->req.length != 8) {
+ req->req.error = RAW1394_ERROR_INVALID_ARG;
+ break;
+ }
+ } else {
+ if (req->req.length != 16) {
+ req->req.error = RAW1394_ERROR_INVALID_ARG;
+ break;
+ }
+ }
+ packet = hpsb_make_lock64packet(fi->host, node, addr,
+ req->req.misc, NULL, 0);
+ if (!packet)
+ return -ENOMEM;
+
+ if (copy_from_user(packet->data, int2ptr(req->req.sendb),
+ req->req.length)) {
+ req->req.error = RAW1394_ERROR_MEMFAULT;
+ break;
+ }
+
+ req->data = packet->data;
+ req->req.length = 8;
+ break;
+
+ default:
+ req->req.error = RAW1394_ERROR_STATE_ORDER;
+ }
+
+ req->packet = packet;
+
+ if (req->req.error) {
+ req->req.length = 0;
+ queue_complete_req(req);
+ return sizeof(struct raw1394_request);
+ }
+
+ hpsb_set_packet_complete_task(packet,
+ (void (*)(void *))queue_complete_cb, req);
+
+ spin_lock_irq(&fi->reqlists_lock);
+ list_add_tail(&req->list, &fi->req_pending);
+ spin_unlock_irq(&fi->reqlists_lock);
packet->generation = req->req.generation;
- if (hpsb_send_packet(packet) < 0) {
- req->req.error = RAW1394_ERROR_SEND_ERROR;
- req->req.length = 0;
- hpsb_free_tlabel(packet);
- queue_complete_req(req);
- }
- return sizeof(struct raw1394_request);
+ if (hpsb_send_packet(packet) < 0) {
+ req->req.error = RAW1394_ERROR_SEND_ERROR;
+ req->req.length = 0;
+ hpsb_free_tlabel(packet);
+ queue_complete_req(req);
+ }
+ return sizeof(struct raw1394_request);
}
static int handle_iso_send(struct file_info *fi, struct pending_request *req,
- int channel)
+ int channel)
{
- struct hpsb_packet *packet;
+ struct hpsb_packet *packet;
packet = hpsb_make_isopacket(fi->host, req->req.length, channel & 0x3f,
- (req->req.misc >> 16) & 0x3, req->req.misc & 0xf);
+ (req->req.misc >> 16) & 0x3,
+ req->req.misc & 0xf);
if (!packet)
return -ENOMEM;
- packet->speed_code = req->req.address & 0x3;
+ packet->speed_code = req->req.address & 0x3;
req->packet = packet;
- if (copy_from_user(packet->data, int2ptr(req->req.sendb),
- req->req.length)) {
- req->req.error = RAW1394_ERROR_MEMFAULT;
- req->req.length = 0;
- queue_complete_req(req);
- return sizeof(struct raw1394_request);
- }
+ if (copy_from_user(packet->data, int2ptr(req->req.sendb),
+ req->req.length)) {
+ req->req.error = RAW1394_ERROR_MEMFAULT;
+ req->req.length = 0;
+ queue_complete_req(req);
+ return sizeof(struct raw1394_request);
+ }
- req->req.length = 0;
- hpsb_set_packet_complete_task(packet, (void (*)(void*))queue_complete_req, req);
+ req->req.length = 0;
+ hpsb_set_packet_complete_task(packet,
+ (void (*)(void *))queue_complete_req,
+ req);
- spin_lock_irq(&fi->reqlists_lock);
- list_add_tail(&req->list, &fi->req_pending);
- spin_unlock_irq(&fi->reqlists_lock);
+ spin_lock_irq(&fi->reqlists_lock);
+ list_add_tail(&req->list, &fi->req_pending);
+ spin_unlock_irq(&fi->reqlists_lock);
/* Update the generation of the packet just before sending. */
packet->generation = req->req.generation;
- if (hpsb_send_packet(packet) < 0) {
- req->req.error = RAW1394_ERROR_SEND_ERROR;
- queue_complete_req(req);
- }
+ if (hpsb_send_packet(packet) < 0) {
+ req->req.error = RAW1394_ERROR_SEND_ERROR;
+ queue_complete_req(req);
+ }
- return sizeof(struct raw1394_request);
+ return sizeof(struct raw1394_request);
}
static int handle_async_send(struct file_info *fi, struct pending_request *req)
{
- struct hpsb_packet *packet;
- int header_length = req->req.misc & 0xffff;
- int expect_response = req->req.misc >> 16;
-
- if ((header_length > req->req.length) ||
- (header_length < 12)) {
- req->req.error = RAW1394_ERROR_INVALID_ARG;
- req->req.length = 0;
- queue_complete_req(req);
- return sizeof(struct raw1394_request);
- }
-
- packet = hpsb_alloc_packet(req->req.length-header_length);
- req->packet = packet;
- if (!packet) return -ENOMEM;
-
- if (copy_from_user(packet->header, int2ptr(req->req.sendb),
- header_length)) {
- req->req.error = RAW1394_ERROR_MEMFAULT;
- req->req.length = 0;
- queue_complete_req(req);
- return sizeof(struct raw1394_request);
- }
-
- if (copy_from_user(packet->data, int2ptr(req->req.sendb) + header_length,
- packet->data_size)) {
- req->req.error = RAW1394_ERROR_MEMFAULT;
- req->req.length = 0;
- queue_complete_req(req);
- return sizeof(struct raw1394_request);
- }
-
- packet->type = hpsb_async;
- packet->node_id = packet->header[0] >> 16;
- packet->tcode = (packet->header[0] >> 4) & 0xf;
- packet->tlabel = (packet->header[0] >> 10) &0x3f;
- packet->host = fi->host;
- packet->expect_response = expect_response;
- packet->header_size=header_length;
- packet->data_size=req->req.length-header_length;
-
- req->req.length = 0;
- hpsb_set_packet_complete_task(packet, (void(*)(void*))queue_complete_cb, req);
-
- spin_lock_irq(&fi->reqlists_lock);
- list_add_tail(&req->list, &fi->req_pending);
- spin_unlock_irq(&fi->reqlists_lock);
-
- /* Update the generation of the packet just before sending. */
- packet->generation = req->req.generation;
-
- if (hpsb_send_packet(packet) < 0) {
- req->req.error = RAW1394_ERROR_SEND_ERROR;
- queue_complete_req(req);
- }
-
- return sizeof(struct raw1394_request);
+ struct hpsb_packet *packet;
+ int header_length = req->req.misc & 0xffff;
+ int expect_response = req->req.misc >> 16;
+
+ if ((header_length > req->req.length) || (header_length < 12)) {
+ req->req.error = RAW1394_ERROR_INVALID_ARG;
+ req->req.length = 0;
+ queue_complete_req(req);
+ return sizeof(struct raw1394_request);
+ }
+
+ packet = hpsb_alloc_packet(req->req.length - header_length);
+ req->packet = packet;
+ if (!packet)
+ return -ENOMEM;
+
+ if (copy_from_user(packet->header, int2ptr(req->req.sendb),
+ header_length)) {
+ req->req.error = RAW1394_ERROR_MEMFAULT;
+ req->req.length = 0;
+ queue_complete_req(req);
+ return sizeof(struct raw1394_request);
+ }
+
+ if (copy_from_user
+ (packet->data, int2ptr(req->req.sendb) + header_length,
+ packet->data_size)) {
+ req->req.error = RAW1394_ERROR_MEMFAULT;
+ req->req.length = 0;
+ queue_complete_req(req);
+ return sizeof(struct raw1394_request);
+ }
+
+ packet->type = hpsb_async;
+ packet->node_id = packet->header[0] >> 16;
+ packet->tcode = (packet->header[0] >> 4) & 0xf;
+ packet->tlabel = (packet->header[0] >> 10) & 0x3f;
+ packet->host = fi->host;
+ packet->expect_response = expect_response;
+ packet->header_size = header_length;
+ packet->data_size = req->req.length - header_length;
+
+ req->req.length = 0;
+ hpsb_set_packet_complete_task(packet,
+ (void (*)(void *))queue_complete_cb, req);
+
+ spin_lock_irq(&fi->reqlists_lock);
+ list_add_tail(&req->list, &fi->req_pending);
+ spin_unlock_irq(&fi->reqlists_lock);
+
+ /* Update the generation of the packet just before sending. */
+ packet->generation = req->req.generation;
+
+ if (hpsb_send_packet(packet) < 0) {
+ req->req.error = RAW1394_ERROR_SEND_ERROR;
+ queue_complete_req(req);
+ }
+
+ return sizeof(struct raw1394_request);
}
-static int arm_read (struct hpsb_host *host, int nodeid, quadlet_t *buffer,
- u64 addr, size_t length, u16 flags)
+static int arm_read(struct hpsb_host *host, int nodeid, quadlet_t * buffer,
+ u64 addr, size_t length, u16 flags)
{
- struct pending_request *req;
- struct host_info *hi;
- struct file_info *fi = NULL;
- struct list_head *entry;
- struct arm_addr *arm_addr = NULL;
- struct arm_request *arm_req = NULL;
- struct arm_response *arm_resp = NULL;
- int found=0, size=0, rcode=-1;
- struct arm_request_response *arm_req_resp = NULL;
-
- DBGMSG("arm_read called by node: %X"
- "addr: %4.4x %8.8x length: %Zu", nodeid,
- (u16) ((addr >>32) & 0xFFFF), (u32) (addr & 0xFFFFFFFF),
- length);
- spin_lock(&host_info_lock);
- hi = find_host_info(host); /* search address-entry */
- if (hi != NULL) {
- list_for_each_entry(fi, &hi->file_info_list, list) {
- entry = fi->addr_list.next;
- while (entry != &(fi->addr_list)) {
- arm_addr = list_entry(entry, struct arm_addr, addr_list);
- if (((arm_addr->start) <= (addr)) &&
- ((arm_addr->end) >= (addr+length))) {
- found = 1;
- break;
- }
- entry = entry->next;
- }
- if (found) {
- break;
- }
- }
- }
- rcode = -1;
- if (!found) {
- printk(KERN_ERR "raw1394: arm_read FAILED addr_entry not found"
- " -> rcode_address_error\n");
- spin_unlock(&host_info_lock);
- return (RCODE_ADDRESS_ERROR);
- } else {
- DBGMSG("arm_read addr_entry FOUND");
- }
- if (arm_addr->rec_length < length) {
- DBGMSG("arm_read blocklength too big -> rcode_data_error");
- rcode = RCODE_DATA_ERROR; /* hardware error, data is unavailable */
- }
- if (rcode == -1) {
- if (arm_addr->access_rights & ARM_READ) {
- if (!(arm_addr->client_transactions & ARM_READ)) {
- memcpy(buffer,(arm_addr->addr_space_buffer)+(addr-(arm_addr->start)),
- length);
- DBGMSG("arm_read -> (rcode_complete)");
- rcode = RCODE_COMPLETE;
- }
- } else {
- rcode = RCODE_TYPE_ERROR; /* function not allowed */
- DBGMSG("arm_read -> rcode_type_error (access denied)");
- }
- }
- if (arm_addr->notification_options & ARM_READ) {
- DBGMSG("arm_read -> entering notification-section");
- req = __alloc_pending_request(SLAB_ATOMIC);
- if (!req) {
- DBGMSG("arm_read -> rcode_conflict_error");
- spin_unlock(&host_info_lock);
- return(RCODE_CONFLICT_ERROR); /* A resource conflict was detected.
- The request may be retried */
- }
- if (rcode == RCODE_COMPLETE) {
- size = sizeof(struct arm_request)+sizeof(struct arm_response) +
- length * sizeof(byte_t) +
- sizeof (struct arm_request_response);
- } else {
- size = sizeof(struct arm_request)+sizeof(struct arm_response) +
- sizeof (struct arm_request_response);
- }
- req->data = kmalloc(size, SLAB_ATOMIC);
- if (!(req->data)) {
- free_pending_request(req);
- DBGMSG("arm_read -> rcode_conflict_error");
- spin_unlock(&host_info_lock);
- return(RCODE_CONFLICT_ERROR); /* A resource conflict was detected.
- The request may be retried */
- }
- req->free_data=1;
- req->file_info = fi;
- req->req.type = RAW1394_REQ_ARM;
- req->req.generation = get_hpsb_generation(host);
- req->req.misc = ( ((length << 16) & (0xFFFF0000)) | (ARM_READ & 0xFF));
- req->req.tag = arm_addr->arm_tag;
- req->req.recvb = arm_addr->recvb;
- req->req.length = size;
- arm_req_resp = (struct arm_request_response *) (req->data);
- arm_req = (struct arm_request *) ((byte_t *)(req->data) +
- (sizeof (struct arm_request_response)));
- arm_resp = (struct arm_response *) ((byte_t *)(arm_req) +
- (sizeof(struct arm_request)));
- arm_req->buffer = NULL;
- arm_resp->buffer = NULL;
- if (rcode == RCODE_COMPLETE) {
- byte_t *buf = (byte_t *)arm_resp + sizeof(struct arm_response);
- memcpy (buf,
- (arm_addr->addr_space_buffer)+(addr-(arm_addr->start)),
- length);
- arm_resp->buffer = int2ptr((arm_addr->recvb) +
- sizeof (struct arm_request_response) +
- sizeof (struct arm_request) +
- sizeof (struct arm_response));
- }
- arm_resp->buffer_length = (rcode == RCODE_COMPLETE) ? length : 0;
- arm_resp->response_code = rcode;
- arm_req->buffer_length = 0;
- arm_req->generation = req->req.generation;
- arm_req->extended_transaction_code = 0;
- arm_req->destination_offset = addr;
- arm_req->source_nodeid = nodeid;
- arm_req->destination_nodeid = host->node_id;
- arm_req->tlabel = (flags >> 10) & 0x3f;
- arm_req->tcode = (flags >> 4) & 0x0f;
- arm_req_resp->request = int2ptr((arm_addr->recvb) +
- sizeof (struct arm_request_response));
- arm_req_resp->response = int2ptr((arm_addr->recvb) +
- sizeof (struct arm_request_response) +
- sizeof (struct arm_request));
- queue_complete_req(req);
- }
- spin_unlock(&host_info_lock);
- return(rcode);
+ struct pending_request *req;
+ struct host_info *hi;
+ struct file_info *fi = NULL;
+ struct list_head *entry;
+ struct arm_addr *arm_addr = NULL;
+ struct arm_request *arm_req = NULL;
+ struct arm_response *arm_resp = NULL;
+ int found = 0, size = 0, rcode = -1;
+ struct arm_request_response *arm_req_resp = NULL;
+
+ DBGMSG("arm_read called by node: %X"
+ "addr: %4.4x %8.8x length: %Zu", nodeid,
+ (u16) ((addr >> 32) & 0xFFFF), (u32) (addr & 0xFFFFFFFF),
+ length);
+ spin_lock(&host_info_lock);
+ hi = find_host_info(host); /* search address-entry */
+ if (hi != NULL) {
+ list_for_each_entry(fi, &hi->file_info_list, list) {
+ entry = fi->addr_list.next;
+ while (entry != &(fi->addr_list)) {
+ arm_addr =
+ list_entry(entry, struct arm_addr,
+ addr_list);
+ if (((arm_addr->start) <= (addr))
+ && ((arm_addr->end) >= (addr + length))) {
+ found = 1;
+ break;
+ }
+ entry = entry->next;
+ }
+ if (found) {
+ break;
+ }
+ }
+ }
+ rcode = -1;
+ if (!found) {
+ printk(KERN_ERR "raw1394: arm_read FAILED addr_entry not found"
+ " -> rcode_address_error\n");
+ spin_unlock(&host_info_lock);
+ return (RCODE_ADDRESS_ERROR);
+ } else {
+ DBGMSG("arm_read addr_entry FOUND");
+ }
+ if (arm_addr->rec_length < length) {
+ DBGMSG("arm_read blocklength too big -> rcode_data_error");
+ rcode = RCODE_DATA_ERROR; /* hardware error, data is unavailable */
+ }
+ if (rcode == -1) {
+ if (arm_addr->access_rights & ARM_READ) {
+ if (!(arm_addr->client_transactions & ARM_READ)) {
+ memcpy(buffer,
+ (arm_addr->addr_space_buffer) + (addr -
+ (arm_addr->
+ start)),
+ length);
+ DBGMSG("arm_read -> (rcode_complete)");
+ rcode = RCODE_COMPLETE;
+ }
+ } else {
+ rcode = RCODE_TYPE_ERROR; /* function not allowed */
+ DBGMSG("arm_read -> rcode_type_error (access denied)");
+ }
+ }
+ if (arm_addr->notification_options & ARM_READ) {
+ DBGMSG("arm_read -> entering notification-section");
+ req = __alloc_pending_request(SLAB_ATOMIC);
+ if (!req) {
+ DBGMSG("arm_read -> rcode_conflict_error");
+ spin_unlock(&host_info_lock);
+ return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected.
+ The request may be retried */
+ }
+ if (rcode == RCODE_COMPLETE) {
+ size =
+ sizeof(struct arm_request) +
+ sizeof(struct arm_response) +
+ length * sizeof(byte_t) +
+ sizeof(struct arm_request_response);
+ } else {
+ size =
+ sizeof(struct arm_request) +
+ sizeof(struct arm_response) +
+ sizeof(struct arm_request_response);
+ }
+ req->data = kmalloc(size, SLAB_ATOMIC);
+ if (!(req->data)) {
+ free_pending_request(req);
+ DBGMSG("arm_read -> rcode_conflict_error");
+ spin_unlock(&host_info_lock);
+ return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected.
+ The request may be retried */
+ }
+ req->free_data = 1;
+ req->file_info = fi;
+ req->req.type = RAW1394_REQ_ARM;
+ req->req.generation = get_hpsb_generation(host);
+ req->req.misc =
+ (((length << 16) & (0xFFFF0000)) | (ARM_READ & 0xFF));
+ req->req.tag = arm_addr->arm_tag;
+ req->req.recvb = arm_addr->recvb;
+ req->req.length = size;
+ arm_req_resp = (struct arm_request_response *)(req->data);
+ arm_req = (struct arm_request *)((byte_t *) (req->data) +
+ (sizeof
+ (struct
+ arm_request_response)));
+ arm_resp =
+ (struct arm_response *)((byte_t *) (arm_req) +
+ (sizeof(struct arm_request)));
+ arm_req->buffer = NULL;
+ arm_resp->buffer = NULL;
+ if (rcode == RCODE_COMPLETE) {
+ byte_t *buf =
+ (byte_t *) arm_resp + sizeof(struct arm_response);
+ memcpy(buf,
+ (arm_addr->addr_space_buffer) + (addr -
+ (arm_addr->
+ start)),
+ length);
+ arm_resp->buffer =
+ int2ptr((arm_addr->recvb) +
+ sizeof(struct arm_request_response) +
+ sizeof(struct arm_request) +
+ sizeof(struct arm_response));
+ }
+ arm_resp->buffer_length =
+ (rcode == RCODE_COMPLETE) ? length : 0;
+ arm_resp->response_code = rcode;
+ arm_req->buffer_length = 0;
+ arm_req->generation = req->req.generation;
+ arm_req->extended_transaction_code = 0;
+ arm_req->destination_offset = addr;
+ arm_req->source_nodeid = nodeid;
+ arm_req->destination_nodeid = host->node_id;
+ arm_req->tlabel = (flags >> 10) & 0x3f;
+ arm_req->tcode = (flags >> 4) & 0x0f;
+ arm_req_resp->request = int2ptr((arm_addr->recvb) +
+ sizeof(struct
+ arm_request_response));
+ arm_req_resp->response =
+ int2ptr((arm_addr->recvb) +
+ sizeof(struct arm_request_response) +
+ sizeof(struct arm_request));
+ queue_complete_req(req);
+ }
+ spin_unlock(&host_info_lock);
+ return (rcode);
}
-static int arm_write (struct hpsb_host *host, int nodeid, int destid,
- quadlet_t *data, u64 addr, size_t length, u16 flags)
+static int arm_write(struct hpsb_host *host, int nodeid, int destid,
+ quadlet_t * data, u64 addr, size_t length, u16 flags)
{
- struct pending_request *req;
- struct host_info *hi;
- struct file_info *fi = NULL;
- struct list_head *entry;
- struct arm_addr *arm_addr = NULL;
- struct arm_request *arm_req = NULL;
- struct arm_response *arm_resp = NULL;
- int found=0, size=0, rcode=-1, length_conflict=0;
- struct arm_request_response *arm_req_resp = NULL;
-
- DBGMSG("arm_write called by node: %X"
- "addr: %4.4x %8.8x length: %Zu", nodeid,
- (u16) ((addr >>32) & 0xFFFF), (u32) (addr & 0xFFFFFFFF),
- length);
- spin_lock(&host_info_lock);
- hi = find_host_info(host); /* search address-entry */
- if (hi != NULL) {
- list_for_each_entry(fi, &hi->file_info_list, list) {
- entry = fi->addr_list.next;
- while (entry != &(fi->addr_list)) {
- arm_addr = list_entry(entry, struct arm_addr, addr_list);
- if (((arm_addr->start) <= (addr)) &&
- ((arm_addr->end) >= (addr+length))) {
- found = 1;
- break;
- }
- entry = entry->next;
- }
- if (found) {
- break;
- }
- }
- }
- rcode = -1;
- if (!found) {
- printk(KERN_ERR "raw1394: arm_write FAILED addr_entry not found"
- " -> rcode_address_error\n");
- spin_unlock(&host_info_lock);
- return (RCODE_ADDRESS_ERROR);
- } else {
- DBGMSG("arm_write addr_entry FOUND");
- }
- if (arm_addr->rec_length < length) {
- DBGMSG("arm_write blocklength too big -> rcode_data_error");
- length_conflict = 1;
- rcode = RCODE_DATA_ERROR; /* hardware error, data is unavailable */
- }
- if (rcode == -1) {
- if (arm_addr->access_rights & ARM_WRITE) {
- if (!(arm_addr->client_transactions & ARM_WRITE)) {
- memcpy((arm_addr->addr_space_buffer)+(addr-(arm_addr->start)),
- data, length);
- DBGMSG("arm_write -> (rcode_complete)");
- rcode = RCODE_COMPLETE;
- }
- } else {
- rcode = RCODE_TYPE_ERROR; /* function not allowed */
- DBGMSG("arm_write -> rcode_type_error (access denied)");
- }
- }
- if (arm_addr->notification_options & ARM_WRITE) {
- DBGMSG("arm_write -> entering notification-section");
- req = __alloc_pending_request(SLAB_ATOMIC);
- if (!req) {
- DBGMSG("arm_write -> rcode_conflict_error");
- spin_unlock(&host_info_lock);
- return(RCODE_CONFLICT_ERROR); /* A resource conflict was detected.
- The request my be retried */
- }
- size = sizeof(struct arm_request)+sizeof(struct arm_response) +
- (length) * sizeof(byte_t) +
- sizeof (struct arm_request_response);
- req->data = kmalloc(size, SLAB_ATOMIC);
- if (!(req->data)) {
- free_pending_request(req);
- DBGMSG("arm_write -> rcode_conflict_error");
- spin_unlock(&host_info_lock);
- return(RCODE_CONFLICT_ERROR); /* A resource conflict was detected.
- The request may be retried */
- }
- req->free_data=1;
- req->file_info = fi;
- req->req.type = RAW1394_REQ_ARM;
- req->req.generation = get_hpsb_generation(host);
- req->req.misc = ( ((length << 16) & (0xFFFF0000)) | (ARM_WRITE & 0xFF));
- req->req.tag = arm_addr->arm_tag;
- req->req.recvb = arm_addr->recvb;
- req->req.length = size;
- arm_req_resp = (struct arm_request_response *) (req->data);
- arm_req = (struct arm_request *) ((byte_t *)(req->data) +
- (sizeof (struct arm_request_response)));
- arm_resp = (struct arm_response *) ((byte_t *)(arm_req) +
- (sizeof(struct arm_request)));
- arm_resp->buffer = NULL;
- memcpy ((byte_t *)arm_resp + sizeof(struct arm_response),
- data, length);
- arm_req->buffer = int2ptr((arm_addr->recvb) +
- sizeof (struct arm_request_response) +
- sizeof (struct arm_request) +
- sizeof (struct arm_response));
- arm_req->buffer_length = length;
- arm_req->generation = req->req.generation;
- arm_req->extended_transaction_code = 0;
- arm_req->destination_offset = addr;
- arm_req->source_nodeid = nodeid;
- arm_req->destination_nodeid = destid;
- arm_req->tlabel = (flags >> 10) & 0x3f;
- arm_req->tcode = (flags >> 4) & 0x0f;
- arm_resp->buffer_length = 0;
- arm_resp->response_code = rcode;
- arm_req_resp->request = int2ptr((arm_addr->recvb) +
- sizeof (struct arm_request_response));
- arm_req_resp->response = int2ptr((arm_addr->recvb) +
- sizeof (struct arm_request_response) +
- sizeof (struct arm_request));
- queue_complete_req(req);
- }
- spin_unlock(&host_info_lock);
- return(rcode);
+ struct pending_request *req;
+ struct host_info *hi;
+ struct file_info *fi = NULL;
+ struct list_head *entry;
+ struct arm_addr *arm_addr = NULL;
+ struct arm_request *arm_req = NULL;
+ struct arm_response *arm_resp = NULL;
+ int found = 0, size = 0, rcode = -1, length_conflict = 0;
+ struct arm_request_response *arm_req_resp = NULL;
+
+ DBGMSG("arm_write called by node: %X"
+ "addr: %4.4x %8.8x length: %Zu", nodeid,
+ (u16) ((addr >> 32) & 0xFFFF), (u32) (addr & 0xFFFFFFFF),
+ length);
+ spin_lock(&host_info_lock);
+ hi = find_host_info(host); /* search address-entry */
+ if (hi != NULL) {
+ list_for_each_entry(fi, &hi->file_info_list, list) {
+ entry = fi->addr_list.next;
+ while (entry != &(fi->addr_list)) {
+ arm_addr =
+ list_entry(entry, struct arm_addr,
+ addr_list);
+ if (((arm_addr->start) <= (addr))
+ && ((arm_addr->end) >= (addr + length))) {
+ found = 1;
+ break;
+ }
+ entry = entry->next;
+ }
+ if (found) {
+ break;
+ }
+ }
+ }
+ rcode = -1;
+ if (!found) {
+ printk(KERN_ERR "raw1394: arm_write FAILED addr_entry not found"
+ " -> rcode_address_error\n");
+ spin_unlock(&host_info_lock);
+ return (RCODE_ADDRESS_ERROR);
+ } else {
+ DBGMSG("arm_write addr_entry FOUND");
+ }
+ if (arm_addr->rec_length < length) {
+ DBGMSG("arm_write blocklength too big -> rcode_data_error");
+ length_conflict = 1;
+ rcode = RCODE_DATA_ERROR; /* hardware error, data is unavailable */
+ }
+ if (rcode == -1) {
+ if (arm_addr->access_rights & ARM_WRITE) {
+ if (!(arm_addr->client_transactions & ARM_WRITE)) {
+ memcpy((arm_addr->addr_space_buffer) +
+ (addr - (arm_addr->start)), data,
+ length);
+ DBGMSG("arm_write -> (rcode_complete)");
+ rcode = RCODE_COMPLETE;
+ }
+ } else {
+ rcode = RCODE_TYPE_ERROR; /* function not allowed */
+ DBGMSG("arm_write -> rcode_type_error (access denied)");
+ }
+ }
+ if (arm_addr->notification_options & ARM_WRITE) {
+ DBGMSG("arm_write -> entering notification-section");
+ req = __alloc_pending_request(SLAB_ATOMIC);
+ if (!req) {
+ DBGMSG("arm_write -> rcode_conflict_error");
+ spin_unlock(&host_info_lock);
+ return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected.
+ The request my be retried */
+ }
+ size =
+ sizeof(struct arm_request) + sizeof(struct arm_response) +
+ (length) * sizeof(byte_t) +
+ sizeof(struct arm_request_response);
+ req->data = kmalloc(size, SLAB_ATOMIC);
+ if (!(req->data)) {
+ free_pending_request(req);
+ DBGMSG("arm_write -> rcode_conflict_error");
+ spin_unlock(&host_info_lock);
+ return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected.
+ The request may be retried */
+ }
+ req->free_data = 1;
+ req->file_info = fi;
+ req->req.type = RAW1394_REQ_ARM;
+ req->req.generation = get_hpsb_generation(host);
+ req->req.misc =
+ (((length << 16) & (0xFFFF0000)) | (ARM_WRITE & 0xFF));
+ req->req.tag = arm_addr->arm_tag;
+ req->req.recvb = arm_addr->recvb;
+ req->req.length = size;
+ arm_req_resp = (struct arm_request_response *)(req->data);
+ arm_req = (struct arm_request *)((byte_t *) (req->data) +
+ (sizeof
+ (struct
+ arm_request_response)));
+ arm_resp =
+ (struct arm_response *)((byte_t *) (arm_req) +
+ (sizeof(struct arm_request)));
+ arm_resp->buffer = NULL;
+ memcpy((byte_t *) arm_resp + sizeof(struct arm_response),
+ data, length);
+ arm_req->buffer = int2ptr((arm_addr->recvb) +
+ sizeof(struct arm_request_response) +
+ sizeof(struct arm_request) +
+ sizeof(struct arm_response));
+ arm_req->buffer_length = length;
+ arm_req->generation = req->req.generation;
+ arm_req->extended_transaction_code = 0;
+ arm_req->destination_offset = addr;
+ arm_req->source_nodeid = nodeid;
+ arm_req->destination_nodeid = destid;
+ arm_req->tlabel = (flags >> 10) & 0x3f;
+ arm_req->tcode = (flags >> 4) & 0x0f;
+ arm_resp->buffer_length = 0;
+ arm_resp->response_code = rcode;
+ arm_req_resp->request = int2ptr((arm_addr->recvb) +
+ sizeof(struct
+ arm_request_response));
+ arm_req_resp->response =
+ int2ptr((arm_addr->recvb) +
+ sizeof(struct arm_request_response) +
+ sizeof(struct arm_request));
+ queue_complete_req(req);
+ }
+ spin_unlock(&host_info_lock);
+ return (rcode);
}
-static int arm_lock (struct hpsb_host *host, int nodeid, quadlet_t *store,
- u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode, u16 flags)
+static int arm_lock(struct hpsb_host *host, int nodeid, quadlet_t * store,
+ u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode,
+ u16 flags)
{
- struct pending_request *req;
- struct host_info *hi;
- struct file_info *fi = NULL;
- struct list_head *entry;
- struct arm_addr *arm_addr = NULL;
- struct arm_request *arm_req = NULL;
- struct arm_response *arm_resp = NULL;
- int found=0, size=0, rcode=-1;
- quadlet_t old, new;
- struct arm_request_response *arm_req_resp = NULL;
-
- if (((ext_tcode & 0xFF) == EXTCODE_FETCH_ADD) ||
- ((ext_tcode & 0xFF) == EXTCODE_LITTLE_ADD)) {
- DBGMSG("arm_lock called by node: %X "
- "addr: %4.4x %8.8x extcode: %2.2X data: %8.8X",
- nodeid, (u16) ((addr >>32) & 0xFFFF), (u32) (addr & 0xFFFFFFFF),
- ext_tcode & 0xFF , be32_to_cpu(data));
- } else {
- DBGMSG("arm_lock called by node: %X "
- "addr: %4.4x %8.8x extcode: %2.2X data: %8.8X arg: %8.8X",
- nodeid, (u16) ((addr >>32) & 0xFFFF), (u32) (addr & 0xFFFFFFFF),
- ext_tcode & 0xFF , be32_to_cpu(data), be32_to_cpu(arg));
- }
- spin_lock(&host_info_lock);
- hi = find_host_info(host); /* search address-entry */
- if (hi != NULL) {
- list_for_each_entry(fi, &hi->file_info_list, list) {
- entry = fi->addr_list.next;
- while (entry != &(fi->addr_list)) {
- arm_addr = list_entry(entry, struct arm_addr, addr_list);
- if (((arm_addr->start) <= (addr)) &&
- ((arm_addr->end) >= (addr+sizeof(*store)))) {
- found = 1;
- break;
- }
- entry = entry->next;
- }
- if (found) {
- break;
- }
- }
- }
- rcode = -1;
- if (!found) {
- printk(KERN_ERR "raw1394: arm_lock FAILED addr_entry not found"
- " -> rcode_address_error\n");
- spin_unlock(&host_info_lock);
- return (RCODE_ADDRESS_ERROR);
- } else {
- DBGMSG("arm_lock addr_entry FOUND");
- }
- if (rcode == -1) {
- if (arm_addr->access_rights & ARM_LOCK) {
- if (!(arm_addr->client_transactions & ARM_LOCK)) {
- memcpy(&old,(arm_addr->addr_space_buffer)+(addr-(arm_addr->start)),
- sizeof(old));
- switch (ext_tcode) {
- case (EXTCODE_MASK_SWAP):
- new = data | (old & ~arg);
- break;
- case (EXTCODE_COMPARE_SWAP):
- if (old == arg) {
- new = data;
- } else {
- new = old;
- }
- break;
- case (EXTCODE_FETCH_ADD):
- new = cpu_to_be32(be32_to_cpu(data) + be32_to_cpu(old));
- break;
- case (EXTCODE_LITTLE_ADD):
- new = cpu_to_le32(le32_to_cpu(data) + le32_to_cpu(old));
- break;
- case (EXTCODE_BOUNDED_ADD):
- if (old != arg) {
- new = cpu_to_be32(be32_to_cpu(data) +
- be32_to_cpu(old));
- } else {
- new = old;
- }
- break;
- case (EXTCODE_WRAP_ADD):
- if (old != arg) {
- new = cpu_to_be32(be32_to_cpu(data) +
- be32_to_cpu(old));
- } else {
- new = data;
- }
- break;
- default:
- rcode = RCODE_TYPE_ERROR; /* function not allowed */
- printk(KERN_ERR "raw1394: arm_lock FAILED "
- "ext_tcode not allowed -> rcode_type_error\n");
- break;
- } /*switch*/
- if (rcode == -1) {
- DBGMSG("arm_lock -> (rcode_complete)");
- rcode = RCODE_COMPLETE;
- memcpy (store, &old, sizeof(*store));
- memcpy ((arm_addr->addr_space_buffer)+
- (addr-(arm_addr->start)),
- &new, sizeof(*store));
- }
- }
- } else {
- rcode = RCODE_TYPE_ERROR; /* function not allowed */
- DBGMSG("arm_lock -> rcode_type_error (access denied)");
- }
- }
- if (arm_addr->notification_options & ARM_LOCK) {
+ struct pending_request *req;
+ struct host_info *hi;
+ struct file_info *fi = NULL;
+ struct list_head *entry;
+ struct arm_addr *arm_addr = NULL;
+ struct arm_request *arm_req = NULL;
+ struct arm_response *arm_resp = NULL;
+ int found = 0, size = 0, rcode = -1;
+ quadlet_t old, new;
+ struct arm_request_response *arm_req_resp = NULL;
+
+ if (((ext_tcode & 0xFF) == EXTCODE_FETCH_ADD) ||
+ ((ext_tcode & 0xFF) == EXTCODE_LITTLE_ADD)) {
+ DBGMSG("arm_lock called by node: %X "
+ "addr: %4.4x %8.8x extcode: %2.2X data: %8.8X",
+ nodeid, (u16) ((addr >> 32) & 0xFFFF),
+ (u32) (addr & 0xFFFFFFFF), ext_tcode & 0xFF,
+ be32_to_cpu(data));
+ } else {
+ DBGMSG("arm_lock called by node: %X "
+ "addr: %4.4x %8.8x extcode: %2.2X data: %8.8X arg: %8.8X",
+ nodeid, (u16) ((addr >> 32) & 0xFFFF),
+ (u32) (addr & 0xFFFFFFFF), ext_tcode & 0xFF,
+ be32_to_cpu(data), be32_to_cpu(arg));
+ }
+ spin_lock(&host_info_lock);
+ hi = find_host_info(host); /* search address-entry */
+ if (hi != NULL) {
+ list_for_each_entry(fi, &hi->file_info_list, list) {
+ entry = fi->addr_list.next;
+ while (entry != &(fi->addr_list)) {
+ arm_addr =
+ list_entry(entry, struct arm_addr,
+ addr_list);
+ if (((arm_addr->start) <= (addr))
+ && ((arm_addr->end) >=
+ (addr + sizeof(*store)))) {
+ found = 1;
+ break;
+ }
+ entry = entry->next;
+ }
+ if (found) {
+ break;
+ }
+ }
+ }
+ rcode = -1;
+ if (!found) {
+ printk(KERN_ERR "raw1394: arm_lock FAILED addr_entry not found"
+ " -> rcode_address_error\n");
+ spin_unlock(&host_info_lock);
+ return (RCODE_ADDRESS_ERROR);
+ } else {
+ DBGMSG("arm_lock addr_entry FOUND");
+ }
+ if (rcode == -1) {
+ if (arm_addr->access_rights & ARM_LOCK) {
+ if (!(arm_addr->client_transactions & ARM_LOCK)) {
+ memcpy(&old,
+ (arm_addr->addr_space_buffer) + (addr -
+ (arm_addr->
+ start)),
+ sizeof(old));
+ switch (ext_tcode) {
+ case (EXTCODE_MASK_SWAP):
+ new = data | (old & ~arg);
+ break;
+ case (EXTCODE_COMPARE_SWAP):
+ if (old == arg) {
+ new = data;
+ } else {
+ new = old;
+ }
+ break;
+ case (EXTCODE_FETCH_ADD):
+ new =
+ cpu_to_be32(be32_to_cpu(data) +
+ be32_to_cpu(old));
+ break;
+ case (EXTCODE_LITTLE_ADD):
+ new =
+ cpu_to_le32(le32_to_cpu(data) +
+ le32_to_cpu(old));
+ break;
+ case (EXTCODE_BOUNDED_ADD):
+ if (old != arg) {
+ new =
+ cpu_to_be32(be32_to_cpu
+ (data) +
+ be32_to_cpu
+ (old));
+ } else {
+ new = old;
+ }
+ break;
+ case (EXTCODE_WRAP_ADD):
+ if (old != arg) {
+ new =
+ cpu_to_be32(be32_to_cpu
+ (data) +
+ be32_to_cpu
+ (old));
+ } else {
+ new = data;
+ }
+ break;
+ default:
+ rcode = RCODE_TYPE_ERROR; /* function not allowed */
+ printk(KERN_ERR
+ "raw1394: arm_lock FAILED "
+ "ext_tcode not allowed -> rcode_type_error\n");
+ break;
+ } /*switch */
+ if (rcode == -1) {
+ DBGMSG("arm_lock -> (rcode_complete)");
+ rcode = RCODE_COMPLETE;
+ memcpy(store, &old, sizeof(*store));
+ memcpy((arm_addr->addr_space_buffer) +
+ (addr - (arm_addr->start)),
+ &new, sizeof(*store));
+ }
+ }
+ } else {
+ rcode = RCODE_TYPE_ERROR; /* function not allowed */
+ DBGMSG("arm_lock -> rcode_type_error (access denied)");
+ }
+ }
+ if (arm_addr->notification_options & ARM_LOCK) {
byte_t *buf1, *buf2;
- DBGMSG("arm_lock -> entering notification-section");
- req = __alloc_pending_request(SLAB_ATOMIC);
- if (!req) {
- DBGMSG("arm_lock -> rcode_conflict_error");
- spin_unlock(&host_info_lock);
- return(RCODE_CONFLICT_ERROR); /* A resource conflict was detected.
- The request may be retried */
- }
- size = sizeof(struct arm_request)+sizeof(struct arm_response) +
- 3 * sizeof(*store) +
- sizeof (struct arm_request_response); /* maximum */
- req->data = kmalloc(size, SLAB_ATOMIC);
- if (!(req->data)) {
- free_pending_request(req);
- DBGMSG("arm_lock -> rcode_conflict_error");
- spin_unlock(&host_info_lock);
- return(RCODE_CONFLICT_ERROR); /* A resource conflict was detected.
- The request may be retried */
- }
- req->free_data=1;
- arm_req_resp = (struct arm_request_response *) (req->data);
- arm_req = (struct arm_request *) ((byte_t *)(req->data) +
- (sizeof (struct arm_request_response)));
- arm_resp = (struct arm_response *) ((byte_t *)(arm_req) +
- (sizeof(struct arm_request)));
- buf1 = (byte_t *)arm_resp + sizeof(struct arm_response);
+ DBGMSG("arm_lock -> entering notification-section");
+ req = __alloc_pending_request(SLAB_ATOMIC);
+ if (!req) {
+ DBGMSG("arm_lock -> rcode_conflict_error");
+ spin_unlock(&host_info_lock);
+ return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected.
+ The request may be retried */
+ }
+ size = sizeof(struct arm_request) + sizeof(struct arm_response) + 3 * sizeof(*store) + sizeof(struct arm_request_response); /* maximum */
+ req->data = kmalloc(size, SLAB_ATOMIC);
+ if (!(req->data)) {
+ free_pending_request(req);
+ DBGMSG("arm_lock -> rcode_conflict_error");
+ spin_unlock(&host_info_lock);
+ return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected.
+ The request may be retried */
+ }
+ req->free_data = 1;
+ arm_req_resp = (struct arm_request_response *)(req->data);
+ arm_req = (struct arm_request *)((byte_t *) (req->data) +
+ (sizeof
+ (struct
+ arm_request_response)));
+ arm_resp =
+ (struct arm_response *)((byte_t *) (arm_req) +
+ (sizeof(struct arm_request)));
+ buf1 = (byte_t *) arm_resp + sizeof(struct arm_response);
buf2 = buf1 + 2 * sizeof(*store);
- if ((ext_tcode == EXTCODE_FETCH_ADD) ||
- (ext_tcode == EXTCODE_LITTLE_ADD)) {
- arm_req->buffer_length = sizeof(*store);
- memcpy (buf1, &data, sizeof(*store));
-
- } else {
- arm_req->buffer_length = 2 * sizeof(*store);
- memcpy (buf1, &arg, sizeof(*store));
- memcpy (buf1 + sizeof(*store), &data, sizeof(*store));
- }
- if (rcode == RCODE_COMPLETE) {
- arm_resp->buffer_length = sizeof(*store);
- memcpy (buf2, &old, sizeof(*store));
- } else {
- arm_resp->buffer_length = 0;
- }
- req->file_info = fi;
- req->req.type = RAW1394_REQ_ARM;
- req->req.generation = get_hpsb_generation(host);
- req->req.misc = ( (((sizeof(*store)) << 16) & (0xFFFF0000)) |
- (ARM_LOCK & 0xFF));
- req->req.tag = arm_addr->arm_tag;
- req->req.recvb = arm_addr->recvb;
- req->req.length = size;
- arm_req->generation = req->req.generation;
- arm_req->extended_transaction_code = ext_tcode;
- arm_req->destination_offset = addr;
- arm_req->source_nodeid = nodeid;
- arm_req->destination_nodeid = host->node_id;
- arm_req->tlabel = (flags >> 10) & 0x3f;
- arm_req->tcode = (flags >> 4) & 0x0f;
- arm_resp->response_code = rcode;
- arm_req_resp->request = int2ptr((arm_addr->recvb) +
- sizeof (struct arm_request_response));
- arm_req_resp->response = int2ptr((arm_addr->recvb) +
- sizeof (struct arm_request_response) +
- sizeof (struct arm_request));
- arm_req->buffer = int2ptr((arm_addr->recvb) +
- sizeof (struct arm_request_response) +
- sizeof (struct arm_request) +
- sizeof (struct arm_response));
- arm_resp->buffer = int2ptr((arm_addr->recvb) +
- sizeof (struct arm_request_response) +
- sizeof (struct arm_request) +
- sizeof (struct arm_response) +
- 2* sizeof (*store));
- queue_complete_req(req);
- }
- spin_unlock(&host_info_lock);
- return(rcode);
+ if ((ext_tcode == EXTCODE_FETCH_ADD) ||
+ (ext_tcode == EXTCODE_LITTLE_ADD)) {
+ arm_req->buffer_length = sizeof(*store);
+ memcpy(buf1, &data, sizeof(*store));
+
+ } else {
+ arm_req->buffer_length = 2 * sizeof(*store);
+ memcpy(buf1, &arg, sizeof(*store));
+ memcpy(buf1 + sizeof(*store), &data, sizeof(*store));
+ }
+ if (rcode == RCODE_COMPLETE) {
+ arm_resp->buffer_length = sizeof(*store);
+ memcpy(buf2, &old, sizeof(*store));
+ } else {
+ arm_resp->buffer_length = 0;
+ }
+ req->file_info = fi;
+ req->req.type = RAW1394_REQ_ARM;
+ req->req.generation = get_hpsb_generation(host);
+ req->req.misc = ((((sizeof(*store)) << 16) & (0xFFFF0000)) |
+ (ARM_LOCK & 0xFF));
+ req->req.tag = arm_addr->arm_tag;
+ req->req.recvb = arm_addr->recvb;
+ req->req.length = size;
+ arm_req->generation = req->req.generation;
+ arm_req->extended_transaction_code = ext_tcode;
+ arm_req->destination_offset = addr;
+ arm_req->source_nodeid = nodeid;
+ arm_req->destination_nodeid = host->node_id;
+ arm_req->tlabel = (flags >> 10) & 0x3f;
+ arm_req->tcode = (flags >> 4) & 0x0f;
+ arm_resp->response_code = rcode;
+ arm_req_resp->request = int2ptr((arm_addr->recvb) +
+ sizeof(struct
+ arm_request_response));
+ arm_req_resp->response =
+ int2ptr((arm_addr->recvb) +
+ sizeof(struct arm_request_response) +
+ sizeof(struct arm_request));
+ arm_req->buffer =
+ int2ptr((arm_addr->recvb) +
+ sizeof(struct arm_request_response) +
+ sizeof(struct arm_request) +
+ sizeof(struct arm_response));
+ arm_resp->buffer =
+ int2ptr((arm_addr->recvb) +
+ sizeof(struct arm_request_response) +
+ sizeof(struct arm_request) +
+ sizeof(struct arm_response) + 2 * sizeof(*store));
+ queue_complete_req(req);
+ }
+ spin_unlock(&host_info_lock);
+ return (rcode);
}
-static int arm_lock64 (struct hpsb_host *host, int nodeid, octlet_t *store,
- u64 addr, octlet_t data, octlet_t arg, int ext_tcode, u16 flags)
+static int arm_lock64(struct hpsb_host *host, int nodeid, octlet_t * store,
+ u64 addr, octlet_t data, octlet_t arg, int ext_tcode,
+ u16 flags)
{
- struct pending_request *req;
- struct host_info *hi;
- struct file_info *fi = NULL;
- struct list_head *entry;
- struct arm_addr *arm_addr = NULL;
- struct arm_request *arm_req = NULL;
- struct arm_response *arm_resp = NULL;
- int found=0, size=0, rcode=-1;
- octlet_t old, new;
- struct arm_request_response *arm_req_resp = NULL;
-
- if (((ext_tcode & 0xFF) == EXTCODE_FETCH_ADD) ||
- ((ext_tcode & 0xFF) == EXTCODE_LITTLE_ADD)) {
- DBGMSG("arm_lock64 called by node: %X "
- "addr: %4.4x %8.8x extcode: %2.2X data: %8.8X %8.8X ",
- nodeid, (u16) ((addr >>32) & 0xFFFF),
- (u32) (addr & 0xFFFFFFFF),
- ext_tcode & 0xFF ,
- (u32) ((be64_to_cpu(data) >> 32) & 0xFFFFFFFF),
- (u32) (be64_to_cpu(data) & 0xFFFFFFFF));
- } else {
- DBGMSG("arm_lock64 called by node: %X "
- "addr: %4.4x %8.8x extcode: %2.2X data: %8.8X %8.8X arg: "
- "%8.8X %8.8X ",
- nodeid, (u16) ((addr >>32) & 0xFFFF),
- (u32) (addr & 0xFFFFFFFF),
- ext_tcode & 0xFF ,
- (u32) ((be64_to_cpu(data) >> 32) & 0xFFFFFFFF),
- (u32) (be64_to_cpu(data) & 0xFFFFFFFF),
- (u32) ((be64_to_cpu(arg) >> 32) & 0xFFFFFFFF),
- (u32) (be64_to_cpu(arg) & 0xFFFFFFFF));
- }
- spin_lock(&host_info_lock);
- hi = find_host_info(host); /* search addressentry in file_info's for host */
- if (hi != NULL) {
- list_for_each_entry(fi, &hi->file_info_list, list) {
- entry = fi->addr_list.next;
- while (entry != &(fi->addr_list)) {
- arm_addr = list_entry(entry, struct arm_addr, addr_list);
- if (((arm_addr->start) <= (addr)) &&
- ((arm_addr->end) >= (addr+sizeof(*store)))) {
- found = 1;
- break;
- }
- entry = entry->next;
- }
- if (found) {
- break;
- }
- }
- }
- rcode = -1;
- if (!found) {
- printk(KERN_ERR "raw1394: arm_lock64 FAILED addr_entry not found"
- " -> rcode_address_error\n");
- spin_unlock(&host_info_lock);
- return (RCODE_ADDRESS_ERROR);
- } else {
- DBGMSG("arm_lock64 addr_entry FOUND");
- }
- if (rcode == -1) {
- if (arm_addr->access_rights & ARM_LOCK) {
- if (!(arm_addr->client_transactions & ARM_LOCK)) {
- memcpy(&old,(arm_addr->addr_space_buffer)+(addr-(arm_addr->start)),
- sizeof(old));
- switch (ext_tcode) {
- case (EXTCODE_MASK_SWAP):
- new = data | (old & ~arg);
- break;
- case (EXTCODE_COMPARE_SWAP):
- if (old == arg) {
- new = data;
- } else {
- new = old;
- }
- break;
- case (EXTCODE_FETCH_ADD):
- new = cpu_to_be64(be64_to_cpu(data) + be64_to_cpu(old));
- break;
- case (EXTCODE_LITTLE_ADD):
- new = cpu_to_le64(le64_to_cpu(data) + le64_to_cpu(old));
- break;
- case (EXTCODE_BOUNDED_ADD):
- if (old != arg) {
- new = cpu_to_be64(be64_to_cpu(data) +
- be64_to_cpu(old));
- } else {
- new = old;
- }
- break;
- case (EXTCODE_WRAP_ADD):
- if (old != arg) {
- new = cpu_to_be64(be64_to_cpu(data) +
- be64_to_cpu(old));
- } else {
- new = data;
- }
- break;
- default:
- printk(KERN_ERR "raw1394: arm_lock64 FAILED "
- "ext_tcode not allowed -> rcode_type_error\n");
- rcode = RCODE_TYPE_ERROR; /* function not allowed */
- break;
- } /*switch*/
- if (rcode == -1) {
- DBGMSG("arm_lock64 -> (rcode_complete)");
- rcode = RCODE_COMPLETE;
- memcpy (store, &old, sizeof(*store));
- memcpy ((arm_addr->addr_space_buffer)+
- (addr-(arm_addr->start)),
- &new, sizeof(*store));
- }
- }
- } else {
- rcode = RCODE_TYPE_ERROR; /* function not allowed */
- DBGMSG("arm_lock64 -> rcode_type_error (access denied)");
- }
- }
- if (arm_addr->notification_options & ARM_LOCK) {
+ struct pending_request *req;
+ struct host_info *hi;
+ struct file_info *fi = NULL;
+ struct list_head *entry;
+ struct arm_addr *arm_addr = NULL;
+ struct arm_request *arm_req = NULL;
+ struct arm_response *arm_resp = NULL;
+ int found = 0, size = 0, rcode = -1;
+ octlet_t old, new;
+ struct arm_request_response *arm_req_resp = NULL;
+
+ if (((ext_tcode & 0xFF) == EXTCODE_FETCH_ADD) ||
+ ((ext_tcode & 0xFF) == EXTCODE_LITTLE_ADD)) {
+ DBGMSG("arm_lock64 called by node: %X "
+ "addr: %4.4x %8.8x extcode: %2.2X data: %8.8X %8.8X ",
+ nodeid, (u16) ((addr >> 32) & 0xFFFF),
+ (u32) (addr & 0xFFFFFFFF),
+ ext_tcode & 0xFF,
+ (u32) ((be64_to_cpu(data) >> 32) & 0xFFFFFFFF),
+ (u32) (be64_to_cpu(data) & 0xFFFFFFFF));
+ } else {
+ DBGMSG("arm_lock64 called by node: %X "
+ "addr: %4.4x %8.8x extcode: %2.2X data: %8.8X %8.8X arg: "
+ "%8.8X %8.8X ",
+ nodeid, (u16) ((addr >> 32) & 0xFFFF),
+ (u32) (addr & 0xFFFFFFFF),
+ ext_tcode & 0xFF,
+ (u32) ((be64_to_cpu(data) >> 32) & 0xFFFFFFFF),
+ (u32) (be64_to_cpu(data) & 0xFFFFFFFF),
+ (u32) ((be64_to_cpu(arg) >> 32) & 0xFFFFFFFF),
+ (u32) (be64_to_cpu(arg) & 0xFFFFFFFF));
+ }
+ spin_lock(&host_info_lock);
+ hi = find_host_info(host); /* search addressentry in file_info's for host */
+ if (hi != NULL) {
+ list_for_each_entry(fi, &hi->file_info_list, list) {
+ entry = fi->addr_list.next;
+ while (entry != &(fi->addr_list)) {
+ arm_addr =
+ list_entry(entry, struct arm_addr,
+ addr_list);
+ if (((arm_addr->start) <= (addr))
+ && ((arm_addr->end) >=
+ (addr + sizeof(*store)))) {
+ found = 1;
+ break;
+ }
+ entry = entry->next;
+ }
+ if (found) {
+ break;
+ }
+ }
+ }
+ rcode = -1;
+ if (!found) {
+ printk(KERN_ERR
+ "raw1394: arm_lock64 FAILED addr_entry not found"
+ " -> rcode_address_error\n");
+ spin_unlock(&host_info_lock);
+ return (RCODE_ADDRESS_ERROR);
+ } else {
+ DBGMSG("arm_lock64 addr_entry FOUND");
+ }
+ if (rcode == -1) {
+ if (arm_addr->access_rights & ARM_LOCK) {
+ if (!(arm_addr->client_transactions & ARM_LOCK)) {
+ memcpy(&old,
+ (arm_addr->addr_space_buffer) + (addr -
+ (arm_addr->
+ start)),
+ sizeof(old));
+ switch (ext_tcode) {
+ case (EXTCODE_MASK_SWAP):
+ new = data | (old & ~arg);
+ break;
+ case (EXTCODE_COMPARE_SWAP):
+ if (old == arg) {
+ new = data;
+ } else {
+ new = old;
+ }
+ break;
+ case (EXTCODE_FETCH_ADD):
+ new =
+ cpu_to_be64(be64_to_cpu(data) +
+ be64_to_cpu(old));
+ break;
+ case (EXTCODE_LITTLE_ADD):
+ new =
+ cpu_to_le64(le64_to_cpu(data) +
+ le64_to_cpu(old));
+ break;
+ case (EXTCODE_BOUNDED_ADD):
+ if (old != arg) {
+ new =
+ cpu_to_be64(be64_to_cpu
+ (data) +
+ be64_to_cpu
+ (old));
+ } else {
+ new = old;
+ }
+ break;
+ case (EXTCODE_WRAP_ADD):
+ if (old != arg) {
+ new =
+ cpu_to_be64(be64_to_cpu
+ (data) +
+ be64_to_cpu
+ (old));
+ } else {
+ new = data;
+ }
+ break;
+ default:
+ printk(KERN_ERR
+ "raw1394: arm_lock64 FAILED "
+ "ext_tcode not allowed -> rcode_type_error\n");
+ rcode = RCODE_TYPE_ERROR; /* function not allowed */
+ break;
+ } /*switch */
+ if (rcode == -1) {
+ DBGMSG
+ ("arm_lock64 -> (rcode_complete)");
+ rcode = RCODE_COMPLETE;
+ memcpy(store, &old, sizeof(*store));
+ memcpy((arm_addr->addr_space_buffer) +
+ (addr - (arm_addr->start)),
+ &new, sizeof(*store));
+ }
+ }
+ } else {
+ rcode = RCODE_TYPE_ERROR; /* function not allowed */
+ DBGMSG
+ ("arm_lock64 -> rcode_type_error (access denied)");
+ }
+ }
+ if (arm_addr->notification_options & ARM_LOCK) {
byte_t *buf1, *buf2;
- DBGMSG("arm_lock64 -> entering notification-section");
- req = __alloc_pending_request(SLAB_ATOMIC);
- if (!req) {
- spin_unlock(&host_info_lock);
- DBGMSG("arm_lock64 -> rcode_conflict_error");
- return(RCODE_CONFLICT_ERROR); /* A resource conflict was detected.
- The request may be retried */
- }
- size = sizeof(struct arm_request)+sizeof(struct arm_response) +
- 3 * sizeof(*store) +
- sizeof (struct arm_request_response); /* maximum */
- req->data = kmalloc(size, SLAB_ATOMIC);
- if (!(req->data)) {
- free_pending_request(req);
- spin_unlock(&host_info_lock);
- DBGMSG("arm_lock64 -> rcode_conflict_error");
- return(RCODE_CONFLICT_ERROR); /* A resource conflict was detected.
- The request may be retried */
- }
- req->free_data=1;
- arm_req_resp = (struct arm_request_response *) (req->data);
- arm_req = (struct arm_request *) ((byte_t *)(req->data) +
- (sizeof (struct arm_request_response)));
- arm_resp = (struct arm_response *) ((byte_t *)(arm_req) +
- (sizeof(struct arm_request)));
- buf1 = (byte_t *)arm_resp + sizeof(struct arm_response);
- buf2 = buf1 + 2 * sizeof(*store);
- if ((ext_tcode == EXTCODE_FETCH_ADD) ||
- (ext_tcode == EXTCODE_LITTLE_ADD)) {
- arm_req->buffer_length = sizeof(*store);
- memcpy (buf1, &data, sizeof(*store));
-
- } else {
- arm_req->buffer_length = 2 * sizeof(*store);
- memcpy (buf1, &arg, sizeof(*store));
- memcpy (buf1 + sizeof(*store), &data, sizeof(*store));
- }
- if (rcode == RCODE_COMPLETE) {
- arm_resp->buffer_length = sizeof(*store);
- memcpy (buf2, &old, sizeof(*store));
- } else {
- arm_resp->buffer_length = 0;
- }
- req->file_info = fi;
- req->req.type = RAW1394_REQ_ARM;
- req->req.generation = get_hpsb_generation(host);
- req->req.misc = ( (((sizeof(*store)) << 16) & (0xFFFF0000)) |
- (ARM_LOCK & 0xFF));
- req->req.tag = arm_addr->arm_tag;
- req->req.recvb = arm_addr->recvb;
- req->req.length = size;
- arm_req->generation = req->req.generation;
- arm_req->extended_transaction_code = ext_tcode;
- arm_req->destination_offset = addr;
- arm_req->source_nodeid = nodeid;
- arm_req->destination_nodeid = host->node_id;
- arm_req->tlabel = (flags >> 10) & 0x3f;
- arm_req->tcode = (flags >> 4) & 0x0f;
- arm_resp->response_code = rcode;
- arm_req_resp->request = int2ptr((arm_addr->recvb) +
- sizeof (struct arm_request_response));
- arm_req_resp->response = int2ptr((arm_addr->recvb) +
- sizeof (struct arm_request_response) +
- sizeof (struct arm_request));
- arm_req->buffer = int2ptr((arm_addr->recvb) +
- sizeof (struct arm_request_response) +
- sizeof (struct arm_request) +
- sizeof (struct arm_response));
- arm_resp->buffer = int2ptr((arm_addr->recvb) +
- sizeof (struct arm_request_response) +
- sizeof (struct arm_request) +
- sizeof (struct arm_response) +
- 2* sizeof (*store));
- queue_complete_req(req);
- }
- spin_unlock(&host_info_lock);
- return(rcode);
+ DBGMSG("arm_lock64 -> entering notification-section");
+ req = __alloc_pending_request(SLAB_ATOMIC);
+ if (!req) {
+ spin_unlock(&host_info_lock);
+ DBGMSG("arm_lock64 -> rcode_conflict_error");
+ return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected.
+ The request may be retried */
+ }
+ size = sizeof(struct arm_request) + sizeof(struct arm_response) + 3 * sizeof(*store) + sizeof(struct arm_request_response); /* maximum */
+ req->data = kmalloc(size, SLAB_ATOMIC);
+ if (!(req->data)) {
+ free_pending_request(req);
+ spin_unlock(&host_info_lock);
+ DBGMSG("arm_lock64 -> rcode_conflict_error");
+ return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected.
+ The request may be retried */
+ }
+ req->free_data = 1;
+ arm_req_resp = (struct arm_request_response *)(req->data);
+ arm_req = (struct arm_request *)((byte_t *) (req->data) +
+ (sizeof
+ (struct
+ arm_request_response)));
+ arm_resp =
+ (struct arm_response *)((byte_t *) (arm_req) +
+ (sizeof(struct arm_request)));
+ buf1 = (byte_t *) arm_resp + sizeof(struct arm_response);
+ buf2 = buf1 + 2 * sizeof(*store);
+ if ((ext_tcode == EXTCODE_FETCH_ADD) ||
+ (ext_tcode == EXTCODE_LITTLE_ADD)) {
+ arm_req->buffer_length = sizeof(*store);
+ memcpy(buf1, &data, sizeof(*store));
+
+ } else {
+ arm_req->buffer_length = 2 * sizeof(*store);
+ memcpy(buf1, &arg, sizeof(*store));
+ memcpy(buf1 + sizeof(*store), &data, sizeof(*store));
+ }
+ if (rcode == RCODE_COMPLETE) {
+ arm_resp->buffer_length = sizeof(*store);
+ memcpy(buf2, &old, sizeof(*store));
+ } else {
+ arm_resp->buffer_length = 0;
+ }
+ req->file_info = fi;
+ req->req.type = RAW1394_REQ_ARM;
+ req->req.generation = get_hpsb_generation(host);
+ req->req.misc = ((((sizeof(*store)) << 16) & (0xFFFF0000)) |
+ (ARM_LOCK & 0xFF));
+ req->req.tag = arm_addr->arm_tag;
+ req->req.recvb = arm_addr->recvb;
+ req->req.length = size;
+ arm_req->generation = req->req.generation;
+ arm_req->extended_transaction_code = ext_tcode;
+ arm_req->destination_offset = addr;
+ arm_req->source_nodeid = nodeid;
+ arm_req->destination_nodeid = host->node_id;
+ arm_req->tlabel = (flags >> 10) & 0x3f;
+ arm_req->tcode = (flags >> 4) & 0x0f;
+ arm_resp->response_code = rcode;
+ arm_req_resp->request = int2ptr((arm_addr->recvb) +
+ sizeof(struct
+ arm_request_response));
+ arm_req_resp->response =
+ int2ptr((arm_addr->recvb) +
+ sizeof(struct arm_request_response) +
+ sizeof(struct arm_request));
+ arm_req->buffer =
+ int2ptr((arm_addr->recvb) +
+ sizeof(struct arm_request_response) +
+ sizeof(struct arm_request) +
+ sizeof(struct arm_response));
+ arm_resp->buffer =
+ int2ptr((arm_addr->recvb) +
+ sizeof(struct arm_request_response) +
+ sizeof(struct arm_request) +
+ sizeof(struct arm_response) + 2 * sizeof(*store));
+ queue_complete_req(req);
+ }
+ spin_unlock(&host_info_lock);
+ return (rcode);
}
static int arm_register(struct file_info *fi, struct pending_request *req)
{
- int retval;
- struct arm_addr *addr;
- struct host_info *hi;
- struct file_info *fi_hlp = NULL;
- struct list_head *entry;
- struct arm_addr *arm_addr = NULL;
- int same_host, another_host;
- unsigned long flags;
-
- DBGMSG("arm_register called "
- "addr(Offset): %8.8x %8.8x length: %u "
- "rights: %2.2X notify: %2.2X "
- "max_blk_len: %4.4X",
- (u32) ((req->req.address >>32) & 0xFFFF),
- (u32) (req->req.address & 0xFFFFFFFF),
- req->req.length, ((req->req.misc >> 8) & 0xFF),
- (req->req.misc & 0xFF),((req->req.misc >> 16) & 0xFFFF));
- /* check addressrange */
- if ((((req->req.address) & ~(0xFFFFFFFFFFFFULL)) != 0) ||
- (((req->req.address + req->req.length) & ~(0xFFFFFFFFFFFFULL)) != 0)) {
- req->req.length = 0;
- return (-EINVAL);
- }
- /* addr-list-entry for fileinfo */
- addr = (struct arm_addr *)kmalloc(sizeof(struct arm_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);
- if (!(addr->addr_space_buffer)) {
- kfree(addr);
- req->req.length = 0;
- return (-ENOMEM);
- }
- /* initialization of addr_space_buffer */
- if ((req->req.sendb)== (unsigned long)NULL) {
- /* init: set 0 */
- memset(addr->addr_space_buffer, 0,req->req.length);
- } else {
- /* init: user -> kernel */
- if (copy_from_user(addr->addr_space_buffer,int2ptr(req->req.sendb),
- req->req.length)) {
- vfree(addr->addr_space_buffer);
- kfree(addr);
- return (-EFAULT);
- }
- }
- INIT_LIST_HEAD(&addr->addr_list);
- addr->arm_tag = req->req.tag;
- addr->start = req->req.address;
- addr->end = req->req.address + req->req.length;
- addr->access_rights = (u8) (req->req.misc & 0x0F);
- addr->notification_options = (u8) ((req->req.misc >> 4) & 0x0F);
- addr->client_transactions = (u8) ((req->req.misc >> 8) & 0x0F);
- addr->access_rights |= addr->client_transactions;
- addr->notification_options |= addr->client_transactions;
- addr->recvb = req->req.recvb;
- addr->rec_length = (u16) ((req->req.misc >> 16) & 0xFFFF);
- spin_lock_irqsave(&host_info_lock, flags);
- hi = find_host_info(fi->host);
- same_host = 0;
- another_host = 0;
- /* same host with address-entry containing same addressrange ? */
- list_for_each_entry(fi_hlp, &hi->file_info_list, list) {
- entry = fi_hlp->addr_list.next;
- while (entry != &(fi_hlp->addr_list)) {
- arm_addr = list_entry(entry, struct arm_addr, addr_list);
- if ( (arm_addr->start == addr->start) &&
- (arm_addr->end == addr->end)) {
- DBGMSG("same host ownes same "
- "addressrange -> EALREADY");
- same_host = 1;
- break;
- }
- entry = entry->next;
- }
- if (same_host) {
- break;
- }
- }
- if (same_host) {
- /* addressrange occupied by same host */
- vfree(addr->addr_space_buffer);
- kfree(addr);
- spin_unlock_irqrestore(&host_info_lock, flags);
- return (-EALREADY);
- }
- /* another host with valid address-entry containing same addressrange */
- list_for_each_entry(hi, &host_info_list, list) {
- if (hi->host != fi->host) {
- list_for_each_entry(fi_hlp, &hi->file_info_list, list) {
- entry = fi_hlp->addr_list.next;
- while (entry != &(fi_hlp->addr_list)) {
- arm_addr = list_entry(entry, struct arm_addr, addr_list);
- if ( (arm_addr->start == addr->start) &&
- (arm_addr->end == addr->end)) {
- DBGMSG("another host ownes same "
- "addressrange");
- another_host = 1;
- break;
- }
- entry = entry->next;
- }
- if (another_host) {
- break;
- }
- }
- }
- }
- if (another_host) {
- DBGMSG("another hosts entry is valid -> SUCCESS");
- if (copy_to_user(int2ptr(req->req.recvb),
- &addr->start,sizeof(u64))) {
- printk(KERN_ERR "raw1394: arm_register failed "
- " address-range-entry is invalid -> EFAULT !!!\n");
- vfree(addr->addr_space_buffer);
- kfree(addr);
- spin_unlock_irqrestore(&host_info_lock, flags);
- return (-EFAULT);
- }
- free_pending_request(req); /* immediate success or fail */
- /* INSERT ENTRY */
- list_add_tail(&addr->addr_list, &fi->addr_list);
- spin_unlock_irqrestore(&host_info_lock, flags);
- return sizeof(struct raw1394_request);
- }
- retval = hpsb_register_addrspace(&raw1394_highlevel, fi->host, &arm_ops, req->req.address,
- req->req.address + req->req.length);
- if (retval) {
- /* INSERT ENTRY */
- list_add_tail(&addr->addr_list, &fi->addr_list);
- } else {
- DBGMSG("arm_register failed errno: %d \n",retval);
- vfree(addr->addr_space_buffer);
- kfree(addr);
- spin_unlock_irqrestore(&host_info_lock, flags);
- return (-EALREADY);
- }
- spin_unlock_irqrestore(&host_info_lock, flags);
- free_pending_request(req); /* immediate success or fail */
- return sizeof(struct raw1394_request);
+ int retval;
+ struct arm_addr *addr;
+ struct host_info *hi;
+ struct file_info *fi_hlp = NULL;
+ struct list_head *entry;
+ struct arm_addr *arm_addr = NULL;
+ int same_host, another_host;
+ unsigned long flags;
+
+ DBGMSG("arm_register called "
+ "addr(Offset): %8.8x %8.8x length: %u "
+ "rights: %2.2X notify: %2.2X "
+ "max_blk_len: %4.4X",
+ (u32) ((req->req.address >> 32) & 0xFFFF),
+ (u32) (req->req.address & 0xFFFFFFFF),
+ req->req.length, ((req->req.misc >> 8) & 0xFF),
+ (req->req.misc & 0xFF), ((req->req.misc >> 16) & 0xFFFF));
+ /* check addressrange */
+ if ((((req->req.address) & ~(0xFFFFFFFFFFFFULL)) != 0) ||
+ (((req->req.address + req->req.length) & ~(0xFFFFFFFFFFFFULL)) !=
+ 0)) {
+ req->req.length = 0;
+ return (-EINVAL);
+ }
+ /* addr-list-entry for fileinfo */
+ addr = (struct arm_addr *)kmalloc(sizeof(struct arm_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);
+ if (!(addr->addr_space_buffer)) {
+ kfree(addr);
+ req->req.length = 0;
+ return (-ENOMEM);
+ }
+ /* initialization of addr_space_buffer */
+ if ((req->req.sendb) == (unsigned long)NULL) {
+ /* init: set 0 */
+ memset(addr->addr_space_buffer, 0, req->req.length);
+ } else {
+ /* init: user -> kernel */
+ if (copy_from_user
+ (addr->addr_space_buffer, int2ptr(req->req.sendb),
+ req->req.length)) {
+ vfree(addr->addr_space_buffer);
+ kfree(addr);
+ return (-EFAULT);
+ }
+ }
+ INIT_LIST_HEAD(&addr->addr_list);
+ addr->arm_tag = req->req.tag;
+ addr->start = req->req.address;
+ addr->end = req->req.address + req->req.length;
+ addr->access_rights = (u8) (req->req.misc & 0x0F);
+ addr->notification_options = (u8) ((req->req.misc >> 4) & 0x0F);
+ addr->client_transactions = (u8) ((req->req.misc >> 8) & 0x0F);
+ addr->access_rights |= addr->client_transactions;
+ addr->notification_options |= addr->client_transactions;
+ addr->recvb = req->req.recvb;
+ addr->rec_length = (u16) ((req->req.misc >> 16) & 0xFFFF);
+ spin_lock_irqsave(&host_info_lock, flags);
+ hi = find_host_info(fi->host);
+ same_host = 0;
+ another_host = 0;
+ /* same host with address-entry containing same addressrange ? */
+ list_for_each_entry(fi_hlp, &hi->file_info_list, list) {
+ entry = fi_hlp->addr_list.next;
+ while (entry != &(fi_hlp->addr_list)) {
+ arm_addr =
+ list_entry(entry, struct arm_addr, addr_list);
+ if ((arm_addr->start == addr->start)
+ && (arm_addr->end == addr->end)) {
+ DBGMSG("same host ownes same "
+ "addressrange -> EALREADY");
+ same_host = 1;
+ break;
+ }
+ entry = entry->next;
+ }
+ if (same_host) {
+ break;
+ }
+ }
+ if (same_host) {
+ /* addressrange occupied by same host */
+ vfree(addr->addr_space_buffer);
+ kfree(addr);
+ spin_unlock_irqrestore(&host_info_lock, flags);
+ return (-EALREADY);
+ }
+ /* another host with valid address-entry containing same addressrange */
+ list_for_each_entry(hi, &host_info_list, list) {
+ if (hi->host != fi->host) {
+ list_for_each_entry(fi_hlp, &hi->file_info_list, list) {
+ entry = fi_hlp->addr_list.next;
+ while (entry != &(fi_hlp->addr_list)) {
+ arm_addr =
+ list_entry(entry, struct arm_addr,
+ addr_list);
+ if ((arm_addr->start == addr->start)
+ && (arm_addr->end == addr->end)) {
+ DBGMSG
+ ("another host ownes same "
+ "addressrange");
+ another_host = 1;
+ break;
+ }
+ entry = entry->next;
+ }
+ if (another_host) {
+ break;
+ }
+ }
+ }
+ }
+ if (another_host) {
+ DBGMSG("another hosts entry is valid -> SUCCESS");
+ if (copy_to_user(int2ptr(req->req.recvb),
+ &addr->start, sizeof(u64))) {
+ printk(KERN_ERR "raw1394: arm_register failed "
+ " address-range-entry is invalid -> EFAULT !!!\n");
+ vfree(addr->addr_space_buffer);
+ kfree(addr);
+ spin_unlock_irqrestore(&host_info_lock, flags);
+ return (-EFAULT);
+ }
+ free_pending_request(req); /* immediate success or fail */
+ /* INSERT ENTRY */
+ list_add_tail(&addr->addr_list, &fi->addr_list);
+ spin_unlock_irqrestore(&host_info_lock, flags);
+ return sizeof(struct raw1394_request);
+ }
+ retval =
+ hpsb_register_addrspace(&raw1394_highlevel, fi->host, &arm_ops,
+ req->req.address,
+ req->req.address + req->req.length);
+ if (retval) {
+ /* INSERT ENTRY */
+ list_add_tail(&addr->addr_list, &fi->addr_list);
+ } else {
+ DBGMSG("arm_register failed errno: %d \n", retval);
+ vfree(addr->addr_space_buffer);
+ kfree(addr);
+ spin_unlock_irqrestore(&host_info_lock, flags);
+ return (-EALREADY);
+ }
+ spin_unlock_irqrestore(&host_info_lock, flags);
+ free_pending_request(req); /* immediate success or fail */
+ return sizeof(struct raw1394_request);
}
static int arm_unregister(struct file_info *fi, struct pending_request *req)
{
- int found = 0;
- int retval = 0;
- struct list_head *entry;
- struct arm_addr *addr = NULL;
- struct host_info *hi;
- struct file_info *fi_hlp = NULL;
- struct arm_addr *arm_addr = NULL;
- int another_host;
- unsigned long flags;
-
- DBGMSG("arm_Unregister called addr(Offset): "
- "%8.8x %8.8x",
- (u32) ((req->req.address >>32) & 0xFFFF),
- (u32) (req->req.address & 0xFFFFFFFF));
- spin_lock_irqsave(&host_info_lock, flags);
- /* get addr */
- entry = fi->addr_list.next;
- while (entry != &(fi->addr_list)) {
- addr = list_entry(entry, struct arm_addr, addr_list);
- if (addr->start == req->req.address) {
- found = 1;
- break;
- }
- entry = entry->next;
- }
- if (!found) {
- DBGMSG("arm_Unregister addr not found");
- spin_unlock_irqrestore(&host_info_lock, flags);
- return (-EINVAL);
- }
- DBGMSG("arm_Unregister addr found");
- another_host = 0;
- /* another host with valid address-entry containing
- same addressrange */
- list_for_each_entry(hi, &host_info_list, list) {
- if (hi->host != fi->host) {
- list_for_each_entry(fi_hlp, &hi->file_info_list, list) {
- entry = fi_hlp->addr_list.next;
- while (entry != &(fi_hlp->addr_list)) {
- arm_addr = list_entry(entry,
- struct arm_addr, addr_list);
- if (arm_addr->start ==
- addr->start) {
- DBGMSG("another host ownes "
- "same addressrange");
- another_host = 1;
- break;
- }
- entry = entry->next;
- }
- if (another_host) {
- break;
- }
- }
- }
- }
- if (another_host) {
- DBGMSG("delete entry from list -> success");
- list_del(&addr->addr_list);
- vfree(addr->addr_space_buffer);
- kfree(addr);
- free_pending_request(req); /* immediate success or fail */
- spin_unlock_irqrestore(&host_info_lock, flags);
- return sizeof(struct raw1394_request);
- }
- retval = hpsb_unregister_addrspace(&raw1394_highlevel, fi->host, addr->start);
- if (!retval) {
- printk(KERN_ERR "raw1394: arm_Unregister failed -> EINVAL\n");
- spin_unlock_irqrestore(&host_info_lock, flags);
- return (-EINVAL);
- }
- DBGMSG("delete entry from list -> success");
- list_del(&addr->addr_list);
- spin_unlock_irqrestore(&host_info_lock, flags);
- vfree(addr->addr_space_buffer);
- kfree(addr);
- free_pending_request(req); /* immediate success or fail */
- return sizeof(struct raw1394_request);
+ int found = 0;
+ int retval = 0;
+ struct list_head *entry;
+ struct arm_addr *addr = NULL;
+ struct host_info *hi;
+ struct file_info *fi_hlp = NULL;
+ struct arm_addr *arm_addr = NULL;
+ int another_host;
+ unsigned long flags;
+
+ DBGMSG("arm_Unregister called addr(Offset): "
+ "%8.8x %8.8x",
+ (u32) ((req->req.address >> 32) & 0xFFFF),
+ (u32) (req->req.address & 0xFFFFFFFF));
+ spin_lock_irqsave(&host_info_lock, flags);
+ /* get addr */
+ entry = fi->addr_list.next;
+ while (entry != &(fi->addr_list)) {
+ addr = list_entry(entry, struct arm_addr, addr_list);
+ if (addr->start == req->req.address) {
+ found = 1;
+ break;
+ }
+ entry = entry->next;
+ }
+ if (!found) {
+ DBGMSG("arm_Unregister addr not found");
+ spin_unlock_irqrestore(&host_info_lock, flags);
+ return (-EINVAL);
+ }
+ DBGMSG("arm_Unregister addr found");
+ another_host = 0;
+ /* another host with valid address-entry containing
+ same addressrange */
+ list_for_each_entry(hi, &host_info_list, list) {
+ if (hi->host != fi->host) {
+ list_for_each_entry(fi_hlp, &hi->file_info_list, list) {
+ entry = fi_hlp->addr_list.next;
+ while (entry != &(fi_hlp->addr_list)) {
+ arm_addr = list_entry(entry,
+ struct arm_addr,
+ addr_list);
+ if (arm_addr->start == addr->start) {
+ DBGMSG("another host ownes "
+ "same addressrange");
+ another_host = 1;
+ break;
+ }
+ entry = entry->next;
+ }
+ if (another_host) {
+ break;
+ }
+ }
+ }
+ }
+ if (another_host) {
+ DBGMSG("delete entry from list -> success");
+ list_del(&addr->addr_list);
+ vfree(addr->addr_space_buffer);
+ kfree(addr);
+ free_pending_request(req); /* immediate success or fail */
+ spin_unlock_irqrestore(&host_info_lock, flags);
+ return sizeof(struct raw1394_request);
+ }
+ retval =
+ hpsb_unregister_addrspace(&raw1394_highlevel, fi->host,
+ addr->start);
+ if (!retval) {
+ printk(KERN_ERR "raw1394: arm_Unregister failed -> EINVAL\n");
+ spin_unlock_irqrestore(&host_info_lock, flags);
+ return (-EINVAL);
+ }
+ DBGMSG("delete entry from list -> success");
+ list_del(&addr->addr_list);
+ spin_unlock_irqrestore(&host_info_lock, flags);
+ vfree(addr->addr_space_buffer);
+ kfree(addr);
+ free_pending_request(req); /* immediate success or fail */
+ return sizeof(struct raw1394_request);
}
/* Copy data from ARM buffer(s) to user buffer. */
static int arm_get_buf(struct file_info *fi, struct pending_request *req)
{
- struct arm_addr *arm_addr = NULL;
+ struct arm_addr *arm_addr = NULL;
unsigned long flags;
unsigned long offset;
@@ -1749,8 +1864,7 @@ static int arm_get_buf(struct file_info *fi, struct pending_request *req)
DBGMSG("arm_get_buf "
"addr(Offset): %04X %08X length: %u",
(u32) ((req->req.address >> 32) & 0xFFFF),
- (u32) (req->req.address & 0xFFFFFFFF),
- (u32) req->req.length);
+ (u32) (req->req.address & 0xFFFFFFFF), (u32) req->req.length);
spin_lock_irqsave(&host_info_lock, flags);
entry = fi->addr_list.next;
@@ -1761,13 +1875,18 @@ static int arm_get_buf(struct file_info *fi, struct pending_request *req)
if (req->req.address + req->req.length <= arm_addr->end) {
offset = req->req.address - arm_addr->start;
- DBGMSG("arm_get_buf copy_to_user( %08X, %p, %u )",
- (u32) req->req.recvb,
- arm_addr->addr_space_buffer+offset,
- (u32) req->req.length);
-
- if (copy_to_user(int2ptr(req->req.recvb), arm_addr->addr_space_buffer+offset, req->req.length)) {
- spin_unlock_irqrestore(&host_info_lock, flags);
+ DBGMSG
+ ("arm_get_buf copy_to_user( %08X, %p, %u )",
+ (u32) req->req.recvb,
+ arm_addr->addr_space_buffer + offset,
+ (u32) req->req.length);
+
+ if (copy_to_user
+ (int2ptr(req->req.recvb),
+ arm_addr->addr_space_buffer + offset,
+ req->req.length)) {
+ spin_unlock_irqrestore(&host_info_lock,
+ flags);
return (-EFAULT);
}
@@ -1789,11 +1908,10 @@ static int arm_get_buf(struct file_info *fi, struct pending_request *req)
return (-EINVAL);
}
-
/* Copy data from user buffer to ARM buffer(s). */
static int arm_set_buf(struct file_info *fi, struct pending_request *req)
{
- struct arm_addr *arm_addr = NULL;
+ struct arm_addr *arm_addr = NULL;
unsigned long flags;
unsigned long offset;
@@ -1802,9 +1920,7 @@ static int arm_set_buf(struct file_info *fi, struct pending_request *req)
DBGMSG("arm_set_buf "
"addr(Offset): %04X %08X length: %u",
(u32) ((req->req.address >> 32) & 0xFFFF),
- (u32) (req->req.address & 0xFFFFFFFF),
- (u32) req->req.length);
-
+ (u32) (req->req.address & 0xFFFFFFFF), (u32) req->req.length);
spin_lock_irqsave(&host_info_lock, flags);
entry = fi->addr_list.next;
@@ -1815,18 +1931,23 @@ static int arm_set_buf(struct file_info *fi, struct pending_request *req)
if (req->req.address + req->req.length <= arm_addr->end) {
offset = req->req.address - arm_addr->start;
- DBGMSG("arm_set_buf copy_from_user( %p, %08X, %u )",
- arm_addr->addr_space_buffer+offset,
- (u32) req->req.sendb,
- (u32) req->req.length);
-
- if (copy_from_user(arm_addr->addr_space_buffer+offset, int2ptr(req->req.sendb), req->req.length)) {
- spin_unlock_irqrestore(&host_info_lock, flags);
+ DBGMSG
+ ("arm_set_buf copy_from_user( %p, %08X, %u )",
+ arm_addr->addr_space_buffer + offset,
+ (u32) req->req.sendb,
+ (u32) req->req.length);
+
+ if (copy_from_user
+ (arm_addr->addr_space_buffer + offset,
+ int2ptr(req->req.sendb),
+ req->req.length)) {
+ spin_unlock_irqrestore(&host_info_lock,
+ flags);
return (-EFAULT);
}
spin_unlock_irqrestore(&host_info_lock, flags);
- free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */
+ free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */
return sizeof(struct raw1394_request);
} else {
DBGMSG("arm_set_buf request exceeded mapping");
@@ -1842,96 +1963,100 @@ static int arm_set_buf(struct file_info *fi, struct pending_request *req)
static int reset_notification(struct file_info *fi, struct pending_request *req)
{
- DBGMSG("reset_notification called - switch %s ",
- (req->req.misc == RAW1394_NOTIFY_OFF)?"OFF":"ON");
- if ((req->req.misc == RAW1394_NOTIFY_OFF) ||
- (req->req.misc == RAW1394_NOTIFY_ON)) {
- fi->notification=(u8)req->req.misc;
- free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */
- return sizeof(struct raw1394_request);
- }
- /* error EINVAL (22) invalid argument */
- return (-EINVAL);
+ DBGMSG("reset_notification called - switch %s ",
+ (req->req.misc == RAW1394_NOTIFY_OFF) ? "OFF" : "ON");
+ if ((req->req.misc == RAW1394_NOTIFY_OFF) ||
+ (req->req.misc == RAW1394_NOTIFY_ON)) {
+ fi->notification = (u8) req->req.misc;
+ free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */
+ return sizeof(struct raw1394_request);
+ }
+ /* error EINVAL (22) invalid argument */
+ return (-EINVAL);
}
static int write_phypacket(struct file_info *fi, struct pending_request *req)
{
- struct hpsb_packet *packet = NULL;
- int retval=0;
- quadlet_t data;
-
- data = be32_to_cpu((u32)req->req.sendb);
- DBGMSG("write_phypacket called - quadlet 0x%8.8x ",data);
- packet = hpsb_make_phypacket (fi->host, data);
- if (!packet) return -ENOMEM;
- req->req.length=0;
- req->packet=packet;
- hpsb_set_packet_complete_task(packet, (void(*)(void*))queue_complete_cb, req);
- spin_lock_irq(&fi->reqlists_lock);
- list_add_tail(&req->list, &fi->req_pending);
- spin_unlock_irq(&fi->reqlists_lock);
- packet->generation = req->req.generation;
- retval = hpsb_send_packet(packet);
- DBGMSG("write_phypacket send_packet called => retval: %d ", retval);
- if (retval < 0) {
- req->req.error = RAW1394_ERROR_SEND_ERROR;
- req->req.length = 0;
- queue_complete_req(req);
- }
- return sizeof(struct raw1394_request);
+ struct hpsb_packet *packet = NULL;
+ int retval = 0;
+ quadlet_t data;
+
+ data = be32_to_cpu((u32) req->req.sendb);
+ DBGMSG("write_phypacket called - quadlet 0x%8.8x ", data);
+ packet = hpsb_make_phypacket(fi->host, data);
+ if (!packet)
+ return -ENOMEM;
+ req->req.length = 0;
+ req->packet = packet;
+ hpsb_set_packet_complete_task(packet,
+ (void (*)(void *))queue_complete_cb, req);
+ spin_lock_irq(&fi->reqlists_lock);
+ list_add_tail(&req->list, &fi->req_pending);
+ spin_unlock_irq(&fi->reqlists_lock);
+ packet->generation = req->req.generation;
+ retval = hpsb_send_packet(packet);
+ DBGMSG("write_phypacket send_packet called => retval: %d ", retval);
+ if (retval < 0) {
+ req->req.error = RAW1394_ERROR_SEND_ERROR;
+ req->req.length = 0;
+ queue_complete_req(req);
+ }
+ return sizeof(struct raw1394_request);
}
static int get_config_rom(struct file_info *fi, struct pending_request *req)
{
- int ret=sizeof(struct raw1394_request);
- quadlet_t *data = kmalloc(req->req.length, SLAB_KERNEL);
- int status;
-
- if (!data) return -ENOMEM;
-
- status = csr1212_read(fi->host->csr.rom, CSR1212_CONFIG_ROM_SPACE_OFFSET,
- data, req->req.length);
- if (copy_to_user(int2ptr(req->req.recvb), data,
- req->req.length))
- ret = -EFAULT;
- if (copy_to_user(int2ptr(req->req.tag), &fi->host->csr.rom->cache_head->len,
- sizeof(fi->host->csr.rom->cache_head->len)))
- ret = -EFAULT;
+ int ret = sizeof(struct raw1394_request);
+ quadlet_t *data = kmalloc(req->req.length, SLAB_KERNEL);
+ int status;
+
+ if (!data)
+ return -ENOMEM;
+
+ status =
+ csr1212_read(fi->host->csr.rom, CSR1212_CONFIG_ROM_SPACE_OFFSET,
+ data, req->req.length);
+ if (copy_to_user(int2ptr(req->req.recvb), data, req->req.length))
+ ret = -EFAULT;
+ if (copy_to_user
+ (int2ptr(req->req.tag), &fi->host->csr.rom->cache_head->len,
+ sizeof(fi->host->csr.rom->cache_head->len)))
+ ret = -EFAULT;
if (copy_to_user(int2ptr(req->req.address), &fi->host->csr.generation,
sizeof(fi->host->csr.generation)))
- ret = -EFAULT;
- if (copy_to_user(int2ptr(req->req.sendb), &status,
- sizeof(status)))
- ret = -EFAULT;
- kfree(data);
- if (ret >= 0) {
- free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */
- }
- return ret;
+ ret = -EFAULT;
+ if (copy_to_user(int2ptr(req->req.sendb), &status, sizeof(status)))
+ ret = -EFAULT;
+ kfree(data);
+ if (ret >= 0) {
+ free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */
+ }
+ return ret;
}
static int update_config_rom(struct file_info *fi, struct pending_request *req)
{
- int ret=sizeof(struct raw1394_request);
- quadlet_t *data = kmalloc(req->req.length, SLAB_KERNEL);
- if (!data) return -ENOMEM;
- if (copy_from_user(data,int2ptr(req->req.sendb),
- req->req.length)) {
- ret= -EFAULT;
- } else {
- int status = hpsb_update_config_rom(fi->host,
- data, req->req.length,
- (unsigned char) req->req.misc);
- if (copy_to_user(int2ptr(req->req.recvb),
- &status, sizeof(status)))
- ret = -ENOMEM;
- }
- kfree(data);
- if (ret >= 0) {
- free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */
+ int ret = sizeof(struct raw1394_request);
+ quadlet_t *data = kmalloc(req->req.length, SLAB_KERNEL);
+ if (!data)
+ return -ENOMEM;
+ if (copy_from_user(data, int2ptr(req->req.sendb), req->req.length)) {
+ ret = -EFAULT;
+ } else {
+ int status = hpsb_update_config_rom(fi->host,
+ data, req->req.length,
+ (unsigned char)req->req.
+ misc);
+ if (copy_to_user
+ (int2ptr(req->req.recvb), &status, sizeof(status)))
+ ret = -ENOMEM;
+ }
+ kfree(data);
+ if (ret >= 0) {
+ free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */
fi->cfgrom_upd = 1;
- }
- return ret;
+ }
+ return ret;
}
static int modify_config_rom(struct file_info *fi, struct pending_request *req)
@@ -1943,23 +2068,32 @@ static int modify_config_rom(struct file_info *fi, struct pending_request *req)
int ret = 0;
if (req->req.misc == ~0) {
- if (req->req.length == 0) return -EINVAL;
+ if (req->req.length == 0)
+ return -EINVAL;
/* Find an unused slot */
- for (dr = 0; dr < RAW1394_MAX_USER_CSR_DIRS && fi->csr1212_dirs[dr]; dr++);
+ for (dr = 0;
+ dr < RAW1394_MAX_USER_CSR_DIRS && fi->csr1212_dirs[dr];
+ dr++) ;
- if (dr == RAW1394_MAX_USER_CSR_DIRS) return -ENOMEM;
+ if (dr == RAW1394_MAX_USER_CSR_DIRS)
+ return -ENOMEM;
- fi->csr1212_dirs[dr] = csr1212_new_directory(CSR1212_KV_ID_VENDOR);
- if (!fi->csr1212_dirs[dr]) return -ENOMEM;
+ fi->csr1212_dirs[dr] =
+ csr1212_new_directory(CSR1212_KV_ID_VENDOR);
+ if (!fi->csr1212_dirs[dr])
+ return -ENOMEM;
} else {
dr = req->req.misc;
- if (!fi->csr1212_dirs[dr]) return -EINVAL;
+ if (!fi->csr1212_dirs[dr])
+ return -EINVAL;
/* Delete old stuff */
- for (dentry = fi->csr1212_dirs[dr]->value.directory.dentries_head;
+ for (dentry =
+ fi->csr1212_dirs[dr]->value.directory.dentries_head;
dentry; dentry = dentry->next) {
- csr1212_detach_keyval_from_directory(fi->host->csr.rom->root_kv,
+ csr1212_detach_keyval_from_directory(fi->host->csr.rom->
+ root_kv,
dentry->kv);
}
@@ -1980,7 +2114,8 @@ 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(struct csr1212_cache_region), GFP_KERNEL);
if (!cache->filled_head) {
csr1212_release_keyval(fi->csr1212_dirs[dr]);
fi->csr1212_dirs[dr] = NULL;
@@ -1994,11 +2129,11 @@ static int modify_config_rom(struct file_info *fi, struct pending_request *req)
csr1212_release_keyval(fi->csr1212_dirs[dr]);
fi->csr1212_dirs[dr] = NULL;
CSR1212_FREE(cache);
- ret= -EFAULT;
+ ret = -EFAULT;
} else {
cache->len = req->req.length;
cache->filled_head->offset_start = 0;
- cache->filled_head->offset_end = cache->size -1;
+ cache->filled_head->offset_end = cache->size - 1;
cache->layout_head = cache->layout_tail = fi->csr1212_dirs[dr];
@@ -2010,17 +2145,20 @@ static int modify_config_rom(struct file_info *fi, struct pending_request *req)
}
/* attach top level items to the root directory */
- for (dentry = fi->csr1212_dirs[dr]->value.directory.dentries_head;
+ for (dentry =
+ fi->csr1212_dirs[dr]->value.directory.dentries_head;
ret == CSR1212_SUCCESS && dentry; dentry = dentry->next) {
- ret = csr1212_attach_keyval_to_directory(fi->host->csr.rom->root_kv,
- dentry->kv);
+ ret =
+ csr1212_attach_keyval_to_directory(fi->host->csr.
+ rom->root_kv,
+ dentry->kv);
}
if (ret == CSR1212_SUCCESS) {
ret = hpsb_update_config_rom_image(fi->host);
if (ret >= 0 && copy_to_user(int2ptr(req->req.recvb),
- &dr, sizeof(dr))) {
+ &dr, sizeof(dr))) {
ret = -ENOMEM;
}
}
@@ -2034,9 +2172,11 @@ static int modify_config_rom(struct file_info *fi, struct pending_request *req)
free_pending_request(req);
return sizeof(struct raw1394_request);
} else {
- for (dentry = fi->csr1212_dirs[dr]->value.directory.dentries_head;
+ for (dentry =
+ fi->csr1212_dirs[dr]->value.directory.dentries_head;
dentry; dentry = dentry->next) {
- csr1212_detach_keyval_from_directory(fi->host->csr.rom->root_kv,
+ csr1212_detach_keyval_from_directory(fi->host->csr.rom->
+ root_kv,
dentry->kv);
}
csr1212_release_keyval(fi->csr1212_dirs[dr]);
@@ -2047,133 +2187,132 @@ static int modify_config_rom(struct file_info *fi, struct pending_request *req)
static int state_connected(struct file_info *fi, struct pending_request *req)
{
- int node = req->req.address >> 48;
+ int node = req->req.address >> 48;
- req->req.error = RAW1394_ERROR_NONE;
+ req->req.error = RAW1394_ERROR_NONE;
- switch (req->req.type) {
+ switch (req->req.type) {
- case RAW1394_REQ_ECHO:
- queue_complete_req(req);
- return sizeof(struct raw1394_request);
+ case RAW1394_REQ_ECHO:
+ queue_complete_req(req);
+ return sizeof(struct raw1394_request);
- case RAW1394_REQ_ISO_SEND:
- return handle_iso_send(fi, req, node);
+ case RAW1394_REQ_ISO_SEND:
+ return handle_iso_send(fi, req, node);
- case RAW1394_REQ_ARM_REGISTER:
- return arm_register(fi, req);
+ case RAW1394_REQ_ARM_REGISTER:
+ return arm_register(fi, req);
- case RAW1394_REQ_ARM_UNREGISTER:
- return arm_unregister(fi, req);
+ case RAW1394_REQ_ARM_UNREGISTER:
+ return arm_unregister(fi, req);
- case RAW1394_REQ_ARM_SET_BUF:
- return arm_set_buf(fi, req);
+ case RAW1394_REQ_ARM_SET_BUF:
+ return arm_set_buf(fi, req);
- case RAW1394_REQ_ARM_GET_BUF:
- return arm_get_buf(fi, req);
+ case RAW1394_REQ_ARM_GET_BUF:
+ return arm_get_buf(fi, req);
- case RAW1394_REQ_RESET_NOTIFY:
- return reset_notification(fi, req);
+ case RAW1394_REQ_RESET_NOTIFY:
+ return reset_notification(fi, req);
- case RAW1394_REQ_ISO_LISTEN:
- handle_iso_listen(fi, req);
- return sizeof(struct raw1394_request);
+ case RAW1394_REQ_ISO_LISTEN:
+ handle_iso_listen(fi, req);
+ return sizeof(struct raw1394_request);
- case RAW1394_REQ_FCP_LISTEN:
- handle_fcp_listen(fi, req);
- return sizeof(struct raw1394_request);
+ case RAW1394_REQ_FCP_LISTEN:
+ handle_fcp_listen(fi, req);
+ return sizeof(struct raw1394_request);
- case RAW1394_REQ_RESET_BUS:
- if (req->req.misc == RAW1394_LONG_RESET) {
- DBGMSG("busreset called (type: LONG)");
- hpsb_reset_bus(fi->host, LONG_RESET);
- free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */
- return sizeof(struct raw1394_request);
- }
- if (req->req.misc == RAW1394_SHORT_RESET) {
- DBGMSG("busreset called (type: SHORT)");
- hpsb_reset_bus(fi->host, SHORT_RESET);
- free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */
- return sizeof(struct raw1394_request);
- }
- /* error EINVAL (22) invalid argument */
- return (-EINVAL);
- case RAW1394_REQ_GET_ROM:
- return get_config_rom(fi, req);
+ case RAW1394_REQ_RESET_BUS:
+ if (req->req.misc == RAW1394_LONG_RESET) {
+ DBGMSG("busreset called (type: LONG)");
+ hpsb_reset_bus(fi->host, LONG_RESET);
+ free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */
+ return sizeof(struct raw1394_request);
+ }
+ if (req->req.misc == RAW1394_SHORT_RESET) {
+ DBGMSG("busreset called (type: SHORT)");
+ hpsb_reset_bus(fi->host, SHORT_RESET);
+ free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */
+ return sizeof(struct raw1394_request);
+ }
+ /* error EINVAL (22) invalid argument */
+ return (-EINVAL);
+ case RAW1394_REQ_GET_ROM:
+ return get_config_rom(fi, req);
- case RAW1394_REQ_UPDATE_ROM:
- return update_config_rom(fi, req);
+ case RAW1394_REQ_UPDATE_ROM:
+ return update_config_rom(fi, req);
case RAW1394_REQ_MODIFY_ROM:
return modify_config_rom(fi, req);
- }
-
- if (req->req.generation != get_hpsb_generation(fi->host)) {
- req->req.error = RAW1394_ERROR_GENERATION;
- req->req.generation = get_hpsb_generation(fi->host);
- req->req.length = 0;
- queue_complete_req(req);
- return sizeof(struct raw1394_request);
- }
-
- switch (req->req.type) {
- case RAW1394_REQ_PHYPACKET:
- return write_phypacket(fi, req);
- case RAW1394_REQ_ASYNC_SEND:
- return handle_async_send(fi, req);
- }
-
- if (req->req.length == 0) {
- req->req.error = RAW1394_ERROR_INVALID_ARG;
- queue_complete_req(req);
- return sizeof(struct raw1394_request);
- }
-
- return handle_async_request(fi, req, node);
-}
+ }
+
+ if (req->req.generation != get_hpsb_generation(fi->host)) {
+ req->req.error = RAW1394_ERROR_GENERATION;
+ req->req.generation = get_hpsb_generation(fi->host);
+ req->req.length = 0;
+ queue_complete_req(req);
+ return sizeof(struct raw1394_request);
+ }
+
+ switch (req->req.type) {
+ case RAW1394_REQ_PHYPACKET:
+ return write_phypacket(fi, req);
+ case RAW1394_REQ_ASYNC_SEND:
+ return handle_async_send(fi, req);
+ }
+ if (req->req.length == 0) {
+ req->req.error = RAW1394_ERROR_INVALID_ARG;
+ queue_complete_req(req);
+ return sizeof(struct raw1394_request);
+ }
+
+ return handle_async_request(fi, req, node);
+}
-static ssize_t raw1394_write(struct file *file, const char __user *buffer, size_t count,
- loff_t *offset_is_ignored)
+static ssize_t raw1394_write(struct file *file, const char __user * buffer,
+ size_t count, loff_t * offset_is_ignored)
{
- struct file_info *fi = (struct file_info *)file->private_data;
- struct pending_request *req;
- ssize_t retval = 0;
-
- if (count != sizeof(struct raw1394_request)) {
- return -EINVAL;
- }
-
- req = alloc_pending_request();
- if (req == NULL) {
- return -ENOMEM;
- }
- req->file_info = fi;
-
- if (copy_from_user(&req->req, buffer, sizeof(struct raw1394_request))) {
- free_pending_request(req);
- return -EFAULT;
- }
-
- switch (fi->state) {
- case opened:
- retval = state_opened(fi, req);
- break;
-
- case initialized:
- retval = state_initialized(fi, req);
- break;
-
- case connected:
- retval = state_connected(fi, req);
- break;
- }
-
- if (retval < 0) {
- free_pending_request(req);
- }
-
- return retval;
+ struct file_info *fi = (struct file_info *)file->private_data;
+ struct pending_request *req;
+ ssize_t retval = 0;
+
+ if (count != sizeof(struct raw1394_request)) {
+ return -EINVAL;
+ }
+
+ req = alloc_pending_request();
+ if (req == NULL) {
+ return -ENOMEM;
+ }
+ req->file_info = fi;
+
+ if (copy_from_user(&req->req, buffer, sizeof(struct raw1394_request))) {
+ free_pending_request(req);
+ return -EFAULT;
+ }
+
+ switch (fi->state) {
+ case opened:
+ retval = state_opened(fi, req);
+ break;
+
+ case initialized:
+ retval = state_initialized(fi, req);
+ break;
+
+ case connected:
+ retval = state_connected(fi, req);
+ break;
+ }
+
+ if (retval < 0) {
+ free_pending_request(req);
+ }
+
+ return retval;
}
/* rawiso operations */
@@ -2185,8 +2324,8 @@ static inline int __rawiso_event_in_queue(struct file_info *fi)
struct pending_request *req;
list_for_each_entry(req, &fi->req_complete, list)
- if (req->req.type == RAW1394_REQ_RAWISO_ACTIVITY)
- return 1;
+ if (req->req.type == RAW1394_REQ_RAWISO_ACTIVITY)
+ return 1;
return 0;
}
@@ -2200,7 +2339,8 @@ static void queue_rawiso_event(struct file_info *fi)
/* only one ISO activity event may be in the queue */
if (!__rawiso_event_in_queue(fi)) {
- struct pending_request *req = __alloc_pending_request(SLAB_ATOMIC);
+ struct pending_request *req =
+ __alloc_pending_request(SLAB_ATOMIC);
if (req) {
req->file_info = fi;
@@ -2220,11 +2360,11 @@ static void queue_rawiso_event(struct file_info *fi)
static void rawiso_activity_cb(struct hpsb_iso *iso)
{
unsigned long flags;
- struct host_info *hi;
+ struct host_info *hi;
struct file_info *fi;
- spin_lock_irqsave(&host_info_lock, flags);
- hi = find_host_info(iso->host);
+ spin_lock_irqsave(&host_info_lock, flags);
+ hi = find_host_info(iso->host);
if (hi != NULL) {
list_for_each_entry(fi, &hi->file_info_list, list) {
@@ -2237,7 +2377,8 @@ static void rawiso_activity_cb(struct hpsb_iso *iso)
}
/* helper function - gather all the kernel iso status bits for returning to user-space */
-static void raw1394_iso_fill_status(struct hpsb_iso *iso, struct raw1394_iso_status *stat)
+static void raw1394_iso_fill_status(struct hpsb_iso *iso,
+ struct raw1394_iso_status *stat)
{
stat->config.data_buf_size = iso->buf_size;
stat->config.buf_packets = iso->buf_packets;
@@ -2249,7 +2390,7 @@ static void raw1394_iso_fill_status(struct hpsb_iso *iso, struct raw1394_iso_sta
stat->xmit_cycle = iso->xmit_cycle;
}
-static int raw1394_iso_xmit_init(struct file_info *fi, void __user *uaddr)
+static int raw1394_iso_xmit_init(struct file_info *fi, void __user * uaddr)
{
struct raw1394_iso_status stat;
@@ -2281,7 +2422,7 @@ static int raw1394_iso_xmit_init(struct file_info *fi, void __user *uaddr)
return 0;
}
-static int raw1394_iso_recv_init(struct file_info *fi, void __user *uaddr)
+static int raw1394_iso_recv_init(struct file_info *fi, void __user * uaddr)
{
struct raw1394_iso_status stat;
@@ -2295,7 +2436,7 @@ static int raw1394_iso_recv_init(struct file_info *fi, void __user *uaddr)
stat.config.data_buf_size,
stat.config.buf_packets,
stat.config.channel,
- stat.config.dma_mode,
+ stat.config.dma_mode,
stat.config.irq_interval,
rawiso_activity_cb);
if (!fi->iso_handle)
@@ -2309,7 +2450,7 @@ static int raw1394_iso_recv_init(struct file_info *fi, void __user *uaddr)
return 0;
}
-static int raw1394_iso_get_status(struct file_info *fi, void __user *uaddr)
+static int raw1394_iso_get_status(struct file_info *fi, void __user * uaddr)
{
struct raw1394_iso_status stat;
struct hpsb_iso *iso = fi->iso_handle;
@@ -2325,7 +2466,7 @@ static int raw1394_iso_get_status(struct file_info *fi, void __user *uaddr)
}
/* copy N packet_infos out of the ringbuffer into user-supplied array */
-static int raw1394_iso_recv_packets(struct file_info *fi, void __user *uaddr)
+static int raw1394_iso_recv_packets(struct file_info *fi, void __user * uaddr)
{
struct raw1394_iso_packets upackets;
unsigned int packet = fi->iso_handle->first_packet;
@@ -2338,15 +2479,16 @@ static int raw1394_iso_recv_packets(struct file_info *fi, void __user *uaddr)
return -EINVAL;
/* ensure user-supplied buffer is accessible and big enough */
- if (verify_area(VERIFY_WRITE, upackets.infos,
- upackets.n_packets * sizeof(struct raw1394_iso_packet_info)))
+ if (!access_ok(VERIFY_WRITE, upackets.infos,
+ upackets.n_packets *
+ sizeof(struct raw1394_iso_packet_info)))
return -EFAULT;
/* copy the packet_infos out */
for (i = 0; i < upackets.n_packets; i++) {
if (__copy_to_user(&upackets.infos[i],
- &fi->iso_handle->infos[packet],
- sizeof(struct raw1394_iso_packet_info)))
+ &fi->iso_handle->infos[packet],
+ sizeof(struct raw1394_iso_packet_info)))
return -EFAULT;
packet = (packet + 1) % fi->iso_handle->buf_packets;
@@ -2356,7 +2498,7 @@ static int raw1394_iso_recv_packets(struct file_info *fi, void __user *uaddr)
}
/* copy N packet_infos from user to ringbuffer, and queue them for transmission */
-static int raw1394_iso_send_packets(struct file_info *fi, void __user *uaddr)
+static int raw1394_iso_send_packets(struct file_info *fi, void __user * uaddr)
{
struct raw1394_iso_packets upackets;
int i, rv;
@@ -2368,8 +2510,9 @@ static int raw1394_iso_send_packets(struct file_info *fi, void __user *uaddr)
return -EINVAL;
/* ensure user-supplied buffer is accessible and big enough */
- if (verify_area(VERIFY_READ, upackets.infos,
- upackets.n_packets * sizeof(struct raw1394_iso_packet_info)))
+ if (!access_ok(VERIFY_READ, upackets.infos,
+ upackets.n_packets *
+ sizeof(struct raw1394_iso_packet_info)))
return -EFAULT;
/* copy the infos structs in and queue the packets */
@@ -2377,7 +2520,7 @@ static int raw1394_iso_send_packets(struct file_info *fi, void __user *uaddr)
struct raw1394_iso_packet_info info;
if (__copy_from_user(&info, &upackets.infos[i],
- sizeof(struct raw1394_iso_packet_info)))
+ sizeof(struct raw1394_iso_packet_info)))
return -EFAULT;
rv = hpsb_iso_xmit_queue_packet(fi->iso_handle, info.offset,
@@ -2410,14 +2553,15 @@ static int raw1394_mmap(struct file *file, struct vm_area_struct *vma)
}
/* ioctl is only used for rawiso operations */
-static int raw1394_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+static int raw1394_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
{
struct file_info *fi = file->private_data;
void __user *argp = (void __user *)arg;
- switch(fi->iso_state) {
+ switch (fi->iso_state) {
case RAW1394_ISO_INACTIVE:
- switch(cmd) {
+ switch (cmd) {
case RAW1394_IOC_ISO_XMIT_INIT:
return raw1394_iso_xmit_init(fi, argp);
case RAW1394_IOC_ISO_RECV_INIT:
@@ -2427,34 +2571,42 @@ static int raw1394_ioctl(struct inode *inode, struct file *file, unsigned int cm
}
break;
case RAW1394_ISO_RECV:
- switch(cmd) {
- case RAW1394_IOC_ISO_RECV_START: {
- /* copy args from user-space */
- int args[3];
- if (copy_from_user(&args[0], argp, sizeof(args)))
- return -EFAULT;
- return hpsb_iso_recv_start(fi->iso_handle, args[0], args[1], args[2]);
- }
+ switch (cmd) {
+ case RAW1394_IOC_ISO_RECV_START:{
+ /* copy args from user-space */
+ int args[3];
+ if (copy_from_user
+ (&args[0], argp, sizeof(args)))
+ return -EFAULT;
+ return hpsb_iso_recv_start(fi->iso_handle,
+ args[0], args[1],
+ args[2]);
+ }
case RAW1394_IOC_ISO_XMIT_RECV_STOP:
hpsb_iso_stop(fi->iso_handle);
return 0;
case RAW1394_IOC_ISO_RECV_LISTEN_CHANNEL:
- return hpsb_iso_recv_listen_channel(fi->iso_handle, arg);
+ return hpsb_iso_recv_listen_channel(fi->iso_handle,
+ arg);
case RAW1394_IOC_ISO_RECV_UNLISTEN_CHANNEL:
- return hpsb_iso_recv_unlisten_channel(fi->iso_handle, arg);
- case RAW1394_IOC_ISO_RECV_SET_CHANNEL_MASK: {
- /* copy the u64 from user-space */
- u64 mask;
- if (copy_from_user(&mask, argp, sizeof(mask)))
- return -EFAULT;
- return hpsb_iso_recv_set_channel_mask(fi->iso_handle, mask);
- }
+ return hpsb_iso_recv_unlisten_channel(fi->iso_handle,
+ arg);
+ case RAW1394_IOC_ISO_RECV_SET_CHANNEL_MASK:{
+ /* copy the u64 from user-space */
+ u64 mask;
+ if (copy_from_user(&mask, argp, sizeof(mask)))
+ return -EFAULT;
+ return hpsb_iso_recv_set_channel_mask(fi->
+ iso_handle,
+ mask);
+ }
case RAW1394_IOC_ISO_GET_STATUS:
return raw1394_iso_get_status(fi, argp);
case RAW1394_IOC_ISO_RECV_PACKETS:
return raw1394_iso_recv_packets(fi, argp);
case RAW1394_IOC_ISO_RECV_RELEASE_PACKETS:
- return hpsb_iso_recv_release_packets(fi->iso_handle, arg);
+ return hpsb_iso_recv_release_packets(fi->iso_handle,
+ arg);
case RAW1394_IOC_ISO_RECV_FLUSH:
return hpsb_iso_recv_flush(fi->iso_handle);
case RAW1394_IOC_ISO_SHUTDOWN:
@@ -2466,14 +2618,16 @@ static int raw1394_ioctl(struct inode *inode, struct file *file, unsigned int cm
}
break;
case RAW1394_ISO_XMIT:
- switch(cmd) {
- case RAW1394_IOC_ISO_XMIT_START: {
- /* copy two ints from user-space */
- int args[2];
- if (copy_from_user(&args[0], argp, sizeof(args)))
- return -EFAULT;
- return hpsb_iso_xmit_start(fi->iso_handle, args[0], args[1]);
- }
+ switch (cmd) {
+ case RAW1394_IOC_ISO_XMIT_START:{
+ /* copy two ints from user-space */
+ int args[2];
+ if (copy_from_user
+ (&args[0], argp, sizeof(args)))
+ return -EFAULT;
+ return hpsb_iso_xmit_start(fi->iso_handle,
+ args[0], args[1]);
+ }
case RAW1394_IOC_ISO_XMIT_SYNC:
return hpsb_iso_xmit_sync(fi->iso_handle);
case RAW1394_IOC_ISO_XMIT_RECV_STOP:
@@ -2498,270 +2652,304 @@ static int raw1394_ioctl(struct inode *inode, struct file *file, unsigned int cm
return -EINVAL;
}
-static unsigned int raw1394_poll(struct file *file, poll_table *pt)
+static unsigned int raw1394_poll(struct file *file, poll_table * pt)
{
- struct file_info *fi = file->private_data;
- unsigned int mask = POLLOUT | POLLWRNORM;
+ struct file_info *fi = file->private_data;
+ unsigned int mask = POLLOUT | POLLWRNORM;
- poll_wait(file, &fi->poll_wait_complete, pt);
+ poll_wait(file, &fi->poll_wait_complete, pt);
- spin_lock_irq(&fi->reqlists_lock);
- if (!list_empty(&fi->req_complete)) {
- mask |= POLLIN | POLLRDNORM;
- }
- spin_unlock_irq(&fi->reqlists_lock);
+ spin_lock_irq(&fi->reqlists_lock);
+ if (!list_empty(&fi->req_complete)) {
+ mask |= POLLIN | POLLRDNORM;
+ }
+ spin_unlock_irq(&fi->reqlists_lock);
- return mask;
+ return mask;
}
static int raw1394_open(struct inode *inode, struct file *file)
{
- struct file_info *fi;
+ struct file_info *fi;
- fi = kmalloc(sizeof(struct file_info), SLAB_KERNEL);
- if (fi == NULL)
- return -ENOMEM;
+ fi = kmalloc(sizeof(struct file_info), SLAB_KERNEL);
+ if (fi == NULL)
+ return -ENOMEM;
- memset(fi, 0, sizeof(struct file_info));
- fi->notification = (u8) RAW1394_NOTIFY_ON; /* busreset notification */
+ memset(fi, 0, sizeof(struct file_info));
+ fi->notification = (u8) RAW1394_NOTIFY_ON; /* busreset notification */
- INIT_LIST_HEAD(&fi->list);
- fi->state = opened;
- INIT_LIST_HEAD(&fi->req_pending);
- INIT_LIST_HEAD(&fi->req_complete);
- sema_init(&fi->complete_sem, 0);
- spin_lock_init(&fi->reqlists_lock);
- init_waitqueue_head(&fi->poll_wait_complete);
- INIT_LIST_HEAD(&fi->addr_list);
+ INIT_LIST_HEAD(&fi->list);
+ fi->state = opened;
+ INIT_LIST_HEAD(&fi->req_pending);
+ INIT_LIST_HEAD(&fi->req_complete);
+ sema_init(&fi->complete_sem, 0);
+ spin_lock_init(&fi->reqlists_lock);
+ init_waitqueue_head(&fi->poll_wait_complete);
+ INIT_LIST_HEAD(&fi->addr_list);
- file->private_data = fi;
+ file->private_data = fi;
- return 0;
+ return 0;
}
static int raw1394_release(struct inode *inode, struct file *file)
{
- struct file_info *fi = file->private_data;
- struct list_head *lh;
- struct pending_request *req;
- int done = 0, i, fail = 0;
- int retval = 0;
- struct list_head *entry;
- struct arm_addr *addr = NULL;
- struct host_info *hi;
- struct file_info *fi_hlp = NULL;
- struct arm_addr *arm_addr = NULL;
- int another_host;
+ struct file_info *fi = file->private_data;
+ struct list_head *lh;
+ struct pending_request *req;
+ int done = 0, i, fail = 0;
+ int retval = 0;
+ struct list_head *entry;
+ struct arm_addr *addr = NULL;
+ struct host_info *hi;
+ struct file_info *fi_hlp = NULL;
+ struct arm_addr *arm_addr = NULL;
+ int another_host;
int csr_mod = 0;
if (fi->iso_state != RAW1394_ISO_INACTIVE)
raw1394_iso_shutdown(fi);
- for (i = 0; i < 64; i++) {
- if (fi->listen_channels & (1ULL << i)) {
- hpsb_unlisten_channel(&raw1394_highlevel, fi->host, i);
- }
- }
-
- spin_lock_irq(&host_info_lock);
- fi->listen_channels = 0;
- spin_unlock_irq(&host_info_lock);
-
- fail = 0;
- /* set address-entries invalid */
- spin_lock_irq(&host_info_lock);
-
- while (!list_empty(&fi->addr_list)) {
- another_host = 0;
- lh = fi->addr_list.next;
- addr = list_entry(lh, struct arm_addr, addr_list);
- /* another host with valid address-entry containing
- same addressrange? */
- list_for_each_entry(hi, &host_info_list, list) {
- if (hi->host != fi->host) {
- list_for_each_entry(fi_hlp, &hi->file_info_list, list) {
- entry = fi_hlp->addr_list.next;
- while (entry != &(fi_hlp->addr_list)) {
- arm_addr = list_entry(entry,
- struct arm_addr, addr_list);
- if (arm_addr->start ==
- addr->start) {
- DBGMSG("raw1394_release: "
- "another host ownes "
- "same addressrange");
- another_host = 1;
- break;
- }
- entry = entry->next;
- }
- if (another_host) {
- break;
- }
- }
- }
- }
- if (!another_host) {
- DBGMSG("raw1394_release: call hpsb_arm_unregister");
- retval = hpsb_unregister_addrspace(&raw1394_highlevel, fi->host, addr->start);
- if (!retval) {
- ++fail;
- printk(KERN_ERR "raw1394_release arm_Unregister failed\n");
- }
- }
- DBGMSG("raw1394_release: delete addr_entry from list");
- list_del(&addr->addr_list);
- vfree(addr->addr_space_buffer);
- kfree(addr);
- } /* while */
- spin_unlock_irq(&host_info_lock);
- if (fail > 0) {
- printk(KERN_ERR "raw1394: during addr_list-release "
- "error(s) occurred \n");
- }
-
- while (!done) {
- spin_lock_irq(&fi->reqlists_lock);
-
- while (!list_empty(&fi->req_complete)) {
- lh = fi->req_complete.next;
- list_del(lh);
-
- req = list_entry(lh, struct pending_request, list);
-
- free_pending_request(req);
- }
-
- if (list_empty(&fi->req_pending)) done = 1;
-
- spin_unlock_irq(&fi->reqlists_lock);
-
- if (!done) down_interruptible(&fi->complete_sem);
- }
+ for (i = 0; i < 64; i++) {
+ if (fi->listen_channels & (1ULL << i)) {
+ hpsb_unlisten_channel(&raw1394_highlevel, fi->host, i);
+ }
+ }
+
+ spin_lock_irq(&host_info_lock);
+ fi->listen_channels = 0;
+ spin_unlock_irq(&host_info_lock);
+
+ fail = 0;
+ /* set address-entries invalid */
+ spin_lock_irq(&host_info_lock);
+
+ while (!list_empty(&fi->addr_list)) {
+ another_host = 0;
+ lh = fi->addr_list.next;
+ addr = list_entry(lh, struct arm_addr, addr_list);
+ /* another host with valid address-entry containing
+ same addressrange? */
+ list_for_each_entry(hi, &host_info_list, list) {
+ if (hi->host != fi->host) {
+ list_for_each_entry(fi_hlp, &hi->file_info_list,
+ list) {
+ entry = fi_hlp->addr_list.next;
+ while (entry != &(fi_hlp->addr_list)) {
+ arm_addr = list_entry(entry,
+ struct
+ arm_addr,
+ addr_list);
+ if (arm_addr->start ==
+ addr->start) {
+ DBGMSG
+ ("raw1394_release: "
+ "another host ownes "
+ "same addressrange");
+ another_host = 1;
+ break;
+ }
+ entry = entry->next;
+ }
+ if (another_host) {
+ break;
+ }
+ }
+ }
+ }
+ if (!another_host) {
+ DBGMSG("raw1394_release: call hpsb_arm_unregister");
+ retval =
+ hpsb_unregister_addrspace(&raw1394_highlevel,
+ fi->host, addr->start);
+ if (!retval) {
+ ++fail;
+ printk(KERN_ERR
+ "raw1394_release arm_Unregister failed\n");
+ }
+ }
+ DBGMSG("raw1394_release: delete addr_entry from list");
+ list_del(&addr->addr_list);
+ vfree(addr->addr_space_buffer);
+ kfree(addr);
+ } /* while */
+ spin_unlock_irq(&host_info_lock);
+ if (fail > 0) {
+ printk(KERN_ERR "raw1394: during addr_list-release "
+ "error(s) occurred \n");
+ }
+
+ while (!done) {
+ spin_lock_irq(&fi->reqlists_lock);
+
+ while (!list_empty(&fi->req_complete)) {
+ lh = fi->req_complete.next;
+ list_del(lh);
+
+ req = list_entry(lh, struct pending_request, list);
+
+ free_pending_request(req);
+ }
+
+ if (list_empty(&fi->req_pending))
+ done = 1;
+
+ spin_unlock_irq(&fi->reqlists_lock);
+
+ if (!done)
+ down_interruptible(&fi->complete_sem);
+ }
/* Remove any sub-trees left by user space programs */
for (i = 0; i < RAW1394_MAX_USER_CSR_DIRS; i++) {
struct csr1212_dentry *dentry;
- if (!fi->csr1212_dirs[i]) continue;
- for (dentry = fi->csr1212_dirs[i]->value.directory.dentries_head;
- dentry; dentry = dentry->next) {
- csr1212_detach_keyval_from_directory(fi->host->csr.rom->root_kv, dentry->kv);
+ if (!fi->csr1212_dirs[i])
+ continue;
+ for (dentry =
+ fi->csr1212_dirs[i]->value.directory.dentries_head; dentry;
+ dentry = dentry->next) {
+ csr1212_detach_keyval_from_directory(fi->host->csr.rom->
+ root_kv,
+ dentry->kv);
}
csr1212_release_keyval(fi->csr1212_dirs[i]);
fi->csr1212_dirs[i] = NULL;
csr_mod = 1;
}
- if ((csr_mod || fi->cfgrom_upd) && hpsb_update_config_rom_image(fi->host) < 0)
- HPSB_ERR("Failed to generate Configuration ROM image for host %d", fi->host->id);
+ if ((csr_mod || fi->cfgrom_upd)
+ && hpsb_update_config_rom_image(fi->host) < 0)
+ HPSB_ERR
+ ("Failed to generate Configuration ROM image for host %d",
+ fi->host->id);
- if (fi->state == connected) {
- spin_lock_irq(&host_info_lock);
- list_del(&fi->list);
- spin_unlock_irq(&host_info_lock);
+ if (fi->state == connected) {
+ spin_lock_irq(&host_info_lock);
+ list_del(&fi->list);
+ spin_unlock_irq(&host_info_lock);
put_device(&fi->host->device);
- }
+ }
- kfree(fi);
+ kfree(fi);
- return 0;
+ return 0;
}
-
/*** HOTPLUG STUFF **********************************************************/
/*
* Export information about protocols/devices supported by this driver.
*/
static struct ieee1394_device_id raw1394_id_table[] = {
{
- .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION,
- .specifier_id = AVC_UNIT_SPEC_ID_ENTRY & 0xffffff,
- .version = AVC_SW_VERSION_ENTRY & 0xffffff
- },
+ .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION,
+ .specifier_id = AVC_UNIT_SPEC_ID_ENTRY & 0xffffff,
+ .version = AVC_SW_VERSION_ENTRY & 0xffffff},
+ {
+ .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION,
+ .specifier_id = CAMERA_UNIT_SPEC_ID_ENTRY & 0xffffff,
+ .version = CAMERA_SW_VERSION_ENTRY & 0xffffff},
{
- .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION,
- .specifier_id = CAMERA_UNIT_SPEC_ID_ENTRY & 0xffffff,
- .version = CAMERA_SW_VERSION_ENTRY & 0xffffff
- },
- { }
+ .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION,
+ .specifier_id = CAMERA_UNIT_SPEC_ID_ENTRY & 0xffffff,
+ .version = (CAMERA_SW_VERSION_ENTRY + 1) & 0xffffff},
+ {
+ .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION,
+ .specifier_id = CAMERA_UNIT_SPEC_ID_ENTRY & 0xffffff,
+ .version = (CAMERA_SW_VERSION_ENTRY + 2) & 0xffffff},
+ {}
};
MODULE_DEVICE_TABLE(ieee1394, raw1394_id_table);
static struct hpsb_protocol_driver raw1394_driver = {
- .name = "raw1394 Driver",
- .id_table = raw1394_id_table,
- .driver = {
- .name = "raw1394",
- .bus = &ieee1394_bus_type,
- },
+ .name = "raw1394 Driver",
+ .id_table = raw1394_id_table,
+ .driver = {
+ .name = "raw1394",
+ .bus = &ieee1394_bus_type,
+ },
};
-
/******************************************************************************/
-
static struct hpsb_highlevel raw1394_highlevel = {
- .name = RAW1394_DEVICE_NAME,
- .add_host = add_host,
- .remove_host = remove_host,
- .host_reset = host_reset,
- .iso_receive = iso_receive,
- .fcp_request = fcp_request,
+ .name = RAW1394_DEVICE_NAME,
+ .add_host = add_host,
+ .remove_host = remove_host,
+ .host_reset = host_reset,
+ .iso_receive = iso_receive,
+ .fcp_request = fcp_request,
};
static struct cdev raw1394_cdev;
static struct file_operations raw1394_fops = {
- .owner = THIS_MODULE,
- .read = raw1394_read,
- .write = raw1394_write,
- .mmap = raw1394_mmap,
- .ioctl = raw1394_ioctl,
- .poll = raw1394_poll,
- .open = raw1394_open,
- .release = raw1394_release,
+ .owner = THIS_MODULE,
+ .read = raw1394_read,
+ .write = raw1394_write,
+ .mmap = raw1394_mmap,
+ .ioctl = raw1394_ioctl,
+ .poll = raw1394_poll,
+ .open = raw1394_open,
+ .release = raw1394_release,
};
static int __init init_raw1394(void)
{
- int ret;
+ int ret = 0;
hpsb_register_highlevel(&raw1394_highlevel);
- devfs_mk_cdev(MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16),
- S_IFCHR | S_IRUSR | S_IWUSR, RAW1394_DEVICE_NAME);
+ if (IS_ERR(class_simple_device_add(hpsb_protocol_class, 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);
cdev_init(&raw1394_cdev, &raw1394_fops);
raw1394_cdev.owner = THIS_MODULE;
kobject_set_name(&raw1394_cdev.kobj, RAW1394_DEVICE_NAME);
ret = cdev_add(&raw1394_cdev, IEEE1394_RAW1394_DEV, 1);
if (ret) {
- HPSB_ERR("raw1394 failed to register minor device block");
- devfs_remove(RAW1394_DEVICE_NAME);
- hpsb_unregister_highlevel(&raw1394_highlevel);
- return ret;
- }
+ HPSB_ERR("raw1394 failed to register minor device block");
+ goto out_dev;
+ }
- HPSB_INFO("raw1394: /dev/%s device initialized", RAW1394_DEVICE_NAME);
+ HPSB_INFO("raw1394: /dev/%s device initialized", RAW1394_DEVICE_NAME);
ret = hpsb_register_protocol(&raw1394_driver);
if (ret) {
HPSB_ERR("raw1394: failed to register protocol");
cdev_del(&raw1394_cdev);
- devfs_remove(RAW1394_DEVICE_NAME);
- hpsb_unregister_highlevel(&raw1394_highlevel);
- return ret;
+ goto out_dev;
}
- return 0;
+ goto out;
+
+out_dev:
+ devfs_remove(RAW1394_DEVICE_NAME);
+ class_simple_device_remove(MKDEV(
+ IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16));
+out_unreg:
+ hpsb_unregister_highlevel(&raw1394_highlevel);
+out:
+ return ret;
}
static void __exit cleanup_raw1394(void)
{
- hpsb_unregister_protocol(&raw1394_driver);
+ class_simple_device_remove(MKDEV(
+ IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16));
cdev_del(&raw1394_cdev);
- devfs_remove(RAW1394_DEVICE_NAME);
- hpsb_unregister_highlevel(&raw1394_highlevel);
+ devfs_remove(RAW1394_DEVICE_NAME);
+ hpsb_unregister_highlevel(&raw1394_highlevel);
+ hpsb_unregister_protocol(&raw1394_driver);
}
module_init(init_raw1394);
diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c
index 125eb6c64f6ab..00c7b958361ad 100644
--- a/drivers/ieee1394/sbp2.c
+++ b/drivers/ieee1394/sbp2.c
@@ -64,7 +64,10 @@
#include <asm/system.h>
#include <asm/scatterlist.h>
-#include "../scsi/scsi.h"
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_dbg.h>
+#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
#include "csr1212.h"
@@ -224,12 +227,12 @@ static void sbp2scsi_complete_all_commands(struct scsi_id_instance_data *scsi_id
u32 status);
static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id,
- u32 scsi_status, Scsi_Cmnd *SCpnt,
- void (*done)(Scsi_Cmnd *));
+ u32 scsi_status, struct scsi_cmnd *SCpnt,
+ void (*done)(struct scsi_cmnd *));
-static Scsi_Host_Template scsi_driver_template;
+static struct scsi_host_template scsi_driver_template;
-const u8 sbp2_speedto_max_payload[] = { 0x7, 0x8, 0x9, 0xA, 0xB, 0xC };
+static const u8 sbp2_speedto_max_payload[] = { 0x7, 0x8, 0x9, 0xA, 0xB, 0xC };
static void sbp2_host_reset(struct hpsb_host *host);
@@ -373,7 +376,7 @@ static void sbp2_free_packet(struct hpsb_packet *packet)
/* This is much like hpsb_node_write(), except it ignores the response
* subaction and returns immediately. Can be used from interrupts.
*/
-int sbp2util_node_write_no_wait(struct node_entry *ne, u64 addr,
+static int sbp2util_node_write_no_wait(struct node_entry *ne, u64 addr,
quadlet_t *buffer, size_t length)
{
struct hpsb_packet *packet;
@@ -520,8 +523,8 @@ static struct sbp2_command_info *sbp2util_find_command_for_SCpnt(struct scsi_id_
*/
static struct sbp2_command_info *sbp2util_allocate_command_orb(
struct scsi_id_instance_data *scsi_id,
- Scsi_Cmnd *Current_SCpnt,
- void (*Current_done)(Scsi_Cmnd *))
+ struct scsi_cmnd *Current_SCpnt,
+ void (*Current_done)(struct scsi_cmnd *))
{
struct list_head *lh;
struct sbp2_command_info *command = NULL;
@@ -902,9 +905,13 @@ alloc_fail:
* connected to the sbp2 device being removed. That host would
* have a certain amount of time to relogin before the sbp2 device
* allows someone else to login instead. One second makes sense. */
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(HZ);
-
+ msleep_interruptible(1000);
+ if (signal_pending(current)) {
+ SBP2_WARN("aborting sbp2_start_device due to event");
+ sbp2_remove_device(scsi_id);
+ return -EINTR;
+ }
+
/*
* Login to the sbp-2 device
*/
@@ -1521,8 +1528,9 @@ static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id,
SBP2_DEBUG("sbp2_management_agent_addr = %x",
(unsigned int) management_agent_addr);
- } else
+ } else if (kv->key.type == CSR1212_KV_TYPE_IMMEDIATE) {
scsi_id->sbp2_device_type_and_lun = kv->value.immediate;
+ }
break;
case SBP2_COMMAND_SET_SPEC_ID_KEY:
@@ -1613,6 +1621,8 @@ static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id,
scsi_id->sbp2_unit_characteristics = unit_characteristics;
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;
}
}
@@ -1700,14 +1710,14 @@ static int sbp2_create_command_orb(struct scsi_id_instance_data *scsi_id,
unsigned int scsi_use_sg,
unsigned int scsi_request_bufflen,
void *scsi_request_buffer,
- unsigned char scsi_dir)
+ enum dma_data_direction dma_dir)
+
{
struct sbp2scsi_host_info *hi = scsi_id->hi;
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];
- int dma_dir = scsi_to_pci_dma_dir (scsi_dir);
u32 sg_count, sg_len, orb_direction;
dma_addr_t sg_addr;
int i;
@@ -1730,22 +1740,22 @@ static int sbp2_create_command_orb(struct scsi_id_instance_data *scsi_id,
* Get the direction of the transfer. If the direction is unknown, then use our
* goofy table as a back-up.
*/
- switch (scsi_dir) {
- case SCSI_DATA_NONE:
+ switch (dma_dir) {
+ case DMA_NONE:
orb_direction = ORB_DIRECTION_NO_DATA_TRANSFER;
break;
- case SCSI_DATA_WRITE:
+ case DMA_TO_DEVICE:
orb_direction = ORB_DIRECTION_WRITE_TO_MEDIA;
break;
- case SCSI_DATA_READ:
+ case DMA_FROM_DEVICE:
orb_direction = ORB_DIRECTION_READ_FROM_MEDIA;
break;
- case SCSI_DATA_UNKNOWN:
+ 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");
- print_command (scsi_cmd);
+ __scsi_print_command(scsi_cmd);
orb_direction = sbp2scsi_direction_table[*scsi_cmd];
break;
}
@@ -2031,7 +2041,8 @@ static int sbp2_link_orb_command(struct scsi_id_instance_data *scsi_id,
* This function is called in order to begin a regular SBP-2 command.
*/
static int sbp2_send_command(struct scsi_id_instance_data *scsi_id,
- Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
+ struct scsi_cmnd *SCpnt,
+ void (*done)(struct scsi_cmnd *))
{
unchar *cmd = (unchar *) SCpnt->cmnd;
unsigned int request_bufflen = SCpnt->request_bufflen;
@@ -2040,7 +2051,7 @@ static int sbp2_send_command(struct scsi_id_instance_data *scsi_id,
SBP2_DEBUG("sbp2_send_command");
#if (CONFIG_IEEE1394_SBP2_DEBUG >= 2) || defined(CONFIG_IEEE1394_SBP2_PACKET_DUMP)
printk("[scsi command]\n ");
- print_command (cmd);
+ scsi_print_command(SCpnt);
#endif
SBP2_DEBUG("SCSI transfer size = %x", request_bufflen);
SBP2_DEBUG("SCSI s/g elements = %x", (unsigned int)SCpnt->use_sg);
@@ -2233,7 +2244,7 @@ static unsigned int sbp2_status_to_sense_data(unchar *sbp2_status, unchar *sense
* response data translations for the SCSI stack
*/
static void sbp2_check_sbp2_response(struct scsi_id_instance_data *scsi_id,
- Scsi_Cmnd *SCpnt)
+ struct scsi_cmnd *SCpnt)
{
u8 *scsi_buf = SCpnt->request_buffer;
u8 device_type = SBP2_DEVICE_TYPE (scsi_id->sbp2_device_type_and_lun);
@@ -2312,7 +2323,7 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int dest
struct sbp2scsi_host_info *hi;
struct scsi_id_instance_data *scsi_id = NULL, *scsi_id_tmp;
u32 id;
- Scsi_Cmnd *SCpnt = NULL;
+ struct scsi_cmnd *SCpnt = NULL;
u32 scsi_status = SBP2_SCSI_STATUS_GOOD;
struct sbp2_command_info *command;
@@ -2454,7 +2465,8 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int dest
* This routine is the main request entry routine for doing I/O. It is
* called from the scsi stack directly.
*/
-static int sbp2scsi_queuecommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
+static int sbp2scsi_queuecommand(struct scsi_cmnd *SCpnt,
+ void (*done)(struct scsi_cmnd *))
{
struct scsi_id_instance_data *scsi_id =
(struct scsi_id_instance_data *)SCpnt->device->host->hostdata[0];
@@ -2550,9 +2562,8 @@ static void sbp2scsi_complete_all_commands(struct scsi_id_instance_data *scsi_id
PCI_DMA_BIDIRECTIONAL);
sbp2util_mark_command_completed(scsi_id, command);
if (command->Current_SCpnt) {
- void (*done)(Scsi_Cmnd *) = command->Current_done;
command->Current_SCpnt->result = status << 16;
- done (command->Current_SCpnt);
+ command->Current_done(command->Current_SCpnt);
}
}
@@ -2565,8 +2576,8 @@ static void sbp2scsi_complete_all_commands(struct scsi_id_instance_data *scsi_id
* This can be called in interrupt context.
*/
static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id,
- u32 scsi_status, Scsi_Cmnd *SCpnt,
- void (*done)(Scsi_Cmnd *))
+ u32 scsi_status, struct scsi_cmnd *SCpnt,
+ void (*done)(struct scsi_cmnd *))
{
unsigned long flags;
@@ -2611,8 +2622,8 @@ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id,
* Debug stuff
*/
#if CONFIG_IEEE1394_SBP2_DEBUG >= 1
- print_command (SCpnt->cmnd);
- print_sense("bh", SCpnt);
+ scsi_print_command(SCpnt);
+ scsi_print_sense("bh", SCpnt);
#endif
break;
@@ -2620,7 +2631,7 @@ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id,
case SBP2_SCSI_STATUS_SELECTION_TIMEOUT:
SBP2_ERR("SBP2_SCSI_STATUS_SELECTION_TIMEOUT");
SCpnt->result = DID_NO_CONNECT << 16;
- print_command (SCpnt->cmnd);
+ scsi_print_command(SCpnt);
break;
case SBP2_SCSI_STATUS_CONDITION_MET:
@@ -2628,7 +2639,7 @@ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id,
case SBP2_SCSI_STATUS_COMMAND_TERMINATED:
SBP2_ERR("Bad SCSI status = %x", scsi_status);
SCpnt->result = DID_ERROR << 16;
- print_command (SCpnt->cmnd);
+ scsi_print_command(SCpnt);
break;
default:
@@ -2688,7 +2699,7 @@ static int sbp2scsi_slave_configure (struct scsi_device *sdev)
* Called by scsi stack when something has really gone wrong. Usually
* called when a command has timed-out for some reason.
*/
-static int sbp2scsi_abort (Scsi_Cmnd *SCpnt)
+static int sbp2scsi_abort(struct scsi_cmnd *SCpnt)
{
struct scsi_id_instance_data *scsi_id =
(struct scsi_id_instance_data *)SCpnt->device->host->hostdata[0];
@@ -2696,7 +2707,7 @@ static int sbp2scsi_abort (Scsi_Cmnd *SCpnt)
struct sbp2_command_info *command;
SBP2_ERR("aborting sbp2 command");
- print_command (SCpnt->cmnd);
+ scsi_print_command(SCpnt);
if (scsi_id) {
@@ -2717,9 +2728,8 @@ static int sbp2scsi_abort (Scsi_Cmnd *SCpnt)
PCI_DMA_BIDIRECTIONAL);
sbp2util_mark_command_completed(scsi_id, command);
if (command->Current_SCpnt) {
- void (*done)(Scsi_Cmnd *) = command->Current_done;
command->Current_SCpnt->result = DID_ABORT << 16;
- done (command->Current_SCpnt);
+ command->Current_done(command->Current_SCpnt);
}
}
@@ -2736,7 +2746,7 @@ static int sbp2scsi_abort (Scsi_Cmnd *SCpnt)
/*
* Called by scsi stack when something has really gone wrong.
*/
-static int sbp2scsi_reset (Scsi_Cmnd *SCpnt)
+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];
@@ -2789,7 +2799,7 @@ MODULE_SUPPORTED_DEVICE(SBP2_DEVICE_NAME);
MODULE_LICENSE("GPL");
/* SCSI host template */
-static Scsi_Host_Template scsi_driver_template = {
+static struct scsi_host_template scsi_driver_template = {
.module = THIS_MODULE,
.name = "SBP-2 IEEE-1394",
.proc_name = SBP2_DEVICE_NAME,
diff --git a/drivers/ieee1394/sbp2.h b/drivers/ieee1394/sbp2.h
index 94b59f80bf90d..a84b039a05b94 100644
--- a/drivers/ieee1394/sbp2.h
+++ b/drivers/ieee1394/sbp2.h
@@ -324,8 +324,8 @@ struct sbp2_command_info {
struct list_head list;
struct sbp2_command_orb command_orb ____cacheline_aligned;
dma_addr_t command_orb_dma ____cacheline_aligned;
- Scsi_Cmnd *Current_SCpnt;
- void (*Current_done)(Scsi_Cmnd *);
+ struct scsi_cmnd *Current_SCpnt;
+ void (*Current_done)(struct scsi_cmnd *);
/* Also need s/g structure for each sbp2 command */
struct sbp2_unrestricted_page_table scatter_gather_element[SG_ALL] ____cacheline_aligned;
@@ -434,8 +434,8 @@ static void sbp2util_remove_command_orb_pool(struct scsi_id_instance_data *scsi_
static struct sbp2_command_info *sbp2util_find_command_for_orb(struct scsi_id_instance_data *scsi_id, dma_addr_t orb);
static struct sbp2_command_info *sbp2util_find_command_for_SCpnt(struct scsi_id_instance_data *scsi_id, void *SCpnt);
static struct sbp2_command_info *sbp2util_allocate_command_orb(struct scsi_id_instance_data *scsi_id,
- Scsi_Cmnd *Current_SCpnt,
- void (*Current_done)(Scsi_Cmnd *));
+ struct scsi_cmnd *Current_SCpnt,
+ void (*Current_done)(struct scsi_cmnd *));
static void sbp2util_mark_command_completed(struct scsi_id_instance_data *scsi_id,
struct sbp2_command_info *command);
@@ -466,14 +466,16 @@ static int sbp2_create_command_orb(struct scsi_id_instance_data *scsi_id,
unsigned int scsi_use_sg,
unsigned int scsi_request_bufflen,
void *scsi_request_buffer,
- unsigned char scsi_dir);
+ 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,
- Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *));
+ 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, Scsi_Cmnd *SCpnt);
+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,
struct unit_directory *ud);
static int sbp2_set_busy_timeout(struct scsi_id_instance_data *scsi_id);
diff --git a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c
index 3acc962296b13..4bedf7113f407 100644
--- a/drivers/ieee1394/video1394.c
+++ b/drivers/ieee1394/video1394.c
@@ -16,14 +16,25 @@
* You should have received a copy of the 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:
+ *
+ * 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
+ * EBUSY when trying to use an already used resource
+ * ESRCH when trying to free/stop a not used resource
+ * EAGAIN for resource allocation failure that could perhaps succeed later
+ * ENOTTY for unsupported ioctl request
+ *
*/
-/* 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 */
-
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/list.h>
@@ -146,8 +157,8 @@ printk(level "video1394: " fmt "\n" , ## args)
#define PRINT(level, card, fmt, args...) \
printk(level "video1394_%d: " fmt "\n" , card , ## args)
-void wakeup_dma_ir_ctx(unsigned long l);
-void wakeup_dma_it_ctx(unsigned long l);
+static void wakeup_dma_ir_ctx(unsigned long l);
+static void wakeup_dma_it_ctx(unsigned long l);
static struct hpsb_highlevel video1394_highlevel;
@@ -487,7 +498,7 @@ find_ctx(struct list_head *list, int type, int channel)
return NULL;
}
-void wakeup_dma_ir_ctx(unsigned long l)
+static void wakeup_dma_ir_ctx(unsigned long l)
{
struct dma_iso_ctx *d = (struct dma_iso_ctx *) l;
int i;
@@ -560,7 +571,7 @@ static inline void put_timestamp(struct ti_ohci *ohci, struct dma_iso_ctx * d,
#endif
}
-void wakeup_dma_it_ctx(unsigned long l)
+static void wakeup_dma_it_ctx(unsigned long l)
{
struct dma_iso_ctx *d = (struct dma_iso_ctx *) l;
struct ti_ohci *ohci = d->ohci;
@@ -699,6 +710,17 @@ static void initialize_dma_it_ctx(struct dma_iso_ctx *d, int sync_tag,
reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, 1<<d->ctx);
}
+static inline unsigned video1394_buffer_state(struct dma_iso_ctx *d,
+ unsigned int buffer)
+{
+ unsigned long flags;
+ unsigned int ret;
+ spin_lock_irqsave(&d->lock, flags);
+ ret = d->buffer_status[buffer];
+ spin_unlock_irqrestore(&d->lock, flags);
+ return ret;
+}
+
static int __video1394_ioctl(struct file *file,
unsigned int cmd, unsigned long arg)
{
@@ -723,7 +745,12 @@ static int __video1394_ioctl(struct file *file,
/* if channel < 0, find lowest available one */
if (v.channel < 0) {
mask = (u64)0x1;
- for (i=0; i<ISO_CHANNELS; i++) {
+ for (i=0; ; i++) {
+ if (i == ISO_CHANNELS) {
+ PRINT(KERN_ERR, ohci->host->id,
+ "No free channel found");
+ return EAGAIN;
+ }
if (!(ohci->ISO_channel_usage & mask)) {
v.channel = i;
PRINT(KERN_INFO, ohci->host->id, "Found free channel %d", i);
@@ -731,42 +758,40 @@ static int __video1394_ioctl(struct file *file,
}
mask = mask << 1;
}
- }
-
- if (v.channel<0 || v.channel>(ISO_CHANNELS-1)) {
+ } else if (v.channel >= ISO_CHANNELS) {
PRINT(KERN_ERR, ohci->host->id,
"Iso channel %d out of bounds", v.channel);
- return -EFAULT;
+ return -EINVAL;
+ } else {
+ mask = (u64)0x1<<v.channel;
}
- mask = (u64)0x1<<v.channel;
- printk("mask: %08X%08X usage: %08X%08X\n",
- (u32)(mask>>32),(u32)(mask&0xffffffff),
- (u32)(ohci->ISO_channel_usage>>32),
- (u32)(ohci->ISO_channel_usage&0xffffffff));
+ PRINT(KERN_INFO, ohci->host->id, "mask: %08X%08X usage: %08X%08X\n",
+ (u32)(mask>>32),(u32)(mask&0xffffffff),
+ (u32)(ohci->ISO_channel_usage>>32),
+ (u32)(ohci->ISO_channel_usage&0xffffffff));
if (ohci->ISO_channel_usage & mask) {
PRINT(KERN_ERR, ohci->host->id,
"Channel %d is already taken", v.channel);
- return -EFAULT;
+ return -EBUSY;
}
- ohci->ISO_channel_usage |= mask;
if (v.buf_size == 0 || v.buf_size > VIDEO1394_MAX_SIZE) {
PRINT(KERN_ERR, ohci->host->id,
"Invalid %d length buffer requested",v.buf_size);
- return -EFAULT;
+ return -EINVAL;
}
if (v.nb_buffers == 0 || v.nb_buffers > VIDEO1394_MAX_SIZE) {
PRINT(KERN_ERR, ohci->host->id,
"Invalid %d buffers requested",v.nb_buffers);
- return -EFAULT;
+ return -EINVAL;
}
if (v.nb_buffers * v.buf_size > VIDEO1394_MAX_SIZE) {
PRINT(KERN_ERR, ohci->host->id,
"%d buffers of size %d bytes is too big",
v.nb_buffers, v.buf_size);
- return -EFAULT;
+ return -EINVAL;
}
if (cmd == VIDEO1394_IOC_LISTEN_CHANNEL) {
@@ -777,7 +802,7 @@ static int __video1394_ioctl(struct file *file,
if (d == NULL) {
PRINT(KERN_ERR, ohci->host->id,
"Couldn't allocate ir context");
- return -EFAULT;
+ return -EAGAIN;
}
initialize_dma_ir_ctx(d, v.sync_tag, v.flags);
@@ -798,7 +823,7 @@ static int __video1394_ioctl(struct file *file,
if (d == NULL) {
PRINT(KERN_ERR, ohci->host->id,
"Couldn't allocate it context");
- return -EFAULT;
+ return -EAGAIN;
}
initialize_dma_it_ctx(d, v.sync_tag,
v.syt_offset, v.flags);
@@ -814,8 +839,12 @@ static int __video1394_ioctl(struct file *file,
v.channel);
}
- if (copy_to_user(argp, &v, sizeof(v)))
+ if (copy_to_user((void *)arg, &v, sizeof(v))) {
+ /* FIXME : free allocated dma resources */
return -EFAULT;
+ }
+
+ ohci->ISO_channel_usage |= mask;
return 0;
}
@@ -829,16 +858,16 @@ static int __video1394_ioctl(struct file *file,
if (copy_from_user(&channel, argp, sizeof(int)))
return -EFAULT;
- if (channel<0 || channel>(ISO_CHANNELS-1)) {
+ if (channel < 0 || channel >= ISO_CHANNELS) {
PRINT(KERN_ERR, ohci->host->id,
"Iso channel %d out of bound", channel);
- return -EFAULT;
+ return -EINVAL;
}
mask = (u64)0x1<<channel;
if (!(ohci->ISO_channel_usage & mask)) {
PRINT(KERN_ERR, ohci->host->id,
"Channel %d is not being used", channel);
- return -EFAULT;
+ return -ESRCH;
}
/* Mark this channel as unused */
@@ -849,7 +878,7 @@ static int __video1394_ioctl(struct file *file,
else
d = find_ctx(&ctx->context_list, OHCI_ISO_TRANSMIT, channel);
- if (d == NULL) return -EFAULT;
+ if (d == NULL) return -ESRCH;
PRINT(KERN_INFO, ohci->host->id, "Iso context %d "
"stop talking on channel %d", d->ctx, channel);
free_dma_iso_ctx(d);
@@ -870,7 +899,7 @@ static int __video1394_ioctl(struct file *file,
if ((v.buffer<0) || (v.buffer>d->num_desc)) {
PRINT(KERN_ERR, ohci->host->id,
"Buffer %d out of range",v.buffer);
- return -EFAULT;
+ return -EINVAL;
}
spin_lock_irqsave(&d->lock,flags);
@@ -879,7 +908,7 @@ static int __video1394_ioctl(struct file *file,
PRINT(KERN_ERR, ohci->host->id,
"Buffer %d is already used",v.buffer);
spin_unlock_irqrestore(&d->lock,flags);
- return -EFAULT;
+ return -EBUSY;
}
d->buffer_status[v.buffer]=VIDEO1394_BUFFER_QUEUED;
@@ -933,7 +962,7 @@ static int __video1394_ioctl(struct file *file,
if ((v.buffer<0) || (v.buffer>d->num_desc)) {
PRINT(KERN_ERR, ohci->host->id,
"Buffer %d out of range",v.buffer);
- return -EFAULT;
+ return -EINVAL;
}
/*
@@ -952,31 +981,20 @@ static int __video1394_ioctl(struct file *file,
return -EINTR;
}
-#if 1
- while (d->buffer_status[v.buffer]!=
- VIDEO1394_BUFFER_READY) {
- spin_unlock_irqrestore(&d->lock, flags);
- interruptible_sleep_on(&d->waitq);
- spin_lock_irqsave(&d->lock, flags);
- if (signal_pending(current)) {
- spin_unlock_irqrestore(&d->lock,flags);
- return -EINTR;
- }
- }
-#else
- if (wait_event_interruptible(d->waitq,
- d->buffer_status[v.buffer]
- == VIDEO1394_BUFFER_READY)
- == -ERESTARTSYS)
- return -EINTR;
-#endif
+ spin_unlock_irqrestore(&d->lock, flags);
+ wait_event_interruptible(d->waitq,
+ video1394_buffer_state(d, v.buffer) ==
+ VIDEO1394_BUFFER_READY);
+ if (signal_pending(current))
+ return -EINTR;
+ spin_lock_irqsave(&d->lock, flags);
d->buffer_status[v.buffer]=VIDEO1394_BUFFER_FREE;
break;
default:
PRINT(KERN_ERR, ohci->host->id,
"Buffer %d is not queued",v.buffer);
spin_unlock_irqrestore(&d->lock, flags);
- return -EFAULT;
+ return -ESRCH;
}
/* set time of buffer */
@@ -1015,7 +1033,7 @@ static int __video1394_ioctl(struct file *file,
if ((v.buffer<0) || (v.buffer>d->num_desc)) {
PRINT(KERN_ERR, ohci->host->id,
"Buffer %d out of range",v.buffer);
- return -EFAULT;
+ return -EINVAL;
}
if (d->flags & VIDEO1394_VARIABLE_PACKET_SIZE) {
@@ -1044,7 +1062,7 @@ static int __video1394_ioctl(struct file *file,
spin_unlock_irqrestore(&d->lock,flags);
if (psizes)
kfree(psizes);
- return -EFAULT;
+ return -EBUSY;
}
if (d->flags & VIDEO1394_VARIABLE_PACKET_SIZE) {
@@ -1118,7 +1136,7 @@ static int __video1394_ioctl(struct file *file,
if ((v.buffer<0) || (v.buffer>d->num_desc)) {
PRINT(KERN_ERR, ohci->host->id,
"Buffer %d out of range",v.buffer);
- return -EFAULT;
+ return -EINVAL;
}
switch(d->buffer_status[v.buffer]) {
@@ -1126,29 +1144,20 @@ static int __video1394_ioctl(struct file *file,
d->buffer_status[v.buffer]=VIDEO1394_BUFFER_FREE;
return 0;
case VIDEO1394_BUFFER_QUEUED:
-#if 1
- while (d->buffer_status[v.buffer]!=
- VIDEO1394_BUFFER_READY) {
- interruptible_sleep_on(&d->waitq);
- if (signal_pending(current)) return -EINTR;
- }
-#else
- if (wait_event_interruptible(d->waitq,
- d->buffer_status[v.buffer]
- == VIDEO1394_BUFFER_READY)
- == -ERESTARTSYS)
+ wait_event_interruptible(d->waitq,
+ (d->buffer_status[v.buffer] == VIDEO1394_BUFFER_READY));
+ if (signal_pending(current))
return -EINTR;
-#endif
d->buffer_status[v.buffer]=VIDEO1394_BUFFER_FREE;
return 0;
default:
PRINT(KERN_ERR, ohci->host->id,
"Buffer %d is not queued",v.buffer);
- return -EFAULT;
+ return -ESRCH;
}
}
default:
- return -EINVAL;
+ return -ENOTTY;
}
}
@@ -1170,7 +1179,7 @@ static long video1394_ioctl(struct file *file, unsigned int cmd, unsigned long a
* But e.g. pte_alloc() does not work in modules ... :-(
*/
-int video1394_mmap(struct file *file, struct vm_area_struct *vma)
+static int video1394_mmap(struct file *file, struct vm_area_struct *vma)
{
struct file_ctx *ctx = (struct file_ctx *)file->private_data;
int res = -EINVAL;
@@ -1269,6 +1278,16 @@ static struct ieee1394_device_id video1394_id_table[] = {
.specifier_id = CAMERA_UNIT_SPEC_ID_ENTRY & 0xffffff,
.version = CAMERA_SW_VERSION_ENTRY & 0xffffff
},
+ {
+ .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION,
+ .specifier_id = CAMERA_UNIT_SPEC_ID_ENTRY & 0xffffff,
+ .version = (CAMERA_SW_VERSION_ENTRY + 1) & 0xffffff
+ },
+ {
+ .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION,
+ .specifier_id = CAMERA_UNIT_SPEC_ID_ENTRY & 0xffffff,
+ .version = (CAMERA_SW_VERSION_ENTRY + 2) & 0xffffff
+ },
{ }
};
@@ -1304,6 +1323,9 @@ static void video1394_add_host (struct hpsb_host *host)
hpsb_set_hostinfo_key(&video1394_highlevel, host, ohci->host->id);
minor = IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->host->id;
+ class_simple_device_add(hpsb_protocol_class, MKDEV(
+ IEEE1394_MAJOR, minor),
+ NULL, "%s-%d", VIDEO1394_DRIVER_NAME, ohci->host->id);
devfs_mk_cdev(MKDEV(IEEE1394_MAJOR, minor),
S_IFCHR | S_IRUSR | S_IWUSR,
"%s/%d", VIDEO1394_DRIVER_NAME, ohci->host->id);
@@ -1314,9 +1336,12 @@ static void video1394_remove_host (struct hpsb_host *host)
{
struct ti_ohci *ohci = hpsb_get_hostinfo(&video1394_highlevel, host);
- if (ohci)
+ if (ohci) {
+ class_simple_device_remove(MKDEV(IEEE1394_MAJOR,
+ IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->host->id));
devfs_remove("%s/%d", VIDEO1394_DRIVER_NAME, ohci->host->id);
-
+ }
+
return;
}
diff --git a/drivers/infiniband/core/agent.c b/drivers/infiniband/core/agent.c
index 49f4f9f92506b..7aee5ebf3f015 100644
--- a/drivers/infiniband/core/agent.c
+++ b/drivers/infiniband/core/agent.c
@@ -45,14 +45,11 @@
#include "smi.h"
#include "agent_priv.h"
#include "mad_priv.h"
-
+#include "agent.h"
spinlock_t ib_agent_port_list_lock;
static LIST_HEAD(ib_agent_port_list);
-extern kmem_cache_t *ib_mad_cache;
-
-
/*
* Caller must hold ib_agent_port_list_lock
*/
@@ -66,14 +63,13 @@ __ib_get_agent_port(struct ib_device *device, int port_num,
if (device) {
list_for_each_entry(entry, &ib_agent_port_list, port_list) {
- if (entry->dr_smp_agent->device == device &&
+ if (entry->smp_agent->device == device &&
entry->port_num == port_num)
return entry;
}
} else {
list_for_each_entry(entry, &ib_agent_port_list, port_list) {
- if ((entry->dr_smp_agent == mad_agent) ||
- (entry->lr_smp_agent == mad_agent) ||
+ if ((entry->smp_agent == mad_agent) ||
(entry->perf_mgmt_agent == mad_agent))
return entry;
}
@@ -111,7 +107,7 @@ int smi_check_local_dr_smp(struct ib_smp *smp,
return 1;
}
- return smi_check_local_smp(port_priv->dr_smp_agent, smp);
+ return smi_check_local_smp(port_priv->smp_agent, smp);
}
static int agent_mad_send(struct ib_mad_agent *mad_agent,
@@ -231,10 +227,8 @@ int agent_send(struct ib_mad_private *mad,
/* Get mad agent based on mgmt_class in MAD */
switch (mad->mad.mad.mad_hdr.mgmt_class) {
case IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE:
- mad_agent = port_priv->dr_smp_agent;
- break;
case IB_MGMT_CLASS_SUBN_LID_ROUTED:
- mad_agent = port_priv->lr_smp_agent;
+ mad_agent = port_priv->smp_agent;
break;
case IB_MGMT_CLASS_PERF_MGMT:
mad_agent = port_priv->perf_mgmt_agent;
@@ -284,7 +278,6 @@ int ib_agent_port_open(struct ib_device *device, int port_num)
{
int ret;
struct ib_agent_port_private *port_priv;
- struct ib_mad_reg_req reg_req;
unsigned long flags;
/* First, check if port already open for SMI */
@@ -308,35 +301,19 @@ int ib_agent_port_open(struct ib_device *device, int port_num)
spin_lock_init(&port_priv->send_list_lock);
INIT_LIST_HEAD(&port_priv->send_posted_list);
- /* Obtain MAD agent for directed route SM class */
- reg_req.mgmt_class = IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE;
- reg_req.mgmt_class_version = 1;
+ /* Obtain send only MAD agent for SM class (SMI QP) */
+ port_priv->smp_agent = ib_register_mad_agent(device, port_num,
+ IB_QPT_SMI,
+ NULL, 0,
+ &agent_send_handler,
+ NULL, NULL);
- port_priv->dr_smp_agent = ib_register_mad_agent(device, port_num,
- IB_QPT_SMI,
- NULL, 0,
- &agent_send_handler,
- NULL, NULL);
-
- if (IS_ERR(port_priv->dr_smp_agent)) {
- ret = PTR_ERR(port_priv->dr_smp_agent);
+ if (IS_ERR(port_priv->smp_agent)) {
+ ret = PTR_ERR(port_priv->smp_agent);
goto error2;
}
- /* Obtain MAD agent for LID routed SM class */
- reg_req.mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED;
- port_priv->lr_smp_agent = ib_register_mad_agent(device, port_num,
- IB_QPT_SMI,
- NULL, 0,
- &agent_send_handler,
- NULL, NULL);
- if (IS_ERR(port_priv->lr_smp_agent)) {
- ret = PTR_ERR(port_priv->lr_smp_agent);
- goto error3;
- }
-
- /* Obtain MAD agent for PerfMgmt class */
- reg_req.mgmt_class = IB_MGMT_CLASS_PERF_MGMT;
+ /* Obtain send only MAD agent for PerfMgmt class (GSI QP) */
port_priv->perf_mgmt_agent = ib_register_mad_agent(device, port_num,
IB_QPT_GSI,
NULL, 0,
@@ -344,15 +321,15 @@ int ib_agent_port_open(struct ib_device *device, int port_num)
NULL, NULL);
if (IS_ERR(port_priv->perf_mgmt_agent)) {
ret = PTR_ERR(port_priv->perf_mgmt_agent);
- goto error4;
+ goto error3;
}
- port_priv->mr = ib_get_dma_mr(port_priv->dr_smp_agent->qp->pd,
+ port_priv->mr = ib_get_dma_mr(port_priv->smp_agent->qp->pd,
IB_ACCESS_LOCAL_WRITE);
if (IS_ERR(port_priv->mr)) {
printk(KERN_ERR SPFX "Couldn't get DMA MR\n");
ret = PTR_ERR(port_priv->mr);
- goto error5;
+ goto error4;
}
spin_lock_irqsave(&ib_agent_port_list_lock, flags);
@@ -361,12 +338,10 @@ int ib_agent_port_open(struct ib_device *device, int port_num)
return 0;
-error5:
- ib_unregister_mad_agent(port_priv->perf_mgmt_agent);
error4:
- ib_unregister_mad_agent(port_priv->lr_smp_agent);
+ ib_unregister_mad_agent(port_priv->perf_mgmt_agent);
error3:
- ib_unregister_mad_agent(port_priv->dr_smp_agent);
+ ib_unregister_mad_agent(port_priv->smp_agent);
error2:
kfree(port_priv);
error1:
@@ -391,8 +366,7 @@ int ib_agent_port_close(struct ib_device *device, int port_num)
ib_dereg_mr(port_priv->mr);
ib_unregister_mad_agent(port_priv->perf_mgmt_agent);
- ib_unregister_mad_agent(port_priv->lr_smp_agent);
- ib_unregister_mad_agent(port_priv->dr_smp_agent);
+ ib_unregister_mad_agent(port_priv->smp_agent);
kfree(port_priv);
return 0;
diff --git a/drivers/infiniband/core/agent_priv.h b/drivers/infiniband/core/agent_priv.h
index 3b63338f12af4..17a0cce5813cb 100644
--- a/drivers/infiniband/core/agent_priv.h
+++ b/drivers/infiniband/core/agent_priv.h
@@ -55,8 +55,7 @@ struct ib_agent_port_private {
struct list_head send_posted_list;
spinlock_t send_list_lock;
int port_num;
- struct ib_mad_agent *dr_smp_agent; /* DR SM class */
- struct ib_mad_agent *lr_smp_agent; /* LR SM class */
+ struct ib_mad_agent *smp_agent; /* SM class */
struct ib_mad_agent *perf_mgmt_agent; /* PerfMgmt class */
struct ib_mr *mr;
};
diff --git a/drivers/infiniband/core/cache.c b/drivers/infiniband/core/cache.c
index f70fbfa11da77..3042360c97e19 100644
--- a/drivers/infiniband/core/cache.c
+++ b/drivers/infiniband/core/cache.c
@@ -37,6 +37,8 @@
#include <linux/errno.h>
#include <linux/slab.h>
+#include <ib_cache.h>
+
#include "core_priv.h"
struct ib_pkey_cache {
@@ -112,7 +114,7 @@ int ib_find_cached_gid(struct ib_device *device,
cache = device->cache.gid_cache[p];
for (i = 0; i < cache->table_len; ++i) {
if (!memcmp(gid, &cache->table[i], sizeof *gid)) {
- *port_num = p;
+ *port_num = p + start_port(device);
if (index)
*index = i;
ret = 0;
diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c
index 754a2c5f702cd..4ec7fff29b5d6 100644
--- a/drivers/infiniband/core/mad.c
+++ b/drivers/infiniband/core/mad.c
@@ -41,7 +41,6 @@
#include "smi.h"
#include "agent.h"
-
MODULE_LICENSE("Dual BSD/GPL");
MODULE_DESCRIPTION("kernel IB MAD API");
MODULE_AUTHOR("Hal Rosenstock");
@@ -69,6 +68,7 @@ static void cancel_mads(struct ib_mad_agent_private *mad_agent_priv);
static void ib_mad_complete_send_wr(struct ib_mad_send_wr_private *mad_send_wr,
struct ib_mad_send_wc *mad_send_wc);
static void timeout_sends(void *data);
+static void cancel_sends(void *data);
static void local_completions(void *data);
static int solicited_mad(struct ib_mad *mad);
static int add_nonoui_reg_req(struct ib_mad_reg_req *mad_reg_req,
@@ -342,6 +342,8 @@ struct ib_mad_agent *ib_register_mad_agent(struct ib_device *device,
INIT_LIST_HEAD(&mad_agent_priv->local_list);
INIT_WORK(&mad_agent_priv->local_work, local_completions,
mad_agent_priv);
+ INIT_LIST_HEAD(&mad_agent_priv->canceled_list);
+ INIT_WORK(&mad_agent_priv->canceled_work, cancel_sends, mad_agent_priv);
atomic_set(&mad_agent_priv->refcount, 1);
init_waitqueue_head(&mad_agent_priv->wait);
@@ -490,6 +492,7 @@ static void unregister_mad_agent(struct ib_mad_agent_private *mad_agent_priv)
cancel_mads(mad_agent_priv);
port_priv = mad_agent_priv->qp_info->port_priv;
+
cancel_delayed_work(&mad_agent_priv->timed_work);
flush_workqueue(port_priv->wq);
@@ -643,7 +646,7 @@ static int handle_outgoing_dr_smp(struct ib_mad_agent_private *mad_agent_priv,
struct ib_smp *smp,
struct ib_send_wr *send_wr)
{
- int ret, alloc_flags, solicited;
+ int ret, solicited;
unsigned long flags;
struct ib_mad_local_private *local;
struct ib_mad_private *mad_priv;
@@ -663,11 +666,7 @@ static int handle_outgoing_dr_smp(struct ib_mad_agent_private *mad_agent_priv,
if (!ret || !device->process_mad)
goto out;
- if (in_atomic() || irqs_disabled())
- alloc_flags = GFP_ATOMIC;
- else
- alloc_flags = GFP_KERNEL;
- local = kmalloc(sizeof *local, alloc_flags);
+ local = kmalloc(sizeof *local, GFP_ATOMIC);
if (!local) {
ret = -ENOMEM;
printk(KERN_ERR PFX "No memory for ib_mad_local_private\n");
@@ -675,7 +674,7 @@ static int handle_outgoing_dr_smp(struct ib_mad_agent_private *mad_agent_priv,
}
local->mad_priv = NULL;
local->recv_mad_agent = NULL;
- mad_priv = kmem_cache_alloc(ib_mad_cache, alloc_flags);
+ mad_priv = kmem_cache_alloc(ib_mad_cache, GFP_ATOMIC);
if (!mad_priv) {
ret = -ENOMEM;
printk(KERN_ERR PFX "No memory for local response MAD\n");
@@ -857,9 +856,7 @@ int ib_post_send_mad(struct ib_mad_agent *mad_agent,
}
/* Allocate MAD send WR tracking structure */
- mad_send_wr = kmalloc(sizeof *mad_send_wr,
- (in_atomic() || irqs_disabled()) ?
- GFP_ATOMIC : GFP_KERNEL);
+ mad_send_wr = kmalloc(sizeof *mad_send_wr, GFP_ATOMIC);
if (!mad_send_wr) {
printk(KERN_ERR PFX "No memory for "
"ib_mad_send_wr_private\n");
@@ -1266,12 +1263,12 @@ static void remove_mad_reg_req(struct ib_mad_agent_private *agent_priv)
}
port_priv = agent_priv->qp_info->port_priv;
+ mgmt_class = convert_mgmt_class(agent_priv->reg_req->mgmt_class);
class = port_priv->version[
agent_priv->reg_req->mgmt_class_version].class;
if (!class)
goto vendor_check;
- mgmt_class = convert_mgmt_class(agent_priv->reg_req->mgmt_class);
method = class->method_table[mgmt_class];
if (method) {
/* Remove any methods for this mad agent */
@@ -1293,16 +1290,21 @@ static void remove_mad_reg_req(struct ib_mad_agent_private *agent_priv)
}
vendor_check:
+ if (!is_vendor_class(mgmt_class))
+ goto out;
+
+ /* normalize mgmt_class to vendor range 2 */
+ mgmt_class = vendor_class_index(agent_priv->reg_req->mgmt_class);
vendor = port_priv->version[
agent_priv->reg_req->mgmt_class_version].vendor;
+
if (!vendor)
goto out;
- mgmt_class = vendor_class_index(agent_priv->reg_req->mgmt_class);
vendor_class = vendor->vendor_class[mgmt_class];
if (vendor_class) {
index = find_vendor_oui(vendor_class, agent_priv->reg_req->oui);
- if (index == -1)
+ if (index < 0)
goto out;
method = vendor_class->method_table[index];
if (method) {
@@ -1999,12 +2001,44 @@ find_send_by_wr_id(struct ib_mad_agent_private *mad_agent_priv,
return NULL;
}
+void cancel_sends(void *data)
+{
+ struct ib_mad_agent_private *mad_agent_priv;
+ struct ib_mad_send_wr_private *mad_send_wr;
+ struct ib_mad_send_wc mad_send_wc;
+ unsigned long flags;
+
+ mad_agent_priv = data;
+
+ mad_send_wc.status = IB_WC_WR_FLUSH_ERR;
+ mad_send_wc.vendor_err = 0;
+
+ spin_lock_irqsave(&mad_agent_priv->lock, flags);
+ while (!list_empty(&mad_agent_priv->canceled_list)) {
+ mad_send_wr = list_entry(mad_agent_priv->canceled_list.next,
+ struct ib_mad_send_wr_private,
+ agent_list);
+
+ list_del(&mad_send_wr->agent_list);
+ spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
+
+ mad_send_wc.wr_id = mad_send_wr->wr_id;
+ mad_agent_priv->agent.send_handler(&mad_agent_priv->agent,
+ &mad_send_wc);
+
+ kfree(mad_send_wr);
+ if (atomic_dec_and_test(&mad_agent_priv->refcount))
+ wake_up(&mad_agent_priv->wait);
+ spin_lock_irqsave(&mad_agent_priv->lock, flags);
+ }
+ spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
+}
+
void ib_cancel_mad(struct ib_mad_agent *mad_agent,
u64 wr_id)
{
struct ib_mad_agent_private *mad_agent_priv;
struct ib_mad_send_wr_private *mad_send_wr;
- struct ib_mad_send_wc mad_send_wc;
unsigned long flags;
mad_agent_priv = container_of(mad_agent, struct ib_mad_agent_private,
@@ -2026,19 +2060,12 @@ void ib_cancel_mad(struct ib_mad_agent *mad_agent,
}
list_del(&mad_send_wr->agent_list);
+ list_add_tail(&mad_send_wr->agent_list, &mad_agent_priv->canceled_list);
adjust_timeout(mad_agent_priv);
spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
- mad_send_wc.status = IB_WC_WR_FLUSH_ERR;
- mad_send_wc.vendor_err = 0;
- mad_send_wc.wr_id = mad_send_wr->wr_id;
- mad_agent_priv->agent.send_handler(&mad_agent_priv->agent,
- &mad_send_wc);
-
- kfree(mad_send_wr);
- if (atomic_dec_and_test(&mad_agent_priv->refcount))
- wake_up(&mad_agent_priv->wait);
-
+ queue_work(mad_agent_priv->qp_info->port_priv->wq,
+ &mad_agent_priv->canceled_work);
out:
return;
}
@@ -2186,7 +2213,6 @@ static int ib_mad_post_receive_mads(struct ib_mad_qp_info *qp_info,
recv_wr.next = NULL;
recv_wr.sg_list = &sg_list;
recv_wr.num_sge = 1;
- recv_wr.recv_flags = IB_RECV_SIGNALED;
do {
/* Allocate and map receive buffer */
@@ -2381,7 +2407,6 @@ static int create_mad_qp(struct ib_mad_qp_info *qp_info,
qp_init_attr.send_cq = qp_info->port_priv->cq;
qp_init_attr.recv_cq = qp_info->port_priv->cq;
qp_init_attr.sq_sig_type = IB_SIGNAL_ALL_WR;
- qp_init_attr.rq_sig_type = IB_SIGNAL_ALL_WR;
qp_init_attr.cap.max_send_wr = IB_MAD_QP_SEND_SIZE;
qp_init_attr.cap.max_recv_wr = IB_MAD_QP_RECV_SIZE;
qp_init_attr.cap.max_send_sge = IB_MAD_SEND_REQ_MAX_SG;
diff --git a/drivers/infiniband/core/mad_priv.h b/drivers/infiniband/core/mad_priv.h
index 6110320b4db5c..4ba9f726bf1d8 100644
--- a/drivers/infiniband/core/mad_priv.h
+++ b/drivers/infiniband/core/mad_priv.h
@@ -58,8 +58,8 @@
#define MAX_MGMT_CLASS 80
#define MAX_MGMT_VERSION 8
#define MAX_MGMT_OUI 8
-#define MAX_MGMT_VENDOR_RANGE2 IB_MGMT_CLASS_VENDOR_RANGE2_END - \
- IB_MGMT_CLASS_VENDOR_RANGE2_START + 1
+#define MAX_MGMT_VENDOR_RANGE2 (IB_MGMT_CLASS_VENDOR_RANGE2_END - \
+ IB_MGMT_CLASS_VENDOR_RANGE2_START + 1)
struct ib_mad_list_head {
struct list_head list;
@@ -95,6 +95,8 @@ struct ib_mad_agent_private {
unsigned long timeout;
struct list_head local_list;
struct work_struct local_work;
+ struct list_head canceled_list;
+ struct work_struct canceled_work;
atomic_t refcount;
wait_queue_head_t wait;
@@ -192,4 +194,6 @@ struct ib_mad_port_private {
struct ib_mad_qp_info qp_info[IB_MAD_QPS_CORE];
};
+extern kmem_cache_t *ib_mad_cache;
+
#endif /* __IB_MAD_PRIV_H__ */
diff --git a/drivers/infiniband/core/smi.c b/drivers/infiniband/core/smi.c
index 6adf653704fc2..b4b284324a33a 100644
--- a/drivers/infiniband/core/smi.c
+++ b/drivers/infiniband/core/smi.c
@@ -37,7 +37,7 @@
*/
#include <ib_smi.h>
-
+#include "smi.h"
/*
* Fixup a directed route SMP for sending
diff --git a/drivers/infiniband/hw/mthca/Makefile b/drivers/infiniband/hw/mthca/Makefile
index e453ebc985445..5dcbd43073e24 100644
--- a/drivers/infiniband/hw/mthca/Makefile
+++ b/drivers/infiniband/hw/mthca/Makefile
@@ -9,4 +9,4 @@ obj-$(CONFIG_INFINIBAND_MTHCA) += ib_mthca.o
ib_mthca-y := mthca_main.o mthca_cmd.o mthca_profile.o mthca_reset.o \
mthca_allocator.o mthca_eq.o mthca_pd.o mthca_cq.o \
mthca_mr.o mthca_qp.o mthca_av.o mthca_mcg.o mthca_mad.o \
- mthca_provider.o mthca_memfree.o
+ mthca_provider.o mthca_memfree.o mthca_uar.o
diff --git a/drivers/infiniband/hw/mthca/mthca_av.c b/drivers/infiniband/hw/mthca/mthca_av.c
index ee7f1dc3a3911..426d32778e9c9 100644
--- a/drivers/infiniband/hw/mthca/mthca_av.c
+++ b/drivers/infiniband/hw/mthca/mthca_av.c
@@ -60,27 +60,34 @@ int mthca_create_ah(struct mthca_dev *dev,
u32 index = -1;
struct mthca_av *av = NULL;
- ah->on_hca = 0;
+ ah->type = MTHCA_AH_PCI_POOL;
- if (!atomic_read(&pd->sqp_count) &&
- !(dev->mthca_flags & MTHCA_FLAG_DDR_HIDDEN)) {
+ if (dev->hca_type == ARBEL_NATIVE) {
+ ah->av = kmalloc(sizeof *ah->av, GFP_KERNEL);
+ if (!ah->av)
+ return -ENOMEM;
+
+ ah->type = MTHCA_AH_KMALLOC;
+ av = ah->av;
+ } else if (!atomic_read(&pd->sqp_count) &&
+ !(dev->mthca_flags & MTHCA_FLAG_DDR_HIDDEN)) {
index = mthca_alloc(&dev->av_table.alloc);
/* fall back to allocate in host memory */
if (index == -1)
- goto host_alloc;
+ goto on_hca_fail;
av = kmalloc(sizeof *av, GFP_KERNEL);
if (!av)
- goto host_alloc;
+ goto on_hca_fail;
- ah->on_hca = 1;
+ ah->type = MTHCA_AH_ON_HCA;
ah->avdma = dev->av_table.ddr_av_base +
index * MTHCA_AV_SIZE;
}
- host_alloc:
- if (!ah->on_hca) {
+on_hca_fail:
+ if (ah->type == MTHCA_AH_PCI_POOL) {
ah->av = pci_pool_alloc(dev->av_table.pool,
SLAB_KERNEL, &ah->avdma);
if (!ah->av)
@@ -123,7 +130,7 @@ int mthca_create_ah(struct mthca_dev *dev,
j * 4, be32_to_cpu(((u32 *) av)[j]));
}
- if (ah->on_hca) {
+ if (ah->type == MTHCA_AH_ON_HCA) {
memcpy_toio(dev->av_table.av_map + index * MTHCA_AV_SIZE,
av, MTHCA_AV_SIZE);
kfree(av);
@@ -134,12 +141,21 @@ int mthca_create_ah(struct mthca_dev *dev,
int mthca_destroy_ah(struct mthca_dev *dev, struct mthca_ah *ah)
{
- if (ah->on_hca)
+ switch (ah->type) {
+ case MTHCA_AH_ON_HCA:
mthca_free(&dev->av_table.alloc,
(ah->avdma - dev->av_table.ddr_av_base) /
MTHCA_AV_SIZE);
- else
+ break;
+
+ case MTHCA_AH_PCI_POOL:
pci_pool_free(dev->av_table.pool, ah->av, ah->avdma);
+ break;
+
+ case MTHCA_AH_KMALLOC:
+ kfree(ah->av);
+ break;
+ }
return 0;
}
@@ -147,7 +163,7 @@ 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)
{
- if (ah->on_hca)
+ if (ah->type == MTHCA_AH_ON_HCA)
return -EINVAL;
header->lrh.service_level = be32_to_cpu(ah->av->sl_tclass_flowlabel) >> 28;
@@ -176,6 +192,9 @@ int __devinit mthca_init_av_table(struct mthca_dev *dev)
{
int err;
+ if (dev->hca_type == ARBEL_NATIVE)
+ return 0;
+
err = mthca_alloc_init(&dev->av_table.alloc,
dev->av_table.num_ddr_avs,
dev->av_table.num_ddr_avs - 1,
@@ -212,6 +231,9 @@ int __devinit mthca_init_av_table(struct mthca_dev *dev)
void __devexit mthca_cleanup_av_table(struct mthca_dev *dev)
{
+ if (dev->hca_type == ARBEL_NATIVE)
+ return;
+
if (dev->av_table.av_map)
iounmap(dev->av_table.av_map);
pci_pool_destroy(dev->av_table.pool);
diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.c b/drivers/infiniband/hw/mthca/mthca_cmd.c
index a82ca9dc6500f..9def0981f6308 100644
--- a/drivers/infiniband/hw/mthca/mthca_cmd.c
+++ b/drivers/infiniband/hw/mthca/mthca_cmd.c
@@ -1290,7 +1290,7 @@ int mthca_MAP_ICM_page(struct mthca_dev *dev, u64 dma_addr, u64 virt, u8 *status
return -ENOMEM;
inbox[0] = cpu_to_be64(virt);
- inbox[1] = cpu_to_be64(dma_addr | (PAGE_SHIFT - 12));
+ inbox[1] = cpu_to_be64(dma_addr);
err = mthca_cmd(dev, indma, 1, 0, CMD_MAP_ICM, CMD_TIME_CLASS_B, status);
@@ -1305,6 +1305,9 @@ int mthca_MAP_ICM_page(struct mthca_dev *dev, u64 dma_addr, u64 virt, u8 *status
int mthca_UNMAP_ICM(struct mthca_dev *dev, u64 virt, u32 page_count, u8 *status)
{
+ mthca_dbg(dev, "Unmapping %d pages at %llx from ICM.\n",
+ page_count, (unsigned long long) virt);
+
return mthca_cmd(dev, virt, page_count, 0, CMD_UNMAP_ICM, CMD_TIME_CLASS_B, status);
}
@@ -1538,10 +1541,10 @@ int mthca_MODIFY_QP(struct mthca_dev *dev, int trans, u32 num,
if (0) {
int i;
mthca_dbg(dev, "Dumping QP context:\n");
- printk(" %08x\n", be32_to_cpup(qp_context));
+ printk(" opt param mask: %08x\n", be32_to_cpup(qp_context));
for (i = 0; i < 0x100 / 4; ++i) {
if (i % 8 == 0)
- printk("[%02x] ", i * 4);
+ printk(" [%02x] ", i * 4);
printk(" %08x", be32_to_cpu(((u32 *) qp_context)[i + 2]));
if ((i + 1) % 8 == 0)
printk("\n");
diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.h b/drivers/infiniband/hw/mthca/mthca_cmd.h
index 3b2f9692b6fed..a8bc6aa36ff19 100644
--- a/drivers/infiniband/hw/mthca/mthca_cmd.h
+++ b/drivers/infiniband/hw/mthca/mthca_cmd.h
@@ -95,7 +95,21 @@ enum {
};
enum {
- DEV_LIM_FLAG_SRQ = 1 << 6
+ DEV_LIM_FLAG_RC = 1 << 0,
+ DEV_LIM_FLAG_UC = 1 << 1,
+ DEV_LIM_FLAG_UD = 1 << 2,
+ DEV_LIM_FLAG_RD = 1 << 3,
+ DEV_LIM_FLAG_RAW_IPV6 = 1 << 4,
+ DEV_LIM_FLAG_RAW_ETHER = 1 << 5,
+ DEV_LIM_FLAG_SRQ = 1 << 6,
+ DEV_LIM_FLAG_BAD_PKEY_CNTR = 1 << 8,
+ DEV_LIM_FLAG_BAD_QKEY_CNTR = 1 << 9,
+ DEV_LIM_FLAG_MW = 1 << 16,
+ DEV_LIM_FLAG_AUTO_PATH_MIG = 1 << 17,
+ DEV_LIM_FLAG_ATOMIC = 1 << 18,
+ DEV_LIM_FLAG_RAW_MULTI = 1 << 19,
+ DEV_LIM_FLAG_UD_AV_PORT_ENFORCE = 1 << 20,
+ DEV_LIM_FLAG_UD_MULTI = 1 << 21,
};
struct mthca_dev_lim {
diff --git a/drivers/infiniband/hw/mthca/mthca_config_reg.h b/drivers/infiniband/hw/mthca/mthca_config_reg.h
index acb94ae0ea57d..b4bfbbfe2c3df 100644
--- a/drivers/infiniband/hw/mthca/mthca_config_reg.h
+++ b/drivers/infiniband/hw/mthca/mthca_config_reg.h
@@ -46,5 +46,6 @@
#define MTHCA_MAP_ECR_SIZE (MTHCA_ECR_SIZE + MTHCA_ECR_CLR_SIZE)
#define MTHCA_CLR_INT_BASE 0xf00d8
#define MTHCA_CLR_INT_SIZE 0x00008
+#define MTHCA_EQ_SET_CI_SIZE (8 * 32)
#endif /* MTHCA_CONFIG_REG_H */
diff --git a/drivers/infiniband/hw/mthca/mthca_cq.c b/drivers/infiniband/hw/mthca/mthca_cq.c
index 38f6d14e916fb..5dead2df7eb06 100644
--- a/drivers/infiniband/hw/mthca/mthca_cq.c
+++ b/drivers/infiniband/hw/mthca/mthca_cq.c
@@ -33,11 +33,13 @@
*/
#include <linux/init.h>
+#include <linux/hardirq.h>
#include <ib_pack.h>
#include "mthca_dev.h"
#include "mthca_cmd.h"
+#include "mthca_memfree.h"
enum {
MTHCA_MAX_DIRECT_CQ_SIZE = 4 * PAGE_SIZE
@@ -54,7 +56,7 @@ struct mthca_cq_context {
u32 flags;
u64 start;
u32 logsize_usrpage;
- u32 error_eqn;
+ u32 error_eqn; /* Tavor only */
u32 comp_eqn;
u32 pd;
u32 lkey;
@@ -63,7 +65,9 @@ struct mthca_cq_context {
u32 consumer_index;
u32 producer_index;
u32 cqn;
- u32 reserved[3];
+ u32 ci_db; /* Arbel only */
+ u32 state_db; /* Arbel only */
+ u32 reserved;
} __attribute__((packed));
#define MTHCA_CQ_STATUS_OK ( 0 << 28)
@@ -132,11 +136,15 @@ struct mthca_err_cqe {
#define MTHCA_CQ_ENTRY_OWNER_SW (0 << 7)
#define MTHCA_CQ_ENTRY_OWNER_HW (1 << 7)
-#define MTHCA_CQ_DB_INC_CI (1 << 24)
-#define MTHCA_CQ_DB_REQ_NOT (2 << 24)
-#define MTHCA_CQ_DB_REQ_NOT_SOL (3 << 24)
-#define MTHCA_CQ_DB_SET_CI (4 << 24)
-#define MTHCA_CQ_DB_REQ_NOT_MULT (5 << 24)
+#define MTHCA_TAVOR_CQ_DB_INC_CI (1 << 24)
+#define MTHCA_TAVOR_CQ_DB_REQ_NOT (2 << 24)
+#define MTHCA_TAVOR_CQ_DB_REQ_NOT_SOL (3 << 24)
+#define MTHCA_TAVOR_CQ_DB_SET_CI (4 << 24)
+#define MTHCA_TAVOR_CQ_DB_REQ_NOT_MULT (5 << 24)
+
+#define MTHCA_ARBEL_CQ_DB_REQ_NOT_SOL (1 << 24)
+#define MTHCA_ARBEL_CQ_DB_REQ_NOT (2 << 24)
+#define MTHCA_ARBEL_CQ_DB_REQ_NOT_MULT (3 << 24)
static inline struct mthca_cqe *get_cqe(struct mthca_cq *cq, int entry)
{
@@ -147,54 +155,58 @@ static inline struct mthca_cqe *get_cqe(struct mthca_cq *cq, int entry)
+ (entry * MTHCA_CQ_ENTRY_SIZE) % PAGE_SIZE;
}
-static inline int cqe_sw(struct mthca_cq *cq, int i)
+static inline struct mthca_cqe *cqe_sw(struct mthca_cq *cq, int i)
{
- return !(MTHCA_CQ_ENTRY_OWNER_HW &
- get_cqe(cq, i)->owner);
+ struct mthca_cqe *cqe = get_cqe(cq, i);
+ return MTHCA_CQ_ENTRY_OWNER_HW & cqe->owner ? NULL : cqe;
}
-static inline int next_cqe_sw(struct mthca_cq *cq)
+static inline struct mthca_cqe *next_cqe_sw(struct mthca_cq *cq)
{
- return cqe_sw(cq, cq->cons_index);
+ return cqe_sw(cq, cq->cons_index & cq->ibcq.cqe);
}
-static inline void set_cqe_hw(struct mthca_cq *cq, int entry)
+static inline void set_cqe_hw(struct mthca_cqe *cqe)
{
- get_cqe(cq, entry)->owner = MTHCA_CQ_ENTRY_OWNER_HW;
+ cqe->owner = MTHCA_CQ_ENTRY_OWNER_HW;
}
-static inline void inc_cons_index(struct mthca_dev *dev, struct mthca_cq *cq,
- int nent)
+/*
+ * incr is ignored in native Arbel (mem-free) mode, so cq->cons_index
+ * should be correct before calling update_cons_index().
+ */
+static inline void update_cons_index(struct mthca_dev *dev, struct mthca_cq *cq,
+ int incr)
{
u32 doorbell[2];
- doorbell[0] = cpu_to_be32(MTHCA_CQ_DB_INC_CI | cq->cqn);
- doorbell[1] = cpu_to_be32(nent - 1);
+ if (dev->hca_type == ARBEL_NATIVE) {
+ *cq->set_ci_db = cpu_to_be32(cq->cons_index);
+ wmb();
+ } else {
+ doorbell[0] = cpu_to_be32(MTHCA_TAVOR_CQ_DB_INC_CI | cq->cqn);
+ doorbell[1] = cpu_to_be32(incr - 1);
- mthca_write64(doorbell,
- dev->kar + MTHCA_CQ_DOORBELL,
- MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock));
+ mthca_write64(doorbell,
+ dev->kar + MTHCA_CQ_DOORBELL,
+ MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock));
+ }
}
void mthca_cq_event(struct mthca_dev *dev, u32 cqn)
{
struct mthca_cq *cq;
- spin_lock(&dev->cq_table.lock);
cq = mthca_array_get(&dev->cq_table.cq, cqn & (dev->limits.num_cqs - 1));
- if (cq)
- atomic_inc(&cq->refcount);
- spin_unlock(&dev->cq_table.lock);
if (!cq) {
mthca_warn(dev, "Completion event for bogus CQ %08x\n", cqn);
return;
}
- cq->ibcq.comp_handler(&cq->ibcq, cq->ibcq.cq_context);
+ ++cq->arm_sn;
- if (atomic_dec_and_test(&cq->refcount))
- wake_up(&cq->wait);
+ cq->ibcq.comp_handler(&cq->ibcq, cq->ibcq.cq_context);
}
void mthca_cq_clean(struct mthca_dev *dev, u32 cqn, u32 qpn)
@@ -250,8 +262,8 @@ void mthca_cq_clean(struct mthca_dev *dev, u32 cqn, u32 qpn)
if (nfreed) {
wmb();
- inc_cons_index(dev, cq, nfreed);
- cq->cons_index = (cq->cons_index + nfreed) & cq->ibcq.cqe;
+ cq->cons_index += nfreed;
+ update_cons_index(dev, cq, nfreed);
}
spin_unlock_irq(&cq->lock);
@@ -344,7 +356,7 @@ static int handle_error_cqe(struct mthca_dev *dev, struct mthca_cq *cq,
break;
}
- err = mthca_free_err_wqe(qp, is_send, wqe_index, &dbd, &new_wqe);
+ err = mthca_free_err_wqe(dev, qp, is_send, wqe_index, &dbd, &new_wqe);
if (err)
return err;
@@ -383,12 +395,13 @@ static inline int mthca_poll_one(struct mthca_dev *dev,
struct mthca_wq *wq;
struct mthca_cqe *cqe;
int wqe_index;
- int is_error = 0;
+ int is_error;
int is_send;
int free_cqe = 1;
int err = 0;
- if (!next_cqe_sw(cq))
+ cqe = next_cqe_sw(cq);
+ if (!cqe)
return -EAGAIN;
/*
@@ -397,8 +410,6 @@ static inline int mthca_poll_one(struct mthca_dev *dev,
*/
rmb();
- cqe = get_cqe(cq, cq->cons_index);
-
if (0) {
mthca_dbg(dev, "%x/%d: CQE -> QPN %06x, WQE @ %08x\n",
cq->cqn, cq->cons_index, be32_to_cpu(cqe->my_qpn),
@@ -407,39 +418,25 @@ static inline int mthca_poll_one(struct mthca_dev *dev,
dump_cqe(cqe);
}
- if ((cqe->opcode & MTHCA_ERROR_CQE_OPCODE_MASK) ==
- MTHCA_ERROR_CQE_OPCODE_MASK) {
- is_error = 1;
- is_send = cqe->opcode & 1;
- } else
- is_send = cqe->is_send & 0x80;
+ is_error = (cqe->opcode & MTHCA_ERROR_CQE_OPCODE_MASK) ==
+ MTHCA_ERROR_CQE_OPCODE_MASK;
+ is_send = is_error ? cqe->opcode & 0x01 : cqe->is_send & 0x80;
if (!*cur_qp || be32_to_cpu(cqe->my_qpn) != (*cur_qp)->qpn) {
- if (*cur_qp) {
- if (*freed) {
- wmb();
- inc_cons_index(dev, cq, *freed);
- *freed = 0;
- }
- spin_unlock(&(*cur_qp)->lock);
- }
-
- spin_lock(&dev->qp_table.lock);
+ /*
+ * We do not have to take the QP table lock here,
+ * because CQs will be locked while QPs are removed
+ * from the table.
+ */
*cur_qp = mthca_array_get(&dev->qp_table.qp,
be32_to_cpu(cqe->my_qpn) &
(dev->limits.num_qps - 1));
- if (*cur_qp)
- atomic_inc(&(*cur_qp)->refcount);
- spin_unlock(&dev->qp_table.lock);
-
if (!*cur_qp) {
mthca_warn(dev, "CQ entry for unknown QP %06x\n",
be32_to_cpu(cqe->my_qpn) & 0xffffff);
err = -EINVAL;
goto out;
}
-
- spin_lock(&(*cur_qp)->lock);
}
entry->qp_num = (*cur_qp)->qpn;
@@ -457,9 +454,9 @@ static inline int mthca_poll_one(struct mthca_dev *dev,
}
if (wq->last_comp < wqe_index)
- wq->cur -= wqe_index - wq->last_comp;
+ wq->tail += wqe_index - wq->last_comp;
else
- wq->cur -= wq->max - wq->last_comp + wqe_index;
+ wq->tail += wqe_index + wq->max - wq->last_comp;
wq->last_comp = wqe_index;
@@ -509,10 +506,10 @@ static inline int mthca_poll_one(struct mthca_dev *dev,
entry->status = IB_WC_SUCCESS;
out:
- if (free_cqe) {
- set_cqe_hw(cq, cq->cons_index);
+ if (likely(free_cqe)) {
+ set_cqe_hw(cqe);
++(*freed);
- cq->cons_index = (cq->cons_index + 1) & cq->ibcq.cqe;
+ ++cq->cons_index;
}
return err;
@@ -540,63 +537,101 @@ int mthca_poll_cq(struct ib_cq *ibcq, int num_entries,
if (freed) {
wmb();
- inc_cons_index(dev, cq, freed);
- }
-
- if (qp) {
- spin_unlock(&qp->lock);
- if (atomic_dec_and_test(&qp->refcount))
- wake_up(&qp->wait);
+ update_cons_index(dev, cq, freed);
}
-
spin_unlock_irqrestore(&cq->lock, flags);
return err == 0 || err == -EAGAIN ? npolled : err;
}
-void mthca_arm_cq(struct mthca_dev *dev, struct mthca_cq *cq,
- int solicited)
+int mthca_tavor_arm_cq(struct ib_cq *cq, enum ib_cq_notify notify)
{
u32 doorbell[2];
- doorbell[0] = cpu_to_be32((solicited ?
- MTHCA_CQ_DB_REQ_NOT_SOL :
- MTHCA_CQ_DB_REQ_NOT) |
- cq->cqn);
+ doorbell[0] = cpu_to_be32((notify == IB_CQ_SOLICITED ?
+ MTHCA_TAVOR_CQ_DB_REQ_NOT_SOL :
+ MTHCA_TAVOR_CQ_DB_REQ_NOT) |
+ to_mcq(cq)->cqn);
doorbell[1] = 0xffffffff;
mthca_write64(doorbell,
- dev->kar + MTHCA_CQ_DOORBELL,
- MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock));
+ to_mdev(cq->device)->kar + MTHCA_CQ_DOORBELL,
+ MTHCA_GET_DOORBELL_LOCK(&to_mdev(cq->device)->doorbell_lock));
+
+ return 0;
}
-int mthca_init_cq(struct mthca_dev *dev, int nent,
- struct mthca_cq *cq)
+int mthca_arbel_arm_cq(struct ib_cq *ibcq, enum ib_cq_notify notify)
+{
+ struct mthca_cq *cq = to_mcq(ibcq);
+ u32 doorbell[2];
+ u32 sn;
+ u32 ci;
+
+ sn = cq->arm_sn & 3;
+ ci = cpu_to_be32(cq->cons_index);
+
+ doorbell[0] = ci;
+ doorbell[1] = cpu_to_be32((cq->cqn << 8) | (2 << 5) | (sn << 3) |
+ (notify == IB_CQ_SOLICITED ? 1 : 2));
+
+ mthca_write_db_rec(doorbell, cq->arm_db);
+
+ /*
+ * Make sure that the doorbell record in host memory is
+ * written before ringing the doorbell via PCI MMIO.
+ */
+ wmb();
+
+ doorbell[0] = cpu_to_be32((sn << 28) |
+ (notify == IB_CQ_SOLICITED ?
+ MTHCA_ARBEL_CQ_DB_REQ_NOT_SOL :
+ MTHCA_ARBEL_CQ_DB_REQ_NOT) |
+ cq->cqn);
+ doorbell[1] = ci;
+
+ mthca_write64(doorbell,
+ to_mdev(ibcq->device)->kar + MTHCA_CQ_DOORBELL,
+ MTHCA_GET_DOORBELL_LOCK(&to_mdev(ibcq->device)->doorbell_lock));
+
+ return 0;
+}
+
+static void mthca_free_cq_buf(struct mthca_dev *dev, struct mthca_cq *cq)
{
- int size = nent * MTHCA_CQ_ENTRY_SIZE;
- dma_addr_t t;
- void *mailbox = NULL;
- int npages, shift;
- u64 *dma_list = NULL;
- struct mthca_cq_context *cq_context;
- int err = -ENOMEM;
- u8 status;
int i;
+ int size;
- might_sleep();
+ if (cq->is_direct)
+ pci_free_consistent(dev->pdev,
+ (cq->ibcq.cqe + 1) * MTHCA_CQ_ENTRY_SIZE,
+ cq->queue.direct.buf,
+ pci_unmap_addr(&cq->queue.direct,
+ mapping));
+ else {
+ size = (cq->ibcq.cqe + 1) * MTHCA_CQ_ENTRY_SIZE;
+ for (i = 0; i < (size + PAGE_SIZE - 1) / PAGE_SIZE; ++i)
+ if (cq->queue.page_list[i].buf)
+ pci_free_consistent(dev->pdev, PAGE_SIZE,
+ cq->queue.page_list[i].buf,
+ pci_unmap_addr(&cq->queue.page_list[i],
+ mapping));
- mailbox = kmalloc(sizeof (struct mthca_cq_context) + MTHCA_CMD_MAILBOX_EXTRA,
- GFP_KERNEL);
- if (!mailbox)
- goto err_out;
+ kfree(cq->queue.page_list);
+ }
+}
- cq_context = MAILBOX_ALIGN(mailbox);
+static int mthca_alloc_cq_buf(struct mthca_dev *dev, int size,
+ struct mthca_cq *cq)
+{
+ int err = -ENOMEM;
+ int npages, shift;
+ u64 *dma_list = NULL;
+ dma_addr_t t;
+ int i;
if (size <= MTHCA_MAX_DIRECT_CQ_SIZE) {
- if (0)
- mthca_dbg(dev, "Creating direct CQ of size %d\n", size);
-
cq->is_direct = 1;
npages = 1;
shift = get_order(size) + PAGE_SHIFT;
@@ -604,7 +639,7 @@ int mthca_init_cq(struct mthca_dev *dev, int nent,
cq->queue.direct.buf = pci_alloc_consistent(dev->pdev,
size, &t);
if (!cq->queue.direct.buf)
- goto err_out;
+ return -ENOMEM;
pci_unmap_addr_set(&cq->queue.direct, mapping, t);
@@ -617,7 +652,7 @@ int mthca_init_cq(struct mthca_dev *dev, int nent,
dma_list = kmalloc(npages * sizeof *dma_list, GFP_KERNEL);
if (!dma_list)
- goto err_out_free;
+ goto err_free;
for (i = 0; i < npages; ++i)
dma_list[i] = t + i * (1 << shift);
@@ -626,12 +661,9 @@ int mthca_init_cq(struct mthca_dev *dev, int nent,
npages = (size + PAGE_SIZE - 1) / PAGE_SIZE;
shift = PAGE_SHIFT;
- if (0)
- mthca_dbg(dev, "Creating indirect CQ with %d pages\n", npages);
-
dma_list = kmalloc(npages * sizeof *dma_list, GFP_KERNEL);
if (!dma_list)
- goto err_out;
+ return -ENOMEM;
cq->queue.page_list = kmalloc(npages * sizeof *cq->queue.page_list,
GFP_KERNEL);
@@ -645,7 +677,7 @@ int mthca_init_cq(struct mthca_dev *dev, int nent,
cq->queue.page_list[i].buf =
pci_alloc_consistent(dev->pdev, PAGE_SIZE, &t);
if (!cq->queue.page_list[i].buf)
- goto err_out_free;
+ goto err_free;
dma_list[i] = t;
pci_unmap_addr_set(&cq->queue.page_list[i], mapping, t);
@@ -654,13 +686,6 @@ int mthca_init_cq(struct mthca_dev *dev, int nent,
}
}
- for (i = 0; i < nent; ++i)
- set_cqe_hw(cq, i);
-
- cq->cqn = mthca_alloc(&dev->cq_table.alloc);
- if (cq->cqn == -1)
- goto err_out_free;
-
err = mthca_mr_alloc_phys(dev, dev->driver_pd.pd_num,
dma_list, shift, npages,
0, size,
@@ -668,7 +693,72 @@ int mthca_init_cq(struct mthca_dev *dev, int nent,
MTHCA_MPT_FLAG_LOCAL_READ,
&cq->mr);
if (err)
- goto err_out_free_cq;
+ goto err_free;
+
+ kfree(dma_list);
+
+ return 0;
+
+err_free:
+ mthca_free_cq_buf(dev, cq);
+
+err_out:
+ kfree(dma_list);
+
+ return err;
+}
+
+int mthca_init_cq(struct mthca_dev *dev, int nent,
+ struct mthca_cq *cq)
+{
+ int size = nent * MTHCA_CQ_ENTRY_SIZE;
+ void *mailbox = NULL;
+ struct mthca_cq_context *cq_context;
+ int err = -ENOMEM;
+ u8 status;
+ int i;
+
+ might_sleep();
+
+ cq->ibcq.cqe = nent - 1;
+
+ cq->cqn = mthca_alloc(&dev->cq_table.alloc);
+ if (cq->cqn == -1)
+ return -ENOMEM;
+
+ if (dev->hca_type == ARBEL_NATIVE) {
+ cq->arm_sn = 1;
+
+ err = mthca_table_get(dev, dev->cq_table.table, cq->cqn);
+ if (err)
+ goto err_out;
+
+ err = -ENOMEM;
+
+ cq->set_ci_db_index = mthca_alloc_db(dev, MTHCA_DB_TYPE_CQ_SET_CI,
+ cq->cqn, &cq->set_ci_db);
+ if (cq->set_ci_db_index < 0)
+ goto err_out_icm;
+
+ cq->arm_db_index = mthca_alloc_db(dev, MTHCA_DB_TYPE_CQ_ARM,
+ cq->cqn, &cq->arm_db);
+ if (cq->arm_db_index < 0)
+ goto err_out_ci;
+ }
+
+ mailbox = kmalloc(sizeof (struct mthca_cq_context) + MTHCA_CMD_MAILBOX_EXTRA,
+ GFP_KERNEL);
+ if (!mailbox)
+ goto err_out_mailbox;
+
+ cq_context = MAILBOX_ALIGN(mailbox);
+
+ err = mthca_alloc_cq_buf(dev, size, cq);
+ if (err)
+ goto err_out_mailbox;
+
+ for (i = 0; i < nent; ++i)
+ set_cqe_hw(get_cqe(cq, i));
spin_lock_init(&cq->lock);
atomic_set(&cq->refcount, 1);
@@ -680,13 +770,18 @@ int mthca_init_cq(struct mthca_dev *dev, int nent,
MTHCA_CQ_FLAG_TR);
cq_context->start = cpu_to_be64(0);
cq_context->logsize_usrpage = cpu_to_be32((ffs(nent) - 1) << 24 |
- MTHCA_KAR_PAGE);
+ dev->driver_uar.index);
cq_context->error_eqn = cpu_to_be32(dev->eq_table.eq[MTHCA_EQ_ASYNC].eqn);
cq_context->comp_eqn = cpu_to_be32(dev->eq_table.eq[MTHCA_EQ_COMP].eqn);
cq_context->pd = cpu_to_be32(dev->driver_pd.pd_num);
cq_context->lkey = cpu_to_be32(cq->mr.ibmr.lkey);
cq_context->cqn = cpu_to_be32(cq->cqn);
+ if (dev->hca_type == ARBEL_NATIVE) {
+ cq_context->ci_db = cpu_to_be32(cq->set_ci_db_index);
+ cq_context->state_db = cpu_to_be32(cq->arm_db_index);
+ }
+
err = mthca_SW2HW_CQ(dev, cq_context, cq->cqn, &status);
if (err) {
mthca_warn(dev, "SW2HW_CQ failed (%d)\n", err);
@@ -711,36 +806,27 @@ int mthca_init_cq(struct mthca_dev *dev, int nent,
cq->cons_index = 0;
- kfree(dma_list);
kfree(mailbox);
return 0;
- err_out_free_mr:
+err_out_free_mr:
mthca_free_mr(dev, &cq->mr);
+ mthca_free_cq_buf(dev, cq);
- err_out_free_cq:
- mthca_free(&dev->cq_table.alloc, cq->cqn);
+err_out_mailbox:
+ kfree(mailbox);
- err_out_free:
- if (cq->is_direct)
- pci_free_consistent(dev->pdev, size,
- cq->queue.direct.buf,
- pci_unmap_addr(&cq->queue.direct, mapping));
- else {
- for (i = 0; i < npages; ++i)
- if (cq->queue.page_list[i].buf)
- pci_free_consistent(dev->pdev, PAGE_SIZE,
- cq->queue.page_list[i].buf,
- pci_unmap_addr(&cq->queue.page_list[i],
- mapping));
+ mthca_free_db(dev, MTHCA_DB_TYPE_CQ_ARM, cq->arm_db_index);
- kfree(cq->queue.page_list);
- }
+err_out_ci:
+ mthca_free_db(dev, MTHCA_DB_TYPE_CQ_SET_CI, cq->set_ci_db_index);
- err_out:
- kfree(dma_list);
- kfree(mailbox);
+err_out_icm:
+ mthca_table_put(dev, dev->cq_table.table, cq->cqn);
+
+err_out:
+ mthca_free(&dev->cq_table.alloc, cq->cqn);
return err;
}
@@ -773,7 +859,7 @@ void mthca_free_cq(struct mthca_dev *dev,
int j;
printk(KERN_ERR "context for CQN %x (cons index %x, next sw %d)\n",
- cq->cqn, cq->cons_index, next_cqe_sw(cq));
+ cq->cqn, cq->cons_index, !!next_cqe_sw(cq));
for (j = 0; j < 16; ++j)
printk(KERN_ERR "[%2x] %08x\n", j * 4, be32_to_cpu(ctx[j]));
}
@@ -783,30 +869,21 @@ void mthca_free_cq(struct mthca_dev *dev,
cq->cqn & (dev->limits.num_cqs - 1));
spin_unlock_irq(&dev->cq_table.lock);
+ if (dev->mthca_flags & MTHCA_FLAG_MSI_X)
+ synchronize_irq(dev->eq_table.eq[MTHCA_EQ_COMP].msi_x_vector);
+ else
+ synchronize_irq(dev->pdev->irq);
+
atomic_dec(&cq->refcount);
wait_event(cq->wait, !atomic_read(&cq->refcount));
mthca_free_mr(dev, &cq->mr);
+ mthca_free_cq_buf(dev, cq);
- if (cq->is_direct)
- pci_free_consistent(dev->pdev,
- (cq->ibcq.cqe + 1) * MTHCA_CQ_ENTRY_SIZE,
- cq->queue.direct.buf,
- pci_unmap_addr(&cq->queue.direct,
- mapping));
- else {
- int i;
-
- for (i = 0;
- i < ((cq->ibcq.cqe + 1) * MTHCA_CQ_ENTRY_SIZE + PAGE_SIZE - 1) /
- PAGE_SIZE;
- ++i)
- pci_free_consistent(dev->pdev, PAGE_SIZE,
- cq->queue.page_list[i].buf,
- pci_unmap_addr(&cq->queue.page_list[i],
- mapping));
-
- kfree(cq->queue.page_list);
+ if (dev->hca_type == ARBEL_NATIVE) {
+ mthca_free_db(dev, MTHCA_DB_TYPE_CQ_ARM, cq->arm_db_index);
+ mthca_free_db(dev, MTHCA_DB_TYPE_CQ_SET_CI, cq->set_ci_db_index);
+ mthca_table_put(dev, dev->cq_table.table, cq->cqn);
}
mthca_free(&dev->cq_table.alloc, cq->cqn);
diff --git a/drivers/infiniband/hw/mthca/mthca_dev.h b/drivers/infiniband/hw/mthca/mthca_dev.h
index 87634ca9ff8c6..56b2bfb5adb13 100644
--- a/drivers/infiniband/hw/mthca/mthca_dev.h
+++ b/drivers/infiniband/hw/mthca/mthca_dev.h
@@ -65,7 +65,6 @@ enum {
};
enum {
- MTHCA_KAR_PAGE = 1,
MTHCA_MAX_PORTS = 2
};
@@ -108,6 +107,7 @@ struct mthca_limits {
int gid_table_len;
int pkey_table_len;
int local_ca_ack_delay;
+ int num_uars;
int max_sg;
int num_qps;
int reserved_qps;
@@ -148,6 +148,12 @@ struct mthca_array {
} *page_list;
};
+struct mthca_uar_table {
+ struct mthca_alloc alloc;
+ u64 uarc_base;
+ int uarc_size;
+};
+
struct mthca_pd_table {
struct mthca_alloc alloc;
};
@@ -165,6 +171,7 @@ struct mthca_eq_table {
struct mthca_alloc alloc;
void __iomem *clr_int;
u32 clr_mask;
+ u32 arm_mask;
struct mthca_eq eq[MTHCA_NUM_EQ];
u64 icm_virt;
struct page *icm_page;
@@ -200,8 +207,9 @@ struct mthca_av_table {
};
struct mthca_mcg_table {
- struct semaphore sem;
- struct mthca_alloc alloc;
+ struct semaphore sem;
+ struct mthca_alloc alloc;
+ struct mthca_icm_table *table;
};
struct mthca_dev {
@@ -210,6 +218,7 @@ struct mthca_dev {
int hca_type;
unsigned long mthca_flags;
+ unsigned long device_cap_flags;
u32 rev_id;
@@ -237,13 +246,22 @@ struct mthca_dev {
struct semaphore cap_mask_mutex;
void __iomem *hcr;
- void __iomem *ecr_base;
- void __iomem *clr_base;
void __iomem *kar;
+ void __iomem *clr_base;
+ union {
+ struct {
+ void __iomem *ecr_base;
+ } tavor;
+ struct {
+ void __iomem *eq_arm;
+ void __iomem *eq_set_ci_base;
+ } arbel;
+ } eq_regs;
struct mthca_cmd cmd;
struct mthca_limits limits;
+ struct mthca_uar_table uar_table;
struct mthca_pd_table pd_table;
struct mthca_mr_table mr_table;
struct mthca_eq_table eq_table;
@@ -252,8 +270,10 @@ struct mthca_dev {
struct mthca_av_table av_table;
struct mthca_mcg_table mcg_table;
- struct mthca_pd driver_pd;
- struct mthca_mr driver_mr;
+ struct mthca_uar driver_uar;
+ struct mthca_db_table *db_tab;
+ struct mthca_pd driver_pd;
+ struct mthca_mr driver_mr;
struct ib_mad_agent *send_agent[MTHCA_MAX_PORTS][2];
struct ib_ah *sm_ah[MTHCA_MAX_PORTS];
@@ -310,6 +330,7 @@ void mthca_array_clear(struct mthca_array *array, int index);
int mthca_array_init(struct mthca_array *array, int nent);
void mthca_array_cleanup(struct mthca_array *array, int nent);
+int mthca_init_uar_table(struct mthca_dev *dev);
int mthca_init_pd_table(struct mthca_dev *dev);
int mthca_init_mr_table(struct mthca_dev *dev);
int mthca_init_eq_table(struct mthca_dev *dev);
@@ -318,6 +339,7 @@ int mthca_init_qp_table(struct mthca_dev *dev);
int mthca_init_av_table(struct mthca_dev *dev);
int mthca_init_mcg_table(struct mthca_dev *dev);
+void mthca_cleanup_uar_table(struct mthca_dev *dev);
void mthca_cleanup_pd_table(struct mthca_dev *dev);
void mthca_cleanup_mr_table(struct mthca_dev *dev);
void mthca_cleanup_eq_table(struct mthca_dev *dev);
@@ -329,6 +351,9 @@ void mthca_cleanup_mcg_table(struct mthca_dev *dev);
int mthca_register_device(struct mthca_dev *dev);
void mthca_unregister_device(struct mthca_dev *dev);
+int mthca_uar_alloc(struct mthca_dev *dev, struct mthca_uar *uar);
+void mthca_uar_free(struct mthca_dev *dev, struct mthca_uar *uar);
+
int mthca_pd_alloc(struct mthca_dev *dev, struct mthca_pd *pd);
void mthca_pd_free(struct mthca_dev *dev, struct mthca_pd *pd);
@@ -345,8 +370,8 @@ void mthca_unmap_eq_icm(struct mthca_dev *dev);
int mthca_poll_cq(struct ib_cq *ibcq, int num_entries,
struct ib_wc *entry);
-void mthca_arm_cq(struct mthca_dev *dev, struct mthca_cq *cq,
- int solicited);
+int mthca_tavor_arm_cq(struct ib_cq *cq, enum ib_cq_notify notify);
+int mthca_arbel_arm_cq(struct ib_cq *cq, enum ib_cq_notify notify);
int mthca_init_cq(struct mthca_dev *dev, int nent,
struct mthca_cq *cq);
void mthca_free_cq(struct mthca_dev *dev,
@@ -357,11 +382,15 @@ void mthca_cq_clean(struct mthca_dev *dev, u32 cqn, u32 qpn);
void mthca_qp_event(struct mthca_dev *dev, u32 qpn,
enum ib_event_type event_type);
int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask);
-int mthca_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
- struct ib_send_wr **bad_wr);
-int mthca_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
- struct ib_recv_wr **bad_wr);
-int mthca_free_err_wqe(struct mthca_qp *qp, int is_send,
+int mthca_tavor_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
+ struct ib_send_wr **bad_wr);
+int mthca_tavor_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
+ struct ib_recv_wr **bad_wr);
+int mthca_arbel_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
+ struct ib_send_wr **bad_wr);
+int mthca_arbel_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
+ struct ib_recv_wr **bad_wr);
+int mthca_free_err_wqe(struct mthca_dev *dev, struct mthca_qp *qp, int is_send,
int index, int *dbd, u32 *new_wqe);
int mthca_alloc_qp(struct mthca_dev *dev,
struct mthca_pd *pd,
@@ -369,14 +398,12 @@ int mthca_alloc_qp(struct mthca_dev *dev,
struct mthca_cq *recv_cq,
enum ib_qp_type type,
enum ib_sig_type send_policy,
- enum ib_sig_type recv_policy,
struct mthca_qp *qp);
int mthca_alloc_sqp(struct mthca_dev *dev,
struct mthca_pd *pd,
struct mthca_cq *send_cq,
struct mthca_cq *recv_cq,
enum ib_sig_type send_policy,
- enum ib_sig_type recv_policy,
int qpn,
int port,
struct mthca_sqp *sqp);
diff --git a/drivers/infiniband/hw/mthca/mthca_doorbell.h b/drivers/infiniband/hw/mthca/mthca_doorbell.h
index cc8ad11d6f696..78b183cab54c6 100644
--- a/drivers/infiniband/hw/mthca/mthca_doorbell.h
+++ b/drivers/infiniband/hw/mthca/mthca_doorbell.h
@@ -57,6 +57,11 @@ static inline void mthca_write64(u32 val[2], void __iomem *dest,
__raw_writeq(*(u64 *) val, dest);
}
+static inline void mthca_write_db_rec(u32 val[2], u32 *db)
+{
+ *(u64 *) db = *(u64 *) val;
+}
+
#else
/*
@@ -80,4 +85,11 @@ static inline void mthca_write64(u32 val[2], void __iomem *dest,
spin_unlock_irqrestore(doorbell_lock, flags);
}
+static inline void mthca_write_db_rec(u32 val[2], u32 *db)
+{
+ db[0] = val[0];
+ wmb();
+ db[1] = val[1];
+}
+
#endif
diff --git a/drivers/infiniband/hw/mthca/mthca_eq.c b/drivers/infiniband/hw/mthca/mthca_eq.c
index 9b37f7030da6b..623daab5c92bd 100644
--- a/drivers/infiniband/hw/mthca/mthca_eq.c
+++ b/drivers/infiniband/hw/mthca/mthca_eq.c
@@ -54,10 +54,10 @@ struct mthca_eq_context {
u32 flags;
u64 start;
u32 logsize_usrpage;
- u32 pd;
+ u32 tavor_pd; /* reserved for Arbel */
u8 reserved1[3];
u8 intr;
- u32 lost_count;
+ u32 arbel_pd; /* lost_count for Tavor */
u32 lkey;
u32 reserved2[2];
u32 consumer_index;
@@ -75,6 +75,7 @@ struct mthca_eq_context {
#define MTHCA_EQ_STATE_ARMED ( 1 << 8)
#define MTHCA_EQ_STATE_FIRED ( 2 << 8)
#define MTHCA_EQ_STATE_ALWAYS_ARMED ( 3 << 8)
+#define MTHCA_EQ_STATE_ARBEL ( 8 << 8)
enum {
MTHCA_EVENT_TYPE_COMP = 0x00,
@@ -164,19 +165,46 @@ static inline u64 async_mask(struct mthca_dev *dev)
MTHCA_ASYNC_EVENT_MASK;
}
-static inline void set_eq_ci(struct mthca_dev *dev, struct mthca_eq *eq, u32 ci)
+static inline void tavor_set_eq_ci(struct mthca_dev *dev, struct mthca_eq *eq, u32 ci)
{
u32 doorbell[2];
doorbell[0] = cpu_to_be32(MTHCA_EQ_DB_SET_CI | eq->eqn);
doorbell[1] = cpu_to_be32(ci & (eq->nent - 1));
+ /*
+ * This barrier makes sure that all updates to ownership bits
+ * done by set_eqe_hw() hit memory before the consumer index
+ * is updated. set_eq_ci() allows the HCA to possibly write
+ * more EQ entries, and we want to avoid the exceedingly
+ * unlikely possibility of the HCA writing an entry and then
+ * having set_eqe_hw() overwrite the owner field.
+ */
+ wmb();
mthca_write64(doorbell,
dev->kar + MTHCA_EQ_DOORBELL,
MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock));
}
-static inline void eq_req_not(struct mthca_dev *dev, int eqn)
+static inline void arbel_set_eq_ci(struct mthca_dev *dev, struct mthca_eq *eq, u32 ci)
+{
+ /* See comment in tavor_set_eq_ci() above. */
+ wmb();
+ __raw_writel(cpu_to_be32(ci), dev->eq_regs.arbel.eq_set_ci_base +
+ eq->eqn * 8);
+ /* We still want ordering, just not swabbing, so add a barrier */
+ mb();
+}
+
+static inline void set_eq_ci(struct mthca_dev *dev, struct mthca_eq *eq, u32 ci)
+{
+ if (dev->hca_type == ARBEL_NATIVE)
+ arbel_set_eq_ci(dev, eq, ci);
+ else
+ tavor_set_eq_ci(dev, eq, ci);
+}
+
+static inline void tavor_eq_req_not(struct mthca_dev *dev, int eqn)
{
u32 doorbell[2];
@@ -188,16 +216,23 @@ static inline void eq_req_not(struct mthca_dev *dev, int eqn)
MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock));
}
+static inline void arbel_eq_req_not(struct mthca_dev *dev, u32 eqn_mask)
+{
+ writel(eqn_mask, dev->eq_regs.arbel.eq_arm);
+}
+
static inline void disarm_cq(struct mthca_dev *dev, int eqn, int cqn)
{
- u32 doorbell[2];
+ if (dev->hca_type != ARBEL_NATIVE) {
+ u32 doorbell[2];
- doorbell[0] = cpu_to_be32(MTHCA_EQ_DB_DISARM_CQ | eqn);
- doorbell[1] = cpu_to_be32(cqn);
+ doorbell[0] = cpu_to_be32(MTHCA_EQ_DB_DISARM_CQ | eqn);
+ doorbell[1] = cpu_to_be32(cqn);
- mthca_write64(doorbell,
- dev->kar + MTHCA_EQ_DOORBELL,
- MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock));
+ mthca_write64(doorbell,
+ dev->kar + MTHCA_EQ_DOORBELL,
+ MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock));
+ }
}
static inline struct mthca_eqe *get_eqe(struct mthca_eq *eq, u32 entry)
@@ -232,7 +267,7 @@ static void port_change(struct mthca_dev *dev, int port, int active)
ib_dispatch_event(&record);
}
-static void mthca_eq_int(struct mthca_dev *dev, struct mthca_eq *eq)
+static int mthca_eq_int(struct mthca_dev *dev, struct mthca_eq *eq)
{
struct mthca_eqe *eqe;
int disarm_cqn;
@@ -333,60 +368,93 @@ static void mthca_eq_int(struct mthca_dev *dev, struct mthca_eq *eq)
++eq->cons_index;
eqes_found = 1;
- if (set_ci) {
- wmb(); /* see comment below */
+ if (unlikely(set_ci)) {
+ /*
+ * Conditional on hca_type is OK here because
+ * this is a rare case, not the fast path.
+ */
set_eq_ci(dev, eq, eq->cons_index);
set_ci = 0;
}
}
/*
- * This barrier makes sure that all updates to
- * ownership bits done by set_eqe_hw() hit memory
- * before the consumer index is updated. set_eq_ci()
- * allows the HCA to possibly write more EQ entries,
- * and we want to avoid the exceedingly unlikely
- * possibility of the HCA writing an entry and then
- * having set_eqe_hw() overwrite the owner field.
+ * Rely on caller to set consumer index so that we don't have
+ * to test hca_type in our interrupt handling fast path.
*/
- if (likely(eqes_found)) {
- wmb();
- set_eq_ci(dev, eq, eq->cons_index);
- }
- eq_req_not(dev, eq->eqn);
+ return eqes_found;
}
-static irqreturn_t mthca_interrupt(int irq, void *dev_ptr, struct pt_regs *regs)
+static irqreturn_t mthca_tavor_interrupt(int irq, void *dev_ptr, struct pt_regs *regs)
{
struct mthca_dev *dev = dev_ptr;
u32 ecr;
- int work = 0;
int i;
if (dev->eq_table.clr_mask)
writel(dev->eq_table.clr_mask, dev->eq_table.clr_int);
- if ((ecr = readl(dev->ecr_base + 4)) != 0) {
- work = 1;
-
- writel(ecr, dev->ecr_base +
+ ecr = readl(dev->eq_regs.tavor.ecr_base + 4);
+ if (ecr) {
+ writel(ecr, dev->eq_regs.tavor.ecr_base +
MTHCA_ECR_CLR_BASE - MTHCA_ECR_BASE + 4);
for (i = 0; i < MTHCA_NUM_EQ; ++i)
- if (ecr & dev->eq_table.eq[i].ecr_mask)
- mthca_eq_int(dev, &dev->eq_table.eq[i]);
+ if (ecr & dev->eq_table.eq[i].eqn_mask &&
+ mthca_eq_int(dev, &dev->eq_table.eq[i])) {
+ tavor_set_eq_ci(dev, &dev->eq_table.eq[i],
+ dev->eq_table.eq[i].cons_index);
+ tavor_eq_req_not(dev, dev->eq_table.eq[i].eqn);
+ }
}
- return IRQ_RETVAL(work);
+ return IRQ_RETVAL(ecr);
}
-static irqreturn_t mthca_msi_x_interrupt(int irq, void *eq_ptr,
+static irqreturn_t mthca_tavor_msi_x_interrupt(int irq, void *eq_ptr,
struct pt_regs *regs)
{
struct mthca_eq *eq = eq_ptr;
struct mthca_dev *dev = eq->dev;
mthca_eq_int(dev, eq);
+ tavor_set_eq_ci(dev, eq, eq->cons_index);
+ tavor_eq_req_not(dev, eq->eqn);
+
+ /* MSI-X vectors always belong to us */
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t mthca_arbel_interrupt(int irq, void *dev_ptr, struct pt_regs *regs)
+{
+ struct mthca_dev *dev = dev_ptr;
+ int work = 0;
+ int i;
+
+ if (dev->eq_table.clr_mask)
+ writel(dev->eq_table.clr_mask, dev->eq_table.clr_int);
+
+ for (i = 0; i < MTHCA_NUM_EQ; ++i)
+ if (mthca_eq_int(dev, &dev->eq_table.eq[i])) {
+ work = 1;
+ arbel_set_eq_ci(dev, &dev->eq_table.eq[i],
+ dev->eq_table.eq[i].cons_index);
+ }
+
+ arbel_eq_req_not(dev, dev->eq_table.arm_mask);
+
+ return IRQ_RETVAL(work);
+}
+
+static irqreturn_t mthca_arbel_msi_x_interrupt(int irq, void *eq_ptr,
+ struct pt_regs *regs)
+{
+ struct mthca_eq *eq = eq_ptr;
+ struct mthca_dev *dev = eq->dev;
+
+ mthca_eq_int(dev, eq);
+ arbel_set_eq_ci(dev, eq, eq->cons_index);
+ arbel_eq_req_not(dev, eq->eqn_mask);
/* MSI-X vectors always belong to us */
return IRQ_HANDLED;
@@ -467,10 +535,16 @@ static int __devinit mthca_create_eq(struct mthca_dev *dev,
MTHCA_EQ_OWNER_HW |
MTHCA_EQ_STATE_ARMED |
MTHCA_EQ_FLAG_TR);
- eq_context->start = cpu_to_be64(0);
- eq_context->logsize_usrpage = cpu_to_be32((ffs(nent) - 1) << 24 |
- MTHCA_KAR_PAGE);
- eq_context->pd = cpu_to_be32(dev->driver_pd.pd_num);
+ if (dev->hca_type == ARBEL_NATIVE)
+ eq_context->flags |= cpu_to_be32(MTHCA_EQ_STATE_ARBEL);
+
+ eq_context->logsize_usrpage = cpu_to_be32((ffs(nent) - 1) << 24);
+ if (dev->hca_type == ARBEL_NATIVE) {
+ eq_context->arbel_pd = cpu_to_be32(dev->driver_pd.pd_num);
+ } else {
+ eq_context->logsize_usrpage |= cpu_to_be32(dev->driver_uar.index);
+ eq_context->tavor_pd = cpu_to_be32(dev->driver_pd.pd_num);
+ }
eq_context->intr = intr;
eq_context->lkey = cpu_to_be32(eq->mr.ibmr.lkey);
@@ -489,10 +563,10 @@ static int __devinit mthca_create_eq(struct mthca_dev *dev,
kfree(dma_list);
kfree(mailbox);
- eq->ecr_mask = swab32(1 << eq->eqn);
+ eq->eqn_mask = swab32(1 << eq->eqn);
eq->cons_index = 0;
- eq_req_not(dev, eq->eqn);
+ dev->eq_table.arm_mask |= eq->eqn_mask;
mthca_dbg(dev, "Allocated EQ %d with %d entries\n",
eq->eqn, nent);
@@ -544,6 +618,8 @@ static void mthca_free_eq(struct mthca_dev *dev,
mthca_warn(dev, "HW2SW_EQ returned status 0x%02x\n",
status);
+ dev->eq_table.arm_mask &= ~eq->eqn_mask;
+
if (0) {
mthca_dbg(dev, "Dumping EQ context %02x:\n", eq->eqn);
for (i = 0; i < sizeof (struct mthca_eq_context) / 4; ++i) {
@@ -555,7 +631,6 @@ static void mthca_free_eq(struct mthca_dev *dev,
}
}
-
mthca_free_mr(dev, &eq->mr);
for (i = 0; i < npages; ++i)
pci_free_consistent(dev->pdev, PAGE_SIZE,
@@ -578,6 +653,129 @@ static void mthca_free_irqs(struct mthca_dev *dev)
dev->eq_table.eq + i);
}
+static int __devinit mthca_map_reg(struct mthca_dev *dev,
+ unsigned long offset, unsigned long size,
+ void __iomem **map)
+{
+ unsigned long base = pci_resource_start(dev->pdev, 0);
+
+ if (!request_mem_region(base + offset, size, DRV_NAME))
+ return -EBUSY;
+
+ *map = ioremap(base + offset, size);
+ if (!*map) {
+ release_mem_region(base + offset, size);
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static void mthca_unmap_reg(struct mthca_dev *dev, unsigned long offset,
+ unsigned long size, void __iomem *map)
+{
+ unsigned long base = pci_resource_start(dev->pdev, 0);
+
+ release_mem_region(base + offset, size);
+ iounmap(map);
+}
+
+static int __devinit mthca_map_eq_regs(struct mthca_dev *dev)
+{
+ unsigned long mthca_base;
+
+ mthca_base = pci_resource_start(dev->pdev, 0);
+
+ if (dev->hca_type == ARBEL_NATIVE) {
+ /*
+ * We assume that the EQ arm and EQ set CI registers
+ * fall within the first BAR. We can't trust the
+ * values firmware gives us, since those addresses are
+ * valid on the HCA's side of the PCI bus but not
+ * necessarily the host side.
+ */
+ if (mthca_map_reg(dev, (pci_resource_len(dev->pdev, 0) - 1) &
+ dev->fw.arbel.clr_int_base, MTHCA_CLR_INT_SIZE,
+ &dev->clr_base)) {
+ mthca_err(dev, "Couldn't map interrupt clear register, "
+ "aborting.\n");
+ return -ENOMEM;
+ }
+
+ /*
+ * Add 4 because we limit ourselves to EQs 0 ... 31,
+ * so we only need the low word of the register.
+ */
+ if (mthca_map_reg(dev, ((pci_resource_len(dev->pdev, 0) - 1) &
+ dev->fw.arbel.eq_arm_base) + 4, 4,
+ &dev->eq_regs.arbel.eq_arm)) {
+ mthca_err(dev, "Couldn't map interrupt clear register, "
+ "aborting.\n");
+ mthca_unmap_reg(dev, (pci_resource_len(dev->pdev, 0) - 1) &
+ dev->fw.arbel.clr_int_base, MTHCA_CLR_INT_SIZE,
+ dev->clr_base);
+ return -ENOMEM;
+ }
+
+ if (mthca_map_reg(dev, (pci_resource_len(dev->pdev, 0) - 1) &
+ dev->fw.arbel.eq_set_ci_base,
+ MTHCA_EQ_SET_CI_SIZE,
+ &dev->eq_regs.arbel.eq_set_ci_base)) {
+ mthca_err(dev, "Couldn't map interrupt clear register, "
+ "aborting.\n");
+ mthca_unmap_reg(dev, ((pci_resource_len(dev->pdev, 0) - 1) &
+ dev->fw.arbel.eq_arm_base) + 4, 4,
+ dev->eq_regs.arbel.eq_arm);
+ mthca_unmap_reg(dev, (pci_resource_len(dev->pdev, 0) - 1) &
+ dev->fw.arbel.clr_int_base, MTHCA_CLR_INT_SIZE,
+ dev->clr_base);
+ return -ENOMEM;
+ }
+ } else {
+ if (mthca_map_reg(dev, MTHCA_CLR_INT_BASE, MTHCA_CLR_INT_SIZE,
+ &dev->clr_base)) {
+ mthca_err(dev, "Couldn't map interrupt clear register, "
+ "aborting.\n");
+ return -ENOMEM;
+ }
+
+ if (mthca_map_reg(dev, MTHCA_ECR_BASE,
+ MTHCA_ECR_SIZE + MTHCA_ECR_CLR_SIZE,
+ &dev->eq_regs.tavor.ecr_base)) {
+ mthca_err(dev, "Couldn't map ecr register, "
+ "aborting.\n");
+ mthca_unmap_reg(dev, MTHCA_CLR_INT_BASE, MTHCA_CLR_INT_SIZE,
+ dev->clr_base);
+ return -ENOMEM;
+ }
+ }
+
+ return 0;
+
+}
+
+static void __devexit mthca_unmap_eq_regs(struct mthca_dev *dev)
+{
+ if (dev->hca_type == ARBEL_NATIVE) {
+ mthca_unmap_reg(dev, (pci_resource_len(dev->pdev, 0) - 1) &
+ dev->fw.arbel.eq_set_ci_base,
+ MTHCA_EQ_SET_CI_SIZE,
+ dev->eq_regs.arbel.eq_set_ci_base);
+ mthca_unmap_reg(dev, ((pci_resource_len(dev->pdev, 0) - 1) &
+ dev->fw.arbel.eq_arm_base) + 4, 4,
+ dev->eq_regs.arbel.eq_arm);
+ mthca_unmap_reg(dev, (pci_resource_len(dev->pdev, 0) - 1) &
+ dev->fw.arbel.clr_int_base, MTHCA_CLR_INT_SIZE,
+ dev->clr_base);
+ } else {
+ mthca_unmap_reg(dev, MTHCA_ECR_BASE,
+ MTHCA_ECR_SIZE + MTHCA_ECR_CLR_SIZE,
+ dev->eq_regs.tavor.ecr_base);
+ mthca_unmap_reg(dev, MTHCA_CLR_INT_BASE, MTHCA_CLR_INT_SIZE,
+ dev->clr_base);
+ }
+}
+
int __devinit mthca_map_eq_icm(struct mthca_dev *dev, u64 icm_virt)
{
int ret;
@@ -636,6 +834,10 @@ int __devinit mthca_init_eq_table(struct mthca_dev *dev)
if (err)
return err;
+ err = mthca_map_eq_regs(dev);
+ if (err)
+ goto err_out_free;
+
if (dev->mthca_flags & MTHCA_FLAG_MSI ||
dev->mthca_flags & MTHCA_FLAG_MSI_X) {
dev->eq_table.clr_mask = 0;
@@ -646,6 +848,8 @@ int __devinit mthca_init_eq_table(struct mthca_dev *dev)
(dev->eq_table.inta_pin < 31 ? 4 : 0);
}
+ dev->eq_table.arm_mask = 0;
+
intr = (dev->mthca_flags & MTHCA_FLAG_MSI) ?
128 : dev->eq_table.inta_pin;
@@ -653,7 +857,7 @@ int __devinit mthca_init_eq_table(struct mthca_dev *dev)
(dev->mthca_flags & MTHCA_FLAG_MSI_X) ? 128 : intr,
&dev->eq_table.eq[MTHCA_EQ_COMP]);
if (err)
- goto err_out_free;
+ goto err_out_unmap;
err = mthca_create_eq(dev, MTHCA_NUM_ASYNC_EQE,
(dev->mthca_flags & MTHCA_FLAG_MSI_X) ? 129 : intr,
@@ -676,15 +880,20 @@ int __devinit mthca_init_eq_table(struct mthca_dev *dev)
for (i = 0; i < MTHCA_NUM_EQ; ++i) {
err = request_irq(dev->eq_table.eq[i].msi_x_vector,
- mthca_msi_x_interrupt, 0,
- eq_name[i], dev->eq_table.eq + i);
+ dev->hca_type == ARBEL_NATIVE ?
+ mthca_arbel_msi_x_interrupt :
+ mthca_tavor_msi_x_interrupt,
+ 0, eq_name[i], dev->eq_table.eq + i);
if (err)
goto err_out_cmd;
dev->eq_table.eq[i].have_irq = 1;
}
} else {
- err = request_irq(dev->pdev->irq, mthca_interrupt, SA_SHIRQ,
- DRV_NAME, dev);
+ err = request_irq(dev->pdev->irq,
+ dev->hca_type == ARBEL_NATIVE ?
+ mthca_arbel_interrupt :
+ mthca_tavor_interrupt,
+ SA_SHIRQ, DRV_NAME, dev);
if (err)
goto err_out_cmd;
dev->eq_table.have_irq = 1;
@@ -708,6 +917,12 @@ int __devinit mthca_init_eq_table(struct mthca_dev *dev)
mthca_warn(dev, "MAP_EQ for cmd EQ %d returned status 0x%02x\n",
dev->eq_table.eq[MTHCA_EQ_CMD].eqn, status);
+ for (i = 0; i < MTHCA_EQ_CMD; ++i)
+ if (dev->hca_type == ARBEL_NATIVE)
+ arbel_eq_req_not(dev, dev->eq_table.eq[i].eqn_mask);
+ else
+ tavor_eq_req_not(dev, dev->eq_table.eq[i].eqn);
+
return 0;
err_out_cmd:
@@ -720,6 +935,9 @@ err_out_async:
err_out_comp:
mthca_free_eq(dev, &dev->eq_table.eq[MTHCA_EQ_COMP]);
+err_out_unmap:
+ mthca_unmap_eq_regs(dev);
+
err_out_free:
mthca_alloc_cleanup(&dev->eq_table.alloc);
return err;
@@ -740,5 +958,7 @@ void __devexit mthca_cleanup_eq_table(struct mthca_dev *dev)
for (i = 0; i < MTHCA_NUM_EQ; ++i)
mthca_free_eq(dev, &dev->eq_table.eq[i]);
+ mthca_unmap_eq_regs(dev);
+
mthca_alloc_cleanup(&dev->eq_table.alloc);
}
diff --git a/drivers/infiniband/hw/mthca/mthca_main.c b/drivers/infiniband/hw/mthca/mthca_main.c
index 4d71ae8999e1f..9e782bc1c38de 100644
--- a/drivers/infiniband/hw/mthca/mthca_main.c
+++ b/drivers/infiniband/hw/mthca/mthca_main.c
@@ -171,6 +171,33 @@ static int __devinit mthca_dev_lim(struct mthca_dev *mdev, struct mthca_dev_lim
mdev->limits.reserved_uars = dev_lim->reserved_uars;
mdev->limits.reserved_pds = dev_lim->reserved_pds;
+ /* IB_DEVICE_RESIZE_MAX_WR not supported by driver.
+ May be doable since hardware supports it for SRQ.
+
+ IB_DEVICE_N_NOTIFY_CQ is supported by hardware but not by driver.
+
+ IB_DEVICE_SRQ_RESIZE is supported by hardware but SRQ is not
+ supported by driver. */
+ mdev->device_cap_flags = IB_DEVICE_CHANGE_PHY_PORT |
+ IB_DEVICE_PORT_ACTIVE_EVENT |
+ IB_DEVICE_SYS_IMAGE_GUID |
+ IB_DEVICE_RC_RNR_NAK_GEN;
+
+ if (dev_lim->flags & DEV_LIM_FLAG_BAD_PKEY_CNTR)
+ mdev->device_cap_flags |= IB_DEVICE_BAD_PKEY_CNTR;
+
+ if (dev_lim->flags & DEV_LIM_FLAG_BAD_QKEY_CNTR)
+ mdev->device_cap_flags |= IB_DEVICE_BAD_QKEY_CNTR;
+
+ if (dev_lim->flags & DEV_LIM_FLAG_RAW_MULTI)
+ mdev->device_cap_flags |= IB_DEVICE_RAW_MULTI;
+
+ if (dev_lim->flags & DEV_LIM_FLAG_AUTO_PATH_MIG)
+ mdev->device_cap_flags |= IB_DEVICE_AUTO_PATH_MIG;
+
+ if (dev_lim->flags & DEV_LIM_FLAG_UD_AV_PORT_ENFORCE)
+ mdev->device_cap_flags |= IB_DEVICE_UD_AV_PORT_ENFORCE;
+
if (dev_lim->flags & DEV_LIM_FLAG_SRQ)
mdev->mthca_flags |= MTHCA_FLAG_SRQ;
@@ -363,10 +390,9 @@ static int __devinit mthca_init_icm(struct mthca_dev *mdev,
}
mdev->mr_table.mtt_table = mthca_alloc_icm_table(mdev, init_hca->mtt_base,
- mdev->limits.num_mtt_segs *
init_hca->mtt_seg_sz,
- mdev->limits.reserved_mtts *
- init_hca->mtt_seg_sz, 1);
+ mdev->limits.num_mtt_segs,
+ mdev->limits.reserved_mtts, 1);
if (!mdev->mr_table.mtt_table) {
mthca_err(mdev, "Failed to map MTT context memory, aborting.\n");
err = -ENOMEM;
@@ -374,10 +400,9 @@ static int __devinit mthca_init_icm(struct mthca_dev *mdev,
}
mdev->mr_table.mpt_table = mthca_alloc_icm_table(mdev, init_hca->mpt_base,
- mdev->limits.num_mpts *
dev_lim->mpt_entry_sz,
- mdev->limits.reserved_mrws *
- dev_lim->mpt_entry_sz, 1);
+ mdev->limits.num_mpts,
+ mdev->limits.reserved_mrws, 1);
if (!mdev->mr_table.mpt_table) {
mthca_err(mdev, "Failed to map MPT context memory, aborting.\n");
err = -ENOMEM;
@@ -385,10 +410,9 @@ static int __devinit mthca_init_icm(struct mthca_dev *mdev,
}
mdev->qp_table.qp_table = mthca_alloc_icm_table(mdev, init_hca->qpc_base,
- mdev->limits.num_qps *
dev_lim->qpc_entry_sz,
- mdev->limits.reserved_qps *
- dev_lim->qpc_entry_sz, 1);
+ mdev->limits.num_qps,
+ mdev->limits.reserved_qps, 0);
if (!mdev->qp_table.qp_table) {
mthca_err(mdev, "Failed to map QP context memory, aborting.\n");
err = -ENOMEM;
@@ -396,10 +420,9 @@ static int __devinit mthca_init_icm(struct mthca_dev *mdev,
}
mdev->qp_table.eqp_table = mthca_alloc_icm_table(mdev, init_hca->eqpc_base,
- mdev->limits.num_qps *
dev_lim->eqpc_entry_sz,
- mdev->limits.reserved_qps *
- dev_lim->eqpc_entry_sz, 1);
+ mdev->limits.num_qps,
+ mdev->limits.reserved_qps, 0);
if (!mdev->qp_table.eqp_table) {
mthca_err(mdev, "Failed to map EQP context memory, aborting.\n");
err = -ENOMEM;
@@ -407,18 +430,38 @@ static int __devinit mthca_init_icm(struct mthca_dev *mdev,
}
mdev->cq_table.table = mthca_alloc_icm_table(mdev, init_hca->cqc_base,
- mdev->limits.num_cqs *
dev_lim->cqc_entry_sz,
- mdev->limits.reserved_cqs *
- dev_lim->cqc_entry_sz, 1);
+ mdev->limits.num_cqs,
+ mdev->limits.reserved_cqs, 0);
if (!mdev->cq_table.table) {
mthca_err(mdev, "Failed to map CQ context memory, aborting.\n");
err = -ENOMEM;
goto err_unmap_eqp;
}
+ /*
+ * It's not strictly required, but for simplicity just map the
+ * whole multicast group table now. The table isn't very big
+ * and it's a lot easier than trying to track ref counts.
+ */
+ mdev->mcg_table.table = mthca_alloc_icm_table(mdev, init_hca->mc_base,
+ MTHCA_MGM_ENTRY_SIZE,
+ mdev->limits.num_mgms +
+ mdev->limits.num_amgms,
+ mdev->limits.num_mgms +
+ mdev->limits.num_amgms,
+ 0);
+ if (!mdev->mcg_table.table) {
+ mthca_err(mdev, "Failed to map MCG context memory, aborting.\n");
+ err = -ENOMEM;
+ goto err_unmap_cq;
+ }
+
return 0;
+err_unmap_cq:
+ mthca_free_icm_table(mdev, mdev->cq_table.table);
+
err_unmap_eqp:
mthca_free_icm_table(mdev, mdev->qp_table.eqp_table);
@@ -570,11 +613,33 @@ static int __devinit mthca_setup_hca(struct mthca_dev *dev)
MTHCA_INIT_DOORBELL_LOCK(&dev->doorbell_lock);
+ err = mthca_init_uar_table(dev);
+ if (err) {
+ mthca_err(dev, "Failed to initialize "
+ "user access region table, aborting.\n");
+ return err;
+ }
+
+ err = mthca_uar_alloc(dev, &dev->driver_uar);
+ if (err) {
+ mthca_err(dev, "Failed to allocate driver access region, "
+ "aborting.\n");
+ goto err_uar_table_free;
+ }
+
+ dev->kar = ioremap(dev->driver_uar.pfn << PAGE_SHIFT, PAGE_SIZE);
+ if (!dev->kar) {
+ mthca_err(dev, "Couldn't map kernel access region, "
+ "aborting.\n");
+ err = -ENOMEM;
+ goto err_uar_free;
+ }
+
err = mthca_init_pd_table(dev);
if (err) {
mthca_err(dev, "Failed to initialize "
"protection domain table, aborting.\n");
- return err;
+ goto err_kar_unmap;
}
err = mthca_init_mr_table(dev);
@@ -591,13 +656,6 @@ static int __devinit mthca_setup_hca(struct mthca_dev *dev)
goto err_mr_table_free;
}
- if (dev->hca_type == ARBEL_NATIVE) {
- mthca_warn(dev, "Sorry, native MT25208 mode support is not done, "
- "aborting.\n");
- err = -ENODEV;
- goto err_pd_free;
- }
-
err = mthca_init_eq_table(dev);
if (err) {
mthca_err(dev, "Failed to initialize "
@@ -621,8 +679,9 @@ static int __devinit mthca_setup_hca(struct mthca_dev *dev)
mthca_err(dev, "BIOS or ACPI interrupt routing problem?\n");
goto err_cmd_poll;
- } else
- mthca_dbg(dev, "NOP command IRQ test passed\n");
+ }
+
+ mthca_dbg(dev, "NOP command IRQ test passed\n");
err = mthca_init_cq_table(dev);
if (err) {
@@ -677,6 +736,15 @@ err_mr_table_free:
err_pd_table_free:
mthca_cleanup_pd_table(dev);
+
+err_kar_unmap:
+ iounmap(dev->kar);
+
+err_uar_free:
+ mthca_uar_free(dev, &dev->driver_uar);
+
+err_uar_table_free:
+ mthca_cleanup_uar_table(dev);
return err;
}
@@ -686,37 +754,18 @@ static int __devinit mthca_request_regions(struct pci_dev *pdev,
int err;
/*
- * We request our first BAR in two chunks, since the MSI-X
- * vector table is right in the middle.
+ * We can't just use pci_request_regions() because the MSI-X
+ * table is right in the middle of the first BAR. If we did
+ * pci_request_region and grab all of the first BAR, then
+ * setting up MSI-X would fail, since the PCI core wants to do
+ * request_mem_region on the MSI-X vector table.
*
- * This is why we can't just use pci_request_regions() -- if
- * we did then setting up MSI-X would fail, since the PCI core
- * wants to do request_mem_region on the MSI-X vector table.
+ * So just request what we need right now, and request any
+ * other regions we need when setting up EQs.
*/
- if (!request_mem_region(pci_resource_start(pdev, 0) +
- MTHCA_HCR_BASE,
- MTHCA_HCR_SIZE,
- DRV_NAME)) {
- err = -EBUSY;
- goto err_hcr_failed;
- }
-
- if (!request_mem_region(pci_resource_start(pdev, 0) +
- MTHCA_ECR_BASE,
- MTHCA_MAP_ECR_SIZE,
- DRV_NAME)) {
- err = -EBUSY;
- goto err_ecr_failed;
- }
-
- if (!request_mem_region(pci_resource_start(pdev, 0) +
- MTHCA_CLR_INT_BASE,
- MTHCA_CLR_INT_SIZE,
- DRV_NAME)) {
- err = -EBUSY;
- goto err_int_failed;
- }
-
+ if (!request_mem_region(pci_resource_start(pdev, 0) + MTHCA_HCR_BASE,
+ MTHCA_HCR_SIZE, DRV_NAME))
+ return -EBUSY;
err = pci_request_region(pdev, 2, DRV_NAME);
if (err)
@@ -731,24 +780,11 @@ static int __devinit mthca_request_regions(struct pci_dev *pdev,
return 0;
err_bar4_failed:
-
pci_release_region(pdev, 2);
-err_bar2_failed:
-
- release_mem_region(pci_resource_start(pdev, 0) +
- MTHCA_CLR_INT_BASE,
- MTHCA_CLR_INT_SIZE);
-err_int_failed:
- release_mem_region(pci_resource_start(pdev, 0) +
- MTHCA_ECR_BASE,
- MTHCA_MAP_ECR_SIZE);
-err_ecr_failed:
-
- release_mem_region(pci_resource_start(pdev, 0) +
- MTHCA_HCR_BASE,
+err_bar2_failed:
+ release_mem_region(pci_resource_start(pdev, 0) + MTHCA_HCR_BASE,
MTHCA_HCR_SIZE);
-err_hcr_failed:
return err;
}
@@ -761,16 +797,7 @@ static void mthca_release_regions(struct pci_dev *pdev,
pci_release_region(pdev, 2);
- release_mem_region(pci_resource_start(pdev, 0) +
- MTHCA_CLR_INT_BASE,
- MTHCA_CLR_INT_SIZE);
-
- release_mem_region(pci_resource_start(pdev, 0) +
- MTHCA_ECR_BASE,
- MTHCA_MAP_ECR_SIZE);
-
- release_mem_region(pci_resource_start(pdev, 0) +
- MTHCA_HCR_BASE,
+ release_mem_region(pci_resource_start(pdev, 0) + MTHCA_HCR_BASE,
MTHCA_HCR_SIZE);
}
@@ -828,9 +855,9 @@ static int __devinit mthca_init_one(struct pci_dev *pdev,
const struct pci_device_id *id)
{
static int mthca_version_printed = 0;
+ static int mthca_memfree_warned = 0;
int ddr_hidden = 0;
int err;
- unsigned long mthca_base;
struct mthca_dev *mdev;
if (!mthca_version_printed) {
@@ -908,6 +935,10 @@ static int __devinit mthca_init_one(struct pci_dev *pdev,
mdev->pdev = pdev;
mdev->hca_type = id->driver_data;
+ if (mdev->hca_type == ARBEL_NATIVE && !mthca_memfree_warned++)
+ mthca_warn(mdev, "Warning: native MT25208 mode support is incomplete. "
+ "Your HCA may not work properly.\n");
+
if (ddr_hidden)
mdev->mthca_flags |= MTHCA_FLAG_DDR_HIDDEN;
@@ -932,8 +963,7 @@ static int __devinit mthca_init_one(struct pci_dev *pdev,
sema_init(&mdev->cmd.poll_sem, 1);
mdev->cmd.use_events = 0;
- mthca_base = pci_resource_start(pdev, 0);
- mdev->hcr = ioremap(mthca_base + MTHCA_HCR_BASE, MTHCA_HCR_SIZE);
+ mdev->hcr = ioremap(pci_resource_start(pdev, 0) + MTHCA_HCR_BASE, MTHCA_HCR_SIZE);
if (!mdev->hcr) {
mthca_err(mdev, "Couldn't map command register, "
"aborting.\n");
@@ -941,40 +971,13 @@ static int __devinit mthca_init_one(struct pci_dev *pdev,
goto err_free_dev;
}
- mdev->clr_base = ioremap(mthca_base + MTHCA_CLR_INT_BASE,
- MTHCA_CLR_INT_SIZE);
- if (!mdev->clr_base) {
- mthca_err(mdev, "Couldn't map interrupt clear register, "
- "aborting.\n");
- err = -ENOMEM;
- goto err_iounmap;
- }
-
- mdev->ecr_base = ioremap(mthca_base + MTHCA_ECR_BASE,
- MTHCA_ECR_SIZE + MTHCA_ECR_CLR_SIZE);
- if (!mdev->ecr_base) {
- mthca_err(mdev, "Couldn't map ecr register, "
- "aborting.\n");
- err = -ENOMEM;
- goto err_iounmap_clr;
- }
-
- mthca_base = pci_resource_start(pdev, 2);
- mdev->kar = ioremap(mthca_base + PAGE_SIZE * MTHCA_KAR_PAGE, PAGE_SIZE);
- if (!mdev->kar) {
- mthca_err(mdev, "Couldn't map kernel access region, "
- "aborting.\n");
- err = -ENOMEM;
- goto err_iounmap_ecr;
- }
-
err = mthca_tune_pci(mdev);
if (err)
- goto err_iounmap_kar;
+ goto err_iounmap;
err = mthca_init_hca(mdev);
if (err)
- goto err_iounmap_kar;
+ goto err_iounmap;
err = mthca_setup_hca(mdev);
if (err)
@@ -1007,19 +1010,11 @@ err_cleanup:
mthca_cleanup_mr_table(mdev);
mthca_cleanup_pd_table(mdev);
+ mthca_cleanup_uar_table(mdev);
err_close:
mthca_close_hca(mdev);
-err_iounmap_kar:
- iounmap(mdev->kar);
-
-err_iounmap_ecr:
- iounmap(mdev->ecr_base);
-
-err_iounmap_clr:
- iounmap(mdev->clr_base);
-
err_iounmap:
iounmap(mdev->hcr);
@@ -1065,11 +1060,13 @@ static void __devexit mthca_remove_one(struct pci_dev *pdev)
mthca_cleanup_mr_table(mdev);
mthca_cleanup_pd_table(mdev);
+ iounmap(mdev->kar);
+ mthca_uar_free(mdev, &mdev->driver_uar);
+ mthca_cleanup_uar_table(mdev);
+
mthca_close_hca(mdev);
iounmap(mdev->hcr);
- iounmap(mdev->ecr_base);
- iounmap(mdev->clr_base);
if (mdev->mthca_flags & MTHCA_FLAG_MSI_X)
pci_disable_msix(pdev);
diff --git a/drivers/infiniband/hw/mthca/mthca_memfree.c b/drivers/infiniband/hw/mthca/mthca_memfree.c
index 7071361c50f10..7730b59606160 100644
--- a/drivers/infiniband/hw/mthca/mthca_memfree.c
+++ b/drivers/infiniband/hw/mthca/mthca_memfree.c
@@ -79,6 +79,7 @@ struct mthca_icm *mthca_alloc_icm(struct mthca_dev *dev, int npages,
if (!icm)
return icm;
+ icm->refcount = 0;
INIT_LIST_HEAD(&icm->chunk_list);
cur_order = get_order(MTHCA_ICM_ALLOC_SIZE);
@@ -138,9 +139,62 @@ fail:
return NULL;
}
+int mthca_table_get(struct mthca_dev *dev, struct mthca_icm_table *table, int obj)
+{
+ int i = (obj & (table->num_obj - 1)) * table->obj_size / MTHCA_TABLE_CHUNK_SIZE;
+ int ret = 0;
+ u8 status;
+
+ down(&table->mutex);
+
+ if (table->icm[i]) {
+ ++table->icm[i]->refcount;
+ goto out;
+ }
+
+ table->icm[i] = mthca_alloc_icm(dev, MTHCA_TABLE_CHUNK_SIZE >> PAGE_SHIFT,
+ (table->lowmem ? GFP_KERNEL : GFP_HIGHUSER) |
+ __GFP_NOWARN);
+ if (!table->icm[i]) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ if (mthca_MAP_ICM(dev, table->icm[i], table->virt + i * MTHCA_TABLE_CHUNK_SIZE,
+ &status) || status) {
+ mthca_free_icm(dev, table->icm[i]);
+ table->icm[i] = NULL;
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ ++table->icm[i]->refcount;
+
+out:
+ up(&table->mutex);
+ return ret;
+}
+
+void mthca_table_put(struct mthca_dev *dev, struct mthca_icm_table *table, int obj)
+{
+ int i = (obj & (table->num_obj - 1)) * table->obj_size / MTHCA_TABLE_CHUNK_SIZE;
+ u8 status;
+
+ down(&table->mutex);
+
+ if (--table->icm[i]->refcount == 0) {
+ mthca_UNMAP_ICM(dev, table->virt + i * MTHCA_TABLE_CHUNK_SIZE,
+ MTHCA_TABLE_CHUNK_SIZE >> 12, &status);
+ mthca_free_icm(dev, table->icm[i]);
+ table->icm[i] = NULL;
+ }
+
+ up(&table->mutex);
+}
+
struct mthca_icm_table *mthca_alloc_icm_table(struct mthca_dev *dev,
- u64 virt, unsigned size,
- unsigned reserved,
+ u64 virt, int obj_size,
+ int nobj, int reserved,
int use_lowmem)
{
struct mthca_icm_table *table;
@@ -148,20 +202,23 @@ struct mthca_icm_table *mthca_alloc_icm_table(struct mthca_dev *dev,
int i;
u8 status;
- num_icm = size / MTHCA_TABLE_CHUNK_SIZE;
+ num_icm = obj_size * nobj / MTHCA_TABLE_CHUNK_SIZE;
table = kmalloc(sizeof *table + num_icm * sizeof *table->icm, GFP_KERNEL);
if (!table)
return NULL;
- table->virt = virt;
- table->num_icm = num_icm;
- init_MUTEX(&table->sem);
+ table->virt = virt;
+ table->num_icm = num_icm;
+ table->num_obj = nobj;
+ table->obj_size = obj_size;
+ table->lowmem = use_lowmem;
+ init_MUTEX(&table->mutex);
for (i = 0; i < num_icm; ++i)
table->icm[i] = NULL;
- for (i = 0; i < (reserved + MTHCA_TABLE_CHUNK_SIZE - 1) / MTHCA_TABLE_CHUNK_SIZE; ++i) {
+ for (i = 0; i * MTHCA_TABLE_CHUNK_SIZE < reserved * obj_size; ++i) {
table->icm[i] = mthca_alloc_icm(dev, MTHCA_TABLE_CHUNK_SIZE >> PAGE_SHIFT,
(use_lowmem ? GFP_KERNEL : GFP_HIGHUSER) |
__GFP_NOWARN);
@@ -173,6 +230,12 @@ struct mthca_icm_table *mthca_alloc_icm_table(struct mthca_dev *dev,
table->icm[i] = NULL;
goto err;
}
+
+ /*
+ * Add a reference to this ICM chunk so that it never
+ * gets freed (since it contains reserved firmware objects).
+ */
+ ++table->icm[i]->refcount;
}
return table;
@@ -204,3 +267,199 @@ void mthca_free_icm_table(struct mthca_dev *dev, struct mthca_icm_table *table)
kfree(table);
}
+
+static u64 mthca_uarc_virt(struct mthca_dev *dev, int page)
+{
+ return dev->uar_table.uarc_base +
+ dev->driver_uar.index * dev->uar_table.uarc_size +
+ page * 4096;
+}
+
+int mthca_alloc_db(struct mthca_dev *dev, int type, u32 qn, u32 **db)
+{
+ int group;
+ int start, end, dir;
+ int i, j;
+ struct mthca_db_page *page;
+ int ret = 0;
+ u8 status;
+
+ down(&dev->db_tab->mutex);
+
+ switch (type) {
+ case MTHCA_DB_TYPE_CQ_ARM:
+ case MTHCA_DB_TYPE_SQ:
+ group = 0;
+ start = 0;
+ end = dev->db_tab->max_group1;
+ dir = 1;
+ break;
+
+ case MTHCA_DB_TYPE_CQ_SET_CI:
+ case MTHCA_DB_TYPE_RQ:
+ case MTHCA_DB_TYPE_SRQ:
+ group = 1;
+ start = dev->db_tab->npages - 1;
+ end = dev->db_tab->min_group2;
+ dir = -1;
+ break;
+
+ default:
+ return -1;
+ }
+
+ for (i = start; i != end; i += dir)
+ if (dev->db_tab->page[i].db_rec &&
+ !bitmap_full(dev->db_tab->page[i].used,
+ MTHCA_DB_REC_PER_PAGE)) {
+ page = dev->db_tab->page + i;
+ goto found;
+ }
+
+ if (dev->db_tab->max_group1 >= dev->db_tab->min_group2 - 1) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ page = dev->db_tab->page + end;
+ page->db_rec = dma_alloc_coherent(&dev->pdev->dev, 4096,
+ &page->mapping, GFP_KERNEL);
+ if (!page->db_rec) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ memset(page->db_rec, 0, 4096);
+
+ ret = mthca_MAP_ICM_page(dev, page->mapping, mthca_uarc_virt(dev, i), &status);
+ if (!ret && status)
+ ret = -EINVAL;
+ if (ret) {
+ dma_free_coherent(&dev->pdev->dev, 4096,
+ page->db_rec, page->mapping);
+ goto out;
+ }
+
+ bitmap_zero(page->used, MTHCA_DB_REC_PER_PAGE);
+ if (group == 0)
+ ++dev->db_tab->max_group1;
+ else
+ --dev->db_tab->min_group2;
+
+found:
+ j = find_first_zero_bit(page->used, MTHCA_DB_REC_PER_PAGE);
+ set_bit(j, page->used);
+
+ if (group == 1)
+ j = MTHCA_DB_REC_PER_PAGE - 1 - j;
+
+ ret = i * MTHCA_DB_REC_PER_PAGE + j;
+
+ page->db_rec[j] = cpu_to_be64((qn << 8) | (type << 5));
+
+ *db = (u32 *) &page->db_rec[j];
+
+out:
+ up(&dev->db_tab->mutex);
+
+ return ret;
+}
+
+void mthca_free_db(struct mthca_dev *dev, int type, int db_index)
+{
+ int i, j;
+ struct mthca_db_page *page;
+ u8 status;
+
+ i = db_index / MTHCA_DB_REC_PER_PAGE;
+ j = db_index % MTHCA_DB_REC_PER_PAGE;
+
+ page = dev->db_tab->page + i;
+
+ down(&dev->db_tab->mutex);
+
+ page->db_rec[j] = 0;
+ if (i >= dev->db_tab->min_group2)
+ j = MTHCA_DB_REC_PER_PAGE - 1 - j;
+ clear_bit(j, page->used);
+
+ if (bitmap_empty(page->used, MTHCA_DB_REC_PER_PAGE) &&
+ i >= dev->db_tab->max_group1 - 1) {
+ mthca_UNMAP_ICM(dev, mthca_uarc_virt(dev, i), 1, &status);
+
+ dma_free_coherent(&dev->pdev->dev, 4096,
+ page->db_rec, page->mapping);
+ page->db_rec = NULL;
+
+ if (i == dev->db_tab->max_group1) {
+ --dev->db_tab->max_group1;
+ /* XXX may be able to unmap more pages now */
+ }
+ if (i == dev->db_tab->min_group2)
+ ++dev->db_tab->min_group2;
+ }
+
+ up(&dev->db_tab->mutex);
+}
+
+int mthca_init_db_tab(struct mthca_dev *dev)
+{
+ int i;
+
+ if (dev->hca_type != ARBEL_NATIVE)
+ return 0;
+
+ dev->db_tab = kmalloc(sizeof *dev->db_tab, GFP_KERNEL);
+ if (!dev->db_tab)
+ return -ENOMEM;
+
+ init_MUTEX(&dev->db_tab->mutex);
+
+ dev->db_tab->npages = dev->uar_table.uarc_size / PAGE_SIZE;
+ dev->db_tab->max_group1 = 0;
+ dev->db_tab->min_group2 = dev->db_tab->npages - 1;
+
+ dev->db_tab->page = kmalloc(dev->db_tab->npages *
+ sizeof *dev->db_tab->page,
+ GFP_KERNEL);
+ if (!dev->db_tab->page) {
+ kfree(dev->db_tab);
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < dev->db_tab->npages; ++i)
+ dev->db_tab->page[i].db_rec = NULL;
+
+ return 0;
+}
+
+void mthca_cleanup_db_tab(struct mthca_dev *dev)
+{
+ int i;
+ u8 status;
+
+ if (dev->hca_type != ARBEL_NATIVE)
+ return;
+
+ /*
+ * Because we don't always free our UARC pages when they
+ * become empty to make mthca_free_db() simpler we need to
+ * make a sweep through the doorbell pages and free any
+ * leftover pages now.
+ */
+ for (i = 0; i < dev->db_tab->npages; ++i) {
+ if (!dev->db_tab->page[i].db_rec)
+ continue;
+
+ if (!bitmap_empty(dev->db_tab->page[i].used, MTHCA_DB_REC_PER_PAGE))
+ mthca_warn(dev, "Kernel UARC page %d not empty\n", i);
+
+ mthca_UNMAP_ICM(dev, mthca_uarc_virt(dev, i), 1, &status);
+
+ dma_free_coherent(&dev->pdev->dev, 4096,
+ dev->db_tab->page[i].db_rec,
+ dev->db_tab->page[i].mapping);
+ }
+
+ kfree(dev->db_tab->page);
+ kfree(dev->db_tab);
+}
diff --git a/drivers/infiniband/hw/mthca/mthca_memfree.h b/drivers/infiniband/hw/mthca/mthca_memfree.h
index b63ae6624fe7d..a8fa97e140f5f 100644
--- a/drivers/infiniband/hw/mthca/mthca_memfree.h
+++ b/drivers/infiniband/hw/mthca/mthca_memfree.h
@@ -53,12 +53,16 @@ struct mthca_icm_chunk {
struct mthca_icm {
struct list_head chunk_list;
+ int refcount;
};
struct mthca_icm_table {
u64 virt;
int num_icm;
- struct semaphore sem;
+ int num_obj;
+ int obj_size;
+ int lowmem;
+ struct semaphore mutex;
struct mthca_icm *icm[0];
};
@@ -75,10 +79,12 @@ struct mthca_icm *mthca_alloc_icm(struct mthca_dev *dev, int npages,
void mthca_free_icm(struct mthca_dev *dev, struct mthca_icm *icm);
struct mthca_icm_table *mthca_alloc_icm_table(struct mthca_dev *dev,
- u64 virt, unsigned size,
- unsigned reserved,
+ u64 virt, int obj_size,
+ int nobj, int reserved,
int use_lowmem);
void mthca_free_icm_table(struct mthca_dev *dev, struct mthca_icm_table *table);
+int mthca_table_get(struct mthca_dev *dev, struct mthca_icm_table *table, int obj);
+void mthca_table_put(struct mthca_dev *dev, struct mthca_icm_table *table, int obj);
static inline void mthca_icm_first(struct mthca_icm *icm,
struct mthca_icm_iter *iter)
@@ -119,4 +125,37 @@ static inline unsigned long mthca_icm_size(struct mthca_icm_iter *iter)
return sg_dma_len(&iter->chunk->mem[iter->page_idx]);
}
+enum {
+ MTHCA_DB_REC_PER_PAGE = 4096 / 8
+};
+
+struct mthca_db_page {
+ DECLARE_BITMAP(used, MTHCA_DB_REC_PER_PAGE);
+ u64 *db_rec;
+ dma_addr_t mapping;
+};
+
+struct mthca_db_table {
+ int npages;
+ int max_group1;
+ int min_group2;
+ struct mthca_db_page *page;
+ struct semaphore mutex;
+};
+
+enum {
+ MTHCA_DB_TYPE_INVALID = 0x0,
+ MTHCA_DB_TYPE_CQ_SET_CI = 0x1,
+ MTHCA_DB_TYPE_CQ_ARM = 0x2,
+ MTHCA_DB_TYPE_SQ = 0x3,
+ MTHCA_DB_TYPE_RQ = 0x4,
+ MTHCA_DB_TYPE_SRQ = 0x5,
+ MTHCA_DB_TYPE_GROUP_SEP = 0x7
+};
+
+int mthca_init_db_tab(struct mthca_dev *dev);
+void mthca_cleanup_db_tab(struct mthca_dev *dev);
+int mthca_alloc_db(struct mthca_dev *dev, int type, u32 qn, u32 **db);
+void mthca_free_db(struct mthca_dev *dev, int type, int db_index);
+
#endif /* MTHCA_MEMFREE_H */
diff --git a/drivers/infiniband/hw/mthca/mthca_mr.c b/drivers/infiniband/hw/mthca/mthca_mr.c
index b7cbd246efc62..80a0cd97881b7 100644
--- a/drivers/infiniband/hw/mthca/mthca_mr.c
+++ b/drivers/infiniband/hw/mthca/mthca_mr.c
@@ -53,7 +53,8 @@ struct mthca_mpt_entry {
u32 window_count;
u32 window_count_limit;
u64 mtt_seg;
- u32 reserved[3];
+ u32 mtt_sz; /* Arbel only */
+ u32 reserved[2];
} __attribute__((packed));
#define MTHCA_MPT_FLAG_SW_OWNS (0xfUL << 28)
@@ -121,21 +122,38 @@ static void mthca_free_mtt(struct mthca_dev *dev, u32 seg, int order)
spin_unlock(&dev->mr_table.mpt_alloc.lock);
}
+static inline u32 hw_index_to_key(struct mthca_dev *dev, u32 ind)
+{
+ if (dev->hca_type == ARBEL_NATIVE)
+ return (ind >> 24) | (ind << 8);
+ else
+ return ind;
+}
+
+static inline u32 key_to_hw_index(struct mthca_dev *dev, u32 key)
+{
+ if (dev->hca_type == ARBEL_NATIVE)
+ return (key << 24) | (key >> 8);
+ else
+ return key;
+}
+
int mthca_mr_alloc_notrans(struct mthca_dev *dev, u32 pd,
u32 access, struct mthca_mr *mr)
{
void *mailbox;
struct mthca_mpt_entry *mpt_entry;
+ u32 key;
int err;
u8 status;
might_sleep();
mr->order = -1;
- mr->ibmr.lkey = mthca_alloc(&dev->mr_table.mpt_alloc);
- if (mr->ibmr.lkey == -1)
+ key = mthca_alloc(&dev->mr_table.mpt_alloc);
+ if (key == -1)
return -ENOMEM;
- mr->ibmr.rkey = mr->ibmr.lkey;
+ mr->ibmr.rkey = mr->ibmr.lkey = hw_index_to_key(dev, key);
mailbox = kmalloc(sizeof *mpt_entry + MTHCA_CMD_MAILBOX_EXTRA,
GFP_KERNEL);
@@ -151,7 +169,7 @@ int mthca_mr_alloc_notrans(struct mthca_dev *dev, u32 pd,
MTHCA_MPT_FLAG_REGION |
access);
mpt_entry->page_size = 0;
- mpt_entry->key = cpu_to_be32(mr->ibmr.lkey);
+ mpt_entry->key = cpu_to_be32(key);
mpt_entry->pd = cpu_to_be32(pd);
mpt_entry->start = 0;
mpt_entry->length = ~0ULL;
@@ -160,7 +178,7 @@ int mthca_mr_alloc_notrans(struct mthca_dev *dev, u32 pd,
sizeof *mpt_entry - offsetof(struct mthca_mpt_entry, lkey));
err = mthca_SW2HW_MPT(dev, mpt_entry,
- mr->ibmr.lkey & (dev->limits.num_mpts - 1),
+ key & (dev->limits.num_mpts - 1),
&status);
if (err)
mthca_warn(dev, "SW2HW_MPT failed (%d)\n", err);
@@ -182,6 +200,7 @@ int mthca_mr_alloc_phys(struct mthca_dev *dev, u32 pd,
void *mailbox;
u64 *mtt_entry;
struct mthca_mpt_entry *mpt_entry;
+ u32 key;
int err = -ENOMEM;
u8 status;
int i;
@@ -189,10 +208,10 @@ int mthca_mr_alloc_phys(struct mthca_dev *dev, u32 pd,
might_sleep();
WARN_ON(buffer_size_shift >= 32);
- mr->ibmr.lkey = mthca_alloc(&dev->mr_table.mpt_alloc);
- if (mr->ibmr.lkey == -1)
+ key = mthca_alloc(&dev->mr_table.mpt_alloc);
+ if (key == -1)
return -ENOMEM;
- mr->ibmr.rkey = mr->ibmr.lkey;
+ mr->ibmr.rkey = mr->ibmr.lkey = hw_index_to_key(dev, key);
for (i = dev->limits.mtt_seg_size / 8, mr->order = 0;
i < list_len;
@@ -254,7 +273,7 @@ int mthca_mr_alloc_phys(struct mthca_dev *dev, u32 pd,
access);
mpt_entry->page_size = cpu_to_be32(buffer_size_shift - 12);
- mpt_entry->key = cpu_to_be32(mr->ibmr.lkey);
+ mpt_entry->key = cpu_to_be32(key);
mpt_entry->pd = cpu_to_be32(pd);
mpt_entry->start = cpu_to_be64(iova);
mpt_entry->length = cpu_to_be64(total_size);
@@ -275,7 +294,7 @@ int mthca_mr_alloc_phys(struct mthca_dev *dev, u32 pd,
}
err = mthca_SW2HW_MPT(dev, mpt_entry,
- mr->ibmr.lkey & (dev->limits.num_mpts - 1),
+ key & (dev->limits.num_mpts - 1),
&status);
if (err)
mthca_warn(dev, "SW2HW_MPT failed (%d)\n", err);
@@ -307,7 +326,8 @@ void mthca_free_mr(struct mthca_dev *dev, struct mthca_mr *mr)
might_sleep();
err = mthca_HW2SW_MPT(dev, NULL,
- mr->ibmr.lkey & (dev->limits.num_mpts - 1),
+ key_to_hw_index(dev, mr->ibmr.lkey) &
+ (dev->limits.num_mpts - 1),
&status);
if (err)
mthca_warn(dev, "HW2SW_MPT failed (%d)\n", err);
@@ -318,7 +338,7 @@ void mthca_free_mr(struct mthca_dev *dev, struct mthca_mr *mr)
if (mr->order >= 0)
mthca_free_mtt(dev, mr->first_seg, mr->order);
- mthca_free(&dev->mr_table.mpt_alloc, mr->ibmr.lkey);
+ mthca_free(&dev->mr_table.mpt_alloc, key_to_hw_index(dev, mr->ibmr.lkey));
}
int __devinit mthca_init_mr_table(struct mthca_dev *dev)
diff --git a/drivers/infiniband/hw/mthca/mthca_profile.c b/drivers/infiniband/hw/mthca/mthca_profile.c
index 9b32ca86c199e..7881a8a919ca3 100644
--- a/drivers/infiniband/hw/mthca/mthca_profile.c
+++ b/drivers/infiniband/hw/mthca/mthca_profile.c
@@ -236,15 +236,20 @@ u64 mthca_make_profile(struct mthca_dev *dev,
init_hca->mtt_seg_sz = ffs(dev_lim->mtt_seg_sz) - 7;
break;
case MTHCA_RES_UAR:
+ dev->limits.num_uars = profile[i].num;
init_hca->uar_scratch_base = profile[i].start;
break;
case MTHCA_RES_UDAV:
dev->av_table.ddr_av_base = profile[i].start;
dev->av_table.num_ddr_avs = profile[i].num;
+ break;
case MTHCA_RES_UARC:
- init_hca->uarc_base = profile[i].start;
- init_hca->log_uarc_sz = ffs(request->uarc_size) - 13;
- init_hca->log_uar_sz = ffs(request->num_uar) - 1;
+ dev->uar_table.uarc_size = request->uarc_size;
+ dev->uar_table.uarc_base = profile[i].start;
+ init_hca->uarc_base = profile[i].start;
+ init_hca->log_uarc_sz = ffs(request->uarc_size) - 13;
+ init_hca->log_uar_sz = ffs(request->num_uar) - 1;
+ break;
default:
break;
}
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c
index 544408709209c..bbf74cf433438 100644
--- a/drivers/infiniband/hw/mthca/mthca_provider.c
+++ b/drivers/infiniband/hw/mthca/mthca_provider.c
@@ -43,6 +43,8 @@ static int mthca_query_device(struct ib_device *ibdev,
struct ib_smp *in_mad = NULL;
struct ib_smp *out_mad = NULL;
int err = -ENOMEM;
+ struct mthca_dev* mdev = to_mdev(ibdev);
+
u8 status;
in_mad = kmalloc(sizeof *in_mad, GFP_KERNEL);
@@ -50,7 +52,7 @@ static int mthca_query_device(struct ib_device *ibdev,
if (!in_mad || !out_mad)
goto out;
- props->fw_ver = to_mdev(ibdev)->fw_ver;
+ props->fw_ver = mdev->fw_ver;
memset(in_mad, 0, sizeof *in_mad);
in_mad->base_version = 1;
@@ -59,7 +61,7 @@ static int mthca_query_device(struct ib_device *ibdev,
in_mad->method = IB_MGMT_METHOD_GET;
in_mad->attr_id = IB_SMP_ATTR_NODE_INFO;
- err = mthca_MAD_IFC(to_mdev(ibdev), 1, 1,
+ err = mthca_MAD_IFC(mdev, 1, 1,
1, NULL, NULL, in_mad, out_mad,
&status);
if (err)
@@ -69,10 +71,11 @@ static int mthca_query_device(struct ib_device *ibdev,
goto out;
}
- props->vendor_id = be32_to_cpup((u32 *) (out_mad->data + 36)) &
+ props->device_cap_flags = mdev->device_cap_flags;
+ props->vendor_id = be32_to_cpup((u32 *) (out_mad->data + 36)) &
0xffffff;
- props->vendor_part_id = be16_to_cpup((u16 *) (out_mad->data + 30));
- props->hw_ver = be16_to_cpup((u16 *) (out_mad->data + 32));
+ props->vendor_part_id = be16_to_cpup((u16 *) (out_mad->data + 30));
+ props->hw_ver = be16_to_cpup((u16 *) (out_mad->data + 32));
memcpy(&props->sys_image_guid, out_mad->data + 4, 8);
memcpy(&props->node_guid, out_mad->data + 12, 8);
@@ -343,7 +346,7 @@ static struct ib_qp *mthca_create_qp(struct ib_pd *pd,
to_mcq(init_attr->send_cq),
to_mcq(init_attr->recv_cq),
init_attr->qp_type, init_attr->sq_sig_type,
- init_attr->rq_sig_type, qp);
+ qp);
qp->ibqp.qp_num = qp->qpn;
break;
}
@@ -364,7 +367,7 @@ static struct ib_qp *mthca_create_qp(struct ib_pd *pd,
err = mthca_alloc_sqp(to_mdev(pd->device), to_mpd(pd),
to_mcq(init_attr->send_cq),
to_mcq(init_attr->recv_cq),
- init_attr->sq_sig_type, init_attr->rq_sig_type,
+ init_attr->sq_sig_type,
qp->ibqp.qp_num, init_attr->port_num,
to_msqp(qp));
break;
@@ -408,8 +411,7 @@ static struct ib_cq *mthca_create_cq(struct ib_device *ibdev, int entries)
if (err) {
kfree(cq);
cq = ERR_PTR(err);
- } else
- cq->ibcq.cqe = nent - 1;
+ }
return &cq->ibcq;
}
@@ -422,13 +424,6 @@ static int mthca_destroy_cq(struct ib_cq *cq)
return 0;
}
-static int mthca_req_notify_cq(struct ib_cq *cq, enum ib_cq_notify notify)
-{
- mthca_arm_cq(to_mdev(cq->device), to_mcq(cq),
- notify == IB_CQ_SOLICITED);
- return 0;
-}
-
static inline u32 convert_access(int acc)
{
return (acc & IB_ACCESS_REMOTE_ATOMIC ? MTHCA_MPT_FLAG_ATOMIC : 0) |
@@ -621,12 +616,9 @@ int mthca_register_device(struct mthca_dev *dev)
dev->ib_dev.create_qp = mthca_create_qp;
dev->ib_dev.modify_qp = mthca_modify_qp;
dev->ib_dev.destroy_qp = mthca_destroy_qp;
- dev->ib_dev.post_send = mthca_post_send;
- dev->ib_dev.post_recv = mthca_post_receive;
dev->ib_dev.create_cq = mthca_create_cq;
dev->ib_dev.destroy_cq = mthca_destroy_cq;
dev->ib_dev.poll_cq = mthca_poll_cq;
- dev->ib_dev.req_notify_cq = mthca_req_notify_cq;
dev->ib_dev.get_dma_mr = mthca_get_dma_mr;
dev->ib_dev.reg_phys_mr = mthca_reg_phys_mr;
dev->ib_dev.dereg_mr = mthca_dereg_mr;
@@ -634,6 +626,16 @@ int mthca_register_device(struct mthca_dev *dev)
dev->ib_dev.detach_mcast = mthca_multicast_detach;
dev->ib_dev.process_mad = mthca_process_mad;
+ if (dev->hca_type == ARBEL_NATIVE) {
+ dev->ib_dev.req_notify_cq = mthca_arbel_arm_cq;
+ dev->ib_dev.post_send = mthca_arbel_post_send;
+ dev->ib_dev.post_recv = mthca_arbel_post_receive;
+ } else {
+ dev->ib_dev.req_notify_cq = mthca_tavor_arm_cq;
+ dev->ib_dev.post_send = mthca_tavor_post_send;
+ dev->ib_dev.post_recv = mthca_tavor_post_receive;
+ }
+
init_MUTEX(&dev->cap_mask_mutex);
ret = ib_register_device(&dev->ib_dev);
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.h b/drivers/infiniband/hw/mthca/mthca_provider.h
index 5c94df3d4dc25..0598f3905d9a1 100644
--- a/drivers/infiniband/hw/mthca/mthca_provider.h
+++ b/drivers/infiniband/hw/mthca/mthca_provider.h
@@ -49,6 +49,11 @@ struct mthca_buf_list {
DECLARE_PCI_UNMAP_ADDR(mapping)
};
+struct mthca_uar {
+ unsigned long pfn;
+ int index;
+};
+
struct mthca_mr {
struct ib_mr ibmr;
int order;
@@ -65,7 +70,7 @@ struct mthca_pd {
struct mthca_eq {
struct mthca_dev *dev;
int eqn;
- u32 ecr_mask;
+ u32 eqn_mask;
u32 cons_index;
u16 msi_x_vector;
u16 msi_x_entry;
@@ -77,12 +82,18 @@ struct mthca_eq {
struct mthca_av;
+enum mthca_ah_type {
+ MTHCA_AH_ON_HCA,
+ MTHCA_AH_PCI_POOL,
+ MTHCA_AH_KMALLOC
+};
+
struct mthca_ah {
- struct ib_ah ibah;
- int on_hca;
- u32 key;
- struct mthca_av *av;
- dma_addr_t avdma;
+ struct ib_ah ibah;
+ enum mthca_ah_type type;
+ u32 key;
+ struct mthca_av *av;
+ dma_addr_t avdma;
};
/*
@@ -136,8 +147,16 @@ struct mthca_cq {
spinlock_t lock;
atomic_t refcount;
int cqn;
- int cons_index;
+ u32 cons_index;
int is_direct;
+
+ /* Next fields are Arbel only */
+ int set_ci_db_index;
+ u32 *set_ci_db;
+ int arm_db_index;
+ u32 *arm_db;
+ int arm_sn;
+
union {
struct mthca_buf_list direct;
struct mthca_buf_list *page_list;
@@ -147,19 +166,22 @@ struct mthca_cq {
};
struct mthca_wq {
- int max;
- int cur;
- int next;
- int last_comp;
- void *last;
- int max_gs;
- int wqe_shift;
- enum ib_sig_type policy;
+ spinlock_t lock;
+ int max;
+ unsigned next_ind;
+ unsigned last_comp;
+ unsigned head;
+ unsigned tail;
+ void *last;
+ int max_gs;
+ int wqe_shift;
+
+ int db_index; /* Arbel only */
+ u32 *db;
};
struct mthca_qp {
struct ib_qp ibqp;
- spinlock_t lock;
atomic_t refcount;
u32 qpn;
int is_direct;
@@ -172,6 +194,7 @@ struct mthca_qp {
struct mthca_wq rq;
struct mthca_wq sq;
+ enum ib_sig_type sq_policy;
int send_wqe_offset;
u64 *wrid;
diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c
index e407ea931f5a2..7e4bbbd31f075 100644
--- a/drivers/infiniband/hw/mthca/mthca_qp.c
+++ b/drivers/infiniband/hw/mthca/mthca_qp.c
@@ -40,6 +40,7 @@
#include "mthca_dev.h"
#include "mthca_cmd.h"
+#include "mthca_memfree.h"
enum {
MTHCA_MAX_DIRECT_QP_SIZE = 4 * PAGE_SIZE,
@@ -105,8 +106,11 @@ struct mthca_qp_path {
struct mthca_qp_context {
u32 flags;
- u32 sched_queue;
- u32 mtu_msgmax;
+ u32 tavor_sched_queue; /* Reserved on Arbel */
+ u8 mtu_msgmax;
+ u8 rq_size_stride; /* Reserved on Tavor */
+ u8 sq_size_stride; /* Reserved on Tavor */
+ u8 rlkey_arbel_sched_queue; /* Reserved on Tavor */
u32 usr_page;
u32 local_qpn;
u32 remote_qpn;
@@ -121,18 +125,22 @@ struct mthca_qp_context {
u32 reserved2;
u32 next_send_psn;
u32 cqn_snd;
- u32 next_snd_wqe[2];
+ u32 snd_wqe_base_l; /* Next send WQE on Tavor */
+ u32 snd_db_index; /* (debugging only entries) */
u32 last_acked_psn;
u32 ssn;
u32 params2;
u32 rnr_nextrecvpsn;
u32 ra_buff_indx;
u32 cqn_rcv;
- u32 next_rcv_wqe[2];
+ u32 rcv_wqe_base_l; /* Next recv WQE on Tavor */
+ u32 rcv_db_index; /* (debugging only entries) */
u32 qkey;
u32 srqn;
u32 rmsn;
- u32 reserved3[19];
+ u16 rq_wqe_counter; /* reserved on Tavor */
+ u16 sq_wqe_counter; /* reserved on Tavor */
+ u32 reserved3[18];
} __attribute__((packed));
struct mthca_qp_param {
@@ -193,7 +201,7 @@ struct mthca_next_seg {
u32 imm; /* immediate data */
};
-struct mthca_ud_seg {
+struct mthca_tavor_ud_seg {
u32 reserved1;
u32 lkey;
u64 av_addr;
@@ -203,6 +211,13 @@ struct mthca_ud_seg {
u32 reserved3[2];
};
+struct mthca_arbel_ud_seg {
+ u32 av[8];
+ u32 dqpn;
+ u32 qkey;
+ u32 reserved[2];
+};
+
struct mthca_bind_seg {
u32 flags; /* [31] Atomic [30] rem write [29] rem read */
u32 reserved;
@@ -238,6 +253,16 @@ struct mthca_mlx_seg {
u16 vcrc;
};
+static const u8 mthca_opcode[] = {
+ [IB_WR_SEND] = MTHCA_OPCODE_SEND,
+ [IB_WR_SEND_WITH_IMM] = MTHCA_OPCODE_SEND_IMM,
+ [IB_WR_RDMA_WRITE] = MTHCA_OPCODE_RDMA_WRITE,
+ [IB_WR_RDMA_WRITE_WITH_IMM] = MTHCA_OPCODE_RDMA_WRITE_IMM,
+ [IB_WR_RDMA_READ] = MTHCA_OPCODE_RDMA_READ,
+ [IB_WR_ATOMIC_CMP_AND_SWP] = MTHCA_OPCODE_ATOMIC_CS,
+ [IB_WR_ATOMIC_FETCH_AND_ADD] = MTHCA_OPCODE_ATOMIC_FA,
+};
+
static int is_sqp(struct mthca_dev *dev, struct mthca_qp *qp)
{
return qp->qpn >= dev->qp_table.sqp_start &&
@@ -552,9 +577,11 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
else
cur_state = attr->cur_qp_state;
} else {
- spin_lock_irq(&qp->lock);
+ spin_lock_irq(&qp->sq.lock);
+ spin_lock(&qp->rq.lock);
cur_state = qp->state;
- spin_unlock_irq(&qp->lock);
+ spin_unlock(&qp->rq.lock);
+ spin_unlock_irq(&qp->sq.lock);
}
if (attr_mask & IB_QP_STATE) {
@@ -617,15 +644,24 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
break;
}
}
- /* leave sched_queue as 0 */
+
+ /* leave tavor_sched_queue as 0 */
+
if (qp->transport == MLX || qp->transport == UD)
- qp_context->mtu_msgmax = cpu_to_be32((IB_MTU_2048 << 29) |
- (11 << 24));
- else if (attr_mask & IB_QP_PATH_MTU) {
- qp_context->mtu_msgmax = cpu_to_be32((attr->path_mtu << 29) |
- (31 << 24));
+ qp_context->mtu_msgmax = (IB_MTU_2048 << 5) | 11;
+ else if (attr_mask & IB_QP_PATH_MTU)
+ qp_context->mtu_msgmax = (attr->path_mtu << 5) | 31;
+
+ if (dev->hca_type == ARBEL_NATIVE) {
+ qp_context->rq_size_stride =
+ ((ffs(qp->rq.max) - 1) << 3) | (qp->rq.wqe_shift - 4);
+ qp_context->sq_size_stride =
+ ((ffs(qp->sq.max) - 1) << 3) | (qp->sq.wqe_shift - 4);
}
- qp_context->usr_page = cpu_to_be32(MTHCA_KAR_PAGE);
+
+ /* leave arbel_sched_queue as 0 */
+
+ qp_context->usr_page = cpu_to_be32(dev->driver_uar.index);
qp_context->local_qpn = cpu_to_be32(qp->qpn);
if (attr_mask & IB_QP_DEST_QPN) {
qp_context->remote_qpn = cpu_to_be32(attr->dest_qp_num);
@@ -690,7 +726,7 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
MTHCA_QP_BIT_SRE |
MTHCA_QP_BIT_SWE |
MTHCA_QP_BIT_SAE);
- if (qp->sq.policy == IB_SIGNAL_ALL_WR)
+ 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) {
qp_context->params1 |= cpu_to_be32(attr->retry_cnt << 16);
@@ -708,6 +744,11 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
qp_context->next_send_psn = cpu_to_be32(attr->sq_psn);
qp_context->cqn_snd = cpu_to_be32(to_mcq(ibqp->send_cq)->cqn);
+ if (dev->hca_type == ARBEL_NATIVE) {
+ qp_context->snd_wqe_base_l = cpu_to_be32(qp->send_wqe_offset);
+ qp_context->snd_db_index = cpu_to_be32(qp->sq.db_index);
+ }
+
if (attr_mask & IB_QP_ACCESS_FLAGS) {
/*
* Only enable RDMA/atomics if we have responder
@@ -778,8 +819,8 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
qp->resp_depth = attr->max_rd_atomic;
}
- if (qp->rq.policy == IB_SIGNAL_ALL_WR)
- qp_context->params2 |= cpu_to_be32(MTHCA_QP_BIT_RSC);
+ qp_context->params2 |= cpu_to_be32(MTHCA_QP_BIT_RSC);
+
if (attr_mask & IB_QP_MIN_RNR_TIMER) {
qp_context->rnr_nextrecvpsn |= cpu_to_be32(attr->min_rnr_timer << 24);
qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_RNR_TIMEOUT);
@@ -787,12 +828,16 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
if (attr_mask & IB_QP_RQ_PSN)
qp_context->rnr_nextrecvpsn |= cpu_to_be32(attr->rq_psn);
- qp_context->ra_buff_indx = dev->qp_table.rdb_base +
- ((qp->qpn & (dev->limits.num_qps - 1)) * MTHCA_RDB_ENTRY_SIZE <<
- dev->qp_table.rdb_shift);
+ qp_context->ra_buff_indx =
+ cpu_to_be32(dev->qp_table.rdb_base +
+ ((qp->qpn & (dev->limits.num_qps - 1)) * MTHCA_RDB_ENTRY_SIZE <<
+ dev->qp_table.rdb_shift));
qp_context->cqn_rcv = cpu_to_be32(to_mcq(ibqp->recv_cq)->cqn);
+ if (dev->hca_type == ARBEL_NATIVE)
+ qp_context->rcv_db_index = cpu_to_be32(qp->rq.db_index);
+
if (attr_mask & IB_QP_QKEY) {
qp_context->qkey = cpu_to_be32(attr->qkey);
qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_Q_KEY);
@@ -860,12 +905,20 @@ static int mthca_alloc_wqe_buf(struct mthca_dev *dev,
size = sizeof (struct mthca_next_seg) +
qp->sq.max_gs * sizeof (struct mthca_data_seg);
- if (qp->transport == MLX)
+ switch (qp->transport) {
+ case MLX:
size += 2 * sizeof (struct mthca_data_seg);
- else if (qp->transport == UD)
- size += sizeof (struct mthca_ud_seg);
- else /* bind seg is as big as atomic + raddr segs */
+ break;
+ case UD:
+ if (dev->hca_type == ARBEL_NATIVE)
+ size += sizeof (struct mthca_arbel_ud_seg);
+ else
+ size += sizeof (struct mthca_tavor_ud_seg);
+ break;
+ default:
+ /* bind seg is as big as atomic + raddr segs */
size += sizeof (struct mthca_bind_seg);
+ }
for (qp->sq.wqe_shift = 6; 1 << qp->sq.wqe_shift < size;
qp->sq.wqe_shift++)
@@ -942,7 +995,6 @@ static int mthca_alloc_wqe_buf(struct mthca_dev *dev,
err = mthca_mr_alloc_phys(dev, pd->pd_num, dma_list, shift,
npages, 0, size,
- MTHCA_MPT_FLAG_LOCAL_WRITE |
MTHCA_MPT_FLAG_LOCAL_READ,
&qp->mr);
if (err)
@@ -972,34 +1024,134 @@ static int mthca_alloc_wqe_buf(struct mthca_dev *dev,
return err;
}
+static int mthca_alloc_memfree(struct mthca_dev *dev,
+ struct mthca_qp *qp)
+{
+ int ret = 0;
+
+ if (dev->hca_type == ARBEL_NATIVE) {
+ ret = mthca_table_get(dev, dev->qp_table.qp_table, qp->qpn);
+ if (ret)
+ return ret;
+
+ ret = mthca_table_get(dev, dev->qp_table.eqp_table, qp->qpn);
+ if (ret)
+ goto err_qpc;
+
+ qp->rq.db_index = mthca_alloc_db(dev, MTHCA_DB_TYPE_RQ,
+ qp->qpn, &qp->rq.db);
+ if (qp->rq.db_index < 0) {
+ ret = -ENOMEM;
+ goto err_eqpc;
+ }
+
+ qp->sq.db_index = mthca_alloc_db(dev, MTHCA_DB_TYPE_SQ,
+ qp->qpn, &qp->sq.db);
+ if (qp->sq.db_index < 0) {
+ ret = -ENOMEM;
+ goto err_rq_db;
+ }
+ }
+
+ return 0;
+
+err_rq_db:
+ mthca_free_db(dev, MTHCA_DB_TYPE_RQ, qp->rq.db_index);
+
+err_eqpc:
+ mthca_table_put(dev, dev->qp_table.eqp_table, qp->qpn);
+
+err_qpc:
+ mthca_table_put(dev, dev->qp_table.qp_table, qp->qpn);
+
+ return ret;
+}
+
+static void mthca_free_memfree(struct mthca_dev *dev,
+ struct mthca_qp *qp)
+{
+ if (dev->hca_type == ARBEL_NATIVE) {
+ mthca_free_db(dev, MTHCA_DB_TYPE_SQ, qp->sq.db_index);
+ mthca_free_db(dev, MTHCA_DB_TYPE_RQ, qp->rq.db_index);
+ mthca_table_put(dev, dev->qp_table.eqp_table, qp->qpn);
+ mthca_table_put(dev, dev->qp_table.qp_table, qp->qpn);
+ }
+}
+
+static void mthca_wq_init(struct mthca_wq* wq)
+{
+ spin_lock_init(&wq->lock);
+ wq->next_ind = 0;
+ wq->last_comp = wq->max - 1;
+ wq->head = 0;
+ wq->tail = 0;
+ wq->last = NULL;
+}
+
static int mthca_alloc_qp_common(struct mthca_dev *dev,
struct mthca_pd *pd,
struct mthca_cq *send_cq,
struct mthca_cq *recv_cq,
enum ib_sig_type send_policy,
- enum ib_sig_type recv_policy,
struct mthca_qp *qp)
{
- int err;
+ struct mthca_next_seg *wqe;
+ int ret;
+ int i;
- spin_lock_init(&qp->lock);
atomic_set(&qp->refcount, 1);
qp->state = IB_QPS_RESET;
qp->atomic_rd_en = 0;
qp->resp_depth = 0;
- qp->sq.policy = send_policy;
- qp->rq.policy = recv_policy;
- qp->rq.cur = 0;
- qp->sq.cur = 0;
- qp->rq.next = 0;
- qp->sq.next = 0;
- qp->rq.last_comp = qp->rq.max - 1;
- qp->sq.last_comp = qp->sq.max - 1;
- qp->rq.last = NULL;
- qp->sq.last = NULL;
-
- err = mthca_alloc_wqe_buf(dev, pd, qp);
- return err;
+ qp->sq_policy = send_policy;
+ mthca_wq_init(&qp->sq);
+ mthca_wq_init(&qp->rq);
+
+ ret = mthca_alloc_memfree(dev, qp);
+ if (ret)
+ return ret;
+
+ ret = mthca_alloc_wqe_buf(dev, pd, qp);
+ if (ret) {
+ mthca_free_memfree(dev, qp);
+ return ret;
+ }
+
+ if (dev->hca_type == ARBEL_NATIVE) {
+ for (i = 0; i < qp->rq.max; ++i) {
+ wqe = get_recv_wqe(qp, i);
+ wqe->nda_op = cpu_to_be32(((i + 1) & (qp->rq.max - 1)) <<
+ qp->rq.wqe_shift);
+ wqe->ee_nds = cpu_to_be32(1 << (qp->rq.wqe_shift - 4));
+ }
+
+ for (i = 0; i < qp->sq.max; ++i) {
+ wqe = get_send_wqe(qp, i);
+ wqe->nda_op = cpu_to_be32((((i + 1) & (qp->sq.max - 1)) <<
+ qp->sq.wqe_shift) +
+ qp->send_wqe_offset);
+ }
+ }
+
+ return 0;
+}
+
+static void mthca_align_qp_size(struct mthca_dev *dev, struct mthca_qp *qp)
+{
+ int i;
+
+ if (dev->hca_type != ARBEL_NATIVE)
+ return;
+
+ for (i = 0; 1 << i < qp->rq.max; ++i)
+ ; /* nothing */
+
+ qp->rq.max = 1 << i;
+
+ for (i = 0; 1 << i < qp->sq.max; ++i)
+ ; /* nothing */
+
+ qp->sq.max = 1 << i;
}
int mthca_alloc_qp(struct mthca_dev *dev,
@@ -1008,11 +1160,12 @@ int mthca_alloc_qp(struct mthca_dev *dev,
struct mthca_cq *recv_cq,
enum ib_qp_type type,
enum ib_sig_type send_policy,
- enum ib_sig_type recv_policy,
struct mthca_qp *qp)
{
int err;
+ mthca_align_qp_size(dev, qp);
+
switch (type) {
case IB_QPT_RC: qp->transport = RC; break;
case IB_QPT_UC: qp->transport = UC; break;
@@ -1025,7 +1178,7 @@ int mthca_alloc_qp(struct mthca_dev *dev,
return -ENOMEM;
err = mthca_alloc_qp_common(dev, pd, send_cq, recv_cq,
- send_policy, recv_policy, qp);
+ send_policy, qp);
if (err) {
mthca_free(&dev->qp_table.alloc, qp->qpn);
return err;
@@ -1044,7 +1197,6 @@ int mthca_alloc_sqp(struct mthca_dev *dev,
struct mthca_cq *send_cq,
struct mthca_cq *recv_cq,
enum ib_sig_type send_policy,
- enum ib_sig_type recv_policy,
int qpn,
int port,
struct mthca_sqp *sqp)
@@ -1052,6 +1204,8 @@ int mthca_alloc_sqp(struct mthca_dev *dev,
int err = 0;
u32 mqpn = qpn * 2 + dev->qp_table.sqp_start + port - 1;
+ mthca_align_qp_size(dev, &sqp->qp);
+
sqp->header_buf_size = sqp->qp.sq.max * MTHCA_UD_HEADER_SIZE;
sqp->header_buf = dma_alloc_coherent(&dev->pdev->dev, sqp->header_buf_size,
&sqp->header_dma, GFP_KERNEL);
@@ -1073,8 +1227,7 @@ int mthca_alloc_sqp(struct mthca_dev *dev,
sqp->qp.transport = MLX;
err = mthca_alloc_qp_common(dev, pd, send_cq, recv_cq,
- send_policy, recv_policy,
- &sqp->qp);
+ send_policy, &sqp->qp);
if (err)
goto err_out_free;
@@ -1083,9 +1236,21 @@ int mthca_alloc_sqp(struct mthca_dev *dev,
return 0;
err_out_free:
- spin_lock_irq(&dev->qp_table.lock);
+ /*
+ * Lock CQs here, so that CQ polling code can do QP lookup
+ * without taking a lock.
+ */
+ spin_lock_irq(&send_cq->lock);
+ if (send_cq != recv_cq)
+ spin_lock(&recv_cq->lock);
+
+ spin_lock(&dev->qp_table.lock);
mthca_array_clear(&dev->qp_table.qp, mqpn);
- spin_unlock_irq(&dev->qp_table.lock);
+ spin_unlock(&dev->qp_table.lock);
+
+ if (send_cq != recv_cq)
+ spin_unlock(&recv_cq->lock);
+ spin_unlock_irq(&send_cq->lock);
err_out:
dma_free_coherent(&dev->pdev->dev, sqp->header_buf_size,
@@ -1100,11 +1265,28 @@ void mthca_free_qp(struct mthca_dev *dev,
u8 status;
int size;
int i;
+ struct mthca_cq *send_cq;
+ struct mthca_cq *recv_cq;
- spin_lock_irq(&dev->qp_table.lock);
+ send_cq = to_mcq(qp->ibqp.send_cq);
+ recv_cq = to_mcq(qp->ibqp.recv_cq);
+
+ /*
+ * Lock CQs here, so that CQ polling code can do QP lookup
+ * without taking a lock.
+ */
+ spin_lock_irq(&send_cq->lock);
+ if (send_cq != recv_cq)
+ spin_lock(&recv_cq->lock);
+
+ spin_lock(&dev->qp_table.lock);
mthca_array_clear(&dev->qp_table.qp,
qp->qpn & (dev->limits.num_qps - 1));
- spin_unlock_irq(&dev->qp_table.lock);
+ spin_unlock(&dev->qp_table.lock);
+
+ if (send_cq != recv_cq)
+ spin_unlock(&recv_cq->lock);
+ spin_unlock_irq(&send_cq->lock);
atomic_dec(&qp->refcount);
wait_event(qp->wait, !atomic_read(&qp->refcount));
@@ -1136,14 +1318,15 @@ void mthca_free_qp(struct mthca_dev *dev,
kfree(qp->wrid);
+ mthca_free_memfree(dev, qp);
+
if (is_sqp(dev, qp)) {
atomic_dec(&(to_mpd(qp->ibqp.pd)->sqp_count));
dma_free_coherent(&dev->pdev->dev,
to_msqp(qp)->header_buf_size,
to_msqp(qp)->header_buf,
to_msqp(qp)->header_dma);
- }
- else
+ } else
mthca_free(&dev->qp_table.alloc, qp->qpn);
}
@@ -1216,8 +1399,26 @@ static int build_mlx_header(struct mthca_dev *dev, struct mthca_sqp *sqp,
return 0;
}
-int mthca_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
- struct ib_send_wr **bad_wr)
+static inline int mthca_wq_overflow(struct mthca_wq *wq, int nreq,
+ struct ib_cq *ib_cq)
+{
+ unsigned cur;
+ struct mthca_cq *cq;
+
+ cur = wq->head - wq->tail;
+ if (likely(cur + nreq < wq->max))
+ return 0;
+
+ cq = to_mcq(ib_cq);
+ spin_lock(&cq->lock);
+ cur = wq->head - wq->tail;
+ spin_unlock(&cq->lock);
+
+ return cur + nreq >= wq->max;
+}
+
+int mthca_tavor_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
+ struct ib_send_wr **bad_wr)
{
struct mthca_dev *dev = to_mdev(ibqp->device);
struct mthca_qp *qp = to_mqp(ibqp);
@@ -1233,26 +1434,18 @@ int mthca_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
int ind;
u8 op0 = 0;
- static const u8 opcode[] = {
- [IB_WR_SEND] = MTHCA_OPCODE_SEND,
- [IB_WR_SEND_WITH_IMM] = MTHCA_OPCODE_SEND_IMM,
- [IB_WR_RDMA_WRITE] = MTHCA_OPCODE_RDMA_WRITE,
- [IB_WR_RDMA_WRITE_WITH_IMM] = MTHCA_OPCODE_RDMA_WRITE_IMM,
- [IB_WR_RDMA_READ] = MTHCA_OPCODE_RDMA_READ,
- [IB_WR_ATOMIC_CMP_AND_SWP] = MTHCA_OPCODE_ATOMIC_CS,
- [IB_WR_ATOMIC_FETCH_AND_ADD] = MTHCA_OPCODE_ATOMIC_FA,
- };
-
- spin_lock_irqsave(&qp->lock, flags);
+ spin_lock_irqsave(&qp->sq.lock, flags);
/* XXX check that state is OK to post send */
- ind = qp->sq.next;
+ ind = qp->sq.next_ind;
for (nreq = 0; wr; ++nreq, wr = wr->next) {
- if (qp->sq.cur + nreq >= qp->sq.max) {
- mthca_err(dev, "SQ full (%d posted, %d max, %d nreq)\n",
- qp->sq.cur, qp->sq.max, nreq);
+ if (mthca_wq_overflow(&qp->sq, nreq, qp->ibqp.send_cq)) {
+ mthca_err(dev, "SQ %06x full (%u head, %u tail,"
+ " %d max, %d nreq)\n", qp->qpn,
+ qp->sq.head, qp->sq.tail,
+ qp->sq.max, nreq);
err = -ENOMEM;
*bad_wr = wr;
goto out;
@@ -1326,17 +1519,17 @@ int mthca_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
break;
case UD:
- ((struct mthca_ud_seg *) wqe)->lkey =
+ ((struct mthca_tavor_ud_seg *) wqe)->lkey =
cpu_to_be32(to_mah(wr->wr.ud.ah)->key);
- ((struct mthca_ud_seg *) wqe)->av_addr =
+ ((struct mthca_tavor_ud_seg *) wqe)->av_addr =
cpu_to_be64(to_mah(wr->wr.ud.ah)->avdma);
- ((struct mthca_ud_seg *) wqe)->dqpn =
+ ((struct mthca_tavor_ud_seg *) wqe)->dqpn =
cpu_to_be32(wr->wr.ud.remote_qpn);
- ((struct mthca_ud_seg *) wqe)->qkey =
+ ((struct mthca_tavor_ud_seg *) wqe)->qkey =
cpu_to_be32(wr->wr.ud.remote_qkey);
- wqe += sizeof (struct mthca_ud_seg);
- size += sizeof (struct mthca_ud_seg) / 16;
+ wqe += sizeof (struct mthca_tavor_ud_seg);
+ size += sizeof (struct mthca_tavor_ud_seg) / 16;
break;
case MLX:
@@ -1381,7 +1574,7 @@ int mthca_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
qp->wrid[ind + qp->rq.max] = wr->wr_id;
- if (wr->opcode >= ARRAY_SIZE(opcode)) {
+ if (wr->opcode >= ARRAY_SIZE(mthca_opcode)) {
mthca_err(dev, "opcode invalid\n");
err = -EINVAL;
*bad_wr = wr;
@@ -1392,15 +1585,15 @@ int mthca_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
((struct mthca_next_seg *) prev_wqe)->nda_op =
cpu_to_be32(((ind << qp->sq.wqe_shift) +
qp->send_wqe_offset) |
- opcode[wr->opcode]);
- smp_wmb();
+ mthca_opcode[wr->opcode]);
+ wmb();
((struct mthca_next_seg *) prev_wqe)->ee_nds =
cpu_to_be32((size0 ? 0 : MTHCA_NEXT_DBD) | size);
}
if (!size0) {
size0 = size;
- op0 = opcode[wr->opcode];
+ op0 = mthca_opcode[wr->opcode];
}
++ind;
@@ -1409,10 +1602,10 @@ int mthca_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
}
out:
- if (nreq) {
+ if (likely(nreq)) {
u32 doorbell[2];
- doorbell[0] = cpu_to_be32(((qp->sq.next << qp->sq.wqe_shift) +
+ doorbell[0] = cpu_to_be32(((qp->sq.next_ind << qp->sq.wqe_shift) +
qp->send_wqe_offset) | f0 | op0);
doorbell[1] = cpu_to_be32((qp->qpn << 8) | size0);
@@ -1423,15 +1616,15 @@ out:
MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock));
}
- qp->sq.cur += nreq;
- qp->sq.next = ind;
+ qp->sq.next_ind = ind;
+ qp->sq.head += nreq;
- spin_unlock_irqrestore(&qp->lock, flags);
+ spin_unlock_irqrestore(&qp->sq.lock, flags);
return err;
}
-int mthca_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
- struct ib_recv_wr **bad_wr)
+int mthca_tavor_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
+ struct ib_recv_wr **bad_wr)
{
struct mthca_dev *dev = to_mdev(ibqp->device);
struct mthca_qp *qp = to_mqp(ibqp);
@@ -1445,15 +1638,18 @@ int mthca_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
void *wqe;
void *prev_wqe;
- spin_lock_irqsave(&qp->lock, flags);
+ spin_lock_irqsave(&qp->rq.lock, flags);
/* XXX check that state is OK to post receive */
- ind = qp->rq.next;
+ ind = qp->rq.next_ind;
for (nreq = 0; wr; ++nreq, wr = wr->next) {
- if (qp->rq.cur + nreq >= qp->rq.max) {
- mthca_err(dev, "RQ %06x full\n", qp->qpn);
+ if (mthca_wq_overflow(&qp->rq, nreq, qp->ibqp.recv_cq)) {
+ mthca_err(dev, "RQ %06x full (%u head, %u tail,"
+ " %d max, %d nreq)\n", qp->qpn,
+ qp->rq.head, qp->rq.tail,
+ qp->rq.max, nreq);
err = -ENOMEM;
*bad_wr = wr;
goto out;
@@ -1466,14 +1662,12 @@ int mthca_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
((struct mthca_next_seg *) wqe)->nda_op = 0;
((struct mthca_next_seg *) wqe)->ee_nds =
cpu_to_be32(MTHCA_NEXT_DBD);
- ((struct mthca_next_seg *) wqe)->flags =
- (wr->recv_flags & IB_RECV_SIGNALED) ?
- cpu_to_be32(MTHCA_NEXT_CQ_UPDATE) : 0;
+ ((struct mthca_next_seg *) wqe)->flags = 0;
wqe += sizeof (struct mthca_next_seg);
size = sizeof (struct mthca_next_seg) / 16;
- if (wr->num_sge > qp->rq.max_gs) {
+ if (unlikely(wr->num_sge > qp->rq.max_gs)) {
err = -EINVAL;
*bad_wr = wr;
goto out;
@@ -1492,10 +1686,10 @@ int mthca_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
qp->wrid[ind] = wr->wr_id;
- if (prev_wqe) {
+ if (likely(prev_wqe)) {
((struct mthca_next_seg *) prev_wqe)->nda_op =
cpu_to_be32((ind << qp->rq.wqe_shift) | 1);
- smp_wmb();
+ wmb();
((struct mthca_next_seg *) prev_wqe)->ee_nds =
cpu_to_be32(MTHCA_NEXT_DBD | size);
}
@@ -1509,10 +1703,10 @@ int mthca_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
}
out:
- if (nreq) {
+ if (likely(nreq)) {
u32 doorbell[2];
- doorbell[0] = cpu_to_be32((qp->rq.next << qp->rq.wqe_shift) | size0);
+ doorbell[0] = cpu_to_be32((qp->rq.next_ind << qp->rq.wqe_shift) | size0);
doorbell[1] = cpu_to_be32((qp->qpn << 8) | nreq);
wmb();
@@ -1522,14 +1716,258 @@ out:
MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock));
}
- qp->rq.cur += nreq;
- qp->rq.next = ind;
+ qp->rq.next_ind = ind;
+ qp->rq.head += nreq;
+
+ spin_unlock_irqrestore(&qp->rq.lock, flags);
+ return err;
+}
+
+int mthca_arbel_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
+ struct ib_send_wr **bad_wr)
+{
+ struct mthca_dev *dev = to_mdev(ibqp->device);
+ struct mthca_qp *qp = to_mqp(ibqp);
+ void *wqe;
+ void *prev_wqe;
+ unsigned long flags;
+ int err = 0;
+ int nreq;
+ int i;
+ int size;
+ int size0 = 0;
+ u32 f0 = 0;
+ int ind;
+ u8 op0 = 0;
+
+ spin_lock_irqsave(&qp->sq.lock, flags);
+
+ /* XXX check that state is OK to post send */
+
+ ind = qp->sq.head & (qp->sq.max - 1);
+
+ for (nreq = 0; wr; ++nreq, wr = wr->next) {
+ if (mthca_wq_overflow(&qp->sq, nreq, qp->ibqp.send_cq)) {
+ mthca_err(dev, "SQ %06x full (%u head, %u tail,"
+ " %d max, %d nreq)\n", qp->qpn,
+ qp->sq.head, qp->sq.tail,
+ qp->sq.max, nreq);
+ err = -ENOMEM;
+ *bad_wr = wr;
+ goto out;
+ }
+
+ wqe = get_send_wqe(qp, ind);
+ prev_wqe = qp->sq.last;
+ qp->sq.last = wqe;
+
+ ((struct mthca_next_seg *) wqe)->flags =
+ ((wr->send_flags & IB_SEND_SIGNALED) ?
+ cpu_to_be32(MTHCA_NEXT_CQ_UPDATE) : 0) |
+ ((wr->send_flags & IB_SEND_SOLICITED) ?
+ cpu_to_be32(MTHCA_NEXT_SOLICIT) : 0) |
+ cpu_to_be32(1);
+ if (wr->opcode == IB_WR_SEND_WITH_IMM ||
+ wr->opcode == IB_WR_RDMA_WRITE_WITH_IMM)
+ ((struct mthca_next_seg *) wqe)->flags = wr->imm_data;
+
+ wqe += sizeof (struct mthca_next_seg);
+ size = sizeof (struct mthca_next_seg) / 16;
+
+ switch (qp->transport) {
+ case UD:
+ memcpy(((struct mthca_arbel_ud_seg *) wqe)->av,
+ to_mah(wr->wr.ud.ah)->av, MTHCA_AV_SIZE);
+ ((struct mthca_arbel_ud_seg *) wqe)->dqpn =
+ cpu_to_be32(wr->wr.ud.remote_qpn);
+ ((struct mthca_arbel_ud_seg *) wqe)->qkey =
+ cpu_to_be32(wr->wr.ud.remote_qkey);
+
+ wqe += sizeof (struct mthca_arbel_ud_seg);
+ size += sizeof (struct mthca_arbel_ud_seg) / 16;
+ break;
+
+ case MLX:
+ err = build_mlx_header(dev, to_msqp(qp), ind, wr,
+ wqe - sizeof (struct mthca_next_seg),
+ wqe);
+ if (err) {
+ *bad_wr = wr;
+ goto out;
+ }
+ wqe += sizeof (struct mthca_data_seg);
+ size += sizeof (struct mthca_data_seg) / 16;
+ break;
+ }
+
+ if (wr->num_sge > qp->sq.max_gs) {
+ mthca_err(dev, "too many gathers\n");
+ err = -EINVAL;
+ *bad_wr = wr;
+ goto out;
+ }
+
+ for (i = 0; i < wr->num_sge; ++i) {
+ ((struct mthca_data_seg *) wqe)->byte_count =
+ cpu_to_be32(wr->sg_list[i].length);
+ ((struct mthca_data_seg *) wqe)->lkey =
+ cpu_to_be32(wr->sg_list[i].lkey);
+ ((struct mthca_data_seg *) wqe)->addr =
+ cpu_to_be64(wr->sg_list[i].addr);
+ wqe += sizeof (struct mthca_data_seg);
+ size += sizeof (struct mthca_data_seg) / 16;
+ }
+
+ /* Add one more inline data segment for ICRC */
+ if (qp->transport == MLX) {
+ ((struct mthca_data_seg *) wqe)->byte_count =
+ cpu_to_be32((1 << 31) | 4);
+ ((u32 *) wqe)[1] = 0;
+ wqe += sizeof (struct mthca_data_seg);
+ size += sizeof (struct mthca_data_seg) / 16;
+ }
+
+ qp->wrid[ind + qp->rq.max] = wr->wr_id;
+
+ if (wr->opcode >= ARRAY_SIZE(mthca_opcode)) {
+ mthca_err(dev, "opcode invalid\n");
+ err = -EINVAL;
+ *bad_wr = wr;
+ goto out;
+ }
+
+ if (likely(prev_wqe)) {
+ ((struct mthca_next_seg *) prev_wqe)->nda_op =
+ cpu_to_be32(((ind << qp->sq.wqe_shift) +
+ qp->send_wqe_offset) |
+ mthca_opcode[wr->opcode]);
+ wmb();
+ ((struct mthca_next_seg *) prev_wqe)->ee_nds =
+ cpu_to_be32(MTHCA_NEXT_DBD | size);
+ }
+
+ if (!size0) {
+ size0 = size;
+ op0 = mthca_opcode[wr->opcode];
+ }
+
+ ++ind;
+ if (unlikely(ind >= qp->sq.max))
+ ind -= qp->sq.max;
+ }
+
+out:
+ if (likely(nreq)) {
+ u32 doorbell[2];
+
+ doorbell[0] = cpu_to_be32((nreq << 24) |
+ ((qp->sq.head & 0xffff) << 8) |
+ f0 | op0);
+ doorbell[1] = cpu_to_be32((qp->qpn << 8) | size0);
+
+ qp->sq.head += nreq;
+
+ /*
+ * Make sure that descriptors are written before
+ * doorbell record.
+ */
+ wmb();
+ *qp->sq.db = cpu_to_be32(qp->sq.head & 0xffff);
+
+ /*
+ * Make sure doorbell record is written before we
+ * write MMIO send doorbell.
+ */
+ wmb();
+ mthca_write64(doorbell,
+ dev->kar + MTHCA_SEND_DOORBELL,
+ MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock));
+ }
+
+ spin_unlock_irqrestore(&qp->sq.lock, flags);
+ return err;
+}
+
+int mthca_arbel_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
+ struct ib_recv_wr **bad_wr)
+{
+ struct mthca_dev *dev = to_mdev(ibqp->device);
+ struct mthca_qp *qp = to_mqp(ibqp);
+ unsigned long flags;
+ int err = 0;
+ int nreq;
+ int ind;
+ int i;
+ void *wqe;
+
+ spin_lock_irqsave(&qp->rq.lock, flags);
+
+ /* XXX check that state is OK to post receive */
+
+ ind = qp->rq.head & (qp->rq.max - 1);
+
+ for (nreq = 0; wr; ++nreq, wr = wr->next) {
+ if (mthca_wq_overflow(&qp->rq, nreq, qp->ibqp.recv_cq)) {
+ mthca_err(dev, "RQ %06x full (%u head, %u tail,"
+ " %d max, %d nreq)\n", qp->qpn,
+ qp->rq.head, qp->rq.tail,
+ qp->rq.max, nreq);
+ err = -ENOMEM;
+ *bad_wr = wr;
+ goto out;
+ }
+
+ wqe = get_recv_wqe(qp, ind);
+
+ ((struct mthca_next_seg *) wqe)->flags = 0;
+
+ wqe += sizeof (struct mthca_next_seg);
+
+ if (unlikely(wr->num_sge > qp->rq.max_gs)) {
+ err = -EINVAL;
+ *bad_wr = wr;
+ goto out;
+ }
+
+ for (i = 0; i < wr->num_sge; ++i) {
+ ((struct mthca_data_seg *) wqe)->byte_count =
+ cpu_to_be32(wr->sg_list[i].length);
+ ((struct mthca_data_seg *) wqe)->lkey =
+ cpu_to_be32(wr->sg_list[i].lkey);
+ ((struct mthca_data_seg *) wqe)->addr =
+ cpu_to_be64(wr->sg_list[i].addr);
+ wqe += sizeof (struct mthca_data_seg);
+ }
+
+ if (i < qp->rq.max_gs) {
+ ((struct mthca_data_seg *) wqe)->byte_count = 0;
+ ((struct mthca_data_seg *) wqe)->lkey = cpu_to_be32(0x100);
+ ((struct mthca_data_seg *) wqe)->addr = 0;
+ }
+
+ qp->wrid[ind] = wr->wr_id;
+
+ ++ind;
+ if (unlikely(ind >= qp->rq.max))
+ ind -= qp->rq.max;
+ }
+out:
+ if (likely(nreq)) {
+ qp->rq.head += nreq;
+
+ /*
+ * Make sure that descriptors are written before
+ * doorbell record.
+ */
+ wmb();
+ *qp->rq.db = cpu_to_be32(qp->rq.head & 0xffff);
+ }
- spin_unlock_irqrestore(&qp->lock, flags);
+ spin_unlock_irqrestore(&qp->rq.lock, flags);
return err;
}
-int mthca_free_err_wqe(struct mthca_qp *qp, int is_send,
+int mthca_free_err_wqe(struct mthca_dev *dev, struct mthca_qp *qp, int is_send,
int index, int *dbd, u32 *new_wqe)
{
struct mthca_next_seg *next;
@@ -1539,7 +1977,10 @@ int mthca_free_err_wqe(struct mthca_qp *qp, int is_send,
else
next = get_recv_wqe(qp, index);
- *dbd = !!(next->ee_nds & cpu_to_be32(MTHCA_NEXT_DBD));
+ if (dev->hca_type == ARBEL_NATIVE)
+ *dbd = 1;
+ else
+ *dbd = !!(next->ee_nds & cpu_to_be32(MTHCA_NEXT_DBD));
if (next->ee_nds & cpu_to_be32(0x3f))
*new_wqe = (next->nda_op & cpu_to_be32(~0x3f)) |
(next->ee_nds & cpu_to_be32(0x3f));
diff --git a/drivers/infiniband/hw/mthca/mthca_reset.c b/drivers/infiniband/hw/mthca/mthca_reset.c
index 35df81c85df26..ce3fff7d02b74 100644
--- a/drivers/infiniband/hw/mthca/mthca_reset.c
+++ b/drivers/infiniband/hw/mthca/mthca_reset.c
@@ -50,7 +50,7 @@ int mthca_reset(struct mthca_dev *mdev)
struct pci_dev *bridge = NULL;
#define MTHCA_RESET_OFFSET 0xf0010
-#define MTHCA_RESET_VALUE cpu_to_be32(1)
+#define MTHCA_RESET_VALUE swab32(1)
/*
* Reset the chip. This is somewhat ugly because we have to
diff --git a/drivers/infiniband/hw/mthca/mthca_uar.c b/drivers/infiniband/hw/mthca/mthca_uar.c
new file mode 100644
index 0000000000000..1c8791ded6ffc
--- /dev/null
+++ b/drivers/infiniband/hw/mthca/mthca_uar.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2005 Topspin Communications. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id$
+ */
+
+#include "mthca_dev.h"
+#include "mthca_memfree.h"
+
+int mthca_uar_alloc(struct mthca_dev *dev, struct mthca_uar *uar)
+{
+ uar->index = mthca_alloc(&dev->uar_table.alloc);
+ if (uar->index == -1)
+ return -ENOMEM;
+
+ uar->pfn = (pci_resource_start(dev->pdev, 2) >> PAGE_SHIFT) + uar->index;
+
+ return 0;
+}
+
+void mthca_uar_free(struct mthca_dev *dev, struct mthca_uar *uar)
+{
+ mthca_free(&dev->uar_table.alloc, uar->index);
+}
+
+int mthca_init_uar_table(struct mthca_dev *dev)
+{
+ int ret;
+
+ ret = mthca_alloc_init(&dev->uar_table.alloc,
+ dev->limits.num_uars,
+ dev->limits.num_uars - 1,
+ dev->limits.reserved_uars);
+ if (ret)
+ return ret;
+
+ ret = mthca_init_db_tab(dev);
+ if (ret)
+ mthca_alloc_cleanup(&dev->uar_table.alloc);
+
+ return ret;
+}
+
+void mthca_cleanup_uar_table(struct mthca_dev *dev)
+{
+ mthca_cleanup_db_tab(dev);
+
+ /* XXX check if any UARs are still allocated? */
+ mthca_alloc_cleanup(&dev->uar_table.alloc);
+}
diff --git a/drivers/infiniband/include/ib_verbs.h b/drivers/infiniband/include/ib_verbs.h
index cd1f01ebe653f..cf01f044a2230 100644
--- a/drivers/infiniband/include/ib_verbs.h
+++ b/drivers/infiniband/include/ib_verbs.h
@@ -73,7 +73,6 @@ enum ib_device_cap_flags {
IB_DEVICE_RC_RNR_NAK_GEN = (1<<12),
IB_DEVICE_SRQ_RESIZE = (1<<13),
IB_DEVICE_N_NOTIFY_CQ = (1<<14),
- IB_DEVICE_RQ_SIG_TYPE = (1<<15)
};
enum ib_atomic_cap {
@@ -408,7 +407,6 @@ struct ib_qp_init_attr {
struct ib_srq *srq;
struct ib_qp_cap cap;
enum ib_sig_type sq_sig_type;
- enum ib_sig_type rq_sig_type;
enum ib_qp_type qp_type;
u8 port_num; /* special QP types only */
};
@@ -533,10 +531,6 @@ enum ib_send_flags {
IB_SEND_INLINE = (1<<3)
};
-enum ib_recv_flags {
- IB_RECV_SIGNALED = 1
-};
-
struct ib_sge {
u64 addr;
u32 length;
@@ -579,7 +573,6 @@ struct ib_recv_wr {
u64 wr_id;
struct ib_sge *sg_list;
int num_sge;
- int recv_flags;
};
enum ib_access_flags {
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h
index 074394d4f8a99..04c98f54e9c4d 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib.h
+++ b/drivers/infiniband/ulp/ipoib/ipoib.h
@@ -308,11 +308,11 @@ static inline void ipoib_unregister_debugfs(void) { }
#ifdef CONFIG_INFINIBAND_IPOIB_DEBUG
-extern int debug_level;
+extern int ipoib_debug_level;
#define ipoib_dbg(priv, format, arg...) \
do { \
- if (debug_level > 0) \
+ if (ipoib_debug_level > 0) \
ipoib_printk(KERN_DEBUG, priv, format , ## arg); \
} while (0)
#define ipoib_dbg_mcast(priv, format, arg...) \
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
index f89ac4640e88d..c5a1d45e0ac52 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
@@ -40,7 +40,7 @@
#include "ipoib.h"
#ifdef CONFIG_INFINIBAND_IPOIB_DEBUG_DATA
-int data_debug_level;
+static int data_debug_level;
module_param(data_debug_level, int, 0644);
MODULE_PARM_DESC(data_debug_level,
@@ -105,7 +105,6 @@ static inline int ipoib_ib_receive(struct ipoib_dev_priv *priv,
.wr_id = wr_id | IPOIB_OP_RECV,
.sg_list = &list,
.num_sge = 1,
- .recv_flags = IB_RECV_SIGNALED
};
struct ib_recv_wr *bad_wr;
@@ -137,6 +136,9 @@ static int ipoib_ib_post_receive(struct net_device *dev, int id)
if (ret) {
ipoib_warn(priv, "ipoib_ib_receive failed for buf %d (%d)\n",
id, ret);
+ dma_unmap_single(priv->ca->dma_device, addr,
+ IPOIB_BUF_SIZE, DMA_FROM_DEVICE);
+ dev_kfree_skb_any(skb);
priv->rx_ring[id].skb = NULL;
}
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index 63c8168d8af80..5a3b5c6a44940 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -51,9 +51,9 @@ MODULE_DESCRIPTION("IP-over-InfiniBand net driver");
MODULE_LICENSE("Dual BSD/GPL");
#ifdef CONFIG_INFINIBAND_IPOIB_DEBUG
-int debug_level;
+int ipoib_debug_level;
-module_param(debug_level, int, 0644);
+module_param_named(debug_level, ipoib_debug_level, int, 0644);
MODULE_PARM_DESC(debug_level, "Enable debug tracing if > 0");
#endif
@@ -215,16 +215,25 @@ static int __path_add(struct net_device *dev, struct ipoib_path *path)
return 0;
}
-static void __path_free(struct net_device *dev, struct ipoib_path *path)
+static void path_free(struct net_device *dev, struct ipoib_path *path)
{
struct ipoib_dev_priv *priv = netdev_priv(dev);
struct ipoib_neigh *neigh, *tn;
struct sk_buff *skb;
+ unsigned long flags;
while ((skb = __skb_dequeue(&path->queue)))
dev_kfree_skb_irq(skb);
+ spin_lock_irqsave(&priv->lock, flags);
+
list_for_each_entry_safe(neigh, tn, &path->neigh_list, list) {
+ /*
+ * It's safe to call ipoib_put_ah() inside priv->lock
+ * here, because we know that path->ah will always
+ * hold one more reference, so ipoib_put_ah() will
+ * never do more than decrement the ref count.
+ */
if (neigh->ah)
ipoib_put_ah(neigh->ah);
*to_ipoib_neigh(neigh->neighbour) = NULL;
@@ -232,11 +241,11 @@ static void __path_free(struct net_device *dev, struct ipoib_path *path)
kfree(neigh);
}
+ spin_unlock_irqrestore(&priv->lock, flags);
+
if (path->ah)
ipoib_put_ah(path->ah);
- rb_erase(&path->rb_node, &priv->path_tree);
- list_del(&path->list);
kfree(path);
}
@@ -248,15 +257,20 @@ void ipoib_flush_paths(struct net_device *dev)
unsigned long flags;
spin_lock_irqsave(&priv->lock, flags);
+
list_splice(&priv->path_list, &remove_list);
INIT_LIST_HEAD(&priv->path_list);
+
+ list_for_each_entry(path, &remove_list, list)
+ rb_erase(&path->rb_node, &priv->path_tree);
+
spin_unlock_irqrestore(&priv->lock, flags);
list_for_each_entry_safe(path, tp, &remove_list, list) {
if (path->query)
ib_sa_cancel_query(path->query_id, path->query);
wait_for_completion(&path->done);
- __path_free(dev, path);
+ path_free(dev, path);
}
}
@@ -346,8 +360,9 @@ static struct ipoib_path *path_rec_create(struct net_device *dev,
if (!path)
return NULL;
- path->dev = dev;
+ path->dev = dev;
path->pathrec.dlid = 0;
+ path->ah = NULL;
skb_queue_head_init(&path->queue);
@@ -360,8 +375,6 @@ static struct ipoib_path *path_rec_create(struct net_device *dev,
path->pathrec.pkey = cpu_to_be16(priv->pkey);
path->pathrec.numb_path = 1;
- __path_add(dev, path);
-
return path;
}
@@ -421,6 +434,8 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev)
(union ib_gid *) (skb->dst->neighbour->ha + 4));
if (!path)
goto err;
+
+ __path_add(dev, path);
}
list_add_tail(&neigh->list, &path->neigh_list);
@@ -450,8 +465,8 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev)
err:
*to_ipoib_neigh(skb->dst->neighbour) = NULL;
list_del(&neigh->list);
- kfree(neigh);
neigh->neighbour->ops->destructor = NULL;
+ kfree(neigh);
++priv->stats.tx_dropped;
dev_kfree_skb_any(skb);
@@ -496,8 +511,12 @@ static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev,
skb_push(skb, sizeof *phdr);
__skb_queue_tail(&path->queue, skb);
- if (path_rec_start(dev, path))
- __path_free(dev, path);
+ if (path_rec_start(dev, path)) {
+ spin_unlock(&priv->lock);
+ path_free(dev, path);
+ return;
+ } else
+ __path_add(dev, path);
} else {
++priv->stats.tx_dropped;
dev_kfree_skb_any(skb);
@@ -657,9 +676,10 @@ static void ipoib_set_mcast_list(struct net_device *dev)
static void ipoib_neigh_destructor(struct neighbour *n)
{
- struct ipoib_neigh *neigh = *to_ipoib_neigh(n);
+ struct ipoib_neigh *neigh;
struct ipoib_dev_priv *priv = netdev_priv(n->dev);
unsigned long flags;
+ struct ipoib_ah *ah = NULL;
ipoib_dbg(priv,
"neigh_destructor for %06x " IPOIB_GID_FMT "\n",
@@ -668,15 +688,19 @@ static void ipoib_neigh_destructor(struct neighbour *n)
spin_lock_irqsave(&priv->lock, flags);
+ neigh = *to_ipoib_neigh(n);
if (neigh) {
if (neigh->ah)
- ipoib_put_ah(neigh->ah);
+ ah = neigh->ah;
list_del(&neigh->list);
*to_ipoib_neigh(n) = NULL;
kfree(neigh);
}
spin_unlock_irqrestore(&priv->lock, flags);
+
+ if (ah)
+ ipoib_put_ah(ah);
}
static int ipoib_neigh_setup(struct neighbour *neigh)
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
index 68969625d966c..f46932dc81c94 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
@@ -93,6 +93,8 @@ 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",
@@ -101,7 +103,8 @@ 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) {
- ipoib_put_ah(neigh->ah);
+ if (neigh->ah)
+ list_add_tail(&neigh->ah->list, &ah_list);
*to_ipoib_neigh(neigh->neighbour) = NULL;
neigh->neighbour->ops->destructor = NULL;
kfree(neigh);
@@ -109,6 +112,9 @@ 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);
@@ -790,7 +796,7 @@ void ipoib_mcast_dev_flush(struct net_device *dev)
spin_unlock_irqrestore(&priv->lock, flags);
- list_for_each_entry(mcast, &remove_list, list) {
+ list_for_each_entry_safe(mcast, tmcast, &remove_list, list) {
ipoib_mcast_leave(dev, mcast);
ipoib_mcast_free(mcast);
}
@@ -902,7 +908,7 @@ void ipoib_mcast_restart_task(void *dev_ptr)
spin_unlock_irqrestore(&priv->lock, flags);
/* We have to cancel outside of the spinlock */
- list_for_each_entry(mcast, &remove_list, list) {
+ list_for_each_entry_safe(mcast, tmcast, &remove_list, list) {
ipoib_mcast_leave(mcast->dev, mcast);
ipoib_mcast_free(mcast);
}
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
index 368162c48ea3a..4933edf062c2b 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
@@ -165,7 +165,6 @@ int ipoib_transport_dev_init(struct net_device *dev, struct ib_device *ca)
.max_recv_sge = 1
},
.sq_sig_type = IB_SIGNAL_ALL_WR,
- .rq_sig_type = IB_SIGNAL_ALL_WR,
.qp_type = IB_QPT_UD
};
diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig
index 262d36a82e30f..58223b5d842a0 100644
--- a/drivers/input/Kconfig
+++ b/drivers/input/Kconfig
@@ -5,7 +5,7 @@
menu "Input device support"
config INPUT
- tristate "Input devices (needed for keyboard, mouse, ...)" if EMBEDDED
+ tristate "Generic input layer (needed for keyboard, mouse, ...)" if EMBEDDED
default y
---help---
Say Y here if you have any input device (mouse, keyboard, tablet,
@@ -22,12 +22,13 @@ config INPUT
To compile this driver as a module, choose M here: the
module will be called input.
+if INPUT
+
comment "Userland interfaces"
config INPUT_MOUSEDEV
tristate "Mouse interface" if EMBEDDED
default y
- depends on INPUT
---help---
Say Y here if you want your mouse to be accessible as char devices
13:32+ - /dev/input/mouseX and 13:63 - /dev/input/mice as an
@@ -74,7 +75,6 @@ config INPUT_MOUSEDEV_SCREEN_Y
config INPUT_JOYDEV
tristate "Joystick interface"
- depends on INPUT
---help---
Say Y here if you want your joystick or gamepad to be
accessible as char device 13:0+ - /dev/input/jsX device.
@@ -88,7 +88,6 @@ config INPUT_JOYDEV
config INPUT_TSDEV
tristate "Touchscreen interface"
- depends on INPUT
---help---
Say Y here if you have an application that only can understand the
Compaq touchscreen protocol for absolute pointer data. This is
@@ -111,7 +110,6 @@ config INPUT_TSDEV_SCREEN_Y
config INPUT_EVDEV
tristate "Event interface"
- depends on INPUT
help
Say Y here if you want your input device events be accessible
under char device 13:64+ - /dev/input/eventX in a generic way.
@@ -121,7 +119,6 @@ config INPUT_EVDEV
config INPUT_EVBUG
tristate "Event debugging"
- depends on INPUT
---help---
Say Y here if you have a problem with the input subsystem and
want all events (keypresses, mouse movements), to be output to
@@ -134,12 +131,6 @@ config INPUT_EVBUG
To compile this driver as a module, choose M here: the
module will be called evbug.
-comment "Input I/O drivers"
-
-source "drivers/input/gameport/Kconfig"
-
-source "drivers/input/serio/Kconfig"
-
comment "Input Device Drivers"
source "drivers/input/keyboard/Kconfig"
@@ -152,5 +143,15 @@ source "drivers/input/touchscreen/Kconfig"
source "drivers/input/misc/Kconfig"
+endif
+
+menu "Hardware I/O ports"
+
+source "drivers/input/serio/Kconfig"
+
+source "drivers/input/gameport/Kconfig"
+
+endmenu
+
endmenu
diff --git a/drivers/input/evbug.c b/drivers/input/evbug.c
index 7eabb5f4ee57f..d7828936fd8f5 100644
--- a/drivers/input/evbug.c
+++ b/drivers/input/evbug.c
@@ -88,13 +88,13 @@ static struct input_handler evbug_handler = {
.id_table = evbug_ids,
};
-int __init evbug_init(void)
+static int __init evbug_init(void)
{
input_register_handler(&evbug_handler);
return 0;
}
-void __exit evbug_exit(void)
+static void __exit evbug_exit(void)
{
input_unregister_handler(&evbug_handler);
}
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index 39c497e5fafaf..17552a29978b8 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -169,6 +169,9 @@ static ssize_t evdev_read(struct file * file, char __user * buffer, size_t count
struct evdev_list *list = file->private_data;
int retval;
+ if (count < sizeof(struct input_event))
+ return -EINVAL;
+
if (list->head == list->tail && list->evdev->exist && (file->f_flags & O_NONBLOCK))
return -EAGAIN;
@@ -196,9 +199,8 @@ static unsigned int evdev_poll(struct file *file, poll_table *wait)
{
struct evdev_list *list = file->private_data;
poll_wait(file, &list->evdev->wait, wait);
- if (list->head != list->tail)
- return POLLIN | POLLRDNORM;
- return 0;
+ return ((list->head == list->tail) ? 0 : (POLLIN | POLLRDNORM)) |
+ (list->evdev->exist ? 0 : (POLLHUP | POLLERR));
}
static int evdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
@@ -223,14 +225,15 @@ static int evdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
case EVIOCGKEYCODE:
if (get_user(t, ip)) return -EFAULT;
- if (t < 0 || t > dev->keycodemax || !dev->keycodesize) return -EINVAL;
+ 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 (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;
u = SET_INPUT_KEYCODE(dev, t, v);
clear_bit(u, dev->keybit);
set_bit(v, dev->keybit);
@@ -438,6 +441,7 @@ static struct input_handle *evdev_connect(struct input_handler *handler, struct
static void evdev_disconnect(struct input_handle *handle)
{
struct evdev *evdev = handle->private;
+ struct evdev_list *list;
class_simple_device_remove(MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + evdev->minor));
devfs_remove("input/event%d", evdev->minor);
@@ -446,6 +450,8 @@ static void evdev_disconnect(struct input_handle *handle)
if (evdev->open) {
input_close_device(handle);
wake_up_interruptible(&evdev->wait);
+ list_for_each_entry(list, &evdev->list, node)
+ kill_fasync(&list->fasync, SIGIO, POLL_HUP);
} else
evdev_free(evdev);
}
diff --git a/drivers/input/gameport/Kconfig b/drivers/input/gameport/Kconfig
index 4473553389602..f67daf023b320 100644
--- a/drivers/input/gameport/Kconfig
+++ b/drivers/input/gameport/Kconfig
@@ -19,30 +19,10 @@ config GAMEPORT
To compile this driver as a module, choose M here: the
module will be called gameport.
-
-# Yes, SOUND_GAMEPORT looks a bit odd. Yes, it ends up being turned on
-# in every .config. Please don't touch it. It is here to handle an
-# unusual dependency between GAMEPORT and sound drivers.
-#
-# Some sound drivers call gameport functions. If GAMEPORT is
-# not selected, empty stubs are provided for the functions and all is
-# well.
-# If GAMEPORT is built in, everything is fine.
-# If GAMEPORT is a module, however, it would need to be loaded for the
-# sound driver to be able to link properly. Therefore, the sound
-# driver must be a module as well in that case. Since there's no way
-# to express that directly in Kconfig, we use SOUND_GAMEPORT to
-# express it. SOUND_GAMEPORT boils down to "if GAMEPORT is 'm',
-# anything that depends on SOUND_GAMEPORT must be 'm' as well. if
-# GAMEPORT is 'y' or 'n', it can be anything".
-config SOUND_GAMEPORT
- tristate
- default y if GAMEPORT!=m
- default m if GAMEPORT=m
+if GAMEPORT
config GAMEPORT_NS558
tristate "Classic ISA and PnP gameport support"
- depends on GAMEPORT
help
Say Y here if you have an ISA or PnP gameport.
@@ -53,7 +33,6 @@ config GAMEPORT_NS558
config GAMEPORT_L4
tristate "PDPI Lightning 4 gamecard support"
- depends on GAMEPORT
help
Say Y here if you have a PDPI Lightning 4 gamecard.
@@ -62,7 +41,6 @@ config GAMEPORT_L4
config GAMEPORT_EMU10K1
tristate "SB Live and Audigy gameport support"
- depends on GAMEPORT
help
Say Y here if you have a SoundBlaster Live! or SoundBlaster
Audigy card and want to use its gameport.
@@ -72,7 +50,6 @@ config GAMEPORT_EMU10K1
config GAMEPORT_VORTEX
tristate "Aureal Vortex, Vortex 2 gameport support"
- depends on GAMEPORT
help
Say Y here if you have an Aureal Vortex 1 or 2 card and want
to use its gameport.
@@ -82,9 +59,28 @@ config GAMEPORT_VORTEX
config GAMEPORT_FM801
tristate "ForteMedia FM801 gameport support"
- depends on GAMEPORT
config GAMEPORT_CS461X
tristate "Crystal SoundFusion gameport support"
- depends on GAMEPORT
+endif
+
+# Yes, SOUND_GAMEPORT looks a bit odd. Yes, it ends up being turned on
+# in every .config. Please don't touch it. It is here to handle an
+# unusual dependency between GAMEPORT and sound drivers.
+#
+# Some sound drivers call gameport functions. If GAMEPORT is
+# not selected, empty stubs are provided for the functions and all is
+# well.
+# If GAMEPORT is built in, everything is fine.
+# If GAMEPORT is a module, however, it would need to be loaded for the
+# sound driver to be able to link properly. Therefore, the sound
+# driver must be a module as well in that case. Since there's no way
+# to express that directly in Kconfig, we use SOUND_GAMEPORT to
+# express it. SOUND_GAMEPORT boils down to "if GAMEPORT is 'm',
+# anything that depends on SOUND_GAMEPORT must be 'm' as well. if
+# GAMEPORT is 'y' or 'n', it can be anything".
+config SOUND_GAMEPORT
+ tristate
+ default m if GAMEPORT=m
+ default y
diff --git a/drivers/input/gameport/cs461x.c b/drivers/input/gameport/cs461x.c
index 2b684b4311a78..d4013ff986235 100644
--- a/drivers/input/gameport/cs461x.c
+++ b/drivers/input/gameport/cs461x.c
@@ -16,7 +16,7 @@
#include <linux/slab.h>
#include <linux/pci.h>
-MODULE_AUTHOR("Victor Krapivin <vik@belcaf.minsk.by>");
+MODULE_AUTHOR("Victor Krapivin");
MODULE_LICENSE("GPL");
/*
@@ -120,9 +120,6 @@ MODULE_LICENSE("GPL");
static unsigned long ba0_addr;
static unsigned int __iomem *ba0;
-static char phys[32];
-static char name[] = "CS416x Gameport";
-
#ifdef CS461X_FULL_MAP
static unsigned long ba1_addr;
static union ba1_t {
@@ -160,10 +157,10 @@ static unsigned int cs461x_peekBA0(unsigned long reg)
static int cs461x_free(struct pci_dev *pdev)
{
struct gameport *port = pci_get_drvdata(pdev);
- if(port){
+
+ if (port)
gameport_unregister_port(port);
- kfree(port);
- }
+
if (ba0) iounmap(ba0);
#ifdef CS461X_FULL_MAP
if (ba1.name.data0) iounmap(ba1.name.data0);
@@ -267,18 +264,17 @@ static int __devinit cs461x_pci_probe(struct pci_dev *pdev, const struct pci_dev
return -ENOMEM;
}
#else
- if (ba0 == NULL){
+ if (ba0 == NULL) {
cs461x_free(pdev);
return -ENOMEM;
}
#endif
- if (!(port = kmalloc(sizeof(struct gameport), GFP_KERNEL))) {
- printk(KERN_ERR "Memory allocation failed.\n");
+ if (!(port = gameport_allocate_port())) {
+ printk(KERN_ERR "cs461x: Memory allocation failed\n");
cs461x_free(pdev);
return -ENOMEM;
}
- memset(port, 0, sizeof(struct gameport));
pci_set_drvdata(pdev, port);
@@ -287,22 +283,15 @@ static int __devinit cs461x_pci_probe(struct pci_dev *pdev, const struct pci_dev
port->read = cs461x_gameport_read;
port->cooked_read = cs461x_gameport_cooked_read;
- sprintf(phys, "pci%s/gameport0", pci_name(pdev));
-
- port->name = name;
- port->phys = phys;
- port->id.bustype = BUS_PCI;
- port->id.vendor = pdev->vendor;
- port->id.product = pdev->device;
+ gameport_set_name(port, "CS416x");
+ gameport_set_phys(port, "pci%s/gameport0", pci_name(pdev));
+ port->dev.parent = &pdev->dev;
cs461x_pokeBA0(BA0_JSIO, 0xFF); // ?
cs461x_pokeBA0(BA0_JSCTL, JSCTL_SP_MEDIUM_SLOW);
gameport_register_port(port);
- printk(KERN_INFO "gameport: %s on pci%s speed %d kHz\n",
- name, pci_name(pdev), port->speed);
-
return 0;
}
@@ -318,12 +307,12 @@ static struct pci_driver cs461x_pci_driver = {
.remove = __devexit_p(cs461x_pci_remove),
};
-int __init cs461x_init(void)
+static int __init cs461x_init(void)
{
- return pci_module_init(&cs461x_pci_driver);
+ return pci_register_driver(&cs461x_pci_driver);
}
-void __exit cs461x_exit(void)
+static void __exit cs461x_exit(void)
{
pci_unregister_driver(&cs461x_pci_driver);
}
diff --git a/drivers/input/gameport/emu10k1-gp.c b/drivers/input/gameport/emu10k1-gp.c
index 8f1461ad2984a..a0118038330a9 100644
--- a/drivers/input/gameport/emu10k1-gp.c
+++ b/drivers/input/gameport/emu10k1-gp.c
@@ -44,13 +44,13 @@ MODULE_LICENSE("GPL");
struct emu {
struct pci_dev *dev;
- struct gameport gameport;
+ struct gameport *gameport;
+ int io;
int size;
- char phys[32];
};
static struct pci_device_id emu_tbl[] = {
-
+
{ 0x1102, 0x7002, PCI_ANY_ID, PCI_ANY_ID }, /* SB Live gameport */
{ 0x1102, 0x7003, PCI_ANY_ID, PCI_ANY_ID }, /* Audigy gameport */
{ 0x1102, 0x7004, PCI_ANY_ID, PCI_ANY_ID }, /* Dell SB Live */
@@ -64,6 +64,7 @@ static int __devinit emu_probe(struct pci_dev *pdev, const struct pci_device_id
{
int ioport, iolen;
struct emu *emu;
+ struct gameport *port;
if (pci_enable_device(pdev))
return -EBUSY;
@@ -74,31 +75,29 @@ static int __devinit emu_probe(struct pci_dev *pdev, const struct pci_device_id
if (!request_region(ioport, iolen, "emu10k1-gp"))
return -EBUSY;
- if (!(emu = kmalloc(sizeof(struct emu), GFP_KERNEL))) {
- printk(KERN_ERR "emu10k1-gp: Memory allocation failed.\n");
+ emu = kcalloc(1, sizeof(struct emu), GFP_KERNEL);
+ port = gameport_allocate_port();
+ if (!emu || !port) {
+ printk(KERN_ERR "emu10k1-gp: Memory allocation failed\n");
release_region(ioport, iolen);
+ kfree(emu);
+ gameport_free_port(port);
return -ENOMEM;
}
- memset(emu, 0, sizeof(struct emu));
-
- sprintf(emu->phys, "pci%s/gameport0", pci_name(pdev));
+ emu->io = ioport;
emu->size = iolen;
emu->dev = pdev;
+ emu->gameport = port;
- emu->gameport.io = ioport;
- emu->gameport.name = pci_name(pdev);
- emu->gameport.phys = emu->phys;
- emu->gameport.id.bustype = BUS_PCI;
- emu->gameport.id.vendor = pdev->vendor;
- emu->gameport.id.product = pdev->device;
+ gameport_set_name(port, "EMU10K1");
+ gameport_set_phys(port, "pci%s/gameport0", pci_name(pdev));
+ port->dev.parent = &pdev->dev;
+ port->io = ioport;
pci_set_drvdata(pdev, emu);
- gameport_register_port(&emu->gameport);
-
- printk(KERN_INFO "gameport: pci%s speed %d kHz\n",
- pci_name(pdev), emu->gameport.speed);
+ gameport_register_port(port);
return 0;
}
@@ -106,8 +105,9 @@ static int __devinit emu_probe(struct pci_dev *pdev, const struct pci_device_id
static void __devexit emu_remove(struct pci_dev *pdev)
{
struct emu *emu = pci_get_drvdata(pdev);
- gameport_unregister_port(&emu->gameport);
- release_region(emu->gameport.io, emu->size);
+
+ gameport_unregister_port(emu->gameport);
+ release_region(emu->io, emu->size);
kfree(emu);
}
@@ -118,12 +118,12 @@ static struct pci_driver emu_driver = {
.remove = __devexit_p(emu_remove),
};
-int __init emu_init(void)
+static int __init emu_init(void)
{
- return pci_module_init(&emu_driver);
+ return pci_register_driver(&emu_driver);
}
-void __exit emu_exit(void)
+static void __exit emu_exit(void)
{
pci_unregister_driver(&emu_driver);
}
diff --git a/drivers/input/gameport/fm801-gp.c b/drivers/input/gameport/fm801-gp.c
index ab0a151bd56bc..57615bc639061 100644
--- a/drivers/input/gameport/fm801-gp.c
+++ b/drivers/input/gameport/fm801-gp.c
@@ -37,10 +37,8 @@
#define HAVE_COOKED
struct fm801_gp {
- struct gameport gameport;
+ struct gameport *gameport;
struct resource *res_port;
- char phys[32];
- char name[32];
};
#ifdef HAVE_COOKED
@@ -83,40 +81,42 @@ static int fm801_gp_open(struct gameport *gameport, int mode)
static int __devinit fm801_gp_probe(struct pci_dev *pci, const struct pci_device_id *id)
{
struct fm801_gp *gp;
+ struct gameport *port;
- if (! (gp = kmalloc(sizeof(*gp), GFP_KERNEL))) {
- printk("cannot malloc for fm801-gp\n");
- return -1;
+ gp = kcalloc(1, sizeof(struct fm801_gp), GFP_KERNEL);
+ port = gameport_allocate_port();
+ if (!gp || !port) {
+ printk(KERN_ERR "fm801-gp: Memory allocation failed\n");
+ kfree(gp);
+ gameport_free_port(port);
+ return -ENOMEM;
}
- memset(gp, 0, sizeof(*gp));
- gp->gameport.open = fm801_gp_open;
+ pci_enable_device(pci);
+
+ port->open = fm801_gp_open;
#ifdef HAVE_COOKED
- gp->gameport.cooked_read = fm801_gp_cooked_read;
+ port->cooked_read = fm801_gp_cooked_read;
#endif
-
- pci_enable_device(pci);
- gp->gameport.io = pci_resource_start(pci, 0);
- if ((gp->res_port = request_region(gp->gameport.io, 0x10, "FM801 GP")) == NULL) {
- printk("unable to grab region 0x%x-0x%x\n", gp->gameport.io, gp->gameport.io + 0x0f);
+ gameport_set_name(port, "FM801");
+ gameport_set_phys(port, "pci%s/gameport0", pci_name(pci));
+ port->dev.parent = &pci->dev;
+ port->io = pci_resource_start(pci, 0);
+
+ gp->gameport = port;
+ gp->res_port = request_region(port->io, 0x10, "FM801 GP");
+ if (!gp->res_port) {
kfree(gp);
- return -1;
+ gameport_free_port(port);
+ printk(KERN_DEBUG "fm801-gp: unable to grab region 0x%x-0x%x\n",
+ port->io, port->io + 0x0f);
+ return -EBUSY;
}
- gp->gameport.phys = gp->phys;
- gp->gameport.name = gp->name;
- gp->gameport.id.bustype = BUS_PCI;
- gp->gameport.id.vendor = pci->vendor;
- gp->gameport.id.product = pci->device;
-
pci_set_drvdata(pci, gp);
- outb(0x60, gp->gameport.io + 0x0d); /* enable joystick 1 and 2 */
-
- gameport_register_port(&gp->gameport);
-
- printk(KERN_INFO "gameport: at pci%s speed %d kHz\n",
- pci_name(pci), gp->gameport.speed);
+ outb(0x60, port->io + 0x0d); /* enable joystick 1 and 2 */
+ gameport_register_port(port);
return 0;
}
@@ -124,8 +124,9 @@ static int __devinit fm801_gp_probe(struct pci_dev *pci, const struct pci_device
static void __devexit fm801_gp_remove(struct pci_dev *pci)
{
struct fm801_gp *gp = pci_get_drvdata(pci);
+
if (gp) {
- gameport_unregister_port(&gp->gameport);
+ gameport_unregister_port(gp->gameport);
release_resource(gp->res_port);
kfree(gp);
}
@@ -143,12 +144,12 @@ static struct pci_driver fm801_gp_driver = {
.remove = __devexit_p(fm801_gp_remove),
};
-int __init fm801_gp_init(void)
+static int __init fm801_gp_init(void)
{
- return pci_module_init(&fm801_gp_driver);
+ return pci_register_driver(&fm801_gp_driver);
}
-void __exit fm801_gp_exit(void)
+static void __exit fm801_gp_exit(void)
{
pci_unregister_driver(&fm801_gp_driver);
}
diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c
index b2a68ab2afede..f20c3f23388b9 100644
--- a/drivers/input/gameport/gameport.c
+++ b/drivers/input/gameport/gameport.c
@@ -2,6 +2,7 @@
* Generic gameport layer
*
* Copyright (c) 1999-2002 Vojtech Pavlik
+ * Copyright (c) 2005 Dmitry Torokhov
*/
/*
@@ -10,32 +11,55 @@
* the Free Software Foundation.
*/
-#include <asm/io.h>
+#include <linux/stddef.h>
#include <linux/module.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/gameport.h>
+#include <linux/wait.h>
+#include <linux/completion.h>
+#include <linux/sched.h>
+#include <linux/smp_lock.h>
#include <linux/slab.h>
-#include <linux/stddef.h>
#include <linux/delay.h>
+/*#include <asm/io.h>*/
+
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("Generic gameport layer");
MODULE_LICENSE("GPL");
-EXPORT_SYMBOL(gameport_register_port);
+EXPORT_SYMBOL(__gameport_register_port);
EXPORT_SYMBOL(gameport_unregister_port);
-EXPORT_SYMBOL(gameport_register_device);
-EXPORT_SYMBOL(gameport_unregister_device);
+EXPORT_SYMBOL(__gameport_register_driver);
+EXPORT_SYMBOL(gameport_unregister_driver);
EXPORT_SYMBOL(gameport_open);
EXPORT_SYMBOL(gameport_close);
EXPORT_SYMBOL(gameport_rescan);
EXPORT_SYMBOL(gameport_cooked_read);
+EXPORT_SYMBOL(gameport_set_name);
+EXPORT_SYMBOL(gameport_set_phys);
+EXPORT_SYMBOL(gameport_start_polling);
+EXPORT_SYMBOL(gameport_stop_polling);
+
+/*
+ * gameport_sem protects entire gameport subsystem and is taken
+ * every time gameport port or driver registrered or unregistered.
+ */
+static DECLARE_MUTEX(gameport_sem);
static LIST_HEAD(gameport_list);
-static LIST_HEAD(gameport_dev_list);
-#ifdef __i386__
+static struct bus_type gameport_bus = {
+ .name = "gameport",
+};
+
+static void gameport_add_port(struct gameport *gameport);
+static void gameport_destroy_port(struct gameport *gameport);
+static void gameport_reconnect_port(struct gameport *gameport);
+static void gameport_disconnect_port(struct gameport *gameport);
+
+#if defined(__i386__)
#define DELTA(x,y) ((y)-(x)+((y)<(x)?1193182/HZ:0))
#define GET_TIME(x) do { x = get_time_pit(); } while (0)
@@ -57,13 +81,15 @@ static unsigned int get_time_pit(void)
#endif
+
+
/*
* gameport_measure_speed() measures the gameport i/o speed.
*/
static int gameport_measure_speed(struct gameport *gameport)
{
-#ifdef __i386__
+#if defined(__i386__)
unsigned int i, t, t1, t2, t3, tx;
unsigned long flags;
@@ -76,7 +102,7 @@ static int gameport_measure_speed(struct gameport *gameport)
for(i = 0; i < 50; i++) {
local_irq_save(flags);
GET_TIME(t1);
- for(t = 0; t < 50; t++) gameport_read(gameport);
+ for (t = 0; t < 50; t++) gameport_read(gameport);
GET_TIME(t2);
GET_TIME(t3);
local_irq_restore(flags);
@@ -87,10 +113,36 @@ static int gameport_measure_speed(struct gameport *gameport)
gameport_close(gameport);
return 59659 / (tx < 1 ? 1 : tx);
+#elif defined (__x86_64__)
+
+ unsigned int i, t;
+ unsigned long tx, t1, t2, flags;
+
+ if (gameport_open(gameport, NULL, GAMEPORT_MODE_RAW))
+ return 0;
+
+ tx = 1 << 30;
+
+ for(i = 0; i < 50; i++) {
+ local_irq_save(flags);
+ rdtscl(t1);
+ for (t = 0; t < 50; t++) gameport_read(gameport);
+ rdtscl(t2);
+ local_irq_restore(flags);
+ udelay(i * 10);
+ if (t2 - t1 < tx) tx = t2 - t1;
+ }
+
+ gameport_close(gameport);
+ return (cpu_data[_smp_processor_id()].loops_per_jiffy * (unsigned long)HZ / (1000 / 50)) / (tx < 1 ? 1 : tx);
+
#else
unsigned int j, t = 0;
+ if (gameport_open(gameport, NULL, GAMEPORT_MODE_RAW))
+ return 0;
+
j = jiffies; while (j == jiffies);
j = jiffies; while (j == jiffies) { t++; gameport_read(gameport); }
@@ -100,81 +152,646 @@ static int gameport_measure_speed(struct gameport *gameport)
#endif
}
-static void gameport_find_dev(struct gameport *gameport)
+void gameport_start_polling(struct gameport *gameport)
{
- struct gameport_dev *dev;
+ spin_lock(&gameport->timer_lock);
- list_for_each_entry(dev, &gameport_dev_list, node) {
- if (gameport->dev)
+ if (!gameport->poll_cnt++) {
+ BUG_ON(!gameport->poll_handler);
+ BUG_ON(!gameport->poll_interval);
+ mod_timer(&gameport->poll_timer, jiffies + msecs_to_jiffies(gameport->poll_interval));
+ }
+
+ spin_unlock(&gameport->timer_lock);
+}
+
+void gameport_stop_polling(struct gameport *gameport)
+{
+ spin_lock(&gameport->timer_lock);
+
+ if (!--gameport->poll_cnt)
+ del_timer(&gameport->poll_timer);
+
+ spin_unlock(&gameport->timer_lock);
+}
+
+static void gameport_run_poll_handler(unsigned long d)
+{
+ struct gameport *gameport = (struct gameport *)d;
+
+ gameport->poll_handler(gameport);
+ if (gameport->poll_cnt)
+ mod_timer(&gameport->poll_timer, jiffies + msecs_to_jiffies(gameport->poll_interval));
+}
+
+/*
+ * Basic gameport -> driver core mappings
+ */
+
+static void gameport_bind_driver(struct gameport *gameport, struct gameport_driver *drv)
+{
+ down_write(&gameport_bus.subsys.rwsem);
+
+ gameport->dev.driver = &drv->driver;
+ if (drv->connect(gameport, drv)) {
+ gameport->dev.driver = NULL;
+ goto out;
+ }
+ device_bind_driver(&gameport->dev);
+out:
+ up_write(&gameport_bus.subsys.rwsem);
+}
+
+static void gameport_release_driver(struct gameport *gameport)
+{
+ down_write(&gameport_bus.subsys.rwsem);
+ device_release_driver(&gameport->dev);
+ up_write(&gameport_bus.subsys.rwsem);
+}
+
+static void gameport_find_driver(struct gameport *gameport)
+{
+ down_write(&gameport_bus.subsys.rwsem);
+ device_attach(&gameport->dev);
+ up_write(&gameport_bus.subsys.rwsem);
+}
+
+
+/*
+ * Gameport event processing.
+ */
+
+enum gameport_event_type {
+ GAMEPORT_RESCAN,
+ GAMEPORT_RECONNECT,
+ GAMEPORT_REGISTER_PORT,
+ GAMEPORT_REGISTER_DRIVER,
+};
+
+struct gameport_event {
+ enum gameport_event_type type;
+ void *object;
+ struct module *owner;
+ struct list_head node;
+};
+
+static DEFINE_SPINLOCK(gameport_event_lock); /* protects gameport_event_list */
+static LIST_HEAD(gameport_event_list);
+static DECLARE_WAIT_QUEUE_HEAD(gameport_wait);
+static DECLARE_COMPLETION(gameport_exited);
+static int gameport_pid;
+
+static void gameport_queue_event(void *object, struct module *owner,
+ enum gameport_event_type event_type)
+{
+ unsigned long flags;
+ struct gameport_event *event;
+
+ spin_lock_irqsave(&gameport_event_lock, flags);
+
+ /*
+ * Scan event list for the other events for the same gameport port,
+ * starting with the most recent one. If event is the same we
+ * do not need add new one. If event is of different type we
+ * need to add this event and should not look further because
+ * we need to preseve sequence of distinct events.
+ */
+ list_for_each_entry_reverse(event, &gameport_event_list, node) {
+ if (event->object == object) {
+ if (event->type == event_type)
+ goto out;
break;
- if (dev->connect)
- dev->connect(gameport, dev);
- }
+ }
+ }
+
+ if ((event = kmalloc(sizeof(struct gameport_event), GFP_ATOMIC))) {
+ if (!try_module_get(owner)) {
+ printk(KERN_WARNING "gameport: Can't get module reference, dropping event %d\n", event_type);
+ goto out;
+ }
+
+ event->type = event_type;
+ event->object = object;
+ event->owner = owner;
+
+ list_add_tail(&event->node, &gameport_event_list);
+ wake_up(&gameport_wait);
+ } else {
+ printk(KERN_ERR "gameport: Not enough memory to queue event %d\n", event_type);
+ }
+out:
+ spin_unlock_irqrestore(&gameport_event_lock, flags);
}
-void gameport_rescan(struct gameport *gameport)
+static void gameport_free_event(struct gameport_event *event)
{
- gameport_close(gameport);
- gameport_find_dev(gameport);
+ module_put(event->owner);
+ kfree(event);
}
-void gameport_register_port(struct gameport *gameport)
+static void gameport_remove_duplicate_events(struct gameport_event *event)
{
- list_add_tail(&gameport->node, &gameport_list);
+ struct list_head *node, *next;
+ struct gameport_event *e;
+ unsigned long flags;
+
+ spin_lock_irqsave(&gameport_event_lock, flags);
+
+ list_for_each_safe(node, next, &gameport_event_list) {
+ e = list_entry(node, struct gameport_event, node);
+ if (event->object == e->object) {
+ /*
+ * If this event is of different type we should not
+ * look further - we only suppress duplicate events
+ * that were sent back-to-back.
+ */
+ if (event->type != e->type)
+ break;
+
+ list_del_init(node);
+ gameport_free_event(e);
+ }
+ }
+
+ spin_unlock_irqrestore(&gameport_event_lock, flags);
+}
+
+
+static struct gameport_event *gameport_get_event(void)
+{
+ struct gameport_event *event;
+ struct list_head *node;
+ unsigned long flags;
+
+ spin_lock_irqsave(&gameport_event_lock, flags);
+
+ if (list_empty(&gameport_event_list)) {
+ spin_unlock_irqrestore(&gameport_event_lock, flags);
+ return NULL;
+ }
+
+ node = gameport_event_list.next;
+ event = list_entry(node, struct gameport_event, node);
+ list_del_init(node);
+
+ spin_unlock_irqrestore(&gameport_event_lock, flags);
+
+ return event;
+}
+
+static void gameport_handle_events(void)
+{
+ struct gameport_event *event;
+ struct gameport_driver *gameport_drv;
+
+ down(&gameport_sem);
+
+ while ((event = gameport_get_event())) {
+
+ switch (event->type) {
+ case GAMEPORT_REGISTER_PORT:
+ gameport_add_port(event->object);
+ break;
+
+ case GAMEPORT_RECONNECT:
+ gameport_reconnect_port(event->object);
+ break;
+
+ case GAMEPORT_RESCAN:
+ gameport_disconnect_port(event->object);
+ gameport_find_driver(event->object);
+ break;
+
+ case GAMEPORT_REGISTER_DRIVER:
+ gameport_drv = event->object;
+ driver_register(&gameport_drv->driver);
+ break;
+
+ default:
+ break;
+ }
+
+ gameport_remove_duplicate_events(event);
+ gameport_free_event(event);
+ }
+
+ up(&gameport_sem);
+}
+
+/*
+ * Remove all events that have been submitted for a given gameport port.
+ */
+static void gameport_remove_pending_events(struct gameport *gameport)
+{
+ struct list_head *node, *next;
+ struct gameport_event *event;
+ unsigned long flags;
+
+ spin_lock_irqsave(&gameport_event_lock, flags);
+
+ list_for_each_safe(node, next, &gameport_event_list) {
+ event = list_entry(node, struct gameport_event, node);
+ if (event->object == gameport) {
+ list_del_init(node);
+ gameport_free_event(event);
+ }
+ }
+
+ spin_unlock_irqrestore(&gameport_event_lock, flags);
+}
+
+/*
+ * Destroy child gameport port (if any) that has not been fully registered yet.
+ *
+ * Note that we rely on the fact that port can have only one child and therefore
+ * only one child registration request can be pending. Additionally, children
+ * are registered by driver's connect() handler so there can't be a grandchild
+ * pending registration together with a child.
+ */
+static struct gameport *gameport_get_pending_child(struct gameport *parent)
+{
+ struct gameport_event *event;
+ struct gameport *gameport, *child = NULL;
+ unsigned long flags;
+
+ spin_lock_irqsave(&gameport_event_lock, flags);
+
+ list_for_each_entry(event, &gameport_event_list, node) {
+ if (event->type == GAMEPORT_REGISTER_PORT) {
+ gameport = event->object;
+ if (gameport->parent == parent) {
+ child = gameport;
+ break;
+ }
+ }
+ }
+
+ spin_unlock_irqrestore(&gameport_event_lock, flags);
+ return child;
+}
+
+static int gameport_thread(void *nothing)
+{
+ lock_kernel();
+ daemonize("kgameportd");
+ allow_signal(SIGTERM);
+
+ do {
+ gameport_handle_events();
+ wait_event_interruptible(gameport_wait, !list_empty(&gameport_event_list));
+ try_to_freeze(PF_FREEZE);
+ } while (!signal_pending(current));
+
+ printk(KERN_DEBUG "gameport: kgameportd exiting\n");
+
+ unlock_kernel();
+ complete_and_exit(&gameport_exited, 0);
+}
+
+
+/*
+ * Gameport port operations
+ */
+
+static ssize_t gameport_show_description(struct device *dev, char *buf)
+{
+ struct gameport *gameport = to_gameport_port(dev);
+ return sprintf(buf, "%s\n", gameport->name);
+}
+
+static ssize_t gameport_rebind_driver(struct device *dev, const char *buf, size_t count)
+{
+ struct gameport *gameport = to_gameport_port(dev);
+ struct device_driver *drv;
+ int retval;
+
+ retval = down_interruptible(&gameport_sem);
+ if (retval)
+ return retval;
+
+ retval = count;
+ if (!strncmp(buf, "none", count)) {
+ gameport_disconnect_port(gameport);
+ } else if (!strncmp(buf, "reconnect", count)) {
+ gameport_reconnect_port(gameport);
+ } else if (!strncmp(buf, "rescan", count)) {
+ gameport_disconnect_port(gameport);
+ gameport_find_driver(gameport);
+ } else if ((drv = driver_find(buf, &gameport_bus)) != NULL) {
+ gameport_disconnect_port(gameport);
+ gameport_bind_driver(gameport, to_gameport_driver(drv));
+ put_driver(drv);
+ } else {
+ retval = -EINVAL;
+ }
+
+ up(&gameport_sem);
+
+ return retval;
+}
+
+static struct device_attribute gameport_device_attrs[] = {
+ __ATTR(description, S_IRUGO, gameport_show_description, NULL),
+ __ATTR(drvctl, S_IWUSR, NULL, gameport_rebind_driver),
+ __ATTR_NULL
+};
+
+static void gameport_release_port(struct device *dev)
+{
+ struct gameport *gameport = to_gameport_port(dev);
+
+ kfree(gameport);
+ module_put(THIS_MODULE);
+}
+
+void gameport_set_phys(struct gameport *gameport, const char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ vsnprintf(gameport->phys, sizeof(gameport->phys), fmt, args);
+ va_end(args);
+}
+
+/*
+ * Prepare gameport port for registration.
+ */
+static void gameport_init_port(struct gameport *gameport)
+{
+ static atomic_t gameport_no = ATOMIC_INIT(0);
+
+ __module_get(THIS_MODULE);
+
+ init_MUTEX(&gameport->drv_sem);
+ device_initialize(&gameport->dev);
+ snprintf(gameport->dev.bus_id, sizeof(gameport->dev.bus_id),
+ "gameport%lu", (unsigned long)atomic_inc_return(&gameport_no) - 1);
+ gameport->dev.bus = &gameport_bus;
+ gameport->dev.release = gameport_release_port;
+ if (gameport->parent)
+ gameport->dev.parent = &gameport->parent->dev;
+
+ spin_lock_init(&gameport->timer_lock);
+ init_timer(&gameport->poll_timer);
+ gameport->poll_timer.function = gameport_run_poll_handler;
+ gameport->poll_timer.data = (unsigned long)gameport;
+}
+
+/*
+ * Complete gameport port registration.
+ * Driver core will attempt to find appropriate driver for the port.
+ */
+static void gameport_add_port(struct gameport *gameport)
+{
+ if (gameport->parent)
+ gameport->parent->child = gameport;
+
gameport->speed = gameport_measure_speed(gameport);
- gameport_find_dev(gameport);
+
+ list_add_tail(&gameport->node, &gameport_list);
+
+ if (gameport->io)
+ printk(KERN_INFO "gameport: %s is %s, io %#x, speed %dkHz\n",
+ gameport->name, gameport->phys, gameport->io, gameport->speed);
+ else
+ printk(KERN_INFO "gameport: %s is %s, speed %dkHz\n",
+ gameport->name, gameport->phys, gameport->speed);
+
+ device_add(&gameport->dev);
+ gameport->registered = 1;
+}
+
+/*
+ * gameport_destroy_port() completes deregistration process and removes
+ * port from the system
+ */
+static void gameport_destroy_port(struct gameport *gameport)
+{
+ struct gameport *child;
+
+ child = gameport_get_pending_child(gameport);
+ if (child) {
+ gameport_remove_pending_events(child);
+ put_device(&child->dev);
+ }
+
+ if (gameport->parent) {
+ gameport->parent->child = NULL;
+ gameport->parent = NULL;
+ }
+
+ if (gameport->registered) {
+ device_del(&gameport->dev);
+ list_del_init(&gameport->node);
+ gameport->registered = 0;
+ }
+
+ gameport_remove_pending_events(gameport);
+ put_device(&gameport->dev);
+}
+
+/*
+ * Reconnect gameport port and all its children (re-initialize attached devices)
+ */
+static void gameport_reconnect_port(struct gameport *gameport)
+{
+ do {
+ if (!gameport->drv || !gameport->drv->reconnect || gameport->drv->reconnect(gameport)) {
+ gameport_disconnect_port(gameport);
+ gameport_find_driver(gameport);
+ /* Ok, old children are now gone, we are done */
+ break;
+ }
+ gameport = gameport->child;
+ } while (gameport);
+}
+
+/*
+ * gameport_disconnect_port() unbinds a port from its driver. As a side effect
+ * all child ports are unbound and destroyed.
+ */
+static void gameport_disconnect_port(struct gameport *gameport)
+{
+ struct gameport *s, *parent;
+
+ if (gameport->child) {
+ /*
+ * Children ports should be disconnected and destroyed
+ * first, staring with the leaf one, since we don't want
+ * to do recursion
+ */
+ for (s = gameport; s->child; s = s->child)
+ /* empty */;
+
+ do {
+ parent = s->parent;
+
+ gameport_release_driver(s);
+ gameport_destroy_port(s);
+ } while ((s = parent) != gameport);
+ }
+
+ /*
+ * Ok, no children left, now disconnect this port
+ */
+ gameport_release_driver(gameport);
+}
+
+void gameport_rescan(struct gameport *gameport)
+{
+ gameport_queue_event(gameport, NULL, GAMEPORT_RESCAN);
+}
+
+void gameport_reconnect(struct gameport *gameport)
+{
+ gameport_queue_event(gameport, NULL, GAMEPORT_RECONNECT);
}
+/*
+ * Submits register request to kgameportd for subsequent execution.
+ * Note that port registration is always asynchronous.
+ */
+void __gameport_register_port(struct gameport *gameport, struct module *owner)
+{
+ gameport_init_port(gameport);
+ gameport_queue_event(gameport, owner, GAMEPORT_REGISTER_PORT);
+}
+
+/*
+ * Synchronously unregisters gameport port.
+ */
void gameport_unregister_port(struct gameport *gameport)
{
- list_del_init(&gameport->node);
- if (gameport->dev && gameport->dev->disconnect)
- gameport->dev->disconnect(gameport);
+ down(&gameport_sem);
+ gameport_disconnect_port(gameport);
+ gameport_destroy_port(gameport);
+ up(&gameport_sem);
}
-void gameport_register_device(struct gameport_dev *dev)
+
+/*
+ * Gameport driver operations
+ */
+
+static ssize_t gameport_driver_show_description(struct device_driver *drv, char *buf)
{
- struct gameport *gameport;
+ struct gameport_driver *driver = to_gameport_driver(drv);
+ return sprintf(buf, "%s\n", driver->description ? driver->description : "(none)");
+}
+
+static struct driver_attribute gameport_driver_attrs[] = {
+ __ATTR(description, S_IRUGO, gameport_driver_show_description, NULL),
+ __ATTR_NULL
+};
+
+static int gameport_driver_probe(struct device *dev)
+{
+ struct gameport *gameport = to_gameport_port(dev);
+ struct gameport_driver *drv = to_gameport_driver(dev->driver);
- list_add_tail(&dev->node, &gameport_dev_list);
- list_for_each_entry(gameport, &gameport_list, node)
- if (!gameport->dev && dev->connect)
- dev->connect(gameport, dev);
+ drv->connect(gameport, drv);
+ return gameport->drv ? 0 : -ENODEV;
}
-void gameport_unregister_device(struct gameport_dev *dev)
+static int gameport_driver_remove(struct device *dev)
+{
+ struct gameport *gameport = to_gameport_port(dev);
+ struct gameport_driver *drv = to_gameport_driver(dev->driver);
+
+ drv->disconnect(gameport);
+ return 0;
+}
+
+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);
+}
+
+void gameport_unregister_driver(struct gameport_driver *drv)
{
struct gameport *gameport;
- list_del_init(&dev->node);
+ down(&gameport_sem);
+ drv->ignore = 1; /* so gameport_find_driver ignores it */
+
+start_over:
list_for_each_entry(gameport, &gameport_list, node) {
- if (gameport->dev == dev && dev->disconnect)
- dev->disconnect(gameport);
- gameport_find_dev(gameport);
+ if (gameport->drv == drv) {
+ gameport_disconnect_port(gameport);
+ gameport_find_driver(gameport);
+ /* we could've deleted some ports, restart */
+ goto start_over;
+ }
}
+
+ driver_unregister(&drv->driver);
+ up(&gameport_sem);
}
-int gameport_open(struct gameport *gameport, struct gameport_dev *dev, int mode)
+static int gameport_bus_match(struct device *dev, struct device_driver *drv)
{
+ struct gameport_driver *gameport_drv = to_gameport_driver(drv);
+
+ return !gameport_drv->ignore;
+}
+
+static void gameport_set_drv(struct gameport *gameport, struct gameport_driver *drv)
+{
+ down(&gameport->drv_sem);
+ gameport->drv = drv;
+ up(&gameport->drv_sem);
+}
+
+int gameport_open(struct gameport *gameport, struct gameport_driver *drv, int mode)
+{
+
if (gameport->open) {
- if (gameport->open(gameport, mode))
+ if (gameport->open(gameport, mode)) {
return -1;
+ }
} else {
if (mode != GAMEPORT_MODE_RAW)
return -1;
}
- if (gameport->dev)
- return -1;
-
- gameport->dev = dev;
-
+ gameport_set_drv(gameport, drv);
return 0;
}
void gameport_close(struct gameport *gameport)
{
- gameport->dev = NULL;
+ del_timer_sync(&gameport->poll_timer);
+ gameport->poll_handler = NULL;
+ gameport->poll_interval = 0;
+ gameport_set_drv(gameport, NULL);
if (gameport->close)
gameport->close(gameport);
}
+
+static int __init gameport_init(void)
+{
+ if (!(gameport_pid = kernel_thread(gameport_thread, NULL, CLONE_KERNEL))) {
+ printk(KERN_ERR "gameport: Failed to start kgameportd\n");
+ return -1;
+ }
+
+ gameport_bus.dev_attrs = gameport_device_attrs;
+ gameport_bus.drv_attrs = gameport_driver_attrs;
+ gameport_bus.match = gameport_bus_match;
+ bus_register(&gameport_bus);
+
+ return 0;
+}
+
+static void __exit gameport_exit(void)
+{
+ bus_unregister(&gameport_bus);
+ kill_proc(gameport_pid, SIGTERM, 1);
+ wait_for_completion(&gameport_exited);
+}
+
+module_init(gameport_init);
+module_exit(gameport_exit);
diff --git a/drivers/input/gameport/lightning.c b/drivers/input/gameport/lightning.c
index 7d1d3832cb3a3..d65d81080257e 100644
--- a/drivers/input/gameport/lightning.c
+++ b/drivers/input/gameport/lightning.c
@@ -54,12 +54,11 @@ MODULE_DESCRIPTION("PDPI Lightning 4 gamecard driver");
MODULE_LICENSE("GPL");
struct l4 {
- struct gameport gameport;
+ struct gameport *gameport;
unsigned char port;
- char phys[32];
-} *l4_port[8];
+};
-char l4_name[] = "PDPI Lightning 4";
+static struct l4 l4_ports[8];
/*
* l4_wait_ready() waits for the L4 to become ready.
@@ -67,10 +66,10 @@ char l4_name[] = "PDPI Lightning 4";
static int l4_wait_ready(void)
{
- unsigned int t;
- t = L4_TIMEOUT;
+ unsigned int t = L4_TIMEOUT;
+
while ((inb(L4_PORT) & L4_BUSY) && t > 0) t--;
- return -(t<=0);
+ return -(t <= 0);
}
/*
@@ -79,7 +78,7 @@ static int l4_wait_ready(void)
static int l4_cooked_read(struct gameport *gameport, int *axes, int *buttons)
{
- struct l4 *l4 = gameport->driver;
+ struct l4 *l4 = gameport->port_data;
unsigned char status;
int i, result = -1;
@@ -112,7 +111,8 @@ fail: outb(L4_SELECT_ANALOG, L4_PORT);
static int l4_open(struct gameport *gameport, int mode)
{
- struct l4 *l4 = gameport->driver;
+ struct l4 *l4 = gameport->port_data;
+
if (l4->port != 0 && mode != GAMEPORT_MODE_COOKED)
return -1;
outb(L4_SELECT_ANALOG, L4_PORT);
@@ -129,24 +129,29 @@ static int l4_getcal(int port, int *cal)
outb(L4_SELECT_ANALOG, L4_PORT);
outb(L4_SELECT_DIGITAL + (port >> 2), L4_PORT);
+ if (inb(L4_PORT) & L4_BUSY)
+ goto out;
- if (inb(L4_PORT) & L4_BUSY) goto fail;
outb(L4_CMD_GETCAL, L4_PORT);
+ if (l4_wait_ready())
+ goto out;
- if (l4_wait_ready()) goto fail;
- if (inb(L4_PORT) != L4_SELECT_DIGITAL + (port >> 2)) goto fail;
+ if (inb(L4_PORT) != L4_SELECT_DIGITAL + (port >> 2))
+ goto out;
- if (l4_wait_ready()) goto fail;
+ if (l4_wait_ready())
+ goto out;
outb(port & 3, L4_PORT);
for (i = 0; i < 4; i++) {
- if (l4_wait_ready()) goto fail;
+ if (l4_wait_ready())
+ goto out;
cal[i] = inb(L4_PORT);
}
result = 0;
-fail: outb(L4_SELECT_ANALOG, L4_PORT);
+out: outb(L4_SELECT_ANALOG, L4_PORT);
return result;
}
@@ -160,24 +165,29 @@ static int l4_setcal(int port, int *cal)
outb(L4_SELECT_ANALOG, L4_PORT);
outb(L4_SELECT_DIGITAL + (port >> 2), L4_PORT);
+ if (inb(L4_PORT) & L4_BUSY)
+ goto out;
- if (inb(L4_PORT) & L4_BUSY) goto fail;
outb(L4_CMD_SETCAL, L4_PORT);
+ if (l4_wait_ready())
+ goto out;
- if (l4_wait_ready()) goto fail;
- if (inb(L4_PORT) != L4_SELECT_DIGITAL + (port >> 2)) goto fail;
+ if (inb(L4_PORT) != L4_SELECT_DIGITAL + (port >> 2))
+ goto out;
- if (l4_wait_ready()) goto fail;
+ if (l4_wait_ready())
+ goto out;
outb(port & 3, L4_PORT);
for (i = 0; i < 4; i++) {
- if (l4_wait_ready()) goto fail;
+ if (l4_wait_ready())
+ goto out;
outb(cal[i], L4_PORT);
}
result = 0;
-fail: outb(L4_SELECT_ANALOG, L4_PORT);
+out: outb(L4_SELECT_ANALOG, L4_PORT);
return result;
}
@@ -190,7 +200,7 @@ static int l4_calibrate(struct gameport *gameport, int *axes, int *max)
{
int i, t;
int cal[4];
- struct l4 *l4 = gameport->driver;
+ struct l4 *l4 = gameport->port_data;
if (l4_getcal(l4->port, cal))
return -1;
@@ -209,73 +219,102 @@ static int l4_calibrate(struct gameport *gameport, int *axes, int *max)
return 0;
}
-static int __init l4_init(void)
+static int __init l4_create_ports(int card_no)
{
- int cal[4] = {255,255,255,255};
- int i, j, rev, cards = 0;
- struct gameport *gameport;
struct l4 *l4;
+ struct gameport *port;
+ int i, idx;
- if (!request_region(L4_PORT, 1, "lightning"))
- return -1;
+ for (i = 0; i < 4; i++) {
- for (i = 0; i < 2; i++) {
+ idx = card_no * 4 + i;
+ l4 = &l4_ports[idx];
- outb(L4_SELECT_ANALOG, L4_PORT);
- outb(L4_SELECT_DIGITAL + i, L4_PORT);
+ if (!(l4->gameport = port = gameport_allocate_port())) {
+ printk(KERN_ERR "lightning: Memory allocation failed\n");
+ while (--i >= 0) {
+ gameport_free_port(l4->gameport);
+ l4->gameport = NULL;
+ }
+ return -ENOMEM;
+ }
+ l4->port = idx;
- if (inb(L4_PORT) & L4_BUSY) continue;
- outb(L4_CMD_ID, L4_PORT);
+ port->port_data = l4;
+ port->open = l4_open;
+ port->cooked_read = l4_cooked_read;
+ port->calibrate = l4_calibrate;
- if (l4_wait_ready()) continue;
- if (inb(L4_PORT) != L4_SELECT_DIGITAL + i) continue;
+ gameport_set_name(port, "PDPI Lightning 4");
+ gameport_set_phys(port, "isa%04x/gameport%d", L4_PORT, idx);
- if (l4_wait_ready()) continue;
- if (inb(L4_PORT) != L4_ID) continue;
+ if (idx == 0)
+ port->io = L4_PORT;
+ }
- if (l4_wait_ready()) continue;
- rev = inb(L4_PORT);
+ return 0;
+}
- if (!rev) continue;
+static int __init l4_add_card(int card_no)
+{
+ int cal[4] = { 255, 255, 255, 255 };
+ int i, rev, result;
+ struct l4 *l4;
- if (!(l4_port[i * 4] = kmalloc(sizeof(struct l4) * 4, GFP_KERNEL))) {
- printk(KERN_ERR "lightning: Out of memory allocating ports.\n");
- continue;
- }
- memset(l4_port[i * 4], 0, sizeof(struct l4) * 4);
+ outb(L4_SELECT_ANALOG, L4_PORT);
+ outb(L4_SELECT_DIGITAL + card_no, L4_PORT);
- for (j = 0; j < 4; j++) {
+ if (inb(L4_PORT) & L4_BUSY)
+ return -1;
+ outb(L4_CMD_ID, L4_PORT);
- l4 = l4_port[i * 4 + j] = l4_port[i * 4] + j;
- l4->port = i * 4 + j;
+ if (l4_wait_ready())
+ return -1;
- sprintf(l4->phys, "isa%04x/gameport%d", L4_PORT, 4 * i + j);
+ if (inb(L4_PORT) != L4_SELECT_DIGITAL + card_no)
+ return -1;
- gameport = &l4->gameport;
- gameport->driver = l4;
- gameport->open = l4_open;
- gameport->cooked_read = l4_cooked_read;
- gameport->calibrate = l4_calibrate;
+ if (l4_wait_ready())
+ return -1;
+ if (inb(L4_PORT) != L4_ID)
+ return -1;
- gameport->name = l4_name;
- gameport->phys = l4->phys;
- gameport->id.bustype = BUS_ISA;
+ if (l4_wait_ready())
+ return -1;
+ rev = inb(L4_PORT);
- if (!i && !j)
- gameport->io = L4_PORT;
+ if (!rev)
+ return -1;
- if (rev > 0x28) /* on 2.9+ the setcal command works correctly */
- l4_setcal(l4->port, cal);
+ result = l4_create_ports(card_no);
+ if (result)
+ return result;
- gameport_register_port(gameport);
- }
+ printk(KERN_INFO "gameport: PDPI Lightning 4 %s card v%d.%d at %#x\n",
+ card_no ? "secondary" : "primary", rev >> 4, rev, L4_PORT);
- printk(KERN_INFO "gameport: PDPI Lightning 4 %s card v%d.%d at %#x\n",
- i ? "secondary" : "primary", rev >> 4, rev, L4_PORT);
+ for (i = 0; i < 4; i++) {
+ l4 = &l4_ports[card_no * 4 + i];
- cards++;
+ if (rev > 0x28) /* on 2.9+ the setcal command works correctly */
+ l4_setcal(l4->port, cal);
+ gameport_register_port(l4->gameport);
}
+ return 0;
+}
+
+static int __init l4_init(void)
+{
+ int i, cards = 0;
+
+ if (!request_region(L4_PORT, 1, "lightning"))
+ return -1;
+
+ for (i = 0; i < 2; i++)
+ if (l4_add_card(i) == 0)
+ cards++;
+
outb(L4_SELECT_ANALOG, L4_PORT);
if (!cards) {
@@ -289,13 +328,14 @@ static int __init l4_init(void)
static void __exit l4_exit(void)
{
int i;
- int cal[4] = {59, 59, 59, 59};
+ int cal[4] = { 59, 59, 59, 59 };
for (i = 0; i < 8; i++)
- if (l4_port[i]) {
- l4_setcal(l4_port[i]->port, cal);
- gameport_unregister_port(&l4_port[i]->gameport);
+ if (l4_ports[i].gameport) {
+ l4_setcal(l4_ports[i].port, cal);
+ gameport_unregister_port(l4_ports[i].gameport);
}
+
outb(L4_SELECT_ANALOG, L4_PORT);
release_region(L4_PORT, 1);
}
diff --git a/drivers/input/gameport/ns558.c b/drivers/input/gameport/ns558.c
index f31ce0bad5794..7c5c6318eeb9f 100644
--- a/drivers/input/gameport/ns558.c
+++ b/drivers/input/gameport/ns558.c
@@ -44,20 +44,16 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("Classic gameport (ISA/PnP) driver");
MODULE_LICENSE("GPL");
-#define NS558_ISA 1
-#define NS558_PNP 2
-
static int ns558_isa_portlist[] = { 0x201, 0x200, 0x202, 0x203, 0x204, 0x205, 0x207, 0x209,
0x20b, 0x20c, 0x20e, 0x20f, 0x211, 0x219, 0x101, 0 };
struct ns558 {
int type;
+ int io;
int size;
struct pnp_dev *dev;
+ struct gameport *gameport;
struct list_head node;
- struct gameport gameport;
- char phys[32];
- char name[32];
};
static LIST_HEAD(ns558_list);
@@ -68,18 +64,19 @@ static LIST_HEAD(ns558_list);
* A joystick must be attached for this to work.
*/
-static void ns558_isa_probe(int io)
+static int ns558_isa_probe(int io)
{
int i, j, b;
unsigned char c, u, v;
- struct ns558 *port;
+ struct ns558 *ns558;
+ struct gameport *port;
/*
* No one should be using this address.
*/
if (!request_region(io, 1, "ns558-isa"))
- return;
+ return -EBUSY;
/*
* We must not be able to write arbitrary values to the port.
@@ -90,8 +87,8 @@ static void ns558_isa_probe(int io)
outb(~c & ~3, io);
if (~(u = v = inb(io)) & 3) {
outb(c, io);
- i = 0;
- goto out;
+ release_region(io, 1);
+ return -ENODEV;
}
/*
* After a trigger, there must be at least some bits changing.
@@ -101,8 +98,8 @@ static void ns558_isa_probe(int io)
if (u == v) {
outb(c, io);
- i = 0;
- goto out;
+ release_region(io, 1);
+ return -ENODEV;
}
msleep(3);
/*
@@ -113,8 +110,8 @@ static void ns558_isa_probe(int io)
for (i = 0; i < 1000; i++)
if ((u ^ inb(io)) & 0xf) {
outb(c, io);
- i = 0;
- goto out;
+ release_region(io, 1);
+ return -ENODEV;
}
/*
* And now find the number of mirrors of the port.
@@ -122,17 +119,17 @@ static void ns558_isa_probe(int io)
for (i = 1; i < 5; i++) {
- release_region(io & (-1 << (i-1)), (1 << (i-1)));
+ release_region(io & (-1 << (i - 1)), (1 << (i - 1)));
- if (!request_region(io & (-1 << i), (1 << i), "ns558-isa")) /* Don't disturb anyone */
- break;
+ if (!request_region(io & (-1 << i), (1 << i), "ns558-isa"))
+ break; /* Don't disturb anyone */
outb(0xff, io & (-1 << i));
for (j = b = 0; j < 1000; j++)
if (inb(io & (-1 << i)) != inb((io & (-1 << i)) + (1 << i) - 1)) b++;
msleep(3);
- if (b > 300) { /* We allow 30% difference */
+ if (b > 300) { /* We allow 30% difference */
release_region(io & (-1 << i), (1 << i));
break;
}
@@ -142,35 +139,33 @@ static void ns558_isa_probe(int io)
if (i != 4) {
if (!request_region(io & (-1 << i), (1 << i), "ns558-isa"))
- return;
+ return -EBUSY;
}
- if (!(port = kmalloc(sizeof(struct ns558), GFP_KERNEL))) {
+ ns558 = kcalloc(1, sizeof(struct ns558), GFP_KERNEL);
+ port = gameport_allocate_port();
+ if (!ns558 || !port) {
printk(KERN_ERR "ns558: Memory allocation failed.\n");
- goto out;
+ release_region(io & (-1 << i), (1 << i));
+ kfree(ns558);
+ gameport_free_port(port);
+ return -ENOMEM;
}
- memset(port, 0, sizeof(struct ns558));
- port->type = NS558_ISA;
- port->size = (1 << i);
- port->gameport.io = io;
- port->gameport.phys = port->phys;
- port->gameport.name = port->name;
- port->gameport.id.bustype = BUS_ISA;
+ memset(ns558, 0, sizeof(struct ns558));
+ ns558->io = io;
+ ns558->size = 1 << i;
+ ns558->gameport = port;
- sprintf(port->phys, "isa%04x/gameport0", io & (-1 << i));
- sprintf(port->name, "NS558 ISA");
+ port->io = io;
+ gameport_set_name(port, "NS558 ISA Gameport");
+ gameport_set_phys(port, "isa%04x/gameport0", io & (-1 << i));
- gameport_register_port(&port->gameport);
+ gameport_register_port(port);
- printk(KERN_INFO "gameport: NS558 ISA at %#x", port->gameport.io);
- if (port->size > 1) printk(" size %d", port->size);
- printk(" speed %d kHz\n", port->gameport.speed);
+ list_add(&ns558->node, &ns558_list);
- list_add(&port->node, &ns558_list);
- return;
-out:
- release_region(io & (-1 << i), (1 << i));
+ return 0;
}
#ifdef CONFIG_PNP
@@ -206,46 +201,42 @@ MODULE_DEVICE_TABLE(pnp, pnp_devids);
static int ns558_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *did)
{
int ioport, iolen;
- struct ns558 *port;
+ struct ns558 *ns558;
+ struct gameport *port;
if (!pnp_port_valid(dev, 0)) {
printk(KERN_WARNING "ns558: No i/o ports on a gameport? Weird\n");
return -ENODEV;
}
- ioport = pnp_port_start(dev,0);
- iolen = pnp_port_len(dev,0);
+ ioport = pnp_port_start(dev, 0);
+ iolen = pnp_port_len(dev, 0);
if (!request_region(ioport, iolen, "ns558-pnp"))
return -EBUSY;
- if (!(port = kmalloc(sizeof(struct ns558), GFP_KERNEL))) {
- printk(KERN_ERR "ns558: Memory allocation failed.\n");
+ ns558 = kcalloc(1, sizeof(struct ns558), GFP_KERNEL);
+ port = gameport_allocate_port();
+ if (!ns558 || !port) {
+ printk(KERN_ERR "ns558: Memory allocation failed\n");
+ kfree(ns558);
+ gameport_free_port(port);
return -ENOMEM;
}
- memset(port, 0, sizeof(struct ns558));
-
- port->type = NS558_PNP;
- port->size = iolen;
- port->dev = dev;
- port->gameport.io = ioport;
- port->gameport.phys = port->phys;
- port->gameport.name = port->name;
- port->gameport.id.bustype = BUS_ISAPNP;
- port->gameport.id.version = 0x100;
+ ns558->io = ioport;
+ ns558->size = iolen;
+ ns558->dev = dev;
+ ns558->gameport = port;
- sprintf(port->phys, "pnp%s/gameport0", dev->dev.bus_id);
- sprintf(port->name, "%s", "NS558 PnP Gameport");
+ gameport_set_name(port, "NS558 PnP Gameport");
+ gameport_set_phys(port, "pnp%s/gameport0", dev->dev.bus_id);
+ port->dev.parent = &dev->dev;
+ port->io = ioport;
- gameport_register_port(&port->gameport);
+ gameport_register_port(port);
- printk(KERN_INFO "gameport: NS558 PnP at pnp%s io %#x",
- dev->dev.bus_id, port->gameport.io);
- if (iolen > 1) printk(" size %d", iolen);
- printk(" speed %d kHz\n", port->gameport.speed);
-
- list_add_tail(&port->node, &ns558_list);
+ list_add_tail(&ns558->node, &ns558_list);
return 0;
}
@@ -261,43 +252,39 @@ static struct pnp_driver ns558_pnp_driver;
#endif
-int __init ns558_init(void)
+static int pnp_registered = 0;
+
+static int __init ns558_init(void)
{
int i = 0;
/*
- * Probe for ISA ports.
+ * Probe ISA ports first so that PnP gets to choose free port addresses
+ * not occupied by the ISA ports.
*/
while (ns558_isa_portlist[i])
ns558_isa_probe(ns558_isa_portlist[i++]);
- pnp_register_driver(&ns558_pnp_driver);
- return list_empty(&ns558_list) ? -ENODEV : 0;
-}
+ if (pnp_register_driver(&ns558_pnp_driver) >= 0)
+ pnp_registered = 1;
-void __exit ns558_exit(void)
-{
- struct ns558 *port;
- list_for_each_entry(port, &ns558_list, node) {
- gameport_unregister_port(&port->gameport);
- switch (port->type) {
+ return (list_empty(&ns558_list) && !pnp_registered) ? -ENODEV : 0;
+}
-#ifdef CONFIG_PNP
- case NS558_PNP:
- /* fall through */
-#endif
- case NS558_ISA:
- release_region(port->gameport.io & ~(port->size - 1), port->size);
- kfree(port);
- break;
+static void __exit ns558_exit(void)
+{
+ struct ns558 *ns558;
- default:
- break;
- }
+ list_for_each_entry(ns558, &ns558_list, node) {
+ gameport_unregister_port(ns558->gameport);
+ release_region(ns558->io & ~(ns558->size - 1), ns558->size);
+ kfree(ns558);
}
- pnp_unregister_driver(&ns558_pnp_driver);
+
+ if (pnp_registered)
+ pnp_unregister_driver(&ns558_pnp_driver);
}
module_init(ns558_init);
diff --git a/drivers/input/gameport/vortex.c b/drivers/input/gameport/vortex.c
index e0a1c3eb58252..36b0309c8bf60 100644
--- a/drivers/input/gameport/vortex.c
+++ b/drivers/input/gameport/vortex.c
@@ -53,28 +53,27 @@ MODULE_LICENSE("GPL");
#define VORTEX_DATA_WAIT 20 /* 20 ms */
struct vortex {
- struct gameport gameport;
+ struct gameport *gameport;
struct pci_dev *dev;
- unsigned char __iomem *base;
- unsigned char __iomem *io;
- char phys[32];
+ unsigned char __iomem *base;
+ unsigned char __iomem *io;
};
static unsigned char vortex_read(struct gameport *gameport)
{
- struct vortex *vortex = gameport->driver;
+ struct vortex *vortex = gameport->port_data;
return readb(vortex->io + VORTEX_LEG);
}
static void vortex_trigger(struct gameport *gameport)
{
- struct vortex *vortex = gameport->driver;
+ struct vortex *vortex = gameport->port_data;
writeb(0xff, vortex->io + VORTEX_LEG);
}
static int vortex_cooked_read(struct gameport *gameport, int *axes, int *buttons)
{
- struct vortex *vortex = gameport->driver;
+ struct vortex *vortex = gameport->port_data;
int i;
*buttons = (~readb(vortex->base + VORTEX_LEG) >> 4) & 0xf;
@@ -89,7 +88,7 @@ static int vortex_cooked_read(struct gameport *gameport, int *axes, int *buttons
static int vortex_open(struct gameport *gameport, int mode)
{
- struct vortex *vortex = gameport->driver;
+ struct vortex *vortex = gameport->port_data;
switch (mode) {
case GAMEPORT_MODE_COOKED:
@@ -109,30 +108,17 @@ static int vortex_open(struct gameport *gameport, int mode)
static int __devinit vortex_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
struct vortex *vortex;
+ struct gameport *port;
int i;
- if (!(vortex = kmalloc(sizeof(struct vortex), GFP_KERNEL)))
- return -1;
- memset(vortex, 0, sizeof(struct vortex));
-
- vortex->dev = dev;
- sprintf(vortex->phys, "pci%s/gameport0", pci_name(dev));
-
- pci_set_drvdata(dev, vortex);
-
- vortex->gameport.driver = vortex;
- vortex->gameport.fuzz = 64;
-
- vortex->gameport.read = vortex_read;
- vortex->gameport.trigger = vortex_trigger;
- vortex->gameport.cooked_read = vortex_cooked_read;
- vortex->gameport.open = vortex_open;
-
- vortex->gameport.name = pci_name(dev);
- vortex->gameport.phys = vortex->phys;
- vortex->gameport.id.bustype = BUS_PCI;
- vortex->gameport.id.vendor = dev->vendor;
- vortex->gameport.id.product = dev->device;
+ vortex = kcalloc(1, sizeof(struct vortex), GFP_KERNEL);
+ port = gameport_allocate_port();
+ if (!vortex || !port) {
+ printk(KERN_ERR "vortex: Memory allocation failed.\n");
+ kfree(vortex);
+ gameport_free_port(port);
+ return -ENOMEM;
+ }
for (i = 0; i < 6; i++)
if (~pci_resource_flags(dev, i) & IORESOURCE_IO)
@@ -140,14 +126,26 @@ static int __devinit vortex_probe(struct pci_dev *dev, const struct pci_device_i
pci_enable_device(dev);
+ vortex->dev = dev;
+ vortex->gameport = port;
vortex->base = ioremap(pci_resource_start(vortex->dev, i),
pci_resource_len(vortex->dev, i));
vortex->io = vortex->base + id->driver_data;
- gameport_register_port(&vortex->gameport);
+ pci_set_drvdata(dev, vortex);
+
+ port->port_data = vortex;
+ port->fuzz = 64;
- printk(KERN_INFO "gameport at pci%s speed %d kHz\n",
- pci_name(dev), vortex->gameport.speed);
+ gameport_set_name(port, "AU88x0");
+ gameport_set_phys(port, "pci%s/gameport0", pci_name(dev));
+ port->dev.parent = &dev->dev;
+ port->read = vortex_read;
+ port->trigger = vortex_trigger;
+ port->cooked_read = vortex_cooked_read;
+ port->open = vortex_open;
+
+ gameport_register_port(port);
return 0;
}
@@ -155,15 +153,17 @@ static int __devinit vortex_probe(struct pci_dev *dev, const struct pci_device_i
static void __devexit vortex_remove(struct pci_dev *dev)
{
struct vortex *vortex = pci_get_drvdata(dev);
- gameport_unregister_port(&vortex->gameport);
+
+ gameport_unregister_port(vortex->gameport);
iounmap(vortex->base);
kfree(vortex);
}
-static struct pci_device_id vortex_id_table[] =
-{{ 0x12eb, 0x0001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0x11000 },
- { 0x12eb, 0x0002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0x28800 },
- { 0 }};
+static struct pci_device_id vortex_id_table[] = {
+ { 0x12eb, 0x0001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0x11000 },
+ { 0x12eb, 0x0002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0x28800 },
+ { 0 }
+};
static struct pci_driver vortex_driver = {
.name = "vortex_gameport",
@@ -172,12 +172,12 @@ static struct pci_driver vortex_driver = {
.remove = __devexit_p(vortex_remove),
};
-int __init vortex_init(void)
+static int __init vortex_init(void)
{
- return pci_module_init(&vortex_driver);
+ return pci_register_driver(&vortex_driver);
}
-void __exit vortex_exit(void)
+static void __exit vortex_exit(void)
{
pci_unregister_driver(&vortex_driver);
}
diff --git a/drivers/input/input.c b/drivers/input/input.c
index 6ff0f388d03c4..3385dd03abfc1 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -50,18 +50,10 @@ static struct input_handler *input_table[8];
#ifdef CONFIG_PROC_FS
static struct proc_dir_entry *proc_bus_input_dir;
-DECLARE_WAIT_QUEUE_HEAD(input_devices_poll_wait);
+static DECLARE_WAIT_QUEUE_HEAD(input_devices_poll_wait);
static int input_devices_state;
#endif
-static inline unsigned int ms_to_jiffies(unsigned int ms)
-{
- unsigned int j;
- j = (ms * HZ + 500) / 1000;
- return (j > 0) ? j : 1;
-}
-
-
void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
{
struct input_handle *handle;
@@ -96,9 +88,9 @@ void input_event(struct input_dev *dev, unsigned int type, unsigned int code, in
change_bit(code, dev->key);
- if (test_bit(EV_REP, dev->evbit) && dev->rep[REP_PERIOD] && dev->timer.data && value) {
+ if (test_bit(EV_REP, dev->evbit) && dev->rep[REP_PERIOD] && dev->rep[REP_DELAY] && dev->timer.data && value) {
dev->repeat_key = code;
- mod_timer(&dev->timer, jiffies + ms_to_jiffies(dev->rep[REP_DELAY]));
+ mod_timer(&dev->timer, jiffies + msecs_to_jiffies(dev->rep[REP_DELAY]));
}
break;
@@ -198,7 +190,8 @@ static void input_repeat_key(unsigned long data)
input_event(dev, EV_KEY, dev->repeat_key, 2);
input_sync(dev);
- mod_timer(&dev->timer, jiffies + ms_to_jiffies(dev->rep[REP_PERIOD]));
+ if (dev->rep[REP_PERIOD])
+ mod_timer(&dev->timer, jiffies + msecs_to_jiffies(dev->rep[REP_PERIOD]));
}
int input_accept_process(struct input_handle *handle, struct file *file)
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c
index 4fe982d63bede..7d7527f8b02dc 100644
--- a/drivers/input/joydev.c
+++ b/drivers/input/joydev.c
@@ -47,15 +47,15 @@ struct joydev {
struct input_handle handle;
wait_queue_head_t wait;
struct list_head list;
- struct js_corr corr[ABS_MAX];
+ struct js_corr corr[ABS_MAX + 1];
struct JS_DATA_SAVE_TYPE glue;
int nabs;
int nkey;
- __u16 keymap[KEY_MAX - BTN_MISC];
- __u16 keypam[KEY_MAX - BTN_MISC];
- __u8 absmap[ABS_MAX];
- __u8 abspam[ABS_MAX];
- __s16 abs[ABS_MAX];
+ __u16 keymap[KEY_MAX - BTN_MISC + 1];
+ __u16 keypam[KEY_MAX - BTN_MISC + 1];
+ __u8 absmap[ABS_MAX + 1];
+ __u8 abspam[ABS_MAX + 1];
+ __s16 abs[ABS_MAX + 1];
};
struct joydev_list {
@@ -281,9 +281,8 @@ static unsigned int joydev_poll(struct file *file, poll_table *wait)
{
struct joydev_list *list = file->private_data;
poll_wait(file, &list->joydev->wait, wait);
- if (list->head != list->tail || list->startup < list->joydev->nabs + list->joydev->nkey)
- return POLLIN | POLLRDNORM;
- return 0;
+ return ((list->head != list->tail || list->startup < list->joydev->nabs + list->joydev->nkey) ?
+ (POLLIN | POLLRDNORM) : 0) | (list->joydev->exist ? 0 : (POLLHUP | POLLERR));
}
static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
@@ -338,7 +337,7 @@ static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
return copy_to_user(argp, joydev->corr,
sizeof(struct js_corr) * joydev->nabs) ? -EFAULT : 0;
case JSIOCSAXMAP:
- if (copy_from_user(joydev->abspam, argp, sizeof(__u8) * ABS_MAX))
+ if (copy_from_user(joydev->abspam, argp, sizeof(__u8) * (ABS_MAX + 1)))
return -EFAULT;
for (i = 0; i < joydev->nabs; i++) {
if (joydev->abspam[i] > ABS_MAX) return -EINVAL;
@@ -347,9 +346,9 @@ static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
return 0;
case JSIOCGAXMAP:
return copy_to_user(argp, joydev->abspam,
- sizeof(__u8) * ABS_MAX) ? -EFAULT : 0;
+ sizeof(__u8) * (ABS_MAX + 1)) ? -EFAULT : 0;
case JSIOCSBTNMAP:
- if (copy_from_user(joydev->keypam, argp, sizeof(__u16) * (KEY_MAX - BTN_MISC)))
+ if (copy_from_user(joydev->keypam, argp, sizeof(__u16) * (KEY_MAX - BTN_MISC + 1)))
return -EFAULT;
for (i = 0; i < joydev->nkey; i++) {
if (joydev->keypam[i] > KEY_MAX || joydev->keypam[i] < BTN_MISC) return -EINVAL;
@@ -358,7 +357,7 @@ static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
return 0;
case JSIOCGBTNMAP:
return copy_to_user(argp, joydev->keypam,
- sizeof(__u16) * (KEY_MAX - BTN_MISC)) ? -EFAULT : 0;
+ sizeof(__u16) * (KEY_MAX - BTN_MISC + 1)) ? -EFAULT : 0;
default:
if ((cmd & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT)) == JSIOCGNAME(0)) {
int len;
@@ -409,21 +408,21 @@ static struct input_handle *joydev_connect(struct input_handler *handler, struct
joydev->handle.private = joydev;
sprintf(joydev->name, "js%d", minor);
- for (i = 0; i < ABS_MAX; i++)
+ for (i = 0; i < ABS_MAX + 1; i++)
if (test_bit(i, dev->absbit)) {
joydev->absmap[i] = joydev->nabs;
joydev->abspam[joydev->nabs] = i;
joydev->nabs++;
}
- for (i = BTN_JOYSTICK - BTN_MISC; i < KEY_MAX - BTN_MISC; i++)
+ for (i = BTN_JOYSTICK - BTN_MISC; i < KEY_MAX - BTN_MISC + 1; i++)
if (test_bit(i + BTN_MISC, dev->keybit)) {
joydev->keymap[i] = joydev->nkey;
joydev->keypam[joydev->nkey] = i + BTN_MISC;
joydev->nkey++;
}
- for (i = 0; i < BTN_JOYSTICK - BTN_MISC; i++)
+ for (i = 0; i < BTN_JOYSTICK - BTN_MISC + 1; i++)
if (test_bit(i + BTN_MISC, dev->keybit)) {
joydev->keymap[i] = joydev->nkey;
joydev->keypam[joydev->nkey] = i + BTN_MISC;
@@ -463,14 +462,18 @@ static struct input_handle *joydev_connect(struct input_handler *handler, struct
static void joydev_disconnect(struct input_handle *handle)
{
struct joydev *joydev = handle->private;
+ struct joydev_list *list;
class_simple_device_remove(MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + joydev->minor));
devfs_remove("input/js%d", joydev->minor);
joydev->exist = 0;
- if (joydev->open)
+ if (joydev->open) {
input_close_device(handle);
- else
+ wake_up_interruptible(&joydev->wait);
+ list_for_each_entry(list, &joydev->list, node)
+ kill_fasync(&list->fasync, SIGIO, POLL_HUP);
+ } else
joydev_free(joydev);
}
diff --git a/drivers/input/joystick/Kconfig b/drivers/input/joystick/Kconfig
index 8f62f70d0e421..67519ef0ef955 100644
--- a/drivers/input/joystick/Kconfig
+++ b/drivers/input/joystick/Kconfig
@@ -1,9 +1,8 @@
#
# Joystick driver configuration
#
-config INPUT_JOYSTICK
+menuconfig INPUT_JOYSTICK
bool "Joysticks"
- depends on INPUT
help
If you have a joystick, 6dof controller, gamepad, steering wheel,
weapon control system or something like that you can say Y here
@@ -13,9 +12,11 @@ config INPUT_JOYSTICK
Please read the file <file:Documentation/input/joystick.txt> which
contains more information.
+if INPUT_JOYSTICK
+
config JOYSTICK_ANALOG
tristate "Classic PC analog joysticks and gamepads"
- depends on INPUT && INPUT_JOYSTICK && GAMEPORT
+ select GAMEPORT
---help---
Say Y here if you have a joystick that connects to the PC
gameport. In addition to the usual PC analog joystick, this driver
@@ -32,7 +33,7 @@ config JOYSTICK_ANALOG
config JOYSTICK_A3D
tristate "Assasin 3D and MadCatz Panther devices"
- depends on INPUT && INPUT_JOYSTICK && GAMEPORT
+ select GAMEPORT
help
Say Y here if you have an FPGaming or MadCatz controller using the
A3D protocol over the PC gameport.
@@ -42,7 +43,7 @@ config JOYSTICK_A3D
config JOYSTICK_ADI
tristate "Logitech ADI digital joysticks and gamepads"
- depends on INPUT && INPUT_JOYSTICK && GAMEPORT
+ select GAMEPORT
help
Say Y here if you have a Logitech controller using the ADI
protocol over the PC gameport.
@@ -52,7 +53,7 @@ config JOYSTICK_ADI
config JOYSTICK_COBRA
tristate "Creative Labs Blaster Cobra gamepad"
- depends on INPUT && INPUT_JOYSTICK && GAMEPORT
+ select GAMEPORT
help
Say Y here if you have a Creative Labs Blaster Cobra gamepad.
@@ -61,7 +62,7 @@ config JOYSTICK_COBRA
config JOYSTICK_GF2K
tristate "Genius Flight2000 Digital joysticks and gamepads"
- depends on INPUT && INPUT_JOYSTICK && GAMEPORT
+ select GAMEPORT
help
Say Y here if you have a Genius Flight2000 or MaxFighter digitally
communicating joystick or gamepad.
@@ -71,7 +72,7 @@ config JOYSTICK_GF2K
config JOYSTICK_GRIP
tristate "Gravis GrIP joysticks and gamepads"
- depends on INPUT && INPUT_JOYSTICK && GAMEPORT
+ select GAMEPORT
help
Say Y here if you have a Gravis controller using the GrIP protocol
over the PC gameport.
@@ -81,7 +82,7 @@ config JOYSTICK_GRIP
config JOYSTICK_GRIP_MP
tristate "Gravis GrIP MultiPort"
- depends on INPUT && INPUT_JOYSTICK && GAMEPORT
+ select GAMEPORT
help
Say Y here if you have the original Gravis GrIP MultiPort, a hub
that connects to the gameport and you connect gamepads to it.
@@ -91,7 +92,7 @@ config JOYSTICK_GRIP_MP
config JOYSTICK_GUILLEMOT
tristate "Guillemot joysticks and gamepads"
- depends on INPUT && INPUT_JOYSTICK && GAMEPORT
+ select GAMEPORT
help
Say Y here if you have a Guillemot joystick using a digital
protocol over the PC gameport.
@@ -101,7 +102,7 @@ config JOYSTICK_GUILLEMOT
config JOYSTICK_INTERACT
tristate "InterAct digital joysticks and gamepads"
- depends on INPUT && INPUT_JOYSTICK && GAMEPORT
+ select GAMEPORT
help
Say Y here if you have an InterAct gameport or joystick
communicating digitally over the gameport.
@@ -111,7 +112,7 @@ config JOYSTICK_INTERACT
config JOYSTICK_SIDEWINDER
tristate "Microsoft SideWinder digital joysticks and gamepads"
- depends on INPUT && INPUT_JOYSTICK && GAMEPORT
+ select GAMEPORT
help
Say Y here if you have a Microsoft controller using the Digital
Overdrive protocol over PC gameport.
@@ -121,7 +122,7 @@ config JOYSTICK_SIDEWINDER
config JOYSTICK_TMDC
tristate "ThrustMaster DirectConnect joysticks and gamepads"
- depends on INPUT && INPUT_JOYSTICK && GAMEPORT
+ select GAMEPORT
help
Say Y here if you have a ThrustMaster controller using the
DirectConnect (BSP) protocol over the PC gameport.
@@ -133,7 +134,6 @@ source "drivers/input/joystick/iforce/Kconfig"
config JOYSTICK_WARRIOR
tristate "Logitech WingMan Warrior joystick"
- depends on INPUT && INPUT_JOYSTICK
select SERIO
help
Say Y here if you have a Logitech WingMan Warrior joystick connected
@@ -144,7 +144,6 @@ config JOYSTICK_WARRIOR
config JOYSTICK_MAGELLAN
tristate "LogiCad3d Magellan/SpaceMouse 6dof controllers"
- depends on INPUT && INPUT_JOYSTICK
select SERIO
help
Say Y here if you have a Magellan or Space Mouse 6DOF controller
@@ -155,7 +154,6 @@ config JOYSTICK_MAGELLAN
config JOYSTICK_SPACEORB
tristate "SpaceTec SpaceOrb/Avenger 6dof controllers"
- depends on INPUT && INPUT_JOYSTICK
select SERIO
help
Say Y here if you have a SpaceOrb 360 or SpaceBall Avenger 6DOF
@@ -166,7 +164,6 @@ config JOYSTICK_SPACEORB
config JOYSTICK_SPACEBALL
tristate "SpaceTec SpaceBall 6dof controllers"
- depends on INPUT && INPUT_JOYSTICK
select SERIO
help
Say Y here if you have a SpaceTec SpaceBall 2003/3003/4000 FLX
@@ -178,7 +175,6 @@ config JOYSTICK_SPACEBALL
config JOYSTICK_STINGER
tristate "Gravis Stinger gamepad"
- depends on INPUT && INPUT_JOYSTICK
select SERIO
help
Say Y here if you have a Gravis Stinger connected to one of your
@@ -187,9 +183,8 @@ config JOYSTICK_STINGER
To compile this driver as a module, choose M here: the
module will be called stinger.
-config JOYSTICK_TWIDDLER
+config JOYSTICK_TWIDJOY
tristate "Twiddler as a joystick"
- depends on INPUT && INPUT_JOYSTICK
select SERIO
help
Say Y here if you have a Handykey Twiddler connected to your
@@ -200,7 +195,7 @@ config JOYSTICK_TWIDDLER
config JOYSTICK_DB9
tristate "Multisystem, Sega Genesis, Saturn joysticks and gamepads"
- depends on INPUT && INPUT_JOYSTICK && PARPORT
+ depends on PARPORT
---help---
Say Y here if you have a Sega Master System gamepad, Sega Genesis
gamepad, Sega Saturn gamepad, or a Multisystem -- Atari, Amiga,
@@ -213,7 +208,7 @@ config JOYSTICK_DB9
config JOYSTICK_GAMECON
tristate "Multisystem, NES, SNES, N64, PSX joysticks and gamepads"
- depends on INPUT && INPUT_JOYSTICK && PARPORT
+ depends on PARPORT
---help---
Say Y here if you have a Nintendo Entertainment System gamepad,
Super Nintendo Entertainment System gamepad, Nintendo 64 gamepad,
@@ -227,7 +222,7 @@ config JOYSTICK_GAMECON
config JOYSTICK_TURBOGRAFX
tristate "Multisystem joysticks via TurboGraFX device"
- depends on INPUT && INPUT_JOYSTICK && PARPORT
+ depends on PARPORT
help
Say Y here if you have the TurboGraFX interface by Steffen Schwenke,
and want to use it with Multisystem -- Atari, Amiga, Commodore,
@@ -239,7 +234,7 @@ config JOYSTICK_TURBOGRAFX
config JOYSTICK_AMIGA
tristate "Amiga joysticks"
- depends on AMIGA && INPUT && INPUT_JOYSTICK
+ depends on AMIGA
help
Say Y here if you have an Amiga with a digital joystick connected
to it.
@@ -249,7 +244,7 @@ config JOYSTICK_AMIGA
config JOYSTICK_JOYDUMP
tristate "Gameport data dumper"
- depends on INPUT && INPUT_JOYSTICK && GAMEPORT
+ select GAMEPORT
help
Say Y here if you want to dump data from your joystick into the system
log for debugging purposes. Say N if you are making a production
@@ -258,3 +253,4 @@ config JOYSTICK_JOYDUMP
To compile this driver as a module, choose M here: the
module will be called joydump.
+endif
diff --git a/drivers/input/joystick/a3d.c b/drivers/input/joystick/a3d.c
index b3eb64fdc512a..ad39fe4bf35f5 100644
--- a/drivers/input/joystick/a3d.c
+++ b/drivers/input/joystick/a3d.c
@@ -35,38 +35,35 @@
#include <linux/gameport.h>
#include <linux/input.h>
+#define DRIVER_DESC "FP-Gaming Assasin 3D joystick driver"
+
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
-MODULE_DESCRIPTION("FP-Gaming Assasin 3D joystick driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
-#define A3D_MAX_START 400 /* 400 us */
-#define A3D_MAX_STROBE 60 /* 40 us */
-#define A3D_DELAY_READ 3 /* 3 ms */
+#define A3D_MAX_START 600 /* 600 us */
+#define A3D_MAX_STROBE 80 /* 80 us */
#define A3D_MAX_LENGTH 40 /* 40*3 bits */
-#define A3D_REFRESH_TIME HZ/50 /* 20 ms */
#define A3D_MODE_A3D 1 /* Assassin 3D */
#define A3D_MODE_PAN 2 /* Panther */
#define A3D_MODE_OEM 3 /* Panther OEM version */
#define A3D_MODE_PXL 4 /* Panther XL */
-char *a3d_names[] = { NULL, "FP-Gaming Assassin 3D", "MadCatz Panther", "OEM Panther",
+static char *a3d_names[] = { NULL, "FP-Gaming Assassin 3D", "MadCatz Panther", "OEM Panther",
"MadCatz Panther XL", "MadCatz Panther XL w/ rudder" };
struct a3d {
struct gameport *gameport;
- struct gameport adc;
+ struct gameport *adc;
struct input_dev dev;
- struct timer_list timer;
int axes[4];
int buttons;
int mode;
int length;
- int used;
int reads;
int bads;
char phys[32];
- char adcphys[32];
};
/*
@@ -109,7 +106,9 @@ static int a3d_read_packet(struct gameport *gameport, int length, char *data)
static int a3d_csum(char *data, int count)
{
int i, csum = 0;
- for (i = 0; i < count - 2; i++) csum += data[i];
+
+ for (i = 0; i < count - 2; i++)
+ csum += data[i];
return (csum & 0x3f) != ((data[count - 2] << 3) | data[count - 1]);
}
@@ -139,7 +138,7 @@ static void a3d_read(struct a3d *a3d, unsigned char *data)
a3d->buttons = ((data[3] << 3) | data[4]) & 0xf;
- return;
+ break;
case A3D_MODE_PXL:
@@ -169,24 +168,26 @@ static void a3d_read(struct a3d *a3d, unsigned char *data)
input_sync(dev);
- return;
+ break;
}
}
/*
- * a3d_timer() reads and analyzes A3D joystick data.
+ * a3d_poll() reads and analyzes A3D joystick data.
*/
-static void a3d_timer(unsigned long private)
+static void a3d_poll(struct gameport *gameport)
{
- struct a3d *a3d = (void *) private;
+ struct a3d *a3d = gameport_get_drvdata(gameport);
unsigned char data[A3D_MAX_LENGTH];
+
a3d->reads++;
- if (a3d_read_packet(a3d->gameport, a3d->length, data) != a3d->length
- || data[0] != a3d->mode || a3d_csum(data, a3d->length))
- a3d->bads++; else a3d_read(a3d, data);
- mod_timer(&a3d->timer, jiffies + A3D_REFRESH_TIME);
+ if (a3d_read_packet(a3d->gameport, a3d->length, data) != a3d->length ||
+ data[0] != a3d->mode || a3d_csum(data, a3d->length))
+ a3d->bads++;
+ else
+ a3d_read(a3d, data);
}
/*
@@ -195,10 +196,11 @@ static void a3d_timer(unsigned long private)
* call this more than 50 times a second, which would use too much CPU.
*/
-int a3d_adc_cooked_read(struct gameport *gameport, int *axes, int *buttons)
+static int a3d_adc_cooked_read(struct gameport *gameport, int *axes, int *buttons)
{
- struct a3d *a3d = gameport->driver;
+ struct a3d *a3d = gameport->port_data;
int i;
+
for (i = 0; i < 4; i++)
axes[i] = (a3d->axes[i] < 254) ? a3d->axes[i] : -1;
*buttons = a3d->buttons;
@@ -210,13 +212,14 @@ int a3d_adc_cooked_read(struct gameport *gameport, int *axes, int *buttons)
* any but cooked data.
*/
-int a3d_adc_open(struct gameport *gameport, int mode)
+static int a3d_adc_open(struct gameport *gameport, int mode)
{
- struct a3d *a3d = gameport->driver;
+ struct a3d *a3d = gameport->port_data;
+
if (mode != GAMEPORT_MODE_COOKED)
return -1;
- if (!a3d->used++)
- mod_timer(&a3d->timer, jiffies + A3D_REFRESH_TIME);
+
+ gameport_start_polling(a3d->gameport);
return 0;
}
@@ -226,9 +229,9 @@ int a3d_adc_open(struct gameport *gameport, int mode)
static void a3d_adc_close(struct gameport *gameport)
{
- struct a3d *a3d = gameport->driver;
- if (!--a3d->used)
- del_timer(&a3d->timer);
+ struct a3d *a3d = gameport->port_data;
+
+ gameport_stop_polling(a3d->gameport);
}
/*
@@ -238,8 +241,8 @@ static void a3d_adc_close(struct gameport *gameport)
static int a3d_open(struct input_dev *dev)
{
struct a3d *a3d = dev->private;
- if (!a3d->used++)
- mod_timer(&a3d->timer, jiffies + A3D_REFRESH_TIME);
+
+ gameport_start_polling(a3d->gameport);
return 0;
}
@@ -250,49 +253,53 @@ static int a3d_open(struct input_dev *dev)
static void a3d_close(struct input_dev *dev)
{
struct a3d *a3d = dev->private;
- if (!--a3d->used)
- del_timer(&a3d->timer);
+
+ gameport_stop_polling(a3d->gameport);
}
/*
* a3d_connect() probes for A3D joysticks.
*/
-static void a3d_connect(struct gameport *gameport, struct gameport_dev *dev)
+static int a3d_connect(struct gameport *gameport, struct gameport_driver *drv)
{
struct a3d *a3d;
+ struct gameport *adc;
unsigned char data[A3D_MAX_LENGTH];
int i;
+ int err;
- if (!(a3d = kmalloc(sizeof(struct a3d), GFP_KERNEL)))
- return;
- memset(a3d, 0, sizeof(struct a3d));
-
- gameport->private = a3d;
+ if (!(a3d = kcalloc(1, sizeof(struct a3d), GFP_KERNEL)))
+ return -ENOMEM;
a3d->gameport = gameport;
- init_timer(&a3d->timer);
- a3d->timer.data = (long) a3d;
- a3d->timer.function = a3d_timer;
- if (gameport_open(gameport, dev, GAMEPORT_MODE_RAW))
+ gameport_set_drvdata(gameport, a3d);
+
+ err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
+ if (err)
goto fail1;
i = a3d_read_packet(gameport, A3D_MAX_LENGTH, data);
- if (!i || a3d_csum(data, i))
+ if (!i || a3d_csum(data, i)) {
+ err = -ENODEV;
goto fail2;
+ }
a3d->mode = data[0];
if (!a3d->mode || a3d->mode > 5) {
printk(KERN_WARNING "a3d.c: Unknown A3D device detected "
"(%s, id=%d), contact <vojtech@ucw.cz>\n", gameport->phys, a3d->mode);
+ err = -ENODEV;
goto fail2;
}
+ gameport_set_poll_handler(gameport, a3d_poll);
+ gameport_set_poll_interval(gameport, 20);
+
sprintf(a3d->phys, "%s/input0", gameport->phys);
- sprintf(a3d->adcphys, "%s/gameport0", gameport->phys);
if (a3d->mode == A3D_MODE_PXL) {
@@ -315,16 +322,11 @@ static void a3d_connect(struct gameport *gameport, struct gameport_dev *dev)
a3d_read(a3d, data);
for (i = 0; i < 4; i++) {
- if (i < 2) {
- a3d->dev.absmin[axes[i]] = 48;
- a3d->dev.absmax[axes[i]] = a3d->dev.abs[axes[i]] * 2 - 48;
- a3d->dev.absflat[axes[i]] = 8;
- } else {
- a3d->dev.absmin[axes[i]] = 2;
- a3d->dev.absmax[axes[i]] = 253;
- }
- a3d->dev.absmin[ABS_HAT0X + i] = -1;
- a3d->dev.absmax[ABS_HAT0X + i] = 1;
+ if (i < 2)
+ input_set_abs_params(&a3d->dev, axes[i], 48, a3d->dev.abs[axes[i]] * 2 - 48, 0, 8);
+ else
+ input_set_abs_params(&a3d->dev, axes[i], 2, 253, 0, 0);
+ input_set_abs_params(&a3d->dev, ABS_HAT0X + i, -1, 1, 0, 0);
}
} else {
@@ -336,23 +338,23 @@ static void a3d_connect(struct gameport *gameport, struct gameport_dev *dev)
a3d->dev.relbit[0] |= BIT(REL_X) | BIT(REL_Y);
a3d->dev.keybit[LONG(BTN_MOUSE)] |= BIT(BTN_RIGHT) | BIT(BTN_LEFT) | BIT(BTN_MIDDLE);
- a3d->adc.driver = a3d;
- a3d->adc.open = a3d_adc_open;
- a3d->adc.close = a3d_adc_close;
- a3d->adc.cooked_read = a3d_adc_cooked_read;
- a3d->adc.fuzz = 1;
+ a3d_read(a3d, data);
- a3d->adc.name = a3d_names[a3d->mode];
- a3d->adc.phys = a3d->adcphys;
- a3d->adc.id.bustype = BUS_GAMEPORT;
- a3d->adc.id.vendor = GAMEPORT_ID_VENDOR_MADCATZ;
- a3d->adc.id.product = a3d->mode;
- a3d->adc.id.version = 0x0100;
+ if (!(a3d->adc = adc = gameport_allocate_port()))
+ printk(KERN_ERR "a3d: Not enough memory for ADC port\n");
+ else {
+ adc->port_data = a3d;
+ adc->open = a3d_adc_open;
+ adc->close = a3d_adc_close;
+ adc->cooked_read = a3d_adc_cooked_read;
+ adc->fuzz = 1;
- a3d_read(a3d, data);
+ gameport_set_name(adc, a3d_names[a3d->mode]);
+ gameport_set_phys(adc, "%s/gameport0", gameport->phys);
+ adc->dev.parent = &gameport->dev;
- gameport_register_port(&a3d->adc);
- printk(KERN_INFO "gameport: %s on %s\n", a3d_names[a3d->mode], gameport->phys);
+ gameport_register_port(adc);
+ }
}
a3d->dev.private = a3d;
@@ -369,36 +371,46 @@ static void a3d_connect(struct gameport *gameport, struct gameport_dev *dev)
input_register_device(&a3d->dev);
printk(KERN_INFO "input: %s on %s\n", a3d_names[a3d->mode], a3d->phys);
- return;
+ return 0;
+
fail2: gameport_close(gameport);
-fail1: kfree(a3d);
+fail1: gameport_set_drvdata(gameport, NULL);
+ kfree(a3d);
+ return err;
}
static void a3d_disconnect(struct gameport *gameport)
{
+ struct a3d *a3d = gameport_get_drvdata(gameport);
- struct a3d *a3d = gameport->private;
input_unregister_device(&a3d->dev);
- if (a3d->mode < A3D_MODE_PXL)
- gameport_unregister_port(&a3d->adc);
+ if (a3d->adc) {
+ gameport_unregister_port(a3d->adc);
+ a3d->adc = NULL;
+ }
gameport_close(gameport);
+ gameport_set_drvdata(gameport, NULL);
kfree(a3d);
}
-static struct gameport_dev a3d_dev = {
- .connect = a3d_connect,
- .disconnect = a3d_disconnect,
+static struct gameport_driver a3d_drv = {
+ .driver = {
+ .name = "adc",
+ },
+ .description = DRIVER_DESC,
+ .connect = a3d_connect,
+ .disconnect = a3d_disconnect,
};
-int __init a3d_init(void)
+static int __init a3d_init(void)
{
- gameport_register_device(&a3d_dev);
+ gameport_register_driver(&a3d_drv);
return 0;
}
-void __exit a3d_exit(void)
+static void __exit a3d_exit(void)
{
- gameport_unregister_device(&a3d_dev);
+ gameport_unregister_driver(&a3d_drv);
}
module_init(a3d_init);
diff --git a/drivers/input/joystick/adi.c b/drivers/input/joystick/adi.c
index da70b5dea625f..83f6dafc17169 100644
--- a/drivers/input/joystick/adi.c
+++ b/drivers/input/joystick/adi.c
@@ -1,7 +1,5 @@
/*
- * $Id: adi.c,v 1.23 2002/01/22 20:26:17 vojtech Exp $
- *
- * Copyright (c) 1998-2001 Vojtech Pavlik
+ * Copyright (c) 1998-2005 Vojtech Pavlik
*/
/*
@@ -37,8 +35,10 @@
#include <linux/gameport.h>
#include <linux/init.h>
+#define DRIVER_DESC "Logitech ADI joystick family driver"
+
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
-MODULE_DESCRIPTION("Logitech ADI joystick family driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
/*
@@ -47,7 +47,6 @@ MODULE_LICENSE("GPL");
#define ADI_MAX_START 200 /* Trigger to packet timeout [200us] */
#define ADI_MAX_STROBE 40 /* Single bit timeout [40us] */
-#define ADI_REFRESH_TIME HZ/50 /* How often to poll the joystick [20 ms] */
#define ADI_INIT_DELAY 10 /* Delay after init packet [10ms] */
#define ADI_DATA_DELAY 4 /* Delay after data packet [4ms] */
@@ -57,7 +56,7 @@ MODULE_LICENSE("GPL");
#define ADI_MIN_ID_LENGTH 66
#define ADI_MAX_NAME_LENGTH 48
#define ADI_MAX_CNAME_LENGTH 16
-#define ADI_MAX_PHYS_LENGTH 32
+#define ADI_MAX_PHYS_LENGTH 64
#define ADI_FLAG_HAT 0x04
#define ADI_FLAG_10BIT 0x08
@@ -127,11 +126,9 @@ struct adi {
struct adi_port {
struct gameport *gameport;
- struct timer_list timer;
struct adi adi[2];
int bad;
int reads;
- int used;
};
/*
@@ -275,15 +272,15 @@ static int adi_read(struct adi_port *port)
}
/*
- * adi_timer() repeatedly polls the Logitech joysticks.
+ * adi_poll() repeatedly polls the Logitech joysticks.
*/
-static void adi_timer(unsigned long data)
+static void adi_poll(struct gameport *gameport)
{
- struct adi_port *port = (void *) data;
+ struct adi_port *port = gameport_get_drvdata(gameport);
+
port->bad -= adi_read(port);
port->reads++;
- mod_timer(&port->timer, jiffies + ADI_REFRESH_TIME);
}
/*
@@ -293,8 +290,8 @@ static void adi_timer(unsigned long data)
static int adi_open(struct input_dev *dev)
{
struct adi_port *port = dev->private;
- if (!port->used++)
- mod_timer(&port->timer, jiffies + ADI_REFRESH_TIME);
+
+ gameport_start_polling(port->gameport);
return 0;
}
@@ -305,8 +302,8 @@ static int adi_open(struct input_dev *dev)
static void adi_close(struct input_dev *dev)
{
struct adi_port *port = dev->private;
- if (!--port->used)
- del_timer(&port->timer);
+
+ gameport_stop_polling(port->gameport);
}
/*
@@ -316,13 +313,16 @@ static void adi_close(struct input_dev *dev)
static void adi_init_digital(struct gameport *gameport)
{
- int seq[] = { 3, -2, -3, 10, -6, -11, -7, -9, 11, 0 };
+ int seq[] = { 4, -2, -3, 10, -6, -11, -7, -9, 11, 0 };
int i;
for (i = 0; seq[i]; i++) {
gameport_trigger(gameport);
if (seq[i] > 0) msleep(seq[i]);
- if (seq[i] < 0) mdelay(-seq[i]);
+ if (seq[i] < 0) {
+ mdelay(-seq[i]);
+ udelay(-seq[i]*14); /* It looks like mdelay() is off by approx 1.4% */
+ }
}
}
@@ -408,9 +408,9 @@ static void adi_init_input(struct adi *adi, struct adi_port *port, int half)
t = adi->id < ADI_ID_MAX ? adi->id : ADI_ID_MAX;
- sprintf(buf, adi_names[t], adi->id);
- sprintf(adi->name, "Logitech %s", buf);
- sprintf(adi->phys, "%s/input%d", port->gameport->phys, half);
+ snprintf(buf, ADI_MAX_PHYS_LENGTH, adi_names[t], adi->id);
+ snprintf(adi->name, ADI_MAX_NAME_LENGTH, "Logitech %s", buf);
+ snprintf(adi->phys, ADI_MAX_PHYS_LENGTH, "%s/input%d", port->gameport->phys, half);
adi->abs = adi_abs[t];
adi->key = adi_key[t];
@@ -439,35 +439,23 @@ static void adi_init_center(struct adi *adi)
{
int i, t, x;
- if (!adi->length) return;
+ if (!adi->length)
+ return;
for (i = 0; i < adi->axes10 + adi->axes8 + (adi->hats + (adi->pad != -1)) * 2; i++) {
t = adi->abs[i];
x = adi->dev.abs[t];
- if (t == ABS_THROTTLE || t == ABS_RUDDER || adi->id == ADI_ID_WGPE) {
- if (i < adi->axes10) x = 512; else x = 128;
- }
-
- if (i < adi->axes10) {
- adi->dev.absmax[t] = x * 2 - 64;
- adi->dev.absmin[t] = 64;
- adi->dev.absfuzz[t] = 2;
- adi->dev.absflat[t] = 16;
- continue;
- }
+ if (t == ABS_THROTTLE || t == ABS_RUDDER || adi->id == ADI_ID_WGPE)
+ x = i < adi->axes10 ? 512 : 128;
- if (i < adi->axes10 + adi->axes8) {
- adi->dev.absmax[t] = x * 2 - 48;
- adi->dev.absmin[t] = 48;
- adi->dev.absfuzz[t] = 1;
- adi->dev.absflat[t] = 16;
- continue;
- }
-
- adi->dev.absmax[t] = 1;
- adi->dev.absmin[t] = -1;
+ if (i < adi->axes10)
+ input_set_abs_params(&adi->dev, t, 64, x * 2 - 64, 2, 16);
+ else if (i < adi->axes10 + adi->axes8)
+ input_set_abs_params(&adi->dev, t, 48, x * 2 - 48, 1, 16);
+ else
+ input_set_abs_params(&adi->dev, t, -1, 1, 0, 0);
}
}
@@ -475,25 +463,23 @@ static void adi_init_center(struct adi *adi)
* adi_connect() probes for Logitech ADI joysticks.
*/
-static void adi_connect(struct gameport *gameport, struct gameport_dev *dev)
+static int adi_connect(struct gameport *gameport, struct gameport_driver *drv)
{
struct adi_port *port;
int i;
+ int err;
- if (!(port = kmalloc(sizeof(struct adi_port), GFP_KERNEL)))
- return;
- memset(port, 0, sizeof(struct adi_port));
-
- gameport->private = port;
+ if (!(port = kcalloc(1, sizeof(struct adi_port), GFP_KERNEL)))
+ return -ENOMEM;
port->gameport = gameport;
- init_timer(&port->timer);
- port->timer.data = (long) port;
- port->timer.function = adi_timer;
- if (gameport_open(gameport, dev, GAMEPORT_MODE_RAW)) {
+ gameport_set_drvdata(gameport, port);
+
+ err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
+ if (err) {
kfree(port);
- return;
+ return err;
}
adi_init_digital(gameport);
@@ -510,9 +496,12 @@ static void adi_connect(struct gameport *gameport, struct gameport_dev *dev)
if (!port->adi[0].length && !port->adi[1].length) {
gameport_close(gameport);
kfree(port);
- return;
+ return -ENODEV;
}
+ gameport_set_poll_handler(gameport, adi_poll);
+ gameport_set_poll_interval(gameport, 20);
+
msleep(ADI_INIT_DELAY);
if (adi_read(port)) {
msleep(ADI_DATA_DELAY);
@@ -526,17 +515,20 @@ static void adi_connect(struct gameport *gameport, struct gameport_dev *dev)
printk(KERN_INFO "input: %s [%s] on %s\n",
port->adi[i].name, port->adi[i].cname, gameport->phys);
}
+
+ return 0;
}
static void adi_disconnect(struct gameport *gameport)
{
int i;
+ struct adi_port *port = gameport_get_drvdata(gameport);
- struct adi_port *port = gameport->private;
for (i = 0; i < 2; i++)
if (port->adi[i].length > 0)
input_unregister_device(&port->adi[i].dev);
gameport_close(gameport);
+ gameport_set_drvdata(gameport, NULL);
kfree(port);
}
@@ -544,20 +536,24 @@ static void adi_disconnect(struct gameport *gameport)
* The gameport device structure.
*/
-static struct gameport_dev adi_dev = {
- .connect = adi_connect,
- .disconnect = adi_disconnect,
+static struct gameport_driver adi_drv = {
+ .driver = {
+ .name = "adi",
+ },
+ .description = DRIVER_DESC,
+ .connect = adi_connect,
+ .disconnect = adi_disconnect,
};
-int __init adi_init(void)
+static int __init adi_init(void)
{
- gameport_register_device(&adi_dev);
+ gameport_register_driver(&adi_drv);
return 0;
}
-void __exit adi_exit(void)
+static void __exit adi_exit(void)
{
- gameport_unregister_device(&adi_dev);
+ gameport_unregister_driver(&adi_drv);
}
module_init(adi_init);
diff --git a/drivers/input/joystick/analog.c b/drivers/input/joystick/analog.c
index df7b2aadbf861..504b7d5505671 100644
--- a/drivers/input/joystick/analog.c
+++ b/drivers/input/joystick/analog.c
@@ -40,8 +40,10 @@
#include <linux/gameport.h>
#include <asm/timex.h>
+#define DRIVER_DESC "Analog joystick and gamepad driver"
+
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
-MODULE_DESCRIPTION("Analog joystick and gamepad driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
/*
@@ -88,7 +90,6 @@ __obsolete_setup("js=");
#define ANALOG_MAX_TIME 3 /* 3 ms */
#define ANALOG_LOOP_TIME 2000 /* 2 * loop */
-#define ANALOG_REFRESH_TIME HZ/100 /* 10 ms */
#define ANALOG_SAITEK_DELAY 200 /* 200 us */
#define ANALOG_SAITEK_TIME 2000 /* 2000 us */
#define ANALOG_AXIS_TIME 2 /* 2 * refresh */
@@ -119,7 +120,6 @@ struct analog {
struct analog_port {
struct gameport *gameport;
- struct timer_list timer;
struct analog analog[2];
unsigned char mask;
char saitek;
@@ -132,7 +132,6 @@ struct analog_port {
int axes[4];
int buttons;
int initial[4];
- int used;
int axtime;
};
@@ -305,12 +304,12 @@ static int analog_button_read(struct analog_port *port, char saitek, char chf)
}
/*
- * analog_timer() repeatedly polls the Analog joysticks.
+ * analog_poll() repeatedly polls the Analog joysticks.
*/
-static void analog_timer(unsigned long data)
+static void analog_poll(struct gameport *gameport)
{
- struct analog_port *port = (void *) data;
+ struct analog_port *port = gameport_get_drvdata(gameport);
int i;
char saitek = !!(port->analog[0].mask & ANALOG_SAITEK);
@@ -336,8 +335,6 @@ static void analog_timer(unsigned long data)
for (i = 0; i < 2; i++)
if (port->analog[i].mask)
analog_decode(port->analog + i, port->axes, port->initial, port->buttons);
-
- mod_timer(&port->timer, jiffies + ANALOG_REFRESH_TIME);
}
/*
@@ -347,8 +344,8 @@ static void analog_timer(unsigned long data)
static int analog_open(struct input_dev *dev)
{
struct analog_port *port = dev->private;
- if (!port->used++)
- mod_timer(&port->timer, jiffies + ANALOG_REFRESH_TIME);
+
+ gameport_start_polling(port->gameport);
return 0;
}
@@ -359,8 +356,8 @@ static int analog_open(struct input_dev *dev)
static void analog_close(struct input_dev *dev)
{
struct analog_port *port = dev->private;
- if (!--port->used)
- del_timer(&port->timer);
+
+ gameport_stop_polling(port->gameport);
}
/*
@@ -379,7 +376,7 @@ static void analog_calibrate_timer(struct analog_port *port)
#ifdef FAKE_TIME
analog_faketime += 830;
#endif
- udelay(1000);
+ mdelay(1);
GET_TIME(t2);
GET_TIME(t3);
local_irq_restore(flags);
@@ -587,17 +584,15 @@ static int analog_init_masks(struct analog_port *port)
return -!(analog[0].mask || analog[1].mask);
}
-static int analog_init_port(struct gameport *gameport, struct gameport_dev *dev, struct analog_port *port)
+static int analog_init_port(struct gameport *gameport, struct gameport_driver *drv, struct analog_port *port)
{
int i, t, u, v;
- gameport->private = port;
port->gameport = gameport;
- init_timer(&port->timer);
- port->timer.data = (long) port;
- port->timer.function = analog_timer;
- if (!gameport_open(gameport, dev, GAMEPORT_MODE_RAW)) {
+ gameport_set_drvdata(gameport, port);
+
+ if (!gameport_open(gameport, drv, GAMEPORT_MODE_RAW)) {
analog_calibrate_timer(port);
@@ -608,7 +603,8 @@ static int analog_init_port(struct gameport *gameport, struct gameport_dev *dev,
port->fuzz = (port->speed * ANALOG_FUZZ_MAGIC) / port->loop / 1000 + ANALOG_FUZZ_BITS;
for (i = 0; i < ANALOG_INIT_RETRIES; i++) {
- if (!analog_cooked_read(port)) break;
+ if (!analog_cooked_read(port))
+ break;
msleep(ANALOG_MAX_TIME);
}
@@ -617,11 +613,13 @@ static int analog_init_port(struct gameport *gameport, struct gameport_dev *dev,
msleep(ANALOG_MAX_TIME);
t = gameport_time(gameport, ANALOG_MAX_TIME * 1000);
gameport_trigger(gameport);
- while ((gameport_read(port->gameport) & port->mask) && (u < t)) u++;
+ while ((gameport_read(port->gameport) & port->mask) && (u < t))
+ u++;
udelay(ANALOG_SAITEK_DELAY);
t = gameport_time(gameport, ANALOG_SAITEK_TIME);
gameport_trigger(gameport);
- while ((gameport_read(port->gameport) & port->mask) && (v < t)) v++;
+ while ((gameport_read(port->gameport) & port->mask) && (v < t))
+ v++;
if (v < (u >> 1)) { /* FIXME - more than one port */
analog_options[0] |= /* FIXME - more than one port */
@@ -632,59 +630,66 @@ static int analog_init_port(struct gameport *gameport, struct gameport_dev *dev,
gameport_close(gameport);
}
- if (!gameport_open(gameport, dev, GAMEPORT_MODE_COOKED)) {
+ if (!gameport_open(gameport, drv, GAMEPORT_MODE_COOKED)) {
for (i = 0; i < ANALOG_INIT_RETRIES; i++)
if (!gameport_cooked_read(gameport, port->axes, &port->buttons))
break;
for (i = 0; i < 4; i++)
- if (port->axes[i] != -1) port->mask |= 1 << i;
+ if (port->axes[i] != -1)
+ port->mask |= 1 << i;
port->fuzz = gameport->fuzz;
port->cooked = 1;
return 0;
}
- if (!gameport_open(gameport, dev, GAMEPORT_MODE_RAW))
- return 0;
-
- return -1;
+ return gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
}
-static void analog_connect(struct gameport *gameport, struct gameport_dev *dev)
+static int analog_connect(struct gameport *gameport, struct gameport_driver *drv)
{
struct analog_port *port;
int i;
+ int err;
- if (!(port = kmalloc(sizeof(struct analog_port), GFP_KERNEL)))
- return;
- memset(port, 0, sizeof(struct analog_port));
+ if (!(port = kcalloc(1, sizeof(struct analog_port), GFP_KERNEL)))
+ return - ENOMEM;
- if (analog_init_port(gameport, dev, port)) {
+ err = analog_init_port(gameport, drv, port);
+ if (err) {
kfree(port);
- return;
+ return err;
}
- if (analog_init_masks(port)) {
+ err = analog_init_masks(port);
+ if (err) {
gameport_close(gameport);
+ gameport_set_drvdata(gameport, NULL);
kfree(port);
- return;
+ return err;
}
+ gameport_set_poll_handler(gameport, analog_poll);
+ gameport_set_poll_interval(gameport, 10);
+
for (i = 0; i < 2; i++)
if (port->analog[i].mask)
analog_init_device(port, port->analog + i, i);
+
+ return 0;
}
static void analog_disconnect(struct gameport *gameport)
{
int i;
+ struct analog_port *port = gameport_get_drvdata(gameport);
- struct analog_port *port = gameport->private;
for (i = 0; i < 2; i++)
if (port->analog[i].mask)
input_unregister_device(&port->analog[i].dev);
gameport_close(gameport);
+ gameport_set_drvdata(gameport, NULL);
printk(KERN_INFO "analog.c: %d out of %d reads (%d%%) on %s failed\n",
port->bads, port->reads, port->reads ? (port->bads * 100 / port->reads) : 0,
port->gameport->phys);
@@ -696,7 +701,7 @@ struct analog_types {
int value;
};
-struct analog_types analog_types[] = {
+static struct analog_types analog_types[] = {
{ "none", 0x00000000 },
{ "auto", 0x000000ff },
{ "2btn", 0x0000003f },
@@ -741,21 +746,26 @@ static void analog_parse_options(void)
* The gameport device structure.
*/
-static struct gameport_dev analog_dev = {
- .connect = analog_connect,
- .disconnect = analog_disconnect,
+static struct gameport_driver analog_drv = {
+ .driver = {
+ .name = "analog",
+ },
+ .description = DRIVER_DESC,
+ .connect = analog_connect,
+ .disconnect = analog_disconnect,
};
-int __init analog_init(void)
+static int __init analog_init(void)
{
analog_parse_options();
- gameport_register_device(&analog_dev);
+ gameport_register_driver(&analog_drv);
+
return 0;
}
-void __exit analog_exit(void)
+static void __exit analog_exit(void)
{
- gameport_unregister_device(&analog_dev);
+ gameport_unregister_driver(&analog_drv);
}
module_init(analog_init);
diff --git a/drivers/input/joystick/cobra.c b/drivers/input/joystick/cobra.c
index fc29ad79b3a4d..a6002205328f8 100644
--- a/drivers/input/joystick/cobra.c
+++ b/drivers/input/joystick/cobra.c
@@ -35,12 +35,13 @@
#include <linux/gameport.h>
#include <linux/input.h>
+#define DRIVER_DESC "Creative Labs Blaster GamePad Cobra driver"
+
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
-MODULE_DESCRIPTION("Creative Labs Blaster GamePad Cobra driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
#define COBRA_MAX_STROBE 45 /* 45 us max wait for first strobe */
-#define COBRA_REFRESH_TIME HZ/50 /* 20 ms between reads */
#define COBRA_LENGTH 36
static char* cobra_name = "Creative Labs Blaster GamePad Cobra";
@@ -49,9 +50,7 @@ static int cobra_btn[] = { BTN_START, BTN_SELECT, BTN_TL, BTN_TR, BTN_X, BTN_Y,
struct cobra {
struct gameport *gameport;
- struct timer_list timer;
struct input_dev dev[2];
- int used;
int reads;
int bads;
unsigned char exists;
@@ -112,18 +111,19 @@ static unsigned char cobra_read_packet(struct gameport *gameport, unsigned int *
return ret;
}
-static void cobra_timer(unsigned long private)
+static void cobra_poll(struct gameport *gameport)
{
- struct cobra *cobra = (void *) private;
+ struct cobra *cobra = gameport_get_drvdata(gameport);
struct input_dev *dev;
unsigned int data[2];
int i, j, r;
cobra->reads++;
- if ((r = cobra_read_packet(cobra->gameport, data)) != cobra->exists)
+ if ((r = cobra_read_packet(gameport, data)) != cobra->exists) {
cobra->bads++;
- else
+ return;
+ }
for (i = 0; i < 2; i++)
if (cobra->exists & r & (1 << i)) {
@@ -139,43 +139,39 @@ static void cobra_timer(unsigned long private)
input_sync(dev);
}
-
- mod_timer(&cobra->timer, jiffies + COBRA_REFRESH_TIME);
}
static int cobra_open(struct input_dev *dev)
{
struct cobra *cobra = dev->private;
- if (!cobra->used++)
- mod_timer(&cobra->timer, jiffies + COBRA_REFRESH_TIME);
+
+ gameport_start_polling(cobra->gameport);
return 0;
}
static void cobra_close(struct input_dev *dev)
{
struct cobra *cobra = dev->private;
- if (!--cobra->used)
- del_timer(&cobra->timer);
+
+ gameport_stop_polling(cobra->gameport);
}
-static void cobra_connect(struct gameport *gameport, struct gameport_dev *dev)
+static int cobra_connect(struct gameport *gameport, struct gameport_driver *drv)
{
struct cobra *cobra;
unsigned int data[2];
int i, j;
+ int err;
- if (!(cobra = kmalloc(sizeof(struct cobra), GFP_KERNEL)))
- return;
- memset(cobra, 0, sizeof(struct cobra));
-
- gameport->private = cobra;
+ if (!(cobra = kcalloc(1, sizeof(struct cobra), GFP_KERNEL)))
+ return -ENOMEM;
cobra->gameport = gameport;
- init_timer(&cobra->timer);
- cobra->timer.data = (long) cobra;
- cobra->timer.function = cobra_timer;
- if (gameport_open(gameport, dev, GAMEPORT_MODE_RAW))
+ gameport_set_drvdata(gameport, cobra);
+
+ err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
+ if (err)
goto fail1;
cobra->exists = cobra_read_packet(gameport, data);
@@ -187,8 +183,13 @@ static void cobra_connect(struct gameport *gameport, struct gameport_dev *dev)
cobra->exists &= ~(1 << i);
}
- if (!cobra->exists)
+ if (!cobra->exists) {
+ err = -ENODEV;
goto fail2;
+ }
+
+ gameport_set_poll_handler(gameport, cobra_poll);
+ gameport_set_poll_interval(gameport, 20);
for (i = 0; i < 2; i++)
if ((cobra->exists >> i) & 1) {
@@ -207,49 +208,56 @@ static void cobra_connect(struct gameport *gameport, struct gameport_dev *dev)
cobra->dev[i].id.version = 0x0100;
cobra->dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
- cobra->dev[i].absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
+
+ input_set_abs_params(&cobra->dev[i], ABS_X, -1, 1, 0, 0);
+ input_set_abs_params(&cobra->dev[i], ABS_Y, -1, 1, 0, 0);
for (j = 0; cobra_btn[j]; j++)
set_bit(cobra_btn[j], cobra->dev[i].keybit);
- cobra->dev[i].absmin[ABS_X] = -1; cobra->dev[i].absmax[ABS_X] = 1;
- cobra->dev[i].absmin[ABS_Y] = -1; cobra->dev[i].absmax[ABS_Y] = 1;
-
- input_register_device(cobra->dev + i);
+ input_register_device(&cobra->dev[i]);
printk(KERN_INFO "input: %s on %s\n", cobra_name, gameport->phys);
}
- return;
+ return 0;
+
fail2: gameport_close(gameport);
-fail1: kfree(cobra);
+fail1: gameport_set_drvdata(gameport, NULL);
+ kfree(cobra);
+ return err;
}
static void cobra_disconnect(struct gameport *gameport)
{
+ struct cobra *cobra = gameport_get_drvdata(gameport);
int i;
- struct cobra *cobra = gameport->private;
for (i = 0; i < 2; i++)
if ((cobra->exists >> i) & 1)
input_unregister_device(cobra->dev + i);
gameport_close(gameport);
+ gameport_set_drvdata(gameport, NULL);
kfree(cobra);
}
-static struct gameport_dev cobra_dev = {
- .connect = cobra_connect,
- .disconnect = cobra_disconnect,
+static struct gameport_driver cobra_drv = {
+ .driver = {
+ .name = "cobra",
+ },
+ .description = DRIVER_DESC,
+ .connect = cobra_connect,
+ .disconnect = cobra_disconnect,
};
-int __init cobra_init(void)
+static int __init cobra_init(void)
{
- gameport_register_device(&cobra_dev);
+ gameport_register_driver(&cobra_drv);
return 0;
}
-void __exit cobra_exit(void)
+static void __exit cobra_exit(void)
{
- gameport_unregister_device(&cobra_dev);
+ gameport_unregister_driver(&cobra_drv);
}
module_init(cobra_init);
diff --git a/drivers/input/joystick/db9.c b/drivers/input/joystick/db9.c
index c5c6115dc4c5c..cfdd3acf06a1c 100644
--- a/drivers/input/joystick/db9.c
+++ b/drivers/input/joystick/db9.c
@@ -619,7 +619,7 @@ static struct db9 __init *db9_probe(int *config, int nargs)
return db9;
}
-int __init db9_init(void)
+static int __init db9_init(void)
{
db9_base[0] = db9_probe(db9, db9_nargs);
db9_base[1] = db9_probe(db9_2, db9_nargs_2);
@@ -631,7 +631,7 @@ int __init db9_init(void)
return -ENODEV;
}
-void __exit db9_exit(void)
+static void __exit db9_exit(void)
{
int i, j;
diff --git a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c
index e3f048b65bfc8..8732f52bdd088 100644
--- a/drivers/input/joystick/gamecon.c
+++ b/drivers/input/joystick/gamecon.c
@@ -227,7 +227,8 @@ static void gc_multi_read_packet(struct gc *gc, int length, unsigned char *data)
*/
#define GC_PSX_DELAY 25 /* 25 usec */
-#define GC_PSX_LENGTH 8 /* talk to the controller in bytes */
+#define GC_PSX_LENGTH 8 /* talk to the controller in bits */
+#define GC_PSX_BYTES 6 /* the maximum number of bytes to read off the controller */
#define GC_PSX_MOUSE 1 /* Mouse */
#define GC_PSX_NEGCON 2 /* NegCon */
@@ -241,7 +242,7 @@ static void gc_multi_read_packet(struct gc *gc, int length, unsigned char *data)
#define GC_PSX_SELECT 0x02 /* Pin 3 */
#define GC_PSX_ID(x) ((x) >> 4) /* High nibble is device type */
-#define GC_PSX_LEN(x) ((x) & 0xf) /* Low nibble is length in words */
+#define GC_PSX_LEN(x) (((x) & 0xf) << 1) /* Low nibble is length in bytes/2 */
static int gc_psx_delay = GC_PSX_DELAY;
module_param_named(psx_delay, gc_psx_delay, uint, 0);
@@ -259,13 +260,13 @@ static short gc_psx_ddr_btn[] = { BTN_0, BTN_1, BTN_2, BTN_3 };
* the psx pad.
*/
-static void gc_psx_command(struct gc *gc, int b, unsigned char data[GC_PSX_LENGTH])
+static void gc_psx_command(struct gc *gc, int b, unsigned char data[5])
{
int i, j, cmd, read;
for (i = 0; i < 5; i++)
data[i] = 0;
- for (i = 0; i < 8; i++, b >>= 1) {
+ for (i = 0; i < GC_PSX_LENGTH; i++, b >>= 1) {
cmd = (b & 1) ? GC_PSX_COMMAND : 0;
parport_write_data(gc->pd->port, cmd | GC_PSX_POWER);
udelay(gc_psx_delay);
@@ -282,7 +283,7 @@ static void gc_psx_command(struct gc *gc, int b, unsigned char data[GC_PSX_LENGT
* device identifier code.
*/
-static void gc_psx_read_packet(struct gc *gc, unsigned char data[5][GC_PSX_LENGTH], unsigned char id[5])
+static void gc_psx_read_packet(struct gc *gc, unsigned char data[5][GC_PSX_BYTES], unsigned char id[5])
{
int i, j, max_len = 0;
unsigned long flags;
@@ -300,10 +301,12 @@ static void gc_psx_read_packet(struct gc *gc, unsigned char data[5][GC_PSX_LENGT
gc_psx_command(gc, 0, data2); /* Dump status */
for (i =0; i < 5; i++) /* Find the longest pad */
- if((gc_status_bit[i] & (gc->pads[GC_PSX] | gc->pads[GC_DDR])) && (GC_PSX_LEN(id[i]) > max_len))
+ if((gc_status_bit[i] & (gc->pads[GC_PSX] | gc->pads[GC_DDR]))
+ && (GC_PSX_LEN(id[i]) > max_len)
+ && (GC_PSX_LEN(id[i]) <= GC_PSX_BYTES))
max_len = GC_PSX_LEN(id[i]);
- for (i = 0; i < max_len * 2; i++) { /* Read in all the data */
+ for (i = 0; i < max_len; i++) { /* Read in all the data */
gc_psx_command(gc, 0, data2);
for (j = 0; j < 5; j++)
data[j][i] = data2[j];
@@ -328,7 +331,7 @@ static void gc_timer(unsigned long private)
struct gc *gc = (void *) private;
struct input_dev *dev = gc->dev;
unsigned char data[GC_MAX_LENGTH];
- unsigned char data_psx[5][GC_PSX_LENGTH];
+ unsigned char data_psx[5][GC_PSX_BYTES];
int i, j, s;
/*
@@ -665,7 +668,7 @@ static struct gc __init *gc_probe(int *config, int nargs)
return gc;
}
-int __init gc_init(void)
+static int __init gc_init(void)
{
gc_base[0] = gc_probe(gc, gc_nargs);
gc_base[1] = gc_probe(gc_2, gc_nargs_2);
@@ -677,7 +680,7 @@ int __init gc_init(void)
return -ENODEV;
}
-void __exit gc_exit(void)
+static void __exit gc_exit(void)
{
int i, j;
diff --git a/drivers/input/joystick/gf2k.c b/drivers/input/joystick/gf2k.c
index 10cc6ca9cecdf..ad13f09a4e710 100644
--- a/drivers/input/joystick/gf2k.c
+++ b/drivers/input/joystick/gf2k.c
@@ -36,15 +36,16 @@
#include <linux/input.h>
#include <linux/gameport.h>
+#define DRIVER_DESC "Genius Flight 2000 joystick driver"
+
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
-MODULE_DESCRIPTION("Genius Flight 2000 joystick driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
#define GF2K_START 400 /* The time we wait for the first bit [400 us] */
#define GF2K_STROBE 40 /* The time we wait for the first bit [40 us] */
#define GF2K_TIMEOUT 4 /* Wait for everything to settle [4 ms] */
#define GF2K_LENGTH 80 /* Max number of triplets in a packet */
-#define GF2K_REFRESH HZ/50 /* Time between joystick polls [20 ms] */
/*
* Genius joystick ids ...
@@ -80,11 +81,9 @@ static short gf2k_seq_digital[] = { 590, 320, 860, 0 };
struct gf2k {
struct gameport *gameport;
- struct timer_list timer;
struct input_dev dev;
int reads;
int bads;
- int used;
unsigned char id;
unsigned char length;
char phys[32];
@@ -202,60 +201,56 @@ static void gf2k_read(struct gf2k *gf2k, unsigned char *data)
}
/*
- * gf2k_timer() reads and analyzes Genius joystick data.
+ * gf2k_poll() reads and analyzes Genius joystick data.
*/
-static void gf2k_timer(unsigned long private)
+static void gf2k_poll(struct gameport *gameport)
{
- struct gf2k *gf2k = (void *) private;
+ struct gf2k *gf2k = gameport_get_drvdata(gameport);
unsigned char data[GF2K_LENGTH];
gf2k->reads++;
- if (gf2k_read_packet(gf2k->gameport, gf2k_length[gf2k->id], data) < gf2k_length[gf2k->id]) {
+ if (gf2k_read_packet(gf2k->gameport, gf2k_length[gf2k->id], data) < gf2k_length[gf2k->id])
gf2k->bads++;
- } else gf2k_read(gf2k, data);
-
- mod_timer(&gf2k->timer, jiffies + GF2K_REFRESH);
+ else
+ gf2k_read(gf2k, data);
}
static int gf2k_open(struct input_dev *dev)
{
struct gf2k *gf2k = dev->private;
- if (!gf2k->used++)
- mod_timer(&gf2k->timer, jiffies + GF2K_REFRESH);
+
+ gameport_start_polling(gf2k->gameport);
return 0;
}
static void gf2k_close(struct input_dev *dev)
{
struct gf2k *gf2k = dev->private;
- if (!--gf2k->used)
- del_timer(&gf2k->timer);
+
+ gameport_stop_polling(gf2k->gameport);
}
/*
* gf2k_connect() probes for Genius id joysticks.
*/
-static void gf2k_connect(struct gameport *gameport, struct gameport_dev *dev)
+static int gf2k_connect(struct gameport *gameport, struct gameport_driver *drv)
{
struct gf2k *gf2k;
unsigned char data[GF2K_LENGTH];
- int i;
-
- if (!(gf2k = kmalloc(sizeof(struct gf2k), GFP_KERNEL)))
- return;
- memset(gf2k, 0, sizeof(struct gf2k));
+ int i, err;
- gameport->private = gf2k;
+ if (!(gf2k = kcalloc(1, sizeof(struct gf2k), GFP_KERNEL)))
+ return -ENOMEM;
gf2k->gameport = gameport;
- init_timer(&gf2k->timer);
- gf2k->timer.data = (long) gf2k;
- gf2k->timer.function = gf2k_timer;
- if (gameport_open(gameport, dev, GAMEPORT_MODE_RAW))
+ gameport_set_drvdata(gameport, gf2k);
+
+ err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
+ if (err)
goto fail1;
gf2k_trigger_seq(gameport, gf2k_seq_reset);
@@ -266,16 +261,22 @@ static void gf2k_connect(struct gameport *gameport, struct gameport_dev *dev)
msleep(GF2K_TIMEOUT);
- if (gf2k_read_packet(gameport, GF2K_LENGTH, data) < 12)
+ if (gf2k_read_packet(gameport, GF2K_LENGTH, data) < 12) {
+ err = -ENODEV;
goto fail2;
+ }
- if (!(gf2k->id = GB(7,2,0) | GB(3,3,2) | GB(0,3,5)))
+ if (!(gf2k->id = GB(7,2,0) | GB(3,3,2) | GB(0,3,5))) {
+ err = -ENODEV;
goto fail2;
+ }
#ifdef RESET_WORKS
if ((gf2k->id != (GB(19,2,0) | GB(15,3,2) | GB(12,3,5))) ||
- (gf2k->id != (GB(31,2,0) | GB(27,3,2) | GB(24,3,5))))
+ (gf2k->id != (GB(31,2,0) | GB(27,3,2) | GB(24,3,5)))) {
+ err = -ENODEV;
goto fail2;
+ }
#else
gf2k->id = 6;
#endif
@@ -283,9 +284,13 @@ static void gf2k_connect(struct gameport *gameport, struct gameport_dev *dev)
if (gf2k->id > GF2K_ID_MAX || !gf2k_axes[gf2k->id]) {
printk(KERN_WARNING "gf2k.c: Not yet supported joystick on %s. [id: %d type:%s]\n",
gameport->phys, gf2k->id, gf2k->id > GF2K_ID_MAX ? "Unknown" : gf2k_names[gf2k->id]);
+ err = -ENODEV;
goto fail2;
}
+ gameport_set_poll_handler(gameport, gf2k_poll);
+ gameport_set_poll_interval(gameport, 20);
+
sprintf(gf2k->phys, "%s/input0", gameport->phys);
gf2k->length = gf2k_lens[gf2k->id];
@@ -333,33 +338,42 @@ static void gf2k_connect(struct gameport *gameport, struct gameport_dev *dev)
input_register_device(&gf2k->dev);
printk(KERN_INFO "input: %s on %s\n", gf2k_names[gf2k->id], gameport->phys);
- return;
+ return 0;
+
fail2: gameport_close(gameport);
-fail1: kfree(gf2k);
+fail1: gameport_set_drvdata(gameport, NULL);
+ kfree(gf2k);
+ return err;
}
static void gf2k_disconnect(struct gameport *gameport)
{
- struct gf2k *gf2k = gameport->private;
+ struct gf2k *gf2k = gameport_get_drvdata(gameport);
+
input_unregister_device(&gf2k->dev);
gameport_close(gameport);
+ gameport_set_drvdata(gameport, NULL);
kfree(gf2k);
}
-static struct gameport_dev gf2k_dev = {
- .connect = gf2k_connect,
- .disconnect = gf2k_disconnect,
+static struct gameport_driver gf2k_drv = {
+ .driver = {
+ .name = "gf2k",
+ },
+ .description = DRIVER_DESC,
+ .connect = gf2k_connect,
+ .disconnect = gf2k_disconnect,
};
-int __init gf2k_init(void)
+static int __init gf2k_init(void)
{
- gameport_register_device(&gf2k_dev);
+ gameport_register_driver(&gf2k_drv);
return 0;
}
-void __exit gf2k_exit(void)
+static void __exit gf2k_exit(void)
{
- gameport_unregister_device(&gf2k_dev);
+ gameport_unregister_driver(&gf2k_drv);
}
module_init(gf2k_init);
diff --git a/drivers/input/joystick/grip.c b/drivers/input/joystick/grip.c
index cd2bb5d623c19..d1500d2562d67 100644
--- a/drivers/input/joystick/grip.c
+++ b/drivers/input/joystick/grip.c
@@ -35,8 +35,10 @@
#include <linux/gameport.h>
#include <linux/input.h>
+#define DRIVER_DESC "Gravis GrIP protocol joystick driver"
+
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
-MODULE_DESCRIPTION("Gravis GrIP protocol joystick driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
#define GRIP_MODE_GPP 1
@@ -51,14 +53,10 @@ MODULE_LICENSE("GPL");
#define GRIP_MAX_CHUNKS_XT 10
#define GRIP_MAX_BITS_XT 30
-#define GRIP_REFRESH_TIME HZ/50 /* 20 ms */
-
struct grip {
struct gameport *gameport;
- struct timer_list timer;
struct input_dev dev[2];
unsigned char mode[2];
- int used;
int reads;
int bads;
char phys[2][32];
@@ -183,9 +181,9 @@ static int grip_xt_read_packet(struct gameport *gameport, int shift, unsigned in
* grip_timer() repeatedly polls the joysticks and generates events.
*/
-static void grip_timer(unsigned long private)
+static void grip_poll(struct gameport *gameport)
{
- struct grip *grip = (void*) private;
+ struct grip *grip = gameport_get_drvdata(gameport);
unsigned int data[GRIP_LENGTH_XT];
struct input_dev *dev;
int i, j;
@@ -279,43 +277,39 @@ static void grip_timer(unsigned long private)
input_sync(dev);
}
-
- mod_timer(&grip->timer, jiffies + GRIP_REFRESH_TIME);
}
static int grip_open(struct input_dev *dev)
{
struct grip *grip = dev->private;
- if (!grip->used++)
- mod_timer(&grip->timer, jiffies + GRIP_REFRESH_TIME);
+
+ gameport_start_polling(grip->gameport);
return 0;
}
static void grip_close(struct input_dev *dev)
{
struct grip *grip = dev->private;
- if (!--grip->used)
- del_timer(&grip->timer);
+
+ gameport_stop_polling(grip->gameport);
}
-static void grip_connect(struct gameport *gameport, struct gameport_dev *dev)
+static int grip_connect(struct gameport *gameport, struct gameport_driver *drv)
{
struct grip *grip;
unsigned int data[GRIP_LENGTH_XT];
int i, j, t;
+ int err;
- if (!(grip = kmalloc(sizeof(struct grip), GFP_KERNEL)))
- return;
- memset(grip, 0, sizeof(struct grip));
-
- gameport->private = grip;
+ if (!(grip = kcalloc(1, sizeof(struct grip), GFP_KERNEL)))
+ return -ENOMEM;
grip->gameport = gameport;
- init_timer(&grip->timer);
- grip->timer.data = (long) grip;
- grip->timer.function = grip_timer;
- if (gameport_open(gameport, dev, GAMEPORT_MODE_RAW))
+ gameport_set_drvdata(gameport, grip);
+
+ err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
+ if (err)
goto fail1;
for (i = 0; i < 2; i++) {
@@ -337,8 +331,13 @@ static void grip_connect(struct gameport *gameport, struct gameport_dev *dev)
}
}
- if (!grip->mode[0] && !grip->mode[1])
+ if (!grip->mode[0] && !grip->mode[1]) {
+ err = -ENODEV;
goto fail2;
+ }
+
+ gameport_set_poll_handler(gameport, grip_poll);
+ gameport_set_poll_interval(gameport, 20);
for (i = 0; i < 2; i++)
if (grip->mode[i]) {
@@ -361,68 +360,62 @@ static void grip_connect(struct gameport *gameport, struct gameport_dev *dev)
for (j = 0; (t = grip_abs[grip->mode[i]][j]) >= 0; j++) {
- set_bit(t, grip->dev[i].absbit);
-
- if (j < grip_cen[grip->mode[i]]) {
- grip->dev[i].absmin[t] = 14;
- grip->dev[i].absmax[t] = 52;
- grip->dev[i].absfuzz[t] = 1;
- grip->dev[i].absflat[t] = 2;
- continue;
- }
-
- if (j < grip_anx[grip->mode[i]]) {
- grip->dev[i].absmin[t] = 3;
- grip->dev[i].absmax[t] = 57;
- grip->dev[i].absfuzz[t] = 1;
- continue;
- }
-
- grip->dev[i].absmin[t] = -1;
- grip->dev[i].absmax[t] = 1;
+ if (j < grip_cen[grip->mode[i]])
+ input_set_abs_params(&grip->dev[i], t, 14, 52, 1, 2);
+ else if (j < grip_anx[grip->mode[i]])
+ input_set_abs_params(&grip->dev[i], t, 3, 57, 1, 0);
+ else
+ input_set_abs_params(&grip->dev[i], t, -1, 1, 0, 0);
}
for (j = 0; (t = grip_btn[grip->mode[i]][j]) >= 0; j++)
if (t > 0)
set_bit(t, grip->dev[i].keybit);
- input_register_device(grip->dev + i);
-
printk(KERN_INFO "input: %s on %s\n",
grip_name[grip->mode[i]], gameport->phys);
+ input_register_device(grip->dev + i);
}
- return;
+ return 0;
+
fail2: gameport_close(gameport);
-fail1: kfree(grip);
+fail1: gameport_set_drvdata(gameport, NULL);
+ kfree(grip);
+ return err;
}
static void grip_disconnect(struct gameport *gameport)
{
+ struct grip *grip = gameport_get_drvdata(gameport);
int i;
- struct grip *grip = gameport->private;
for (i = 0; i < 2; i++)
if (grip->mode[i])
input_unregister_device(grip->dev + i);
gameport_close(gameport);
+ gameport_set_drvdata(gameport, NULL);
kfree(grip);
}
-static struct gameport_dev grip_dev = {
- .connect = grip_connect,
- .disconnect = grip_disconnect,
+static struct gameport_driver grip_drv = {
+ .driver = {
+ .name = "grip",
+ },
+ .description = DRIVER_DESC,
+ .connect = grip_connect,
+ .disconnect = grip_disconnect,
};
-int __init grip_init(void)
+static int __init grip_init(void)
{
- gameport_register_device(&grip_dev);
+ gameport_register_driver(&grip_drv);
return 0;
}
-void __exit grip_exit(void)
+static void __exit grip_exit(void)
{
- gameport_unregister_device(&grip_dev);
+ gameport_unregister_driver(&grip_drv);
}
module_init(grip_init);
diff --git a/drivers/input/joystick/grip_mp.c b/drivers/input/joystick/grip_mp.c
index 849d0de043b88..42e5005d621f2 100644
--- a/drivers/input/joystick/grip_mp.c
+++ b/drivers/input/joystick/grip_mp.c
@@ -20,8 +20,10 @@
#include <linux/delay.h>
#include <linux/proc_fs.h>
+#define DRIVER_DESC "Gravis Grip Multiport driver"
+
MODULE_AUTHOR("Brian Bonnlander");
-MODULE_DESCRIPTION("Gravis Grip Multiport driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
#ifdef GRIP_DEBUG
@@ -36,11 +38,9 @@ MODULE_LICENSE("GPL");
struct grip_mp {
struct gameport *gameport;
- struct timer_list timer;
struct input_dev dev[4];
int mode[4];
int registered[4];
- int used;
int reads;
int bads;
@@ -79,7 +79,6 @@ struct grip_mp {
*/
#define GRIP_INIT_DELAY 2000 /* 2 ms */
-#define GRIP_REFRESH_TIME HZ/50 /* 20 ms */
#define GRIP_MODE_NONE 0
#define GRIP_MODE_RESET 1
@@ -477,9 +476,9 @@ static int multiport_init(struct grip_mp *grip)
}
if (dig_mode)
- dbg("multiport_init(): digital mode achieved.\n");
+ dbg("multiport_init(): digital mode activated.\n");
else {
- dbg("multiport_init(): unable to achieve digital mode.\n");
+ dbg("multiport_init(): unable to activate digital mode.\n");
return 0;
}
@@ -524,8 +523,9 @@ static void report_slot(struct grip_mp *grip, int slot)
* Get the multiport state.
*/
-static void get_and_report_mp_state(struct grip_mp *grip)
+static void grip_poll(struct gameport *gameport)
{
+ struct grip_mp *grip = gameport_get_drvdata(gameport);
int i, npkts, flags;
for (npkts = 0; npkts < 4; npkts++) {
@@ -551,8 +551,8 @@ static void get_and_report_mp_state(struct grip_mp *grip)
static int grip_open(struct input_dev *dev)
{
struct grip_mp *grip = dev->private;
- if (!grip->used++)
- mod_timer(&grip->timer, jiffies + GRIP_REFRESH_TIME);
+
+ gameport_start_polling(grip->gameport);
return 0;
}
@@ -563,8 +563,8 @@ static int grip_open(struct input_dev *dev)
static void grip_close(struct input_dev *dev)
{
struct grip_mp *grip = dev->private;
- if (!--grip->used)
- del_timer(&grip->timer);
+
+ gameport_start_polling(grip->gameport);
}
/*
@@ -585,11 +585,8 @@ static void register_slot(int slot, struct grip_mp *grip)
grip->dev[slot].id.version = 0x0100;
grip->dev[slot].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
- for (j = 0; (t = grip_abs[grip->mode[slot]][j]) >= 0; j++) {
- set_bit(t, grip->dev[slot].absbit);
- grip->dev[slot].absmin[t] = -1;
- grip->dev[slot].absmax[t] = 1;
- }
+ for (j = 0; (t = grip_abs[grip->mode[slot]][j]) >= 0; j++)
+ input_set_abs_params(&grip->dev[slot], t, -1, 1, 0, 0);
for (j = 0; (t = grip_btn[grip->mode[slot]][j]) >= 0; j++)
if (t > 0)
@@ -605,69 +602,75 @@ static void register_slot(int slot, struct grip_mp *grip)
grip_name[grip->mode[slot]], slot);
}
-/*
- * Repeatedly polls the multiport and generates events.
- */
-
-static void grip_timer(unsigned long private)
-{
- struct grip_mp *grip = (void*) private;
- get_and_report_mp_state(grip);
- mod_timer(&grip->timer, jiffies + GRIP_REFRESH_TIME);
-}
-
-static void grip_connect(struct gameport *gameport, struct gameport_dev *dev)
+static int grip_connect(struct gameport *gameport, struct gameport_driver *drv)
{
struct grip_mp *grip;
+ int err;
+
+ if (!(grip = kcalloc(1, sizeof(struct grip_mp), GFP_KERNEL)))
+ return -ENOMEM;
- if (!(grip = kmalloc(sizeof(struct grip_mp), GFP_KERNEL)))
- return;
- memset(grip, 0, sizeof(struct grip_mp));
- gameport->private = grip;
grip->gameport = gameport;
- init_timer(&grip->timer);
- grip->timer.data = (long) grip;
- grip->timer.function = grip_timer;
- if (gameport_open(gameport, dev, GAMEPORT_MODE_RAW))
+ gameport_set_drvdata(gameport, grip);
+
+ err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
+ if (err)
goto fail1;
- if (!multiport_init(grip))
+
+ gameport_set_poll_handler(gameport, grip_poll);
+ gameport_set_poll_interval(gameport, 20);
+
+ if (!multiport_init(grip)) {
+ err = -ENODEV;
goto fail2;
- if (!grip->mode[0] && !grip->mode[1] && /* nothing plugged in */
- !grip->mode[2] && !grip->mode[3])
+ }
+
+ if (!grip->mode[0] && !grip->mode[1] && !grip->mode[2] && !grip->mode[3]) {
+ /* nothing plugged in */
+ err = -ENODEV;
goto fail2;
- return;
+ }
+
+ return 0;
fail2: gameport_close(gameport);
-fail1: kfree(grip);
+fail1: gameport_set_drvdata(gameport, NULL);
+ kfree(grip);
+ return err;
}
static void grip_disconnect(struct gameport *gameport)
{
+ struct grip_mp *grip = gameport_get_drvdata(gameport);
int i;
- struct grip_mp *grip = gameport->private;
for (i = 0; i < 4; i++)
if (grip->registered[i])
input_unregister_device(grip->dev + i);
gameport_close(gameport);
+ gameport_set_drvdata(gameport, NULL);
kfree(grip);
}
-static struct gameport_dev grip_dev = {
+static struct gameport_driver grip_drv = {
+ .driver = {
+ .name = "grip_mp",
+ },
+ .description = DRIVER_DESC,
.connect = grip_connect,
.disconnect = grip_disconnect,
};
-static int grip_init(void)
+static int __init grip_init(void)
{
- gameport_register_device(&grip_dev);
+ gameport_register_driver(&grip_drv);
return 0;
}
-static void grip_exit(void)
+static void __exit grip_exit(void)
{
- gameport_unregister_device(&grip_dev);
+ gameport_unregister_driver(&grip_drv);
}
module_init(grip_init);
diff --git a/drivers/input/joystick/guillemot.c b/drivers/input/joystick/guillemot.c
index cfe8c6be1a5a0..f93da7bc082d0 100644
--- a/drivers/input/joystick/guillemot.c
+++ b/drivers/input/joystick/guillemot.c
@@ -36,14 +36,15 @@
#include <linux/gameport.h>
#include <linux/input.h>
+#define DRIVER_DESC "Guillemot Digital joystick driver"
+
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
-MODULE_DESCRIPTION("Guillemot Digital joystick driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
#define GUILLEMOT_MAX_START 600 /* 600 us */
#define GUILLEMOT_MAX_STROBE 60 /* 60 us */
#define GUILLEMOT_MAX_LENGTH 17 /* 17 bytes */
-#define GUILLEMOT_REFRESH_TIME HZ/50 /* 20 ms */
static short guillemot_abs_pad[] =
{ ABS_X, ABS_Y, ABS_THROTTLE, ABS_RUDDER, -1 };
@@ -67,8 +68,6 @@ struct guillemot_type {
struct guillemot {
struct gameport *gameport;
struct input_dev dev;
- struct timer_list timer;
- int used;
int bads;
int reads;
struct guillemot_type *type;
@@ -118,12 +117,12 @@ static int guillemot_read_packet(struct gameport *gameport, u8 *data)
}
/*
- * guillemot_timer() reads and analyzes Guillemot joystick data.
+ * guillemot_poll() reads and analyzes Guillemot joystick data.
*/
-static void guillemot_timer(unsigned long private)
+static void guillemot_poll(struct gameport *gameport)
{
- struct guillemot *guillemot = (struct guillemot *) private;
+ struct guillemot *guillemot = gameport_get_drvdata(gameport);
struct input_dev *dev = &guillemot->dev;
u8 data[GUILLEMOT_MAX_LENGTH];
int i;
@@ -148,8 +147,6 @@ static void guillemot_timer(unsigned long private)
}
input_sync(dev);
-
- mod_timer(&guillemot->timer, jiffies + GUILLEMOT_REFRESH_TIME);
}
/*
@@ -159,8 +156,8 @@ static void guillemot_timer(unsigned long private)
static int guillemot_open(struct input_dev *dev)
{
struct guillemot *guillemot = dev->private;
- if (!guillemot->used++)
- mod_timer(&guillemot->timer, jiffies + GUILLEMOT_REFRESH_TIME);
+
+ gameport_start_polling(guillemot->gameport);
return 0;
}
@@ -171,38 +168,38 @@ static int guillemot_open(struct input_dev *dev)
static void guillemot_close(struct input_dev *dev)
{
struct guillemot *guillemot = dev->private;
- if (!--guillemot->used)
- del_timer(&guillemot->timer);
+
+ gameport_stop_polling(guillemot->gameport);
}
/*
* guillemot_connect() probes for Guillemot joysticks.
*/
-static void guillemot_connect(struct gameport *gameport, struct gameport_dev *dev)
+static int guillemot_connect(struct gameport *gameport, struct gameport_driver *drv)
{
struct guillemot *guillemot;
u8 data[GUILLEMOT_MAX_LENGTH];
int i, t;
+ int err;
- if (!(guillemot = kmalloc(sizeof(struct guillemot), GFP_KERNEL)))
- return;
- memset(guillemot, 0, sizeof(struct guillemot));
-
- gameport->private = guillemot;
+ if (!(guillemot = kcalloc(1, sizeof(struct guillemot), GFP_KERNEL)))
+ return -ENOMEM;
guillemot->gameport = gameport;
- init_timer(&guillemot->timer);
- guillemot->timer.data = (long) guillemot;
- guillemot->timer.function = guillemot_timer;
- if (gameport_open(gameport, dev, GAMEPORT_MODE_RAW))
+ gameport_set_drvdata(gameport, guillemot);
+
+ err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
+ if (err)
goto fail1;
i = guillemot_read_packet(gameport, data);
- if (i != GUILLEMOT_MAX_LENGTH * 8 || data[0] != 0x55 || data[16] != 0xaa)
+ if (i != GUILLEMOT_MAX_LENGTH * 8 || data[0] != 0x55 || data[16] != 0xaa) {
+ err = -ENODEV;
goto fail2;
+ }
for (i = 0; guillemot_type[i].name; i++)
if (guillemot_type[i].id == data[11])
@@ -211,9 +208,13 @@ static void guillemot_connect(struct gameport *gameport, struct gameport_dev *de
if (!guillemot_type[i].name) {
printk(KERN_WARNING "guillemot.c: Unknown joystick on %s. [ %02x%02x:%04x, ver %d.%02d ]\n",
gameport->phys, data[12], data[13], data[11], data[14], data[15]);
+ err = -ENODEV;
goto fail2;
}
+ gameport_set_poll_handler(gameport, guillemot_poll);
+ gameport_set_poll_interval(gameport, 20);
+
sprintf(guillemot->phys, "%s/input0", gameport->phys);
guillemot->type = guillemot_type + i;
@@ -231,19 +232,13 @@ static void guillemot_connect(struct gameport *gameport, struct gameport_dev *de
guillemot->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
- for (i = 0; (t = guillemot->type->abs[i]) >= 0; i++) {
- set_bit(t, guillemot->dev.absbit);
- guillemot->dev.absmin[t] = 0;
- guillemot->dev.absmax[t] = 255;
- }
+ for (i = 0; (t = guillemot->type->abs[i]) >= 0; i++)
+ input_set_abs_params(&guillemot->dev, t, 0, 255, 0, 0);
- if (guillemot->type->hat)
- for (i = 0; i < 2; i++) {
- t = ABS_HAT0X + i;
- set_bit(t, guillemot->dev.absbit);
- guillemot->dev.absmin[t] = -1;
- guillemot->dev.absmax[t] = 1;
- }
+ if (guillemot->type->hat) {
+ input_set_abs_params(&guillemot->dev, ABS_HAT0X, -1, 1, 0, 0);
+ input_set_abs_params(&guillemot->dev, ABS_HAT0Y, -1, 1, 0, 0);
+ }
for (i = 0; (t = guillemot->type->btn[i]) >= 0; i++)
set_bit(t, guillemot->dev.keybit);
@@ -252,34 +247,42 @@ static void guillemot_connect(struct gameport *gameport, struct gameport_dev *de
printk(KERN_INFO "input: %s ver %d.%02d on %s\n",
guillemot->type->name, data[14], data[15], gameport->phys);
- return;
+ return 0;
+
fail2: gameport_close(gameport);
-fail1: kfree(guillemot);
+fail1: gameport_set_drvdata(gameport, NULL);
+ kfree(guillemot);
+ return err;
}
static void guillemot_disconnect(struct gameport *gameport)
{
- struct guillemot *guillemot = gameport->private;
+ struct guillemot *guillemot = gameport_get_drvdata(gameport);
+
printk(KERN_INFO "guillemot.c: Failed %d reads out of %d on %s\n", guillemot->reads, guillemot->bads, guillemot->phys);
input_unregister_device(&guillemot->dev);
gameport_close(gameport);
kfree(guillemot);
}
-static struct gameport_dev guillemot_dev = {
- .connect = guillemot_connect,
- .disconnect = guillemot_disconnect,
+static struct gameport_driver guillemot_drv = {
+ .driver = {
+ .name = "guillemot",
+ },
+ .description = DRIVER_DESC,
+ .connect = guillemot_connect,
+ .disconnect = guillemot_disconnect,
};
-int __init guillemot_init(void)
+static int __init guillemot_init(void)
{
- gameport_register_device(&guillemot_dev);
+ gameport_register_driver(&guillemot_drv);
return 0;
}
-void __exit guillemot_exit(void)
+static void __exit guillemot_exit(void)
{
- gameport_unregister_device(&guillemot_dev);
+ gameport_unregister_driver(&guillemot_drv);
}
module_init(guillemot_init);
diff --git a/drivers/input/joystick/iforce/iforce-serio.c b/drivers/input/joystick/iforce/iforce-serio.c
index 9422407c2acbc..11f51905cba78 100644
--- a/drivers/input/joystick/iforce/iforce-serio.c
+++ b/drivers/input/joystick/iforce/iforce-serio.c
@@ -75,13 +75,15 @@ again:
static void iforce_serio_write_wakeup(struct serio *serio)
{
- iforce_serial_xmit((struct iforce *)serio->private);
+ struct iforce *iforce = serio_get_drvdata(serio);
+
+ iforce_serial_xmit(iforce);
}
static irqreturn_t iforce_serio_irq(struct serio *serio,
unsigned char data, unsigned int flags, struct pt_regs *regs)
{
- struct iforce* iforce = serio->private;
+ struct iforce *iforce = serio_get_drvdata(serio);
if (!iforce->pkt) {
if (data == 0x2b)
@@ -124,45 +126,66 @@ out:
return IRQ_HANDLED;
}
-static void iforce_serio_connect(struct serio *serio, struct serio_driver *drv)
+static int iforce_serio_connect(struct serio *serio, struct serio_driver *drv)
{
struct iforce *iforce;
- if (serio->type != (SERIO_RS232 | SERIO_IFORCE))
- return;
+ int err;
+
+ if (!(iforce = kmalloc(sizeof(struct iforce), GFP_KERNEL)))
+ return -ENOMEM;
- if (!(iforce = kmalloc(sizeof(struct iforce), GFP_KERNEL))) return;
memset(iforce, 0, sizeof(struct iforce));
iforce->bus = IFORCE_232;
iforce->serio = serio;
- serio->private = iforce;
- if (serio_open(serio, drv)) {
+ serio_set_drvdata(serio, iforce);
+
+ err = serio_open(serio, drv);
+ if (err) {
+ serio_set_drvdata(serio, NULL);
kfree(iforce);
- return;
+ return err;
}
if (iforce_init_device(iforce)) {
serio_close(serio);
+ serio_set_drvdata(serio, NULL);
kfree(iforce);
- return;
+ return -ENODEV;
}
+
+ return 0;
}
static void iforce_serio_disconnect(struct serio *serio)
{
- struct iforce* iforce = serio->private;
+ struct iforce *iforce = serio_get_drvdata(serio);
input_unregister_device(&iforce->dev);
serio_close(serio);
+ serio_set_drvdata(serio, NULL);
kfree(iforce);
}
+static struct serio_device_id iforce_serio_ids[] = {
+ {
+ .type = SERIO_RS232,
+ .proto = SERIO_IFORCE,
+ .id = SERIO_ANY,
+ .extra = SERIO_ANY,
+ },
+ { 0 }
+};
+
+MODULE_DEVICE_TABLE(serio, iforce_serio_ids);
+
struct serio_driver iforce_serio_drv = {
.driver = {
.name = "iforce",
},
.description = "RS232 I-Force joysticks and wheels driver",
+ .id_table = iforce_serio_ids,
.write_wakeup = iforce_serio_write_wakeup,
.interrupt = iforce_serio_irq,
.connect = iforce_serio_connect,
diff --git a/drivers/input/joystick/interact.c b/drivers/input/joystick/interact.c
index b2d7cad81e406..9d3f8c38cb097 100644
--- a/drivers/input/joystick/interact.c
+++ b/drivers/input/joystick/interact.c
@@ -39,14 +39,15 @@
#include <linux/gameport.h>
#include <linux/input.h>
+#define DRIVER_DESC "InterAct digital joystick driver"
+
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
-MODULE_DESCRIPTION("InterAct digital joystick driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
-#define INTERACT_MAX_START 400 /* 400 us */
-#define INTERACT_MAX_STROBE 40 /* 40 us */
+#define INTERACT_MAX_START 600 /* 400 us */
+#define INTERACT_MAX_STROBE 60 /* 40 us */
#define INTERACT_MAX_LENGTH 32 /* 32 bits */
-#define INTERACT_REFRESH_TIME HZ/50 /* 20 ms */
#define INTERACT_TYPE_HHFX 0 /* HammerHead/FX */
#define INTERACT_TYPE_PP8D 1 /* ProPad 8 */
@@ -54,8 +55,6 @@ MODULE_LICENSE("GPL");
struct interact {
struct gameport *gameport;
struct input_dev dev;
- struct timer_list timer;
- int used;
int bads;
int reads;
unsigned char type;
@@ -125,12 +124,12 @@ static int interact_read_packet(struct gameport *gameport, int length, u32 *data
}
/*
- * interact_timer() reads and analyzes InterAct joystick data.
+ * interact_poll() reads and analyzes InterAct joystick data.
*/
-static void interact_timer(unsigned long private)
+static void interact_poll(struct gameport *gameport)
{
- struct interact *interact = (struct interact *) private;
+ struct interact *interact = gameport_get_drvdata(gameport);
struct input_dev *dev = &interact->dev;
u32 data[3];
int i;
@@ -177,9 +176,6 @@ static void interact_timer(unsigned long private)
}
input_sync(dev);
-
- mod_timer(&interact->timer, jiffies + INTERACT_REFRESH_TIME);
-
}
/*
@@ -189,8 +185,8 @@ static void interact_timer(unsigned long private)
static int interact_open(struct input_dev *dev)
{
struct interact *interact = dev->private;
- if (!interact->used++)
- mod_timer(&interact->timer, jiffies + INTERACT_REFRESH_TIME);
+
+ gameport_start_polling(interact->gameport);
return 0;
}
@@ -201,37 +197,36 @@ static int interact_open(struct input_dev *dev)
static void interact_close(struct input_dev *dev)
{
struct interact *interact = dev->private;
- if (!--interact->used)
- del_timer(&interact->timer);
+
+ gameport_stop_polling(interact->gameport);
}
/*
* interact_connect() probes for InterAct joysticks.
*/
-static void interact_connect(struct gameport *gameport, struct gameport_dev *dev)
+static int interact_connect(struct gameport *gameport, struct gameport_driver *drv)
{
struct interact *interact;
__u32 data[3];
int i, t;
+ int err;
- if (!(interact = kmalloc(sizeof(struct interact), GFP_KERNEL)))
- return;
- memset(interact, 0, sizeof(struct interact));
-
- gameport->private = interact;
+ if (!(interact = kcalloc(1, sizeof(struct interact), GFP_KERNEL)))
+ return -ENOMEM;
interact->gameport = gameport;
- init_timer(&interact->timer);
- interact->timer.data = (long) interact;
- interact->timer.function = interact_timer;
- if (gameport_open(gameport, dev, GAMEPORT_MODE_RAW))
+ gameport_set_drvdata(gameport, interact);
+
+ err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
+ if (err)
goto fail1;
i = interact_read_packet(gameport, INTERACT_MAX_LENGTH * 2, data);
if (i != 32 || (data[0] >> 24) != 0x0c || (data[1] >> 24) != 0x02) {
+ err = -ENODEV;
goto fail2;
}
@@ -242,9 +237,13 @@ static void interact_connect(struct gameport *gameport, struct gameport_dev *dev
if (!interact_type[i].length) {
printk(KERN_WARNING "interact.c: Unknown joystick on %s. [len %d d0 %08x d1 %08x i2 %08x]\n",
gameport->phys, i, data[0], data[1], data[2]);
+ err = -ENODEV;
goto fail2;
}
+ gameport_set_poll_handler(gameport, interact_poll);
+ gameport_set_poll_interval(gameport, 20);
+
sprintf(interact->phys, "%s/input0", gameport->phys);
interact->type = i;
@@ -281,33 +280,42 @@ static void interact_connect(struct gameport *gameport, struct gameport_dev *dev
printk(KERN_INFO "input: %s on %s\n",
interact_type[interact->type].name, gameport->phys);
- return;
+ return 0;
+
fail2: gameport_close(gameport);
-fail1: kfree(interact);
+fail1: gameport_set_drvdata(gameport, NULL);
+ kfree(interact);
+ return err;
}
static void interact_disconnect(struct gameport *gameport)
{
- struct interact *interact = gameport->private;
+ struct interact *interact = gameport_get_drvdata(gameport);
+
input_unregister_device(&interact->dev);
gameport_close(gameport);
+ gameport_set_drvdata(gameport, NULL);
kfree(interact);
}
-static struct gameport_dev interact_dev = {
- .connect = interact_connect,
- .disconnect = interact_disconnect,
+static struct gameport_driver interact_drv = {
+ .driver = {
+ .name = "interact",
+ },
+ .description = DRIVER_DESC,
+ .connect = interact_connect,
+ .disconnect = interact_disconnect,
};
-int __init interact_init(void)
+static int __init interact_init(void)
{
- gameport_register_device(&interact_dev);
+ gameport_register_driver(&interact_drv);
return 0;
}
-void __exit interact_exit(void)
+static void __exit interact_exit(void)
{
- gameport_unregister_device(&interact_dev);
+ gameport_unregister_driver(&interact_drv);
}
module_init(interact_init);
diff --git a/drivers/input/joystick/joydump.c b/drivers/input/joystick/joydump.c
index 15962a684dd7f..4234ccaf9146d 100644
--- a/drivers/input/joystick/joydump.c
+++ b/drivers/input/joystick/joydump.c
@@ -35,8 +35,10 @@
#include <linux/delay.h>
#include <linux/init.h>
+#define DRIVER_DESC "Gameport data dumper module"
+
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
-MODULE_DESCRIPTION("Gameport data dumper module");
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
#define BUF_SIZE 256
@@ -46,38 +48,46 @@ struct joydump {
unsigned char data;
};
-static void __devinit joydump_connect(struct gameport *gameport, struct gameport_dev *dev)
+static int joydump_connect(struct gameport *gameport, struct gameport_driver *drv)
{
- struct joydump buf[BUF_SIZE];
+ struct joydump *buf; /* all entries */
+ struct joydump *dump, *prev; /* one entry each */
int axes[4], buttons;
int i, j, t, timeout;
unsigned long flags;
unsigned char u;
- printk(KERN_INFO "joydump: ,------------------- START ------------------.\n");
- printk(KERN_INFO "joydump: | Dumping gameport%s.\n", gameport->phys);
- printk(KERN_INFO "joydump: | Speed: %4d kHz. |\n", gameport->speed);
+ printk(KERN_INFO "joydump: ,------------------ START ----------------.\n");
+ printk(KERN_INFO "joydump: | Dumping: %30s |\n", gameport->phys);
+ printk(KERN_INFO "joydump: | Speed: %28d kHz |\n", gameport->speed);
- if (gameport_open(gameport, dev, GAMEPORT_MODE_RAW)) {
+ if (gameport_open(gameport, drv, GAMEPORT_MODE_RAW)) {
printk(KERN_INFO "joydump: | Raw mode not available - trying cooked. |\n");
- if (gameport_open(gameport, dev, GAMEPORT_MODE_COOKED)) {
+ if (gameport_open(gameport, drv, GAMEPORT_MODE_COOKED)) {
- printk(KERN_INFO "joydump: | Cooked not available either. Failing. |\n");
- printk(KERN_INFO "joydump: `-------------------- END -------------------'\n");
- return;
+ printk(KERN_INFO "joydump: | Cooked not available either. Failing. |\n");
+ printk(KERN_INFO "joydump: `------------------- END -----------------'\n");
+ return -ENODEV;
}
gameport_cooked_read(gameport, axes, &buttons);
for (i = 0; i < 4; i++)
- printk(KERN_INFO "joydump: | Axis %d: %4d. |\n", i, axes[i]);
- printk(KERN_INFO "joydump: | Buttons %02x. |\n", buttons);
- printk(KERN_INFO "joydump: `-------------------- END -------------------'\n");
+ printk(KERN_INFO "joydump: | Axis %d: %4d. |\n", i, axes[i]);
+ printk(KERN_INFO "joydump: | Buttons %02x. |\n", buttons);
+ printk(KERN_INFO "joydump: `------------------- END -----------------'\n");
}
timeout = gameport_time(gameport, 10000); /* 10 ms */
+
+ buf = kmalloc(BUF_SIZE * sizeof(struct joydump), GFP_KERNEL);
+ if (!buf) {
+ printk(KERN_INFO "joydump: no memory for testing\n");
+ goto jd_end;
+ }
+ dump = buf;
t = 0;
i = 1;
@@ -85,19 +95,21 @@ static void __devinit joydump_connect(struct gameport *gameport, struct gameport
u = gameport_read(gameport);
- buf[0].data = u;
- buf[0].time = t;
+ dump->data = u;
+ dump->time = t;
+ dump++;
gameport_trigger(gameport);
while (i < BUF_SIZE && t < timeout) {
- buf[i].data = gameport_read(gameport);
+ dump->data = gameport_read(gameport);
- if (buf[i].data ^ u) {
- u = buf[i].data;
- buf[i].time = t;
+ if (dump->data ^ u) {
+ u = dump->data;
+ dump->time = t;
i++;
+ dump++;
}
t++;
}
@@ -109,42 +121,54 @@ static void __devinit joydump_connect(struct gameport *gameport, struct gameport
*/
t = i;
+ dump = buf;
+ prev = dump;
- printk(KERN_INFO "joydump: >------------------- DATA -------------------<\n");
- printk(KERN_INFO "joydump: | index: %3d delta: %3d.%02d us data: ", 0, 0, 0);
+ printk(KERN_INFO "joydump: >------------------ DATA -----------------<\n");
+ printk(KERN_INFO "joydump: | index: %3d delta: %3d us data: ", 0, 0);
for (j = 7; j >= 0; j--)
- printk("%d",(buf[0].data >> j) & 1);
+ printk("%d", (dump->data >> j) & 1);
printk(" |\n");
- for (i = 1; i < t; i++) {
+ dump++;
+
+ for (i = 1; i < t; i++, dump++, prev++) {
printk(KERN_INFO "joydump: | index: %3d delta: %3d us data: ",
- i, buf[i].time - buf[i-1].time);
+ i, dump->time - prev->time);
for (j = 7; j >= 0; j--)
- printk("%d",(buf[i].data >> j) & 1);
- printk(" |\n");
+ printk("%d", (dump->data >> j) & 1);
+ printk(" |\n");
}
+ kfree(buf);
+
+jd_end:
+ printk(KERN_INFO "joydump: `------------------- END -----------------'\n");
- printk(KERN_INFO "joydump: `-------------------- END -------------------'\n");
+ return 0;
}
-static void __devexit joydump_disconnect(struct gameport *gameport)
+static void joydump_disconnect(struct gameport *gameport)
{
gameport_close(gameport);
}
-static struct gameport_dev joydump_dev = {
- .connect = joydump_connect,
- .disconnect = joydump_disconnect,
+static struct gameport_driver joydump_drv = {
+ .driver = {
+ .name = "joydump",
+ },
+ .description = DRIVER_DESC,
+ .connect = joydump_connect,
+ .disconnect = joydump_disconnect,
};
static int __init joydump_init(void)
{
- gameport_register_device(&joydump_dev);
+ gameport_register_driver(&joydump_drv);
return 0;
}
static void __exit joydump_exit(void)
{
- gameport_unregister_device(&joydump_dev);
+ gameport_unregister_driver(&joydump_drv);
}
module_init(joydump_init);
diff --git a/drivers/input/joystick/magellan.c b/drivers/input/joystick/magellan.c
index 42b088614c8a5..1ba5036272422 100644
--- a/drivers/input/joystick/magellan.c
+++ b/drivers/input/joystick/magellan.c
@@ -118,7 +118,7 @@ static void magellan_process_packet(struct magellan* magellan, struct pt_regs *r
static irqreturn_t magellan_interrupt(struct serio *serio,
unsigned char data, unsigned int flags, struct pt_regs *regs)
{
- struct magellan* magellan = serio->private;
+ struct magellan* magellan = serio_get_drvdata(serio);
if (data == '\r') {
magellan_process_packet(magellan, regs);
@@ -136,28 +136,28 @@ static irqreturn_t magellan_interrupt(struct serio *serio,
static void magellan_disconnect(struct serio *serio)
{
- struct magellan* magellan = serio->private;
+ struct magellan* magellan = serio_get_drvdata(serio);
+
input_unregister_device(&magellan->dev);
serio_close(serio);
+ serio_set_drvdata(serio, NULL);
kfree(magellan);
}
/*
* magellan_connect() is the routine that is called when someone adds a
- * new serio device. It looks for the Magellan, and if found, registers
- * it as an input device.
+ * new serio device that supports Magellan protocol and registers it as
+ * an input device.
*/
-static void magellan_connect(struct serio *serio, struct serio_driver *drv)
+static int magellan_connect(struct serio *serio, struct serio_driver *drv)
{
struct magellan *magellan;
int i, t;
-
- if (serio->type != (SERIO_RS232 | SERIO_MAGELLAN))
- return;
+ int err;
if (!(magellan = kmalloc(sizeof(struct magellan), GFP_KERNEL)))
- return;
+ return -ENOMEM;
memset(magellan, 0, sizeof(struct magellan));
@@ -185,28 +185,44 @@ static void magellan_connect(struct serio *serio, struct serio_driver *drv)
magellan->dev.id.version = 0x0100;
magellan->dev.dev = &serio->dev;
- serio->private = magellan;
+ serio_set_drvdata(serio, magellan);
- if (serio_open(serio, drv)) {
+ err = serio_open(serio, drv);
+ if (err) {
+ serio_set_drvdata(serio, NULL);
kfree(magellan);
- return;
+ return err;
}
input_register_device(&magellan->dev);
printk(KERN_INFO "input: %s on %s\n", magellan_name, serio->phys);
+ return 0;
}
/*
- * The serio device structure.
+ * The serio driver structure.
*/
+static struct serio_device_id magellan_serio_ids[] = {
+ {
+ .type = SERIO_RS232,
+ .proto = SERIO_MAGELLAN,
+ .id = SERIO_ANY,
+ .extra = SERIO_ANY,
+ },
+ { 0 }
+};
+
+MODULE_DEVICE_TABLE(serio, magellan_serio_ids);
+
static struct serio_driver magellan_drv = {
.driver = {
.name = "magellan",
},
.description = DRIVER_DESC,
+ .id_table = magellan_serio_ids,
.interrupt = magellan_interrupt,
.connect = magellan_connect,
.disconnect = magellan_disconnect,
@@ -216,13 +232,13 @@ static struct serio_driver magellan_drv = {
* The functions for inserting/removing us as a module.
*/
-int __init magellan_init(void)
+static int __init magellan_init(void)
{
serio_register_driver(&magellan_drv);
return 0;
}
-void __exit magellan_exit(void)
+static void __exit magellan_exit(void)
{
serio_unregister_driver(&magellan_drv);
}
diff --git a/drivers/input/joystick/sidewinder.c b/drivers/input/joystick/sidewinder.c
index b29d576129f39..47144a7ed9e75 100644
--- a/drivers/input/joystick/sidewinder.c
+++ b/drivers/input/joystick/sidewinder.c
@@ -1,7 +1,5 @@
/*
- * $Id: sidewinder.c,v 1.29 2002/01/22 20:28:51 vojtech Exp $
- *
- * Copyright (c) 1998-2001 Vojtech Pavlik
+ * Copyright (c) 1998-2005 Vojtech Pavlik
*/
/*
@@ -36,8 +34,10 @@
#include <linux/input.h>
#include <linux/gameport.h>
+#define DRIVER_DESC "Microsoft SideWinder joystick family driver"
+
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
-MODULE_DESCRIPTION("Microsoft SideWinder joystick family driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
/*
@@ -45,18 +45,18 @@ MODULE_LICENSE("GPL");
* as well as break everything.
*/
-/* #define SW_DEBUG */
+#undef SW_DEBUG
+#undef SW_DEBUG_DATA
-#define SW_START 400 /* The time we wait for the first bit [400 us] */
-#define SW_STROBE 45 /* Max time per bit [45 us] */
-#define SW_TIMEOUT 4000 /* Wait for everything to settle [4 ms] */
+#define SW_START 600 /* The time we wait for the first bit [600 us] */
+#define SW_STROBE 60 /* Max time per bit [60 us] */
+#define SW_TIMEOUT 6 /* Wait for everything to settle [6 ms] */
#define SW_KICK 45 /* Wait after A0 fall till kick [45 us] */
#define SW_END 8 /* Number of bits before end of packet to kick */
#define SW_FAIL 16 /* Number of packet read errors to fail and reinitialize */
#define SW_BAD 2 /* Number of packet read errors to switch off 3d Pro optimization */
#define SW_OK 64 /* Number of packet read successes to switch optimization back on */
#define SW_LENGTH 512 /* Max number of bits in a packet */
-#define SW_REFRESH HZ/50 /* Time to wait between updates of joystick data [20 ms] */
#ifdef SW_DEBUG
#define dbg(format, arg...) printk(KERN_DEBUG __FILE__ ": " format "\n" , ## arg)
@@ -113,7 +113,6 @@ static struct {
struct sw {
struct gameport *gameport;
- struct timer_list timer;
struct input_dev dev[4];
char name[64];
char phys[4][32];
@@ -125,7 +124,6 @@ struct sw {
int ok;
int reads;
int bads;
- int used;
};
/*
@@ -141,7 +139,7 @@ static int sw_read_packet(struct gameport *gameport, unsigned char *buf, int len
unsigned char pending, u, v;
i = -id; /* Don't care about data, only want ID */
- timeout = id ? gameport_time(gameport, SW_TIMEOUT) : 0; /* Set up global timeout for ID packet */
+ timeout = id ? gameport_time(gameport, SW_TIMEOUT * 1000) : 0; /* Set up global timeout for ID packet */
kick = id ? gameport_time(gameport, SW_KICK) : 0; /* Set up kick timeout for ID packet */
start = gameport_time(gameport, SW_START);
strobe = gameport_time(gameport, SW_STROBE);
@@ -160,7 +158,8 @@ static int sw_read_packet(struct gameport *gameport, unsigned char *buf, int len
v = gameport_read(gameport);
} while (!(~v & u & 0x10) && (bitout > 0)); /* Wait for first falling edge on clock */
- if (bitout > 0) bitout = strobe; /* Extend time if not timed out */
+ if (bitout > 0)
+ bitout = strobe; /* Extend time if not timed out */
while ((timeout > 0 || bitout > 0) && (i < length)) {
@@ -194,7 +193,7 @@ static int sw_read_packet(struct gameport *gameport, unsigned char *buf, int len
local_irq_restore(flags); /* Done - relax */
-#ifdef SW_DEBUG
+#ifdef SW_DEBUG_DATA
{
int j;
printk(KERN_DEBUG "sidewinder.c: Read %d triplets. [", i);
@@ -249,7 +248,7 @@ static void sw_init_digital(struct gameport *gameport)
i = 0;
do {
gameport_trigger(gameport); /* Trigger */
- t = gameport_time(gameport, SW_TIMEOUT);
+ t = gameport_time(gameport, SW_TIMEOUT * 1000);
while ((gameport_read(gameport) & 1) && t) t--; /* Wait for axis to fall back to 0 */
udelay(seq[i]); /* Delay magic time */
} while (seq[++i]);
@@ -266,6 +265,7 @@ static void sw_init_digital(struct gameport *gameport)
static int sw_parity(__u64 t)
{
int x = t ^ (t >> 32);
+
x ^= x >> 16;
x ^= x >> 8;
x ^= x >> 4;
@@ -307,7 +307,8 @@ static int sw_parse(unsigned char *buf, struct sw *sw)
case SW_ID_3DP:
- if (sw_check(GB(0,64)) || (hat = (GB(6,1) << 3) | GB(60,3)) > 8) return -1;
+ if (sw_check(GB(0,64)) || (hat = (GB(6,1) << 3) | GB(60,3)) > 8)
+ return -1;
input_report_abs(dev, ABS_X, (GB( 3,3) << 7) | GB(16,7));
input_report_abs(dev, ABS_Y, (GB( 0,3) << 7) | GB(24,7));
@@ -331,7 +332,8 @@ static int sw_parse(unsigned char *buf, struct sw *sw)
for (i = 0; i < sw->number; i ++) {
- if (sw_parity(GB(i*15,15))) return -1;
+ if (sw_parity(GB(i*15,15)))
+ return -1;
input_report_abs(dev + i, ABS_X, GB(i*15+3,1) - GB(i*15+2,1));
input_report_abs(dev + i, ABS_Y, GB(i*15+0,1) - GB(i*15+1,1));
@@ -347,7 +349,8 @@ static int sw_parse(unsigned char *buf, struct sw *sw)
case SW_ID_PP:
case SW_ID_FFP:
- if (!sw_parity(GB(0,48)) || (hat = GB(42,4)) > 8) return -1;
+ if (!sw_parity(GB(0,48)) || (hat = GB(42,4)) > 8)
+ return -1;
input_report_abs(dev, ABS_X, GB( 9,10));
input_report_abs(dev, ABS_Y, GB(19,10));
@@ -366,7 +369,8 @@ static int sw_parse(unsigned char *buf, struct sw *sw)
case SW_ID_FSP:
- if (!sw_parity(GB(0,43)) || (hat = GB(28,4)) > 8) return -1;
+ if (!sw_parity(GB(0,43)) || (hat = GB(28,4)) > 8)
+ return -1;
input_report_abs(dev, ABS_X, GB( 0,10));
input_report_abs(dev, ABS_Y, GB(16,10));
@@ -389,7 +393,8 @@ static int sw_parse(unsigned char *buf, struct sw *sw)
case SW_ID_FFW:
- if (!sw_parity(GB(0,33))) return -1;
+ if (!sw_parity(GB(0,33)))
+ return -1;
input_report_abs(dev, ABS_RX, GB( 0,10));
input_report_abs(dev, ABS_RUDDER, GB(10, 6));
@@ -466,19 +471,20 @@ static int sw_read(struct sw *sw)
sw->length = 66;
}
- if (sw->fail < SW_FAIL) return -1; /* Not enough, don't reinitialize yet */
+ if (sw->fail < SW_FAIL)
+ return -1; /* Not enough, don't reinitialize yet */
printk(KERN_WARNING "sidewinder.c: Too many bit errors on %s"
" - reinitializing joystick.\n", sw->gameport->phys);
if (!i && sw->type == SW_ID_3DP) { /* 3D Pro can be in analog mode */
- udelay(3 * SW_TIMEOUT);
+ mdelay(3 * SW_TIMEOUT);
sw_init_digital(sw->gameport);
}
- udelay(SW_TIMEOUT);
+ mdelay(SW_TIMEOUT);
i = sw_read_packet(sw->gameport, buf, SW_LENGTH, 0); /* Read normal data packet */
- udelay(SW_TIMEOUT);
+ mdelay(SW_TIMEOUT);
sw_read_packet(sw->gameport, buf, SW_LENGTH, i); /* Read ID packet, this initializes the stick */
sw->fail = SW_FAIL;
@@ -486,28 +492,28 @@ static int sw_read(struct sw *sw)
return -1;
}
-static void sw_timer(unsigned long private)
+static void sw_poll(struct gameport *gameport)
{
- struct sw *sw = (void *) private;
+ struct sw *sw = gameport_get_drvdata(gameport);
sw->reads++;
- if (sw_read(sw)) sw->bads++;
- mod_timer(&sw->timer, jiffies + SW_REFRESH);
+ if (sw_read(sw))
+ sw->bads++;
}
static int sw_open(struct input_dev *dev)
{
struct sw *sw = dev->private;
- if (!sw->used++)
- mod_timer(&sw->timer, jiffies + SW_REFRESH);
+
+ gameport_start_polling(sw->gameport);
return 0;
}
static void sw_close(struct input_dev *dev)
{
struct sw *sw = dev->private;
- if (!--sw->used)
- del_timer(&sw->timer);
+
+ gameport_stop_polling(sw->gameport);
}
/*
@@ -561,7 +567,10 @@ static int sw_guess_mode(unsigned char *buf, int len)
{
int i;
unsigned char xor = 0;
- for (i = 1; i < len; i++) xor |= (buf[i - 1] ^ buf[i]) & 6;
+
+ for (i = 1; i < len; i++)
+ xor |= (buf[i - 1] ^ buf[i]) & 6;
+
return !!xor * 2 + 1;
}
@@ -569,10 +578,11 @@ static int sw_guess_mode(unsigned char *buf, int len)
* sw_connect() probes for SideWinder type joysticks.
*/
-static void sw_connect(struct gameport *gameport, struct gameport_dev *dev)
+static int sw_connect(struct gameport *gameport, struct gameport_driver *drv)
{
struct sw *sw;
int i, j, k, l;
+ int err;
unsigned char *buf = NULL; /* [SW_LENGTH] */
unsigned char *idbuf = NULL; /* [SW_LENGTH] */
unsigned char m = 1;
@@ -580,50 +590,55 @@ static void sw_connect(struct gameport *gameport, struct gameport_dev *dev)
comment[0] = 0;
- if (!(sw = kmalloc(sizeof(struct sw), GFP_KERNEL))) return;
- memset(sw, 0, sizeof(struct sw));
-
+ sw = kcalloc(1, sizeof(struct sw), GFP_KERNEL);
buf = kmalloc(SW_LENGTH, GFP_KERNEL);
idbuf = kmalloc(SW_LENGTH, GFP_KERNEL);
- if (!buf || !idbuf)
+ if (!sw || !buf || !idbuf) {
+ err = -ENOMEM;
goto fail1;
-
- gameport->private = sw;
+ }
sw->gameport = gameport;
- init_timer(&sw->timer);
- sw->timer.data = (long) sw;
- sw->timer.function = sw_timer;
- if (gameport_open(gameport, dev, GAMEPORT_MODE_RAW))
+ gameport_set_drvdata(gameport, sw);
+
+ err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
+ if (err)
goto fail1;
dbg("Init 0: Opened %s, io %#x, speed %d",
gameport->phys, gameport->io, gameport->speed);
i = sw_read_packet(gameport, buf, SW_LENGTH, 0); /* Read normal packet */
- udelay(SW_TIMEOUT);
+ msleep(SW_TIMEOUT);
dbg("Init 1: Mode %d. Length %d.", m , i);
if (!i) { /* No data. 3d Pro analog mode? */
sw_init_digital(gameport); /* Switch to digital */
- udelay(SW_TIMEOUT);
+ msleep(SW_TIMEOUT);
i = sw_read_packet(gameport, buf, SW_LENGTH, 0); /* Retry reading packet */
- udelay(SW_TIMEOUT);
+ msleep(SW_TIMEOUT);
dbg("Init 1b: Length %d.", i);
- if (!i) goto fail2; /* No data -> FAIL */
+ if (!i) { /* No data -> FAIL */
+ err = -ENODEV;
+ goto fail2;
+ }
}
j = sw_read_packet(gameport, idbuf, SW_LENGTH, i); /* Read ID. This initializes the stick */
m |= sw_guess_mode(idbuf, j); /* ID packet should carry mode info [3DP] */
- dbg("Init 2: Mode %d. ID Length %d.", m , j);
+ dbg("Init 2: Mode %d. ID Length %d.", m, j);
- if (!j) { /* Read ID failed. Happens in 1-bit mode on PP */
- udelay(SW_TIMEOUT);
+ if (j <= 0) { /* Read ID failed. Happens in 1-bit mode on PP */
+ msleep(SW_TIMEOUT);
i = sw_read_packet(gameport, buf, SW_LENGTH, 0); /* Retry reading packet */
+ m |= sw_guess_mode(buf, i);
dbg("Init 2b: Mode %d. Length %d.", m, i);
- if (!i) goto fail2;
- udelay(SW_TIMEOUT);
+ if (!i) {
+ err = -ENODEV;
+ goto fail2;
+ }
+ msleep(SW_TIMEOUT);
j = sw_read_packet(gameport, idbuf, SW_LENGTH, i); /* Retry reading ID */
dbg("Init 2c: ID Length %d.", j);
}
@@ -634,7 +649,7 @@ static void sw_connect(struct gameport *gameport, struct gameport_dev *dev)
do {
k--;
- udelay(SW_TIMEOUT);
+ msleep(SW_TIMEOUT);
i = sw_read_packet(gameport, buf, SW_LENGTH, 0); /* Read data packet */
dbg("Init 3: Mode %d. Length %d. Last %d. Tries %d.", m, i, l, k);
@@ -686,13 +701,14 @@ static void sw_connect(struct gameport *gameport, struct gameport_dev *dev)
}
}
- } while (k && (sw->type == -1));
+ } while (k && sw->type == -1);
if (sw->type == -1) {
printk(KERN_WARNING "sidewinder.c: unknown joystick device detected "
"on %s, contact <vojtech@ucw.cz>\n", gameport->phys);
sw_print_packet("ID", j * 3, idbuf, 3);
sw_print_packet("Data", i * m, buf, m);
+ err = -ENODEV;
goto fail2;
}
@@ -701,6 +717,9 @@ static void sw_connect(struct gameport *gameport, struct gameport_dev *dev)
sw_print_packet("Data", i * m, buf, m);
#endif
+ gameport_set_poll_handler(gameport, sw_poll);
+ gameport_set_poll_interval(gameport, 20);
+
k = i;
l = j;
@@ -742,38 +761,46 @@ static void sw_connect(struct gameport *gameport, struct gameport_dev *dev)
sw->name, comment, gameport->phys, m, l, k);
}
- return;
+ return 0;
+
fail2: gameport_close(gameport);
-fail1: kfree(sw);
+fail1: gameport_set_drvdata(gameport, NULL);
+ kfree(sw);
kfree(buf);
kfree(idbuf);
+ return err;
}
static void sw_disconnect(struct gameport *gameport)
{
+ struct sw *sw = gameport_get_drvdata(gameport);
int i;
- struct sw *sw = gameport->private;
for (i = 0; i < sw->number; i++)
input_unregister_device(sw->dev + i);
gameport_close(gameport);
+ gameport_set_drvdata(gameport, NULL);
kfree(sw);
}
-static struct gameport_dev sw_dev = {
- .connect = sw_connect,
- .disconnect = sw_disconnect,
+static struct gameport_driver sw_drv = {
+ .driver = {
+ .name = "sidewinder",
+ },
+ .description = DRIVER_DESC,
+ .connect = sw_connect,
+ .disconnect = sw_disconnect,
};
-int __init sw_init(void)
+static int __init sw_init(void)
{
- gameport_register_device(&sw_dev);
+ gameport_register_driver(&sw_drv);
return 0;
}
-void __exit sw_exit(void)
+static void __exit sw_exit(void)
{
- gameport_unregister_device(&sw_dev);
+ gameport_unregister_driver(&sw_drv);
}
module_init(sw_init);
diff --git a/drivers/input/joystick/spaceball.c b/drivers/input/joystick/spaceball.c
index f046d1e9530ae..ec0a2a64d49c4 100644
--- a/drivers/input/joystick/spaceball.c
+++ b/drivers/input/joystick/spaceball.c
@@ -154,7 +154,7 @@ static void spaceball_process_packet(struct spaceball* spaceball, struct pt_regs
static irqreturn_t spaceball_interrupt(struct serio *serio,
unsigned char data, unsigned int flags, struct pt_regs *regs)
{
- struct spaceball *spaceball = serio->private;
+ struct spaceball *spaceball = serio_get_drvdata(serio);
switch (data) {
case 0xd:
@@ -191,31 +191,32 @@ static irqreturn_t spaceball_interrupt(struct serio *serio,
static void spaceball_disconnect(struct serio *serio)
{
- struct spaceball* spaceball = serio->private;
+ struct spaceball* spaceball = serio_get_drvdata(serio);
+
input_unregister_device(&spaceball->dev);
serio_close(serio);
+ serio_set_drvdata(serio, NULL);
kfree(spaceball);
}
/*
* spaceball_connect() is the routine that is called when someone adds a
- * new serio device. It looks for the Magellan, and if found, registers
- * it as an input device.
+ * new serio device that supports Spaceball protocol and registers it as
+ * an input device.
*/
-static void spaceball_connect(struct serio *serio, struct serio_driver *drv)
+static int spaceball_connect(struct serio *serio, struct serio_driver *drv)
{
struct spaceball *spaceball;
int i, t, id;
+ int err;
- if ((serio->type & ~SERIO_ID) != (SERIO_RS232 | SERIO_SPACEBALL))
- return;
-
- if ((id = (serio->type & SERIO_ID) >> 8) > SPACEBALL_MAX_ID)
- return;
+ if ((id = serio->id.id) > SPACEBALL_MAX_ID)
+ return -ENODEV;
if (!(spaceball = kmalloc(sizeof(struct spaceball), GFP_KERNEL)))
- return;
+ return - ENOMEM;
+
memset(spaceball, 0, sizeof(struct spaceball));
spaceball->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
@@ -255,28 +256,45 @@ static void spaceball_connect(struct serio *serio, struct serio_driver *drv)
spaceball->dev.id.version = 0x0100;
spaceball->dev.dev = &serio->dev;
- serio->private = spaceball;
+ serio_set_drvdata(serio, spaceball);
- if (serio_open(serio, drv)) {
+ err = serio_open(serio, drv);
+ if (err) {
+ serio_set_drvdata(serio, NULL);
kfree(spaceball);
- return;
+ return err;
}
input_register_device(&spaceball->dev);
printk(KERN_INFO "input: %s on serio%s\n",
spaceball_names[id], serio->phys);
+
+ return 0;
}
/*
- * The serio device structure.
+ * The serio driver structure.
*/
+static struct serio_device_id spaceball_serio_ids[] = {
+ {
+ .type = SERIO_RS232,
+ .proto = SERIO_SPACEBALL,
+ .id = SERIO_ANY,
+ .extra = SERIO_ANY,
+ },
+ { 0 }
+};
+
+MODULE_DEVICE_TABLE(serio, spaceball_serio_ids);
+
static struct serio_driver spaceball_drv = {
.driver = {
.name = "spaceball",
},
.description = DRIVER_DESC,
+ .id_table = spaceball_serio_ids,
.interrupt = spaceball_interrupt,
.connect = spaceball_connect,
.disconnect = spaceball_disconnect,
@@ -286,13 +304,13 @@ static struct serio_driver spaceball_drv = {
* The functions for inserting/removing us as a module.
*/
-int __init spaceball_init(void)
+static int __init spaceball_init(void)
{
serio_register_driver(&spaceball_drv);
return 0;
}
-void __exit spaceball_exit(void)
+static void __exit spaceball_exit(void)
{
serio_unregister_driver(&spaceball_drv);
}
diff --git a/drivers/input/joystick/spaceorb.c b/drivers/input/joystick/spaceorb.c
index 19f27c72817b2..c76cf8ff29c0d 100644
--- a/drivers/input/joystick/spaceorb.c
+++ b/drivers/input/joystick/spaceorb.c
@@ -135,7 +135,7 @@ static void spaceorb_process_packet(struct spaceorb *spaceorb, struct pt_regs *r
static irqreturn_t spaceorb_interrupt(struct serio *serio,
unsigned char data, unsigned int flags, struct pt_regs *regs)
{
- struct spaceorb* spaceorb = serio->private;
+ struct spaceorb* spaceorb = serio_get_drvdata(serio);
if (~data & 0x80) {
if (spaceorb->idx) spaceorb_process_packet(spaceorb, regs);
@@ -152,28 +152,29 @@ static irqreturn_t spaceorb_interrupt(struct serio *serio,
static void spaceorb_disconnect(struct serio *serio)
{
- struct spaceorb* spaceorb = serio->private;
+ struct spaceorb* spaceorb = serio_get_drvdata(serio);
+
input_unregister_device(&spaceorb->dev);
serio_close(serio);
+ serio_set_drvdata(serio, NULL);
kfree(spaceorb);
}
/*
* spaceorb_connect() is the routine that is called when someone adds a
- * new serio device. It looks for the SpaceOrb/Avenger, and if found, registers
+ * new serio device that supports SpaceOrb/Avenger protocol and registers
* it as an input device.
*/
-static void spaceorb_connect(struct serio *serio, struct serio_driver *drv)
+static int spaceorb_connect(struct serio *serio, struct serio_driver *drv)
{
struct spaceorb *spaceorb;
int i, t;
-
- if (serio->type != (SERIO_RS232 | SERIO_SPACEORB))
- return;
+ int err;
if (!(spaceorb = kmalloc(sizeof(struct spaceorb), GFP_KERNEL)))
- return;
+ return -ENOMEM;
+
memset(spaceorb, 0, sizeof(struct spaceorb));
spaceorb->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
@@ -202,25 +203,42 @@ static void spaceorb_connect(struct serio *serio, struct serio_driver *drv)
spaceorb->dev.id.version = 0x0100;
spaceorb->dev.dev = &serio->dev;
- serio->private = spaceorb;
+ serio_set_drvdata(serio, spaceorb);
- if (serio_open(serio, drv)) {
+ err = serio_open(serio, drv);
+ if (err) {
+ serio_set_drvdata(serio, NULL);
kfree(spaceorb);
- return;
+ return err;
}
input_register_device(&spaceorb->dev);
+
+ return 0;
}
/*
- * The serio device structure.
+ * The serio driver structure.
*/
+static struct serio_device_id spaceorb_serio_ids[] = {
+ {
+ .type = SERIO_RS232,
+ .proto = SERIO_SPACEORB,
+ .id = SERIO_ANY,
+ .extra = SERIO_ANY,
+ },
+ { 0 }
+};
+
+MODULE_DEVICE_TABLE(serio, spaceorb_serio_ids);
+
static struct serio_driver spaceorb_drv = {
.driver = {
.name = "spaceorb",
},
.description = DRIVER_DESC,
+ .id_table = spaceorb_serio_ids,
.interrupt = spaceorb_interrupt,
.connect = spaceorb_connect,
.disconnect = spaceorb_disconnect,
@@ -230,13 +248,13 @@ static struct serio_driver spaceorb_drv = {
* The functions for inserting/removing us as a module.
*/
-int __init spaceorb_init(void)
+static int __init spaceorb_init(void)
{
serio_register_driver(&spaceorb_drv);
return 0;
}
-void __exit spaceorb_exit(void)
+static void __exit spaceorb_exit(void)
{
serio_unregister_driver(&spaceorb_drv);
}
diff --git a/drivers/input/joystick/stinger.c b/drivers/input/joystick/stinger.c
index 57c00f42310ea..6f6e6753d5902 100644
--- a/drivers/input/joystick/stinger.c
+++ b/drivers/input/joystick/stinger.c
@@ -103,7 +103,7 @@ static void stinger_process_packet(struct stinger *stinger, struct pt_regs *regs
static irqreturn_t stinger_interrupt(struct serio *serio,
unsigned char data, unsigned int flags, struct pt_regs *regs)
{
- struct stinger* stinger = serio->private;
+ struct stinger *stinger = serio_get_drvdata(serio);
/* All Stinger packets are 4 bytes */
@@ -124,28 +124,28 @@ static irqreturn_t stinger_interrupt(struct serio *serio,
static void stinger_disconnect(struct serio *serio)
{
- struct stinger* stinger = serio->private;
+ struct stinger *stinger = serio_get_drvdata(serio);
+
input_unregister_device(&stinger->dev);
serio_close(serio);
+ serio_set_drvdata(serio, NULL);
kfree(stinger);
}
/*
* stinger_connect() is the routine that is called when someone adds a
- * new serio device. It looks for the Stinger, and if found, registers
- * it as an input device.
+ * new serio device that supports Stinger protocol and registers it as
+ * an input device.
*/
-static void stinger_connect(struct serio *serio, struct serio_driver *drv)
+static int stinger_connect(struct serio *serio, struct serio_driver *drv)
{
struct stinger *stinger;
int i;
-
- if (serio->type != (SERIO_RS232 | SERIO_STINGER))
- return;
+ int err;
if (!(stinger = kmalloc(sizeof(struct stinger), GFP_KERNEL)))
- return;
+ return -ENOMEM;
memset(stinger, 0, sizeof(struct stinger));
@@ -173,28 +173,45 @@ static void stinger_connect(struct serio *serio, struct serio_driver *drv)
}
stinger->dev.private = stinger;
- serio->private = stinger;
- if (serio_open(serio, drv)) {
+ serio_set_drvdata(serio, stinger);
+
+ err = serio_open(serio, drv);
+ if (err) {
+ serio_set_drvdata(serio, NULL);
kfree(stinger);
- return;
+ return err;
}
input_register_device(&stinger->dev);
printk(KERN_INFO "input: %s on %s\n", stinger_name, serio->phys);
+ return 0;
}
/*
- * The serio device structure.
+ * The serio driver structure.
*/
+static struct serio_device_id stinger_serio_ids[] = {
+ {
+ .type = SERIO_RS232,
+ .proto = SERIO_STINGER,
+ .id = SERIO_ANY,
+ .extra = SERIO_ANY,
+ },
+ { 0 }
+};
+
+MODULE_DEVICE_TABLE(serio, stinger_serio_ids);
+
static struct serio_driver stinger_drv = {
.driver = {
.name = "stinger",
},
.description = DRIVER_DESC,
+ .id_table = stinger_serio_ids,
.interrupt = stinger_interrupt,
.connect = stinger_connect,
.disconnect = stinger_disconnect,
@@ -204,13 +221,13 @@ static struct serio_driver stinger_drv = {
* The functions for inserting/removing us as a module.
*/
-int __init stinger_init(void)
+static int __init stinger_init(void)
{
serio_register_driver(&stinger_drv);
return 0;
}
-void __exit stinger_exit(void)
+static void __exit stinger_exit(void)
{
serio_unregister_driver(&stinger_drv);
}
diff --git a/drivers/input/joystick/tmdc.c b/drivers/input/joystick/tmdc.c
index e11d2914826d8..aaee52ceb920a 100644
--- a/drivers/input/joystick/tmdc.c
+++ b/drivers/input/joystick/tmdc.c
@@ -39,14 +39,15 @@
#include <linux/gameport.h>
#include <linux/input.h>
+#define DRIVER_DESC "ThrustMaster DirectConnect joystick driver"
+
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
-MODULE_DESCRIPTION("ThrustMaster DirectConnect joystick driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
-#define TMDC_MAX_START 400 /* 400 us */
-#define TMDC_MAX_STROBE 45 /* 45 us */
+#define TMDC_MAX_START 600 /* 600 us */
+#define TMDC_MAX_STROBE 60 /* 60 us */
#define TMDC_MAX_LENGTH 13
-#define TMDC_REFRESH_TIME HZ/50 /* 20 ms */
#define TMDC_MODE_M3DI 1
#define TMDC_MODE_3DRP 3
@@ -92,7 +93,6 @@ static struct {
struct tmdc {
struct gameport *gameport;
- struct timer_list timer;
struct input_dev dev[2];
char name[2][64];
char phys[2][32];
@@ -102,7 +102,6 @@ struct tmdc {
unsigned char absc[2];
unsigned char btnc[2][4];
unsigned char btno[2][4];
- int used;
int reads;
int bads;
unsigned char exists;
@@ -158,13 +157,13 @@ static int tmdc_read_packet(struct gameport *gameport, unsigned char data[2][TMD
}
/*
- * tmdc_read() reads and analyzes ThrustMaster joystick data.
+ * tmdc_poll() reads and analyzes ThrustMaster joystick data.
*/
-static void tmdc_timer(unsigned long private)
+static void tmdc_poll(struct gameport *gameport)
{
unsigned char data[2][TMDC_MAX_LENGTH];
- struct tmdc *tmdc = (void *) private;
+ struct tmdc *tmdc = gameport_get_drvdata(gameport);
struct input_dev *dev;
unsigned char r, bad = 0;
int i, j, k, l;
@@ -219,32 +218,30 @@ static void tmdc_timer(unsigned long private)
}
tmdc->bads += bad;
-
- mod_timer(&tmdc->timer, jiffies + TMDC_REFRESH_TIME);
}
static int tmdc_open(struct input_dev *dev)
{
struct tmdc *tmdc = dev->private;
- if (!tmdc->used++)
- mod_timer(&tmdc->timer, jiffies + TMDC_REFRESH_TIME);
+
+ gameport_start_polling(tmdc->gameport);
return 0;
}
static void tmdc_close(struct input_dev *dev)
{
struct tmdc *tmdc = dev->private;
- if (!--tmdc->used)
- del_timer(&tmdc->timer);
+
+ gameport_stop_polling(tmdc->gameport);
}
/*
* tmdc_probe() probes for ThrustMaster type joysticks.
*/
-static void tmdc_connect(struct gameport *gameport, struct gameport_dev *dev)
+static int tmdc_connect(struct gameport *gameport, struct gameport_driver *drv)
{
- struct models {
+ static struct models {
unsigned char id;
char *name;
char abs;
@@ -263,23 +260,26 @@ static void tmdc_connect(struct gameport *gameport, struct gameport_dev *dev)
unsigned char data[2][TMDC_MAX_LENGTH];
struct tmdc *tmdc;
int i, j, k, l, m;
+ int err;
- if (!(tmdc = kmalloc(sizeof(struct tmdc), GFP_KERNEL)))
- return;
- memset(tmdc, 0, sizeof(struct tmdc));
-
- gameport->private = tmdc;
+ if (!(tmdc = kcalloc(1, sizeof(struct tmdc), GFP_KERNEL)))
+ return -ENOMEM;
tmdc->gameport = gameport;
- init_timer(&tmdc->timer);
- tmdc->timer.data = (long) tmdc;
- tmdc->timer.function = tmdc_timer;
- if (gameport_open(gameport, dev, GAMEPORT_MODE_RAW))
+ gameport_set_drvdata(gameport, tmdc);
+
+ err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
+ if (err)
goto fail1;
- if (!(tmdc->exists = tmdc_read_packet(gameport, data)))
+ if (!(tmdc->exists = tmdc_read_packet(gameport, data))) {
+ err = -ENODEV;
goto fail2;
+ }
+
+ gameport_set_poll_handler(gameport, tmdc_poll);
+ gameport_set_poll_interval(gameport, 20);
for (j = 0; j < 2; j++)
if (tmdc->exists & (1 << j)) {
@@ -321,20 +321,13 @@ static void tmdc_connect(struct gameport *gameport, struct gameport_dev *dev)
tmdc->dev[j].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
- for (i = 0; i < models[m].abs && i < TMDC_ABS; i++) {
- if (tmdc->abs[j][i] < 0) continue;
- set_bit(tmdc->abs[j][i], tmdc->dev[j].absbit);
- tmdc->dev[j].absmin[tmdc->abs[j][i]] = 8;
- tmdc->dev[j].absmax[tmdc->abs[j][i]] = 248;
- tmdc->dev[j].absfuzz[tmdc->abs[j][i]] = 2;
- tmdc->dev[j].absflat[tmdc->abs[j][i]] = 4;
- }
+ for (i = 0; i < models[m].abs && i < TMDC_ABS; i++)
+ if (tmdc->abs[j][i] >= 0)
+ input_set_abs_params(&tmdc->dev[j], tmdc->abs[j][i], 8, 248, 2, 4);
+
+ for (i = 0; i < models[m].hats && i < TMDC_ABS_HAT; i++)
+ input_set_abs_params(&tmdc->dev[j], tmdc_abs_hat[i], -1, 1, 0, 0);
- for (i = 0; i < models[m].hats && i < TMDC_ABS_HAT; i++) {
- set_bit(tmdc_abs_hat[i], tmdc->dev[j].absbit);
- tmdc->dev[j].absmin[tmdc_abs_hat[i]] = -1;
- tmdc->dev[j].absmax[tmdc_abs_hat[i]] = 1;
- }
for (k = l = 0; k < 4; k++) {
for (i = 0; i < models[m].btnc[k] && i < TMDC_BTN; i++)
@@ -346,36 +339,45 @@ static void tmdc_connect(struct gameport *gameport, struct gameport_dev *dev)
printk(KERN_INFO "input: %s on %s\n", tmdc->name[j], gameport->phys);
}
- return;
+ return 0;
+
fail2: gameport_close(gameport);
-fail1: kfree(tmdc);
+fail1: gameport_set_drvdata(gameport, NULL);
+ kfree(tmdc);
+ return err;
}
static void tmdc_disconnect(struct gameport *gameport)
{
- struct tmdc *tmdc = gameport->private;
+ struct tmdc *tmdc = gameport_get_drvdata(gameport);
int i;
+
for (i = 0; i < 2; i++)
if (tmdc->exists & (1 << i))
input_unregister_device(tmdc->dev + i);
gameport_close(gameport);
+ gameport_set_drvdata(gameport, NULL);
kfree(tmdc);
}
-static struct gameport_dev tmdc_dev = {
- .connect = tmdc_connect,
- .disconnect = tmdc_disconnect,
+static struct gameport_driver tmdc_drv = {
+ .driver = {
+ .name = "tmdc",
+ },
+ .description = DRIVER_DESC,
+ .connect = tmdc_connect,
+ .disconnect = tmdc_disconnect,
};
-int __init tmdc_init(void)
+static int __init tmdc_init(void)
{
- gameport_register_device(&tmdc_dev);
+ gameport_register_driver(&tmdc_drv);
return 0;
}
-void __exit tmdc_exit(void)
+static void __exit tmdc_exit(void)
{
- gameport_unregister_device(&tmdc_dev);
+ gameport_unregister_driver(&tmdc_drv);
}
module_init(tmdc_init);
diff --git a/drivers/input/joystick/turbografx.c b/drivers/input/joystick/turbografx.c
index 0e620cb882cdb..dd88b9cb49fa0 100644
--- a/drivers/input/joystick/turbografx.c
+++ b/drivers/input/joystick/turbografx.c
@@ -77,7 +77,7 @@ __obsolete_setup("tgfx_3=");
static int tgfx_buttons[] = { BTN_TRIGGER, BTN_THUMB, BTN_THUMB2, BTN_TOP, BTN_TOP2 };
static char *tgfx_name = "TurboGraFX Multisystem joystick";
-struct tgfx {
+static struct tgfx {
struct pardevice *pd;
struct timer_list timer;
struct input_dev dev[7];
@@ -229,7 +229,7 @@ static struct tgfx __init *tgfx_probe(int *config, int nargs)
return tgfx;
}
-int __init tgfx_init(void)
+static int __init tgfx_init(void)
{
tgfx_base[0] = tgfx_probe(tgfx, tgfx_nargs);
tgfx_base[1] = tgfx_probe(tgfx_2, tgfx_nargs_2);
@@ -241,7 +241,7 @@ int __init tgfx_init(void)
return -ENODEV;
}
-void __exit tgfx_exit(void)
+static void __exit tgfx_exit(void)
{
int i, j;
diff --git a/drivers/input/joystick/twidjoy.c b/drivers/input/joystick/twidjoy.c
index 27c71ec345062..0379bc1665252 100644
--- a/drivers/input/joystick/twidjoy.c
+++ b/drivers/input/joystick/twidjoy.c
@@ -58,7 +58,9 @@
#include <linux/serio.h>
#include <linux/init.h>
-MODULE_DESCRIPTION("Handykey Twiddler keyboard as a joystick driver");
+#define DRIVER_DESC "Handykey Twiddler keyboard as a joystick driver"
+
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
/*
@@ -147,7 +149,7 @@ static void twidjoy_process_packet(struct twidjoy *twidjoy, struct pt_regs *regs
static irqreturn_t twidjoy_interrupt(struct serio *serio, unsigned char data, unsigned int flags, struct pt_regs *regs)
{
- struct twidjoy *twidjoy = serio->private;
+ struct twidjoy *twidjoy = serio_get_drvdata(serio);
/* All Twiddler packets are 5 bytes. The fact that the first byte
* has a MSB of 0 and all other bytes have a MSB of 1 can be used
@@ -175,9 +177,11 @@ static irqreturn_t twidjoy_interrupt(struct serio *serio, unsigned char data, un
static void twidjoy_disconnect(struct serio *serio)
{
- struct twidjoy *twidjoy = serio->private;
+ struct twidjoy *twidjoy = serio_get_drvdata(serio);
+
input_unregister_device(&twidjoy->dev);
serio_close(serio);
+ serio_set_drvdata(serio, NULL);
kfree(twidjoy);
}
@@ -187,17 +191,15 @@ static void twidjoy_disconnect(struct serio *serio)
* it as an input device.
*/
-static void twidjoy_connect(struct serio *serio, struct serio_driver *drv)
+static int twidjoy_connect(struct serio *serio, struct serio_driver *drv)
{
struct twidjoy_button_spec *bp;
struct twidjoy *twidjoy;
int i;
-
- if (serio->type != (SERIO_RS232 | SERIO_TWIDJOY))
- return;
+ int err;
if (!(twidjoy = kmalloc(sizeof(struct twidjoy), GFP_KERNEL)))
- return;
+ return -ENOMEM;
memset(twidjoy, 0, sizeof(struct twidjoy));
@@ -231,27 +233,45 @@ static void twidjoy_connect(struct serio *serio, struct serio_driver *drv)
}
twidjoy->dev.private = twidjoy;
- serio->private = twidjoy;
- if (serio_open(serio, drv)) {
+ serio_set_drvdata(serio, twidjoy);
+
+ err = serio_open(serio, drv);
+ if (err) {
+ serio_set_drvdata(serio, NULL);
kfree(twidjoy);
- return;
+ return err;
}
input_register_device(&twidjoy->dev);
printk(KERN_INFO "input: %s on %s\n", twidjoy_name, serio->phys);
+
+ return 0;
}
/*
- * The serio device structure.
+ * The serio driver structure.
*/
+static struct serio_device_id twidjoy_serio_ids[] = {
+ {
+ .type = SERIO_RS232,
+ .proto = SERIO_TWIDJOY,
+ .id = SERIO_ANY,
+ .extra = SERIO_ANY,
+ },
+ { 0 }
+};
+
+MODULE_DEVICE_TABLE(serio, twidjoy_serio_ids);
+
static struct serio_driver twidjoy_drv = {
.driver = {
.name = "twidjoy",
},
.description = DRIVER_DESC,
+ .id_table = twidjoy_serio_ids,
.interrupt = twidjoy_interrupt,
.connect = twidjoy_connect,
.disconnect = twidjoy_disconnect,
diff --git a/drivers/input/joystick/warrior.c b/drivers/input/joystick/warrior.c
index 53d535bd1b59f..6976a219504c5 100644
--- a/drivers/input/joystick/warrior.c
+++ b/drivers/input/joystick/warrior.c
@@ -104,7 +104,7 @@ static void warrior_process_packet(struct warrior *warrior, struct pt_regs *regs
static irqreturn_t warrior_interrupt(struct serio *serio,
unsigned char data, unsigned int flags, struct pt_regs *regs)
{
- struct warrior* warrior = serio->private;
+ struct warrior *warrior = serio_get_drvdata(serio);
if (data & 0x80) {
if (warrior->idx) warrior_process_packet(warrior, regs);
@@ -129,9 +129,11 @@ static irqreturn_t warrior_interrupt(struct serio *serio,
static void warrior_disconnect(struct serio *serio)
{
- struct warrior* warrior = serio->private;
+ struct warrior *warrior = serio_get_drvdata(serio);
+
input_unregister_device(&warrior->dev);
serio_close(serio);
+ serio_set_drvdata(serio, NULL);
kfree(warrior);
}
@@ -141,16 +143,14 @@ static void warrior_disconnect(struct serio *serio)
* it as an input device.
*/
-static void warrior_connect(struct serio *serio, struct serio_driver *drv)
+static int warrior_connect(struct serio *serio, struct serio_driver *drv)
{
struct warrior *warrior;
int i;
-
- if (serio->type != (SERIO_RS232 | SERIO_WARRIOR))
- return;
+ int err;
if (!(warrior = kmalloc(sizeof(struct warrior), GFP_KERNEL)))
- return;
+ return -ENOMEM;
memset(warrior, 0, sizeof(struct warrior));
@@ -186,27 +186,44 @@ static void warrior_connect(struct serio *serio, struct serio_driver *drv)
warrior->dev.private = warrior;
- serio->private = warrior;
+ serio_set_drvdata(serio, warrior);
- if (serio_open(serio, drv)) {
+ err = serio_open(serio, drv);
+ if (err) {
+ serio_set_drvdata(serio, NULL);
kfree(warrior);
- return;
+ return err;
}
input_register_device(&warrior->dev);
printk(KERN_INFO "input: Logitech WingMan Warrior on %s\n", serio->phys);
+
+ return 0;
}
/*
- * The serio device structure.
+ * The serio driver structure.
*/
+static struct serio_device_id warrior_serio_ids[] = {
+ {
+ .type = SERIO_RS232,
+ .proto = SERIO_WARRIOR,
+ .id = SERIO_ANY,
+ .extra = SERIO_ANY,
+ },
+ { 0 }
+};
+
+MODULE_DEVICE_TABLE(serio, warrior_serio_ids);
+
static struct serio_driver warrior_drv = {
.driver = {
.name = "warrior",
},
.description = DRIVER_DESC,
+ .id_table = warrior_serio_ids,
.interrupt = warrior_interrupt,
.connect = warrior_connect,
.disconnect = warrior_disconnect,
@@ -216,13 +233,13 @@ static struct serio_driver warrior_drv = {
* The functions for inserting/removing us as a module.
*/
-int __init warrior_init(void)
+static int __init warrior_init(void)
{
serio_register_driver(&warrior_drv);
return 0;
}
-void __exit warrior_exit(void)
+static void __exit warrior_exit(void)
{
serio_unregister_driver(&warrior_drv);
}
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index 2d2aa70e4c5ce..e55dee3907756 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -1,20 +1,20 @@
#
# Input core configuration
#
-config INPUT_KEYBOARD
+menuconfig INPUT_KEYBOARD
bool "Keyboards" if EMBEDDED || !X86
default y
- depends on INPUT
help
Say Y here, and a list of supported keyboards will be displayed.
This option doesn't affect the kernel.
If unsure, say Y.
+if INPUT_KEYBOARD
+
config KEYBOARD_ATKBD
- tristate "AT keyboard support" if !PC
+ tristate "AT keyboard" if !PC
default y
- depends on INPUT && INPUT_KEYBOARD
select SERIO
select SERIO_LIBPS2
select SERIO_I8042 if PC
@@ -30,9 +30,46 @@ config KEYBOARD_ATKBD
To compile this driver as a module, choose M here: the
module will be called atkbd.
+config KEYBOARD_ATKBD_HP_KEYCODES
+ bool "Use HP keyboard scancodes"
+ depends on PARISC && KEYBOARD_ATKBD
+ default y
+ help
+ Say Y here if you have a PA-RISC machine and want to use an AT or
+ PS/2 keyboard, and your keyboard uses keycodes that are specific to
+ PA-RISC keyboards.
+
+ Say N if you use a standard keyboard.
+
+config KEYBOARD_ATKBD_RDI_KEYCODES
+ bool "Use PrecisionBook keyboard scancodes"
+ depends on KEYBOARD_ATKBD_HP_KEYCODES
+ default n
+ help
+ If you have an RDI PrecisionBook, say Y here if you want to use its
+ built-in keyboard (as opposed to an external keyboard).
+
+ The PrecisionBook has five keys that conflict with those used by most
+ AT and PS/2 keyboards. These are as follows:
+
+ PrecisionBook Standard AT or PS/2
+
+ F1 F12
+ Left Ctrl Left Alt
+ Caps Lock Left Ctrl
+ Right Ctrl Caps Lock
+ Left 102nd key (the key to the right of Left Shift)
+
+ If you say N here, and use the PrecisionBook keyboard, then each key
+ in the left-hand column will be interpreted as the corresponding key
+ in the right-hand column.
+
+ If you say Y here, and use an external keyboard, then each key in the
+ right-hand column will be interpreted as the key shown in the
+ left-hand column.
+
config KEYBOARD_SUNKBD
- tristate "Sun Type 4 and Type 5 keyboard support"
- depends on INPUT && INPUT_KEYBOARD
+ tristate "Sun Type 4 and Type 5 keyboard"
select SERIO
help
Say Y here if you want to use a Sun Type 4 or Type 5 keyboard,
@@ -43,8 +80,7 @@ config KEYBOARD_SUNKBD
module will be called sunkbd.
config KEYBOARD_LKKBD
- tristate "DECstation/VAXstation LK201/LK401 keyboard support"
- depends on INPUT && INPUT_KEYBOARD
+ tristate "DECstation/VAXstation LK201/LK401 keyboard"
select SERIO
help
Say Y here if you want to use a LK201 or LK401 style serial
@@ -55,9 +91,17 @@ config KEYBOARD_LKKBD
To compile this driver as a module, choose M here: the
module will be called lkkbd.
+config KEYBOARD_LOCOMO
+ tristate "LoCoMo Keyboard Support"
+ depends on SHARP_LOCOMO
+ help
+ Say Y here if you are running Linux on a Sharp Zaurus Collie or Poodle based PDA
+
+ To compile this driver as a module, choose M here: the
+ module will be called locomokbd.
+
config KEYBOARD_XTKBD
- tristate "XT Keyboard support"
- depends on INPUT && INPUT_KEYBOARD
+ tristate "XT keyboard"
select SERIO
help
Say Y here if you want to use the old IBM PC/XT keyboard (or
@@ -70,7 +114,6 @@ config KEYBOARD_XTKBD
config KEYBOARD_NEWTON
tristate "Newton keyboard"
- depends on INPUT && INPUT_KEYBOARD
select SERIO
help
Say Y here if you have a Newton keyboard on a serial port.
@@ -78,9 +121,20 @@ config KEYBOARD_NEWTON
To compile this driver as a module, choose M here: the
module will be called newtonkbd.
+config KEYBOARD_CORGI
+ tristate "Corgi keyboard"
+ depends on PXA_SHARPSL
+ default y
+ help
+ Say Y here to enable the keyboard on the Sharp Zaurus SL-C7xx
+ series of PDAs.
+
+ To compile this driver as a module, choose M here: the
+ module will be called corgikbd.
+
config KEYBOARD_MAPLE
- tristate "Maple bus keyboard support"
- depends on SH_DREAMCAST && INPUT && INPUT_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.
@@ -90,10 +144,42 @@ config KEYBOARD_MAPLE
config KEYBOARD_AMIGA
tristate "Amiga keyboard"
- depends on AMIGA && INPUT && INPUT_KEYBOARD
+ depends on AMIGA
help
Say Y here if you are running Linux on any AMIGA and have a keyboard
attached.
To compile this driver as a module, choose M here: the
module will be called amikbd.
+
+config KEYBOARD_HIL_OLD
+ tristate "HP HIL keyboard support (simple driver)"
+ depends on GSC
+ default y
+ help
+ The "Human Interface Loop" is a older, 8-channel USB-like
+ controller used in several Hewlett Packard models. This driver
+ was adapted from the one written for m68k/hp300, and implements
+ support for a keyboard attached to the HIL port, but not for
+ any other types of HIL input devices like mice or tablets.
+ However, it has been thoroughly tested and is stable.
+
+ If you want full HIL support including support for multiple
+ keyboards, mices and tablets, you have to enable the
+ "HP System Device Controller i8042 Support" in the input/serio
+ submenu.
+
+config KEYBOARD_HIL
+ tristate "HP HIL keyboard support"
+ depends on GSC
+ default y
+ select HP_SDC
+ select HIL_MLC
+ select SERIO
+ help
+ The "Human Interface Loop" is a older, 8-channel USB-like
+ controller used in several Hewlett Packard models.
+ This driver implements support for HIL-keyboards attached
+ to your machine, so normally you should say Y here.
+
+endif
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
index cfe9ff2f8b21d..b02eeceea3c32 100644
--- a/drivers/input/keyboard/Makefile
+++ b/drivers/input/keyboard/Makefile
@@ -10,5 +10,10 @@ obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o
obj-$(CONFIG_KEYBOARD_LKKBD) += lkkbd.o
obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o
obj-$(CONFIG_KEYBOARD_AMIGA) += amikbd.o
+obj-$(CONFIG_KEYBOARD_LOCOMO) += locomokbd.o
obj-$(CONFIG_KEYBOARD_NEWTON) += newtonkbd.o
obj-$(CONFIG_KEYBOARD_98KBD) += 98kbd.o
+obj-$(CONFIG_KEYBOARD_CORGI) += corgikbd.o
+obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o
+obj-$(CONFIG_KEYBOARD_HIL_OLD) += hilkbd.o
+
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
index 8b4686618430e..f7304f0ce542b 100644
--- a/drivers/input/keyboard/atkbd.c
+++ b/drivers/input/keyboard/atkbd.c
@@ -54,7 +54,7 @@ static int atkbd_softraw = 1;
module_param_named(softraw, atkbd_softraw, bool, 0);
MODULE_PARM_DESC(softraw, "Use software generated rawmode");
-static int atkbd_scroll;
+static int atkbd_scroll = 1;
module_param_named(scroll, atkbd_scroll, bool, 0);
MODULE_PARM_DESC(scroll, "Enable scroll-wheel on MS Office and similar keyboards");
@@ -71,12 +71,15 @@ __obsolete_setup("atkbd_softrepeat=");
* are loadable via an userland utility.
*/
-#if defined(__hppa__)
-#include "hpps2atkbd.h"
-#else
-
static unsigned char atkbd_set2_keycode[512] = {
+#ifdef CONFIG_KEYBOARD_ATKBD_HP_KEYCODES
+
+/* XXX: need a more general approach */
+
+#include "hpps2atkbd.h" /* include the keyboard scancodes */
+
+#else
0, 67, 65, 63, 61, 59, 60, 88, 0, 68, 66, 64, 62, 15, 41,117,
0, 56, 42, 93, 29, 16, 2, 0, 0, 0, 44, 31, 30, 17, 3, 0,
0, 46, 45, 32, 18, 5, 4, 95, 0, 57, 47, 33, 20, 19, 6,183,
@@ -96,9 +99,8 @@ static unsigned char atkbd_set2_keycode[512] = {
110,111,108,112,106,103, 0,119, 0,118,109, 0, 99,104,119, 0,
0, 0, 0, 65, 99,
-};
-
#endif
+};
static unsigned char atkbd_set3_keycode[512] = {
@@ -141,7 +143,6 @@ static unsigned char atkbd_unxlate_table[128] = {
#define ATKBD_CMD_EX_SETLEDS 0x20eb
#define ATKBD_CMD_OK_GETID 0x02e8
-
#define ATKBD_RET_ACK 0xfa
#define ATKBD_RET_NAK 0xfe
#define ATKBD_RET_BAT 0xaa
@@ -160,15 +161,22 @@ static unsigned char atkbd_unxlate_table[128] = {
#define ATKBD_SCR_4 252
#define ATKBD_SCR_8 251
#define ATKBD_SCR_CLICK 250
-
-#define ATKBD_SPECIAL 250
-
-static unsigned char atkbd_scroll_keys[5][2] = {
- { ATKBD_SCR_1, 0x45 },
- { ATKBD_SCR_2, 0x29 },
- { ATKBD_SCR_4, 0x36 },
- { ATKBD_SCR_8, 0x27 },
- { ATKBD_SCR_CLICK, 0x60 },
+#define ATKBD_SCR_LEFT 249
+#define ATKBD_SCR_RIGHT 248
+
+#define ATKBD_SPECIAL 248
+
+static struct {
+ unsigned char keycode;
+ unsigned char set2;
+} atkbd_scroll_keys[] = {
+ { ATKBD_SCR_1, 0xc5 },
+ { ATKBD_SCR_2, 0xa9 },
+ { ATKBD_SCR_4, 0xb6 },
+ { ATKBD_SCR_8, 0xa7 },
+ { ATKBD_SCR_CLICK, 0xe0 },
+ { ATKBD_SCR_LEFT, 0xcb },
+ { ATKBD_SCR_RIGHT, 0xd2 },
};
/*
@@ -249,9 +257,9 @@ static void atkbd_report_key(struct input_dev *dev, struct pt_regs *regs, int co
static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
unsigned int flags, struct pt_regs *regs)
{
- struct atkbd *atkbd = serio->private;
+ struct atkbd *atkbd = serio_get_drvdata(serio);
unsigned int code = data;
- int scroll = 0, click = -1;
+ int scroll = 0, hscroll = 0, click = -1;
int value;
#ifdef ATKBD_DEBUG
@@ -370,6 +378,12 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
case ATKBD_SCR_CLICK:
click = !atkbd->release;
break;
+ case ATKBD_SCR_LEFT:
+ hscroll = -1;
+ break;
+ case ATKBD_SCR_RIGHT:
+ hscroll = 1;
+ break;
default:
value = atkbd->release ? 0 :
(1 + (!atkbd->softrepeat && test_bit(atkbd->keycode[code], atkbd->dev.key)));
@@ -380,7 +394,7 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
break;
case 1:
atkbd->last = code;
- atkbd->time = jiffies + (atkbd->dev.rep[REP_DELAY] * HZ + 500) / 1000 / 2;
+ atkbd->time = jiffies + msecs_to_jiffies(atkbd->dev.rep[REP_DELAY]) / 2;
break;
case 2:
if (!time_after(jiffies, atkbd->time) && atkbd->last == code)
@@ -391,10 +405,12 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
atkbd_report_key(&atkbd->dev, regs, atkbd->keycode[code], value);
}
- if (scroll || click != -1) {
+ if (atkbd->scroll) {
input_regs(&atkbd->dev, regs);
- input_report_key(&atkbd->dev, BTN_MIDDLE, click);
+ if (click != -1)
+ input_report_key(&atkbd->dev, BTN_MIDDLE, click);
input_report_rel(&atkbd->dev, REL_WHEEL, scroll);
+ input_report_rel(&atkbd->dev, REL_HWHEEL, hscroll);
input_sync(&atkbd->dev);
}
@@ -403,7 +419,6 @@ out:
return IRQ_HANDLED;
}
-
/*
* Event callback from the input module. Events that change the state of
* the hardware are processed here.
@@ -647,7 +662,7 @@ static int atkbd_activate(struct atkbd *atkbd)
static void atkbd_cleanup(struct serio *serio)
{
- struct atkbd *atkbd = serio->private;
+ struct atkbd *atkbd = serio_get_drvdata(serio);
ps2_command(&atkbd->ps2dev, NULL, ATKBD_CMD_RESET_BAT);
}
@@ -658,7 +673,7 @@ static void atkbd_cleanup(struct serio *serio)
static void atkbd_disconnect(struct serio *serio)
{
- struct atkbd *atkbd = serio->private;
+ struct atkbd *atkbd = serio_get_drvdata(serio);
atkbd_disable(atkbd);
@@ -674,6 +689,7 @@ static void atkbd_disconnect(struct serio *serio)
input_unregister_device(&atkbd->dev);
serio_close(serio);
+ serio_set_drvdata(serio, NULL);
kfree(atkbd);
}
@@ -694,12 +710,9 @@ static void atkbd_set_keycode_table(struct atkbd *atkbd)
atkbd->keycode[i] = atkbd_set2_keycode[atkbd_unxlate_table[i]];
atkbd->keycode[i | 0x80] = atkbd_set2_keycode[atkbd_unxlate_table[i] | 0x80];
if (atkbd->scroll)
- for (j = 0; i < 5; i++) {
- if (atkbd_unxlate_table[i] == atkbd_scroll_keys[j][1])
- atkbd->keycode[i] = atkbd_scroll_keys[j][0];
- if ((atkbd_unxlate_table[i] | 0x80) == atkbd_scroll_keys[j][1])
- atkbd->keycode[i | 0x80] = atkbd_scroll_keys[j][0];
- }
+ for (j = 0; j < ARRAY_SIZE(atkbd_scroll_keys); j++)
+ if ((atkbd_unxlate_table[i] | 0x80) == atkbd_scroll_keys[j].set2)
+ atkbd->keycode[i | 0x80] = atkbd_scroll_keys[j].keycode;
}
} else if (atkbd->set == 3) {
memcpy(atkbd->keycode, atkbd_set3_keycode, sizeof(atkbd->keycode));
@@ -707,8 +720,8 @@ static void atkbd_set_keycode_table(struct atkbd *atkbd)
memcpy(atkbd->keycode, atkbd_set2_keycode, sizeof(atkbd->keycode));
if (atkbd->scroll)
- for (i = 0; i < 5; i++)
- atkbd->keycode[atkbd_scroll_keys[i][1]] = atkbd_scroll_keys[i][0];
+ for (i = 0; i < ARRAY_SIZE(atkbd_scroll_keys); i++)
+ atkbd->keycode[atkbd_scroll_keys[i].set2] = atkbd_scroll_keys[i].keycode;
}
}
@@ -754,7 +767,7 @@ static void atkbd_set_device_attrs(struct atkbd *atkbd)
if (atkbd->scroll) {
atkbd->dev.evbit[0] |= BIT(EV_REL);
- atkbd->dev.relbit[0] = BIT(REL_WHEEL);
+ atkbd->dev.relbit[0] = BIT(REL_WHEEL) | BIT(REL_HWHEEL);
set_bit(BTN_MIDDLE, atkbd->dev.keybit);
}
@@ -768,23 +781,25 @@ static void atkbd_set_device_attrs(struct atkbd *atkbd)
}
/*
- * atkbd_connect() is called when the serio module finds and interface
+ * atkbd_connect() is called when the serio module finds an interface
* that isn't handled yet by an appropriate device driver. We check if
* there is an AT keyboard out there and if yes, we register ourselves
* to the input module.
*/
-static void atkbd_connect(struct serio *serio, struct serio_driver *drv)
+static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
{
struct atkbd *atkbd;
+ int err;
if (!(atkbd = kmalloc(sizeof(struct atkbd), GFP_KERNEL)))
- return;
+ return - ENOMEM;
+
memset(atkbd, 0, sizeof(struct atkbd));
ps2_init(&atkbd->ps2dev, serio);
- switch (serio->type & SERIO_TYPE) {
+ switch (serio->id.type) {
case SERIO_8042_XL:
atkbd->translated = 1;
@@ -792,12 +807,6 @@ static void atkbd_connect(struct serio *serio, struct serio_driver *drv)
if (serio->write)
atkbd->write = 1;
break;
- case SERIO_RS232:
- if ((serio->type & SERIO_PROTO) == SERIO_PS2SER)
- break;
- default:
- kfree(atkbd);
- return;
}
atkbd->softraw = atkbd_softraw;
@@ -810,20 +819,22 @@ static void atkbd_connect(struct serio *serio, struct serio_driver *drv)
if (atkbd->softrepeat)
atkbd->softraw = 1;
- serio->private = atkbd;
+ serio_set_drvdata(serio, atkbd);
- if (serio_open(serio, drv)) {
+ err = serio_open(serio, drv);
+ if (err) {
+ serio_set_drvdata(serio, NULL);
kfree(atkbd);
- return;
+ return err;
}
if (atkbd->write) {
if (atkbd_probe(atkbd)) {
serio_close(serio);
- serio->private = NULL;
+ serio_set_drvdata(serio, NULL);
kfree(atkbd);
- return;
+ return -ENODEV;
}
atkbd->set = atkbd_select_set(atkbd, atkbd_set, atkbd_extra);
@@ -856,6 +867,8 @@ static void atkbd_connect(struct serio *serio, struct serio_driver *drv)
atkbd_enable(atkbd);
printk(KERN_INFO "input: %s on %s\n", atkbd->name, serio->phys);
+
+ return 0;
}
/*
@@ -865,7 +878,7 @@ static void atkbd_connect(struct serio *serio, struct serio_driver *drv)
static int atkbd_reconnect(struct serio *serio)
{
- struct atkbd *atkbd = serio->private;
+ struct atkbd *atkbd = serio_get_drvdata(serio);
struct serio_driver *drv = serio->drv;
unsigned char param[1];
@@ -897,11 +910,36 @@ static int atkbd_reconnect(struct serio *serio)
return 0;
}
+static struct serio_device_id atkbd_serio_ids[] = {
+ {
+ .type = SERIO_8042,
+ .proto = SERIO_ANY,
+ .id = SERIO_ANY,
+ .extra = SERIO_ANY,
+ },
+ {
+ .type = SERIO_8042_XL,
+ .proto = SERIO_ANY,
+ .id = SERIO_ANY,
+ .extra = SERIO_ANY,
+ },
+ {
+ .type = SERIO_RS232,
+ .proto = SERIO_PS2SER,
+ .id = SERIO_ANY,
+ .extra = SERIO_ANY,
+ },
+ { 0 }
+};
+
+MODULE_DEVICE_TABLE(serio, atkbd_serio_ids);
+
static struct serio_driver atkbd_drv = {
.driver = {
.name = "atkbd",
},
.description = DRIVER_DESC,
+ .id_table = atkbd_serio_ids,
.interrupt = atkbd_interrupt,
.connect = atkbd_connect,
.reconnect = atkbd_reconnect,
@@ -924,7 +962,7 @@ static ssize_t atkbd_attr_show_helper(struct device *dev, char *buf,
goto out;
}
- retval = handler((struct atkbd *)serio->private, buf);
+ retval = handler((struct atkbd *)serio_get_drvdata(serio), buf);
out:
serio_unpin_driver(serio);
@@ -947,7 +985,7 @@ static ssize_t atkbd_attr_set_helper(struct device *dev, const char *buf, size_t
goto out;
}
- atkbd = serio->private;
+ atkbd = serio_get_drvdata(serio);
atkbd_disable(atkbd);
retval = handler(atkbd, buf, count);
atkbd_enable(atkbd);
@@ -1095,13 +1133,13 @@ static ssize_t atkbd_set_softraw(struct atkbd *atkbd, const char *buf, size_t co
}
-int __init atkbd_init(void)
+static int __init atkbd_init(void)
{
serio_register_driver(&atkbd_drv);
return 0;
}
-void __exit atkbd_exit(void)
+static void __exit atkbd_exit(void)
{
serio_unregister_driver(&atkbd_drv);
}
diff --git a/drivers/input/keyboard/corgikbd.c b/drivers/input/keyboard/corgikbd.c
new file mode 100644
index 0000000000000..0f1220a0ceb5d
--- /dev/null
+++ b/drivers/input/keyboard/corgikbd.c
@@ -0,0 +1,361 @@
+/*
+ * Keyboard driver for Sharp Corgi models (SL-C7xx)
+ *
+ * Copyright (c) 2004-2005 Richard Purdie
+ *
+ * Based on xtkbd.c/locomkbd.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <asm/irq.h>
+
+#include <asm/arch/corgi.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/pxa-regs.h>
+#include <asm/hardware/scoop.h>
+
+#define KB_ROWS 8
+#define KB_COLS 12
+#define KB_ROWMASK(r) (1 << (r))
+#define SCANCODE(r,c) ( ((r)<<4) + (c) + 1 )
+/* zero code, 124 scancodes + 3 hinge combinations */
+#define NR_SCANCODES ( SCANCODE(KB_ROWS-1,KB_COLS-1) +1 +1 +3 )
+#define SCAN_INTERVAL (HZ/10)
+#define CORGIKBD_PRESSED 1
+
+#define HINGE_SCAN_INTERVAL (HZ/4)
+
+#define CORGI_KEY_CALENDER KEY_F1
+#define CORGI_KEY_ADDRESS KEY_F2
+#define CORGI_KEY_FN KEY_F3
+#define CORGI_KEY_OFF KEY_SUSPEND
+#define CORGI_KEY_EXOK KEY_F5
+#define CORGI_KEY_EXCANCEL KEY_F6
+#define CORGI_KEY_EXJOGDOWN KEY_F7
+#define CORGI_KEY_EXJOGUP KEY_F8
+#define CORGI_KEY_JAP1 KEY_LEFTCTRL
+#define CORGI_KEY_JAP2 KEY_LEFTALT
+#define CORGI_KEY_OK KEY_F11
+#define CORGI_KEY_MENU KEY_F12
+#define CORGI_HINGE_0 KEY_KP0
+#define CORGI_HINGE_1 KEY_KP1
+#define CORGI_HINGE_2 KEY_KP2
+
+static unsigned char corgikbd_keycode[NR_SCANCODES] = {
+ 0, /* 0 */
+ 0, KEY_1, KEY_3, KEY_5, KEY_6, KEY_7, KEY_9, KEY_0, KEY_BACKSPACE, 0, 0, 0, 0, 0, 0, 0, /* 1-16 */
+ 0, KEY_2, KEY_4, KEY_R, KEY_Y, KEY_8, KEY_I, KEY_O, KEY_P, 0, 0, 0, 0, 0, 0, 0, /* 17-32 */
+ KEY_TAB, KEY_Q, KEY_E, KEY_T, KEY_G, KEY_U, KEY_J, KEY_K, 0, 0, 0, 0, 0, 0, 0, 0, /* 33-48 */
+ CORGI_KEY_CALENDER, KEY_W, KEY_S, KEY_F, KEY_V, KEY_H, KEY_M, KEY_L, 0, KEY_RIGHTSHIFT, 0, 0, 0, 0, 0, 0, /* 49-64 */
+ CORGI_KEY_ADDRESS, KEY_A, KEY_D, KEY_C, KEY_B, KEY_N, KEY_DOT, 0, KEY_ENTER, 0, KEY_LEFTSHIFT, 0, 0, 0, 0, 0, /* 65-80 */
+ KEY_MAIL, KEY_Z, KEY_X, KEY_MINUS, KEY_SPACE, KEY_COMMA, 0, KEY_UP, 0, 0, 0, CORGI_KEY_FN, 0, 0, 0, 0, /* 81-96 */
+ KEY_SYSRQ, CORGI_KEY_JAP1, CORGI_KEY_JAP2, KEY_CANCEL, CORGI_KEY_OK, CORGI_KEY_MENU, KEY_LEFT, KEY_DOWN, KEY_RIGHT, 0, 0, 0, 0, 0, 0, 0, /* 97-112 */
+ CORGI_KEY_OFF, CORGI_KEY_EXOK, CORGI_KEY_EXCANCEL, CORGI_KEY_EXJOGDOWN, CORGI_KEY_EXJOGUP, 0, 0, 0, 0, 0, 0, 0, /* 113-124 */
+ CORGI_HINGE_0, CORGI_HINGE_1, CORGI_HINGE_2 /* 125-127 */
+};
+
+
+struct corgikbd {
+ unsigned char keycode[ARRAY_SIZE(corgikbd_keycode)];
+ struct input_dev input;
+ char phys[32];
+
+ unsigned char state[ARRAY_SIZE(corgikbd_keycode)];
+ spinlock_t lock;
+
+ struct timer_list timer;
+ struct timer_list htimer;
+};
+
+static void handle_scancode(unsigned int pressed,unsigned int scancode, struct corgikbd *corgikbd_data)
+{
+ if (pressed && !(corgikbd_data->state[scancode] & CORGIKBD_PRESSED)) {
+ corgikbd_data->state[scancode] |= CORGIKBD_PRESSED;
+ input_report_key(&corgikbd_data->input, corgikbd_data->keycode[scancode], 1);
+ if (corgikbd_data->keycode[scancode] == CORGI_KEY_OFF)
+ input_event(&corgikbd_data->input, EV_PWR, CORGI_KEY_OFF, 1);
+ } else if (!pressed && corgikbd_data->state[scancode] & CORGIKBD_PRESSED) {
+ corgikbd_data->state[scancode] &= ~CORGIKBD_PRESSED;
+ input_report_key(&corgikbd_data->input, corgikbd_data->keycode[scancode], 0);
+ }
+}
+
+#define KB_DISCHARGE_DELAY 10
+#define KB_ACTIVATE_DELAY 10
+
+/* Helper functions for reading the keyboard matrix
+ * Note: We should really be using pxa_gpio_mode to alter GPDR but it
+ * requires a function call per GPIO bit which is excessive
+ * when we need to access 12 bits at once multiple times.
+ * These functions must be called within local_irq_save()/local_irq_restore()
+ * or similar.
+ */
+static inline void corgikbd_discharge_all(void)
+{
+ // STROBE All HiZ
+ GPCR2 = CORGI_GPIO_ALL_STROBE_BIT;
+ GPDR2 &= ~CORGI_GPIO_ALL_STROBE_BIT;
+}
+
+static inline void corgikbd_activate_all(void)
+{
+ // STROBE ALL -> High
+ GPSR2 = CORGI_GPIO_ALL_STROBE_BIT;
+ GPDR2 |= CORGI_GPIO_ALL_STROBE_BIT;
+
+ udelay(KB_DISCHARGE_DELAY);
+
+ // Clear any interrupts we may have triggered when altering the GPIO lines
+ GEDR1 = CORGI_GPIO_HIGH_SENSE_BIT;
+ GEDR2 = CORGI_GPIO_LOW_SENSE_BIT;
+}
+
+static inline void corgikbd_activate_col(int col)
+{
+ // STROBE col -> High, not col -> HiZ
+ GPSR2 = CORGI_GPIO_STROBE_BIT(col);
+ GPDR2 = (GPDR2 & ~CORGI_GPIO_ALL_STROBE_BIT) | CORGI_GPIO_STROBE_BIT(col);
+}
+
+static inline void corgikbd_reset_col(int col)
+{
+ // STROBE col -> Low
+ GPCR2 = CORGI_GPIO_STROBE_BIT(col);
+ // STROBE col -> out, not col -> HiZ
+ GPDR2 = (GPDR2 & ~CORGI_GPIO_ALL_STROBE_BIT) | CORGI_GPIO_STROBE_BIT(col);
+}
+
+#define GET_ROWS_STATUS(c) (((GPLR1 & CORGI_GPIO_HIGH_SENSE_BIT) >> CORGI_GPIO_HIGH_SENSE_RSHIFT) | ((GPLR2 & CORGI_GPIO_LOW_SENSE_BIT) << CORGI_GPIO_LOW_SENSE_LSHIFT))
+
+/*
+ * The corgi keyboard only generates interrupts when a key is pressed.
+ * When a key is pressed, we enable a timer which then scans the
+ * keyboard to detect when the key is released.
+ */
+
+/* Scan the hardware keyboard and push any changes up through the input layer */
+static void corgikbd_scankeyboard(struct corgikbd *corgikbd_data, struct pt_regs *regs)
+{
+ unsigned int row, col, rowd, scancode;
+ unsigned long flags;
+ unsigned int num_pressed;
+
+ spin_lock_irqsave(&corgikbd_data->lock, flags);
+
+ if (regs)
+ input_regs(&corgikbd_data->input, regs);
+
+ num_pressed = 0;
+ for (col = 0; col < KB_COLS; col++) {
+ /*
+ * Discharge the output driver capacitatance
+ * in the keyboard matrix. (Yes it is significant..)
+ */
+
+ corgikbd_discharge_all();
+ udelay(KB_DISCHARGE_DELAY);
+
+ corgikbd_activate_col(col);
+ udelay(KB_ACTIVATE_DELAY);
+
+ rowd = GET_ROWS_STATUS(col);
+ for (row = 0; row < KB_ROWS; row++) {
+ scancode = SCANCODE(row, col);
+ handle_scancode((rowd & KB_ROWMASK(row)), scancode, corgikbd_data);
+ if (rowd & KB_ROWMASK(row))
+ num_pressed++;
+ }
+ corgikbd_reset_col(col);
+ }
+
+ corgikbd_activate_all();
+
+ input_sync(&corgikbd_data->input);
+
+ /* if any keys are pressed, enable the timer */
+ if (num_pressed)
+ mod_timer(&corgikbd_data->timer, jiffies + SCAN_INTERVAL);
+
+ spin_unlock_irqrestore(&corgikbd_data->lock, flags);
+}
+
+/*
+ * corgi keyboard interrupt handler.
+ */
+static irqreturn_t corgikbd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct corgikbd *corgikbd_data = dev_id;
+
+ if (!timer_pending(&corgikbd_data->timer)) {
+ /** wait chattering delay **/
+ udelay(20);
+ corgikbd_scankeyboard(corgikbd_data, regs);
+ }
+
+ return IRQ_HANDLED;
+}
+
+/*
+ * corgi timer checking for released keys
+ */
+static void corgikbd_timer_callback(unsigned long data)
+{
+ struct corgikbd *corgikbd_data = (struct corgikbd *) data;
+ corgikbd_scankeyboard(corgikbd_data, NULL);
+}
+
+/*
+ * The hinge switches generate no interrupt so they need to be
+ * monitored by a timer.
+ *
+ * When we detect changes, we debounce it and then pass the three
+ * positions the system can take as keypresses to the input system.
+ */
+
+#define HINGE_STABLE_COUNT 2
+static int sharpsl_hinge_state;
+static int hinge_count;
+
+static void corgikbd_hinge_timer(unsigned long data)
+{
+ struct corgikbd *corgikbd_data = (struct corgikbd *) data;
+ unsigned long gprr;
+ unsigned long flags;
+
+ gprr = read_scoop_reg(SCOOP_GPRR) & (CORGI_SCP_SWA | CORGI_SCP_SWB);
+ if (gprr != sharpsl_hinge_state) {
+ hinge_count = 0;
+ sharpsl_hinge_state = gprr;
+ } else if (hinge_count < HINGE_STABLE_COUNT) {
+ hinge_count++;
+ if (hinge_count >= HINGE_STABLE_COUNT) {
+ spin_lock_irqsave(&corgikbd_data->lock, flags);
+
+ handle_scancode((sharpsl_hinge_state == 0x00), 125, corgikbd_data); /* Keyboard with Landscape Screen */
+ handle_scancode((sharpsl_hinge_state == 0x08), 126, corgikbd_data); /* No Keyboard with Portrait Screen */
+ handle_scancode((sharpsl_hinge_state == 0x0c), 127, corgikbd_data); /* Keyboard and Screen Closed */
+ input_sync(&corgikbd_data->input);
+
+ spin_unlock_irqrestore(&corgikbd_data->lock, flags);
+ }
+ }
+ mod_timer(&corgikbd_data->htimer, jiffies + HINGE_SCAN_INTERVAL);
+}
+
+static int __init corgikbd_probe(struct device *dev)
+{
+ int i;
+ struct corgikbd *corgikbd;
+
+ corgikbd = kcalloc(1, sizeof(struct corgikbd), GFP_KERNEL);
+ if (!corgikbd)
+ return -ENOMEM;
+
+ dev_set_drvdata(dev,corgikbd);
+ strcpy(corgikbd->phys, "corgikbd/input0");
+
+ spin_lock_init(corgikbd->lock);
+
+ /* Init Keyboard rescan timer */
+ init_timer(&corgikbd->timer);
+ corgikbd->timer.function = corgikbd_timer_callback;
+ corgikbd->timer.data = (unsigned long) corgikbd;
+
+ /* Init Hinge Timer */
+ init_timer(&corgikbd->htimer);
+ corgikbd->htimer.function = corgikbd_hinge_timer;
+ corgikbd->htimer.data = (unsigned long) corgikbd;
+
+ init_input_dev(&corgikbd->input);
+ corgikbd->input.private = corgikbd;
+ corgikbd->input.name = "Corgi Keyboard";
+ corgikbd->input.dev = dev;
+ corgikbd->input.phys = corgikbd->phys;
+ corgikbd->input.id.bustype = BUS_HOST;
+ corgikbd->input.id.vendor = 0x0001;
+ corgikbd->input.id.product = 0x0001;
+ corgikbd->input.id.version = 0x0100;
+ corgikbd->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_PWR);
+ corgikbd->input.keycode = corgikbd->keycode;
+ corgikbd->input.keycodesize = sizeof(unsigned char);
+ corgikbd->input.keycodemax = ARRAY_SIZE(corgikbd_keycode);
+
+ memcpy(corgikbd->keycode, corgikbd_keycode, sizeof(corgikbd->keycode));
+ for (i = 0; i < ARRAY_SIZE(corgikbd_keycode); i++)
+ set_bit(corgikbd->keycode[i], corgikbd->input.keybit);
+ clear_bit(0, corgikbd->input.keybit);
+
+ input_register_device(&corgikbd->input);
+ mod_timer(&corgikbd->htimer, jiffies + HINGE_SCAN_INTERVAL);
+
+ /* Setup sense interrupts - RisingEdge Detect, sense lines as inputs */
+ 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))
+ 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 */
+ for (i = 0; i < CORGI_KEY_STROBE_NUM; i++)
+ pxa_gpio_mode(CORGI_GPIO_KEY_STROBE(i) | GPIO_OUT | GPIO_DFLT_HIGH);
+
+ printk(KERN_INFO "input: Corgi Keyboard Registered\n");
+
+ return 0;
+}
+
+static int corgikbd_remove(struct device *dev)
+{
+ int i;
+ struct corgikbd *corgikbd = dev_get_drvdata(dev);
+
+ for (i = 0; i < CORGI_KEY_SENSE_NUM; i++)
+ free_irq(CORGI_IRQ_GPIO_KEY_SENSE(i), corgikbd);
+
+ del_timer_sync(&corgikbd->htimer);
+ del_timer_sync(&corgikbd->timer);
+
+ input_unregister_device(&corgikbd->input);
+
+ kfree(corgikbd);
+
+ return 0;
+}
+
+static struct device_driver corgikbd_driver = {
+ .name = "corgi-keyboard",
+ .bus = &platform_bus_type,
+ .probe = corgikbd_probe,
+ .remove = corgikbd_remove,
+};
+
+static int __devinit corgikbd_init(void)
+{
+ return driver_register(&corgikbd_driver);
+}
+
+static void __exit corgikbd_exit(void)
+{
+ driver_unregister(&corgikbd_driver);
+}
+
+module_init(corgikbd_init);
+module_exit(corgikbd_exit);
+
+MODULE_AUTHOR("Richard Purdie <rpurdie@rpsys.net>");
+MODULE_DESCRIPTION("Corgi Keyboard Driver");
+MODULE_LICENSE("GPLv2");
diff --git a/drivers/input/keyboard/hil_kbd.c b/drivers/input/keyboard/hil_kbd.c
new file mode 100644
index 0000000000000..ef78bffed5e7b
--- /dev/null
+++ b/drivers/input/keyboard/hil_kbd.c
@@ -0,0 +1,375 @@
+/*
+ * Generic linux-input device driver for keyboard devices
+ *
+ * Copyright (c) 2001 Brian S. Julin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. The name of the author may not 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").
+ *
+ * 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
+ *
+ * References:
+ * HP-HIL Technical Reference Manual. Hewlett Packard Product No. 45918A
+ *
+ */
+
+#include <linux/hil.h>
+#include <linux/input.h>
+#include <linux/serio.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/pci_ids.h>
+
+#define PREFIX "HIL KEYB: "
+#define HIL_GENERIC_NAME "HIL keyboard"
+
+MODULE_AUTHOR("Brian S. Julin <bri@calyx.com>");
+MODULE_DESCRIPTION(HIL_GENERIC_NAME " driver");
+MODULE_LICENSE("Dual BSD/GPL");
+
+#define HIL_KBD_MAX_LENGTH 16
+
+#define HIL_KBD_SET1_UPBIT 0x01
+#define HIL_KBD_SET1_SHIFT 1
+static unsigned int hil_kbd_set1[HIL_KEYCODES_SET1_TBLSIZE] =
+ { HIL_KEYCODES_SET1 };
+
+#define HIL_KBD_SET2_UPBIT 0x01
+#define HIL_KBD_SET2_SHIFT 1
+/* Set2 is user defined */
+
+#define HIL_KBD_SET3_UPBIT 0x80
+#define HIL_KBD_SET3_SHIFT 0
+static unsigned int hil_kbd_set3[HIL_KEYCODES_SET3_TBLSIZE] =
+ { HIL_KEYCODES_SET3 };
+
+static char hil_language[][16] = { HIL_LOCALE_MAP };
+
+struct hil_kbd {
+ struct input_dev dev;
+ struct serio *serio;
+
+ /* Input buffer and index for packets from HIL bus. */
+ hil_packet data[HIL_KBD_MAX_LENGTH];
+ int idx4; /* four counts per packet */
+
+ /* Raw device info records from HIL bus, see hil.h for fields. */
+ char idd[HIL_KBD_MAX_LENGTH]; /* DID byte and IDD record */
+ char rsc[HIL_KBD_MAX_LENGTH]; /* RSC record */
+ char exd[HIL_KBD_MAX_LENGTH]; /* EXD record */
+ char rnm[HIL_KBD_MAX_LENGTH + 1]; /* RNM record + NULL term. */
+
+ /* Something to sleep around with. */
+ struct semaphore sem;
+};
+
+/* Process a complete packet after transfer from the HIL */
+static void hil_kbd_process_record(struct hil_kbd *kbd)
+{
+ struct input_dev *dev = &kbd->dev;
+ hil_packet *data = kbd->data;
+ hil_packet p;
+ int idx, i, cnt;
+
+ idx = kbd->idx4/4;
+ p = data[idx - 1];
+
+ if ((p & ~HIL_CMDCT_POL) ==
+ (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL)) goto report;
+ if ((p & ~HIL_CMDCT_RPL) ==
+ (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_RPL)) goto report;
+
+ /* Not a poll response. See if we are loading config records. */
+ switch (p & HIL_PKT_DATA_MASK) {
+ case HIL_CMD_IDD:
+ for (i = 0; i < idx; i++)
+ kbd->idd[i] = kbd->data[i] & HIL_PKT_DATA_MASK;
+ for (; i < HIL_KBD_MAX_LENGTH; i++)
+ kbd->idd[i] = 0;
+ break;
+ case HIL_CMD_RSC:
+ for (i = 0; i < idx; i++)
+ kbd->rsc[i] = kbd->data[i] & HIL_PKT_DATA_MASK;
+ for (; i < HIL_KBD_MAX_LENGTH; i++)
+ kbd->rsc[i] = 0;
+ break;
+ case HIL_CMD_EXD:
+ for (i = 0; i < idx; i++)
+ kbd->exd[i] = kbd->data[i] & HIL_PKT_DATA_MASK;
+ for (; i < HIL_KBD_MAX_LENGTH; i++)
+ kbd->exd[i] = 0;
+ break;
+ case HIL_CMD_RNM:
+ for (i = 0; i < idx; i++)
+ kbd->rnm[i] = kbd->data[i] & HIL_PKT_DATA_MASK;
+ for (; i < HIL_KBD_MAX_LENGTH + 1; i++)
+ kbd->rnm[i] = '\0';
+ break;
+ default:
+ /* These occur when device isn't present */
+ if (p == (HIL_ERR_INT | HIL_PKT_CMD)) break;
+ /* Anything else we'd like to know about. */
+ printk(KERN_WARNING PREFIX "Device sent unknown record %x\n", p);
+ break;
+ }
+ goto out;
+
+ report:
+ cnt = 1;
+ switch (kbd->data[0] & HIL_POL_CHARTYPE_MASK) {
+ case HIL_POL_CHARTYPE_NONE:
+ break;
+ case HIL_POL_CHARTYPE_ASCII:
+ while (cnt < idx - 1)
+ input_report_key(dev, kbd->data[cnt++] & 0x7f, 1);
+ break;
+ case HIL_POL_CHARTYPE_RSVD1:
+ case HIL_POL_CHARTYPE_RSVD2:
+ case HIL_POL_CHARTYPE_BINARY:
+ while (cnt < idx - 1)
+ input_report_key(dev, kbd->data[cnt++], 1);
+ break;
+ case HIL_POL_CHARTYPE_SET1:
+ while (cnt < idx - 1) {
+ unsigned int key;
+ int up;
+ key = kbd->data[cnt++];
+ up = key & HIL_KBD_SET1_UPBIT;
+ key &= (~HIL_KBD_SET1_UPBIT & 0xff);
+ key = hil_kbd_set1[key >> HIL_KBD_SET1_SHIFT];
+ if (key != KEY_RESERVED)
+ input_report_key(dev, key, !up);
+ }
+ break;
+ case HIL_POL_CHARTYPE_SET2:
+ while (cnt < idx - 1) {
+ unsigned int key;
+ int up;
+ key = kbd->data[cnt++];
+ up = key & HIL_KBD_SET2_UPBIT;
+ key &= (~HIL_KBD_SET1_UPBIT & 0xff);
+ key = key >> HIL_KBD_SET2_SHIFT;
+ if (key != KEY_RESERVED)
+ input_report_key(dev, key, !up);
+ }
+ break;
+ case HIL_POL_CHARTYPE_SET3:
+ while (cnt < idx - 1) {
+ unsigned int key;
+ int up;
+ key = kbd->data[cnt++];
+ up = key & HIL_KBD_SET3_UPBIT;
+ key &= (~HIL_KBD_SET1_UPBIT & 0xff);
+ key = hil_kbd_set3[key >> HIL_KBD_SET3_SHIFT];
+ if (key != KEY_RESERVED)
+ input_report_key(dev, key, !up);
+ }
+ break;
+ }
+ out:
+ kbd->idx4 = 0;
+ up(&kbd->sem);
+}
+
+static void hil_kbd_process_err(struct hil_kbd *kbd) {
+ printk(KERN_WARNING PREFIX "errored HIL packet\n");
+ kbd->idx4 = 0;
+ up(&kbd->sem);
+}
+
+static irqreturn_t hil_kbd_interrupt(struct serio *serio,
+ unsigned char data, unsigned int flags, struct pt_regs *regs)
+{
+ struct hil_kbd *kbd;
+ hil_packet packet;
+ int idx;
+
+ kbd = (struct hil_kbd *)serio->private;
+ if (kbd == NULL) {
+ BUG();
+ return IRQ_HANDLED;
+ }
+
+ if (kbd->idx4 >= (HIL_KBD_MAX_LENGTH * sizeof(hil_packet))) {
+ hil_kbd_process_err(kbd);
+ return IRQ_HANDLED;
+ }
+ idx = kbd->idx4/4;
+ if (!(kbd->idx4 % 4)) kbd->data[idx] = 0;
+ packet = kbd->data[idx];
+ packet |= ((hil_packet)data) << ((3 - (kbd->idx4 % 4)) * 8);
+ kbd->data[idx] = packet;
+
+ /* Records of N 4-byte hil_packets must terminate with a command. */
+ if ((++(kbd->idx4)) % 4) return IRQ_HANDLED;
+ if ((packet & 0xffff0000) != HIL_ERR_INT) {
+ hil_kbd_process_err(kbd);
+ return IRQ_HANDLED;
+ }
+ if (packet & HIL_PKT_CMD) hil_kbd_process_record(kbd);
+ return IRQ_HANDLED;
+}
+
+static void hil_kbd_disconnect(struct serio *serio)
+{
+ struct hil_kbd *kbd;
+
+ kbd = (struct hil_kbd *)serio->private;
+ if (kbd == NULL) {
+ BUG();
+ return;
+ }
+
+ input_unregister_device(&kbd->dev);
+ serio_close(serio);
+ kfree(kbd);
+}
+
+static void hil_kbd_connect(struct serio *serio, struct serio_driver *drv)
+{
+ struct hil_kbd *kbd;
+ uint8_t did, *idd;
+ int i;
+
+ if (serio->type != (SERIO_HIL_MLC | SERIO_HIL)) return;
+
+ if (!(kbd = kmalloc(sizeof(struct hil_kbd), GFP_KERNEL))) return;
+ memset(kbd, 0, sizeof(struct hil_kbd));
+
+ if (serio_open(serio, drv)) goto bail0;
+
+ serio->private = kbd;
+ kbd->serio = serio;
+ kbd->dev.private = kbd;
+
+ init_MUTEX_LOCKED(&(kbd->sem));
+
+ /* Get device info. MLC driver supplies devid/status/etc. */
+ serio->write(serio, 0);
+ serio->write(serio, 0);
+ serio->write(serio, HIL_PKT_CMD >> 8);
+ serio->write(serio, HIL_CMD_IDD);
+ down(&(kbd->sem));
+
+ serio->write(serio, 0);
+ serio->write(serio, 0);
+ serio->write(serio, HIL_PKT_CMD >> 8);
+ serio->write(serio, HIL_CMD_RSC);
+ down(&(kbd->sem));
+
+ serio->write(serio, 0);
+ serio->write(serio, 0);
+ serio->write(serio, HIL_PKT_CMD >> 8);
+ serio->write(serio, HIL_CMD_RNM);
+ down(&(kbd->sem));
+
+ serio->write(serio, 0);
+ serio->write(serio, 0);
+ serio->write(serio, HIL_PKT_CMD >> 8);
+ serio->write(serio, HIL_CMD_EXD);
+ down(&(kbd->sem));
+
+ up(&(kbd->sem));
+
+ did = kbd->idd[0];
+ idd = kbd->idd + 1;
+ switch (did & HIL_IDD_DID_TYPE_MASK) {
+ case HIL_IDD_DID_TYPE_KB_INTEGRAL:
+ case HIL_IDD_DID_TYPE_KB_ITF:
+ case HIL_IDD_DID_TYPE_KB_RSVD:
+ case HIL_IDD_DID_TYPE_CHAR:
+ printk(KERN_INFO PREFIX "HIL keyboard found (did = 0x%02x, lang = %s)\n",
+ did, hil_language[did & HIL_IDD_DID_TYPE_KB_LANG_MASK]);
+ break;
+ default:
+ goto bail1;
+ }
+
+ if(HIL_IDD_NUM_BUTTONS(idd) || HIL_IDD_NUM_AXES_PER_SET(*idd)) {
+ printk(KERN_INFO PREFIX "keyboards only, no combo devices supported.\n");
+ goto bail1;
+ }
+
+
+ kbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
+ kbd->dev.ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL);
+ kbd->dev.keycodemax = HIL_KEYCODES_SET1_TBLSIZE;
+ kbd->dev.keycodesize = sizeof(hil_kbd_set1[0]);
+ kbd->dev.keycode = hil_kbd_set1;
+ kbd->dev.name = strlen(kbd->rnm) ? kbd->rnm : HIL_GENERIC_NAME;
+ kbd->dev.phys = "hpkbd/input0"; /* XXX */
+
+ kbd->dev.id.bustype = BUS_HIL;
+ kbd->dev.id.vendor = PCI_VENDOR_ID_HP;
+ kbd->dev.id.product = 0x0001; /* TODO: get from kbd->rsc */
+ kbd->dev.id.version = 0x0100; /* TODO: get from kbd->rsc */
+ kbd->dev.dev = &serio->dev;
+
+ for (i = 0; i < 128; i++) {
+ set_bit(hil_kbd_set1[i], kbd->dev.keybit);
+ set_bit(hil_kbd_set3[i], kbd->dev.keybit);
+ }
+ clear_bit(0, kbd->dev.keybit);
+
+ input_register_device(&kbd->dev);
+ printk(KERN_INFO "input: %s, ID: %d\n",
+ kbd->dev.name, did);
+
+ serio->write(serio, 0);
+ serio->write(serio, 0);
+ serio->write(serio, HIL_PKT_CMD >> 8);
+ serio->write(serio, HIL_CMD_EK1); /* Enable Keyswitch Autorepeat 1 */
+ down(&(kbd->sem));
+ up(&(kbd->sem));
+
+ return;
+ bail1:
+ serio_close(serio);
+ bail0:
+ kfree(kbd);
+}
+
+
+struct serio_driver hil_kbd_serio_drv = {
+ .driver = {
+ .name = "hil_kbd",
+ },
+ .description = "HP HIL keyboard driver",
+ .connect = hil_kbd_connect,
+ .disconnect = hil_kbd_disconnect,
+ .interrupt = hil_kbd_interrupt
+};
+
+static int __init hil_kbd_init(void)
+{
+ serio_register_driver(&hil_kbd_serio_drv);
+ return 0;
+}
+
+static void __exit hil_kbd_exit(void)
+{
+ serio_unregister_driver(&hil_kbd_serio_drv);
+}
+
+module_init(hil_kbd_init);
+module_exit(hil_kbd_exit);
diff --git a/drivers/input/keyboard/hilkbd.c b/drivers/input/keyboard/hilkbd.c
new file mode 100644
index 0000000000000..eecb77db08477
--- /dev/null
+++ b/drivers/input/keyboard/hilkbd.c
@@ -0,0 +1,343 @@
+/*
+ * linux/drivers/hil/hilkbd.c
+ *
+ * Copyright (C) 1998 Philip Blundell <philb@gnu.org>
+ * Copyright (C) 1999 Matthew Wilcox <willy@bofh.ai>
+ * Copyright (C) 1999-2003 Helge Deller <deller@gmx.de>
+ *
+ * Very basic HP Human Interface Loop (HIL) driver.
+ * This driver handles the keyboard on HP300 (m68k) and on some
+ * HP700 (parisc) series machines.
+ *
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License version 2. See the file COPYING in the main directory of this
+ * archive for more details.
+ */
+
+#include <linux/pci_ids.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/input.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/hil.h>
+#include <linux/spinlock.h>
+
+
+MODULE_AUTHOR("Philip Blundell, Matthew Wilcox, Helge Deller");
+MODULE_DESCRIPTION("HIL keyboard driver (basic functionality)");
+MODULE_LICENSE("GPL v2");
+
+
+#if defined(CONFIG_PARISC)
+
+ #include <asm/io.h>
+ #include <asm/hardware.h>
+ #include <asm/parisc-device.h>
+ static unsigned long hil_base; /* HPA for the HIL device */
+ static unsigned int hil_irq;
+ #define HILBASE hil_base /* HPPA (parisc) port address */
+ #define HIL_DATA 0x800
+ #define HIL_CMD 0x801
+ #define HIL_IRQ hil_irq
+ #define hil_readb(p) gsc_readb(p)
+ #define hil_writeb(v,p) gsc_writeb((v),(p))
+
+#elif defined(CONFIG_HP300)
+
+ #define HILBASE 0xf0428000 /* HP300 (m86k) port address */
+ #define HIL_DATA 0x1
+ #define HIL_CMD 0x3
+ #define HIL_IRQ 2
+ #define hil_readb(p) readb(p)
+ #define hil_writeb(v,p) writeb((v),(p))
+
+#else
+#error "HIL is not supported on this platform"
+#endif
+
+
+
+/* HIL helper functions */
+
+#define hil_busy() (hil_readb(HILBASE + HIL_CMD) & HIL_BUSY)
+#define hil_data_available() (hil_readb(HILBASE + HIL_CMD) & HIL_DATA_RDY)
+#define hil_status() (hil_readb(HILBASE + HIL_CMD))
+#define hil_command(x) do { hil_writeb((x), HILBASE + HIL_CMD); } while (0)
+#define hil_read_data() (hil_readb(HILBASE + HIL_DATA))
+#define hil_write_data(x) do { hil_writeb((x), HILBASE + HIL_DATA); } while (0)
+
+/* HIL constants */
+
+#define HIL_BUSY 0x02
+#define HIL_DATA_RDY 0x01
+
+#define HIL_SETARD 0xA0 /* set auto-repeat delay */
+#define HIL_SETARR 0xA2 /* set auto-repeat rate */
+#define HIL_SETTONE 0xA3 /* set tone generator */
+#define HIL_CNMT 0xB2 /* clear nmi */
+#define HIL_INTON 0x5C /* Turn on interrupts. */
+#define HIL_INTOFF 0x5D /* Turn off interrupts. */
+
+#define HIL_READKBDSADR 0xF9
+#define HIL_WRITEKBDSADR 0xE9
+
+static unsigned int hphilkeyb_keycode[HIL_KEYCODES_SET1_TBLSIZE] =
+ { HIL_KEYCODES_SET1 };
+
+/* HIL structure */
+static struct {
+ struct input_dev dev;
+
+ unsigned int curdev;
+
+ unsigned char s;
+ unsigned char c;
+ int valid;
+
+ unsigned char data[16];
+ unsigned int ptr;
+ spinlock_t lock;
+
+ void *dev_id; /* native bus device */
+} hil_dev;
+
+
+static void poll_finished(void)
+{
+ int down;
+ int key;
+ unsigned char scode;
+
+ switch (hil_dev.data[0]) {
+ case 0x40:
+ down = (hil_dev.data[1] & 1) == 0;
+ scode = hil_dev.data[1] >> 1;
+ key = hphilkeyb_keycode[scode];
+ input_report_key(&hil_dev.dev, key, down);
+ break;
+ }
+ hil_dev.curdev = 0;
+}
+
+static inline void handle_status(unsigned char s, unsigned char c)
+{
+ if (c & 0x8) {
+ /* End of block */
+ if (c & 0x10)
+ poll_finished();
+ } else {
+ if (c & 0x10) {
+ if (hil_dev.curdev)
+ poll_finished(); /* just in case */
+ hil_dev.curdev = c & 7;
+ hil_dev.ptr = 0;
+ }
+ }
+}
+
+static inline void handle_data(unsigned char s, unsigned char c)
+{
+ if (hil_dev.curdev) {
+ hil_dev.data[hil_dev.ptr++] = c;
+ hil_dev.ptr &= 15;
+ }
+}
+
+
+/*
+ * Handle HIL interrupts.
+ */
+static irqreturn_t hil_interrupt(int irq, void *handle, struct pt_regs *regs)
+{
+ unsigned char s, c;
+
+ s = hil_status();
+ c = hil_read_data();
+
+ switch (s >> 4) {
+ case 0x5:
+ handle_status(s, c);
+ break;
+ case 0x6:
+ handle_data(s, c);
+ break;
+ case 0x4:
+ hil_dev.s = s;
+ hil_dev.c = c;
+ mb();
+ hil_dev.valid = 1;
+ break;
+ }
+ return IRQ_HANDLED;
+}
+
+/*
+ * Send a command to the HIL
+ */
+
+static void hil_do(unsigned char cmd, unsigned char *data, unsigned int len)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&hil_dev.lock, flags);
+ while (hil_busy())
+ /* wait */;
+ hil_command(cmd);
+ while (len--) {
+ while (hil_busy())
+ /* wait */;
+ hil_write_data(*(data++));
+ }
+ spin_unlock_irqrestore(&hil_dev.lock, flags);
+}
+
+
+/*
+ * Initialise HIL.
+ */
+
+static int __init
+hil_keyb_init(void)
+{
+ unsigned char c;
+ unsigned int i, kbid;
+ wait_queue_head_t hil_wait;
+
+ if (hil_dev.dev.id.bustype) {
+ return -ENODEV; /* already initialized */
+ }
+
+#if defined(CONFIG_HP300)
+ if (!hwreg_present((void *)(HILBASE + HIL_DATA)))
+ return -ENODEV;
+
+ request_region(HILBASE+HIL_DATA, 2, "hil");
+#endif
+
+ request_irq(HIL_IRQ, hil_interrupt, 0, "hil", hil_dev.dev_id);
+
+ /* Turn on interrupts */
+ hil_do(HIL_INTON, NULL, 0);
+
+ /* Look for keyboards */
+ hil_dev.valid = 0; /* clear any pending data */
+ hil_do(HIL_READKBDSADR, NULL, 0);
+
+ init_waitqueue_head(&hil_wait);
+ wait_event_interruptible_timeout(hil_wait, hil_dev.valid, 3*HZ);
+ if (!hil_dev.valid) {
+ printk(KERN_WARNING "HIL: timed out, assuming no keyboard present.\n");
+ }
+
+ c = hil_dev.c;
+ hil_dev.valid = 0;
+ if (c == 0) {
+ kbid = -1;
+ printk(KERN_WARNING "HIL: no keyboard present.\n");
+ } else {
+ kbid = ffz(~c);
+ /* printk(KERN_INFO "HIL: keyboard found at id %d\n", kbid); */
+ }
+
+ /* set it to raw mode */
+ c = 0;
+ hil_do(HIL_WRITEKBDSADR, &c, 1);
+
+ init_input_dev(&hil_dev.dev);
+
+ for (i = 0; i < HIL_KEYCODES_SET1_TBLSIZE; i++)
+ if (hphilkeyb_keycode[i] != KEY_RESERVED)
+ set_bit(hphilkeyb_keycode[i], hil_dev.dev.keybit);
+
+ hil_dev.dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
+ hil_dev.dev.ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL);
+ hil_dev.dev.keycodemax = HIL_KEYCODES_SET1_TBLSIZE;
+ hil_dev.dev.keycodesize = sizeof(hphilkeyb_keycode[0]);
+ hil_dev.dev.keycode = hphilkeyb_keycode;
+ hil_dev.dev.name = "HIL keyboard";
+ hil_dev.dev.phys = "hpkbd/input0";
+
+ hil_dev.dev.id.bustype = BUS_HIL;
+ hil_dev.dev.id.vendor = PCI_VENDOR_ID_HP;
+ hil_dev.dev.id.product = 0x0001;
+ hil_dev.dev.id.version = 0x0010;
+
+ input_register_device(&hil_dev.dev);
+ printk(KERN_INFO "input: %s, ID %d at 0x%08lx (irq %d) found and attached\n",
+ hil_dev.dev.name, kbid, HILBASE, HIL_IRQ);
+
+ return 0;
+}
+
+#if defined(CONFIG_PARISC)
+static int __init
+hil_init_chip(struct parisc_device *dev)
+{
+ if (!dev->irq) {
+ printk(KERN_WARNING "HIL: IRQ not found for HIL bus at 0x%08lx\n", dev->hpa);
+ return -ENODEV;
+ }
+
+ hil_base = dev->hpa;
+ hil_irq = dev->irq;
+ hil_dev.dev_id = dev;
+
+ printk(KERN_INFO "Found HIL bus at 0x%08lx, IRQ %d\n", hil_base, hil_irq);
+
+ return hil_keyb_init();
+}
+
+static struct parisc_device_id hil_tbl[] = {
+ { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00073 },
+ { 0, }
+};
+
+MODULE_DEVICE_TABLE(parisc, hil_tbl);
+
+static struct parisc_driver hil_driver = {
+ .name = "HIL",
+ .id_table = hil_tbl,
+ .probe = hil_init_chip,
+};
+#endif /* CONFIG_PARISC */
+
+
+
+
+
+static int __init hil_init(void)
+{
+#if defined(CONFIG_PARISC)
+ return register_parisc_driver(&hil_driver);
+#else
+ return hil_keyb_init();
+#endif
+}
+
+
+static void __exit hil_exit(void)
+{
+ if (HIL_IRQ) {
+ disable_irq(HIL_IRQ);
+ free_irq(HIL_IRQ, hil_dev.dev_id);
+ }
+
+ /* Turn off interrupts */
+ hil_do(HIL_INTOFF, NULL, 0);
+
+ input_unregister_device(&hil_dev.dev);
+
+#if defined(CONFIG_PARISC)
+ unregister_parisc_driver(&hil_driver);
+#else
+ release_region(HILBASE+HIL_DATA, 2);
+#endif
+}
+
+module_init(hil_init);
+module_exit(hil_exit);
+
diff --git a/drivers/input/keyboard/hpps2atkbd.h b/drivers/input/keyboard/hpps2atkbd.h
index 92f6e8b98b40a..dc33f6945222a 100644
--- a/drivers/input/keyboard/hpps2atkbd.h
+++ b/drivers/input/keyboard/hpps2atkbd.h
@@ -3,7 +3,7 @@
*
* Copyright (c) 2004 Helge Deller <deller@gmx.de>
* Copyright (c) 2002 Laurent Canet <canetl@esiee.fr>
- * Copyright (c) 2002 Thibaut Varene <varenet@esiee.fr>
+ * Copyright (c) 2002 Thibaut Varene <varenet@parisc-linux.org>
* Copyright (c) 2000 Xavier Debacker <debackex@esiee.fr>
*
* HP PS/2 AT-compatible Keyboard, found in PA/RISC Workstations & Laptops
@@ -14,10 +14,8 @@
*/
-/* undefine if you have a RDI PRECISIONBOOK */
-#define STANDARD_KEYBOARD
-
-#if defined(STANDARD_KEYBOARD)
+/* Is the keyboard an RDI PrecisionBook? */
+#ifndef CONFIG_KEYBOARD_ATKBD_RDI_KEYCODES
# define CONFLICT(x,y) x
#else
# define CONFLICT(x,y) y
@@ -50,10 +48,10 @@
/* 60 */ KEY_DOWN, C_61, KEY_PAUSE, KEY_UP, KEY_DELETE, KEY_END, KEY_BACKSPACE, KEY_INSERT,
/* 68 */ KEY_RESERVED, KEY_KP1, KEY_RIGHT, KEY_KP4, KEY_KP7, KEY_PAGEDOWN, KEY_HOME, KEY_PAGEUP,
/* 70 */ KEY_KP0, KEY_KPDOT, KEY_KP2, KEY_KP5, KEY_KP6, KEY_KP8, KEY_ESC, KEY_NUMLOCK,
-/* 78 */ KEY_F11, KEY_KPPLUS, KEY_KP3, KEY_KPMINUS, KEY_KPASTERISK,KEY_KP9, KEY_SCROLLLOCK,KEY_103RD,
+/* 78 */ KEY_F11, KEY_KPPLUS, KEY_KP3, KEY_KPMINUS, KEY_KPASTERISK,KEY_KP9, KEY_SCROLLLOCK,KEY_102ND,
/* 80 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
/* 88 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
-/* 90 */ KEY_RESERVED, KEY_RIGHTALT, KEY_SYSRQ, KEY_RESERVED, KEY_RIGHTCTRL, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
+/* 90 */ KEY_RESERVED, KEY_RIGHTALT, 255, KEY_RESERVED, KEY_RIGHTCTRL, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
/* 98 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_CAPSLOCK, KEY_RESERVED, KEY_LEFTMETA,
/* a0 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RIGHTMETA,
/* a8 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_COMPOSE,
@@ -103,7 +101,6 @@
/* f0 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
/* f8 */ KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED
-#undef STANDARD_KEYBOARD
#undef CONFLICT
#undef C_07
#undef C_11
diff --git a/drivers/input/keyboard/lkkbd.c b/drivers/input/keyboard/lkkbd.c
index 77aae8056c9f6..2694ff2b5beb6 100644
--- a/drivers/input/keyboard/lkkbd.c
+++ b/drivers/input/keyboard/lkkbd.c
@@ -14,14 +14,14 @@
* DISCLAIMER: This works for _me_. If you break anything by using the
* information given below, I will _not_ be liable!
*
- * RJ11 pinout: To DE9: Or DB25:
+ * RJ10 pinout: To DE9: Or DB25:
* 1 - RxD <----> Pin 3 (TxD) <-> Pin 2 (TxD)
* 2 - GND <----> Pin 5 (GND) <-> Pin 7 (GND)
* 4 - TxD <----> Pin 2 (RxD) <-> Pin 3 (RxD)
* 3 - +12V (from HDD drive connector), DON'T connect to DE9 or DB25!!!
*
* Pin numbers for DE9 and DB25 are noted on the plug (quite small:). For
- * RJ11, it's like this:
+ * RJ10, it's like this:
*
* __=__ Hold the plug in front of you, cable downwards,
* /___/| nose is hidden behind the plug. Now, pin 1 is at
@@ -417,7 +417,7 @@ static irqreturn_t
lkkbd_interrupt (struct serio *serio, unsigned char data, unsigned int flags,
struct pt_regs *regs)
{
- struct lkkbd *lk = serio->private;
+ struct lkkbd *lk = serio_get_drvdata (serio);
int i;
DBG (KERN_INFO "Got byte 0x%02x\n", data);
@@ -623,19 +623,16 @@ lkkbd_reinit (void *data)
/*
* lkkbd_connect() probes for a LK keyboard and fills the necessary structures.
*/
-static void
+static int
lkkbd_connect (struct serio *serio, struct serio_driver *drv)
{
struct lkkbd *lk;
int i;
-
- if ((serio->type & SERIO_TYPE) != SERIO_RS232)
- return;
- if ((serio->type & SERIO_PROTO) != SERIO_LKKBD)
- return;
+ int err;
if (!(lk = kmalloc (sizeof (struct lkkbd), GFP_KERNEL)))
- return;
+ return -ENOMEM;
+
memset (lk, 0, sizeof (struct lkkbd));
init_input_dev (&lk->dev);
@@ -665,11 +662,13 @@ lkkbd_connect (struct serio *serio, struct serio_driver *drv)
lk->dev.event = lkkbd_event;
lk->dev.private = lk;
- serio->private = lk;
+ serio_set_drvdata (serio, lk);
- if (serio_open (serio, drv)) {
+ err = serio_open (serio, drv);
+ if (err) {
+ serio_set_drvdata (serio, NULL);
kfree (lk);
- return;
+ return err;
}
sprintf (lk->name, "DEC LK keyboard");
@@ -691,6 +690,8 @@ lkkbd_connect (struct serio *serio, struct serio_driver *drv)
printk (KERN_INFO "input: %s on %s, initiating reset\n", lk->name, serio->phys);
lk->serio->write (lk->serio, LK_CMD_POWERCYCLE_RESET);
+
+ return 0;
}
/*
@@ -699,18 +700,32 @@ lkkbd_connect (struct serio *serio, struct serio_driver *drv)
static void
lkkbd_disconnect (struct serio *serio)
{
- struct lkkbd *lk = serio->private;
+ struct lkkbd *lk = serio_get_drvdata (serio);
input_unregister_device (&lk->dev);
serio_close (serio);
+ serio_set_drvdata (serio, NULL);
kfree (lk);
}
+static struct serio_device_id lkkbd_serio_ids[] = {
+ {
+ .type = SERIO_RS232,
+ .proto = SERIO_LKKBD,
+ .id = SERIO_ANY,
+ .extra = SERIO_ANY,
+ },
+ { 0 }
+};
+
+MODULE_DEVICE_TABLE(serio, lkkbd_serio_ids);
+
static struct serio_driver lkkbd_drv = {
.driver = {
.name = "lkkbd",
},
.description = DRIVER_DESC,
+ .id_table = lkkbd_serio_ids,
.connect = lkkbd_connect,
.disconnect = lkkbd_disconnect,
.interrupt = lkkbd_interrupt,
@@ -719,14 +734,14 @@ static struct serio_driver lkkbd_drv = {
/*
* The functions for insering/removing us as a module.
*/
-int __init
+static int __init
lkkbd_init (void)
{
serio_register_driver(&lkkbd_drv);
return 0;
}
-void __exit
+static void __exit
lkkbd_exit (void)
{
serio_unregister_driver(&lkkbd_drv);
diff --git a/drivers/input/keyboard/locomokbd.c b/drivers/input/keyboard/locomokbd.c
new file mode 100644
index 0000000000000..d3e9dd6a13cdc
--- /dev/null
+++ b/drivers/input/keyboard/locomokbd.c
@@ -0,0 +1,309 @@
+/*
+ * Copyright (c) 2005 John Lenz
+ *
+ * Based on from xtkbd.c
+ */
+
+/*
+ * LoCoMo keyboard driver for Linux/ARM
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the 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/slab.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+
+#include <asm/hardware/locomo.h>
+#include <asm/irq.h>
+
+MODULE_AUTHOR("John Lenz <lenz@cs.wisc.edu>");
+MODULE_DESCRIPTION("LoCoMo keyboard driver");
+MODULE_LICENSE("GPL");
+
+#define LOCOMOKBD_NUMKEYS 128
+
+#define KEY_ACTIVITY KEY_F16
+#define KEY_CONTACT KEY_F18
+#define KEY_CENTER KEY_F15
+
+static unsigned char locomokbd_keycode[LOCOMOKBD_NUMKEYS] = {
+ 0, KEY_ESC, KEY_ACTIVITY, 0, 0, 0, 0, 0, 0, 0, /* 0 - 9 */
+ 0, 0, 0, 0, 0, 0, 0, KEY_MENU, KEY_HOME, KEY_CONTACT, /* 10 - 19 */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 20 - 29 */
+ 0, 0, 0, KEY_CENTER, 0, KEY_MAIL, 0, 0, 0, 0, /* 30 - 39 */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_RIGHT, /* 40 - 49 */
+ KEY_UP, KEY_LEFT, 0, 0, KEY_P, 0, KEY_O, KEY_I, KEY_Y, KEY_T, /* 50 - 59 */
+ KEY_E, KEY_W, 0, 0, 0, 0, KEY_DOWN, KEY_ENTER, 0, 0, /* 60 - 69 */
+ KEY_BACKSPACE, 0, KEY_L, KEY_U, KEY_H, KEY_R, KEY_D, KEY_Q, 0, 0, /* 70 - 79 */
+ 0, 0, 0, 0, 0, 0, KEY_ENTER, KEY_RIGHTSHIFT, KEY_K, KEY_J, /* 80 - 89 */
+ KEY_G, KEY_F, KEY_X, KEY_S, 0, 0, 0, 0, 0, 0, /* 90 - 99 */
+ 0, 0, KEY_DOT, 0, KEY_COMMA, KEY_N, KEY_B, KEY_C, KEY_Z, KEY_A, /* 100 - 109 */
+ KEY_LEFTSHIFT, KEY_TAB, KEY_LEFTCTRL, 0, 0, 0, 0, 0, 0, 0, /* 110 - 119 */
+ KEY_M, KEY_SPACE, KEY_V, KEY_APOSTROPHE, KEY_SLASH, 0, 0, 0 /* 120 - 128 */
+};
+
+#define KB_ROWS 16
+#define KB_COLS 8
+#define KB_ROWMASK(r) (1 << (r))
+#define SCANCODE(c,r) ( ((c)<<4) + (r) + 1 )
+#define NR_SCANCODES 128
+
+#define KB_DELAY 8
+#define SCAN_INTERVAL (HZ/10)
+#define LOCOMOKBD_PRESSED 1
+
+struct locomokbd {
+ unsigned char keycode[LOCOMOKBD_NUMKEYS];
+ struct input_dev input;
+ char phys[32];
+
+ struct locomo_dev *ldev;
+ unsigned long base;
+ spinlock_t lock;
+
+ struct timer_list timer;
+};
+
+/* helper functions for reading the keyboard matrix */
+static inline void locomokbd_charge_all(unsigned long membase)
+{
+ locomo_writel(0x00FF, membase + LOCOMO_KSC);
+}
+
+static inline void locomokbd_activate_all(unsigned long membase)
+{
+ unsigned long r;
+
+ locomo_writel(0, membase + LOCOMO_KSC);
+ r = locomo_readl(membase + LOCOMO_KIC);
+ r &= 0xFEFF;
+ locomo_writel(r, membase + LOCOMO_KIC);
+}
+
+static inline void locomokbd_activate_col(unsigned long membase, int col)
+{
+ unsigned short nset;
+ unsigned short nbset;
+
+ nset = 0xFF & ~(1 << col);
+ nbset = (nset << 8) + nset;
+ locomo_writel(nbset, membase + LOCOMO_KSC);
+}
+
+static inline void locomokbd_reset_col(unsigned long membase, int col)
+{
+ unsigned short nbset;
+
+ nbset = ((0xFF & ~(1 << col)) << 8) + 0xFF;
+ locomo_writel(nbset, membase + LOCOMO_KSC);
+}
+
+/*
+ * The LoCoMo keyboard only generates interrupts when a key is pressed.
+ * So when a key is pressed, we enable a timer. This timer scans the
+ * keyboard, and this is how we detect when the key is released.
+ */
+
+/* Scan the hardware keyboard and push any changes up through the input layer */
+static void locomokbd_scankeyboard(struct locomokbd *locomokbd, struct pt_regs *regs)
+{
+ unsigned int row, col, rowd, scancode;
+ unsigned long flags;
+ unsigned int num_pressed;
+ unsigned long membase = locomokbd->base;
+
+ spin_lock_irqsave(&locomokbd->lock, flags);
+
+ if (regs)
+ input_regs(&locomokbd->input, regs);
+
+ locomokbd_charge_all(membase);
+
+ num_pressed = 0;
+ for (col = 0; col < KB_COLS; col++) {
+
+ locomokbd_activate_col(membase, col);
+ udelay(KB_DELAY);
+
+ rowd = ~locomo_readl(membase + LOCOMO_KIB);
+ for (row = 0; row < KB_ROWS; row++ ) {
+ scancode = SCANCODE(col, row);
+ if (rowd & KB_ROWMASK(row)) {
+ num_pressed += 1;
+ input_report_key(&locomokbd->input, locomokbd->keycode[scancode], 1);
+ } else {
+ input_report_key(&locomokbd->input, locomokbd->keycode[scancode], 0);
+ }
+ }
+ locomokbd_reset_col(membase, col);
+ }
+ locomokbd_activate_all(membase);
+
+ input_sync(&locomokbd->input);
+
+ /* if any keys are pressed, enable the timer */
+ if (num_pressed)
+ mod_timer(&locomokbd->timer, jiffies + SCAN_INTERVAL);
+
+ spin_unlock_irqrestore(&locomokbd->lock, flags);
+}
+
+/*
+ * LoCoMo keyboard interrupt handler.
+ */
+static irqreturn_t locomokbd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct locomokbd *locomokbd = dev_id;
+ /** wait chattering delay **/
+ udelay(100);
+
+ locomokbd_scankeyboard(locomokbd, regs);
+
+ return IRQ_HANDLED;
+}
+
+/*
+ * LoCoMo timer checking for released keys
+ */
+static void locomokbd_timer_callback(unsigned long data)
+{
+ struct locomokbd *locomokbd = (struct locomokbd *) data;
+ locomokbd_scankeyboard(locomokbd, NULL);
+}
+
+static int locomokbd_probe(struct locomo_dev *dev)
+{
+ struct locomokbd *locomokbd;
+ int i, ret;
+
+ locomokbd = kmalloc(sizeof(struct locomokbd), GFP_KERNEL);
+ if (!locomokbd)
+ return -ENOMEM;
+
+ memset(locomokbd, 0, sizeof(struct locomokbd));
+
+ /* try and claim memory region */
+ if (!request_mem_region((unsigned long) dev->mapbase,
+ dev->length,
+ LOCOMO_DRIVER_NAME(dev))) {
+ ret = -EBUSY;
+ printk(KERN_ERR "locomokbd: Can't acquire access to io memory for keyboard\n");
+ goto free;
+ }
+
+ locomokbd->ldev = dev;
+ locomo_set_drvdata(dev, locomokbd);
+
+ locomokbd->base = (unsigned long) dev->mapbase;
+
+ spin_lock_init(&locomokbd->lock);
+
+ init_timer(&locomokbd->timer);
+ locomokbd->timer.function = locomokbd_timer_callback;
+ locomokbd->timer.data = (unsigned long) locomokbd;
+
+ locomokbd->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
+
+ init_input_dev(&locomokbd->input);
+ locomokbd->input.keycode = locomokbd->keycode;
+ locomokbd->input.keycodesize = sizeof(unsigned char);
+ locomokbd->input.keycodemax = ARRAY_SIZE(locomokbd_keycode);
+ locomokbd->input.private = locomokbd;
+
+ memcpy(locomokbd->keycode, locomokbd_keycode, sizeof(locomokbd->keycode));
+ for (i = 0; i < LOCOMOKBD_NUMKEYS; i++)
+ set_bit(locomokbd->keycode[i], locomokbd->input.keybit);
+ clear_bit(0, locomokbd->input.keybit);
+
+ strcpy(locomokbd->phys, "locomokbd/input0");
+
+ locomokbd->input.name = "LoCoMo keyboard";
+ locomokbd->input.phys = locomokbd->phys;
+ locomokbd->input.id.bustype = BUS_XTKBD;
+ locomokbd->input.id.vendor = 0x0001;
+ locomokbd->input.id.product = 0x0001;
+ locomokbd->input.id.version = 0x0100;
+
+ /* attempt to get the interrupt */
+ ret = request_irq(dev->irq[0], locomokbd_interrupt, 0, "locomokbd", locomokbd);
+ if (ret) {
+ printk(KERN_ERR "locomokbd: Can't get irq for keyboard\n");
+ goto out;
+ }
+
+ input_register_device(&locomokbd->input);
+
+ printk(KERN_INFO "input: LoCoMo keyboard on locomokbd\n");
+
+ return 0;
+
+out:
+ release_mem_region((unsigned long) dev->mapbase, dev->length);
+ locomo_set_drvdata(dev, NULL);
+free:
+ kfree(locomokbd);
+
+ return ret;
+}
+
+static int locomokbd_remove(struct locomo_dev *dev)
+{
+ struct locomokbd *locomokbd = locomo_get_drvdata(dev);
+
+ free_irq(dev->irq[0], locomokbd);
+
+ del_timer_sync(&locomokbd->timer);
+
+ input_unregister_device(&locomokbd->input);
+ locomo_set_drvdata(dev, NULL);
+
+ release_mem_region((unsigned long) dev->mapbase, dev->length);
+
+ kfree(locomokbd);
+
+ return 0;
+}
+
+static struct locomo_driver keyboard_driver = {
+ .drv = {
+ .name = "locomokbd"
+ },
+ .devid = LOCOMO_DEVID_KEYBOARD,
+ .probe = locomokbd_probe,
+ .remove = locomokbd_remove,
+};
+
+static int __init locomokbd_init(void)
+{
+ return locomo_driver_register(&keyboard_driver);
+}
+
+static void __exit locomokbd_exit(void)
+{
+ locomo_driver_unregister(&keyboard_driver);
+}
+
+module_init(locomokbd_init);
+module_exit(locomokbd_exit);
diff --git a/drivers/input/keyboard/newtonkbd.c b/drivers/input/keyboard/newtonkbd.c
index 6556c4610348e..2e8ce1613eec9 100644
--- a/drivers/input/keyboard/newtonkbd.c
+++ b/drivers/input/keyboard/newtonkbd.c
@@ -66,10 +66,10 @@ struct nkbd {
char phys[32];
};
-irqreturn_t nkbd_interrupt(struct serio *serio,
+static irqreturn_t nkbd_interrupt(struct serio *serio,
unsigned char data, unsigned int flags, struct pt_regs *regs)
{
- struct nkbd *nkbd = serio->private;
+ struct nkbd *nkbd = serio_get_drvdata(serio);
/* invalid scan codes are probably the init sequence, so we ignore them */
if (nkbd->keycode[data & NKBD_KEY]) {
@@ -84,16 +84,14 @@ irqreturn_t nkbd_interrupt(struct serio *serio,
}
-void nkbd_connect(struct serio *serio, struct serio_driver *drv)
+static int nkbd_connect(struct serio *serio, struct serio_driver *drv)
{
struct nkbd *nkbd;
int i;
-
- if (serio->type != (SERIO_RS232 | SERIO_NEWTON))
- return;
+ int err;
if (!(nkbd = kmalloc(sizeof(struct nkbd), GFP_KERNEL)))
- return;
+ return -ENOMEM;
memset(nkbd, 0, sizeof(struct nkbd));
@@ -106,11 +104,14 @@ void nkbd_connect(struct serio *serio, struct serio_driver *drv)
nkbd->dev.keycodesize = sizeof(unsigned char);
nkbd->dev.keycodemax = ARRAY_SIZE(nkbd_keycode);
nkbd->dev.private = nkbd;
- serio->private = nkbd;
- if (serio_open(serio, drv)) {
+ serio_set_drvdata(serio, nkbd);
+
+ err = serio_open(serio, drv);
+ if (err) {
+ serio_set_drvdata(serio, NULL);
kfree(nkbd);
- return;
+ return err;
}
memcpy(nkbd->keycode, nkbd_keycode, sizeof(nkbd->keycode));
@@ -131,33 +132,50 @@ void nkbd_connect(struct serio *serio, struct serio_driver *drv)
input_register_device(&nkbd->dev);
printk(KERN_INFO "input: %s on %s\n", nkbd_name, serio->phys);
+
+ return 0;
}
-void nkbd_disconnect(struct serio *serio)
+static void nkbd_disconnect(struct serio *serio)
{
- struct nkbd *nkbd = serio->private;
+ struct nkbd *nkbd = serio_get_drvdata(serio);
+
input_unregister_device(&nkbd->dev);
serio_close(serio);
+ serio_set_drvdata(serio, NULL);
kfree(nkbd);
}
-struct serio_driver nkbd_drv = {
+static struct serio_device_id nkbd_serio_ids[] = {
+ {
+ .type = SERIO_RS232,
+ .proto = SERIO_NEWTON,
+ .id = SERIO_ANY,
+ .extra = SERIO_ANY,
+ },
+ { 0 }
+};
+
+MODULE_DEVICE_TABLE(serio, nkbd_serio_ids);
+
+static struct serio_driver nkbd_drv = {
.driver = {
.name = "newtonkbd",
},
.description = DRIVER_DESC,
+ .id_table = nkbd_serio_ids,
.interrupt = nkbd_interrupt,
.connect = nkbd_connect,
.disconnect = nkbd_disconnect,
};
-int __init nkbd_init(void)
+static int __init nkbd_init(void)
{
serio_register_driver(&nkbd_drv);
return 0;
}
-void __exit nkbd_exit(void)
+static void __exit nkbd_exit(void)
{
serio_unregister_driver(&nkbd_drv);
}
diff --git a/drivers/input/keyboard/sunkbd.c b/drivers/input/keyboard/sunkbd.c
index 57dee484546cf..596964ceb96dc 100644
--- a/drivers/input/keyboard/sunkbd.c
+++ b/drivers/input/keyboard/sunkbd.c
@@ -95,7 +95,7 @@ struct sunkbd {
static irqreturn_t sunkbd_interrupt(struct serio *serio,
unsigned char data, unsigned int flags, struct pt_regs *regs)
{
- struct sunkbd* sunkbd = serio->private;
+ struct sunkbd* sunkbd = serio_get_drvdata(serio);
if (sunkbd->reset <= -1) { /* If cp[i] is 0xff, sunkbd->reset will stay -1. */
sunkbd->reset = data; /* The keyboard sends 0xff 0xff 0xID on powerup */
@@ -223,19 +223,14 @@ static void sunkbd_reinit(void *data)
* sunkbd_connect() probes for a Sun keyboard and fills the necessary structures.
*/
-static void sunkbd_connect(struct serio *serio, struct serio_driver *drv)
+static int sunkbd_connect(struct serio *serio, struct serio_driver *drv)
{
struct sunkbd *sunkbd;
int i;
-
- if ((serio->type & SERIO_TYPE) != SERIO_RS232)
- return;
-
- if ((serio->type & SERIO_PROTO) && (serio->type & SERIO_PROTO) != SERIO_SUNKBD)
- return;
+ int err;
if (!(sunkbd = kmalloc(sizeof(struct sunkbd), GFP_KERNEL)))
- return;
+ return -ENOMEM;
memset(sunkbd, 0, sizeof(struct sunkbd));
@@ -257,17 +252,20 @@ static void sunkbd_connect(struct serio *serio, struct serio_driver *drv)
sunkbd->dev.event = sunkbd_event;
sunkbd->dev.private = sunkbd;
- serio->private = sunkbd;
+ serio_set_drvdata(serio, sunkbd);
- if (serio_open(serio, drv)) {
+ err = serio_open(serio, drv);
+ if (err) {
+ serio_set_drvdata(serio, NULL);
kfree(sunkbd);
- return;
+ return err;
}
if (sunkbd_initialize(sunkbd) < 0) {
serio_close(serio);
+ serio_set_drvdata(serio, NULL);
kfree(sunkbd);
- return;
+ return -ENODEV;
}
sprintf(sunkbd->name, "Sun Type %d keyboard", sunkbd->type);
@@ -290,6 +288,8 @@ static void sunkbd_connect(struct serio *serio, struct serio_driver *drv)
input_register_device(&sunkbd->dev);
printk(KERN_INFO "input: %s on %s\n", sunkbd->name, serio->phys);
+
+ return 0;
}
/*
@@ -298,17 +298,37 @@ static void sunkbd_connect(struct serio *serio, struct serio_driver *drv)
static void sunkbd_disconnect(struct serio *serio)
{
- struct sunkbd *sunkbd = serio->private;
+ struct sunkbd *sunkbd = serio_get_drvdata(serio);
input_unregister_device(&sunkbd->dev);
serio_close(serio);
+ serio_set_drvdata(serio, NULL);
kfree(sunkbd);
}
+static struct serio_device_id sunkbd_serio_ids[] = {
+ {
+ .type = SERIO_RS232,
+ .proto = SERIO_SUNKBD,
+ .id = SERIO_ANY,
+ .extra = SERIO_ANY,
+ },
+ {
+ .type = SERIO_RS232,
+ .proto = SERIO_UNKNOWN, /* sunkbd does probe */
+ .id = SERIO_ANY,
+ .extra = SERIO_ANY,
+ },
+ { 0 }
+};
+
+MODULE_DEVICE_TABLE(serio, sunkbd_serio_ids);
+
static struct serio_driver sunkbd_drv = {
.driver = {
.name = "sunkbd",
},
.description = DRIVER_DESC,
+ .id_table = sunkbd_serio_ids,
.interrupt = sunkbd_interrupt,
.connect = sunkbd_connect,
.disconnect = sunkbd_disconnect,
@@ -318,13 +338,13 @@ static struct serio_driver sunkbd_drv = {
* The functions for insering/removing us as a module.
*/
-int __init sunkbd_init(void)
+static int __init sunkbd_init(void)
{
serio_register_driver(&sunkbd_drv);
return 0;
}
-void __exit sunkbd_exit(void)
+static void __exit sunkbd_exit(void)
{
serio_unregister_driver(&sunkbd_drv);
}
diff --git a/drivers/input/keyboard/xtkbd.c b/drivers/input/keyboard/xtkbd.c
index 4c1c31642ef46..19eaec7789d1d 100644
--- a/drivers/input/keyboard/xtkbd.c
+++ b/drivers/input/keyboard/xtkbd.c
@@ -65,10 +65,10 @@ struct xtkbd {
char phys[32];
};
-irqreturn_t xtkbd_interrupt(struct serio *serio,
+static irqreturn_t xtkbd_interrupt(struct serio *serio,
unsigned char data, unsigned int flags, struct pt_regs *regs)
{
- struct xtkbd *xtkbd = serio->private;
+ struct xtkbd *xtkbd = serio_get_drvdata(serio);
switch (data) {
case XTKBD_EMUL0:
@@ -88,16 +88,14 @@ irqreturn_t xtkbd_interrupt(struct serio *serio,
return IRQ_HANDLED;
}
-void xtkbd_connect(struct serio *serio, struct serio_driver *drv)
+static int xtkbd_connect(struct serio *serio, struct serio_driver *drv)
{
struct xtkbd *xtkbd;
int i;
-
- if ((serio->type & SERIO_TYPE) != SERIO_XT)
- return;
+ int err;
if (!(xtkbd = kmalloc(sizeof(struct xtkbd), GFP_KERNEL)))
- return;
+ return -ENOMEM;
memset(xtkbd, 0, sizeof(struct xtkbd));
@@ -111,11 +109,13 @@ void xtkbd_connect(struct serio *serio, struct serio_driver *drv)
xtkbd->dev.keycodemax = ARRAY_SIZE(xtkbd_keycode);
xtkbd->dev.private = xtkbd;
- serio->private = xtkbd;
+ serio_set_drvdata(serio, xtkbd);
- if (serio_open(serio, drv)) {
+ err = serio_open(serio, drv);
+ if (err) {
+ serio_set_drvdata(serio, NULL);
kfree(xtkbd);
- return;
+ return err;
}
memcpy(xtkbd->keycode, xtkbd_keycode, sizeof(xtkbd->keycode));
@@ -136,33 +136,50 @@ void xtkbd_connect(struct serio *serio, struct serio_driver *drv)
input_register_device(&xtkbd->dev);
printk(KERN_INFO "input: %s on %s\n", xtkbd_name, serio->phys);
+
+ return 0;
}
-void xtkbd_disconnect(struct serio *serio)
+static void xtkbd_disconnect(struct serio *serio)
{
- struct xtkbd *xtkbd = serio->private;
+ struct xtkbd *xtkbd = serio_get_drvdata(serio);
+
input_unregister_device(&xtkbd->dev);
serio_close(serio);
+ serio_set_drvdata(serio, NULL);
kfree(xtkbd);
}
-struct serio_driver xtkbd_drv = {
+static struct serio_device_id xtkbd_serio_ids[] = {
+ {
+ .type = SERIO_XT,
+ .proto = SERIO_ANY,
+ .id = SERIO_ANY,
+ .extra = SERIO_ANY,
+ },
+ { 0 }
+};
+
+MODULE_DEVICE_TABLE(serio, xtkbd_serio_ids);
+
+static struct serio_driver xtkbd_drv = {
.driver = {
.name = "xtkbd",
},
.description = DRIVER_DESC,
+ .id_table = xtkbd_serio_ids,
.interrupt = xtkbd_interrupt,
.connect = xtkbd_connect,
.disconnect = xtkbd_disconnect,
};
-int __init xtkbd_init(void)
+static int __init xtkbd_init(void)
{
serio_register_driver(&xtkbd_drv);
return 0;
}
-void __exit xtkbd_exit(void)
+static void __exit xtkbd_exit(void)
{
serio_unregister_driver(&xtkbd_drv);
}
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index 26f9ed6630b39..bb934e6d9636c 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -1,9 +1,8 @@
#
# Input misc drivers configuration
#
-config INPUT_MISC
- bool "Misc"
- depends on INPUT
+menuconfig INPUT_MISC
+ bool "Miscellaneous devices"
help
Say Y here, and a list of miscellaneous input drivers will be displayed.
Everything that didn't fit into the other categories is here. This option
@@ -11,9 +10,11 @@ config INPUT_MISC
If unsure, say Y.
+if INPUT_MISC
+
config INPUT_PCSPKR
tristate "PC Speaker support"
- depends on (ALPHA || X86 || X86_64 || MIPS || PPC_PREP || PPC_CHRP || PPC_PSERIES) && INPUT && INPUT_MISC
+ depends on ALPHA || X86 || X86_64 || MIPS || PPC_PREP || PPC_CHRP || PPC_PSERIES
help
Say Y here if you want the standard PC Speaker to be used for
bells and whistles.
@@ -25,7 +26,7 @@ config INPUT_PCSPKR
config INPUT_SPARCSPKR
tristate "SPARC Speaker support"
- depends on (SPARC32 || SPARC64) && INPUT && INPUT_MISC && PCI
+ depends on PCI && (SPARC32 || SPARC64)
help
Say Y here if you want the standard Speaker on Sparc PCI systems
to be used for bells and whistles.
@@ -37,11 +38,10 @@ config INPUT_SPARCSPKR
config INPUT_M68K_BEEP
tristate "M68k Beeper support"
- depends on M68K && INPUT && INPUT_MISC
+ depends on M68K
config INPUT_UINPUT
tristate "User level driver support"
- depends on INPUT && INPUT_MISC
help
Say Y here if you want to support user level drivers for input
subsystem accessible under char device 10:223 - /dev/input/uinput.
@@ -49,3 +49,12 @@ config INPUT_UINPUT
To compile this driver as a module, choose M here: the
module will be called uinput.
+config HP_SDC_RTC
+ tristate "HP SDC Real Time Clock"
+ depends on GSC
+ select HP_SDC
+ help
+ Say Y here if you want to support the built-in real time clock
+ of the HP SDC controller.
+
+endif
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index 82e5de21939d3..f8d01c69f3495 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -9,3 +9,4 @@ obj-$(CONFIG_INPUT_PCSPKR) += pcspkr.o
obj-$(CONFIG_INPUT_M68K_BEEP) += m68kspkr.o
obj-$(CONFIG_INPUT_98SPKR) += 98spkr.o
obj-$(CONFIG_INPUT_UINPUT) += uinput.o
+obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o
diff --git a/drivers/input/misc/hp_sdc_rtc.c b/drivers/input/misc/hp_sdc_rtc.c
new file mode 100644
index 0000000000000..1cd7657f7e424
--- /dev/null
+++ b/drivers/input/misc/hp_sdc_rtc.c
@@ -0,0 +1,724 @@
+/*
+ * HP i8042 SDC + MSM-58321 BBRTC driver.
+ *
+ * Copyright (c) 2001 Brian S. Julin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. The name of the author may not 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").
+ *
+ * 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
+ *
+ * References:
+ * System Device Controller Microprocessor Firmware Theory of Operation
+ * for Part Number 1820-4784 Revision B. Dwg No. A-1820-4784-2
+ * efirtc.c by Stephane Eranian/Hewlett Packard
+ *
+ */
+
+#include <linux/hp_sdc.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/time.h>
+#include <linux/miscdevice.h>
+#include <linux/proc_fs.h>
+#include <linux/poll.h>
+#include <linux/rtc.h>
+
+MODULE_AUTHOR("Brian S. Julin <bri@calyx.com>");
+MODULE_DESCRIPTION("HP i8042 SDC + MSM-58321 RTC Driver");
+MODULE_LICENSE("Dual BSD/GPL");
+
+#define RTC_VERSION "1.10d"
+
+static unsigned long epoch = 2000;
+
+static struct semaphore i8042tregs;
+
+static hp_sdc_irqhook hp_sdc_rtc_isr;
+
+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);
+
+static int hp_sdc_rtc_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg);
+
+static unsigned int hp_sdc_rtc_poll(struct file *file, poll_table *wait);
+
+static int hp_sdc_rtc_open(struct inode *inode, struct file *file);
+static int hp_sdc_rtc_release(struct inode *inode, struct file *file);
+static int hp_sdc_rtc_fasync (int fd, struct file *filp, int on);
+
+static int hp_sdc_rtc_read_proc(char *page, char **start, off_t off,
+ int count, int *eof, void *data);
+
+static void hp_sdc_rtc_isr (int irq, void *dev_id,
+ uint8_t status, uint8_t data)
+{
+ return;
+}
+
+static int hp_sdc_rtc_do_read_bbrtc (struct rtc_time *rtctm)
+{
+ struct semaphore tsem;
+ hp_sdc_transaction t;
+ uint8_t tseq[91];
+ int i;
+
+ i = 0;
+ while (i < 91) {
+ tseq[i++] = HP_SDC_ACT_DATAREG |
+ HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN;
+ tseq[i++] = 0x01; /* write i8042[0x70] */
+ tseq[i] = i / 7; /* BBRTC reg address */
+ i++;
+ tseq[i++] = HP_SDC_CMD_DO_RTCR; /* Trigger command */
+ tseq[i++] = 2; /* expect 1 stat/dat pair back. */
+ i++; i++; /* buffer for stat/dat pair */
+ }
+ tseq[84] |= HP_SDC_ACT_SEMAPHORE;
+ t.endidx = 91;
+ t.seq = tseq;
+ t.act.semaphore = &tsem;
+ init_MUTEX_LOCKED(&tsem);
+
+ if (hp_sdc_enqueue_transaction(&t)) return -1;
+
+ down_interruptible(&tsem); /* Put ourselves to sleep for results. */
+
+ /* Check for nonpresence of BBRTC */
+ if (!((tseq[83] | tseq[90] | tseq[69] | tseq[76] |
+ tseq[55] | tseq[62] | tseq[34] | tseq[41] |
+ tseq[20] | tseq[27] | tseq[6] | tseq[13]) & 0x0f))
+ return -1;
+
+ memset(rtctm, 0, sizeof(struct rtc_time));
+ rtctm->tm_year = (tseq[83] & 0x0f) + (tseq[90] & 0x0f) * 10;
+ rtctm->tm_mon = (tseq[69] & 0x0f) + (tseq[76] & 0x0f) * 10;
+ rtctm->tm_mday = (tseq[55] & 0x0f) + (tseq[62] & 0x0f) * 10;
+ rtctm->tm_wday = (tseq[48] & 0x0f);
+ rtctm->tm_hour = (tseq[34] & 0x0f) + (tseq[41] & 0x0f) * 10;
+ rtctm->tm_min = (tseq[20] & 0x0f) + (tseq[27] & 0x0f) * 10;
+ rtctm->tm_sec = (tseq[6] & 0x0f) + (tseq[13] & 0x0f) * 10;
+
+ return 0;
+}
+
+static int hp_sdc_rtc_read_bbrtc (struct rtc_time *rtctm)
+{
+ struct rtc_time tm, tm_last;
+ int i = 0;
+
+ /* MSM-58321 has no read latch, so must read twice and compare. */
+
+ if (hp_sdc_rtc_do_read_bbrtc(&tm_last)) return -1;
+ if (hp_sdc_rtc_do_read_bbrtc(&tm)) return -1;
+
+ while (memcmp(&tm, &tm_last, sizeof(struct rtc_time))) {
+ if (i++ > 4) return -1;
+ memcpy(&tm_last, &tm, sizeof(struct rtc_time));
+ if (hp_sdc_rtc_do_read_bbrtc(&tm)) return -1;
+ }
+
+ memcpy(rtctm, &tm, sizeof(struct rtc_time));
+
+ return 0;
+}
+
+
+static int64_t hp_sdc_rtc_read_i8042timer (uint8_t loadcmd, int numreg)
+{
+ hp_sdc_transaction t;
+ uint8_t tseq[26] = {
+ HP_SDC_ACT_PRECMD | HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN,
+ 0,
+ HP_SDC_CMD_READ_T1, 2, 0, 0,
+ HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN,
+ HP_SDC_CMD_READ_T2, 2, 0, 0,
+ HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN,
+ HP_SDC_CMD_READ_T3, 2, 0, 0,
+ HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN,
+ HP_SDC_CMD_READ_T4, 2, 0, 0,
+ HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN,
+ HP_SDC_CMD_READ_T5, 2, 0, 0
+ };
+
+ t.endidx = numreg * 5;
+
+ tseq[1] = loadcmd;
+ tseq[t.endidx - 4] |= HP_SDC_ACT_SEMAPHORE; /* numreg assumed > 1 */
+
+ t.seq = tseq;
+ t.act.semaphore = &i8042tregs;
+
+ down_interruptible(&i8042tregs); /* Sleep if output regs in use. */
+
+ if (hp_sdc_enqueue_transaction(&t)) return -1;
+
+ down_interruptible(&i8042tregs); /* Sleep until results come back. */
+ up(&i8042tregs);
+
+ return (tseq[5] |
+ ((uint64_t)(tseq[10]) << 8) | ((uint64_t)(tseq[15]) << 16) |
+ ((uint64_t)(tseq[20]) << 24) | ((uint64_t)(tseq[25]) << 32));
+}
+
+
+/* Read the i8042 real-time clock */
+static inline int hp_sdc_rtc_read_rt(struct timeval *res) {
+ int64_t raw;
+ uint32_t tenms;
+ unsigned int days;
+
+ raw = hp_sdc_rtc_read_i8042timer(HP_SDC_CMD_LOAD_RT, 5);
+ if (raw < 0) return -1;
+
+ tenms = (uint32_t)raw & 0xffffff;
+ days = (unsigned int)(raw >> 24) & 0xffff;
+
+ res->tv_usec = (suseconds_t)(tenms % 100) * 10000;
+ res->tv_sec = (time_t)(tenms / 100) + days * 86400;
+
+ return 0;
+}
+
+
+/* Read the i8042 fast handshake timer */
+static inline int hp_sdc_rtc_read_fhs(struct timeval *res) {
+ uint64_t raw;
+ unsigned int tenms;
+
+ raw = hp_sdc_rtc_read_i8042timer(HP_SDC_CMD_LOAD_FHS, 2);
+ if (raw < 0) return -1;
+
+ tenms = (unsigned int)raw & 0xffff;
+
+ res->tv_usec = (suseconds_t)(tenms % 100) * 10000;
+ res->tv_sec = (time_t)(tenms / 100);
+
+ return 0;
+}
+
+
+/* Read the i8042 match timer (a.k.a. alarm) */
+static inline int hp_sdc_rtc_read_mt(struct timeval *res) {
+ int64_t raw;
+ uint32_t tenms;
+
+ raw = hp_sdc_rtc_read_i8042timer(HP_SDC_CMD_LOAD_MT, 3);
+ if (raw < 0) return -1;
+
+ tenms = (uint32_t)raw & 0xffffff;
+
+ res->tv_usec = (suseconds_t)(tenms % 100) * 10000;
+ res->tv_sec = (time_t)(tenms / 100);
+
+ return 0;
+}
+
+
+/* Read the i8042 delay timer */
+static inline int hp_sdc_rtc_read_dt(struct timeval *res) {
+ int64_t raw;
+ uint32_t tenms;
+
+ raw = hp_sdc_rtc_read_i8042timer(HP_SDC_CMD_LOAD_DT, 3);
+ if (raw < 0) return -1;
+
+ tenms = (uint32_t)raw & 0xffffff;
+
+ res->tv_usec = (suseconds_t)(tenms % 100) * 10000;
+ res->tv_sec = (time_t)(tenms / 100);
+
+ return 0;
+}
+
+
+/* Read the i8042 cycle timer (a.k.a. periodic) */
+static inline int hp_sdc_rtc_read_ct(struct timeval *res) {
+ int64_t raw;
+ uint32_t tenms;
+
+ raw = hp_sdc_rtc_read_i8042timer(HP_SDC_CMD_LOAD_CT, 3);
+ if (raw < 0) return -1;
+
+ tenms = (uint32_t)raw & 0xffffff;
+
+ res->tv_usec = (suseconds_t)(tenms % 100) * 10000;
+ res->tv_sec = (time_t)(tenms / 100);
+
+ return 0;
+}
+
+
+/* Set the i8042 real-time clock */
+static int hp_sdc_rtc_set_rt (struct timeval *setto)
+{
+ uint32_t tenms;
+ unsigned int days;
+ hp_sdc_transaction t;
+ uint8_t tseq[11] = {
+ HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT,
+ HP_SDC_CMD_SET_RTMS, 3, 0, 0, 0,
+ HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT,
+ HP_SDC_CMD_SET_RTD, 2, 0, 0
+ };
+
+ t.endidx = 10;
+
+ if (0xffff < setto->tv_sec / 86400) return -1;
+ days = setto->tv_sec / 86400;
+ if (0xffff < setto->tv_usec / 1000000 / 86400) return -1;
+ days += ((setto->tv_sec % 86400) + setto->tv_usec / 1000000) / 86400;
+ if (days > 0xffff) return -1;
+
+ if (0xffffff < setto->tv_sec) return -1;
+ tenms = setto->tv_sec * 100;
+ if (0xffffff < setto->tv_usec / 10000) return -1;
+ tenms += setto->tv_usec / 10000;
+ if (tenms > 0xffffff) return -1;
+
+ tseq[3] = (uint8_t)(tenms & 0xff);
+ tseq[4] = (uint8_t)((tenms >> 8) & 0xff);
+ tseq[5] = (uint8_t)((tenms >> 16) & 0xff);
+
+ tseq[9] = (uint8_t)(days & 0xff);
+ tseq[10] = (uint8_t)((days >> 8) & 0xff);
+
+ t.seq = tseq;
+
+ if (hp_sdc_enqueue_transaction(&t)) return -1;
+ return 0;
+}
+
+/* Set the i8042 fast handshake timer */
+static int hp_sdc_rtc_set_fhs (struct timeval *setto)
+{
+ uint32_t tenms;
+ hp_sdc_transaction t;
+ uint8_t tseq[5] = {
+ HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT,
+ HP_SDC_CMD_SET_FHS, 2, 0, 0
+ };
+
+ t.endidx = 4;
+
+ if (0xffff < setto->tv_sec) return -1;
+ tenms = setto->tv_sec * 100;
+ if (0xffff < setto->tv_usec / 10000) return -1;
+ tenms += setto->tv_usec / 10000;
+ if (tenms > 0xffff) return -1;
+
+ tseq[3] = (uint8_t)(tenms & 0xff);
+ tseq[4] = (uint8_t)((tenms >> 8) & 0xff);
+
+ t.seq = tseq;
+
+ if (hp_sdc_enqueue_transaction(&t)) return -1;
+ return 0;
+}
+
+
+/* Set the i8042 match timer (a.k.a. alarm) */
+#define hp_sdc_rtc_set_mt (setto) \
+ hp_sdc_rtc_set_i8042timer(setto, HP_SDC_CMD_SET_MT)
+
+/* Set the i8042 delay timer */
+#define hp_sdc_rtc_set_dt (setto) \
+ hp_sdc_rtc_set_i8042timer(setto, HP_SDC_CMD_SET_DT)
+
+/* Set the i8042 cycle timer (a.k.a. periodic) */
+#define hp_sdc_rtc_set_ct (setto) \
+ hp_sdc_rtc_set_i8042timer(setto, HP_SDC_CMD_SET_CT)
+
+/* Set one of the i8042 3-byte wide timers */
+static int hp_sdc_rtc_set_i8042timer (struct timeval *setto, uint8_t setcmd)
+{
+ uint32_t tenms;
+ hp_sdc_transaction t;
+ uint8_t tseq[6] = {
+ HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT,
+ 0, 3, 0, 0, 0
+ };
+
+ t.endidx = 6;
+
+ if (0xffffff < setto->tv_sec) return -1;
+ tenms = setto->tv_sec * 100;
+ if (0xffffff < setto->tv_usec / 10000) return -1;
+ tenms += setto->tv_usec / 10000;
+ if (tenms > 0xffffff) return -1;
+
+ tseq[1] = setcmd;
+ tseq[3] = (uint8_t)(tenms & 0xff);
+ tseq[4] = (uint8_t)((tenms >> 8) & 0xff);
+ tseq[5] = (uint8_t)((tenms >> 16) & 0xff);
+
+ t.seq = tseq;
+
+ if (hp_sdc_enqueue_transaction(&t)) {
+ return -1;
+ }
+ 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;
+
+ if (count < sizeof(unsigned long))
+ return -EINVAL;
+
+ retval = put_user(68, (unsigned long *)buf);
+ return retval;
+}
+
+static unsigned int hp_sdc_rtc_poll(struct file *file, poll_table *wait)
+{
+ unsigned long l;
+
+ l = 0;
+ if (l != 0)
+ return POLLIN | POLLRDNORM;
+ return 0;
+}
+
+static int hp_sdc_rtc_open(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
+static int hp_sdc_rtc_release(struct inode *inode, struct file *file)
+{
+ /* Turn off interrupts? */
+
+ if (file->f_flags & FASYNC) {
+ hp_sdc_rtc_fasync (-1, file, 0);
+ }
+
+ return 0;
+}
+
+static int hp_sdc_rtc_fasync (int fd, struct file *filp, int on)
+{
+ return fasync_helper (fd, filp, on, &hp_sdc_rtc_async_queue);
+}
+
+static int hp_sdc_rtc_proc_output (char *buf)
+{
+#define YN(bit) ("no")
+#define NY(bit) ("yes")
+ char *p;
+ struct rtc_time tm;
+ struct timeval tv;
+
+ memset(&tm, 0, sizeof(struct rtc_time));
+
+ p = buf;
+
+ if (hp_sdc_rtc_read_bbrtc(&tm)) {
+ p += sprintf(p, "BBRTC\t\t: READ FAILED!\n");
+ } else {
+ p += sprintf(p,
+ "rtc_time\t: %02d:%02d:%02d\n"
+ "rtc_date\t: %04d-%02d-%02d\n"
+ "rtc_epoch\t: %04lu\n",
+ tm.tm_hour, tm.tm_min, tm.tm_sec,
+ tm.tm_year + 1900, tm.tm_mon + 1,
+ tm.tm_mday, epoch);
+ }
+
+ if (hp_sdc_rtc_read_rt(&tv)) {
+ p += sprintf(p, "i8042 rtc\t: READ FAILED!\n");
+ } else {
+ p += sprintf(p, "i8042 rtc\t: %ld.%02d seconds\n",
+ tv.tv_sec, tv.tv_usec/1000);
+ }
+
+ if (hp_sdc_rtc_read_fhs(&tv)) {
+ p += sprintf(p, "handshake\t: READ FAILED!\n");
+ } else {
+ p += sprintf(p, "handshake\t: %ld.%02d seconds\n",
+ tv.tv_sec, tv.tv_usec/1000);
+ }
+
+ if (hp_sdc_rtc_read_mt(&tv)) {
+ p += sprintf(p, "alarm\t\t: READ FAILED!\n");
+ } else {
+ p += sprintf(p, "alarm\t\t: %ld.%02d seconds\n",
+ tv.tv_sec, tv.tv_usec/1000);
+ }
+
+ if (hp_sdc_rtc_read_dt(&tv)) {
+ p += sprintf(p, "delay\t\t: READ FAILED!\n");
+ } else {
+ p += sprintf(p, "delay\t\t: %ld.%02d seconds\n",
+ tv.tv_sec, tv.tv_usec/1000);
+ }
+
+ if (hp_sdc_rtc_read_ct(&tv)) {
+ p += sprintf(p, "periodic\t: READ FAILED!\n");
+ } else {
+ p += sprintf(p, "periodic\t: %ld.%02d seconds\n",
+ tv.tv_sec, tv.tv_usec/1000);
+ }
+
+ p += sprintf(p,
+ "DST_enable\t: %s\n"
+ "BCD\t\t: %s\n"
+ "24hr\t\t: %s\n"
+ "square_wave\t: %s\n"
+ "alarm_IRQ\t: %s\n"
+ "update_IRQ\t: %s\n"
+ "periodic_IRQ\t: %s\n"
+ "periodic_freq\t: %ld\n"
+ "batt_status\t: %s\n",
+ YN(RTC_DST_EN),
+ NY(RTC_DM_BINARY),
+ YN(RTC_24H),
+ YN(RTC_SQWE),
+ YN(RTC_AIE),
+ YN(RTC_UIE),
+ YN(RTC_PIE),
+ 1UL,
+ 1 ? "okay" : "dead");
+
+ return p - buf;
+#undef YN
+#undef NY
+}
+
+static int hp_sdc_rtc_read_proc(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ int len = hp_sdc_rtc_proc_output (page);
+ if (len <= off+count) *eof = 1;
+ *start = page + off;
+ len -= off;
+ if (len>count) len = count;
+ if (len<0) len = 0;
+ return len;
+}
+
+static int hp_sdc_rtc_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+#if 1
+ return -EINVAL;
+#else
+
+ struct rtc_time wtime;
+ struct timeval ttime;
+ int use_wtime = 0;
+
+ /* This needs major work. */
+
+ switch (cmd) {
+
+ case RTC_AIE_OFF: /* Mask alarm int. enab. bit */
+ case RTC_AIE_ON: /* Allow alarm interrupts. */
+ case RTC_PIE_OFF: /* Mask periodic int. enab. bit */
+ case RTC_PIE_ON: /* Allow periodic ints */
+ case RTC_UIE_ON: /* Allow ints for RTC updates. */
+ case RTC_UIE_OFF: /* Allow ints for RTC updates. */
+ {
+ /* We cannot mask individual user timers and we
+ cannot tell them apart when they occur, so it
+ would be disingenuous to succeed these IOCTLs */
+ return -EINVAL;
+ }
+ case RTC_ALM_READ: /* Read the present alarm time */
+ {
+ if (hp_sdc_rtc_read_mt(&ttime)) return -EFAULT;
+ if (hp_sdc_rtc_read_bbrtc(&wtime)) return -EFAULT;
+
+ wtime.tm_hour = ttime.tv_sec / 3600; ttime.tv_sec %= 3600;
+ wtime.tm_min = ttime.tv_sec / 60; ttime.tv_sec %= 60;
+ wtime.tm_sec = ttime.tv_sec;
+
+ break;
+ }
+ case RTC_IRQP_READ: /* Read the periodic IRQ rate. */
+ {
+ return put_user(hp_sdc_rtc_freq, (unsigned long *)arg);
+ }
+ case RTC_IRQP_SET: /* Set periodic IRQ rate. */
+ {
+ /*
+ * The max we can do is 100Hz.
+ */
+
+ if ((arg < 1) || (arg > 100)) return -EINVAL;
+ ttime.tv_sec = 0;
+ ttime.tv_usec = 1000000 / arg;
+ if (hp_sdc_rtc_set_ct(&ttime)) return -EFAULT;
+ hp_sdc_rtc_freq = arg;
+ return 0;
+ }
+ case RTC_ALM_SET: /* Store a time into the alarm */
+ {
+ /*
+ * This expects a struct hp_sdc_rtc_time. Writing 0xff means
+ * "don't care" or "match all" for PC timers. The HP SDC
+ * does not support that perk, but it could be emulated fairly
+ * easily. Only the tm_hour, tm_min and tm_sec are used.
+ * We could do it with 10ms accuracy with the HP SDC, if the
+ * rtc interface left us a way to do that.
+ */
+ struct hp_sdc_rtc_time alm_tm;
+
+ if (copy_from_user(&alm_tm, (struct hp_sdc_rtc_time*)arg,
+ sizeof(struct hp_sdc_rtc_time)))
+ return -EFAULT;
+
+ if (alm_tm.tm_hour > 23) return -EINVAL;
+ if (alm_tm.tm_min > 59) return -EINVAL;
+ if (alm_tm.tm_sec > 59) return -EINVAL;
+
+ ttime.sec = alm_tm.tm_hour * 3600 +
+ alm_tm.tm_min * 60 + alm_tm.tm_sec;
+ ttime.usec = 0;
+ if (hp_sdc_rtc_set_mt(&ttime)) return -EFAULT;
+ return 0;
+ }
+ case RTC_RD_TIME: /* Read the time/date from RTC */
+ {
+ if (hp_sdc_rtc_read_bbrtc(&wtime)) return -EFAULT;
+ break;
+ }
+ case RTC_SET_TIME: /* Set the RTC */
+ {
+ struct rtc_time hp_sdc_rtc_tm;
+ unsigned char mon, day, hrs, min, sec, leap_yr;
+ unsigned int yrs;
+
+ if (!capable(CAP_SYS_TIME))
+ return -EACCES;
+ if (copy_from_user(&hp_sdc_rtc_tm, (struct rtc_time *)arg,
+ sizeof(struct rtc_time)))
+ return -EFAULT;
+
+ yrs = hp_sdc_rtc_tm.tm_year + 1900;
+ mon = hp_sdc_rtc_tm.tm_mon + 1; /* tm_mon starts at zero */
+ day = hp_sdc_rtc_tm.tm_mday;
+ hrs = hp_sdc_rtc_tm.tm_hour;
+ min = hp_sdc_rtc_tm.tm_min;
+ sec = hp_sdc_rtc_tm.tm_sec;
+
+ if (yrs < 1970)
+ return -EINVAL;
+
+ leap_yr = ((!(yrs % 4) && (yrs % 100)) || !(yrs % 400));
+
+ if ((mon > 12) || (day == 0))
+ return -EINVAL;
+ if (day > (days_in_mo[mon] + ((mon == 2) && leap_yr)))
+ return -EINVAL;
+ if ((hrs >= 24) || (min >= 60) || (sec >= 60))
+ return -EINVAL;
+
+ if ((yrs -= eH) > 255) /* They are unsigned */
+ return -EINVAL;
+
+
+ return 0;
+ }
+ case RTC_EPOCH_READ: /* Read the epoch. */
+ {
+ return put_user (epoch, (unsigned long *)arg);
+ }
+ case RTC_EPOCH_SET: /* Set the epoch. */
+ {
+ /*
+ * There were no RTC clocks before 1900.
+ */
+ if (arg < 1900)
+ return -EINVAL;
+ if (!capable(CAP_SYS_TIME))
+ return -EACCES;
+
+ epoch = arg;
+ return 0;
+ }
+ default:
+ return -EINVAL;
+ }
+ return copy_to_user((void *)arg, &wtime, sizeof wtime) ? -EFAULT : 0;
+#endif
+}
+
+static struct file_operations hp_sdc_rtc_fops = {
+ .owner = THIS_MODULE,
+ .llseek = hp_sdc_rtc_llseek,
+ .read = hp_sdc_rtc_read,
+ .poll = hp_sdc_rtc_poll,
+ .ioctl = hp_sdc_rtc_ioctl,
+ .open = hp_sdc_rtc_open,
+ .release = hp_sdc_rtc_release,
+ .fasync = hp_sdc_rtc_fasync,
+};
+
+static struct miscdevice hp_sdc_rtc_dev = {
+ .minor = RTC_MINOR,
+ .name = "rtc_HIL",
+ .fops = &hp_sdc_rtc_fops
+};
+
+static int __init hp_sdc_rtc_init(void)
+{
+ int ret;
+
+ init_MUTEX(&i8042tregs);
+
+ if ((ret = hp_sdc_request_timer_irq(&hp_sdc_rtc_isr)))
+ return ret;
+ misc_register(&hp_sdc_rtc_dev);
+ create_proc_read_entry ("driver/rtc", 0, 0,
+ hp_sdc_rtc_read_proc, NULL);
+
+ printk(KERN_INFO "HP i8042 SDC + MSM-58321 RTC support loaded "
+ "(RTC v " RTC_VERSION ")\n");
+
+ return 0;
+}
+
+static void __exit hp_sdc_rtc_exit(void)
+{
+ remove_proc_entry ("driver/rtc", NULL);
+ misc_deregister(&hp_sdc_rtc_dev);
+ hp_sdc_release_timer_irq(hp_sdc_rtc_isr);
+ printk(KERN_INFO "HP i8042 SDC + MSM-58321 RTC support unloaded\n");
+}
+
+module_init(hp_sdc_rtc_init);
+module_exit(hp_sdc_rtc_exit);
diff --git a/drivers/input/misc/pcspkr.c b/drivers/input/misc/pcspkr.c
index 58a39fd93fb83..3013194f462b8 100644
--- a/drivers/input/misc/pcspkr.c
+++ b/drivers/input/misc/pcspkr.c
@@ -27,7 +27,7 @@ static char pcspkr_name[] = "PC Speaker";
static char pcspkr_phys[] = "isa0061/input0";
static struct input_dev pcspkr_dev;
-DEFINE_SPINLOCK(i8253_beep_lock);
+static DEFINE_SPINLOCK(i8253_beep_lock);
static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
{
@@ -89,6 +89,8 @@ static int __init pcspkr_init(void)
static void __exit pcspkr_exit(void)
{
input_unregister_device(&pcspkr_dev);
+ /* turn off the speaker */
+ pcspkr_event(NULL, EV_SND, SND_BELL, 0);
}
module_init(pcspkr_init);
diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c
index 477579b9ee51f..158c8e845ff98 100644
--- a/drivers/input/misc/uinput.c
+++ b/drivers/input/misc/uinput.c
@@ -20,6 +20,9 @@
* Author: Aristeu Sergio Rozanski Filho <aris@cathedrallabs.org>
*
* Changes/Revisions:
+ * 0.2 16/10/2004 (Micah Dowty <micah@navi.cx>)
+ * - added force feedback support
+ * - added UI_SET_PHYS
* 0.1 20/06/2002
* - first public version
*/
@@ -47,7 +50,7 @@ static int uinput_dev_event(struct input_dev *dev, unsigned int type, unsigned i
{
struct uinput_device *udev;
- udev = (struct uinput_device *)dev->private;
+ udev = dev->private;
udev->buff[udev->head].type = type;
udev->buff[udev->head].code = code;
@@ -60,14 +63,93 @@ static int uinput_dev_event(struct input_dev *dev, unsigned int type, unsigned i
return 0;
}
+static int uinput_request_alloc_id(struct input_dev *dev, struct uinput_request *request)
+{
+ /* Atomically allocate an ID for the given request. Returns 0 on success. */
+ struct uinput_device *udev = dev->private;
+ int id;
+
+ down(&udev->requests_sem);
+ for (id=0; id<UINPUT_NUM_REQUESTS; id++)
+ if (!udev->requests[id]) {
+ udev->requests[id] = request;
+ request->id = id;
+ up(&udev->requests_sem);
+ return 0;
+ }
+ up(&udev->requests_sem);
+ return -1;
+}
+
+static struct uinput_request* uinput_request_find(struct uinput_device *udev, int id)
+{
+ /* Find an input request, by ID. Returns NULL if the ID isn't valid. */
+ if (id >= UINPUT_NUM_REQUESTS || id < 0)
+ return NULL;
+ if (udev->requests[id]->completed)
+ return NULL;
+ return udev->requests[id];
+}
+
+static void uinput_request_init(struct input_dev *dev, struct uinput_request *request, int code)
+{
+ struct uinput_device *udev = dev->private;
+
+ memset(request, 0, sizeof(struct uinput_request));
+ request->code = code;
+ init_waitqueue_head(&request->waitq);
+
+ /* Allocate an ID. If none are available right away, wait. */
+ request->retval = wait_event_interruptible(udev->requests_waitq,
+ !uinput_request_alloc_id(dev, request));
+}
+
+static void uinput_request_submit(struct input_dev *dev, struct uinput_request *request)
+{
+ struct uinput_device *udev = dev->private;
+ int retval;
+
+ /* Tell our userspace app about this new request by queueing an input event */
+ uinput_dev_event(dev, EV_UINPUT, request->code, request->id);
+
+ /* Wait for the request to complete */
+ retval = wait_event_interruptible(request->waitq, request->completed);
+ if (retval)
+ request->retval = retval;
+
+ /* Release this request's ID, let others know it's available */
+ udev->requests[request->id] = NULL;
+ wake_up_interruptible(&udev->requests_waitq);
+}
+
static int uinput_dev_upload_effect(struct input_dev *dev, struct ff_effect *effect)
{
- return 0;
+ struct uinput_request request;
+
+ if (!test_bit(EV_FF, dev->evbit))
+ return -ENOSYS;
+
+ uinput_request_init(dev, &request, UI_FF_UPLOAD);
+ if (request.retval)
+ return request.retval;
+ request.u.effect = effect;
+ uinput_request_submit(dev, &request);
+ return request.retval;
}
static int uinput_dev_erase_effect(struct input_dev *dev, int effect_id)
{
- return 0;
+ struct uinput_request request;
+
+ if (!test_bit(EV_FF, dev->evbit))
+ return -ENOSYS;
+
+ uinput_request_init(dev, &request, UI_FF_ERASE);
+ if (request.retval)
+ return request.retval;
+ request.u.effect_id = effect_id;
+ uinput_request_submit(dev, &request);
+ return request.retval;
}
static int uinput_create_device(struct uinput_device *udev)
@@ -116,6 +198,8 @@ static int uinput_open(struct inode *inode, struct file *file)
if (!newdev)
goto error;
memset(newdev, 0, sizeof(struct uinput_device));
+ init_MUTEX(&newdev->requests_sem);
+ init_waitqueue_head(&newdev->requests_waitq);
newinput = kmalloc(sizeof(struct input_dev), GFP_KERNEL);
if (!newinput)
@@ -138,12 +222,11 @@ static int uinput_validate_absbits(struct input_dev *dev)
unsigned int cnt;
int retval = 0;
- for (cnt = 0; cnt < ABS_MAX; cnt++) {
+ for (cnt = 0; cnt < ABS_MAX + 1; cnt++) {
if (!test_bit(cnt, dev->absbit))
continue;
- if (/*!dev->absmin[cnt] || !dev->absmax[cnt] || */
- (dev->absmax[cnt] <= dev->absmin[cnt])) {
+ if ((dev->absmax[cnt] <= dev->absmin[cnt])) {
printk(KERN_DEBUG
"%s: invalid abs[%02x] min:%d max:%d\n",
UINPUT_NAME, cnt,
@@ -152,8 +235,7 @@ static int uinput_validate_absbits(struct input_dev *dev)
break;
}
- if ((dev->absflat[cnt] < dev->absmin[cnt]) ||
- (dev->absflat[cnt] > dev->absmax[cnt])) {
+ if (dev->absflat[cnt] > (dev->absmax[cnt] - dev->absmin[cnt])) {
printk(KERN_DEBUG
"%s: absflat[%02x] out of range: %d "
"(min:%d/max:%d)\n",
@@ -176,7 +258,7 @@ static int uinput_alloc_device(struct file *file, const char __user *buffer, siz
retval = count;
- udev = (struct uinput_device *)file->private_data;
+ udev = file->private_data;
dev = udev->dev;
user_dev = kmalloc(sizeof(*user_dev), GFP_KERNEL);
@@ -228,7 +310,7 @@ exit:
static ssize_t uinput_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
{
- struct uinput_device *udev = file->private_data;
+ struct uinput_device *udev = file->private_data;
if (test_bit(UIST_CREATED, &(udev->state))) {
struct input_event ev;
@@ -279,9 +361,6 @@ static unsigned int uinput_poll(struct file *file, poll_table *wait)
{
struct uinput_device *udev = file->private_data;
- if (!test_bit(UIST_CREATED, &(udev->state)))
- return 0;
-
poll_wait(file, &udev->waitq, wait);
if (udev->head != udev->tail)
@@ -295,6 +374,11 @@ static int uinput_burn_device(struct uinput_device *udev)
if (test_bit(UIST_CREATED, &(udev->state)))
uinput_destroy_device(udev);
+ if (NULL != udev->dev->name)
+ kfree(udev->dev->name);
+ if (NULL != udev->dev->phys)
+ kfree(udev->dev->phys);
+
kfree(udev->dev);
kfree(udev);
@@ -303,19 +387,35 @@ static int uinput_burn_device(struct uinput_device *udev)
static int uinput_close(struct inode *inode, struct file *file)
{
- return uinput_burn_device((struct uinput_device *)file->private_data);
+ return uinput_burn_device(file->private_data);
}
static int uinput_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
int retval = 0;
struct uinput_device *udev;
+ void __user *p = (void __user *)arg;
+ struct uinput_ff_upload ff_up;
+ struct uinput_ff_erase ff_erase;
+ struct uinput_request *req;
+ int length;
- udev = (struct uinput_device *)file->private_data;
+ udev = file->private_data;
/* device attributes can not be changed after the device is created */
- if (cmd >= UI_SET_EVBIT && test_bit(UIST_CREATED, &(udev->state)))
- return -EINVAL;
+ switch (cmd) {
+ case UI_SET_EVBIT:
+ case UI_SET_KEYBIT:
+ case UI_SET_RELBIT:
+ case UI_SET_ABSBIT:
+ case UI_SET_MSCBIT:
+ case UI_SET_LEDBIT:
+ case UI_SET_SNDBIT:
+ case UI_SET_FFBIT:
+ case UI_SET_PHYS:
+ if (test_bit(UIST_CREATED, &(udev->state)))
+ return -EINVAL;
+ }
switch (cmd) {
case UI_DEV_CREATE:
@@ -390,13 +490,102 @@ static int uinput_ioctl(struct inode *inode, struct file *file, unsigned int cmd
set_bit(arg, udev->dev->ffbit);
break;
+ case UI_SET_PHYS:
+ length = strnlen_user(p, 1024);
+ if (length <= 0) {
+ retval = -EFAULT;
+ break;
+ }
+ if (NULL != udev->dev->phys)
+ kfree(udev->dev->phys);
+ udev->dev->phys = kmalloc(length, GFP_KERNEL);
+ if (!udev->dev->phys) {
+ retval = -ENOMEM;
+ break;
+ }
+ if (copy_from_user(udev->dev->phys, p, length)) {
+ retval = -EFAULT;
+ kfree(udev->dev->phys);
+ udev->dev->phys = NULL;
+ break;
+ }
+ udev->dev->phys[length-1] = '\0';
+ break;
+
+ case UI_BEGIN_FF_UPLOAD:
+ if (copy_from_user(&ff_up, p, sizeof(ff_up))) {
+ retval = -EFAULT;
+ break;
+ }
+ req = uinput_request_find(udev, ff_up.request_id);
+ if (!(req && req->code==UI_FF_UPLOAD && req->u.effect)) {
+ retval = -EINVAL;
+ break;
+ }
+ ff_up.retval = 0;
+ memcpy(&ff_up.effect, req->u.effect, sizeof(struct ff_effect));
+ if (copy_to_user(p, &ff_up, sizeof(ff_up))) {
+ retval = -EFAULT;
+ break;
+ }
+ break;
+
+ case UI_BEGIN_FF_ERASE:
+ if (copy_from_user(&ff_erase, p, sizeof(ff_erase))) {
+ retval = -EFAULT;
+ break;
+ }
+ req = uinput_request_find(udev, ff_erase.request_id);
+ if (!(req && req->code==UI_FF_ERASE)) {
+ retval = -EINVAL;
+ break;
+ }
+ ff_erase.retval = 0;
+ ff_erase.effect_id = req->u.effect_id;
+ if (copy_to_user(p, &ff_erase, sizeof(ff_erase))) {
+ retval = -EFAULT;
+ break;
+ }
+ break;
+
+ case UI_END_FF_UPLOAD:
+ if (copy_from_user(&ff_up, p, sizeof(ff_up))) {
+ retval = -EFAULT;
+ break;
+ }
+ req = uinput_request_find(udev, ff_up.request_id);
+ if (!(req && req->code==UI_FF_UPLOAD && req->u.effect)) {
+ retval = -EINVAL;
+ break;
+ }
+ req->retval = ff_up.retval;
+ memcpy(req->u.effect, &ff_up.effect, sizeof(struct ff_effect));
+ req->completed = 1;
+ wake_up_interruptible(&req->waitq);
+ break;
+
+ case UI_END_FF_ERASE:
+ if (copy_from_user(&ff_erase, p, sizeof(ff_erase))) {
+ retval = -EFAULT;
+ break;
+ }
+ req = uinput_request_find(udev, ff_erase.request_id);
+ if (!(req && req->code==UI_FF_ERASE)) {
+ retval = -EINVAL;
+ break;
+ }
+ req->retval = ff_erase.retval;
+ req->completed = 1;
+ wake_up_interruptible(&req->waitq);
+ break;
+
default:
- retval = -EFAULT;
+ retval = -EINVAL;
}
return retval;
}
-struct file_operations uinput_fops = {
+static struct file_operations uinput_fops = {
.owner = THIS_MODULE,
.open = uinput_open,
.release = uinput_close,
diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig
index 421ee31421b4e..537154dd7a873 100644
--- a/drivers/input/mouse/Kconfig
+++ b/drivers/input/mouse/Kconfig
@@ -1,20 +1,20 @@
#
# Mouse driver configuration
#
-config INPUT_MOUSE
- bool "Mice"
+menuconfig INPUT_MOUSE
+ bool "Mouse"
default y
- depends on INPUT
help
Say Y here, and a list of supported mice will be displayed.
This option doesn't affect the kernel.
If unsure, say Y.
+if INPUT_MOUSE
+
config MOUSE_PS2
tristate "PS/2 mouse"
default y
- depends on INPUT && INPUT_MOUSE
select SERIO
select SERIO_LIBPS2
select SERIO_I8042 if PC
@@ -39,7 +39,6 @@ config MOUSE_PS2
config MOUSE_SERIAL
tristate "Serial mouse"
- depends on INPUT && INPUT_MOUSE
select SERIO
---help---
Say Y here if you have a serial (RS-232, COM port) mouse connected
@@ -53,7 +52,7 @@ config MOUSE_SERIAL
config MOUSE_INPORT
tristate "InPort/MS/ATIXL busmouse"
- depends on INPUT && INPUT_MOUSE && ISA
+ depends on ISA
help
Say Y here if you have an InPort, Microsoft or ATI XL busmouse.
They are rather rare these days.
@@ -69,7 +68,7 @@ config MOUSE_ATIXL
config MOUSE_LOGIBM
tristate "Logitech busmouse"
- depends on INPUT && INPUT_MOUSE && ISA
+ depends on ISA
help
Say Y here if you have a Logitech busmouse.
They are rather rare these days.
@@ -79,7 +78,7 @@ config MOUSE_LOGIBM
config MOUSE_PC110PAD
tristate "IBM PC110 touchpad"
- depends on INPUT && INPUT_MOUSE && ISA
+ depends on ISA
help
Say Y if you have the IBM PC-110 micro-notebook and want its
touchpad supported.
@@ -89,7 +88,7 @@ config MOUSE_PC110PAD
config MOUSE_MAPLE
tristate "Maple bus mouse"
- depends on SH_DREAMCAST && INPUT && INPUT_MOUSE && MAPLE
+ depends on SH_DREAMCAST && MAPLE
help
Say Y if you have a DreamCast console and a mouse attached to
its Maple bus.
@@ -99,7 +98,7 @@ config MOUSE_MAPLE
config MOUSE_AMIGA
tristate "Amiga mouse"
- depends on AMIGA && INPUT && INPUT_MOUSE
+ depends on AMIGA
help
Say Y here if you have an Amiga and want its native mouse
supported by the kernel.
@@ -109,7 +108,7 @@ config MOUSE_AMIGA
config MOUSE_RISCPC
tristate "Acorn RiscPC mouse"
- depends on ARCH_ACORN && INPUT && INPUT_MOUSE
+ depends on ARCH_ACORN
help
Say Y here if you have the Acorn RiscPC computer and want its
native mouse supported.
@@ -119,7 +118,6 @@ config MOUSE_RISCPC
config MOUSE_VSXXXAA
tristate "DEC VSXXX-AA/GA mouse and VSXXX-AB tablet"
- depends on INPUT && INPUT_MOUSE
select SERIO
help
Say Y (or M) if you want to use a DEC VSXXX-AA (hockey
@@ -129,3 +127,12 @@ config MOUSE_VSXXXAA
described in the source file). This driver also works with the
digitizer (VSXXX-AB) DEC produced.
+config MOUSE_HIL
+ tristate "HIL pointers (mice etc)."
+ depends on GSC
+ select HP_SDC
+ select HIL_MLC
+ help
+ Say Y here to support HIL pointers.
+
+endif
diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile
index 46184d5f79105..a7864195806a6 100644
--- a/drivers/input/mouse/Makefile
+++ b/drivers/input/mouse/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_MOUSE_MAPLE) += maplemouse.o
obj-$(CONFIG_MOUSE_PC110PAD) += pc110pad.o
obj-$(CONFIG_MOUSE_PS2) += psmouse.o
obj-$(CONFIG_MOUSE_SERIAL) += sermouse.o
+obj-$(CONFIG_MOUSE_HIL) += hil_ptr.o
obj-$(CONFIG_MOUSE_VSXXXAA) += vsxxxaa.o
psmouse-objs := psmouse-base.o alps.o logips2pp.o synaptics.o
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index e8c0b61e3ad6b..1f85a9718c898 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -4,6 +4,7 @@
* Copyright (c) 2003 Neil Brown <neilb@cse.unsw.edu.au>
* Copyright (c) 2003 Peter Osterlund <petero2@telia.com>
* Copyright (c) 2004 Dmitry Torokhov <dtor@mail.ru>
+ * Copyright (c) 2005 Vojtech Pavlik <vojtech@suse.cz>
*
* ALPS detection, tap switching and status querying info is taken from
* tpconfig utility (by C. Scott Ananian and Bruce Kall).
@@ -27,102 +28,122 @@
#define dbg(format, arg...) do {} while (0)
#endif
-#define ALPS_MODEL_GLIDEPOINT 1
-#define ALPS_MODEL_DUALPOINT 2
-
-struct alps_model_info {
- unsigned char signature[3];
- unsigned char model;
-} alps_model_data[] = {
-/* { { 0x33, 0x02, 0x0a }, ALPS_MODEL_GLIDEPOINT }, */
- { { 0x53, 0x02, 0x0a }, ALPS_MODEL_GLIDEPOINT },
- { { 0x53, 0x02, 0x14 }, ALPS_MODEL_GLIDEPOINT },
- { { 0x63, 0x02, 0x0a }, ALPS_MODEL_GLIDEPOINT },
- { { 0x63, 0x02, 0x14 }, ALPS_MODEL_GLIDEPOINT },
- { { 0x73, 0x02, 0x0a }, ALPS_MODEL_GLIDEPOINT },
- { { 0x73, 0x02, 0x14 }, ALPS_MODEL_GLIDEPOINT },
- { { 0x63, 0x02, 0x28 }, ALPS_MODEL_GLIDEPOINT },
-/* { { 0x63, 0x02, 0x3c }, ALPS_MODEL_GLIDEPOINT }, */
-/* { { 0x63, 0x02, 0x50 }, ALPS_MODEL_GLIDEPOINT }, */
- { { 0x63, 0x02, 0x64 }, ALPS_MODEL_GLIDEPOINT },
- { { 0x20, 0x02, 0x0e }, ALPS_MODEL_DUALPOINT },
- { { 0x22, 0x02, 0x0a }, ALPS_MODEL_DUALPOINT },
- { { 0x22, 0x02, 0x14 }, ALPS_MODEL_DUALPOINT },
- { { 0x63, 0x03, 0xc8 }, ALPS_MODEL_DUALPOINT },
+#define ALPS_DUALPOINT 0x01
+#define ALPS_WHEEL 0x02
+#define ALPS_FW_BK 0x04
+#define ALPS_4BTN 0x08
+#define ALPS_OLDPROTO 0x10
+#define ALPS_PASS 0x20
+
+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 },
+ { { 0x63, 0x02, 0x0a }, 0xf8, 0xf8, 0 },
+ { { 0x63, 0x02, 0x14 }, 0xf8, 0xf8, 0 },
+ { { 0x63, 0x02, 0x28 }, 0xf8, 0xf8, 0 },
+ { { 0x63, 0x02, 0x3c }, 0x8f, 0x8f, ALPS_WHEEL }, /* Toshiba Satellite S2400-103 */
+ { { 0x63, 0x02, 0x50 }, 0xef, 0xef, ALPS_FW_BK }, /* NEC Versa L320 */
+ { { 0x63, 0x02, 0x64 }, 0xf8, 0xf8, 0 },
+ { { 0x63, 0x03, 0xc8 }, 0xf8, 0xf8, ALPS_PASS }, /* Dell Latitude D800 */
+ { { 0x73, 0x02, 0x0a }, 0xf8, 0xf8, 0 },
+ { { 0x73, 0x02, 0x14 }, 0xf8, 0xf8, 0 },
+ { { 0x20, 0x02, 0x0e }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */
+ { { 0x22, 0x02, 0x0a }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT },
+ { { 0x22, 0x02, 0x14 }, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */
};
/*
- * ALPS abolute Mode
- * byte 0: 1 1 1 1 1 mid0 rig0 lef0
+ * XXX - this entry is suspicious. First byte has zero lower nibble,
+ * which is what a normal mouse would report. Also, the value 0x0e
+ * isn't valid per PS/2 spec.
+ */
+
+/*
+ * ALPS abolute Mode - new format
+ *
+ * byte 0: 1 ? ? ? 1 ? ? ?
* byte 1: 0 x6 x5 x4 x3 x2 x1 x0
- * byte 2: 0 x10 x9 x8 x7 up1 fin ges
- * byte 3: 0 y9 y8 y7 1 mid1 rig1 lef1
+ * byte 2: 0 x10 x9 x8 x7 ? fin ges
+ * byte 3: 0 y9 y8 y7 1 M R L
* byte 4: 0 y6 y5 y4 y3 y2 y1 y0
* byte 5: 0 z6 z5 z4 z3 z2 z1 z0
*
- * On a dualpoint, {mid,rig,lef}0 are the stick, 1 are the pad.
- * We just 'or' them together for now.
- *
- * We used to send 'ges'tures as BTN_TOUCH but this made it impossible
- * to disable tap events in the synaptics driver since the driver
- * was unable to distinguish a gesture tap from an actual button click.
- * A tap gesture now creates an emulated touch that the synaptics
- * driver can interpret as a tap event, if MaxTapTime=0 and
- * MaxTapMove=0 then the driver will ignore taps.
- *
- * The touchpad on an 'Acer Aspire' has 4 buttons:
- * left,right,up,down.
- * This device always sets {mid,rig,lef}0 to 1 and
- * reflects left,right,down,up in lef1,rig1,mid1,up1.
+ * ?'s can have different meanings on different models,
+ * such as wheel rotation, extra buttons, stick buttons
+ * on a dualpoint, etc.
*/
static void alps_process_packet(struct psmouse *psmouse, struct pt_regs *regs)
{
+ struct alps_data *priv = psmouse->private;
unsigned char *packet = psmouse->packet;
struct input_dev *dev = &psmouse->dev;
- int x, y, z;
- int left = 0, right = 0, middle = 0;
+ struct input_dev *dev2 = &priv->dev2;
+ int x, y, z, ges, fin, left, right, middle;
input_regs(dev, regs);
if ((packet[0] & 0xc8) == 0x08) { /* 3-byte PS/2 packet */
- x = packet[1];
- if (packet[0] & 0x10)
- x = x - 256;
- y = packet[2];
- if (packet[0] & 0x20)
- y = y - 256;
- left = (packet[0] ) & 1;
- right = (packet[0] >> 1) & 1;
-
- input_report_rel(dev, REL_X, x);
- input_report_rel(dev, REL_Y, -y);
- input_report_key(dev, BTN_A, left);
- input_report_key(dev, BTN_B, right);
- input_sync(dev);
+ input_report_key(dev2, BTN_LEFT, packet[0] & 1);
+ input_report_key(dev2, BTN_RIGHT, packet[0] & 2);
+ input_report_key(dev2, BTN_MIDDLE, packet[0] & 4);
+ input_report_rel(dev2, REL_X,
+ packet[1] ? packet[1] - ((packet[0] << 4) & 0x100) : 0);
+ input_report_rel(dev2, REL_Y,
+ packet[2] ? ((packet[0] << 3) & 0x100) - packet[2] : 0);
+ input_sync(dev2);
return;
}
- x = (packet[1] & 0x7f) | ((packet[2] & 0x78)<<(7-3));
- y = (packet[4] & 0x7f) | ((packet[3] & 0x70)<<(7-4));
- z = packet[5];
-
- if (z == 127) { /* DualPoint stick is relative, not absolute */
- if (x > 383)
- x = x - 768;
- if (y > 255)
- y = y - 512;
- left = packet[3] & 1;
- right = (packet[3] >> 1) & 1;
-
- input_report_rel(dev, REL_X, x);
- input_report_rel(dev, REL_Y, -y);
- input_report_key(dev, BTN_LEFT, left);
- input_report_key(dev, BTN_RIGHT, right);
+ if (priv->i->flags & ALPS_OLDPROTO) {
+ left = packet[2] & 0x08;
+ right = packet[2] & 0x10;
+ middle = 0;
+ x = packet[1] | ((packet[0] & 0x07) << 7);
+ y = packet[4] | ((packet[3] & 0x07) << 7);
+ z = packet[5];
+ } else {
+ left = packet[3] & 1;
+ right = packet[3] & 2;
+ middle = packet[3] & 4;
+ x = packet[1] | ((packet[2] & 0x78) << (7 - 3));
+ y = packet[4] | ((packet[3] & 0x70) << (7 - 4));
+ z = packet[5];
+ }
+
+ ges = packet[2] & 1;
+ fin = packet[2] & 2;
+
+ input_report_key(dev, BTN_LEFT, left);
+ input_report_key(dev, BTN_RIGHT, right);
+ input_report_key(dev, BTN_MIDDLE, middle);
+
+ if ((priv->i->flags & ALPS_DUALPOINT) && z == 127) {
+ input_report_rel(dev2, REL_X, (x > 383 ? (x - 768) : x));
+ input_report_rel(dev2, REL_Y, -(y > 255 ? (y - 512) : y));
input_sync(dev);
+ input_sync(dev2);
return;
}
+ /* Convert hardware tap to a reasonable Z value */
+ if (ges && !fin) z = 40;
+
+ /*
+ * A "tap and drag" operation is reported by the hardware as a transition
+ * from (!fin && ges) to (fin && ges). This should be translated to the
+ * sequence Z>0, Z==0, Z>0, so the Z==0 event has to be generated manually.
+ */
+ if (ges && fin && !priv->prev_fin) {
+ input_report_abs(dev, ABS_X, x);
+ input_report_abs(dev, ABS_Y, y);
+ input_report_abs(dev, ABS_PRESSURE, 0);
+ input_report_key(dev, BTN_TOOL_FINGER, 0);
+ input_sync(dev);
+ }
+ priv->prev_fin = fin;
+
if (z > 30) input_report_key(dev, BTN_TOUCH, 1);
if (z < 25) input_report_key(dev, BTN_TOUCH, 0);
@@ -130,38 +151,26 @@ static void alps_process_packet(struct psmouse *psmouse, struct pt_regs *regs)
input_report_abs(dev, ABS_X, x);
input_report_abs(dev, ABS_Y, y);
}
+
input_report_abs(dev, ABS_PRESSURE, z);
input_report_key(dev, BTN_TOOL_FINGER, z > 0);
- left |= (packet[2] ) & 1;
- left |= (packet[3] ) & 1;
- right |= (packet[3] >> 1) & 1;
- if (packet[0] == 0xff) {
- int back = (packet[3] >> 2) & 1;
- int forward = (packet[2] >> 2) & 1;
- if (back && forward) {
- middle = 1;
- back = 0;
- forward = 0;
- }
- input_report_key(dev, BTN_BACK, back);
- input_report_key(dev, BTN_FORWARD, forward);
- } else {
- left |= (packet[0] ) & 1;
- right |= (packet[0] >> 1) & 1;
- middle |= (packet[0] >> 2) & 1;
- middle |= (packet[3] >> 2) & 1;
- }
- input_report_key(dev, BTN_LEFT, left);
- input_report_key(dev, BTN_RIGHT, right);
- input_report_key(dev, BTN_MIDDLE, middle);
+ if (priv->i->flags & ALPS_WHEEL)
+ input_report_rel(dev, REL_WHEEL, ((packet[0] >> 4) & 0x07) | ((packet[2] >> 2) & 0x08));
+
+ if (priv->i->flags & ALPS_FW_BK) {
+ input_report_key(dev, BTN_FORWARD, packet[0] & 0x10);
+ input_report_key(dev, BTN_BACK, packet[2] & 0x04);
+ }
input_sync(dev);
}
static psmouse_ret_t alps_process_byte(struct psmouse *psmouse, struct pt_regs *regs)
{
+ struct alps_data *priv = psmouse->private;
+
if ((psmouse->packet[0] & 0xc8) == 0x08) { /* PS/2 packet */
if (psmouse->pktcnt == 3) {
alps_process_packet(psmouse, regs);
@@ -170,13 +179,12 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse, struct pt_regs *
return PSMOUSE_GOOD_DATA;
}
- /* ALPS absolute mode packets start with 0b11111mrl */
- if ((psmouse->packet[0] & 0xf8) != 0xf8)
+ if ((psmouse->packet[0] & priv->i->mask0) != priv->i->byte0)
return PSMOUSE_BAD_DATA;
/* Bytes 2 - 6 should have 0 in the highest bit */
if (psmouse->pktcnt >= 2 && psmouse->pktcnt <= 6 &&
- (psmouse->packet[psmouse->pktcnt-1] & 0x80))
+ (psmouse->packet[psmouse->pktcnt - 1] & 0x80))
return PSMOUSE_BAD_DATA;
if (psmouse->pktcnt == 6) {
@@ -187,51 +195,58 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse, struct pt_regs *
return PSMOUSE_GOOD_DATA;
}
-int alps_get_model(struct psmouse *psmouse)
+static struct alps_model_info *alps_get_model(struct psmouse *psmouse, int *version)
{
struct ps2dev *ps2dev = &psmouse->ps2dev;
+ unsigned char rates[] = { 0, 10, 20, 40, 60, 80, 100, 200 };
unsigned char param[4];
int i;
/*
* First try "E6 report".
- * ALPS should return 0x00,0x00,0x0a or 0x00,0x00,0x64
+ * ALPS should return 0,0,10 or 0,0,100
*/
param[0] = 0;
if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES) ||
ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) ||
ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) ||
ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11))
- return -1;
+ return NULL;
param[0] = param[1] = param[2] = 0xff;
if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO))
- return -1;
+ return NULL;
dbg("E6 report: %2.2x %2.2x %2.2x", param[0], param[1], param[2]);
- if (param[0] != 0x00 || param[1] != 0x00 || (param[2] != 0x0a && param[2] != 0x64))
- return -1;
+ if (param[0] != 0 || param[1] != 0 || (param[2] != 10 && param[2] != 100))
+ return NULL;
- /* Now try "E7 report". ALPS should return 0x33 in byte 1 */
+ /*
+ * Now try "E7 report". Allowed responses are in
+ * alps_model_data[].signature
+ */
param[0] = 0;
if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES) ||
ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) ||
ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) ||
ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21))
- return -1;
+ return NULL;
param[0] = param[1] = param[2] = 0xff;
if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO))
- return -1;
+ return NULL;
dbg("E7 report: %2.2x %2.2x %2.2x", param[0], param[1], param[2]);
+ for (i = 0; i < ARRAY_SIZE(rates) && param[2] != rates[i]; i++);
+ *version = (param[0] << 8) | (param[1] << 4) | i;
+
for (i = 0; i < ARRAY_SIZE(alps_model_data); i++)
if (!memcmp(param, alps_model_data[i].signature, sizeof(alps_model_data[i].signature)))
- return alps_model_data[i].model;
+ return alps_model_data + i;
- return -1;
+ return NULL;
}
/*
@@ -322,27 +337,28 @@ static int alps_tap_mode(struct psmouse *psmouse, int enable)
static int alps_reconnect(struct psmouse *psmouse)
{
- int model;
+ struct alps_data *priv = psmouse->private;
unsigned char param[4];
+ int version;
- if ((model = alps_get_model(psmouse)) < 0)
+ if (!(priv->i = alps_get_model(psmouse, &version)))
return -1;
- if (model == ALPS_MODEL_DUALPOINT && alps_passthrough_mode(psmouse, 1))
+ if (priv->i->flags & ALPS_PASS && alps_passthrough_mode(psmouse, 1))
return -1;
if (alps_get_status(psmouse, param))
return -1;
if (param[0] & 0x04)
- alps_tap_mode(psmouse, 0);
+ alps_tap_mode(psmouse, 1);
if (alps_absolute_mode(psmouse)) {
printk(KERN_ERR "alps.c: Failed to enable absolute mode\n");
return -1;
}
- if (model == ALPS_MODEL_DUALPOINT && alps_passthrough_mode(psmouse, 0))
+ if (priv->i->flags == ALPS_PASS && alps_passthrough_mode(psmouse, 0))
return -1;
return 0;
@@ -350,57 +366,83 @@ static int alps_reconnect(struct psmouse *psmouse)
static void alps_disconnect(struct psmouse *psmouse)
{
+ struct alps_data *priv = psmouse->private;
psmouse_reset(psmouse);
+ input_unregister_device(&priv->dev2);
+ kfree(priv);
}
int alps_init(struct psmouse *psmouse)
{
+ struct alps_data *priv;
unsigned char param[4];
- int model;
+ int version;
- if ((model = alps_get_model(psmouse)) < 0)
- return -1;
+ psmouse->private = priv = kmalloc(sizeof(struct alps_data), GFP_KERNEL);
+ if (!priv)
+ goto init_fail;
+ memset(priv, 0, sizeof(struct alps_data));
- printk(KERN_INFO "ALPS Touchpad (%s) detected\n",
- model == ALPS_MODEL_GLIDEPOINT ? "Glidepoint" : "Dualpoint");
+ if (!(priv->i = alps_get_model(psmouse, &version)))
+ goto init_fail;
- if (model == ALPS_MODEL_DUALPOINT && alps_passthrough_mode(psmouse, 1))
- return -1;
+ if ((priv->i->flags & ALPS_PASS) && alps_passthrough_mode(psmouse, 1))
+ goto init_fail;
if (alps_get_status(psmouse, param)) {
printk(KERN_ERR "alps.c: touchpad status report request failed\n");
- return -1;
+ goto init_fail;
}
if (param[0] & 0x04) {
- printk(KERN_INFO " Disabling hardware tapping\n");
- if (alps_tap_mode(psmouse, 0))
- printk(KERN_WARNING "alps.c: Failed to disable hardware tapping\n");
+ printk(KERN_INFO " Enabling hardware tapping\n");
+ if (alps_tap_mode(psmouse, 1))
+ printk(KERN_WARNING "alps.c: Failed to enable hardware tapping\n");
}
if (alps_absolute_mode(psmouse)) {
printk(KERN_ERR "alps.c: Failed to enable absolute mode\n");
- return -1;
+ goto init_fail;
}
- if (model == ALPS_MODEL_DUALPOINT && alps_passthrough_mode(psmouse, 0))
- return -1;
+ if ((priv->i->flags & ALPS_PASS) && alps_passthrough_mode(psmouse, 0))
+ goto init_fail;
- psmouse->dev.evbit[LONG(EV_REL)] |= BIT(EV_REL);
- psmouse->dev.relbit[LONG(REL_X)] |= BIT(REL_X);
- psmouse->dev.relbit[LONG(REL_Y)] |= BIT(REL_Y);
- psmouse->dev.keybit[LONG(BTN_A)] |= BIT(BTN_A);
- psmouse->dev.keybit[LONG(BTN_B)] |= BIT(BTN_B);
+ psmouse->dev.evbit[LONG(EV_KEY)] |= BIT(EV_KEY);
+ psmouse->dev.keybit[LONG(BTN_TOUCH)] |= BIT(BTN_TOUCH);
+ psmouse->dev.keybit[LONG(BTN_TOOL_FINGER)] |= BIT(BTN_TOOL_FINGER);
+ psmouse->dev.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
psmouse->dev.evbit[LONG(EV_ABS)] |= BIT(EV_ABS);
input_set_abs_params(&psmouse->dev, ABS_X, 0, 1023, 0, 0);
- input_set_abs_params(&psmouse->dev, ABS_Y, 0, 1023, 0, 0);
+ input_set_abs_params(&psmouse->dev, ABS_Y, 0, 767, 0, 0);
input_set_abs_params(&psmouse->dev, ABS_PRESSURE, 0, 127, 0, 0);
- psmouse->dev.keybit[LONG(BTN_TOUCH)] |= BIT(BTN_TOUCH);
- psmouse->dev.keybit[LONG(BTN_TOOL_FINGER)] |= BIT(BTN_TOOL_FINGER);
- psmouse->dev.keybit[LONG(BTN_FORWARD)] |= BIT(BTN_FORWARD);
- psmouse->dev.keybit[LONG(BTN_BACK)] |= BIT(BTN_BACK);
+ if (priv->i->flags & ALPS_WHEEL) {
+ psmouse->dev.evbit[LONG(EV_REL)] |= BIT(EV_REL);
+ psmouse->dev.relbit[LONG(REL_WHEEL)] |= BIT(REL_WHEEL);
+ }
+
+ if (priv->i->flags & ALPS_FW_BK) {
+ psmouse->dev.keybit[LONG(BTN_FORWARD)] |= BIT(BTN_FORWARD);
+ psmouse->dev.keybit[LONG(BTN_BACK)] |= BIT(BTN_BACK);
+ }
+
+ sprintf(priv->phys, "%s/input1", psmouse->ps2dev.serio->phys);
+ priv->dev2.phys = priv->phys;
+ priv->dev2.name = (priv->i->flags & ALPS_DUALPOINT) ? "DualPoint Stick" : "PS/2 Mouse";
+ priv->dev2.id.bustype = BUS_I8042;
+ priv->dev2.id.vendor = 0x0002;
+ priv->dev2.id.product = PSMOUSE_ALPS;
+ priv->dev2.id.version = 0x0000;
+
+ priv->dev2.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
+ priv->dev2.relbit[LONG(REL_X)] |= BIT(REL_X) | BIT(REL_Y);
+ priv->dev2.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
+
+ input_register_device(&priv->dev2);
+
+ printk(KERN_INFO "input: %s on %s\n", priv->dev2.name, psmouse->ps2dev.serio->phys);
psmouse->protocol_handler = alps_process_byte;
psmouse->disconnect = alps_disconnect;
@@ -408,16 +450,27 @@ int alps_init(struct psmouse *psmouse)
psmouse->pktsize = 6;
return 0;
+
+init_fail:
+ kfree(priv);
+ return -1;
}
int alps_detect(struct psmouse *psmouse, int set_properties)
{
- if (alps_get_model(psmouse) < 0)
+ int version;
+ struct alps_model_info *model;
+
+ if (!(model = alps_get_model(psmouse, &version)))
return -1;
if (set_properties) {
psmouse->vendor = "ALPS";
- psmouse->name = "TouchPad";
+ if (model->flags & ALPS_DUALPOINT)
+ psmouse->name = "DualPoint TouchPad";
+ else
+ psmouse->name = "GlidePoint";
+ psmouse->model = version;
}
return 0;
}
diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h
index 8efcec5d0a66e..aba103dd65b79 100644
--- a/drivers/input/mouse/alps.h
+++ b/drivers/input/mouse/alps.h
@@ -2,6 +2,7 @@
* ALPS touchpad PS/2 mouse driver
*
* Copyright (c) 2003 Peter Osterlund <petero2@telia.com>
+ * Copyright (c) 2005 Vojtech Pavlik <vojtech@suse.cz>
*
* 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
@@ -14,4 +15,18 @@
int alps_detect(struct psmouse *psmouse, int set_properties);
int alps_init(struct psmouse *psmouse);
+struct alps_model_info {
+ unsigned char signature[3];
+ unsigned char byte0, mask0;
+ unsigned char flags;
+};
+
+struct alps_data {
+ struct input_dev dev2; /* Relative device */
+ char name[32]; /* Name */
+ char phys[32]; /* Phys */
+ struct alps_model_info *i; /* Info */
+ int prev_fin; /* Finger bit from previous packet */
+};
+
#endif
diff --git a/drivers/input/mouse/hil_ptr.c b/drivers/input/mouse/hil_ptr.c
new file mode 100644
index 0000000000000..bc22849c6c79e
--- /dev/null
+++ b/drivers/input/mouse/hil_ptr.c
@@ -0,0 +1,414 @@
+/*
+ * Generic linux-input device driver for axis-bearing devices
+ *
+ * Copyright (c) 2001 Brian S. Julin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. The name of the author may not 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").
+ *
+ * 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
+ *
+ * References:
+ * HP-HIL Technical Reference Manual. Hewlett Packard Product No. 45918A
+ *
+ */
+
+#include <linux/hil.h>
+#include <linux/input.h>
+#include <linux/serio.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/pci_ids.h>
+
+#define PREFIX "HIL PTR: "
+#define HIL_GENERIC_NAME "HIL pointer device"
+
+MODULE_AUTHOR("Brian S. Julin <bri@calyx.com>");
+MODULE_DESCRIPTION(HIL_GENERIC_NAME " driver");
+MODULE_LICENSE("Dual BSD/GPL");
+
+
+#define TABLET_SIMULATES_MOUSE /* allow tablet to be used as mouse */
+#undef TABLET_AUTOADJUST /* auto-adjust valid tablet ranges */
+
+
+#define HIL_PTR_MAX_LENGTH 16
+
+struct hil_ptr {
+ struct input_dev dev;
+ struct serio *serio;
+
+ /* Input buffer and index for packets from HIL bus. */
+ hil_packet data[HIL_PTR_MAX_LENGTH];
+ int idx4; /* four counts per packet */
+
+ /* Raw device info records from HIL bus, see hil.h for fields. */
+ char idd[HIL_PTR_MAX_LENGTH]; /* DID byte and IDD record */
+ char rsc[HIL_PTR_MAX_LENGTH]; /* RSC record */
+ char exd[HIL_PTR_MAX_LENGTH]; /* EXD record */
+ char rnm[HIL_PTR_MAX_LENGTH + 1]; /* RNM record + NULL term. */
+
+ /* Extra device details not contained in struct input_dev. */
+ unsigned int nbtn, naxes;
+ unsigned int btnmap[7];
+
+ /* Something to sleep around with. */
+ struct semaphore sem;
+};
+
+/* Process a complete packet after transfer from the HIL */
+static void hil_ptr_process_record(struct hil_ptr *ptr)
+{
+ struct input_dev *dev = &ptr->dev;
+ hil_packet *data = ptr->data;
+ hil_packet p;
+ int idx, i, cnt, laxis;
+ int ax16, absdev;
+
+ idx = ptr->idx4/4;
+ p = data[idx - 1];
+
+ if ((p & ~HIL_CMDCT_POL) ==
+ (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL)) goto report;
+ if ((p & ~HIL_CMDCT_RPL) ==
+ (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_RPL)) goto report;
+
+ /* Not a poll response. See if we are loading config records. */
+ switch (p & HIL_PKT_DATA_MASK) {
+ case HIL_CMD_IDD:
+ for (i = 0; i < idx; i++)
+ ptr->idd[i] = ptr->data[i] & HIL_PKT_DATA_MASK;
+ for (; i < HIL_PTR_MAX_LENGTH; i++)
+ ptr->idd[i] = 0;
+ break;
+ case HIL_CMD_RSC:
+ for (i = 0; i < idx; i++)
+ ptr->rsc[i] = ptr->data[i] & HIL_PKT_DATA_MASK;
+ for (; i < HIL_PTR_MAX_LENGTH; i++)
+ ptr->rsc[i] = 0;
+ break;
+ case HIL_CMD_EXD:
+ for (i = 0; i < idx; i++)
+ ptr->exd[i] = ptr->data[i] & HIL_PKT_DATA_MASK;
+ for (; i < HIL_PTR_MAX_LENGTH; i++)
+ ptr->exd[i] = 0;
+ break;
+ case HIL_CMD_RNM:
+ for (i = 0; i < idx; i++)
+ ptr->rnm[i] = ptr->data[i] & HIL_PKT_DATA_MASK;
+ for (; i < HIL_PTR_MAX_LENGTH + 1; i++)
+ ptr->rnm[i] = '\0';
+ break;
+ default:
+ /* These occur when device isn't present */
+ if (p == (HIL_ERR_INT | HIL_PKT_CMD)) break;
+ /* Anything else we'd like to know about. */
+ printk(KERN_WARNING PREFIX "Device sent unknown record %x\n", p);
+ break;
+ }
+ goto out;
+
+ report:
+ if ((p & HIL_CMDCT_POL) != idx - 1) {
+ printk(KERN_WARNING PREFIX "Malformed poll packet %x (idx = %i)\n", p, idx);
+ goto out;
+ }
+
+ i = (ptr->data[0] & HIL_POL_AXIS_ALT) ? 3 : 0;
+ laxis = ptr->data[0] & HIL_POL_NUM_AXES_MASK;
+ laxis += i;
+
+ ax16 = ptr->idd[1] & HIL_IDD_HEADER_16BIT; /* 8 or 16bit resolution */
+ absdev = ptr->idd[1] & HIL_IDD_HEADER_ABS;
+
+ for (cnt = 1; i < laxis; i++) {
+ unsigned int lo,hi,val;
+ lo = ptr->data[cnt++] & HIL_PKT_DATA_MASK;
+ hi = ax16 ? (ptr->data[cnt++] & HIL_PKT_DATA_MASK) : 0;
+ if (absdev) {
+ val = lo + (hi<<8);
+#ifdef TABLET_AUTOADJUST
+ if (val < ptr->dev.absmin[ABS_X + i])
+ ptr->dev.absmin[ABS_X + i] = val;
+ if (val > ptr->dev.absmax[ABS_X + i])
+ ptr->dev.absmax[ABS_X + i] = val;
+#endif
+ if (i%3) val = ptr->dev.absmax[ABS_X + i] - val;
+ input_report_abs(dev, ABS_X + i, val);
+ } else {
+ val = (int) (((int8_t)lo) | ((int8_t)hi<<8));
+ if (i%3) val *= -1;
+ input_report_rel(dev, REL_X + i, val);
+ }
+ }
+
+ while (cnt < idx - 1) {
+ unsigned int btn;
+ int up;
+ btn = ptr->data[cnt++];
+ up = btn & 1;
+ btn &= 0xfe;
+ if (btn == 0x8e) {
+ continue; /* TODO: proximity == touch? */
+ }
+ else if ((btn > 0x8c) || (btn < 0x80)) continue;
+ btn = (btn - 0x80) >> 1;
+ btn = ptr->btnmap[btn];
+ input_report_key(dev, btn, !up);
+ }
+ input_sync(dev);
+ out:
+ ptr->idx4 = 0;
+ up(&ptr->sem);
+}
+
+static void hil_ptr_process_err(struct hil_ptr *ptr) {
+ printk(KERN_WARNING PREFIX "errored HIL packet\n");
+ ptr->idx4 = 0;
+ up(&ptr->sem);
+ return;
+}
+
+static irqreturn_t hil_ptr_interrupt(struct serio *serio,
+ unsigned char data, unsigned int flags, struct pt_regs *regs)
+{
+ struct hil_ptr *ptr;
+ hil_packet packet;
+ int idx;
+
+ ptr = (struct hil_ptr *)serio->private;
+ if (ptr == NULL) {
+ BUG();
+ return IRQ_HANDLED;
+ }
+
+ if (ptr->idx4 >= (HIL_PTR_MAX_LENGTH * sizeof(hil_packet))) {
+ hil_ptr_process_err(ptr);
+ return IRQ_HANDLED;
+ }
+ idx = ptr->idx4/4;
+ if (!(ptr->idx4 % 4)) ptr->data[idx] = 0;
+ packet = ptr->data[idx];
+ packet |= ((hil_packet)data) << ((3 - (ptr->idx4 % 4)) * 8);
+ ptr->data[idx] = packet;
+
+ /* Records of N 4-byte hil_packets must terminate with a command. */
+ if ((++(ptr->idx4)) % 4) return IRQ_HANDLED;
+ if ((packet & 0xffff0000) != HIL_ERR_INT) {
+ hil_ptr_process_err(ptr);
+ return IRQ_HANDLED;
+ }
+ if (packet & HIL_PKT_CMD)
+ hil_ptr_process_record(ptr);
+ return IRQ_HANDLED;
+}
+
+static void hil_ptr_disconnect(struct serio *serio)
+{
+ struct hil_ptr *ptr;
+
+ ptr = (struct hil_ptr *)serio->private;
+ if (ptr == NULL) {
+ BUG();
+ return;
+ }
+
+ input_unregister_device(&ptr->dev);
+ serio_close(serio);
+ kfree(ptr);
+}
+
+static void hil_ptr_connect(struct serio *serio, struct serio_driver *driver)
+{
+ struct hil_ptr *ptr;
+ char *txt;
+ unsigned int i, naxsets, btntype;
+ uint8_t did, *idd;
+
+ if (serio->type != (SERIO_HIL_MLC | SERIO_HIL)) return;
+
+ if (!(ptr = kmalloc(sizeof(struct hil_ptr), GFP_KERNEL))) return;
+ memset(ptr, 0, sizeof(struct hil_ptr));
+
+ if (serio_open(serio, driver)) goto bail0;
+
+ serio->private = ptr;
+ ptr->serio = serio;
+ ptr->dev.private = ptr;
+
+ init_MUTEX_LOCKED(&(ptr->sem));
+
+ /* Get device info. MLC driver supplies devid/status/etc. */
+ serio->write(serio, 0);
+ serio->write(serio, 0);
+ serio->write(serio, HIL_PKT_CMD >> 8);
+ serio->write(serio, HIL_CMD_IDD);
+ down(&(ptr->sem));
+
+ serio->write(serio, 0);
+ serio->write(serio, 0);
+ serio->write(serio, HIL_PKT_CMD >> 8);
+ serio->write(serio, HIL_CMD_RSC);
+ down(&(ptr->sem));
+
+ serio->write(serio, 0);
+ serio->write(serio, 0);
+ serio->write(serio, HIL_PKT_CMD >> 8);
+ serio->write(serio, HIL_CMD_RNM);
+ down(&(ptr->sem));
+
+ serio->write(serio, 0);
+ serio->write(serio, 0);
+ serio->write(serio, HIL_PKT_CMD >> 8);
+ serio->write(serio, HIL_CMD_EXD);
+ down(&(ptr->sem));
+
+ up(&(ptr->sem));
+
+ init_input_dev(&ptr->dev);
+ did = ptr->idd[0];
+ idd = ptr->idd + 1;
+ txt = "unknown";
+ if ((did & HIL_IDD_DID_TYPE_MASK) == HIL_IDD_DID_TYPE_REL) {
+ ptr->dev.evbit[0] = BIT(EV_REL);
+ txt = "relative";
+ }
+
+ if ((did & HIL_IDD_DID_TYPE_MASK) == HIL_IDD_DID_TYPE_ABS) {
+ ptr->dev.evbit[0] = BIT(EV_ABS);
+ txt = "absolute";
+ }
+ if (!ptr->dev.evbit[0]) {
+ goto bail1;
+ }
+
+ ptr->nbtn = HIL_IDD_NUM_BUTTONS(idd);
+ if (ptr->nbtn) ptr->dev.evbit[0] |= BIT(EV_KEY);
+
+ naxsets = HIL_IDD_NUM_AXSETS(*idd);
+ ptr->naxes = HIL_IDD_NUM_AXES_PER_SET(*idd);
+
+ printk(KERN_INFO PREFIX "HIL pointer device found (did: 0x%02x, axis: %s)\n",
+ did, txt);
+ printk(KERN_INFO PREFIX "HIL pointer has %i buttons and %i sets of %i axes\n",
+ ptr->nbtn, naxsets, ptr->naxes);
+
+ btntype = BTN_MISC;
+ if ((did & HIL_IDD_DID_ABS_TABLET_MASK) == HIL_IDD_DID_ABS_TABLET)
+#ifdef TABLET_SIMULATES_MOUSE
+ btntype = BTN_TOUCH;
+#else
+ btntype = BTN_DIGI;
+#endif
+ if ((did & HIL_IDD_DID_ABS_TSCREEN_MASK) == HIL_IDD_DID_ABS_TSCREEN)
+ btntype = BTN_TOUCH;
+
+ if ((did & HIL_IDD_DID_REL_MOUSE_MASK) == HIL_IDD_DID_REL_MOUSE)
+ btntype = BTN_MOUSE;
+
+ for (i = 0; i < ptr->nbtn; i++) {
+ set_bit(btntype | i, ptr->dev.keybit);
+ ptr->btnmap[i] = btntype | i;
+ }
+
+ if (btntype == BTN_MOUSE) {
+ /* Swap buttons 2 and 3 */
+ ptr->btnmap[1] = BTN_MIDDLE;
+ ptr->btnmap[2] = BTN_RIGHT;
+ }
+
+ if ((did & HIL_IDD_DID_TYPE_MASK) == HIL_IDD_DID_TYPE_REL) {
+ for (i = 0; i < ptr->naxes; i++) {
+ set_bit(REL_X + i, ptr->dev.relbit);
+ }
+ for (i = 3; (i < ptr->naxes + 3) && (naxsets > 1); i++) {
+ set_bit(REL_X + i, ptr->dev.relbit);
+ }
+ } else {
+ for (i = 0; i < ptr->naxes; i++) {
+ set_bit(ABS_X + i, ptr->dev.absbit);
+ ptr->dev.absmin[ABS_X + i] = 0;
+ ptr->dev.absmax[ABS_X + i] =
+ HIL_IDD_AXIS_MAX((ptr->idd + 1), i);
+ }
+ for (i = 3; (i < ptr->naxes + 3) && (naxsets > 1); i++) {
+ set_bit(ABS_X + i, ptr->dev.absbit);
+ ptr->dev.absmin[ABS_X + i] = 0;
+ ptr->dev.absmax[ABS_X + i] =
+ HIL_IDD_AXIS_MAX((ptr->idd + 1), (i - 3));
+ }
+#ifdef TABLET_AUTOADJUST
+ for (i = 0; i < ABS_MAX; i++) {
+ int diff = ptr->dev.absmax[ABS_X + i] / 10;
+ ptr->dev.absmin[ABS_X + i] += diff;
+ ptr->dev.absmax[ABS_X + i] -= diff;
+ }
+#endif
+ }
+
+ ptr->dev.name = strlen(ptr->rnm) ? ptr->rnm : HIL_GENERIC_NAME;
+
+ ptr->dev.id.bustype = BUS_HIL;
+ ptr->dev.id.vendor = PCI_VENDOR_ID_HP;
+ ptr->dev.id.product = 0x0001; /* TODO: get from ptr->rsc */
+ ptr->dev.id.version = 0x0100; /* TODO: get from ptr->rsc */
+ ptr->dev.dev = &serio->dev;
+
+ input_register_device(&ptr->dev);
+ printk(KERN_INFO "input: %s (%s), ID: %d\n",
+ ptr->dev.name,
+ (btntype == BTN_MOUSE) ? "HIL mouse":"HIL tablet or touchpad",
+ did);
+
+ return;
+ bail1:
+ serio_close(serio);
+ bail0:
+ kfree(ptr);
+ return;
+}
+
+
+static struct serio_driver hil_ptr_serio_driver = {
+ .driver = {
+ .name = "hil_ptr",
+ },
+ .description = "HP HIL mouse/tablet driver",
+ .connect = hil_ptr_connect,
+ .disconnect = hil_ptr_disconnect,
+ .interrupt = hil_ptr_interrupt
+};
+
+static int __init hil_ptr_init(void)
+{
+ serio_register_driver(&hil_ptr_serio_driver);
+ return 0;
+}
+
+static void __exit hil_ptr_exit(void)
+{
+ serio_unregister_driver(&hil_ptr_serio_driver);
+}
+
+module_init(hil_ptr_init);
+module_exit(hil_ptr_exit);
diff --git a/drivers/input/mouse/logips2pp.c b/drivers/input/mouse/logips2pp.c
index 9c8f659178248..5ab1bd7d529d7 100644
--- a/drivers/input/mouse/logips2pp.c
+++ b/drivers/input/mouse/logips2pp.c
@@ -202,6 +202,9 @@ static struct ps2pp_info *get_model_info(unsigned char model)
static struct ps2pp_info ps2pp_list[] = {
{ 12, 0, PS2PP_SIDE_BTN},
{ 13, 0, 0 },
+ { 15, PS2PP_KIND_MX, /* MX1000 */
+ PS2PP_WHEEL | PS2PP_SIDE_BTN | PS2PP_TASK_BTN |
+ PS2PP_EXTRA_BTN | PS2PP_NAV_BTN | PS2PP_HWHEEL },
{ 40, 0, PS2PP_SIDE_BTN },
{ 41, 0, PS2PP_SIDE_BTN },
{ 42, 0, PS2PP_SIDE_BTN },
@@ -210,9 +213,9 @@ static struct ps2pp_info *get_model_info(unsigned char model)
{ 51, 0, 0 },
{ 52, PS2PP_KIND_WHEEL, PS2PP_SIDE_BTN | PS2PP_WHEEL },
{ 53, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
- { 61, PS2PP_KIND_MX,
+ { 61, PS2PP_KIND_MX, /* MX700 */
PS2PP_WHEEL | PS2PP_SIDE_BTN | PS2PP_TASK_BTN |
- PS2PP_EXTRA_BTN | PS2PP_NAV_BTN }, /* MX700 */
+ PS2PP_EXTRA_BTN | PS2PP_NAV_BTN },
{ 73, 0, PS2PP_SIDE_BTN },
{ 75, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
{ 76, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
@@ -222,15 +225,17 @@ static struct ps2pp_info *get_model_info(unsigned char model)
{ 88, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
{ 96, 0, 0 },
{ 97, PS2PP_KIND_TP3, PS2PP_WHEEL | PS2PP_HWHEEL },
- { 100, PS2PP_KIND_MX,
+ { 100, PS2PP_KIND_MX, /* MX510 */
PS2PP_WHEEL | PS2PP_SIDE_BTN | PS2PP_TASK_BTN |
- PS2PP_EXTRA_BTN | PS2PP_NAV_BTN }, /* MX510 */
- { 112, PS2PP_KIND_MX,
+ PS2PP_EXTRA_BTN | PS2PP_NAV_BTN },
+ { 111, PS2PP_KIND_MX, /* MX300 */
+ PS2PP_WHEEL | PS2PP_EXTRA_BTN | PS2PP_TASK_BTN },
+ { 112, PS2PP_KIND_MX, /* MX500 */
PS2PP_WHEEL | PS2PP_SIDE_BTN | PS2PP_TASK_BTN |
- PS2PP_EXTRA_BTN | PS2PP_NAV_BTN }, /* MX500 */
- { 114, PS2PP_KIND_MX,
+ PS2PP_EXTRA_BTN | PS2PP_NAV_BTN },
+ { 114, PS2PP_KIND_MX, /* MX310 */
PS2PP_WHEEL | PS2PP_SIDE_BTN |
- PS2PP_TASK_BTN | PS2PP_EXTRA_BTN }, /* M310 */
+ PS2PP_TASK_BTN | PS2PP_EXTRA_BTN },
{ }
};
int i;
@@ -238,6 +243,8 @@ static struct ps2pp_info *get_model_info(unsigned char model)
for (i = 0; ps2pp_list[i].model; i++)
if (model == ps2pp_list[i].model)
return &ps2pp_list[i];
+
+ printk(KERN_WARNING "logips2pp: Detected unknown logitech mouse model %d\n", model);
return NULL;
}
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
index 5c975d55f9d52..cd8509549eac6 100644
--- a/drivers/input/mouse/psmouse-base.c
+++ b/drivers/input/mouse/psmouse-base.c
@@ -31,25 +31,30 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
-static char *psmouse_proto;
static unsigned int psmouse_max_proto = -1U;
-module_param_named(proto, psmouse_proto, charp, 0);
-MODULE_PARM_DESC(proto, "Highest protocol extension to probe (bare, imps, exps). Useful for KVM switches.");
+static int psmouse_set_maxproto(const char *val, struct kernel_param *kp);
+static int psmouse_get_maxproto(char *buffer, struct kernel_param *kp);
+static char *psmouse_proto_abbrev[] = { NULL, "bare", NULL, NULL, NULL, "imps", "exps", NULL, NULL, NULL };
+#define param_check_proto_abbrev(name, p) __param_check(name, p, unsigned int)
+#define param_set_proto_abbrev psmouse_set_maxproto
+#define param_get_proto_abbrev psmouse_get_maxproto
+module_param_named(proto, psmouse_max_proto, proto_abbrev, 0644);
+MODULE_PARM_DESC(proto, "Highest protocol extension to probe (bare, imps, exps, any). Useful for KVM switches.");
static unsigned int psmouse_resolution = 200;
-module_param_named(resolution, psmouse_resolution, uint, 0);
+module_param_named(resolution, psmouse_resolution, uint, 0644);
MODULE_PARM_DESC(resolution, "Resolution, in dpi.");
static unsigned int psmouse_rate = 100;
-module_param_named(rate, psmouse_rate, uint, 0);
+module_param_named(rate, psmouse_rate, uint, 0644);
MODULE_PARM_DESC(rate, "Report rate, in reports per second.");
static unsigned int psmouse_smartscroll = 1;
-module_param_named(smartscroll, psmouse_smartscroll, bool, 0);
+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;
-module_param_named(resetafter, psmouse_resetafter, uint, 0);
+module_param_named(resetafter, psmouse_resetafter, uint, 0644);
MODULE_PARM_DESC(resetafter, "Reset device after so many bad packets (0 = never).");
PSMOUSE_DEFINE_ATTR(rate);
@@ -142,7 +147,7 @@ static psmouse_ret_t psmouse_process_byte(struct psmouse *psmouse, struct pt_reg
static irqreturn_t psmouse_interrupt(struct serio *serio,
unsigned char data, unsigned int flags, struct pt_regs *regs)
{
- struct psmouse *psmouse = serio->private;
+ struct psmouse *psmouse = serio_get_drvdata(serio);
psmouse_ret_t rc;
if (psmouse->state == PSMOUSE_IGNORE)
@@ -423,7 +428,7 @@ static int psmouse_extensions(struct psmouse *psmouse,
* upsets the thinkingmouse).
*/
- if (max_proto > PSMOUSE_PS2 && thinking_detect(psmouse, set_properties) == 0)
+ if (max_proto > PSMOUSE_IMEX && thinking_detect(psmouse, set_properties) == 0)
return PSMOUSE_THINKPS;
/*
@@ -634,7 +639,7 @@ static void psmouse_deactivate(struct psmouse *psmouse)
static void psmouse_cleanup(struct serio *serio)
{
- struct psmouse *psmouse = serio->private;
+ struct psmouse *psmouse = serio_get_drvdata(serio);
psmouse_reset(psmouse);
}
@@ -651,11 +656,11 @@ static void psmouse_disconnect(struct serio *serio)
device_remove_file(&serio->dev, &psmouse_attr_resolution);
device_remove_file(&serio->dev, &psmouse_attr_resetafter);
- psmouse = serio->private;
+ psmouse = serio_get_drvdata(serio);
psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
- if (serio->parent && (serio->type & SERIO_TYPE) == SERIO_PS_PSTHRU) {
- parent = serio->parent->private;
+ if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
+ parent = serio_get_drvdata(serio->parent);
if (parent->pt_deactivate)
parent->pt_deactivate(parent);
}
@@ -667,6 +672,7 @@ static void psmouse_disconnect(struct serio *serio)
input_unregister_device(&psmouse->dev);
serio_close(serio);
+ serio_set_drvdata(serio, NULL);
kfree(psmouse);
}
@@ -674,29 +680,29 @@ static void psmouse_disconnect(struct serio *serio)
* psmouse_connect() is a callback from the serio module when
* an unhandled serio port is found.
*/
-static void psmouse_connect(struct serio *serio, struct serio_driver *drv)
+static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
{
struct psmouse *psmouse, *parent = NULL;
-
- if ((serio->type & SERIO_TYPE) != SERIO_8042 &&
- (serio->type & SERIO_TYPE) != SERIO_PS_PSTHRU)
- return;
+ int retval;
/*
* If this is a pass-through port deactivate parent so the device
* connected to this port can be successfully identified
*/
- if (serio->parent && (serio->type & SERIO_TYPE) == SERIO_PS_PSTHRU) {
- parent = serio->parent->private;
+ if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
+ parent = serio_get_drvdata(serio->parent);
psmouse_deactivate(parent);
}
- if (!(psmouse = kmalloc(sizeof(struct psmouse), GFP_KERNEL)))
+ if (!(psmouse = kmalloc(sizeof(struct psmouse), GFP_KERNEL))) {
+ retval = -ENOMEM;
goto out;
+ }
memset(psmouse, 0, sizeof(struct psmouse));
ps2_init(&psmouse->ps2dev, serio);
+ sprintf(psmouse->phys, "%s/input0", serio->phys);
psmouse->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
psmouse->dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
psmouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y);
@@ -704,17 +710,20 @@ static void psmouse_connect(struct serio *serio, struct serio_driver *drv)
psmouse->dev.dev = &serio->dev;
psmouse_set_state(psmouse, PSMOUSE_INITIALIZING);
- serio->private = psmouse;
- if (serio_open(serio, drv)) {
+ serio_set_drvdata(serio, psmouse);
+
+ retval = serio_open(serio, drv);
+ if (retval) {
+ serio_set_drvdata(serio, NULL);
kfree(psmouse);
- serio->private = NULL;
goto out;
}
if (psmouse_probe(psmouse) < 0) {
serio_close(serio);
+ serio_set_drvdata(serio, NULL);
kfree(psmouse);
- serio->private = NULL;
+ retval = -ENODEV;
goto out;
}
@@ -731,8 +740,6 @@ static void psmouse_connect(struct serio *serio, struct serio_driver *drv)
sprintf(psmouse->devname, "%s %s %s",
psmouse_protocols[psmouse->type], psmouse->vendor, psmouse->name);
- sprintf(psmouse->phys, "%s/input0",
- serio->phys);
psmouse->dev.name = psmouse->devname;
psmouse->dev.phys = psmouse->phys;
@@ -756,26 +763,22 @@ static void psmouse_connect(struct serio *serio, struct serio_driver *drv)
device_create_file(&serio->dev, &psmouse_attr_resolution);
device_create_file(&serio->dev, &psmouse_attr_resetafter);
- if (serio->child) {
- /*
- * Nothing to be done here, serio core will detect that
- * the driver set serio->child and will register it for us.
- */
- printk(KERN_INFO "serio: %s port at %s\n", serio->child->name, psmouse->phys);
- }
-
psmouse_activate(psmouse);
+ retval = 0;
+
out:
/* If this is a pass-through port the parent awaits to be activated */
if (parent)
psmouse_activate(parent);
+
+ return retval;
}
static int psmouse_reconnect(struct serio *serio)
{
- struct psmouse *psmouse = serio->private;
+ struct psmouse *psmouse = serio_get_drvdata(serio);
struct psmouse *parent = NULL;
struct serio_driver *drv = serio->drv;
int rc = -1;
@@ -785,8 +788,8 @@ static int psmouse_reconnect(struct serio *serio)
return -1;
}
- if (serio->parent && (serio->type & SERIO_TYPE) == SERIO_PS_PSTHRU) {
- parent = serio->parent->private;
+ if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
+ parent = serio_get_drvdata(serio->parent);
psmouse_deactivate(parent);
}
@@ -820,12 +823,30 @@ out:
return rc;
}
+static struct serio_device_id psmouse_serio_ids[] = {
+ {
+ .type = SERIO_8042,
+ .proto = SERIO_ANY,
+ .id = SERIO_ANY,
+ .extra = SERIO_ANY,
+ },
+ {
+ .type = SERIO_PS_PSTHRU,
+ .proto = SERIO_ANY,
+ .id = SERIO_ANY,
+ .extra = SERIO_ANY,
+ },
+ { 0 }
+};
+
+MODULE_DEVICE_TABLE(serio, psmouse_serio_ids);
static struct serio_driver psmouse_drv = {
.driver = {
.name = "psmouse",
},
.description = DRIVER_DESC,
+ .id_table = psmouse_serio_ids,
.interrupt = psmouse_interrupt,
.connect = psmouse_connect,
.reconnect = psmouse_reconnect,
@@ -848,7 +869,7 @@ ssize_t psmouse_attr_show_helper(struct device *dev, char *buf,
goto out;
}
- retval = handler(serio->private, buf);
+ retval = handler(serio_get_drvdata(serio), buf);
out:
serio_unpin_driver(serio);
@@ -859,7 +880,8 @@ ssize_t psmouse_attr_set_helper(struct device *dev, const char *buf, size_t coun
ssize_t (*handler)(struct psmouse *, const char *, size_t))
{
struct serio *serio = to_serio_port(dev);
- struct psmouse *psmouse = serio->private, *parent = NULL;
+ struct psmouse *psmouse = serio_get_drvdata(serio);
+ struct psmouse *parent = NULL;
int retval;
retval = serio_pin_driver(serio);
@@ -871,8 +893,8 @@ ssize_t psmouse_attr_set_helper(struct device *dev, const char *buf, size_t coun
goto out;
}
- if (serio->parent && (serio->type & SERIO_TYPE) == SERIO_PS_PSTHRU) {
- parent = serio->parent->private;
+ if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
+ parent = serio_get_drvdata(serio->parent);
psmouse_deactivate(parent);
}
psmouse_deactivate(psmouse);
@@ -942,28 +964,45 @@ static ssize_t psmouse_attr_set_resetafter(struct psmouse *psmouse, const char *
return count;
}
-static inline void psmouse_parse_proto(void)
+static int psmouse_set_maxproto(const char *val, struct kernel_param *kp)
{
- if (psmouse_proto) {
- if (!strcmp(psmouse_proto, "bare"))
- psmouse_max_proto = PSMOUSE_PS2;
- else if (!strcmp(psmouse_proto, "imps"))
- psmouse_max_proto = PSMOUSE_IMPS;
- else if (!strcmp(psmouse_proto, "exps"))
- psmouse_max_proto = PSMOUSE_IMEX;
- else
- printk(KERN_ERR "psmouse: unknown protocol type '%s'\n", psmouse_proto);
+ int i;
+
+ if (!val)
+ return -EINVAL;
+
+ if (!strncmp(val, "any", 3)) {
+ *((unsigned int *)kp->arg) = -1UL;
+ return 0;
}
+
+ for (i = 0; i < ARRAY_SIZE(psmouse_proto_abbrev); i++) {
+ if (!psmouse_proto_abbrev[i])
+ continue;
+
+ if (!strncmp(val, psmouse_proto_abbrev[i], strlen(psmouse_proto_abbrev[i]))) {
+ *((unsigned int *)kp->arg) = i;
+ return 0;
+ }
+ }
+
+ return -EINVAL; \
+}
+
+static int psmouse_get_maxproto(char *buffer, struct kernel_param *kp)
+{
+ return sprintf(buffer, "%s\n",
+ psmouse_max_proto < ARRAY_SIZE(psmouse_proto_abbrev) ?
+ psmouse_proto_abbrev[psmouse_max_proto] : "any");
}
-int __init psmouse_init(void)
+static int __init psmouse_init(void)
{
- psmouse_parse_proto();
serio_register_driver(&psmouse_drv);
return 0;
}
-void __exit psmouse_exit(void)
+static void __exit psmouse_exit(void)
{
serio_unregister_driver(&psmouse_drv);
}
diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h
index 91c7da37bb70d..bda5b065d03c5 100644
--- a/drivers/input/mouse/psmouse.h
+++ b/drivers/input/mouse/psmouse.h
@@ -44,7 +44,7 @@ struct psmouse {
unsigned char pktcnt;
unsigned char pktsize;
unsigned char type;
- unsigned char model;
+ unsigned int model;
unsigned long last;
unsigned long out_of_sync;
enum psmouse_state state;
diff --git a/drivers/input/mouse/sermouse.c b/drivers/input/mouse/sermouse.c
index a69ffed179650..d12b93ae39007 100644
--- a/drivers/input/mouse/sermouse.c
+++ b/drivers/input/mouse/sermouse.c
@@ -209,7 +209,7 @@ static void sermouse_process_ms(struct sermouse *sermouse, signed char data, str
static irqreturn_t sermouse_interrupt(struct serio *serio,
unsigned char data, unsigned int flags, struct pt_regs *regs)
{
- struct sermouse *sermouse = serio->private;
+ struct sermouse *sermouse = serio_get_drvdata(serio);
if (time_after(jiffies, sermouse->last + HZ/10)) sermouse->count = 0;
sermouse->last = jiffies;
@@ -228,9 +228,11 @@ static irqreturn_t sermouse_interrupt(struct serio *serio,
static void sermouse_disconnect(struct serio *serio)
{
- struct sermouse *sermouse = serio->private;
+ struct sermouse *sermouse = serio_get_drvdata(serio);
+
input_unregister_device(&sermouse->dev);
serio_close(serio);
+ serio_set_drvdata(serio, NULL);
kfree(sermouse);
}
@@ -239,19 +241,17 @@ static void sermouse_disconnect(struct serio *serio)
* an unhandled serio port is found.
*/
-static void sermouse_connect(struct serio *serio, struct serio_driver *drv)
+static int sermouse_connect(struct serio *serio, struct serio_driver *drv)
{
struct sermouse *sermouse;
unsigned char c;
+ int err;
- if ((serio->type & SERIO_TYPE) != SERIO_RS232)
- return;
-
- if (!(serio->type & SERIO_PROTO) || ((serio->type & SERIO_PROTO) > SERIO_MZPP))
- return;
+ if (!serio->id.proto || serio->id.proto > SERIO_MZPP)
+ return -ENODEV;
if (!(sermouse = kmalloc(sizeof(struct sermouse), GFP_KERNEL)))
- return;
+ return -ENOMEM;
memset(sermouse, 0, sizeof(struct sermouse));
@@ -261,10 +261,8 @@ static void sermouse_connect(struct serio *serio, struct serio_driver *drv)
sermouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y);
sermouse->dev.private = sermouse;
- serio->private = sermouse;
-
- sermouse->type = serio->type & SERIO_PROTO;
- c = (serio->type & SERIO_EXTRA) >> 16;
+ sermouse->type = serio->id.proto;
+ c = serio->id.extra;
if (c & 0x01) set_bit(BTN_MIDDLE, sermouse->dev.keybit);
if (c & 0x02) set_bit(BTN_SIDE, sermouse->dev.keybit);
@@ -282,33 +280,88 @@ static void sermouse_connect(struct serio *serio, struct serio_driver *drv)
sermouse->dev.id.version = 0x0100;
sermouse->dev.dev = &serio->dev;
- if (serio_open(serio, drv)) {
+ serio_set_drvdata(serio, sermouse);
+
+ err = serio_open(serio, drv);
+ if (err) {
+ serio_set_drvdata(serio, NULL);
kfree(sermouse);
- return;
+ return err;
}
input_register_device(&sermouse->dev);
printk(KERN_INFO "input: %s on %s\n", sermouse_protocols[sermouse->type], serio->phys);
+
+ return 0;
}
+static struct serio_device_id sermouse_serio_ids[] = {
+ {
+ .type = SERIO_RS232,
+ .proto = SERIO_MSC,
+ .id = SERIO_ANY,
+ .extra = SERIO_ANY,
+ },
+ {
+ .type = SERIO_RS232,
+ .proto = SERIO_SUN,
+ .id = SERIO_ANY,
+ .extra = SERIO_ANY,
+ },
+ {
+ .type = SERIO_RS232,
+ .proto = SERIO_MS,
+ .id = SERIO_ANY,
+ .extra = SERIO_ANY,
+ },
+ {
+ .type = SERIO_RS232,
+ .proto = SERIO_MP,
+ .id = SERIO_ANY,
+ .extra = SERIO_ANY,
+ },
+ {
+ .type = SERIO_RS232,
+ .proto = SERIO_MZ,
+ .id = SERIO_ANY,
+ .extra = SERIO_ANY,
+ },
+ {
+ .type = SERIO_RS232,
+ .proto = SERIO_MZP,
+ .id = SERIO_ANY,
+ .extra = SERIO_ANY,
+ },
+ {
+ .type = SERIO_RS232,
+ .proto = SERIO_MZPP,
+ .id = SERIO_ANY,
+ .extra = SERIO_ANY,
+ },
+ { 0 }
+};
+
+MODULE_DEVICE_TABLE(serio, sermouse_serio_ids);
+
static struct serio_driver sermouse_drv = {
.driver = {
.name = "sermouse",
},
.description = DRIVER_DESC,
+ .id_table = sermouse_serio_ids,
.interrupt = sermouse_interrupt,
.connect = sermouse_connect,
.disconnect = sermouse_disconnect,
};
-int __init sermouse_init(void)
+static int __init sermouse_init(void)
{
serio_register_driver(&sermouse_drv);
return 0;
}
-void __exit sermouse_exit(void)
+static void __exit sermouse_exit(void)
{
serio_unregister_driver(&sermouse_drv);
}
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
index 3d41031185607..69832f8fb7202 100644
--- a/drivers/input/mouse/synaptics.c
+++ b/drivers/input/mouse/synaptics.c
@@ -229,7 +229,7 @@ static void synaptics_set_rate(struct psmouse *psmouse, unsigned int rate)
****************************************************************************/
static int synaptics_pt_write(struct serio *serio, unsigned char c)
{
- struct psmouse *parent = serio->parent->private;
+ struct psmouse *parent = serio_get_drvdata(serio->parent);
char rate_param = SYN_PS_CLIENT_CMD; /* indicates that we want pass-through port */
if (psmouse_sliced_command(parent, c))
@@ -246,7 +246,7 @@ static inline int synaptics_is_pt_packet(unsigned char *buf)
static void synaptics_pass_pt_packet(struct serio *ptport, unsigned char *packet)
{
- struct psmouse *child = ptport->private;
+ struct psmouse *child = serio_get_drvdata(ptport);
if (child && child->state == PSMOUSE_ACTIVATED) {
serio_interrupt(ptport, packet[1], 0, NULL);
@@ -260,7 +260,8 @@ static void synaptics_pass_pt_packet(struct serio *ptport, unsigned char *packet
static void synaptics_pt_activate(struct psmouse *psmouse)
{
- struct psmouse *child = psmouse->ps2dev.serio->child->private;
+ struct serio *ptport = psmouse->ps2dev.serio->child;
+ struct psmouse *child = serio_get_drvdata(ptport);
struct synaptics_data *priv = psmouse->private;
/* adjust the touchpad to child's choice of protocol */
@@ -287,7 +288,7 @@ static void synaptics_pt_create(struct psmouse *psmouse)
memset(serio, 0, sizeof(struct serio));
- serio->type = SERIO_PS_PSTHRU;
+ serio->id.type = SERIO_PS_PSTHRU;
strlcpy(serio->name, "Synaptics pass-through", sizeof(serio->name));
strlcpy(serio->phys, "synaptics-pt/serio0", sizeof(serio->name));
serio->write = synaptics_pt_write;
@@ -295,7 +296,8 @@ static void synaptics_pt_create(struct psmouse *psmouse)
psmouse->pt_activate = synaptics_pt_activate;
- psmouse->ps2dev.serio->child = serio;
+ printk(KERN_INFO "serio: %s port at %s\n", serio->name, psmouse->phys);
+ serio_register_port(serio);
}
/*****************************************************************************
@@ -322,8 +324,11 @@ static void synaptics_parse_hw_state(unsigned char buf[], struct synaptics_data
hw->left = (buf[0] & 0x01) ? 1 : 0;
hw->right = (buf[0] & 0x02) ? 1 : 0;
- if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities))
+ if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities)) {
hw->middle = ((buf[0] ^ buf[3]) & 0x01) ? 1 : 0;
+ if (hw->w == 2)
+ hw->scroll = (signed char)(buf[1]);
+ }
if (SYN_CAP_FOUR_BUTTON(priv->capabilities)) {
hw->up = ((buf[0] ^ buf[3]) & 0x01) ? 1 : 0;
@@ -379,6 +384,26 @@ static void synaptics_process_packet(struct psmouse *psmouse)
synaptics_parse_hw_state(psmouse->packet, priv, &hw);
+ if (hw.scroll) {
+ priv->scroll += hw.scroll;
+
+ while (priv->scroll >= 4) {
+ input_report_key(dev, BTN_BACK, !hw.down);
+ input_sync(dev);
+ input_report_key(dev, BTN_BACK, hw.down);
+ input_sync(dev);
+ priv->scroll -= 4;
+ }
+ while (priv->scroll <= -4) {
+ input_report_key(dev, BTN_FORWARD, !hw.up);
+ input_sync(dev);
+ input_report_key(dev, BTN_FORWARD, hw.up);
+ input_sync(dev);
+ priv->scroll += 4;
+ }
+ return;
+ }
+
if (hw.z > 0) {
num_fingers = 1;
finger_width = 5;
@@ -528,7 +553,8 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv)
if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities))
set_bit(BTN_MIDDLE, dev->keybit);
- if (SYN_CAP_FOUR_BUTTON(priv->capabilities)) {
+ if (SYN_CAP_FOUR_BUTTON(priv->capabilities) ||
+ SYN_CAP_MIDDLE_BUTTON(priv->capabilities)) {
set_bit(BTN_FORWARD, dev->keybit);
set_bit(BTN_BACK, dev->keybit);
}
@@ -551,6 +577,7 @@ static void synaptics_disconnect(struct psmouse *psmouse)
{
synaptics_reset(psmouse);
kfree(psmouse->private);
+ psmouse->private = NULL;
}
static int synaptics_reconnect(struct psmouse *psmouse)
@@ -604,6 +631,20 @@ int synaptics_detect(struct psmouse *psmouse, int set_properties)
return 0;
}
+#if defined(__i386__)
+#include <linux/dmi.h>
+static struct dmi_system_id toshiba_dmi_table[] = {
+ {
+ .ident = "Toshiba Satellite",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+ DMI_MATCH(DMI_PRODUCT_NAME , "Satellite"),
+ },
+ },
+ { }
+};
+#endif
+
int synaptics_init(struct psmouse *psmouse)
{
struct synaptics_data *priv;
@@ -625,9 +666,6 @@ int synaptics_init(struct psmouse *psmouse)
priv->pkt_type = SYN_MODEL_NEWABS(priv->model_id) ? SYN_NEWABS : SYN_OLDABS;
- if (SYN_CAP_PASS_THROUGH(priv->capabilities))
- synaptics_pt_create(psmouse);
-
print_ident(priv);
set_input_params(&psmouse->dev, priv);
@@ -637,6 +675,21 @@ int synaptics_init(struct psmouse *psmouse)
psmouse->reconnect = synaptics_reconnect;
psmouse->pktsize = 6;
+ if (SYN_CAP_PASS_THROUGH(priv->capabilities))
+ synaptics_pt_create(psmouse);
+
+#if defined(__i386__)
+ /*
+ * Toshiba's KBC seems to have trouble handling data from
+ * Synaptics as full rate, switch to lower rate which is roughly
+ * thye same as rate of standard PS/2 mouse.
+ */
+ if (psmouse->rate >= 80 && dmi_check_system(toshiba_dmi_table)) {
+ printk(KERN_INFO "synaptics: Toshiba Satellite detected, limiting rate to 40pps.\n");
+ psmouse->rate = 40;
+ }
+#endif
+
return 0;
init_fail:
diff --git a/drivers/input/mouse/synaptics.h b/drivers/input/mouse/synaptics.h
index 3df65bbcf2598..68fff1dcd7de6 100644
--- a/drivers/input/mouse/synaptics.h
+++ b/drivers/input/mouse/synaptics.h
@@ -92,6 +92,7 @@ struct synaptics_hw_state {
unsigned int up:1;
unsigned int down:1;
unsigned char ext_buttons;
+ signed char scroll;
};
struct synaptics_data {
@@ -103,6 +104,7 @@ struct synaptics_data {
unsigned char pkt_type; /* packet type - old, new, etc */
unsigned char mode; /* current mode byte */
+ int scroll;
};
#endif /* _SYNAPTICS_H */
diff --git a/drivers/input/mouse/vsxxxaa.c b/drivers/input/mouse/vsxxxaa.c
index a14b76e490533..b2cb101c8110b 100644
--- a/drivers/input/mouse/vsxxxaa.c
+++ b/drivers/input/mouse/vsxxxaa.c
@@ -470,7 +470,7 @@ static irqreturn_t
vsxxxaa_interrupt (struct serio *serio, unsigned char data, unsigned int flags,
struct pt_regs *regs)
{
- struct vsxxxaa *mouse = serio->private;
+ struct vsxxxaa *mouse = serio_get_drvdata (serio);
vsxxxaa_queue_byte (mouse, data);
vsxxxaa_parse_buffer (mouse, regs);
@@ -481,25 +481,22 @@ vsxxxaa_interrupt (struct serio *serio, unsigned char data, unsigned int flags,
static void
vsxxxaa_disconnect (struct serio *serio)
{
- struct vsxxxaa *mouse = serio->private;
+ struct vsxxxaa *mouse = serio_get_drvdata (serio);
input_unregister_device (&mouse->dev);
serio_close (serio);
+ serio_set_drvdata (serio, NULL);
kfree (mouse);
}
-static void
+static int
vsxxxaa_connect (struct serio *serio, struct serio_driver *drv)
{
struct vsxxxaa *mouse;
-
- if ((serio->type & SERIO_TYPE) != SERIO_RS232)
- return;
- if ((serio->type & SERIO_PROTO) != SERIO_VSXXXAA)
- return;
+ int err;
if (!(mouse = kmalloc (sizeof (struct vsxxxaa), GFP_KERNEL)))
- return;
+ return -ENOMEM;
memset (mouse, 0, sizeof (struct vsxxxaa));
@@ -522,7 +519,6 @@ vsxxxaa_connect (struct serio *serio, struct serio_driver *drv)
mouse->dev.absmax[ABS_Y] = 1023;
mouse->dev.private = mouse;
- serio->private = mouse;
sprintf (mouse->name, "DEC VSXXX-AA/-GA mouse or VSXXX-AB digitizer");
sprintf (mouse->phys, "%s/input0", serio->phys);
@@ -532,9 +528,13 @@ vsxxxaa_connect (struct serio *serio, struct serio_driver *drv)
mouse->dev.dev = &serio->dev;
mouse->serio = serio;
- if (serio_open (serio, drv)) {
+ serio_set_drvdata (serio, mouse);
+
+ err = serio_open (serio, drv);
+ if (err) {
+ serio_set_drvdata (serio, NULL);
kfree (mouse);
- return;
+ return err;
}
/*
@@ -546,26 +546,41 @@ vsxxxaa_connect (struct serio *serio, struct serio_driver *drv)
input_register_device (&mouse->dev);
printk (KERN_INFO "input: %s on %s\n", mouse->name, mouse->phys);
+
+ return 0;
}
+static struct serio_device_id vsxxaa_serio_ids[] = {
+ {
+ .type = SERIO_RS232,
+ .proto = SERIO_VSXXXAA,
+ .id = SERIO_ANY,
+ .extra = SERIO_ANY,
+ },
+ { 0 }
+};
+
+MODULE_DEVICE_TABLE(serio, vsxxaa_serio_ids);
+
static struct serio_driver vsxxxaa_drv = {
.driver = {
.name = "vsxxxaa",
},
.description = DRIVER_DESC,
+ .id_table = vsxxaa_serio_ids,
.connect = vsxxxaa_connect,
.interrupt = vsxxxaa_interrupt,
.disconnect = vsxxxaa_disconnect,
};
-int __init
+static int __init
vsxxxaa_init (void)
{
serio_register_driver(&vsxxxaa_drv);
return 0;
}
-void __exit
+static void __exit
vsxxxaa_exit (void)
{
serio_unregister_driver(&vsxxxaa_drv);
diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c
index 28ffa54d59885..564974ce57935 100644
--- a/drivers/input/mousedev.c
+++ b/drivers/input/mousedev.c
@@ -71,6 +71,7 @@ struct mousedev {
struct mousedev_hw_data packet;
unsigned int pkt_count;
int old_x[4], old_y[4];
+ int frac_dx, frac_dy;
unsigned long touch;
};
@@ -117,24 +118,31 @@ static struct mousedev mousedev_mix;
static void mousedev_touchpad_event(struct input_dev *dev, struct mousedev *mousedev, unsigned int code, int value)
{
- int size;
+ int size, tmp;
+ enum { FRACTION_DENOM = 128 };
if (mousedev->touch) {
+ size = dev->absmax[ABS_X] - dev->absmin[ABS_X];
+ if (size == 0) size = 256 * 2;
switch (code) {
case ABS_X:
- size = dev->absmax[ABS_X] - dev->absmin[ABS_X];
- if (size == 0) size = xres;
fx(0) = value;
- if (mousedev->pkt_count >= 2)
- mousedev->packet.dx = ((fx(0) - fx(1)) / 2 + (fx(1) - fx(2)) / 2) * xres / (size * 2);
+ if (mousedev->pkt_count >= 2) {
+ tmp = ((value - fx(2)) * (256 * FRACTION_DENOM)) / size;
+ tmp += mousedev->frac_dx;
+ mousedev->packet.dx = tmp / FRACTION_DENOM;
+ mousedev->frac_dx = tmp - mousedev->packet.dx * FRACTION_DENOM;
+ }
break;
case ABS_Y:
- size = dev->absmax[ABS_Y] - dev->absmin[ABS_Y];
- if (size == 0) size = yres;
fy(0) = value;
- if (mousedev->pkt_count >= 2)
- mousedev->packet.dy = -((fy(0) - fy(1)) / 2 + (fy(1) - fy(2)) / 2) * yres / (size * 2);
+ if (mousedev->pkt_count >= 2) {
+ tmp = -((value - fy(2)) * (256 * FRACTION_DENOM)) / size;
+ tmp += mousedev->frac_dy;
+ mousedev->packet.dy = tmp / FRACTION_DENOM;
+ mousedev->frac_dy = tmp - mousedev->packet.dy * FRACTION_DENOM;
+ }
break;
}
}
@@ -268,6 +276,8 @@ static void mousedev_touchpad_touch(struct mousedev *mousedev, int value)
clear_bit(0, &mousedev_mix.packet.buttons);
}
mousedev->touch = mousedev->pkt_count = 0;
+ mousedev->frac_dx = 0;
+ mousedev->frac_dy = 0;
}
else
if (!mousedev->touch)
@@ -445,7 +455,7 @@ static void mousedev_packet(struct mousedev_list *list, signed char *ps2_data)
switch (list->mode) {
case MOUSEDEV_EMUL_EXPS:
- ps2_data[3] = mousedev_limit_delta(p->dz, 127);
+ ps2_data[3] = mousedev_limit_delta(p->dz, 7);
p->dz -= ps2_data[3];
ps2_data[3] = (ps2_data[3] & 0x0f) | ((p->buttons & 0x18) << 1);
list->bufsiz = 4;
@@ -585,12 +595,11 @@ static unsigned int mousedev_poll(struct file *file, poll_table *wait)
{
struct mousedev_list *list = file->private_data;
poll_wait(file, &list->mousedev->wait, wait);
- if (list->ready || list->buffer)
- return POLLIN | POLLRDNORM;
- return 0;
+ return ((list->ready || list->buffer) ? (POLLIN | POLLRDNORM) : 0) |
+ (list->mousedev->exist ? 0 : (POLLHUP | POLLERR));
}
-struct file_operations mousedev_fops = {
+static struct file_operations mousedev_fops = {
.owner = THIS_MODULE,
.read = mousedev_read,
.write = mousedev_write,
@@ -643,6 +652,7 @@ static struct input_handle *mousedev_connect(struct input_handler *handler, stru
static void mousedev_disconnect(struct input_handle *handle)
{
struct mousedev *mousedev = handle->private;
+ struct mousedev_list *list;
class_simple_device_remove(MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + mousedev->minor));
devfs_remove("input/mouse%d", mousedev->minor);
@@ -650,6 +660,9 @@ static void mousedev_disconnect(struct input_handle *handle)
if (mousedev->open) {
input_close_device(handle);
+ wake_up_interruptible(&mousedev->wait);
+ list_for_each_entry(list, &mousedev->list, node)
+ kill_fasync(&list->fasync, SIGIO, POLL_HUP);
} else {
if (mousedev_mix.open)
input_close_device(handle);
diff --git a/drivers/input/power.c b/drivers/input/power.c
index f7469b55e1cad..bfc5c63ebffe2 100644
--- a/drivers/input/power.c
+++ b/drivers/input/power.c
@@ -58,8 +58,6 @@ static void power_event(struct input_handle *handle, unsigned int type,
printk("Entering power_event\n");
- if (type != EV_KEY || type != EV_PWR) return;
-
if (type == EV_PWR) {
switch (code) {
case KEY_SUSPEND:
@@ -76,7 +74,9 @@ static void power_event(struct input_handle *handle, unsigned int type,
default:
return;
}
- } else {
+ }
+
+ if (type == EV_KEY) {
switch (code) {
case KEY_SUSPEND:
printk("Powering down input device\n");
@@ -103,12 +103,6 @@ static struct input_handle *power_connect(struct input_handler *handler,
{
struct input_handle *handle;
- if (!test_bit(EV_KEY, dev->evbit) || !test_bit(EV_PWR, dev->evbit))
- return NULL;
-
- if (!test_bit(KEY_SUSPEND, dev->keybit) || (!test_bit(KEY_POWER, dev->keybit)))
- return NULL;
-
if (!(handle = kmalloc(sizeof(struct input_handle), GFP_KERNEL)))
return NULL;
memset(handle, 0, sizeof(struct input_handle));
diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig
index 6826783fdab54..b3710733b36b1 100644
--- a/drivers/input/serio/Kconfig
+++ b/drivers/input/serio/Kconfig
@@ -2,11 +2,11 @@
# Input core configuration
#
config SERIO
- tristate "Serial i/o support" if EMBEDDED || !X86
+ tristate "Serial I/O support" if EMBEDDED || !X86
default y
---help---
Say Yes here if you have any input device that uses serial I/O to
- communicate with the system. This includes the
+ communicate with the system. This includes the
* standard AT keyboard and PS/2 mouse *
as well as serial mice, Sun keyboards, some joysticks and 6dof
devices and more.
@@ -16,10 +16,11 @@ config SERIO
To compile this driver as a module, choose M here: the
module will be called serio.
+if SERIO
+
config SERIO_I8042
tristate "i8042 PC Keyboard controller" if EMBEDDED || !X86
default y
- select SERIO
depends on !PARISC && (!ARM || ARCH_SHARK || FOOTBRIDGE_HOST) && !M68K
---help---
i8042 is the chip over which the standard AT keyboard and PS/2
@@ -34,7 +35,6 @@ config SERIO_I8042
config SERIO_SERPORT
tristate "Serial port line discipline"
default y
- depends on SERIO
---help---
Say Y here if you plan to use an input device (mouse, joystick,
tablet, 6dof) that communicates over the RS232 serial (COM) port.
@@ -48,8 +48,7 @@ config SERIO_SERPORT
config SERIO_CT82C710
tristate "ct82c710 Aux port controller"
- depends on SERIO
- depends on !PARISC
+ depends on X86
---help---
Say Y here if you have a Texas Instruments TravelMate notebook
equipped with the ct82c710 chip and want to use a mouse connected
@@ -62,11 +61,11 @@ config SERIO_CT82C710
config SERIO_Q40KBD
tristate "Q40 keyboard controller"
- depends on Q40 && SERIO
+ depends on Q40
config SERIO_PARKBD
tristate "Parallel port keyboard adapter"
- depends on SERIO && PARPORT
+ depends on PARPORT
---help---
Say Y here if you built a simple parallel port adapter to attach
an additional AT keyboard, XT keyboard or PS/2 mouse.
@@ -80,7 +79,7 @@ config SERIO_PARKBD
config SERIO_RPCKBD
tristate "Acorn RiscPC keyboard controller"
- depends on (ARCH_ACORN || ARCH_CLPS7500) && SERIO
+ depends on ARCH_ACORN || ARCH_CLPS7500
default y
help
Say Y here if you have the Acorn RiscPC and want to use an AT
@@ -91,15 +90,15 @@ config SERIO_RPCKBD
config SERIO_AMBAKMI
tristate "AMBA KMI keyboard controller"
- depends on ARM_AMBA && SERIO
+ depends on ARM_AMBA
config SERIO_SA1111
tristate "Intel SA1111 keyboard controller"
- depends on SA1111 && SERIO
+ depends on SA1111
config SERIO_GSCPS2
tristate "HP GSC PS/2 keyboard and PS/2 mouse controller"
- depends on GSC && SERIO
+ depends on GSC
default y
help
This driver provides support for the PS/2 ports on PA-RISC machines
@@ -111,9 +110,35 @@ config SERIO_GSCPS2
To compile this driver as a module, choose M here: the
module will be called gscps2.
+config HP_SDC
+ tristate "HP System Device Controller i8042 Support"
+ depends on GSC && SERIO
+ default y
+ ---help---
+ This option enables supports for the the "System Device
+ Controller", an i8042 carrying microcode to manage a
+ few miscellanous devices on some Hewlett Packard systems.
+ The SDC itself contains a 10ms resolution timer/clock capable
+ of delivering interrupts on a periodic and one-shot basis.
+ The SDC may also be connected to a battery-backed real-time
+ clock, a basic audio waveform generator, and an HP-HIL Master
+ Link Controller serving up to seven input devices.
+
+ By itself this option is rather useless, but enabling it will
+ enable selection of drivers for the abovementioned devices.
+ It is, however, incompatible with the old, reliable HIL keyboard
+ driver, and the new HIL driver is experimental, so if you plan
+ to use a HIL keyboard as your primary keyboard, you may wish
+ to keep using that driver until the new HIL drivers have had
+ more testing.
+
+config HIL_MLC
+ tristate "HIL MLC Support (needed for HIL input devices)"
+ depends on HP_SDC
+
config SERIO_PCIPS2
tristate "PCI PS/2 keyboard and PS/2 mouse controller"
- depends on PCI && SERIO
+ depends on PCI
help
Say Y here if you have a Mobility Docking station with PS/2
keyboard and mice ports.
@@ -123,7 +148,7 @@ config SERIO_PCIPS2
config SERIO_MACEPS2
tristate "SGI O2 MACE PS/2 controller"
- depends on SGI_IP32 && SERIO
+ depends on SGI_IP32
help
Say Y here if you have SGI O2 workstation and want to use its
PS/2 ports.
@@ -133,7 +158,6 @@ config SERIO_MACEPS2
config SERIO_LIBPS2
tristate "PS/2 driver library" if EMBEDDED
- depends on SERIO
help
Say Y here if you are using a driver for device connected
to a PS/2 port, such as PS/2 mouse or standard AT keyboard.
@@ -143,7 +167,6 @@ config SERIO_LIBPS2
config SERIO_RAW
tristate "Raw access to serio ports"
- depends on SERIO
help
Say Y here if you want to have raw access to serio ports, such as
AUX ports on i8042 keyboard controller. Each serio port that is
@@ -156,3 +179,5 @@ config SERIO_RAW
To compile this driver as a module, choose M here: the
module will be called serio_raw.
+
+endif
diff --git a/drivers/input/serio/Makefile b/drivers/input/serio/Makefile
index 45b42d5020e73..678a8599f9ffb 100644
--- a/drivers/input/serio/Makefile
+++ b/drivers/input/serio/Makefile
@@ -15,6 +15,8 @@ obj-$(CONFIG_SERIO_AMBAKMI) += ambakmi.o
obj-$(CONFIG_SERIO_Q40KBD) += q40kbd.o
obj-$(CONFIG_SERIO_98KBD) += 98kbd-io.o
obj-$(CONFIG_SERIO_GSCPS2) += gscps2.o
+obj-$(CONFIG_HP_SDC) += hp_sdc.o
+obj-$(CONFIG_HIL_MLC) += hp_sdc_mlc.o hil_mlc.o
obj-$(CONFIG_SERIO_PCIPS2) += pcips2.o
obj-$(CONFIG_SERIO_MACEPS2) += maceps2.o
obj-$(CONFIG_SERIO_LIBPS2) += libps2.o
diff --git a/drivers/input/serio/ambakmi.c b/drivers/input/serio/ambakmi.c
index 23ce7dc77c51d..9b1ab5e7a98d1 100644
--- a/drivers/input/serio/ambakmi.c
+++ b/drivers/input/serio/ambakmi.c
@@ -134,7 +134,7 @@ static int amba_kmi_probe(struct amba_device *dev, void *id)
memset(kmi, 0, sizeof(struct amba_kmi_port));
memset(io, 0, sizeof(struct serio));
- io->type = SERIO_8042;
+ io->id.type = SERIO_8042;
io->write = amba_kmi_write;
io->open = amba_kmi_open;
io->close = amba_kmi_close;
diff --git a/drivers/input/serio/ct82c710.c b/drivers/input/serio/ct82c710.c
index ee785460b78fa..dd0f5bd902413 100644
--- a/drivers/input/serio/ct82c710.c
+++ b/drivers/input/serio/ct82c710.c
@@ -181,7 +181,7 @@ static struct serio * __init ct82c710_allocate_port(void)
serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
if (serio) {
memset(serio, 0, sizeof(struct serio));
- serio->type = SERIO_8042;
+ serio->id.type = SERIO_8042;
serio->open = ct82c710_open;
serio->close = ct82c710_close;
serio->write = ct82c710_write;
@@ -193,7 +193,7 @@ static struct serio * __init ct82c710_allocate_port(void)
return serio;
}
-int __init ct82c710_init(void)
+static int __init ct82c710_init(void)
{
if (ct82c710_probe())
return -ENODEV;
@@ -215,7 +215,7 @@ int __init ct82c710_init(void)
return 0;
}
-void __exit ct82c710_exit(void)
+static void __exit ct82c710_exit(void)
{
serio_unregister_port(ct82c710_port);
platform_device_unregister(ct82c710_device);
diff --git a/drivers/input/serio/gscps2.c b/drivers/input/serio/gscps2.c
index 401d750116d58..897e4c12b6427 100644
--- a/drivers/input/serio/gscps2.c
+++ b/drivers/input/serio/gscps2.c
@@ -3,7 +3,7 @@
*
* Copyright (c) 2004 Helge Deller <deller@gmx.de>
* Copyright (c) 2002 Laurent Canet <canetl@esiee.fr>
- * Copyright (c) 2002 Thibaut Varene <varenet@esiee.fr>
+ * Copyright (c) 2002 Thibaut Varene <varenet@parisc-linux.org>
*
* Pieces of code based on linux-2.4's hp_mouse.c & hp_keyb.c
* Copyright (c) 1999 Alex deVries <alex@onefishtwo.ca>
@@ -37,8 +37,8 @@
#include <asm/io.h>
#include <asm/parisc-device.h>
-MODULE_AUTHOR("Laurent Canet <canetl@esiee.fr>, Thibaut Varene <varenet@esiee.fr>, Helge Deller <deller@gmx.de>");
-MODULE_DESCRIPTION("HP GSC PS/2 port driver");
+MODULE_AUTHOR("Laurent Canet <canetl@esiee.fr>, Thibaut Varene <varenet@parisc-linux.org>, Helge Deller <deller@gmx.de>");
+MODULE_DESCRIPTION("HP GSC PS2 port driver");
MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE(parisc, gscps2_device_tbl);
@@ -363,11 +363,7 @@ static int __init gscps2_probe(struct parisc_device *dev)
snprintf(serio->name, sizeof(serio->name), "GSC PS/2 %s",
(ps2port->id == GSC_ID_KEYBOARD) ? "keyboard" : "mouse");
strlcpy(serio->phys, dev->dev.bus_id, sizeof(serio->phys));
- serio->idbus = BUS_GSC;
- serio->idvendor = PCI_VENDOR_ID_HP;
- serio->idproduct = 0x0001;
- serio->idversion = 0x0010;
- serio->type = SERIO_8042;
+ serio->id.type = SERIO_8042;
serio->write = gscps2_write;
serio->open = gscps2_open;
serio->close = gscps2_close;
@@ -448,7 +444,7 @@ static struct parisc_device_id gscps2_device_tbl[] = {
};
static struct parisc_driver parisc_ps2_driver = {
- .name = "GSC PS/2",
+ .name = "GSC PS2",
.id_table = gscps2_device_tbl,
.probe = gscps2_probe,
.remove = gscps2_remove,
diff --git a/drivers/input/serio/hil_mlc.c b/drivers/input/serio/hil_mlc.c
new file mode 100644
index 0000000000000..c243cb6fdfc4a
--- /dev/null
+++ b/drivers/input/serio/hil_mlc.c
@@ -0,0 +1,949 @@
+/*
+ * HIL MLC state machine and serio interface driver
+ *
+ * Copyright (c) 2001 Brian S. Julin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. The name of the author may not 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").
+ *
+ * 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
+ *
+ * References:
+ * HP-HIL Technical Reference Manual. Hewlett Packard Product No. 45918A
+ *
+ *
+ * Driver theory of operation:
+ *
+ * Some access methods and an ISR is defined by the sub-driver
+ * (e.g. hp_sdc_mlc.c). These methods are expected to provide a
+ * few bits of logic in addition to raw access to the HIL MLC,
+ * specifically, the ISR, which is entirely registered by the
+ * sub-driver and invoked directly, must check for record
+ * termination or packet match, at which point a semaphore must
+ * be cleared and then the hil_mlcs_tasklet must be scheduled.
+ *
+ * The hil_mlcs_tasklet processes the state machine for all MLCs
+ * each time it runs, checking each MLC's progress at the current
+ * node in the state machine, and moving the MLC to subsequent nodes
+ * in the state machine when appropriate. It will reschedule
+ * itself if output is pending. (This rescheduling should be replaced
+ * at some point with a sub-driver-specific mechanism.)
+ *
+ * A timer task prods the tasklet once per second to prevent
+ * hangups when attached devices do not return expected data
+ * and to initiate probes of the loop for new devices.
+ */
+
+#include <linux/hil_mlc.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/timer.h>
+#include <linux/sched.h>
+#include <linux/list.h>
+
+MODULE_AUTHOR("Brian S. Julin <bri@calyx.com>");
+MODULE_DESCRIPTION("HIL MLC serio");
+MODULE_LICENSE("Dual BSD/GPL");
+
+EXPORT_SYMBOL(hil_mlc_register);
+EXPORT_SYMBOL(hil_mlc_unregister);
+
+#define PREFIX "HIL MLC: "
+
+static LIST_HEAD(hil_mlcs);
+static DEFINE_RWLOCK(hil_mlcs_lock);
+static struct timer_list hil_mlcs_kicker;
+static int hil_mlcs_probe;
+
+static void hil_mlcs_process(unsigned long unused);
+DECLARE_TASKLET_DISABLED(hil_mlcs_tasklet, hil_mlcs_process, 0);
+
+
+/* #define HIL_MLC_DEBUG */
+
+/********************** Device info/instance management **********************/
+
+static void hil_mlc_clear_di_map (hil_mlc *mlc, int val) {
+ int j;
+ for (j = val; j < 7 ; j++) {
+ mlc->di_map[j] = -1;
+ }
+}
+
+static void hil_mlc_clear_di_scratch (hil_mlc *mlc) {
+ memset(&(mlc->di_scratch), 0, sizeof(mlc->di_scratch));
+}
+
+static void hil_mlc_copy_di_scratch (hil_mlc *mlc, int idx) {
+ memcpy(&(mlc->di[idx]), &(mlc->di_scratch), sizeof(mlc->di_scratch));
+}
+
+static int hil_mlc_match_di_scratch (hil_mlc *mlc) {
+ int idx;
+
+ for (idx = 0; idx < HIL_MLC_DEVMEM; idx++) {
+ int j, found;
+
+ /* In-use slots are not eligible. */
+ found = 0;
+ for (j = 0; j < 7 ; j++) {
+ if (mlc->di_map[j] == idx) found++;
+ }
+ if (found) continue;
+ if (!memcmp(mlc->di + idx,
+ &(mlc->di_scratch),
+ sizeof(mlc->di_scratch))) break;
+ }
+ return((idx >= HIL_MLC_DEVMEM) ? -1 : idx);
+}
+
+static int hil_mlc_find_free_di(hil_mlc *mlc) {
+ int idx;
+ /* TODO: Pick all-zero slots first, failing that,
+ * randomize the slot picked among those eligible.
+ */
+ for (idx = 0; idx < HIL_MLC_DEVMEM; idx++) {
+ int j, found;
+ found = 0;
+ for (j = 0; j < 7 ; j++) {
+ if (mlc->di_map[j] == idx) found++;
+ }
+ if (!found) break;
+ }
+ return(idx); /* Note: It is guaranteed at least one above will match */
+}
+
+static inline void hil_mlc_clean_serio_map(hil_mlc *mlc) {
+ int idx;
+ for (idx = 0; idx < HIL_MLC_DEVMEM; idx++) {
+ int j, found;
+ found = 0;
+ for (j = 0; j < 7 ; j++) {
+ if (mlc->di_map[j] == idx) found++;
+ }
+ if (!found) mlc->serio_map[idx].di_revmap = -1;
+ }
+}
+
+static void hil_mlc_send_polls(hil_mlc *mlc) {
+ int did, i, cnt;
+ struct serio *serio;
+ struct serio_driver *drv;
+
+ i = cnt = 0;
+ did = (mlc->ipacket[0] & HIL_PKT_ADDR_MASK) >> 8;
+ serio = did ? mlc->serio[mlc->di_map[did - 1]] : NULL;
+ drv = (serio != NULL) ? serio->drv : NULL;
+
+ while (mlc->icount < 15 - i) {
+ hil_packet p;
+ p = mlc->ipacket[i];
+ if (did != (p & HIL_PKT_ADDR_MASK) >> 8) {
+ if (drv == NULL || drv->interrupt == NULL) goto skip;
+
+ drv->interrupt(serio, 0, 0, NULL);
+ drv->interrupt(serio, HIL_ERR_INT >> 16, 0, NULL);
+ drv->interrupt(serio, HIL_PKT_CMD >> 8, 0, NULL);
+ drv->interrupt(serio, HIL_CMD_POL + cnt, 0, NULL);
+ skip:
+ did = (p & HIL_PKT_ADDR_MASK) >> 8;
+ serio = did ? mlc->serio[mlc->di_map[did-1]] : NULL;
+ drv = (serio != NULL) ? serio->drv : NULL;
+ cnt = 0;
+ }
+ cnt++; i++;
+ if (drv == NULL || drv->interrupt == NULL) continue;
+ drv->interrupt(serio, (p >> 24), 0, NULL);
+ drv->interrupt(serio, (p >> 16) & 0xff, 0, NULL);
+ drv->interrupt(serio, (p >> 8) & ~HIL_PKT_ADDR_MASK, 0, NULL);
+ drv->interrupt(serio, p & 0xff, 0, NULL);
+ }
+}
+
+/*************************** State engine *********************************/
+
+#define HILSEN_SCHED 0x000100 /* Schedule the tasklet */
+#define HILSEN_BREAK 0x000200 /* Wait until next pass */
+#define HILSEN_UP 0x000400 /* relative node#, decrement */
+#define HILSEN_DOWN 0x000800 /* relative node#, increment */
+#define HILSEN_FOLLOW 0x001000 /* use retval as next node# */
+
+#define HILSEN_MASK 0x0000ff
+#define HILSEN_START 0
+#define HILSEN_RESTART 1
+#define HILSEN_DHR 9
+#define HILSEN_DHR2 10
+#define HILSEN_IFC 14
+#define HILSEN_HEAL0 16
+#define HILSEN_HEAL 18
+#define HILSEN_ACF 21
+#define HILSEN_ACF2 22
+#define HILSEN_DISC0 25
+#define HILSEN_DISC 27
+#define HILSEN_MATCH 40
+#define HILSEN_OPERATE 41
+#define HILSEN_PROBE 44
+#define HILSEN_DSR 52
+#define HILSEN_REPOLL 55
+#define HILSEN_IFCACF 58
+#define HILSEN_END 60
+
+#define HILSEN_NEXT (HILSEN_DOWN | 1)
+#define HILSEN_SAME (HILSEN_DOWN | 0)
+#define HILSEN_LAST (HILSEN_UP | 1)
+
+#define HILSEN_DOZE (HILSEN_SAME | HILSEN_SCHED | HILSEN_BREAK)
+#define HILSEN_SLEEP (HILSEN_SAME | HILSEN_BREAK)
+
+static int hilse_match(hil_mlc *mlc, int unused) {
+ int rc;
+ rc = hil_mlc_match_di_scratch(mlc);
+ if (rc == -1) {
+ rc = hil_mlc_find_free_di(mlc);
+ if (rc == -1) goto err;
+#ifdef HIL_MLC_DEBUG
+ printk(KERN_DEBUG PREFIX "new in slot %i\n", rc);
+#endif
+ hil_mlc_copy_di_scratch(mlc, rc);
+ mlc->di_map[mlc->ddi] = rc;
+ mlc->serio_map[rc].di_revmap = mlc->ddi;
+ hil_mlc_clean_serio_map(mlc);
+ serio_rescan(mlc->serio[rc]);
+ return -1;
+ }
+ mlc->di_map[mlc->ddi] = rc;
+#ifdef HIL_MLC_DEBUG
+ printk(KERN_DEBUG PREFIX "same in slot %i\n", rc);
+#endif
+ mlc->serio_map[rc].di_revmap = mlc->ddi;
+ hil_mlc_clean_serio_map(mlc);
+ return 0;
+ err:
+ printk(KERN_ERR PREFIX "Residual device slots exhausted, close some serios!\n");
+ return 1;
+}
+
+/* An LCV used to prevent runaway loops, forces 5 second sleep when reset. */
+static int hilse_init_lcv(hil_mlc *mlc, int unused) {
+ struct timeval tv;
+
+ do_gettimeofday(&tv);
+
+ if(mlc->lcv == 0) goto restart; /* First init, no need to dally */
+ if(tv.tv_sec - mlc->lcv_tv.tv_sec < 5) return -1;
+ restart:
+ mlc->lcv_tv = tv;
+ mlc->lcv = 0;
+ return 0;
+}
+
+static int hilse_inc_lcv(hil_mlc *mlc, int lim) {
+ if (mlc->lcv++ >= lim) return -1;
+ return 0;
+}
+
+#if 0
+static int hilse_set_lcv(hil_mlc *mlc, int val) {
+ mlc->lcv = val;
+ return 0;
+}
+#endif
+
+/* Management of the discovered device index (zero based, -1 means no devs) */
+static int hilse_set_ddi(hil_mlc *mlc, int val) {
+ mlc->ddi = val;
+ hil_mlc_clear_di_map(mlc, val + 1);
+ return 0;
+}
+
+static int hilse_dec_ddi(hil_mlc *mlc, int unused) {
+ mlc->ddi--;
+ if (mlc->ddi <= -1) {
+ mlc->ddi = -1;
+ hil_mlc_clear_di_map(mlc, 0);
+ return -1;
+ }
+ hil_mlc_clear_di_map(mlc, mlc->ddi + 1);
+ return 0;
+}
+
+static int hilse_inc_ddi(hil_mlc *mlc, int unused) {
+ if (mlc->ddi >= 6) {
+ BUG();
+ return -1;
+ }
+ mlc->ddi++;
+ return 0;
+}
+
+static int hilse_take_idd(hil_mlc *mlc, int unused) {
+ int i;
+
+ /* Help the state engine:
+ * Is this a real IDD response or just an echo?
+ *
+ * Real IDD response does not start with a command.
+ */
+ if (mlc->ipacket[0] & HIL_PKT_CMD) goto bail;
+ /* Should have the command echoed further down. */
+ for (i = 1; i < 16; i++) {
+ if (((mlc->ipacket[i] & HIL_PKT_ADDR_MASK) ==
+ (mlc->ipacket[0] & HIL_PKT_ADDR_MASK)) &&
+ (mlc->ipacket[i] & HIL_PKT_CMD) &&
+ ((mlc->ipacket[i] & HIL_PKT_DATA_MASK) == HIL_CMD_IDD))
+ break;
+ }
+ if (i > 15) goto bail;
+ /* And the rest of the packets should still be clear. */
+ while (++i < 16) {
+ if (mlc->ipacket[i]) break;
+ }
+ if (i < 16) goto bail;
+ for (i = 0; i < 16; i++) {
+ mlc->di_scratch.idd[i] =
+ mlc->ipacket[i] & HIL_PKT_DATA_MASK;
+ }
+ /* Next step is to see if RSC supported */
+ if (mlc->di_scratch.idd[1] & HIL_IDD_HEADER_RSC)
+ return HILSEN_NEXT;
+ if (mlc->di_scratch.idd[1] & HIL_IDD_HEADER_EXD)
+ return HILSEN_DOWN | 4;
+ return 0;
+ bail:
+ mlc->ddi--;
+ return -1; /* This should send us off to ACF */
+}
+
+static int hilse_take_rsc(hil_mlc *mlc, int unused) {
+ int i;
+
+ for (i = 0; i < 16; i++) {
+ mlc->di_scratch.rsc[i] =
+ mlc->ipacket[i] & HIL_PKT_DATA_MASK;
+ }
+ /* Next step is to see if EXD supported (IDD has already been read) */
+ if (mlc->di_scratch.idd[1] & HIL_IDD_HEADER_EXD)
+ return HILSEN_NEXT;
+ return 0;
+}
+
+static int hilse_take_exd(hil_mlc *mlc, int unused) {
+ int i;
+
+ for (i = 0; i < 16; i++) {
+ mlc->di_scratch.exd[i] =
+ mlc->ipacket[i] & HIL_PKT_DATA_MASK;
+ }
+ /* Next step is to see if RNM supported. */
+ if (mlc->di_scratch.exd[0] & HIL_EXD_HEADER_RNM)
+ return HILSEN_NEXT;
+ return 0;
+}
+
+static int hilse_take_rnm(hil_mlc *mlc, int unused) {
+ int i;
+
+ for (i = 0; i < 16; i++) {
+ mlc->di_scratch.rnm[i] =
+ mlc->ipacket[i] & HIL_PKT_DATA_MASK;
+ }
+ do {
+ char nam[17];
+ snprintf(nam, 16, "%s", mlc->di_scratch.rnm);
+ nam[16] = '\0';
+ printk(KERN_INFO PREFIX "Device name gotten: %s\n", nam);
+ } while (0);
+ return 0;
+}
+
+static int hilse_operate(hil_mlc *mlc, int repoll) {
+
+ if (mlc->opercnt == 0) hil_mlcs_probe = 0;
+ mlc->opercnt = 1;
+
+ hil_mlc_send_polls(mlc);
+
+ if (!hil_mlcs_probe) return 0;
+ hil_mlcs_probe = 0;
+ mlc->opercnt = 0;
+ return 1;
+}
+
+#define FUNC(funct, funct_arg, zero_rc, neg_rc, pos_rc) \
+{ HILSE_FUNC, { func: &funct }, funct_arg, zero_rc, neg_rc, pos_rc },
+#define OUT(pack) \
+{ HILSE_OUT, { packet: pack }, 0, HILSEN_NEXT, HILSEN_DOZE, 0 },
+#define CTS \
+{ HILSE_CTS, { packet: 0 }, 0, HILSEN_NEXT | HILSEN_SCHED | HILSEN_BREAK, HILSEN_DOZE, 0 },
+#define EXPECT(comp, to, got, got_wrong, timed_out) \
+{ HILSE_EXPECT, { packet: comp }, to, got, got_wrong, timed_out },
+#define EXPECT_LAST(comp, to, got, got_wrong, timed_out) \
+{ HILSE_EXPECT_LAST, { packet: comp }, to, got, got_wrong, timed_out },
+#define EXPECT_DISC(comp, to, got, got_wrong, timed_out) \
+{ HILSE_EXPECT_DISC, { packet: comp }, to, got, got_wrong, timed_out },
+#define IN(to, got, got_error, timed_out) \
+{ HILSE_IN, { packet: 0 }, to, got, got_error, timed_out },
+#define OUT_DISC(pack) \
+{ HILSE_OUT_DISC, { packet: pack }, 0, 0, 0, 0 },
+#define OUT_LAST(pack) \
+{ HILSE_OUT_LAST, { packet: pack }, 0, 0, 0, 0 },
+
+struct hilse_node hil_mlc_se[HILSEN_END] = {
+
+ /* 0 HILSEN_START */
+ FUNC(hilse_init_lcv, 0, HILSEN_NEXT, HILSEN_SLEEP, 0)
+
+ /* 1 HILSEN_RESTART */
+ FUNC(hilse_inc_lcv, 10, HILSEN_NEXT, HILSEN_START, 0)
+ OUT(HIL_CTRL_ONLY) /* Disable APE */
+ CTS
+
+#define TEST_PACKET(x) \
+(HIL_PKT_CMD | (x << HIL_PKT_ADDR_SHIFT) | x << 4 | x)
+
+ OUT(HIL_DO_ALTER_CTRL | HIL_CTRL_TEST | TEST_PACKET(0x5))
+ EXPECT(HIL_ERR_INT | TEST_PACKET(0x5),
+ 2000, HILSEN_NEXT, HILSEN_RESTART, HILSEN_RESTART)
+ OUT(HIL_DO_ALTER_CTRL | HIL_CTRL_TEST | TEST_PACKET(0xa))
+ EXPECT(HIL_ERR_INT | TEST_PACKET(0xa),
+ 2000, HILSEN_NEXT, HILSEN_RESTART, HILSEN_RESTART)
+ OUT(HIL_CTRL_ONLY | 0) /* Disable test mode */
+
+ /* 9 HILSEN_DHR */
+ FUNC(hilse_init_lcv, 0, HILSEN_NEXT, HILSEN_SLEEP, 0)
+
+ /* 10 HILSEN_DHR2 */
+ FUNC(hilse_inc_lcv, 10, HILSEN_NEXT, HILSEN_START, 0)
+ FUNC(hilse_set_ddi, -1, HILSEN_NEXT, 0, 0)
+ OUT(HIL_PKT_CMD | HIL_CMD_DHR)
+ IN(300000, HILSEN_DHR2, HILSEN_DHR2, HILSEN_NEXT)
+
+ /* 14 HILSEN_IFC */
+ OUT(HIL_PKT_CMD | HIL_CMD_IFC)
+ EXPECT(HIL_PKT_CMD | HIL_CMD_IFC | HIL_ERR_INT,
+ 20000, HILSEN_DISC, HILSEN_DHR2, HILSEN_NEXT )
+
+ /* If devices are there, they weren't in PUP or other loopback mode.
+ * We're more concerned at this point with restoring operation
+ * to devices than discovering new ones, so we try to salvage
+ * the loop configuration by closing off the loop.
+ */
+
+ /* 16 HILSEN_HEAL0 */
+ FUNC(hilse_dec_ddi, 0, HILSEN_NEXT, HILSEN_ACF, 0)
+ FUNC(hilse_inc_ddi, 0, HILSEN_NEXT, 0, 0)
+
+ /* 18 HILSEN_HEAL */
+ OUT_LAST(HIL_CMD_ELB)
+ EXPECT_LAST(HIL_CMD_ELB | HIL_ERR_INT,
+ 20000, HILSEN_REPOLL, HILSEN_DSR, HILSEN_NEXT)
+ FUNC(hilse_dec_ddi, 0, HILSEN_HEAL, HILSEN_NEXT, 0)
+
+ /* 21 HILSEN_ACF */
+ FUNC(hilse_init_lcv, 0, HILSEN_NEXT, HILSEN_DOZE, 0)
+
+ /* 22 HILSEN_ACF2 */
+ FUNC(hilse_inc_lcv, 10, HILSEN_NEXT, HILSEN_START, 0)
+ OUT(HIL_PKT_CMD | HIL_CMD_ACF | 1)
+ IN(20000, HILSEN_NEXT, HILSEN_DSR, HILSEN_NEXT)
+
+ /* 25 HILSEN_DISC0 */
+ OUT_DISC(HIL_PKT_CMD | HIL_CMD_ELB)
+ EXPECT_DISC(HIL_PKT_CMD | HIL_CMD_ELB | HIL_ERR_INT,
+ 20000, HILSEN_NEXT, HILSEN_DSR, HILSEN_DSR)
+
+ /* Only enter here if response just received */
+ /* 27 HILSEN_DISC */
+ OUT_DISC(HIL_PKT_CMD | HIL_CMD_IDD)
+ EXPECT_DISC(HIL_PKT_CMD | HIL_CMD_IDD | HIL_ERR_INT,
+ 20000, HILSEN_NEXT, HILSEN_DSR, HILSEN_START)
+ FUNC(hilse_inc_ddi, 0, HILSEN_NEXT, HILSEN_START, 0)
+ FUNC(hilse_take_idd, 0, HILSEN_MATCH, HILSEN_IFCACF, HILSEN_FOLLOW)
+ OUT_LAST(HIL_PKT_CMD | HIL_CMD_RSC)
+ EXPECT_LAST(HIL_PKT_CMD | HIL_CMD_RSC | HIL_ERR_INT,
+ 30000, HILSEN_NEXT, HILSEN_DSR, HILSEN_DSR)
+ FUNC(hilse_take_rsc, 0, HILSEN_MATCH, 0, HILSEN_FOLLOW)
+ OUT_LAST(HIL_PKT_CMD | HIL_CMD_EXD)
+ EXPECT_LAST(HIL_PKT_CMD | HIL_CMD_EXD | HIL_ERR_INT,
+ 30000, HILSEN_NEXT, HILSEN_DSR, HILSEN_DSR)
+ FUNC(hilse_take_exd, 0, HILSEN_MATCH, 0, HILSEN_FOLLOW)
+ OUT_LAST(HIL_PKT_CMD | HIL_CMD_RNM)
+ EXPECT_LAST(HIL_PKT_CMD | HIL_CMD_RNM | HIL_ERR_INT,
+ 30000, HILSEN_NEXT, HILSEN_DSR, HILSEN_DSR)
+ FUNC(hilse_take_rnm, 0, HILSEN_MATCH, 0, 0)
+
+ /* 40 HILSEN_MATCH */
+ FUNC(hilse_match, 0, HILSEN_NEXT, HILSEN_NEXT, /* TODO */ 0)
+
+ /* 41 HILSEN_OPERATE */
+ OUT(HIL_PKT_CMD | HIL_CMD_POL)
+ EXPECT(HIL_PKT_CMD | HIL_CMD_POL | HIL_ERR_INT,
+ 20000, HILSEN_NEXT, HILSEN_DSR, HILSEN_NEXT)
+ FUNC(hilse_operate, 0, HILSEN_OPERATE, HILSEN_IFC, HILSEN_NEXT)
+
+ /* 44 HILSEN_PROBE */
+ OUT_LAST(HIL_PKT_CMD | HIL_CMD_EPT)
+ IN(10000, HILSEN_DISC, HILSEN_DSR, HILSEN_NEXT)
+ OUT_DISC(HIL_PKT_CMD | HIL_CMD_ELB)
+ IN(10000, HILSEN_DISC, HILSEN_DSR, HILSEN_NEXT)
+ OUT(HIL_PKT_CMD | HIL_CMD_ACF | 1)
+ IN(10000, HILSEN_DISC0, HILSEN_DSR, HILSEN_NEXT)
+ OUT_LAST(HIL_PKT_CMD | HIL_CMD_ELB)
+ IN(10000, HILSEN_OPERATE, HILSEN_DSR, HILSEN_DSR)
+
+ /* 52 HILSEN_DSR */
+ FUNC(hilse_set_ddi, -1, HILSEN_NEXT, 0, 0)
+ OUT(HIL_PKT_CMD | HIL_CMD_DSR)
+ IN(20000, HILSEN_DHR, HILSEN_DHR, HILSEN_IFC)
+
+ /* 55 HILSEN_REPOLL */
+ OUT(HIL_PKT_CMD | HIL_CMD_RPL)
+ EXPECT(HIL_PKT_CMD | HIL_CMD_RPL | HIL_ERR_INT,
+ 20000, HILSEN_NEXT, HILSEN_DSR, HILSEN_NEXT)
+ FUNC(hilse_operate, 1, HILSEN_OPERATE, HILSEN_IFC, HILSEN_PROBE)
+
+ /* 58 HILSEN_IFCACF */
+ OUT(HIL_PKT_CMD | HIL_CMD_IFC)
+ EXPECT(HIL_PKT_CMD | HIL_CMD_IFC | HIL_ERR_INT,
+ 20000, HILSEN_ACF2, HILSEN_DHR2, HILSEN_HEAL)
+
+ /* 60 HILSEN_END */
+};
+
+static inline void hilse_setup_input(hil_mlc *mlc, struct hilse_node *node) {
+
+ switch (node->act) {
+ case HILSE_EXPECT_DISC:
+ mlc->imatch = node->object.packet;
+ mlc->imatch |= ((mlc->ddi + 2) << HIL_PKT_ADDR_SHIFT);
+ break;
+ case HILSE_EXPECT_LAST:
+ mlc->imatch = node->object.packet;
+ mlc->imatch |= ((mlc->ddi + 1) << HIL_PKT_ADDR_SHIFT);
+ break;
+ case HILSE_EXPECT:
+ mlc->imatch = node->object.packet;
+ break;
+ case HILSE_IN:
+ mlc->imatch = 0;
+ break;
+ default:
+ BUG();
+ }
+ mlc->istarted = 1;
+ mlc->intimeout = node->arg;
+ do_gettimeofday(&(mlc->instart));
+ mlc->icount = 15;
+ memset(mlc->ipacket, 0, 16 * sizeof(hil_packet));
+ if (down_trylock(&(mlc->isem))) BUG();
+
+ return;
+}
+
+#ifdef HIL_MLC_DEBUG
+static int doze = 0;
+static int seidx; /* For debug */
+static int kick = 1;
+#endif
+
+static int hilse_donode (hil_mlc *mlc) {
+ struct hilse_node *node;
+ int nextidx = 0;
+ int sched_long = 0;
+ unsigned long flags;
+
+#ifdef HIL_MLC_DEBUG
+ if (mlc->seidx && (mlc->seidx != seidx) && mlc->seidx != 41 && mlc->seidx != 42 && mlc->seidx != 43) {
+ printk(KERN_DEBUG PREFIX "z%i \n%s {%i}", doze, kick ? "K" : "", mlc->seidx);
+ doze = 0;
+ }
+ kick = 0;
+
+ seidx = mlc->seidx;
+#endif
+ node = hil_mlc_se + mlc->seidx;
+
+ switch (node->act) {
+ int rc;
+ hil_packet pack;
+
+ case HILSE_FUNC:
+ if (node->object.func == NULL) break;
+ rc = node->object.func(mlc, node->arg);
+ nextidx = (rc > 0) ? node->ugly :
+ ((rc < 0) ? node->bad : node->good);
+ if (nextidx == HILSEN_FOLLOW) nextidx = rc;
+ break;
+ case HILSE_EXPECT_LAST:
+ case HILSE_EXPECT_DISC:
+ case HILSE_EXPECT:
+ case HILSE_IN:
+ /* Already set up from previous HILSE_OUT_* */
+ write_lock_irqsave(&(mlc->lock), flags);
+ rc = mlc->in(mlc, node->arg);
+ if (rc == 2) {
+ nextidx = HILSEN_DOZE;
+ sched_long = 1;
+ write_unlock_irqrestore(&(mlc->lock), flags);
+ break;
+ }
+ if (rc == 1) nextidx = node->ugly;
+ else if (rc == 0) nextidx = node->good;
+ else nextidx = node->bad;
+ mlc->istarted = 0;
+ write_unlock_irqrestore(&(mlc->lock), flags);
+ break;
+ case HILSE_OUT_LAST:
+ write_lock_irqsave(&(mlc->lock), flags);
+ pack = node->object.packet;
+ pack |= ((mlc->ddi + 1) << HIL_PKT_ADDR_SHIFT);
+ goto out;
+ case HILSE_OUT_DISC:
+ write_lock_irqsave(&(mlc->lock), flags);
+ pack = node->object.packet;
+ pack |= ((mlc->ddi + 2) << HIL_PKT_ADDR_SHIFT);
+ goto out;
+ case HILSE_OUT:
+ write_lock_irqsave(&(mlc->lock), flags);
+ pack = node->object.packet;
+ out:
+ if (mlc->istarted) goto out2;
+ /* Prepare to receive input */
+ if ((node + 1)->act & HILSE_IN)
+ hilse_setup_input(mlc, node + 1);
+
+ out2:
+ write_unlock_irqrestore(&(mlc->lock), flags);
+
+ if (down_trylock(&mlc->osem)) {
+ nextidx = HILSEN_DOZE;
+ break;
+ }
+ up(&mlc->osem);
+
+ write_lock_irqsave(&(mlc->lock), flags);
+ if (!(mlc->ostarted)) {
+ mlc->ostarted = 1;
+ mlc->opacket = pack;
+ mlc->out(mlc);
+ nextidx = HILSEN_DOZE;
+ write_unlock_irqrestore(&(mlc->lock), flags);
+ break;
+ }
+ mlc->ostarted = 0;
+ do_gettimeofday(&(mlc->instart));
+ write_unlock_irqrestore(&(mlc->lock), flags);
+ nextidx = HILSEN_NEXT;
+ break;
+ case HILSE_CTS:
+ nextidx = mlc->cts(mlc) ? node->bad : node->good;
+ break;
+ default:
+ BUG();
+ nextidx = 0;
+ break;
+ }
+
+#ifdef HIL_MLC_DEBUG
+ if (nextidx == HILSEN_DOZE) doze++;
+#endif
+
+ while (nextidx & HILSEN_SCHED) {
+ struct timeval tv;
+
+ if (!sched_long) goto sched;
+
+ do_gettimeofday(&tv);
+ tv.tv_usec += 1000000 * (tv.tv_sec - mlc->instart.tv_sec);
+ tv.tv_usec -= mlc->instart.tv_usec;
+ if (tv.tv_usec >= mlc->intimeout) goto sched;
+ tv.tv_usec = (mlc->intimeout - tv.tv_usec) * HZ / 1000000;
+ if (!tv.tv_usec) goto sched;
+ mod_timer(&hil_mlcs_kicker, jiffies + tv.tv_usec);
+ break;
+ sched:
+ tasklet_schedule(&hil_mlcs_tasklet);
+ break;
+ }
+ if (nextidx & HILSEN_DOWN) mlc->seidx += nextidx & HILSEN_MASK;
+ else if (nextidx & HILSEN_UP) mlc->seidx -= nextidx & HILSEN_MASK;
+ else mlc->seidx = nextidx & HILSEN_MASK;
+
+ if (nextidx & HILSEN_BREAK) return 1;
+ return 0;
+}
+
+/******************** tasklet context functions **************************/
+static void hil_mlcs_process(unsigned long unused) {
+ struct list_head *tmp;
+
+ read_lock(&hil_mlcs_lock);
+ list_for_each(tmp, &hil_mlcs) {
+ struct hil_mlc *mlc = list_entry(tmp, hil_mlc, list);
+ while (hilse_donode(mlc) == 0) {
+#ifdef HIL_MLC_DEBUG
+ if (mlc->seidx != 41 &&
+ mlc->seidx != 42 &&
+ mlc->seidx != 43)
+ printk(KERN_DEBUG PREFIX " + ");
+#endif
+ };
+ }
+ read_unlock(&hil_mlcs_lock);
+}
+
+/************************* Keepalive timer task *********************/
+
+void hil_mlcs_timer (unsigned long data) {
+ hil_mlcs_probe = 1;
+ tasklet_schedule(&hil_mlcs_tasklet);
+ /* Re-insert the periodic task. */
+ if (!timer_pending(&hil_mlcs_kicker))
+ mod_timer(&hil_mlcs_kicker, jiffies + HZ);
+}
+
+/******************** user/kernel context functions **********************/
+
+static int hil_mlc_serio_write(struct serio *serio, unsigned char c) {
+ struct hil_mlc_serio_map *map;
+ struct hil_mlc *mlc;
+ struct serio_driver *drv;
+ uint8_t *idx, *last;
+
+ map = serio->port_data;
+ if (map == NULL) {
+ BUG();
+ return -EIO;
+ }
+ mlc = map->mlc;
+ if (mlc == NULL) {
+ BUG();
+ return -EIO;
+ }
+ mlc->serio_opacket[map->didx] |=
+ ((hil_packet)c) << (8 * (3 - mlc->serio_oidx[map->didx]));
+
+ if (mlc->serio_oidx[map->didx] >= 3) {
+ /* for now only commands */
+ if (!(mlc->serio_opacket[map->didx] & HIL_PKT_CMD))
+ return -EIO;
+ switch (mlc->serio_opacket[map->didx] & HIL_PKT_DATA_MASK) {
+ case HIL_CMD_IDD:
+ idx = mlc->di[map->didx].idd;
+ goto emu;
+ case HIL_CMD_RSC:
+ idx = mlc->di[map->didx].rsc;
+ goto emu;
+ case HIL_CMD_EXD:
+ idx = mlc->di[map->didx].exd;
+ goto emu;
+ case HIL_CMD_RNM:
+ idx = mlc->di[map->didx].rnm;
+ goto emu;
+ default:
+ break;
+ }
+ mlc->serio_oidx[map->didx] = 0;
+ mlc->serio_opacket[map->didx] = 0;
+ }
+
+ mlc->serio_oidx[map->didx]++;
+ return -EIO;
+ emu:
+ drv = serio->drv;
+ if (drv == NULL) {
+ BUG();
+ return -EIO;
+ }
+ last = idx + 15;
+ while ((last != idx) && (*last == 0)) last--;
+
+ while (idx != last) {
+ drv->interrupt(serio, 0, 0, NULL);
+ drv->interrupt(serio, HIL_ERR_INT >> 16, 0, NULL);
+ drv->interrupt(serio, 0, 0, NULL);
+ drv->interrupt(serio, *idx, 0, NULL);
+ idx++;
+ }
+ drv->interrupt(serio, 0, 0, NULL);
+ drv->interrupt(serio, HIL_ERR_INT >> 16, 0, NULL);
+ drv->interrupt(serio, HIL_PKT_CMD >> 8, 0, NULL);
+ drv->interrupt(serio, *idx, 0, NULL);
+
+ mlc->serio_oidx[map->didx] = 0;
+ mlc->serio_opacket[map->didx] = 0;
+
+ return 0;
+}
+
+static int hil_mlc_serio_open(struct serio *serio) {
+ struct hil_mlc_serio_map *map;
+ struct hil_mlc *mlc;
+
+ if (serio->private != NULL) return -EBUSY;
+
+ map = serio->port_data;
+ if (map == NULL) {
+ BUG();
+ return -ENODEV;
+ }
+ mlc = map->mlc;
+ if (mlc == NULL) {
+ BUG();
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static void hil_mlc_serio_close(struct serio *serio) {
+ struct hil_mlc_serio_map *map;
+ struct hil_mlc *mlc;
+
+ map = serio->port_data;
+ if (map == NULL) {
+ BUG();
+ return;
+ }
+ mlc = map->mlc;
+ if (mlc == NULL) {
+ BUG();
+ return;
+ }
+
+ serio->private = NULL;
+ serio->drv = NULL;
+ /* TODO wake up interruptable */
+}
+
+int hil_mlc_register(hil_mlc *mlc) {
+ int i;
+ unsigned long flags;
+
+ if (mlc == NULL) {
+ return -EINVAL;
+ }
+
+ mlc->istarted = 0;
+ mlc->ostarted = 0;
+
+ rwlock_init(&mlc->lock);
+ init_MUTEX(&(mlc->osem));
+
+ init_MUTEX(&(mlc->isem));
+ mlc->icount = -1;
+ mlc->imatch = 0;
+
+ mlc->opercnt = 0;
+
+ init_MUTEX_LOCKED(&(mlc->csem));
+
+ hil_mlc_clear_di_scratch(mlc);
+ hil_mlc_clear_di_map(mlc, 0);
+ for (i = 0; i < HIL_MLC_DEVMEM; i++) {
+ struct serio *mlc_serio;
+ hil_mlc_copy_di_scratch(mlc, i);
+ mlc_serio = kmalloc(sizeof(*mlc_serio), GFP_KERNEL);
+ mlc->serio[i] = mlc_serio;
+ memset(mlc_serio, 0, sizeof(*mlc_serio));
+ mlc_serio->type = SERIO_HIL | SERIO_HIL_MLC;
+ mlc_serio->write = hil_mlc_serio_write;
+ mlc_serio->open = hil_mlc_serio_open;
+ mlc_serio->close = hil_mlc_serio_close;
+ mlc_serio->port_data = &(mlc->serio_map[i]);
+ mlc->serio_map[i].mlc = mlc;
+ mlc->serio_map[i].didx = i;
+ mlc->serio_map[i].di_revmap = -1;
+ mlc->serio_opacket[i] = 0;
+ mlc->serio_oidx[i] = 0;
+ serio_register_port(mlc_serio);
+ }
+
+ mlc->tasklet = &hil_mlcs_tasklet;
+
+ write_lock_irqsave(&hil_mlcs_lock, flags);
+ list_add_tail(&mlc->list, &hil_mlcs);
+ mlc->seidx = HILSEN_START;
+ write_unlock_irqrestore(&hil_mlcs_lock, flags);
+
+ tasklet_schedule(&hil_mlcs_tasklet);
+ return 0;
+}
+
+int hil_mlc_unregister(hil_mlc *mlc) {
+ struct list_head *tmp;
+ unsigned long flags;
+ int i;
+
+ if (mlc == NULL)
+ return -EINVAL;
+
+ write_lock_irqsave(&hil_mlcs_lock, flags);
+ list_for_each(tmp, &hil_mlcs) {
+ if (list_entry(tmp, hil_mlc, list) == mlc)
+ goto found;
+ }
+
+ /* not found in list */
+ write_unlock_irqrestore(&hil_mlcs_lock, flags);
+ tasklet_schedule(&hil_mlcs_tasklet);
+ return -ENODEV;
+
+ found:
+ list_del(tmp);
+ write_unlock_irqrestore(&hil_mlcs_lock, flags);
+
+ for (i = 0; i < HIL_MLC_DEVMEM; i++) {
+ serio_unregister_port(mlc->serio[i]);
+ mlc->serio[i] = NULL;
+ }
+
+ tasklet_schedule(&hil_mlcs_tasklet);
+ return 0;
+}
+
+/**************************** Module interface *************************/
+
+static int __init hil_mlc_init(void)
+{
+ init_timer(&hil_mlcs_kicker);
+ hil_mlcs_kicker.expires = jiffies + HZ;
+ hil_mlcs_kicker.function = &hil_mlcs_timer;
+ add_timer(&hil_mlcs_kicker);
+
+ tasklet_enable(&hil_mlcs_tasklet);
+
+ return 0;
+}
+
+static void __exit hil_mlc_exit(void)
+{
+ del_timer(&hil_mlcs_kicker);
+
+ tasklet_disable(&hil_mlcs_tasklet);
+ tasklet_kill(&hil_mlcs_tasklet);
+}
+
+module_init(hil_mlc_init);
+module_exit(hil_mlc_exit);
diff --git a/drivers/input/serio/hp_sdc.c b/drivers/input/serio/hp_sdc.c
new file mode 100644
index 0000000000000..7629452dd64b0
--- /dev/null
+++ b/drivers/input/serio/hp_sdc.c
@@ -0,0 +1,1054 @@
+/*
+ * HP i8042-based System Device Controller driver.
+ *
+ * Copyright (c) 2001 Brian S. Julin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. The name of the author may not 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").
+ *
+ * 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
+ *
+ * References:
+ * System Device Controller Microprocessor Firmware Theory of Operation
+ * for Part Number 1820-4784 Revision B. Dwg No. A-1820-4784-2
+ * Helge Deller's original hilkbd.c port for PA-RISC.
+ *
+ *
+ * Driver theory of operation:
+ *
+ * hp_sdc_put does all writing to the SDC. ISR can run on a different
+ * CPU than hp_sdc_put, but only one CPU runs hp_sdc_put at a time
+ * (it cannot really benefit from SMP anyway.) A tasket fit this perfectly.
+ *
+ * All data coming back from the SDC is sent via interrupt and can be read
+ * fully in the ISR, so there are no latency/throughput problems there.
+ * The problem is with output, due to the slow clock speed of the SDC
+ * compared to the CPU. This should not be too horrible most of the time,
+ * but if used with HIL devices that support the multibyte transfer command,
+ * keeping outbound throughput flowing at the 6500KBps that the HIL is
+ * capable of is more than can be done at HZ=100.
+ *
+ * Busy polling for IBF clear wastes CPU cycles and bus cycles. hp_sdc.ibf
+ * is set to 0 when the IBF flag in the status register has cleared. ISR
+ * may do this, and may also access the parts of queued transactions related
+ * to reading data back from the SDC, but otherwise will not touch the
+ * hp_sdc state. Whenever a register is written hp_sdc.ibf is set to 1.
+ *
+ * The i8042 write index and the values in the 4-byte input buffer
+ * starting at 0x70 are kept track of in hp_sdc.wi, and .r7[], respectively,
+ * to minimize the amount of IO needed to the SDC. However these values
+ * do not need to be locked since they are only ever accessed by hp_sdc_put.
+ *
+ * A timer task schedules the tasklet once per second just to make
+ * sure it doesn't freeze up and to allow for bad reads to time out.
+ */
+
+#include <linux/hp_sdc.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/ioport.h>
+#include <linux/time.h>
+#include <linux/slab.h>
+#include <linux/hil.h>
+#include <asm/io.h>
+#include <asm/system.h>
+
+/* Machine-specific abstraction */
+
+#if defined(__hppa__)
+# include <asm/parisc-device.h>
+# define sdc_readb(p) gsc_readb(p)
+# define sdc_writeb(v,p) gsc_writeb((v),(p))
+#elif defined(__mc68000__)
+# include <asm/uaccess.h>
+# define sdc_readb(p) in_8(p)
+# define sdc_writeb(v,p) out_8((p),(v))
+#else
+# error "HIL is not supported on this platform"
+#endif
+
+#define PREFIX "HP SDC: "
+
+MODULE_AUTHOR("Brian S. Julin <bri@calyx.com>");
+MODULE_DESCRIPTION("HP i8042-based SDC Driver");
+MODULE_LICENSE("Dual BSD/GPL");
+
+EXPORT_SYMBOL(hp_sdc_request_timer_irq);
+EXPORT_SYMBOL(hp_sdc_request_hil_irq);
+EXPORT_SYMBOL(hp_sdc_request_cooked_irq);
+
+EXPORT_SYMBOL(hp_sdc_release_timer_irq);
+EXPORT_SYMBOL(hp_sdc_release_hil_irq);
+EXPORT_SYMBOL(hp_sdc_release_cooked_irq);
+
+EXPORT_SYMBOL(hp_sdc_enqueue_transaction);
+EXPORT_SYMBOL(hp_sdc_dequeue_transaction);
+
+static hp_i8042_sdc hp_sdc; /* All driver state is kept in here. */
+
+/*************** primitives for use in any context *********************/
+static inline uint8_t hp_sdc_status_in8 (void) {
+ uint8_t status;
+ unsigned long flags;
+
+ write_lock_irqsave(&hp_sdc.ibf_lock, flags);
+ status = sdc_readb(hp_sdc.status_io);
+ if (!(status & HP_SDC_STATUS_IBF)) hp_sdc.ibf = 0;
+ write_unlock_irqrestore(&hp_sdc.ibf_lock, flags);
+
+ return status;
+}
+
+static inline uint8_t hp_sdc_data_in8 (void) {
+ return sdc_readb(hp_sdc.data_io);
+}
+
+static inline void hp_sdc_status_out8 (uint8_t val) {
+ unsigned long flags;
+
+ write_lock_irqsave(&hp_sdc.ibf_lock, flags);
+ hp_sdc.ibf = 1;
+ if ((val & 0xf0) == 0xe0) hp_sdc.wi = 0xff;
+ sdc_writeb(val, hp_sdc.status_io);
+ write_unlock_irqrestore(&hp_sdc.ibf_lock, flags);
+}
+
+static inline void hp_sdc_data_out8 (uint8_t val) {
+ unsigned long flags;
+
+ write_lock_irqsave(&hp_sdc.ibf_lock, flags);
+ hp_sdc.ibf = 1;
+ sdc_writeb(val, hp_sdc.data_io);
+ write_unlock_irqrestore(&hp_sdc.ibf_lock, flags);
+}
+
+/* Care must be taken to only invoke hp_sdc_spin_ibf when
+ * absolutely needed, or in rarely invoked subroutines.
+ * Not only does it waste CPU cycles, it also wastes bus cycles.
+ */
+static inline void hp_sdc_spin_ibf(void) {
+ unsigned long flags;
+ rwlock_t *lock;
+
+ lock = &hp_sdc.ibf_lock;
+
+ read_lock_irqsave(lock, flags);
+ if (!hp_sdc.ibf) {
+ read_unlock_irqrestore(lock, flags);
+ return;
+ }
+ read_unlock(lock);
+ write_lock(lock);
+ while (sdc_readb(hp_sdc.status_io) & HP_SDC_STATUS_IBF) {};
+ hp_sdc.ibf = 0;
+ write_unlock_irqrestore(lock, flags);
+}
+
+
+/************************ Interrupt context functions ************************/
+static void hp_sdc_take (int irq, void *dev_id, uint8_t status, uint8_t data) {
+ hp_sdc_transaction *curr;
+
+ read_lock(&hp_sdc.rtq_lock);
+ if (hp_sdc.rcurr < 0) {
+ read_unlock(&hp_sdc.rtq_lock);
+ return;
+ }
+ curr = hp_sdc.tq[hp_sdc.rcurr];
+ read_unlock(&hp_sdc.rtq_lock);
+
+ curr->seq[curr->idx++] = status;
+ curr->seq[curr->idx++] = data;
+ hp_sdc.rqty -= 2;
+ do_gettimeofday(&hp_sdc.rtv);
+
+ if (hp_sdc.rqty <= 0) {
+ /* All data has been gathered. */
+ if(curr->seq[curr->actidx] & HP_SDC_ACT_SEMAPHORE) {
+ if (curr->act.semaphore) up(curr->act.semaphore);
+ }
+ if(curr->seq[curr->actidx] & HP_SDC_ACT_CALLBACK) {
+ if (curr->act.irqhook)
+ curr->act.irqhook(irq, dev_id, status, data);
+ }
+ curr->actidx = curr->idx;
+ curr->idx++;
+ /* Return control of this transaction */
+ write_lock(&hp_sdc.rtq_lock);
+ hp_sdc.rcurr = -1;
+ hp_sdc.rqty = 0;
+ write_unlock(&hp_sdc.rtq_lock);
+ tasklet_schedule(&hp_sdc.task);
+ }
+}
+
+static irqreturn_t hp_sdc_isr(int irq, void *dev_id, struct pt_regs * regs) {
+ uint8_t status, data;
+
+ status = hp_sdc_status_in8();
+ /* Read data unconditionally to advance i8042. */
+ data = hp_sdc_data_in8();
+
+ /* For now we are ignoring these until we get the SDC to behave. */
+ if (((status & 0xf1) == 0x51) && data == 0x82) {
+ return IRQ_HANDLED;
+ }
+
+ switch(status & HP_SDC_STATUS_IRQMASK) {
+ case 0: /* This case is not documented. */
+ break;
+ case HP_SDC_STATUS_USERTIMER:
+ case HP_SDC_STATUS_PERIODIC:
+ case HP_SDC_STATUS_TIMER:
+ read_lock(&hp_sdc.hook_lock);
+ if (hp_sdc.timer != NULL)
+ hp_sdc.timer(irq, dev_id, status, data);
+ read_unlock(&hp_sdc.hook_lock);
+ break;
+ case HP_SDC_STATUS_REG:
+ hp_sdc_take(irq, dev_id, status, data);
+ break;
+ case HP_SDC_STATUS_HILCMD:
+ case HP_SDC_STATUS_HILDATA:
+ read_lock(&hp_sdc.hook_lock);
+ if (hp_sdc.hil != NULL)
+ hp_sdc.hil(irq, dev_id, status, data);
+ read_unlock(&hp_sdc.hook_lock);
+ break;
+ case HP_SDC_STATUS_PUP:
+ read_lock(&hp_sdc.hook_lock);
+ if (hp_sdc.pup != NULL)
+ hp_sdc.pup(irq, dev_id, status, data);
+ else printk(KERN_INFO PREFIX "HP SDC reports successful PUP.\n");
+ read_unlock(&hp_sdc.hook_lock);
+ break;
+ default:
+ read_lock(&hp_sdc.hook_lock);
+ if (hp_sdc.cooked != NULL)
+ hp_sdc.cooked(irq, dev_id, status, data);
+ read_unlock(&hp_sdc.hook_lock);
+ break;
+ }
+ return IRQ_HANDLED;
+}
+
+
+static irqreturn_t hp_sdc_nmisr(int irq, void *dev_id, struct pt_regs * regs) {
+ int status;
+
+ status = hp_sdc_status_in8();
+ printk(KERN_WARNING PREFIX "NMI !\n");
+
+#if 0
+ if (status & HP_SDC_NMISTATUS_FHS) {
+ read_lock(&hp_sdc.hook_lock);
+ if (hp_sdc.timer != NULL)
+ hp_sdc.timer(irq, dev_id, status, 0);
+ read_unlock(&hp_sdc.hook_lock);
+ }
+ else {
+ /* TODO: pass this on to the HIL handler, or do SAK here? */
+ printk(KERN_WARNING PREFIX "HIL NMI\n");
+ }
+#endif
+ return IRQ_HANDLED;
+}
+
+
+/***************** Kernel (tasklet) context functions ****************/
+
+unsigned long hp_sdc_put(void);
+
+static void hp_sdc_tasklet(unsigned long foo) {
+
+ write_lock_irq(&hp_sdc.rtq_lock);
+ if (hp_sdc.rcurr >= 0) {
+ struct timeval tv;
+ do_gettimeofday(&tv);
+ if (tv.tv_sec > hp_sdc.rtv.tv_sec) tv.tv_usec += 1000000;
+ if (tv.tv_usec - hp_sdc.rtv.tv_usec > HP_SDC_MAX_REG_DELAY) {
+ hp_sdc_transaction *curr;
+ uint8_t tmp;
+
+ curr = hp_sdc.tq[hp_sdc.rcurr];
+ /* If this turns out to be a normal failure mode
+ * we'll need to figure out a way to communicate
+ * it back to the application. and be less verbose.
+ */
+ printk(KERN_WARNING PREFIX "read timeout (%ius)!\n",
+ tv.tv_usec - hp_sdc.rtv.tv_usec);
+ curr->idx += hp_sdc.rqty;
+ hp_sdc.rqty = 0;
+ tmp = curr->seq[curr->actidx];
+ curr->seq[curr->actidx] |= HP_SDC_ACT_DEAD;
+ if(tmp & HP_SDC_ACT_SEMAPHORE) {
+ if (curr->act.semaphore)
+ up(curr->act.semaphore);
+ }
+ if(tmp & HP_SDC_ACT_CALLBACK) {
+ /* Note this means that irqhooks may be called
+ * in tasklet/bh context.
+ */
+ if (curr->act.irqhook)
+ curr->act.irqhook(0, 0, 0, 0);
+ }
+ curr->actidx = curr->idx;
+ curr->idx++;
+ hp_sdc.rcurr = -1;
+ }
+ }
+ write_unlock_irq(&hp_sdc.rtq_lock);
+ hp_sdc_put();
+}
+
+unsigned long hp_sdc_put(void) {
+ hp_sdc_transaction *curr;
+ uint8_t act;
+ int idx, curridx;
+
+ int limit = 0;
+
+ write_lock(&hp_sdc.lock);
+
+ /* If i8042 buffers are full, we cannot do anything that
+ requires output, so we skip to the administrativa. */
+ if (hp_sdc.ibf) {
+ hp_sdc_status_in8();
+ if (hp_sdc.ibf) goto finish;
+ }
+
+ anew:
+ /* See if we are in the middle of a sequence. */
+ if (hp_sdc.wcurr < 0) hp_sdc.wcurr = 0;
+ read_lock_irq(&hp_sdc.rtq_lock);
+ if (hp_sdc.rcurr == hp_sdc.wcurr) hp_sdc.wcurr++;
+ read_unlock_irq(&hp_sdc.rtq_lock);
+ if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN) hp_sdc.wcurr = 0;
+ curridx = hp_sdc.wcurr;
+
+ if (hp_sdc.tq[curridx] != NULL) goto start;
+
+ while (++curridx != hp_sdc.wcurr) {
+ if (curridx >= HP_SDC_QUEUE_LEN) {
+ curridx = -1; /* Wrap to top */
+ continue;
+ }
+ read_lock_irq(&hp_sdc.rtq_lock);
+ if (hp_sdc.rcurr == curridx) {
+ read_unlock_irq(&hp_sdc.rtq_lock);
+ continue;
+ }
+ read_unlock_irq(&hp_sdc.rtq_lock);
+ if (hp_sdc.tq[curridx] != NULL) break; /* Found one. */
+ }
+ if (curridx == hp_sdc.wcurr) { /* There's nothing queued to do. */
+ curridx = -1;
+ }
+ hp_sdc.wcurr = curridx;
+
+ start:
+
+ /* Check to see if the interrupt mask needs to be set. */
+ if (hp_sdc.set_im) {
+ hp_sdc_status_out8(hp_sdc.im | HP_SDC_CMD_SET_IM);
+ hp_sdc.set_im = 0;
+ goto finish;
+ }
+
+ if (hp_sdc.wcurr == -1) goto done;
+
+ curr = hp_sdc.tq[curridx];
+ idx = curr->actidx;
+
+ if (curr->actidx >= curr->endidx) {
+ hp_sdc.tq[curridx] = NULL;
+ /* Interleave outbound data between the transactions. */
+ hp_sdc.wcurr++;
+ if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN) hp_sdc.wcurr = 0;
+ goto finish;
+ }
+
+ act = curr->seq[idx];
+ idx++;
+
+ if (curr->idx >= curr->endidx) {
+ if (act & HP_SDC_ACT_DEALLOC) kfree(curr);
+ hp_sdc.tq[curridx] = NULL;
+ /* Interleave outbound data between the transactions. */
+ hp_sdc.wcurr++;
+ if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN) hp_sdc.wcurr = 0;
+ goto finish;
+ }
+
+ while (act & HP_SDC_ACT_PRECMD) {
+ if (curr->idx != idx) {
+ idx++;
+ act &= ~HP_SDC_ACT_PRECMD;
+ break;
+ }
+ hp_sdc_status_out8(curr->seq[idx]);
+ curr->idx++;
+ /* act finished? */
+ if ((act & HP_SDC_ACT_DURING) == HP_SDC_ACT_PRECMD)
+ goto actdone;
+ /* skip quantity field if data-out sequence follows. */
+ if (act & HP_SDC_ACT_DATAOUT) curr->idx++;
+ goto finish;
+ }
+ if (act & HP_SDC_ACT_DATAOUT) {
+ int qty;
+
+ qty = curr->seq[idx];
+ idx++;
+ if (curr->idx - idx < qty) {
+ hp_sdc_data_out8(curr->seq[curr->idx]);
+ curr->idx++;
+ /* act finished? */
+ if ((curr->idx - idx >= qty) &&
+ ((act & HP_SDC_ACT_DURING) == HP_SDC_ACT_DATAOUT))
+ goto actdone;
+ goto finish;
+ }
+ idx += qty;
+ act &= ~HP_SDC_ACT_DATAOUT;
+ }
+ else while (act & HP_SDC_ACT_DATAREG) {
+ int mask;
+ uint8_t w7[4];
+
+ mask = curr->seq[idx];
+ if (idx != curr->idx) {
+ idx++;
+ idx += !!(mask & 1);
+ idx += !!(mask & 2);
+ idx += !!(mask & 4);
+ idx += !!(mask & 8);
+ act &= ~HP_SDC_ACT_DATAREG;
+ break;
+ }
+
+ w7[0] = (mask & 1) ? curr->seq[++idx] : hp_sdc.r7[0];
+ w7[1] = (mask & 2) ? curr->seq[++idx] : hp_sdc.r7[1];
+ w7[2] = (mask & 4) ? curr->seq[++idx] : hp_sdc.r7[2];
+ w7[3] = (mask & 8) ? curr->seq[++idx] : hp_sdc.r7[3];
+
+ if (hp_sdc.wi > 0x73 || hp_sdc.wi < 0x70 ||
+ w7[hp_sdc.wi-0x70] == hp_sdc.r7[hp_sdc.wi-0x70]) {
+ int i = 0;
+
+ /* Need to point the write index register */
+ while ((i < 4) && w7[i] == hp_sdc.r7[i]) i++;
+ if (i < 4) {
+ hp_sdc_status_out8(HP_SDC_CMD_SET_D0 + i);
+ hp_sdc.wi = 0x70 + i;
+ goto finish;
+ }
+ idx++;
+ if ((act & HP_SDC_ACT_DURING) == HP_SDC_ACT_DATAREG)
+ goto actdone;
+ curr->idx = idx;
+ act &= ~HP_SDC_ACT_DATAREG;
+ break;
+ }
+
+ hp_sdc_data_out8(w7[hp_sdc.wi - 0x70]);
+ hp_sdc.r7[hp_sdc.wi - 0x70] = w7[hp_sdc.wi - 0x70];
+ hp_sdc.wi++; /* write index register autoincrements */
+ {
+ int i = 0;
+
+ while ((i < 4) && w7[i] == hp_sdc.r7[i]) i++;
+ if (i >= 4) {
+ curr->idx = idx + 1;
+ if ((act & HP_SDC_ACT_DURING) ==
+ HP_SDC_ACT_DATAREG)
+ goto actdone;
+ }
+ }
+ goto finish;
+ }
+ /* We don't go any further in the command if there is a pending read,
+ because we don't want interleaved results. */
+ read_lock_irq(&hp_sdc.rtq_lock);
+ if (hp_sdc.rcurr >= 0) {
+ read_unlock_irq(&hp_sdc.rtq_lock);
+ goto finish;
+ }
+ read_unlock_irq(&hp_sdc.rtq_lock);
+
+
+ if (act & HP_SDC_ACT_POSTCMD) {
+ uint8_t postcmd;
+
+ /* curr->idx should == idx at this point. */
+ postcmd = curr->seq[idx];
+ curr->idx++;
+ if (act & HP_SDC_ACT_DATAIN) {
+
+ /* Start a new read */
+ hp_sdc.rqty = curr->seq[curr->idx];
+ do_gettimeofday(&hp_sdc.rtv);
+ curr->idx++;
+ /* Still need to lock here in case of spurious irq. */
+ write_lock_irq(&hp_sdc.rtq_lock);
+ hp_sdc.rcurr = curridx;
+ write_unlock_irq(&hp_sdc.rtq_lock);
+ hp_sdc_status_out8(postcmd);
+ goto finish;
+ }
+ hp_sdc_status_out8(postcmd);
+ goto actdone;
+ }
+
+actdone:
+ if (act & HP_SDC_ACT_SEMAPHORE) {
+ up(curr->act.semaphore);
+ }
+ else if (act & HP_SDC_ACT_CALLBACK) {
+ curr->act.irqhook(0,0,0,0);
+ }
+ if (curr->idx >= curr->endidx) { /* This transaction is over. */
+ if (act & HP_SDC_ACT_DEALLOC) kfree(curr);
+ hp_sdc.tq[curridx] = NULL;
+ }
+ else {
+ curr->actidx = idx + 1;
+ curr->idx = idx + 2;
+ }
+ /* Interleave outbound data between the transactions. */
+ hp_sdc.wcurr++;
+ if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN) hp_sdc.wcurr = 0;
+
+ finish:
+ /* If by some quirk IBF has cleared and our ISR has run to
+ see that that has happened, do it all again. */
+ if (!hp_sdc.ibf && limit++ < 20) goto anew;
+
+ done:
+ if (hp_sdc.wcurr >= 0) tasklet_schedule(&hp_sdc.task);
+ write_unlock(&hp_sdc.lock);
+ return 0;
+}
+
+/******* Functions called in either user or kernel context ****/
+int hp_sdc_enqueue_transaction(hp_sdc_transaction *this) {
+ unsigned long flags;
+ int i;
+
+ if (this == NULL) {
+ tasklet_schedule(&hp_sdc.task);
+ return -EINVAL;
+ };
+
+ write_lock_irqsave(&hp_sdc.lock, flags);
+
+ /* Can't have same transaction on queue twice */
+ for (i=0; i < HP_SDC_QUEUE_LEN; i++)
+ if (hp_sdc.tq[i] == this) goto fail;
+
+ this->actidx = 0;
+ this->idx = 1;
+
+ /* Search for empty slot */
+ for (i=0; i < HP_SDC_QUEUE_LEN; i++) {
+ if (hp_sdc.tq[i] == NULL) {
+ hp_sdc.tq[i] = this;
+ write_unlock_irqrestore(&hp_sdc.lock, flags);
+ tasklet_schedule(&hp_sdc.task);
+ return 0;
+ }
+ }
+ write_unlock_irqrestore(&hp_sdc.lock, flags);
+ printk(KERN_WARNING PREFIX "No free slot to add transaction.\n");
+ return -EBUSY;
+
+ fail:
+ write_unlock_irqrestore(&hp_sdc.lock,flags);
+ printk(KERN_WARNING PREFIX "Transaction add failed: transaction already queued?\n");
+ return -EINVAL;
+}
+
+int hp_sdc_dequeue_transaction(hp_sdc_transaction *this) {
+ unsigned long flags;
+ int i;
+
+ write_lock_irqsave(&hp_sdc.lock, flags);
+
+ /* TODO: don't remove it if it's not done. */
+
+ for (i=0; i < HP_SDC_QUEUE_LEN; i++)
+ if (hp_sdc.tq[i] == this) hp_sdc.tq[i] = NULL;
+
+ write_unlock_irqrestore(&hp_sdc.lock, flags);
+ return 0;
+}
+
+
+
+/********************** User context functions **************************/
+int hp_sdc_request_timer_irq(hp_sdc_irqhook *callback) {
+
+ if (callback == NULL || hp_sdc.dev == NULL) {
+ return -EINVAL;
+ }
+ write_lock_irq(&hp_sdc.hook_lock);
+ if (hp_sdc.timer != NULL) {
+ write_unlock_irq(&hp_sdc.hook_lock);
+ return -EBUSY;
+ }
+
+ hp_sdc.timer = callback;
+ /* Enable interrupts from the timers */
+ hp_sdc.im &= ~HP_SDC_IM_FH;
+ hp_sdc.im &= ~HP_SDC_IM_PT;
+ hp_sdc.im &= ~HP_SDC_IM_TIMERS;
+ hp_sdc.set_im = 1;
+ write_unlock_irq(&hp_sdc.hook_lock);
+
+ tasklet_schedule(&hp_sdc.task);
+
+ return 0;
+}
+
+int hp_sdc_request_hil_irq(hp_sdc_irqhook *callback) {
+
+ if (callback == NULL || hp_sdc.dev == NULL) {
+ return -EINVAL;
+ }
+ write_lock_irq(&hp_sdc.hook_lock);
+ if (hp_sdc.hil != NULL) {
+ write_unlock_irq(&hp_sdc.hook_lock);
+ return -EBUSY;
+ }
+
+ hp_sdc.hil = callback;
+ hp_sdc.im &= ~(HP_SDC_IM_HIL | HP_SDC_IM_RESET);
+ hp_sdc.set_im = 1;
+ write_unlock_irq(&hp_sdc.hook_lock);
+
+ tasklet_schedule(&hp_sdc.task);
+
+ return 0;
+}
+
+int hp_sdc_request_cooked_irq(hp_sdc_irqhook *callback) {
+
+ if (callback == NULL || hp_sdc.dev == NULL) {
+ return -EINVAL;
+ }
+ write_lock_irq(&hp_sdc.hook_lock);
+ if (hp_sdc.cooked != NULL) {
+ write_unlock_irq(&hp_sdc.hook_lock);
+ return -EBUSY;
+ }
+
+ /* Enable interrupts from the HIL MLC */
+ hp_sdc.cooked = callback;
+ hp_sdc.im &= ~(HP_SDC_IM_HIL | HP_SDC_IM_RESET);
+ hp_sdc.set_im = 1;
+ write_unlock_irq(&hp_sdc.hook_lock);
+
+ tasklet_schedule(&hp_sdc.task);
+
+ return 0;
+}
+
+int hp_sdc_release_timer_irq(hp_sdc_irqhook *callback) {
+
+
+ write_lock_irq(&hp_sdc.hook_lock);
+ if ((callback != hp_sdc.timer) ||
+ (hp_sdc.timer == NULL)) {
+ write_unlock_irq(&hp_sdc.hook_lock);
+ return -EINVAL;
+ }
+
+ /* Disable interrupts from the timers */
+ hp_sdc.timer = NULL;
+ hp_sdc.im |= HP_SDC_IM_TIMERS;
+ hp_sdc.im |= HP_SDC_IM_FH;
+ hp_sdc.im |= HP_SDC_IM_PT;
+ hp_sdc.set_im = 1;
+ write_unlock_irq(&hp_sdc.hook_lock);
+ tasklet_schedule(&hp_sdc.task);
+
+ return 0;
+}
+
+int hp_sdc_release_hil_irq(hp_sdc_irqhook *callback) {
+
+ write_lock_irq(&hp_sdc.hook_lock);
+ if ((callback != hp_sdc.hil) ||
+ (hp_sdc.hil == NULL)) {
+ write_unlock_irq(&hp_sdc.hook_lock);
+ return -EINVAL;
+ }
+
+ hp_sdc.hil = NULL;
+ /* Disable interrupts from HIL only if there is no cooked driver. */
+ if(hp_sdc.cooked == NULL) {
+ hp_sdc.im |= (HP_SDC_IM_HIL | HP_SDC_IM_RESET);
+ hp_sdc.set_im = 1;
+ }
+ write_unlock_irq(&hp_sdc.hook_lock);
+ tasklet_schedule(&hp_sdc.task);
+
+ return 0;
+}
+
+int hp_sdc_release_cooked_irq(hp_sdc_irqhook *callback) {
+
+ write_lock_irq(&hp_sdc.hook_lock);
+ if ((callback != hp_sdc.cooked) ||
+ (hp_sdc.cooked == NULL)) {
+ write_unlock_irq(&hp_sdc.hook_lock);
+ return -EINVAL;
+ }
+
+ hp_sdc.cooked = NULL;
+ /* Disable interrupts from HIL only if there is no raw HIL driver. */
+ if(hp_sdc.hil == NULL) {
+ hp_sdc.im |= (HP_SDC_IM_HIL | HP_SDC_IM_RESET);
+ hp_sdc.set_im = 1;
+ }
+ write_unlock_irq(&hp_sdc.hook_lock);
+ tasklet_schedule(&hp_sdc.task);
+
+ return 0;
+}
+
+/************************* Keepalive timer task *********************/
+
+void hp_sdc_kicker (unsigned long data) {
+ tasklet_schedule(&hp_sdc.task);
+ /* Re-insert the periodic task. */
+ mod_timer(&hp_sdc.kicker, jiffies + HZ);
+}
+
+/************************** Module Initialization ***************************/
+
+#if defined(__hppa__)
+
+static struct parisc_device_id hp_sdc_tbl[] = {
+ {
+ .hw_type = HPHW_FIO,
+ .hversion_rev = HVERSION_REV_ANY_ID,
+ .hversion = HVERSION_ANY_ID,
+ .sversion = 0x73,
+ },
+ { 0, }
+};
+
+MODULE_DEVICE_TABLE(parisc, hp_sdc_tbl);
+
+static int __init hp_sdc_init_hppa(struct parisc_device *d);
+
+static struct parisc_driver hp_sdc_driver = {
+ .name = "HP SDC",
+ .id_table = hp_sdc_tbl,
+ .probe = hp_sdc_init_hppa,
+};
+
+#endif /* __hppa__ */
+
+static int __init hp_sdc_init(void)
+{
+ int i;
+ char *errstr;
+ hp_sdc_transaction t_sync;
+ uint8_t ts_sync[6];
+ struct semaphore s_sync;
+
+ rwlock_init(&hp_sdc.lock);
+ rwlock_init(&hp_sdc.ibf_lock);
+ rwlock_init(&hp_sdc.rtq_lock);
+ rwlock_init(&hp_sdc.hook_lock);
+
+ hp_sdc.timer = NULL;
+ hp_sdc.hil = NULL;
+ hp_sdc.pup = NULL;
+ hp_sdc.cooked = NULL;
+ hp_sdc.im = HP_SDC_IM_MASK; /* Mask maskable irqs */
+ hp_sdc.set_im = 1;
+ hp_sdc.wi = 0xff;
+ hp_sdc.r7[0] = 0xff;
+ hp_sdc.r7[1] = 0xff;
+ hp_sdc.r7[2] = 0xff;
+ hp_sdc.r7[3] = 0xff;
+ hp_sdc.ibf = 1;
+
+ for (i = 0; i < HP_SDC_QUEUE_LEN; i++) hp_sdc.tq[i] = NULL;
+ hp_sdc.wcurr = -1;
+ hp_sdc.rcurr = -1;
+ hp_sdc.rqty = 0;
+
+ hp_sdc.dev_err = -ENODEV;
+
+ errstr = "IO not found for";
+ if (!hp_sdc.base_io) goto err0;
+
+ errstr = "IRQ not found for";
+ if (!hp_sdc.irq) goto err0;
+
+ hp_sdc.dev_err = -EBUSY;
+
+#if defined(__hppa__)
+ errstr = "IO not available for";
+ if (request_region(hp_sdc.data_io, 2, hp_sdc_driver.name)) goto err0;
+#endif
+
+ errstr = "IRQ not available for";
+ if(request_irq(hp_sdc.irq, &hp_sdc_isr, 0, "HP SDC",
+ (void *) hp_sdc.base_io)) goto err1;
+
+ errstr = "NMI not available for";
+ if (request_irq(hp_sdc.nmi, &hp_sdc_nmisr, 0, "HP SDC NMI",
+ (void *) hp_sdc.base_io)) goto err2;
+
+ printk(KERN_INFO PREFIX "HP SDC at 0x%p, IRQ %d (NMI IRQ %d)\n",
+ (void *)hp_sdc.base_io, hp_sdc.irq, hp_sdc.nmi);
+
+ hp_sdc_status_in8();
+ hp_sdc_data_in8();
+
+ tasklet_init(&hp_sdc.task, hp_sdc_tasklet, 0);
+
+ /* Sync the output buffer registers, thus scheduling hp_sdc_tasklet. */
+ t_sync.actidx = 0;
+ t_sync.idx = 1;
+ t_sync.endidx = 6;
+ t_sync.seq = ts_sync;
+ ts_sync[0] = HP_SDC_ACT_DATAREG | HP_SDC_ACT_SEMAPHORE;
+ ts_sync[1] = 0x0f;
+ ts_sync[2] = ts_sync[3] = ts_sync[4] = ts_sync[5] = 0;
+ t_sync.act.semaphore = &s_sync;
+ init_MUTEX_LOCKED(&s_sync);
+ hp_sdc_enqueue_transaction(&t_sync);
+ down(&s_sync); /* Wait for t_sync to complete */
+
+ /* Create the keepalive task */
+ init_timer(&hp_sdc.kicker);
+ hp_sdc.kicker.expires = jiffies + HZ;
+ hp_sdc.kicker.function = &hp_sdc_kicker;
+ add_timer(&hp_sdc.kicker);
+
+ hp_sdc.dev_err = 0;
+ return 0;
+ err2:
+ free_irq(hp_sdc.irq, NULL);
+ err1:
+ release_region(hp_sdc.data_io, 2);
+ err0:
+ printk(KERN_WARNING PREFIX ": %s SDC IO=0x%p IRQ=0x%x NMI=0x%x\n",
+ errstr, (void *)hp_sdc.base_io, hp_sdc.irq, hp_sdc.nmi);
+ hp_sdc.dev = NULL;
+ return hp_sdc.dev_err;
+}
+
+#if defined(__hppa__)
+
+static int __init hp_sdc_init_hppa(struct parisc_device *d)
+{
+ if (!d) return 1;
+ if (hp_sdc.dev != NULL) return 1; /* We only expect one SDC */
+
+ hp_sdc.dev = d;
+ hp_sdc.irq = d->irq;
+ hp_sdc.nmi = d->aux_irq;
+ hp_sdc.base_io = d->hpa;
+ hp_sdc.data_io = d->hpa + 0x800;
+ hp_sdc.status_io = d->hpa + 0x801;
+
+ return hp_sdc_init();
+}
+
+#endif /* __hppa__ */
+
+#if !defined(__mc68000__) /* Link error on m68k! */
+static void __exit hp_sdc_exit(void)
+#else
+static void hp_sdc_exit(void)
+#endif
+{
+ write_lock_irq(&hp_sdc.lock);
+
+ /* Turn off all maskable "sub-function" irq's. */
+ hp_sdc_spin_ibf();
+ sdc_writeb(HP_SDC_CMD_SET_IM | HP_SDC_IM_MASK, hp_sdc.status_io);
+
+ /* Wait until we know this has been processed by the i8042 */
+ hp_sdc_spin_ibf();
+
+ free_irq(hp_sdc.nmi, NULL);
+ free_irq(hp_sdc.irq, NULL);
+ write_unlock_irq(&hp_sdc.lock);
+
+ del_timer(&hp_sdc.kicker);
+
+ tasklet_kill(&hp_sdc.task);
+
+/* release_region(hp_sdc.data_io, 2); */
+
+#if defined(__hppa__)
+ if (unregister_parisc_driver(&hp_sdc_driver))
+ printk(KERN_WARNING PREFIX "Error unregistering HP SDC");
+#endif
+}
+
+static int __init hp_sdc_register(void)
+{
+ hp_sdc_transaction tq_init;
+ uint8_t tq_init_seq[5];
+ struct semaphore tq_init_sem;
+#if defined(__mc68000__)
+ mm_segment_t fs;
+ unsigned char i;
+#endif
+
+ hp_sdc.dev = NULL;
+ hp_sdc.dev_err = 0;
+#if defined(__hppa__)
+ if (register_parisc_driver(&hp_sdc_driver)) {
+ printk(KERN_WARNING PREFIX "Error registering SDC with system bus tree.\n");
+ return -ENODEV;
+ }
+#elif defined(__mc68000__)
+ if (!MACH_IS_HP300)
+ return -ENODEV;
+
+ hp_sdc.irq = 1;
+ hp_sdc.nmi = 7;
+ hp_sdc.base_io = (unsigned long) 0xf0428000;
+ hp_sdc.data_io = (unsigned long) hp_sdc.base_io + 1;
+ hp_sdc.status_io = (unsigned long) hp_sdc.base_io + 3;
+ fs = get_fs();
+ set_fs(KERNEL_DS);
+ if (!get_user(i, (unsigned char *)hp_sdc.data_io))
+ hp_sdc.dev = (void *)1;
+ set_fs(fs);
+ hp_sdc.dev_err = hp_sdc_init();
+#endif
+ if (hp_sdc.dev == NULL) {
+ printk(KERN_WARNING PREFIX "No SDC found.\n");
+ return hp_sdc.dev_err;
+ }
+
+ init_MUTEX_LOCKED(&tq_init_sem);
+
+ tq_init.actidx = 0;
+ tq_init.idx = 1;
+ tq_init.endidx = 5;
+ tq_init.seq = tq_init_seq;
+ tq_init.act.semaphore = &tq_init_sem;
+
+ tq_init_seq[0] =
+ HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN | HP_SDC_ACT_SEMAPHORE;
+ tq_init_seq[1] = HP_SDC_CMD_READ_KCC;
+ tq_init_seq[2] = 1;
+ tq_init_seq[3] = 0;
+ tq_init_seq[4] = 0;
+
+ hp_sdc_enqueue_transaction(&tq_init);
+
+ down(&tq_init_sem);
+ up(&tq_init_sem);
+
+ if ((tq_init_seq[0] & HP_SDC_ACT_DEAD) == HP_SDC_ACT_DEAD) {
+ printk(KERN_WARNING PREFIX "Error reading config byte.\n");
+ hp_sdc_exit();
+ return -ENODEV;
+ }
+ hp_sdc.r11 = tq_init_seq[4];
+ if (hp_sdc.r11 & HP_SDC_CFG_NEW) {
+ char *str;
+ printk(KERN_INFO PREFIX "New style SDC\n");
+ tq_init_seq[1] = HP_SDC_CMD_READ_XTD;
+ tq_init.actidx = 0;
+ tq_init.idx = 1;
+ down(&tq_init_sem);
+ hp_sdc_enqueue_transaction(&tq_init);
+ down(&tq_init_sem);
+ up(&tq_init_sem);
+ if ((tq_init_seq[0] & HP_SDC_ACT_DEAD) == HP_SDC_ACT_DEAD) {
+ printk(KERN_WARNING PREFIX "Error reading extended config byte.\n");
+ return -ENODEV;
+ }
+ hp_sdc.r7e = tq_init_seq[4];
+ HP_SDC_XTD_REV_STRINGS(hp_sdc.r7e & HP_SDC_XTD_REV, str)
+ printk(KERN_INFO PREFIX "Revision: %s\n", str);
+ if (hp_sdc.r7e & HP_SDC_XTD_BEEPER) {
+ printk(KERN_INFO PREFIX "TI SN76494 beeper present\n");
+ }
+ if (hp_sdc.r7e & HP_SDC_XTD_BBRTC) {
+ printk(KERN_INFO PREFIX "OKI MSM-58321 BBRTC present\n");
+ }
+ printk(KERN_INFO PREFIX "Spunking the self test register to force PUP "
+ "on next firmware reset.\n");
+ tq_init_seq[0] = HP_SDC_ACT_PRECMD |
+ HP_SDC_ACT_DATAOUT | HP_SDC_ACT_SEMAPHORE;
+ tq_init_seq[1] = HP_SDC_CMD_SET_STR;
+ tq_init_seq[2] = 1;
+ tq_init_seq[3] = 0;
+ tq_init.actidx = 0;
+ tq_init.idx = 1;
+ tq_init.endidx = 4;
+ down(&tq_init_sem);
+ hp_sdc_enqueue_transaction(&tq_init);
+ down(&tq_init_sem);
+ up(&tq_init_sem);
+ }
+ else {
+ printk(KERN_INFO PREFIX "Old style SDC (1820-%s).\n",
+ (hp_sdc.r11 & HP_SDC_CFG_REV) ? "3300" : "2564/3087");
+ }
+
+ return 0;
+}
+
+module_init(hp_sdc_register);
+module_exit(hp_sdc_exit);
+
+/* Timing notes: These measurements taken on my 64MHz 7100-LC (715/64)
+ * cycles cycles-adj time
+ * between two consecutive mfctl(16)'s: 4 n/a 63ns
+ * hp_sdc_spin_ibf when idle: 119 115 1.7us
+ * gsc_writeb status register: 83 79 1.2us
+ * IBF to clear after sending SET_IM: 6204 6006 93us
+ * IBF to clear after sending LOAD_RT: 4467 4352 68us
+ * IBF to clear after sending two LOAD_RTs: 18974 18859 295us
+ * READ_T1, read status/data, IRQ, call handler: 35564 n/a 556us
+ * cmd to ~IBF READ_T1 2nd time right after: 5158403 n/a 81ms
+ * between IRQ received and ~IBF for above: 2578877 n/a 40ms
+ *
+ * Performance stats after a run of this module configuring HIL and
+ * receiving a few mouse events:
+ *
+ * status in8 282508 cycles 7128 calls
+ * status out8 8404 cycles 341 calls
+ * data out8 1734 cycles 78 calls
+ * isr 174324 cycles 617 calls (includes take)
+ * take 1241 cycles 2 calls
+ * put 1411504 cycles 6937 calls
+ * task 1655209 cycles 6937 calls (includes put)
+ *
+ */
diff --git a/drivers/input/serio/hp_sdc_mlc.c b/drivers/input/serio/hp_sdc_mlc.c
new file mode 100644
index 0000000000000..e3c44ffae6742
--- /dev/null
+++ b/drivers/input/serio/hp_sdc_mlc.c
@@ -0,0 +1,358 @@
+/*
+ * Access to HP-HIL MLC through HP System Device Controller.
+ *
+ * Copyright (c) 2001 Brian S. Julin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. The name of the author may not 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").
+ *
+ * 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
+ *
+ * References:
+ * HP-HIL Technical Reference Manual. Hewlett Packard Product No. 45918A
+ * System Device Controller Microprocessor Firmware Theory of Operation
+ * for Part Number 1820-4784 Revision B. Dwg No. A-1820-4784-2
+ *
+ */
+
+#include <linux/hil_mlc.h>
+#include <linux/hp_sdc.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/string.h>
+
+#define PREFIX "HP SDC MLC: "
+
+static hil_mlc hp_sdc_mlc;
+
+MODULE_AUTHOR("Brian S. Julin <bri@calyx.com>");
+MODULE_DESCRIPTION("Glue for onboard HIL MLC in HP-PARISC machines");
+MODULE_LICENSE("Dual BSD/GPL");
+
+struct hp_sdc_mlc_priv_s {
+ int emtestmode;
+ hp_sdc_transaction trans;
+ u8 tseq[16];
+ int got5x;
+} hp_sdc_mlc_priv;
+
+/************************* Interrupt context ******************************/
+static void hp_sdc_mlc_isr (int irq, void *dev_id,
+ uint8_t status, uint8_t data) {
+ int idx;
+ hil_mlc *mlc = &hp_sdc_mlc;
+
+ write_lock(&(mlc->lock));
+ if (mlc->icount < 0) {
+ printk(KERN_WARNING PREFIX "HIL Overflow!\n");
+ up(&mlc->isem);
+ goto out;
+ }
+ idx = 15 - mlc->icount;
+ if ((status & HP_SDC_STATUS_IRQMASK) == HP_SDC_STATUS_HILDATA) {
+ mlc->ipacket[idx] |= data | HIL_ERR_INT;
+ mlc->icount--;
+ if (hp_sdc_mlc_priv.got5x) goto check;
+ if (!idx) goto check;
+ if ((mlc->ipacket[idx-1] & HIL_PKT_ADDR_MASK) !=
+ (mlc->ipacket[idx] & HIL_PKT_ADDR_MASK)) {
+ mlc->ipacket[idx] &= ~HIL_PKT_ADDR_MASK;
+ mlc->ipacket[idx] |= (mlc->ipacket[idx-1]
+ & HIL_PKT_ADDR_MASK);
+ }
+ goto check;
+ }
+ /* We know status is 5X */
+ if (data & HP_SDC_HIL_ISERR) goto err;
+ mlc->ipacket[idx] =
+ (data & HP_SDC_HIL_R1MASK) << HIL_PKT_ADDR_SHIFT;
+ hp_sdc_mlc_priv.got5x = 1;
+ goto out;
+
+ check:
+ hp_sdc_mlc_priv.got5x = 0;
+ if (mlc->imatch == 0) goto done;
+ if ((mlc->imatch == (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL))
+ && (mlc->ipacket[idx] == (mlc->imatch | idx))) goto done;
+ if (mlc->ipacket[idx] == mlc->imatch) goto done;
+ goto out;
+
+ err:
+ printk(KERN_DEBUG PREFIX "err code %x\n", data);
+ switch (data) {
+ case HP_SDC_HIL_RC_DONE:
+ printk(KERN_WARNING PREFIX "Bastard SDC reconfigured loop!\n");
+ break;
+ case HP_SDC_HIL_ERR:
+ mlc->ipacket[idx] |= HIL_ERR_INT | HIL_ERR_PERR |
+ HIL_ERR_FERR | HIL_ERR_FOF;
+ break;
+ case HP_SDC_HIL_TO:
+ mlc->ipacket[idx] |= HIL_ERR_INT | HIL_ERR_LERR;
+ break;
+ case HP_SDC_HIL_RC:
+ printk(KERN_WARNING PREFIX "Bastard SDC decided to reconfigure loop!\n");
+ break;
+ default:
+ printk(KERN_WARNING PREFIX "Unkown HIL Error status (%x)!\n", data);
+ break;
+ }
+ /* No more data will be coming due to an error. */
+ done:
+ tasklet_schedule(mlc->tasklet);
+ up(&(mlc->isem));
+ out:
+ write_unlock(&(mlc->lock));
+}
+
+
+/******************** Tasklet or userspace context functions ****************/
+
+static int hp_sdc_mlc_in (hil_mlc *mlc, suseconds_t timeout) {
+ unsigned long flags;
+ struct hp_sdc_mlc_priv_s *priv;
+ int rc = 2;
+
+ priv = mlc->priv;
+
+ write_lock_irqsave(&(mlc->lock), flags);
+
+ /* Try to down the semaphore */
+ if (down_trylock(&(mlc->isem))) {
+ struct timeval tv;
+ if (priv->emtestmode) {
+ mlc->ipacket[0] =
+ HIL_ERR_INT | (mlc->opacket &
+ (HIL_PKT_CMD |
+ HIL_PKT_ADDR_MASK |
+ HIL_PKT_DATA_MASK));
+ mlc->icount = 14;
+ /* printk(KERN_DEBUG PREFIX ">[%x]\n", mlc->ipacket[0]); */
+ goto wasup;
+ }
+ do_gettimeofday(&tv);
+ tv.tv_usec += 1000000 * (tv.tv_sec - mlc->instart.tv_sec);
+ if (tv.tv_usec - mlc->instart.tv_usec > mlc->intimeout) {
+ /* printk("!%i %i",
+ tv.tv_usec - mlc->instart.tv_usec,
+ mlc->intimeout);
+ */
+ rc = 1;
+ up(&(mlc->isem));
+ }
+ goto done;
+ }
+ wasup:
+ up(&(mlc->isem));
+ rc = 0;
+ goto done;
+ done:
+ write_unlock_irqrestore(&(mlc->lock), flags);
+ return rc;
+}
+
+static int hp_sdc_mlc_cts (hil_mlc *mlc) {
+ struct hp_sdc_mlc_priv_s *priv;
+ unsigned long flags;
+
+ priv = mlc->priv;
+
+ write_lock_irqsave(&(mlc->lock), flags);
+
+ /* Try to down the semaphores -- they should be up. */
+ if (down_trylock(&(mlc->isem))) {
+ BUG();
+ goto busy;
+ }
+ if (down_trylock(&(mlc->osem))) {
+ BUG();
+ up(&(mlc->isem));
+ goto busy;
+ }
+ up(&(mlc->isem));
+ up(&(mlc->osem));
+
+ if (down_trylock(&(mlc->csem))) {
+ if (priv->trans.act.semaphore != &(mlc->csem)) goto poll;
+ goto busy;
+ }
+ if (!(priv->tseq[4] & HP_SDC_USE_LOOP)) goto done;
+
+ poll:
+ priv->trans.act.semaphore = &(mlc->csem);
+ priv->trans.actidx = 0;
+ priv->trans.idx = 1;
+ priv->trans.endidx = 5;
+ priv->tseq[0] =
+ HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN | HP_SDC_ACT_SEMAPHORE;
+ priv->tseq[1] = HP_SDC_CMD_READ_USE;
+ priv->tseq[2] = 1;
+ priv->tseq[3] = 0;
+ priv->tseq[4] = 0;
+ hp_sdc_enqueue_transaction(&(priv->trans));
+ busy:
+ write_unlock_irqrestore(&(mlc->lock), flags);
+ return 1;
+ done:
+ priv->trans.act.semaphore = &(mlc->osem);
+ up(&(mlc->csem));
+ write_unlock_irqrestore(&(mlc->lock), flags);
+ return 0;
+}
+
+static void hp_sdc_mlc_out (hil_mlc *mlc) {
+ struct hp_sdc_mlc_priv_s *priv;
+ unsigned long flags;
+
+ priv = mlc->priv;
+
+ write_lock_irqsave(&(mlc->lock), flags);
+
+ /* Try to down the semaphore -- it should be up. */
+ if (down_trylock(&(mlc->osem))) {
+ BUG();
+ goto done;
+ }
+
+ if (mlc->opacket & HIL_DO_ALTER_CTRL) goto do_control;
+
+ do_data:
+ if (priv->emtestmode) {
+ up(&(mlc->osem));
+ goto done;
+ }
+ /* Shouldn't be sending commands when loop may be busy */
+ if (down_trylock(&(mlc->csem))) {
+ BUG();
+ goto done;
+ }
+ up(&(mlc->csem));
+
+ priv->trans.actidx = 0;
+ priv->trans.idx = 1;
+ priv->trans.act.semaphore = &(mlc->osem);
+ priv->trans.endidx = 6;
+ priv->tseq[0] =
+ HP_SDC_ACT_DATAREG | HP_SDC_ACT_POSTCMD | HP_SDC_ACT_SEMAPHORE;
+ priv->tseq[1] = 0x7;
+ priv->tseq[2] =
+ (mlc->opacket &
+ (HIL_PKT_ADDR_MASK | HIL_PKT_CMD))
+ >> HIL_PKT_ADDR_SHIFT;
+ priv->tseq[3] =
+ (mlc->opacket & HIL_PKT_DATA_MASK)
+ >> HIL_PKT_DATA_SHIFT;
+ priv->tseq[4] = 0; /* No timeout */
+ if (priv->tseq[3] == HIL_CMD_DHR) priv->tseq[4] = 1;
+ priv->tseq[5] = HP_SDC_CMD_DO_HIL;
+ goto enqueue;
+
+ do_control:
+ priv->emtestmode = mlc->opacket & HIL_CTRL_TEST;
+ if ((mlc->opacket & (HIL_CTRL_APE | HIL_CTRL_IPF)) == HIL_CTRL_APE) {
+ BUG(); /* we cannot emulate this, it should not be used. */
+ }
+ if ((mlc->opacket & HIL_CTRL_ONLY) == HIL_CTRL_ONLY) goto control_only;
+ if (mlc->opacket & HIL_CTRL_APE) {
+ BUG(); /* Should not send command/data after engaging APE */
+ goto done;
+ }
+ /* Disengaging APE this way would not be valid either since
+ * the loop must be allowed to idle.
+ *
+ * So, it works out that we really never actually send control
+ * and data when using SDC, we just send the data.
+ */
+ goto do_data;
+
+ control_only:
+ priv->trans.actidx = 0;
+ priv->trans.idx = 1;
+ priv->trans.act.semaphore = &(mlc->osem);
+ priv->trans.endidx = 4;
+ priv->tseq[0] =
+ HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT | HP_SDC_ACT_SEMAPHORE;
+ priv->tseq[1] = HP_SDC_CMD_SET_LPC;
+ priv->tseq[2] = 1;
+ // priv->tseq[3] = (mlc->ddc + 1) | HP_SDC_LPS_ACSUCC;
+ priv->tseq[3] = 0;
+ if (mlc->opacket & HIL_CTRL_APE) {
+ priv->tseq[3] |= HP_SDC_LPC_APE_IPF;
+ down_trylock(&(mlc->csem));
+ }
+ enqueue:
+ hp_sdc_enqueue_transaction(&(priv->trans));
+ done:
+ write_unlock_irqrestore(&(mlc->lock), flags);
+}
+
+static int __init hp_sdc_mlc_init(void)
+{
+ hil_mlc *mlc = &hp_sdc_mlc;
+
+ printk(KERN_INFO PREFIX "Registering the System Domain Controller's HIL MLC.\n");
+
+ hp_sdc_mlc_priv.emtestmode = 0;
+ hp_sdc_mlc_priv.trans.seq = hp_sdc_mlc_priv.tseq;
+ hp_sdc_mlc_priv.trans.act.semaphore = &(mlc->osem);
+ hp_sdc_mlc_priv.got5x = 0;
+
+ mlc->cts = &hp_sdc_mlc_cts;
+ mlc->in = &hp_sdc_mlc_in;
+ mlc->out = &hp_sdc_mlc_out;
+
+ if (hil_mlc_register(mlc)) {
+ printk(KERN_WARNING PREFIX "Failed to register MLC structure with hil_mlc\n");
+ goto err0;
+ }
+ mlc->priv = &hp_sdc_mlc_priv;
+
+ if (hp_sdc_request_hil_irq(&hp_sdc_mlc_isr)) {
+ printk(KERN_WARNING PREFIX "Request for raw HIL ISR hook denied\n");
+ goto err1;
+ }
+ return 0;
+ err1:
+ if (hil_mlc_unregister(mlc)) {
+ printk(KERN_ERR PREFIX "Failed to unregister MLC structure with hil_mlc.\n"
+ "This is bad. Could cause an oops.\n");
+ }
+ err0:
+ return -EBUSY;
+}
+
+static void __exit hp_sdc_mlc_exit(void)
+{
+ hil_mlc *mlc = &hp_sdc_mlc;
+ if (hp_sdc_release_hil_irq(&hp_sdc_mlc_isr)) {
+ printk(KERN_ERR PREFIX "Failed to release the raw HIL ISR hook.\n"
+ "This is bad. Could cause an oops.\n");
+ }
+ if (hil_mlc_unregister(mlc)) {
+ printk(KERN_ERR PREFIX "Failed to unregister MLC structure with hil_mlc.\n"
+ "This is bad. Could cause an oops.\n");
+ }
+}
+
+module_init(hp_sdc_mlc_init);
+module_exit(hp_sdc_mlc_exit);
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h
index d878a10f88571..f64867808fea9 100644
--- a/drivers/input/serio/i8042-x86ia64io.h
+++ b/drivers/input/serio/i8042-x86ia64io.h
@@ -67,7 +67,7 @@ static inline void i8042_write_command(int val)
#include <linux/dmi.h>
-static struct dmi_system_id __initdata i8042_dmi_table[] = {
+static struct dmi_system_id __initdata i8042_dmi_noloop_table[] = {
{
.ident = "Compaq Proliant 8500",
.matches = {
@@ -86,186 +86,208 @@ static struct dmi_system_id __initdata i8042_dmi_table[] = {
},
{ }
};
+
+/*
+ * Some Fujitsu notebooks are ahving trouble with touhcpads if
+ * active multiplexing mode is activated. Luckily they don't have
+ * external PS/2 ports so we can safely disable it.
+ */
+static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = {
+ {
+ .ident = "Fujitsu Lifebook P7010/P7010D",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "P7010"),
+ },
+ },
+ {
+ .ident = "Fujitsu Lifebook P5020D",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook P Series"),
+ },
+ },
+ {
+ .ident = "Fujitsu Lifebook S2000",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook S Series"),
+ },
+ },
+ {
+ .ident = "Fujitsu T70H",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "FMVLT70H"),
+ },
+ },
+ { }
+};
+
+
+
#endif
-#ifdef CONFIG_ACPI
-#include <linux/acpi.h>
-#include <acpi/acpi_bus.h>
-struct i8042_acpi_resources {
- unsigned int port1;
- unsigned int port2;
- unsigned int irq;
-};
+#ifdef CONFIG_PNP
+#include <linux/pnp.h>
-static int i8042_acpi_kbd_registered;
-static int i8042_acpi_aux_registered;
+static int i8042_pnp_kbd_registered;
+static int i8042_pnp_aux_registered;
-static acpi_status i8042_acpi_parse_resource(struct acpi_resource *res, void *data)
-{
- struct i8042_acpi_resources *i8042_res = data;
- struct acpi_resource_io *io;
- struct acpi_resource_fixed_io *fixed_io;
- struct acpi_resource_irq *irq;
- struct acpi_resource_ext_irq *ext_irq;
-
- switch (res->id) {
- case ACPI_RSTYPE_IO:
- io = &res->data.io;
- if (io->range_length) {
- if (!i8042_res->port1)
- i8042_res->port1 = io->min_base_address;
- else
- i8042_res->port2 = io->min_base_address;
- }
- break;
-
- case ACPI_RSTYPE_FIXED_IO:
- fixed_io = &res->data.fixed_io;
- if (fixed_io->range_length) {
- if (!i8042_res->port1)
- i8042_res->port1 = fixed_io->base_address;
- else
- i8042_res->port2 = fixed_io->base_address;
- }
- break;
-
- case ACPI_RSTYPE_IRQ:
- irq = &res->data.irq;
- if (irq->number_of_interrupts > 0)
- i8042_res->irq =
- acpi_register_gsi(irq->interrupts[0],
- irq->edge_level,
- irq->active_high_low);
- break;
-
- case ACPI_RSTYPE_EXT_IRQ:
- ext_irq = &res->data.extended_irq;
- if (ext_irq->number_of_interrupts > 0)
- i8042_res->irq =
- acpi_register_gsi(ext_irq->interrupts[0],
- ext_irq->edge_level,
- ext_irq->active_high_low);
- break;
- }
- return AE_OK;
-}
+static int i8042_pnp_command_reg;
+static int i8042_pnp_data_reg;
+static int i8042_pnp_kbd_irq;
+static int i8042_pnp_aux_irq;
-static int i8042_acpi_kbd_add(struct acpi_device *device)
+static char i8042_pnp_kbd_name[32];
+static char i8042_pnp_aux_name[32];
+
+static int i8042_pnp_kbd_probe(struct pnp_dev *dev, const struct pnp_device_id *did)
{
- struct i8042_acpi_resources kbd_res;
- acpi_status status;
+ if (pnp_port_valid(dev, 0) && pnp_port_len(dev, 0) == 1)
+ i8042_pnp_data_reg = pnp_port_start(dev,0);
- memset(&kbd_res, 0, sizeof(kbd_res));
- status = acpi_walk_resources(device->handle, METHOD_NAME__CRS,
- i8042_acpi_parse_resource, &kbd_res);
- if (ACPI_FAILURE(status))
- return -ENODEV;
+ if (pnp_port_valid(dev, 1) && pnp_port_len(dev, 1) == 1)
+ i8042_pnp_command_reg = pnp_port_start(dev, 1);
- if (kbd_res.port1)
- i8042_data_reg = kbd_res.port1;
- else
- printk(KERN_WARNING "ACPI: [%s] has no data port; default is 0x%x\n",
- acpi_device_bid(device), i8042_data_reg);
-
- if (kbd_res.port2)
- i8042_command_reg = kbd_res.port2;
- else
- printk(KERN_WARNING "ACPI: [%s] has no command port; default is 0x%x\n",
- acpi_device_bid(device), i8042_command_reg);
-
- if (kbd_res.irq)
- i8042_kbd_irq = kbd_res.irq;
- else
- printk(KERN_WARNING "ACPI: [%s] has no IRQ; default is %d\n",
- acpi_device_bid(device), i8042_kbd_irq);
-
- strncpy(acpi_device_name(device), "PS/2 Keyboard Controller",
- sizeof(acpi_device_name(device)));
- printk("ACPI: %s [%s] at I/O 0x%x, 0x%x, irq %d\n",
- acpi_device_name(device), acpi_device_bid(device),
- i8042_data_reg, i8042_command_reg, i8042_kbd_irq);
+ if (pnp_irq_valid(dev,0))
+ i8042_pnp_kbd_irq = pnp_irq(dev, 0);
+
+ strncpy(i8042_pnp_kbd_name, did->id, sizeof(i8042_pnp_kbd_name));
+ if (strlen(pnp_dev_name(dev))) {
+ strncat(i8042_pnp_kbd_name, ":", sizeof(i8042_pnp_kbd_name));
+ strncat(i8042_pnp_kbd_name, pnp_dev_name(dev), sizeof(i8042_pnp_kbd_name));
+ }
return 0;
}
-static int i8042_acpi_aux_add(struct acpi_device *device)
+static int i8042_pnp_aux_probe(struct pnp_dev *dev, const struct pnp_device_id *did)
{
- struct i8042_acpi_resources aux_res;
- acpi_status status;
+ if (pnp_port_valid(dev, 0) && pnp_port_len(dev, 0) == 1)
+ i8042_pnp_data_reg = pnp_port_start(dev,0);
- memset(&aux_res, 0, sizeof(aux_res));
- status = acpi_walk_resources(device->handle, METHOD_NAME__CRS,
- i8042_acpi_parse_resource, &aux_res);
- if (ACPI_FAILURE(status))
- return -ENODEV;
+ if (pnp_port_valid(dev, 1) && pnp_port_len(dev, 1) == 1)
+ i8042_pnp_command_reg = pnp_port_start(dev, 1);
- if (aux_res.irq)
- i8042_aux_irq = aux_res.irq;
- else
- printk(KERN_WARNING "ACPI: [%s] has no IRQ; default is %d\n",
- acpi_device_bid(device), i8042_aux_irq);
+ if (pnp_irq_valid(dev, 0))
+ i8042_pnp_aux_irq = pnp_irq(dev, 0);
- strncpy(acpi_device_name(device), "PS/2 Mouse Controller",
- sizeof(acpi_device_name(device)));
- printk("ACPI: %s [%s] at irq %d\n",
- acpi_device_name(device), acpi_device_bid(device), i8042_aux_irq);
+ strncpy(i8042_pnp_aux_name, did->id, sizeof(i8042_pnp_aux_name));
+ if (strlen(pnp_dev_name(dev))) {
+ strncat(i8042_pnp_aux_name, ":", sizeof(i8042_pnp_aux_name));
+ strncat(i8042_pnp_aux_name, pnp_dev_name(dev), sizeof(i8042_pnp_aux_name));
+ }
return 0;
}
-static struct acpi_driver i8042_acpi_kbd_driver = {
- .name = "i8042",
- .ids = "PNP0303,PNP030B",
- .ops = {
- .add = i8042_acpi_kbd_add,
- },
+static struct pnp_device_id pnp_kbd_devids[] = {
+ { .id = "PNP0303", .driver_data = 0 },
+ { .id = "PNP030b", .driver_data = 0 },
+ { .id = "", },
};
-static struct acpi_driver i8042_acpi_aux_driver = {
- .name = "i8042",
- .ids = "PNP0F13,SYN0801",
- .ops = {
- .add = i8042_acpi_aux_add,
- },
+static struct pnp_driver i8042_pnp_kbd_driver = {
+ .name = "i8042 kbd",
+ .id_table = pnp_kbd_devids,
+ .probe = i8042_pnp_kbd_probe,
+};
+
+static struct pnp_device_id pnp_aux_devids[] = {
+ { .id = "PNP0f03", .driver_data = 0 },
+ { .id = "PNP0f0b", .driver_data = 0 },
+ { .id = "PNP0f0e", .driver_data = 0 },
+ { .id = "PNP0f12", .driver_data = 0 },
+ { .id = "PNP0f13", .driver_data = 0 },
+ { .id = "PNP0f19", .driver_data = 0 },
+ { .id = "PNP0f1c", .driver_data = 0 },
+ { .id = "SYN0801", .driver_data = 0 },
+ { .id = "", },
+};
+
+static struct pnp_driver i8042_pnp_aux_driver = {
+ .name = "i8042 aux",
+ .id_table = pnp_aux_devids,
+ .probe = i8042_pnp_aux_probe,
};
-static int i8042_acpi_init(void)
+static void i8042_pnp_exit(void)
{
- int result;
+ if (i8042_pnp_kbd_registered)
+ pnp_unregister_driver(&i8042_pnp_kbd_driver);
- if (acpi_disabled || i8042_noacpi) {
- printk("i8042: ACPI detection disabled\n");
+ if (i8042_pnp_aux_registered)
+ pnp_unregister_driver(&i8042_pnp_aux_driver);
+}
+
+static int i8042_pnp_init(void)
+{
+ int result_kbd, result_aux;
+
+ if (i8042_nopnp) {
+ printk("i8042: PNP detection disabled\n");
return 0;
}
- result = acpi_bus_register_driver(&i8042_acpi_kbd_driver);
- if (result < 0)
- return result;
+ if ((result_kbd = pnp_register_driver(&i8042_pnp_kbd_driver)) >= 0)
+ i8042_pnp_kbd_registered = 1;
+ if ((result_aux = pnp_register_driver(&i8042_pnp_aux_driver)) >= 0)
+ i8042_pnp_aux_registered = 1;
- if (result == 0) {
- acpi_bus_unregister_driver(&i8042_acpi_kbd_driver);
+ if (result_kbd <= 0 && result_aux <= 0) {
+ i8042_pnp_exit();
+#if defined(__ia64__)
return -ENODEV;
+#else
+ printk(KERN_WARNING "PNP: No PS/2 controller found. Probing ports directly.\n");
+ return 0;
+#endif
}
- i8042_acpi_kbd_registered = 1;
- result = acpi_bus_register_driver(&i8042_acpi_aux_driver);
- if (result >= 0)
- i8042_acpi_aux_registered = 1;
- if (result == 0)
+ if (((i8042_pnp_data_reg & ~0xf) == (i8042_data_reg & ~0xf) &&
+ i8042_pnp_data_reg != i8042_data_reg) || !i8042_pnp_data_reg) {
+ printk(KERN_WARNING "PNP: PS/2 controller has invalid data port %#x; using default %#x\n",
+ i8042_pnp_data_reg, i8042_data_reg);
+ i8042_pnp_data_reg = i8042_data_reg;
+ }
+
+ if (((i8042_pnp_command_reg & ~0xf) == (i8042_command_reg & ~0xf) &&
+ i8042_pnp_command_reg != i8042_command_reg) || !i8042_pnp_command_reg) {
+ printk(KERN_WARNING "PNP: PS/2 controller has invalid command port %#x; using default %#x\n",
+ i8042_pnp_command_reg, i8042_command_reg);
+ i8042_pnp_command_reg = i8042_command_reg;
+ }
+
+ if (!i8042_pnp_kbd_irq) {
+ printk(KERN_WARNING "PNP: PS/2 controller doesn't have KBD irq; using default %#x\n", i8042_kbd_irq);
+ i8042_pnp_kbd_irq = i8042_kbd_irq;
+ }
+
+ if (result_aux > 0 && !i8042_pnp_aux_irq) {
+ printk(KERN_WARNING "PNP: PS/2 controller doesn't have AUX irq; using default %#x\n", i8042_aux_irq);
+ i8042_pnp_aux_irq = i8042_aux_irq;
+ }
+
+#if defined(__ia64__)
+ if (result_aux <= 0)
i8042_noaux = 1;
+#endif
- return 0;
-}
+ i8042_data_reg = i8042_pnp_data_reg;
+ i8042_command_reg = i8042_pnp_command_reg;
+ i8042_kbd_irq = i8042_pnp_kbd_irq;
+ i8042_aux_irq = i8042_pnp_aux_irq;
-static void i8042_acpi_exit(void)
-{
- if (i8042_acpi_kbd_registered)
- acpi_bus_unregister_driver(&i8042_acpi_kbd_driver);
+ printk(KERN_INFO "PNP: PS/2 Controller [%s%s%s] at %#x,%#x irq %d%s%d\n",
+ i8042_pnp_kbd_name, (result_kbd > 0 && result_aux > 0) ? "," : "", i8042_pnp_aux_name,
+ i8042_data_reg, i8042_command_reg, i8042_kbd_irq,
+ (result_aux > 0) ? "," : "", i8042_aux_irq);
- if (i8042_acpi_aux_registered)
- acpi_bus_unregister_driver(&i8042_acpi_aux_driver);
+ return 0;
}
+
#endif
static inline int i8042_platform_init(void)
@@ -281,8 +303,8 @@ static inline int i8042_platform_init(void)
i8042_kbd_irq = I8042_MAP_IRQ(1);
i8042_aux_irq = I8042_MAP_IRQ(12);
-#ifdef CONFIG_ACPI
- if (i8042_acpi_init())
+#ifdef CONFIG_PNP
+ if (i8042_pnp_init())
return -1;
#endif
@@ -291,8 +313,11 @@ static inline int i8042_platform_init(void)
#endif
#if defined(__i386__)
- if (dmi_check_system(i8042_dmi_table))
+ if (dmi_check_system(i8042_dmi_noloop_table))
i8042_noloop = 1;
+
+ if (dmi_check_system(i8042_dmi_nomux_table))
+ i8042_nomux = 1;
#endif
return 0;
@@ -300,8 +325,8 @@ static inline int i8042_platform_init(void)
static inline void i8042_platform_exit(void)
{
-#ifdef CONFIG_ACPI
- i8042_acpi_exit();
+#ifdef CONFIG_PNP
+ i8042_pnp_exit();
#endif
}
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c
index 36e5011a6d21b..8e63e464d361e 100644
--- a/drivers/input/serio/i8042.c
+++ b/drivers/input/serio/i8042.c
@@ -19,6 +19,7 @@
#include <linux/init.h>
#include <linux/serio.h>
#include <linux/err.h>
+#include <linux/rcupdate.h>
#include <asm/io.h>
@@ -52,12 +53,16 @@ MODULE_PARM_DESC(dumbkbd, "Pretend that controller can only read data from keybo
static unsigned int i8042_noloop;
module_param_named(noloop, i8042_noloop, bool, 0);
-MODULE_PARM_DESC(dumbkbd, "Disable the AUX Loopback command while probing for the AUX port");
+MODULE_PARM_DESC(noloop, "Disable the AUX Loopback command while probing for the AUX port");
-#ifdef CONFIG_ACPI
-static int i8042_noacpi;
-module_param_named(noacpi, i8042_noacpi, bool, 0);
-MODULE_PARM_DESC(noacpi, "Do not use ACPI to detect controller settings");
+static unsigned int i8042_blink_frequency = 500;
+module_param_named(panicblink, i8042_blink_frequency, uint, 0600);
+MODULE_PARM_DESC(panicblink, "Frequency with which keyboard LEDs should blink when kernel panics");
+
+#ifdef CONFIG_PNP
+static int i8042_nopnp;
+module_param_named(nopnp, i8042_nopnp, bool, 0);
+MODULE_PARM_DESC(nopnp, "Do not use PNP to detect controller settings");
#endif
#define DEBUG
@@ -76,9 +81,10 @@ __obsolete_setup("i8042_dumbkbd");
#include "i8042.h"
-DEFINE_SPINLOCK(i8042_lock);
+static DEFINE_SPINLOCK(i8042_lock);
-struct i8042_values {
+struct i8042_port {
+ struct serio *serio;
int irq;
unsigned char disable;
unsigned char irqen;
@@ -87,25 +93,25 @@ struct i8042_values {
char name[8];
};
-static struct i8042_values i8042_kbd_values = {
- .disable = I8042_CTR_KBDDIS,
- .irqen = I8042_CTR_KBDINT,
- .mux = -1,
- .name = "KBD",
-};
-
-static struct i8042_values i8042_aux_values = {
- .disable = I8042_CTR_AUXDIS,
- .irqen = I8042_CTR_AUXINT,
- .mux = -1,
- .name = "AUX",
+#define I8042_KBD_PORT_NO 0
+#define I8042_AUX_PORT_NO 1
+#define I8042_MUX_PORT_NO 2
+#define I8042_NUM_PORTS (I8042_NUM_MUX_PORTS + 2)
+static struct i8042_port i8042_ports[I8042_NUM_PORTS] = {
+ {
+ .disable = I8042_CTR_KBDDIS,
+ .irqen = I8042_CTR_KBDINT,
+ .mux = -1,
+ .name = "KBD",
+ },
+ {
+ .disable = I8042_CTR_AUXDIS,
+ .irqen = I8042_CTR_AUXINT,
+ .mux = -1,
+ .name = "AUX",
+ }
};
-static struct i8042_values i8042_mux_values[I8042_NUM_MUX_PORTS];
-
-static struct serio *i8042_kbd_port;
-static struct serio *i8042_aux_port;
-static struct serio *i8042_mux_port[I8042_NUM_MUX_PORTS];
static unsigned char i8042_initial_ctr;
static unsigned char i8042_ctr;
static unsigned char i8042_mux_open;
@@ -113,6 +119,7 @@ static unsigned char i8042_mux_present;
static struct timer_list i8042_timer;
static struct platform_device *i8042_platform_device;
+
/*
* Shared IRQ's require a device pointer, but this driver doesn't support
* multiple devices
@@ -155,16 +162,17 @@ static int i8042_wait_write(void)
static int i8042_flush(void)
{
unsigned long flags;
- unsigned char data;
+ unsigned char data, str;
int i = 0;
spin_lock_irqsave(&i8042_lock, flags);
- while ((i8042_read_status() & I8042_STR_OBF) && (i++ < I8042_BUFFER_SIZE)) {
+ while (((str = i8042_read_status()) & I8042_STR_OBF) && (i < I8042_BUFFER_SIZE)) {
udelay(50);
data = i8042_read_data();
+ i++;
dbg("%02x <- i8042 (flush, %s)", data,
- i8042_read_status() & I8042_STR_AUXDATA ? "aux" : "kbd");
+ str & I8042_STR_AUXDATA ? "aux" : "kbd");
}
spin_unlock_irqrestore(&i8042_lock, flags);
@@ -246,19 +254,19 @@ static int i8042_kbd_write(struct serio *port, unsigned char c)
* i8042_aux_write() sends a byte out through the aux interface.
*/
-static int i8042_aux_write(struct serio *port, unsigned char c)
+static int i8042_aux_write(struct serio *serio, unsigned char c)
{
- struct i8042_values *values = port->port_data;
+ struct i8042_port *port = serio->port_data;
int retval;
/*
* Send the byte out.
*/
- if (values->mux == -1)
+ if (port->mux == -1)
retval = i8042_command(&c, I8042_CMD_AUX_SEND);
else
- retval = i8042_command(&c, I8042_CMD_MUX_SEND + values->mux);
+ retval = i8042_command(&c, I8042_CMD_MUX_SEND + port->mux);
/*
* Make sure the interrupt happens and the character is received even
@@ -274,9 +282,10 @@ static int i8042_aux_write(struct serio *port, unsigned char c)
* i8042_activate_port() enables port on a chip.
*/
-static int i8042_activate_port(struct serio *port)
+static int i8042_activate_port(struct i8042_port *port)
{
- struct i8042_values *values = port->port_data;
+ if (!port->serio)
+ return -1;
i8042_flush();
@@ -284,12 +293,12 @@ static int i8042_activate_port(struct serio *port)
* Enable port again here because it is disabled if we are
* resuming (normally it is enabled already).
*/
- i8042_ctr &= ~values->disable;
+ i8042_ctr &= ~port->disable;
- i8042_ctr |= values->irqen;
+ i8042_ctr |= port->irqen;
if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) {
- i8042_ctr &= ~values->irqen;
+ i8042_ctr &= ~port->irqen;
return -1;
}
@@ -302,22 +311,22 @@ static int i8042_activate_port(struct serio *port)
* It allocates the interrupt and calls i8042_enable_port.
*/
-static int i8042_open(struct serio *port)
+static int i8042_open(struct serio *serio)
{
- struct i8042_values *values = port->port_data;
+ struct i8042_port *port = serio->port_data;
- if (values->mux != -1)
+ if (port->mux != -1)
if (i8042_mux_open++)
return 0;
- if (request_irq(values->irq, i8042_interrupt,
+ if (request_irq(port->irq, i8042_interrupt,
SA_SHIRQ, "i8042", i8042_request_irq_cookie)) {
- printk(KERN_ERR "i8042.c: Can't get irq %d for %s, unregistering the port.\n", values->irq, values->name);
+ printk(KERN_ERR "i8042.c: Can't get irq %d for %s, unregistering the port.\n", port->irq, port->name);
goto irq_fail;
}
if (i8042_activate_port(port)) {
- printk(KERN_ERR "i8042.c: Can't activate %s, unregistering the port\n", values->name);
+ printk(KERN_ERR "i8042.c: Can't activate %s, unregistering the port\n", port->name);
goto activate_fail;
}
@@ -326,11 +335,10 @@ static int i8042_open(struct serio *port)
return 0;
activate_fail:
- free_irq(values->irq, i8042_request_irq_cookie);
+ free_irq(port->irq, i8042_request_irq_cookie);
irq_fail:
- values->exists = 0;
- serio_unregister_port_delayed(port);
+ serio_unregister_port_delayed(serio);
return -1;
}
@@ -341,27 +349,58 @@ irq_fail:
* the BIOS could have used the AUX interrupt for PCI.
*/
-static void i8042_close(struct serio *port)
+static void i8042_close(struct serio *serio)
{
- struct i8042_values *values = port->port_data;
+ struct i8042_port *port = serio->port_data;
- if (values->mux != -1)
+ if (port->mux != -1)
if (--i8042_mux_open)
return;
- i8042_ctr &= ~values->irqen;
+ i8042_ctr &= ~port->irqen;
if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) {
- printk(KERN_ERR "i8042.c: Can't write CTR while closing %s.\n", values->name);
- return;
+ printk(KERN_WARNING "i8042.c: Can't write CTR while closing %s.\n", port->name);
+/*
+ * We still want to continue and free IRQ so if more data keeps coming in
+ * kernel will just ignore the irq.
+ */
}
- free_irq(values->irq, i8042_request_irq_cookie);
+ free_irq(port->irq, i8042_request_irq_cookie);
i8042_flush();
}
/*
+ * i8042_start() is called by serio core when port is about to finish
+ * registering. It will mark port as existing so i8042_interrupt can
+ * start sending data through it.
+ */
+static int i8042_start(struct serio *serio)
+{
+ struct i8042_port *port = serio->port_data;
+
+ port->exists = 1;
+ mb();
+ return 0;
+}
+
+/*
+ * i8042_stop() marks serio port as non-existing so i8042_interrupt
+ * will not try to send data to the port that is about to go away.
+ * The function is called by serio core as part of unregister procedure.
+ */
+static void i8042_stop(struct serio *serio)
+{
+ struct i8042_port *port = serio->port_data;
+
+ port->exists = 0;
+ synchronize_kernel();
+ port->serio = NULL;
+}
+
+/*
* i8042_interrupt() is the most important function in this driver -
* it handles the interrupts from the i8042, and sends incoming bytes
* to the upper layers.
@@ -369,25 +408,25 @@ static void i8042_close(struct serio *port)
static irqreturn_t i8042_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
+ struct i8042_port *port;
unsigned long flags;
- unsigned char str, data = 0;
+ unsigned char str, data;
unsigned int dfl;
- unsigned int aux_idx;
+ unsigned int port_no;
int ret;
mod_timer(&i8042_timer, jiffies + I8042_POLL_PERIOD);
spin_lock_irqsave(&i8042_lock, flags);
str = i8042_read_status();
- if (str & I8042_STR_OBF)
- data = i8042_read_data();
- spin_unlock_irqrestore(&i8042_lock, flags);
-
- if (~str & I8042_STR_OBF) {
+ if (unlikely(~str & I8042_STR_OBF)) {
+ spin_unlock_irqrestore(&i8042_lock, flags);
if (irq) dbg("Interrupt %d, without any data", irq);
ret = 0;
goto out;
}
+ data = i8042_read_data();
+ spin_unlock_irqrestore(&i8042_lock, flags);
if (i8042_mux_present && (str & I8042_STR_AUXDATA)) {
static unsigned long last_transmit;
@@ -419,39 +458,28 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id, struct pt_regs *regs)
}
}
- aux_idx = (str >> 6) & 3;
-
- dbg("%02x <- i8042 (interrupt, aux%d, %d%s%s)",
- data, aux_idx, irq,
- dfl & SERIO_PARITY ? ", bad parity" : "",
- dfl & SERIO_TIMEOUT ? ", timeout" : "");
-
- if (likely(i8042_mux_values[aux_idx].exists))
- serio_interrupt(i8042_mux_port[aux_idx], data, dfl, regs);
-
+ port_no = I8042_MUX_PORT_NO + ((str >> 6) & 3);
last_str = str;
last_transmit = jiffies;
- goto irq_ret;
+ } else {
+
+ dfl = ((str & I8042_STR_PARITY) ? SERIO_PARITY : 0) |
+ ((str & I8042_STR_TIMEOUT) ? SERIO_TIMEOUT : 0);
+
+ port_no = (str & I8042_STR_AUXDATA) ?
+ I8042_AUX_PORT_NO : I8042_KBD_PORT_NO;
}
- dfl = ((str & I8042_STR_PARITY) ? SERIO_PARITY : 0) |
- ((str & I8042_STR_TIMEOUT) ? SERIO_TIMEOUT : 0);
+ port = &i8042_ports[port_no];
dbg("%02x <- i8042 (interrupt, %s, %d%s%s)",
- data, (str & I8042_STR_AUXDATA) ? "aux" : "kbd", irq,
- dfl & SERIO_PARITY ? ", bad parity" : "",
- dfl & SERIO_TIMEOUT ? ", timeout" : "");
+ data, port->name, irq,
+ dfl & SERIO_PARITY ? ", bad parity" : "",
+ dfl & SERIO_TIMEOUT ? ", timeout" : "");
+ if (likely(port->exists))
+ serio_interrupt(port->serio, data, dfl, regs);
- if (str & I8042_STR_AUXDATA) {
- if (likely(i8042_aux_values.exists))
- serio_interrupt(i8042_aux_port, data, dfl, regs);
- } else {
- if (likely(i8042_kbd_values.exists))
- serio_interrupt(i8042_kbd_port, data, dfl, regs);
- }
-
-irq_ret:
ret = 1;
out:
return IRQ_RETVAL(ret);
@@ -500,7 +528,7 @@ static int i8042_set_mux_mode(unsigned int mode, unsigned char *mux_version)
* the controller has been switched into Multiplexed mode
*/
-static int i8042_enable_mux_ports(struct i8042_values *values)
+static int i8042_enable_mux_ports(void)
{
unsigned char param;
int i;
@@ -535,7 +563,7 @@ static int i8042_enable_mux_ports(struct i8042_values *values)
* LCS/Telegraphics.
*/
-static int __init i8042_check_mux(struct i8042_values *values)
+static int __init i8042_check_mux(void)
{
unsigned char mux_version;
@@ -550,7 +578,7 @@ static int __init i8042_check_mux(struct i8042_values *values)
printk(KERN_INFO "i8042.c: Detected active multiplexing controller, rev %d.%d.\n",
(mux_version >> 4) & 0xf, mux_version & 0xf);
- if (i8042_enable_mux_ports(values))
+ if (i8042_enable_mux_ports())
return -1;
i8042_mux_present = 1;
@@ -563,7 +591,7 @@ static int __init i8042_check_mux(struct i8042_values *values)
* the presence of an AUX interface.
*/
-static int __init i8042_check_aux(struct i8042_values *values)
+static int __init i8042_check_aux(void)
{
unsigned char param;
static int i8042_check_aux_cookie;
@@ -573,10 +601,10 @@ static int __init i8042_check_aux(struct i8042_values *values)
* in trying to detect AUX presence.
*/
- if (request_irq(values->irq, i8042_interrupt, SA_SHIRQ,
- "i8042", &i8042_check_aux_cookie))
+ if (request_irq(i8042_ports[I8042_AUX_PORT_NO].irq, i8042_interrupt,
+ SA_SHIRQ, "i8042", &i8042_check_aux_cookie))
return -1;
- free_irq(values->irq, &i8042_check_aux_cookie);
+ free_irq(i8042_ports[I8042_AUX_PORT_NO].irq, &i8042_check_aux_cookie);
/*
* Get rid of bytes in the queue.
@@ -641,27 +669,25 @@ static int __init i8042_check_aux(struct i8042_values *values)
* registers it, and reports to the user.
*/
-static int __init i8042_port_register(struct serio *port)
+static int __init i8042_port_register(struct i8042_port *port)
{
- struct i8042_values *values = port->port_data;
-
- values->exists = 1;
-
- i8042_ctr &= ~values->disable;
+ i8042_ctr &= ~port->disable;
if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) {
printk(KERN_WARNING "i8042.c: Can't write CTR while registering.\n");
- values->exists = 0;
+ kfree(port->serio);
+ port->serio = NULL;
+ i8042_ctr |= port->disable;
return -1;
}
printk(KERN_INFO "serio: i8042 %s port at %#lx,%#lx irq %d\n",
- values->name,
+ port->name,
(unsigned long) I8042_DATA_REG,
(unsigned long) I8042_COMMAND_REG,
- values->irq);
+ port->irq);
- serio_register_port(port);
+ serio_register_port(port->serio);
return 0;
}
@@ -688,7 +714,10 @@ static int i8042_controller_init(void)
* before doing anything else.
*/
- i8042_flush();
+ if (i8042_flush() == I8042_BUFFER_SIZE) {
+ printk(KERN_ERR "i8042.c: No controller found.\n");
+ return -1;
+ }
if (i8042_reset) {
@@ -771,7 +800,7 @@ static int i8042_controller_init(void)
/*
* Reset the controller.
*/
-void i8042_controller_reset(void)
+static void i8042_controller_reset(void)
{
unsigned char param;
@@ -806,7 +835,7 @@ void i8042_controller_reset(void)
* able to talk to the hardware when rebooting.
*/
-void i8042_controller_cleanup(void)
+static void i8042_controller_cleanup(void)
{
int i;
@@ -816,39 +845,41 @@ void i8042_controller_cleanup(void)
* Reset anything that is connected to the ports.
*/
- if (i8042_kbd_values.exists)
- serio_cleanup(i8042_kbd_port);
-
- if (i8042_aux_values.exists)
- serio_cleanup(i8042_aux_port);
-
- for (i = 0; i < I8042_NUM_MUX_PORTS; i++)
- if (i8042_mux_values[i].exists)
- serio_cleanup(i8042_mux_port[i]);
+ for (i = 0; i < I8042_NUM_PORTS; i++)
+ if (i8042_ports[i].exists)
+ serio_cleanup(i8042_ports[i].serio);
i8042_controller_reset();
}
-static int blink_frequency = 500;
-module_param_named(panicblink, blink_frequency, int, 0600);
+/*
+ * i8042_panic_blink() will flash the keyboard LEDs and is called when
+ * kernel panics. Flashing LEDs is useful for users running X who may
+ * not see the console and will help distingushing panics from "real"
+ * lockups.
+ *
+ * Note that DELAY has a limit of 10ms so we will not get stuck here
+ * waiting for KBC to free up even if KBD interrupt is off
+ */
-/* Catch the case when the kbd interrupt is off */
#define DELAY do { mdelay(1); if (++delay > 10) return delay; } while(0)
-/* Tell the user who may be running in X and not see the console that we have
- panic'ed. This is to distingush panics from "real" lockups. */
static long i8042_panic_blink(long count)
{
long delay = 0;
static long last_blink;
static char led;
- /* Roughly 1/2s frequency. KDB uses about 1s. Make sure it is
- different. */
- if (!blink_frequency)
+
+ /*
+ * We expect frequency to be about 1/2s. KDB uses about 1s.
+ * Make sure they are different.
+ */
+ if (!i8042_blink_frequency)
return 0;
- if (count - last_blink < blink_frequency)
+ if (count - last_blink < i8042_blink_frequency)
return 0;
+
led ^= 0x01 | 0x04;
while (i8042_read_status() & I8042_STR_IBF)
DELAY;
@@ -869,7 +900,7 @@ static long i8042_panic_blink(long count)
* Here we try to restore the original BIOS settings
*/
-static int i8042_suspend(struct device *dev, u32 state, u32 level)
+static int i8042_suspend(struct device *dev, pm_message_t state, u32 level)
{
if (level == SUSPEND_DISABLE) {
del_timer_sync(&i8042_timer);
@@ -897,24 +928,16 @@ static int i8042_resume(struct device *dev, u32 level)
}
if (i8042_mux_present)
- if (i8042_set_mux_mode(1, NULL) ||
- i8042_enable_mux_ports(&i8042_aux_values)) {
+ if (i8042_set_mux_mode(1, NULL) || i8042_enable_mux_ports())
printk(KERN_WARNING "i8042: failed to resume active multiplexor, mouse won't work.\n");
- }
/*
- * Reconnect anything that was connected to the ports.
+ * Activate all ports.
*/
- if (i8042_kbd_values.exists && i8042_activate_port(i8042_kbd_port) == 0)
- serio_reconnect(i8042_kbd_port);
+ for (i = 0; i < I8042_NUM_PORTS; i++)
+ i8042_activate_port(&i8042_ports[i]);
- if (i8042_aux_values.exists && i8042_activate_port(i8042_aux_port) == 0)
- serio_reconnect(i8042_aux_port);
-
- for (i = 0; i < I8042_NUM_MUX_PORTS; i++)
- if (i8042_mux_values[i].exists && i8042_activate_port(i8042_mux_port[i]) == 0)
- serio_reconnect(i8042_mux_port[i]);
/*
* Restart timer (for polling "stuck" data)
*/
@@ -944,72 +967,83 @@ static struct device_driver i8042_driver = {
.shutdown = i8042_shutdown,
};
-static struct serio * __init i8042_allocate_kbd_port(void)
+static void __init i8042_create_kbd_port(void)
{
struct serio *serio;
+ struct i8042_port *port = &i8042_ports[I8042_KBD_PORT_NO];
serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
if (serio) {
memset(serio, 0, sizeof(struct serio));
- serio->type = i8042_direct ? SERIO_8042 : SERIO_8042_XL,
- serio->write = i8042_dumbkbd ? NULL : i8042_kbd_write,
- serio->open = i8042_open,
- serio->close = i8042_close,
- serio->port_data = &i8042_kbd_values,
+ serio->id.type = i8042_direct ? SERIO_8042 : SERIO_8042_XL;
+ serio->write = i8042_dumbkbd ? NULL : i8042_kbd_write;
+ serio->open = i8042_open;
+ serio->close = i8042_close;
+ serio->start = i8042_start;
+ serio->stop = i8042_stop;
+ serio->port_data = port;
serio->dev.parent = &i8042_platform_device->dev;
strlcpy(serio->name, "i8042 Kbd Port", sizeof(serio->name));
strlcpy(serio->phys, I8042_KBD_PHYS_DESC, sizeof(serio->phys));
- }
- return serio;
+ port->serio = serio;
+ i8042_port_register(port);
+ }
}
-static struct serio * __init i8042_allocate_aux_port(void)
+static void __init i8042_create_aux_port(void)
{
struct serio *serio;
+ struct i8042_port *port = &i8042_ports[I8042_AUX_PORT_NO];
serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
if (serio) {
memset(serio, 0, sizeof(struct serio));
- serio->type = SERIO_8042;
+ serio->id.type = SERIO_8042;
serio->write = i8042_aux_write;
serio->open = i8042_open;
serio->close = i8042_close;
- serio->port_data = &i8042_aux_values,
+ serio->start = i8042_start;
+ serio->stop = i8042_stop;
+ serio->port_data = port;
serio->dev.parent = &i8042_platform_device->dev;
strlcpy(serio->name, "i8042 Aux Port", sizeof(serio->name));
strlcpy(serio->phys, I8042_AUX_PHYS_DESC, sizeof(serio->phys));
- }
- return serio;
+ port->serio = serio;
+ i8042_port_register(port);
+ }
}
-static struct serio * __init i8042_allocate_mux_port(int index)
+static void __init i8042_create_mux_port(int index)
{
struct serio *serio;
- struct i8042_values *values = &i8042_mux_values[index];
+ struct i8042_port *port = &i8042_ports[I8042_MUX_PORT_NO + index];
serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
if (serio) {
- *values = i8042_aux_values;
- snprintf(values->name, sizeof(values->name), "AUX%d", index);
- values->mux = index;
-
memset(serio, 0, sizeof(struct serio));
- serio->type = SERIO_8042;
+ serio->id.type = SERIO_8042;
serio->write = i8042_aux_write;
serio->open = i8042_open;
serio->close = i8042_close;
- serio->port_data = values;
+ serio->start = i8042_start;
+ serio->stop = i8042_stop;
+ serio->port_data = port;
serio->dev.parent = &i8042_platform_device->dev;
snprintf(serio->name, sizeof(serio->name), "i8042 Aux-%d Port", index);
snprintf(serio->phys, sizeof(serio->phys), I8042_MUX_PHYS_DESC, index + 1);
- }
- return serio;
+ *port = i8042_ports[I8042_AUX_PORT_NO];
+ port->exists = 0;
+ snprintf(port->name, sizeof(port->name), "AUX%d", index);
+ port->mux = index;
+ port->serio = serio;
+ i8042_port_register(port);
+ }
}
-int __init i8042_init(void)
+static int __init i8042_init(void)
{
int i;
int err;
@@ -1022,60 +1056,51 @@ int __init i8042_init(void)
if (i8042_platform_init())
return -EBUSY;
- i8042_aux_values.irq = I8042_AUX_IRQ;
- i8042_kbd_values.irq = I8042_KBD_IRQ;
+ i8042_ports[I8042_AUX_PORT_NO].irq = I8042_AUX_IRQ;
+ i8042_ports[I8042_KBD_PORT_NO].irq = I8042_KBD_IRQ;
- if (i8042_controller_init())
+ if (i8042_controller_init()) {
+ i8042_platform_exit();
return -ENODEV;
+ }
err = driver_register(&i8042_driver);
- if (err)
+ if (err) {
+ i8042_platform_exit();
return err;
+ }
i8042_platform_device = platform_device_register_simple("i8042", -1, NULL, 0);
if (IS_ERR(i8042_platform_device)) {
driver_unregister(&i8042_driver);
+ i8042_platform_exit();
return PTR_ERR(i8042_platform_device);
}
- if (!i8042_noaux && !i8042_check_aux(&i8042_aux_values)) {
- if (!i8042_nomux && !i8042_check_mux(&i8042_aux_values))
- for (i = 0; i < I8042_NUM_MUX_PORTS; i++) {
- i8042_mux_port[i] = i8042_allocate_mux_port(i);
- if (i8042_mux_port[i])
- i8042_port_register(i8042_mux_port[i]);
- }
- else {
- i8042_aux_port = i8042_allocate_aux_port();
- if (i8042_aux_port)
- i8042_port_register(i8042_aux_port);
- }
+ if (!i8042_noaux && !i8042_check_aux()) {
+ if (!i8042_nomux && !i8042_check_mux())
+ for (i = 0; i < I8042_NUM_MUX_PORTS; i++)
+ i8042_create_mux_port(i);
+ else
+ i8042_create_aux_port();
}
- i8042_kbd_port = i8042_allocate_kbd_port();
- if (i8042_kbd_port)
- i8042_port_register(i8042_kbd_port);
+ i8042_create_kbd_port();
mod_timer(&i8042_timer, jiffies + I8042_POLL_PERIOD);
return 0;
}
-void __exit i8042_exit(void)
+static void __exit i8042_exit(void)
{
int i;
i8042_controller_cleanup();
- if (i8042_kbd_values.exists)
- serio_unregister_port(i8042_kbd_port);
-
- if (i8042_aux_values.exists)
- serio_unregister_port(i8042_aux_port);
-
- for (i = 0; i < I8042_NUM_MUX_PORTS; i++)
- if (i8042_mux_values[i].exists)
- serio_unregister_port(i8042_mux_port[i]);
+ for (i = 0; i < I8042_NUM_PORTS; i++)
+ if (i8042_ports[i].exists)
+ serio_unregister_port(i8042_ports[i].serio);
del_timer_sync(&i8042_timer);
diff --git a/drivers/input/serio/i8042.h b/drivers/input/serio/i8042.h
index 500112b7b93d5..13835039a2a79 100644
--- a/drivers/input/serio/i8042.h
+++ b/drivers/input/serio/i8042.h
@@ -100,10 +100,10 @@
/*
* Expected maximum internal i8042 buffer size. This is used for flushing
- * the i8042 buffers. 32 should be more than enough.
+ * the i8042 buffers.
*/
-#define I8042_BUFFER_SIZE 32
+#define I8042_BUFFER_SIZE 16
/*
* Number of AUX ports on controllers supporting active multiplexing
@@ -117,13 +117,13 @@
*/
#ifdef DEBUG
-static unsigned long i8042_start;
-#define dbg_init() do { i8042_start = jiffies; } while (0)
+static unsigned long i8042_start_time;
+#define dbg_init() do { i8042_start_time = jiffies; } while (0)
#define dbg(format, arg...) \
do { \
if (i8042_debug) \
printk(KERN_DEBUG __FILE__ ": " format " [%d]\n" , \
- ## arg, (int) (jiffies - i8042_start)); \
+ ## arg, (int) (jiffies - i8042_start_time)); \
} while (0)
#else
#define dbg_init() do { } while (0)
diff --git a/drivers/input/serio/maceps2.c b/drivers/input/serio/maceps2.c
index 72b15b20d2a59..9880fc145d905 100644
--- a/drivers/input/serio/maceps2.c
+++ b/drivers/input/serio/maceps2.c
@@ -125,7 +125,7 @@ static struct serio * __init maceps2_allocate_port(int idx)
serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
if (serio) {
memset(serio, 0, sizeof(struct serio));
- serio->type = SERIO_8042;
+ serio->id.type = SERIO_8042;
serio->write = maceps2_write;
serio->open = maceps2_open;
serio->close = maceps2_close;
diff --git a/drivers/input/serio/parkbd.c b/drivers/input/serio/parkbd.c
index d0510ecaf9acd..1d15c2819818d 100644
--- a/drivers/input/serio/parkbd.c
+++ b/drivers/input/serio/parkbd.c
@@ -1,31 +1,47 @@
/*
- * $Id: parkbd.c,v 1.10 2002/03/13 10:09:20 vojtech Exp $
+ * Parallel port to Keyboard port adapter driver for Linux
*
- * Copyright (c) 1999-2001 Vojtech Pavlik
+ * Copyright (c) 1999-2004 Vojtech Pavlik
*/
/*
- * Parallel port to Keyboard port adapter driver for Linux
+ * 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 free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * To connect an AT or XT keyboard to the parallel port, a fairly simple adapter
+ * can be made:
+ *
+ * Parallel port Keyboard port
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * +5V --------------------- +5V (4)
+ *
+ * ______
+ * +5V -------|______|--.
+ * |
+ * ACK (10) ------------|
+ * |--- KBD CLOCK (5)
+ * STROBE (1) ---|<|----'
+ *
+ * ______
+ * +5V -------|______|--.
+ * |
+ * BUSY (11) -----------|
+ * |--- KBD DATA (1)
+ * AUTOFD (14) --|<|----'
*
- * You should have received a copy of the 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
+ * GND (18-25) ------------- GND (3)
+ *
+ * The diodes can be fairly any type, and the resistors should be somewhere
+ * around 5 kOhm, but the adapter will likely work without the resistors,
+ * too.
*
- * Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
- * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
+ * The +5V source can be taken either from USB, from mouse or keyboard ports,
+ * or from a joystick port. Unfortunately, the parallel port of a PC doesn't
+ * have a +5V pin, and feeding the keyboard from signal pins is out of question
+ * with 300 mA power reqirement of a typical AT keyboard.
*/
#include <linux/module.h>
@@ -158,7 +174,7 @@ static struct serio * __init parkbd_allocate_serio(void)
serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
if (serio) {
memset(serio, 0, sizeof(struct serio));
- serio->type = parkbd_mode;
+ serio->id.type = parkbd_mode;
serio->write = parkbd_write,
strlcpy(serio->name, "PARKBD AT/XT keyboard adapter", sizeof(serio->name));
snprintf(serio->phys, sizeof(serio->phys), "%s/serio0", parkbd_dev->port->name);
@@ -167,7 +183,7 @@ static struct serio * __init parkbd_allocate_serio(void)
return serio;
}
-int __init parkbd_init(void)
+static int __init parkbd_init(void)
{
int err;
@@ -191,7 +207,7 @@ int __init parkbd_init(void)
return 0;
}
-void __exit parkbd_exit(void)
+static void __exit parkbd_exit(void)
{
parport_release(parkbd_dev);
serio_unregister_port(parkbd_port);
diff --git a/drivers/input/serio/pcips2.c b/drivers/input/serio/pcips2.c
index 489749e7c9d08..1e139c5e59de1 100644
--- a/drivers/input/serio/pcips2.c
+++ b/drivers/input/serio/pcips2.c
@@ -150,7 +150,7 @@ static int __devinit pcips2_probe(struct pci_dev *dev, const struct pci_device_i
memset(ps2if, 0, sizeof(struct pcips2_data));
memset(serio, 0, sizeof(struct serio));
- serio->type = SERIO_8042;
+ serio->id.type = SERIO_8042;
serio->write = pcips2_write;
serio->open = pcips2_open;
serio->close = pcips2_close;
@@ -217,7 +217,7 @@ static struct pci_driver pcips2_driver = {
static int __init pcips2_init(void)
{
- return pci_module_init(&pcips2_driver);
+ return pci_register_driver(&pcips2_driver);
}
static void __exit pcips2_exit(void)
diff --git a/drivers/input/serio/q40kbd.c b/drivers/input/serio/q40kbd.c
index ab4425db304c1..46093c507988e 100644
--- a/drivers/input/serio/q40kbd.c
+++ b/drivers/input/serio/q40kbd.c
@@ -122,7 +122,7 @@ static struct serio * __init q40kbd_allocate_port(void)
serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
if (serio) {
memset(serio, 0, sizeof(struct serio));
- serio->type = SERIO_8042;
+ serio->id.type = SERIO_8042;
serio->open = q40kbd_open;
serio->close = q40kbd_close;
serio->dev.parent = &q40kbd_device->dev;
diff --git a/drivers/input/serio/rpckbd.c b/drivers/input/serio/rpckbd.c
index 49a58410295ef..106f5eefd89a2 100644
--- a/drivers/input/serio/rpckbd.c
+++ b/drivers/input/serio/rpckbd.c
@@ -115,7 +115,7 @@ static int __devinit rpckbd_probe(struct device *dev)
return -ENOMEM;
memset(serio, 0, sizeof(struct serio));
- serio->type = SERIO_8042;
+ serio->id.type = SERIO_8042;
serio->write = rpckbd_write;
serio->open = rpckbd_open;
serio->close = rpckbd_close;
diff --git a/drivers/input/serio/sa1111ps2.c b/drivers/input/serio/sa1111ps2.c
index 6c68286c7736e..3f0df3330fb21 100644
--- a/drivers/input/serio/sa1111ps2.c
+++ b/drivers/input/serio/sa1111ps2.c
@@ -245,7 +245,7 @@ static int ps2_probe(struct sa1111_dev *dev)
memset(ps2if, 0, sizeof(struct ps2if));
memset(serio, 0, sizeof(struct serio));
- serio->type = SERIO_8042;
+ serio->id.type = SERIO_8042;
serio->write = ps2_write;
serio->open = ps2_open;
serio->close = ps2_close;
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c
index 754b444d5ac52..3313e2daeab02 100644
--- a/drivers/input/serio/serio.c
+++ b/drivers/input/serio/serio.c
@@ -41,76 +41,98 @@ MODULE_DESCRIPTION("Serio abstraction core");
MODULE_LICENSE("GPL");
EXPORT_SYMBOL(serio_interrupt);
-EXPORT_SYMBOL(serio_register_port);
-EXPORT_SYMBOL(serio_register_port_delayed);
+EXPORT_SYMBOL(__serio_register_port);
EXPORT_SYMBOL(serio_unregister_port);
-EXPORT_SYMBOL(serio_unregister_port_delayed);
-EXPORT_SYMBOL(serio_register_driver);
+EXPORT_SYMBOL(__serio_unregister_port_delayed);
+EXPORT_SYMBOL(__serio_register_driver);
EXPORT_SYMBOL(serio_unregister_driver);
EXPORT_SYMBOL(serio_open);
EXPORT_SYMBOL(serio_close);
EXPORT_SYMBOL(serio_rescan);
EXPORT_SYMBOL(serio_reconnect);
-static DECLARE_MUTEX(serio_sem); /* protects serio_list and serio_diriver_list */
+/*
+ * serio_sem protects entire serio subsystem and is taken every time
+ * serio port or driver registrered or unregistered.
+ */
+static DECLARE_MUTEX(serio_sem);
+
static LIST_HEAD(serio_list);
-static LIST_HEAD(serio_driver_list);
-static unsigned int serio_no;
-struct bus_type serio_bus = {
+static struct bus_type serio_bus = {
.name = "serio",
};
-static void serio_find_driver(struct serio *serio);
-static void serio_create_port(struct serio *serio);
+static void serio_add_port(struct serio *serio);
static void serio_destroy_port(struct serio *serio);
-static void serio_connect_port(struct serio *serio, struct serio_driver *drv);
static void serio_reconnect_port(struct serio *serio);
static void serio_disconnect_port(struct serio *serio);
-static int serio_bind_driver(struct serio *serio, struct serio_driver *drv)
+static int serio_match_port(const struct serio_device_id *ids, struct serio *serio)
{
- get_driver(&drv->driver);
+ while (ids->type || ids->proto) {
+ if ((ids->type == SERIO_ANY || ids->type == serio->id.type) &&
+ (ids->proto == SERIO_ANY || ids->proto == serio->id.proto) &&
+ (ids->extra == SERIO_ANY || ids->extra == serio->id.extra) &&
+ (ids->id == SERIO_ANY || ids->id == serio->id.id))
+ return 1;
+ ids++;
+ }
+ return 0;
+}
- drv->connect(serio, drv);
- if (serio->drv) {
- down_write(&serio_bus.subsys.rwsem);
+/*
+ * Basic serio -> driver core mappings
+ */
+
+static void serio_bind_driver(struct serio *serio, struct serio_driver *drv)
+{
+ down_write(&serio_bus.subsys.rwsem);
+
+ if (serio_match_port(drv->id_table, serio)) {
serio->dev.driver = &drv->driver;
+ if (drv->connect(serio, drv)) {
+ serio->dev.driver = NULL;
+ goto out;
+ }
device_bind_driver(&serio->dev);
- up_write(&serio_bus.subsys.rwsem);
- return 1;
}
+out:
+ up_write(&serio_bus.subsys.rwsem);
+}
- put_driver(&drv->driver);
- return 0;
+static void serio_release_driver(struct serio *serio)
+{
+ down_write(&serio_bus.subsys.rwsem);
+ device_release_driver(&serio->dev);
+ up_write(&serio_bus.subsys.rwsem);
}
-/* serio_find_driver() must be called with serio_sem down. */
static void serio_find_driver(struct serio *serio)
{
- struct serio_driver *drv;
-
- list_for_each_entry(drv, &serio_driver_list, node)
- if (!drv->manual_bind)
- if (serio_bind_driver(serio, drv))
- break;
+ down_write(&serio_bus.subsys.rwsem);
+ device_attach(&serio->dev);
+ up_write(&serio_bus.subsys.rwsem);
}
+
/*
* Serio event processing.
*/
-struct serio_event {
- int type;
- struct serio *serio;
- struct list_head node;
-};
-
enum serio_event_type {
SERIO_RESCAN,
SERIO_RECONNECT,
SERIO_REGISTER_PORT,
SERIO_UNREGISTER_PORT,
+ SERIO_REGISTER_DRIVER,
+};
+
+struct serio_event {
+ enum serio_event_type type;
+ void *object;
+ struct module *owner;
+ struct list_head node;
};
static DEFINE_SPINLOCK(serio_event_lock); /* protects serio_event_list */
@@ -119,24 +141,82 @@ static DECLARE_WAIT_QUEUE_HEAD(serio_wait);
static DECLARE_COMPLETION(serio_exited);
static int serio_pid;
-static void serio_queue_event(struct serio *serio, int event_type)
+static void serio_queue_event(void *object, struct module *owner,
+ enum serio_event_type event_type)
{
unsigned long flags;
struct serio_event *event;
spin_lock_irqsave(&serio_event_lock, flags);
+ /*
+ * Scan event list for the other events for the same serio port,
+ * starting with the most recent one. If event is the same we
+ * do not need add new one. If event is of different type we
+ * need to add this event and should not look further because
+ * we need to preseve sequence of distinct events.
+ */
+ list_for_each_entry_reverse(event, &serio_event_list, node) {
+ if (event->object == object) {
+ if (event->type == event_type)
+ goto out;
+ break;
+ }
+ }
+
if ((event = kmalloc(sizeof(struct serio_event), GFP_ATOMIC))) {
+ if (!try_module_get(owner)) {
+ printk(KERN_WARNING "serio: Can't get module reference, dropping event %d\n", event_type);
+ goto out;
+ }
+
event->type = event_type;
- event->serio = serio;
+ event->object = object;
+ event->owner = owner;
list_add_tail(&event->node, &serio_event_list);
wake_up(&serio_wait);
+ } else {
+ printk(KERN_ERR "serio: Not enough memory to queue event %d\n", event_type);
+ }
+out:
+ spin_unlock_irqrestore(&serio_event_lock, flags);
+}
+
+static void serio_free_event(struct serio_event *event)
+{
+ module_put(event->owner);
+ kfree(event);
+}
+
+static void serio_remove_duplicate_events(struct serio_event *event)
+{
+ struct list_head *node, *next;
+ struct serio_event *e;
+ unsigned long flags;
+
+ spin_lock_irqsave(&serio_event_lock, flags);
+
+ list_for_each_safe(node, next, &serio_event_list) {
+ e = list_entry(node, struct serio_event, node);
+ if (event->object == e->object) {
+ /*
+ * If this event is of different type we should not
+ * look further - we only suppress duplicate events
+ * that were sent back-to-back.
+ */
+ if (event->type != e->type)
+ break;
+
+ list_del_init(node);
+ serio_free_event(e);
+ }
}
spin_unlock_irqrestore(&serio_event_lock, flags);
}
+
static struct serio_event *serio_get_event(void)
{
struct serio_event *event;
@@ -151,7 +231,7 @@ static struct serio_event *serio_get_event(void)
}
node = serio_event_list.next;
- event = container_of(node, struct serio_event, node);
+ event = list_entry(node, struct serio_event, node);
list_del_init(node);
spin_unlock_irqrestore(&serio_event_lock, flags);
@@ -162,39 +242,50 @@ static struct serio_event *serio_get_event(void)
static void serio_handle_events(void)
{
struct serio_event *event;
+ struct serio_driver *serio_drv;
- while ((event = serio_get_event())) {
+ down(&serio_sem);
- down(&serio_sem);
+ while ((event = serio_get_event())) {
switch (event->type) {
- case SERIO_REGISTER_PORT :
- serio_create_port(event->serio);
- serio_connect_port(event->serio, NULL);
+ case SERIO_REGISTER_PORT:
+ serio_add_port(event->object);
break;
- case SERIO_UNREGISTER_PORT :
- serio_disconnect_port(event->serio);
- serio_destroy_port(event->serio);
+ case SERIO_UNREGISTER_PORT:
+ serio_disconnect_port(event->object);
+ serio_destroy_port(event->object);
break;
- case SERIO_RECONNECT :
- serio_reconnect_port(event->serio);
+ case SERIO_RECONNECT:
+ serio_reconnect_port(event->object);
break;
- case SERIO_RESCAN :
- serio_disconnect_port(event->serio);
- serio_connect_port(event->serio, NULL);
+ case SERIO_RESCAN:
+ serio_disconnect_port(event->object);
+ serio_find_driver(event->object);
break;
+
+ case SERIO_REGISTER_DRIVER:
+ serio_drv = event->object;
+ driver_register(&serio_drv->driver);
+ break;
+
default:
break;
}
- up(&serio_sem);
- kfree(event);
+ serio_remove_duplicate_events(event);
+ serio_free_event(event);
}
+
+ up(&serio_sem);
}
+/*
+ * Remove all events that have been submitted for a given serio port.
+ */
static void serio_remove_pending_events(struct serio *serio)
{
struct list_head *node, *next;
@@ -204,16 +295,45 @@ static void serio_remove_pending_events(struct serio *serio)
spin_lock_irqsave(&serio_event_lock, flags);
list_for_each_safe(node, next, &serio_event_list) {
- event = container_of(node, struct serio_event, node);
- if (event->serio == serio) {
+ event = list_entry(node, struct serio_event, node);
+ if (event->object == serio) {
list_del_init(node);
- kfree(event);
+ serio_free_event(event);
}
}
spin_unlock_irqrestore(&serio_event_lock, flags);
}
+/*
+ * Destroy child serio port (if any) that has not been fully registered yet.
+ *
+ * Note that we rely on the fact that port can have only one child and therefore
+ * only one child registration request can be pending. Additionally, children
+ * are registered by driver's connect() handler so there can't be a grandchild
+ * pending registration together with a child.
+ */
+static struct serio *serio_get_pending_child(struct serio *parent)
+{
+ struct serio_event *event;
+ struct serio *serio, *child = NULL;
+ unsigned long flags;
+
+ spin_lock_irqsave(&serio_event_lock, flags);
+
+ list_for_each_entry(event, &serio_event_list, node) {
+ if (event->type == SERIO_REGISTER_PORT) {
+ serio = event->object;
+ if (serio->parent == parent) {
+ child = serio;
+ break;
+ }
+ }
+ }
+
+ spin_unlock_irqrestore(&serio_event_lock, flags);
+ return child;
+}
static int serio_thread(void *nothing)
{
@@ -244,6 +364,30 @@ static ssize_t serio_show_description(struct device *dev, char *buf)
return sprintf(buf, "%s\n", serio->name);
}
+static ssize_t serio_show_id_type(struct device *dev, char *buf)
+{
+ struct serio *serio = to_serio_port(dev);
+ return sprintf(buf, "%02x\n", serio->id.type);
+}
+
+static ssize_t serio_show_id_proto(struct device *dev, char *buf)
+{
+ struct serio *serio = to_serio_port(dev);
+ return sprintf(buf, "%02x\n", serio->id.proto);
+}
+
+static ssize_t serio_show_id_id(struct device *dev, char *buf)
+{
+ struct serio *serio = to_serio_port(dev);
+ return sprintf(buf, "%02x\n", serio->id.id);
+}
+
+static ssize_t serio_show_id_extra(struct device *dev, char *buf)
+{
+ struct serio *serio = to_serio_port(dev);
+ return sprintf(buf, "%02x\n", serio->id.extra);
+}
+
static ssize_t serio_rebind_driver(struct device *dev, const char *buf, size_t count)
{
struct serio *serio = to_serio_port(dev);
@@ -261,10 +405,10 @@ static ssize_t serio_rebind_driver(struct device *dev, const char *buf, size_t c
serio_reconnect_port(serio);
} else if (!strncmp(buf, "rescan", count)) {
serio_disconnect_port(serio);
- serio_connect_port(serio, NULL);
+ serio_find_driver(serio);
} else if ((drv = driver_find(buf, &serio_bus)) != NULL) {
serio_disconnect_port(serio);
- serio_connect_port(serio, to_serio_driver(drv));
+ serio_bind_driver(serio, to_serio_driver(drv));
put_driver(drv);
} else {
retval = -EINVAL;
@@ -300,6 +444,10 @@ static ssize_t serio_set_bind_mode(struct device *dev, const char *buf, size_t c
static struct device_attribute serio_device_attrs[] = {
__ATTR(description, S_IRUGO, serio_show_description, NULL),
+ __ATTR(id_type, S_IRUGO, serio_show_id_type, NULL),
+ __ATTR(id_proto, S_IRUGO, serio_show_id_proto, NULL),
+ __ATTR(id_id, S_IRUGO, serio_show_id_id, NULL),
+ __ATTR(id_extra, S_IRUGO, serio_show_id_extra, NULL),
__ATTR(drvctl, S_IWUSR, NULL, serio_rebind_driver),
__ATTR(bind_mode, S_IWUSR | S_IRUGO, serio_show_bind_mode, serio_set_bind_mode),
__ATTR_NULL
@@ -314,95 +462,88 @@ static void serio_release_port(struct device *dev)
module_put(THIS_MODULE);
}
-static void serio_create_port(struct serio *serio)
+/*
+ * Prepare serio port for registration.
+ */
+static void serio_init_port(struct serio *serio)
{
- try_module_get(THIS_MODULE);
+ static atomic_t serio_no = ATOMIC_INIT(0);
+
+ __module_get(THIS_MODULE);
spin_lock_init(&serio->lock);
init_MUTEX(&serio->drv_sem);
- list_add_tail(&serio->node, &serio_list);
- snprintf(serio->dev.bus_id, sizeof(serio->dev.bus_id), "serio%d", serio_no++);
+ device_initialize(&serio->dev);
+ snprintf(serio->dev.bus_id, sizeof(serio->dev.bus_id),
+ "serio%ld", (long)atomic_inc_return(&serio_no) - 1);
serio->dev.bus = &serio_bus;
serio->dev.release = serio_release_port;
if (serio->parent)
serio->dev.parent = &serio->parent->dev;
- device_register(&serio->dev);
}
/*
- * serio_destroy_port() completes deregistration process and removes
- * port from the system
+ * Complete serio port registration.
+ * Driver core will attempt to find appropriate driver for the port.
*/
-static void serio_destroy_port(struct serio *serio)
+static void serio_add_port(struct serio *serio)
{
- struct serio_driver *drv = serio->drv;
- unsigned long flags;
-
- serio_remove_pending_events(serio);
- list_del_init(&serio->node);
-
- if (drv) {
- drv->disconnect(serio);
- down_write(&serio_bus.subsys.rwsem);
- device_release_driver(&serio->dev);
- up_write(&serio_bus.subsys.rwsem);
- put_driver(&drv->driver);
- }
-
if (serio->parent) {
- spin_lock_irqsave(&serio->parent->lock, flags);
- serio->parent->child = NULL;
- spin_unlock_irqrestore(&serio->parent->lock, flags);
+ serio_pause_rx(serio->parent);
+ serio->parent->child = serio;
+ serio_continue_rx(serio->parent);
}
- device_unregister(&serio->dev);
+ list_add_tail(&serio->node, &serio_list);
+ if (serio->start)
+ serio->start(serio);
+ device_add(&serio->dev);
+ serio->registered = 1;
}
/*
- * serio_connect_port() tries to bind the port and possible all its
- * children to appropriate drivers. If driver passed in the function will not
- * try otehr drivers when binding parent port.
+ * serio_destroy_port() completes deregistration process and removes
+ * port from the system
*/
-static void serio_connect_port(struct serio *serio, struct serio_driver *drv)
+static void serio_destroy_port(struct serio *serio)
{
- WARN_ON(serio->drv);
- WARN_ON(serio->child);
+ struct serio *child;
- if (drv)
- serio_bind_driver(serio, drv);
- else if (!serio->manual_bind)
- serio_find_driver(serio);
-
- /* Ok, now bind children, if any */
- while (serio->child) {
- serio = serio->child;
+ child = serio_get_pending_child(serio);
+ if (child) {
+ serio_remove_pending_events(child);
+ put_device(&child->dev);
+ }
- WARN_ON(serio->drv);
- WARN_ON(serio->child);
+ if (serio->stop)
+ serio->stop(serio);
- serio_create_port(serio);
+ if (serio->parent) {
+ serio_pause_rx(serio->parent);
+ serio->parent->child = NULL;
+ serio_continue_rx(serio->parent);
+ serio->parent = NULL;
+ }
- if (!serio->manual_bind) {
- /*
- * With children we just _prefer_ passed in driver,
- * but we will try other options in case preferred
- * is not the one
- */
- if (!drv || !serio_bind_driver(serio, drv))
- serio_find_driver(serio);
- }
+ if (serio->registered) {
+ device_del(&serio->dev);
+ list_del_init(&serio->node);
+ serio->registered = 0;
}
+
+ serio_remove_pending_events(serio);
+ put_device(&serio->dev);
}
/*
- *
+ * Reconnect serio port and all its children (re-initialize attached devices)
*/
static void serio_reconnect_port(struct serio *serio)
{
do {
if (!serio->drv || !serio->drv->reconnect || serio->drv->reconnect(serio)) {
serio_disconnect_port(serio);
- serio_connect_port(serio, NULL);
+ serio_find_driver(serio);
/* Ok, old children are now gone, we are done */
break;
}
@@ -416,8 +557,7 @@ static void serio_reconnect_port(struct serio *serio)
*/
static void serio_disconnect_port(struct serio *serio)
{
- struct serio_driver *drv = serio->drv;
- struct serio *s;
+ struct serio *s, *parent;
if (serio->child) {
/*
@@ -425,56 +565,46 @@ static void serio_disconnect_port(struct serio *serio)
* first, staring with the leaf one, since we don't want
* to do recursion
*/
+ for (s = serio; s->child; s = s->child)
+ /* empty */;
+
do {
- s = serio->child;
- } while (s->child);
+ parent = s->parent;
- while (s != serio) {
- s = s->parent;
- serio_destroy_port(s->child);
- }
+ serio_release_driver(s);
+ serio_destroy_port(s);
+ } while ((s = parent) != serio);
}
/*
* Ok, no children left, now disconnect this port
*/
- if (drv) {
- drv->disconnect(serio);
- down_write(&serio_bus.subsys.rwsem);
- device_release_driver(&serio->dev);
- up_write(&serio_bus.subsys.rwsem);
- put_driver(&drv->driver);
- }
+ serio_release_driver(serio);
}
void serio_rescan(struct serio *serio)
{
- serio_queue_event(serio, SERIO_RESCAN);
+ serio_queue_event(serio, NULL, SERIO_RESCAN);
}
void serio_reconnect(struct serio *serio)
{
- serio_queue_event(serio, SERIO_RECONNECT);
-}
-
-void serio_register_port(struct serio *serio)
-{
- down(&serio_sem);
- serio_create_port(serio);
- serio_connect_port(serio, NULL);
- up(&serio_sem);
+ serio_queue_event(serio, NULL, SERIO_RECONNECT);
}
/*
* Submits register request to kseriod for subsequent execution.
- * Can be used when it is not obvious whether the serio_sem is
- * taken or not and when delayed execution is feasible.
+ * Note that port registration is always asynchronous.
*/
-void serio_register_port_delayed(struct serio *serio)
+void __serio_register_port(struct serio *serio, struct module *owner)
{
- serio_queue_event(serio, SERIO_REGISTER_PORT);
+ serio_init_port(serio);
+ serio_queue_event(serio, owner, SERIO_REGISTER_PORT);
}
+/*
+ * Synchronously unregisters serio port.
+ */
void serio_unregister_port(struct serio *serio)
{
down(&serio_sem);
@@ -484,13 +614,13 @@ void serio_unregister_port(struct serio *serio)
}
/*
- * Submits unregister request to kseriod for subsequent execution.
+ * Submits register request to kseriod for subsequent execution.
* Can be used when it is not obvious whether the serio_sem is
* taken or not and when delayed execution is feasible.
*/
-void serio_unregister_port_delayed(struct serio *serio)
+void __serio_unregister_port_delayed(struct serio *serio, struct module *owner)
{
- serio_queue_event(serio, SERIO_UNREGISTER_PORT);
+ serio_queue_event(serio, owner, SERIO_UNREGISTER_PORT);
}
@@ -535,35 +665,30 @@ static struct driver_attribute serio_driver_attrs[] = {
__ATTR_NULL
};
-void serio_register_driver(struct serio_driver *drv)
+static int serio_driver_probe(struct device *dev)
{
- struct serio *serio;
-
- down(&serio_sem);
+ struct serio *serio = to_serio_port(dev);
+ struct serio_driver *drv = to_serio_driver(dev->driver);
- list_add_tail(&drv->node, &serio_driver_list);
+ return drv->connect(serio, drv);
+}
- drv->driver.bus = &serio_bus;
- driver_register(&drv->driver);
+static int serio_driver_remove(struct device *dev)
+{
+ struct serio *serio = to_serio_port(dev);
+ struct serio_driver *drv = to_serio_driver(dev->driver);
- if (drv->manual_bind)
- goto out;
+ drv->disconnect(serio);
+ return 0;
+}
-start_over:
- list_for_each_entry(serio, &serio_list, node) {
- if (!serio->drv) {
- serio_connect_port(serio, drv);
- /*
- * if new child appeared then the list is changed,
- * we need to start over
- */
- if (serio->child)
- goto start_over;
- }
- }
+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;
-out:
- up(&serio_sem);
+ serio_queue_event(drv, owner, SERIO_REGISTER_DRIVER);
}
void serio_unregister_driver(struct serio_driver *drv)
@@ -571,21 +696,19 @@ void serio_unregister_driver(struct serio_driver *drv)
struct serio *serio;
down(&serio_sem);
-
- list_del_init(&drv->node);
+ drv->manual_bind = 1; /* so serio_find_driver ignores it */
start_over:
list_for_each_entry(serio, &serio_list, node) {
if (serio->drv == drv) {
serio_disconnect_port(serio);
- serio_connect_port(serio, NULL);
+ serio_find_driver(serio);
/* we could've deleted some ports, restart */
goto start_over;
}
}
driver_unregister(&drv->driver);
-
up(&serio_sem);
}
@@ -598,6 +721,75 @@ static void serio_set_drv(struct serio *serio, struct serio_driver *drv)
up(&serio->drv_sem);
}
+static int serio_bus_match(struct device *dev, struct device_driver *drv)
+{
+ struct serio *serio = to_serio_port(dev);
+ struct serio_driver *serio_drv = to_serio_driver(drv);
+
+ if (serio->manual_bind || serio_drv->manual_bind)
+ return 0;
+
+ return serio_match_port(serio_drv->id_table, serio);
+}
+
+#ifdef CONFIG_HOTPLUG
+
+#define PUT_ENVP(fmt, val) \
+do { \
+ envp[i++] = buffer; \
+ length += snprintf(buffer, buffer_size - length, fmt, val); \
+ if (buffer_size - length <= 0 || i >= num_envp) \
+ return -ENOMEM; \
+ length++; \
+ buffer += length; \
+} while (0)
+static int serio_hotplug(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size)
+{
+ struct serio *serio;
+ int i = 0;
+ int length = 0;
+
+ if (!dev)
+ return -ENODEV;
+
+ serio = to_serio_port(dev);
+
+ PUT_ENVP("SERIO_TYPE=%02x", serio->id.type);
+ PUT_ENVP("SERIO_PROTO=%02x", serio->id.proto);
+ PUT_ENVP("SERIO_ID=%02x", serio->id.id);
+ PUT_ENVP("SERIO_EXTRA=%02x", serio->id.extra);
+
+ envp[i] = NULL;
+
+ return 0;
+}
+#undef PUT_ENVP
+
+#else
+
+static int serio_hotplug(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size)
+{
+ return -ENODEV;
+}
+
+#endif /* CONFIG_HOTPLUG */
+
+static int serio_resume(struct device *dev)
+{
+ struct serio *serio = to_serio_port(dev);
+
+ if (!serio->drv || !serio->drv->reconnect || serio->drv->reconnect(serio)) {
+ serio_disconnect_port(serio);
+ /*
+ * Driver re-probing can take a while, so better let kseriod
+ * deal with it.
+ */
+ serio_rescan(serio);
+ }
+
+ return 0;
+}
+
/* called from serio_driver->connect/disconnect methods under serio_sem */
int serio_open(struct serio *serio, struct serio_driver *drv)
{
@@ -629,14 +821,9 @@ irqreturn_t serio_interrupt(struct serio *serio,
if (likely(serio->drv)) {
ret = serio->drv->interrupt(serio, data, dfl, regs);
- } else {
- if (!dfl) {
- if ((serio->type != SERIO_8042 &&
- serio->type != SERIO_8042_XL) || (data == 0xaa)) {
- serio_rescan(serio);
- ret = IRQ_HANDLED;
- }
- }
+ } else if (!dfl && serio->registered) {
+ serio_rescan(serio);
+ ret = IRQ_HANDLED;
}
spin_unlock_irqrestore(&serio->lock, flags);
@@ -647,12 +834,15 @@ irqreturn_t serio_interrupt(struct serio *serio,
static int __init serio_init(void)
{
if (!(serio_pid = kernel_thread(serio_thread, NULL, CLONE_KERNEL))) {
- printk(KERN_WARNING "serio: Failed to start kseriod\n");
+ printk(KERN_ERR "serio: Failed to start kseriod\n");
return -1;
}
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.resume = serio_resume;
bus_register(&serio_bus);
return 0;
diff --git a/drivers/input/serio/serio_raw.c b/drivers/input/serio/serio_raw.c
index f424fdf19e7d6..d914e7e93db4c 100644
--- a/drivers/input/serio/serio_raw.c
+++ b/drivers/input/serio/serio_raw.c
@@ -235,7 +235,7 @@ static unsigned int serio_raw_poll(struct file *file, poll_table *wait)
return 0;
}
-struct file_operations serio_raw_fops = {
+static struct file_operations serio_raw_fops = {
.owner = THIS_MODULE,
.open = serio_raw_open,
.release = serio_raw_release,
@@ -253,7 +253,7 @@ struct file_operations serio_raw_fops = {
static irqreturn_t serio_raw_interrupt(struct serio *serio, unsigned char data,
unsigned int dfl, struct pt_regs *regs)
{
- struct serio_raw *serio_raw = serio->private;
+ struct serio_raw *serio_raw = serio_get_drvdata(serio);
struct serio_raw_list *list;
unsigned int head = serio_raw->head;
@@ -270,17 +270,14 @@ static irqreturn_t serio_raw_interrupt(struct serio *serio, unsigned char data,
return IRQ_HANDLED;
}
-static void serio_raw_connect(struct serio *serio, struct serio_driver *drv)
+static int serio_raw_connect(struct serio *serio, struct serio_driver *drv)
{
struct serio_raw *serio_raw;
int err;
- if ((serio->type & SERIO_TYPE) != SERIO_8042)
- return;
-
if (!(serio_raw = kmalloc(sizeof(struct serio_raw), GFP_KERNEL))) {
printk(KERN_ERR "serio_raw.c: can't allocate memory for a device\n");
- return;
+ return -ENOMEM;
}
down(&serio_raw_sem);
@@ -292,8 +289,10 @@ static void serio_raw_connect(struct serio *serio, struct serio_driver *drv)
INIT_LIST_HEAD(&serio_raw->list);
init_waitqueue_head(&serio_raw->wait);
- serio->private = serio_raw;
- if (serio_open(serio, drv))
+ serio_set_drvdata(serio, serio_raw);
+
+ err = serio_open(serio, drv);
+ if (err)
goto out_free;
list_add_tail(&serio_raw->node, &serio_raw_list);
@@ -322,15 +321,16 @@ out_close:
serio_close(serio);
list_del_init(&serio_raw->node);
out_free:
- serio->private = NULL;
+ serio_set_drvdata(serio, NULL);
kfree(serio_raw);
out:
up(&serio_raw_sem);
+ return err;
}
static int serio_raw_reconnect(struct serio *serio)
{
- struct serio_raw *serio_raw = serio->private;
+ struct serio_raw *serio_raw = serio_get_drvdata(serio);
struct serio_driver *drv = serio->drv;
if (!drv || !serio_raw) {
@@ -351,10 +351,10 @@ static void serio_raw_disconnect(struct serio *serio)
down(&serio_raw_sem);
- serio_raw = serio->private;
+ serio_raw = serio_get_drvdata(serio);
serio_close(serio);
- serio->private = NULL;
+ serio_set_drvdata(serio, NULL);
serio_raw->serio = NULL;
if (!serio_raw_cleanup(serio_raw))
@@ -363,11 +363,24 @@ static void serio_raw_disconnect(struct serio *serio)
up(&serio_raw_sem);
}
+static struct serio_device_id serio_raw_serio_ids[] = {
+ {
+ .type = SERIO_8042,
+ .proto = SERIO_ANY,
+ .id = SERIO_ANY,
+ .extra = SERIO_ANY,
+ },
+ { 0 }
+};
+
+MODULE_DEVICE_TABLE(serio, serio_raw_serio_ids);
+
static struct serio_driver serio_raw_drv = {
.driver = {
.name = "serio_raw",
},
.description = DRIVER_DESC,
+ .id_table = serio_raw_serio_ids,
.interrupt = serio_raw_interrupt,
.connect = serio_raw_connect,
.reconnect = serio_raw_reconnect,
@@ -375,13 +388,13 @@ static struct serio_driver serio_raw_drv = {
.manual_bind = 1,
};
-int __init serio_raw_init(void)
+static int __init serio_raw_init(void)
{
serio_register_driver(&serio_raw_drv);
return 0;
}
-void __exit serio_raw_exit(void)
+static void __exit serio_raw_exit(void)
{
serio_unregister_driver(&serio_raw_drv);
}
diff --git a/drivers/input/serio/serport.c b/drivers/input/serio/serport.c
index 538ccf1807970..22f73683952bf 100644
--- a/drivers/input/serio/serport.c
+++ b/drivers/input/serio/serport.c
@@ -49,7 +49,7 @@ static void serport_serio_close(struct serio *serio)
{
struct serport *serport = serio->port_data;
- serport->serio->type = 0;
+ serport->serio->id.type = 0;
wake_up_interruptible(&serport->wait);
}
@@ -84,7 +84,7 @@ static int serport_ldisc_open(struct tty_struct *tty)
memset(serio, 0, sizeof(struct serio));
strlcpy(serio->name, "Serial port", sizeof(serio->name));
snprintf(serio->phys, sizeof(serio->phys), "%s/serio0", tty_name(tty, name));
- serio->type = SERIO_RS232;
+ serio->id.type = SERIO_RS232;
serio->write = serport_serio_write;
serio->close = serport_serio_close;
serio->port_data = serport;
@@ -148,7 +148,7 @@ static ssize_t serport_ldisc_read(struct tty_struct * tty, struct file * file, u
serio_register_port(serport->serio);
printk(KERN_INFO "serio: Serial port %s\n", tty_name(tty, name));
- wait_event_interruptible(serport->wait, !serport->serio->type);
+ wait_event_interruptible(serport->wait, !serport->serio->id.type);
serio_unregister_port(serport->serio);
clear_bit(SERPORT_BUSY, &serport->flags);
@@ -163,9 +163,19 @@ static ssize_t serport_ldisc_read(struct tty_struct * tty, struct file * file, u
static int serport_ldisc_ioctl(struct tty_struct * tty, struct file * file, unsigned int cmd, unsigned long arg)
{
struct serport *serport = (struct serport*) tty->disc_data;
+ struct serio *serio = serport->serio;
+ unsigned long type;
- if (cmd == SPIOCSTYPE)
- return get_user(serport->serio->type, (unsigned long __user *) arg);
+ if (cmd == SPIOCSTYPE) {
+ if (get_user(type, (unsigned long __user *) arg))
+ return -EFAULT;
+
+ serio->id.proto = type & 0x000000ff;
+ serio->id.id = (type & 0x0000ff00) >> 8;
+ serio->id.extra = (type & 0x00ff0000) >> 16;
+
+ return 0;
+ }
return -EINVAL;
}
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 4a1e7d6ea8210..7e991274ea400 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -1,18 +1,19 @@
#
# Mouse driver configuration
#
-config INPUT_TOUCHSCREEN
+menuconfig INPUT_TOUCHSCREEN
bool "Touchscreens"
- depends on INPUT
help
Say Y here, and a list of supported touchscreens will be displayed.
This option doesn't affect the kernel.
If unsure, say Y.
+if INPUT_TOUCHSCREEN
+
config TOUCHSCREEN_BITSY
- tristate "Compaq iPAQ H3600 (Bitsy) touchscreen input driver"
- depends on SA1100_BITSY && INPUT && INPUT_TOUCHSCREEN
+ tristate "Compaq iPAQ H3600 (Bitsy) touchscreen"
+ depends on SA1100_BITSY
select SERIO
help
Say Y here if you have the h3600 (Bitsy) touchscreen.
@@ -22,9 +23,21 @@ config TOUCHSCREEN_BITSY
To compile this driver as a module, choose M here: the
module will be called h3600_ts_input.
+config TOUCHSCREEN_CORGI
+ tristate "Corgi touchscreen (for Sharp SL-C7xx)"
+ depends on PXA_SHARPSL
+ default y
+ help
+ Say Y here to enable the driver for the touchscreen on the
+ Sharp SL-C7xx series of PDAs.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ads7846_ts.
+
config TOUCHSCREEN_GUNZE
tristate "Gunze AHL-51S touchscreen"
- depends on INPUT && INPUT_TOUCHSCREEN
select SERIO
help
Say Y here if you have the Gunze AHL-51 touchscreen connected to
@@ -35,3 +48,51 @@ config TOUCHSCREEN_GUNZE
To compile this driver as a module, choose M here: the
module will be called gunze.
+config TOUCHSCREEN_ELO
+ tristate "Elo serial touchscreens"
+ select SERIO
+ help
+ Say Y here if you have an Elo serial touchscreen connected to
+ your system.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called gunze.
+
+config TOUCHSCREEN_MTOUCH
+ tristate "MicroTouch serial touchscreens"
+ select SERIO
+ help
+ Say Y here if you have a MicroTouch (3M) serial touchscreen connected to
+ your system.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called mtouch.
+
+config TOUCHSCREEN_MK712
+ tristate "ICS MicroClock MK712 touchscreen"
+ help
+ Say Y here if you have the ICS MicroClock MK712 touchscreen
+ controller chip in your system.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called mk712.
+
+config TOUCHSCREEN_HP600
+ tristate "HP Jornada 680/690 touchscreen"
+ depends on SH_HP600 && SH_ADC
+ help
+ Say Y here if you have a HP Jornada 680 or 690 and want to
+ support the built-in touchscreen.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called hp680_ts_input.
+
+endif
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 421890f61c920..6842869c9a263 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -5,4 +5,9 @@
# Each configuration option enables a list of files.
obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o
+obj-$(CONFIG_TOUCHSCREEN_CORGI) += corgi_ts.o
obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o
+obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o
+obj-$(CONFIG_TOUCHSCREEN_MTOUCH) += mtouch.o
+obj-$(CONFIG_TOUCHSCREEN_MK712) += mk712.o
+obj-$(CONFIG_TOUCHSCREEN_HP600) += hp680_ts_input.o
diff --git a/drivers/input/touchscreen/corgi_ts.c b/drivers/input/touchscreen/corgi_ts.c
new file mode 100644
index 0000000000000..3f8b61cfbc379
--- /dev/null
+++ b/drivers/input/touchscreen/corgi_ts.c
@@ -0,0 +1,380 @@
+/*
+ * Touchscreen driver for Sharp Corgi models (SL-C7xx)
+ *
+ * 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/delay.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <asm/irq.h>
+
+#include <asm/arch/corgi.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/pxa-regs.h>
+
+
+#define PWR_MODE_ACTIVE 0
+#define PWR_MODE_SUSPEND 1
+
+#define X_AXIS_MAX 3830
+#define X_AXIS_MIN 150
+#define Y_AXIS_MAX 3830
+#define Y_AXIS_MIN 190
+#define PRESSURE_MIN 0
+#define PRESSURE_MAX 15000
+
+struct ts_event {
+ short pressure;
+ short x;
+ short y;
+};
+
+struct corgi_ts {
+ char phys[32];
+ struct input_dev input;
+ struct timer_list timer;
+ struct ts_event tc;
+ int pendown;
+ int power_mode;
+};
+
+#define STATUS_HSYNC (GPLR(CORGI_GPIO_HSYNC) & GPIO_bit(CORGI_GPIO_HSYNC))
+
+#define SyncHS() while((STATUS_HSYNC) == 0); while((STATUS_HSYNC) != 0);
+#define CCNT(a) asm volatile ("mrc p14, 0, %0, C1, C0, 0" : "=r"(a))
+#define CCNT_ON() {int pmnc = 1; asm volatile ("mcr p14, 0, %0, C0, C0, 0" : : "r"(pmnc));}
+#define CCNT_OFF() {int pmnc = 0; asm volatile ("mcr p14, 0, %0, C0, C0, 0" : : "r"(pmnc));}
+
+#define WAIT_HS_400_VGA 7013U // 17.615us
+#define WAIT_HS_400_QVGA 16622U // 41.750us
+
+
+/* ADS7846 Touch Screen Controller bit definitions */
+#define ADSCTRL_PD0 (1u << 0) /* PD0 */
+#define ADSCTRL_PD1 (1u << 1) /* PD1 */
+#define ADSCTRL_DFR (1u << 2) /* SER/DFR */
+#define ADSCTRL_MOD (1u << 3) /* Mode */
+#define ADSCTRL_ADR_SH 4 /* Address setting */
+#define ADSCTRL_STS (1u << 7) /* Start Bit */
+
+/* External Functions */
+extern int w100fb_get_xres(void);
+extern int w100fb_get_blanking(void);
+extern int w100fb_get_fastsysclk(void);
+extern unsigned int get_clk_frequency_khz(int info);
+
+static unsigned long calc_waittime(void)
+{
+ int w100fb_xres = w100fb_get_xres();
+ unsigned int waittime = 0;
+
+ if (w100fb_xres == 480 || w100fb_xres == 640) {
+ waittime = WAIT_HS_400_VGA * get_clk_frequency_khz(0) / 398131U;
+
+ if (w100fb_get_fastsysclk() == 100)
+ waittime = waittime * 75 / 100;
+
+ if (w100fb_xres == 640)
+ waittime *= 3;
+
+ return waittime;
+ }
+
+ return WAIT_HS_400_QVGA * get_clk_frequency_khz(0) / 398131U;
+}
+
+static int sync_receive_data_send_cmd(int doRecive, int doSend, unsigned int address, unsigned long wait_time)
+{
+ int pos = 0;
+ unsigned long timer1 = 0, timer2;
+ int dosleep;
+
+ dosleep = !w100fb_get_blanking();
+
+ if (dosleep && doSend) {
+ CCNT_ON();
+ /* polling HSync */
+ SyncHS();
+ /* get CCNT */
+ CCNT(timer1);
+ }
+
+ if (doRecive)
+ pos = corgi_ssp_ads7846_get();
+
+ if (doSend) {
+ int cmd = ADSCTRL_PD0 | ADSCTRL_PD1 | (address << ADSCTRL_ADR_SH) | ADSCTRL_STS;
+ /* dummy command */
+ corgi_ssp_ads7846_put(cmd);
+ corgi_ssp_ads7846_get();
+
+ if (dosleep) {
+ /* Wait after HSync */
+ CCNT(timer2);
+ if (timer2-timer1 > wait_time) {
+ /* timeout */
+ SyncHS();
+ /* get OSCR */
+ CCNT(timer1);
+ /* Wait after HSync */
+ CCNT(timer2);
+ }
+ while (timer2 - timer1 < wait_time)
+ CCNT(timer2);
+ }
+ corgi_ssp_ads7846_put(cmd);
+ if (dosleep)
+ CCNT_OFF();
+ }
+ return pos;
+}
+
+static int read_xydata(struct corgi_ts *corgi_ts)
+{
+ unsigned int x, y, z1, z2;
+ unsigned long flags, wait_time;
+
+ /* critical section */
+ local_irq_save(flags);
+ corgi_ssp_ads7846_lock();
+ wait_time=calc_waittime();
+
+ /* Y-axis */
+ sync_receive_data_send_cmd(0, 1, 1u, wait_time);
+
+ /* Y-axis */
+ sync_receive_data_send_cmd(1, 1, 1u, wait_time);
+
+ /* X-axis */
+ y = sync_receive_data_send_cmd(1, 1, 5u, wait_time);
+
+ /* Z1 */
+ x = sync_receive_data_send_cmd(1, 1, 3u, wait_time);
+
+ /* Z2 */
+ z1 = sync_receive_data_send_cmd(1, 1, 4u, wait_time);
+ z2 = sync_receive_data_send_cmd(1, 0, 4u, wait_time);
+
+ /* Power-Down Enable */
+ corgi_ssp_ads7846_put((1u << ADSCTRL_ADR_SH) | ADSCTRL_STS);
+ corgi_ssp_ads7846_get();
+
+ corgi_ssp_ads7846_unlock();
+ local_irq_restore(flags);
+
+ if (x== 0 || y == 0 || z1 == 0 || (x * (z2 - z1) / z1) >= 15000) {
+ corgi_ts->tc.pressure = 0;
+ return 0;
+ }
+
+ corgi_ts->tc.x = x;
+ corgi_ts->tc.y = y;
+ corgi_ts->tc.pressure = (x * (z2 - z1)) / z1;
+ return 1;
+}
+
+static void new_data(struct corgi_ts *corgi_ts, struct pt_regs *regs)
+{
+ if (corgi_ts->power_mode != PWR_MODE_ACTIVE)
+ return;
+
+ if (!corgi_ts->tc.pressure && corgi_ts->pendown == 0)
+ return;
+
+ if (regs)
+ input_regs(&corgi_ts->input, regs);
+
+ input_report_abs(&corgi_ts->input, ABS_X, corgi_ts->tc.x);
+ input_report_abs(&corgi_ts->input, ABS_Y, corgi_ts->tc.y);
+ input_report_abs(&corgi_ts->input, ABS_PRESSURE, corgi_ts->tc.pressure);
+ input_report_key(&corgi_ts->input, BTN_TOUCH, (corgi_ts->pendown != 0));
+ input_sync(&corgi_ts->input);
+}
+
+static void ts_interrupt_main(struct corgi_ts *corgi_ts, int isTimer, struct pt_regs *regs)
+{
+ if ((GPLR(CORGI_GPIO_TP_INT) & GPIO_bit(CORGI_GPIO_TP_INT)) == 0) {
+ /* Disable Interrupt */
+ set_irq_type(CORGI_IRQ_GPIO_TP_INT, IRQT_NOEDGE);
+ if (read_xydata(corgi_ts)) {
+ corgi_ts->pendown = 1;
+ new_data(corgi_ts, regs);
+ }
+ mod_timer(&corgi_ts->timer, jiffies + HZ / 100);
+ } else {
+ if (corgi_ts->pendown == 1 || corgi_ts->pendown == 2) {
+ mod_timer(&corgi_ts->timer, jiffies + HZ / 100);
+ corgi_ts->pendown++;
+ return;
+ }
+
+ if (corgi_ts->pendown) {
+ corgi_ts->tc.pressure = 0;
+ new_data(corgi_ts, regs);
+ }
+
+ /* Enable Falling Edge */
+ set_irq_type(CORGI_IRQ_GPIO_TP_INT, IRQT_FALLING);
+ corgi_ts->pendown = 0;
+ }
+}
+
+static void corgi_ts_timer(unsigned long data)
+{
+ struct corgi_ts *corgits_data = (struct corgi_ts *) data;
+ ts_interrupt_main(corgits_data, 1, NULL);
+}
+
+static irqreturn_t ts_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct corgi_ts *corgits_data = dev_id;
+ ts_interrupt_main(corgits_data, 0, regs);
+ return IRQ_HANDLED;
+}
+
+#ifdef CONFIG_PM
+static int corgits_suspend(struct device *dev, uint32_t state, uint32_t level)
+{
+ if (level == SUSPEND_POWER_DOWN) {
+ struct corgi_ts *corgi_ts = dev_get_drvdata(dev);
+
+ if (corgi_ts->pendown) {
+ del_timer_sync(&corgi_ts->timer);
+ corgi_ts->tc.pressure = 0;
+ new_data(corgi_ts, NULL);
+ corgi_ts->pendown = 0;
+ }
+ corgi_ts->power_mode = PWR_MODE_SUSPEND;
+
+ corgi_ssp_ads7846_putget((1u << ADSCTRL_ADR_SH) | ADSCTRL_STS);
+ }
+ return 0;
+}
+
+static int corgits_resume(struct device *dev, uint32_t level)
+{
+ if (level == RESUME_POWER_ON) {
+ struct corgi_ts *corgi_ts = dev_get_drvdata(dev);
+
+ corgi_ssp_ads7846_putget((4u << ADSCTRL_ADR_SH) | ADSCTRL_STS);
+ /* Enable Falling Edge */
+ set_irq_type(CORGI_IRQ_GPIO_TP_INT, IRQT_FALLING);
+ corgi_ts->power_mode = PWR_MODE_ACTIVE;
+ }
+ return 0;
+}
+#else
+#define corgits_suspend NULL
+#define corgits_resume NULL
+#endif
+
+static int __init corgits_probe(struct device *dev)
+{
+ struct corgi_ts *corgi_ts;
+
+ if (!(corgi_ts = kmalloc(sizeof(struct corgi_ts), GFP_KERNEL)))
+ return -ENOMEM;
+
+ dev_set_drvdata(dev, corgi_ts);
+
+ memset(corgi_ts, 0, sizeof(struct corgi_ts));
+
+ init_input_dev(&corgi_ts->input);
+ corgi_ts->input.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ corgi_ts->input.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+ input_set_abs_params(&corgi_ts->input, ABS_X, X_AXIS_MIN, X_AXIS_MAX, 0, 0);
+ input_set_abs_params(&corgi_ts->input, ABS_Y, Y_AXIS_MIN, Y_AXIS_MAX, 0, 0);
+ input_set_abs_params(&corgi_ts->input, ABS_PRESSURE, PRESSURE_MIN, PRESSURE_MAX, 0, 0);
+
+ strcpy(corgi_ts->phys, "corgits/input0");
+
+ corgi_ts->input.private = corgi_ts;
+ corgi_ts->input.name = "Corgi Touchscreen";
+ corgi_ts->input.dev = dev;
+ corgi_ts->input.phys = corgi_ts->phys;
+ corgi_ts->input.id.bustype = BUS_HOST;
+ corgi_ts->input.id.vendor = 0x0001;
+ corgi_ts->input.id.product = 0x0002;
+ corgi_ts->input.id.version = 0x0100;
+
+ pxa_gpio_mode(CORGI_GPIO_TP_INT | GPIO_IN);
+ pxa_gpio_mode(CORGI_GPIO_HSYNC | GPIO_IN);
+
+ /* Initiaize ADS7846 Difference Reference mode */
+ corgi_ssp_ads7846_putget((1u << ADSCTRL_ADR_SH) | ADSCTRL_STS);
+ mdelay(5);
+ corgi_ssp_ads7846_putget((3u << ADSCTRL_ADR_SH) | ADSCTRL_STS);
+ mdelay(5);
+ corgi_ssp_ads7846_putget((4u << ADSCTRL_ADR_SH) | ADSCTRL_STS);
+ mdelay(5);
+ corgi_ssp_ads7846_putget((5u << ADSCTRL_ADR_SH) | ADSCTRL_STS);
+ mdelay(5);
+
+ init_timer(&corgi_ts->timer);
+ corgi_ts->timer.data = (unsigned long) corgi_ts;
+ corgi_ts->timer.function = corgi_ts_timer;
+
+ input_register_device(&corgi_ts->input);
+ corgi_ts->power_mode = PWR_MODE_ACTIVE;
+
+ if (request_irq(CORGI_IRQ_GPIO_TP_INT, ts_interrupt, SA_INTERRUPT, "ts", corgi_ts)) {
+ input_unregister_device(&corgi_ts->input);
+ kfree(corgi_ts);
+ return -EBUSY;
+ }
+
+ /* Enable Falling Edge */
+ set_irq_type(CORGI_IRQ_GPIO_TP_INT, IRQT_FALLING);
+
+ printk(KERN_INFO "input: Corgi Touchscreen Registered\n");
+
+ return 0;
+}
+
+static int corgits_remove(struct device *dev)
+{
+ struct corgi_ts *corgi_ts = dev_get_drvdata(dev);
+
+ free_irq(CORGI_IRQ_GPIO_TP_INT, NULL);
+ del_timer_sync(&corgi_ts->timer);
+ input_unregister_device(&corgi_ts->input);
+ kfree(corgi_ts);
+ return 0;
+}
+
+static struct device_driver corgits_driver = {
+ .name = "corgi-ts",
+ .bus = &platform_bus_type,
+ .probe = corgits_probe,
+ .remove = corgits_remove,
+ .suspend = corgits_suspend,
+ .resume = corgits_resume,
+};
+
+static int __devinit corgits_init(void)
+{
+ return driver_register(&corgits_driver);
+}
+
+static void __exit corgits_exit(void)
+{
+ driver_unregister(&corgits_driver);
+}
+
+module_init(corgits_init);
+module_exit(corgits_exit);
+
+MODULE_AUTHOR("Richard Purdie <rpurdie@rpsys.net>");
+MODULE_DESCRIPTION("Corgi TouchScreen Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/elo.c b/drivers/input/touchscreen/elo.c
new file mode 100644
index 0000000000000..546ce599334e0
--- /dev/null
+++ b/drivers/input/touchscreen/elo.c
@@ -0,0 +1,315 @@
+/*
+ * Elo serial touchscreen driver
+ *
+ * Copyright (c) 2004 Vojtech Pavlik
+ */
+
+/*
+ * 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 driver can handle serial Elo touchscreens using either the Elo standard
+ * 'E271-2210' 10-byte protocol, Elo legacy 'E281A-4002' 6-byte protocol, Elo
+ * legacy 'E271-140' 4-byte protocol and Elo legacy 'E261-280' 3-byte protocol.
+ */
+
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/serio.h>
+#include <linux/init.h>
+
+#define DRIVER_DESC "Elo serial touchscreen driver"
+
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+
+/*
+ * Definitions & global arrays.
+ */
+
+#define ELO_MAX_LENGTH 10
+
+static char *elo_name = "Elo Serial TouchScreen";
+
+/*
+ * Per-touchscreen data.
+ */
+
+struct elo {
+ struct input_dev dev;
+ struct serio *serio;
+ int id;
+ int idx;
+ unsigned char csum;
+ unsigned char data[ELO_MAX_LENGTH];
+ char phys[32];
+};
+
+static void elo_process_data_10(struct elo* elo, unsigned char data, struct pt_regs *regs)
+{
+ struct input_dev *dev = &elo->dev;
+
+ elo->csum += elo->data[elo->idx] = data;
+
+ switch (elo->idx++) {
+
+ case 0:
+ if (data != 'U') {
+ elo->idx = 0;
+ elo->csum = 0;
+ }
+ break;
+
+ case 1:
+ if (data != 'T') {
+ elo->idx = 0;
+ elo->csum = 0;
+ }
+ break;
+
+ case 9:
+ if (elo->csum) {
+ input_regs(dev, regs);
+ input_report_abs(dev, ABS_X, (elo->data[4] << 8) | elo->data[3]);
+ input_report_abs(dev, ABS_Y, (elo->data[6] << 8) | elo->data[5]);
+ input_report_abs(dev, ABS_PRESSURE, (elo->data[8] << 8) | elo->data[7]);
+ input_report_key(dev, BTN_TOUCH, elo->data[2] & 3);
+ input_sync(dev);
+ }
+ elo->idx = 0;
+ elo->csum = 0;
+ break;
+ }
+}
+
+static void elo_process_data_6(struct elo* elo, unsigned char data, struct pt_regs *regs)
+{
+ struct input_dev *dev = &elo->dev;
+
+ elo->data[elo->idx] = data;
+
+ switch (elo->idx++) {
+
+ case 0: if ((data & 0xc0) != 0xc0) elo->idx = 0; break;
+ case 1: if ((data & 0xc0) != 0x80) elo->idx = 0; break;
+ case 2: if ((data & 0xc0) != 0x40) elo->idx = 0; break;
+
+ case 3:
+ if (data & 0xc0) {
+ elo->idx = 0;
+ break;
+ }
+
+ input_regs(dev, regs);
+ input_report_abs(dev, ABS_X, ((elo->data[0] & 0x3f) << 6) | (elo->data[1] & 0x3f));
+ input_report_abs(dev, ABS_Y, ((elo->data[2] & 0x3f) << 6) | (elo->data[3] & 0x3f));
+
+ if (elo->id == 2) {
+ input_report_key(dev, BTN_TOUCH, 1);
+ input_sync(dev);
+ elo->idx = 0;
+ }
+
+ break;
+
+ case 4:
+ if (data) {
+ input_sync(dev);
+ elo->idx = 0;
+ }
+ break;
+
+ case 5:
+ if ((data & 0xf0) == 0) {
+ input_report_abs(dev, ABS_PRESSURE, elo->data[5]);
+ input_report_key(dev, BTN_TOUCH, elo->data[5]);
+ }
+ input_sync(dev);
+ elo->idx = 0;
+ break;
+ }
+}
+
+static void elo_process_data_3(struct elo* elo, unsigned char data, struct pt_regs *regs)
+{
+ struct input_dev *dev = &elo->dev;
+
+ elo->data[elo->idx] = data;
+
+ switch (elo->idx++) {
+
+ case 0:
+ if ((data & 0x7f) != 0x01)
+ elo->idx = 0;
+ break;
+ case 2:
+ input_regs(dev, regs);
+ input_report_key(dev, BTN_TOUCH, !(elo->data[1] & 0x80));
+ input_report_abs(dev, ABS_X, elo->data[1]);
+ input_report_abs(dev, ABS_Y, elo->data[2]);
+ input_sync(dev);
+ elo->idx = 0;
+ break;
+ }
+}
+
+static irqreturn_t elo_interrupt(struct serio *serio,
+ unsigned char data, unsigned int flags, struct pt_regs *regs)
+{
+ struct elo* elo = serio_get_drvdata(serio);
+
+ switch(elo->id) {
+ case 0:
+ elo_process_data_10(elo, data, regs);
+ break;
+
+ case 1:
+ case 2:
+ elo_process_data_6(elo, data, regs);
+ break;
+
+ case 3:
+ elo_process_data_3(elo, data, regs);
+ break;
+ }
+
+ return IRQ_HANDLED;
+}
+
+/*
+ * elo_disconnect() is the opposite of elo_connect()
+ */
+
+static void elo_disconnect(struct serio *serio)
+{
+ struct elo* elo = serio_get_drvdata(serio);
+
+ input_unregister_device(&elo->dev);
+ serio_close(serio);
+ serio_set_drvdata(serio, NULL);
+ kfree(elo);
+}
+
+/*
+ * elo_connect() is the routine that is called when someone adds a
+ * new serio device that supports Gunze protocol and registers it as
+ * an input device.
+ */
+
+static int elo_connect(struct serio *serio, struct serio_driver *drv)
+{
+ struct elo *elo;
+ int err;
+
+ if (!(elo = kmalloc(sizeof(struct elo), GFP_KERNEL)))
+ return -ENOMEM;
+
+ memset(elo, 0, sizeof(struct elo));
+
+ init_input_dev(&elo->dev);
+ elo->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ elo->dev.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+
+ elo->id = serio->id.id;
+
+ switch (elo->id) {
+
+ case 0: /* 10-byte protocol */
+ input_set_abs_params(&elo->dev, ABS_X, 96, 4000, 0, 0);
+ input_set_abs_params(&elo->dev, ABS_Y, 96, 4000, 0, 0);
+ input_set_abs_params(&elo->dev, ABS_PRESSURE, 0, 255, 0, 0);
+ break;
+
+ case 1: /* 6-byte protocol */
+ input_set_abs_params(&elo->dev, ABS_PRESSURE, 0, 15, 0, 0);
+
+ case 2: /* 4-byte protocol */
+ input_set_abs_params(&elo->dev, ABS_X, 96, 4000, 0, 0);
+ input_set_abs_params(&elo->dev, ABS_Y, 96, 4000, 0, 0);
+ break;
+
+ case 3: /* 3-byte protocol */
+ input_set_abs_params(&elo->dev, ABS_X, 0, 255, 0, 0);
+ input_set_abs_params(&elo->dev, ABS_Y, 0, 255, 0, 0);
+ break;
+ }
+
+ elo->serio = serio;
+
+ sprintf(elo->phys, "%s/input0", serio->phys);
+
+ elo->dev.private = elo;
+ elo->dev.name = elo_name;
+ elo->dev.phys = elo->phys;
+ elo->dev.id.bustype = BUS_RS232;
+ elo->dev.id.vendor = SERIO_ELO;
+ elo->dev.id.product = elo->id;
+ elo->dev.id.version = 0x0100;
+
+ serio_set_drvdata(serio, elo);
+
+ err = serio_open(serio, drv);
+ if (err) {
+ serio_set_drvdata(serio, NULL);
+ kfree(elo);
+ return err;
+ }
+
+ input_register_device(&elo->dev);
+
+ printk(KERN_INFO "input: %s on %s\n", elo_name, serio->phys);
+
+ return 0;
+}
+
+/*
+ * The serio driver structure.
+ */
+
+static struct serio_device_id elo_serio_ids[] = {
+ {
+ .type = SERIO_RS232,
+ .proto = SERIO_ELO,
+ .id = SERIO_ANY,
+ .extra = SERIO_ANY,
+ },
+ { 0 }
+};
+
+MODULE_DEVICE_TABLE(serio, elo_serio_ids);
+
+static struct serio_driver elo_drv = {
+ .driver = {
+ .name = "elo",
+ },
+ .description = DRIVER_DESC,
+ .id_table = elo_serio_ids,
+ .interrupt = elo_interrupt,
+ .connect = elo_connect,
+ .disconnect = elo_disconnect,
+};
+
+/*
+ * The functions for inserting/removing us as a module.
+ */
+
+static int __init elo_init(void)
+{
+ serio_register_driver(&elo_drv);
+ return 0;
+}
+
+static void __exit elo_exit(void)
+{
+ serio_unregister_driver(&elo_drv);
+}
+
+module_init(elo_init);
+module_exit(elo_exit);
diff --git a/drivers/input/touchscreen/gunze.c b/drivers/input/touchscreen/gunze.c
index e5e38dd4a191e..c9d0a153671c6 100644
--- a/drivers/input/touchscreen/gunze.c
+++ b/drivers/input/touchscreen/gunze.c
@@ -74,8 +74,8 @@ static void gunze_process_packet(struct gunze* gunze, struct pt_regs *regs)
}
input_regs(dev, regs);
- input_report_abs(dev, ABS_X, simple_strtoul(gunze->data + 1, NULL, 10) * 4);
- input_report_abs(dev, ABS_Y, 3072 - simple_strtoul(gunze->data + 6, NULL, 10) * 3);
+ input_report_abs(dev, ABS_X, simple_strtoul(gunze->data + 1, NULL, 10));
+ input_report_abs(dev, ABS_Y, 1024 - simple_strtoul(gunze->data + 6, NULL, 10));
input_report_key(dev, BTN_TOUCH, gunze->data[0] == 'T');
input_sync(dev);
}
@@ -83,7 +83,7 @@ static void gunze_process_packet(struct gunze* gunze, struct pt_regs *regs)
static irqreturn_t gunze_interrupt(struct serio *serio,
unsigned char data, unsigned int flags, struct pt_regs *regs)
{
- struct gunze* gunze = serio->private;
+ struct gunze* gunze = serio_get_drvdata(serio);
if (data == '\r') {
gunze_process_packet(gunze, regs);
@@ -101,38 +101,37 @@ static irqreturn_t gunze_interrupt(struct serio *serio,
static void gunze_disconnect(struct serio *serio)
{
- struct gunze* gunze = serio->private;
+ struct gunze* gunze = serio_get_drvdata(serio);
+
input_unregister_device(&gunze->dev);
serio_close(serio);
+ serio_set_drvdata(serio, NULL);
kfree(gunze);
}
/*
* gunze_connect() is the routine that is called when someone adds a
- * new serio device. It looks whether it was registered as a Gunze touchscreen
- * and if yes, registers it as an input device.
+ * new serio device that supports Gunze protocol and registers it as
+ * an input device.
*/
-static void gunze_connect(struct serio *serio, struct serio_driver *drv)
+static int gunze_connect(struct serio *serio, struct serio_driver *drv)
{
struct gunze *gunze;
-
- if (serio->type != (SERIO_RS232 | SERIO_GUNZE))
- return;
+ int err;
if (!(gunze = kmalloc(sizeof(struct gunze), GFP_KERNEL)))
- return;
+ return -ENOMEM;
memset(gunze, 0, sizeof(struct gunze));
init_input_dev(&gunze->dev);
gunze->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
gunze->dev.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
- input_set_abs_params(&gunze->dev, ABS_X, 96, 4000, 0, 0);
- input_set_abs_params(&gunze->dev, ABS_Y, 72, 3000, 0, 0);
+ input_set_abs_params(&gunze->dev, ABS_X, 24, 1000, 0, 0);
+ input_set_abs_params(&gunze->dev, ABS_Y, 24, 1000, 0, 0);
gunze->serio = serio;
- serio->private = gunze;
sprintf(gunze->phys, "%s/input0", serio->phys);
@@ -144,25 +143,44 @@ static void gunze_connect(struct serio *serio, struct serio_driver *drv)
gunze->dev.id.product = 0x0051;
gunze->dev.id.version = 0x0100;
- if (serio_open(serio, drv)) {
+ serio_set_drvdata(serio, gunze);
+
+ err = serio_open(serio, drv);
+ if (err) {
+ serio_set_drvdata(serio, NULL);
kfree(gunze);
- return;
+ return err;
}
input_register_device(&gunze->dev);
printk(KERN_INFO "input: %s on %s\n", gunze_name, serio->phys);
+
+ return 0;
}
/*
- * The serio device structure.
+ * The serio driver structure.
*/
+static struct serio_device_id gunze_serio_ids[] = {
+ {
+ .type = SERIO_RS232,
+ .proto = SERIO_GUNZE,
+ .id = SERIO_ANY,
+ .extra = SERIO_ANY,
+ },
+ { 0 }
+};
+
+MODULE_DEVICE_TABLE(serio, gunze_serio_ids);
+
static struct serio_driver gunze_drv = {
.driver = {
.name = "gunze",
},
.description = DRIVER_DESC,
+ .id_table = gunze_serio_ids,
.interrupt = gunze_interrupt,
.connect = gunze_connect,
.disconnect = gunze_disconnect,
@@ -172,13 +190,13 @@ static struct serio_driver gunze_drv = {
* The functions for inserting/removing us as a module.
*/
-int __init gunze_init(void)
+static int __init gunze_init(void)
{
serio_register_driver(&gunze_drv);
return 0;
}
-void __exit gunze_exit(void)
+static void __exit gunze_exit(void)
{
serio_unregister_driver(&gunze_drv);
}
diff --git a/drivers/input/touchscreen/h3600_ts_input.c b/drivers/input/touchscreen/h3600_ts_input.c
index 10ace15bc220f..acb9137a02263 100644
--- a/drivers/input/touchscreen/h3600_ts_input.c
+++ b/drivers/input/touchscreen/h3600_ts_input.c
@@ -102,6 +102,7 @@ struct h3600_dev {
struct input_dev dev;
struct pm_dev *pm_dev;
struct serio *serio;
+ struct pm_dev *pm_dev;
unsigned char event; /* event ID from packet */
unsigned char chksum;
unsigned char len;
@@ -331,7 +332,7 @@ static int state;
static irqreturn_t h3600ts_interrupt(struct serio *serio, unsigned char data,
unsigned int flags, struct pt_regs *regs)
{
- struct h3600_dev *ts = serio->private;
+ struct h3600_dev *ts = serio_get_drvdata(serio);
/*
* We have a new frame coming in.
@@ -373,18 +374,16 @@ static irqreturn_t h3600ts_interrupt(struct serio *serio, unsigned char data,
/*
* h3600ts_connect() is the routine that is called when someone adds a
- * new serio device. It looks whether it was registered as a H3600 touchscreen
- * and if yes, registers it as an input device.
+ * new serio device that supports H3600 protocol and registers it as
+ * an input device.
*/
-static void h3600ts_connect(struct serio *serio, struct serio_driver *drv)
+static int h3600ts_connect(struct serio *serio, struct serio_driver *drv)
{
struct h3600_dev *ts;
-
- if (serio->type != (SERIO_RS232 | SERIO_H3600))
- return;
+ int err;
if (!(ts = kmalloc(sizeof(struct h3600_dev), GFP_KERNEL)))
- return;
+ return -ENOMEM;
memset(ts, 0, sizeof(struct h3600_dev));
@@ -399,7 +398,7 @@ static void h3600ts_connect(struct serio *serio, struct serio_driver *drv)
"h3600_action", &ts->dev)) {
printk(KERN_ERR "h3600ts.c: Could not allocate Action Button IRQ!\n");
kfree(ts);
- return;
+ return -EBUSY;
}
if (request_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, npower_button_handler,
@@ -408,7 +407,7 @@ static void h3600ts_connect(struct serio *serio, struct serio_driver *drv)
free_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, &ts->dev);
printk(KERN_ERR "h3600ts.c: Could not allocate Power Button IRQ!\n");
kfree(ts);
- return;
+ return -EBUSY;
}
/* Now we have things going we setup our input device */
@@ -431,7 +430,6 @@ static void h3600ts_connect(struct serio *serio, struct serio_driver *drv)
ts->dev.keybit[LONG(KEY_SUSPEND)] |= BIT(KEY_SUSPEND);
ts->serio = serio;
- serio->private = ts;
sprintf(ts->phys, "%s/input0", serio->phys);
@@ -444,11 +442,15 @@ static void h3600ts_connect(struct serio *serio, struct serio_driver *drv)
ts->dev.id.product = 0x0666; /* FIXME !!! We can ask the hardware */
ts->dev.id.version = 0x0100;
- if (serio_open(serio, drv)) {
+ serio_set_drvdata(serio, ts);
+
+ err = serio_open(serio, drv);
+ if (err) {
free_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, ts);
free_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, ts);
+ serio_set_drvdata(serio, NULL);
kfree(ts);
- return;
+ return err;
}
//h3600_flite_control(1, 25); /* default brightness */
@@ -460,6 +462,8 @@ static void h3600ts_connect(struct serio *serio, struct serio_driver *drv)
input_register_device(&ts->dev);
printk(KERN_INFO "input: %s on %s\n", h3600_name, serio->phys);
+
+ return 0;
}
/*
@@ -468,24 +472,38 @@ static void h3600ts_connect(struct serio *serio, struct serio_driver *drv)
static void h3600ts_disconnect(struct serio *serio)
{
- struct h3600_dev *ts = serio->private;
+ struct h3600_dev *ts = serio_get_drvdata(serio);
- free_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, &ts->dev);
- free_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, &ts->dev);
+ free_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, &ts->dev);
+ free_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, &ts->dev);
input_unregister_device(&ts->dev);
serio_close(serio);
+ serio_set_drvdata(serio, NULL);
kfree(ts);
}
/*
- * The serio device structure.
+ * The serio driver structure.
*/
+static struct serio_device_id h3600ts_serio_ids[] = {
+ {
+ .type = SERIO_RS232,
+ .proto = SERIO_H3600,
+ .id = SERIO_ANY,
+ .extra = SERIO_ANY,
+ },
+ { 0 }
+};
+
+MODULE_DEVICE_TABLE(serio, h3600ts_serio_ids);
+
static struct serio_driver h3600ts_drv = {
.driver = {
.name = "h3600ts",
},
.description = DRIVER_DESC,
+ .id_table = h3600ts_serio_ids,
.interrupt = h3600ts_interrupt,
.connect = h3600ts_connect,
.disconnect = h3600ts_disconnect,
diff --git a/drivers/input/touchscreen/hp680_ts_input.c b/drivers/input/touchscreen/hp680_ts_input.c
new file mode 100644
index 0000000000000..7e1404441ecaa
--- /dev/null
+++ b/drivers/input/touchscreen/hp680_ts_input.c
@@ -0,0 +1,135 @@
+#include <linux/input.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <linux/interrupt.h>
+#include <asm/io.h>
+#include <asm/delay.h>
+#include <asm/adc.h>
+#include <asm/hp6xx/hp6xx.h>
+
+#define MODNAME "hp680_ts_input"
+
+#define HP680_TS_ABS_X_MIN 40
+#define HP680_TS_ABS_X_MAX 950
+#define HP680_TS_ABS_Y_MIN 80
+#define HP680_TS_ABS_Y_MAX 910
+
+#define SCPCR 0xa4000116
+#define PHDR 0xa400012e
+#define SCPDR 0xa4000136
+
+static void do_softint(void *data);
+
+static struct input_dev hp680_ts_dev;
+static DECLARE_WORK(work, do_softint, 0);
+static char *hp680_ts_name = "HP Jornada touchscreen";
+static char *hp680_ts_phys = "input0";
+
+static void do_softint(void *data)
+{
+ int absx = 0, absy = 0;
+ u8 scpdr;
+ int touched = 0;
+
+ if (ctrl_inb(PHDR) & PHDR_TS_PEN_DOWN) {
+ scpdr = ctrl_inb(SCPDR);
+ scpdr |= SCPDR_TS_SCAN_ENABLE;
+ scpdr &= ~SCPDR_TS_SCAN_Y;
+ ctrl_outb(scpdr, SCPDR);
+ udelay(30);
+
+ absy = adc_single(ADC_CHANNEL_TS_Y);
+
+ scpdr = ctrl_inb(SCPDR);
+ scpdr |= SCPDR_TS_SCAN_Y;
+ scpdr &= ~SCPDR_TS_SCAN_X;
+ ctrl_outb(scpdr, SCPDR);
+ udelay(30);
+
+ absx = adc_single(ADC_CHANNEL_TS_X);
+
+ scpdr = ctrl_inb(SCPDR);
+ scpdr |= SCPDR_TS_SCAN_X;
+ scpdr &= ~SCPDR_TS_SCAN_ENABLE;
+ ctrl_outb(scpdr, SCPDR);
+ udelay(100);
+ touched = ctrl_inb(PHDR) & PHDR_TS_PEN_DOWN;
+ }
+
+ if (touched) {
+ input_report_key(&hp680_ts_dev, BTN_TOUCH, 1);
+ input_report_abs(&hp680_ts_dev, ABS_X, absx);
+ input_report_abs(&hp680_ts_dev, ABS_Y, absy);
+ } else {
+ input_report_key(&hp680_ts_dev, BTN_TOUCH, 0);
+ }
+
+ input_sync(&hp680_ts_dev);
+ enable_irq(HP680_TS_IRQ);
+}
+
+static irqreturn_t hp680_ts_interrupt(int irq, void *dev, struct pt_regs *regs)
+{
+ disable_irq_nosync(irq);
+ schedule_delayed_work(&work, HZ / 20);
+
+ return IRQ_HANDLED;
+}
+
+static int __init hp680_ts_init(void)
+{
+ u8 scpdr;
+ u16 scpcr;
+
+ scpdr = ctrl_inb(SCPDR);
+ scpdr |= SCPDR_TS_SCAN_X | SCPDR_TS_SCAN_Y;
+ scpdr &= ~SCPDR_TS_SCAN_ENABLE;
+ ctrl_outb(scpdr, SCPDR);
+
+ scpcr = ctrl_inw(SCPCR);
+ scpcr &= ~SCPCR_TS_MASK;
+ scpcr |= SCPCR_TS_ENABLE;
+ ctrl_outw(scpcr, SCPCR);
+
+ memset(&hp680_ts_dev, 0, sizeof(hp680_ts_dev));
+ init_input_dev(&hp680_ts_dev);
+
+ hp680_ts_dev.evbit[0] = BIT(EV_ABS) | BIT(EV_KEY);
+ hp680_ts_dev.absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
+ hp680_ts_dev.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+
+ hp680_ts_dev.absmin[ABS_X] = HP680_TS_ABS_X_MIN;
+ hp680_ts_dev.absmin[ABS_Y] = HP680_TS_ABS_Y_MIN;
+ hp680_ts_dev.absmax[ABS_X] = HP680_TS_ABS_X_MAX;
+ hp680_ts_dev.absmax[ABS_Y] = HP680_TS_ABS_Y_MAX;
+
+ hp680_ts_dev.name = hp680_ts_name;
+ hp680_ts_dev.phys = hp680_ts_phys;
+ input_register_device(&hp680_ts_dev);
+
+ if (request_irq
+ (HP680_TS_IRQ, hp680_ts_interrupt, SA_INTERRUPT, MODNAME, 0) < 0) {
+ printk(KERN_ERR "hp680_touchscreen.c : Can't allocate irq %d\n",
+ HP680_TS_IRQ);
+ input_unregister_device(&hp680_ts_dev);
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
+static void __exit hp680_ts_exit(void)
+{
+ free_irq(HP680_TS_IRQ, 0);
+ cancel_delayed_work(&work);
+ flush_scheduled_work();
+ input_unregister_device(&hp680_ts_dev);
+}
+
+module_init(hp680_ts_init);
+module_exit(hp680_ts_exit);
+
+MODULE_AUTHOR("Andriy Skulysh, askulysh@image.kiev.ua");
+MODULE_DESCRIPTION("HP Jornada 680 touchscreen driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/mk712.c b/drivers/input/touchscreen/mk712.c
new file mode 100644
index 0000000000000..2d14a57a05e5d
--- /dev/null
+++ b/drivers/input/touchscreen/mk712.c
@@ -0,0 +1,222 @@
+/*
+ * ICS MK712 touchscreen controller driver
+ *
+ * Copyright (c) 1999-2002 Transmeta Corporation
+ * Copyright (c) 2005 Rick Koch <n1gp@hotmail.com>
+ * Copyright (c) 2005 Vojtech Pavlik <vojtech@suse.cz>
+ */
+
+/*
+ * 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 driver supports the ICS MicroClock MK712 TouchScreen controller,
+ * found in Gateway AOL Connected Touchpad computers.
+ *
+ * Documentation for ICS MK712 can be found at:
+ * http://www.icst.com/pdf/mk712.pdf
+ */
+
+/*
+ * 1999-12-18: original version, Daniel Quinlan
+ * 1999-12-19: added anti-jitter code, report pen-up events, fixed mk712_poll
+ * to use queue_empty, Nathan Laredo
+ * 1999-12-20: improved random point rejection, Nathan Laredo
+ * 2000-01-05: checked in new anti-jitter code, changed mouse protocol, fixed
+ * queue code, added module options, other fixes, Daniel Quinlan
+ * 2002-03-15: Clean up for kernel merge <alan@redhat.com>
+ * Fixed multi open race, fixed memory checks, fixed resource
+ * allocation, fixed close/powerdown bug, switched to new init
+ * 2005-01-18: Ported to 2.6 from 2.4.28, Rick Koch
+ * 2005-02-05: Rewritten for the input layer, Vojtech Pavlik
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/input.h>
+#include <asm/io.h>
+
+MODULE_AUTHOR("Daniel Quinlan <quinlan@pathname.com>, Vojtech Pavlik <vojtech@suse.cz>");
+MODULE_DESCRIPTION("ICS MicroClock MK712 TouchScreen driver");
+MODULE_LICENSE("GPL");
+
+static unsigned int mk712_io = 0x260; /* Also 0x200, 0x208, 0x300 */
+module_param_named(io, mk712_io, uint, 0);
+MODULE_PARM_DESC(io, "I/O base address of MK712 touchscreen controller");
+
+static unsigned int mk712_irq = 10; /* Also 12, 14, 15 */
+module_param_named(irq, mk712_irq, uint, 0);
+MODULE_PARM_DESC(irq, "IRQ of MK712 touchscreen controller");
+
+/* eight 8-bit registers */
+#define MK712_STATUS 0
+#define MK712_X 2
+#define MK712_Y 4
+#define MK712_CONTROL 6
+#define MK712_RATE 7
+
+/* status */
+#define MK712_STATUS_TOUCH 0x10
+#define MK712_CONVERSION_COMPLETE 0x80
+
+/* control */
+#define MK712_ENABLE_INT 0x01
+#define MK712_INT_ON_CONVERSION_COMPLETE 0x02
+#define MK712_INT_ON_CHANGE_IN_TOUCH_STATUS 0x04
+#define MK712_ENABLE_PERIODIC_CONVERSIONS 0x10
+#define MK712_READ_ONE_POINT 0x20
+#define MK712_POWERUP 0x40
+
+static int mk712_used = 0;
+static struct input_dev mk712_dev;
+static DEFINE_SPINLOCK(mk712_lock);
+
+static irqreturn_t mk712_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ unsigned char status;
+ static int debounce = 1;
+ static unsigned short last_x;
+ static unsigned short last_y;
+
+ spin_lock(&mk712_lock);
+ input_regs(&mk712_dev, regs);
+
+ status = inb(mk712_io + MK712_STATUS);
+
+ if (~status & MK712_CONVERSION_COMPLETE) {
+ debounce = 1;
+ goto end;
+ }
+
+ if (~status & MK712_STATUS_TOUCH)
+ {
+ debounce = 1;
+ input_report_key(&mk712_dev, BTN_TOUCH, 0);
+ goto end;
+ }
+
+ if (debounce)
+ {
+ debounce = 0;
+ goto end;
+ }
+
+ input_report_key(&mk712_dev, BTN_TOUCH, 1);
+ input_report_abs(&mk712_dev, ABS_X, last_x);
+ input_report_abs(&mk712_dev, ABS_Y, last_y);
+
+end:
+
+ last_x = inw(mk712_io + MK712_X) & 0x0fff;
+ last_y = inw(mk712_io + MK712_Y) & 0x0fff;
+ input_sync(&mk712_dev);
+ spin_unlock(&mk712_lock);
+ return IRQ_HANDLED;
+}
+
+static int mk712_open(struct input_dev *dev)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&mk712_lock, flags);
+
+ if (!mk712_used++) {
+
+ outb(0, mk712_io + MK712_CONTROL); /* Reset */
+
+ outb(MK712_ENABLE_INT | MK712_INT_ON_CONVERSION_COMPLETE |
+ MK712_INT_ON_CHANGE_IN_TOUCH_STATUS |
+ MK712_ENABLE_PERIODIC_CONVERSIONS |
+ MK712_POWERUP, mk712_io + MK712_CONTROL);
+
+ outb(10, mk712_io + MK712_RATE); /* 187 points per second */
+ }
+
+ spin_unlock_irqrestore(&mk712_lock, flags);
+
+ return 0;
+}
+
+static void mk712_close(struct input_dev *dev)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&mk712_lock, flags);
+
+ if (!--mk712_used)
+ outb(0, mk712_io + MK712_CONTROL);
+
+ spin_unlock_irqrestore(&mk712_lock, flags);
+}
+
+static struct input_dev mk712_dev = {
+ .evbit = { BIT(EV_KEY) | BIT(EV_ABS) },
+ .keybit = { [LONG(BTN_TOUCH)] = BIT(BTN_TOUCH) },
+ .absbit = { BIT(ABS_X) | BIT(ABS_Y) },
+ .open = mk712_open,
+ .close = mk712_close,
+ .name = "ICS MicroClock MK712 TouchScreen",
+ .phys = "isa0260/input0",
+ .absmin = { [ABS_X] = 0, [ABS_Y] = 0 },
+ .absmax = { [ABS_X] = 0xfff, [ABS_Y] = 0xfff },
+ .absfuzz = { [ABS_X] = 88, [ABS_Y] = 88 },
+ .id = {
+ .bustype = BUS_ISA,
+ .vendor = 0x0005,
+ .product = 0x0001,
+ .version = 0x0100,
+ },
+};
+
+int __init mk712_init(void)
+{
+
+ if(!request_region(mk712_io, 8, "mk712"))
+ {
+ printk(KERN_WARNING "mk712: unable to get IO region\n");
+ return -ENODEV;
+ }
+
+ outb(0, mk712_io + MK712_CONTROL);
+
+ if ((inw(mk712_io + MK712_X) & 0xf000) || /* Sanity check */
+ (inw(mk712_io + MK712_Y) & 0xf000) ||
+ (inw(mk712_io + MK712_STATUS) & 0xf333)) {
+ printk(KERN_WARNING "mk712: device not present\n");
+ release_region(mk712_io, 8);
+ return -ENODEV;
+ }
+
+ if(request_irq(mk712_irq, mk712_interrupt, 0, "mk712", &mk712_dev))
+ {
+ printk(KERN_WARNING "mk712: unable to get IRQ\n");
+ release_region(mk712_io, 8);
+ return -EBUSY;
+ }
+
+ input_register_device(&mk712_dev);
+
+ printk(KERN_INFO "input: ICS MicroClock MK712 TouchScreen at %#x irq %d\n", mk712_io, mk712_irq);
+
+ return 0;
+}
+
+static void __exit mk712_exit(void)
+{
+ input_unregister_device(&mk712_dev);
+ free_irq(mk712_irq, &mk712_dev);
+ release_region(mk712_io, 8);
+}
+
+module_init(mk712_init);
+module_exit(mk712_exit);
diff --git a/drivers/input/touchscreen/mtouch.c b/drivers/input/touchscreen/mtouch.c
new file mode 100644
index 0000000000000..aa8ee7842179c
--- /dev/null
+++ b/drivers/input/touchscreen/mtouch.c
@@ -0,0 +1,219 @@
+/*
+ * MicroTouch (3M) serial touchscreen driver
+ *
+ * Copyright (c) 2004 Vojtech Pavlik
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+/*
+ * 2005/02/19 Dan Streetman <ddstreet@ieee.org>
+ * Copied elo.c and edited for MicroTouch protocol
+ */
+
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/serio.h>
+#include <linux/init.h>
+
+#define DRIVER_DESC "MicroTouch serial touchscreen driver"
+
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+
+/*
+ * Definitions & global arrays.
+ */
+
+#define MTOUCH_FORMAT_TABLET_STATUS_BIT 0x80
+#define MTOUCH_FORMAT_TABLET_TOUCH_BIT 0x40
+#define MTOUCH_FORMAT_TABLET_LENGTH 5
+#define MTOUCH_RESPONSE_BEGIN_BYTE 0x01
+#define MTOUCH_RESPONSE_END_BYTE 0x0d
+
+/* todo: check specs for max length of all responses */
+#define MTOUCH_MAX_LENGTH 16
+
+#define MTOUCH_MIN_XC 0
+#define MTOUCH_MAX_XC 0x3fff
+#define MTOUCH_MIN_YC 0
+#define MTOUCH_MAX_YC 0x3fff
+
+#define MTOUCH_GET_XC(data) (((data[2])<<7) | data[1])
+#define MTOUCH_GET_YC(data) (((data[4])<<7) | data[3])
+#define MTOUCH_GET_TOUCHED(data) (MTOUCH_FORMAT_TABLET_TOUCH_BIT & data[0])
+
+static char *mtouch_name = "MicroTouch Serial TouchScreen";
+
+/*
+ * Per-touchscreen data.
+ */
+
+struct mtouch {
+ struct input_dev dev;
+ struct serio *serio;
+ int idx;
+ unsigned char data[MTOUCH_MAX_LENGTH];
+ char phys[32];
+};
+
+static void mtouch_process_format_tablet(struct mtouch *mtouch, struct pt_regs *regs)
+{
+ struct input_dev *dev = &mtouch->dev;
+
+ if (MTOUCH_FORMAT_TABLET_LENGTH == ++mtouch->idx) {
+ input_regs(dev, regs);
+ input_report_abs(dev, ABS_X, MTOUCH_GET_XC(mtouch->data));
+ input_report_abs(dev, ABS_Y, MTOUCH_MAX_YC - MTOUCH_GET_YC(mtouch->data));
+ input_report_key(dev, BTN_TOUCH, MTOUCH_GET_TOUCHED(mtouch->data));
+ input_sync(dev);
+
+ mtouch->idx = 0;
+ }
+}
+
+static void mtouch_process_response(struct mtouch *mtouch, struct pt_regs *regs)
+{
+ if (MTOUCH_RESPONSE_END_BYTE == mtouch->data[mtouch->idx++]) {
+ /* FIXME - process response */
+ mtouch->idx = 0;
+ } else if (MTOUCH_MAX_LENGTH == mtouch->idx) {
+ printk(KERN_ERR "mtouch.c: too many response bytes\n");
+ mtouch->idx = 0;
+ }
+}
+
+static irqreturn_t mtouch_interrupt(struct serio *serio,
+ unsigned char data, unsigned int flags, struct pt_regs *regs)
+{
+ struct mtouch* mtouch = serio_get_drvdata(serio);
+
+ mtouch->data[mtouch->idx] = data;
+
+ if (MTOUCH_FORMAT_TABLET_STATUS_BIT & mtouch->data[0])
+ mtouch_process_format_tablet(mtouch, regs);
+ else if (MTOUCH_RESPONSE_BEGIN_BYTE == mtouch->data[0])
+ mtouch_process_response(mtouch, regs);
+ else
+ printk(KERN_DEBUG "mtouch.c: unknown/unsynchronized data from device, byte %x\n",mtouch->data[0]);
+
+ return IRQ_HANDLED;
+}
+
+/*
+ * mtouch_disconnect() is the opposite of mtouch_connect()
+ */
+
+static void mtouch_disconnect(struct serio *serio)
+{
+ struct mtouch* mtouch = serio_get_drvdata(serio);
+
+ input_unregister_device(&mtouch->dev);
+ serio_close(serio);
+ serio_set_drvdata(serio, NULL);
+ kfree(mtouch);
+}
+
+/*
+ * mtouch_connect() is the routine that is called when someone adds a
+ * new serio device that supports MicroTouch (Format Tablet) protocol and registers it as
+ * an input device.
+ */
+
+static int mtouch_connect(struct serio *serio, struct serio_driver *drv)
+{
+ struct mtouch *mtouch;
+ int err;
+
+ if (!(mtouch = kmalloc(sizeof(*mtouch), GFP_KERNEL)))
+ return -ENOMEM;
+
+ memset(mtouch, 0, sizeof(*mtouch));
+
+ init_input_dev(&mtouch->dev);
+ mtouch->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ mtouch->dev.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+
+ input_set_abs_params(&mtouch->dev, ABS_X, MTOUCH_MIN_XC, MTOUCH_MAX_XC, 0, 0);
+ input_set_abs_params(&mtouch->dev, ABS_Y, MTOUCH_MIN_YC, MTOUCH_MAX_YC, 0, 0);
+
+ mtouch->serio = serio;
+
+ sprintf(mtouch->phys, "%s/input0", serio->phys);
+
+ mtouch->dev.private = mtouch;
+ mtouch->dev.name = mtouch_name;
+ mtouch->dev.phys = mtouch->phys;
+ mtouch->dev.id.bustype = BUS_RS232;
+ mtouch->dev.id.vendor = SERIO_MICROTOUCH;
+ mtouch->dev.id.product = 0;
+ mtouch->dev.id.version = 0x0100;
+
+ serio_set_drvdata(serio, mtouch);
+
+ err = serio_open(serio, drv);
+ if (err) {
+ serio_set_drvdata(serio, NULL);
+ kfree(mtouch);
+ return err;
+ }
+
+ input_register_device(&mtouch->dev);
+
+ printk(KERN_INFO "input: %s on %s\n", mtouch->dev.name, serio->phys);
+
+ return 0;
+}
+
+/*
+ * The serio driver structure.
+ */
+
+static struct serio_device_id mtouch_serio_ids[] = {
+ {
+ .type = SERIO_RS232,
+ .proto = SERIO_MICROTOUCH,
+ .id = SERIO_ANY,
+ .extra = SERIO_ANY,
+ },
+ { 0 }
+};
+
+MODULE_DEVICE_TABLE(serio, mtouch_serio_ids);
+
+static struct serio_driver mtouch_drv = {
+ .driver = {
+ .name = "mtouch",
+ },
+ .description = DRIVER_DESC,
+ .id_table = mtouch_serio_ids,
+ .interrupt = mtouch_interrupt,
+ .connect = mtouch_connect,
+ .disconnect = mtouch_disconnect,
+};
+
+/*
+ * The functions for inserting/removing us as a module.
+ */
+
+static int __init mtouch_init(void)
+{
+ serio_register_driver(&mtouch_drv);
+ return 0;
+}
+
+static void __exit mtouch_exit(void)
+{
+ serio_unregister_driver(&mtouch_drv);
+}
+
+module_init(mtouch_init);
+module_exit(mtouch_exit);
diff --git a/drivers/input/tsdev.c b/drivers/input/tsdev.c
index 9c00dbd39c6fa..d0afba85720be 100644
--- a/drivers/input/tsdev.c
+++ b/drivers/input/tsdev.c
@@ -232,11 +232,9 @@ static ssize_t tsdev_read(struct file *file, char __user *buffer, size_t count,
static unsigned int tsdev_poll(struct file *file, poll_table * wait)
{
struct tsdev_list *list = file->private_data;
-
poll_wait(file, &list->tsdev->wait, wait);
- if (list->head != list->tail)
- return POLLIN | POLLRDNORM;
- return 0;
+ return ((list->head == list->tail) ? 0 : (POLLIN | POLLRDNORM)) |
+ (list->tsdev->exist ? 0 : (POLLHUP | POLLERR));
}
static int tsdev_ioctl(struct inode *inode, struct file *file,
@@ -265,7 +263,7 @@ static int tsdev_ioctl(struct inode *inode, struct file *file,
return retval;
}
-struct file_operations tsdev_fops = {
+static struct file_operations tsdev_fops = {
.owner = THIS_MODULE,
.open = tsdev_open,
.release = tsdev_release,
@@ -426,6 +424,7 @@ static struct input_handle *tsdev_connect(struct input_handler *handler,
static void tsdev_disconnect(struct input_handle *handle)
{
struct tsdev *tsdev = handle->private;
+ struct tsdev_list *list;
class_simple_device_remove(MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + tsdev->minor));
devfs_remove("input/ts%d", tsdev->minor);
@@ -435,6 +434,8 @@ static void tsdev_disconnect(struct input_handle *handle)
if (tsdev->open) {
input_close_device(handle);
wake_up_interruptible(&tsdev->wait);
+ list_for_each_entry(list, &tsdev->list, node)
+ kill_fasync(&list->fasync, SIGIO, POLL_HUP);
} else
tsdev_free(tsdev);
}
diff --git a/drivers/isdn/Makefile b/drivers/isdn/Makefile
index 2f3e65b763e5b..03d8ccd51955c 100644
--- a/drivers/isdn/Makefile
+++ b/drivers/isdn/Makefile
@@ -13,4 +13,3 @@ obj-$(CONFIG_ISDN_DRV_SC) += sc/
obj-$(CONFIG_ISDN_DRV_LOOP) += isdnloop/
obj-$(CONFIG_ISDN_DRV_ACT2000) += act2000/
obj-$(CONFIG_HYSDN) += hysdn/
-obj-$(CONFIG_ISDN_DRV_TPAM) += tpam/
diff --git a/drivers/isdn/act2000/act2000_isa.c b/drivers/isdn/act2000/act2000_isa.c
index df7923c5b843a..bc98d77c5ecdc 100644
--- a/drivers/isdn/act2000/act2000_isa.c
+++ b/drivers/isdn/act2000/act2000_isa.c
@@ -401,7 +401,6 @@ int
act2000_isa_download(act2000_card * card, act2000_ddef __user * cb)
{
unsigned int length;
- int ret;
int l;
int c;
long timeout;
@@ -413,12 +412,12 @@ act2000_isa_download(act2000_card * card, act2000_ddef __user * cb)
if (!act2000_isa_reset(card->port))
return -ENXIO;
msleep_interruptible(500);
- if(copy_from_user(&cblock, cb, sizeof(cblock)))
+ if (copy_from_user(&cblock, cb, sizeof(cblock)))
return -EFAULT;
length = cblock.length;
p = cblock.buffer;
- if ((ret = verify_area(VERIFY_READ, p, length)))
- return ret;
+ if (!access_ok(VERIFY_READ, p, length))
+ return -EFAULT;
buf = (u_char *) kmalloc(1024, GFP_KERNEL);
if (!buf)
return -ENOMEM;
diff --git a/drivers/isdn/hardware/avm/b1pci.c b/drivers/isdn/hardware/avm/b1pci.c
index 4d4f63cf15a15..5435a6cfb5e7a 100644
--- a/drivers/isdn/hardware/avm/b1pci.c
+++ b/drivers/isdn/hardware/avm/b1pci.c
@@ -391,7 +391,7 @@ static int __init b1pci_init(void)
strcpy(rev, "1.0");
- err = pci_module_init(&b1pci_pci_driver);
+ err = pci_register_driver(&b1pci_pci_driver);
if (!err) {
strlcpy(capi_driver_b1pci.revision, rev, 32);
register_capi_driver(&capi_driver_b1pci);
diff --git a/drivers/isdn/hardware/avm/c4.c b/drivers/isdn/hardware/avm/c4.c
index 0e40acac7ffeb..fa6b93b1a42d6 100644
--- a/drivers/isdn/hardware/avm/c4.c
+++ b/drivers/isdn/hardware/avm/c4.c
@@ -1288,7 +1288,7 @@ static int __init c4_init(void)
} else
strcpy(rev, "1.0");
- err = pci_module_init(&c4_pci_driver);
+ err = pci_register_driver(&c4_pci_driver);
if (!err) {
strlcpy(capi_driver_c2.revision, rev, 32);
register_capi_driver(&capi_driver_c2);
diff --git a/drivers/isdn/hardware/avm/t1pci.c b/drivers/isdn/hardware/avm/t1pci.c
index 5bfa89fb7f862..2ceec8e8419f3 100644
--- a/drivers/isdn/hardware/avm/t1pci.c
+++ b/drivers/isdn/hardware/avm/t1pci.c
@@ -241,7 +241,7 @@ static int __init t1pci_init(void)
} else
strcpy(rev, "1.0");
- err = pci_module_init(&t1pci_pci_driver);
+ err = pci_register_driver(&t1pci_pci_driver);
if (!err) {
strlcpy(capi_driver_t1pci.revision, rev, 32);
register_capi_driver(&capi_driver_t1pci);
diff --git a/drivers/isdn/hisax/Kconfig b/drivers/isdn/hisax/Kconfig
index c7709db82c186..6c7b8bffc6fdb 100644
--- a/drivers/isdn/hisax/Kconfig
+++ b/drivers/isdn/hisax/Kconfig
@@ -411,6 +411,12 @@ config HISAX_HFCUSB
help
This enables the driver for HFC USB based ISDN modems.
+config HISAX_HFC4S8S
+ tristate "HFC-4S/8S based ISDN cards (EXPERIMENTAL)"
+ depends on EXPERIMENTAL
+ help
+ This enables the driver for HFC-4S/8S based ISDN cards.
+
config HISAX_FRITZ_PCIPNP
tristate "AVM Fritz!Card PCI/PCIv2/PnP support (EXPERIMENTAL)"
depends on PCI && EXPERIMENTAL
diff --git a/drivers/isdn/hisax/Makefile b/drivers/isdn/hisax/Makefile
index eb748e1fa31de..8d6bb56754b8c 100644
--- a/drivers/isdn/hisax/Makefile
+++ b/drivers/isdn/hisax/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_HISAX_AVM_A1_CS) += avma1_cs.o
obj-$(CONFIG_HISAX_TELES_CS) += teles_cs.o
obj-$(CONFIG_HISAX_ST5481) += hisax_st5481.o
obj-$(CONFIG_HISAX_HFCUSB) += hfc_usb.o
+obj-$(CONFIG_HISAX_HFC4S8S) += hfc4s8s_l1.o
obj-$(CONFIG_HISAX_FRITZ_PCIPNP) += hisax_isac.o hisax_fcpcipnp.o
ifdef CONFIG_HISAX_HDLC
diff --git a/drivers/isdn/hisax/elsa.c b/drivers/isdn/hisax/elsa.c
index 21271465bd2f2..4d7a0250d7e20 100644
--- a/drivers/isdn/hisax/elsa.c
+++ b/drivers/isdn/hisax/elsa.c
@@ -838,7 +838,7 @@ static struct pci_dev *dev_qs1000 __devinitdata = NULL;
static struct pci_dev *dev_qs3000 __devinitdata = NULL;
#ifdef __ISAPNP__
-static struct isapnp_device_id elsa_ids[] __initdata = {
+static struct isapnp_device_id elsa_ids[] __devinitdata = {
{ ISAPNP_VENDOR('E', 'L', 'S'), ISAPNP_FUNCTION(0x0133),
ISAPNP_VENDOR('E', 'L', 'S'), ISAPNP_FUNCTION(0x0133),
(unsigned long) "Elsa QS1000" },
@@ -848,7 +848,7 @@ static struct isapnp_device_id elsa_ids[] __initdata = {
{ 0, }
};
-static struct isapnp_device_id *ipid __initdata = &elsa_ids[0];
+static struct isapnp_device_id *ipid __devinitdata = &elsa_ids[0];
static struct pnp_card *pnp_c __devinitdata = NULL;
#endif
diff --git a/drivers/isdn/hisax/hfc4s8s_l1.c b/drivers/isdn/hisax/hfc4s8s_l1.c
new file mode 100644
index 0000000000000..1ac46c26b9363
--- /dev/null
+++ b/drivers/isdn/hisax/hfc4s8s_l1.c
@@ -0,0 +1,1714 @@
+/*************************************************************************/
+/* $Id: hfc4s8s_l1.c,v 1.10 2005/02/09 16:31:09 martinb1 Exp $ */
+/* HFC-4S/8S low layer interface for Cologne Chip HFC-4S/8S isdn chips */
+/* The low layer (L1) is implemented as a loadable module for usage with */
+/* the HiSax isdn driver for passive cards. */
+/* */
+/* Author: Werner Cornelius */
+/* (C) 2003 Cornelius Consult (werner@cornelius-consult.de) */
+/* */
+/* Driver maintained by Cologne Chip */
+/* - Martin Bachem, support@colognechip.com */
+/* */
+/* This driver only works with chip revisions >= 1, older revision 0 */
+/* engineering samples (only first manufacturer sample cards) will not */
+/* work and are rejected by the driver. */
+/* */
+/* This file distributed under the GNU GPL. */
+/* */
+/* See Version History at the end of this file */
+/* */
+/*************************************************************************/
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/config.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/skbuff.h>
+#include <linux/wait.h>
+#include "hisax_if.h"
+#include "hfc4s8s_l1.h"
+
+static const char hfc4s8s_rev[] = "Revision: 1.10";
+
+/***************************************************************/
+/* adjustable transparent mode fifo threshold */
+/* The value defines the used fifo threshold with the equation */
+/* */
+/* notify number of bytes = 2 * 2 ^ TRANS_FIFO_THRES */
+/* */
+/* The default value is 5 which results in a buffer size of 64 */
+/* and an interrupt rate of 8ms. */
+/* The maximum value is 7 due to fifo size restrictions. */
+/* Values below 3-4 are not recommended due to high interrupt */
+/* load of the processor. For non critical applications the */
+/* value should be raised to 7 to reduce any interrupt overhead*/
+/***************************************************************/
+#define TRANS_FIFO_THRES 5
+
+/*************/
+/* constants */
+/*************/
+#define CLOCKMODE_0 0 /* ext. 24.576 MhZ clk freq, int. single clock mode */
+#define CLOCKMODE_1 1 /* ext. 49.576 MhZ clk freq, int. single clock mode */
+#define CHIP_ID_SHIFT 4
+#define HFC_MAX_ST 8
+#define MAX_D_FRAME_SIZE 270
+#define MAX_B_FRAME_SIZE 1536
+#define TRANS_TIMER_MODE (TRANS_FIFO_THRES & 0xf)
+#define TRANS_FIFO_BYTES (2 << TRANS_FIFO_THRES)
+#define MAX_F_CNT 0x0f
+
+#define CLKDEL_NT 0x6c
+#define CLKDEL_TE 0xf
+#define CTRL0_NT 4
+#define CTRL0_TE 0
+
+#define L1_TIMER_T4 2 /* minimum in jiffies */
+#define L1_TIMER_T3 (7 * HZ) /* activation timeout */
+#define L1_TIMER_T1 ((120 * HZ) / 1000) /* NT mode deactivation timeout */
+
+
+/******************/
+/* types and vars */
+/******************/
+static int card_cnt;
+
+/* private driver_data */
+typedef struct {
+ int chip_id;
+ int clock_mode;
+ int max_st_ports;
+ char *device_name;
+} hfc4s8s_param;
+
+static struct pci_device_id hfc4s8s_ids[] = {
+ {.vendor = PCI_VENDOR_ID_CCD,
+ .device = PCI_DEVICE_ID_4S,
+ .subvendor = 0x1397,
+ .subdevice = 0x08b4,
+ .driver_data =
+ (unsigned long) &((hfc4s8s_param) {CHIP_ID_4S, CLOCKMODE_0, 4,
+ "HFC-4S Evaluation Board"}),
+ },
+ {.vendor = PCI_VENDOR_ID_CCD,
+ .device = PCI_DEVICE_ID_8S,
+ .subvendor = 0x1397,
+ .subdevice = 0x16b8,
+ .driver_data =
+ (unsigned long) &((hfc4s8s_param) {CHIP_ID_8S, CLOCKMODE_0, 8,
+ "HFC-8S Evaluation Board"}),
+ },
+ {.vendor = PCI_VENDOR_ID_CCD,
+ .device = PCI_DEVICE_ID_4S,
+ .subvendor = 0x1397,
+ .subdevice = 0xb520,
+ .driver_data =
+ (unsigned long) &((hfc4s8s_param) {CHIP_ID_4S, CLOCKMODE_1, 4,
+ "IOB4ST"}),
+ },
+ {.vendor = PCI_VENDOR_ID_CCD,
+ .device = PCI_DEVICE_ID_8S,
+ .subvendor = 0x1397,
+ .subdevice = 0xb522,
+ .driver_data =
+ (unsigned long) &((hfc4s8s_param) {CHIP_ID_8S, CLOCKMODE_1, 8,
+ "IOB8ST"}),
+ },
+ {}
+};
+
+MODULE_DEVICE_TABLE(pci, hfc4s8s_ids);
+
+MODULE_AUTHOR("Werner Cornelius, werner@cornelius-consult.de");
+MODULE_DESCRIPTION("ISDN layer 1 for Cologne Chip HFC-4S/8S chips");
+MODULE_LICENSE("GPL");
+
+/***********/
+/* layer 1 */
+/***********/
+struct hfc4s8s_btype {
+ spinlock_t lock;
+ struct hisax_b_if b_if;
+ struct hfc4s8s_l1 *l1p;
+ struct sk_buff_head tx_queue;
+ struct sk_buff *tx_skb;
+ struct sk_buff *rx_skb;
+ __u8 *rx_ptr;
+ int tx_cnt;
+ int bchan;
+ int mode;
+};
+
+struct _hfc4s8s_hw;
+
+struct hfc4s8s_l1 {
+ spinlock_t lock;
+ struct _hfc4s8s_hw *hw; /* pointer to hardware area */
+ int l1_state; /* actual l1 state */
+ struct timer_list l1_timer; /* layer 1 timer structure */
+ int nt_mode; /* set to nt mode */
+ int st_num; /* own index */
+ int enabled; /* interface is enabled */
+ struct sk_buff_head d_tx_queue; /* send queue */
+ int tx_cnt; /* bytes to send */
+ struct hisax_d_if d_if; /* D-channel interface */
+ struct hfc4s8s_btype b_ch[2]; /* B-channel data */
+ struct hisax_b_if *b_table[2];
+};
+
+/**********************/
+/* hardware structure */
+/**********************/
+typedef struct _hfc4s8s_hw {
+ spinlock_t lock;
+
+ int cardnum;
+ int ifnum;
+ int iobase;
+ int nt_mode;
+ u_char *membase;
+ u_char *hw_membase;
+ void *pdev;
+ int max_fifo;
+ hfc4s8s_param driver_data;
+ int irq;
+ int fifo_sched_cnt;
+ struct work_struct tqueue;
+ struct hfc4s8s_l1 l1[HFC_MAX_ST];
+ char card_name[60];
+ struct {
+ u_char r_irq_ctrl;
+ u_char r_ctrl0;
+ volatile u_char r_irq_statech; /* active isdn l1 status */
+ u_char r_irqmsk_statchg; /* enabled isdn status ints */
+ u_char r_irq_fifo_blx[8]; /* fifo status registers */
+ u_char fifo_rx_trans_enables[8]; /* mask for enabled transparent rx fifos */
+ u_char fifo_slow_timer_service[8]; /* mask for fifos needing slower timer service */
+ volatile u_char r_irq_oview; /* contents of overview register */
+ volatile u_char timer_irq;
+ int timer_usg_cnt; /* number of channels using timer */
+ } mr;
+} hfc4s8s_hw;
+
+
+
+/***************************/
+/* inline function defines */
+/***************************/
+#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM /* inline functions mempry mapped */
+
+/* memory write and dummy IO read to avoid PCI byte merge problems */
+#define Write_hfc8(a,b,c) {(*((volatile u_char *)(a->membase+b)) = c); inb(a->iobase+4);}
+/* memory write without dummy IO access for fifo data access */
+#define fWrite_hfc8(a,b,c) (*((volatile u_char *)(a->membase+b)) = c)
+#define Read_hfc8(a,b) (*((volatile u_char *)(a->membase+b)))
+#define Write_hfc16(a,b,c) (*((volatile unsigned short *)(a->membase+b)) = c)
+#define Read_hfc16(a,b) (*((volatile unsigned short *)(a->membase+b)))
+#define Write_hfc32(a,b,c) (*((volatile unsigned long *)(a->membase+b)) = c)
+#define Read_hfc32(a,b) (*((volatile unsigned long *)(a->membase+b)))
+#define wait_busy(a) {while ((Read_hfc8(a, R_STATUS) & M_BUSY));}
+#define PCI_ENA_MEMIO 0x03
+
+#else
+
+/* inline functions io mapped */
+static inline void
+SetRegAddr(hfc4s8s_hw * a, u_char b)
+{
+ outb(b, (a->iobase) + 4);
+}
+
+static inline u_char
+GetRegAddr(hfc4s8s_hw * a)
+{
+ return (inb((volatile u_int) (a->iobase + 4)));
+}
+
+
+static inline void
+Write_hfc8(hfc4s8s_hw * a, u_char b, u_char c)
+{
+ SetRegAddr(a, b);
+ outb(c, a->iobase);
+}
+
+static inline void
+fWrite_hfc8(hfc4s8s_hw * a, u_char c)
+{
+ outb(c, a->iobase);
+}
+
+static inline void
+Write_hfc16(hfc4s8s_hw * a, u_char b, u_short c)
+{
+ SetRegAddr(a, b);
+ outw(c, a->iobase);
+}
+
+static inline void
+Write_hfc32(hfc4s8s_hw * a, u_char b, u_long c)
+{
+ SetRegAddr(a, b);
+ outl(c, a->iobase);
+}
+
+static inline void
+fWrite_hfc32(hfc4s8s_hw * a, u_long c)
+{
+ outl(c, a->iobase);
+}
+
+static inline u_char
+Read_hfc8(hfc4s8s_hw * a, u_char b)
+{
+ SetRegAddr(a, b);
+ return (inb((volatile u_int) a->iobase));
+}
+
+static inline u_char
+fRead_hfc8(hfc4s8s_hw * a)
+{
+ return (inb((volatile u_int) a->iobase));
+}
+
+
+static inline u_short
+Read_hfc16(hfc4s8s_hw * a, u_char b)
+{
+ SetRegAddr(a, b);
+ return (inw((volatile u_int) a->iobase));
+}
+
+static inline u_long
+Read_hfc32(hfc4s8s_hw * a, u_char b)
+{
+ SetRegAddr(a, b);
+ return (inl((volatile u_int) a->iobase));
+}
+
+static inline u_long
+fRead_hfc32(hfc4s8s_hw * a)
+{
+ return (inl((volatile u_int) a->iobase));
+}
+
+static inline void
+wait_busy(hfc4s8s_hw * a)
+{
+ SetRegAddr(a, R_STATUS);
+ while (inb((volatile u_int) a->iobase) & M_BUSY);
+}
+
+#define PCI_ENA_REGIO 0x01
+
+#endif /* CONFIG_HISAX_HFC4S8S_PCIMEM */
+
+/******************************************************/
+/* function to read critical counter registers that */
+/* may be udpated by the chip during read */
+/******************************************************/
+static volatile u_char
+Read_hfc8_stable(hfc4s8s_hw * hw, int reg)
+{
+ u_char ref8;
+ u_char in8;
+ ref8 = Read_hfc8(hw, reg);
+ while (((in8 = Read_hfc8(hw, reg)) != ref8)) {
+ ref8 = in8;
+ }
+ return in8;
+}
+
+static volatile int
+Read_hfc16_stable(hfc4s8s_hw * hw, int reg)
+{
+ int ref16;
+ int in16;
+
+ ref16 = Read_hfc16(hw, reg);
+ while (((in16 = Read_hfc16(hw, reg)) != ref16)) {
+ ref16 = in16;
+ }
+ return in16;
+}
+
+/*****************************/
+/* D-channel call from HiSax */
+/*****************************/
+static void
+dch_l2l1(struct hisax_d_if *iface, int pr, void *arg)
+{
+ struct hfc4s8s_l1 *l1 = iface->ifc.priv;
+ struct sk_buff *skb = (struct sk_buff *) arg;
+ u_long flags;
+
+ switch (pr) {
+
+ case (PH_DATA | REQUEST):
+ if (!l1->enabled) {
+ dev_kfree_skb(skb);
+ break;
+ }
+ spin_lock_irqsave(&l1->lock, flags);
+ skb_queue_tail(&l1->d_tx_queue, skb);
+ if ((skb_queue_len(&l1->d_tx_queue) == 1) &&
+ (l1->tx_cnt <= 0)) {
+ l1->hw->mr.r_irq_fifo_blx[l1->st_num] |=
+ 0x10;
+ spin_unlock_irqrestore(&l1->lock, flags);
+ schedule_work(&l1->hw->tqueue);
+ } else
+ spin_unlock_irqrestore(&l1->lock, flags);
+ break;
+
+ case (PH_ACTIVATE | REQUEST):
+ if (!l1->enabled)
+ break;
+ if (!l1->nt_mode) {
+ if (l1->l1_state < 6) {
+ spin_lock_irqsave(&l1->lock,
+ flags);
+
+ Write_hfc8(l1->hw, R_ST_SEL,
+ l1->st_num);
+ Write_hfc8(l1->hw, A_ST_WR_STA,
+ 0x60);
+ mod_timer(&l1->l1_timer,
+ jiffies + L1_TIMER_T3);
+ spin_unlock_irqrestore(&l1->lock,
+ flags);
+ } else if (l1->l1_state == 7)
+ l1->d_if.ifc.l1l2(&l1->d_if.ifc,
+ PH_ACTIVATE |
+ INDICATION,
+ NULL);
+ } else {
+ if (l1->l1_state != 3) {
+ spin_lock_irqsave(&l1->lock,
+ flags);
+ Write_hfc8(l1->hw, R_ST_SEL,
+ l1->st_num);
+ Write_hfc8(l1->hw, A_ST_WR_STA,
+ 0x60);
+ spin_unlock_irqrestore(&l1->lock,
+ flags);
+ } else if (l1->l1_state == 3)
+ l1->d_if.ifc.l1l2(&l1->d_if.ifc,
+ PH_ACTIVATE |
+ INDICATION,
+ NULL);
+ }
+ break;
+
+ default:
+ printk(KERN_INFO
+ "HFC-4S/8S: Unknown D-chan cmd 0x%x received, ignored\n",
+ pr);
+ break;
+ }
+ if (!l1->enabled)
+ l1->d_if.ifc.l1l2(&l1->d_if.ifc,
+ PH_DEACTIVATE | INDICATION, NULL);
+} /* dch_l2l1 */
+
+/*****************************/
+/* B-channel call from HiSax */
+/*****************************/
+static void
+bch_l2l1(struct hisax_if *ifc, int pr, void *arg)
+{
+ struct hfc4s8s_btype *bch = ifc->priv;
+ struct hfc4s8s_l1 *l1 = bch->l1p;
+ struct sk_buff *skb = (struct sk_buff *) arg;
+ int mode = (int) arg;
+ u_long flags;
+
+ switch (pr) {
+
+ case (PH_DATA | REQUEST):
+ if (!l1->enabled || (bch->mode == L1_MODE_NULL)) {
+ dev_kfree_skb(skb);
+ break;
+ }
+ spin_lock_irqsave(&l1->lock, flags);
+ skb_queue_tail(&bch->tx_queue, skb);
+ if (!bch->tx_skb && (bch->tx_cnt <= 0)) {
+ l1->hw->mr.r_irq_fifo_blx[l1->st_num] |=
+ ((bch->bchan == 1) ? 1 : 4);
+ spin_unlock_irqrestore(&l1->lock, flags);
+ schedule_work(&l1->hw->tqueue);
+ } else
+ spin_unlock_irqrestore(&l1->lock, flags);
+ break;
+
+ case (PH_ACTIVATE | REQUEST):
+ case (PH_DEACTIVATE | REQUEST):
+ if (!l1->enabled)
+ break;
+ if (pr == (PH_DEACTIVATE | REQUEST))
+ mode = L1_MODE_NULL;
+
+ switch (mode) {
+ case L1_MODE_HDLC:
+ spin_lock_irqsave(&l1->lock,
+ flags);
+ l1->hw->mr.timer_usg_cnt++;
+ l1->hw->mr.
+ fifo_slow_timer_service[l1->
+ st_num]
+ |=
+ ((bch->bchan ==
+ 1) ? 0x2 : 0x8);
+ Write_hfc8(l1->hw, R_FIFO,
+ (l1->st_num * 8 +
+ ((bch->bchan ==
+ 1) ? 0 : 2)));
+ wait_busy(l1->hw);
+ Write_hfc8(l1->hw, A_CON_HDLC, 0xc); /* HDLC mode, flag fill, connect ST */
+ Write_hfc8(l1->hw, A_SUBCH_CFG, 0); /* 8 bits */
+ Write_hfc8(l1->hw, A_IRQ_MSK, 1); /* enable TX interrupts for hdlc */
+ Write_hfc8(l1->hw, A_INC_RES_FIFO, 2); /* reset fifo */
+ wait_busy(l1->hw);
+
+ Write_hfc8(l1->hw, R_FIFO,
+ (l1->st_num * 8 +
+ ((bch->bchan ==
+ 1) ? 1 : 3)));
+ wait_busy(l1->hw);
+ Write_hfc8(l1->hw, A_CON_HDLC, 0xc); /* HDLC mode, flag fill, connect ST */
+ Write_hfc8(l1->hw, A_SUBCH_CFG, 0); /* 8 bits */
+ Write_hfc8(l1->hw, A_IRQ_MSK, 1); /* enable RX interrupts for hdlc */
+ Write_hfc8(l1->hw, A_INC_RES_FIFO, 2); /* reset fifo */
+
+ Write_hfc8(l1->hw, R_ST_SEL,
+ l1->st_num);
+ l1->hw->mr.r_ctrl0 |=
+ (bch->bchan & 3);
+ Write_hfc8(l1->hw, A_ST_CTRL0,
+ l1->hw->mr.r_ctrl0);
+ bch->mode = L1_MODE_HDLC;
+ spin_unlock_irqrestore(&l1->lock,
+ flags);
+
+ bch->b_if.ifc.l1l2(&bch->b_if.ifc,
+ PH_ACTIVATE |
+ INDICATION,
+ NULL);
+ break;
+
+ case L1_MODE_TRANS:
+ spin_lock_irqsave(&l1->lock,
+ flags);
+ l1->hw->mr.
+ fifo_rx_trans_enables[l1->
+ st_num]
+ |=
+ ((bch->bchan ==
+ 1) ? 0x2 : 0x8);
+ l1->hw->mr.timer_usg_cnt++;
+ Write_hfc8(l1->hw, R_FIFO,
+ (l1->st_num * 8 +
+ ((bch->bchan ==
+ 1) ? 0 : 2)));
+ wait_busy(l1->hw);
+ Write_hfc8(l1->hw, A_CON_HDLC, 0xf); /* Transparent mode, 1 fill, connect ST */
+ Write_hfc8(l1->hw, A_SUBCH_CFG, 0); /* 8 bits */
+ Write_hfc8(l1->hw, A_IRQ_MSK, 0); /* disable TX interrupts */
+ Write_hfc8(l1->hw, A_INC_RES_FIFO, 2); /* reset fifo */
+ wait_busy(l1->hw);
+
+ Write_hfc8(l1->hw, R_FIFO,
+ (l1->st_num * 8 +
+ ((bch->bchan ==
+ 1) ? 1 : 3)));
+ wait_busy(l1->hw);
+ Write_hfc8(l1->hw, A_CON_HDLC, 0xf); /* Transparent mode, 1 fill, connect ST */
+ Write_hfc8(l1->hw, A_SUBCH_CFG, 0); /* 8 bits */
+ Write_hfc8(l1->hw, A_IRQ_MSK, 0); /* disable RX interrupts */
+ Write_hfc8(l1->hw, A_INC_RES_FIFO, 2); /* reset fifo */
+
+ Write_hfc8(l1->hw, R_ST_SEL,
+ l1->st_num);
+ l1->hw->mr.r_ctrl0 |=
+ (bch->bchan & 3);
+ Write_hfc8(l1->hw, A_ST_CTRL0,
+ l1->hw->mr.r_ctrl0);
+ bch->mode = L1_MODE_TRANS;
+ spin_unlock_irqrestore(&l1->lock,
+ flags);
+
+ bch->b_if.ifc.l1l2(&bch->b_if.ifc,
+ PH_ACTIVATE |
+ INDICATION,
+ NULL);
+ break;
+
+ default:
+ if (bch->mode == L1_MODE_NULL)
+ break;
+ spin_lock_irqsave(&l1->lock,
+ flags);
+ l1->hw->mr.
+ fifo_slow_timer_service[l1->
+ st_num]
+ &=
+ ~((bch->bchan ==
+ 1) ? 0x3 : 0xc);
+ l1->hw->mr.
+ fifo_rx_trans_enables[l1->
+ st_num]
+ &=
+ ~((bch->bchan ==
+ 1) ? 0x3 : 0xc);
+ l1->hw->mr.timer_usg_cnt--;
+ Write_hfc8(l1->hw, R_FIFO,
+ (l1->st_num * 8 +
+ ((bch->bchan ==
+ 1) ? 0 : 2)));
+ wait_busy(l1->hw);
+ Write_hfc8(l1->hw, A_IRQ_MSK, 0); /* disable TX interrupts */
+ wait_busy(l1->hw);
+ Write_hfc8(l1->hw, R_FIFO,
+ (l1->st_num * 8 +
+ ((bch->bchan ==
+ 1) ? 1 : 3)));
+ wait_busy(l1->hw);
+ Write_hfc8(l1->hw, A_IRQ_MSK, 0); /* disable RX interrupts */
+ Write_hfc8(l1->hw, R_ST_SEL,
+ l1->st_num);
+ l1->hw->mr.r_ctrl0 &=
+ ~(bch->bchan & 3);
+ Write_hfc8(l1->hw, A_ST_CTRL0,
+ l1->hw->mr.r_ctrl0);
+ spin_unlock_irqrestore(&l1->lock,
+ flags);
+
+ bch->mode = L1_MODE_NULL;
+ bch->b_if.ifc.l1l2(&bch->b_if.ifc,
+ PH_DEACTIVATE |
+ INDICATION,
+ NULL);
+ if (bch->tx_skb) {
+ dev_kfree_skb(bch->tx_skb);
+ bch->tx_skb = NULL;
+ }
+ if (bch->rx_skb) {
+ dev_kfree_skb(bch->rx_skb);
+ bch->rx_skb = NULL;
+ }
+ skb_queue_purge(&bch->tx_queue);
+ bch->tx_cnt = 0;
+ bch->rx_ptr = NULL;
+ break;
+ }
+
+ /* timer is only used when at least one b channel */
+ /* is set up to transparent mode */
+ if (l1->hw->mr.timer_usg_cnt) {
+ Write_hfc8(l1->hw, R_IRQMSK_MISC,
+ M_TI_IRQMSK);
+ } else {
+ Write_hfc8(l1->hw, R_IRQMSK_MISC, 0);
+ }
+
+ break;
+
+ default:
+ printk(KERN_INFO
+ "HFC-4S/8S: Unknown B-chan cmd 0x%x received, ignored\n",
+ pr);
+ break;
+ }
+ if (!l1->enabled)
+ bch->b_if.ifc.l1l2(&bch->b_if.ifc,
+ PH_DEACTIVATE | INDICATION, NULL);
+} /* bch_l2l1 */
+
+/**************************/
+/* layer 1 timer function */
+/**************************/
+static void
+hfc_l1_timer(struct hfc4s8s_l1 *l1)
+{
+ u_long flags;
+
+ if (!l1->enabled)
+ return;
+
+ spin_lock_irqsave(&l1->lock, flags);
+ if (l1->nt_mode) {
+ l1->l1_state = 1;
+ Write_hfc8(l1->hw, R_ST_SEL, l1->st_num);
+ Write_hfc8(l1->hw, A_ST_WR_STA, 0x11);
+ spin_unlock_irqrestore(&l1->lock, flags);
+ l1->d_if.ifc.l1l2(&l1->d_if.ifc,
+ PH_DEACTIVATE | INDICATION, NULL);
+ spin_lock_irqsave(&l1->lock, flags);
+ l1->l1_state = 1;
+ Write_hfc8(l1->hw, A_ST_WR_STA, 0x1);
+ spin_unlock_irqrestore(&l1->lock, flags);
+ } else {
+ /* activation timed out */
+ Write_hfc8(l1->hw, R_ST_SEL, l1->st_num);
+ Write_hfc8(l1->hw, A_ST_WR_STA, 0x13);
+ spin_unlock_irqrestore(&l1->lock, flags);
+ l1->d_if.ifc.l1l2(&l1->d_if.ifc,
+ PH_DEACTIVATE | INDICATION, NULL);
+ spin_lock_irqsave(&l1->lock, flags);
+ Write_hfc8(l1->hw, R_ST_SEL, l1->st_num);
+ Write_hfc8(l1->hw, A_ST_WR_STA, 0x3);
+ spin_unlock_irqrestore(&l1->lock, flags);
+ }
+} /* hfc_l1_timer */
+
+/****************************************/
+/* a complete D-frame has been received */
+/****************************************/
+static void
+rx_d_frame(struct hfc4s8s_l1 *l1p, int ech)
+{
+ int z1, z2;
+ u_char f1, f2, df;
+ struct sk_buff *skb;
+ u_char *cp;
+
+
+ if (!l1p->enabled)
+ return;
+ do {
+ /* E/D RX fifo */
+ Write_hfc8(l1p->hw, R_FIFO,
+ (l1p->st_num * 8 + ((ech) ? 7 : 5)));
+ wait_busy(l1p->hw);
+
+ f1 = Read_hfc8_stable(l1p->hw, A_F1);
+ f2 = Read_hfc8(l1p->hw, A_F2);
+ df = f1 - f2;
+ if ((f1 - f2) < 0)
+ df = f1 - f2 + MAX_F_CNT + 1;
+
+
+ if (!df) {
+ return; /* no complete frame in fifo */
+ }
+
+ z1 = Read_hfc16_stable(l1p->hw, A_Z1);
+ z2 = Read_hfc16(l1p->hw, A_Z2);
+
+ z1 = z1 - z2 + 1;
+ if (z1 < 0)
+ z1 += 384;
+
+ if (!(skb = dev_alloc_skb(MAX_D_FRAME_SIZE))) {
+ printk(KERN_INFO
+ "HFC-4S/8S: Could not allocate D/E "
+ "channel receive buffer");
+ Write_hfc8(l1p->hw, A_INC_RES_FIFO, 2);
+ wait_busy(l1p->hw);
+ return;
+ }
+
+ if (((z1 < 4) || (z1 > MAX_D_FRAME_SIZE))) {
+ if (skb)
+ dev_kfree_skb(skb);
+ /* remove errornous D frame */
+ if (df == 1) {
+ /* reset fifo */
+ Write_hfc8(l1p->hw, A_INC_RES_FIFO, 2);
+ wait_busy(l1p->hw);
+ return;
+ } else {
+ /* read errornous D frame */
+
+#ifndef CONFIG_HISAX_HFC4S8S_PCIMEM
+ SetRegAddr(l1p->hw, A_FIFO_DATA0);
+#endif
+
+ while (z1 >= 4) {
+#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
+ Read_hfc32(l1p->hw, A_FIFO_DATA0);
+#else
+ fRead_hfc32(l1p->hw);
+#endif
+ z1 -= 4;
+ }
+
+ while (z1--)
+#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
+ Read_hfc8(l1p->hw, A_FIFO_DATA0);
+#else
+ fRead_hfc8(l1p->hw);
+#endif
+
+ Write_hfc8(l1p->hw, A_INC_RES_FIFO, 1);
+ wait_busy(l1p->hw);
+ return;
+ }
+ }
+
+ cp = skb->data;
+
+#ifndef CONFIG_HISAX_HFC4S8S_PCIMEM
+ SetRegAddr(l1p->hw, A_FIFO_DATA0);
+#endif
+
+ while (z1 >= 4) {
+#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
+ *((unsigned long *) cp) =
+ Read_hfc32(l1p->hw, A_FIFO_DATA0);
+#else
+ *((unsigned long *) cp) = fRead_hfc32(l1p->hw);
+#endif
+ cp += 4;
+ z1 -= 4;
+ }
+
+ while (z1--)
+#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
+ *cp++ = Read_hfc8(l1p->hw, A_FIFO_DATA0);
+#else
+ *cp++ = fRead_hfc8(l1p->hw);
+#endif
+
+ Write_hfc8(l1p->hw, A_INC_RES_FIFO, 1); /* increment f counter */
+ wait_busy(l1p->hw);
+
+ if (*(--cp)) {
+ dev_kfree_skb(skb);
+ } else {
+ skb->len = (cp - skb->data) - 2;
+ if (ech)
+ l1p->d_if.ifc.l1l2(&l1p->d_if.ifc,
+ PH_DATA_E | INDICATION,
+ skb);
+ else
+ l1p->d_if.ifc.l1l2(&l1p->d_if.ifc,
+ PH_DATA | INDICATION,
+ skb);
+ }
+ } while (1);
+} /* rx_d_frame */
+
+/*************************************************************/
+/* a B-frame has been received (perhaps not fully completed) */
+/*************************************************************/
+static void
+rx_b_frame(struct hfc4s8s_btype *bch)
+{
+ int z1, z2, hdlc_complete;
+ u_char f1, f2;
+ struct hfc4s8s_l1 *l1 = bch->l1p;
+ struct sk_buff *skb;
+
+ if (!l1->enabled || (bch->mode == L1_MODE_NULL))
+ return;
+
+ do {
+ /* RX Fifo */
+ Write_hfc8(l1->hw, R_FIFO,
+ (l1->st_num * 8 + ((bch->bchan == 1) ? 1 : 3)));
+ wait_busy(l1->hw);
+
+ if (bch->mode == L1_MODE_HDLC) {
+ f1 = Read_hfc8_stable(l1->hw, A_F1);
+ f2 = Read_hfc8(l1->hw, A_F2);
+ hdlc_complete = ((f1 ^ f2) & MAX_F_CNT);
+ } else
+ hdlc_complete = 0;
+ z1 = Read_hfc16_stable(l1->hw, A_Z1);
+ z2 = Read_hfc16(l1->hw, A_Z2);
+ z1 = (z1 - z2);
+ if (hdlc_complete)
+ z1++;
+ if (z1 < 0)
+ z1 += 384;
+
+ if (!z1)
+ break;
+
+ if (!(skb = bch->rx_skb)) {
+ if (!
+ (skb =
+ dev_alloc_skb((bch->mode ==
+ L1_MODE_TRANS) ? z1
+ : (MAX_B_FRAME_SIZE + 3)))) {
+ printk(KERN_ERR
+ "HFC-4S/8S: Could not allocate B "
+ "channel receive buffer");
+ return;
+ }
+ bch->rx_ptr = skb->data;
+ bch->rx_skb = skb;
+ }
+
+ skb->len = (bch->rx_ptr - skb->data) + z1;
+
+ /* HDLC length check */
+ if ((bch->mode == L1_MODE_HDLC) &&
+ ((hdlc_complete && (skb->len < 4)) ||
+ (skb->len > (MAX_B_FRAME_SIZE + 3)))) {
+
+ skb->len = 0;
+ bch->rx_ptr = skb->data;
+ Write_hfc8(l1->hw, A_INC_RES_FIFO, 2); /* reset fifo */
+ wait_busy(l1->hw);
+ return;
+ }
+#ifndef CONFIG_HISAX_HFC4S8S_PCIMEM
+ SetRegAddr(l1->hw, A_FIFO_DATA0);
+#endif
+
+ while (z1 >= 4) {
+#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
+ *((unsigned long *) bch->rx_ptr) =
+ Read_hfc32(l1->hw, A_FIFO_DATA0);
+#else
+ *((unsigned long *) bch->rx_ptr) =
+ fRead_hfc32(l1->hw);
+#endif
+ bch->rx_ptr += 4;
+ z1 -= 4;
+ }
+
+ while (z1--)
+#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
+ *(bch->rx_ptr++) = Read_hfc8(l1->hw, A_FIFO_DATA0);
+#else
+ *(bch->rx_ptr++) = fRead_hfc8(l1->hw);
+#endif
+
+ if (hdlc_complete) {
+ /* increment f counter */
+ Write_hfc8(l1->hw, A_INC_RES_FIFO, 1);
+ wait_busy(l1->hw);
+
+ /* hdlc crc check */
+ bch->rx_ptr--;
+ if (*bch->rx_ptr) {
+ skb->len = 0;
+ bch->rx_ptr = skb->data;
+ continue;
+ }
+ skb->len -= 3;
+ }
+ if (hdlc_complete || (bch->mode == L1_MODE_TRANS)) {
+ bch->rx_skb = NULL;
+ bch->rx_ptr = NULL;
+ bch->b_if.ifc.l1l2(&bch->b_if.ifc,
+ PH_DATA | INDICATION, skb);
+ }
+
+ } while (1);
+} /* rx_b_frame */
+
+/********************************************/
+/* a D-frame has been/should be transmitted */
+/********************************************/
+static void
+tx_d_frame(struct hfc4s8s_l1 *l1p)
+{
+ struct sk_buff *skb;
+ u_char f1, f2;
+ u_char *cp;
+ int cnt;
+
+ if (l1p->l1_state != 7)
+ return;
+
+ /* TX fifo */
+ Write_hfc8(l1p->hw, R_FIFO, (l1p->st_num * 8 + 4));
+ wait_busy(l1p->hw);
+
+ f1 = Read_hfc8(l1p->hw, A_F1);
+ f2 = Read_hfc8_stable(l1p->hw, A_F2);
+
+ if ((f1 ^ f2) & MAX_F_CNT)
+ return; /* fifo is still filled */
+
+ if (l1p->tx_cnt > 0) {
+ cnt = l1p->tx_cnt;
+ l1p->tx_cnt = 0;
+ l1p->d_if.ifc.l1l2(&l1p->d_if.ifc, PH_DATA | CONFIRM,
+ (void *) cnt);
+ }
+
+ if ((skb = skb_dequeue(&l1p->d_tx_queue))) {
+ cp = skb->data;
+ cnt = skb->len;
+#ifndef CONFIG_HISAX_HFC4S8S_PCIMEM
+ SetRegAddr(l1p->hw, A_FIFO_DATA0);
+#endif
+
+ while (cnt >= 4) {
+#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
+ fWrite_hfc32(l1p->hw, A_FIFO_DATA0,
+ *(unsigned long *) cp);
+#else
+ SetRegAddr(l1p->hw, A_FIFO_DATA0);
+ fWrite_hfc32(l1p->hw, *(unsigned long *) cp);
+#endif
+ cp += 4;
+ cnt -= 4;
+ }
+
+#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
+ while (cnt--)
+ fWrite_hfc8(l1p->hw, A_FIFO_DATA0, *cp++);
+#else
+ while (cnt--)
+ fWrite_hfc8(l1p->hw, *cp++);
+#endif
+
+ l1p->tx_cnt = skb->truesize;
+ Write_hfc8(l1p->hw, A_INC_RES_FIFO, 1); /* increment f counter */
+ wait_busy(l1p->hw);
+
+ dev_kfree_skb(skb);
+ }
+} /* tx_d_frame */
+
+/******************************************************/
+/* a B-frame may be transmitted (or is not completed) */
+/******************************************************/
+static void
+tx_b_frame(struct hfc4s8s_btype *bch)
+{
+ struct sk_buff *skb;
+ struct hfc4s8s_l1 *l1 = bch->l1p;
+ u_char *cp;
+ int cnt, max, hdlc_num, ack_len = 0;
+
+ if (!l1->enabled || (bch->mode == L1_MODE_NULL))
+ return;
+
+ /* TX fifo */
+ Write_hfc8(l1->hw, R_FIFO,
+ (l1->st_num * 8 + ((bch->bchan == 1) ? 0 : 2)));
+ wait_busy(l1->hw);
+ do {
+
+ if (bch->mode == L1_MODE_HDLC) {
+ hdlc_num = Read_hfc8(l1->hw, A_F1) & MAX_F_CNT;
+ hdlc_num -=
+ (Read_hfc8_stable(l1->hw, A_F2) & MAX_F_CNT);
+ if (hdlc_num < 0)
+ hdlc_num += 16;
+ if (hdlc_num >= 15)
+ break; /* fifo still filled up with hdlc frames */
+ } else
+ hdlc_num = 0;
+
+ if (!(skb = bch->tx_skb)) {
+ if (!(skb = skb_dequeue(&bch->tx_queue))) {
+ l1->hw->mr.fifo_slow_timer_service[l1->
+ st_num]
+ &= ~((bch->bchan == 1) ? 1 : 4);
+ break; /* list empty */
+ }
+ bch->tx_skb = skb;
+ bch->tx_cnt = 0;
+ }
+
+ if (!hdlc_num)
+ l1->hw->mr.fifo_slow_timer_service[l1->st_num] |=
+ ((bch->bchan == 1) ? 1 : 4);
+ else
+ l1->hw->mr.fifo_slow_timer_service[l1->st_num] &=
+ ~((bch->bchan == 1) ? 1 : 4);
+
+ max = Read_hfc16_stable(l1->hw, A_Z2);
+ max -= Read_hfc16(l1->hw, A_Z1);
+ if (max <= 0)
+ max += 384;
+ max--;
+
+ if (max < 16)
+ break; /* don't write to small amounts of bytes */
+
+ cnt = skb->len - bch->tx_cnt;
+ if (cnt > max)
+ cnt = max;
+ cp = skb->data + bch->tx_cnt;
+ bch->tx_cnt += cnt;
+
+#ifndef CONFIG_HISAX_HFC4S8S_PCIMEM
+ SetRegAddr(l1->hw, A_FIFO_DATA0);
+#endif
+ while (cnt >= 4) {
+#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
+ fWrite_hfc32(l1->hw, A_FIFO_DATA0,
+ *(unsigned long *) cp);
+#else
+ fWrite_hfc32(l1->hw, *(unsigned long *) cp);
+#endif
+ cp += 4;
+ cnt -= 4;
+ }
+
+ while (cnt--)
+#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
+ fWrite_hfc8(l1->hw, A_FIFO_DATA0, *cp++);
+#else
+ fWrite_hfc8(l1->hw, *cp++);
+#endif
+
+ if (bch->tx_cnt >= skb->len) {
+ if (bch->mode == L1_MODE_HDLC) {
+ /* increment f counter */
+ Write_hfc8(l1->hw, A_INC_RES_FIFO, 1);
+ }
+ ack_len += skb->truesize;
+ bch->tx_skb = 0;
+ bch->tx_cnt = 0;
+ dev_kfree_skb(skb);
+ } else
+ /* Re-Select */
+ Write_hfc8(l1->hw, R_FIFO,
+ (l1->st_num * 8 +
+ ((bch->bchan == 1) ? 0 : 2)));
+ wait_busy(l1->hw);
+ } while (1);
+
+ if (ack_len)
+ bch->b_if.ifc.l1l2((struct hisax_if *) &bch->b_if,
+ PH_DATA | CONFIRM, (void *) ack_len);
+} /* tx_b_frame */
+
+/*************************************/
+/* bottom half handler for interrupt */
+/*************************************/
+static void
+hfc4s8s_bh(hfc4s8s_hw * hw)
+{
+ u_char b;
+ struct hfc4s8s_l1 *l1p;
+ volatile u_char *fifo_stat;
+ int idx;
+
+ /* handle layer 1 state changes */
+ b = 1;
+ l1p = hw->l1;
+ while (b) {
+ if ((b & hw->mr.r_irq_statech)) {
+ /* reset l1 event */
+ hw->mr.r_irq_statech &= ~b;
+ if (l1p->enabled) {
+ if (l1p->nt_mode) {
+ u_char oldstate = l1p->l1_state;
+
+ Write_hfc8(l1p->hw, R_ST_SEL,
+ l1p->st_num);
+ l1p->l1_state =
+ Read_hfc8(l1p->hw,
+ A_ST_RD_STA) & 0xf;
+
+ if ((oldstate == 3)
+ && (l1p->l1_state != 3))
+ l1p->d_if.ifc.l1l2(&l1p->
+ d_if.
+ ifc,
+ PH_DEACTIVATE
+ |
+ INDICATION,
+ NULL);
+
+ if (l1p->l1_state != 2) {
+ del_timer(&l1p->l1_timer);
+ if (l1p->l1_state == 3) {
+ l1p->d_if.ifc.
+ l1l2(&l1p->
+ d_if.ifc,
+ PH_ACTIVATE
+ |
+ INDICATION,
+ NULL);
+ }
+ } else {
+ /* allow transition */
+ Write_hfc8(hw, A_ST_WR_STA,
+ M_SET_G2_G3);
+ mod_timer(&l1p->l1_timer,
+ jiffies +
+ L1_TIMER_T1);
+ }
+ printk(KERN_INFO
+ "HFC-4S/8S: NT ch %d l1 state %d -> %d\n",
+ l1p->st_num, oldstate,
+ l1p->l1_state);
+ } else {
+ u_char oldstate = l1p->l1_state;
+
+ Write_hfc8(l1p->hw, R_ST_SEL,
+ l1p->st_num);
+ l1p->l1_state =
+ Read_hfc8(l1p->hw,
+ A_ST_RD_STA) & 0xf;
+
+ if (((l1p->l1_state == 3) &&
+ ((oldstate == 7) ||
+ (oldstate == 8))) ||
+ ((timer_pending
+ (&l1p->l1_timer))
+ && (l1p->l1_state == 8))) {
+ mod_timer(&l1p->l1_timer,
+ L1_TIMER_T4 +
+ jiffies);
+ } else {
+ if (l1p->l1_state == 7) {
+ del_timer(&l1p->
+ l1_timer);
+ l1p->d_if.ifc.
+ l1l2(&l1p->
+ d_if.ifc,
+ PH_ACTIVATE
+ |
+ INDICATION,
+ NULL);
+ tx_d_frame(l1p);
+ }
+ if (l1p->l1_state == 3) {
+ if (oldstate != 3)
+ l1p->d_if.
+ ifc.
+ l1l2
+ (&l1p->
+ d_if.
+ ifc,
+ PH_DEACTIVATE
+ |
+ INDICATION,
+ NULL);
+ }
+ }
+ printk(KERN_INFO
+ "HFC-4S/8S: TE %d ch %d l1 state %d -> %d\n",
+ l1p->hw->cardnum,
+ l1p->st_num, oldstate,
+ l1p->l1_state);
+ }
+ }
+ }
+ b <<= 1;
+ l1p++;
+ }
+
+ /* now handle the fifos */
+ idx = 0;
+ fifo_stat = hw->mr.r_irq_fifo_blx;
+ l1p = hw->l1;
+ while (idx < hw->driver_data.max_st_ports) {
+
+ if (hw->mr.timer_irq) {
+ *fifo_stat |= hw->mr.fifo_rx_trans_enables[idx];
+ if (hw->fifo_sched_cnt <= 0) {
+ *fifo_stat |=
+ hw->mr.fifo_slow_timer_service[l1p->
+ st_num];
+ }
+ }
+ /* ignore fifo 6 (TX E fifo) */
+ *fifo_stat &= 0xff - 0x40;
+
+ while (*fifo_stat) {
+
+ if (!l1p->nt_mode) {
+ /* RX Fifo has data to read */
+ if ((*fifo_stat & 0x20)) {
+ *fifo_stat &= ~0x20;
+ rx_d_frame(l1p, 0);
+ }
+ /* E Fifo has data to read */
+ if ((*fifo_stat & 0x80)) {
+ *fifo_stat &= ~0x80;
+ rx_d_frame(l1p, 1);
+ }
+ /* TX Fifo completed send */
+ if ((*fifo_stat & 0x10)) {
+ *fifo_stat &= ~0x10;
+ tx_d_frame(l1p);
+ }
+ }
+ /* B1 RX Fifo has data to read */
+ if ((*fifo_stat & 0x2)) {
+ *fifo_stat &= ~0x2;
+ rx_b_frame(l1p->b_ch);
+ }
+ /* B1 TX Fifo has send completed */
+ if ((*fifo_stat & 0x1)) {
+ *fifo_stat &= ~0x1;
+ tx_b_frame(l1p->b_ch);
+ }
+ /* B2 RX Fifo has data to read */
+ if ((*fifo_stat & 0x8)) {
+ *fifo_stat &= ~0x8;
+ rx_b_frame(l1p->b_ch + 1);
+ }
+ /* B2 TX Fifo has send completed */
+ if ((*fifo_stat & 0x4)) {
+ *fifo_stat &= ~0x4;
+ tx_b_frame(l1p->b_ch + 1);
+ }
+ }
+ fifo_stat++;
+ l1p++;
+ idx++;
+ }
+
+ if (hw->fifo_sched_cnt <= 0)
+ hw->fifo_sched_cnt += (1 << (7 - TRANS_TIMER_MODE));
+ hw->mr.timer_irq = 0; /* clear requested timer irq */
+} /* hfc4s8s_bh */
+
+/*********************/
+/* interrupt handler */
+/*********************/
+static irqreturn_t
+hfc4s8s_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+{
+ hfc4s8s_hw *hw = dev_id;
+ u_char b, ovr;
+ volatile u_char *ovp;
+ int idx;
+ u_char old_ioreg;
+
+ if (!hw || !(hw->mr.r_irq_ctrl & M_GLOB_IRQ_EN))
+ return IRQ_NONE;
+
+#ifndef CONFIG_HISAX_HFC4S8S_PCIMEM
+ /* read current selected regsister */
+ old_ioreg = GetRegAddr(hw);
+#endif
+
+ /* Layer 1 State change */
+ hw->mr.r_irq_statech |=
+ (Read_hfc8(hw, R_SCI) & hw->mr.r_irqmsk_statchg);
+ if (!
+ (b = (Read_hfc8(hw, R_STATUS) & (M_MISC_IRQSTA | M_FR_IRQSTA)))
+&& !hw->mr.r_irq_statech) {
+#ifndef CONFIG_HISAX_HFC4S8S_PCIMEM
+ SetRegAddr(hw, old_ioreg);
+#endif
+ return IRQ_NONE;
+ }
+
+ /* timer event */
+ if (Read_hfc8(hw, R_IRQ_MISC) & M_TI_IRQ) {
+ hw->mr.timer_irq = 1;
+ hw->fifo_sched_cnt--;
+ }
+
+ /* FIFO event */
+ if ((ovr = Read_hfc8(hw, R_IRQ_OVIEW))) {
+ hw->mr.r_irq_oview |= ovr;
+ idx = R_IRQ_FIFO_BL0;
+ ovp = hw->mr.r_irq_fifo_blx;
+ while (ovr) {
+ if ((ovr & 1)) {
+ *ovp |= Read_hfc8(hw, idx);
+ }
+ ovp++;
+ idx++;
+ ovr >>= 1;
+ }
+ }
+
+ /* queue the request to allow other cards to interrupt */
+ schedule_work(&hw->tqueue);
+
+#ifndef CONFIG_HISAX_HFC4S8S_PCIMEM
+ SetRegAddr(hw, old_ioreg);
+#endif
+ return IRQ_HANDLED;
+} /* hfc4s8s_interrupt */
+
+/***********************************************************************/
+/* reset the complete chip, don't release the chips irq but disable it */
+/***********************************************************************/
+static void
+chipreset(hfc4s8s_hw * hw)
+{
+ u_long flags;
+
+ spin_lock_irqsave(&hw->lock, flags);
+ Write_hfc8(hw, R_CTRL, 0); /* use internal RAM */
+ Write_hfc8(hw, R_RAM_MISC, 0); /* 32k*8 RAM */
+ Write_hfc8(hw, R_FIFO_MD, 0); /* fifo mode 386 byte/fifo simple mode */
+ Write_hfc8(hw, R_CIRM, M_SRES); /* reset chip */
+ hw->mr.r_irq_ctrl = 0; /* interrupt is inactive */
+ spin_unlock_irqrestore(&hw->lock, flags);
+
+ udelay(3);
+ Write_hfc8(hw, R_CIRM, 0); /* disable reset */
+ wait_busy(hw);
+
+ Write_hfc8(hw, R_PCM_MD0, M_PCM_MD); /* master mode */
+ Write_hfc8(hw, R_RAM_MISC, M_FZ_MD); /* transmit fifo option */
+ if (hw->driver_data.clock_mode == 1)
+ Write_hfc8(hw, R_BRG_PCM_CFG, M_PCM_CLK); /* PCM clk / 2 */
+ Write_hfc8(hw, R_TI_WD, TRANS_TIMER_MODE); /* timer interval */
+
+ memset(&hw->mr, 0, sizeof(hw->mr));
+} /* chipreset */
+
+/********************************************/
+/* disable/enable hardware in nt or te mode */
+/********************************************/
+void
+hfc_hardware_enable(hfc4s8s_hw * hw, int enable, int nt_mode)
+{
+ u_long flags;
+ char if_name[40];
+ int i;
+
+ if (enable) {
+ /* save system vars */
+ hw->nt_mode = nt_mode;
+
+ /* enable fifo and state irqs, but not global irq enable */
+ hw->mr.r_irq_ctrl = M_FIFO_IRQ;
+ Write_hfc8(hw, R_IRQ_CTRL, hw->mr.r_irq_ctrl);
+ hw->mr.r_irqmsk_statchg = 0;
+ Write_hfc8(hw, R_SCI_MSK, hw->mr.r_irqmsk_statchg);
+ Write_hfc8(hw, R_PWM_MD, 0x80);
+ Write_hfc8(hw, R_PWM1, 26);
+ if (!nt_mode)
+ Write_hfc8(hw, R_ST_SYNC, M_AUTO_SYNC);
+
+ /* enable the line interfaces and fifos */
+ for (i = 0; i < hw->driver_data.max_st_ports; i++) {
+ hw->mr.r_irqmsk_statchg |= (1 << i);
+ Write_hfc8(hw, R_SCI_MSK, hw->mr.r_irqmsk_statchg);
+ Write_hfc8(hw, R_ST_SEL, i);
+ Write_hfc8(hw, A_ST_CLK_DLY,
+ ((nt_mode) ? CLKDEL_NT : CLKDEL_TE));
+ hw->mr.r_ctrl0 = ((nt_mode) ? CTRL0_NT : CTRL0_TE);
+ Write_hfc8(hw, A_ST_CTRL0, hw->mr.r_ctrl0);
+ Write_hfc8(hw, A_ST_CTRL2, 3);
+ Write_hfc8(hw, A_ST_WR_STA, 0); /* enable state machine */
+
+ hw->l1[i].enabled = 1;
+ hw->l1[i].nt_mode = nt_mode;
+
+ if (!nt_mode) {
+ /* setup E-fifo */
+ Write_hfc8(hw, R_FIFO, i * 8 + 7); /* E fifo */
+ wait_busy(hw);
+ Write_hfc8(hw, A_CON_HDLC, 0x11); /* HDLC mode, 1 fill, connect ST */
+ Write_hfc8(hw, A_SUBCH_CFG, 2); /* only 2 bits */
+ Write_hfc8(hw, A_IRQ_MSK, 1); /* enable interrupt */
+ Write_hfc8(hw, A_INC_RES_FIFO, 2); /* reset fifo */
+ wait_busy(hw);
+
+ /* setup D RX-fifo */
+ Write_hfc8(hw, R_FIFO, i * 8 + 5); /* RX fifo */
+ wait_busy(hw);
+ Write_hfc8(hw, A_CON_HDLC, 0x11); /* HDLC mode, 1 fill, connect ST */
+ Write_hfc8(hw, A_SUBCH_CFG, 2); /* only 2 bits */
+ Write_hfc8(hw, A_IRQ_MSK, 1); /* enable interrupt */
+ Write_hfc8(hw, A_INC_RES_FIFO, 2); /* reset fifo */
+ wait_busy(hw);
+
+ /* setup D TX-fifo */
+ Write_hfc8(hw, R_FIFO, i * 8 + 4); /* TX fifo */
+ wait_busy(hw);
+ Write_hfc8(hw, A_CON_HDLC, 0x11); /* HDLC mode, 1 fill, connect ST */
+ Write_hfc8(hw, A_SUBCH_CFG, 2); /* only 2 bits */
+ Write_hfc8(hw, A_IRQ_MSK, 1); /* enable interrupt */
+ Write_hfc8(hw, A_INC_RES_FIFO, 2); /* reset fifo */
+ wait_busy(hw);
+ }
+
+ sprintf(if_name, "hfc4s8s_%d%d_", hw->cardnum, i);
+
+ if (hisax_register
+ (&hw->l1[i].d_if, hw->l1[i].b_table, if_name,
+ ((nt_mode) ? 3 : 2))) {
+
+ hw->l1[i].enabled = 0;
+ hw->mr.r_irqmsk_statchg &= ~(1 << i);
+ Write_hfc8(hw, R_SCI_MSK,
+ hw->mr.r_irqmsk_statchg);
+ printk(KERN_INFO
+ "HFC-4S/8S: Unable to register S/T device %s, break\n",
+ if_name);
+ break;
+ }
+ }
+ spin_lock_irqsave(&hw->lock, flags);
+ hw->mr.r_irq_ctrl |= M_GLOB_IRQ_EN;
+ Write_hfc8(hw, R_IRQ_CTRL, hw->mr.r_irq_ctrl);
+ spin_unlock_irqrestore(&hw->lock, flags);
+ } else {
+ /* disable hardware */
+ spin_lock_irqsave(&hw->lock, flags);
+ hw->mr.r_irq_ctrl &= ~M_GLOB_IRQ_EN;
+ Write_hfc8(hw, R_IRQ_CTRL, hw->mr.r_irq_ctrl);
+ spin_unlock_irqrestore(&hw->lock, flags);
+
+ for (i = hw->driver_data.max_st_ports - 1; i >= 0; i--) {
+ hw->l1[i].enabled = 0;
+ hisax_unregister(&hw->l1[i].d_if);
+ del_timer(&hw->l1[i].l1_timer);
+ skb_queue_purge(&hw->l1[i].d_tx_queue);
+ skb_queue_purge(&hw->l1[i].b_ch[0].tx_queue);
+ skb_queue_purge(&hw->l1[i].b_ch[1].tx_queue);
+ }
+ chipreset(hw);
+ }
+} /* hfc_hardware_enable */
+
+/******************************************/
+/* disable memory mapped ports / io ports */
+/******************************************/
+void
+release_pci_ports(hfc4s8s_hw * hw)
+{
+ pci_write_config_word(hw->pdev, PCI_COMMAND, 0);
+#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
+ if (hw->membase)
+ iounmap((void *) hw->membase);
+#else
+ if (hw->iobase)
+ release_region(hw->iobase, 8);
+#endif
+}
+
+/*****************************************/
+/* enable memory mapped ports / io ports */
+/*****************************************/
+void
+enable_pci_ports(hfc4s8s_hw * hw)
+{
+#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
+ pci_write_config_word(hw->pdev, PCI_COMMAND, PCI_ENA_MEMIO);
+#else
+ pci_write_config_word(hw->pdev, PCI_COMMAND, PCI_ENA_REGIO);
+#endif
+}
+
+/*************************************/
+/* initialise the HFC-4s/8s hardware */
+/* return 0 on success. */
+/*************************************/
+static int __devinit
+setup_instance(hfc4s8s_hw * hw)
+{
+ int err = -EIO;
+ int i;
+
+ for (i = 0; i < HFC_MAX_ST; i++) {
+ struct hfc4s8s_l1 *l1p;
+
+ l1p = hw->l1 + i;
+ spin_lock_init(&l1p->lock);
+ l1p->hw = hw;
+ l1p->l1_timer.function = (void *) hfc_l1_timer;
+ l1p->l1_timer.data = (long) (l1p);
+ init_timer(&l1p->l1_timer);
+ l1p->st_num = i;
+ skb_queue_head_init(&l1p->d_tx_queue);
+ l1p->d_if.ifc.priv = hw->l1 + i;
+ l1p->d_if.ifc.l2l1 = (void *) dch_l2l1;
+
+ spin_lock_init(&l1p->b_ch[0].lock);
+ l1p->b_ch[0].b_if.ifc.l2l1 = (void *) bch_l2l1;
+ l1p->b_ch[0].b_if.ifc.priv = (void *) &l1p->b_ch[0];
+ l1p->b_ch[0].l1p = hw->l1 + i;
+ l1p->b_ch[0].bchan = 1;
+ l1p->b_table[0] = &l1p->b_ch[0].b_if;
+ skb_queue_head_init(&l1p->b_ch[0].tx_queue);
+
+ spin_lock_init(&l1p->b_ch[1].lock);
+ l1p->b_ch[1].b_if.ifc.l2l1 = (void *) bch_l2l1;
+ l1p->b_ch[1].b_if.ifc.priv = (void *) &l1p->b_ch[1];
+ l1p->b_ch[1].l1p = hw->l1 + i;
+ l1p->b_ch[1].bchan = 2;
+ l1p->b_table[1] = &l1p->b_ch[1].b_if;
+ skb_queue_head_init(&l1p->b_ch[1].tx_queue);
+ }
+
+ enable_pci_ports(hw);
+ chipreset(hw);
+
+ i = Read_hfc8(hw, R_CHIP_ID) >> CHIP_ID_SHIFT;
+ if (i != hw->driver_data.chip_id) {
+ printk(KERN_INFO
+ "HFC-4S/8S: invalid chip id 0x%x instead of 0x%x, card ignored\n",
+ i, hw->driver_data.chip_id);
+ goto out;
+ }
+
+ i = Read_hfc8(hw, R_CHIP_RV) & 0xf;
+ if (!i) {
+ printk(KERN_INFO
+ "HFC-4S/8S: chip revision 0 not supported, card ignored\n");
+ goto out;
+ }
+
+ INIT_WORK(&hw->tqueue, (void *) (void *) hfc4s8s_bh, hw);
+
+ if (request_irq
+ (hw->irq, hfc4s8s_interrupt, SA_SHIRQ, hw->card_name, hw)) {
+ printk(KERN_INFO
+ "HFC-4S/8S: unable to alloc irq %d, card ignored\n",
+ hw->irq);
+ goto out;
+ }
+#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
+ printk(KERN_INFO
+ "HFC-4S/8S: found PCI card at membase 0x%p, irq %d\n",
+ hw->hw_membase, hw->irq);
+#else
+ printk(KERN_INFO
+ "HFC-4S/8S: found PCI card at iobase 0x%x, irq %d\n",
+ hw->iobase, hw->irq);
+#endif
+
+ hfc_hardware_enable(hw, 1, 0);
+
+ return (0);
+
+ out:
+ hw->irq = 0;
+ release_pci_ports(hw);
+ kfree(hw);
+ return (err);
+}
+
+/*****************************************/
+/* PCI hotplug interface: probe new card */
+/*****************************************/
+static int __devinit
+hfc4s8s_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+ int err = -ENOMEM;
+ hfc4s8s_param *driver_data = (hfc4s8s_param *) ent->driver_data;
+ hfc4s8s_hw *hw;
+
+ if (!(hw = kmalloc(sizeof(hfc4s8s_hw), GFP_ATOMIC))) {
+ printk(KERN_ERR "No kmem for HFC-4S/8S card\n");
+ return (err);
+ }
+ memset(hw, 0, sizeof(hfc4s8s_hw));
+
+ hw->pdev = pdev;
+ err = pci_enable_device(pdev);
+
+ if (err)
+ goto out;
+
+ hw->cardnum = card_cnt;
+ sprintf(hw->card_name, "hfc4s8s_%d", hw->cardnum);
+ printk(KERN_INFO "HFC-4S/8S: found adapter %s (%s) at %s\n",
+ driver_data->device_name, hw->card_name, pci_name(pdev));
+
+ spin_lock_init(&hw->lock);
+
+ hw->driver_data = *driver_data;
+ hw->irq = pdev->irq;
+ hw->iobase = pci_resource_start(pdev, 0);
+
+#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
+ hw->hw_membase = (u_char *) pci_resource_start(pdev, 1);
+ hw->membase = ioremap((ulong) hw->hw_membase, 256);
+#else
+ if (!request_region(hw->iobase, 8, hw->card_name)) {
+ printk(KERN_INFO
+ "HFC-4S/8S: failed to rquest address space at 0x%04x\n",
+ hw->iobase);
+ goto out;
+ }
+#endif
+
+ pci_set_drvdata(pdev, hw);
+ err = setup_instance(hw);
+ if (!err)
+ card_cnt++;
+ return (err);
+
+ out:
+ kfree(hw);
+ return (err);
+}
+
+/**************************************/
+/* PCI hotplug interface: remove card */
+/**************************************/
+static void __devexit
+hfc4s8s_remove(struct pci_dev *pdev)
+{
+ hfc4s8s_hw *hw = pci_get_drvdata(pdev);
+
+ printk(KERN_INFO "HFC-4S/8S: removing card %d\n", hw->cardnum);
+ hfc_hardware_enable(hw, 0, 0);
+
+ if (hw->irq)
+ free_irq(hw->irq, hw);
+ hw->irq = 0;
+ release_pci_ports(hw);
+
+ card_cnt--;
+ pci_disable_device(pdev);
+ kfree(hw);
+ return;
+}
+
+static struct pci_driver hfc4s8s_driver = {
+ name:"hfc4s8s_l1",
+ probe:hfc4s8s_probe,
+ remove:__devexit_p(hfc4s8s_remove),
+ id_table:hfc4s8s_ids,
+};
+
+/**********************/
+/* driver Module init */
+/**********************/
+static int __init
+hfc4s8s_module_init(void)
+{
+ int err;
+
+ printk(KERN_INFO
+ "HFC-4S/8S: Layer 1 driver module for HFC-4S/8S isdn chips, %s\n",
+ hfc4s8s_rev);
+ printk(KERN_INFO
+ "HFC-4S/8S: (C) 2003 Cornelius Consult, www.cornelius-consult.de\n");
+
+ card_cnt = 0;
+
+ err = pci_register_driver(&hfc4s8s_driver);
+ if (err < 0) {
+ goto out;
+ }
+ printk(KERN_INFO "HFC-4S/8S: found %d cards\n", card_cnt);
+
+#if !defined(CONFIG_HOTPLUG)
+ if (err == 0) {
+ err = -ENODEV;
+ pci_unregister_driver(&hfc4s8s_driver);
+ goto out;
+ }
+#endif
+
+ return 0;
+ out:
+ return (err);
+} /* hfc4s8s_init_hw */
+
+/*************************************/
+/* driver module exit : */
+/* release the HFC-4s/8s hardware */
+/*************************************/
+static void
+hfc4s8s_module_exit(void)
+{
+ pci_unregister_driver(&hfc4s8s_driver);
+ printk(KERN_INFO "HFC-4S/8S: module removed\n");
+} /* hfc4s8s_release_hw */
+
+module_init(hfc4s8s_module_init);
+module_exit(hfc4s8s_module_exit);
diff --git a/drivers/isdn/hisax/hfc4s8s_l1.h b/drivers/isdn/hisax/hfc4s8s_l1.h
new file mode 100644
index 0000000000000..e8f9c077fa85f
--- /dev/null
+++ b/drivers/isdn/hisax/hfc4s8s_l1.h
@@ -0,0 +1,88 @@
+/***************************************************************/
+/* $Id: hfc4s8s_l1.h,v 1.1 2005/02/02 17:28:55 martinb1 Exp $ */
+/* */
+/* This file is a minimal required extraction of hfc48scu.h */
+/* (Genero 3.2, HFC XML 1.7a for HFC-E1, HFC-4S and HFC-8S) */
+/* */
+/* To get this complete register description contact */
+/* Cologne Chip AG : */
+/* Internet: http://www.colognechip.com/ */
+/* E-Mail: info@colognechip.com */
+/***************************************************************/
+
+#ifndef _HFC4S8S_L1_H_
+#define _HFC4S8S_L1_H_
+
+
+/*
+* include Genero generated HFC-4S/8S header file hfc48scu.h
+* for comlete register description. This will define _HFC48SCU_H_
+* to prevent redefinitions
+*/
+
+// #include "hfc48scu.h"
+
+#ifndef _HFC48SCU_H_
+#define _HFC48SCU_H_
+
+#ifndef PCI_VENDOR_ID_CCD
+#define PCI_VENDOR_ID_CCD 0x1397
+#endif
+
+#define CHIP_ID_4S 0x0C
+#define CHIP_ID_8S 0x08
+#define PCI_DEVICE_ID_4S 0x08B4
+#define PCI_DEVICE_ID_8S 0x16B8
+
+#define R_IRQ_MISC 0x11
+#define M_TI_IRQ 0x02
+#define A_ST_RD_STA 0x30
+#define A_ST_WR_STA 0x30
+#define M_SET_G2_G3 0x80
+#define A_ST_CTRL0 0x31
+#define A_ST_CTRL2 0x33
+#define A_ST_CLK_DLY 0x37
+#define A_Z1 0x04
+#define A_Z2 0x06
+#define R_CIRM 0x00
+#define M_SRES 0x08
+#define R_CTRL 0x01
+#define R_BRG_PCM_CFG 0x02
+#define M_PCM_CLK 0x20
+#define R_RAM_MISC 0x0C
+#define M_FZ_MD 0x80
+#define R_FIFO_MD 0x0D
+#define A_INC_RES_FIFO 0x0E
+#define R_FIFO 0x0F
+#define A_F1 0x0C
+#define A_F2 0x0D
+#define R_IRQ_OVIEW 0x10
+#define R_CHIP_ID 0x16
+#define R_STATUS 0x1C
+#define M_BUSY 0x01
+#define M_MISC_IRQSTA 0x40
+#define M_FR_IRQSTA 0x80
+#define R_CHIP_RV 0x1F
+#define R_IRQ_CTRL 0x13
+#define M_FIFO_IRQ 0x01
+#define M_GLOB_IRQ_EN 0x08
+#define R_PCM_MD0 0x14
+#define M_PCM_MD 0x01
+#define A_FIFO_DATA0 0x80
+#define R_TI_WD 0x1A
+#define R_PWM1 0x39
+#define R_PWM_MD 0x46
+#define R_IRQ_FIFO_BL0 0xC8
+#define A_CON_HDLC 0xFA
+#define A_SUBCH_CFG 0xFB
+#define A_IRQ_MSK 0xFF
+#define R_SCI_MSK 0x12
+#define R_ST_SEL 0x16
+#define R_ST_SYNC 0x17
+#define M_AUTO_SYNC 0x08
+#define R_SCI 0x12
+#define R_IRQMSK_MISC 0x11
+#define M_TI_IRQMSK 0x02
+
+#endif /* _HFC4S8S_L1_H_ */
+#endif /* _HFC48SCU_H_ */
diff --git a/drivers/isdn/hisax/hfc_sx.c b/drivers/isdn/hisax/hfc_sx.c
index 685fcc2d72567..a307fcb6c6349 100644
--- a/drivers/isdn/hisax/hfc_sx.c
+++ b/drivers/isdn/hisax/hfc_sx.c
@@ -1382,14 +1382,14 @@ hfcsx_card_msg(struct IsdnCardState *cs, int mt, void *arg)
}
#ifdef __ISAPNP__
-static struct isapnp_device_id hfc_ids[] __initdata = {
+static struct isapnp_device_id hfc_ids[] __devinitdata = {
{ ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2620),
ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2620),
(unsigned long) "Teles 16.3c2" },
{ 0, }
};
-static struct isapnp_device_id *ipid __initdata = &hfc_ids[0];
+static struct isapnp_device_id *ipid __devinitdata = &hfc_ids[0];
static struct pnp_card *pnp_c __devinitdata = NULL;
#endif
diff --git a/drivers/isdn/hisax/hfc_usb.c b/drivers/isdn/hisax/hfc_usb.c
index fcc67afd53c59..ffd74b84f502e 100644
--- a/drivers/isdn/hisax/hfc_usb.c
+++ b/drivers/isdn/hisax/hfc_usb.c
@@ -1,11 +1,15 @@
/*
* hfc_usb.c
*
- * modular HiSax ISDN driver for Colognechip HFC-USB chip
+ * $Id: hfc_usb.c,v 4.34 2005/01/26 17:25:53 martinb1 Exp $
*
- * Authors : Peter Sprenger (sprenger@moving-byters.de)
+ * modular HiSax ISDN driver for Colognechip HFC-S USB chip
+ *
+ * Authors : Peter Sprenger (sprenger@moving-bytes.de)
* Martin Bachem (info@colognechip.com)
- * based on the first hfc_usb driver of Werner Cornelius (werner@isdn-development.de)
+ *
+ * based on the first hfc_usb driver of
+ * Werner Cornelius (werner@isdn-development.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
@@ -21,249 +25,229 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
+ * See Version Histroy at the bottom of this file
+ *
*/
-
#include <linux/types.h>
#include <linux/stddef.h>
#include <linux/timer.h>
#include <linux/config.h>
#include <linux/init.h>
-#include "hisax.h"
#include <linux/module.h>
#include <linux/kernel_stat.h>
#include <linux/usb.h>
#include <linux/kernel.h>
#include <linux/smp_lock.h>
#include <linux/sched.h>
+#include "hisax.h"
#include "hisax_if.h"
-
-static const char *hfcusb_revision = "4.0";
+#include "hfc_usb.h"
/*
- to enable much mire debug messages in this driver, define
- VERBOSE_USB_DEBUG and VERBOSE_ISDN_DEBUG
- below
+* Version Information
+* (do not modify the CVS Makros $Revision: 4.34 $ and $Date: 2005/01/26 17:25:53 $ !)
*/
+static const char *hfcusb_revision =
+ "Revision: 4.34 $ Date: 2005/01/26 17:25:53 $ ";
-#define VERBOSE_USB_DEBUG
-#define VERBOSE_ISDN_DEBUG
-
-#define INCLUDE_INLINE_FUNCS
-
-#define TRUE 1
-#define FALSE 0
-
-
-/***********/
-/* defines */
-/***********/
-#define HFC_CTRL_TIMEOUT 20 //(HZ * USB_CTRL_GET_TIMEOUT)
-/* 5ms timeout writing/reading regs */
-#define HFC_TIMER_T3 8000 /* timeout for l1 activation timer */
-#define HFC_TIMER_T4 500 /* time for state change interval */
-
-#define HFCUSB_L1_STATECHANGE 0 /* L1 state changed */
-#define HFCUSB_L1_DRX 1 /* D-frame received */
-#define HFCUSB_L1_ERX 2 /* E-frame received */
-#define HFCUSB_L1_DTX 4 /* D-frames completed */
-
-#define MAX_BCH_SIZE 2048 /* allowed B-channel packet size */
-
-#define HFCUSB_RX_THRESHOLD 64 /* threshold for fifo report bit rx */
-#define HFCUSB_TX_THRESHOLD 64 /* threshold for fifo report bit tx */
-
-#define HFCUSB_CHIP_ID 0x16 /* Chip ID register index */
-#define HFCUSB_CIRM 0x00 /* cirm register index */
-#define HFCUSB_USB_SIZE 0x07 /* int length register */
-#define HFCUSB_USB_SIZE_I 0x06 /* iso length register */
-#define HFCUSB_F_CROSS 0x0b /* bit order register */
-#define HFCUSB_CLKDEL 0x37 /* bit delay register */
-#define HFCUSB_CON_HDLC 0xfa /* channel connect register */
-#define HFCUSB_HDLC_PAR 0xfb
-#define HFCUSB_SCTRL 0x31 /* S-bus control register (tx) */
-#define HFCUSB_SCTRL_E 0x32 /* same for E and special funcs */
-#define HFCUSB_SCTRL_R 0x33 /* S-bus control register (rx) */
-#define HFCUSB_F_THRES 0x0c /* threshold register */
-#define HFCUSB_FIFO 0x0f /* fifo select register */
-#define HFCUSB_F_USAGE 0x1a /* fifo usage register */
-#define HFCUSB_MST_MODE0 0x14
-#define HFCUSB_MST_MODE1 0x15
-#define HFCUSB_P_DATA 0x1f
-#define HFCUSB_INC_RES_F 0x0e
-#define HFCUSB_STATES 0x30
-
-#define HFCUSB_CHIPID 0x40 /* ID value of HFC-USB */
-
-/******************/
-/* fifo registers */
-/******************/
-#define HFCUSB_NUM_FIFOS 8 /* maximum number of fifos */
-#define HFCUSB_B1_TX 0 /* index for B1 transmit bulk/int */
-#define HFCUSB_B1_RX 1 /* index for B1 receive bulk/int */
-#define HFCUSB_B2_TX 2
-#define HFCUSB_B2_RX 3
-#define HFCUSB_D_TX 4
-#define HFCUSB_D_RX 5
-#define HFCUSB_PCM_TX 6
-#define HFCUSB_PCM_RX 7
-
-/*
-* used to switch snd_transfer_mode for different TA modes e.g. the Billion USB TA just
-* supports ISO out, while the Cologne Chip EVAL TA just supports BULK out
+/* Hisax debug support
+* use "modprobe debug=x" where x is bitfield of USB_DBG & ISDN_DBG
*/
-#define USB_INT 0
-#define USB_BULK 1
-#define USB_ISOC 2
-
-#define ISOC_PACKETS_D 8
-#define ISOC_PACKETS_B 8
-#define ISO_BUFFER_SIZE 128
-
-// ISO send definitions
-#define SINK_MAX 68
-#define SINK_MIN 48
-#define SINK_DMIN 12
-#define SINK_DMAX 18
-#define BITLINE_INF (-64*8)
-
-
-
-
-/**********/
-/* macros */
-/**********/
-#define write_usb(a,b,c) usb_control_msg((a)->dev,(a)->ctrl_out_pipe,0,0x40,(c),(b),NULL,0,HFC_CTRL_TIMEOUT)
-#define read_usb(a,b,c) usb_control_msg((a)->dev,(a)->ctrl_in_pipe,1,0xC0,0,(b),(c),1,HFC_CTRL_TIMEOUT)
-
-/*************************************************/
-/* entry and size of output/input control buffer */
-/*************************************************/
-#define HFC_CTRL_BUFSIZE 32
-typedef struct
-{
- __u8 hfc_reg; /* register number */
- __u8 reg_val; /* value to be written (or read) */
- int action; /* data for action handler */
+#ifdef CONFIG_HISAX_DEBUG
+#include <linux/moduleparam.h>
+#define __debug_variable hfc_debug
+#include "hisax_debug.h"
+static u_int debug;
+module_param(debug, uint, 0);
+int hfc_debug;
+#endif
-} ctrl_buft;
-typedef struct
-{
- int vendor; // vendor id
- int prod_id; // product id
- char *vend_name; // vendor string
- __u8 led_scheme; // led display scheme
- __u8 led_invert; // invert led aux port settings
- __u8 led_bits[8]; // array of 8 possible LED bitmask settings
+/****************************************/
+/* data defining the devices to be used */
+/****************************************/
+static struct usb_device_id hfc_usb_idtab[] = {
+ {USB_DEVICE(0x0959, 0x2bd0)}, /* Colognechip USB eval TA */
+ {USB_DEVICE(0x0675, 0x1688)}, /* DrayTek miniVigor 128 USB ISDN TA */
+ {USB_DEVICE(0x07b0, 0x0007)}, /* Billion USB TA 2 */
+ {USB_DEVICE(0x0742, 0x2008)}, /* Stollmann USB TA */
+ {USB_DEVICE(0x0742, 0x2009)}, /* Aceex USB ISDN TA */
+ {USB_DEVICE(0x0742, 0x200A)}, /* OEM USB ISDN TA */
+ {USB_DEVICE(0x08e3, 0x0301)}, /* OliTec ISDN USB */
+ {USB_DEVICE(0x07fa, 0x0846)}, /* Bewan ISDN USB TA */
+ {USB_DEVICE(0x07fa, 0x0847)}, /* Djinn Numeris USB */
+ {USB_DEVICE(0x07b0, 0x0006)}, /* Twister ISDN USB TA */
+ {} /* end with an all-zeroes entry */
+};
-} vendor_data;
+/* driver internal device specific data:
+* VendorID, ProductID, Devicename, LED_SCHEME,
+* LED's BitMask in HFCUSB_P_DATA Register : LED_USB, LED_S0, LED_B1, LED_B2
+*/
+vendor_data vdata[] = {
+ /* CologneChip Eval TA */
+ {0x0959, 0x2bd0, "ISDN USB TA (Cologne Chip HFC-S USB based)",
+ LED_OFF, {4, 0, 2, 1}
+ }
+ ,
+ /* DrayTek miniVigor 128 USB ISDN TA */
+ {0x0675, 0x1688, "DrayTek miniVigor 128 USB ISDN TA",
+ LED_SCHEME1, {1, 2, 0, 0}
+ }
+ ,
+ /* Billion TA */
+ {0x07b0, 0x0007, "Billion tiny USB ISDN TA 128",
+ LED_SCHEME1, {0x80, -64, -32, -16}
+ }
+ ,
+ /* Stollmann TA */
+ {0x0742, 0x2008, "Stollmann USB TA",
+ LED_SCHEME1, {4, 0, 2, 1}
+ }
+ ,
+ /* Aceex USB ISDN TA */
+ {0x0742, 0x2009, "Aceex USB ISDN TA",
+ LED_SCHEME1, {4, 0, 2, 1}
+ }
+ ,
+ /* OEM USB ISDN TA */
+ {0x0742, 0x200A, "OEM USB ISDN TA",
+ LED_SCHEME1, {4, 0, 2, 1}
+ }
+ ,
+ /* Olitec TA */
+ {0x08e3, 0x0301, "Olitec USB RNIS",
+ LED_SCHEME1, {2, 0, 1, 4}
+ }
+ ,
+ /* Bewan TA */
+ {0x07fa, 0x0846, "Bewan Modem RNIS USB",
+ LED_SCHEME1, {0x80, -64, -32, -16}
+ }
+ ,
+ /* Bewan TA */
+ {0x07fa, 0x0847, "Djinn Numeris USB",
+ LED_SCHEME1, {0x80, -64, -32, -16}
+ }
+ ,
+ /* Twister ISDN TA */
+ {0x07b0, 0x0006, "Twister ISDN TA",
+ LED_SCHEME1, {0x80, -64, -32, -16}
+ }
+ ,
+ {0, 0, 0} /* EOL element */
+};
/***************************************************************/
/* structure defining input+output fifos (interrupt/bulk mode) */
/***************************************************************/
-
-struct usb_fifo; /* forward definition */
-typedef struct iso_urb_struct
-{
+struct usb_fifo; /* forward definition */
+typedef struct iso_urb_struct {
struct urb *purb;
__u8 buffer[ISO_BUFFER_SIZE]; /* buffer incoming/outgoing data */
- struct usb_fifo *owner_fifo; // pointer to owner fifo
+ struct usb_fifo *owner_fifo; /* pointer to owner fifo */
} iso_urb_struct;
-struct hfcusb_data; /* forward definition */
-typedef struct usb_fifo
-{
- int fifonum; /* fifo index attached to this structure */
- int active; /* fifo is currently active */
+struct hfcusb_data; /* forward definition */
+typedef struct usb_fifo {
+ int fifonum; /* fifo index attached to this structure */
+ int active; /* fifo is currently active */
struct hfcusb_data *hfc; /* pointer to main structure */
- int pipe; /* address of endpoint */
- __u8 usb_packet_maxlen; /* maximum length for usb transfer */
- unsigned int max_size; /* maximum size of receive/send packet */
- __u8 intervall; /* interrupt interval */
- struct sk_buff *skbuff; /* actual used buffer */
- struct urb *urb; /* transfer structure for usb routines */
- __u8 buffer[128]; /* buffer incoming/outgoing data */
- int bit_line; /* how much bits are in the fifo? */
-
- volatile __u8 usb_transfer_mode;/* switched between ISO and INT */
- iso_urb_struct iso[2]; /* need two urbs to have one always for pending */
- struct hisax_if *hif; /* hisax interface */
- int delete_flg; /* only delete skbuff once */
- int last_urblen; /* remember length of last packet */
+ int pipe; /* address of endpoint */
+ __u8 usb_packet_maxlen; /* maximum length for usb transfer */
+ unsigned int max_size; /* maximum size of receive/send packet */
+ __u8 intervall; /* interrupt interval */
+ struct sk_buff *skbuff; /* actual used buffer */
+ struct urb *urb; /* transfer structure for usb routines */
+ __u8 buffer[128]; /* buffer incoming/outgoing data */
+ int bit_line; /* how much bits are in the fifo? */
+
+ volatile __u8 usb_transfer_mode; /* switched between ISO and INT */
+ iso_urb_struct iso[2]; /* need two urbs to have one always for pending */
+ struct hisax_if *hif; /* hisax interface */
+ int delete_flg; /* only delete skbuff once */
+ int last_urblen; /* remember length of last packet */
} usb_fifo;
-
/*********************************************/
/* structure holding all data for one device */
/*********************************************/
-typedef struct hfcusb_data
-{
- // HiSax Interface for loadable Layer1 drivers
- struct hisax_d_if d_if; /* see hisax_if.h */
- struct hisax_b_if b_if[2]; /* see hisax_if.h */
+typedef struct hfcusb_data {
+ /* HiSax Interface for loadable Layer1 drivers */
+ struct hisax_d_if d_if; /* see hisax_if.h */
+ struct hisax_b_if b_if[2]; /* see hisax_if.h */
int protocol;
-
- struct usb_device *dev; /* our device */
- int if_used; /* used interface number */
- int alt_used; /* used alternate config */
- int ctrl_paksize; /* control pipe packet size */
- int ctrl_in_pipe, ctrl_out_pipe; /* handles for control pipe */
- int cfg_used; /* configuration index used */
- int vend_idx; // vendor found
- int b_mode[2]; // B-channel mode
-
- int l1_activated; // layer 1 activated
-
- int packet_size,iso_packet_size;
+ struct usb_device *dev; /* our device */
+ int if_used; /* used interface number */
+ int alt_used; /* used alternate config */
+ int ctrl_paksize; /* control pipe packet size */
+ int ctrl_in_pipe, ctrl_out_pipe; /* handles for control pipe */
+ int cfg_used; /* configuration index used */
+ int vend_idx; /* vendor found */
+ int b_mode[2]; /* B-channel mode */
+ int l1_activated; /* layer 1 activated */
+ int disc_flag; /* TRUE if device was disonnected to avoid some USB actions */
+ int packet_size, iso_packet_size;
/* control pipe background handling */
ctrl_buft ctrl_buff[HFC_CTRL_BUFSIZE]; /* buffer holding queued data */
- volatile int ctrl_in_idx, ctrl_out_idx,
- ctrl_cnt; /* input/output pointer + count */
- struct urb *ctrl_urb; /* transfer structure for control channel */
+ volatile int ctrl_in_idx, ctrl_out_idx, ctrl_cnt; /* input/output pointer + count */
+ struct urb *ctrl_urb; /* transfer structure for control channel */
struct usb_ctrlrequest ctrl_write; /* buffer for control write request */
struct usb_ctrlrequest ctrl_read; /* same for read request */
- __u8 led_state,led_new_data,led_b_active;
+ __u8 old_led_state, led_state, led_new_data, led_b_active;
- volatile __u8 threshold_mask; /* threshold actually reported */
- volatile __u8 bch_enables; /* or mask for sctrl_r and sctrl register values */
+ volatile __u8 threshold_mask; /* threshold actually reported */
+ volatile __u8 bch_enables; /* or mask for sctrl_r and sctrl register values */
usb_fifo fifos[HFCUSB_NUM_FIFOS]; /* structure holding all fifo data */
- volatile __u8 l1_state; /* actual l1 state */
- struct timer_list t3_timer; /* timer 3 for activation/deactivation */
- struct timer_list t4_timer; /* timer 4 for activation/deactivation */
- struct timer_list led_timer; /* timer flashing leds */
+ volatile __u8 l1_state; /* actual l1 state */
+ struct timer_list t3_timer; /* timer 3 for activation/deactivation */
+ struct timer_list t4_timer; /* timer 4 for activation/deactivation */
+ struct timer_list led_timer; /* timer flashing leds */
} hfcusb_data;
-static void collect_rx_frame(usb_fifo *fifo,__u8 *data,int len,int finish);
+static void collect_rx_frame(usb_fifo * fifo, __u8 * data, int len,
+ int finish);
+static inline const char *
+symbolic(struct hfcusb_symbolic_list list[], const int num)
+{
+ int i;
+ for (i = 0; list[i].name != NULL; i++)
+ if (list[i].num == num)
+ return (list[i].name);
+ return "<unkown>";
+}
+
/******************************************************/
/* start next background transfer for control channel */
/******************************************************/
-static void ctrl_start_transfer(hfcusb_data * hfc)
+static void
+ctrl_start_transfer(hfcusb_data * hfc)
{
- int err;
- if(hfc->ctrl_cnt)
- {
+ if (hfc->ctrl_cnt) {
hfc->ctrl_urb->pipe = hfc->ctrl_out_pipe;
hfc->ctrl_urb->setup_packet = (u_char *) & hfc->ctrl_write;
hfc->ctrl_urb->transfer_buffer = NULL;
hfc->ctrl_urb->transfer_buffer_length = 0;
- hfc->ctrl_write.wIndex = hfc->ctrl_buff[hfc->ctrl_out_idx].hfc_reg;
- hfc->ctrl_write.wValue = hfc->ctrl_buff[hfc->ctrl_out_idx].reg_val;
- err = usb_submit_urb(hfc->ctrl_urb, GFP_ATOMIC); /* start transfer */
- printk(KERN_DEBUG "ctrl_start_transfer: submit %d\n", err);
+ hfc->ctrl_write.wIndex =
+ hfc->ctrl_buff[hfc->ctrl_out_idx].hfc_reg;
+ hfc->ctrl_write.wValue =
+ hfc->ctrl_buff[hfc->ctrl_out_idx].reg_val;
+
+ usb_submit_urb(hfc->ctrl_urb, GFP_ATOMIC); /* start transfer */
}
} /* ctrl_start_transfer */
@@ -271,271 +255,284 @@ static void ctrl_start_transfer(hfcusb_data * hfc)
/* queue a control transfer request */
/* return 0 on success. */
/************************************/
-static int queue_control_request(hfcusb_data * hfc, __u8 reg, __u8 val,int action)
+static int
+queue_control_request(hfcusb_data * hfc, __u8 reg, __u8 val, int action)
{
ctrl_buft *buf;
-#ifdef VERBOSE_USB_DEBUG
- printk ("HFC_USB: queue_control_request reg: %x, val: %x\n", reg, val);
-#endif
-
- if(hfc->ctrl_cnt >= HFC_CTRL_BUFSIZE) return(1); /* no space left */
+ if (hfc->ctrl_cnt >= HFC_CTRL_BUFSIZE)
+ return (1); /* no space left */
buf = &hfc->ctrl_buff[hfc->ctrl_in_idx]; /* pointer to new index */
buf->hfc_reg = reg;
buf->reg_val = val;
- buf->action=action;
+ buf->action = action;
if (++hfc->ctrl_in_idx >= HFC_CTRL_BUFSIZE)
hfc->ctrl_in_idx = 0; /* pointer wrap */
if (++hfc->ctrl_cnt == 1)
ctrl_start_transfer(hfc);
- return(0);
-} /* queue_control_request */
-
+ return (0);
+} /* queue_control_request */
-static int control_action_handler(hfcusb_data *hfc,int reg,int val,int action)
+static int
+control_action_handler(hfcusb_data * hfc, int reg, int val, int action)
{
- if(!action) return(1); // no action defined
-
- return(0);
+ if (!action)
+ return (1); /* no action defined */
+ return (0);
}
-
/***************************************************************/
/* control completion routine handling background control cmds */
/***************************************************************/
-static void ctrl_complete(struct urb *urb, struct pt_regs *regs)
+static void
+ctrl_complete(struct urb *urb, struct pt_regs *regs)
{
hfcusb_data *hfc = (hfcusb_data *) urb->context;
ctrl_buft *buf;
- printk(KERN_DEBUG "ctrl_complete cnt %d\n", hfc->ctrl_cnt);
urb->dev = hfc->dev;
- if(hfc->ctrl_cnt)
- {
- buf=&hfc->ctrl_buff[hfc->ctrl_out_idx];
- control_action_handler(hfc,buf->hfc_reg,buf->reg_val,buf->action);
+ if (hfc->ctrl_cnt) {
+ buf = &hfc->ctrl_buff[hfc->ctrl_out_idx];
+ control_action_handler(hfc, buf->hfc_reg, buf->reg_val,
+ buf->action);
hfc->ctrl_cnt--; /* decrement actual count */
- if(++hfc->ctrl_out_idx >= HFC_CTRL_BUFSIZE) hfc->ctrl_out_idx = 0; /* pointer wrap */
+ if (++hfc->ctrl_out_idx >= HFC_CTRL_BUFSIZE)
+ hfc->ctrl_out_idx = 0; /* pointer wrap */
ctrl_start_transfer(hfc); /* start next transfer */
}
} /* ctrl_complete */
-
-
-#define LED_OFF 0 // no LED support
-#define LED_SCHEME1 1 // LED standard scheme
-#define LED_SCHEME2 2 // not used yet...
-
-#define LED_POWER_ON 1
-#define LED_POWER_OFF 2
-#define LED_S0_ON 3
-#define LED_S0_OFF 4
-#define LED_B1_ON 5
-#define LED_B1_OFF 6
-#define LED_B1_DATA 7
-#define LED_B2_ON 8
-#define LED_B2_OFF 9
-#define LED_B2_DATA 10
-
-#define LED_NORMAL 0 // LEDs are normal
-#define LED_INVERTED 1 // LEDs are inverted
-
-// time for LED flashing
-#define LED_TIME 250
-
-vendor_data vdata[]=
-{
- {0x959, 0x2bd0, "ISDN USB TA (Cologne Chip HFC-S USB based)", LED_OFF,LED_NORMAL,{4,0,2,1}}, /* CologneChip Eval TA */
- {0x7b0, 0x0007, "Billion tiny USB ISDN TA 128", LED_SCHEME1, LED_INVERTED, {8,0x40,0x20,0x10}}, /* Billion TA */
- {0x742, 0x2008, "Stollmann USB TA", LED_SCHEME1, LED_NORMAL, {4,0,2,1}}, /* Stollmann TA */
- {0x8e3, 0x0301, "Olitec USB RNIS", LED_SCHEME1, LED_NORMAL, {2,0,1,4}}, /* Olitec TA */
- {0x675, 0x1688, "DrayTec USB ISDN TA", LED_SCHEME1, LED_NORMAL, {4,0,2,1}}, /* Draytec TA */
- {0x7fa, 0x0846, "Bewan Modem RNIS USB", LED_SCHEME1, LED_INVERTED, {8,0x40,0x20,0x10}}, /* Bewan TA */
- {0} // EOL element
-};
-
/***************************************************/
/* write led data to auxport & invert if necessary */
/***************************************************/
-static void write_led(hfcusb_data * hfc,__u8 led_state)
+static void
+write_led(hfcusb_data * hfc, __u8 led_state)
{
- if(led_state!=hfc->led_state)
- {
- hfc->led_state=led_state;
- queue_control_request(hfc, HFCUSB_P_DATA,(vdata[hfc->vend_idx].led_invert) ? ~led_state : led_state,1);
+ if (led_state != hfc->old_led_state) {
+ hfc->old_led_state = led_state;
+ queue_control_request(hfc, HFCUSB_P_DATA, led_state, 1);
+ }
+}
+
+/**************************/
+/* handle LED bits */
+/**************************/
+static void
+set_led_bit(hfcusb_data * hfc, signed short led_bits, int unset)
+{
+ if (unset) {
+ if (led_bits < 0)
+ hfc->led_state |= abs(led_bits);
+ else
+ hfc->led_state &= ~led_bits;
+ } else {
+ if (led_bits < 0)
+ hfc->led_state &= ~abs(led_bits);
+ else
+ hfc->led_state |= led_bits;
}
}
/******************************************/
/* invert B-channel LEDs if data is sent */
/******************************************/
-static void led_timer(hfcusb_data * hfc)
+static void
+led_timer(hfcusb_data * hfc)
{
- static int cnt=0;
- __u8 led_state=hfc->led_state;
-
- if(cnt)
- {
- if(hfc->led_b_active&1) led_state|=vdata[hfc->vend_idx].led_bits[2];
- if(hfc->led_b_active&2) led_state|=vdata[hfc->vend_idx].led_bits[3];
- }
- else
- {
- if(!(hfc->led_b_active&1) || hfc->led_new_data&1) led_state&=~vdata[hfc->vend_idx].led_bits[2];
- if(!(hfc->led_b_active&2) || hfc->led_new_data&2) led_state&=~vdata[hfc->vend_idx].led_bits[3];
+ static int cnt = 0;
+
+ if (cnt) {
+ if (hfc->led_b_active & 1)
+ set_led_bit(hfc, vdata[hfc->vend_idx].led_bits[2],
+ 0);
+ if (hfc->led_b_active & 2)
+ set_led_bit(hfc, vdata[hfc->vend_idx].led_bits[3],
+ 0);
+ } else {
+ if (!(hfc->led_b_active & 1) || hfc->led_new_data & 1)
+ set_led_bit(hfc, vdata[hfc->vend_idx].led_bits[2],
+ 1);
+ if (!(hfc->led_b_active & 2) || hfc->led_new_data & 2)
+ set_led_bit(hfc, vdata[hfc->vend_idx].led_bits[3],
+ 1);
}
- write_led(hfc,led_state);
- hfc->led_new_data=0;
+ write_led(hfc, hfc->led_state);
+ hfc->led_new_data = 0;
+
+ cnt = !cnt;
- cnt=!cnt;
- // restart 4 hz timer
- hfc->led_timer.expires = jiffies + (LED_TIME * HZ) / 1000;
- if(!timer_pending(&hfc->led_timer)) add_timer(&hfc->led_timer);
+ /* restart 4 hz timer */
+ if (!timer_pending(&hfc->led_timer)) {
+ add_timer(&hfc->led_timer);
+ hfc->led_timer.expires = jiffies + (LED_TIME * HZ) / 1000;
+ }
}
/**************************/
/* handle LED requests */
/**************************/
-static void handle_led(hfcusb_data * hfc,int event)
+static void
+handle_led(hfcusb_data * hfc, int event)
{
- __u8 led_state=hfc->led_state;
-
- // if no scheme -> no LED action
- if(vdata[hfc->vend_idx].led_scheme==LED_OFF) return;
+ /* if no scheme -> no LED action */
+ if (vdata[hfc->vend_idx].led_scheme == LED_OFF)
+ return;
- switch(event)
- {
+ switch (event) {
case LED_POWER_ON:
- led_state|=vdata[hfc->vend_idx].led_bits[0];
- break;
- case LED_POWER_OFF: // no Power off handling
- break;
+ set_led_bit(hfc, vdata[hfc->vend_idx].led_bits[0],
+ 0);
+ set_led_bit(hfc, vdata[hfc->vend_idx].led_bits[1],
+ 1);
+ set_led_bit(hfc, vdata[hfc->vend_idx].led_bits[2],
+ 1);
+ set_led_bit(hfc, vdata[hfc->vend_idx].led_bits[3],
+ 1);
+ break;
+ case LED_POWER_OFF: /* no Power off handling */
+ break;
case LED_S0_ON:
- led_state|=vdata[hfc->vend_idx].led_bits[1];
- break;
+ set_led_bit(hfc, vdata[hfc->vend_idx].led_bits[1],
+ 0);
+ break;
case LED_S0_OFF:
- led_state&=~vdata[hfc->vend_idx].led_bits[1];
- break;
+ set_led_bit(hfc, vdata[hfc->vend_idx].led_bits[1],
+ 1);
+ break;
case LED_B1_ON:
- hfc->led_b_active|=1;
- break;
+ hfc->led_b_active |= 1;
+ break;
case LED_B1_OFF:
- hfc->led_b_active&=~1;
- break;
+ hfc->led_b_active &= ~1;
+ break;
case LED_B1_DATA:
- hfc->led_new_data|=1;
- break;
+ hfc->led_new_data |= 1;
+ break;
case LED_B2_ON:
- hfc->led_b_active|=2;
- break;
+ hfc->led_b_active |= 2;
+ break;
case LED_B2_OFF:
- hfc->led_b_active&=~2;
- break;
+ hfc->led_b_active &= ~2;
+ break;
case LED_B2_DATA:
- hfc->led_new_data|=2;
- break;
+ hfc->led_new_data |= 2;
+ break;
}
-
- write_led(hfc,led_state);
+
+ write_led(hfc, hfc->led_state);
}
/********************************/
/* called when timer t3 expires */
/********************************/
-static void l1_timer_expire_t3(hfcusb_data * hfc)
+static void
+l1_timer_expire_t3(hfcusb_data * hfc)
{
- //printk (KERN_INFO "HFC-USB: l1_timer_expire_t3\n");
-
- hfc->d_if.ifc.l1l2(&hfc->d_if.ifc,PH_DEACTIVATE | INDICATION,NULL);
-#ifdef VERBOSE_USB_DEBUG
- printk(KERN_INFO "PH_DEACTIVATE | INDICATION sent\n");
+ hfc->d_if.ifc.l1l2(&hfc->d_if.ifc, PH_DEACTIVATE | INDICATION,
+ NULL);
+#ifdef CONFIG_HISAX_DEBUG
+ DBG(ISDN_DBG,
+ "HFC-S USB: PH_DEACTIVATE | INDICATION sent (T3 expire)");
#endif
- hfc->l1_activated=FALSE;
- handle_led(hfc,LED_S0_OFF);
+ hfc->l1_activated = FALSE;
+ handle_led(hfc, LED_S0_OFF);
+ /* deactivate : */
+ queue_control_request(hfc, HFCUSB_STATES, 0x10, 1);
+ queue_control_request(hfc, HFCUSB_STATES, 3, 1);
}
/********************************/
/* called when timer t4 expires */
/********************************/
-static void l1_timer_expire_t4(hfcusb_data * hfc)
+static void
+l1_timer_expire_t4(hfcusb_data * hfc)
{
- //printk (KERN_INFO "HFC-USB: l1_timer_expire_t4\n");
-
- hfc->d_if.ifc.l1l2(&hfc->d_if.ifc,PH_DEACTIVATE | INDICATION,NULL);
-#ifdef VERBOSE_USB_DEBUG
- printk(KERN_INFO "PH_DEACTIVATE | INDICATION sent\n");
+ hfc->d_if.ifc.l1l2(&hfc->d_if.ifc, PH_DEACTIVATE | INDICATION,
+ NULL);
+#ifdef CONFIG_HISAX_DEBUG
+ DBG(ISDN_DBG,
+ "HFC-S USB: PH_DEACTIVATE | INDICATION sent (T4 expire)");
#endif
- hfc->l1_activated=FALSE;
- handle_led(hfc,LED_S0_OFF);
+ hfc->l1_activated = FALSE;
+ handle_led(hfc, LED_S0_OFF);
}
/*****************************/
/* handle S0 state changes */
/*****************************/
-static void state_handler(hfcusb_data * hfc,__u8 state)
+static void
+state_handler(hfcusb_data * hfc, __u8 state)
{
__u8 old_state;
- old_state=hfc->l1_state;
-
- // range check
- if(state==old_state || state<1 || state>8) return;
+ old_state = hfc->l1_state;
+ if (state == old_state || state < 1 || state > 8)
+ return;
-#ifdef VERBOSE_ISDN_DEBUG
- printk(KERN_INFO "HFC-USB: new S0 state:%d old_state:%d\n",state,old_state);
+#ifdef CONFIG_HISAX_DEBUG
+ DBG(ISDN_DBG, "HFC-S USB: new S0 state:%d old_state:%d", state,
+ old_state);
+#endif
+ if (state < 4 || state == 7 || state == 8) {
+ if (timer_pending(&hfc->t3_timer))
+ del_timer(&hfc->t3_timer);
+#ifdef CONFIG_HISAX_DEBUG
+ DBG(ISDN_DBG, "HFC-S USB: T3 deactivated");
#endif
-
- if(state<4 || state==7 || state==8)
- {
- if(timer_pending(&hfc->t3_timer)) del_timer(&hfc->t3_timer);
- //printk(KERN_INFO "HFC-USB: T3 deactivated\n");
}
-
- if(state>=7)
- {
- if(timer_pending(&hfc->t4_timer)) del_timer(&hfc->t4_timer);
- //printk(KERN_INFO "HFC-USB: T4 deactivated\n");
+ if (state >= 7) {
+ if (timer_pending(&hfc->t4_timer))
+ del_timer(&hfc->t4_timer);
+#ifdef CONFIG_HISAX_DEBUG
+ DBG(ISDN_DBG, "HFC-S USB: T4 deactivated");
+#endif
}
- if(state==7 && !hfc->l1_activated)
- {
- hfc->d_if.ifc.l1l2(&hfc->d_if.ifc,PH_ACTIVATE | INDICATION,NULL);
- //printk(KERN_INFO "HFC-USB: PH_ACTIVATE | INDICATION sent\n");
- hfc->l1_activated=TRUE;
- handle_led(hfc,LED_S0_ON);
- }
- else
- if(state<=3 /* && activated*/)
- {
- if(old_state==7 || old_state==8)
- {
- //printk(KERN_INFO "HFC-USB: T4 activated\n");
- hfc->t4_timer.expires = jiffies + (HFC_TIMER_T4 * HZ) / 1000;
- if(!timer_pending(&hfc->t4_timer)) add_timer(&hfc->t4_timer);
- }
- else
- {
- hfc->d_if.ifc.l1l2(&hfc->d_if.ifc,PH_DEACTIVATE | INDICATION,NULL);
- //printk(KERN_INFO "HFC-USB: PH_DEACTIVATE | INDICATION sent\n");
- hfc->l1_activated=FALSE;
- handle_led(hfc,LED_S0_OFF);
+ if (state == 7 && !hfc->l1_activated) {
+ hfc->d_if.ifc.l1l2(&hfc->d_if.ifc,
+ PH_ACTIVATE | INDICATION, NULL);
+#ifdef CONFIG_HISAX_DEBUG
+ DBG(ISDN_DBG, "HFC-S USB: PH_ACTIVATE | INDICATION sent");
+#endif
+ hfc->l1_activated = TRUE;
+ handle_led(hfc, LED_S0_ON);
+ } else if (state <= 3 /* && activated */ ) {
+ if (old_state == 7 || old_state == 8) {
+#ifdef CONFIG_HISAX_DEBUG
+ DBG(ISDN_DBG, "HFC-S USB: T4 activated");
+#endif
+ if (!timer_pending(&hfc->t4_timer)) {
+ hfc->t4_timer.expires =
+ jiffies + (HFC_TIMER_T4 * HZ) / 1000;
+ add_timer(&hfc->t4_timer);
+ }
+ } else {
+ hfc->d_if.ifc.l1l2(&hfc->d_if.ifc,
+ PH_DEACTIVATE | INDICATION,
+ NULL);
+#ifdef CONFIG_HISAX_DEBUG
+ DBG(ISDN_DBG,
+ "HFC-S USB: PH_DEACTIVATE | INDICATION sent");
+#endif
+ hfc->l1_activated = FALSE;
+ handle_led(hfc, LED_S0_OFF);
}
}
-
- hfc->l1_state=state;
+ hfc->l1_state = state;
}
-
/* prepare iso urb */
-static void fill_isoc_urb(struct urb *urb, struct usb_device *dev, unsigned int pipe, void *buf,
- int num_packets, int packet_size, int interval, usb_complete_t complete, void *context)
+static void
+fill_isoc_urb(struct urb *urb, struct usb_device *dev, unsigned int pipe,
+ void *buf, int num_packets, int packet_size, int interval,
+ usb_complete_t complete, void *context)
{
int k;
- spin_lock_init(&urb->lock); // do we really need spin_lock_init ?
+ spin_lock_init(&urb->lock);
urb->dev = dev;
urb->pipe = pipe;
urb->complete = complete;
@@ -543,7 +540,6 @@ static void fill_isoc_urb(struct urb *urb, struct usb_device *dev, unsigned int
urb->transfer_buffer_length = packet_size * num_packets;
urb->context = context;
urb->transfer_buffer = buf;
- urb->transfer_flags = 0;
urb->transfer_flags = URB_ISO_ASAP;
urb->actual_length = 0;
urb->interval = interval;
@@ -554,67 +550,80 @@ static void fill_isoc_urb(struct urb *urb, struct usb_device *dev, unsigned int
}
}
-/* allocs urbs and start isoc transfer with two pending urbs to avoid gaps in the transfer chain */
-static int start_isoc_chain(usb_fifo * fifo, int num_packets_per_urb,usb_complete_t complete,int packet_size)
+/* allocs urbs and start isoc transfer with two pending urbs to avoid
+ gaps in the transfer chain */
+static int
+start_isoc_chain(usb_fifo * fifo, int num_packets_per_urb,
+ usb_complete_t complete, int packet_size)
{
int i, k, errcode;
-#ifdef VERBOSE_USB_DEBUG
- printk(KERN_INFO "HFC-USB: starting ISO-chain for Fifo %i\n", fifo->fifonum);
-#endif
-
+ printk(KERN_INFO "HFC-S USB: starting ISO-chain for Fifo %i\n",
+ fifo->fifonum);
- // allocate Memory for Iso out Urbs
+ /* allocate Memory for Iso out Urbs */
for (i = 0; i < 2; i++) {
if (!(fifo->iso[i].purb)) {
- fifo->iso[i].purb = usb_alloc_urb(num_packets_per_urb, GFP_KERNEL);
+ fifo->iso[i].purb =
+ usb_alloc_urb(num_packets_per_urb, GFP_KERNEL);
+ if (!(fifo->iso[i].purb)) {
+ printk(KERN_INFO
+ "alloc urb for fifo %i failed!!!",
+ fifo->fifonum);
+ }
fifo->iso[i].owner_fifo = (struct usb_fifo *) fifo;
- // Init the first iso
- if (ISO_BUFFER_SIZE >= (fifo->usb_packet_maxlen * num_packets_per_urb))
- {
-
- fill_isoc_urb(fifo->iso[i].purb, fifo->hfc->dev, fifo->pipe, fifo->iso[i].buffer,
- num_packets_per_urb, fifo->usb_packet_maxlen, fifo->intervall,
- complete, &fifo->iso[i]);
-
- memset(fifo->iso[i].buffer, 0, sizeof(fifo->iso[i].buffer));
-
- // defining packet delimeters in fifo->buffer
- for(k = 0; k < num_packets_per_urb; k++)
- {
- fifo->iso[i].purb->iso_frame_desc[k].offset = k*packet_size;
- fifo->iso[i].purb->iso_frame_desc[k].length = packet_size;
+ /* Init the first iso */
+ if (ISO_BUFFER_SIZE >=
+ (fifo->usb_packet_maxlen *
+ num_packets_per_urb)) {
+ fill_isoc_urb(fifo->iso[i].purb,
+ fifo->hfc->dev, fifo->pipe,
+ fifo->iso[i].buffer,
+ num_packets_per_urb,
+ fifo->usb_packet_maxlen,
+ fifo->intervall, complete,
+ &fifo->iso[i]);
+ memset(fifo->iso[i].buffer, 0,
+ sizeof(fifo->iso[i].buffer));
+ /* defining packet delimeters in fifo->buffer */
+ for (k = 0; k < num_packets_per_urb; k++) {
+ fifo->iso[i].purb->
+ iso_frame_desc[k].offset =
+ k * packet_size;
+ fifo->iso[i].purb->
+ iso_frame_desc[k].length =
+ packet_size;
}
+ } else {
+ printk(KERN_INFO
+ "HFC-S USB: ISO Buffer size to small!\n");
}
}
-
fifo->bit_line = BITLINE_INF;
errcode = usb_submit_urb(fifo->iso[i].purb, GFP_KERNEL);
fifo->active = (errcode >= 0) ? 1 : 0;
- if(errcode < 0)
- {
- printk(KERN_INFO "HFC-USB: error submitting ISO URB: %i.%i \n", errcode, i);
+ if (errcode < 0) {
+ printk(KERN_INFO "HFC-S USB: %s URB nr:%d\n",
+ symbolic(urb_errlist, errcode), i);
};
-
}
-
- // errcode = (usb_submit_urb(fifo->iso[0].purb, GFP_KERNEL));
- return(fifo->active);
+ return (fifo->active);
}
/* stops running iso chain and frees their pending urbs */
-static void stop_isoc_chain(usb_fifo * fifo)
+static void
+stop_isoc_chain(usb_fifo * fifo)
{
int i;
- for(i = 0; i < 2; i++)
- {
- if(fifo->iso[i].purb)
- {
-#ifdef VERBOSE_USB_DEBUG
- printk(KERN_INFO "HFC-USB: Stopping iso chain for fifo %i.%i\n", fifo->fifonum, i);
+ for (i = 0; i < 2; i++) {
+ if (fifo->iso[i].purb) {
+#ifdef CONFIG_HISAX_DEBUG
+ DBG(USB_DBG,
+ "HFC-S USB: Stopping iso chain for fifo %i.%i",
+ fifo->fifonum, i);
#endif
usb_unlink_urb(fifo->iso[i].purb);
usb_free_urb(fifo->iso[i].purb);
@@ -629,554 +638,653 @@ static void stop_isoc_chain(usb_fifo * fifo)
fifo->active = 0;
}
-// defines how much ISO packets are handled in one URB
-static int iso_packets[8]={ISOC_PACKETS_B,ISOC_PACKETS_B,ISOC_PACKETS_B,ISOC_PACKETS_B,
- ISOC_PACKETS_D,ISOC_PACKETS_D,ISOC_PACKETS_D,ISOC_PACKETS_D};
+/* defines how much ISO packets are handled in one URB */
+static int iso_packets[8] =
+ { ISOC_PACKETS_B, ISOC_PACKETS_B, ISOC_PACKETS_B, ISOC_PACKETS_B,
+ ISOC_PACKETS_D, ISOC_PACKETS_D, ISOC_PACKETS_D, ISOC_PACKETS_D
+};
/*****************************************************/
/* transmit completion routine for all ISO tx fifos */
/*****************************************************/
-static void tx_iso_complete(struct urb *urb, struct pt_regs *regs)
+static void
+tx_iso_complete(struct urb *urb, struct pt_regs *regs)
{
iso_urb_struct *context_iso_urb = (iso_urb_struct *) urb->context;
usb_fifo *fifo = context_iso_urb->owner_fifo;
hfcusb_data *hfc = fifo->hfc;
- int k, tx_offset, num_isoc_packets, sink, len, current_len,errcode,frame_complete,transp_mode,fifon;
+ int k, tx_offset, num_isoc_packets, sink, len, current_len,
+ errcode;
+ int frame_complete, transp_mode, fifon, status;
__u8 threshbit;
- __u8 threshtable[8] = { 1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80};
-
- fifon=fifo->fifonum;
- tx_offset=0;
- // very weird error code when using ohci drivers, for now : ignore this error ... (MB)
- if(urb->status == -EOVERFLOW)
- {
- urb->status = 0;
-#ifdef VERBOSE_USB_DEBUG
- printk(KERN_INFO "HFC-USB: ignoring USB DATAOVERRUN for fifo %i \n",fifon);
-#endif
- }
-
- if(fifo->active && !urb->status)
- {
- transp_mode=0;
- if(fifon<4 && hfc->b_mode[fifon/2]==L1_MODE_TRANS) transp_mode=TRUE;
+ __u8 threshtable[8] = { 1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80 };
- threshbit = threshtable[fifon] & hfc->threshold_mask; // is threshold set for our channel?
- num_isoc_packets=iso_packets[fifon];
+ fifon = fifo->fifonum;
+ status = urb->status;
- if(fifon >= HFCUSB_D_TX)
- {
- sink = (threshbit) ? SINK_DMIN : SINK_DMAX; // how much bit go to the sink for D-channel?
- }
- else
- {
- sink = (threshbit) ? SINK_MIN : SINK_MAX; // how much bit go to the sink for B-channel?
- }
+ tx_offset = 0;
- // prepare ISO Urb
- fill_isoc_urb(urb, fifo->hfc->dev, fifo->pipe,context_iso_urb->buffer, num_isoc_packets,
- fifo->usb_packet_maxlen, fifo->intervall, tx_iso_complete, urb->context);
- memset(context_iso_urb->buffer, 0, sizeof(context_iso_urb->buffer));
+ if (fifo->active && !status) {
+ transp_mode = 0;
+ if (fifon < 4 && hfc->b_mode[fifon / 2] == L1_MODE_TRANS)
+ transp_mode = TRUE;
- frame_complete=FALSE;
+ /* is FifoFull-threshold set for our channel? */
+ threshbit = threshtable[fifon] & hfc->threshold_mask;
+ num_isoc_packets = iso_packets[fifon];
- // Generate Iso Packets
- for(k = 0; k < num_isoc_packets; ++k)
- {
- if(fifo->skbuff)
- {
- len = fifo->skbuff->len; // remaining length
-
- fifo->bit_line -= sink; // we lower data margin every msec
+ /* predict dataflow to avoid fifo overflow */
+ if (fifon >= HFCUSB_D_TX) {
+ sink = (threshbit) ? SINK_DMIN : SINK_DMAX;
+ } else {
+ sink = (threshbit) ? SINK_MIN : SINK_MAX;
+ }
+ fill_isoc_urb(urb, fifo->hfc->dev, fifo->pipe,
+ context_iso_urb->buffer, num_isoc_packets,
+ fifo->usb_packet_maxlen, fifo->intervall,
+ tx_iso_complete, urb->context);
+ memset(context_iso_urb->buffer, 0,
+ sizeof(context_iso_urb->buffer));
+ frame_complete = FALSE;
+ /* Generate next Iso Packets */
+ for (k = 0; k < num_isoc_packets; ++k) {
+ if (fifo->skbuff) {
+ len = fifo->skbuff->len;
+ /* we lower data margin every msec */
+ fifo->bit_line -= sink;
current_len = (0 - fifo->bit_line) / 8;
- if(current_len > 14) current_len = 14; // maximum 15 byte for every ISO packet makes our life easier
- current_len = (len <= current_len) ? len : current_len;
- fifo->bit_line += current_len * 8; // how much bit do we put on the line?
+ /* maximum 15 byte for every ISO packet makes our life easier */
+ if (current_len > 14)
+ current_len = 14;
+ current_len =
+ (len <=
+ current_len) ? len : current_len;
+ /* how much bit do we put on the line? */
+ fifo->bit_line += current_len * 8;
context_iso_urb->buffer[tx_offset] = 0;
- if(current_len == len)
- {
- if(!transp_mode)
- {
- context_iso_urb->buffer[tx_offset] = 1; // here frame completion
- fifo->bit_line += 32; // add 2 byte flags and 16bit CRC at end of ISDN frame
+ if (current_len == len) {
+ if (!transp_mode) {
+ /* here frame completion */
+ context_iso_urb->
+ buffer[tx_offset] = 1;
+ /* add 2 byte flags and 16bit CRC at end of ISDN frame */
+ fifo->bit_line += 32;
}
frame_complete = TRUE;
}
- // copy bytes from buffer into ISO_URB
- memcpy(context_iso_urb->buffer+tx_offset+1,fifo->skbuff->data,current_len);
- skb_pull(fifo->skbuff,current_len);
+ memcpy(context_iso_urb->buffer +
+ tx_offset + 1, fifo->skbuff->data,
+ current_len);
+ skb_pull(fifo->skbuff, current_len);
- // define packet delimeters within the URB buffer
+ /* define packet delimeters within the URB buffer */
urb->iso_frame_desc[k].offset = tx_offset;
- urb->iso_frame_desc[k].length = current_len + 1;
+ urb->iso_frame_desc[k].length =
+ current_len + 1;
tx_offset += (current_len + 1);
- // printk(KERN_INFO "HFC-USB: fifonum:%d,%d bytes to send, %d bytes ISO packet,bitline:%d,sink:%d,threshbit:%d,threshmask:%x\n",fifon,len,current_len,fifo->bit_line,sink,threshbit,hfc->threshold_mask);
- if(!transp_mode)
- {
- if(fifon==HFCUSB_B1_TX) handle_led(hfc,LED_B1_DATA);
- if(fifon==HFCUSB_B2_TX) handle_led(hfc,LED_B2_DATA);
+ if (!transp_mode) {
+ if (fifon == HFCUSB_B1_TX)
+ handle_led(hfc,
+ LED_B1_DATA);
+ if (fifon == HFCUSB_B2_TX)
+ handle_led(hfc,
+ LED_B2_DATA);
}
- }
- else
- {
- // we have no more data - generate 1 byte ISO packets
- urb->iso_frame_desc[k].offset = tx_offset++;
+ } else {
+ urb->iso_frame_desc[k].offset =
+ tx_offset++;
urb->iso_frame_desc[k].length = 1;
- fifo->bit_line -= sink; // we lower data margin every msec
+ fifo->bit_line -= sink; /* we lower data margin every msec */
- if(fifo->bit_line < BITLINE_INF)
- {
+ if (fifo->bit_line < BITLINE_INF) {
fifo->bit_line = BITLINE_INF;
- //printk (KERN_INFO "HFC-USB: BITLINE_INF underrun\n");
}
}
- if(frame_complete)
- {
- // delete the buffer only once, here or in hfc_usb_l2l1() in a PH_DATA|REQUEST
- fifo->delete_flg=TRUE;
-
- fifo->hif->l1l2(fifo->hif,PH_DATA|CONFIRM,(void*)fifo->skbuff->truesize);
-
- if(fifo->skbuff && fifo->delete_flg)
- {
+ if (frame_complete) {
+ fifo->delete_flg = TRUE;
+ fifo->hif->l1l2(fifo->hif,
+ PH_DATA | CONFIRM,
+ (void *) fifo->skbuff->
+ truesize);
+ if (fifo->skbuff && fifo->delete_flg) {
dev_kfree_skb_any(fifo->skbuff);
- //printk(KERN_INFO "HFC-USB: skbuff=NULL on fifo:%d\n",fifo->fifonum);
fifo->skbuff = NULL;
- fifo->delete_flg=FALSE;
+ fifo->delete_flg = FALSE;
}
-
- frame_complete=FALSE;
+ frame_complete = FALSE;
}
- }
-
+ }
errcode = usb_submit_urb(urb, GFP_ATOMIC);
- if(errcode < 0)
- {
- printk(KERN_INFO "HFC-USB: error submitting ISO URB: %i \n", errcode);
+ if (errcode < 0) {
+ printk(KERN_INFO
+ "HFC-S USB: error submitting ISO URB: %d \n",
+ errcode);
}
- }
- else
- {
- if(urb->status)
- {
- printk(KERN_INFO "HFC-USB: tx_iso_complete : urb->status %i, fifonum %i\n", urb->status,fifon);
+ } else {
+ if (status && !hfc->disc_flag) {
+ printk(KERN_INFO
+ "HFC-S USB: tx_iso_complete : urb->status %s (%i), fifonum=%d\n",
+ symbolic(urb_errlist, status), status,
+ fifon);
}
}
-
} /* tx_iso_complete */
/*****************************************************/
/* receive completion routine for all ISO tx fifos */
/*****************************************************/
-static void rx_iso_complete(struct urb *urb, struct pt_regs *regs)
+static void
+rx_iso_complete(struct urb *urb, struct pt_regs *regs)
{
iso_urb_struct *context_iso_urb = (iso_urb_struct *) urb->context;
usb_fifo *fifo = context_iso_urb->owner_fifo;
hfcusb_data *hfc = fifo->hfc;
- int k, len, errcode, offset, num_isoc_packets,fifon;
+ int k, len, errcode, offset, num_isoc_packets, fifon, maxlen,
+ status;
+ unsigned int iso_status;
__u8 *buf;
+ static __u8 eof[8];
+#ifdef CONFIG_HISAX_DEBUG
+ __u8 i;
+#endif
+
+ fifon = fifo->fifonum;
+ status = urb->status;
- fifon=fifo->fifonum;
- // very weird error code when using ohci drivers, for now : ignore this error ... (MB)
- if(urb->status == -EOVERFLOW)
- {
- urb->status = 0;
-#ifdef VERBOSE_USB_DEBUG
- printk(KERN_INFO "HFC-USB: ignoring USB DATAOVERRUN for fifo %i \n",fifon);
+ if (urb->status == -EOVERFLOW) {
+#ifdef CONFIG_HISAX_DEBUG
+ DBG(USB_DBG,
+ "HFC-USB: ignoring USB DATAOVERRUN for fifo %i \n",
+ fifon);
#endif
+ status = 0;
}
-
- if(fifo->active && !urb->status)
- {
- num_isoc_packets=iso_packets[fifon];
-
- // Generate D-Channel Iso Packets
- for(k = 0; k < num_isoc_packets; ++k)
- {
- len=urb->iso_frame_desc[k].actual_length;
- offset=urb->iso_frame_desc[k].offset;
- buf=context_iso_urb->buffer+offset;
-
- if(fifo->last_urblen!=fifo->usb_packet_maxlen)
- {
- // the threshold mask is in the 2nd status byte
- hfc->threshold_mask=buf[1];
- // the S0 state is in the upper half of the 1st status byte
- state_handler(hfc,buf[0] >> 4);
- // if we have more than the 2 status bytes -> collect data
- if(len>2) collect_rx_frame(fifo,buf+2,len-2,buf[0]&1);
+ if (fifo->active && !status) {
+ num_isoc_packets = iso_packets[fifon];
+ maxlen = fifo->usb_packet_maxlen;
+ for (k = 0; k < num_isoc_packets; ++k) {
+ len = urb->iso_frame_desc[k].actual_length;
+ offset = urb->iso_frame_desc[k].offset;
+ buf = context_iso_urb->buffer + offset;
+ iso_status = urb->iso_frame_desc[k].status;
+#ifdef CONFIG_HISAX_DEBUG
+ if (iso_status && !hfc->disc_flag)
+ DBG(USB_DBG,
+ "HFC-S USB: ISO packet failure - status:%x",
+ iso_status);
+
+ if ((fifon == 5) && (debug > 1)) {
+ printk(KERN_INFO
+ "HFC-S USB: ISO-D-RX lst_urblen:%2d "
+ "act_urblen:%2d max-urblen:%2d "
+ "EOF:0x%0x DATA: ",
+ fifo->last_urblen, len, maxlen,
+ eof[5]);
+ for (i = 0; i < len; i++)
+ printk("%.2x ", buf[i]);
+ printk("\n");
}
- else collect_rx_frame(fifo,buf,len,0);
-
- fifo->last_urblen=len;
-
- }
-
- // prepare ISO Urb
- fill_isoc_urb(urb, fifo->hfc->dev, fifo->pipe,context_iso_urb->buffer, num_isoc_packets,
- fifo->usb_packet_maxlen, fifo->intervall, rx_iso_complete, urb->context);
+#endif
+ if (fifo->last_urblen != maxlen) {
+ /* the threshold mask is in the 2nd status byte */
+ hfc->threshold_mask = buf[1];
+ /* care for L1 state only for D-Channel
+ to avoid overlapped iso completions */
+ if (fifon == 5) {
+ /* the S0 state is in the upper half
+ of the 1st status byte */
+ state_handler(hfc, buf[0] >> 4);
+ }
+ eof[fifon] = buf[0] & 1;
+ if (len > 2)
+ collect_rx_frame(fifo, buf + 2,
+ len - 2,
+ (len <
+ maxlen) ?
+ eof[fifon] : 0);
+ } else {
+ collect_rx_frame(fifo, buf, len,
+ (len <
+ maxlen) ? eof[fifon] :
+ 0);
+ }
+ fifo->last_urblen = len;
+ }
+ fill_isoc_urb(urb, fifo->hfc->dev, fifo->pipe,
+ context_iso_urb->buffer, num_isoc_packets,
+ fifo->usb_packet_maxlen, fifo->intervall,
+ rx_iso_complete, urb->context);
errcode = usb_submit_urb(urb, GFP_ATOMIC);
- if(errcode < 0)
- {
- printk(KERN_INFO "HFC-USB: error submitting ISO URB: %i \n", errcode);
+ if (errcode < 0) {
+ printk(KERN_INFO
+ "HFC-S USB: error submitting ISO URB: %d \n",
+ errcode);
}
- }
- else
- {
- if(urb->status)
- {
- printk(KERN_INFO "HFC-USB: rx_iso_complete : urb->status %i, fifonum %i\n", urb->status,fifon);
+ } else {
+ if (status && !hfc->disc_flag) {
+ printk(KERN_INFO
+ "HFC-S USB: rx_iso_complete : "
+ "urb->status %d, fifonum %d\n",
+ status, fifon);
}
}
} /* rx_iso_complete */
-
/*****************************************************/
/* collect data from interrupt or isochron in */
/*****************************************************/
-static void collect_rx_frame(usb_fifo *fifo,__u8 *data,int len,int finish)
+static void
+collect_rx_frame(usb_fifo * fifo, __u8 * data, int len, int finish)
{
hfcusb_data *hfc = fifo->hfc;
- int transp_mode,fifon;
-
- fifon=fifo->fifonum;
- transp_mode=0;
- if(fifon<4 && hfc->b_mode[fifon/2]==L1_MODE_TRANS) transp_mode=TRUE;
-
- //printk(KERN_INFO "HFC-USB: got %d bytes finish:%d max_size:%d fifo:%d\n",len,finish,fifo->max_size,fifon);
- if(!fifo->skbuff)
- {
- // allocate sk buffer
- fifo->skbuff=dev_alloc_skb(fifo->max_size + 3);
- if(!fifo->skbuff)
- {
- printk(KERN_INFO "HFC-USB: cannot allocate buffer (dev_alloc_skb) fifo:%d\n",fifon);
+ int transp_mode, fifon;
+#ifdef CONFIG_HISAX_DEBUG
+ int i;
+#endif
+ fifon = fifo->fifonum;
+ transp_mode = 0;
+ if (fifon < 4 && hfc->b_mode[fifon / 2] == L1_MODE_TRANS)
+ transp_mode = TRUE;
+
+ if (!fifo->skbuff) {
+ fifo->skbuff = dev_alloc_skb(fifo->max_size + 3);
+ if (!fifo->skbuff) {
+ printk(KERN_INFO
+ "HFC-S USB: cannot allocate buffer (dev_alloc_skb) fifo:%d\n",
+ fifon);
return;
}
-
}
-
- if(len && fifo->skbuff->len+len<fifo->max_size)
- {
- memcpy(skb_put(fifo->skbuff,len),data,len);
+ if (len) {
+ if (fifo->skbuff->len + len < fifo->max_size) {
+ memcpy(skb_put(fifo->skbuff, len), data, len);
+ } else {
+#ifdef CONFIG_HISAX_DEBUG
+ printk(KERN_INFO "HFC-S USB: ");
+ for (i = 0; i < 15; i++)
+ printk("%.2x ",
+ fifo->skbuff->data[fifo->skbuff->
+ len - 15 + i]);
+ printk("\n");
+#endif
+ printk(KERN_INFO
+ "HCF-USB: got frame exceeded fifo->max_size:%d on fifo:%d\n",
+ fifo->max_size, fifon);
+ }
}
- else printk(KERN_INFO "HCF-USB: got frame exceeded fifo->max_size:%d\n",fifo->max_size);
-
- // give transparent data up, when 128 byte are available
- if(transp_mode && fifo->skbuff->len>=128)
- {
- fifo->hif->l1l2(fifo->hif,PH_DATA | INDICATION,fifo->skbuff);
- fifo->skbuff = NULL; // buffer was freed from upper layer
+ if (transp_mode && fifo->skbuff->len >= 128) {
+ fifo->hif->l1l2(fifo->hif, PH_DATA | INDICATION,
+ fifo->skbuff);
+ fifo->skbuff = NULL;
return;
}
-
- // we have a complete hdlc packet
- if(finish)
- {
- if(!fifo->skbuff->data[fifo->skbuff->len-1])
- {
- skb_trim(fifo->skbuff,fifo->skbuff->len-3); // remove CRC & status
-
- //printk(KERN_INFO "HFC-USB: got frame %d bytes on fifo:%d\n",fifo->skbuff->len,fifon);
-
- if(fifon==HFCUSB_PCM_RX) fifo->hif->l1l2(fifo->hif,PH_DATA_E | INDICATION,fifo->skbuff);
- else fifo->hif->l1l2(fifo->hif,PH_DATA | INDICATION,fifo->skbuff);
-
- fifo->skbuff = NULL; // buffer was freed from upper layer
- }
- else
- {
- printk(KERN_INFO "HFC-USB: got frame %d bytes but CRC ERROR!!!\n",fifo->skbuff->len);
-
- skb_trim(fifo->skbuff,0); // clear whole buffer
+ /* we have a complete hdlc packet */
+ if (finish) {
+ if ((!fifo->skbuff->data[fifo->skbuff->len - 1])
+ && (fifo->skbuff->len > 3)) {
+ /* remove CRC & status */
+ skb_trim(fifo->skbuff, fifo->skbuff->len - 3);
+ if (fifon == HFCUSB_PCM_RX) {
+ fifo->hif->l1l2(fifo->hif,
+ PH_DATA_E | INDICATION,
+ fifo->skbuff);
+ } else
+ fifo->hif->l1l2(fifo->hif,
+ PH_DATA | INDICATION,
+ fifo->skbuff);
+ fifo->skbuff = NULL; /* buffer was freed from upper layer */
+ } else {
+ if (fifo->skbuff->len > 3) {
+ printk(KERN_INFO
+ "HFC-S USB: got frame %d bytes but CRC ERROR on fifo:%d!!!\n",
+ fifo->skbuff->len, fifon);
+#ifdef CONFIG_HISAX_DEBUG
+ if (debug > 1) {
+ printk(KERN_INFO "HFC-S USB: ");
+ for (i = 0; i < 15; i++)
+ printk("%.2x ",
+ fifo->skbuff->
+ data[fifo->skbuff->
+ len - 15 + i]);
+ printk("\n");
+ }
+#endif
+ }
+#ifdef CONFIG_HISAX_DEBUG
+ else {
+ printk(KERN_INFO
+ "HFC-S USB: frame to small (%d bytes)!!!\n",
+ fifo->skbuff->len);
+ }
+#endif
+ skb_trim(fifo->skbuff, 0);
}
}
- // LED flashing only in HDLC mode
- if(!transp_mode)
- {
- if(fifon==HFCUSB_B1_RX) handle_led(hfc,LED_B1_DATA);
- if(fifon==HFCUSB_B2_RX) handle_led(hfc,LED_B2_DATA);
+ /* LED flashing only in HDLC mode */
+ if (!transp_mode) {
+ if (fifon == HFCUSB_B1_RX)
+ handle_led(hfc, LED_B1_DATA);
+ if (fifon == HFCUSB_B2_RX)
+ handle_led(hfc, LED_B2_DATA);
}
}
/***********************************************/
/* receive completion routine for all rx fifos */
/***********************************************/
-static void rx_complete(struct urb *urb, struct pt_regs *regs)
+static void
+rx_complete(struct urb *urb, struct pt_regs *regs)
{
int len;
- __u8 *buf;
- usb_fifo *fifo = (usb_fifo *) urb->context; /* pointer to our fifo */
+ int status;
+ __u8 *buf, maxlen, fifon;
+ usb_fifo *fifo = (usb_fifo *) urb->context;
hfcusb_data *hfc = fifo->hfc;
+ static __u8 eof[8];
+#ifdef CONFIG_HISAX_DEBUG
+ __u8 i;
+#endif
urb->dev = hfc->dev; /* security init */
- if((!fifo->active) || (urb->status)) {
-#ifdef VERBOSE_USB_DEBUG
- printk(KERN_INFO "HFC-USB: RX-Fifo %i is going down (%i)\n", fifo->fifonum, urb->status);
+ fifon = fifo->fifonum;
+ if ((!fifo->active) || (urb->status)) {
+#ifdef CONFIG_HISAX_DEBUG
+ DBG(USB_DBG, "HFC-S USB: RX-Fifo %i is going down (%i)",
+ fifon, urb->status);
#endif
fifo->urb->interval = 0; /* cancel automatic rescheduling */
- if(fifo->skbuff) {
+ if (fifo->skbuff) {
dev_kfree_skb_any(fifo->skbuff);
fifo->skbuff = NULL;
}
return;
}
+ len = urb->actual_length;
+ buf = fifo->buffer;
+ maxlen = fifo->usb_packet_maxlen;
+
+#ifdef CONFIG_HISAX_DEBUG
+ if ((fifon == 5) && (debug > 1)) {
+ printk(KERN_INFO
+ "HFC-S USB: INT-D-RX lst_urblen:%2d act_urblen:%2d max-urblen:%2d EOF:0x%0x DATA: ",
+ fifo->last_urblen, len, maxlen, eof[5]);
+ for (i = 0; i < len; i++)
+ printk("%.2x ", buf[i]);
+ printk("\n");
+ }
+#endif
- len=urb->actual_length;
- buf=fifo->buffer;
-
- if(fifo->last_urblen!=fifo->usb_packet_maxlen) {
- // the threshold mask is in the 2nd status byte
- hfc->threshold_mask=buf[1];
- // the S0 state is in the upper half of the 1st status byte
- state_handler(hfc,buf[0] >> 4);
- // if we have more than the 2 status bytes -> collect data
- if(len>2) collect_rx_frame(fifo,buf+2,urb->actual_length-2,buf[0]&1);
- } else
- collect_rx_frame(fifo,buf,urb->actual_length,0);
-
- fifo->last_urblen=urb->actual_length;
-
-
-} /* rx_complete */
-
-
+ if (fifo->last_urblen != fifo->usb_packet_maxlen) {
+ /* the threshold mask is in the 2nd status byte */
+ hfc->threshold_mask = buf[1];
+ /* the S0 state is in the upper half of the 1st status byte */
+ state_handler(hfc, buf[0] >> 4);
+ eof[fifon] = buf[0] & 1;
+ /* if we have more than the 2 status bytes -> collect data */
+ if (len > 2)
+ collect_rx_frame(fifo, buf + 2,
+ urb->actual_length - 2,
+ (len < maxlen) ? eof[fifon] : 0);
+ } else {
+ collect_rx_frame(fifo, buf, urb->actual_length,
+ (len < maxlen) ? eof[fifon] : 0);
+ }
+ fifo->last_urblen = urb->actual_length;
+ status = usb_submit_urb(urb, GFP_ATOMIC);
+ if (status) {
+ printk(KERN_INFO
+ "HFC-S USB: error resubmitting URN at rx_complete...\n");
+ }
+} /* rx_complete */
/***************************************************/
/* start the interrupt transfer for the given fifo */
/***************************************************/
-static void start_int_fifo(usb_fifo * fifo)
+static void
+start_int_fifo(usb_fifo * fifo)
{
int errcode;
-#ifdef VERBOSE_USB_DEBUG
- printk(KERN_INFO "HFC-USB: starting intr IN fifo:%d\n", fifo->fifonum);
-#endif
+ printk(KERN_INFO "HFC-S USB: starting intr IN fifo:%d\n",
+ fifo->fifonum);
+
if (!fifo->urb) {
fifo->urb = usb_alloc_urb(0, GFP_KERNEL);
if (!fifo->urb)
return;
}
- usb_fill_int_urb(fifo->urb, fifo->hfc->dev, fifo->pipe, fifo->buffer,
- fifo->usb_packet_maxlen, rx_complete, fifo, fifo->intervall);
- fifo->active = 1; /* must be marked active */
+ usb_fill_int_urb(fifo->urb, fifo->hfc->dev, fifo->pipe,
+ fifo->buffer, fifo->usb_packet_maxlen,
+ rx_complete, fifo, fifo->intervall);
+ fifo->active = 1; /* must be marked active */
errcode = usb_submit_urb(fifo->urb, GFP_KERNEL);
-
- if(errcode)
- {
- printk(KERN_INFO "HFC-USB: submit URB error(start_int_info): status:%i\n", errcode);
+ if (errcode) {
+ printk(KERN_INFO
+ "HFC-S USB: submit URB error(start_int_info): status:%i\n",
+ errcode);
fifo->active = 0;
fifo->skbuff = NULL;
}
-} /* start_int_fifo */
+} /* start_int_fifo */
/*****************************/
/* set the B-channel mode */
/*****************************/
-static void set_hfcmode(hfcusb_data *hfc,int channel,int mode)
+static void
+set_hfcmode(hfcusb_data * hfc, int channel, int mode)
{
- __u8 val,idx_table[2]={0,2};
-
-#ifdef VERBOSE_ISDN_DEBUG
- printk (KERN_INFO "HFC-USB: setting channel %d to mode %d\n",channel,mode);
-#endif
-
- hfc->b_mode[channel]=mode;
-
- // setup CON_HDLC
- val=0;
- if(mode!=L1_MODE_NULL) val=8; // enable fifo?
- if(mode==L1_MODE_TRANS) val|=2; // set transparent bit
-
- queue_control_request(hfc,HFCUSB_FIFO,idx_table[channel],1); // set FIFO to transmit register
- queue_control_request(hfc,HFCUSB_CON_HDLC,val,1);
- queue_control_request(hfc,HFCUSB_INC_RES_F,2,1); // reset fifo
+ __u8 val, idx_table[2] = { 0, 2 };
- queue_control_request(hfc,HFCUSB_FIFO,idx_table[channel]+1,1); // set FIFO to receive register
- queue_control_request(hfc,HFCUSB_CON_HDLC,val,1);
- queue_control_request(hfc,HFCUSB_INC_RES_F,2,1); // reset fifo
-
- val=0x40;
- if(hfc->b_mode[0]) val|=1;
- if(hfc->b_mode[1]) val|=2;
- queue_control_request(hfc,HFCUSB_SCTRL,val,1);
-
- val=0;
- if(hfc->b_mode[0]) val|=1;
- if(hfc->b_mode[1]) val|=2;
- queue_control_request(hfc,HFCUSB_SCTRL_R,val,1);
-
- if(mode==L1_MODE_NULL)
- {
- if(channel) handle_led(hfc,LED_B2_OFF);
- else handle_led(hfc,LED_B1_OFF);
+ if (hfc->disc_flag) {
+ return;
}
- else
- {
- if(channel) handle_led(hfc,LED_B2_ON);
- else handle_led(hfc,LED_B1_ON);
+#ifdef CONFIG_HISAX_DEBUG
+ DBG(ISDN_DBG, "HFC-S USB: setting channel %d to mode %d", channel,
+ mode);
+#endif
+ hfc->b_mode[channel] = mode;
+
+ /* setup CON_HDLC */
+ val = 0;
+ if (mode != L1_MODE_NULL)
+ val = 8; /* enable fifo? */
+ if (mode == L1_MODE_TRANS)
+ val |= 2; /* set transparent bit */
+
+ /* set FIFO to transmit register */
+ queue_control_request(hfc, HFCUSB_FIFO, idx_table[channel], 1);
+ queue_control_request(hfc, HFCUSB_CON_HDLC, val, 1);
+ /* reset fifo */
+ queue_control_request(hfc, HFCUSB_INC_RES_F, 2, 1);
+ /* set FIFO to receive register */
+ queue_control_request(hfc, HFCUSB_FIFO, idx_table[channel] + 1, 1);
+ queue_control_request(hfc, HFCUSB_CON_HDLC, val, 1);
+ /* reset fifo */
+ queue_control_request(hfc, HFCUSB_INC_RES_F, 2, 1);
+
+ val = 0x40;
+ if (hfc->b_mode[0])
+ val |= 1;
+ if (hfc->b_mode[1])
+ val |= 2;
+ queue_control_request(hfc, HFCUSB_SCTRL, val, 1);
+
+ val = 0;
+ if (hfc->b_mode[0])
+ val |= 1;
+ if (hfc->b_mode[1])
+ val |= 2;
+ queue_control_request(hfc, HFCUSB_SCTRL_R, val, 1);
+
+ if (mode == L1_MODE_NULL) {
+ if (channel)
+ handle_led(hfc, LED_B2_OFF);
+ else
+ handle_led(hfc, LED_B1_OFF);
+ } else {
+ if (channel)
+ handle_led(hfc, LED_B2_ON);
+ else
+ handle_led(hfc, LED_B1_ON);
}
}
-/*
- --------------------------------------------------------------------------------------
- from here : hisax_if callback routines :
- - void hfc_usb_d_l2l1(struct hisax_if *hisax_d_if, int pr, void *arg) {
-
- l1 to l2 routines :
- - static void hfc_usb_l1l2(hfcusb_data * hfc)
-
-*/
-
-void hfc_usb_l2l1(struct hisax_if *my_hisax_if, int pr, void *arg)
+void
+hfc_usb_l2l1(struct hisax_if *my_hisax_if, int pr, void *arg)
{
- usb_fifo *fifo = my_hisax_if->priv;
+ usb_fifo *fifo = my_hisax_if->priv;
hfcusb_data *hfc = fifo->hfc;
- switch (pr) {
+ switch (pr) {
case PH_ACTIVATE | REQUEST:
- if(fifo->fifonum==HFCUSB_D_TX)
- {
-#ifdef VERBOSE_ISDN_DEBUG
- printk (KERN_INFO "HFC_USB: hfc_usb_d_l2l1 D-chan: PH_ACTIVATE | REQUEST\n");
+ if (fifo->fifonum == HFCUSB_D_TX) {
+#ifdef CONFIG_HISAX_DEBUG
+ DBG(ISDN_DBG,
+ "HFC_USB: hfc_usb_d_l2l1 D-chan: PH_ACTIVATE | REQUEST");
#endif
- queue_control_request(hfc, HFCUSB_STATES,0x60,1); /* make activation */
- hfc->t3_timer.expires = jiffies + (HFC_TIMER_T3 * HZ) / 1000;
- if(!timer_pending(&hfc->t3_timer)) add_timer(&hfc->t3_timer);
- }
- else
- {
-#ifdef VERBOSE_ISDN_DEBUG
- printk (KERN_INFO "HFC_USB: hfc_usb_d_l2l1 Bx-chan: PH_ACTIVATE | REQUEST\n");
+ if (hfc->l1_state != 3
+ && hfc->l1_state != 7) {
+ hfc->d_if.ifc.l1l2(&hfc->d_if.ifc,
+ PH_DEACTIVATE |
+ INDICATION,
+ NULL);
+#ifdef CONFIG_HISAX_DEBUG
+ DBG(ISDN_DBG,
+ "HFC-S USB: PH_DEACTIVATE | INDICATION sent (not state 3 or 7)");
#endif
- set_hfcmode(hfc,(fifo->fifonum==HFCUSB_B1_TX) ? 0 : 1 ,(int)arg);
- fifo->hif->l1l2(fifo->hif,PH_ACTIVATE | INDICATION, NULL);
- }
- break;
- case PH_DEACTIVATE | REQUEST:
- if(fifo->fifonum==HFCUSB_D_TX)
- {
-#ifdef VERBOSE_ISDN_DEBUG
- printk (KERN_INFO "HFC_USB: hfc_usb_d_l2l1 D-chan: PH_DEACTIVATE | REQUEST\n");
+ } else {
+ if (hfc->l1_state == 7) { /* l1 already active */
+ hfc->d_if.ifc.l1l2(&hfc->
+ d_if.
+ ifc,
+ PH_ACTIVATE
+ |
+ INDICATION,
+ NULL);
+#ifdef CONFIG_HISAX_DEBUG
+ DBG(ISDN_DBG,
+ "HFC-S USB: PH_ACTIVATE | INDICATION sent again ;)");
#endif
- printk (KERN_INFO "HFC-USB: ISDN TE device should not deativate...\n");
+ } else {
+ /* force sending sending INFO1 */
+ queue_control_request(hfc,
+ HFCUSB_STATES,
+ 0x14,
+ 1);
+ mdelay(1);
+ /* start l1 activation */
+ queue_control_request(hfc,
+ HFCUSB_STATES,
+ 0x04,
+ 1);
+ if (!timer_pending
+ (&hfc->t3_timer)) {
+ hfc->t3_timer.
+ expires =
+ jiffies +
+ (HFC_TIMER_T3 *
+ HZ) / 1000;
+ add_timer(&hfc->
+ t3_timer);
+ }
+ }
}
- else
- {
-#ifdef VERBOSE_ISDN_DEBUG
- printk (KERN_INFO "HFC_USB: hfc_usb_d_l2l1 Bx-chan: PH_DEACTIVATE | REQUEST\n");
+ } else {
+#ifdef CONFIG_HISAX_DEBUG
+ DBG(ISDN_DBG,
+ "HFC_USB: hfc_usb_d_l2l1 Bx-chan: PH_ACTIVATE | REQUEST");
#endif
- set_hfcmode(hfc,(fifo->fifonum==HFCUSB_B1_TX) ? 0 : 1 ,(int)L1_MODE_NULL);
- fifo->hif->l1l2(fifo->hif,PH_DEACTIVATE | INDICATION, NULL);
- }
- break;
+ set_hfcmode(hfc,
+ (fifo->fifonum ==
+ HFCUSB_B1_TX) ? 0 : 1,
+ (int) arg);
+ fifo->hif->l1l2(fifo->hif,
+ PH_ACTIVATE | INDICATION,
+ NULL);
+ }
+ break;
+ case PH_DEACTIVATE | REQUEST:
+ if (fifo->fifonum == HFCUSB_D_TX) {
+#ifdef CONFIG_HISAX_DEBUG
+ DBG(ISDN_DBG,
+ "HFC_USB: hfc_usb_d_l2l1 D-chan: PH_DEACTIVATE | REQUEST");
+#endif
+ printk(KERN_INFO
+ "HFC-S USB: ISDN TE device should not deativate...\n");
+ } else {
+#ifdef CONFIG_HISAX_DEBUG
+ DBG(ISDN_DBG,
+ "HFC_USB: hfc_usb_d_l2l1 Bx-chan: PH_DEACTIVATE | REQUEST");
+#endif
+ set_hfcmode(hfc,
+ (fifo->fifonum ==
+ HFCUSB_B1_TX) ? 0 : 1,
+ (int) L1_MODE_NULL);
+ fifo->hif->l1l2(fifo->hif,
+ PH_DEACTIVATE | INDICATION,
+ NULL);
+ }
+ break;
case PH_DATA | REQUEST:
- if(fifo->skbuff && fifo->delete_flg)
- {
- dev_kfree_skb_any(fifo->skbuff);
- //printk(KERN_INFO "skbuff=NULL on fifo:%d\n",fifo->fifonum);
- fifo->skbuff = NULL;
- fifo->delete_flg=FALSE;
- }
-
- fifo->skbuff=arg; // we have a new buffer
-
- //if(fifo->fifonum==HFCUSB_D_TX) printk (KERN_INFO "HFC_USB: hfc_usb_d_l2l1 D-chan: PH_DATA | REQUEST\n");
- //else printk (KERN_INFO "HFC_USB: hfc_usb_d_l2l1 Bx-chan: PH_DATA | REQUEST\n");
- break;
- default:
- printk (KERN_INFO "HFC_USB: hfc_usb_d_l2l1: unkown state : %#x\n", pr);
- break;
- }
+ if (fifo->skbuff && fifo->delete_flg) {
+ dev_kfree_skb_any(fifo->skbuff);
+ fifo->skbuff = NULL;
+ fifo->delete_flg = FALSE;
+ }
+ fifo->skbuff = arg; /* we have a new buffer */
+ break;
+ default:
+ printk(KERN_INFO
+ "HFC_USB: hfc_usb_d_l2l1: unkown state : %#x\n",
+ pr);
+ break;
+ }
}
-// valid configurations
-#define CNF_4INT3ISO 1 // 4 INT IN, 3 ISO OUT
-#define CNF_3INT3ISO 2 // 3 INT IN, 3 ISO OUT
-#define CNF_4ISO3ISO 3 // 4 ISO IN, 3 ISO OUT
-#define CNF_3ISO3ISO 4 // 3 ISO IN, 3 ISO OUT
-
-
-/*
- --------------------------------------------------------------------------------------
- From here on USB initialization and deactivation related routines are implemented :
-
- - hfc_usb_init :
- is the main Entry Point for the USB Subsystem when the device get plugged
- in. This function calls usb_register with usb_driver as parameter.
- Here, further entry points for probing (hfc_usb_probe) and disconnecting
- the device (hfc_usb_disconnect) are published, as the id_table
-
- - hfc_usb_probe
- this function is called by the usb subsystem, and steps through the alternate
- settings of the currently plugged in device to detect all Endpoints needed to
- run an ISDN TA.
- Needed EndPoints are
- 3 (+1) IntIn EndPoints (D-in, E-in, B1-in, B2-in, (E-in)) or
- 3 (+1) Isochron In Endpoints (D-out, B1-out, B2-out) and 3 IsoOut Endpoints
- The currently used transfer mode of on the Out-Endpoints will be stored in
- hfc->usb_transfer_mode and is either USB_INT or USB_ISO
- When a valid alternate setting could be found, the usb_init (see blow)
- function is called
-
- - usb_init
- Here, the HFC_USB Chip itself gets initialized and the USB framework to send/receive
- Data to/from the several EndPoints are initialized:
- The E- and D-Channel Int-In chain gets started
- The IsoChain for the Iso-Out traffic get started
-
- - hfc_usb_disconnect
- this function is called by the usb subsystem and has to free all resources
- and stop all usb traffic to allow a proper hotplugging disconnect.
-
-*/
-
/***************************************************************************/
/* usb_init is called once when a new matching device is detected to setup */
-/* main parameters. It registers the driver at the main hisax module. */
+/* main parameters. It registers the driver at the main hisax module. */
/* on success 0 is returned. */
/***************************************************************************/
-static int usb_init(hfcusb_data * hfc)
+static int
+usb_init(hfcusb_data * hfc)
{
usb_fifo *fifo;
int i, err;
u_char b;
struct hisax_b_if *p_b_if[2];
-
+
/* check the chip id */
- printk(KERN_INFO "HFCUSB_CHIP_ID begin\n");
if (read_usb(hfc, HFCUSB_CHIP_ID, &b) != 1) {
printk(KERN_INFO "HFC-USB: cannot read chip id\n");
- return(1);
+ return (1);
}
- printk(KERN_INFO "HFCUSB_CHIP_ID %x\n", b);
if (b != HFCUSB_CHIPID) {
- printk(KERN_INFO "HFC-USB: Invalid chip id 0x%02x\n", b);
- return(1);
+ printk(KERN_INFO "HFC-S USB: Invalid chip id 0x%02x\n", b);
+ return (1);
}
/* first set the needed config, interface and alternate */
- printk(KERN_INFO "usb_init 1\n");
-// usb_set_configuration(hfc->dev, 1);
- printk(KERN_INFO "usb_init 2\n");
err = usb_set_interface(hfc->dev, hfc->if_used, hfc->alt_used);
- printk(KERN_INFO "usb_init usb_set_interface return %d\n", err);
- /* now we initialize the chip */
- write_usb(hfc, HFCUSB_CIRM, 8); // do reset
- write_usb(hfc, HFCUSB_CIRM, 0x10); // aux = output, reset off
- // set USB_SIZE to match the the wMaxPacketSize for INT or BULK transfers
- write_usb(hfc, HFCUSB_USB_SIZE,(hfc->packet_size/8) | ((hfc->packet_size/8) << 4));
+ /* do Chip reset */
+ write_usb(hfc, HFCUSB_CIRM, 8);
+ /* aux = output, reset off */
+ write_usb(hfc, HFCUSB_CIRM, 0x10);
- // set USB_SIZE_I to match the the wMaxPacketSize for ISO transfers
+ /* set USB_SIZE to match the the wMaxPacketSize for INT or BULK transfers */
+ write_usb(hfc, HFCUSB_USB_SIZE,
+ (hfc->packet_size / 8) | ((hfc->packet_size / 8) << 4));
+
+ /* set USB_SIZE_I to match the the wMaxPacketSize for ISO transfers */
write_usb(hfc, HFCUSB_USB_SIZE_I, hfc->iso_packet_size);
/* enable PCM/GCI master mode */
@@ -1184,412 +1292,447 @@ static int usb_init(hfcusb_data * hfc)
write_usb(hfc, HFCUSB_MST_MODE0, 1); /* enable master mode */
/* init the fifos */
- write_usb(hfc, HFCUSB_F_THRES, (HFCUSB_TX_THRESHOLD/8) |((HFCUSB_RX_THRESHOLD/8) << 4));
+ write_usb(hfc, HFCUSB_F_THRES,
+ (HFCUSB_TX_THRESHOLD /
+ 8) | ((HFCUSB_RX_THRESHOLD / 8) << 4));
fifo = hfc->fifos;
- for(i = 0; i < HFCUSB_NUM_FIFOS; i++)
- {
+ for (i = 0; i < HFCUSB_NUM_FIFOS; i++) {
write_usb(hfc, HFCUSB_FIFO, i); /* select the desired fifo */
fifo[i].skbuff = NULL; /* init buffer pointer */
- fifo[i].max_size = (i <= HFCUSB_B2_RX) ? MAX_BCH_SIZE : MAX_DFRAME_LEN;
- fifo[i].last_urblen=0;
- write_usb(hfc, HFCUSB_HDLC_PAR, ((i <= HFCUSB_B2_RX) ? 0 : 2)); // set 2 bit for D- & E-channel
- write_usb(hfc, HFCUSB_CON_HDLC, ((i==HFCUSB_D_TX) ? 0x09 : 0x08)); // rx hdlc, enable IFF for D-channel
+ fifo[i].max_size =
+ (i <= HFCUSB_B2_RX) ? MAX_BCH_SIZE : MAX_DFRAME_LEN;
+ fifo[i].last_urblen = 0;
+ /* set 2 bit for D- & E-channel */
+ write_usb(hfc, HFCUSB_HDLC_PAR,
+ ((i <= HFCUSB_B2_RX) ? 0 : 2));
+ /* rx hdlc, enable IFF for D-channel */
+ write_usb(hfc, HFCUSB_CON_HDLC,
+ ((i == HFCUSB_D_TX) ? 0x09 : 0x08));
write_usb(hfc, HFCUSB_INC_RES_F, 2); /* reset the fifo */
}
- write_usb(hfc, HFCUSB_CLKDEL, 0x0f); /* clock delay value */
- write_usb(hfc, HFCUSB_STATES, 3 | 0x10); /* set deactivated mode */
- write_usb(hfc, HFCUSB_STATES, 3); /* enable state machine */
+ write_usb(hfc, HFCUSB_CLKDEL, 0x0f); /* clock delay value */
+ write_usb(hfc, HFCUSB_STATES, 3 | 0x10); /* set deactivated mode */
+ write_usb(hfc, HFCUSB_STATES, 3); /* enable state machine */
- write_usb(hfc, HFCUSB_SCTRL_R, 0); /* disable both B receivers */
- write_usb(hfc, HFCUSB_SCTRL, 0x40); /* disable B transmitters + capacitive mode */
+ write_usb(hfc, HFCUSB_SCTRL_R, 0); /* disable both B receivers */
+ write_usb(hfc, HFCUSB_SCTRL, 0x40); /* disable B transmitters + capacitive mode */
- // set both B-channel to not connected
- hfc->b_mode[0]=L1_MODE_NULL;
- hfc->b_mode[1]=L1_MODE_NULL;
+ /* set both B-channel to not connected */
+ hfc->b_mode[0] = L1_MODE_NULL;
+ hfc->b_mode[1] = L1_MODE_NULL;
- hfc->l1_activated=FALSE;
- hfc->led_state=0;
- hfc->led_new_data=0;
+ hfc->l1_activated = FALSE;
+ hfc->disc_flag = FALSE;
+ hfc->led_state = 0;
+ hfc->led_new_data = 0;
+ hfc->old_led_state = 0;
/* init the t3 timer */
init_timer(&hfc->t3_timer);
hfc->t3_timer.data = (long) hfc;
hfc->t3_timer.function = (void *) l1_timer_expire_t3;
+
/* init the t4 timer */
init_timer(&hfc->t4_timer);
hfc->t4_timer.data = (long) hfc;
hfc->t4_timer.function = (void *) l1_timer_expire_t4;
+
/* init the led timer */
init_timer(&hfc->led_timer);
hfc->led_timer.data = (long) hfc;
hfc->led_timer.function = (void *) led_timer;
- // trigger 4 hz led timer
- hfc->led_timer.expires = jiffies + (LED_TIME * HZ) / 1000;
- if(!timer_pending(&hfc->led_timer)) add_timer(&hfc->led_timer);
- // init the background machinery for control requests
+ /* trigger 4 hz led timer */
+ if (!timer_pending(&hfc->led_timer)) {
+ hfc->led_timer.expires = jiffies + (LED_TIME * HZ) / 1000;
+ add_timer(&hfc->led_timer);
+ }
+
+ /* init the background machinery for control requests */
hfc->ctrl_read.bRequestType = 0xc0;
hfc->ctrl_read.bRequest = 1;
hfc->ctrl_read.wLength = 1;
hfc->ctrl_write.bRequestType = 0x40;
hfc->ctrl_write.bRequest = 0;
hfc->ctrl_write.wLength = 0;
- usb_fill_control_urb(hfc->ctrl_urb, hfc->dev, hfc->ctrl_out_pipe,(u_char *) & hfc->ctrl_write, NULL, 0, ctrl_complete, hfc);
-
+ usb_fill_control_urb(hfc->ctrl_urb,
+ hfc->dev,
+ hfc->ctrl_out_pipe,
+ (u_char *) & hfc->ctrl_write,
+ NULL, 0, ctrl_complete, hfc);
/* Init All Fifos */
- for(i = 0; i < HFCUSB_NUM_FIFOS; i++)
- {
+ for (i = 0; i < HFCUSB_NUM_FIFOS; i++) {
hfc->fifos[i].iso[0].purb = NULL;
hfc->fifos[i].iso[1].purb = NULL;
hfc->fifos[i].active = 0;
}
-
- // register like Germaschewski :
+ /* register Modul to upper Hisax Layers */
hfc->d_if.owner = THIS_MODULE;
hfc->d_if.ifc.priv = &hfc->fifos[HFCUSB_D_TX];
hfc->d_if.ifc.l2l1 = hfc_usb_l2l1;
-
- for (i=0; i<2; i++)
- {
- hfc->b_if[i].ifc.priv = &hfc->fifos[HFCUSB_B1_TX+i*2];
+ for (i = 0; i < 2; i++) {
+ hfc->b_if[i].ifc.priv = &hfc->fifos[HFCUSB_B1_TX + i * 2];
hfc->b_if[i].ifc.l2l1 = hfc_usb_l2l1;
p_b_if[i] = &hfc->b_if[i];
}
-
- hfc->protocol = 2; /* default EURO ISDN, should be a module_param */
+ /* default Prot: EURO ISDN, should be a module_param */
+ hfc->protocol = 2;
hisax_register(&hfc->d_if, p_b_if, "hfc_usb", hfc->protocol);
-
- for (i=0; i<4; i++)
- hfc->fifos[i].hif=&p_b_if[i/2]->ifc;
- for (i=4; i<8; i++)
- hfc->fifos[i].hif=&hfc->d_if.ifc;
-
- // 3 (+1) INT IN + 3 ISO OUT
- if(hfc->cfg_used == CNF_3INT3ISO || hfc->cfg_used == CNF_4INT3ISO)
- {
- start_int_fifo(hfc->fifos + HFCUSB_D_RX); // Int IN D-fifo
- if(hfc->fifos[HFCUSB_PCM_RX].pipe) start_int_fifo(hfc->fifos + HFCUSB_PCM_RX); // E-fifo
- start_int_fifo(hfc->fifos + HFCUSB_B1_RX); // Int IN B1-fifo
- start_int_fifo(hfc->fifos + HFCUSB_B2_RX); // Int IN B2-fifo
- }
-
- // 3 (+1) ISO IN + 3 ISO OUT
- if(hfc->cfg_used==CNF_3ISO3ISO || hfc->cfg_used==CNF_4ISO3ISO)
- {
- start_isoc_chain(hfc->fifos + HFCUSB_D_RX, ISOC_PACKETS_D, rx_iso_complete,16);
- if(hfc->fifos[HFCUSB_PCM_RX].pipe) start_isoc_chain(hfc->fifos + HFCUSB_PCM_RX, ISOC_PACKETS_D, rx_iso_complete,16);
- start_isoc_chain(hfc->fifos + HFCUSB_B1_RX, ISOC_PACKETS_B, rx_iso_complete,16);
- start_isoc_chain(hfc->fifos + HFCUSB_B2_RX, ISOC_PACKETS_B, rx_iso_complete,16);
- }
-
- start_isoc_chain(hfc->fifos + HFCUSB_D_TX, ISOC_PACKETS_D, tx_iso_complete,1);
- start_isoc_chain(hfc->fifos + HFCUSB_B1_TX, ISOC_PACKETS_B, tx_iso_complete,1);
- start_isoc_chain(hfc->fifos + HFCUSB_B2_TX, ISOC_PACKETS_B, tx_iso_complete,1);
-
- handle_led(hfc,LED_POWER_ON);
-
- return(0);
-} /* usb_init */
-
-
-/****************************************/
-/* data defining the devices to be used */
-/****************************************/
-// static __devinitdata const struct usb_device_id hfc_usb_idtab[3] = {
-static struct usb_device_id hfc_usb_idtab[] = {
- {USB_DEVICE(0x7b0, 0x0007)}, /* Billion USB TA 2 */
- {USB_DEVICE(0x742, 0x2008)}, /* Stollmann USB TA */
- {USB_DEVICE(0x959, 0x2bd0)}, /* Colognechip USB eval TA */
- {USB_DEVICE(0x8e3, 0x0301)}, /* OliTec ISDN USB */
- {USB_DEVICE(0x675, 0x1688)}, /* DrayTec ISDN USB */
- {USB_DEVICE(0x7fa, 0x0846)}, /* Bewan ISDN USB TA */
- {} /* end with an all-zeroes entry */
-};
-MODULE_AUTHOR("Peter Sprenger (sprenger@moving-byters.de)/Martin Bachem (info@colognechip.com)");
-MODULE_DESCRIPTION("HFC I4L USB driver");
-MODULE_DEVICE_TABLE(usb, hfc_usb_idtab);
-MODULE_LICENSE("GPL");
+#ifdef CONFIG_HISAX_DEBUG
+ hfc_debug = debug;
+#endif
-#define EP_NUL 1 // Endpoint at this position not allowed
-#define EP_NOP 2 // all type of endpoints allowed at this position
-#define EP_ISO 3 // Isochron endpoint mandatory at this position
-#define EP_BLK 4 // Bulk endpoint mandatory at this position
-#define EP_INT 5 // Interrupt endpoint mandatory at this position
+ for (i = 0; i < 4; i++)
+ hfc->fifos[i].hif = &p_b_if[i / 2]->ifc;
+ for (i = 4; i < 8; i++)
+ hfc->fifos[i].hif = &hfc->d_if.ifc;
+
+ /* 3 (+1) INT IN + 3 ISO OUT */
+ if (hfc->cfg_used == CNF_3INT3ISO || hfc->cfg_used == CNF_4INT3ISO) {
+ start_int_fifo(hfc->fifos + HFCUSB_D_RX);
+ if (hfc->fifos[HFCUSB_PCM_RX].pipe)
+ start_int_fifo(hfc->fifos + HFCUSB_PCM_RX);
+ start_int_fifo(hfc->fifos + HFCUSB_B1_RX);
+ start_int_fifo(hfc->fifos + HFCUSB_B2_RX);
+ }
+ /* 3 (+1) ISO IN + 3 ISO OUT */
+ if (hfc->cfg_used == CNF_3ISO3ISO || hfc->cfg_used == CNF_4ISO3ISO) {
+ start_isoc_chain(hfc->fifos + HFCUSB_D_RX, ISOC_PACKETS_D,
+ rx_iso_complete, 16);
+ if (hfc->fifos[HFCUSB_PCM_RX].pipe)
+ start_isoc_chain(hfc->fifos + HFCUSB_PCM_RX,
+ ISOC_PACKETS_D, rx_iso_complete,
+ 16);
+ start_isoc_chain(hfc->fifos + HFCUSB_B1_RX, ISOC_PACKETS_B,
+ rx_iso_complete, 16);
+ start_isoc_chain(hfc->fifos + HFCUSB_B2_RX, ISOC_PACKETS_B,
+ rx_iso_complete, 16);
+ }
-// this array represents all endpoints possible in the HCF-USB
-// the last 2 entries are the configuration number and the minimum interval for Interrupt endpoints
-int validconf[][18]=
-{
- // INT in, ISO out config
- {EP_NUL,EP_INT,EP_NUL,EP_INT,EP_NUL,EP_INT,EP_NOP,EP_INT,EP_ISO,EP_NUL,EP_ISO,EP_NUL,EP_ISO,EP_NUL,EP_NUL,EP_NUL,CNF_4INT3ISO,2},
- {EP_NUL,EP_INT,EP_NUL,EP_INT,EP_NUL,EP_INT,EP_NUL,EP_NUL,EP_ISO,EP_NUL,EP_ISO,EP_NUL,EP_ISO,EP_NUL,EP_NUL,EP_NUL,CNF_3INT3ISO,2},
- // ISO in, ISO out config
- {EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_ISO,EP_ISO,EP_ISO,EP_ISO,EP_ISO,EP_ISO,EP_NOP,EP_ISO,CNF_4ISO3ISO,2},
- {EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_ISO,EP_ISO,EP_ISO,EP_ISO,EP_ISO,EP_ISO,EP_NUL,EP_NUL,CNF_3ISO3ISO,2},
- {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} // EOL element
-};
+ start_isoc_chain(hfc->fifos + HFCUSB_D_TX, ISOC_PACKETS_D,
+ tx_iso_complete, 1);
+ start_isoc_chain(hfc->fifos + HFCUSB_B1_TX, ISOC_PACKETS_B,
+ tx_iso_complete, 1);
+ start_isoc_chain(hfc->fifos + HFCUSB_B2_TX, ISOC_PACKETS_B,
+ tx_iso_complete, 1);
-// string description of chosen config
-char *conf_str[]=
-{
- "4 Interrupt IN + 3 Isochron OUT",
- "3 Interrupt IN + 3 Isochron OUT",
- "4 Isochron IN + 3 Isochron OUT",
- "3 Isochron IN + 3 Isochron OUT"
-};
+ handle_led(hfc, LED_POWER_ON);
+ return (0);
+} /* usb_init */
/*************************************************/
/* function called to probe a new plugged device */
/*************************************************/
-static int hfc_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
+static int
+hfc_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
- struct usb_device *dev= interface_to_usbdev(intf);
+ struct usb_device *dev = interface_to_usbdev(intf);
hfcusb_data *context;
struct usb_host_interface *iface = intf->cur_altsetting;
struct usb_host_interface *iface_used = NULL;
struct usb_host_endpoint *ep;
int ifnum = iface->desc.bInterfaceNumber;
- int i, idx, alt_idx, probe_alt_setting, vend_idx, cfg_used, *vcf, attr, cfg_found, cidx, ep_addr;
- int cmptbl[16],small_match,iso_packet_size,packet_size,alt_used=0;
-
-// usb_show_device(dev);
-// usb_show_device_descriptor(&dev->descriptor);
-// usb_show_interface_descriptor(&iface->desc);
- vend_idx=0xffff;
- for(i=0;vdata[i].vendor;i++) {
- if (le16_to_cpu(dev->descriptor.idVendor) == vdata[i].vendor &&
- le16_to_cpu(dev->descriptor.idProduct) == vdata[i].prod_id)
+ int i, idx, alt_idx, probe_alt_setting, vend_idx, cfg_used, *vcf,
+ attr, cfg_found, cidx, ep_addr;
+ int cmptbl[16], small_match, iso_packet_size, packet_size,
+ alt_used = 0;
+
+ vend_idx = 0xffff;
+ for (i = 0; vdata[i].vendor; i++) {
+ if (dev->descriptor.idVendor == vdata[i].vendor
+ && dev->descriptor.idProduct == vdata[i].prod_id)
vend_idx = i;
}
-
-
-#ifdef VERBOSE_USB_DEBUG
- printk(KERN_INFO "HFC-USB: probing interface(%d) actalt(%d) minor(%d)\n",
- ifnum, iface->desc.bAlternateSetting, intf->minor);
+#ifdef CONFIG_HISAX_DEBUG
+ DBG(USB_DBG,
+ "HFC-USB: probing interface(%d) actalt(%d) minor(%d)\n", ifnum,
+ iface->desc.bAlternateSetting, intf->minor);
#endif
+ printk(KERN_INFO
+ "HFC-S USB: probing interface(%d) actalt(%d) minor(%d)\n",
+ ifnum, iface->desc.bAlternateSetting, intf->minor);
if (vend_idx != 0xffff) {
-#ifdef VERBOSE_USB_DEBUG
- printk(KERN_INFO "HFC-USB: found vendor idx:%d name:%s\n",vend_idx,vdata[vend_idx].vend_name);
+#ifdef CONFIG_HISAX_DEBUG
+ DBG(USB_DBG, "HFC-S USB: found vendor idx:%d name:%s",
+ vend_idx, vdata[vend_idx].vend_name);
#endif
- /* if vendor and product ID is OK, start probing a matching alternate setting ... */
+ /* if vendor and product ID is OK, start probing alternate settings */
alt_idx = 0;
- small_match=0xffff;
- // default settings
- iso_packet_size=16;
- packet_size=64;
+ small_match = 0xffff;
+
+ /* default settings */
+ iso_packet_size = 16;
+ packet_size = 64;
while (alt_idx < intf->num_altsetting) {
iface = intf->altsetting + alt_idx;
probe_alt_setting = iface->desc.bAlternateSetting;
- cfg_used=0;
+ cfg_used = 0;
-#ifdef VERBOSE_USB_DEBUG
- printk(KERN_INFO "HFC-USB: test alt_setting %d\n", probe_alt_setting);
-#endif
- // check for config EOL element
+ /* check for config EOL element */
while (validconf[cfg_used][0]) {
- cfg_found=TRUE;
- vcf=validconf[cfg_used];
- ep = iface->endpoint; /* first endpoint descriptor */
-
-#ifdef VERBOSE_USB_DEBUG
- printk(KERN_INFO "HFC-USB: (if=%d alt=%d cfg_used=%d)\n",
- ifnum, probe_alt_setting, cfg_used);
+ cfg_found = TRUE;
+ vcf = validconf[cfg_used];
+ /* first endpoint descriptor */
+ ep = iface->endpoint;
+#ifdef CONFIG_HISAX_DEBUG
+ DBG(USB_DBG,
+ "HFC-S USB: (if=%d alt=%d cfg_used=%d)\n",
+ ifnum, probe_alt_setting, cfg_used);
#endif
- // copy table
- memcpy(cmptbl,vcf,16*sizeof(int));
-
- // check for all endpoints in this alternate setting
- for (i=0; i < iface->desc.bNumEndpoints; i++) {
- ep_addr = ep->desc.bEndpointAddress;
- idx = ((ep_addr & 0x7f)-1)*2; /* get endpoint base */
+ memcpy(cmptbl, vcf, 16 * sizeof(int));
+
+ /* check for all endpoints in this alternate setting */
+ for (i = 0; i < iface->desc.bNumEndpoints;
+ i++) {
+ ep_addr =
+ ep->desc.bEndpointAddress;
+ /* get endpoint base */
+ idx = ((ep_addr & 0x7f) - 1) * 2;
if (ep_addr & 0x80)
idx++;
attr = ep->desc.bmAttributes;
-
if (cmptbl[idx] == EP_NUL) {
- printk(KERN_INFO "HFC-USB: cfg_found=FALSE in idx:%d attr:%d cmptbl[%d]:%d\n",
- idx, attr, idx, cmptbl[idx]);
cfg_found = FALSE;
}
-
- if (attr == USB_ENDPOINT_XFER_INT && cmptbl[idx] == EP_INT)
+ if (attr == USB_ENDPOINT_XFER_INT
+ && cmptbl[idx] == EP_INT)
cmptbl[idx] = EP_NUL;
- if (attr == USB_ENDPOINT_XFER_BULK && cmptbl[idx] == EP_BLK)
+ if (attr == USB_ENDPOINT_XFER_BULK
+ && cmptbl[idx] == EP_BLK)
cmptbl[idx] = EP_NUL;
- if (attr == USB_ENDPOINT_XFER_ISOC && cmptbl[idx] == EP_ISO)
+ if (attr == USB_ENDPOINT_XFER_ISOC
+ && cmptbl[idx] == EP_ISO)
cmptbl[idx] = EP_NUL;
- // check if all INT endpoints match minimum interval
- if (attr == USB_ENDPOINT_XFER_INT && ep->desc.bInterval < vcf[17]) {
-#ifdef VERBOSE_USB_DEBUG
+ /* check if all INT endpoints match minimum interval */
+ if (attr == USB_ENDPOINT_XFER_INT
+ && ep->desc.bInterval <
+ vcf[17]) {
+#ifdef CONFIG_HISAX_DEBUG
if (cfg_found)
- printk(KERN_INFO "HFC-USB: Interrupt Endpoint interval < %d found - skipping config\n",
- vcf[17]);
+ DBG(USB_DBG,
+ "HFC-S USB: Interrupt Endpoint interval < %d found - skipping config",
+ vcf[17]);
#endif
cfg_found = FALSE;
}
-
ep++;
}
-
for (i = 0; i < 16; i++) {
- // printk(KERN_INFO "HFC-USB: cmptbl[%d]:%d\n", i, cmptbl[i]);
-
- // all entries must be EP_NOP or EP_NUL for a valid config
- if (cmptbl[i] != EP_NOP && cmptbl[i] != EP_NUL)
+ /* all entries must be EP_NOP or EP_NUL for a valid config */
+ if (cmptbl[i] != EP_NOP
+ && cmptbl[i] != EP_NUL)
cfg_found = FALSE;
}
-
- // we check for smallest match, to provide configuration priority
- // configurations with smaller index have higher priority
if (cfg_found) {
if (cfg_used < small_match) {
small_match = cfg_used;
- alt_used = probe_alt_setting;
+ alt_used =
+ probe_alt_setting;
iface_used = iface;
}
-#ifdef VERBOSE_USB_DEBUG
- printk(KERN_INFO "HFC-USB: small_match=%x %x\n", small_match, alt_used);
+#ifdef CONFIG_HISAX_DEBUG
+ DBG(USB_DBG,
+ "HFC-USB: small_match=%x %x\n",
+ small_match, alt_used);
#endif
}
-
cfg_used++;
}
-
alt_idx++;
} /* (alt_idx < intf->num_altsetting) */
-#ifdef VERBOSE_USB_DEBUG
- printk(KERN_INFO "HFC-USB: final small_match=%x alt_used=%x\n",small_match, alt_used);
-#endif
- // yiipiee, we found a valid config
+
+ /* found a valid USB Ta Endpint config */
if (small_match != 0xffff) {
iface = iface_used;
+ if (!
+ (context =
+ kmalloc(sizeof(hfcusb_data), GFP_KERNEL)))
+ return (-ENOMEM); /* got no mem */
+ memset(context, 0, sizeof(hfcusb_data));
- if (!(context = kmalloc(sizeof(hfcusb_data), GFP_KERNEL)))
- return(-ENOMEM); /* got no mem */
- memset(context, 0, sizeof(hfcusb_data)); /* clear the structure */
-
- ep = iface->endpoint; /* first endpoint descriptor */
+ ep = iface->endpoint;
vcf = validconf[small_match];
for (i = 0; i < iface->desc.bNumEndpoints; i++) {
ep_addr = ep->desc.bEndpointAddress;
- idx = ((ep_addr & 0x7f)-1)*2; /* get endpoint base */
+ /* get endpoint base */
+ idx = ((ep_addr & 0x7f) - 1) * 2;
if (ep_addr & 0x80)
idx++;
cidx = idx & 7;
attr = ep->desc.bmAttributes;
- // only initialize used endpoints
- if (vcf[idx] != EP_NOP && vcf[idx] != EP_NUL) {
+ /* init Endpoints */
+ if (vcf[idx] != EP_NOP
+ && vcf[idx] != EP_NUL) {
switch (attr) {
case USB_ENDPOINT_XFER_INT:
- context->fifos[cidx].pipe = usb_rcvintpipe(dev, ep->desc.bEndpointAddress);
- context->fifos[cidx].usb_transfer_mode = USB_INT;
- packet_size = le16_to_cpu(ep->desc.wMaxPacketSize); // remember max packet size
-#ifdef VERBOSE_USB_DEBUG
- printk (KERN_INFO "HFC-USB: Interrupt-In Endpoint found %d ms(idx:%d cidx:%d)!\n",
- ep->desc.bInterval, idx, cidx);
-#endif
+ context->
+ fifos[cidx].
+ pipe =
+ usb_rcvintpipe
+ (dev,
+ ep->desc.
+ bEndpointAddress);
+ context->
+ fifos[cidx].
+ usb_transfer_mode
+ = USB_INT;
+ packet_size =
+ ep->desc.
+ wMaxPacketSize;
break;
case USB_ENDPOINT_XFER_BULK:
if (ep_addr & 0x80)
- context->fifos[cidx].pipe = usb_rcvbulkpipe(dev, ep->desc.bEndpointAddress);
+ context->
+ fifos
+ [cidx].
+ pipe =
+ usb_rcvbulkpipe
+ (dev,
+ ep->
+ desc.
+ bEndpointAddress);
else
- context->fifos[cidx].pipe = usb_sndbulkpipe(dev, ep->desc.bEndpointAddress);
- context->fifos[cidx].usb_transfer_mode = USB_BULK;
- packet_size = le16_to_cpu(ep->desc.wMaxPacketSize); // remember max packet size
-#ifdef VERBOSE_USB_DEBUG
- printk (KERN_INFO "HFC-USB: Bulk Endpoint found (idx:%d cidx:%d)!\n",
- idx, cidx);
-#endif
+ context->
+ fifos
+ [cidx].
+ pipe =
+ usb_sndbulkpipe
+ (dev,
+ ep->
+ desc.
+ bEndpointAddress);
+ context->
+ fifos[cidx].
+ usb_transfer_mode
+ = USB_BULK;
+ packet_size =
+ ep->desc.
+ wMaxPacketSize;
break;
case USB_ENDPOINT_XFER_ISOC:
if (ep_addr & 0x80)
- context->fifos[cidx].pipe = usb_rcvisocpipe(dev, ep->desc.bEndpointAddress);
+ context->
+ fifos
+ [cidx].
+ pipe =
+ usb_rcvisocpipe
+ (dev,
+ ep->
+ desc.
+ bEndpointAddress);
else
- context->fifos[cidx].pipe = usb_sndisocpipe(dev, ep->desc.bEndpointAddress);
- context->fifos[cidx].usb_transfer_mode = USB_ISOC;
- iso_packet_size = le16_to_cpu(ep->desc.wMaxPacketSize); // remember max packet size
-#ifdef VERBOSE_USB_DEBUG
- printk (KERN_INFO "HFC-USB: ISO Endpoint found (idx:%d cidx:%d)!\n",
- idx, cidx);
-#endif
+ context->
+ fifos
+ [cidx].
+ pipe =
+ usb_sndisocpipe
+ (dev,
+ ep->
+ desc.
+ bEndpointAddress);
+ context->
+ fifos[cidx].
+ usb_transfer_mode
+ = USB_ISOC;
+ iso_packet_size =
+ ep->desc.
+ wMaxPacketSize;
break;
default:
- context->fifos[cidx].pipe = 0; /* reset data */
+ context->
+ fifos[cidx].
+ pipe = 0;
} /* switch attribute */
if (context->fifos[cidx].pipe) {
- context->fifos[cidx].fifonum = cidx;
- context->fifos[cidx].hfc = context;
- context->fifos[cidx].usb_packet_maxlen = le16_to_cpu(ep->desc.wMaxPacketSize);
- context->fifos[cidx].intervall = ep->desc.bInterval;
- context->fifos[cidx].skbuff = NULL;
-#ifdef VERBOSE_USB_DEBUG
- printk (KERN_INFO "HFC-USB: fifo%d pktlen %d interval %d\n",
- context->fifos[cidx].fifonum,
- context->fifos[cidx].usb_packet_maxlen,
- context->fifos[cidx].intervall);
-#endif
+ context->fifos[cidx].
+ fifonum = cidx;
+ context->fifos[cidx].hfc =
+ context;
+ context->fifos[cidx].
+ usb_packet_maxlen =
+ ep->desc.
+ wMaxPacketSize;
+ context->fifos[cidx].
+ intervall =
+ ep->desc.bInterval;
+ context->fifos[cidx].
+ skbuff = NULL;
}
}
-
ep++;
}
-
- // now share our luck
- context->dev = dev; /* save device */
- context->if_used = ifnum; /* save used interface */
- context->alt_used = alt_used; /* and alternate config */
+ context->dev = dev; /* save device */
+ context->if_used = ifnum; /* save used interface */
+ context->alt_used = alt_used; /* and alternate config */
context->ctrl_paksize = dev->descriptor.bMaxPacketSize0; /* control size */
- context->cfg_used=vcf[16]; // store used config
- context->vend_idx=vend_idx; // store found vendor
- context->packet_size=packet_size;
- context->iso_packet_size=iso_packet_size;
+ context->cfg_used = vcf[16]; /* store used config */
+ context->vend_idx = vend_idx; /* store found vendor */
+ context->packet_size = packet_size;
+ context->iso_packet_size = iso_packet_size;
/* create the control pipes needed for register access */
- context->ctrl_in_pipe = usb_rcvctrlpipe(context->dev, 0);
- context->ctrl_out_pipe = usb_sndctrlpipe(context->dev, 0);
+ context->ctrl_in_pipe =
+ usb_rcvctrlpipe(context->dev, 0);
+ context->ctrl_out_pipe =
+ usb_sndctrlpipe(context->dev, 0);
context->ctrl_urb = usb_alloc_urb(0, GFP_KERNEL);
- printk(KERN_INFO "HFC-USB: detected \"%s\" configuration: %s (if=%d alt=%d)\n",
- vdata[vend_idx].vend_name, conf_str[small_match], context->if_used, context->alt_used);
-
+ printk(KERN_INFO
+ "HFC-S USB: detected \"%s\"\n",
+ vdata[vend_idx].vend_name);
+#ifdef CONFIG_HISAX_DEBUG
+ DBG(USB_DBG,
+ "HFC-S USB: Endpoint-Config: %s (if=%d alt=%d)\n",
+ conf_str[small_match], context->if_used,
+ context->alt_used);
+ printk(KERN_INFO
+ "HFC-S USB: E-channel (\"ECHO:\") logging ");
+ if (validconf[small_match][18])
+ printk(" possible\n");
+ else
+ printk("NOT possible\n");
+#endif
/* init the chip and register the driver */
- if (usb_init(context))
- {
+ if (usb_init(context)) {
if (context->ctrl_urb) {
usb_unlink_urb(context->ctrl_urb);
usb_free_urb(context->ctrl_urb);
context->ctrl_urb = NULL;
}
kfree(context);
- return(-EIO);
+ return (-EIO);
}
usb_set_intfdata(intf, context);
- return(0);
- }
+ return (0);
+ }
+ } else {
+ printk(KERN_INFO
+ "HFC-S USB: no valid vendor found in USB descriptor\n");
}
- return(-EIO);
+ return (-EIO);
}
/****************************************************/
/* function called when an active device is removed */
/****************************************************/
-static void hfc_usb_disconnect(struct usb_interface *intf)
+static void
+hfc_usb_disconnect(struct usb_interface
+ *intf)
{
hfcusb_data *context = usb_get_intfdata(intf);
int i;
-
- printk(KERN_INFO "HFC-USB: device disconnect\n");
-
+ printk(KERN_INFO "HFC-S USB: device disconnect\n");
+ context->disc_flag = TRUE;
usb_set_intfdata(intf, NULL);
if (!context)
return;
@@ -1599,23 +1742,24 @@ static void hfc_usb_disconnect(struct usb_interface *intf)
del_timer(&context->t4_timer);
if (timer_pending(&context->led_timer))
del_timer(&context->led_timer);
-
- hisax_unregister(&context->d_if);
-
/* tell all fifos to terminate */
- for(i = 0; i < HFCUSB_NUM_FIFOS; i++) {
- if(context->fifos[i].usb_transfer_mode == USB_ISOC) {
- if(context->fifos[i].active > 0) {
- stop_isoc_chain(&context->fifos[i]);
-#ifdef VERBOSE_USB_DEBUG
- printk (KERN_INFO "HFC-USB: hfc_usb_disconnect: stopping ISOC chain Fifo no %i\n", i);
+ for (i = 0; i < HFCUSB_NUM_FIFOS; i++) {
+ if (context->fifos[i].usb_transfer_mode == USB_ISOC) {
+ if (context->fifos[i].active > 0) {
+ stop_isoc_chain(&context->fifos[i]);
+#ifdef CONFIG_HISAX_DEBUG
+ DBG(USB_DBG,
+ "HFC-S USB: hfc_usb_disconnect: stopping ISOC chain Fifo no %i",
+ i);
#endif
- }
+ }
} else {
- if(context->fifos[i].active > 0) {
+ if (context->fifos[i].active > 0) {
context->fifos[i].active = 0;
-#ifdef VERBOSE_USB_DEBUG
- printk (KERN_INFO "HFC-USB: hfc_usb_disconnect: unlinking URB for Fifo no %i\n", i);
+#ifdef CONFIG_HISAX_DEBUG
+ DBG(USB_DBG,
+ "HFC-S USB: hfc_usb_disconnect: unlinking URB for Fifo no %i",
+ i);
#endif
}
if (context->fifos[i].urb) {
@@ -1626,46 +1770,59 @@ static void hfc_usb_disconnect(struct usb_interface *intf)
}
context->fifos[i].active = 0;
}
+ /* wait for all URBS to terminate */
+ mdelay(10);
if (context->ctrl_urb) {
usb_unlink_urb(context->ctrl_urb);
usb_free_urb(context->ctrl_urb);
context->ctrl_urb = NULL;
}
+ hisax_unregister(&context->d_if);
kfree(context); /* free our structure again */
} /* hfc_usb_disconnect */
-
/************************************/
/* our driver information structure */
/************************************/
static struct usb_driver hfc_drv = {
- .owner = THIS_MODULE,
- .name = "hfc_usb",
- .id_table = hfc_usb_idtab,
- .probe = hfc_usb_probe,
- .disconnect = hfc_usb_disconnect,
+ .owner = THIS_MODULE,.name =
+ "hfc_usb",.id_table = hfc_usb_idtab,.probe =
+ hfc_usb_probe,.disconnect = hfc_usb_disconnect,
};
-
-static void __exit hfc_usb_exit(void)
+static void __exit
+hfc_usb_exit(void)
{
-#ifdef VERBOSE_USB_DEBUG
- printk ("HFC-USB: calling \"hfc_usb_exit\" ...\n");
+#ifdef CONFIG_HISAX_DEBUG
+ DBG(USB_DBG, "HFC-S USB: calling \"hfc_usb_exit\" ...");
#endif
usb_deregister(&hfc_drv); /* release our driver */
- printk(KERN_INFO "HFC-USB module removed\n");
+ printk(KERN_INFO "HFC-S USB: module removed\n");
}
-static int __init hfc_usb_init(void)
+static int __init
+hfc_usb_init(void)
{
- printk ("HFC-USB: driver module revision %s loaded\n", hfcusb_revision);
-
- if(usb_register(&hfc_drv))
- {
- printk(KERN_INFO "HFC-USB: Unable to register HFC-USB module at usb stack\n");
- return(-1); /* unable to register */
+#ifndef CONFIG_HISAX_DEBUG
+ unsigned int debug = -1;
+#endif
+ char revstr[30], datestr[30], dummy[30];
+ sscanf(hfcusb_revision,
+ "%s %s $ %s %s %s $ ", dummy, revstr,
+ dummy, datestr, dummy);
+ printk(KERN_INFO
+ "HFC-S USB: driver module revision %s date %s loaded, (debug=%i)\n",
+ revstr, datestr, debug);
+ if (usb_register(&hfc_drv)) {
+ printk(KERN_INFO
+ "HFC-S USB: Unable to register HFC-S USB module at usb stack\n");
+ return (-1); /* unable to register */
}
- return(0);
+ return (0);
}
module_init(hfc_usb_init);
module_exit(hfc_usb_exit);
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(usb, hfc_usb_idtab);
diff --git a/drivers/isdn/hisax/hfc_usb.h b/drivers/isdn/hisax/hfc_usb.h
new file mode 100644
index 0000000000000..b171600cf6412
--- /dev/null
+++ b/drivers/isdn/hisax/hfc_usb.h
@@ -0,0 +1,228 @@
+/*
+* hfc_usb.h
+*
+* $Id: hfc_usb.h,v 4.1 2005/01/26 17:25:53 martinb1 Exp $
+*/
+
+#ifndef __HFC_USB_H__
+#define __HFC_USB_H__
+
+#define DRIVER_AUTHOR "Peter Sprenger (sprenger@moving-byters.de)"
+#define DRIVER_DESC "HFC-S USB based HiSAX ISDN driver"
+
+#define VERBOSE_USB_DEBUG
+
+#define TRUE 1
+#define FALSE 0
+
+
+/***********/
+/* defines */
+/***********/
+#define HFC_CTRL_TIMEOUT 20 /* 5ms timeout writing/reading regs */
+#define HFC_TIMER_T3 8000 /* timeout for l1 activation timer */
+#define HFC_TIMER_T4 500 /* time for state change interval */
+
+#define HFCUSB_L1_STATECHANGE 0 /* L1 state changed */
+#define HFCUSB_L1_DRX 1 /* D-frame received */
+#define HFCUSB_L1_ERX 2 /* E-frame received */
+#define HFCUSB_L1_DTX 4 /* D-frames completed */
+
+#define MAX_BCH_SIZE 2048 /* allowed B-channel packet size */
+
+#define HFCUSB_RX_THRESHOLD 64 /* threshold for fifo report bit rx */
+#define HFCUSB_TX_THRESHOLD 64 /* threshold for fifo report bit tx */
+
+#define HFCUSB_CHIP_ID 0x16 /* Chip ID register index */
+#define HFCUSB_CIRM 0x00 /* cirm register index */
+#define HFCUSB_USB_SIZE 0x07 /* int length register */
+#define HFCUSB_USB_SIZE_I 0x06 /* iso length register */
+#define HFCUSB_F_CROSS 0x0b /* bit order register */
+#define HFCUSB_CLKDEL 0x37 /* bit delay register */
+#define HFCUSB_CON_HDLC 0xfa /* channel connect register */
+#define HFCUSB_HDLC_PAR 0xfb
+#define HFCUSB_SCTRL 0x31 /* S-bus control register (tx) */
+#define HFCUSB_SCTRL_E 0x32 /* same for E and special funcs */
+#define HFCUSB_SCTRL_R 0x33 /* S-bus control register (rx) */
+#define HFCUSB_F_THRES 0x0c /* threshold register */
+#define HFCUSB_FIFO 0x0f /* fifo select register */
+#define HFCUSB_F_USAGE 0x1a /* fifo usage register */
+#define HFCUSB_MST_MODE0 0x14
+#define HFCUSB_MST_MODE1 0x15
+#define HFCUSB_P_DATA 0x1f
+#define HFCUSB_INC_RES_F 0x0e
+#define HFCUSB_STATES 0x30
+
+#define HFCUSB_CHIPID 0x40 /* ID value of HFC-S USB */
+
+/******************/
+/* fifo registers */
+/******************/
+#define HFCUSB_NUM_FIFOS 8 /* maximum number of fifos */
+#define HFCUSB_B1_TX 0 /* index for B1 transmit bulk/int */
+#define HFCUSB_B1_RX 1 /* index for B1 receive bulk/int */
+#define HFCUSB_B2_TX 2
+#define HFCUSB_B2_RX 3
+#define HFCUSB_D_TX 4
+#define HFCUSB_D_RX 5
+#define HFCUSB_PCM_TX 6
+#define HFCUSB_PCM_RX 7
+
+/*
+* used to switch snd_transfer_mode for different TA modes e.g. the Billion USB TA just
+* supports ISO out, while the Cologne Chip EVAL TA just supports BULK out
+*/
+#define USB_INT 0
+#define USB_BULK 1
+#define USB_ISOC 2
+
+#define ISOC_PACKETS_D 8
+#define ISOC_PACKETS_B 8
+#define ISO_BUFFER_SIZE 128
+
+// ISO send definitions
+#define SINK_MAX 68
+#define SINK_MIN 48
+#define SINK_DMIN 12
+#define SINK_DMAX 18
+#define BITLINE_INF (-64*8)
+
+
+/**********/
+/* macros */
+/**********/
+#define write_usb(a,b,c)usb_control_msg((a)->dev,(a)->ctrl_out_pipe,0,0x40,(c),(b),0,0,HFC_CTRL_TIMEOUT)
+#define read_usb(a,b,c) usb_control_msg((a)->dev,(a)->ctrl_in_pipe,1,0xC0,0,(b),(c),1,HFC_CTRL_TIMEOUT)
+
+
+/*******************/
+/* Debugging Flags */
+/*******************/
+#define USB_DBG 1
+#define ISDN_DBG 2
+
+
+/* *********************/
+/* USB related defines */
+/***********************/
+#define HFC_CTRL_BUFSIZE 32
+
+
+
+/*************************************************/
+/* entry and size of output/input control buffer */
+/*************************************************/
+typedef struct {
+ __u8 hfc_reg; /* register number */
+ __u8 reg_val; /* value to be written (or read) */
+ int action; /* data for action handler */
+} ctrl_buft;
+
+
+/********************/
+/* URB error codes: */
+/********************/
+/* Used to represent a list of values and their respective symbolic names */
+struct hfcusb_symbolic_list {
+ const int num;
+ const char *name;
+};
+
+static struct hfcusb_symbolic_list urb_errlist[] = {
+ {-ENOMEM, "No memory for allocation of internal structures"},
+ {-ENOSPC, "The host controller's bandwidth is already consumed"},
+ {-ENOENT, "URB was canceled by unlink_urb"},
+ {-EXDEV, "ISO transfer only partially completed"},
+ {-EAGAIN, "Too match scheduled for the future"},
+ {-ENXIO, "URB already queued"},
+ {-EFBIG, "Too much ISO frames requested"},
+ {-ENOSR, "Buffer error (overrun)"},
+ {-EPIPE, "Specified endpoint is stalled (device not responding)"},
+ {-EOVERFLOW, "Babble (bad cable?)"},
+ {-EPROTO, "Bit-stuff error (bad cable?)"},
+ {-EILSEQ, "CRC/Timeout"},
+ {-ETIMEDOUT, "NAK (device does not respond)"},
+ {-ESHUTDOWN, "Device unplugged"},
+ {-1, NULL}
+};
+
+
+/*****************************************************/
+/* device dependant information to support different */
+/* ISDN Ta's using the HFC-S USB chip */
+/*****************************************************/
+
+/* USB descriptor need to contain one of the following EndPoint combination: */
+#define CNF_4INT3ISO 1 // 4 INT IN, 3 ISO OUT
+#define CNF_3INT3ISO 2 // 3 INT IN, 3 ISO OUT
+#define CNF_4ISO3ISO 3 // 4 ISO IN, 3 ISO OUT
+#define CNF_3ISO3ISO 4 // 3 ISO IN, 3 ISO OUT
+
+#define EP_NUL 1 // Endpoint at this position not allowed
+#define EP_NOP 2 // all type of endpoints allowed at this position
+#define EP_ISO 3 // Isochron endpoint mandatory at this position
+#define EP_BLK 4 // Bulk endpoint mandatory at this position
+#define EP_INT 5 // Interrupt endpoint mandatory at this position
+
+/* this array represents all endpoints possible in the HCF-USB the last
+* 3 entries are the configuration number, the minimum interval for
+* Interrupt endpoints & boolean if E-channel logging possible
+*/
+int validconf[][19] = {
+ // INT in, ISO out config
+ {EP_NUL, EP_INT, EP_NUL, EP_INT, EP_NUL, EP_INT, EP_NOP, EP_INT,
+ EP_ISO, EP_NUL, EP_ISO, EP_NUL, EP_ISO, EP_NUL, EP_NUL, EP_NUL,
+ CNF_4INT3ISO, 2, 1},
+ {EP_NUL, EP_INT, EP_NUL, EP_INT, EP_NUL, EP_INT, EP_NUL, EP_NUL,
+ EP_ISO, EP_NUL, EP_ISO, EP_NUL, EP_ISO, EP_NUL, EP_NUL, EP_NUL,
+ CNF_3INT3ISO, 2, 0},
+ // ISO in, ISO out config
+ {EP_NUL, EP_NUL, EP_NUL, EP_NUL, EP_NUL, EP_NUL, EP_NUL, EP_NUL,
+ EP_ISO, EP_ISO, EP_ISO, EP_ISO, EP_ISO, EP_ISO, EP_NOP, EP_ISO,
+ CNF_4ISO3ISO, 2, 1},
+ {EP_NUL, EP_NUL, EP_NUL, EP_NUL, EP_NUL, EP_NUL, EP_NUL, EP_NUL,
+ EP_ISO, EP_ISO, EP_ISO, EP_ISO, EP_ISO, EP_ISO, EP_NUL, EP_NUL,
+ CNF_3ISO3ISO, 2, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} // EOL element
+};
+
+// string description of chosen config
+char *conf_str[] = {
+ "4 Interrupt IN + 3 Isochron OUT",
+ "3 Interrupt IN + 3 Isochron OUT",
+ "4 Isochron IN + 3 Isochron OUT",
+ "3 Isochron IN + 3 Isochron OUT"
+};
+
+
+typedef struct {
+ int vendor; // vendor id
+ int prod_id; // product id
+ char *vend_name; // vendor string
+ __u8 led_scheme; // led display scheme
+ signed short led_bits[8]; // array of 8 possible LED bitmask settings
+} vendor_data;
+
+#define LED_OFF 0 // no LED support
+#define LED_SCHEME1 1 // LED standard scheme
+#define LED_SCHEME2 2 // not used yet...
+
+#define LED_POWER_ON 1
+#define LED_POWER_OFF 2
+#define LED_S0_ON 3
+#define LED_S0_OFF 4
+#define LED_B1_ON 5
+#define LED_B1_OFF 6
+#define LED_B1_DATA 7
+#define LED_B2_ON 8
+#define LED_B2_OFF 9
+#define LED_B2_DATA 10
+
+#define LED_NORMAL 0 // LEDs are normal
+#define LED_INVERTED 1 // LEDs are inverted
+
+/* time in ms to perform a Flashing LED when B-Channel has traffic */
+#define LED_TIME 250
+
+
+#endif // __HFC_USB_H__
diff --git a/drivers/isdn/hisax/hisax_fcpcipnp.c b/drivers/isdn/hisax/hisax_fcpcipnp.c
index e8fd6af948c3d..b4d795d401542 100644
--- a/drivers/isdn/hisax/hisax_fcpcipnp.c
+++ b/drivers/isdn/hisax/hisax_fcpcipnp.c
@@ -902,7 +902,7 @@ static int __devinit fcpci_probe(struct pci_dev *pdev,
adapter->irq = pdev->irq;
printk(KERN_INFO "hisax_fcpcipnp: found adapter %s at %s\n",
- (char *) ent->driver_data, pdev->slot_name);
+ (char *) ent->driver_data, pci_name(pdev));
retval = fcpcipnp_setup(adapter);
if (retval)
@@ -1010,12 +1010,6 @@ static int __init hisax_fcpcipnp_init(void)
#endif
return 0;
-#if !defined(CONFIG_HOTPLUG) || defined(MODULE)
- out_unregister_isapnp:
-#ifdef __ISAPNP__
- pnp_unregister_driver(&fcpnp_driver);
-#endif
-#endif
out_unregister_pci:
pci_unregister_driver(&fcpci_driver);
out:
diff --git a/drivers/isdn/hisax/icc.c b/drivers/isdn/hisax/icc.c
index 60b7e133a6b7d..dcf31f83c6000 100644
--- a/drivers/isdn/hisax/icc.c
+++ b/drivers/isdn/hisax/icc.c
@@ -27,7 +27,7 @@
static char *ICCVer[] __initdata =
{"2070 A1/A3", "2070 B1", "2070 B2/B3", "2070 V2.4"};
-void
+void __init
ICCVersion(struct IsdnCardState *cs, char *s)
{
int val;
diff --git a/drivers/isdn/hisax/icc.h b/drivers/isdn/hisax/icc.h
index e7f593967e43a..b3bb3d5de5321 100644
--- a/drivers/isdn/hisax/icc.h
+++ b/drivers/isdn/hisax/icc.h
@@ -65,7 +65,7 @@
#define ICC_IND_AIL 0xE
#define ICC_IND_DC 0xF
-extern void ICCVersion(struct IsdnCardState *cs, char *s);
+extern void __init ICCVersion(struct IsdnCardState *cs, char *s);
extern void initicc(struct IsdnCardState *cs);
extern void icc_interrupt(struct IsdnCardState *cs, u_char val);
extern void clear_pending_icc_ints(struct IsdnCardState *cs);
diff --git a/drivers/isdn/hisax/sedlbauer.c b/drivers/isdn/hisax/sedlbauer.c
index 3393370ce09e0..8390f16068534 100644
--- a/drivers/isdn/hisax/sedlbauer.c
+++ b/drivers/isdn/hisax/sedlbauer.c
@@ -516,7 +516,7 @@ Sedl_card_msg(struct IsdnCardState *cs, int mt, void *arg)
static struct pci_dev *dev_sedl __devinitdata = NULL;
#ifdef __ISAPNP__
-static struct isapnp_device_id sedl_ids[] __initdata = {
+static struct isapnp_device_id sedl_ids[] __devinitdata = {
{ ISAPNP_VENDOR('S', 'A', 'G'), ISAPNP_FUNCTION(0x01),
ISAPNP_VENDOR('S', 'A', 'G'), ISAPNP_FUNCTION(0x01),
(unsigned long) "Speed win" },
@@ -526,7 +526,7 @@ static struct isapnp_device_id sedl_ids[] __initdata = {
{ 0, }
};
-static struct isapnp_device_id *ipid __initdata = &sedl_ids[0];
+static struct isapnp_device_id *ipid __devinitdata = &sedl_ids[0];
static struct pnp_card *pnp_c __devinitdata = NULL;
#endif
diff --git a/drivers/isdn/hisax/teles3.c b/drivers/isdn/hisax/teles3.c
index 81cb3b55e1b6a..c5b1f65f7275a 100644
--- a/drivers/isdn/hisax/teles3.c
+++ b/drivers/isdn/hisax/teles3.c
@@ -254,7 +254,7 @@ Teles_card_msg(struct IsdnCardState *cs, int mt, void *arg)
#ifdef __ISAPNP__
-static struct isapnp_device_id teles_ids[] __initdata = {
+static struct isapnp_device_id teles_ids[] __devinitdata = {
{ ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2110),
ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2110),
(unsigned long) "Teles 16.3 PnP" },
@@ -267,7 +267,7 @@ static struct isapnp_device_id teles_ids[] __initdata = {
{ 0, }
};
-static struct isapnp_device_id *ipid __initdata = &teles_ids[0];
+static struct isapnp_device_id *ipid __devinitdata = &teles_ids[0];
static struct pnp_card *pnp_c __devinitdata = NULL;
#endif
diff --git a/drivers/isdn/hisax/w6692.c b/drivers/isdn/hisax/w6692.c
index 36cfc4a482896..d2b6b8e72980d 100644
--- a/drivers/isdn/hisax/w6692.c
+++ b/drivers/isdn/hisax/w6692.c
@@ -49,7 +49,7 @@ static char *W6692Ver[] __initdata =
{"W6692 V00", "W6692 V01", "W6692 V10",
"W6692 V11"};
-static void
+static void __init
W6692Version(struct IsdnCardState *cs, char *s)
{
int val;
diff --git a/drivers/isdn/i4l/Kconfig b/drivers/isdn/i4l/Kconfig
index 7754641a8a2e2..1789b607f0903 100644
--- a/drivers/isdn/i4l/Kconfig
+++ b/drivers/isdn/i4l/Kconfig
@@ -135,8 +135,6 @@ source "drivers/isdn/sc/Kconfig"
source "drivers/isdn/act2000/Kconfig"
-source "drivers/isdn/tpam/Kconfig"
-
source "drivers/isdn/hysdn/Kconfig"
endmenu
diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c
index 4956e2e020185..c406df6f268a5 100644
--- a/drivers/isdn/i4l/isdn_common.c
+++ b/drivers/isdn/i4l/isdn_common.c
@@ -1180,9 +1180,9 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
if (arg) {
ulong __user *p = argp;
int i;
- if ((ret = verify_area(VERIFY_WRITE, p,
- sizeof(ulong) * ISDN_MAX_CHANNELS * 2)))
- return ret;
+ if (!access_ok(VERIFY_WRITE, p,
+ sizeof(ulong) * ISDN_MAX_CHANNELS * 2))
+ return -EFAULT;
for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
put_user(dev->ibytes[i], p++);
put_user(dev->obytes[i], p++);
@@ -1420,10 +1420,10 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
char __user *p = argp;
int i;
- if ((ret = verify_area(VERIFY_WRITE, argp,
+ if (!access_ok(VERIFY_WRITE, argp,
(ISDN_MODEM_NUMREG + ISDN_MSNLEN + ISDN_LMSNLEN)
- * ISDN_MAX_CHANNELS)))
- return ret;
+ * ISDN_MAX_CHANNELS))
+ return -EFAULT;
for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
if (copy_to_user(p, dev->mdm.info[i].emu.profile,
@@ -1447,10 +1447,10 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
char __user *p = argp;
int i;
- if ((ret = verify_area(VERIFY_READ, argp,
+ if (!access_ok(VERIFY_READ, argp,
(ISDN_MODEM_NUMREG + ISDN_MSNLEN + ISDN_LMSNLEN)
- * ISDN_MAX_CHANNELS)))
- return ret;
+ * ISDN_MAX_CHANNELS))
+ return -EFAULT;
for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
if (copy_from_user(dev->mdm.info[i].emu.profile, p,
@@ -1496,8 +1496,8 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
int j = 0;
while (1) {
- if ((ret = verify_area(VERIFY_READ, p, 1)))
- return ret;
+ if (!access_ok(VERIFY_READ, p, 1))
+ return -EFAULT;
get_user(bname[j], p++);
switch (bname[j]) {
case '\0':
@@ -1563,9 +1563,9 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
drvidx = 0;
if (drvidx == -1)
return -ENODEV;
- if ((ret = verify_area(VERIFY_WRITE, argp,
- sizeof(isdn_ioctl_struct))))
- return ret;
+ if (!access_ok(VERIFY_WRITE, argp,
+ sizeof(isdn_ioctl_struct)))
+ return -EFAULT;
c.driver = drvidx;
c.command = ISDN_CMD_IOCTL;
c.arg = cmd;
diff --git a/drivers/isdn/i4l/isdn_net.c b/drivers/isdn/i4l/isdn_net.c
index 964d5c9752827..e2b790e345108 100644
--- a/drivers/isdn/i4l/isdn_net.c
+++ b/drivers/isdn/i4l/isdn_net.c
@@ -1786,6 +1786,7 @@ isdn_net_receive(struct net_device *ndev, struct sk_buff *skb)
lp->stats.rx_bytes += skb->len;
}
skb->dev = ndev;
+ skb->input_dev = ndev;
skb->pkt_type = PACKET_HOST;
skb->mac.raw = skb->data;
#ifdef ISDN_DEBUG_NET_DUMP
diff --git a/drivers/isdn/i4l/isdn_ppp.c b/drivers/isdn/i4l/isdn_ppp.c
index a11be53573d09..e8d11a7c48a81 100644
--- a/drivers/isdn/i4l/isdn_ppp.c
+++ b/drivers/isdn/i4l/isdn_ppp.c
@@ -764,7 +764,6 @@ isdn_ppp_read(int min, struct file *file, char __user *buf, int count)
{
struct ippp_struct *is;
struct ippp_buf_queue *b;
- int r;
u_long flags;
u_char *save_buf;
@@ -773,8 +772,8 @@ isdn_ppp_read(int min, struct file *file, char __user *buf, int count)
if (!(is->state & IPPP_OPEN))
return 0;
- if ((r = verify_area(VERIFY_WRITE, buf, count)))
- return r;
+ if (!access_ok(VERIFY_WRITE, buf, count))
+ return -EFAULT;
spin_lock_irqsave(&is->buflock, flags);
b = is->first->next;
@@ -1178,6 +1177,7 @@ isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff
mlp->huptimer = 0;
#endif /* CONFIG_IPPP_FILTER */
skb->dev = dev;
+ skb->input_dev = dev;
skb->mac.raw = skb->data;
netif_rx(skb);
/* net_dev->local->stats.rx_packets++; done in isdn_net.c */
@@ -1578,7 +1578,7 @@ static int isdn_ppp_mp_init( isdn_net_local * lp, ippp_bundle * add_to )
lp->next = lp->last = lp; /* nobody else in a queue */
lp->netdev->pb->frags = NULL;
lp->netdev->pb->frames = 0;
- lp->netdev->pb->seq = LONG_MAX;
+ lp->netdev->pb->seq = UINT_MAX;
}
lp->netdev->pb->ref_ct++;
@@ -1995,12 +1995,9 @@ isdn_ppp_dev_ioctl_stats(int slot, struct ifreq *ifr, struct net_device *dev)
struct ppp_stats __user *res = ifr->ifr_data;
struct ppp_stats t;
isdn_net_local *lp = (isdn_net_local *) dev->priv;
- int err;
-
- err = verify_area(VERIFY_WRITE, res, sizeof(struct ppp_stats));
- if (err)
- return err;
+ if (!access_ok(VERIFY_WRITE, res, sizeof(struct ppp_stats)))
+ return -EFAULT;
/* build a temporary stat struct and copy it to user space */
diff --git a/drivers/isdn/icn/icn.c b/drivers/isdn/icn/icn.c
index 20c13c12802ca..9fc0c1e037321 100644
--- a/drivers/isdn/icn/icn.c
+++ b/drivers/isdn/icn/icn.c
@@ -908,14 +908,13 @@ icn_loadproto(u_char __user * buffer, icn_card * card)
uint left = ICN_CODE_STAGE2;
uint cnt;
int timer;
- int ret;
unsigned long flags;
#ifdef BOOT_DEBUG
printk(KERN_DEBUG "icn_loadproto called\n");
#endif
- if ((ret = verify_area(VERIFY_READ, buffer, ICN_CODE_STAGE2)))
- return ret;
+ if (!access_ok(VERIFY_READ, buffer, ICN_CODE_STAGE2))
+ return -EFAULT;
timer = 0;
spin_lock_irqsave(&dev.devlock, flags);
if (card->secondhalf) {
diff --git a/drivers/isdn/isdnloop/isdnloop.c b/drivers/isdn/isdnloop/isdnloop.c
index 7f17ab1ac7ee0..14e1f8fbc61f0 100644
--- a/drivers/isdn/isdnloop/isdnloop.c
+++ b/drivers/isdn/isdnloop/isdnloop.c
@@ -1146,8 +1146,8 @@ isdnloop_command(isdn_ctrl * c, isdnloop_card * card)
case ISDNLOOP_IOCTL_DEBUGVAR:
return (ulong) card;
case ISDNLOOP_IOCTL_STARTUP:
- if ((i = verify_area(VERIFY_READ, (void *) a, sizeof(isdnloop_sdef))))
- return i;
+ if (!access_ok(VERIFY_READ, (void *) a, sizeof(isdnloop_sdef)))
+ return -EFAULT;
return (isdnloop_start(card, (isdnloop_sdef *) a));
break;
case ISDNLOOP_IOCTL_ADDCARD:
diff --git a/drivers/isdn/tpam/Kconfig b/drivers/isdn/tpam/Kconfig
deleted file mode 100644
index 22b23c88ea697..0000000000000
--- a/drivers/isdn/tpam/Kconfig
+++ /dev/null
@@ -1,15 +0,0 @@
-#
-# Config.in for Auvertech TurboPAM ISDN driver
-#
-config ISDN_DRV_TPAM
- tristate "Auvertech TurboPAM support (EXPERIMENTAL)"
- depends on EXPERIMENTAL && ISDN_I4L && PCI
- select CRC_CCITT
- help
- This enables support for the Auvertech TurboPAM ISDN-card.
- For running this card, additional firmware is necessary, which has
- to be downloaded into the card using a utility which is distributed
- separately from the Auvertech's web site: <http://www.auvertech.fr/>.
-
- Please redirect all support questions to <support@auvertech.fr>.
-
diff --git a/drivers/isdn/tpam/Makefile b/drivers/isdn/tpam/Makefile
deleted file mode 100644
index 5860692b14b4e..0000000000000
--- a/drivers/isdn/tpam/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-# Makefile for the TurboPAM ISDN device driver
-
-# Each configuration option enables a list of files.
-
-obj-$(CONFIG_ISDN_DRV_TPAM) += tpam.o
-
-# Multipart objects.
-
-tpam-y := tpam_main.o tpam_nco.o tpam_memory.o \
- tpam_commands.o tpam_queues.o tpam_hdlc.o \
- tpam_crcpc.o
diff --git a/drivers/isdn/tpam/tpam.h b/drivers/isdn/tpam/tpam.h
deleted file mode 100644
index 5b92b956151b5..0000000000000
--- a/drivers/isdn/tpam/tpam.h
+++ /dev/null
@@ -1,229 +0,0 @@
-/* $Id: tpam.h,v 1.1.2.3 2001/11/06 20:58:30 kai Exp $
- *
- * Turbo PAM ISDN driver for Linux. (Kernel Driver)
- *
- * Copyright 2001 Stelian Pop <stelian.pop@fr.alcove.com>, Alcôve
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- * For all support questions please contact: <support@auvertech.fr>
- *
- */
-
-#ifndef _TPAM_PRIV_H_
-#define _TPAM_PRIV_H_
-
-//#define DEBUG /* uncomment if you want debugging output */
-#include <linux/kernel.h>
-#include <linux/isdnif.h>
-#include <linux/init.h>
-#include <linux/workqueue.h>
-#include <linux/interrupt.h>
-
-/* Maximum number of channels for this board */
-#define TPAM_NBCHANNEL 30
-/* Maximum size of data */
-#define TPAM_MAXBUFSIZE 2032
-/* Size of a page of board memory */
-#define TPAM_PAGE_SIZE 0x003ffffc /* 4 MB */
-/* Magic number present if the board was successfully started */
-#define TPAM_MAGICNUMBER 0x2a343242
-
-/* Registers in the PCI BAR0 */
-#define TPAM_PAGE_REGISTER 0x00400000 /* Select page */
-#define TPAM_DSPINT_REGISTER 0x00400004 /* Interrupt board */
-#define TPAM_RESETPAM_REGISTER 0x00400008 /* Reset board */
-#define TPAM_HINTACK_REGISTER 0x0040000c /* Ack interrupt */
-#define TPAM_HPIC_REGISTER 0x00400014 /* Board ready */
-
-/* Registers in the board memory */
-#define TPAM_MAGICNUMBER_REGISTER 0x80008000 /* Magic number */
-#define TPAM_EXID_REGISTER 0x80008004 /* EXID - not used */
-#define TPAM_UPLOADPTR_REGISTER 0x80008008 /* Upload data ptr */
-#define TPAM_DOWNLOADPTR_REGISTER 0x8000800c /* Download data ptr */
-#define TPAM_ACKUPLOAD_REGISTER 0x80008010 /* Ack upload */
-#define TPAM_ACKDOWNLOAD_REGISTER 0x80008014 /* Ack download */
-#define TPAM_INTERRUPTACK_REGISTER 0x80008018 /* Ack interrupt */
-
-/* Reserved areas in the board memory */
-#define TPAM_RESERVEDAREA1_START 0x00000000
-#define TPAM_RESERVEDAREA1_END 0x003FFFFF
-#define TPAM_RESERVEDAREA2_START 0x01C00000
-#define TPAM_RESERVEDAREA2_END 0x01FFFFFF
-#define TPAM_RESERVEDAREA3_START 0x04000000
-#define TPAM_RESERVEDAREA3_END 0x7FFFFFFF
-#define TPAM_RESERVEDAREA4_START 0x80010000
-#define TPAM_RESERVEDAREA4_END 0xFFFFFFFF
-
-/* NCO ID invalid */
-#define TPAM_NCOID_INVALID 0xffff
-/* channel number invalid */
-#define TPAM_CHANNEL_INVALID 0xffff
-
-/* Channel structure */
-typedef struct tpam_channel {
- int num; /* channel number */
- struct tpam_card *card; /* channel's card */
- u32 ncoid; /* ncoid */
- u8 hdlc; /* hdlc mode (set by user level) */
- u8 realhdlc; /* hdlc mode (negociated with peer) */
- u32 hdlcshift; /* hdlc shift */
- u8 readytoreceive; /* channel ready to receive data */
- struct sk_buff_head sendq; /* Send queue */
-} tpam_channel;
-
-/* Card structure */
-typedef struct tpam_card {
- struct tpam_card *next; /* next card in list */
- unsigned int irq; /* IRQ used by this board */
- void __iomem *bar0; /* ioremapped bar0 */
- int id; /* id of the board */
- isdn_if interface; /* isdn link-level pointer */
- int channels_used; /* number of channels actually used */
- int channels_tested; /* number of channels being tested */
- u8 loopmode; /* board in looptest mode */
- tpam_channel channels[TPAM_NBCHANNEL];/* channels tab */
- int running; /* card is running */
- int busy; /* waiting for ack from card */
- int roundrobin; /* round robin between channels */
- struct sk_buff_head sendq; /* send queue */
- struct sk_buff_head recvq; /* receive queue */
- struct work_struct send_tq; /* send task queue */
- struct work_struct recv_tq; /* receive task queue */
- spinlock_t lock; /* lock for the card */
-} tpam_card;
-
-/* Timeout waiting for signature to become available */
-#define SIGNATURE_TIMEOUT (5*HZ)
-/* Timeout waiting for receiving all the ACreateNCOCnf */
-#define NCOCREATE_TIMEOUT (30*HZ)
-
-/* Maximum size of the TLV block */
-#define MPB_MAXIMUMBLOCKTLVSIZE 128
-/* Maximum size of the data block */
-#define MPB_MAXIMUMDATASIZE 4904
-/* Maximum size of a phone number */
-#define PHONE_MAXIMUMSIZE 32
-
-/* Header for a sk_buff structure */
-typedef struct skb_header {
- u16 size; /* size of pci_mpb block + size of tlv block */
- u16 data_size; /* size of the data block */
- u16 ack; /* packet needs to send ack upon send */
- u16 ack_size; /* size of data to be acknowledged upon send */
-} skb_header;
-
-/* PCI message header structure */
-typedef struct pci_mpb {
- u16 exID; /* exID - not used */
- u16 flags; /* flags - not used */
- u32 errorCode; /* errorCode - not used */
- u16 messageID; /* message ID - one of ID_XXX */
- u16 maximumBlockTLVSize; /* MPB_MAXIMUMBLOCKTLVSIZE */
- u16 actualBlockTLVSize; /* size of the tlv block */
- u16 maximumDataSize; /* MPB_MAXIMUMDATASIZE */
- u16 actualDataSize; /* size of the data block */
- u16 dummy; /* padding */
-} pci_mpb;
-
-/* Types of PCI messages */
-#define ID_ACreateNCOReq 101
-#define ID_ACreateNCOCnf 102
-#define ID_ADestroyNCOReq 103
-#define ID_ADestroyNCOCnf 104
-#define ID_CConnectReq 203
-#define ID_CConnectInd 204
-#define ID_CConnectRsp 205
-#define ID_CConnectCnf 206
-#define ID_CDisconnectReq 207
-#define ID_CDisconnectInd 208
-#define ID_CDisconnectRsp 209
-#define ID_CDisconnectCnf 210
-#define ID_U3DataReq 307
-#define ID_U3DataInd 308
-#define ID_U3ReadyToReceiveInd 318
-
-/* Parameters for the PCI message TLV block */
-#define PAR_BearerCap 3
-#define PAR_CalledNumber 7
-#define PAR_CallingNumber 11
-#define PAR_CauseToPUF 15
-#define PAR_Cdirection 16
-#define PAR_CompletionStatus 19
-#define PAR_Facility 30
-#define PAR_HLC 34
-#define PAR_NCOID 49
-#define PAR_NCOType 50
-#define PAR_ReadyFlag 55
-#define PAR_U3Protocol 62
-#define PAR_Udirection 64
-
-/* Delayed statcallb structure */
-typedef struct tpam_statcallb_data {
- tpam_card *card; /* card issuing the statcallb */
- struct timer_list *timer; /* timer launching the statcallb */
- isdn_ctrl ctrl; /* isdn command */
-} tpam_statcallb_data;
-
-/* Function prototypes from tpam_main.c */
-extern tpam_card *tpam_findcard(int);
-extern u32 tpam_findchannel(tpam_card *, u32);
-
-/* Function prototypes from tpam_memory.c */
-extern void copy_to_pam_dword(tpam_card *, u32, u32);
-extern void copy_to_pam(tpam_card *, u32, const void *, u32);
-extern u32 copy_from_pam_dword(tpam_card *, u32);
-extern void copy_from_pam(tpam_card *, void *, u32, u32);
-extern int copy_from_pam_to_user(tpam_card *, void __user *, u32, u32);
-extern int copy_from_user_to_pam(tpam_card *, u32, const void __user *, u32);
-extern int tpam_verify_area(u32, u32);
-
-/* Function prototypes from tpam_nco.c */
-extern struct sk_buff *build_ACreateNCOReq(const u8 *);
-extern struct sk_buff *build_ADestroyNCOReq(u32);
-extern struct sk_buff *build_CConnectReq(u32, const u8 *, u8);
-extern struct sk_buff *build_CConnectRsp(u32);
-extern struct sk_buff *build_CDisconnectReq(u32);
-extern struct sk_buff *build_CDisconnectRsp(u32);
-extern struct sk_buff *build_U3DataReq(u32, void *, u16, u16, u16);
-extern int parse_ACreateNCOCnf(struct sk_buff *, u8 *, u32 *);
-extern int parse_ADestroyNCOCnf(struct sk_buff *, u8 *, u32 *);
-extern int parse_CConnectCnf(struct sk_buff *, u32 *);
-extern int parse_CConnectInd(struct sk_buff *, u32 *, u8 *, u8 *,
- u8 *, u8 *, u8 *);
-extern int parse_CDisconnectCnf(struct sk_buff *, u32 *, u32 *);
-extern int parse_CDisconnectInd(struct sk_buff *, u32 *, u32 *);
-extern int parse_U3ReadyToReceiveInd(struct sk_buff *, u32 *, u8 *);
-extern int parse_U3DataInd(struct sk_buff *, u32 *, u8 **, u16 *);
-
-/* Function prototypes from tpam_queues.c */
-extern void tpam_enqueue(tpam_card *, struct sk_buff *);
-extern void tpam_enqueue_data(tpam_channel *, struct sk_buff *);
-extern irqreturn_t tpam_irq(int, void *, struct pt_regs *);
-extern void tpam_recv_tq(tpam_card *);
-extern void tpam_send_tq(tpam_card *);
-
-/* Function prototypes from tpam_commands.c */
-extern int tpam_command(isdn_ctrl *);
-extern int tpam_writebuf_skb(int, int, int, struct sk_buff *);
-extern void tpam_recv_ACreateNCOCnf(tpam_card *, struct sk_buff *);
-extern void tpam_recv_ADestroyNCOCnf(tpam_card *, struct sk_buff *);
-extern void tpam_recv_CConnectCnf(tpam_card *, struct sk_buff *);
-extern void tpam_recv_CConnectInd(tpam_card *, struct sk_buff *);
-extern void tpam_recv_CDisconnectInd(tpam_card *, struct sk_buff *);
-extern void tpam_recv_CDisconnectCnf(tpam_card *, struct sk_buff *);
-extern void tpam_recv_U3DataInd(tpam_card *, struct sk_buff *);
-extern void tpam_recv_U3ReadyToReceiveInd(tpam_card *, struct sk_buff *);
-
-/* Function prototypes from tpam_hdlc.c */
-extern u32 tpam_hdlc_encode(u8 *, u8 *, u32 *, u32);
-extern u32 tpam_hdlc_decode(u8 *, u8 *, u32);
-
-/* Function prototypes from tpam_crcpc.c */
-extern void init_CRC(void);
-extern void hdlc_encode_modem(u8 *, u32, u8 *, u32 *);
-extern void hdlc_no_accm_encode(u8 *, u32, u8 *, u32 *);
-extern u32 hdlc_no_accm_decode(u8 *, u32);
-
-#endif /* _TPAM_H_ */
diff --git a/drivers/isdn/tpam/tpam_commands.c b/drivers/isdn/tpam/tpam_commands.c
deleted file mode 100644
index 3f8e793934252..0000000000000
--- a/drivers/isdn/tpam/tpam_commands.c
+++ /dev/null
@@ -1,987 +0,0 @@
-/* $Id: tpam_commands.c,v 1.1.2.4 2001/11/06 20:58:30 kai Exp $
- *
- * Turbo PAM ISDN driver for Linux. (Kernel Driver - ISDN commands)
- *
- * Copyright 2001 Stelian Pop <stelian.pop@fr.alcove.com>, Alcôve
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- * For all support questions please contact: <support@auvertech.fr>
- *
- */
-
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <asm/io.h>
-
-#include <linux/isdn/tpam.h>
-#include "tpam.h"
-
-/* Local functions prototypes */
-static int tpam_command_ioctl_dspload(tpam_card *, unsigned long);
-static int tpam_command_ioctl_dspsave(tpam_card *, unsigned long);
-static int tpam_command_ioctl_dsprun(tpam_card *);
-static int tpam_command_ioctl_loopmode(tpam_card *, u8);
-static int tpam_command_dial(tpam_card *, u32, u8 *);
-static int tpam_command_setl2(tpam_card *, u32, u8);
-static int tpam_command_acceptd(tpam_card *, u32);
-static int tpam_command_acceptb(tpam_card *, u32);
-static int tpam_command_hangup(tpam_card *, u32);
-static int tpam_command_proceed(tpam_card *, u32);
-static void tpam_statcallb_run(unsigned long);
-static void tpam_statcallb(tpam_card *, isdn_ctrl);
-
-/*
- * Function called when the ISDN link level send a command to the driver.
- *
- * c: ISDN command.
- *
- * Return: 0 if OK, <0 on errors.
- */
-int tpam_command(isdn_ctrl *c) {
- tpam_card *card;
- unsigned long argp;
-
- pr_debug("TurboPAM(tpam_command) card=%d, command=%d\n",
- c->driver, c->command);
-
- /* search for the board */
- if (!(card = tpam_findcard(c->driver))) {
- printk(KERN_ERR "TurboPAM(tpam_command): invalid driverId %d\n",
- c->driver);
- return -ENODEV;
- }
-
- /* dispatch the command */
- switch (c->command) {
- case ISDN_CMD_IOCTL:
- argp = c->parm.userdata;
- switch (c->arg) {
- case TPAM_CMD_DSPLOAD:
- return tpam_command_ioctl_dspload(card,
- argp);
- case TPAM_CMD_DSPSAVE:
- return tpam_command_ioctl_dspsave(card,
- argp);
- case TPAM_CMD_DSPRUN:
- return tpam_command_ioctl_dsprun(card);
- case TPAM_CMD_LOOPMODEON:
- return tpam_command_ioctl_loopmode(card,
- 1);
- case TPAM_CMD_LOOPMODEOFF:
- return tpam_command_ioctl_loopmode(card,
- 0);
- default:
- pr_debug("TurboPAM(tpam_command): "
- "invalid tpam ioctl %ld\n",
- c->arg);
- return -EINVAL;
- }
- case ISDN_CMD_DIAL:
- return tpam_command_dial(card, c->arg,
- c->parm.setup.phone);
- case ISDN_CMD_ACCEPTD:
- return tpam_command_acceptd(card, c->arg);
- case ISDN_CMD_ACCEPTB:
- return tpam_command_acceptb(card, c->arg);
- case ISDN_CMD_HANGUP:
- return tpam_command_hangup(card, c->arg);
- case ISDN_CMD_SETL2:
- return tpam_command_setl2(card, c->arg & 0xff,
- c->arg >> 8);
- case ISDN_CMD_PROCEED:
- return tpam_command_proceed(card, c->arg);
- default:
- pr_debug("TurboPAM(tpam_command): "
- "unknown or unused isdn ioctl %d\n",
- c->command);
- return -EINVAL;
- }
-
- /* not reached */
- return -EINVAL;
-}
-
-/*
- * Load some data into the board's memory.
- *
- * card: the board
- * arg: IOCTL argument containing the user space address of
- * the tpam_dsp_ioctl structure describing the IOCTL.
- *
- * Return: 0 if OK, <0 on errors.
- */
-static int tpam_command_ioctl_dspload(tpam_card *card, unsigned long arg) {
- tpam_dsp_ioctl tdl;
-
- pr_debug("TurboPAM(tpam_command_ioctl_dspload): card=%d\n", card->id);
-
- /* get the IOCTL parameter from userspace */
- if (copy_from_user(&tdl, (void __user *)arg, sizeof(tpam_dsp_ioctl)))
- return -EFAULT;
-
- /* if the board's firmware was started, protect against writes
- * to unallowed memory areas. If the board's firmware wasn't started,
- * all is allowed. */
- if (card->running && tpam_verify_area(tdl.address, tdl.data_len))
- return -EPERM;
-
- /* write the data in the board's memory */
- return copy_from_user_to_pam(card, tdl.address,
- (void __user *)arg + sizeof(tpam_dsp_ioctl),
- tdl.data_len);
-}
-
-/*
- * Extract some data from the board's memory.
- *
- * card: the board
- * arg: IOCTL argument containing the user space address of
- * the tpam_dsp_ioctl structure describing the IOCTL.
- *
- * Return: 0 if OK, <0 on errors.
- */
-static int tpam_command_ioctl_dspsave(tpam_card *card, unsigned long arg) {
- tpam_dsp_ioctl tdl;
-
- pr_debug("TurboPAM(tpam_command_ioctl_dspsave): card=%d\n", card->id);
-
- /* get the IOCTL parameter from userspace */
- if (copy_from_user(&tdl, (void __user *)arg, sizeof(tpam_dsp_ioctl)))
- return -EFAULT;
-
- /* protect against read from unallowed memory areas */
- if (tpam_verify_area(tdl.address, tdl.data_len))
- return -EPERM;
-
- /* read the data from the board's memory */
- return copy_from_pam_to_user(card, (void __user *)arg + sizeof(tpam_dsp_ioctl),
- tdl.address, tdl.data_len);
-}
-
-/*
- * Launch the board's firmware. This function must be called after the
- * firmware was loaded into the board's memory using TPAM_CMD_DSPLOAD
- * IOCTL commands. After launching the firmware, this function creates
- * the NCOs and waits for their creation.
- *
- * card: the board
- *
- * Return: 0 if OK, <0 on errors.
- */
-static int tpam_command_ioctl_dsprun(tpam_card *card) {
- u32 signature = 0, i;
- unsigned long timeout;
- isdn_ctrl ctrl;
- struct sk_buff *skb;
-
- pr_debug("TurboPAM(tpam_command_ioctl_dsprun): card=%d\n", card->id);
-
- /* board must _not_ be running */
- if (card->running)
- return -EBUSY;
-
- /* reset the board */
- spin_lock_irq(&card->lock);
- copy_to_pam_dword(card, TPAM_MAGICNUMBER_REGISTER, 0xdeadface);
- readl(card->bar0 + TPAM_DSPINT_REGISTER);
- readl(card->bar0 + TPAM_HINTACK_REGISTER);
- spin_unlock_irq(&card->lock);
-
- /* wait for the board signature */
- timeout = jiffies + SIGNATURE_TIMEOUT;
- while (time_before(jiffies, timeout)) {
- spin_lock_irq(&card->lock);
- signature = copy_from_pam_dword(card,
- TPAM_MAGICNUMBER_REGISTER);
- spin_unlock_irq(&card->lock);
- if (signature == TPAM_MAGICNUMBER)
- break;
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(2);
- }
-
- /* signature not present -> board not started */
- if (signature != TPAM_MAGICNUMBER) {
- printk(KERN_ERR "TurboPAM(tpam_command_ioctl_dsprun): "
- "card=%d, signature 0x%lx, expected 0x%lx\n",
- card->id, (unsigned long)signature,
- (unsigned long)TPAM_MAGICNUMBER);
- printk(KERN_ERR "TurboPAM(tpam_command_ioctl_dsprun): "
- "card=%d, firmware not started\n", card->id);
- return -EIO;
- }
-
- /* the firmware is started */
- printk(KERN_INFO "TurboPAM: card=%d, firmware started\n", card->id);
-
- /* init the CRC routines */
- init_CRC();
-
- /* create all the NCOs */
- for (i = 0; i < TPAM_NBCHANNEL; ++i)
- if ((skb = build_ACreateNCOReq("")))
- tpam_enqueue(card, skb);
-
- /* wait for NCO creation confirmation */
- timeout = jiffies + NCOCREATE_TIMEOUT;
- while (time_before(jiffies, timeout)) {
- if (card->channels_tested == TPAM_NBCHANNEL)
- break;
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(2);
- }
-
- card->running = 1;
-
- if (card->channels_tested != TPAM_NBCHANNEL)
- printk(KERN_ERR "TurboPAM(tpam_command_ioctl_dsprun): "
- "card=%d, tried to init %d channels, "
- "got reply from only %d channels\n", card->id,
- TPAM_NBCHANNEL, card->channels_tested);
-
- /* if all the channels were not initialized, signal to the ISDN
- * link layer that fact that some channels are not usable */
- if (card->channels_used != TPAM_NBCHANNEL)
- for (i = card->channels_used; i < TPAM_NBCHANNEL; ++i) {
- ctrl.driver = card->id;
- ctrl.command = ISDN_STAT_DISCH;
- ctrl.arg = i;
- ctrl.parm.num[0] = 0;
- (* card->interface.statcallb)(&ctrl);
- }
-
- printk(KERN_INFO "TurboPAM: card=%d, ready, %d channels available\n",
- card->id, card->channels_used);
-
- /* let's rock ! */
- ctrl.driver = card->id;
- ctrl.command = ISDN_STAT_RUN;
- ctrl.arg = 0;
- tpam_statcallb(card, ctrl);
-
- return 0;
-}
-
-/*
- * Set/reset the board's looptest mode.
- *
- * card: the board
- * mode: if 1, sets the board's looptest mode, if 0 resets it.
- *
- * Return: 0 if OK, <0 if error.
- */
-static int tpam_command_ioctl_loopmode(tpam_card *card, u8 mode) {
-
- /* board must be running */
- if (!card->running)
- return -ENODEV;
-
- card->loopmode = mode;
- return 0;
-}
-
-/*
- * Issue a dial command. This function builds and sends a CConnectReq.
- *
- * card: the board
- * channel: the channel number
- * phone: the remote phone number (EAZ)
- *
- * Return: 0 if OK, <0 if error.
- */
-static int tpam_command_dial(tpam_card *card, u32 channel, u8 *phone) {
- struct sk_buff *skb;
- isdn_ctrl ctrl;
-
- pr_debug("TurboPAM(tpam_command_dial): card=%d, channel=%lu, phone=%s\n",
- card->id, (unsigned long)channel, phone);
-
- /* board must be running */
- if (!card->running)
- return -ENODEV;
-
- /* initialize channel parameters */
- card->channels[channel].realhdlc = card->channels[channel].hdlc;
- card->channels[channel].hdlcshift = 0;
- card->channels[channel].readytoreceive = 0;
-
- /* build and send a CConnectReq */
- skb = build_CConnectReq(card->channels[channel].ncoid, phone,
- card->channels[channel].realhdlc);
- if (!skb)
- return -ENOMEM;
- tpam_enqueue(card, skb);
-
- /* making a connection in modem mode is slow and causes the ISDN
- * link layer to hangup the connection before even it gets a chance
- * to establish... All we can do is simulate a successful connection
- * for now, and send a DHUP later if the connection fails */
- if (!card->channels[channel].realhdlc) {
- ctrl.driver = card->id;
- ctrl.command = ISDN_STAT_DCONN;
- ctrl.arg = channel;
- tpam_statcallb(card, ctrl);
- }
-
- return 0;
-}
-
-/*
- * Set the level2 protocol (modem or HDLC).
- *
- * card: the board
- * channel: the channel number
- * proto: the level2 protocol (one of ISDN_PROTO_L2*)
- *
- * Return: 0 if OK, <0 if error.
- */
-static int tpam_command_setl2(tpam_card *card, u32 channel, u8 proto) {
-
- pr_debug("TurboPAM(tpam_command_setl2): card=%d, channel=%lu, proto=%d\n",
- card->id, (unsigned long)channel, proto);
-
- /* board must be running */
- if (!card->running)
- return -ENODEV;
-
- /* set the hdlc/modem mode */
- switch (proto) {
- case ISDN_PROTO_L2_HDLC:
- card->channels[channel].hdlc = 1;
- break;
- case ISDN_PROTO_L2_MODEM:
- card->channels[channel].hdlc = 0;
- break;
- default:
- return -EINVAL;
- }
- return 0;
-}
-
-/*
- * Accept a D-channel connection (incoming connection). This function
- * builds and sends a CConnectRsp message and signals DCONN to the ISDN
- * link level.
- *
- * card: the board
- * channel: the channel number
- *
- * Return: 0 if OK, <0 if error.
- */
-static int tpam_command_acceptd(tpam_card *card, u32 channel) {
- isdn_ctrl ctrl;
- struct sk_buff *skb;
-
- pr_debug("TurboPAM(tpam_command_acceptd): card=%d, channel=%lu\n",
- card->id, (unsigned long)channel);
-
- /* board must be running */
- if (!card->running)
- return -ENODEV;
-
- /* build and send a CConnectRsp */
- skb = build_CConnectRsp(card->channels[channel].ncoid);
- if (!skb)
- return -ENOMEM;
- tpam_enqueue(card, skb);
-
- /* issue DCONN to the ISDN link level */
- ctrl.driver = card->id;
- ctrl.command = ISDN_STAT_DCONN;
- ctrl.arg = channel;
- tpam_statcallb(card, ctrl);
- return 0;
-}
-
-/*
- * Accepts a B-channel connection. This is not used by the driver,
- * since the TurboPAM is an active card hiding its B-channels from
- * us. We just signal BCONN to the ISDN link layer.
- *
- * card: the board
- * channel: the channel number
- *
- * Return: 0 if OK, <0 if error.
- */
-static int tpam_command_acceptb(tpam_card *card, u32 channel) {
- isdn_ctrl ctrl;
-
- pr_debug("TurboPAM(tpam_command_acceptb): card=%d, channel=%lu\n",
- card->id, (unsigned long)channel);
-
- /* board must be running */
- if (!card->running)
- return -ENODEV;
-
- /* issue BCONN to the ISDN link level */
- ctrl.driver = card->id;
- ctrl.command = ISDN_STAT_BCONN;
- ctrl.arg = channel;
- ctrl.parm.num[0] = '\0';
- tpam_statcallb(card, ctrl);
- return 0;
-}
-
-/*
- * Hang up a connection. This function builds and sends a CDisconnectReq.
- *
- * card: the board
- * channel: the channel number.
- *
- * Return: 0 if OK, <0 if error.
- */
-static int tpam_command_hangup(tpam_card *card, u32 channel) {
- struct sk_buff *skb;
-
- pr_debug("TurboPAM(tpam_command_hangup): card=%d, channel=%lu\n",
- card->id, (unsigned long)channel);
-
- /* board must be running */
- if (!card->running)
- return -ENODEV;
-
- /* build and send a CDisconnectReq */
- skb = build_CDisconnectReq(card->channels[channel].ncoid);
- if (!skb)
- return -ENOMEM;
- tpam_enqueue(card, skb);
- return 0;
-}
-
-/*
- * Proceed with an incoming connection. This function builds and sends a
- * CConnectRsp.
- *
- * card: the board
- * channel: the channel number.
- *
- * Return: 0 if OK, <0 if error.
- */
-static int tpam_command_proceed(tpam_card *card, u32 channel) {
- struct sk_buff *skb;
-
- pr_debug("TurboPAM(tpam_command_proceed): card=%d, channel=%lu\n",
- card->id, (unsigned long)channel);
-
- /* board must be running */
- if (!card->running)
- return -ENODEV;
-
- /* build and send a CConnectRsp */
- skb = build_CConnectRsp(card->channels[channel].ncoid);
- if (!skb)
- return -ENOMEM;
- tpam_enqueue(card, skb);
- return 0;
-}
-
-/*
- * Send data through the board. This function encodes the data depending
- * on the connection type (modem or HDLC), then builds and sends a U3DataReq.
- *
- * driverId: the driver id (really meaning here the board)
- * channel: the channel number
- * ack: data needs to be acknowledged upon send
- * skb: sk_buff containing the data
- *
- * Return: size of data send if OK, <0 if error.
- */
-int tpam_writebuf_skb(int driverId, int channel, int ack, struct sk_buff *skb) {
- tpam_card *card;
- int orig_size = skb->len;
- void *finaldata;
- u32 finallen;
-
- pr_debug("TurboPAM(tpam_writebuf_skb): "
- "card=%d, channel=%ld, ack=%d, data size=%d\n",
- driverId, (unsigned long)channel, ack, skb->len);
-
- /* find the board based on its driver ID */
- if (!(card = tpam_findcard(driverId))) {
- printk(KERN_ERR "TurboPAM(tpam_writebuf_skb): "
- "invalid driverId %d\n", driverId);
- return -ENODEV;
- }
-
- /* board must be running */
- if (!card->running)
- return -ENODEV;
-
- /* allocate some temporary memory */
- if (!(finaldata = (void *)__get_free_page(GFP_ATOMIC))) {
- printk(KERN_ERR "TurboPAM(tpam_writebuf_skb): "
- "get_free_page failed\n");
- return -ENOMEM;
- }
-
- /* encode the data */
- if (!card->channels[channel].realhdlc) {
- /* modem mode */
- hdlc_encode_modem(skb->data, skb->len, finaldata, &finallen);
- }
- else {
- /* HDLC mode */
- void *tempdata;
- u32 templen;
-
- if (!(tempdata = (void *)__get_free_page(GFP_ATOMIC))) {
- printk(KERN_ERR "TurboPAM(tpam_writebuf_skb): "
- "get_free_page failed\n");
- free_page((unsigned long)finaldata);
- return -ENOMEM;
- }
- hdlc_no_accm_encode(skb->data, skb->len, tempdata, &templen);
- finallen = tpam_hdlc_encode(tempdata, finaldata,
- &card->channels[channel].hdlcshift,
- templen);
- free_page((unsigned long)tempdata);
- }
-
- /* free the old sk_buff */
- kfree_skb(skb);
-
- /* build and send a U3DataReq */
- skb = build_U3DataReq(card->channels[channel].ncoid, finaldata,
- finallen, ack, orig_size);
- if (!skb) {
- free_page((unsigned long)finaldata);
- return -ENOMEM;
- }
- tpam_enqueue_data(&card->channels[channel], skb);
-
- /* free the temporary memory */
- free_page((unsigned long)finaldata);
- return orig_size;
-}
-
-/*
- * Treat a received ACreateNCOCnf message.
- *
- * card: the board
- * skb: the received message
- */
-void tpam_recv_ACreateNCOCnf(tpam_card *card, struct sk_buff *skb) {
- u32 ncoid;
- u8 status;
- u32 channel;
-
- pr_debug("TurboPAM(tpam_recv_ACreateNCOCnf): card=%d\n", card->id);
-
- /* parse the message contents */
- if (parse_ACreateNCOCnf(skb, &status, &ncoid))
- return;
-
- /* if the card is alreay running, it means that this message
- * arrives too late... */
- if (card->running) {
- printk(KERN_ERR "TurboPAM(tpam_recv_ACreateNCOCnf): "
- "ACreateNCOCnf received too late, status=%d\n", status);
- return;
- }
-
- /* the NCO creation failed, the corresponding channel will
- * be unused */
- if (status) {
- printk(KERN_ERR "TurboPAM(tpam_recv_ACreateNCOCnf): "
- "ACreateNCO failed, status=%d\n", status);
- card->channels_tested++;
- return;
- }
-
- /* find the first free channel and assign the nco ID to it */
- if ((channel = tpam_findchannel(card, TPAM_NCOID_INVALID)) == TPAM_CHANNEL_INVALID) {
- printk(KERN_ERR "TurboPAM(tpam_recv_ACreateNCOCnf): "
- "All channels are assigned\n");
- return;
- }
- card->channels[channel].ncoid = ncoid;
- card->channels_tested++;
- card->channels_used++;
-}
-
-/*
- * Treat a received ADestroyNCOCnf message. Not used by the driver.
- *
- * card: the board
- * skb: the received message
- */
-void tpam_recv_ADestroyNCOCnf(tpam_card *card, struct sk_buff *skb) {
- u32 ncoid;
- u8 status;
- u32 channel;
-
- pr_debug("TurboPAM(tpam_recv_ADestroyNCOCnf): card=%d\n", card->id);
-
- /* parse the message contents */
- if (parse_ADestroyNCOCnf(skb, &status, &ncoid))
- return;
-
- if (status) {
- printk(KERN_ERR "TurboPAM(tpam_recv_ADestroyNCOCnf): "
- "ADestroyNCO failed, status=%d\n", status);
- return;
- }
-
- /* clears the channel's nco ID */
- if ((channel = tpam_findchannel(card, ncoid)) == TPAM_CHANNEL_INVALID) {
- printk(KERN_ERR "TurboPAM(tpam_recv_ADestroyNCOCnf): "
- "ncoid invalid %lu\n", (unsigned long)ncoid);
- return;
- }
-
- card->channels[channel].ncoid = TPAM_NCOID_INVALID;
-}
-
-/*
- * Treat a received CConnectCnf message.
- *
- * card: the board
- * skb: the received message
- */
-void tpam_recv_CConnectCnf(tpam_card *card, struct sk_buff *skb) {
- u32 ncoid;
- u32 channel;
- isdn_ctrl ctrl;
-
- pr_debug("TurboPAM(tpam_recv_CConnectCnf): card=%d\n", card->id);
-
- /* parse the message contents */
- if (parse_CConnectCnf(skb, &ncoid))
- return;
-
- /* find the channel by its nco ID */
- if ((channel = tpam_findchannel(card, ncoid)) == TPAM_CHANNEL_INVALID) {
- printk(KERN_ERR "TurboPAM(tpam_recv_CConnectCnf): "
- "ncoid invalid %lu\n", (unsigned long)ncoid);
- return;
- }
-
- /* issue a DCONN command to the ISDN link layer if we are in HDLC mode.
- * In modem mode, we alreay did it - the ISDN timer kludge */
- if (card->channels[channel].realhdlc) {
- ctrl.driver = card->id;
- ctrl.command = ISDN_STAT_DCONN;
- ctrl.arg = channel;
- (* card->interface.statcallb)(&ctrl);
- }
-}
-
-/*
- * Treat a received CConnectInd message. This function signals a ICALL
- * to the ISDN link layer.
- *
- * card: the board
- * skb: the received message
- */
-void tpam_recv_CConnectInd(tpam_card *card, struct sk_buff *skb) {
- u32 ncoid;
- u32 channel;
- u8 hdlc, plan, screen;
- u8 calling[PHONE_MAXIMUMSIZE], called[PHONE_MAXIMUMSIZE];
- isdn_ctrl ctrl;
- int status;
-
- pr_debug("TurboPAM(tpam_recv_CConnectInd): card=%d\n", card->id);
-
- /* parse the message contents */
- if (parse_CConnectInd(skb, &ncoid, &hdlc, calling, called, &plan, &screen))
- return;
-
- /* find the channel by its nco ID */
- if ((channel = tpam_findchannel(card, ncoid)) == TPAM_CHANNEL_INVALID) {
- printk(KERN_ERR "TurboPAM(tpam_recv_CConnectInd): "
- "ncoid invalid %lu\n", (unsigned long)ncoid);
- return;
- }
-
- /* initialize the channel parameters */
- card->channels[channel].realhdlc = hdlc;
- card->channels[channel].hdlcshift = 0;
- card->channels[channel].readytoreceive = 0;
-
- /* issue a ICALL command to the ISDN link layer */
- ctrl.driver = card->id;
- ctrl.command = ISDN_STAT_ICALL;
- ctrl.arg = channel;
- memcpy(ctrl.parm.setup.phone, calling, 32);
- memcpy(ctrl.parm.setup.eazmsn, called, 32);
- ctrl.parm.setup.si1 = 7; /* data capability */
- ctrl.parm.setup.si2 = 0;
- ctrl.parm.setup.plan = plan;
- ctrl.parm.setup.screen = screen;
-
- status = (* card->interface.statcallb)(&ctrl);
- switch (status) {
- case 1:
- case 4:
- /* call accepted, link layer will send us a ACCEPTD
- * command later */
- pr_debug("TurboPAM(tpam_recv_CConnectInd): "
- "card=%d, channel=%d, icall waiting, status=%d\n",
- card->id, channel, status);
- break;
- default:
- /* call denied, we build and send a CDisconnectReq */
- pr_debug("TurboPAM(tpam_recv_CConnectInd): "
- "card=%d, channel=%d, icall denied, status=%d\n",
- card->id, channel, status);
- skb = build_CDisconnectReq(ncoid);
- if (!skb)
- return;
- tpam_enqueue(card, skb);
- }
-}
-
-/*
- * Treat a received CDisconnectInd message. This function signals a DHUP and
- * a BHUP to the ISDN link layer.
- *
- * card: the board
- * skb: the received message
- */
-void tpam_recv_CDisconnectInd(tpam_card *card, struct sk_buff *skb) {
- u32 ncoid;
- u32 channel;
- u32 cause;
- isdn_ctrl ctrl;
-
- pr_debug("TurboPAM(tpam_recv_CDisconnectInd): card=%d\n", card->id);
-
- /* parse the message contents */
- if (parse_CDisconnectInd(skb, &ncoid, &cause))
- return;
-
- /* find the channel by its nco ID */
- if ((channel = tpam_findchannel(card, ncoid)) == TPAM_CHANNEL_INVALID) {
- printk(KERN_ERR "TurboPAM(tpam_recv_CDisconnectInd): "
- "ncoid invalid %lu\n", (unsigned long)ncoid);
- return;
- }
-
- /* build and send a CDisconnectRsp */
- skb = build_CDisconnectRsp(ncoid);
- if (!skb)
- return;
- tpam_enqueue(card, skb);
-
- /* issue a DHUP to the ISDN link layer */
- ctrl.driver = card->id;
- ctrl.command = ISDN_STAT_DHUP;
- ctrl.arg = channel;
- (* card->interface.statcallb)(&ctrl);
-
- /* issue a BHUP to the ISDN link layer */
- ctrl.driver = card->id;
- ctrl.command = ISDN_STAT_BHUP;
- ctrl.arg = channel;
- (* card->interface.statcallb)(&ctrl);
-}
-
-/*
- * Treat a received CDisconnectCnf message. This function signals a DHUP and
- * a BHUP to the ISDN link layer.
- *
- * card: the board
- * skb: the received message
- */
-void tpam_recv_CDisconnectCnf(tpam_card *card, struct sk_buff *skb) {
- u32 ncoid;
- u32 channel;
- u32 cause;
- isdn_ctrl ctrl;
-
- pr_debug("TurboPAM(tpam_recv_CDisconnectCnf): card=%d\n", card->id);
-
- /* parse the message contents */
- if (parse_CDisconnectCnf(skb, &ncoid, &cause))
- return;
-
- /* find the channel by its nco ID */
- if ((channel = tpam_findchannel(card, ncoid)) == TPAM_CHANNEL_INVALID) {
- printk(KERN_ERR "TurboPAM(tpam_recv_CDisconnectCnf): "
- "ncoid invalid %lu\n", (unsigned long)ncoid);
- return;
- }
-
- /* issue a DHUP to the ISDN link layer */
- ctrl.driver = card->id;
- ctrl.command = ISDN_STAT_DHUP;
- ctrl.arg = channel;
- (* card->interface.statcallb)(&ctrl);
-
- /* issue a BHUP to the ISDN link layer */
- ctrl.driver = card->id;
- ctrl.command = ISDN_STAT_BHUP;
- ctrl.arg = channel;
- (* card->interface.statcallb)(&ctrl);
-}
-
-/*
- * Treat a received U3DataInd message. This function decodes the data
- * depending on the connection type (modem or HDLC) and passes it to the
- * ISDN link layer by using rcvcallb_skb.
- *
- * card: the board
- * skb: the received message + data
- */
-void tpam_recv_U3DataInd(tpam_card *card, struct sk_buff *skb) {
- u32 ncoid;
- u32 channel;
- u8 *data;
- u16 len;
- struct sk_buff *result;
-
- pr_debug("TurboPAM(tpam_recv_U3DataInd): card=%d, datalen=%d\n",
- card->id, skb->len);
-
- /* parse the message contents */
- if (parse_U3DataInd(skb, &ncoid, &data, &len))
- return;
-
- /* find the channel by its nco ID */
- if ((channel = tpam_findchannel(card, ncoid)) == TPAM_CHANNEL_INVALID) {
- printk(KERN_ERR "TurboPAM(tpam_recv_U3DataInd): "
- "ncoid invalid %lu\n", (unsigned long)ncoid);
- return;
- }
-
- /* decode the data */
- if (card->channels[ncoid].realhdlc) {
- /* HDLC mode */
- u8 *tempdata;
- u32 templen;
-
- if (!(tempdata = (void *)__get_free_page(GFP_ATOMIC))) {
- printk(KERN_ERR "TurboPAM(tpam_recv_U3DataInd): "
- "get_free_page failed\n");
- return;
- }
- templen = tpam_hdlc_decode(data, tempdata, len);
- templen = hdlc_no_accm_decode(tempdata, templen);
- if (!(result = alloc_skb(templen, GFP_ATOMIC))) {
- printk(KERN_ERR "TurboPAM(tpam_recv_U3DataInd): "
- "alloc_skb failed\n");
- free_page((unsigned long)tempdata);
- return;
- }
- memcpy(skb_put(result, templen), tempdata, templen);
- free_page((unsigned long)tempdata);
- }
- else {
- /* modem mode */
- if (!(result = alloc_skb(len, GFP_ATOMIC))) {
- printk(KERN_ERR "TurboPAM(tpam_recv_U3DataInd): "
- "alloc_skb failed\n");
- return;
- }
- memcpy(skb_put(result, len), data, len);
- }
-
- /* In loop mode, resend the data immediately */
- if (card->loopmode) {
- struct sk_buff *loopskb;
-
- if (!(loopskb = alloc_skb(skb->len, GFP_ATOMIC))) {
- printk(KERN_ERR "TurboPAM(tpam_recv_U3DataInd): "
- "alloc_skb failed\n");
- kfree_skb(result);
- return;
- }
- memcpy(skb_put(loopskb, result->len), result->data,
- result->len);
- if (tpam_writebuf_skb(card->id, channel, 0, loopskb) < 0)
- kfree_skb(loopskb);
- }
-
- /* pass the data to the ISDN link layer */
- (* card->interface.rcvcallb_skb)(card->id, channel, result);
-}
-
-/*
- * Treat a received U3ReadyToReceiveInd message. This function sets the
- * channel ready flag and triggers the send of data if the channel becomed
- * ready.
- *
- * card: the board
- * skb: the received message + data
- */
-void tpam_recv_U3ReadyToReceiveInd(tpam_card *card, struct sk_buff *skb) {
- u32 ncoid;
- u32 channel;
- u8 ready;
-
- pr_debug("TurboPAM(tpam_recv_U3ReadyToReceiveInd): card=%d\n", card->id);
-
- /* parse the message contents */
- if (parse_U3ReadyToReceiveInd(skb, &ncoid, &ready))
- return;
-
- /* find the channel by its nco ID */
- if ((channel = tpam_findchannel(card, ncoid)) == TPAM_CHANNEL_INVALID) {
- printk(KERN_ERR "TurboPAM(tpam_recv_U3ReadyToReceiveInd): "
- "ncoid invalid %lu\n", (unsigned long)ncoid);
- return;
- }
-
- /* set the readytoreceive flag */
- card->channels[channel].readytoreceive = ready;
-
- /* if the channel just becomed ready, trigger the send of queued data */
- if (ready)
- tpam_enqueue_data(&card->channels[channel], NULL);
-}
-
-/*
- * Runs the delayed statcallb when its timer expires.
- *
- * parm: pointer to the tpam_statcallb_data statcallb argument.
- */
-static void tpam_statcallb_run(unsigned long parm) {
- tpam_statcallb_data *ds = (tpam_statcallb_data *)parm;
-
- pr_debug("TurboPAM(tpam_statcallb_run)\n");
-
- (* ds->card->interface.statcallb)(&ds->ctrl);
-
- kfree(ds->timer);
- kfree(ds);
-}
-
-/*
- * Queues a statcallb call for delayed invocation.
- *
- * card: the board
- * ctrl: the statcallb argument
- */
-static void tpam_statcallb(tpam_card *card, isdn_ctrl ctrl) {
- struct timer_list *timer;
- tpam_statcallb_data *ds;
-
- pr_debug("TurboPAM(tpam_statcallb): card=%d\n", card->id);
-
- if (!(timer = (struct timer_list *) kmalloc(sizeof(struct timer_list),
- GFP_ATOMIC))) {
- printk(KERN_ERR "TurboPAM: tpam_statcallb: kmalloc failed!\n");
- return;
- }
-
- if (!(ds = (tpam_statcallb_data *) kmalloc(sizeof(tpam_statcallb_data),
- GFP_ATOMIC))) {
- printk(KERN_ERR "TurboPAM: tpam_statcallb: kmalloc failed!\n");
- kfree(timer);
- return;
- }
- ds->card = card;
- ds->timer = timer;
- memcpy(&ds->ctrl, &ctrl, sizeof(isdn_ctrl));
-
- init_timer(timer);
- timer->function = tpam_statcallb_run;
- timer->data = (unsigned long)ds;
- timer->expires = jiffies + HZ / 10; /* 0.1 second */
- add_timer(timer);
-}
diff --git a/drivers/isdn/tpam/tpam_crcpc.c b/drivers/isdn/tpam/tpam_crcpc.c
deleted file mode 100644
index fae8df7ae1365..0000000000000
--- a/drivers/isdn/tpam/tpam_crcpc.c
+++ /dev/null
@@ -1,162 +0,0 @@
-/* $Id: tpam_crcpc.c,v 1.1.2.2 2001/09/23 22:25:03 kai Exp $
- *
- * Turbo PAM ISDN driver for Linux. (Kernel Driver - CRC encoding)
- *
- * Copyright 1998-2000 AUVERTECH Télécom
- * Copyright 2001 Stelian Pop <stelian.pop@fr.alcove.com>, Alcôve
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- * For all support questions please contact: <support@auvertech.fr>
- *
- */
-
-/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
-Module Name:
-
- crcpc.c
-
-Abstract:
-
- Modem HDLC coding
- Software HDLC coding / decoding
-
-Revision History:
-
----------------------------------------------------------------------------*/
-
-#include <linux/crc-ccitt.h>
-#include "tpam.h"
-
-#define HDLC_CTRL_CHAR_CMPL_MASK 0x20 /* HDLC control character complement mask */
-#define HDLC_FLAG 0x7E /* HDLC flag */
-#define HDLC_CTRL_ESC 0x7D /* HDLC control escapr character */
-#define HDLC_LIKE_FCS_INIT_VAL 0xFFFF /* FCS initial value (0xFFFF for new equipment or 0) */
-#define HDLC_FCS_OK 0xF0B8 /* This value is the only valid value of FCS */
-
-#define TRUE 1
-#define FALSE 0
-
-static u8 ap_t_ctrl_char_complemented[256]; /* list of characters to complement */
-
-static void ap_hdlc_like_ctrl_char_list (u32 ctrl_char) {
- int i;
-
- for (i = 0; i < 256; ++i)
- ap_t_ctrl_char_complemented[i] = FALSE;
- for (i = 0; i < 32; ++i)
- if ((ctrl_char >> i) & 0x0001)
- ap_t_ctrl_char_complemented [i] = TRUE;
- ap_t_ctrl_char_complemented[HDLC_FLAG] = TRUE;
- ap_t_ctrl_char_complemented[HDLC_CTRL_ESC] = TRUE;
-
-}
-
-void init_CRC(void) {
- ap_hdlc_like_ctrl_char_list(0xffffffff);
-}
-
-void hdlc_encode_modem(u8 *buffer_in, u32 lng_in,
- u8 *buffer_out, u32 *lng_out) {
- u16 fcs;
- register u8 data;
- register u8 *p_data_out = buffer_out;
-
- fcs = HDLC_LIKE_FCS_INIT_VAL;
-
- /*
- * Insert HDLC flag at the beginning of the frame
- */
- *p_data_out++ = HDLC_FLAG;
-
-#define ESCAPE_CHAR(data_out, data) \
- if (ap_t_ctrl_char_complemented[data]) { \
- *data_out++ = HDLC_CTRL_ESC; \
- *data_out++ = data ^ 0x20; \
- } \
- else \
- *data_out++ = data;
-
- while (lng_in--) {
- data = *buffer_in++;
-
- /*
- * FCS calculation
- */
- fcs = crc_ccitt_byte(fcs, data);
-
- ESCAPE_CHAR(p_data_out, data);
- }
-
- /*
- * Add FCS and closing flag
- */
- fcs ^= 0xFFFF; // Complement
-
- data = (u8)(fcs & 0xff); /* LSB */
- ESCAPE_CHAR(p_data_out, data);
-
- data = (u8)((fcs >> 8)); /* MSB */
- ESCAPE_CHAR(p_data_out, data);
-#undef ESCAPE_CHAR
-
- *p_data_out++ = HDLC_FLAG;
-
- *lng_out = (u32)(p_data_out - buffer_out);
-}
-
-void hdlc_no_accm_encode(u8 *buffer_in, u32 lng_in,
- u8 *buffer_out, u32 *lng_out) {
- u16 fcs;
- register u8 data;
- register u8 *p_data_out = buffer_out;
-
- /*
- * Insert HDLC flag at the beginning of the frame
- */
- fcs = HDLC_LIKE_FCS_INIT_VAL;
-
- while (lng_in--) {
- data = *buffer_in++;
- /* calculate FCS */
- fcs = crc_ccitt_byte(fcs, data);
- *p_data_out++ = data;
- }
-
- /*
- * Add FCS and closing flag
- */
- fcs ^= 0xFFFF; // Complement
- data = (u8)(fcs);
- *p_data_out++ = data;
-
- data =(u8)((fcs >> 8)); // revense MSB / LSB
- *p_data_out++ = data;
-
- *lng_out = (u32)(p_data_out - buffer_out);
-}
-
-u32 hdlc_no_accm_decode(u8 *buffer_in, u32 lng_in) {
- u16 fcs;
- u32 lng = lng_in;
- register u8 data;
-
- /*
- * Insert HDLC flag at the beginning of the frame
- */
- fcs = HDLC_LIKE_FCS_INIT_VAL;
-
- while (lng_in--) {
- data = *buffer_in++;
- /* calculate FCS */
- fcs = crc_ccitt_byte(fcs, data);
- }
-
- if (fcs == HDLC_FCS_OK)
- return (lng-2);
- else
- return 0;
-}
-
diff --git a/drivers/isdn/tpam/tpam_hdlc.c b/drivers/isdn/tpam/tpam_hdlc.c
deleted file mode 100644
index 1fec4b8e53b16..0000000000000
--- a/drivers/isdn/tpam/tpam_hdlc.c
+++ /dev/null
@@ -1,923 +0,0 @@
-/* $Id: tpam_hdlc.c,v 1.1.2.3 2001/11/06 20:58:30 kai Exp $
- *
- * Turbo PAM ISDN driver for Linux. (Kernel Driver - HDLC encoding)
- *
- * Copyright 1998-2000 AUVERTECH Télécom
- * Copyright 2001 Stelian Pop <stelian.pop@fr.alcove.com>, Alcôve
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- * For all support questions please contact: <support@auvertech.fr>
- *
- */
-
-/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
-Module Name:
-
- hdlc.c
-
-Abstract:
-
- stuff0 : array necessary for the bit stuffing algorithm
- stuff1 : array necessary for the bit stuffing algorithm
- stuff2 : array necessary for the bit stuffing algorithm
- stuff3 : array necessary for the bit stuffing algorithm
- stuff4 : array necessary for the bit stuffing algorithm
- stuff5 : array necessary for the bit stuffing algorithm
- stuffs[] : array conaining the previous 6 arrays
- destuff0 : array necessary for the bit destuffing algorithm
- destuff1 : array necessary for the bit destuffing algorithm
- destuff2 : array necessary for the bit destuffing algorithm
- destuff3 : array necessary for the bit destuffing algorithm
- destuff4 : array necessary for the bit destuffing algorithm
- destuff5 : array necessary for the bit destuffing algorithm
- destuffs[] : array conaining the previous 6 arrays
-
- tpam_hdlc_encode : bit stuffing of a byte array, with the addition
- of a start and end flag, using the bit shift given in
- parameter (which is updated at the end of encoding).
- tpam_hdlc_decode : bit de-stuffing of a byte array with detection of
- possible ABORTs.
-
-Revision History:
-
----------------------------------------------------------------------------*/
-
-/* The arrays are used as follows:
-
- For the bit stuffing :
-
- stuff0 = used if the previous byte ended with '0'
- stuff1 = used if the previous byte ended with '10'
- stuff2 = used if the previous byte ended with '110'
- stuff3 = used if the previous byte ended with '1110'
- stuff4 = used if the previous byte ended with '11110'
- stuff5 = used if the previous byte ended with '111110'
-
- those arrays are indexed by the byte to stuff.
-
- the data of those arrays are of the form (in binary):
- "bbbbaaaa cccccccc"
- with "cccccccc" : byte stuffed
- "aaaa" : "0000" --> no insertion of '0'
- "0100" --> 1 '0' inserted, carry = '0'
- "0101" --> 1 '0' inserted, carry = '1'
- "1000" --> 2 '0' inserted, carry = '00'
- "1001" --> 2 '0' inserted, carry = '01'
- "1010" --> 2 '0' inserted, carry = '10'
- "1011" --> 2 '0' inserted, carry = '11'
- "bbbb" : count of '1' at the end of "cccccccc"
-
-
-
- For the bit de-stuffing :
-
- destuff0 = used if the previous byte ended with '0'
- destuff1 = used if the previous byte ended with '10'
- destuff2 = used if the previous byte ended with '110'
- destuff3 = used if the previous byte ended with '1110'
- destuff4 = used if the previous byte ended with '11110'
- destuff5 = used if the previous byte ended with '111110'
-
- those arrays are indexed by the byte to de-stuff.
-
- the data of those arrays are of the form (in binary):
- "dbbbaaaa cccccccc"
- with "cccccccc" : byte destuffed
- "aaaa" : count of '1' at the end of the byte non destuffed
- "bbb" : count of bits to use in the destuffed byte (8 less the count
- of '0' deleted) less 1 (can be only 7, 6 or 5)
- "d" : '1' if the byte non destuffed has more than 5 consecutive '1'
- (flag or abort)
-*/
-
-#include <linux/types.h>
-#include "tpam.h"
-
-typedef u8 BYTE;
-typedef u16 WORD;
-typedef u32 DWORD;
-typedef u8 BOOL;
-
-#define TRUE 1
-#define FALSE 0
-
-static WORD stuff0[] =
-{
- 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
- 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
- 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
- 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x041F,
- 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
- 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
- 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
- 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x043E, 0x045F,
- 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
- 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
- 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
- 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x149F,
- 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
- 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
- 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
- 0x0078, 0x0079, 0x007A, 0x007B, 0x047C, 0x047D, 0x14BE, 0x24DF,
- 0x1080, 0x1081, 0x1082, 0x1083, 0x1084, 0x1085, 0x1086, 0x1087,
- 0x1088, 0x1089, 0x108A, 0x108B, 0x108C, 0x108D, 0x108E, 0x108F,
- 0x1090, 0x1091, 0x1092, 0x1093, 0x1094, 0x1095, 0x1096, 0x1097,
- 0x1098, 0x1099, 0x109A, 0x109B, 0x109C, 0x109D, 0x109E, 0x051F,
- 0x10A0, 0x10A1, 0x10A2, 0x10A3, 0x10A4, 0x10A5, 0x10A6, 0x10A7,
- 0x10A8, 0x10A9, 0x10AA, 0x10AB, 0x10AC, 0x10AD, 0x10AE, 0x10AF,
- 0x10B0, 0x10B1, 0x10B2, 0x10B3, 0x10B4, 0x10B5, 0x10B6, 0x10B7,
- 0x10B8, 0x10B9, 0x10BA, 0x10BB, 0x10BC, 0x10BD, 0x053E, 0x055F,
- 0x20C0, 0x20C1, 0x20C2, 0x20C3, 0x20C4, 0x20C5, 0x20C6, 0x20C7,
- 0x20C8, 0x20C9, 0x20CA, 0x20CB, 0x20CC, 0x20CD, 0x20CE, 0x20CF,
- 0x20D0, 0x20D1, 0x20D2, 0x20D3, 0x20D4, 0x20D5, 0x20D6, 0x20D7,
- 0x20D8, 0x20D9, 0x20DA, 0x20DB, 0x20DC, 0x20DD, 0x20DE, 0x159F,
- 0x30E0, 0x30E1, 0x30E2, 0x30E3, 0x30E4, 0x30E5, 0x30E6, 0x30E7,
- 0x30E8, 0x30E9, 0x30EA, 0x30EB, 0x30EC, 0x30ED, 0x30EE, 0x30EF,
- 0x40F0, 0x40F1, 0x40F2, 0x40F3, 0x40F4, 0x40F5, 0x40F6, 0x40F7,
- 0x50F8, 0x50F9, 0x50FA, 0x50FB, 0x057C, 0x057D, 0x15BE, 0x25DF,
-};
-
-
-static WORD stuff1[] =
-{
- 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
- 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x040F,
- 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
- 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x042F,
- 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
- 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x044F,
- 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
- 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x043E, 0x046F,
- 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
- 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x148F,
- 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
- 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x14AF,
- 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
- 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x24CF,
- 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
- 0x0078, 0x0079, 0x007A, 0x007B, 0x047C, 0x047D, 0x14BE, 0x34EF,
- 0x1080, 0x1081, 0x1082, 0x1083, 0x1084, 0x1085, 0x1086, 0x1087,
- 0x1088, 0x1089, 0x108A, 0x108B, 0x108C, 0x108D, 0x108E, 0x050F,
- 0x1090, 0x1091, 0x1092, 0x1093, 0x1094, 0x1095, 0x1096, 0x1097,
- 0x1098, 0x1099, 0x109A, 0x109B, 0x109C, 0x109D, 0x109E, 0x052F,
- 0x10A0, 0x10A1, 0x10A2, 0x10A3, 0x10A4, 0x10A5, 0x10A6, 0x10A7,
- 0x10A8, 0x10A9, 0x10AA, 0x10AB, 0x10AC, 0x10AD, 0x10AE, 0x054F,
- 0x10B0, 0x10B1, 0x10B2, 0x10B3, 0x10B4, 0x10B5, 0x10B6, 0x10B7,
- 0x10B8, 0x10B9, 0x10BA, 0x10BB, 0x10BC, 0x10BD, 0x053E, 0x056F,
- 0x20C0, 0x20C1, 0x20C2, 0x20C3, 0x20C4, 0x20C5, 0x20C6, 0x20C7,
- 0x20C8, 0x20C9, 0x20CA, 0x20CB, 0x20CC, 0x20CD, 0x20CE, 0x158F,
- 0x20D0, 0x20D1, 0x20D2, 0x20D3, 0x20D4, 0x20D5, 0x20D6, 0x20D7,
- 0x20D8, 0x20D9, 0x20DA, 0x20DB, 0x20DC, 0x20DD, 0x20DE, 0x15AF,
- 0x30E0, 0x30E1, 0x30E2, 0x30E3, 0x30E4, 0x30E5, 0x30E6, 0x30E7,
- 0x30E8, 0x30E9, 0x30EA, 0x30EB, 0x30EC, 0x30ED, 0x30EE, 0x25CF,
- 0x40F0, 0x40F1, 0x40F2, 0x40F3, 0x40F4, 0x40F5, 0x40F6, 0x40F7,
- 0x50F8, 0x50F9, 0x50FA, 0x50FB, 0x057C, 0x057D, 0x15BE, 0x35EF,
-};
-
-
-static WORD stuff2[] =
-{
- 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0407,
- 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x0417,
- 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0427,
- 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x0437,
- 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0447,
- 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x0457,
- 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0467,
- 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x043E, 0x0477,
- 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x1487,
- 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x1497,
- 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x14A7,
- 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x14B7,
- 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x24C7,
- 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x24D7,
- 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x34E7,
- 0x0078, 0x0079, 0x007A, 0x007B, 0x047C, 0x047D, 0x14BE, 0x44F7,
- 0x1080, 0x1081, 0x1082, 0x1083, 0x1084, 0x1085, 0x1086, 0x0507,
- 0x1088, 0x1089, 0x108A, 0x108B, 0x108C, 0x108D, 0x108E, 0x0517,
- 0x1090, 0x1091, 0x1092, 0x1093, 0x1094, 0x1095, 0x1096, 0x0527,
- 0x1098, 0x1099, 0x109A, 0x109B, 0x109C, 0x109D, 0x109E, 0x0537,
- 0x10A0, 0x10A1, 0x10A2, 0x10A3, 0x10A4, 0x10A5, 0x10A6, 0x0547,
- 0x10A8, 0x10A9, 0x10AA, 0x10AB, 0x10AC, 0x10AD, 0x10AE, 0x0557,
- 0x10B0, 0x10B1, 0x10B2, 0x10B3, 0x10B4, 0x10B5, 0x10B6, 0x0567,
- 0x10B8, 0x10B9, 0x10BA, 0x10BB, 0x10BC, 0x10BD, 0x053E, 0x0577,
- 0x20C0, 0x20C1, 0x20C2, 0x20C3, 0x20C4, 0x20C5, 0x20C6, 0x1587,
- 0x20C8, 0x20C9, 0x20CA, 0x20CB, 0x20CC, 0x20CD, 0x20CE, 0x1597,
- 0x20D0, 0x20D1, 0x20D2, 0x20D3, 0x20D4, 0x20D5, 0x20D6, 0x15A7,
- 0x20D8, 0x20D9, 0x20DA, 0x20DB, 0x20DC, 0x20DD, 0x20DE, 0x15B7,
- 0x30E0, 0x30E1, 0x30E2, 0x30E3, 0x30E4, 0x30E5, 0x30E6, 0x25C7,
- 0x30E8, 0x30E9, 0x30EA, 0x30EB, 0x30EC, 0x30ED, 0x30EE, 0x25D7,
- 0x40F0, 0x40F1, 0x40F2, 0x40F3, 0x40F4, 0x40F5, 0x40F6, 0x35E7,
- 0x50F8, 0x50F9, 0x50FA, 0x50FB, 0x057C, 0x057D, 0x15BE, 0x45F7,
-};
-
-
-static WORD stuff3[] =
-{
- 0x0000, 0x0001, 0x0002, 0x0403, 0x0004, 0x0005, 0x0006, 0x040B,
- 0x0008, 0x0009, 0x000A, 0x0413, 0x000C, 0x000D, 0x000E, 0x041B,
- 0x0010, 0x0011, 0x0012, 0x0423, 0x0014, 0x0015, 0x0016, 0x042B,
- 0x0018, 0x0019, 0x001A, 0x0433, 0x001C, 0x001D, 0x001E, 0x043B,
- 0x0020, 0x0021, 0x0022, 0x0443, 0x0024, 0x0025, 0x0026, 0x044B,
- 0x0028, 0x0029, 0x002A, 0x0453, 0x002C, 0x002D, 0x002E, 0x045B,
- 0x0030, 0x0031, 0x0032, 0x0463, 0x0034, 0x0035, 0x0036, 0x046B,
- 0x0038, 0x0039, 0x003A, 0x0473, 0x003C, 0x003D, 0x043E, 0x047B,
- 0x0040, 0x0041, 0x0042, 0x1483, 0x0044, 0x0045, 0x0046, 0x148B,
- 0x0048, 0x0049, 0x004A, 0x1493, 0x004C, 0x004D, 0x004E, 0x149B,
- 0x0050, 0x0051, 0x0052, 0x14A3, 0x0054, 0x0055, 0x0056, 0x14AB,
- 0x0058, 0x0059, 0x005A, 0x14B3, 0x005C, 0x005D, 0x005E, 0x14BB,
- 0x0060, 0x0061, 0x0062, 0x24C3, 0x0064, 0x0065, 0x0066, 0x24CB,
- 0x0068, 0x0069, 0x006A, 0x24D3, 0x006C, 0x006D, 0x006E, 0x24DB,
- 0x0070, 0x0071, 0x0072, 0x34E3, 0x0074, 0x0075, 0x0076, 0x34EB,
- 0x0078, 0x0079, 0x007A, 0x44F3, 0x047C, 0x047D, 0x14BE, 0x54FB,
- 0x1080, 0x1081, 0x1082, 0x0503, 0x1084, 0x1085, 0x1086, 0x050B,
- 0x1088, 0x1089, 0x108A, 0x0513, 0x108C, 0x108D, 0x108E, 0x051B,
- 0x1090, 0x1091, 0x1092, 0x0523, 0x1094, 0x1095, 0x1096, 0x052B,
- 0x1098, 0x1099, 0x109A, 0x0533, 0x109C, 0x109D, 0x109E, 0x053B,
- 0x10A0, 0x10A1, 0x10A2, 0x0543, 0x10A4, 0x10A5, 0x10A6, 0x054B,
- 0x10A8, 0x10A9, 0x10AA, 0x0553, 0x10AC, 0x10AD, 0x10AE, 0x055B,
- 0x10B0, 0x10B1, 0x10B2, 0x0563, 0x10B4, 0x10B5, 0x10B6, 0x056B,
- 0x10B8, 0x10B9, 0x10BA, 0x0573, 0x10BC, 0x10BD, 0x053E, 0x057B,
- 0x20C0, 0x20C1, 0x20C2, 0x1583, 0x20C4, 0x20C5, 0x20C6, 0x158B,
- 0x20C8, 0x20C9, 0x20CA, 0x1593, 0x20CC, 0x20CD, 0x20CE, 0x159B,
- 0x20D0, 0x20D1, 0x20D2, 0x15A3, 0x20D4, 0x20D5, 0x20D6, 0x15AB,
- 0x20D8, 0x20D9, 0x20DA, 0x15B3, 0x20DC, 0x20DD, 0x20DE, 0x15BB,
- 0x30E0, 0x30E1, 0x30E2, 0x25C3, 0x30E4, 0x30E5, 0x30E6, 0x25CB,
- 0x30E8, 0x30E9, 0x30EA, 0x25D3, 0x30EC, 0x30ED, 0x30EE, 0x25DB,
- 0x40F0, 0x40F1, 0x40F2, 0x35E3, 0x40F4, 0x40F5, 0x40F6, 0x35EB,
- 0x50F8, 0x50F9, 0x50FA, 0x45F3, 0x057C, 0x057D, 0x15BE, 0x55FB,
-};
-
-
-static WORD stuff4[] =
-{
- 0x0000, 0x0401, 0x0002, 0x0405, 0x0004, 0x0409, 0x0006, 0x040D,
- 0x0008, 0x0411, 0x000A, 0x0415, 0x000C, 0x0419, 0x000E, 0x041D,
- 0x0010, 0x0421, 0x0012, 0x0425, 0x0014, 0x0429, 0x0016, 0x042D,
- 0x0018, 0x0431, 0x001A, 0x0435, 0x001C, 0x0439, 0x001E, 0x043D,
- 0x0020, 0x0441, 0x0022, 0x0445, 0x0024, 0x0449, 0x0026, 0x044D,
- 0x0028, 0x0451, 0x002A, 0x0455, 0x002C, 0x0459, 0x002E, 0x045D,
- 0x0030, 0x0461, 0x0032, 0x0465, 0x0034, 0x0469, 0x0036, 0x046D,
- 0x0038, 0x0471, 0x003A, 0x0475, 0x003C, 0x0479, 0x043E, 0x087D,
- 0x0040, 0x1481, 0x0042, 0x1485, 0x0044, 0x1489, 0x0046, 0x148D,
- 0x0048, 0x1491, 0x004A, 0x1495, 0x004C, 0x1499, 0x004E, 0x149D,
- 0x0050, 0x14A1, 0x0052, 0x14A5, 0x0054, 0x14A9, 0x0056, 0x14AD,
- 0x0058, 0x14B1, 0x005A, 0x14B5, 0x005C, 0x14B9, 0x005E, 0x14BD,
- 0x0060, 0x24C1, 0x0062, 0x24C5, 0x0064, 0x24C9, 0x0066, 0x24CD,
- 0x0068, 0x24D1, 0x006A, 0x24D5, 0x006C, 0x24D9, 0x006E, 0x24DD,
- 0x0070, 0x34E1, 0x0072, 0x34E5, 0x0074, 0x34E9, 0x0076, 0x34ED,
- 0x0078, 0x44F1, 0x007A, 0x44F5, 0x047C, 0x54F9, 0x14BE, 0x097D,
- 0x1080, 0x0501, 0x1082, 0x0505, 0x1084, 0x0509, 0x1086, 0x050D,
- 0x1088, 0x0511, 0x108A, 0x0515, 0x108C, 0x0519, 0x108E, 0x051D,
- 0x1090, 0x0521, 0x1092, 0x0525, 0x1094, 0x0529, 0x1096, 0x052D,
- 0x1098, 0x0531, 0x109A, 0x0535, 0x109C, 0x0539, 0x109E, 0x053D,
- 0x10A0, 0x0541, 0x10A2, 0x0545, 0x10A4, 0x0549, 0x10A6, 0x054D,
- 0x10A8, 0x0551, 0x10AA, 0x0555, 0x10AC, 0x0559, 0x10AE, 0x055D,
- 0x10B0, 0x0561, 0x10B2, 0x0565, 0x10B4, 0x0569, 0x10B6, 0x056D,
- 0x10B8, 0x0571, 0x10BA, 0x0575, 0x10BC, 0x0579, 0x053E, 0x0A7D,
- 0x20C0, 0x1581, 0x20C2, 0x1585, 0x20C4, 0x1589, 0x20C6, 0x158D,
- 0x20C8, 0x1591, 0x20CA, 0x1595, 0x20CC, 0x1599, 0x20CE, 0x159D,
- 0x20D0, 0x15A1, 0x20D2, 0x15A5, 0x20D4, 0x15A9, 0x20D6, 0x15AD,
- 0x20D8, 0x15B1, 0x20DA, 0x15B5, 0x20DC, 0x15B9, 0x20DE, 0x15BD,
- 0x30E0, 0x25C1, 0x30E2, 0x25C5, 0x30E4, 0x25C9, 0x30E6, 0x25CD,
- 0x30E8, 0x25D1, 0x30EA, 0x25D5, 0x30EC, 0x25D9, 0x30EE, 0x25DD,
- 0x40F0, 0x35E1, 0x40F2, 0x35E5, 0x40F4, 0x35E9, 0x40F6, 0x35ED,
- 0x50F8, 0x45F1, 0x50FA, 0x45F5, 0x057C, 0x55F9, 0x15BE, 0x0B7D,
-};
-
-
-static WORD stuff5[] =
-{
- 0x0400, 0x0402, 0x0404, 0x0406, 0x0408, 0x040A, 0x040C, 0x040E,
- 0x0410, 0x0412, 0x0414, 0x0416, 0x0418, 0x041A, 0x041C, 0x041E,
- 0x0420, 0x0422, 0x0424, 0x0426, 0x0428, 0x042A, 0x042C, 0x042E,
- 0x0430, 0x0432, 0x0434, 0x0436, 0x0438, 0x043A, 0x043C, 0x083E,
- 0x0440, 0x0442, 0x0444, 0x0446, 0x0448, 0x044A, 0x044C, 0x044E,
- 0x0450, 0x0452, 0x0454, 0x0456, 0x0458, 0x045A, 0x045C, 0x045E,
- 0x0460, 0x0462, 0x0464, 0x0466, 0x0468, 0x046A, 0x046C, 0x046E,
- 0x0470, 0x0472, 0x0474, 0x0476, 0x0478, 0x047A, 0x087C, 0x18BE,
- 0x1480, 0x1482, 0x1484, 0x1486, 0x1488, 0x148A, 0x148C, 0x148E,
- 0x1490, 0x1492, 0x1494, 0x1496, 0x1498, 0x149A, 0x149C, 0x149E,
- 0x14A0, 0x14A2, 0x14A4, 0x14A6, 0x14A8, 0x14AA, 0x14AC, 0x14AE,
- 0x14B0, 0x14B2, 0x14B4, 0x14B6, 0x14B8, 0x14BA, 0x14BC, 0x093E,
- 0x24C0, 0x24C2, 0x24C4, 0x24C6, 0x24C8, 0x24CA, 0x24CC, 0x24CE,
- 0x24D0, 0x24D2, 0x24D4, 0x24D6, 0x24D8, 0x24DA, 0x24DC, 0x24DE,
- 0x34E0, 0x34E2, 0x34E4, 0x34E6, 0x34E8, 0x34EA, 0x34EC, 0x34EE,
- 0x44F0, 0x44F2, 0x44F4, 0x44F6, 0x54F8, 0x54FA, 0x097C, 0x19BE,
- 0x0500, 0x0502, 0x0504, 0x0506, 0x0508, 0x050A, 0x050C, 0x050E,
- 0x0510, 0x0512, 0x0514, 0x0516, 0x0518, 0x051A, 0x051C, 0x051E,
- 0x0520, 0x0522, 0x0524, 0x0526, 0x0528, 0x052A, 0x052C, 0x052E,
- 0x0530, 0x0532, 0x0534, 0x0536, 0x0538, 0x053A, 0x053C, 0x0A3E,
- 0x0540, 0x0542, 0x0544, 0x0546, 0x0548, 0x054A, 0x054C, 0x054E,
- 0x0550, 0x0552, 0x0554, 0x0556, 0x0558, 0x055A, 0x055C, 0x055E,
- 0x0560, 0x0562, 0x0564, 0x0566, 0x0568, 0x056A, 0x056C, 0x056E,
- 0x0570, 0x0572, 0x0574, 0x0576, 0x0578, 0x057A, 0x0A7C, 0x1ABE,
- 0x1580, 0x1582, 0x1584, 0x1586, 0x1588, 0x158A, 0x158C, 0x158E,
- 0x1590, 0x1592, 0x1594, 0x1596, 0x1598, 0x159A, 0x159C, 0x159E,
- 0x15A0, 0x15A2, 0x15A4, 0x15A6, 0x15A8, 0x15AA, 0x15AC, 0x15AE,
- 0x15B0, 0x15B2, 0x15B4, 0x15B6, 0x15B8, 0x15BA, 0x15BC, 0x0B3E,
- 0x25C0, 0x25C2, 0x25C4, 0x25C6, 0x25C8, 0x25CA, 0x25CC, 0x25CE,
- 0x25D0, 0x25D2, 0x25D4, 0x25D6, 0x25D8, 0x25DA, 0x25DC, 0x25DE,
- 0x35E0, 0x35E2, 0x35E4, 0x35E6, 0x35E8, 0x35EA, 0x35EC, 0x35EE,
- 0x45F0, 0x45F2, 0x45F4, 0x45F6, 0x55F8, 0x55FA, 0x0B7C, 0x1BBE,
-};
-
-static WORD destuff0[] =
-{
- 0x7000, 0x7001, 0x7002, 0x7003, 0x7004, 0x7005, 0x7006, 0x7007,
- 0x7008, 0x7009, 0x700A, 0x700B, 0x700C, 0x700D, 0x700E, 0x700F,
- 0x7010, 0x7011, 0x7012, 0x7013, 0x7014, 0x7015, 0x7016, 0x7017,
- 0x7018, 0x7019, 0x701A, 0x701B, 0x701C, 0x701D, 0x701E, 0x601F,
- 0x7020, 0x7021, 0x7022, 0x7023, 0x7024, 0x7025, 0x7026, 0x7027,
- 0x7028, 0x7029, 0x702A, 0x702B, 0x702C, 0x702D, 0x702E, 0x702F,
- 0x7030, 0x7031, 0x7032, 0x7033, 0x7034, 0x7035, 0x7036, 0x7037,
- 0x7038, 0x7039, 0x703A, 0x703B, 0x703C, 0x703D, 0x603E, 0xF03F,
- 0x7040, 0x7041, 0x7042, 0x7043, 0x7044, 0x7045, 0x7046, 0x7047,
- 0x7048, 0x7049, 0x704A, 0x704B, 0x704C, 0x704D, 0x704E, 0x704F,
- 0x7050, 0x7051, 0x7052, 0x7053, 0x7054, 0x7055, 0x7056, 0x7057,
- 0x7058, 0x7059, 0x705A, 0x705B, 0x705C, 0x705D, 0x705E, 0x603F,
- 0x7060, 0x7061, 0x7062, 0x7063, 0x7064, 0x7065, 0x7066, 0x7067,
- 0x7068, 0x7069, 0x706A, 0x706B, 0x706C, 0x706D, 0x706E, 0x706F,
- 0x7070, 0x7071, 0x7072, 0x7073, 0x7074, 0x7075, 0x7076, 0x7077,
- 0x7078, 0x7079, 0x707A, 0x707B, 0x607C, 0x607D, 0xF07E, 0xF07F,
- 0x7180, 0x7181, 0x7182, 0x7183, 0x7184, 0x7185, 0x7186, 0x7187,
- 0x7188, 0x7189, 0x718A, 0x718B, 0x718C, 0x718D, 0x718E, 0x718F,
- 0x7190, 0x7191, 0x7192, 0x7193, 0x7194, 0x7195, 0x7196, 0x7197,
- 0x7198, 0x7199, 0x719A, 0x719B, 0x719C, 0x719D, 0x719E, 0x615F,
- 0x71A0, 0x71A1, 0x71A2, 0x71A3, 0x71A4, 0x71A5, 0x71A6, 0x71A7,
- 0x71A8, 0x71A9, 0x71AA, 0x71AB, 0x71AC, 0x71AD, 0x71AE, 0x71AF,
- 0x71B0, 0x71B1, 0x71B2, 0x71B3, 0x71B4, 0x71B5, 0x71B6, 0x71B7,
- 0x71B8, 0x71B9, 0x71BA, 0x71BB, 0x71BC, 0x71BD, 0x617E, 0xF1BF,
- 0x72C0, 0x72C1, 0x72C2, 0x72C3, 0x72C4, 0x72C5, 0x72C6, 0x72C7,
- 0x72C8, 0x72C9, 0x72CA, 0x72CB, 0x72CC, 0x72CD, 0x72CE, 0x72CF,
- 0x72D0, 0x72D1, 0x72D2, 0x72D3, 0x72D4, 0x72D5, 0x72D6, 0x72D7,
- 0x72D8, 0x72D9, 0x72DA, 0x72DB, 0x72DC, 0x72DD, 0x72DE, 0x627F,
- 0x73E0, 0x73E1, 0x73E2, 0x73E3, 0x73E4, 0x73E5, 0x73E6, 0x73E7,
- 0x73E8, 0x73E9, 0x73EA, 0x73EB, 0x73EC, 0x73ED, 0x73EE, 0x73EF,
- 0x74F0, 0x74F1, 0x74F2, 0x74F3, 0x74F4, 0x74F5, 0x74F6, 0x74F7,
- 0x75F8, 0x75F9, 0x75FA, 0x75FB, 0xF6FC, 0xF6FD, 0xF7FE, 0xF8FF,
-};
-
-
-static WORD destuff1[] =
-{
- 0x7000, 0x7001, 0x7002, 0x7003, 0x7004, 0x7005, 0x7006, 0x7007,
- 0x7008, 0x7009, 0x700A, 0x700B, 0x700C, 0x700D, 0x700E, 0x600F,
- 0x7010, 0x7011, 0x7012, 0x7013, 0x7014, 0x7015, 0x7016, 0x7017,
- 0x7018, 0x7019, 0x701A, 0x701B, 0x701C, 0x701D, 0x701E, 0xF01F,
- 0x7020, 0x7021, 0x7022, 0x7023, 0x7024, 0x7025, 0x7026, 0x7027,
- 0x7028, 0x7029, 0x702A, 0x702B, 0x702C, 0x702D, 0x702E, 0x601F,
- 0x7030, 0x7031, 0x7032, 0x7033, 0x7034, 0x7035, 0x7036, 0x7037,
- 0x7038, 0x7039, 0x703A, 0x703B, 0x703C, 0x703D, 0x603E, 0xF03F,
- 0x7040, 0x7041, 0x7042, 0x7043, 0x7044, 0x7045, 0x7046, 0x7047,
- 0x7048, 0x7049, 0x704A, 0x704B, 0x704C, 0x704D, 0x704E, 0x602F,
- 0x7050, 0x7051, 0x7052, 0x7053, 0x7054, 0x7055, 0x7056, 0x7057,
- 0x7058, 0x7059, 0x705A, 0x705B, 0x705C, 0x705D, 0x705E, 0xF05F,
- 0x7060, 0x7061, 0x7062, 0x7063, 0x7064, 0x7065, 0x7066, 0x7067,
- 0x7068, 0x7069, 0x706A, 0x706B, 0x706C, 0x706D, 0x706E, 0x603F,
- 0x7070, 0x7071, 0x7072, 0x7073, 0x7074, 0x7075, 0x7076, 0x7077,
- 0x7078, 0x7079, 0x707A, 0x707B, 0x607C, 0x607D, 0xF07E, 0xF07F,
- 0x7180, 0x7181, 0x7182, 0x7183, 0x7184, 0x7185, 0x7186, 0x7187,
- 0x7188, 0x7189, 0x718A, 0x718B, 0x718C, 0x718D, 0x718E, 0x614F,
- 0x7190, 0x7191, 0x7192, 0x7193, 0x7194, 0x7195, 0x7196, 0x7197,
- 0x7198, 0x7199, 0x719A, 0x719B, 0x719C, 0x719D, 0x719E, 0xF19F,
- 0x71A0, 0x71A1, 0x71A2, 0x71A3, 0x71A4, 0x71A5, 0x71A6, 0x71A7,
- 0x71A8, 0x71A9, 0x71AA, 0x71AB, 0x71AC, 0x71AD, 0x71AE, 0x615F,
- 0x71B0, 0x71B1, 0x71B2, 0x71B3, 0x71B4, 0x71B5, 0x71B6, 0x71B7,
- 0x71B8, 0x71B9, 0x71BA, 0x71BB, 0x71BC, 0x71BD, 0x617E, 0xF1BF,
- 0x72C0, 0x72C1, 0x72C2, 0x72C3, 0x72C4, 0x72C5, 0x72C6, 0x72C7,
- 0x72C8, 0x72C9, 0x72CA, 0x72CB, 0x72CC, 0x72CD, 0x72CE, 0x626F,
- 0x72D0, 0x72D1, 0x72D2, 0x72D3, 0x72D4, 0x72D5, 0x72D6, 0x72D7,
- 0x72D8, 0x72D9, 0x72DA, 0x72DB, 0x72DC, 0x72DD, 0x72DE, 0xF2DF,
- 0x73E0, 0x73E1, 0x73E2, 0x73E3, 0x73E4, 0x73E5, 0x73E6, 0x73E7,
- 0x73E8, 0x73E9, 0x73EA, 0x73EB, 0x73EC, 0x73ED, 0x73EE, 0x637F,
- 0x74F0, 0x74F1, 0x74F2, 0x74F3, 0x74F4, 0x74F5, 0x74F6, 0x74F7,
- 0x75F8, 0x75F9, 0x75FA, 0x75FB, 0xF6FC, 0xF6FD, 0xF7FE, 0xF9FF,
-};
-
-
-static WORD destuff2[] =
-{
- 0x7000, 0x7001, 0x7002, 0x7003, 0x7004, 0x7005, 0x7006, 0x6007,
- 0x7008, 0x7009, 0x700A, 0x700B, 0x700C, 0x700D, 0x700E, 0xF00F,
- 0x7010, 0x7011, 0x7012, 0x7013, 0x7014, 0x7015, 0x7016, 0x600F,
- 0x7018, 0x7019, 0x701A, 0x701B, 0x701C, 0x701D, 0x701E, 0xF01F,
- 0x7020, 0x7021, 0x7022, 0x7023, 0x7024, 0x7025, 0x7026, 0x6017,
- 0x7028, 0x7029, 0x702A, 0x702B, 0x702C, 0x702D, 0x702E, 0xF02F,
- 0x7030, 0x7031, 0x7032, 0x7033, 0x7034, 0x7035, 0x7036, 0x601F,
- 0x7038, 0x7039, 0x703A, 0x703B, 0x703C, 0x703D, 0x603E, 0xF03F,
- 0x7040, 0x7041, 0x7042, 0x7043, 0x7044, 0x7045, 0x7046, 0x6027,
- 0x7048, 0x7049, 0x704A, 0x704B, 0x704C, 0x704D, 0x704E, 0xF04F,
- 0x7050, 0x7051, 0x7052, 0x7053, 0x7054, 0x7055, 0x7056, 0x602F,
- 0x7058, 0x7059, 0x705A, 0x705B, 0x705C, 0x705D, 0x705E, 0xF05F,
- 0x7060, 0x7061, 0x7062, 0x7063, 0x7064, 0x7065, 0x7066, 0x6037,
- 0x7068, 0x7069, 0x706A, 0x706B, 0x706C, 0x706D, 0x706E, 0xF06F,
- 0x7070, 0x7071, 0x7072, 0x7073, 0x7074, 0x7075, 0x7076, 0x603F,
- 0x7078, 0x7079, 0x707A, 0x707B, 0x607C, 0x607D, 0xF07E, 0xF07F,
- 0x7180, 0x7181, 0x7182, 0x7183, 0x7184, 0x7185, 0x7186, 0x6147,
- 0x7188, 0x7189, 0x718A, 0x718B, 0x718C, 0x718D, 0x718E, 0xF18F,
- 0x7190, 0x7191, 0x7192, 0x7193, 0x7194, 0x7195, 0x7196, 0x614F,
- 0x7198, 0x7199, 0x719A, 0x719B, 0x719C, 0x719D, 0x719E, 0xF19F,
- 0x71A0, 0x71A1, 0x71A2, 0x71A3, 0x71A4, 0x71A5, 0x71A6, 0x6157,
- 0x71A8, 0x71A9, 0x71AA, 0x71AB, 0x71AC, 0x71AD, 0x71AE, 0xF1AF,
- 0x71B0, 0x71B1, 0x71B2, 0x71B3, 0x71B4, 0x71B5, 0x71B6, 0x615F,
- 0x71B8, 0x71B9, 0x71BA, 0x71BB, 0x71BC, 0x71BD, 0x617E, 0xF1BF,
- 0x72C0, 0x72C1, 0x72C2, 0x72C3, 0x72C4, 0x72C5, 0x72C6, 0x6267,
- 0x72C8, 0x72C9, 0x72CA, 0x72CB, 0x72CC, 0x72CD, 0x72CE, 0xF2CF,
- 0x72D0, 0x72D1, 0x72D2, 0x72D3, 0x72D4, 0x72D5, 0x72D6, 0x626F,
- 0x72D8, 0x72D9, 0x72DA, 0x72DB, 0x72DC, 0x72DD, 0x72DE, 0xF2DF,
- 0x73E0, 0x73E1, 0x73E2, 0x73E3, 0x73E4, 0x73E5, 0x73E6, 0x6377,
- 0x73E8, 0x73E9, 0x73EA, 0x73EB, 0x73EC, 0x73ED, 0x73EE, 0xF3EF,
- 0x74F0, 0x74F1, 0x74F2, 0x74F3, 0x74F4, 0x74F5, 0x74F6, 0x647F,
- 0x75F8, 0x75F9, 0x75FA, 0x75FB, 0xF6FC, 0xF6FD, 0xF7FE, 0xFAFF,
-};
-
-
-static WORD destuff3[] =
-{
- 0x7000, 0x7001, 0x7002, 0x6003, 0x7004, 0x7005, 0x7006, 0xF007,
- 0x7008, 0x7009, 0x700A, 0x6007, 0x700C, 0x700D, 0x700E, 0xF00F,
- 0x7010, 0x7011, 0x7012, 0x600B, 0x7014, 0x7015, 0x7016, 0xF017,
- 0x7018, 0x7019, 0x701A, 0x600F, 0x701C, 0x701D, 0x701E, 0xF01F,
- 0x7020, 0x7021, 0x7022, 0x6013, 0x7024, 0x7025, 0x7026, 0xF027,
- 0x7028, 0x7029, 0x702A, 0x6017, 0x702C, 0x702D, 0x702E, 0xF02F,
- 0x7030, 0x7031, 0x7032, 0x601B, 0x7034, 0x7035, 0x7036, 0xF037,
- 0x7038, 0x7039, 0x703A, 0x601F, 0x703C, 0x703D, 0x603E, 0xF03F,
- 0x7040, 0x7041, 0x7042, 0x6023, 0x7044, 0x7045, 0x7046, 0xF047,
- 0x7048, 0x7049, 0x704A, 0x6027, 0x704C, 0x704D, 0x704E, 0xF04F,
- 0x7050, 0x7051, 0x7052, 0x602B, 0x7054, 0x7055, 0x7056, 0xF057,
- 0x7058, 0x7059, 0x705A, 0x602F, 0x705C, 0x705D, 0x705E, 0xF05F,
- 0x7060, 0x7061, 0x7062, 0x6033, 0x7064, 0x7065, 0x7066, 0xF067,
- 0x7068, 0x7069, 0x706A, 0x6037, 0x706C, 0x706D, 0x706E, 0xF06F,
- 0x7070, 0x7071, 0x7072, 0x603B, 0x7074, 0x7075, 0x7076, 0xF077,
- 0x7078, 0x7079, 0x707A, 0x603F, 0x607C, 0x607D, 0xF07E, 0xF07F,
- 0x7180, 0x7181, 0x7182, 0x6143, 0x7184, 0x7185, 0x7186, 0xF187,
- 0x7188, 0x7189, 0x718A, 0x6147, 0x718C, 0x718D, 0x718E, 0xF18F,
- 0x7190, 0x7191, 0x7192, 0x614B, 0x7194, 0x7195, 0x7196, 0xF197,
- 0x7198, 0x7199, 0x719A, 0x614F, 0x719C, 0x719D, 0x719E, 0xF19F,
- 0x71A0, 0x71A1, 0x71A2, 0x6153, 0x71A4, 0x71A5, 0x71A6, 0xF1A7,
- 0x71A8, 0x71A9, 0x71AA, 0x6157, 0x71AC, 0x71AD, 0x71AE, 0xF1AF,
- 0x71B0, 0x71B1, 0x71B2, 0x615B, 0x71B4, 0x71B5, 0x71B6, 0xF1B7,
- 0x71B8, 0x71B9, 0x71BA, 0x615F, 0x71BC, 0x71BD, 0x617E, 0xF1BF,
- 0x72C0, 0x72C1, 0x72C2, 0x6263, 0x72C4, 0x72C5, 0x72C6, 0xF2C7,
- 0x72C8, 0x72C9, 0x72CA, 0x6267, 0x72CC, 0x72CD, 0x72CE, 0xF2CF,
- 0x72D0, 0x72D1, 0x72D2, 0x626B, 0x72D4, 0x72D5, 0x72D6, 0xF2D7,
- 0x72D8, 0x72D9, 0x72DA, 0x626F, 0x72DC, 0x72DD, 0x72DE, 0xF2DF,
- 0x73E0, 0x73E1, 0x73E2, 0x6373, 0x73E4, 0x73E5, 0x73E6, 0xF3E7,
- 0x73E8, 0x73E9, 0x73EA, 0x6377, 0x73EC, 0x73ED, 0x73EE, 0xF3EF,
- 0x74F0, 0x74F1, 0x74F2, 0x647B, 0x74F4, 0x74F5, 0x74F6, 0xF4F7,
- 0x75F8, 0x75F9, 0x75FA, 0x657F, 0xF6FC, 0xF6FD, 0xF7FE, 0xFBFF,
-};
-
-
-static WORD destuff4[] =
-{
- 0x7000, 0x6001, 0x7002, 0xF003, 0x7004, 0x6003, 0x7006, 0xF007,
- 0x7008, 0x6005, 0x700A, 0xF00B, 0x700C, 0x6007, 0x700E, 0xF00F,
- 0x7010, 0x6009, 0x7012, 0xF013, 0x7014, 0x600B, 0x7016, 0xF017,
- 0x7018, 0x600D, 0x701A, 0xF01B, 0x701C, 0x600F, 0x701E, 0xF01F,
- 0x7020, 0x6011, 0x7022, 0xF023, 0x7024, 0x6013, 0x7026, 0xF027,
- 0x7028, 0x6015, 0x702A, 0xF02B, 0x702C, 0x6017, 0x702E, 0xF02F,
- 0x7030, 0x6019, 0x7032, 0xF033, 0x7034, 0x601B, 0x7036, 0xF037,
- 0x7038, 0x601D, 0x703A, 0xF03B, 0x703C, 0x601F, 0x603E, 0xF03F,
- 0x7040, 0x6021, 0x7042, 0xF043, 0x7044, 0x6023, 0x7046, 0xF047,
- 0x7048, 0x6025, 0x704A, 0xF04B, 0x704C, 0x6027, 0x704E, 0xF04F,
- 0x7050, 0x6029, 0x7052, 0xF053, 0x7054, 0x602B, 0x7056, 0xF057,
- 0x7058, 0x602D, 0x705A, 0xF05B, 0x705C, 0x602F, 0x705E, 0xF05F,
- 0x7060, 0x6031, 0x7062, 0xF063, 0x7064, 0x6033, 0x7066, 0xF067,
- 0x7068, 0x6035, 0x706A, 0xF06B, 0x706C, 0x6037, 0x706E, 0xF06F,
- 0x7070, 0x6039, 0x7072, 0xF073, 0x7074, 0x603B, 0x7076, 0xF077,
- 0x7078, 0x603D, 0x707A, 0xF07B, 0x607C, 0x503F, 0xF07E, 0xF07F,
- 0x7180, 0x6141, 0x7182, 0xF183, 0x7184, 0x6143, 0x7186, 0xF187,
- 0x7188, 0x6145, 0x718A, 0xF18B, 0x718C, 0x6147, 0x718E, 0xF18F,
- 0x7190, 0x6149, 0x7192, 0xF193, 0x7194, 0x614B, 0x7196, 0xF197,
- 0x7198, 0x614D, 0x719A, 0xF19B, 0x719C, 0x614F, 0x719E, 0xF19F,
- 0x71A0, 0x6151, 0x71A2, 0xF1A3, 0x71A4, 0x6153, 0x71A6, 0xF1A7,
- 0x71A8, 0x6155, 0x71AA, 0xF1AB, 0x71AC, 0x6157, 0x71AE, 0xF1AF,
- 0x71B0, 0x6159, 0x71B2, 0xF1B3, 0x71B4, 0x615B, 0x71B6, 0xF1B7,
- 0x71B8, 0x615D, 0x71BA, 0xF1BB, 0x71BC, 0x615F, 0x617E, 0xF1BF,
- 0x72C0, 0x6261, 0x72C2, 0xF2C3, 0x72C4, 0x6263, 0x72C6, 0xF2C7,
- 0x72C8, 0x6265, 0x72CA, 0xF2CB, 0x72CC, 0x6267, 0x72CE, 0xF2CF,
- 0x72D0, 0x6269, 0x72D2, 0xF2D3, 0x72D4, 0x626B, 0x72D6, 0xF2D7,
- 0x72D8, 0x626D, 0x72DA, 0xF2DB, 0x72DC, 0x626F, 0x72DE, 0xF2DF,
- 0x73E0, 0x6371, 0x73E2, 0xF3E3, 0x73E4, 0x6373, 0x73E6, 0xF3E7,
- 0x73E8, 0x6375, 0x73EA, 0xF3EB, 0x73EC, 0x6377, 0x73EE, 0xF3EF,
- 0x74F0, 0x6479, 0x74F2, 0xF4F3, 0x74F4, 0x647B, 0x74F6, 0xF4F7,
- 0x75F8, 0x657D, 0x75FA, 0xF5FB, 0xF6FC, 0xE67F, 0xF7FE, 0xFCFF,
-};
-
-
-static WORD destuff5[] =
-{
- 0x6000, 0xF001, 0x6001, 0xF003, 0x6002, 0xF005, 0x6003, 0xF007,
- 0x6004, 0xF009, 0x6005, 0xF00B, 0x6006, 0xF00D, 0x6007, 0xF00F,
- 0x6008, 0xF011, 0x6009, 0xF013, 0x600A, 0xF015, 0x600B, 0xF017,
- 0x600C, 0xF019, 0x600D, 0xF01B, 0x600E, 0xF01D, 0x600F, 0xF01F,
- 0x6010, 0xF021, 0x6011, 0xF023, 0x6012, 0xF025, 0x6013, 0xF027,
- 0x6014, 0xF029, 0x6015, 0xF02B, 0x6016, 0xF02D, 0x6017, 0xF02F,
- 0x6018, 0xF031, 0x6019, 0xF033, 0x601A, 0xF035, 0x601B, 0xF037,
- 0x601C, 0xF039, 0x601D, 0xF03B, 0x601E, 0xF03D, 0x501F, 0xF03F,
- 0x6020, 0xF041, 0x6021, 0xF043, 0x6022, 0xF045, 0x6023, 0xF047,
- 0x6024, 0xF049, 0x6025, 0xF04B, 0x6026, 0xF04D, 0x6027, 0xF04F,
- 0x6028, 0xF051, 0x6029, 0xF053, 0x602A, 0xF055, 0x602B, 0xF057,
- 0x602C, 0xF059, 0x602D, 0xF05B, 0x602E, 0xF05D, 0x602F, 0xF05F,
- 0x6030, 0xF061, 0x6031, 0xF063, 0x6032, 0xF065, 0x6033, 0xF067,
- 0x6034, 0xF069, 0x6035, 0xF06B, 0x6036, 0xF06D, 0x6037, 0xF06F,
- 0x6038, 0xF071, 0x6039, 0xF073, 0x603A, 0xF075, 0x603B, 0xF077,
- 0x603C, 0xF079, 0x603D, 0xF07B, 0x503E, 0xE07D, 0xE03F, 0xF07F,
- 0x6140, 0xF181, 0x6141, 0xF183, 0x6142, 0xF185, 0x6143, 0xF187,
- 0x6144, 0xF189, 0x6145, 0xF18B, 0x6146, 0xF18D, 0x6147, 0xF18F,
- 0x6148, 0xF191, 0x6149, 0xF193, 0x614A, 0xF195, 0x614B, 0xF197,
- 0x614C, 0xF199, 0x614D, 0xF19B, 0x614E, 0xF19D, 0x614F, 0xF19F,
- 0x6150, 0xF1A1, 0x6151, 0xF1A3, 0x6152, 0xF1A5, 0x6153, 0xF1A7,
- 0x6154, 0xF1A9, 0x6155, 0xF1AB, 0x6156, 0xF1AD, 0x6157, 0xF1AF,
- 0x6158, 0xF1B1, 0x6159, 0xF1B3, 0x615A, 0xF1B5, 0x615B, 0xF1B7,
- 0x615C, 0xF1B9, 0x615D, 0xF1BB, 0x615E, 0xF1BD, 0x513F, 0xF1BF,
- 0x6260, 0xF2C1, 0x6261, 0xF2C3, 0x6262, 0xF2C5, 0x6263, 0xF2C7,
- 0x6264, 0xF2C9, 0x6265, 0xF2CB, 0x6266, 0xF2CD, 0x6267, 0xF2CF,
- 0x6268, 0xF2D1, 0x6269, 0xF2D3, 0x626A, 0xF2D5, 0x626B, 0xF2D7,
- 0x626C, 0xF2D9, 0x626D, 0xF2DB, 0x626E, 0xF2DD, 0x626F, 0xF2DF,
- 0x6370, 0xF3E1, 0x6371, 0xF3E3, 0x6372, 0xF3E5, 0x6373, 0xF3E7,
- 0x6374, 0xF3E9, 0x6375, 0xF3EB, 0x6376, 0xF3ED, 0x6377, 0xF3EF,
- 0x6478, 0xF4F1, 0x6479, 0xF4F3, 0x647A, 0xF4F5, 0x647B, 0xF4F7,
- 0x657C, 0xF5F9, 0x657D, 0xF5FB, 0xE67E, 0xF6FD, 0xE77F, 0xFDFF,
-};
-
-
-static WORD * stuffs[] = { stuff0, stuff1, stuff2, stuff3, stuff4, stuff5 };
-WORD * destuffs[] = { destuff0, destuff1, destuff2, destuff3, destuff4, destuff5 };
-
-
-/*- AuverTech Telecom -------------------------------------------------------+
- | |
- | @Function : tpam_hdlc_encode |
- | @Author : Cyrille Boudon |
- | |
- +---------------------------------------------------------------------------+
- | |
- | @Param : BYTE *pbyBuffIn IN, array of bytes to encode |
- | @Param : BYTE *pbyBuffOut OUT, array of bytes encoded |
- | @Param : DWORD *pdwInitialShift INOUT, initial shift |
- | @Param : DWORD dwLength IN, count of bytes to encode |
- | |
- | @Return : DWORD count of bytes encoded |
- | |
- +------------------------------- @Abstract ---------------------------------+
- | |
- | Bit stuffing of thz array pbyBuffIn with the insertion of a flag at the |
- | beginning and the end, using the initial shift (due to the emission of |
- | previous frames). The last byte can be used to insert flags (by outputting|
- | the flag N times) before the next frame. The initial shift is updated at |
- | the end of the algorithm for the next frame. Its signification is: for the|
- | flags shifted like "1100111111001111" *pdwInitialShift = 3. At the |
- | beginning (for the first frame), the shift must be initialized to 0. |
- | |
- +---------------------------------------------------------------------------*/
-DWORD tpam_hdlc_encode(BYTE *pbyBuffIn, BYTE *pbyBuffOut,
- DWORD *pdwInitialShift, DWORD dwLength)
-{
- DWORD dwShifter; // temporary variable
- DWORD dwShiftNb; // shift due to the insertion of '0'
- DWORD dwState; // count of '1' at the end of the current byte
- DWORD dwNb; // length of the encoded array
- BYTE byCarry; // carry due to the shift
- BYTE byNewCarry; // temporary variable
- BYTE byCharIn; // byte being encoded
- BYTE byCarryMSB; // lost bit of the carry if dwShiftNb=7 and 2 '0' inserted
- WORD woDecal; // temporary variable
- WORD woInfo; // data read in the arrays
- BOOL bContinue; // true until the two last bytes
- BOOL bContinue2; // true until the last byte
-
- bContinue = TRUE;
- bContinue2 = TRUE;
- dwShiftNb = 0;
- byCarry = 0;
- dwState = 0;
- woDecal = 0x7E;
- byCarryMSB = 0xFF;
- dwNb = 1; // length to 1 to account for the first flag
-
- /*-----------------------------
- | insert the flag using the
- | shift given by
- | *pdwInitialShift)
- +-----------------------------*/
- * pbyBuffOut ++ = 0x7E7E >> *pdwInitialShift;
-
- /*-----------------------------
- | main loop
- +-----------------------------*/
- while (dwLength--)
- {
- byCharIn = *pbyBuffIn ++;
-
-/*-----------------------------
- | go back here to treat the
- | carry when its length
- | is over 7 and for the first
- | byte (with flag)
- +-----------------------------*/
-carry:
-
- dwNb ++;
-
- /*-----------------------------
- | shift the byte to get the
- | byte to encode (without
- | taking into account the
- | initial shift)
- +-----------------------------*/
- if (dwShiftNb)
- {
- dwShifter = byCharIn << dwShiftNb;
- byNewCarry = dwShifter >> 8;
- byCharIn = dwShifter | byCarry;
- byCarry = byNewCarry;
- }
-
- /*-----------------------------
- | get the data from the arrays
- | and take into account the
- | initial shift for the byte
- | to encode
- +-----------------------------*/
- woInfo = stuffs[dwState][byCharIn];
- woDecal |= (woInfo & 0x00FF) << 8;
- * pbyBuffOut ++ = woDecal >> *pdwInitialShift;
- woDecal = woInfo & 0x00FF;
- dwState = woInfo >> 12;
-
- /*-----------------------------
- | treat the lost bit if we had
- | a carry overflow
- +-----------------------------*/
- if (byCarryMSB != 0xFF)
- {
- if (!dwShiftNb)
- {
- if(byCarryMSB)
- byCarry = 1;
- dwShiftNb = 1;
- }
- byCarryMSB = 0xFF;
- }
-
- /*-----------------------------
- | if one '0' get inserted, we
- | have to calculate the new
- | carry and the new shift
- +-----------------------------*/
- if (woInfo & 0x0F00)
- {
- byCarryMSB = byCarry & 0x40;
- byCarry <<= (woInfo & 0x0C00) >> 10;
- byCarry |= (woInfo & 0x0300) >> 8;
- dwShiftNb += (woInfo & 0x0C00) >> 10;
- }
-
- /*-----------------------------
- | if the carry is a whole byte
- | we use it as a byte to encode
- +-----------------------------*/
- if (dwShiftNb > 7)
- {
- if (dwShiftNb == 8)
- byCarryMSB = 0xFF;
- dwShiftNb = 0;
- byCharIn = byCarry;
- byCarry = 0;
- goto carry;
- }
-
- /*-----------------------------
- | at the end of the array
- +-----------------------------*/
- if (!dwLength)
- {
- /*-----------------------------
- | take into account the bits
- | set in the carry
- +-----------------------------*/
- if (bContinue)
- {
- bContinue = FALSE;
- byCharIn = 0;
- goto carry;
- }
-
- /*-----------------------------
- | treat the last byte if we
- | had a carry overflow
- +-----------------------------*/
- if (bContinue2 && ((8 - *pdwInitialShift) + dwShiftNb) > 7)
- {
- bContinue2 = FALSE;
- byCharIn = 0;
- goto carry;
- }
-
- /*-----------------------------
- | Calculate the new shift
- +-----------------------------*/
- *pdwInitialShift = ((8 - *pdwInitialShift) + dwShiftNb)%8;
-
- /*-----------------------------
- | Add a flag at the end of the
- | carry and a full flag
- +-----------------------------*/
- pbyBuffOut--;
- *pbyBuffOut++ |= 0x7E << *pdwInitialShift;
- byCarry = 0x7E7E >> (8 - *pdwInitialShift);
- *pbyBuffOut++ = byCarry;
- *pbyBuffOut++ = byCarry;
- dwNb += 2;
- }
- }
-
- /*-------------------------------
- | Pad the array to a multiple
- | of 64 bytes.
- +-------------------------------*/
- for(;dwNb%64;dwNb++)
- *pbyBuffOut ++ = byCarry;
-
- *pdwInitialShift = (8 - *pdwInitialShift)%8;
-
- return dwNb;
-}
-
-
-
-/*- AuverTech Telecom -------------------------------------------------------+
- | |
- | @Function : tpam_hdlc_decode |
- | @Author : Cyrille Boudon |
- | |
- +---------------------------------------------------------------------------+
- | |
- | @Param : BYTE * pbyBuffIn IN, array of bytes to decode |
- | @Param : BYTE * pbyBuffOut OUT, array of decoded bytes |
- | @Param : DWORD dwLength IN, count of bytes to decode |
- | |
- | @Return : DWORD count of decoded bytes |
- | |
- +------------------------------- @Abstract ---------------------------------+
- | |
- | Bit de-stuffing of the array pbyBuffIn. There has to be at least 1 full |
- | flag at the beginning. At the end there has to be a flag or an abort (more|
- | than 6 consecutive '1'). |
- | If an abort is encountered, the returned count is '0'. |
- | |
- +---------------------------------------------------------------------------*/
-DWORD tpam_hdlc_decode(BYTE * pbyBuffIn, BYTE * pbyBuffOut, DWORD dwLength)
-{
- BYTE byCharIn; // byte being decoded
- BYTE byCarry; // current carry
- WORD woInfo; // data read in the arrays
- WORD woNb1; // count of '1' at the end of the previous byte
- BYTE byShift; // shift of the first flag
- DWORD dwInit; // temporary variable
- DWORD dwLengthOut; // count of the decoded bytes
- BYTE byLgCarry; // count of used bits in the carry
- BYTE byLgByte; // count of used bits in the decoded byte
-
- /*-----------------------------
- | Find the 1st flag. At the end
- | of the loop dwShift is the count
- | of bits to reach the 1st bit
- | of the 1st flag.
- +-----------------------------*/
- dwInit = *pbyBuffIn | (*(pbyBuffIn+1)<<8) | (*(pbyBuffIn+2)<<16);
- for (byShift=0;byShift<17;byShift++)
- {
- if (!(((dwInit>>byShift)&0xFF)^0x7E))
- {
- break;
- }
- }
-
- /*-----------------------------
- | If at the end of the previous
- | loop dwShift = 17, it means
- | that no flag was found in the
- | first 3 bytes (normally
- | impossible impossible with the
- | DSP algorithm)
- +-----------------------------*/
- if (byShift == 17)
- return 0;
-
- /*-----------------------------
- | Plase the array pointer after
- | the first flag. Update the
- | shift.
- +-----------------------------*/
- pbyBuffIn += byShift/8 + 1;
- dwLength -= byShift/8 + 1;
- byShift %= 8;
-
- /*-----------------------------
- | Walk through the frame to
- | find the first data byte
- +-----------------------------*/
- dwInit = *pbyBuffIn | (*(pbyBuffIn+1)<<8);
- while (!(((dwInit>>byShift)&0xFF)^0x7E))
- {
- pbyBuffIn ++;
- dwLength --;
- dwInit = *pbyBuffIn | (*(pbyBuffIn+1)<<8);
- }
-
- dwLengthOut = 0;
- byCarry = 0;
- byLgCarry = 0;
- byLgByte = 0;
-
- /*-------------------------------
- | Treat the first byte
- +-------------------------------*/
- byCharIn = (*pbyBuffIn >> byShift) << byShift;
- woInfo = destuffs[0][byCharIn];
- byLgByte = ((woInfo & 0x7000) >> 12) + 1;
- woNb1 = (woInfo & 0x0F00) >> 8;
- dwLength --;
- pbyBuffIn++;
-
- if (woNb1 > 5)
- return 0;
-
- if (byLgByte - byShift == 8)
- {
- *pbyBuffOut ++ = woInfo;
- dwLengthOut ++;
- }
- else
- {
- byCarry = woInfo << (8 - byLgByte);
- byLgCarry = byLgByte - byShift;
- }
-
- /*-------------------------------
- | main loop
- +-------------------------------*/
- while(dwLength --)
- {
- byCharIn = *pbyBuffIn ++;
-
- woInfo = destuffs[woNb1][byCharIn];
- byLgByte = ((woInfo & 0x7000) >> 12) + 1;
-
- /*-------------------------------
- | if the used bits in the carry
- | and the current byte makes
- | possible to output a full byte
- +-------------------------------*/
- if (byLgByte + byLgCarry >= 8)
- {
- *pbyBuffOut ++ = ( (woInfo << 8) | byCarry) >> (8 - byLgCarry);
- dwLengthOut ++;
- byLgCarry += byLgByte - 8;
- byCarry = woInfo << (8-byLgByte);
- }
- /*-------------------------------
- | if the used bits in the carry
- | and the current byte doesn't
- | make possible to output a full
- | byte
- +-------------------------------*/
- else
- {
- dwInit = (woInfo << 8) | byCarry;
- byLgCarry += byLgByte;
- byCarry = dwInit >> byLgByte;
- }
-
- woNb1 = (woInfo & 0x0F00) >> 8;
-
- /*-------------------------------
- | if the current byte contains
- | six or more consecutive '1'
- +-------------------------------*/
- if (woInfo & 0x8000)
- {
- byCarry = ((byCharIn << 8) | *(pbyBuffIn-2)) >> (8 - byLgCarry);
- if (byCarry == 0x7E)
- return dwLengthOut-1;
- else
- if (woNb1 > 6)
- return 0;
- else
- if ((!(*pbyBuffIn & 1)) && (byLgCarry == 7))
- return dwLengthOut;
- else
- return 0;
- }
- }
-
- return dwLengthOut;
-}
-
diff --git a/drivers/isdn/tpam/tpam_main.c b/drivers/isdn/tpam/tpam_main.c
deleted file mode 100644
index e11cb903297b4..0000000000000
--- a/drivers/isdn/tpam/tpam_main.c
+++ /dev/null
@@ -1,297 +0,0 @@
-/* $Id: tpam_main.c,v 1.1.2.3 2001/09/23 22:25:03 kai Exp $
- *
- * Turbo PAM ISDN driver for Linux. (Kernel Driver - main routines)
- *
- * Copyright 2001 Stelian Pop <stelian.pop@fr.alcove.com>, Alcôve
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- * For all support questions please contact: <support@auvertech.fr>
- *
- */
-
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-
-#include <linux/init.h>
-#include <asm/io.h>
-
-#include "tpam.h"
-
-/* Local functions prototypes */
-static int __devinit tpam_probe(struct pci_dev *, const struct pci_device_id *);
-static void __devexit tpam_unregister_card(struct pci_dev *, tpam_card *);
-static void __devexit tpam_remove(struct pci_dev *);
-static int __init tpam_init(void);
-static void __exit tpam_exit(void);
-
-/* List of boards */
-static tpam_card *cards; /* = NULL; */
-/* Number of cards */
-static int cards_num;
-/* Configurable id of the driver */
-static char *id = "tpam\0\0\0\0\0\0\0\0\0\0\0\0";
-
-MODULE_DESCRIPTION("ISDN4Linux: Driver for TurboPAM ISDN cards");
-MODULE_AUTHOR("Stelian Pop");
-MODULE_LICENSE("GPL");
-MODULE_PARM_DESC(id,"ID-String of the driver");
-module_param(id, charp, 0);
-
-/*
- * Finds a board by its driver ID.
- *
- * driverId: driver ID (as referenced by the IDSN link layer)
- *
- * Return: the tpam_card structure if found, NULL on error.
- */
-tpam_card *tpam_findcard(int driverid) {
- tpam_card *p = cards;
-
- while (p) {
- if (p->id == driverid)
- return p;
- p = p->next;
- }
- return NULL;
-}
-
-/*
- * Finds a channel number by its ncoid.
- *
- * card: the board
- * ncoid: the NCO id
- *
- * Return: the channel number if found, TPAM_CHANNEL_INVALID if not.
- */
-u32 tpam_findchannel(tpam_card *card, u32 ncoid) {
- int i;
-
- for (i = 0; i < TPAM_NBCHANNEL; ++i)
- if (card->channels[i].ncoid == ncoid)
- return card->channels[i].num;
- return TPAM_CHANNEL_INVALID;
-}
-
-/*
- * Initializes and registers a new TurboPAM card.
- *
- * dev: the PCI device
- * num: the board number
- *
- * Return: 0 if OK, <0 if error
- */
-static int __devinit tpam_probe(struct pci_dev *dev, const struct pci_device_id *pci_id) {
- tpam_card *card, *c;
- int i, err;
-
- if ((err = pci_enable_device(dev))) {
- printk(KERN_ERR "TurboPAM: can't enable PCI device at %s\n",
- pci_name(dev));
- return err;
- }
-
- /* allocate memory for the board structure */
- if (!(card = (tpam_card *)kmalloc(sizeof(tpam_card), GFP_KERNEL))) {
- printk(KERN_ERR "TurboPAM: tpam_register_card: "
- "kmalloc failed!\n");
- err = -ENOMEM;
- goto err_out_disable_dev;
- }
-
- memset((char *)card, 0, sizeof(tpam_card));
-
- card->irq = dev->irq;
- spin_lock_init(&card->lock);
- sprintf(card->interface.id, "%s%d", id, cards_num);
-
- /* request interrupt */
- if (request_irq(card->irq, &tpam_irq, SA_INTERRUPT | SA_SHIRQ,
- card->interface.id, card)) {
- printk(KERN_ERR "TurboPAM: tpam_register_card: "
- "could not request irq %d\n", card->irq);
- err = -EIO;
- goto err_out_free_card;
- }
-
- /* remap board memory */
- if (!(card->bar0 = ioremap(pci_resource_start(dev, 0),
- 0x800000))) {
- printk(KERN_ERR "TurboPAM: tpam_register_card: "
- "unable to remap bar0\n");
- err = -EIO;
- goto err_out_free_irq;
- }
-
- /* reset the board */
- readl(card->bar0 + TPAM_RESETPAM_REGISTER);
-
- /* initialisation magic :-( */
- copy_to_pam_dword(card, 0x01800008, 0x00000030);
- copy_to_pam_dword(card, 0x01800010, 0x00000030);
- copy_to_pam_dword(card, 0x01800014, 0x42240822);
- copy_to_pam_dword(card, 0x01800018, 0x07114000);
- copy_to_pam_dword(card, 0x0180001c, 0x00000400);
- copy_to_pam_dword(card, 0x01840070, 0x00000010);
-
- /* fill the ISDN link layer structure */
- card->interface.owner = THIS_MODULE;
- card->interface.channels = TPAM_NBCHANNEL;
- card->interface.maxbufsize = TPAM_MAXBUFSIZE;
- card->interface.features =
- ISDN_FEATURE_P_EURO |
- ISDN_FEATURE_L2_HDLC |
- ISDN_FEATURE_L2_MODEM |
- ISDN_FEATURE_L3_TRANS;
- card->interface.hl_hdrlen = 0;
- card->interface.command = tpam_command;
- card->interface.writebuf_skb = tpam_writebuf_skb;
- card->interface.writecmd = NULL;
- card->interface.readstat = NULL;
-
- /* register wrt the ISDN link layer */
- if (!register_isdn(&card->interface)) {
- printk(KERN_ERR "TurboPAM: tpam_register_card: "
- "unable to register %s\n", card->interface.id);
- err = -EIO;
- goto err_out_iounmap;
- }
- card->id = card->interface.channels;
-
- /* initialize all channels */
- for (i = 0; i < TPAM_NBCHANNEL; ++i) {
- card->channels[i].num = i;
- card->channels[i].card = card;
- card->channels[i].ncoid = TPAM_NCOID_INVALID;
- card->channels[i].hdlc = 0;
- card->channels[i].realhdlc = 0;
- card->channels[i].hdlcshift = 0;
- skb_queue_head_init(&card->channels[i].sendq);
- }
-
- /* initialize the rest of board structure */
- card->channels_used = 0;
- card->channels_tested = 0;
- card->running = 0;
- card->busy = 0;
- card->roundrobin = 0;
- card->loopmode = 0;
- skb_queue_head_init(&card->sendq);
- skb_queue_head_init(&card->recvq);
- INIT_WORK(&card->recv_tq, (void *) (void *) tpam_recv_tq, card);
- INIT_WORK(&card->send_tq, (void *) (void *) tpam_send_tq, card);
-
- /* add the board at the end of the list of boards */
- card->next = NULL;
- if (cards) {
- c = cards;
- while (c->next)
- c = c->next;
- c->next = card;
- }
- else
- cards = card;
-
- ++cards_num;
- pci_set_drvdata(dev, card);
-
- return 0;
-
-err_out_iounmap:
- iounmap(card->bar0);
-
-err_out_free_irq:
- free_irq(card->irq, card);
-
-err_out_free_card:
- kfree(card);
-
-err_out_disable_dev:
- pci_disable_device(dev);
- return err;
-}
-
-/*
- * Unregisters a TurboPAM board by releasing all its ressources (irq, mem etc).
- *
- * card: the board.
- */
-static void __devexit tpam_unregister_card(struct pci_dev *pcidev, tpam_card *card) {
- isdn_ctrl cmd;
-
- /* prevent the ISDN link layer that the driver will be unloaded */
- cmd.command = ISDN_STAT_UNLOAD;
- cmd.driver = card->id;
- (* card->interface.statcallb)(&cmd);
-
- /* release interrupt */
- free_irq(card->irq, card);
-
- /* release mapped memory */
- iounmap(card->bar0);
-
- pci_disable_device(pcidev);
-}
-
-/*
- * Stops the driver.
- */
-static void __devexit tpam_remove(struct pci_dev *pcidev) {
- tpam_card *card = pci_get_drvdata(pcidev);
- tpam_card *c;
-
- /* remove from the list of cards */
- if (card == cards)
- cards = cards->next;
- else {
- c = cards;
- while (c->next != card)
- c = c->next;
- c->next = c->next->next;
- }
-
- /* unregister each board */
- tpam_unregister_card(pcidev, card);
-
- /* and free the board structure itself */
- kfree(card);
-}
-
-static struct pci_device_id tpam_pci_tbl[] = {
- { PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_TURBOPAM,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { }
-};
-
-MODULE_DEVICE_TABLE(pci, tpam_pci_tbl);
-
-static struct pci_driver tpam_driver = {
- .name = "tpam",
- .id_table = tpam_pci_tbl,
- .probe = tpam_probe,
- .remove = __devexit_p(tpam_remove),
-};
-
-static int __init tpam_init(void) {
- int ret;
-
- ret = pci_module_init(&tpam_driver);
- if (ret)
- return ret;
- printk(KERN_INFO "TurboPAM: %d card%s found, driver loaded.\n",
- cards_num, (cards_num > 1) ? "s" : "");
- return 0;
-}
-
-static void __exit tpam_exit(void) {
- pci_unregister_driver(&tpam_driver);
- printk(KERN_INFO "TurboPAM: driver unloaded\n");
-}
-
-/* Module entry points */
-module_init(tpam_init);
-module_exit(tpam_exit);
-
diff --git a/drivers/isdn/tpam/tpam_memory.c b/drivers/isdn/tpam/tpam_memory.c
deleted file mode 100644
index 854f574f5db80..0000000000000
--- a/drivers/isdn/tpam/tpam_memory.c
+++ /dev/null
@@ -1,247 +0,0 @@
-/* $Id: tpam_memory.c,v 1.1.2.2 2001/09/23 22:25:03 kai Exp $
- *
- * Turbo PAM ISDN driver for Linux. (Kernel Driver - Board Memory Access)
- *
- * Copyright 2001 Stelian Pop <stelian.pop@fr.alcove.com>, Alcôve
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- * For all support questions please contact: <support@auvertech.fr>
- *
- */
-
-#include <linux/pci.h>
-#include <asm/io.h>
-
-#include "tpam.h"
-
-/*
- * Write a DWORD into the board memory.
- *
- * card: the board
- * addr: the address (in the board memory)
- * val: the value to put into the memory.
- */
-void copy_to_pam_dword(tpam_card *card, u32 addr, u32 val) {
-
- /* set the page register */
- writel(addr | TPAM_PAGE_SIZE,
- card->bar0 + TPAM_PAGE_REGISTER);
-
- /* write the value */
- writel(val, card->bar0 + (addr & TPAM_PAGE_SIZE));
-}
-
-/*
- * Write n bytes into the board memory. The count of bytes will be rounded
- * up to a multiple of 4.
- *
- * card: the board
- * to: the destination address (in the board memory)
- * from: the source address (in the kernel memory)
- * n: number of bytes
- */
-void copy_to_pam(tpam_card *card, u32 to, const void *from, u32 n) {
- u32 page, offset, count;
-
- /* need to write in dword ! */
- while (n & 3) n++;
-
- while (n) {
- page = to | TPAM_PAGE_SIZE;
- offset = to & TPAM_PAGE_SIZE;
- count = n < TPAM_PAGE_SIZE - offset
- ? n
- : TPAM_PAGE_SIZE - offset;
-
- /* set the page register */
- writel(page, card->bar0 + TPAM_PAGE_REGISTER);
-
- /* copy the data */
- memcpy_toio(card->bar0 + offset, from, count);
-
- from += count;
- to += count;
- n -= count;
- }
-}
-
-/*
- * Read a DWORD from the board memory.
- *
- * card: the board
- * addr: the address (in the board memory)
- *
- * Return: the value read into the memory.
- */
-u32 copy_from_pam_dword(tpam_card *card, u32 addr) {
-
- /* set the page register */
- writel(((u32)addr) | TPAM_PAGE_SIZE,
- card->bar0 + TPAM_PAGE_REGISTER);
-
- /* read the data */
- return readl(card->bar0 + (addr & TPAM_PAGE_SIZE));
-}
-
-/*
- * Read n bytes from the board memory.
- *
- * card: the board
- * to: the destination address (in the kernel memory)
- * from: the source address (in the board memory)
- * n: number of bytes
- */
-void copy_from_pam(tpam_card *card, void *to, u32 from, u32 n) {
- u32 page, offset, count;
-
- while (n) {
- page = from | TPAM_PAGE_SIZE;
- offset = from & TPAM_PAGE_SIZE;
- count = n < TPAM_PAGE_SIZE - offset
- ? n
- : TPAM_PAGE_SIZE - offset;
-
- /* set the page register */
- writel(page, card->bar0 + TPAM_PAGE_REGISTER);
-
- /* read the data */
- memcpy_fromio(to, card->bar0 + offset, count);
-
- from += count;
- to += count;
- n -= count;
- }
-}
-
-/*
- * Read n bytes from the board memory and writes them into the user memory.
- *
- * card: the board
- * to: the destination address (in the userspace memory)
- * from: the source address (in the board memory)
- * n: number of bytes
- *
- * Return: 0 if OK, <0 if error.
- */
-int copy_from_pam_to_user(tpam_card *card, void __user *to, u32 from, u32 n) {
- void *page;
- u32 count;
-
- /* allocate a free page for the data transfer */
- if (!(page = (void *)__get_free_page(GFP_KERNEL))) {
- printk(KERN_ERR "TurboPAM(copy_from_pam_to_user): "
- "get_free_page failed\n");
- return -ENOMEM;
- }
-
- while (n) {
- count = n < PAGE_SIZE ? n : PAGE_SIZE;
-
- /* copy data from the board into the kernel memory */
- spin_lock_irq(&card->lock);
- copy_from_pam(card, page, from, count);
- spin_unlock_irq(&card->lock);
-
- /* copy it from the kernel memory into the user memory */
- if (copy_to_user(to, page, count)) {
-
- /* this can fail... */
- free_page((unsigned long)page);
- return -EFAULT;
- }
- from += count;
- to += count;
- n -= count;
- }
-
- /* release allocated memory */
- free_page((unsigned long)page);
- return 0;
-}
-
-/*
- * Read n bytes from the user memory and writes them into the board memory.
- *
- * card: the board
- * to: the destination address (in the board memory)
- * from: the source address (in the userspace memory)
- * n: number of bytes
- *
- * Return: 0 if OK, <0 if error.
- */
-int copy_from_user_to_pam(tpam_card *card, u32 to, const void __user *from, u32 n) {
- void *page;
- u32 count;
-
- /* allocate a free page for the data transfer */
- if (!(page = (void *)__get_free_page(GFP_KERNEL))) {
- printk(KERN_ERR "TurboPAM(copy_from_user_to_pam): "
- "get_free_page failed\n");
- return -ENOMEM;
- }
-
- while (n) {
- count = n < PAGE_SIZE ? n : PAGE_SIZE;
-
- /* copy data from the user memory into the kernel memory */
- if (copy_from_user(page, from, count)) {
- /* this can fail... */
- free_page((unsigned long)page);
- return -EFAULT;
- }
-
- /* copy it from the kernel memory into the board memory */
- spin_lock_irq(&card->lock);
- copy_to_pam(card, to, page, count);
- spin_unlock_irq(&card->lock);
-
- from += count;
- to += count;
- n -= count;
- }
-
- /* release allocated memory */
- free_page((unsigned long)page);
- return 0;
-}
-
-/*
- * Verify if we have the permission to read or writes len bytes at the
- * address address from/to the board memory.
- *
- * address: the start address (in the board memory)
- * len: number of bytes
- *
- * Return: 0 if OK, <0 if error.
- */
-int tpam_verify_area(u32 address, u32 len) {
-
- if (address < TPAM_RESERVEDAREA1_START)
- return (address + len <= TPAM_RESERVEDAREA1_START) ? 0 : -1;
-
- if (address <= TPAM_RESERVEDAREA1_END)
- return -1;
-
- if (address < TPAM_RESERVEDAREA2_START)
- return (address + len <= TPAM_RESERVEDAREA2_START) ? 0 : -1;
-
- if (address <= TPAM_RESERVEDAREA2_END)
- return -1;
-
- if (address < TPAM_RESERVEDAREA3_START)
- return (address + len <= TPAM_RESERVEDAREA3_START) ? 0 : -1;
-
- if (address <= TPAM_RESERVEDAREA3_END)
- return -1;
-
- if (address < TPAM_RESERVEDAREA4_START)
- return (address + len <= TPAM_RESERVEDAREA4_START) ? 0 : -1;
-
- if (address <= TPAM_RESERVEDAREA4_END)
- return -1;
-
- return 0;
-}
-
diff --git a/drivers/isdn/tpam/tpam_nco.c b/drivers/isdn/tpam/tpam_nco.c
deleted file mode 100644
index de4904f352960..0000000000000
--- a/drivers/isdn/tpam/tpam_nco.c
+++ /dev/null
@@ -1,651 +0,0 @@
-/* $Id: tpam_nco.c,v 1.1.2.2 2001/09/23 22:25:03 kai Exp $
- *
- * Turbo PAM ISDN driver for Linux.
- * (Kernel Driver - Low Level NCO Manipulation)
- *
- * Copyright 2001 Stelian Pop <stelian.pop@fr.alcove.com>, Alcôve
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- * For all support questions please contact: <support@auvertech.fr>
- *
- */
-
-#include <linux/pci.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <asm/io.h>
-
-#include "tpam.h"
-
-/* Local function prototypes */
-static struct sk_buff *build_NCOpacket(u16, u16, u16, u16, u16);
-static int extract_NCOParameter(struct sk_buff *, u8, void *, u16);
-
-/*
- * Build a NCO packet (PCI message).
- *
- * messageID: the message type (ID_*)
- * size: size of the TLV block
- * data_size: size of the data block
- * ack: packet needs to send ack upon send
- * ack_size: size of data to be acknowledged upon send
- *
- * Return: the sk_buff filled with the NCO packet, or NULL if error.
- */
-static struct sk_buff *build_NCOpacket(u16 messageID, u16 size,
- u16 data_size, u16 ack,
- u16 ack_size) {
- struct sk_buff *skb;
- skb_header *h;
- pci_mpb *p;
- u16 finalsize;
-
- /* reserve enough space for the sk_buff header, the pci * header,
- * size bytes for the TLV block, size bytes for the data and 4 more
- * bytes in order to make sure we can write dwords to the board. */
- finalsize = sizeof(skb_header) + sizeof(pci_mpb) + size + data_size + 4;
-
- /* allocate the sk_buff */
- if (!(skb = alloc_skb(finalsize, GFP_ATOMIC))) {
- printk(KERN_ERR "TurboPAM(make_NCOpacket): alloc_skb failed\n");
- return NULL;
- }
-
- /* construct the skb_header */
- h = (skb_header *)skb_put(skb, sizeof(skb_header));
- h->size = sizeof(pci_mpb) + size;
- h->data_size = data_size;
- h->ack = ack;
- h->ack_size = ack_size;
-
- /* construct the pci_mpb */
- p = (pci_mpb *)skb_put(skb, sizeof(pci_mpb));
- p->exID = 0;
- p->flags = 0;
- p->errorCode = 0;
- p->messageID = messageID;
- p->maximumBlockTLVSize = MPB_MAXIMUMBLOCKTLVSIZE;
- p->actualBlockTLVSize = size;
- p->maximumDataSize = MPB_MAXIMUMDATASIZE;
- p->actualDataSize = data_size;
- return skb;
-}
-
-/*
- * Build a ACreateNCOReq message.
- *
- * phone: the local phone number.
- *
- * Return: the sk_buff filled with the NCO packet, or NULL if error.
- */
-struct sk_buff *build_ACreateNCOReq(const u8 *phone) {
- struct sk_buff *skb;
- u8 *tlv;
-
- pr_debug("TurboPAM(build_ACreateNCOReq): phone=%s\n", phone);
-
- /* build the NCO packet */
- if (!(skb = build_NCOpacket(ID_ACreateNCOReq, 23 + strlen(phone), 0, 0, 0)))
- return NULL;
-
- /* add the parameters */
- tlv = (u8 *)skb_put(skb, 3);
- *tlv = PAR_NCOType;
- *(tlv+1) = 1;
- *(tlv+2) = 5; /* mistery value... */
-
- tlv = (u8 *)skb_put(skb, 4);
- *tlv = PAR_U3Protocol;
- *(tlv+1) = 2;
- *(tlv+2) = 4; /* no level 3 protocol */
- *(tlv+3) = 1; /* HDLC in level 2 */
-
- tlv = (u8 *)skb_put(skb, 3);
- *tlv = PAR_Cdirection;
- *(tlv+1) = 1;
- *(tlv+2) = 3; /* PCI_DIRECTION_BOTH */
-
- tlv = (u8 *)skb_put(skb, 3);
- *tlv = PAR_Udirection;
- *(tlv+1) = 1;
- *(tlv+2) = 3; /* PCI_DIRECTION_BOTH */
-
- tlv = (u8 *)skb_put(skb, 4);
- *tlv = PAR_BearerCap;
- *(tlv+1) = 2;
- *(tlv+2) = 0x88;
- *(tlv+3) = 0x90;
-
- tlv = (u8 *)skb_put(skb, 6 + strlen(phone));
- *tlv = PAR_CallingNumber;
- *(tlv+1) = strlen(phone) + 4;
- *(tlv+2) = 0x01; /* international */
- *(tlv+3) = 0x01; /* isdn */
- *(tlv+4) = 0x00;
- *(tlv+5) = 0x00;
- memcpy(tlv + 6, phone, strlen(phone));
-
- return skb;
-}
-
-/*
- * Build a ADestroyNCOReq message.
- *
- * ncoid: the NCO id.
- *
- * Return: the sk_buff filled with the NCO packet, or NULL if error.
- */
-struct sk_buff *build_ADestroyNCOReq(u32 ncoid) {
- struct sk_buff *skb;
- u8 *tlv;
-
- pr_debug("TurboPAM(build_ADestroyNCOReq): ncoid=%lu\n",
- (unsigned long)ncoid);
-
- /* build the NCO packet */
- if (!(skb = build_NCOpacket(ID_ADestroyNCOReq, 6, 0, 0, 0)))
- return NULL;
-
- /* add the parameters */
- tlv = (u8 *)skb_put(skb, 6);
- *tlv = PAR_NCOID;
- *(tlv+1) = 4;
- *((u32 *)(tlv+2)) = ncoid;
-
- return skb;
-}
-
-/*
- * Build a CConnectReq message.
- *
- * ncoid: the NCO id.
- * called: the destination phone number
- * hdlc: type of connection: 1 (HDLC) or 0(modem)
- *
- * Return: the sk_buff filled with the NCO packet, or NULL if error.
- */
-struct sk_buff *build_CConnectReq(u32 ncoid, const u8 *called, u8 hdlc) {
- struct sk_buff *skb;
- u8 *tlv;
-
- pr_debug("TurboPAM(build_CConnectReq): ncoid=%lu, called=%s, hdlc=%d\n",
- (unsigned long)ncoid, called, hdlc);
-
- /* build the NCO packet */
- if (!(skb = build_NCOpacket(ID_CConnectReq, 20 + strlen(called), 0, 0, 0)))
- return NULL;
-
- /* add the parameters */
- tlv = (u8 *)skb_put(skb, 6);
- *tlv = PAR_NCOID;
- *(tlv+1) = 4;
- *((u32 *)(tlv+2)) = ncoid;
-
- tlv = (u8 *)skb_put(skb, 4 + strlen(called));
- *tlv = PAR_CalledNumber;
- *(tlv+1) = strlen(called) + 2;
- *(tlv+2) = 0x01; /* international */
- *(tlv+3) = 0x01; /* isdn */
- memcpy(tlv + 4, called, strlen(called));
-
- tlv = (u8 *)skb_put(skb, 3);
- *tlv = PAR_BearerCap;
- *(tlv+1) = 1;
- *(tlv+2) = hdlc ? 0x88 /* HDLC */ : 0x80 /* MODEM */;
-
- tlv = (u8 *)skb_put(skb, 4);
- *tlv = PAR_HLC;
- *(tlv+1) = 2;
- *(tlv+2) = 0x2;
- *(tlv+3) = 0x7f;
-
- tlv = (u8 *)skb_put(skb, 3);
- *tlv = PAR_Facility;
- *(tlv+1) = 1;
- *(tlv+2) = 2;
-
- return skb;
-}
-
-/*
- * Build a CConnectRsp message.
- *
- * ncoid: the NCO id.
- *
- * Return: the sk_buff filled with the NCO packet, or NULL if error.
- */
-struct sk_buff *build_CConnectRsp(u32 ncoid) {
- struct sk_buff *skb;
- u8 *tlv;
-
- pr_debug("TurboPAM(build_CConnectRsp): ncoid=%lu\n",
- (unsigned long)ncoid);
-
- /* build the NCO packet */
- if (!(skb = build_NCOpacket(ID_CConnectRsp, 6, 0, 0, 0)))
- return NULL;
-
- /* add the parameters */
- tlv = (u8 *)skb_put(skb, 6);
- *tlv = PAR_NCOID;
- *(tlv+1) = 4;
- *((u32 *)(tlv+2)) = ncoid;
-
- return skb;
-}
-
-/*
- * Build a CDisconnectReq message.
- *
- * ncoid: the NCO id.
- *
- * Return: the sk_buff filled with the NCO packet, or NULL if error.
- */
-struct sk_buff *build_CDisconnectReq(u32 ncoid) {
- struct sk_buff *skb;
- u8 *tlv;
-
- pr_debug("TurboPAM(build_CDisconnectReq): ncoid=%lu\n",
- (unsigned long)ncoid);
-
- /* build the NCO packet */
- if (!(skb = build_NCOpacket(ID_CDisconnectReq, 6, 0, 0, 0)))
- return NULL;
-
- /* add the parameters */
- tlv = (u8 *)skb_put(skb, 6);
- *tlv = PAR_NCOID;
- *(tlv+1) = 4;
- *((u32 *)(tlv+2)) = ncoid;
-
- return skb;
-}
-
-/*
- * Build a CDisconnectRsp message.
- *
- * ncoid: the NCO id.
- *
- * Return: the sk_buff filled with the NCO packet, or NULL if error.
- */
-struct sk_buff *build_CDisconnectRsp(u32 ncoid) {
- struct sk_buff *skb;
- u8 *tlv;
-
- pr_debug("TurboPAM(build_CDisconnectRsp): ncoid=%lu\n",
- (unsigned long)ncoid);
-
- /* build the NCO packet */
- if (!(skb = build_NCOpacket(ID_CDisconnectRsp, 6, 0, 0, 0)))
- return NULL;
-
- /* add the parameters */
- tlv = (u8 *)skb_put(skb, 6);
- *tlv = PAR_NCOID;
- *(tlv+1) = 4;
- *((u32 *)(tlv+2)) = ncoid;
-
- return skb;
-}
-
-/*
- * Build a U3DataReq message.
- *
- * ncoid: the NCO id.
- * data: the data to be send
- * len: length of the data
- * ack: send ack upon send
- * ack_size: size of data to be acknowledged upon send
- *
- * Return: the sk_buff filled with the NCO packet, or NULL if error.
- */
-struct sk_buff *build_U3DataReq(u32 ncoid, void *data, u16 len,
- u16 ack, u16 ack_size) {
- struct sk_buff *skb;
- u8 *tlv;
- void *p;
-
- pr_debug("TurboPAM(build_U3DataReq): "
- "ncoid=%lu, len=%d, ack=%d, ack_size=%d\n",
- (unsigned long)ncoid, len, ack, ack_size);
-
- /* build the NCO packet */
- if (!(skb = build_NCOpacket(ID_U3DataReq, 6, len, ack, ack_size)))
- return NULL;
-
- /* add the parameters */
- tlv = (u8 *)skb_put(skb, 6);
- *tlv = PAR_NCOID;
- *(tlv+1) = 4;
- *((u32 *)(tlv+2)) = ncoid;
-
- p = skb_put(skb, len);
- memcpy(p, data, len);
-
- return skb;
-}
-
-/*
- * Extract a parameter from a TLV block.
- *
- * skb: sk_buff containing the PCI message
- * type: parameter to search for (PARAM_*)
- * value: to be filled with the value of the parameter
- * len: maximum length of the parameter value
- *
- * Return: 0 if OK, <0 if error.
- */
-static int extract_NCOParameter(struct sk_buff *skb, u8 type,
- void *value, u16 len) {
- void *buffer = (void *)skb->data;
- pci_mpb *p;
- void * bufferend;
- u8 valtype;
- u16 vallen;
-
- /* calculate the start and end of the TLV block */
- buffer += sizeof(skb_header);
- p = (pci_mpb *)buffer;
- buffer += sizeof(pci_mpb);
- bufferend = buffer + p->actualBlockTLVSize;
-
- /* walk through the parameters */
- while (buffer < bufferend) {
-
- /* parameter type */
- valtype = *((u8 *)buffer++);
- /* parameter length */
- vallen = *((u8 *)buffer++);
- if (vallen == 0xff) {
- /* parameter length is on 2 bytes */
- vallen = *((u8 *)buffer++);
- vallen <<= 8;
- vallen |= *((u8 *)buffer++);
- }
- /* got the right parameter */
- if (valtype == type) {
- /* not enough space for returning the value */
- if (vallen > len)
- return -1;
- /* OK, return it */
- memcpy(value, buffer, vallen);
- return 0;
- }
- buffer += vallen;
- }
- return -1;
-}
-
-/*
- * Parse a ACreateNCOCnf message.
- *
- * skb: the sk_buff containing the message
- * status: to be filled with the status field value
- * ncoid: to be filled with the ncoid field value
- *
- * Return: 0 if OK, <0 if error.
- */
-int parse_ACreateNCOCnf(struct sk_buff *skb, u8 *status, u32 *ncoid) {
-
- /* extract the status */
- if (extract_NCOParameter(skb, PAR_CompletionStatus, status, 1)) {
- printk(KERN_ERR "TurboPAM(parse_ACreateNCOCnf): "
- "CompletionStatus not found\n");
- return -1;
- }
-
- if (*status) {
- pr_debug("TurboPAM(parse_ACreateNCOCnf): status=%d\n", *status);
- return 0;
- }
-
- /* extract the ncoid */
- if (extract_NCOParameter(skb, PAR_NCOID, ncoid, 4)) {
- printk(KERN_ERR "TurboPAM(parse_ACreateNCOCnf): "
- "NCOID not found\n");
- return -1;
- }
-
- pr_debug("TurboPAM(parse_ACreateNCOCnf): ncoid=%lu, status=%d\n",
- (unsigned long)*ncoid, *status);
- return 0;
-}
-
-/*
- * Parse a ADestroyNCOCnf message. Not used in the driver.
- *
- * skb: the sk_buff containing the message
- * status: to be filled with the status field value
- * ncoid: to be filled with the ncoid field value
- *
- * Return: 0 if OK, <0 if error.
- */
-int parse_ADestroyNCOCnf(struct sk_buff *skb, u8 *status, u32 *ncoid) {
-
- /* extract the status */
- if (extract_NCOParameter(skb, PAR_CompletionStatus, status, 1)) {
- printk(KERN_ERR "TurboPAM(parse_ADestroyNCOCnf): "
- "CompletionStatus not found\n");
- return -1;
- }
-
- if (*status) {
- pr_debug("TurboPAM(parse_ADestroyNCOCnf): status=%d\n", *status);
- return 0;
- }
-
- /* extract the ncoid */
- if (extract_NCOParameter(skb, PAR_NCOID, ncoid, 4)) {
- printk(KERN_ERR "TurboPAM(parse_ADestroyNCOCnf): "
- "NCOID not found\n");
- return -1;
- }
-
- pr_debug("TurboPAM(parse_ADestroyNCOCnf): ncoid=%lu, status=%d\n",
- (unsigned long)*ncoid, *status);
- return 0;
-}
-
-/*
- * Parse a CConnectCnf message.
- *
- * skb: the sk_buff containing the message
- * ncoid: to be filled with the ncoid field value
- *
- * Return: 0 if OK, <0 if error.
- */
-int parse_CConnectCnf(struct sk_buff *skb, u32 *ncoid) {
-
- /* extract the ncoid */
- if (extract_NCOParameter(skb, PAR_NCOID, ncoid, 4)) {
- printk(KERN_ERR "TurboPAM(parse_CConnectCnf): "
- "NCOID not found\n");
- return -1;
- }
- pr_debug("TurboPAM(parse_CConnectCnf): ncoid=%lu\n",
- (unsigned long)*ncoid);
- return 0;
-}
-
-/*
- * Parse a CConnectInd message.
- *
- * skb: the sk_buff containing the message
- * ncoid: to be filled with the ncoid field value
- * hdlc: to be filled with 1 if the incoming connection is a HDLC one,
- * with 0 if the incoming connection is a modem one
- * calling: to be filled with the calling phone number value
- * called: to be filled with the called phone number value
- * plan: to be filled with the plan value
- * screen: to be filled with the screen value
- *
- * Return: 0 if OK, <0 if error.
- */
-int parse_CConnectInd(struct sk_buff *skb, u32 *ncoid, u8 *hdlc,
- u8 *calling, u8 *called, u8 *plan, u8 *screen) {
- u8 phone[PHONE_MAXIMUMSIZE + 4];
-
- /* extract the ncoid */
- if (extract_NCOParameter(skb, PAR_NCOID, ncoid, 4)) {
- printk(KERN_ERR "TurboPAM(parse_CConnectInd): "
- "NCOID not found\n");
- return -1;
- }
-
- /* extract the bearer capability field */
- if (extract_NCOParameter(skb, PAR_BearerCap, hdlc, 1)) {
- printk(KERN_ERR "TurboPAM(parse_CConnectInd): "
- "BearerCap not found\n");
- return -1;
- }
- *hdlc = (*hdlc == 0x88) ? 1 : 0;
-
- /* extract the calling number / plan / screen */
- if (extract_NCOParameter(skb, PAR_CallingNumber, phone,
- PHONE_MAXIMUMSIZE + 4)) {
- printk(KERN_ERR "TurboPAM(parse_CConnectInd): "
- "CallingNumber not found\n");
- return -1;
- }
- memcpy(calling, phone + 4, PHONE_MAXIMUMSIZE);
- *plan = phone[1];
- *screen = phone[3];
-
- /* extract the called number */
- if (extract_NCOParameter(skb, PAR_CalledNumber, phone,
- PHONE_MAXIMUMSIZE + 2)) {
- printk(KERN_ERR "TurboPAM(parse_CConnectInd): "
- "CalledNumber not found\n");
- return -1;
- }
- memcpy(called, phone + 2, PHONE_MAXIMUMSIZE);
-
- pr_debug("TurboPAM(parse_CConnectInd): "
- "ncoid=%lu, hdlc=%d, plan=%d, scr=%d, calling=%s, called=%s\n",
- (unsigned long)*ncoid, *hdlc, *plan, *screen, calling, called);
- return 0;
-}
-
-/*
- * Parse a CDisconnectCnf message.
- *
- * skb: the sk_buff containing the message
- * ncoid: to be filled with the ncoid field value
- * causetopuf: to be filled with the cause field value
- *
- * Return: 0 if OK, <0 if error.
- */
-int parse_CDisconnectCnf(struct sk_buff *skb, u32 *ncoid, u32 *causetopuf) {
-
- /* extract the ncoid */
- if (extract_NCOParameter(skb, PAR_NCOID, ncoid, 4)) {
- printk(KERN_ERR "TurboPAM(parse_CDisconnectCnf): "
- "NCOID not found\n");
- return -1;
- }
-
- /* extract the cause of disconnection */
- if (extract_NCOParameter(skb, PAR_CauseToPUF, causetopuf, 4)) {
- printk(KERN_ERR "TurboPAM(parse_CDisconnectCnf): "
- "CauseToPUF not found\n");
- return -1;
- }
-
- pr_debug("TurboPAM(parse_CDisconnectCnf): ncoid=%lu, causetopuf=%lu\n",
- (unsigned long)*ncoid, (unsigned long)*causetopuf);
- return 0;
-}
-
-/*
- * Parse a CDisconnectInd message.
- *
- * skb: the sk_buff containing the message
- * ncoid: to be filled with the ncoid field value
- * causetopuf: to be filled with the cause field value
- *
- * Return: 0 if OK, <0 if error.
- */
-int parse_CDisconnectInd(struct sk_buff *skb, u32 *ncoid, u32 *causetopuf) {
-
- /* extract the ncoid */
- if (extract_NCOParameter(skb, PAR_NCOID, ncoid, 4)) {
- printk(KERN_ERR "TurboPAM(parse_CDisconnectInd): "
- "NCOID not found\n");
- return -1;
- }
-
- /* extract the cause of disconnection */
- if (extract_NCOParameter(skb, PAR_CauseToPUF, causetopuf, 4)) {
- printk(KERN_ERR "TurboPAM(parse_CDisconnectInd): "
- "CauseToPUF not found\n");
- return -1;
- }
-
- pr_debug("TurboPAM(parse_CDisconnectInd): ncoid=%lu, causetopuf=%lu\n",
- (unsigned long)*ncoid, (unsigned long)*causetopuf);
- return 0;
-}
-
-/*
- * Parse a U3ReadyToReceiveInd message.
- *
- * skb: the sk_buff containing the message
- * ncoid: to be filled with the ncoid field value
- * ready: to be filled with the ready field value
- *
- * Return: 0 if OK, <0 if error.
- */
-int parse_U3ReadyToReceiveInd(struct sk_buff *skb, u32 *ncoid, u8 *ready) {
-
- /* extract the ncoid */
- if (extract_NCOParameter(skb, PAR_NCOID, ncoid, 4)) {
- printk(KERN_ERR "TurboPAM(parse_U3ReadyToReceiveInd): "
- "NCOID not found\n");
- return -1;
- }
-
- /* extract the ready flag */
- if (extract_NCOParameter(skb, PAR_ReadyFlag, ready, 1)) {
- printk(KERN_ERR "TurboPAM(parse_U3ReadyToReceiveInd): "
- "ReadyFlag not found\n");
- return -1;
- }
-
- pr_debug("TurboPAM(parse_U3ReadyToReceiveInd): ncoid=%lu, ready=%d\n",
- (unsigned long)*ncoid, *ready);
- return 0;
-}
-
-/*
- * Parse a U3DataInd message.
- *
- * skb: the sk_buff containing the message + data
- * ncoid: to be filled with the ncoid field value
- * data: to be filled with the data
- * ready: to be filled with the data length
- *
- * Return: 0 if OK, <0 if error.
- */
-int parse_U3DataInd(struct sk_buff *skb, u32 *ncoid, u8 **data, u16 *len) {
- pci_mpb *p;
-
- /* extract the ncoid */
- if (extract_NCOParameter(skb, PAR_NCOID, ncoid, 4) == -1) {
- printk(KERN_ERR "TurboPAM(parse_U3DataInd): NCOID not found\n");
- return -1;
- }
-
- /* get a pointer to the beginning of the data block and its length */
- p = (pci_mpb *)(skb->data + sizeof(skb_header));
- *len = p->actualDataSize;
- skb_pull(skb,
- sizeof(skb_header) + sizeof(pci_mpb) + p->actualBlockTLVSize);
- *data = skb->data;
-
- pr_debug("TurboPAM(parse_U3DataInd): ncoid=%lu, datalen=%d\n",
- (unsigned long)*ncoid, *len);
- return 0;
-}
-
diff --git a/drivers/isdn/tpam/tpam_queues.c b/drivers/isdn/tpam/tpam_queues.c
deleted file mode 100644
index 35add91b83a2f..0000000000000
--- a/drivers/isdn/tpam/tpam_queues.c
+++ /dev/null
@@ -1,401 +0,0 @@
-/* $Id: tpam_queues.c,v 1.1.2.2 2001/09/23 22:25:03 kai Exp $
- *
- * Turbo PAM ISDN driver for Linux. (Kernel Driver)
- *
- * Copyright 2001 Stelian Pop <stelian.pop@fr.alcove.com>, Alcôve
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- * For all support questions please contact: <support@auvertech.fr>
- *
- */
-
-#include <linux/pci.h>
-#include <linux/sched.h>
-#include <linux/workqueue.h>
-#include <linux/interrupt.h>
-#include <asm/io.h>
-
-#include "tpam.h"
-
-/* Local function prototype */
-static int tpam_sendpacket(tpam_card *card, tpam_channel *channel);
-
-/*
- * Queue a message to be send to the card when possible.
- *
- * card: the board
- * skb: the sk_buff containing the message.
- */
-void tpam_enqueue(tpam_card *card, struct sk_buff *skb) {
-
- pr_debug("TurboPAM(tpam_enqueue): card=%d\n", card->id);
-
- /* queue the sk_buff on the board's send queue */
- skb_queue_tail(&card->sendq, skb);
-
- /* queue the board's send task struct for immediate treatment */
- schedule_work(&card->send_tq);
-}
-
-/*
- * Queue a data message to be send to the card when possible.
- *
- * card: the board
- * skb: the sk_buff containing the message and the data. This parameter
- * can be NULL if we want just to trigger the send of queued
- * messages.
- */
-void tpam_enqueue_data(tpam_channel *channel, struct sk_buff *skb) {
-
- pr_debug("TurboPAM(tpam_enqueue_data): card=%d, channel=%d\n",
- channel->card->id, channel->num);
-
- /* if existant, queue the sk_buff on the channel's send queue */
- if (skb)
- skb_queue_tail(&channel->sendq, skb);
-
- /* queue the channel's send task struct for immediate treatment */
- schedule_work(&channel->card->send_tq);
-}
-
-/*
- * IRQ handler.
- *
- * If a message comes from the board we read it, construct a sk_buff containing
- * the message and we queue the sk_buff on the board's receive queue, and we
- * trigger the execution of the board's receive task queue.
- *
- * If a message ack comes from the board we can go on and send a new message,
- * so we trigger the execution of the board's send task queue.
- *
- * irq: the irq number
- * dev_id: the registered board to the irq
- * regs: not used.
- */
-irqreturn_t tpam_irq(int irq, void *dev_id, struct pt_regs *regs)
-{
- tpam_card *card = (tpam_card *)dev_id;
- u32 ackupload, uploadptr;
- u32 waiting_too_long;
- u32 hpic;
- struct sk_buff *skb;
- pci_mpb mpb;
- skb_header *skbh;
-
- pr_debug("TurboPAM(tpam_irq): IRQ received, card=%d\n", card->id);
-
- /* grab the board lock */
- spin_lock(&card->lock);
-
- /* get the message type */
- ackupload = copy_from_pam_dword(card, TPAM_ACKUPLOAD_REGISTER);
-
- /* acknowledge the interrupt */
- copy_to_pam_dword(card, TPAM_INTERRUPTACK_REGISTER, 0);
- readl(card->bar0 + TPAM_HINTACK_REGISTER);
-
- if (!ackupload) {
- /* it is a new message from the board */
-
- pr_debug("TurboPAM(tpam_irq): message received, card=%d\n",
- card->id);
-
- /* get the upload pointer */
- uploadptr = copy_from_pam_dword(card,
- TPAM_UPLOADPTR_REGISTER);
-
- /* get the beginning of the message (pci_mpb part) */
- copy_from_pam(card, &mpb, uploadptr, sizeof(pci_mpb));
-
- /* allocate the sk_buff */
- if (!(skb = alloc_skb(sizeof(skb_header) + sizeof(pci_mpb) +
- mpb.actualBlockTLVSize +
- mpb.actualDataSize, GFP_ATOMIC))) {
- printk(KERN_ERR "TurboPAM(tpam_irq): "
- "alloc_skb failed\n");
- spin_unlock(&card->lock);
- return IRQ_HANDLED;
- }
-
- /* build the skb_header */
- skbh = (skb_header *)skb_put(skb, sizeof(skb_header));
- skbh->size = sizeof(pci_mpb) + mpb.actualBlockTLVSize;
- skbh->data_size = mpb.actualDataSize;
- skbh->ack = 0;
- skbh->ack_size = 0;
-
- /* copy the pci_mpb into the sk_buff */
- memcpy(skb_put(skb, sizeof(pci_mpb)), &mpb, sizeof(pci_mpb));
-
- /* copy the TLV block into the sk_buff */
- copy_from_pam(card, skb_put(skb, mpb.actualBlockTLVSize),
- uploadptr + sizeof(pci_mpb),
- mpb.actualBlockTLVSize);
-
- /* if existent, copy the data block into the sk_buff */
- if (mpb.actualDataSize)
- copy_from_pam(card, skb_put(skb, mpb.actualDataSize),
- uploadptr + sizeof(pci_mpb) + 4096,
- mpb.actualDataSize);
-
- /* wait for the board to become ready */
- waiting_too_long = 0;
- do {
- hpic = readl(card->bar0 + TPAM_HPIC_REGISTER);
- if (waiting_too_long++ > 0xfffffff) {
- kfree_skb(skb);
- spin_unlock(&card->lock);
- printk(KERN_ERR "TurboPAM(tpam_irq): "
- "waiting too long...\n");
- return IRQ_HANDLED;
- }
- } while (hpic & 0x00000002);
-
- /* acknowledge the message */
- copy_to_pam_dword(card, TPAM_ACKDOWNLOAD_REGISTER,
- 0xffffffff);
- readl(card->bar0 + TPAM_DSPINT_REGISTER);
-
- /* release the board lock */
- spin_unlock(&card->lock);
-
- if (mpb.messageID == ID_U3ReadyToReceiveInd) {
- /* this message needs immediate treatment */
- tpam_recv_U3ReadyToReceiveInd(card, skb);
- kfree_skb(skb);
- }
- else {
- /* put the message in the receive queue */
- skb_queue_tail(&card->recvq, skb);
- schedule_work(&card->recv_tq);
- }
- return IRQ_HANDLED;
- }
- else {
- /* it is a ack from the board */
-
- pr_debug("TurboPAM(tpam_irq): message acknowledged, card=%d\n",
- card->id);
-
- /* board is not busy anymore */
- card->busy = 0;
-
- /* release the lock */
- spin_unlock(&card->lock);
-
- /* schedule the send queue for execution */
- schedule_work(&card->send_tq);
- }
- return IRQ_HANDLED;
-}
-
-/*
- * Run the board's receive task queue, dispatching each message on the queue,
- * to its treatment function.
- *
- * card: the board.
- */
-void tpam_recv_tq(tpam_card *card) {
- pci_mpb *p;
- struct sk_buff *skb;
-
- /* for each message on the receive queue... */
- while ((skb = skb_dequeue(&card->recvq))) {
-
- /* point to the pci_mpb block */
- p = (pci_mpb *)(skb->data + sizeof(skb_header));
-
- /* dispatch the message */
- switch (p->messageID) {
- case ID_ACreateNCOCnf:
- tpam_recv_ACreateNCOCnf(card, skb);
- break;
- case ID_ADestroyNCOCnf:
- tpam_recv_ADestroyNCOCnf(card, skb);
- break;
- case ID_CConnectCnf:
- tpam_recv_CConnectCnf(card, skb);
- break;
- case ID_CConnectInd:
- tpam_recv_CConnectInd(card, skb);
- break;
- case ID_CDisconnectInd:
- tpam_recv_CDisconnectInd(card, skb);
- break;
- case ID_CDisconnectCnf:
- tpam_recv_CDisconnectCnf(card, skb);
- break;
- case ID_U3DataInd:
- tpam_recv_U3DataInd(card, skb);
- break;
- default:
- pr_debug("TurboPAM(tpam_recv_tq): "
- "unknown messageID %d, card=%d\n",
- p->messageID, card->id);
- break;
- }
- /* free the sk_buff */
- kfree_skb(skb);
- }
-}
-
-/*
- * Run the board's send task queue. If there is a message in the board's send
- * queue, it gets sended. If not, it examines each channel (one at the time,
- * using a round robin algorithm). For each channel, if there is a message
- * in the channel's send queue, it gets sended. This function sends only one
- * message, it does not consume all the queue.
- */
-void tpam_send_tq(tpam_card *card) {
- int i;
-
- /* first, try to send a packet from the board's send queue */
- if (tpam_sendpacket(card, NULL))
- return;
-
- /* then, try each channel, in a round-robin manner */
- for (i=card->roundrobin; i<card->roundrobin+card->channels_used; i++) {
- if (tpam_sendpacket(card,
- &card->channels[i % card->channels_used])) {
- card->roundrobin = (i + 1) % card->channels_used;
- return;
- }
- }
-}
-
-/*
- * Try to send a packet from the board's send queue or from the channel's
- * send queue.
- *
- * card: the board.
- * channel: the channel (if NULL, the packet will be taken from the
- * board's send queue. If not, it will be taken from the
- * channel's send queue.
- *
- * Return: 0 if tpam_send_tq must try another card/channel combination
- * (meaning that no packet has been send), 1 if no more packets
- * can be send at that time (a packet has been send or the card is
- * still busy from a previous send).
- */
-static int tpam_sendpacket(tpam_card *card, tpam_channel *channel) {
- struct sk_buff *skb;
- u32 hpic;
- u32 downloadptr;
- skb_header *skbh;
- u32 waiting_too_long;
-
- pr_debug("TurboPAM(tpam_sendpacket), card=%d, channel=%d\n",
- card->id, channel ? channel->num : -1);
-
- if (channel) {
- /* dequeue a packet from the channel's send queue */
- if (!(skb = skb_dequeue(&channel->sendq))) {
- pr_debug("TurboPAM(tpam_sendpacket): "
- "card=%d, channel=%d, no packet\n",
- card->id, channel->num);
- return 0;
- }
-
- /* if the channel is not ready to receive, requeue the packet
- * and return 0 to give a chance to another channel */
- if (!channel->readytoreceive) {
- pr_debug("TurboPAM(tpam_sendpacket): "
- "card=%d, channel=%d, channel not ready\n",
- card->id, channel->num);
- skb_queue_head(&channel->sendq, skb);
- return 0;
- }
-
- /* grab the board lock */
- spin_lock_irq(&card->lock);
-
- /* if the board is busy, requeue the packet and return 1 since
- * there is no need to try another channel */
- if (card->busy) {
- pr_debug("TurboPAM(tpam_sendpacket): "
- "card=%d, channel=%d, card busy\n",
- card->id, channel->num);
- skb_queue_head(&channel->sendq, skb);
- spin_unlock_irq(&card->lock);
- return 1;
- }
- }
- else {
- /* dequeue a packet from the board's send queue */
- if (!(skb = skb_dequeue(&card->sendq))) {
- pr_debug("TurboPAM(tpam_sendpacket): "
- "card=%d, no packet\n", card->id);
- return 0;
- }
-
- /* grab the board lock */
- spin_lock_irq(&card->lock);
-
- /* if the board is busy, requeue the packet and return 1 since
- * there is no need to try another channel */
- if (card->busy) {
- pr_debug("TurboPAM(tpam_sendpacket): "
- "card=%d, card busy\n", card->id);
- skb_queue_head(&card->sendq, skb);
- spin_unlock_irq(&card->lock);
- return 1;
- }
- }
-
- /* wait for the board to become ready */
- waiting_too_long = 0;
- do {
- hpic = readl(card->bar0 + TPAM_HPIC_REGISTER);
- if (waiting_too_long++ > 0xfffffff) {
- spin_unlock_irq(&card->lock);
- printk(KERN_ERR "TurboPAM(tpam_sendpacket): "
- "waiting too long...\n");
- return 1;
- }
- } while (hpic & 0x00000002);
-
- skbh = (skb_header *)skb->data;
- pr_debug("TurboPAM(tpam_sendpacket): "
- "card=%d, card ready, sending %d/%d bytes\n",
- card->id, skbh->size, skbh->data_size);
-
- /* get the board's download pointer */
- downloadptr = copy_from_pam_dword(card, TPAM_DOWNLOADPTR_REGISTER);
-
- /* copy the packet to the board at the downloadptr location */
- copy_to_pam(card, downloadptr, skb->data + sizeof(skb_header),
- skbh->size);
- if (skbh->data_size)
- /* if there is some data in the packet, copy it too */
- copy_to_pam(card, downloadptr + sizeof(pci_mpb) + 4096,
- skb->data + sizeof(skb_header) + skbh->size,
- skbh->data_size);
-
- /* card will become busy right now */
- card->busy = 1;
-
- /* interrupt the board */
- copy_to_pam_dword(card, TPAM_ACKDOWNLOAD_REGISTER, 0);
- readl(card->bar0 + TPAM_DSPINT_REGISTER);
-
- /* release the lock */
- spin_unlock_irq(&card->lock);
-
- /* if a data ack was requested by the ISDN link layer, send it now */
- if (skbh->ack) {
- isdn_ctrl ctrl;
- ctrl.driver = card->id;
- ctrl.command = ISDN_STAT_BSENT;
- ctrl.arg = channel->num;
- ctrl.parm.length = skbh->ack_size;
- (* card->interface.statcallb)(&ctrl);
- }
-
- /* free the sk_buff */
- kfree_skb(skb);
-
- return 1;
-}
-
diff --git a/drivers/macintosh/Kconfig b/drivers/macintosh/Kconfig
index f87ed85539d5f..8a7117a08cf09 100644
--- a/drivers/macintosh/Kconfig
+++ b/drivers/macintosh/Kconfig
@@ -78,6 +78,14 @@ config ADB_PMU
this device; you should do so if your machine is one of those
mentioned above.
+config PMAC_SMU
+ bool "Support for SMU based PowerMacs"
+ depends on PPC_PMAC64
+ help
+ This option adds support for the newer G5 iMacs and PowerMacs based
+ on the "SMU" system control chip which replaces the old PMU.
+ If you don't know, say Y.
+
config PMAC_PBOOK
bool "Power management support for PowerBooks"
depends on ADB_PMU
diff --git a/drivers/macintosh/Makefile b/drivers/macintosh/Makefile
index 8775a4119b50f..c3a4705a82953 100644
--- a/drivers/macintosh/Makefile
+++ b/drivers/macintosh/Makefile
@@ -15,6 +15,7 @@ obj-$(CONFIG_ANSLCD) += ans-lcd.o
obj-$(CONFIG_ADB_PMU) += via-pmu.o
obj-$(CONFIG_ADB_CUDA) += via-cuda.o
obj-$(CONFIG_PMAC_APM_EMU) += apm_emu.o
+obj-$(CONFIG_PMAC_SMU) += smu.o
obj-$(CONFIG_ADB) += adb.o
obj-$(CONFIG_ADB_MACII) += via-macii.o
diff --git a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c
index 5855bbf02e277..7297c77f99cfb 100644
--- a/drivers/macintosh/adb.c
+++ b/drivers/macintosh/adb.c
@@ -755,7 +755,7 @@ static int adb_release(struct inode *inode, struct file *file)
static ssize_t adb_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
- int ret;
+ int ret = 0;
struct adbdev_state *state = file->private_data;
struct adb_request *req;
wait_queue_t wait = __WAITQUEUE_INITIALIZER(wait,current);
@@ -765,9 +765,8 @@ static ssize_t adb_read(struct file *file, char __user *buf,
return -EINVAL;
if (count > sizeof(req->reply))
count = sizeof(req->reply);
- ret = verify_area(VERIFY_WRITE, buf, count);
- if (ret)
- return ret;
+ if (!access_ok(VERIFY_WRITE, buf, count))
+ return -EFAULT;
req = NULL;
spin_lock_irqsave(&state->lock, flags);
@@ -824,9 +823,8 @@ static ssize_t adb_write(struct file *file, const char __user *buf,
return -EINVAL;
if (adb_controller == NULL)
return -ENXIO;
- ret = verify_area(VERIFY_READ, buf, count);
- if (ret)
- return ret;
+ if (!access_ok(VERIFY_READ, buf, count))
+ return -EFAULT;
req = (struct adb_request *) kmalloc(sizeof(struct adb_request),
GFP_KERNEL);
diff --git a/drivers/macintosh/ans-lcd.c b/drivers/macintosh/ans-lcd.c
index c5adb05e3ff09..5e0811dc6536a 100644
--- a/drivers/macintosh/ans-lcd.c
+++ b/drivers/macintosh/ans-lcd.c
@@ -61,7 +61,7 @@ anslcd_write( struct file * file, const char __user * buf,
printk(KERN_DEBUG "LCD: write\n");
#endif
- if ( verify_area(VERIFY_READ, buf, count) )
+ if (!access_ok(VERIFY_READ, buf, count))
return -EFAULT;
for ( i = *ppos; count > 0; ++i, ++p, --count )
{
diff --git a/drivers/macintosh/macio_asic.c b/drivers/macintosh/macio_asic.c
index 401d8ac742c33..3a609ecd251bd 100644
--- a/drivers/macintosh/macio_asic.c
+++ b/drivers/macintosh/macio_asic.c
@@ -617,7 +617,7 @@ static int __init macio_module_init (void)
#ifdef CONFIG_PCI
int rc;
- rc = pci_module_init(&macio_pci_driver);
+ rc = pci_register_driver(&macio_pci_driver);
if (rc)
return rc;
#endif /* CONFIG_PCI */
diff --git a/drivers/macintosh/macserial.c b/drivers/macintosh/macserial.c
index ad0f620f04a09..0be3ac6cc1699 100644
--- a/drivers/macintosh/macserial.c
+++ b/drivers/macintosh/macserial.c
@@ -155,7 +155,7 @@ static void dbdma_flush(volatile struct dbdma_regs *dma);
static irqreturn_t rs_txdma_irq(int irq, void *dev_id, struct pt_regs *regs);
static irqreturn_t rs_rxdma_irq(int irq, void *dev_id, struct pt_regs *regs);
static void dma_init(struct mac_serial * info);
-static void rxdma_start(struct mac_serial * info, int current);
+static void rxdma_start(struct mac_serial * info, int curr);
static void rxdma_to_tty(struct mac_serial * info);
/*
@@ -762,10 +762,10 @@ static int startup(struct mac_serial * info)
return 0;
}
-static _INLINE_ void rxdma_start(struct mac_serial * info, int current)
+static _INLINE_ void rxdma_start(struct mac_serial * info, int curr)
{
volatile struct dbdma_regs *rd = &info->rx->dma;
- volatile struct dbdma_cmd *cd = info->rx_cmds[current];
+ volatile struct dbdma_cmd *cd = info->rx_cmds[curr];
//printk(KERN_DEBUG "SCC: rxdma_start\n");
diff --git a/drivers/macintosh/mediabay.c b/drivers/macintosh/mediabay.c
index 9f0e47d28be2f..b8b5a2f1485a4 100644
--- a/drivers/macintosh/mediabay.c
+++ b/drivers/macintosh/mediabay.c
@@ -98,11 +98,6 @@ int media_bay_count = 0;
#define MB_IDE_READY(i) ((readb(media_bays[i].cd_base + 0x70) & 0x80) == 0)
#endif
-/* Note: All delays are not in milliseconds and converted to HZ relative
- * values by the macro below
- */
-#define MS_TO_HZ(ms) ((ms * HZ + 999) / 1000)
-
/*
* Wait that number of ms between each step in normal polling mode
*/
@@ -384,7 +379,7 @@ static inline void __pmac set_mb_power(struct media_bay_info* bay, int onoff)
bay->state = mb_powering_down;
MBDBG("mediabay%d: powering down\n", bay->index);
}
- bay->timer = MS_TO_HZ(MB_POWER_DELAY);
+ bay->timer = msecs_to_jiffies(MB_POWER_DELAY);
}
static void __pmac poll_media_bay(struct media_bay_info* bay)
@@ -393,8 +388,8 @@ static void __pmac poll_media_bay(struct media_bay_info* bay)
if (id == bay->last_value) {
if (id != bay->content_id) {
- bay->value_count += MS_TO_HZ(MB_POLL_DELAY);
- if (bay->value_count >= MS_TO_HZ(MB_STABLE_DELAY)) {
+ bay->value_count += msecs_to_jiffies(MB_POLL_DELAY);
+ if (bay->value_count >= msecs_to_jiffies(MB_STABLE_DELAY)) {
/* If the device type changes without going thru
* "MB_NO", we force a pass by "MB_NO" to make sure
* things are properly reset
@@ -504,7 +499,7 @@ static void __pmac media_bay_step(int i)
/* If timer expired or polling IDE busy, run state machine */
if ((bay->state != mb_ide_waiting) && (bay->timer != 0)) {
- bay->timer -= MS_TO_HZ(MB_POLL_DELAY);
+ bay->timer -= msecs_to_jiffies(MB_POLL_DELAY);
if (bay->timer > 0)
return;
bay->timer = 0;
@@ -517,13 +512,13 @@ static void __pmac media_bay_step(int i)
set_mb_power(bay, 0);
break;
}
- bay->timer = MS_TO_HZ(MB_RESET_DELAY);
+ bay->timer = msecs_to_jiffies(MB_RESET_DELAY);
bay->state = mb_enabling_bay;
MBDBG("mediabay%d: enabling (kind:%d)\n", i, bay->content_id);
break;
case mb_enabling_bay:
bay->ops->un_reset(bay);
- bay->timer = MS_TO_HZ(MB_SETUP_DELAY);
+ bay->timer = msecs_to_jiffies(MB_SETUP_DELAY);
bay->state = mb_resetting;
MBDBG("mediabay%d: waiting reset (kind:%d)\n", i, bay->content_id);
break;
@@ -537,7 +532,7 @@ static void __pmac media_bay_step(int i)
#ifdef CONFIG_BLK_DEV_IDE
MBDBG("mediabay%d: waiting IDE reset (kind:%d)\n", i, bay->content_id);
bay->ops->un_reset_ide(bay);
- bay->timer = MS_TO_HZ(MB_IDE_WAIT);
+ bay->timer = msecs_to_jiffies(MB_IDE_WAIT);
bay->state = mb_ide_resetting;
#else
printk(KERN_DEBUG "media-bay %d is ide (not compiled in kernel)\n", i);
@@ -547,7 +542,7 @@ static void __pmac media_bay_step(int i)
#ifdef CONFIG_BLK_DEV_IDE
case mb_ide_resetting:
- bay->timer = MS_TO_HZ(MB_IDE_TIMEOUT);
+ bay->timer = msecs_to_jiffies(MB_IDE_TIMEOUT);
bay->state = mb_ide_waiting;
MBDBG("mediabay%d: waiting IDE ready (kind:%d)\n", i, bay->content_id);
break;
@@ -583,7 +578,7 @@ static void __pmac media_bay_step(int i)
}
break;
} else if (bay->timer > 0)
- bay->timer -= MS_TO_HZ(MB_POLL_DELAY);
+ bay->timer -= msecs_to_jiffies(MB_POLL_DELAY);
if (bay->timer <= 0) {
printk("\nIDE Timeout in bay %d !, IDE state is: 0x%02x\n",
i, readb(bay->cd_base + 0x70));
@@ -641,8 +636,7 @@ static int __pmac media_bay_task(void *x)
up(&media_bays[i].lock);
}
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(MS_TO_HZ(MB_POLL_DELAY));
+ msleep_interruptible(MB_POLL_DELAY);
if (signal_pending(current))
return 0;
}
@@ -691,7 +685,7 @@ static int __devinit media_bay_attach(struct macio_dev *mdev, const struct of_ma
msleep(MB_POWER_DELAY);
bay->content_id = MB_NO;
bay->last_value = bay->ops->content(bay);
- bay->value_count = MS_TO_HZ(MB_STABLE_DELAY);
+ bay->value_count = msecs_to_jiffies(MB_STABLE_DELAY);
bay->state = mb_empty;
do {
msleep(MB_POLL_DELAY);
@@ -747,8 +741,8 @@ static int __pmac media_bay_resume(struct macio_dev *mdev)
}
set_mb_power(bay, 1);
bay->last_value = bay->content_id;
- bay->value_count = MS_TO_HZ(MB_STABLE_DELAY);
- bay->timer = MS_TO_HZ(MB_POWER_DELAY);
+ bay->value_count = msecs_to_jiffies(MB_STABLE_DELAY);
+ bay->timer = msecs_to_jiffies(MB_POWER_DELAY);
#ifdef CONFIG_BLK_DEV_IDE
bay->cd_retry = 0;
#endif
diff --git a/drivers/macintosh/nvram.c b/drivers/macintosh/nvram.c
index 9e714f09184b2..30791875fc975 100644
--- a/drivers/macintosh/nvram.c
+++ b/drivers/macintosh/nvram.c
@@ -45,7 +45,7 @@ static ssize_t read_nvram(struct file *file, char __user *buf,
unsigned int i;
char __user *p = buf;
- if (verify_area(VERIFY_WRITE, buf, count))
+ if (!access_ok(VERIFY_WRITE, buf, count))
return -EFAULT;
if (*ppos >= NVRAM_SIZE)
return 0;
@@ -63,7 +63,7 @@ static ssize_t write_nvram(struct file *file, const char __user *buf,
const char __user *p = buf;
char c;
- if (verify_area(VERIFY_READ, buf, count))
+ if (!access_ok(VERIFY_READ, buf, count))
return -EFAULT;
if (*ppos >= NVRAM_SIZE)
return 0;
diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c
new file mode 100644
index 0000000000000..fb535737d17d1
--- /dev/null
+++ b/drivers/macintosh/smu.c
@@ -0,0 +1,364 @@
+/*
+ * PowerMac G5 SMU driver
+ *
+ * Copyright 2004 J. Mayer <l_indien@magic.fr>
+ * Copyright 2005 Benjamin Herrenschmidt, IBM Corp.
+ *
+ * Released under the term of the GNU GPL v2.
+ */
+
+/*
+ * For now, this driver includes:
+ * - RTC get & set
+ * - reboot & shutdown commands
+ * all synchronous with IRQ disabled (ugh)
+ *
+ * TODO:
+ * rework in a way the PMU driver works, that is asynchronous
+ * with a queue of commands. I'll do that as soon as I have an
+ * SMU based machine at hand. Some more cleanup is needed too,
+ * like maybe fitting it into a platform device, etc...
+ * Also check what's up with cache coherency, and if we really
+ * can't do better than flushing the cache, maybe build a table
+ * of command len/reply len like the PMU driver to only flush
+ * what is actually necessary.
+ * --BenH.
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/dmapool.h>
+#include <linux/bootmem.h>
+#include <linux/vmalloc.h>
+#include <linux/highmem.h>
+#include <linux/jiffies.h>
+#include <linux/interrupt.h>
+#include <linux/rtc.h>
+
+#include <asm/byteorder.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/machdep.h>
+#include <asm/pmac_feature.h>
+#include <asm/smu.h>
+#include <asm/sections.h>
+#include <asm/abs_addr.h>
+
+#define DEBUG_SMU 1
+
+#ifdef DEBUG_SMU
+#define DPRINTK(fmt, args...) do { printk(KERN_DEBUG fmt , ##args); } while (0)
+#else
+#define DPRINTK(fmt, args...) do { } while (0)
+#endif
+
+/*
+ * This is the command buffer passed to the SMU hardware
+ */
+struct smu_cmd_buf {
+ u8 cmd;
+ u8 length;
+ u8 data[0x0FFE];
+};
+
+struct smu_device {
+ spinlock_t lock;
+ struct device_node *of_node;
+ int db_ack; /* doorbell ack GPIO */
+ int db_req; /* doorbell req GPIO */
+ u32 __iomem *db_buf; /* doorbell buffer */
+ struct smu_cmd_buf *cmd_buf; /* command buffer virtual */
+ u32 cmd_buf_abs; /* command buffer absolute */
+};
+
+/*
+ * I don't think there will ever be more than one SMU, so
+ * for now, just hard code that
+ */
+static struct smu_device *smu;
+
+/*
+ * SMU low level communication stuff
+ */
+static inline int smu_cmd_stat(struct smu_cmd_buf *cmd_buf, u8 cmd_ack)
+{
+ rmb();
+ return cmd_buf->cmd == cmd_ack && cmd_buf->length != 0;
+}
+
+static inline u8 smu_save_ack_cmd(struct smu_cmd_buf *cmd_buf)
+{
+ return (~cmd_buf->cmd) & 0xff;
+}
+
+static void smu_send_cmd(struct smu_device *dev)
+{
+ /* SMU command buf is currently cacheable, we need a physical
+ * address. This isn't exactly a DMA mapping here, I suspect
+ * the SMU is actually communicating with us via i2c to the
+ * northbridge or the CPU to access RAM.
+ */
+ writel(dev->cmd_buf_abs, dev->db_buf);
+
+ /* Ring the SMU doorbell */
+ pmac_do_feature_call(PMAC_FTR_WRITE_GPIO, NULL, dev->db_req, 4);
+ pmac_do_feature_call(PMAC_FTR_READ_GPIO, NULL, dev->db_req, 4);
+}
+
+static int smu_cmd_done(struct smu_device *dev)
+{
+ unsigned long wait = 0;
+ int gpio;
+
+ /* Check the SMU doorbell */
+ do {
+ gpio = pmac_do_feature_call(PMAC_FTR_READ_GPIO,
+ NULL, dev->db_ack);
+ if ((gpio & 7) == 7)
+ return 0;
+ udelay(100);
+ } while(++wait < 10000);
+
+ printk(KERN_ERR "SMU timeout !\n");
+ return -ENXIO;
+}
+
+static int smu_do_cmd(struct smu_device *dev)
+{
+ int rc;
+ u8 cmd_ack;
+
+ DPRINTK("SMU do_cmd %02x len=%d %02x\n",
+ dev->cmd_buf->cmd, dev->cmd_buf->length,
+ dev->cmd_buf->data[0]);
+
+ cmd_ack = smu_save_ack_cmd(dev->cmd_buf);
+
+ /* Clear cmd_buf cache lines */
+ flush_inval_dcache_range((unsigned long)dev->cmd_buf,
+ ((unsigned long)dev->cmd_buf) +
+ sizeof(struct smu_cmd_buf));
+ smu_send_cmd(dev);
+ rc = smu_cmd_done(dev);
+ if (rc == 0)
+ rc = smu_cmd_stat(dev->cmd_buf, cmd_ack) ? 0 : -1;
+
+ DPRINTK("SMU do_cmd %02x len=%d %02x => %d (%02x)\n",
+ dev->cmd_buf->cmd, dev->cmd_buf->length,
+ dev->cmd_buf->data[0], rc, cmd_ack);
+
+ return rc;
+}
+
+/* RTC low level commands */
+static inline int bcd2hex (int n)
+{
+ return (((n & 0xf0) >> 4) * 10) + (n & 0xf);
+}
+
+static inline int hex2bcd (int n)
+{
+ return ((n / 10) << 4) + (n % 10);
+}
+
+#if 0
+static inline void smu_fill_set_pwrup_timer_cmd(struct smu_cmd_buf *cmd_buf)
+{
+ cmd_buf->cmd = 0x8e;
+ cmd_buf->length = 8;
+ cmd_buf->data[0] = 0x00;
+ memset(cmd_buf->data + 1, 0, 7);
+}
+
+static inline void smu_fill_get_pwrup_timer_cmd(struct smu_cmd_buf *cmd_buf)
+{
+ cmd_buf->cmd = 0x8e;
+ cmd_buf->length = 1;
+ cmd_buf->data[0] = 0x01;
+}
+
+static inline void smu_fill_dis_pwrup_timer_cmd(struct smu_cmd_buf *cmd_buf)
+{
+ cmd_buf->cmd = 0x8e;
+ cmd_buf->length = 1;
+ cmd_buf->data[0] = 0x02;
+}
+#endif
+
+static inline void smu_fill_set_rtc_cmd(struct smu_cmd_buf *cmd_buf,
+ struct rtc_time *time)
+{
+ cmd_buf->cmd = 0x8e;
+ cmd_buf->length = 8;
+ cmd_buf->data[0] = 0x80;
+ cmd_buf->data[1] = hex2bcd(time->tm_sec);
+ cmd_buf->data[2] = hex2bcd(time->tm_min);
+ cmd_buf->data[3] = hex2bcd(time->tm_hour);
+ cmd_buf->data[4] = time->tm_wday;
+ cmd_buf->data[5] = hex2bcd(time->tm_mday);
+ cmd_buf->data[6] = hex2bcd(time->tm_mon) + 1;
+ cmd_buf->data[7] = hex2bcd(time->tm_year - 100);
+}
+
+static inline void smu_fill_get_rtc_cmd(struct smu_cmd_buf *cmd_buf)
+{
+ cmd_buf->cmd = 0x8e;
+ cmd_buf->length = 1;
+ cmd_buf->data[0] = 0x81;
+}
+
+static void smu_parse_get_rtc_reply(struct smu_cmd_buf *cmd_buf,
+ struct rtc_time *time)
+{
+ time->tm_sec = bcd2hex(cmd_buf->data[0]);
+ time->tm_min = bcd2hex(cmd_buf->data[1]);
+ time->tm_hour = bcd2hex(cmd_buf->data[2]);
+ time->tm_wday = bcd2hex(cmd_buf->data[3]);
+ time->tm_mday = bcd2hex(cmd_buf->data[4]);
+ time->tm_mon = bcd2hex(cmd_buf->data[5]) - 1;
+ time->tm_year = bcd2hex(cmd_buf->data[6]) + 100;
+}
+
+int smu_get_rtc_time(struct rtc_time *time)
+{
+ unsigned long flags;
+ int rc;
+
+ if (smu == NULL)
+ return -ENODEV;
+
+ memset(time, 0, sizeof(struct rtc_time));
+ spin_lock_irqsave(&smu->lock, flags);
+ smu_fill_get_rtc_cmd(smu->cmd_buf);
+ rc = smu_do_cmd(smu);
+ if (rc == 0)
+ smu_parse_get_rtc_reply(smu->cmd_buf, time);
+ spin_unlock_irqrestore(&smu->lock, flags);
+
+ return rc;
+}
+
+int smu_set_rtc_time(struct rtc_time *time)
+{
+ unsigned long flags;
+ int rc;
+
+ if (smu == NULL)
+ return -ENODEV;
+
+ spin_lock_irqsave(&smu->lock, flags);
+ smu_fill_set_rtc_cmd(smu->cmd_buf, time);
+ rc = smu_do_cmd(smu);
+ spin_unlock_irqrestore(&smu->lock, flags);
+
+ return rc;
+}
+
+void smu_shutdown(void)
+{
+ const unsigned char *command = "SHUTDOWN";
+ unsigned long flags;
+
+ if (smu == NULL)
+ return;
+
+ spin_lock_irqsave(&smu->lock, flags);
+ smu->cmd_buf->cmd = 0xaa;
+ smu->cmd_buf->length = strlen(command);
+ strcpy(smu->cmd_buf->data, command);
+ smu_do_cmd(smu);
+ for (;;)
+ ;
+ spin_unlock_irqrestore(&smu->lock, flags);
+}
+
+void smu_restart(void)
+{
+ const unsigned char *command = "RESTART";
+ unsigned long flags;
+
+ if (smu == NULL)
+ return;
+
+ spin_lock_irqsave(&smu->lock, flags);
+ smu->cmd_buf->cmd = 0xaa;
+ smu->cmd_buf->length = strlen(command);
+ strcpy(smu->cmd_buf->data, command);
+ smu_do_cmd(smu);
+ for (;;)
+ ;
+ spin_unlock_irqrestore(&smu->lock, flags);
+}
+
+int smu_present(void)
+{
+ return smu != NULL;
+}
+
+
+int smu_init (void)
+{
+ struct device_node *np;
+ u32 *data;
+
+ np = of_find_node_by_type(NULL, "smu");
+ if (np == NULL)
+ return -ENODEV;
+
+ if (smu_cmdbuf_abs == 0) {
+ printk(KERN_ERR "SMU: Command buffer not allocated !\n");
+ return -EINVAL;
+ }
+
+ smu = alloc_bootmem(sizeof(struct smu_device));
+ if (smu == NULL)
+ return -ENOMEM;
+ memset(smu, 0, sizeof(*smu));
+
+ spin_lock_init(&smu->lock);
+ smu->of_node = np;
+ /* smu_cmdbuf_abs is in the low 2G of RAM, can be converted to a
+ * 32 bits value safely
+ */
+ smu->cmd_buf_abs = (u32)smu_cmdbuf_abs;
+ smu->cmd_buf = (struct smu_cmd_buf *)abs_to_virt(smu_cmdbuf_abs);
+
+ np = of_find_node_by_name(NULL, "smu-doorbell");
+ if (np == NULL) {
+ printk(KERN_ERR "SMU: Can't find doorbell GPIO !\n");
+ goto fail;
+ }
+ data = (u32 *)get_property(np, "reg", NULL);
+ of_node_put(np);
+ if (data == NULL) {
+ printk(KERN_ERR "SMU: Can't find doorbell GPIO address !\n");
+ goto fail;
+ }
+
+ /* Current setup has one doorbell GPIO that does both doorbell
+ * and ack. GPIOs are at 0x50, best would be to find that out
+ * in the device-tree though.
+ */
+ smu->db_req = 0x50 + *data;
+ smu->db_ack = 0x50 + *data;
+
+ /* Doorbell buffer is currently hard-coded, I didn't find a proper
+ * device-tree entry giving the address. Best would probably to use
+ * an offset for K2 base though, but let's do it that way for now.
+ */
+ smu->db_buf = ioremap(0x8000860c, 0x1000);
+ if (smu->db_buf == NULL) {
+ printk(KERN_ERR "SMU: Can't map doorbell buffer pointer !\n");
+ goto fail;
+ }
+
+ sys_ctrler = SYS_CTRLER_SMU;
+ return 0;
+
+ fail:
+ smu = NULL;
+ return -ENXIO;
+
+}
diff --git a/drivers/macintosh/therm_adt746x.c b/drivers/macintosh/therm_adt746x.c
index cce6b36427268..e0ac63effa554 100644
--- a/drivers/macintosh/therm_adt746x.c
+++ b/drivers/macintosh/therm_adt746x.c
@@ -548,7 +548,15 @@ thermostat_init(void)
prop = (u32 *)get_property(np, "reg", NULL);
if (!prop)
return -ENODEV;
- therm_bus = ((*prop) >> 8) & 0x0f;
+
+ /* look for bus either by path or using "reg" */
+ if (strstr(np->full_name, "/i2c-bus@") != NULL) {
+ const char *tmp_bus = (strstr(np->full_name, "/i2c-bus@") + 9);
+ therm_bus = tmp_bus[0]-'0';
+ } else {
+ therm_bus = ((*prop) >> 8) & 0x0f;
+ }
+
therm_address = ((*prop) & 0xff) >> 1;
printk(KERN_INFO "adt746x: Thermostat bus: %d, address: 0x%02x, "
diff --git a/drivers/macintosh/therm_pm72.c b/drivers/macintosh/therm_pm72.c
index 3c606ef981704..82336a5a54744 100644
--- a/drivers/macintosh/therm_pm72.c
+++ b/drivers/macintosh/therm_pm72.c
@@ -47,8 +47,11 @@
* decisions, like slewing down CPUs
* - Deal with fan and i2c failures in a better way
* - Maybe do a generic PID based on params used for
- * U3 and Drives ?
- * - Add RackMac3,1 support (XServe g5)
+ * U3 and Drives ? Definitely need to factor code a bit
+ * bettter... also make sensor detection more robust using
+ * the device-tree to probe for them
+ * - Figure out how to get the slots consumption and set the
+ * slots fan accordingly
*
* History:
*
@@ -85,6 +88,13 @@
* - Add new CPU cooling algorithm for machines with liquid cooling
* - Workaround for some PowerMac7,3 with empty "fan" node in the devtree
* - Fix a signed/unsigned compare issue in some PID loops
+ *
+ * Mar. 10, 2005 : 1.2
+ * - Add basic support for Xserve G5
+ * - Retreive pumps min/max from EEPROM image in device-tree (broken)
+ * - Use min/max macros here or there
+ * - Latest darwin updated U3H min fan speed to 20% PWM
+ *
*/
#include <linux/config.h>
@@ -113,7 +123,7 @@
#include "therm_pm72.h"
-#define VERSION "1.1"
+#define VERSION "1.2b2"
#undef DEBUG
@@ -131,21 +141,26 @@
static struct of_device * of_dev;
static struct i2c_adapter * u3_0;
static struct i2c_adapter * u3_1;
+static struct i2c_adapter * k2;
static struct i2c_client * fcu;
static struct cpu_pid_state cpu_state[2];
static struct basckside_pid_params backside_params;
static struct backside_pid_state backside_state;
static struct drives_pid_state drives_state;
+static struct dimm_pid_state dimms_state;
static int state;
static int cpu_count;
static int cpu_pid_type;
static pid_t ctrl_task;
static struct completion ctrl_complete;
static int critical_state;
+static int rackmac;
+static s32 dimm_output_clamp;
+
static DECLARE_MUTEX(driver_lock);
/*
- * We have 2 types of CPU PID control. One is "split" old style control
+ * We have 3 types of CPU PID control. One is "split" old style control
* for intake & exhaust fans, the other is "combined" control for both
* CPUs that also deals with the pumps when present. To be "compatible"
* with OS X at this point, we only use "COMBINED" on the machines that
@@ -155,6 +170,7 @@ static DECLARE_MUTEX(driver_lock);
*/
#define CPU_PID_TYPE_SPLIT 0
#define CPU_PID_TYPE_COMBINED 1
+#define CPU_PID_TYPE_RACKMAC 2
/*
* This table describes all fans in the FCU. The "id" and "type" values
@@ -177,7 +193,7 @@ struct fcu_fan_table
struct fcu_fan_table fcu_fans[] = {
[BACKSIDE_FAN_PWM_INDEX] = {
- .loc = "BACKSIDE",
+ .loc = "BACKSIDE,SYS CTRLR FAN",
.type = FCU_FAN_PWM,
.id = BACKSIDE_FAN_PWM_DEFAULT_ID,
},
@@ -187,7 +203,7 @@ struct fcu_fan_table fcu_fans[] = {
.id = DRIVES_FAN_RPM_DEFAULT_ID,
},
[SLOTS_FAN_PWM_INDEX] = {
- .loc = "SLOT",
+ .loc = "SLOT,PCI FAN",
.type = FCU_FAN_PWM,
.id = SLOTS_FAN_PWM_DEFAULT_ID,
},
@@ -224,6 +240,37 @@ struct fcu_fan_table fcu_fans[] = {
.type = FCU_FAN_RPM,
.id = FCU_FAN_ABSENT_ID,
},
+ /* Xserve fans */
+ [CPU_A1_FAN_RPM_INDEX] = {
+ .loc = "CPU A 1",
+ .type = FCU_FAN_RPM,
+ .id = FCU_FAN_ABSENT_ID,
+ },
+ [CPU_A2_FAN_RPM_INDEX] = {
+ .loc = "CPU A 2",
+ .type = FCU_FAN_RPM,
+ .id = FCU_FAN_ABSENT_ID,
+ },
+ [CPU_A3_FAN_RPM_INDEX] = {
+ .loc = "CPU A 3",
+ .type = FCU_FAN_RPM,
+ .id = FCU_FAN_ABSENT_ID,
+ },
+ [CPU_B1_FAN_RPM_INDEX] = {
+ .loc = "CPU B 1",
+ .type = FCU_FAN_RPM,
+ .id = FCU_FAN_ABSENT_ID,
+ },
+ [CPU_B2_FAN_RPM_INDEX] = {
+ .loc = "CPU B 2",
+ .type = FCU_FAN_RPM,
+ .id = FCU_FAN_ABSENT_ID,
+ },
+ [CPU_B3_FAN_RPM_INDEX] = {
+ .loc = "CPU B 3",
+ .type = FCU_FAN_RPM,
+ .id = FCU_FAN_ABSENT_ID,
+ },
};
/*
@@ -251,7 +298,9 @@ static struct i2c_client *attach_i2c_chip(int id, const char *name)
struct i2c_client *clt;
struct i2c_adapter *adap;
- if (id & 0x100)
+ if (id & 0x200)
+ adap = k2;
+ else if (id & 0x100)
adap = u3_1;
else
adap = u3_0;
@@ -361,6 +410,31 @@ static int read_smon_adc(struct cpu_pid_state *state, int chan)
}
}
+static int read_lm87_reg(struct i2c_client * chip, int reg)
+{
+ int rc, tries = 0;
+ u8 buf;
+
+ for (;;) {
+ /* Set address */
+ buf = (u8)reg;
+ rc = i2c_master_send(chip, &buf, 1);
+ if (rc <= 0)
+ goto error;
+ rc = i2c_master_recv(chip, &buf, 1);
+ if (rc <= 0)
+ goto error;
+ return (int)buf;
+ error:
+ DBG("Error reading LM87, retrying...\n");
+ if (++tries > 10) {
+ printk(KERN_ERR "therm_pm72: Error reading LM87 !\n");
+ return -1;
+ }
+ msleep(10);
+ }
+}
+
static int fan_read_reg(int reg, unsigned char *buf, int nb)
{
int tries, nr, nw;
@@ -570,6 +644,38 @@ static int read_eeprom(int cpu, struct mpu_data *out)
return 0;
}
+static void fetch_cpu_pumps_minmax(void)
+{
+ struct cpu_pid_state *state0 = &cpu_state[0];
+ struct cpu_pid_state *state1 = &cpu_state[1];
+ u16 pump_min = 0, pump_max = 0xffff;
+ u16 tmp[4];
+
+ /* Try to fetch pumps min/max infos from eeprom */
+
+ memcpy(&tmp, &state0->mpu.processor_part_num, 8);
+ if (tmp[0] != 0xffff && tmp[1] != 0xffff) {
+ pump_min = max(pump_min, tmp[0]);
+ pump_max = min(pump_max, tmp[1]);
+ }
+ if (tmp[2] != 0xffff && tmp[3] != 0xffff) {
+ pump_min = max(pump_min, tmp[2]);
+ pump_max = min(pump_max, tmp[3]);
+ }
+
+ /* Double check the values, this _IS_ needed as the EEPROM on
+ * some dual 2.5Ghz G5s seem, at least, to have both min & max
+ * same to the same value ... (grrrr)
+ */
+ if (pump_min == pump_max || pump_min == 0 || pump_max == 0xffff) {
+ pump_min = CPU_PUMP_OUTPUT_MIN;
+ pump_max = CPU_PUMP_OUTPUT_MAX;
+ }
+
+ state0->pump_min = state1->pump_min = pump_min;
+ state0->pump_max = state1->pump_max = pump_max;
+}
+
/*
* Now, unfortunately, sysfs doesn't give us a nice void * we could
* pass around to the attribute functions, so we don't really have
@@ -611,6 +717,8 @@ BUILD_SHOW_FUNC_INT(backside_fan_pwm, backside_state.pwm)
BUILD_SHOW_FUNC_FIX(drives_temperature, drives_state.last_temp)
BUILD_SHOW_FUNC_INT(drives_fan_rpm, drives_state.rpm)
+BUILD_SHOW_FUNC_FIX(dimms_temperature, dimms_state.last_temp)
+
static DEVICE_ATTR(cpu0_temperature,S_IRUGO,show_cpu0_temperature,NULL);
static DEVICE_ATTR(cpu0_voltage,S_IRUGO,show_cpu0_voltage,NULL);
static DEVICE_ATTR(cpu0_current,S_IRUGO,show_cpu0_current,NULL);
@@ -629,6 +737,8 @@ static DEVICE_ATTR(backside_fan_pwm,S_IRUGO,show_backside_fan_pwm,NULL);
static DEVICE_ATTR(drives_temperature,S_IRUGO,show_drives_temperature,NULL);
static DEVICE_ATTR(drives_fan_rpm,S_IRUGO,show_drives_fan_rpm,NULL);
+static DEVICE_ATTR(dimms_temperature,S_IRUGO,show_dimms_temperature,NULL);
+
/*
* CPUs fans control loop
*/
@@ -636,17 +746,21 @@ static DEVICE_ATTR(drives_fan_rpm,S_IRUGO,show_drives_fan_rpm,NULL);
static int do_read_one_cpu_values(struct cpu_pid_state *state, s32 *temp, s32 *power)
{
s32 ltemp, volts, amps;
- int rc = 0;
+ int index, rc = 0;
/* Default (in case of error) */
*temp = state->cur_temp;
*power = state->cur_power;
- /* Read current fan status */
- if (state->index == 0)
- rc = get_rpm_fan(CPUA_EXHAUST_FAN_RPM_INDEX, !RPM_PID_USE_ACTUAL_SPEED);
+ if (cpu_pid_type == CPU_PID_TYPE_RACKMAC)
+ index = (state->index == 0) ?
+ CPU_A1_FAN_RPM_INDEX : CPU_B1_FAN_RPM_INDEX;
else
- rc = get_rpm_fan(CPUB_EXHAUST_FAN_RPM_INDEX, !RPM_PID_USE_ACTUAL_SPEED);
+ index = (state->index == 0) ?
+ CPUA_EXHAUST_FAN_RPM_INDEX : CPUB_EXHAUST_FAN_RPM_INDEX;
+
+ /* Read current fan status */
+ rc = get_rpm_fan(index, !RPM_PID_USE_ACTUAL_SPEED);
if (rc < 0) {
/* XXX What do we do now ? Nothing for now, keep old value, but
* return error upstream
@@ -777,11 +891,6 @@ static void do_cpu_pid(struct cpu_pid_state *state, s32 temp, s32 power)
DBG(" sum: %d\n", (int)sum);
state->rpm += (s32)sum;
-
- if (state->rpm < (int)state->mpu.rminn_exhaust_fan)
- state->rpm = state->mpu.rminn_exhaust_fan;
- if (state->rpm > (int)state->mpu.rmaxn_exhaust_fan)
- state->rpm = state->mpu.rmaxn_exhaust_fan;
}
static void do_monitor_cpu_combined(void)
@@ -823,28 +932,28 @@ static void do_monitor_cpu_combined(void)
if (state0->overtemp > 0) {
state0->rpm = state0->mpu.rmaxn_exhaust_fan;
state0->intake_rpm = intake = state0->mpu.rmaxn_intake_fan;
- pump = CPU_PUMP_OUTPUT_MAX;
+ pump = state0->pump_min;
goto do_set_fans;
}
/* Do the PID */
do_cpu_pid(state0, temp_combi, power_combi);
+ /* Range check */
+ state0->rpm = max(state0->rpm, (int)state0->mpu.rminn_exhaust_fan);
+ state0->rpm = min(state0->rpm, (int)state0->mpu.rmaxn_exhaust_fan);
+
/* Calculate intake fan speed */
intake = (state0->rpm * CPU_INTAKE_SCALE) >> 16;
- if (intake < (int)state0->mpu.rminn_intake_fan)
- intake = state0->mpu.rminn_intake_fan;
- if (intake > (int)state0->mpu.rmaxn_intake_fan)
- intake = state0->mpu.rmaxn_intake_fan;
+ intake = max(intake, (int)state0->mpu.rminn_intake_fan);
+ intake = min(intake, (int)state0->mpu.rmaxn_intake_fan);
state0->intake_rpm = intake;
/* Calculate pump speed */
- pump = (state0->rpm * CPU_PUMP_OUTPUT_MAX) /
+ pump = (state0->rpm * state0->pump_max) /
state0->mpu.rmaxn_exhaust_fan;
- if (pump > CPU_PUMP_OUTPUT_MAX)
- pump = CPU_PUMP_OUTPUT_MAX;
- if (pump < CPU_PUMP_OUTPUT_MIN)
- pump = CPU_PUMP_OUTPUT_MIN;
+ pump = min(pump, state0->pump_max);
+ pump = max(pump, state0->pump_min);
do_set_fans:
/* We copy values from state 0 to state 1 for /sysfs */
@@ -904,11 +1013,14 @@ static void do_monitor_cpu_split(struct cpu_pid_state *state)
/* Do the PID */
do_cpu_pid(state, temp, power);
+ /* Range check */
+ state->rpm = max(state->rpm, (int)state->mpu.rminn_exhaust_fan);
+ state->rpm = min(state->rpm, (int)state->mpu.rmaxn_exhaust_fan);
+
+ /* Calculate intake fan */
intake = (state->rpm * CPU_INTAKE_SCALE) >> 16;
- if (intake < (int)state->mpu.rminn_intake_fan)
- intake = state->mpu.rminn_intake_fan;
- if (intake > (int)state->mpu.rmaxn_intake_fan)
- intake = state->mpu.rmaxn_intake_fan;
+ intake = max(intake, (int)state->mpu.rminn_intake_fan);
+ intake = min(intake, (int)state->mpu.rmaxn_intake_fan);
state->intake_rpm = intake;
do_set_fans:
@@ -929,6 +1041,67 @@ static void do_monitor_cpu_split(struct cpu_pid_state *state)
}
}
+static void do_monitor_cpu_rack(struct cpu_pid_state *state)
+{
+ s32 temp, power, fan_min;
+ int rc;
+
+ /* Read current fan status */
+ rc = do_read_one_cpu_values(state, &temp, &power);
+ if (rc < 0) {
+ /* XXX What do we do now ? */
+ }
+
+ /* Check tmax, increment overtemp if we are there. At tmax+8, we go
+ * full blown immediately and try to trigger a shutdown
+ */
+ if (temp >= ((state->mpu.tmax + 8) << 16)) {
+ printk(KERN_WARNING "Warning ! CPU %d temperature way above maximum"
+ " (%d) !\n",
+ state->index, temp >> 16);
+ state->overtemp = CPU_MAX_OVERTEMP;
+ } else if (temp > (state->mpu.tmax << 16))
+ state->overtemp++;
+ else
+ state->overtemp = 0;
+ if (state->overtemp >= CPU_MAX_OVERTEMP)
+ critical_state = 1;
+ if (state->overtemp > 0) {
+ state->rpm = state->intake_rpm = state->mpu.rmaxn_intake_fan;
+ goto do_set_fans;
+ }
+
+ /* Do the PID */
+ do_cpu_pid(state, temp, power);
+
+ /* Check clamp from dimms */
+ fan_min = dimm_output_clamp;
+ fan_min = max(fan_min, (int)state->mpu.rminn_intake_fan);
+
+ state->rpm = max(state->rpm, (int)fan_min);
+ state->rpm = min(state->rpm, (int)state->mpu.rmaxn_intake_fan);
+ state->intake_rpm = state->rpm;
+
+ do_set_fans:
+ DBG("** CPU %d RPM: %d overtemp: %d\n",
+ state->index, (int)state->rpm, state->overtemp);
+
+ /* We should check for errors, shouldn't we ? But then, what
+ * do we do once the error occurs ? For FCU notified fan
+ * failures (-EFAULT) we probably want to notify userland
+ * some way...
+ */
+ if (state->index == 0) {
+ set_rpm_fan(CPU_A1_FAN_RPM_INDEX, state->rpm);
+ set_rpm_fan(CPU_A2_FAN_RPM_INDEX, state->rpm);
+ set_rpm_fan(CPU_A3_FAN_RPM_INDEX, state->rpm);
+ } else {
+ set_rpm_fan(CPU_B1_FAN_RPM_INDEX, state->rpm);
+ set_rpm_fan(CPU_B2_FAN_RPM_INDEX, state->rpm);
+ set_rpm_fan(CPU_B3_FAN_RPM_INDEX, state->rpm);
+ }
+}
+
/*
* Initialize the state structure for one CPU control loop
*/
@@ -936,7 +1109,7 @@ static int init_cpu_state(struct cpu_pid_state *state, int index)
{
state->index = index;
state->first = 1;
- state->rpm = 1000;
+ state->rpm = (cpu_pid_type == CPU_PID_TYPE_RACKMAC) ? 4000 : 1000;
state->overtemp = 0;
state->adc_config = 0x00;
@@ -1012,13 +1185,13 @@ static void dispose_cpu_state(struct cpu_pid_state *state)
*/
static void do_monitor_backside(struct backside_pid_state *state)
{
- s32 temp, integral, derivative;
+ s32 temp, integral, derivative, fan_min;
s64 integ_p, deriv_p, prop_p, sum;
int i, rc;
if (--state->ticks != 0)
return;
- state->ticks = BACKSIDE_PID_INTERVAL;
+ state->ticks = backside_params.interval;
DBG("backside:\n");
@@ -1059,7 +1232,7 @@ static void do_monitor_backside(struct backside_pid_state *state)
integral = 0;
for (i = 0; i < BACKSIDE_PID_HISTORY_SIZE; i++)
integral += state->error_history[i];
- integral *= BACKSIDE_PID_INTERVAL;
+ integral *= backside_params.interval;
DBG(" integral: %08x\n", integral);
integ_p = ((s64)backside_params.G_r) * (s64)integral;
DBG(" integ_p: %d\n", (int)(integ_p >> 36));
@@ -1069,7 +1242,7 @@ static void do_monitor_backside(struct backside_pid_state *state)
derivative = state->error_history[state->cur_sample] -
state->error_history[(state->cur_sample + BACKSIDE_PID_HISTORY_SIZE - 1)
% BACKSIDE_PID_HISTORY_SIZE];
- derivative /= BACKSIDE_PID_INTERVAL;
+ derivative /= backside_params.interval;
deriv_p = ((s64)backside_params.G_d) * (s64)derivative;
DBG(" deriv_p: %d\n", (int)(deriv_p >> 36));
sum += deriv_p;
@@ -1083,11 +1256,17 @@ static void do_monitor_backside(struct backside_pid_state *state)
sum >>= 36;
DBG(" sum: %d\n", (int)sum);
- state->pwm += (s32)sum;
- if (state->pwm < backside_params.output_min)
- state->pwm = backside_params.output_min;
- if (state->pwm > backside_params.output_max)
- state->pwm = backside_params.output_max;
+ if (backside_params.additive)
+ state->pwm += (s32)sum;
+ else
+ state->pwm = sum;
+
+ /* Check for clamp */
+ fan_min = (dimm_output_clamp * 100) / 14000;
+ fan_min = max(fan_min, backside_params.output_min);
+
+ state->pwm = max(state->pwm, fan_min);
+ state->pwm = min(state->pwm, backside_params.output_max);
DBG("** BACKSIDE PWM: %d\n", (int)state->pwm);
set_pwm_fan(BACKSIDE_FAN_PWM_INDEX, state->pwm);
@@ -1114,17 +1293,33 @@ static int init_backside_state(struct backside_pid_state *state)
of_node_put(u3);
}
- backside_params.G_p = BACKSIDE_PID_G_p;
- backside_params.G_r = BACKSIDE_PID_G_r;
- backside_params.output_max = BACKSIDE_PID_OUTPUT_MAX;
- if (u3h) {
+ if (rackmac) {
+ backside_params.G_d = BACKSIDE_PID_RACK_G_d;
+ backside_params.input_target = BACKSIDE_PID_RACK_INPUT_TARGET;
+ backside_params.output_min = BACKSIDE_PID_U3H_OUTPUT_MIN;
+ backside_params.interval = BACKSIDE_PID_RACK_INTERVAL;
+ backside_params.G_p = BACKSIDE_PID_RACK_G_p;
+ backside_params.G_r = BACKSIDE_PID_G_r;
+ backside_params.output_max = BACKSIDE_PID_OUTPUT_MAX;
+ backside_params.additive = 0;
+ } else if (u3h) {
backside_params.G_d = BACKSIDE_PID_U3H_G_d;
backside_params.input_target = BACKSIDE_PID_U3H_INPUT_TARGET;
backside_params.output_min = BACKSIDE_PID_U3H_OUTPUT_MIN;
+ backside_params.interval = BACKSIDE_PID_INTERVAL;
+ backside_params.G_p = BACKSIDE_PID_G_p;
+ backside_params.G_r = BACKSIDE_PID_G_r;
+ backside_params.output_max = BACKSIDE_PID_OUTPUT_MAX;
+ backside_params.additive = 1;
} else {
backside_params.G_d = BACKSIDE_PID_U3_G_d;
backside_params.input_target = BACKSIDE_PID_U3_INPUT_TARGET;
backside_params.output_min = BACKSIDE_PID_U3_OUTPUT_MIN;
+ backside_params.interval = BACKSIDE_PID_INTERVAL;
+ backside_params.G_p = BACKSIDE_PID_G_p;
+ backside_params.G_r = BACKSIDE_PID_G_r;
+ backside_params.output_max = BACKSIDE_PID_OUTPUT_MAX;
+ backside_params.additive = 1;
}
state->ticks = 1;
@@ -1233,10 +1428,9 @@ static void do_monitor_drives(struct drives_pid_state *state)
DBG(" sum: %d\n", (int)sum);
state->rpm += (s32)sum;
- if (state->rpm < DRIVES_PID_OUTPUT_MIN)
- state->rpm = DRIVES_PID_OUTPUT_MIN;
- if (state->rpm > DRIVES_PID_OUTPUT_MAX)
- state->rpm = DRIVES_PID_OUTPUT_MAX;
+
+ state->rpm = max(state->rpm, DRIVES_PID_OUTPUT_MIN);
+ state->rpm = min(state->rpm, DRIVES_PID_OUTPUT_MAX);
DBG("** DRIVES RPM: %d\n", (int)state->rpm);
set_rpm_fan(DRIVES_FAN_RPM_INDEX, state->rpm);
@@ -1276,6 +1470,126 @@ static void dispose_drives_state(struct drives_pid_state *state)
state->monitor = NULL;
}
+/*
+ * DIMMs temp control loop
+ */
+static void do_monitor_dimms(struct dimm_pid_state *state)
+{
+ s32 temp, integral, derivative, fan_min;
+ s64 integ_p, deriv_p, prop_p, sum;
+ int i;
+
+ if (--state->ticks != 0)
+ return;
+ state->ticks = DIMM_PID_INTERVAL;
+
+ DBG("DIMM:\n");
+
+ DBG(" current value: %d\n", state->output);
+
+ temp = read_lm87_reg(state->monitor, LM87_INT_TEMP);
+ if (temp < 0)
+ return;
+ temp <<= 16;
+ state->last_temp = temp;
+ DBG(" temp: %d.%03d, target: %d.%03d\n", FIX32TOPRINT(temp),
+ FIX32TOPRINT(DIMM_PID_INPUT_TARGET));
+
+ /* Store temperature and error in history array */
+ state->cur_sample = (state->cur_sample + 1) % DIMM_PID_HISTORY_SIZE;
+ state->sample_history[state->cur_sample] = temp;
+ state->error_history[state->cur_sample] = temp - DIMM_PID_INPUT_TARGET;
+
+ /* If first loop, fill the history table */
+ if (state->first) {
+ for (i = 0; i < (DIMM_PID_HISTORY_SIZE - 1); i++) {
+ state->cur_sample = (state->cur_sample + 1) %
+ DIMM_PID_HISTORY_SIZE;
+ state->sample_history[state->cur_sample] = temp;
+ state->error_history[state->cur_sample] =
+ temp - DIMM_PID_INPUT_TARGET;
+ }
+ state->first = 0;
+ }
+
+ /* Calculate the integral term */
+ sum = 0;
+ integral = 0;
+ for (i = 0; i < DIMM_PID_HISTORY_SIZE; i++)
+ integral += state->error_history[i];
+ integral *= DIMM_PID_INTERVAL;
+ DBG(" integral: %08x\n", integral);
+ integ_p = ((s64)DIMM_PID_G_r) * (s64)integral;
+ DBG(" integ_p: %d\n", (int)(integ_p >> 36));
+ sum += integ_p;
+
+ /* Calculate the derivative term */
+ derivative = state->error_history[state->cur_sample] -
+ state->error_history[(state->cur_sample + DIMM_PID_HISTORY_SIZE - 1)
+ % DIMM_PID_HISTORY_SIZE];
+ derivative /= DIMM_PID_INTERVAL;
+ deriv_p = ((s64)DIMM_PID_G_d) * (s64)derivative;
+ DBG(" deriv_p: %d\n", (int)(deriv_p >> 36));
+ sum += deriv_p;
+
+ /* Calculate the proportional term */
+ prop_p = ((s64)DIMM_PID_G_p) * (s64)(state->error_history[state->cur_sample]);
+ DBG(" prop_p: %d\n", (int)(prop_p >> 36));
+ sum += prop_p;
+
+ /* Scale sum */
+ sum >>= 36;
+
+ DBG(" sum: %d\n", (int)sum);
+ state->output = (s32)sum;
+ state->output = max(state->output, DIMM_PID_OUTPUT_MIN);
+ state->output = min(state->output, DIMM_PID_OUTPUT_MAX);
+ dimm_output_clamp = state->output;
+
+ DBG("** DIMM clamp value: %d\n", (int)state->output);
+
+ /* Backside PID is only every 5 seconds, force backside fan clamping now */
+ fan_min = (dimm_output_clamp * 100) / 14000;
+ fan_min = max(fan_min, backside_params.output_min);
+ if (backside_state.pwm < fan_min) {
+ backside_state.pwm = fan_min;
+ DBG(" -> applying clamp to backside fan now: %d !\n", fan_min);
+ set_pwm_fan(BACKSIDE_FAN_PWM_INDEX, fan_min);
+ }
+}
+
+/*
+ * Initialize the state structure for the DIMM temp control loop
+ */
+static int init_dimms_state(struct dimm_pid_state *state)
+{
+ state->ticks = 1;
+ state->first = 1;
+ state->output = 4000;
+
+ state->monitor = attach_i2c_chip(XSERVE_DIMMS_LM87, "dimms_temp");
+ if (state->monitor == NULL)
+ return -ENODEV;
+
+ device_create_file(&of_dev->dev, &dev_attr_dimms_temperature);
+
+ return 0;
+}
+
+/*
+ * Dispose of the state data for the drives control loop
+ */
+static void dispose_dimms_state(struct dimm_pid_state *state)
+{
+ if (state->monitor == NULL)
+ return;
+
+ device_remove_file(&of_dev->dev, &dev_attr_dimms_temperature);
+
+ detach_i2c_chip(state->monitor);
+ state->monitor = NULL;
+}
+
static int call_critical_overtemp(void)
{
char *argv[] = { critical_overtemp_path, NULL };
@@ -1321,15 +1635,29 @@ static int main_control_loop(void *x)
start = jiffies;
down(&driver_lock);
+
+ /* First, we always calculate the new DIMMs state on an Xserve */
+ if (rackmac)
+ do_monitor_dimms(&dimms_state);
+
+ /* Then, the CPUs */
if (cpu_pid_type == CPU_PID_TYPE_COMBINED)
do_monitor_cpu_combined();
- else {
+ else if (cpu_pid_type == CPU_PID_TYPE_RACKMAC) {
+ do_monitor_cpu_rack(&cpu_state[0]);
+ if (cpu_state[1].monitor != NULL)
+ do_monitor_cpu_rack(&cpu_state[1]);
+ // better deal with UP
+ } else {
do_monitor_cpu_split(&cpu_state[0]);
if (cpu_state[1].monitor != NULL)
do_monitor_cpu_split(&cpu_state[1]);
+ // better deal with UP
}
+ /* Then, the rest */
do_monitor_backside(&backside_state);
- do_monitor_drives(&drives_state);
+ if (!rackmac)
+ do_monitor_drives(&drives_state);
up(&driver_lock);
if (critical_state == 1) {
@@ -1369,9 +1697,9 @@ static void dispose_control_loops(void)
{
dispose_cpu_state(&cpu_state[0]);
dispose_cpu_state(&cpu_state[1]);
-
dispose_backside_state(&backside_state);
dispose_drives_state(&drives_state);
+ dispose_dimms_state(&dimms_state);
}
/*
@@ -1395,7 +1723,9 @@ static int create_control_loops(void)
* the pumps, though that may not be the best way, that is good enough
* for now
*/
- if (machine_is_compatible("PowerMac7,3")
+ if (rackmac)
+ cpu_pid_type = CPU_PID_TYPE_RACKMAC;
+ else if (machine_is_compatible("PowerMac7,3")
&& (cpu_count > 1)
&& fcu_fans[CPUA_PUMP_RPM_INDEX].id != FCU_FAN_ABSENT_ID
&& fcu_fans[CPUB_PUMP_RPM_INDEX].id != FCU_FAN_ABSENT_ID) {
@@ -1409,11 +1739,16 @@ static int create_control_loops(void)
*/
if (init_cpu_state(&cpu_state[0], 0))
goto fail;
+ if (cpu_pid_type == CPU_PID_TYPE_COMBINED)
+ fetch_cpu_pumps_minmax();
+
if (cpu_count > 1 && init_cpu_state(&cpu_state[1], 1))
goto fail;
if (init_backside_state(&backside_state))
goto fail;
- if (init_drives_state(&drives_state))
+ if (rackmac && init_dimms_state(&dimms_state))
+ goto fail;
+ if (!rackmac && init_drives_state(&drives_state))
goto fail;
DBG("all control loops up !\n");
@@ -1492,17 +1827,24 @@ static int therm_pm72_attach(struct i2c_adapter *adapter)
/* Check if we are looking for one of these */
if (u3_0 == NULL && !strcmp(adapter->name, "u3 0")) {
u3_0 = adapter;
- DBG("found U3-0, creating control loops\n");
- if (create_control_loops())
- u3_0 = NULL;
+ DBG("found U3-0\n");
+ if (k2 || !rackmac)
+ if (create_control_loops())
+ u3_0 = NULL;
} else if (u3_1 == NULL && !strcmp(adapter->name, "u3 1")) {
u3_1 = adapter;
DBG("found U3-1, attaching FCU\n");
if (attach_fcu())
u3_1 = NULL;
+ } else if (k2 == NULL && !strcmp(adapter->name, "mac-io 0")) {
+ k2 = adapter;
+ DBG("Found K2\n");
+ if (u3_0 && rackmac)
+ if (create_control_loops())
+ k2 = NULL;
}
/* We got all we need, start control loops */
- if (u3_0 != NULL && u3_1 != NULL) {
+ if (u3_0 != NULL && u3_1 != NULL && (k2 || !rackmac)) {
DBG("everything up, starting control loops\n");
state = state_attached;
start_control_loops();
@@ -1548,6 +1890,27 @@ static int therm_pm72_detach(struct i2c_adapter *adapter)
return 0;
}
+static int fan_check_loc_match(const char *loc, int fan)
+{
+ char tmp[64];
+ char *c, *e;
+
+ strlcpy(tmp, fcu_fans[fan].loc, 64);
+
+ c = tmp;
+ for (;;) {
+ e = strchr(c, ',');
+ if (e)
+ *e = 0;
+ if (strcmp(loc, c) == 0)
+ return 1;
+ if (e == NULL)
+ break;
+ c = e + 1;
+ }
+ return 0;
+}
+
static void fcu_lookup_fans(struct device_node *fcu_node)
{
struct device_node *np = NULL;
@@ -1589,7 +1952,7 @@ static void fcu_lookup_fans(struct device_node *fcu_node)
for (i = 0; i < FCU_FAN_COUNT; i++) {
int fan_id;
- if (strcmp(loc, fcu_fans[i].loc))
+ if (!fan_check_loc_match(loc, i))
continue;
DBG(" location match, index: %d\n", i);
fcu_fans[i].id = FCU_FAN_ABSENT_ID;
@@ -1671,8 +2034,11 @@ static int __init therm_pm72_init(void)
{
struct device_node *np;
+ rackmac = machine_is_compatible("RackMac3,1");
+
if (!machine_is_compatible("PowerMac7,2") &&
- !machine_is_compatible("PowerMac7,3"))
+ !machine_is_compatible("PowerMac7,3") &&
+ !rackmac)
return -ENODEV;
printk(KERN_INFO "PowerMac G5 Thermal control driver %s\n", VERSION);
@@ -1709,6 +2075,6 @@ module_init(therm_pm72_init);
module_exit(therm_pm72_exit);
MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
-MODULE_DESCRIPTION("Driver for Apple's PowerMac7,2 G5 thermal control");
+MODULE_DESCRIPTION("Driver for Apple's PowerMac G5 thermal control");
MODULE_LICENSE("GPL");
diff --git a/drivers/macintosh/therm_pm72.h b/drivers/macintosh/therm_pm72.h
index 1a4c71ad3ae28..c17e61f9c418c 100644
--- a/drivers/macintosh/therm_pm72.h
+++ b/drivers/macintosh/therm_pm72.h
@@ -52,7 +52,7 @@ struct mpu_data
u16 rmaxn_intake_fan; /* 0x4e - Intake fan max RPM */
u16 rminn_exhaust_fan; /* 0x50 - Exhaust fan min RPM */
u16 rmaxn_exhaust_fan; /* 0x52 - Exhaust fan max RPM */
- u8 processor_part_num[8]; /* 0x54 - Processor part number */
+ u8 processor_part_num[8]; /* 0x54 - Processor part number XX pumps min/max */
u32 processor_lot_num; /* 0x5c - Processor lot number */
u8 orig_card_sernum[0x10]; /* 0x60 - Card original serial number */
u8 curr_card_sernum[0x10]; /* 0x70 - Card current serial number */
@@ -94,19 +94,25 @@ static char * critical_overtemp_path = "/sbin/critical_overtemp";
* of the driver, though I would accept any clean patch
* doing a better use of the device-tree without turning the
* while i2c registration mecanism into a racy mess
+ *
+ * Note: Xserve changed this. We have some bits on the K2 bus,
+ * which I arbitrarily set to 0x200. Ultimately, we really want
+ * too lookup these in the device-tree though
*/
#define FAN_CTRLER_ID 0x15e
#define SUPPLY_MONITOR_ID 0x58
#define SUPPLY_MONITORB_ID 0x5a
#define DRIVES_DALLAS_ID 0x94
#define BACKSIDE_MAX_ID 0x98
+#define XSERVE_DIMMS_LM87 0x25a
/*
- * Some MAX6690 & DS1775 register definitions
+ * Some MAX6690, DS1775, LM87 register definitions
*/
#define MAX6690_INT_TEMP 0
#define MAX6690_EXT_TEMP 1
#define DS1775_TEMP 0
+#define LM87_INT_TEMP 0x27
/*
* Scaling factors for the AD7417 ADC converters (except
@@ -126,14 +132,18 @@ static char * critical_overtemp_path = "/sbin/critical_overtemp";
#define BACKSIDE_FAN_PWM_INDEX 0
#define BACKSIDE_PID_U3_G_d 0x02800000
#define BACKSIDE_PID_U3H_G_d 0x01400000
+#define BACKSIDE_PID_RACK_G_d 0x00500000
#define BACKSIDE_PID_G_p 0x00500000
+#define BACKSIDE_PID_RACK_G_p 0x0004cccc
#define BACKSIDE_PID_G_r 0x00000000
#define BACKSIDE_PID_U3_INPUT_TARGET 0x00410000
#define BACKSIDE_PID_U3H_INPUT_TARGET 0x004b0000
+#define BACKSIDE_PID_RACK_INPUT_TARGET 0x00460000
#define BACKSIDE_PID_INTERVAL 5
+#define BACKSIDE_PID_RACK_INTERVAL 1
#define BACKSIDE_PID_OUTPUT_MAX 100
#define BACKSIDE_PID_U3_OUTPUT_MIN 20
-#define BACKSIDE_PID_U3H_OUTPUT_MIN 30
+#define BACKSIDE_PID_U3H_OUTPUT_MIN 20
#define BACKSIDE_PID_HISTORY_SIZE 2
struct basckside_pid_params
@@ -144,6 +154,8 @@ struct basckside_pid_params
s32 input_target;
s32 output_min;
s32 output_max;
+ s32 interval;
+ int additive;
};
struct backside_pid_state
@@ -188,25 +200,34 @@ struct drives_pid_state
#define SLOTS_FAN_PWM_INDEX 2
#define SLOTS_FAN_DEFAULT_PWM 50 /* Do better here ! */
+
/*
- * IDs in Darwin for the sensors & fans
- *
- * CPU A AD7417_TEMP 10 (CPU A ambient temperature)
- * CPU A AD7417_AD1 11 (CPU A diode temperature)
- * CPU A AD7417_AD2 12 (CPU A 12V current)
- * CPU A AD7417_AD3 13 (CPU A voltage)
- * CPU A AD7417_AD4 14 (CPU A current)
- *
- * CPU A FAKE POWER 48 (I_V_inputs: 13, 14)
- *
- * CPU B AD7417_TEMP 15 (CPU B ambient temperature)
- * CPU B AD7417_AD1 16 (CPU B diode temperature)
- * CPU B AD7417_AD2 17 (CPU B 12V current)
- * CPU B AD7417_AD3 18 (CPU B voltage)
- * CPU B AD7417_AD4 19 (CPU B current)
- *
- * CPU B FAKE POWER 49 (I_V_inputs: 18, 19)
+ * PID factors for the Xserve DIMM control loop
*/
+#define DIMM_PID_G_d 0
+#define DIMM_PID_G_p 0
+#define DIMM_PID_G_r 0x6553600
+#define DIMM_PID_INPUT_TARGET 3276800
+#define DIMM_PID_INTERVAL 1
+#define DIMM_PID_OUTPUT_MAX 14000
+#define DIMM_PID_OUTPUT_MIN 4000
+#define DIMM_PID_HISTORY_SIZE 20
+
+struct dimm_pid_state
+{
+ int ticks;
+ struct i2c_client * monitor;
+ s32 sample_history[DIMM_PID_HISTORY_SIZE];
+ s32 error_history[DIMM_PID_HISTORY_SIZE];
+ int cur_sample;
+ s32 last_temp;
+ int first;
+ int output;
+};
+
+
+
+/* Desktops */
#define CPUA_INTAKE_FAN_RPM_DEFAULT_ID 3
#define CPUA_EXHAUST_FAN_RPM_DEFAULT_ID 4
@@ -226,8 +247,17 @@ struct drives_pid_state
#define CPUA_PUMP_RPM_INDEX 7
#define CPUB_PUMP_RPM_INDEX 8
-#define CPU_PUMP_OUTPUT_MAX 3700
-#define CPU_PUMP_OUTPUT_MIN 1000
+#define CPU_PUMP_OUTPUT_MAX 3200
+#define CPU_PUMP_OUTPUT_MIN 1250
+
+/* Xserve */
+#define CPU_A1_FAN_RPM_INDEX 9
+#define CPU_A2_FAN_RPM_INDEX 10
+#define CPU_A3_FAN_RPM_INDEX 11
+#define CPU_B1_FAN_RPM_INDEX 12
+#define CPU_B2_FAN_RPM_INDEX 13
+#define CPU_B3_FAN_RPM_INDEX 14
+
struct cpu_pid_state
{
@@ -249,6 +279,8 @@ struct cpu_pid_state
s32 last_power;
int first;
u8 adc_config;
+ s32 pump_min;
+ s32 pump_max;
};
/*
diff --git a/drivers/macintosh/therm_windtunnel.c b/drivers/macintosh/therm_windtunnel.c
index 897902b82f759..c153699d0f842 100644
--- a/drivers/macintosh/therm_windtunnel.c
+++ b/drivers/macintosh/therm_windtunnel.c
@@ -47,8 +47,6 @@
#define LOG_TEMP 0 /* continously log temperature */
#define I2C_DRIVERID_G4FAN 0x9001 /* fixme */
-#define THERMOSTAT_CLIENT_ID 1
-#define FAN_CLIENT_ID 2
static int do_probe( struct i2c_adapter *adapter, int addr, int kind);
@@ -372,7 +370,6 @@ attach_fan( struct i2c_client *cl )
goto out;
printk("ADM1030 fan controller [@%02x]\n", cl->addr );
- cl->id = FAN_CLIENT_ID;
strlcpy( cl->name, "ADM1030 fan controller", sizeof(cl->name) );
if( !i2c_attach_client(cl) )
@@ -412,7 +409,6 @@ attach_thermostat( struct i2c_client *cl )
x.overheat_temp = os_temp;
x.overheat_hyst = hyst_temp;
- cl->id = THERMOSTAT_CLIENT_ID;
strlcpy( cl->name, "DS1775 thermostat", sizeof(cl->name) );
if( !i2c_attach_client(cl) )
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c
index 019f4c4e3a941..cea1e758eb469 100644
--- a/drivers/macintosh/via-pmu.c
+++ b/drivers/macintosh/via-pmu.c
@@ -43,6 +43,7 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/device.h>
+#include <linux/sysdev.h>
#include <linux/suspend.h>
#include <linux/syscalls.h>
#include <linux/cpu.h>
@@ -367,9 +368,7 @@ find_via_pmu(void)
printk(KERN_INFO "PMU driver %d initialized for %s, firmware: %02x\n",
PMU_DRIVER_VERSION, pbook_type[pmu_kind], pmu_version);
-#ifndef CONFIG_PPC64
sys_ctrler = SYS_CTRLER_PMU;
-#endif
return 1;
}
@@ -1745,6 +1744,9 @@ pmu_restart(void)
{
struct adb_request req;
+ if (via == NULL)
+ return;
+
local_irq_disable();
drop_interrupts = 1;
@@ -1767,6 +1769,9 @@ pmu_shutdown(void)
{
struct adb_request req;
+ if (via == NULL)
+ return;
+
local_irq_disable();
drop_interrupts = 1;
@@ -2326,7 +2331,7 @@ pmac_suspend_devices(void)
/* Sync the disks. */
/* XXX It would be nice to have some way to ensure that
* nobody is dirtying any new buffers while we wait. That
- * could be acheived using the refrigerator for processes
+ * could be achieved using the refrigerator for processes
* that swsusp uses
*/
sys_sync();
@@ -2339,7 +2344,7 @@ pmac_suspend_devices(void)
}
/* Send suspend call to devices, hold the device core's dpm_sem */
- ret = device_suspend(PM_SUSPEND_MEM);
+ ret = device_suspend(PMSG_SUSPEND);
if (ret) {
broadcast_wake();
printk(KERN_ERR "Driver sleep failed\n");
@@ -2379,7 +2384,6 @@ pmac_suspend_devices(void)
/* Wait for completion of async backlight requests */
while (!bright_req_1.complete || !bright_req_2.complete ||
-
!batt_req.complete)
pmu_poll();
@@ -2389,7 +2393,7 @@ pmac_suspend_devices(void)
enable_kernel_fp();
#ifdef CONFIG_ALTIVEC
- if (cur_cpu_spec[0]->cpu_features & CPU_FTR_ALTIVEC)
+ if (cpu_has_feature(CPU_FTR_ALTIVEC))
enable_kernel_altivec();
#endif /* CONFIG_ALTIVEC */
@@ -2770,13 +2774,12 @@ pmu_read(struct file *file, char __user *buf,
struct pmu_private *pp = file->private_data;
DECLARE_WAITQUEUE(wait, current);
unsigned long flags;
- int ret;
+ int ret = 0;
if (count < 1 || pp == 0)
return -EINVAL;
- ret = verify_area(VERIFY_WRITE, buf, count);
- if (ret)
- return ret;
+ if (!access_ok(VERIFY_WRITE, buf, count))
+ return -EFAULT;
spin_lock_irqsave(&pp->lock, flags);
add_wait_queue(&pp->wait, &wait);
@@ -3040,6 +3043,88 @@ pmu_polled_request(struct adb_request *req)
}
#endif /* DEBUG_SLEEP */
+
+/* FIXME: This is a temporary set of callbacks to enable us
+ * to do suspend-to-disk.
+ */
+
+#ifdef CONFIG_PM
+
+static int pmu_sys_suspended = 0;
+
+static int pmu_sys_suspend(struct sys_device *sysdev, u32 state)
+{
+ if (state != PM_SUSPEND_DISK || pmu_sys_suspended)
+ return 0;
+
+ /* Suspend PMU event interrupts */
+ pmu_suspend();
+
+ pmu_sys_suspended = 1;
+ return 0;
+}
+
+static int pmu_sys_resume(struct sys_device *sysdev)
+{
+ struct adb_request req;
+
+ if (!pmu_sys_suspended)
+ return 0;
+
+ /* Tell PMU we are ready */
+ pmu_request(&req, NULL, 2, PMU_SYSTEM_READY, 2);
+ pmu_wait_complete(&req);
+
+ /* Resume PMU event interrupts */
+ pmu_resume();
+
+ pmu_sys_suspended = 0;
+
+ return 0;
+}
+
+#endif /* CONFIG_PM */
+
+static struct sysdev_class pmu_sysclass = {
+ set_kset_name("pmu"),
+};
+
+static struct sys_device device_pmu = {
+ .id = 0,
+ .cls = &pmu_sysclass,
+};
+
+static struct sysdev_driver driver_pmu = {
+#ifdef CONFIG_PM
+ .suspend = &pmu_sys_suspend,
+ .resume = &pmu_sys_resume,
+#endif /* CONFIG_PM */
+};
+
+static int __init init_pmu_sysfs(void)
+{
+ int rc;
+
+ rc = sysdev_class_register(&pmu_sysclass);
+ if (rc) {
+ printk(KERN_ERR "Failed registering PMU sys class\n");
+ return -ENODEV;
+ }
+ rc = sysdev_register(&device_pmu);
+ if (rc) {
+ printk(KERN_ERR "Failed registering PMU sys device\n");
+ return -ENODEV;
+ }
+ rc = sysdev_driver_register(&pmu_sysclass, &driver_pmu);
+ if (rc) {
+ printk(KERN_ERR "Failed registering PMU sys driver\n");
+ return -ENODEV;
+ }
+ return 0;
+}
+
+subsys_initcall(init_pmu_sysfs);
+
EXPORT_SYMBOL(pmu_request);
EXPORT_SYMBOL(pmu_poll);
EXPORT_SYMBOL(pmu_poll_adb);
diff --git a/drivers/md/Kconfig b/drivers/md/Kconfig
index a86569d281680..ac43f98062fd1 100644
--- a/drivers/md/Kconfig
+++ b/drivers/md/Kconfig
@@ -93,7 +93,7 @@ config MD_RAID10
mirroring (RAID-1) with easier configuration and more flexable
layout.
Unlike RAID-0, but like RAID-1, RAID-10 requires all devices to
- be the same size (or atleast, only as much as the smallest device
+ be the same size (or at least, only as much as the smallest device
will be used).
RAID-10 provides a variety of layouts that provide different levels
of redundancy and performance.
@@ -102,6 +102,7 @@ config MD_RAID10
ftp://ftp.kernel.org/pub/linux/utils/raid/mdadm/
+ If unsure, say Y.
config MD_RAID5
tristate "RAID-4/RAID-5 mode"
@@ -120,20 +121,16 @@ config MD_RAID5
<http://www.tldp.org/docs.html#howto>. There you will also
learn where to get the supporting user space utilities raidtools.
- If you want to use such a RAID-4/RAID-5 set, say Y. To compile
- this code as a module, choose M here: the module will be called raid5.
+ If you want to use such a RAID-4/RAID-5 set, say Y. To
+ compile this code as a module, choose M here: the module
+ will be called raid5.
If unsure, say Y.
config MD_RAID6
- tristate "RAID-6 mode (EXPERIMENTAL)"
- depends on BLK_DEV_MD && EXPERIMENTAL
+ tristate "RAID-6 mode"
+ depends on BLK_DEV_MD
---help---
- WARNING: RAID-6 is currently highly experimental. If you
- use it, there is no guarantee whatsoever that it won't
- destroy your data, eat your disk drives, insult your mother,
- or re-appoint George W. Bush.
-
A RAID-6 set of N drives with a capacity of C MB per drive
provides the capacity of C * (N - 2) MB, and protects
against a failure of any two drives. For a given sector
@@ -150,7 +147,7 @@ config MD_RAID6
this code as a module, choose M here: the module will be
called raid6.
- If unsure, say N.
+ If unsure, say Y.
config MD_MULTIPATH
tristate "Multipath I/O support"
@@ -227,5 +224,17 @@ config DM_ZERO
A target that discards writes, and returns all zeroes for
reads. Useful in some recovery situations.
+config DM_MULTIPATH
+ tristate "Multipath target (EXPERIMENTAL)"
+ depends on BLK_DEV_DM && EXPERIMENTAL
+ ---help---
+ Allow volume managers to support multipath hardware.
+
+config DM_MULTIPATH_EMC
+ tristate "EMC CX/AX multipath support (EXPERIMENTAL)"
+ depends on DM_MULTIPATH && BLK_DEV_DM && EXPERIMENTAL
+ ---help---
+ Multipath support for EMC CX/AX series hardware.
+
endmenu
diff --git a/drivers/md/Makefile b/drivers/md/Makefile
index eeba14dcbecf7..90de9c146a5f5 100644
--- a/drivers/md/Makefile
+++ b/drivers/md/Makefile
@@ -4,6 +4,7 @@
dm-mod-objs := dm.o dm-table.o dm-target.o dm-linear.o dm-stripe.o \
dm-ioctl.o dm-io.o kcopyd.o
+dm-multipath-objs := dm-hw-handler.o dm-path-selector.o dm-mpath.o
dm-snapshot-objs := dm-snap.o dm-exception-store.o
dm-mirror-objs := dm-log.o dm-raid1.o
raid6-objs := raid6main.o raid6algos.o raid6recov.o raid6tables.o \
@@ -30,6 +31,8 @@ obj-$(CONFIG_MD_FAULTY) += faulty.o
obj-$(CONFIG_BLK_DEV_MD) += md.o
obj-$(CONFIG_BLK_DEV_DM) += dm-mod.o
obj-$(CONFIG_DM_CRYPT) += dm-crypt.o
+obj-$(CONFIG_DM_MULTIPATH) += dm-multipath.o dm-round-robin.o
+obj-$(CONFIG_DM_MULTIPATH_EMC) += dm-emc.o
obj-$(CONFIG_DM_SNAPSHOT) += dm-snapshot.o
obj-$(CONFIG_DM_MIRROR) += dm-mirror.o
obj-$(CONFIG_DM_ZERO) += dm-zero.o
diff --git a/drivers/md/dm-bio-record.h b/drivers/md/dm-bio-record.h
new file mode 100644
index 0000000000000..d3ec217847d68
--- /dev/null
+++ b/drivers/md/dm-bio-record.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
+ *
+ * This file is released under the GPL.
+ */
+
+#ifndef DM_BIO_RECORD_H
+#define DM_BIO_RECORD_H
+
+#include <linux/bio.h>
+
+/*
+ * There are lots of mutable fields in the bio struct that get
+ * changed by the lower levels of the block layer. Some targets,
+ * such as multipath, may wish to resubmit a bio on error. The
+ * functions in this file help the target record and restore the
+ * original bio state.
+ */
+struct dm_bio_details {
+ sector_t bi_sector;
+ struct block_device *bi_bdev;
+ unsigned int bi_size;
+ unsigned short bi_idx;
+ unsigned long bi_flags;
+};
+
+static inline void dm_bio_record(struct dm_bio_details *bd, struct bio *bio)
+{
+ bd->bi_sector = bio->bi_sector;
+ bd->bi_bdev = bio->bi_bdev;
+ bd->bi_size = bio->bi_size;
+ bd->bi_idx = bio->bi_idx;
+ bd->bi_flags = bio->bi_flags;
+}
+
+static inline void dm_bio_restore(struct dm_bio_details *bd, struct bio *bio)
+{
+ bio->bi_sector = bd->bi_sector;
+ bio->bi_bdev = bd->bi_bdev;
+ bio->bi_size = bd->bi_size;
+ bio->bi_idx = bd->bi_idx;
+ bio->bi_flags = bd->bi_flags;
+}
+
+#endif
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index d93373b34b8ca..77619a56e2bfb 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -96,7 +96,7 @@ static kmem_cache_t *_crypt_io_pool;
/*
* Mempool alloc and free functions for the page
*/
-static void *mempool_alloc_page(int gfp_mask, void *data)
+static void *mempool_alloc_page(unsigned int __nocast gfp_mask, void *data)
{
return alloc_page(gfp_mask);
}
@@ -869,7 +869,6 @@ static int crypt_status(struct dm_target *ti, status_type_t type,
char *result, unsigned int maxlen)
{
struct crypt_config *cc = (struct crypt_config *) ti->private;
- char buffer[32];
const char *cipher;
const char *chainmode = NULL;
unsigned int sz = 0;
@@ -910,9 +909,8 @@ static int crypt_status(struct dm_target *ti, status_type_t type,
result[sz++] = '-';
}
- format_dev_t(buffer, cc->dev->bdev->bd_dev);
DMEMIT(" " SECTOR_FORMAT " %s " SECTOR_FORMAT,
- cc->iv_offset, buffer, cc->start);
+ cc->iv_offset, cc->dev->name, cc->start);
break;
}
return 0;
diff --git a/drivers/md/dm-emc.c b/drivers/md/dm-emc.c
new file mode 100644
index 0000000000000..7006586645943
--- /dev/null
+++ b/drivers/md/dm-emc.c
@@ -0,0 +1,359 @@
+/*
+ * Copyright (C) 2004 SUSE LINUX Products GmbH. All rights reserved.
+ * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+ *
+ * This file is released under the GPL.
+ *
+ * Multipath support for EMC CLARiiON AX/CX-series hardware.
+ */
+
+#include "dm.h"
+#include "dm-hw-handler.h"
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+
+struct emc_handler {
+ spinlock_t lock;
+
+ /* Whether we should send the short trespass command (FC-series)
+ * or the long version (default for AX/CX CLARiiON arrays). */
+ unsigned short_trespass;
+ /* Whether or not to honor SCSI reservations when initiating a
+ * switch-over. Default: Don't. */
+ unsigned hr;
+
+ unsigned char sense[SCSI_SENSE_BUFFERSIZE];
+};
+
+#define TRESPASS_PAGE 0x22
+#define EMC_FAILOVER_TIMEOUT (60 * HZ)
+
+/* Code borrowed from dm-lsi-rdac by Mike Christie */
+
+static inline void free_bio(struct bio *bio)
+{
+ __free_page(bio->bi_io_vec[0].bv_page);
+ bio_put(bio);
+}
+
+static int emc_endio(struct bio *bio, unsigned int bytes_done, int error)
+{
+ struct path *path = bio->bi_private;
+
+ if (bio->bi_size)
+ return 1;
+
+ /* We also need to look at the sense keys here whether or not to
+ * switch to the next PG etc.
+ *
+ * For now simple logic: either it works or it doesn't.
+ */
+ if (error)
+ dm_pg_init_complete(path, MP_FAIL_PATH);
+ else
+ dm_pg_init_complete(path, 0);
+
+ /* request is freed in block layer */
+ free_bio(bio);
+
+ return 0;
+}
+
+static struct bio *get_failover_bio(struct path *path, unsigned data_size)
+{
+ struct bio *bio;
+ struct page *page;
+
+ bio = bio_alloc(GFP_ATOMIC, 1);
+ if (!bio) {
+ DMERR("dm-emc: get_failover_bio: bio_alloc() failed.");
+ return NULL;
+ }
+
+ bio->bi_rw |= (1 << BIO_RW);
+ bio->bi_bdev = path->dev->bdev;
+ bio->bi_sector = 0;
+ bio->bi_private = path;
+ bio->bi_end_io = emc_endio;
+
+ page = alloc_page(GFP_ATOMIC);
+ if (!page) {
+ DMERR("dm-emc: get_failover_bio: alloc_page() failed.");
+ bio_put(bio);
+ return NULL;
+ }
+
+ if (bio_add_page(bio, page, data_size, 0) != data_size) {
+ DMERR("dm-emc: get_failover_bio: alloc_page() failed.");
+ __free_page(page);
+ bio_put(bio);
+ return NULL;
+ }
+
+ return bio;
+}
+
+static struct request *get_failover_req(struct emc_handler *h,
+ struct bio *bio, struct path *path)
+{
+ struct request *rq;
+ struct block_device *bdev = bio->bi_bdev;
+ struct request_queue *q = bdev_get_queue(bdev);
+
+ /* FIXME: Figure out why it fails with GFP_ATOMIC. */
+ rq = blk_get_request(q, WRITE, __GFP_WAIT);
+ if (!rq) {
+ DMERR("dm-emc: get_failover_req: blk_get_request failed");
+ return NULL;
+ }
+
+ rq->bio = rq->biotail = bio;
+ blk_rq_bio_prep(q, rq, bio);
+
+ rq->rq_disk = bdev->bd_contains->bd_disk;
+
+ /* bio backed don't set data */
+ rq->buffer = rq->data = NULL;
+ /* rq data_len used for pc cmd's request_bufflen */
+ rq->data_len = bio->bi_size;
+
+ rq->sense = h->sense;
+ memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
+ rq->sense_len = 0;
+
+ memset(&rq->cmd, 0, BLK_MAX_CDB);
+
+ rq->timeout = EMC_FAILOVER_TIMEOUT;
+ rq->flags |= (REQ_BLOCK_PC | REQ_FAILFAST | REQ_NOMERGE);
+
+ return rq;
+}
+
+static struct request *emc_trespass_get(struct emc_handler *h,
+ struct path *path)
+{
+ struct bio *bio;
+ struct request *rq;
+ unsigned char *page22;
+ unsigned char long_trespass_pg[] = {
+ 0, 0, 0, 0,
+ TRESPASS_PAGE, /* Page code */
+ 0x09, /* Page length - 2 */
+ h->hr ? 0x01 : 0x81, /* Trespass code + Honor reservation bit */
+ 0xff, 0xff, /* Trespass target */
+ 0, 0, 0, 0, 0, 0 /* Reserved bytes / unknown */
+ };
+ unsigned char short_trespass_pg[] = {
+ 0, 0, 0, 0,
+ TRESPASS_PAGE, /* Page code */
+ 0x02, /* Page length - 2 */
+ h->hr ? 0x01 : 0x81, /* Trespass code + Honor reservation bit */
+ 0xff, /* Trespass target */
+ };
+ unsigned data_size = h->short_trespass ? sizeof(short_trespass_pg) :
+ sizeof(long_trespass_pg);
+
+ /* get bio backing */
+ if (data_size > PAGE_SIZE)
+ /* this should never happen */
+ return NULL;
+
+ bio = get_failover_bio(path, data_size);
+ if (!bio) {
+ DMERR("dm-emc: emc_trespass_get: no bio");
+ return NULL;
+ }
+
+ page22 = (unsigned char *)bio_data(bio);
+ memset(page22, 0, data_size);
+
+ memcpy(page22, h->short_trespass ?
+ short_trespass_pg : long_trespass_pg, data_size);
+
+ /* get request for block layer packet command */
+ rq = get_failover_req(h, bio, path);
+ if (!rq) {
+ DMERR("dm-emc: emc_trespass_get: no rq");
+ free_bio(bio);
+ return NULL;
+ }
+
+ /* Prepare the command. */
+ rq->cmd[0] = MODE_SELECT;
+ rq->cmd[1] = 0x10;
+ rq->cmd[4] = data_size;
+ rq->cmd_len = COMMAND_SIZE(rq->cmd[0]);
+
+ return rq;
+}
+
+static void emc_pg_init(struct hw_handler *hwh, unsigned bypassed,
+ struct path *path)
+{
+ struct request *rq;
+ struct request_queue *q = bdev_get_queue(path->dev->bdev);
+
+ /*
+ * We can either blindly init the pg (then look at the sense),
+ * or we can send some commands to get the state here (then
+ * possibly send the fo cmnd), or we can also have the
+ * initial state passed into us and then get an update here.
+ */
+ if (!q) {
+ DMINFO("dm-emc: emc_pg_init: no queue");
+ goto fail_path;
+ }
+
+ /* FIXME: The request should be pre-allocated. */
+ rq = emc_trespass_get(hwh->context, path);
+ if (!rq) {
+ DMERR("dm-emc: emc_pg_init: no rq");
+ goto fail_path;
+ }
+
+ DMINFO("dm-emc: emc_pg_init: sending switch-over command");
+ elv_add_request(q, rq, ELEVATOR_INSERT_FRONT, 1);
+ return;
+
+fail_path:
+ dm_pg_init_complete(path, MP_FAIL_PATH);
+}
+
+static struct emc_handler *alloc_emc_handler(void)
+{
+ struct emc_handler *h = kmalloc(sizeof(*h), GFP_KERNEL);
+
+ if (h)
+ spin_lock_init(&h->lock);
+
+ return h;
+}
+
+static int emc_create(struct hw_handler *hwh, unsigned argc, char **argv)
+{
+ struct emc_handler *h;
+ unsigned hr, short_trespass;
+
+ if (argc == 0) {
+ /* No arguments: use defaults */
+ hr = 0;
+ short_trespass = 0;
+ } else if (argc != 2) {
+ DMWARN("dm-emc hwhandler: incorrect number of arguments");
+ return -EINVAL;
+ } else {
+ if ((sscanf(argv[0], "%u", &short_trespass) != 1)
+ || (short_trespass > 1)) {
+ DMWARN("dm-emc: invalid trespass mode selected");
+ return -EINVAL;
+ }
+
+ if ((sscanf(argv[1], "%u", &hr) != 1)
+ || (hr > 1)) {
+ DMWARN("dm-emc: invalid honor reservation flag selected");
+ return -EINVAL;
+ }
+ }
+
+ h = alloc_emc_handler();
+ if (!h)
+ return -ENOMEM;
+
+ memset(h, 0, sizeof(*h));
+
+ hwh->context = h;
+
+ if ((h->short_trespass = short_trespass))
+ DMWARN("dm-emc: short trespass command will be send");
+ else
+ DMWARN("dm-emc: long trespass command will be send");
+
+ if ((h->hr = hr))
+ DMWARN("dm-emc: honor reservation bit will be set");
+ else
+ DMWARN("dm-emc: honor reservation bit will not be set (default)");
+
+ return 0;
+}
+
+static void emc_destroy(struct hw_handler *hwh)
+{
+ struct emc_handler *h = (struct emc_handler *) hwh->context;
+
+ kfree(h);
+ hwh->context = NULL;
+}
+
+static unsigned emc_error(struct hw_handler *hwh, struct bio *bio)
+{
+ /* FIXME: Patch from axboe still missing */
+#if 0
+ int sense;
+
+ if (bio->bi_error & BIO_SENSE) {
+ sense = bio->bi_error & 0xffffff; /* sense key / asc / ascq */
+
+ if (sense == 0x020403) {
+ /* LUN Not Ready - Manual Intervention Required
+ * indicates this is a passive path.
+ *
+ * FIXME: However, if this is seen and EVPD C0
+ * indicates that this is due to a NDU in
+ * progress, we should set FAIL_PATH too.
+ * This indicates we might have to do a SCSI
+ * inquiry in the end_io path. Ugh. */
+ return MP_BYPASS_PG | MP_RETRY_IO;
+ } else if (sense == 0x052501) {
+ /* An array based copy is in progress. Do not
+ * fail the path, do not bypass to another PG,
+ * do not retry. Fail the IO immediately.
+ * (Actually this is the same conclusion as in
+ * the default handler, but lets make sure.) */
+ return 0;
+ } else if (sense == 0x062900) {
+ /* Unit Attention Code. This is the first IO
+ * to the new path, so just retry. */
+ return MP_RETRY_IO;
+ }
+ }
+#endif
+
+ /* Try default handler */
+ return dm_scsi_err_handler(hwh, bio);
+}
+
+static struct hw_handler_type emc_hwh = {
+ .name = "emc",
+ .module = THIS_MODULE,
+ .create = emc_create,
+ .destroy = emc_destroy,
+ .pg_init = emc_pg_init,
+ .error = emc_error,
+};
+
+static int __init dm_emc_init(void)
+{
+ int r = dm_register_hw_handler(&emc_hwh);
+
+ if (r < 0)
+ DMERR("emc: register failed %d", r);
+
+ DMINFO("dm-emc version 0.0.3 loaded");
+
+ return r;
+}
+
+static void __exit dm_emc_exit(void)
+{
+ int r = dm_unregister_hw_handler(&emc_hwh);
+
+ if (r < 0)
+ DMERR("emc: unregister failed %d", r);
+}
+
+module_init(dm_emc_init);
+module_exit(dm_emc_exit);
+
+MODULE_DESCRIPTION(DM_NAME " EMC CX/AX/FC-family multipath");
+MODULE_AUTHOR("Lars Marowsky-Bree <lmb@suse.de>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/md/dm-hw-handler.c b/drivers/md/dm-hw-handler.c
new file mode 100644
index 0000000000000..ae63772e44c9c
--- /dev/null
+++ b/drivers/md/dm-hw-handler.c
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+ *
+ * This file is released under the GPL.
+ *
+ * Multipath hardware handler registration.
+ */
+
+#include "dm.h"
+#include "dm-hw-handler.h"
+
+#include <linux/slab.h>
+
+struct hwh_internal {
+ struct hw_handler_type hwht;
+
+ struct list_head list;
+ long use;
+};
+
+#define hwht_to_hwhi(__hwht) container_of((__hwht), struct hwh_internal, hwht)
+
+static LIST_HEAD(_hw_handlers);
+static DECLARE_RWSEM(_hwh_lock);
+
+struct hwh_internal *__find_hw_handler_type(const char *name)
+{
+ struct hwh_internal *hwhi;
+
+ list_for_each_entry(hwhi, &_hw_handlers, list) {
+ if (!strcmp(name, hwhi->hwht.name))
+ return hwhi;
+ }
+
+ return NULL;
+}
+
+static struct hwh_internal *get_hw_handler(const char *name)
+{
+ struct hwh_internal *hwhi;
+
+ down_read(&_hwh_lock);
+ hwhi = __find_hw_handler_type(name);
+ if (hwhi) {
+ if ((hwhi->use == 0) && !try_module_get(hwhi->hwht.module))
+ hwhi = NULL;
+ else
+ hwhi->use++;
+ }
+ up_read(&_hwh_lock);
+
+ return hwhi;
+}
+
+struct hw_handler_type *dm_get_hw_handler(const char *name)
+{
+ struct hwh_internal *hwhi;
+
+ if (!name)
+ return NULL;
+
+ hwhi = get_hw_handler(name);
+ if (!hwhi) {
+ request_module("dm-%s", name);
+ hwhi = get_hw_handler(name);
+ }
+
+ return hwhi ? &hwhi->hwht : NULL;
+}
+
+void dm_put_hw_handler(struct hw_handler_type *hwht)
+{
+ struct hwh_internal *hwhi;
+
+ if (!hwht)
+ return;
+
+ down_read(&_hwh_lock);
+ hwhi = __find_hw_handler_type(hwht->name);
+ if (!hwhi)
+ goto out;
+
+ if (--hwhi->use == 0)
+ module_put(hwhi->hwht.module);
+
+ if (hwhi->use < 0)
+ BUG();
+
+ out:
+ up_read(&_hwh_lock);
+}
+
+static struct hwh_internal *_alloc_hw_handler(struct hw_handler_type *hwht)
+{
+ struct hwh_internal *hwhi = kmalloc(sizeof(*hwhi), GFP_KERNEL);
+
+ if (hwhi) {
+ memset(hwhi, 0, sizeof(*hwhi));
+ hwhi->hwht = *hwht;
+ }
+
+ return hwhi;
+}
+
+int dm_register_hw_handler(struct hw_handler_type *hwht)
+{
+ int r = 0;
+ struct hwh_internal *hwhi = _alloc_hw_handler(hwht);
+
+ if (!hwhi)
+ return -ENOMEM;
+
+ down_write(&_hwh_lock);
+
+ if (__find_hw_handler_type(hwht->name)) {
+ kfree(hwhi);
+ r = -EEXIST;
+ } else
+ list_add(&hwhi->list, &_hw_handlers);
+
+ up_write(&_hwh_lock);
+
+ return r;
+}
+
+int dm_unregister_hw_handler(struct hw_handler_type *hwht)
+{
+ struct hwh_internal *hwhi;
+
+ down_write(&_hwh_lock);
+
+ hwhi = __find_hw_handler_type(hwht->name);
+ if (!hwhi) {
+ up_write(&_hwh_lock);
+ return -EINVAL;
+ }
+
+ if (hwhi->use) {
+ up_write(&_hwh_lock);
+ return -ETXTBSY;
+ }
+
+ list_del(&hwhi->list);
+
+ up_write(&_hwh_lock);
+
+ kfree(hwhi);
+
+ return 0;
+}
+
+unsigned dm_scsi_err_handler(struct hw_handler *hwh, struct bio *bio)
+{
+#if 0
+ int sense_key, asc, ascq;
+
+ if (bio->bi_error & BIO_SENSE) {
+ /* FIXME: This is just an initial guess. */
+ /* key / asc / ascq */
+ sense_key = (bio->bi_error >> 16) & 0xff;
+ asc = (bio->bi_error >> 8) & 0xff;
+ ascq = bio->bi_error & 0xff;
+
+ switch (sense_key) {
+ /* This block as a whole comes from the device.
+ * So no point retrying on another path. */
+ case 0x03: /* Medium error */
+ case 0x05: /* Illegal request */
+ case 0x07: /* Data protect */
+ case 0x08: /* Blank check */
+ case 0x0a: /* copy aborted */
+ case 0x0c: /* obsolete - no clue ;-) */
+ case 0x0d: /* volume overflow */
+ case 0x0e: /* data miscompare */
+ case 0x0f: /* reserved - no idea either. */
+ return MP_ERROR_IO;
+
+ /* For these errors it's unclear whether they
+ * come from the device or the controller.
+ * So just lets try a different path, and if
+ * it eventually succeeds, user-space will clear
+ * the paths again... */
+ case 0x02: /* Not ready */
+ case 0x04: /* Hardware error */
+ case 0x09: /* vendor specific */
+ case 0x0b: /* Aborted command */
+ return MP_FAIL_PATH;
+
+ case 0x06: /* Unit attention - might want to decode */
+ if (asc == 0x04 && ascq == 0x01)
+ /* "Unit in the process of
+ * becoming ready" */
+ return 0;
+ return MP_FAIL_PATH;
+
+ /* FIXME: For Unit Not Ready we may want
+ * to have a generic pg activation
+ * feature (START_UNIT). */
+
+ /* Should these two ever end up in the
+ * error path? I don't think so. */
+ case 0x00: /* No sense */
+ case 0x01: /* Recovered error */
+ return 0;
+ }
+ }
+#endif
+
+ /* We got no idea how to decode the other kinds of errors ->
+ * assume generic error condition. */
+ return MP_FAIL_PATH;
+}
+
+EXPORT_SYMBOL_GPL(dm_register_hw_handler);
+EXPORT_SYMBOL_GPL(dm_unregister_hw_handler);
+EXPORT_SYMBOL_GPL(dm_scsi_err_handler);
diff --git a/drivers/md/dm-hw-handler.h b/drivers/md/dm-hw-handler.h
new file mode 100644
index 0000000000000..15f5629e231ad
--- /dev/null
+++ b/drivers/md/dm-hw-handler.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+ *
+ * This file is released under the GPL.
+ *
+ * Multipath hardware handler registration.
+ */
+
+#ifndef DM_HW_HANDLER_H
+#define DM_HW_HANDLER_H
+
+#include <linux/device-mapper.h>
+
+#include "dm-mpath.h"
+
+struct hw_handler_type;
+struct hw_handler {
+ struct hw_handler_type *type;
+ void *context;
+};
+
+/*
+ * Constructs a hardware handler object, takes custom arguments
+ */
+/* Information about a hardware handler type */
+struct hw_handler_type {
+ char *name;
+ struct module *module;
+
+ int (*create) (struct hw_handler *handler, unsigned int argc,
+ char **argv);
+ void (*destroy) (struct hw_handler *hwh);
+
+ void (*pg_init) (struct hw_handler *hwh, unsigned bypassed,
+ struct path *path);
+ unsigned (*error) (struct hw_handler *hwh, struct bio *bio);
+ int (*status) (struct hw_handler *hwh, status_type_t type,
+ char *result, unsigned int maxlen);
+};
+
+/* Register a hardware handler */
+int dm_register_hw_handler(struct hw_handler_type *type);
+
+/* Unregister a hardware handler */
+int dm_unregister_hw_handler(struct hw_handler_type *type);
+
+/* Returns a registered hardware handler type */
+struct hw_handler_type *dm_get_hw_handler(const char *name);
+
+/* Releases a hardware handler */
+void dm_put_hw_handler(struct hw_handler_type *hwht);
+
+/* Default err function */
+unsigned dm_scsi_err_handler(struct hw_handler *hwh, struct bio *bio);
+
+/* Error flags for err and dm_pg_init_complete */
+#define MP_FAIL_PATH 1
+#define MP_BYPASS_PG 2
+#define MP_ERROR_IO 4 /* Don't retry this I/O */
+
+#endif
diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c
index ac5f74766fa28..45754bb6a7999 100644
--- a/drivers/md/dm-io.c
+++ b/drivers/md/dm-io.c
@@ -12,191 +12,7 @@
#include <linux/sched.h>
#include <linux/slab.h>
-#define BIO_POOL_SIZE 256
-
-
-/*-----------------------------------------------------------------
- * Bio set, move this to bio.c
- *---------------------------------------------------------------*/
-#define BV_NAME_SIZE 16
-struct biovec_pool {
- int nr_vecs;
- char name[BV_NAME_SIZE];
- kmem_cache_t *slab;
- mempool_t *pool;
- atomic_t allocated; /* FIXME: debug */
-};
-
-#define BIOVEC_NR_POOLS 6
-struct bio_set {
- char name[BV_NAME_SIZE];
- kmem_cache_t *bio_slab;
- mempool_t *bio_pool;
- struct biovec_pool pools[BIOVEC_NR_POOLS];
-};
-
-static void bio_set_exit(struct bio_set *bs)
-{
- unsigned i;
- struct biovec_pool *bp;
-
- if (bs->bio_pool)
- mempool_destroy(bs->bio_pool);
-
- if (bs->bio_slab)
- kmem_cache_destroy(bs->bio_slab);
-
- for (i = 0; i < BIOVEC_NR_POOLS; i++) {
- bp = bs->pools + i;
- if (bp->pool)
- mempool_destroy(bp->pool);
-
- if (bp->slab)
- kmem_cache_destroy(bp->slab);
- }
-}
-
-static void mk_name(char *str, size_t len, const char *prefix, unsigned count)
-{
- snprintf(str, len, "%s-%u", prefix, count);
-}
-
-static int bio_set_init(struct bio_set *bs, const char *slab_prefix,
- unsigned pool_entries, unsigned scale)
-{
- /* FIXME: this must match bvec_index(), why not go the
- * whole hog and have a pool per power of 2 ? */
- static unsigned _vec_lengths[BIOVEC_NR_POOLS] = {
- 1, 4, 16, 64, 128, BIO_MAX_PAGES
- };
-
-
- unsigned i, size;
- struct biovec_pool *bp;
-
- /* zero the bs so we can tear down properly on error */
- memset(bs, 0, sizeof(*bs));
-
- /*
- * Set up the bio pool.
- */
- snprintf(bs->name, sizeof(bs->name), "%s-bio", slab_prefix);
-
- bs->bio_slab = kmem_cache_create(bs->name, sizeof(struct bio), 0,
- SLAB_HWCACHE_ALIGN, NULL, NULL);
- if (!bs->bio_slab) {
- DMWARN("can't init bio slab");
- goto bad;
- }
-
- bs->bio_pool = mempool_create(pool_entries, mempool_alloc_slab,
- mempool_free_slab, bs->bio_slab);
- if (!bs->bio_pool) {
- DMWARN("can't init bio pool");
- goto bad;
- }
-
- /*
- * Set up the biovec pools.
- */
- for (i = 0; i < BIOVEC_NR_POOLS; i++) {
- bp = bs->pools + i;
- bp->nr_vecs = _vec_lengths[i];
- atomic_set(&bp->allocated, 1); /* FIXME: debug */
-
-
- size = bp->nr_vecs * sizeof(struct bio_vec);
-
- mk_name(bp->name, sizeof(bp->name), slab_prefix, i);
- bp->slab = kmem_cache_create(bp->name, size, 0,
- SLAB_HWCACHE_ALIGN, NULL, NULL);
- if (!bp->slab) {
- DMWARN("can't init biovec slab cache");
- goto bad;
- }
-
- if (i >= scale)
- pool_entries >>= 1;
-
- bp->pool = mempool_create(pool_entries, mempool_alloc_slab,
- mempool_free_slab, bp->slab);
- if (!bp->pool) {
- DMWARN("can't init biovec mempool");
- goto bad;
- }
- }
-
- return 0;
-
- bad:
- bio_set_exit(bs);
- return -ENOMEM;
-}
-
-/* FIXME: blech */
-static inline unsigned bvec_index(unsigned nr)
-{
- switch (nr) {
- case 1: return 0;
- case 2 ... 4: return 1;
- case 5 ... 16: return 2;
- case 17 ... 64: return 3;
- case 65 ... 128:return 4;
- case 129 ... BIO_MAX_PAGES: return 5;
- }
-
- BUG();
- return 0;
-}
-
-static unsigned _bio_count = 0;
-struct bio *bio_set_alloc(struct bio_set *bs, int gfp_mask, int nr_iovecs)
-{
- struct biovec_pool *bp;
- struct bio_vec *bv = NULL;
- unsigned long idx;
- struct bio *bio;
-
- bio = mempool_alloc(bs->bio_pool, gfp_mask);
- if (unlikely(!bio))
- return NULL;
-
- bio_init(bio);
-
- if (likely(nr_iovecs)) {
- idx = bvec_index(nr_iovecs);
- bp = bs->pools + idx;
- bv = mempool_alloc(bp->pool, gfp_mask);
- if (!bv) {
- mempool_free(bio, bs->bio_pool);
- return NULL;
- }
-
- memset(bv, 0, bp->nr_vecs * sizeof(*bv));
- bio->bi_flags |= idx << BIO_POOL_OFFSET;
- bio->bi_max_vecs = bp->nr_vecs;
- atomic_inc(&bp->allocated);
- }
-
- bio->bi_io_vec = bv;
- return bio;
-}
-
-static void bio_set_free(struct bio_set *bs, struct bio *bio)
-{
- struct biovec_pool *bp = bs->pools + BIO_POOL_IDX(bio);
-
- if (atomic_dec_and_test(&bp->allocated))
- BUG();
-
- mempool_free(bio->bi_io_vec, bp->pool);
- mempool_free(bio, bs->bio_pool);
-}
-
-/*-----------------------------------------------------------------
- * dm-io proper
- *---------------------------------------------------------------*/
-static struct bio_set _bios;
+static struct bio_set *_bios;
/* FIXME: can we shrink this ? */
struct io {
@@ -216,7 +32,7 @@ struct io {
static unsigned _num_ios;
static mempool_t *_io_pool;
-static void *alloc_io(int gfp_mask, void *pool_data)
+static void *alloc_io(unsigned int __nocast gfp_mask, void *pool_data)
{
return kmalloc(sizeof(struct io), gfp_mask);
}
@@ -240,7 +56,7 @@ static int resize_pool(unsigned int new_ios)
/* free off the pool */
mempool_destroy(_io_pool);
_io_pool = NULL;
- bio_set_exit(&_bios);
+ bioset_free(_bios);
} else {
/* resize the pool */
@@ -253,10 +69,11 @@ static int resize_pool(unsigned int new_ios)
if (!_io_pool)
return -ENOMEM;
- r = bio_set_init(&_bios, "dm-io", 512, 1);
- if (r) {
+ _bios = bioset_create(16, 16, 4);
+ if (!_bios) {
mempool_destroy(_io_pool);
_io_pool = NULL;
+ return -ENOMEM;
}
}
@@ -280,6 +97,7 @@ void dm_io_put(unsigned int num_pages)
* We need to keep track of which region a bio is doing io for.
* In order to save a memory allocation we store this the last
* bvec which we know is unused (blech).
+ * XXX This is ugly and can OOPS with some configs... find another way.
*---------------------------------------------------------------*/
static inline void bio_set_region(struct bio *bio, unsigned region)
{
@@ -315,21 +133,6 @@ static void dec_count(struct io *io, unsigned int region, int error)
}
}
-/* FIXME Move this to bio.h? */
-static void zero_fill_bio(struct bio *bio)
-{
- unsigned long flags;
- struct bio_vec *bv;
- int i;
-
- bio_for_each_segment(bv, bio, i) {
- char *data = bvec_kmap_irq(bv, &flags);
- memset(data, 0, bv->bv_len);
- flush_dcache_page(bv->bv_page);
- bvec_kunmap_irq(data, &flags);
- }
-}
-
static int endio(struct bio *bio, unsigned int done, int error)
{
struct io *io = (struct io *) bio->bi_private;
@@ -347,12 +150,6 @@ static int endio(struct bio *bio, unsigned int done, int error)
return 0;
}
-static void bio_dtr(struct bio *bio)
-{
- _bio_count--;
- bio_set_free(&_bios, bio);
-}
-
/*-----------------------------------------------------------------
* These little objects provide an abstraction for getting a new
* destination page for io.
@@ -461,13 +258,11 @@ static void do_region(int rw, unsigned int region, struct io_region *where,
* bvec for bio_get/set_region().
*/
num_bvecs = (remaining / (PAGE_SIZE >> 9)) + 2;
- _bio_count++;
- bio = bio_set_alloc(&_bios, GFP_NOIO, num_bvecs);
+ bio = bio_alloc_bioset(GFP_NOIO, num_bvecs, _bios);
bio->bi_sector = where->sector + (where->count - remaining);
bio->bi_bdev = where->bdev;
bio->bi_end_io = endio;
bio->bi_private = io;
- bio->bi_destructor = bio_dtr;
bio_set_region(bio, region);
/*
diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c
index df79d95329f6a..6a2cd5dc8a635 100644
--- a/drivers/md/dm-linear.c
+++ b/drivers/md/dm-linear.c
@@ -80,7 +80,6 @@ static int linear_status(struct dm_target *ti, status_type_t type,
char *result, unsigned int maxlen)
{
struct linear_c *lc = (struct linear_c *) ti->private;
- char buffer[32];
switch (type) {
case STATUSTYPE_INFO:
@@ -88,8 +87,8 @@ static int linear_status(struct dm_target *ti, status_type_t type,
break;
case STATUSTYPE_TABLE:
- format_dev_t(buffer, lc->dev->bdev->bd_dev);
- snprintf(result, maxlen, "%s " SECTOR_FORMAT, buffer, lc->start);
+ snprintf(result, maxlen, "%s " SECTOR_FORMAT, lc->dev->name,
+ lc->start);
break;
}
return 0;
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
new file mode 100644
index 0000000000000..43763a0bd0961
--- /dev/null
+++ b/drivers/md/dm-mpath.c
@@ -0,0 +1,1302 @@
+/*
+ * Copyright (C) 2003 Sistina Software Limited.
+ * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
+ *
+ * This file is released under the GPL.
+ */
+
+#include "dm.h"
+#include "dm-path-selector.h"
+#include "dm-hw-handler.h"
+#include "dm-bio-list.h"
+#include "dm-bio-record.h"
+
+#include <linux/ctype.h>
+#include <linux/init.h>
+#include <linux/mempool.h>
+#include <linux/module.h>
+#include <linux/pagemap.h>
+#include <linux/slab.h>
+#include <linux/time.h>
+#include <linux/workqueue.h>
+#include <asm/atomic.h>
+
+#define MESG_STR(x) x, sizeof(x)
+
+/* Path properties */
+struct pgpath {
+ struct list_head list;
+
+ struct priority_group *pg; /* Owning PG */
+ unsigned fail_count; /* Cumulative failure count */
+
+ struct path path;
+};
+
+#define path_to_pgpath(__pgp) container_of((__pgp), struct pgpath, path)
+
+/*
+ * Paths are grouped into Priority Groups and numbered from 1 upwards.
+ * Each has a path selector which controls which path gets used.
+ */
+struct priority_group {
+ struct list_head list;
+
+ struct multipath *m; /* Owning multipath instance */
+ struct path_selector ps;
+
+ unsigned pg_num; /* Reference number */
+ unsigned bypassed; /* Temporarily bypass this PG? */
+
+ unsigned nr_pgpaths; /* Number of paths in PG */
+ struct list_head pgpaths;
+};
+
+/* Multipath context */
+struct multipath {
+ struct list_head list;
+ struct dm_target *ti;
+
+ spinlock_t lock;
+
+ struct hw_handler hw_handler;
+ unsigned nr_priority_groups;
+ struct list_head priority_groups;
+ unsigned pg_init_required; /* pg_init needs calling? */
+
+ unsigned nr_valid_paths; /* Total number of usable paths */
+ struct pgpath *current_pgpath;
+ struct priority_group *current_pg;
+ struct priority_group *next_pg; /* Switch to this PG if set */
+ unsigned repeat_count; /* I/Os left before calling PS again */
+
+ unsigned queue_io; /* Must we queue all I/O? */
+ unsigned queue_if_no_path; /* Queue I/O if last path fails? */
+ unsigned suspended; /* Has dm core suspended our I/O? */
+
+ struct work_struct process_queued_ios;
+ struct bio_list queued_ios;
+ unsigned queue_size;
+
+ struct work_struct trigger_event;
+
+ /*
+ * We must use a mempool of mpath_io structs so that we
+ * can resubmit bios on error.
+ */
+ mempool_t *mpio_pool;
+};
+
+/*
+ * Context information attached to each bio we process.
+ */
+struct mpath_io {
+ struct pgpath *pgpath;
+ struct dm_bio_details details;
+};
+
+typedef int (*action_fn) (struct pgpath *pgpath);
+
+#define MIN_IOS 256 /* Mempool size */
+
+static kmem_cache_t *_mpio_cache;
+
+static void process_queued_ios(void *data);
+static void trigger_event(void *data);
+
+
+/*-----------------------------------------------
+ * Allocation routines
+ *-----------------------------------------------*/
+
+static struct pgpath *alloc_pgpath(void)
+{
+ struct pgpath *pgpath = kmalloc(sizeof(*pgpath), GFP_KERNEL);
+
+ if (pgpath) {
+ memset(pgpath, 0, sizeof(*pgpath));
+ pgpath->path.is_active = 1;
+ }
+
+ return pgpath;
+}
+
+static inline void free_pgpath(struct pgpath *pgpath)
+{
+ kfree(pgpath);
+}
+
+static struct priority_group *alloc_priority_group(void)
+{
+ struct priority_group *pg;
+
+ pg = kmalloc(sizeof(*pg), GFP_KERNEL);
+ if (!pg)
+ return NULL;
+
+ memset(pg, 0, sizeof(*pg));
+ INIT_LIST_HEAD(&pg->pgpaths);
+
+ return pg;
+}
+
+static void free_pgpaths(struct list_head *pgpaths, struct dm_target *ti)
+{
+ struct pgpath *pgpath, *tmp;
+
+ list_for_each_entry_safe(pgpath, tmp, pgpaths, list) {
+ list_del(&pgpath->list);
+ dm_put_device(ti, pgpath->path.dev);
+ free_pgpath(pgpath);
+ }
+}
+
+static void free_priority_group(struct priority_group *pg,
+ struct dm_target *ti)
+{
+ struct path_selector *ps = &pg->ps;
+
+ if (ps->type) {
+ ps->type->destroy(ps);
+ dm_put_path_selector(ps->type);
+ }
+
+ free_pgpaths(&pg->pgpaths, ti);
+ kfree(pg);
+}
+
+static struct multipath *alloc_multipath(void)
+{
+ struct multipath *m;
+
+ m = kmalloc(sizeof(*m), GFP_KERNEL);
+ if (m) {
+ memset(m, 0, sizeof(*m));
+ INIT_LIST_HEAD(&m->priority_groups);
+ spin_lock_init(&m->lock);
+ m->queue_io = 1;
+ INIT_WORK(&m->process_queued_ios, process_queued_ios, m);
+ INIT_WORK(&m->trigger_event, trigger_event, m);
+ m->mpio_pool = mempool_create(MIN_IOS, mempool_alloc_slab,
+ mempool_free_slab, _mpio_cache);
+ if (!m->mpio_pool) {
+ kfree(m);
+ return NULL;
+ }
+ }
+
+ return m;
+}
+
+static void free_multipath(struct multipath *m)
+{
+ struct priority_group *pg, *tmp;
+ struct hw_handler *hwh = &m->hw_handler;
+
+ list_for_each_entry_safe(pg, tmp, &m->priority_groups, list) {
+ list_del(&pg->list);
+ free_priority_group(pg, m->ti);
+ }
+
+ if (hwh->type) {
+ hwh->type->destroy(hwh);
+ dm_put_hw_handler(hwh->type);
+ }
+
+ mempool_destroy(m->mpio_pool);
+ kfree(m);
+}
+
+
+/*-----------------------------------------------
+ * Path selection
+ *-----------------------------------------------*/
+
+static void __switch_pg(struct multipath *m, struct pgpath *pgpath)
+{
+ struct hw_handler *hwh = &m->hw_handler;
+
+ m->current_pg = pgpath->pg;
+
+ /* Must we initialise the PG first, and queue I/O till it's ready? */
+ if (hwh->type && hwh->type->pg_init) {
+ m->pg_init_required = 1;
+ m->queue_io = 1;
+ } else {
+ m->pg_init_required = 0;
+ m->queue_io = 0;
+ }
+}
+
+static int __choose_path_in_pg(struct multipath *m, struct priority_group *pg)
+{
+ struct path *path;
+
+ path = pg->ps.type->select_path(&pg->ps, &m->repeat_count);
+ if (!path)
+ return -ENXIO;
+
+ m->current_pgpath = path_to_pgpath(path);
+
+ if (m->current_pg != pg)
+ __switch_pg(m, m->current_pgpath);
+
+ return 0;
+}
+
+static void __choose_pgpath(struct multipath *m)
+{
+ struct priority_group *pg;
+ unsigned bypassed = 1;
+
+ if (!m->nr_valid_paths)
+ goto failed;
+
+ /* Were we instructed to switch PG? */
+ if (m->next_pg) {
+ pg = m->next_pg;
+ m->next_pg = NULL;
+ if (!__choose_path_in_pg(m, pg))
+ return;
+ }
+
+ /* Don't change PG until it has no remaining paths */
+ if (m->current_pg && !__choose_path_in_pg(m, m->current_pg))
+ return;
+
+ /*
+ * Loop through priority groups until we find a valid path.
+ * First time we skip PGs marked 'bypassed'.
+ * Second time we only try the ones we skipped.
+ */
+ do {
+ list_for_each_entry(pg, &m->priority_groups, list) {
+ if (pg->bypassed == bypassed)
+ continue;
+ if (!__choose_path_in_pg(m, pg))
+ return;
+ }
+ } while (bypassed--);
+
+failed:
+ m->current_pgpath = NULL;
+ m->current_pg = NULL;
+}
+
+static int map_io(struct multipath *m, struct bio *bio, struct mpath_io *mpio,
+ unsigned was_queued)
+{
+ int r = 1;
+ unsigned long flags;
+ struct pgpath *pgpath;
+
+ spin_lock_irqsave(&m->lock, flags);
+
+ /* Do we need to select a new pgpath? */
+ if (!m->current_pgpath ||
+ (!m->queue_io && (m->repeat_count && --m->repeat_count == 0)))
+ __choose_pgpath(m);
+
+ pgpath = m->current_pgpath;
+
+ if (was_queued)
+ m->queue_size--;
+
+ if ((pgpath && m->queue_io) ||
+ (!pgpath && m->queue_if_no_path && !m->suspended)) {
+ /* Queue for the daemon to resubmit */
+ bio_list_add(&m->queued_ios, bio);
+ m->queue_size++;
+ if (m->pg_init_required || !m->queue_io)
+ schedule_work(&m->process_queued_ios);
+ pgpath = NULL;
+ r = 0;
+ } else if (!pgpath)
+ r = -EIO; /* Failed */
+ else
+ bio->bi_bdev = pgpath->path.dev->bdev;
+
+ mpio->pgpath = pgpath;
+
+ spin_unlock_irqrestore(&m->lock, flags);
+
+ return r;
+}
+
+/*
+ * If we run out of usable paths, should we queue I/O or error it?
+ */
+static int queue_if_no_path(struct multipath *m, unsigned queue_if_no_path)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&m->lock, flags);
+
+ m->queue_if_no_path = queue_if_no_path;
+ if (!m->queue_if_no_path)
+ schedule_work(&m->process_queued_ios);
+
+ spin_unlock_irqrestore(&m->lock, flags);
+
+ return 0;
+}
+
+/*-----------------------------------------------------------------
+ * The multipath daemon is responsible for resubmitting queued ios.
+ *---------------------------------------------------------------*/
+
+static void dispatch_queued_ios(struct multipath *m)
+{
+ int r;
+ unsigned long flags;
+ struct bio *bio = NULL, *next;
+ struct mpath_io *mpio;
+ union map_info *info;
+
+ spin_lock_irqsave(&m->lock, flags);
+ bio = bio_list_get(&m->queued_ios);
+ spin_unlock_irqrestore(&m->lock, flags);
+
+ while (bio) {
+ next = bio->bi_next;
+ bio->bi_next = NULL;
+
+ info = dm_get_mapinfo(bio);
+ mpio = info->ptr;
+
+ r = map_io(m, bio, mpio, 1);
+ if (r < 0)
+ bio_endio(bio, bio->bi_size, r);
+ else if (r == 1)
+ generic_make_request(bio);
+
+ bio = next;
+ }
+}
+
+static void process_queued_ios(void *data)
+{
+ struct multipath *m = (struct multipath *) data;
+ struct hw_handler *hwh = &m->hw_handler;
+ struct pgpath *pgpath;
+ unsigned init_required, must_queue = 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&m->lock, flags);
+
+ if (!m->current_pgpath)
+ __choose_pgpath(m);
+
+ pgpath = m->current_pgpath;
+
+ if ((pgpath && m->queue_io) ||
+ (!pgpath && m->queue_if_no_path && !m->suspended))
+ must_queue = 1;
+
+ init_required = m->pg_init_required;
+ if (init_required)
+ m->pg_init_required = 0;
+
+ spin_unlock_irqrestore(&m->lock, flags);
+
+ if (init_required)
+ hwh->type->pg_init(hwh, pgpath->pg->bypassed, &pgpath->path);
+
+ if (!must_queue)
+ dispatch_queued_ios(m);
+}
+
+/*
+ * An event is triggered whenever a path is taken out of use.
+ * Includes path failure and PG bypass.
+ */
+static void trigger_event(void *data)
+{
+ struct multipath *m = (struct multipath *) data;
+
+ dm_table_event(m->ti->table);
+}
+
+/*-----------------------------------------------------------------
+ * Constructor/argument parsing:
+ * <#multipath feature args> [<arg>]*
+ * <#hw_handler args> [hw_handler [<arg>]*]
+ * <#priority groups>
+ * <initial priority group>
+ * [<selector> <#selector args> [<arg>]*
+ * <#paths> <#per-path selector args>
+ * [<path> [<arg>]* ]+ ]+
+ *---------------------------------------------------------------*/
+struct param {
+ unsigned min;
+ unsigned max;
+ char *error;
+};
+
+#define ESTR(s) ("dm-multipath: " s)
+
+static int read_param(struct param *param, char *str, unsigned *v, char **error)
+{
+ if (!str ||
+ (sscanf(str, "%u", v) != 1) ||
+ (*v < param->min) ||
+ (*v > param->max)) {
+ *error = param->error;
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+struct arg_set {
+ unsigned argc;
+ char **argv;
+};
+
+static char *shift(struct arg_set *as)
+{
+ char *r;
+
+ if (as->argc) {
+ as->argc--;
+ r = *as->argv;
+ as->argv++;
+ return r;
+ }
+
+ return NULL;
+}
+
+static void consume(struct arg_set *as, unsigned n)
+{
+ BUG_ON (as->argc < n);
+ as->argc -= n;
+ as->argv += n;
+}
+
+static int parse_path_selector(struct arg_set *as, struct priority_group *pg,
+ struct dm_target *ti)
+{
+ int r;
+ struct path_selector_type *pst;
+ unsigned ps_argc;
+
+ static struct param _params[] = {
+ {0, 1024, ESTR("invalid number of path selector args")},
+ };
+
+ pst = dm_get_path_selector(shift(as));
+ if (!pst) {
+ ti->error = ESTR("unknown path selector type");
+ return -EINVAL;
+ }
+
+ r = read_param(_params, shift(as), &ps_argc, &ti->error);
+ if (r)
+ return -EINVAL;
+
+ r = pst->create(&pg->ps, ps_argc, as->argv);
+ if (r) {
+ dm_put_path_selector(pst);
+ ti->error = ESTR("path selector constructor failed");
+ return r;
+ }
+
+ pg->ps.type = pst;
+ consume(as, ps_argc);
+
+ return 0;
+}
+
+static struct pgpath *parse_path(struct arg_set *as, struct path_selector *ps,
+ struct dm_target *ti)
+{
+ int r;
+ struct pgpath *p;
+
+ /* we need at least a path arg */
+ if (as->argc < 1) {
+ ti->error = ESTR("no device given");
+ return NULL;
+ }
+
+ p = alloc_pgpath();
+ if (!p)
+ return NULL;
+
+ r = dm_get_device(ti, shift(as), ti->begin, ti->len,
+ dm_table_get_mode(ti->table), &p->path.dev);
+ if (r) {
+ ti->error = ESTR("error getting device");
+ goto bad;
+ }
+
+ r = ps->type->add_path(ps, &p->path, as->argc, as->argv, &ti->error);
+ if (r) {
+ dm_put_device(ti, p->path.dev);
+ goto bad;
+ }
+
+ return p;
+
+ bad:
+ free_pgpath(p);
+ return NULL;
+}
+
+static struct priority_group *parse_priority_group(struct arg_set *as,
+ struct multipath *m,
+ struct dm_target *ti)
+{
+ static struct param _params[] = {
+ {1, 1024, ESTR("invalid number of paths")},
+ {0, 1024, ESTR("invalid number of selector args")}
+ };
+
+ int r;
+ unsigned i, nr_selector_args, nr_params;
+ struct priority_group *pg;
+
+ if (as->argc < 2) {
+ as->argc = 0;
+ ti->error = ESTR("not enough priority group aruments");
+ return NULL;
+ }
+
+ pg = alloc_priority_group();
+ if (!pg) {
+ ti->error = ESTR("couldn't allocate priority group");
+ return NULL;
+ }
+ pg->m = m;
+
+ r = parse_path_selector(as, pg, ti);
+ if (r)
+ goto bad;
+
+ /*
+ * read the paths
+ */
+ r = read_param(_params, shift(as), &pg->nr_pgpaths, &ti->error);
+ if (r)
+ goto bad;
+
+ r = read_param(_params + 1, shift(as), &nr_selector_args, &ti->error);
+ if (r)
+ goto bad;
+
+ nr_params = 1 + nr_selector_args;
+ for (i = 0; i < pg->nr_pgpaths; i++) {
+ struct pgpath *pgpath;
+ struct arg_set path_args;
+
+ if (as->argc < nr_params)
+ goto bad;
+
+ path_args.argc = nr_params;
+ path_args.argv = as->argv;
+
+ pgpath = parse_path(&path_args, &pg->ps, ti);
+ if (!pgpath)
+ goto bad;
+
+ pgpath->pg = pg;
+ list_add_tail(&pgpath->list, &pg->pgpaths);
+ consume(as, nr_params);
+ }
+
+ return pg;
+
+ bad:
+ free_priority_group(pg, ti);
+ return NULL;
+}
+
+static int parse_hw_handler(struct arg_set *as, struct multipath *m,
+ struct dm_target *ti)
+{
+ int r;
+ struct hw_handler_type *hwht;
+ unsigned hw_argc;
+
+ static struct param _params[] = {
+ {0, 1024, ESTR("invalid number of hardware handler args")},
+ };
+
+ r = read_param(_params, shift(as), &hw_argc, &ti->error);
+ if (r)
+ return -EINVAL;
+
+ if (!hw_argc)
+ return 0;
+
+ hwht = dm_get_hw_handler(shift(as));
+ if (!hwht) {
+ ti->error = ESTR("unknown hardware handler type");
+ return -EINVAL;
+ }
+
+ r = hwht->create(&m->hw_handler, hw_argc - 1, as->argv);
+ if (r) {
+ dm_put_hw_handler(hwht);
+ ti->error = ESTR("hardware handler constructor failed");
+ return r;
+ }
+
+ m->hw_handler.type = hwht;
+ consume(as, hw_argc - 1);
+
+ return 0;
+}
+
+static int parse_features(struct arg_set *as, struct multipath *m,
+ struct dm_target *ti)
+{
+ int r;
+ unsigned argc;
+
+ static struct param _params[] = {
+ {0, 1, ESTR("invalid number of feature args")},
+ };
+
+ r = read_param(_params, shift(as), &argc, &ti->error);
+ if (r)
+ return -EINVAL;
+
+ if (!argc)
+ return 0;
+
+ if (!strnicmp(shift(as), MESG_STR("queue_if_no_path")))
+ return queue_if_no_path(m, 1);
+ else {
+ ti->error = "Unrecognised multipath feature request";
+ return -EINVAL;
+ }
+}
+
+static int multipath_ctr(struct dm_target *ti, unsigned int argc,
+ char **argv)
+{
+ /* target parameters */
+ static struct param _params[] = {
+ {1, 1024, ESTR("invalid number of priority groups")},
+ {1, 1024, ESTR("invalid initial priority group number")},
+ };
+
+ int r;
+ struct multipath *m;
+ struct arg_set as;
+ unsigned pg_count = 0;
+ unsigned next_pg_num;
+
+ as.argc = argc;
+ as.argv = argv;
+
+ m = alloc_multipath();
+ if (!m) {
+ ti->error = ESTR("can't allocate multipath");
+ return -EINVAL;
+ }
+
+ r = parse_features(&as, m, ti);
+ if (r)
+ goto bad;
+
+ r = parse_hw_handler(&as, m, ti);
+ if (r)
+ goto bad;
+
+ r = read_param(_params, shift(&as), &m->nr_priority_groups, &ti->error);
+ if (r)
+ goto bad;
+
+ r = read_param(_params + 1, shift(&as), &next_pg_num, &ti->error);
+ if (r)
+ goto bad;
+
+ /* parse the priority groups */
+ while (as.argc) {
+ struct priority_group *pg;
+
+ pg = parse_priority_group(&as, m, ti);
+ if (!pg) {
+ r = -EINVAL;
+ goto bad;
+ }
+
+ m->nr_valid_paths += pg->nr_pgpaths;
+ list_add_tail(&pg->list, &m->priority_groups);
+ pg_count++;
+ pg->pg_num = pg_count;
+ if (!--next_pg_num)
+ m->next_pg = pg;
+ }
+
+ if (pg_count != m->nr_priority_groups) {
+ ti->error = ESTR("priority group count mismatch");
+ r = -EINVAL;
+ goto bad;
+ }
+
+ ti->private = m;
+ m->ti = ti;
+
+ return 0;
+
+ bad:
+ free_multipath(m);
+ return r;
+}
+
+static void multipath_dtr(struct dm_target *ti)
+{
+ struct multipath *m = (struct multipath *) ti->private;
+ free_multipath(m);
+}
+
+/*
+ * Map bios, recording original fields for later in case we have to resubmit
+ */
+static int multipath_map(struct dm_target *ti, struct bio *bio,
+ union map_info *map_context)
+{
+ int r;
+ struct mpath_io *mpio;
+ struct multipath *m = (struct multipath *) ti->private;
+
+ mpio = mempool_alloc(m->mpio_pool, GFP_NOIO);
+ dm_bio_record(&mpio->details, bio);
+
+ map_context->ptr = mpio;
+ bio->bi_rw |= (1 << BIO_RW_FAILFAST);
+ r = map_io(m, bio, mpio, 0);
+ if (r < 0)
+ mempool_free(mpio, m->mpio_pool);
+
+ return r;
+}
+
+/*
+ * Take a path out of use.
+ */
+static int fail_path(struct pgpath *pgpath)
+{
+ unsigned long flags;
+ struct multipath *m = pgpath->pg->m;
+
+ spin_lock_irqsave(&m->lock, flags);
+
+ if (!pgpath->path.is_active)
+ goto out;
+
+ DMWARN("dm-multipath: Failing path %s.", pgpath->path.dev->name);
+
+ pgpath->pg->ps.type->fail_path(&pgpath->pg->ps, &pgpath->path);
+ pgpath->path.is_active = 0;
+ pgpath->fail_count++;
+
+ m->nr_valid_paths--;
+
+ if (pgpath == m->current_pgpath)
+ m->current_pgpath = NULL;
+
+ schedule_work(&m->trigger_event);
+
+out:
+ spin_unlock_irqrestore(&m->lock, flags);
+
+ return 0;
+}
+
+/*
+ * Reinstate a previously-failed path
+ */
+static int reinstate_path(struct pgpath *pgpath)
+{
+ int r = 0;
+ unsigned long flags;
+ struct multipath *m = pgpath->pg->m;
+
+ spin_lock_irqsave(&m->lock, flags);
+
+ if (pgpath->path.is_active)
+ goto out;
+
+ if (!pgpath->pg->ps.type) {
+ DMWARN("Reinstate path not supported by path selector %s",
+ pgpath->pg->ps.type->name);
+ r = -EINVAL;
+ goto out;
+ }
+
+ r = pgpath->pg->ps.type->reinstate_path(&pgpath->pg->ps, &pgpath->path);
+ if (r)
+ goto out;
+
+ pgpath->path.is_active = 1;
+
+ m->current_pgpath = NULL;
+ if (!m->nr_valid_paths++)
+ schedule_work(&m->process_queued_ios);
+
+ schedule_work(&m->trigger_event);
+
+out:
+ spin_unlock_irqrestore(&m->lock, flags);
+
+ return r;
+}
+
+/*
+ * Fail or reinstate all paths that match the provided struct dm_dev.
+ */
+static int action_dev(struct multipath *m, struct dm_dev *dev,
+ action_fn action)
+{
+ int r = 0;
+ struct pgpath *pgpath;
+ struct priority_group *pg;
+
+ list_for_each_entry(pg, &m->priority_groups, list) {
+ list_for_each_entry(pgpath, &pg->pgpaths, list) {
+ if (pgpath->path.dev == dev)
+ r = action(pgpath);
+ }
+ }
+
+ return r;
+}
+
+/*
+ * Temporarily try to avoid having to use the specified PG
+ */
+static void bypass_pg(struct multipath *m, struct priority_group *pg,
+ int bypassed)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&m->lock, flags);
+
+ pg->bypassed = bypassed;
+ m->current_pgpath = NULL;
+ m->current_pg = NULL;
+
+ spin_unlock_irqrestore(&m->lock, flags);
+
+ schedule_work(&m->trigger_event);
+}
+
+/*
+ * Switch to using the specified PG from the next I/O that gets mapped
+ */
+static int switch_pg_num(struct multipath *m, const char *pgstr)
+{
+ struct priority_group *pg;
+ unsigned pgnum;
+ unsigned long flags;
+
+ if (!pgstr || (sscanf(pgstr, "%u", &pgnum) != 1) || !pgnum ||
+ (pgnum > m->nr_priority_groups)) {
+ DMWARN("invalid PG number supplied to switch_pg_num");
+ return -EINVAL;
+ }
+
+ spin_lock_irqsave(&m->lock, flags);
+ list_for_each_entry(pg, &m->priority_groups, list) {
+ pg->bypassed = 0;
+ if (--pgnum)
+ continue;
+
+ m->current_pgpath = NULL;
+ m->current_pg = NULL;
+ m->next_pg = pg;
+ }
+ spin_unlock_irqrestore(&m->lock, flags);
+
+ schedule_work(&m->trigger_event);
+ return 0;
+}
+
+/*
+ * Set/clear bypassed status of a PG.
+ * PGs are numbered upwards from 1 in the order they were declared.
+ */
+static int bypass_pg_num(struct multipath *m, const char *pgstr, int bypassed)
+{
+ struct priority_group *pg;
+ unsigned pgnum;
+
+ if (!pgstr || (sscanf(pgstr, "%u", &pgnum) != 1) || !pgnum ||
+ (pgnum > m->nr_priority_groups)) {
+ DMWARN("invalid PG number supplied to bypass_pg");
+ return -EINVAL;
+ }
+
+ list_for_each_entry(pg, &m->priority_groups, list) {
+ if (!--pgnum)
+ break;
+ }
+
+ bypass_pg(m, pg, bypassed);
+ return 0;
+}
+
+/*
+ * pg_init must call this when it has completed its initialisation
+ */
+void dm_pg_init_complete(struct path *path, unsigned err_flags)
+{
+ struct pgpath *pgpath = path_to_pgpath(path);
+ struct priority_group *pg = pgpath->pg;
+ struct multipath *m = pg->m;
+ unsigned long flags;
+
+ /* We insist on failing the path if the PG is already bypassed. */
+ if (err_flags && pg->bypassed)
+ err_flags |= MP_FAIL_PATH;
+
+ if (err_flags & MP_FAIL_PATH)
+ fail_path(pgpath);
+
+ if (err_flags & MP_BYPASS_PG)
+ bypass_pg(m, pg, 1);
+
+ spin_lock_irqsave(&m->lock, flags);
+ if (!err_flags)
+ m->queue_io = 0;
+ else {
+ m->current_pgpath = NULL;
+ m->current_pg = NULL;
+ }
+ schedule_work(&m->process_queued_ios);
+ spin_unlock_irqrestore(&m->lock, flags);
+}
+
+/*
+ * end_io handling
+ */
+static int do_end_io(struct multipath *m, struct bio *bio,
+ int error, struct mpath_io *mpio)
+{
+ struct hw_handler *hwh = &m->hw_handler;
+ unsigned err_flags = MP_FAIL_PATH; /* Default behavior */
+
+ if (!error)
+ return 0; /* I/O complete */
+
+ spin_lock(&m->lock);
+ if (!m->nr_valid_paths) {
+ if (!m->queue_if_no_path || m->suspended) {
+ spin_unlock(&m->lock);
+ return -EIO;
+ } else {
+ spin_unlock(&m->lock);
+ goto requeue;
+ }
+ }
+ spin_unlock(&m->lock);
+
+ if (hwh->type && hwh->type->error)
+ err_flags = hwh->type->error(hwh, bio);
+
+ if (mpio->pgpath) {
+ if (err_flags & MP_FAIL_PATH)
+ fail_path(mpio->pgpath);
+
+ if (err_flags & MP_BYPASS_PG)
+ bypass_pg(m, mpio->pgpath->pg, 1);
+ }
+
+ if (err_flags & MP_ERROR_IO)
+ return -EIO;
+
+ requeue:
+ dm_bio_restore(&mpio->details, bio);
+
+ /* queue for the daemon to resubmit or fail */
+ spin_lock(&m->lock);
+ bio_list_add(&m->queued_ios, bio);
+ m->queue_size++;
+ if (!m->queue_io)
+ schedule_work(&m->process_queued_ios);
+ spin_unlock(&m->lock);
+
+ return 1; /* io not complete */
+}
+
+static int multipath_end_io(struct dm_target *ti, struct bio *bio,
+ int error, union map_info *map_context)
+{
+ struct multipath *m = (struct multipath *) ti->private;
+ struct mpath_io *mpio = (struct mpath_io *) map_context->ptr;
+ struct pgpath *pgpath = mpio->pgpath;
+ struct path_selector *ps;
+ int r;
+
+ r = do_end_io(m, bio, error, mpio);
+ if (pgpath) {
+ ps = &pgpath->pg->ps;
+ if (ps->type->end_io)
+ ps->type->end_io(ps, &pgpath->path);
+ }
+ if (r <= 0)
+ mempool_free(mpio, m->mpio_pool);
+
+ return r;
+}
+
+/*
+ * Suspend can't complete until all the I/O is processed so if
+ * the last path failed we will now error any queued I/O.
+ */
+static void multipath_presuspend(struct dm_target *ti)
+{
+ struct multipath *m = (struct multipath *) ti->private;
+ unsigned long flags;
+
+ spin_lock_irqsave(&m->lock, flags);
+ m->suspended = 1;
+ if (m->queue_if_no_path)
+ schedule_work(&m->process_queued_ios);
+ spin_unlock_irqrestore(&m->lock, flags);
+}
+
+static void multipath_resume(struct dm_target *ti)
+{
+ struct multipath *m = (struct multipath *) ti->private;
+ unsigned long flags;
+
+ spin_lock_irqsave(&m->lock, flags);
+ m->suspended = 0;
+ spin_unlock_irqrestore(&m->lock, flags);
+}
+
+/*
+ * Info output has the following format:
+ * num_multipath_feature_args [multipath_feature_args]*
+ * num_handler_status_args [handler_status_args]*
+ * num_groups init_group_number
+ * [A|D|E num_ps_status_args [ps_status_args]*
+ * num_paths num_selector_args
+ * [path_dev A|F fail_count [selector_args]* ]+ ]+
+ *
+ * Table output has the following format (identical to the constructor string):
+ * num_feature_args [features_args]*
+ * num_handler_args hw_handler [hw_handler_args]*
+ * num_groups init_group_number
+ * [priority selector-name num_ps_args [ps_args]*
+ * num_paths num_selector_args [path_dev [selector_args]* ]+ ]+
+ */
+static int multipath_status(struct dm_target *ti, status_type_t type,
+ char *result, unsigned int maxlen)
+{
+ int sz = 0;
+ unsigned long flags;
+ struct multipath *m = (struct multipath *) ti->private;
+ struct hw_handler *hwh = &m->hw_handler;
+ struct priority_group *pg;
+ struct pgpath *p;
+ unsigned pg_num;
+ char state;
+
+ spin_lock_irqsave(&m->lock, flags);
+
+ /* Features */
+ if (type == STATUSTYPE_INFO)
+ DMEMIT("1 %u ", m->queue_size);
+ else if (m->queue_if_no_path)
+ DMEMIT("1 queue_if_no_path ");
+ else
+ DMEMIT("0 ");
+
+ if (hwh->type && hwh->type->status)
+ sz += hwh->type->status(hwh, type, result + sz, maxlen - sz);
+ else if (!hwh->type || type == STATUSTYPE_INFO)
+ DMEMIT("0 ");
+ else
+ DMEMIT("1 %s ", hwh->type->name);
+
+ DMEMIT("%u ", m->nr_priority_groups);
+
+ if (m->next_pg)
+ pg_num = m->next_pg->pg_num;
+ else if (m->current_pg)
+ pg_num = m->current_pg->pg_num;
+ else
+ pg_num = 1;
+
+ DMEMIT("%u ", pg_num);
+
+ switch (type) {
+ case STATUSTYPE_INFO:
+ list_for_each_entry(pg, &m->priority_groups, list) {
+ if (pg->bypassed)
+ state = 'D'; /* Disabled */
+ else if (pg == m->current_pg)
+ state = 'A'; /* Currently Active */
+ else
+ state = 'E'; /* Enabled */
+
+ DMEMIT("%c ", state);
+
+ if (pg->ps.type->status)
+ sz += pg->ps.type->status(&pg->ps, NULL, type,
+ result + sz,
+ maxlen - sz);
+ else
+ DMEMIT("0 ");
+
+ DMEMIT("%u %u ", pg->nr_pgpaths,
+ pg->ps.type->info_args);
+
+ list_for_each_entry(p, &pg->pgpaths, list) {
+ DMEMIT("%s %s %u ", p->path.dev->name,
+ p->path.is_active ? "A" : "F",
+ p->fail_count);
+ if (pg->ps.type->status)
+ sz += pg->ps.type->status(&pg->ps,
+ &p->path, type, result + sz,
+ maxlen - sz);
+ }
+ }
+ break;
+
+ case STATUSTYPE_TABLE:
+ list_for_each_entry(pg, &m->priority_groups, list) {
+ DMEMIT("%s ", pg->ps.type->name);
+
+ if (pg->ps.type->status)
+ sz += pg->ps.type->status(&pg->ps, NULL, type,
+ result + sz,
+ maxlen - sz);
+ else
+ DMEMIT("0 ");
+
+ DMEMIT("%u %u ", pg->nr_pgpaths,
+ pg->ps.type->table_args);
+
+ list_for_each_entry(p, &pg->pgpaths, list) {
+ DMEMIT("%s ", p->path.dev->name);
+ if (pg->ps.type->status)
+ sz += pg->ps.type->status(&pg->ps,
+ &p->path, type, result + sz,
+ maxlen - sz);
+ }
+ }
+ break;
+ }
+
+ spin_unlock_irqrestore(&m->lock, flags);
+
+ return 0;
+}
+
+static int multipath_message(struct dm_target *ti, unsigned argc, char **argv)
+{
+ int r;
+ struct dm_dev *dev;
+ struct multipath *m = (struct multipath *) ti->private;
+ action_fn action;
+
+ if (argc == 1) {
+ if (!strnicmp(argv[0], MESG_STR("queue_if_no_path")))
+ return queue_if_no_path(m, 1);
+ else if (!strnicmp(argv[0], MESG_STR("fail_if_no_path")))
+ return queue_if_no_path(m, 0);
+ }
+
+ if (argc != 2)
+ goto error;
+
+ if (!strnicmp(argv[0], MESG_STR("disable_group")))
+ return bypass_pg_num(m, argv[1], 1);
+ else if (!strnicmp(argv[0], MESG_STR("enable_group")))
+ return bypass_pg_num(m, argv[1], 0);
+ else if (!strnicmp(argv[0], MESG_STR("switch_group")))
+ return switch_pg_num(m, argv[1]);
+ else if (!strnicmp(argv[0], MESG_STR("reinstate_path")))
+ action = reinstate_path;
+ else if (!strnicmp(argv[0], MESG_STR("fail_path")))
+ action = fail_path;
+ else
+ goto error;
+
+ r = dm_get_device(ti, argv[1], ti->begin, ti->len,
+ dm_table_get_mode(ti->table), &dev);
+ if (r) {
+ DMWARN("dm-multipath message: error getting device %s",
+ argv[1]);
+ return -EINVAL;
+ }
+
+ r = action_dev(m, dev, action);
+
+ dm_put_device(ti, dev);
+
+ return r;
+
+error:
+ DMWARN("Unrecognised multipath message received.");
+ return -EINVAL;
+}
+
+/*-----------------------------------------------------------------
+ * Module setup
+ *---------------------------------------------------------------*/
+static struct target_type multipath_target = {
+ .name = "multipath",
+ .version = {1, 0, 4},
+ .module = THIS_MODULE,
+ .ctr = multipath_ctr,
+ .dtr = multipath_dtr,
+ .map = multipath_map,
+ .end_io = multipath_end_io,
+ .presuspend = multipath_presuspend,
+ .resume = multipath_resume,
+ .status = multipath_status,
+ .message = multipath_message,
+};
+
+static int __init dm_multipath_init(void)
+{
+ int r;
+
+ /* allocate a slab for the dm_ios */
+ _mpio_cache = kmem_cache_create("dm_mpath", sizeof(struct mpath_io),
+ 0, 0, NULL, NULL);
+ if (!_mpio_cache)
+ return -ENOMEM;
+
+ r = dm_register_target(&multipath_target);
+ if (r < 0) {
+ DMERR("%s: register failed %d", multipath_target.name, r);
+ kmem_cache_destroy(_mpio_cache);
+ return -EINVAL;
+ }
+
+ DMINFO("dm-multipath version %u.%u.%u loaded",
+ multipath_target.version[0], multipath_target.version[1],
+ multipath_target.version[2]);
+
+ return r;
+}
+
+static void __exit dm_multipath_exit(void)
+{
+ int r;
+
+ r = dm_unregister_target(&multipath_target);
+ if (r < 0)
+ DMERR("%s: target unregister failed %d",
+ multipath_target.name, r);
+ kmem_cache_destroy(_mpio_cache);
+}
+
+EXPORT_SYMBOL_GPL(dm_pg_init_complete);
+
+module_init(dm_multipath_init);
+module_exit(dm_multipath_exit);
+
+MODULE_DESCRIPTION(DM_NAME " multipath target");
+MODULE_AUTHOR("Sistina Software <dm-devel@redhat.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/md/dm-mpath.h b/drivers/md/dm-mpath.h
new file mode 100644
index 0000000000000..8a4bf2b6d52e0
--- /dev/null
+++ b/drivers/md/dm-mpath.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+ *
+ * This file is released under the GPL.
+ *
+ * Multipath.
+ */
+
+#ifndef DM_MPATH_H
+#define DM_MPATH_H
+
+struct dm_dev;
+
+struct path {
+ struct dm_dev *dev; /* Read-only */
+ unsigned is_active; /* Read-only */
+
+ void *pscontext; /* For path-selector use */
+ void *hwhcontext; /* For hw-handler use */
+};
+
+/* Callback for hwh_pg_init_fn to use when complete */
+void dm_pg_init_complete(struct path *path, unsigned err_flags);
+
+#endif
diff --git a/drivers/md/dm-path-selector.c b/drivers/md/dm-path-selector.c
new file mode 100644
index 0000000000000..ac5c4bbec6c18
--- /dev/null
+++ b/drivers/md/dm-path-selector.c
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2003 Sistina Software.
+ * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+ *
+ * Module Author: Heinz Mauelshagen
+ *
+ * This file is released under the GPL.
+ *
+ * Path selector registration.
+ */
+
+#include "dm.h"
+#include "dm-path-selector.h"
+
+#include <linux/slab.h>
+
+struct ps_internal {
+ struct path_selector_type pst;
+
+ struct list_head list;
+ long use;
+};
+
+#define pst_to_psi(__pst) container_of((__pst), struct ps_internal, pst)
+
+static LIST_HEAD(_path_selectors);
+static DECLARE_RWSEM(_ps_lock);
+
+struct ps_internal *__find_path_selector_type(const char *name)
+{
+ struct ps_internal *psi;
+
+ list_for_each_entry(psi, &_path_selectors, list) {
+ if (!strcmp(name, psi->pst.name))
+ return psi;
+ }
+
+ return NULL;
+}
+
+static struct ps_internal *get_path_selector(const char *name)
+{
+ struct ps_internal *psi;
+
+ down_read(&_ps_lock);
+ psi = __find_path_selector_type(name);
+ if (psi) {
+ if ((psi->use == 0) && !try_module_get(psi->pst.module))
+ psi = NULL;
+ else
+ psi->use++;
+ }
+ up_read(&_ps_lock);
+
+ return psi;
+}
+
+struct path_selector_type *dm_get_path_selector(const char *name)
+{
+ struct ps_internal *psi;
+
+ if (!name)
+ return NULL;
+
+ psi = get_path_selector(name);
+ if (!psi) {
+ request_module("dm-%s", name);
+ psi = get_path_selector(name);
+ }
+
+ return psi ? &psi->pst : NULL;
+}
+
+void dm_put_path_selector(struct path_selector_type *pst)
+{
+ struct ps_internal *psi;
+
+ if (!pst)
+ return;
+
+ down_read(&_ps_lock);
+ psi = __find_path_selector_type(pst->name);
+ if (!psi)
+ goto out;
+
+ if (--psi->use == 0)
+ module_put(psi->pst.module);
+
+ if (psi->use < 0)
+ BUG();
+
+out:
+ up_read(&_ps_lock);
+}
+
+static struct ps_internal *_alloc_path_selector(struct path_selector_type *pst)
+{
+ struct ps_internal *psi = kmalloc(sizeof(*psi), GFP_KERNEL);
+
+ if (psi) {
+ memset(psi, 0, sizeof(*psi));
+ psi->pst = *pst;
+ }
+
+ return psi;
+}
+
+int dm_register_path_selector(struct path_selector_type *pst)
+{
+ int r = 0;
+ struct ps_internal *psi = _alloc_path_selector(pst);
+
+ if (!psi)
+ return -ENOMEM;
+
+ down_write(&_ps_lock);
+
+ if (__find_path_selector_type(pst->name)) {
+ kfree(psi);
+ r = -EEXIST;
+ } else
+ list_add(&psi->list, &_path_selectors);
+
+ up_write(&_ps_lock);
+
+ return r;
+}
+
+int dm_unregister_path_selector(struct path_selector_type *pst)
+{
+ struct ps_internal *psi;
+
+ down_write(&_ps_lock);
+
+ psi = __find_path_selector_type(pst->name);
+ if (!psi) {
+ up_write(&_ps_lock);
+ return -EINVAL;
+ }
+
+ if (psi->use) {
+ up_write(&_ps_lock);
+ return -ETXTBSY;
+ }
+
+ list_del(&psi->list);
+
+ up_write(&_ps_lock);
+
+ kfree(psi);
+
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(dm_register_path_selector);
+EXPORT_SYMBOL_GPL(dm_unregister_path_selector);
diff --git a/drivers/md/dm-path-selector.h b/drivers/md/dm-path-selector.h
new file mode 100644
index 0000000000000..732d06a84f850
--- /dev/null
+++ b/drivers/md/dm-path-selector.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2003 Sistina Software.
+ * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+ *
+ * Module Author: Heinz Mauelshagen
+ *
+ * This file is released under the GPL.
+ *
+ * Path-Selector registration.
+ */
+
+#ifndef DM_PATH_SELECTOR_H
+#define DM_PATH_SELECTOR_H
+
+#include <linux/device-mapper.h>
+
+#include "dm-mpath.h"
+
+/*
+ * We provide an abstraction for the code that chooses which path
+ * to send some io down.
+ */
+struct path_selector_type;
+struct path_selector {
+ struct path_selector_type *type;
+ void *context;
+};
+
+/* Information about a path selector type */
+struct path_selector_type {
+ char *name;
+ struct module *module;
+
+ unsigned int table_args;
+ unsigned int info_args;
+
+ /*
+ * Constructs a path selector object, takes custom arguments
+ */
+ int (*create) (struct path_selector *ps, unsigned argc, char **argv);
+ void (*destroy) (struct path_selector *ps);
+
+ /*
+ * Add an opaque path object, along with some selector specific
+ * path args (eg, path priority).
+ */
+ int (*add_path) (struct path_selector *ps, struct path *path,
+ int argc, char **argv, char **error);
+
+ /*
+ * Chooses a path for this io, if no paths are available then
+ * NULL will be returned.
+ *
+ * repeat_count is the number of times to use the path before
+ * calling the function again. 0 means don't call it again unless
+ * the path fails.
+ */
+ struct path *(*select_path) (struct path_selector *ps,
+ unsigned *repeat_count);
+
+ /*
+ * Notify the selector that a path has failed.
+ */
+ void (*fail_path) (struct path_selector *ps, struct path *p);
+
+ /*
+ * Ask selector to reinstate a path.
+ */
+ int (*reinstate_path) (struct path_selector *ps, struct path *p);
+
+ /*
+ * Table content based on parameters added in ps_add_path_fn
+ * or path selector status
+ */
+ int (*status) (struct path_selector *ps, struct path *path,
+ status_type_t type, char *result, unsigned int maxlen);
+
+ int (*end_io) (struct path_selector *ps, struct path *path);
+};
+
+/* Register a path selector */
+int dm_register_path_selector(struct path_selector_type *type);
+
+/* Unregister a path selector */
+int dm_unregister_path_selector(struct path_selector_type *type);
+
+/* Returns a registered path selector type */
+struct path_selector_type *dm_get_path_selector(const char *name);
+
+/* Releases a path selector */
+void dm_put_path_selector(struct path_selector_type *pst);
+
+#endif
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c
index 1fb4dfb114453..6e3cf7e134515 100644
--- a/drivers/md/dm-raid1.c
+++ b/drivers/md/dm-raid1.c
@@ -122,7 +122,7 @@ static inline sector_t region_to_sector(struct region_hash *rh, region_t region)
/* FIXME move this */
static void queue_bio(struct mirror_set *ms, struct bio *bio, int rw);
-static void *region_alloc(int gfp_mask, void *pool_data)
+static void *region_alloc(unsigned int __nocast gfp_mask, void *pool_data)
{
return kmalloc(sizeof(struct region), gfp_mask);
}
@@ -1182,7 +1182,6 @@ static void mirror_resume(struct dm_target *ti)
static int mirror_status(struct dm_target *ti, status_type_t type,
char *result, unsigned int maxlen)
{
- char buffer[32];
unsigned int m, sz;
struct mirror_set *ms = (struct mirror_set *) ti->private;
@@ -1191,10 +1190,8 @@ static int mirror_status(struct dm_target *ti, status_type_t type,
switch (type) {
case STATUSTYPE_INFO:
DMEMIT("%d ", ms->nr_mirrors);
- for (m = 0; m < ms->nr_mirrors; m++) {
- format_dev_t(buffer, ms->mirror[m].dev->bdev->bd_dev);
- DMEMIT("%s ", buffer);
- }
+ for (m = 0; m < ms->nr_mirrors; m++)
+ DMEMIT("%s ", ms->mirror[m].dev->name);
DMEMIT(SECTOR_FORMAT "/" SECTOR_FORMAT,
ms->rh.log->type->get_sync_count(ms->rh.log),
@@ -1203,11 +1200,9 @@ static int mirror_status(struct dm_target *ti, status_type_t type,
case STATUSTYPE_TABLE:
DMEMIT("%d ", ms->nr_mirrors);
- for (m = 0; m < ms->nr_mirrors; m++) {
- format_dev_t(buffer, ms->mirror[m].dev->bdev->bd_dev);
+ for (m = 0; m < ms->nr_mirrors; m++)
DMEMIT("%s " SECTOR_FORMAT " ",
- buffer, ms->mirror[m].offset);
- }
+ ms->mirror[m].dev->name, ms->mirror[m].offset);
}
return 0;
diff --git a/drivers/md/dm-round-robin.c b/drivers/md/dm-round-robin.c
new file mode 100644
index 0000000000000..d0024865a7893
--- /dev/null
+++ b/drivers/md/dm-round-robin.c
@@ -0,0 +1,214 @@
+/*
+ * Copyright (C) 2003 Sistina Software.
+ * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
+ *
+ * Module Author: Heinz Mauelshagen
+ *
+ * This file is released under the GPL.
+ *
+ * Round-robin path selector.
+ */
+
+#include "dm.h"
+#include "dm-path-selector.h"
+
+#include <linux/slab.h>
+
+/*-----------------------------------------------------------------
+ * Path-handling code, paths are held in lists
+ *---------------------------------------------------------------*/
+struct path_info {
+ struct list_head list;
+ struct path *path;
+ unsigned repeat_count;
+};
+
+static void free_paths(struct list_head *paths)
+{
+ struct path_info *pi, *next;
+
+ list_for_each_entry_safe(pi, next, paths, list) {
+ list_del(&pi->list);
+ kfree(pi);
+ }
+}
+
+/*-----------------------------------------------------------------
+ * Round-robin selector
+ *---------------------------------------------------------------*/
+
+#define RR_MIN_IO 1000
+
+struct selector {
+ struct list_head valid_paths;
+ struct list_head invalid_paths;
+};
+
+static struct selector *alloc_selector(void)
+{
+ struct selector *s = kmalloc(sizeof(*s), GFP_KERNEL);
+
+ if (s) {
+ INIT_LIST_HEAD(&s->valid_paths);
+ INIT_LIST_HEAD(&s->invalid_paths);
+ }
+
+ return s;
+}
+
+static int rr_create(struct path_selector *ps, unsigned argc, char **argv)
+{
+ struct selector *s;
+
+ s = alloc_selector();
+ if (!s)
+ return -ENOMEM;
+
+ ps->context = s;
+ return 0;
+}
+
+static void rr_destroy(struct path_selector *ps)
+{
+ struct selector *s = (struct selector *) ps->context;
+
+ free_paths(&s->valid_paths);
+ free_paths(&s->invalid_paths);
+ kfree(s);
+ ps->context = NULL;
+}
+
+static int rr_status(struct path_selector *ps, struct path *path,
+ status_type_t type, char *result, unsigned int maxlen)
+{
+ struct path_info *pi;
+ int sz = 0;
+
+ if (!path)
+ DMEMIT("0 ");
+ else {
+ switch(type) {
+ case STATUSTYPE_INFO:
+ break;
+ case STATUSTYPE_TABLE:
+ pi = path->pscontext;
+ DMEMIT("%u ", pi->repeat_count);
+ break;
+ }
+ }
+
+ return sz;
+}
+
+/*
+ * Called during initialisation to register each path with an
+ * optional repeat_count.
+ */
+static int rr_add_path(struct path_selector *ps, struct path *path,
+ int argc, char **argv, char **error)
+{
+ struct selector *s = (struct selector *) ps->context;
+ struct path_info *pi;
+ unsigned repeat_count = RR_MIN_IO;
+
+ if (argc > 1) {
+ *error = "round-robin ps: incorrect number of arguments";
+ return -EINVAL;
+ }
+
+ /* First path argument is number of I/Os before switching path */
+ if ((argc == 1) && (sscanf(argv[0], "%u", &repeat_count) != 1)) {
+ *error = "round-robin ps: invalid repeat count";
+ return -EINVAL;
+ }
+
+ /* allocate the path */
+ pi = kmalloc(sizeof(*pi), GFP_KERNEL);
+ if (!pi) {
+ *error = "round-robin ps: Error allocating path context";
+ return -ENOMEM;
+ }
+
+ pi->path = path;
+ pi->repeat_count = repeat_count;
+
+ path->pscontext = pi;
+
+ list_add(&pi->list, &s->valid_paths);
+
+ return 0;
+}
+
+static void rr_fail_path(struct path_selector *ps, struct path *p)
+{
+ struct selector *s = (struct selector *) ps->context;
+ struct path_info *pi = p->pscontext;
+
+ list_move(&pi->list, &s->invalid_paths);
+}
+
+static int rr_reinstate_path(struct path_selector *ps, struct path *p)
+{
+ struct selector *s = (struct selector *) ps->context;
+ struct path_info *pi = p->pscontext;
+
+ list_move(&pi->list, &s->valid_paths);
+
+ return 0;
+}
+
+static struct path *rr_select_path(struct path_selector *ps,
+ unsigned *repeat_count)
+{
+ struct selector *s = (struct selector *) ps->context;
+ struct path_info *pi = NULL;
+
+ if (!list_empty(&s->valid_paths)) {
+ pi = list_entry(s->valid_paths.next, struct path_info, list);
+ list_move_tail(&pi->list, &s->valid_paths);
+ *repeat_count = pi->repeat_count;
+ }
+
+ return pi ? pi->path : NULL;
+}
+
+static struct path_selector_type rr_ps = {
+ .name = "round-robin",
+ .module = THIS_MODULE,
+ .table_args = 1,
+ .info_args = 0,
+ .create = rr_create,
+ .destroy = rr_destroy,
+ .status = rr_status,
+ .add_path = rr_add_path,
+ .fail_path = rr_fail_path,
+ .reinstate_path = rr_reinstate_path,
+ .select_path = rr_select_path,
+};
+
+static int __init dm_rr_init(void)
+{
+ int r = dm_register_path_selector(&rr_ps);
+
+ if (r < 0)
+ DMERR("round-robin: register failed %d", r);
+
+ DMINFO("dm-round-robin version 1.0.0 loaded");
+
+ return r;
+}
+
+static void __exit dm_rr_exit(void)
+{
+ int r = dm_unregister_path_selector(&rr_ps);
+
+ if (r < 0)
+ DMERR("round-robin: unregister failed %d", r);
+}
+
+module_init(dm_rr_init);
+module_exit(dm_rr_exit);
+
+MODULE_DESCRIPTION(DM_NAME " round-robin multipath path selector");
+MODULE_AUTHOR("Sistina Software <dm-devel@redhat.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
index 36691ab1e0a9d..7e691ab9a748a 100644
--- a/drivers/md/dm-snap.c
+++ b/drivers/md/dm-snap.c
@@ -864,8 +864,6 @@ static int snapshot_status(struct dm_target *ti, status_type_t type,
char *result, unsigned int maxlen)
{
struct dm_snapshot *snap = (struct dm_snapshot *) ti->private;
- char cow[32];
- char org[32];
switch (type) {
case STATUSTYPE_INFO:
@@ -892,9 +890,8 @@ static int snapshot_status(struct dm_target *ti, status_type_t type,
* to make private copies if the output is to
* make sense.
*/
- format_dev_t(cow, snap->cow->bdev->bd_dev);
- format_dev_t(org, snap->origin->bdev->bd_dev);
- snprintf(result, maxlen, "%s %s %c " SECTOR_FORMAT, org, cow,
+ snprintf(result, maxlen, "%s %s %c " SECTOR_FORMAT,
+ snap->origin->name, snap->cow->name,
snap->type, snap->chunk_size);
break;
}
@@ -1082,7 +1079,6 @@ static int origin_status(struct dm_target *ti, status_type_t type, char *result,
unsigned int maxlen)
{
struct dm_dev *dev = (struct dm_dev *) ti->private;
- char buffer[32];
switch (type) {
case STATUSTYPE_INFO:
@@ -1090,8 +1086,7 @@ static int origin_status(struct dm_target *ti, status_type_t type, char *result,
break;
case STATUSTYPE_TABLE:
- format_dev_t(buffer, dev->bdev->bd_dev);
- snprintf(result, maxlen, "%s", buffer);
+ snprintf(result, maxlen, "%s", dev->name);
break;
}
diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c
index 16acecc11e9c7..ab89278a56bf4 100644
--- a/drivers/md/dm-stripe.c
+++ b/drivers/md/dm-stripe.c
@@ -188,7 +188,6 @@ static int stripe_status(struct dm_target *ti,
struct stripe_c *sc = (struct stripe_c *) ti->private;
unsigned int sz = 0;
unsigned int i;
- char buffer[32];
switch (type) {
case STATUSTYPE_INFO:
@@ -197,11 +196,9 @@ static int stripe_status(struct dm_target *ti,
case STATUSTYPE_TABLE:
DMEMIT("%d " SECTOR_FORMAT, sc->stripes, sc->chunk_mask + 1);
- for (i = 0; i < sc->stripes; i++) {
- format_dev_t(buffer, sc->stripe[i].dev->bdev->bd_dev);
- DMEMIT(" %s " SECTOR_FORMAT, buffer,
+ for (i = 0; i < sc->stripes; i++)
+ DMEMIT(" %s " SECTOR_FORMAT, sc->stripe[i].dev->name,
sc->stripe[i].physical_start);
- }
break;
}
return 0;
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index 3ef2ad4681b01..ee175d4906c4d 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -455,6 +455,8 @@ static int __table_get_device(struct dm_table *t, struct dm_target *ti,
return r;
}
+ format_dev_t(dd->name, dev);
+
atomic_set(&dd->count, 0);
list_add(&dd->list, &t->devices);
diff --git a/drivers/md/dm-zero.c b/drivers/md/dm-zero.c
index 725f2c812c16d..7febc2cac73d8 100644
--- a/drivers/md/dm-zero.c
+++ b/drivers/md/dm-zero.c
@@ -24,23 +24,6 @@ static int zero_ctr(struct dm_target *ti, unsigned int argc, char **argv)
}
/*
- * Fills the bio pages with zeros
- */
-static void zero_fill_bio(struct bio *bio)
-{
- unsigned long flags;
- struct bio_vec *bv;
- int i;
-
- bio_for_each_segment(bv, bio, i) {
- char *data = bvec_kmap_irq(bv, &flags);
- memset(data, 0, bv->bv_len);
- flush_dcache_page(bv->bv_page);
- bvec_kunmap_irq(data, &flags);
- }
-}
-
-/*
* Return zeros only on reads
*/
static int zero_map(struct dm_target *ti, struct bio *bio,
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 7f1af5231ef76..243ff6884e83f 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -43,6 +43,13 @@ struct target_io {
union map_info info;
};
+union map_info *dm_get_mapinfo(struct bio *bio)
+{
+ if (bio && bio->bi_private)
+ return &((struct target_io *)bio->bi_private)->info;
+ return NULL;
+}
+
/*
* Bits for the md->flags field.
*/
@@ -96,10 +103,16 @@ struct mapped_device {
static kmem_cache_t *_io_cache;
static kmem_cache_t *_tio_cache;
+static struct bio_set *dm_set;
+
static int __init local_init(void)
{
int r;
+ dm_set = bioset_create(16, 16, 4);
+ if (!dm_set)
+ return -ENOMEM;
+
/* allocate a slab for the dm_ios */
_io_cache = kmem_cache_create("dm_io",
sizeof(struct dm_io), 0, 0, NULL, NULL);
@@ -133,6 +146,8 @@ static void local_exit(void)
kmem_cache_destroy(_tio_cache);
kmem_cache_destroy(_io_cache);
+ bioset_free(dm_set);
+
if (unregister_blkdev(_major, _name) < 0)
DMERR("devfs_unregister_blkdev failed");
@@ -393,7 +408,7 @@ static struct bio *split_bvec(struct bio *bio, sector_t sector,
struct bio *clone;
struct bio_vec *bv = bio->bi_io_vec + idx;
- clone = bio_alloc(GFP_NOIO, 1);
+ clone = bio_alloc_bioset(GFP_NOIO, 1, dm_set);
*clone->bi_io_vec = *bv;
clone->bi_sector = sector;
@@ -1164,6 +1179,8 @@ static struct block_device_operations dm_blk_dops = {
.owner = THIS_MODULE
};
+EXPORT_SYMBOL(dm_get_mapinfo);
+
/*
* module hooks
*/
diff --git a/drivers/md/dm.h b/drivers/md/dm.h
index e6ef0b4d077d9..e38c3fc1a1db4 100644
--- a/drivers/md/dm.h
+++ b/drivers/md/dm.h
@@ -44,6 +44,7 @@ struct dm_dev {
atomic_t count;
int mode;
struct block_device *bdev;
+ char name[16];
};
struct dm_table;
@@ -189,5 +190,6 @@ int dm_stripe_init(void);
void dm_stripe_exit(void);
void *dm_vcalloc(unsigned long nmemb, unsigned long elem_size);
+union map_info *dm_get_mapinfo(struct bio *bio);
#endif
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 68669ce102689..04562add1920a 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -527,7 +527,7 @@ static int super_90_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version
rdev->preferred_minor = sb->md_minor;
rdev->data_offset = 0;
- if (sb->level == MULTIPATH)
+ if (sb->level == LEVEL_MULTIPATH)
rdev->desc_nr = -1;
else
rdev->desc_nr = sb->this_disk.number;
@@ -940,7 +940,7 @@ static void super_1_sync(mddev_t *mddev, mdk_rdev_t *rdev)
sb->max_dev = cpu_to_le32(max_dev);
for (i=0; i<max_dev;i++)
- sb->dev_roles[max_dev] = cpu_to_le16(0xfffe);
+ sb->dev_roles[i] = cpu_to_le16(0xfffe);
ITERATE_RDEV(mddev,rdev2,tmp) {
i = rdev2->desc_nr;
@@ -1435,9 +1435,8 @@ static int analyze_sbs(mddev_t * mddev)
- if ((mddev->recovery_cp != MaxSector) &&
- ((mddev->level == 1) ||
- ((mddev->level >= 4) && (mddev->level <= 6))))
+ if (mddev->recovery_cp != MaxSector &&
+ mddev->level >= 1)
printk(KERN_ERR "md: %s: raid array is not clean"
" -- starting background reconstruction\n",
mdname(mddev));
@@ -3545,18 +3544,18 @@ void md_check_recovery(mddev_t *mddev)
/* no recovery is running.
* remove any failed drives, then
- * add spares if possible
+ * add spares if possible.
+ * Spare are also removed and re-added, to allow
+ * the personality to fail the re-add.
*/
- ITERATE_RDEV(mddev,rdev,rtmp) {
+ ITERATE_RDEV(mddev,rdev,rtmp)
if (rdev->raid_disk >= 0 &&
- rdev->faulty &&
+ (rdev->faulty || ! rdev->in_sync) &&
atomic_read(&rdev->nr_pending)==0) {
if (mddev->pers->hot_remove_disk(mddev, rdev->raid_disk)==0)
rdev->raid_disk = -1;
}
- if (!rdev->faulty && rdev->raid_disk >= 0 && !rdev->in_sync)
- spares++;
- }
+
if (mddev->degraded) {
ITERATE_RDEV(mddev,rdev,rtmp)
if (rdev->raid_disk < 0
diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c
index 63f81fd3d25a8..c9b134cd1532f 100644
--- a/drivers/md/multipath.c
+++ b/drivers/md/multipath.c
@@ -38,7 +38,7 @@
static mdk_personality_t multipath_personality;
-static void *mp_pool_alloc(int gfp_flags, void *data)
+static void *mp_pool_alloc(unsigned int __nocast gfp_flags, void *data)
{
struct multipath_bh *mpb;
mpb = kmalloc(sizeof(*mpb), gfp_flags);
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 060c6a28c86c3..a389394b52f6f 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -34,7 +34,7 @@ static mdk_personality_t raid1_personality;
static void unplug_slaves(mddev_t *mddev);
-static void * r1bio_pool_alloc(int gfp_flags, void *data)
+static void * r1bio_pool_alloc(unsigned int __nocast gfp_flags, void *data)
{
struct pool_info *pi = data;
r1bio_t *r1_bio;
@@ -61,7 +61,7 @@ static void r1bio_pool_free(void *r1_bio, void *data)
#define RESYNC_PAGES ((RESYNC_BLOCK_SIZE + PAGE_SIZE-1) / PAGE_SIZE)
#define RESYNC_WINDOW (2048*1024)
-static void * r1buf_pool_alloc(int gfp_flags, void *data)
+static void * r1buf_pool_alloc(unsigned int __nocast gfp_flags, void *data)
{
struct pool_info *pi = data;
struct page *page;
@@ -338,6 +338,7 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio)
int new_disk = conf->last_used, disk = new_disk;
const int sectors = r1_bio->sectors;
sector_t new_distance, current_distance;
+ mdk_rdev_t *new_rdev, *rdev;
rcu_read_lock();
/*
@@ -345,13 +346,14 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio)
* device if no resync is going on, or below the resync window.
* We take the first readable disk when above the resync window.
*/
+ retry:
if (conf->mddev->recovery_cp < MaxSector &&
(this_sector + sectors >= conf->next_resync)) {
/* Choose the first operation device, for consistancy */
new_disk = 0;
- while (!conf->mirrors[new_disk].rdev ||
- !conf->mirrors[new_disk].rdev->in_sync) {
+ while ((new_rdev=conf->mirrors[new_disk].rdev) == NULL ||
+ !new_rdev->in_sync) {
new_disk++;
if (new_disk == conf->raid_disks) {
new_disk = -1;
@@ -363,8 +365,8 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio)
/* make sure the disk is operational */
- while (!conf->mirrors[new_disk].rdev ||
- !conf->mirrors[new_disk].rdev->in_sync) {
+ while ((new_rdev=conf->mirrors[new_disk].rdev) == NULL ||
+ !new_rdev->in_sync) {
if (new_disk <= 0)
new_disk = conf->raid_disks;
new_disk--;
@@ -393,18 +395,20 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio)
disk = conf->raid_disks;
disk--;
- if (!conf->mirrors[disk].rdev ||
- !conf->mirrors[disk].rdev->in_sync)
+ if ((rdev=conf->mirrors[disk].rdev) == NULL ||
+ !rdev->in_sync)
continue;
- if (!atomic_read(&conf->mirrors[disk].rdev->nr_pending)) {
+ if (!atomic_read(&rdev->nr_pending)) {
new_disk = disk;
+ new_rdev = rdev;
break;
}
new_distance = abs(this_sector - conf->mirrors[disk].head_position);
if (new_distance < current_distance) {
current_distance = new_distance;
new_disk = disk;
+ new_rdev = rdev;
}
} while (disk != conf->last_used);
@@ -414,7 +418,14 @@ rb_out:
if (new_disk >= 0) {
conf->next_seq_sect = this_sector + sectors;
conf->last_used = new_disk;
- atomic_inc(&conf->mirrors[new_disk].rdev->nr_pending);
+ atomic_inc(&new_rdev->nr_pending);
+ if (!new_rdev->in_sync) {
+ /* cannot risk returning a device that failed
+ * before we inc'ed nr_pending
+ */
+ atomic_dec(&new_rdev->nr_pending);
+ goto retry;
+ }
}
rcu_read_unlock();
@@ -512,6 +523,7 @@ static int make_request(request_queue_t *q, struct bio * bio)
r1bio_t *r1_bio;
struct bio *read_bio;
int i, disks;
+ mdk_rdev_t *rdev;
/*
* Register the new request and wait if the reconstruction
@@ -585,10 +597,14 @@ static int make_request(request_queue_t *q, struct bio * bio)
disks = conf->raid_disks;
rcu_read_lock();
for (i = 0; i < disks; i++) {
- if (conf->mirrors[i].rdev &&
- !conf->mirrors[i].rdev->faulty) {
- atomic_inc(&conf->mirrors[i].rdev->nr_pending);
- r1_bio->bios[i] = bio;
+ if ((rdev=conf->mirrors[i].rdev) != NULL &&
+ !rdev->faulty) {
+ atomic_inc(&rdev->nr_pending);
+ if (rdev->faulty) {
+ atomic_dec(&rdev->nr_pending);
+ r1_bio->bios[i] = NULL;
+ } else
+ r1_bio->bios[i] = bio;
} else
r1_bio->bios[i] = NULL;
}
@@ -1346,7 +1362,7 @@ static int raid1_reshape(mddev_t *mddev, int raid_disks)
if (conf->mirrors[d].rdev)
return -EBUSY;
- newpoolinfo = kmalloc(sizeof(newpoolinfo), GFP_KERNEL);
+ newpoolinfo = kmalloc(sizeof(*newpoolinfo), GFP_KERNEL);
if (!newpoolinfo)
return -ENOMEM;
newpoolinfo->mddev = mddev;
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 7c8ea87ded1fd..b100bfe4fdcac 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -47,7 +47,7 @@
static void unplug_slaves(mddev_t *mddev);
-static void * r10bio_pool_alloc(int gfp_flags, void *data)
+static void * r10bio_pool_alloc(unsigned int __nocast gfp_flags, void *data)
{
conf_t *conf = data;
r10bio_t *r10_bio;
@@ -81,7 +81,7 @@ static void r10bio_pool_free(void *r10_bio, void *data)
* one for write (we recover only one drive per r10buf)
*
*/
-static void * r10buf_pool_alloc(int gfp_flags, void *data)
+static void * r10buf_pool_alloc(unsigned int __nocast gfp_flags, void *data)
{
conf_t *conf = data;
struct page *page;
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 470e17e609975..52c3a81c4aa75 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -1493,6 +1493,15 @@ static int sync_request (mddev_t *mddev, sector_t sector_nr, int go_faster)
unplug_slaves(mddev);
return 0;
}
+ /* if there is 1 or more failed drives and we are trying
+ * to resync, then assert that we are finished, because there is
+ * nothing we can do.
+ */
+ if (mddev->degraded >= 1 && test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) {
+ int rv = (mddev->size << 1) - sector_nr;
+ md_done_sync(mddev, rv, 1);
+ return rv;
+ }
x = sector_nr;
chunk_offset = sector_div(x, sectors_per_chunk);
@@ -1884,6 +1893,10 @@ static int raid5_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
int disk;
struct disk_info *p;
+ if (mddev->degraded > 1)
+ /* no point adding a device */
+ return 0;
+
/*
* find the disk ...
*/
diff --git a/drivers/md/raid6altivec.uc b/drivers/md/raid6altivec.uc
index e21197a363c3c..1de8f030eee0e 100644
--- a/drivers/md/raid6altivec.uc
+++ b/drivers/md/raid6altivec.uc
@@ -108,7 +108,7 @@ int raid6_have_altivec(void);
int raid6_have_altivec(void)
{
/* This assumes either all CPUs have Altivec or none does */
- return cur_cpu_spec->cpu_features & CPU_FTR_ALTIVEC;
+ return cpu_has_feature(CPU_FTR_ALTIVEC);
}
#endif
diff --git a/drivers/md/raid6main.c b/drivers/md/raid6main.c
index ac9420f77b219..7e30ab29691a0 100644
--- a/drivers/md/raid6main.c
+++ b/drivers/md/raid6main.c
@@ -1652,6 +1652,15 @@ static int sync_request (mddev_t *mddev, sector_t sector_nr, int go_faster)
unplug_slaves(mddev);
return 0;
}
+ /* if there are 2 or more failed drives and we are trying
+ * to resync, then assert that we are finished, because there is
+ * nothing we can do.
+ */
+ if (mddev->degraded >= 2 && test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) {
+ int rv = (mddev->size << 1) - sector_nr;
+ md_done_sync(mddev, rv, 1);
+ return rv;
+ }
x = sector_nr;
chunk_offset = sector_div(x, sectors_per_chunk);
@@ -2050,6 +2059,9 @@ static int raid6_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
int disk;
struct disk_info *p;
+ if (mddev->degraded > 2)
+ /* no point adding a device */
+ return 0;
/*
* find the disk ...
*/
diff --git a/drivers/media/common/ir-common.c b/drivers/media/common/ir-common.c
index 5c0f01b3b6adc..8c842e2f59a2c 100644
--- a/drivers/media/common/ir-common.c
+++ b/drivers/media/common/ir-common.c
@@ -1,5 +1,5 @@
/*
- * $Id: ir-common.c,v 1.6 2004/12/10 12:33:39 kraxel Exp $
+ * $Id: ir-common.c,v 1.8 2005/02/22 12:28:40 kraxel Exp $
*
* some common structs and functions to handle infrared remotes via
* input layer ...
@@ -23,7 +23,6 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
-
#include <media/ir-common.h>
/* -------------------------------------------------------------------------- */
@@ -45,6 +44,7 @@ module_param(debug, int, 0644);
/* generic RC5 keytable */
/* see http://users.pandora.be/nenya/electronics/rc5/codes00.htm */
+/* used by old (black) Hauppauge remotes */
IR_KEYTAB_TYPE ir_codes_rc5_tv[IR_KEYTAB_SIZE] = {
[ 0x00 ] = KEY_KP0, // 0
[ 0x01 ] = KEY_KP1, // 1
@@ -117,12 +117,102 @@ IR_KEYTAB_TYPE ir_codes_rc5_tv[IR_KEYTAB_SIZE] = {
};
EXPORT_SYMBOL_GPL(ir_codes_rc5_tv);
+/* Table for Leadtek Winfast Remote Controls - used by both bttv and cx88 */
+IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE] = {
+ [ 5 ] = KEY_KP1,
+ [ 6 ] = KEY_KP2,
+ [ 7 ] = KEY_KP3,
+ [ 9 ] = KEY_KP4,
+ [ 10 ] = KEY_KP5,
+ [ 11 ] = KEY_KP6,
+ [ 13 ] = KEY_KP7,
+ [ 14 ] = KEY_KP8,
+ [ 15 ] = KEY_KP9,
+ [ 18 ] = KEY_KP0,
+
+ [ 0 ] = KEY_POWER,
+// [ 27 ] = MTS button
+ [ 2 ] = KEY_TUNER, // TV/FM
+ [ 30 ] = KEY_VIDEO,
+// [ 22 ] = display button
+ [ 4 ] = KEY_VOLUMEUP,
+ [ 8 ] = KEY_VOLUMEDOWN,
+ [ 12 ] = KEY_CHANNELUP,
+ [ 16 ] = KEY_CHANNELDOWN,
+ [ 3 ] = KEY_ZOOM, // fullscreen
+ [ 31 ] = KEY_SUBTITLE, // closed caption/teletext
+ [ 32 ] = KEY_SLEEP,
+// [ 41 ] = boss key
+ [ 20 ] = KEY_MUTE,
+ [ 43 ] = KEY_RED,
+ [ 44 ] = KEY_GREEN,
+ [ 45 ] = KEY_YELLOW,
+ [ 46 ] = KEY_BLUE,
+ [ 24 ] = KEY_KPPLUS, //fine tune +
+ [ 25 ] = KEY_KPMINUS, //fine tune -
+// [ 42 ] = picture in picture
+ [ 33 ] = KEY_KPDOT,
+ [ 19 ] = KEY_KPENTER,
+// [ 17 ] = recall
+ [ 34 ] = KEY_BACK,
+ [ 35 ] = KEY_PLAYPAUSE,
+ [ 36 ] = KEY_NEXT,
+// [ 37 ] = time shifting
+ [ 38 ] = KEY_STOP,
+ [ 39 ] = KEY_RECORD
+// [ 40 ] = snapshot
+};
+EXPORT_SYMBOL_GPL(ir_codes_winfast);
+
/* empty keytable, can be used as placeholder for not-yet created keytables */
IR_KEYTAB_TYPE ir_codes_empty[IR_KEYTAB_SIZE] = {
[ 42 ] = KEY_COFFEE,
};
EXPORT_SYMBOL_GPL(ir_codes_empty);
+/* Hauppauge: the newer, gray remotes (seems there are multiple
+ * slightly different versions), shipped with cx88+ivtv cards.
+ * almost rc5 coding, but some non-standard keys */
+IR_KEYTAB_TYPE ir_codes_hauppauge_new[IR_KEYTAB_SIZE] = {
+ [ 0x00 ] = KEY_KP0, // 0
+ [ 0x01 ] = KEY_KP1, // 1
+ [ 0x02 ] = KEY_KP2, // 2
+ [ 0x03 ] = KEY_KP3, // 3
+ [ 0x04 ] = KEY_KP4, // 4
+ [ 0x05 ] = KEY_KP5, // 5
+ [ 0x06 ] = KEY_KP6, // 6
+ [ 0x07 ] = KEY_KP7, // 7
+ [ 0x08 ] = KEY_KP8, // 8
+ [ 0x09 ] = KEY_KP9, // 9
+ [ 0x0b ] = KEY_RED, // red button
+ [ 0x0c ] = KEY_OPTION, // black key without text
+ [ 0x0d ] = KEY_MENU, // menu
+ [ 0x0f ] = KEY_MUTE, // mute
+ [ 0x10 ] = KEY_VOLUMEUP, // volume +
+ [ 0x11 ] = KEY_VOLUMEDOWN, // volume -
+ [ 0x1e ] = KEY_NEXT, // skip >|
+ [ 0x1f ] = KEY_EXIT, // back/exit
+ [ 0x20 ] = KEY_CHANNELUP, // channel / program +
+ [ 0x21 ] = KEY_CHANNELDOWN, // channel / program -
+ [ 0x22 ] = KEY_CHANNEL, // source (old black remote)
+ [ 0x24 ] = KEY_PREVIOUS, // replay |<
+ [ 0x25 ] = KEY_ENTER, // OK
+ [ 0x26 ] = KEY_SLEEP, // minimize (old black remote)
+ [ 0x29 ] = KEY_BLUE, // blue key
+ [ 0x2e ] = KEY_GREEN, // green button
+ [ 0x30 ] = KEY_PAUSE, // pause
+ [ 0x32 ] = KEY_REWIND, // backward <<
+ [ 0x34 ] = KEY_FASTFORWARD, // forward >>
+ [ 0x35 ] = KEY_PLAY, // play
+ [ 0x36 ] = KEY_STOP, // stop
+ [ 0x37 ] = KEY_RECORD, // recording
+ [ 0x38 ] = KEY_YELLOW, // yellow key
+ [ 0x3b ] = KEY_SELECT, // top right button
+ [ 0x3c ] = KEY_ZOOM, // full
+ [ 0x3d ] = KEY_POWER, // system power (green button)
+};
+EXPORT_SYMBOL(ir_codes_hauppauge_new);
+
/* -------------------------------------------------------------------------- */
static void ir_input_key_event(struct input_dev *dev, struct ir_input_state *ir)
@@ -192,6 +282,8 @@ void ir_input_keydown(struct input_dev *dev, struct ir_input_state *ir,
#endif
}
+/* -------------------------------------------------------------------------- */
+
u32 ir_extract_bits(u32 data, u32 mask)
{
int mbit, vbit;
@@ -209,10 +301,78 @@ u32 ir_extract_bits(u32 data, u32 mask)
return value;
}
+static int inline getbit(u32 *samples, int bit)
+{
+ return (samples[bit/32] & (1 << (31-(bit%32)))) ? 1 : 0;
+}
+
+/* sump raw samples for visual debugging ;) */
+int ir_dump_samples(u32 *samples, int count)
+{
+ int i, bit, start;
+
+ printk(KERN_DEBUG "ir samples: ");
+ start = 0;
+ for (i = 0; i < count * 32; i++) {
+ bit = getbit(samples,i);
+ if (bit)
+ start = 1;
+ if (0 == start)
+ continue;
+ printk("%s", bit ? "#" : "_");
+ }
+ printk("\n");
+ return 0;
+}
+
+/* decode raw samples, biphase coding, used by rc5 for example */
+int ir_decode_biphase(u32 *samples, int count, int low, int high)
+{
+ int i,last,bit,len,flips;
+ u32 value;
+
+ /* find start bit (1) */
+ for (i = 0; i < 32; i++) {
+ bit = getbit(samples,i);
+ if (bit)
+ break;
+ }
+
+ /* go decoding */
+ len = 0;
+ flips = 0;
+ value = 1;
+ for (; i < count * 32; i++) {
+ if (len > high)
+ break;
+ if (flips > 1)
+ break;
+ last = bit;
+ bit = getbit(samples,i);
+ if (last == bit) {
+ len++;
+ continue;
+ }
+ if (len < low) {
+ len++;
+ flips++;
+ continue;
+ }
+ value <<= 1;
+ value |= bit;
+ flips = 0;
+ len = 1;
+ }
+ return value;
+}
+
EXPORT_SYMBOL_GPL(ir_input_init);
EXPORT_SYMBOL_GPL(ir_input_nokey);
EXPORT_SYMBOL_GPL(ir_input_keydown);
+
EXPORT_SYMBOL_GPL(ir_extract_bits);
+EXPORT_SYMBOL_GPL(ir_dump_samples);
+EXPORT_SYMBOL_GPL(ir_decode_biphase);
/*
* Local variables:
diff --git a/drivers/media/common/saa7146_core.c b/drivers/media/common/saa7146_core.c
index 5df06f2f8a50e..9f6c19ac12853 100644
--- a/drivers/media/common/saa7146_core.c
+++ b/drivers/media/common/saa7146_core.c
@@ -20,11 +20,9 @@
#include <media/saa7146.h>
-/* global variables */
-struct list_head saa7146_devices;
-struct semaphore saa7146_devices_lock;
+LIST_HEAD(saa7146_devices);
+DECLARE_MUTEX(saa7146_devices_lock);
-static int initialized = 0;
static int saa7146_num = 0;
unsigned int saa7146_debug = 0;
@@ -48,21 +46,15 @@ static void dump_registers(struct saa7146_dev* dev)
* gpio and debi helper functions
****************************************************************************/
-/* write "data" to the gpio-pin "pin" -- unused */
-void saa7146_set_gpio(struct saa7146_dev *dev, u8 pin, u8 data)
+void saa7146_setgpio(struct saa7146_dev *dev, int port, u32 data)
{
u32 value = 0;
- /* sanity check */
- if(pin > 3)
- return;
-
- /* read old register contents */
- value = saa7146_read(dev, GPIO_CTRL );
-
- value &= ~(0xff << (8*pin));
- value |= (data << (8*pin));
+ BUG_ON(port > 3);
+ value = saa7146_read(dev, GPIO_CTRL);
+ value &= ~(0xff << (8*port));
+ value |= (data << (8*port));
saa7146_write(dev, GPIO_CTRL, value);
}
@@ -105,7 +97,7 @@ int saa7146_wait_for_debi_done(struct saa7146_dev *dev, int nobusyloop)
* general helper functions
****************************************************************************/
-/* this is videobuf_vmalloc_to_sg() from video-buf.c
+/* this is videobuf_vmalloc_to_sg() from video-buf.c
make sure virt has been allocated with vmalloc_32(), otherwise the BUG()
may be triggered on highmem machines */
static struct scatterlist* vmalloc_to_sg(unsigned char *virt, int nr_pages)
@@ -128,7 +120,7 @@ static struct scatterlist* vmalloc_to_sg(unsigned char *virt, int nr_pages)
sglist[i].length = PAGE_SIZE;
}
return sglist;
-
+
err:
kfree(sglist);
return NULL;
@@ -158,7 +150,7 @@ char *saa7146_vmalloc_build_pgtable(struct pci_dev *pci, long length, struct saa
vfree(mem);
return NULL;
}
-
+
slen = pci_map_sg(pci,pt->slist,pages,PCI_DMA_FROMDEVICE);
if (0 != saa7146_pgtable_build_single(pci, pt, pt->slist, slen)) {
return NULL;
@@ -198,13 +190,13 @@ int saa7146_pgtable_alloc(struct pci_dev *pci, struct saa7146_pgtable *pt)
int saa7146_pgtable_build_single(struct pci_dev *pci, struct saa7146_pgtable *pt,
struct scatterlist *list, int sglen )
{
- u32 *ptr, fill;
+ u32 *ptr, fill;
int nr_pages = 0;
- int i,p;
+ int i,p;
- BUG_ON( 0 == sglen);
+ BUG_ON(0 == sglen);
BUG_ON(list->offset > PAGE_SIZE);
-
+
/* if we have a user buffer, the first page may not be
aligned to a page boundary. */
pt->offset = list->offset;
@@ -238,19 +230,6 @@ int saa7146_pgtable_build_single(struct pci_dev *pci, struct saa7146_pgtable *pt
}
/********************************************************************************/
-/* gpio functions */
-
-void saa7146_setgpio(struct saa7146_dev *dev, int port, u32 data)
-{
- u32 val = 0;
-
- val=saa7146_read(dev,GPIO_CTRL);
- val&=~(0xff << (8*(port)));
- val|=(data)<<(8*(port));
- saa7146_write(dev, GPIO_CTRL, val);
-}
-
-/********************************************************************************/
/* interrupt handler */
static irqreturn_t interrupt_hw(int irq, void *dev_id, struct pt_regs *regs)
{
@@ -322,10 +301,10 @@ static irqreturn_t interrupt_hw(int irq, void *dev_id, struct pt_regs *regs)
static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent)
{
struct saa7146_pci_extension_data *pci_ext = (struct saa7146_pci_extension_data *)ent->driver_data;
- struct saa7146_extension* ext = pci_ext->ext;
+ struct saa7146_extension *ext = pci_ext->ext;
struct saa7146_dev *dev;
int err = -ENOMEM;
-
+
dev = kmalloc(sizeof(struct saa7146_dev), GFP_KERNEL);
if (!dev) {
ERR(("out of memory.\n"));
@@ -394,7 +373,7 @@ static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent
goto err_unmap;
}
- err = -ENOMEM;
+ err = -ENOMEM;
/* get memory for various stuff */
dev->d_rps0.cpu_addr = pci_alloc_consistent(pci, SAA7146_RPS_MEM,
@@ -423,7 +402,7 @@ static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent
INFO(("found saa7146 @ mem %p (revision %d, irq %d) (0x%04x,0x%04x).\n", dev->mem, dev->revision, pci->irq, pci->subsystem_vendor, pci->subsystem_device));
dev->ext = ext;
- pci_set_drvdata(pci,dev);
+ pci_set_drvdata(pci, dev);
init_MUTEX(&dev->lock);
spin_lock_init(&dev->int_slock);
@@ -435,11 +414,11 @@ static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent
init_waitqueue_head(&dev->i2c_wq);
/* set some sane pci arbitrition values */
- saa7146_write(dev, PCI_BT_V1, 0x1c00101f);
+ saa7146_write(dev, PCI_BT_V1, 0x1c00101f);
/* TODO: use the status code of the callback */
- err = -ENODEV;
+ err = -ENODEV;
if (ext->probe && ext->probe(dev)) {
DEB_D(("ext->probe() failed for %p. skipping device.\n",dev));
@@ -460,7 +439,7 @@ out:
return err;
err_unprobe:
- pci_set_drvdata(pci,NULL);
+ pci_set_drvdata(pci, NULL);
err_free_i2c:
pci_free_consistent(pci, SAA7146_RPS_MEM, dev->d_i2c.cpu_addr,
dev->d_i2c.dma_handle);
@@ -527,12 +506,6 @@ int saa7146_register_extension(struct saa7146_extension* ext)
{
DEB_EE(("ext:%p\n",ext));
- if( 0 == initialized ) {
- INIT_LIST_HEAD(&saa7146_devices);
- init_MUTEX(&saa7146_devices_lock);
- initialized = 1;
- }
-
ext->driver.name = ext->name;
ext->driver.id_table = ext->pci_tbl;
ext->driver.probe = saa7146_init_one;
@@ -550,23 +523,6 @@ int saa7146_unregister_extension(struct saa7146_extension* ext)
return 0;
}
-static int __init saa7146_init_module(void)
-{
- if( 0 == initialized ) {
- INIT_LIST_HEAD(&saa7146_devices);
- init_MUTEX(&saa7146_devices_lock);
- initialized = 1;
- }
- return 0;
-}
-
-static void __exit saa7146_cleanup_module(void)
-{
-}
-
-module_init(saa7146_init_module);
-module_exit(saa7146_cleanup_module);
-
EXPORT_SYMBOL_GPL(saa7146_register_extension);
EXPORT_SYMBOL_GPL(saa7146_unregister_extension);
diff --git a/drivers/media/common/saa7146_fops.c b/drivers/media/common/saa7146_fops.c
index 817c4a6a66b63..cb826c9adfe7e 100644
--- a/drivers/media/common/saa7146_fops.c
+++ b/drivers/media/common/saa7146_fops.c
@@ -444,7 +444,7 @@ int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv)
memset(vv, 0x0, sizeof(*vv));
DEB_EE(("dev:%p\n",dev));
-
+
/* set default values for video parts of the saa7146 */
saa7146_write(dev, BCS_CTRL, 0x80400040);
@@ -497,7 +497,7 @@ int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev,
struct video_device *vfd;
DEB_EE(("dev:%p, name:'%s', type:%d\n",dev,name,type));
-
+
// released by vfd->release
vfd = video_device_alloc();
if (vfd == NULL)
diff --git a/drivers/media/common/saa7146_hlp.c b/drivers/media/common/saa7146_hlp.c
index 7bf6316b3480b..ec52dff8cb695 100644
--- a/drivers/media/common/saa7146_hlp.c
+++ b/drivers/media/common/saa7146_hlp.c
@@ -4,7 +4,7 @@
static void calculate_output_format_register(struct saa7146_dev* saa, u32 palette, u32* clip_format)
{
/* clear out the necessary bits */
- *clip_format &= 0x0000ffff;
+ *clip_format &= 0x0000ffff;
/* set these bits new */
*clip_format |= (( ((palette&0xf00)>>8) << 30) | ((palette&0x00f) << 24) | (((palette&0x0f0)>>4) << 16));
}
@@ -21,7 +21,7 @@ static void calculate_hxo_and_hyo(struct saa7146_vv *vv, u32* hps_h_scale, u32*
hyo = vv->standard->v_offset;
hxo = vv->standard->h_offset;
-
+
*hps_h_scale &= ~(MASK_B0 | 0xf00);
*hps_h_scale |= (hxo << 0);
@@ -40,7 +40,7 @@ static void calculate_hxo_and_hyo(struct saa7146_vv *vv, u32* hps_h_scale, u32*
static struct {
u16 hps_coeff;
u16 weight_sum;
-} hps_h_coeff_tab [] = {
+} hps_h_coeff_tab [] = {
{0x00, 2}, {0x02, 4}, {0x00, 4}, {0x06, 8}, {0x02, 8},
{0x08, 8}, {0x00, 8}, {0x1E, 16}, {0x0E, 8}, {0x26, 8},
{0x06, 8}, {0x42, 8}, {0x02, 8}, {0x80, 8}, {0x00, 8},
@@ -65,11 +65,11 @@ static int calculate_h_scale_registers(struct saa7146_dev *dev,
u32* hps_ctrl, u32* hps_v_gain, u32* hps_h_prescale, u32* hps_h_scale)
{
/* horizontal prescaler */
- u32 dcgx = 0, xpsc = 0, xacm = 0, cxy = 0, cxuv = 0;
+ u32 dcgx = 0, xpsc = 0, xacm = 0, cxy = 0, cxuv = 0;
/* horizontal scaler */
- u32 xim = 0, xp = 0, xsci =0;
+ u32 xim = 0, xp = 0, xsci =0;
/* vertical scale & gain */
- u32 pfuv = 0;
+ u32 pfuv = 0;
/* helper variables */
u32 h_atten = 0, i = 0;
@@ -77,29 +77,29 @@ static int calculate_h_scale_registers(struct saa7146_dev *dev,
if ( 0 == out_x ) {
return -EINVAL;
}
-
+
/* mask out vanity-bit */
*hps_ctrl &= ~MASK_29;
-
+
/* calculate prescale-(xspc)-value: [n .. 1/2) : 1
- [1/2 .. 1/3) : 2
- [1/3 .. 1/4) : 3
- ... */
+ [1/2 .. 1/3) : 2
+ [1/3 .. 1/4) : 3
+ ... */
if (in_x > out_x) {
xpsc = in_x / out_x;
}
else {
/* zooming */
- xpsc = 1;
+ xpsc = 1;
}
-
+
/* if flip_lr-bit is set, number of pixels after
horizontal prescaling must be < 384 */
if ( 0 != flip_lr ) {
-
+
/* set vanity bit */
*hps_ctrl |= MASK_29;
-
+
while (in_x / xpsc >= 384 )
xpsc++;
}
@@ -109,35 +109,35 @@ static int calculate_h_scale_registers(struct saa7146_dev *dev,
while ( in_x / xpsc >= 768 )
xpsc++;
}
-
+
/* maximum prescale is 64 (p.69) */
if ( xpsc > 64 )
xpsc = 64;
/* keep xacm clear*/
xacm = 0;
-
+
/* set horizontal filter parameters (CXY = CXUV) */
cxy = hps_h_coeff_tab[( (xpsc - 1) < 63 ? (xpsc - 1) : 63 )].hps_coeff;
cxuv = cxy;
-
+
/* calculate and set horizontal fine scale (xsci) */
-
+
/* bypass the horizontal scaler ? */
if ( (in_x == out_x) && ( 1 == xpsc ) )
xsci = 0x400;
- else
+ else
xsci = ( (1024 * in_x) / (out_x * xpsc) ) + xpsc;
- /* set start phase for horizontal fine scale (xp) to 0 */
+ /* set start phase for horizontal fine scale (xp) to 0 */
xp = 0;
-
+
/* set xim, if we bypass the horizontal scaler */
if ( 0x400 == xsci )
xim = 1;
else
xim = 0;
-
+
/* if the prescaler is bypassed, enable horizontal
accumulation mode (xacm) and clear dcgx */
if( 1 == xpsc ) {
@@ -148,12 +148,12 @@ static int calculate_h_scale_registers(struct saa7146_dev *dev,
/* get best match in the table of attenuations
for horizontal scaling */
h_atten = hps_h_coeff_tab[( (xpsc - 1) < 63 ? (xpsc - 1) : 63 )].weight_sum;
-
+
for (i = 0; h_attenuation[i] != 0; i++) {
if (h_attenuation[i] >= h_atten)
break;
}
-
+
dcgx = i;
}
@@ -171,11 +171,11 @@ static int calculate_h_scale_registers(struct saa7146_dev *dev,
else
pfuv = 0x33;
-
+
*hps_v_gain &= MASK_W0|MASK_B2;
- *hps_v_gain |= (pfuv << 24);
+ *hps_v_gain |= (pfuv << 24);
- *hps_h_scale &= ~(MASK_W1 | 0xf000);
+ *hps_h_scale &= ~(MASK_W1 | 0xf000);
*hps_h_scale |= (xim << 31) | (xp << 24) | (xsci << 12);
*hps_h_prescale |= (dcgx << 27) | ((xpsc-1) << 18) | (xacm << 17) | (cxy << 8) | (cxuv << 0);
@@ -186,7 +186,7 @@ static int calculate_h_scale_registers(struct saa7146_dev *dev,
static struct {
u16 hps_coeff;
u16 weight_sum;
-} hps_v_coeff_tab [] = {
+} hps_v_coeff_tab [] = {
{0x0100, 2}, {0x0102, 4}, {0x0300, 4}, {0x0106, 8}, {0x0502, 8},
{0x0708, 8}, {0x0F00, 8}, {0x011E, 16}, {0x110E, 16}, {0x1926, 16},
{0x3906, 16}, {0x3D42, 16}, {0x7D02, 16}, {0x7F80, 16}, {0xFF00, 16},
@@ -210,14 +210,14 @@ static int calculate_v_scale_registers(struct saa7146_dev *dev, enum v4l2_field
int in_y, int out_y, u32* hps_v_scale, u32* hps_v_gain)
{
int lpi = 0;
-
+
/* vertical scaling */
u32 yacm = 0, ysci = 0, yacl = 0, ypo = 0, ype = 0;
/* vertical scale & gain */
u32 dcgy = 0, cya_cyb = 0;
-
+
/* helper variables */
- u32 v_atten = 0, i = 0;
+ u32 v_atten = 0, i = 0;
/* error, if vertical zooming */
if ( in_y < out_y ) {
@@ -245,7 +245,7 @@ static int calculate_v_scale_registers(struct saa7146_dev *dev, enum v4l2_field
yacm = 0;
yacl = 0;
cya_cyb = 0x00ff;
-
+
/* calculate scaling increment */
if ( in_y > out_y )
ysci = ((1024 * in_y) / (out_y + 1)) - 1024;
@@ -257,9 +257,9 @@ static int calculate_v_scale_registers(struct saa7146_dev *dev, enum v4l2_field
/* calculate ype and ypo */
ype = ysci / 16;
ypo = ype + (ysci / 64);
-
+
} else {
- yacm = 1;
+ yacm = 1;
/* calculate scaling increment */
ysci = (((10 * 1024 * (in_y - out_y - 1)) / in_y) + 9) / 10;
@@ -269,7 +269,7 @@ static int calculate_v_scale_registers(struct saa7146_dev *dev, enum v4l2_field
/* the sequence length interval (yacl) has to be set according
to the prescale value, e.g. [n .. 1/2) : 0
- [1/2 .. 1/3) : 1
+ [1/2 .. 1/3) : 1
[1/3 .. 1/4) : 2
... */
if ( ysci < 512) {
@@ -278,7 +278,7 @@ static int calculate_v_scale_registers(struct saa7146_dev *dev, enum v4l2_field
yacl = ( ysci / (1024 - ysci) );
}
- /* get filter coefficients for cya, cyb from table hps_v_coeff_tab */
+ /* get filter coefficients for cya, cyb from table hps_v_coeff_tab */
cya_cyb = hps_v_coeff_tab[ (yacl < 63 ? yacl : 63 ) ].hps_coeff;
/* get best match in the table of attenuations for vertical scaling */
@@ -288,7 +288,7 @@ static int calculate_v_scale_registers(struct saa7146_dev *dev, enum v4l2_field
if (v_attenuation[i] >= v_atten)
break;
}
-
+
dcgy = i;
}
@@ -306,12 +306,12 @@ static int sort_and_eliminate(u32* values, int* count)
{
int low = 0, high = 0, top = 0, temp = 0;
int cur = 0, next = 0;
-
+
/* sanity checks */
if( (0 > *count) || (NULL == values) ) {
return -EINVAL;
}
-
+
/* bubble sort the first ´count´ items of the array ´values´ */
for( top = *count; top > 0; top--) {
for( low = 0, high = 1; high < top; low++, high++) {
@@ -328,9 +328,9 @@ static int sort_and_eliminate(u32* values, int* count)
if( values[cur] != values[next])
values[++cur] = values[next];
}
-
+
*count = cur + 1;
-
+
return 0;
}
@@ -343,8 +343,8 @@ static void calculate_clipping_registers_rect(struct saa7146_dev *dev, struct sa
int width = fh->ov.win.w.width;
int height = fh->ov.win.w.height;
int clipcount = fh->ov.nclips;
-
- u32 line_list[32];
+
+ u32 line_list[32];
u32 pixel_list[32];
int numdwords = 0;
@@ -361,12 +361,12 @@ static void calculate_clipping_registers_rect(struct saa7146_dev *dev, struct sa
/* fill the line and pixel-lists */
for(i = 0; i < clipcount; i++) {
int l = 0, r = 0, t = 0, b = 0;
-
+
x[i] = fh->ov.clips[i].c.left;
y[i] = fh->ov.clips[i].c.top;
w[i] = fh->ov.clips[i].c.width;
h[i] = fh->ov.clips[i].c.height;
-
+
if( w[i] < 0) {
x[i] += w[i]; w[i] = -w[i];
}
@@ -378,7 +378,7 @@ static void calculate_clipping_registers_rect(struct saa7146_dev *dev, struct sa
}
if( y[i] < 0) {
h[i] += y[i]; y[i] = 0;
- }
+ }
if( 0 != vv->vflip ) {
y[i] = height - y[i] - h[i];
}
@@ -387,7 +387,7 @@ static void calculate_clipping_registers_rect(struct saa7146_dev *dev, struct sa
r = x[i]+w[i];
t = y[i];
b = y[i]+h[i];
-
+
/* insert left/right coordinates */
pixel_list[ 2*i ] = min_t(int, l, width);
pixel_list[(2*i)+1] = min_t(int, r, width);
@@ -423,7 +423,7 @@ static void calculate_clipping_registers_rect(struct saa7146_dev *dev, struct sa
x[j] = 0;
if( pixel_list[i] < (x[j] + w[j])) {
-
+
if ( pixel_list[i] >= x[j] ) {
clipping[2*i] |= cpu_to_le32(1 << j);
}
@@ -445,8 +445,8 @@ static void calculate_clipping_registers_rect(struct saa7146_dev *dev, struct sa
/* adjust arbitration control register */
*arbtr_ctrl &= 0xffff00ff;
- *arbtr_ctrl |= 0x00001c00;
-
+ *arbtr_ctrl |= 0x00001c00;
+
vdma2->base_even = vv->d_clipping.dma_handle;
vdma2->base_odd = vv->d_clipping.dma_handle;
vdma2->prot_addr = vv->d_clipping.dma_handle+((sizeof(u32))*(numdwords));
@@ -473,9 +473,9 @@ static void saa7146_disable_clipping(struct saa7146_dev *dev)
/* upload clipping-registers*/
saa7146_write(dev, CLIP_FORMAT_CTRL,clip_format);
- saa7146_write(dev, MC2, (MASK_05 | MASK_21));
-
- /* disable video dma2 */
+ saa7146_write(dev, MC2, (MASK_05 | MASK_21));
+
+ /* disable video dma2 */
saa7146_write(dev, MC1, MASK_21);
}
@@ -509,10 +509,10 @@ static void saa7146_set_clipping_rect(struct saa7146_fh *fh)
saa7146_write(dev, BASE_PAGE2, vdma2.base_page);
saa7146_write(dev, PITCH2, vdma2.pitch);
saa7146_write(dev, NUM_LINE_BYTE2, vdma2.num_line_byte);
-
+
/* prepare the rest */
saa7146_write(dev, CLIP_FORMAT_CTRL,clip_format);
- saa7146_write(dev, PCI_BT_V1, arbtr_ctrl);
+ saa7146_write(dev, PCI_BT_V1, arbtr_ctrl);
/* upload clip_control-register, clipping-registers, enable video dma2 */
saa7146_write(dev, MC2, (MASK_05 | MASK_21 | MASK_03 | MASK_19));
@@ -530,11 +530,11 @@ static void saa7146_set_window(struct saa7146_dev *dev, int width, int height, e
/* set vertical scale */
hps_v_scale = 0; /* all bits get set by the function-call */
- hps_v_gain = 0; /* fixme: saa7146_read(dev, HPS_V_GAIN);*/
+ hps_v_gain = 0; /* fixme: saa7146_read(dev, HPS_V_GAIN);*/
calculate_v_scale_registers(dev, field, vv->standard->v_field*2, height, &hps_v_scale, &hps_v_gain);
/* set horizontal scale */
- hps_ctrl = 0;
+ hps_ctrl = 0;
hps_h_prescale = 0; /* all bits get set in the function */
hps_h_scale = 0;
calculate_h_scale_registers(dev, vv->standard->h_pixels, width, vv->hflip, &hps_ctrl, &hps_v_gain, &hps_h_prescale, &hps_h_scale);
@@ -542,43 +542,43 @@ static void saa7146_set_window(struct saa7146_dev *dev, int width, int height, e
/* set hyo and hxo */
calculate_hxo_and_hyo(vv, &hps_h_scale, &hps_ctrl);
calculate_hps_source_and_sync(dev, source, sync, &hps_ctrl);
-
+
/* write out new register contents */
saa7146_write(dev, HPS_V_SCALE, hps_v_scale);
saa7146_write(dev, HPS_V_GAIN, hps_v_gain);
saa7146_write(dev, HPS_CTRL, hps_ctrl);
saa7146_write(dev, HPS_H_PRESCALE,hps_h_prescale);
saa7146_write(dev, HPS_H_SCALE, hps_h_scale);
-
+
/* upload shadow-ram registers */
- saa7146_write(dev, MC2, (MASK_05 | MASK_06 | MASK_21 | MASK_22) );
+ saa7146_write(dev, MC2, (MASK_05 | MASK_06 | MASK_21 | MASK_22) );
}
/* calculate the new memory offsets for a desired position */
static void saa7146_set_position(struct saa7146_dev *dev, int w_x, int w_y, int w_height, enum v4l2_field field, u32 pixelformat)
-{
+{
struct saa7146_vv *vv = dev->vv_data;
struct saa7146_format *sfmt = format_by_fourcc(dev, pixelformat);
int b_depth = vv->ov_fmt->depth;
int b_bpl = vv->ov_fb.fmt.bytesperline;
u32 base = (u32)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 = (u32)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 = (u32)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));
}
-
+
if (V4L2_FIELD_HAS_BOTH(field)) {
} else if (field == V4L2_FIELD_ALTERNATE) {
/* fixme */
@@ -596,7 +596,7 @@ static void saa7146_set_position(struct saa7146_dev *dev, int w_x, int w_y, int
if ( 0 != vv->vflip ) {
vdma1.pitch *= -1;
}
-
+
vdma1.base_page = sfmt->swap;
vdma1.num_line_byte = (vv->standard->v_field<<16)+vv->standard->h_pixels;
@@ -606,13 +606,13 @@ static void saa7146_set_position(struct saa7146_dev *dev, int w_x, int w_y, int
static void saa7146_set_output_format(struct saa7146_dev *dev, unsigned long palette)
{
u32 clip_format = saa7146_read(dev, CLIP_FORMAT_CTRL);
-
+
/* call helper function */
calculate_output_format_register(dev,palette,&clip_format);
/* update the hps registers */
saa7146_write(dev, CLIP_FORMAT_CTRL, clip_format);
- saa7146_write(dev, MC2, (MASK_05 | MASK_21));
+ saa7146_write(dev, MC2, (MASK_05 | MASK_21));
}
/* select input-source */
@@ -630,10 +630,10 @@ void saa7146_set_hps_source_and_sync(struct saa7146_dev *dev, int source, int sy
/* write back & upload register */
saa7146_write(dev, HPS_CTRL, hps_ctrl);
saa7146_write(dev, MC2, (MASK_05 | MASK_21));
-
+
vv->current_hps_source = source;
vv->current_hps_sync = sync;
-}
+}
int saa7146_enable_overlay(struct saa7146_fh *fh)
{
@@ -655,31 +655,31 @@ void saa7146_disable_overlay(struct saa7146_fh *fh)
struct saa7146_dev *dev = fh->dev;
/* disable clipping + video dma1 */
- saa7146_disable_clipping(dev);
+ saa7146_disable_clipping(dev);
saa7146_write(dev, MC1, MASK_22);
-}
+}
-void saa7146_write_out_dma(struct saa7146_dev* dev, int which, struct saa7146_video_dma* vdma)
+void saa7146_write_out_dma(struct saa7146_dev* dev, int which, struct saa7146_video_dma* vdma)
{
int where = 0;
-
+
if( which < 1 || which > 3) {
return;
}
-
+
/* calculate starting address */
where = (which-1)*0x18;
- saa7146_write(dev, where, vdma->base_odd);
- saa7146_write(dev, where+0x04, vdma->base_even);
- saa7146_write(dev, where+0x08, vdma->prot_addr);
- saa7146_write(dev, where+0x0c, vdma->pitch);
- saa7146_write(dev, where+0x10, vdma->base_page);
+ saa7146_write(dev, where, vdma->base_odd);
+ saa7146_write(dev, where+0x04, vdma->base_even);
+ saa7146_write(dev, where+0x08, vdma->prot_addr);
+ saa7146_write(dev, where+0x0c, vdma->pitch);
+ saa7146_write(dev, where+0x10, vdma->base_page);
saa7146_write(dev, where+0x14, vdma->num_line_byte);
-
+
/* upload */
- saa7146_write(dev, MC2, (MASK_02<<(which-1))|(MASK_18<<(which-1)));
-/*
+ saa7146_write(dev, MC2, (MASK_02<<(which-1))|(MASK_18<<(which-1)));
+/*
printk("vdma%d.base_even: 0x%08x\n", which,vdma->base_even);
printk("vdma%d.base_odd: 0x%08x\n", which,vdma->base_odd);
printk("vdma%d.prot_addr: 0x%08x\n", which,vdma->prot_addr);
@@ -688,6 +688,7 @@ void saa7146_write_out_dma(struct saa7146_dev* dev, int which, struct saa7146_vi
printk("vdma%d.num_line_byte: 0x%08x\n", which,vdma->num_line_byte);
*/
}
+
static int calculate_video_dma_grab_packed(struct saa7146_dev* dev, struct saa7146_buf *buf)
{
struct saa7146_vv *vv = dev->vv_data;
@@ -708,11 +709,11 @@ static int calculate_video_dma_grab_packed(struct saa7146_dev* dev, struct saa71
if( bytesperline != 0) {
vdma1.pitch = bytesperline*2;
} else {
- vdma1.pitch = (width*depth*2)/8;
+ vdma1.pitch = (width*depth*2)/8;
}
vdma1.num_line_byte = ((vv->standard->v_field<<16) + vv->standard->h_pixels);
vdma1.base_page = buf->pt[0].dma | ME1 | sfmt->swap;
-
+
if( 0 != vv->vflip ) {
vdma1.prot_addr = buf->pt[0].offset;
vdma1.base_even = buf->pt[0].offset+(vdma1.pitch/2)*height;
@@ -745,7 +746,7 @@ static int calculate_video_dma_grab_packed(struct saa7146_dev* dev, struct saa71
if( 0 != vv->vflip ) {
vdma1.pitch *= -1;
- }
+ }
saa7146_write_out_dma(dev, 1, &vdma1);
return 0;
@@ -769,12 +770,11 @@ static int calc_planar_422(struct saa7146_vv *vv, struct saa7146_buf *buf, struc
vdma3->prot_addr = buf->pt[2].offset;
vdma3->base_even = ((vdma3->pitch/2)*height)+buf->pt[2].offset;
vdma3->base_odd = vdma3->base_even - (vdma3->pitch/2);
-
} else {
vdma3->base_even = buf->pt[2].offset;
vdma3->base_odd = vdma3->base_even + (vdma3->pitch/2);
vdma3->prot_addr = (vdma3->pitch/2)*height+buf->pt[2].offset;
-
+
vdma2->base_even = buf->pt[1].offset;
vdma2->base_odd = vdma2->base_even + (vdma2->pitch/2);
vdma2->prot_addr = (vdma2->pitch/2)*height+buf->pt[1].offset;
@@ -812,7 +812,6 @@ static int calc_planar_420(struct saa7146_vv *vv, struct saa7146_buf *buf, struc
return 0;
}
-
static int calculate_video_dma_grab_planar(struct saa7146_dev* dev, struct saa7146_buf *buf)
{
struct saa7146_vv *vv = dev->vv_data;
@@ -905,7 +904,7 @@ static int calculate_video_dma_grab_planar(struct saa7146_dev* dev, struct saa71
vdma1.pitch *= -1;
vdma2.pitch *= -1;
vdma3.pitch *= -1;
- }
+ }
saa7146_write_out_dma(dev, 1, &vdma1);
if( (sfmt->flags & FORMAT_BYTE_SWAP) != 0 ) {
@@ -931,32 +930,32 @@ static void program_capture_engine(struct saa7146_dev *dev, int planar)
WRITE_RPS0(CMD_PAUSE | CMD_OAN | CMD_SIG0 | e_wait);
/* set rps register 0 */
- WRITE_RPS0(CMD_WR_REG | (1 << 8) | (MC2/4));
+ WRITE_RPS0(CMD_WR_REG | (1 << 8) | (MC2/4));
WRITE_RPS0(MASK_27 | MASK_11);
-
+
/* turn on video-dma1 */
- WRITE_RPS0(CMD_WR_REG_MASK | (MC1/4));
- WRITE_RPS0(MASK_06 | MASK_22); /* => mask */
+ WRITE_RPS0(CMD_WR_REG_MASK | (MC1/4));
+ WRITE_RPS0(MASK_06 | MASK_22); /* => mask */
WRITE_RPS0(MASK_06 | MASK_22); /* => values */
if( 0 != planar ) {
/* turn on video-dma2 */
- WRITE_RPS0(CMD_WR_REG_MASK | (MC1/4));
- WRITE_RPS0(MASK_05 | MASK_21); /* => mask */
+ WRITE_RPS0(CMD_WR_REG_MASK | (MC1/4));
+ WRITE_RPS0(MASK_05 | MASK_21); /* => mask */
WRITE_RPS0(MASK_05 | MASK_21); /* => values */
/* turn on video-dma3 */
- WRITE_RPS0(CMD_WR_REG_MASK | (MC1/4));
- WRITE_RPS0(MASK_04 | MASK_20); /* => mask */
+ WRITE_RPS0(CMD_WR_REG_MASK | (MC1/4));
+ WRITE_RPS0(MASK_04 | MASK_20); /* => mask */
WRITE_RPS0(MASK_04 | MASK_20); /* => values */
}
-
+
/* wait for o_fid_a/b / e_fid_a/b toggle */
if ( vv->last_field == V4L2_FIELD_INTERLACED ) {
WRITE_RPS0(CMD_PAUSE | o_wait);
- WRITE_RPS0(CMD_PAUSE | e_wait);
+ WRITE_RPS0(CMD_PAUSE | e_wait);
} else if ( vv->last_field == V4L2_FIELD_TOP ) {
WRITE_RPS0(CMD_PAUSE | (vv->current_hps_sync == SAA7146_HPS_SYNC_PORT_A ? MASK_10 : MASK_09));
- WRITE_RPS0(CMD_PAUSE | o_wait);
+ WRITE_RPS0(CMD_PAUSE | o_wait);
} else if ( vv->last_field == V4L2_FIELD_BOTTOM ) {
WRITE_RPS0(CMD_PAUSE | (vv->current_hps_sync == SAA7146_HPS_SYNC_PORT_A ? MASK_10 : MASK_09));
WRITE_RPS0(CMD_PAUSE | e_wait);
@@ -964,25 +963,25 @@ static void program_capture_engine(struct saa7146_dev *dev, int planar)
/* turn off video-dma1 */
WRITE_RPS0(CMD_WR_REG_MASK | (MC1/4));
- WRITE_RPS0(MASK_22 | MASK_06); /* => mask */
- WRITE_RPS0(MASK_22); /* => values */
+ WRITE_RPS0(MASK_22 | MASK_06); /* => mask */
+ WRITE_RPS0(MASK_22); /* => values */
if( 0 != planar ) {
/* turn off video-dma2 */
- WRITE_RPS0(CMD_WR_REG_MASK | (MC1/4));
- WRITE_RPS0(MASK_05 | MASK_21); /* => mask */
- WRITE_RPS0(MASK_21); /* => values */
+ WRITE_RPS0(CMD_WR_REG_MASK | (MC1/4));
+ WRITE_RPS0(MASK_05 | MASK_21); /* => mask */
+ WRITE_RPS0(MASK_21); /* => values */
/* turn off video-dma3 */
- WRITE_RPS0(CMD_WR_REG_MASK | (MC1/4));
- WRITE_RPS0(MASK_04 | MASK_20); /* => mask */
- WRITE_RPS0(MASK_20); /* => values */
+ WRITE_RPS0(CMD_WR_REG_MASK | (MC1/4));
+ WRITE_RPS0(MASK_04 | MASK_20); /* => mask */
+ WRITE_RPS0(MASK_20); /* => values */
}
/* generate interrupt */
- WRITE_RPS0(CMD_INTERRUPT);
+ WRITE_RPS0(CMD_INTERRUPT);
/* stop */
- WRITE_RPS0(CMD_STOP);
+ WRITE_RPS0(CMD_STOP);
}
void saa7146_set_capture(struct saa7146_dev *dev, struct saa7146_buf *buf, struct saa7146_buf *next)
@@ -1033,6 +1032,5 @@ void saa7146_set_capture(struct saa7146_dev *dev, struct saa7146_buf *buf, struc
saa7146_write(dev, RPS_ADDR0, dev->d_rps0.dma_handle);
/* turn on rps */
- saa7146_write(dev, MC1, (MASK_12 | MASK_28));
+ saa7146_write(dev, MC1, (MASK_12 | MASK_28));
}
-
diff --git a/drivers/media/common/saa7146_i2c.c b/drivers/media/common/saa7146_i2c.c
index 875ebd46623c1..781f23f0cbcc5 100644
--- a/drivers/media/common/saa7146_i2c.c
+++ b/drivers/media/common/saa7146_i2c.c
@@ -12,7 +12,7 @@ static u32 saa7146_i2c_func(struct i2c_adapter *adapter)
}
/* this function returns the status-register of our i2c-device */
-static inline u32 saa7146_i2c_status(struct saa7146_dev *dev)
+static inline u32 saa7146_i2c_status(struct saa7146_dev *dev)
{
u32 iicsta = saa7146_read(dev, I2C_STATUS);
/*
@@ -22,10 +22,10 @@ static inline u32 saa7146_i2c_status(struct saa7146_dev *dev)
}
/* this function runs through the i2c-messages and prepares the data to be
- sent through the saa7146. have a look at the specifications p. 122 ff
+ sent through the saa7146. have a look at the specifications p. 122 ff
to understand this. it returns the number of u32s to send, or -1
in case of an error. */
-static int saa7146_i2c_msg_prepare(const struct i2c_msg m[], int num, u32 *op)
+static int saa7146_i2c_msg_prepare(const struct i2c_msg *m, int num, u32 *op)
{
int h1, h2;
int i, j, addr;
@@ -56,7 +56,7 @@ static int saa7146_i2c_msg_prepare(const struct i2c_msg m[], int num, u32 *op)
/* insert the address of the i2c-slave.
note: we get 7 bit i2c-addresses,
so we have to perform a translation */
- addr = (m[i].addr*2) + ( (0 != (m[i].flags & I2C_M_RD)) ? 1 : 0);
+ addr = (m[i].addr*2) + ( (0 != (m[i].flags & I2C_M_RD)) ? 1 : 0);
h1 = op_count/3; h2 = op_count%3;
op[h1] |= ( (u8)addr << ((3-h2)*8));
op[h1] |= (SAA7146_I2C_START << ((3-h2)*2));
@@ -70,8 +70,8 @@ static int saa7146_i2c_msg_prepare(const struct i2c_msg m[], int num, u32 *op)
op[h1] |= ( SAA7146_I2C_CONT << ((3-h2)*2));
op_count++;
}
-
- }
+
+ }
/* have a look at the last byte inserted:
if it was: ...CONT change it to ...STOP */
@@ -81,7 +81,7 @@ static int saa7146_i2c_msg_prepare(const struct i2c_msg m[], int num, u32 *op)
op[h1] |= (SAA7146_I2C_STOP << ((3-h2)*2));
}
- /* return the number of u32s to send */
+ /* return the number of u32s to send */
return mem;
}
@@ -89,7 +89,7 @@ static int saa7146_i2c_msg_prepare(const struct i2c_msg m[], int num, u32 *op)
which bytes were read through the adapter and write them back to the corresponding
i2c-message. but instead, we simply write back all bytes.
fixme: this could be improved. */
-static int saa7146_i2c_msg_cleanup(const struct i2c_msg m[], int num, u32 *op)
+static int saa7146_i2c_msg_cleanup(const struct i2c_msg *m, int num, u32 *op)
{
int i, j;
int op_count = 0;
@@ -106,16 +106,16 @@ static int saa7146_i2c_msg_cleanup(const struct i2c_msg m[], int num, u32 *op)
op_count++;
}
}
-
+
return 0;
}
/* this functions resets the i2c-device and returns 0 if everything was fine, otherwise -1 */
-static int saa7146_i2c_reset(struct saa7146_dev *dev)
+static int saa7146_i2c_reset(struct saa7146_dev *dev)
{
/* get current status */
u32 status = saa7146_i2c_status(dev);
-
+
/* clear registers for sure */
saa7146_write(dev, I2C_STATUS, dev->i2c_bitrate);
saa7146_write(dev, I2C_TRANSFER, 0);
@@ -135,7 +135,7 @@ static int saa7146_i2c_reset(struct saa7146_dev *dev)
saa7146_write(dev, I2C_STATUS, dev->i2c_bitrate);
saa7146_write(dev, MC2, (MASK_00 | MASK_16));
msleep(SAA7146_I2C_DELAY);
- }
+ }
/* check if any error is (still) present. (this can be necessary because p.123, note 1) */
status = saa7146_i2c_status(dev);
@@ -160,7 +160,7 @@ static int saa7146_i2c_reset(struct saa7146_dev *dev)
saa7146_write(dev, I2C_STATUS, dev->i2c_bitrate);
saa7146_write(dev, MC2, (MASK_00 | MASK_16));
msleep(SAA7146_I2C_DELAY);
- }
+ }
/* if any error is still present, a fatal error has occured ... */
status = saa7146_i2c_status(dev);
@@ -272,21 +272,21 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d
return 0;
}
-int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg msgs[], int num, int retries)
+int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg *msgs, int num, int retries)
{
int i = 0, count = 0;
u32* buffer = dev->d_i2c.cpu_addr;
int err = 0;
int address_err = 0;
int short_delay = 0;
-
+
if (down_interruptible (&dev->i2c_lock))
return -ERESTARTSYS;
for(i=0;i<num;i++) {
DEB_I2C(("msg:%d/%d\n",i+1,num));
}
-
+
/* prepare the message(s), get number of u32s to transfer */
count = saa7146_i2c_msg_prepare(msgs, num, buffer);
if ( 0 > count ) {
@@ -296,14 +296,14 @@ int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg msgs[], i
if ( count > 3 || 0 != (SAA7146_I2C_SHORT_DELAY & dev->ext->flags) )
short_delay = 1;
-
+
do {
/* reset the i2c-device if necessary */
err = saa7146_i2c_reset(dev);
if ( 0 > err ) {
DEB_I2C(("could not reset i2c-device.\n"));
goto out;
- }
+ }
/* write out the u32s one after another */
for(i = 0; i < count; i++) {
@@ -314,10 +314,10 @@ int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg msgs[], i
thinks that an address error occured. in that case, the
transaction should be retrying, even if an address error
occured. analog saa7146 based cards extensively rely on
- i2c address probing, however, and address errors indicate that a
+ i2c address probing, however, and address errors indicate that a
device is really *not* there. retrying in that case
increases the time the device needs to probe greatly, so
- it should be avoided. because of the fact, that only
+ it should be avoided. because of the fact, that only
analog based cards use irq based i2c transactions (for dvb
cards, this screwes up other interrupt sources), we bail out
completely for analog cards after an address error and trust
@@ -336,17 +336,17 @@ int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg msgs[], i
err = num;
break;
}
-
+
/* delay a bit before retrying */
msleep(10);
-
+
} while (err != num && retries--);
/* if every retry had an address error, exit right away */
if (address_err == retries) {
goto out;
}
-
+
/* if any things had to be read, get the results */
if ( 0 != saa7146_i2c_msg_cleanup(msgs, num, buffer)) {
DEB_I2C(("could not cleanup i2c-message.\n"));
@@ -358,7 +358,7 @@ int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg msgs[], i
DEB_I2C(("transmission successful. (msg:%d).\n",err));
out:
/* another bug in revision 0: the i2c-registers get uploaded randomly by other
- uploads, so we better clear them out before continueing */
+ uploads, so we better clear them out before continueing */
if( 0 == dev->revision ) {
u32 zero = 0;
saa7146_i2c_reset(dev);
@@ -368,14 +368,14 @@ out:
}
up(&dev->i2c_lock);
- return err;
+ return err;
}
/* utility functions */
-static int saa7146_i2c_xfer(struct i2c_adapter* adapter, struct i2c_msg msg[], int num)
+static int saa7146_i2c_xfer(struct i2c_adapter* adapter, struct i2c_msg *msg, int num)
{
struct saa7146_dev* dev = i2c_get_adapdata(adapter);
-
+
/* use helper function to transfer data */
return saa7146_i2c_transfer(dev, msg, num, adapter->retries);
}
@@ -396,7 +396,7 @@ static struct i2c_algorithm saa7146_algo = {
int saa7146_i2c_adapter_prepare(struct saa7146_dev *dev, struct i2c_adapter *i2c_adapter, u32 bitrate)
{
DEB_EE(("bitrate: 0x%08x\n",bitrate));
-
+
/* enable i2c-port pins */
saa7146_write(dev, MC1, (MASK_08 | MASK_24));
@@ -412,10 +412,10 @@ int saa7146_i2c_adapter_prepare(struct saa7146_dev *dev, struct i2c_adapter *i2c
#endif
i2c_adapter->algo = &saa7146_algo;
i2c_adapter->algo_data = NULL;
- i2c_adapter->id = I2C_ALGO_SAA7146;
+ i2c_adapter->id = I2C_ALGO_SAA7146;
i2c_adapter->timeout = SAA7146_I2C_TIMEOUT;
i2c_adapter->retries = SAA7146_I2C_RETRIES;
}
-
+
return 0;
}
diff --git a/drivers/media/common/saa7146_vbi.c b/drivers/media/common/saa7146_vbi.c
index 55884d9351563..cb86a97fda1fa 100644
--- a/drivers/media/common/saa7146_vbi.c
+++ b/drivers/media/common/saa7146_vbi.c
@@ -8,14 +8,14 @@ static int vbi_workaround(struct saa7146_dev *dev)
u32 *cpu;
dma_addr_t dma_addr;
-
+
int count = 0;
int i;
DECLARE_WAITQUEUE(wait, current);
-
+
DEB_VBI(("dev:%p\n",dev));
-
+
/* once again, a bug in the saa7146: the brs acquisition
is buggy and especially the BXO-counter does not work
as specified. there is this workaround, but please
@@ -29,15 +29,15 @@ static int vbi_workaround(struct saa7146_dev *dev)
saa7146_write(dev, BASE_EVEN3, dma_addr);
saa7146_write(dev, BASE_ODD3, dma_addr+vbi_pixel_to_capture);
saa7146_write(dev, PROT_ADDR3, dma_addr+4096);
- saa7146_write(dev, PITCH3, vbi_pixel_to_capture);
+ saa7146_write(dev, PITCH3, vbi_pixel_to_capture);
saa7146_write(dev, BASE_PAGE3, 0x0);
saa7146_write(dev, NUM_LINE_BYTE3, (2<<16)|((vbi_pixel_to_capture)<<0));
saa7146_write(dev, MC2, MASK_04|MASK_20);
- /* load brs-control register */
- WRITE_RPS1(CMD_WR_REG | (1 << 8) | (BRS_CTRL/4));
- /* BXO = 1h, BRS to outbound */
- WRITE_RPS1(0xc000008c);
+ /* load brs-control register */
+ WRITE_RPS1(CMD_WR_REG | (1 << 8) | (BRS_CTRL/4));
+ /* BXO = 1h, BRS to outbound */
+ WRITE_RPS1(0xc000008c);
/* wait for vbi_a or vbi_b*/
if ( 0 != (SAA7146_USE_PORT_B_FOR_VBI & dev->ext_vv_data->flags)) {
DEB_D(("...using port b\n"));
@@ -50,36 +50,36 @@ static int vbi_workaround(struct saa7146_dev *dev)
DEB_D(("...using port a\n"));
WRITE_RPS1(CMD_PAUSE | MASK_10);
}
- /* upload brs */
- WRITE_RPS1(CMD_UPLOAD | MASK_08);
- /* load brs-control register */
- WRITE_RPS1(CMD_WR_REG | (1 << 8) | (BRS_CTRL/4));
- /* BYO = 1, BXO = NQBIL (=1728 for PAL, for NTSC this is 858*2) - NumByte3 (=1440) = 288 */
- WRITE_RPS1(((1728-(vbi_pixel_to_capture)) << 7) | MASK_19);
- /* wait for brs_done */
- WRITE_RPS1(CMD_PAUSE | MASK_08);
- /* upload brs */
- WRITE_RPS1(CMD_UPLOAD | MASK_08);
- /* load video-dma3 NumLines3 and NumBytes3 */
- WRITE_RPS1(CMD_WR_REG | (1 << 8) | (NUM_LINE_BYTE3/4));
- /* dev->vbi_count*2 lines, 720 pixel (= 1440 Bytes) */
- WRITE_RPS1((2 << 16) | (vbi_pixel_to_capture));
- /* load brs-control register */
- WRITE_RPS1(CMD_WR_REG | (1 << 8) | (BRS_CTRL/4));
- /* Set BRS right: note: this is an experimental value for BXO (=> PAL!) */
- WRITE_RPS1((540 << 7) | (5 << 19)); // 5 == vbi_start
- /* wait for brs_done */
- WRITE_RPS1(CMD_PAUSE | MASK_08);
- /* upload brs and video-dma3*/
- WRITE_RPS1(CMD_UPLOAD | MASK_08 | MASK_04);
- /* load mc2 register: enable dma3 */
- WRITE_RPS1(CMD_WR_REG | (1 << 8) | (MC1/4));
- WRITE_RPS1(MASK_20 | MASK_04);
- /* generate interrupt */
- WRITE_RPS1(CMD_INTERRUPT);
- /* stop rps1 */
- WRITE_RPS1(CMD_STOP);
-
+ /* upload brs */
+ WRITE_RPS1(CMD_UPLOAD | MASK_08);
+ /* load brs-control register */
+ WRITE_RPS1(CMD_WR_REG | (1 << 8) | (BRS_CTRL/4));
+ /* BYO = 1, BXO = NQBIL (=1728 for PAL, for NTSC this is 858*2) - NumByte3 (=1440) = 288 */
+ WRITE_RPS1(((1728-(vbi_pixel_to_capture)) << 7) | MASK_19);
+ /* wait for brs_done */
+ WRITE_RPS1(CMD_PAUSE | MASK_08);
+ /* upload brs */
+ WRITE_RPS1(CMD_UPLOAD | MASK_08);
+ /* load video-dma3 NumLines3 and NumBytes3 */
+ WRITE_RPS1(CMD_WR_REG | (1 << 8) | (NUM_LINE_BYTE3/4));
+ /* dev->vbi_count*2 lines, 720 pixel (= 1440 Bytes) */
+ WRITE_RPS1((2 << 16) | (vbi_pixel_to_capture));
+ /* load brs-control register */
+ WRITE_RPS1(CMD_WR_REG | (1 << 8) | (BRS_CTRL/4));
+ /* Set BRS right: note: this is an experimental value for BXO (=> PAL!) */
+ WRITE_RPS1((540 << 7) | (5 << 19)); // 5 == vbi_start
+ /* wait for brs_done */
+ WRITE_RPS1(CMD_PAUSE | MASK_08);
+ /* upload brs and video-dma3*/
+ WRITE_RPS1(CMD_UPLOAD | MASK_08 | MASK_04);
+ /* load mc2 register: enable dma3 */
+ WRITE_RPS1(CMD_WR_REG | (1 << 8) | (MC1/4));
+ WRITE_RPS1(MASK_20 | MASK_04);
+ /* generate interrupt */
+ WRITE_RPS1(CMD_INTERRUPT);
+ /* stop rps1 */
+ WRITE_RPS1(CMD_STOP);
+
/* we have to do the workaround twice to be sure that
everything is ok */
for(i = 0; i < 2; i++) {
@@ -89,7 +89,7 @@ static int vbi_workaround(struct saa7146_dev *dev)
saa7146_write(dev, NUM_LINE_BYTE3, (1<<16)|(2<<0));
saa7146_write(dev, MC2, MASK_04|MASK_20);
-
+
/* enable rps1 irqs */
SAA7146_IER_ENABLE(dev,MASK_28);
@@ -99,12 +99,12 @@ static int vbi_workaround(struct saa7146_dev *dev)
/* start rps1 to enable workaround */
saa7146_write(dev, RPS_ADDR1, dev->d_rps1.dma_handle);
- saa7146_write(dev, MC1, (MASK_13 | MASK_29));
-
+ saa7146_write(dev, MC1, (MASK_13 | MASK_29));
+
schedule();
DEB_VBI(("brs bug workaround %d/1.\n",i));
-
+
remove_wait_queue(&vv->vbi_wq, &wait);
current->state = TASK_RUNNING;
@@ -115,7 +115,7 @@ static int vbi_workaround(struct saa7146_dev *dev)
saa7146_write(dev, MC1, MASK_20);
if(signal_pending(current)) {
-
+
DEB_VBI(("aborted (rps:0x%08x).\n",saa7146_read(dev,RPS_ADDR1)));
/* stop rps1 for sure */
@@ -154,6 +154,7 @@ static void saa7146_set_vbi_capture(struct saa7146_dev *dev, struct saa7146_buf
vdma3.pitch = vbi_pixel_to_capture;
vdma3.base_page = buf->pt[2].dma | ME1;
vdma3.num_line_byte = (16 << 16) | vbi_pixel_to_capture;
+
saa7146_write_out_dma(dev, 3, &vdma3);
/* write beginning of rps-program */
@@ -165,29 +166,29 @@ static void saa7146_set_vbi_capture(struct saa7146_dev *dev, struct saa7146_buf
capture and might cause that the first buffer is only half filled (with only
one field). but since this is some sort of streaming data, this is not that negative.
but by doing this, we can use the whole engine from video-buf.c... */
-
+
/*
WRITE_RPS1(CMD_PAUSE | CMD_OAN | CMD_SIG1 | e_wait);
WRITE_RPS1(CMD_PAUSE | CMD_OAN | CMD_SIG1 | o_wait);
*/
/* set bit 1 */
- WRITE_RPS1(CMD_WR_REG | (1 << 8) | (MC2/4));
+ WRITE_RPS1(CMD_WR_REG | (1 << 8) | (MC2/4));
WRITE_RPS1(MASK_28 | MASK_12);
-
+
/* turn on video-dma3 */
- WRITE_RPS1(CMD_WR_REG_MASK | (MC1/4));
- WRITE_RPS1(MASK_04 | MASK_20); /* => mask */
+ WRITE_RPS1(CMD_WR_REG_MASK | (MC1/4));
+ WRITE_RPS1(MASK_04 | MASK_20); /* => mask */
WRITE_RPS1(MASK_04 | MASK_20); /* => values */
-
+
/* wait for o_fid_a/b / e_fid_a/b toggle */
WRITE_RPS1(CMD_PAUSE | o_wait);
WRITE_RPS1(CMD_PAUSE | e_wait);
/* generate interrupt */
- WRITE_RPS1(CMD_INTERRUPT);
+ WRITE_RPS1(CMD_INTERRUPT);
/* stop */
- WRITE_RPS1(CMD_STOP);
+ WRITE_RPS1(CMD_STOP);
/* enable rps1 irqs */
SAA7146_IER_ENABLE(dev, MASK_28);
@@ -196,7 +197,7 @@ static void saa7146_set_vbi_capture(struct saa7146_dev *dev, struct saa7146_buf
saa7146_write(dev, RPS_ADDR1, dev->d_rps1.dma_handle);
/* turn on rps */
- saa7146_write(dev, MC1, (MASK_13 | MASK_29));
+ saa7146_write(dev, MC1, (MASK_13 | MASK_29));
}
static int buffer_activate(struct saa7146_dev *dev,
@@ -228,12 +229,12 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,e
size = lines * llength;
DEB_VBI(("vb:%p\n",vb));
-
+
if (0 != buf->vb.baddr && buf->vb.bsize < size) {
DEB_VBI(("size mismatch.\n"));
return -EINVAL;
}
-
+
if (buf->vb.size != size)
saa7146_dma_free(dev,buf);
@@ -246,7 +247,7 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,e
saa7146_pgtable_free(dev->pci, &buf->pt[2]);
saa7146_pgtable_alloc(dev->pci, &buf->pt[2]);
- err = videobuf_iolock(dev->pci,&buf->vb,NULL);
+ err = videobuf_iolock(dev->pci,&buf->vb, NULL);
if (err)
goto oops;
err = saa7146_pgtable_build_single(dev->pci, &buf->pt[2], buf->vb.dma.sglist, buf->vb.dma.sglen);
@@ -268,7 +269,7 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,e
static int buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
{
int llength,lines;
-
+
lines = 16 * 2 ; /* 2 fields */
llength = vbi_pixel_to_capture;
@@ -287,7 +288,7 @@ static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
struct saa7146_dev *dev = fh->dev;
struct saa7146_vv *vv = dev->vv_data;
struct saa7146_buf *buf = (struct saa7146_buf *)vb;
-
+
DEB_VBI(("vb:%p\n",vb));
saa7146_buffer_queue(dev,&vv->vbi_q,buf);
}
@@ -298,7 +299,7 @@ static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
struct saa7146_fh *fh = file->private_data;
struct saa7146_dev *dev = fh->dev;
struct saa7146_buf *buf = (struct saa7146_buf *)vb;
-
+
DEB_VBI(("vb:%p\n",vb));
saa7146_dma_free(dev,buf);
}
@@ -318,7 +319,7 @@ static void vbi_stop(struct saa7146_fh *fh, struct file *file)
struct saa7146_vv *vv = dev->vv_data;
unsigned long flags;
DEB_VBI(("dev:%p, fh:%p\n",dev, fh));
-
+
spin_lock_irqsave(&dev->slock,flags);
/* disable rps1 */
@@ -349,7 +350,7 @@ static void vbi_read_timeout(unsigned long data)
struct file *file = (struct file*)data;
struct saa7146_fh *fh = file->private_data;
struct saa7146_dev *dev = fh->dev;
-
+
DEB_VBI(("dev:%p, fh:%p\n",dev, fh));
vbi_stop(fh, file);
@@ -372,10 +373,10 @@ static void vbi_init(struct saa7146_dev *dev, struct saa7146_vv *vv)
static int vbi_open(struct saa7146_dev *dev, struct file *file)
{
struct saa7146_fh *fh = (struct saa7146_fh *)file->private_data;
-
+
u32 arbtr_ctrl = saa7146_read(dev, PCI_BT_V1);
int ret = 0;
-
+
DEB_VBI(("dev:%p, fh:%p\n",dev,fh));
ret = saa7146_res_get(fh, RESOURCE_DMA3_BRS);
@@ -388,12 +389,12 @@ static int vbi_open(struct saa7146_dev *dev, struct file *file)
arbtr_ctrl &= ~0x1f0000;
arbtr_ctrl |= 0x1d0000;
saa7146_write(dev, PCI_BT_V1, arbtr_ctrl);
- saa7146_write(dev, MC2, (MASK_04|MASK_20));
-
+ saa7146_write(dev, MC2, (MASK_04|MASK_20));
+
memset(&fh->vbi_fmt,0,sizeof(fh->vbi_fmt));
fh->vbi_fmt.sampling_rate = 27000000;
- fh->vbi_fmt.offset = 248; /* todo */
+ fh->vbi_fmt.offset = 248; /* todo */
fh->vbi_fmt.samples_per_line = vbi_pixel_to_capture;
fh->vbi_fmt.sample_format = V4L2_PIX_FMT_GREY;
@@ -428,7 +429,7 @@ static int vbi_open(struct saa7146_dev *dev, struct file *file)
}
/* upload brs register */
- saa7146_write(dev, MC2, (MASK_08|MASK_24));
+ saa7146_write(dev, MC2, (MASK_08|MASK_24));
return 0;
}
@@ -471,7 +472,7 @@ static ssize_t vbi_read(struct file *file, char __user *data, size_t count, loff
ssize_t ret = 0;
DEB_VBI(("dev:%p, fh:%p\n",dev,fh));
-
+
if( NULL == vv->vbi_streaming ) {
// fixme: check if dma3 is available
// fixme: activate vbi engine here if necessary. (really?)
diff --git a/drivers/media/common/saa7146_video.c b/drivers/media/common/saa7146_video.c
index 87b0f64658121..8dd4d15ca36d8 100644
--- a/drivers/media/common/saa7146_video.c
+++ b/drivers/media/common/saa7146_video.c
@@ -14,64 +14,64 @@ MODULE_PARM_DESC(max_memory, "maximum memory usage for capture buffers (default:
/* format descriptions for capture and preview */
static struct saa7146_format formats[] = {
{
- .name = "RGB-8 (3-3-2)",
+ .name = "RGB-8 (3-3-2)",
.pixelformat = V4L2_PIX_FMT_RGB332,
- .trans = RGB08_COMPOSED,
+ .trans = RGB08_COMPOSED,
.depth = 8,
.flags = 0,
}, {
- .name = "RGB-16 (5/B-6/G-5/R)",
+ .name = "RGB-16 (5/B-6/G-5/R)",
.pixelformat = V4L2_PIX_FMT_RGB565,
- .trans = RGB16_COMPOSED,
+ .trans = RGB16_COMPOSED,
.depth = 16,
.flags = 0,
}, {
- .name = "RGB-24 (B-G-R)",
+ .name = "RGB-24 (B-G-R)",
.pixelformat = V4L2_PIX_FMT_BGR24,
- .trans = RGB24_COMPOSED,
+ .trans = RGB24_COMPOSED,
.depth = 24,
.flags = 0,
}, {
- .name = "RGB-32 (B-G-R)",
+ .name = "RGB-32 (B-G-R)",
.pixelformat = V4L2_PIX_FMT_BGR32,
- .trans = RGB32_COMPOSED,
+ .trans = RGB32_COMPOSED,
.depth = 32,
.flags = 0,
}, {
- .name = "RGB-32 (R-G-B)",
+ .name = "RGB-32 (R-G-B)",
.pixelformat = V4L2_PIX_FMT_RGB32,
- .trans = RGB32_COMPOSED,
+ .trans = RGB32_COMPOSED,
.depth = 32,
.flags = 0,
.swap = 0x2,
}, {
- .name = "Greyscale-8",
+ .name = "Greyscale-8",
.pixelformat = V4L2_PIX_FMT_GREY,
- .trans = Y8,
+ .trans = Y8,
.depth = 8,
.flags = 0,
}, {
- .name = "YUV 4:2:2 planar (Y-Cb-Cr)",
+ .name = "YUV 4:2:2 planar (Y-Cb-Cr)",
.pixelformat = V4L2_PIX_FMT_YUV422P,
- .trans = YUV422_DECOMPOSED,
+ .trans = YUV422_DECOMPOSED,
.depth = 16,
.flags = FORMAT_BYTE_SWAP|FORMAT_IS_PLANAR,
}, {
- .name = "YVU 4:2:0 planar (Y-Cb-Cr)",
+ .name = "YVU 4:2:0 planar (Y-Cb-Cr)",
.pixelformat = V4L2_PIX_FMT_YVU420,
- .trans = YUV420_DECOMPOSED,
+ .trans = YUV420_DECOMPOSED,
.depth = 12,
.flags = FORMAT_BYTE_SWAP|FORMAT_IS_PLANAR,
}, {
- .name = "YUV 4:2:0 planar (Y-Cb-Cr)",
+ .name = "YUV 4:2:0 planar (Y-Cb-Cr)",
.pixelformat = V4L2_PIX_FMT_YUV420,
- .trans = YUV420_DECOMPOSED,
+ .trans = YUV420_DECOMPOSED,
.depth = 12,
.flags = FORMAT_IS_PLANAR,
}, {
- .name = "YUV 4:2:2 (U-Y-V-Y)",
+ .name = "YUV 4:2:2 (U-Y-V-Y)",
.pixelformat = V4L2_PIX_FMT_UYVY,
- .trans = YUV422_COMPOSED,
+ .trans = YUV422_COMPOSED,
.depth = 16,
.flags = 0,
}
@@ -80,19 +80,19 @@ static struct saa7146_format formats[] = {
/* unfortunately, the saa7146 contains a bug which prevents it from doing on-the-fly byte swaps.
due to this, it's impossible to provide additional *packed* formats, which are simply byte swapped
(like V4L2_PIX_FMT_YUYV) ... 8-( */
-
+
static int NUM_FORMATS = sizeof(formats)/sizeof(struct saa7146_format);
struct saa7146_format* format_by_fourcc(struct saa7146_dev *dev, int fourcc)
{
int i, j = NUM_FORMATS;
-
+
for (i = 0; i < j; i++) {
if (formats[i].pixelformat == fourcc) {
return formats+i;
}
}
-
+
DEB_D(("unknown pixelformat:'%4.4s'\n",(char *)&fourcc));
return NULL;
}
@@ -182,7 +182,7 @@ static int try_fmt(struct saa7146_fh *fh, struct v4l2_format *f)
struct saa7146_dev *dev = fh->dev;
struct saa7146_vv *vv = dev->vv_data;
int err;
-
+
switch (f->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
{
@@ -201,7 +201,7 @@ static int try_fmt(struct saa7146_fh *fh, struct v4l2_format *f)
field = f->fmt.pix.field;
maxw = vv->standard->h_max_out;
maxh = vv->standard->v_max_out;
-
+
if (V4L2_FIELD_ANY == field) {
field = (f->fmt.pix.height > maxh/2)
? V4L2_FIELD_INTERLACED
@@ -237,10 +237,10 @@ static int try_fmt(struct saa7146_fh *fh, struct v4l2_format *f)
if (f->fmt.pix.bytesperline < calc_bpl)
f->fmt.pix.bytesperline = calc_bpl;
-
+
if (f->fmt.pix.bytesperline > (2*PAGE_SIZE * fmt->depth)/8) /* arbitrary constraint */
f->fmt.pix.bytesperline = calc_bpl;
-
+
f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * f->fmt.pix.height;
DEB_D(("w:%d, h:%d, bytesperline:%d, sizeimage:%d\n",f->fmt.pix.width,f->fmt.pix.height,f->fmt.pix.bytesperline,f->fmt.pix.sizeimage));
@@ -277,36 +277,36 @@ int saa7146_start_preview(struct saa7146_fh *fh)
if (IS_CAPTURE_ACTIVE(fh) != 0) {
DEB_D(("streaming capture is active.\n"));
return -EBUSY;
- }
+ }
/* check if overlay is running */
- if (IS_OVERLAY_ACTIVE(fh) != 0) {
+ if (IS_OVERLAY_ACTIVE(fh) != 0) {
if (vv->video_fh == fh) {
- DEB_D(("overlay is already active.\n"));
- return 0;
- }
+ DEB_D(("overlay is already active.\n"));
+ return 0;
+ }
DEB_D(("overlay is already active in another open.\n"));
return -EBUSY;
}
-
+
if (0 == saa7146_res_get(fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP)) {
DEB_D(("cannot get necessary overlay resources\n"));
return -EBUSY;
- }
-
+ }
+
err = try_win(dev,&fh->ov.win);
if (0 != err) {
saa7146_res_free(vv->video_fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP);
return -EBUSY;
}
-
+
vv->ov_data = &fh->ov;
DEB_D(("%dx%d+%d+%d %s field=%s\n",
fh->ov.win.w.width,fh->ov.win.w.height,
fh->ov.win.w.left,fh->ov.win.w.top,
vv->ov_fmt->name,v4l2_field_names[fh->ov.win.field]));
-
+
if (0 != (ret = saa7146_enable_overlay(fh))) {
DEB_D(("enabling overlay failed: %d\n",ret));
saa7146_res_free(vv->video_fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP);
@@ -333,7 +333,7 @@ int saa7146_stop_preview(struct saa7146_fh *fh)
}
/* check if overlay is running at all */
- if ((vv->video_status & STATUS_OVERLAY) == 0) {
+ if ((vv->video_status & STATUS_OVERLAY) == 0) {
DEB_D(("no active overlay.\n"));
return 0;
}
@@ -347,7 +347,7 @@ int saa7146_stop_preview(struct saa7146_fh *fh)
vv->video_fh = NULL;
saa7146_disable_overlay(fh);
-
+
saa7146_res_free(fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP);
return 0;
@@ -359,7 +359,7 @@ static int s_fmt(struct saa7146_fh *fh, struct v4l2_format *f)
struct saa7146_vv *vv = dev->vv_data;
int err;
-
+
switch (f->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n",dev,fh));
@@ -387,7 +387,7 @@ static int s_fmt(struct saa7146_fh *fh, struct v4l2_format *f)
up(&dev->lock);
return -EFAULT;
}
-
+
/* fh->ov.fh is used to indicate that we have valid overlay informations, too */
fh->ov.fh = fh;
@@ -395,8 +395,8 @@ static int s_fmt(struct saa7146_fh *fh, struct v4l2_format *f)
/* check if our current overlay is active */
if (IS_OVERLAY_ACTIVE(fh) != 0) {
- saa7146_stop_preview(fh);
- saa7146_start_preview(fh);
+ saa7146_stop_preview(fh);
+ saa7146_start_preview(fh);
}
return 0;
default:
@@ -454,7 +454,7 @@ static int NUM_CONTROLS = sizeof(controls)/sizeof(struct v4l2_queryctrl);
static struct v4l2_queryctrl* ctrl_by_id(int id)
{
int i;
-
+
for (i = 0; i < NUM_CONTROLS; i++)
if (controls[i].id == id)
return controls+i;
@@ -515,7 +515,7 @@ static int set_control(struct saa7146_fh *fh, struct v4l2_control *c)
DEB_D(("unknown control %d\n",c->id));
return -EINVAL;
}
-
+
down(&dev->lock);
switch (ctrl->type) {
@@ -578,10 +578,10 @@ static int set_control(struct saa7146_fh *fh, struct v4l2_control *c)
}
}
up(&dev->lock);
-
+
if (IS_OVERLAY_ACTIVE(fh) != 0) {
- saa7146_stop_preview(fh);
- saa7146_start_preview(fh);
+ saa7146_stop_preview(fh);
+ saa7146_start_preview(fh);
}
return 0;
}
@@ -633,7 +633,7 @@ static int saa7146_pgtable_build(struct saa7146_dev *dev, struct saa7146_buf *bu
return -1;
}
}
-
+
ptr1 = pt1->cpu;
ptr2 = pt2->cpu;
ptr3 = pt3->cpu;
@@ -649,14 +649,14 @@ static int saa7146_pgtable_build(struct saa7146_dev *dev, struct saa7146_buf *bu
for(j=0;j<40;j++) {
printk("ptr1 %d: 0x%08x\n",j,ptr1[j]);
}
-*/
+*/
/* if we have a user buffer, the first page may not be
aligned to a page boundary. */
pt1->offset = buf->vb.dma.sglist->offset;
pt2->offset = pt1->offset+o1;
pt3->offset = pt1->offset+o2;
-
+
/* create video-dma2 page table */
ptr1 = pt1->cpu;
for(i = m1; i <= m2 ; i++, ptr2++) {
@@ -675,7 +675,7 @@ static int saa7146_pgtable_build(struct saa7146_dev *dev, struct saa7146_buf *bu
for(;i<1024;i++,ptr3++) {
*ptr3 = fill;
}
- /* finally: finish up video-dma1 page table */
+ /* finally: finish up video-dma1 page table */
ptr1 = pt1->cpu+m1;
fill = pt1->cpu[m1];
for(i=m1;i<1024;i++,ptr1++) {
@@ -694,7 +694,7 @@ static int saa7146_pgtable_build(struct saa7146_dev *dev, struct saa7146_buf *bu
for(j=0;j<40;j++) {
printk("ptr3 %d: 0x%08x\n",j,ptr3[j]);
}
-*/
+*/
} else {
struct saa7146_pgtable *pt = &buf->pt[0];
return saa7146_pgtable_build_single(pci, pt, list, length);
@@ -719,9 +719,9 @@ static int video_begin(struct saa7146_fh *fh)
if ((vv->video_status & STATUS_CAPTURE) != 0) {
if (vv->video_fh == fh) {
- DEB_S(("already capturing.\n"));
+ DEB_S(("already capturing.\n"));
return 0;
- }
+ }
DEB_S(("already capturing in another open.\n"));
return -EBUSY;
}
@@ -735,7 +735,7 @@ static int video_begin(struct saa7146_fh *fh)
return err;
}
}
-
+
fmt = format_by_fourcc(dev,fh->video_fmt.pixelformat);
/* we need to have a valid format set here */
BUG_ON(NULL == fmt);
@@ -811,7 +811,7 @@ static int video_end(struct saa7146_fh *fh, struct file *file)
saa7146_write(dev, MC1, dmas);
spin_unlock_irqrestore(&dev->slock, flags);
-
+
vv->video_fh = NULL;
vv->video_status = 0;
@@ -820,7 +820,7 @@ static int video_end(struct saa7146_fh *fh, struct file *file)
if (vv->ov_suspend != NULL) {
saa7146_start_preview(vv->ov_suspend);
vv->ov_suspend = NULL;
-}
+ }
return 0;
}
@@ -847,7 +847,7 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int
if( cmd == dev->ext_vv_data->ioctls[ee].cmd )
break;
}
-
+
if( 0 != (dev->ext_vv_data->ioctls[ee].flags & SAA7146_EXCLUSIVE) ) {
DEB_D(("extension handles ioctl exclusive.\n"));
result = dev->ext_vv_data->ioctl(fh, cmd, arg);
@@ -860,7 +860,7 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int
return result;
}
}
-
+
/* fixme: add handle "after" case (is it still needed?) */
switch (fh->type) {
@@ -880,21 +880,21 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int
}
switch (cmd) {
- case VIDIOC_QUERYCAP:
+ case VIDIOC_QUERYCAP:
{
struct v4l2_capability *cap = arg;
memset(cap,0,sizeof(*cap));
DEB_EE(("VIDIOC_QUERYCAP\n"));
-
+
strcpy(cap->driver, "saa7146 v4l2");
strlcpy(cap->card, dev->ext->name, sizeof(cap->card));
- sprintf(cap->bus_info,"PCI:%s",dev->pci->slot_name);
+ sprintf(cap->bus_info,"PCI:%s", pci_name(dev->pci));
cap->version = SAA7146_VERSION_CODE;
cap->capabilities =
V4L2_CAP_VIDEO_CAPTURE |
V4L2_CAP_VIDEO_OVERLAY |
- V4L2_CAP_READWRITE |
+ V4L2_CAP_READWRITE |
V4L2_CAP_STREAMING;
cap->capabilities |= dev->ext_vv_data->capabilities;
return 0;
@@ -925,18 +925,18 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int
if (NULL == fmt) {
return -EINVAL;
}
-
+
/* planar formats are not allowed for overlay video, clipping and video dma would clash */
if (0 != (fmt->flags & FORMAT_IS_PLANAR)) {
DEB_S(("planar pixelformat '%4.4s' not allowed for overlay\n",(char *)&fmt->pixelformat));
}
/* check if overlay is running */
- if (IS_OVERLAY_ACTIVE(fh) != 0) {
+ if (IS_OVERLAY_ACTIVE(fh) != 0) {
if (vv->video_fh != fh) {
DEB_D(("refusing to change framebuffer informations while overlay is active in another open.\n"));
return -EBUSY;
- }
+ }
}
down(&dev->lock);
@@ -971,7 +971,7 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int
break;
}
default:
- return -EINVAL;
+ return -EINVAL;
}
DEB_EE(("VIDIOC_ENUM_FMT: type:%d, index:%d\n",f->type,f->index));
@@ -987,12 +987,12 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int
(c->id < V4L2_CID_PRIVATE_BASE ||
c->id >= V4L2_CID_PRIVATE_LASTP1))
return -EINVAL;
-
+
ctrl = ctrl_by_id(c->id);
if( NULL == ctrl ) {
return -EINVAL;
/*
- c->flags = V4L2_CTRL_FLAG_DISABLED;
+ c->flags = V4L2_CTRL_FLAG_DISABLED;
return 0;
*/
}
@@ -1006,10 +1006,6 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int
return get_control(fh,arg);
}
case VIDIOC_S_CTRL:
-
-
-
-
{
DEB_EE(("VIDIOC_S_CTRL\n"));
err = set_control(fh,arg);
@@ -1073,7 +1069,7 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int
v4l2_std_id *id = arg;
int found = 0;
int i, err;
-
+
DEB_EE(("VIDIOC_S_STD\n"));
if ((vv->video_status & STATUS_CAPTURE) == STATUS_CAPTURE) {
@@ -1091,7 +1087,7 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int
}
down(&dev->lock);
-
+
for(i = 0; i < dev->ext_vv_data->num_stds; i++)
if (*id & dev->ext_vv_data->stds[i].id)
break;
@@ -1164,8 +1160,8 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int
err = video_begin(fh);
if( 0 != err) {
- return err;
- }
+ return err;
+ }
err = videobuf_streamon(q);
return err;
}
@@ -1190,7 +1186,7 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int
err = videobuf_streamoff(q);
if (0 != err) {
DEB_D(("warning: videobuf_streamoff() failed.\n"));
- video_end(fh, file);
+ video_end(fh, file);
} else {
err = video_end(fh, file);
}
@@ -1203,9 +1199,9 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int
int i;
/* fixme: number of capture buffers and sizes for v4l apps */
- int gbuffers = 2;
+ int gbuffers = 2;
int gbufsize = 768*576*4;
-
+
DEB_D(("VIDIOCGMBUF \n"));
q = &fh->video_q;
@@ -1242,7 +1238,7 @@ static int buffer_activate (struct saa7146_dev *dev,
buf->vb.state = STATE_ACTIVE;
saa7146_set_capture(dev,buf,next);
-
+
mod_timer(&vv->video_q.timeout, jiffies+BUFFER_TIMEOUT);
return 0;
}
@@ -1273,7 +1269,7 @@ static int buffer_prepare(struct videobuf_queue *q,
DEB_D(("size mismatch.\n"));
return -EINVAL;
}
-
+
DEB_CAP(("buffer_prepare [size=%dx%d,bytes=%d,fields=%s]\n",
fh->video_fmt.width,fh->video_fmt.height,size,v4l2_field_names[fh->video_fmt.field]));
if (buf->vb.width != fh->video_fmt.width ||
@@ -1288,7 +1284,7 @@ static int buffer_prepare(struct videobuf_queue *q,
if (STATE_NEEDS_INIT == buf->vb.state) {
struct saa7146_format *sfmt;
-
+
buf->vb.bytesperline = fh->video_fmt.bytesperline;
buf->vb.width = fh->video_fmt.width;
buf->vb.height = fh->video_fmt.height;
@@ -1296,9 +1292,9 @@ static int buffer_prepare(struct videobuf_queue *q,
buf->vb.field = field;
buf->fmt = &fh->video_fmt;
buf->vb.field = fh->video_fmt.field;
-
+
sfmt = format_by_fourcc(dev,buf->fmt->pixelformat);
-
+
if( 0 != IS_PLANAR(sfmt->trans)) {
saa7146_pgtable_free(dev->pci, &buf->pt[0]);
saa7146_pgtable_free(dev->pci, &buf->pt[1]);
@@ -1311,7 +1307,7 @@ static int buffer_prepare(struct videobuf_queue *q,
saa7146_pgtable_free(dev->pci, &buf->pt[0]);
saa7146_pgtable_alloc(dev->pci, &buf->pt[0]);
}
-
+
err = videobuf_iolock(dev->pci,&buf->vb, &vv->ov_fb);
if (err)
goto oops;
@@ -1345,7 +1341,7 @@ static int buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned
if( (*count * *size) > (max_memory*1048576) ) {
*count = (max_memory*1048576) / *size;
}
-
+
DEB_CAP(("%d buffers, %d bytes each.\n",*count,*size));
return 0;
@@ -1358,7 +1354,7 @@ static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
struct saa7146_dev *dev = fh->dev;
struct saa7146_vv *vv = dev->vv_data;
struct saa7146_buf *buf = (struct saa7146_buf *)vb;
-
+
DEB_CAP(("vbuf:%p\n",vb));
saa7146_buffer_queue(fh->dev,&vv->video_q,buf);
}
@@ -1370,7 +1366,7 @@ static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
struct saa7146_fh *fh = file->private_data;
struct saa7146_dev *dev = fh->dev;
struct saa7146_buf *buf = (struct saa7146_buf *)vb;
-
+
DEB_CAP(("vbuf:%p\n",vb));
saa7146_dma_free(dev,buf);
}
@@ -1434,13 +1430,13 @@ static void video_close(struct saa7146_dev *dev, struct file *file)
struct saa7146_fh *fh = (struct saa7146_fh *)file->private_data;
struct saa7146_vv *vv = dev->vv_data;
int err;
-
+
if (IS_CAPTURE_ACTIVE(fh) != 0) {
- err = video_end(fh, file);
+ err = video_end(fh, file);
} else if (IS_OVERLAY_ACTIVE(fh) != 0) {
err = saa7146_stop_preview(fh);
}
-
+
/* hmm, why is this function declared void? */
/* return err */
}
@@ -1450,7 +1446,7 @@ static void video_irq_done(struct saa7146_dev *dev, unsigned long st)
{
struct saa7146_vv *vv = dev->vv_data;
struct saa7146_dmaqueue *q = &vv->video_q;
-
+
spin_lock(&dev->slock);
DEB_CAP(("called.\n"));
@@ -1473,11 +1469,11 @@ static ssize_t video_read(struct file *file, char __user *data, size_t count, lo
DEB_EE(("called.\n"));
if ((vv->video_status & STATUS_CAPTURE) != 0) {
- /* fixme: should we allow read() captures while streaming capture? */
+ /* fixme: should we allow read() captures while streaming capture? */
if (vv->video_fh == fh) {
- DEB_S(("already capturing.\n"));
- return -EBUSY;
- }
+ DEB_S(("already capturing.\n"));
+ return -EBUSY;
+ }
DEB_S(("already capturing in another open.\n"));
return -EBUSY;
}
@@ -1487,10 +1483,10 @@ static ssize_t video_read(struct file *file, char __user *data, size_t count, lo
goto out;
}
- ret = videobuf_read_one(&fh->video_q, data, count, ppos,
+ ret = videobuf_read_one(&fh->video_q , data, count, ppos,
file->f_flags & O_NONBLOCK);
if (ret != 0) {
- video_end(fh, file);
+ video_end(fh, file);
} else {
ret = video_end(fh, file);
}
@@ -1500,7 +1496,7 @@ out:
saa7146_start_preview(vv->ov_suspend);
vv->ov_suspend = NULL;
}
-
+
return ret;
}
diff --git a/drivers/media/common/saa7146_vv_ksyms.c b/drivers/media/common/saa7146_vv_ksyms.c
index 76f2e862f3c8a..62226eb4753b1 100644
--- a/drivers/media/common/saa7146_vv_ksyms.c
+++ b/drivers/media/common/saa7146_vv_ksyms.c
@@ -1,9 +1,6 @@
#include <linux/module.h>
#include <media/saa7146_vv.h>
-EXPORT_SYMBOL_GPL(saa7146_vbi_uops);
-EXPORT_SYMBOL_GPL(saa7146_video_uops);
-
EXPORT_SYMBOL_GPL(saa7146_start_preview);
EXPORT_SYMBOL_GPL(saa7146_stop_preview);
diff --git a/drivers/media/dvb/Kconfig b/drivers/media/dvb/Kconfig
index c9a5138e4215e..883ec08490f41 100644
--- a/drivers/media/dvb/Kconfig
+++ b/drivers/media/dvb/Kconfig
@@ -8,13 +8,13 @@ config DVB
bool "DVB For Linux"
depends on NET && INET
---help---
- Support Digital Video Broadcasting hardware. Enable this if you
- own a DVB adapter and want to use it or if you compile Linux for
+ Support Digital Video Broadcasting hardware. Enable this if you
+ own a DVB adapter and want to use it or if you compile Linux for
a digital SetTopBox.
API specs and user tools are available from <http://www.linuxtv.org/>.
- Please report problems regarding this driver to the LinuxDVB
+ Please report problems regarding this driver to the LinuxDVB
mailing list.
If unsure say N.
diff --git a/drivers/media/dvb/b2c2/b2c2-common.c b/drivers/media/dvb/b2c2/b2c2-common.c
index cb42d44f4f986..000d60c405e37 100644
--- a/drivers/media/dvb/b2c2/b2c2-common.c
+++ b/drivers/media/dvb/b2c2/b2c2-common.c
@@ -158,7 +158,7 @@ static int samsung_tdtc9251dh0_demod_init(struct dvb_frontend* fe)
return 0;
}
-int samsung_tdtc9251dh0_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf)
+static int samsung_tdtc9251dh0_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf)
{
u32 div;
unsigned char bs = 0;
diff --git a/drivers/media/dvb/b2c2/b2c2-usb-core.c b/drivers/media/dvb/b2c2/b2c2-usb-core.c
index 6cc0502f43a49..9306da046c91d 100644
--- a/drivers/media/dvb/b2c2/b2c2-usb-core.c
+++ b/drivers/media/dvb/b2c2/b2c2-usb-core.c
@@ -194,7 +194,7 @@ static u32 b2c2_usb_read_dw(struct usb_b2c2_usb *b2c2, u16 wRegOffsPCI)
0,
&val,
sizeof(u32),
- B2C2_WAIT_FOR_OPERATION_RDW * HZ);
+ B2C2_WAIT_FOR_OPERATION_RDW * 1000);
if (len != sizeof(u32)) {
err("error while reading dword from %d (%d).",wAddress,wRegOffsPCI);
@@ -220,7 +220,7 @@ static int b2c2_usb_write_dw(struct usb_b2c2_usb *b2c2, u16 wRegOffsPCI, u32 val
0,
&val,
sizeof(u32),
- B2C2_WAIT_FOR_OPERATION_RDW * HZ);
+ B2C2_WAIT_FOR_OPERATION_RDW * 1000);
if (len != sizeof(u32)) {
err("error while reading dword from %d (%d).",wAddress,wRegOffsPCI);
@@ -270,7 +270,7 @@ static int b2c2_usb_v8_memory_req(struct usb_b2c2_usb *b2c2,
wIndex,
pbBuffer,
buflen,
- nWaitTime * HZ);
+ nWaitTime * 1000);
return len == buflen ? 0 : -EIO;
}
@@ -312,7 +312,7 @@ static int b2c2_usb_i2c_req(struct usb_b2c2_usb *b2c2,
wIndex,
buf,
buflen,
- nWaitTime * HZ);
+ nWaitTime * 1000);
return len == buflen ? 0 : -EIO;
}
@@ -334,7 +334,7 @@ int static b2c2_usb_utility_req(struct usb_b2c2_usb *b2c2, int set,
wIndex,
pvBuffer,
buflen,
- nWaitTime * HZ);
+ nWaitTime * 1000);
return len == buflen ? 0 : -EIO;
}
@@ -546,3 +546,4 @@ module_exit (b2c2_usb_exit);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(usb, b2c2_usb_table);
diff --git a/drivers/media/dvb/b2c2/skystar2.c b/drivers/media/dvb/b2c2/skystar2.c
index 9db4699574195..336c178fcd5fc 100644
--- a/drivers/media/dvb/b2c2/skystar2.c
+++ b/drivers/media/dvb/b2c2/skystar2.c
@@ -5,14 +5,14 @@
* Copyright (C) 2003 Vadim Catana, skystar@moldova.cc
*
* FIX: DISEQC Tone Burst in flexcop_diseqc_ioctl()
- * FIX: FULL soft DiSEqC for skystar2 (FlexCopII rev 130) VP310 equipped
+ * FIX: FULL soft DiSEqC for skystar2 (FlexCopII rev 130) VP310 equipped
* Vincenzo Di Massa, hawk.it at tiscalinet.it
- *
+ *
* Converted to Linux coding style
* Misc reorganization, polishing, restyling
- * Roberto Ragusa, r.ragusa at libero.it
- *
- * Added hardware filtering support,
+ * Roberto Ragusa, skystar2-c5b8 at robertoragusa dot it
+ *
+ * Added hardware filtering support,
* Niklas Peinecke, peinecke at gdv.uni-hannover.de
*
*
@@ -231,8 +231,8 @@ static void fixchipaddr(u32 device, u32 bus, u32 addr, u32 *ret)
{
if (device == 0x20000000)
*ret = bus | ((addr >> 8) & 3);
-
- *ret = bus;
+ else
+ *ret = bus;
}
static u32 flex_i2c_read(struct adapter *adapter, u32 device, u32 bus, u32 addr, u8 *buf, u32 len)
@@ -293,7 +293,7 @@ static u32 flex_i2c_write(struct adapter *adapter, u32 device, u32 bus, u32 addr
return buf - start;
}
-static int master_xfer(struct i2c_adapter* adapter, struct i2c_msg msgs[], int num)
+static int master_xfer(struct i2c_adapter* adapter, struct i2c_msg *msgs, int num)
{
struct adapter *tmp = i2c_get_adapdata(adapter);
int i, ret = 0;
@@ -1968,7 +1968,7 @@ static int driver_initialize(struct pci_dev *pdev)
ctrl_enable_mac(adapter, 1);
}
- adapter->lock = SPIN_LOCK_UNLOCKED;
+ spin_lock_init(&adapter->lock);
out:
return ret;
@@ -1996,10 +1996,6 @@ static void driver_halt(struct pci_dev *pdev)
free_adapter_object(adapter);
pci_set_drvdata(pdev, NULL);
-
- pci_disable_device(pdev);
- pci_release_region(pdev, 1);
- pci_release_region(pdev, 0);
}
static int dvb_start_feed(struct dvb_demux_feed *dvbdmxfeed)
@@ -2356,7 +2352,7 @@ static int samsung_tdtc9251dh0_demod_init(struct dvb_frontend* fe)
return 0;
}
-int samsung_tdtc9251dh0_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf)
+static int samsung_tdtc9251dh0_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf)
{
u32 div;
unsigned char bs = 0;
@@ -2633,7 +2629,7 @@ static struct pci_driver skystar2_pci_driver = {
static int skystar2_init(void)
{
- return pci_module_init(&skystar2_pci_driver);
+ return pci_register_driver(&skystar2_pci_driver);
}
static void skystar2_cleanup(void)
diff --git a/drivers/media/dvb/bt8xx/Kconfig b/drivers/media/dvb/bt8xx/Kconfig
index bc7b48ed176ec..e7d11e0667a8b 100644
--- a/drivers/media/dvb/bt8xx/Kconfig
+++ b/drivers/media/dvb/bt8xx/Kconfig
@@ -5,9 +5,11 @@ config DVB_BT8XX
select DVB_SP887X
select DVB_NXT6000
select DVB_CX24110
+ select DVB_OR51211
help
Support for PCI cards based on the Bt8xx PCI bridge. Examples are
- the Nebula cards, the Pinnacle PCTV cards and Twinhan DST cards.
+ the Nebula cards, the Pinnacle PCTV cards, the Twinhan DST cards and
+ pcHDTV HD2000 cards.
Since these cards have no MPEG decoder onboard, they transmit
only compressed MPEG data over the PCI bus, so you need
diff --git a/drivers/media/dvb/bt8xx/bt878.c b/drivers/media/dvb/bt8xx/bt878.c
index 7968bfef30455..213ff79020242 100644
--- a/drivers/media/dvb/bt8xx/bt878.c
+++ b/drivers/media/dvb/bt8xx/bt878.c
@@ -55,10 +55,10 @@ static unsigned int bt878_verbose = 1;
static unsigned int bt878_debug;
module_param_named(verbose, bt878_verbose, int, 0444);
-MODULE_PARM_DESC(bt878_verbose,
+MODULE_PARM_DESC(verbose,
"verbose startup messages, default is 1 (yes)");
module_param_named(debug, bt878_debug, int, 0644);
-MODULE_PARM_DESC(bt878_debug, "Turn on/off debugging (default:off).");
+MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
int bt878_num;
struct bt878 bt878[BT878_MAX];
@@ -381,21 +381,6 @@ bt878_device_control(struct bt878 *bt, unsigned int cmd, union dst_gpio_packet *
EXPORT_SYMBOL(bt878_device_control);
-struct bt878 *bt878_find_by_i2c_adap(struct i2c_adapter *adapter)
-{
- unsigned int card_nr;
-
- printk("bt878 find by dvb adap: checking \"%s\"\n",adapter->name);
- for (card_nr = 0; card_nr < bt878_num; card_nr++) {
- if (bt878[card_nr].adapter == adapter)
- return &bt878[card_nr];
- }
- printk("bt878 find by dvb adap: NOT found \"%s\"\n",adapter->name);
- return NULL;
-}
-
-EXPORT_SYMBOL(bt878_find_by_i2c_adap);
-
/***********************/
/* PCI device handling */
/***********************/
@@ -578,7 +563,7 @@ static int bt878_init_module(void)
/* later we register inside of bt878_find_audio_dma()
* because we may want to ignore certain cards */
bt878_pci_driver_registered = 1;
- return pci_module_init(&bt878_pci_driver);
+ return pci_register_driver(&bt878_pci_driver);
}
static void bt878_cleanup_module(void)
diff --git a/drivers/media/dvb/bt8xx/bt878.h b/drivers/media/dvb/bt8xx/bt878.h
index 22fa5211c493e..e1b9809d1b083 100644
--- a/drivers/media/dvb/bt8xx/bt878.h
+++ b/drivers/media/dvb/bt8xx/bt878.h
@@ -89,7 +89,6 @@
#define BT878_RISC_SYNC_MASK (1 << 15)
extern int bt878_num;
-extern struct bt878 bt878[BT878_MAX];
struct bt878 {
struct semaphore gpio_lock;
@@ -124,6 +123,8 @@ struct bt878 {
int shutdown;
};
+extern struct bt878 bt878[BT878_MAX];
+
void bt878_start(struct bt878 *bt, u32 controlreg, u32 op_sync_orin,
u32 irq_err_ignore);
void bt878_stop(struct bt878 *bt);
diff --git a/drivers/media/dvb/bt8xx/dst.c b/drivers/media/dvb/bt8xx/dst.c
index 62830d177aae2..eac83768dfd0e 100644
--- a/drivers/media/dvb/bt8xx/dst.c
+++ b/drivers/media/dvb/bt8xx/dst.c
@@ -141,7 +141,7 @@ static int dst_gpio_inb(struct dst_state *state, u8 * result)
}
#define DST_I2C_ENABLE 1
-#define DST_8820 2
+#define DST_8820 2
static int dst_reset8820(struct dst_state *state)
{
@@ -998,7 +998,7 @@ struct dvb_frontend* dst_attach(const struct dst_config* config,
return &state->frontend;
error:
- if (state) kfree(state);
+ kfree(state);
return NULL;
}
@@ -1036,7 +1036,7 @@ static struct dvb_frontend_ops dst_dvbs_ops = {
.frequency_tolerance = 29500,
.symbol_rate_min = 1000000,
.symbol_rate_max = 45000000,
- /* . symbol_rate_tolerance = ???,*/
+ /* . symbol_rate_tolerance = ???,*/
.caps = FE_CAN_FEC_AUTO | FE_CAN_QPSK
},
@@ -1066,7 +1066,7 @@ static struct dvb_frontend_ops dst_dvbc_ops = {
.frequency_max = 858000000,
.symbol_rate_min = 1000000,
.symbol_rate_max = 45000000,
- /* . symbol_rate_tolerance = ???,*/
+ /* . symbol_rate_tolerance = ???,*/
.caps = FE_CAN_FEC_AUTO | FE_CAN_QAM_AUTO
},
diff --git a/drivers/media/dvb/bt8xx/dst_priv.h b/drivers/media/dvb/bt8xx/dst_priv.h
index b3d5e6fc6d13d..80488aa628b40 100644
--- a/drivers/media/dvb/bt8xx/dst_priv.h
+++ b/drivers/media/dvb/bt8xx/dst_priv.h
@@ -34,4 +34,3 @@ struct bt878;
int bt878_device_control(struct bt878 *bt, unsigned int cmd, union dst_gpio_packet *mp);
-struct bt878 *bt878_find_by_i2c_adap(struct i2c_adapter *adap);
diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/drivers/media/dvb/bt8xx/dvb-bt8xx.c
index 80e1f52dea496..b735397f59aad 100644
--- a/drivers/media/dvb/bt8xx/dvb-bt8xx.c
+++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.c
@@ -1,5 +1,5 @@
/*
- * Bt8xx based DVB adapter driver
+ * Bt8xx based DVB adapter driver
*
* Copyright (C) 2002,2003 Florian Schirmer <jolt@tuxbox.org>
*
@@ -71,7 +71,7 @@ static int dvb_bt8xx_start_feed(struct dvb_demux_feed *dvbdmxfeed)
int rc;
dprintk("dvb_bt8xx: start_feed\n");
-
+
if (!dvbdmx->dmx.frontend)
return -EINVAL;
@@ -91,10 +91,10 @@ static int dvb_bt8xx_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
struct dvb_bt8xx_card *card = dvbdmx->priv;
dprintk("dvb_bt8xx: stop_feed\n");
-
+
if (!dvbdmx->dmx.frontend)
return -EINVAL;
-
+
down(&card->lock);
card->nfeeds--;
if (card->nfeeds == 0)
@@ -117,7 +117,7 @@ static int is_pci_slot_eq(struct pci_dev* adev, struct pci_dev* bdev)
static struct bt878 __init *dvb_bt8xx_878_match(unsigned int bttv_nr, struct pci_dev* bttv_pci_dev)
{
unsigned int card_nr;
-
+
/* Hmm, n squared. Hope n is small */
for (card_nr = 0; card_nr < bt878_num; card_nr++) {
if (is_pci_slot_eq(bt878[card_nr].dev, bttv_pci_dev))
@@ -133,7 +133,7 @@ static int thomson_dtt7579_demod_init(struct dvb_frontend* fe)
static u8 mt352_reset [] = { 0x50, 0x80 };
static u8 mt352_adc_ctl_1_cfg [] = { 0x8E, 0x40 };
static u8 mt352_agc_cfg [] = { 0x67, 0x28, 0x20 };
- static u8 mt352_gpp_ctl_cfg [] = { 0x75, 0x33 };
+ static u8 mt352_gpp_ctl_cfg [] = { 0x8C, 0x33 };
static u8 mt352_capt_range_cfg[] = { 0x75, 0x32 };
mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config));
@@ -167,9 +167,9 @@ static int thomson_dtt7579_pll_set(struct dvb_frontend* fe, struct dvb_frontend_
pllbuf[0] = 0xc0; // Note: non-linux standard PLL i2c address
pllbuf[1] = div >> 8;
- pllbuf[2] = div & 0xff;
- pllbuf[3] = cp;
- pllbuf[4] = bs;
+ pllbuf[2] = div & 0xff;
+ pllbuf[3] = cp;
+ pllbuf[4] = bs;
return 0;
}
@@ -184,25 +184,25 @@ static struct mt352_config thomson_dtt7579_config = {
static int cx24108_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
{
u32 freq = params->frequency;
-
- int i, a, n, pump;
+
+ int i, a, n, pump;
u32 band, pll;
-
-
+
+
u32 osci[]={950000,1019000,1075000,1178000,1296000,1432000,
1576000,1718000,1856000,2036000,2150000};
u32 bandsel[]={0,0x00020000,0x00040000,0x00100800,0x00101000,
0x00102000,0x00104000,0x00108000,0x00110000,
0x00120000,0x00140000};
-
+
#define XTAL 1011100 /* Hz, really 1.0111 MHz and a /10 prescaler */
printk("cx24108 debug: entering SetTunerFreq, freq=%d\n",freq);
-
+
/* This is really the bit driving the tuner chip cx24108 */
-
+
if(freq<950000) freq=950000; /* kHz */
if(freq>2150000) freq=2150000; /* satellite IF is 950..2150MHz */
-
+
/* decide which VCO to use for the input frequency */
for(i=1;(i<sizeof(osci)/sizeof(osci[0]))&&(osci[i]<freq);i++);
printk("cx24108 debug: select vco #%d (f=%d)\n",i,freq);
@@ -210,7 +210,7 @@ static int cx24108_pll_set(struct dvb_frontend* fe, struct dvb_frontend_paramete
/* the gain values must be set by SetSymbolrate */
/* compute the pll divider needed, from Conexant data sheet,
resolved for (n*32+a), remember f(vco) is f(receive) *2 or *4,
- depending on the divider bit. It is set to /4 on the 2 lowest
+ depending on the divider bit. It is set to /4 on the 2 lowest
bands */
n=((i<=2?2:1)*freq*10L)/(XTAL/100);
a=n%32; n/=32; if(a==0) n--;
@@ -348,9 +348,9 @@ static int advbt771_samsung_tdtc9251dh0_pll_set(struct dvb_frontend* fe, struct
pllbuf[0] = 0xc2; // Note: non-linux standard PLL i2c address
pllbuf[1] = div >> 8;
- pllbuf[2] = div & 0xff;
- pllbuf[3] = cp;
- pllbuf[4] = bs;
+ pllbuf[2] = div & 0xff;
+ pllbuf[3] = cp;
+ pllbuf[4] = bs;
return 0;
}
@@ -369,6 +369,63 @@ static struct dst_config dst_config = {
};
+static int or51211_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name)
+{
+ struct dvb_bt8xx_card* bt = (struct dvb_bt8xx_card*) fe->dvb->priv;
+
+ return request_firmware(fw, name, &bt->bt->dev->dev);
+}
+
+static void or51211_setmode(struct dvb_frontend * fe, int mode)
+{
+ struct dvb_bt8xx_card *bt = fe->dvb->priv;
+ bttv_write_gpio(bt->bttv_nr, 0x0002, mode); /* Reset */
+ msleep(20);
+}
+
+static void or51211_reset(struct dvb_frontend * fe)
+{
+ struct dvb_bt8xx_card *bt = fe->dvb->priv;
+
+ /* RESET DEVICE
+ * reset is controled by GPIO-0
+ * when set to 0 causes reset and when to 1 for normal op
+ * must remain reset for 128 clock cycles on a 50Mhz clock
+ * also PRM1 PRM2 & PRM4 are controled by GPIO-1,GPIO-2 & GPIO-4
+ * We assume that the reset has be held low long enough or we
+ * have been reset by a power on. When the driver is unloaded
+ * reset set to 0 so if reloaded we have been reset.
+ */
+ /* reset & PRM1,2&4 are outputs */
+ int ret = bttv_gpio_enable(bt->bttv_nr, 0x001F, 0x001F);
+ if (ret != 0) {
+ printk(KERN_WARNING "or51211: Init Error - Can't Reset DVR "
+ "(%i)\n", ret);
+ }
+ bttv_write_gpio(bt->bttv_nr, 0x001F, 0x0000); /* Reset */
+ msleep(20);
+ /* Now set for normal operation */
+ bttv_write_gpio(bt->bttv_nr, 0x0001F, 0x0001);
+ /* wait for operation to begin */
+ msleep(500);
+}
+
+static void or51211_sleep(struct dvb_frontend * fe)
+{
+ struct dvb_bt8xx_card *bt = fe->dvb->priv;
+ bttv_write_gpio(bt->bttv_nr, 0x0001, 0x0000);
+}
+
+static struct or51211_config or51211_config = {
+
+ .demod_address = 0x15,
+ .request_firmware = or51211_request_firmware,
+ .setmode = or51211_setmode,
+ .reset = or51211_reset,
+ .sleep = or51211_sleep,
+};
+
+
static int vp3021_alps_tded4_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
{
struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *) fe->dvb->priv;
@@ -451,13 +508,20 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
break;
}
break;
-
+
case BTTV_PINNACLESAT:
card->fe = cx24110_attach(&pctvsat_config, card->i2c_adapter);
if (card->fe != NULL) {
break;
}
break;
+
+ case BTTV_PC_HDTV:
+ card->fe = or51211_attach(&or51211_config, card->i2c_adapter);
+ if (card->fe != NULL) {
+ break;
+ }
+ break;
}
if (card->fe == NULL) {
@@ -484,7 +548,7 @@ static int __init dvb_bt8xx_load_card(struct dvb_bt8xx_card *card, u32 type)
THIS_MODULE)) < 0) {
printk("dvb_bt8xx: dvb_register_adapter failed (errno = %d)\n", result);
return result;
-
+
}
card->dvb_adapter->priv = card;
@@ -500,7 +564,7 @@ static int __init dvb_bt8xx_load_card(struct dvb_bt8xx_card *card, u32 type)
card->demux.start_feed = dvb_bt8xx_start_feed;
card->demux.stop_feed = dvb_bt8xx_stop_feed;
card->demux.write_to_decoder = NULL;
-
+
if ((result = dvb_dmx_init(&card->demux)) < 0) {
printk("dvb_bt8xx: dvb_dmx_init failed (errno = %d)\n", result);
@@ -511,7 +575,7 @@ static int __init dvb_bt8xx_load_card(struct dvb_bt8xx_card *card, u32 type)
card->dmxdev.filternum = 256;
card->dmxdev.demux = &card->demux.dmx;
card->dmxdev.capabilities = 0;
-
+
if ((result = dvb_dmxdev_init(&card->dmxdev, card->dvb_adapter)) < 0) {
printk("dvb_bt8xx: dvb_dmxdev_init failed (errno = %d)\n", result);
@@ -530,7 +594,7 @@ static int __init dvb_bt8xx_load_card(struct dvb_bt8xx_card *card, u32 type)
dvb_unregister_adapter(card->dvb_adapter);
return result;
}
-
+
card->fe_mem.source = DMX_MEMORY_FE;
if ((result = card->demux.dmx.add_frontend(&card->demux.dmx, &card->fe_mem)) < 0) {
@@ -557,7 +621,7 @@ static int __init dvb_bt8xx_load_card(struct dvb_bt8xx_card *card, u32 type)
dvb_net_init(card->dvb_adapter, &card->dvbnet, &card->demux.dmx);
tasklet_init(&card->bt->tasklet, dvb_bt8xx_task, (unsigned long) card);
-
+
frontend_init(card, type);
return 0;
@@ -588,17 +652,17 @@ static int dvb_bt8xx_probe(struct device *dev)
card->op_sync_orin = 0;
card->irq_err_ignore = 0;
break;
-
+
#ifdef BTTV_DVICO_DVBT_LITE
case BTTV_DVICO_DVBT_LITE:
#endif
card->gpio_mode = 0x0400C060;
card->op_sync_orin = 0;
card->irq_err_ignore = 0;
- /* 26, 15, 14, 6, 5
+ /* 26, 15, 14, 6, 5
* A_PWRDN DA_DPM DA_SBR DA_IOM_DA
- * DA_APP(parallel) */
- break;
+ * DA_APP(parallel) */
+ break;
#ifdef BTTV_TWINHAN_VP3021
case BTTV_TWINHAN_VP3021:
@@ -609,40 +673,46 @@ static int dvb_bt8xx_probe(struct device *dev)
card->gpio_mode = (1 << 26) | (1 << 14) | (1 << 5);
card->op_sync_orin = 0;
card->irq_err_ignore = 0;
- /* A_PWRDN DA_SBR DA_APP (high speed serial) */
- break;
+ /* A_PWRDN DA_SBR DA_APP (high speed serial) */
+ break;
case BTTV_AVDVBT_771: //case 0x07711461:
card->gpio_mode = 0x0400402B;
card->op_sync_orin = BT878_RISC_SYNC_MASK;
card->irq_err_ignore = 0;
/* A_PWRDN DA_SBR DA_APP[0] PKTP=10 RISC_ENABLE FIFO_ENABLE*/
- break;
+ break;
case BTTV_TWINHAN_DST:
card->gpio_mode = 0x2204f2c;
card->op_sync_orin = BT878_RISC_SYNC_MASK;
card->irq_err_ignore = BT878_APABORT | BT878_ARIPERR |
BT878_APPERR | BT878_AFBUS;
- /* 25,21,14,11,10,9,8,3,2 then
- * 0x33 = 5,4,1,0
- * A_SEL=SML, DA_MLB, DA_SBR,
- * DA_SDR=f, fifo trigger = 32 DWORDS
- * IOM = 0 == audio A/D
- * DPM = 0 == digital audio mode
- * == async data parallel port
- * then 0x33 (13 is set by start_capture)
- * DA_APP = async data parallel port,
- * ACAP_EN = 1,
- * RISC+FIFO ENABLE */
- break;
-
- default:
+ /* 25,21,14,11,10,9,8,3,2 then
+ * 0x33 = 5,4,1,0
+ * A_SEL=SML, DA_MLB, DA_SBR,
+ * DA_SDR=f, fifo trigger = 32 DWORDS
+ * IOM = 0 == audio A/D
+ * DPM = 0 == digital audio mode
+ * == async data parallel port
+ * then 0x33 (13 is set by start_capture)
+ * DA_APP = async data parallel port,
+ * ACAP_EN = 1,
+ * RISC+FIFO ENABLE */
+ break;
+
+ case BTTV_PC_HDTV:
+ card->gpio_mode = 0x0100EC7B;
+ card->op_sync_orin = 0;
+ card->irq_err_ignore = 0;
+ break;
+
+ default:
printk(KERN_WARNING "dvb_bt8xx: Unknown bttv card type: %d.\n",
sub->core->type);
kfree(card);
return -ENODEV;
- }
+ }
dprintk("dvb_bt8xx: identified card%d as %s\n", card->bttv_nr, card->card_name);
@@ -661,7 +731,7 @@ static int dvb_bt8xx_probe(struct device *dev)
kfree(card);
return -EFAULT;
-}
+ }
init_MUTEX(&card->bt->gpio_lock);
card->bt->bttv_nr = sub->core->nr;
@@ -678,23 +748,23 @@ static int dvb_bt8xx_probe(struct device *dev)
static int dvb_bt8xx_remove(struct device *dev)
{
struct dvb_bt8xx_card *card = dev_get_drvdata(dev);
-
- dprintk("dvb_bt8xx: unloading card%d\n", card->bttv_nr);
- bt878_stop(card->bt);
- tasklet_kill(&card->bt->tasklet);
- dvb_net_release(&card->dvbnet);
- card->demux.dmx.remove_frontend(&card->demux.dmx, &card->fe_mem);
- card->demux.dmx.remove_frontend(&card->demux.dmx, &card->fe_hw);
- dvb_dmxdev_release(&card->dmxdev);
- dvb_dmx_release(&card->demux);
+ dprintk("dvb_bt8xx: unloading card%d\n", card->bttv_nr);
+
+ bt878_stop(card->bt);
+ tasklet_kill(&card->bt->tasklet);
+ dvb_net_release(&card->dvbnet);
+ card->demux.dmx.remove_frontend(&card->demux.dmx, &card->fe_mem);
+ card->demux.dmx.remove_frontend(&card->demux.dmx, &card->fe_hw);
+ dvb_dmxdev_release(&card->dmxdev);
+ dvb_dmx_release(&card->demux);
if (card->fe) dvb_unregister_frontend(card->fe);
- dvb_unregister_adapter(card->dvb_adapter);
-
- kfree(card);
+ dvb_unregister_adapter(card->dvb_adapter);
+
+ kfree(card);
return 0;
- }
+}
static struct bttv_sub_driver driver = {
.drv = {
@@ -721,7 +791,7 @@ static void __exit dvb_bt8xx_exit(void)
module_init(dvb_bt8xx_init);
module_exit(dvb_bt8xx_exit);
+
MODULE_DESCRIPTION("Bt8xx based DVB adapter driver");
MODULE_AUTHOR("Florian Schirmer <jolt@tuxbox.org>");
MODULE_LICENSE("GPL");
-
diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.h b/drivers/media/dvb/bt8xx/dvb-bt8xx.h
index 5fb87df65739a..80ef189f930f3 100644
--- a/drivers/media/dvb/bt8xx/dvb-bt8xx.h
+++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.h
@@ -1,5 +1,5 @@
/*
- * Bt8xx based DVB adapter driver
+ * Bt8xx based DVB adapter driver
*
* Copyright (C) 2002,2003 Florian Schirmer <jolt@tuxbox.org>
* Copyright (C) 2002 Peter Hettkamp <peter.hettkamp@t-online.de>
@@ -34,6 +34,7 @@
#include "dst.h"
#include "nxt6000.h"
#include "cx24110.h"
+#include "or51211.h"
struct dvb_bt8xx_card {
struct semaphore lock;
@@ -51,7 +52,7 @@ struct dvb_bt8xx_card {
u32 irq_err_ignore;
struct i2c_adapter *i2c_adapter;
struct dvb_net dvbnet;
-
+
struct dvb_frontend* fe;
};
diff --git a/drivers/media/dvb/cinergyT2/cinergyT2.c b/drivers/media/dvb/cinergyT2/cinergyT2.c
index 644d9241c10d4..f1f539761371f 100644
--- a/drivers/media/dvb/cinergyT2/cinergyT2.c
+++ b/drivers/media/dvb/cinergyT2/cinergyT2.c
@@ -37,13 +37,6 @@
#include "dvb_net.h"
-
-
-
-
-
-
-
#ifdef CONFIG_DVB_CINERGYT2_TUNING
#define STREAM_URB_COUNT (CONFIG_DVB_CINERGYT2_STREAM_URB_COUNT)
#define STREAM_BUF_SIZE (CONFIG_DVB_CINERGYT2_STREAM_BUF_SIZE)
@@ -66,7 +59,7 @@ static int debug;
module_param_named(debug, debug, int, 0644);
MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
-#define dprintk(level, args...) \
+#define dprintk(level, args...) \
do { \
if ((debug & level)) { \
printk("%s: %s(): ", __stringify(KBUILD_MODNAME), \
@@ -77,8 +70,8 @@ do { \
enum cinergyt2_ep1_cmd {
CINERGYT2_EP1_PID_TABLE_RESET = 0x01,
CINERGYT2_EP1_PID_SETUP = 0x02,
- CINERGYT2_EP1_CONTROL_STREAM_TRANSFER = 0x03,
- CINERGYT2_EP1_SET_TUNER_PARAMETERS = 0x04,
+ CINERGYT2_EP1_CONTROL_STREAM_TRANSFER = 0x03,
+ CINERGYT2_EP1_SET_TUNER_PARAMETERS = 0x04,
CINERGYT2_EP1_GET_TUNER_STATUS = 0x05,
CINERGYT2_EP1_START_SCAN = 0x06,
CINERGYT2_EP1_CONTINUE_SCAN = 0x07,
@@ -143,7 +136,7 @@ struct cinergyt2 {
void *streambuf;
dma_addr_t streambuf_dmahandle;
- struct urb *stream_urb[STREAM_URB_COUNT];
+ struct urb *stream_urb [STREAM_URB_COUNT];
#ifdef ENABLE_RC
struct input_dev rc_input_dev;
@@ -164,47 +157,47 @@ struct cinergyt2_rc_event {
} __attribute__((packed));
static const uint32_t rc_keys [] = {
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xfe01eb04, KEY_POWER,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xfd02eb04, KEY_1,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xfc03eb04, KEY_2,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xfb04eb04, KEY_3,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xfa05eb04, KEY_4,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xf906eb04, KEY_5,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xf807eb04, KEY_6,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xf708eb04, KEY_7,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xf609eb04, KEY_8,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xf50aeb04, KEY_9,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xf30ceb04, KEY_0,
+ CINERGYT2_RC_EVENT_TYPE_NEC, 0xfe01eb04, KEY_POWER,
+ CINERGYT2_RC_EVENT_TYPE_NEC, 0xfd02eb04, KEY_1,
+ CINERGYT2_RC_EVENT_TYPE_NEC, 0xfc03eb04, KEY_2,
+ CINERGYT2_RC_EVENT_TYPE_NEC, 0xfb04eb04, KEY_3,
+ CINERGYT2_RC_EVENT_TYPE_NEC, 0xfa05eb04, KEY_4,
+ CINERGYT2_RC_EVENT_TYPE_NEC, 0xf906eb04, KEY_5,
+ CINERGYT2_RC_EVENT_TYPE_NEC, 0xf807eb04, KEY_6,
+ CINERGYT2_RC_EVENT_TYPE_NEC, 0xf708eb04, KEY_7,
+ CINERGYT2_RC_EVENT_TYPE_NEC, 0xf609eb04, KEY_8,
+ CINERGYT2_RC_EVENT_TYPE_NEC, 0xf50aeb04, KEY_9,
+ CINERGYT2_RC_EVENT_TYPE_NEC, 0xf30ceb04, KEY_0,
CINERGYT2_RC_EVENT_TYPE_NEC, 0xf40beb04, KEY_VIDEO,
CINERGYT2_RC_EVENT_TYPE_NEC, 0xf20deb04, KEY_REFRESH,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xf10eeb04, KEY_SELECT,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xf00feb04, KEY_EPG,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xef10eb04, KEY_UP,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xeb14eb04, KEY_DOWN,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xee11eb04, KEY_LEFT,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xec13eb04, KEY_RIGHT,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xed12eb04, KEY_OK,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xea15eb04, KEY_TEXT,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xe916eb04, KEY_INFO,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xe817eb04, KEY_RED,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xe718eb04, KEY_GREEN,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xe619eb04, KEY_YELLOW,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xe51aeb04, KEY_BLUE,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xe31ceb04, KEY_VOLUMEUP,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xe11eeb04, KEY_VOLUMEDOWN,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xe21deb04, KEY_MUTE,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xe41beb04, KEY_CHANNELUP,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xe01feb04, KEY_CHANNELDOWN,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xbf40eb04, KEY_PAUSE,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xb34ceb04, KEY_PLAY,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xa758eb04, KEY_RECORD,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xab54eb04, KEY_PREVIOUS,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xb748eb04, KEY_STOP,
- CINERGYT2_RC_EVENT_TYPE_NEC, 0xa35ceb04, KEY_NEXT
+ CINERGYT2_RC_EVENT_TYPE_NEC, 0xf10eeb04, KEY_SELECT,
+ CINERGYT2_RC_EVENT_TYPE_NEC, 0xf00feb04, KEY_EPG,
+ CINERGYT2_RC_EVENT_TYPE_NEC, 0xef10eb04, KEY_UP,
+ CINERGYT2_RC_EVENT_TYPE_NEC, 0xeb14eb04, KEY_DOWN,
+ CINERGYT2_RC_EVENT_TYPE_NEC, 0xee11eb04, KEY_LEFT,
+ CINERGYT2_RC_EVENT_TYPE_NEC, 0xec13eb04, KEY_RIGHT,
+ CINERGYT2_RC_EVENT_TYPE_NEC, 0xed12eb04, KEY_OK,
+ CINERGYT2_RC_EVENT_TYPE_NEC, 0xea15eb04, KEY_TEXT,
+ CINERGYT2_RC_EVENT_TYPE_NEC, 0xe916eb04, KEY_INFO,
+ CINERGYT2_RC_EVENT_TYPE_NEC, 0xe817eb04, KEY_RED,
+ CINERGYT2_RC_EVENT_TYPE_NEC, 0xe718eb04, KEY_GREEN,
+ CINERGYT2_RC_EVENT_TYPE_NEC, 0xe619eb04, KEY_YELLOW,
+ CINERGYT2_RC_EVENT_TYPE_NEC, 0xe51aeb04, KEY_BLUE,
+ CINERGYT2_RC_EVENT_TYPE_NEC, 0xe31ceb04, KEY_VOLUMEUP,
+ CINERGYT2_RC_EVENT_TYPE_NEC, 0xe11eeb04, KEY_VOLUMEDOWN,
+ CINERGYT2_RC_EVENT_TYPE_NEC, 0xe21deb04, KEY_MUTE,
+ CINERGYT2_RC_EVENT_TYPE_NEC, 0xe41beb04, KEY_CHANNELUP,
+ CINERGYT2_RC_EVENT_TYPE_NEC, 0xe01feb04, KEY_CHANNELDOWN,
+ CINERGYT2_RC_EVENT_TYPE_NEC, 0xbf40eb04, KEY_PAUSE,
+ CINERGYT2_RC_EVENT_TYPE_NEC, 0xb34ceb04, KEY_PLAY,
+ CINERGYT2_RC_EVENT_TYPE_NEC, 0xa758eb04, KEY_RECORD,
+ CINERGYT2_RC_EVENT_TYPE_NEC, 0xab54eb04, KEY_PREVIOUS,
+ CINERGYT2_RC_EVENT_TYPE_NEC, 0xb748eb04, KEY_STOP,
+ CINERGYT2_RC_EVENT_TYPE_NEC, 0xa35ceb04, KEY_NEXT
};
static int cinergyt2_command (struct cinergyt2 *cinergyt2,
- char *send_buf, int send_buf_len,
+ char *send_buf, int send_buf_len,
char *recv_buf, int recv_buf_len)
{
int actual_len;
@@ -212,7 +205,7 @@ static int cinergyt2_command (struct cinergyt2 *cinergyt2,
int ret;
ret = usb_bulk_msg(cinergyt2->udev, usb_sndbulkpipe(cinergyt2->udev, 1),
- send_buf, send_buf_len, &actual_len, HZ);
+ send_buf, send_buf_len, &actual_len, 1000);
if (ret)
dprintk(1, "usb_bulk_msg (send) failed, err %i\n", ret);
@@ -221,7 +214,7 @@ static int cinergyt2_command (struct cinergyt2 *cinergyt2,
recv_buf = &dummy;
ret = usb_bulk_msg(cinergyt2->udev, usb_rcvbulkpipe(cinergyt2->udev, 1),
- recv_buf, recv_buf_len, &actual_len, HZ);
+ recv_buf, recv_buf_len, &actual_len, 1000);
if (ret)
dprintk(1, "usb_bulk_msg (read) failed, err %i\n", ret);
@@ -232,13 +225,13 @@ static int cinergyt2_command (struct cinergyt2 *cinergyt2,
static void cinergyt2_control_stream_transfer (struct cinergyt2 *cinergyt2, int enable)
{
char buf [] = { CINERGYT2_EP1_CONTROL_STREAM_TRANSFER, enable ? 1 : 0 };
- cinergyt2_command(cinergyt2, buf, sizeof(buf), NULL, 0);
+ cinergyt2_command(cinergyt2, buf, sizeof(buf), NULL, 0);
}
static void cinergyt2_sleep (struct cinergyt2 *cinergyt2, int sleep)
{
char buf [] = { CINERGYT2_EP1_SLEEP_MODE, sleep ? 1 : 0 };
- cinergyt2_command(cinergyt2, buf, sizeof(buf), NULL, 0);
+ cinergyt2_command(cinergyt2, buf, sizeof(buf), NULL, 0);
cinergyt2->sleeping = sleep;
}
@@ -290,7 +283,7 @@ static int cinergyt2_alloc_stream_urbs (struct cinergyt2 *cinergyt2)
{
int i;
- cinergyt2->streambuf = pci_alloc_consistent(NULL,
+ cinergyt2->streambuf = pci_alloc_consistent(NULL,
STREAM_URB_COUNT*STREAM_BUF_SIZE,
&cinergyt2->streambuf_dmahandle);
if (!cinergyt2->streambuf) {
@@ -301,7 +294,7 @@ static int cinergyt2_alloc_stream_urbs (struct cinergyt2 *cinergyt2)
memset(cinergyt2->streambuf, 0, STREAM_URB_COUNT*STREAM_BUF_SIZE);
for (i=0; i<STREAM_URB_COUNT; i++) {
- struct urb *urb;
+ struct urb *urb;
if (!(urb = usb_alloc_urb(0, GFP_ATOMIC))) {
dprintk(1, "failed to alloc consistent stream urbs, bailing out!\n");
@@ -352,9 +345,9 @@ static int cinergyt2_start_feed(struct dvb_demux_feed *dvbdmxfeed)
if (down_interruptible(&cinergyt2->sem))
return -ERESTARTSYS;
-
+
if (cinergyt2->streaming == 0)
- cinergyt2_start_stream_xfer(cinergyt2);
+ cinergyt2_start_stream_xfer(cinergyt2);
cinergyt2->streaming++;
up(&cinergyt2->sem);
@@ -364,7 +357,7 @@ static int cinergyt2_start_feed(struct dvb_demux_feed *dvbdmxfeed)
static int cinergyt2_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
{
struct dvb_demux *demux = dvbdmxfeed->demux;
- struct cinergyt2 *cinergyt2 = demux->priv;
+ struct cinergyt2 *cinergyt2 = demux->priv;
if (down_interruptible(&cinergyt2->sem))
return -ERESTARTSYS;
@@ -497,7 +490,7 @@ static int cinergyt2_open (struct inode *inode, struct file *file)
if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
cinergyt2_sleep(cinergyt2, 0);
schedule_delayed_work(&cinergyt2->query_work, HZ/2);
-}
+ }
up(&cinergyt2->sem);
return 0;
@@ -520,20 +513,20 @@ static int cinergyt2_release (struct inode *inode, struct file *file)
up(&cinergyt2->sem);
return dvb_generic_release(inode, file);
- }
+}
static unsigned int cinergyt2_poll (struct file *file, struct poll_table_struct *wait)
- {
+{
struct dvb_device *dvbdev = file->private_data;
struct cinergyt2 *cinergyt2 = dvbdev->priv;
poll_wait(file, &cinergyt2->poll_wq, wait);
return (POLLIN | POLLRDNORM | POLLPRI);
- }
+}
static int cinergyt2_ioctl (struct inode *inode, struct file *file,
unsigned cmd, unsigned long arg)
- {
+{
struct dvb_device *dvbdev = file->private_data;
struct cinergyt2 *cinergyt2 = dvbdev->priv;
struct dvbt_get_status_msg *stat = &cinergyt2->status;
@@ -574,7 +567,7 @@ static int cinergyt2_ioctl (struct inode *inode, struct file *file,
/* UNC are already converted to host byte order... */
return put_user(stat->uncorrected_block_count,
(__u32 __user *) arg);
-
+
case FE_SET_FRONTEND:
{
struct dvbt_set_parameters_msg *param = &cinergyt2->param;
@@ -611,7 +604,7 @@ static int cinergyt2_ioctl (struct inode *inode, struct file *file,
case FE_GET_FRONTEND:
/**
* trivial to implement (see struct dvbt_get_status_msg).
- * equivalent to FE_READ ioctls, but needs
+ * equivalent to FE_READ ioctls, but needs
* TPS -> linux-dvb parameter set conversion. Feel free
* to implement this and send us a patch if you need this
* functionality.
@@ -661,7 +654,7 @@ static int cinergyt2_mmap(struct file *file, struct vm_area_struct *vma)
goto bailout;
}
- vma->vm_flags |= (VM_IO | VM_DONTCOPY);
+ vma->vm_flags |= (VM_IO | VM_DONTCOPY);
vma->vm_file = file;
ret = remap_pfn_range(vma, vma->vm_start,
@@ -700,7 +693,7 @@ static void cinergyt2_query_rc (void *data)
if (down_interruptible(&cinergyt2->sem))
return;
- len = cinergyt2_command(cinergyt2, buf, sizeof(buf),
+ len = cinergyt2_command(cinergyt2, buf, sizeof(buf),
(char *) rc_events, sizeof(rc_events));
for (n=0; len>0 && n<(len/sizeof(rc_events[0])); n++) {
@@ -712,7 +705,7 @@ static void cinergyt2_query_rc (void *data)
/**
* keyrepeat bit. If we would handle this properly
* we would need to emit down events as long the
- * keyrepeat goes, a up event if no further
+ * keyrepeat goes, a up event if no further
* repeat bits occur. Would need a timer to implement
* and no other driver does this, so we simply
* emit the last key up/down sequence again.
@@ -733,7 +726,7 @@ static void cinergyt2_query_rc (void *data)
input_report_key(&cinergyt2->rc_input_dev, cinergyt2->rc_input_event, 1);
input_report_key(&cinergyt2->rc_input_dev, cinergyt2->rc_input_event, 0);
input_sync(&cinergyt2->rc_input_dev);
- }
+ }
}
schedule_delayed_work(&cinergyt2->rc_query_work,
@@ -793,7 +786,7 @@ static int cinergyt2_probe (struct usb_interface *intf,
cinergyt2->udev = interface_to_usbdev(intf);
cinergyt2->param.cmd = CINERGYT2_EP1_SET_TUNER_PARAMETERS;
-
+
if (cinergyt2_alloc_stream_urbs (cinergyt2) < 0) {
dprintk(1, "unable to allocate stream urbs\n");
kfree(cinergyt2);
@@ -808,8 +801,8 @@ static int cinergyt2_probe (struct usb_interface *intf,
cinergyt2->demux.start_feed = cinergyt2_start_feed;
cinergyt2->demux.stop_feed = cinergyt2_stop_feed;
cinergyt2->demux.dmx.capabilities = DMX_TS_FILTERING |
- DMX_SECTION_FILTERING |
- DMX_MEMORY_BASED_FILTERING;
+ DMX_SECTION_FILTERING |
+ DMX_MEMORY_BASED_FILTERING;
if ((err = dvb_dmx_init(&cinergyt2->demux)) < 0) {
dprintk(1, "dvb_dmx_init() failed (err = %d)\n", err);
@@ -833,7 +826,7 @@ static int cinergyt2_probe (struct usb_interface *intf,
DVB_DEVICE_FRONTEND);
#ifdef ENABLE_RC
- init_input_dev(&cinergyt2->rc_input_dev);
+ init_input_dev(&cinergyt2->rc_input_dev);
cinergyt2->rc_input_dev.evbit[0] = BIT(EV_KEY);
cinergyt2->rc_input_dev.keycodesize = sizeof(unsigned char);
@@ -846,7 +839,7 @@ static int cinergyt2_probe (struct usb_interface *intf,
input_register_device(&cinergyt2->rc_input_dev);
cinergyt2->rc_input_event = KEY_MAX;
-
+
INIT_WORK(&cinergyt2->rc_query_work, cinergyt2_query_rc, cinergyt2);
schedule_delayed_work(&cinergyt2->rc_query_work, HZ/2);
#endif
@@ -878,7 +871,6 @@ static void cinergyt2_disconnect (struct usb_interface *intf)
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);
@@ -901,7 +893,7 @@ static int cinergyt2_suspend (struct usb_interface *intf, u32 state)
#endif
cancel_delayed_work(&cinergyt2->query_work);
if (cinergyt2->streaming)
- cinergyt2_stop_stream_xfer(cinergyt2);
+ cinergyt2_stop_stream_xfer(cinergyt2);
flush_scheduled_work();
cinergyt2_sleep(cinergyt2, 1);
}
@@ -922,7 +914,7 @@ static int cinergyt2_resume (struct usb_interface *intf)
cinergyt2_sleep(cinergyt2, 0);
cinergyt2_command(cinergyt2, (char *) param, sizeof(*param), NULL, 0);
if (cinergyt2->streaming)
- cinergyt2_start_stream_xfer(cinergyt2);
+ cinergyt2_start_stream_xfer(cinergyt2);
schedule_delayed_work(&cinergyt2->query_work, HZ/2);
}
@@ -941,13 +933,13 @@ static const struct usb_device_id cinergyt2_table [] __devinitdata = {
MODULE_DEVICE_TABLE(usb, cinergyt2_table);
static struct usb_driver cinergyt2_driver = {
- .owner = THIS_MODULE,
+ .owner = THIS_MODULE,
.name = "cinergyT2",
- .probe = cinergyt2_probe,
- .disconnect = cinergyt2_disconnect,
+ .probe = cinergyt2_probe,
+ .disconnect = cinergyt2_disconnect,
.suspend = cinergyt2_suspend,
.resume = cinergyt2_resume,
- .id_table = cinergyt2_table
+ .id_table = cinergyt2_table
};
static int __init cinergyt2_init (void)
diff --git a/drivers/media/dvb/dibusb/Kconfig b/drivers/media/dvb/dibusb/Kconfig
index 1352ceba82bdc..74dfc73ae5b01 100644
--- a/drivers/media/dvb/dibusb/Kconfig
+++ b/drivers/media/dvb/dibusb/Kconfig
@@ -13,7 +13,7 @@ config DVB_DIBUSB
TwinhanDTV USB-Ter (VP7041)
TwinhanDTV Magic Box (VP7041e)
- KWorld V-Stream XPERT DTV - DVB-T USB
+ KWorld/JetWay/ADSTech V-Stream XPERT DTV - DVB-T USB1.1 and USB2.0
Hama DVB-T USB-Box
DiBcom reference devices (non-public)
Ultima Electronic/Artec T1 USB TVBOX
@@ -23,6 +23,7 @@ config DVB_DIBUSB
Artec T1 USB1.1 and USB2.0 boxes
Yakumo/Typhoon DVB-T USB2.0
Hanftek UMT-010 USB2.0
+ Hauppauge WinTV NOVA-T USB2
The VP7041 seems to be identical to "CTS Portable" (Chinese
Television System).
diff --git a/drivers/media/dvb/dibusb/Makefile b/drivers/media/dvb/dibusb/Makefile
index a0319f8cbeaea..e941c508624ef 100644
--- a/drivers/media/dvb/dibusb/Makefile
+++ b/drivers/media/dvb/dibusb/Makefile
@@ -4,7 +4,7 @@ dvb-dibusb-objs = dvb-dibusb-core.o \
dvb-dibusb-firmware.o \
dvb-dibusb-remote.o \
dvb-dibusb-usb.o \
- dvb-dibusb-pid.o
+ dvb-fe-dtt200u.o
obj-$(CONFIG_DVB_DIBUSB) += dvb-dibusb.o
diff --git a/drivers/media/dvb/dibusb/dvb-dibusb-core.c b/drivers/media/dvb/dibusb/dvb-dibusb-core.c
index 503ca57c11986..26235f9247e45 100644
--- a/drivers/media/dvb/dibusb/dvb-dibusb-core.c
+++ b/drivers/media/dvb/dibusb/dvb-dibusb-core.c
@@ -42,11 +42,16 @@ static int pid_parse;
module_param(pid_parse, int, 0644);
MODULE_PARM_DESC(pid_parse, "enable pid parsing (filtering) when running at USB2.0");
-static int rc_query_interval;
+static int rc_query_interval = 100;
module_param(rc_query_interval, int, 0644);
MODULE_PARM_DESC(rc_query_interval, "interval in msecs for remote control query (default: 100; min: 40)");
+static int rc_key_repeat_count = 2;
+module_param(rc_key_repeat_count, int, 0644);
+MODULE_PARM_DESC(rc_key_repeat_count, "how many key repeats will be dropped before passing the key event again (default: 2)");
+
/* Vendor IDs */
+#define USB_VID_ADSTECH 0x06e1
#define USB_VID_ANCHOR 0x0547
#define USB_VID_AVERMEDIA 0x14aa
#define USB_VID_COMPRO 0x185b
@@ -55,13 +60,16 @@ MODULE_PARM_DESC(rc_query_interval, "interval in msecs for remote control query
#define USB_VID_DIBCOM 0x10b8
#define USB_VID_EMPIA 0xeb1a
#define USB_VID_GRANDTEC 0x5032
-#define USB_VID_HYPER_PALTEK 0x1025
#define USB_VID_HANFTEK 0x15f4
+#define USB_VID_HAUPPAUGE 0x2040
+#define USB_VID_HYPER_PALTEK 0x1025
#define USB_VID_IMC_NETWORKS 0x13d3
#define USB_VID_TWINHAN 0x1822
#define USB_VID_ULTIMA_ELECTRONIC 0x05d8
/* Product IDs */
+#define USB_PID_ADSTECH_USB2_COLD 0xa333
+#define USB_PID_ADSTECH_USB2_WARM 0xa334
#define USB_PID_AVERMEDIA_DVBT_USB_COLD 0x0001
#define USB_PID_AVERMEDIA_DVBT_USB_WARM 0x0002
#define USB_PID_COMPRO_DVBU2000_COLD 0xd000
@@ -90,9 +98,11 @@ MODULE_PARM_DESC(rc_query_interval, "interval in msecs for remote control query
#define USB_PID_UNK_HYPER_PALTEK_COLD 0x005e
#define USB_PID_UNK_HYPER_PALTEK_WARM 0x005f
#define USB_PID_HANFTEK_UMT_010_COLD 0x0001
-#define USB_PID_HANFTEK_UMT_010_WARM 0x0025
+#define USB_PID_HANFTEK_UMT_010_WARM 0x0015
#define USB_PID_YAKUMO_DTT200U_COLD 0x0201
#define USB_PID_YAKUMO_DTT200U_WARM 0x0301
+#define USB_PID_WINTV_NOVA_T_USB2_COLD 0x9300
+#define USB_PID_WINTV_NOVA_T_USB2_WARM 0x9301
/* USB Driver stuff
* table of devices that this driver is working with
@@ -109,10 +119,6 @@ static struct usb_device_id dib_table [] = {
/* 00 */ { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_DVBT_USB_COLD)},
/* 01 */ { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_DVBT_USB_WARM)},
/* 02 */ { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_YAKUMO_DTT200U_COLD) },
-
-/* the following device is actually not supported, but when loading the
- * correct firmware (ie. its usb ids will change) everything works fine then
- */
/* 03 */ { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_YAKUMO_DTT200U_WARM) },
/* 04 */ { USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_DVBU2000_COLD) },
@@ -143,16 +149,20 @@ static struct usb_device_id dib_table [] = {
/* 28 */ { USB_DEVICE(USB_VID_HANFTEK, USB_PID_HANFTEK_UMT_010_COLD) },
/* 29 */ { USB_DEVICE(USB_VID_HANFTEK, USB_PID_HANFTEK_UMT_010_WARM) },
+/* 30 */ { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_WINTV_NOVA_T_USB2_COLD) },
+/* 31 */ { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_WINTV_NOVA_T_USB2_WARM) },
+/* 32 */ { USB_DEVICE(USB_VID_ADSTECH, USB_PID_ADSTECH_USB2_COLD) },
+/* 33 */ { USB_DEVICE(USB_VID_ADSTECH, USB_PID_ADSTECH_USB2_WARM) },
/*
* activate the following define when you have one of the devices and want to
* build it from build-2.6 in dvb-kernel
*/
-// #define CONFIG_DVB_DIBUSB_MISDESIGNED_DEVICES
+// #define CONFIG_DVB_DIBUSB_MISDESIGNED_DEVICES
#ifdef CONFIG_DVB_DIBUSB_MISDESIGNED_DEVICES
-/* 30 */ { USB_DEVICE(USB_VID_ANCHOR, USB_PID_ULTIMA_TVBOX_ANCHOR_COLD) },
-/* 31 */ { USB_DEVICE(USB_VID_CYPRESS, USB_PID_ULTIMA_TVBOX_USB2_FX_COLD) },
-/* 32 */ { USB_DEVICE(USB_VID_ANCHOR, USB_PID_ULTIMA_TVBOX_USB2_FX_WARM) },
-/* 33 */ { USB_DEVICE(USB_VID_ANCHOR, USB_PID_DIBCOM_ANCHOR_2135_COLD) },
+/* 34 */ { USB_DEVICE(USB_VID_ANCHOR, USB_PID_ULTIMA_TVBOX_ANCHOR_COLD) },
+/* 35 */ { USB_DEVICE(USB_VID_CYPRESS, USB_PID_ULTIMA_TVBOX_USB2_FX_COLD) },
+/* 36 */ { USB_DEVICE(USB_VID_ANCHOR, USB_PID_ULTIMA_TVBOX_USB2_FX_WARM) },
+/* 37 */ { USB_DEVICE(USB_VID_ANCHOR, USB_PID_DIBCOM_ANCHOR_2135_COLD) },
#endif
{ } /* Terminating entry */
};
@@ -193,13 +203,17 @@ static struct dibusb_demod dibusb_demod[] = {
254,
{ 0xf, 0 },
},
+ { DTT200U_FE,
+ 8,
+ { 0xff,0 }, /* there is no i2c bus in this device */
+ }
};
static struct dibusb_device_class dibusb_device_classes[] = {
{ .id = DIBUSB1_1, .usb_ctrl = &dibusb_usb_ctrl[0],
.firmware = "dvb-dibusb-5.0.0.11.fw",
.pipe_cmd = 0x01, .pipe_data = 0x02,
- .urb_count = 3, .urb_buffer_size = 4096,
+ .urb_count = 7, .urb_buffer_size = 4096,
DIBUSB_RC_NEC_PROTOCOL,
&dibusb_demod[DIBUSB_DIB3000MB],
&dibusb_tuner[DIBUSB_TUNER_CABLE_THOMSON],
@@ -207,7 +221,7 @@ static struct dibusb_device_class dibusb_device_classes[] = {
{ DIBUSB1_1_AN2235, &dibusb_usb_ctrl[1],
"dvb-dibusb-an2235-1.fw",
0x01, 0x02,
- 3, 4096,
+ 7, 4096,
DIBUSB_RC_NEC_PROTOCOL,
&dibusb_demod[DIBUSB_DIB3000MB],
&dibusb_tuner[DIBUSB_TUNER_CABLE_THOMSON],
@@ -215,20 +229,43 @@ static struct dibusb_device_class dibusb_device_classes[] = {
{ DIBUSB2_0,&dibusb_usb_ctrl[2],
"dvb-dibusb-6.0.0.5.fw",
0x01, 0x06,
- 3, 188*210,
+ 7, 4096,
DIBUSB_RC_NEC_PROTOCOL,
&dibusb_demod[DIBUSB_DIB3000MC],
&dibusb_tuner[DIBUSB_TUNER_COFDM_PANASONIC_ENV57H1XD5],
},
{ UMT2_0, &dibusb_usb_ctrl[2],
- "dvb-dibusb-umt-1.fw",
- 0x01, 0x02,
- 15, 188*21,
+ "dvb-dibusb-umt-2.fw",
+ 0x01, 0x06,
+ 20, 512,
DIBUSB_RC_NO,
&dibusb_demod[DIBUSB_MT352],
-// &dibusb_tuner[DIBUSB_TUNER_COFDM_PANASONIC_ENV77H11D5],
&dibusb_tuner[DIBUSB_TUNER_CABLE_LG_TDTP_E102P],
},
+ { DIBUSB2_0B,&dibusb_usb_ctrl[2],
+ "dvb-dibusb-adstech-usb2-1.fw",
+ 0x01, 0x06,
+ 7, 4096,
+ DIBUSB_RC_NEC_PROTOCOL,
+ &dibusb_demod[DIBUSB_DIB3000MB],
+ &dibusb_tuner[DIBUSB_TUNER_CABLE_THOMSON],
+ },
+ { NOVAT_USB2,&dibusb_usb_ctrl[2],
+ "dvb-dibusb-nova-t-1.fw",
+ 0x01, 0x06,
+ 7, 4096,
+ DIBUSB_RC_HAUPPAUGE_PROTO,
+ &dibusb_demod[DIBUSB_DIB3000MC],
+ &dibusb_tuner[DIBUSB_TUNER_COFDM_PANASONIC_ENV57H1XD5],
+ },
+ { DTT200U,&dibusb_usb_ctrl[2],
+ "dvb-dtt200u-1.fw",
+ 0x01, 0x02,
+ 7, 4096,
+ DIBUSB_RC_NO,
+ &dibusb_demod[DTT200U_FE],
+ NULL, /* no explicit tuner/pll-programming necessary (it has the ENV57H1XD5) */
+ },
};
static struct dibusb_usb_device dibusb_devices[] = {
@@ -287,30 +324,40 @@ static struct dibusb_usb_device dibusb_devices[] = {
{ &dib_table[27], NULL },
{ NULL },
},
- { "AVermedia/Yakumo/Hama/Typhoon DVB-T USB2.0",
- &dibusb_device_classes[UMT2_0],
+ { "Hauppauge WinTV NOVA-T USB2",
+ &dibusb_device_classes[NOVAT_USB2],
+ { &dib_table[30], NULL },
+ { &dib_table[31], NULL },
+ },
+ { "DTT200U (Yakumo/Hama/Typhoon) DVB-T USB2.0",
+ &dibusb_device_classes[DTT200U],
{ &dib_table[2], NULL },
- { NULL },
+ { &dib_table[3], NULL },
},
{ "Hanftek UMT-010 DVB-T USB2.0",
&dibusb_device_classes[UMT2_0],
{ &dib_table[28], NULL },
{ &dib_table[29], NULL },
},
+ { "KWorld/ADSTech Instant DVB-T USB 2.0",
+ &dibusb_device_classes[DIBUSB2_0B],
+ { &dib_table[32], NULL },
+ { &dib_table[33], NULL }, /* device ID with default DIBUSB2_0-firmware */
+ },
#ifdef CONFIG_DVB_DIBUSB_MISDESIGNED_DEVICES
{ "Artec T1 USB1.1 TVBOX with AN2235 (misdesigned)",
&dibusb_device_classes[DIBUSB1_1_AN2235],
- { &dib_table[30], NULL },
+ { &dib_table[34], NULL },
{ NULL },
},
{ "Artec T1 USB2.0 TVBOX with FX2 IDs (misdesigned, please report the warm ID)",
- &dibusb_device_classes[DIBUSB2_0],
- { &dib_table[31], NULL },
- { &dib_table[32], NULL }, /* undefined, it could be that the device will get another USB ID in warm state */
+ &dibusb_device_classes[DTT200U],
+ { &dib_table[35], NULL },
+ { &dib_table[36], NULL }, /* undefined, it could be that the device will get another USB ID in warm state */
},
{ "DiBcom USB1.1 DVB-T reference design (MOD3000) with AN2135 default IDs",
&dibusb_device_classes[DIBUSB1_1],
- { &dib_table[33], NULL },
+ { &dib_table[37], NULL },
{ NULL },
},
#endif
@@ -322,7 +369,6 @@ static int dibusb_exit(struct usb_dibusb *dib)
dibusb_remote_exit(dib);
dibusb_fe_exit(dib);
dibusb_i2c_exit(dib);
- dibusb_pid_list_exit(dib);
dibusb_dvb_exit(dib);
dibusb_urb_exit(dib);
deb_info("init_state should be zero now: %x\n",dib->init_state);
@@ -341,7 +387,6 @@ static int dibusb_init(struct usb_dibusb *dib)
if ((ret = dibusb_urb_init(dib)) ||
(ret = dibusb_dvb_init(dib)) ||
- (ret = dibusb_pid_list_init(dib)) ||
(ret = dibusb_i2c_init(dib))) {
dibusb_exit(dib);
return ret;
@@ -356,30 +401,62 @@ static int dibusb_init(struct usb_dibusb *dib)
return 0;
}
+static struct dibusb_usb_device * dibusb_device_class_quirk(struct usb_device *udev, struct dibusb_usb_device *dev)
+{
+ int i;
+
+ /* Quirk for the Kworld/ADSTech Instant USB2.0 device. It has the same USB
+ * IDs like the USB1.1 KWorld after loading the firmware. Which is a bad
+ * idea and make this quirk necessary.
+ */
+ if (dev->dev_cl->id == DIBUSB1_1 && udev->speed == USB_SPEED_HIGH) {
+ info("this seems to be the Kworld/ADSTech Instant USB2.0 device or equal.");
+ for (i = 0; i < sizeof(dibusb_devices)/sizeof(struct dibusb_usb_device); i++) {
+ if (dibusb_devices[i].dev_cl->id == DIBUSB2_0B) {
+ dev = &dibusb_devices[i];
+ break;
+ }
+ }
+ }
+
+ return dev;
+}
+
static struct dibusb_usb_device * dibusb_find_device (struct usb_device *udev,int *cold)
{
int i,j;
+ struct dibusb_usb_device *dev = NULL;
*cold = -1;
+
for (i = 0; i < sizeof(dibusb_devices)/sizeof(struct dibusb_usb_device); i++) {
for (j = 0; j < DIBUSB_ID_MAX_NUM && dibusb_devices[i].cold_ids[j] != NULL; j++) {
deb_info("check for cold %x %x\n",dibusb_devices[i].cold_ids[j]->idVendor, dibusb_devices[i].cold_ids[j]->idProduct);
if (dibusb_devices[i].cold_ids[j]->idVendor == le16_to_cpu(udev->descriptor.idVendor) &&
dibusb_devices[i].cold_ids[j]->idProduct == le16_to_cpu(udev->descriptor.idProduct)) {
*cold = 1;
- return &dibusb_devices[i];
+ dev = &dibusb_devices[i];
+ break;
}
}
+ if (dev != NULL)
+ break;
+
for (j = 0; j < DIBUSB_ID_MAX_NUM && dibusb_devices[i].warm_ids[j] != NULL; j++) {
deb_info("check for warm %x %x\n",dibusb_devices[i].warm_ids[j]->idVendor, dibusb_devices[i].warm_ids[j]->idProduct);
if (dibusb_devices[i].warm_ids[j]->idVendor == le16_to_cpu(udev->descriptor.idVendor) &&
dibusb_devices[i].warm_ids[j]->idProduct == le16_to_cpu(udev->descriptor.idProduct)) {
*cold = 0;
- return &dibusb_devices[i];
+ dev = &dibusb_devices[i];
+ break;
}
}
}
- return NULL;
+
+ if (dev != NULL)
+ dev = dibusb_device_class_quirk(udev,dev);
+
+ return dev;
}
/*
@@ -418,6 +495,7 @@ static int dibusb_probe(struct usb_interface *intf,
/* store parameters to structures */
dib->rc_query_interval = rc_query_interval;
dib->pid_parse = pid_parse;
+ dib->rc_key_repeat_count = rc_key_repeat_count;
usb_set_intfdata(intf, dib);
@@ -446,7 +524,7 @@ static void dibusb_disconnect(struct usb_interface *intf)
}
/* usb specific object needed to register this driver with the usb subsystem */
-struct usb_driver dibusb_driver = {
+static struct usb_driver dibusb_driver = {
.owner = THIS_MODULE,
.name = DRIVER_DESC,
.probe = dibusb_probe,
diff --git a/drivers/media/dvb/dibusb/dvb-dibusb-dvb.c b/drivers/media/dvb/dibusb/dvb-dibusb-dvb.c
index d7dd6e747c5d4..04e54ec093f0b 100644
--- a/drivers/media/dvb/dibusb/dvb-dibusb-dvb.c
+++ b/drivers/media/dvb/dibusb/dvb-dibusb-dvb.c
@@ -22,46 +22,34 @@ static u32 urb_compl_count;
void dibusb_urb_complete(struct urb *urb, struct pt_regs *ptregs)
{
struct usb_dibusb *dib = urb->context;
- int ret;
deb_ts("urb complete feedcount: %d, status: %d, length: %d\n",dib->feedcount,urb->status,
urb->actual_length);
urb_compl_count++;
- if (urb_compl_count % 500 == 0)
+ if (urb_compl_count % 1000 == 0)
deb_info("%d urbs completed so far.\n",urb_compl_count);
switch (urb->status) {
case 0: /* success */
case -ETIMEDOUT: /* NAK */
break;
- case -ECONNRESET: /* unlink */
+ case -ECONNRESET: /* kill */
case -ENOENT:
case -ESHUTDOWN:
return;
default: /* error */
- warn("urb completition error %d.", urb->status);
+ deb_ts("urb completition error %d.", urb->status);
+ break;
}
- if (dib->feedcount > 0) {
- deb_ts("URB return len: %d\n",urb->actual_length);
- if (urb->actual_length % 188)
- deb_ts("TS Packets: %d, %d\n", urb->actual_length/188,urb->actual_length % 188);
-
- /* Francois recommends to drop not full-filled packets, even if they may
- * contain valid TS packets, at least for USB1.1
- *
- * if (urb->actual_length == dib->dibdev->parm->default_size && dib->dvb_is_ready) */
+ if (dib->feedcount > 0 && urb->actual_length > 0) {
if (dib->init_state & DIBUSB_STATE_DVB)
dvb_dmx_swfilter(&dib->demux, (u8*) urb->transfer_buffer,urb->actual_length);
- else
- deb_ts("URB dropped because of the "
- "actual_length or !dvb_is_ready (%d).\n",dib->init_state & DIBUSB_STATE_DVB);
} else
deb_ts("URB dropped because of feedcount.\n");
- ret = usb_submit_urb(urb,GFP_ATOMIC);
- deb_ts("urb resubmitted, (%d)\n",ret);
+ usb_submit_urb(urb,GFP_ATOMIC);
}
static int dibusb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff)
@@ -77,7 +65,6 @@ static int dibusb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff)
/*
* stop feed before setting a new pid if there will be no pid anymore
*/
-// if ((dib->dibdev->parm->firmware_bug && dib->feedcount) ||
if (newfeedcount == 0) {
deb_ts("stop feeding\n");
if (dib->xfer_ops.fifo_ctrl != NULL) {
@@ -86,23 +73,20 @@ static int dibusb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff)
return -ENODEV;
}
}
+ dibusb_streaming(dib,0);
}
dib->feedcount = newfeedcount;
- /* get a free pid from the list and activate it on the device
- * specific pid_filter
- */
- if (dib->pid_parse)
- dibusb_ctrl_pid(dib,dvbdmxfeed,onoff);
+ /* activate the pid on the device specific pid_filter */
+ deb_ts("setting pid: %5d %04x at index %d '%s'\n",dvbdmxfeed->pid,dvbdmxfeed->pid,dvbdmxfeed->index,onoff ? "on" : "off");
+ if (dib->pid_parse && dib->xfer_ops.pid_ctrl != NULL)
+ dib->xfer_ops.pid_ctrl(dib->fe,dvbdmxfeed->index,dvbdmxfeed->pid,onoff);
/*
- * start the feed, either if there is the firmware bug or
- * if this was the first pid to set and there is still a pid for
- * reception.
+ * start the feed if this was the first pid to set and there is still a pid
+ * for reception.
*/
-
-// if ((dib->dibdev->parm->firmware_bug)
if (dib->feedcount == onoff && dib->feedcount > 0) {
deb_ts("controlling pid parser\n");
@@ -142,12 +126,8 @@ int dibusb_dvb_init(struct usb_dibusb *dib)
urb_compl_count = 0;
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,4)
- if ((ret = dvb_register_adapter(&dib->adapter, DRIVER_DESC)) < 0) {
-#else
- if ((ret = dvb_register_adapter(&dib->adapter, DRIVER_DESC ,
+ if ((ret = dvb_register_adapter(&dib->adapter, DRIVER_DESC,
THIS_MODULE)) < 0) {
-#endif
deb_info("dvb_register_adapter failed: error %d", ret);
goto err;
}
diff --git a/drivers/media/dvb/dibusb/dvb-dibusb-fe-i2c.c b/drivers/media/dvb/dibusb/dvb-dibusb-fe-i2c.c
index 925c8599faabc..2ed89488c7c49 100644
--- a/drivers/media/dvb/dibusb/dvb-dibusb-fe-i2c.c
+++ b/drivers/media/dvb/dibusb/dvb-dibusb-fe-i2c.c
@@ -1,5 +1,5 @@
/*
- * dvb-dibusb-fe-i2c.c is part of the driver for mobile USB Budget DVB-T devices
+ * dvb-dibusb-fe-i2c.c is part of the driver for mobile USB Budget DVB-T devices
* based on reference design made by DiBcom (http://www.dibcom.fr/)
*
* Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
@@ -8,47 +8,47 @@
*
* This file contains functions for attaching, initializing of an appropriate
* demodulator/frontend. I2C-stuff is also located here.
- *
+ *
*/
#include "dvb-dibusb.h"
#include <linux/usb.h>
-int dibusb_i2c_msg(struct usb_dibusb *dib, u8 addr,
- u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
+static int dibusb_i2c_msg(struct usb_dibusb *dib, u8 addr,
+ u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
{
u8 sndbuf[wlen+4]; /* lead(1) devaddr,direction(1) addr(2) data(wlen) (len(2) (when reading)) */
/* write only ? */
- int wo = (rbuf == NULL || rlen == 0),
+ int wo = (rbuf == NULL || rlen == 0),
len = 2 + wlen + (wo ? 0 : 2);
-
+
sndbuf[0] = wo ? DIBUSB_REQ_I2C_WRITE : DIBUSB_REQ_I2C_READ;
sndbuf[1] = (addr << 1) | (wo ? 0 : 1);
memcpy(&sndbuf[2],wbuf,wlen);
-
+
if (!wo) {
sndbuf[wlen+2] = (rlen >> 8) & 0xff;
sndbuf[wlen+3] = rlen & 0xff;
}
-
+
return dibusb_readwrite_usb(dib,sndbuf,len,rbuf,rlen);
}
/*
* I2C master xfer function
*/
-static int dibusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num)
+static int dibusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg *msg,int num)
{
struct usb_dibusb *dib = i2c_get_adapdata(adap);
int i;
- if (down_interruptible(&dib->i2c_sem) < 0)
+ if (down_interruptible(&dib->i2c_sem) < 0)
return -EAGAIN;
if (num > 2)
warn("more than 2 i2c messages at a time is not handled yet. TODO.");
-
+
for (i = 0; i < num; i++) {
/* write/read request */
if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) {
@@ -56,13 +56,13 @@ static int dibusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num
msg[i+1].buf,msg[i+1].len) < 0)
break;
i++;
- } else
+ } else
if (dibusb_i2c_msg(dib, msg[i].addr, msg[i].buf,msg[i].len,NULL,0) < 0)
break;
}
-
+
up(&dib->i2c_sem);
- return i;
+ return i;
}
static u32 dibusb_i2c_func(struct i2c_adapter *adapter)
@@ -80,16 +80,16 @@ static struct i2c_algorithm dibusb_algo = {
static int dibusb_general_demod_init(struct dvb_frontend *fe);
static u8 dibusb_general_pll_addr(struct dvb_frontend *fe);
static int dibusb_general_pll_init(struct dvb_frontend *fe, u8 pll_buf[5]);
-static int dibusb_general_pll_set(struct dvb_frontend *fe,
+static int dibusb_general_pll_set(struct dvb_frontend *fe,
struct dvb_frontend_parameters* params, u8 pll_buf[5]);
static struct mt352_config mt352_hanftek_umt_010_config = {
.demod_address = 0x1e,
.demod_init = dibusb_general_demod_init,
- .pll_set = dibusb_general_pll_set,
+ .pll_set = dibusb_general_pll_set,
};
-static int dibusb_tuner_quirk(struct usb_dibusb *dib)
+static int dibusb_tuner_quirk(struct usb_dibusb *dib)
{
switch (dib->dibdev->dev_cl->id) {
case DIBUSB1_1: /* some these device have the ENV77H11D5 and some the THOMSON CABLE */
@@ -100,11 +100,11 @@ static int dibusb_tuner_quirk(struct usb_dibusb *dib)
{ .flags = 0, .buf = b, .len = 2 },
{ .flags = I2C_M_RD, .buf = b2, .len = 1},
};
-
+
t = &dibusb_tuner[DIBUSB_TUNER_COFDM_PANASONIC_ENV77H11D5];
-
+
msg[0].addr = msg[1].addr = t->pll_addr;
-
+
if (dib->xfer_ops.tuner_pass_ctrl != NULL)
dib->xfer_ops.tuner_pass_ctrl(dib->fe,1,t->pll_addr);
dibusb_i2c_xfer(&dib->i2c_adap,msg,2);
@@ -117,7 +117,7 @@ static int dibusb_tuner_quirk(struct usb_dibusb *dib)
dib->tuner = t;
info("this device has the Panasonic ENV77H11D5 onboard.");
}
- break;
+ break;
}
default:
break;
@@ -125,34 +125,13 @@ static int dibusb_tuner_quirk(struct usb_dibusb *dib)
return 0;
}
-/* there is a ugly pid_filter in the firmware of the umt devices, it is accessible
- * by i2c address 0x8. Don't know how to deactivate it and how many rows it has.
- */
-static int dibusb_umt_pid_control(struct dvb_frontend *fe, int index, int pid, int onoff)
-{
- struct usb_dibusb *dib = fe->dvb->priv;
- u8 b[3];
- b[0] = index;
- if (onoff) {
- b[1] = (pid >> 8) & 0xff;
- b[2] = pid & 0xff;
- } else {
- b[1] = 0;
- b[2] = 0;
- }
- dibusb_i2c_msg(dib, 0x8, b, 3, NULL,0);
- dibusb_set_streaming_mode(dib,0);
- dibusb_set_streaming_mode(dib,1);
- return 0;
-}
-
int dibusb_fe_init(struct usb_dibusb* dib)
{
struct dib3000_config demod_cfg;
int i;
-
- if (dib->init_state & DIBUSB_STATE_I2C) {
- for (i = 0; i < sizeof(dib->dibdev->dev_cl->demod->i2c_addrs) / sizeof(unsigned char) &&
+
+ if (dib->init_state & DIBUSB_STATE_I2C) {
+ for (i = 0; i < sizeof(dib->dibdev->dev_cl->demod->i2c_addrs) / sizeof(unsigned char) &&
dib->dibdev->dev_cl->demod->i2c_addrs[i] != 0; i++) {
demod_cfg.demod_address = dib->dibdev->dev_cl->demod->i2c_addrs[i];
@@ -160,6 +139,8 @@ int dibusb_fe_init(struct usb_dibusb* dib)
demod_cfg.pll_set = dibusb_general_pll_set;
demod_cfg.pll_init = dibusb_general_pll_init;
+ deb_info("demod id: %d %d\n",dib->dibdev->dev_cl->demod->id,DTT200U_FE);
+
switch (dib->dibdev->dev_cl->demod->id) {
case DIBUSB_DIB3000MB:
dib->fe = dib3000mb_attach(&demod_cfg,&dib->i2c_adap,&dib->xfer_ops);
@@ -170,7 +151,9 @@ int dibusb_fe_init(struct usb_dibusb* dib)
case DIBUSB_MT352:
mt352_hanftek_umt_010_config.demod_address = dib->dibdev->dev_cl->demod->i2c_addrs[i];
dib->fe = mt352_attach(&mt352_hanftek_umt_010_config, &dib->i2c_adap);
- dib->xfer_ops.pid_ctrl = dibusb_umt_pid_control;
+ break;
+ case DTT200U_FE:
+ dib->fe = dtt200u_fe_attach(dib,&dib->xfer_ops);
break;
}
if (dib->fe != NULL) {
@@ -178,19 +161,22 @@ int dibusb_fe_init(struct usb_dibusb* dib)
break;
}
}
- if (dib->fe->ops->sleep != NULL)
- dib->fe_sleep = dib->fe->ops->sleep;
- dib->fe->ops->sleep = dibusb_hw_sleep;
-
- if (dib->fe->ops->init != NULL )
- dib->fe_init = dib->fe->ops->init;
- dib->fe->ops->init = dibusb_hw_wakeup;
-
- /* setting the default tuner */
- dib->tuner = dib->dibdev->dev_cl->tuner;
-
- /* check which tuner is mounted on this device, in case this is unsure */
- dibusb_tuner_quirk(dib);
+ /* if a frontend was found */
+ if (dib->fe != NULL) {
+ if (dib->fe->ops->sleep != NULL)
+ dib->fe_sleep = dib->fe->ops->sleep;
+ dib->fe->ops->sleep = dibusb_hw_sleep;
+
+ if (dib->fe->ops->init != NULL )
+ dib->fe_init = dib->fe->ops->init;
+ dib->fe->ops->init = dibusb_hw_wakeup;
+
+ /* setting the default tuner */
+ dib->tuner = dib->dibdev->dev_cl->tuner;
+
+ /* check which tuner is mounted on this device, in case this is unsure */
+ dibusb_tuner_quirk(dib);
+ }
}
if (dib->fe == NULL) {
err("A frontend driver was not found for device '%s'.",
@@ -205,6 +191,7 @@ int dibusb_fe_init(struct usb_dibusb* dib)
return -ENODEV;
}
}
+
return 0;
}
@@ -227,15 +214,15 @@ int dibusb_i2c_init(struct usb_dibusb *dib)
#else
dib->i2c_adap.class = I2C_CLASS_TV_DIGITAL,
#endif
- dib->i2c_adap.algo = &dibusb_algo;
+ dib->i2c_adap.algo = &dibusb_algo;
dib->i2c_adap.algo_data = NULL;
dib->i2c_adap.id = I2C_ALGO_BIT;
-
+
i2c_set_adapdata(&dib->i2c_adap, dib);
-
+
if ((ret = i2c_add_adapter(&dib->i2c_adap)) < 0)
err("could not add i2c adapter");
-
+
dib->init_state |= DIBUSB_STATE_I2C;
return ret;
@@ -267,21 +254,21 @@ static int thomson_cable_eu_pll_set(struct dvb_frontend_parameters *fep, u8 pllb
pllbuf[0] = (tfreq >> 8) & 0x7f;
pllbuf[1] = tfreq & 0xff;
- pllbuf[2] = 0x8e;
- pllbuf[3] = (vu << 7) | (p2 << 2) | (p1 << 1) | p0;
+ pllbuf[2] = 0x8e;
+ pllbuf[3] = (vu << 7) | (p2 << 2) | (p1 << 1) | p0;
return 0;
}
static int panasonic_cofdm_env57h1xd5_pll_set(struct dvb_frontend_parameters *fep, u8 pllbuf[4])
{
- u32 freq = fep->frequency;
- u32 tfreq = ((freq + 36125000)*6 + 500000) / 1000000;
+ u32 freq_khz = fep->frequency / 1000;
+ u32 tfreq = ((freq_khz + 36125)*6 + 500) / 1000;
u8 TA, T210, R210, ctrl1, cp210, p4321;
- if (freq > 858000000) {
+ if (freq_khz > 858000) {
err("frequency cannot be larger than 858 MHz.");
return -EINVAL;
}
-
+
// contol data 1 : 1 | T/A=1 | T2,T1,T0 = 0,0,0 | R2,R1,R0 = 0,1,0
TA = 1;
T210 = 0;
@@ -289,19 +276,19 @@ static int panasonic_cofdm_env57h1xd5_pll_set(struct dvb_frontend_parameters *fe
ctrl1 = (1 << 7) | (TA << 6) | (T210 << 3) | R210;
// ******** CHARGE PUMP CONFIG vs RF FREQUENCIES *****************
- if (freq < 470000000)
+ if (freq_khz < 470000)
cp210 = 2; // VHF Low and High band ch E12 to E4 to E12
- else if (freq < 526000000)
+ else if (freq_khz < 526000)
cp210 = 4; // UHF band Ch E21 to E27
- else // if (freq < 862000000)
+ else // if (freq < 862000000)
cp210 = 5; // UHF band ch E28 to E69
//********************* BW select *******************************
- if (freq < 153000000)
+ if (freq_khz < 153000)
p4321 = 1; // BW selected for VHF low
- else if (freq < 470000000)
+ else if (freq_khz < 470000)
p4321 = 2; // BW selected for VHF high E5 to E12
- else // if (freq < 862000000)
+ else // if (freq < 862000000)
p4321 = 4; // BW selection for UHF E21 to E69
pllbuf[0] = (tfreq >> 8) & 0xff;
@@ -313,7 +300,7 @@ static int panasonic_cofdm_env57h1xd5_pll_set(struct dvb_frontend_parameters *fe
}
/*
- * 7 6 5 4 3 2 1 0
+ * 7 6 5 4 3 2 1 0
* Address Byte 1 1 0 0 0 MA1 MA0 R/~W=0
*
* Program divider byte 1 0 n14 n13 n12 n11 n10 n9 n8
@@ -321,14 +308,14 @@ static int panasonic_cofdm_env57h1xd5_pll_set(struct dvb_frontend_parameters *fe
*
* Control byte 1 1 T/A=1 T2 T1 T0 R2 R1 R0
* 1 T/A=0 0 0 ATC AL2 AL1 AL0
- *
+ *
* Control byte 2 CP2 CP1 CP0 BS5 BS4 BS3 BS2 BS1
- *
+ *
* MA0/1 = programmable address bits
* R/~W = read/write bit (0 for writing)
* N14-0 = programmable LO frequency
- *
- * T/A = test AGC bit (0 = next 6 bits AGC setting,
+ *
+ * T/A = test AGC bit (0 = next 6 bits AGC setting,
* 1 = next 6 bits test and reference divider ratio settings)
* T2-0 = test bits
* R2-0 = reference divider ratio and programmable frequency step
@@ -341,8 +328,6 @@ static int panasonic_cofdm_env57h1xd5_pll_set(struct dvb_frontend_parameters *fe
* BSn = 0 corresponding port is off, high-impedance state (at power-on)
* BSn = 1 corresponding port is on
*/
-
-
static int panasonic_cofdm_env77h11d5_tda6650_init(struct dvb_frontend *fe, u8 pllbuf[4])
{
pllbuf[0] = 0x0b;
@@ -420,14 +405,14 @@ static int panasonic_cofdm_env77h11d5_tda6650_set (struct dvb_frontend_parameter
}
/*
- * 7 6 5 4 3 2 1 0
+ * 7 6 5 4 3 2 1 0
* Address Byte 1 1 0 0 0 MA1 MA0 R/~W=0
*
* Program divider byte 1 0 n14 n13 n12 n11 n10 n9 n8
* Program divider byte 2 n7 n6 n5 n4 n3 n2 n1 n0
*
* Control byte 1 CP T2 T1 T0 RSA RSB OS
- *
+ *
* Band Switch byte X X X P4 P3 P2 P1 P0
*
* Auxiliary byte ATC AL2 AL1 AL0 0 0 0 0
@@ -437,72 +422,71 @@ static int panasonic_cofdm_env77h11d5_tda6650_set (struct dvb_frontend_parameter
* 0 1 c2 (always valid)
* 1 0 c4
* 1 1 c6
- *
- *
- *
*/
-
-static int lg_tdtp_e102p_tua6034(struct dvb_frontend_parameters* fep, u8 pllbuf[4])
+static int lg_tdtp_e102p_tua6034(struct dvb_frontend_parameters* fep, u8 pllbuf[4])
{
u32 div;
- u8 p3210, p4;
+ u8 p210, p3;
#define TUNER_MUL 62500
div = (fep->frequency + 36125000 + TUNER_MUL / 2) / TUNER_MUL;
+// div = ((fep->frequency/1000 + 36166) * 6) / 1000;
- if (fep->frequency < 174500000)
- p3210 = 1; // not supported by the tdtp_e102p
+ if (fep->frequency < 174500000)
+ p210 = 1; // not supported by the tdtp_e102p
else if (fep->frequency < 230000000) // VHF
- p3210 = 2;
- else
- p3210 = 4;
+ p210 = 2;
+ else
+ p210 = 4;
if (fep->u.ofdm.bandwidth == BANDWIDTH_7_MHZ)
- p4 = 0;
- else
- p4 = 1;
-
+ p3 = 0;
+ else
+ p3 = 1;
+
pllbuf[0] = (div >> 8) & 0x7f;
pllbuf[1] = div & 0xff;
pllbuf[2] = 0xce;
- pllbuf[3] = (p4 << 4) | p3210;
+// pllbuf[2] = 0xcc;
+ pllbuf[3] = (p3 << 3) | p210;
return 0;
}
static int lg_tdtp_e102p_mt352_demod_init(struct dvb_frontend *fe)
{
- static u8 mt352_clock_config[] = { 0x89, 0xb0, 0x2d };
+ static u8 mt352_clock_config[] = { 0x89, 0xb8, 0x2d };
static u8 mt352_reset[] = { 0x50, 0x80 };
static u8 mt352_mclk_ratio[] = { 0x8b, 0x00 };
static u8 mt352_adc_ctl_1_cfg[] = { 0x8E, 0x40 };
- static u8 mt352_agc_cfg[] = { 0x67, 0x14, 0x22 };
- static u8 mt352_sec_agc_cfg[] = { 0x69, 0x00, 0xff, 0xff, 0x00, 0xff, 0x00, 0x40, 0x40 };
+ static u8 mt352_agc_cfg[] = { 0x67, 0x10, 0xa0 };
- static u8 mt352_unk [] = { 0xb5, 0x7a };
+ static u8 mt352_sec_agc_cfg1[] = { 0x6a, 0xff };
+ static u8 mt352_sec_agc_cfg2[] = { 0x6d, 0xff };
+ static u8 mt352_sec_agc_cfg3[] = { 0x70, 0x40 };
+ static u8 mt352_sec_agc_cfg4[] = { 0x7b, 0x03 };
+ static u8 mt352_sec_agc_cfg5[] = { 0x7d, 0x0f };
- static u8 mt352_acq_ctl[] = { 0x53, 0x5f };
- static u8 mt352_input_freq_1[] = { 0x56, 0xf1, 0x05 };
-
-// static u8 mt352_capt_range_cfg[] = { 0x75, 0x32 };
+ static u8 mt352_acq_ctl[] = { 0x53, 0x50 };
+ static u8 mt352_input_freq_1[] = { 0x56, 0x31, 0x06 };
mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config));
udelay(2000);
mt352_write(fe, mt352_reset, sizeof(mt352_reset));
mt352_write(fe, mt352_mclk_ratio, sizeof(mt352_mclk_ratio));
-
+
mt352_write(fe, mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg));
mt352_write(fe, mt352_agc_cfg, sizeof(mt352_agc_cfg));
- mt352_write(fe, mt352_sec_agc_cfg, sizeof(mt352_sec_agc_cfg));
+ mt352_write(fe, mt352_sec_agc_cfg1, sizeof(mt352_sec_agc_cfg1));
+ mt352_write(fe, mt352_sec_agc_cfg2, sizeof(mt352_sec_agc_cfg2));
+ mt352_write(fe, mt352_sec_agc_cfg3, sizeof(mt352_sec_agc_cfg3));
+ mt352_write(fe, mt352_sec_agc_cfg4, sizeof(mt352_sec_agc_cfg4));
+ mt352_write(fe, mt352_sec_agc_cfg5, sizeof(mt352_sec_agc_cfg5));
- mt352_write(fe, mt352_unk, sizeof(mt352_unk));
-
mt352_write(fe, mt352_acq_ctl, sizeof(mt352_acq_ctl));
mt352_write(fe, mt352_input_freq_1, sizeof(mt352_input_freq_1));
-
-// mt352_write(fe, mt352_capt_range_cfg, sizeof(mt352_capt_range_cfg));
return 0;
}
@@ -528,11 +512,11 @@ static u8 dibusb_general_pll_addr(struct dvb_frontend *fe)
static int dibusb_pll_i2c_helper(struct usb_dibusb *dib, u8 pll_buf[5], u8 buf[4])
{
if (pll_buf == NULL) {
- struct i2c_msg msg = {
- .addr = dib->tuner->pll_addr,
- .flags = 0,
- .buf = buf,
- .len = sizeof(buf)
+ struct i2c_msg msg = {
+ .addr = dib->tuner->pll_addr,
+ .flags = 0,
+ .buf = buf,
+ .len = sizeof(buf)
};
if (i2c_transfer (&dib->i2c_adap, &msg, 1) != 1)
return -EIO;
@@ -545,7 +529,7 @@ static int dibusb_pll_i2c_helper(struct usb_dibusb *dib, u8 pll_buf[5], u8 buf[4
return 0;
}
-static int dibusb_general_pll_init(struct dvb_frontend *fe,
+static int dibusb_general_pll_init(struct dvb_frontend *fe,
u8 pll_buf[5])
{
struct usb_dibusb* dib = (struct usb_dibusb*) fe->dvb->priv;
@@ -558,14 +542,14 @@ static int dibusb_general_pll_init(struct dvb_frontend *fe,
default:
break;
}
-
+
if (ret)
return ret;
return dibusb_pll_i2c_helper(dib,pll_buf,buf);
}
-static int dibusb_general_pll_set(struct dvb_frontend *fe,
+static int dibusb_general_pll_set(struct dvb_frontend *fe,
struct dvb_frontend_parameters *fep, u8 pll_buf[5])
{
struct usb_dibusb* dib = (struct usb_dibusb*) fe->dvb->priv;
@@ -573,14 +557,14 @@ static int dibusb_general_pll_set(struct dvb_frontend *fe,
int ret=0;
switch (dib->tuner->id) {
- case DIBUSB_TUNER_CABLE_THOMSON:
- ret = thomson_cable_eu_pll_set(fep, buf);
+ case DIBUSB_TUNER_CABLE_THOMSON:
+ ret = thomson_cable_eu_pll_set(fep, buf);
break;
case DIBUSB_TUNER_COFDM_PANASONIC_ENV57H1XD5:
ret = panasonic_cofdm_env57h1xd5_pll_set(fep, buf);
break;
case DIBUSB_TUNER_CABLE_LG_TDTP_E102P:
- ret = lg_tdtp_e102p_tua6034(fep, buf);
+ ret = lg_tdtp_e102p_tua6034(fep, buf);
break;
case DIBUSB_TUNER_COFDM_PANASONIC_ENV77H11D5:
ret = panasonic_cofdm_env77h11d5_tda6650_set(fep,buf);
@@ -590,9 +574,9 @@ static int dibusb_general_pll_set(struct dvb_frontend *fe,
ret = -ENODEV;
break;
}
-
+
if (ret)
return ret;
-
+
return dibusb_pll_i2c_helper(dib,pll_buf,buf);
}
diff --git a/drivers/media/dvb/dibusb/dvb-dibusb-firmware.c b/drivers/media/dvb/dibusb/dvb-dibusb-firmware.c
index 972548a0c8c4b..504ba47afdf37 100644
--- a/drivers/media/dvb/dibusb/dvb-dibusb-firmware.c
+++ b/drivers/media/dvb/dibusb/dvb-dibusb-firmware.c
@@ -19,7 +19,7 @@
static int dibusb_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 dibusb_loadfirmware(struct usb_device *udev, struct dibusb_usb_device *dibdev)
@@ -30,11 +30,13 @@ int dibusb_loadfirmware(struct usb_device *udev, struct dibusb_usb_device *dibde
int ret = 0,i;
if ((ret = request_firmware(&fw, dibdev->dev_cl->firmware, &udev->dev)) != 0) {
- err("did not find a valid firmware file. (%s) "
+ err("did not find the firmware file. (%s) "
"Please see linux/Documentation/dvb/ for more details on firmware-problems.",
dibdev->dev_cl->firmware);
return ret;
}
+
+ info("downloading firmware from file '%s'.",dibdev->dev_cl->firmware);
p = kmalloc(fw->size,GFP_KERNEL);
if (p != NULL) {
diff --git a/drivers/media/dvb/dibusb/dvb-dibusb-pid.c b/drivers/media/dvb/dibusb/dvb-dibusb-pid.c
deleted file mode 100644
index 91a39541d5242..0000000000000
--- a/drivers/media/dvb/dibusb/dvb-dibusb-pid.c
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * dvb-dibusb-pid.c is part of the driver for mobile USB Budget DVB-T devices
- * based on reference design made by DiBcom (http://www.dibcom.fr/)
- *
- * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
- *
- * see dvb-dibusb-core.c for more copyright details.
- *
- * This file contains functions for initializing and handling the internal
- * pid-list. This pid-list mirrors the information currently stored in the
- * devices pid-list.
- */
-#include "dvb-dibusb.h"
-
-int dibusb_pid_list_init(struct usb_dibusb *dib)
-{
- int i;
- dib->pid_list = kmalloc(sizeof(struct dibusb_pid) * dib->dibdev->dev_cl->demod->pid_filter_count,GFP_KERNEL);
- if (dib->pid_list == NULL)
- return -ENOMEM;
-
- deb_xfer("initializing %d pids for the pid_list.\n",dib->dibdev->dev_cl->demod->pid_filter_count);
-
- dib->pid_list_lock = SPIN_LOCK_UNLOCKED;
- memset(dib->pid_list,0,dib->dibdev->dev_cl->demod->pid_filter_count*(sizeof(struct dibusb_pid)));
- for (i=0; i < dib->dibdev->dev_cl->demod->pid_filter_count; i++) {
- dib->pid_list[i].index = i;
- dib->pid_list[i].pid = 0;
- dib->pid_list[i].active = 0;
- }
-
- dib->init_state |= DIBUSB_STATE_PIDLIST;
- return 0;
-}
-
-void dibusb_pid_list_exit(struct usb_dibusb *dib)
-{
- if (dib->init_state & DIBUSB_STATE_PIDLIST)
- kfree(dib->pid_list);
- dib->init_state &= ~DIBUSB_STATE_PIDLIST;
-}
-
-/* fetch a pid from pid_list and set it on or off */
-int dibusb_ctrl_pid(struct usb_dibusb *dib, struct dvb_demux_feed *dvbdmxfeed , int onoff)
-{
- int i,ret = -1;
- unsigned long flags;
- u16 pid = dvbdmxfeed->pid;
-
- if (onoff) {
- spin_lock_irqsave(&dib->pid_list_lock,flags);
- for (i=0; i < dib->dibdev->dev_cl->demod->pid_filter_count; i++)
- if (!dib->pid_list[i].active) {
- dib->pid_list[i].pid = pid;
- dib->pid_list[i].active = 1;
- ret = i;
- break;
- }
- dvbdmxfeed->priv = &dib->pid_list[ret];
- spin_unlock_irqrestore(&dib->pid_list_lock,flags);
-
- if (dib->xfer_ops.pid_ctrl != NULL)
- dib->xfer_ops.pid_ctrl(dib->fe,dib->pid_list[ret].index,dib->pid_list[ret].pid,1);
- } else {
- struct dibusb_pid *dpid = dvbdmxfeed->priv;
-
- if (dib->xfer_ops.pid_ctrl != NULL)
- dib->xfer_ops.pid_ctrl(dib->fe,dpid->index,0,0);
-
- dpid->pid = 0;
- dpid->active = 0;
- ret = dpid->index;
- }
-
- /* a free pid from the list */
- deb_info("setting pid: %5d %04x at index %d '%s'\n",pid,pid,ret,onoff ? "on" : "off");
-
- return ret;
-}
-
diff --git a/drivers/media/dvb/dibusb/dvb-dibusb-remote.c b/drivers/media/dvb/dibusb/dvb-dibusb-remote.c
index b3b6f24135e4e..9dc8b15517b7c 100644
--- a/drivers/media/dvb/dibusb/dvb-dibusb-remote.c
+++ b/drivers/media/dvb/dibusb/dvb-dibusb-remote.c
@@ -13,7 +13,7 @@
/* Table to map raw key codes to key events. This should not be hard-wired
into the kernel. */
-static const struct { u8 c0, c1, c2; uint32_t key; } rc_keys [] =
+static const struct { u8 c0, c1, c2; uint32_t key; } nec_rc_keys [] =
{
/* Key codes for the little Artec T1/Twinhan/HAMA/ remote. */
{ 0x00, 0xff, 0x16, KEY_POWER },
@@ -83,18 +83,58 @@ static const struct { u8 c0, c1, c2; uint32_t key; } rc_keys [] =
{ 0x86, 0x6b, 0x1b, KEY_RIGHT },
};
-/*
- * Read the remote control and feed the appropriate event.
- * NEC protocol is used for remote controls
- */
-static int dibusb_read_remote_control(struct usb_dibusb *dib)
+/* Hauppauge NOVA-T USB2 keys */
+static const struct { u16 raw; uint32_t key; } haupp_rc_keys [] = {
+ { 0xddf, KEY_GOTO },
+ { 0xdef, KEY_POWER },
+ { 0xce7, KEY_TV },
+ { 0xcc7, KEY_VIDEO },
+ { 0xccf, KEY_AUDIO },
+ { 0xcd7, KEY_MEDIA },
+ { 0xcdf, KEY_EPG },
+ { 0xca7, KEY_UP },
+ { 0xc67, KEY_RADIO },
+ { 0xcb7, KEY_LEFT },
+ { 0xd2f, KEY_OK },
+ { 0xcbf, KEY_RIGHT },
+ { 0xcff, KEY_BACK },
+ { 0xcaf, KEY_DOWN },
+ { 0xc6f, KEY_MENU },
+ { 0xc87, KEY_VOLUMEUP },
+ { 0xc8f, KEY_VOLUMEDOWN },
+ { 0xc97, KEY_CHANNEL },
+ { 0xc7f, KEY_MUTE },
+ { 0xd07, KEY_CHANNELUP },
+ { 0xd0f, KEY_CHANNELDOWN },
+ { 0xdbf, KEY_RECORD },
+ { 0xdb7, KEY_STOP },
+ { 0xd97, KEY_REWIND },
+ { 0xdaf, KEY_PLAY },
+ { 0xda7, KEY_FASTFORWARD },
+ { 0xd27, KEY_LAST }, /* Skip backwards */
+ { 0xd87, KEY_PAUSE },
+ { 0xcf7, KEY_NEXT },
+ { 0xc07, KEY_0 },
+ { 0xc0f, KEY_1 },
+ { 0xc17, KEY_2 },
+ { 0xc1f, KEY_3 },
+ { 0xc27, KEY_4 },
+ { 0xc2f, KEY_5 },
+ { 0xc37, KEY_6 },
+ { 0xc3f, KEY_7 },
+ { 0xc47, KEY_8 },
+ { 0xc4f, KEY_9 },
+ { 0xc57, KEY_KPASTERISK },
+ { 0xc77, KEY_GRAVE }, /* # */
+ { 0xc5f, KEY_RED },
+ { 0xd77, KEY_GREEN },
+ { 0xdc7, KEY_YELLOW },
+ { 0xd4f, KEY_BLUE},
+};
+
+static int dibusb_key2event_nec(struct usb_dibusb *dib,u8 rb[5])
{
- u8 b[1] = { DIBUSB_REQ_POLL_REMOTE }, rb[5];
- int ret;
int i;
- if ((ret = dibusb_readwrite_usb(dib,b,1,rb,5)))
- return ret;
-
switch (rb[0]) {
case DIBUSB_RC_NEC_KEY_PRESSED:
/* rb[1-3] is the actual key, rb[4] is a checksum */
@@ -107,30 +147,100 @@ static int dibusb_read_remote_control(struct usb_dibusb *dib)
}
/* See if we can match the raw key code. */
- for (i = 0; i < sizeof(rc_keys)/sizeof(rc_keys[0]); i++) {
- if (rc_keys[i].c0 == rb[1] &&
- rc_keys[i].c1 == rb[2] &&
- rc_keys[i].c2 == rb[3]) {
- dib->rc_input_event = rc_keys[i].key;
- deb_rc("Translated key 0x%04x\n", dib->rc_input_event);
- /* Signal down and up events for this key. */
- input_report_key(&dib->rc_input_dev, dib->rc_input_event, 1);
- input_report_key(&dib->rc_input_dev, dib->rc_input_event, 0);
- input_sync(&dib->rc_input_dev);
- break;
+ for (i = 0; i < sizeof(nec_rc_keys)/sizeof(nec_rc_keys[0]); i++) {
+ if (nec_rc_keys[i].c0 == rb[1] &&
+ nec_rc_keys[i].c1 == rb[2] &&
+ nec_rc_keys[i].c2 == rb[3]) {
+
+ dib->last_event = nec_rc_keys[i].key;
+ return 1;
}
}
break;
- case DIBUSB_RC_NEC_EMPTY: /* No (more) remote control keys. */
- break;
case DIBUSB_RC_NEC_KEY_REPEATED:
/* rb[1]..rb[4] are always zero.*/
/* Repeats often seem to occur so for the moment just ignore this. */
- deb_rc("Key repeat\n");
+ return 0;
+ case DIBUSB_RC_NEC_EMPTY: /* No (more) remote control keys. */
+ default:
+ break;
+ }
+ return -1;
+}
+
+static int dibusb_key2event_hauppauge(struct usb_dibusb *dib,u8 rb[4])
+{
+ u16 raw;
+ int i,state;
+ switch (rb[0]) {
+ case DIBUSB_RC_HAUPPAUGE_KEY_PRESSED:
+ raw = ((rb[1] & 0x0f) << 8) | rb[2];
+
+ state = !!(rb[1] & 0x40);
+
+ deb_rc("raw key code 0x%02x, 0x%02x, 0x%02x to %04x state: %d\n",rb[1],rb[2],rb[3],raw,state);
+ for (i = 0; i < sizeof(haupp_rc_keys)/sizeof(haupp_rc_keys[0]); i++) {
+ if (haupp_rc_keys[i].raw == raw) {
+ if (dib->last_event == haupp_rc_keys[i].key &&
+ dib->last_state == state) {
+ deb_rc("key repeat\n");
+ return 0;
+ } else {
+ dib->last_event = haupp_rc_keys[i].key;
+ dib->last_state = state;
+ return 1;
+ }
+ }
+ }
+
+ break;
+ case DIBUSB_RC_HAUPPAUGE_KEY_EMPTY:
+ default:
+ break;
+ }
+ return -1;
+}
+
+/*
+ * Read the remote control and feed the appropriate event.
+ * NEC protocol is used for remote controls
+ */
+static int dibusb_read_remote_control(struct usb_dibusb *dib)
+{
+ u8 b[1] = { DIBUSB_REQ_POLL_REMOTE }, rb[5];
+ int ret,event = 0;
+
+ if ((ret = dibusb_readwrite_usb(dib,b,1,rb,5)))
+ return ret;
+
+ switch (dib->dibdev->dev_cl->remote_type) {
+ case DIBUSB_RC_NEC_PROTOCOL:
+ event = dibusb_key2event_nec(dib,rb);
break;
+ case DIBUSB_RC_HAUPPAUGE_PROTO:
+ event = dibusb_key2event_hauppauge(dib,rb);
default:
break;
}
+
+ /* key repeat */
+ if (event == 0)
+ if (++dib->repeat_key_count < dib->rc_key_repeat_count) {
+ deb_rc("key repeat dropped. (%d)\n",dib->repeat_key_count);
+ event = -1; /* skip this key repeat */
+ }
+
+ if (event == 1 || event == 0) {
+ deb_rc("Translated key 0x%04x\n",event);
+
+ /* Signal down and up events for this key. */
+ input_report_key(&dib->rc_input_dev, dib->last_event, 1);
+ input_report_key(&dib->rc_input_dev, dib->last_event, 0);
+ input_sync(&dib->rc_input_dev);
+
+ if (event == 1)
+ dib->repeat_key_count = 0;
+ }
return 0;
}
@@ -161,12 +271,21 @@ int dibusb_remote_init(struct usb_dibusb *dib)
dib->rc_input_dev.keycodemax = KEY_MAX;
dib->rc_input_dev.name = DRIVER_DESC " remote control";
- for (i=0; i<sizeof(rc_keys)/sizeof(rc_keys[0]); i++)
- set_bit(rc_keys[i].key, dib->rc_input_dev.keybit);
+ switch (dib->dibdev->dev_cl->remote_type) {
+ case DIBUSB_RC_NEC_PROTOCOL:
+ for (i=0; i<sizeof(nec_rc_keys)/sizeof(nec_rc_keys[0]); i++)
+ set_bit(nec_rc_keys[i].key, dib->rc_input_dev.keybit);
+ break;
+ case DIBUSB_RC_HAUPPAUGE_PROTO:
+ for (i=0; i<sizeof(haupp_rc_keys)/sizeof(haupp_rc_keys[0]); i++)
+ set_bit(haupp_rc_keys[i].key, dib->rc_input_dev.keybit);
+ break;
+ default:
+ break;
+ }
- input_register_device(&dib->rc_input_dev);
- dib->rc_input_event = KEY_MAX;
+ input_register_device(&dib->rc_input_dev);
INIT_WORK(&dib->rc_query_work, dibusb_remote_query, dib);
diff --git a/drivers/media/dvb/dibusb/dvb-dibusb-usb.c b/drivers/media/dvb/dibusb/dvb-dibusb-usb.c
index 656a0115c101e..642f0596a5ba9 100644
--- a/drivers/media/dvb/dibusb/dvb-dibusb-usb.c
+++ b/drivers/media/dvb/dibusb/dvb-dibusb-usb.c
@@ -1,12 +1,12 @@
/*
- * dvb-dibusb-usb.c is part of the driver for mobile USB Budget DVB-T devices
+ * dvb-dibusb-usb.c is part of the driver for mobile USB Budget DVB-T devices
* based on reference design made by DiBcom (http://www.dibcom.fr/)
*
* Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
*
* see dvb-dibusb-core.c for more copyright details.
*
- * This file contains functions for initializing and handling the
+ * This file contains functions for initializing and handling the
* usb specific stuff.
*/
#include "dvb-dibusb.h"
@@ -25,18 +25,12 @@ int dibusb_readwrite_usb(struct usb_dibusb *dib, u8 *wbuf, u16 wlen, u8 *rbuf,
if ((ret = down_interruptible(&dib->usb_sem)))
return ret;
- if (dib->feedcount &&
- wbuf[0] == DIBUSB_REQ_I2C_WRITE &&
- dib->dibdev->dev_cl->id == DIBUSB1_1)
- deb_err("BUG: writing to i2c, while TS-streaming destroys the stream."
- "(%x reg: %x %x)\n", wbuf[0],wbuf[2],wbuf[3]);
-
debug_dump(wbuf,wlen);
ret = usb_bulk_msg(dib->udev,usb_sndbulkpipe(dib->udev,
dib->dibdev->dev_cl->pipe_cmd), wbuf,wlen,&actlen,
DIBUSB_I2C_TIMEOUT);
-
+
if (ret)
err("bulk message failed: %d (%d/%d)",ret,wlen,actlen);
else
@@ -55,7 +49,7 @@ int dibusb_readwrite_usb(struct usb_dibusb *dib, u8 *wbuf, u16 wlen, u8 *rbuf,
debug_dump(rbuf,actlen);
}
}
-
+
up(&dib->usb_sem);
return ret;
}
@@ -63,15 +57,18 @@ int dibusb_readwrite_usb(struct usb_dibusb *dib, u8 *wbuf, u16 wlen, u8 *rbuf,
/*
* Cypress controls
*/
+int dibusb_write_usb(struct usb_dibusb *dib, u8 *buf, u16 len)
+{
+ return dibusb_readwrite_usb(dib,buf,len,NULL,0);
+}
#if 0
-/*
- * #if 0'ing the following functions as they are not in use _now_,
+/*
+ * #if 0'ing the following functions as they are not in use _now_,
* but probably will be sometime.
*/
-
/*
- * do not use this, just a workaround for a bug,
+ * do not use this, just a workaround for a bug,
* which will hopefully never occur :).
*/
int dibusb_interrupt_read_loop(struct usb_dibusb *dib)
@@ -79,15 +76,10 @@ int dibusb_interrupt_read_loop(struct usb_dibusb *dib)
u8 b[1] = { DIBUSB_REQ_INTR_READ };
return dibusb_write_usb(dib,b,1);
}
-
-#endif
-static int dibusb_write_usb(struct usb_dibusb *dib, u8 *buf, u16 len)
-{
- return dibusb_readwrite_usb(dib,buf,len,NULL,0);
-}
+#endif
/*
- * ioctl for the firmware
+ * ioctl for the firmware
*/
static int dibusb_ioctl_cmd(struct usb_dibusb *dib, u8 cmd, u8 *param, int plen)
{
@@ -111,11 +103,18 @@ int dibusb_hw_wakeup(struct dvb_frontend *fe)
struct usb_dibusb *dib = (struct usb_dibusb *) fe->dvb->priv;
u8 b[1] = { DIBUSB_IOCTL_POWER_WAKEUP };
deb_info("dibusb-device is getting up.\n");
- dibusb_ioctl_cmd(dib,DIBUSB_IOCTL_CMD_POWER_MODE, b,1);
-
+
+ switch (dib->dibdev->dev_cl->id) {
+ case DTT200U:
+ break;
+ default:
+ dibusb_ioctl_cmd(dib,DIBUSB_IOCTL_CMD_POWER_MODE, b,1);
+ break;
+ }
+
if (dib->fe_init)
return dib->fe_init(fe);
-
+
return 0;
}
@@ -124,11 +123,19 @@ int dibusb_hw_sleep(struct dvb_frontend *fe)
struct usb_dibusb *dib = (struct usb_dibusb *) fe->dvb->priv;
u8 b[1] = { DIBUSB_IOCTL_POWER_SLEEP };
deb_info("dibusb-device is going to bed.\n");
- dibusb_ioctl_cmd(dib,DIBUSB_IOCTL_CMD_POWER_MODE, b,1);
-
+ /* workaround, something is wrong, when dibusb 1.1 device are going to bed too late */
+ switch (dib->dibdev->dev_cl->id) {
+ case DIBUSB1_1:
+ case NOVAT_USB2:
+ case DTT200U:
+ break;
+ default:
+ dibusb_ioctl_cmd(dib,DIBUSB_IOCTL_CMD_POWER_MODE, b,1);
+ break;
+ }
if (dib->fe_sleep)
return dib->fe_sleep(fe);
-
+
return 0;
}
@@ -138,18 +145,57 @@ int dibusb_set_streaming_mode(struct usb_dibusb *dib,u8 mode)
return dibusb_readwrite_usb(dib,b,2,NULL,0);
}
+static int dibusb_urb_kill(struct usb_dibusb *dib)
+{
+ int i;
+deb_info("trying to kill urbs\n");
+ if (dib->init_state & DIBUSB_STATE_URB_SUBMIT) {
+ for (i = 0; i < dib->dibdev->dev_cl->urb_count; i++) {
+ deb_info("killing URB no. %d.\n",i);
+
+ /* stop the URB */
+ usb_kill_urb(dib->urb_list[i]);
+ }
+ } else
+ deb_info(" URBs not killed.\n");
+ dib->init_state &= ~DIBUSB_STATE_URB_SUBMIT;
+ return 0;
+}
+
+static int dibusb_urb_submit(struct usb_dibusb *dib)
+{
+ int i,ret;
+ if (dib->init_state & DIBUSB_STATE_URB_INIT) {
+ for (i = 0; i < dib->dibdev->dev_cl->urb_count; i++) {
+ deb_info("submitting URB no. %d\n",i);
+ if ((ret = usb_submit_urb(dib->urb_list[i],GFP_ATOMIC))) {
+ err("could not submit buffer urb no. %d - get them all back\n",i);
+ dibusb_urb_kill(dib);
+ return ret;
+ }
+ dib->init_state |= DIBUSB_STATE_URB_SUBMIT;
+ }
+ }
+ return 0;
+}
+
int dibusb_streaming(struct usb_dibusb *dib,int onoff)
{
+ if (onoff)
+ dibusb_urb_submit(dib);
+ else
+ dibusb_urb_kill(dib);
+
switch (dib->dibdev->dev_cl->id) {
case DIBUSB2_0:
+ case DIBUSB2_0B:
+ case NOVAT_USB2:
+ case UMT2_0:
if (onoff)
return dibusb_ioctl_cmd(dib,DIBUSB_IOCTL_CMD_ENABLE_STREAM,NULL,0);
else
return dibusb_ioctl_cmd(dib,DIBUSB_IOCTL_CMD_DISABLE_STREAM,NULL,0);
break;
- case UMT2_0:
- return dibusb_set_streaming_mode(dib,onoff);
- break;
default:
break;
}
@@ -158,10 +204,10 @@ int dibusb_streaming(struct usb_dibusb *dib,int onoff)
int dibusb_urb_init(struct usb_dibusb *dib)
{
- int ret,i,bufsize,def_pid_parse = 1;
-
+ int i,bufsize,def_pid_parse = 1;
+
/*
- * when reloading the driver w/o replugging the device
+ * when reloading the driver w/o replugging the device
* a timeout occures, this helps
*/
usb_clear_halt(dib->udev,usb_sndbulkpipe(dib->udev,dib->dibdev->dev_cl->pipe_cmd));
@@ -175,7 +221,7 @@ int dibusb_urb_init(struct usb_dibusb *dib)
memset(dib->urb_list,0,dib->dibdev->dev_cl->urb_count*sizeof(struct urb *));
dib->init_state |= DIBUSB_STATE_URB_LIST;
-
+
bufsize = dib->dibdev->dev_cl->urb_count*dib->dibdev->dev_cl->urb_buffer_size;
deb_info("allocate %d bytes as buffersize for all URBs\n",bufsize);
/* allocate the actual buffer for the URBs */
@@ -185,7 +231,7 @@ int dibusb_urb_init(struct usb_dibusb *dib)
}
deb_info("allocation complete\n");
memset(dib->buffer,0,bufsize);
-
+
dib->init_state |= DIBUSB_STATE_URB_BUF;
/* allocate and submit the URBs */
@@ -193,55 +239,49 @@ int dibusb_urb_init(struct usb_dibusb *dib)
if (!(dib->urb_list[i] = usb_alloc_urb(0,GFP_ATOMIC))) {
return -ENOMEM;
}
- deb_info("submitting URB no. %d\n",i);
-
- usb_fill_bulk_urb( dib->urb_list[i], dib->udev,
+
+ usb_fill_bulk_urb( dib->urb_list[i], dib->udev,
usb_rcvbulkpipe(dib->udev,dib->dibdev->dev_cl->pipe_data),
- &dib->buffer[i*dib->dibdev->dev_cl->urb_buffer_size],
- dib->dibdev->dev_cl->urb_buffer_size,
+ &dib->buffer[i*dib->dibdev->dev_cl->urb_buffer_size],
+ dib->dibdev->dev_cl->urb_buffer_size,
dibusb_urb_complete, dib);
-
+
dib->urb_list[i]->transfer_flags = 0;
- if ((ret = usb_submit_urb(dib->urb_list[i],GFP_ATOMIC))) {
- err("could not submit buffer urb no. %d\n",i);
- return ret;
- }
- dib->init_state |= DIBUSB_STATE_URB_SUBMIT;
+ dib->init_state |= DIBUSB_STATE_URB_INIT;
}
/* dib->pid_parse here contains the value of the module parameter */
/* decide if pid parsing can be deactivated:
- * is possible (by speed) and wanted (by user)
+ * is possible (by device type) and wanted (by user)
*/
switch (dib->dibdev->dev_cl->id) {
case DIBUSB2_0:
+ case DIBUSB2_0B:
if (dib->udev->speed == USB_SPEED_HIGH && !dib->pid_parse) {
def_pid_parse = 0;
info("running at HIGH speed, will deliver the complete TS.");
} else
info("will use pid_parsing.");
break;
- default:
+ default:
break;
}
/* from here on it contains the device and user decision */
dib->pid_parse = def_pid_parse;
-
+
return 0;
}
int dibusb_urb_exit(struct usb_dibusb *dib)
{
int i;
+
+ dibusb_urb_kill(dib);
+
if (dib->init_state & DIBUSB_STATE_URB_LIST) {
for (i = 0; i < dib->dibdev->dev_cl->urb_count; i++) {
if (dib->urb_list[i] != NULL) {
- deb_info("killing URB no. %d.\n",i);
-
- /* stop the URBs */
- usb_kill_urb(dib->urb_list[i]);
-
deb_info("freeing URB no. %d.\n",i);
/* free the URBs */
usb_free_urb(dib->urb_list[i]);
@@ -249,7 +289,6 @@ int dibusb_urb_exit(struct usb_dibusb *dib)
}
/* free the urb array */
kfree(dib->urb_list);
- dib->init_state &= ~DIBUSB_STATE_URB_SUBMIT;
dib->init_state &= ~DIBUSB_STATE_URB_LIST;
}
@@ -259,5 +298,6 @@ int dibusb_urb_exit(struct usb_dibusb *dib)
dib->buffer,dib->dma_handle);
dib->init_state &= ~DIBUSB_STATE_URB_BUF;
+ dib->init_state &= ~DIBUSB_STATE_URB_INIT;
return 0;
}
diff --git a/drivers/media/dvb/dibusb/dvb-dibusb.h b/drivers/media/dvb/dibusb/dvb-dibusb.h
index 914a010a13b2d..52cd35dd9d838 100644
--- a/drivers/media/dvb/dibusb/dvb-dibusb.h
+++ b/drivers/media/dvb/dibusb/dvb-dibusb.h
@@ -44,7 +44,7 @@ extern int dvb_dibusb_debug;
/* Version information */
#define DRIVER_VERSION "0.3"
-#define DRIVER_DESC "Driver for DiBcom based USB Budget DVB-T device"
+#define DRIVER_DESC "DiBcom based USB Budget DVB-T device"
#define DRIVER_AUTHOR "Patrick Boettcher, patrick.boettcher@desy.de"
#define deb_info(args...) dprintk(0x01,args)
@@ -55,9 +55,12 @@ extern int dvb_dibusb_debug;
#define deb_rc(args...) dprintk(0x20,args)
/* generic log methods - taken from usb.h */
-#define err(format, arg...) printk(KERN_ERR "%s: " format "\n" , __FILE__ , ## arg)
-#define info(format, arg...) printk(KERN_INFO "%s: " format "\n" , __FILE__ , ## arg)
-#define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n" , __FILE__ , ## arg)
+#undef err
+#define err(format, arg...) printk(KERN_ERR "dvb-dibusb: " format "\n" , ## arg)
+#undef info
+#define info(format, arg...) printk(KERN_INFO "dvb-dibusb: " format "\n" , ## arg)
+#undef warn
+#define warn(format, arg...) printk(KERN_WARNING "dvb-dibusb: " format "\n" , ## arg)
struct dibusb_usb_controller {
const char *name; /* name of the usb controller */
@@ -69,6 +72,9 @@ typedef enum {
DIBUSB1_1_AN2235,
DIBUSB2_0,
UMT2_0,
+ DIBUSB2_0B,
+ NOVAT_USB2,
+ DTT200U,
} dibusb_class_t;
typedef enum {
@@ -82,11 +88,13 @@ typedef enum {
DIBUSB_DIB3000MB = 0,
DIBUSB_DIB3000MC,
DIBUSB_MT352,
+ DTT200U_FE,
} dibusb_demodulator_t;
typedef enum {
DIBUSB_RC_NO = 0,
- DIBUSB_RC_NEC_PROTOCOL = 1,
+ DIBUSB_RC_NEC_PROTOCOL,
+ DIBUSB_RC_HAUPPAUGE_PROTO,
} dibusb_remote_t;
struct dibusb_tuner {
@@ -113,7 +121,7 @@ struct dibusb_device_class {
int pipe_cmd; /* command pipe (read/write) */
int pipe_data; /* data pipe */
-
+
int urb_count; /* number of data URBs to be submitted */
int urb_buffer_size; /* the size of the buffer for each URB */
@@ -149,11 +157,11 @@ struct usb_dibusb {
#define DIBUSB_STATE_INIT 0x000
#define DIBUSB_STATE_URB_LIST 0x001
#define DIBUSB_STATE_URB_BUF 0x002
-#define DIBUSB_STATE_URB_SUBMIT 0x004
+#define DIBUSB_STATE_URB_INIT 0x004
#define DIBUSB_STATE_DVB 0x008
#define DIBUSB_STATE_I2C 0x010
#define DIBUSB_STATE_REMOTE 0x020
-#define DIBUSB_STATE_PIDLIST 0x040
+#define DIBUSB_STATE_URB_SUBMIT 0x040
int init_state;
int feedcount;
@@ -172,10 +180,6 @@ struct usb_dibusb {
struct semaphore usb_sem;
struct semaphore i2c_sem;
- /* pid filtering */
- spinlock_t pid_list_lock;
- struct dibusb_pid *pid_list;
-
/* dvb */
struct dvb_adapter *adapter;
struct dmxdev dmxdev;
@@ -189,7 +193,10 @@ struct usb_dibusb {
/* remote control */
struct input_dev rc_input_dev;
struct work_struct rc_query_work;
- int rc_input_event;
+ int last_event;
+ int last_state; /* for Hauppauge RC protocol */
+ int repeat_key_count;
+ int rc_key_repeat_count; /* module parameter */
/* module parameters */
int pid_parse;
@@ -206,8 +213,6 @@ int dibusb_remote_exit(struct usb_dibusb *dib);
int dibusb_remote_init(struct usb_dibusb *dib);
/* dvb-dibusb-fe-i2c.c */
-int dibusb_i2c_msg(struct usb_dibusb *dib, u8 addr,
- u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen);
int dibusb_fe_init(struct usb_dibusb* dib);
int dibusb_fe_exit(struct usb_dibusb *dib);
int dibusb_i2c_init(struct usb_dibusb *dib);
@@ -221,6 +226,7 @@ int dibusb_dvb_exit(struct usb_dibusb *dib);
/* dvb-dibusb-usb.c */
int dibusb_readwrite_usb(struct usb_dibusb *dib, u8 *wbuf, u16 wlen, u8 *rbuf,
u16 rlen);
+int dibusb_write_usb(struct usb_dibusb *dib, u8 *buf, u16 len);
int dibusb_hw_wakeup(struct dvb_frontend *);
int dibusb_hw_sleep(struct dvb_frontend *);
@@ -230,19 +236,17 @@ int dibusb_streaming(struct usb_dibusb *,int);
int dibusb_urb_init(struct usb_dibusb *);
int dibusb_urb_exit(struct usb_dibusb *);
-/* dvb-dibusb-pid.c */
-int dibusb_pid_list_init(struct usb_dibusb *dib);
-void dibusb_pid_list_exit(struct usb_dibusb *dib);
-int dibusb_ctrl_pid(struct usb_dibusb *dib, struct dvb_demux_feed *dvbdmxfeed , int onoff);
+/* dvb-fe-dtt200u.c */
+struct dvb_frontend* dtt200u_fe_attach(struct usb_dibusb *,struct dib_fe_xfer_ops *);
/* i2c and transfer stuff */
-#define DIBUSB_I2C_TIMEOUT HZ*5
+#define DIBUSB_I2C_TIMEOUT 5000
-/*
+/*
* protocol of all dibusb related devices
*/
-/*
+/*
* bulk msg to/from endpoint 0x01
*
* general structure:
@@ -252,23 +256,23 @@ int dibusb_ctrl_pid(struct usb_dibusb *dib, struct dvb_demux_feed *dvbdmxfeed ,
#define DIBUSB_REQ_START_READ 0x00
#define DIBUSB_REQ_START_DEMOD 0x01
-/*
- * i2c read
+/*
+ * i2c read
* bulk write: 0x02 ((7bit i2c_addr << 1) & 0x01) register_bytes length_word
* bulk read: byte_buffer (length_word bytes)
*/
-#define DIBUSB_REQ_I2C_READ 0x02
-
+#define DIBUSB_REQ_I2C_READ 0x02
+
/*
* i2c write
* bulk write: 0x03 (7bit i2c_addr << 1) register_bytes value_bytes
*/
-#define DIBUSB_REQ_I2C_WRITE 0x03
+#define DIBUSB_REQ_I2C_WRITE 0x03
-/*
- * polling the value of the remote control
+/*
+ * polling the value of the remote control
* bulk write: 0x04
- * bulk read: byte_buffer (5 bytes)
+ * bulk read: byte_buffer (5 bytes)
*
* first byte of byte_buffer shows the status (0x00, 0x01, 0x02)
*/
@@ -278,27 +282,31 @@ int dibusb_ctrl_pid(struct usb_dibusb *dib, struct dvb_demux_feed *dvbdmxfeed ,
#define DIBUSB_RC_NEC_KEY_PRESSED 0x01
#define DIBUSB_RC_NEC_KEY_REPEATED 0x02
+/* additional status values for Hauppauge Remote Control Protocol */
+#define DIBUSB_RC_HAUPPAUGE_KEY_PRESSED 0x01
+#define DIBUSB_RC_HAUPPAUGE_KEY_EMPTY 0x03
+
/* streaming mode:
- * bulk write: 0x05 mode_byte
+ * bulk write: 0x05 mode_byte
*
* mode_byte is mostly 0x00
*/
#define DIBUSB_REQ_SET_STREAMING_MODE 0x05
/* interrupt the internal read loop, when blocking */
-#define DIBUSB_REQ_INTR_READ 0x06
+#define DIBUSB_REQ_INTR_READ 0x06
/* io control
* 0x07 cmd_byte param_bytes
*
* param_bytes can be up to 32 bytes
*
- * cmd_byte function parameter name
+ * cmd_byte function parameter name
* 0x00 power mode
* 0x00 sleep
* 0x01 wakeup
*
- * 0x01 enable streaming
+ * 0x01 enable streaming
* 0x02 disable streaming
*
*
diff --git a/drivers/media/dvb/dibusb/dvb-fe-dtt200u.c b/drivers/media/dvb/dibusb/dvb-fe-dtt200u.c
new file mode 100644
index 0000000000000..1872aa6d200a0
--- /dev/null
+++ b/drivers/media/dvb/dibusb/dvb-fe-dtt200u.c
@@ -0,0 +1,263 @@
+/*
+ * dvb-dtt200u-fe.c is a driver which implements the frontend-part of the
+ * Yakumo/Typhoon/Hama USB2.0 boxes. It is hard-wired to the dibusb-driver as
+ * it uses the usb-transfer functions directly (maybe creating a
+ * generic-dvb-usb-lib for all usb-drivers will be reduce some more code.)
+ *
+ * Copyright (C) 2005 Patrick Boettcher <patrick.boettcher@desy.de>
+ *
+ * see dvb-dibusb-core.c for copyright details.
+ */
+
+/* guessed protocol description (reverse engineered):
+ * read
+ * 00 - USB type 0x02 for usb2.0, 0x01 for usb1.1
+ * 81 - <TS_LOCK> <current frequency divided by 250000>
+ * 82 - crash - do not touch
+ * 83 - crash - do not touch
+ * 84 - remote control
+ * 85 - crash - do not touch (OK, stop testing here)
+ * 88 - locking 2 bytes (0x80 0x40 == no signal, 0x89 0x20 == nice signal)
+ * 89 - noise-to-signal
+ * 8a - unkown 1 byte - signal_strength
+ * 8c - ber ???
+ * 8d - ber
+ * 8e - unc
+ *
+ * write
+ * 02 - bandwidth
+ * 03 - frequency (divided by 250000)
+ * 04 - pid table (index pid(7:0) pid(12:8))
+ * 05 - reset the pid table
+ * 08 - demod transfer enabled or not (FX2 transfer is enabled by default)
+ */
+
+#include "dvb-dibusb.h"
+#include "dvb_frontend.h"
+
+struct dtt200u_fe_state {
+ struct usb_dibusb *dib;
+
+ struct dvb_frontend_parameters fep;
+ struct dvb_frontend frontend;
+};
+
+#define moan(which,what) info("unexpected value in '%s' for cmd '%02x' - please report to linux-dvb@linuxtv.org",which,what)
+
+static int dtt200u_fe_read_status(struct dvb_frontend* fe, fe_status_t *stat)
+{
+ struct dtt200u_fe_state *state = fe->demodulator_priv;
+ u8 bw[1] = { 0x81 };
+ u8 br[3] = { 0 };
+// u8 bdeb[5] = { 0 };
+
+ dibusb_readwrite_usb(state->dib,bw,1,br,3);
+ switch (br[0]) {
+ case 0x01:
+ *stat = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
+ break;
+ case 0x00:
+ *stat = 0;
+ break;
+ default:
+ moan("br[0]",0x81);
+ break;
+ }
+
+// bw[0] = 0x88;
+// dibusb_readwrite_usb(state->dib,bw,1,bdeb,5);
+
+// deb_info("%02x: %02x %02x %02x %02x %02x\n",bw[0],bdeb[0],bdeb[1],bdeb[2],bdeb[3],bdeb[4]);
+
+ return 0;
+}
+static int dtt200u_fe_read_ber(struct dvb_frontend* fe, u32 *ber)
+{
+ struct dtt200u_fe_state *state = fe->demodulator_priv;
+ u8 bw[1] = { 0x8d };
+ *ber = 0;
+ dibusb_readwrite_usb(state->dib,bw,1,(u8*) ber, 3);
+ return 0;
+}
+
+static int dtt200u_fe_read_unc_blocks(struct dvb_frontend* fe, u32 *unc)
+{
+ struct dtt200u_fe_state *state = fe->demodulator_priv;
+ u8 bw[1] = { 0x8c };
+ *unc = 0;
+ dibusb_readwrite_usb(state->dib,bw,1,(u8*) unc, 3);
+ return 0;
+}
+
+static int dtt200u_fe_read_signal_strength(struct dvb_frontend* fe, u16 *strength)
+{
+ struct dtt200u_fe_state *state = fe->demodulator_priv;
+ u8 bw[1] = { 0x8a };
+ u8 b;
+ dibusb_readwrite_usb(state->dib,bw,1,&b, 1);
+ *strength = (b << 8) | b;
+ return 0;
+}
+
+static int dtt200u_fe_read_snr(struct dvb_frontend* fe, u16 *snr)
+{
+ struct dtt200u_fe_state *state = fe->demodulator_priv;
+ u8 bw[1] = { 0x89 };
+ u8 br[1] = { 0 };
+ dibusb_readwrite_usb(state->dib,bw,1,br,1);
+ *snr = ((0xff - br[0]) << 8) | (0xff - br[0]);
+ return 0;
+}
+
+static int dtt200u_fe_init(struct dvb_frontend* fe)
+{
+ struct dtt200u_fe_state *state = fe->demodulator_priv;
+ u8 b[] = { 0x01 };
+ return dibusb_write_usb(state->dib,b,1);
+}
+
+static int dtt200u_fe_sleep(struct dvb_frontend* fe)
+{
+ return dtt200u_fe_init(fe);
+}
+
+static int dtt200u_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
+{
+ tune->min_delay_ms = 1500;
+ tune->step_size = 166667;
+ tune->max_drift = 166667 * 2;
+ return 0;
+}
+
+static int dtt200u_fe_set_frontend(struct dvb_frontend* fe,
+ struct dvb_frontend_parameters *fep)
+{
+ struct dtt200u_fe_state *state = fe->demodulator_priv;
+ u16 freq = fep->frequency / 250000;
+ u8 bw,bwbuf[2] = { 0x03, 0 }, freqbuf[3] = { 0x02, 0, 0 };
+
+ switch (fep->u.ofdm.bandwidth) {
+ case BANDWIDTH_8_MHZ: bw = 8; break;
+ case BANDWIDTH_7_MHZ: bw = 7; break;
+ case BANDWIDTH_6_MHZ: bw = 6; break;
+ case BANDWIDTH_AUTO: return -EOPNOTSUPP;
+ default:
+ return -EINVAL;
+ }
+ deb_info("set_frontend\n");
+
+ bwbuf[1] = bw;
+ dibusb_write_usb(state->dib,bwbuf,2);
+
+ freqbuf[1] = freq & 0xff;
+ freqbuf[2] = (freq >> 8) & 0xff;
+ dibusb_write_usb(state->dib,freqbuf,3);
+
+ memcpy(&state->fep,fep,sizeof(struct dvb_frontend_parameters));
+
+ return 0;
+}
+
+static int dtt200u_fe_get_frontend(struct dvb_frontend* fe,
+ struct dvb_frontend_parameters *fep)
+{
+ struct dtt200u_fe_state *state = fe->demodulator_priv;
+ memcpy(fep,&state->fep,sizeof(struct dvb_frontend_parameters));
+ return 0;
+}
+
+static void dtt200u_fe_release(struct dvb_frontend* fe)
+{
+ struct dtt200u_fe_state *state = (struct dtt200u_fe_state*) fe->demodulator_priv;
+ kfree(state);
+}
+
+static int dtt200u_pid_control(struct dvb_frontend *fe,int index, int pid,int onoff)
+{
+ struct dtt200u_fe_state *state = (struct dtt200u_fe_state*) fe->demodulator_priv;
+ u8 b_pid[4];
+ pid = onoff ? pid : 0;
+
+ b_pid[0] = 0x04;
+ b_pid[1] = index;
+ b_pid[2] = pid & 0xff;
+ b_pid[3] = (pid >> 8) & 0xff;
+
+ dibusb_write_usb(state->dib,b_pid,4);
+ return 0;
+}
+
+static int dtt200u_fifo_control(struct dvb_frontend *fe, int onoff)
+{
+ struct dtt200u_fe_state *state = (struct dtt200u_fe_state*) fe->demodulator_priv;
+ u8 b_streaming[2] = { 0x08, onoff };
+ u8 b_rst_pid[1] = { 0x05 };
+
+ dibusb_write_usb(state->dib,b_streaming,2);
+
+ if (!onoff)
+ dibusb_write_usb(state->dib,b_rst_pid,1);
+ return 0;
+}
+
+static struct dvb_frontend_ops dtt200u_fe_ops;
+
+struct dvb_frontend* dtt200u_fe_attach(struct usb_dibusb *dib, struct dib_fe_xfer_ops *xfer_ops)
+{
+ 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);
+ if (state == NULL)
+ goto error;
+ memset(state,0,sizeof(struct dtt200u_fe_state));
+
+ deb_info("attaching frontend dtt200u\n");
+
+ state->dib = dib;
+
+ state->frontend.ops = &dtt200u_fe_ops;
+ state->frontend.demodulator_priv = state;
+
+ xfer_ops->fifo_ctrl = dtt200u_fifo_control;
+ xfer_ops->pid_ctrl = dtt200u_pid_control;
+
+ goto success;
+error:
+ return NULL;
+success:
+ return &state->frontend;
+}
+
+static struct dvb_frontend_ops dtt200u_fe_ops = {
+ .info = {
+ .name = "DTT200U (Yakumo/Typhoon/Hama) DVB-T",
+ .type = FE_OFDM,
+ .frequency_min = 44250000,
+ .frequency_max = 867250000,
+ .frequency_stepsize = 250000,
+ .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_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
+ FE_CAN_TRANSMISSION_MODE_AUTO |
+ FE_CAN_GUARD_INTERVAL_AUTO |
+ FE_CAN_RECOVER |
+ FE_CAN_HIERARCHY_AUTO,
+ },
+
+ .release = dtt200u_fe_release,
+
+ .init = dtt200u_fe_init,
+ .sleep = dtt200u_fe_sleep,
+
+ .set_frontend = dtt200u_fe_set_frontend,
+ .get_frontend = dtt200u_fe_get_frontend,
+ .get_tune_settings = dtt200u_fe_get_tune_settings,
+
+ .read_status = dtt200u_fe_read_status,
+ .read_ber = dtt200u_fe_read_ber,
+ .read_signal_strength = dtt200u_fe_read_signal_strength,
+ .read_snr = dtt200u_fe_read_snr,
+ .read_ucblocks = dtt200u_fe_read_unc_blocks,
+};
diff --git a/drivers/media/dvb/dvb-core/demux.h b/drivers/media/dvb/dvb-core/demux.h
index 8ff49c0f7a034..fb55eaa5c8e70 100644
--- a/drivers/media/dvb/dvb-core/demux.h
+++ b/drivers/media/dvb/dvb-core/demux.h
@@ -1,8 +1,8 @@
-/*
- * demux.h
+/*
+ * demux.h
*
* Copyright (c) 2002 Convergence GmbH
- *
+ *
* based on code:
* Copyright (c) 2000 Nokia Research Center
* Tampere, FINLAND
@@ -23,56 +23,56 @@
*
*/
-#ifndef __DEMUX_H
-#define __DEMUX_H
+#ifndef __DEMUX_H
+#define __DEMUX_H
#include <linux/types.h>
#include <linux/errno.h>
-#include <linux/list.h>
-#include <linux/time.h>
+#include <linux/list.h>
+#include <linux/time.h>
-/*--------------------------------------------------------------------------*/
-/* Common definitions */
-/*--------------------------------------------------------------------------*/
+/*--------------------------------------------------------------------------*/
+/* Common definitions */
+/*--------------------------------------------------------------------------*/
/*
* DMX_MAX_FILTER_SIZE: Maximum length (in bytes) of a section/PES filter.
- */
+ */
-#ifndef DMX_MAX_FILTER_SIZE
+#ifndef DMX_MAX_FILTER_SIZE
#define DMX_MAX_FILTER_SIZE 18
-#endif
+#endif
/*
* DMX_MAX_SECFEED_SIZE: Maximum length (in bytes) of a private section feed filter.
- */
+ */
-#ifndef DMX_MAX_SECFEED_SIZE
+#ifndef DMX_MAX_SECFEED_SIZE
#define DMX_MAX_SECFEED_SIZE 4096
-#endif
+#endif
/*
- * enum dmx_success: Success codes for the Demux Callback API.
- */
-
-enum dmx_success {
- DMX_OK = 0, /* Received Ok */
- DMX_LENGTH_ERROR, /* Incorrect length */
- DMX_OVERRUN_ERROR, /* Receiver ring buffer overrun */
- DMX_CRC_ERROR, /* Incorrect CRC */
- DMX_FRAME_ERROR, /* Frame alignment error */
- DMX_FIFO_ERROR, /* Receiver FIFO overrun */
- DMX_MISSED_ERROR /* Receiver missed packet */
-} ;
-
-/*--------------------------------------------------------------------------*/
-/* TS packet reception */
+ * enum dmx_success: Success codes for the Demux Callback API.
+ */
+
+enum dmx_success {
+ DMX_OK = 0, /* Received Ok */
+ DMX_LENGTH_ERROR, /* Incorrect length */
+ DMX_OVERRUN_ERROR, /* Receiver ring buffer overrun */
+ DMX_CRC_ERROR, /* Incorrect CRC */
+ DMX_FRAME_ERROR, /* Frame alignment error */
+ DMX_FIFO_ERROR, /* Receiver FIFO overrun */
+ DMX_MISSED_ERROR /* Receiver missed packet */
+} ;
+
+/*--------------------------------------------------------------------------*/
+/* TS packet reception */
/*--------------------------------------------------------------------------*/
/* TS filter type for set() */
-#define TS_PACKET 1 /* send TS packets (188 bytes) to callback (default) */
+#define TS_PACKET 1 /* send TS packets (188 bytes) to callback (default) */
#define TS_PAYLOAD_ONLY 2 /* in case TS_PACKET is set, only send the TS
payload (<=184 bytes per packet) to callback */
#define TS_DECODER 4 /* send stream to built-in decoder (if present) */
@@ -116,38 +116,38 @@ enum dmx_ts_pes
#define DMX_TS_PES_PCR DMX_TS_PES_PCR0
-struct dmx_ts_feed {
+struct dmx_ts_feed {
int is_filtering; /* Set to non-zero when filtering in progress */
struct dmx_demux *parent; /* Back-pointer */
- void *priv; /* Pointer to private data of the API client */
- int (*set) (struct dmx_ts_feed *feed,
+ void *priv; /* Pointer to private data of the API client */
+ int (*set) (struct dmx_ts_feed *feed,
u16 pid,
- int type,
+ int type,
enum dmx_ts_pes pes_type,
- size_t callback_length,
- size_t circular_buffer_size,
- int descramble,
- struct timespec timeout);
- int (*start_filtering) (struct dmx_ts_feed* feed);
- int (*stop_filtering) (struct dmx_ts_feed* feed);
+ size_t callback_length,
+ size_t circular_buffer_size,
+ int descramble,
+ struct timespec timeout);
+ int (*start_filtering) (struct dmx_ts_feed* feed);
+ int (*stop_filtering) (struct dmx_ts_feed* feed);
};
-/*--------------------------------------------------------------------------*/
-/* Section reception */
-/*--------------------------------------------------------------------------*/
+/*--------------------------------------------------------------------------*/
+/* Section reception */
+/*--------------------------------------------------------------------------*/
-struct dmx_section_filter {
- u8 filter_value [DMX_MAX_FILTER_SIZE];
- u8 filter_mask [DMX_MAX_FILTER_SIZE];
- u8 filter_mode [DMX_MAX_FILTER_SIZE];
- struct dmx_section_feed* parent; /* Back-pointer */
- void* priv; /* Pointer to private data of the API client */
+struct dmx_section_filter {
+ u8 filter_value [DMX_MAX_FILTER_SIZE];
+ u8 filter_mask [DMX_MAX_FILTER_SIZE];
+ u8 filter_mode [DMX_MAX_FILTER_SIZE];
+ struct dmx_section_feed* parent; /* Back-pointer */
+ void* priv; /* Pointer to private data of the API client */
};
-struct dmx_section_feed {
- int is_filtering; /* Set to non-zero when filtering in progress */
+struct dmx_section_feed {
+ int is_filtering; /* Set to non-zero when filtering in progress */
struct dmx_demux* parent; /* Back-pointer */
- void* priv; /* Pointer to private data of the API client */
+ void* priv; /* Pointer to private data of the API client */
int check_crc;
u32 crc_val;
@@ -156,42 +156,42 @@ struct dmx_section_feed {
u8 secbuf_base[DMX_MAX_SECFEED_SIZE];
u16 secbufp, seclen, tsfeedp;
- int (*set) (struct dmx_section_feed* feed,
- u16 pid,
- size_t circular_buffer_size,
- int descramble,
- int check_crc);
- int (*allocate_filter) (struct dmx_section_feed* feed,
- struct dmx_section_filter** filter);
- int (*release_filter) (struct dmx_section_feed* feed,
- struct dmx_section_filter* filter);
- int (*start_filtering) (struct dmx_section_feed* feed);
- int (*stop_filtering) (struct dmx_section_feed* feed);
+ int (*set) (struct dmx_section_feed* feed,
+ u16 pid,
+ size_t circular_buffer_size,
+ int descramble,
+ int check_crc);
+ int (*allocate_filter) (struct dmx_section_feed* feed,
+ struct dmx_section_filter** filter);
+ int (*release_filter) (struct dmx_section_feed* feed,
+ struct dmx_section_filter* filter);
+ int (*start_filtering) (struct dmx_section_feed* feed);
+ int (*stop_filtering) (struct dmx_section_feed* feed);
};
-/*--------------------------------------------------------------------------*/
-/* Callback functions */
-/*--------------------------------------------------------------------------*/
+/*--------------------------------------------------------------------------*/
+/* Callback functions */
+/*--------------------------------------------------------------------------*/
-typedef int (*dmx_ts_cb) ( const u8 * buffer1,
+typedef int (*dmx_ts_cb) ( const u8 * buffer1,
size_t buffer1_length,
- const u8 * buffer2,
+ const u8 * buffer2,
size_t buffer2_length,
- struct dmx_ts_feed* source,
- enum dmx_success success);
+ struct dmx_ts_feed* source,
+ enum dmx_success success);
typedef int (*dmx_section_cb) ( const u8 * buffer1,
size_t buffer1_len,
- const u8 * buffer2,
+ const u8 * buffer2,
size_t buffer2_len,
- struct dmx_section_filter * source,
- enum dmx_success success);
+ struct dmx_section_filter * source,
+ enum dmx_success success);
-/*--------------------------------------------------------------------------*/
+/*--------------------------------------------------------------------------*/
/* DVB Front-End */
-/*--------------------------------------------------------------------------*/
+/*--------------------------------------------------------------------------*/
-enum dmx_frontend_source {
+enum dmx_frontend_source {
DMX_MEMORY_FE,
DMX_FRONTEND_0,
DMX_FRONTEND_1,
@@ -201,106 +201,101 @@ enum dmx_frontend_source {
DMX_STREAM_1,
DMX_STREAM_2,
DMX_STREAM_3
-};
+};
-struct dmx_frontend {
- struct list_head connectivity_list; /* List of front-ends that can
- be connected to a particular
- demux */
- void* priv; /* Pointer to private data of the API client */
+struct dmx_frontend {
+ struct list_head connectivity_list; /* List of front-ends that can
+ be connected to a particular
+ demux */
+ void* priv; /* Pointer to private data of the API client */
enum dmx_frontend_source source;
};
-/*--------------------------------------------------------------------------*/
-/* MPEG-2 TS Demux */
-/*--------------------------------------------------------------------------*/
-
-/*
- * Flags OR'ed in the capabilites field of struct dmx_demux.
- */
-
-#define DMX_TS_FILTERING 1
-#define DMX_PES_FILTERING 2
-#define DMX_SECTION_FILTERING 4
-#define DMX_MEMORY_BASED_FILTERING 8 /* write() available */
-#define DMX_CRC_CHECKING 16
-#define DMX_TS_DESCRAMBLING 32
-#define DMX_SECTION_PAYLOAD_DESCRAMBLING 64
-#define DMX_MAC_ADDRESS_DESCRAMBLING 128
-
-/*
- * Demux resource type identifier.
-*/
-
-/*
- * DMX_FE_ENTRY(): Casts elements in the list of registered
+/*--------------------------------------------------------------------------*/
+/* MPEG-2 TS Demux */
+/*--------------------------------------------------------------------------*/
+
+/*
+ * Flags OR'ed in the capabilites field of struct dmx_demux.
+ */
+
+#define DMX_TS_FILTERING 1
+#define DMX_PES_FILTERING 2
+#define DMX_SECTION_FILTERING 4
+#define DMX_MEMORY_BASED_FILTERING 8 /* write() available */
+#define DMX_CRC_CHECKING 16
+#define DMX_TS_DESCRAMBLING 32
+#define DMX_SECTION_PAYLOAD_DESCRAMBLING 64
+#define DMX_MAC_ADDRESS_DESCRAMBLING 128
+
+/*
+ * Demux resource type identifier.
+*/
+
+/*
+ * DMX_FE_ENTRY(): Casts elements in the list of registered
* front-ends from the generic type struct list_head
* to the type * struct dmx_frontend
- *.
+ *.
*/
-#define DMX_FE_ENTRY(list) list_entry(list, struct dmx_frontend, connectivity_list)
+#define DMX_FE_ENTRY(list) list_entry(list, struct dmx_frontend, connectivity_list)
-struct dmx_demux {
- u32 capabilities; /* Bitfield of capability flags */
- struct dmx_frontend* frontend; /* Front-end connected to the demux */
+struct dmx_demux {
+ u32 capabilities; /* Bitfield of capability flags */
+ struct dmx_frontend* frontend; /* Front-end connected to the demux */
struct list_head reg_list; /* List of registered demuxes */
- void* priv; /* Pointer to private data of the API client */
+ void* priv; /* Pointer to private data of the API client */
int users; /* Number of users */
- int (*open) (struct dmx_demux* demux);
- int (*close) (struct dmx_demux* demux);
- int (*write) (struct dmx_demux* demux, const char* buf, size_t count);
- int (*allocate_ts_feed) (struct dmx_demux* demux,
- struct dmx_ts_feed** feed,
- dmx_ts_cb callback);
- int (*release_ts_feed) (struct dmx_demux* demux,
- struct dmx_ts_feed* feed);
- int (*allocate_section_feed) (struct dmx_demux* demux,
- struct dmx_section_feed** feed,
- dmx_section_cb callback);
+ int (*open) (struct dmx_demux* demux);
+ int (*close) (struct dmx_demux* demux);
+ int (*write) (struct dmx_demux* demux, const char* buf, size_t count);
+ int (*allocate_ts_feed) (struct dmx_demux* demux,
+ struct dmx_ts_feed** feed,
+ dmx_ts_cb callback);
+ int (*release_ts_feed) (struct dmx_demux* demux,
+ struct dmx_ts_feed* feed);
+ int (*allocate_section_feed) (struct dmx_demux* demux,
+ struct dmx_section_feed** feed,
+ dmx_section_cb callback);
int (*release_section_feed) (struct dmx_demux* demux,
- struct dmx_section_feed* feed);
- int (*descramble_mac_address) (struct dmx_demux* demux,
- u8* buffer1,
- size_t buffer1_length,
- u8* buffer2,
+ struct dmx_section_feed* feed);
+ int (*descramble_mac_address) (struct dmx_demux* demux,
+ u8* buffer1,
+ size_t buffer1_length,
+ u8* buffer2,
size_t buffer2_length,
- u16 pid);
+ u16 pid);
int (*descramble_section_payload) (struct dmx_demux* demux,
- u8* buffer1,
+ u8* buffer1,
size_t buffer1_length,
u8* buffer2, size_t buffer2_length,
- u16 pid);
- int (*add_frontend) (struct dmx_demux* demux,
- struct dmx_frontend* frontend);
+ u16 pid);
+ int (*add_frontend) (struct dmx_demux* demux,
+ struct dmx_frontend* frontend);
int (*remove_frontend) (struct dmx_demux* demux,
- struct dmx_frontend* frontend);
- struct list_head* (*get_frontends) (struct dmx_demux* demux);
- int (*connect_frontend) (struct dmx_demux* demux,
- struct dmx_frontend* frontend);
- int (*disconnect_frontend) (struct dmx_demux* demux);
+ struct dmx_frontend* frontend);
+ struct list_head* (*get_frontends) (struct dmx_demux* demux);
+ int (*connect_frontend) (struct dmx_demux* demux,
+ struct dmx_frontend* frontend);
+ int (*disconnect_frontend) (struct dmx_demux* demux);
int (*get_pes_pids) (struct dmx_demux* demux, u16 *pids);
int (*get_stc) (struct dmx_demux* demux, unsigned int num,
u64 *stc, unsigned int *base);
-};
+};
-/*--------------------------------------------------------------------------*/
-/* Demux directory */
-/*--------------------------------------------------------------------------*/
+/*--------------------------------------------------------------------------*/
+/* Demux directory */
+/*--------------------------------------------------------------------------*/
-/*
- * DMX_DIR_ENTRY(): Casts elements in the list of registered
+/*
+ * DMX_DIR_ENTRY(): Casts elements in the list of registered
* demuxes from the generic type struct list_head* to the type struct dmx_demux
- *.
- */
+ *.
+ */
#define DMX_DIR_ENTRY(list) list_entry(list, struct dmx_demux, reg_list)
-int dmx_register_demux (struct dmx_demux* demux);
-int dmx_unregister_demux (struct dmx_demux* demux);
-struct list_head* dmx_get_demuxes (void);
-
#endif /* #ifndef __DEMUX_H */
-
diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c
index cdbfb15b78f33..1863f1dfb00c5 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.c
+++ b/drivers/media/dvb/dvb-core/dmxdev.c
@@ -1,5 +1,5 @@
-/*
- * dmxdev.c - DVB demultiplexer device
+/*
+ * dmxdev.c - DVB demultiplexer device
*
* Copyright (C) 2000 Ralph Metzler <ralph@convergence.de>
* & Marcus Metzler <marcus@convergence.de>
@@ -48,7 +48,7 @@ dvb_dmxdev_file_to_filter(struct file *file)
return (struct dmxdev_filter *) file->private_data;
}
-static inline void dvb_dmxdev_buffer_init(struct dmxdev_buffer *buffer)
+static inline void dvb_dmxdev_buffer_init(struct dmxdev_buffer *buffer)
{
buffer->data=NULL;
buffer->size=8192;
@@ -58,7 +58,7 @@ static inline void dvb_dmxdev_buffer_init(struct dmxdev_buffer *buffer)
init_waitqueue_head(&buffer->queue);
}
-static inline int dvb_dmxdev_buffer_write(struct dmxdev_buffer *buf, const u8 *src, int len)
+static inline int dvb_dmxdev_buffer_write(struct dmxdev_buffer *buf, const u8 *src, int len)
{
int split;
int free;
@@ -68,7 +68,7 @@ static inline int dvb_dmxdev_buffer_write(struct dmxdev_buffer *buf, const u8 *s
return 0;
if (!buf->data)
return 0;
-
+
free=buf->pread-buf->pwrite;
split=0;
if (free<=0) {
@@ -97,14 +97,14 @@ static ssize_t dvb_dmxdev_buffer_read(struct dmxdev_buffer *src,
{
unsigned long todo=count;
int split, avail, error;
-
+
if (!src->data)
return 0;
if ((error=src->error)) {
src->pwrite=src->pread;
src->error=0;
- return error;
+ return error;
}
if (non_blocking && (src->pwrite==src->pread))
@@ -122,9 +122,9 @@ static ssize_t dvb_dmxdev_buffer_read(struct dmxdev_buffer *src,
if ((error=src->error)) {
src->pwrite=src->pread;
src->error=0;
- return error;
+ return error;
}
-
+
split=src->size;
avail=src->pwrite - src->pread;
if (avail<0) {
@@ -162,7 +162,7 @@ static struct dmx_frontend * get_fe(struct dmx_demux *demux, int type)
list_for_each(pos, head)
if (DMX_FE_ENTRY(pos)->source==type)
return DMX_FE_ENTRY(pos);
-
+
return NULL;
}
@@ -183,7 +183,7 @@ static int dvb_dvr_open(struct inode *inode, struct file *file)
if (down_interruptible (&dmxdev->mutex))
return -ERESTARTSYS;
-
+
if ((file->f_flags&O_ACCMODE)==O_RDWR) {
if (!(dmxdev->capabilities&DMXDEV_CAP_DUPLEX)) {
up(&dmxdev->mutex);
@@ -203,20 +203,20 @@ static int dvb_dvr_open(struct inode *inode, struct file *file)
if ((file->f_flags&O_ACCMODE)==O_WRONLY) {
dmxdev->dvr_orig_fe=dmxdev->demux->frontend;
-
+
if (!dmxdev->demux->write) {
up(&dmxdev->mutex);
return -EOPNOTSUPP;
}
-
+
front=get_fe(dmxdev->demux, DMX_MEMORY_FE);
-
+
if (!front) {
up(&dmxdev->mutex);
return -EINVAL;
}
- dmxdev->demux->disconnect_frontend(dmxdev->demux);
- dmxdev->demux->connect_frontend(dmxdev->demux, front);
+ dmxdev->demux->disconnect_frontend(dmxdev->demux);
+ dmxdev->demux->connect_frontend(dmxdev->demux, front);
}
up(&dmxdev->mutex);
return 0;
@@ -231,8 +231,8 @@ static int dvb_dvr_release(struct inode *inode, struct file *file)
return -ERESTARTSYS;
if ((file->f_flags&O_ACCMODE)==O_WRONLY) {
- dmxdev->demux->disconnect_frontend(dmxdev->demux);
- dmxdev->demux->connect_frontend(dmxdev->demux,
+ dmxdev->demux->disconnect_frontend(dmxdev->demux);
+ dmxdev->demux->connect_frontend(dmxdev->demux,
dmxdev->dvr_orig_fe);
}
if ((file->f_flags&O_ACCMODE)==O_RDONLY) {
@@ -275,8 +275,8 @@ static ssize_t dvb_dvr_read(struct file *file, char __user *buf, size_t count,
int ret;
//down(&dmxdev->mutex);
- ret= dvb_dmxdev_buffer_read(&dmxdev->dvr_buffer,
- file->f_flags&O_NONBLOCK,
+ ret= dvb_dmxdev_buffer_read(&dmxdev->dvr_buffer,
+ file->f_flags&O_NONBLOCK,
buf, count, ppos);
//up(&dmxdev->mutex);
return ret;
@@ -302,11 +302,10 @@ static int dvb_dmxdev_set_buffer_size(struct dmxdev_filter *dmxdevfilter, unsign
mem=buf->data;
buf->data=NULL;
buf->size=size;
- buf->pwrite=buf->pread=0;
+ buf->pwrite=buf->pread=0;
spin_unlock_irq(&dmxdevfilter->dev->lock);
- if (mem)
- vfree(mem);
-
+ vfree(mem);
+
if (buf->size) {
mem=vmalloc(dmxdevfilter->buffer.size);
if (!mem)
@@ -321,7 +320,7 @@ static int dvb_dmxdev_set_buffer_size(struct dmxdev_filter *dmxdevfilter, unsign
static void dvb_dmxdev_filter_timeout(unsigned long data)
{
struct dmxdev_filter *dmxdevfilter=(struct dmxdev_filter *)data;
-
+
dmxdevfilter->buffer.error=-ETIMEDOUT;
spin_lock_irq(&dmxdevfilter->dev->lock);
dmxdevfilter->state=DMXDEV_STATE_TIMEDOUT;
@@ -332,7 +331,7 @@ static void dvb_dmxdev_filter_timeout(unsigned long data)
static void dvb_dmxdev_filter_timer(struct dmxdev_filter *dmxdevfilter)
{
struct dmx_sct_filter_params *para=&dmxdevfilter->params.sec;
-
+
del_timer(&dmxdevfilter->timer);
if (para->timeout) {
dmxdevfilter->timer.function=dvb_dmxdev_filter_timeout;
@@ -348,7 +347,7 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,
{
struct dmxdev_filter *dmxdevfilter=(struct dmxdev_filter *) filter->priv;
int ret;
-
+
if (dmxdevfilter->buffer.error) {
wake_up(&dmxdevfilter->buffer.queue);
return 0;
@@ -359,16 +358,16 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,
return 0;
}
del_timer(&dmxdevfilter->timer);
- dprintk("dmxdev: section callback %02x %02x %02x %02x %02x %02x\n",
- buffer1[0], buffer1[1],
- buffer1[2], buffer1[3],
+ dprintk("dmxdev: section callback %02x %02x %02x %02x %02x %02x\n",
+ buffer1[0], buffer1[1],
+ buffer1[2], buffer1[3],
buffer1[4], buffer1[5]);
ret=dvb_dmxdev_buffer_write(&dmxdevfilter->buffer, buffer1, buffer1_len);
if (ret==buffer1_len) {
ret=dvb_dmxdev_buffer_write(&dmxdevfilter->buffer, buffer2, buffer2_len);
}
if (ret<0) {
- dmxdevfilter->buffer.pwrite=dmxdevfilter->buffer.pread;
+ dmxdevfilter->buffer.pwrite=dmxdevfilter->buffer.pread;
dmxdevfilter->buffer.error=-EOVERFLOW;
}
if (dmxdevfilter->params.sec.flags&DMX_ONESHOT)
@@ -385,7 +384,7 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
struct dmxdev_filter *dmxdevfilter=(struct dmxdev_filter *) feed->priv;
struct dmxdev_buffer *buffer;
int ret;
-
+
spin_lock(&dmxdevfilter->dev->lock);
if (dmxdevfilter->params.pes.output==DMX_OUT_DECODER) {
spin_unlock(&dmxdevfilter->dev->lock);
@@ -402,10 +401,10 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
return 0;
}
ret=dvb_dmxdev_buffer_write(buffer, buffer1, buffer1_len);
- if (ret==buffer1_len)
+ if (ret==buffer1_len)
ret=dvb_dmxdev_buffer_write(buffer, buffer2, buffer2_len);
if (ret<0) {
- buffer->pwrite=buffer->pread;
+ buffer->pwrite=buffer->pread;
buffer->error=-EOVERFLOW;
}
spin_unlock(&dmxdevfilter->dev->lock);
@@ -456,7 +455,7 @@ static int dvb_dmxdev_feed_start(struct dmxdev_filter *filter)
}
-/* restart section feed if it has filters left associated with it,
+/* restart section feed if it has filters left associated with it,
otherwise release the feed */
static int dvb_dmxdev_feed_restart(struct dmxdev_filter *filter)
@@ -464,15 +463,15 @@ static int dvb_dmxdev_feed_restart(struct dmxdev_filter *filter)
int i;
struct dmxdev *dmxdev = filter->dev;
u16 pid = filter->params.sec.pid;
-
- for (i=0; i<dmxdev->filternum; i++)
+
+ for (i=0; i<dmxdev->filternum; i++)
if (dmxdev->filter[i].state>=DMXDEV_STATE_GO &&
dmxdev->filter[i].type==DMXDEV_TYPE_SEC &&
dmxdev->filter[i].pid==pid) {
dvb_dmxdev_feed_start(&dmxdev->filter[i]);
return 0;
}
-
+
filter->dev->demux->release_section_feed(dmxdev->demux, filter->feed.sec);
return 0;
@@ -480,7 +479,7 @@ static int dvb_dmxdev_feed_restart(struct dmxdev_filter *filter)
static int dvb_dmxdev_filter_stop(struct dmxdev_filter *dmxdevfilter)
{
- if (dmxdevfilter->state<DMXDEV_STATE_GO)
+ if (dmxdevfilter->state<DMXDEV_STATE_GO)
return 0;
switch (dmxdevfilter->type) {
@@ -505,17 +504,17 @@ static int dvb_dmxdev_filter_stop(struct dmxdev_filter *dmxdevfilter)
dmxdevfilter->feed.ts=NULL;
break;
default:
- if (dmxdevfilter->state==DMXDEV_STATE_ALLOCATED)
+ if (dmxdevfilter->state==DMXDEV_STATE_ALLOCATED)
return 0;
return -EINVAL;
}
- dmxdevfilter->buffer.pwrite=dmxdevfilter->buffer.pread=0;
+ dmxdevfilter->buffer.pwrite=dmxdevfilter->buffer.pread=0;
return 0;
}
static inline int dvb_dmxdev_filter_reset(struct dmxdev_filter *dmxdevfilter)
{
- if (dmxdevfilter->state<DMXDEV_STATE_SET)
+ if (dmxdevfilter->state<DMXDEV_STATE_SET)
return 0;
dmxdevfilter->type=DMXDEV_TYPE_NONE;
@@ -530,11 +529,11 @@ static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter)
void *mem;
int ret, i;
- if (filter->state < DMXDEV_STATE_SET)
+ if (filter->state < DMXDEV_STATE_SET)
return -EINVAL;
if (filter->state >= DMXDEV_STATE_GO)
- dvb_dmxdev_filter_stop(filter);
+ dvb_dmxdev_filter_stop(filter);
if (!(mem = filter->buffer.data)) {
mem = vmalloc(filter->buffer.size);
@@ -560,27 +559,27 @@ static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter)
/* find active filter/feed with same PID */
for (i=0; i<dmxdev->filternum; i++) {
if (dmxdev->filter[i].state >= DMXDEV_STATE_GO &&
- dmxdev->filter[i].pid == para->pid &&
+ dmxdev->filter[i].pid == para->pid &&
dmxdev->filter[i].type == DMXDEV_TYPE_SEC) {
*secfeed = dmxdev->filter[i].feed.sec;
break;
}
}
- /* if no feed found, try to allocate new one */
+ /* if no feed found, try to allocate new one */
if (!*secfeed) {
- ret=dmxdev->demux->allocate_section_feed(dmxdev->demux,
- secfeed,
+ ret=dmxdev->demux->allocate_section_feed(dmxdev->demux,
+ secfeed,
dvb_dmxdev_section_callback);
if (ret<0) {
printk ("DVB (%s): could not alloc feed\n",
__FUNCTION__);
return ret;
}
-
- ret=(*secfeed)->set(*secfeed, para->pid, 32768, 0,
+
+ ret=(*secfeed)->set(*secfeed, para->pid, 32768, 0,
(para->flags & DMX_CHECK_CRC) ? 1 : 0);
-
+
if (ret<0) {
printk ("DVB (%s): could not set feed\n",
__FUNCTION__);
@@ -590,7 +589,7 @@ static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter)
} else {
dvb_dmxdev_feed_stop(filter);
}
-
+
ret=(*secfeed)->allocate_filter(*secfeed, secfilter);
if (ret < 0) {
@@ -602,11 +601,11 @@ static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter)
(*secfilter)->priv = filter;
- memcpy(&((*secfilter)->filter_value[3]),
+ memcpy(&((*secfilter)->filter_value[3]),
&(para->filter.filter[1]), DMX_FILTER_SIZE-1);
- memcpy(&(*secfilter)->filter_mask[3],
+ memcpy(&(*secfilter)->filter_mask[3],
&para->filter.mask[1], DMX_FILTER_SIZE-1);
- memcpy(&(*secfilter)->filter_mode[3],
+ memcpy(&(*secfilter)->filter_mode[3],
&para->filter.mode[1], DMX_FILTER_SIZE-1);
(*secfilter)->filter_value[0]=para->filter.filter[0];
@@ -614,7 +613,7 @@ static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter)
(*secfilter)->filter_mode[0]=para->filter.mode[0];
(*secfilter)->filter_mask[1]=0;
(*secfilter)->filter_mask[2]=0;
-
+
filter->todo = 0;
ret = filter->feed.sec->start_filtering (filter->feed.sec);
@@ -626,7 +625,7 @@ static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter)
break;
}
- case DMXDEV_TYPE_PES:
+ case DMXDEV_TYPE_PES:
{
struct timespec timeout = { 0 };
struct dmx_pes_filter_params *para = &filter->params.pes;
@@ -635,27 +634,27 @@ static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter)
int ts_type;
enum dmx_ts_pes ts_pes;
struct dmx_ts_feed **tsfeed = &filter->feed.ts;
-
+
filter->feed.ts = NULL;
otype=para->output;
-
+
ts_pes=(enum dmx_ts_pes) para->pes_type;
-
- if (ts_pes<DMX_PES_OTHER)
+
+ if (ts_pes<DMX_PES_OTHER)
ts_type=TS_DECODER;
else
ts_type=0;
-
- if (otype == DMX_OUT_TS_TAP)
+
+ if (otype == DMX_OUT_TS_TAP)
ts_type |= TS_PACKET;
-
- if (otype == DMX_OUT_TAP)
+
+ if (otype == DMX_OUT_TAP)
ts_type |= TS_PAYLOAD_ONLY|TS_PACKET;
-
- ret=dmxdev->demux->allocate_ts_feed(dmxdev->demux,
- tsfeed,
+
+ ret=dmxdev->demux->allocate_ts_feed(dmxdev->demux,
+ tsfeed,
dvb_dmxdev_ts_callback);
- if (ret<0)
+ if (ret<0)
return ret;
(*tsfeed)->priv = (void *) filter;
@@ -730,13 +729,13 @@ static int dvb_dmxdev_filter_free(struct dmxdev *dmxdev, struct dmxdev_filter *d
up(&dmxdev->mutex);
return -ERESTARTSYS;
}
-
+
dvb_dmxdev_filter_stop(dmxdevfilter);
dvb_dmxdev_filter_reset(dmxdevfilter);
-
+
if (dmxdevfilter->buffer.data) {
void *mem=dmxdevfilter->buffer.data;
-
+
spin_lock_irq(&dmxdev->lock);
dmxdevfilter->buffer.data=NULL;
spin_unlock_irq(&dmxdev->lock);
@@ -759,22 +758,22 @@ static inline void invert_mode(dmx_filter_t *filter)
}
-static int dvb_dmxdev_filter_set(struct dmxdev *dmxdev,
- struct dmxdev_filter *dmxdevfilter,
+static int dvb_dmxdev_filter_set(struct dmxdev *dmxdev,
+ struct dmxdev_filter *dmxdevfilter,
struct dmx_sct_filter_params *params)
{
dprintk ("function : %s\n", __FUNCTION__);
dvb_dmxdev_filter_stop(dmxdevfilter);
-
+
dmxdevfilter->type=DMXDEV_TYPE_SEC;
dmxdevfilter->pid=params->pid;
- memcpy(&dmxdevfilter->params.sec,
+ memcpy(&dmxdevfilter->params.sec,
params, sizeof(struct dmx_sct_filter_params));
invert_mode(&dmxdevfilter->params.sec.filter);
dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_SET);
-
- if (params->flags&DMX_IMMEDIATE_START)
+
+ if (params->flags&DMX_IMMEDIATE_START)
return dvb_dmxdev_filter_start(dmxdevfilter);
return 0;
@@ -795,7 +794,7 @@ static int dvb_dmxdev_pes_filter_set(struct dmxdev *dmxdev,
dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_SET);
- if (params->flags&DMX_IMMEDIATE_START)
+ if (params->flags&DMX_IMMEDIATE_START)
return dvb_dmxdev_filter_start(dmxdevfilter);
return 0;
@@ -806,18 +805,18 @@ static ssize_t dvb_dmxdev_read_sec(struct dmxdev_filter *dfil,
{
int result, hcount;
int done=0;
-
+
if (dfil->todo<=0) {
hcount=3+dfil->todo;
if (hcount>count)
hcount=count;
- result=dvb_dmxdev_buffer_read(&dfil->buffer, file->f_flags&O_NONBLOCK,
+ result=dvb_dmxdev_buffer_read(&dfil->buffer, file->f_flags&O_NONBLOCK,
buf, hcount, ppos);
if (result<0) {
dfil->todo=0;
return result;
}
- if (copy_from_user(dfil->secheader-dfil->todo, buf, result))
+ if (copy_from_user(dfil->secheader-dfil->todo, buf, result))
return -EFAULT;
buf+=result;
done=result;
@@ -831,7 +830,7 @@ static ssize_t dvb_dmxdev_read_sec(struct dmxdev_filter *dfil,
}
if (count>dfil->todo)
count=dfil->todo;
- result=dvb_dmxdev_buffer_read(&dfil->buffer, file->f_flags&O_NONBLOCK,
+ result=dvb_dmxdev_buffer_read(&dfil->buffer, file->f_flags&O_NONBLOCK,
buf, count, ppos);
if (result<0)
return result;
@@ -852,8 +851,8 @@ dvb_demux_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
if (dmxdevfilter->type==DMXDEV_TYPE_SEC)
ret=dvb_dmxdev_read_sec(dmxdevfilter, file, buf, count, ppos);
else
- ret=dvb_dmxdev_buffer_read(&dmxdevfilter->buffer,
- file->f_flags&O_NONBLOCK,
+ ret=dvb_dmxdev_buffer_read(&dmxdevfilter->buffer,
+ file->f_flags&O_NONBLOCK,
buf, count, ppos);
up(&dmxdevfilter->mutex);
@@ -868,7 +867,7 @@ static int dvb_demux_do_ioctl(struct inode *inode, struct file *file,
struct dmxdev *dmxdev=dmxdevfilter->dev;
unsigned long arg=(unsigned long) parg;
int ret=0;
-
+
if (down_interruptible (&dmxdev->mutex))
return -ERESTARTSYS;
@@ -894,27 +893,27 @@ static int dvb_demux_do_ioctl(struct inode *inode, struct file *file,
up(&dmxdevfilter->mutex);
break;
- case DMX_SET_FILTER:
+ case DMX_SET_FILTER:
if (down_interruptible(&dmxdevfilter->mutex)) {
up(&dmxdev->mutex);
return -ERESTARTSYS;
}
- ret = dvb_dmxdev_filter_set(dmxdev, dmxdevfilter,
+ ret = dvb_dmxdev_filter_set(dmxdev, dmxdevfilter,
(struct dmx_sct_filter_params *)parg);
up(&dmxdevfilter->mutex);
break;
- case DMX_SET_PES_FILTER:
+ case DMX_SET_PES_FILTER:
if (down_interruptible(&dmxdevfilter->mutex)) {
up(&dmxdev->mutex);
return -ERESTARTSYS;
}
- ret=dvb_dmxdev_pes_filter_set(dmxdev, dmxdevfilter,
+ ret=dvb_dmxdev_pes_filter_set(dmxdev, dmxdevfilter,
(struct dmx_pes_filter_params *)parg);
up(&dmxdevfilter->mutex);
break;
- case DMX_SET_BUFFER_SIZE:
+ case DMX_SET_BUFFER_SIZE:
if (down_interruptible(&dmxdevfilter->mutex)) {
up(&dmxdev->mutex);
return -ERESTARTSYS;
@@ -922,11 +921,11 @@ static int dvb_demux_do_ioctl(struct inode *inode, struct file *file,
ret=dvb_dmxdev_set_buffer_size(dmxdevfilter, arg);
up(&dmxdevfilter->mutex);
break;
-
- case DMX_GET_EVENT:
+
+ case DMX_GET_EVENT:
break;
-
- case DMX_GET_PES_PIDS:
+
+ case DMX_GET_PES_PIDS:
if (!dmxdev->demux->get_pes_pids) {
ret=-EINVAL;
break;
@@ -992,6 +991,7 @@ static int dvb_demux_release(struct inode *inode, struct file *file)
return dvb_dmxdev_filter_free(dmxdev, dmxdevfilter);
}
+
static struct file_operations dvb_demux_fops = {
.owner = THIS_MODULE,
.read = dvb_demux_read,
@@ -1001,6 +1001,7 @@ static struct file_operations dvb_demux_fops = {
.poll = dvb_demux_poll,
};
+
static struct dvb_device dvbdev_demux = {
.priv = NULL,
.users = 1,
@@ -1008,8 +1009,9 @@ static struct dvb_device dvbdev_demux = {
.fops = &dvb_demux_fops
};
+
static int dvb_dvr_do_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, void *parg)
+ unsigned int cmd, void *parg)
{
struct dvb_device *dvbdev=(struct dvb_device *) file->private_data;
struct dmxdev *dmxdev=(struct dmxdev *) dvbdev->priv;
@@ -1020,11 +1022,11 @@ static int dvb_dvr_do_ioctl(struct inode *inode, struct file *file,
return -ERESTARTSYS;
switch (cmd) {
- case DMX_SET_BUFFER_SIZE:
+ case DMX_SET_BUFFER_SIZE:
// FIXME: implement
ret=0;
break;
-
+
default:
ret=-EINVAL;
}
@@ -1032,8 +1034,9 @@ static int dvb_dvr_do_ioctl(struct inode *inode, struct file *file,
return ret;
}
+
static int dvb_dvr_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
+ unsigned int cmd, unsigned long arg)
{
return dvb_usercopy(inode, file, cmd, arg, dvb_dvr_do_ioctl);
}
@@ -1055,7 +1058,7 @@ static unsigned int dvb_dvr_poll (struct file *file, poll_table *wait)
if (dmxdev->dvr_buffer.pread!=dmxdev->dvr_buffer.pwrite)
mask |= (POLLIN | POLLRDNORM | POLLPRI);
- } else
+ } else
mask |= (POLLOUT | POLLWRNORM | POLLPRI);
return mask;
@@ -1079,14 +1082,14 @@ static struct dvb_device dvbdev_dvr = {
.fops = &dvb_dvr_fops
};
-int
+int
dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *dvb_adapter)
{
int i;
- if (dmxdev->demux->open(dmxdev->demux)<0)
+ if (dmxdev->demux->open(dmxdev->demux) < 0)
return -EUSERS;
-
+
dmxdev->filter = vmalloc(dmxdev->filternum*sizeof(struct dmxdev_filter));
if (!dmxdev->filter)
return -ENOMEM;
@@ -1109,6 +1112,7 @@ dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *dvb_adapter)
dvb_dmxdev_filter_state_set(&dmxdev->filter[i], DMXDEV_STATE_FREE);
dvb_dmxdev_dvr_state_set(&dmxdev->dvr[i], DMXDEV_STATE_FREE);
}
+
dvb_register_device(dvb_adapter, &dmxdev->dvbdev, &dvbdev_demux, dmxdev, DVB_DEVICE_DEMUX);
dvb_register_device(dvb_adapter, &dmxdev->dvr_dvbdev, &dvbdev_dvr, dmxdev, DVB_DEVICE_DVR);
@@ -1118,20 +1122,16 @@ dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *dvb_adapter)
}
EXPORT_SYMBOL(dvb_dmxdev_init);
-void
+void
dvb_dmxdev_release(struct dmxdev *dmxdev)
{
dvb_unregister_device(dmxdev->dvbdev);
dvb_unregister_device(dmxdev->dvr_dvbdev);
- if (dmxdev->filter) {
- vfree(dmxdev->filter);
- dmxdev->filter=NULL;
- }
- if (dmxdev->dvr) {
- vfree(dmxdev->dvr);
- dmxdev->dvr=NULL;
- }
+
+ vfree(dmxdev->filter);
+ dmxdev->filter=NULL;
+ vfree(dmxdev->dvr);
+ dmxdev->dvr=NULL;
dmxdev->demux->close(dmxdev->demux);
}
EXPORT_SYMBOL(dvb_dmxdev_release);
-
diff --git a/drivers/media/dvb/dvb-core/dmxdev.h b/drivers/media/dvb/dvb-core/dmxdev.h
index 47d31777c0c36..395a9cd75012c 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.h
+++ b/drivers/media/dvb/dvb-core/dmxdev.h
@@ -1,4 +1,4 @@
-/*
+/*
* dmxdev.h
*
* Copyright (C) 2000 Ralph Metzler & Marcus Metzler
diff --git a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
index 63eccd4b67b2b..c1ea89f2880ce 100644
--- a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
+++ b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
@@ -61,19 +61,19 @@ MODULE_PARM_DESC(cam_debug, "enable verbose debug messages");
#define CTRLIF_SIZE_LOW 2
#define CTRLIF_SIZE_HIGH 3
-#define CMDREG_HC 1 /* Host control */
-#define CMDREG_SW 2 /* Size write */
-#define CMDREG_SR 4 /* Size read */
-#define CMDREG_RS 8 /* Reset interface */
-#define CMDREG_FRIE 0x40 /* Enable FR interrupt */
-#define CMDREG_DAIE 0x80 /* Enable DA interrupt */
+#define CMDREG_HC 1 /* Host control */
+#define CMDREG_SW 2 /* Size write */
+#define CMDREG_SR 4 /* Size read */
+#define CMDREG_RS 8 /* Reset interface */
+#define CMDREG_FRIE 0x40 /* Enable FR interrupt */
+#define CMDREG_DAIE 0x80 /* Enable DA interrupt */
#define IRQEN (CMDREG_DAIE)
-#define STATUSREG_RE 1 /* read error */
-#define STATUSREG_WE 2 /* write error */
-#define STATUSREG_FR 0x40 /* module free */
-#define STATUSREG_DA 0x80 /* data available */
-#define STATUSREG_TXERR (STATUSREG_RE|STATUSREG_WE) /* general transfer error */
+#define STATUSREG_RE 1 /* read error */
+#define STATUSREG_WE 2 /* write error */
+#define STATUSREG_FR 0x40 /* module free */
+#define STATUSREG_DA 0x80 /* data available */
+#define STATUSREG_TXERR (STATUSREG_RE|STATUSREG_WE) /* general transfer error */
#define DVB_CA_SLOTSTATE_NONE 0
@@ -89,83 +89,83 @@ MODULE_PARM_DESC(cam_debug, "enable verbose debug messages");
/* Information on a CA slot */
struct dvb_ca_slot {
- /* current state of the CAM */
- int slot_state;
+ /* current state of the CAM */
+ int slot_state;
- /* Number of CAMCHANGES that have occurred since last processing */
- atomic_t camchange_count;
+ /* Number of CAMCHANGES that have occurred since last processing */
+ atomic_t camchange_count;
- /* Type of last CAMCHANGE */
- int camchange_type;
+ /* Type of last CAMCHANGE */
+ int camchange_type;
- /* base address of CAM config */
- u32 config_base;
+ /* base address of CAM config */
+ u32 config_base;
- /* value to write into Config Control register */
- u8 config_option;
+ /* value to write into Config Control register */
+ u8 config_option;
- /* if 1, the CAM supports DA IRQs */
- u8 da_irq_supported:1;
+ /* if 1, the CAM supports DA IRQs */
+ u8 da_irq_supported:1;
- /* size of the buffer to use when talking to the CAM */
- int link_buf_size;
+ /* size of the buffer to use when talking to the CAM */
+ int link_buf_size;
- /* semaphore for syncing access to slot structure */
- struct rw_semaphore sem;
+ /* semaphore for syncing access to slot structure */
+ struct rw_semaphore sem;
- /* buffer for incoming packets */
- struct dvb_ringbuffer rx_buffer;
+ /* buffer for incoming packets */
+ struct dvb_ringbuffer rx_buffer;
- /* timer used during various states of the slot */
- unsigned long timeout;
+ /* timer used during various states of the slot */
+ unsigned long timeout;
};
/* Private CA-interface information */
struct dvb_ca_private {
- /* pointer back to the public data structure */
- struct dvb_ca_en50221* pub;
+ /* pointer back to the public data structure */
+ struct dvb_ca_en50221 *pub;
- /* the DVB device */
- struct dvb_device *dvbdev;
+ /* the DVB device */
+ struct dvb_device *dvbdev;
- /* Flags describing the interface (DVB_CA_FLAG_*) */
- u32 flags;
+ /* Flags describing the interface (DVB_CA_FLAG_*) */
+ u32 flags;
- /* number of slots supported by this CA interface */
- unsigned int slot_count;
+ /* number of slots supported by this CA interface */
+ unsigned int slot_count;
- /* information on each slot */
- struct dvb_ca_slot* slot_info;
+ /* information on each slot */
+ struct dvb_ca_slot *slot_info;
- /* wait queues for read() and write() operations */
- wait_queue_head_t wait_queue;
+ /* wait queues for read() and write() operations */
+ wait_queue_head_t wait_queue;
- /* PID of the monitoring thread */
- pid_t thread_pid;
+ /* PID of the monitoring thread */
+ pid_t thread_pid;
- /* Wait queue used when shutting thread down */
- wait_queue_head_t thread_queue;
+ /* Wait queue used when shutting thread down */
+ wait_queue_head_t thread_queue;
- /* Flag indicating when thread should exit */
- int exit:1;
+ /* Flag indicating when thread should exit */
+ unsigned int exit:1;
- /* Flag indicating if the CA device is open */
- int open:1;
+ /* Flag indicating if the CA device is open */
+ unsigned int open:1;
- /* Flag indicating the thread should wake up now */
- int wakeup:1;
+ /* Flag indicating the thread should wake up now */
+ unsigned int wakeup:1;
- /* Delay the main thread should use */
- unsigned long delay;
+ /* Delay the main thread should use */
+ unsigned long delay;
- /* Slot to start looking for data to read from in the next user-space read operation */
- int next_read_slot;
+ /* Slot to start looking for data to read from in the next user-space read operation */
+ int next_read_slot;
};
-static void dvb_ca_en50221_thread_wakeup(struct dvb_ca_private* ca);
-static int dvb_ca_en50221_read_data(struct dvb_ca_private* ca, int slot, u8* ebuf, int ecount);
-static int dvb_ca_en50221_write_data(struct dvb_ca_private* ca, int slot, u8* ebuf, int ecount);
+static void dvb_ca_en50221_thread_wakeup(struct dvb_ca_private *ca);
+static int dvb_ca_en50221_read_data(struct dvb_ca_private *ca, int slot, u8 * ebuf, int ecount);
+static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot, u8 * ebuf, int ecount);
/**
@@ -177,19 +177,19 @@ static int dvb_ca_en50221_write_data(struct dvb_ca_private* ca, int slot, u8* eb
* @param nlen Number of bytes in needle.
* @return Pointer into haystack needle was found at, or NULL if not found.
*/
-static u8* findstr(u8* haystack, int hlen, u8* needle, int nlen)
+static u8 *findstr(u8 * haystack, int hlen, u8 * needle, int nlen)
{
- int i;
+ int i;
if (hlen < nlen)
return NULL;
- for(i=0; i<= hlen - nlen; i++) {
+ for (i = 0; i <= hlen - nlen; i++) {
if (!strncmp(haystack + i, needle, nlen))
return haystack + i;
- }
+ }
- return NULL;
+ return NULL;
}
@@ -201,43 +201,43 @@ static u8* findstr(u8* haystack, int hlen, u8* needle, int nlen)
/**
* Check CAM status.
*/
-static int dvb_ca_en50221_check_camstatus(struct dvb_ca_private* ca, int slot)
+static int dvb_ca_en50221_check_camstatus(struct dvb_ca_private *ca, int slot)
{
- int slot_status;
- int cam_present_now;
- int cam_changed;
+ int slot_status;
+ int cam_present_now;
+ int cam_changed;
- /* IRQ mode */
- if (ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE) {
- return (atomic_read(&ca->slot_info[slot].camchange_count) != 0);
- }
+ /* IRQ mode */
+ if (ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE) {
+ return (atomic_read(&ca->slot_info[slot].camchange_count) != 0);
+ }
- /* poll mode */
+ /* poll mode */
slot_status = ca->pub->poll_slot_status(ca->pub, slot, ca->open);
- cam_present_now = (slot_status & DVB_CA_EN50221_POLL_CAM_PRESENT) ? 1: 0;
- cam_changed = (slot_status & DVB_CA_EN50221_POLL_CAM_CHANGED) ? 1: 0;
- if (!cam_changed) {
- int cam_present_old = (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_NONE);
- cam_changed = (cam_present_now != cam_present_old);
- }
-
- if (cam_changed) {
- if (!cam_present_now) {
- ca->slot_info[slot].camchange_type = DVB_CA_EN50221_CAMCHANGE_REMOVED;
- } else {
- ca->slot_info[slot].camchange_type = DVB_CA_EN50221_CAMCHANGE_INSERTED;
- }
- atomic_set(&ca->slot_info[slot].camchange_count, 1);
- } else {
- if ((ca->slot_info[slot].slot_state == DVB_CA_SLOTSTATE_WAITREADY) &&
- (slot_status & DVB_CA_EN50221_POLL_CAM_READY)) {
- // move to validate state if reset is completed
- ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_VALIDATE;
- }
- }
-
- return cam_changed;
+ cam_present_now = (slot_status & DVB_CA_EN50221_POLL_CAM_PRESENT) ? 1 : 0;
+ cam_changed = (slot_status & DVB_CA_EN50221_POLL_CAM_CHANGED) ? 1 : 0;
+ if (!cam_changed) {
+ int cam_present_old = (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_NONE);
+ cam_changed = (cam_present_now != cam_present_old);
+ }
+
+ if (cam_changed) {
+ if (!cam_present_now) {
+ ca->slot_info[slot].camchange_type = DVB_CA_EN50221_CAMCHANGE_REMOVED;
+ } else {
+ ca->slot_info[slot].camchange_type = DVB_CA_EN50221_CAMCHANGE_INSERTED;
+ }
+ atomic_set(&ca->slot_info[slot].camchange_count, 1);
+ } else {
+ if ((ca->slot_info[slot].slot_state == DVB_CA_SLOTSTATE_WAITREADY) &&
+ (slot_status & DVB_CA_EN50221_POLL_CAM_READY)) {
+ // move to validate state if reset is completed
+ ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_VALIDATE;
+ }
+ }
+
+ return cam_changed;
}
@@ -255,39 +255,39 @@ static int dvb_ca_en50221_check_camstatus(struct dvb_ca_private* ca, int slot)
static int dvb_ca_en50221_wait_if_status(struct dvb_ca_private *ca, int slot,
u8 waitfor, int timeout_hz)
{
- unsigned long timeout;
- unsigned long start;
+ unsigned long timeout;
+ unsigned long start;
- dprintk ("%s\n", __FUNCTION__);
+ dprintk("%s\n", __FUNCTION__);
- /* loop until timeout elapsed */
- start = jiffies;
- timeout = jiffies + timeout_hz;
- while(1) {
- /* read the status and check for error */
- int res = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS);
+ /* loop until timeout elapsed */
+ start = jiffies;
+ timeout = jiffies + timeout_hz;
+ while (1) {
+ /* read the status and check for error */
+ int res = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS);
if (res < 0)
return -EIO;
- /* if we got the flags, it was successful! */
- if (res & waitfor) {
- dprintk("%s succeeded timeout:%lu\n", __FUNCTION__, jiffies - start);
- return 0;
- }
+ /* if we got the flags, it was successful! */
+ if (res & waitfor) {
+ dprintk("%s succeeded timeout:%lu\n", __FUNCTION__, jiffies - start);
+ return 0;
+ }
- /* check for timeout */
- if (time_after(jiffies, timeout)) {
- break;
- }
+ /* check for timeout */
+ if (time_after(jiffies, timeout)) {
+ break;
+ }
- /* wait for a bit */
- msleep(1);
- }
+ /* wait for a bit */
+ msleep(1);
+ }
- dprintk("%s failed timeout:%lu\n", __FUNCTION__, jiffies - start);
+ dprintk("%s failed timeout:%lu\n", __FUNCTION__, jiffies - start);
- /* if we get here, we've timed out */
- return -ETIMEDOUT;
+ /* if we get here, we've timed out */
+ return -ETIMEDOUT;
}
@@ -299,22 +299,22 @@ static int dvb_ca_en50221_wait_if_status(struct dvb_ca_private *ca, int slot,
*
* @return 0 on success, nonzero on failure.
*/
-static int dvb_ca_en50221_link_init(struct dvb_ca_private* ca, int slot)
+static int dvb_ca_en50221_link_init(struct dvb_ca_private *ca, int slot)
{
- int ret;
- int buf_size;
- u8 buf[2];
+ int ret;
+ int buf_size;
+ u8 buf[2];
- dprintk ("%s\n", __FUNCTION__);
+ dprintk("%s\n", __FUNCTION__);
- /* we'll be determining these during this function */
- ca->slot_info[slot].da_irq_supported = 0;
+ /* we'll be determining these during this function */
+ ca->slot_info[slot].da_irq_supported = 0;
- /* set the host link buffer size temporarily. it will be overwritten with the
- * real negotiated size later. */
- ca->slot_info[slot].link_buf_size = 2;
+ /* set the host link buffer size temporarily. it will be overwritten with the
+ * real negotiated size later. */
+ ca->slot_info[slot].link_buf_size = 2;
- /* read the buffer size from the CAM */
+ /* read the buffer size from the CAM */
if ((ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN | CMDREG_SR)) != 0)
return ret;
if ((ret = dvb_ca_en50221_wait_if_status(ca, slot, STATUSREG_DA, HZ / 10)) != 0)
@@ -324,16 +324,16 @@ static int dvb_ca_en50221_link_init(struct dvb_ca_private* ca, int slot)
if ((ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN)) != 0)
return ret;
- /* store it, and choose the minimum of our buffer and the CAM's buffer size */
- buf_size = (buf[0] << 8) | buf[1];
+ /* store it, and choose the minimum of our buffer and the CAM's buffer size */
+ buf_size = (buf[0] << 8) | buf[1];
if (buf_size > HOST_LINK_BUF_SIZE)
buf_size = HOST_LINK_BUF_SIZE;
- ca->slot_info[slot].link_buf_size = buf_size;
- buf[0] = buf_size >> 8;
- buf[1] = buf_size & 0xff;
- dprintk("Chosen link buffer size of %i\n", buf_size);
+ ca->slot_info[slot].link_buf_size = buf_size;
+ buf[0] = buf_size >> 8;
+ buf[1] = buf_size & 0xff;
+ dprintk("Chosen link buffer size of %i\n", buf_size);
- /* write the buffer size to the CAM */
+ /* write the buffer size to the CAM */
if ((ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN | CMDREG_SW)) != 0)
return ret;
if ((ret = dvb_ca_en50221_wait_if_status(ca, slot, STATUSREG_FR, HZ / 10)) != 0)
@@ -343,8 +343,8 @@ static int dvb_ca_en50221_link_init(struct dvb_ca_private* ca, int slot)
if ((ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN)) != 0)
return ret;
- /* success */
- return 0;
+ /* success */
+ return 0;
}
/**
@@ -359,44 +359,44 @@ static int dvb_ca_en50221_link_init(struct dvb_ca_private* ca, int slot)
*
* @return 0 on success, nonzero on error.
*/
-static int dvb_ca_en50221_read_tuple(struct dvb_ca_private* ca, int slot,
- int* address, int* tupleType, int* tupleLength, u8* tuple)
+static int dvb_ca_en50221_read_tuple(struct dvb_ca_private *ca, int slot,
+ int *address, int *tupleType, int *tupleLength, u8 * tuple)
{
- int i;
- int _tupleType;
- int _tupleLength;
- int _address = *address;
+ int i;
+ int _tupleType;
+ int _tupleLength;
+ int _address = *address;
- /* grab the next tuple length and type */
+ /* grab the next tuple length and type */
if ((_tupleType = ca->pub->read_attribute_mem(ca->pub, slot, _address)) < 0)
return _tupleType;
- if (_tupleType == 0xff) {
- dprintk("END OF CHAIN TUPLE type:0x%x\n", _tupleType);
- *address += 2;
- *tupleType = _tupleType;
- *tupleLength = 0;
- return 0;
- }
+ if (_tupleType == 0xff) {
+ dprintk("END OF CHAIN TUPLE type:0x%x\n", _tupleType);
+ *address += 2;
+ *tupleType = _tupleType;
+ *tupleLength = 0;
+ return 0;
+ }
if ((_tupleLength = ca->pub->read_attribute_mem(ca->pub, slot, _address + 2)) < 0)
return _tupleLength;
- _address += 4;
+ _address += 4;
- dprintk("TUPLE type:0x%x length:%i\n", _tupleType, _tupleLength);
+ dprintk("TUPLE type:0x%x length:%i\n", _tupleType, _tupleLength);
- /* read in the whole tuple */
- for(i=0; i< _tupleLength; i++) {
- tuple[i] = ca->pub->read_attribute_mem(ca->pub, slot, _address + (i*2));
+ /* read in the whole tuple */
+ for (i = 0; i < _tupleLength; i++) {
+ tuple[i] = ca->pub->read_attribute_mem(ca->pub, slot, _address + (i * 2));
dprintk(" 0x%02x: 0x%02x %c\n",
i, tuple[i] & 0xff,
((tuple[i] > 31) && (tuple[i] < 127)) ? tuple[i] : '.');
- }
- _address += (_tupleLength*2);
-
- // success
- *tupleType = _tupleType;
- *tupleLength = _tupleLength;
- *address = _address;
- return 0;
+ }
+ _address += (_tupleLength * 2);
+
+ // success
+ *tupleType = _tupleType;
+ *tupleLength = _tupleLength;
+ *address = _address;
+ return 0;
}
@@ -409,23 +409,23 @@ static int dvb_ca_en50221_read_tuple(struct dvb_ca_private* ca, int slot,
*
* @return 0 on success, <0 on failure.
*/
-static int dvb_ca_en50221_parse_attributes(struct dvb_ca_private* ca, int slot)
+static int dvb_ca_en50221_parse_attributes(struct dvb_ca_private *ca, int slot)
{
- int address = 0;
- int tupleLength;
- int tupleType;
- u8 tuple[257];
- char* dvb_str;
- int rasz;
- int status;
- int got_cftableentry = 0;
- int end_chain = 0;
- int i;
- u16 manfid = 0;
- u16 devid = 0;
-
-
- // CISTPL_DEVICE_0A
+ int address = 0;
+ int tupleLength;
+ int tupleType;
+ u8 tuple[257];
+ char *dvb_str;
+ int rasz;
+ int status;
+ int got_cftableentry = 0;
+ int end_chain = 0;
+ int i;
+ u16 manfid = 0;
+ u16 devid = 0;
+
+
+ // CISTPL_DEVICE_0A
if ((status =
dvb_ca_en50221_read_tuple(ca, slot, &address, &tupleType, &tupleLength, tuple)) < 0)
return status;
@@ -434,7 +434,7 @@ static int dvb_ca_en50221_parse_attributes(struct dvb_ca_private* ca, int slot)
- // CISTPL_DEVICE_0C
+ // CISTPL_DEVICE_0C
if ((status =
dvb_ca_en50221_read_tuple(ca, slot, &address, &tupleType, &tupleLength, tuple)) < 0)
return status;
@@ -443,7 +443,7 @@ static int dvb_ca_en50221_parse_attributes(struct dvb_ca_private* ca, int slot)
- // CISTPL_VERS_1
+ // CISTPL_VERS_1
if ((status =
dvb_ca_en50221_read_tuple(ca, slot, &address, &tupleType, &tupleLength, tuple)) < 0)
return status;
@@ -452,7 +452,7 @@ static int dvb_ca_en50221_parse_attributes(struct dvb_ca_private* ca, int slot)
- // CISTPL_MANFID
+ // CISTPL_MANFID
if ((status = dvb_ca_en50221_read_tuple(ca, slot, &address, &tupleType,
&tupleLength, tuple)) < 0)
return status;
@@ -460,12 +460,12 @@ static int dvb_ca_en50221_parse_attributes(struct dvb_ca_private* ca, int slot)
return -EINVAL;
if (tupleLength != 4)
return -EINVAL;
- manfid = (tuple[1] << 8) | tuple[0];
- devid = (tuple[3] << 8) | tuple[2];
+ manfid = (tuple[1] << 8) | tuple[0];
+ devid = (tuple[3] << 8) | tuple[2];
- // CISTPL_CONFIG
+ // CISTPL_CONFIG
if ((status = dvb_ca_en50221_read_tuple(ca, slot, &address, &tupleType,
&tupleLength, tuple)) < 0)
return status;
@@ -474,76 +474,76 @@ static int dvb_ca_en50221_parse_attributes(struct dvb_ca_private* ca, int slot)
if (tupleLength < 3)
return -EINVAL;
- /* extract the configbase */
- rasz = tuple[0] & 3;
+ /* extract the configbase */
+ rasz = tuple[0] & 3;
if (tupleLength < (3 + rasz + 14))
return -EINVAL;
- ca->slot_info[slot].config_base = 0;
- for(i=0; i< rasz+1; i++) {
- ca->slot_info[slot].config_base |= (tuple[2+i] << (8*i));
- }
+ ca->slot_info[slot].config_base = 0;
+ for (i = 0; i < rasz + 1; i++) {
+ ca->slot_info[slot].config_base |= (tuple[2 + i] << (8 * i));
+ }
- /* check it contains the correct DVB string */
- dvb_str = findstr(tuple, tupleLength, "DVB_CI_V", 8);
+ /* check it contains the correct DVB string */
+ dvb_str = findstr(tuple, tupleLength, "DVB_CI_V", 8);
if (dvb_str == NULL)
return -EINVAL;
if (tupleLength < ((dvb_str - (char *) tuple) + 12))
return -EINVAL;
- /* is it a version we support? */
- if (strncmp(dvb_str + 8, "1.00", 4)) {
- printk("dvb_ca adapter %d: Unsupported DVB CAM module version %c%c%c%c\n",
+ /* is it a version we support? */
+ if (strncmp(dvb_str + 8, "1.00", 4)) {
+ printk("dvb_ca adapter %d: Unsupported DVB CAM module version %c%c%c%c\n",
ca->dvbdev->adapter->num, dvb_str[8], dvb_str[9], dvb_str[10], dvb_str[11]);
- return -EINVAL;
- }
+ return -EINVAL;
+ }
- /* process the CFTABLE_ENTRY tuples, and any after those */
- while((!end_chain) && (address < 0x1000)) {
+ /* process the CFTABLE_ENTRY tuples, and any after those */
+ while ((!end_chain) && (address < 0x1000)) {
if ((status = dvb_ca_en50221_read_tuple(ca, slot, &address, &tupleType,
&tupleLength, tuple)) < 0)
return status;
- switch(tupleType) {
- case 0x1B: // CISTPL_CFTABLE_ENTRY
+ switch (tupleType) {
+ case 0x1B: // CISTPL_CFTABLE_ENTRY
if (tupleLength < (2 + 11 + 17))
break;
- /* if we've already parsed one, just use it */
+ /* if we've already parsed one, just use it */
if (got_cftableentry)
break;
- /* get the config option */
- ca->slot_info[slot].config_option = tuple[0] & 0x3f;
+ /* get the config option */
+ ca->slot_info[slot].config_option = tuple[0] & 0x3f;
- /* OK, check it contains the correct strings */
- if ((findstr(tuple, tupleLength, "DVB_HOST", 8) == NULL) ||
+ /* OK, check it contains the correct strings */
+ if ((findstr(tuple, tupleLength, "DVB_HOST", 8) == NULL) ||
(findstr(tuple, tupleLength, "DVB_CI_MODULE", 13) == NULL))
break;
- got_cftableentry = 1;
- break;
+ got_cftableentry = 1;
+ break;
- case 0x14: // CISTPL_NO_LINK
- break;
+ case 0x14: // CISTPL_NO_LINK
+ break;
- case 0xFF: // CISTPL_END
- end_chain = 1;
- break;
+ case 0xFF: // CISTPL_END
+ end_chain = 1;
+ break;
- default: /* Unknown tuple type - just skip this tuple and move to the next one */
+ default: /* Unknown tuple type - just skip this tuple and move to the next one */
dprintk("dvb_ca: Skipping unknown tuple type:0x%x length:0x%x\n", tupleType,
tupleLength);
- break;
- }
- }
+ break;
+ }
+ }
if ((address > 0x1000) || (!got_cftableentry))
return -EINVAL;
- dprintk("Valid DVB CAM detected MANID:%x DEVID:%x CONFIGBASE:0x%x CONFIGOPTION:0x%x\n",
+ dprintk("Valid DVB CAM detected MANID:%x DEVID:%x CONFIGBASE:0x%x CONFIGOPTION:0x%x\n",
manfid, devid, ca->slot_info[slot].config_base, ca->slot_info[slot].config_option);
- // success!
- return 0;
+ // success!
+ return 0;
}
@@ -553,24 +553,24 @@ static int dvb_ca_en50221_parse_attributes(struct dvb_ca_private* ca, int slot)
* @param ca CA instance.
* @param slot Slot containing the CAM.
*/
-static int dvb_ca_en50221_set_configoption(struct dvb_ca_private* ca, int slot)
+static int dvb_ca_en50221_set_configoption(struct dvb_ca_private *ca, int slot)
{
- int configoption;
+ int configoption;
- dprintk ("%s\n", __FUNCTION__);
+ dprintk("%s\n", __FUNCTION__);
- /* set the config option */
+ /* set the config option */
ca->pub->write_attribute_mem(ca->pub, slot,
ca->slot_info[slot].config_base,
ca->slot_info[slot].config_option);
- /* check it */
- configoption = ca->pub->read_attribute_mem(ca->pub, slot, ca->slot_info[slot].config_base);
- dprintk("Set configoption 0x%x, read configoption 0x%x\n",
+ /* check it */
+ configoption = ca->pub->read_attribute_mem(ca->pub, slot, ca->slot_info[slot].config_base);
+ dprintk("Set configoption 0x%x, read configoption 0x%x\n",
ca->slot_info[slot].config_option, configoption & 0x3f);
- /* fine! */
- return 0;
+ /* fine! */
+ return 0;
}
@@ -588,17 +588,17 @@ static int dvb_ca_en50221_set_configoption(struct dvb_ca_private* ca, int slot)
*
* @return Number of bytes read, or < 0 on error
*/
-static int dvb_ca_en50221_read_data(struct dvb_ca_private* ca, int slot, u8* ebuf, int ecount)
+static int dvb_ca_en50221_read_data(struct dvb_ca_private *ca, int slot, u8 * ebuf, int ecount)
{
- int bytes_read;
- int status;
- u8 buf[HOST_LINK_BUF_SIZE];
- int i;
+ int bytes_read;
+ int status;
+ u8 buf[HOST_LINK_BUF_SIZE];
+ int i;
- dprintk ("%s\n", __FUNCTION__);
+ dprintk("%s\n", __FUNCTION__);
- /* check if we have space for a link buf in the rx_buffer */
- if (ebuf == NULL) {
+ /* check if we have space for a link buf in the rx_buffer */
+ if (ebuf == NULL) {
int buf_free;
down_read(&ca->slot_info[slot].sem);
@@ -610,99 +610,98 @@ static int dvb_ca_en50221_read_data(struct dvb_ca_private* ca, int slot, u8* ebu
buf_free = dvb_ringbuffer_free(&ca->slot_info[slot].rx_buffer);
up_read(&ca->slot_info[slot].sem);
- if (buf_free < (ca->slot_info[slot].link_buf_size + DVB_RINGBUFFER_PKTHDRSIZE)) {
- status = -EAGAIN;
- goto exit;
- }
- }
+ if (buf_free < (ca->slot_info[slot].link_buf_size + DVB_RINGBUFFER_PKTHDRSIZE)) {
+ status = -EAGAIN;
+ goto exit;
+ }
+ }
- /* check if there is data available */
+ /* check if there is data available */
if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0)
goto exit;
- if (!(status & STATUSREG_DA)) {
- /* no data */
- status = 0;
- goto exit;
- }
+ if (!(status & STATUSREG_DA)) {
+ /* no data */
+ status = 0;
+ goto exit;
+ }
- /* read the amount of data */
+ /* read the amount of data */
if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_SIZE_HIGH)) < 0)
goto exit;
- bytes_read = status << 8;
+ bytes_read = status << 8;
if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_SIZE_LOW)) < 0)
goto exit;
- bytes_read |= status;
+ bytes_read |= status;
- /* check it will fit */
- if (ebuf == NULL) {
- if (bytes_read > ca->slot_info[slot].link_buf_size) {
+ /* check it will fit */
+ if (ebuf == NULL) {
+ if (bytes_read > ca->slot_info[slot].link_buf_size) {
printk("dvb_ca adapter %d: CAM tried to send a buffer larger than the link buffer size (%i > %i)!\n",
ca->dvbdev->adapter->num, bytes_read, ca->slot_info[slot].link_buf_size);
- ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT;
- status = -EIO;
- goto exit;
- }
- if (bytes_read < 2) {
+ ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT;
+ status = -EIO;
+ goto exit;
+ }
+ if (bytes_read < 2) {
printk("dvb_ca adapter %d: CAM sent a buffer that was less than 2 bytes!\n",
ca->dvbdev->adapter->num);
- ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT;
- status = -EIO;
- goto exit;
- }
- } else {
- if (bytes_read > ecount) {
+ ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT;
+ status = -EIO;
+ goto exit;
+ }
+ } else {
+ if (bytes_read > ecount) {
printk("dvb_ca adapter %d: CAM tried to send a buffer larger than the ecount size!\n",
ca->dvbdev->adapter->num);
- status = -EIO;
- goto exit;
- }
- }
-
- /* fill the buffer */
- for(i=0; i < bytes_read; i++) {
- /* read byte and check */
+ status = -EIO;
+ goto exit;
+ }
+ }
+
+ /* fill the buffer */
+ for (i = 0; i < bytes_read; i++) {
+ /* read byte and check */
if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_DATA)) < 0)
goto exit;
- /* OK, store it in the buffer */
- buf[i] = status;
- }
+ /* OK, store it in the buffer */
+ buf[i] = status;
+ }
- /* check for read error (RE should now be 0) */
+ /* check for read error (RE should now be 0) */
if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0)
goto exit;
- if (status & STATUSREG_RE) {
+ if (status & STATUSREG_RE) {
ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT;
- status = -EIO;
- goto exit;
- }
+ status = -EIO;
+ goto exit;
+ }
- /* OK, add it to the receive buffer, or copy into external buffer if supplied */
- if (ebuf == NULL) {
+ /* OK, add it to the receive buffer, or copy into external buffer if supplied */
+ if (ebuf == NULL) {
down_read(&ca->slot_info[slot].sem);
if (ca->slot_info[slot].rx_buffer.data == NULL) {
up_read(&ca->slot_info[slot].sem);
status = -EIO;
goto exit;
}
- dvb_ringbuffer_pkt_write(&ca->slot_info[slot].rx_buffer, buf, bytes_read);
+ dvb_ringbuffer_pkt_write(&ca->slot_info[slot].rx_buffer, buf, bytes_read);
up_read(&ca->slot_info[slot].sem);
- } else {
- memcpy(ebuf, buf, bytes_read);
- }
+ } else {
+ memcpy(ebuf, buf, bytes_read);
+ }
dprintk("Received CA packet for slot %i connection id 0x%x last_frag:%i size:0x%x\n", slot,
buf[0], (buf[1] & 0x80) == 0, bytes_read);
- /* wake up readers when a last_fragment is received */
- if ((buf[1] & 0x80) == 0x00) {
- wake_up_interruptible(&ca->wait_queue);
- }
-
- status = bytes_read;
+ /* wake up readers when a last_fragment is received */
+ if ((buf[1] & 0x80) == 0x00) {
+ wake_up_interruptible(&ca->wait_queue);
+ }
+ status = bytes_read;
exit:
- return status;
+ return status;
}
@@ -718,71 +717,71 @@ exit:
*
* @return Number of bytes written, or < 0 on error.
*/
-static int dvb_ca_en50221_write_data(struct dvb_ca_private* ca, int slot, u8* buf, int bytes_write)
+static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot, u8 * buf, int bytes_write)
{
- int status;
- int i;
+ int status;
+ int i;
- dprintk ("%s\n", __FUNCTION__);
+ dprintk("%s\n", __FUNCTION__);
- // sanity check
+ // sanity check
if (bytes_write > ca->slot_info[slot].link_buf_size)
return -EINVAL;
- /* check if interface is actually waiting for us to read from it, or if a read is in progress */
+ /* check if interface is actually waiting for us to read from it, or if a read is in progress */
if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0)
goto exitnowrite;
- if (status & (STATUSREG_DA|STATUSREG_RE)) {
- status = -EAGAIN;
- goto exitnowrite;
- }
+ if (status & (STATUSREG_DA | STATUSREG_RE)) {
+ status = -EAGAIN;
+ goto exitnowrite;
+ }
- /* OK, set HC bit */
+ /* OK, set HC bit */
if ((status = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND,
IRQEN | CMDREG_HC)) != 0)
goto exit;
- /* check if interface is still free */
+ /* check if interface is still free */
if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0)
goto exit;
- if (!(status & STATUSREG_FR)) {
- /* it wasn't free => try again later */
- status = -EAGAIN;
- goto exit;
- }
+ if (!(status & STATUSREG_FR)) {
+ /* it wasn't free => try again later */
+ status = -EAGAIN;
+ goto exit;
+ }
- /* send the amount of data */
+ /* send the amount of data */
if ((status = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_SIZE_HIGH, bytes_write >> 8)) != 0)
goto exit;
if ((status = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_SIZE_LOW,
bytes_write & 0xff)) != 0)
goto exit;
- /* send the buffer */
- for(i=0; i < bytes_write; i++) {
+ /* send the buffer */
+ for (i = 0; i < bytes_write; i++) {
if ((status = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_DATA, buf[i])) != 0)
goto exit;
- }
+ }
- /* check for write error (WE should now be 0) */
+ /* check for write error (WE should now be 0) */
if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0)
goto exit;
- if (status & STATUSREG_WE) {
+ if (status & STATUSREG_WE) {
ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT;
- status = -EIO;
- goto exit;
- }
- status = bytes_write;
+ status = -EIO;
+ goto exit;
+ }
+ status = bytes_write;
dprintk("Wrote CA packet for slot %i, connection id 0x%x last_frag:%i size:0x%x\n", slot,
buf[0], (buf[1] & 0x80) == 0, bytes_write);
exit:
- ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN);
+ ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN);
exitnowrite:
- return status;
+ return status;
}
EXPORT_SYMBOL(dvb_ca_en50221_camchange_irq);
@@ -798,26 +797,25 @@ EXPORT_SYMBOL(dvb_ca_en50221_camchange_irq);
* @param ca CA instance.
* @param slot Slot to shut down.
*/
-static int dvb_ca_en50221_slot_shutdown(struct dvb_ca_private* ca, int slot)
+static int dvb_ca_en50221_slot_shutdown(struct dvb_ca_private *ca, int slot)
{
- dprintk ("%s\n", __FUNCTION__);
+ dprintk("%s\n", __FUNCTION__);
- down_write(&ca->slot_info[slot].sem);
- ca->pub->slot_shutdown(ca->pub, slot);
- ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_NONE;
- if (ca->slot_info[slot].rx_buffer.data)
- vfree(ca->slot_info[slot].rx_buffer.data);
- ca->slot_info[slot].rx_buffer.data = NULL;
- up_write(&ca->slot_info[slot].sem);
+ down_write(&ca->slot_info[slot].sem);
+ ca->pub->slot_shutdown(ca->pub, slot);
+ ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_NONE;
+ vfree(ca->slot_info[slot].rx_buffer.data);
+ ca->slot_info[slot].rx_buffer.data = NULL;
+ up_write(&ca->slot_info[slot].sem);
- /* need to wake up all processes to check if they're now
- trying to write to a defunct CAM */
- wake_up_interruptible(&ca->wait_queue);
+ /* need to wake up all processes to check if they're now
+ trying to write to a defunct CAM */
+ wake_up_interruptible(&ca->wait_queue);
- dprintk("Slot %i shutdown\n", slot);
+ dprintk("Slot %i shutdown\n", slot);
- /* success */
- return 0;
+ /* success */
+ return 0;
}
EXPORT_SYMBOL(dvb_ca_en50221_camready_irq);
@@ -829,24 +827,24 @@ EXPORT_SYMBOL(dvb_ca_en50221_camready_irq);
* @param slot Slot concerned.
* @param change_type One of the DVB_CA_CAMCHANGE_* values.
*/
-void dvb_ca_en50221_camchange_irq(struct dvb_ca_en50221* pubca, int slot, int change_type)
+void dvb_ca_en50221_camchange_irq(struct dvb_ca_en50221 *pubca, int slot, int change_type)
{
- struct dvb_ca_private* ca = (struct dvb_ca_private*) pubca->private;
+ struct dvb_ca_private *ca = (struct dvb_ca_private *) pubca->private;
- dprintk("CAMCHANGE IRQ slot:%i change_type:%i\n", slot, change_type);
+ dprintk("CAMCHANGE IRQ slot:%i change_type:%i\n", slot, change_type);
- switch(change_type) {
- case DVB_CA_EN50221_CAMCHANGE_REMOVED:
- case DVB_CA_EN50221_CAMCHANGE_INSERTED:
- break;
+ switch (change_type) {
+ case DVB_CA_EN50221_CAMCHANGE_REMOVED:
+ case DVB_CA_EN50221_CAMCHANGE_INSERTED:
+ break;
- default:
- return;
- }
+ default:
+ return;
+ }
- ca->slot_info[slot].camchange_type = change_type;
- atomic_inc(&ca->slot_info[slot].camchange_count);
- dvb_ca_en50221_thread_wakeup(ca);
+ ca->slot_info[slot].camchange_type = change_type;
+ atomic_inc(&ca->slot_info[slot].camchange_count);
+ dvb_ca_en50221_thread_wakeup(ca);
}
EXPORT_SYMBOL(dvb_ca_en50221_frda_irq);
@@ -857,16 +855,16 @@ EXPORT_SYMBOL(dvb_ca_en50221_frda_irq);
* @param ca CA instance.
* @param slot Slot concerned.
*/
-void dvb_ca_en50221_camready_irq(struct dvb_ca_en50221* pubca, int slot)
+void dvb_ca_en50221_camready_irq(struct dvb_ca_en50221 *pubca, int slot)
{
- struct dvb_ca_private* ca = (struct dvb_ca_private*) pubca->private;
+ struct dvb_ca_private *ca = (struct dvb_ca_private *) pubca->private;
- dprintk("CAMREADY IRQ slot:%i\n", slot);
+ dprintk("CAMREADY IRQ slot:%i\n", slot);
- if (ca->slot_info[slot].slot_state == DVB_CA_SLOTSTATE_WAITREADY) {
- ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_VALIDATE;
- dvb_ca_en50221_thread_wakeup(ca);
- }
+ if (ca->slot_info[slot].slot_state == DVB_CA_SLOTSTATE_WAITREADY) {
+ ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_VALIDATE;
+ dvb_ca_en50221_thread_wakeup(ca);
+ }
}
@@ -876,27 +874,27 @@ void dvb_ca_en50221_camready_irq(struct dvb_ca_en50221* pubca, int slot)
* @param ca CA instance.
* @param slot Slot concerned.
*/
-void dvb_ca_en50221_frda_irq(struct dvb_ca_en50221* pubca, int slot)
+void dvb_ca_en50221_frda_irq(struct dvb_ca_en50221 *pubca, int slot)
{
- struct dvb_ca_private* ca = (struct dvb_ca_private*) pubca->private;
- int flags;
+ struct dvb_ca_private *ca = (struct dvb_ca_private *) pubca->private;
+ int flags;
- dprintk("FR/DA IRQ slot:%i\n", slot);
+ dprintk("FR/DA IRQ slot:%i\n", slot);
- switch(ca->slot_info[slot].slot_state) {
- case DVB_CA_SLOTSTATE_LINKINIT:
- flags = ca->pub->read_cam_control(pubca, slot, CTRLIF_STATUS);
- if (flags & STATUSREG_DA) {
- dprintk("CAM supports DA IRQ\n");
- ca->slot_info[slot].da_irq_supported = 1;
+ switch (ca->slot_info[slot].slot_state) {
+ case DVB_CA_SLOTSTATE_LINKINIT:
+ flags = ca->pub->read_cam_control(pubca, slot, CTRLIF_STATUS);
+ if (flags & STATUSREG_DA) {
+ dprintk("CAM supports DA IRQ\n");
+ ca->slot_info[slot].da_irq_supported = 1;
}
- break;
+ break;
- case DVB_CA_SLOTSTATE_RUNNING:
+ case DVB_CA_SLOTSTATE_RUNNING:
if (ca->open)
dvb_ca_en50221_read_data(ca, slot, NULL, 0);
- break;
- }
+ break;
+ }
}
@@ -909,14 +907,14 @@ void dvb_ca_en50221_frda_irq(struct dvb_ca_en50221* pubca, int slot)
*
* @param ca CA instance.
*/
-static void dvb_ca_en50221_thread_wakeup(struct dvb_ca_private* ca)
+static void dvb_ca_en50221_thread_wakeup(struct dvb_ca_private *ca)
{
- dprintk ("%s\n", __FUNCTION__);
+ dprintk("%s\n", __FUNCTION__);
- ca->wakeup = 1;
- mb();
- wake_up_interruptible(&ca->thread_queue);
+ ca->wakeup = 1;
+ mb();
+ wake_up_interruptible(&ca->thread_queue);
}
/**
@@ -924,16 +922,16 @@ static void dvb_ca_en50221_thread_wakeup(struct dvb_ca_private* ca)
*
* @param ca CA instance.
*/
-static int dvb_ca_en50221_thread_should_wakeup(struct dvb_ca_private* ca)
+static int dvb_ca_en50221_thread_should_wakeup(struct dvb_ca_private *ca)
{
- if (ca->wakeup) {
- ca->wakeup = 0;
- return 1;
- }
+ if (ca->wakeup) {
+ ca->wakeup = 0;
+ return 1;
+ }
if (ca->exit)
return 1;
-
- return 0;
+
+ return 0;
}
@@ -942,50 +940,50 @@ static int dvb_ca_en50221_thread_should_wakeup(struct dvb_ca_private* ca)
*
* @param ca CA instance.
*/
-static void dvb_ca_en50221_thread_update_delay(struct dvb_ca_private* ca)
+static void dvb_ca_en50221_thread_update_delay(struct dvb_ca_private *ca)
{
- int delay;
- int curdelay = 100000000;
- int slot;
-
- for(slot=0; slot < ca->slot_count; slot++) {
- switch(ca->slot_info[slot].slot_state) {
- default:
- case DVB_CA_SLOTSTATE_NONE:
- case DVB_CA_SLOTSTATE_INVALID:
- delay = HZ*60;
- if (!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) {
- delay = HZ/10;
- }
- break;
-
- case DVB_CA_SLOTSTATE_UNINITIALISED:
- case DVB_CA_SLOTSTATE_WAITREADY:
- case DVB_CA_SLOTSTATE_VALIDATE:
- case DVB_CA_SLOTSTATE_WAITFR:
- case DVB_CA_SLOTSTATE_LINKINIT:
- delay = HZ/10;
- break;
-
- case DVB_CA_SLOTSTATE_RUNNING:
- delay = HZ*60;
- if (!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) {
- delay = HZ/10;
- }
- if (ca->open) {
- if ((!ca->slot_info[slot].da_irq_supported) ||
- (!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_DA))) {
- delay = HZ/100;
- }
- }
- break;
- }
+ int delay;
+ int curdelay = 100000000;
+ int slot;
+
+ for (slot = 0; slot < ca->slot_count; slot++) {
+ switch (ca->slot_info[slot].slot_state) {
+ default:
+ case DVB_CA_SLOTSTATE_NONE:
+ case DVB_CA_SLOTSTATE_INVALID:
+ delay = HZ * 60;
+ if (!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) {
+ delay = HZ / 10;
+ }
+ break;
+
+ case DVB_CA_SLOTSTATE_UNINITIALISED:
+ case DVB_CA_SLOTSTATE_WAITREADY:
+ case DVB_CA_SLOTSTATE_VALIDATE:
+ case DVB_CA_SLOTSTATE_WAITFR:
+ case DVB_CA_SLOTSTATE_LINKINIT:
+ delay = HZ / 10;
+ break;
+
+ case DVB_CA_SLOTSTATE_RUNNING:
+ delay = HZ * 60;
+ if (!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) {
+ delay = HZ / 10;
+ }
+ if (ca->open) {
+ if ((!ca->slot_info[slot].da_irq_supported) ||
+ (!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_DA))) {
+ delay = HZ / 10;
+ }
+ }
+ break;
+ }
if (delay < curdelay)
curdelay = delay;
- }
+ }
- ca->delay = curdelay;
+ ca->delay = curdelay;
}
@@ -993,160 +991,159 @@ static void dvb_ca_en50221_thread_update_delay(struct dvb_ca_private* ca)
/**
* Kernel thread which monitors CA slots for CAM changes, and performs data transfers.
*/
-static int dvb_ca_en50221_thread(void* data)
+static int dvb_ca_en50221_thread(void *data)
{
- struct dvb_ca_private *ca = (struct dvb_ca_private*) data;
- char name[15];
- int slot;
- int flags;
+ struct dvb_ca_private *ca = (struct dvb_ca_private *) data;
+ char name[15];
+ int slot;
+ int flags;
int status;
- int pktcount;
- void* rxbuf;
+ int pktcount;
+ void *rxbuf;
- dprintk ("%s\n", __FUNCTION__);
+ dprintk("%s\n", __FUNCTION__);
- /* setup kernel thread */
- snprintf(name, sizeof(name), "kdvb-ca-%i:%i", ca->dvbdev->adapter->num, ca->dvbdev->id);
+ /* setup kernel thread */
+ snprintf(name, sizeof(name), "kdvb-ca-%i:%i", ca->dvbdev->adapter->num, ca->dvbdev->id);
- lock_kernel ();
- daemonize (name);
- sigfillset (&current->blocked);
- unlock_kernel ();
+ lock_kernel();
+ daemonize(name);
+ sigfillset(&current->blocked);
+ unlock_kernel();
- /* choose the correct initial delay */
- dvb_ca_en50221_thread_update_delay(ca);
+ /* choose the correct initial delay */
+ dvb_ca_en50221_thread_update_delay(ca);
- /* main loop */
- while(!ca->exit) {
- /* sleep for a bit */
- if (!ca->wakeup) {
+ /* main loop */
+ while (!ca->exit) {
+ /* sleep for a bit */
+ if (!ca->wakeup) {
flags = wait_event_interruptible_timeout(ca->thread_queue,
dvb_ca_en50221_thread_should_wakeup(ca),
ca->delay);
- if ((flags == -ERESTARTSYS) || ca->exit) {
- /* got signal or quitting */
- break;
- }
- }
- ca->wakeup = 0;
-
- /* go through all the slots processing them */
- for(slot=0; slot < ca->slot_count; slot++) {
-
- // check the cam status + deal with CAMCHANGEs
- while(dvb_ca_en50221_check_camstatus(ca, slot)) {
- /* clear down an old CI slot if necessary */
+ if ((flags == -ERESTARTSYS) || ca->exit) {
+ /* got signal or quitting */
+ break;
+ }
+ }
+ ca->wakeup = 0;
+
+ /* go through all the slots processing them */
+ for (slot = 0; slot < ca->slot_count; slot++) {
+
+ // check the cam status + deal with CAMCHANGEs
+ while (dvb_ca_en50221_check_camstatus(ca, slot)) {
+ /* clear down an old CI slot if necessary */
if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_NONE)
dvb_ca_en50221_slot_shutdown(ca, slot);
- /* if a CAM is NOW present, initialise it */
- if (ca->slot_info[slot].camchange_type == DVB_CA_EN50221_CAMCHANGE_INSERTED) {
- ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_UNINITIALISED;
- }
-
- /* we've handled one CAMCHANGE */
- dvb_ca_en50221_thread_update_delay(ca);
- atomic_dec(&ca->slot_info[slot].camchange_count);
- }
-
- // CAM state machine
- switch(ca->slot_info[slot].slot_state) {
- case DVB_CA_SLOTSTATE_NONE:
- case DVB_CA_SLOTSTATE_INVALID:
- // no action needed
- break;
-
- case DVB_CA_SLOTSTATE_UNINITIALISED:
- ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_WAITREADY;
- ca->pub->slot_reset(ca->pub, slot);
- ca->slot_info[slot].timeout = jiffies + (INIT_TIMEOUT_SECS * HZ);
- break;
-
- case DVB_CA_SLOTSTATE_WAITREADY:
- if (time_after(jiffies, ca->slot_info[slot].timeout)) {
+ /* if a CAM is NOW present, initialise it */
+ if (ca->slot_info[slot].camchange_type == DVB_CA_EN50221_CAMCHANGE_INSERTED) {
+ ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_UNINITIALISED;
+ }
+
+ /* we've handled one CAMCHANGE */
+ dvb_ca_en50221_thread_update_delay(ca);
+ atomic_dec(&ca->slot_info[slot].camchange_count);
+ }
+
+ // CAM state machine
+ switch (ca->slot_info[slot].slot_state) {
+ case DVB_CA_SLOTSTATE_NONE:
+ case DVB_CA_SLOTSTATE_INVALID:
+ // no action needed
+ break;
+
+ case DVB_CA_SLOTSTATE_UNINITIALISED:
+ ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_WAITREADY;
+ ca->pub->slot_reset(ca->pub, slot);
+ ca->slot_info[slot].timeout = jiffies + (INIT_TIMEOUT_SECS * HZ);
+ break;
+
+ case DVB_CA_SLOTSTATE_WAITREADY:
+ if (time_after(jiffies, ca->slot_info[slot].timeout)) {
printk("dvb_ca adaptor %d: PC card did not respond :(\n",
ca->dvbdev->adapter->num);
- ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
- dvb_ca_en50221_thread_update_delay(ca);
- break;
- }
- // no other action needed; will automatically change state when ready
- break;
-
- case DVB_CA_SLOTSTATE_VALIDATE:
+ ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
+ dvb_ca_en50221_thread_update_delay(ca);
+ break;
+ }
+ // no other action needed; will automatically change state when ready
+ break;
+
+ case DVB_CA_SLOTSTATE_VALIDATE:
if (dvb_ca_en50221_parse_attributes(ca, slot)
!= 0) {
printk("dvb_ca adapter %d: Invalid PC card inserted :(\n",
ca->dvbdev->adapter->num);
- ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
- dvb_ca_en50221_thread_update_delay(ca);
- break;
- }
- if (dvb_ca_en50221_set_configoption(ca, slot) != 0) {
+ ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
+ dvb_ca_en50221_thread_update_delay(ca);
+ break;
+ }
+ if (dvb_ca_en50221_set_configoption(ca, slot) != 0) {
printk("dvb_ca adapter %d: Unable to initialise CAM :(\n",
ca->dvbdev->adapter->num);
- ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
- dvb_ca_en50221_thread_update_delay(ca);
- break;
- }
+ ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
+ dvb_ca_en50221_thread_update_delay(ca);
+ break;
+ }
if (ca->pub->write_cam_control(ca->pub, slot,
CTRLIF_COMMAND, CMDREG_RS) != 0) {
printk("dvb_ca adapter %d: Unable to reset CAM IF\n",
ca->dvbdev->adapter->num);
- ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
- dvb_ca_en50221_thread_update_delay(ca);
- break;
- }
-
- dprintk("DVB CAM validated successfully\n");
+ ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
+ dvb_ca_en50221_thread_update_delay(ca);
+ break;
+ }
+ dprintk("DVB CAM validated successfully\n");
- ca->slot_info[slot].timeout = jiffies + (INIT_TIMEOUT_SECS * HZ);
- ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_WAITFR;
- ca->wakeup = 1;
- break;
+ ca->slot_info[slot].timeout = jiffies + (INIT_TIMEOUT_SECS * HZ);
+ ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_WAITFR;
+ ca->wakeup = 1;
+ break;
- case DVB_CA_SLOTSTATE_WAITFR:
- if (time_after(jiffies, ca->slot_info[slot].timeout)) {
+ case DVB_CA_SLOTSTATE_WAITFR:
+ if (time_after(jiffies, ca->slot_info[slot].timeout)) {
printk("dvb_ca adapter %d: DVB CAM did not respond :(\n",
ca->dvbdev->adapter->num);
- ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
- dvb_ca_en50221_thread_update_delay(ca);
- break;
- }
-
- flags = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS);
- if (flags & STATUSREG_FR) {
- ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT;
- ca->wakeup = 1;
- }
- break;
-
- case DVB_CA_SLOTSTATE_LINKINIT:
- if (dvb_ca_en50221_link_init(ca, slot) != 0) {
- printk("dvb_ca adapter %d: DVB CAM link initialisation failed :(\n", ca->dvbdev->adapter->num);
- ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
- dvb_ca_en50221_thread_update_delay(ca);
- break;
- }
-
- rxbuf = vmalloc(RX_BUFFER_SIZE);
- if (rxbuf == NULL) {
- printk("dvb_ca adapter %d: Unable to allocate CAM rx buffer :(\n", ca->dvbdev->adapter->num);
- ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
- dvb_ca_en50221_thread_update_delay(ca);
- break;
- }
+ ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
+ dvb_ca_en50221_thread_update_delay(ca);
+ break;
+ }
+
+ flags = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS);
+ if (flags & STATUSREG_FR) {
+ ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT;
+ ca->wakeup = 1;
+ }
+ break;
+
+ case DVB_CA_SLOTSTATE_LINKINIT:
+ if (dvb_ca_en50221_link_init(ca, slot) != 0) {
+ printk("dvb_ca adapter %d: DVB CAM link initialisation failed :(\n", ca->dvbdev->adapter->num);
+ ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
+ dvb_ca_en50221_thread_update_delay(ca);
+ break;
+ }
+
+ rxbuf = vmalloc(RX_BUFFER_SIZE);
+ if (rxbuf == NULL) {
+ printk("dvb_ca adapter %d: Unable to allocate CAM rx buffer :(\n", ca->dvbdev->adapter->num);
+ ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
+ dvb_ca_en50221_thread_update_delay(ca);
+ break;
+ }
down_write(&ca->slot_info[slot].sem);
- dvb_ringbuffer_init(&ca->slot_info[slot].rx_buffer, rxbuf, RX_BUFFER_SIZE);
+ dvb_ringbuffer_init(&ca->slot_info[slot].rx_buffer, rxbuf, RX_BUFFER_SIZE);
up_write(&ca->slot_info[slot].sem);
- ca->pub->slot_ts_enable(ca->pub, slot);
- ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_RUNNING;
- dvb_ca_en50221_thread_update_delay(ca);
- printk("dvb_ca adapter %d: DVB CAM detected and initialised successfully\n", ca->dvbdev->adapter->num);
- break;
+ ca->pub->slot_ts_enable(ca->pub, slot);
+ ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_RUNNING;
+ dvb_ca_en50221_thread_update_delay(ca);
+ printk("dvb_ca adapter %d: DVB CAM detected and initialised successfully\n", ca->dvbdev->adapter->num);
+ break;
- case DVB_CA_SLOTSTATE_RUNNING:
+ case DVB_CA_SLOTSTATE_RUNNING:
if (!ca->open)
continue;
@@ -1155,35 +1152,35 @@ static int dvb_ca_en50221_thread(void* data)
break;
// poll mode
- pktcount = 0;
+ pktcount = 0;
while ((status = dvb_ca_en50221_read_data(ca, slot, NULL, 0)) > 0) {
if (!ca->open)
break;
- /* if a CAMCHANGE occurred at some point, do not do any more processing of this slot */
- if (dvb_ca_en50221_check_camstatus(ca, slot)) {
- // we dont want to sleep on the next iteration so we can handle the cam change
- ca->wakeup = 1;
- break;
- }
-
- /* check if we've hit our limit this time */
- if (++pktcount >= MAX_RX_PACKETS_PER_ITERATION) {
- // dont sleep; there is likely to be more data to read
- ca->wakeup = 1;
- break;
- }
- }
- break;
- }
- }
- }
-
- /* completed */
- ca->thread_pid = 0;
- mb();
- wake_up_interruptible (&ca->thread_queue);
- return 0;
+ /* if a CAMCHANGE occurred at some point, do not do any more processing of this slot */
+ if (dvb_ca_en50221_check_camstatus(ca, slot)) {
+ // we dont want to sleep on the next iteration so we can handle the cam change
+ ca->wakeup = 1;
+ break;
+ }
+
+ /* check if we've hit our limit this time */
+ if (++pktcount >= MAX_RX_PACKETS_PER_ITERATION) {
+ // dont sleep; there is likely to be more data to read
+ ca->wakeup = 1;
+ break;
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ /* completed */
+ ca->thread_pid = 0;
+ mb();
+ wake_up_interruptible(&ca->thread_queue);
+ return 0;
}
@@ -1205,62 +1202,62 @@ static int dvb_ca_en50221_thread(void* data)
static int dvb_ca_en50221_io_do_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, void *parg)
{
- struct dvb_device* dvbdev=(struct dvb_device*) file->private_data;
- struct dvb_ca_private* ca = (struct dvb_ca_private*) dvbdev->priv;
- int err=0;
- int slot;
-
- dprintk ("%s\n", __FUNCTION__);
-
- switch (cmd) {
- case CA_RESET:
- for(slot = 0; slot < ca->slot_count; slot++) {
- if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_NONE) {
- dvb_ca_en50221_slot_shutdown(ca, slot);
- if (ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)
+ struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
+ struct dvb_ca_private *ca = (struct dvb_ca_private *) dvbdev->priv;
+ int err = 0;
+ int slot;
+
+ dprintk("%s\n", __FUNCTION__);
+
+ switch (cmd) {
+ case CA_RESET:
+ for (slot = 0; slot < ca->slot_count; slot++) {
+ if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_NONE) {
+ dvb_ca_en50221_slot_shutdown(ca, slot);
+ if (ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)
dvb_ca_en50221_camchange_irq(ca->pub,
slot,
DVB_CA_EN50221_CAMCHANGE_INSERTED);
- }
- }
- ca->next_read_slot = 0;
- dvb_ca_en50221_thread_wakeup(ca);
- break;
+ }
+ }
+ ca->next_read_slot = 0;
+ dvb_ca_en50221_thread_wakeup(ca);
+ break;
case CA_GET_CAP: {
- struct ca_caps *caps = (struct ca_caps*) parg;
+ struct ca_caps *caps = (struct ca_caps *) parg;
- caps->slot_num=ca->slot_count;
- caps->slot_type=CA_CI_LINK;
- caps->descr_num=0;
- caps->descr_type=0;
- break;
- }
+ caps->slot_num = ca->slot_count;
+ caps->slot_type = CA_CI_LINK;
+ caps->descr_num = 0;
+ caps->descr_type = 0;
+ break;
+ }
case CA_GET_SLOT_INFO: {
- struct ca_slot_info *info=(struct ca_slot_info *)parg;
+ struct ca_slot_info *info = (struct ca_slot_info *) parg;
- if ((info->num > ca->slot_count) || (info->num < 0))
- return -EINVAL;
+ if ((info->num > ca->slot_count) || (info->num < 0))
+ return -EINVAL;
- info->type = CA_CI_LINK;
- info->flags = 0;
+ info->type = CA_CI_LINK;
+ info->flags = 0;
if ((ca->slot_info[info->num].slot_state != DVB_CA_SLOTSTATE_NONE)
&& (ca->slot_info[info->num].slot_state != DVB_CA_SLOTSTATE_INVALID)) {
- info->flags = CA_CI_MODULE_PRESENT;
- }
- if (ca->slot_info[info->num].slot_state == DVB_CA_SLOTSTATE_RUNNING) {
- info->flags |= CA_CI_MODULE_READY;
- }
- break;
- }
-
- default:
- err=-EINVAL;
- break;
- }
-
- return err;
+ info->flags = CA_CI_MODULE_PRESENT;
+ }
+ if (ca->slot_info[info->num].slot_state == DVB_CA_SLOTSTATE_RUNNING) {
+ info->flags |= CA_CI_MODULE_READY;
+ }
+ break;
+ }
+
+ default:
+ err = -EINVAL;
+ break;
+ }
+
+ return err;
}
@@ -1277,7 +1274,7 @@ static int dvb_ca_en50221_io_do_ioctl(struct inode *inode, struct file *file,
static int dvb_ca_en50221_io_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
- return dvb_usercopy(inode, file, cmd, arg, dvb_ca_en50221_io_do_ioctl);
+ return dvb_usercopy(inode, file, cmd, arg, dvb_ca_en50221_io_do_ioctl);
}
@@ -1294,127 +1291,127 @@ static int dvb_ca_en50221_io_ioctl(struct inode *inode, struct file *file,
static ssize_t dvb_ca_en50221_io_write(struct file *file,
const char __user * buf, size_t count, loff_t * ppos)
{
- struct dvb_device *dvbdev=(struct dvb_device *) file->private_data;
- struct dvb_ca_private *ca=(struct dvb_ca_private*) dvbdev->priv;
- u8 slot, connection_id;
- int status;
- char fragbuf[HOST_LINK_BUF_SIZE];
- int fragpos = 0;
- int fraglen;
- unsigned long timeout;
- int written;
-
- dprintk ("%s\n", __FUNCTION__);
-
- /* Incoming packet has a 2 byte header. hdr[0] = slot_id, hdr[1] = connection_id */
+ struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
+ struct dvb_ca_private *ca = (struct dvb_ca_private *) dvbdev->priv;
+ u8 slot, connection_id;
+ int status;
+ char fragbuf[HOST_LINK_BUF_SIZE];
+ int fragpos = 0;
+ int fraglen;
+ unsigned long timeout;
+ int written;
+
+ dprintk("%s\n", __FUNCTION__);
+
+ /* Incoming packet has a 2 byte header. hdr[0] = slot_id, hdr[1] = connection_id */
if (count < 2)
return -EINVAL;
- /* extract slot & connection id */
+ /* extract slot & connection id */
if (copy_from_user(&slot, buf, 1))
return -EFAULT;
if (copy_from_user(&connection_id, buf + 1, 1))
return -EFAULT;
- buf+=2;
- count-=2;
+ buf += 2;
+ count -= 2;
- /* check if the slot is actually running */
+ /* check if the slot is actually running */
if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_RUNNING)
return -EINVAL;
- /* fragment the packets & store in the buffer */
- while(fragpos < count) {
- fraglen = ca->slot_info[slot].link_buf_size - 2;
+ /* fragment the packets & store in the buffer */
+ while (fragpos < count) {
+ fraglen = ca->slot_info[slot].link_buf_size - 2;
if ((count - fragpos) < fraglen)
fraglen = count - fragpos;
- fragbuf[0] = connection_id;
- fragbuf[1] = ((fragpos + fraglen) < count) ? 0x80 : 0x00;
+ fragbuf[0] = connection_id;
+ fragbuf[1] = ((fragpos + fraglen) < count) ? 0x80 : 0x00;
if ((status = copy_from_user(fragbuf + 2, buf + fragpos, fraglen)) != 0)
goto exit;
- timeout = jiffies + HZ/2;
- written = 0;
- while(!time_after(jiffies, timeout)) {
+ timeout = jiffies + HZ / 2;
+ written = 0;
+ while (!time_after(jiffies, timeout)) {
/* check the CAM hasn't been removed/reset in the meantime */
if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_RUNNING) {
status = -EIO;
goto exit;
}
- status = dvb_ca_en50221_write_data(ca, slot, fragbuf, fraglen+2);
- if (status == (fraglen+2)) {
- written = 1;
- break;
+ status = dvb_ca_en50221_write_data(ca, slot, fragbuf, fraglen + 2);
+ if (status == (fraglen + 2)) {
+ written = 1;
+ break;
}
if (status != -EAGAIN)
goto exit;
- msleep(1);
- }
- if (!written) {
- status = -EIO;
- goto exit;
+ msleep(1);
+ }
+ if (!written) {
+ status = -EIO;
+ goto exit;
}
- fragpos += fraglen;
- }
- status = count + 2;
+ fragpos += fraglen;
+ }
+ status = count + 2;
exit:
- return status;
+ return status;
}
/**
* Condition for waking up in dvb_ca_en50221_io_read_condition
*/
-static int dvb_ca_en50221_io_read_condition(struct dvb_ca_private* ca, int* result, int* _slot)
+static int dvb_ca_en50221_io_read_condition(struct dvb_ca_private *ca, int *result, int *_slot)
{
- int slot;
- int slot_count = 0;
- int idx;
- int fraglen;
- int connection_id = -1;
- int found = 0;
- u8 hdr[2];
-
- slot = ca->next_read_slot;
- while((slot_count < ca->slot_count) && (!found)) {
+ int slot;
+ int slot_count = 0;
+ int idx;
+ int fraglen;
+ int connection_id = -1;
+ int found = 0;
+ u8 hdr[2];
+
+ slot = ca->next_read_slot;
+ while ((slot_count < ca->slot_count) && (!found)) {
if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_RUNNING)
goto nextslot;
- down_read(&ca->slot_info[slot].sem);
+ down_read(&ca->slot_info[slot].sem);
if (ca->slot_info[slot].rx_buffer.data == NULL) {
up_read(&ca->slot_info[slot].sem);
return 0;
}
- idx = dvb_ringbuffer_pkt_next(&ca->slot_info[slot].rx_buffer, -1, &fraglen);
- while(idx != -1) {
- dvb_ringbuffer_pkt_read(&ca->slot_info[slot].rx_buffer, idx, 0, hdr, 2, 0);
+ idx = dvb_ringbuffer_pkt_next(&ca->slot_info[slot].rx_buffer, -1, &fraglen);
+ while (idx != -1) {
+ dvb_ringbuffer_pkt_read(&ca->slot_info[slot].rx_buffer, idx, 0, hdr, 2, 0);
if (connection_id == -1)
connection_id = hdr[0];
- if ((hdr[0] == connection_id) && ((hdr[1] & 0x80) == 0)) {
- *_slot = slot;
- found = 1;
- break;
- }
+ if ((hdr[0] == connection_id) && ((hdr[1] & 0x80) == 0)) {
+ *_slot = slot;
+ found = 1;
+ break;
+ }
- idx = dvb_ringbuffer_pkt_next(&ca->slot_info[slot].rx_buffer, idx, &fraglen);
- }
+ idx = dvb_ringbuffer_pkt_next(&ca->slot_info[slot].rx_buffer, idx, &fraglen);
+ }
if (!found)
up_read(&ca->slot_info[slot].sem);
-nextslot:
- slot = (slot + 1) % ca->slot_count;
- slot_count++;
- }
+ nextslot:
+ slot = (slot + 1) % ca->slot_count;
+ slot_count++;
+ }
- ca->next_read_slot = slot;
- return found;
+ ca->next_read_slot = slot;
+ return found;
}
@@ -1431,91 +1428,91 @@ nextslot:
static ssize_t dvb_ca_en50221_io_read(struct file *file, char __user * buf,
size_t count, loff_t * ppos)
{
- struct dvb_device *dvbdev=(struct dvb_device *) file->private_data;
- struct dvb_ca_private *ca=(struct dvb_ca_private*) dvbdev->priv;
- int status;
- int result = 0;
- u8 hdr[2];
- int slot;
- int connection_id = -1;
- size_t idx, idx2;
- int last_fragment = 0;
- size_t fraglen;
- int pktlen;
- int dispose = 0;
-
- dprintk ("%s\n", __FUNCTION__);
-
- /* Outgoing packet has a 2 byte header. hdr[0] = slot_id, hdr[1] = connection_id */
+ struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
+ struct dvb_ca_private *ca = (struct dvb_ca_private *) dvbdev->priv;
+ int status;
+ int result = 0;
+ u8 hdr[2];
+ int slot;
+ int connection_id = -1;
+ size_t idx, idx2;
+ int last_fragment = 0;
+ size_t fraglen;
+ int pktlen;
+ int dispose = 0;
+
+ dprintk("%s\n", __FUNCTION__);
+
+ /* Outgoing packet has a 2 byte header. hdr[0] = slot_id, hdr[1] = connection_id */
if (count < 2)
return -EINVAL;
- /* wait for some data */
- if ((status = dvb_ca_en50221_io_read_condition(ca, &result, &slot)) == 0) {
+ /* wait for some data */
+ if ((status = dvb_ca_en50221_io_read_condition(ca, &result, &slot)) == 0) {
- /* if we're in nonblocking mode, exit immediately */
+ /* if we're in nonblocking mode, exit immediately */
if (file->f_flags & O_NONBLOCK)
return -EWOULDBLOCK;
- /* wait for some data */
+ /* wait for some data */
status = wait_event_interruptible(ca->wait_queue,
dvb_ca_en50221_io_read_condition
(ca, &result, &slot));
- }
- if ((status < 0) || (result < 0)) {
+ }
+ if ((status < 0) || (result < 0)) {
if (result)
return result;
- return status;
- }
-
- idx = dvb_ringbuffer_pkt_next(&ca->slot_info[slot].rx_buffer, -1, &fraglen);
- pktlen = 2;
- do {
- if (idx == -1) {
- printk("dvb_ca adapter %d: BUG: read packet ended before last_fragment encountered\n", ca->dvbdev->adapter->num);
- status = -EIO;
- goto exit;
- }
-
- dvb_ringbuffer_pkt_read(&ca->slot_info[slot].rx_buffer, idx, 0, hdr, 2, 0);
+ return status;
+ }
+
+ idx = dvb_ringbuffer_pkt_next(&ca->slot_info[slot].rx_buffer, -1, &fraglen);
+ pktlen = 2;
+ do {
+ if (idx == -1) {
+ printk("dvb_ca adapter %d: BUG: read packet ended before last_fragment encountered\n", ca->dvbdev->adapter->num);
+ status = -EIO;
+ goto exit;
+ }
+
+ dvb_ringbuffer_pkt_read(&ca->slot_info[slot].rx_buffer, idx, 0, hdr, 2, 0);
if (connection_id == -1)
connection_id = hdr[0];
- if (hdr[0] == connection_id) {
- if (pktlen < count) {
- if ((pktlen + fraglen - 2) > count) {
- fraglen = count - pktlen;
- } else {
- fraglen -= 2;
- }
+ if (hdr[0] == connection_id) {
+ if (pktlen < count) {
+ if ((pktlen + fraglen - 2) > count) {
+ fraglen = count - pktlen;
+ } else {
+ fraglen -= 2;
+ }
if ((status = dvb_ringbuffer_pkt_read(&ca->slot_info[slot].rx_buffer, idx, 2,
buf + pktlen, fraglen, 1)) < 0) {
- goto exit;
- }
- pktlen += fraglen;
- }
+ goto exit;
+ }
+ pktlen += fraglen;
+ }
if ((hdr[1] & 0x80) == 0)
last_fragment = 1;
- dispose = 1;
- }
+ dispose = 1;
+ }
- idx2 = dvb_ringbuffer_pkt_next(&ca->slot_info[slot].rx_buffer, idx, &fraglen);
+ idx2 = dvb_ringbuffer_pkt_next(&ca->slot_info[slot].rx_buffer, idx, &fraglen);
if (dispose)
dvb_ringbuffer_pkt_dispose(&ca->slot_info[slot].rx_buffer, idx);
- idx = idx2;
- dispose = 0;
- } while (!last_fragment);
+ idx = idx2;
+ dispose = 0;
+ } while (!last_fragment);
- hdr[0] = slot;
- hdr[1] = connection_id;
+ hdr[0] = slot;
+ hdr[1] = connection_id;
if ((status = copy_to_user(buf, hdr, 2)) != 0)
goto exit;
- status = pktlen;
+ status = pktlen;
-exit:
- up_read(&ca->slot_info[slot].sem);
- return status;
+ exit:
+ up_read(&ca->slot_info[slot].sem);
+ return status;
}
@@ -1529,36 +1526,36 @@ exit:
*/
static int dvb_ca_en50221_io_open(struct inode *inode, struct file *file)
{
- struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
- struct dvb_ca_private *ca = (struct dvb_ca_private*) dvbdev->priv;
- int err;
- int i;
+ struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
+ struct dvb_ca_private *ca = (struct dvb_ca_private *) dvbdev->priv;
+ int err;
+ int i;
- dprintk ("%s\n", __FUNCTION__);
+ dprintk("%s\n", __FUNCTION__);
if (!try_module_get(ca->pub->owner))
return -EIO;
- err=dvb_generic_open(inode, file);
- if (err<0)
- return err;
+ err = dvb_generic_open(inode, file);
+ if (err < 0)
+ return err;
- for(i=0; i< ca->slot_count; i++) {
+ for (i = 0; i < ca->slot_count; i++) {
- if (ca->slot_info[i].slot_state == DVB_CA_SLOTSTATE_RUNNING) {
- down_write(&ca->slot_info[i].sem);
+ if (ca->slot_info[i].slot_state == DVB_CA_SLOTSTATE_RUNNING) {
+ down_write(&ca->slot_info[i].sem);
if (ca->slot_info[i].rx_buffer.data != NULL) {
- dvb_ringbuffer_flush(&ca->slot_info[i].rx_buffer);
+ dvb_ringbuffer_flush(&ca->slot_info[i].rx_buffer);
}
- up_write(&ca->slot_info[i].sem);
- }
- }
+ up_write(&ca->slot_info[i].sem);
+ }
+ }
- ca->open = 1;
- dvb_ca_en50221_thread_update_delay(ca);
- dvb_ca_en50221_thread_wakeup(ca);
+ ca->open = 1;
+ dvb_ca_en50221_thread_update_delay(ca);
+ dvb_ca_en50221_thread_wakeup(ca);
- return 0;
+ return 0;
}
@@ -1572,21 +1569,21 @@ static int dvb_ca_en50221_io_open(struct inode *inode, struct file *file)
*/
static int dvb_ca_en50221_io_release(struct inode *inode, struct file *file)
{
- struct dvb_device *dvbdev=(struct dvb_device *) file->private_data;
- struct dvb_ca_private *ca=(struct dvb_ca_private*) dvbdev->priv;
+ struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
+ struct dvb_ca_private *ca = (struct dvb_ca_private *) dvbdev->priv;
int err = 0;
- dprintk ("%s\n", __FUNCTION__);
+ dprintk("%s\n", __FUNCTION__);
- /* mark the CA device as closed */
- ca->open = 0;
- dvb_ca_en50221_thread_update_delay(ca);
+ /* mark the CA device as closed */
+ ca->open = 0;
+ dvb_ca_en50221_thread_update_delay(ca);
- err=dvb_generic_release(inode, file);
+ err = dvb_generic_release(inode, file);
module_put(ca->pub->owner);
- return 0;
+ return 0;
}
@@ -1598,56 +1595,57 @@ static int dvb_ca_en50221_io_release(struct inode *inode, struct file *file)
*
* @return Standard poll mask.
*/
-static unsigned int dvb_ca_en50221_io_poll(struct file *file, poll_table *wait)
+static unsigned int dvb_ca_en50221_io_poll(struct file *file, poll_table * wait)
{
- struct dvb_device* dvbdev = (struct dvb_device*) file->private_data;
- struct dvb_ca_private* ca = (struct dvb_ca_private*) dvbdev->priv;
- unsigned int mask=0;
- int slot;
- int result = 0;
+ struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
+ struct dvb_ca_private *ca = (struct dvb_ca_private *) dvbdev->priv;
+ unsigned int mask = 0;
+ int slot;
+ int result = 0;
- dprintk ("%s\n", __FUNCTION__);
+ dprintk("%s\n", __FUNCTION__);
- if (dvb_ca_en50221_io_read_condition(ca, &result, &slot) == 1) {
- up_read(&ca->slot_info[slot].sem);
- mask |= POLLIN;
- }
+ if (dvb_ca_en50221_io_read_condition(ca, &result, &slot) == 1) {
+ up_read(&ca->slot_info[slot].sem);
+ mask |= POLLIN;
+ }
- /* if there is something, return now */
+ /* if there is something, return now */
if (mask)
return mask;
- /* wait for something to happen */
- poll_wait(file, &ca->wait_queue, wait);
+ /* wait for something to happen */
+ poll_wait(file, &ca->wait_queue, wait);
- if (dvb_ca_en50221_io_read_condition(ca, &result, &slot) == 1) {
- up_read(&ca->slot_info[slot].sem);
- mask |= POLLIN;
- }
+ if (dvb_ca_en50221_io_read_condition(ca, &result, &slot) == 1) {
+ up_read(&ca->slot_info[slot].sem);
+ mask |= POLLIN;
+ }
- return mask;
+ return mask;
}
EXPORT_SYMBOL(dvb_ca_en50221_init);
static struct file_operations dvb_ca_fops = {
- .owner = THIS_MODULE,
- .read = dvb_ca_en50221_io_read,
- .write = dvb_ca_en50221_io_write,
- .ioctl = dvb_ca_en50221_io_ioctl,
- .open = dvb_ca_en50221_io_open,
- .release= dvb_ca_en50221_io_release,
- .poll = dvb_ca_en50221_io_poll,
+ .owner = THIS_MODULE,
+ .read = dvb_ca_en50221_io_read,
+ .write = dvb_ca_en50221_io_write,
+ .ioctl = dvb_ca_en50221_io_ioctl,
+ .open = dvb_ca_en50221_io_open,
+ .release = dvb_ca_en50221_io_release,
+ .poll = dvb_ca_en50221_io_poll,
};
static struct dvb_device dvbdev_ca = {
- .priv = NULL,
- .users = 1,
- .readers= 1,
- .writers= 1,
- .fops = &dvb_ca_fops,
+ .priv = NULL,
+ .users = 1,
+ .readers = 1,
+ .writers = 1,
+ .fops = &dvb_ca_fops,
};
+
/* ******************************************************************************** */
/* Initialisation/shutdown functions */
@@ -1665,79 +1663,80 @@ static struct dvb_device dvbdev_ca = {
int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter,
struct dvb_ca_en50221 *pubca, int flags, int slot_count)
{
- int ret;
- struct dvb_ca_private* ca = NULL;
- int i;
+ int ret;
+ struct dvb_ca_private *ca = NULL;
+ int i;
- dprintk ("%s\n", __FUNCTION__);
+ dprintk("%s\n", __FUNCTION__);
if (slot_count < 1)
return -EINVAL;
- /* initialise the system data */
+ /* initialise the system data */
if ((ca =
(struct dvb_ca_private *) kmalloc(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) {
- 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);
- ca->exit = 0;
- ca->open = 0;
- ca->wakeup = 0;
- ca->next_read_slot = 0;
- pubca->private = ca;
-
- /* register the DVB device */
- ret = dvb_register_device(dvb_adapter, &ca->dvbdev, &dvbdev_ca, ca, DVB_DEVICE_CA);
+ 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) {
+ 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);
+ ca->exit = 0;
+ ca->open = 0;
+ ca->wakeup = 0;
+ ca->next_read_slot = 0;
+ pubca->private = ca;
+
+ /* register the DVB device */
+ ret = dvb_register_device(dvb_adapter, &ca->dvbdev, &dvbdev_ca, ca, DVB_DEVICE_CA);
if (ret)
goto error;
- /* now initialise each slot */
- for(i=0; i< slot_count; i++) {
- memset(&ca->slot_info[i], 0, sizeof(struct dvb_ca_slot));
- ca->slot_info[i].slot_state = DVB_CA_SLOTSTATE_NONE;
- atomic_set(&ca->slot_info[i].camchange_count, 0);
- ca->slot_info[i].camchange_type = DVB_CA_EN50221_CAMCHANGE_REMOVED;
- init_rwsem(&ca->slot_info[i].sem);
- }
-
- if (signal_pending(current)) {
- ret = -EINTR;
- goto error;
- }
- mb();
-
- /* create a kthread for monitoring this CA device */
- ret = kernel_thread (dvb_ca_en50221_thread, ca, 0);
- if (ret < 0) {
- printk("dvb_ca_init: failed to start kernel_thread (%d)\n", ret);
- goto error;
- }
- ca->thread_pid = ret;
- return 0;
-
-error:
- if (ca != NULL) {
+ /* now initialise each slot */
+ for (i = 0; i < slot_count; i++) {
+ memset(&ca->slot_info[i], 0, sizeof(struct dvb_ca_slot));
+ ca->slot_info[i].slot_state = DVB_CA_SLOTSTATE_NONE;
+ atomic_set(&ca->slot_info[i].camchange_count, 0);
+ ca->slot_info[i].camchange_type = DVB_CA_EN50221_CAMCHANGE_REMOVED;
+ init_rwsem(&ca->slot_info[i].sem);
+ }
+
+ if (signal_pending(current)) {
+ ret = -EINTR;
+ goto error;
+ }
+ mb();
+
+ /* create a kthread for monitoring this CA device */
+
+ ret = kernel_thread(dvb_ca_en50221_thread, ca, 0);
+
+ if (ret < 0) {
+ printk("dvb_ca_init: failed to start kernel_thread (%d)\n", ret);
+ goto error;
+ }
+ ca->thread_pid = ret;
+ return 0;
+
+ error:
+ if (ca != NULL) {
if (ca->dvbdev != NULL)
dvb_unregister_device(ca->dvbdev);
- if (ca->slot_info != NULL)
- kfree(ca->slot_info);
- kfree(ca);
- }
- pubca->private = NULL;
- return ret;
+ kfree(ca->slot_info);
+ kfree(ca);
+ }
+ pubca->private = NULL;
+ return ret;
}
EXPORT_SYMBOL(dvb_ca_en50221_release);
@@ -1749,32 +1748,31 @@ EXPORT_SYMBOL(dvb_ca_en50221_release);
* @param ca_dev The dvb_device_t instance for the CA device.
* @param ca The associated dvb_ca instance.
*/
-void dvb_ca_en50221_release(struct dvb_ca_en50221* pubca)
+void dvb_ca_en50221_release(struct dvb_ca_en50221 *pubca)
{
- struct dvb_ca_private* ca = (struct dvb_ca_private*) pubca->private;
- int i;
+ struct dvb_ca_private *ca = (struct dvb_ca_private *) pubca->private;
+ int i;
- dprintk ("%s\n", __FUNCTION__);
+ dprintk("%s\n", __FUNCTION__);
- /* shutdown the thread if there was one */
- if (ca->thread_pid) {
- if (kill_proc(ca->thread_pid, 0, 1) == -ESRCH) {
+ /* shutdown the thread if there was one */
+ if (ca->thread_pid) {
+ if (kill_proc(ca->thread_pid, 0, 1) == -ESRCH) {
printk("dvb_ca_release adapter %d: thread PID %d already died\n",
ca->dvbdev->adapter->num, ca->thread_pid);
- } else {
- ca->exit = 1;
- mb();
- dvb_ca_en50221_thread_wakeup(ca);
- wait_event_interruptible(ca->thread_queue, ca->thread_pid == 0);
- }
- }
-
- for(i=0; i< ca->slot_count; i++) {
- dvb_ca_en50221_slot_shutdown(ca, i);
- }
- kfree(ca->slot_info);
- dvb_unregister_device(ca->dvbdev);
- kfree(ca);
- pubca->private = NULL;
+ } else {
+ ca->exit = 1;
+ mb();
+ dvb_ca_en50221_thread_wakeup(ca);
+ wait_event_interruptible(ca->thread_queue, ca->thread_pid == 0);
+ }
+ }
+
+ for (i = 0; i < ca->slot_count; i++) {
+ dvb_ca_en50221_slot_shutdown(ca, i);
+ }
+ kfree(ca->slot_info);
+ dvb_unregister_device(ca->dvbdev);
+ kfree(ca);
+ pubca->private = NULL;
}
-
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c
index 7901398d6e3f2..ac9889d222882 100644
--- a/drivers/media/dvb/dvb-core/dvb_demux.c
+++ b/drivers/media/dvb/dvb-core/dvb_demux.c
@@ -1,4 +1,4 @@
-/*
+/*
* dvb_demux.c - DVB kernel demux API
*
* Copyright (C) 2000-2001 Ralph Metzler <ralph@convergence.de>
@@ -27,29 +27,29 @@
#include <linux/module.h>
#include <linux/poll.h>
#include <linux/string.h>
- #include <linux/crc32.h>
+#include <linux/crc32.h>
#include <asm/uaccess.h>
#include "dvb_demux.h"
-#define NOBUFS
-/*
+#define NOBUFS
+/*
** #define DVB_DEMUX_SECTION_LOSS_LOG to monitor payload loss in the syslog
*/
// #define DVB_DEMUX_SECTION_LOSS_LOG
-LIST_HEAD(dmx_muxs);
+static LIST_HEAD(dmx_muxs);
-int dmx_register_demux(struct dmx_demux *demux)
+static int dmx_register_demux(struct dmx_demux *demux)
{
demux->users = 0;
list_add(&demux->reg_list, &dmx_muxs);
return 0;
}
-int dmx_unregister_demux(struct dmx_demux* demux)
+static int dmx_unregister_demux(struct dmx_demux* demux)
{
struct list_head *pos, *n, *head=&dmx_muxs;
@@ -66,14 +66,6 @@ int dmx_unregister_demux(struct dmx_demux* demux)
}
-struct list_head *dmx_get_demuxes(void)
-{
- if (list_empty(&dmx_muxs))
- return NULL;
-
- return &dmx_muxs;
-}
-
/******************************************************************************
* static inlined helper functions
******************************************************************************/
@@ -93,10 +85,10 @@ static inline u16 ts_pid(const u8 *buf)
static inline u8 payload(const u8 *tsp)
{
- if (!(tsp[3]&0x10)) // no payload?
+ if (!(tsp[3] & 0x10)) // no payload?
return 0;
- if (tsp[3]&0x20) { // adaptation field?
- if (tsp[4]>183) // corrupted data?
+ if (tsp[3] & 0x20) { // adaptation field?
+ if (tsp[4] > 183) // corrupted data?
return 0;
else
return 184-1-tsp[4];
@@ -105,19 +97,6 @@ static inline u8 payload(const u8 *tsp)
}
-void dvb_set_crc32(u8 *data, int length)
-{
- u32 crc;
-
- crc = crc32_be(~0, data, length);
-
- data[length] = (crc >> 24) & 0xff;
- data[length+1] = (crc >> 16) & 0xff;
- data[length+2] = (crc >> 8) & 0xff;
- data[length+3] = (crc) & 0xff;
-}
-
-
static u32 dvb_dmx_crc32 (struct dvb_demux_feed *f, const u8 *src, size_t len)
{
return (f->feed.sec.crc_val = crc32_be (f->feed.sec.crc_val, src, len));
@@ -134,7 +113,7 @@ static void dvb_dmx_memcopy (struct dvb_demux_feed *f, u8 *d, const u8 *s, size_
* Software filter functions
******************************************************************************/
-static inline int dvb_dmx_swfilter_payload (struct dvb_demux_feed *feed, const u8 *buf)
+static inline int dvb_dmx_swfilter_payload (struct dvb_demux_feed *feed, const u8 *buf)
{
int count = payload(buf);
int p;
@@ -159,11 +138,11 @@ static inline int dvb_dmx_swfilter_payload (struct dvb_demux_feed *feed, const u
feed->peslen += count;
- return feed->cb.ts (&buf[p], count, NULL, 0, &feed->feed.ts, DMX_OK);
+ return feed->cb.ts (&buf[p], count, NULL, 0, &feed->feed.ts, DMX_OK);
}
-static int dvb_dmx_swfilter_sectionfilter (struct dvb_demux_feed *feed,
+static int dvb_dmx_swfilter_sectionfilter (struct dvb_demux_feed *feed,
struct dvb_demux_filter *f)
{
u8 neq = 0;
@@ -181,8 +160,8 @@ static int dvb_dmx_swfilter_sectionfilter (struct dvb_demux_feed *feed,
if (f->doneq && !neq)
return 0;
- return feed->cb.sec (feed->feed.sec.secbuf, feed->feed.sec.seclen,
- NULL, 0, &f->filter, DMX_OK);
+ return feed->cb.sec (feed->feed.sec.secbuf, feed->feed.sec.seclen,
+ NULL, 0, &f->filter, DMX_OK);
}
@@ -203,7 +182,7 @@ static inline int dvb_dmx_swfilter_section_feed (struct dvb_demux_feed *feed)
section_syntax_indicator = ((sec->secbuf[1] & 0x80) != 0);
if (section_syntax_indicator &&
demux->check_crc32(feed, sec->secbuf, sec->seclen))
- return -1;
+ return -1;
}
do {
@@ -232,27 +211,27 @@ static void dvb_dmx_swfilter_section_new(struct dvb_demux_feed *feed)
*/
if(sec->secbuf[0] != 0xff || sec->secbuf[n-1] != 0xff)
{
- printk("dvb_demux.c section ts padding loss: %d/%d\n",
+ printk("dvb_demux.c section ts padding loss: %d/%d\n",
n, sec->tsfeedp);
printk("dvb_demux.c pad data:");
for(i = 0; i < n; i++)
printk(" %02x", sec->secbuf[i]);
printk("\n");
- }
- }
+ }
+ }
#endif
sec->tsfeedp = sec->secbufp = sec->seclen = 0;
sec->secbuf = sec->secbuf_base;
- }
+}
-/*
+/*
** Losless Section Demux 1.4.1 by Emard
** Valsecchi Patrick:
** - middle of section A (no PUSI)
-** - end of section A and start of section B
+** - end of section A and start of section B
** (with PUSI pointing to the start of the second section)
-**
+**
** In this case, without feed->pusi_seen you'll receive a garbage section
** consisting of the end of section A. Basically because tsfeedp
** is incemented and the use=0 condition is not raised
@@ -276,7 +255,7 @@ static int dvb_dmx_swfilter_section_copy_dump(struct dvb_demux_feed *feed, const
if(sec->tsfeedp + len > DMX_MAX_SECFEED_SIZE)
{
#ifdef DVB_DEMUX_SECTION_LOSS_LOG
- printk("dvb_demux.c section buffer full loss: %d/%d\n",
+ printk("dvb_demux.c section buffer full loss: %d/%d\n",
sec->tsfeedp + len - DMX_MAX_SECFEED_SIZE, DMX_MAX_SECFEED_SIZE);
#endif
len = DMX_MAX_SECFEED_SIZE - sec->tsfeedp;
@@ -302,38 +281,38 @@ static int dvb_dmx_swfilter_section_copy_dump(struct dvb_demux_feed *feed, const
for(n = 0; sec->secbufp + 2 < limit; n++)
{
seclen = section_length(sec->secbuf);
- if(seclen <= 0 || seclen > DMX_MAX_SECFEED_SIZE
+ if(seclen <= 0 || seclen > DMX_MAX_SECFEED_SIZE
|| seclen + sec->secbufp > limit)
return 0;
sec->seclen = seclen;
sec->crc_val = ~0;
/* dump [secbuf .. secbuf+seclen) */
if(feed->pusi_seen)
- dvb_dmx_swfilter_section_feed(feed);
+ dvb_dmx_swfilter_section_feed(feed);
#ifdef DVB_DEMUX_SECTION_LOSS_LOG
else
printk("dvb_demux.c pusi not seen, discarding section data\n");
#endif
sec->secbufp += seclen; /* secbufp and secbuf moving together is */
sec->secbuf += seclen; /* redundand but saves pointer arithmetic */
- }
-
- return 0;
}
+ return 0;
+}
+
-static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed, const u8 *buf)
+static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed, const u8 *buf)
{
u8 p, count;
int ccok, dc_i = 0;
u8 cc;
count = payload(buf);
-
+
if (count == 0) /* count == 0 if no payload or out of range */
- return -1;
+ return -1;
- p = 188-count; /* payload start */
+ p = 188 - count; /* payload start */
cc = buf[3] & 0x0f;
ccok = ((feed->cc + 1) & 0x0f) == cc;
@@ -376,7 +355,7 @@ static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed, const u8
}
#ifdef DVB_DEMUX_SECTION_LOSS_LOG
else
- if(count > 0)
+ if (count > 0)
printk("dvb_demux.c PUSI=1 but %d bytes lost\n", count);
#endif
} else {
@@ -400,9 +379,9 @@ static inline void dvb_dmx_swfilter_packet_type(struct dvb_demux_feed *feed, con
if (feed->ts_type & TS_PAYLOAD_ONLY)
dvb_dmx_swfilter_payload(feed, buf);
else
- feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts, DMX_OK);
+ feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts, DMX_OK);
}
- if (feed->ts_type & TS_DECODER)
+ if (feed->ts_type & TS_DECODER)
if (feed->demux->write_to_decoder)
feed->demux->write_to_decoder(feed, buf, 188);
break;
@@ -424,7 +403,7 @@ static inline void dvb_dmx_swfilter_packet_type(struct dvb_demux_feed *feed, con
((f)->feed.ts.is_filtering) && \
(((f)->ts_type & (TS_PACKET|TS_PAYLOAD_ONLY)) == TS_PACKET))
-void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf)
+static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf)
{
struct dvb_demux_feed *feed;
struct list_head *pos, *head=&demux->feed_list;
@@ -443,7 +422,7 @@ void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf)
continue;
if (feed->pid == pid) {
- dvb_dmx_swfilter_packet_type (feed, buf);
+ dvb_dmx_swfilter_packet_type(feed, buf);
if (DVR_FEED(feed))
continue;
}
@@ -452,15 +431,14 @@ void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf)
feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts, DMX_OK);
}
}
-EXPORT_SYMBOL(dvb_dmx_swfilter_packet);
void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf, size_t count)
{
spin_lock(&demux->lock);
while (count--) {
- if(buf[0] == 0x47) {
- dvb_dmx_swfilter_packet(demux, buf);
+ if(buf[0] == 0x47) {
+ dvb_dmx_swfilter_packet(demux, buf);
}
buf += 188;
}
@@ -472,8 +450,8 @@ EXPORT_SYMBOL(dvb_dmx_swfilter_packets);
void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count)
{
- int p = 0,i, j;
-
+ int p = 0, i, j;
+
spin_lock(&demux->lock);
if ((i = demux->tsbufp)) {
@@ -484,7 +462,7 @@ void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count)
}
memcpy(&demux->tsbuf[i], buf, j);
if (demux->tsbuf[0] == 0x47)
- dvb_dmx_swfilter_packet(demux, demux->tsbuf);
+ dvb_dmx_swfilter_packet(demux, demux->tsbuf);
demux->tsbufp = 0;
p += j;
}
@@ -500,7 +478,7 @@ void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count)
demux->tsbufp=i;
goto bailout;
}
- } else
+ } else
p++;
}
@@ -544,7 +522,7 @@ void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count)
demux->tsbufp=i;
goto bailout;
}
- } else {
+ } else {
p++;
}
}
@@ -595,8 +573,8 @@ static int dvb_demux_feed_find(struct dvb_demux_feed *feed)
if (entry == feed)
return 1;
- return 0;
- }
+ return 0;
+}
static void dvb_demux_feed_add(struct dvb_demux_feed *feed)
{
@@ -619,16 +597,16 @@ static void dvb_demux_feed_del(struct dvb_demux_feed *feed)
printk(KERN_ERR "%s: feed not in list (type=%x state=%x pid=%x)\n",
__FUNCTION__, feed->type, feed->state, feed->pid);
goto out;
-}
+ }
list_del(&feed->list_head);
out:
spin_unlock_irq(&feed->demux->lock);
}
-static int dmx_ts_feed_set (struct dmx_ts_feed* ts_feed, u16 pid, int ts_type,
- enum dmx_ts_pes pes_type, size_t callback_length,
- size_t circular_buffer_size, int descramble,
+static int dmx_ts_feed_set (struct dmx_ts_feed* ts_feed, u16 pid, int ts_type,
+ enum dmx_ts_pes pes_type, size_t callback_length,
+ size_t circular_buffer_size, int descramble,
struct timespec timeout)
{
struct dvb_demux_feed *feed = (struct dvb_demux_feed *) ts_feed;
@@ -636,7 +614,7 @@ static int dmx_ts_feed_set (struct dmx_ts_feed* ts_feed, u16 pid, int ts_type,
if (pid > DMX_MAX_PID)
return -EINVAL;
-
+
if (down_interruptible (&demux->mutex))
return -ERESTARTSYS;
@@ -646,7 +624,7 @@ static int dmx_ts_feed_set (struct dmx_ts_feed* ts_feed, u16 pid, int ts_type,
return -EINVAL;
}
- if (demux->pesfilter[pes_type] &&
+ if (demux->pesfilter[pes_type] &&
demux->pesfilter[pes_type] != feed) {
up(&demux->mutex);
return -EINVAL;
@@ -682,7 +660,7 @@ static int dmx_ts_feed_set (struct dmx_ts_feed* ts_feed, u16 pid, int ts_type,
}
#endif
}
-
+
feed->state = DMX_STATE_READY;
up(&demux->mutex);
@@ -722,7 +700,7 @@ static int dmx_ts_feed_start_filtering(struct dmx_ts_feed* ts_feed)
return 0;
}
-
+
static int dmx_ts_feed_stop_filtering(struct dmx_ts_feed* ts_feed)
{
struct dvb_demux_feed *feed = (struct dvb_demux_feed *) ts_feed;
@@ -732,7 +710,7 @@ static int dmx_ts_feed_stop_filtering(struct dmx_ts_feed* ts_feed)
if (down_interruptible (&demux->mutex))
return -ERESTARTSYS;
- if (feed->state<DMX_STATE_GO) {
+ if (feed->state < DMX_STATE_GO) {
up(&demux->mutex);
return -EINVAL;
}
@@ -742,7 +720,7 @@ static int dmx_ts_feed_stop_filtering(struct dmx_ts_feed* ts_feed)
return -ENODEV;
}
- ret = demux->stop_feed(feed);
+ ret = demux->stop_feed(feed);
spin_lock_irq(&demux->lock);
ts_feed->is_filtering = 0;
@@ -753,7 +731,7 @@ static int dmx_ts_feed_stop_filtering(struct dmx_ts_feed* ts_feed)
return ret;
}
-static int dvbdmx_allocate_ts_feed (struct dmx_demux *dmx, struct dmx_ts_feed **ts_feed,
+static int dvbdmx_allocate_ts_feed (struct dmx_demux *dmx, struct dmx_ts_feed **ts_feed,
dmx_ts_cb callback)
{
struct dvb_demux *demux = (struct dvb_demux *) dmx;
@@ -792,7 +770,7 @@ static int dvbdmx_allocate_ts_feed (struct dmx_demux *dmx, struct dmx_ts_feed **
feed->filter->type = DMX_TYPE_TS;
feed->filter->feed = feed;
feed->filter->state = DMX_STATE_READY;
-
+
up(&demux->mutex);
return 0;
@@ -812,8 +790,8 @@ static int dvbdmx_release_ts_feed(struct dmx_demux *dmx, struct dmx_ts_feed *ts_
}
#ifndef NOBUFS
- vfree(feed->buffer);
- feed->buffer=0;
+ vfree(feed->buffer);
+ feed->buffer=0;
#endif
feed->state = DMX_STATE_FREE;
@@ -821,8 +799,8 @@ static int dvbdmx_release_ts_feed(struct dmx_demux *dmx, struct dmx_ts_feed *ts_
dvb_demux_feed_del(feed);
- feed->pid = 0xffff;
-
+ feed->pid = 0xffff;
+
if (feed->ts_type & TS_DECODER && feed->pes_type < DMX_TS_PES_OTHER)
demux->pesfilter[feed->pes_type] = NULL;
@@ -835,64 +813,65 @@ static int dvbdmx_release_ts_feed(struct dmx_demux *dmx, struct dmx_ts_feed *ts_
* dmx_section_feed API calls
******************************************************************************/
-static int dmx_section_feed_allocate_filter(struct dmx_section_feed* feed,
- struct dmx_section_filter** filter)
+static int dmx_section_feed_allocate_filter(struct dmx_section_feed* feed,
+ struct dmx_section_filter** filter)
{
- struct dvb_demux_feed *dvbdmxfeed=(struct dvb_demux_feed *) feed;
- struct dvb_demux *dvbdemux=dvbdmxfeed->demux;
+ struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *) feed;
+ struct dvb_demux *dvbdemux = dvbdmxfeed->demux;
struct dvb_demux_filter *dvbdmxfilter;
if (down_interruptible (&dvbdemux->mutex))
return -ERESTARTSYS;
- dvbdmxfilter=dvb_dmx_filter_alloc(dvbdemux);
+ dvbdmxfilter = dvb_dmx_filter_alloc(dvbdemux);
if (!dvbdmxfilter) {
up(&dvbdemux->mutex);
return -EBUSY;
}
spin_lock_irq(&dvbdemux->lock);
- *filter=&dvbdmxfilter->filter;
- (*filter)->parent=feed;
- (*filter)->priv=NULL;
- dvbdmxfilter->feed=dvbdmxfeed;
- dvbdmxfilter->type=DMX_TYPE_SEC;
- dvbdmxfilter->state=DMX_STATE_READY;
-
- dvbdmxfilter->next=dvbdmxfeed->filter;
- dvbdmxfeed->filter=dvbdmxfilter;
+ *filter = &dvbdmxfilter->filter;
+ (*filter)->parent = feed;
+ (*filter)->priv = NULL;
+ dvbdmxfilter->feed = dvbdmxfeed;
+ dvbdmxfilter->type = DMX_TYPE_SEC;
+ dvbdmxfilter->state = DMX_STATE_READY;
+ dvbdmxfilter->next = dvbdmxfeed->filter;
+ dvbdmxfeed->filter = dvbdmxfilter;
spin_unlock_irq(&dvbdemux->lock);
+
up(&dvbdemux->mutex);
return 0;
}
-static int dmx_section_feed_set(struct dmx_section_feed* feed,
- u16 pid, size_t circular_buffer_size,
- int descramble, int check_crc)
+static int dmx_section_feed_set(struct dmx_section_feed* feed,
+ u16 pid, size_t circular_buffer_size,
+ int descramble, int check_crc)
{
- struct dvb_demux_feed *dvbdmxfeed=(struct dvb_demux_feed *) feed;
- struct dvb_demux *dvbdmx=dvbdmxfeed->demux;
+ struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *) feed;
+ struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
- if (pid>0x1fff)
+ if (pid > 0x1fff)
return -EINVAL;
if (down_interruptible (&dvbdmx->mutex))
return -ERESTARTSYS;
-
+
dvb_demux_feed_add(dvbdmxfeed);
dvbdmxfeed->pid = pid;
- dvbdmxfeed->buffer_size=circular_buffer_size;
- dvbdmxfeed->descramble=descramble;
+ dvbdmxfeed->buffer_size = circular_buffer_size;
+ dvbdmxfeed->descramble = descramble;
if (dvbdmxfeed->descramble) {
up(&dvbdmx->mutex);
return -ENOSYS;
}
- dvbdmxfeed->feed.sec.check_crc=check_crc;
+ dvbdmxfeed->feed.sec.check_crc = check_crc;
+
#ifdef NOBUFS
- dvbdmxfeed->buffer=NULL;
+ dvbdmxfeed->buffer = NULL;
#else
dvbdmxfeed->buffer=vmalloc(dvbdmxfeed->buffer_size);
if (!dvbdmxfeed->buffer) {
@@ -900,47 +879,50 @@ static int dmx_section_feed_set(struct dmx_section_feed* feed,
return -ENOMEM;
}
#endif
- dvbdmxfeed->state=DMX_STATE_READY;
+
+ dvbdmxfeed->state = DMX_STATE_READY;
up(&dvbdmx->mutex);
return 0;
}
+
static void prepare_secfilters(struct dvb_demux_feed *dvbdmxfeed)
{
int i;
struct dvb_demux_filter *f;
struct dmx_section_filter *sf;
u8 mask, mode, doneq;
-
+
if (!(f=dvbdmxfeed->filter))
return;
do {
- sf=&f->filter;
- doneq=0;
+ sf = &f->filter;
+ doneq = 0;
for (i=0; i<DVB_DEMUX_MASK_MAX; i++) {
- mode=sf->filter_mode[i];
- mask=sf->filter_mask[i];
- f->maskandmode[i]=mask&mode;
- doneq|=f->maskandnotmode[i]=mask&~mode;
+ mode = sf->filter_mode[i];
+ mask = sf->filter_mask[i];
+ f->maskandmode[i] = mask & mode;
+ doneq |= f->maskandnotmode[i] = mask & ~mode;
}
- f->doneq=doneq ? 1 : 0;
- } while ((f=f->next));
+ f->doneq = doneq ? 1 : 0;
+ } while ((f = f->next));
}
static int dmx_section_feed_start_filtering(struct dmx_section_feed *feed)
{
- struct dvb_demux_feed *dvbdmxfeed=(struct dvb_demux_feed *) feed;
- struct dvb_demux *dvbdmx=dvbdmxfeed->demux;
+ struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *) feed;
+ struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
int ret;
if (down_interruptible (&dvbdmx->mutex))
return -ERESTARTSYS;
-
+
if (feed->is_filtering) {
up(&dvbdmx->mutex);
return -EBUSY;
}
+
if (!dvbdmxfeed->filter) {
up(&dvbdmx->mutex);
return -EINVAL;
@@ -948,9 +930,9 @@ static int dmx_section_feed_start_filtering(struct dmx_section_feed *feed)
dvbdmxfeed->feed.sec.tsfeedp = 0;
dvbdmxfeed->feed.sec.secbuf = dvbdmxfeed->feed.sec.secbuf_base;
- dvbdmxfeed->feed.sec.secbufp=0;
- dvbdmxfeed->feed.sec.seclen=0;
-
+ dvbdmxfeed->feed.sec.secbufp = 0;
+ dvbdmxfeed->feed.sec.seclen = 0;
+
if (!dvbdmx->start_feed) {
up(&dvbdmx->mutex);
return -ENODEV;
@@ -964,9 +946,10 @@ static int dmx_section_feed_start_filtering(struct dmx_section_feed *feed)
}
spin_lock_irq(&dvbdmx->lock);
- feed->is_filtering=1;
- dvbdmxfeed->state=DMX_STATE_GO;
+ feed->is_filtering = 1;
+ dvbdmxfeed->state = DMX_STATE_GO;
spin_unlock_irq(&dvbdmx->lock);
+
up(&dvbdmx->mutex);
return 0;
}
@@ -974,8 +957,8 @@ static int dmx_section_feed_start_filtering(struct dmx_section_feed *feed)
static int dmx_section_feed_stop_filtering(struct dmx_section_feed* feed)
{
- struct dvb_demux_feed *dvbdmxfeed=(struct dvb_demux_feed *) feed;
- struct dvb_demux *dvbdmx=dvbdmxfeed->demux;
+ struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *) feed;
+ struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
int ret;
if (down_interruptible (&dvbdmx->mutex))
@@ -985,93 +968,99 @@ static int dmx_section_feed_stop_filtering(struct dmx_section_feed* feed)
up(&dvbdmx->mutex);
return -ENODEV;
}
- ret=dvbdmx->stop_feed(dvbdmxfeed);
+
+ ret = dvbdmx->stop_feed(dvbdmxfeed);
+
spin_lock_irq(&dvbdmx->lock);
- dvbdmxfeed->state=DMX_STATE_READY;
- feed->is_filtering=0;
+ dvbdmxfeed->state = DMX_STATE_READY;
+ feed->is_filtering = 0;
spin_unlock_irq(&dvbdmx->lock);
+
up(&dvbdmx->mutex);
return ret;
}
-static int dmx_section_feed_release_filter(struct dmx_section_feed *feed,
+static int dmx_section_feed_release_filter(struct dmx_section_feed *feed,
struct dmx_section_filter* filter)
{
- struct dvb_demux_filter *dvbdmxfilter=(struct dvb_demux_filter *) filter, *f;
- struct dvb_demux_feed *dvbdmxfeed=(struct dvb_demux_feed *) feed;
- struct dvb_demux *dvbdmx=dvbdmxfeed->demux;
+ struct dvb_demux_filter *dvbdmxfilter = (struct dvb_demux_filter *) filter, *f;
+ struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *) feed;
+ struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
if (down_interruptible (&dvbdmx->mutex))
return -ERESTARTSYS;
- if (dvbdmxfilter->feed!=dvbdmxfeed) {
+ if (dvbdmxfilter->feed != dvbdmxfeed) {
up(&dvbdmx->mutex);
return -EINVAL;
}
- if (feed->is_filtering)
+
+ if (feed->is_filtering)
feed->stop_filtering(feed);
-
+
spin_lock_irq(&dvbdmx->lock);
- f=dvbdmxfeed->filter;
+ f = dvbdmxfeed->filter;
if (f == dvbdmxfilter) {
- dvbdmxfeed->filter=dvbdmxfilter->next;
+ dvbdmxfeed->filter = dvbdmxfilter->next;
} else {
- while(f->next!=dvbdmxfilter)
- f=f->next;
- f->next=f->next->next;
+ while(f->next != dvbdmxfilter)
+ f = f->next;
+ f->next = f->next->next;
}
- dvbdmxfilter->state=DMX_STATE_FREE;
+
+ dvbdmxfilter->state = DMX_STATE_FREE;
spin_unlock_irq(&dvbdmx->lock);
up(&dvbdmx->mutex);
return 0;
}
-static int dvbdmx_allocate_section_feed(struct dmx_demux *demux,
+static int dvbdmx_allocate_section_feed(struct dmx_demux *demux,
struct dmx_section_feed **feed,
dmx_section_cb callback)
{
- struct dvb_demux *dvbdmx=(struct dvb_demux *) demux;
+ struct dvb_demux *dvbdmx = (struct dvb_demux *) demux;
struct dvb_demux_feed *dvbdmxfeed;
if (down_interruptible (&dvbdmx->mutex))
return -ERESTARTSYS;
- if (!(dvbdmxfeed=dvb_dmx_feed_alloc(dvbdmx))) {
+ if (!(dvbdmxfeed = dvb_dmx_feed_alloc(dvbdmx))) {
up(&dvbdmx->mutex);
return -EBUSY;
}
- dvbdmxfeed->type=DMX_TYPE_SEC;
- dvbdmxfeed->cb.sec=callback;
- dvbdmxfeed->demux=dvbdmx;
- dvbdmxfeed->pid=0xffff;
+
+ dvbdmxfeed->type = DMX_TYPE_SEC;
+ dvbdmxfeed->cb.sec = callback;
+ dvbdmxfeed->demux = dvbdmx;
+ dvbdmxfeed->pid = 0xffff;
dvbdmxfeed->feed.sec.secbuf = dvbdmxfeed->feed.sec.secbuf_base;
dvbdmxfeed->feed.sec.secbufp = dvbdmxfeed->feed.sec.seclen = 0;
dvbdmxfeed->feed.sec.tsfeedp = 0;
- dvbdmxfeed->filter=NULL;
- dvbdmxfeed->buffer=NULL;
+ dvbdmxfeed->filter = NULL;
+ dvbdmxfeed->buffer = NULL;
(*feed)=&dvbdmxfeed->feed.sec;
- (*feed)->is_filtering=0;
- (*feed)->parent=demux;
- (*feed)->priv=NULL;
-
- (*feed)->set=dmx_section_feed_set;
- (*feed)->allocate_filter=dmx_section_feed_allocate_filter;
- (*feed)->start_filtering=dmx_section_feed_start_filtering;
- (*feed)->stop_filtering=dmx_section_feed_stop_filtering;
+ (*feed)->is_filtering = 0;
+ (*feed)->parent = demux;
+ (*feed)->priv = NULL;
+
+ (*feed)->set = dmx_section_feed_set;
+ (*feed)->allocate_filter = dmx_section_feed_allocate_filter;
+ (*feed)->start_filtering = dmx_section_feed_start_filtering;
+ (*feed)->stop_filtering = dmx_section_feed_stop_filtering;
(*feed)->release_filter = dmx_section_feed_release_filter;
up(&dvbdmx->mutex);
return 0;
}
-static int dvbdmx_release_section_feed(struct dmx_demux *demux,
+static int dvbdmx_release_section_feed(struct dmx_demux *demux,
struct dmx_section_feed *feed)
{
- struct dvb_demux_feed *dvbdmxfeed=(struct dvb_demux_feed *) feed;
- struct dvb_demux *dvbdmx=(struct dvb_demux *) demux;
+ struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *) feed;
+ struct dvb_demux *dvbdmx = (struct dvb_demux *) demux;
if (down_interruptible (&dvbdmx->mutex))
return -ERESTARTSYS;
@@ -1081,14 +1070,14 @@ static int dvbdmx_release_section_feed(struct dmx_demux *demux,
return -EINVAL;
}
#ifndef NOBUFS
- vfree(dvbdmxfeed->buffer);
- dvbdmxfeed->buffer=0;
+ vfree(dvbdmxfeed->buffer);
+ dvbdmxfeed->buffer=0;
#endif
dvbdmxfeed->state=DMX_STATE_FREE;
dvb_demux_feed_del(dvbdmxfeed);
- dvbdmxfeed->pid = 0xffff;
+ dvbdmxfeed->pid = 0xffff;
up(&dvbdmx->mutex);
return 0;
@@ -1101,10 +1090,11 @@ static int dvbdmx_release_section_feed(struct dmx_demux *demux,
static int dvbdmx_open(struct dmx_demux *demux)
{
- struct dvb_demux *dvbdemux=(struct dvb_demux *) demux;
+ struct dvb_demux *dvbdemux = (struct dvb_demux *) demux;
- if (dvbdemux->users>=MAX_DVB_DEMUX_USERS)
+ if (dvbdemux->users >= MAX_DVB_DEMUX_USERS)
return -EUSERS;
+
dvbdemux->users++;
return 0;
}
@@ -1112,10 +1102,11 @@ static int dvbdmx_open(struct dmx_demux *demux)
static int dvbdmx_close(struct dmx_demux *demux)
{
- struct dvb_demux *dvbdemux=(struct dvb_demux *) demux;
+ struct dvb_demux *dvbdemux = (struct dvb_demux *) demux;
- if (dvbdemux->users==0)
+ if (dvbdemux->users == 0)
return -ENODEV;
+
dvbdemux->users--;
//FIXME: release any unneeded resources if users==0
return 0;
@@ -1142,7 +1133,7 @@ static int dvbdmx_write(struct dmx_demux *demux, const char *buf, size_t count)
static int dvbdmx_add_frontend(struct dmx_demux *demux, struct dmx_frontend *frontend)
{
- struct dvb_demux *dvbdemux=(struct dvb_demux *) demux;
+ struct dvb_demux *dvbdemux = (struct dvb_demux *) demux;
struct list_head *head = &dvbdemux->frontend_list;
list_add(&(frontend->connectivity_list), head);
@@ -1153,8 +1144,8 @@ static int dvbdmx_add_frontend(struct dmx_demux *demux, struct dmx_frontend *fro
static int dvbdmx_remove_frontend(struct dmx_demux *demux, struct dmx_frontend *frontend)
{
- struct dvb_demux *dvbdemux=(struct dvb_demux *) demux;
- struct list_head *pos, *n, *head=&dvbdemux->frontend_list;
+ struct dvb_demux *dvbdemux = (struct dvb_demux *) demux;
+ struct list_head *pos, *n, *head = &dvbdemux->frontend_list;
list_for_each_safe (pos, n, head) {
if (DMX_FE_ENTRY(pos) == frontend) {
@@ -1162,13 +1153,14 @@ static int dvbdmx_remove_frontend(struct dmx_demux *demux, struct dmx_frontend *
return 0;
}
}
+
return -ENODEV;
}
static struct list_head * dvbdmx_get_frontends(struct dmx_demux *demux)
{
- struct dvb_demux *dvbdemux=(struct dvb_demux *) demux;
+ struct dvb_demux *dvbdemux = (struct dvb_demux *) demux;
if (list_empty(&dvbdemux->frontend_list))
return NULL;
@@ -1176,40 +1168,38 @@ static struct list_head * dvbdmx_get_frontends(struct dmx_demux *demux)
}
-int dvbdmx_connect_frontend(struct dmx_demux *demux, struct dmx_frontend *frontend)
+static int dvbdmx_connect_frontend(struct dmx_demux *demux, struct dmx_frontend *frontend)
{
- struct dvb_demux *dvbdemux=(struct dvb_demux *) demux;
+ struct dvb_demux *dvbdemux = (struct dvb_demux *) demux;
if (demux->frontend)
return -EINVAL;
-
+
if (down_interruptible (&dvbdemux->mutex))
return -ERESTARTSYS;
- demux->frontend=frontend;
+ demux->frontend = frontend;
up(&dvbdemux->mutex);
return 0;
}
-EXPORT_SYMBOL(dvbdmx_connect_frontend);
-int dvbdmx_disconnect_frontend(struct dmx_demux *demux)
+static int dvbdmx_disconnect_frontend(struct dmx_demux *demux)
{
- struct dvb_demux *dvbdemux=(struct dvb_demux *) demux;
+ struct dvb_demux *dvbdemux = (struct dvb_demux *) demux;
if (down_interruptible (&dvbdemux->mutex))
return -ERESTARTSYS;
- demux->frontend=NULL;
+ demux->frontend = NULL;
up(&dvbdemux->mutex);
return 0;
}
-EXPORT_SYMBOL(dvbdmx_disconnect_frontend);
static int dvbdmx_get_pes_pids(struct dmx_demux *demux, u16 *pids)
{
- struct dvb_demux *dvbdemux=(struct dvb_demux *) demux;
+ struct dvb_demux *dvbdemux = (struct dvb_demux *) demux;
memcpy(pids, dvbdemux->pids, 5*sizeof(u16));
return 0;
@@ -1221,35 +1211,38 @@ int dvb_dmx_init(struct dvb_demux *dvbdemux)
int i, err;
struct dmx_demux *dmx = &dvbdemux->dmx;
- dvbdemux->users=0;
- dvbdemux->filter=vmalloc(dvbdemux->filternum*sizeof(struct dvb_demux_filter));
+ dvbdemux->users = 0;
+ dvbdemux->filter = vmalloc(dvbdemux->filternum*sizeof(struct dvb_demux_filter));
+
if (!dvbdemux->filter)
return -ENOMEM;
- dvbdemux->feed=vmalloc(dvbdemux->feednum*sizeof(struct dvb_demux_feed));
+ dvbdemux->feed = vmalloc(dvbdemux->feednum*sizeof(struct dvb_demux_feed));
if (!dvbdemux->feed) {
vfree(dvbdemux->filter);
return -ENOMEM;
}
for (i=0; i<dvbdemux->filternum; i++) {
- dvbdemux->filter[i].state=DMX_STATE_FREE;
- dvbdemux->filter[i].index=i;
+ dvbdemux->filter[i].state = DMX_STATE_FREE;
+ dvbdemux->filter[i].index = i;
+ }
+ for (i=0; i<dvbdemux->feednum; i++) {
+ dvbdemux->feed[i].state = DMX_STATE_FREE;
+ dvbdemux->feed[i].index = i;
}
- for (i=0; i<dvbdemux->feednum; i++)
- dvbdemux->feed[i].state=DMX_STATE_FREE;
dvbdemux->frontend_list.next=
dvbdemux->frontend_list.prev=
&dvbdemux->frontend_list;
for (i=0; i<DMX_TS_PES_OTHER; i++) {
- dvbdemux->pesfilter[i]=NULL;
- dvbdemux->pids[i]=0xffff;
+ dvbdemux->pesfilter[i] = NULL;
+ dvbdemux->pids[i] = 0xffff;
}
INIT_LIST_HEAD(&dvbdemux->feed_list);
dvbdemux->playing = 0;
dvbdemux->recording = 0;
- dvbdemux->tsbufp=0;
+ dvbdemux->tsbufp = 0;
if (!dvbdemux->check_crc32)
dvbdemux->check_crc32 = dvb_dmx_crc32;
@@ -1257,30 +1250,31 @@ int dvb_dmx_init(struct dvb_demux *dvbdemux)
if (!dvbdemux->memcopy)
dvbdemux->memcopy = dvb_dmx_memcopy;
- dmx->frontend=NULL;
+ dmx->frontend = NULL;
dmx->reg_list.prev = dmx->reg_list.next = &dmx->reg_list;
- dmx->priv=(void *) dvbdemux;
- dmx->open=dvbdmx_open;
- dmx->close=dvbdmx_close;
- dmx->write=dvbdmx_write;
- dmx->allocate_ts_feed=dvbdmx_allocate_ts_feed;
- dmx->release_ts_feed=dvbdmx_release_ts_feed;
- dmx->allocate_section_feed=dvbdmx_allocate_section_feed;
- dmx->release_section_feed=dvbdmx_release_section_feed;
-
- dmx->descramble_mac_address=NULL;
- dmx->descramble_section_payload=NULL;
-
- dmx->add_frontend=dvbdmx_add_frontend;
- dmx->remove_frontend=dvbdmx_remove_frontend;
- dmx->get_frontends=dvbdmx_get_frontends;
- dmx->connect_frontend=dvbdmx_connect_frontend;
- dmx->disconnect_frontend=dvbdmx_disconnect_frontend;
- dmx->get_pes_pids=dvbdmx_get_pes_pids;
+ dmx->priv = (void *) dvbdemux;
+ dmx->open = dvbdmx_open;
+ dmx->close = dvbdmx_close;
+ dmx->write = dvbdmx_write;
+ dmx->allocate_ts_feed = dvbdmx_allocate_ts_feed;
+ dmx->release_ts_feed = dvbdmx_release_ts_feed;
+ dmx->allocate_section_feed = dvbdmx_allocate_section_feed;
+ dmx->release_section_feed = dvbdmx_release_section_feed;
+
+ dmx->descramble_mac_address = NULL;
+ dmx->descramble_section_payload = NULL;
+
+ dmx->add_frontend = dvbdmx_add_frontend;
+ dmx->remove_frontend = dvbdmx_remove_frontend;
+ dmx->get_frontends = dvbdmx_get_frontends;
+ dmx->connect_frontend = dvbdmx_connect_frontend;
+ dmx->disconnect_frontend = dvbdmx_disconnect_frontend;
+ dmx->get_pes_pids = dvbdmx_get_pes_pids;
+
sema_init(&dvbdemux->mutex, 1);
spin_lock_init(&dvbdemux->lock);
- if ((err = dmx_register_demux(dmx)) < 0)
+ if ((err = dmx_register_demux(dmx)) < 0)
return err;
return 0;
@@ -1293,9 +1287,8 @@ int dvb_dmx_release(struct dvb_demux *dvbdemux)
struct dmx_demux *dmx = &dvbdemux->dmx;
dmx_unregister_demux(dmx);
- vfree(dvbdemux->filter);
- vfree(dvbdemux->feed);
+ vfree(dvbdemux->filter);
+ vfree(dvbdemux->feed);
return 0;
}
EXPORT_SYMBOL(dvb_dmx_release);
-
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.h b/drivers/media/dvb/dvb-core/dvb_demux.h
index 02faa99d297fc..c09beb3916225 100644
--- a/drivers/media/dvb/dvb-core/dvb_demux.h
+++ b/drivers/media/dvb/dvb-core/dvb_demux.h
@@ -1,4 +1,4 @@
-/*
+/*
* dvb_demux.h: DVB kernel demux API
*
* Copyright (C) 2000-2001 Marcus Metzler & Ralph Metzler
@@ -45,10 +45,10 @@
struct dvb_demux_filter {
struct dmx_section_filter filter;
- u8 maskandmode [DMX_MAX_FILTER_SIZE];
- u8 maskandnotmode [DMX_MAX_FILTER_SIZE];
+ u8 maskandmode [DMX_MAX_FILTER_SIZE];
+ u8 maskandnotmode [DMX_MAX_FILTER_SIZE];
int doneq;
-
+
struct dvb_demux_filter *next;
struct dvb_demux_feed *feed;
int index;
@@ -85,10 +85,10 @@ struct dvb_demux_feed {
int buffer_size;
int descramble;
- struct timespec timeout;
+ struct timespec timeout;
struct dvb_demux_filter *filter;
int cb_length;
-
+
int ts_type;
enum dmx_ts_pes pes_type;
@@ -98,6 +98,7 @@ struct dvb_demux_feed {
u16 peslen;
struct list_head list_head;
+ int index; /* a unique index for each feed (can be used as hardware pid filter index) */
};
struct dvb_demux {
@@ -113,7 +114,7 @@ struct dvb_demux {
const u8 *buf, size_t len);
void (*memcopy) (struct dvb_demux_feed *feed, u8 *dst,
const u8 *src, size_t len);
-
+
int users;
#define MAX_DVB_DEMUX_USERS 10
struct dvb_demux_filter *filter;
@@ -123,8 +124,8 @@ struct dvb_demux {
struct dvb_demux_feed *pesfilter[DMX_TS_PES_OTHER];
u16 pids[DMX_TS_PES_OTHER];
- int playing;
- int recording;
+ int playing;
+ int recording;
#define DMX_MAX_PID 0x2000
struct list_head feed_list;
@@ -138,13 +139,8 @@ struct dvb_demux {
int dvb_dmx_init(struct dvb_demux *dvbdemux);
int dvb_dmx_release(struct dvb_demux *dvbdemux);
-void dvb_dmx_swfilter_packet(struct dvb_demux *dvbdmx, const u8 *buf);
void dvb_dmx_swfilter_packets(struct dvb_demux *dvbdmx, const u8 *buf, size_t count);
void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count);
void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count);
-int dvbdmx_connect_frontend(struct dmx_demux *demux, struct dmx_frontend *frontend);
-int dvbdmx_disconnect_frontend(struct dmx_demux *demux);
-
#endif /* _DVB_DEMUX_H_ */
-
diff --git a/drivers/media/dvb/dvb-core/dvb_filter.c b/drivers/media/dvb/dvb-core/dvb_filter.c
index 5ce4f6569d0be..bd5143906084d 100644
--- a/drivers/media/dvb/dvb-core/dvb_filter.c
+++ b/drivers/media/dvb/dvb-core/dvb_filter.c
@@ -22,12 +22,12 @@ static u32 ac3_frames[3][32] =
{69,87,104,121,139,174,208,243,278,348,417,487,557,696,835,975,1114,
1253,1393,0,0,0,0,0,0,0,0,0,0,0,0,0},
{96,120,144,168,192,240,288,336,384,480,576,672,768,960,1152,1344,
- 1536,1728,1920,0,0,0,0,0,0,0,0,0,0,0,0,0}};
+ 1536,1728,1920,0,0,0,0,0,0,0,0,0,0,0,0,0}};
#if 0
-static void setup_ts2pes(ipack *pa, ipack *pv, u16 *pida, u16 *pidv,
+static void setup_ts2pes(ipack *pa, ipack *pv, u16 *pida, u16 *pidv,
void (*pes_write)(u8 *buf, int count, void *data),
void *priv)
{
@@ -72,7 +72,7 @@ static int read_picture_header(u8 *headr, struct mpg_picture *pic, int field, in
u8 pct;
if (pr) printk( "Pic header: ");
- pic->temporal_reference[field] = (( headr[0] << 2 ) |
+ pic->temporal_reference[field] = (( headr[0] << 2 ) |
(headr[1] & 0x03) )& 0x03ff;
if (pr) printk( " temp ref: 0x%04x", pic->temporal_reference[field]);
@@ -93,31 +93,31 @@ static int read_picture_header(u8 *headr, struct mpg_picture *pic, int field, in
}
- pic->vinfo.vbv_delay = (( headr[1] >> 5 ) | ( headr[2] << 3) |
+ pic->vinfo.vbv_delay = (( headr[1] >> 5 ) | ( headr[2] << 3) |
( (headr[3] & 0x1F) << 11) ) & 0xffff;
if (pr) printk( " vbv delay: 0x%04x", pic->vinfo.vbv_delay);
- pic->picture_header_parameter = ( headr[3] & 0xe0 ) |
+ pic->picture_header_parameter = ( headr[3] & 0xe0 ) |
((headr[4] & 0x80) >> 3);
if ( pct == B_FRAME ){
pic->picture_header_parameter |= ( headr[4] >> 3 ) & 0x0f;
}
- if (pr) printk( " pic head param: 0x%x",
+ if (pr) printk( " pic head param: 0x%x",
pic->picture_header_parameter);
return pct;
-}
+}
#endif
#if 0
/* needs 4 byte input */
static int read_gop_header(u8 *headr, struct mpg_picture *pic, int pr)
{
- if (pr) printk("GOP header: ");
+ if (pr) printk("GOP header: ");
- pic->time_code = (( headr[0] << 17 ) | ( headr[1] << 9) |
+ pic->time_code = (( headr[0] << 17 ) | ( headr[1] << 9) |
( headr[2] << 1 ) | (headr[3] &0x01)) & 0x1ffffff;
if (pr) printk(" time: %d:%d.%d ", (headr[0]>>2)& 0x1F,
@@ -129,14 +129,14 @@ static int read_gop_header(u8 *headr, struct mpg_picture *pic, int pr)
} else {
pic->closed_gop = 0;
}
- if (pr) printk("closed: %d", pic->closed_gop);
+ if (pr) printk("closed: %d", pic->closed_gop);
if ( ( headr[3] & 0x20 ) != 0 ){
pic->broken_link = 1;
} else {
pic->broken_link = 0;
}
- if (pr) printk(" broken: %d\n", pic->broken_link);
+ if (pr) printk(" broken: %d\n", pic->broken_link);
return 0;
}
@@ -153,39 +153,39 @@ static int read_sequence_header(u8 *headr, struct dvb_video_info *vi, int pr)
vi->horizontal_size = ((headr[1] &0xF0) >> 4) | (headr[0] << 4);
vi->vertical_size = ((headr[1] &0x0F) << 8) | (headr[2]);
-
+
sw = (int)((headr[3]&0xF0) >> 4) ;
switch( sw ){
case 1:
if (pr)
printk("Videostream: ASPECT: 1:1");
- vi->aspect_ratio = 100;
+ vi->aspect_ratio = 100;
break;
case 2:
if (pr)
printk("Videostream: ASPECT: 4:3");
- vi->aspect_ratio = 133;
+ vi->aspect_ratio = 133;
break;
case 3:
if (pr)
printk("Videostream: ASPECT: 16:9");
- vi->aspect_ratio = 177;
+ vi->aspect_ratio = 177;
break;
case 4:
if (pr)
printk("Videostream: ASPECT: 2.21:1");
- vi->aspect_ratio = 221;
+ vi->aspect_ratio = 221;
break;
case 5 ... 15:
if (pr)
printk("Videostream: ASPECT: reserved");
- vi->aspect_ratio = 0;
+ vi->aspect_ratio = 0;
break;
default:
- vi->aspect_ratio = 0;
+ vi->aspect_ratio = 0;
return -1;
}
@@ -240,7 +240,7 @@ static int read_sequence_header(u8 *headr, struct dvb_video_info *vi, int pr)
}
vi->bit_rate = (headr[4] << 10) | (headr[5] << 2) | (headr[6] & 0x03);
-
+
vi->vbv_buffer_size
= (( headr[6] & 0xF8) >> 3 ) | (( headr[7] & 0x1F )<< 5);
@@ -303,7 +303,7 @@ static int get_ainfo(u8 *mbuf, int count, struct dvb_audio_info *ai, int pr)
else {
c++;
}
- }
+ }
if (!found) return -1;
@@ -333,8 +333,8 @@ static int get_ainfo(u8 *mbuf, int count, struct dvb_audio_info *ai, int pr)
if (ai->frequency == 3)
printk(" Freq: reserved\n");
else
- printk(" Freq: %d kHz\n",ai->frequency);
-
+ printk(" Freq: %d kHz\n",ai->frequency);
+
}
ai->off = c;
return 0;
@@ -349,7 +349,7 @@ int dvb_filter_get_ac3info(u8 *mbuf, int count, struct dvb_audio_info *ai, int p
int c = 0;
u8 frame = 0;
int fr = 0;
-
+
while ( !found && c < count){
u8 *b = mbuf+c;
@@ -358,7 +358,7 @@ int dvb_filter_get_ac3info(u8 *mbuf, int count, struct dvb_audio_info *ai, int p
else {
c++;
}
- }
+ }
if (!found) return -1;
if (pr)
@@ -402,7 +402,7 @@ static u8 *skip_pes_header(u8 **bufp)
int skip = 0;
static const int mpeg1_skip_table[16] = {
- 1, 0xffff, 5, 10, 0xffff, 0xffff, 0xffff, 0xffff,
+ 1, 0xffff, 5, 10, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff
};
@@ -479,9 +479,9 @@ static void initialize_mpg_picture(struct mpg_picture *pic)
pic->picture_display_extension_flag[0] = 0;
pic->picture_display_extension_flag[1] = 0;
- pic->sequence_header_flag = 0;
- pic->gop_flag = 0;
- pic->sequence_end_flag = 0;
+ pic->sequence_header_flag = 0;
+ pic->gop_flag = 0;
+ pic->sequence_end_flag = 0;
}
#endif
@@ -553,7 +553,7 @@ static void init_mpg_picture( struct mpg_picture *pic, int chan, int32_t field_t
}
#endif
-void dvb_filter_pes2ts_init(struct dvb_filter_pes2ts *p2ts, unsigned short pid,
+void dvb_filter_pes2ts_init(struct dvb_filter_pes2ts *p2ts, unsigned short pid,
dvb_filter_pes2ts_cb_t *cb, void *priv)
{
unsigned char *buf=p2ts->buf;
@@ -572,11 +572,11 @@ int dvb_filter_pes2ts(struct dvb_filter_pes2ts *p2ts, unsigned char *pes,
{
unsigned char *buf=p2ts->buf;
int ret=0, rest;
-
+
//len=6+((pes[4]<<8)|pes[5]);
if (payload_start)
- buf[1]|=0x40;
+ buf[1]|=0x40;
else
buf[1]&=~0x40;
while (len>=184) {
@@ -601,4 +601,3 @@ int dvb_filter_pes2ts(struct dvb_filter_pes2ts *p2ts, unsigned char *pes,
return p2ts->cb(p2ts->priv, buf);
}
EXPORT_SYMBOL(dvb_filter_pes2ts);
-
diff --git a/drivers/media/dvb/dvb-core/dvb_filter.h b/drivers/media/dvb/dvb-core/dvb_filter.h
index e55f80ca85af7..b0848f7836b74 100644
--- a/drivers/media/dvb/dvb-core/dvb_filter.h
+++ b/drivers/media/dvb/dvb-core/dvb_filter.h
@@ -34,8 +34,8 @@ struct dvb_filter_pes2ts {
void *priv;
};
-void dvb_filter_pes2ts_init(struct dvb_filter_pes2ts *p2ts, unsigned short pid,
- dvb_filter_pes2ts_cb_t *cb, void *priv);
+void dvb_filter_pes2ts_init(struct dvb_filter_pes2ts *p2ts, unsigned short pid,
+ dvb_filter_pes2ts_cb_t *cb, void *priv);
int dvb_filter_pes2ts(struct dvb_filter_pes2ts *p2ts, unsigned char *pes,
int len, int payload_start);
@@ -70,8 +70,8 @@ int dvb_filter_pes2ts(struct dvb_filter_pes2ts *p2ts, unsigned char *pes,
#define QUANT_MATRIX_EXTENSION 0x03
#define PICTURE_DISPLAY_EXTENSION 0x07
-#define I_FRAME 0x01
-#define B_FRAME 0x02
+#define I_FRAME 0x01
+#define B_FRAME 0x02
#define P_FRAME 0x03
/* Initialize sequence_data */
@@ -92,7 +92,7 @@ int dvb_filter_pes2ts(struct dvb_filter_pes2ts *p2ts, unsigned char *pes,
#define PES_CRC_FLAG 0x02
#define PES_EXT_FLAG 0x01
-//pts_dts flags
+//pts_dts flags
#define PTS_ONLY 0x80
#define PTS_DTS 0xC0
@@ -165,7 +165,7 @@ struct dvb_video_info {
s16 vbv_delay;
u32 CSPF;
u32 off;
-};
+};
#define OFF_SIZE 4
#define FIRST_FIELD 0
@@ -181,10 +181,10 @@ struct mpg_picture {
int low_delay;
int closed_gop;
int broken_link;
- int sequence_header_flag;
- int gop_flag;
+ int sequence_header_flag;
+ int gop_flag;
int sequence_end_flag;
-
+
u8 profile_and_level;
s32 picture_coding_parameter;
u32 matrix[32];
@@ -211,26 +211,26 @@ struct mpg_picture {
int forward_bank;
int backward_bank;
int compress;
- s16 frame_centre_horizontal_offset[OFF_SIZE];
+ s16 frame_centre_horizontal_offset[OFF_SIZE];
/* [0-2] 1st field, [3] 2nd field */
s16 frame_centre_vertical_offset[OFF_SIZE];
/* [0-2] 1st field, [3] 2nd field */
- s16 temporal_reference[2];
+ s16 temporal_reference[2];
/* [0] 1st field, [1] 2nd field */
s8 picture_coding_type[2];
- /* [0] 1st field, [1] 2nd field */
+ /* [0] 1st field, [1] 2nd field */
s8 picture_structure[2];
- /* [0] 1st field, [1] 2nd field */
+ /* [0] 1st field, [1] 2nd field */
s8 picture_display_extension_flag[2];
- /* [0] 1st field, [1] 2nd field */
- /* picture_display_extenion() 0:no 1:exit*/
+ /* [0] 1st field, [1] 2nd field */
+ /* picture_display_extenion() 0:no 1:exit*/
s8 pts_flag[2];
- /* [0] 1st field, [1] 2nd field */
+ /* [0] 1st field, [1] 2nd field */
};
struct dvb_audio_info {
- int layer ;
+ int layer;
u32 bit_rate;
u32 frequency;
u32 mode;
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c
index 2f1cf834817a2..59a9adfae1ebc 100644
--- a/drivers/media/dvb/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.c
@@ -3,9 +3,9 @@
*
*
* Copyright (C) 1999-2001 Ralph Metzler
- * Marcus Metzler
- * Holger Waechtler
- * for convergence integrated media GmbH
+ * Marcus Metzler
+ * Holger Waechtler
+ * for convergence integrated media GmbH
*
* Copyright (C) 2004 Andrew de Quincey (tuning thread cleanup)
*
@@ -16,7 +16,7 @@
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
@@ -161,39 +161,39 @@ static int dvb_frontend_get_event(struct dvb_frontend *fe,
dprintk ("%s\n", __FUNCTION__);
if (events->overflow) {
- events->overflow = 0;
- return -EOVERFLOW;
- }
+ events->overflow = 0;
+ return -EOVERFLOW;
+ }
- if (events->eventw == events->eventr) {
+ if (events->eventw == events->eventr) {
int ret;
- if (flags & O_NONBLOCK)
- return -EWOULDBLOCK;
+ if (flags & O_NONBLOCK)
+ return -EWOULDBLOCK;
up(&fepriv->sem);
- ret = wait_event_interruptible (events->wait_queue,
- events->eventw != events->eventr);
+ ret = wait_event_interruptible (events->wait_queue,
+ events->eventw != events->eventr);
if (down_interruptible (&fepriv->sem))
return -ERESTARTSYS;
- if (ret < 0)
- return ret;
- }
+ if (ret < 0)
+ return ret;
+ }
- if (down_interruptible (&events->sem))
+ if (down_interruptible (&events->sem))
return -ERESTARTSYS;
- memcpy (event, &events->events[events->eventr],
+ memcpy (event, &events->events[events->eventr],
sizeof(struct dvb_frontend_event));
- events->eventr = (events->eventr + 1) % MAX_EVENT;
+ events->eventr = (events->eventr + 1) % MAX_EVENT;
- up (&events->sem);
+ up (&events->sem);
- return 0;
+ return 0;
}
static void dvb_frontend_init(struct dvb_frontend *fe)
@@ -206,26 +206,26 @@ 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 update_delay(int *quality, int *delay, int min_delay, 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)
+ (*quality) = (*quality * 220 + 36*256) / 256;
+ else
+ (*quality) = (*quality * 220 + 0) / 256;
- q2 = *quality - 128;
- q2 *= q2;
+ q2 = *quality - 128;
+ q2 *= q2;
*delay = min_delay + q2 * HZ / (128*128);
}
/**
* Performs automatic twiddling of frontend parameters.
- *
+ *
* @param fe The frontend concerned.
* @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.
@@ -270,26 +270,26 @@ static int dvb_frontend_autotune(struct dvb_frontend *fe, int check_wrapped)
case 2:
if (fepriv->lnb_drift == 0) break;
-
+
fepriv->lnb_drift = -fepriv->lnb_drift;
ready = 1;
break;
-
+
case 3:
if (fepriv->lnb_drift == 0) break;
if (!autoinversion) break;
-
+
fepriv->inversion = (fepriv->inversion == INVERSION_OFF) ? INVERSION_ON : INVERSION_OFF;
fepriv->lnb_drift = -fepriv->lnb_drift;
ready = 1;
break;
-
+
default:
fepriv->auto_step++;
fepriv->auto_sub_step = -1; /* it'll be incremented to 0 in a moment */
break;
}
-
+
if (!ready) fepriv->auto_sub_step++;
}
@@ -298,13 +298,13 @@ static int dvb_frontend_autotune(struct dvb_frontend *fe, int check_wrapped)
if ((fepriv->auto_step == fepriv->started_auto_step) &&
(fepriv->auto_sub_step == 0) && check_wrapped) {
return 1;
- }
+ }
dprintk("%s: drift:%i inversion:%i auto_step:%i "
"auto_sub_step:%i started_auto_step:%i\n",
__FUNCTION__, fepriv->lnb_drift, fepriv->inversion,
fepriv->auto_step, fepriv->auto_sub_step, fepriv->started_auto_step);
-
+
/* set the frontend itself */
fepriv->parameters.frequency += fepriv->lnb_drift;
if (autoinversion)
@@ -355,7 +355,7 @@ static void dvb_frontend_wakeup(struct dvb_frontend *fe)
/*
* FIXME: use linux/kthread.h
*/
-static int dvb_frontend_thread (void *data)
+static int dvb_frontend_thread(void *data)
{
struct dvb_frontend *fe = (struct dvb_frontend *) data;
struct dvb_frontend_private *fepriv = (struct dvb_frontend_private*) fe->frontend_priv;
@@ -365,17 +365,17 @@ static int dvb_frontend_thread (void *data)
fe_status_t s;
int check_wrapped = 0;
- dprintk ("%s\n", __FUNCTION__);
+ dprintk("%s\n", __FUNCTION__);
snprintf (name, sizeof(name), "kdvb-fe-%i", fe->dvb->num);
- lock_kernel ();
- daemonize (name);
- sigfillset (&current->blocked);
- unlock_kernel ();
+ lock_kernel();
+ daemonize(name);
+ sigfillset(&current->blocked);
+ unlock_kernel();
fepriv->status = 0;
- dvb_frontend_init (fe);
+ dvb_frontend_init(fe);
fepriv->wakeup = 0;
while (1) {
@@ -384,7 +384,7 @@ static int dvb_frontend_thread (void *data)
timeout = wait_event_interruptible_timeout(fepriv->wait_queue,
dvb_frontend_should_wakeup(fe),
delay);
- if (0 != dvb_frontend_is_exiting (fe)) {
+ if (0 != dvb_frontend_is_exiting(fe)) {
/* got signal or quitting */
break;
}
@@ -409,7 +409,7 @@ static int dvb_frontend_thread (void *data)
if (fe->ops->read_status)
fe->ops->read_status(fe, &s);
if (s != fepriv->status) {
- dvb_frontend_add_event (fe, s);
+ dvb_frontend_add_event(fe, s);
fepriv->status = s;
}
}
@@ -447,16 +447,16 @@ static int dvb_frontend_thread (void *data)
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;
- }
-
+ 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
@@ -495,7 +495,7 @@ static int dvb_frontend_thread (void *data)
/* 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);
@@ -567,7 +567,7 @@ static int dvb_frontend_start(struct dvb_frontend *fe)
if (!fepriv->exit)
return 0;
else
- dvb_frontend_stop (fe);
+ dvb_frontend_stop (fe);
}
if (signal_pending(current))
@@ -592,8 +592,7 @@ static int dvb_frontend_start(struct dvb_frontend *fe)
return 0;
}
-
-static int dvb_frontend_ioctl (struct inode *inode, struct file *file,
+static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, void *parg)
{
struct dvb_device *dvbdev = file->private_data;
@@ -712,14 +711,14 @@ static int dvb_frontend_ioctl (struct inode *inode, struct file *file,
case FE_SET_FRONTEND: {
struct dvb_frontend_tune_settings fetunesettings;
-
+
memcpy (&fepriv->parameters, parg,
sizeof (struct dvb_frontend_parameters));
memset(&fetunesettings, 0, sizeof(struct dvb_frontend_tune_settings));
memcpy(&fetunesettings.parameters, parg,
sizeof (struct dvb_frontend_parameters));
-
+
/* force auto frequency inversion if requested */
if (dvb_force_auto_inversion) {
fepriv->parameters.inversion = INVERSION_AUTO;
@@ -745,14 +744,14 @@ static int dvb_frontend_ioctl (struct inode *inode, struct file *file,
fepriv->min_delay = HZ/20;
fepriv->step_size = fepriv->parameters.u.qpsk.symbol_rate / 16000;
fepriv->max_drift = fepriv->parameters.u.qpsk.symbol_rate / 2000;
- break;
-
+ break;
+
case FE_QAM:
fepriv->min_delay = HZ/20;
fepriv->step_size = 0; /* no zigzag */
fepriv->max_drift = 0;
break;
-
+
case FE_OFDM:
fepriv->min_delay = HZ/20;
fepriv->step_size = fe->ops->info.frequency_stepsize * 2;
@@ -768,7 +767,7 @@ static int dvb_frontend_ioctl (struct inode *inode, struct file *file,
fepriv->state = FESTATE_RETUNE;
dvb_frontend_wakeup(fe);
- dvb_frontend_add_event (fe, 0);
+ dvb_frontend_add_event(fe, 0);
fepriv->status = 0;
err = 0;
break;
@@ -790,8 +789,7 @@ static int dvb_frontend_ioctl (struct inode *inode, struct file *file,
return err;
}
-
-static unsigned int dvb_frontend_poll (struct file *file, struct poll_table_struct *wait)
+static unsigned int dvb_frontend_poll(struct file *file, struct poll_table_struct *wait)
{
struct dvb_device *dvbdev = file->private_data;
struct dvb_frontend *fe = dvbdev->priv;
@@ -807,8 +805,7 @@ static unsigned int dvb_frontend_poll (struct file *file, struct poll_table_stru
return 0;
}
-
-static int dvb_frontend_open (struct inode *inode, struct file *file)
+static int dvb_frontend_open(struct inode *inode, struct file *file)
{
struct dvb_device *dvbdev = file->private_data;
struct dvb_frontend *fe = dvbdev->priv;
@@ -828,12 +825,11 @@ static int dvb_frontend_open (struct inode *inode, struct file *file)
/* empty event queue */
fepriv->events.eventr = fepriv->events.eventw = 0;
}
-
+
return ret;
}
-
-static int dvb_frontend_release (struct inode *inode, struct file *file)
+static int dvb_frontend_release(struct inode *inode, struct file *file)
{
struct dvb_device *dvbdev = file->private_data;
struct dvb_frontend *fe = dvbdev->priv;
@@ -847,7 +843,6 @@ static int dvb_frontend_release (struct inode *inode, struct file *file)
return dvb_generic_release (inode, file);
}
-
static struct file_operations dvb_frontend_fops = {
.owner = THIS_MODULE,
.ioctl = dvb_generic_ioctl,
@@ -907,14 +902,13 @@ int dvb_unregister_frontend(struct dvb_frontend* fe)
down (&frontend_mutex);
dvb_unregister_device (fepriv->dvbdev);
- dvb_frontend_stop (fe);
+ dvb_frontend_stop (fe);
if (fe->ops->release)
fe->ops->release(fe);
else
printk("dvb_frontend: Demodulator (%s) does not have a release callback!\n", fe->ops->info.name);
/* fe is invalid now */
- if (fepriv)
- kfree(fepriv);
+ kfree(fepriv);
up (&frontend_mutex);
return 0;
}
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.h b/drivers/media/dvb/dvb-core/dvb_frontend.h
index e2ec9ba3aaf82..d2b021792791e 100644
--- a/drivers/media/dvb/dvb-core/dvb_frontend.h
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.h
@@ -1,4 +1,4 @@
-/*
+/*
* dvb_frontend.h
*
* Copyright (C) 2001 convergence integrated media GmbH
diff --git a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c
index c8d9098059673..44892e7abd3d1 100644
--- a/drivers/media/dvb/dvb-core/dvb_net.c
+++ b/drivers/media/dvb/dvb-core/dvb_net.c
@@ -1,4 +1,4 @@
-/*
+/*
* dvb_net.c
*
* Copyright (C) 2001 Convergence integrated media GmbH
@@ -9,8 +9,8 @@
* Copyright (C) 2003, 2004 gcs - Global Communication & Services GmbH.
* and Department of Scientific Computing
* Paris Lodron University of Salzburg.
- * Hilmar Linder <hlinder@cosy.sbg.ac.at>
- * and Wolfram Stering <wstering@cosy.sbg.ac.at>
+ * Hilmar Linder <hlinder@cosy.sbg.ac.at>
+ * and Wolfram Stering <wstering@cosy.sbg.ac.at>
*
* ULE Decaps according to draft-ietf-ipdvb-ule-03.txt.
*
@@ -18,12 +18,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the 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.
@@ -122,10 +122,10 @@ static void hexdump( const unsigned char *buf, unsigned short len )
struct dvb_net_priv {
int in_use;
- struct net_device_stats stats;
+ struct net_device_stats stats;
u16 pid;
struct dvb_net *host;
- struct dmx_demux *demux;
+ struct dmx_demux *demux;
struct dmx_section_feed *secfeed;
struct dmx_section_filter *secfilter;
struct dmx_ts_feed *tsfeed;
@@ -156,7 +156,7 @@ struct dvb_net_priv {
/**
- * Determine the packet's protocol ID. The rule here is that we
+ * Determine the packet's protocol ID. The rule here is that we
* assume 802.3 if the type field is short enough to be a length.
* This is normal practice and works for any 'now in use' protocol.
*
@@ -168,7 +168,7 @@ static unsigned short dvb_net_eth_type_trans(struct sk_buff *skb,
{
struct ethhdr *eth;
unsigned char *rawp;
-
+
skb->mac.raw=skb->data;
skb_pull(skb,dev->hard_header_len);
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,8)
@@ -176,19 +176,19 @@ static unsigned short dvb_net_eth_type_trans(struct sk_buff *skb,
#else
eth = eth_hdr(skb);
#endif
-
+
if (*eth->h_dest & 1) {
if(memcmp(eth->h_dest,dev->broadcast, ETH_ALEN)==0)
skb->pkt_type=PACKET_BROADCAST;
else
skb->pkt_type=PACKET_MULTICAST;
}
-
+
if (ntohs(eth->h_proto) >= 1536)
return eth->h_proto;
-
+
rawp = skb->data;
-
+
/**
* This is a magic hack to spot IPX packets. Older Novell breaks
* the protocol design and runs IPX over 802.3 without an 802.2 LLC
@@ -197,7 +197,7 @@ static unsigned short dvb_net_eth_type_trans(struct sk_buff *skb,
*/
if (*(unsigned short *)rawp == 0xFFFF)
return htons(ETH_P_802_3);
-
+
/**
* Real 802.2 LLC
*/
@@ -217,12 +217,12 @@ static unsigned short dvb_net_eth_type_trans(struct sk_buff *skb,
#define ULE_TEST 0
#define ULE_BRIDGED 1
-int ule_test_sndu( struct dvb_net_priv *p )
+static int ule_test_sndu( struct dvb_net_priv *p )
{
return -1;
}
-int ule_bridged_sndu( struct dvb_net_priv *p )
+static int ule_bridged_sndu( struct dvb_net_priv *p )
{
/* BRIDGE SNDU handling sucks in draft-ietf-ipdvb-ule-03.txt.
* This has to be the last extension header, otherwise it won't work.
@@ -236,7 +236,7 @@ int ule_bridged_sndu( struct dvb_net_priv *p )
/** Handle ULE extension headers.
* Function is called after a successful CRC32 verification of an ULE SNDU to complete its decoding.
* Returns: >= 0: nr. of bytes consumed by next extension header
- * -1: Mandatory extension header that is not recognized or TEST SNDU; discard.
+ * -1: Mandatory extension header that is not recognized or TEST SNDU; discard.
*/
static int handle_one_ule_extension( struct dvb_net_priv *p )
{
@@ -345,7 +345,7 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
if (ule_dump) {
hexdump( ule_where, TS_SZ );
ule_dump = 0;
- }
+ }
ule_where += TS_SZ;
#endif
@@ -586,9 +586,9 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
ule_crc = iov_crc32(ule_crc, iov, 3);
expected_crc = *((u8 *)priv->ule_skb->tail - 4) << 24 |
- *((u8 *)priv->ule_skb->tail - 3) << 16 |
- *((u8 *)priv->ule_skb->tail - 2) << 8 |
- *((u8 *)priv->ule_skb->tail - 1);
+ *((u8 *)priv->ule_skb->tail - 3) << 16 |
+ *((u8 *)priv->ule_skb->tail - 2) << 8 |
+ *((u8 *)priv->ule_skb->tail - 1);
if (ule_crc != expected_crc) {
printk(KERN_WARNING "%lu: CRC32 check FAILED: %#lx / %#lx, SNDU len %d type %#x, ts_remain %d, next 2: %x.\n",
priv->ts_count, ule_crc, expected_crc, priv->ule_sndu_len, priv->ule_sndu_type, ts_remain, ts_remain > 2 ? *(unsigned short *)from_where : 0);
@@ -790,12 +790,12 @@ static void dvb_net_sec(struct net_device *dev, u8 *pkt, int pkt_len)
eth[13] = 0x00;
skb->protocol = dvb_net_eth_type_trans(skb, dev);
-
+
stats->rx_packets++;
stats->rx_bytes+=skb->len;
netif_rx(skb);
}
-
+
static int dvb_net_sec_callback(const u8 *buffer1, size_t buffer1_len,
const u8 *buffer2, size_t buffer2_len,
struct dmx_section_filter *filter,
@@ -873,7 +873,7 @@ static int dvb_net_feed_start(struct net_device *dev)
struct dvb_net_priv *priv = (struct dvb_net_priv*) dev->priv;
struct dmx_demux *demux = priv->demux;
unsigned char *mac = (unsigned char *) dev->dev_addr;
-
+
dprintk("%s: rx_mode %i\n", __FUNCTION__, priv->rx_mode);
if (priv->tsfeed || priv->secfeed || priv->secfilter || priv->multi_secfilter[0])
printk("%s: BUG %d\n", __FUNCTION__, __LINE__);
@@ -883,51 +883,51 @@ static int dvb_net_feed_start(struct net_device *dev)
priv->tsfeed = NULL;
if (priv->feedtype == DVB_NET_FEEDTYPE_MPE) {
- dprintk("%s: alloc secfeed\n", __FUNCTION__);
- ret=demux->allocate_section_feed(demux, &priv->secfeed,
+ dprintk("%s: alloc secfeed\n", __FUNCTION__);
+ ret=demux->allocate_section_feed(demux, &priv->secfeed,
dvb_net_sec_callback);
- if (ret<0) {
- printk("%s: could not allocate section feed\n", dev->name);
- return ret;
- }
+ if (ret<0) {
+ printk("%s: could not allocate section feed\n", dev->name);
+ return ret;
+ }
- ret = priv->secfeed->set(priv->secfeed, priv->pid, 32768, 0, 1);
+ ret = priv->secfeed->set(priv->secfeed, priv->pid, 32768, 0, 1);
- if (ret<0) {
- printk("%s: could not set section feed\n", dev->name);
- priv->demux->release_section_feed(priv->demux, priv->secfeed);
- priv->secfeed=NULL;
- return ret;
- }
+ if (ret<0) {
+ printk("%s: could not set section feed\n", dev->name);
+ priv->demux->release_section_feed(priv->demux, priv->secfeed);
+ priv->secfeed=NULL;
+ return ret;
+ }
- if (priv->rx_mode != RX_MODE_PROMISC) {
- dprintk("%s: set secfilter\n", __FUNCTION__);
+ if (priv->rx_mode != RX_MODE_PROMISC) {
+ dprintk("%s: set secfilter\n", __FUNCTION__);
dvb_net_filter_sec_set(dev, &priv->secfilter, mac, mask_normal);
- }
+ }
- switch (priv->rx_mode) {
- case RX_MODE_MULTI:
- for (i = 0; i < priv->multi_num; i++) {
- dprintk("%s: set multi_secfilter[%d]\n", __FUNCTION__, i);
+ switch (priv->rx_mode) {
+ case RX_MODE_MULTI:
+ for (i = 0; i < priv->multi_num; i++) {
+ dprintk("%s: set multi_secfilter[%d]\n", __FUNCTION__, i);
dvb_net_filter_sec_set(dev, &priv->multi_secfilter[i],
- priv->multi_macs[i], mask_normal);
- }
- break;
- case RX_MODE_ALL_MULTI:
- priv->multi_num=1;
- dprintk("%s: set multi_secfilter[0]\n", __FUNCTION__);
+ priv->multi_macs[i], mask_normal);
+ }
+ break;
+ case RX_MODE_ALL_MULTI:
+ priv->multi_num=1;
+ dprintk("%s: set multi_secfilter[0]\n", __FUNCTION__);
dvb_net_filter_sec_set(dev, &priv->multi_secfilter[0],
- mac_allmulti, mask_allmulti);
- break;
- case RX_MODE_PROMISC:
- priv->multi_num=0;
- dprintk("%s: set secfilter\n", __FUNCTION__);
+ mac_allmulti, mask_allmulti);
+ break;
+ case RX_MODE_PROMISC:
+ priv->multi_num=0;
+ dprintk("%s: set secfilter\n", __FUNCTION__);
dvb_net_filter_sec_set(dev, &priv->secfilter, mac, mask_promisc);
- break;
- }
-
- dprintk("%s: start filtering\n", __FUNCTION__);
- priv->secfeed->start_filtering(priv->secfeed);
+ break;
+ }
+
+ dprintk("%s: start filtering\n", __FUNCTION__);
+ priv->secfeed->start_filtering(priv->secfeed);
} else if (priv->feedtype == DVB_NET_FEEDTYPE_ULE) {
struct timespec timeout = { 0, 30000000 }; // 30 msec
@@ -970,33 +970,33 @@ static int dvb_net_feed_stop(struct net_device *dev)
dprintk("%s\n", __FUNCTION__);
if (priv->feedtype == DVB_NET_FEEDTYPE_MPE) {
- if (priv->secfeed) {
- if (priv->secfeed->is_filtering) {
- dprintk("%s: stop secfeed\n", __FUNCTION__);
- priv->secfeed->stop_filtering(priv->secfeed);
- }
+ if (priv->secfeed) {
+ if (priv->secfeed->is_filtering) {
+ dprintk("%s: stop secfeed\n", __FUNCTION__);
+ priv->secfeed->stop_filtering(priv->secfeed);
+ }
- if (priv->secfilter) {
- dprintk("%s: release secfilter\n", __FUNCTION__);
- priv->secfeed->release_filter(priv->secfeed,
- priv->secfilter);
- priv->secfilter=NULL;
- }
+ if (priv->secfilter) {
+ dprintk("%s: release secfilter\n", __FUNCTION__);
+ priv->secfeed->release_filter(priv->secfeed,
+ priv->secfilter);
+ priv->secfilter=NULL;
+ }
- for (i=0; i<priv->multi_num; i++) {
- if (priv->multi_secfilter[i]) {
+ for (i=0; i<priv->multi_num; i++) {
+ if (priv->multi_secfilter[i]) {
dprintk("%s: release multi_filter[%d]\n",
__FUNCTION__, i);
- priv->secfeed->release_filter(priv->secfeed,
- priv->multi_secfilter[i]);
- priv->multi_secfilter[i]=NULL;
- }
- }
+ priv->secfeed->release_filter(priv->secfeed,
+ priv->multi_secfilter[i]);
+ priv->multi_secfilter[i] = NULL;
+ }
+ }
- priv->demux->release_section_feed(priv->demux, priv->secfeed);
- priv->secfeed=NULL;
- } else
- printk("%s: no feed to stop\n", dev->name);
+ priv->demux->release_section_feed(priv->demux, priv->secfeed);
+ priv->secfeed = NULL;
+ } else
+ printk("%s: no feed to stop\n", dev->name);
} else if (priv->feedtype == DVB_NET_FEEDTYPE_ULE) {
if (priv->tsfeed) {
if (priv->tsfeed->is_filtering) {
@@ -1036,8 +1036,8 @@ static void wq_set_multicast_list (void *data)
dvb_net_feed_stop(dev);
priv->rx_mode = RX_MODE_UNI;
-
- if(dev->flags & IFF_PROMISC) {
+
+ if (dev->flags & IFF_PROMISC) {
dprintk("%s: promiscuous mode\n", dev->name);
priv->rx_mode = RX_MODE_PROMISC;
} else if ((dev->flags & IFF_ALLMULTI)) {
@@ -1053,15 +1053,15 @@ static void wq_set_multicast_list (void *data)
priv->rx_mode = RX_MODE_MULTI;
priv->multi_num = 0;
- for (mci = 0, mc=dev->mc_list;
+ for (mci = 0, mc=dev->mc_list;
mci < dev->mc_count;
mc = mc->next, mci++) {
dvb_set_mc_filter(dev, mc);
}
}
- dvb_net_feed_start(dev);
- }
+ dvb_net_feed_start(dev);
+}
static void dvb_net_set_multicast_list (struct net_device *dev)
@@ -1119,7 +1119,6 @@ static struct net_device_stats * dvb_net_get_stats(struct net_device *dev)
return &((struct dvb_net_priv*) dev->priv)->stats;
}
-
static void dvb_net_setup(struct net_device *dev)
{
ether_setup(dev);
@@ -1133,7 +1132,6 @@ static void dvb_net_setup(struct net_device *dev)
dev->mtu = 4096;
dev->mc_count = 0;
dev->hard_header_cache = NULL;
-
dev->flags |= IFF_NOARP;
}
@@ -1154,11 +1152,11 @@ static int get_if(struct dvb_net *dvbnet)
static int dvb_net_add_if(struct dvb_net *dvbnet, u16 pid, u8 feedtype)
{
- struct net_device *net;
+ struct net_device *net;
struct dvb_net_priv *priv;
int result;
int if_num;
-
+
if (feedtype != DVB_NET_FEEDTYPE_MPE && feedtype != DVB_NET_FEEDTYPE_ULE)
return -EINVAL;
if ((if_num = get_if(dvbnet)) < 0)
@@ -1167,7 +1165,7 @@ static int dvb_net_add_if(struct dvb_net *dvbnet, u16 pid, u8 feedtype)
net = alloc_netdev(sizeof(struct dvb_net_priv), "dvb", dvb_net_setup);
if (!net)
return -ENOMEM;
-
+
if (dvbnet->dvbdev->id)
snprintf(net->name, IFNAMSIZ, "dvb%d%u%d",
dvbnet->dvbdev->adapter->num, dvbnet->dvbdev->id, if_num);
@@ -1176,14 +1174,14 @@ static int dvb_net_add_if(struct dvb_net *dvbnet, u16 pid, u8 feedtype)
snprintf(net->name, IFNAMSIZ, "dvb%d_%d",
dvbnet->dvbdev->adapter->num, if_num);
- net->addr_len = 6;
+ net->addr_len = 6;
memcpy(net->dev_addr, dvbnet->dvbdev->adapter->proposed_mac, 6);
dvbnet->device[if_num] = net;
-
+
priv = net->priv;
- priv->demux = dvbnet->demux;
- priv->pid = pid;
+ priv->demux = dvbnet->demux;
+ priv->pid = pid;
priv->rx_mode = RX_MODE_UNI;
priv->need_pusi = 1;
priv->tscc = 0;
@@ -1193,8 +1191,8 @@ static int dvb_net_add_if(struct dvb_net *dvbnet, u16 pid, u8 feedtype)
INIT_WORK(&priv->set_multicast_list_wq, wq_set_multicast_list, net);
INIT_WORK(&priv->restart_net_feed_wq, wq_restart_net_feed, net);
- net->base_addr = pid;
-
+ net->base_addr = pid;
+
if ((result = register_netdev(net)) < 0) {
dvbnet->device[if_num] = NULL;
free_netdev(net);
@@ -1202,10 +1200,9 @@ static int dvb_net_add_if(struct dvb_net *dvbnet, u16 pid, u8 feedtype)
}
printk("dvb_net: created network interface %s\n", net->name);
- return if_num;
+ return if_num;
}
-
static int dvb_net_remove_if(struct dvb_net *dvbnet, unsigned int num)
{
struct net_device *net = dvbnet->device[num];
@@ -1220,7 +1217,7 @@ static int dvb_net_remove_if(struct dvb_net *dvbnet, unsigned int num)
dvb_net_stop(net);
flush_scheduled_work();
printk("dvb_net: removed network interface %s\n", net->name);
- unregister_netdev(net);
+ unregister_netdev(net);
dvbnet->state[num]=0;
dvbnet->device[num] = NULL;
free_netdev(net);
@@ -1228,7 +1225,6 @@ static int dvb_net_remove_if(struct dvb_net *dvbnet, unsigned int num)
return 0;
}
-
static int dvb_net_do_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, void *parg)
{
@@ -1237,13 +1233,13 @@ static int dvb_net_do_ioctl(struct inode *inode, struct file *file,
if (((file->f_flags&O_ACCMODE)==O_RDONLY))
return -EPERM;
-
+
switch (cmd) {
case NET_ADD_IF:
{
struct dvb_net_if *dvbnetif=(struct dvb_net_if *)parg;
int result;
-
+
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
@@ -1269,6 +1265,7 @@ static int dvb_net_do_ioctl(struct inode *inode, struct file *file,
return -EINVAL;
netdev = dvbnet->device[dvbnetif->if_num];
+
priv_data=(struct dvb_net_priv*)netdev->priv;
dvbnetif->pid=priv_data->pid;
dvbnetif->feedtype=priv_data->feedtype;
@@ -1316,9 +1313,10 @@ static int dvb_net_do_ioctl(struct inode *inode, struct file *file,
if (dvbnetif->if_num >= DVB_NET_DEVICES_MAX ||
!dvbnet->state[dvbnetif->if_num])
- return -EINVAL;
+ return -EINVAL;
netdev = dvbnet->device[dvbnetif->if_num];
+
priv_data=(struct dvb_net_priv*)netdev->priv;
dvbnetif->pid=priv_data->pid;
break;
@@ -1369,7 +1367,7 @@ int dvb_net_init (struct dvb_adapter *adap, struct dvb_net *dvbnet,
struct dmx_demux *dmx)
{
int i;
-
+
dvbnet->demux = dmx;
for (i=0; i<DVB_NET_DEVICES_MAX; i++)
diff --git a/drivers/media/dvb/dvb-core/dvb_net.h b/drivers/media/dvb/dvb-core/dvb_net.h
index 5b701efe8e4db..f14e4ca385708 100644
--- a/drivers/media/dvb/dvb-core/dvb_net.h
+++ b/drivers/media/dvb/dvb-core/dvb_net.h
@@ -1,4 +1,4 @@
-/*
+/*
* dvb_net.h
*
* Copyright (C) 2001 Ralph Metzler for convergence integrated media GmbH
@@ -44,4 +44,3 @@ void dvb_net_release(struct dvb_net *);
int dvb_net_init(struct dvb_adapter *, struct dvb_net *, struct dmx_demux *);
#endif
-
diff --git a/drivers/media/dvb/dvb-core/dvb_ringbuffer.c b/drivers/media/dvb/dvb-core/dvb_ringbuffer.c
index fd04a1f3fb14e..fb6d94a69d71f 100644
--- a/drivers/media/dvb/dvb-core/dvb_ringbuffer.c
+++ b/drivers/media/dvb/dvb-core/dvb_ringbuffer.c
@@ -2,9 +2,9 @@
*
* dvb_ringbuffer.c: ring buffer implementation for the dvb driver
*
- * Copyright (C) 2003 Oliver Endriss
+ * Copyright (C) 2003 Oliver Endriss
* Copyright (C) 2004 Andrew de Quincey
- *
+ *
* based on code originally found in av7110.c & dvb_ci.c:
* Copyright (C) 1999-2003 Ralph Metzler
* & Marcus Metzler for convergence integrated media GmbH
@@ -13,7 +13,7 @@
* 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 program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
@@ -63,7 +63,7 @@ int dvb_ringbuffer_empty(struct dvb_ringbuffer *rbuf)
ssize_t dvb_ringbuffer_free(struct dvb_ringbuffer *rbuf)
{
ssize_t free;
-
+
free = rbuf->pread - rbuf->pwrite;
if (free <= 0)
free += rbuf->size;
@@ -75,7 +75,7 @@ ssize_t dvb_ringbuffer_free(struct dvb_ringbuffer *rbuf)
ssize_t dvb_ringbuffer_avail(struct dvb_ringbuffer *rbuf)
{
ssize_t avail;
-
+
avail = rbuf->pwrite - rbuf->pread;
if (avail < 0)
avail += rbuf->size;
@@ -137,19 +137,19 @@ ssize_t dvb_ringbuffer_write(struct dvb_ringbuffer *rbuf, const u8 *buf, size_t
{
size_t todo = len;
size_t split;
-
+
split = (rbuf->pwrite + len > rbuf->size) ? rbuf->size - rbuf->pwrite : 0;
if (split > 0) {
- memcpy(rbuf->data+rbuf->pwrite, buf, split);
+ memcpy(rbuf->data+rbuf->pwrite, buf, split);
buf += split;
todo -= split;
rbuf->pwrite = 0;
}
- memcpy(rbuf->data+rbuf->pwrite, buf, todo);
+ memcpy(rbuf->data+rbuf->pwrite, buf, todo);
rbuf->pwrite = (rbuf->pwrite + todo) % rbuf->size;
- return len;
+ return len;
}
ssize_t dvb_ringbuffer_pkt_write(struct dvb_ringbuffer *rbuf, u8* buf, size_t len)
diff --git a/drivers/media/dvb/dvb-core/dvb_ringbuffer.h b/drivers/media/dvb/dvb-core/dvb_ringbuffer.h
index c1ffa271f5837..d18e9c4ba9ea3 100644
--- a/drivers/media/dvb/dvb-core/dvb_ringbuffer.h
+++ b/drivers/media/dvb/dvb-core/dvb_ringbuffer.h
@@ -2,9 +2,9 @@
*
* dvb_ringbuffer.h: ring buffer implementation for the dvb driver
*
- * Copyright (C) 2003 Oliver Endriss
+ * Copyright (C) 2003 Oliver Endriss
* Copyright (C) 2004 Andrew de Quincey
- *
+ *
* based on code originally found in av7110.c & dvb_ci.c:
* Copyright (C) 1999-2003 Ralph Metzler & Marcus Metzler
* for convergence integrated media GmbH
@@ -13,12 +13,12 @@
* 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 program is distributed in the hope that 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 program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
@@ -52,7 +52,7 @@ struct dvb_ringbuffer {
**
** *** write <buflen> bytes ***
** free = dvb_ringbuffer_free(rbuf);
-** if (free >= buflen)
+** if (free >= buflen)
** count = dvb_ringbuffer_write(rbuf, buffer, buflen);
** else
** ...
@@ -64,7 +64,7 @@ struct dvb_ringbuffer {
** else
** ...
**
-** (2) If there is exactly one reader and one writer, there is no need
+** (2) If there is exactly one reader and one writer, there is no need
** to lock read or write operations.
** Two or more readers must be locked against each other.
** Flushing the buffer counts as a read operation.
@@ -99,13 +99,13 @@ extern void dvb_ringbuffer_flush_spinlock_wakeup(struct dvb_ringbuffer *rbuf);
/* advance read ptr by <num> bytes */
#define DVB_RINGBUFFER_SKIP(rbuf,num) \
(rbuf)->pread=((rbuf)->pread+(num))%(rbuf)->size
-
+
/*
-** read <len> bytes from ring buffer into <buf>
+** read <len> bytes from ring buffer into <buf>
** <usermem> specifies whether <buf> resides in user space
** returns number of bytes transferred or -EFAULT
*/
-extern ssize_t dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf, u8 *buf,
+extern ssize_t dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf, u8 *buf,
size_t len, int usermem);
diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c
index 4032239b39d0d..cf4ffe38fda37 100644
--- a/drivers/media/dvb/dvb-core/dvbdev.c
+++ b/drivers/media/dvb/dvb-core/dvbdev.c
@@ -1,4 +1,4 @@
-/*
+/*
* dvbdev.c
*
* Copyright (C) 2000 Ralph Metzler <ralph@convergence.de>
@@ -51,10 +51,10 @@ static const char * const dnames[] = {
"net", "osd"
};
-
-#define DVB_MAX_IDS 6
-#define nums2minor(num,type,id) ((num << 6) | (id << 4) | type)
-#define MAX_DVB_MINORS (DVB_MAX_IDS*64)
+#define DVB_MAX_ADAPTERS 8
+#define DVB_MAX_IDS 4
+#define nums2minor(num,type,id) ((num << 6) | (id << 4) | type)
+#define MAX_DVB_MINORS (DVB_MAX_ADAPTERS*64)
struct class_simple *dvb_class;
EXPORT_SYMBOL(dvb_class);
@@ -82,7 +82,7 @@ static struct dvb_device* dvbdev_find_device (int minor)
static int dvb_device_open(struct inode *inode, struct file *file)
{
struct dvb_device *dvbdev;
-
+
dvbdev = dvbdev_find_device (iminor(inode));
if (dvbdev && dvbdev->fops) {
@@ -111,7 +111,6 @@ static struct file_operations dvb_device_fops =
.open = dvb_device_open,
};
-
static struct cdev dvb_device_cdev = {
.kobj = {.name = "dvb", },
.owner = THIS_MODULE,
@@ -166,7 +165,7 @@ int dvb_generic_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
struct dvb_device *dvbdev = file->private_data;
-
+
if (!dvbdev)
return -ENODEV;
@@ -198,7 +197,7 @@ skip:
}
-int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
+int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
const struct dvb_device *template, void *priv, int type)
{
struct dvb_device *dvbdev;
@@ -222,7 +221,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
}
up (&dvbdev_register_lock);
-
+
memcpy(dvbdev, template, sizeof(struct dvb_device));
dvbdev->type = type;
dvbdev->id = id;
@@ -254,15 +253,15 @@ void dvb_unregister_device(struct dvb_device *dvbdev)
if (!dvbdev)
return;
- devfs_remove("dvb/adapter%d/%s%d", dvbdev->adapter->num,
- dnames[dvbdev->type], dvbdev->id);
+ devfs_remove("dvb/adapter%d/%s%d", dvbdev->adapter->num,
+ dnames[dvbdev->type], dvbdev->id);
class_simple_device_remove(MKDEV(DVB_MAJOR, nums2minor(dvbdev->adapter->num,
dvbdev->type, dvbdev->id)));
- list_del(&dvbdev->list_head);
- kfree(dvbdev);
- }
+ list_del (&dvbdev->list_head);
+ kfree (dvbdev);
+}
EXPORT_SYMBOL(dvb_unregister_device);
@@ -270,7 +269,7 @@ static int dvbdev_get_free_adapter_num (void)
{
int num = 0;
- while (1) {
+ while (num < DVB_MAX_ADAPTERS) {
struct list_head *entry;
list_for_each (entry, &dvb_adapter_list) {
struct dvb_adapter *adap;
@@ -309,9 +308,8 @@ int dvb_register_adapter(struct dvb_adapter **padap, const char *name, struct mo
INIT_LIST_HEAD (&adap->device_list);
printk ("DVB: registering new adapter (%s).\n", name);
-
- devfs_mk_dir("dvb/adapter%d", num);
+ devfs_mk_dir("dvb/adapter%d", num);
adap->num = num;
adap->name = name;
adap->module = module;
@@ -399,9 +397,7 @@ int dvb_usercopy(struct inode *inode, struct file *file,
}
out:
- if (mbuf)
- kfree(mbuf);
-
+ kfree(mbuf);
return err;
}
@@ -451,4 +447,3 @@ module_exit(exit_dvbdev);
MODULE_DESCRIPTION("DVB Core Driver");
MODULE_AUTHOR("Marcus Metzler, Ralph Metzler, Holger Waechtler");
MODULE_LICENSE("GPL");
-
diff --git a/drivers/media/dvb/dvb-core/dvbdev.h b/drivers/media/dvb/dvb-core/dvbdev.h
index 333ada77ce7b1..184edba3caa71 100644
--- a/drivers/media/dvb/dvb-core/dvbdev.h
+++ b/drivers/media/dvb/dvb-core/dvbdev.h
@@ -1,4 +1,4 @@
-/*
+/*
* dvbdev.h
*
* Copyright (C) 2000 Ralph Metzler & Marcus Metzler
@@ -58,9 +58,6 @@ struct dvb_adapter {
struct dvb_device {
struct list_head list_head;
struct file_operations *fops;
-
-
-
struct dvb_adapter *adapter;
int type;
u32 id;
@@ -83,7 +80,7 @@ extern int dvb_register_adapter (struct dvb_adapter **padap, const char *name, s
extern int dvb_unregister_adapter (struct dvb_adapter *adap);
extern int dvb_register_device (struct dvb_adapter *adap,
- struct dvb_device **pdvbdev,
+ struct dvb_device **pdvbdev,
const struct dvb_device *template,
void *priv,
int type);
@@ -105,4 +102,3 @@ extern int dvb_usercopy(struct inode *inode, struct file *file,
unsigned int cmd, void *arg));
#endif /* #ifndef _DVBDEV_H_ */
-
diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig
index 4c3582940e62a..0bfd4df17d08d 100644
--- a/drivers/media/dvb/frontends/Kconfig
+++ b/drivers/media/dvb/frontends/Kconfig
@@ -108,14 +108,14 @@ config DVB_MT352
A DVB-T tuner module. Say Y when you want to support this frontend.
config DVB_DIB3000MB
- tristate "DiBcom 3000-MB"
+ tristate "DiBcom 3000M-B"
depends on DVB_CORE
help
A DVB-T tuner module. Designed for mobile usage. Say Y when you want
to support this frontend.
config DVB_DIB3000MC
- tristate "DiBcom 3000-MC/P"
+ tristate "DiBcom 3000P/M-C"
depends on DVB_CORE
help
A DVB-T tuner module. Designed for mobile usage. Say Y when you want
@@ -154,6 +154,18 @@ comment "ATSC (North American/Korean Terresterial DTV) frontends"
config DVB_NXT2002
tristate "Nxt2002 based"
depends on DVB_CORE
+ select FW_LOADER
+ help
+ An ATSC 8VSB tuner module. Say Y when you want to support this frontend.
+
+config DVB_OR51132
+ tristate "OR51132 based (pcHDTV)"
+ depends on DVB_CORE
+
+config DVB_OR51211
+ tristate "or51211 based (pcHDTV HD2000 card)"
+ depends on DVB_CORE
+ select FW_LOADER
help
An ATSC 8VSB tuner module. Say Y when you want to support this frontend.
diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile
index 117ed87eb322b..7f8784870eab2 100644
--- a/drivers/media/dvb/frontends/Makefile
+++ b/drivers/media/dvb/frontends/Makefile
@@ -4,6 +4,7 @@
EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/
+obj-$(CONFIG_DVB_CORE) += dvb-pll.o
obj-$(CONFIG_DVB_STV0299) += stv0299.o
obj-$(CONFIG_DVB_SP8870) += sp8870.o
obj-$(CONFIG_DVB_CX22700) += cx22700.o
@@ -25,4 +26,5 @@ obj-$(CONFIG_DVB_TDA80XX) += tda80xx.o
obj-$(CONFIG_DVB_TDA10021) += tda10021.o
obj-$(CONFIG_DVB_STV0297) += stv0297.o
obj-$(CONFIG_DVB_NXT2002) += nxt2002.o
-
+obj-$(CONFIG_DVB_OR51211) += or51211.o
+obj-$(CONFIG_DVB_OR51132) += or51132.o
diff --git a/drivers/media/dvb/frontends/at76c651.c b/drivers/media/dvb/frontends/at76c651.c
index 4b6c539a0d67d..ce2eaa1640e87 100644
--- a/drivers/media/dvb/frontends/at76c651.c
+++ b/drivers/media/dvb/frontends/at76c651.c
@@ -1,6 +1,6 @@
/*
* at76c651.c
- *
+ *
* Atmel DVB-C Frontend Driver (at76c651/tua6010xs)
*
* Copyright (C) 2001 fnbrd <fnbrd@gmx.de>
@@ -150,7 +150,7 @@ static int at76c651_set_auto_config(struct at76c651_state *state)
if (state->revision == 0x11) {
at76c651_writereg(state, 0x2E, 0x38);
at76c651_writereg(state, 0x2F, 0x13);
-}
+ }
at76c651_disable_interrupts(state);
@@ -255,16 +255,8 @@ static int at76c651_set_inversion(struct at76c651_state* state, fe_spectral_inve
return at76c651_writereg(state, 0x60, feciqinv);
}
-
-
-
-
-
-
-
-
static int at76c651_set_parameters(struct dvb_frontend* fe,
- struct dvb_frontend_parameters *p)
+ struct dvb_frontend_parameters *p)
{
int ret;
struct at76c651_state* state = (struct at76c651_state*) fe->demodulator_priv;
@@ -295,54 +287,50 @@ static int at76c651_set_defaults(struct dvb_frontend* fe)
at76c651_writereg(state, 0x0c, 0xc3);
state->config->pll_init(fe);
at76c651_writereg(state, 0x0c, 0xc2);
-}
+ }
return 0;
}
static int at76c651_read_status(struct dvb_frontend* fe, fe_status_t* status)
- {
+{
struct at76c651_state* state = (struct at76c651_state*) fe->demodulator_priv;
- u8 sync;
+ u8 sync;
- /*
- * Bits: FEC, CAR, EQU, TIM, AGC2, AGC1, ADC, PLL (PLL=0)
- */
+ /*
+ * Bits: FEC, CAR, EQU, TIM, AGC2, AGC1, ADC, PLL (PLL=0)
+ */
sync = at76c651_readreg(state, 0x80);
- *status = 0;
-
- if (sync & (0x04 | 0x10)) /* AGC1 || TIM */
- *status |= FE_HAS_SIGNAL;
-
- if (sync & 0x10) /* TIM */
- *status |= FE_HAS_CARRIER;
-
- if (sync & 0x80) /* FEC */
- *status |= FE_HAS_VITERBI;
-
- if (sync & 0x40) /* CAR */
- *status |= FE_HAS_SYNC;
-
- if ((sync & 0xF0) == 0xF0) /* TIM && EQU && CAR && FEC */
- *status |= FE_HAS_LOCK;
+ *status = 0;
+
+ if (sync & (0x04 | 0x10)) /* AGC1 || TIM */
+ *status |= FE_HAS_SIGNAL;
+ if (sync & 0x10) /* TIM */
+ *status |= FE_HAS_CARRIER;
+ if (sync & 0x80) /* FEC */
+ *status |= FE_HAS_VITERBI;
+ if (sync & 0x40) /* CAR */
+ *status |= FE_HAS_SYNC;
+ if ((sync & 0xF0) == 0xF0) /* TIM && EQU && CAR && FEC */
+ *status |= FE_HAS_LOCK;
return 0;
- }
+}
static int at76c651_read_ber(struct dvb_frontend* fe, u32* ber)
- {
+{
struct at76c651_state* state = (struct at76c651_state*) fe->demodulator_priv;
*ber = (at76c651_readreg(state, 0x81) & 0x0F) << 16;
*ber |= at76c651_readreg(state, 0x82) << 8;
*ber |= at76c651_readreg(state, 0x83);
- *ber *= 10;
+ *ber *= 10;
return 0;
- }
+}
static int at76c651_read_signal_strength(struct dvb_frontend* fe, u16* strength)
- {
+{
struct at76c651_state* state = (struct at76c651_state*) fe->demodulator_priv;
u8 gain = ~at76c651_readreg(state, 0x91);
@@ -359,12 +347,11 @@ static int at76c651_read_snr(struct dvb_frontend* fe, u16* snr)
((at76c651_readreg(state, 0x8F) << 8) |
at76c651_readreg(state, 0x90));
-
return 0;
}
static int at76c651_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
- {
+{
struct at76c651_state* state = (struct at76c651_state*) fe->demodulator_priv;
*ucblocks = at76c651_readreg(state, 0x82);
@@ -378,13 +365,13 @@ static int at76c651_get_tune_settings(struct dvb_frontend* fe, struct dvb_fronte
fesettings->step_size = 0;
fesettings->max_drift = 0;
return 0;
- }
+}
static void at76c651_release(struct dvb_frontend* fe)
{
struct at76c651_state* state = (struct at76c651_state*) fe->demodulator_priv;
- kfree(state);
- }
+ kfree(state);
+}
static struct dvb_frontend_ops at76c651_ops;
@@ -415,7 +402,7 @@ struct dvb_frontend* at76c651_attach(const struct at76c651_config* config,
return &state->frontend;
error:
- if (state) kfree(state);
+ kfree(state);
return NULL;
}
diff --git a/drivers/media/dvb/frontends/cx22700.c b/drivers/media/dvb/frontends/cx22700.c
index cddfe05a8686b..a212279042b8f 100644
--- a/drivers/media/dvb/frontends/cx22700.c
+++ b/drivers/media/dvb/frontends/cx22700.c
@@ -230,16 +230,6 @@ static int cx22700_get_tps (struct cx22700_state* state, struct dvb_ofdm_paramet
return 0;
}
-
-
-
-
-
-
-
-
-
-
static int cx22700_init (struct dvb_frontend* fe)
{ struct cx22700_state* state = (struct cx22700_state*) fe->demodulator_priv;
@@ -402,18 +392,18 @@ struct dvb_frontend* cx22700_attach(const struct cx22700_config* config,
return &state->frontend;
error:
- if (state) kfree(state);
+ kfree(state);
return NULL;
}
static struct dvb_frontend_ops cx22700_ops = {
.info = {
- .name = "Conexant CX22700 DVB-T",
- .type = FE_OFDM,
- .frequency_min = 470000000,
- .frequency_max = 860000000,
- .frequency_stepsize = 166667,
+ .name = "Conexant CX22700 DVB-T",
+ .type = FE_OFDM,
+ .frequency_min = 470000000,
+ .frequency_max = 860000000,
+ .frequency_stepsize = 166667,
.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 |
diff --git a/drivers/media/dvb/frontends/cx22702.c b/drivers/media/dvb/frontends/cx22702.c
index 15ae90316c1f5..1930b513eefad 100644
--- a/drivers/media/dvb/frontends/cx22702.c
+++ b/drivers/media/dvb/frontends/cx22702.c
@@ -186,7 +186,7 @@ static int cx22702_get_tps (struct cx22702_state *state, struct dvb_ofdm_paramet
case 1: p->guard_interval = GUARD_INTERVAL_1_16; break;
case 2: p->guard_interval = GUARD_INTERVAL_1_8; break;
case 3: p->guard_interval = GUARD_INTERVAL_1_4; break;
-}
+ }
switch( val&0x03 ) {
case 0: p->transmission_mode = TRANSMISSION_MODE_2K; break;
case 1: p->transmission_mode = TRANSMISSION_MODE_8K; break;
@@ -195,18 +195,6 @@ static int cx22702_get_tps (struct cx22702_state *state, struct dvb_ofdm_paramet
return 0;
}
-
-
-
-
-
-
-
-
-
-
-
-
/* 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)
{
@@ -259,7 +247,7 @@ static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_paramet
return 0;
}
- /* manually programmed values */
+ /* manually programmed values */
val=0;
switch(p->u.ofdm.constellation) {
case QPSK: val = (val&0xe7); break;
@@ -332,7 +320,6 @@ static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_paramet
return 0;
}
-
/* Reset the demod hardware and reset all of the configuration registers
to a default state. */
static int cx22702_init (struct dvb_frontend* fe)
@@ -364,48 +351,48 @@ static int cx22702_read_status(struct dvb_frontend* fe, fe_status_t* status)
u8 reg0A;
u8 reg23;
- *status = 0;
+ *status = 0;
reg0A = cx22702_readreg (state, 0x0A);
reg23 = cx22702_readreg (state, 0x23);
- dprintk ("%s: status demod=0x%02x agc=0x%02x\n"
- ,__FUNCTION__,reg0A,reg23);
+ dprintk ("%s: status demod=0x%02x agc=0x%02x\n"
+ ,__FUNCTION__,reg0A,reg23);
- if(reg0A & 0x10) {
- *status |= FE_HAS_LOCK;
- *status |= FE_HAS_VITERBI;
- *status |= FE_HAS_SYNC;
- }
+ if(reg0A & 0x10) {
+ *status |= FE_HAS_LOCK;
+ *status |= FE_HAS_VITERBI;
+ *status |= FE_HAS_SYNC;
+ }
- if(reg0A & 0x20)
- *status |= FE_HAS_CARRIER;
+ if(reg0A & 0x20)
+ *status |= FE_HAS_CARRIER;
- if(reg23 < 0xf0)
- *status |= FE_HAS_SIGNAL;
+ if(reg23 < 0xf0)
+ *status |= FE_HAS_SIGNAL;
return 0;
- }
+}
static int cx22702_read_ber(struct dvb_frontend* fe, u32* ber)
- {
+{
struct cx22702_state* state = (struct cx22702_state*) fe->demodulator_priv;
if(cx22702_readreg (state, 0xE4) & 0x02) {
- /* Realtime statistics */
+ /* Realtime statistics */
*ber = (cx22702_readreg (state, 0xDE) & 0x7F) << 7
| (cx22702_readreg (state, 0xDF)&0x7F);
- } else {
+ } else {
/* Averagtine statistics */
*ber = (cx22702_readreg (state, 0xDE) & 0x7F) << 7
| cx22702_readreg (state, 0xDF);
- }
+ }
return 0;
- }
+}
static int cx22702_read_signal_strength(struct dvb_frontend* fe, u16* signal_strength)
- {
+{
struct cx22702_state* state = (struct cx22702_state*) fe->demodulator_priv;
*signal_strength = cx22702_readreg (state, 0x23);
@@ -460,8 +447,8 @@ static int cx22702_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
static void cx22702_release(struct dvb_frontend* fe)
{
struct cx22702_state* state = (struct cx22702_state*) fe->demodulator_priv;
- kfree(state);
- }
+ kfree(state);
+}
static struct dvb_frontend_ops cx22702_ops;
@@ -489,7 +476,7 @@ struct dvb_frontend* cx22702_attach(const struct cx22702_config* config,
return &state->frontend;
error:
- if (state) kfree(state);
+ kfree(state);
return NULL;
}
diff --git a/drivers/media/dvb/frontends/cx24110.c b/drivers/media/dvb/frontends/cx24110.c
index f8d5ec9ea11f8..ae16112a06535 100644
--- a/drivers/media/dvb/frontends/cx24110.c
+++ b/drivers/media/dvb/frontends/cx24110.c
@@ -131,7 +131,6 @@ static int cx24110_writereg (struct cx24110_state* state, int reg, int data)
return 0;
}
-
static int cx24110_readreg (struct cx24110_state* state, u8 reg)
{
int ret;
@@ -181,7 +180,6 @@ static int cx24110_set_inversion (struct cx24110_state* state, fe_spectral_inver
return 0;
}
-
static int cx24110_set_fec (struct cx24110_state* state, fe_code_rate_t fec)
{
/* fixme (low): error handling */
@@ -227,7 +225,6 @@ static int cx24110_set_fec (struct cx24110_state* state, fe_code_rate_t fec)
return 0;
}
-
static fe_code_rate_t cx24110_get_fec (struct cx24110_state* state)
{
int i;
@@ -244,7 +241,6 @@ static fe_code_rate_t cx24110_get_fec (struct cx24110_state* state)
}
}
-
static int cx24110_set_symbolrate (struct cx24110_state* state, u32 srate)
{
/* fixme (low): add error handling */
@@ -317,17 +313,6 @@ dprintk("cx24110 debug: entering %s(%d)\n",__FUNCTION__,srate);
}
-
-
-
-
-
-
-
-
-
-
-
int cx24110_pll_write (struct dvb_frontend* fe, u32 data)
{
struct cx24110_state *state = (struct cx24110_state*) fe->demodulator_priv;
@@ -369,8 +354,6 @@ int cx24110_pll_write (struct dvb_frontend* fe, u32 data)
return 0;
}
-
-
static int cx24110_initfe(struct dvb_frontend* fe)
{
struct cx24110_state *state = (struct cx24110_state*) fe->demodulator_priv;
@@ -388,7 +371,6 @@ static int cx24110_initfe(struct dvb_frontend* fe)
return 0;
}
-
static int cx24110_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltage)
{
struct cx24110_state *state = (struct cx24110_state*) fe->demodulator_priv;
@@ -403,8 +385,32 @@ static int cx24110_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltag
};
}
+static int cx24110_diseqc_send_burst(struct dvb_frontend* fe,
+ fe_sec_mini_cmd_t burst)
+{
+ int rv, bit, i;
+ struct cx24110_state *state = fe->demodulator_priv;
+
+ if (burst == SEC_MINI_A)
+ bit = 0x00;
+ else if (burst == SEC_MINI_B)
+ bit = 0x08;
+ else
+ return -EINVAL;
+
+ rv = cx24110_readreg(state, 0x77);
+ cx24110_writereg(state, 0x77, rv|0x04);
+
+ rv = cx24110_readreg(state, 0x76);
+ cx24110_writereg(state, 0x76, ((rv & 0x90) | 0x40 | bit));
+ for (i = 500; i-- > 0 && !(cx24110_readreg(state,0x76)&0x40) ; )
+ ; /* wait for LNB ready */
+
+ return 0;
+}
+
static int cx24110_send_diseqc_msg(struct dvb_frontend* fe,
- struct dvb_diseqc_master_cmd *cmd)
+ struct dvb_diseqc_master_cmd *cmd)
{
int i, rv;
struct cx24110_state *state = (struct cx24110_state*) fe->demodulator_priv;
@@ -412,6 +418,9 @@ static int cx24110_send_diseqc_msg(struct dvb_frontend* fe,
for (i = 0; i < cmd->msg_len; i++)
cx24110_writereg(state, 0x79 + i, cmd->msg[i]);
+ rv = cx24110_readreg(state, 0x77);
+ cx24110_writereg(state, 0x77, rv|0x04);
+
rv = cx24110_readreg(state, 0x76);
cx24110_writereg(state, 0x76, ((rv & 0x90) | 0x40) | ((cmd->msg_len-3) & 3));
@@ -427,33 +436,33 @@ static int cx24110_read_status(struct dvb_frontend* fe, fe_status_t* status)
int sync = cx24110_readreg (state, 0x55);
- *status = 0;
+ *status = 0;
- if (sync & 0x10)
- *status |= FE_HAS_SIGNAL;
+ if (sync & 0x10)
+ *status |= FE_HAS_SIGNAL;
- if (sync & 0x08)
- *status |= FE_HAS_CARRIER;
+ if (sync & 0x08)
+ *status |= FE_HAS_CARRIER;
sync = cx24110_readreg (state, 0x08);
- if (sync & 0x40)
- *status |= FE_HAS_VITERBI;
+ if (sync & 0x40)
+ *status |= FE_HAS_VITERBI;
- if (sync & 0x20)
- *status |= FE_HAS_SYNC;
+ if (sync & 0x20)
+ *status |= FE_HAS_SYNC;
- if ((sync & 0x60) == 0x60)
- *status |= FE_HAS_LOCK;
+ if ((sync & 0x60) == 0x60)
+ *status |= FE_HAS_LOCK;
return 0;
- }
+}
static int cx24110_read_ber(struct dvb_frontend* fe, u32* ber)
- {
+{
struct cx24110_state *state = (struct cx24110_state*) fe->demodulator_priv;
-/* fixme (maybe): value range is 16 bit. Scale? */
+ /* fixme (maybe): value range is 16 bit. Scale? */
if(cx24110_readreg(state,0x24)&0x10) {
/* the Viterbi error counter has finished one counting window */
cx24110_writereg(state,0x24,0x04); /* select the ber reg */
@@ -465,10 +474,10 @@ static int cx24110_read_ber(struct dvb_frontend* fe, u32* ber)
*ber = state->lastber;
return 0;
- }
+}
static int cx24110_read_signal_strength(struct dvb_frontend* fe, u16* signal_strength)
- {
+{
struct cx24110_state *state = (struct cx24110_state*) fe->demodulator_priv;
/* no provision in hardware. Read the frontend AGC accumulator. No idea how to scale this, but I know it is 2s complement */
@@ -476,13 +485,13 @@ static int cx24110_read_signal_strength(struct dvb_frontend* fe, u16* signal_str
*signal_strength = (signal << 8) | signal;
return 0;
- }
+}
static int cx24110_read_snr(struct dvb_frontend* fe, u16* snr)
- {
+{
struct cx24110_state *state = (struct cx24110_state*) fe->demodulator_priv;
-/* no provision in hardware. Can be computed from the Es/N0 estimator, but I don't know how. */
+ /* no provision in hardware. Can be computed from the Es/N0 estimator, but I don't know how. */
if(cx24110_readreg(state,0x6a)&0x80) {
/* the Es/N0 error counter has finished one counting window */
state->lastesn0=cx24110_readreg(state,0x69)|
@@ -492,10 +501,10 @@ static int cx24110_read_snr(struct dvb_frontend* fe, u16* snr)
*snr = state->lastesn0;
return 0;
- }
+}
static int cx24110_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
- {
+{
struct cx24110_state *state = (struct cx24110_state*) fe->demodulator_priv;
u32 lastbyer;
@@ -517,7 +526,7 @@ static int cx24110_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
}
static int cx24110_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
- {
+{
struct cx24110_state *state = (struct cx24110_state*) fe->demodulator_priv;
state->config->pll_set(fe, p);
@@ -527,38 +536,38 @@ static int cx24110_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
cx24110_writereg(state,0x04,0x05); /* start aquisition */
return 0;
- }
+}
static int cx24110_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
- {
- struct cx24110_state *state = (struct cx24110_state*) fe->demodulator_priv;
- s32 afc; unsigned sclk;
+{
+ struct cx24110_state *state = (struct cx24110_state*) fe->demodulator_priv;
+ s32 afc; unsigned sclk;
/* cannot read back tuner settings (freq). Need to have some private storage */
sclk = cx24110_readreg (state, 0x07) & 0x03;
/* ok, real AFC (FEDR) freq. is afc/2^24*fsamp, fsamp=45/60/80/90MHz.
* Need 64 bit arithmetic. Is thiss possible in the kernel? */
- if (sclk==0) sclk=90999000L/2L;
- else if (sclk==1) sclk=60666000L;
- else if (sclk==2) sclk=80888000L;
- else sclk=90999000L;
- sclk>>=8;
+ if (sclk==0) sclk=90999000L/2L;
+ else if (sclk==1) sclk=60666000L;
+ else if (sclk==2) sclk=80888000L;
+ else sclk=90999000L;
+ sclk>>=8;
afc = sclk*(cx24110_readreg (state, 0x44)&0x1f)+
((sclk*cx24110_readreg (state, 0x45))>>8)+
((sclk*cx24110_readreg (state, 0x46))>>16);
- p->frequency += afc;
+ p->frequency += afc;
p->inversion = (cx24110_readreg (state, 0x22) & 0x10) ?
- INVERSION_ON : INVERSION_OFF;
+ INVERSION_ON : INVERSION_OFF;
p->u.qpsk.fec_inner = cx24110_get_fec (state);
- return 0;
+ return 0;
}
static int cx24110_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
{
- struct cx24110_state *state = (struct cx24110_state*) fe->demodulator_priv;
+ struct cx24110_state *state = (struct cx24110_state*) fe->demodulator_priv;
return cx24110_writereg(state,0x76,(cx24110_readreg(state,0x76)&~0x10)|(((tone==SEC_TONE_ON))?0x10:0));
}
@@ -566,7 +575,7 @@ static int cx24110_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
static void cx24110_release(struct dvb_frontend* fe)
{
struct cx24110_state* state = (struct cx24110_state*) fe->demodulator_priv;
- kfree(state);
+ kfree(state);
}
static struct dvb_frontend_ops cx24110_ops;
@@ -587,7 +596,7 @@ struct dvb_frontend* cx24110_attach(const struct cx24110_config* config,
memcpy(&state->ops, &cx24110_ops, sizeof(struct dvb_frontend_ops));
state->lastber = 0;
state->lastbler = 0;
- state->lastesn0 = 0;
+ state->lastesn0 = 0;
/* check if the demod is there */
ret = cx24110_readreg(state, 0x00);
@@ -599,7 +608,7 @@ struct dvb_frontend* cx24110_attach(const struct cx24110_config* config,
return &state->frontend;
error:
- if (state) kfree(state);
+ kfree(state);
return NULL;
}
@@ -634,6 +643,7 @@ static struct dvb_frontend_ops cx24110_ops = {
.diseqc_send_master_cmd = cx24110_send_diseqc_msg,
.set_tone = cx24110_set_tone,
.set_voltage = cx24110_set_voltage,
+ .diseqc_send_burst = cx24110_diseqc_send_burst,
};
module_param(debug, int, 0644);
diff --git a/drivers/media/dvb/frontends/dib3000-common.c b/drivers/media/dvb/frontends/dib3000-common.c
index 1a4f1f7c228a1..47ab02e133d1b 100644
--- a/drivers/media/dvb/frontends/dib3000-common.c
+++ b/drivers/media/dvb/frontends/dib3000-common.c
@@ -73,7 +73,7 @@ u16 dib3000_seq[2][2][2] = /* fft,gua, inv */
};
MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de");
-MODULE_DESCRIPTION("Common functions for the dib3000mb/dib3000mc dvb frontend drivers");
+MODULE_DESCRIPTION("Common functions for the dib3000mb/dib3000mc dvb-frontend drivers");
MODULE_LICENSE("GPL");
EXPORT_SYMBOL(dib3000_seq);
diff --git a/drivers/media/dvb/frontends/dib3000-common.h b/drivers/media/dvb/frontends/dib3000-common.h
index 2286891da698b..c31d6df15472e 100644
--- a/drivers/media/dvb/frontends/dib3000-common.h
+++ b/drivers/media/dvb/frontends/dib3000-common.h
@@ -1,6 +1,6 @@
/*
* .h-files for the common use of the frontend drivers made by DiBcom
- * DiBcom 3000-MB/MC/P
+ * DiBcom 3000M-B/C, 3000P
*
* DiBcom (http://www.dibcom.fr/)
*
@@ -30,9 +30,9 @@
#include "dib3000.h"
/* info and err, taken from usb.h, if there is anything available like by default. */
-#define err(format, arg...) printk(KERN_ERR "dib3000mX: " format "\n" , ## arg)
-#define info(format, arg...) printk(KERN_INFO "dib3000mX: " format "\n" , ## arg)
-#define warn(format, arg...) printk(KERN_WARNING "dib3000mX: " format "\n" , ## arg)
+#define err(format, arg...) printk(KERN_ERR "dib3000: " format "\n" , ## arg)
+#define info(format, arg...) printk(KERN_INFO "dib3000: " format "\n" , ## arg)
+#define warn(format, arg...) printk(KERN_WARNING "dib3000: " format "\n" , ## arg)
/* frontend state */
struct dib3000_state {
diff --git a/drivers/media/dvb/frontends/dib3000.h b/drivers/media/dvb/frontends/dib3000.h
index a2525e478f629..80687c130836f 100644
--- a/drivers/media/dvb/frontends/dib3000.h
+++ b/drivers/media/dvb/frontends/dib3000.h
@@ -1,6 +1,6 @@
/*
* public header file of the frontend drivers for mobile DVB-T demodulators
- * DiBcom 3000-MB and DiBcom 3000-MC/P (http://www.dibcom.fr/)
+ * DiBcom 3000M-B and DiBcom 3000P/M-C (http://www.dibcom.fr/)
*
* Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
*
diff --git a/drivers/media/dvb/frontends/dib3000mb.c b/drivers/media/dvb/frontends/dib3000mb.c
index 041349789c312..a853d12a26f1e 100644
--- a/drivers/media/dvb/frontends/dib3000mb.c
+++ b/drivers/media/dvb/frontends/dib3000mb.c
@@ -1,5 +1,5 @@
/*
- * Frontend driver for mobile DVB-T demodulator DiBcom 3000-MB
+ * Frontend driver for mobile DVB-T demodulator DiBcom 3000M-B
* DiBcom (http://www.dibcom.fr/)
*
* Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
@@ -35,7 +35,7 @@
/* Version information */
#define DRIVER_VERSION "0.1"
-#define DRIVER_DESC "DiBcom 3000-MB DVB-T demodulator driver"
+#define DRIVER_DESC "DiBcom 3000M-B DVB-T demodulator"
#define DRIVER_AUTHOR "Patrick Boettcher, patrick.boettcher@desy.de"
#ifdef CONFIG_DVB_DIBCOM_DEBUG
@@ -54,12 +54,12 @@ static int dib3000mb_get_frontend(struct dvb_frontend* fe,
struct dvb_frontend_parameters *fep);
static int dib3000mb_set_frontend(struct dvb_frontend* fe,
- struct dvb_frontend_parameters *fep, int tuner)
+ struct dvb_frontend_parameters *fep, int tuner)
{
struct dib3000_state* state = (struct dib3000_state*) fe->demodulator_priv;
struct dvb_ofdm_parameters *ofdm = &fep->u.ofdm;
fe_code_rate_t fe_cr = FEC_NONE;
- int search_state,seq;
+ int search_state, seq;
if (tuner) {
dib3000mb_tuner_pass_ctrl(fe,1,state->config.pll_addr(fe));
@@ -70,18 +70,18 @@ static int dib3000mb_set_frontend(struct dvb_frontend* fe,
switch (ofdm->bandwidth) {
case BANDWIDTH_8_MHZ:
deb_setf("8 MHz\n");
- wr_foreach(dib3000mb_reg_timing_freq,dib3000mb_timing_freq[2]);
- wr_foreach(dib3000mb_reg_bandwidth,dib3000mb_bandwidth_8mhz);
+ wr_foreach(dib3000mb_reg_timing_freq, dib3000mb_timing_freq[2]);
+ wr_foreach(dib3000mb_reg_bandwidth, dib3000mb_bandwidth_8mhz);
break;
case BANDWIDTH_7_MHZ:
deb_setf("7 MHz\n");
- wr_foreach(dib3000mb_reg_timing_freq,dib3000mb_timing_freq[1]);
- wr_foreach(dib3000mb_reg_bandwidth,dib3000mb_bandwidth_7mhz);
+ wr_foreach(dib3000mb_reg_timing_freq, dib3000mb_timing_freq[1]);
+ wr_foreach(dib3000mb_reg_bandwidth, dib3000mb_bandwidth_7mhz);
break;
case BANDWIDTH_6_MHZ:
deb_setf("6 MHz\n");
- wr_foreach(dib3000mb_reg_timing_freq,dib3000mb_timing_freq[0]);
- wr_foreach(dib3000mb_reg_bandwidth,dib3000mb_bandwidth_6mhz);
+ wr_foreach(dib3000mb_reg_timing_freq, dib3000mb_timing_freq[0]);
+ wr_foreach(dib3000mb_reg_bandwidth, dib3000mb_bandwidth_6mhz);
break;
case BANDWIDTH_AUTO:
return -EOPNOTSUPP;
@@ -90,7 +90,7 @@ static int dib3000mb_set_frontend(struct dvb_frontend* fe,
return -EINVAL;
}
}
- wr(DIB3000MB_REG_LOCK1_MASK,DIB3000MB_LOCK1_SEARCH_4);
+ wr(DIB3000MB_REG_LOCK1_MASK, DIB3000MB_LOCK1_SEARCH_4);
deb_setf("transmission mode: ");
switch (ofdm->transmission_mode) {
@@ -170,25 +170,25 @@ static int dib3000mb_set_frontend(struct dvb_frontend* fe,
default:
return -EINVAL;
}
- deb_setf("hierachy: ");
+ deb_setf("hierachy: ");
switch (ofdm->hierarchy_information) {
case HIERARCHY_NONE:
deb_setf("none ");
/* fall through */
case HIERARCHY_1:
- deb_setf("alpha=1\n");
+ deb_setf("alpha=1\n");
wr(DIB3000MB_REG_VIT_ALPHA, DIB3000_ALPHA_1);
break;
case HIERARCHY_2:
- deb_setf("alpha=2\n");
+ deb_setf("alpha=2\n");
wr(DIB3000MB_REG_VIT_ALPHA, DIB3000_ALPHA_2);
break;
case HIERARCHY_4:
- deb_setf("alpha=4\n");
+ deb_setf("alpha=4\n");
wr(DIB3000MB_REG_VIT_ALPHA, DIB3000_ALPHA_4);
break;
case HIERARCHY_AUTO:
- deb_setf("alpha=auto\n");
+ deb_setf("alpha=auto\n");
break;
default:
return -EINVAL;
@@ -243,39 +243,39 @@ static int dib3000mb_set_frontend(struct dvb_frontend* fe,
[ofdm->guard_interval == GUARD_INTERVAL_AUTO]
[fep->inversion == INVERSION_AUTO];
- deb_setf("seq? %d\n",seq);
+ deb_setf("seq? %d\n", seq);
- wr(DIB3000MB_REG_SEQ,seq);
+ wr(DIB3000MB_REG_SEQ, seq);
- wr(DIB3000MB_REG_ISI,seq ? DIB3000MB_ISI_INHIBIT : DIB3000MB_ISI_ACTIVATE);
+ wr(DIB3000MB_REG_ISI, seq ? DIB3000MB_ISI_INHIBIT : DIB3000MB_ISI_ACTIVATE);
if (ofdm->transmission_mode == TRANSMISSION_MODE_2K) {
if (ofdm->guard_interval == GUARD_INTERVAL_1_8) {
- wr(DIB3000MB_REG_SYNC_IMPROVEMENT,DIB3000MB_SYNC_IMPROVE_2K_1_8);
+ wr(DIB3000MB_REG_SYNC_IMPROVEMENT, DIB3000MB_SYNC_IMPROVE_2K_1_8);
} else {
- wr(DIB3000MB_REG_SYNC_IMPROVEMENT,DIB3000MB_SYNC_IMPROVE_DEFAULT);
+ wr(DIB3000MB_REG_SYNC_IMPROVEMENT, DIB3000MB_SYNC_IMPROVE_DEFAULT);
}
- wr(DIB3000MB_REG_UNK_121,DIB3000MB_UNK_121_2K);
+ wr(DIB3000MB_REG_UNK_121, DIB3000MB_UNK_121_2K);
} else {
- wr(DIB3000MB_REG_UNK_121,DIB3000MB_UNK_121_DEFAULT);
+ wr(DIB3000MB_REG_UNK_121, DIB3000MB_UNK_121_DEFAULT);
}
- wr(DIB3000MB_REG_MOBILE_ALGO,DIB3000MB_MOBILE_ALGO_OFF);
- wr(DIB3000MB_REG_MOBILE_MODE_QAM,DIB3000MB_MOBILE_MODE_QAM_OFF);
- wr(DIB3000MB_REG_MOBILE_MODE,DIB3000MB_MOBILE_MODE_OFF);
+ wr(DIB3000MB_REG_MOBILE_ALGO, DIB3000MB_MOBILE_ALGO_OFF);
+ wr(DIB3000MB_REG_MOBILE_MODE_QAM, DIB3000MB_MOBILE_MODE_QAM_OFF);
+ wr(DIB3000MB_REG_MOBILE_MODE, DIB3000MB_MOBILE_MODE_OFF);
- wr_foreach(dib3000mb_reg_agc_bandwidth,dib3000mb_agc_bandwidth_high);
+ wr_foreach(dib3000mb_reg_agc_bandwidth, dib3000mb_agc_bandwidth_high);
- wr(DIB3000MB_REG_ISI,DIB3000MB_ISI_ACTIVATE);
+ wr(DIB3000MB_REG_ISI, DIB3000MB_ISI_ACTIVATE);
- wr(DIB3000MB_REG_RESTART,DIB3000MB_RESTART_AGC+DIB3000MB_RESTART_CTRL);
- wr(DIB3000MB_REG_RESTART,DIB3000MB_RESTART_OFF);
+ wr(DIB3000MB_REG_RESTART, DIB3000MB_RESTART_AGC + DIB3000MB_RESTART_CTRL);
+ wr(DIB3000MB_REG_RESTART, DIB3000MB_RESTART_OFF);
/* wait for AGC lock */
msleep(70);
- wr_foreach(dib3000mb_reg_agc_bandwidth,dib3000mb_agc_bandwidth_low);
+ wr_foreach(dib3000mb_reg_agc_bandwidth, dib3000mb_agc_bandwidth_low);
/* something has to be auto searched */
if (ofdm->constellation == QAM_AUTO ||
@@ -284,12 +284,12 @@ static int dib3000mb_set_frontend(struct dvb_frontend* fe,
fep->inversion == INVERSION_AUTO) {
int as_count=0;
- deb_setf("autosearch enabled.\n");
+ deb_setf("autosearch enabled.\n");
- wr(DIB3000MB_REG_ISI,DIB3000MB_ISI_INHIBIT);
+ wr(DIB3000MB_REG_ISI, DIB3000MB_ISI_INHIBIT);
- wr(DIB3000MB_REG_RESTART,DIB3000MB_RESTART_AUTO_SEARCH);
- wr(DIB3000MB_REG_RESTART,DIB3000MB_RESTART_OFF);
+ wr(DIB3000MB_REG_RESTART, DIB3000MB_RESTART_AUTO_SEARCH);
+ wr(DIB3000MB_REG_RESTART, DIB3000MB_RESTART_OFF);
while ((search_state =
dib3000_search_status(
@@ -297,7 +297,7 @@ static int dib3000mb_set_frontend(struct dvb_frontend* fe,
rd(DIB3000MB_REG_LOCK2_VALUE))) < 0 && as_count++ < 100)
msleep(1);
- deb_info("search_state after autosearch %d after %d checks\n",search_state,as_count);
+ deb_setf("search_state after autosearch %d after %d checks\n",search_state,as_count);
if (search_state == 1) {
struct dvb_frontend_parameters feps;
@@ -308,8 +308,8 @@ static int dib3000mb_set_frontend(struct dvb_frontend* fe,
}
} else {
- wr(DIB3000MB_REG_RESTART,DIB3000MB_RESTART_CTRL);
- wr(DIB3000MB_REG_RESTART,DIB3000MB_RESTART_OFF);
+ wr(DIB3000MB_REG_RESTART, DIB3000MB_RESTART_CTRL);
+ wr(DIB3000MB_REG_RESTART, DIB3000MB_RESTART_OFF);
}
return 0;
@@ -319,74 +319,75 @@ static int dib3000mb_fe_init(struct dvb_frontend* fe, int mobile_mode)
{
struct dib3000_state* state = (struct dib3000_state*) fe->demodulator_priv;
- wr(DIB3000MB_REG_POWER_CONTROL,DIB3000MB_POWER_UP);
+ deb_info("dib3000mb is getting up.\n");
+ wr(DIB3000MB_REG_POWER_CONTROL, DIB3000MB_POWER_UP);
wr(DIB3000MB_REG_RESTART, DIB3000MB_RESTART_AGC);
- wr(DIB3000MB_REG_RESET_DEVICE,DIB3000MB_RESET_DEVICE);
- wr(DIB3000MB_REG_RESET_DEVICE,DIB3000MB_RESET_DEVICE_RST);
+ wr(DIB3000MB_REG_RESET_DEVICE, DIB3000MB_RESET_DEVICE);
+ wr(DIB3000MB_REG_RESET_DEVICE, DIB3000MB_RESET_DEVICE_RST);
- wr(DIB3000MB_REG_CLOCK,DIB3000MB_CLOCK_DEFAULT);
+ wr(DIB3000MB_REG_CLOCK, DIB3000MB_CLOCK_DEFAULT);
- wr(DIB3000MB_REG_ELECT_OUT_MODE,DIB3000MB_ELECT_OUT_MODE_ON);
+ wr(DIB3000MB_REG_ELECT_OUT_MODE, DIB3000MB_ELECT_OUT_MODE_ON);
- wr(DIB3000MB_REG_DDS_FREQ_MSB,DIB3000MB_DDS_FREQ_MSB);
- wr(DIB3000MB_REG_DDS_FREQ_LSB,DIB3000MB_DDS_FREQ_LSB);
+ wr(DIB3000MB_REG_DDS_FREQ_MSB, DIB3000MB_DDS_FREQ_MSB);
+ wr(DIB3000MB_REG_DDS_FREQ_LSB, DIB3000MB_DDS_FREQ_LSB);
- wr_foreach(dib3000mb_reg_timing_freq,dib3000mb_timing_freq[2]);
+ wr_foreach(dib3000mb_reg_timing_freq, dib3000mb_timing_freq[2]);
wr_foreach(dib3000mb_reg_impulse_noise,
dib3000mb_impulse_noise_values[DIB3000MB_IMPNOISE_OFF]);
- wr_foreach(dib3000mb_reg_agc_gain,dib3000mb_default_agc_gain);
+ wr_foreach(dib3000mb_reg_agc_gain, dib3000mb_default_agc_gain);
- wr(DIB3000MB_REG_PHASE_NOISE,DIB3000MB_PHASE_NOISE_DEFAULT);
+ wr(DIB3000MB_REG_PHASE_NOISE, DIB3000MB_PHASE_NOISE_DEFAULT);
wr_foreach(dib3000mb_reg_phase_noise, dib3000mb_default_noise_phase);
- wr_foreach(dib3000mb_reg_lock_duration,dib3000mb_default_lock_duration);
+ wr_foreach(dib3000mb_reg_lock_duration, dib3000mb_default_lock_duration);
- wr_foreach(dib3000mb_reg_agc_bandwidth,dib3000mb_agc_bandwidth_low);
+ wr_foreach(dib3000mb_reg_agc_bandwidth, dib3000mb_agc_bandwidth_low);
- wr(DIB3000MB_REG_LOCK0_MASK,DIB3000MB_LOCK0_DEFAULT);
- wr(DIB3000MB_REG_LOCK1_MASK,DIB3000MB_LOCK1_SEARCH_4);
- wr(DIB3000MB_REG_LOCK2_MASK,DIB3000MB_LOCK2_DEFAULT);
+ wr(DIB3000MB_REG_LOCK0_MASK, DIB3000MB_LOCK0_DEFAULT);
+ wr(DIB3000MB_REG_LOCK1_MASK, DIB3000MB_LOCK1_SEARCH_4);
+ wr(DIB3000MB_REG_LOCK2_MASK, DIB3000MB_LOCK2_DEFAULT);
wr(DIB3000MB_REG_SEQ, dib3000_seq[1][1][1]);
- wr_foreach(dib3000mb_reg_bandwidth,dib3000mb_bandwidth_8mhz);
-
- wr(DIB3000MB_REG_UNK_68,DIB3000MB_UNK_68);
- wr(DIB3000MB_REG_UNK_69,DIB3000MB_UNK_69);
- wr(DIB3000MB_REG_UNK_71,DIB3000MB_UNK_71);
- wr(DIB3000MB_REG_UNK_77,DIB3000MB_UNK_77);
- wr(DIB3000MB_REG_UNK_78,DIB3000MB_UNK_78);
- wr(DIB3000MB_REG_ISI,DIB3000MB_ISI_INHIBIT);
- wr(DIB3000MB_REG_UNK_92,DIB3000MB_UNK_92);
- wr(DIB3000MB_REG_UNK_96,DIB3000MB_UNK_96);
- wr(DIB3000MB_REG_UNK_97,DIB3000MB_UNK_97);
- wr(DIB3000MB_REG_UNK_106,DIB3000MB_UNK_106);
- wr(DIB3000MB_REG_UNK_107,DIB3000MB_UNK_107);
- wr(DIB3000MB_REG_UNK_108,DIB3000MB_UNK_108);
- wr(DIB3000MB_REG_UNK_122,DIB3000MB_UNK_122);
- wr(DIB3000MB_REG_MOBILE_MODE_QAM,DIB3000MB_MOBILE_MODE_QAM_OFF);
- wr(DIB3000MB_REG_BERLEN,DIB3000MB_BERLEN_DEFAULT);
-
- wr_foreach(dib3000mb_reg_filter_coeffs,dib3000mb_filter_coeffs);
-
- wr(DIB3000MB_REG_MOBILE_ALGO,DIB3000MB_MOBILE_ALGO_ON);
- wr(DIB3000MB_REG_MULTI_DEMOD_MSB,DIB3000MB_MULTI_DEMOD_MSB);
- wr(DIB3000MB_REG_MULTI_DEMOD_LSB,DIB3000MB_MULTI_DEMOD_LSB);
-
- wr(DIB3000MB_REG_OUTPUT_MODE,DIB3000MB_OUTPUT_MODE_SLAVE);
-
- wr(DIB3000MB_REG_FIFO_142,DIB3000MB_FIFO_142);
- wr(DIB3000MB_REG_MPEG2_OUT_MODE,DIB3000MB_MPEG2_OUT_MODE_188);
+ wr_foreach(dib3000mb_reg_bandwidth, dib3000mb_bandwidth_8mhz);
+
+ wr(DIB3000MB_REG_UNK_68, DIB3000MB_UNK_68);
+ wr(DIB3000MB_REG_UNK_69, DIB3000MB_UNK_69);
+ wr(DIB3000MB_REG_UNK_71, DIB3000MB_UNK_71);
+ wr(DIB3000MB_REG_UNK_77, DIB3000MB_UNK_77);
+ wr(DIB3000MB_REG_UNK_78, DIB3000MB_UNK_78);
+ wr(DIB3000MB_REG_ISI, DIB3000MB_ISI_INHIBIT);
+ wr(DIB3000MB_REG_UNK_92, DIB3000MB_UNK_92);
+ wr(DIB3000MB_REG_UNK_96, DIB3000MB_UNK_96);
+ wr(DIB3000MB_REG_UNK_97, DIB3000MB_UNK_97);
+ wr(DIB3000MB_REG_UNK_106, DIB3000MB_UNK_106);
+ wr(DIB3000MB_REG_UNK_107, DIB3000MB_UNK_107);
+ wr(DIB3000MB_REG_UNK_108, DIB3000MB_UNK_108);
+ wr(DIB3000MB_REG_UNK_122, DIB3000MB_UNK_122);
+ wr(DIB3000MB_REG_MOBILE_MODE_QAM, DIB3000MB_MOBILE_MODE_QAM_OFF);
+ wr(DIB3000MB_REG_BERLEN, DIB3000MB_BERLEN_DEFAULT);
+
+ wr_foreach(dib3000mb_reg_filter_coeffs, dib3000mb_filter_coeffs);
+
+ wr(DIB3000MB_REG_MOBILE_ALGO, DIB3000MB_MOBILE_ALGO_ON);
+ wr(DIB3000MB_REG_MULTI_DEMOD_MSB, DIB3000MB_MULTI_DEMOD_MSB);
+ wr(DIB3000MB_REG_MULTI_DEMOD_LSB, DIB3000MB_MULTI_DEMOD_LSB);
+
+ wr(DIB3000MB_REG_OUTPUT_MODE, DIB3000MB_OUTPUT_MODE_SLAVE);
+
+ wr(DIB3000MB_REG_FIFO_142, DIB3000MB_FIFO_142);
+ wr(DIB3000MB_REG_MPEG2_OUT_MODE, DIB3000MB_MPEG2_OUT_MODE_188);
wr(DIB3000MB_REG_PID_PARSE, DIB3000MB_PID_PARSE_ACTIVATE);
- wr(DIB3000MB_REG_FIFO,DIB3000MB_FIFO_INHIBIT);
- wr(DIB3000MB_REG_FIFO_146,DIB3000MB_FIFO_146);
- wr(DIB3000MB_REG_FIFO_147,DIB3000MB_FIFO_147);
+ wr(DIB3000MB_REG_FIFO, DIB3000MB_FIFO_INHIBIT);
+ wr(DIB3000MB_REG_FIFO_146, DIB3000MB_FIFO_146);
+ wr(DIB3000MB_REG_FIFO_147, DIB3000MB_FIFO_147);
- wr(DIB3000MB_REG_DATA_IN_DIVERSITY,DIB3000MB_DATA_DIVERSITY_IN_OFF);
+ wr(DIB3000MB_REG_DATA_IN_DIVERSITY, DIB3000MB_DATA_DIVERSITY_IN_OFF);
if (state->config.pll_init) {
dib3000mb_tuner_pass_ctrl(fe,1,state->config.pll_addr(fe));
@@ -451,7 +452,7 @@ static int dib3000mb_get_frontend(struct dvb_frontend* fe,
default:
err("Unexpected constellation returned by TPS (%d)", tps_val);
break;
- }
+ }
deb_getf("TPS: %d\n", tps_val);
if (rd(DIB3000MB_REG_TPS_HRCH)) {
@@ -574,16 +575,9 @@ static int dib3000mb_read_status(struct dvb_frontend* fe, fe_status_t *stat)
if (rd(DIB3000MB_REG_TS_SYNC_LOCK))
*stat |= (FE_HAS_SYNC | FE_HAS_LOCK);
- deb_info("actual status is %2x\n",*stat);
+ deb_getf("actual status is %2x\n",*stat);
- deb_getf("tps %x %x %x %x %x\n",
- rd(DIB3000MB_REG_TPS_1),
- rd(DIB3000MB_REG_TPS_2),
- rd(DIB3000MB_REG_TPS_3),
- rd(DIB3000MB_REG_TPS_4),
- rd(DIB3000MB_REG_TPS_5));
-
- deb_info("autoval: tps: %d, qam: %d, hrch: %d, alpha: %d, hp: %d, lp: %d, guard: %d, fft: %d cell: %d\n",
+ deb_getf("autoval: tps: %d, qam: %d, hrch: %d, alpha: %d, hp: %d, lp: %d, guard: %d, fft: %d cell: %d\n",
rd(DIB3000MB_REG_TPS_LOCK),
rd(DIB3000MB_REG_TPS_QAM),
rd(DIB3000MB_REG_TPS_HRCH),
@@ -602,71 +596,25 @@ static int dib3000mb_read_ber(struct dvb_frontend* fe, u32 *ber)
{
struct dib3000_state* state = (struct dib3000_state*) fe->demodulator_priv;
- *ber = ((rd(DIB3000MB_REG_BER_MSB) << 16) | rd(DIB3000MB_REG_BER_LSB) );
+ *ber = ((rd(DIB3000MB_REG_BER_MSB) << 16) | rd(DIB3000MB_REG_BER_LSB));
return 0;
}
-/*
- * Amaury:
- * signal strength is measured with dBm (power compared to mW)
- * the standard range is -90dBm(low power) to -10 dBm (strong power),
- * but the calibration is done for -100 dBm to 0dBm
- */
-#define DIB3000MB_AGC_REF_dBm -14
-#define DIB3000MB_GAIN_SLOPE_dBm 100
-#define DIB3000MB_GAIN_DELTA_dBm -2
+/* see dib3000-watch dvb-apps for exact calcuations of signal_strength and snr */
static int dib3000mb_read_signal_strength(struct dvb_frontend* fe, u16 *strength)
{
struct dib3000_state* state = (struct dib3000_state*) fe->demodulator_priv;
-/* TODO log10
- u16 sigpow = rd(DIB3000MB_REG_SIGNAL_POWER),
- n_agc_power = rd(DIB3000MB_REG_AGC_POWER),
- rf_power = rd(DIB3000MB_REG_RF_POWER);
- double rf_power_dBm, ad_power_dBm, minar_power_dBm;
-
- if (n_agc_power == 0 )
- n_agc_power = 1 ;
-
- ad_power_dBm = 10 * log10 ( (float)n_agc_power / (float)(1<<16) );
- minor_power_dBm = ad_power_dBm - DIB3000MB_AGC_REF_dBm;
- rf_power_dBm = (-DIB3000MB_GAIN_SLOPE_dBm * (float)rf_power / (float)(1<<16) +
- DIB3000MB_GAIN_DELTA_dBm) + minor_power_dBm;
- // relative rf_power
- *strength = (u16) ((rf_power_dBm + 100) / 100 * 0xffff);
-*/
*strength = rd(DIB3000MB_REG_SIGNAL_POWER) * 0xffff / 0x170;
return 0;
}
-/*
- * Amaury:
- * snr is the signal quality measured in dB.
- * snr = 10*log10(signal power / noise power)
- * the best quality is near 35dB (cable transmission & good modulator)
- * the minimum without errors depend of transmission parameters
- * some indicative values are given in en300744 Annex A
- * ex : 16QAM 2/3 (Gaussian) = 11.1 dB
- *
- * If SNR is above 20dB, BER should be always 0.
- * choose 0dB as the minimum
- */
static int dib3000mb_read_snr(struct dvb_frontend* fe, u16 *snr)
{
struct dib3000_state* state = (struct dib3000_state*) fe->demodulator_priv;
short sigpow = rd(DIB3000MB_REG_SIGNAL_POWER);
int icipow = ((rd(DIB3000MB_REG_NOISE_POWER_MSB) & 0xff) << 16) |
rd(DIB3000MB_REG_NOISE_POWER_LSB);
-/*
- float snr_dBm=0;
-
- if (sigpow > 0 && icipow > 0)
- snr_dBm = 10.0 * log10( (float) (sigpow<<8) / (float)icipow ) ;
- else if (sigpow > 0)
- snr_dBm = 35;
-
- *snr = (u16) ((snr_dBm / 35) * 0xffff);
-*/
*snr = (sigpow << 8) / ((icipow > 0) ? icipow : 1);
return 0;
}
@@ -682,8 +630,8 @@ static int dib3000mb_read_unc_blocks(struct dvb_frontend* fe, u32 *unc)
static int dib3000mb_sleep(struct dvb_frontend* fe)
{
struct dib3000_state* state = (struct dib3000_state*) fe->demodulator_priv;
-
- wr(DIB3000MB_REG_POWER_CONTROL,DIB3000MB_POWER_DOWN);
+ deb_info("dib3000mb is going to bed.\n");
+ wr(DIB3000MB_REG_POWER_CONTROL, DIB3000MB_POWER_DOWN);
return 0;
}
@@ -691,8 +639,8 @@ static int dib3000mb_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_fr
{
tune->min_delay_ms = 800;
tune->step_size = 166667;
- tune->max_drift = 166667*2;
-
+ tune->max_drift = 166667 * 2;
+
return 0;
}
@@ -717,7 +665,7 @@ static int dib3000mb_pid_control(struct dvb_frontend *fe,int index, int pid,int
{
struct dib3000_state *state = fe->demodulator_priv;
pid = (onoff ? pid | DIB3000_ACTIVATE_PID_FILTERING : 0);
- wr(index+DIB3000MB_REG_FIRST_PID,pid);
+ wr(index+DIB3000MB_REG_FIRST_PID,pid);
return 0;
}
@@ -732,14 +680,15 @@ static int dib3000mb_fifo_control(struct dvb_frontend *fe, int onoff)
wr(DIB3000MB_REG_FIFO, DIB3000MB_FIFO_INHIBIT);
}
return 0;
- }
+}
static int dib3000mb_pid_parse(struct dvb_frontend *fe, int onoff)
{
- //struct dib3000_state *state = fe->demodulator_priv;
- /* switch it off and on */
+ struct dib3000_state *state = fe->demodulator_priv;
+ deb_xfer("%s pid parsing\n",onoff ? "enabling" : "disabling");
+ wr(DIB3000MB_REG_PID_PARSE,onoff);
return 0;
- }
+}
static int dib3000mb_tuner_pass_ctrl(struct dvb_frontend *fe, int onoff, u8 pll_addr)
{
@@ -763,6 +712,7 @@ struct dvb_frontend* dib3000mb_attach(const struct dib3000_config* config,
state = (struct dib3000_state*) kmalloc(sizeof(struct dib3000_state), GFP_KERNEL);
if (state == NULL)
goto error;
+ memset(state,0,sizeof(struct dib3000_state));
/* setup the state */
state->i2c = i2c;
@@ -789,18 +739,17 @@ struct dvb_frontend* dib3000mb_attach(const struct dib3000_config* config,
return &state->frontend;
error:
- if (state)
kfree(state);
return NULL;
- }
+}
static struct dvb_frontend_ops dib3000mb_ops = {
.info = {
- .name = "DiBcom 3000-MB DVB-T",
- .type = FE_OFDM,
- .frequency_min = 44250000,
- .frequency_max = 867250000,
+ .name = "DiBcom 3000M-B DVB-T",
+ .type = FE_OFDM,
+ .frequency_min = 44250000,
+ .frequency_max = 867250000,
.frequency_stepsize = 62500,
.caps = FE_CAN_INVERSION_AUTO |
FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
diff --git a/drivers/media/dvb/frontends/dib3000mc.c b/drivers/media/dvb/frontends/dib3000mc.c
index 26e640cd43c30..4a31c05eaecd1 100644
--- a/drivers/media/dvb/frontends/dib3000mc.c
+++ b/drivers/media/dvb/frontends/dib3000mc.c
@@ -1,5 +1,5 @@
/*
- * Frontend driver for mobile DVB-T demodulator DiBcom 3000-MC/P
+ * Frontend driver for mobile DVB-T demodulator DiBcom 3000P/M-C
* DiBcom (http://www.dibcom.fr/)
*
* Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
@@ -34,7 +34,7 @@
/* Version information */
#define DRIVER_VERSION "0.1"
-#define DRIVER_DESC "DiBcom 3000-MC DVB-T demodulator driver"
+#define DRIVER_DESC "DiBcom 3000M-C DVB-T demodulator"
#define DRIVER_AUTHOR "Patrick Boettcher, patrick.boettcher@desy.de"
#ifdef CONFIG_DVB_DIBCOM_DEBUG
@@ -189,13 +189,13 @@ static int dib3000mc_init_auto_scan(struct dib3000_state *state, fe_bandwidth_t
static int dib3000mc_set_adp_cfg(struct dib3000_state *state, fe_modulation_t con)
{
switch (con) {
- case QAM_64:
+ case QAM_64:
wr_foreach(dib3000mc_reg_adp_cfg,dib3000mc_adp_cfg[2]);
break;
- case QAM_16:
+ case QAM_16:
wr_foreach(dib3000mc_reg_adp_cfg,dib3000mc_adp_cfg[1]);
break;
- case QPSK:
+ case QPSK:
wr_foreach(dib3000mc_reg_adp_cfg,dib3000mc_adp_cfg[0]);
break;
case QAM_AUTO:
@@ -223,13 +223,13 @@ static int dib3000mc_set_general_cfg(struct dib3000_state *state, struct dvb_fro
switch (ofdm->guard_interval) {
case GUARD_INTERVAL_1_32: guard = DIB3000_GUARD_TIME_1_32; break;
case GUARD_INTERVAL_1_16: guard = DIB3000_GUARD_TIME_1_16; break;
- case GUARD_INTERVAL_1_8: guard = DIB3000_GUARD_TIME_1_8; break;
- case GUARD_INTERVAL_1_4: guard = DIB3000_GUARD_TIME_1_4; break;
+ case GUARD_INTERVAL_1_8: guard = DIB3000_GUARD_TIME_1_8; break;
+ case GUARD_INTERVAL_1_4: guard = DIB3000_GUARD_TIME_1_4; break;
case GUARD_INTERVAL_AUTO: break;
default: return -EINVAL;
}
switch (ofdm->constellation) {
- case QPSK: qam = DIB3000_CONSTELLATION_QPSK; break;
+ case QPSK: qam = DIB3000_CONSTELLATION_QPSK; break;
case QAM_16: qam = DIB3000_CONSTELLATION_16QAM; break;
case QAM_64: qam = DIB3000_CONSTELLATION_64QAM; break;
case QAM_AUTO: break;
@@ -244,13 +244,13 @@ static int dib3000mc_set_general_cfg(struct dib3000_state *state, struct dvb_fro
default: return -EINVAL;
}
if (ofdm->hierarchy_information == HIERARCHY_NONE) {
- hrch = DIB3000_HRCH_OFF;
+ hrch = DIB3000_HRCH_OFF;
sel_hp = DIB3000_SELECT_HP;
- fe_cr = ofdm->code_rate_HP;
+ fe_cr = ofdm->code_rate_HP;
} else if (ofdm->hierarchy_information != HIERARCHY_AUTO) {
- hrch = DIB3000_HRCH_ON;
+ hrch = DIB3000_HRCH_ON;
sel_hp = DIB3000_SELECT_LP;
- fe_cr = ofdm->code_rate_LP;
+ fe_cr = ofdm->code_rate_LP;
}
switch (fe_cr) {
case FEC_1_2: cr = DIB3000_FEC_1_2; break;
@@ -286,10 +286,10 @@ static int dib3000mc_set_general_cfg(struct dib3000_state *state, struct dvb_fro
deb_setf("seq? %d\n", seq);
wr(DIB3000MC_REG_SEQ_TPS,DIB3000MC_SEQ_TPS(seq,1));
*auto_val = ofdm->constellation == QAM_AUTO ||
- ofdm->hierarchy_information == HIERARCHY_AUTO ||
- ofdm->guard_interval == GUARD_INTERVAL_AUTO ||
- ofdm->transmission_mode == TRANSMISSION_MODE_AUTO ||
- fe_cr == FEC_AUTO ||
+ ofdm->hierarchy_information == HIERARCHY_AUTO ||
+ ofdm->guard_interval == GUARD_INTERVAL_AUTO ||
+ ofdm->transmission_mode == TRANSMISSION_MODE_AUTO ||
+ fe_cr == FEC_AUTO ||
fep->inversion == INVERSION_AUTO;
return 0;
}
@@ -334,7 +334,7 @@ static int dib3000mc_get_frontend(struct dvb_frontend* fe,
fep->frequency = state->last_tuned_freq;
fep->u.ofdm.bandwidth= state->last_tuned_bw;
-
+
tps_val = rd(DIB3000MC_REG_TUNING_PARM);
switch (DIB3000MC_TP_QAM(tps_val)) {
@@ -353,7 +353,7 @@ static int dib3000mc_get_frontend(struct dvb_frontend* fe,
default:
err("Unexpected constellation returned by TPS (%d)", tps_val);
break;
- }
+ }
if (DIB3000MC_TP_HRCH(tps_val)) {
deb_getf("HRCH ON ");
@@ -462,12 +462,12 @@ static int dib3000mc_set_frontend(struct dvb_frontend* fe,
struct dvb_ofdm_parameters *ofdm = &fep->u.ofdm;
int search_state,auto_val;
u16 val;
-
+
if (tuner) { /* initial call from dvb */
dib3000mc_tuner_pass_ctrl(fe,1,state->config.pll_addr(fe));
state->config.pll_set(fe,fep,NULL);
dib3000mc_tuner_pass_ctrl(fe,0,state->config.pll_addr(fe));
-
+
state->last_tuned_freq = fep->frequency;
// if (!scanboost) {
dib3000mc_set_timing(state,0,ofdm->transmission_mode,ofdm->bandwidth);
@@ -477,7 +477,7 @@ static int dib3000mc_set_frontend(struct dvb_frontend* fe,
wr_foreach(dib3000mc_reg_agc_bandwidth,dib3000mc_agc_bandwidth);
wr(DIB3000MC_REG_RESTART,DIB3000MC_RESTART_AGC);
wr(DIB3000MC_REG_RESTART,DIB3000MC_RESTART_OFF);
-
+
/* Default cfg isi offset adp */
wr_foreach(dib3000mc_reg_offset,dib3000mc_offset[0]);
@@ -495,7 +495,7 @@ static int dib3000mc_set_frontend(struct dvb_frontend* fe,
auto_val = 0;
dib3000mc_set_general_cfg(state,fep,&auto_val);
dib3000mc_set_impulse_noise(state,0,ofdm->constellation,ofdm->bandwidth);
-
+
val = rd(DIB3000MC_REG_DEMOD_PARM);
wr(DIB3000MC_REG_DEMOD_PARM,val|DIB3000MC_DEMOD_RST_DEMOD_ON);
wr(DIB3000MC_REG_DEMOD_PARM,val);
@@ -507,17 +507,17 @@ static int dib3000mc_set_frontend(struct dvb_frontend* fe,
int as_count=0;
deb_setf("autosearch enabled.\n");
-
+
val = rd(DIB3000MC_REG_DEMOD_PARM);
wr(DIB3000MC_REG_DEMOD_PARM,val | DIB3000MC_DEMOD_RST_AUTO_SRCH_ON);
wr(DIB3000MC_REG_DEMOD_PARM,val);
while ((search_state = dib3000_search_status(
- rd(DIB3000MC_REG_AS_IRQ),1)) < 0 && as_count++ < 100)
+ rd(DIB3000MC_REG_AS_IRQ),1)) < 0 && as_count++ < 100)
msleep(10);
-
+
deb_info("search_state after autosearch %d after %d checks\n",search_state,as_count);
-
+
if (search_state == 1) {
struct dvb_frontend_parameters feps;
if (dib3000mc_get_frontend(fe, &feps) == 0) {
@@ -529,33 +529,33 @@ static int dib3000mc_set_frontend(struct dvb_frontend* fe,
dib3000mc_set_impulse_noise(state,0,ofdm->transmission_mode,ofdm->bandwidth);
wr(DIB3000MC_REG_ISI,DIB3000MC_ISI_DEFAULT|DIB3000MC_ISI_ACTIVATE);
dib3000mc_set_adp_cfg(state,ofdm->constellation);
-
+
/* set_offset_cfg */
wr_foreach(dib3000mc_reg_offset,
dib3000mc_offset[(ofdm->transmission_mode == TRANSMISSION_MODE_8K)+1]);
}
} else { /* second call, after autosearch (fka: set_WithKnownParams) */
// dib3000mc_set_timing(state,1,ofdm->transmission_mode,ofdm->bandwidth);
-
+
auto_val = 0;
dib3000mc_set_general_cfg(state,fep,&auto_val);
if (auto_val)
deb_info("auto_val is true, even though an auto search was already performed.\n");
dib3000mc_set_impulse_noise(state,0,ofdm->constellation,ofdm->bandwidth);
-
+
val = rd(DIB3000MC_REG_DEMOD_PARM);
wr(DIB3000MC_REG_DEMOD_PARM,val | DIB3000MC_DEMOD_RST_AUTO_SRCH_ON);
wr(DIB3000MC_REG_DEMOD_PARM,val);
-
+
msleep(30);
-
+
wr(DIB3000MC_REG_ISI,DIB3000MC_ISI_DEFAULT|DIB3000MC_ISI_ACTIVATE);
dib3000mc_set_adp_cfg(state,ofdm->constellation);
wr_foreach(dib3000mc_reg_offset,
dib3000mc_offset[(ofdm->transmission_mode == TRANSMISSION_MODE_8K)+1]);
-
-
+
+
}
return 0;
}
@@ -569,26 +569,26 @@ static int dib3000mc_fe_init(struct dvb_frontend* fe, int mobile_mode)
state = fe->demodulator_priv;
state->timing_offset = 0;
state->timing_offset_comp_done = 0;
-
+
wr(DIB3000MC_REG_RESTART,DIB3000MC_RESTART_CONFIG);
wr(DIB3000MC_REG_RESTART,DIB3000MC_RESTART_OFF);
wr(DIB3000MC_REG_CLK_CFG_1,DIB3000MC_CLK_CFG_1_POWER_UP);
wr(DIB3000MC_REG_CLK_CFG_2,DIB3000MC_CLK_CFG_2_PUP_MOBILE);
wr(DIB3000MC_REG_CLK_CFG_3,DIB3000MC_CLK_CFG_3_POWER_UP);
wr(DIB3000MC_REG_CLK_CFG_7,DIB3000MC_CLK_CFG_7_INIT);
-
+
wr(DIB3000MC_REG_RST_UNC,DIB3000MC_RST_UNC_OFF);
wr(DIB3000MC_REG_UNK_19,DIB3000MC_UNK_19);
wr(33,5);
wr(36,81);
- wr(DIB3000MC_REG_UNK_88,DIB3000MC_UNK_88);
-
+ wr(DIB3000MC_REG_UNK_88,DIB3000MC_UNK_88);
+
wr(DIB3000MC_REG_UNK_99,DIB3000MC_UNK_99);
wr(DIB3000MC_REG_UNK_111,DIB3000MC_UNK_111_PH_N_MODE_0); /* phase noise algo off */
/* mobile mode - portable reception */
- wr_foreach(dib3000mc_reg_mobile_mode,dib3000mc_mobile_mode[1]);
+ wr_foreach(dib3000mc_reg_mobile_mode,dib3000mc_mobile_mode[1]);
/* TUNER_PANASONIC_ENV57H12D5: */
wr_foreach(dib3000mc_reg_agc_bandwidth,dib3000mc_agc_bandwidth);
@@ -601,24 +601,24 @@ static int dib3000mc_fe_init(struct dvb_frontend* fe, int mobile_mode)
wr(DIB3000MC_REG_UNK_2,DIB3000MC_UNK_2);
wr(DIB3000MC_REG_UNK_3,DIB3000MC_UNK_3);
wr(DIB3000MC_REG_SEQ_TPS,DIB3000MC_SEQ_TPS_DEFAULT);
-
+
wr_foreach(dib3000mc_reg_bandwidth,dib3000mc_bandwidth_8mhz);
wr_foreach(dib3000mc_reg_bandwidth_general,dib3000mc_bandwidth_general);
-
+
wr(DIB3000MC_REG_UNK_4,DIB3000MC_UNK_4);
wr(DIB3000MC_REG_SET_DDS_FREQ_MSB,DIB3000MC_DDS_FREQ_MSB_INV_OFF);
wr(DIB3000MC_REG_SET_DDS_FREQ_LSB,DIB3000MC_DDS_FREQ_LSB);
- dib3000mc_set_timing(state,0,TRANSMISSION_MODE_8K,BANDWIDTH_8_MHZ);
+ dib3000mc_set_timing(state,0,TRANSMISSION_MODE_8K,BANDWIDTH_8_MHZ);
// wr_foreach(dib3000mc_reg_timing_freq,dib3000mc_timing_freq[3]);
-
+
wr(DIB3000MC_REG_UNK_120,DIB3000MC_UNK_120);
wr(DIB3000MC_REG_UNK_134,DIB3000MC_UNK_134);
wr(DIB3000MC_REG_FEC_CFG,DIB3000MC_FEC_CFG);
-
+
wr(DIB3000MC_REG_DIVERSITY3,DIB3000MC_DIVERSITY3_IN_OFF);
-
+
dib3000mc_set_impulse_noise(state,0,TRANSMISSION_MODE_8K,BANDWIDTH_8_MHZ);
/* output mode control, just the MPEG2_SLAVE */
@@ -634,13 +634,13 @@ static int dib3000mc_fe_init(struct dvb_frontend* fe, int mobile_mode)
rd(DIB3000MC_REG_OUTMODE)));
wr(DIB3000MC_REG_SMO_MODE,
- DIB3000MC_SMO_MODE_DEFAULT |
+ DIB3000MC_SMO_MODE_DEFAULT |
DIB3000MC_SMO_MODE_188);
wr(DIB3000MC_REG_FIFO_THRESHOLD,DIB3000MC_FIFO_THRESHOLD_DEFAULT);
wr(DIB3000MC_REG_ELEC_OUT,DIB3000MC_ELEC_OUT_DIV_OUT_ON);
*/
-
+
/* diversity */
wr(DIB3000MC_REG_DIVERSITY1,DIB3000MC_DIVERSITY1_DEFAULT);
wr(DIB3000MC_REG_DIVERSITY2,DIB3000MC_DIVERSITY2_DEFAULT);
@@ -756,7 +756,7 @@ static int dib3000mc_set_frontend_and_tuner(struct dvb_frontend* fe, struct dvb_
static void dib3000mc_release(struct dvb_frontend* fe)
{
- struct dib3000_state *state = (struct dib3000_state*) fe->demodulator_priv;
+ struct dib3000_state *state = (struct dib3000_state *) fe->demodulator_priv;
kfree(state);
}
@@ -765,7 +765,7 @@ static int dib3000mc_pid_control(struct dvb_frontend *fe,int index, int pid,int
{
struct dib3000_state *state = fe->demodulator_priv;
pid = (onoff ? pid | DIB3000_ACTIVATE_PID_FILTERING : 0);
- wr(index+DIB3000MC_REG_FIRST_PID,pid);
+ wr(index+DIB3000MC_REG_FIRST_PID,pid);
return 0;
}
@@ -773,9 +773,9 @@ static int dib3000mc_fifo_control(struct dvb_frontend *fe, int onoff)
{
struct dib3000_state *state = (struct dib3000_state*) fe->demodulator_priv;
u16 tmp = rd(DIB3000MC_REG_SMO_MODE);
-
+
deb_xfer("%s fifo\n",onoff ? "enabling" : "disabling");
-
+
if (onoff) {
deb_xfer("%d %x\n",tmp & DIB3000MC_SMO_MODE_FIFO_UNFLUSH,tmp & DIB3000MC_SMO_MODE_FIFO_UNFLUSH);
wr(DIB3000MC_REG_SMO_MODE,tmp & DIB3000MC_SMO_MODE_FIFO_UNFLUSH);
@@ -790,14 +790,12 @@ static int dib3000mc_pid_parse(struct dvb_frontend *fe, int onoff)
{
struct dib3000_state *state = fe->demodulator_priv;
u16 tmp = rd(DIB3000MC_REG_SMO_MODE);
-
+
deb_xfer("%s pid parsing\n",onoff ? "enabling" : "disabling");
-
+
if (onoff) {
- deb_xfer("%d %x\n",tmp | DIB3000MC_SMO_MODE_PID_PARSE,tmp | DIB3000MC_SMO_MODE_PID_PARSE);
wr(DIB3000MC_REG_SMO_MODE,tmp | DIB3000MC_SMO_MODE_PID_PARSE);
} else {
- deb_xfer("%d %x\n",tmp & DIB3000MC_SMO_MODE_NO_PID_PARSE,tmp & DIB3000MC_SMO_MODE_NO_PID_PARSE);
wr(DIB3000MC_REG_SMO_MODE,tmp & DIB3000MC_SMO_MODE_NO_PID_PARSE);
}
return 0;
@@ -814,7 +812,7 @@ static int dib3000mc_tuner_pass_ctrl(struct dvb_frontend *fe, int onoff, u8 pll_
return 0;
}
-static int dib3000mc_demod_init(struct dib3000_state *state)
+static int dib3000mc_demod_init(struct dib3000_state *state)
{
u16 default_addr = 0x0a;
/* first init */
@@ -822,13 +820,13 @@ static int dib3000mc_demod_init(struct dib3000_state *state)
deb_info("initializing the demod the first time. Setting demod addr to 0x%x\n",default_addr);
wr(DIB3000MC_REG_ELEC_OUT,DIB3000MC_ELEC_OUT_DIV_OUT_ON);
wr(DIB3000MC_REG_OUTMODE,DIB3000MC_OM_PAR_CONT_CLK);
-
+
wr(DIB3000MC_REG_RST_I2C_ADDR,
DIB3000MC_DEMOD_ADDR(default_addr) |
DIB3000MC_DEMOD_ADDR_ON);
-
+
state->config.demod_address = default_addr;
-
+
wr(DIB3000MC_REG_RST_I2C_ADDR,
DIB3000MC_DEMOD_ADDR(default_addr));
} else
@@ -849,6 +847,7 @@ struct dvb_frontend* dib3000mc_attach(const struct dib3000_config* config,
state = (struct dib3000_state*) kmalloc(sizeof(struct dib3000_state), GFP_KERNEL);
if (state == NULL)
goto error;
+ memset(state,0,sizeof(struct dib3000_state));
/* setup the state */
state->i2c = i2c;
@@ -865,10 +864,10 @@ struct dvb_frontend* dib3000mc_attach(const struct dib3000_config* config,
switch (devid) {
case DIB3000MC_DEVICE_ID:
- info("Found a DiBcom 3000-MC, interesting...");
+ info("Found a DiBcom 3000M-C, interesting...");
break;
case DIB3000P_DEVICE_ID:
- info("Found a DiBcom 3000-P.");
+ info("Found a DiBcom 3000P.");
break;
}
@@ -887,18 +886,17 @@ struct dvb_frontend* dib3000mc_attach(const struct dib3000_config* config,
return &state->frontend;
error:
- if (state)
- kfree(state);
+ kfree(state);
return NULL;
}
static struct dvb_frontend_ops dib3000mc_ops = {
.info = {
- .name = "DiBcom 3000-MC/P DVB-T",
- .type = FE_OFDM,
- .frequency_min = 44250000,
- .frequency_max = 867250000,
+ .name = "DiBcom 3000P/M-C DVB-T",
+ .type = FE_OFDM,
+ .frequency_min = 44250000,
+ .frequency_max = 867250000,
.frequency_stepsize = 62500,
.caps = FE_CAN_INVERSION_AUTO |
FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
diff --git a/drivers/media/dvb/frontends/dib3000mc_priv.h b/drivers/media/dvb/frontends/dib3000mc_priv.h
index 569e521e81ff7..2930aac7591b7 100644
--- a/drivers/media/dvb/frontends/dib3000mc_priv.h
+++ b/drivers/media/dvb/frontends/dib3000mc_priv.h
@@ -187,7 +187,7 @@ static u16 dib3000mc_reg_agc_bandwidth_general[] = { 50,51,52,53,54 };
static u16 dib3000mc_agc_bandwidth_general[] =
{ 0x8000, 0x91ca, 0x01ba, 0x0087, 0x0087 };
-#define DIB3000MC_REG_IMP_NOISE_55 ( 55)
+#define DIB3000MC_REG_IMP_NOISE_55 ( 55)
#define DIB3000MC_IMP_NEW_ALGO(w) (w | (1<<10))
/* Impulse noise params */
@@ -209,14 +209,14 @@ static u16 dib3000mc_fft_modes[][29] = {
{ 0x38, 0x6d9, 0x3f28, 0x7a7, 0x3a74, 0x196, 0x32a, 0x48c,
0x3ffe, 0x7f3, 0x2d94, 0x76, 0x53d,
0x3ff8, 0x7e3, 0x3320, 0x76, 0x5b3,
- 0x3feb, 0x7d2, 0x365e, 0x76, 0x48c,
- 0x3ffe, 0x5b3, 0x3feb, 0x76, 0x0, 0xd
+ 0x3feb, 0x7d2, 0x365e, 0x76, 0x48c,
+ 0x3ffe, 0x5b3, 0x3feb, 0x76, 0x0, 0xd
}, /* fft mode 0 */
{ 0x3b, 0x6d9, 0x3f28, 0x7a7, 0x3a74, 0x196, 0x32a, 0x48c,
0x3ffe, 0x7f3, 0x2d94, 0x76, 0x53d,
0x3ff8, 0x7e3, 0x3320, 0x76, 0x5b3,
- 0x3feb, 0x7d2, 0x365e, 0x76, 0x48c,
- 0x3ffe, 0x5b3, 0x3feb, 0x0, 0x8200, 0xd
+ 0x3feb, 0x7d2, 0x365e, 0x76, 0x48c,
+ 0x3ffe, 0x5b3, 0x3feb, 0x0, 0x8200, 0xd
}, /* fft mode 1 */
};
@@ -299,7 +299,7 @@ static u16 dib3000mc_mobile_mode[][5] = {
* |||| +---- fifo_ctrl (1 = inhibit (flushed), 0 = active (unflushed))
* |||+------ pid_parse (1 = enabled, 0 = disabled)
* ||+------- outp_188 (1 = TS packet size 188, 0 = packet size 204)
- * |+-------- unk
+ * |+-------- unk
* +--------- unk
*/
@@ -320,7 +320,7 @@ static u16 dib3000mc_mobile_mode[][5] = {
* pidfilter
* it is not a hardware pidfilter but a filter which drops all pids
* except the ones set. When connected to USB1.1 bandwidth this is important.
- * DiB3000-MC/P can filter up to 32 PIDs
+ * DiB3000P/M-C can filter up to 32 PIDs
*/
#define DIB3000MC_REG_FIRST_PID ( 212)
#define DIB3000MC_NUM_PIDS ( 32)
diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c
new file mode 100644
index 0000000000000..2a3c2ce7b2aa8
--- /dev/null
+++ b/drivers/media/dvb/frontends/dvb-pll.c
@@ -0,0 +1,168 @@
+/*
+ * $Id: dvb-pll.c,v 1.7 2005/02/10 11:52:02 kraxel Exp $
+ *
+ * descriptions + helper functions for simple dvb plls.
+ *
+ * (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/dvb/frontend.h>
+#include <asm/types.h>
+
+#include "dvb-pll.h"
+
+/* ----------------------------------------------------------- */
+/* descriptions */
+
+struct dvb_pll_desc dvb_pll_thomson_dtt7579 = {
+ .name = "Thomson dtt7579",
+ .min = 177000000,
+ .max = 858000000,
+ .count = 5,
+ .entries = {
+ { 0, 36166667, 166666, 0xb4, 0x03 }, /* go sleep */
+ { 443250000, 36166667, 166666, 0xb4, 0x02 },
+ { 542000000, 36166667, 166666, 0xb4, 0x08 },
+ { 771000000, 36166667, 166666, 0xbc, 0x08 },
+ { 999999999, 36166667, 166666, 0xf4, 0x08 },
+ },
+};
+EXPORT_SYMBOL(dvb_pll_thomson_dtt7579);
+
+struct dvb_pll_desc dvb_pll_thomson_dtt7610 = {
+ .name = "Thomson dtt7610",
+ .min = 44000000,
+ .max = 958000000,
+ .count = 3,
+ .entries = {
+ { 157250000, 44000000, 62500, 0x8e, 0x39 },
+ { 454000000, 44000000, 62500, 0x8e, 0x3a },
+ { 999999999, 44000000, 62500, 0x8e, 0x3c },
+ },
+};
+EXPORT_SYMBOL(dvb_pll_thomson_dtt7610);
+
+static void thomson_dtt759x_bw(u8 *buf, int bandwidth)
+{
+ if (BANDWIDTH_7_MHZ == bandwidth)
+ buf[3] |= 0x10;
+}
+
+struct dvb_pll_desc dvb_pll_thomson_dtt759x = {
+ .name = "Thomson dtt759x",
+ .min = 177000000,
+ .max = 896000000,
+ .setbw = thomson_dtt759x_bw,
+ .count = 6,
+ .entries = {
+ { 0, 36166667, 166666, 0x84, 0x03 },
+ { 264000000, 36166667, 166666, 0xb4, 0x02 },
+ { 470000000, 36166667, 166666, 0xbc, 0x02 },
+ { 735000000, 36166667, 166666, 0xbc, 0x08 },
+ { 835000000, 36166667, 166666, 0xf4, 0x08 },
+ { 999999999, 36166667, 166666, 0xfc, 0x08 },
+ },
+};
+EXPORT_SYMBOL(dvb_pll_thomson_dtt759x);
+
+struct dvb_pll_desc dvb_pll_lg_z201 = {
+ .name = "LG z201",
+ .min = 174000000,
+ .max = 862000000,
+ .count = 5,
+ .entries = {
+ { 0, 36166667, 166666, 0xbc, 0x03 },
+ { 443250000, 36166667, 166666, 0xbc, 0x01 },
+ { 542000000, 36166667, 166666, 0xbc, 0x02 },
+ { 830000000, 36166667, 166666, 0xf4, 0x02 },
+ { 999999999, 36166667, 166666, 0xfc, 0x02 },
+ },
+};
+EXPORT_SYMBOL(dvb_pll_lg_z201);
+
+struct dvb_pll_desc dvb_pll_unknown_1 = {
+ .name = "unknown 1", /* used by dntv live dvb-t */
+ .min = 174000000,
+ .max = 862000000,
+ .count = 9,
+ .entries = {
+ { 150000000, 36166667, 166666, 0xb4, 0x01 },
+ { 173000000, 36166667, 166666, 0xbc, 0x01 },
+ { 250000000, 36166667, 166666, 0xb4, 0x02 },
+ { 400000000, 36166667, 166666, 0xbc, 0x02 },
+ { 420000000, 36166667, 166666, 0xf4, 0x02 },
+ { 470000000, 36166667, 166666, 0xfc, 0x02 },
+ { 600000000, 36166667, 166666, 0xbc, 0x08 },
+ { 730000000, 36166667, 166666, 0xf4, 0x08 },
+ { 999999999, 36166667, 166666, 0xfc, 0x08 },
+ },
+};
+EXPORT_SYMBOL(dvb_pll_unknown_1);
+
+/* ----------------------------------------------------------- */
+/* code */
+
+static int debug = 0;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "enable verbose debug messages");
+
+int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf,
+ u32 freq, int bandwidth)
+{
+ u32 div;
+ int i;
+
+ if (freq != 0 && (freq < desc->min || freq > desc->max))
+ return -EINVAL;
+
+ for (i = 0; i < desc->count; i++) {
+ if (freq > desc->entries[i].limit)
+ continue;
+ break;
+ }
+ if (debug)
+ printk("pll: %s: freq=%d bw=%d | i=%d/%d\n",
+ desc->name, freq, bandwidth, i, desc->count);
+ BUG_ON(i == desc->count);
+
+ div = (freq + desc->entries[i].offset) / desc->entries[i].stepsize;
+ buf[0] = div >> 8;
+ buf[1] = div & 0xff;
+ buf[2] = desc->entries[i].cb1;
+ buf[3] = desc->entries[i].cb2;
+
+ if (desc->setbw)
+ desc->setbw(buf, bandwidth);
+
+ if (debug)
+ printk("pll: %s: div=%d | buf=0x%02x,0x%02x,0x%02x,0x%02x\n",
+ desc->name, div, buf[0], buf[1], buf[2], buf[3]);
+
+ return 0;
+}
+EXPORT_SYMBOL(dvb_pll_configure);
+
+MODULE_DESCRIPTION("dvb pll library");
+MODULE_AUTHOR("Gerd Knorr");
+MODULE_LICENSE("GPL");
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/dvb/frontends/dvb-pll.h b/drivers/media/dvb/frontends/dvb-pll.h
new file mode 100644
index 0000000000000..016c794a5677f
--- /dev/null
+++ b/drivers/media/dvb/frontends/dvb-pll.h
@@ -0,0 +1,34 @@
+/*
+ * $Id: dvb-pll.h,v 1.2 2005/02/10 11:43:41 kraxel Exp $
+ */
+
+struct dvb_pll_desc {
+ char *name;
+ u32 min;
+ u32 max;
+ void (*setbw)(u8 *buf, int bandwidth);
+ int count;
+ struct {
+ u32 limit;
+ u32 offset;
+ u32 stepsize;
+ u8 cb1;
+ u8 cb2;
+ } entries[9];
+};
+
+extern struct dvb_pll_desc dvb_pll_thomson_dtt7579;
+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_unknown_1;
+
+int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf,
+ u32 freq, int bandwidth);
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * compile-command: "make DVB=1"
+ * End:
+ */
diff --git a/drivers/media/dvb/frontends/dvb_dummy_fe.c b/drivers/media/dvb/frontends/dvb_dummy_fe.c
index b17a19526b4e8..c05a9b05600c2 100644
--- a/drivers/media/dvb/frontends/dvb_dummy_fe.c
+++ b/drivers/media/dvb/frontends/dvb_dummy_fe.c
@@ -1,5 +1,5 @@
-/*
- * Driver for Dummy Frontend
+/*
+ * Driver for Dummy Frontend
*
* Written by Emard <emard@softhome.net>
*
@@ -17,7 +17,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., 675 Mass Ave, Cambridge, MA 02139, USA.=
- */
+ */
#include <linux/module.h>
#include <linux/moduleparam.h>
@@ -27,52 +27,50 @@
#include "dvb_dummy_fe.h"
-
struct dvb_dummy_fe_state {
-
struct dvb_frontend_ops ops;
-
struct dvb_frontend frontend;
};
+
static int dvb_dummy_fe_read_status(struct dvb_frontend* fe, fe_status_t* status)
- {
- *status = FE_HAS_SIGNAL
- | FE_HAS_CARRIER
- | FE_HAS_VITERBI
- | FE_HAS_SYNC
- | FE_HAS_LOCK;
+{
+ *status = FE_HAS_SIGNAL
+ | FE_HAS_CARRIER
+ | FE_HAS_VITERBI
+ | FE_HAS_SYNC
+ | FE_HAS_LOCK;
return 0;
- }
+}
static int dvb_dummy_fe_read_ber(struct dvb_frontend* fe, u32* ber)
- {
- *ber = 0;
+{
+ *ber = 0;
return 0;
- }
+}
static int dvb_dummy_fe_read_signal_strength(struct dvb_frontend* fe, u16* strength)
- {
+{
*strength = 0;
return 0;
- }
+}
static int dvb_dummy_fe_read_snr(struct dvb_frontend* fe, u16* snr)
- {
+{
*snr = 0;
return 0;
- }
+}
static int dvb_dummy_fe_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
{
*ucblocks = 0;
- return 0;
+ return 0;
}
static int dvb_dummy_fe_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
{
- return 0;
+ return 0;
}
static int dvb_dummy_fe_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
@@ -82,18 +80,18 @@ static int dvb_dummy_fe_set_frontend(struct dvb_frontend* fe, struct dvb_fronten
static int dvb_dummy_fe_sleep(struct dvb_frontend* fe)
{
- return 0;
+ return 0;
}
static int dvb_dummy_fe_init(struct dvb_frontend* fe)
{
return 0;
- }
+}
static int dvb_dummy_fe_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
{
- return 0;
-}
+ return 0;
+}
static int dvb_dummy_fe_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
{
@@ -125,7 +123,7 @@ struct dvb_frontend* dvb_dummy_fe_ofdm_attach(void)
return &state->frontend;
error:
- if (state) kfree(state);
+ kfree(state);
return NULL;
}
@@ -179,9 +177,9 @@ static struct dvb_frontend_ops dvb_dummy_fe_ofdm_ops = {
.info = {
.name = "Dummy DVB-T",
- .type = FE_OFDM,
- .frequency_min = 0,
- .frequency_max = 863250000,
+ .type = FE_OFDM,
+ .frequency_min = 0,
+ .frequency_max = 863250000,
.frequency_stepsize = 62500,
.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 |
@@ -211,12 +209,12 @@ static struct dvb_frontend_ops dvb_dummy_fe_qam_ops = {
.info = {
.name = "Dummy DVB-C",
- .type = FE_QAM,
+ .type = FE_QAM,
.frequency_stepsize = 62500,
- .frequency_min = 51000000,
- .frequency_max = 858000000,
- .symbol_rate_min = (57840000/2)/64, /* SACLK/64 == (XIN/2)/64 */
- .symbol_rate_max = (57840000/2)/4, /* SACLK/4 */
+ .frequency_min = 51000000,
+ .frequency_max = 858000000,
+ .symbol_rate_min = (57840000/2)/64, /* SACLK/64 == (XIN/2)/64 */
+ .symbol_rate_max = (57840000/2)/4, /* SACLK/4 */
.caps = FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 |
FE_CAN_QAM_128 | FE_CAN_QAM_256 |
FE_CAN_FEC_AUTO | FE_CAN_INVERSION_AUTO
@@ -240,14 +238,14 @@ static struct dvb_frontend_ops dvb_dummy_fe_qam_ops = {
static struct dvb_frontend_ops dvb_dummy_fe_qpsk_ops = {
.info = {
- .name = "Dummy DVB-S",
- .type = FE_QPSK,
- .frequency_min = 950000,
- .frequency_max = 2150000,
- .frequency_stepsize = 250, /* kHz for QPSK frontends */
- .frequency_tolerance = 29500,
- .symbol_rate_min = 1000000,
- .symbol_rate_max = 45000000,
+ .name = "Dummy DVB-S",
+ .type = FE_QPSK,
+ .frequency_min = 950000,
+ .frequency_max = 2150000,
+ .frequency_stepsize = 250, /* 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 |
@@ -269,7 +267,7 @@ static struct dvb_frontend_ops dvb_dummy_fe_qpsk_ops = {
.read_ucblocks = dvb_dummy_fe_read_ucblocks,
.set_voltage = dvb_dummy_fe_set_voltage,
- .set_tone = dvb_dummy_fe_set_tone,
+ .set_tone = dvb_dummy_fe_set_tone,
};
MODULE_DESCRIPTION("DVB DUMMY Frontend");
diff --git a/drivers/media/dvb/frontends/l64781.c b/drivers/media/dvb/frontends/l64781.c
index af4cb09b03a22..9ac95de9834d5 100644
--- a/drivers/media/dvb/frontends/l64781.c
+++ b/drivers/media/dvb/frontends/l64781.c
@@ -1,9 +1,8 @@
/*
driver for LSI L64781 COFDM demodulator
- Copyright (C) 2001 Holger Waechtler <holger@convergence.de>
- for Convergence Integrated Media GmbH
- Marko Kohtala <marko.kohtala@nokia.com>
+ Copyright (C) 2001 Holger Waechtler for Convergence Integrated Media GmbH
+ Marko Kohtala <marko.kohtala@luukku.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
@@ -32,17 +31,13 @@
struct l64781_state {
-
struct i2c_adapter* i2c;
-
struct dvb_frontend_ops ops;
-
const struct l64781_config* config;
-
struct dvb_frontend frontend;
/* private demodulator data */
- int first:1;
+ int first:1;
};
#define dprintk(args...) \
@@ -544,7 +539,7 @@ struct dvb_frontend* l64781_attach(const struct l64781_config* config,
/* Responds to all reads with 0 */
if (l64781_readreg(state, 0x1a) != 0) {
- dprintk("Read 1 returned unexpcted value\n");
+ dprintk("Read 1 returned unexpcted value\n");
goto error;
}
@@ -553,7 +548,7 @@ struct dvb_frontend* l64781_attach(const struct l64781_config* config,
/* Responds with register default value */
if (l64781_readreg(state, 0x1a) != 0xa1) {
- dprintk("Read 2 returned unexpcted value\n");
+ dprintk("Read 2 returned unexpcted value\n");
goto error;
}
@@ -564,7 +559,7 @@ struct dvb_frontend* l64781_attach(const struct l64781_config* config,
error:
if (reg0x3e >= 0) l64781_writereg (state, 0x3e, reg0x3e); /* restore reg 0x3e */
- if (state) kfree(state);
+ kfree(state);
return NULL;
}
@@ -581,10 +576,10 @@ static struct dvb_frontend_ops l64781_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_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 |
- FE_CAN_MUTE_TS
+ FE_CAN_MUTE_TS
},
- .release = l64781_release,
+ .release = l64781_release,
.init = l64781_init,
.sleep = l64781_sleep,
diff --git a/drivers/media/dvb/frontends/l64781.h b/drivers/media/dvb/frontends/l64781.h
index 259dfffcc8679..7e30fb0fdfa78 100644
--- a/drivers/media/dvb/frontends/l64781.h
+++ b/drivers/media/dvb/frontends/l64781.h
@@ -1,9 +1,8 @@
/*
driver for LSI L64781 COFDM demodulator
- Copyright (C) 2001 Holger Waechtler <holger@convergence.de>
- for Convergence Integrated Media GmbH
- Marko Kohtala <marko.kohtala@nokia.com>
+ Copyright (C) 2001 Holger Waechtler for Convergence Integrated Media GmbH
+ Marko Kohtala <marko.kohtala@luukku.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
diff --git a/drivers/media/dvb/frontends/mt312.c b/drivers/media/dvb/frontends/mt312.c
index a5dcc8766313a..176a22e3441bf 100644
--- a/drivers/media/dvb/frontends/mt312.c
+++ b/drivers/media/dvb/frontends/mt312.c
@@ -1,4 +1,4 @@
-/*
+/*
Driver for Zarlink VP310/MT312 Satellite Channel Decoder
Copyright (C) 2003 Andreas Oberritter <obi@linuxtv.org>
@@ -36,14 +36,10 @@
struct mt312_state {
-
struct i2c_adapter* i2c;
-
struct dvb_frontend_ops ops;
-
/* configuration settings */
const struct mt312_config* config;
-
struct dvb_frontend frontend;
u8 id;
@@ -128,7 +124,7 @@ static int mt312_write(struct mt312_state* state, const enum mt312_reg_addr reg,
}
static inline int mt312_readreg(struct mt312_state* state,
- const enum mt312_reg_addr reg, u8 * val)
+ const enum mt312_reg_addr reg, u8 *val)
{
return mt312_read(state, reg, val, 1);
}
@@ -181,7 +177,7 @@ static int mt312_get_symbol_rate(struct mt312_state* state, u32 *sr)
return ret;
if ((ret = mt312_read(state, MONITOR_H, buf, sizeof(buf))) < 0)
- return ret;
+ return ret;
monitor = (buf[0] << 8) | buf[1];
@@ -206,7 +202,7 @@ static int mt312_get_symbol_rate(struct mt312_state* state, u32 *sr)
dprintk(KERN_DEBUG "*sr(manual) = %lu\n",
(((MT312_PLL_CLK * 8192) / (sym_rat_op + 8192)) *
2) - dec_ratio);
-}
+ }
return 0;
}
@@ -226,21 +222,7 @@ static int mt312_get_code_rate(struct mt312_state* state, fe_code_rate_t *cr)
*cr = fec_tab[(fec_status >> 4) & 0x07];
return 0;
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+}
static int mt312_initfe(struct dvb_frontend* fe)
{
@@ -525,7 +507,7 @@ static int mt312_set_frontend(struct dvb_frontend* fe,
state->frequency = 90;
if ((ret = mt312_initfe(fe)) < 0)
return ret;
- }
+ }
}
else
{
@@ -533,7 +515,7 @@ static int mt312_set_frontend(struct dvb_frontend* fe,
state->frequency = 60;
if ((ret = mt312_initfe(fe)) < 0)
return ret;
- }
+ }
}
break;
@@ -614,12 +596,12 @@ static int mt312_sleep(struct dvb_frontend* fe)
}
static int mt312_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings)
- {
- fesettings->min_delay_ms = 50;
- fesettings->step_size = 0;
- fesettings->max_drift = 0;
- return 0;
- }
+{
+ fesettings->min_delay_ms = 50;
+ fesettings->step_size = 0;
+ fesettings->max_drift = 0;
+ return 0;
+}
static void mt312_release(struct dvb_frontend* fe)
{
@@ -653,14 +635,13 @@ struct dvb_frontend* vp310_attach(const struct mt312_config* config,
}
/* create dvb_frontend */
- state->frequency = 90;
+ state->frequency = 90;
state->frontend.ops = &state->ops;
state->frontend.demodulator_priv = state;
return &state->frontend;
error:
- if (state)
- kfree(state);
+ kfree(state);
return NULL;
}
@@ -685,7 +666,7 @@ struct dvb_frontend* mt312_attach(const struct mt312_config* config,
goto error;
if (state->id != ID_MT312) {
goto error;
-}
+ }
/* create dvb_frontend */
state->frequency = 60;
@@ -716,7 +697,7 @@ static struct dvb_frontend_ops vp310_mt312_ops = {
FE_CAN_RECOVER
},
- .release = mt312_release,
+ .release = mt312_release,
.init = mt312_initfe,
.sleep = mt312_sleep,
diff --git a/drivers/media/dvb/frontends/mt312.h b/drivers/media/dvb/frontends/mt312.h
index 1f58f0c9d110e..b3a53a73a117e 100644
--- a/drivers/media/dvb/frontends/mt312.h
+++ b/drivers/media/dvb/frontends/mt312.h
@@ -1,4 +1,4 @@
-/*
+/*
Driver for Zarlink MT312 Satellite Channel Decoder
Copyright (C) 2003 Andreas Oberritter <obi@linuxtv.org>
diff --git a/drivers/media/dvb/frontends/mt352.c b/drivers/media/dvb/frontends/mt352.c
index 270cb9c9bc99d..50326c7248fa3 100644
--- a/drivers/media/dvb/frontends/mt352.c
+++ b/drivers/media/dvb/frontends/mt352.c
@@ -41,48 +41,45 @@
#include "mt352.h"
struct mt352_state {
-
struct i2c_adapter* i2c;
-
+ struct dvb_frontend frontend;
struct dvb_frontend_ops ops;
/* configuration settings */
const struct mt352_config* config;
-
- struct dvb_frontend frontend;
};
static int debug;
#define dprintk(args...) \
-do { \
+ do { \
if (debug) printk(KERN_DEBUG "mt352: " args); \
-} while (0)
+ } while (0)
static int mt352_single_write(struct dvb_frontend *fe, u8 reg, u8 val)
{
- struct mt352_state* state = (struct mt352_state*) fe->demodulator_priv;
+ struct mt352_state* state = fe->demodulator_priv;
u8 buf[2] = { reg, val };
struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0,
.buf = buf, .len = 2 };
int err = i2c_transfer(state->i2c, &msg, 1);
if (err != 1) {
- dprintk("mt352_write() to reg %x failed (err = %d)!\n", reg, err);
+ printk("mt352_write() to reg %x failed (err = %d)!\n", reg, err);
return err;
-}
- return 0;
+ }
+ return 0;
}
int mt352_write(struct dvb_frontend* fe, u8* ibuf, int ilen)
{
int err,i;
for (i=0; i < ilen-1; i++)
- if ((err = mt352_single_write(fe,ibuf[0]+i,ibuf[i+1])))
+ if ((err = mt352_single_write(fe,ibuf[0]+i,ibuf[i+1])))
return err;
return 0;
}
-static u8 mt352_read_register(struct mt352_state* state, u8 reg)
+static int mt352_read_register(struct mt352_state* state, u8 reg)
{
int ret;
u8 b0 [] = { reg };
@@ -96,41 +93,87 @@ static u8 mt352_read_register(struct mt352_state* state, u8 reg)
ret = i2c_transfer(state->i2c, msg, 2);
- if (ret != 2)
- dprintk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret);
+ if (ret != 2) {
+ printk("%s: readreg error (reg=%d, ret==%i)\n",
+ __FUNCTION__, reg, ret);
+ return ret;
+ }
return b1[0];
}
-u8 mt352_read(struct dvb_frontend *fe, u8 reg)
+int mt352_read(struct dvb_frontend *fe, u8 reg)
{
return mt352_read_register(fe->demodulator_priv,reg);
}
-
-
-
-
-
-
-
static int mt352_sleep(struct dvb_frontend* fe)
{
static u8 mt352_softdown[] = { CLOCK_CTL, 0x20, 0x08 };
mt352_write(fe, mt352_softdown, sizeof(mt352_softdown));
-
return 0;
}
+static void mt352_calc_nominal_rate(struct mt352_state* state,
+ enum fe_bandwidth bandwidth,
+ unsigned char *buf)
+{
+ u32 adc_clock = 20480; /* 20.340 MHz */
+ u32 bw,value;
+
+ switch (bandwidth) {
+ case BANDWIDTH_6_MHZ:
+ bw = 6;
+ break;
+ case BANDWIDTH_7_MHZ:
+ bw = 7;
+ break;
+ case BANDWIDTH_8_MHZ:
+ default:
+ bw = 8;
+ break;
+ }
+ if (state->config->adc_clock)
+ adc_clock = state->config->adc_clock;
+
+ value = 64 * bw * (1<<16) / (7 * 8);
+ value = value * 1000 / adc_clock;
+ dprintk("%s: bw %d, adc_clock %d => 0x%x\n",
+ __FUNCTION__, bw, adc_clock, value);
+ buf[0] = msb(value);
+ buf[1] = lsb(value);
+}
+
+static void mt352_calc_input_freq(struct mt352_state* state,
+ unsigned char *buf)
+{
+ int adc_clock = 20480; /* 20.480000 MHz */
+ int if2 = 36167; /* 36.166667 MHz */
+ int ife,value;
+
+ if (state->config->adc_clock)
+ adc_clock = state->config->adc_clock;
+ if (state->config->if2)
+ if2 = state->config->if2;
+
+ ife = (2*adc_clock - if2);
+ value = -16374 * ife / adc_clock;
+ dprintk("%s: if2 %d, ife %d, adc_clock %d => %d / 0x%x\n",
+ __FUNCTION__, if2, ife, adc_clock, value, value & 0x3fff);
+ buf[0] = msb(value);
+ buf[1] = lsb(value);
+}
+
static int mt352_set_parameters(struct dvb_frontend* fe,
struct dvb_frontend_parameters *param)
{
- struct mt352_state* state = (struct mt352_state*) fe->demodulator_priv;
- unsigned char buf[14];
+ struct mt352_state* state = fe->demodulator_priv;
+ unsigned char buf[13];
+ static unsigned char tuner_go[] = { 0x5d, 0x01 };
+ static unsigned char fsm_go[] = { 0x5e, 0x01 };
unsigned int tps = 0;
struct dvb_ofdm_parameters *op = &param->u.ofdm;
- int i;
switch (op->code_rate_HP) {
case FEC_2_3:
@@ -241,46 +284,28 @@ static int mt352_set_parameters(struct dvb_frontend* fe,
buf[1] = msb(tps); /* TPS_GIVEN_(1|0) */
buf[2] = lsb(tps);
- buf[3] = 0x50;
-
- /**
- * these settings assume 20.48MHz f_ADC, for other tuners you might
- * need other values. See p. 33 in the MT352 Design Manual.
- */
- if (op->bandwidth == BANDWIDTH_8_MHZ) {
- buf[4] = 0x72; /* TRL_NOMINAL_RATE_(1|0) */
- buf[5] = 0x49;
- } else if (op->bandwidth == BANDWIDTH_7_MHZ) {
- buf[4] = 0x64;
- buf[5] = 0x00;
- } else { /* 6MHz */
- buf[4] = 0x55;
- buf[5] = 0xb7;
- }
-
- buf[6] = 0x31; /* INPUT_FREQ_(1|0), 20.48MHz clock, 36.166667MHz IF */
- buf[7] = 0x05; /* see MT352 Design Manual page 32 for details */
+ buf[3] = 0x50; // old
+// buf[3] = 0xf4; // pinnacle
+ mt352_calc_nominal_rate(state, op->bandwidth, buf+4);
+ mt352_calc_input_freq(state, buf+6);
state->config->pll_set(fe, param, buf+8);
- buf[13] = 0x01; /* TUNER_GO!! */
-
- /* Only send the tuning request if the tuner doesn't have the requested
- * parameters already set. Enhances tuning time and prevents stream
- * breakup when retuning the same transponder. */
- for (i = 1; i < 13; i++)
- if (buf[i] != mt352_read_register(state, i + 0x50)) {
- mt352_write(fe, buf, sizeof(buf));
- break;
- }
-
+ mt352_write(fe, buf, sizeof(buf));
+ if (state->config->no_tuner) {
+ /* start decoding */
+ mt352_write(fe, fsm_go, 2);
+ } else {
+ /* start tuning */
+ mt352_write(fe, tuner_go, 2);
+ }
return 0;
}
static int mt352_get_parameters(struct dvb_frontend* fe,
struct dvb_frontend_parameters *param)
{
- struct mt352_state* state = (struct mt352_state*) fe->demodulator_priv;
+ struct mt352_state* state = fe->demodulator_priv;
u16 tps;
u16 div;
u8 trl;
@@ -298,9 +323,7 @@ static int mt352_get_parameters(struct dvb_frontend* fe,
};
if ( (mt352_read_register(state,0x00) & 0xC0) != 0xC0 )
- {
return -EINVAL;
- }
/* Use TPS_RECEIVED-registers, not the TPS_CURRENT-registers because
* the mt352 sometimes works with the wrong parameters
@@ -371,17 +394,11 @@ static int mt352_get_parameters(struct dvb_frontend* fe,
param->frequency = ( 500 * (div - IF_FREQUENCYx6) ) / 3 * 1000;
if (trl == 0x72)
- {
op->bandwidth = BANDWIDTH_8_MHZ;
- }
else if (trl == 0x64)
- {
op->bandwidth = BANDWIDTH_7_MHZ;
- }
else
- {
op->bandwidth = BANDWIDTH_6_MHZ;
- }
if (mt352_read_register(state, STATUS_2) & 0x02)
@@ -394,25 +411,39 @@ static int mt352_get_parameters(struct dvb_frontend* fe,
static int mt352_read_status(struct dvb_frontend* fe, fe_status_t* status)
{
- struct mt352_state* state = (struct mt352_state*) fe->demodulator_priv;
- u8 r;
-
- *status = 0;
- r = mt352_read_register (state, STATUS_0);
- if (r & (1 << 4))
- *status = FE_HAS_CARRIER;
- if (r & (1 << 1))
- *status |= FE_HAS_VITERBI;
- if (r & (1 << 5))
- *status |= FE_HAS_LOCK;
-
- r = mt352_read_register (state, STATUS_1);
- if (r & (1 << 1))
- *status |= FE_HAS_SYNC;
-
- r = mt352_read_register (state, STATUS_3);
- if (r & (1 << 6))
- *status |= FE_HAS_SIGNAL;
+ struct mt352_state* state = fe->demodulator_priv;
+ int s0, s1, s3;
+
+ /* FIXME:
+ *
+ * The MT352 design manual from Zarlink states (page 46-47):
+ *
+ * Notes about the TUNER_GO register:
+ *
+ * If the Read_Tuner_Byte (bit-1) is activated, then the tuner status
+ * byte is copied from the tuner to the STATUS_3 register and
+ * completion of the read operation is indicated by bit-5 of the
+ * INTERRUPT_3 register.
+ */
+
+ if ((s0 = mt352_read_register(state, STATUS_0)) < 0)
+ return -EREMOTEIO;
+ if ((s1 = mt352_read_register(state, STATUS_1)) < 0)
+ return -EREMOTEIO;
+ if ((s3 = mt352_read_register(state, STATUS_3)) < 0)
+ return -EREMOTEIO;
+
+ *status = 0;
+ if (s0 & (1 << 4))
+ *status |= FE_HAS_CARRIER;
+ if (s0 & (1 << 1))
+ *status |= FE_HAS_VITERBI;
+ if (s0 & (1 << 5))
+ *status |= FE_HAS_LOCK;
+ if (s1 & (1 << 1))
+ *status |= FE_HAS_SYNC;
+ if (s3 & (1 << 6))
+ *status |= FE_HAS_SIGNAL;
if ((*status & (FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC)) !=
(FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC))
@@ -423,21 +454,21 @@ static int mt352_read_status(struct dvb_frontend* fe, fe_status_t* status)
static int mt352_read_ber(struct dvb_frontend* fe, u32* ber)
{
- struct mt352_state* state = (struct mt352_state*) fe->demodulator_priv;
+ struct mt352_state* state = fe->demodulator_priv;
*ber = (mt352_read_register (state, RS_ERR_CNT_2) << 16) |
(mt352_read_register (state, RS_ERR_CNT_1) << 8) |
(mt352_read_register (state, RS_ERR_CNT_0));
- return 0;
- }
+ return 0;
+}
static int mt352_read_signal_strength(struct dvb_frontend* fe, u16* strength)
{
- struct mt352_state* state = (struct mt352_state*) fe->demodulator_priv;
+ struct mt352_state* state = fe->demodulator_priv;
- u16 signal = (mt352_read_register (state, AGC_GAIN_3) << 8) |
- (mt352_read_register (state, AGC_GAIN_2));
+ u16 signal = ((mt352_read_register(state, AGC_GAIN_1) << 8) & 0x0f) |
+ (mt352_read_register(state, AGC_GAIN_0));
*strength = ~signal;
return 0;
@@ -445,7 +476,7 @@ static int mt352_read_signal_strength(struct dvb_frontend* fe, u16* strength)
static int mt352_read_snr(struct dvb_frontend* fe, u16* snr)
{
- struct mt352_state* state = (struct mt352_state*) fe->demodulator_priv;
+ struct mt352_state* state = fe->demodulator_priv;
u8 _snr = mt352_read_register (state, SNR);
*snr = (_snr << 8) | _snr;
@@ -455,13 +486,13 @@ static int mt352_read_snr(struct dvb_frontend* fe, u16* snr)
static int mt352_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
{
- struct mt352_state* state = (struct mt352_state*) fe->demodulator_priv;
+ struct mt352_state* state = fe->demodulator_priv;
*ucblocks = (mt352_read_register (state, RS_UBC_1) << 8) |
(mt352_read_register (state, RS_UBC_0));
return 0;
- }
+}
static int mt352_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fe_tune_settings)
{
@@ -470,30 +501,32 @@ static int mt352_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_
fe_tune_settings->max_drift = 0;
return 0;
- }
+}
static int mt352_init(struct dvb_frontend* fe)
{
- struct mt352_state* state = (struct mt352_state*) fe->demodulator_priv;
+ struct mt352_state* state = fe->demodulator_priv;
static u8 mt352_reset_attach [] = { RESET, 0xC0 };
+ dprintk("%s: hello\n",__FUNCTION__);
+
if ((mt352_read_register(state, CLOCK_CTL) & 0x10) == 0 ||
(mt352_read_register(state, CONFIG) & 0x20) == 0) {
- /* Do a "hard" reset */
+ /* Do a "hard" reset */
mt352_write(fe, mt352_reset_attach, sizeof(mt352_reset_attach));
return state->config->demod_init(fe);
}
return 0;
- }
+}
static void mt352_release(struct dvb_frontend* fe)
{
- struct mt352_state* state = (struct mt352_state*) fe->demodulator_priv;
- kfree(state);
- }
+ struct mt352_state* state = fe->demodulator_priv;
+ kfree(state);
+}
static struct dvb_frontend_ops mt352_ops;
@@ -503,8 +536,9 @@ struct dvb_frontend* mt352_attach(const struct mt352_config* config,
struct mt352_state* state = NULL;
/* allocate memory for the internal state */
- state = (struct mt352_state*) kmalloc(sizeof(struct mt352_state), GFP_KERNEL);
+ state = kmalloc(sizeof(struct mt352_state), GFP_KERNEL);
if (state == NULL) goto error;
+ memset(state,0,sizeof(*state));
/* setup the state */
state->config = config;
@@ -520,7 +554,7 @@ struct dvb_frontend* mt352_attach(const struct mt352_config* config,
return &state->frontend;
error:
- if (state) kfree(state);
+ kfree(state);
return NULL;
}
@@ -568,3 +602,9 @@ MODULE_LICENSE("GPL");
EXPORT_SYMBOL(mt352_attach);
EXPORT_SYMBOL(mt352_write);
EXPORT_SYMBOL(mt352_read);
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * compile-command: "make DVB=1"
+ * End:
+ */
diff --git a/drivers/media/dvb/frontends/mt352.h b/drivers/media/dvb/frontends/mt352.h
index 390b6126e4724..f5d8a5aed8a93 100644
--- a/drivers/media/dvb/frontends/mt352.h
+++ b/drivers/media/dvb/frontends/mt352.h
@@ -40,6 +40,13 @@ struct mt352_config
/* the demodulator's i2c address */
u8 demod_address;
+ /* frequencies in kHz */
+ int adc_clock; // default: 20480
+ int if2; // default: 36166
+
+ /* set if no pll is connected to the secondary i2c bus */
+ int no_tuner;
+
/* Initialise the demodulator and PLL. Cannot be NULL */
int (*demod_init)(struct dvb_frontend* fe);
@@ -54,6 +61,12 @@ extern struct dvb_frontend* mt352_attach(const struct mt352_config* config,
struct i2c_adapter* i2c);
extern int mt352_write(struct dvb_frontend* fe, u8* ibuf, int ilen);
-extern u8 mt352_read(struct dvb_frontend *fe, u8 reg);
+extern int mt352_read(struct dvb_frontend *fe, u8 reg);
#endif // MT352_H
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/dvb/frontends/nxt2002.c b/drivers/media/dvb/frontends/nxt2002.c
index a5a3ab9f6ec0a..4743aa17406e0 100644
--- a/drivers/media/dvb/frontends/nxt2002.c
+++ b/drivers/media/dvb/frontends/nxt2002.c
@@ -1,5 +1,5 @@
/*
- Support for B2C2/BBTI Technisat Air2PC - ATSC
+ Support for B2C2/BBTI Technisat Air2PC - ATSC
Copyright (C) 2004 Taylor Jacob <rtjacob@earthlink.net>
@@ -59,7 +59,7 @@ static int i2c_writebytes (struct nxt2002_state* state, u8 reg, u8 *buf, u8 len)
u8 buf2 [256],x;
int err;
struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf2, .len = len + 1 };
-
+
buf2[0] = reg;
for (x = 0 ; x < len ; x++)
buf2[x+1] = buf[x];
@@ -91,12 +91,12 @@ static u8 i2c_readbytes (struct nxt2002_state* state, u8 reg, u8* buf, u8 len)
return 0;
}
-static u16 nxt2002_crc(u16 crc, u8 c)
+static u16 nxt2002_crc(u16 crc, u8 c)
{
u8 i;
u16 input = (u16) c & 0xFF;
-
+
input<<=8;
for(i=0 ;i<8 ;i++) {
if((crc ^ input) & 0x8000)
@@ -130,7 +130,7 @@ static int nxt2002_writereg_multibyte (struct nxt2002_state* state, u8 reg, u8*
if ((buf & 0x02) == 0)
return 0;
-
+
dprintk("Error writing multireg register %02X\n",reg);
return 0;
@@ -162,16 +162,16 @@ static void nxt2002_microcontroller_stop (struct nxt2002_state* state)
buf[0] = 0x80;
i2c_writebytes(state,0x22,buf,1);
- while (counter < 20) {
+ while (counter < 20) {
i2c_readbytes(state,0x31,buf,1);
- if (buf[0] & 0x40)
+ if (buf[0] & 0x40)
return;
msleep(10);
counter++;
}
dprintk("Timeout waiting for micro to stop.. This is ok after firmware upload\n");
- return;
+ return;
}
static void nxt2002_microcontroller_start (struct nxt2002_state* state)
@@ -211,7 +211,7 @@ static int nxt2002_writetuner (struct nxt2002_state* state, u8* data)
/* write UC Opmode to begin transfer */
buf = 0x80;
i2c_writebytes(state,0x21,&buf,1);
-
+
while (count < 20) {
i2c_readbytes(state,0x21,&buf,1);
if ((buf & 0x80)== 0x00)
@@ -243,7 +243,7 @@ static int nxt2002_load_firmware (struct dvb_frontend* fe, const struct firmware
struct nxt2002_state* state = (struct nxt2002_state*) fe->demodulator_priv;
u8 buf[256],written = 0,chunkpos = 0;
- u16 rambase,position,crc = 0;
+ u16 rambase,position,crc = 0;
dprintk("%s\n", __FUNCTION__);
dprintk("Firmware is %zu bytes\n",fw->size);
@@ -251,7 +251,6 @@ static int nxt2002_load_firmware (struct dvb_frontend* fe, const struct firmware
/* Get the RAM base for this nxt2002 */
i2c_readbytes(state,0x10,buf,1);
-
if (buf[0] & 0x10)
rambase = 0x1000;
else
@@ -263,7 +262,6 @@ static int nxt2002_load_firmware (struct dvb_frontend* fe, const struct firmware
buf[0] = 0x80;
i2c_writebytes(state,0x2B,buf,1);
-
for (position = 0; position < fw->size ; position++) {
if (written == 0) {
crc = 0;
@@ -274,7 +272,7 @@ static int nxt2002_load_firmware (struct dvb_frontend* fe, const struct firmware
/* write starting address */
i2c_writebytes(state,0x29,buf,3);
}
- written++;
+ written++;
chunkpos++;
if ((written % 4) == 0)
@@ -282,7 +280,6 @@ static int nxt2002_load_firmware (struct dvb_frontend* fe, const struct firmware
crc = nxt2002_crc(crc,fw->data[position]);
-
if ((written == 255) || (position+1 == fw->size)) {
/* write remaining bytes of firmware */
i2c_writebytes(state, chunkpos+4-(written %4),
@@ -290,7 +287,7 @@ static int nxt2002_load_firmware (struct dvb_frontend* fe, const struct firmware
written %4);
buf[0] = crc << 8;
buf[1] = crc & 0xFF;
-
+
/* write crc */
i2c_writebytes(state,0x2C,buf,2);
@@ -309,24 +306,23 @@ static int nxt2002_load_firmware (struct dvb_frontend* fe, const struct firmware
return 0;
};
-
static int nxt2002_setup_frontend_parameters (struct dvb_frontend* fe,
struct dvb_frontend_parameters *p)
{
struct nxt2002_state* state = (struct nxt2002_state*) fe->demodulator_priv;
u32 freq = 0;
- u16 tunerfreq = 0;
+ u16 tunerfreq = 0;
u8 buf[4];
- freq = 44000 + ( p->frequency / 1000 );
+ freq = 44000 + ( p->frequency / 1000 );
dprintk("freq = %d p->frequency = %d\n",freq,p->frequency);
tunerfreq = freq * 24/4000;
-
+
buf[0] = (tunerfreq >> 8) & 0x7F;
buf[1] = (tunerfreq & 0xFF);
-
+
if (p->frequency <= 214000000) {
buf[2] = 0x84 + (0x06 << 3);
buf[3] = (p->frequency <= 172000000) ? 0x01 : 0x02;
@@ -337,7 +333,7 @@ static int nxt2002_setup_frontend_parameters (struct dvb_frontend* fe,
buf[2] = 0x84 + (0x0E << 3);
buf[3] = 0x08;
} else {
- buf[2] = 0x84 + (0x0F << 3);
+ buf[2] = 0x84 + (0x0F << 3);
buf[3] = 0x02;
}
@@ -347,8 +343,21 @@ static int nxt2002_setup_frontend_parameters (struct dvb_frontend* fe,
/* reset the agc now that tuning has been completed */
nxt2002_agc_reset(state);
+
+
/* set target power level */
- buf[0] = 0x70;
+ switch (p->u.vsb.modulation) {
+ case QAM_64:
+ case QAM_256:
+ buf[0] = 0x74;
+ break;
+ case VSB_8:
+ buf[0] = 0x70;
+ break;
+ default:
+ return -EINVAL;
+ break;
+ }
i2c_writebytes(state,0x42,buf,1);
/* configure sdm */
@@ -361,7 +370,20 @@ static int nxt2002_setup_frontend_parameters (struct dvb_frontend* fe,
nxt2002_writereg_multibyte(state,0x58,buf,2);
/* write sdmx input */
- buf[0] = 0x60;
+ switch (p->u.vsb.modulation) {
+ case QAM_64:
+ buf[0] = 0x68;
+ break;
+ case QAM_256:
+ buf[0] = 0x64;
+ break;
+ case VSB_8:
+ buf[0] = 0x60;
+ break;
+ default:
+ return -EINVAL;
+ break;
+ }
buf[1] = 0x00;
nxt2002_writereg_multibyte(state,0x5C,buf,2);
@@ -391,7 +413,20 @@ static int nxt2002_setup_frontend_parameters (struct dvb_frontend* fe,
i2c_writebytes(state,0x41,buf,1);
/* write agc ucgp0 */
- buf[0] = 0x00;
+ switch (p->u.vsb.modulation) {
+ case QAM_64:
+ buf[0] = 0x02;
+ break;
+ case QAM_256:
+ buf[0] = 0x03;
+ break;
+ case VSB_8:
+ buf[0] = 0x00;
+ break;
+ default:
+ return -EINVAL;
+ break;
+ }
i2c_writebytes(state,0x30,buf,1);
/* write agc control reg */
@@ -410,7 +445,7 @@ static int nxt2002_setup_frontend_parameters (struct dvb_frontend* fe,
nxt2002_microcontroller_start(state);
- /* adjacent channel detection should be done here, but I don't
+ /* adjacent channel detection should be done here, but I don't
have any stations with this need so I cannot test it */
return 0;
@@ -427,7 +462,7 @@ static int nxt2002_read_status(struct dvb_frontend* fe, fe_status_t* status)
*status |= FE_HAS_SIGNAL;
*status |= FE_HAS_CARRIER;
*status |= FE_HAS_VITERBI;
- *status |= FE_HAS_SYNC;
+ *status |= FE_HAS_SYNC;
*status |= FE_HAS_LOCK;
}
return 0;
@@ -438,10 +473,10 @@ static int nxt2002_read_ber(struct dvb_frontend* fe, u32* ber)
struct nxt2002_state* state = (struct nxt2002_state*) fe->demodulator_priv;
u8 b[3];
- nxt2002_readreg_multibyte(state,0xE6,b,3);
+ nxt2002_readreg_multibyte(state,0xE6,b,3);
*ber = ((b[0] << 8) + b[1]) * 8;
-
+
return 0;
}
@@ -456,7 +491,7 @@ static int nxt2002_read_signal_strength(struct dvb_frontend* fe, u16* strength)
i2c_writebytes(state,0xA1,b,1);
/* get multreg val */
- nxt2002_readreg_multibyte(state,0xA6,b,2);
+ nxt2002_readreg_multibyte(state,0xA6,b,2);
temp = (b[0] << 8) | b[1];
*strength = ((0x7FFF - temp) & 0x0FFF) * 16;
@@ -477,7 +512,7 @@ static int nxt2002_read_snr(struct dvb_frontend* fe, u16* snr)
i2c_writebytes(state,0xA1,b,1);
/* get multreg val from 0xA6 */
- nxt2002_readreg_multibyte(state,0xA6,b,2);
+ nxt2002_readreg_multibyte(state,0xA6,b,2);
temp = (b[0] << 8) | b[1];
temp2 = 0x7FFF - temp;
@@ -503,9 +538,8 @@ static int nxt2002_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
{
struct nxt2002_state* state = (struct nxt2002_state*) fe->demodulator_priv;
u8 b[3];
-
- nxt2002_readreg_multibyte(state,0xE6,b,3);
+ nxt2002_readreg_multibyte(state,0xE6,b,3);
*ucblocks = b[2];
return 0;
@@ -525,7 +559,7 @@ static int nxt2002_init(struct dvb_frontend* fe)
if (!state->initialised) {
/* request the firmware, this will block until someone uploads it */
- printk("nxt2002: Waiting for firmware upload...\n");
+ printk("nxt2002: Waiting for firmware upload (%s)...\n", NXT2002_DEFAULT_FIRMWARE);
ret = state->config->request_firmware(fe, &fw, NXT2002_DEFAULT_FIRMWARE);
printk("nxt2002: Waiting for firmware upload(2)...\n");
if (ret) {
@@ -539,10 +573,11 @@ static int nxt2002_init(struct dvb_frontend* fe)
release_firmware(fw);
return ret;
}
+ printk("nxt2002: firmware upload complete\n");
/* Put the micro into reset */
nxt2002_microcontroller_stop(state);
-
+
/* ensure transfer is complete */
buf[0]=0;
i2c_writebytes(state,0x2B,buf,1);
@@ -557,11 +592,11 @@ static int nxt2002_init(struct dvb_frontend* fe)
i2c_writebytes(state,0x08,buf,1);
/* write agc sdm configure */
- buf[0] = 0xF1;
+ buf[0] = 0xF1;
i2c_writebytes(state,0x57,buf,1);
/* write mod output format */
- buf[0] = 0x20;
+ buf[0] = 0x20;
i2c_writebytes(state,0x09,buf,1);
/* write fec mpeg mode */
@@ -614,11 +649,11 @@ struct dvb_frontend* nxt2002_attach(const struct nxt2002_config* config,
/* Check the first 5 registers to ensure this a revision we can handle */
i2c_readbytes(state, 0x00, buf, 5);
- if (buf[0] != 0x04) goto error; /* device id */
- if (buf[1] != 0x02) goto error; /* fab id */
- if (buf[2] != 0x11) goto error; /* month */
- if (buf[3] != 0x20) goto error; /* year msb */
- if (buf[4] != 0x00) goto error; /* year lsb */
+ if (buf[0] != 0x04) goto error; /* device id */
+ if (buf[1] != 0x02) goto error; /* fab id */
+ if (buf[2] != 0x11) goto error; /* month */
+ if (buf[3] != 0x20) goto error; /* year msb */
+ if (buf[4] != 0x00) goto error; /* year lsb */
/* create dvb_frontend */
state->frontend.ops = &state->ops;
@@ -626,7 +661,7 @@ struct dvb_frontend* nxt2002_attach(const struct nxt2002_config* config,
return &state->frontend;
error:
- if (state) kfree(state);
+ kfree(state);
return NULL;
}
@@ -636,12 +671,12 @@ static struct dvb_frontend_ops nxt2002_ops = {
.name = "Nextwave nxt2002 VSB/QAM frontend",
.type = FE_ATSC,
.frequency_min = 54000000,
- .frequency_max = 803000000,
+ .frequency_max = 860000000,
/* stepsize is just a guess */
- .frequency_stepsize = 166666,
+ .frequency_stepsize = 166666,
.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_8VSB
+ FE_CAN_8VSB | FE_CAN_QAM_64 | FE_CAN_QAM_256
},
.release = nxt2002_release,
diff --git a/drivers/media/dvb/frontends/nxt2002.h b/drivers/media/dvb/frontends/nxt2002.h
index a177d5e6bafeb..462301f577ee0 100644
--- a/drivers/media/dvb/frontends/nxt2002.h
+++ b/drivers/media/dvb/frontends/nxt2002.h
@@ -18,6 +18,6 @@ struct nxt2002_config
};
extern struct dvb_frontend* nxt2002_attach(const struct nxt2002_config* config,
- struct i2c_adapter* i2c);
+ struct i2c_adapter* i2c);
#endif // NXT2002_H
diff --git a/drivers/media/dvb/frontends/nxt6000.c b/drivers/media/dvb/frontends/nxt6000.c
index a55fd99a6383a..a41f7da8b8422 100644
--- a/drivers/media/dvb/frontends/nxt6000.c
+++ b/drivers/media/dvb/frontends/nxt6000.c
@@ -1,6 +1,6 @@
-/*
+/*
NxtWave Communications - NXT6000 demodulator driver
-
+
Copyright (C) 2002-2003 Florian Schirmer <jolt@tuxbox.org>
Copyright (C) 2003 Paul Andreassen <paul@andreassen.com.au>
@@ -17,8 +17,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., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
+*/
#include <linux/init.h>
#include <linux/kernel.h>
@@ -33,16 +32,11 @@
struct nxt6000_state {
-
- struct i2c_adapter *i2c;
-
+ struct i2c_adapter* i2c;
struct dvb_frontend_ops ops;
-
/* configuration settings */
const struct nxt6000_config* config;
-
struct dvb_frontend frontend;
-
};
static int debug = 0;
@@ -50,10 +44,10 @@ static int debug = 0;
static int nxt6000_writereg(struct nxt6000_state* state, u8 reg, u8 data)
{
- u8 buf[] = {reg, data};
+ u8 buf[] = { reg, data };
struct i2c_msg msg = {.addr = state->config->demod_address,.flags = 0,.buf = buf,.len = 2 };
int ret;
-
+
if ((ret = i2c_transfer(state->i2c, &msg, 1)) != 1)
dprintk("nxt6000: nxt6000_write error (reg: 0x%02X, data: 0x%02X, ret: %d)\n", reg, data, ret);
@@ -63,18 +57,18 @@ static int nxt6000_writereg(struct nxt6000_state* state, u8 reg, u8 data)
static u8 nxt6000_readreg(struct nxt6000_state* state, u8 reg)
{
int ret;
- u8 b0[] = {reg};
- u8 b1[] = {0};
+ u8 b0[] = { reg };
+ u8 b1[] = { 0 };
struct i2c_msg msgs[] = {
{.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, msgs, 2);
-
+
if (ret != 2)
dprintk("nxt6000: nxt6000_read error (reg: 0x%02X, ret: %d)\n", reg, ret);
-
+
return b1[0];
}
@@ -83,7 +77,7 @@ static void nxt6000_reset(struct nxt6000_state* state)
u8 val;
val = nxt6000_readreg(state, OFDM_COR_CTL);
-
+
nxt6000_writereg(state, OFDM_COR_CTL, val & ~COREACT);
nxt6000_writereg(state, OFDM_COR_CTL, val | COREACT);
}
@@ -93,71 +87,65 @@ static int nxt6000_set_bandwidth(struct nxt6000_state* state, fe_bandwidth_t ban
u16 nominal_rate;
int result;
- switch(bandwidth) {
-
- case BANDWIDTH_6_MHZ:
-
- nominal_rate = 0x55B7;
-
- break;
-
- case BANDWIDTH_7_MHZ:
+ switch (bandwidth) {
- nominal_rate = 0x6400;
-
- break;
+ case BANDWIDTH_6_MHZ:
+ nominal_rate = 0x55B7;
+ break;
- case BANDWIDTH_8_MHZ:
+ case BANDWIDTH_7_MHZ:
+ nominal_rate = 0x6400;
+ break;
- nominal_rate = 0x7249;
-
- break;
+ case BANDWIDTH_8_MHZ:
+ nominal_rate = 0x7249;
+ break;
- default:
- return -EINVAL;
+ default:
+ return -EINVAL;
}
if ((result = nxt6000_writereg(state, OFDM_TRL_NOMINALRATE_1, nominal_rate & 0xFF)) < 0)
return result;
-
+
return nxt6000_writereg(state, OFDM_TRL_NOMINALRATE_2, (nominal_rate >> 8) & 0xFF);
}
static int nxt6000_set_guard_interval(struct nxt6000_state* state, fe_guard_interval_t guard_interval)
{
- switch(guard_interval) {
-
- case GUARD_INTERVAL_1_32:
+ switch (guard_interval) {
+
+ case GUARD_INTERVAL_1_32:
return nxt6000_writereg(state, OFDM_COR_MODEGUARD, 0x00 | (nxt6000_readreg(state, OFDM_COR_MODEGUARD) & ~0x03));
- case GUARD_INTERVAL_1_16:
+ case GUARD_INTERVAL_1_16:
return nxt6000_writereg(state, OFDM_COR_MODEGUARD, 0x01 | (nxt6000_readreg(state, OFDM_COR_MODEGUARD) & ~0x03));
- case GUARD_INTERVAL_AUTO:
- case GUARD_INTERVAL_1_8:
+ case GUARD_INTERVAL_AUTO:
+ case GUARD_INTERVAL_1_8:
return nxt6000_writereg(state, OFDM_COR_MODEGUARD, 0x02 | (nxt6000_readreg(state, OFDM_COR_MODEGUARD) & ~0x03));
- case GUARD_INTERVAL_1_4:
+ case GUARD_INTERVAL_1_4:
return nxt6000_writereg(state, OFDM_COR_MODEGUARD, 0x03 | (nxt6000_readreg(state, OFDM_COR_MODEGUARD) & ~0x03));
-
- default:
- return -EINVAL;
+
+ default:
+ return -EINVAL;
}
}
static int nxt6000_set_inversion(struct nxt6000_state* state, fe_spectral_inversion_t inversion)
{
- switch(inversion) {
-
- case INVERSION_OFF:
+ switch (inversion) {
+
+ case INVERSION_OFF:
return nxt6000_writereg(state, OFDM_ITB_CTL, 0x00);
-
- case INVERSION_ON:
+
+ case INVERSION_ON:
return nxt6000_writereg(state, OFDM_ITB_CTL, ITBINV);
- default:
- return -EINVAL;
-
+ default:
+ return -EINVAL;
+
}
}
@@ -165,31 +153,31 @@ static int nxt6000_set_transmission_mode(struct nxt6000_state* state, fe_transmi
{
int result;
- switch(transmission_mode) {
+ switch (transmission_mode) {
- case TRANSMISSION_MODE_2K:
+ case TRANSMISSION_MODE_2K:
if ((result = nxt6000_writereg(state, EN_DMD_RACQ, 0x00 | (nxt6000_readreg(state, EN_DMD_RACQ) & ~0x03))) < 0)
- return result;
-
+ return result;
+
return nxt6000_writereg(state, OFDM_COR_MODEGUARD, (0x00 << 2) | (nxt6000_readreg(state, OFDM_COR_MODEGUARD) & ~0x04));
- case TRANSMISSION_MODE_8K:
- case TRANSMISSION_MODE_AUTO:
+ case TRANSMISSION_MODE_8K:
+ case TRANSMISSION_MODE_AUTO:
if ((result = nxt6000_writereg(state, EN_DMD_RACQ, 0x02 | (nxt6000_readreg(state, EN_DMD_RACQ) & ~0x03))) < 0)
- return result;
+ return result;
return nxt6000_writereg(state, OFDM_COR_MODEGUARD, (0x01 << 2) | (nxt6000_readreg(state, OFDM_COR_MODEGUARD) & ~0x04));
- default:
- return -EINVAL;
-
+ default:
+ return -EINVAL;
+
}
}
static void nxt6000_setup(struct dvb_frontend* fe)
{
struct nxt6000_state* state = (struct nxt6000_state*) fe->demodulator_priv;
-
+
nxt6000_writereg(state, RS_COR_SYNC_PARAM, SYNC_PARAM);
nxt6000_writereg(state, BER_CTRL, /*(1 << 2) | */ (0x01 << 1) | 0x01);
nxt6000_writereg(state, VIT_COR_CTL, VIT_COR_RESYNC);
@@ -214,7 +202,7 @@ static void nxt6000_setup(struct dvb_frontend* fe)
nxt6000_writereg(state, SUB_DIAG_MODE_SEL, 0);
nxt6000_writereg(state, TS_FORMAT, 0);
-
+
if (state->config->pll_init) {
nxt6000_writereg(state, ENABLE_TUNER_IIC, 0x01); /* open i2c bus switch */
state->config->pll_init(fe);
@@ -241,7 +229,7 @@ static void nxt6000_dump_status(struct nxt6000_state *state)
printk("NXT6000 status:");
val = nxt6000_readreg(state, RS_COR_STAT);
-
+
printk(" DATA DESCR LOCK: %d,", val & 0x01);
printk(" DATA SYNC LOCK: %d,", (val >> 1) & 0x01);
@@ -249,91 +237,73 @@ static void nxt6000_dump_status(struct nxt6000_state *state)
printk(" VITERBI LOCK: %d,", (val >> 7) & 0x01);
- switch((val >> 4) & 0x07) {
-
- case 0x00:
-
- printk(" VITERBI CODERATE: 1/2,");
-
- break;
-
- case 0x01:
-
- printk(" VITERBI CODERATE: 2/3,");
-
- break;
-
- case 0x02:
-
- printk(" VITERBI CODERATE: 3/4,");
-
- break;
-
- case 0x03:
- printk(" VITERBI CODERATE: 5/6,");
- break;
-
- case 0x04:
- printk(" VITERBI CODERATE: 7/8,");
- break;
-
- default:
-
- printk(" VITERBI CODERATE: Reserved,");
-
+ switch ((val >> 4) & 0x07) {
+
+ case 0x00:
+ printk(" VITERBI CODERATE: 1/2,");
+ break;
+
+ case 0x01:
+ printk(" VITERBI CODERATE: 2/3,");
+ break;
+
+ case 0x02:
+ printk(" VITERBI CODERATE: 3/4,");
+ break;
+
+ case 0x03:
+ printk(" VITERBI CODERATE: 5/6,");
+ break;
+
+ case 0x04:
+ printk(" VITERBI CODERATE: 7/8,");
+ break;
+
+ default:
+ printk(" VITERBI CODERATE: Reserved,");
+
}
val = nxt6000_readreg(state, OFDM_COR_STAT);
-
+
printk(" CHCTrack: %d,", (val >> 7) & 0x01);
printk(" TPSLock: %d,", (val >> 6) & 0x01);
printk(" SYRLock: %d,", (val >> 5) & 0x01);
printk(" AGCLock: %d,", (val >> 4) & 0x01);
- switch(val & 0x0F) {
-
- case 0x00:
-
- printk(" CoreState: IDLE,");
-
- break;
-
- case 0x02:
-
- printk(" CoreState: WAIT_AGC,");
-
- break;
-
- case 0x03:
-
- printk(" CoreState: WAIT_SYR,");
-
- break;
-
- case 0x04:
- printk(" CoreState: WAIT_PPM,");
- break;
-
- case 0x01:
- printk(" CoreState: WAIT_TRL,");
- break;
-
- case 0x05:
-
- printk(" CoreState: WAIT_TPS,");
-
- break;
-
- case 0x06:
-
- printk(" CoreState: MONITOR_TPS,");
-
- break;
-
- default:
-
- printk(" CoreState: Reserved,");
-
+ switch (val & 0x0F) {
+
+ case 0x00:
+ printk(" CoreState: IDLE,");
+ break;
+
+ case 0x02:
+ printk(" CoreState: WAIT_AGC,");
+ break;
+
+ case 0x03:
+ printk(" CoreState: WAIT_SYR,");
+ break;
+
+ case 0x04:
+ printk(" CoreState: WAIT_PPM,");
+ break;
+
+ case 0x01:
+ printk(" CoreState: WAIT_TRL,");
+ break;
+
+ case 0x05:
+ printk(" CoreState: WAIT_TPS,");
+ break;
+
+ case 0x06:
+ printk(" CoreState: MONITOR_TPS,");
+ break;
+
+ default:
+ printk(" CoreState: Reserved,");
+
}
val = nxt6000_readreg(state, OFDM_SYR_STAT);
@@ -341,133 +311,105 @@ static void nxt6000_dump_status(struct nxt6000_state *state)
printk(" SYRLock: %d,", (val >> 4) & 0x01);
printk(" SYRMode: %s,", (val >> 2) & 0x01 ? "8K" : "2K");
- switch((val >> 4) & 0x03) {
-
- case 0x00:
-
- printk(" SYRGuard: 1/32,");
-
- break;
-
- case 0x01:
-
- printk(" SYRGuard: 1/16,");
-
- break;
-
- case 0x02:
-
- printk(" SYRGuard: 1/8,");
-
- break;
-
- case 0x03:
- printk(" SYRGuard: 1/4,");
- break;
+ switch ((val >> 4) & 0x03) {
+
+ case 0x00:
+ printk(" SYRGuard: 1/32,");
+ break;
+
+ case 0x01:
+ printk(" SYRGuard: 1/16,");
+ break;
+
+ case 0x02:
+ printk(" SYRGuard: 1/8,");
+ break;
+
+ case 0x03:
+ printk(" SYRGuard: 1/4,");
+ break;
}
val = nxt6000_readreg(state, OFDM_TPS_RCVD_3);
-
- switch((val >> 4) & 0x07) {
-
- case 0x00:
-
- printk(" TPSLP: 1/2,");
-
- break;
-
- case 0x01:
-
- printk(" TPSLP: 2/3,");
-
- break;
-
- case 0x02:
-
- printk(" TPSLP: 3/4,");
-
- break;
-
- case 0x03:
- printk(" TPSLP: 5/6,");
- break;
-
- case 0x04:
- printk(" TPSLP: 7/8,");
- break;
-
- default:
-
- printk(" TPSLP: Reserved,");
-
+
+ switch ((val >> 4) & 0x07) {
+
+ case 0x00:
+ printk(" TPSLP: 1/2,");
+ break;
+
+ case 0x01:
+ printk(" TPSLP: 2/3,");
+ break;
+
+ case 0x02:
+ printk(" TPSLP: 3/4,");
+ break;
+
+ case 0x03:
+ printk(" TPSLP: 5/6,");
+ break;
+
+ case 0x04:
+ printk(" TPSLP: 7/8,");
+ break;
+
+ default:
+ printk(" TPSLP: Reserved,");
+
}
- switch(val & 0x07) {
-
- case 0x00:
-
- printk(" TPSHP: 1/2,");
-
- break;
-
- case 0x01:
-
- printk(" TPSHP: 2/3,");
-
- break;
-
- case 0x02:
-
- printk(" TPSHP: 3/4,");
-
- break;
-
- case 0x03:
- printk(" TPSHP: 5/6,");
- break;
-
- case 0x04:
- printk(" TPSHP: 7/8,");
- break;
-
- default:
-
- printk(" TPSHP: Reserved,");
-
+ switch (val & 0x07) {
+
+ case 0x00:
+ printk(" TPSHP: 1/2,");
+ break;
+
+ case 0x01:
+ printk(" TPSHP: 2/3,");
+ break;
+
+ case 0x02:
+ printk(" TPSHP: 3/4,");
+ break;
+
+ case 0x03:
+ printk(" TPSHP: 5/6,");
+ break;
+
+ case 0x04:
+ printk(" TPSHP: 7/8,");
+ break;
+
+ default:
+ printk(" TPSHP: Reserved,");
+
}
val = nxt6000_readreg(state, OFDM_TPS_RCVD_4);
-
+
printk(" TPSMode: %s,", val & 0x01 ? "8K" : "2K");
-
- switch((val >> 4) & 0x03) {
-
- case 0x00:
-
- printk(" TPSGuard: 1/32,");
-
- break;
-
- case 0x01:
-
- printk(" TPSGuard: 1/16,");
-
- break;
-
- case 0x02:
-
- printk(" TPSGuard: 1/8,");
-
- break;
-
- case 0x03:
-
- printk(" TPSGuard: 1/4,");
-
- break;
-
+
+ switch ((val >> 4) & 0x03) {
+
+ case 0x00:
+ printk(" TPSGuard: 1/32,");
+ break;
+
+ case 0x01:
+ printk(" TPSGuard: 1/16,");
+ break;
+
+ case 0x02:
+ printk(" TPSGuard: 1/8,");
+ break;
+
+ case 0x03:
+ printk(" TPSGuard: 1/4,");
+ break;
+
}
-
+
/* Strange magic required to gain access to RF_AGC_STATUS */
nxt6000_readreg(state, RF_AGC_VAL_1);
val = nxt6000_readreg(state, RF_AGC_STATUS);
@@ -477,87 +419,75 @@ static void nxt6000_dump_status(struct nxt6000_state *state)
printk("\n");
}
-
-
-
-
-
-
-
-
-
-
static int nxt6000_read_status(struct dvb_frontend* fe, fe_status_t* status)
{
- u8 core_status;
+ u8 core_status;
struct nxt6000_state* state = (struct nxt6000_state*) fe->demodulator_priv;
- *status = 0;
-
+ *status = 0;
+
core_status = nxt6000_readreg(state, OFDM_COR_STAT);
- if (core_status & AGCLOCKED)
- *status |= FE_HAS_SIGNAL;
+ if (core_status & AGCLOCKED)
+ *status |= FE_HAS_SIGNAL;
if (nxt6000_readreg(state, OFDM_SYR_STAT) & GI14_SYR_LOCK)
- *status |= FE_HAS_CARRIER;
+ *status |= FE_HAS_CARRIER;
if (nxt6000_readreg(state, VIT_SYNC_STATUS) & VITINSYNC)
- *status |= FE_HAS_VITERBI;
+ *status |= FE_HAS_VITERBI;
if (nxt6000_readreg(state, RS_COR_STAT) & RSCORESTATUS)
- *status |= FE_HAS_SYNC;
-
- if ((core_status & TPSLOCKED) && (*status == (FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC)))
- *status |= FE_HAS_LOCK;
-
- if (debug)
+ *status |= FE_HAS_SYNC;
+
+ if ((core_status & TPSLOCKED) && (*status == (FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC)))
+ *status |= FE_HAS_LOCK;
+
+ if (debug)
nxt6000_dump_status(state);
- return 0;
- }
-
+ return 0;
+}
+
static int nxt6000_init(struct dvb_frontend* fe)
- {
+{
struct nxt6000_state* state = (struct nxt6000_state*) fe->demodulator_priv;
nxt6000_reset(state);
nxt6000_setup(fe);
-
- return 0;
- }
-
+
+ return 0;
+}
static int nxt6000_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *param)
- {
+{
struct nxt6000_state* state = (struct nxt6000_state*) fe->demodulator_priv;
- int result;
+ int result;
nxt6000_writereg(state, ENABLE_TUNER_IIC, 0x01); /* open i2c bus switch */
state->config->pll_set(fe, param);
nxt6000_writereg(state, ENABLE_TUNER_IIC, 0x00); /* close i2c bus switch */
if ((result = nxt6000_set_bandwidth(state, param->u.ofdm.bandwidth)) < 0)
- return result;
+ return result;
if ((result = nxt6000_set_guard_interval(state, param->u.ofdm.guard_interval)) < 0)
- return result;
+ return result;
if ((result = nxt6000_set_transmission_mode(state, param->u.ofdm.transmission_mode)) < 0)
- return result;
+ return result;
if ((result = nxt6000_set_inversion(state, param->inversion)) < 0)
- return result;
+ return result;
return 0;
-}
-
+}
static void nxt6000_release(struct dvb_frontend* fe)
{
struct nxt6000_state* state = (struct nxt6000_state*) fe->demodulator_priv;
kfree(state);
- }
-
+}
+
static struct dvb_frontend_ops nxt6000_ops;
-
+
struct dvb_frontend* nxt6000_attach(const struct nxt6000_config* config,
struct i2c_adapter* i2c)
{
@@ -581,9 +511,9 @@ struct dvb_frontend* nxt6000_attach(const struct nxt6000_config* config,
return &state->frontend;
error:
- if (state) kfree(state);
+ kfree(state);
return NULL;
- }
+}
static struct dvb_frontend_ops nxt6000_ops = {
@@ -608,9 +538,9 @@ static struct dvb_frontend_ops nxt6000_ops = {
.release = nxt6000_release,
.init = nxt6000_init,
-
+
.set_frontend = nxt6000_set_frontend,
-
+
.read_status = nxt6000_read_status,
};
diff --git a/drivers/media/dvb/frontends/or51132.c b/drivers/media/dvb/frontends/or51132.c
new file mode 100644
index 0000000000000..df5dee7760a34
--- /dev/null
+++ b/drivers/media/dvb/frontends/or51132.c
@@ -0,0 +1,628 @@
+/*
+ * Support for OR51132 (pcHDTV HD-3000) - VSB/QAM
+ *
+ * Copyright (C) 2005 Kirk Lapray <kirk_lapray@bigfoot.com>
+ *
+ * Based on code from Jack Kelliher (kelliher@xmission.com)
+ * Copyright (C) 2002 & pcHDTV, inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+*/
+
+/*
+ * This driver needs two external firmware files. Please copy
+ * "dvb-fe-or51132-vsb.fw" and "dvb-fe-or51132-qam.fw" to
+ * /usr/lib/hotplug/firmware/ or /lib/firmware/
+ * (depending on configuration of firmware hotplug).
+ */
+#define OR51132_VSB_FIRMWARE "dvb-fe-or51132-vsb.fw"
+#define OR51132_QAM_FIRMWARE "dvb-fe-or51132-qam.fw"
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <asm/byteorder.h>
+
+#include "dvb_frontend.h"
+#include "dvb-pll.h"
+#include "or51132.h"
+
+static int debug;
+#define dprintk(args...) \
+ do { \
+ if (debug) printk(KERN_DEBUG "or51132: " args); \
+ } while (0)
+
+
+struct or51132_state
+{
+ struct i2c_adapter* i2c;
+ struct dvb_frontend_ops ops;
+
+ /* Configuration settings */
+ const struct or51132_config* config;
+
+ struct dvb_frontend frontend;
+
+ /* Demodulator private data */
+ fe_modulation_t current_modulation;
+
+ /* Tuner private data */
+ u32 current_frequency;
+};
+
+static int i2c_writebytes (struct or51132_state* state, u8 reg, u8 *buf, int len)
+{
+ int err;
+ struct i2c_msg msg;
+ msg.addr = reg;
+ msg.flags = 0;
+ msg.len = len;
+ msg.buf = buf;
+
+ if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
+ printk(KERN_WARNING "or51132: i2c_writebytes error (addr %02x, err == %i)\n", reg, err);
+ return -EREMOTEIO;
+ }
+
+ return 0;
+}
+
+static u8 i2c_readbytes (struct or51132_state* state, u8 reg, u8* buf, int len)
+{
+ int err;
+ struct i2c_msg msg;
+ msg.addr = reg;
+ msg.flags = I2C_M_RD;
+ msg.len = len;
+ msg.buf = buf;
+
+ if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
+ printk(KERN_WARNING "or51132: i2c_readbytes error (addr %02x, err == %i)\n", reg, err);
+ return -EREMOTEIO;
+ }
+
+ return 0;
+}
+
+static int or51132_load_firmware (struct dvb_frontend* fe, const struct firmware *fw)
+{
+ struct or51132_state* state = (struct or51132_state*) fe->demodulator_priv;
+ static u8 run_buf[] = {0x7F,0x01};
+ static u8 get_ver_buf[] = {0x04,0x00,0x30,0x00,0x00};
+ u8 rec_buf[14];
+ u8 cmd_buf[14];
+ u32 firmwareAsize, firmwareBsize;
+ int i,ret;
+
+ dprintk("Firmware is %Zd bytes\n",fw->size);
+
+ /* Get size of firmware A and B */
+ firmwareAsize = le32_to_cpu(*((u32*)fw->data));
+ dprintk("FirmwareA is %i bytes\n",firmwareAsize);
+ firmwareBsize = le32_to_cpu(*((u32*)(fw->data+4)));
+ dprintk("FirmwareB is %i bytes\n",firmwareBsize);
+
+ /* Upload firmware */
+ if ((ret = i2c_writebytes(state,state->config->demod_address,
+ &fw->data[8],firmwareAsize))) {
+ printk(KERN_WARNING "or51132: load_firmware error 1\n");
+ return ret;
+ }
+ msleep(1); /* 1ms */
+ if ((ret = i2c_writebytes(state,state->config->demod_address,
+ &fw->data[8+firmwareAsize],firmwareBsize))) {
+ printk(KERN_WARNING "or51132: load_firmware error 2\n");
+ return ret;
+ }
+ msleep(1); /* 1ms */
+
+ if ((ret = i2c_writebytes(state,state->config->demod_address,
+ run_buf,2))) {
+ printk(KERN_WARNING "or51132: load_firmware error 3\n");
+ return ret;
+ }
+
+ /* Wait at least 5 msec */
+ msleep(20); /* 10ms */
+
+ if ((ret = i2c_writebytes(state,state->config->demod_address,
+ run_buf,2))) {
+ printk(KERN_WARNING "or51132: load_firmware error 4\n");
+ return ret;
+ }
+
+ /* 50ms for operation to begin */
+ msleep(50);
+
+ /* Read back ucode version to besure we loaded correctly and are really up and running */
+ /* Get uCode version */
+ cmd_buf[0] = 0x10;
+ cmd_buf[1] = 0x10;
+ cmd_buf[2] = 0x00;
+ cmd_buf[3] = 0x00;
+ msleep(20); /* 20ms */
+ if ((ret = i2c_writebytes(state,state->config->demod_address,
+ cmd_buf,3))) {
+ printk(KERN_WARNING "or51132: load_firmware error a\n");
+ return ret;
+ }
+
+ cmd_buf[0] = 0x04;
+ cmd_buf[1] = 0x17;
+ cmd_buf[2] = 0x00;
+ cmd_buf[3] = 0x00;
+ msleep(20); /* 20ms */
+ if ((ret = i2c_writebytes(state,state->config->demod_address,
+ cmd_buf,2))) {
+ printk(KERN_WARNING "or51132: load_firmware error b\n");
+ return ret;
+ }
+
+ cmd_buf[0] = 0x00;
+ cmd_buf[1] = 0x00;
+ cmd_buf[2] = 0x00;
+ cmd_buf[3] = 0x00;
+ msleep(20); /* 20ms */
+ if ((ret = i2c_writebytes(state,state->config->demod_address,
+ cmd_buf,2))) {
+ printk(KERN_WARNING "or51132: load_firmware error c\n");
+ return ret;
+ }
+
+ for(i=0;i<4;i++) {
+ msleep(20); /* 20ms */
+ get_ver_buf[4] = i+1;
+ if ((ret = i2c_readbytes(state,state->config->demod_address,
+ &rec_buf[i*2],2))) {
+ printk(KERN_WARNING
+ "or51132: load_firmware error d - %d\n",i);
+ return ret;
+ }
+ }
+
+ printk(KERN_WARNING
+ "or51132: Version: %02X%02X%02X%02X-%02X%02X%02X%02X (%02X%01X-%01X-%02X%01X-%01X)\n",
+ rec_buf[1],rec_buf[0],rec_buf[3],rec_buf[2],
+ rec_buf[5],rec_buf[4],rec_buf[7],rec_buf[6],
+ rec_buf[3],rec_buf[2]>>4,rec_buf[2]&0x0f,
+ rec_buf[5],rec_buf[4]>>4,rec_buf[4]&0x0f);
+
+ cmd_buf[0] = 0x10;
+ cmd_buf[1] = 0x00;
+ cmd_buf[2] = 0x00;
+ cmd_buf[3] = 0x00;
+ msleep(20); /* 20ms */
+ if ((ret = i2c_writebytes(state,state->config->demod_address,
+ cmd_buf,3))) {
+ printk(KERN_WARNING "or51132: load_firmware error e\n");
+ return ret;
+ }
+ return 0;
+};
+
+static int or51132_init(struct dvb_frontend* fe)
+{
+ return 0;
+}
+
+static int or51132_read_ber(struct dvb_frontend* fe, u32* ber)
+{
+ *ber = 0;
+ return 0;
+}
+
+static int or51132_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
+{
+ *ucblocks = 0;
+ return 0;
+}
+
+static int or51132_sleep(struct dvb_frontend* fe)
+{
+ return 0;
+}
+
+static int or51132_setmode(struct dvb_frontend* fe)
+{
+ struct or51132_state* state = (struct or51132_state*) fe->demodulator_priv;
+ unsigned char cmd_buf[4];
+
+ dprintk("setmode %d\n",(int)state->current_modulation);
+ /* set operation mode in Receiver 1 register; */
+ cmd_buf[0] = 0x04;
+ cmd_buf[1] = 0x01;
+ switch (state->current_modulation) {
+ case QAM_256:
+ case QAM_64:
+ case QAM_AUTO:
+ /* Auto-deinterleave; MPEG ser, MPEG2tr, phase noise-high*/
+ cmd_buf[2] = 0x5F;
+ break;
+ case VSB_8:
+ /* Auto CH, Auto NTSC rej, MPEGser, MPEG2tr, phase noise-high*/
+ cmd_buf[2] = 0x50;
+ break;
+ default:
+ printk("setmode:Modulation set to unsupported value\n");
+ };
+ cmd_buf[3] = 0x00;
+ if (i2c_writebytes(state,state->config->demod_address,
+ cmd_buf,3)) {
+ printk(KERN_WARNING "or51132: set_mode error 1\n");
+ return -1;
+ }
+ dprintk("or51132: set #1 to %02x\n", cmd_buf[2]);
+
+ /* Set operation mode in Receiver 6 register */
+ cmd_buf[0] = 0x1C;
+ switch (state->current_modulation) {
+ case QAM_AUTO:
+ /* REC MODE Normal Carrier Lock */
+ cmd_buf[1] = 0x00;
+ /* Channel MODE Auto QAM64/256 */
+ cmd_buf[2] = 0x4f;
+ break;
+ case QAM_256:
+ /* REC MODE Normal Carrier Lock */
+ cmd_buf[1] = 0x00;
+ /* Channel MODE QAM256 */
+ cmd_buf[2] = 0x45;
+ break;
+ case QAM_64:
+ /* REC MODE Normal Carrier Lock */
+ cmd_buf[1] = 0x00;
+ /* Channel MODE QAM64 */
+ cmd_buf[2] = 0x43;
+ break;
+ case VSB_8:
+ /* REC MODE inv IF spectrum, Normal */
+ cmd_buf[1] = 0x03;
+ /* Channel MODE ATSC/VSB8 */
+ cmd_buf[2] = 0x06;
+ break;
+ default:
+ printk("setmode: Modulation set to unsupported value\n");
+ };
+ cmd_buf[3] = 0x00;
+ msleep(20); /* 20ms */
+ if (i2c_writebytes(state,state->config->demod_address,
+ cmd_buf,3)) {
+ printk(KERN_WARNING "or51132: set_mode error 2\n");
+ return -1;
+ }
+ dprintk("or51132: set #6 to 0x%02x%02x\n", cmd_buf[1], cmd_buf[2]);
+
+ return 0;
+}
+
+static int or51132_set_parameters(struct dvb_frontend* fe,
+ struct dvb_frontend_parameters *param)
+{
+ int ret;
+ u8 buf[4];
+ struct or51132_state* state = (struct or51132_state*) fe->demodulator_priv;
+ const struct firmware *fw;
+
+ /* Change only if we are actually changing the modulation */
+ if (state->current_modulation != param->u.vsb.modulation) {
+ switch(param->u.vsb.modulation) {
+ case VSB_8:
+ dprintk("set_parameters VSB MODE\n");
+ printk("or51132: Waiting for firmware upload(%s)...\n",
+ OR51132_VSB_FIRMWARE);
+ ret = request_firmware(&fw, OR51132_VSB_FIRMWARE,
+ &state->i2c->dev);
+ if (ret){
+ printk(KERN_WARNING "or51132: No firmware up"
+ "loaded(timeout or file not found?)\n");
+ return ret;
+ }
+ /* Set non-punctured clock for VSB */
+ state->config->set_ts_params(fe, 0);
+ break;
+ case QAM_AUTO:
+ case QAM_64:
+ case QAM_256:
+ dprintk("set_parameters QAM MODE\n");
+ printk("or51132: Waiting for firmware upload(%s)...\n",
+ OR51132_QAM_FIRMWARE);
+ ret = request_firmware(&fw, OR51132_QAM_FIRMWARE,
+ &state->i2c->dev);
+ if (ret){
+ printk(KERN_WARNING "or51132: No firmware up"
+ "loaded(timeout or file not found?)\n");
+ return ret;
+ }
+ /* Set punctured clock for QAM */
+ state->config->set_ts_params(fe, 1);
+ break;
+ default:
+ printk("or51132:Modulation type(%d) UNSUPPORTED\n",
+ param->u.vsb.modulation);
+ return -1;
+ };
+ ret = or51132_load_firmware(fe, fw);
+ release_firmware(fw);
+ if (ret) {
+ printk(KERN_WARNING "or51132: Writing firmware to "
+ "device failed!\n");
+ return ret;
+ }
+ printk("or51132: Firmware upload complete.\n");
+
+ state->current_modulation = param->u.vsb.modulation;
+ or51132_setmode(fe);
+ }
+
+ /* Change only if we are actually changing the channel */
+ if (state->current_frequency != param->frequency) {
+ dvb_pll_configure(state->config->pll_desc, buf,
+ param->frequency, 0);
+ dprintk("set_parameters tuner bytes: 0x%02x 0x%02x "
+ "0x%02x 0x%02x\n",buf[0],buf[1],buf[2],buf[3]);
+ if (i2c_writebytes(state, state->config->pll_address ,buf, 4))
+ printk(KERN_WARNING "or51132: set_parameters error "
+ "writing to tuner\n");
+
+ /* Set to current mode */
+ or51132_setmode(fe);
+
+ /* Update current frequency */
+ state->current_frequency = param->frequency;
+ }
+ return 0;
+}
+
+static int or51132_read_status(struct dvb_frontend* fe, fe_status_t* status)
+{
+ struct or51132_state* state = (struct or51132_state*) fe->demodulator_priv;
+ unsigned char rec_buf[2];
+ unsigned char snd_buf[2];
+ *status = 0;
+
+ /* Receiver Status */
+ snd_buf[0]=0x04;
+ snd_buf[1]=0x00;
+ msleep(30); /* 30ms */
+ if (i2c_writebytes(state,state->config->demod_address,snd_buf,2)) {
+ printk(KERN_WARNING "or51132: read_status write error\n");
+ return -1;
+ }
+ msleep(30); /* 30ms */
+ if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) {
+ printk(KERN_WARNING "or51132: read_status read error\n");
+ return -1;
+ }
+ dprintk("read_status %x %x\n",rec_buf[0],rec_buf[1]);
+
+ if (rec_buf[1] & 0x01) { /* Receiver Lock */
+ *status |= FE_HAS_SIGNAL;
+ *status |= FE_HAS_CARRIER;
+ *status |= FE_HAS_VITERBI;
+ *status |= FE_HAS_SYNC;
+ *status |= FE_HAS_LOCK;
+ }
+ return 0;
+}
+
+/* log10-1 table at .5 increments from 1 to 100.5 */
+static unsigned int i100x20log10[] = {
+ 0, 352, 602, 795, 954, 1088, 1204, 1306, 1397, 1480,
+ 1556, 1625, 1690, 1750, 1806, 1858, 1908, 1955, 2000, 2042,
+ 2082, 2121, 2158, 2193, 2227, 2260, 2292, 2322, 2352, 2380,
+ 2408, 2434, 2460, 2486, 2510, 2534, 2557, 2580, 2602, 2623,
+ 2644, 2664, 2684, 2704, 2723, 2742, 2760, 2778, 2795, 2813,
+ 2829, 2846, 2862, 2878, 2894, 2909, 2924, 2939, 2954, 2968,
+ 2982, 2996, 3010, 3023, 3037, 3050, 3062, 3075, 3088, 3100,
+ 3112, 3124, 3136, 3148, 3159, 3170, 3182, 3193, 3204, 3214,
+ 3225, 3236, 3246, 3256, 3266, 3276, 3286, 3296, 3306, 3316,
+ 3325, 3334, 3344, 3353, 3362, 3371, 3380, 3389, 3397, 3406,
+ 3415, 3423, 3432, 3440, 3448, 3456, 3464, 3472, 3480, 3488,
+ 3496, 3504, 3511, 3519, 3526, 3534, 3541, 3549, 3556, 3563,
+ 3570, 3577, 3584, 3591, 3598, 3605, 3612, 3619, 3625, 3632,
+ 3639, 3645, 3652, 3658, 3665, 3671, 3677, 3683, 3690, 3696,
+ 3702, 3708, 3714, 3720, 3726, 3732, 3738, 3744, 3750, 3755,
+ 3761, 3767, 3772, 3778, 3784, 3789, 3795, 3800, 3806, 3811,
+ 3816, 3822, 3827, 3832, 3838, 3843, 3848, 3853, 3858, 3863,
+ 3868, 3874, 3879, 3884, 3888, 3893, 3898, 3903, 3908, 3913,
+ 3918, 3922, 3927, 3932, 3936, 3941, 3946, 3950, 3955, 3960,
+ 3964, 3969, 3973, 3978, 3982, 3986, 3991, 3995, 4000, 4004,
+};
+
+static unsigned int denom[] = {1,1,100,1000,10000,100000,1000000,10000000,100000000};
+
+static unsigned int i20Log10(unsigned short val)
+{
+ unsigned int rntval = 100;
+ unsigned int tmp = val;
+ unsigned int exp = 1;
+
+ while(tmp > 100) {tmp /= 100; exp++;}
+
+ val = (2 * val)/denom[exp];
+ if (exp > 1) rntval = 2000*exp;
+
+ rntval += i100x20log10[val];
+ return rntval;
+}
+
+static int or51132_read_signal_strength(struct dvb_frontend* fe, u16* strength)
+{
+ struct or51132_state* state = (struct or51132_state*) fe->demodulator_priv;
+ unsigned char rec_buf[2];
+ unsigned char snd_buf[2];
+ u8 rcvr_stat;
+ u16 snr_equ;
+ int usK;
+
+ snd_buf[0]=0x04;
+ snd_buf[1]=0x02; /* SNR after Equalizer */
+ msleep(30); /* 30ms */
+ if (i2c_writebytes(state,state->config->demod_address,snd_buf,2)) {
+ printk(KERN_WARNING "or51132: read_status write error\n");
+ return -1;
+ }
+ msleep(30); /* 30ms */
+ if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) {
+ printk(KERN_WARNING "or51132: read_status read error\n");
+ return -1;
+ }
+ snr_equ = rec_buf[0] | (rec_buf[1] << 8);
+ dprintk("read_signal_strength snr_equ %x %x (%i)\n",rec_buf[0],rec_buf[1],snr_equ);
+
+ /* Receiver Status */
+ snd_buf[0]=0x04;
+ snd_buf[1]=0x00;
+ msleep(30); /* 30ms */
+ if (i2c_writebytes(state,state->config->demod_address,snd_buf,2)) {
+ printk(KERN_WARNING "or51132: read_signal_strength read_status write error\n");
+ return -1;
+ }
+ msleep(30); /* 30ms */
+ if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) {
+ printk(KERN_WARNING "or51132: read_signal_strength read_status read error\n");
+ return -1;
+ }
+ dprintk("read_signal_strength read_status %x %x\n",rec_buf[0],rec_buf[1]);
+ rcvr_stat = rec_buf[1];
+ usK = (rcvr_stat & 0x10) ? 3 : 0;
+
+ /* The value reported back from the frontend will be FFFF=100% 0000=0% */
+ *strength = (((8952 - i20Log10(snr_equ) - usK*100)/3+5)*65535)/1000;
+ dprintk("read_signal_strength %i\n",*strength);
+
+ return 0;
+}
+
+static int or51132_read_snr(struct dvb_frontend* fe, u16* snr)
+{
+ struct or51132_state* state = (struct or51132_state*) fe->demodulator_priv;
+ unsigned char rec_buf[2];
+ unsigned char snd_buf[2];
+ u16 snr_equ;
+
+ snd_buf[0]=0x04;
+ snd_buf[1]=0x02; /* SNR after Equalizer */
+ msleep(30); /* 30ms */
+ if (i2c_writebytes(state,state->config->demod_address,snd_buf,2)) {
+ printk(KERN_WARNING "or51132: read_snr write error\n");
+ return -1;
+ }
+ msleep(30); /* 30ms */
+ if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) {
+ printk(KERN_WARNING "or51132: read_snr dvr read error\n");
+ return -1;
+ }
+ snr_equ = rec_buf[0] | (rec_buf[1] << 8);
+ dprintk("read_snr snr_equ %x %x (%i)\n",rec_buf[0],rec_buf[1],snr_equ);
+
+ *snr = 0xFFFF - snr_equ;
+ dprintk("read_snr %i\n",*snr);
+
+ return 0;
+}
+
+static int or51132_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fe_tune_settings)
+{
+ fe_tune_settings->min_delay_ms = 500;
+ fe_tune_settings->step_size = 0;
+ fe_tune_settings->max_drift = 0;
+
+ return 0;
+}
+
+static void or51132_release(struct dvb_frontend* fe)
+{
+ struct or51132_state* state = (struct or51132_state*) fe->demodulator_priv;
+ kfree(state);
+}
+
+static struct dvb_frontend_ops or51132_ops;
+
+struct dvb_frontend* or51132_attach(const struct or51132_config* config,
+ struct i2c_adapter* i2c)
+{
+ struct or51132_state* state = NULL;
+
+ /* Allocate memory for the internal state */
+ state = kmalloc(sizeof(struct or51132_state), GFP_KERNEL);
+ if (state == NULL)
+ goto error;
+
+ /* Setup the state */
+ state->config = config;
+ state->i2c = i2c;
+ memcpy(&state->ops, &or51132_ops, sizeof(struct dvb_frontend_ops));
+ state->current_frequency = -1;
+ state->current_modulation = -1;
+
+ /* Create dvb_frontend */
+ state->frontend.ops = &state->ops;
+ state->frontend.demodulator_priv = state;
+ return &state->frontend;
+
+error:
+ if (state)
+ kfree(state);
+ return NULL;
+}
+
+static struct dvb_frontend_ops or51132_ops = {
+
+ .info = {
+ .name = "Oren OR51132 VSB/QAM Frontend",
+ .type = FE_ATSC,
+ .frequency_min = 44000000,
+ .frequency_max = 958000000,
+ .frequency_stepsize = 166666,
+ .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_64 | FE_CAN_QAM_256 | FE_CAN_QAM_AUTO |
+ FE_CAN_8VSB
+ },
+
+ .release = or51132_release,
+
+ .init = or51132_init,
+ .sleep = or51132_sleep,
+
+ .set_frontend = or51132_set_parameters,
+ .get_tune_settings = or51132_get_tune_settings,
+
+ .read_status = or51132_read_status,
+ .read_ber = or51132_read_ber,
+ .read_signal_strength = or51132_read_signal_strength,
+ .read_snr = or51132_read_snr,
+ .read_ucblocks = or51132_read_ucblocks,
+};
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
+
+MODULE_DESCRIPTION("OR51132 ATSC [pcHDTV HD-3000] (8VSB & ITU J83 AnnexB FEC QAM64/256) Demodulator Driver");
+MODULE_AUTHOR("Kirk Lapray");
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(or51132_attach);
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/dvb/frontends/or51132.h b/drivers/media/dvb/frontends/or51132.h
new file mode 100644
index 0000000000000..622cdd18381b9
--- /dev/null
+++ b/drivers/media/dvb/frontends/or51132.h
@@ -0,0 +1,48 @@
+/*
+ * Support for OR51132 (pcHDTV HD-3000) - VSB/QAM
+ *
+ * Copyright (C) 2005 Kirk Lapray <kirk_lapray@bigfoot.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 OR51132_H
+#define OR51132_H
+
+#include <linux/firmware.h>
+#include <linux/dvb/frontend.h>
+
+struct or51132_config
+{
+ /* The demodulator's i2c address */
+ u8 demod_address;
+ u8 pll_address;
+ struct dvb_pll_desc *pll_desc;
+
+ /* Need to set device param for start_dma */
+ int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured);
+};
+
+extern struct dvb_frontend* or51132_attach(const struct or51132_config* config,
+ struct i2c_adapter* i2c);
+
+#endif // OR51132_H
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/dvb/frontends/or51211.c b/drivers/media/dvb/frontends/or51211.c
new file mode 100644
index 0000000000000..ad56a99584043
--- /dev/null
+++ b/drivers/media/dvb/frontends/or51211.c
@@ -0,0 +1,631 @@
+/*
+ * Support for OR51211 (pcHDTV HD-2000) - VSB
+ *
+ * Copyright (C) 2005 Kirk Lapray <kirk_lapray@bigfoot.com>
+ *
+ * Based on code from Jack Kelliher (kelliher@xmission.com)
+ * Copyright (C) 2002 & pcHDTV, inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+*/
+
+/*
+ * 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.
+ */
+#define OR51211_DEFAULT_FIRMWARE "dvb-fe-or51211.fw"
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/device.h>
+#include <linux/firmware.h>
+#include <asm/byteorder.h>
+
+#include "dvb_frontend.h"
+#include "or51211.h"
+
+static int debug;
+#define dprintk(args...) \
+ do { \
+ if (debug) printk(KERN_DEBUG "or51211: " args); \
+ } while (0)
+
+static u8 run_buf[] = {0x7f,0x01};
+static u8 cmd_buf[] = {0x04,0x01,0x50,0x80,0x06}; // ATSC
+
+struct or51211_state {
+
+ struct i2c_adapter* i2c;
+ struct dvb_frontend_ops ops;
+
+ /* Configuration settings */
+ const struct or51211_config* config;
+
+ struct dvb_frontend frontend;
+ struct bt878* bt;
+
+ /* Demodulator private data */
+ u8 initialized:1;
+
+ /* Tuner private data */
+ u32 current_frequency;
+};
+
+static int i2c_writebytes (struct or51211_state* state, u8 reg, u8 *buf,
+ int len)
+{
+ int err;
+ struct i2c_msg msg;
+ msg.addr = reg;
+ msg.flags = 0;
+ msg.len = len;
+ msg.buf = buf;
+
+ if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
+ printk(KERN_WARNING "or51211: i2c_writebytes error "
+ "(addr %02x, err == %i)\n", reg, err);
+ return -EREMOTEIO;
+ }
+
+ return 0;
+}
+
+static u8 i2c_readbytes (struct or51211_state* state, u8 reg, u8* buf, int len)
+{
+ int err;
+ struct i2c_msg msg;
+ msg.addr = reg;
+ msg.flags = I2C_M_RD;
+ msg.len = len;
+ msg.buf = buf;
+
+ if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
+ printk(KERN_WARNING "or51211: i2c_readbytes error "
+ "(addr %02x, err == %i)\n", reg, err);
+ return -EREMOTEIO;
+ }
+
+ return 0;
+}
+
+static int or51211_load_firmware (struct dvb_frontend* fe,
+ const struct firmware *fw)
+{
+ struct or51211_state* state = fe->demodulator_priv;
+ u8 tudata[585];
+ int i;
+
+ dprintk("Firmware is %d bytes\n",fw->size);
+
+ /* Get eprom data */
+ tudata[0] = 17;
+ if (i2c_writebytes(state,0x50,tudata,1)) {
+ printk(KERN_WARNING "or51211:load_firmware error eprom addr\n");
+ return -1;
+ }
+ if (i2c_readbytes(state,0x50,&tudata[145],192)) {
+ printk(KERN_WARNING "or51211: load_firmware error eprom\n");
+ return -1;
+ }
+
+ /* Create firmware buffer */
+ for (i = 0; i < 145; i++)
+ tudata[i] = fw->data[i];
+
+ for (i = 0; i < 248; i++)
+ tudata[i+337] = fw->data[145+i];
+
+ state->config->reset(fe);
+
+ if (i2c_writebytes(state,state->config->demod_address,tudata,585)) {
+ printk(KERN_WARNING "or51211: load_firmware error 1\n");
+ return -1;
+ }
+ msleep(1);
+
+ if (i2c_writebytes(state,state->config->demod_address,
+ &fw->data[393],8125)) {
+ printk(KERN_WARNING "or51211: load_firmware error 2\n");
+ return -1;
+ }
+ msleep(1);
+
+ if (i2c_writebytes(state,state->config->demod_address,run_buf,2)) {
+ printk(KERN_WARNING "or51211: load_firmware error 3\n");
+ return -1;
+ }
+
+ /* Wait at least 5 msec */
+ msleep(10);
+ if (i2c_writebytes(state,state->config->demod_address,run_buf,2)) {
+ printk(KERN_WARNING "or51211: load_firmware error 4\n");
+ return -1;
+ }
+ msleep(10);
+
+ printk("or51211: Done.\n");
+ return 0;
+};
+
+static int or51211_setmode(struct dvb_frontend* fe, int mode)
+{
+ struct or51211_state* state = fe->demodulator_priv;
+ u8 rec_buf[14];
+
+ state->config->setmode(fe, mode);
+
+ if (i2c_writebytes(state,state->config->demod_address,run_buf,2)) {
+ printk(KERN_WARNING "or51211: setmode error 1\n");
+ return -1;
+ }
+
+ /* Wait at least 5 msec */
+ msleep(10);
+ if (i2c_writebytes(state,state->config->demod_address,run_buf,2)) {
+ printk(KERN_WARNING "or51211: setmode error 2\n");
+ return -1;
+ }
+
+ msleep(10);
+
+ /* Set operation mode in Receiver 1 register;
+ * type 1:
+ * data 0x50h Automatic sets receiver channel conditions
+ * Automatic NTSC rejection filter
+ * Enable MPEG serial data output
+ * MPEG2tr
+ * High tuner phase noise
+ * normal +/-150kHz Carrier acquisition range
+ */
+ if (i2c_writebytes(state,state->config->demod_address,cmd_buf,3)) {
+ printk(KERN_WARNING "or51211: setmode error 3\n");
+ return -1;
+ }
+
+ rec_buf[0] = 0x04;
+ rec_buf[1] = 0x00;
+ rec_buf[2] = 0x03;
+ rec_buf[3] = 0x00;
+ msleep(20);
+ if (i2c_writebytes(state,state->config->demod_address,rec_buf,3)) {
+ printk(KERN_WARNING "or51211: setmode error 5\n");
+ }
+ msleep(3);
+ if (i2c_readbytes(state,state->config->demod_address,&rec_buf[10],2)) {
+ printk(KERN_WARNING "or51211: setmode error 6");
+ return -1;
+ }
+ dprintk("setmode rec status %02x %02x\n",rec_buf[10],rec_buf[11]);
+
+ return 0;
+}
+
+static int or51211_set_parameters(struct dvb_frontend* fe,
+ struct dvb_frontend_parameters *param)
+{
+ struct or51211_state* state = fe->demodulator_priv;
+ u32 freq = 0;
+ u16 tunerfreq = 0;
+ u8 buf[4];
+
+ /* Change only if we are actually changing the channel */
+ if (state->current_frequency != param->frequency) {
+ freq = 44000 + (param->frequency/1000);
+ tunerfreq = freq * 16/1000;
+
+ dprintk("set_parameters frequency = %d (tunerfreq = %d)\n",
+ param->frequency,tunerfreq);
+
+ buf[0] = (tunerfreq >> 8) & 0x7F;
+ buf[1] = (tunerfreq & 0xFF);
+ buf[2] = 0x8E;
+
+ if (param->frequency < 157250000) {
+ buf[3] = 0xA0;
+ dprintk("set_parameters VHF low range\n");
+ } else if (param->frequency < 454000000) {
+ buf[3] = 0x90;
+ dprintk("set_parameters VHF high range\n");
+ } else {
+ buf[3] = 0x30;
+ dprintk("set_parameters UHF range\n");
+ }
+ dprintk("set_parameters tuner bytes: 0x%02x 0x%02x "
+ "0x%02x 0x%02x\n",buf[0],buf[1],buf[2],buf[3]);
+
+ if (i2c_writebytes(state,0xC2>>1,buf,4))
+ printk(KERN_WARNING "or51211:set_parameters error "
+ "writing to tuner\n");
+
+ /* Set to ATSC mode */
+ or51211_setmode(fe,0);
+
+ /* Update current frequency */
+ state->current_frequency = param->frequency;
+ }
+ return 0;
+}
+
+static int or51211_read_status(struct dvb_frontend* fe, fe_status_t* status)
+{
+ struct or51211_state* state = fe->demodulator_priv;
+ unsigned char rec_buf[2];
+ unsigned char snd_buf[] = {0x04,0x00,0x03,0x00};
+ *status = 0;
+
+ /* Receiver Status */
+ if (i2c_writebytes(state,state->config->demod_address,snd_buf,3)) {
+ printk(KERN_WARNING "or51132: read_status write error\n");
+ return -1;
+ }
+ msleep(3);
+ if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) {
+ printk(KERN_WARNING "or51132: read_status read error\n");
+ return -1;
+ }
+ dprintk("read_status %x %x\n",rec_buf[0],rec_buf[1]);
+
+ if (rec_buf[0] & 0x01) { /* Receiver Lock */
+ *status |= FE_HAS_SIGNAL;
+ *status |= FE_HAS_CARRIER;
+ *status |= FE_HAS_VITERBI;
+ *status |= FE_HAS_SYNC;
+ *status |= FE_HAS_LOCK;
+ }
+ return 0;
+}
+
+/* log10-1 table at .5 increments from 1 to 100.5 */
+static unsigned int i100x20log10[] = {
+ 0, 352, 602, 795, 954, 1088, 1204, 1306, 1397, 1480,
+ 1556, 1625, 1690, 1750, 1806, 1858, 1908, 1955, 2000, 2042,
+ 2082, 2121, 2158, 2193, 2227, 2260, 2292, 2322, 2352, 2380,
+ 2408, 2434, 2460, 2486, 2510, 2534, 2557, 2580, 2602, 2623,
+ 2644, 2664, 2684, 2704, 2723, 2742, 2760, 2778, 2795, 2813,
+ 2829, 2846, 2862, 2878, 2894, 2909, 2924, 2939, 2954, 2968,
+ 2982, 2996, 3010, 3023, 3037, 3050, 3062, 3075, 3088, 3100,
+ 3112, 3124, 3136, 3148, 3159, 3170, 3182, 3193, 3204, 3214,
+ 3225, 3236, 3246, 3256, 3266, 3276, 3286, 3296, 3306, 3316,
+ 3325, 3334, 3344, 3353, 3362, 3371, 3380, 3389, 3397, 3406,
+ 3415, 3423, 3432, 3440, 3448, 3456, 3464, 3472, 3480, 3488,
+ 3496, 3504, 3511, 3519, 3526, 3534, 3541, 3549, 3556, 3563,
+ 3570, 3577, 3584, 3591, 3598, 3605, 3612, 3619, 3625, 3632,
+ 3639, 3645, 3652, 3658, 3665, 3671, 3677, 3683, 3690, 3696,
+ 3702, 3708, 3714, 3720, 3726, 3732, 3738, 3744, 3750, 3755,
+ 3761, 3767, 3772, 3778, 3784, 3789, 3795, 3800, 3806, 3811,
+ 3816, 3822, 3827, 3832, 3838, 3843, 3848, 3853, 3858, 3863,
+ 3868, 3874, 3879, 3884, 3888, 3893, 3898, 3903, 3908, 3913,
+ 3918, 3922, 3927, 3932, 3936, 3941, 3946, 3950, 3955, 3960,
+ 3964, 3969, 3973, 3978, 3982, 3986, 3991, 3995, 4000, 4004,
+};
+
+static unsigned int denom[] = {1,1,100,1000,10000,100000,1000000,10000000,100000000};
+
+static unsigned int i20Log10(unsigned short val)
+{
+ unsigned int rntval = 100;
+ unsigned int tmp = val;
+ unsigned int exp = 1;
+
+ while(tmp > 100) {tmp /= 100; exp++;}
+
+ val = (2 * val)/denom[exp];
+ if (exp > 1) rntval = 2000*exp;
+
+ rntval += i100x20log10[val];
+ return rntval;
+}
+
+static int or51211_read_signal_strength(struct dvb_frontend* fe, u16* strength)
+{
+ struct or51211_state* state = fe->demodulator_priv;
+ u8 rec_buf[2];
+ u8 snd_buf[4];
+ u8 snr_equ;
+
+ /* SNR after Equalizer */
+ snd_buf[0] = 0x04;
+ snd_buf[1] = 0x00;
+ snd_buf[2] = 0x04;
+ snd_buf[3] = 0x00;
+
+ if (i2c_writebytes(state,state->config->demod_address,snd_buf,3)) {
+ printk(KERN_WARNING "or51211: read_status write error\n");
+ return -1;
+ }
+ msleep(3);
+ if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) {
+ printk(KERN_WARNING "or51211: read_status read error\n");
+ return -1;
+ }
+ snr_equ = rec_buf[0] & 0xff;
+
+ /* The value reported back from the frontend will be FFFF=100% 0000=0% */
+ *strength = (((5334 - i20Log10(snr_equ))/3+5)*65535)/1000;
+
+ dprintk("read_signal_strength %i\n",*strength);
+
+ return 0;
+}
+
+static int or51211_read_snr(struct dvb_frontend* fe, u16* snr)
+{
+ struct or51211_state* state = fe->demodulator_priv;
+ u8 rec_buf[2];
+ u8 snd_buf[4];
+
+ /* SNR after Equalizer */
+ snd_buf[0] = 0x04;
+ snd_buf[1] = 0x00;
+ snd_buf[2] = 0x04;
+ snd_buf[3] = 0x00;
+
+ if (i2c_writebytes(state,state->config->demod_address,snd_buf,3)) {
+ printk(KERN_WARNING "or51211: read_status write error\n");
+ return -1;
+ }
+ msleep(3);
+ if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) {
+ printk(KERN_WARNING "or51211: read_status read error\n");
+ return -1;
+ }
+ *snr = rec_buf[0] & 0xff;
+
+ dprintk("read_snr %i\n",*snr);
+
+ return 0;
+}
+
+static int or51211_read_ber(struct dvb_frontend* fe, u32* ber)
+{
+ *ber = -ENOSYS;
+ return 0;
+}
+
+static int or51211_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
+{
+ *ucblocks = -ENOSYS;
+ return 0;
+}
+
+static int or51211_sleep(struct dvb_frontend* fe)
+{
+ return 0;
+}
+
+static int or51211_init(struct dvb_frontend* fe)
+{
+ struct or51211_state* state = fe->demodulator_priv;
+ const struct or51211_config* config = state->config;
+ const struct firmware* fw;
+ unsigned char get_ver_buf[] = {0x04,0x00,0x30,0x00,0x00};
+ unsigned char rec_buf[14];
+ int ret,i;
+
+ if (!state->initialized) {
+ /* Request the firmware, this will block until it uploads */
+ printk(KERN_INFO "or51211: Waiting for firmware upload "
+ "(%s)...\n", OR51211_DEFAULT_FIRMWARE);
+ ret = config->request_firmware(fe, &fw,
+ OR51211_DEFAULT_FIRMWARE);
+ printk(KERN_INFO "or51211:Got Hotplug firmware\n");
+ if (ret) {
+ printk(KERN_WARNING "or51211: No firmware uploaded "
+ "(timeout or file not found?)\n");
+ return ret;
+ }
+
+ ret = or51211_load_firmware(fe, fw);
+ if (ret) {
+ printk(KERN_WARNING "or51211: Writing firmware to "
+ "device failed!\n");
+ release_firmware(fw);
+ return ret;
+ }
+ printk(KERN_INFO "or51211: Firmware upload complete.\n");
+
+ /* Set operation mode in Receiver 1 register;
+ * type 1:
+ * data 0x50h Automatic sets receiver channel conditions
+ * Automatic NTSC rejection filter
+ * Enable MPEG serial data output
+ * MPEG2tr
+ * High tuner phase noise
+ * normal +/-150kHz Carrier acquisition range
+ */
+ if (i2c_writebytes(state,state->config->demod_address,
+ cmd_buf,3)) {
+ printk(KERN_WARNING "or51211: Load DVR Error 5\n");
+ return -1;
+ }
+
+ /* Read back ucode version to besure we loaded correctly */
+ /* and are really up and running */
+ rec_buf[0] = 0x04;
+ rec_buf[1] = 0x00;
+ rec_buf[2] = 0x03;
+ rec_buf[3] = 0x00;
+ msleep(30);
+ if (i2c_writebytes(state,state->config->demod_address,
+ rec_buf,3)) {
+ printk(KERN_WARNING "or51211: Load DVR Error A\n");
+ return -1;
+ }
+ msleep(3);
+ if (i2c_readbytes(state,state->config->demod_address,
+ &rec_buf[10],2)) {
+ printk(KERN_WARNING "or51211: Load DVR Error B\n");
+ return -1;
+ }
+
+ rec_buf[0] = 0x04;
+ rec_buf[1] = 0x00;
+ rec_buf[2] = 0x01;
+ rec_buf[3] = 0x00;
+ msleep(20);
+ if (i2c_writebytes(state,state->config->demod_address,
+ rec_buf,3)) {
+ printk(KERN_WARNING "or51211: Load DVR Error C\n");
+ return -1;
+ }
+ msleep(3);
+ if (i2c_readbytes(state,state->config->demod_address,
+ &rec_buf[12],2)) {
+ printk(KERN_WARNING "or51211: Load DVR Error D\n");
+ return -1;
+ }
+
+ for (i = 0; i < 8; i++)
+ rec_buf[i]=0xed;
+
+ for (i = 0; i < 5; i++) {
+ msleep(30);
+ get_ver_buf[4] = i+1;
+ if (i2c_writebytes(state,state->config->demod_address,
+ get_ver_buf,5)) {
+ printk(KERN_WARNING "or51211:Load DVR Error 6"
+ " - %d\n",i);
+ return -1;
+ }
+ msleep(3);
+
+ if (i2c_readbytes(state,state->config->demod_address,
+ &rec_buf[i*2],2)) {
+ printk(KERN_WARNING "or51211:Load DVR Error 7"
+ " - %d\n",i);
+ return -1;
+ }
+ /* If we didn't receive the right index, try again */
+ if ((int)rec_buf[i*2+1]!=i+1){
+ i--;
+ }
+ }
+ dprintk("read_fwbits %x %x %x %x %x %x %x %x %x %x\n",
+ rec_buf[0], rec_buf[1], rec_buf[2], rec_buf[3],
+ rec_buf[4], rec_buf[5], rec_buf[6], rec_buf[7],
+ rec_buf[8], rec_buf[9]);
+
+ printk(KERN_INFO "or51211: ver TU%02x%02x%02x VSB mode %02x"
+ " Status %02x\n",
+ rec_buf[2], rec_buf[4],rec_buf[6],
+ rec_buf[12],rec_buf[10]);
+
+ rec_buf[0] = 0x04;
+ rec_buf[1] = 0x00;
+ rec_buf[2] = 0x03;
+ rec_buf[3] = 0x00;
+ msleep(20);
+ if (i2c_writebytes(state,state->config->demod_address,
+ rec_buf,3)) {
+ printk(KERN_WARNING "or51211: Load DVR Error 8\n");
+ return -1;
+ }
+ msleep(20);
+ if (i2c_readbytes(state,state->config->demod_address,
+ &rec_buf[8],2)) {
+ printk(KERN_WARNING "or51211: Load DVR Error 9\n");
+ return -1;
+ }
+ state->initialized = 1;
+ }
+
+ return 0;
+}
+
+static int or51211_get_tune_settings(struct dvb_frontend* fe,
+ struct dvb_frontend_tune_settings* fesettings)
+{
+ fesettings->min_delay_ms = 500;
+ fesettings->step_size = 0;
+ fesettings->max_drift = 0;
+ return 0;
+}
+
+static void or51211_release(struct dvb_frontend* fe)
+{
+ struct or51211_state* state = fe->demodulator_priv;
+ state->config->sleep(fe);
+ kfree(state);
+}
+
+static struct dvb_frontend_ops or51211_ops;
+
+struct dvb_frontend* or51211_attach(const struct or51211_config* config,
+ struct i2c_adapter* i2c)
+{
+ struct or51211_state* state = NULL;
+
+ /* Allocate memory for the internal state */
+ state = kmalloc(sizeof(struct or51211_state), GFP_KERNEL);
+ if (state == NULL)
+ goto error;
+
+ /* Setup the state */
+ state->config = config;
+ state->i2c = i2c;
+ memcpy(&state->ops, &or51211_ops, sizeof(struct dvb_frontend_ops));
+ state->initialized = 0;
+ state->current_frequency = 0;
+
+ /* 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 or51211_ops = {
+
+ .info = {
+ .name = "Oren OR51211 VSB Frontend",
+ .type = FE_ATSC,
+ .frequency_min = 44000000,
+ .frequency_max = 958000000,
+ .frequency_stepsize = 166666,
+ .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_8VSB
+ },
+
+ .release = or51211_release,
+
+ .init = or51211_init,
+ .sleep = or51211_sleep,
+
+ .set_frontend = or51211_set_parameters,
+ .get_tune_settings = or51211_get_tune_settings,
+
+ .read_status = or51211_read_status,
+ .read_ber = or51211_read_ber,
+ .read_signal_strength = or51211_read_signal_strength,
+ .read_snr = or51211_read_snr,
+ .read_ucblocks = or51211_read_ucblocks,
+};
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
+
+MODULE_DESCRIPTION("Oren OR51211 VSB [pcHDTV HD-2000] Demodulator Driver");
+MODULE_AUTHOR("Kirk Lapray");
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(or51211_attach);
+
diff --git a/drivers/media/dvb/frontends/or51211.h b/drivers/media/dvb/frontends/or51211.h
new file mode 100644
index 0000000000000..13a5a3afbf8b1
--- /dev/null
+++ b/drivers/media/dvb/frontends/or51211.h
@@ -0,0 +1,44 @@
+/*
+ * Support for OR51211 (pcHDTV HD-2000) - VSB
+ *
+ * Copyright (C) 2005 Kirk Lapray <kirk_lapray@bigfoot.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 OR51211_H
+#define OR51211_H
+
+#include <linux/dvb/frontend.h>
+#include <linux/firmware.h>
+
+struct or51211_config
+{
+ /* The demodulator's i2c address */
+ u8 demod_address;
+
+ /* Request firmware for device */
+ int (*request_firmware)(struct dvb_frontend* fe, const struct firmware **fw, char* name);
+ void (*setmode)(struct dvb_frontend * fe, int mode);
+ void (*reset)(struct dvb_frontend * fe);
+ void (*sleep)(struct dvb_frontend * fe);
+};
+
+extern struct dvb_frontend* or51211_attach(const struct or51211_config* config,
+ struct i2c_adapter* i2c);
+
+#endif // OR51211_H
+
diff --git a/drivers/media/dvb/frontends/sp8870.c b/drivers/media/dvb/frontends/sp8870.c
index 72338d461ba5b..58ad34ef0a007 100644
--- a/drivers/media/dvb/frontends/sp8870.c
+++ b/drivers/media/dvb/frontends/sp8870.c
@@ -130,7 +130,7 @@ static int sp8870_firmware_upload (struct sp8870_state* state, const struct firm
msg.flags = 0;
msg.buf = tx_buf;
msg.len = tx_len + 2;
- if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
+ if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
printk("%s: firmware upload failed!\n", __FUNCTION__);
printk ("%s: i2c error (err == %i)\n", __FUNCTION__, err);
return err;
@@ -570,7 +570,7 @@ struct dvb_frontend* sp8870_attach(const struct sp8870_config* config,
return &state->frontend;
error:
- if (state) kfree(state);
+ kfree(state);
return NULL;
}
diff --git a/drivers/media/dvb/frontends/sp887x.c b/drivers/media/dvb/frontends/sp887x.c
index 40ae6459251e2..7eae833ece490 100644
--- a/drivers/media/dvb/frontends/sp887x.c
+++ b/drivers/media/dvb/frontends/sp887x.c
@@ -20,13 +20,9 @@
struct sp887x_state {
-
struct i2c_adapter* i2c;
-
struct dvb_frontend_ops ops;
-
const struct sp887x_config* config;
-
struct dvb_frontend frontend;
/* demodulator private data */
@@ -315,8 +311,8 @@ static void divide (int n, int d, int *quotient_i, int *quotient_f)
}
static void sp887x_correct_offsets (struct sp887x_state* state,
- struct dvb_frontend_parameters *p,
- int actual_freq)
+ struct dvb_frontend_parameters *p,
+ int actual_freq)
{
static const u32 srate_correction [] = { 1879617, 4544878, 8098561 };
int bw_index = p->u.ofdm.bandwidth - BANDWIDTH_8_MHZ;
@@ -345,21 +341,8 @@ static void sp887x_correct_offsets (struct sp887x_state* state,
sp887x_writereg(state, 0x30a, frequency_shift & 0xfff);
}
-
-
-
-
-
-
-
-
-
-
-
-
-
static int sp887x_setup_frontend_parameters (struct dvb_frontend* fe,
- struct dvb_frontend_parameters *p)
+ struct dvb_frontend_parameters *p)
{
struct sp887x_state* state = (struct sp887x_state*) fe->demodulator_priv;
int actual_freq, err;
@@ -421,73 +404,73 @@ static int sp887x_setup_frontend_parameters (struct dvb_frontend* fe,
}
static int sp887x_read_status(struct dvb_frontend* fe, fe_status_t* status)
- {
+{
struct sp887x_state* state = (struct sp887x_state*) fe->demodulator_priv;
u16 snr12 = sp887x_readreg(state, 0xf16);
u16 sync0x200 = sp887x_readreg(state, 0x200);
u16 sync0xf17 = sp887x_readreg(state, 0xf17);
- *status = 0;
+ *status = 0;
- if (snr12 > 0x00f)
- *status |= FE_HAS_SIGNAL;
+ if (snr12 > 0x00f)
+ *status |= FE_HAS_SIGNAL;
- //if (sync0x200 & 0x004)
- // *status |= FE_HAS_SYNC | FE_HAS_CARRIER;
+ //if (sync0x200 & 0x004)
+ // *status |= FE_HAS_SYNC | FE_HAS_CARRIER;
- //if (sync0x200 & 0x008)
- // *status |= FE_HAS_VITERBI;
+ //if (sync0x200 & 0x008)
+ // *status |= FE_HAS_VITERBI;
- if ((sync0xf17 & 0x00f) == 0x002) {
- *status |= FE_HAS_LOCK;
- *status |= FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_CARRIER;
- }
+ if ((sync0xf17 & 0x00f) == 0x002) {
+ *status |= FE_HAS_LOCK;
+ *status |= FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_CARRIER;
+ }
- if (sync0x200 & 0x001) { /* tuner adjustment requested...*/
- int steps = (sync0x200 >> 4) & 0x00f;
- if (steps & 0x008)
- steps = -steps;
- dprintk("sp887x: implement tuner adjustment (%+i steps)!!\n",
- steps);
- }
+ if (sync0x200 & 0x001) { /* tuner adjustment requested...*/
+ int steps = (sync0x200 >> 4) & 0x00f;
+ if (steps & 0x008)
+ steps = -steps;
+ dprintk("sp887x: implement tuner adjustment (%+i steps)!!\n",
+ steps);
+ }
return 0;
- }
+}
static int sp887x_read_ber(struct dvb_frontend* fe, u32* ber)
- {
+{
struct sp887x_state* state = (struct sp887x_state*) fe->demodulator_priv;
*ber = (sp887x_readreg(state, 0xc08) & 0x3f) |
(sp887x_readreg(state, 0xc07) << 6);
sp887x_writereg(state, 0xc08, 0x000);
sp887x_writereg(state, 0xc07, 0x000);
- if (*ber >= 0x3fff0)
- *ber = ~0;
+ if (*ber >= 0x3fff0)
+ *ber = ~0;
return 0;
- }
+}
static int sp887x_read_signal_strength(struct dvb_frontend* fe, u16* strength)
- {
+{
struct sp887x_state* state = (struct sp887x_state*) fe->demodulator_priv;
u16 snr12 = sp887x_readreg(state, 0xf16);
- u32 signal = 3 * (snr12 << 4);
+ u32 signal = 3 * (snr12 << 4);
*strength = (signal < 0xffff) ? signal : 0xffff;
return 0;
- }
+}
static int sp887x_read_snr(struct dvb_frontend* fe, u16* snr)
- {
+{
struct sp887x_state* state = (struct sp887x_state*) fe->demodulator_priv;
u16 snr12 = sp887x_readreg(state, 0xf16);
*snr = (snr12 << 4) | (snr12 >> 8);
- return 0;
- }
+ return 0;
+}
static int sp887x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
{
@@ -497,7 +480,7 @@ static int sp887x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
if (*ucblocks == 0xfff)
*ucblocks = ~0;
- return 0;
+ return 0;
}
static int sp887x_sleep(struct dvb_frontend* fe)
@@ -508,7 +491,7 @@ static int sp887x_sleep(struct dvb_frontend* fe)
sp887x_writereg(state, 0xc18, 0x000);
return 0;
- }
+}
static int sp887x_init(struct dvb_frontend* fe)
{
@@ -517,20 +500,20 @@ static int sp887x_init(struct dvb_frontend* fe)
int ret;
if (!state->initialised) {
- /* request the firmware, this will block until someone uploads it */
+ /* request the firmware, this will block until someone uploads it */
printk("sp887x: waiting for firmware upload (%s)...\n", SP887X_DEFAULT_FIRMWARE);
ret = state->config->request_firmware(fe, &fw, SP887X_DEFAULT_FIRMWARE);
- if (ret) {
- printk("sp887x: no firmware upload (timeout or file not found?)\n");
+ if (ret) {
+ printk("sp887x: no firmware upload (timeout or file not found?)\n");
return ret;
- }
+ }
ret = sp887x_initial_setup(fe, fw);
- if (ret) {
- printk("sp887x: writing firmware to device failed\n");
+ if (ret) {
+ printk("sp887x: writing firmware to device failed\n");
release_firmware(fw);
return ret;
- }
+ }
printk("sp887x: firmware upload complete\n");
state->initialised = 1;
}
@@ -581,7 +564,7 @@ struct dvb_frontend* sp887x_attach(const struct sp887x_config* config,
return &state->frontend;
error:
- if (state) kfree(state);
+ kfree(state);
return NULL;
}
diff --git a/drivers/media/dvb/frontends/stv0297.c b/drivers/media/dvb/frontends/stv0297.c
index b51a6d2565c56..502c6403dfc64 100644
--- a/drivers/media/dvb/frontends/stv0297.c
+++ b/drivers/media/dvb/frontends/stv0297.c
@@ -29,14 +29,10 @@
#include "stv0297.h"
struct stv0297_state {
-
- struct i2c_adapter* i2c;
-
- struct dvb_frontend_ops ops;
-
- const struct stv0297_config* config;
-
- struct dvb_frontend frontend;
+ struct i2c_adapter *i2c;
+ struct dvb_frontend_ops ops;
+ const struct stv0297_config *config;
+ struct dvb_frontend frontend;
unsigned long base_freq;
u8 pwm;
@@ -50,164 +46,164 @@ struct stv0297_state {
#define STV0297_CLOCK_KHZ 28900
-static u8 init_tab [] = {
- 0x00, 0x09,
- 0x01, 0x69,
- 0x03, 0x00,
- 0x04, 0x00,
- 0x07, 0x00,
- 0x08, 0x00,
- 0x20, 0x00,
- 0x21, 0x40,
- 0x22, 0x00,
- 0x23, 0x00,
- 0x24, 0x40,
- 0x25, 0x88,
- 0x30, 0xff,
- 0x31, 0x00,
- 0x32, 0xff,
- 0x33, 0x00,
- 0x34, 0x50,
- 0x35, 0x7f,
- 0x36, 0x00,
- 0x37, 0x20,
- 0x38, 0x00,
- 0x40, 0x1c,
- 0x41, 0xff,
- 0x42, 0x29,
+static u8 init_tab[] = {
+ 0x00, 0x09,
+ 0x01, 0x69,
+ 0x03, 0x00,
+ 0x04, 0x00,
+ 0x07, 0x00,
+ 0x08, 0x00,
+ 0x20, 0x00,
+ 0x21, 0x40,
+ 0x22, 0x00,
+ 0x23, 0x00,
+ 0x24, 0x40,
+ 0x25, 0x88,
+ 0x30, 0xff,
+ 0x31, 0x00,
+ 0x32, 0xff,
+ 0x33, 0x00,
+ 0x34, 0x50,
+ 0x35, 0x7f,
+ 0x36, 0x00,
+ 0x37, 0x20,
+ 0x38, 0x00,
+ 0x40, 0x1c,
+ 0x41, 0xff,
+ 0x42, 0x29,
0x43, 0x00,
- 0x44, 0xff,
- 0x45, 0x00,
- 0x46, 0x00,
- 0x49, 0x04,
- 0x4a, 0xff,
- 0x4b, 0x7f,
- 0x52, 0x30,
- 0x55, 0xae,
- 0x56, 0x47,
- 0x57, 0xe1,
- 0x58, 0x3a,
- 0x5a, 0x1e,
- 0x5b, 0x34,
- 0x60, 0x00,
- 0x63, 0x00,
- 0x64, 0x00,
- 0x65, 0x00,
- 0x66, 0x00,
- 0x67, 0x00,
- 0x68, 0x00,
- 0x69, 0x00,
- 0x6a, 0x02,
- 0x6b, 0x00,
- 0x70, 0xff,
- 0x71, 0x00,
- 0x72, 0x00,
- 0x73, 0x00,
- 0x74, 0x0c,
- 0x80, 0x00,
- 0x81, 0x00,
- 0x82, 0x00,
- 0x83, 0x00,
- 0x84, 0x04,
- 0x85, 0x80,
- 0x86, 0x24,
- 0x87, 0x78,
- 0x88, 0x00,
- 0x89, 0x00,
- 0x90, 0x01,
- 0x91, 0x01,
- 0xa0, 0x00,
- 0xa1, 0x00,
- 0xa2, 0x00,
- 0xb0, 0x91,
- 0xb1, 0x0b,
- 0xc0, 0x53,
- 0xc1, 0x70,
- 0xc2, 0x12,
- 0xd0, 0x00,
- 0xd1, 0x00,
- 0xd2, 0x00,
- 0xd3, 0x00,
- 0xd4, 0x00,
- 0xd5, 0x00,
- 0xde, 0x00,
- 0xdf, 0x00,
- 0x61, 0x49,
- 0x62, 0x0b,
- 0x53, 0x08,
- 0x59, 0x08,
+ 0x44, 0xff,
+ 0x45, 0x00,
+ 0x46, 0x00,
+ 0x49, 0x04,
+ 0x4a, 0xff,
+ 0x4b, 0x7f,
+ 0x52, 0x30,
+ 0x55, 0xae,
+ 0x56, 0x47,
+ 0x57, 0xe1,
+ 0x58, 0x3a,
+ 0x5a, 0x1e,
+ 0x5b, 0x34,
+ 0x60, 0x00,
+ 0x63, 0x00,
+ 0x64, 0x00,
+ 0x65, 0x00,
+ 0x66, 0x00,
+ 0x67, 0x00,
+ 0x68, 0x00,
+ 0x69, 0x00,
+ 0x6a, 0x02,
+ 0x6b, 0x00,
+ 0x70, 0xff,
+ 0x71, 0x00,
+ 0x72, 0x00,
+ 0x73, 0x00,
+ 0x74, 0x0c,
+ 0x80, 0x00,
+ 0x81, 0x00,
+ 0x82, 0x00,
+ 0x83, 0x00,
+ 0x84, 0x04,
+ 0x85, 0x80,
+ 0x86, 0x24,
+ 0x87, 0x78,
+ 0x88, 0x00,
+ 0x89, 0x00,
+ 0x90, 0x01,
+ 0x91, 0x01,
+ 0xa0, 0x00,
+ 0xa1, 0x00,
+ 0xa2, 0x00,
+ 0xb0, 0x91,
+ 0xb1, 0x0b,
+ 0xc0, 0x53,
+ 0xc1, 0x70,
+ 0xc2, 0x12,
+ 0xd0, 0x00,
+ 0xd1, 0x00,
+ 0xd2, 0x00,
+ 0xd3, 0x00,
+ 0xd4, 0x00,
+ 0xd5, 0x00,
+ 0xde, 0x00,
+ 0xdf, 0x00,
+ 0x61, 0x49,
+ 0x62, 0x0b,
+ 0x53, 0x08,
+ 0x59, 0x08,
};
-static int stv0297_writereg (struct stv0297_state* state, u8 reg, u8 data)
+static int stv0297_writereg(struct stv0297_state *state, u8 reg, u8 data)
{
- int ret;
- u8 buf [] = { reg, data };
- struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 };
+ int ret;
+ u8 buf[] = { reg, data };
+ struct i2c_msg msg = {.addr = state->config->demod_address,.flags = 0,.buf = buf,.len = 2 };
- ret = i2c_transfer (state->i2c, &msg, 1);
+ ret = i2c_transfer(state->i2c, &msg, 1);
- if (ret != 1)
- dprintk("%s: writereg error (reg == 0x%02x, val == 0x%02x, "
- "ret == %i)\n", __FUNCTION__, reg, data, ret);
+ if (ret != 1)
+ dprintk("%s: writereg error (reg == 0x%02x, val == 0x%02x, "
+ "ret == %i)\n", __FUNCTION__, reg, data, ret);
- return (ret != 1) ? -1 : 0;
+ return (ret != 1) ? -1 : 0;
}
-static int stv0297_readreg (struct stv0297_state* state, u8 reg)
+static int stv0297_readreg(struct stv0297_state *state, u8 reg)
{
- int ret;
- u8 b0[] = { reg };
- u8 b1[] = { 0 };
+ 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}
};
- // this device needs a STOP between the register and data
- if ((ret = i2c_transfer (state->i2c, &msg[0], 1)) != 1) {
+ // this device needs a STOP between the register and data
+ if ((ret = i2c_transfer(state->i2c, &msg[0], 1)) != 1) {
dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg, ret);
- return -1;
- }
- if ((ret = i2c_transfer (state->i2c, &msg[1], 1)) != 1) {
+ return -1;
+ }
+ if ((ret = i2c_transfer(state->i2c, &msg[1], 1)) != 1) {
dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg, ret);
- return -1;
- }
+ return -1;
+ }
- return b1[0];
+ return b1[0];
}
-static int stv0297_writereg_mask (struct stv0297_state* state, u8 reg, u8 mask, u8 data)
+static int stv0297_writereg_mask(struct stv0297_state *state, u8 reg, u8 mask, u8 data)
{
- int val;
+ int val;
- val = stv0297_readreg(state, reg);
- val &= ~mask;
- val |= (data & mask);
- stv0297_writereg(state, reg, val);
+ val = stv0297_readreg(state, reg);
+ val &= ~mask;
+ val |= (data & mask);
+ stv0297_writereg(state, reg, val);
- return 0;
+ return 0;
}
-static int stv0297_readregs (struct stv0297_state* state, u8 reg1, u8 *b, u8 len)
+static int stv0297_readregs(struct stv0297_state *state, u8 reg1, u8 * b, u8 len)
{
- int ret;
+ int ret;
struct i2c_msg msg[] = { {.addr = state->config->demod_address,.flags = 0,.buf =
&reg1,.len = 1},
{.addr = state->config->demod_address,.flags = I2C_M_RD,.buf = b,.len = len}
};
- // this device needs a STOP between the register and data
- if ((ret = i2c_transfer (state->i2c, &msg[0], 1)) != 1) {
+ // this device needs a STOP between the register and data
+ if ((ret = i2c_transfer(state->i2c, &msg[0], 1)) != 1) {
dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg1, ret);
- return -1;
- }
- if ((ret = i2c_transfer (state->i2c, &msg[1], 1)) != 1) {
+ return -1;
+ }
+ if ((ret = i2c_transfer(state->i2c, &msg[1], 1)) != 1) {
dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg1, ret);
- return -1;
- }
+ return -1;
+ }
- return 0;
+ return 0;
}
static u32 stv0297_get_symbolrate(struct stv0297_state *state)
@@ -233,10 +229,10 @@ static void stv0297_set_symbolrate(struct stv0297_state *state, u32 srate)
tmp = tmp / (STV0297_CLOCK_KHZ / 4); /* 1/4 = 2^-2 */
tmp = tmp * 8192L; /* 8192 = 2^13 */
- stv0297_writereg (state, 0x55,(unsigned char)(tmp & 0xFF));
- stv0297_writereg (state, 0x56,(unsigned char)(tmp>> 8));
- stv0297_writereg (state, 0x57,(unsigned char)(tmp>>16));
- stv0297_writereg (state, 0x58,(unsigned char)(tmp>>24));
+ stv0297_writereg(state, 0x55, (unsigned char) (tmp & 0xFF));
+ stv0297_writereg(state, 0x56, (unsigned char) (tmp >> 8));
+ stv0297_writereg(state, 0x57, (unsigned char) (tmp >> 16));
+ stv0297_writereg(state, 0x58, (unsigned char) (tmp >> 24));
}
static void stv0297_set_sweeprate(struct stv0297_state *state, short fshift, long symrate)
@@ -247,19 +243,19 @@ static void stv0297_set_sweeprate(struct stv0297_state *state, short fshift, lon
tmp /= symrate;
tmp *= 1024; /* 1024 = 2*10 */
- // adjust
- if (tmp >= 0) {
- tmp += 500000;
- } else {
- tmp -= 500000;
- }
+ // adjust
+ if (tmp >= 0) {
+ tmp += 500000;
+ } else {
+ tmp -= 500000;
+ }
tmp /= 1000000;
- stv0297_writereg(state, 0x60, tmp & 0xFF);
- stv0297_writereg_mask(state, 0x69, 0xF0, (tmp >> 4) & 0xf0);
+ stv0297_writereg(state, 0x60, tmp & 0xFF);
+ stv0297_writereg_mask(state, 0x69, 0xF0, (tmp >> 4) & 0xf0);
}
-static void stv0297_set_carrieroffset(struct stv0297_state* state, long offset)
+static void stv0297_set_carrieroffset(struct stv0297_state *state, long offset)
{
long tmp;
@@ -276,11 +272,11 @@ static void stv0297_set_carrieroffset(struct stv0297_state* state, long offset)
}
/*
-static long stv0297_get_carrieroffset(struct stv0297_state* state)
+static long stv0297_get_carrieroffset(struct stv0297_state *state)
{
s64 tmp;
- stv0297_writereg(state,0x6B, 0x00);
+ stv0297_writereg(state, 0x6B, 0x00);
tmp = stv0297_readreg(state, 0x66);
tmp |= (stv0297_readreg(state, 0x67) << 8);
@@ -294,7 +290,7 @@ static long stv0297_get_carrieroffset(struct stv0297_state* state)
}
*/
-static void stv0297_set_initialdemodfreq(struct stv0297_state* state, long freq)
+static void stv0297_set_initialdemodfreq(struct stv0297_state *state, long freq)
{
s32 tmp;
@@ -306,128 +302,116 @@ static void stv0297_set_initialdemodfreq(struct stv0297_state* state, long freq)
if (tmp > 0xffff)
tmp = 0xffff;
- stv0297_writereg_mask(state, 0x25, 0x80, 0x80);
- stv0297_writereg(state, 0x21, tmp >> 8);
- stv0297_writereg(state, 0x20, tmp);
+ stv0297_writereg_mask(state, 0x25, 0x80, 0x80);
+ stv0297_writereg(state, 0x21, tmp >> 8);
+ stv0297_writereg(state, 0x20, tmp);
}
-static int stv0297_set_qam(struct stv0297_state* state, fe_modulation_t modulation)
+static int stv0297_set_qam(struct stv0297_state *state, fe_modulation_t modulation)
{
- int val = 0;
+ int val = 0;
- switch(modulation) {
- case QAM_16:
- val = 0;
- break;
+ switch (modulation) {
+ case QAM_16:
+ val = 0;
+ break;
- case QAM_32:
- val = 1;
- break;
+ case QAM_32:
+ val = 1;
+ break;
- case QAM_64:
- val = 4;
- break;
+ case QAM_64:
+ val = 4;
+ break;
- case QAM_128:
- val = 2;
- break;
+ case QAM_128:
+ val = 2;
+ break;
- case QAM_256:
- val = 3;
- break;
+ case QAM_256:
+ val = 3;
+ break;
- default:
- return -EINVAL;
- }
+ default:
+ return -EINVAL;
+ }
- stv0297_writereg_mask(state, 0x00, 0x70, val << 4);
+ stv0297_writereg_mask(state, 0x00, 0x70, val << 4);
- return 0;
+ return 0;
}
-static int stv0297_set_inversion(struct stv0297_state* state, fe_spectral_inversion_t inversion)
+static int stv0297_set_inversion(struct stv0297_state *state, fe_spectral_inversion_t inversion)
{
- int val = 0;
+ int val = 0;
- switch(inversion) {
- case INVERSION_OFF:
- val = 0;
- break;
+ switch (inversion) {
+ case INVERSION_OFF:
+ val = 0;
+ break;
- case INVERSION_ON:
- val = 1;
- break;
+ case INVERSION_ON:
+ val = 1;
+ break;
- default:
- return -EINVAL;
- }
+ default:
+ return -EINVAL;
+ }
- stv0297_writereg_mask(state, 0x83, 0x08, val << 3);
+ stv0297_writereg_mask(state, 0x83, 0x08, val << 3);
- return 0;
+ return 0;
}
-
-
-
-
-
-
-
-
-
-
-
-
-int stv0297_enable_plli2c(struct dvb_frontend* fe)
+int stv0297_enable_plli2c(struct dvb_frontend *fe)
{
- struct stv0297_state* state = (struct stv0297_state*) fe->demodulator_priv;
+ struct stv0297_state *state = (struct stv0297_state *) fe->demodulator_priv;
- stv0297_writereg(state, 0x87, 0x78);
- stv0297_writereg(state, 0x86, 0xc8);
+ stv0297_writereg(state, 0x87, 0x78);
+ stv0297_writereg(state, 0x86, 0xc8);
- return 0;
+ return 0;
}
-static int stv0297_init (struct dvb_frontend* fe)
+static int stv0297_init(struct dvb_frontend *fe)
{
- struct stv0297_state* state = (struct stv0297_state*) fe->demodulator_priv;
- int i;
+ struct stv0297_state *state = (struct stv0297_state *) fe->demodulator_priv;
+ int i;
/* soft reset */
- stv0297_writereg_mask(state, 0x80, 1, 1);
- stv0297_writereg_mask(state, 0x80, 1, 0);
+ stv0297_writereg_mask(state, 0x80, 1, 1);
+ stv0297_writereg_mask(state, 0x80, 1, 0);
/* reset deinterleaver */
- stv0297_writereg_mask(state, 0x81, 1, 1);
- stv0297_writereg_mask(state, 0x81, 1, 0);
+ stv0297_writereg_mask(state, 0x81, 1, 1);
+ stv0297_writereg_mask(state, 0x81, 1, 0);
/* load init table */
- for (i=0; i<sizeof(init_tab); i+=2) {
- stv0297_writereg (state, init_tab[i], init_tab[i+1]);
- }
+ for (i = 0; i < sizeof(init_tab); i += 2) {
+ stv0297_writereg(state, init_tab[i], init_tab[i + 1]);
+ }
/* set a dummy symbol rate */
- stv0297_set_symbolrate(state, 6900);
+ stv0297_set_symbolrate(state, 6900);
/* invert AGC1 polarity */
- stv0297_writereg_mask(state, 0x88, 0x10, 0x10);
+ stv0297_writereg_mask(state, 0x88, 0x10, 0x10);
/* setup bit error counting */
- stv0297_writereg_mask(state, 0xA0, 0x80, 0x00);
- stv0297_writereg_mask(state, 0xA0, 0x10, 0x00);
- stv0297_writereg_mask(state, 0xA0, 0x08, 0x00);
- stv0297_writereg_mask(state, 0xA0, 0x07, 0x04);
+ stv0297_writereg_mask(state, 0xA0, 0x80, 0x00);
+ stv0297_writereg_mask(state, 0xA0, 0x10, 0x00);
+ stv0297_writereg_mask(state, 0xA0, 0x08, 0x00);
+ stv0297_writereg_mask(state, 0xA0, 0x07, 0x04);
/* min + max PWM */
- stv0297_writereg(state, 0x4a, 0x00);
- stv0297_writereg(state, 0x4b, state->pwm);
- msleep(200);
+ stv0297_writereg(state, 0x4a, 0x00);
+ stv0297_writereg(state, 0x4b, state->pwm);
+ msleep(200);
if (state->config->pll_init)
state->config->pll_init(fe);
- return 0;
+ return 0;
}
static int stv0297_sleep(struct dvb_frontend *fe)
@@ -439,121 +423,121 @@ static int stv0297_sleep(struct dvb_frontend *fe)
return 0;
}
-static int stv0297_read_status(struct dvb_frontend* fe, fe_status_t* status)
+static int stv0297_read_status(struct dvb_frontend *fe, fe_status_t * status)
{
- struct stv0297_state* state = (struct stv0297_state*) fe->demodulator_priv;
+ struct stv0297_state *state = (struct stv0297_state *) fe->demodulator_priv;
- u8 sync = stv0297_readreg (state, 0xDF);
+ u8 sync = stv0297_readreg(state, 0xDF);
- *status = 0;
- if (sync & 0x80)
+ *status = 0;
+ if (sync & 0x80)
*status |=
FE_HAS_SYNC | FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_LOCK;
- return 0;
+ return 0;
}
-static int stv0297_read_ber(struct dvb_frontend* fe, u32* ber)
+static int stv0297_read_ber(struct dvb_frontend *fe, u32 * ber)
{
- struct stv0297_state* state = (struct stv0297_state*) fe->demodulator_priv;
- u8 BER[3];
+ struct stv0297_state *state = (struct stv0297_state *) fe->demodulator_priv;
+ u8 BER[3];
- stv0297_writereg (state, 0xA0, 0x80); // Start Counting bit errors for 4096 Bytes
- mdelay(25); // Hopefully got 4096 Bytes
- stv0297_readregs (state, 0xA0, BER, 3);
- mdelay(25);
- *ber = (BER[2] << 8 | BER[1]) / ( 8 * 4096);
+ stv0297_writereg(state, 0xA0, 0x80); // Start Counting bit errors for 4096 Bytes
+ mdelay(25); // Hopefully got 4096 Bytes
+ stv0297_readregs(state, 0xA0, BER, 3);
+ mdelay(25);
+ *ber = (BER[2] << 8 | BER[1]) / (8 * 4096);
- return 0;
+ return 0;
}
-static int stv0297_read_signal_strength(struct dvb_frontend* fe, u16* strength)
+static int stv0297_read_signal_strength(struct dvb_frontend *fe, u16 * strength)
{
- struct stv0297_state* state = (struct stv0297_state*) fe->demodulator_priv;
- u8 STRENGTH[2];
+ struct stv0297_state *state = (struct stv0297_state *) fe->demodulator_priv;
+ u8 STRENGTH[2];
- stv0297_readregs (state, 0x41, STRENGTH, 2);
- *strength = (STRENGTH[1] & 0x03) << 8 | STRENGTH[0];
+ stv0297_readregs(state, 0x41, STRENGTH, 2);
+ *strength = (STRENGTH[1] & 0x03) << 8 | STRENGTH[0];
- return 0;
+ return 0;
}
-static int stv0297_read_snr(struct dvb_frontend* fe, u16* snr)
+static int stv0297_read_snr(struct dvb_frontend *fe, u16 * snr)
{
- struct stv0297_state* state = (struct stv0297_state*) fe->demodulator_priv;
- u8 SNR[2];
+ struct stv0297_state *state = (struct stv0297_state *) fe->demodulator_priv;
+ u8 SNR[2];
- stv0297_readregs (state, 0x07, SNR, 2);
- *snr = SNR[1] << 8 | SNR[0];
+ stv0297_readregs(state, 0x07, SNR, 2);
+ *snr = SNR[1] << 8 | SNR[0];
- return 0;
+ return 0;
}
-static int stv0297_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
+static int stv0297_read_ucblocks(struct dvb_frontend *fe, u32 * ucblocks)
{
- struct stv0297_state* state = (struct stv0297_state*) fe->demodulator_priv;
+ struct stv0297_state *state = (struct stv0297_state *) fe->demodulator_priv;
- *ucblocks = (stv0297_readreg (state, 0xD5) << 8)
- | stv0297_readreg (state, 0xD4);
+ *ucblocks = (stv0297_readreg(state, 0xD5) << 8)
+ | stv0297_readreg(state, 0xD4);
- return 0;
+ return 0;
}
-static int stv0297_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters * p)
+static int stv0297_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
{
- struct stv0297_state* state = (struct stv0297_state*) fe->demodulator_priv;
- int u_threshold;
- int initial_u;
- int blind_u;
- int delay;
- int sweeprate;
- int carrieroffset;
- unsigned long starttime;
- unsigned long timeout;
+ struct stv0297_state *state = (struct stv0297_state *) fe->demodulator_priv;
+ int u_threshold;
+ int initial_u;
+ int blind_u;
+ int delay;
+ int sweeprate;
+ int carrieroffset;
+ unsigned long starttime;
+ unsigned long timeout;
fe_spectral_inversion_t inversion;
- switch(p->u.qam.modulation) {
- case QAM_16:
- case QAM_32:
- case QAM_64:
- delay = 100;
- sweeprate = 1500;
- break;
-
- case QAM_128:
- delay = 150;
- sweeprate = 1000;
- break;
-
- case QAM_256:
- delay = 200;
- sweeprate = 500;
- break;
-
- default:
- return -EINVAL;
- }
-
- // determine inversion dependant parameters
+ switch (p->u.qam.modulation) {
+ case QAM_16:
+ case QAM_32:
+ case QAM_64:
+ delay = 100;
+ sweeprate = 1500;
+ break;
+
+ case QAM_128:
+ delay = 150;
+ sweeprate = 1000;
+ break;
+
+ case QAM_256:
+ delay = 200;
+ sweeprate = 500;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ // determine inversion dependant parameters
inversion = p->inversion;
if (state->config->invert)
inversion = (inversion == INVERSION_ON) ? INVERSION_OFF : INVERSION_ON;
- carrieroffset = -330;
+ carrieroffset = -330;
switch (inversion) {
- case INVERSION_OFF:
- break;
+ case INVERSION_OFF:
+ break;
- case INVERSION_ON:
- sweeprate = -sweeprate;
- carrieroffset = -carrieroffset;
- break;
+ case INVERSION_ON:
+ sweeprate = -sweeprate;
+ carrieroffset = -carrieroffset;
+ break;
- default:
- return -EINVAL;
- }
+ default:
+ return -EINVAL;
+ }
stv0297_init(fe);
- state->config->pll_set(fe, p);
+ state->config->pll_set(fe, p);
/* clear software interrupts */
stv0297_writereg(state, 0x82, 0x0);
@@ -562,163 +546,163 @@ static int stv0297_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
stv0297_set_initialdemodfreq(state, 7250);
/* setup AGC */
- stv0297_writereg_mask(state, 0x43, 0x10, 0x00);
- stv0297_writereg(state, 0x41, 0x00);
- stv0297_writereg_mask(state, 0x42, 0x03, 0x01);
- stv0297_writereg_mask(state, 0x36, 0x60, 0x00);
- stv0297_writereg_mask(state, 0x36, 0x18, 0x00);
- stv0297_writereg_mask(state, 0x71, 0x80, 0x80);
- stv0297_writereg(state, 0x72, 0x00);
- stv0297_writereg(state, 0x73, 0x00);
- stv0297_writereg_mask(state, 0x74, 0x0F, 0x00);
- stv0297_writereg_mask(state, 0x43, 0x08, 0x00);
- stv0297_writereg_mask(state, 0x71, 0x80, 0x00);
+ stv0297_writereg_mask(state, 0x43, 0x10, 0x00);
+ stv0297_writereg(state, 0x41, 0x00);
+ stv0297_writereg_mask(state, 0x42, 0x03, 0x01);
+ stv0297_writereg_mask(state, 0x36, 0x60, 0x00);
+ stv0297_writereg_mask(state, 0x36, 0x18, 0x00);
+ stv0297_writereg_mask(state, 0x71, 0x80, 0x80);
+ stv0297_writereg(state, 0x72, 0x00);
+ stv0297_writereg(state, 0x73, 0x00);
+ stv0297_writereg_mask(state, 0x74, 0x0F, 0x00);
+ stv0297_writereg_mask(state, 0x43, 0x08, 0x00);
+ stv0297_writereg_mask(state, 0x71, 0x80, 0x00);
/* setup STL */
- stv0297_writereg_mask(state, 0x5a, 0x20, 0x20);
- stv0297_writereg_mask(state, 0x5b, 0x02, 0x02);
- stv0297_writereg_mask(state, 0x5b, 0x02, 0x00);
- stv0297_writereg_mask(state, 0x5b, 0x01, 0x00);
- stv0297_writereg_mask(state, 0x5a, 0x40, 0x40);
+ stv0297_writereg_mask(state, 0x5a, 0x20, 0x20);
+ stv0297_writereg_mask(state, 0x5b, 0x02, 0x02);
+ stv0297_writereg_mask(state, 0x5b, 0x02, 0x00);
+ stv0297_writereg_mask(state, 0x5b, 0x01, 0x00);
+ stv0297_writereg_mask(state, 0x5a, 0x40, 0x40);
/* disable frequency sweep */
- stv0297_writereg_mask(state, 0x6a, 0x01, 0x00);
+ stv0297_writereg_mask(state, 0x6a, 0x01, 0x00);
/* reset deinterleaver */
- stv0297_writereg_mask(state, 0x81, 0x01, 0x01);
- stv0297_writereg_mask(state, 0x81, 0x01, 0x00);
+ stv0297_writereg_mask(state, 0x81, 0x01, 0x01);
+ stv0297_writereg_mask(state, 0x81, 0x01, 0x00);
/* ??? */
- stv0297_writereg_mask(state, 0x83, 0x20, 0x20);
- stv0297_writereg_mask(state, 0x83, 0x20, 0x00);
+ stv0297_writereg_mask(state, 0x83, 0x20, 0x20);
+ stv0297_writereg_mask(state, 0x83, 0x20, 0x00);
/* reset equaliser */
- u_threshold = stv0297_readreg(state, 0x00) & 0xf;
- initial_u = stv0297_readreg(state, 0x01) >> 4;
- blind_u = stv0297_readreg(state, 0x01) & 0xf;
- stv0297_writereg_mask(state, 0x84, 0x01, 0x01);
- stv0297_writereg_mask(state, 0x84, 0x01, 0x00);
- stv0297_writereg_mask(state, 0x00, 0x0f, u_threshold);
- stv0297_writereg_mask(state, 0x01, 0xf0, initial_u << 4);
- stv0297_writereg_mask(state, 0x01, 0x0f, blind_u);
+ u_threshold = stv0297_readreg(state, 0x00) & 0xf;
+ initial_u = stv0297_readreg(state, 0x01) >> 4;
+ blind_u = stv0297_readreg(state, 0x01) & 0xf;
+ stv0297_writereg_mask(state, 0x84, 0x01, 0x01);
+ stv0297_writereg_mask(state, 0x84, 0x01, 0x00);
+ stv0297_writereg_mask(state, 0x00, 0x0f, u_threshold);
+ stv0297_writereg_mask(state, 0x01, 0xf0, initial_u << 4);
+ stv0297_writereg_mask(state, 0x01, 0x0f, blind_u);
/* data comes from internal A/D */
- stv0297_writereg_mask(state, 0x87, 0x80, 0x00);
+ stv0297_writereg_mask(state, 0x87, 0x80, 0x00);
/* clear phase registers */
- stv0297_writereg(state, 0x63, 0x00);
- stv0297_writereg(state, 0x64, 0x00);
- stv0297_writereg(state, 0x65, 0x00);
- stv0297_writereg(state, 0x66, 0x00);
- stv0297_writereg(state, 0x67, 0x00);
- stv0297_writereg(state, 0x68, 0x00);
- stv0297_writereg_mask(state, 0x69, 0x0f, 0x00);
+ stv0297_writereg(state, 0x63, 0x00);
+ stv0297_writereg(state, 0x64, 0x00);
+ stv0297_writereg(state, 0x65, 0x00);
+ stv0297_writereg(state, 0x66, 0x00);
+ stv0297_writereg(state, 0x67, 0x00);
+ stv0297_writereg(state, 0x68, 0x00);
+ stv0297_writereg_mask(state, 0x69, 0x0f, 0x00);
/* set parameters */
- stv0297_set_qam(state, p->u.qam.modulation);
- stv0297_set_symbolrate(state, p->u.qam.symbol_rate/1000);
+ stv0297_set_qam(state, p->u.qam.modulation);
+ stv0297_set_symbolrate(state, p->u.qam.symbol_rate / 1000);
stv0297_set_sweeprate(state, sweeprate, p->u.qam.symbol_rate / 1000);
- stv0297_set_carrieroffset(state, carrieroffset);
+ stv0297_set_carrieroffset(state, carrieroffset);
stv0297_set_inversion(state, inversion);
/* kick off lock */
- stv0297_writereg_mask(state, 0x88, 0x08, 0x08);
- stv0297_writereg_mask(state, 0x5a, 0x20, 0x00);
- stv0297_writereg_mask(state, 0x6a, 0x01, 0x01);
- stv0297_writereg_mask(state, 0x43, 0x40, 0x40);
- stv0297_writereg_mask(state, 0x5b, 0x30, 0x00);
- stv0297_writereg_mask(state, 0x03, 0x0c, 0x0c);
- stv0297_writereg_mask(state, 0x03, 0x03, 0x03);
- stv0297_writereg_mask(state, 0x43, 0x10, 0x10);
+ stv0297_writereg_mask(state, 0x88, 0x08, 0x08);
+ stv0297_writereg_mask(state, 0x5a, 0x20, 0x00);
+ stv0297_writereg_mask(state, 0x6a, 0x01, 0x01);
+ stv0297_writereg_mask(state, 0x43, 0x40, 0x40);
+ stv0297_writereg_mask(state, 0x5b, 0x30, 0x00);
+ stv0297_writereg_mask(state, 0x03, 0x0c, 0x0c);
+ stv0297_writereg_mask(state, 0x03, 0x03, 0x03);
+ stv0297_writereg_mask(state, 0x43, 0x10, 0x10);
/* wait for WGAGC lock */
- starttime = jiffies;
- timeout = jiffies + (200*HZ)/1000;
- while(time_before(jiffies, timeout)) {
- msleep(10);
+ starttime = jiffies;
+ timeout = jiffies + (200 * HZ) / 1000;
+ while (time_before(jiffies, timeout)) {
+ msleep(10);
if (stv0297_readreg(state, 0x43) & 0x08)
break;
- }
- if (time_after(jiffies, timeout)) {
- goto timeout;
- }
- msleep(20);
+ }
+ if (time_after(jiffies, timeout)) {
+ goto timeout;
+ }
+ msleep(20);
/* wait for equaliser partial convergence */
- timeout = jiffies + (50*HZ)/1000;
- while(time_before(jiffies, timeout)) {
- msleep(10);
+ timeout = jiffies + (50 * HZ) / 1000;
+ while (time_before(jiffies, timeout)) {
+ msleep(10);
- if (stv0297_readreg(state, 0x82) & 0x04) {
+ if (stv0297_readreg(state, 0x82) & 0x04) {
break;
- }
- }
+ }
+ }
if (time_after(jiffies, timeout)) {
- goto timeout;
- }
+ goto timeout;
+ }
/* wait for equaliser full convergence */
- timeout = jiffies + (delay*HZ)/1000;
- while(time_before(jiffies, timeout)) {
- msleep(10);
-
- if (stv0297_readreg(state, 0x82) & 0x08) {
- break;
- }
- }
- if (time_after(jiffies, timeout)) {
- goto timeout;
- }
+ timeout = jiffies + (delay * HZ) / 1000;
+ while (time_before(jiffies, timeout)) {
+ msleep(10);
+
+ if (stv0297_readreg(state, 0x82) & 0x08) {
+ break;
+ }
+ }
+ if (time_after(jiffies, timeout)) {
+ goto timeout;
+ }
/* disable sweep */
- stv0297_writereg_mask(state, 0x6a, 1, 0);
- stv0297_writereg_mask(state, 0x88, 8, 0);
+ stv0297_writereg_mask(state, 0x6a, 1, 0);
+ stv0297_writereg_mask(state, 0x88, 8, 0);
/* wait for main lock */
- timeout = jiffies + (20*HZ)/1000;
- while(time_before(jiffies, timeout)) {
- msleep(10);
-
- if (stv0297_readreg(state, 0xDF) & 0x80) {
- break;
- }
- }
- if (time_after(jiffies, timeout)) {
- goto timeout;
- }
- msleep(100);
+ timeout = jiffies + (20 * HZ) / 1000;
+ while (time_before(jiffies, timeout)) {
+ msleep(10);
+
+ if (stv0297_readreg(state, 0xDF) & 0x80) {
+ break;
+ }
+ }
+ if (time_after(jiffies, timeout)) {
+ goto timeout;
+ }
+ msleep(100);
/* is it still locked after that delay? */
- if (!(stv0297_readreg(state, 0xDF) & 0x80)) {
- goto timeout;
- }
+ if (!(stv0297_readreg(state, 0xDF) & 0x80)) {
+ goto timeout;
+ }
/* success!! */
- stv0297_writereg_mask(state, 0x5a, 0x40, 0x00);
- state->base_freq = p->frequency;
- return 0;
+ stv0297_writereg_mask(state, 0x5a, 0x40, 0x00);
+ state->base_freq = p->frequency;
+ return 0;
timeout:
- stv0297_writereg_mask(state, 0x6a, 0x01, 0x00);
- return 0;
+ stv0297_writereg_mask(state, 0x6a, 0x01, 0x00);
+ return 0;
}
-static int stv0297_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters * p)
+static int stv0297_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
{
- struct stv0297_state* state = (struct stv0297_state*) fe->demodulator_priv;
- int reg_00, reg_83;
+ struct stv0297_state *state = (struct stv0297_state *) fe->demodulator_priv;
+ int reg_00, reg_83;
- reg_00 = stv0297_readreg(state, 0x00);
- reg_83 = stv0297_readreg(state, 0x83);
+ reg_00 = stv0297_readreg(state, 0x00);
+ reg_83 = stv0297_readreg(state, 0x83);
p->frequency = state->base_freq;
- p->inversion = (reg_83 & 0x08) ? INVERSION_ON : INVERSION_OFF;
+ p->inversion = (reg_83 & 0x08) ? INVERSION_ON : INVERSION_OFF;
if (state->config->invert)
p->inversion = (p->inversion == INVERSION_ON) ? INVERSION_OFF : INVERSION_ON;
p->u.qam.symbol_rate = stv0297_get_symbolrate(state) * 1000;
p->u.qam.fec_inner = FEC_NONE;
- switch((reg_00 >> 4) & 0x7) {
+ switch ((reg_00 >> 4) & 0x7) {
case 0:
p->u.qam.modulation = QAM_16;
break;
@@ -734,77 +718,76 @@ static int stv0297_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
case 4:
p->u.qam.modulation = QAM_64;
break;
- }
+ }
- return 0;
+ return 0;
}
-static void stv0297_release(struct dvb_frontend* fe)
+static void stv0297_release(struct dvb_frontend *fe)
{
- struct stv0297_state* state = (struct stv0297_state*) fe->demodulator_priv;
- kfree(state);
+ struct stv0297_state *state = (struct stv0297_state *) fe->demodulator_priv;
+ kfree(state);
}
static struct dvb_frontend_ops stv0297_ops;
-struct dvb_frontend* stv0297_attach(const struct stv0297_config* config,
+struct dvb_frontend *stv0297_attach(const struct stv0297_config *config,
struct i2c_adapter *i2c, int pwm)
{
- struct stv0297_state* state = NULL;
+ struct stv0297_state *state = NULL;
- /* allocate memory for the internal state */
- state = (struct stv0297_state*) kmalloc(sizeof(struct stv0297_state), GFP_KERNEL);
+ /* allocate memory for the internal state */
+ state = (struct stv0297_state *) kmalloc(sizeof(struct stv0297_state), GFP_KERNEL);
if (state == NULL)
goto error;
- /* setup the state */
- state->config = config;
- state->i2c = i2c;
- memcpy(&state->ops, &stv0297_ops, sizeof(struct dvb_frontend_ops));
- state->base_freq = 0;
- state->pwm = pwm;
+ /* setup the state */
+ state->config = config;
+ state->i2c = i2c;
+ memcpy(&state->ops, &stv0297_ops, sizeof(struct dvb_frontend_ops));
+ state->base_freq = 0;
+ state->pwm = pwm;
- /* check if the demod is there */
+ /* check if the demod is there */
if ((stv0297_readreg(state, 0x80) & 0x70) != 0x20)
goto error;
- /* create dvb_frontend */
- state->frontend.ops = &state->ops;
- state->frontend.demodulator_priv = state;
- return &state->frontend;
+ /* create dvb_frontend */
+ state->frontend.ops = &state->ops;
+ state->frontend.demodulator_priv = state;
+ return &state->frontend;
error:
- if (state)
- kfree(state);
- return NULL;
+ kfree(state);
+ return NULL;
}
static struct dvb_frontend_ops stv0297_ops = {
- .info = {
- .name = "ST STV0297 DVB-C",
- .type = FE_QAM,
- .frequency_min = 64000000,
- .frequency_max = 1300000000,
- .frequency_stepsize = 62500,
- .symbol_rate_min = 870000,
- .symbol_rate_max = 11700000,
- .caps = FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 |
+ .info = {
+ .name = "ST STV0297 DVB-C",
+ .type = FE_QAM,
+ .frequency_min = 64000000,
+ .frequency_max = 1300000000,
+ .frequency_stepsize = 62500,
+ .symbol_rate_min = 870000,
+ .symbol_rate_max = 11700000,
+ .caps = FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 |
FE_CAN_QAM_128 | FE_CAN_QAM_256 | FE_CAN_FEC_AUTO},
- .release = stv0297_release,
+ .release = stv0297_release,
- .init = stv0297_init,
+ .init = stv0297_init,
.sleep = stv0297_sleep,
- .set_frontend = stv0297_set_frontend,
- .get_frontend = stv0297_get_frontend,
+ .set_frontend = stv0297_set_frontend,
+ .get_frontend = stv0297_get_frontend,
- .read_status = stv0297_read_status,
- .read_ber = stv0297_read_ber,
- .read_signal_strength = stv0297_read_signal_strength,
- .read_snr = stv0297_read_snr,
- .read_ucblocks = stv0297_read_ucblocks,
+ .read_status = stv0297_read_status,
+ .read_ber = stv0297_read_ber,
+ .read_signal_strength = stv0297_read_signal_strength,
+ .read_snr = stv0297_read_snr,
+ .read_ucblocks = stv0297_read_ucblocks,
};
MODULE_DESCRIPTION("ST STV0297 DVB-C Demodulator driver");
diff --git a/drivers/media/dvb/frontends/stv0299.c b/drivers/media/dvb/frontends/stv0299.c
index bf5de103142fa..15b40541b62d1 100644
--- a/drivers/media/dvb/frontends/stv0299.c
+++ b/drivers/media/dvb/frontends/stv0299.c
@@ -5,7 +5,7 @@
<ralph@convergence.de>,
<holger@convergence.de>,
<js@convergence.de>
-
+
Philips SU1278/SH
@@ -15,7 +15,7 @@
LG TDQF-S001F
Copyright (C) 2002 Felix Domke <tmbinc@elitedvb.net>
- & Andreas Oberritter <obi@linuxtv.org>
+ & Andreas Oberritter <obi@linuxtv.org>
Support for Samsung TBMU24112IMB used on Technisat SkyStar2 rev. 2.6B
@@ -40,7 +40,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
+*/
#include <linux/init.h>
#include <linux/kernel.h>
@@ -54,13 +54,9 @@
#include "stv0299.h"
struct stv0299_state {
-
struct i2c_adapter* i2c;
-
struct dvb_frontend_ops ops;
-
const struct stv0299_config* config;
-
struct dvb_frontend frontend;
u8 initialised:1;
@@ -88,7 +84,7 @@ static int stv0299_writeregI (struct stv0299_state* state, u8 reg, u8 data)
ret = i2c_transfer (state->i2c, &msg, 1);
- if (ret != 1)
+ if (ret != 1)
dprintk("%s: writereg error (reg == 0x%02x, val == 0x%02x, "
"ret == %i)\n", __FUNCTION__, reg, data, ret);
@@ -102,7 +98,6 @@ int stv0299_writereg (struct dvb_frontend* fe, u8 reg, u8 data)
return stv0299_writeregI(state, reg, data);
}
-
static u8 stv0299_readreg (struct stv0299_state* state, u8 reg)
{
int ret;
@@ -112,30 +107,28 @@ static u8 stv0299_readreg (struct stv0299_state* state, u8 reg)
{ .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } };
ret = i2c_transfer (state->i2c, msg, 2);
-
- if (ret != 2)
+
+ if (ret != 2)
dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n",
__FUNCTION__, reg, ret);
return b1[0];
}
-
static int stv0299_readregs (struct stv0299_state* state, u8 reg1, u8 *b, u8 len)
{
- int ret;
+ int ret;
struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = &reg1, .len = 1 },
{ .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b, .len = len } };
ret = i2c_transfer (state->i2c, msg, 2);
- if (ret != 2)
- dprintk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret);
+ if (ret != 2)
+ dprintk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret);
- return ret == 2 ? 0 : ret;
+ return ret == 2 ? 0 : ret;
}
-
static int stv0299_set_FEC (struct stv0299_state* state, fe_code_rate_t fec)
{
dprintk ("%s\n", __FUNCTION__);
@@ -169,9 +162,8 @@ static int stv0299_set_FEC (struct stv0299_state* state, fe_code_rate_t fec)
{
return -EINVAL;
}
+ }
}
-}
-
static fe_code_rate_t stv0299_get_fec (struct stv0299_state* state)
{
@@ -190,7 +182,6 @@ static fe_code_rate_t stv0299_get_fec (struct stv0299_state* state)
return fec_tab [index];
}
-
static int stv0299_wait_diseqc_fifo (struct stv0299_state* state, int timeout)
{
unsigned long start = jiffies;
@@ -208,7 +199,6 @@ static int stv0299_wait_diseqc_fifo (struct stv0299_state* state, int timeout)
return 0;
}
-
static int stv0299_wait_diseqc_idle (struct stv0299_state* state, int timeout)
{
unsigned long start = jiffies;
@@ -244,7 +234,6 @@ static int stv0299_set_symbolrate (struct dvb_frontend* fe, u32 srate)
return state->config->set_symbol_rate(fe, srate, ratio);
}
-
static int stv0299_get_symbolrate (struct stv0299_state* state)
{
u32 Mclk = state->config->mclk / 4096L;
@@ -277,21 +266,8 @@ static int stv0299_get_symbolrate (struct stv0299_state* state)
return srate;
}
-
-
-
-
-
-
-
-
-
-
-
-
-
static int stv0299_send_diseqc_msg (struct dvb_frontend* fe,
- struct dvb_diseqc_master_cmd *m)
+ struct dvb_diseqc_master_cmd *m)
{
struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv;
u8 val;
@@ -321,7 +297,6 @@ static int stv0299_send_diseqc_msg (struct dvb_frontend* fe,
return 0;
}
-
static int stv0299_send_diseqc_burst (struct dvb_frontend* fe, fe_sec_mini_cmd_t burst)
{
struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv;
@@ -349,7 +324,6 @@ static int stv0299_send_diseqc_burst (struct dvb_frontend* fe, fe_sec_mini_cmd_t
return 0;
}
-
static int stv0299_set_tone (struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
{
struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv;
@@ -372,7 +346,6 @@ static int stv0299_set_tone (struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
}
}
-
static int stv0299_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltage)
{
struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv;
@@ -380,7 +353,7 @@ static int stv0299_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltag
u8 reg0x0c;
dprintk("%s: %s\n", __FUNCTION__,
- voltage == SEC_VOLTAGE_13 ? "SEC_VOLTAGE_13" :
+ voltage == SEC_VOLTAGE_13 ? "SEC_VOLTAGE_13" :
voltage == SEC_VOLTAGE_18 ? "SEC_VOLTAGE_18" : "??");
reg0x08 = stv0299_readreg (state, 0x08);
@@ -395,7 +368,7 @@ static int stv0299_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltag
stv0299_writeregI (state, 0x0c, 0x00); /* LNB power off! */
return stv0299_writeregI (state, 0x08, 0x00); /* LNB power off! */
}
-
+
stv0299_writeregI (state, 0x08, (reg0x08 & 0x3f) | (state->config->lock_output << 6));
switch (voltage) {
@@ -412,7 +385,6 @@ 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)
{
u8 last = 1;
@@ -433,9 +405,7 @@ static int stv0299_send_legacy_dish_cmd(struct dvb_frontend* fe, u32 cmd)
for (i=0; i<9; i++) {
if((cmd & 0x01) != last) {
- stv0299_set_voltage(fe,
- last ? SEC_VOLTAGE_13 :
- SEC_VOLTAGE_18);
+ stv0299_set_voltage(fe, last ? SEC_VOLTAGE_13 : SEC_VOLTAGE_18);
last = (last) ? 0 : 1;
}
@@ -448,7 +418,6 @@ static int stv0299_send_legacy_dish_cmd(struct dvb_frontend* fe, u32 cmd)
return 0;
}
-
static int stv0299_init (struct dvb_frontend* fe)
{
struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv;
@@ -468,34 +437,33 @@ static int stv0299_init (struct dvb_frontend* fe)
return 0;
}
-
static int stv0299_read_status(struct dvb_frontend* fe, fe_status_t* status)
- {
+{
struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv;
u8 signal = 0xff - stv0299_readreg (state, 0x18);
u8 sync = stv0299_readreg (state, 0x1b);
- dprintk ("%s : FE_READ_STATUS : VSTATUS: 0x%02x\n", __FUNCTION__, sync);
- *status = 0;
+ dprintk ("%s : FE_READ_STATUS : VSTATUS: 0x%02x\n", __FUNCTION__, sync);
+ *status = 0;
- if (signal > 10)
- *status |= FE_HAS_SIGNAL;
+ if (signal > 10)
+ *status |= FE_HAS_SIGNAL;
- if (sync & 0x80)
- *status |= FE_HAS_CARRIER;
+ if (sync & 0x80)
+ *status |= FE_HAS_CARRIER;
- if (sync & 0x10)
- *status |= FE_HAS_VITERBI;
+ if (sync & 0x10)
+ *status |= FE_HAS_VITERBI;
- if (sync & 0x08)
- *status |= FE_HAS_SYNC;
+ if (sync & 0x08)
+ *status |= FE_HAS_SYNC;
- if ((sync & 0x98) == 0x98)
- *status |= FE_HAS_LOCK;
+ if ((sync & 0x98) == 0x98)
+ *status |= FE_HAS_LOCK;
return 0;
- }
+}
static int stv0299_read_ber(struct dvb_frontend* fe, u32* ber)
{
@@ -505,27 +473,27 @@ static int stv0299_read_ber(struct dvb_frontend* fe, u32* ber)
*ber = (stv0299_readreg (state, 0x1d) << 8) | stv0299_readreg (state, 0x1e);
return 0;
- }
+}
static int stv0299_read_signal_strength(struct dvb_frontend* fe, u16* strength)
- {
+{
struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv;
s32 signal = 0xffff - ((stv0299_readreg (state, 0x18) << 8)
| stv0299_readreg (state, 0x19));
- dprintk ("%s : FE_READ_SIGNAL_STRENGTH : AGC2I: 0x%02x%02x, signal=0x%04x\n", __FUNCTION__,
+ dprintk ("%s : FE_READ_SIGNAL_STRENGTH : AGC2I: 0x%02x%02x, signal=0x%04x\n", __FUNCTION__,
stv0299_readreg (state, 0x18),
stv0299_readreg (state, 0x19), (int) signal);
- signal = signal * 5 / 4;
+ signal = signal * 5 / 4;
*strength = (signal > 0xffff) ? 0xffff : (signal < 0) ? 0 : signal;
return 0;
- }
+}
static int stv0299_read_snr(struct dvb_frontend* fe, u16* snr)
- {
+{
struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv;
s32 xsnr = 0xffff - ((stv0299_readreg (state, 0x24) << 8)
@@ -549,40 +517,40 @@ static int stv0299_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
static int stv0299_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters * p)
{
struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv;
- int invval = 0;
+ int invval = 0;
- dprintk ("%s : FE_SET_FRONTEND\n", __FUNCTION__);
+ dprintk ("%s : FE_SET_FRONTEND\n", __FUNCTION__);
- // set the inversion
- if (p->inversion == INVERSION_OFF) invval = 0;
- else if (p->inversion == INVERSION_ON) invval = 1;
- else {
- printk("stv0299 does not support auto-inversion\n");
- return -EINVAL;
- }
+ // set the inversion
+ if (p->inversion == INVERSION_OFF) invval = 0;
+ else if (p->inversion == INVERSION_ON) invval = 1;
+ else {
+ printk("stv0299 does not support auto-inversion\n");
+ return -EINVAL;
+ }
if (state->config->invert) invval = (~invval) & 1;
stv0299_writeregI(state, 0x0c, (stv0299_readreg(state, 0x0c) & 0xfe) | invval);
if (state->config->enhanced_tuning) {
- /* check if we should do a finetune */
- int frequency_delta = p->frequency - state->tuner_frequency;
- int minmax = p->u.qpsk.symbol_rate / 2000;
- if (minmax < 5000) minmax = 5000;
-
- if ((frequency_delta > -minmax) && (frequency_delta < minmax) && (frequency_delta != 0) &&
- (state->fec_inner == p->u.qpsk.fec_inner) &&
- (state->symbol_rate == p->u.qpsk.symbol_rate)) {
+ /* check if we should do a finetune */
+ int frequency_delta = p->frequency - state->tuner_frequency;
+ int minmax = p->u.qpsk.symbol_rate / 2000;
+ if (minmax < 5000) minmax = 5000;
+
+ if ((frequency_delta > -minmax) && (frequency_delta < minmax) && (frequency_delta != 0) &&
+ (state->fec_inner == p->u.qpsk.fec_inner) &&
+ (state->symbol_rate == p->u.qpsk.symbol_rate)) {
int Drot_freq = (frequency_delta << 16) / (state->config->mclk / 1000);
- // zap the derotator registers first
+ // zap the derotator registers first
stv0299_writeregI(state, 0x22, 0x00);
stv0299_writeregI(state, 0x23, 0x00);
- // now set them as we want
+ // now set them as we want
stv0299_writeregI(state, 0x22, Drot_freq >> 8);
stv0299_writeregI(state, 0x23, Drot_freq);
- } else {
- /* A "normal" tune is requested */
+ } else {
+ /* A "normal" tune is requested */
stv0299_writeregI(state, 0x05, 0xb5); /* enable i2c repeater on stv0299 */
state->config->pll_set(fe, p);
stv0299_writeregI(state, 0x05, 0x35); /* disable i2c repeater on stv0299 */
@@ -605,39 +573,39 @@ static int stv0299_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
stv0299_writeregI(state, 0x23, 0x00);
stv0299_readreg (state, 0x23);
stv0299_writeregI(state, 0x12, 0xb9);
- }
+ }
- state->tuner_frequency = p->frequency;
- state->fec_inner = p->u.qpsk.fec_inner;
- state->symbol_rate = p->u.qpsk.symbol_rate;
+ state->tuner_frequency = p->frequency;
+ state->fec_inner = p->u.qpsk.fec_inner;
+ state->symbol_rate = p->u.qpsk.symbol_rate;
return 0;
- }
+}
static int stv0299_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters * p)
- {
+{
struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv;
- s32 derot_freq;
- int invval;
+ s32 derot_freq;
+ int invval;
derot_freq = (s32)(s16) ((stv0299_readreg (state, 0x22) << 8)
| stv0299_readreg (state, 0x23));
derot_freq *= (state->config->mclk >> 16);
- derot_freq += 500;
- derot_freq /= 1000;
+ derot_freq += 500;
+ derot_freq /= 1000;
- p->frequency += derot_freq;
+ p->frequency += derot_freq;
invval = stv0299_readreg (state, 0x0c) & 1;
if (state->config->invert) invval = (~invval) & 1;
- p->inversion = invval ? INVERSION_ON : INVERSION_OFF;
+ p->inversion = invval ? INVERSION_ON : INVERSION_OFF;
p->u.qpsk.fec_inner = stv0299_get_fec (state);
p->u.qpsk.symbol_rate = stv0299_get_symbolrate (state);
return 0;
- }
+}
static int stv0299_sleep(struct dvb_frontend* fe)
{
@@ -650,22 +618,22 @@ static int stv0299_sleep(struct dvb_frontend* fe)
}
static int stv0299_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings)
- {
+{
struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv;
fesettings->min_delay_ms = state->config->min_delay_ms;
- if (fesettings->parameters.u.qpsk.symbol_rate < 10000000) {
- fesettings->step_size = fesettings->parameters.u.qpsk.symbol_rate / 32000;
- fesettings->max_drift = 5000;
- } else {
- fesettings->step_size = fesettings->parameters.u.qpsk.symbol_rate / 16000;
- fesettings->max_drift = fesettings->parameters.u.qpsk.symbol_rate / 2000;
- }
+ if (fesettings->parameters.u.qpsk.symbol_rate < 10000000) {
+ fesettings->step_size = fesettings->parameters.u.qpsk.symbol_rate / 32000;
+ fesettings->max_drift = 5000;
+ } else {
+ fesettings->step_size = fesettings->parameters.u.qpsk.symbol_rate / 16000;
+ fesettings->max_drift = fesettings->parameters.u.qpsk.symbol_rate / 2000;
+ }
return 0;
}
static void stv0299_release(struct dvb_frontend* fe)
- {
+{
struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv;
kfree(state);
}
@@ -677,7 +645,7 @@ struct dvb_frontend* stv0299_attach(const struct stv0299_config* config,
{
struct stv0299_state* state = NULL;
int id;
-
+
/* allocate memory for the internal state */
state = (struct stv0299_state*) kmalloc(sizeof(struct stv0299_state), GFP_KERNEL);
if (state == NULL) goto error;
@@ -707,7 +675,7 @@ struct dvb_frontend* stv0299_attach(const struct stv0299_config* config,
return &state->frontend;
error:
- if (state) kfree(state);
+ kfree(state);
return NULL;
}
diff --git a/drivers/media/dvb/frontends/tda10021.c b/drivers/media/dvb/frontends/tda10021.c
index 40ab6292b7328..4e40d95ee95da 100644
--- a/drivers/media/dvb/frontends/tda10021.c
+++ b/drivers/media/dvb/frontends/tda10021.c
@@ -35,14 +35,10 @@
struct tda10021_state {
-
struct i2c_adapter* i2c;
-
struct dvb_frontend_ops ops;
-
/* configuration settings */
const struct tda10021_config* config;
-
struct dvb_frontend frontend;
u8 pwm;
@@ -65,12 +61,12 @@ static int verbose;
#define FIN (XIN >> 4)
-int tda10021_inittab_size = 0x40;
+static int tda10021_inittab_size = 0x40;
static u8 tda10021_inittab[0x40]=
{
0x73, 0x6a, 0x23, 0x0a, 0x02, 0x37, 0x77, 0x1a,
0x37, 0x6a, 0x17, 0x8a, 0x1e, 0x86, 0x43, 0x40,
- 0xb8, 0x3f, 0xa1, 0x00, 0xcd, 0x01, 0x00, 0xff,
+ 0xb8, 0x3f, 0xa0, 0x00, 0xcd, 0x01, 0x00, 0xff,
0x11, 0x00, 0x7c, 0x31, 0x30, 0x20, 0x00, 0x00,
0x02, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x00, 0x00,
0x07, 0x00, 0x33, 0x11, 0x0d, 0x95, 0x08, 0x58,
@@ -94,7 +90,6 @@ static int tda10021_writereg (struct tda10021_state* state, u8 reg, u8 data)
return (ret != 1) ? -EREMOTEIO : 0;
}
-
static u8 tda10021_readreg (struct tda10021_state* state, u8 reg)
{
u8 b0 [] = { reg };
@@ -208,15 +203,6 @@ static int tda10021_set_symbolrate (struct tda10021_state* state, u32 symbolrate
return 0;
}
-
-
-
-
-
-
-
-
-
static int tda10021_init (struct dvb_frontend *fe)
{
struct tda10021_state* state = (struct tda10021_state*) fe->demodulator_priv;
@@ -320,8 +306,8 @@ static int tda10021_read_ber(struct dvb_frontend* fe, u32* ber)
struct tda10021_state* state = (struct tda10021_state*) fe->demodulator_priv;
u32 _ber = tda10021_readreg(state, 0x14) |
- (tda10021_readreg(state, 0x15) << 8) |
- ((tda10021_readreg(state, 0x16) & 0x0f) << 16);
+ (tda10021_readreg(state, 0x15) << 8) |
+ ((tda10021_readreg(state, 0x16) & 0x0f) << 16);
*ber = 10 * _ber;
return 0;
@@ -434,7 +420,7 @@ struct dvb_frontend* tda10021_attach(const struct tda10021_config* config,
return &state->frontend;
error:
- if (state) kfree(state);
+ kfree(state);
return NULL;
}
diff --git a/drivers/media/dvb/frontends/tda10021.h b/drivers/media/dvb/frontends/tda10021.h
index a837c77b8be27..7d6a51ce291e1 100644
--- a/drivers/media/dvb/frontends/tda10021.h
+++ b/drivers/media/dvb/frontends/tda10021.h
@@ -37,7 +37,6 @@ struct tda10021_config
};
extern struct dvb_frontend* tda10021_attach(const struct tda10021_config* config,
- struct i2c_adapter* i2c,
- u8 pwm);
+ struct i2c_adapter* i2c, u8 pwm);
#endif // TDA10021_H
diff --git a/drivers/media/dvb/frontends/tda1004x.c b/drivers/media/dvb/frontends/tda1004x.c
index 1e38162c2ecd2..687ad9cf3384b 100644
--- a/drivers/media/dvb/frontends/tda1004x.c
+++ b/drivers/media/dvb/frontends/tda1004x.c
@@ -39,19 +39,14 @@
#define TDA1004X_DEMOD_TDA10046 1
-struct tda1004x_state
-{
+struct tda1004x_state {
struct i2c_adapter* i2c;
-
struct dvb_frontend_ops ops;
-
const struct tda1004x_config* config;
-
struct dvb_frontend frontend;
/* private demod data */
u8 initialised:1;
-
u8 demod_type;
};
@@ -347,7 +342,6 @@ static int tda1004x_check_upload_ok(struct tda1004x_state *state, u8 dspVersion)
return 0;
}
-
static int tda10045_fwupload(struct dvb_frontend* fe)
{
struct tda1004x_state* state = fe->demodulator_priv;
@@ -359,11 +353,11 @@ static int tda10045_fwupload(struct dvb_frontend* fe)
if (tda1004x_check_upload_ok(state, 0x2c) == 0) return 0;
/* request the firmware, this will block until someone uploads it */
- printk("tda1004x: waiting for firmware upload...\n");
+ printk("tda1004x: waiting for firmware upload (%s)...\n", TDA10045_DEFAULT_FIRMWARE);
ret = state->config->request_firmware(fe, &fw, TDA10045_DEFAULT_FIRMWARE);
if (ret) {
printk("tda1004x: no firmware upload (timeout or file not found?)\n");
- return ret;
+ return ret;
}
/* reset chip */
@@ -378,6 +372,7 @@ static int tda10045_fwupload(struct dvb_frontend* fe)
ret = tda1004x_do_upload(state, fw->data, fw->size, TDA10045H_FWPAGE, TDA10045H_CODE_IN);
if (ret)
return ret;
+ printk("tda1004x: firmware upload complete\n");
/* wait for DSP to initialise */
/* DSPREADY doesn't seem to work on the TDA10045H */
@@ -402,11 +397,11 @@ static int tda10046_fwupload(struct dvb_frontend* fe)
if (tda1004x_check_upload_ok(state, 0x20) == 0) return 0;
/* request the firmware, this will block until someone uploads it */
- printk("tda1004x: waiting for firmware upload...\n");
+ printk("tda1004x: waiting for firmware upload (%s)...\n", TDA10046_DEFAULT_FIRMWARE);
ret = state->config->request_firmware(fe, &fw, TDA10046_DEFAULT_FIRMWARE);
if (ret) {
printk("tda1004x: no firmware upload (timeout or file not found?)\n");
- return ret;
+ return ret;
}
/* set parameters */
@@ -420,6 +415,7 @@ static int tda10046_fwupload(struct dvb_frontend* fe)
ret = tda1004x_do_upload(state, fw->data, fw->size, TDA10046H_CODE_CPT, TDA10046H_CODE_IN);
if (ret)
return ret;
+ printk("tda1004x: firmware upload complete\n");
/* wait for DSP to initialise */
timeout = jiffies + HZ;
@@ -474,29 +470,12 @@ static int tda1004x_decode_fec(int tdafec)
return -1;
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
int tda1004x_write_byte(struct dvb_frontend* fe, int reg, int data)
{
struct tda1004x_state* state = fe->demodulator_priv;
return tda1004x_write_byteI(state, reg, data);
- }
+}
static int tda10045_init(struct dvb_frontend* fe)
{
@@ -509,7 +488,7 @@ static int tda10045_init(struct dvb_frontend* fe)
if (tda10045_fwupload(fe)) {
printk("tda1004x: firmware upload failed\n");
return -EIO;
- }
+ }
tda1004x_write_mask(state, TDA1004X_CONFADC1, 0x10, 0); // wake up the ADC
@@ -537,7 +516,7 @@ static int tda10045_init(struct dvb_frontend* fe)
state->initialised = 1;
return 0;
- }
+}
static int tda10046_init(struct dvb_frontend* fe)
{
@@ -548,8 +527,8 @@ static int tda10046_init(struct dvb_frontend* fe)
if (tda10046_fwupload(fe)) {
printk("tda1004x: firmware upload failed\n");
- return -EIO;
- }
+ return -EIO;
+ }
tda1004x_write_mask(state, TDA1004X_CONFC4, 1, 0); // wake up the chip
@@ -623,9 +602,9 @@ static int tda1004x_set_fe(struct dvb_frontend* fe,
// Hardcoded to use auto as much as possible on the TDA10045 as it
// is very unreliable if AUTO mode is _not_ used.
if (state->demod_type == TDA1004X_DEMOD_TDA10045) {
- fe_params->u.ofdm.code_rate_HP = FEC_AUTO;
- fe_params->u.ofdm.guard_interval = GUARD_INTERVAL_AUTO;
- fe_params->u.ofdm.transmission_mode = TRANSMISSION_MODE_AUTO;
+ fe_params->u.ofdm.code_rate_HP = FEC_AUTO;
+ fe_params->u.ofdm.guard_interval = GUARD_INTERVAL_AUTO;
+ fe_params->u.ofdm.transmission_mode = TRANSMISSION_MODE_AUTO;
}
// Set standard params.. or put them to auto
@@ -1066,30 +1045,30 @@ static int tda1004x_sleep(struct dvb_frontend* fe)
switch(state->demod_type) {
case TDA1004X_DEMOD_TDA10045:
tda1004x_write_mask(state, TDA1004X_CONFADC1, 0x10, 0x10);
- break;
+ break;
case TDA1004X_DEMOD_TDA10046:
tda1004x_write_mask(state, TDA1004X_CONFC4, 1, 1);
- break;
- }
+ break;
+ }
state->initialised = 0;
- return 0;
- }
+ return 0;
+}
static int tda1004x_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings)
- {
- fesettings->min_delay_ms = 800;
- fesettings->step_size = 166667;
- fesettings->max_drift = 166667*2;
- return 0;
- }
+{
+ fesettings->min_delay_ms = 800;
+ fesettings->step_size = 166667;
+ fesettings->max_drift = 166667*2;
+ return 0;
+}
static void tda1004x_release(struct dvb_frontend* fe)
{
struct tda1004x_state* state = (struct tda1004x_state*) fe->demodulator_priv;
kfree(state);
- }
+}
static struct dvb_frontend_ops tda10045_ops;
@@ -1118,9 +1097,9 @@ struct dvb_frontend* tda10045_attach(const struct tda1004x_config* config,
return &state->frontend;
error:
- if (state) kfree(state);
+ kfree(state);
return NULL;
- }
+}
static struct dvb_frontend_ops tda10046_ops;
@@ -1151,7 +1130,7 @@ struct dvb_frontend* tda10046_attach(const struct tda1004x_config* config,
error:
if (state) kfree(state);
return NULL;
- }
+}
static struct dvb_frontend_ops tda10045_ops = {
diff --git a/drivers/media/dvb/frontends/tda8083.c b/drivers/media/dvb/frontends/tda8083.c
index 03c4366e18895..da82e90d6d136 100644
--- a/drivers/media/dvb/frontends/tda8083.c
+++ b/drivers/media/dvb/frontends/tda8083.c
@@ -35,14 +35,10 @@
struct tda8083_state {
-
struct i2c_adapter* i2c;
-
struct dvb_frontend_ops ops;
-
/* configuration settings */
const struct tda8083_config* config;
-
struct dvb_frontend frontend;
};
@@ -78,7 +74,6 @@ static int tda8083_writereg (struct tda8083_state* state, u8 reg, u8 data)
return (ret != 1) ? -1 : 0;
}
-
static int tda8083_readregs (struct tda8083_state* state, u8 reg1, u8 *b, u8 len)
{
int ret;
@@ -94,7 +89,6 @@ static int tda8083_readregs (struct tda8083_state* state, u8 reg1, u8 *b, u8 len
return ret == 2 ? 0 : -1;
}
-
static inline u8 tda8083_readreg (struct tda8083_state* state, u8 reg)
{
u8 val;
@@ -104,8 +98,6 @@ static inline u8 tda8083_readreg (struct tda8083_state* state, u8 reg)
return val;
}
-
-
static int tda8083_set_inversion (struct tda8083_state* state, fe_spectral_inversion_t inversion)
{
/* XXX FIXME: implement other modes than FEC_AUTO */
@@ -115,7 +107,6 @@ static int tda8083_set_inversion (struct tda8083_state* state, fe_spectral_inver
return -EINVAL;
}
-
static int tda8083_set_fec (struct tda8083_state* state, fe_code_rate_t fec)
{
if (fec == FEC_AUTO)
@@ -127,7 +118,6 @@ static int tda8083_set_fec (struct tda8083_state* state, fe_code_rate_t fec)
return -EINVAL;
}
-
static fe_code_rate_t tda8083_get_fec (struct tda8083_state* state)
{
u8 index;
@@ -139,7 +129,6 @@ static fe_code_rate_t tda8083_get_fec (struct tda8083_state* state)
return fec_tab [index];
}
-
static int tda8083_set_symbolrate (struct tda8083_state* state, u32 srate)
{
u32 ratio;
@@ -179,7 +168,6 @@ static int tda8083_set_symbolrate (struct tda8083_state* state, u32 srate)
return 1;
}
-
static void tda8083_wait_diseqc_fifo (struct tda8083_state* state, int timeout)
{
unsigned long start = jiffies;
@@ -205,7 +193,6 @@ static int tda8083_set_tone (struct tda8083_state* state, fe_sec_tone_mode_t ton
};
}
-
static int tda8083_set_voltage (struct tda8083_state* state, fe_sec_voltage_t voltage)
{
switch (voltage) {
@@ -236,27 +223,6 @@ static int tda8083_send_diseqc_burst (struct tda8083_state* state, fe_sec_mini_c
return 0;
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
static int tda8083_send_diseqc_msg (struct dvb_frontend* fe,
struct dvb_diseqc_master_cmd *m)
{
@@ -439,7 +405,7 @@ struct dvb_frontend* tda8083_attach(const struct tda8083_config* config,
return &state->frontend;
error:
- if (state) kfree(state);
+ kfree(state);
return NULL;
}
@@ -475,9 +441,9 @@ static struct dvb_frontend_ops tda8083_ops = {
.read_snr = tda8083_read_snr,
.diseqc_send_master_cmd = tda8083_send_diseqc_msg,
- .diseqc_send_burst = tda8083_diseqc_send_burst,
- .set_tone = tda8083_diseqc_set_tone,
- .set_voltage = tda8083_diseqc_set_voltage,
+ .diseqc_send_burst = tda8083_diseqc_send_burst,
+ .set_tone = tda8083_diseqc_set_tone,
+ .set_voltage = tda8083_diseqc_set_voltage,
};
module_param(debug, int, 0644);
diff --git a/drivers/media/dvb/frontends/tda80xx.c b/drivers/media/dvb/frontends/tda80xx.c
index da352fc7c3aa6..c99632114283d 100644
--- a/drivers/media/dvb/frontends/tda80xx.c
+++ b/drivers/media/dvb/frontends/tda80xx.c
@@ -204,8 +204,8 @@ static int tda80xx_set_parameters(struct tda80xx_state* state,
* r = k * clk / symbol_rate
*
* k: 2^21 for caa 0..3,
- * 2^20 for caa 4..5,
- * 2^19 for caa 6..7
+ * 2^20 for caa 4..5,
+ * 2^19 for caa 6..7
*/
if (symbol_rate <= (clk * 3) / 32)
k = (1 << 19);
@@ -422,7 +422,7 @@ static int tda8044_init(struct dvb_frontend* fe)
tda80xx_write(state, 0x00, tda8044_inittab_post, sizeof(tda8044_inittab_post));
if (state->config->pll_init) {
- tda80xx_writereg(state, 0x1c, 0x80);
+ tda80xx_writereg(state, 0x1c, 0x80);
state->config->pll_init(fe);
tda80xx_writereg(state, 0x1c, 0x00);
}
@@ -437,7 +437,7 @@ static int tda8083_init(struct dvb_frontend* fe)
tda80xx_write(state, 0x00, tda8083_inittab, sizeof(tda8083_inittab));
if (state->config->pll_init) {
- tda80xx_writereg(state, 0x1c, 0x80);
+ tda80xx_writereg(state, 0x1c, 0x80);
state->config->pll_init(fe);
tda80xx_writereg(state, 0x1c, 0x00);
}
@@ -445,21 +445,6 @@ static int tda8083_init(struct dvb_frontend* fe)
return 0;
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
static int tda80xx_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
{
struct tda80xx_state* state = (struct tda80xx_state*) fe->demodulator_priv;
@@ -492,7 +477,7 @@ static int tda80xx_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
static int tda80xx_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd *cmd)
{
- struct tda80xx_state* state = (struct tda80xx_state*) fe->demodulator_priv;
+ struct tda80xx_state* state = (struct tda80xx_state*) fe->demodulator_priv;
if (cmd->msg_len > 6)
return -EINVAL;
@@ -536,7 +521,7 @@ static int tda80xx_sleep(struct dvb_frontend* fe)
static int tda80xx_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
{
- struct tda80xx_state* state = (struct tda80xx_state*) fe->demodulator_priv;
+ struct tda80xx_state* state = (struct tda80xx_state*) fe->demodulator_priv;
tda80xx_writereg(state, 0x1c, 0x80);
state->config->pll_set(fe, p);
@@ -698,7 +683,7 @@ struct dvb_frontend* tda80xx_attach(const struct tda80xx_config* config,
return &state->frontend;
error:
- if (state) kfree(state);
+ kfree(state);
return NULL;
}
@@ -735,9 +720,9 @@ static struct dvb_frontend_ops tda80xx_ops = {
.read_ucblocks = tda80xx_read_ucblocks,
.diseqc_send_master_cmd = tda80xx_send_diseqc_msg,
- .diseqc_send_burst = tda80xx_send_diseqc_burst,
- .set_tone = tda80xx_set_tone,
- .set_voltage = tda80xx_set_voltage,
+ .diseqc_send_burst = tda80xx_send_diseqc_burst,
+ .set_tone = tda80xx_set_tone,
+ .set_voltage = tda80xx_set_voltage,
};
module_param(debug, int, 0644);
diff --git a/drivers/media/dvb/frontends/ves1820.c b/drivers/media/dvb/frontends/ves1820.c
index 3d8e7804c580b..9c0d23e1d9e5a 100644
--- a/drivers/media/dvb/frontends/ves1820.c
+++ b/drivers/media/dvb/frontends/ves1820.c
@@ -1,4 +1,4 @@
-/*
+/*
VES1820 - Single Chip Cable Channel Receiver driver module
Copyright (C) 1999 Convergence Integrated Media GmbH <ralph@convergence.de>
@@ -16,7 +16,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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
+*/
#include <linux/config.h>
#include <linux/delay.h>
@@ -34,14 +34,10 @@
struct ves1820_state {
-
- struct i2c_adapter *i2c;
-
+ struct i2c_adapter* i2c;
struct dvb_frontend_ops ops;
-
/* configuration settings */
const struct ves1820_config* config;
-
struct dvb_frontend frontend;
/* private demodulator data */
@@ -64,9 +60,9 @@ static u8 ves1820_inittab[] = {
static int ves1820_writereg(struct ves1820_state *state, u8 reg, u8 data)
{
- u8 buf[] = { 0x00, reg, data };
+ u8 buf[] = { 0x00, reg, data };
struct i2c_msg msg = {.addr = state->config->demod_address,.flags = 0,.buf = buf,.len = 3 };
- int ret;
+ int ret;
ret = i2c_transfer(state->i2c, &msg, 1);
@@ -80,8 +76,8 @@ static int ves1820_writereg(struct ves1820_state *state, u8 reg, u8 data)
static u8 ves1820_readreg(struct ves1820_state *state, u8 reg)
{
- u8 b0 [] = { 0x00, reg };
- u8 b1 [] = { 0 };
+ u8 b0[] = { 0x00, reg };
+ u8 b1[] = { 0 };
struct i2c_msg msg[] = {
{.addr = state->config->demod_address,.flags = 0,.buf = b0,.len = 2},
{.addr = state->config->demod_address,.flags = I2C_M_RD,.buf = b1,.len = 1}
@@ -97,23 +93,20 @@ static u8 ves1820_readreg(struct ves1820_state *state, u8 reg)
return b1[0];
}
-
static int ves1820_setup_reg0(struct ves1820_state *state, u8 reg0, fe_spectral_inversion_t inversion)
{
reg0 |= state->reg0 & 0x62;
-
+
if (INVERSION_ON == inversion) {
if (!state->config->invert) reg0 |= 0x20;
else reg0 &= ~0x20;
-
} else if (INVERSION_OFF == inversion) {
-
- if (!state->config->invert) reg0 &= ~0x20;
+ if (!state->config->invert) reg0 &= ~0x20;
else reg0 |= 0x20;
}
- ves1820_writereg(state, 0x00, reg0 & 0xfe);
- ves1820_writereg(state, 0x00, reg0 | 0x01);
+ ves1820_writereg(state, 0x00, reg0 & 0xfe);
+ ves1820_writereg(state, 0x00, reg0 | 0x01);
state->reg0 = reg0;
@@ -122,10 +115,10 @@ static int ves1820_setup_reg0(struct ves1820_state *state, u8 reg0, fe_spectral_
static int ves1820_set_symbolrate(struct ves1820_state *state, u32 symbolrate)
{
- s32 BDR;
- s32 BDRI;
- s16 SFIL=0;
- u16 NDEC = 0;
+ s32 BDR;
+ s32 BDRI;
+ s16 SFIL = 0;
+ u16 NDEC = 0;
u32 ratio;
u32 fin;
u32 tmp;
@@ -136,7 +129,7 @@ static int ves1820_set_symbolrate(struct ves1820_state *state, u32 symbolrate)
symbolrate = state->config->xin / 2;
if (symbolrate < 500000)
- symbolrate = 500000;
+ symbolrate = 500000;
if (symbolrate < state->config->xin / 16)
NDEC = 1;
@@ -168,24 +161,24 @@ static int ves1820_set_symbolrate(struct ves1820_state *state, u32 symbolrate)
fptmp = fpxin; do_div(fptmp, 984);
if (symbolrate < fptmp);
SFIL = 1;
-
+
fin = state->config->xin >> 4;
- symbolrate <<= NDEC;
+ symbolrate <<= NDEC;
ratio = (symbolrate << 4) / fin;
tmp = ((symbolrate << 4) % fin) << 8;
ratio = (ratio << 8) + tmp / fin;
tmp = (tmp % fin) << 8;
ratio = (ratio << 8) + (tmp + fin / 2) / fin;
-
- BDR = ratio;
+
+ BDR = ratio;
BDRI = (((state->config->xin << 5) / symbolrate) + 1) / 2;
-
- if (BDRI > 0xFF)
- BDRI = 0xFF;
-
- SFIL = (SFIL << 4) | ves1820_inittab[0x0E];
-
- NDEC = (NDEC << 6) | ves1820_inittab[0x03];
+
+ if (BDRI > 0xFF)
+ BDRI = 0xFF;
+
+ SFIL = (SFIL << 4) | ves1820_inittab[0x0E];
+
+ NDEC = (NDEC << 6) | ves1820_inittab[0x03];
ves1820_writereg(state, 0x03, NDEC);
ves1820_writereg(state, 0x0a, BDR & 0xff);
@@ -195,21 +188,9 @@ static int ves1820_set_symbolrate(struct ves1820_state *state, u32 symbolrate)
ves1820_writereg(state, 0x0d, BDRI);
ves1820_writereg(state, 0x0e, SFIL);
- return 0;
+ return 0;
}
-
-
-
-
-
-
-
-
-
-
-
-
static int ves1820_init(struct dvb_frontend* fe)
{
struct ves1820_state* state = (struct ves1820_state*) fe->demodulator_priv;
@@ -234,11 +215,11 @@ static int ves1820_init(struct dvb_frontend* fe)
static int ves1820_set_parameters(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
{
struct ves1820_state* state = (struct ves1820_state*) fe->demodulator_priv;
- static const u8 reg0x00 [] = { 0x00, 0x04, 0x08, 0x0c, 0x10 };
- static const u8 reg0x01 [] = { 140, 140, 106, 100, 92 };
- static const u8 reg0x05 [] = { 135, 100, 70, 54, 38 };
- static const u8 reg0x08 [] = { 162, 116, 67, 52, 35 };
- static const u8 reg0x09 [] = { 145, 150, 106, 126, 107 };
+ static const u8 reg0x00[] = { 0x00, 0x04, 0x08, 0x0c, 0x10 };
+ static const u8 reg0x01[] = { 140, 140, 106, 100, 92 };
+ static const u8 reg0x05[] = { 135, 100, 70, 54, 38 };
+ static const u8 reg0x08[] = { 162, 116, 67, 52, 35 };
+ static const u8 reg0x09[] = { 145, 150, 106, 126, 107 };
int real_qam = p->u.qam.modulation - QAM_16;
if (real_qam < 0 || real_qam > 4)
@@ -261,61 +242,60 @@ static int ves1820_set_parameters(struct dvb_frontend* fe, struct dvb_frontend_p
static int ves1820_read_status(struct dvb_frontend* fe, fe_status_t* status)
{
struct ves1820_state* state = (struct ves1820_state*) fe->demodulator_priv;
- int sync;
+ int sync;
- *status = 0;
+ *status = 0;
+ sync = ves1820_readreg(state, 0x11);
- sync = ves1820_readreg(state, 0x11);
+ if (sync & 1)
+ *status |= FE_HAS_SIGNAL;
- if (sync & 1)
- *status |= FE_HAS_SIGNAL;
+ if (sync & 2)
+ *status |= FE_HAS_CARRIER;
- if (sync & 2)
- *status |= FE_HAS_CARRIER;
+ if (sync & 2) /* XXX FIXME! */
+ *status |= FE_HAS_VITERBI;
- if (sync & 2) /* XXX FIXME! */
- *status |= FE_HAS_VITERBI;
-
- if (sync & 4)
- *status |= FE_HAS_SYNC;
+ if (sync & 4)
+ *status |= FE_HAS_SYNC;
- if (sync & 8)
- *status |= FE_HAS_LOCK;
+ if (sync & 8)
+ *status |= FE_HAS_LOCK;
return 0;
- }
+}
static int ves1820_read_ber(struct dvb_frontend* fe, u32* ber)
- {
+{
struct ves1820_state* state = (struct ves1820_state*) fe->demodulator_priv;
u32 _ber = ves1820_readreg(state, 0x14) |
- (ves1820_readreg(state, 0x15) << 8) |
- ((ves1820_readreg(state, 0x16) & 0x0f) << 16);
+ (ves1820_readreg(state, 0x15) << 8) |
+ ((ves1820_readreg(state, 0x16) & 0x0f) << 16);
*ber = 10 * _ber;
return 0;
- }
+}
static int ves1820_read_signal_strength(struct dvb_frontend* fe, u16* strength)
- {
+{
struct ves1820_state* state = (struct ves1820_state*) fe->demodulator_priv;
- u8 gain = ves1820_readreg(state, 0x17);
+ u8 gain = ves1820_readreg(state, 0x17);
*strength = (gain << 8) | gain;
return 0;
- }
+}
static int ves1820_read_snr(struct dvb_frontend* fe, u16* snr)
- {
+{
struct ves1820_state* state = (struct ves1820_state*) fe->demodulator_priv;
- u8 quality = ~ves1820_readreg(state, 0x18);
+ u8 quality = ~ves1820_readreg(state, 0x18);
*snr = (quality << 8) | quality;
return 0;
- }
+}
static int ves1820_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
{
@@ -325,26 +305,26 @@ static int ves1820_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
if (*ucblocks == 0x7f)
*ucblocks = 0xffffffff;
- /* reset uncorrected block counter */
- ves1820_writereg(state, 0x10, ves1820_inittab[0x10] & 0xdf);
- ves1820_writereg(state, 0x10, ves1820_inittab[0x10]);
+ /* reset uncorrected block counter */
+ ves1820_writereg(state, 0x10, ves1820_inittab[0x10] & 0xdf);
+ ves1820_writereg(state, 0x10, ves1820_inittab[0x10]);
return 0;
}
static int ves1820_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
- {
+{
struct ves1820_state* state = (struct ves1820_state*) fe->demodulator_priv;
- int sync;
- s8 afc = 0;
-
- sync = ves1820_readreg(state, 0x11);
- afc = ves1820_readreg(state, 0x19);
- if (verbose) {
- /* AFC only valid when carrier has been recovered */
- printk(sync & 2 ? "ves1820: AFC (%d) %dHz\n" :
- "ves1820: [AFC (%d) %dHz]\n", afc, -((s32) p->u.qam.symbol_rate * afc) >> 10);
- }
+ int sync;
+ s8 afc = 0;
+
+ sync = ves1820_readreg(state, 0x11);
+ afc = ves1820_readreg(state, 0x19);
+ if (verbose) {
+ /* AFC only valid when carrier has been recovered */
+ printk(sync & 2 ? "ves1820: AFC (%d) %dHz\n" :
+ "ves1820: [AFC (%d) %dHz]\n", afc, -((s32) p->u.qam.symbol_rate * afc) >> 10);
+ }
if (!state->config->invert) {
p->inversion = (state->reg0 & 0x20) ? INVERSION_ON : INVERSION_OFF;
@@ -352,16 +332,16 @@ static int ves1820_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
p->inversion = (!(state->reg0 & 0x20)) ? INVERSION_ON : INVERSION_OFF;
}
- p->u.qam.modulation = ((state->reg0 >> 2) & 7) + QAM_16;
+ p->u.qam.modulation = ((state->reg0 >> 2) & 7) + QAM_16;
- p->u.qam.fec_inner = FEC_NONE;
+ p->u.qam.fec_inner = FEC_NONE;
- p->frequency = ((p->frequency + 31250) / 62500) * 62500;
- if (sync & 2)
- p->frequency -= ((s32)p->u.qam.symbol_rate * afc) >> 10;
+ p->frequency = ((p->frequency + 31250) / 62500) * 62500;
+ if (sync & 2)
+ p->frequency -= ((s32) p->u.qam.symbol_rate * afc) >> 10;
- return 0;
-}
+ return 0;
+}
static int ves1820_sleep(struct dvb_frontend* fe)
{
@@ -424,9 +404,9 @@ struct dvb_frontend* ves1820_attach(const struct ves1820_config* config,
return &state->frontend;
error:
- if (state) kfree(state);
+ kfree(state);
return NULL;
- }
+}
static struct dvb_frontend_ops ves1820_ops = {
diff --git a/drivers/media/dvb/frontends/ves1820.h b/drivers/media/dvb/frontends/ves1820.h
index 8739fec48ec2c..355f130b1be8e 100644
--- a/drivers/media/dvb/frontends/ves1820.h
+++ b/drivers/media/dvb/frontends/ves1820.h
@@ -46,7 +46,6 @@ struct ves1820_config
};
extern struct dvb_frontend* ves1820_attach(const struct ves1820_config* config,
- struct i2c_adapter* i2c,
- u8 pwm);
+ struct i2c_adapter* i2c, u8 pwm);
#endif // VES1820_H
diff --git a/drivers/media/dvb/frontends/ves1x93.c b/drivers/media/dvb/frontends/ves1x93.c
index 4a13dcea97d3b..edcad283aa86e 100644
--- a/drivers/media/dvb/frontends/ves1x93.c
+++ b/drivers/media/dvb/frontends/ves1x93.c
@@ -1,4 +1,4 @@
-/*
+/*
Driver for VES1893 and VES1993 QPSK Demodulators
Copyright (C) 1999 Convergence Integrated Media GmbH <ralph@convergence.de>
@@ -21,7 +21,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
+*/
#include <linux/kernel.h>
#include <linux/module.h>
@@ -35,14 +35,10 @@
struct ves1x93_state {
-
struct i2c_adapter* i2c;
-
struct dvb_frontend_ops ops;
-
/* configuration settings */
const struct ves1x93_config* config;
-
struct dvb_frontend frontend;
/* previous uncorrected block counter */
@@ -69,7 +65,6 @@ static u8 init_1893_tab [] = {
0x00, 0x55, 0x00, 0x00, 0x7f, 0x00
};
-
static u8 init_1993_tab [] = {
0x00, 0x9c, 0x35, 0x80, 0x6a, 0x09, 0x72, 0x8c,
0x09, 0x6b, 0x00, 0x00, 0x4c, 0x08, 0x00, 0x00,
@@ -83,13 +78,12 @@ static u8 init_1993_tab [] = {
static u8 init_1893_wtab[] =
{
- 1,1,1,1,1,1,1,1, 1,1,0,0,1,1,0,0,
- 0,1,0,0,0,0,0,0, 1,0,1,1,0,0,0,1,
- 1,1,1,0,0,0,0,0, 0,0,1,1,0,0,0,0,
- 1,1,1,0,1,1
+ 1,1,1,1,1,1,1,1, 1,1,0,0,1,1,0,0,
+ 0,1,0,0,0,0,0,0, 1,0,1,1,0,0,0,1,
+ 1,1,1,0,0,0,0,0, 0,0,1,1,0,0,0,0,
+ 1,1,1,0,1,1
};
-
static u8 init_1993_wtab[] =
{
1,1,1,1,1,1,1,1, 1,1,0,0,1,1,0,0,
@@ -100,7 +94,7 @@ static u8 init_1993_wtab[] =
static int ves1x93_writereg (struct ves1x93_state* state, u8 reg, u8 data)
{
- u8 buf [] = { 0x00, reg, data };
+ u8 buf [] = { 0x00, reg, data };
struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 3 };
int err;
@@ -109,10 +103,9 @@ static int ves1x93_writereg (struct ves1x93_state* state, u8 reg, u8 data)
return -EREMOTEIO;
}
- return 0;
+ return 0;
}
-
static u8 ves1x93_readreg (struct ves1x93_state* state, u8 reg)
{
int ret;
@@ -163,7 +156,6 @@ static int ves1x93_set_inversion (struct ves1x93_state* state, fe_spectral_inver
return ves1x93_writereg (state, 0x0c, (state->init_1x93_tab[0x0c] & 0x3f) | val);
}
-
static int ves1x93_set_fec (struct ves1x93_state* state, fe_code_rate_t fec)
{
if (fec == FEC_AUTO)
@@ -174,18 +166,16 @@ static int ves1x93_set_fec (struct ves1x93_state* state, fe_code_rate_t fec)
return ves1x93_writereg (state, 0x0d, fec - FEC_1_2);
}
-
static fe_code_rate_t ves1x93_get_fec (struct ves1x93_state* state)
{
return FEC_1_2 + ((ves1x93_readreg (state, 0x0d) >> 4) & 0x7);
}
-
static int ves1x93_set_symbolrate (struct ves1x93_state* state, u32 srate)
{
u32 BDR;
- u32 ratio;
- u8 ADCONF, FCONF, FNR;
+ u32 ratio;
+ u8 ADCONF, FCONF, FNR, AGCR;
u32 BDRI;
u32 tmp;
u32 FIN;
@@ -213,15 +203,15 @@ static int ves1x93_set_symbolrate (struct ves1x93_state* state, u32 srate)
FNR = 0xff;
- if (ratio < MUL/3) FNR = 0;
+ if (ratio < MUL/3) FNR = 0;
if (ratio < (MUL*11)/50) FNR = 1;
- if (ratio < MUL/6) FNR = 2;
- if (ratio < MUL/9) FNR = 3;
- if (ratio < MUL/12) FNR = 4;
+ if (ratio < MUL/6) FNR = 2;
+ if (ratio < MUL/9) FNR = 3;
+ if (ratio < MUL/12) FNR = 4;
if (ratio < (MUL*11)/200) FNR = 5;
- if (ratio < MUL/24) FNR = 6;
+ if (ratio < MUL/24) FNR = 6;
if (ratio < (MUL*27)/1000) FNR = 7;
- if (ratio < MUL/48) FNR = 8;
+ if (ratio < MUL/48) FNR = 8;
if (ratio < (MUL*137)/10000) FNR = 9;
if (FNR == 0xff) {
@@ -231,16 +221,16 @@ static int ves1x93_set_symbolrate (struct ves1x93_state* state, u32 srate)
} else {
ADCONF = 0x81;
FCONF = 0x88 | (FNR >> 1) | ((FNR & 0x01) << 5);
- /*FCONF = 0x80 | ((FNR & 0x01) << 5) | (((FNR > 1) & 0x03) << 3) | ((FNR >> 1) & 0x07);*/
+ /*FCONF = 0x80 | ((FNR & 0x01) << 5) | (((FNR > 1) & 0x03) << 3) | ((FNR >> 1) & 0x07);*/
}
BDR = (( (ratio << (FNR >> 1)) >> 4) + 1) >> 1;
BDRI = ( ((FIN << 8) / ((srate << (FNR >> 1)) >> 2)) + 1) >> 1;
- dprintk("FNR= %d\n", FNR);
- dprintk("ratio= %08x\n", (unsigned int) ratio);
- dprintk("BDR= %08x\n", (unsigned int) BDR);
- dprintk("BDRI= %02x\n", (unsigned int) BDRI);
+ dprintk("FNR= %d\n", FNR);
+ dprintk("ratio= %08x\n", (unsigned int) ratio);
+ dprintk("BDR= %08x\n", (unsigned int) BDR);
+ dprintk("BDRI= %02x\n", (unsigned int) BDRI);
if (BDRI > 0xff)
BDRI = 0xff;
@@ -253,10 +243,16 @@ static int ves1x93_set_symbolrate (struct ves1x93_state* state, u32 srate)
ves1x93_writereg (state, 0x20, ADCONF);
ves1x93_writereg (state, 0x21, FCONF);
- if (srate < 6000000)
- ves1x93_writereg (state, 0x05, state->init_1x93_tab[0x05] | 0x80);
+ AGCR = state->init_1x93_tab[0x05];
+ if (state->config->invert_pwm)
+ AGCR |= 0x20;
+
+ if (srate < 6000000)
+ AGCR |= 0x80;
else
- ves1x93_writereg (state, 0x05, state->init_1x93_tab[0x05] & 0x7f);
+ AGCR &= ~0x80;
+
+ ves1x93_writereg (state, 0x05, AGCR);
/* ves1993 hates this, will lose lock */
if (state->demod_type != DEMOD_VES1993)
@@ -265,20 +261,6 @@ static int ves1x93_set_symbolrate (struct ves1x93_state* state, u32 srate)
return 0;
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
static int ves1x93_init (struct dvb_frontend* fe)
{
struct ves1x93_state* state = (struct ves1x93_state*) fe->demodulator_priv;
@@ -327,80 +309,79 @@ static int ves1x93_read_status(struct dvb_frontend* fe, fe_status_t* status)
u8 sync = ves1x93_readreg (state, 0x0e);
- /*
- * The ves1893 sometimes returns sync values that make no sense,
- * because, e.g., the SIGNAL bit is 0, while some of the higher
- * bits are 1 (and how can there be a CARRIER w/o a SIGNAL?).
- * Tests showed that the the VITERBI and SYNC bits are returned
- * reliably, while the SIGNAL and CARRIER bits ar sometimes wrong.
- * If such a case occurs, we read the value again, until we get a
- * valid value.
- */
- int maxtry = 10; /* just for safety - let's not get stuck here */
- while ((sync & 0x03) != 0x03 && (sync & 0x0c) && maxtry--) {
- msleep(10);
+ /*
+ * The ves1893 sometimes returns sync values that make no sense,
+ * because, e.g., the SIGNAL bit is 0, while some of the higher
+ * bits are 1 (and how can there be a CARRIER w/o a SIGNAL?).
+ * Tests showed that the the VITERBI and SYNC bits are returned
+ * reliably, while the SIGNAL and CARRIER bits ar sometimes wrong.
+ * If such a case occurs, we read the value again, until we get a
+ * valid value.
+ */
+ int maxtry = 10; /* just for safety - let's not get stuck here */
+ while ((sync & 0x03) != 0x03 && (sync & 0x0c) && maxtry--) {
+ msleep(10);
sync = ves1x93_readreg (state, 0x0e);
- }
+ }
- *status = 0;
+ *status = 0;
- if (sync & 1)
- *status |= FE_HAS_SIGNAL;
+ if (sync & 1)
+ *status |= FE_HAS_SIGNAL;
- if (sync & 2)
- *status |= FE_HAS_CARRIER;
+ if (sync & 2)
+ *status |= FE_HAS_CARRIER;
- if (sync & 4)
- *status |= FE_HAS_VITERBI;
+ if (sync & 4)
+ *status |= FE_HAS_VITERBI;
- if (sync & 8)
- *status |= FE_HAS_SYNC;
+ if (sync & 8)
+ *status |= FE_HAS_SYNC;
- if ((sync & 0x1f) == 0x1f)
- *status |= FE_HAS_LOCK;
+ if ((sync & 0x1f) == 0x1f)
+ *status |= FE_HAS_LOCK;
return 0;
- }
-
+}
static int ves1x93_read_ber(struct dvb_frontend* fe, u32* ber)
- {
+{
struct ves1x93_state* state = (struct ves1x93_state*) fe->demodulator_priv;
*ber = ves1x93_readreg (state, 0x15);
*ber |= (ves1x93_readreg (state, 0x16) << 8);
*ber |= ((ves1x93_readreg (state, 0x17) & 0x0F) << 16);
- *ber *= 10;
+ *ber *= 10;
return 0;
- }
+}
static int ves1x93_read_signal_strength(struct dvb_frontend* fe, u16* strength)
- {
+{
struct ves1x93_state* state = (struct ves1x93_state*) fe->demodulator_priv;
u8 signal = ~ves1x93_readreg (state, 0x0b);
*strength = (signal << 8) | signal;
return 0;
- }
+}
static int ves1x93_read_snr(struct dvb_frontend* fe, u16* snr)
- {
+{
struct ves1x93_state* state = (struct ves1x93_state*) fe->demodulator_priv;
u8 _snr = ~ves1x93_readreg (state, 0x1c);
*snr = (_snr << 8) | _snr;
return 0;
- }
+}
static int ves1x93_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
- {
+{
struct ves1x93_state* state = (struct ves1x93_state*) fe->demodulator_priv;
*ucblocks = ves1x93_readreg (state, 0x18) & 0x7f;
-
+
if (*ucblocks == 0x7f)
*ucblocks = 0xffffffff; /* counter overflow... */
@@ -408,10 +389,10 @@ static int ves1x93_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
ves1x93_writereg (state, 0x18, 0x80); /* dto. */
return 0;
- }
+}
static int ves1x93_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
- {
+{
struct ves1x93_state* state = (struct ves1x93_state*) fe->demodulator_priv;
ves1x93_writereg(state, 0x00, 0x11);
@@ -420,28 +401,28 @@ static int ves1x93_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
ves1x93_set_inversion (state, p->inversion);
ves1x93_set_fec (state, p->u.qpsk.fec_inner);
ves1x93_set_symbolrate (state, p->u.qpsk.symbol_rate);
- state->inversion = p->inversion;
+ state->inversion = p->inversion;
return 0;
- }
+}
static int ves1x93_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
- {
+{
struct ves1x93_state* state = (struct ves1x93_state*) fe->demodulator_priv;
- int afc;
+ int afc;
afc = ((int)((char)(ves1x93_readreg (state, 0x0a) << 1)))/2;
- afc = (afc * (int)(p->u.qpsk.symbol_rate/1000/8))/16;
+ afc = (afc * (int)(p->u.qpsk.symbol_rate/1000/8))/16;
- p->frequency -= afc;
+ p->frequency -= afc;
- /*
- * inversion indicator is only valid
- * if auto inversion was used
- */
- if (state->inversion == INVERSION_AUTO)
+ /*
+ * inversion indicator is only valid
+ * if auto inversion was used
+ */
+ if (state->inversion == INVERSION_AUTO)
p->inversion = (ves1x93_readreg (state, 0x0f) & 2) ?
- INVERSION_OFF : INVERSION_ON;
+ INVERSION_OFF : INVERSION_ON;
p->u.qpsk.fec_inner = ves1x93_get_fec (state);
/* XXX FIXME: timing offset !! */
@@ -454,12 +435,12 @@ static int ves1x93_sleep(struct dvb_frontend* fe)
return ves1x93_writereg (state, 0x00, 0x08);
}
-
+
static void ves1x93_release(struct dvb_frontend* fe)
{
struct ves1x93_state* state = (struct ves1x93_state*) fe->demodulator_priv;
kfree(state);
-}
+}
static struct dvb_frontend_ops ves1x93_ops;
@@ -516,9 +497,9 @@ struct dvb_frontend* ves1x93_attach(const struct ves1x93_config* config,
return &state->frontend;
error:
- if (state) kfree(state);
+ kfree(state);
return NULL;
- }
+}
static struct dvb_frontend_ops ves1x93_ops = {
diff --git a/drivers/media/dvb/ttpci/Kconfig b/drivers/media/dvb/ttpci/Kconfig
index edb9c730ebc92..7ffa2c7315b38 100644
--- a/drivers/media/dvb/ttpci/Kconfig
+++ b/drivers/media/dvb/ttpci/Kconfig
@@ -10,6 +10,7 @@ config DVB_AV7110
select DVB_TDA8083
select DVB_SP8870
select DVB_STV0297
+ select DVB_L64781
help
Support for SAA7146 and AV7110 based DVB cards as produced
by Fujitsu-Siemens, Technotrend, Hauppauge and others.
diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c
index 438c5d88ca28d..922c205a26522 100644
--- a/drivers/media/dvb/ttpci/av7110.c
+++ b/drivers/media/dvb/ttpci/av7110.c
@@ -2,7 +2,7 @@
* driver for the SAA7146 based AV110 cards (like the Fujitsu-Siemens DVB)
* av7110.c: initialization and demux stuff
*
- * Copyright (C) 1999-2002 Ralph Metzler
+ * Copyright (C) 1999-2002 Ralph Metzler
* & Marcus Metzler for convergence integrated media GmbH
*
* originally based on code by:
@@ -12,19 +12,19 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
- *
+ *
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
*
* You should have received a copy of the 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.
* Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- *
+ *
*
* the project's page is at http://www.linuxtv.org/dvb/
*/
@@ -75,9 +75,9 @@
int av7110_debug;
-static int vidmode=CVBS_RGB_OUT;
+static int vidmode = CVBS_RGB_OUT;
static int pids_off;
-static int adac=DVB_ADAC_TI;
+static int adac = DVB_ADAC_TI;
static int hw_sections;
static int rgb_on;
static int volume = 255;
@@ -109,14 +109,14 @@ static int av7110_num = 0;
{\
if (fe_func != NULL) { \
av7110_copy = fe_func; \
- fe_func = av7110_func; \
+ fe_func = av7110_func; \
} \
}
static void init_av7110_av(struct av7110 *av7110)
{
- struct saa7146_dev *dev=av7110->dev;
+ struct saa7146_dev *dev = av7110->dev;
/* set internal volume control to maximum */
av7110->adac_type = DVB_ADAC_TI;
@@ -137,9 +137,9 @@ static void init_av7110_av(struct av7110 *av7110)
i2c_writereg(av7110, 0x20, 0x03, 0x00);
i2c_writereg(av7110, 0x20, 0x04, 0x00);
- /**
- * some special handling for the Siemens DVB-C cards...
- */
+ /**
+ * some special handling for the Siemens DVB-C cards...
+ */
} else if (0 == av7110_init_analog_module(av7110)) {
/* done. */
}
@@ -161,8 +161,8 @@ static void init_av7110_av(struct av7110 *av7110)
if (rgb_on &&
(av7110->dev->pci->subsystem_vendor == 0x110a) && (av7110->dev->pci->subsystem_device == 0x0000)) {
saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); // RGB on, SCART pin 16
- //saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); // SCARTpin 8
- }
+ //saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); // SCARTpin 8
+ }
}
av7110_set_volume(av7110, av7110->mixer.volume_left, av7110->mixer.volume_right);
@@ -175,7 +175,7 @@ static void recover_arm(struct av7110 *av7110)
av7110_bootarm(av7110);
msleep(100);
- restart_feeds(av7110);
+ restart_feeds(av7110);
av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, SetIR, 1, av7110->ir_config);
}
@@ -183,23 +183,32 @@ static void arm_error(struct av7110 *av7110)
{
dprintk(4, "%p\n",av7110);
- av7110->arm_errors++;
- av7110->arm_ready=0;
- recover_arm(av7110);
+ av7110->arm_errors++;
+ av7110->arm_ready = 0;
+ recover_arm(av7110);
+}
+
+static void av7110_arm_sync(struct av7110 *av7110)
+{
+ av7110->arm_rmmod = 1;
+ wake_up_interruptible(&av7110->arm_wait);
+
+ while (av7110->arm_thread)
+ msleep(1);
}
static int arm_thread(void *data)
{
struct av7110 *av7110 = data;
- u16 newloops = 0;
+ u16 newloops = 0;
int timeout;
dprintk(4, "%p\n",av7110);
-
- lock_kernel ();
- daemonize ("arm_mon");
- sigfillset (&current->blocked);
- unlock_kernel ();
+
+ lock_kernel();
+ daemonize("arm_mon");
+ sigfillset(&current->blocked);
+ unlock_kernel();
av7110->arm_thread = current;
@@ -211,31 +220,31 @@ static int arm_thread(void *data)
break;
}
- if (!av7110->arm_ready)
- continue;
+ if (!av7110->arm_ready)
+ continue;
- if (down_interruptible(&av7110->dcomlock))
- break;
+ if (down_interruptible(&av7110->dcomlock))
+ break;
- newloops=rdebi(av7110, DEBINOSWAP, STATUS_LOOPS, 0, 2);
- up(&av7110->dcomlock);
+ newloops = rdebi(av7110, DEBINOSWAP, STATUS_LOOPS, 0, 2);
+ up(&av7110->dcomlock);
- if (newloops==av7110->arm_loops) {
+ if (newloops == av7110->arm_loops) {
printk(KERN_ERR "dvb-ttpci: ARM crashed @ card %d\n",
- av7110->dvb_adapter->num);
+ av7110->dvb_adapter->num);
arm_error(av7110);
av7710_set_video_mode(av7110, vidmode);
init_av7110_av(av7110);
- if (down_interruptible(&av7110->dcomlock))
- break;
+ if (down_interruptible(&av7110->dcomlock))
+ break;
- newloops=rdebi(av7110, DEBINOSWAP, STATUS_LOOPS, 0, 2)-1;
- up(&av7110->dcomlock);
- }
- av7110->arm_loops=newloops;
+ newloops = rdebi(av7110, DEBINOSWAP, STATUS_LOOPS, 0, 2) - 1;
+ up(&av7110->dcomlock);
+ }
+ av7110->arm_loops = newloops;
}
av7110->arm_thread = NULL;
@@ -245,15 +254,15 @@ static int arm_thread(void *data)
/**
* Hack! we save the last av7110 ptr. This should be ok, since
- * you rarely will use more then one IR control.
+ * you rarely will use more then one IR control.
*
* If we want to support multiple controls we would have to do much more...
*/
-void av7110_setup_irc_config (struct av7110 *av7110, u32 ir_config)
+void av7110_setup_irc_config(struct av7110 *av7110, u32 ir_config)
{
static struct av7110 *last;
- dprintk(4, "%p\n",av7110);
+ dprintk(4, "%p\n", av7110);
if (!av7110)
av7110 = last;
@@ -268,22 +277,22 @@ void av7110_setup_irc_config (struct av7110 *av7110, u32 ir_config)
static void (*irc_handler)(u32);
-void av7110_register_irc_handler(void (*func)(u32))
+void av7110_register_irc_handler(void (*func)(u32))
{
dprintk(4, "registering %p\n", func);
- irc_handler = func;
+ irc_handler = func;
}
-void av7110_unregister_irc_handler(void (*func)(u32))
+void av7110_unregister_irc_handler(void (*func)(u32))
{
dprintk(4, "unregistering %p\n", func);
- irc_handler = NULL;
+ irc_handler = NULL;
}
static void run_handlers(unsigned long ircom)
{
- if (irc_handler != NULL)
- (*irc_handler)((u32) ircom);
+ if (irc_handler != NULL)
+ (*irc_handler)((u32) ircom);
}
static DECLARE_TASKLET(irtask, run_handlers, 0);
@@ -291,8 +300,8 @@ static DECLARE_TASKLET(irtask, run_handlers, 0);
static void IR_handle(struct av7110 *av7110, u32 ircom)
{
dprintk(4, "ircommand = %08x\n", ircom);
- irtask.data = (unsigned long) ircom;
- tasklet_schedule(&irtask);
+ irtask.data = (unsigned long) ircom;
+ tasklet_schedule(&irtask);
}
/****************************************************************************
@@ -300,51 +309,51 @@ static void IR_handle(struct av7110 *av7110, u32 ircom)
****************************************************************************/
static int DvbDmxFilterCallback(u8 *buffer1, size_t buffer1_len,
- u8 * buffer2, size_t buffer2_len,
- struct dvb_demux_filter *dvbdmxfilter,
- enum dmx_success success,
- struct av7110 *av7110)
-{
- if (!dvbdmxfilter->feed->demux->dmx.frontend)
- return 0;
- if (dvbdmxfilter->feed->demux->dmx.frontend->source==DMX_MEMORY_FE)
- return 0;
-
- switch(dvbdmxfilter->type) {
- case DMX_TYPE_SEC:
- if ((((buffer1[1]<<8)|buffer1[2])&0xfff)+3!=buffer1_len)
- return 0;
- if (dvbdmxfilter->doneq) {
- struct dmx_section_filter *filter=&dvbdmxfilter->filter;
- int i;
- u8 xor, neq=0;
-
- for (i=0; i<DVB_DEMUX_MASK_MAX; i++) {
- xor=filter->filter_value[i]^buffer1[i];
- neq|=dvbdmxfilter->maskandnotmode[i]&xor;
- }
- if (!neq)
- return 0;
- }
- return dvbdmxfilter->feed->cb.sec(buffer1, buffer1_len,
+ u8 *buffer2, size_t buffer2_len,
+ struct dvb_demux_filter *dvbdmxfilter,
+ enum dmx_success success,
+ struct av7110 *av7110)
+{
+ if (!dvbdmxfilter->feed->demux->dmx.frontend)
+ return 0;
+ if (dvbdmxfilter->feed->demux->dmx.frontend->source == DMX_MEMORY_FE)
+ return 0;
+
+ switch (dvbdmxfilter->type) {
+ case DMX_TYPE_SEC:
+ if ((((buffer1[1] << 8) | buffer1[2]) & 0xfff) + 3 != buffer1_len)
+ return 0;
+ if (dvbdmxfilter->doneq) {
+ struct dmx_section_filter *filter = &dvbdmxfilter->filter;
+ int i;
+ u8 xor, neq = 0;
+
+ for (i = 0; i < DVB_DEMUX_MASK_MAX; i++) {
+ xor = filter->filter_value[i] ^ buffer1[i];
+ neq |= dvbdmxfilter->maskandnotmode[i] & xor;
+ }
+ if (!neq)
+ return 0;
+ }
+ return dvbdmxfilter->feed->cb.sec(buffer1, buffer1_len,
buffer2, buffer2_len,
&dvbdmxfilter->filter,
- DMX_OK);
- case DMX_TYPE_TS:
- if (!(dvbdmxfilter->feed->ts_type & TS_PACKET))
- return 0;
- if (dvbdmxfilter->feed->ts_type & TS_PAYLOAD_ONLY)
- return dvbdmxfilter->feed->cb.ts(buffer1, buffer1_len,
- buffer2, buffer2_len,
- &dvbdmxfilter->feed->feed.ts,
- DMX_OK);
- else
+ DMX_OK);
+ case DMX_TYPE_TS:
+ if (!(dvbdmxfilter->feed->ts_type & TS_PACKET))
+ return 0;
+ if (dvbdmxfilter->feed->ts_type & TS_PAYLOAD_ONLY)
+ return dvbdmxfilter->feed->cb.ts(buffer1, buffer1_len,
+ buffer2, buffer2_len,
+ &dvbdmxfilter->feed->feed.ts,
+ DMX_OK);
+ else
av7110_p2t_write(buffer1, buffer1_len,
- dvbdmxfilter->feed->pid,
- &av7110->p2t_filter[dvbdmxfilter->index]);
+ dvbdmxfilter->feed->pid,
+ &av7110->p2t_filter[dvbdmxfilter->index]);
default:
- return 0;
- }
+ return 0;
+ }
}
@@ -352,9 +361,9 @@ static int DvbDmxFilterCallback(u8 *buffer1, size_t buffer1_len,
static inline void print_time(char *s)
{
#ifdef DEBUG_TIMING
- struct timeval tv;
- do_gettimeofday(&tv);
- printk("%s: %d.%d\n", s, (int)tv.tv_sec, (int)tv.tv_usec);
+ struct timeval tv;
+ do_gettimeofday(&tv);
+ printk("%s: %d.%d\n", s, (int)tv.tv_sec, (int)tv.tv_usec);
#endif
}
@@ -379,129 +388,129 @@ static inline void start_debi_dma(struct av7110 *av7110, int dir,
irdebi(av7110, DEBISWAB, addr, 0, len);
}
-static void debiirq (unsigned long data)
+static void debiirq(unsigned long data)
{
- struct av7110 *av7110 = (struct av7110*) data;
- int type=av7110->debitype;
- int handle=(type>>8)&0x1f;
+ struct av7110 *av7110 = (struct av7110 *) data;
+ int type = av7110->debitype;
+ int handle = (type >> 8) & 0x1f;
unsigned int xfer = 0;
- print_time("debi");
+ print_time("debi");
dprintk(4, "type 0x%04x\n", type);
- if (type==-1) {
+ if (type == -1) {
printk("DEBI irq oops @ %ld, psr:0x%08x, ssr:0x%08x\n",
jiffies, saa7146_read(av7110->dev, PSR),
saa7146_read(av7110->dev, SSR));
goto debi_done;
- }
- av7110->debitype=-1;
+ }
+ av7110->debitype = -1;
- switch (type&0xff) {
+ switch (type & 0xff) {
- case DATA_TS_RECORD:
- dvb_dmx_swfilter_packets(&av7110->demux,
- (const u8 *)av7110->debi_virt,
- av7110->debilen/188);
+ case DATA_TS_RECORD:
+ dvb_dmx_swfilter_packets(&av7110->demux,
+ (const u8 *) av7110->debi_virt,
+ av7110->debilen / 188);
xfer = RX_BUFF;
break;
- case DATA_PES_RECORD:
- if (av7110->demux.recording)
+ case DATA_PES_RECORD:
+ if (av7110->demux.recording)
av7110_record_cb(&av7110->p2t[handle],
- (u8 *)av7110->debi_virt,
- av7110->debilen);
+ (u8 *) av7110->debi_virt,
+ av7110->debilen);
xfer = RX_BUFF;
break;
- case DATA_IPMPE:
- case DATA_FSECTION:
- case DATA_PIPING:
- if (av7110->handle2filter[handle])
- DvbDmxFilterCallback((u8 *)av7110->debi_virt,
- av7110->debilen, NULL, 0,
- av7110->handle2filter[handle],
- DMX_OK, av7110);
+ case DATA_IPMPE:
+ case DATA_FSECTION:
+ case DATA_PIPING:
+ if (av7110->handle2filter[handle])
+ DvbDmxFilterCallback((u8 *)av7110->debi_virt,
+ av7110->debilen, NULL, 0,
+ av7110->handle2filter[handle],
+ DMX_OK, av7110);
xfer = RX_BUFF;
break;
- case DATA_CI_GET:
- {
- u8 *data=av7110->debi_virt;
-
- if ((data[0]<2) && data[2]==0xff) {
- int flags=0;
- if (data[5]>0)
- flags|=CA_CI_MODULE_PRESENT;
- if (data[5]>5)
- flags|=CA_CI_MODULE_READY;
- av7110->ci_slot[data[0]].flags=flags;
- } else
- ci_get_data(&av7110->ci_rbuffer,
- av7110->debi_virt,
- av7110->debilen);
+ case DATA_CI_GET:
+ {
+ u8 *data = av7110->debi_virt;
+
+ if ((data[0] < 2) && data[2] == 0xff) {
+ int flags = 0;
+ if (data[5] > 0)
+ flags |= CA_CI_MODULE_PRESENT;
+ if (data[5] > 5)
+ flags |= CA_CI_MODULE_READY;
+ av7110->ci_slot[data[0]].flags = flags;
+ } else
+ ci_get_data(&av7110->ci_rbuffer,
+ av7110->debi_virt,
+ av7110->debilen);
xfer = RX_BUFF;
break;
- }
+ }
- case DATA_COMMON_INTERFACE:
- CI_handle(av7110, (u8 *)av7110->debi_virt, av7110->debilen);
+ case DATA_COMMON_INTERFACE:
+ CI_handle(av7110, (u8 *)av7110->debi_virt, av7110->debilen);
#if 0
- {
- int i;
-
- printk("av7110%d: ", av7110->num);
- printk("%02x ", *(u8 *)av7110->debi_virt);
- printk("%02x ", *(1+(u8 *)av7110->debi_virt));
- for (i=2; i<av7110->debilen; i++)
- printk("%02x ", (*(i+(unsigned char *)av7110->debi_virt)));
- for (i=2; i<av7110->debilen; i++)
- printk("%c", chtrans(*(i+(unsigned char *)av7110->debi_virt)));
-
- printk("\n");
- }
+ {
+ int i;
+
+ printk("av7110%d: ", av7110->num);
+ printk("%02x ", *(u8 *)av7110->debi_virt);
+ printk("%02x ", *(1+(u8 *)av7110->debi_virt));
+ for (i = 2; i < av7110->debilen; i++)
+ printk("%02x ", (*(i+(unsigned char *)av7110->debi_virt)));
+ for (i = 2; i < av7110->debilen; i++)
+ printk("%c", chtrans(*(i+(unsigned char *)av7110->debi_virt)));
+
+ printk("\n");
+ }
#endif
xfer = RX_BUFF;
break;
- case DATA_DEBUG_MESSAGE:
- ((s8*)av7110->debi_virt)[Reserved_SIZE-1]=0;
- printk("%s\n", (s8 *)av7110->debi_virt);
+ case DATA_DEBUG_MESSAGE:
+ ((s8*)av7110->debi_virt)[Reserved_SIZE - 1] = 0;
+ printk("%s\n", (s8 *) av7110->debi_virt);
xfer = RX_BUFF;
break;
- case DATA_CI_PUT:
+ case DATA_CI_PUT:
dprintk(4, "debi DATA_CI_PUT\n");
- case DATA_MPEG_PLAY:
+ case DATA_MPEG_PLAY:
dprintk(4, "debi DATA_MPEG_PLAY\n");
- case DATA_BMP_LOAD:
+ case DATA_BMP_LOAD:
dprintk(4, "debi DATA_BMP_LOAD\n");
xfer = TX_BUFF;
break;
- default:
- break;
- }
+ default:
+ break;
+ }
debi_done:
- spin_lock(&av7110->debilock);
+ spin_lock(&av7110->debilock);
if (xfer)
iwdebi(av7110, DEBINOSWAP, xfer, 0, 2);
- ARM_ClearMailBox(av7110);
- spin_unlock(&av7110->debilock);
+ ARM_ClearMailBox(av7110);
+ spin_unlock(&av7110->debilock);
}
/* irq from av7110 firmware writing the mailbox register in the DPRAM */
-static void gpioirq (unsigned long data)
+static void gpioirq(unsigned long data)
{
- struct av7110 *av7110 = (struct av7110*) data;
- u32 rxbuf, txbuf;
- int len;
-
- if (av7110->debitype !=-1)
+ struct av7110 *av7110 = (struct av7110 *) data;
+ u32 rxbuf, txbuf;
+ int len;
+
+ if (av7110->debitype != -1)
/* we shouldn't get any irq while a debi xfer is running */
printk("dvb-ttpci: GPIO0 irq oops @ %ld, psr:0x%08x, ssr:0x%08x\n",
jiffies, saa7146_read(av7110->dev, PSR),
saa7146_read(av7110->dev, SSR));
-
+
if (saa7146_wait_for_debi_done(av7110->dev, 0)) {
printk(KERN_ERR "%s: saa7146_wait_for_debi_done timed out\n", __FUNCTION__);
BUG(); /* maybe we should try resetting the debi? */
@@ -511,37 +520,37 @@ static void gpioirq (unsigned long data)
ARM_ClearIrq(av7110);
/* see what the av7110 wants */
- av7110->debitype = irdebi(av7110, DEBINOSWAP, IRQ_STATE, 0, 2);
- av7110->debilen = irdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
- rxbuf=irdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
- txbuf=irdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
+ av7110->debitype = irdebi(av7110, DEBINOSWAP, IRQ_STATE, 0, 2);
+ av7110->debilen = irdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
+ rxbuf = irdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
+ txbuf = irdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
len = (av7110->debilen + 3) & ~3;
- print_time("gpio");
+ print_time("gpio");
dprintk(8, "GPIO0 irq 0x%04x %d\n", av7110->debitype, av7110->debilen);
- switch (av7110->debitype&0xff) {
+ switch (av7110->debitype & 0xff) {
- case DATA_TS_PLAY:
- case DATA_PES_PLAY:
- break;
+ case DATA_TS_PLAY:
+ case DATA_PES_PLAY:
+ break;
case DATA_MPEG_VIDEO_EVENT:
{
u32 h_ar;
struct video_event event;
- av7110->video_size.w = irdebi(av7110, DEBINOSWAP, STATUS_MPEG_WIDTH, 0, 2);
- h_ar = irdebi(av7110, DEBINOSWAP, STATUS_MPEG_HEIGHT_AR, 0, 2);
+ av7110->video_size.w = irdebi(av7110, DEBINOSWAP, STATUS_MPEG_WIDTH, 0, 2);
+ h_ar = irdebi(av7110, DEBINOSWAP, STATUS_MPEG_HEIGHT_AR, 0, 2);
- iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
- iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
+ iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
+ 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);
+ 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;
@@ -567,139 +576,139 @@ static void gpioirq (unsigned long data)
break;
}
- case DATA_CI_PUT:
- {
- int avail;
- struct dvb_ringbuffer *cibuf=&av7110->ci_wbuffer;
-
- avail=dvb_ringbuffer_avail(cibuf);
- if (avail<=2) {
- iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
- iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
- iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
- break;
- }
- len= DVB_RINGBUFFER_PEEK(cibuf,0)<<8;
- len|=DVB_RINGBUFFER_PEEK(cibuf,1);
- if (avail<len+2) {
- iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
- iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
- iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
- break;
- }
- DVB_RINGBUFFER_SKIP(cibuf,2);
-
- dvb_ringbuffer_read(cibuf,av7110->debi_virt,len,0);
-
- iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2);
- iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, len, 2);
+ case DATA_CI_PUT:
+ {
+ int avail;
+ struct dvb_ringbuffer *cibuf = &av7110->ci_wbuffer;
+
+ avail = dvb_ringbuffer_avail(cibuf);
+ if (avail <= 2) {
+ iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
+ iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
+ iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
+ break;
+ }
+ len = DVB_RINGBUFFER_PEEK(cibuf, 0) << 8;
+ len |= DVB_RINGBUFFER_PEEK(cibuf, 1);
+ if (avail < len + 2) {
+ iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
+ iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
+ iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
+ break;
+ }
+ DVB_RINGBUFFER_SKIP(cibuf, 2);
+
+ dvb_ringbuffer_read(cibuf, av7110->debi_virt, len, 0);
+
+ iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2);
+ iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, len, 2);
dprintk(8, "DMA: CI\n");
start_debi_dma(av7110, DEBI_WRITE, DPRAM_BASE + txbuf, len);
- spin_unlock(&av7110->debilock);
+ spin_unlock(&av7110->debilock);
wake_up(&cibuf->queue);
- return;
- }
-
- case DATA_MPEG_PLAY:
- if (!av7110->playing) {
- iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
- iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
- iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
- break;
- }
- len=0;
- if (av7110->debitype&0x100) {
- spin_lock(&av7110->aout.lock);
- len=av7110_pes_play(av7110->debi_virt, &av7110->aout, 2048);
- spin_unlock(&av7110->aout.lock);
- }
- if (len<=0 && (av7110->debitype&0x200)
- &&av7110->videostate.play_state!=VIDEO_FREEZED) {
- spin_lock(&av7110->avout.lock);
- len=av7110_pes_play(av7110->debi_virt, &av7110->avout, 2048);
- spin_unlock(&av7110->avout.lock);
- }
- if (len<=0) {
- iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
- iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
- iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
- break;
- }
+ return;
+ }
+
+ case DATA_MPEG_PLAY:
+ if (!av7110->playing) {
+ iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
+ iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
+ iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
+ break;
+ }
+ len = 0;
+ if (av7110->debitype & 0x100) {
+ spin_lock(&av7110->aout.lock);
+ len = av7110_pes_play(av7110->debi_virt, &av7110->aout, 2048);
+ spin_unlock(&av7110->aout.lock);
+ }
+ if (len <= 0 && (av7110->debitype & 0x200)
+ &&av7110->videostate.play_state != VIDEO_FREEZED) {
+ spin_lock(&av7110->avout.lock);
+ len = av7110_pes_play(av7110->debi_virt, &av7110->avout, 2048);
+ spin_unlock(&av7110->avout.lock);
+ }
+ if (len <= 0) {
+ iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
+ iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
+ iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
+ break;
+ }
dprintk(8, "GPIO0 PES_PLAY len=%04x\n", len);
- iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2);
- iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, len, 2);
+ iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2);
+ iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, len, 2);
dprintk(8, "DMA: MPEG_PLAY\n");
start_debi_dma(av7110, DEBI_WRITE, DPRAM_BASE + txbuf, len);
- spin_unlock(&av7110->debilock);
- return;
+ spin_unlock(&av7110->debilock);
+ return;
- case DATA_BMP_LOAD:
- len=av7110->debilen;
+ case DATA_BMP_LOAD:
+ len = av7110->debilen;
dprintk(8, "gpio DATA_BMP_LOAD len %d\n", len);
- if (!len) {
- av7110->bmp_state=BMP_LOADED;
- iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
- iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
- iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
- wake_up(&av7110->bmpq);
+ if (!len) {
+ av7110->bmp_state = BMP_LOADED;
+ iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
+ iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
+ iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
+ wake_up(&av7110->bmpq);
dprintk(8, "gpio DATA_BMP_LOAD done\n");
- break;
- }
- if (len>av7110->bmplen)
- len=av7110->bmplen;
- if (len>2*1024)
- len=2*1024;
- iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2);
- iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, len, 2);
- memcpy(av7110->debi_virt, av7110->bmpbuf+av7110->bmpp, len);
- av7110->bmpp+=len;
- av7110->bmplen-=len;
+ break;
+ }
+ if (len > av7110->bmplen)
+ len = av7110->bmplen;
+ if (len > 2 * 1024)
+ len = 2 * 1024;
+ iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2);
+ iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, len, 2);
+ memcpy(av7110->debi_virt, av7110->bmpbuf+av7110->bmpp, len);
+ av7110->bmpp += len;
+ av7110->bmplen -= len;
dprintk(8, "gpio DATA_BMP_LOAD DMA len %d\n", len);
start_debi_dma(av7110, DEBI_WRITE, DPRAM_BASE+txbuf, len);
- spin_unlock(&av7110->debilock);
- return;
-
- case DATA_CI_GET:
- case DATA_COMMON_INTERFACE:
- case DATA_FSECTION:
- case DATA_IPMPE:
- case DATA_PIPING:
- if (!len || len>4*1024) {
- iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
- break;
+ spin_unlock(&av7110->debilock);
+ return;
+
+ case DATA_CI_GET:
+ case DATA_COMMON_INTERFACE:
+ case DATA_FSECTION:
+ case DATA_IPMPE:
+ case DATA_PIPING:
+ if (!len || len > 4 * 1024) {
+ iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
+ break;
}
/* fall through */
- case DATA_TS_RECORD:
- case DATA_PES_RECORD:
+ case DATA_TS_RECORD:
+ case DATA_PES_RECORD:
dprintk(8, "DMA: TS_REC etc.\n");
start_debi_dma(av7110, DEBI_READ, DPRAM_BASE+rxbuf, len);
- spin_unlock(&av7110->debilock);
- return;
-
- case DATA_DEBUG_MESSAGE:
- if (!len || len>0xff) {
- iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
- break;
- }
+ spin_unlock(&av7110->debilock);
+ return;
+
+ case DATA_DEBUG_MESSAGE:
+ if (!len || len > 0xff) {
+ iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
+ break;
+ }
start_debi_dma(av7110, DEBI_READ, Reserved, len);
- spin_unlock(&av7110->debilock);
- return;
+ spin_unlock(&av7110->debilock);
+ return;
- case DATA_IRCOMMAND:
- IR_handle(av7110,
- swahw32(irdebi(av7110, DEBINOSWAP, Reserved, 0, 4)));
- iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
- break;
+ case DATA_IRCOMMAND:
+ IR_handle(av7110,
+ swahw32(irdebi(av7110, DEBINOSWAP, Reserved, 0, 4)));
+ iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
+ break;
- default:
+ default:
printk("dvb-ttpci: gpioirq unknown type=%d len=%d\n",
- av7110->debitype, av7110->debilen);
- break;
- }
- av7110->debitype=-1;
+ av7110->debitype, av7110->debilen);
+ break;
+ }
+ av7110->debitype = -1;
ARM_ClearMailBox(av7110);
- spin_unlock(&av7110->debilock);
+ spin_unlock(&av7110->debilock);
}
@@ -718,7 +727,7 @@ static int dvb_osd_ioctl(struct inode *inode, struct file *file,
return av7110_osd_capability(av7110, (osd_cap_t *) parg);
return -EINVAL;
- }
+}
static struct file_operations dvb_osd_fops = {
@@ -740,7 +749,7 @@ static struct dvb_device dvbdev_osd = {
static inline int SetPIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid,
u16 subpid, u16 pcrpid)
- {
+{
dprintk(4, "%p\n", av7110);
if (vpid == 0x1fff || apid == 0x1fff ||
@@ -760,7 +769,7 @@ void ChangePIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid,
u16 subpid, u16 pcrpid)
{
dprintk(4, "%p\n", av7110);
-
+
if (down_interruptible(&av7110->pid_mutex))
return;
@@ -772,13 +781,13 @@ void ChangePIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid,
av7110->pids[DMX_PES_TELETEXT] = ttpid;
if (!(pcrpid & 0x8000))
av7110->pids[DMX_PES_PCR] = pcrpid;
-
+
av7110->pids[DMX_PES_SUBTITLE] = 0;
if (av7110->fe_synced) {
pcrpid = av7110->pids[DMX_PES_PCR];
SetPIDs(av7110, vpid, apid, ttpid, subpid, pcrpid);
- }
+ }
up(&av7110->pid_mutex);
}
@@ -795,8 +804,8 @@ static int StartHWFilter(struct dvb_demux_filter *dvbdmxfilter)
u16 buf[20];
int ret, i;
u16 handle;
-// u16 mode=0x0320;
- u16 mode=0xb96a;
+// u16 mode = 0x0320;
+ u16 mode = 0xb96a;
dprintk(4, "%p\n", av7110);
@@ -809,11 +818,11 @@ static int StartHWFilter(struct dvb_demux_filter *dvbdmxfilter)
(dvbdmxfilter->filter.filter_value[i] << 8) |
dvbdmxfilter->maskandmode[i];
mode = 4;
- }
+ }
} else if ((dvbdmxfeed->ts_type & TS_PACKET) &&
!(dvbdmxfeed->ts_type & TS_PAYLOAD_ONLY)) {
av7110_p2t_init(&av7110->p2t_filter[dvbdmxfilter->index], dvbdmxfeed);
- }
+ }
buf[0] = (COMTYPE_PID_FILTER << 8) + AddPIDFilter;
buf[1] = 16;
@@ -828,13 +837,13 @@ static int StartHWFilter(struct dvb_demux_filter *dvbdmxfilter)
ret, handle);
dvbdmxfilter->hw_handle = 0xffff;
return -1;
- }
+ }
av7110->handle2filter[handle] = dvbdmxfilter;
dvbdmxfilter->hw_handle = handle;
return ret;
- }
+}
static int StopHWFilter(struct dvb_demux_filter *dvbdmxfilter)
{
@@ -843,7 +852,7 @@ static int StopHWFilter(struct dvb_demux_filter *dvbdmxfilter)
u16 answ[2];
int ret;
u16 handle;
-
+
dprintk(4, "%p\n", av7110);
handle = dvbdmxfilter->hw_handle;
@@ -851,7 +860,7 @@ static int StopHWFilter(struct dvb_demux_filter *dvbdmxfilter)
printk("%s tried to stop invalid filter %04x, filter type = %x\n",
__FUNCTION__, handle, dvbdmxfilter->type);
return 0;
- }
+ }
av7110->handle2filter[handle] = NULL;
@@ -865,8 +874,8 @@ static int StopHWFilter(struct dvb_demux_filter *dvbdmxfilter)
__FUNCTION__, buf[0], buf[1], buf[2], ret,
answ[0], answ[1], dvbdmxfilter->feed->pid);
ret = -1;
- }
- return ret;
+ }
+ return ret;
}
@@ -890,7 +899,7 @@ static void dvb_feed_start_pid(struct dvb_demux_feed *dvbdmxfeed)
}
if (dvbdmxfeed->pes_type <= 2 || dvbdmxfeed->pes_type == 4)
ChangePIDs(av7110, npids[1], npids[0], npids[2], npids[3], npids[4]);
-
+
if (dvbdmxfeed->pes_type < 2 && npids[0])
if (av7110->fe_synced)
av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, Scan, 0);
@@ -902,16 +911,16 @@ static void dvb_feed_start_pid(struct dvb_demux_feed *dvbdmxfeed)
av7110_av_start_record(av7110, RP_VIDEO, dvbdmxfeed);
}
}
-
+
static void dvb_feed_stop_pid(struct dvb_demux_feed *dvbdmxfeed)
{
struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
struct av7110 *av7110 = (struct av7110 *) dvbdmx->priv;
u16 *pid = dvbdmx->pids, npids[5];
int i;
-
+
dprintk(4, "%p\n", av7110);
-
+
if (dvbdmxfeed->pes_type <= 1) {
av7110_av_stop(av7110, dvbdmxfeed->pes_type ? RP_VIDEO : RP_AUDIO);
if (!av7110->rec_mode)
@@ -926,31 +935,31 @@ static void dvb_feed_stop_pid(struct dvb_demux_feed *dvbdmxfeed)
if (dvbdmxfeed->ts_type & TS_PACKET)
StopHWFilter(dvbdmxfeed->filter);
npids[2] = 0;
- break;
+ break;
case 0:
case 1:
case 4:
if (!pids_off)
return;
npids[i] = (pid[i]&0x8000) ? 0 : pid[i];
- break;
- }
+ break;
+ }
ChangePIDs(av7110, npids[1], npids[0], npids[2], npids[3], npids[4]);
}
-
+
static int av7110_start_feed(struct dvb_demux_feed *feed)
{
struct dvb_demux *demux = feed->demux;
struct av7110 *av7110 = demux->priv;
-
+
dprintk(4, "%p\n", av7110);
-
+
if (!demux->dmx.frontend)
return -EINVAL;
-
+
if (feed->pid > 0x1fff)
return -EINVAL;
-
+
if (feed->type == DMX_TYPE_TS) {
if ((feed->ts_type & TS_DECODER) &&
(feed->pes_type < DMX_TS_PES_OTHER)) {
@@ -965,17 +974,17 @@ static int av7110_start_feed(struct dvb_demux_feed *feed)
av7110_av_start_play(av7110,RP_AV);
demux->playing = 1;
}
- break;
- default:
+ break;
+ default:
dvb_feed_start_pid(feed);
- break;
- }
+ break;
+ }
} else if ((feed->ts_type & TS_PACKET) &&
(demux->dmx.frontend->source != DMX_MEMORY_FE)) {
StartHWFilter(feed->filter);
}
}
-
+
if (feed->type == DMX_TYPE_SEC) {
int i;
@@ -989,8 +998,8 @@ static int av7110_start_feed(struct dvb_demux_feed *feed)
demux->filter[i].state = DMX_STATE_GO;
if (demux->dmx.frontend->source != DMX_MEMORY_FE)
StartHWFilter(&demux->filter[i]);
- }
- }
+ }
+ }
return 0;
}
@@ -1023,7 +1032,7 @@ static int av7110_stop_feed(struct dvb_demux_feed *feed)
if (feed->type == DMX_TYPE_SEC) {
int i;
- for (i=0; i<demux->filternum; i++)
+ for (i = 0; i<demux->filternum; i++)
if (demux->filter[i].state == DMX_STATE_GO &&
demux->filter[i].filter.parent == &feed->feed.sec) {
demux->filter[i].state = DMX_STATE_READY;
@@ -1032,7 +1041,7 @@ static int av7110_stop_feed(struct dvb_demux_feed *feed)
}
}
- return 0;
+ return 0;
}
@@ -1085,14 +1094,14 @@ static int dvb_get_stc(struct dmx_demux *demux, unsigned int num,
if (ret) {
printk(KERN_ERR "%s: av7110_fw_request error\n", __FUNCTION__);
return -EIO;
-}
+ }
dprintk(2, "fwstc = %04hx %04hx %04hx %04hx\n",
fwstc[0], fwstc[1], fwstc[2], fwstc[3]);
*stc = (((uint64_t) ((fwstc[3] & 0x8000) >> 15)) << 32) |
(((uint64_t) fwstc[1]) << 16) | ((uint64_t) fwstc[0]);
*base = 1;
-
+
dprintk(4, "stc = %lu\n", (unsigned long)*stc);
return 0;
@@ -1109,15 +1118,16 @@ static int av7110_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
switch (tone) {
- case SEC_TONE_ON:
- Set22K(av7110, 1);
- break;
- case SEC_TONE_OFF:
- Set22K(av7110, 0);
- break;
+ case SEC_TONE_ON:
+ Set22K(av7110, 1);
+ break;
- default:
- return -EINVAL;
+ case SEC_TONE_OFF:
+ Set22K(av7110, 0);
+ break;
+
+ default:
+ return -EINVAL;
}
return 0;
@@ -1241,21 +1251,21 @@ static void vpeirq(unsigned long data)
static int av7110_register(struct av7110 *av7110)
{
- int ret, i;
- struct dvb_demux *dvbdemux=&av7110->demux;
+ int ret, i;
+ struct dvb_demux *dvbdemux = &av7110->demux;
struct dvb_demux *dvbdemux1 = &av7110->demux1;
dprintk(4, "%p\n", av7110);
- if (av7110->registered)
- return -1;
+ if (av7110->registered)
+ return -1;
- av7110->registered=1;
+ av7110->registered = 1;
- dvbdemux->priv = (void *) av7110;
+ dvbdemux->priv = (void *) av7110;
- for (i=0; i<32; i++)
- av7110->handle2filter[i]=NULL;
+ for (i = 0; i < 32; i++)
+ av7110->handle2filter[i] = NULL;
dvbdemux->filternum = 32;
dvbdemux->feednum = 32;
@@ -1271,27 +1281,27 @@ static int av7110_register(struct av7110 *av7110)
av7110->dmxdev.filternum = 32;
av7110->dmxdev.demux = &dvbdemux->dmx;
av7110->dmxdev.capabilities = 0;
-
+
dvb_dmxdev_init(&av7110->dmxdev, av7110->dvb_adapter);
- av7110->hw_frontend.source = DMX_FRONTEND_0;
+ av7110->hw_frontend.source = DMX_FRONTEND_0;
+
+ ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &av7110->hw_frontend);
- ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &av7110->hw_frontend);
+ if (ret < 0)
+ return ret;
- if (ret < 0)
- return ret;
-
- av7110->mem_frontend.source = DMX_MEMORY_FE;
+ av7110->mem_frontend.source = DMX_MEMORY_FE;
ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &av7110->mem_frontend);
if (ret < 0)
- return ret;
-
- ret = dvbdemux->dmx.connect_frontend(&dvbdemux->dmx,
+ return ret;
+
+ ret = dvbdemux->dmx.connect_frontend(&dvbdemux->dmx,
&av7110->hw_frontend);
- if (ret < 0)
- return ret;
+ if (ret < 0)
+ return ret;
av7110_av_register(av7110);
av7110_ca_register(av7110);
@@ -1300,8 +1310,8 @@ static int av7110_register(struct av7110 *av7110)
dvb_register_device(av7110->dvb_adapter, &av7110->osd_dev,
&dvbdev_osd, av7110, DVB_DEVICE_OSD);
#endif
-
- dvb_net_init(av7110->dvb_adapter, &av7110->dvb_net, &dvbdemux->dmx);
+
+ dvb_net_init(av7110->dvb_adapter, &av7110->dvb_net, &dvbdemux->dmx);
if (budgetpatch) {
/* initialize software demux1 without its own frontend
@@ -1335,13 +1345,13 @@ static int av7110_register(struct av7110 *av7110)
static void dvb_unregister(struct av7110 *av7110)
{
- struct dvb_demux *dvbdemux=&av7110->demux;
+ struct dvb_demux *dvbdemux = &av7110->demux;
struct dvb_demux *dvbdemux1 = &av7110->demux1;
dprintk(4, "%p\n", av7110);
- if (!av7110->registered)
- return;
+ if (!av7110->registered)
+ return;
if (budgetpatch) {
dvb_net_release(&av7110->dvb_net1);
@@ -1353,11 +1363,11 @@ static void dvb_unregister(struct av7110 *av7110)
dvb_net_release(&av7110->dvb_net);
dvbdemux->dmx.close(&dvbdemux->dmx);
- dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &av7110->hw_frontend);
- dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &av7110->mem_frontend);
+ dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &av7110->hw_frontend);
+ dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &av7110->mem_frontend);
- dvb_dmxdev_release(&av7110->dmxdev);
- dvb_dmx_release(&av7110->demux);
+ dvb_dmxdev_release(&av7110->dmxdev);
+ dvb_dmx_release(&av7110->demux);
if (av7110->fe != NULL)
dvb_unregister_frontend(av7110->fe);
@@ -1375,7 +1385,7 @@ int i2c_writereg(struct av7110 *av7110, u8 id, u8 reg, u8 val)
{
u8 msg[2] = { reg, val };
struct i2c_msg msgs;
-
+
msgs.flags = 0;
msgs.addr = id / 2;
msgs.len = 2;
@@ -1411,10 +1421,10 @@ static int check_firmware(struct av7110* av7110)
{
u32 crc = 0, len = 0;
unsigned char *ptr;
-
+
/* check for firmware magic */
ptr = av7110->bin_fw;
- if (ptr[0] != 'A' || ptr[1] != 'V' ||
+ if (ptr[0] != 'A' || ptr[1] != 'V' ||
ptr[2] != 'F' || ptr[3] != 'W') {
printk("dvb-ttpci: this is not an av7110 firmware\n");
return -EINVAL;
@@ -1422,34 +1432,34 @@ static int check_firmware(struct av7110* av7110)
ptr += 4;
/* check dpram file */
- crc = ntohl(*(u32*)ptr);
+ crc = ntohl(*(u32*) ptr);
ptr += 4;
- len = ntohl(*(u32*)ptr);
+ len = ntohl(*(u32*) ptr);
ptr += 4;
if (len >= 512) {
printk("dvb-ttpci: dpram file is way to big.\n");
return -EINVAL;
}
- if( crc != crc32_le(0,ptr,len)) {
+ if (crc != crc32_le(0, ptr, len)) {
printk("dvb-ttpci: crc32 of dpram file does not match.\n");
return -EINVAL;
}
av7110->bin_dpram = ptr;
av7110->size_dpram = len;
ptr += len;
-
+
/* check root file */
- crc = ntohl(*(u32*)ptr);
+ crc = ntohl(*(u32*) ptr);
ptr += 4;
- len = ntohl(*(u32*)ptr);
+ len = ntohl(*(u32*) ptr);
ptr += 4;
-
+
if (len <= 200000 || len >= 300000 ||
len > ((av7110->bin_fw + av7110->size_fw) - ptr)) {
- printk("dvb-ttpci: root file has strange size (%d). aborting.\n",len);
+ printk("dvb-ttpci: root file has strange size (%d). aborting.\n", len);
return -EINVAL;
}
- if( crc != crc32_le(0,ptr,len)) {
+ if( crc != crc32_le(0, ptr, len)) {
printk("dvb-ttpci: crc32 of root file does not match.\n");
return -EINVAL;
}
@@ -1460,6 +1470,11 @@ static int check_firmware(struct av7110* av7110)
#ifdef CONFIG_DVB_AV7110_FIRMWARE_FILE
#include "av7110_firm.h"
+static void put_firmware(struct av7110* av7110)
+{
+ av7110->bin_fw = NULL;
+}
+
static inline int get_firmware(struct av7110* av7110)
{
av7110->bin_fw = dvb_ttpci_fw;
@@ -1467,6 +1482,11 @@ static inline int get_firmware(struct av7110* av7110)
return check_firmware(av7110);
}
#else
+static void put_firmware(struct av7110* av7110)
+{
+ vfree(av7110->bin_fw);
+}
+
static int get_firmware(struct av7110* av7110)
{
int ret;
@@ -1495,7 +1515,7 @@ static int get_firmware(struct av7110* av7110)
}
/* check if the firmware is available */
- av7110->bin_fw = (unsigned char*) vmalloc(fw->size);
+ av7110->bin_fw = (unsigned char *) vmalloc(fw->size);
if (NULL == av7110->bin_fw) {
dprintk(1, "out of memory\n");
release_firmware(fw);
@@ -1603,11 +1623,11 @@ static int alps_bsru6_set_symbol_rate(struct dvb_frontend* fe, u32 srate, u32 ra
else if (srate < 30000000) { aclk = 0xb6; bclk = 0x53; }
else if (srate < 45000000) { aclk = 0xb4; bclk = 0x51; }
- stv0299_writereg (fe, 0x13, aclk);
- stv0299_writereg (fe, 0x14, bclk);
- stv0299_writereg (fe, 0x1f, (ratio >> 16) & 0xff);
- stv0299_writereg (fe, 0x20, (ratio >> 8) & 0xff);
- stv0299_writereg (fe, 0x21, (ratio ) & 0xf0);
+ stv0299_writereg(fe, 0x13, aclk);
+ stv0299_writereg(fe, 0x14, bclk);
+ stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);
+ stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff);
+ stv0299_writereg(fe, 0x21, (ratio ) & 0xf0);
return 0;
}
@@ -1631,7 +1651,7 @@ static int alps_bsru6_pll_set(struct dvb_frontend* fe, struct dvb_frontend_param
if (params->frequency > 1530000) data[3] = 0xc0;
- ret = i2c_transfer (&av7110->i2c_adap, &msg, 1);
+ ret = i2c_transfer(&av7110->i2c_adap, &msg, 1);
if (ret != 1)
return -EIO;
return 0;
@@ -1668,7 +1688,7 @@ static int alps_tdbe2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_param
data[2] = 0x85 | ((div >> 10) & 0x60);
data[3] = (params->frequency < 174000000 ? 0x88 : params->frequency < 470000000 ? 0x84 : 0x81);
- if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1)
+ if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
return -EIO;
return 0;
}
@@ -1698,7 +1718,7 @@ static int grundig_29504_451_pll_set(struct dvb_frontend* fe,
data[2] = 0x8e;
data[3] = 0x00;
- if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1)
+ if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
return -EIO;
return 0;
}
@@ -1726,7 +1746,7 @@ static int philips_cd1516_pll_set(struct dvb_frontend* fe,
data[2] = 0x8e;
data[3] = (f < 174000000 ? 0xa1 : f < 470000000 ? 0x92 : 0x34);
- if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1)
+ if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
return -EIO;
return 0;
}
@@ -1760,7 +1780,7 @@ static int alps_tdlb7_pll_set(struct dvb_frontend* fe, struct dvb_frontend_param
data[2] = 0x85;
data[3] = pwr << 6;
- if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1)
+ if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
return -EIO;
return 0;
}
@@ -1808,16 +1828,16 @@ static int nexusca_stv0297_pll_set(struct dvb_frontend* fe, struct dvb_frontend_
return -EINVAL;
stv0297_enable_plli2c(fe);
- if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1) {
+ if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1) {
printk("nexusca: pll transfer failed!\n");
return -EIO;
}
// wait for PLL lock
- for(i=0; i< 20; i++) {
+ for(i = 0; i < 20; i++) {
stv0297_enable_plli2c(fe);
- if (i2c_transfer (&av7110->i2c_adap, &readmsg, 1) == 1)
+ if (i2c_transfer(&av7110->i2c_adap, &readmsg, 1) == 1)
if (data[0] & 0x40) break;
msleep(10);
}
@@ -1833,6 +1853,45 @@ static struct stv0297_config nexusca_stv0297_config = {
};
+
+static int grundig_29504_401_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+{
+ struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
+ u32 div;
+ u8 cfg, cpump, band_select;
+ u8 data[4];
+ struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
+
+ div = (36125000 + params->frequency) / 166666;
+
+ cfg = 0x88;
+
+ if (params->frequency < 175000000) cpump = 2;
+ else if (params->frequency < 390000000) cpump = 1;
+ else if (params->frequency < 470000000) cpump = 2;
+ else if (params->frequency < 750000000) cpump = 1;
+ else cpump = 3;
+
+ if (params->frequency < 175000000) band_select = 0x0e;
+ else if (params->frequency < 470000000) band_select = 0x05;
+ else band_select = 0x03;
+
+ data[0] = (div >> 8) & 0x7f;
+ data[1] = div & 0xff;
+ data[2] = ((div >> 10) & 0x60) | cfg;
+ data[3] = (cpump << 6) | band_select;
+
+ if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1) return -EIO;
+ return 0;
+}
+
+static struct l64781_config grundig_29504_401_config = {
+ .demod_address = 0x55,
+ .pll_set = grundig_29504_401_pll_set,
+};
+
+
+
static void av7110_fe_lock_fix(struct av7110* av7110, fe_status_t status)
{
int synced = (status & FE_HAS_LOCK) ? 1 : 0;
@@ -1855,9 +1914,9 @@ static void av7110_fe_lock_fix(struct av7110* av7110, fe_status_t status)
av7110->pids[DMX_PES_AUDIO],
av7110->pids[DMX_PES_TELETEXT], 0,
av7110->pids[DMX_PES_PCR]);
- av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, Scan, 0);
+ av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, Scan, 0);
} else {
- SetPIDs(av7110, 0, 0, 0, 0, 0);
+ SetPIDs(av7110, 0, 0, 0, 0, 0);
av7110_fw_cmd(av7110, COMTYPE_PID_FILTER, FlushTSQueue, 0);
av7110_wait_msgstate(av7110, GPMQBusy);
}
@@ -1959,8 +2018,10 @@ static u8 read_pwm(struct av7110* av7110)
return pwm;
}
-static void frontend_init(struct av7110 *av7110)
+static int frontend_init(struct av7110 *av7110)
{
+ int ret;
+
if (av7110->dev->pci->subsystem_vendor == 0x110a) {
switch(av7110->dev->pci->subsystem_device) {
case 0x0000: // Fujitsu/Siemens DVB-Cable (ves1820/Philips CD1516(??))
@@ -2038,6 +2099,11 @@ static void frontend_init(struct av7110 *av7110)
}
break;
+ case 0x0008: // Hauppauge/TT DVB-T
+
+ av7110->fe = l64781_attach(&grundig_29504_401_config, &av7110->i2c_adap);
+ break;
+
case 0x000A: // Hauppauge/TT Nexus-CA rev1.X
av7110->fe = stv0297_attach(&nexusca_stv0297_config, &av7110->i2c_adap, 0x7b);
@@ -2053,7 +2119,9 @@ static void frontend_init(struct av7110 *av7110)
}
}
- if (av7110->fe == NULL) {
+ if (!av7110->fe) {
+ /* FIXME: propagate the failure code from the lower layers */
+ ret = -ENOMEM;
printk("dvb-ttpci: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n",
av7110->dev->pci->vendor,
av7110->dev->pci->device,
@@ -2070,13 +2138,15 @@ static void frontend_init(struct av7110 *av7110)
FE_FUNC_OVERRIDE(av7110->fe->ops->dishnetwork_send_legacy_command, av7110->fe_dishnetwork_send_legacy_command, av7110_fe_dishnetwork_send_legacy_command);
FE_FUNC_OVERRIDE(av7110->fe->ops->set_frontend, av7110->fe_set_frontend, av7110_fe_set_frontend);
- if (dvb_register_frontend(av7110->dvb_adapter, av7110->fe)) {
+ ret = dvb_register_frontend(av7110->dvb_adapter, av7110->fe);
+ if (ret < 0) {
printk("av7110: Frontend registration failed!\n");
if (av7110->fe->ops->release)
av7110->fe->ops->release(av7110->fe);
av7110->fe = NULL;
}
}
+ return ret;
}
/* Budgetpatch note:
@@ -2146,10 +2216,10 @@ static void frontend_init(struct av7110 *av7110)
*/
static int av7110_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_data *pci_ext)
{
- struct av7110 *av7110 = NULL;
- int length = TS_WIDTH * TS_HEIGHT;
- int ret = 0;
- int count = 0;
+ const int length = TS_WIDTH * TS_HEIGHT;
+ struct pci_dev *pdev = dev->pci;
+ struct av7110 *av7110;
+ int ret, count = 0;
dprintk(4, "dev: %p\n", dev);
@@ -2243,23 +2313,26 @@ static int av7110_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_d
}
/* prepare the av7110 device struct */
- if (!(av7110 = kmalloc (sizeof (struct av7110), GFP_KERNEL))) {
+ av7110 = kmalloc(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->card_name = (char*) pci_ext->ext_priv;
av7110->dev = dev;
dev->ext_priv = av7110;
- if ((ret = get_firmware(av7110))) {
- kfree(av7110);
- return ret;
- }
+ ret = get_firmware(av7110);
+ if (ret < 0)
+ goto err_kfree_0;
- dvb_register_adapter(&av7110->dvb_adapter, av7110->card_name, THIS_MODULE);
+ ret = dvb_register_adapter(&av7110->dvb_adapter, av7110->card_name,
+ THIS_MODULE);
+ if (ret < 0)
+ goto err_put_firmware_1;
/* the Siemens DVB needs this if you want to have the i2c chips
get recognized before the main driver is fully loaded */
@@ -2274,21 +2347,21 @@ static int av7110_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_d
saa7146_i2c_adapter_prepare(dev, &av7110->i2c_adap, SAA7146_I2C_BUS_BIT_RATE_120); /* 275 kHz */
- if (i2c_add_adapter(&av7110->i2c_adap) < 0) {
-err_no_mem:
- dvb_unregister_adapter (av7110->dvb_adapter);
- kfree(av7110);
- return -ENOMEM;
- }
+ ret = i2c_add_adapter(&av7110->i2c_adap);
+ if (ret < 0)
+ goto err_dvb_unregister_adapter_2;
- ttpci_eeprom_parse_mac(&av7110->i2c_adap, av7110->dvb_adapter->proposed_mac);
+ ttpci_eeprom_parse_mac(&av7110->i2c_adap,
+ av7110->dvb_adapter->proposed_mac);
+ ret = -ENOMEM;
if (budgetpatch) {
spin_lock_init(&av7110->feedlock1);
- av7110->grabbing = saa7146_vmalloc_build_pgtable(
- dev->pci, length, &av7110->pt);
+ av7110->grabbing = saa7146_vmalloc_build_pgtable(pdev, length,
+ &av7110->pt);
if (!av7110->grabbing)
- goto err_no_mem;
+ goto err_i2c_del_3;
+
saa7146_write(dev, PCI_BT_V1, 0x1c1f101f);
saa7146_write(dev, BCS_CTRL, 0x80400040);
/* set dd1 stream a & b */
@@ -2363,131 +2436,140 @@ err_no_mem:
/* end of budgetpatch register initialization */
tasklet_init (&av7110->vpe_tasklet, vpeirq, (unsigned long) av7110);
} else {
- saa7146_write(dev, PCI_BT_V1, 0x1c00101f);
- saa7146_write(dev, BCS_CTRL, 0x80400040);
+ saa7146_write(dev, PCI_BT_V1, 0x1c00101f);
+ saa7146_write(dev, BCS_CTRL, 0x80400040);
- /* set dd1 stream a & b */
- saa7146_write(dev, DD1_STREAM_B, 0x00000000);
- saa7146_write(dev, DD1_INIT, 0x03000000);
- saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
+ /* set dd1 stream a & b */
+ saa7146_write(dev, DD1_STREAM_B, 0x00000000);
+ saa7146_write(dev, DD1_INIT, 0x03000000);
+ saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
- /* upload all */
- saa7146_write(dev, MC2, 0x077c077c);
- saa7146_write(dev, GPIO_CTRL, 0x000000);
+ /* upload all */
+ saa7146_write(dev, MC2, 0x077c077c);
+ saa7146_write(dev, GPIO_CTRL, 0x000000);
}
tasklet_init (&av7110->debi_tasklet, debiirq, (unsigned long) av7110);
tasklet_init (&av7110->gpio_tasklet, gpioirq, (unsigned long) av7110);
- sema_init(&av7110->pid_mutex, 1);
+ sema_init(&av7110->pid_mutex, 1);
- /* locks for data transfers from/to AV7110 */
- spin_lock_init (&av7110->debilock);
- sema_init(&av7110->dcomlock, 1);
- av7110->debitype=-1;
+ /* locks for data transfers from/to AV7110 */
+ spin_lock_init(&av7110->debilock);
+ sema_init(&av7110->dcomlock, 1);
+ av7110->debitype = -1;
- /* default OSD window */
- av7110->osdwin=1;
+ /* default OSD window */
+ av7110->osdwin = 1;
sema_init(&av7110->osd_sema, 1);
- /* ARM "watchdog" */
+ /* ARM "watchdog" */
init_waitqueue_head(&av7110->arm_wait);
- av7110->arm_thread=NULL;
-
- /* allocate and init buffers */
- av7110->debi_virt = pci_alloc_consistent(dev->pci, 8192,
- &av7110->debi_bus);
- if (!av7110->debi_virt) {
- ret = -ENOMEM;
- goto err;
- }
+ av7110->arm_thread = NULL;
- av7110->iobuf = vmalloc(AVOUTLEN+AOUTLEN+BMPLEN+4*IPACKS);
- if (!av7110->iobuf) {
- ret = -ENOMEM;
- goto err;
- }
+ /* allocate and init buffers */
+ av7110->debi_virt = pci_alloc_consistent(pdev, 8192, &av7110->debi_bus);
+ if (!av7110->debi_virt)
+ goto err_saa71466_vfree_4;
- av7110_av_init(av7110);
- /* init BMP buffer */
- av7110->bmpbuf=av7110->iobuf+AVOUTLEN+AOUTLEN;
- init_waitqueue_head(&av7110->bmpq);
-
- av7110_ca_init(av7110);
+ av7110->iobuf = vmalloc(AVOUTLEN+AOUTLEN+BMPLEN+4*IPACKS);
+ if (!av7110->iobuf)
+ goto err_pci_free_5;
- /* load firmware into AV7110 cards */
- av7110_bootarm(av7110);
- if (av7110_firmversion(av7110)) {
- ret = -EIO;
- goto err2;
- }
+ ret = av7110_av_init(av7110);
+ if (ret < 0)
+ goto err_iobuf_vfree_6;
+
+ /* init BMP buffer */
+ av7110->bmpbuf = av7110->iobuf+AVOUTLEN+AOUTLEN;
+ init_waitqueue_head(&av7110->bmpq);
+
+ ret = av7110_ca_init(av7110);
+ if (ret < 0)
+ goto err_av7110_av_exit_7;
+
+ /* load firmware into AV7110 cards */
+ ret = av7110_bootarm(av7110);
+ if (ret < 0)
+ goto err_av7110_ca_exit_8;
+
+ ret = av7110_firmversion(av7110);
+ if (ret < 0)
+ goto err_stop_arm_9;
if (FW_VERSION(av7110->arm_app)<0x2501)
printk ("dvb-ttpci: Warning, firmware version 0x%04x is too old. "
"System might be unstable!\n", FW_VERSION(av7110->arm_app));
- if (kernel_thread(arm_thread, (void *) av7110, 0) < 0) {
- printk("dvb-ttpci: failed to start arm_mon kernel thread @ card %d\n",
- av7110->dvb_adapter->num);
- goto err2;
- }
+ ret = kernel_thread(arm_thread, (void *) av7110, 0);
+ if (ret < 0)
+ goto err_stop_arm_9;
/* set initial volume in mixer struct */
av7110->mixer.volume_left = volume;
av7110->mixer.volume_right = volume;
-
+
init_av7110_av(av7110);
- av7110_register(av7110);
-
+ ret = av7110_register(av7110);
+ if (ret < 0)
+ goto err_arm_thread_stop_10;
+
/* special case DVB-C: these cards have an analog tuner
plus need some special handling, so we have separate
saa7146_ext_vv data for these... */
ret = av7110_init_v4l(av7110);
-
- if (ret)
- goto err3;
+ if (ret < 0)
+ goto err_av7110_unregister_11;
av7110->dvb_adapter->priv = av7110;
- frontend_init(av7110);
+ ret = frontend_init(av7110);
+ if (ret < 0)
+ goto err_av7110_exit_v4l_12;
+#if defined(CONFIG_INPUT_EVDEV) || defined(CONFIG_INPUT_EVDEV_MODULE)
+ av7110_ir_init();
+#endif
printk(KERN_INFO "dvb-ttpci: found av7110-%d.\n", av7110_num);
- av7110->device_initialized = 1;
av7110_num++;
- return 0;
+out:
+ return ret;
-err3:
- av7110->arm_rmmod = 1;
- wake_up_interruptible(&av7110->arm_wait);
- while (av7110->arm_thread)
- msleep(1);
-err2:
+err_av7110_exit_v4l_12:
+ av7110_exit_v4l(av7110);
+err_av7110_unregister_11:
+ dvb_unregister(av7110);
+err_arm_thread_stop_10:
+ av7110_arm_sync(av7110);
+err_stop_arm_9:
+ /* Nothing to do. Rejoice. */
+err_av7110_ca_exit_8:
av7110_ca_exit(av7110);
+err_av7110_av_exit_7:
av7110_av_exit(av7110);
-err:
+err_iobuf_vfree_6:
+ vfree(av7110->iobuf);
+err_pci_free_5:
+ pci_free_consistent(pdev, 8192, av7110->debi_virt, av7110->debi_bus);
+err_saa71466_vfree_4:
+ if (!av7110->grabbing)
+ saa7146_pgtable_free(pdev, &av7110->pt);
+err_i2c_del_3:
i2c_del_adapter(&av7110->i2c_adap);
-
- dvb_unregister_adapter (av7110->dvb_adapter);
-
- if (NULL != av7110->debi_virt)
- pci_free_consistent(dev->pci, 8192, av7110->debi_virt, av7110->debi_bus);
- if (NULL != av7110->iobuf)
- vfree(av7110->iobuf);
- if (NULL != av7110 ) {
- kfree(av7110);
- }
-
- return ret;
+err_dvb_unregister_adapter_2:
+ dvb_unregister_adapter(av7110->dvb_adapter);
+err_put_firmware_1:
+ put_firmware(av7110);
+err_kfree_0:
+ kfree(av7110);
+ goto out;
}
-static int av7110_detach (struct saa7146_dev* saa)
+static int av7110_detach(struct saa7146_dev* saa)
{
- struct av7110 *av7110 = (struct av7110*)saa->ext_priv;
+ struct av7110 *av7110 = saa->ext_priv;
dprintk(4, "%p\n", av7110);
-
- if (!av7110->device_initialized )
- return 0;
if (budgetpatch) {
/* Disable RPS1 */
@@ -2503,17 +2585,13 @@ static int av7110_detach (struct saa7146_dev* saa)
}
av7110_exit_v4l(av7110);
- av7110->arm_rmmod=1;
- wake_up_interruptible(&av7110->arm_wait);
-
- while (av7110->arm_thread)
- msleep(1);
+ av7110_arm_sync(av7110);
tasklet_kill(&av7110->debi_tasklet);
tasklet_kill(&av7110->gpio_tasklet);
dvb_unregister(av7110);
-
+
SAA7146_IER_DISABLE(saa, MASK_19 | MASK_03);
SAA7146_ISR_CLEAR(saa, MASK_19 | MASK_03);
@@ -2529,18 +2607,18 @@ static int av7110_detach (struct saa7146_dev* saa)
dvb_unregister_adapter (av7110->dvb_adapter);
av7110_num--;
-#ifndef CONFIG_DVB_AV7110_FIRMWARE_FILE
- if (av7110->bin_fw)
- vfree(av7110->bin_fw);
-#endif
- kfree (av7110);
+
+ put_firmware(av7110);
+
+ kfree(av7110);
+
saa->ext_priv = NULL;
return 0;
}
-static void av7110_irq(struct saa7146_dev* dev, u32 *isr)
+static void av7110_irq(struct saa7146_dev* dev, u32 *isr)
{
struct av7110 *av7110 = dev->ext_priv;
@@ -2569,13 +2647,13 @@ static void av7110_irq(struct saa7146_dev* dev, u32 *isr)
*/
SAA7146_IER_DISABLE(av7110->dev, MASK_19);
SAA7146_ISR_CLEAR(av7110->dev, MASK_19);
- tasklet_schedule (&av7110->debi_tasklet);
+ tasklet_schedule(&av7110->debi_tasklet);
}
-
+
if (*isr & MASK_03) {
//printk("av7110_irq: GPIO\n");
- tasklet_schedule (&av7110->gpio_tasklet);
-}
+ tasklet_schedule(&av7110->gpio_tasklet);
+ }
if ((*isr & MASK_10) && budgetpatch)
tasklet_schedule(&av7110->vpe_tasklet);
@@ -2595,6 +2673,7 @@ MAKE_AV7110_INFO(ttc_1_X, "Technotrend/Hauppauge WinTV Nexus-CA rev1.X");
MAKE_AV7110_INFO(ttc_2_X, "Technotrend/Hauppauge WinTV DVB-C rev2.X");
MAKE_AV7110_INFO(tts_2_X, "Technotrend/Hauppauge WinTV Nexus-S rev2.X");
MAKE_AV7110_INFO(tts_1_3se, "Technotrend/Hauppauge WinTV DVB-S rev1.3 SE");
+MAKE_AV7110_INFO(ttt, "Technotrend/Hauppauge DVB-T");
MAKE_AV7110_INFO(fsc, "Fujitsu Siemens DVB-C");
MAKE_AV7110_INFO(fss, "Fujitsu Siemens DVB-S rev1.6");
@@ -2607,10 +2686,10 @@ static struct pci_device_id pci_tbl[] = {
MAKE_EXTENSION_PCI(fsc, 0x110a, 0x0000),
MAKE_EXTENSION_PCI(ttc_1_X, 0x13c2, 0x000a),
MAKE_EXTENSION_PCI(fss, 0x13c2, 0x0006),
+ MAKE_EXTENSION_PCI(ttt, 0x13c2, 0x0008),
/* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0004), UNDEFINED CARD */ // Galaxis DVB PC-Sat-Carte
/* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0005), UNDEFINED CARD */ // Technisat SkyStar1
-/* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0008), UNDEFINED CARD */ // TT/Hauppauge WinTV DVB-T v????
/* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0009), UNDEFINED CARD */ // TT/Hauppauge WinTV Nexus-CA v????
{
@@ -2632,25 +2711,13 @@ static struct saa7146_extension av7110_extension = {
.irq_mask = MASK_19 | MASK_03 | MASK_10,
.irq_func = av7110_irq,
-};
+};
-static int __init av7110_init(void)
+static int __init av7110_init(void)
{
int retval;
retval = saa7146_register_extension(&av7110_extension);
-#if defined(CONFIG_INPUT_EVDEV) || defined(CONFIG_INPUT_EVDEV_MODULE)
- if (retval)
- goto failed_saa7146_register;
-
- retval = av7110_ir_init();
- if (retval)
- goto failed_av7110_ir_init;
- return 0;
-failed_av7110_ir_init:
- saa7146_unregister_extension(&av7110_extension);
-failed_saa7146_register:
-#endif
return retval;
}
@@ -2670,4 +2737,3 @@ MODULE_DESCRIPTION("driver for the SAA7146 based AV110 PCI DVB cards by "
"Siemens, Technotrend, Hauppauge");
MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, others");
MODULE_LICENSE("GPL");
-
diff --git a/drivers/media/dvb/ttpci/av7110.h b/drivers/media/dvb/ttpci/av7110.h
index a1eded6999af6..5070e0523da71 100644
--- a/drivers/media/dvb/ttpci/av7110.h
+++ b/drivers/media/dvb/ttpci/av7110.h
@@ -31,6 +31,7 @@
#include "tda8083.h"
#include "sp8870.h"
#include "stv0297.h"
+#include "l64781.h"
#include <media/saa7146_vv.h>
@@ -49,38 +50,38 @@ extern int av7110_debug;
enum {AV_PES_STREAM, PS_STREAM, TS_STREAM, PES_STREAM};
struct av7110_p2t {
- u8 pes[TS_SIZE];
- u8 counter;
- long int pos;
- int frags;
- struct dvb_demux_feed *feed;
+ u8 pes[TS_SIZE];
+ u8 counter;
+ long int pos;
+ int frags;
+ struct dvb_demux_feed *feed;
};
/* video MPEG decoder events: */
/* (code copied from dvb_frontend.c, should maybe be factored out...) */
#define MAX_VIDEO_EVENT 8
struct dvb_video_events {
- struct video_event events[MAX_VIDEO_EVENT];
- int eventw;
- int eventr;
- int overflow;
- wait_queue_head_t wait_queue;
- spinlock_t lock;
+ struct video_event events[MAX_VIDEO_EVENT];
+ int eventw;
+ int eventr;
+ int overflow;
+ wait_queue_head_t wait_queue;
+ spinlock_t lock;
};
/* place to store all the necessary device information */
struct av7110 {
- /* devices */
+ /* devices */
- struct dvb_device dvb_dev;
- struct dvb_net dvb_net;
+ struct dvb_device dvb_dev;
+ struct dvb_net dvb_net;
struct video_device *v4l_dev;
struct video_device *vbi_dev;
- struct saa7146_dev *dev;
+ struct saa7146_dev *dev;
struct i2c_adapter i2c_adap;
@@ -90,31 +91,31 @@ struct av7110 {
int analog_tuner_flags;
int current_input;
u32 current_freq;
-
- struct tasklet_struct debi_tasklet;
- struct tasklet_struct gpio_tasklet;
- int adac_type; /* audio DAC type */
-#define DVB_ADAC_TI 0
+ struct tasklet_struct debi_tasklet;
+ struct tasklet_struct gpio_tasklet;
+
+ int adac_type; /* audio DAC type */
+#define DVB_ADAC_TI 0
#define DVB_ADAC_CRYSTAL 1
-#define DVB_ADAC_MSP 2
-#define DVB_ADAC_NONE -1
+#define DVB_ADAC_MSP 2
+#define DVB_ADAC_NONE -1
- /* buffers */
+ /* buffers */
- void *iobuf; /* memory for all buffers */
- struct dvb_ringbuffer avout; /* buffer for video or A/V mux */
+ void *iobuf; /* memory for all buffers */
+ struct dvb_ringbuffer avout; /* buffer for video or A/V mux */
#define AVOUTLEN (128*1024)
- struct dvb_ringbuffer aout; /* buffer for audio */
+ struct dvb_ringbuffer aout; /* buffer for audio */
#define AOUTLEN (64*1024)
- void *bmpbuf;
+ void *bmpbuf;
#define BMPLEN (8*32768+1024)
- /* bitmap buffers and states */
+ /* bitmap buffers and states */
- int bmpp;
- int bmplen;
+ int bmpp;
+ int bmplen;
volatile int bmp_state;
#define BMP_NONE 0
#define BMP_LOADING 1
@@ -123,40 +124,40 @@ struct av7110 {
wait_queue_head_t bmpq;
- /* DEBI and polled command interface */
+ /* DEBI and polled command interface */
- spinlock_t debilock;
- struct semaphore dcomlock;
+ spinlock_t debilock;
+ struct semaphore dcomlock;
volatile int debitype;
volatile int debilen;
- /* Recording and playback flags */
+ /* Recording and playback flags */
- int rec_mode;
- int playing;
+ int rec_mode;
+ int playing;
#define RP_NONE 0
#define RP_VIDEO 1
#define RP_AUDIO 2
-#define RP_AV 3
+#define RP_AV 3
- /* OSD */
+ /* OSD */
- int osdwin; /* currently active window */
- u16 osdbpp[8];
+ int osdwin; /* currently active window */
+ u16 osdbpp[8];
struct semaphore osd_sema;
- /* CA */
+ /* CA */
- ca_slot_info_t ci_slot[2];
+ ca_slot_info_t ci_slot[2];
- int vidmode;
- struct dmxdev dmxdev;
- struct dvb_demux demux;
+ int vidmode;
+ struct dmxdev dmxdev;
+ struct dvb_demux demux;
- struct dmx_frontend hw_frontend;
- struct dmx_frontend mem_frontend;
+ struct dmx_frontend hw_frontend;
+ struct dmx_frontend mem_frontend;
/* for budget mode demux1 */
struct dmxdev dmxdev1;
@@ -170,69 +171,67 @@ struct av7110 {
struct saa7146_pgtable pt;
struct tasklet_struct vpe_tasklet;
- int fe_synced;
- struct semaphore pid_mutex;
+ int fe_synced;
+ struct semaphore pid_mutex;
- int video_blank;
- struct video_status videostate;
- int display_ar;
- int trickmode;
+ int video_blank;
+ struct video_status videostate;
+ int display_ar;
+ int trickmode;
#define TRICK_NONE 0
#define TRICK_FAST 1
#define TRICK_SLOW 2
#define TRICK_FREEZE 3
- struct audio_status audiostate;
+ struct audio_status audiostate;
- struct dvb_demux_filter *handle2filter[32];
- struct av7110_p2t p2t_filter[MAXFILT];
- struct dvb_filter_pes2ts p2t[2];
- struct ipack ipack[2];
- u8 *kbuf[2];
+ struct dvb_demux_filter *handle2filter[32];
+ struct av7110_p2t p2t_filter[MAXFILT];
+ struct dvb_filter_pes2ts p2t[2];
+ struct ipack ipack[2];
+ u8 *kbuf[2];
- int sinfo;
- int feeding;
+ int sinfo;
+ int feeding;
- int arm_errors;
- int registered;
+ int arm_errors;
+ int registered;
/* AV711X */
- u32 arm_fw;
- u32 arm_rtsl;
- u32 arm_vid;
- u32 arm_app;
- u32 avtype;
- int arm_ready;
- struct task_struct *arm_thread;
+ u32 arm_fw;
+ u32 arm_rtsl;
+ u32 arm_vid;
+ u32 arm_app;
+ u32 avtype;
+ int arm_ready;
+ struct task_struct *arm_thread;
wait_queue_head_t arm_wait;
- u16 arm_loops;
- int arm_rmmod;
+ u16 arm_loops;
+ int arm_rmmod;
+
+ void *debi_virt;
+ dma_addr_t debi_bus;
- void *debi_virt;
- dma_addr_t debi_bus;
+ u16 pids[DMX_PES_OTHER];
- u16 pids[DMX_PES_OTHER];
-
- struct dvb_ringbuffer ci_rbuffer;
- struct dvb_ringbuffer ci_wbuffer;
+ struct dvb_ringbuffer ci_rbuffer;
+ struct dvb_ringbuffer ci_wbuffer;
struct audio_mixer mixer;
- struct dvb_adapter *dvb_adapter;
- struct dvb_device *video_dev;
- struct dvb_device *audio_dev;
- struct dvb_device *ca_dev;
- struct dvb_device *osd_dev;
+ struct dvb_adapter *dvb_adapter;
+ struct dvb_device *video_dev;
+ struct dvb_device *audio_dev;
+ struct dvb_device *ca_dev;
+ struct dvb_device *osd_dev;
struct dvb_video_events video_events;
- video_size_t video_size;
+ video_size_t video_size;
- u32 ir_config;
-
- /* firmware stuff */
- unsigned int device_initialized;
+ u32 ir_config;
+ /* firmware stuff */
unsigned char *bin_fw;
unsigned long size_fw;
@@ -260,7 +259,7 @@ extern void ChangePIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid,
u16 subpid, u16 pcrpid);
extern void av7110_register_irc_handler(void (*func)(u32));
-extern void av7110_unregister_irc_handler(void (*func)(u32));
+extern void av7110_unregister_irc_handler(void (*func)(u32));
extern void av7110_setup_irc_config (struct av7110 *av7110, u32 ir_config);
extern int av7110_ir_init (void);
@@ -283,4 +282,3 @@ extern int av7110_init_v4l(struct av7110 *av7110);
extern int av7110_exit_v4l(struct av7110 *av7110);
#endif /* _AV7110_H_ */
-
diff --git a/drivers/media/dvb/ttpci/av7110_av.c b/drivers/media/dvb/ttpci/av7110_av.c
index f875efcf5de68..d77e8a00688fc 100644
--- a/drivers/media/dvb/ttpci/av7110_av.c
+++ b/drivers/media/dvb/ttpci/av7110_av.c
@@ -1426,25 +1426,34 @@ void av7110_av_unregister(struct av7110 *av7110)
int av7110_av_init(struct av7110 *av7110)
{
+ void (*play[])(u8 *, int, void *) = { play_audio_cb, play_video_cb };
+ int i, ret;
+
av7110->vidmode = VIDEO_MODE_PAL;
- av7110_ipack_init(&av7110->ipack[0], IPACKS, play_audio_cb);
- av7110->ipack[0].data = (void *) av7110;
- av7110_ipack_init(&av7110->ipack[1], IPACKS, play_video_cb);
- av7110->ipack[1].data = (void *) av7110;
+ for (i = 0; i < 2; i++) {
+ struct ipack *ipack = av7110->ipack + i;
+
+ ret = av7110_ipack_init(ipack, IPACKS, play[i]);
+ if (ret < 0) {
+ if (i)
+ av7110_ipack_free(--ipack);
+ goto out;
+ }
+ ipack->data = av7110;
+ }
dvb_ringbuffer_init(&av7110->avout, av7110->iobuf, AVOUTLEN);
dvb_ringbuffer_init(&av7110->aout, av7110->iobuf + AVOUTLEN, AOUTLEN);
av7110->kbuf[0] = (u8 *)(av7110->iobuf + AVOUTLEN + AOUTLEN + BMPLEN);
av7110->kbuf[1] = av7110->kbuf[0] + 2 * IPACKS;
-
- return 0;
+out:
+ return ret;
}
-int av7110_av_exit(struct av7110 *av7110)
+void av7110_av_exit(struct av7110 *av7110)
{
av7110_ipack_free(&av7110->ipack[0]);
av7110_ipack_free(&av7110->ipack[1]);
- return 0;
}
diff --git a/drivers/media/dvb/ttpci/av7110_av.h b/drivers/media/dvb/ttpci/av7110_av.h
index 9bfdf37459db9..cc5e7a7e87c39 100644
--- a/drivers/media/dvb/ttpci/av7110_av.h
+++ b/drivers/media/dvb/ttpci/av7110_av.h
@@ -23,7 +23,7 @@ extern void av7110_p2t_write(u8 const *buf, long int length, u16 pid, struct av7
extern int av7110_av_register(struct av7110 *av7110);
extern void av7110_av_unregister(struct av7110 *av7110);
extern int av7110_av_init(struct av7110 *av7110);
-extern int av7110_av_exit(struct av7110 *av7110);
+extern void av7110_av_exit(struct av7110 *av7110);
#endif /* _AV7110_AV_H_ */
diff --git a/drivers/media/dvb/ttpci/av7110_ca.c b/drivers/media/dvb/ttpci/av7110_ca.c
index 0bd0da28dfad9..21f7aacf77266 100644
--- a/drivers/media/dvb/ttpci/av7110_ca.c
+++ b/drivers/media/dvb/ttpci/av7110_ca.c
@@ -91,8 +91,20 @@ void ci_get_data(struct dvb_ringbuffer *cibuf, u8 *data, int len)
static int ci_ll_init(struct dvb_ringbuffer *cirbuf, struct dvb_ringbuffer *ciwbuf, int size)
{
- dvb_ringbuffer_init(cirbuf, vmalloc(size), size);
- dvb_ringbuffer_init(ciwbuf, vmalloc(size), size);
+ struct dvb_ringbuffer *tab[] = { cirbuf, ciwbuf, NULL }, **p;
+ void *data;
+
+ for (p = tab; *p; p++) {
+ data = vmalloc(size);
+ if (!data) {
+ while (p-- != tab) {
+ vfree(p[0]->data);
+ p[0]->data = NULL;
+ }
+ return -ENOMEM;
+ }
+ dvb_ringbuffer_init(*p, data, size);
+ }
return 0;
}
@@ -367,9 +379,9 @@ void av7110_ca_unregister(struct av7110 *av7110)
dvb_unregister_device(av7110->ca_dev);
}
-void av7110_ca_init(struct av7110* av7110)
+int av7110_ca_init(struct av7110* av7110)
{
- ci_ll_init(&av7110->ci_rbuffer, &av7110->ci_wbuffer, 8192);
+ return ci_ll_init(&av7110->ci_rbuffer, &av7110->ci_wbuffer, 8192);
}
void av7110_ca_exit(struct av7110* av7110)
diff --git a/drivers/media/dvb/ttpci/av7110_ca.h b/drivers/media/dvb/ttpci/av7110_ca.h
index f9a0b3d5ef824..70ee855ece1bb 100644
--- a/drivers/media/dvb/ttpci/av7110_ca.h
+++ b/drivers/media/dvb/ttpci/av7110_ca.h
@@ -8,7 +8,7 @@ extern void ci_get_data(struct dvb_ringbuffer *cibuf, u8 *data, int len);
extern int av7110_ca_register(struct av7110 *av7110);
extern void av7110_ca_unregister(struct av7110 *av7110);
-extern void av7110_ca_init(struct av7110* av7110);
+extern int av7110_ca_init(struct av7110* av7110);
extern void av7110_ca_exit(struct av7110* av7110);
#endif /* _AV7110_CA_H_ */
diff --git a/drivers/media/dvb/ttpci/av7110_hw.c b/drivers/media/dvb/ttpci/av7110_hw.c
index d33136df4064c..bd6e5ea4aefe3 100644
--- a/drivers/media/dvb/ttpci/av7110_hw.c
+++ b/drivers/media/dvb/ttpci/av7110_hw.c
@@ -399,7 +399,7 @@ int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
if (type != NULL) {
/* non-immediate COMMAND type */
- start = jiffies;
+ start = jiffies;
for (;;) {
stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
if (stat & flags[0]) {
@@ -412,8 +412,8 @@ int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
if (time_after(jiffies, start + ARM_WAIT_FREE)) {
printk(KERN_ERR "%s: timeout waiting on busy %s QUEUE\n",
__FUNCTION__, type);
- return -1;
- }
+ return -1;
+ }
msleep(1);
}
}
@@ -889,11 +889,11 @@ static int BlitBitmap(struct av7110 *av7110, u16 win, u16 x, u16 y, u16 trans)
ret, av7110->bmp_state);
av7110->bmp_state = BMP_NONE;
return (ret == 0) ? -ETIMEDOUT : ret;
- }
+ }
BUG_ON (av7110->bmp_state != BMP_LOADED);
- return av7110_fw_cmd(av7110, COMTYPE_OSD, BlitBmp, 4, win, x, y, trans);
+ return av7110_fw_cmd(av7110, COMTYPE_OSD, BlitBmp, 4, win, x, y, trans);
}
static inline int ReleaseBitmap(struct av7110 *av7110)
@@ -962,7 +962,7 @@ static int OSDSetPalette(struct av7110 *av7110, u32 __user * colors, u8 first, u
}
static int OSDSetBlock(struct av7110 *av7110, int x0, int y0,
- int x1, int y1, int inc, u8 __user *data)
+ int x1, int y1, int inc, u8 __user * data)
{
uint w, h, bpp, bpl, size, lpb, bnum, brest;
int i;
@@ -1061,9 +1061,9 @@ int av7110_osd_cmd(struct av7110 *av7110, osd_cmd_t *dc)
get_user(blend, colors + i * 4 + 3)) {
ret = -EFAULT;
goto out;
- }
+ }
OSDSetColor(av7110, dc->color + i, r, g, b, blend);
- }
+ }
}
ret = 0;
goto out;
@@ -1162,9 +1162,9 @@ int av7110_osd_capability(struct av7110 *av7110, osd_cap_t *cap)
cap->val = 1000000;
else
cap->val = 92000;
- return 0;
- default:
- return -EINVAL;
- }
+ return 0;
+ default:
+ return -EINVAL;
+ }
}
#endif /* CONFIG_DVB_AV7110_OSD */
diff --git a/drivers/media/dvb/ttpci/av7110_ipack.c b/drivers/media/dvb/ttpci/av7110_ipack.c
index b10bd77f9a6d8..2466407418886 100644
--- a/drivers/media/dvb/ttpci/av7110_ipack.c
+++ b/drivers/media/dvb/ttpci/av7110_ipack.c
@@ -21,9 +21,9 @@ void av7110_ipack_reset(struct ipack *p)
int av7110_ipack_init(struct ipack *p, int size,
- void (*func)(u8 *buf, int size, void *priv))
+ void (*func)(u8 *buf, int size, void *priv))
{
- if ( !(p->buf = vmalloc(size*sizeof(u8))) ){
+ if (!(p->buf = vmalloc(size*sizeof(u8)))) {
printk ("Couldn't allocate memory for ipack\n");
return -ENOMEM;
}
@@ -35,10 +35,9 @@ int av7110_ipack_init(struct ipack *p, int size,
}
-void av7110_ipack_free(struct ipack * p)
+void av7110_ipack_free(struct ipack *p)
{
- if (p->buf)
- vfree(p->buf);
+ vfree(p->buf);
}
@@ -47,44 +46,44 @@ static void send_ipack(struct ipack *p)
int off;
struct dvb_audio_info ai;
int ac3_off = 0;
- int streamid=0;
- int nframes= 0;
- int f=0;
+ int streamid = 0;
+ int nframes = 0;
+ int f = 0;
- switch ( p->mpeg ){
- case 2:
+ switch (p->mpeg) {
+ case 2:
if (p->count < 10)
return;
p->buf[3] = p->cid;
p->buf[4] = (u8)(((p->count - 6) & 0xff00) >> 8);
p->buf[5] = (u8)((p->count - 6) & 0x00ff);
- if (p->repack_subids && p->cid == PRIVATE_STREAM1){
- off = 9+p->buf[8];
+ if (p->repack_subids && p->cid == PRIVATE_STREAM1) {
+ off = 9 + p->buf[8];
streamid = p->buf[off];
if ((streamid & 0xf8) == 0x80) {
ai.off = 0;
- ac3_off = ((p->buf[off+2] << 8)|
- p->buf[off+3]);
+ ac3_off = ((p->buf[off + 2] << 8)|
+ p->buf[off + 3]);
if (ac3_off < p->count)
- f=dvb_filter_get_ac3info(p->buf+off+3+ac3_off,
- p->count-ac3_off, &ai,0);
- if ( !f ){
- nframes = (p->count-off-3-ac3_off)/
+ f = dvb_filter_get_ac3info(p->buf + off + 3 + ac3_off,
+ p->count - ac3_off, &ai, 0);
+ if (!f) {
+ nframes = (p->count - off - 3 - ac3_off) /
ai.framesize + 1;
p->buf[off + 2] = (ac3_off >> 8) & 0xff;
p->buf[off + 3] = (ac3_off) & 0xff;
- p->buf[off+1] = nframes;
+ p->buf[off + 1] = nframes;
ac3_off += nframes * ai.framesize - p->count;
}
}
- }
+ }
p->func(p->buf, p->count, p->data);
-
+
p->buf[6] = 0x80;
p->buf[7] = 0x00;
p->buf[8] = 0x00;
p->count = 9;
- if (p->repack_subids && p->cid == PRIVATE_STREAM1
+ if (p->repack_subids && p->cid == PRIVATE_STREAM1
&& (streamid & 0xf8) == 0x80) {
p->count += 4;
p->buf[9] = streamid;
@@ -101,7 +100,7 @@ static void send_ipack(struct ipack *p)
p->buf[4] = (u8)(((p->count - 6) & 0xff00) >> 8);
p->buf[5] = (u8)((p->count - 6) & 0x00ff);
p->func(p->buf, p->count, p->data);
-
+
p->buf[6] = 0x0f;
p->count = 7;
break;
@@ -111,9 +110,9 @@ static void send_ipack(struct ipack *p)
void av7110_ipack_flush(struct ipack *p)
{
- if (p->plength != MMAX_PLENGTH-6 || p->found<=6)
+ if (p->plength != MMAX_PLENGTH - 6 || p->found <= 6)
return;
- p->plength = p->found-6;
+ p->plength = p->found - 6;
p->found = 0;
send_ipack(p);
av7110_ipack_reset(p);
@@ -122,9 +121,9 @@ void av7110_ipack_flush(struct ipack *p)
static void write_ipack(struct ipack *p, const u8 *data, int count)
{
- u8 headr[3] = { 0x00, 0x00, 0x01} ;
+ u8 headr[3] = { 0x00, 0x00, 0x01 };
- if (p->count < 6){
+ if (p->count < 6) {
memcpy(p->buf, headr, 3);
p->count = 6;
}
@@ -138,7 +137,7 @@ static void write_ipack(struct ipack *p, const u8 *data, int count)
p->count += rest;
send_ipack(p);
if (count - rest > 0)
- write_ipack(p, data+rest, count-rest);
+ write_ipack(p, data + rest, count - rest);
}
}
@@ -146,13 +145,13 @@ static void write_ipack(struct ipack *p, const u8 *data, int count)
int av7110_ipack_instant_repack (const u8 *buf, int count, struct ipack *p)
{
int l;
- int c=0;
+ int c = 0;
while (c < count && (p->mpeg == 0 ||
(p->mpeg == 1 && p->found < 7) ||
(p->mpeg == 2 && p->found < 9))
- && (p->found < 5 || !p->done)){
- switch ( p->found ){
+ && (p->found < 5 || !p->done)) {
+ switch (p->found) {
case 0:
case 1:
if (buf[c] == 0x00)
@@ -172,7 +171,7 @@ int av7110_ipack_instant_repack (const u8 *buf, int count, struct ipack *p)
break;
case 3:
p->cid = 0;
- switch (buf[c]){
+ switch (buf[c]) {
case PROG_STREAM_MAP:
case PRIVATE_STREAM2:
case PROG_STREAM_DIR:
@@ -195,16 +194,16 @@ int av7110_ipack_instant_repack (const u8 *buf, int count, struct ipack *p)
break;
}
break;
-
+
case 4:
- if (count-c > 1){
+ if (count-c > 1) {
p->plen[0] = buf[c];
c++;
p->plen[1] = buf[c];
c++;
- p->found+=2;
- p->plength=(p->plen[0]<<8)|p->plen[1];
- } else {
+ p->found += 2;
+ p->plength = (p->plen[0] << 8) | p->plen[1];
+ } else {
p->plen[0] = buf[c];
p->found++;
return count;
@@ -214,10 +213,10 @@ int av7110_ipack_instant_repack (const u8 *buf, int count, struct ipack *p)
p->plen[1] = buf[c];
c++;
p->found++;
- p->plength=(p->plen[0]<<8)|p->plen[1];
+ p->plength = (p->plen[0] << 8) | p->plen[1];
break;
case 6:
- if (!p->done){
+ if (!p->done) {
p->flag1 = buf[c];
c++;
p->found++;
@@ -233,15 +232,15 @@ int av7110_ipack_instant_repack (const u8 *buf, int count, struct ipack *p)
break;
case 7:
- if ( !p->done && p->mpeg == 2) {
+ if (!p->done && p->mpeg == 2) {
p->flag2 = buf[c];
c++;
p->found++;
- }
+ }
break;
case 8:
- if ( !p->done && p->mpeg == 2) {
+ if (!p->done && p->mpeg == 2) {
p->hlength = buf[c];
c++;
p->found++;
@@ -256,28 +255,26 @@ int av7110_ipack_instant_repack (const u8 *buf, int count, struct ipack *p)
if (!p->plength)
p->plength = MMAX_PLENGTH - 6;
- if ( p->done || ((p->mpeg == 2 && p->found >= 9) ||
- (p->mpeg == 1 && p->found >= 7)) ){
- switch (p->cid){
-
- case AUDIO_STREAM_S ... AUDIO_STREAM_E:
+ if (p->done || ((p->mpeg == 2 && p->found >= 9) ||
+ (p->mpeg == 1 && p->found >= 7))) {
+ switch (p->cid) {
+ case AUDIO_STREAM_S ... AUDIO_STREAM_E:
case VIDEO_STREAM_S ... VIDEO_STREAM_E:
case PRIVATE_STREAM1:
-
if (p->mpeg == 2 && p->found == 9) {
write_ipack(p, &p->flag1, 1);
write_ipack(p, &p->flag2, 1);
write_ipack(p, &p->hlength, 1);
}
- if (p->mpeg == 1 && p->found == 7)
+ if (p->mpeg == 1 && p->found == 7)
write_ipack(p, &p->flag1, 1);
-
- if (p->mpeg == 2 && (p->flag2 & PTS_ONLY) &&
+
+ if (p->mpeg == 2 && (p->flag2 & PTS_ONLY) &&
p->found < 14) {
while (c < count && p->found < 14) {
- p->pts[p->found-9] = buf[c];
- write_ipack(p, buf+c, 1);
+ p->pts[p->found - 9] = buf[c];
+ write_ipack(p, buf + c, 1);
c++;
p->found++;
}
@@ -292,30 +289,30 @@ int av7110_ipack_instant_repack (const u8 *buf, int count, struct ipack *p)
p->hlength = 1;
}
- while (!p->which && c < count &&
+ while (!p->which && c < count &&
p->check == 0xff){
p->check = buf[c];
- write_ipack(p, buf+c, 1);
+ write_ipack(p, buf + c, 1);
c++;
p->found++;
p->hlength++;
}
-
+
if (c == count)
return count;
-
+
if ((p->check & 0xc0) == 0x40 && !p->which) {
p->check = buf[c];
- write_ipack(p, buf+c, 1);
+ write_ipack(p, buf + c, 1);
c++;
p->found++;
p->hlength++;
-
+
p->which = 1;
if (c == count)
return count;
p->check = buf[c];
- write_ipack(p, buf+c, 1);
+ write_ipack(p, buf + c, 1);
c++;
p->found++;
p->hlength++;
@@ -323,10 +320,10 @@ int av7110_ipack_instant_repack (const u8 *buf, int count, struct ipack *p)
if (c == count)
return count;
}
-
- if (p->which == 1){
+
+ if (p->which == 1) {
p->check = buf[c];
- write_ipack(p, buf+c, 1);
+ write_ipack(p, buf + c, 1);
c++;
p->found++;
p->hlength++;
@@ -334,20 +331,20 @@ int av7110_ipack_instant_repack (const u8 *buf, int count, struct ipack *p)
if (c == count)
return count;
}
-
+
if ((p->check & 0x30) && p->check != 0xff) {
p->flag2 = (p->check & 0xf0) << 2;
p->pts[0] = p->check;
p->which = 3;
- }
-
+ }
+
if (c == count)
return count;
if (p->which > 2){
if ((p->flag2 & PTS_DTS_FLAGS) == PTS_ONLY) {
while (c < count && p->which < 7) {
p->pts[p->which - 2] = buf[c];
- write_ipack(p,buf+c,1);
+ write_ipack(p, buf + c, 1);
c++;
p->found++;
p->which++;
@@ -357,9 +354,9 @@ int av7110_ipack_instant_repack (const u8 *buf, int count, struct ipack *p)
return count;
} else if ((p->flag2 & PTS_DTS_FLAGS) == PTS_DTS) {
while (c < count && p->which < 12) {
- if (p->which< 7)
+ if (p->which < 7)
p->pts[p->which - 2] = buf[c];
- write_ipack(p,buf+c,1);
+ write_ipack(p, buf + c, 1);
c++;
p->found++;
p->which++;
@@ -370,39 +367,37 @@ int av7110_ipack_instant_repack (const u8 *buf, int count, struct ipack *p)
}
p->which = 2000;
}
-
+
}
-
- while (c < count && p->found < p->plength+6){
- l = count -c;
- if (l+p->found > p->plength+6)
- l = p->plength+6-p->found;
- write_ipack(p, buf+c, l);
+
+ while (c < count && p->found < p->plength + 6) {
+ l = count - c;
+ if (l + p->found > p->plength + 6)
+ l = p->plength + 6 - p->found;
+ write_ipack(p, buf + c, l);
p->found += l;
c += l;
- }
-
+ }
break;
}
- if ( p->done ){
- if( p->found + count - c < p->plength+6){
- p->found += count-c;
+ if (p->done) {
+ if (p->found + count - c < p->plength + 6) {
+ p->found += count - c;
c = count;
} else {
- c += p->plength+6 - p->found;
- p->found = p->plength+6;
+ c += p->plength + 6 - p->found;
+ p->found = p->plength + 6;
}
}
- if (p->plength && p->found == p->plength+6) {
+ if (p->plength && p->found == p->plength + 6) {
send_ipack(p);
av7110_ipack_reset(p);
if (c < count)
- av7110_ipack_instant_repack(buf+c, count-c, p);
+ av7110_ipack_instant_repack(buf + c, count - c, p);
}
}
return count;
}
-
diff --git a/drivers/media/dvb/ttpci/av7110_ipack.h b/drivers/media/dvb/ttpci/av7110_ipack.h
index 5348eb4dfbdc3..becf94d3fdfa0 100644
--- a/drivers/media/dvb/ttpci/av7110_ipack.h
+++ b/drivers/media/dvb/ttpci/av7110_ipack.h
@@ -2,7 +2,7 @@
#define _AV7110_IPACK_H_
extern int av7110_ipack_init(struct ipack *p, int size,
- void (*func)(u8 *buf, int size, void *priv));
+ void (*func)(u8 *buf, int size, void *priv));
extern void av7110_ipack_reset(struct ipack *p);
extern int av7110_ipack_instant_repack(const u8 *buf, int count, struct ipack *p);
@@ -10,4 +10,3 @@ extern void av7110_ipack_free(struct ipack * p);
extern void av7110_ipack_flush(struct ipack *p);
#endif
-
diff --git a/drivers/media/dvb/ttpci/av7110_ir.c b/drivers/media/dvb/ttpci/av7110_ir.c
index eaf3cb2c9b0a7..6d2256f1e3542 100644
--- a/drivers/media/dvb/ttpci/av7110_ir.c
+++ b/drivers/media/dvb/ttpci/av7110_ir.c
@@ -12,6 +12,7 @@
/* enable ir debugging by or'ing av7110_debug with 16 */
+static int ir_initialized;
static struct input_dev input_dev;
static u32 ir_config;
@@ -19,40 +20,40 @@ static u32 ir_config;
static u16 key_map [256] = {
KEY_0, KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7,
KEY_8, KEY_9, KEY_BACK, 0, KEY_POWER, KEY_MUTE, 0, KEY_INFO,
- KEY_VOLUMEUP, KEY_VOLUMEDOWN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ KEY_VOLUMEUP, KEY_VOLUMEDOWN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
KEY_CHANNELUP, KEY_CHANNELDOWN, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, KEY_TEXT, 0, 0, KEY_TV, 0, 0, 0, 0, 0, KEY_SETUP, 0, 0,
0, 0, 0, KEY_SUBTITLE, 0, 0, KEY_LANGUAGE, 0,
- KEY_RADIO, 0, 0, 0, 0, KEY_EXIT, 0, 0,
+ KEY_RADIO, 0, 0, 0, 0, KEY_EXIT, 0, 0,
KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT, KEY_OK, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_RED, KEY_GREEN, KEY_YELLOW,
- KEY_BLUE, 0, 0, 0, 0, 0, 0, 0, KEY_MENU, KEY_LIST, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ KEY_BLUE, 0, 0, 0, 0, 0, 0, 0, KEY_MENU, KEY_LIST, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, KEY_UP, KEY_UP, KEY_DOWN, KEY_DOWN,
- 0, 0, 0, 0, KEY_EPG, 0, 0, 0,
+ 0, 0, 0, 0, KEY_EPG, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_VCR
};
-static void av7110_emit_keyup (unsigned long data)
+static void av7110_emit_keyup(unsigned long data)
{
- if (!data || !test_bit (data, input_dev.key))
+ if (!data || !test_bit(data, input_dev.key))
return;
- input_event (&input_dev, EV_KEY, data, !!0);
+ input_event(&input_dev, EV_KEY, data, !!0);
}
static struct timer_list keyup_timer = { .function = av7110_emit_keyup };
-static void av7110_emit_key (u32 ircom)
+static void av7110_emit_key(u32 ircom)
{
u8 data;
u8 addr;
@@ -72,9 +73,9 @@ static void av7110_emit_key (u32 ircom)
}
keycode = key_map[data];
-
+
dprintk(16, "#########%08x######### addr %i data 0x%02x (keycode %i)\n",
- ircom, addr, data, keycode);
+ ircom, addr, data, keycode);
/* check device address (if selected) */
if (ir_config & 0x4000)
@@ -86,41 +87,41 @@ static void av7110_emit_key (u32 ircom)
return;
}
- if (ir_config & 0x0001)
+ if (ir_config & 0x0001)
new_toggle = 0; /* RCMM */
else
new_toggle = (ircom & 0x800); /* RC5 */
- if (timer_pending (&keyup_timer)) {
- del_timer (&keyup_timer);
+ if (timer_pending(&keyup_timer)) {
+ del_timer(&keyup_timer);
if (keyup_timer.data != keycode || new_toggle != old_toggle) {
- input_event (&input_dev, EV_KEY, keyup_timer.data, !!0);
- input_event (&input_dev, EV_KEY, keycode, !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);
+ input_event(&input_dev, EV_KEY, keycode, 2);
} else
- input_event (&input_dev, EV_KEY, keycode, !0);
+ input_event(&input_dev, EV_KEY, keycode, !0);
keyup_timer.expires = jiffies + UP_TIMEOUT;
keyup_timer.data = keycode;
- add_timer (&keyup_timer);
+ add_timer(&keyup_timer);
old_toggle = new_toggle;
}
-static void input_register_keys (void)
+static void input_register_keys(void)
{
int i;
- memset (input_dev.keybit, 0, sizeof(input_dev.keybit));
+ memset(input_dev.keybit, 0, sizeof(input_dev.keybit));
- for (i=0; i<sizeof(key_map)/sizeof(key_map[0]); i++) {
+ for (i = 0; i < sizeof(key_map) / sizeof(key_map[0]); i++) {
if (key_map[i] > KEY_MAX)
key_map[i] = 0;
else if (key_map[i] > KEY_RESERVED)
- set_bit (key_map[i], input_dev.keybit);
+ set_bit(key_map[i], input_dev.keybit);
}
}
@@ -131,77 +132,79 @@ static void input_repeat_key(unsigned long data)
}
-static int av7110_ir_write_proc (struct file *file, const char __user *buffer,
- unsigned long count, void *data)
+static int av7110_ir_write_proc(struct file *file, const char __user *buffer,
+ unsigned long count, void *data)
{
char *page;
int size = 4 + 256 * sizeof(u16);
if (count < size)
return -EINVAL;
-
- page = (char *)vmalloc(size);
+
+ page = (char *) vmalloc(size);
if (!page)
return -ENOMEM;
-
+
if (copy_from_user(page, buffer, size)) {
vfree(page);
return -EFAULT;
}
- memcpy (&ir_config, page, 4);
- memcpy (&key_map, page + 4, 256 * sizeof(u16));
-
+ memcpy(&ir_config, page, 4);
+ memcpy(&key_map, page + 4, 256 * sizeof(u16));
vfree(page);
-
- av7110_setup_irc_config (NULL, ir_config);
-
- input_register_keys ();
-
+ av7110_setup_irc_config(NULL, ir_config);
+ input_register_keys();
return count;
}
-int __init av7110_ir_init (void)
+int __init av7110_ir_init(void)
{
static struct proc_dir_entry *e;
- init_timer (&keyup_timer);
+ if (ir_initialized)
+ return 0;
+
+ init_timer(&keyup_timer);
keyup_timer.data = 0;
- input_dev.name = "DVB on-card IR receiver";
+ input_dev.name = "DVB on-card IR receiver";
- /**
- * enable keys
- */
- set_bit (EV_KEY, input_dev.evbit);
- set_bit (EV_REP, input_dev.evbit);
+ /**
+ * enable keys
+ */
+ set_bit(EV_KEY, input_dev.evbit);
+ set_bit(EV_REP, input_dev.evbit);
- input_register_keys ();
+ input_register_keys();
input_register_device(&input_dev);
input_dev.timer.function = input_repeat_key;
- av7110_setup_irc_config (NULL, 0x0001);
- av7110_register_irc_handler (av7110_emit_key);
-
- e = create_proc_entry ("av7110_ir", S_IFREG | S_IRUGO | S_IWUSR, NULL);
+ av7110_setup_irc_config(NULL, 0x0001);
+ av7110_register_irc_handler(av7110_emit_key);
+ e = create_proc_entry("av7110_ir", S_IFREG | S_IRUGO | S_IWUSR, NULL);
if (e) {
e->write_proc = av7110_ir_write_proc;
e->size = 4 + 256 * sizeof(u16);
}
+ ir_initialized = 1;
return 0;
}
-void __exit av7110_ir_exit (void)
+void __exit av7110_ir_exit(void)
{
+ if (ir_initialized == 0)
+ return;
del_timer_sync(&keyup_timer);
- remove_proc_entry ("av7110_ir", NULL);
- av7110_unregister_irc_handler (av7110_emit_key);
+ remove_proc_entry("av7110_ir", NULL);
+ av7110_unregister_irc_handler(av7110_emit_key);
input_unregister_device(&input_dev);
+ ir_initialized = 0;
}
//MODULE_AUTHOR("Holger Waechtler <holger@convergence.de>");
diff --git a/drivers/media/dvb/ttpci/av7110_v4l.c b/drivers/media/dvb/ttpci/av7110_v4l.c
index 0c618ddd91e37..eb84fb08d95cd 100644
--- a/drivers/media/dvb/ttpci/av7110_v4l.c
+++ b/drivers/media/dvb/ttpci/av7110_v4l.c
@@ -70,8 +70,6 @@ int msp_readreg(struct av7110 *av7110, u8 dev, u16 reg, u16 *val)
return 0;
}
-
-
static struct v4l2_input inputs[2] = {
{
.index = 0,
diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c
index ae9260094d76b..14e963206b890 100644
--- a/drivers/media/dvb/ttpci/budget-av.c
+++ b/drivers/media/dvb/ttpci/budget-av.c
@@ -1,34 +1,34 @@
/*
* budget-av.c: driver for the SAA7146 based Budget DVB cards
- * with analog video in
+ * with analog video in
*
- * Compiled from various sources by Michael Hunold <michael@mihu.de>
+ * Compiled from various sources by Michael Hunold <michael@mihu.de>
*
* CI interface support (c) 2004 Olivier Gournet <ogournet@anevia.com> &
* Andrew de Quincey <adq_dvb@lidskialf.net>
*
* Copyright (C) 2002 Ralph Metzler <rjkm@metzlerbros.de>
*
- * Copyright (C) 1999-2002 Ralph Metzler
+ * Copyright (C) 1999-2002 Ralph Metzler
* & Marcus Metzler for convergence integrated media GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
- *
+ *
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
*
* You should have received a copy of the 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.
* Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- *
+ *
*
* the project's page is at http://www.linuxtv.org/dvb/
*/
@@ -59,23 +59,22 @@ struct budget_av {
struct dvb_ca_en50221 ca;
};
-int enable_ci = 0;
+static int enable_ci = 0;
/****************************************************************************
* INITIALIZATION
****************************************************************************/
-
-static u8 i2c_readreg (struct i2c_adapter *i2c, u8 id, u8 reg)
+static u8 i2c_readreg(struct i2c_adapter *i2c, u8 id, u8 reg)
{
- u8 mm1[] = {0x00};
- u8 mm2[] = {0x00};
+ u8 mm1[] = { 0x00 };
+ u8 mm2[] = { 0x00 };
struct i2c_msg msgs[2];
msgs[0].flags = 0;
msgs[1].flags = I2C_M_RD;
- msgs[0].addr = msgs[1].addr=id/2;
+ msgs[0].addr = msgs[1].addr = id / 2;
mm1[0] = reg;
msgs[0].len = 1;
msgs[1].len = 1;
@@ -87,31 +86,30 @@ static u8 i2c_readreg (struct i2c_adapter *i2c, u8 id, u8 reg)
return mm2[0];
}
-static int i2c_readregs(struct i2c_adapter *i2c, u8 id, u8 reg, u8 *buf, u8 len)
+static int i2c_readregs(struct i2c_adapter *i2c, u8 id, u8 reg, u8 * buf, u8 len)
{
- u8 mm1[] = { reg };
- struct i2c_msg msgs[2] = {
- { .addr = id/2, .flags = 0, .buf = mm1, .len = 1 },
- { .addr = id/2, .flags = I2C_M_RD, .buf = buf, .len = len }
+ u8 mm1[] = { reg };
+ struct i2c_msg msgs[2] = {
+ {.addr = id / 2,.flags = 0,.buf = mm1,.len = 1},
+ {.addr = id / 2,.flags = I2C_M_RD,.buf = buf,.len = len}
};
- if (i2c_transfer(i2c, msgs, 2) != 2)
+ if (i2c_transfer(i2c, msgs, 2) != 2)
return -EIO;
return 0;
}
-
-static int i2c_writereg (struct i2c_adapter *i2c, u8 id, u8 reg, u8 val)
+static int i2c_writereg(struct i2c_adapter *i2c, u8 id, u8 reg, u8 val)
{
- u8 msg[2]={ reg, val };
- struct i2c_msg msgs;
-
- msgs.flags=0;
- msgs.addr=id/2;
- msgs.len=2;
- msgs.buf=msg;
- return i2c_transfer(i2c, &msgs, 1);
+ u8 msg[2] = { reg, val };
+ struct i2c_msg msgs;
+
+ msgs.flags = 0;
+ msgs.addr = id / 2;
+ msgs.len = 2;
+ msgs.buf = msg;
+ return i2c_transfer(i2c, &msgs, 1);
}
static int ciintf_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address)
@@ -123,6 +121,8 @@ static int ciintf_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int ad
return -EINVAL;
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);
if (result == -ETIMEDOUT)
@@ -139,6 +139,8 @@ static int ciintf_write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int a
return -EINVAL;
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);
if (result == -ETIMEDOUT)
@@ -155,6 +157,8 @@ static int ciintf_read_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 addre
return -EINVAL;
saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO);
+ udelay(1);
+
result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 3, 1, 0, 0);
if (result == -ETIMEDOUT)
@@ -171,6 +175,8 @@ static int ciintf_write_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 addr
return -EINVAL;
saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO);
+ udelay(1);
+
result = ttpci_budget_debiwrite(&budget_av->budget, DEBICICAM, address & 3, 1, value, 0, 0);
if (result == -ETIMEDOUT)
@@ -182,6 +188,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 max = 20;
if (slot != 0)
return -EINVAL;
@@ -192,7 +199,9 @@ static int ciintf_slot_reset(struct dvb_ca_en50221 *ca, int slot)
saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTHI);
msleep(100);
saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO);
- msleep(2000); /* horrendous I know, but its the only way to be absolutely sure without an IRQ line! */
+
+ while (--max > 0 && ciintf_read_attribute_mem(ca, slot, 0) != 0x1d)
+ msleep(100);
ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);
return 0;
@@ -335,49 +344,47 @@ static const u8 saa7113_tab[] = {
0x0c, 0x40,
0x0d, 0x00,
0x0e, 0x01,
- 0x0f, 0x44,
+ 0x0f, 0x44,
0x10, 0x08,
0x11, 0x0c,
0x12, 0x7b,
0x13, 0x00,
- 0x15, 0x00, 0x16, 0x00, 0x17, 0x00,
+ 0x15, 0x00, 0x16, 0x00, 0x17, 0x00,
- 0x57, 0xff,
- 0x40, 0x82, 0x58, 0x00, 0x59, 0x54, 0x5a, 0x07,
- 0x5b, 0x83, 0x5e, 0x00,
- 0xff
+ 0x57, 0xff,
+ 0x40, 0x82, 0x58, 0x00, 0x59, 0x54, 0x5a, 0x07,
+ 0x5b, 0x83, 0x5e, 0x00,
+ 0xff
};
-
-static int saa7113_init (struct budget_av *budget_av)
+static int saa7113_init(struct budget_av *budget_av)
{
struct budget *budget = &budget_av->budget;
const u8 *data = saa7113_tab;
- if (i2c_writereg (&budget->i2c_adap, 0x4a, 0x01, 0x08) != 1) {
- dprintk(1, "saa7113 not found on KNC card\n");
- return -ENODEV;
- }
+ if (i2c_writereg(&budget->i2c_adap, 0x4a, 0x01, 0x08) != 1) {
+ dprintk(1, "saa7113 not found on KNC card\n");
+ return -ENODEV;
+ }
- dprintk(1, "saa7113 detected and initializing\n");
+ dprintk(1, "saa7113 detected and initializing\n");
while (*data != 0xff) {
- i2c_writereg(&budget->i2c_adap, 0x4a, *data, *(data+1));
- data += 2;
- }
+ i2c_writereg(&budget->i2c_adap, 0x4a, *data, *(data + 1));
+ data += 2;
+ }
dprintk(1, "saa7113 status=%02x\n", i2c_readreg(&budget->i2c_adap, 0x4a, 0x1f));
return 0;
}
-
-static int saa7113_setinput (struct budget_av *budget_av, int input)
+static int saa7113_setinput(struct budget_av *budget_av, int input)
{
struct budget *budget = &budget_av->budget;
- if ( 1 != budget_av->has_saa7113 )
+ if (1 != budget_av->has_saa7113)
return -ENODEV;
if (input == 1) {
@@ -662,7 +669,7 @@ static int philips_tu1216_request_firmware(struct dvb_frontend *fe,
return request_firmware(fw, name, &budget->dev->pci->dev);
}
-struct tda1004x_config philips_tu1216_config = {
+static struct tda1004x_config philips_tu1216_config = {
.demod_address = 0x8,
.invert = 1,
@@ -773,19 +780,19 @@ static void budget_av_irq(struct saa7146_dev *dev, u32 * isr)
ttpci_budget_irq10_handler(dev, isr);
}
-static int budget_av_detach (struct saa7146_dev *dev)
+static int budget_av_detach(struct saa7146_dev *dev)
{
- struct budget_av *budget_av = (struct budget_av*) dev->ext_priv;
+ struct budget_av *budget_av = (struct budget_av *) dev->ext_priv;
int err;
dprintk(2, "dev: %p\n", dev);
- if ( 1 == budget_av->has_saa7113 ) {
- saa7146_setgpio(dev, 0, SAA7146_GPIO_OUTLO);
+ if (1 == budget_av->has_saa7113) {
+ saa7146_setgpio(dev, 0, SAA7146_GPIO_OUTLO);
msleep(200);
- saa7146_unregister_device (&budget_av->vd, dev);
+ saa7146_unregister_device(&budget_av->vd, dev);
}
if (budget_av->budget.ci_present)
@@ -793,9 +800,9 @@ static int budget_av_detach (struct saa7146_dev *dev)
if (budget_av->budget.dvb_frontend != NULL)
dvb_unregister_frontend(budget_av->budget.dvb_frontend);
- err = ttpci_budget_deinit (&budget_av->budget);
+ err = ttpci_budget_deinit(&budget_av->budget);
- kfree (budget_av);
+ kfree(budget_av);
return err;
}
@@ -832,30 +839,30 @@ static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio
saa7146_setgpio(dev, 0, SAA7146_GPIO_OUTHI);
msleep(500);
- if ( 0 == saa7113_init(budget_av) ) {
+ if (0 == saa7113_init(budget_av)) {
budget_av->has_saa7113 = 1;
- if ( 0 != saa7146_vv_init(dev,&vv_data)) {
- /* fixme: proper cleanup here */
- ERR(("cannot init vv subsystem.\n"));
- return err;
- }
+ if (0 != saa7146_vv_init(dev, &vv_data)) {
+ /* fixme: proper cleanup here */
+ ERR(("cannot init vv subsystem.\n"));
+ return err;
+ }
if ((err = saa7146_register_device(&budget_av->vd, dev, "knc1", VFL_TYPE_GRABBER))) {
- /* fixme: proper cleanup here */
- ERR(("cannot register capture v4l2 device.\n"));
- return err;
- }
+ /* fixme: proper cleanup here */
+ ERR(("cannot register capture v4l2 device.\n"));
+ return err;
+ }
- /* beware: this modifies dev->vv ... */
- saa7146_set_hps_source_and_sync(dev, SAA7146_HPS_SOURCE_PORT_A,
- SAA7146_HPS_SYNC_PORT_A);
+ /* beware: this modifies dev->vv ... */
+ saa7146_set_hps_source_and_sync(dev, SAA7146_HPS_SOURCE_PORT_A,
+ SAA7146_HPS_SYNC_PORT_A);
- saa7113_setinput (budget_av, 0);
+ saa7113_setinput(budget_av, 0);
} else {
budget_av->has_saa7113 = 0;
- saa7146_setgpio(dev, 0, SAA7146_GPIO_OUTLO);
+ saa7146_setgpio(dev, 0, SAA7146_GPIO_OUTLO);
}
/* fixme: find some sane values here... */
@@ -864,13 +871,13 @@ static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio
mac = budget_av->budget.dvb_adapter->proposed_mac;
if (i2c_readregs(&budget_av->budget.i2c_adap, 0xa0, 0x30, mac, 6)) {
printk("KNC1-%d: Could not read MAC from KNC1 card\n",
- budget_av->budget.dvb_adapter->num);
+ budget_av->budget.dvb_adapter->num);
memset(mac, 0, 6);
} else {
printk("KNC1-%d: MAC addr = %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
- budget_av->budget.dvb_adapter->num,
- mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
-}
+ budget_av->budget.dvb_adapter->num,
+ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+ }
budget_av->budget.dvb_adapter->priv = budget_av;
frontend_init(budget_av);
@@ -883,47 +890,45 @@ static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio
#define KNC1_INPUTS 2
static struct v4l2_input knc1_inputs[KNC1_INPUTS] = {
- { 0, "Composite", V4L2_INPUT_TYPE_TUNER, 1, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
- { 1, "S-Video", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 },
+ {0, "Composite", V4L2_INPUT_TYPE_TUNER, 1, 0, V4L2_STD_PAL_BG | V4L2_STD_NTSC_M, 0},
+ {1, "S-Video", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG | V4L2_STD_NTSC_M, 0},
};
-
static struct saa7146_extension_ioctls ioctls[] = {
- { VIDIOC_ENUMINPUT, SAA7146_EXCLUSIVE },
- { VIDIOC_G_INPUT, SAA7146_EXCLUSIVE },
- { VIDIOC_S_INPUT, SAA7146_EXCLUSIVE },
- { 0, 0 }
+ {VIDIOC_ENUMINPUT, SAA7146_EXCLUSIVE},
+ {VIDIOC_G_INPUT, SAA7146_EXCLUSIVE},
+ {VIDIOC_S_INPUT, SAA7146_EXCLUSIVE},
+ {0, 0}
};
-
-static int av_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
+static int av_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
{
struct saa7146_dev *dev = fh->dev;
- struct budget_av *budget_av = (struct budget_av*) dev->ext_priv;
+ struct budget_av *budget_av = (struct budget_av *) dev->ext_priv;
- switch(cmd) {
+ switch (cmd) {
case VIDIOC_ENUMINPUT:{
struct v4l2_input *i = arg;
-
+
dprintk(1, "VIDIOC_ENUMINPUT %d.\n", i->index);
- if( i->index < 0 || i->index >= KNC1_INPUTS) {
+ if (i->index < 0 || i->index >= KNC1_INPUTS) {
return -EINVAL;
}
memcpy(i, &knc1_inputs[i->index], sizeof(struct v4l2_input));
return 0;
}
case VIDIOC_G_INPUT:{
- int *input = (int *)arg;
+ int *input = (int *) arg;
*input = budget_av->cur_input;
dprintk(1, "VIDIOC_G_INPUT %d.\n", *input);
- return 0;
- }
+ return 0;
+ }
case VIDIOC_S_INPUT:{
- int input = *(int *)arg;
+ int input = *(int *) arg;
dprintk(1, "VIDIOC_S_INPUT %d.\n", input);
- return saa7113_setinput (budget_av, input);
+ return saa7113_setinput(budget_av, input);
}
default:
return -ENOIOCTLCMD;
@@ -933,24 +938,24 @@ static int av_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
static struct saa7146_standard standard[] = {
{.name = "PAL",.id = V4L2_STD_PAL,
- .v_offset = 0x17, .v_field = 288,
- .h_offset = 0x14, .h_pixels = 680,
+ .v_offset = 0x17,.v_field = 288,
+ .h_offset = 0x14,.h_pixels = 680,
.v_max_out = 576,.h_max_out = 768 },
{.name = "NTSC",.id = V4L2_STD_NTSC,
- .v_offset = 0x16, .v_field = 240,
- .h_offset = 0x06, .h_pixels = 708,
+ .v_offset = 0x16,.v_field = 240,
+ .h_offset = 0x06,.h_pixels = 708,
.v_max_out = 480,.h_max_out = 640, },
};
static struct saa7146_ext_vv vv_data = {
- .inputs = 2,
- .capabilities = 0, // perhaps later: V4L2_CAP_VBI_CAPTURE, but that need tweaking with the saa7113
- .flags = 0,
- .stds = &standard[0],
- .num_stds = sizeof(standard)/sizeof(struct saa7146_standard),
- .ioctls = &ioctls[0],
- .ioctl = av_ioctl,
+ .inputs = 2,
+ .capabilities = 0, // perhaps later: V4L2_CAP_VBI_CAPTURE, but that need tweaking with the saa7113
+ .flags = 0,
+ .stds = &standard[0],
+ .num_stds = sizeof(standard) / sizeof(struct saa7146_standard),
+ .ioctls = &ioctls[0],
+ .ioctl = av_ioctl,
};
static struct saa7146_extension budget_extension;
@@ -962,7 +967,7 @@ MAKE_BUDGET_INFO(cin1200s, "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 [] = {
+static struct pci_device_id pci_tbl[] = {
MAKE_EXTENSION_PCI(knc1s, 0x1131, 0x4f56),
MAKE_EXTENSION_PCI(knc1c, 0x1894, 0x0020),
MAKE_EXTENSION_PCI(knc1t, 0x1894, 0x0030),
@@ -970,32 +975,32 @@ static struct pci_device_id pci_tbl [] = {
MAKE_EXTENSION_PCI(cin1200c, 0x153b, 0x1156),
MAKE_EXTENSION_PCI(cin1200t, 0x153b, 0x1157),
{
- .vendor = 0,
+ .vendor = 0,
}
};
MODULE_DEVICE_TABLE(pci, pci_tbl);
static struct saa7146_extension budget_extension = {
- .name = "budget dvb /w video in\0",
- .pci_tbl = pci_tbl,
+ .name = "budget dvb /w video in\0",
+ .pci_tbl = pci_tbl,
- .module = THIS_MODULE,
- .attach = budget_av_attach,
- .detach = budget_av_detach,
+ .module = THIS_MODULE,
+ .attach = budget_av_attach,
+ .detach = budget_av_detach,
- .irq_mask = MASK_10,
+ .irq_mask = MASK_10,
.irq_func = budget_av_irq,
-};
+};
-static int __init budget_av_init(void)
+static int __init budget_av_init(void)
{
return saa7146_register_extension(&budget_extension);
}
static void __exit budget_av_exit(void)
{
- saa7146_unregister_extension(&budget_extension);
+ saa7146_unregister_extension(&budget_extension);
}
module_init(budget_av_init);
diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c
index 898a8bf3b4660..521111be35582 100644
--- a/drivers/media/dvb/ttpci/budget-ci.c
+++ b/drivers/media/dvb/ttpci/budget-ci.c
@@ -1,7 +1,7 @@
/*
- * budget-ci.c: driver for the SAA7146 based Budget DVB cards
+ * budget-ci.c: driver for the SAA7146 based Budget DVB cards
*
- * Compiled from various sources by Michael Hunold <michael@mihu.de>
+ * Compiled from various sources by Michael Hunold <michael@mihu.de>
*
* msp430 IR support contributed by Jack Thomasson <jkt@Helius.COM>
* partially based on the Siemens DVB driver by Ralph+Marcus Metzler
@@ -12,19 +12,19 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
- *
+ *
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
*
* You should have received a copy of the 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.
* Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- *
+ *
*
* the project's page is at http://www.linuxtv.org/dvb/
*/
@@ -76,57 +76,56 @@ struct budget_ci {
Hauppauge (from NOVA-CI-s box product)
i've taken a "middle of the road" approach and note the differences
*/
-static u16 key_map[64] = {
+static u16 key_map[64] = {
/* 0x0X */
KEY_0, KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8,
KEY_9,
KEY_ENTER,
KEY_RED,
- KEY_POWER, /* RADIO on Hauppauge */
+ KEY_POWER, /* RADIO on Hauppauge */
KEY_MUTE,
0,
- KEY_A, /* TV on Hauppauge */
+ KEY_A, /* TV on Hauppauge */
/* 0x1X */
KEY_VOLUMEUP, KEY_VOLUMEDOWN,
0, 0,
KEY_B,
0, 0, 0, 0, 0, 0, 0,
KEY_UP, KEY_DOWN,
- KEY_OPTION, /* RESERVED on Hauppauge */
+ KEY_OPTION, /* RESERVED on Hauppauge */
KEY_BREAK,
/* 0x2X */
KEY_CHANNELUP, KEY_CHANNELDOWN,
- KEY_PREVIOUS, /* Prev. Ch on Zenith, SOURCE on Hauppauge */
+ KEY_PREVIOUS, /* Prev. Ch on Zenith, SOURCE on Hauppauge */
0, KEY_RESTART, KEY_OK,
- KEY_CYCLEWINDOWS, /* MINIMIZE on Hauppauge */
+ KEY_CYCLEWINDOWS, /* MINIMIZE on Hauppauge */
0,
- KEY_ENTER, /* VCR mode on Zenith */
+ KEY_ENTER, /* VCR mode on Zenith */
KEY_PAUSE,
0,
KEY_RIGHT, KEY_LEFT,
0,
- KEY_MENU, /* FULL SCREEN on Hauppauge */
+ KEY_MENU, /* FULL SCREEN on Hauppauge */
0,
/* 0x3X */
KEY_SLOW,
- KEY_PREVIOUS, /* VCR mode on Zenith */
+ KEY_PREVIOUS, /* VCR mode on Zenith */
KEY_REWIND,
0,
KEY_FASTFORWARD,
KEY_PLAY, KEY_STOP,
KEY_RECORD,
- KEY_TUNER, /* TV/VCR on Zenith */
+ KEY_TUNER, /* TV/VCR on Zenith */
0,
KEY_C,
0,
KEY_EXIT,
KEY_POWER2,
- KEY_TUNER, /* VCR mode on Zenith */
+ KEY_TUNER, /* VCR mode on Zenith */
0,
};
-
-static void msp430_ir_debounce (unsigned long data)
+static void msp430_ir_debounce(unsigned long data)
{
struct input_dev *dev = (struct input_dev *) data;
@@ -138,34 +137,32 @@ static void msp430_ir_debounce (unsigned long data)
dev->rep[0] = 0;
dev->timer.expires = jiffies + HZ * 350 / 1000;
add_timer(&dev->timer);
- input_event(dev, EV_KEY, key_map[dev->repeat_key], 2); /* REPEAT */
+ input_event(dev, EV_KEY, key_map[dev->repeat_key], 2); /* REPEAT */
}
-
-
-static void msp430_ir_interrupt (unsigned long data)
+static void msp430_ir_interrupt(unsigned long data)
{
- struct budget_ci *budget_ci = (struct budget_ci*) data;
+ struct budget_ci *budget_ci = (struct budget_ci *) data;
struct input_dev *dev = &budget_ci->input_dev;
unsigned int code =
ttpci_budget_debiread(&budget_ci->budget, DEBINOSWAP, DEBIADDR_IR, 2, 1, 0) >> 8;
if (code & 0x40) {
- code &= 0x3f;
-
- if (timer_pending(&dev->timer)) {
- if (code == dev->repeat_key) {
- ++dev->rep[0];
- return;
- }
- del_timer(&dev->timer);
- input_event(dev, EV_KEY, key_map[dev->repeat_key], !!0);
+ code &= 0x3f;
+
+ if (timer_pending(&dev->timer)) {
+ if (code == dev->repeat_key) {
+ ++dev->rep[0];
+ return;
+ }
+ del_timer(&dev->timer);
+ input_event(dev, EV_KEY, key_map[dev->repeat_key], !!0);
}
if (!key_map[code]) {
printk("DVB (%s): no key for %02x!\n", __FUNCTION__, code);
- return;
- }
+ return;
+ }
/* initialize debounce and repeat */
dev->repeat_key = code;
@@ -174,25 +171,24 @@ static void msp430_ir_interrupt (unsigned long data)
/* 350 milliseconds */
dev->timer.expires = jiffies + HZ * 350 / 1000;
/* MAKE */
- input_event(dev, EV_KEY, key_map[code], !0);
+ input_event(dev, EV_KEY, key_map[code], !0);
add_timer(&dev->timer);
}
}
-
-static int msp430_ir_init (struct budget_ci *budget_ci)
+static int msp430_ir_init(struct budget_ci *budget_ci)
{
struct saa7146_dev *saa = budget_ci->budget.dev;
int i;
memset(&budget_ci->input_dev, 0, sizeof(struct input_dev));
- sprintf (budget_ci->ir_dev_name, "Budget-CI dvb ir receiver %s", saa->name);
+ sprintf(budget_ci->ir_dev_name, "Budget-CI dvb ir receiver %s", saa->name);
budget_ci->input_dev.name = budget_ci->ir_dev_name;
set_bit(EV_KEY, budget_ci->input_dev.evbit);
- for (i=0; i<sizeof(key_map)/sizeof(*key_map); i++)
+ for (i = 0; i < sizeof(key_map) / sizeof(*key_map); i++)
if (key_map[i])
set_bit(key_map[i], budget_ci->input_dev.keybit);
@@ -202,13 +198,12 @@ static int msp430_ir_init (struct budget_ci *budget_ci)
saa7146_write(saa, IER, saa7146_read(saa, IER) | MASK_06);
- saa7146_setgpio(saa, 3, SAA7146_GPIO_IRQHI);
+ saa7146_setgpio(saa, 3, SAA7146_GPIO_IRQHI);
return 0;
}
-
-static void msp430_ir_deinit (struct budget_ci *budget_ci)
+static void msp430_ir_deinit(struct budget_ci *budget_ci)
{
struct saa7146_dev *saa = budget_ci->budget.dev;
struct input_dev *dev = &budget_ci->input_dev;
@@ -224,7 +219,7 @@ static void msp430_ir_deinit (struct budget_ci *budget_ci)
static int ciintf_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address)
{
- struct budget_ci* budget_ci = (struct budget_ci*) ca->data;
+ struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
if (slot != 0)
return -EINVAL;
@@ -235,7 +230,7 @@ static int ciintf_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int ad
static int ciintf_write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address, u8 value)
{
- struct budget_ci* budget_ci = (struct budget_ci*) ca->data;
+ struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
if (slot != 0)
return -EINVAL;
@@ -246,7 +241,7 @@ static int ciintf_write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int a
static int ciintf_read_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address)
{
- struct budget_ci* budget_ci = (struct budget_ci*) ca->data;
+ struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
if (slot != 0)
return -EINVAL;
@@ -257,7 +252,7 @@ static int ciintf_read_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 addre
static int ciintf_write_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address, u8 value)
{
- struct budget_ci* budget_ci = (struct budget_ci*) ca->data;
+ struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
if (slot != 0)
return -EINVAL;
@@ -268,7 +263,7 @@ static int ciintf_write_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 addr
static int ciintf_slot_reset(struct dvb_ca_en50221 *ca, int slot)
{
- struct budget_ci* budget_ci = (struct budget_ci*) ca->data;
+ struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
struct saa7146_dev *saa = budget_ci->budget.dev;
if (slot != 0)
@@ -283,13 +278,13 @@ static int ciintf_slot_reset(struct dvb_ca_en50221 *ca, int slot)
CICONTROL_RESET, 1, 0);
saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTHI);
- ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);
+ ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);
return 0;
}
static int ciintf_slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
{
- struct budget_ci* budget_ci = (struct budget_ci*) ca->data;
+ struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
struct saa7146_dev *saa = budget_ci->budget.dev;
if (slot != 0)
@@ -302,7 +297,7 @@ static int ciintf_slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
static int ciintf_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
{
- struct budget_ci* budget_ci = (struct budget_ci*) ca->data;
+ struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
struct saa7146_dev *saa = budget_ci->budget.dev;
int tmp;
@@ -315,14 +310,13 @@ static int ciintf_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
tmp | CICONTROL_ENABLETS, 1, 0);
- ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTA);
+ ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTA);
return 0;
}
-
-static void ciintf_interrupt (unsigned long data)
+static void ciintf_interrupt(unsigned long data)
{
- struct budget_ci *budget_ci = (struct budget_ci*) data;
+ struct budget_ci *budget_ci = (struct budget_ci *) data;
struct saa7146_dev *saa = budget_ci->budget.dev;
unsigned int flags;
@@ -335,7 +329,7 @@ static void ciintf_interrupt (unsigned long data)
if (flags & CICONTROL_CAMDETECT) {
// GPIO should be set to trigger on falling edge if a CAM is present
- saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQLO);
+ saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQLO);
if (budget_ci->slot_status & SLOTSTATUS_NONE) {
// CAM insertion IRQ
@@ -359,7 +353,7 @@ static void ciintf_interrupt (unsigned long data)
// the CAM might not actually be ready yet.
saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI);
- // generate a CAM removal IRQ if we haven't already
+ // generate a CAM removal IRQ if we haven't already
if (budget_ci->slot_status & SLOTSTATUS_OCCUPIED) {
// CAM removal IRQ
budget_ci->slot_status = SLOTSTATUS_NONE;
@@ -369,7 +363,7 @@ static void ciintf_interrupt (unsigned long data)
}
}
-static int ciintf_init(struct budget_ci* budget_ci)
+static int ciintf_init(struct budget_ci *budget_ci)
{
struct saa7146_dev *saa = budget_ci->budget.dev;
int flags;
@@ -409,11 +403,10 @@ static int ciintf_init(struct budget_ci* budget_ci)
printk("budget_ci: CI interface detected, but initialisation failed.\n");
goto error;
}
-
// Setup CI slot IRQ
- tasklet_init (&budget_ci->ciintf_irq_tasklet, ciintf_interrupt, (unsigned long) budget_ci);
+ tasklet_init(&budget_ci->ciintf_irq_tasklet, ciintf_interrupt, (unsigned long) budget_ci);
if (budget_ci->slot_status != SLOTSTATUS_NONE) {
- saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQLO);
+ saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQLO);
} else {
saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI);
}
@@ -438,7 +431,7 @@ error:
return result;
}
-static void ciintf_deinit(struct budget_ci* budget_ci)
+static void ciintf_deinit(struct budget_ci *budget_ci)
{
struct saa7146_dev *saa = budget_ci->budget.dev;
@@ -461,20 +454,20 @@ static void ciintf_deinit(struct budget_ci* budget_ci)
saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16));
}
-static void budget_ci_irq (struct saa7146_dev *dev, u32 *isr)
+static void budget_ci_irq(struct saa7146_dev *dev, u32 * isr)
{
- struct budget_ci *budget_ci = (struct budget_ci*) dev->ext_priv;
+ struct budget_ci *budget_ci = (struct budget_ci *) dev->ext_priv;
dprintk(8, "dev: %p, budget_ci: %p\n", dev, budget_ci);
- if (*isr & MASK_06)
- tasklet_schedule (&budget_ci->msp430_irq_tasklet);
+ if (*isr & MASK_06)
+ tasklet_schedule(&budget_ci->msp430_irq_tasklet);
- if (*isr & MASK_10)
- ttpci_budget_irq10_handler (dev, isr);
+ if (*isr & MASK_10)
+ ttpci_budget_irq10_handler(dev, isr);
if ((*isr & MASK_03) && (budget_ci->budget.ci_present))
- tasklet_schedule (&budget_ci->ciintf_irq_tasklet);
+ tasklet_schedule(&budget_ci->ciintf_irq_tasklet);
}
@@ -902,7 +895,7 @@ static int budget_ci_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio
struct budget_ci *budget_ci;
int err;
- if (!(budget_ci = kmalloc (sizeof(struct budget_ci), GFP_KERNEL)))
+ if (!(budget_ci = kmalloc(sizeof(struct budget_ci), GFP_KERNEL)))
return -ENOMEM;
dprintk(2, "budget_ci: %p\n", budget_ci);
@@ -912,14 +905,14 @@ static int budget_ci_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio
dev->ext_priv = budget_ci;
if ((err = ttpci_budget_init(&budget_ci->budget, dev, info, THIS_MODULE))) {
- kfree (budget_ci);
+ kfree(budget_ci);
return err;
}
- tasklet_init (&budget_ci->msp430_irq_tasklet, msp430_ir_interrupt,
- (unsigned long) budget_ci);
+ tasklet_init(&budget_ci->msp430_irq_tasklet, msp430_ir_interrupt,
+ (unsigned long) budget_ci);
- msp430_ir_init (budget_ci);
+ msp430_ir_init(budget_ci);
ciintf_init(budget_ci);
@@ -929,11 +922,9 @@ static int budget_ci_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio
return 0;
}
-
-
-static int budget_ci_detach (struct saa7146_dev* dev)
+static int budget_ci_detach(struct saa7146_dev *dev)
{
- struct budget_ci *budget_ci = (struct budget_ci*) dev->ext_priv;
+ struct budget_ci *budget_ci = (struct budget_ci *) dev->ext_priv;
struct saa7146_dev *saa = budget_ci->budget.dev;
int err;
@@ -941,60 +932,57 @@ static int budget_ci_detach (struct saa7146_dev* dev)
ciintf_deinit(budget_ci);
if (budget_ci->budget.dvb_frontend)
dvb_unregister_frontend(budget_ci->budget.dvb_frontend);
- err = ttpci_budget_deinit (&budget_ci->budget);
+ err = ttpci_budget_deinit(&budget_ci->budget);
- tasklet_kill (&budget_ci->msp430_irq_tasklet);
+ tasklet_kill(&budget_ci->msp430_irq_tasklet);
- msp430_ir_deinit (budget_ci);
+ msp430_ir_deinit(budget_ci);
// disable frontend and CI interface
saa7146_setgpio(saa, 2, SAA7146_GPIO_INPUT);
- kfree (budget_ci);
+ kfree(budget_ci);
return err;
}
+static struct saa7146_extension budget_extension;
-
-static struct saa7146_extension budget_extension;
-
-MAKE_BUDGET_INFO(ttbci, "TT-Budget/WinTV-NOVA-CI PCI", BUDGET_TT_HW_DISEQC);
-MAKE_BUDGET_INFO(ttbt2, "TT-Budget/WinTV-NOVA-T PCI", BUDGET_TT);
+MAKE_BUDGET_INFO(ttbci, "TT-Budget/WinTV-NOVA-CI PCI", BUDGET_TT_HW_DISEQC);
+MAKE_BUDGET_INFO(ttbt2, "TT-Budget/WinTV-NOVA-T PCI", BUDGET_TT);
static struct pci_device_id pci_tbl[] = {
MAKE_EXTENSION_PCI(ttbci, 0x13c2, 0x100c),
MAKE_EXTENSION_PCI(ttbci, 0x13c2, 0x100f),
- MAKE_EXTENSION_PCI(ttbt2, 0x13c2, 0x1011),
+ MAKE_EXTENSION_PCI(ttbt2, 0x13c2, 0x1011),
{
- .vendor = 0,
- }
+ .vendor = 0,
+ }
};
MODULE_DEVICE_TABLE(pci, pci_tbl);
static struct saa7146_extension budget_extension = {
- .name = "budget_ci dvb\0",
- .flags = 0,
-
- .module = THIS_MODULE,
- .pci_tbl = &pci_tbl[0],
- .attach = budget_ci_attach,
- .detach = budget_ci_detach,
+ .name = "budget_ci dvb\0",
+ .flags = 0,
- .irq_mask = MASK_03 | MASK_06 | MASK_10,
- .irq_func = budget_ci_irq,
-};
+ .module = THIS_MODULE,
+ .pci_tbl = &pci_tbl[0],
+ .attach = budget_ci_attach,
+ .detach = budget_ci_detach,
+ .irq_mask = MASK_03 | MASK_06 | MASK_10,
+ .irq_func = budget_ci_irq,
+};
-static int __init budget_ci_init(void)
+static int __init budget_ci_init(void)
{
return saa7146_register_extension(&budget_extension);
}
static void __exit budget_ci_exit(void)
{
- saa7146_unregister_extension(&budget_extension);
+ saa7146_unregister_extension(&budget_extension);
}
module_init(budget_ci_init);
@@ -1005,4 +993,3 @@ MODULE_AUTHOR("Michael Hunold, Jack Thomasson, Andrew de Quincey, others");
MODULE_DESCRIPTION("driver for the SAA7146 based so-called "
"budget PCI DVB cards w/ CI-module produced by "
"Siemens, Technotrend, Hauppauge");
-
diff --git a/drivers/media/dvb/ttpci/budget-core.c b/drivers/media/dvb/ttpci/budget-core.c
index 669105a9b1182..93a9b40917e43 100644
--- a/drivers/media/dvb/ttpci/budget-core.c
+++ b/drivers/media/dvb/ttpci/budget-core.c
@@ -40,9 +40,8 @@
#include "ttpci-eeprom.h"
int budget_debug;
-
module_param_named(debug, budget_debug, int, 0644);
-MODULE_PARM_DESC(budget_debug, "Turn on/off budget debugging (default:off).");
+MODULE_PARM_DESC(debug, "Turn on/off budget debugging (default:off).");
/****************************************************************************
* TT budget / WinTV Nova
@@ -52,32 +51,31 @@ static int stop_ts_capture(struct budget *budget)
{
dprintk(2, "budget: %p\n", budget);
- if (--budget->feeding)
- return budget->feeding;
+ if (--budget->feeding)
+ return budget->feeding;
- saa7146_write(budget->dev, MC1, MASK_20); // DMA3 off
+ saa7146_write(budget->dev, MC1, MASK_20); // DMA3 off
SAA7146_IER_DISABLE(budget->dev, MASK_10);
- return 0;
+ return 0;
}
-
-static int start_ts_capture (struct budget *budget)
+static int start_ts_capture(struct budget *budget)
{
- struct saa7146_dev *dev=budget->dev;
+ struct saa7146_dev *dev = budget->dev;
dprintk(2, "budget: %p\n", budget);
- if (budget->feeding)
- return ++budget->feeding;
+ if (budget->feeding)
+ return ++budget->feeding;
- saa7146_write(dev, MC1, MASK_20); // DMA3 off
+ saa7146_write(dev, MC1, MASK_20); // DMA3 off
- memset(budget->grabbing, 0x00, TS_HEIGHT*TS_WIDTH);
+ memset(budget->grabbing, 0x00, TS_HEIGHT * TS_WIDTH);
saa7146_write(dev, PCI_BT_V1, 0x001c0000 | (saa7146_read(dev, PCI_BT_V1) & ~0x001f0000));
- budget->tsf=0xff;
- budget->ttbp=0;
+ budget->tsf = 0xff;
+ budget->ttbp = 0;
/*
* Signal path on the Activy:
@@ -86,7 +84,7 @@ static int start_ts_capture (struct budget *budget)
*
* Since the tuner feeds 204 bytes packets into the SAA7146,
* DMA3 is configured to strip the trailing 16 FEC bytes:
- * Pitch: 188, NumBytes3: 188, NumLines3: 1024
+ * Pitch: 188, NumBytes3: 188, NumLines3: 1024
*/
switch(budget->card->type) {
@@ -106,63 +104,62 @@ static int start_ts_capture (struct budget *budget)
saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
saa7146_write(dev, BRS_CTRL, 0x00000000);
} else {
- saa7146_write(dev, DD1_INIT, 0x02000600);
- saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
- saa7146_write(dev, BRS_CTRL, 0x60000000);
+ saa7146_write(dev, DD1_INIT, 0x02000600);
+ saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
+ saa7146_write(dev, BRS_CTRL, 0x60000000);
}
}
- saa7146_write(dev, MC2, (MASK_08 | MASK_24));
- mdelay(10);
+ saa7146_write(dev, MC2, (MASK_08 | MASK_24));
+ mdelay(10);
- saa7146_write(dev, BASE_ODD3, 0);
- saa7146_write(dev, BASE_EVEN3, 0);
- saa7146_write(dev, PROT_ADDR3, TS_WIDTH*TS_HEIGHT);
- saa7146_write(dev, BASE_PAGE3, budget->pt.dma |ME1|0x90);
+ saa7146_write(dev, BASE_ODD3, 0);
+ saa7146_write(dev, BASE_EVEN3, 0);
+ saa7146_write(dev, PROT_ADDR3, TS_WIDTH * TS_HEIGHT);
+ saa7146_write(dev, BASE_PAGE3, budget->pt.dma | ME1 | 0x90);
if (budget->card->type == BUDGET_FS_ACTIVY) {
- saa7146_write(dev, PITCH3, TS_WIDTH/2);
- saa7146_write(dev, NUM_LINE_BYTE3, ((TS_HEIGHT*2)<<16)|(TS_WIDTH/2));
+ saa7146_write(dev, PITCH3, TS_WIDTH / 2);
+ saa7146_write(dev, NUM_LINE_BYTE3, ((TS_HEIGHT * 2) << 16) | (TS_WIDTH / 2));
} else {
saa7146_write(dev, PITCH3, TS_WIDTH);
- saa7146_write(dev, NUM_LINE_BYTE3, (TS_HEIGHT<<16)|TS_WIDTH);
+ saa7146_write(dev, NUM_LINE_BYTE3, (TS_HEIGHT << 16) | TS_WIDTH);
}
- saa7146_write(dev, MC2, (MASK_04 | MASK_20));
+ saa7146_write(dev, MC2, (MASK_04 | MASK_20));
SAA7146_ISR_CLEAR(budget->dev, MASK_10); /* VPE */
SAA7146_IER_ENABLE(budget->dev, MASK_10); /* VPE */
saa7146_write(dev, MC1, (MASK_04 | MASK_20)); /* DMA3 on */
- return ++budget->feeding;
+ return ++budget->feeding;
}
-
-static void vpeirq (unsigned long data)
+static void vpeirq(unsigned long data)
{
- struct budget *budget = (struct budget*) data;
- u8 *mem = (u8 *)(budget->grabbing);
- u32 olddma = budget->ttbp;
- u32 newdma = saa7146_read(budget->dev, PCI_VDP3);
+ struct budget *budget = (struct budget *) data;
+ u8 *mem = (u8 *) (budget->grabbing);
+ u32 olddma = budget->ttbp;
+ u32 newdma = saa7146_read(budget->dev, PCI_VDP3);
- /* nearest lower position divisible by 188 */
- newdma -= newdma % 188;
+ /* nearest lower position divisible by 188 */
+ newdma -= newdma % 188;
- if (newdma >= TS_BUFLEN)
- return;
+ if (newdma >= TS_BUFLEN)
+ return;
budget->ttbp = newdma;
-
- if(budget->feeding == 0 || newdma == olddma)
+
+ if (budget->feeding == 0 || newdma == olddma)
return;
- if (newdma > olddma) { /* no wraparound, dump olddma..newdma */
+ if (newdma > olddma) { /* no wraparound, dump olddma..newdma */
dvb_dmx_swfilter_packets(&budget->demux, mem + olddma, (newdma - olddma) / 188);
- } else { /* wraparound, dump olddma..buflen and 0..newdma */
+ } else { /* wraparound, dump olddma..buflen and 0..newdma */
dvb_dmx_swfilter_packets(&budget->demux, mem + olddma, (TS_BUFLEN - olddma) / 188);
dvb_dmx_swfilter_packets(&budget->demux, mem, newdma / 188);
}
- }
+}
int ttpci_budget_debiread(struct budget *budget, u32 config, int addr, int count,
@@ -247,106 +244,104 @@ int ttpci_budget_debiwrite(struct budget *budget, u32 config, int addr,
static int budget_start_feed(struct dvb_demux_feed *feed)
{
- struct dvb_demux *demux = feed->demux;
- struct budget *budget = (struct budget*) demux->priv;
+ struct dvb_demux *demux = feed->demux;
+ struct budget *budget = (struct budget *) demux->priv;
int status;
dprintk(2, "budget: %p\n", budget);
- if (!demux->dmx.frontend)
- return -EINVAL;
+ if (!demux->dmx.frontend)
+ return -EINVAL;
- spin_lock(&budget->feedlock);
+ spin_lock(&budget->feedlock);
feed->pusi_seen = 0; /* have a clean section start */
- status = start_ts_capture (budget);
- spin_unlock(&budget->feedlock);
+ status = start_ts_capture(budget);
+ spin_unlock(&budget->feedlock);
return status;
}
static int budget_stop_feed(struct dvb_demux_feed *feed)
{
- struct dvb_demux *demux = feed->demux;
- struct budget *budget = (struct budget *) demux->priv;
+ struct dvb_demux *demux = feed->demux;
+ struct budget *budget = (struct budget *) demux->priv;
int status;
dprintk(2, "budget: %p\n", budget);
- spin_lock(&budget->feedlock);
- status = stop_ts_capture (budget);
- spin_unlock(&budget->feedlock);
+ spin_lock(&budget->feedlock);
+ status = stop_ts_capture(budget);
+ spin_unlock(&budget->feedlock);
return status;
}
-
static int budget_register(struct budget *budget)
{
- struct dvb_demux *dvbdemux=&budget->demux;
- int ret;
+ struct dvb_demux *dvbdemux = &budget->demux;
+ int ret;
dprintk(2, "budget: %p\n", budget);
- dvbdemux->priv = (void *) budget;
+ dvbdemux->priv = (void *) budget;
dvbdemux->filternum = 256;
- dvbdemux->feednum = 256;
- dvbdemux->start_feed = budget_start_feed;
- dvbdemux->stop_feed = budget_stop_feed;
- dvbdemux->write_to_decoder = NULL;
+ dvbdemux->feednum = 256;
+ dvbdemux->start_feed = budget_start_feed;
+ dvbdemux->stop_feed = budget_stop_feed;
+ dvbdemux->write_to_decoder = NULL;
+
+ dvbdemux->dmx.capabilities = (DMX_TS_FILTERING | DMX_SECTION_FILTERING |
+ DMX_MEMORY_BASED_FILTERING);
- dvbdemux->dmx.capabilities = (DMX_TS_FILTERING | DMX_SECTION_FILTERING |
- DMX_MEMORY_BASED_FILTERING);
+ dvb_dmx_init(&budget->demux);
- dvb_dmx_init(&budget->demux);
+ budget->dmxdev.filternum = 256;
+ budget->dmxdev.demux = &dvbdemux->dmx;
+ budget->dmxdev.capabilities = 0;
- budget->dmxdev.filternum = 256;
- budget->dmxdev.demux = &dvbdemux->dmx;
- budget->dmxdev.capabilities = 0;
+ dvb_dmxdev_init(&budget->dmxdev, budget->dvb_adapter);
- dvb_dmxdev_init(&budget->dmxdev, budget->dvb_adapter);
+ budget->hw_frontend.source = DMX_FRONTEND_0;
- budget->hw_frontend.source = DMX_FRONTEND_0;
+ ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &budget->hw_frontend);
- ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &budget->hw_frontend);
+ if (ret < 0)
+ return ret;
- if (ret < 0)
- return ret;
-
- budget->mem_frontend.source = DMX_MEMORY_FE;
+ budget->mem_frontend.source = DMX_MEMORY_FE;
ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &budget->mem_frontend);
- if (ret<0)
- return ret;
-
+ if (ret < 0)
+ return ret;
+
ret = dvbdemux->dmx.connect_frontend(&dvbdemux->dmx, &budget->hw_frontend);
- if (ret < 0)
- return ret;
+ if (ret < 0)
+ return ret;
- dvb_net_init(budget->dvb_adapter, &budget->dvb_net, &dvbdemux->dmx);
+ dvb_net_init(budget->dvb_adapter, &budget->dvb_net, &dvbdemux->dmx);
return 0;
}
-
static void budget_unregister(struct budget *budget)
{
- struct dvb_demux *dvbdemux=&budget->demux;
+ struct dvb_demux *dvbdemux = &budget->demux;
dprintk(2, "budget: %p\n", budget);
dvb_net_release(&budget->dvb_net);
dvbdemux->dmx.close(&dvbdemux->dmx);
- dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &budget->hw_frontend);
- dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &budget->mem_frontend);
+ dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &budget->hw_frontend);
+ dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &budget->mem_frontend);
- dvb_dmxdev_release(&budget->dmxdev);
- dvb_dmx_release(&budget->demux);
+ dvb_dmxdev_release(&budget->dmxdev);
+ dvb_dmx_release(&budget->demux);
}
int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev,
struct saa7146_pci_extension_data *info,
struct module *owner)
{
- int length = TS_WIDTH*TS_HEIGHT;
+ int length = TS_WIDTH * TS_HEIGHT;
int ret = 0;
struct budget_info *bi = info->ext_priv;
@@ -360,13 +355,13 @@ int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev,
dvb_register_adapter(&budget->dvb_adapter, budget->card->name, owner);
/* set dd1 stream a & b */
- saa7146_write(dev, DD1_STREAM_B, 0x00000000);
+ saa7146_write(dev, DD1_STREAM_B, 0x00000000);
saa7146_write(dev, MC2, (MASK_09 | MASK_25));
saa7146_write(dev, MC2, (MASK_10 | MASK_26));
saa7146_write(dev, DD1_INIT, 0x02000000);
saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
- if (bi->type != BUDGET_FS_ACTIVY)
+ if (bi->type != BUDGET_FS_ACTIVY)
budget->video_port = BUDGET_VIDEO_PORTB;
else
budget->video_port = BUDGET_VIDEO_PORTA;
@@ -374,10 +369,10 @@ int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev,
spin_lock_init(&budget->debilock);
/* the Siemens DVB needs this if you want to have the i2c chips
- get recognized before the main driver is loaded */
+ get recognized before the main driver is loaded */
if (bi->type != BUDGET_FS_ACTIVY)
- saa7146_write(dev, GPIO_CTRL, 0x500000); /* GPIO 3 = 1 */
-
+ saa7146_write(dev, GPIO_CTRL, 0x500000); /* GPIO 3 = 1 */
+
#ifdef I2C_ADAP_CLASS_TV_DIGITAL
budget->i2c_adap.class = I2C_ADAP_CLASS_TV_DIGITAL;
#else
@@ -390,7 +385,7 @@ int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev,
strcpy(budget->i2c_adap.name, budget->card->name);
if (i2c_add_adapter(&budget->i2c_adap) < 0) {
- dvb_unregister_adapter (budget->dvb_adapter);
+ dvb_unregister_adapter(budget->dvb_adapter);
return -ENOMEM;
}
@@ -404,9 +399,9 @@ int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev,
saa7146_write(dev, PCI_BT_V1, 0x001c0000);
/* upload all */
- saa7146_write(dev, GPIO_CTRL, 0x000000);
+ saa7146_write(dev, GPIO_CTRL, 0x000000);
- tasklet_init (&budget->vpe_tasklet, vpeirq, (unsigned long) budget);
+ tasklet_init(&budget->vpe_tasklet, vpeirq, (unsigned long) budget);
/* frontend power on */
if (bi->type == BUDGET_FS_ACTIVY)
@@ -414,66 +409,64 @@ int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev,
else
saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI);
- if (budget_register(budget) == 0) {
+ if (budget_register(budget) == 0) {
return 0;
}
err:
i2c_del_adapter(&budget->i2c_adap);
- if (budget->grabbing)
- vfree(budget->grabbing);
+ vfree(budget->grabbing);
- dvb_unregister_adapter (budget->dvb_adapter);
+ dvb_unregister_adapter(budget->dvb_adapter);
return ret;
}
-
-int ttpci_budget_deinit (struct budget *budget)
+int ttpci_budget_deinit(struct budget *budget)
{
struct saa7146_dev *dev = budget->dev;
dprintk(2, "budget: %p\n", budget);
- budget_unregister (budget);
+ budget_unregister(budget);
i2c_del_adapter(&budget->i2c_adap);
- dvb_unregister_adapter (budget->dvb_adapter);
+ dvb_unregister_adapter(budget->dvb_adapter);
- tasklet_kill (&budget->vpe_tasklet);
+ tasklet_kill(&budget->vpe_tasklet);
- saa7146_pgtable_free (dev->pci, &budget->pt);
+ saa7146_pgtable_free(dev->pci, &budget->pt);
- vfree (budget->grabbing);
+ vfree(budget->grabbing);
return 0;
}
-void ttpci_budget_irq10_handler (struct saa7146_dev* dev, u32 *isr)
+void ttpci_budget_irq10_handler(struct saa7146_dev *dev, u32 * isr)
{
- struct budget *budget = (struct budget*)dev->ext_priv;
+ struct budget *budget = (struct budget *) dev->ext_priv;
- dprintk(8, "dev: %p, budget: %p\n",dev,budget);
+ dprintk(8, "dev: %p, budget: %p\n", dev, budget);
if (*isr & MASK_10)
- tasklet_schedule (&budget->vpe_tasklet);
+ tasklet_schedule(&budget->vpe_tasklet);
}
-void ttpci_budget_set_video_port(struct saa7146_dev* dev, int video_port)
+void ttpci_budget_set_video_port(struct saa7146_dev *dev, int video_port)
{
- struct budget *budget = (struct budget*)dev->ext_priv;
+ struct budget *budget = (struct budget *) dev->ext_priv;
spin_lock(&budget->feedlock);
budget->video_port = video_port;
if (budget->feeding) {
int oldfeeding = budget->feeding;
- budget->feeding = 1;
+ budget->feeding = 1;
stop_ts_capture(budget);
start_ts_capture(budget);
- budget->feeding = oldfeeding;
+ budget->feeding = oldfeeding;
}
- spin_unlock(&budget->feedlock);
+ spin_unlock(&budget->feedlock);
}
EXPORT_SYMBOL_GPL(ttpci_budget_debiread);
@@ -485,4 +478,3 @@ EXPORT_SYMBOL_GPL(ttpci_budget_set_video_port);
EXPORT_SYMBOL_GPL(budget_debug);
MODULE_LICENSE("GPL");
-
diff --git a/drivers/media/dvb/ttpci/budget-patch.c b/drivers/media/dvb/ttpci/budget-patch.c
index 619e87f063575..5d524a4f213f3 100644
--- a/drivers/media/dvb/ttpci/budget-patch.c
+++ b/drivers/media/dvb/ttpci/budget-patch.c
@@ -13,19 +13,19 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
- *
+ *
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
*
* You should have received a copy of the 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.
* Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- *
+ *
*
* the project's page is at http://www.linuxtv.org/dvb/
*/
@@ -55,7 +55,7 @@ static struct pci_device_id pci_tbl[] = {
/* those lines are for budget-patch to be tried
** on a true budget card and observe the
** behaviour of VSYNC generated by rps1.
-** this code was shamelessly copy/pasted from budget.c
+** this code was shamelessly copy/pasted from budget.c
*/
static void gpio_Set22K (struct budget *budget, int state)
{
@@ -96,10 +96,10 @@ static void DiseqcSendByte (struct budget *budget, int data)
static int SendDiSEqCMsg (struct budget *budget, int len, u8 *msg, unsigned long burst)
{
- struct saa7146_dev *dev=budget->dev;
+ struct saa7146_dev *dev=budget->dev;
int i;
- dprintk(2, "budget: %p\n", budget);
+ dprintk(2, "budget: %p\n", budget);
saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
mdelay(16);
@@ -123,7 +123,7 @@ static int SendDiSEqCMsg (struct budget *budget, int len, u8 *msg, unsigned long
return 0;
}
-/* shamelessly copy/pasted from budget.c
+/* shamelessly copy/pasted from budget.c
*/
static int budget_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
{
@@ -151,7 +151,7 @@ static int budget_diseqc_send_master_cmd(struct dvb_frontend* fe, struct dvb_dis
SendDiSEqCMsg (budget, cmd->msg_len, cmd->msg, 0);
- return 0;
+ return 0;
}
static int budget_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd)
@@ -173,27 +173,25 @@ static int budget_av7110_send_fw_cmd(struct budget_patch *budget, u16* buf, int
{
ttpci_budget_debiwrite(budget, DEBINOSWAP, COMMAND + 2*i, 2, (u32) buf[i], 0,0);
msleep(5);
- }
+ }
if (length)
ttpci_budget_debiwrite(budget, DEBINOSWAP, COMMAND + 2, 2, (u32) buf[1], 0,0);
else
ttpci_budget_debiwrite(budget, DEBINOSWAP, COMMAND + 2, 2, 0, 0,0);
- msleep(5);
+ msleep(5);
ttpci_budget_debiwrite(budget, DEBINOSWAP, COMMAND, 2, (u32) buf[0], 0,0);
msleep(5);
return 0;
}
-
static void av7110_set22k(struct budget_patch *budget, int state)
{
u16 buf[2] = {( COMTYPE_AUDIODAC << 8) | (state ? ON22K : OFF22K), 0};
-
+
dprintk(2, "budget: %p\n", budget);
budget_av7110_send_fw_cmd(budget, buf, 2);
}
-
static int av7110_send_diseqc_msg(struct budget_patch *budget, int len, u8 *msg, int burst)
{
int i;
@@ -212,7 +210,7 @@ static int av7110_send_diseqc_msg(struct budget_patch *budget, int len, u8 *msg,
buf[3]=burst ? 0x01 : 0x00;
else
buf[3]=0xffff;
-
+
for (i=0; i<len; i++)
buf[i+4]=msg[i];
@@ -225,27 +223,29 @@ static int budget_patch_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t ton
struct budget_patch* budget = (struct budget_patch*) fe->dvb->priv;
switch (tone) {
- case SEC_TONE_ON:
- av7110_set22k (budget, 1);
- break;
- case SEC_TONE_OFF:
- av7110_set22k (budget, 0);
- break;
- default:
- return -EINVAL;
- }
+ case SEC_TONE_ON:
+ av7110_set22k (budget, 1);
+ break;
+
+ case SEC_TONE_OFF:
+ av7110_set22k (budget, 0);
+ break;
+
+ default:
+ return -EINVAL;
+ }
return 0;
}
static int budget_patch_diseqc_send_master_cmd(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd)
- {
+{
struct budget_patch* budget = (struct budget_patch*) fe->dvb->priv;
- av7110_send_diseqc_msg (budget, cmd->msg_len, cmd->msg, 0);
+ av7110_send_diseqc_msg (budget, cmd->msg_len, cmd->msg, 0);
return 0;
- }
+}
static int budget_patch_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd)
{
@@ -254,7 +254,7 @@ static int budget_patch_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_c
av7110_send_diseqc_msg (budget, 0, NULL, minicmd);
return 0;
- }
+}
static int alps_bsrv2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
{
@@ -350,7 +350,7 @@ static int alps_bsru6_set_symbol_rate(struct dvb_frontend* fe, u32 srate, u32 ra
stv0299_writereg (fe, 0x20, (ratio >> 8) & 0xff);
stv0299_writereg (fe, 0x21, (ratio ) & 0xf0);
- return 0;
+ return 0;
}
static int alps_bsru6_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
@@ -406,7 +406,7 @@ static int grundig_29504_451_pll_set(struct dvb_frontend* fe, struct dvb_fronten
return 0;
}
-struct tda8083_config grundig_29504_451_config = {
+static struct tda8083_config grundig_29504_451_config = {
.demod_address = 0x68,
.pll_set = grundig_29504_451_pll_set,
};
@@ -498,7 +498,7 @@ static int budget_patch_attach (struct saa7146_dev* dev, struct saa7146_pci_exte
saa7146_write(dev, CLIP_FORMAT_CTRL, 0); // r78
// Set HPS prescaler for port B input
saa7146_write(dev, HPS_CTRL, (1<<30) | (0<<29) | (1<<28) | (0<<12) );
- saa7146_write(dev, MC2,
+ saa7146_write(dev, MC2,
0 * (MASK_08 | MASK_24) | // BRS control
0 * (MASK_09 | MASK_25) | // a
0 * (MASK_10 | MASK_26) | // b
@@ -512,15 +512,15 @@ static int budget_patch_attach (struct saa7146_dev* dev, struct saa7146_pci_exte
// RPS1 timeout disable
saa7146_write(dev, RPS_TOV1, 0);
- // code for autodetection
+ // code for autodetection
// will wait for VBI_B event (vertical blank at port B)
// and will reset GPIO3 after VBI_B is detected.
// (GPIO3 should be raised high by CPU to
- // test if GPIO3 will generate vertical blank signal
+ // test if GPIO3 will generate vertical blank signal
// in budget patch GPIO3 is connected to VSYNC_B
count = 0;
#if 0
- WRITE_RPS1(cpu_to_le32(CMD_UPLOAD |
+ WRITE_RPS1(cpu_to_le32(CMD_UPLOAD |
MASK_10 | MASK_09 | MASK_08 | MASK_06 | MASK_05 | MASK_04 | MASK_03 | MASK_02 ));
#endif
WRITE_RPS1(cpu_to_le32(CMD_PAUSE | EVT_VBI_B));
@@ -557,7 +557,7 @@ static int budget_patch_attach (struct saa7146_dev* dev, struct saa7146_pci_exte
saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI);
mdelay(150);
-
+
if( (saa7146_read(dev, GPIO_CTRL) & 0x10000000) == 0)
detected = 1;
@@ -570,51 +570,51 @@ static int budget_patch_attach (struct saa7146_dev* dev, struct saa7146_pci_exte
if(detected == 0)
printk("budget-patch not detected or saa7146 in non-default state.\n"
"try enabling ressetting of 7146 with MASK_31 in MC1 register\n");
-
+
else
printk("BUDGET-PATCH DETECTED.\n");
/* OLD (Original design by Roberto Deza):
-** This code will setup the SAA7146_RPS1 to generate a square
-** wave on GPIO3, changing when a field (TS_HEIGHT/2 "lines" of
-** TS_WIDTH packets) has been acquired on SAA7146_D1B video port;
-** then, this GPIO3 output which is connected to the D1B_VSYNC
-** input, will trigger the acquisition of the alternate field
+** This code will setup the SAA7146_RPS1 to generate a square
+** wave on GPIO3, changing when a field (TS_HEIGHT/2 "lines" of
+** TS_WIDTH packets) has been acquired on SAA7146_D1B video port;
+** then, this GPIO3 output which is connected to the D1B_VSYNC
+** input, will trigger the acquisition of the alternate field
** and so on.
-** Currently, the TT_budget / WinTV_Nova cards have two ICs
-** (74HCT4040, LVC74) for the generation of this VSYNC signal,
+** Currently, the TT_budget / WinTV_Nova cards have two ICs
+** (74HCT4040, LVC74) for the generation of this VSYNC signal,
** which seems that can be done perfectly without this :-)).
-*/
+*/
/* New design (By Emard)
** this rps1 code will copy internal HS event to GPIO3 pin.
** GPIO3 is in budget-patch hardware connectd to port B VSYNC
** HS is an internal event of 7146, accessible with RPS
-** and temporarily raised high every n lines
+** and temporarily raised high every n lines
** (n in defined in the RPS_THRESH1 counter threshold)
** I think HS is raised high on the beginning of the n-th line
** and remains high until this n-th line that triggered
** it is completely received. When the receiption of n-th line
** ends, HS is lowered.
-** To transmit data over DMA, 7146 needs changing state at
-** port B VSYNC pin. Any changing of port B VSYNC will
+** To transmit data over DMA, 7146 needs changing state at
+** port B VSYNC pin. Any changing of port B VSYNC will
** cause some DMA data transfer, with more or less packets loss.
-** It depends on the phase and frequency of VSYNC and
+** It depends on the phase and frequency of VSYNC and
** the way of 7146 is instructed to trigger on port B (defined
** in DD1_INIT register, 3rd nibble from the right valid
** numbers are 0-7, see datasheet)
**
-** The correct triggering can minimize packet loss,
+** The correct triggering can minimize packet loss,
** dvbtraffic should give this stable bandwidths:
** 22k transponder = 33814 kbit/s
** 27.5k transponder = 38045 kbit/s
-** by experiment it is found that the best results
-** (stable bandwidths and almost no packet loss)
-** are obtained using DD1_INIT triggering number 2
-** (Va at rising edge of VS Fa = HS x VS-failing forced toggle)
+** by experiment it is found that the best results
+** (stable bandwidths and almost no packet loss)
+** are obtained using DD1_INIT triggering number 2
+** (Va at rising edge of VS Fa = HS x VS-failing forced toggle)
** and a VSYNC phase that occurs in the middle of DMA transfer
** (about byte 188*512=96256 in the DMA window).
**
@@ -625,20 +625,20 @@ static int budget_patch_attach (struct saa7146_dev* dev, struct saa7146_pci_exte
** increment. That's how the 7146 is programmed to do event
** counting in this budget-patch.c
** I *think* HPS setting has something to do with the phase
-** of HS but I cant be 100% sure in that.
+** of HS but I cant be 100% sure in that.
** hardware debug note: a working budget card (including budget patch)
** with vpeirq() interrupt setup in mode "0x90" (every 64K) will
** generate 3 interrupts per 25-Hz DMA frame of 2*188*512 bytes
** and that means 3*25=75 Hz of interrupt freqency, as seen by
-** watch cat /proc/interrupts
+** watch cat /proc/interrupts
**
** If this frequency is 3x lower (and data received in the DMA
** buffer don't start with 0x47, but in the middle of packets,
** whose lengths appear to be like 188 292 188 104 etc.
-** this means VSYNC line is not connected in the hardware.
+** this means VSYNC line is not connected in the hardware.
** (check soldering pcb and pins)
-** The same behaviour of missing VSYNC can be duplicated on budget
+** The same behaviour of missing VSYNC can be duplicated on budget
** cards, by seting DD1_INIT trigger mode 7 in 3rd nibble.
*/
@@ -681,14 +681,14 @@ static int budget_patch_attach (struct saa7146_dev* dev, struct saa7146_pci_exte
// low 16 bits are set to TS_WIDTH bytes (TS_WIDTH=2*188
//,then RPS_THRESH1
// should be set to trigger every TS_HEIGHT (512) lines.
- //
+ //
saa7146_write(dev, RPS_THRESH1, (TS_HEIGHT*1) | MASK_12 );
-
+
// saa7146_write(dev, RPS_THRESH0, ((TS_HEIGHT/2)<<16) |MASK_28| (TS_HEIGHT/2) |MASK_12 );
// Enable RPS1 (rFC p33)
saa7146_write(dev, MC1, (MASK_13 | MASK_29));
-
+
if (!(budget = kmalloc (sizeof(struct budget_patch), GFP_KERNEL)))
return -ENOMEM;
@@ -708,7 +708,6 @@ static int budget_patch_attach (struct saa7146_dev* dev, struct saa7146_pci_exte
return 0;
}
-
static int budget_patch_detach (struct saa7146_dev* dev)
{
struct budget_patch *budget = (struct budget_patch*) dev->ext_priv;
@@ -723,22 +722,20 @@ static int budget_patch_detach (struct saa7146_dev* dev)
return err;
}
-
-static int __init budget_patch_init(void)
+static int __init budget_patch_init(void)
{
return saa7146_register_extension(&budget_extension);
}
static void __exit budget_patch_exit(void)
{
- saa7146_unregister_extension(&budget_extension);
+ saa7146_unregister_extension(&budget_extension);
}
-
static struct saa7146_extension budget_extension = {
.name = "budget_patch dvb\0",
.flags = 0,
-
+
.module = THIS_MODULE,
.pci_tbl = pci_tbl,
.attach = budget_patch_attach,
@@ -748,7 +745,6 @@ static struct saa7146_extension budget_extension = {
.irq_func = ttpci_budget_irq10_handler,
};
-
module_init(budget_patch_init);
module_exit(budget_patch_exit);
@@ -756,4 +752,3 @@ MODULE_LICENSE("GPL");
MODULE_AUTHOR("Emard, Roberto Deza, Holger Waechtler, Michael Hunold, others");
MODULE_DESCRIPTION("Driver for full TS modified DVB-S SAA7146+AV7110 "
"based so-called Budget Patch cards");
-
diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c
index 031105c1d48ee..5e6a10f4ad95b 100644
--- a/drivers/media/dvb/ttpci/budget.c
+++ b/drivers/media/dvb/ttpci/budget.c
@@ -1,35 +1,35 @@
/*
- * budget.c: driver for the SAA7146 based Budget DVB cards
+ * budget.c: driver for the SAA7146 based Budget DVB cards
*
- * Compiled from various sources by Michael Hunold <michael@mihu.de>
+ * Compiled from various sources by Michael Hunold <michael@mihu.de>
*
* Copyright (C) 2002 Ralph Metzler <rjkm@metzlerbros.de>
*
- * Copyright (C) 1999-2002 Ralph Metzler
+ * Copyright (C) 1999-2002 Ralph Metzler
* & Marcus Metzler for convergence integrated media GmbH
*
* 26feb2004 Support for FS Activy Card (Grundig tuner) by
* Michael Dreher <michael@5dot1.de>,
* Oliver Endriss <o.endriss@gmx.de> and
* Andreas 'randy' Weinberger
- *
+ *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
- *
+ *
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
*
* You should have received a copy of the 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.
* Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- *
+ *
*
* the project's page is at http://www.linuxtv.org/dvb/
*/
@@ -48,7 +48,6 @@ static void Set22K (struct budget *budget, int state)
saa7146_setgpio(dev, 3, (state ? SAA7146_GPIO_OUTHI : SAA7146_GPIO_OUTLO));
}
-
/* Diseqc functions only for TT Budget card */
/* taken from the Skyvision DVB driver by
Ralph Metzler <rjkm@metzlerbros.de> */
@@ -64,7 +63,6 @@ static void DiseqcSendBit (struct budget *budget, int data)
udelay(data ? 1000 : 500);
}
-
static void DiseqcSendByte (struct budget *budget, int data)
{
int i, par=1, d;
@@ -80,7 +78,6 @@ static void DiseqcSendByte (struct budget *budget, int data)
DiseqcSendBit(budget, par);
}
-
static int SendDiSEqCMsg (struct budget *budget, int len, u8 *msg, unsigned long burst)
{
struct saa7146_dev *dev=budget->dev;
@@ -119,7 +116,7 @@ static int SetVoltage_Activy (struct budget *budget, fe_sec_voltage_t voltage)
{
struct saa7146_dev *dev=budget->dev;
- dprintk(2, "budget: %p\n", budget);
+ dprintk(2, "budget: %p\n", budget);
switch (voltage) {
case SEC_VOLTAGE_13:
@@ -147,28 +144,29 @@ static int budget_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
struct budget* budget = (struct budget*) fe->dvb->priv;
switch (tone) {
- case SEC_TONE_ON:
- Set22K (budget, 1);
- break;
- case SEC_TONE_OFF:
- Set22K (budget, 0);
- break;
-
- default:
- return -EINVAL;
+ case SEC_TONE_ON:
+ Set22K (budget, 1);
+ break;
+
+ case SEC_TONE_OFF:
+ Set22K (budget, 0);
+ break;
+
+ default:
+ return -EINVAL;
}
return 0;
}
static int budget_diseqc_send_master_cmd(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd)
- {
+{
struct budget* budget = (struct budget*) fe->dvb->priv;
- SendDiSEqCMsg (budget, cmd->msg_len, cmd->msg, 0);
+ SendDiSEqCMsg (budget, cmd->msg_len, cmd->msg, 0);
return 0;
- }
+}
static int budget_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd)
{
@@ -176,7 +174,7 @@ static int budget_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t m
SendDiSEqCMsg (budget, 0, NULL, minicmd);
- return 0;
+ return 0;
}
static int alps_bsrv2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
@@ -275,7 +273,7 @@ static int alps_bsru6_set_symbol_rate(struct dvb_frontend* fe, u32 srate, u32 ra
stv0299_writereg (fe, 0x21, (ratio ) & 0xf0);
return 0;
- }
+}
static int alps_bsru6_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
{
@@ -368,7 +366,7 @@ static int grundig_29504_401_pll_set(struct dvb_frontend* fe, struct dvb_fronten
if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
return 0;
- }
+}
static struct l64781_config grundig_29504_401_config = {
.demod_address = 0x55,
@@ -434,22 +432,28 @@ static void frontend_init(struct budget *budget)
}
break;
- case 0x1004: // Hauppauge/TT DVB-C budget (ves1820/ALPS TDBE2(sp5659))
+ case 0x1004: // Hauppauge/TT DVB-C budget (ves1820/ALPS TDBE2(sp5659))
budget->dvb_frontend = ves1820_attach(&alps_tdbe2_config, &budget->i2c_adap, read_pwm(budget));
if (budget->dvb_frontend) break;
break;
- case 0x1005: // Hauppauge/TT Nova-T budget (L64781/Grundig 29504-401(tsa5060))
+ case 0x1005: // Hauppauge/TT Nova-T budget (L64781/Grundig 29504-401(tsa5060))
budget->dvb_frontend = l64781_attach(&grundig_29504_401_config, &budget->i2c_adap);
if (budget->dvb_frontend) break;
break;
- case 0x4f61: // Fujitsu Siemens Activy Budget-S PCI (tda8083/Grundig 29504-451(tsa5522))
+ case 0x4f60: // Fujitsu Siemens Activy Budget-S PCI rev AL (stv0299/ALPS BSRU6(tsa5059))
+ 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;
+ }
+ break;
- // grundig 29504-451
- budget->dvb_frontend = tda8083_attach(&grundig_29504_451_config, &budget->i2c_adap);
+ case 0x4f61: // Fujitsu Siemens Activy Budget-S PCI rev GR (tda8083/Grundig 29504-451(tsa5522))
+ 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;
@@ -499,7 +503,6 @@ static int budget_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_
return 0;
}
-
static int budget_detach (struct saa7146_dev* dev)
{
struct budget *budget = (struct budget*) dev->ext_priv;
@@ -515,22 +518,22 @@ static int budget_detach (struct saa7146_dev* dev)
return err;
}
-
-
static struct saa7146_extension budget_extension;
MAKE_BUDGET_INFO(ttbs, "TT-Budget/WinTV-NOVA-S PCI", BUDGET_TT);
MAKE_BUDGET_INFO(ttbc, "TT-Budget/WinTV-NOVA-C PCI", BUDGET_TT);
MAKE_BUDGET_INFO(ttbt, "TT-Budget/WinTV-NOVA-T PCI", BUDGET_TT);
MAKE_BUDGET_INFO(satel, "SATELCO Multimedia PCI", BUDGET_TT_HW_DISEQC);
-MAKE_BUDGET_INFO(fsacs, "Fujitsu Siemens Activy Budget-S PCI", BUDGET_FS_ACTIVY);
+MAKE_BUDGET_INFO(fsacs0, "Fujitsu Siemens Activy Budget-S PCI (rev GR/grundig frontend)", BUDGET_FS_ACTIVY);
+MAKE_BUDGET_INFO(fsacs1, "Fujitsu Siemens Activy Budget-S PCI (rev AL/alps frontend)", BUDGET_FS_ACTIVY);
static struct pci_device_id pci_tbl[] = {
MAKE_EXTENSION_PCI(ttbs, 0x13c2, 0x1003),
MAKE_EXTENSION_PCI(ttbc, 0x13c2, 0x1004),
MAKE_EXTENSION_PCI(ttbt, 0x13c2, 0x1005),
MAKE_EXTENSION_PCI(satel, 0x13c2, 0x1013),
- MAKE_EXTENSION_PCI(fsacs, 0x1131, 0x4f61),
+ MAKE_EXTENSION_PCI(fsacs1,0x1131, 0x4f60),
+ MAKE_EXTENSION_PCI(fsacs0,0x1131, 0x4f61),
{
.vendor = 0,
}
@@ -540,8 +543,8 @@ MODULE_DEVICE_TABLE(pci, pci_tbl);
static struct saa7146_extension budget_extension = {
.name = "budget dvb\0",
- .flags = 0,
-
+ .flags = 0,
+
.module = THIS_MODULE,
.pci_tbl = pci_tbl,
.attach = budget_attach,
@@ -549,18 +552,16 @@ static struct saa7146_extension budget_extension = {
.irq_mask = MASK_10,
.irq_func = ttpci_budget_irq10_handler,
-};
-
+};
-static int __init budget_init(void)
+static int __init budget_init(void)
{
return saa7146_register_extension(&budget_extension);
}
-
static void __exit budget_exit(void)
{
- saa7146_unregister_extension(&budget_extension);
+ saa7146_unregister_extension(&budget_extension);
}
module_init(budget_init);
@@ -570,4 +571,3 @@ MODULE_LICENSE("GPL");
MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, Michael Hunold, others");
MODULE_DESCRIPTION("driver for the SAA7146 based so-called "
"budget PCI DVB cards by Siemens, Technotrend, Hauppauge");
-
diff --git a/drivers/media/dvb/ttpci/budget.h b/drivers/media/dvb/ttpci/budget.h
index 726394cab8cd2..10bd41f0363b0 100644
--- a/drivers/media/dvb/ttpci/budget.h
+++ b/drivers/media/dvb/ttpci/budget.h
@@ -29,48 +29,46 @@ struct budget_info {
/* place to store all the necessary device information */
struct budget {
- /* devices */
- struct dvb_device dvb_dev;
- struct dvb_net dvb_net;
+ /* devices */
+ struct dvb_device dvb_dev;
+ struct dvb_net dvb_net;
- struct saa7146_dev *dev;
+ struct saa7146_dev *dev;
- struct i2c_adapter i2c_adap;
- struct budget_info *card;
+ struct i2c_adapter i2c_adap;
+ struct budget_info *card;
- unsigned char *grabbing;
- struct saa7146_pgtable pt;
+ unsigned char *grabbing;
+ struct saa7146_pgtable pt;
- struct tasklet_struct fidb_tasklet;
- struct tasklet_struct vpe_tasklet;
+ struct tasklet_struct fidb_tasklet;
+ struct tasklet_struct vpe_tasklet;
- struct dmxdev dmxdev;
- struct dvb_demux demux;
+ struct dmxdev dmxdev;
+ struct dvb_demux demux;
- struct dmx_frontend hw_frontend;
- struct dmx_frontend mem_frontend;
+ struct dmx_frontend hw_frontend;
+ struct dmx_frontend mem_frontend;
- int fe_synced;
- struct semaphore pid_mutex;
+ int fe_synced;
+ struct semaphore pid_mutex;
- int ci_present;
- int video_port;
+ int ci_present;
+ int video_port;
- u8 tsf;
- u32 ttbp;
- int feeding;
+ u8 tsf;
+ u32 ttbp;
+ int feeding;
spinlock_t feedlock;
spinlock_t debilock;
- struct dvb_adapter *dvb_adapter;
+ struct dvb_adapter *dvb_adapter;
struct dvb_frontend *dvb_frontend;
- void *priv;
+ void *priv;
};
-
-
#define MAKE_BUDGET_INFO(x_var,x_name,x_type) \
static struct budget_info x_var ## _info = { \
.name=x_name, \
@@ -101,9 +99,9 @@ static struct saa7146_pci_extension_data x_var = { \
extern int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev,
struct saa7146_pci_extension_data *info,
struct module *owner);
-extern int ttpci_budget_deinit (struct budget *budget);
-extern void ttpci_budget_irq10_handler (struct saa7146_dev* dev, u32 *isr);
-extern void ttpci_budget_set_video_port(struct saa7146_dev* dev, int video_port);
+extern int ttpci_budget_deinit(struct budget *budget);
+extern void ttpci_budget_irq10_handler(struct saa7146_dev *dev, u32 * isr);
+extern void ttpci_budget_set_video_port(struct saa7146_dev *dev, int video_port);
extern int ttpci_budget_debiread(struct budget *budget, u32 config, int addr, int count,
int uselocks, int nobusyloop);
extern int ttpci_budget_debiwrite(struct budget *budget, u32 config, int addr, int count, u32 value,
diff --git a/drivers/media/dvb/ttpci/ttpci-eeprom.c b/drivers/media/dvb/ttpci/ttpci-eeprom.c
index 0659c53f94644..e9a8457b07279 100644
--- a/drivers/media/dvb/ttpci/ttpci-eeprom.c
+++ b/drivers/media/dvb/ttpci/ttpci-eeprom.c
@@ -90,7 +90,7 @@ static int ttpci_eeprom_read_encodedMAC(struct i2c_adapter *adapter, u8 * encode
u8 b0[] = { 0xcc };
struct i2c_msg msg[] = {
- {.addr = 0x50,.flags = 0,.buf = b0,.len = 1},
+ { .addr = 0x50, .flags = 0, .buf = b0, .len = 1 },
{ .addr = 0x50, .flags = I2C_M_RD, .buf = encodedMAC, .len = 20 }
};
@@ -144,4 +144,3 @@ MODULE_LICENSE("GPL");
MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, others");
MODULE_DESCRIPTION("Decode dvb_net MAC address from EEPROM of PCI DVB cards "
"made by Siemens, Technotrend, Hauppauge");
-
diff --git a/drivers/media/dvb/ttusb-budget/Kconfig b/drivers/media/dvb/ttusb-budget/Kconfig
index b4d3322b3b76f..4aa714ab4c28b 100644
--- a/drivers/media/dvb/ttusb-budget/Kconfig
+++ b/drivers/media/dvb/ttusb-budget/Kconfig
@@ -10,6 +10,6 @@ config DVB_TTUSB_BUDGET
produced by Hauppauge, shipped under the brand name 'Nova-USB'.
These devices don't have a MPEG decoder built in, so you need
- an external software decoder to watch TV.
+ 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 0485faa51b4d0..4c046ece883a8 100644
--- a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
+++ b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
@@ -33,6 +33,7 @@
#include <linux/dvb/dmx.h>
#include <linux/pci.h>
+
/*
TTUSB_HWSECTIONS:
the DSP supports filtering in hardware, however, since the "muxstream"
@@ -41,12 +42,12 @@
so the best way is maybe to keep TTUSB_HWSECTIONS undef'd and just
parse TS data. USB bandwith will be a problem when having large
datastreams, especially for dvb-net, but hey, that's not my problem.
-
+
TTUSB_DISEQC, TTUSB_TONE:
let the STC do the diseqc/tone stuff. this isn't supported at least with
my TTUSB, so let it undef'd unless you want to implement another
frontend. never tested.
-
+
DEBUG:
define it to > 3 for really hardcore debugging. you probably don't want
this unless the device doesn't load at all. > 2 for bandwidth statistics.
@@ -67,6 +68,7 @@ MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
#define TTUSB_MAXFILTER 16 /* ??? */
#endif
+#define TTUSB_REV_2_2 0x22
#define TTUSB_BUDGET_NAME "ttusb_stc_fw"
/**
@@ -78,9 +80,8 @@ struct ttusb {
struct dmxdev dmxdev;
struct dvb_net dvbnet;
- /* our semaphore, for channel allocation/deallocation */
- struct semaphore sem;
/* and one for USB access. */
+ struct semaphore semi2c;
struct semaphore semusb;
struct dvb_adapter *adapter;
@@ -118,21 +119,10 @@ struct ttusb {
int cc; /* MuxCounter - will increment on EVERY MUX PACKET */
/* (including stuffing. yes. really.) */
-
u8 last_result[32];
- struct ttusb_channel {
- struct ttusb *ttusb;
- struct dvb_demux_feed *dvbdmxfeed;
+ int revision;
- int active;
- int id;
- int pid;
- int type; /* 1 - TS, 2 - Filter */
-#ifdef TTUSB_HWSECTIONS
- int filterstate[TTUSB_MAXFILTER]; /* 0: not busy, 1: busy */
-#endif
- } channel[TTUSB_MAXCHANNEL];
#if 0
devfs_handle_t stc_devfs_handle;
#endif
@@ -162,7 +152,7 @@ static int ttusb_cmd(struct ttusb *ttusb,
return -EAGAIN;
err = usb_bulk_msg(ttusb->dev, ttusb->bulk_out_pipe,
- (u8 *) data, len, &actual_len, HZ);
+ (u8 *) data, len, &actual_len, 1000);
if (err != 0) {
dprintk("%s: usb_bulk_msg(send) failed, err == %i!\n",
__FUNCTION__, err);
@@ -177,7 +167,7 @@ static int ttusb_cmd(struct ttusb *ttusb,
}
err = usb_bulk_msg(ttusb->dev, ttusb->bulk_in_pipe,
- ttusb->last_result, 32, &actual_len, HZ);
+ ttusb->last_result, 32, &actual_len, 1000);
if (err != 0) {
printk("%s: failed, receive error %d\n", __FUNCTION__,
@@ -252,13 +242,13 @@ static int ttusb_i2c_msg(struct ttusb *ttusb,
return rcv_len;
}
-static int master_xfer(struct i2c_adapter* adapter, struct i2c_msg msg[], int num)
+static int master_xfer(struct i2c_adapter* adapter, struct i2c_msg *msg, int num)
{
struct ttusb *ttusb = i2c_get_adapdata(adapter);
int i = 0;
int inc;
- if (down_interruptible(&ttusb->sem) < 0)
+ if (down_interruptible(&ttusb->semi2c) < 0)
return -EAGAIN;
while (i < num) {
@@ -292,7 +282,7 @@ static int master_xfer(struct i2c_adapter* adapter, struct i2c_msg msg[], int nu
i += inc;
}
- up(&ttusb->sem);
+ up(&ttusb->semi2c);
return i;
}
@@ -445,13 +435,17 @@ static int ttusb_init_controller(struct ttusb *ttusb)
if (memcmp(get_version + 4, "V 0.0", 5) &&
memcmp(get_version + 4, "V 1.1", 5) &&
- memcmp(get_version + 4, "V 2.1", 5)) {
+ memcmp(get_version + 4, "V 2.1", 5) &&
+ memcmp(get_version + 4, "V 2.2", 5)) {
printk
("%s: unknown STC version %c%c%c%c%c, please report!\n",
__FUNCTION__, get_version[4], get_version[5],
get_version[6], get_version[7], get_version[8]);
}
+ ttusb->revision = ((get_version[6] - '0') << 4) |
+ (get_version[8] - '0');
+
err =
ttusb_cmd(ttusb, get_dsp_version, sizeof(get_dsp_version), 1);
if (err)
@@ -468,7 +462,7 @@ static int ttusb_init_controller(struct ttusb *ttusb)
#ifdef TTUSB_DISEQC
static int ttusb_send_diseqc(struct dvb_frontend* fe,
- const struct dvb_diseqc_master_cmd *cmd)
+ const struct dvb_diseqc_master_cmd *cmd)
{
struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv;
u8 b[12] = { 0xaa, ++ttusb->c, 0x18 };
@@ -491,6 +485,31 @@ static int ttusb_send_diseqc(struct dvb_frontend* fe,
}
#endif
+static int lnbp21_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
+{
+ struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv;
+ int ret;
+ u8 data[1];
+ struct i2c_msg msg = { .addr = 0x08, .flags = 0, .buf = data, .len = sizeof(data) };
+
+ switch(voltage) {
+ case SEC_VOLTAGE_OFF:
+ data[0] = 0x00;
+ break;
+ case SEC_VOLTAGE_13:
+ data[0] = 0x44;
+ break;
+ case SEC_VOLTAGE_18:
+ data[0] = 0x4c;
+ break;
+ default:
+ return -EINVAL;
+ };
+
+ ret = i2c_transfer(&ttusb->i2c_adap, &msg, 1);
+ return (ret != 1) ? -EIO : 0;
+}
+
static int ttusb_update_lnb(struct ttusb *ttusb)
{
u8 b[] = { 0xaa, ++ttusb->c, 0x16, 5, /*power: */ 1,
@@ -831,7 +850,7 @@ static void ttusb_stop_iso_xfer(struct ttusb *ttusb)
int i;
for (i = 0; i < ISO_BUF_COUNT; i++)
- usb_unlink_urb(ttusb->iso_urb[i]);
+ usb_kill_urb(ttusb->iso_urb[i]);
ttusb->iso_streaming = 0;
}
@@ -888,15 +907,13 @@ static int ttusb_start_iso_xfer(struct ttusb *ttusb)
}
#ifdef TTUSB_HWSECTIONS
-static void ttusb_handle_ts_data(struct ttusb_channel *channel, const u8 * data,
+static void ttusb_handle_ts_data(struct dvb_demux_feed *dvbdmxfeed, const u8 * data,
int len)
{
- struct dvb_demux_feed *dvbdmxfeed = channel->dvbdmxfeed;
-
dvbdmxfeed->cb.ts(data, len, 0, 0, &dvbdmxfeed->feed.ts, 0);
}
-static void ttusb_handle_sec_data(struct ttusb_channel *channel, const u8 * data,
+static void ttusb_handle_sec_data(struct dvb_demux_feed *dvbdmxfeed, const u8 * data,
int len)
{
// struct dvb_demux_feed *dvbdmxfeed = channel->dvbdmxfeed;
@@ -905,31 +922,10 @@ static void ttusb_handle_sec_data(struct ttusb_channel *channel, const u8 * data
}
#endif
-static struct ttusb_channel *ttusb_channel_allocate(struct ttusb *ttusb)
-{
- int i;
-
- if (down_interruptible(&ttusb->sem))
- return NULL;
-
- /* lock! */
- for (i = 0; i < TTUSB_MAXCHANNEL; ++i) {
- if (!ttusb->channel[i].active) {
- ttusb->channel[i].active = 1;
- up(&ttusb->sem);
- return ttusb->channel + i;
- }
- }
-
- up(&ttusb->sem);
-
- return NULL;
-}
-
static int ttusb_start_feed(struct dvb_demux_feed *dvbdmxfeed)
{
struct ttusb *ttusb = (struct ttusb *) dvbdmxfeed->demux;
- struct ttusb_channel *channel;
+ int feed_type = 1;
dprintk("ttusb_start_feed\n");
@@ -949,35 +945,22 @@ static int ttusb_start_feed(struct dvb_demux_feed *dvbdmxfeed)
case DMX_TS_PES_TELETEXT:
case DMX_TS_PES_PCR:
case DMX_TS_PES_OTHER:
- channel = ttusb_channel_allocate(ttusb);
break;
default:
return -EINVAL;
}
- } else {
- channel = ttusb_channel_allocate(ttusb);
}
- if (!channel)
- return -EBUSY;
-
- dvbdmxfeed->priv = channel;
- channel->dvbdmxfeed = dvbdmxfeed;
-
- channel->pid = dvbdmxfeed->pid;
-
#ifdef TTUSB_HWSECTIONS
+#error TODO: allocate filters
if (dvbdmxfeed->type == DMX_TYPE_TS) {
- channel->type = 1;
+ feed_type = 1;
} else if (dvbdmxfeed->type == DMX_TYPE_SEC) {
- channel->type = 2;
-#error TODO: allocate filters
+ feed_type = 2;
}
-#else
- channel->type = 1;
#endif
- ttusb_set_channel(ttusb, channel->id, channel->type, channel->pid);
+ ttusb_set_channel(ttusb, dvbdmxfeed->index, feed_type, dvbdmxfeed->pid);
if (0 == ttusb->running_feed_count++)
ttusb_start_iso_xfer(ttusb);
@@ -987,17 +970,13 @@ static int ttusb_start_feed(struct dvb_demux_feed *dvbdmxfeed)
static int ttusb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
{
- struct ttusb_channel *channel =
- (struct ttusb_channel *) dvbdmxfeed->priv;
struct ttusb *ttusb = (struct ttusb *) dvbdmxfeed->demux;
- ttusb_del_channel(channel->ttusb, channel->id);
+ ttusb_del_channel(ttusb, dvbdmxfeed->index);
if (--ttusb->running_feed_count == 0)
ttusb_stop_iso_xfer(ttusb);
- channel->active = 0;
-
return 0;
}
@@ -1201,10 +1180,51 @@ static struct tda1004x_config philips_tdm1316l_config = {
.request_firmware = philips_tdm1316l_request_firmware,
};
+static u8 alps_bsbe1_inittab[] = {
+ 0x01, 0x15,
+ 0x02, 0x30,
+ 0x03, 0x00,
+ 0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */
+ 0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */
+ 0x06, 0x40, /* DAC not used, set to high impendance mode */
+ 0x07, 0x00, /* DAC LSB */
+ 0x08, 0x40, /* DiSEqC off, LNB power on OP2/LOCK pin on */
+ 0x09, 0x00, /* FIFO */
+ 0x0c, 0x51, /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */
+ 0x0d, 0x82, /* DC offset compensation = ON, beta_agc1 = 2 */
+ 0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */
+ 0x10, 0x3f, // AGC2 0x3d
+ 0x11, 0x84,
+ 0x12, 0xb5, // Lock detect: -64 Carrier freq detect:on
+ 0x15, 0xc9, // lock detector threshold
+ 0x16, 0x00,
+ 0x17, 0x00,
+ 0x18, 0x00,
+ 0x19, 0x00,
+ 0x1a, 0x00,
+ 0x1f, 0x50,
+ 0x20, 0x00,
+ 0x21, 0x00,
+ 0x22, 0x00,
+ 0x23, 0x00,
+ 0x28, 0x00, // out imp: normal out type: parallel FEC mode:0
+ 0x29, 0x1e, // 1/2 threshold
+ 0x2a, 0x14, // 2/3 threshold
+ 0x2b, 0x0f, // 3/4 threshold
+ 0x2c, 0x09, // 5/6 threshold
+ 0x2d, 0x05, // 7/8 threshold
+ 0x2e, 0x01,
+ 0x31, 0x1f, // test all FECs
+ 0x32, 0x19, // viterbi and synchro search
+ 0x33, 0xfc, // rs control
+ 0x34, 0x93, // error control
+ 0x0f, 0x92,
+ 0xff, 0xff
+};
static u8 alps_bsru6_inittab[] = {
0x01, 0x15,
- 0x02, 0x00,
+ 0x02, 0x30,
0x03, 0x00,
0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */
0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */
@@ -1244,7 +1264,7 @@ static u8 alps_bsru6_inittab[] = {
0xff, 0xff
};
-static int alps_bsru6_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ratio)
+static int alps_stv0299_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ratio)
{
u8 aclk = 0;
u8 bclk = 0;
@@ -1278,7 +1298,7 @@ static int alps_bsru6_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ra
return 0;
}
-static int alps_bsru6_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int philips_tsa5059_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
{
struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv;
u8 buf[4];
@@ -1295,7 +1315,11 @@ static int alps_bsru6_pll_set(struct dvb_frontend *fe, struct dvb_frontend_param
buf[3] = 0xC4;
if (params->frequency > 1530000)
- buf[3] = 0xc0;
+ buf[3] = 0xC0;
+
+ /* BSBE1 wants XCE bit set */
+ if (ttusb->revision == TTUSB_REV_2_2)
+ buf[3] |= 0x20;
if (i2c_transfer(&ttusb->i2c_adap, &msg, 1) != 1)
return -EIO;
@@ -1303,8 +1327,7 @@ static int alps_bsru6_pll_set(struct dvb_frontend *fe, struct dvb_frontend_param
return 0;
}
-static struct stv0299_config alps_bsru6_config = {
-
+static struct stv0299_config alps_stv0299_config = {
.demod_address = 0x68,
.inittab = alps_bsru6_inittab,
.mclk = 88000000UL,
@@ -1314,8 +1337,8 @@ static struct stv0299_config alps_bsru6_config = {
.lock_output = STV0229_LOCKOUTPUT_1,
.volt13_op0_op1 = STV0299_VOLT13_OP1,
.min_delay_ms = 100,
- .set_symbol_rate = alps_bsru6_set_symbol_rate,
- .pll_set = alps_bsru6_pll_set,
+ .set_symbol_rate = alps_stv0299_set_symbol_rate,
+ .pll_set = philips_tsa5059_pll_set,
};
static int ttusb_novas_grundig_29504_491_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
@@ -1349,11 +1372,16 @@ static struct tda8083_config ttusb_novas_grundig_29504_491_config = {
static void frontend_init(struct ttusb* ttusb)
{
switch(le16_to_cpu(ttusb->dev->descriptor.idProduct)) {
- case 0x1003: // Hauppauge/TT Nova-USB-S budget (stv0299/ALPS BSRU6(tsa5059)
- // try the ALPS BSRU6 first
- ttusb->fe = stv0299_attach(&alps_bsru6_config, &ttusb->i2c_adap);
+ case 0x1003: // Hauppauge/TT Nova-USB-S budget (stv0299/ALPS BSRU6|BSBE1(tsa5059))
+ // try the stv0299 based first
+ ttusb->fe = stv0299_attach(&alps_stv0299_config, &ttusb->i2c_adap);
if (ttusb->fe != NULL) {
- ttusb->fe->ops->set_voltage = ttusb_set_voltage;
+ if(ttusb->revision == TTUSB_REV_2_2) { // ALPS BSBE1
+ alps_stv0299_config.inittab = alps_bsbe1_inittab;
+ ttusb->fe->ops->set_voltage = lnbp21_set_voltage;
+ } else { // ALPS BSRU6
+ ttusb->fe->ops->set_voltage = ttusb_set_voltage;
+ }
break;
}
@@ -1406,7 +1434,7 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i
{
struct usb_device *udev;
struct ttusb *ttusb;
- int result, channel;
+ int result;
dprintk("%s: TTUSB DVB connected\n", __FUNCTION__);
@@ -1419,15 +1447,10 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i
memset(ttusb, 0, sizeof(struct ttusb));
- for (channel = 0; channel < TTUSB_MAXCHANNEL; ++channel) {
- ttusb->channel[channel].id = channel;
- ttusb->channel[channel].ttusb = ttusb;
- }
-
ttusb->dev = udev;
ttusb->c = 0;
ttusb->mux_state = 0;
- sema_init(&ttusb->sem, 0);
+ sema_init(&ttusb->semi2c, 0);
sema_init(&ttusb->semusb, 1);
ttusb_setup_interfaces(ttusb);
@@ -1436,7 +1459,7 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i
if (ttusb_init_controller(ttusb))
printk("ttusb_init_controller: error\n");
- up(&ttusb->sem);
+ up(&ttusb->semi2c);
dvb_register_adapter(&ttusb->adapter, "Technotrend/Hauppauge Nova-USB", THIS_MODULE);
ttusb->adapter->priv = ttusb;
@@ -1448,9 +1471,9 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i
i2c_set_adapdata(&ttusb->i2c_adap, ttusb);
#ifdef I2C_ADAP_CLASS_TV_DIGITAL
- ttusb->i2c_adap.class = I2C_ADAP_CLASS_TV_DIGITAL;
+ ttusb->i2c_adap.class = I2C_ADAP_CLASS_TV_DIGITAL;
#else
- ttusb->i2c_adap.class = I2C_CLASS_TV_DIGITAL;
+ ttusb->i2c_adap.class = I2C_CLASS_TV_DIGITAL;
#endif
ttusb->i2c_adap.algo = &ttusb_dec_algo;
ttusb->i2c_adap.algo_data = NULL;
@@ -1555,10 +1578,10 @@ static struct usb_device_id ttusb_table[] = {
MODULE_DEVICE_TABLE(usb, ttusb_table);
static struct usb_driver ttusb_driver = {
- .name = "Technotrend/Hauppauge USB-Nova",
- .probe = ttusb_probe,
- .disconnect = ttusb_disconnect,
- .id_table = ttusb_table,
+ .name = "Technotrend/Hauppauge USB-Nova",
+ .probe = ttusb_probe,
+ .disconnect = ttusb_disconnect,
+ .id_table = ttusb_table,
};
static int __init ttusb_init(void)
diff --git a/drivers/media/dvb/ttusb-dec/Kconfig b/drivers/media/dvb/ttusb-dec/Kconfig
index 61fabb6681759..c334526af66f2 100644
--- a/drivers/media/dvb/ttusb-dec/Kconfig
+++ b/drivers/media/dvb/ttusb-dec/Kconfig
@@ -10,7 +10,7 @@ config DVB_TTUSB_DEC
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.
+ 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",
diff --git a/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/drivers/media/dvb/ttusb-dec/ttusb_dec.c
index f85069f8b2199..64e771bd89078 100644
--- a/drivers/media/dvb/ttusb-dec/ttusb_dec.c
+++ b/drivers/media/dvb/ttusb-dec/ttusb_dec.c
@@ -2,6 +2,7 @@
* TTUSB DEC Driver
*
* Copyright (C) 2003-2004 Alex Woods <linux-dvb@giblets.org>
+ * IR support by Peter Beutner <p.beutner@gmx.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -32,6 +33,7 @@
#include <linux/firmware.h>
#include <linux/crc32.h>
#include <linux/init.h>
+#include <linux/input.h>
#include "dmxdev.h"
#include "dvb_demux.h"
@@ -42,27 +44,32 @@
static int debug;
static int output_pva;
+static int enable_rc;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
module_param(output_pva, int, 0444);
MODULE_PARM_DESC(output_pva, "Output PVA from dvr device (default:off)");
+module_param(enable_rc, int, 0644);
+MODULE_PARM_DESC(enable_rc, "Turn on/off IR remote control(default: off)");
#define dprintk if (debug) printk
#define DRIVER_NAME "TechnoTrend/Hauppauge DEC USB"
#define COMMAND_PIPE 0x03
-#define RESULT_PIPE 0x84
-#define IN_PIPE 0x88
+#define RESULT_PIPE 0x04
+#define IN_PIPE 0x08
#define OUT_PIPE 0x07
+#define IRQ_PIPE 0x0A
#define COMMAND_PACKET_SIZE 0x3c
#define ARM_PACKET_SIZE 0x1000
+#define IRQ_PACKET_SIZE 0x8
#define ISO_BUF_COUNT 0x04
#define FRAMES_PER_ISO_BUF 0x04
-#define ISO_FRAME_SIZE 0x03FF
+#define ISO_FRAME_SIZE 0x0380
#define MAX_PVA_LENGTH 6144
@@ -101,15 +108,19 @@ struct ttusb_dec {
u16 pid[DMX_PES_OTHER];
/* USB bits */
- struct usb_device *udev;
- u8 trans_count;
- unsigned int command_pipe;
- unsigned int result_pipe;
+ struct usb_device *udev;
+ u8 trans_count;
+ unsigned int command_pipe;
+ unsigned int result_pipe;
unsigned int in_pipe;
unsigned int out_pipe;
+ unsigned int irq_pipe;
enum ttusb_dec_interface interface;
- struct semaphore usb_sem;
+ struct semaphore usb_sem;
+ void *irq_buffer;
+ struct urb *irq_urb;
+ dma_addr_t irq_dma_handle;
void *iso_buffer;
dma_addr_t iso_dma_handle;
struct urb *iso_urb[ISO_BUF_COUNT];
@@ -142,6 +153,8 @@ struct ttusb_dec {
struct list_head filter_info_list;
spinlock_t filter_info_list_lock;
+ struct input_dev rc_input_dev;
+
int active; /* Loaded successfully */
};
@@ -157,9 +170,83 @@ struct filter_info {
struct list_head filter_info_list;
};
+static u16 rc_keys[] = {
+ KEY_POWER,
+ KEY_MUTE,
+ KEY_1,
+ KEY_2,
+ KEY_3,
+ KEY_4,
+ KEY_5,
+ KEY_6,
+ KEY_7,
+ KEY_8,
+ KEY_9,
+ KEY_0,
+ KEY_CHANNELUP,
+ KEY_VOLUMEDOWN,
+ KEY_OK,
+ KEY_VOLUMEUP,
+ KEY_CHANNELDOWN,
+ KEY_PREVIOUS,
+ KEY_ESC,
+ KEY_RED,
+ KEY_GREEN,
+ KEY_YELLOW,
+ KEY_BLUE,
+ KEY_OPTION,
+ KEY_M,
+ KEY_RADIO
+};
+
static void ttusb_dec_set_model(struct ttusb_dec *dec,
enum ttusb_dec_model model);
+static void ttusb_dec_handle_irq( struct urb *urb, struct pt_regs *regs)
+{
+ struct ttusb_dec * dec = urb->context;
+ char *buffer = dec->irq_buffer;
+ int retval;
+
+ switch(urb->status) {
+ case 0: /*success*/
+ break;
+ case -ECONNRESET:
+ case -ENOENT:
+ case -ESHUTDOWN:
+ case -ETIMEDOUT:
+ /* this urb is dead, cleanup */
+ dprintk("%s:urb shutting down with status: %d\n",
+ __FUNCTION__, urb->status);
+ return;
+ default:
+ dprintk("%s:nonzero status received: %d\n",
+ __FUNCTION__,urb->status);
+ goto exit;
+ }
+
+ if( (buffer[0] == 0x1) && (buffer[2] == 0x15) ) {
+ /* IR - Event */
+ /* this is an fact a bit too simple implementation;
+ * the box also reports a keyrepeat signal
+ * (with buffer[3] == 0x40) in an intervall of ~100ms.
+ * But to handle this correctly we had to imlemenent some
+ * kind of timer which signals a 'key up' event if no
+ * keyrepeat signal is recieved for lets say 200ms.
+ * this should/could be added later ...
+ * for now lets report each signal as a key down and up*/
+ dprintk("%s:rc signal:%d\n", __FUNCTION__, buffer[4]);
+ input_report_key(&dec->rc_input_dev,rc_keys[buffer[4]-1],1);
+ input_report_key(&dec->rc_input_dev,rc_keys[buffer[4]-1],0);
+ input_sync(&dec->rc_input_dev);
+ }
+
+exit: retval = usb_submit_urb(urb, GFP_ATOMIC);
+ if(retval)
+ printk("%s - usb_commit_urb failed with result: %d\n",
+ __FUNCTION__, retval);
+}
+
static u16 crc16(u16 crc, const u8 *buf, size_t len)
{
u16 tmp;
@@ -181,7 +268,7 @@ static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command,
u8 *b;
dprintk("%s\n", __FUNCTION__);
-
+
b = kmalloc(COMMAND_PACKET_SIZE + 4, GFP_KERNEL);
if (!b)
return -ENOMEM;
@@ -208,7 +295,7 @@ static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command,
}
result = usb_bulk_msg(dec->udev, dec->command_pipe, b,
- COMMAND_PACKET_SIZE + 4, &actual_len, HZ);
+ COMMAND_PACKET_SIZE + 4, &actual_len, 1000);
if (result) {
printk("%s: command bulk message failed: error %d\n",
@@ -219,7 +306,7 @@ static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command,
}
result = usb_bulk_msg(dec->udev, dec->result_pipe, b,
- COMMAND_PACKET_SIZE + 4, &actual_len, HZ);
+ COMMAND_PACKET_SIZE + 4, &actual_len, 1000);
if (result) {
printk("%s: result bulk message failed: error %d\n",
@@ -320,9 +407,9 @@ static void ttusb_dec_set_pids(struct ttusb_dec *dec)
ttusb_dec_send_command(dec, 0x50, sizeof(b), b, NULL, NULL);
- dvb_filter_pes2ts_init(&dec->a_pes2ts, dec->pid[DMX_PES_AUDIO],
+ dvb_filter_pes2ts_init(&dec->a_pes2ts, dec->pid[DMX_PES_AUDIO],
ttusb_dec_audio_pes2ts_cb, dec);
- dvb_filter_pes2ts_init(&dec->v_pes2ts, dec->pid[DMX_PES_VIDEO],
+ dvb_filter_pes2ts_init(&dec->v_pes2ts, dec->pid[DMX_PES_VIDEO],
ttusb_dec_video_pes2ts_cb, dec);
dec->v_pes_length = 0;
dec->v_pes_postbytes = 0;
@@ -345,7 +432,7 @@ static void ttusb_dec_process_pva(struct ttusb_dec *dec, u8 *pva, int length)
case 0x01: { /* VideoStream */
int prebytes = pva[5] & 0x03;
int postbytes = (pva[5] & 0x0c) >> 2;
- u16 v_pes_payload_length;
+ u16 v_pes_payload_length;
if (output_pva) {
dec->video_filter->feed->cb.ts(pva, length, NULL, 0,
@@ -353,23 +440,23 @@ static void ttusb_dec_process_pva(struct ttusb_dec *dec, u8 *pva, int length)
return;
}
- if (dec->v_pes_postbytes > 0 &&
- dec->v_pes_postbytes == prebytes) {
- memcpy(&dec->v_pes[dec->v_pes_length],
+ if (dec->v_pes_postbytes > 0 &&
+ dec->v_pes_postbytes == prebytes) {
+ memcpy(&dec->v_pes[dec->v_pes_length],
&pva[12], prebytes);
- dvb_filter_pes2ts(&dec->v_pes2ts, dec->v_pes,
+ dvb_filter_pes2ts(&dec->v_pes2ts, dec->v_pes,
dec->v_pes_length + prebytes, 1);
- }
+ }
if (pva[5] & 0x10) {
- dec->v_pes[7] = 0x80;
- dec->v_pes[8] = 0x05;
+ dec->v_pes[7] = 0x80;
+ dec->v_pes[8] = 0x05;
dec->v_pes[9] = 0x21 | ((pva[8] & 0xc0) >> 5);
dec->v_pes[10] = ((pva[8] & 0x3f) << 2) |
((pva[9] & 0xc0) >> 6);
- dec->v_pes[11] = 0x01 |
+ dec->v_pes[11] = 0x01 |
((pva[9] & 0x3f) << 2) |
((pva[10] & 0x80) >> 6);
dec->v_pes[12] = ((pva[10] & 0x7f) << 1) |
@@ -379,33 +466,33 @@ static void ttusb_dec_process_pva(struct ttusb_dec *dec, u8 *pva, int length)
memcpy(&dec->v_pes[14], &pva[12 + prebytes],
length - 12 - prebytes);
dec->v_pes_length = 14 + length - 12 - prebytes;
- } else {
- dec->v_pes[7] = 0x00;
- dec->v_pes[8] = 0x00;
+ } else {
+ dec->v_pes[7] = 0x00;
+ dec->v_pes[8] = 0x00;
memcpy(&dec->v_pes[9], &pva[8], length - 8);
dec->v_pes_length = 9 + length - 8;
- }
+ }
- dec->v_pes_postbytes = postbytes;
+ dec->v_pes_postbytes = postbytes;
- if (dec->v_pes[9 + dec->v_pes[8]] == 0x00 &&
- dec->v_pes[10 + dec->v_pes[8]] == 0x00 &&
- dec->v_pes[11 + dec->v_pes[8]] == 0x01)
- dec->v_pes[6] = 0x84;
- else
- dec->v_pes[6] = 0x80;
+ if (dec->v_pes[9 + dec->v_pes[8]] == 0x00 &&
+ dec->v_pes[10 + dec->v_pes[8]] == 0x00 &&
+ dec->v_pes[11 + dec->v_pes[8]] == 0x01)
+ dec->v_pes[6] = 0x84;
+ else
+ dec->v_pes[6] = 0x80;
- v_pes_payload_length = htons(dec->v_pes_length - 6 +
- postbytes);
- memcpy(&dec->v_pes[4], &v_pes_payload_length, 2);
+ v_pes_payload_length = htons(dec->v_pes_length - 6 +
+ postbytes);
+ memcpy(&dec->v_pes[4], &v_pes_payload_length, 2);
- if (postbytes == 0)
- dvb_filter_pes2ts(&dec->v_pes2ts, dec->v_pes,
- dec->v_pes_length, 1);
+ if (postbytes == 0)
+ dvb_filter_pes2ts(&dec->v_pes2ts, dec->v_pes,
+ dec->v_pes_length, 1);
- break;
- }
+ break;
+ }
case 0x02: /* MainAudioStream */
if (output_pva) {
@@ -487,7 +574,7 @@ static void ttusb_dec_process_packet(struct ttusb_dec *dec)
case TTUSB_DEC_PACKET_PVA:
if (dec->pva_stream_count)
ttusb_dec_process_pva(dec, dec->packet,
- dec->packet_payload_length);
+ dec->packet_payload_length);
break;
case TTUSB_DEC_PACKET_SECTION:
@@ -513,7 +600,7 @@ static void swap_bytes(u8 *b, int length)
}
}
-static void ttusb_dec_process_urb_frame(struct ttusb_dec * dec, u8 * b,
+static void ttusb_dec_process_urb_frame(struct ttusb_dec *dec, u8 *b,
int length)
{
swap_bytes(b, length);
@@ -562,7 +649,7 @@ static void ttusb_dec_process_urb_frame(struct ttusb_dec * dec, u8 * b,
TTUSB_DEC_PACKET_EMPTY;
dec->packet_payload_length = 2;
dec->packet_state = 7;
- } else {
+ } else {
printk("%s: unknown packet type: "
"%02x%02x\n", __FUNCTION__,
dec->packet[0], dec->packet[1]);
@@ -598,23 +685,23 @@ static void ttusb_dec_process_urb_frame(struct ttusb_dec * dec, u8 * b,
int remainder = dec->packet_payload_length -
dec->packet_length;
- if (length >= remainder) {
+ if (length >= remainder) {
memcpy(dec->packet + dec->packet_length,
- b, remainder);
+ b, remainder);
dec->packet_length += remainder;
- b += remainder;
- length -= remainder;
+ b += remainder;
+ length -= remainder;
dec->packet_state++;
- } else {
+ } else {
memcpy(&dec->packet[dec->packet_length],
- b, length);
+ b, length);
dec->packet_length += length;
- length = 0;
- }
-
- break;
+ length = 0;
}
+ break;
+ }
+
case 7: {
int tail = 4;
@@ -676,7 +763,6 @@ static void ttusb_dec_process_urb(struct urb *urb, struct pt_regs *ptregs)
for (i = 0; i < FRAMES_PER_ISO_BUF; i++) {
struct usb_iso_packet_descriptor *d;
-
u8 *b;
int length;
struct urb_frame *frame;
@@ -782,7 +868,7 @@ static int ttusb_dec_set_interface(struct ttusb_dec *dec,
b, NULL, NULL);
if (result)
return result;
- result = usb_set_interface(dec->udev, 0, 7);
+ result = usb_set_interface(dec->udev, 0, 8);
break;
case TTUSB_DEC_INTERFACE_OUT:
result = usb_set_interface(dec->udev, 0, 1);
@@ -1067,7 +1153,7 @@ static int ttusb_dec_alloc_iso_urbs(struct ttusb_dec *dec)
ISO_FRAME_SIZE *
(FRAMES_PER_ISO_BUF *
ISO_BUF_COUNT),
- &dec->iso_dma_handle);
+ &dec->iso_dma_handle);
memset(dec->iso_buffer, 0,
ISO_FRAME_SIZE * (FRAMES_PER_ISO_BUF * ISO_BUF_COUNT));
@@ -1096,6 +1182,31 @@ static void ttusb_dec_init_tasklet(struct ttusb_dec *dec)
(unsigned long)dec);
}
+static void ttusb_init_rc( struct ttusb_dec *dec)
+{
+ u8 b[] = { 0x00, 0x01 };
+ int i;
+
+ init_input_dev(&dec->rc_input_dev);
+
+ dec->rc_input_dev.name = "ttusb_dec remote control";
+ dec->rc_input_dev.evbit[0] = BIT(EV_KEY);
+ dec->rc_input_dev.keycodesize = sizeof(u16);
+ dec->rc_input_dev.keycodemax = 0x1a;
+ dec->rc_input_dev.keycode = rc_keys;
+
+ for (i = 0; i < sizeof(rc_keys)/sizeof(rc_keys[0]); i++)
+ set_bit(rc_keys[i], dec->rc_input_dev.keybit);
+
+ input_register_device(&dec->rc_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);
+}
+
static void ttusb_dec_init_v_pes(struct ttusb_dec *dec)
{
dprintk("%s\n", __FUNCTION__);
@@ -1106,7 +1217,7 @@ static void ttusb_dec_init_v_pes(struct ttusb_dec *dec)
dec->v_pes[3] = 0xe0;
}
-static void ttusb_dec_init_usb(struct ttusb_dec *dec)
+static int ttusb_dec_init_usb(struct ttusb_dec *dec)
{
dprintk("%s\n", __FUNCTION__);
@@ -1117,8 +1228,26 @@ static void ttusb_dec_init_usb(struct ttusb_dec *dec)
dec->result_pipe = usb_rcvbulkpipe(dec->udev, RESULT_PIPE);
dec->in_pipe = usb_rcvisocpipe(dec->udev, IN_PIPE);
dec->out_pipe = usb_sndisocpipe(dec->udev, OUT_PIPE);
+ dec->irq_pipe = usb_rcvintpipe(dec->udev, IRQ_PIPE);
- ttusb_dec_alloc_iso_urbs(dec);
+ if(enable_rc) {
+ dec->irq_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if(!dec->irq_urb) {
+ return -ENOMEM;
+ }
+ dec->irq_buffer = usb_buffer_alloc(dec->udev,IRQ_PACKET_SIZE,
+ SLAB_ATOMIC, &dec->irq_dma_handle);
+ if(!dec->irq_buffer) {
+ return -ENOMEM;
+ }
+ usb_fill_int_urb(dec->irq_urb, dec->udev,dec->irq_pipe,
+ dec->irq_buffer, IRQ_PACKET_SIZE,
+ ttusb_dec_handle_irq, dec, 1);
+ dec->irq_urb->transfer_dma = dec->irq_dma_handle;
+ dec->irq_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+ }
+
+ return ttusb_dec_alloc_iso_urbs(dec);
}
static int ttusb_dec_boot_dsp(struct ttusb_dec *dec)
@@ -1205,12 +1334,12 @@ static int ttusb_dec_boot_dsp(struct ttusb_dec *dec)
if (j >= ARM_PACKET_SIZE) {
result = usb_bulk_msg(dec->udev, dec->command_pipe, b,
ARM_PACKET_SIZE, &actual_len,
- HZ / 10);
+ 100);
j = 0;
} else if (size < COMMAND_PACKET_SIZE) {
result = usb_bulk_msg(dec->udev, dec->command_pipe, b,
j - COMMAND_PACKET_SIZE + size,
- &actual_len, HZ / 10);
+ &actual_len, 100);
}
}
@@ -1244,7 +1373,7 @@ static int ttusb_dec_init_stb(struct ttusb_dec *dec)
result = ttusb_dec_boot_dsp(dec);
if (result)
return result;
- else
+ else
return 1;
} else {
/* We can't trust the USB IDs that some firmwares
@@ -1273,7 +1402,7 @@ static int ttusb_dec_init_stb(struct ttusb_dec *dec)
dec->can_playback = 1;
return 0;
- }
+ }
}
else
return result;
@@ -1370,6 +1499,26 @@ static void ttusb_dec_exit_dvb(struct ttusb_dec *dec)
dvb_unregister_adapter(dec->adapter);
}
+static void ttusb_dec_exit_rc(struct ttusb_dec *dec)
+{
+
+ dprintk("%s\n", __FUNCTION__);
+ /* we have to check whether the irq URB is already submitted.
+ * As the irq is submitted after the interface is changed,
+ * this is the best method i figured out.
+ * Any others?*/
+ if(dec->interface == TTUSB_DEC_INTERFACE_IN)
+ usb_kill_urb(dec->irq_urb);
+
+ usb_free_urb(dec->irq_urb);
+
+ usb_buffer_free(dec->udev,IRQ_PACKET_SIZE,
+ dec->irq_buffer, dec->irq_dma_handle);
+
+ input_unregister_device(&dec->rc_input_dev);
+}
+
+
static void ttusb_dec_exit_usb(struct ttusb_dec *dec)
{
int i;
@@ -1448,22 +1597,23 @@ static int ttusb_dec_probe(struct usb_interface *intf,
memset(dec, 0, sizeof(struct ttusb_dec));
switch (le16_to_cpu(id->idProduct)) {
- case 0x1006:
+ case 0x1006:
ttusb_dec_set_model(dec, TTUSB_DEC3000S);
- break;
+ break;
- case 0x1008:
+ case 0x1008:
ttusb_dec_set_model(dec, TTUSB_DEC2000T);
break;
case 0x1009:
ttusb_dec_set_model(dec, TTUSB_DEC2540T);
- break;
+ break;
}
dec->udev = udev;
- ttusb_dec_init_usb(dec);
+ if (ttusb_dec_init_usb(dec))
+ return 0;
if (ttusb_dec_init_stb(dec)) {
ttusb_dec_exit_usb(dec);
return 0;
@@ -1503,6 +1653,9 @@ static int ttusb_dec_probe(struct usb_interface *intf,
ttusb_dec_set_interface(dec, TTUSB_DEC_INTERFACE_IN);
+ if(enable_rc)
+ ttusb_init_rc(dec);
+
return 0;
}
@@ -1515,10 +1668,12 @@ static void ttusb_dec_disconnect(struct usb_interface *intf)
dprintk("%s\n", __FUNCTION__);
if (dec->active) {
- ttusb_dec_exit_tasklet(dec);
+ ttusb_dec_exit_tasklet(dec);
ttusb_dec_exit_filters(dec);
- ttusb_dec_exit_usb(dec);
- ttusb_dec_exit_dvb(dec);
+ if(enable_rc)
+ ttusb_dec_exit_rc(dec);
+ ttusb_dec_exit_usb(dec);
+ ttusb_dec_exit_dvb(dec);
}
kfree(dec);
@@ -1557,9 +1712,9 @@ static struct usb_device_id ttusb_dec_table[] = {
static struct usb_driver ttusb_dec_driver = {
.name = "ttusb-dec",
- .probe = ttusb_dec_probe,
- .disconnect = ttusb_dec_disconnect,
- .id_table = ttusb_dec_table,
+ .probe = ttusb_dec_probe,
+ .disconnect = ttusb_dec_disconnect,
+ .id_table = ttusb_dec_table,
};
static int __init ttusb_dec_init(void)
@@ -1587,4 +1742,3 @@ MODULE_AUTHOR("Alex Woods <linux-dvb@giblets.org>");
MODULE_DESCRIPTION(DRIVER_NAME);
MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE(usb, ttusb_dec_table);
-
diff --git a/drivers/media/dvb/ttusb-dec/ttusbdecfe.c b/drivers/media/dvb/ttusb-dec/ttusbdecfe.c
index ff0e5212a1f44..1699cc9f6bb0d 100644
--- a/drivers/media/dvb/ttusb-dec/ttusbdecfe.c
+++ b/drivers/media/dvb/ttusb-dec/ttusbdecfe.c
@@ -169,7 +169,7 @@ struct dvb_frontend* ttusbdecfe_dvbt_attach(const struct ttusbdecfe_config* conf
return &state->frontend;
error:
- if (state) kfree(state);
+ kfree(state);
return NULL;
}
@@ -195,7 +195,7 @@ struct dvb_frontend* ttusbdecfe_dvbs_attach(const struct ttusbdecfe_config* conf
return &state->frontend;
error:
- if (state) kfree(state);
+ kfree(state);
return NULL;
}
diff --git a/drivers/media/radio/miropcm20-radio.c b/drivers/media/radio/miropcm20-radio.c
index eb8cc6fd1b3f8..c2ebe8754a956 100644
--- a/drivers/media/radio/miropcm20-radio.c
+++ b/drivers/media/radio/miropcm20-radio.c
@@ -75,9 +75,7 @@ static int pcm20_getflags(struct pcm20_device *dev, __u32 *flags, __u16 *signal)
if ((i=aci_rw_cmd(ACI_READ_TUNERSTATION, -1, -1))<0)
return i;
-#ifdef DEBUG
- printk("check_sig: 0x%x\n", i);
-#endif
+ pr_debug("check_sig: 0x%x\n", i);
if (i & 0x80) {
/* no signal from tuner */
*flags=0;
@@ -107,9 +105,7 @@ static int pcm20_getflags(struct pcm20_device *dev, __u32 *flags, __u16 *signal)
if ((i=aci_rds_cmd(RDS_RXVALUE, &buf, 1))<0)
return i;
-#ifdef DEBUG
- printk("rds-signal: %d\n", buf);
-#endif
+ pr_debug("rds-signal: %d\n", buf);
if (buf > 15) {
printk("miropcm20-radio: RX strengths unexpected high...\n");
buf=15;
@@ -172,9 +168,7 @@ static int pcm20_do_ioctl(struct inode *inode, struct file *file,
unsigned long *freq = arg;
pcm20->freq = *freq;
i=pcm20_setfreq(pcm20, pcm20->freq);
-#ifdef DEBUG
- printk("First view (setfreq): 0x%x\n", i);
-#endif
+ pr_debug("First view (setfreq): 0x%x\n", i);
return i;
}
case VIDIOCGAUDIO:
diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c
index ec3ff0e1cf621..3a464a09221f9 100644
--- a/drivers/media/radio/radio-sf16fmi.c
+++ b/drivers/media/radio/radio-sf16fmi.c
@@ -326,13 +326,3 @@ static void __exit fmi_cleanup_module(void)
module_init(fmi_init);
module_exit(fmi_cleanup_module);
-
-#ifndef MODULE
-static int __init fmi_setup_io(char *str)
-{
- get_option(&str, &io);
- return 1;
-}
-
-__setup("sf16fm=", fmi_setup_io);
-#endif
diff --git a/drivers/media/radio/radio-zoltrix.c b/drivers/media/radio/radio-zoltrix.c
index 31ee3f02a00a7..342f92df4aba7 100644
--- a/drivers/media/radio/radio-zoltrix.c
+++ b/drivers/media/radio/radio-zoltrix.c
@@ -29,7 +29,7 @@
#include <linux/module.h> /* Modules */
#include <linux/init.h> /* Initdata */
#include <linux/ioport.h> /* check_region, request_region */
-#include <linux/delay.h> /* udelay */
+#include <linux/delay.h> /* udelay, msleep */
#include <asm/io.h> /* outb, outb_p */
#include <asm/uaccess.h> /* copy to/from user */
#include <linux/videodev.h> /* kernel radio structs */
@@ -51,15 +51,6 @@ struct zol_device {
struct semaphore lock;
};
-
-/* local things */
-
-static void sleep_delay(void)
-{
- /* Sleep nicely for +/- 10 mS */
- schedule();
-}
-
static int zol_setvol(struct zol_device *dev, int vol)
{
dev->curvol = vol;
@@ -76,7 +67,7 @@ static int zol_setvol(struct zol_device *dev, int vol)
}
outb(dev->curvol-1, io);
- sleep_delay();
+ msleep(10);
inb(io + 2);
up(&dev->lock);
return 0;
@@ -176,11 +167,10 @@ static int zol_getsigstr(struct zol_device *dev)
down(&dev->lock);
outb(0x00, io); /* This stuff I found to do nothing */
outb(dev->curvol, io);
- sleep_delay();
- sleep_delay();
+ msleep(20);
a = inb(io);
- sleep_delay();
+ msleep(10);
b = inb(io);
up(&dev->lock);
@@ -202,11 +192,10 @@ static int zol_is_stereo (struct zol_device *dev)
outb(0x00, io);
outb(dev->curvol, io);
- sleep_delay();
- sleep_delay();
+ msleep(20);
x1 = inb(io);
- sleep_delay();
+ msleep(10);
x2 = inb(io);
up(&dev->lock);
@@ -368,8 +357,7 @@ static int __init zoltrix_init(void)
outb(0, io);
outb(0, io);
- sleep_delay();
- sleep_delay();
+ msleep(20);
inb(io + 3);
zoltrix_unit.curvol = 0;
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index ee274bdaab8e7..c1b3542dad881 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -249,7 +249,9 @@ config VIDEO_SAA7134
config VIDEO_SAA7134_DVB
tristate "DVB Support for saa7134 based TV cards"
- depends on VIDEO_SAA7134 && DVB_CORE && BROKEN
+ depends on VIDEO_SAA7134 && DVB_CORE
+ select VIDEO_BUF_DVB
+ select DVB_MT352
---help---
This adds support for DVB cards based on the
Philips saa7134 chip.
@@ -305,11 +307,14 @@ config VIDEO_HEXIUM_GEMINI
config VIDEO_CX88
tristate "Conexant 2388x (bt878 successor) support"
- depends on VIDEO_DEV && PCI && EXPERIMENTAL
+ depends on VIDEO_DEV && PCI && I2C && EXPERIMENTAL
select I2C_ALGOBIT
+ select FW_LOADER
select VIDEO_BTCX
select VIDEO_BUF
select VIDEO_TUNER
+ select VIDEO_TVEEPROM
+ select VIDEO_IR
---help---
This is a video4linux driver for Conexant 2388x based
TV cards.
@@ -319,10 +324,12 @@ config VIDEO_CX88
config VIDEO_CX88_DVB
tristate "DVB Support for cx2388x based TV cards"
- depends on VIDEO_CX88 && DVB_CORE && BROKEN
+ depends on VIDEO_CX88 && DVB_CORE
select VIDEO_BUF_DVB
+ select DVB_MT352
+ select DVB_OR51132
---help---
- This adds support for DVB cards based on the
+ This adds support for DVB/ATSC cards based on the
Connexant 2388x chip.
config VIDEO_OVCAMCHIP
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
index 8d0a3fba9653e..2dc906fdfa550 100644
--- a/drivers/media/video/Makefile
+++ b/drivers/media/video/Makefile
@@ -7,6 +7,7 @@ bttv-objs := bttv-driver.o bttv-cards.o bttv-if.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
obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-common.o v4l1-compat.o
diff --git a/drivers/media/video/adv7170.c b/drivers/media/video/adv7170.c
index 4e1f5554846c3..80254caa444c9 100644
--- a/drivers/media/video/adv7170.c
+++ b/drivers/media/video/adv7170.c
@@ -130,7 +130,7 @@ adv7170_write_block (struct i2c_client *client,
u8 block_data[32];
msg.addr = client->addr;
- msg.flags = client->flags;
+ msg.flags = 0;
while (len >= 2) {
msg.buf = (char *) block_data;
msg.len = 0;
@@ -402,7 +402,6 @@ static struct i2c_client_address_data addr_data = {
.force = force
};
-static int adv7170_i2c_id = 0;
static struct i2c_driver i2c_driver_adv7170;
static int
@@ -432,7 +431,6 @@ adv7170_detect_client (struct i2c_adapter *adapter,
client->adapter = adapter;
client->driver = &i2c_driver_adv7170;
client->flags = I2C_CLIENT_ALLOW_USE;
- client->id = adv7170_i2c_id++;
if ((client->addr == I2C_ADV7170 >> 1) ||
(client->addr == (I2C_ADV7170 >> 1) + 1)) {
dname = adv7170_name;
@@ -444,8 +442,7 @@ adv7170_detect_client (struct i2c_adapter *adapter,
kfree(client);
return 0;
}
- snprintf(I2C_NAME(client), sizeof(I2C_NAME(client)) - 1,
- "%s[%d]", dname, client->id);
+ strlcpy(I2C_NAME(client), dname, sizeof(I2C_NAME(client)));
encoder = kmalloc(sizeof(struct adv7170), GFP_KERNEL);
if (encoder == NULL) {
diff --git a/drivers/media/video/adv7175.c b/drivers/media/video/adv7175.c
index 1e24c0b96e823..95d0974b0ab53 100644
--- a/drivers/media/video/adv7175.c
+++ b/drivers/media/video/adv7175.c
@@ -126,7 +126,7 @@ adv7175_write_block (struct i2c_client *client,
u8 block_data[32];
msg.addr = client->addr;
- msg.flags = client->flags;
+ msg.flags = 0;
while (len >= 2) {
msg.buf = (char *) block_data;
msg.len = 0;
@@ -452,7 +452,6 @@ static struct i2c_client_address_data addr_data = {
.force = force
};
-static int adv7175_i2c_id = 0;
static struct i2c_driver i2c_driver_adv7175;
static int
@@ -482,7 +481,6 @@ adv7175_detect_client (struct i2c_adapter *adapter,
client->adapter = adapter;
client->driver = &i2c_driver_adv7175;
client->flags = I2C_CLIENT_ALLOW_USE;
- client->id = adv7175_i2c_id++;
if ((client->addr == I2C_ADV7175 >> 1) ||
(client->addr == (I2C_ADV7175 >> 1) + 1)) {
dname = adv7175_name;
@@ -494,8 +492,7 @@ adv7175_detect_client (struct i2c_adapter *adapter,
kfree(client);
return 0;
}
- snprintf(I2C_NAME(client), sizeof(I2C_NAME(client)) - 1,
- "%s[%d]", dname, client->id);
+ strlcpy(I2C_NAME(client), dname, sizeof(I2C_NAME(client)));
encoder = kmalloc(sizeof(struct adv7175), GFP_KERNEL);
if (encoder == NULL) {
diff --git a/drivers/media/video/bt819.c b/drivers/media/video/bt819.c
index 83857c1dc9514..cf0db2554a80d 100644
--- a/drivers/media/video/bt819.c
+++ b/drivers/media/video/bt819.c
@@ -146,7 +146,7 @@ bt819_write_block (struct i2c_client *client,
u8 block_data[32];
msg.addr = client->addr;
- msg.flags = client->flags;
+ msg.flags = 0;
while (len >= 2) {
msg.buf = (char *) block_data;
msg.len = 0;
@@ -236,7 +236,8 @@ bt819_init (struct i2c_client *client)
init[0x07 * 2 - 1] = timing->hactive & 0xff;
init[0x08 * 2 - 1] = timing->hscale >> 8;
init[0x09 * 2 - 1] = timing->hscale & 0xff;
- init[0x19*2-1] = decoder->norm == 0 ? 115 : 93; /* Chroma burst delay */
+ /* 0x15 in array is address 0x19 */
+ init[0x15 * 2 - 1] = (decoder->norm == 0) ? 115 : 93; /* Chroma burst delay */
/* reset */
bt819_write(client, 0x1f, 0x00);
mdelay(1);
@@ -517,7 +518,6 @@ static struct i2c_client_address_data addr_data = {
.force = force
};
-static int bt819_i2c_id = 0;
static struct i2c_driver i2c_driver_bt819;
static int
@@ -546,7 +546,6 @@ bt819_detect_client (struct i2c_adapter *adapter,
client->adapter = adapter;
client->driver = &i2c_driver_bt819;
client->flags = I2C_CLIENT_ALLOW_USE;
- client->id = bt819_i2c_id++;
decoder = kmalloc(sizeof(struct bt819), GFP_KERNEL);
if (decoder == NULL) {
@@ -568,16 +567,13 @@ bt819_detect_client (struct i2c_adapter *adapter,
id = bt819_read(client, 0x17);
switch (id & 0xf0) {
case 0x70:
- snprintf(I2C_NAME(client), sizeof(I2C_NAME(client)) - 1,
- "bt819a[%d]", client->id);
+ strlcpy(I2C_NAME(client), "bt819a", sizeof(I2C_NAME(client)));
break;
case 0x60:
- snprintf(I2C_NAME(client), sizeof(I2C_NAME(client)) - 1,
- "bt817a[%d]", client->id);
+ strlcpy(I2C_NAME(client), "bt817a", sizeof(I2C_NAME(client)));
break;
case 0x20:
- snprintf(I2C_NAME(client), sizeof(I2C_NAME(client)) - 1,
- "bt815a[%d]", client->id);
+ strlcpy(I2C_NAME(client), "bt815a", sizeof(I2C_NAME(client)));
break;
default:
dprintk(1,
diff --git a/drivers/media/video/bt856.c b/drivers/media/video/bt856.c
index d7e45f85a92c8..72c7eb0f8c24f 100644
--- a/drivers/media/video/bt856.c
+++ b/drivers/media/video/bt856.c
@@ -306,7 +306,6 @@ static struct i2c_client_address_data addr_data = {
.force = force
};
-static int bt856_i2c_id = 0;
static struct i2c_driver i2c_driver_bt856;
static int
@@ -335,9 +334,7 @@ bt856_detect_client (struct i2c_adapter *adapter,
client->adapter = adapter;
client->driver = &i2c_driver_bt856;
client->flags = I2C_CLIENT_ALLOW_USE;
- client->id = bt856_i2c_id++;
- snprintf(I2C_NAME(client), sizeof(I2C_NAME(client)) - 1,
- "bt856[%d]", client->id);
+ strlcpy(I2C_NAME(client), "bt856", sizeof(I2C_NAME(client)));
encoder = kmalloc(sizeof(struct bt856), GFP_KERNEL);
if (encoder == NULL) {
diff --git a/drivers/media/video/btcx-risc.c b/drivers/media/video/btcx-risc.c
index 2a840d88fc8eb..7f2d515d28737 100644
--- a/drivers/media/video/btcx-risc.c
+++ b/drivers/media/video/btcx-risc.c
@@ -1,5 +1,5 @@
/*
- $Id: btcx-risc.c,v 1.5 2004/12/10 12:33:39 kraxel Exp $
+ $Id: btcx-risc.c,v 1.6 2005/02/21 13:57:59 kraxel Exp $
btcx-risc.c
@@ -52,12 +52,13 @@ void btcx_riscmem_free(struct pci_dev *pci,
{
if (NULL == risc->cpu)
return;
- pci_free_consistent(pci, risc->size, risc->cpu, risc->dma);
- memset(risc,0,sizeof(*risc));
if (debug) {
memcnt--;
- printk("btcx: riscmem free [%d]\n",memcnt);
+ printk("btcx: riscmem free [%d] dma=%lx\n",
+ memcnt, (unsigned long)risc->dma);
}
+ pci_free_consistent(pci, risc->size, risc->cpu, risc->dma);
+ memset(risc,0,sizeof(*risc));
}
int btcx_riscmem_alloc(struct pci_dev *pci,
@@ -78,7 +79,8 @@ int btcx_riscmem_alloc(struct pci_dev *pci,
risc->size = size;
if (debug) {
memcnt++;
- printk("btcx: riscmem alloc size=%d [%d]\n",size,memcnt);
+ printk("btcx: riscmem alloc [%d] dma=%lx cpu=%p size=%d\n",
+ memcnt, (unsigned long)dma, cpu, size);
}
}
memset(risc->cpu,0,risc->size);
diff --git a/drivers/media/video/bttv-cards.c b/drivers/media/video/bttv-cards.c
index 4ee9026fc36b8..abce874e71cc6 100644
--- a/drivers/media/video/bttv-cards.c
+++ b/drivers/media/video/bttv-cards.c
@@ -1,5 +1,5 @@
/*
- $Id: bttv-cards.c,v 1.42 2005/01/13 17:22:33 kraxel Exp $
+ $Id: bttv-cards.c,v 1.47 2005/02/22 14:06:32 kraxel Exp $
bttv-cards.c
@@ -80,6 +80,9 @@ static void picolo_tetra_init(struct bttv *btv);
static void tibetCS16_muxsel(struct bttv *btv, unsigned int input);
static void tibetCS16_init(struct bttv *btv);
+static void kodicom4400r_muxsel(struct bttv *btv, unsigned int input);
+static void kodicom4400r_init(struct bttv *btv);
+
static void sigmaSLC_muxsel(struct bttv *btv, unsigned int input);
static void sigmaSQ_muxsel(struct bttv *btv, unsigned int input);
@@ -101,6 +104,7 @@ static unsigned int pll[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = UNSET };
static unsigned int tuner[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = UNSET };
static unsigned int svhs[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = UNSET };
static unsigned int remote[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = UNSET };
+static struct bttv *master[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = NULL };
#ifdef MODULE
static unsigned int autoload = 1;
#else
@@ -170,6 +174,8 @@ static struct CARD {
// some cards ship with byteswapped IDs ...
{ 0x1200bd11, BTTV_PINNACLE, "Pinnacle PCTV [bswap]" },
{ 0xff00bd11, BTTV_PINNACLE, "Pinnacle PCTV [bswap]" },
+ // this seems to happen as well ...
+ { 0xff1211bd, BTTV_PINNACLE, "Pinnacle PCTV" },
{ 0x3000121a, BTTV_VOODOOTV_FM, "3Dfx VoodooTV FM/ VoodooTV 200" },
{ 0x263710b4, BTTV_VOODOOTV_FM, "3Dfx VoodooTV FM/ VoodooTV 200" },
@@ -291,7 +297,7 @@ static struct CARD {
{ 0x07611461, BTTV_AVDVBT_761, "AverMedia AverTV DVB-T 761" },
{ 0x001c11bd, BTTV_PINNACLESAT, "Pinnacle PCTV Sat" },
{ 0x002611bd, BTTV_TWINHAN_DST, "Pinnacle PCTV SAT CI" },
- { 0x00011822, BTTV_TWINHAN_DST, "Twinhan VisionPlus DVB-T" },
+ { 0x00011822, BTTV_TWINHAN_DST, "Twinhan VisionPlus DVB" },
{ 0xfc00270f, BTTV_TWINHAN_DST, "ChainTech digitop DST-1000 DVB-S" },
{ 0x07711461, BTTV_AVDVBT_771, "AVermedia AverTV DVB-T 771" },
{ 0xdb1018ac, BTTV_DVICO_DVBT_LITE, "DVICO FusionHDTV DVB-T Lite" },
@@ -1920,6 +1926,7 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.muxsel = { 2, 3, 1, 0},
.tuner_type = TUNER_PHILIPS_ATSC,
+ .has_dvb = 1,
},{
.name = "Twinhan DST + clones",
.no_msp34xx = 1,
@@ -2188,6 +2195,63 @@ struct tvcard bttv_tvcards[] = {
.no_tda7432 = 1,
.tuner_type = -1,
.muxsel_hook = tibetCS16_muxsel,
+},
+{
+ /* Bill Brack <wbrack@mmm.com.hk> */
+ /*
+ * Note that, because of the card's wiring, the "master"
+ * BT878A chip (i.e. the one which controls the analog switch
+ * and must use this card type) is the 2nd one detected. The
+ * other 3 chips should use card type 0x85, whose description
+ * follows this one. There is a EEPROM on the card (which is
+ * connected to the I2C of one of those other chips), but is
+ * not currently handled. There is also a facility for a
+ * "monitor", which is also not currently implemented.
+ */
+ .name = "Kodicom 4400R (master)",
+ .video_inputs = 16,
+ .audio_inputs = 0,
+ .tuner = -1,
+ .tuner_type = -1,
+ .svhs = -1,
+ /* GPIO bits 0-9 used for analog switch:
+ * 00 - 03: camera selector
+ * 04 - 06: channel (controller) selector
+ * 07: data (1->on, 0->off)
+ * 08: strobe
+ * 09: reset
+ * bit 16 is input from sync separator for the channel
+ */
+ .gpiomask = 0x0003ff,
+ .no_gpioirq = 1,
+ .muxsel = { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
+ .pll = PLL_28,
+ .no_msp34xx = 1,
+ .no_tda7432 = 1,
+ .no_tda9875 = 1,
+ .muxsel_hook = kodicom4400r_muxsel,
+},
+{
+ /* Bill Brack <wbrack@mmm.com.hk> */
+ /* Note that, for reasons unknown, the "master" BT878A chip (i.e. the
+ * one which controls the analog switch, and must use the card type)
+ * is the 2nd one detected. The other 3 chips should use this card
+ * type
+ */
+ .name = "Kodicom 4400R (slave)",
+ .video_inputs = 16,
+ .audio_inputs = 0,
+ .tuner = -1,
+ .tuner_type = -1,
+ .svhs = -1,
+ .gpiomask = 0x010000,
+ .no_gpioirq = 1,
+ .muxsel = { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
+ .pll = PLL_28,
+ .no_msp34xx = 1,
+ .no_tda7432 = 1,
+ .no_tda9875 = 1,
+ .muxsel_hook = kodicom4400r_muxsel,
}};
static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards);
@@ -2682,6 +2746,9 @@ void __devinit bttv_init_card2(struct bttv *btv)
case BTTV_TIBET_CS16:
tibetCS16_init(btv);
break;
+ case BTTV_KODICOM_4400R:
+ kodicom4400r_init(btv);
+ break;
}
/* pll configuration */
@@ -3894,6 +3961,112 @@ static void tibetCS16_init(struct bttv *btv)
gpio_write(0x0f7fff);
}
+/*
+ * The following routines for the Kodicom-4400r get a little mind-twisting.
+ * There is a "master" controller and three "slave" controllers, together
+ * an analog switch which connects any of 16 cameras to any of the BT87A's.
+ * The analog switch is controlled by the "master", but the detection order
+ * of the four BT878A chips is in an order which I just don't understand.
+ * The "master" is actually the second controller to be detected. The
+ * logic on the board uses logical numbers for the 4 controlers, but
+ * those numbers are different from the detection sequence. When working
+ * with the analog switch, we need to "map" from the detection sequence
+ * over to the board's logical controller number. This mapping sequence
+ * is {3, 0, 2, 1}, i.e. the first controller to be detected is logical
+ * unit 3, the second (which is the master) is logical unit 0, etc.
+ * We need to maintain the status of the analog switch (which of the 16
+ * cameras is connected to which of the 4 controllers). Rather than
+ * add to the bttv structure for this, we use the data reserved for
+ * the mbox (unused for this card type).
+ */
+
+/*
+ * First a routine to set the analog switch, which controls which camera
+ * is routed to which controller. The switch comprises an X-address
+ * (gpio bits 0-3, representing the camera, ranging from 0-15), and a
+ * Y-address (gpio bits 4-6, representing the controller, ranging from 0-3).
+ * A data value (gpio bit 7) of '1' enables the switch, and '0' disables
+ * the switch. A STROBE bit (gpio bit 8) latches the data value into the
+ * specified address. The idea is to set the address and data, then bring
+ * STROBE high, and finally bring STROBE back to low.
+ */
+static void kodicom4400r_write(struct bttv *btv,
+ unsigned char xaddr,
+ unsigned char yaddr,
+ unsigned char data) {
+ unsigned int udata;
+
+ udata = (data << 7) | ((yaddr&3) << 4) | (xaddr&0xf);
+ gpio_bits(0x1ff, udata); /* write ADDR and DAT */
+ gpio_bits(0x1ff, udata | (1 << 8)); /* strobe high */
+ gpio_bits(0x1ff, udata); /* strobe low */
+}
+
+/*
+ * Next the mux select. Both the "master" and "slave" 'cards' (controllers)
+ * use this routine. The routine finds the "master" for the card, maps
+ * the controller number from the detected position over to the logical
+ * number, writes the appropriate data to the analog switch, and housekeeps
+ * the local copy of the switch information. The parameter 'input' is the
+ * requested camera number (0 - 15).
+ */
+static void kodicom4400r_muxsel(struct bttv *btv, unsigned int input)
+{
+ char *sw_status;
+ int xaddr, yaddr;
+ struct bttv *mctlr;
+ static unsigned char map[4] = {3, 0, 2, 1};
+
+ mctlr = master[btv->c.nr];
+ if (mctlr == NULL) { /* ignore if master not yet detected */
+ return;
+ }
+ yaddr = (btv->c.nr - mctlr->c.nr + 1) & 3; /* the '&' is for safety */
+ yaddr = map[yaddr];
+ sw_status = (char *)(&mctlr->mbox_we);
+ xaddr = input & 0xf;
+ /* Check if the controller/camera pair has changed, else ignore */
+ if (sw_status[yaddr] != xaddr)
+ {
+ /* "open" the old switch, "close" the new one, save the new */
+ kodicom4400r_write(mctlr, sw_status[yaddr], yaddr, 0);
+ sw_status[yaddr] = xaddr;
+ kodicom4400r_write(mctlr, xaddr, yaddr, 1);
+ }
+}
+
+/*
+ * During initialisation, we need to reset the analog switch. We
+ * also preset the switch to map the 4 connectors on the card to the
+ * *user's* (see above description of kodicom4400r_muxsel) channels
+ * 0 through 3
+ */
+static void kodicom4400r_init(struct bttv *btv)
+{
+ char *sw_status = (char *)(&btv->mbox_we);
+ int ix;
+
+ gpio_inout(0x0003ff, 0x0003ff);
+ gpio_write(1 << 9); /* reset MUX */
+ gpio_write(0);
+ /* Preset camera 0 to the 4 controllers */
+ for (ix=0; ix<4; ix++) {
+ sw_status[ix] = ix;
+ kodicom4400r_write(btv, ix, ix, 1);
+ }
+ /*
+ * Since this is the "master", we need to set up the
+ * other three controller chips' pointers to this structure
+ * for later use in the muxsel routine.
+ */
+ if ((btv->c.nr<1) || (btv->c.nr>BTTV_MAX-3))
+ return;
+ master[btv->c.nr-1] = btv;
+ master[btv->c.nr] = btv;
+ master[btv->c.nr+1] = btv;
+ master[btv->c.nr+2] = btv;
+}
+
// The Grandtec X-Guard framegrabber card uses two Dual 4-channel
// video multiplexers to provide up to 16 video inputs. These
// multiplexers are controlled by the lower 8 GPIO pins of the
diff --git a/drivers/media/video/bttv-driver.c b/drivers/media/video/bttv-driver.c
index 5b2522fa89319..c13f222fe6bdd 100644
--- a/drivers/media/video/bttv-driver.c
+++ b/drivers/media/video/bttv-driver.c
@@ -1,5 +1,5 @@
/*
- $Id: bttv-driver.c,v 1.34 2005/01/07 13:11:19 kraxel Exp $
+ $Id: bttv-driver.c,v 1.37 2005/02/21 13:57:59 kraxel Exp $
bttv - Bt848 frame grabber driver
@@ -3167,6 +3167,82 @@ static struct video_device radio_template =
};
/* ----------------------------------------------------------------------- */
+/* some debug code */
+
+int bttv_risc_decode(u32 risc)
+{
+ static char *instr[16] = {
+ [ BT848_RISC_WRITE >> 28 ] = "write",
+ [ BT848_RISC_SKIP >> 28 ] = "skip",
+ [ BT848_RISC_WRITEC >> 28 ] = "writec",
+ [ BT848_RISC_JUMP >> 28 ] = "jump",
+ [ BT848_RISC_SYNC >> 28 ] = "sync",
+ [ BT848_RISC_WRITE123 >> 28 ] = "write123",
+ [ BT848_RISC_SKIP123 >> 28 ] = "skip123",
+ [ BT848_RISC_WRITE1S23 >> 28 ] = "write1s23",
+ };
+ static int incr[16] = {
+ [ BT848_RISC_WRITE >> 28 ] = 2,
+ [ BT848_RISC_JUMP >> 28 ] = 2,
+ [ BT848_RISC_SYNC >> 28 ] = 2,
+ [ BT848_RISC_WRITE123 >> 28 ] = 5,
+ [ BT848_RISC_SKIP123 >> 28 ] = 2,
+ [ BT848_RISC_WRITE1S23 >> 28 ] = 3,
+ };
+ static char *bits[] = {
+ "be0", "be1", "be2", "be3/resync",
+ "set0", "set1", "set2", "set3",
+ "clr0", "clr1", "clr2", "clr3",
+ "irq", "res", "eol", "sol",
+ };
+ int i;
+
+ printk("0x%08x [ %s", risc,
+ instr[risc >> 28] ? instr[risc >> 28] : "INVALID");
+ for (i = ARRAY_SIZE(bits)-1; i >= 0; i--)
+ if (risc & (1 << (i + 12)))
+ printk(" %s",bits[i]);
+ printk(" count=%d ]\n", risc & 0xfff);
+ return incr[risc >> 28] ? incr[risc >> 28] : 1;
+}
+
+void bttv_risc_disasm(struct bttv *btv,
+ struct btcx_riscmem *risc)
+{
+ unsigned int i,j,n;
+
+ printk("%s: risc disasm: %p [dma=0x%08lx]\n",
+ btv->c.name, risc->cpu, (unsigned long)risc->dma);
+ for (i = 0; i < (risc->size >> 2); i += n) {
+ printk("%s: 0x%lx: ", btv->c.name,
+ (unsigned long)(risc->dma + (i<<2)));
+ n = bttv_risc_decode(risc->cpu[i]);
+ for (j = 1; j < n; j++)
+ printk("%s: 0x%lx: 0x%08x [ arg #%d ]\n",
+ btv->c.name, (unsigned long)(risc->dma + ((i+j)<<2)),
+ risc->cpu[i+j], j);
+ if (0 == risc->cpu[i])
+ break;
+ }
+}
+
+static void bttv_print_riscaddr(struct bttv *btv)
+{
+ printk(" main: %08Lx\n",
+ (unsigned long long)btv->main.dma);
+ printk(" vbi : o=%08Lx e=%08Lx\n",
+ btv->cvbi ? (unsigned long long)btv->cvbi->top.dma : 0,
+ btv->cvbi ? (unsigned long long)btv->cvbi->bottom.dma : 0);
+ printk(" cap : o=%08Lx e=%08Lx\n",
+ btv->curr.top ? (unsigned long long)btv->curr.top->top.dma : 0,
+ btv->curr.bottom ? (unsigned long long)btv->curr.bottom->bottom.dma : 0);
+ printk(" scr : o=%08Lx e=%08Lx\n",
+ btv->screen ? (unsigned long long)btv->screen->top.dma : 0,
+ btv->screen ? (unsigned long long)btv->screen->bottom.dma : 0);
+ bttv_risc_disasm(btv, &btv->main);
+}
+
+/* ----------------------------------------------------------------------- */
/* irq handler */
static char *irq_name[] = {
@@ -3204,21 +3280,6 @@ static void bttv_print_irqbits(u32 print, u32 mark)
}
}
-static void bttv_print_riscaddr(struct bttv *btv)
-{
- printk(" main: %08Lx\n",
- (unsigned long long)btv->main.dma);
- printk(" vbi : o=%08Lx e=%08Lx\n",
- btv->cvbi ? (unsigned long long)btv->cvbi->top.dma : 0,
- btv->cvbi ? (unsigned long long)btv->cvbi->bottom.dma : 0);
- printk(" cap : o=%08Lx e=%08Lx\n",
- btv->curr.top ? (unsigned long long)btv->curr.top->top.dma : 0,
- btv->curr.bottom ? (unsigned long long)btv->curr.bottom->bottom.dma : 0);
- printk(" scr : o=%08Lx e=%08Lx\n",
- btv->screen ? (unsigned long long)btv->screen->top.dma : 0,
- btv->screen ? (unsigned long long)btv->screen->bottom.dma : 0);
-}
-
static void bttv_irq_debug_low_latency(struct bttv *btv, u32 rc)
{
printk("bttv%d: irq: skipped frame [main=%lx,o_vbi=%lx,o_field=%lx,rc=%lx]\n",
@@ -3921,7 +3982,7 @@ static void __devexit bttv_remove(struct pci_dev *pci_dev)
return;
}
-static int bttv_suspend(struct pci_dev *pci_dev, u32 state)
+static int bttv_suspend(struct pci_dev *pci_dev, pm_message_t state)
{
struct bttv *btv = pci_get_drvdata(pci_dev);
struct bttv_buffer_set idle;
diff --git a/drivers/media/video/bttv-gpio.c b/drivers/media/video/bttv-gpio.c
index ef6744232106b..77320cdf205fc 100644
--- a/drivers/media/video/bttv-gpio.c
+++ b/drivers/media/video/bttv-gpio.c
@@ -1,5 +1,5 @@
/*
- $Id: bttv-gpio.c,v 1.6 2004/11/03 09:04:50 kraxel Exp $
+ $Id: bttv-gpio.c,v 1.7 2005/02/16 12:14:10 kraxel Exp $
bttv-gpio.c -- gpio sub drivers
@@ -94,6 +94,7 @@ int bttv_sub_del_devices(struct bttv_core *core)
list_for_each_safe(item,save,&core->subs) {
sub = list_entry(item,struct bttv_sub_device,list);
+ list_del(&sub->list);
device_unregister(&sub->dev);
}
return 0;
@@ -113,20 +114,6 @@ void bttv_gpio_irq(struct bttv_core *core)
}
}
-void bttv_i2c_info(struct bttv_core *core, struct i2c_client *client, int attach)
-{
- struct bttv_sub_driver *drv;
- struct bttv_sub_device *dev;
- struct list_head *item;
-
- 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->i2c_info)
- drv->i2c_info(dev,client,attach);
- }
-}
-
/* ----------------------------------------------------------------------- */
/* external: sub-driver register/unregister */
diff --git a/drivers/media/video/bttv-i2c.c b/drivers/media/video/bttv-i2c.c
index 1315c499cac5e..e42f1ec13f3e6 100644
--- a/drivers/media/video/bttv-i2c.c
+++ b/drivers/media/video/bttv-i2c.c
@@ -1,5 +1,5 @@
/*
- $Id: bttv-i2c.c,v 1.17 2004/12/14 15:33:30 kraxel Exp $
+ $Id: bttv-i2c.c,v 1.18 2005/02/16 12:14:10 kraxel Exp $
bttv-i2c.c -- all the i2c code is here
@@ -39,7 +39,6 @@ static struct i2c_adapter bttv_i2c_adap_hw_template;
static struct i2c_client bttv_i2c_client_template;
static int attach_inform(struct i2c_client *client);
-static int detach_inform(struct i2c_client *client);
static int i2c_debug = 0;
static int i2c_hw = 0;
@@ -112,7 +111,6 @@ static struct i2c_adapter bttv_i2c_adap_sw_template = {
I2C_DEVNAME("bt848"),
.id = I2C_HW_B_BT848,
.client_register = attach_inform,
- .client_unregister = detach_inform,
};
/* ----------------------------------------------------------------------- */
@@ -245,7 +243,7 @@ bttv_i2c_readbytes(struct bttv *btv, const struct i2c_msg *msg, int last)
return retval;
}
-static int bttv_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num)
+static int bttv_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
{
struct bttv *btv = i2c_get_adapdata(i2c_adap);
int retval = 0;
@@ -290,7 +288,6 @@ static struct i2c_adapter bttv_i2c_adap_hw_template = {
.id = I2C_ALGO_BIT | I2C_HW_B_BT848 /* FIXME */,
.algo = &bttv_algo,
.client_register = attach_inform,
- .client_unregister = detach_inform,
};
/* ----------------------------------------------------------------------- */
@@ -305,22 +302,12 @@ static int attach_inform(struct i2c_client *client)
if (btv->pinnacle_id != UNSET)
bttv_call_i2c_clients(btv,AUDC_CONFIG_PINNACLE,
&btv->pinnacle_id);
- bttv_i2c_info(&btv->c, client, 1);
-
if (bttv_debug)
printk("bttv%d: i2c attach [client=%s]\n",
btv->c.nr, i2c_clientname(client));
return 0;
}
-static int detach_inform(struct i2c_client *client)
-{
- struct bttv *btv = i2c_get_adapdata(client->adapter);
-
- bttv_i2c_info(&btv->c, client, 0);
- return 0;
-}
-
void bttv_call_i2c_clients(struct bttv *btv, unsigned int cmd, void *arg)
{
if (0 != btv->i2c_rc)
@@ -330,7 +317,6 @@ void bttv_call_i2c_clients(struct bttv *btv, unsigned int cmd, void *arg)
static struct i2c_client bttv_i2c_client_template = {
I2C_DEVNAME("bttv internal"),
- .id = -1,
};
diff --git a/drivers/media/video/bttv.h b/drivers/media/video/bttv.h
index 5f7473084432c..8322b66e09054 100644
--- a/drivers/media/video/bttv.h
+++ b/drivers/media/video/bttv.h
@@ -1,5 +1,5 @@
/*
- * $Id: bttv.h,v 1.14 2005/01/07 13:11:19 kraxel Exp $
+ * $Id: bttv.h,v 1.17 2005/02/22 14:06:32 kraxel Exp $
*
* bttv - Bt848 frame grabber driver
*
@@ -134,6 +134,7 @@
#define BTTV_APAC_VIEWCOMP 0x7f
#define BTTV_DVICO_DVBT_LITE 0x80
#define BTTV_TIBET_CS16 0x83
+#define BTTV_KODICOM_4400R 0x84
/* i2c address list */
#define I2C_TSA5522 0xc2
@@ -302,8 +303,6 @@ struct bttv_sub_driver {
struct device_driver drv;
char wanted[BUS_ID_SIZE];
void (*gpio_irq)(struct bttv_sub_device *sub);
- void (*i2c_info)(struct bttv_sub_device *sub,
- struct i2c_client *client, int attach);
};
#define to_bttv_sub_drv(x) container_of((x), struct bttv_sub_driver, drv)
diff --git a/drivers/media/video/bttvp.h b/drivers/media/video/bttvp.h
index 3862bc97bf867..1a9ba7e1cf519 100644
--- a/drivers/media/video/bttvp.h
+++ b/drivers/media/video/bttvp.h
@@ -1,5 +1,5 @@
/*
- $Id: bttvp.h,v 1.15 2004/12/14 15:33:30 kraxel Exp $
+ $Id: bttvp.h,v 1.17 2005/02/16 12:14:10 kraxel Exp $
bttv - Bt848 frame grabber driver
@@ -209,7 +209,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);
-void bttv_i2c_info(struct bttv_core *core, struct i2c_client *client, int attach);
/* ---------------------------------------------------------- */
@@ -230,7 +229,6 @@ extern int fini_bttv_i2c(struct bttv *btv);
/* our devices */
#define BTTV_MAX 16
extern unsigned int bttv_num;
-extern struct bttv bttvs[BTTV_MAX];
#define BTTV_MAX_FBUF 0x208000
#define VBIBUF_SIZE (2048*VBI_MAXLINES*2)
@@ -377,6 +375,7 @@ struct bttv {
unsigned int users;
struct bttv_fh init;
};
+extern struct bttv bttvs[BTTV_MAX];
/* private ioctls */
#define BTTV_VERSION _IOR('v' , BASE_VIDIOCPRIVATE+6, int)
diff --git a/drivers/media/video/c-qcam.c b/drivers/media/video/c-qcam.c
index 3ea10d4bc9c72..75442ec49f352 100644
--- a/drivers/media/video/c-qcam.c
+++ b/drivers/media/video/c-qcam.c
@@ -363,7 +363,7 @@ static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long le
size_t wantlen, outptr = 0;
char tmpbuf[BUFSZ];
- if (verify_area(VERIFY_WRITE, buf, len))
+ if (!access_ok(VERIFY_WRITE, buf, len))
return -EFAULT;
/* Wait for camera to become ready */
diff --git a/drivers/media/video/cpia_usb.c b/drivers/media/video/cpia_usb.c
index 0bf9349db8707..cdda423386c5c 100644
--- a/drivers/media/video/cpia_usb.c
+++ b/drivers/media/video/cpia_usb.c
@@ -308,7 +308,7 @@ static int WritePacket(struct usb_device *udev, const u8 *packet, u8 *buf, size_
packet[1] + (packet[0] << 8),
USB_TYPE_VENDOR | USB_RECIP_DEVICE,
packet[2] + (packet[3] << 8),
- packet[4] + (packet[5] << 8), buf, size, HZ);
+ packet[4] + (packet[5] << 8), buf, size, 1000);
}
/****************************************************************************
@@ -325,7 +325,7 @@ static int ReadPacket(struct usb_device *udev, u8 *packet, u8 *buf, size_t size)
packet[1] + (packet[0] << 8),
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
packet[2] + (packet[3] << 8),
- packet[4] + (packet[5] << 8), buf, size, HZ);
+ packet[4] + (packet[5] << 8), buf, size, 1000);
}
static int cpia_usb_transferCmd(void *privdata, u8 *command, u8 *data)
@@ -440,7 +440,7 @@ static void cpia_usb_free_resources(struct usb_cpia *ucpia, int try)
/* Unschedule all of the iso td's */
if (ucpia->sbuf[1].urb) {
- usb_unlink_urb(ucpia->sbuf[1].urb);
+ usb_kill_urb(ucpia->sbuf[1].urb);
usb_free_urb(ucpia->sbuf[1].urb);
ucpia->sbuf[1].urb = NULL;
}
@@ -451,7 +451,7 @@ static void cpia_usb_free_resources(struct usb_cpia *ucpia, int try)
}
if (ucpia->sbuf[0].urb) {
- usb_unlink_urb(ucpia->sbuf[0].urb);
+ usb_kill_urb(ucpia->sbuf[0].urb);
usb_free_urb(ucpia->sbuf[0].urb);
ucpia->sbuf[0].urb = NULL;
}
diff --git a/drivers/media/video/cx88/Makefile b/drivers/media/video/cx88/Makefile
index de2b190a5dede..606d0348da2ce 100644
--- a/drivers/media/video/cx88/Makefile
+++ b/drivers/media/video/cx88/Makefile
@@ -1,4 +1,5 @@
-cx88xx-objs := cx88-cards.o cx88-core.o cx88-i2c.o cx88-tvaudio.o
+cx88xx-objs := cx88-cards.o cx88-core.o cx88-i2c.o cx88-tvaudio.o \
+ cx88-input.o
cx8800-objs := cx88-video.o cx88-vbi.o
cx8802-objs := cx88-mpeg.o
diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c
index ef56a5d1e5720..46d6778b863b6 100644
--- a/drivers/media/video/cx88/cx88-blackbird.c
+++ b/drivers/media/video/cx88/cx88-blackbird.c
@@ -1,5 +1,5 @@
/*
- * $Id: cx88-blackbird.c,v 1.17 2004/11/07 13:17:15 kraxel Exp $
+ * $Id: cx88-blackbird.c,v 1.26 2005/03/07 15:58:05 kraxel Exp $
*
* Support for a cx23416 mpeg encoder via cx2388x host port.
* "blackbird" reference design.
@@ -25,6 +25,7 @@
*/
#include <linux/module.h>
+#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/delay.h>
@@ -207,10 +208,6 @@ static int register_write(struct cx88_core *core, u32 address, u32 value)
cx_read(P1_RADDR0);
return wait_ready_gpio0_bit1(core,1);
-#if 0
- udelay(1000); /* without this, things don't go right (subsequent memory_write()'s don't get through */
- /* ? would this be safe here? set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(1); */
-#endif
}
@@ -283,7 +280,7 @@ static int blackbird_api_cmd(struct cx8802_dev *dev, u32 command,
timeout = jiffies + msecs_to_jiffies(10);
for (;;) {
memory_read(dev->core, dev->mailbox, &flag);
- if (0 == (flag & 4))
+ if (0 != (flag & 4))
break;
if (time_after(jiffies,timeout)) {
dprintk(0, "ERROR: API Mailbox timeout\n");
@@ -324,7 +321,7 @@ static int blackbird_find_mailbox(struct cx8802_dev *dev)
signaturecnt = 0;
if (4 == signaturecnt) {
dprintk(1, "Mailbox signature found\n");
- return i;
+ return i+1;
}
}
dprintk(0, "Mailbox signature values not found!\n");
@@ -427,7 +424,8 @@ static void blackbird_codec_settings(struct cx8802_dev *dev)
blackbird_api_cmd(dev, IVTV_API_ASSIGN_FRAMERATE, 1, 0, 0);
/* assign frame size */
- blackbird_api_cmd(dev, IVTV_API_ASSIGN_FRAME_SIZE, 2, 0, 480, 720);
+ blackbird_api_cmd(dev, IVTV_API_ASSIGN_FRAME_SIZE, 2, 0,
+ dev->height, dev->width);
/* assign aspect ratio */
blackbird_api_cmd(dev, IVTV_API_ASSIGN_ASPECT_RATIO, 1, 0, 2);
@@ -629,8 +627,8 @@ static int mpeg_do_ioctl(struct inode *inode, struct file *file,
memset(f,0,sizeof(*f));
f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- f->fmt.pix.width = 720;
- f->fmt.pix.height = 576;
+ f->fmt.pix.width = dev->width;
+ f->fmt.pix.height = dev->height;
f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
f->fmt.pix.sizeimage = 1024 * 512 /* FIXME: BUFFER_SIZE */;
}
@@ -694,6 +692,10 @@ static int mpeg_open(struct inode *inode, struct file *file)
file->private_data = fh;
fh->dev = dev;
+ /* FIXME: locking against other video device */
+ cx88_set_scale(dev->core, dev->width, dev->height,
+ V4L2_FIELD_INTERLACED);
+
videobuf_queue_init(&fh->mpegq, &blackbird_qops,
dev->pci, &dev->slock,
V4L2_BUF_TYPE_VIDEO_CAPTURE,
@@ -715,6 +717,7 @@ static int mpeg_release(struct inode *inode, struct file *file)
if (fh->mpegq.reading)
videobuf_read_stop(&fh->mpegq);
+ videobuf_mmap_free(&fh->mpegq);
file->private_data = NULL;
kfree(fh);
return 0;
@@ -821,6 +824,8 @@ static int __devinit blackbird_probe(struct pci_dev *pci_dev,
memset(dev,0,sizeof(*dev));
dev->pci = pci_dev;
dev->core = core;
+ dev->width = 720;
+ dev->height = 480;
err = cx8802_init_common(dev);
if (0 != err)
@@ -852,6 +857,8 @@ static void __devexit blackbird_remove(struct pci_dev *pci_dev)
/* common */
cx8802_fini_common(dev);
+ cx88_core_put(dev->core,dev->pci);
+ kfree(dev);
}
static struct pci_device_id cx8802_pci_tbl[] = {
@@ -885,7 +892,7 @@ static int blackbird_init(void)
printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n",
SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100);
#endif
- return pci_module_init(&blackbird_pci_driver);
+ return pci_register_driver(&blackbird_pci_driver);
}
static void blackbird_fini(void)
diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c
index 01413b045fb38..367624822d776 100644
--- a/drivers/media/video/cx88/cx88-cards.c
+++ b/drivers/media/video/cx88/cx88-cards.c
@@ -1,5 +1,5 @@
/*
- * $Id: cx88-cards.c,v 1.47 2004/11/03 09:04:50 kraxel Exp $
+ * $Id: cx88-cards.c,v 1.66 2005/03/04 09:12:23 kraxel Exp $
*
* device driver for Conexant 2388x based TV cards
* card-specific stuff.
@@ -26,14 +26,7 @@
#include <linux/pci.h>
#include <linux/delay.h>
-#if defined(CONFIG_VIDEO_CX88_DVB) || defined(CONFIG_VIDEO_CX88_DVB_MODULE)
-# define WITH_DVB 1
-#endif
-
#include "cx88.h"
-#ifdef WITH_DVB
-#include "cx22702.h"
-#endif
/* ------------------------------------------------------------------ */
/* board config info */
@@ -59,6 +52,7 @@ struct cx88_board cx88_boards[] = {
[CX88_BOARD_HAUPPAUGE] = {
.name = "Hauppauge WinTV 34xxx models",
.tuner_type = UNSET,
+ .tda9887_conf = TDA9887_PRESENT,
.input = {{
.type = CX88_VMUX_TELEVISION,
.vmux = 0,
@@ -91,7 +85,7 @@ struct cx88_board cx88_boards[] = {
},
[CX88_BOARD_PIXELVIEW] = {
.name = "PixelView",
- .tuner_type = UNSET,
+ .tuner_type = 5,
.input = {{
.type = CX88_VMUX_TELEVISION,
.vmux = 0,
@@ -126,7 +120,7 @@ struct cx88_board cx88_boards[] = {
.gpio0 = 0x03fe,
}},
},
- [CX88_BOARD_WINFAST2000XP] = {
+ [CX88_BOARD_WINFAST2000XP_EXPERT] = {
.name = "Leadtek Winfast 2000XP Expert",
.tuner_type = 44,
.tda9887_conf = TDA9887_PRESENT,
@@ -217,26 +211,55 @@ struct cx88_board cx88_boards[] = {
.input = {{
.type = CX88_VMUX_TELEVISION,
.vmux = 0,
- }},
+ .gpio0 = 0x0035e700,
+ .gpio1 = 0x00003004,
+ .gpio2 = 0x0035e700,
+ .gpio3 = 0x02000000,
+ },{
+
+ .type = CX88_VMUX_COMPOSITE1,
+ .vmux = 1,
+ .gpio0 = 0x0035c700,
+ .gpio1 = 0x00003004,
+ .gpio2 = 0x0035c700,
+ .gpio3 = 0x02000000,
+ },{
+ .type = CX88_VMUX_SVIDEO,
+ .vmux = 2,
+ .gpio0 = 0x0035c700,
+ .gpio1 = 0x0035c700,
+ .gpio2 = 0x02000000,
+ .gpio3 = 0x02000000,
+ }},
.radio = {
- .type = CX88_RADIO,
- },
+ .type = CX88_RADIO,
+ .gpio0 = 0x0035d700,
+ .gpio1 = 0x00007004,
+ .gpio2 = 0x0035d700,
+ .gpio3 = 0x02000000,
+ },
},
[CX88_BOARD_LEADTEK_PVR2000] = {
+ // gpio values for PAL version from regspy by DScaler
.name = "Leadtek PVR 2000",
.tuner_type = 38,
+ .tda9887_conf = TDA9887_PRESENT,
.input = {{
.type = CX88_VMUX_TELEVISION,
.vmux = 0,
+ .gpio0 = 0x0000bde6,
},{
.type = CX88_VMUX_COMPOSITE1,
.vmux = 1,
+ .gpio0 = 0x0000bde6,
},{
.type = CX88_VMUX_SVIDEO,
.vmux = 2,
+ .gpio0 = 0x0000bde6,
}},
.radio = {
.type = CX88_RADIO,
+ .gpio0 = 0x0000bd62,
},
.blackbird = 1,
},
@@ -320,14 +343,15 @@ struct cx88_board cx88_boards[] = {
.name = "KWorld/VStream XPert DVB-T",
.tuner_type = TUNER_ABSENT,
.input = {{
- .type = CX88_VMUX_DVB,
- .vmux = 0,
- },{
.type = CX88_VMUX_COMPOSITE1,
.vmux = 1,
+ .gpio0 = 0x0700,
+ .gpio2 = 0x0101,
},{
.type = CX88_VMUX_SVIDEO,
.vmux = 2,
+ .gpio0 = 0x0700,
+ .gpio2 = 0x0101,
}},
.dvb = 1,
},
@@ -452,6 +476,131 @@ struct cx88_board cx88_boards[] = {
}},
.dvb = 1,
},
+ [CX88_BOARD_DNTV_LIVE_DVB_T] = {
+ .name = "digitalnow DNTV Live! DVB-T",
+ .tuner_type = TUNER_ABSENT,
+ .input = {{
+ .type = CX88_VMUX_COMPOSITE1,
+ .vmux = 1,
+ .gpio0 = 0x00000700,
+ .gpio2 = 0x00000101,
+ },{
+ .type = CX88_VMUX_SVIDEO,
+ .vmux = 2,
+ .gpio0 = 0x00000700,
+ .gpio2 = 0x00000101,
+ }},
+ .dvb = 1,
+ },
+ [CX88_BOARD_PCHDTV_HD3000] = {
+ .name = "pcHDTV HD3000 HDTV",
+ .tuner_type = TUNER_THOMSON_DTT7610,
+ .input = {{
+ .type = CX88_VMUX_TELEVISION,
+ .vmux = 0,
+ .gpio0 = 0x00008484,
+ .gpio1 = 0x00000000,
+ .gpio2 = 0x00000000,
+ .gpio3 = 0x00000000,
+ },{
+ .type = CX88_VMUX_COMPOSITE1,
+ .vmux = 1,
+ .gpio0 = 0x00008400,
+ .gpio1 = 0x00000000,
+ .gpio2 = 0x00000000,
+ .gpio3 = 0x00000000,
+ },{
+ .type = CX88_VMUX_SVIDEO,
+ .vmux = 2,
+ .gpio0 = 0x00008400,
+ .gpio1 = 0x00000000,
+ .gpio2 = 0x00000000,
+ .gpio3 = 0x00000000,
+ }},
+ .radio = {
+ .type = CX88_RADIO,
+ .vmux = 2,
+ .gpio0 = 0x00008400,
+ .gpio1 = 0x00000000,
+ .gpio2 = 0x00000000,
+ .gpio3 = 0x00000000,
+ },
+ .dvb = 1,
+ },
+ [CX88_BOARD_HAUPPAUGE_ROSLYN] = {
+ // entry added by Kaustubh D. Bhalerao <bhalerao.1@osu.edu>
+ // GPIO values obtained from regspy, courtesy Sean Covel
+ .name = "Hauppauge WinTV 28xxx (Roslyn) models",
+ .tuner_type = UNSET,
+ .input = {{
+ .type = CX88_VMUX_TELEVISION,
+ .vmux = 0,
+ .gpio0 = 0xed12, // internal decoder
+ .gpio2 = 0x00ff,
+ },{
+ .type = CX88_VMUX_DEBUG,
+ .vmux = 0,
+ .gpio0 = 0xff01, // mono from tuner chip
+ },{
+ .type = CX88_VMUX_COMPOSITE1,
+ .vmux = 1,
+ .gpio0 = 0xff02,
+ },{
+ .type = CX88_VMUX_SVIDEO,
+ .vmux = 2,
+ .gpio0 = 0xed92,
+ .gpio2 = 0x00ff,
+ }},
+ .radio = {
+ .type = CX88_RADIO,
+ .gpio0 = 0xed96,
+ .gpio2 = 0x00ff,
+ },
+ .blackbird = 1,
+ },
+ [CX88_BOARD_DIGITALLOGIC_MEC] = {
+ /* params copied over from Leadtek PVR 2000 */
+ .name = "Digital-Logic MICROSPACE Entertainment Center (MEC)",
+ /* not sure yet about the tuner type */
+ .tuner_type = 38,
+ .tda9887_conf = TDA9887_PRESENT,
+ .input = {{
+ .type = CX88_VMUX_TELEVISION,
+ .vmux = 0,
+ .gpio0 = 0x0000bde6,
+ },{
+ .type = CX88_VMUX_COMPOSITE1,
+ .vmux = 1,
+ .gpio0 = 0x0000bde6,
+ },{
+ .type = CX88_VMUX_SVIDEO,
+ .vmux = 2,
+ .gpio0 = 0x0000bde6,
+ }},
+ .radio = {
+ .type = CX88_RADIO,
+ .gpio0 = 0x0000bd62,
+ },
+ .blackbird = 1,
+ },
+ [CX88_BOARD_IODATA_GVBCTV7E] = {
+ .name = "IODATA GV/BCTV7E",
+ .tuner_type = TUNER_PHILIPS_FQ1286,
+ .tda9887_conf = TDA9887_PRESENT,
+ .input = {{
+ .type = CX88_VMUX_TELEVISION,
+ .vmux = 1,
+ .gpio1 = 0x0000e03f,
+ },{
+ .type = CX88_VMUX_COMPOSITE1,
+ .vmux = 2,
+ .gpio1 = 0x0000e07f,
+ },{
+ .type = CX88_VMUX_SVIDEO,
+ .vmux = 3,
+ .gpio1 = 0x0000e07f,
+ }}
+ },
};
const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards);
@@ -482,11 +631,11 @@ struct cx88_subid cx88_subids[] = {
},{
.subvendor = 0x107d,
.subdevice = 0x6611,
- .card = CX88_BOARD_WINFAST2000XP,
+ .card = CX88_BOARD_WINFAST2000XP_EXPERT,
},{
.subvendor = 0x107d,
.subdevice = 0x6613, /* NTSC */
- .card = CX88_BOARD_WINFAST2000XP,
+ .card = CX88_BOARD_WINFAST2000XP_EXPERT,
},{
.subvendor = 0x107d,
.subdevice = 0x6620,
@@ -543,6 +692,30 @@ struct cx88_subid cx88_subids[] = {
.subvendor = 0x18AC,
.subdevice = 0xDB10,
.card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS,
+ },{
+ .subvendor = 0x1554,
+ .subdevice = 0x4811,
+ .card = CX88_BOARD_PIXELVIEW,
+ },{
+ .subvendor = 0x7063,
+ .subdevice = 0x3000, /* HD-3000 card */
+ .card = CX88_BOARD_PCHDTV_HD3000,
+ },{
+ .subvendor = 0x17DE,
+ .subdevice = 0xA8A6,
+ .card = CX88_BOARD_DNTV_LIVE_DVB_T,
+ },{
+ .subvendor = 0x0070,
+ .subdevice = 0x2801,
+ .card = CX88_BOARD_HAUPPAUGE_ROSLYN,
+ },{
+ .subvendor = 0x14F1,
+ .subdevice = 0x0342,
+ .card = CX88_BOARD_DIGITALLOGIC_MEC,
+ },{
+ .subvendor = 0x10fc,
+ .subdevice = 0xd035,
+ .card = CX88_BOARD_IODATA_GVBCTV7E,
}
};
const unsigned int cx88_idcount = ARRAY_SIZE(cx88_subids);
@@ -552,7 +725,7 @@ const unsigned int cx88_idcount = ARRAY_SIZE(cx88_subids);
static void __devinit leadtek_eeprom(struct cx88_core *core, u8 *eeprom_data)
{
- /* This is just for the Winfast 2000 XP board ATM; I don't have data on
+ /* This is just for the "Winfast 2000XP Expert" board ATM; I don't have data on
* any others.
*
* Byte 0 is 1 on the NTSC board.
@@ -569,108 +742,27 @@ static void __devinit leadtek_eeprom(struct cx88_core *core, u8 *eeprom_data)
core->has_radio = 1;
core->tuner_type = (eeprom_data[6] == 0x13) ? 43 : 38;
- printk(KERN_INFO "%s: Leadtek Winfast 2000 XP config: "
+ printk(KERN_INFO "%s: Leadtek Winfast 2000XP Expert config: "
"tuner=%d, eeprom[0]=0x%02x\n",
core->name, core->tuner_type, eeprom_data[0]);
}
/* ----------------------------------------------------------------------- */
-/* some hauppauge specific stuff */
-
-static struct {
- int id;
- char *name;
-} hauppauge_tuner[] __devinitdata = {
- { TUNER_ABSENT, "" },
- { TUNER_ABSENT, "External" },
- { TUNER_ABSENT, "Unspecified" },
- { TUNER_PHILIPS_PAL, "Philips FI1216" },
- { TUNER_PHILIPS_SECAM, "Philips FI1216MF" },
- { TUNER_PHILIPS_NTSC, "Philips FI1236" },
- { TUNER_PHILIPS_PAL_I, "Philips FI1246" },
- { TUNER_PHILIPS_PAL_DK,"Philips FI1256" },
- { TUNER_PHILIPS_PAL, "Philips FI1216 MK2" },
- { TUNER_PHILIPS_SECAM, "Philips FI1216MF MK2" },
- { TUNER_PHILIPS_NTSC, "Philips FI1236 MK2" },
- { TUNER_PHILIPS_PAL_I, "Philips FI1246 MK2" },
- { TUNER_PHILIPS_PAL_DK,"Philips FI1256 MK2" },
- { TUNER_TEMIC_NTSC, "Temic 4032FY5" },
- { TUNER_TEMIC_PAL, "Temic 4002FH5" },
- { TUNER_TEMIC_PAL_I, "Temic 4062FY5" },
- { TUNER_PHILIPS_PAL, "Philips FR1216 MK2" },
- { TUNER_PHILIPS_SECAM, "Philips FR1216MF MK2" },
- { TUNER_PHILIPS_NTSC, "Philips FR1236 MK2" },
- { TUNER_PHILIPS_PAL_I, "Philips FR1246 MK2" },
- { TUNER_PHILIPS_PAL_DK,"Philips FR1256 MK2" },
- { TUNER_PHILIPS_PAL, "Philips FM1216" },
- { TUNER_PHILIPS_SECAM, "Philips FM1216MF" },
- { TUNER_PHILIPS_NTSC, "Philips FM1236" },
- { TUNER_PHILIPS_PAL_I, "Philips FM1246" },
- { TUNER_PHILIPS_PAL_DK,"Philips FM1256" },
- { TUNER_TEMIC_4036FY5_NTSC, "Temic 4036FY5" },
- { TUNER_ABSENT, "Samsung TCPN9082D" },
- { TUNER_ABSENT, "Samsung TCPM9092P" },
- { TUNER_TEMIC_4006FH5_PAL, "Temic 4006FH5" },
- { TUNER_ABSENT, "Samsung TCPN9085D" },
- { TUNER_ABSENT, "Samsung TCPB9085P" },
- { TUNER_ABSENT, "Samsung TCPL9091P" },
- { TUNER_TEMIC_4039FR5_NTSC, "Temic 4039FR5" },
- { TUNER_PHILIPS_FQ1216ME, "Philips FQ1216 ME" },
- { TUNER_TEMIC_4066FY5_PAL_I, "Temic 4066FY5" },
- { TUNER_PHILIPS_NTSC, "Philips TD1536" },
- { TUNER_PHILIPS_NTSC, "Philips TD1536D" },
- { TUNER_PHILIPS_NTSC, "Philips FMR1236" }, /* mono radio */
- { TUNER_ABSENT, "Philips FI1256MP" },
- { TUNER_ABSENT, "Samsung TCPQ9091P" },
- { TUNER_TEMIC_4006FN5_MULTI_PAL, "Temic 4006FN5" },
- { TUNER_TEMIC_4009FR5_PAL, "Temic 4009FR5" },
- { TUNER_TEMIC_4046FM5, "Temic 4046FM5" },
- { TUNER_TEMIC_4009FN5_MULTI_PAL_FM, "Temic 4009FN5" },
- { TUNER_ABSENT, "Philips TD1536D_FH_44"},
- { TUNER_LG_NTSC_FM, "LG TPI8NSR01F"},
- { TUNER_LG_PAL_FM, "LG TPI8PSB01D"},
- { TUNER_LG_PAL, "LG TPI8PSB11D"},
- { TUNER_LG_PAL_I_FM, "LG TAPC-I001D"},
- { TUNER_LG_PAL_I, "LG TAPC-I701D"}
-};
static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data)
{
- unsigned int blk2,tuner,radio,model;
-
- if (eeprom_data[0] != 0x84 || eeprom_data[2] != 0) {
- printk(KERN_WARNING "%s: Hauppauge eeprom: invalid\n",
- core->name);
- return;
- }
-
- /* Block 2 starts after len+3 bytes header */
- blk2 = eeprom_data[1] + 3;
+ struct tveeprom tv;
- /* decode + use some config infos */
- model = eeprom_data[12] << 8 | eeprom_data[11];
- tuner = eeprom_data[9];
- radio = eeprom_data[blk2-1] & 0x01;
-
- if (tuner < ARRAY_SIZE(hauppauge_tuner))
- core->tuner_type = hauppauge_tuner[tuner].id;
- if (radio)
- core->has_radio = 1;
-
- printk(KERN_INFO "%s: hauppauge eeprom: model=%d, "
- "tuner=%s (%d), radio=%s\n",
- core->name, model, (tuner < ARRAY_SIZE(hauppauge_tuner)
- ? hauppauge_tuner[tuner].name : "?"),
- core->tuner_type, radio ? "yes" : "no");
+ tveeprom_hauppauge_analog(&tv, eeprom_data);
+ core->tuner_type = tv.tuner_type;
+ core->has_radio = tv.has_radio;
}
-#ifdef WITH_DVB
static int hauppauge_eeprom_dvb(struct cx88_core *core, u8 *ee)
{
int model;
int tuner;
- char *tname;
/* Make sure we support the board model */
model = ee[0x1f] << 24 | ee[0x1e] << 16 | ee[0x1d] << 8 | ee[0x1c];
@@ -689,26 +781,18 @@ static int hauppauge_eeprom_dvb(struct cx88_core *core, u8 *ee)
/* Make sure we support the tuner */
tuner = ee[0x2d];
switch(tuner) {
- case 0x4B:
- tname = "Thomson DTT 7595";
- core->pll_type = PLLTYPE_DTT7595;
- break;
- case 0x4C:
- tname = "Thomson DTT 7592";
- core->pll_type = PLLTYPE_DTT7592;
+ case 0x4B: /* dtt 7595 */
+ case 0x4C: /* dtt 7592 */
break;
default:
printk("%s: error: unknown hauppauge tuner 0x%02x\n",
core->name, tuner);
return -ENODEV;
}
- printk(KERN_INFO "%s: hauppauge eeprom: model=%d, tuner=%s (%d)\n",
- core->name, model, tname, tuner);
-
- core->pll_addr = 0x61;
- core->demod_addr = 0x43;
+ printk(KERN_INFO "%s: hauppauge eeprom: model=%d, tuner=%d\n",
+ core->name, model, tuner);
+ return 0;
}
-#endif
/* ----------------------------------------------------------------------- */
/* some GDI (was: Modular Technology) specific stuff */
@@ -763,36 +847,6 @@ static void gdi_eeprom(struct cx88_core *core, u8 *eeprom_data)
/* ----------------------------------------------------------------------- */
-static int
-i2c_eeprom(struct i2c_client *c, unsigned char *eedata, int len)
-{
- unsigned char buf;
- int err;
-
- c->addr = 0xa0 >> 1;
- buf = 0;
- if (1 != (err = i2c_master_send(c,&buf,1))) {
- printk(KERN_INFO "cx88: Huh, no eeprom present (err=%d)?\n",
- err);
- return -1;
- }
- if (len != (err = i2c_master_recv(c,eedata,len))) {
- printk(KERN_WARNING "cx88: i2c eeprom read error (err=%d)\n",
- err);
- return -1;
- }
-#if 0
- for (i = 0; i < len; i++) {
- if (0 == (i % 16))
- printk(KERN_INFO "cx88 ee: %02x:",i);
- printk(" %02x",eedata[i]);
- if (15 == (i % 16))
- printk("\n");
- }
-#endif
- return 0;
-}
-
void cx88_card_list(struct cx88_core *core, struct pci_dev *pci)
{
int i;
@@ -823,41 +877,46 @@ void cx88_card_setup(struct cx88_core *core)
{
static u8 eeprom[128];
+ if (0 == core->i2c_rc) {
+ core->i2c_client.addr = 0xa0 >> 1;
+ tveeprom_read(&core->i2c_client,eeprom,sizeof(eeprom));
+ }
+
switch (core->board) {
case CX88_BOARD_HAUPPAUGE:
+ case CX88_BOARD_HAUPPAUGE_ROSLYN:
if (0 == core->i2c_rc)
- i2c_eeprom(&core->i2c_client,eeprom,sizeof(eeprom));
- hauppauge_eeprom(core,eeprom+8);
+ hauppauge_eeprom(core,eeprom+8);
break;
case CX88_BOARD_GDI:
if (0 == core->i2c_rc)
- i2c_eeprom(&core->i2c_client,eeprom,sizeof(eeprom));
- gdi_eeprom(core,eeprom);
+ gdi_eeprom(core,eeprom);
break;
- case CX88_BOARD_WINFAST2000XP:
+ case CX88_BOARD_WINFAST2000XP_EXPERT:
if (0 == core->i2c_rc)
- i2c_eeprom(&core->i2c_client,eeprom,sizeof(eeprom));
- leadtek_eeprom(core,eeprom);
+ leadtek_eeprom(core,eeprom);
+ break;
+ case CX88_BOARD_HAUPPAUGE_DVB_T1:
+ if (0 == core->i2c_rc)
+ hauppauge_eeprom_dvb(core,eeprom);
break;
case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1:
- /* Tuner reset is hooked to the tuner out of reset */
+ case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS:
+ /* GPIO0:0 is hooked to mt352 reset pin */
cx_set(MO_GP0_IO, 0x00000101);
cx_clear(MO_GP0_IO, 0x00000001);
msleep(1);
cx_set(MO_GP0_IO, 0x00000101);
break;
-#ifdef WITH_DVB
- case CX88_BOARD_HAUPPAUGE_DVB_T1:
- if (0 == core->i2c_rc)
- i2c_eeprom(&core->i2c_client,eeprom,sizeof(eeprom));
- hauppauge_eeprom_dvb(core,eeprom);
- break;
- case CX88_BOARD_CONEXANT_DVB_T1:
- core->pll_type = PLLTYPE_DTT7579;
- core->pll_addr = 0x60;
- core->demod_addr = 0x43;
+ case CX88_BOARD_KWORLD_DVB_T:
+ case CX88_BOARD_DNTV_LIVE_DVB_T:
+ cx_set(MO_GP0_IO, 0x00000707);
+ cx_set(MO_GP2_IO, 0x00000101);
+ cx_clear(MO_GP2_IO, 0x00000001);
+ msleep(1);
+ cx_clear(MO_GP0_IO, 0x00000007);
+ cx_set(MO_GP2_IO, 0x00000101);
break;
-#endif
}
if (cx88_boards[core->board].radio.type == CX88_RADIO)
core->has_radio = 1;
diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c
index 3239c81ab29b7..26a6138015cb7 100644
--- a/drivers/media/video/cx88/cx88-core.c
+++ b/drivers/media/video/cx88/cx88-core.c
@@ -1,5 +1,5 @@
/*
- * $Id: cx88-core.c,v 1.15 2004/10/25 11:26:36 kraxel Exp $
+ * $Id: cx88-core.c,v 1.24 2005/01/19 12:01:55 kraxel Exp $
*
* device driver for Conexant 2388x based TV cards
* driver core
@@ -24,6 +24,7 @@
#include <linux/init.h>
#include <linux/list.h>
#include <linux/module.h>
+#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/kmod.h>
@@ -62,6 +63,10 @@ static unsigned int nicam = 0;
module_param(nicam,int,0644);
MODULE_PARM_DESC(nicam,"tv audio is nicam");
+static unsigned int nocomb = 0;
+module_param(nocomb,int,0644);
+MODULE_PARM_DESC(nocomb,"disable comb filter");
+
#define dprintk(level,fmt, arg...) if (core_debug >= level) \
printk(KERN_DEBUG "%s: " fmt, core->name , ## arg)
@@ -462,6 +467,7 @@ int cx88_risc_decode(u32 risc)
return incr[risc >> 28] ? incr[risc >> 28] : 1;
}
+#if 0 /* currently unused, but useful for debugging */
void cx88_risc_disasm(struct cx88_core *core,
struct btcx_riscmem *risc)
{
@@ -479,6 +485,7 @@ void cx88_risc_disasm(struct cx88_core *core,
break;
}
}
+#endif
void cx88_sram_channel_dump(struct cx88_core *core,
struct sram_channel *ch)
@@ -579,10 +586,19 @@ void cx88_print_irqbits(char *name, char *tag, char **strings,
/* ------------------------------------------------------------------ */
-void cx88_irq(struct cx88_core *core, u32 status, u32 mask)
+int cx88_core_irq(struct cx88_core *core, u32 status)
{
- cx88_print_irqbits(core->name, "irq pci",
- cx88_pci_irqs, status, mask);
+ int handled = 0;
+
+ if (status & (1<<18)) {
+ cx88_ir_irq(core);
+ handled++;
+ }
+ if (!handled)
+ cx88_print_irqbits(core->name, "irq pci",
+ cx88_pci_irqs, status,
+ core->pci_irqmask);
+ return handled;
}
void cx88_wakeup(struct cx88_core *core,
@@ -800,6 +816,8 @@ int cx88_set_scale(struct cx88_core *core, unsigned int width, unsigned int heig
value |= (1 << 0); // 3-tap interpolation
if (width < 193)
value |= (1 << 1); // 5-tap interpolation
+ if (nocomb)
+ value |= (3 << 5); // disable comb filter
cx_write(MO_FILTER_EVEN, value);
cx_write(MO_FILTER_ODD, value);
@@ -887,8 +905,8 @@ static int set_tvaudio(struct cx88_core *core)
cx88_set_tvaudio(core);
// cx88_set_stereo(dev,V4L2_TUNER_MODE_STEREO);
- cx_write(MO_AUDD_LNGTH, 128/8); /* fifo size */
- cx_write(MO_AUDR_LNGTH, 128/8); /* fifo size */
+ cx_write(MO_AUDD_LNGTH, 128); /* fifo size */
+ cx_write(MO_AUDR_LNGTH, 128); /* fifo size */
cx_write(MO_AUD_DMACNTRL, 0x03); /* need audio fifo */
return 0;
}
@@ -969,6 +987,9 @@ int cx88_set_tvnorm(struct cx88_core *core, struct cx88_tvnorm *norm)
cx_write(MO_VBI_PACKET, ((1 << 11) | /* (norm_vdelay(norm) << 11) | */
norm_vbipack(norm)));
+ // this is needed as well to set all tvnorm parameter
+ cx88_set_scale(core, 320, 240, V4L2_FIELD_INTERLACED);
+
// audio
set_tvaudio(core);
@@ -1105,9 +1126,10 @@ struct cx88_core* cx88_core_get(struct pci_dev *pci)
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);
- atomic_inc(&core->refcount);
+ core->pci_irqmask = 0x00fc00;
core->nr = cx88_devcount++;
sprintf(core->name,"cx88[%d]",core->nr);
@@ -1150,6 +1172,7 @@ struct cx88_core* cx88_core_get(struct pci_dev *pci)
cx88_reset(core);
cx88_i2c_init(core,pci);
cx88_card_setup(core);
+ cx88_ir_init(core,pci);
up(&devlist);
return core;
@@ -1170,6 +1193,7 @@ void cx88_core_put(struct cx88_core *core, struct pci_dev *pci)
return;
down(&devlist);
+ cx88_ir_fini(core);
if (0 == core->i2c_rc)
i2c_bit_del_bus(&core->i2c_adap);
list_del(&core->devlist);
@@ -1187,7 +1211,7 @@ EXPORT_SYMBOL(cx88_vid_irqs);
EXPORT_SYMBOL(cx88_mpeg_irqs);
EXPORT_SYMBOL(cx88_print_irqbits);
-EXPORT_SYMBOL(cx88_irq);
+EXPORT_SYMBOL(cx88_core_irq);
EXPORT_SYMBOL(cx88_wakeup);
EXPORT_SYMBOL(cx88_reset);
EXPORT_SYMBOL(cx88_shutdown);
@@ -1197,8 +1221,6 @@ EXPORT_SYMBOL(cx88_risc_databuffer);
EXPORT_SYMBOL(cx88_risc_stopper);
EXPORT_SYMBOL(cx88_free_buffer);
-EXPORT_SYMBOL(cx88_risc_disasm);
-
EXPORT_SYMBOL(cx88_sram_channels);
EXPORT_SYMBOL(cx88_sram_channel_setup);
EXPORT_SYMBOL(cx88_sram_channel_dump);
diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c
index 277a6d6e058b2..bc6f18c453574 100644
--- a/drivers/media/video/cx88/cx88-dvb.c
+++ b/drivers/media/video/cx88/cx88-dvb.c
@@ -1,5 +1,5 @@
/*
- * $Id: cx88-dvb.c,v 1.19 2004/11/07 14:44:59 kraxel Exp $
+ * $Id: cx88-dvb.c,v 1.31 2005/03/07 15:58:05 kraxel Exp $
*
* device driver for Conexant 2388x based TV cards
* MPEG Transport Stream (DVB) routines
@@ -30,10 +30,20 @@
#include <linux/file.h>
#include <linux/suspend.h>
+/* those two frontends need merging via linuxtv cvs ... */
+#define HAVE_CX22702 0
+#define HAVE_OR51132 1
+
#include "cx88.h"
-#include "cx22702.h"
+#include "dvb-pll.h"
#include "mt352.h"
-#include "mt352_priv.h" /* FIXME */
+#include "mt352_priv.h"
+#if HAVE_CX22702
+# include "cx22702.h"
+#endif
+#if HAVE_OR51132
+# include "or51132.h"
+#endif
MODULE_DESCRIPTION("driver for cx2388x based DVB cards");
MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>");
@@ -110,111 +120,144 @@ static int dvico_fusionhdtv_demod_init(struct dvb_frontend* fe)
return 0;
}
-#define IF_FREQUENCYx6 217 /* 6 * 36.16666666667MHz */
-
-static int lg_z201_pll_set(struct dvb_frontend* fe,
- struct dvb_frontend_parameters* params, u8* pllbuf)
+static int dntv_live_dvbt_demod_init(struct dvb_frontend* fe)
{
- u32 div;
- unsigned char cp = 0;
- unsigned char bs = 0;
-
- div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
+ static u8 clock_config [] = { 0x89, 0x38, 0x39 };
+ static u8 reset [] = { 0x50, 0x80 };
+ static u8 adc_ctl_1_cfg [] = { 0x8E, 0x40 };
+ static u8 agc_cfg [] = { 0x67, 0x10, 0x23, 0x00, 0xFF, 0xFF,
+ 0x00, 0xFF, 0x00, 0x40, 0x40 };
+ static u8 dntv_extra[] = { 0xB5, 0x7A };
+ static u8 capt_range_cfg[] = { 0x75, 0x32 };
- if (params->frequency < 542000000) cp = 0xbc;
- else if (params->frequency < 830000000) cp = 0xf4;
- else cp = 0xfc;
-
- if (params->frequency == 0) bs = 0x03;
- else if (params->frequency < 157500000) bs = 0x01;
- else if (params->frequency < 443250000) bs = 0x02;
- else bs = 0x04;
+ 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));
- pllbuf[0] = 0xC2; /* Note: non-linux standard PLL I2C address */
- pllbuf[1] = div >> 8;
- pllbuf[2] = div & 0xff;
- pllbuf[3] = cp;
- pllbuf[4] = bs;
+ 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 thomson_dtt7579_pll_set(struct dvb_frontend* fe,
- struct dvb_frontend_parameters* params,
- u8* pllbuf)
+static int mt352_pll_set(struct dvb_frontend* fe,
+ struct dvb_frontend_parameters* params,
+ u8* pllbuf)
{
- u32 div;
- unsigned char cp = 0;
- unsigned char bs = 0;
-
- div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
-
- if (params->frequency < 542000000) cp = 0xb4;
- else if (params->frequency < 771000000) cp = 0xbc;
- else cp = 0xf4;
-
- if (params->frequency == 0) bs = 0x03;
- else if (params->frequency < 443250000) bs = 0x02;
- else bs = 0x08;
-
- pllbuf[0] = 0xc0; // Note: non-linux standard PLL i2c address
- pllbuf[1] = div >> 8;
- pllbuf[2] = div & 0xff;
- pllbuf[3] = cp;
- pllbuf[4] = bs;
+ struct cx8802_dev *dev= fe->dvb->priv;
+ pllbuf[0] = dev->core->pll_addr << 1;
+ dvb_pll_configure(dev->core->pll_desc, pllbuf+1,
+ params->frequency,
+ params->u.ofdm.bandwidth);
return 0;
}
-struct mt352_config dvico_fusionhdtv_dvbt1 = {
+static struct mt352_config dvico_fusionhdtv = {
.demod_address = 0x0F,
.demod_init = dvico_fusionhdtv_demod_init,
- .pll_set = lg_z201_pll_set,
+ .pll_set = mt352_pll_set,
};
-struct mt352_config dvico_fusionhdtv_dvbt_plus = {
- .demod_address = 0x0F,
- .demod_init = dvico_fusionhdtv_demod_init,
- .pll_set = thomson_dtt7579_pll_set,
+static struct mt352_config dntv_live_dvbt_config = {
+ .demod_address = 0x0f,
+ .demod_init = dntv_live_dvbt_demod_init,
+ .pll_set = mt352_pll_set,
};
+#if HAVE_CX22702
+static struct cx22702_config connexant_refboard_config = {
+ .demod_address = 0x43,
+ .pll_address = 0x60,
+ .pll_desc = &dvb_pll_thomson_dtt7579,
+};
+
+static struct cx22702_config hauppauge_novat_config = {
+ .demod_address = 0x43,
+ .pll_address = 0x61,
+ .pll_desc = &dvb_pll_thomson_dtt759x,
+};
+#endif
+
+#if HAVE_OR51132
+static int or51132_set_ts_param(struct dvb_frontend* fe,
+ int is_punctured)
+{
+ struct cx8802_dev *dev= fe->dvb->priv;
+ dev->ts_gen_cntrl = is_punctured ? 0x04 : 0x00;
+ return 0;
+}
+
+struct or51132_config pchdtv_hd3000 = {
+ .demod_address = 0x15,
+ .pll_address = 0x61,
+ .pll_desc = &dvb_pll_thomson_dtt7610,
+ .set_ts_params = or51132_set_ts_param,
+};
+#endif
+
static int dvb_register(struct cx8802_dev *dev)
{
/* init struct videobuf_dvb */
dev->dvb.name = dev->core->name;
+ dev->ts_gen_cntrl = 0x0c;
/* init frontend */
switch (dev->core->board) {
+#if HAVE_CX22702
case CX88_BOARD_HAUPPAUGE_DVB_T1:
+ dev->dvb.frontend = cx22702_attach(&hauppauge_novat_config,
+ &dev->core->i2c_adap);
+ break;
case CX88_BOARD_CONEXANT_DVB_T1:
- dev->dvb.frontend = cx22702_create(&dev->core->i2c_adap,
- dev->core->pll_addr,
- dev->core->pll_type,
- dev->core->demod_addr);
+ dev->dvb.frontend = cx22702_attach(&connexant_refboard_config,
+ &dev->core->i2c_adap);
break;
+#endif
case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1:
- dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv_dvbt1,
+ dev->core->pll_addr = 0x61;
+ dev->core->pll_desc = &dvb_pll_lg_z201;
+ dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv,
&dev->core->i2c_adap);
- if (dev->dvb.frontend) {
- dev->dvb.frontend->ops->info.frequency_min = 174000000;
- dev->dvb.frontend->ops->info.frequency_max = 862000000;
- }
break;
case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS:
- dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv_dvbt_plus,
+ dev->core->pll_addr = 0x60;
+ dev->core->pll_desc = &dvb_pll_thomson_dtt7579;
+ dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv,
+ &dev->core->i2c_adap);
+ break;
+ case CX88_BOARD_KWORLD_DVB_T:
+ case CX88_BOARD_DNTV_LIVE_DVB_T:
+ dev->core->pll_addr = 0x61;
+ dev->core->pll_desc = &dvb_pll_unknown_1;
+ dev->dvb.frontend = mt352_attach(&dntv_live_dvbt_config,
+ &dev->core->i2c_adap);
+ break;
+#if HAVE_OR51132
+ case CX88_BOARD_PCHDTV_HD3000:
+ dev->dvb.frontend = or51132_attach(&pchdtv_hd3000,
&dev->core->i2c_adap);
- if (dev->dvb.frontend) {
- dev->dvb.frontend->ops->info.frequency_min = 174000000;
- dev->dvb.frontend->ops->info.frequency_max = 862000000;
- }
break;
+#endif
default:
- printk("%s: FIXME: frontend handling not here yet ...\n",
- dev->core->name);
+ printk("%s: The frontend of your DVB/ATSC card isn't supported yet\n"
+ "%s: you might want to look out for patches here:\n"
+ "%s: http://dl.bytesex.org/patches/\n",
+ dev->core->name, dev->core->name, dev->core->name);
break;
}
- if (NULL == dev->dvb.frontend)
+ if (NULL == dev->dvb.frontend) {
+ printk("%s: frontend initialization failed\n",dev->core->name);
return -1;
+ }
+
+ if (dev->core->pll_desc) {
+ dev->dvb.frontend->ops->info.frequency_min = dev->core->pll_desc->min;
+ dev->dvb.frontend->ops->info.frequency_max = dev->core->pll_desc->max;
+ }
/* Copy the board name into the DVB structure */
strlcpy(dev->dvb.frontend->ops->info.name,
@@ -222,7 +265,7 @@ static int dvb_register(struct cx8802_dev *dev)
sizeof(dev->dvb.frontend->ops->info.name));
/* register everything */
- return videobuf_dvb_register(&dev->dvb);
+ return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev);
}
/* ----------------------------------------------------------- */
@@ -319,7 +362,7 @@ static int dvb_init(void)
printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n",
SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100);
#endif
- return pci_module_init(&dvb_pci_driver);
+ return pci_register_driver(&dvb_pci_driver);
}
static void dvb_fini(void)
diff --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c
index 36b0dbb494551..60800172c0261 100644
--- a/drivers/media/video/cx88/cx88-i2c.c
+++ b/drivers/media/video/cx88/cx88-i2c.c
@@ -1,5 +1,5 @@
/*
- $Id: cx88-i2c.c,v 1.18 2004/10/13 10:39:00 kraxel Exp $
+ $Id: cx88-i2c.c,v 1.20 2005/02/15 15:59:35 kraxel Exp $
cx88-i2c.c -- all the i2c code is here
@@ -25,6 +25,7 @@
*/
#include <linux/module.h>
+#include <linux/moduleparam.h>
#include <linux/init.h>
#include <asm/io.h>
@@ -141,7 +142,6 @@ static struct i2c_adapter cx8800_i2c_adap_template = {
static struct i2c_client cx8800_i2c_client_template = {
I2C_DEVNAME("cx88xx internal"),
- .id = -1,
};
static char *i2c_devs[128] = {
diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c
new file mode 100644
index 0000000000000..af6ad8cdbdb77
--- /dev/null
+++ b/drivers/media/video/cx88/cx88-input.c
@@ -0,0 +1,396 @@
+/*
+ * $Id: cx88-input.c,v 1.9 2005/03/04 09:12:23 kraxel Exp $
+ *
+ * Device driver for GPIO attached remote control interfaces
+ * on Conexant 2388x based TV/DVB cards.
+ *
+ * Copyright (c) 2003 Pavel Machek
+ * Copyright (c) 2004 Gerd Knorr
+ * Copyright (c) 2004 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the 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/delay.h>
+#include <linux/input.h>
+#include <linux/pci.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+
+#include <media/ir-common.h>
+
+#include "cx88.h"
+
+/* ---------------------------------------------------------------------- */
+
+/* DigitalNow DNTV Live DVB-T Remote */
+static IR_KEYTAB_TYPE ir_codes_dntv_live_dvb_t[IR_KEYTAB_SIZE] = {
+ [ 0x00 ] = KEY_ESC, // 'go up a level?'
+ [ 0x01 ] = KEY_KP1, // '1'
+ [ 0x02 ] = KEY_KP2, // '2'
+ [ 0x03 ] = KEY_KP3, // '3'
+ [ 0x04 ] = KEY_KP4, // '4'
+ [ 0x05 ] = KEY_KP5, // '5'
+ [ 0x06 ] = KEY_KP6, // '6'
+ [ 0x07 ] = KEY_KP7, // '7'
+ [ 0x08 ] = KEY_KP8, // '8'
+ [ 0x09 ] = KEY_KP9, // '9'
+ [ 0x0a ] = KEY_KP0, // '0'
+ [ 0x0b ] = KEY_TUNER, // 'tv/fm'
+ [ 0x0c ] = KEY_SEARCH, // 'scan'
+ [ 0x0d ] = KEY_STOP, // 'stop'
+ [ 0x0e ] = KEY_PAUSE, // 'pause'
+ [ 0x0f ] = KEY_LIST, // 'source'
+
+ [ 0x10 ] = KEY_MUTE, // 'mute'
+ [ 0x11 ] = KEY_REWIND, // 'backward <<'
+ [ 0x12 ] = KEY_POWER, // 'power'
+ [ 0x13 ] = KEY_S, // 'snap'
+ [ 0x14 ] = KEY_AUDIO, // 'stereo'
+ [ 0x15 ] = KEY_CLEAR, // 'reset'
+ [ 0x16 ] = KEY_PLAY, // 'play'
+ [ 0x17 ] = KEY_ENTER, // 'enter'
+ [ 0x18 ] = KEY_ZOOM, // 'full screen'
+ [ 0x19 ] = KEY_FASTFORWARD, // 'forward >>'
+ [ 0x1a ] = KEY_CHANNELUP, // 'channel +'
+ [ 0x1b ] = KEY_VOLUMEUP, // 'volume +'
+ [ 0x1c ] = KEY_INFO, // 'preview'
+ [ 0x1d ] = KEY_RECORD, // 'record'
+ [ 0x1e ] = KEY_CHANNELDOWN, // 'channel -'
+ [ 0x1f ] = KEY_VOLUMEDOWN, // 'volume -'
+};
+
+/* ---------------------------------------------------------------------- */
+
+/* IO-DATA BCTV7E Remote */
+static IR_KEYTAB_TYPE ir_codes_iodata_bctv7e[IR_KEYTAB_SIZE] = {
+ [ 0x40 ] = KEY_TV, // TV
+ [ 0x20 ] = KEY_RADIO, // FM
+ [ 0x60 ] = KEY_EPG, // EPG
+ [ 0x00 ] = KEY_POWER, // power
+
+ [ 0x50 ] = KEY_KP1, // 1
+ [ 0x30 ] = KEY_KP2, // 2
+ [ 0x70 ] = KEY_KP3, // 3
+ [ 0x10 ] = KEY_L, // Live
+
+ [ 0x48 ] = KEY_KP4, // 4
+ [ 0x28 ] = KEY_KP5, // 5
+ [ 0x68 ] = KEY_KP6, // 6
+ [ 0x08 ] = KEY_T, // Time Shift
+
+ [ 0x58 ] = KEY_KP7, // 7
+ [ 0x38 ] = KEY_KP8, // 8
+ [ 0x78 ] = KEY_KP9, // 9
+ [ 0x18 ] = KEY_PLAYPAUSE, // Play
+
+ [ 0x44 ] = KEY_KP0, // 10
+ [ 0x24 ] = KEY_ENTER, // 11
+ [ 0x64 ] = KEY_ESC, // 12
+ [ 0x04 ] = KEY_M, // Multi
+
+ [ 0x54 ] = KEY_VIDEO, // VIDEO
+ [ 0x34 ] = KEY_CHANNELUP, // channel +
+ [ 0x74 ] = KEY_VOLUMEUP, // volume +
+ [ 0x14 ] = KEY_MUTE, // Mute
+
+ [ 0x4c ] = KEY_S, // SVIDEO
+ [ 0x2c ] = KEY_CHANNELDOWN, // channel -
+ [ 0x6c ] = KEY_VOLUMEDOWN, // volume -
+ [ 0x0c ] = KEY_ZOOM, // Zoom
+
+ [ 0x5c ] = KEY_PAUSE, // pause
+ [ 0x3c ] = KEY_C, // || (red)
+ [ 0x7c ] = KEY_RECORD, // recording
+ [ 0x1c ] = KEY_STOP, // stop
+
+ [ 0x41 ] = KEY_REWIND, // backward <<
+ [ 0x21 ] = KEY_PLAY, // play
+ [ 0x61 ] = KEY_FASTFORWARD, // forward >>
+ [ 0x01 ] = KEY_NEXT, // skip >|
+};
+
+/* ---------------------------------------------------------------------- */
+
+struct cx88_IR {
+ struct cx88_core *core;
+ struct input_dev input;
+ struct ir_input_state ir;
+ char name[32];
+ char phys[32];
+
+ /* sample from gpio pin 16 */
+ int sampling;
+ u32 samples[16];
+ int scount;
+ unsigned long release;
+
+ /* poll external decoder */
+ int polling;
+ struct work_struct work;
+ struct timer_list timer;
+ u32 gpio_addr;
+ u32 last_gpio;
+ u32 mask_keycode;
+ u32 mask_keydown;
+ u32 mask_keyup;
+};
+
+static int ir_debug = 0;
+module_param(ir_debug, int, 0644); /* debug level [IR] */
+MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]");
+
+#define ir_dprintk(fmt, arg...) if (ir_debug) \
+ printk(KERN_DEBUG "%s IR: " fmt , ir->core->name, ## arg)
+
+/* ---------------------------------------------------------------------- */
+
+static void cx88_ir_handle_key(struct cx88_IR *ir)
+{
+ struct cx88_core *core = ir->core;
+ u32 gpio, data;
+
+ /* read gpio value */
+ gpio = cx_read(ir->gpio_addr);
+ if (ir->polling) {
+ if (ir->last_gpio == gpio)
+ return;
+ ir->last_gpio = gpio;
+ }
+
+ /* extract data */
+ data = ir_extract_bits(gpio, ir->mask_keycode);
+ ir_dprintk("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);
+ }
+
+ } else {
+ /* can't distinguish keydown/up :-/ */
+ ir_input_keydown(&ir->input,&ir->ir,data,data);
+ ir_input_nokey(&ir->input,&ir->ir);
+ }
+}
+
+static void ir_timer(unsigned long data)
+{
+ struct cx88_IR *ir = (struct cx88_IR*)data;
+
+ schedule_work(&ir->work);
+}
+
+static void cx88_ir_work(void *data)
+{
+ struct cx88_IR *ir = data;
+ unsigned long timeout;
+
+ cx88_ir_handle_key(ir);
+ timeout = jiffies + (ir->polling * HZ / 1000);
+ mod_timer(&ir->timer, timeout);
+}
+
+/* ---------------------------------------------------------------------- */
+
+int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
+{
+ struct cx88_IR *ir;
+ IR_KEYTAB_TYPE *ir_codes = NULL;
+ int ir_type = IR_TYPE_OTHER;
+
+ ir = kmalloc(sizeof(*ir),GFP_KERNEL);
+ if (NULL == ir)
+ return -ENOMEM;
+ memset(ir,0,sizeof(*ir));
+
+ /* detect & configure */
+ switch (core->board) {
+ case CX88_BOARD_DNTV_LIVE_DVB_T:
+ ir_codes = ir_codes_dntv_live_dvb_t;
+ ir->gpio_addr = MO_GP1_IO;
+ ir->mask_keycode = 0x1f;
+ ir->mask_keyup = 0x60;
+ ir->polling = 50; // ms
+ break;
+ case CX88_BOARD_HAUPPAUGE:
+ case CX88_BOARD_HAUPPAUGE_DVB_T1:
+ ir_codes = ir_codes_hauppauge_new;
+ ir_type = IR_TYPE_RC5;
+ ir->sampling = 1;
+ break;
+ case CX88_BOARD_WINFAST2000XP_EXPERT:
+ ir_codes = ir_codes_winfast;
+ ir->gpio_addr = MO_GP0_IO;
+ ir->mask_keycode = 0x8f8;
+ ir->mask_keyup = 0x100;
+ ir->polling = 1; // ms
+ break;
+ case CX88_BOARD_IODATA_GVBCTV7E:
+ ir_codes = ir_codes_iodata_bctv7e;
+ ir->gpio_addr = MO_GP0_IO;
+ ir->mask_keycode = 0xfd;
+ ir->mask_keydown = 0x02;
+ ir->polling = 5; // ms
+ break;
+ }
+ if (NULL == ir_codes) {
+ kfree(ir);
+ return -ENODEV;
+ }
+
+ /* init input device */
+ snprintf(ir->name, sizeof(ir->name), "cx88 IR (%s)",
+ cx88_boards[core->board].name);
+ snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0",
+ pci_name(pci));
+
+ ir_input_init(&ir->input, &ir->ir, ir_type, ir_codes);
+ ir->input.name = ir->name;
+ ir->input.phys = ir->phys;
+ ir->input.id.bustype = BUS_PCI;
+ ir->input.id.version = 1;
+ if (pci->subsystem_vendor) {
+ ir->input.id.vendor = pci->subsystem_vendor;
+ ir->input.id.product = pci->subsystem_device;
+ } else {
+ ir->input.id.vendor = pci->vendor;
+ ir->input.id.product = pci->device;
+ }
+
+ /* record handles to ourself */
+ ir->core = core;
+ core->ir = ir;
+
+ if (ir->polling) {
+ INIT_WORK(&ir->work, cx88_ir_work, ir);
+ init_timer(&ir->timer);
+ ir->timer.function = ir_timer;
+ ir->timer.data = (unsigned long)ir;
+ schedule_work(&ir->work);
+ }
+ if (ir->sampling) {
+ core->pci_irqmask |= (1<<18); // IR_SMP_INT
+ cx_write(MO_DDS_IO, 0xa80a80); // 4 kHz sample rate
+ cx_write(MO_DDSCFG_IO, 0x5); // enable
+ }
+
+ /* all done */
+ input_register_device(&ir->input);
+ printk("%s: registered IR remote control\n", core->name);
+
+ return 0;
+}
+
+int cx88_ir_fini(struct cx88_core *core)
+{
+ struct cx88_IR *ir = core->ir;
+
+ /* skip detach on non attached boards */
+ if (NULL == ir)
+ return 0;
+
+ if (ir->polling) {
+ del_timer(&ir->timer);
+ flush_scheduled_work();
+ }
+
+ input_unregister_device(&ir->input);
+ kfree(ir);
+
+ /* done */
+ core->ir = NULL;
+ return 0;
+}
+
+/* ---------------------------------------------------------------------- */
+
+void cx88_ir_irq(struct cx88_core *core)
+{
+ struct cx88_IR *ir = core->ir;
+ u32 samples,rc5;
+ int i;
+
+ if (NULL == ir)
+ return;
+ if (!ir->sampling)
+ return;
+
+ samples = cx_read(MO_SAMPLE_IO);
+ if (0 != samples && 0xffffffff != samples) {
+ /* record sample data */
+ if (ir->scount < ARRAY_SIZE(ir->samples))
+ ir->samples[ir->scount++] = samples;
+ return;
+ }
+ if (!ir->scount) {
+ /* nothing to sample */
+ if (ir->ir.keypressed && time_after(jiffies,ir->release))
+ ir_input_nokey(&ir->input,&ir->ir);
+ return;
+ }
+
+ /* have a complete sample */
+ if (ir->scount < ARRAY_SIZE(ir->samples))
+ ir->samples[ir->scount++] = samples;
+ for (i = 0; i < ir->scount; i++)
+ ir->samples[i] = ~ir->samples[i];
+ if (ir_debug)
+ ir_dump_samples(ir->samples,ir->scount);
+
+ /* decode it */
+ switch (core->board) {
+ case CX88_BOARD_HAUPPAUGE:
+ case CX88_BOARD_HAUPPAUGE_DVB_T1:
+ rc5 = ir_decode_biphase(ir->samples,ir->scount,5,7);
+ ir_dprintk("biphase decoded: %x\n",rc5);
+ if ((rc5 & 0xfffff000) != 0x3000)
+ break;
+ ir_input_keydown(&ir->input, &ir->ir, rc5 & 0x3f, rc5);
+ ir->release = jiffies + msecs_to_jiffies(120);
+ break;
+ }
+
+ ir->scount = 0;
+ return;
+}
+
+/* ---------------------------------------------------------------------- */
+
+MODULE_AUTHOR("Gerd Knorr, Pavel Machek, Chris Pascoe");
+MODULE_DESCRIPTION("input driver for cx88 GPIO-based IR remote controls");
+MODULE_LICENSE("GPL");
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c
index 3045b4b62eab3..07aae1899e17a 100644
--- a/drivers/media/video/cx88/cx88-mpeg.c
+++ b/drivers/media/video/cx88/cx88-mpeg.c
@@ -1,5 +1,5 @@
/*
- * $Id: cx88-mpeg.c,v 1.14 2004/10/25 11:26:36 kraxel Exp $
+ * $Id: cx88-mpeg.c,v 1.25 2005/03/07 14:18:00 kraxel Exp $
*
* Support for the mpeg transport stream transfers
* PCI function #2 of the cx2388x.
@@ -24,6 +24,7 @@
*/
#include <linux/module.h>
+#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/interrupt.h>
@@ -68,8 +69,14 @@ static int cx8802_start_dma(struct cx8802_dev *dev,
* also: move to cx88-blackbird + cx88-dvb source files? */
if (cx88_boards[core->board].dvb) {
- /* Setup TS portion of chip */
- cx_write(TS_GEN_CNTRL, 0x0c);
+ /* negedge driven & software reset */
+ cx_write(TS_GEN_CNTRL, 0x40);
+ udelay(100);
+ cx_write(MO_PINMUX_IO, 0x00);
+ cx_write(TS_HW_SOP_CNTRL,47<<16|188<<4|0x00);
+ cx_write(TS_SOP_STAT,0x00);
+ cx_write(TS_GEN_CNTRL, dev->ts_gen_cntrl);
+ udelay(100);
}
if (cx88_boards[core->board].blackbird) {
@@ -93,7 +100,7 @@ static int cx8802_start_dma(struct cx8802_dev *dev,
q->count = 1;
/* enable irqs */
- cx_set(MO_PCI_INTMSK, 0x00fc04);
+ cx_set(MO_PCI_INTMSK, core->pci_irqmask | 0x04);
cx_write(MO_TS_INTMSK, 0x1f0011);
/* start dma */
@@ -292,19 +299,18 @@ static irqreturn_t cx8802_irq(int irq, void *dev_id, struct pt_regs *regs)
{
struct cx8802_dev *dev = dev_id;
struct cx88_core *core = dev->core;
- u32 status, mask;
+ u32 status;
int loop, handled = 0;
for (loop = 0; loop < 10; loop++) {
- status = cx_read(MO_PCI_INTSTAT) & (~0x1f | 0x04);
- mask = cx_read(MO_PCI_INTMSK);
- if (0 == (status & mask))
+ status = cx_read(MO_PCI_INTSTAT) & (core->pci_irqmask | 0x04);
+ if (0 == status)
goto out;
handled = 1;
cx_write(MO_PCI_INTSTAT, status);
- if (status & mask & ~0x1f)
- cx88_irq(core,status,mask);
+ if (status & core->pci_irqmask)
+ cx88_core_irq(core,status);
if (status & 0x04)
cx8802_mpeg_irq(dev);
};
@@ -323,6 +329,7 @@ static irqreturn_t cx8802_irq(int irq, void *dev_id, struct pt_regs *regs)
int cx8802_init_common(struct cx8802_dev *dev)
{
+ struct cx88_core *core = dev->core;
int err;
/* pci init */
@@ -354,11 +361,6 @@ int cx8802_init_common(struct cx8802_dev *dev)
cx88_risc_stopper(dev->pci,&dev->mpegq.stopper,
MO_TS_DMACNTRL,0x11,0x00);
-#if 0 /* FIXME */
- /* initialize hardware */
- cx8802_reset(dev);
-#endif
-
/* get irq */
err = request_irq(dev->pci->irq, cx8802_irq,
SA_SHIRQ | SA_INTERRUPT, dev->core->name, dev);
@@ -367,11 +369,7 @@ int cx8802_init_common(struct cx8802_dev *dev)
dev->core->name, dev->pci->irq);
return err;
}
-
-#if 0 /* FIXME */
- /* register i2c bus + load i2c helpers */
- cx88_card_setup(dev);
-#endif
+ cx_set(MO_PCI_INTMSK, core->pci_irqmask);
/* everything worked */
pci_set_drvdata(dev->pci,dev);
@@ -393,7 +391,7 @@ void cx8802_fini_common(struct cx8802_dev *dev)
/* ----------------------------------------------------------- */
-int cx8802_suspend_common(struct pci_dev *pci_dev, u32 state)
+int cx8802_suspend_common(struct pci_dev *pci_dev, pm_message_t state)
{
struct cx8802_dev *dev = pci_get_drvdata(pci_dev);
struct cx88_core *core = dev->core;
@@ -413,7 +411,7 @@ int cx8802_suspend_common(struct pci_dev *pci_dev, u32 state)
#endif
pci_save_state(pci_dev);
- if (0 != pci_set_power_state(pci_dev, state)) {
+ if (0 != pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state))) {
pci_disable_device(pci_dev);
dev->state.disabled = 1;
}
@@ -429,7 +427,7 @@ int cx8802_resume_common(struct pci_dev *pci_dev)
pci_enable_device(pci_dev);
dev->state.disabled = 0;
}
- pci_set_power_state(pci_dev, 0);
+ pci_set_power_state(pci_dev, PCI_D0);
pci_restore_state(pci_dev);
#if 1
diff --git a/drivers/media/video/cx88/cx88-tvaudio.c b/drivers/media/video/cx88/cx88-tvaudio.c
index 874d2974d5e60..f2a9475a2feef 100644
--- a/drivers/media/video/cx88/cx88-tvaudio.c
+++ b/drivers/media/video/cx88/cx88-tvaudio.c
@@ -1,5 +1,5 @@
/*
- $Id: cx88-tvaudio.c,v 1.24 2004/10/25 11:51:00 kraxel Exp $
+ $Id: cx88-tvaudio.c,v 1.34 2005/03/07 16:10:51 kraxel Exp $
cx88x-audio.c - Conexant CX23880/23881 audio downstream driver driver
@@ -37,6 +37,7 @@
*/
#include <linux/module.h>
+#include <linux/moduleparam.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/slab.h>
@@ -56,7 +57,7 @@
#include "cx88.h"
-static unsigned int audio_debug = 1;
+static unsigned int audio_debug = 0;
module_param(audio_debug,int,0644);
MODULE_PARM_DESC(audio_debug,"enable debug messages [audio]");
@@ -141,6 +142,13 @@ static void set_audio_finish(struct cx88_core *core)
{
u32 volume;
+ if (cx88_boards[core->board].blackbird) {
+ // 'pass-thru mode': this enables the i2s output to the mpeg encoder
+ cx_set(AUD_CTL, 0x2000);
+ cx_write(AUD_I2SOUTPUTCNTL, 1);
+ //cx_write(AUD_APB_IN_RATE_ADJ, 0);
+ }
+
// finish programming
cx_write(AUD_SOFT_RESET, 0x0000);
@@ -263,6 +271,7 @@ static void set_audio_standard_BTSC(struct cx88_core *core, unsigned int sap)
set_audio_finish(core);
}
+#if 0
static void set_audio_standard_NICAM(struct cx88_core *core)
{
static const struct rlist nicam_common[] = {
@@ -335,128 +344,243 @@ static void set_audio_standard_NICAM(struct cx88_core *core)
};
set_audio_finish(core);
}
+#endif
-static void set_audio_standard_NICAM_L(struct cx88_core *core)
+static void set_audio_standard_NICAM_L(struct cx88_core *core, int stereo)
{
- /* This is officially weird.. register dumps indicate windows
- * uses audio mode 4.. A2. Let's operate and find out. */
+ /* This is probably weird..
+ * Let's operate and find out. */
+
+ static const struct rlist nicam_l_mono[] = {
+ { AUD_ERRLOGPERIOD_R, 0x00000064 },
+ { AUD_ERRINTRPTTHSHLD1_R, 0x00000FFF },
+ { AUD_ERRINTRPTTHSHLD2_R, 0x0000001F },
+ { AUD_ERRINTRPTTHSHLD3_R, 0x0000000F },
+
+ { AUD_PDF_DDS_CNST_BYTE2, 0x48 },
+ { AUD_PDF_DDS_CNST_BYTE1, 0x3D },
+ { AUD_QAM_MODE, 0x00 },
+ { AUD_PDF_DDS_CNST_BYTE0, 0xf5 },
+ { AUD_PHACC_FREQ_8MSB, 0x3a },
+ { AUD_PHACC_FREQ_8LSB, 0x4a },
+
+ { AUD_DEEMPHGAIN_R, 0x6680 },
+ { AUD_DEEMPHNUMER1_R, 0x353DE },
+ { AUD_DEEMPHNUMER2_R, 0x1B1 },
+ { AUD_DEEMPHDENOM1_R, 0x0F3D0 },
+ { AUD_DEEMPHDENOM2_R, 0x0 },
+ { AUD_FM_MODE_ENABLE, 0x7 },
+ { AUD_POLYPH80SCALEFAC, 0x3 },
+ { AUD_AFE_12DB_EN, 0x1 },
+ { AAGC_GAIN, 0x0 },
+ { AAGC_HYST, 0x18 },
+ { AAGC_DEF, 0x20 },
+ { AUD_DN0_FREQ, 0x0 },
+ { AUD_POLY0_DDS_CONSTANT, 0x0E4DB2 },
+ { AUD_DCOC_0_SRC, 0x21 },
+ { AUD_IIR1_0_SEL, 0x0 },
+ { AUD_IIR1_0_SHIFT, 0x7 },
+ { AUD_IIR1_1_SEL, 0x2 },
+ { AUD_IIR1_1_SHIFT, 0x0 },
+ { AUD_DCOC_1_SRC, 0x3 },
+ { AUD_DCOC1_SHIFT, 0x0 },
+ { AUD_DCOC_PASS_IN, 0x0 },
+ { AUD_IIR1_2_SEL, 0x23 },
+ { AUD_IIR1_2_SHIFT, 0x0 },
+ { AUD_IIR1_3_SEL, 0x4 },
+ { AUD_IIR1_3_SHIFT, 0x7 },
+ { AUD_IIR1_4_SEL, 0x5 },
+ { AUD_IIR1_4_SHIFT, 0x7 },
+ { AUD_IIR3_0_SEL, 0x7 },
+ { AUD_IIR3_0_SHIFT, 0x0 },
+ { AUD_DEEMPH0_SRC_SEL, 0x11 },
+ { AUD_DEEMPH0_SHIFT, 0x0 },
+ { AUD_DEEMPH0_G0, 0x7000 },
+ { AUD_DEEMPH0_A0, 0x0 },
+ { AUD_DEEMPH0_B0, 0x0 },
+ { AUD_DEEMPH0_A1, 0x0 },
+ { AUD_DEEMPH0_B1, 0x0 },
+ { AUD_DEEMPH1_SRC_SEL, 0x11 },
+ { AUD_DEEMPH1_SHIFT, 0x0 },
+ { AUD_DEEMPH1_G0, 0x7000 },
+ { AUD_DEEMPH1_A0, 0x0 },
+ { AUD_DEEMPH1_B0, 0x0 },
+ { AUD_DEEMPH1_A1, 0x0 },
+ { AUD_DEEMPH1_B1, 0x0 },
+ { AUD_OUT0_SEL, 0x3F },
+ { AUD_OUT1_SEL, 0x3F },
+ { AUD_DMD_RA_DDS, 0x0F5C285 },
+ { AUD_PLL_INT, 0x1E },
+ { AUD_PLL_DDS, 0x0 },
+ { AUD_PLL_FRAC, 0x0E542 },
+
+ // setup QAM registers
+ { AUD_RATE_ADJ1, 0x00000100 },
+ { AUD_RATE_ADJ2, 0x00000200 },
+ { AUD_RATE_ADJ3, 0x00000300 },
+ { AUD_RATE_ADJ4, 0x00000400 },
+ { AUD_RATE_ADJ5, 0x00000500 },
+ { AUD_RATE_THRES_DMD, 0x000000C0 },
+ { /* end of list */ },
+ };
- static const struct rlist nicam_l[] = {
- // setup QAM registers
- { AUD_PDF_DDS_CNST_BYTE2, 0x48 },
- { AUD_PDF_DDS_CNST_BYTE1, 0x3d },
- { AUD_PDF_DDS_CNST_BYTE0, 0xf5 },
- { AUD_QAM_MODE, 0x00 },
- { AUD_PHACC_FREQ_8MSB, 0x3a },
- { AUD_PHACC_FREQ_8LSB, 0x4a },
-
- { AUD_POLY0_DDS_CONSTANT, 0x000e4db2 },
- { AUD_IIR1_0_SEL, 0x00000000 },
- { AUD_IIR1_1_SEL, 0x00000002 },
- { AUD_IIR1_2_SEL, 0x00000023 },
- { AUD_IIR1_3_SEL, 0x00000004 },
- { AUD_IIR1_4_SEL, 0x00000005 },
- { AUD_IIR1_5_SEL, 0x00000007 },
- { AUD_IIR1_0_SHIFT, 0x00000007 },
- { AUD_IIR1_1_SHIFT, 0x00000000 },
- { AUD_IIR1_2_SHIFT, 0x00000000 },
- { AUD_IIR1_3_SHIFT, 0x00000007 },
- { AUD_IIR1_4_SHIFT, 0x00000007 },
- { AUD_IIR1_5_SHIFT, 0x00000007 },
- { AUD_IIR2_0_SEL, 0x00000002 },
- { AUD_IIR2_1_SEL, 0x00000003 },
- { AUD_IIR2_2_SEL, 0x00000004 },
- { AUD_IIR2_3_SEL, 0x00000005 },
- { AUD_IIR3_0_SEL, 0x00000007 },
- { AUD_IIR3_1_SEL, 0x00000023 },
- { AUD_IIR3_2_SEL, 0x00000016 },
- { AUD_IIR4_0_SHIFT, 0x00000000 },
- { AUD_IIR4_1_SHIFT, 0x00000000 },
- { AUD_IIR3_2_SHIFT, 0x00000002 },
- { AUD_IIR4_0_SEL, 0x0000001d },
- { AUD_IIR4_1_SEL, 0x00000019 },
- { AUD_IIR4_2_SEL, 0x00000008 },
- { AUD_IIR4_0_SHIFT, 0x00000000 },
- { AUD_IIR4_1_SHIFT, 0x00000007 },
- { AUD_IIR4_2_SHIFT, 0x00000007 },
- { AUD_IIR4_0_CA0, 0x0003e57e },
- { AUD_IIR4_0_CA1, 0x00005e11 },
- { AUD_IIR4_0_CA2, 0x0003a7cf },
- { AUD_IIR4_0_CB0, 0x00002368 },
- { AUD_IIR4_0_CB1, 0x0003bf1b },
- { AUD_IIR4_1_CA0, 0x00006349 },
- { AUD_IIR4_1_CA1, 0x00006f27 },
- { AUD_IIR4_1_CA2, 0x0000e7a3 },
- { AUD_IIR4_1_CB0, 0x00005653 },
- { AUD_IIR4_1_CB1, 0x0000cf97 },
- { AUD_IIR4_2_CA0, 0x00006349 },
- { AUD_IIR4_2_CA1, 0x00006f27 },
- { AUD_IIR4_2_CA2, 0x0000e7a3 },
- { AUD_IIR4_2_CB0, 0x00005653 },
- { AUD_IIR4_2_CB1, 0x0000cf97 },
- { AUD_HP_MD_IIR4_1, 0x00000001 },
- { AUD_HP_PROG_IIR4_1, 0x0000001a },
- { AUD_DN0_FREQ, 0x00000000 },
- { AUD_DN1_FREQ, 0x00003318 },
- { AUD_DN1_SRC_SEL, 0x00000017 },
- { AUD_DN1_SHFT, 0x00000007 },
- { AUD_DN1_AFC, 0x00000000 },
- { AUD_DN1_FREQ_SHIFT, 0x00000000 },
- { AUD_DN2_FREQ, 0x00003551 },
- { AUD_DN2_SRC_SEL, 0x00000001 },
- { AUD_DN2_SHFT, 0x00000000 },
- { AUD_DN2_AFC, 0x00000002 },
- { AUD_DN2_FREQ_SHIFT, 0x00000000 },
- { AUD_PDET_SRC, 0x00000014 },
- { AUD_PDET_SHIFT, 0x00000000 },
- { AUD_DEEMPH0_SRC_SEL, 0x00000011 },
- { AUD_DEEMPH1_SRC_SEL, 0x00000011 },
- { AUD_DEEMPH0_SHIFT, 0x00000000 },
- { AUD_DEEMPH1_SHIFT, 0x00000000 },
- { AUD_DEEMPH0_G0, 0x00007000 },
- { AUD_DEEMPH0_A0, 0x00000000 },
- { AUD_DEEMPH0_B0, 0x00000000 },
- { AUD_DEEMPH0_A1, 0x00000000 },
- { AUD_DEEMPH0_B1, 0x00000000 },
- { AUD_DEEMPH1_G0, 0x00007000 },
- { AUD_DEEMPH1_A0, 0x00000000 },
- { AUD_DEEMPH1_B0, 0x00000000 },
- { AUD_DEEMPH1_A1, 0x00000000 },
- { AUD_DEEMPH1_B1, 0x00000000 },
- { AUD_DMD_RA_DDS, 0x00f5c285 },
- { AUD_RATE_ADJ1, 0x00000100 },
- { AUD_RATE_ADJ2, 0x00000200 },
- { AUD_RATE_ADJ3, 0x00000300 },
- { AUD_RATE_ADJ4, 0x00000400 },
- { AUD_RATE_ADJ5, 0x00000500 },
- { AUD_C2_UP_THR, 0x00005400 },
- { AUD_C2_LO_THR, 0x00003000 },
- { AUD_C1_UP_THR, 0x00007000 },
- { AUD_C2_LO_THR, 0x00005400 },
- { AUD_CTL, 0x0000100c },
- { AUD_DCOC_0_SRC, 0x00000021 },
- { AUD_DCOC_1_SRC, 0x00000003 },
- { AUD_DCOC1_SHIFT, 0x00000000 },
- { AUD_DCOC_1_SHIFT_IN0, 0x0000000a },
- { AUD_DCOC_1_SHIFT_IN1, 0x00000008 },
- { AUD_DCOC_PASS_IN, 0x00000000 },
- { AUD_DCOC_2_SRC, 0x0000001b },
- { AUD_IIR4_0_SEL, 0x0000001d },
- { AUD_POLY0_DDS_CONSTANT, 0x000e4db2 },
- { AUD_PHASE_FIX_CTL, 0x00000000 },
- { AUD_CORDIC_SHIFT_1, 0x00000007 },
- { AUD_PLL_EN, 0x00000000 },
- { AUD_PLL_PRESCALE, 0x00000002 },
- { AUD_PLL_INT, 0x0000001e },
- { AUD_OUT1_SHIFT, 0x00000000 },
+ static const struct rlist nicam_l[] = {
+ // setup QAM registers
+ { AUD_RATE_ADJ1, 0x00000060 },
+ { AUD_RATE_ADJ2, 0x000000F9 },
+ { AUD_RATE_ADJ3, 0x000001CC },
+ { AUD_RATE_ADJ4, 0x000002B3 },
+ { AUD_RATE_ADJ5, 0x00000726 },
+ { AUD_DEEMPHDENOM1_R, 0x0000F3D0 },
+ { AUD_DEEMPHDENOM2_R, 0x00000000 },
+ { AUD_ERRLOGPERIOD_R, 0x00000064 },
+ { AUD_ERRINTRPTTHSHLD1_R, 0x00000FFF },
+ { AUD_ERRINTRPTTHSHLD2_R, 0x0000001F },
+ { AUD_ERRINTRPTTHSHLD3_R, 0x0000000F },
+ { AUD_POLYPH80SCALEFAC, 0x00000003 },
+ { AUD_DMD_RA_DDS, 0x00C00000 },
+ { AUD_PLL_INT, 0x0000001E },
+ { AUD_PLL_DDS, 0x00000000 },
+ { AUD_PLL_FRAC, 0x0000E542 },
+ { AUD_START_TIMER, 0x00000000 },
+ { AUD_DEEMPHNUMER1_R, 0x000353DE },
+ { AUD_DEEMPHNUMER2_R, 0x000001B1 },
+ { AUD_PDF_DDS_CNST_BYTE2, 0x06 },
+ { AUD_PDF_DDS_CNST_BYTE1, 0x82 },
+ { AUD_QAM_MODE, 0x05 },
+ { AUD_PDF_DDS_CNST_BYTE0, 0x12 },
+ { AUD_PHACC_FREQ_8MSB, 0x34 },
+ { AUD_PHACC_FREQ_8LSB, 0x4C },
+ { AUD_DEEMPHGAIN_R, 0x00006680 },
+ { AUD_RATE_THRES_DMD, 0x000000C0 },
+ { /* end of list */ },
+ } ;
+ dprintk("%s (status: devel), stereo : %d\n",__FUNCTION__,stereo);
+
+ if (!stereo) {
+ /* AM mono sound */
+ set_audio_start(core, 0x0004,
+ 0x100c /* FIXME again */);
+ set_audio_registers(core, nicam_l_mono);
+ } else {
+ set_audio_start(core, 0x0010,
+ 0x1924 /* FIXME again */);
+ set_audio_registers(core, nicam_l);
+ }
+ set_audio_finish(core);
- { /* end of list */ },
- };
+}
- dprintk("%s (status: unknown)\n",__FUNCTION__);
- set_audio_start(core, 0x0004,
- 0 /* FIXME */);
- set_audio_registers(core, nicam_l);
+static void set_audio_standard_PAL_I(struct cx88_core *core, int stereo)
+{
+ static const struct rlist pal_i_fm_mono[] = {
+ {AUD_ERRLOGPERIOD_R, 0x00000064},
+ {AUD_ERRINTRPTTHSHLD1_R, 0x00000fff},
+ {AUD_ERRINTRPTTHSHLD2_R, 0x0000001f},
+ {AUD_ERRINTRPTTHSHLD3_R, 0x0000000f},
+ {AUD_PDF_DDS_CNST_BYTE2, 0x06},
+ {AUD_PDF_DDS_CNST_BYTE1, 0x82},
+ {AUD_PDF_DDS_CNST_BYTE0, 0x12},
+ {AUD_QAM_MODE, 0x05},
+ {AUD_PHACC_FREQ_8MSB, 0x3a},
+ {AUD_PHACC_FREQ_8LSB, 0x93},
+ {AUD_DMD_RA_DDS, 0x002a4f2f},
+ {AUD_PLL_INT, 0x0000001e},
+ {AUD_PLL_DDS, 0x00000004},
+ {AUD_PLL_FRAC, 0x0000e542},
+ {AUD_RATE_ADJ1, 0x00000100},
+ {AUD_RATE_ADJ2, 0x00000200},
+ {AUD_RATE_ADJ3, 0x00000300},
+ {AUD_RATE_ADJ4, 0x00000400},
+ {AUD_RATE_ADJ5, 0x00000500},
+ {AUD_THR_FR, 0x00000000},
+ {AUD_PILOT_BQD_1_K0, 0x0000755b},
+ {AUD_PILOT_BQD_1_K1, 0x00551340},
+ {AUD_PILOT_BQD_1_K2, 0x006d30be},
+ {AUD_PILOT_BQD_1_K3, 0xffd394af},
+ {AUD_PILOT_BQD_1_K4, 0x00400000},
+ {AUD_PILOT_BQD_2_K0, 0x00040000},
+ {AUD_PILOT_BQD_2_K1, 0x002a4841},
+ {AUD_PILOT_BQD_2_K2, 0x00400000},
+ {AUD_PILOT_BQD_2_K3, 0x00000000},
+ {AUD_PILOT_BQD_2_K4, 0x00000000},
+ {AUD_MODE_CHG_TIMER, 0x00000060},
+ {AUD_AFE_12DB_EN, 0x00000001},
+ {AAGC_HYST, 0x0000000a},
+ {AUD_CORDIC_SHIFT_0, 0x00000007},
+ {AUD_CORDIC_SHIFT_1, 0x00000007},
+ {AUD_C1_UP_THR, 0x00007000},
+ {AUD_C1_LO_THR, 0x00005400},
+ {AUD_C2_UP_THR, 0x00005400},
+ {AUD_C2_LO_THR, 0x00003000},
+ {AUD_DCOC_0_SRC, 0x0000001a},
+ {AUD_DCOC0_SHIFT, 0x00000000},
+ {AUD_DCOC_0_SHIFT_IN0, 0x0000000a},
+ {AUD_DCOC_0_SHIFT_IN1, 0x00000008},
+ {AUD_DCOC_PASS_IN, 0x00000003},
+ {AUD_IIR3_0_SEL, 0x00000021},
+ {AUD_DN2_AFC, 0x00000002},
+ {AUD_DCOC_1_SRC, 0x0000001b},
+ {AUD_DCOC1_SHIFT, 0x00000000},
+ {AUD_DCOC_1_SHIFT_IN0, 0x0000000a},
+ {AUD_DCOC_1_SHIFT_IN1, 0x00000008},
+ {AUD_IIR3_1_SEL, 0x00000023},
+ {AUD_DN0_FREQ, 0x000035a3},
+ {AUD_DN2_FREQ, 0x000029c7},
+ {AUD_CRDC0_SRC_SEL, 0x00000511},
+ {AUD_IIR1_0_SEL, 0x00000001},
+ {AUD_IIR1_1_SEL, 0x00000000},
+ {AUD_IIR3_2_SEL, 0x00000003},
+ {AUD_IIR3_2_SHIFT, 0x00000000},
+ {AUD_IIR3_0_SEL, 0x00000002},
+ {AUD_IIR2_0_SEL, 0x00000021},
+ {AUD_IIR2_0_SHIFT, 0x00000002},
+ {AUD_DEEMPH0_SRC_SEL, 0x0000000b},
+ {AUD_DEEMPH1_SRC_SEL, 0x0000000b},
+ {AUD_POLYPH80SCALEFAC, 0x00000001},
+ {AUD_START_TIMER, 0x00000000},
+ { /* end of list */ },
+ };
+
+ static const struct rlist pal_i_nicam[] = {
+ { AUD_RATE_ADJ1, 0x00000010 },
+ { AUD_RATE_ADJ2, 0x00000040 },
+ { AUD_RATE_ADJ3, 0x00000100 },
+ { AUD_RATE_ADJ4, 0x00000400 },
+ { AUD_RATE_ADJ5, 0x00001000 },
+ // { AUD_DMD_RA_DDS, 0x00c0d5ce },
+ { AUD_DEEMPHGAIN_R, 0x000023c2 },
+ { AUD_DEEMPHNUMER1_R, 0x0002a7bc },
+ { AUD_DEEMPHNUMER2_R, 0x0003023e },
+ { AUD_DEEMPHDENOM1_R, 0x0000f3d0 },
+ { AUD_DEEMPHDENOM2_R, 0x00000000 },
+ { AUD_DEEMPHDENOM2_R, 0x00000000 },
+ { AUD_ERRLOGPERIOD_R, 0x00000fff },
+ { AUD_ERRINTRPTTHSHLD1_R, 0x000003ff },
+ { AUD_ERRINTRPTTHSHLD2_R, 0x000000ff },
+ { AUD_ERRINTRPTTHSHLD3_R, 0x0000003f },
+ { AUD_POLYPH80SCALEFAC, 0x00000003 },
+ { AUD_PDF_DDS_CNST_BYTE2, 0x06 },
+ { AUD_PDF_DDS_CNST_BYTE1, 0x82 },
+ { AUD_PDF_DDS_CNST_BYTE0, 0x16 },
+ { AUD_QAM_MODE, 0x05 },
+ { AUD_PDF_DDS_CNST_BYTE0, 0x12 },
+ { AUD_PHACC_FREQ_8MSB, 0x3a },
+ { AUD_PHACC_FREQ_8LSB, 0x93 },
+ { /* end of list */ },
+ };
+
+ dprintk("%s (status: devel), stereo : %d\n",__FUNCTION__,stereo);
+
+ if (!stereo) {
+ // FM mono
+ set_audio_start(core, 0x0004, EN_DMTRX_SUMDIFF | EN_A2_FORCE_MONO1);
+ set_audio_registers(core, pal_i_fm_mono);
+ } else {
+ // Nicam Stereo
+ set_audio_start(core, 0x0010, EN_DMTRX_LR | EN_DMTRX_BYPASS | EN_NICAM_AUTO_STEREO);
+ set_audio_registers(core, pal_i_nicam);
+ }
set_audio_finish(core);
}
@@ -553,13 +677,6 @@ static void set_audio_standard_A2(struct cx88_core *core)
set_audio_start(core, 0x0004, EN_DMTRX_SUMDIFF | EN_A2_AUTO_STEREO);
set_audio_registers(core, a2_common);
switch (core->tvaudio) {
- case WW_NICAM_I:
- /* gives at least mono according to the dscaler guys */
- /* so use use that while nicam is broken ... */
- dprintk("%s PAL-I mono (status: unknown)\n",__FUNCTION__);
- set_audio_registers(core, a2_table1);
- cx_write(AUD_CTL, EN_A2_FORCE_MONO1);
- break;
case WW_A2_BG:
dprintk("%s PAL-BG A2 (status: known-good)\n",__FUNCTION__);
set_audio_registers(core, a2_table1);
@@ -646,11 +763,12 @@ void cx88_set_tvaudio(struct cx88_core *core)
case WW_BTSC:
set_audio_standard_BTSC(core,0);
break;
- // case WW_NICAM_I:
case WW_NICAM_BGDKL:
- set_audio_standard_NICAM(core);
+ set_audio_standard_NICAM_L(core,0);
break;
case WW_NICAM_I:
+ set_audio_standard_PAL_I(core,0);
+ break;
case WW_A2_BG:
case WW_A2_DK:
case WW_A2_M:
@@ -663,7 +781,7 @@ void cx88_set_tvaudio(struct cx88_core *core)
set_audio_standard_FM(core);
break;
case WW_SYSTEM_L_AM:
- set_audio_standard_NICAM_L(core);
+ set_audio_standard_NICAM_L(core, 1);
break;
case WW_NONE:
default:
@@ -674,6 +792,19 @@ void cx88_set_tvaudio(struct cx88_core *core)
return;
}
+void cx88_newstation(struct cx88_core *core)
+{
+ core->audiomode_manual = UNSET;
+
+ switch (core->tvaudio) {
+ case WW_SYSTEM_L_AM:
+ /* try nicam ... */
+ core->audiomode_current = V4L2_TUNER_MODE_STEREO;
+ set_audio_standard_NICAM_L(core, 1);
+ break;
+ }
+}
+
void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t)
{
static char *m[] = {"stereo", "dual mono", "mono", "sap"};
@@ -721,22 +852,37 @@ void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t)
}
break;
case WW_NICAM_BGDKL:
- if (0 == mode)
+ if (0 == mode) {
t->audmode = V4L2_TUNER_MODE_STEREO;
+ t->rxsubchans |= V4L2_TUNER_SUB_STEREO;
+ }
break;
+ case WW_SYSTEM_L_AM:
+ if (0x0 == mode && !(cx_read(AUD_INIT) & 0x04)) {
+ t->audmode = V4L2_TUNER_MODE_STEREO;
+ t->rxsubchans |= V4L2_TUNER_SUB_STEREO;
+ }
+ break ;
default:
- t->rxsubchans = V4L2_TUNER_SUB_MONO;
- t->audmode = V4L2_TUNER_MODE_MONO;
+ /* nothing */
break;
}
return;
}
-void cx88_set_stereo(struct cx88_core *core, u32 mode)
+void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual)
{
u32 ctl = UNSET;
u32 mask = UNSET;
+ if (manual) {
+ core->audiomode_manual = mode;
+ } else {
+ if (UNSET != core->audiomode_manual)
+ return;
+ }
+ core->audiomode_current = mode;
+
switch (core->tvaudio) {
case WW_BTSC:
switch (mode) {
@@ -789,6 +935,28 @@ void cx88_set_stereo(struct cx88_core *core, u32 mode)
break;
}
break;
+ case WW_SYSTEM_L_AM:
+ switch (mode) {
+ case V4L2_TUNER_MODE_MONO:
+ case V4L2_TUNER_MODE_LANG1: /* FIXME */
+ set_audio_standard_NICAM_L(core, 0);
+ break;
+ case V4L2_TUNER_MODE_STEREO:
+ set_audio_standard_NICAM_L(core, 1);
+ break;
+ }
+ break;
+ case WW_NICAM_I:
+ switch (mode) {
+ case V4L2_TUNER_MODE_MONO:
+ case V4L2_TUNER_MODE_LANG1:
+ set_audio_standard_PAL_I(core, 0);
+ break;
+ case V4L2_TUNER_MODE_STEREO:
+ set_audio_standard_PAL_I(core, 1);
+ break;
+ }
+ break;
case WW_FM:
switch (mode) {
case V4L2_TUNER_MODE_MONO:
@@ -804,13 +972,11 @@ void cx88_set_stereo(struct cx88_core *core, u32 mode)
}
if (UNSET != ctl) {
- cx_write(AUD_SOFT_RESET, 0x0001);
- cx_andor(AUD_CTL, mask, ctl);
- cx_write(AUD_SOFT_RESET, 0x0000);
dprintk("cx88_set_stereo: mask 0x%x, ctl 0x%x "
"[status=0x%x,ctl=0x%x,vol=0x%x]\n",
mask, ctl, cx_read(AUD_STATUS),
cx_read(AUD_CTL), cx_sread(SHADOW_AUD_VOL_CTL));
+ cx_andor(AUD_CTL, mask, ctl);
}
return;
}
@@ -819,16 +985,32 @@ int cx88_audio_thread(void *data)
{
struct cx88_core *core = data;
struct v4l2_tuner t;
+ u32 mode = 0;
dprintk("cx88: tvaudio thread started\n");
for (;;) {
+ msleep_interruptible(1000);
if (kthread_should_stop())
break;
/* just monitor the audio status for now ... */
memset(&t,0,sizeof(t));
cx88_get_stereo(core,&t);
- msleep_interruptible(1000);
+
+ if (UNSET != core->audiomode_manual)
+ /* manually set, don't do anything. */
+ continue;
+
+ /* monitor signal */
+ if (t.rxsubchans & V4L2_TUNER_SUB_STEREO)
+ mode = V4L2_TUNER_MODE_STEREO;
+ else
+ mode = V4L2_TUNER_MODE_MONO;
+ if (mode == core->audiomode_current)
+ continue;
+
+ /* automatically switch to best available mode */
+ cx88_set_stereo(core, mode, 0);
}
dprintk("cx88: tvaudio thread exiting\n");
@@ -838,6 +1020,7 @@ int cx88_audio_thread(void *data)
/* ----------------------------------------------------------- */
EXPORT_SYMBOL(cx88_set_tvaudio);
+EXPORT_SYMBOL(cx88_newstation);
EXPORT_SYMBOL(cx88_set_stereo);
EXPORT_SYMBOL(cx88_get_stereo);
EXPORT_SYMBOL(cx88_audio_thread);
diff --git a/drivers/media/video/cx88/cx88-vbi.c b/drivers/media/video/cx88/cx88-vbi.c
index 672d1b456c160..471e508b07465 100644
--- a/drivers/media/video/cx88/cx88-vbi.c
+++ b/drivers/media/video/cx88/cx88-vbi.c
@@ -1,8 +1,9 @@
/*
- * $Id: cx88-vbi.c,v 1.14 2004/11/07 13:17:15 kraxel Exp $
+ * $Id: cx88-vbi.c,v 1.16 2004/12/10 12:33:39 kraxel Exp $
*/
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/slab.h>
@@ -64,7 +65,7 @@ int cx8800_start_vbi_dma(struct cx8800_dev *dev,
q->count = 1;
/* enable irqs */
- cx_set(MO_PCI_INTMSK, 0x00fc01);
+ cx_set(MO_PCI_INTMSK, core->pci_irqmask | 0x01);
cx_set(MO_VID_INTMSK, 0x0f0088);
/* enable capture */
diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c
index aa1f35a2fa439..701f594e18164 100644
--- a/drivers/media/video/cx88/cx88-video.c
+++ b/drivers/media/video/cx88/cx88-video.c
@@ -1,5 +1,5 @@
/*
- * $Id: cx88-video.c,v 1.46 2004/11/07 14:44:59 kraxel Exp $
+ * $Id: cx88-video.c,v 1.58 2005/03/07 15:58:05 kraxel Exp $
*
* device driver for Conexant 2388x based TV cards
* video4linux video interface
@@ -24,6 +24,7 @@
#include <linux/init.h>
#include <linux/list.h>
#include <linux/module.h>
+#include <linux/moduleparam.h>
#include <linux/kmod.h>
#include <linux/kernel.h>
#include <linux/slab.h>
@@ -428,7 +429,7 @@ static int start_video_dma(struct cx8800_dev *dev,
q->count = 1;
/* enable irqs */
- cx_set(MO_PCI_INTMSK, 0x00fc01);
+ cx_set(MO_PCI_INTMSK, core->pci_irqmask | 0x01);
cx_set(MO_VID_INTMSK, 0x0f0011);
/* enable capture */
@@ -994,7 +995,7 @@ static int video_open(struct inode *inode, struct file *file)
cx_write(MO_GP3_IO, cx88_boards[board].radio.gpio3);
dev->core->tvaudio = WW_FM;
cx88_set_tvaudio(core);
- cx88_set_stereo(core,V4L2_TUNER_MODE_STEREO);
+ cx88_set_stereo(core,V4L2_TUNER_MODE_STEREO,1);
cx88_call_i2c_clients(dev->core,AUDC_SET_RADIO,NULL);
}
@@ -1002,7 +1003,7 @@ static int video_open(struct inode *inode, struct file *file)
}
static ssize_t
-video_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
+video_read(struct file *file, char *data, size_t count, loff_t *ppos)
{
struct cx8800_fh *fh = file->private_data;
@@ -1083,6 +1084,8 @@ static int video_release(struct inode *inode, struct file *file)
res_free(dev,fh,RESOURCE_VBI);
}
+ videobuf_mmap_free(&fh->vidq);
+ videobuf_mmap_free(&fh->vbiq);
file->private_data = NULL;
kfree(fh);
return 0;
@@ -1338,7 +1341,6 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
0;
if (UNSET != core->tuner_type)
cap->capabilities |= V4L2_CAP_TUNER;
-
return 0;
}
@@ -1429,6 +1431,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
if (*i >= 4)
return -EINVAL;
down(&dev->lock);
+ cx88_newstation(core);
video_mux(dev,*i);
up(&dev->lock);
return 0;
@@ -1560,7 +1563,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
return -EINVAL;
if (0 != t->index)
return -EINVAL;
- cx88_set_stereo(core, t->audmode);
+ cx88_set_stereo(core, t->audmode, 1);
return 0;
}
case VIDIOC_G_FREQUENCY:
@@ -1590,6 +1593,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
return -EINVAL;
down(&dev->lock);
dev->freq = f->frequency;
+ cx88_newstation(core);
#ifdef V4L2_I2C_CLIENTS
cx88_call_i2c_clients(dev->core,VIDIOC_S_FREQUENCY,f);
#else
@@ -1880,19 +1884,18 @@ static irqreturn_t cx8800_irq(int irq, void *dev_id, struct pt_regs *regs)
{
struct cx8800_dev *dev = dev_id;
struct cx88_core *core = dev->core;
- u32 status, mask;
+ u32 status;
int loop, handled = 0;
for (loop = 0; loop < 10; loop++) {
- status = cx_read(MO_PCI_INTSTAT) & (~0x1f | 0x01);
- mask = cx_read(MO_PCI_INTMSK);
- if (0 == (status & mask))
+ status = cx_read(MO_PCI_INTSTAT) & (core->pci_irqmask | 0x01);
+ if (0 == status)
goto out;
cx_write(MO_PCI_INTSTAT, status);
handled = 1;
- if (status & mask & ~0x1f)
- cx88_irq(core,status,mask);
+ if (status & core->pci_irqmask)
+ cx88_core_irq(core,status);
if (status & 0x01)
cx8800_vid_irq(dev);
};
@@ -2055,6 +2058,7 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev,
core->name,pci_dev->irq);
goto fail_core;
}
+ cx_set(MO_PCI_INTMSK, core->pci_irqmask);
/* load and configure helper modules */
if (TUNER_ABSENT != core->tuner_type)
@@ -2156,7 +2160,7 @@ static void __devexit cx8800_finidev(struct pci_dev *pci_dev)
kfree(dev);
}
-static int cx8800_suspend(struct pci_dev *pci_dev, u32 state)
+static int cx8800_suspend(struct pci_dev *pci_dev, pm_message_t state)
{
struct cx8800_dev *dev = pci_get_drvdata(pci_dev);
struct cx88_core *core = dev->core;
@@ -2181,7 +2185,7 @@ static int cx8800_suspend(struct pci_dev *pci_dev, u32 state)
#endif
pci_save_state(pci_dev);
- if (0 != pci_set_power_state(pci_dev, state)) {
+ if (0 != pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state))) {
pci_disable_device(pci_dev);
dev->state.disabled = 1;
}
@@ -2197,7 +2201,7 @@ static int cx8800_resume(struct pci_dev *pci_dev)
pci_enable_device(pci_dev);
dev->state.disabled = 0;
}
- pci_set_power_state(pci_dev, 0);
+ pci_set_power_state(pci_dev, PCI_D0);
pci_restore_state(pci_dev);
#if 1
@@ -2254,7 +2258,7 @@ static int cx8800_init(void)
printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n",
SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100);
#endif
- return pci_module_init(&cx8800_pci_driver);
+ return pci_register_driver(&cx8800_pci_driver);
}
static void cx8800_fini(void)
diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h
index 926eaf7f08cdb..b351d9eae6159 100644
--- a/drivers/media/video/cx88/cx88.h
+++ b/drivers/media/video/cx88/cx88.h
@@ -1,5 +1,5 @@
/*
- * $Id: cx88.h,v 1.40 2004/11/03 09:04:51 kraxel Exp $
+ * $Id: cx88.h,v 1.56 2005/03/04 09:12:23 kraxel Exp $
*
* v4l2 device driver for cx2388x based TV cards
*
@@ -27,6 +27,7 @@
#include <linux/kdev_t.h>
#include <media/tuner.h>
+#include <media/tveeprom.h>
#include <media/audiochip.h>
#include <media/video-buf.h>
#include <media/video-buf-dvb.h>
@@ -139,7 +140,7 @@ extern struct sram_channel cx88_sram_channels[];
#define CX88_BOARD_GDI 2
#define CX88_BOARD_PIXELVIEW 3
#define CX88_BOARD_ATI_WONDER_PRO 4
-#define CX88_BOARD_WINFAST2000XP 5
+#define CX88_BOARD_WINFAST2000XP_EXPERT 5
#define CX88_BOARD_AVERTV_303 6
#define CX88_BOARD_MSI_TVANYWHERE_MASTER 7
#define CX88_BOARD_WINFAST_DV2000 8
@@ -156,6 +157,11 @@ extern struct sram_channel cx88_sram_channels[];
#define CX88_BOARD_CONEXANT_DVB_T1 19
#define CX88_BOARD_PROVIDEO_PV259 20
#define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS 21
+#define CX88_BOARD_PCHDTV_HD3000 22
+#define CX88_BOARD_DNTV_LIVE_DVB_T 23
+#define CX88_BOARD_HAUPPAUGE_ROSLYN 24
+#define CX88_BOARD_DIGITALLOGIC_MEC 25
+#define CX88_BOARD_IODATA_GVBCTV7E 26
enum cx88_itype {
CX88_VMUX_COMPOSITE1 = 1,
@@ -238,6 +244,7 @@ struct cx88_core {
u32 __iomem *lmmio;
u8 __iomem *bmmio;
u32 shadow[SHADOW_MAX];
+ int pci_irqmask;
/* i2c i/o */
struct i2c_adapter i2c_adap;
@@ -252,16 +259,20 @@ struct cx88_core {
unsigned int has_radio;
/* config info -- dvb */
- unsigned int pll_type;
+ struct dvb_pll_desc *pll_desc;
unsigned int pll_addr;
- unsigned int demod_addr;
/* state info */
struct task_struct *kthread;
struct cx88_tvnorm *tvnorm;
u32 tvaudio;
+ u32 audiomode_manual;
+ u32 audiomode_current;
u32 input;
u32 astat;
+
+ /* IR remote control state */
+ struct cx88_IR *ir;
};
struct cx8800_dev;
@@ -371,11 +382,16 @@ struct cx8802_dev {
struct list_head devlist;
struct video_device *mpeg_dev;
u32 mailbox;
+ int width;
+ int height;
/* for dvb only */
struct videobuf_dvb dvb;
void* fe_handle;
int (*fe_release)(void *handle);
+
+ /* for switching modulation types */
+ unsigned char ts_gen_cntrl;
};
/* ----------------------------------------------------------- */
@@ -411,7 +427,7 @@ 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 void cx88_irq(struct cx88_core *core, u32 status, u32 mask);
+extern int cx88_core_irq(struct cx88_core *core, u32 status);
extern void cx88_wakeup(struct cx88_core *core,
struct cx88_dmaqueue *q, u32 count);
extern void cx88_shutdown(struct cx88_core *core);
@@ -503,11 +519,19 @@ extern void cx88_card_setup(struct cx88_core *core);
#define WW_FM 12
void cx88_set_tvaudio(struct cx88_core *core);
+void cx88_newstation(struct cx88_core *core);
void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t);
-void cx88_set_stereo(struct cx88_core *core, u32 mode);
+void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual);
int cx88_audio_thread(void *data);
/* ----------------------------------------------------------- */
+/* cx88-input.c */
+
+int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci);
+int cx88_ir_fini(struct cx88_core *core);
+void cx88_ir_irq(struct cx88_core *core);
+
+/* ----------------------------------------------------------- */
/* cx88-mpeg.c */
int cx8802_buf_prepare(struct cx8802_dev *dev, struct cx88_buffer *buf);
@@ -517,7 +541,7 @@ void cx8802_cancel_buffers(struct cx8802_dev *dev);
int cx8802_init_common(struct cx8802_dev *dev);
void cx8802_fini_common(struct cx8802_dev *dev);
-int cx8802_suspend_common(struct pci_dev *pci_dev, u32 state);
+int cx8802_suspend_common(struct pci_dev *pci_dev, pm_message_t state);
int cx8802_resume_common(struct pci_dev *pci_dev);
/*
diff --git a/drivers/media/video/ir-kbd-gpio.c b/drivers/media/video/ir-kbd-gpio.c
index 973b081883108..ab6620de4b3b8 100644
--- a/drivers/media/video/ir-kbd-gpio.c
+++ b/drivers/media/video/ir-kbd-gpio.c
@@ -1,5 +1,5 @@
/*
- * $Id: ir-kbd-gpio.c,v 1.11 2004/10/25 11:26:36 kraxel Exp $
+ * $Id: ir-kbd-gpio.c,v 1.12 2005/02/22 12:28:40 kraxel Exp $
*
* Copyright (c) 2003 Gerd Knorr
* Copyright (c) 2003 Pavel Machek
@@ -114,51 +114,6 @@ static IR_KEYTAB_TYPE ir_codes_avermedia_dvbt[IR_KEYTAB_SIZE] = {
[ 0x3e ] = KEY_VOLUMEUP, // 'volume +'
};
-static IR_KEYTAB_TYPE winfast_codes[IR_KEYTAB_SIZE] = {
- [ 5 ] = KEY_KP1,
- [ 6 ] = KEY_KP2,
- [ 7 ] = KEY_KP3,
- [ 9 ] = KEY_KP4,
- [ 10 ] = KEY_KP5,
- [ 11 ] = KEY_KP6,
- [ 13 ] = KEY_KP7,
- [ 14 ] = KEY_KP8,
- [ 15 ] = KEY_KP9,
- [ 18 ] = KEY_KP0,
-
- [ 0 ] = KEY_POWER,
-// [ 27 ] = MTS button
- [ 2 ] = KEY_TUNER, // TV/FM
- [ 30 ] = KEY_VIDEO,
-// [ 22 ] = display button
- [ 4 ] = KEY_VOLUMEUP,
- [ 8 ] = KEY_VOLUMEDOWN,
- [ 12 ] = KEY_CHANNELUP,
- [ 16 ] = KEY_CHANNELDOWN,
- [ 3 ] = KEY_ZOOM, // fullscreen
- [ 31 ] = KEY_SUBTITLE, // closed caption/teletext
- [ 32 ] = KEY_SLEEP,
-// [ 41 ] = boss key
- [ 20 ] = KEY_MUTE,
- [ 43 ] = KEY_RED,
- [ 44 ] = KEY_GREEN,
- [ 45 ] = KEY_YELLOW,
- [ 46 ] = KEY_BLUE,
- [ 24 ] = KEY_KPPLUS, //fine tune +
- [ 25 ] = KEY_KPMINUS, //fine tune -
-// [ 42 ] = picture in picture
- [ 33 ] = KEY_KPDOT,
- [ 19 ] = KEY_KPENTER,
-// [ 17 ] = recall
- [ 34 ] = KEY_BACK,
- [ 35 ] = KEY_PLAYPAUSE,
- [ 36 ] = KEY_NEXT,
-// [ 37 ] = time shifting
- [ 38 ] = KEY_STOP,
- [ 39 ] = KEY_RECORD
-// [ 40 ] = snapshot
-};
-
static IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE] = {
[ 2 ] = KEY_KP0,
[ 1 ] = KEY_KP1,
@@ -388,12 +343,12 @@ static int ir_probe(struct device *dev)
break;
case BTTV_WINFAST2000:
- ir_codes = winfast_codes;
+ ir_codes = ir_codes_winfast;
ir->mask_keycode = 0x1f8;
break;
case BTTV_MAGICTVIEW061:
case BTTV_MAGICTVIEW063:
- ir_codes = winfast_codes;
+ ir_codes = ir_codes_winfast;
ir->mask_keycode = 0x0008e000;
ir->mask_keydown = 0x00200000;
break;
diff --git a/drivers/media/video/meye.c b/drivers/media/video/meye.c
index d0478307fbacc..be72c2ce242ef 100644
--- a/drivers/media/video/meye.c
+++ b/drivers/media/video/meye.c
@@ -1154,7 +1154,7 @@ static int meye_do_ioctl(struct inode *inode, struct file *file,
memset(cap, 0, sizeof(*cap));
strcpy(cap->driver, "meye");
strcpy(cap->card, "meye");
- sprintf(cap->bus_info, "PCI:%s", meye.mchip_dev->slot_name);
+ sprintf(cap->bus_info, "PCI:%s", pci_name(meye.mchip_dev));
cap->version = (MEYE_DRIVER_MAJORVERSION << 8) +
MEYE_DRIVER_MINORVERSION;
cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
diff --git a/drivers/media/video/msp3400.c b/drivers/media/video/msp3400.c
index 040d9312e37d2..d996ec99caff9 100644
--- a/drivers/media/video/msp3400.c
+++ b/drivers/media/video/msp3400.c
@@ -734,6 +734,7 @@ static int msp34xx_sleep(struct msp3400c *msp, int timeout)
{
DECLARE_WAITQUEUE(wait, current);
+again:
add_wait_queue(&msp->wq, &wait);
if (!kthread_should_stop()) {
if (timeout < 0) {
@@ -749,9 +750,12 @@ static int msp34xx_sleep(struct msp3400c *msp, int timeout)
#endif
}
}
- if (current->flags & PF_FREEZE)
- refrigerator(PF_FREEZE);
+
remove_wait_queue(&msp->wq, &wait);
+
+ if (try_to_freeze(PF_FREEZE))
+ goto again;
+
return msp->restart;
}
diff --git a/drivers/media/video/mt20xx.c b/drivers/media/video/mt20xx.c
new file mode 100644
index 0000000000000..95ad17b7f38e3
--- /dev/null
+++ b/drivers/media/video/mt20xx.c
@@ -0,0 +1,558 @@
+/*
+ * $Id: mt20xx.c,v 1.4 2005/03/04 09:24:56 kraxel Exp $
+ *
+ * i2c tv tuner chip device driver
+ * controls microtune tuners, mt2032 + mt2050 at the moment.
+ */
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/videodev.h>
+#include <linux/moduleparam.h>
+#include <media/tuner.h>
+
+/* ---------------------------------------------------------------------- */
+
+static unsigned int optimize_vco = 1;
+module_param(optimize_vco, int, 0644);
+
+static unsigned int tv_antenna = 1;
+module_param(tv_antenna, int, 0644);
+
+static unsigned int radio_antenna = 0;
+module_param(radio_antenna, int, 0644);
+
+/* ---------------------------------------------------------------------- */
+
+#define MT2032 0x04
+#define MT2030 0x06
+#define MT2040 0x07
+#define MT2050 0x42
+
+static char *microtune_part[] = {
+ [ MT2030 ] = "MT2030",
+ [ MT2032 ] = "MT2032",
+ [ MT2040 ] = "MT2040",
+ [ MT2050 ] = "MT2050",
+};
+
+// IsSpurInBand()?
+static int mt2032_spurcheck(struct i2c_client *c,
+ int f1, int f2, int spectrum_from,int spectrum_to)
+{
+ struct tuner *t = i2c_get_clientdata(c);
+ int n1=1,n2,f;
+
+ f1=f1/1000; //scale to kHz to avoid 32bit overflows
+ f2=f2/1000;
+ spectrum_from/=1000;
+ spectrum_to/=1000;
+
+ tuner_dbg("spurcheck f1=%d f2=%d from=%d to=%d\n",
+ f1,f2,spectrum_from,spectrum_to);
+
+ do {
+ n2=-n1;
+ f=n1*(f1-f2);
+ do {
+ n2--;
+ f=f-f2;
+ tuner_dbg("spurtest n1=%d n2=%d ftest=%d\n",n1,n2,f);
+
+ if( (f>spectrum_from) && (f<spectrum_to))
+ tuner_dbg("mt2032 spurcheck triggered: %d\n",n1);
+ } while ( (f>(f2-spectrum_to)) || (n2>-5));
+ n1++;
+ } while (n1<5);
+
+ return 1;
+}
+
+static int mt2032_compute_freq(struct i2c_client *c,
+ unsigned int rfin,
+ unsigned int if1, unsigned int if2,
+ unsigned int spectrum_from,
+ unsigned int spectrum_to,
+ unsigned char *buf,
+ int *ret_sel,
+ unsigned int xogc) //all in Hz
+{
+ struct tuner *t = i2c_get_clientdata(c);
+ unsigned int fref,lo1,lo1n,lo1a,s,sel,lo1freq, desired_lo1,
+ desired_lo2,lo2,lo2n,lo2a,lo2num,lo2freq;
+
+ fref= 5250 *1000; //5.25MHz
+ desired_lo1=rfin+if1;
+
+ lo1=(2*(desired_lo1/1000)+(fref/1000)) / (2*fref/1000);
+ lo1n=lo1/8;
+ lo1a=lo1-(lo1n*8);
+
+ s=rfin/1000/1000+1090;
+
+ if(optimize_vco) {
+ if(s>1890) sel=0;
+ else if(s>1720) sel=1;
+ else if(s>1530) sel=2;
+ else if(s>1370) sel=3;
+ else sel=4; // >1090
+ }
+ else {
+ if(s>1790) sel=0; // <1958
+ else if(s>1617) sel=1;
+ else if(s>1449) sel=2;
+ else if(s>1291) sel=3;
+ else sel=4; // >1090
+ }
+ *ret_sel=sel;
+
+ lo1freq=(lo1a+8*lo1n)*fref;
+
+ tuner_dbg("mt2032: rfin=%d lo1=%d lo1n=%d lo1a=%d sel=%d, lo1freq=%d\n",
+ rfin,lo1,lo1n,lo1a,sel,lo1freq);
+
+ desired_lo2=lo1freq-rfin-if2;
+ lo2=(desired_lo2)/fref;
+ lo2n=lo2/8;
+ lo2a=lo2-(lo2n*8);
+ lo2num=((desired_lo2/1000)%(fref/1000))* 3780/(fref/1000); //scale to fit in 32bit arith
+ lo2freq=(lo2a+8*lo2n)*fref + lo2num*(fref/1000)/3780*1000;
+
+ tuner_dbg("mt2032: rfin=%d lo2=%d lo2n=%d lo2a=%d num=%d lo2freq=%d\n",
+ rfin,lo2,lo2n,lo2a,lo2num,lo2freq);
+
+ if(lo1a<0 || lo1a>7 || lo1n<17 ||lo1n>48 || lo2a<0 ||lo2a >7 ||lo2n<17 || lo2n>30) {
+ tuner_info("mt2032: frequency parameters out of range: %d %d %d %d\n",
+ lo1a, lo1n, lo2a,lo2n);
+ return(-1);
+ }
+
+ mt2032_spurcheck(c, lo1freq, desired_lo2, spectrum_from, spectrum_to);
+ // should recalculate lo1 (one step up/down)
+
+ // set up MT2032 register map for transfer over i2c
+ buf[0]=lo1n-1;
+ buf[1]=lo1a | (sel<<4);
+ buf[2]=0x86; // LOGC
+ buf[3]=0x0f; //reserved
+ buf[4]=0x1f;
+ buf[5]=(lo2n-1) | (lo2a<<5);
+ if(rfin >400*1000*1000)
+ buf[6]=0xe4;
+ else
+ buf[6]=0xf4; // set PKEN per rev 1.2
+ buf[7]=8+xogc;
+ buf[8]=0xc3; //reserved
+ buf[9]=0x4e; //reserved
+ buf[10]=0xec; //reserved
+ buf[11]=(lo2num&0xff);
+ buf[12]=(lo2num>>8) |0x80; // Lo2RST
+
+ return 0;
+}
+
+static int mt2032_check_lo_lock(struct i2c_client *c)
+{
+ struct tuner *t = i2c_get_clientdata(c);
+ int try,lock=0;
+ unsigned char buf[2];
+
+ for(try=0;try<10;try++) {
+ buf[0]=0x0e;
+ i2c_master_send(c,buf,1);
+ i2c_master_recv(c,buf,1);
+ tuner_dbg("mt2032 Reg.E=0x%02x\n",buf[0]);
+ lock=buf[0] &0x06;
+
+ if (lock==6)
+ break;
+
+ tuner_dbg("mt2032: pll wait 1ms for lock (0x%2x)\n",buf[0]);
+ udelay(1000);
+ }
+ return lock;
+}
+
+static int mt2032_optimize_vco(struct i2c_client *c,int sel,int lock)
+{
+ struct tuner *t = i2c_get_clientdata(c);
+ unsigned char buf[2];
+ int tad1;
+
+ buf[0]=0x0f;
+ i2c_master_send(c,buf,1);
+ i2c_master_recv(c,buf,1);
+ tuner_dbg("mt2032 Reg.F=0x%02x\n",buf[0]);
+ tad1=buf[0]&0x07;
+
+ if(tad1 ==0) return lock;
+ if(tad1 ==1) return lock;
+
+ if(tad1==2) {
+ if(sel==0)
+ return lock;
+ else sel--;
+ }
+ else {
+ if(sel<4)
+ sel++;
+ else
+ return lock;
+ }
+
+ tuner_dbg("mt2032 optimize_vco: sel=%d\n",sel);
+
+ buf[0]=0x0f;
+ buf[1]=sel;
+ i2c_master_send(c,buf,2);
+ lock=mt2032_check_lo_lock(c);
+ return lock;
+}
+
+
+static void mt2032_set_if_freq(struct i2c_client *c, unsigned int rfin,
+ unsigned int if1, unsigned int if2,
+ unsigned int from, unsigned int to)
+{
+ unsigned char buf[21];
+ int lint_try,ret,sel,lock=0;
+ struct tuner *t = i2c_get_clientdata(c);
+
+ tuner_dbg("mt2032_set_if_freq rfin=%d if1=%d if2=%d from=%d to=%d\n",
+ rfin,if1,if2,from,to);
+
+ buf[0]=0;
+ ret=i2c_master_send(c,buf,1);
+ i2c_master_recv(c,buf,21);
+
+ buf[0]=0;
+ ret=mt2032_compute_freq(c,rfin,if1,if2,from,to,&buf[1],&sel,t->xogc);
+ if (ret<0)
+ return;
+
+ // send only the relevant registers per Rev. 1.2
+ buf[0]=0;
+ ret=i2c_master_send(c,buf,4);
+ buf[5]=5;
+ ret=i2c_master_send(c,buf+5,4);
+ buf[11]=11;
+ ret=i2c_master_send(c,buf+11,3);
+ if(ret!=3)
+ tuner_warn("i2c i/o error: rc == %d (should be 3)\n",ret);
+
+ // wait for PLLs to lock (per manual), retry LINT if not.
+ for(lint_try=0; lint_try<2; lint_try++) {
+ lock=mt2032_check_lo_lock(c);
+
+ if(optimize_vco)
+ lock=mt2032_optimize_vco(c,sel,lock);
+ if(lock==6) break;
+
+ tuner_dbg("mt2032: re-init PLLs by LINT\n");
+ buf[0]=7;
+ buf[1]=0x80 +8+t->xogc; // set LINT to re-init PLLs
+ i2c_master_send(c,buf,2);
+ mdelay(10);
+ buf[1]=8+t->xogc;
+ i2c_master_send(c,buf,2);
+ }
+
+ if (lock!=6)
+ tuner_warn("MT2032 Fatal Error: PLLs didn't lock.\n");
+
+ buf[0]=2;
+ buf[1]=0x20; // LOGC for optimal phase noise
+ ret=i2c_master_send(c,buf,2);
+ if (ret!=2)
+ tuner_warn("i2c i/o error: rc == %d (should be 2)\n",ret);
+}
+
+
+static void mt2032_set_tv_freq(struct i2c_client *c, unsigned int freq)
+{
+ struct tuner *t = i2c_get_clientdata(c);
+ int if2,from,to;
+
+ // signal bandwidth and picture carrier
+ if (t->std & V4L2_STD_525_60) {
+ // NTSC
+ from = 40750*1000;
+ to = 46750*1000;
+ if2 = 45750*1000;
+ } else {
+ // PAL
+ from = 32900*1000;
+ to = 39900*1000;
+ if2 = 38900*1000;
+ }
+
+ mt2032_set_if_freq(c, freq*62500 /* freq*1000*1000/16 */,
+ 1090*1000*1000, if2, from, to);
+}
+
+static void mt2032_set_radio_freq(struct i2c_client *c, unsigned int freq)
+{
+ struct tuner *t = i2c_get_clientdata(c);
+ int if2 = t->radio_if2;
+
+ // per Manual for FM tuning: first if center freq. 1085 MHz
+ mt2032_set_if_freq(c, freq*62500 /* freq*1000*1000/16 */,
+ 1085*1000*1000,if2,if2,if2);
+}
+
+// Initalization as described in "MT203x Programming Procedures", Rev 1.2, Feb.2001
+static int mt2032_init(struct i2c_client *c)
+{
+ struct tuner *t = i2c_get_clientdata(c);
+ unsigned char buf[21];
+ int ret,xogc,xok=0;
+
+ // Initialize Registers per spec.
+ buf[1]=2; // Index to register 2
+ buf[2]=0xff;
+ buf[3]=0x0f;
+ buf[4]=0x1f;
+ ret=i2c_master_send(c,buf+1,4);
+
+ buf[5]=6; // Index register 6
+ buf[6]=0xe4;
+ buf[7]=0x8f;
+ buf[8]=0xc3;
+ buf[9]=0x4e;
+ buf[10]=0xec;
+ ret=i2c_master_send(c,buf+5,6);
+
+ buf[12]=13; // Index register 13
+ buf[13]=0x32;
+ ret=i2c_master_send(c,buf+12,2);
+
+ // Adjust XOGC (register 7), wait for XOK
+ xogc=7;
+ do {
+ tuner_dbg("mt2032: xogc = 0x%02x\n",xogc&0x07);
+ mdelay(10);
+ buf[0]=0x0e;
+ i2c_master_send(c,buf,1);
+ i2c_master_recv(c,buf,1);
+ xok=buf[0]&0x01;
+ tuner_dbg("mt2032: xok = 0x%02x\n",xok);
+ if (xok == 1) break;
+
+ xogc--;
+ tuner_dbg("mt2032: xogc = 0x%02x\n",xogc&0x07);
+ if (xogc == 3) {
+ xogc=4; // min. 4 per spec
+ break;
+ }
+ buf[0]=0x07;
+ buf[1]=0x88 + xogc;
+ ret=i2c_master_send(c,buf,2);
+ if (ret!=2)
+ tuner_warn("i2c i/o error: rc == %d (should be 2)\n",ret);
+ } while (xok != 1 );
+ t->xogc=xogc;
+
+ t->tv_freq = mt2032_set_tv_freq;
+ t->radio_freq = mt2032_set_radio_freq;
+ return(1);
+}
+
+static void mt2050_set_antenna(struct i2c_client *c, unsigned char antenna)
+{
+ struct tuner *t = i2c_get_clientdata(c);
+ unsigned char buf[2];
+ int ret;
+
+ buf[0] = 6;
+ buf[1] = antenna ? 0x11 : 0x10;
+ ret=i2c_master_send(c,buf,2);
+ tuner_dbg("mt2050: enabled antenna connector %d\n", antenna);
+}
+
+static void mt2050_set_if_freq(struct i2c_client *c,unsigned int freq, unsigned int if2)
+{
+ struct tuner *t = i2c_get_clientdata(c);
+ unsigned int if1=1218*1000*1000;
+ unsigned int f_lo1,f_lo2,lo1,lo2,f_lo1_modulo,f_lo2_modulo,num1,num2,div1a,div1b,div2a,div2b;
+ int ret;
+ unsigned char buf[6];
+
+ tuner_dbg("mt2050_set_if_freq freq=%d if1=%d if2=%d\n",
+ freq,if1,if2);
+
+ f_lo1=freq+if1;
+ f_lo1=(f_lo1/1000000)*1000000;
+
+ f_lo2=f_lo1-freq-if2;
+ f_lo2=(f_lo2/50000)*50000;
+
+ lo1=f_lo1/4000000;
+ lo2=f_lo2/4000000;
+
+ f_lo1_modulo= f_lo1-(lo1*4000000);
+ f_lo2_modulo= f_lo2-(lo2*4000000);
+
+ num1=4*f_lo1_modulo/4000000;
+ num2=4096*(f_lo2_modulo/1000)/4000;
+
+ // todo spurchecks
+
+ div1a=(lo1/12)-1;
+ div1b=lo1-(div1a+1)*12;
+
+ div2a=(lo2/8)-1;
+ div2b=lo2-(div2a+1)*8;
+
+ if (tuner_debug > 1) {
+ tuner_dbg("lo1 lo2 = %d %d\n", lo1, lo2);
+ tuner_dbg("num1 num2 div1a div1b div2a div2b= %x %x %x %x %x %x\n",
+ num1,num2,div1a,div1b,div2a,div2b);
+ }
+
+ buf[0]=1;
+ buf[1]= 4*div1b + num1;
+ if(freq<275*1000*1000) buf[1] = buf[1]|0x80;
+
+ buf[2]=div1a;
+ buf[3]=32*div2b + num2/256;
+ buf[4]=num2-(num2/256)*256;
+ buf[5]=div2a;
+ if(num2!=0) buf[5]=buf[5]|0x40;
+
+ if (tuner_debug > 1) {
+ int i;
+ tuner_dbg("bufs is: ");
+ for(i=0;i<6;i++)
+ printk("%x ",buf[i]);
+ printk("\n");
+ }
+
+ ret=i2c_master_send(c,buf,6);
+ if (ret!=6)
+ tuner_warn("i2c i/o error: rc == %d (should be 6)\n",ret);
+}
+
+static void mt2050_set_tv_freq(struct i2c_client *c, unsigned int freq)
+{
+ struct tuner *t = i2c_get_clientdata(c);
+ unsigned int if2;
+
+ if (t->std & V4L2_STD_525_60) {
+ // NTSC
+ if2 = 45750*1000;
+ } else {
+ // PAL
+ if2 = 38900*1000;
+ }
+ if (V4L2_TUNER_DIGITAL_TV == t->mode) {
+ // DVB (pinnacle 300i)
+ if2 = 36150*1000;
+ }
+ mt2050_set_if_freq(c, freq*62500, if2);
+ mt2050_set_antenna(c, tv_antenna);
+}
+
+static void mt2050_set_radio_freq(struct i2c_client *c, unsigned int freq)
+{
+ struct tuner *t = i2c_get_clientdata(c);
+ int if2 = t->radio_if2;
+
+ mt2050_set_if_freq(c, freq*62500, if2);
+ mt2050_set_antenna(c, radio_antenna);
+}
+
+static int mt2050_init(struct i2c_client *c)
+{
+ struct tuner *t = i2c_get_clientdata(c);
+ unsigned char buf[2];
+ int ret;
+
+ buf[0]=6;
+ buf[1]=0x10;
+ ret=i2c_master_send(c,buf,2); // power
+
+ buf[0]=0x0f;
+ buf[1]=0x0f;
+ ret=i2c_master_send(c,buf,2); // m1lo
+
+ buf[0]=0x0d;
+ ret=i2c_master_send(c,buf,1);
+ 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;
+ return 0;
+}
+
+int microtune_init(struct i2c_client *c)
+{
+ struct tuner *t = i2c_get_clientdata(c);
+ char *name;
+ unsigned char buf[21];
+ int company_code;
+
+ memset(buf,0,sizeof(buf));
+ t->tv_freq = NULL;
+ t->radio_freq = NULL;
+ name = "unknown";
+
+ i2c_master_send(c,buf,1);
+ i2c_master_recv(c,buf,21);
+ if (tuner_debug) {
+ int i;
+ tuner_dbg("MT20xx hexdump:");
+ for(i=0;i<21;i++) {
+ printk(" %02x",buf[i]);
+ if(((i+1)%8)==0) printk(" ");
+ }
+ printk("\n");
+ }
+ company_code = buf[0x11] << 8 | buf[0x12];
+ tuner_info("microtune: companycode=%04x part=%02x rev=%02x\n",
+ company_code,buf[0x13],buf[0x14]);
+
+#if 0
+ /* seems to cause more problems than it solves ... */
+ switch (company_code) {
+ case 0x30bf:
+ case 0x3cbf:
+ case 0x3dbf:
+ case 0x4d54:
+ case 0x8e81:
+ case 0x8e91:
+ /* ok (?) */
+ break;
+ default:
+ tuner_warn("tuner: microtune: unknown companycode\n");
+ return 0;
+ }
+#endif
+
+ if (buf[0x13] < ARRAY_SIZE(microtune_part) &&
+ NULL != microtune_part[buf[0x13]])
+ name = microtune_part[buf[0x13]];
+ switch (buf[0x13]) {
+ case MT2032:
+ mt2032_init(c);
+ break;
+ case MT2050:
+ mt2050_init(c);
+ break;
+ default:
+ tuner_info("microtune %s found, not (yet?) supported, sorry :-/\n",
+ name);
+ return 0;
+ }
+
+ strlcpy(c->name, name, sizeof(c->name));
+ tuner_info("microtune %s found, OK\n",name);
+ return 0;
+}
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/video/ovcamchip/ovcamchip_core.c b/drivers/media/video/ovcamchip/ovcamchip_core.c
index 67f2fc4a4f9f2..54dd5612d3b82 100644
--- a/drivers/media/video/ovcamchip/ovcamchip_core.c
+++ b/drivers/media/video/ovcamchip/ovcamchip_core.c
@@ -422,7 +422,6 @@ static struct i2c_driver driver = {
static struct i2c_client client_template = {
I2C_DEVNAME("(unset)"),
- .id = -1,
.driver = &driver,
};
diff --git a/drivers/media/video/planb.c b/drivers/media/video/planb.c
index 10eb49b5b709b..b19c33434eaf8 100644
--- a/drivers/media/video/planb.c
+++ b/drivers/media/video/planb.c
@@ -40,6 +40,7 @@
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/videodev.h>
+#include <linux/wait.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/prom.h>
@@ -421,6 +422,16 @@ static void planb_prepare_close(struct planb *pb)
/* overlay support functions */
/*****************************/
+static inline int overlay_is_active(struct planb *pb)
+{
+ unsigned int size = pb->tab_size * sizeof(struct dbdma_cmd);
+ unsigned int caddr = (unsigned)in_le32(&pb->planb_base->ch1.cmdptr);
+
+ return (in_le32(&pb->overlay_last1->cmd_dep) == pb->ch1_cmd_phys)
+ && (caddr < (pb->ch1_cmd_phys + size))
+ && (caddr >= (unsigned)pb->ch1_cmd_phys);
+}
+
static void overlay_start(struct planb *pb)
{
@@ -852,16 +863,6 @@ static int palette2fmt[] = {
#define PLANB_PALETTE_MAX 15
-static inline int overlay_is_active(struct planb *pb)
-{
- unsigned int size = pb->tab_size * sizeof(struct dbdma_cmd);
- unsigned int caddr = (unsigned)in_le32(&pb->planb_base->ch1.cmdptr);
-
- return (in_le32(&pb->overlay_last1->cmd_dep) == pb->ch1_cmd_phys)
- && (caddr < (pb->ch1_cmd_phys + size))
- && (caddr >= (unsigned)pb->ch1_cmd_phys);
-}
-
static int vgrab(struct planb *pb, struct video_mmap *mp)
{
unsigned int fr = mp->frame;
@@ -1609,8 +1610,7 @@ static int planb_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
}
planb_lock(pb);
/* empty the grabbing queue */
- while(pb->grabbing)
- interruptible_sleep_on(&pb->capq);
+ wait_event(pb->capq, !pb->grabbing);
pb->maxlines = maxlines;
pb->win.norm = v.norm;
/* Stop overlay if running */
diff --git a/drivers/media/video/saa5246a.c b/drivers/media/video/saa5246a.c
index 86a57b70bc8ee..ba69f09cbdd1f 100644
--- a/drivers/media/video/saa5246a.c
+++ b/drivers/media/video/saa5246a.c
@@ -65,18 +65,7 @@ static struct video_device saa_template; /* Declared near bottom */
/* Addresses to scan */
static unsigned short normal_i2c[] = { I2C_ADDRESS, I2C_CLIENT_END };
static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
-static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short force[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-
-static struct i2c_client_address_data addr_data = {
- normal_i2c, normal_i2c_range,
- probe, probe_range,
- ignore, ignore_range,
- force
-};
+I2C_CLIENT_INSMOD;
static struct i2c_client client_template;
@@ -185,7 +174,6 @@ static struct i2c_driver i2c_driver_videotext =
};
static struct i2c_client client_template = {
- .id = -1,
.driver = &i2c_driver_videotext,
.name = "(unset)",
};
diff --git a/drivers/media/video/saa5249.c b/drivers/media/video/saa5249.c
index e9846574e804a..d74caa139f0a7 100644
--- a/drivers/media/video/saa5249.c
+++ b/drivers/media/video/saa5249.c
@@ -133,18 +133,7 @@ static struct video_device saa_template; /* Declared near bottom */
/* Addresses to scan */
static unsigned short normal_i2c[] = {34>>1,I2C_CLIENT_END};
static unsigned short normal_i2c_range[] = {I2C_CLIENT_END};
-static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short force[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-
-static struct i2c_client_address_data addr_data = {
- normal_i2c, normal_i2c_range,
- probe, probe_range,
- ignore, ignore_range,
- force
-};
+I2C_CLIENT_INSMOD;
static struct i2c_client client_template;
@@ -258,7 +247,6 @@ static struct i2c_driver i2c_driver_videotext =
};
static struct i2c_client client_template = {
- .id = -1,
.driver = &i2c_driver_videotext,
.name = "(unset)",
};
diff --git a/drivers/media/video/saa7110.c b/drivers/media/video/saa7110.c
index 4d8c922667fa0..64273b4385303 100644
--- a/drivers/media/video/saa7110.c
+++ b/drivers/media/video/saa7110.c
@@ -30,6 +30,7 @@
#include <linux/types.h>
#include <linux/delay.h>
#include <linux/slab.h>
+#include <linux/wait.h>
#include <asm/io.h>
#include <asm/uaccess.h>
@@ -60,8 +61,10 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)");
#define I2C_SAA7110 0x9C /* or 0x9E */
+#define SAA7110_NR_REG 0x35
+
struct saa7110 {
- unsigned char reg[54];
+ u8 reg[SAA7110_NR_REG];
int norm;
int input;
@@ -95,31 +98,28 @@ saa7110_write_block (struct i2c_client *client,
unsigned int len)
{
int ret = -1;
- u8 reg = *data++;
+ u8 reg = *data; /* first register to write to */
- len--;
+ /* Sanity check */
+ if (reg + (len - 1) > SAA7110_NR_REG)
+ return ret;
/* the saa7110 has an autoincrement function, use it if
* the adapter understands raw I2C */
if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
struct saa7110 *decoder = i2c_get_clientdata(client);
struct i2c_msg msg;
- u8 block_data[54];
- msg.len = 0;
- msg.buf = (char *) block_data;
+ msg.len = len;
+ msg.buf = (char *) data;
msg.addr = client->addr;
- msg.flags = client->flags;
- while (len >= 1) {
- msg.len = 0;
- block_data[msg.len++] = reg;
- while (len-- >= 1 && msg.len < 54)
- block_data[msg.len++] =
- decoder->reg[reg++] = *data++;
- ret = i2c_transfer(client->adapter, &msg, 1);
- }
+ msg.flags = 0;
+ ret = i2c_transfer(client->adapter, &msg, 1);
+
+ /* Cache the written data */
+ memcpy(decoder->reg + reg, data + 1, len - 1);
} else {
- while (len-- >= 1) {
+ for (++data, --len; len; len--) {
if ((ret = saa7110_write(client, reg++,
*data++)) < 0)
break;
@@ -192,7 +192,7 @@ saa7110_selmux (struct i2c_client *client,
return 0;
}
-static const unsigned char initseq[] = {
+static const unsigned char initseq[1 + SAA7110_NR_REG] = {
0, 0x4C, 0x3C, 0x0D, 0xEF, 0xBD, 0xF2, 0x03, 0x00,
/* 0x08 */ 0xF8, 0xF8, 0x60, 0x60, 0x00, 0x86, 0x18, 0x90,
/* 0x10 */ 0x00, 0x59, 0x40, 0x46, 0x42, 0x1A, 0xFF, 0xDA,
@@ -205,13 +205,16 @@ static const unsigned char initseq[] = {
static int
determine_norm (struct i2c_client *client)
{
+ DEFINE_WAIT(wait);
struct saa7110 *decoder = i2c_get_clientdata(client);
int status;
/* mode changed, start automatic detection */
saa7110_write_block(client, initseq, sizeof(initseq));
saa7110_selmux(client, decoder->input);
- sleep_on_timeout(&decoder->wq, HZ / 4);
+ prepare_to_wait(&decoder->wq, &wait, TASK_UNINTERRUPTIBLE);
+ schedule_timeout(HZ/4);
+ finish_wait(&decoder->wq, &wait);
status = saa7110_read(client);
if (status & 0x40) {
dprintk(1, KERN_INFO "%s: status=0x%02x (no signal)\n",
@@ -250,7 +253,9 @@ determine_norm (struct i2c_client *client)
saa7110_write(client, 0x11, 0x59);
//saa7110_write(client,0x2E,0x9A);
- sleep_on_timeout(&decoder->wq, HZ / 4);
+ prepare_to_wait(&decoder->wq, &wait, TASK_UNINTERRUPTIBLE);
+ schedule_timeout(HZ/4);
+ finish_wait(&decoder->wq, &wait);
status = saa7110_read(client);
if ((status & 0x03) == 0x01) {
@@ -476,7 +481,6 @@ static struct i2c_client_address_data addr_data = {
.force = force
};
-static int saa7110_i2c_id = 0;
static struct i2c_driver i2c_driver_saa7110;
static int
@@ -507,9 +511,7 @@ saa7110_detect_client (struct i2c_adapter *adapter,
client->adapter = adapter;
client->driver = &i2c_driver_saa7110;
client->flags = I2C_CLIENT_ALLOW_USE;
- client->id = saa7110_i2c_id++;
- snprintf(I2C_NAME(client), sizeof(I2C_NAME(client)) - 1,
- "saa7110[%d]", client->id);
+ strlcpy(I2C_NAME(client), "saa7110", sizeof(I2C_NAME(client)));
decoder = kmalloc(sizeof(struct saa7110), GFP_KERNEL);
if (decoder == 0) {
diff --git a/drivers/media/video/saa7111.c b/drivers/media/video/saa7111.c
index cb53427d3fb1d..0a873112ae23d 100644
--- a/drivers/media/video/saa7111.c
+++ b/drivers/media/video/saa7111.c
@@ -500,7 +500,6 @@ static struct i2c_client_address_data addr_data = {
.force = force
};
-static int saa7111_i2c_id = 0;
static struct i2c_driver i2c_driver_saa7111;
static int
@@ -530,9 +529,7 @@ saa7111_detect_client (struct i2c_adapter *adapter,
client->adapter = adapter;
client->driver = &i2c_driver_saa7111;
client->flags = I2C_CLIENT_ALLOW_USE;
- client->id = saa7111_i2c_id++;
- snprintf(I2C_NAME(client), sizeof(I2C_NAME(client)) - 1,
- "saa7111[%d]", client->id);
+ strlcpy(I2C_NAME(client), "saa7111", sizeof(I2C_NAME(client)));
decoder = kmalloc(sizeof(struct saa7111), GFP_KERNEL);
if (decoder == NULL) {
diff --git a/drivers/media/video/saa7114.c b/drivers/media/video/saa7114.c
index 627457ad77ee8..e73023695e585 100644
--- a/drivers/media/video/saa7114.c
+++ b/drivers/media/video/saa7114.c
@@ -163,7 +163,7 @@ saa7114_write_block (struct i2c_client *client,
u8 block_data[32];
msg.addr = client->addr;
- msg.flags = client->flags;
+ msg.flags = 0;
while (len >= 2) {
msg.buf = (char *) block_data;
msg.len = 0;
@@ -838,7 +838,6 @@ static struct i2c_client_address_data addr_data = {
.force = force
};
-static int saa7114_i2c_id = 0;
static struct i2c_driver i2c_driver_saa7114;
static int
@@ -871,9 +870,7 @@ saa7114_detect_client (struct i2c_adapter *adapter,
client->adapter = adapter;
client->driver = &i2c_driver_saa7114;
client->flags = I2C_CLIENT_ALLOW_USE;
- client->id = saa7114_i2c_id++;
- snprintf(I2C_NAME(client), sizeof(I2C_NAME(client)) - 1,
- "saa7114[%d]", client->id);
+ strlcpy(I2C_NAME(client), "saa7114", sizeof(I2C_NAME(client)));
decoder = kmalloc(sizeof(struct saa7114), GFP_KERNEL);
if (decoder == NULL) {
diff --git a/drivers/media/video/saa7134/Makefile b/drivers/media/video/saa7134/Makefile
index 25028cead1f02..e577a06b136b4 100644
--- a/drivers/media/video/saa7134/Makefile
+++ b/drivers/media/video/saa7134/Makefile
@@ -8,3 +8,4 @@ obj-$(CONFIG_VIDEO_SAA7134_DVB) += saa7134-dvb.o
EXTRA_CFLAGS += -I$(src)/..
EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/dvb-core
+EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/frontends
diff --git a/drivers/media/video/saa7134/saa6752hs.c b/drivers/media/video/saa7134/saa6752hs.c
index 5fdff48292295..cee13584c9cfa 100644
--- a/drivers/media/video/saa7134/saa6752hs.c
+++ b/drivers/media/video/saa7134/saa6752hs.c
@@ -11,9 +11,14 @@
#include <linux/types.h>
#include <linux/videodev.h>
#include <linux/init.h>
+#include <linux/crc32.h>
#include <media/id.h>
-#include <media/saa6752hs.h>
+
+#define MPEG_VIDEO_TARGET_BITRATE_MAX 27000
+#define MPEG_VIDEO_MAX_BITRATE_MAX 27000
+#define MPEG_TOTAL_TARGET_BITRATE_MAX 27000
+#define MPEG_PID_MAX ((1 << 14) - 1)
/* Addresses to scan */
static unsigned short normal_i2c[] = {0x20, I2C_CLIENT_END};
@@ -27,6 +32,10 @@ MODULE_LICENSE("GPL");
static struct i2c_driver driver;
static struct i2c_client client_template;
+struct saa6752hs_state {
+ struct i2c_client client;
+ struct v4l2_mpeg_compression params;
+};
enum saa6752hs_command {
SAA6752HS_COMMAND_RESET = 0,
@@ -40,7 +49,6 @@ enum saa6752hs_command {
SAA6752HS_COMMAND_MAX
};
-
/* ---------------------------------------------------------------------- */
static u8 PAT[] = {
@@ -64,9 +72,9 @@ static u8 PAT[] = {
0x00, 0x01, // program_number(1)
- 0xe0, 0x10, // PMT PID(0x10)
+ 0xe0, 0x00, // PMT PID
- 0x76, 0xf1, 0x44, 0xd1 // CRC32
+ 0x00, 0x00, 0x00, 0x00 // CRC32
};
static u8 PMT[] = {
@@ -74,7 +82,7 @@ static u8 PMT[] = {
0x01, // table number for encoder
0x47, // sync
- 0x40, 0x10, // transport_error_indicator(0), payload_unit_start(1), transport_priority(0), pid(0x10)
+ 0x40, 0x00, // transport_error_indicator(0), payload_unit_start(1), transport_priority(0), pid
0x10, // transport_scrambling_control(00), adaptation_field_control(01), continuity_counter(0)
0x00, // PSI pointer to start of table
@@ -88,28 +96,51 @@ static u8 PMT[] = {
0x00, 0x00, // section_number(0), last_section_number(0)
- 0xe1, 0x04, // PCR_PID (0x104)
+ 0xe0, 0x00, // PCR_PID
0xf0, 0x00, // program_info_length(0)
- 0x02, 0xe1, 0x00, 0xf0, 0x00, // video stream type(2), pid(0x100)
- 0x04, 0xe1, 0x03, 0xf0, 0x00, // audio stream type(4), pid(0x103)
+ 0x02, 0xe0, 0x00, 0xf0, 0x00, // video stream type(2), pid
+ 0x04, 0xe0, 0x00, 0xf0, 0x00, // audio stream type(4), pid
- 0xa1, 0xca, 0x0f, 0x82 // CRC32
+ 0x00, 0x00, 0x00, 0x00 // CRC32
};
-static struct mpeg_params mpeg_params_template =
+static struct v4l2_mpeg_compression param_defaults =
{
- .bitrate_mode = MPEG_BITRATE_MODE_CBR,
- .video_target_bitrate = 5000,
- .audio_bitrate = MPEG_AUDIO_BITRATE_256,
- .total_bitrate = 6000,
+ .st_type = V4L2_MPEG_TS_2,
+ .st_bitrate = {
+ .mode = V4L2_BITRATE_CBR,
+ .target = 7000,
+ },
+
+ .ts_pid_pmt = 16,
+ .ts_pid_video = 260,
+ .ts_pid_audio = 256,
+ .ts_pid_pcr = 259,
+
+ .vi_type = V4L2_MPEG_VI_2,
+ .vi_aspect_ratio = V4L2_MPEG_ASPECT_4_3,
+ .vi_bitrate = {
+ .mode = V4L2_BITRATE_VBR,
+ .target = 4000,
+ .max = 6000,
+ },
+
+ .au_type = V4L2_MPEG_AU_2_II,
+ .au_bitrate = {
+ .mode = V4L2_BITRATE_CBR,
+ .target = 256,
+ },
+
+#if 0
+ /* FIXME: size? via S_FMT? */
+ .video_format = MPEG_VIDEO_FORMAT_D1,
+#endif
};
-
/* ---------------------------------------------------------------------- */
-
static int saa6752hs_chip_command(struct i2c_client* client,
enum saa6752hs_command command)
{
@@ -124,7 +155,7 @@ static int saa6752hs_chip_command(struct i2c_client* client,
break;
case SAA6752HS_COMMAND_STOP:
- buf[0] = 0x03;
+ buf[0] = 0x03;
break;
case SAA6752HS_COMMAND_START:
@@ -180,74 +211,117 @@ static int saa6752hs_chip_command(struct i2c_client* client,
static int saa6752hs_set_bitrate(struct i2c_client* client,
- struct mpeg_params* params)
+ struct v4l2_mpeg_compression* params)
{
u8 buf[3];
// set the bitrate mode
buf[0] = 0x71;
- buf[1] = params->bitrate_mode;
+ buf[1] = (params->vi_bitrate.mode == V4L2_BITRATE_VBR) ? 0 : 1;
i2c_master_send(client, buf, 2);
// set the video bitrate
- if (params->bitrate_mode == MPEG_BITRATE_MODE_VBR) {
+ if (params->vi_bitrate.mode == V4L2_BITRATE_VBR) {
// set the target bitrate
buf[0] = 0x80;
- buf[1] = params->video_target_bitrate >> 8;
- buf[2] = params->video_target_bitrate & 0xff;
+ buf[1] = params->vi_bitrate.target >> 8;
+ buf[2] = params->vi_bitrate.target & 0xff;
i2c_master_send(client, buf, 3);
// set the max bitrate
buf[0] = 0x81;
- buf[1] = params->video_max_bitrate >> 8;
- buf[2] = params->video_max_bitrate & 0xff;
+ buf[1] = params->vi_bitrate.max >> 8;
+ buf[2] = params->vi_bitrate.max & 0xff;
i2c_master_send(client, buf, 3);
} else {
// set the target bitrate (no max bitrate for CBR)
buf[0] = 0x81;
- buf[1] = params->video_target_bitrate >> 8;
- buf[2] = params->video_target_bitrate & 0xff;
+ buf[1] = params->vi_bitrate.target >> 8;
+ buf[2] = params->vi_bitrate.target & 0xff;
i2c_master_send(client, buf, 3);
}
// set the audio bitrate
buf[0] = 0x94;
- buf[1] = params->audio_bitrate;
+ buf[1] = (256 == params->au_bitrate.target) ? 0 : 1;
i2c_master_send(client, buf, 2);
// set the total bitrate
buf[0] = 0xb1;
- buf[1] = params->total_bitrate >> 8;
- buf[2] = params->total_bitrate & 0xff;
+ buf[1] = params->st_bitrate.target >> 8;
+ buf[2] = params->st_bitrate.target & 0xff;
i2c_master_send(client, buf, 3);
+ // return success
return 0;
}
-static int saa6752hs_init(struct i2c_client* client, struct mpeg_params* params)
+static void saa6752hs_set_params(struct i2c_client* client,
+ struct v4l2_mpeg_compression* params)
{
- unsigned char buf[3];
- void *data;
-
- // check the bitrate parameters first
- if (params != NULL) {
- if (params->bitrate_mode >= MPEG_BITRATE_MODE_MAX)
- return -EINVAL;
- if (params->video_target_bitrate >= MPEG_VIDEO_TARGET_BITRATE_MAX)
- return -EINVAL;
- if (params->video_max_bitrate >= MPEG_VIDEO_MAX_BITRATE_MAX)
- return -EINVAL;
- if (params->audio_bitrate >= MPEG_AUDIO_BITRATE_MAX)
- return -EINVAL;
- if (params->total_bitrate >= MPEG_TOTAL_BITRATE_MAX)
- return -EINVAL;
- if (params->bitrate_mode == MPEG_BITRATE_MODE_MAX &&
- params->video_target_bitrate <= params->video_max_bitrate)
- return -EINVAL;
- }
+ struct saa6752hs_state *h = i2c_get_clientdata(client);
+
+ /* check PIDs */
+ if (params->ts_pid_pmt <= MPEG_PID_MAX)
+ h->params.ts_pid_pmt = params->ts_pid_pmt;
+ if (params->ts_pid_pcr <= MPEG_PID_MAX)
+ h->params.ts_pid_pcr = params->ts_pid_pcr;
+ if (params->ts_pid_video <= MPEG_PID_MAX)
+ h->params.ts_pid_video = params->ts_pid_video;
+ if (params->ts_pid_audio <= MPEG_PID_MAX)
+ h->params.ts_pid_audio = params->ts_pid_audio;
+
+ /* check bitrate parameters */
+ if ((params->vi_bitrate.mode == V4L2_BITRATE_CBR) ||
+ (params->vi_bitrate.mode == V4L2_BITRATE_VBR))
+ h->params.vi_bitrate.mode = params->vi_bitrate.mode;
+ if (params->vi_bitrate.mode != V4L2_BITRATE_NONE)
+ h->params.st_bitrate.target = params->st_bitrate.target;
+ if (params->vi_bitrate.mode != V4L2_BITRATE_NONE)
+ h->params.vi_bitrate.target = params->vi_bitrate.target;
+ if (params->vi_bitrate.mode == V4L2_BITRATE_VBR)
+ h->params.vi_bitrate.max = params->vi_bitrate.max;
+ if (params->au_bitrate.mode != V4L2_BITRATE_NONE)
+ h->params.au_bitrate.target = params->au_bitrate.target;
+
+ /* aspect ratio */
+ if (params->vi_aspect_ratio == V4L2_MPEG_ASPECT_4_3 ||
+ params->vi_aspect_ratio == V4L2_MPEG_ASPECT_16_9)
+ h->params.vi_aspect_ratio = params->vi_aspect_ratio;
+
+ /* range checks */
+ if (h->params.st_bitrate.target > MPEG_TOTAL_TARGET_BITRATE_MAX)
+ h->params.st_bitrate.target = MPEG_TOTAL_TARGET_BITRATE_MAX;
+ if (h->params.vi_bitrate.target > MPEG_VIDEO_TARGET_BITRATE_MAX)
+ h->params.vi_bitrate.target = MPEG_VIDEO_TARGET_BITRATE_MAX;
+ if (h->params.vi_bitrate.max > MPEG_VIDEO_MAX_BITRATE_MAX)
+ h->params.vi_bitrate.max = MPEG_VIDEO_MAX_BITRATE_MAX;
+ if (h->params.au_bitrate.target <= 256)
+ h->params.au_bitrate.target = 256;
+ else
+ h->params.au_bitrate.target = 384;
+}
- // Set GOP structure {3, 13}
+static int saa6752hs_init(struct i2c_client* client)
+{
+ unsigned char buf[9], buf2[4];
+ struct saa6752hs_state *h;
+ u32 crc;
+ unsigned char localPAT[256];
+ unsigned char localPMT[256];
+
+ h = i2c_get_clientdata(client);
+
+ // Set video format - must be done first as it resets other settings
+ buf[0] = 0x41;
+ buf[1] = 0 /* MPEG_VIDEO_FORMAT_D1 */;
+ i2c_master_send(client, buf, 2);
+
+ // set bitrate
+ saa6752hs_set_bitrate(client, &h->params);
+
+ // Set GOP structure {3, 13}
buf[0] = 0x72;
buf[1] = 0x03;
buf[2] = 0x0D;
@@ -265,7 +339,7 @@ static int saa6752hs_init(struct i2c_client* client, struct mpeg_params* params)
// Set Output Protocol
buf[0] = 0xD0;
- buf[1] = 0x01;
+ buf[1] = 0x81;
i2c_master_send(client,buf,2);
// Set video output stream format {TS}
@@ -273,25 +347,53 @@ static int saa6752hs_init(struct i2c_client* client, struct mpeg_params* params)
buf[1] = 0x05;
i2c_master_send(client,buf,2);
- // Set Audio PID {0x103}
+ /* compute PAT */
+ memcpy(localPAT, PAT, sizeof(PAT));
+ localPAT[17] = 0xe0 | ((h->params.ts_pid_pmt >> 8) & 0x0f);
+ localPAT[18] = h->params.ts_pid_pmt & 0xff;
+ crc = crc32_be(~0, &localPAT[7], sizeof(PAT) - 7 - 4);
+ localPAT[sizeof(PAT) - 4] = (crc >> 24) & 0xFF;
+ localPAT[sizeof(PAT) - 3] = (crc >> 16) & 0xFF;
+ localPAT[sizeof(PAT) - 2] = (crc >> 8) & 0xFF;
+ localPAT[sizeof(PAT) - 1] = crc & 0xFF;
+
+ /* compute PMT */
+ memcpy(localPMT, PMT, sizeof(PMT));
+ localPMT[3] = 0x40 | ((h->params.ts_pid_pmt >> 8) & 0x0f);
+ localPMT[4] = h->params.ts_pid_pmt & 0xff;
+ localPMT[15] = 0xE0 | ((h->params.ts_pid_pcr >> 8) & 0x0F);
+ localPMT[16] = h->params.ts_pid_pcr & 0xFF;
+ localPMT[20] = 0xE0 | ((h->params.ts_pid_video >> 8) & 0x0F);
+ localPMT[21] = h->params.ts_pid_video & 0xFF;
+ localPMT[25] = 0xE0 | ((h->params.ts_pid_audio >> 8) & 0x0F);
+ localPMT[26] = h->params.ts_pid_audio & 0xFF;
+ crc = crc32_be(~0, &localPMT[7], sizeof(PMT) - 7 - 4);
+ localPMT[sizeof(PMT) - 4] = (crc >> 24) & 0xFF;
+ localPMT[sizeof(PMT) - 3] = (crc >> 16) & 0xFF;
+ localPMT[sizeof(PMT) - 2] = (crc >> 8) & 0xFF;
+ localPMT[sizeof(PMT) - 1] = crc & 0xFF;
+
+ // Set Audio PID
buf[0] = 0xC1;
- buf[1] = 0x01;
- buf[2] = 0x03;
+ buf[1] = (h->params.ts_pid_audio >> 8) & 0xFF;
+ buf[2] = h->params.ts_pid_audio & 0xFF;
i2c_master_send(client,buf,3);
- // setup bitrate settings
- data = i2c_get_clientdata(client);
- if (params) {
- saa6752hs_set_bitrate(client, params);
- memcpy(data, params, sizeof(struct mpeg_params));
- } else {
- // parameters were not supplied. use the previous set
- saa6752hs_set_bitrate(client, (struct mpeg_params*) data);
- }
+ // Set Video PID
+ buf[0] = 0xC0;
+ buf[1] = (h->params.ts_pid_video >> 8) & 0xFF;
+ buf[2] = h->params.ts_pid_video & 0xFF;
+ i2c_master_send(client,buf,3);
+
+ // Set PCR PID
+ buf[0] = 0xC4;
+ buf[1] = (h->params.ts_pid_pcr >> 8) & 0xFF;
+ buf[2] = h->params.ts_pid_pcr & 0xFF;
+ i2c_master_send(client,buf,3);
// Send SI tables
- i2c_master_send(client,PAT,sizeof(PAT));
- i2c_master_send(client,PMT,sizeof(PMT));
+ i2c_master_send(client,localPAT,sizeof(PAT));
+ i2c_master_send(client,localPMT,sizeof(PMT));
// mute then unmute audio. This removes buzzing artefacts
buf[0] = 0xa4;
@@ -303,31 +405,56 @@ static int saa6752hs_init(struct i2c_client* client, struct mpeg_params* params)
// start it going
saa6752hs_chip_command(client, SAA6752HS_COMMAND_START);
+ // readout current state
+ buf[0] = 0xE1;
+ buf[1] = 0xA7;
+ buf[2] = 0xFE;
+ buf[3] = 0x82;
+ buf[4] = 0xB0;
+ i2c_master_send(client, buf, 5);
+ i2c_master_recv(client, buf2, 4);
+
+ // change aspect ratio
+ buf[0] = 0xE0;
+ buf[1] = 0xA7;
+ buf[2] = 0xFE;
+ buf[3] = 0x82;
+ buf[4] = 0xB0;
+ buf[5] = buf2[0];
+ switch(h->params.vi_aspect_ratio) {
+ case V4L2_MPEG_ASPECT_16_9:
+ buf[6] = buf2[1] | 0x40;
+ break;
+ case V4L2_MPEG_ASPECT_4_3:
+ default:
+ buf[6] = buf2[1] & 0xBF;
+ break;
+ break;
+ }
+ buf[7] = buf2[2];
+ buf[8] = buf2[3];
+ i2c_master_send(client, buf, 9);
+
+ // return success
return 0;
}
static int saa6752hs_attach(struct i2c_adapter *adap, int addr, int kind)
{
- struct i2c_client *client;
- struct mpeg_params* params;
-
- client_template.adapter = adap;
- client_template.addr = addr;
+ struct saa6752hs_state *h;
printk("saa6752hs: chip found @ 0x%x\n", addr<<1);
- if (NULL == (client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL)))
+ if (NULL == (h = kmalloc(sizeof(*h), GFP_KERNEL)))
return -ENOMEM;
- memcpy(client,&client_template,sizeof(struct i2c_client));
- strlcpy(client->name, "saa6752hs", sizeof(client->name));
-
- if (NULL == (params = kmalloc(sizeof(struct mpeg_params), GFP_KERNEL)))
- return -ENOMEM;
- memcpy(params,&mpeg_params_template,sizeof(struct mpeg_params));
- i2c_set_clientdata(client, params);
-
- i2c_attach_client(client);
-
+ memset(h,0,sizeof(*h));
+ h->client = client_template;
+ h->params = param_defaults;
+ h->client.adapter = adap;
+ h->client.addr = addr;
+
+ i2c_set_clientdata(&h->client, h);
+ i2c_attach_client(&h->client);
return 0;
}
@@ -340,30 +467,39 @@ static int saa6752hs_probe(struct i2c_adapter *adap)
static int saa6752hs_detach(struct i2c_client *client)
{
- void *data;
+ struct saa6752hs_state *h;
- data = i2c_get_clientdata(client);
+ h = i2c_get_clientdata(client);
i2c_detach_client(client);
- kfree(data);
- kfree(client);
+ kfree(h);
return 0;
}
static int
saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg)
{
- struct mpeg_params* init_arg = arg;
+ struct saa6752hs_state *h = i2c_get_clientdata(client);
+ struct v4l2_mpeg_compression *params = arg;
+ int err = 0;
switch (cmd) {
- case MPEG_SETPARAMS:
- return saa6752hs_init(client, init_arg);
-
+ case VIDIOC_S_MPEGCOMP:
+ if (NULL == params) {
+ /* apply settings and start encoder */
+ saa6752hs_init(client);
+ break;
+ }
+ saa6752hs_set_params(client, params);
+ /* fall through */
+ case VIDIOC_G_MPEGCOMP:
+ *params = h->params;
+ break;
default:
/* nothing */
break;
}
- return 0;
+ return err;
}
/* ----------------------------------------------------------------------- */
@@ -380,7 +516,7 @@ static struct i2c_driver driver = {
static struct i2c_client client_template =
{
- I2C_DEVNAME("(saa6752hs unset)"),
+ I2C_DEVNAME("saa6752hs"),
.flags = I2C_CLIENT_ALLOW_USE,
.driver = &driver,
};
diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c
index 53bce030fd42d..180d3175ea5b9 100644
--- a/drivers/media/video/saa7134/saa7134-cards.c
+++ b/drivers/media/video/saa7134/saa7134-cards.c
@@ -1,5 +1,6 @@
+
/*
- * $Id: saa7134-cards.c,v 1.35 2004/11/07 14:44:59 kraxel Exp $
+ * $Id: saa7134-cards.c,v 1.54 2005/03/07 12:01:51 kraxel Exp $
*
* device driver for philips saa7134 based TV cards
* card-specific stuff.
@@ -156,11 +157,11 @@ struct saa7134_board saa7134_boards[] = {
.gpio = 0x8000,
},
},
- [SAA7134_BOARD_FLYTVPLATINUM] = {
+ [SAA7134_BOARD_FLYTVPLATINUM_MINI] = {
/* "Arnaud Quette" <aquette@free.fr> */
- .name = "LifeView FlyTV Platinum",
+ .name = "LifeView FlyTV Platinum Mini",
.audio_clock = 0x00200000,
- .tuner_type = TUNER_PHILIPS_SECAM,
+ .tuner_type = TUNER_PHILIPS_TDA8290,
.inputs = {{
.name = name_tv,
.vmux = 1,
@@ -176,6 +177,47 @@ struct saa7134_board saa7134_boards[] = {
.amux = LINE2,
}},
},
+ [SAA7134_BOARD_FLYTVPLATINUM_FM] = {
+ /* LifeView FlyTV Platinum FM (LR214WF) */
+ /* "Peter Missel <peter.missel@onlinehome.de> */
+ .name = "LifeView FlyTV Platinum FM",
+ .audio_clock = 0x00200000,
+ .tuner_type = TUNER_PHILIPS_TDA8290,
+// .gpiomask = 0xe000,
+ .inputs = {{
+ .name = name_tv,
+ .vmux = 1,
+ .amux = TV,
+// .gpio = 0x0000,
+ .tv = 1,
+ },{
+/* .name = name_tv_mono,
+ .vmux = 1,
+ .amux = LINE2,
+ .gpio = 0x0000,
+ .tv = 1,
+ },{
+*/ .name = name_comp1, /* Composite signal on S-Video input */
+ .vmux = 0,
+ .amux = LINE2,
+// .gpio = 0x4000,
+ },{
+ .name = name_comp2, /* Composite input */
+ .vmux = 3,
+ .amux = LINE2,
+// .gpio = 0x4000,
+ },{
+ .name = name_svideo, /* S-Video signal on S-Video input */
+ .vmux = 8,
+ .amux = LINE2,
+// .gpio = 0x4000,
+ }},
+/* .radio = {
+ .name = name_radio,
+ .amux = LINE2,
+ .gpio = 0x2000,
+ },
+*/ },
[SAA7134_BOARD_EMPRESS] = {
/* "Gert Vervoort" <gert.vervoort@philips.com> */
.name = "EMPRESS",
@@ -436,6 +478,7 @@ struct saa7134_board saa7134_boards[] = {
.audio_clock = 0x00187de7,
.tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
.tda9887_conf = TDA9887_PRESENT,
+ .mpeg = SAA7134_MPEG_DVB,
.inputs = {{
.name = name_tv,
.vmux = 1,
@@ -444,11 +487,11 @@ struct saa7134_board saa7134_boards[] = {
},{
.name = name_comp1,
.vmux = 0,
- .amux = LINE2,
+ .amux = LINE1,
},{
.name = name_svideo,
.vmux = 8,
- .amux = LINE2,
+ .amux = LINE1,
}},
.radio = {
.name = name_radio,
@@ -544,6 +587,34 @@ struct saa7134_board saa7134_boards[] = {
.amux = LINE1,
},
},
+ [SAA7135_BOARD_ASUSTeK_TVFM7135] = {
+ .name = "ASUS TV-FM 7135",
+ .audio_clock = 0x00187de7,
+ .tuner_type = TUNER_PHILIPS_TDA8290,
+ .gpiomask = 0x200000,
+ .inputs = {{
+ .name = name_tv,
+ .vmux = 1,
+ .amux = TV,
+ .gpio = 0x0000,
+ .tv = 1,
+ },{
+ .name = name_comp1,
+ .vmux = 4,
+ .amux = LINE2,
+ .gpio = 0x0000,
+ },{
+ .name = name_svideo,
+ .vmux = 6,
+ .amux = LINE2,
+ .gpio = 0x0000,
+ }},
+ .radio = {
+ .name = name_radio,
+ .amux = TV,
+ .gpio = 0x200000,
+ },
+ },
[SAA7134_BOARD_VA1000POWER] = {
.name = "AOPEN VA1000 POWER",
.audio_clock = 0x00187de7,
@@ -749,7 +820,7 @@ struct saa7134_board saa7134_boards[] = {
},{
.name = name_tv,
.vmux = 3,
- .amux = LINE2,
+ .amux = TV,
.tv = 1,
}},
.mpeg = SAA7134_MPEG_EMPRESS,
@@ -828,6 +899,10 @@ struct saa7134_board saa7134_boards[] = {
.name = name_radio,
.amux = LINE2,
},
+ .mute = {
+ .name = name_mute,
+ .amux = LINE1,
+ },
},
[SAA7134_BOARD_MANLI_MTV001] = {
/* Ognjen Nastic <ognjen@logosoft.ba> UNTESTED */
@@ -975,6 +1050,9 @@ struct saa7134_board saa7134_boards[] = {
.inputs = {{
.name = name_comp1,
.vmux = 3,
+ },{
+ .name = name_svideo,
+ .vmux = 8,
}},
},
[SAA7134_BOARD_NOVAC_PRIMETV7133] = {
@@ -995,11 +1073,12 @@ struct saa7134_board saa7134_boards[] = {
.vmux = 8,
}},
},
- [SAA7134_BOARD_AVERMEDIA_305] = {
- .name = "AverMedia 305",
+ [SAA7134_BOARD_AVERMEDIA_STUDIO_305] = {
+ .name = "AverMedia AverTV Studio 305",
.audio_clock = 0x00187de7,
- .tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
+ .tuner_type = TUNER_PHILIPS_FM1256_IH3,
.tda9887_conf = TDA9887_PRESENT,
+ .gpiomask = 0x3,
.inputs = {{
.name = name_tv,
.vmux = 1,
@@ -1104,23 +1183,23 @@ struct saa7134_board saa7134_boards[] = {
.name = name_svideo,
.vmux = 8,
.amux = LINE1,
- .gpio = 0x00080
+ .gpio = 0x00080,
},{
.name = name_comp1,
.vmux = 3,
.amux = LINE1,
- .gpio = 0x00080
+ .gpio = 0x00080,
},{
.name = name_tv,
.vmux = 1,
- .amux = LINE2,
+ .amux = LINE2_LEFT,
.tv = 1,
- .gpio = 0x00080
+ .gpio = 0x00080,
}},
.radio = {
- .name = name_radio,
- .amux = LINE2,
- .gpio = 0x80000
+ .name = name_radio,
+ .amux = LINE2,
+ .gpio = 0x80000,
},
.mute = {
.name = name_mute,
@@ -1129,21 +1208,20 @@ struct saa7134_board saa7134_boards[] = {
},
},
[SAA7134_BOARD_SABRENT_SBTTVFM] = {
- /* Michael Rodriguez-Torrent */
+ /* Michael Rodriguez-Torrent <mrtorrent@asu.edu> */
.name = "Sabrent SBT-TVFM (saa7130)",
.audio_clock = 0x00187de7,
.tuner_type = TUNER_PHILIPS_NTSC_M,
- .tda9887_conf = TDA9887_PRESENT,
.inputs = {{
+ .name = name_comp1,
+ .vmux = 1,
+ .amux = LINE2,
+ },{
.name = name_tv,
.vmux = 3,
.amux = LINE2,
.tv = 1,
},{
- .name = name_comp1,
- .vmux = 1,
- .amux = LINE2,
- },{
.name = name_svideo,
.vmux = 8,
.amux = LINE2,
@@ -1208,32 +1286,41 @@ struct saa7134_board saa7134_boards[] = {
}
},
[SAA7134_BOARD_AVERMEDIA_307] = {
- /* Nickolay V. Shmyrev <nshmyrev@yandex.ru> */
+ /*
+ Nickolay V. Shmyrev <nshmyrev@yandex.ru>
+ Lots of thanks to Andrey Zolotarev <zolotarev_andrey@mail.ru>
+ */
.name = "Avermedia AVerTV Studio 307",
.audio_clock = 0x00187de7,
- .tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
+ .tuner_type = TUNER_PHILIPS_FM1256_IH3,
.tda9887_conf = TDA9887_PRESENT,
+ .gpiomask = 0x03,
.inputs = {{
.name = name_tv,
.vmux = 1,
.amux = TV,
.tv = 1,
+ .gpio = 0x00,
},{
.name = name_comp1,
.vmux = 0,
.amux = LINE2,
+ .gpio = 0x00,
},{
.name = name_comp2,
.vmux = 3,
.amux = LINE2,
+ .gpio = 0x00,
},{
.name = name_svideo,
.vmux = 8,
.amux = LINE2,
+ .gpio = 0x00,
}},
.radio = {
.name = name_radio,
- .amux = TV,
+ .amux = LINE1,
+ .gpio = 0x01,
},
},
[SAA7134_BOARD_AVERMEDIA_CARDBUS] = {
@@ -1263,10 +1350,17 @@ struct saa7134_board saa7134_boards[] = {
[SAA7134_BOARD_CINERGY400_CARDBUS] = {
.name = "Terratec Cinergy 400 mobile",
.audio_clock = 0x187de7,
- .tuner_type = UNSET /* not supported yet :/ */,
+ .tuner_type = TUNER_ALPS_TSBE5_PAL,
+ .tda9887_conf = TDA9887_PRESENT,
.inputs = {{
.name = name_tv,
- .vmux = 5,
+ .vmux = 1,
+ .amux = TV,
+ .tv = 1,
+ },{
+ .name = name_tv_mono,
+ .vmux = 1,
+ .amux = LINE2,
.tv = 1,
},{
.name = name_comp1,
@@ -1274,8 +1368,182 @@ struct saa7134_board saa7134_boards[] = {
.amux = LINE1,
},{
.name = name_svideo,
+ .vmux = 8,
+ .amux = LINE1,
+ }},
+ },
+ [SAA7134_BOARD_CINERGY600_MK3] = {
+ .name = "Terratec Cinergy 600 TV MK3",
+ .audio_clock = 0x00200000,
+ .tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
+ .tda9887_conf = TDA9887_PRESENT,
+ .inputs = {{
+ .name = name_tv,
+ .vmux = 1,
+ .amux = TV,
+ .tv = 1,
+ },{
+ .name = name_comp1,
.vmux = 4,
.amux = LINE1,
+ },{
+ .name = name_svideo,
+ .vmux = 8,
+ .amux = LINE1,
+ },{
+ .name = name_comp2, // CVideo over SVideo Connector
+ .vmux = 0,
+ .amux = LINE1,
+ }},
+ .radio = {
+ .name = name_radio,
+ .amux = LINE2,
+ },
+ },
+ [SAA7134_BOARD_VIDEOMATE_GOLD_PLUS] = {
+ /* Dylan Walkden <dylan_walkden@hotmail.com> */
+ .name = "Compro VideoMate Gold+ Pal",
+ .audio_clock = 0x00187de7,
+ .tuner_type = TUNER_PHILIPS_PAL,
+ .gpiomask = 0x1ce780,
+ .inputs = {{
+ .name = name_svideo,
+ .vmux = 0, // CVideo over SVideo Connector - ok?
+ .amux = LINE1,
+ .gpio = 0x008080,
+ },{
+ .name = name_comp1,
+ .vmux = 3,
+ .amux = LINE1,
+ .gpio = 0x008080,
+ },{
+ .name = name_tv,
+ .vmux = 1,
+ .amux = TV,
+ .tv = 1,
+ .gpio = 0x008080,
+ }},
+ .radio = {
+ .name = name_radio,
+ .amux = LINE2,
+ .gpio = 0x80000,
+ },
+ .mute = {
+ .name = name_mute,
+ .amux = LINE2,
+ .gpio = 0x0c8000,
+ },
+ },
+ [SAA7134_BOARD_PINNACLE_300I_DVBT_PAL] = {
+ .name = "Pinnacle PCTV 300i DVB-T + PAL",
+ .audio_clock = 0x00187de7,
+ .tuner_type = TUNER_MT2032,
+ .tda9887_conf = TDA9887_PRESENT | TDA9887_INTERCARRIER,
+ .mpeg = SAA7134_MPEG_DVB,
+ .inputs = {{
+ .name = name_tv,
+ .vmux = 3,
+ .amux = TV,
+ .tv = 1,
+ },{
+ .name = name_comp1,
+ .vmux = 0,
+ .amux = LINE2,
+ },{
+ .name = name_comp2,
+ .vmux = 1,
+ .amux = LINE2,
+ },{
+ .name = name_svideo,
+ .vmux = 8,
+ .amux = LINE2,
+ }},
+ },
+ [SAA7134_BOARD_PROVIDEO_PV952] = {
+ /* andreas.kretschmer@web.de */
+ .name = "ProVideo PV952",
+ .audio_clock = 0x00187de7,
+ .tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
+ .tda9887_conf = TDA9887_PRESENT,
+ .inputs = {{
+ .name = name_comp1,
+ .vmux = 0,
+ .amux = LINE1,
+ },{
+ .name = name_tv,
+ .vmux = 1,
+ .amux = TV,
+ .tv = 1,
+ },{
+ .name = name_tv_mono,
+ .vmux = 1,
+ .amux = LINE2,
+ .tv = 1,
+ }},
+ .radio = {
+ .name = name_radio,
+ .amux = LINE2,
+ },
+ },
+ [SAA7134_BOARD_AVERMEDIA_305] = {
+ /* much like the "studio" version but without radio
+ * and another tuner (sirspiritus@yandex.ru) */
+ .name = "AverMedia AverTV/305",
+ .audio_clock = 0x00187de7,
+ .tuner_type = TUNER_PHILIPS_FQ1216ME,
+ .tda9887_conf = TDA9887_PRESENT,
+ .gpiomask = 0x3,
+ .inputs = {{
+ .name = name_tv,
+ .vmux = 1,
+ .amux = LINE2,
+ .tv = 1,
+ },{
+ .name = name_comp1,
+ .vmux = 0,
+ .amux = LINE2,
+ },{
+ .name = name_comp2,
+ .vmux = 3,
+ .amux = LINE2,
+ },{
+ .name = name_svideo,
+ .vmux = 8,
+ .amux = LINE2,
+ }},
+ .mute = {
+ .name = name_mute,
+ .amux = LINE1,
+ },
+ },
+ [SAA7134_BOARD_FLYDVBTDUO] = {
+ /* LifeView FlyDVB-T DUO */
+ /* "Nico Sabbi <nsabbi@tiscali.it> */
+ .name = "LifeView FlyDVB-T DUO",
+ .audio_clock = 0x00200000,
+ .tuner_type = TUNER_PHILIPS_TDA8290,
+// .gpiomask = 0xe000,
+ .inputs = {{
+ .name = name_tv,
+ .vmux = 1,
+ .amux = TV,
+// .gpio = 0x0000,
+ .tv = 1,
+ },{
+ .name = name_comp1, /* Composite signal on S-Video input */
+ .vmux = 0,
+ .amux = LINE2,
+// .gpio = 0x4000,
+ },{
+ .name = name_comp2, /* Composite input */
+ .vmux = 3,
+ .amux = LINE2,
+// .gpio = 0x4000,
+ },{
+ .name = name_svideo, /* S-Video signal on S-Video input */
+ .vmux = 8,
+ .amux = LINE2,
+// .gpio = 0x4000,
}},
},
};
@@ -1322,6 +1590,12 @@ struct pci_device_id saa7134_pci_tbl[] = {
.subdevice = 0x1143,
.driver_data = SAA7134_BOARD_CINERGY600,
},{
+ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7134,
+ .subvendor = 0x153B,
+ .subdevice = 0x1158,
+ .driver_data = SAA7134_BOARD_CINERGY600_MK3,
+ },{
.vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7133,
.subvendor = 0x153b,
@@ -1349,8 +1623,14 @@ struct pci_device_id saa7134_pci_tbl[] = {
.vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7135,
.subvendor = 0x5168,
- .subdevice = 0x0212,
- .driver_data = SAA7134_BOARD_FLYTVPLATINUM,
+ .subdevice = 0x0212, /* minipci, LR212 */
+ .driver_data = SAA7134_BOARD_FLYTVPLATINUM_MINI,
+ },{
+ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
+ .subvendor = 0x5168,
+ .subdevice = 0x0214, /* Standard PCI, LR214WF */
+ .driver_data = SAA7134_BOARD_FLYTVPLATINUM_FM,
},{
.vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7134,
@@ -1377,6 +1657,12 @@ struct pci_device_id saa7134_pci_tbl[] = {
.driver_data = SAA7134_BOARD_ASUSTeK_TVFM7134,
},{
.vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
+ .subvendor = PCI_VENDOR_ID_ASUSTEK,
+ .subdevice = 0x4845,
+ .driver_data = SAA7135_BOARD_ASUSTeK_TVFM7135,
+ },{
+ .vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7134,
.subvendor = PCI_VENDOR_ID_ASUSTEK,
.subdevice = 0x4830,
@@ -1452,6 +1738,12 @@ struct pci_device_id saa7134_pci_tbl[] = {
.device = PCI_DEVICE_ID_PHILIPS_SAA7130,
.subvendor = 0x1461, /* Avermedia Technologies Inc */
.subdevice = 0x2115,
+ .driver_data = SAA7134_BOARD_AVERMEDIA_STUDIO_305,
+ },{
+ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7130,
+ .subvendor = 0x1461, /* Avermedia Technologies Inc */
+ .subdevice = 0x2108,
.driver_data = SAA7134_BOARD_AVERMEDIA_305,
},{
.vendor = PCI_VENDOR_ID_PHILIPS,
@@ -1483,8 +1775,8 @@ struct pci_device_id saa7134_pci_tbl[] = {
.vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7134,
.subvendor = 0x11bd,
- .subdevice = 0x002d, /* 300i DVB-T + PAL */
- .driver_data = SAA7134_BOARD_PINNACLE_PCTV_STEREO,
+ .subdevice = 0x002d,
+ .driver_data = SAA7134_BOARD_PINNACLE_300I_DVBT_PAL,
},{
.vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7134,
@@ -1509,20 +1801,43 @@ struct pci_device_id saa7134_pci_tbl[] = {
.subvendor = 0x153B,
.subdevice = 0x1152,
.driver_data = SAA7134_BOARD_CINERGY200,
-
},{
.vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7130,
.subvendor = 0x185b,
.subdevice = 0xc100,
.driver_data = SAA7134_BOARD_VIDEOMATE_TV_PVR,
-
},{
.vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7130,
+ .subvendor = 0x1131,
+ .subdevice = 0,
+ .driver_data = SAA7134_BOARD_SABRENT_SBTTVFM,
+ },{
+ .vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7134,
- .subvendor = 0x1461, /* Avermedia Technologies Inc */
- .subdevice = 0x9715,
+ .subvendor = 0x1461, /* Avermedia Technologies Inc */
+ .subdevice = 0x9715,
.driver_data = SAA7134_BOARD_AVERMEDIA_307,
+ },{
+ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7134,
+ .subvendor = 0x185b,
+ .subdevice = 0xc200,
+ .driver_data = SAA7134_BOARD_VIDEOMATE_GOLD_PLUS,
+ },{
+ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7134,
+ .subvendor = 0x1540,
+ .subdevice = 0x9524,
+ .driver_data = SAA7134_BOARD_PROVIDEO_PV952,
+
+ },{
+ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
+ .subvendor = 0x5168,
+ .subdevice = 0x0306,
+ .driver_data = SAA7134_BOARD_FLYDVBTDUO,
},{
/* --- boards without eeprom + subsystem ID --- */
@@ -1631,16 +1946,19 @@ int saa7134_board_init1(struct saa7134_dev *dev)
case SAA7134_BOARD_FLYVIDEO2000:
case SAA7134_BOARD_FLYVIDEO3000:
dev->has_remote = 1;
- /* fall throuth */
- case SAA7134_BOARD_FLYTVPLATINUM:
board_flyvideo(dev);
break;
case SAA7134_BOARD_CINERGY400:
case SAA7134_BOARD_CINERGY600:
+ case SAA7134_BOARD_CINERGY600_MK3:
case SAA7134_BOARD_ECS_TVP3XP:
case SAA7134_BOARD_ECS_TVP3XP_4CB5:
case SAA7134_BOARD_MD2819:
+ case SAA7134_BOARD_AVERMEDIA_STUDIO_305:
+ case SAA7134_BOARD_AVERMEDIA_305:
case SAA7134_BOARD_AVERMEDIA_307:
+// case SAA7134_BOARD_SABRENT_SBTTVFM: /* not finished yet */
+ case SAA7134_BOARD_VIDEOMATE_TV_PVR:
dev->has_remote = 1;
break;
case SAA7134_BOARD_AVACSSMARTTV:
@@ -1656,8 +1974,13 @@ int saa7134_board_init1(struct saa7134_dev *dev)
/* power-up tuner chip */
saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x00040000, 0x00040000);
saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x00040000, 0x00000000);
+ msleep(1);
break;
}
+ if (dev->has_remote)
+ dev->irq2_mask |= (SAA7134_IRQ2_INTE_GPIO18 |
+ SAA7134_IRQ2_INTE_GPIO18A |
+ SAA7134_IRQ2_INTE_GPIO16 );
return 0;
}
@@ -1676,6 +1999,7 @@ int saa7134_board_init2(struct saa7134_dev *dev)
: SAA7134_BOARD_BMK_MPEX_TUNER;
if (board == dev->board)
break;
+ dev->board = board;
printk("%s: board type fixup: %s\n", dev->name,
saa7134_boards[dev->board].name);
dev->tuner_type = saa7134_boards[dev->board].tuner_type;
diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c
index da675c744d563..d506cafba8ffe 100644
--- a/drivers/media/video/saa7134/saa7134-core.c
+++ b/drivers/media/video/saa7134/saa7134-core.c
@@ -1,5 +1,5 @@
/*
- * $Id: saa7134-core.c,v 1.15 2004/11/07 14:44:59 kraxel Exp $
+ * $Id: saa7134-core.c,v 1.28 2005/02/22 09:56:29 kraxel Exp $
*
* device driver for philips saa7134 based TV cards
* driver core
@@ -25,6 +25,7 @@
#include <linux/init.h>
#include <linux/list.h>
#include <linux/module.h>
+#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/kmod.h>
@@ -88,7 +89,7 @@ MODULE_PARM_DESC(card, "card type");
static DECLARE_MUTEX(devlist_lock);
LIST_HEAD(saa7134_devlist);
static LIST_HEAD(mops_list);
-unsigned int saa7134_devcount;
+static unsigned int saa7134_devcount;
#define dprintk(fmt, arg...) if (core_debug) \
printk(KERN_DEBUG "%s/core: " fmt, dev->name , ## arg)
@@ -620,7 +621,7 @@ static irqreturn_t saa7134_irq(int irq, void *dev_id, struct pt_regs *regs)
dump_statusregs(dev);
#endif
- if (report & SAA7134_IRQ_REPORT_INTL)
+ if (report & SAA7134_IRQ_REPORT_RDCAP /* _INTL */)
saa7134_irq_video_intl(dev);
if ((report & SAA7134_IRQ_REPORT_DONE_RA0) &&
@@ -642,8 +643,8 @@ static irqreturn_t saa7134_irq(int irq, void *dev_id, struct pt_regs *regs)
SAA7134_IRQ_REPORT_GPIO18)) &&
dev->remote)
saa7134_input_irq(dev);
+ }
- };
if (10 == loop) {
print_irqstatus(dev,loop,report,status);
if (report & SAA7134_IRQ_REPORT_PE) {
@@ -651,6 +652,13 @@ 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 */
+ 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));
} else {
/* disable all irqs */
printk(KERN_WARNING "%s/irq: looping -- "
@@ -725,20 +733,7 @@ static int saa7134_hwinit2(struct saa7134_dev *dev)
/* enable IRQ's */
saa_writel(SAA7134_IRQ1, 0);
- saa_writel(SAA7134_IRQ2,
- SAA7134_IRQ2_INTE_GPIO18 |
- SAA7134_IRQ2_INTE_GPIO18A |
- SAA7134_IRQ2_INTE_GPIO16 |
- SAA7134_IRQ2_INTE_SC2 |
- SAA7134_IRQ2_INTE_SC1 |
- SAA7134_IRQ2_INTE_SC0 |
- /* SAA7134_IRQ2_INTE_DEC5 | FIXME: TRIG_ERR ??? */
- SAA7134_IRQ2_INTE_DEC3 |
- SAA7134_IRQ2_INTE_DEC2 |
- /* SAA7134_IRQ2_INTE_DEC1 | */
- SAA7134_IRQ2_INTE_DEC0 |
- SAA7134_IRQ2_INTE_PE |
- SAA7134_IRQ2_INTE_AR);
+ saa_writel(SAA7134_IRQ2, dev->irq2_mask);
return 0;
}
@@ -959,6 +954,13 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
}
/* initialize hardware #1 */
+ dev->irq2_mask =
+ SAA7134_IRQ2_INTE_DEC3 |
+ SAA7134_IRQ2_INTE_DEC2 |
+ SAA7134_IRQ2_INTE_DEC1 |
+ SAA7134_IRQ2_INTE_DEC0 |
+ SAA7134_IRQ2_INTE_PE |
+ SAA7134_IRQ2_INTE_AR;
saa7134_board_init1(dev);
saa7134_hwinit1(dev);
@@ -1060,6 +1062,9 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
}
list_add_tail(&dev->devlist,&saa7134_devlist);
up(&devlist_lock);
+
+ /* check for signal */
+ saa7134_irq_video_intl(dev);
return 0;
fail5:
@@ -1207,6 +1212,10 @@ static int saa7134_init(void)
static void saa7134_fini(void)
{
+#ifdef CONFIG_MODULES
+ if (pending_registered)
+ unregister_module_notifier(&pending_notifier);
+#endif
pci_unregister_driver(&saa7134_pci_driver);
}
diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c
index b51f0acb1fa9d..dd4a6c8ee65f1 100644
--- a/drivers/media/video/saa7134/saa7134-dvb.c
+++ b/drivers/media/video/saa7134/saa7134-dvb.c
@@ -1,5 +1,5 @@
/*
- * $Id: saa7134-dvb.c,v 1.4 2004/11/07 14:44:59 kraxel Exp $
+ * $Id: saa7134-dvb.c,v 1.12 2005/02/18 12:28:29 kraxel Exp $
*
* (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
*
@@ -30,35 +30,211 @@
#include "saa7134-reg.h"
#include "saa7134.h"
+#include "dvb-pll.h"
+#include "mt352.h"
+#include "mt352_priv.h" /* FIXME */
+#include "tda1004x.h"
+
MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
MODULE_LICENSE("GPL");
+static unsigned int antenna_pwr = 0;
+module_param(antenna_pwr, int, 0444);
+MODULE_PARM_DESC(antenna_pwr,"enable antenna power (Pinnacle 300i)");
+
/* ------------------------------------------------------------------ */
-static int dvb_init(struct saa7134_dev *dev)
+static int pinnacle_antenna_pwr(struct saa7134_dev *dev, int on)
{
- printk("%s: %s\n",dev->name,__FUNCTION__);
+ u32 ok;
+
+ if (!on) {
+ saa_setl(SAA7134_GPIO_GPMODE0 >> 2, (1 << 26));
+ saa_clearl(SAA7134_GPIO_GPSTATUS0 >> 2, (1 << 26));
+ return 0;
+ }
+
+ saa_setl(SAA7134_GPIO_GPMODE0 >> 2, (1 << 26));
+ saa_setl(SAA7134_GPIO_GPSTATUS0 >> 2, (1 << 26));
+ udelay(10);
+
+ saa_setl(SAA7134_GPIO_GPMODE0 >> 2, (1 << 28));
+ saa_clearl(SAA7134_GPIO_GPSTATUS0 >> 2, (1 << 28));
+ udelay(10);
+ saa_setl(SAA7134_GPIO_GPSTATUS0 >> 2, (1 << 28));
+ udelay(10);
+ ok = saa_readl(SAA7134_GPIO_GPSTATUS0) & (1 << 27);
+ printk("%s: %s %s\n", dev->name, __FUNCTION__,
+ ok ? "on" : "off");
+
+ if (!ok)
+ saa_clearl(SAA7134_GPIO_GPSTATUS0 >> 2, (1 << 26));
+ return ok;
+}
+
+static int mt352_pinnacle_init(struct dvb_frontend* fe)
+{
+ static u8 clock_config [] = { CLOCK_CTL, 0x3d, 0x28 };
+ static u8 reset [] = { RESET, 0x80 };
+ static u8 adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 };
+ static u8 agc_cfg [] = { AGC_TARGET, 0x28, 0xa0 };
+ static u8 capt_range_cfg[] = { CAPT_RANGE, 0x31 };
+ static u8 fsm_ctl_cfg[] = { 0x7b, 0x04 };
+ static u8 gpp_ctl_cfg [] = { GPP_CTL, 0x0f };
+ static u8 scan_ctl_cfg [] = { SCAN_CTL, 0x0d };
+ static u8 irq_cfg [] = { INTERRUPT_EN_0, 0x00, 0x00, 0x00, 0x00 };
+ struct saa7134_dev *dev= fe->dvb->priv;
+
+ printk("%s: %s called\n",dev->name,__FUNCTION__);
+
+ 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, capt_range_cfg, sizeof(capt_range_cfg));
+ mt352_write(fe, gpp_ctl_cfg, sizeof(gpp_ctl_cfg));
+
+ mt352_write(fe, fsm_ctl_cfg, sizeof(fsm_ctl_cfg));
+ mt352_write(fe, scan_ctl_cfg, sizeof(scan_ctl_cfg));
+ mt352_write(fe, irq_cfg, sizeof(irq_cfg));
+ return 0;
+}
+
+static int mt352_pinnacle_pll_set(struct dvb_frontend* fe,
+ struct dvb_frontend_parameters* params,
+ u8* pllbuf)
+{
+ static int on = TDA9887_PRESENT | TDA9887_PORT2_INACTIVE;
+ static int off = TDA9887_PRESENT | TDA9887_PORT2_ACTIVE;
+ struct saa7134_dev *dev = fe->dvb->priv;
+ struct v4l2_frequency f;
+
+ /* set frequency (mt2050) */
+ f.tuner = 0;
+ f.type = V4L2_TUNER_DIGITAL_TV;
+ f.frequency = params->frequency / 1000 * 16 / 1000;
+ saa7134_i2c_call_clients(dev,TDA9887_SET_CONFIG,&on);
+ saa7134_i2c_call_clients(dev,VIDIOC_S_FREQUENCY,&f);
+ saa7134_i2c_call_clients(dev,TDA9887_SET_CONFIG,&off);
+
+ pinnacle_antenna_pwr(dev, antenna_pwr);
+
+ /* mt352 setup */
+ mt352_pinnacle_init(fe);
+ pllbuf[0] = 0xc2;
+ pllbuf[1] = 0x00;
+ pllbuf[2] = 0x00;
+ pllbuf[3] = 0x80;
+ pllbuf[4] = 0x00;
+ return 0;
+}
+
+static struct mt352_config pinnacle_300i = {
+ .demod_address = 0x3c >> 1,
+ .adc_clock = 20333,
+ .if2 = 36150,
+ .no_tuner = 1,
+ .demod_init = mt352_pinnacle_init,
+ .pll_set = mt352_pinnacle_pll_set,
+};
+
+/* ------------------------------------------------------------------ */
+
+static int medion_cardbus_init(struct dvb_frontend* fe)
+{
+ /* anything to do here ??? */
+ return 0;
+}
+
+static int medion_cardbus_pll_set(struct dvb_frontend* fe,
+ struct dvb_frontend_parameters* params)
+{
+ struct saa7134_dev *dev = fe->dvb->priv;
+ struct v4l2_frequency f;
+
+ /*
+ * this instructs tuner.o to set the frequency, the call will
+ * end up in tuner_command(), VIDIOC_S_FREQUENCY switch.
+ * tda9887.o will see that as well.
+ */
+ f.tuner = 0;
+ f.type = V4L2_TUNER_DIGITAL_TV;
+ f.frequency = params->frequency / 1000 * 16 / 1000;
+ saa7134_i2c_call_clients(dev,VIDIOC_S_FREQUENCY,&f);
+ return 0;
+}
+static int fe_request_firmware(struct dvb_frontend* fe,
+ const struct firmware **fw, char* name)
+{
+ struct saa7134_dev *dev = fe->dvb->priv;
+ return request_firmware(fw, name, &dev->pci->dev);
+}
+
+struct tda1004x_config medion_cardbus = {
+ .demod_address = 0x08, /* not sure this is correct */
+ .invert = 0,
+ .invert_oclk = 0,
+ .pll_init = medion_cardbus_init,
+ .pll_set = medion_cardbus_pll_set,
+ .request_firmware = fe_request_firmware,
+};
+
+/* ------------------------------------------------------------------ */
+
+static int dvb_init(struct saa7134_dev *dev)
+{
/* init struct videobuf_dvb */
+ dev->ts.nr_bufs = 32;
+ dev->ts.nr_packets = 32*4;
dev->dvb.name = dev->name;
videobuf_queue_init(&dev->dvb.dvbq, &saa7134_ts_qops,
dev->pci, &dev->slock,
V4L2_BUF_TYPE_VIDEO_CAPTURE,
- V4L2_FIELD_TOP,
+ V4L2_FIELD_ALTERNATE,
sizeof(struct saa7134_buf),
dev);
- /* TODO: init frontend */
- if (NULL == dev->dvb.frontend)
+ switch (dev->board) {
+ case SAA7134_BOARD_PINNACLE_300I_DVBT_PAL:
+ printk("%s: pinnacle 300i dvb setup\n",dev->name);
+ dev->dvb.frontend = mt352_attach(&pinnacle_300i,
+ &dev->i2c_adap);
+ break;
+ case SAA7134_BOARD_MD7134:
+ dev->dvb.frontend = tda10046_attach(&medion_cardbus,
+ &dev->i2c_adap);
+ if (NULL == dev->dvb.frontend)
+ printk("%s: Hmm, looks like this is the old MD7134 "
+ "version without DVB-T support\n",dev->name);
+ break;
+ default:
+ printk("%s: Huh? unknown DVB card?\n",dev->name);
+ break;
+ }
+
+ if (NULL == dev->dvb.frontend) {
+ printk("%s: frontend initialization failed\n",dev->name);
return -1;
+ }
/* register everything else */
- return videobuf_dvb_register(&dev->dvb);
+ return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev);
}
static int dvb_fini(struct saa7134_dev *dev)
{
+ static int on = TDA9887_PRESENT | TDA9887_PORT2_INACTIVE;
+
printk("%s: %s\n",dev->name,__FUNCTION__);
+
+ switch (dev->board) {
+ case SAA7134_BOARD_PINNACLE_300I_DVBT_PAL:
+ /* otherwise we don't detect the tuner on next insmod */
+ saa7134_i2c_call_clients(dev,TDA9887_SET_CONFIG,&on);
+ break;
+ };
videobuf_dvb_unregister(&dev->dvb);
return 0;
}
@@ -86,6 +262,5 @@ module_exit(dvb_unregister);
/*
* Local variables:
* c-basic-offset: 8
- * compile-command: "make DVB=1"
* End:
*/
diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c
index c2bca399800c1..2021e099e35ac 100644
--- a/drivers/media/video/saa7134/saa7134-empress.c
+++ b/drivers/media/video/saa7134/saa7134-empress.c
@@ -1,5 +1,5 @@
/*
- * $Id: saa7134-empress.c,v 1.3 2004/11/07 13:17:15 kraxel Exp $
+ * $Id: saa7134-empress.c,v 1.10 2005/02/03 10:24:33 kraxel Exp $
*
* (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
*
@@ -21,6 +21,7 @@
#include <linux/init.h>
#include <linux/list.h>
#include <linux/module.h>
+#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/delay.h>
@@ -50,16 +51,21 @@ MODULE_PARM_DESC(debug,"enable debug messages");
static void ts_reset_encoder(struct saa7134_dev* dev)
{
+ if (!dev->empress_started)
+ return;
+
saa_writeb(SAA7134_SPECIAL_MODE, 0x00);
msleep(10);
saa_writeb(SAA7134_SPECIAL_MODE, 0x01);
msleep(100);
+ dev->empress_started = 0;
}
-static int ts_init_encoder(struct saa7134_dev* dev, void* arg)
+static int ts_init_encoder(struct saa7134_dev* dev)
{
ts_reset_encoder(dev);
- saa7134_i2c_call_clients(dev, MPEG_SETPARAMS, arg);
+ saa7134_i2c_call_clients(dev, VIDIOC_S_MPEGCOMP, NULL);
+ dev->empress_started = 1;
return 0;
}
@@ -81,18 +87,19 @@ static int ts_open(struct inode *inode, struct file *file)
return -ENODEV;
dprintk("open minor=%d\n",minor);
- down(&dev->empress_tsq.lock);
err = -EBUSY;
- if (dev->empress_users)
+ if (down_trylock(&dev->empress_tsq.lock))
goto done;
+ if (dev->empress_users)
+ goto done_up;
dev->empress_users++;
file->private_data = dev;
- ts_init_encoder(dev, NULL);
err = 0;
- done:
+done_up:
up(&dev->empress_tsq.lock);
+done:
return err;
}
@@ -105,6 +112,7 @@ static int ts_release(struct inode *inode, struct file *file)
down(&dev->empress_tsq.lock);
if (dev->empress_tsq.reading)
videobuf_read_stop(&dev->empress_tsq);
+ videobuf_mmap_free(&dev->empress_tsq);
dev->empress_users--;
/* stop the encoder */
@@ -119,6 +127,9 @@ ts_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
{
struct saa7134_dev *dev = file->private_data;
+ if (!dev->empress_started)
+ ts_init_encoder(dev);
+
return videobuf_read_stream(&dev->empress_tsq,
data, count, ppos, 0,
file->f_flags & O_NONBLOCK);
@@ -281,8 +292,13 @@ static int ts_do_ioctl(struct inode *inode, struct file *file,
case VIDIOC_S_CTRL:
return saa7134_common_ioctl(dev, cmd, arg);
- case MPEG_SETPARAMS:
- return ts_init_encoder(dev, arg);
+ case VIDIOC_S_MPEGCOMP:
+ saa7134_i2c_call_clients(dev, VIDIOC_S_MPEGCOMP, arg);
+ ts_init_encoder(dev);
+ return 0;
+ case VIDIOC_G_MPEGCOMP:
+ saa7134_i2c_call_clients(dev, VIDIOC_G_MPEGCOMP, arg);
+ return 0;
default:
return -ENOIOCTLCMD;
@@ -320,6 +336,26 @@ static struct video_device saa7134_empress_template =
.minor = -1,
};
+static void empress_signal_update(void* data)
+{
+ struct saa7134_dev* dev = (struct saa7134_dev*) data;
+
+ if (dev->nosignal) {
+ dprintk("no video signal\n");
+ ts_reset_encoder(dev);
+ } else {
+ dprintk("video signal acquired\n");
+ if (dev->empress_users)
+ ts_init_encoder(dev);
+ }
+}
+
+static void empress_signal_change(struct saa7134_dev *dev)
+{
+ schedule_work(&dev->empress_workqueue);
+}
+
+
static int empress_init(struct saa7134_dev *dev)
{
int err;
@@ -335,6 +371,8 @@ static int empress_init(struct saa7134_dev *dev)
"%s empress (%s)", dev->name,
saa7134_boards[dev->board].name);
+ INIT_WORK(&dev->empress_workqueue, empress_signal_update, (void*) dev);
+
err = video_register_device(dev->empress_dev,VFL_TYPE_GRABBER,
empress_nr[dev->nr]);
if (err < 0) {
@@ -353,6 +391,8 @@ static int empress_init(struct saa7134_dev *dev)
V4L2_FIELD_ALTERNATE,
sizeof(struct saa7134_buf),
dev);
+
+ empress_signal_update(dev);
return 0;
}
@@ -362,6 +402,7 @@ static int empress_fini(struct saa7134_dev *dev)
if (NULL == dev->empress_dev)
return 0;
+ flush_scheduled_work();
video_unregister_device(dev->empress_dev);
dev->empress_dev = NULL;
return 0;
@@ -371,6 +412,7 @@ static struct saa7134_mpeg_ops empress_ops = {
.type = SAA7134_MPEG_EMPRESS,
.init = empress_init,
.fini = empress_fini,
+ .signal_change = empress_signal_change,
};
static int __init empress_register(void)
diff --git a/drivers/media/video/saa7134/saa7134-i2c.c b/drivers/media/video/saa7134/saa7134-i2c.c
index fa6cfbb9087bc..702bb63d98133 100644
--- a/drivers/media/video/saa7134/saa7134-i2c.c
+++ b/drivers/media/video/saa7134/saa7134-i2c.c
@@ -1,5 +1,5 @@
/*
- * $Id: saa7134-i2c.c,v 1.7 2004/11/07 13:17:15 kraxel Exp $
+ * $Id: saa7134-i2c.c,v 1.10 2005/01/24 17:37:23 kraxel Exp $
*
* device driver for philips saa7134 based TV cards
* i2c interface support
@@ -24,6 +24,7 @@
#include <linux/init.h>
#include <linux/list.h>
#include <linux/module.h>
+#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/delay.h>
@@ -205,7 +206,8 @@ static inline int i2c_send_byte(struct saa7134_dev *dev,
dword &= 0x0f;
dword |= (attr << 6);
dword |= ((__u32)data << 8);
- dword |= 0x00 << 16;
+ dword |= 0x00 << 16; /* 100 kHz */
+// dword |= 0x40 << 16; /* 400 kHz */
dword |= 0xf0 << 24;
saa_writel(SAA7134_I2C_ATTR_STATUS >> 2, dword);
#endif
@@ -236,7 +238,7 @@ static inline int i2c_recv_byte(struct saa7134_dev *dev)
}
static int saa7134_i2c_xfer(struct i2c_adapter *i2c_adap,
- struct i2c_msg msgs[], int num)
+ struct i2c_msg *msgs, int num)
{
struct saa7134_dev *dev = i2c_adap->algo_data;
enum i2c_status status;
@@ -248,13 +250,24 @@ static int saa7134_i2c_xfer(struct i2c_adapter *i2c_adap,
if (!i2c_reset(dev))
return -EIO;
+ d2printk("start xfer\n");
d1printk(KERN_DEBUG "%s: i2c xfer:",dev->name);
for (i = 0; i < num; i++) {
if (!(msgs[i].flags & I2C_M_NOSTART) || 0 == i) {
/* send address */
+ d2printk("send address\n");
addr = msgs[i].addr << 1;
if (msgs[i].flags & I2C_M_RD)
addr |= 1;
+ if (i > 0 && msgs[i].flags & I2C_M_RD) {
+ /* workaround for a saa7134 i2c bug
+ * needed to talk to the mt352 demux
+ * thanks to pinnacle for the hint */
+ int quirk = 0xfd;
+ d1printk(" [%02x quirk]",quirk);
+ i2c_send_byte(dev,START,quirk);
+ i2c_recv_byte(dev);
+ }
d1printk(" < %02x", addr);
rc = i2c_send_byte(dev,START,addr);
if (rc < 0)
@@ -262,6 +275,7 @@ static int saa7134_i2c_xfer(struct i2c_adapter *i2c_adap,
}
if (msgs[i].flags & I2C_M_RD) {
/* read bytes */
+ d2printk("read bytes\n");
for (byte = 0; byte < msgs[i].len; byte++) {
d1printk(" =");
rc = i2c_recv_byte(dev);
@@ -272,6 +286,7 @@ static int saa7134_i2c_xfer(struct i2c_adapter *i2c_adap,
}
} else {
/* write bytes */
+ d2printk("write bytes\n");
for (byte = 0; byte < msgs[i].len; byte++) {
data = msgs[i].buf[byte];
d1printk(" %02x", data);
@@ -281,6 +296,7 @@ static int saa7134_i2c_xfer(struct i2c_adapter *i2c_adap,
}
}
}
+ d2printk("xfer done\n");
d1printk(" >");
i2c_set_attr(dev,STOP);
rc = -EIO;
@@ -313,18 +329,6 @@ static u32 functionality(struct i2c_adapter *adap)
return I2C_FUNC_SMBUS_EMUL;
}
-#ifndef I2C_PEC
-static void inc_use(struct i2c_adapter *adap)
-{
- MOD_INC_USE_COUNT;
-}
-
-static void dec_use(struct i2c_adapter *adap)
-{
- MOD_DEC_USE_COUNT;
-}
-#endif
-
static int attach_inform(struct i2c_client *client)
{
struct saa7134_dev *dev = client->adapter->algo_data;
@@ -345,12 +349,7 @@ static struct i2c_algorithm saa7134_algo = {
};
static struct i2c_adapter saa7134_adap_template = {
-#ifdef I2C_PEC
.owner = THIS_MODULE,
-#else
- .inc_use = inc_use,
- .dec_use = dec_use,
-#endif
#ifdef I2C_CLASS_TV_ANALOG
.class = I2C_CLASS_TV_ANALOG,
#endif
@@ -362,7 +361,6 @@ static struct i2c_adapter saa7134_adap_template = {
static struct i2c_client saa7134_client_template = {
I2C_DEVNAME("saa7134 internal"),
- .id = -1,
};
/* ----------------------------------------------------------- */
diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c
index a732935d8eb9e..727d437e07df4 100644
--- a/drivers/media/video/saa7134/saa7134-input.c
+++ b/drivers/media/video/saa7134/saa7134-input.c
@@ -1,5 +1,5 @@
/*
- * $Id: saa7134-input.c,v 1.12 2004/11/07 13:17:15 kraxel Exp $
+ * $Id: saa7134-input.c,v 1.16 2004/12/10 12:33:39 kraxel Exp $
*
* handle saa7134 IR remotes via linux kernel input layer.
*
@@ -20,6 +20,7 @@
*/
#include <linux/module.h>
+#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/sched.h>
@@ -258,6 +259,55 @@ static IR_KEYTAB_TYPE md2819_codes[IR_KEYTAB_SIZE] = {
[ 17 ] = KEY_CHANNELDOWN, // CHANNEL/PAGE-
[ 49 ] = KEY_CHANNELUP // CHANNEL/PAGE+
};
+
+static IR_KEYTAB_TYPE videomate_tv_pvr_codes[IR_KEYTAB_SIZE] = {
+ [ 20 ] = KEY_MUTE,
+ [ 36 ] = KEY_ZOOM,
+
+ [ 1 ] = KEY_DVD,
+ [ 35 ] = KEY_RADIO,
+ [ 0 ] = KEY_TV,
+
+ [ 10 ] = KEY_REWIND,
+ [ 8 ] = KEY_PLAYPAUSE,
+ [ 15 ] = KEY_FORWARD,
+
+ [ 2 ] = KEY_PREVIOUS,
+ [ 7 ] = KEY_STOP,
+ [ 6 ] = KEY_NEXT,
+
+ [ 12 ] = KEY_UP,
+ [ 14 ] = KEY_DOWN,
+ [ 11 ] = KEY_LEFT,
+ [ 13 ] = KEY_RIGHT,
+ [ 17 ] = KEY_OK,
+
+ [ 3 ] = KEY_MENU,
+ [ 9 ] = KEY_SETUP,
+ [ 5 ] = KEY_VIDEO,
+ [ 34 ] = KEY_CHANNEL,
+
+ [ 18 ] = KEY_VOLUMEUP,
+ [ 21 ] = KEY_VOLUMEDOWN,
+ [ 16 ] = KEY_CHANNELUP,
+ [ 19 ] = KEY_CHANNELDOWN,
+
+ [ 4 ] = KEY_RECORD,
+
+ [ 22 ] = KEY_KP1,
+ [ 23 ] = KEY_KP2,
+ [ 24 ] = KEY_KP3,
+ [ 25 ] = KEY_KP4,
+ [ 26 ] = KEY_KP5,
+ [ 27 ] = KEY_KP6,
+ [ 28 ] = KEY_KP7,
+ [ 29 ] = KEY_KP8,
+ [ 30 ] = KEY_KP9,
+ [ 31 ] = KEY_KP0,
+
+ [ 32 ] = KEY_LANGUAGE,
+ [ 33 ] = KEY_SLEEP,
+};
/* ---------------------------------------------------------------------- */
static int build_key(struct saa7134_dev *dev)
@@ -335,6 +385,7 @@ int saa7134_input_init1(struct saa7134_dev *dev)
break;
case SAA7134_BOARD_CINERGY400:
case SAA7134_BOARD_CINERGY600:
+ case SAA7134_BOARD_CINERGY600_MK3:
ir_codes = cinergy_codes;
mask_keycode = 0x00003f;
mask_keyup = 0x040000;
@@ -353,6 +404,7 @@ int saa7134_input_init1(struct saa7134_dev *dev)
polling = 50; // ms
break;
case SAA7134_BOARD_MD2819:
+ case SAA7134_BOARD_AVERMEDIA_305:
case SAA7134_BOARD_AVERMEDIA_307:
ir_codes = md2819_codes;
mask_keycode = 0x0007C8;
@@ -362,6 +414,12 @@ int saa7134_input_init1(struct saa7134_dev *dev)
saa_setb(SAA7134_GPIO_GPMODE0, 0x4);
saa_setb(SAA7134_GPIO_GPSTATUS0, 0x4);
break;
+ case SAA7134_BOARD_VIDEOMATE_TV_PVR:
+ ir_codes = videomate_tv_pvr_codes;
+ mask_keycode = 0x00003F;
+ mask_keyup = 0x400000;
+ polling = 50; // ms
+ break;
}
if (NULL == ir_codes) {
printk("%s: Oops: IR config error [card=%d]\n",
diff --git a/drivers/media/video/saa7134/saa7134-oss.c b/drivers/media/video/saa7134/saa7134-oss.c
index 55a4548cf22e6..6b6a643bf1cda 100644
--- a/drivers/media/video/saa7134/saa7134-oss.c
+++ b/drivers/media/video/saa7134/saa7134-oss.c
@@ -1,5 +1,5 @@
/*
- * $Id: saa7134-oss.c,v 1.11 2004/11/07 13:17:15 kraxel Exp $
+ * $Id: saa7134-oss.c,v 1.13 2004/12/10 12:33:39 kraxel Exp $
*
* device driver for philips saa7134 based TV cards
* oss dsp interface
@@ -24,6 +24,7 @@
#include <linux/init.h>
#include <linux/list.h>
#include <linux/module.h>
+#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/soundcard.h>
@@ -543,6 +544,7 @@ mixer_recsrc_7134(struct saa7134_dev *dev)
break;
case LINE1:
case LINE2:
+ case LINE2_LEFT:
analog_io = (LINE1 == dev->oss.input) ? 0x00 : 0x08;
rate = (32000 == dev->oss.rate) ? 0x01 : 0x03;
saa_andorb(SAA7134_ANALOG_IO_SELECT, 0x08, analog_io);
@@ -566,6 +568,7 @@ mixer_recsrc_7133(struct saa7134_dev *dev)
value = 0xbbbb32; /* AUX1 */
break;
case LINE2:
+ case LINE2_LEFT:
value = 0xbbbb54; /* AUX2 */
break;
}
@@ -608,6 +611,7 @@ mixer_level(struct saa7134_dev *dev, enum saa7134_audio_in src, int level)
(100 == level) ? 0x00 : 0x10);
break;
case LINE2:
+ case LINE2_LEFT:
saa_andorb(SAA7134_ANALOG_IO_SELECT, 0x20,
(100 == level) ? 0x00 : 0x20);
break;
diff --git a/drivers/media/video/saa7134/saa7134-ts.c b/drivers/media/video/saa7134/saa7134-ts.c
index ed73f71a4fa58..345eb2a8c28de 100644
--- a/drivers/media/video/saa7134/saa7134-ts.c
+++ b/drivers/media/video/saa7134/saa7134-ts.c
@@ -1,5 +1,5 @@
/*
- * $Id: saa7134-ts.c,v 1.12 2004/11/07 13:17:15 kraxel Exp $
+ * $Id: saa7134-ts.c,v 1.14 2005/02/03 10:24:33 kraxel Exp $
*
* device driver for philips saa7134 based TV cards
* video4linux video interface
@@ -24,6 +24,7 @@
#include <linux/init.h>
#include <linux/list.h>
#include <linux/module.h>
+#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/delay.h>
@@ -220,10 +221,10 @@ void saa7134_irq_ts_done(struct saa7134_dev *dev, unsigned long status)
if (dev->ts_q.curr) {
field = dev->ts_q.curr->vb.field;
if (field == V4L2_FIELD_TOP) {
- if ((status & 0x100000) != 0x100000)
+ if ((status & 0x100000) != 0x000000)
goto done;
} else {
- if ((status & 0x100000) != 0x000000)
+ if ((status & 0x100000) != 0x100000)
goto done;
}
saa7134_buffer_finish(dev,&dev->ts_q,STATE_DONE);
diff --git a/drivers/media/video/saa7134/saa7134-tvaudio.c b/drivers/media/video/saa7134/saa7134-tvaudio.c
index 7461f8a1982b7..ecac13c006d51 100644
--- a/drivers/media/video/saa7134/saa7134-tvaudio.c
+++ b/drivers/media/video/saa7134/saa7134-tvaudio.c
@@ -1,5 +1,5 @@
/*
- * $Id: saa7134-tvaudio.c,v 1.17 2004/11/07 13:17:15 kraxel Exp $
+ * $Id: saa7134-tvaudio.c,v 1.22 2005/01/07 13:11:19 kraxel Exp $
*
* device driver for philips saa7134 based TV cards
* tv audio decoder (fm stereo, nicam, ...)
@@ -24,6 +24,7 @@
#include <linux/init.h>
#include <linux/list.h>
#include <linux/module.h>
+#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/delay.h>
@@ -237,13 +238,14 @@ static void mute_input_7134(struct saa7134_dev *dev)
if (PCI_DEVICE_ID_PHILIPS_SAA7134 == dev->pci->device)
/* 7134 mute */
- saa_writeb(SAA7134_AUDIO_MUTE_CTRL, mute ? 0xff : 0xbb);
+ saa_writeb(SAA7134_AUDIO_MUTE_CTRL, mute ? 0xbf : 0xbb);
/* switch internal audio mux */
switch (in->amux) {
- case TV: ausel=0xc0; ics=0x00; ocs=0x02; break;
- case LINE1: ausel=0x80; ics=0x00; ocs=0x00; break;
- case LINE2: ausel=0x80; ics=0x08; ocs=0x01; break;
+ case TV: ausel=0xc0; ics=0x00; ocs=0x02; break;
+ case LINE1: ausel=0x80; ics=0x00; ocs=0x00; break;
+ case LINE2: ausel=0x80; ics=0x08; ocs=0x01; break;
+ case LINE2_LEFT: ausel=0x80; ics=0x08; ocs=0x05; break;
}
saa_andorb(SAA7134_AUDIO_FORMAT_CTRL, 0xc0, ausel);
saa_andorb(SAA7134_ANALOG_IO_SELECT, 0x08, ics);
@@ -437,15 +439,16 @@ static int tvaudio_getstereo(struct saa7134_dev *dev, struct saa7134_tvaudio *au
nicam = saa_readb(SAA7134_NICAM_STATUS);
dprintk("getstereo: nicam=0x%x\n",nicam);
switch (nicam & 0x0b) {
- case 0x08:
- retval = V4L2_TUNER_SUB_MONO;
- break;
case 0x09:
retval = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
break;
case 0x0a:
retval = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
break;
+ case 0x08:
+ default:
+ retval = V4L2_TUNER_SUB_MONO;
+ break;
}
break;
}
@@ -748,9 +751,16 @@ static int mute_input_7133(struct saa7134_dev *dev)
int mask;
switch (dev->input->amux) {
- case TV: reg = 0x02; break;
- case LINE1: reg = 0x00; break;
- case LINE2: reg = 0x01; break;
+ case TV:
+ reg = 0x02;
+ break;
+ case LINE1:
+ reg = 0x00;
+ break;
+ case LINE2:
+ case LINE2_LEFT:
+ reg = 0x01;
+ break;
}
if (dev->ctl_mute)
reg = 0x07;
@@ -869,6 +879,21 @@ static int tvaudio_thread_ddep(void *data)
/* ------------------------------------------------------------------ */
/* common stuff + external entry points */
+static void saa7134_enable_i2s(struct saa7134_dev *dev)
+{
+ int i2s_format;
+
+ if (!card_is_empress(dev))
+ return;
+ i2s_format = (dev->input->amux == TV) ? 0x00 : 0x01;
+
+ /* enable I2S audio output for the mpeg encoder */
+ saa_writeb(SAA7134_I2S_OUTPUT_SELECT, 0x80);
+ saa_writeb(SAA7134_I2S_OUTPUT_FORMAT, i2s_format);
+ saa_writeb(SAA7134_I2S_OUTPUT_LEVEL, 0x0F);
+ saa_writeb(SAA7134_I2S_AUDIO_OUTPUT, 0x01);
+}
+
int saa7134_tvaudio_rx2mode(u32 rx)
{
u32 mode;
@@ -911,6 +936,7 @@ void saa7134_tvaudio_setinput(struct saa7134_dev *dev,
mute_input_7133(dev);
break;
}
+ saa7134_enable_i2s(dev);
}
void saa7134_tvaudio_setvolume(struct saa7134_dev *dev, int level)
@@ -946,18 +972,6 @@ int saa7134_tvaudio_init2(struct saa7134_dev *dev)
DECLARE_MUTEX_LOCKED(sem);
int (*my_thread)(void *data) = NULL;
- /* enable I2S audio output */
- if (card_is_empress(dev)) {
- int i2sform = (48000 == dev->oss.rate)
- ? 0x01 : 0x00;
-
- /* enable I2S output */
- saa_writeb(SAA7134_I2S_OUTPUT_SELECT, 0x80);
- saa_writeb(SAA7134_I2S_OUTPUT_FORMAT, i2sform);
- saa_writeb(SAA7134_I2S_OUTPUT_LEVEL, 0x0F);
- saa_writeb(SAA7134_I2S_AUDIO_OUTPUT, 0x01);
- }
-
switch (dev->pci->device) {
case PCI_DEVICE_ID_PHILIPS_SAA7134:
my_thread = tvaudio_thread;
@@ -977,9 +991,10 @@ int saa7134_tvaudio_init2(struct saa7134_dev *dev)
if (dev->thread.pid < 0)
printk(KERN_WARNING "%s: kernel_thread() failed\n",
dev->name);
- wake_up_interruptible(&dev->thread.wq);
+ saa7134_tvaudio_do_scan(dev);
}
+ saa7134_enable_i2s(dev);
return 0;
}
diff --git a/drivers/media/video/saa7134/saa7134-vbi.c b/drivers/media/video/saa7134/saa7134-vbi.c
index 5707e9021bc73..86954cc7c3776 100644
--- a/drivers/media/video/saa7134/saa7134-vbi.c
+++ b/drivers/media/video/saa7134/saa7134-vbi.c
@@ -1,5 +1,5 @@
/*
- * $Id: saa7134-vbi.c,v 1.5 2004/11/07 13:17:15 kraxel Exp $
+ * $Id: saa7134-vbi.c,v 1.6 2004/12/10 12:33:39 kraxel Exp $
*
* device driver for philips saa7134 based TV cards
* video4linux video interface
@@ -24,6 +24,7 @@
#include <linux/init.h>
#include <linux/list.h>
#include <linux/module.h>
+#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/slab.h>
diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c
index b00696a26b968..5d66060026ff5 100644
--- a/drivers/media/video/saa7134/saa7134-video.c
+++ b/drivers/media/video/saa7134/saa7134-video.c
@@ -1,5 +1,5 @@
/*
- * $Id: saa7134-video.c,v 1.19 2004/11/07 14:44:59 kraxel Exp $
+ * $Id: saa7134-video.c,v 1.28 2005/02/15 15:59:35 kraxel Exp $
*
* device driver for philips saa7134 based TV cards
* video4linux video interface
@@ -24,6 +24,7 @@
#include <linux/init.h>
#include <linux/list.h>
#include <linux/module.h>
+#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/slab.h>
@@ -267,6 +268,24 @@ static struct saa7134_tvnorm tvnorms[] = {
.chroma_ctrl2 = 0x06,
.vgate_misc = 0x1c,
+ },{
+ .name = "PAL-60",
+ .id = V4L2_STD_PAL_60,
+
+ .h_start = 0,
+ .h_stop = 719,
+ .video_v_start = 22,
+ .video_v_stop = 22+239,
+ .vbi_v_start = 10, /* FIXME */
+ .vbi_v_stop = 21, /* FIXME */
+ .src_timing = 1,
+
+ .sync_control = 0x18,
+ .luma_control = 0x40,
+ .chroma_ctrl1 = 0x81,
+ .chroma_gain = 0x2a,
+ .chroma_ctrl2 = 0x06,
+ .vgate_misc = 0x1c,
}
};
#define TVNORMS ARRAY_SIZE(tvnorms)
@@ -443,11 +462,10 @@ void res_free(struct saa7134_dev *dev, struct saa7134_fh *fh, unsigned int bits)
static void set_tvnorm(struct saa7134_dev *dev, struct saa7134_tvnorm *norm)
{
- int luma_control,sync_control,mux,nosignal;
+ int luma_control,sync_control,mux;
dprintk("set tv norm = %s\n",norm->name);
dev->tvnorm = norm;
- nosignal = (0 == (saa_readb(SAA7134_STATUS_VIDEO1) & 0x03));
mux = card_in(dev,dev->ctl_input).vmux;
luma_control = norm->luma_control;
@@ -455,7 +473,7 @@ static void set_tvnorm(struct saa7134_dev *dev, struct saa7134_tvnorm *norm)
if (mux > 5)
luma_control |= 0x80; /* svideo */
- if (noninterlaced || nosignal)
+ if (noninterlaced || dev->nosignal)
sync_control |= 0x20;
/* setup cropping */
@@ -1359,6 +1377,9 @@ static int video_release(struct inode *inode, struct file *file)
res_free(dev,fh,RESOURCE_VBI);
}
+ /* free stuff */
+ videobuf_mmap_free(&fh->cap);
+ videobuf_mmap_free(&fh->vbi);
saa7134_pgtable_free(dev->pci,&fh->pt_cap);
saa7134_pgtable_free(dev->pci,&fh->pt_vbi);
@@ -1472,6 +1493,7 @@ static int saa7134_try_fmt(struct saa7134_dev *dev, struct saa7134_fh *fh,
f->fmt.pix.width = maxw;
if (f->fmt.pix.height > maxh)
f->fmt.pix.height = maxh;
+ f->fmt.pix.width &= ~0x03;
f->fmt.pix.bytesperline =
(f->fmt.pix.width * fmt->depth) >> 3;
f->fmt.pix.sizeimage =
@@ -2267,7 +2289,7 @@ int saa7134_video_init1(struct saa7134_dev *dev)
dev->ctl_hue = ctrl_by_id(V4L2_CID_HUE)->default_value;
dev->ctl_saturation = ctrl_by_id(V4L2_CID_SATURATION)->default_value;
dev->ctl_volume = ctrl_by_id(V4L2_CID_AUDIO_VOLUME)->default_value;
- dev->ctl_mute = ctrl_by_id(V4L2_CID_AUDIO_MUTE)->default_value;
+ dev->ctl_mute = 1; // ctrl_by_id(V4L2_CID_AUDIO_MUTE)->default_value;
dev->ctl_invert = ctrl_by_id(V4L2_CID_PRIVATE_INVERT)->default_value;
dev->ctl_automute = ctrl_by_id(V4L2_CID_PRIVATE_AUTOMUTE)->default_value;
@@ -2317,24 +2339,31 @@ int saa7134_video_fini(struct saa7134_dev *dev)
void saa7134_irq_video_intl(struct saa7134_dev *dev)
{
static const char *st[] = {
- "no signal", "found NTSC", "found PAL", "found SECAM" };
- int norm;
-
- norm = saa_readb(SAA7134_STATUS_VIDEO1) & 0x03;
- dprintk("DCSDT: %s\n",st[norm]);
-
- if (0 != norm) {
- /* wake up tvaudio audio carrier scan thread */
- saa7134_tvaudio_do_scan(dev);
- if (!noninterlaced)
- saa_clearb(SAA7134_SYNC_CTRL, 0x20);
- } else {
+ "(no signal)", "NTSC", "PAL", "SECAM" };
+ u32 st1,st2;
+
+ st1 = saa_readb(SAA7134_STATUS_VIDEO1);
+ st2 = saa_readb(SAA7134_STATUS_VIDEO2);
+ dprintk("DCSDT: pll: %s, sync: %s, norm: %s\n",
+ (st1 & 0x40) ? "not locked" : "locked",
+ (st2 & 0x40) ? "no" : "yes",
+ st[st1 & 0x03]);
+ dev->nosignal = (st1 & 0x40) || (st2 & 0x40);
+
+ if (dev->nosignal) {
/* no video signal -> mute audio */
if (dev->ctl_automute)
dev->automute = 1;
saa7134_tvaudio_setmute(dev);
saa_setb(SAA7134_SYNC_CTRL, 0x20);
+ } else {
+ /* wake up tvaudio audio carrier scan thread */
+ saa7134_tvaudio_do_scan(dev);
+ if (!noninterlaced)
+ saa_clearb(SAA7134_SYNC_CTRL, 0x20);
}
+ if (dev->mops && dev->mops->signal_change)
+ dev->mops->signal_change(dev);
}
void saa7134_irq_video_done(struct saa7134_dev *dev, unsigned long status)
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h
index a4e68b3fc182d..ac90a98532360 100644
--- a/drivers/media/video/saa7134/saa7134.h
+++ b/drivers/media/video/saa7134/saa7134.h
@@ -1,5 +1,5 @@
/*
- * $Id: saa7134.h,v 1.27 2004/11/04 11:03:52 kraxel Exp $
+ * $Id: saa7134.h,v 1.38 2005/03/07 12:01:51 kraxel Exp $
*
* v4l2 device driver for philips saa7134 based TV cards
*
@@ -64,6 +64,7 @@ enum saa7134_audio_in {
TV = 1,
LINE1 = 2,
LINE2 = 3,
+ LINE2_LEFT,
};
enum saa7134_video_out {
@@ -156,11 +157,11 @@ struct saa7134_format {
#define SAA7134_BOARD_AVACSSMARTTV 32
#define SAA7134_BOARD_AVERMEDIA_DVD_EZMAKER 33
#define SAA7134_BOARD_NOVAC_PRIMETV7133 34
-#define SAA7134_BOARD_AVERMEDIA_305 35
+#define SAA7134_BOARD_AVERMEDIA_STUDIO_305 35
#define SAA7133_BOARD_UPMOST_PURPLE_TV 36
#define SAA7134_BOARD_ITEMS_MTV005 37
#define SAA7134_BOARD_CINERGY200 38
-#define SAA7134_BOARD_FLYTVPLATINUM 39
+#define SAA7134_BOARD_FLYTVPLATINUM_MINI 39
#define SAA7134_BOARD_VIDEOMATE_TV_PVR 40
#define SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUS 41
#define SAA7134_BOARD_SABRENT_SBTTVFM 42
@@ -169,6 +170,14 @@ struct saa7134_format {
#define SAA7134_BOARD_AVERMEDIA_307 45
#define SAA7134_BOARD_AVERMEDIA_CARDBUS 46
#define SAA7134_BOARD_CINERGY400_CARDBUS 47
+#define SAA7134_BOARD_CINERGY600_MK3 48
+#define SAA7134_BOARD_VIDEOMATE_GOLD_PLUS 49
+#define SAA7134_BOARD_PINNACLE_300I_DVBT_PAL 50
+#define SAA7134_BOARD_PROVIDEO_PV952 51
+#define SAA7134_BOARD_AVERMEDIA_305 52
+#define SAA7135_BOARD_ASUSTeK_TVFM7135 53
+#define SAA7134_BOARD_FLYTVPLATINUM_FM 54
+#define SAA7134_BOARD_FLYDVBTDUO 55
#define SAA7134_MAXBOARDS 8
#define SAA7134_INPUT_MAX 8
@@ -355,6 +364,7 @@ struct saa7134_mpeg_ops {
struct list_head next;
int (*init)(struct saa7134_dev *dev);
int (*fini)(struct saa7134_dev *dev);
+ void (*signal_change)(struct saa7134_dev *dev);
};
/* global device status */
@@ -390,6 +400,7 @@ struct saa7134_dev {
unsigned int tuner_type;
unsigned int tda9887_conf;
unsigned int gpio_value;
+ unsigned int irq2_mask;
/* i2c i/o */
struct i2c_adapter i2c_adap;
@@ -437,6 +448,7 @@ struct saa7134_dev {
struct saa7134_input *hw_input;
unsigned int hw_mute;
int last_carrier;
+ int nosignal;
/* SAA7134_MPEG_* */
struct saa7134_ts ts;
@@ -447,6 +459,8 @@ struct saa7134_dev {
struct video_device *empress_dev;
struct videobuf_queue empress_tsq;
unsigned int empress_users;
+ struct work_struct empress_workqueue;
+ int empress_started;
/* SAA7134_MPEG_DVB only */
struct videobuf_dvb dvb;
@@ -476,7 +490,6 @@ struct saa7134_dev {
/* saa7134-core.c */
extern struct list_head saa7134_devlist;
-extern unsigned int saa7134_devcount;
void saa7134_print_ioctl(char *name, unsigned int cmd);
void saa7134_track_gpio(struct saa7134_dev *dev, char *msg);
diff --git a/drivers/media/video/saa7185.c b/drivers/media/video/saa7185.c
index 26d62b43e816c..5f0b224c3cb63 100644
--- a/drivers/media/video/saa7185.c
+++ b/drivers/media/video/saa7185.c
@@ -118,7 +118,7 @@ saa7185_write_block (struct i2c_client *client,
u8 block_data[32];
msg.addr = client->addr;
- msg.flags = client->flags;
+ msg.flags = 0;
while (len >= 2) {
msg.buf = (char *) block_data;
msg.len = 0;
@@ -398,7 +398,6 @@ static struct i2c_client_address_data addr_data = {
.force = force
};
-static int saa7185_i2c_id = 0;
static struct i2c_driver i2c_driver_saa7185;
static int
@@ -427,9 +426,7 @@ saa7185_detect_client (struct i2c_adapter *adapter,
client->adapter = adapter;
client->driver = &i2c_driver_saa7185;
client->flags = I2C_CLIENT_ALLOW_USE;
- client->id = saa7185_i2c_id++;
- snprintf(I2C_NAME(client), sizeof(I2C_NAME(client)) - 1,
- "saa7185[%d]", client->id);
+ strlcpy(I2C_NAME(client), "saa7185", sizeof(I2C_NAME(client)));
encoder = kmalloc(sizeof(struct saa7185), GFP_KERNEL);
if (encoder == NULL) {
diff --git a/drivers/media/video/stradis.c b/drivers/media/video/stradis.c
index 35fc25454e85b..b57743571087b 100644
--- a/drivers/media/video/stradis.c
+++ b/drivers/media/video/stradis.c
@@ -2181,12 +2181,9 @@ static void release_saa(void)
/* unmap and free memory */
saa->audhead = saa->audtail = saa->osdhead = 0;
saa->vidhead = saa->vidtail = saa->osdtail = 0;
- if (saa->vidbuf)
- vfree(saa->vidbuf);
- if (saa->audbuf)
- vfree(saa->audbuf);
- if (saa->osdbuf)
- vfree(saa->osdbuf);
+ vfree(saa->vidbuf);
+ vfree(saa->audbuf);
+ vfree(saa->osdbuf);
if (saa->dmavid2)
kfree((void *) saa->dmavid2);
saa->audbuf = saa->vidbuf = saa->osdbuf = NULL;
diff --git a/drivers/media/video/tda7432.c b/drivers/media/video/tda7432.c
index 1272113e118f8..376a4a439e9b5 100644
--- a/drivers/media/video/tda7432.c
+++ b/drivers/media/video/tda7432.c
@@ -528,7 +528,6 @@ static struct i2c_driver driver = {
static struct i2c_client client_template =
{
I2C_DEVNAME("tda7432"),
- .id = -1,
.driver = &driver,
};
diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c
new file mode 100644
index 0000000000000..b27cc348d95ce
--- /dev/null
+++ b/drivers/media/video/tda8290.c
@@ -0,0 +1,224 @@
+/*
+ * $Id: tda8290.c,v 1.7 2005/03/07 12:01:51 kraxel Exp $
+ *
+ * i2c tv tuner chip device driver
+ * controls the philips tda8290+75 tuner chip combo.
+ */
+#include <linux/i2c.h>
+#include <linux/videodev.h>
+#include <linux/delay.h>
+#include <media/tuner.h>
+
+/* ---------------------------------------------------------------------- */
+
+struct freq_entry {
+ u16 freq;
+ u8 value;
+};
+
+static struct freq_entry band_table[] = {
+ { 0x2DF4, 0x1C },
+ { 0x2574, 0x14 },
+ { 0x22B4, 0x0C },
+ { 0x20D4, 0x0B },
+ { 0x1E74, 0x3B },
+ { 0x1C34, 0x33 },
+ { 0x16F4, 0x5B },
+ { 0x1454, 0x53 },
+ { 0x12D4, 0x52 },
+ { 0x1034, 0x4A },
+ { 0x0EE4, 0x7A },
+ { 0x0D34, 0x72 },
+ { 0x0B54, 0x9A },
+ { 0x0914, 0x91 },
+ { 0x07F4, 0x89 },
+ { 0x0774, 0xB9 },
+ { 0x067B, 0xB1 },
+ { 0x0634, 0xD9 },
+ { 0x05A4, 0xD8 }, // FM radio
+ { 0x0494, 0xD0 },
+ { 0x03BC, 0xC8 },
+ { 0x0394, 0xF8 }, // 57250000 Hz
+ { 0x0000, 0xF0 }, // 0
+};
+
+static struct freq_entry div_table[] = {
+ { 0x1C34, 3 },
+ { 0x0D34, 2 },
+ { 0x067B, 1 },
+ { 0x0000, 0 },
+};
+
+static struct freq_entry agc_table[] = {
+ { 0x22B4, 0x8F },
+ { 0x0B54, 0x9F },
+ { 0x09A4, 0x8F },
+ { 0x0554, 0x9F },
+ { 0x0000, 0xBF },
+};
+
+static __u8 get_freq_entry( struct freq_entry* table, __u16 freq)
+{
+ while(table->freq && table->freq > freq)
+ table++;
+ return table->value;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static unsigned char i2c_enable_bridge[2] = { 0x21, 0xC0 };
+static unsigned char i2c_disable_bridge[2] = { 0x21, 0x80 };
+static unsigned char i2c_init_tda8275[14] = { 0x00, 0x00, 0x00, 0x00,
+ 0x7C, 0x04, 0xA3, 0x3F,
+ 0x2A, 0x04, 0xFF, 0x00,
+ 0x00, 0x40 };
+static unsigned char i2c_set_VS[2] = { 0x30, 0x6F };
+static unsigned char i2c_set_GP01_CF[2] = { 0x20, 0x0B };
+static unsigned char i2c_tda8290_reset[2] = { 0x00, 0x00 };
+static unsigned char i2c_gainset_off[2] = { 0x28, 0x14 };
+static unsigned char i2c_gainset_on[2] = { 0x28, 0x54 };
+static unsigned char i2c_agc3_00[2] = { 0x80, 0x00 };
+static unsigned char i2c_agc2_BF[2] = { 0x60, 0xBF };
+static unsigned char i2c_cb1_D2[2] = { 0x30, 0xD2 };
+static unsigned char i2c_cb1_56[2] = { 0x30, 0x56 };
+static unsigned char i2c_cb1_52[2] = { 0x30, 0x52 };
+static unsigned char i2c_cb1_50[2] = { 0x30, 0x50 };
+static unsigned char i2c_agc2_7F[2] = { 0x60, 0x7F };
+static unsigned char i2c_agc3_08[2] = { 0x80, 0x08 };
+
+static struct i2c_msg i2c_msg_init[] = {
+ { I2C_ADDR_TDA8275, 0, ARRAY_SIZE(i2c_init_tda8275), i2c_init_tda8275 },
+ { I2C_ADDR_TDA8290, 0, ARRAY_SIZE(i2c_disable_bridge), i2c_disable_bridge },
+ { I2C_ADDR_TDA8290, 0, ARRAY_SIZE(i2c_set_VS), i2c_set_VS },
+ { I2C_ADDR_TDA8290, 0, ARRAY_SIZE(i2c_set_GP01_CF), i2c_set_GP01_CF },
+};
+
+static struct i2c_msg i2c_msg_prolog[] = {
+// { I2C_ADDR_TDA8290, 0, ARRAY_SIZE(i2c_easy_mode), i2c_easy_mode },
+ { I2C_ADDR_TDA8290, 0, ARRAY_SIZE(i2c_gainset_off), i2c_gainset_off },
+ { I2C_ADDR_TDA8290, 0, ARRAY_SIZE(i2c_tda8290_reset), i2c_tda8290_reset },
+ { I2C_ADDR_TDA8290, 0, ARRAY_SIZE(i2c_enable_bridge), i2c_enable_bridge },
+};
+
+static struct i2c_msg i2c_msg_config[] = {
+// { I2C_ADDR_TDA8275, 0, ARRAY_SIZE(i2c_set_freq), i2c_set_freq },
+ { I2C_ADDR_TDA8275, 0, ARRAY_SIZE(i2c_agc3_00), i2c_agc3_00 },
+ { I2C_ADDR_TDA8275, 0, ARRAY_SIZE(i2c_agc2_BF), i2c_agc2_BF },
+ { I2C_ADDR_TDA8275, 0, ARRAY_SIZE(i2c_cb1_D2), i2c_cb1_D2 },
+ { I2C_ADDR_TDA8275, 0, ARRAY_SIZE(i2c_cb1_56), i2c_cb1_56 },
+ { I2C_ADDR_TDA8275, 0, ARRAY_SIZE(i2c_cb1_52), i2c_cb1_52 },
+};
+
+static struct i2c_msg i2c_msg_epilog[] = {
+ { I2C_ADDR_TDA8275, 0, ARRAY_SIZE(i2c_cb1_50), i2c_cb1_50 },
+ { I2C_ADDR_TDA8275, 0, ARRAY_SIZE(i2c_agc2_7F), i2c_agc2_7F },
+ { I2C_ADDR_TDA8275, 0, ARRAY_SIZE(i2c_agc3_08), i2c_agc3_08 },
+ { I2C_ADDR_TDA8290, 0, ARRAY_SIZE(i2c_disable_bridge), i2c_disable_bridge },
+ { I2C_ADDR_TDA8290, 0, ARRAY_SIZE(i2c_gainset_on), i2c_gainset_on },
+};
+
+static int tda8290_tune(struct i2c_client *c)
+{
+ struct tuner *t = i2c_get_clientdata(c);
+ struct i2c_msg easy_mode =
+ { I2C_ADDR_TDA8290, 0, 2, t->i2c_easy_mode };
+ struct i2c_msg set_freq =
+ { I2C_ADDR_TDA8275, 0, 8, t->i2c_set_freq };
+
+ i2c_transfer(c->adapter, &easy_mode, 1);
+ i2c_transfer(c->adapter, i2c_msg_prolog, ARRAY_SIZE(i2c_msg_prolog));
+
+ i2c_transfer(c->adapter, &set_freq, 1);
+ i2c_transfer(c->adapter, i2c_msg_config, ARRAY_SIZE(i2c_msg_config));
+
+ msleep(550);
+ i2c_transfer(c->adapter, i2c_msg_epilog, ARRAY_SIZE(i2c_msg_epilog));
+ return 0;
+}
+
+static void set_frequency(struct tuner *t, u16 ifc)
+{
+ u32 N = (((t->freq<<3)+ifc)&0x3fffc);
+
+ N = N >> get_freq_entry(div_table, t->freq);
+ t->i2c_set_freq[0] = 0;
+ t->i2c_set_freq[1] = (unsigned char)(N>>8);
+ t->i2c_set_freq[2] = (unsigned char) N;
+ t->i2c_set_freq[3] = 0x40;
+ t->i2c_set_freq[4] = 0x52;
+ t->i2c_set_freq[5] = get_freq_entry(band_table, t->freq);
+ t->i2c_set_freq[6] = get_freq_entry(agc_table, t->freq);
+ t->i2c_set_freq[7] = 0x8f;
+}
+
+#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)
+{
+ t->i2c_easy_mode[0] = 0x01;
+
+ if (t->std & V4L2_STD_MN)
+ t->i2c_easy_mode[1] = 0x01;
+ else if (t->std & V4L2_STD_B)
+ t->i2c_easy_mode[1] = 0x02;
+ else if (t->std & V4L2_STD_GH)
+ t->i2c_easy_mode[1] = 0x04;
+ else if (t->std & V4L2_STD_PAL_I)
+ t->i2c_easy_mode[1] = 0x08;
+ else if (t->std & V4L2_STD_DK)
+ t->i2c_easy_mode[1] = 0x10;
+ else if (t->std & V4L2_STD_SECAM_L)
+ t->i2c_easy_mode[1] = 0x20;
+}
+
+static void set_tv_freq(struct i2c_client *c, unsigned int freq)
+{
+ struct tuner *t = i2c_get_clientdata(c);
+
+ set_audio(t);
+ set_frequency(t, 864);
+ tda8290_tune(c);
+}
+
+static void set_radio_freq(struct i2c_client *c, unsigned int freq)
+{
+ struct tuner *t = i2c_get_clientdata(c);
+ set_frequency(t, 704);
+ tda8290_tune(c);
+}
+
+static int has_signal(struct i2c_client *c)
+{
+ unsigned char i2c_get_afc[1] = { 0x1B };
+ unsigned char afc = 0;
+
+ i2c_master_send(c, i2c_get_afc, ARRAY_SIZE(i2c_get_afc));
+ i2c_master_recv(c, &afc, 1);
+ return (afc & 0x80)? 65535:0;
+}
+
+int tda8290_init(struct i2c_client *c)
+{
+ struct tuner *t = i2c_get_clientdata(c);
+
+ strlcpy(c->name, "tda8290+75", sizeof(c->name));
+ tuner_info("tuner: type set to %s\n", c->name);
+ t->tv_freq = set_tv_freq;
+ t->radio_freq = set_radio_freq;
+ t->has_signal = has_signal;
+
+ i2c_master_send(c, i2c_enable_bridge, ARRAY_SIZE(i2c_enable_bridge));
+ i2c_transfer(c->adapter, i2c_msg_init, ARRAY_SIZE(i2c_msg_init));
+ return 0;
+}
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/video/tda9840.c b/drivers/media/video/tda9840.c
index c0438989d28bd..8de20ad14e9b2 100644
--- a/drivers/media/video/tda9840.c
+++ b/drivers/media/video/tda9840.c
@@ -51,9 +51,6 @@ I2C_CLIENT_INSMOD;
static struct i2c_driver driver;
static struct i2c_client client_template;
-/* unique ID allocation */
-static int tda9840_id = 0;
-
static int command(struct i2c_client *client, unsigned int cmd, void *arg)
{
int result;
@@ -179,7 +176,6 @@ static int detect(struct i2c_adapter *adapter, int address, int kind)
/* fill client structure */
memcpy(client, &client_template, sizeof(struct i2c_client));
- client->id = tda9840_id++;
client->addr = address;
client->adapter = adapter;
diff --git a/drivers/media/video/tda9875.c b/drivers/media/video/tda9875.c
index 707cadaf1e573..4f1114c033a11 100644
--- a/drivers/media/video/tda9875.c
+++ b/drivers/media/video/tda9875.c
@@ -399,7 +399,6 @@ static struct i2c_driver driver = {
static struct i2c_client client_template =
{
I2C_DEVNAME("tda9875"),
- .id = -1,
.driver = &driver,
};
diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c
index 941f2c47d3945..7fb063a279610 100644
--- a/drivers/media/video/tda9887.c
+++ b/drivers/media/video/tda9887.c
@@ -557,7 +557,7 @@ static int tda9887_configure(struct tda9887 *t)
#if 0
/* This as-is breaks some cards, must be fixed in a
* card-specific way, probably using TDA9887_SET_CONFIG to
- * turn on/off port2 */
+ * turn on/off port2 */
if (t->std & V4L2_STD_SECAM_L) {
/* secam fixup (FIXME: move this to tvnorms array?) */
buf[1] &= ~cOutputPort2Inactive;
diff --git a/drivers/media/video/tea6415c.c b/drivers/media/video/tea6415c.c
index 807fd7ecd599e..3ec39550bf467 100644
--- a/drivers/media/video/tea6415c.c
+++ b/drivers/media/video/tea6415c.c
@@ -51,9 +51,6 @@ I2C_CLIENT_INSMOD;
static struct i2c_driver driver;
static struct i2c_client client_template;
-/* unique ID allocation */
-static int tea6415c_id = 0;
-
/* this function is called by i2c_probe */
static int detect(struct i2c_adapter *adapter, int address, int kind)
{
@@ -73,7 +70,6 @@ static int detect(struct i2c_adapter *adapter, int address, int kind)
/* fill client structure */
memcpy(client, &client_template, sizeof(struct i2c_client));
- client->id = tea6415c_id++;
client->addr = address;
client->adapter = adapter;
diff --git a/drivers/media/video/tea6420.c b/drivers/media/video/tea6420.c
index f46b2196448e4..bd10710fd909a 100644
--- a/drivers/media/video/tea6420.c
+++ b/drivers/media/video/tea6420.c
@@ -48,9 +48,6 @@ I2C_CLIENT_INSMOD;
static struct i2c_driver driver;
static struct i2c_client client_template;
-/* unique ID allocation */
-static int tea6420_id = 0;
-
/* make a connection between the input 'i' and the output 'o'
with gain 'g' for the tea6420-client 'client' (note: i = 6 means 'mute') */
static int tea6420_switch(struct i2c_client *client, int i, int o, int g)
@@ -111,7 +108,6 @@ static int tea6420_detect(struct i2c_adapter *adapter, int address, int kind)
/* fill client structure */
memcpy(client, &client_template, sizeof(struct i2c_client));
- client->id = tea6420_id++;
client->addr = address;
client->adapter = adapter;
diff --git a/drivers/media/video/tuner-3036.c b/drivers/media/video/tuner-3036.c
index d97e2de690cf9..6b20aa902a8f6 100644
--- a/drivers/media/video/tuner-3036.c
+++ b/drivers/media/video/tuner-3036.c
@@ -192,7 +192,6 @@ i2c_driver_tuner =
static struct i2c_client client_template =
{
- .id = -1,
.driver = &i2c_driver_tuner,
.name = "SAB3036",
};
diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c
new file mode 100644
index 0000000000000..2f4e18d20b7aa
--- /dev/null
+++ b/drivers/media/video/tuner-core.c
@@ -0,0 +1,443 @@
+/*
+ * $Id: tuner-core.c,v 1.5 2005/02/15 15:59:35 kraxel Exp $
+ *
+ * i2c tv tuner chip device driver
+ * core core, i.e. kernel interfaces, registering and so on
+ */
+
+#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/poll.h>
+#include <linux/i2c.h>
+#include <linux/types.h>
+#include <linux/videodev.h>
+#include <linux/init.h>
+
+#include <media/tuner.h>
+#include <media/audiochip.h>
+
+#define UNSET (-1U)
+
+/* standard i2c insmod options */
+static unsigned short normal_i2c[] = {
+ 0x4b, /* tda8290 */
+ I2C_CLIENT_END
+};
+static unsigned short normal_i2c_range[] = {
+ 0x60, 0x6f,
+ I2C_CLIENT_END
+};
+I2C_CLIENT_INSMOD;
+
+/* insmod options used at init time => read/only */
+static unsigned int addr = 0;
+module_param(addr, int, 0444);
+
+/* insmod options used at runtime => read/write */
+unsigned int tuner_debug = 0;
+module_param(tuner_debug, int, 0644);
+
+static unsigned int tv_range[2] = { 44, 958 };
+static unsigned int radio_range[2] = { 65, 108 };
+
+module_param_array(tv_range, int, NULL, 0644);
+module_param_array(radio_range, int, NULL, 0644);
+
+MODULE_DESCRIPTION("device driver for various TV and TV+FM radio tuners");
+MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer");
+MODULE_LICENSE("GPL");
+
+static int this_adap;
+
+static struct i2c_driver driver;
+static struct i2c_client client_template;
+
+/* ---------------------------------------------------------------------- */
+
+// Set tuner frequency, freq in Units of 62.5kHz = 1/16MHz
+static void set_tv_freq(struct i2c_client *c, unsigned int freq)
+{
+ struct tuner *t = i2c_get_clientdata(c);
+
+ if (t->type == UNSET) {
+ tuner_info("tuner type not set\n");
+ return;
+ }
+ if (NULL == t->tv_freq) {
+ tuner_info("Huh? tv_set is NULL?\n");
+ return;
+ }
+ if (freq < tv_range[0]*16 || freq > tv_range[1]*16) {
+ /* FIXME: better do that chip-specific, but
+ right now we don't have that in the config
+ struct and this way is still better than no
+ check at all */
+ tuner_info("TV freq (%d.%02d) out of range (%d-%d)\n",
+ freq/16,freq%16*100/16,tv_range[0],tv_range[1]);
+ return;
+ }
+ t->tv_freq(c,freq);
+}
+
+static void set_radio_freq(struct i2c_client *c, unsigned int freq)
+{
+ struct tuner *t = i2c_get_clientdata(c);
+
+ if (t->type == UNSET) {
+ tuner_info("tuner type not set\n");
+ return;
+ }
+ if (NULL == t->radio_freq) {
+ tuner_info("no radio tuning for this one, sorry.\n");
+ return;
+ }
+ if (freq < radio_range[0]*16 || freq > radio_range[1]*16) {
+ tuner_info("radio freq (%d.%02d) out of range (%d-%d)\n",
+ freq/16,freq%16*100/16,
+ radio_range[0],radio_range[1]);
+ return;
+ }
+ t->radio_freq(c,freq);
+}
+
+static void set_freq(struct i2c_client *c, unsigned long freq)
+{
+ struct tuner *t = i2c_get_clientdata(c);
+
+ switch (t->mode) {
+ case V4L2_TUNER_RADIO:
+ tuner_dbg("radio freq set to %lu.%02lu\n",
+ freq/16,freq%16*100/16);
+ set_radio_freq(c,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);
+ break;
+ }
+ t->freq = freq;
+}
+
+static void set_type(struct i2c_client *c, unsigned int type)
+{
+ struct tuner *t = i2c_get_clientdata(c);
+
+ /* sanity check */
+ if (type == UNSET || type == TUNER_ABSENT)
+ return;
+ if (type >= tuner_count)
+ return;
+
+ if (NULL == t->i2c.dev.driver) {
+ /* not registered yet */
+ t->type = type;
+ return;
+ }
+ if (t->initialized)
+ /* run only once */
+ return;
+
+ t->initialized = 1;
+ t->type = type;
+ switch (t->type) {
+ case TUNER_MT2032:
+ microtune_init(c);
+ break;
+ case TUNER_PHILIPS_TDA8290:
+ tda8290_init(c);
+ break;
+ default:
+ default_tuner_init(c);
+ break;
+ }
+}
+
+static char pal[] = "-";
+module_param_string(pal, pal, 0644, sizeof(pal));
+
+static int tuner_fixup_std(struct tuner *t)
+{
+ if ((t->std & V4L2_STD_PAL) == V4L2_STD_PAL) {
+ /* get more precise norm info from insmod option */
+ switch (pal[0]) {
+ case 'b':
+ case 'B':
+ case 'g':
+ case 'G':
+ tuner_dbg("insmod fixup: PAL => PAL-BG\n");
+ t->std = V4L2_STD_PAL_BG;
+ break;
+ case 'i':
+ case 'I':
+ tuner_dbg("insmod fixup: PAL => PAL-I\n");
+ t->std = V4L2_STD_PAL_I;
+ break;
+ case 'd':
+ case 'D':
+ case 'k':
+ case 'K':
+ tuner_dbg("insmod fixup: PAL => PAL-DK\n");
+ t->std = V4L2_STD_PAL_DK;
+ break;
+ }
+ }
+ return 0;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static int tuner_attach(struct i2c_adapter *adap, int addr, int kind)
+{
+ struct tuner *t;
+
+ if (this_adap > 0)
+ return -1;
+ this_adap++;
+
+ client_template.adapter = adap;
+ client_template.addr = addr;
+
+ t = kmalloc(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
+
+ i2c_attach_client(&t->i2c);
+ tuner_info("chip found @ 0x%x (%s)\n",
+ addr << 1, adap->name);
+ set_type(&t->i2c, t->type);
+ return 0;
+}
+
+static int tuner_probe(struct i2c_adapter *adap)
+{
+ if (0 != addr) {
+ normal_i2c[0] = addr;
+ normal_i2c_range[0] = addr;
+ normal_i2c_range[1] = addr;
+ }
+ this_adap = 0;
+
+ if (adap->class & I2C_CLASS_TV_ANALOG)
+ return i2c_probe(adap, &addr_data, tuner_attach);
+ return 0;
+}
+
+static int tuner_detach(struct i2c_client *client)
+{
+ struct tuner *t = i2c_get_clientdata(client);
+
+ i2c_detach_client(&t->i2c);
+ kfree(t);
+ return 0;
+}
+
+#define SWITCH_V4L2 if (!t->using_v4l2 && tuner_debug) \
+ tuner_info("switching to v4l2\n"); \
+ t->using_v4l2 = 1;
+#define CHECK_V4L2 if (t->using_v4l2) { if (tuner_debug) \
+ tuner_info("ignore v4l1 call\n"); \
+ return 0; }
+
+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;
+
+ switch (cmd) {
+
+ /* --- configuration --- */
+ case TUNER_SET_TYPE:
+ set_type(client,*iarg);
+ break;
+ case AUDC_SET_RADIO:
+ if (V4L2_TUNER_RADIO != t->mode) {
+ set_tv_freq(client,400 * 16);
+ t->mode = V4L2_TUNER_RADIO;
+ }
+ 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;
+ }
+ break;
+
+ /* --- v4l ioctls --- */
+ /* take care: bttv does userspace copying, we'll get a
+ kernel pointer here... */
+ case VIDIOCSCHAN:
+ {
+ static const v4l2_std_id map[] = {
+ [ VIDEO_MODE_PAL ] = V4L2_STD_PAL,
+ [ VIDEO_MODE_NTSC ] = V4L2_STD_NTSC_M,
+ [ VIDEO_MODE_SECAM ] = V4L2_STD_SECAM,
+ [ 4 /* bttv */ ] = V4L2_STD_PAL_M,
+ [ 5 /* bttv */ ] = V4L2_STD_PAL_N,
+ [ 6 /* bttv */ ] = V4L2_STD_NTSC_M_JP,
+ };
+ struct video_channel *vc = arg;
+
+ CHECK_V4L2;
+ t->mode = V4L2_TUNER_ANALOG_TV;
+ if (vc->norm < ARRAY_SIZE(map))
+ t->std = map[vc->norm];
+ tuner_fixup_std(t);
+ if (t->freq)
+ set_tv_freq(client,t->freq);
+ return 0;
+ }
+ case VIDIOCSFREQ:
+ {
+ unsigned long *v = arg;
+
+ CHECK_V4L2;
+ set_freq(client,*v);
+ return 0;
+ }
+ case VIDIOCGTUNER:
+ {
+ struct video_tuner *vt = arg;
+
+ CHECK_V4L2;
+ if (V4L2_TUNER_RADIO == t->mode && t->has_signal)
+ vt->signal = t->has_signal(client);
+ return 0;
+ }
+ case VIDIOCGAUDIO:
+ {
+ struct video_audio *va = arg;
+
+ CHECK_V4L2;
+ if (V4L2_TUNER_RADIO == t->mode && t->is_stereo)
+ va->mode = t->is_stereo(client)
+ ? VIDEO_SOUND_STEREO
+ : VIDEO_SOUND_MONO;
+ return 0;
+ }
+
+ case VIDIOC_S_STD:
+ {
+ v4l2_std_id *id = arg;
+
+ SWITCH_V4L2;
+ t->mode = V4L2_TUNER_ANALOG_TV;
+ t->std = *id;
+ tuner_fixup_std(t);
+ if (t->freq)
+ set_freq(client,t->freq);
+ break;
+ }
+ case VIDIOC_S_FREQUENCY:
+ {
+ struct v4l2_frequency *f = arg;
+
+ SWITCH_V4L2;
+ if (V4L2_TUNER_RADIO == f->type &&
+ V4L2_TUNER_RADIO != t->mode)
+ set_tv_freq(client,400*16);
+ t->mode = f->type;
+ t->freq = f->frequency;
+ set_freq(client,t->freq);
+ break;
+ }
+ case VIDIOC_G_TUNER:
+ {
+ struct v4l2_tuner *tuner = arg;
+
+ SWITCH_V4L2;
+ if (V4L2_TUNER_RADIO == t->mode && t->has_signal)
+ tuner->signal = t->has_signal(client);
+ break;
+ }
+ default:
+ /* nothing */
+ break;
+ }
+
+ return 0;
+}
+
+static int tuner_suspend(struct device * dev, u32 state, u32 level)
+{
+ struct i2c_client *c = container_of(dev, struct i2c_client, dev);
+ struct tuner *t = i2c_get_clientdata(c);
+
+ tuner_dbg("suspend\n");
+ /* FIXME: power down ??? */
+ return 0;
+}
+
+static int tuner_resume(struct device * dev, u32 level)
+{
+ struct i2c_client *c = container_of(dev, struct i2c_client, dev);
+ struct tuner *t = i2c_get_clientdata(c);
+
+ tuner_dbg("resume\n");
+ if (t->freq)
+ set_freq(c,t->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,
+ },
+};
+static struct i2c_client client_template =
+{
+ I2C_DEVNAME("(tuner unset)"),
+ .flags = I2C_CLIENT_ALLOW_USE,
+ .driver = &driver,
+};
+
+static int __init tuner_init_module(void)
+{
+ return i2c_add_driver(&driver);
+}
+
+static void __exit tuner_cleanup_module(void)
+{
+ i2c_del_driver(&driver);
+}
+
+module_init(tuner_init_module);
+module_exit(tuner_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/tuner-simple.c b/drivers/media/video/tuner-simple.c
new file mode 100644
index 0000000000000..48c6ceff1dc26
--- /dev/null
+++ b/drivers/media/video/tuner-simple.c
@@ -0,0 +1,474 @@
+/*
+ * $Id: tuner-simple.c,v 1.10 2005/03/08 08:38:00 kraxel Exp $
+ *
+ * i2c tv tuner chip device driver
+ * controls all those simple 4-control-bytes style tuners.
+ */
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/videodev.h>
+#include <media/tuner.h>
+
+/* ---------------------------------------------------------------------- */
+
+/* tv standard selection for Temic 4046 FM5
+ this value takes the low bits of control byte 2
+ from datasheet Rev.01, Feb.00
+ standard BG I L L2 D
+ picture IF 38.9 38.9 38.9 33.95 38.9
+ sound 1 33.4 32.9 32.4 40.45 32.4
+ sound 2 33.16
+ NICAM 33.05 32.348 33.05 33.05
+ */
+#define TEMIC_SET_PAL_I 0x05
+#define TEMIC_SET_PAL_DK 0x09
+#define TEMIC_SET_PAL_L 0x0a // SECAM ?
+#define TEMIC_SET_PAL_L2 0x0b // change IF !
+#define TEMIC_SET_PAL_BG 0x0c
+
+/* tv tuner system standard selection for Philips FQ1216ME
+ this value takes the low bits of control byte 2
+ from datasheet "1999 Nov 16" (supersedes "1999 Mar 23")
+ standard BG DK I L L`
+ picture carrier 38.90 38.90 38.90 38.90 33.95
+ colour 34.47 34.47 34.47 34.47 38.38
+ sound 1 33.40 32.40 32.90 32.40 40.45
+ sound 2 33.16 - - - -
+ NICAM 33.05 33.05 32.35 33.05 39.80
+ */
+#define PHILIPS_SET_PAL_I 0x01 /* Bit 2 always zero !*/
+#define PHILIPS_SET_PAL_BGDK 0x09
+#define PHILIPS_SET_PAL_L2 0x0a
+#define PHILIPS_SET_PAL_L 0x0b
+
+/* system switching for Philips FI1216MF MK2
+ from datasheet "1996 Jul 09",
+ standard BG L L'
+ picture carrier 38.90 38.90 33.95
+ colour 34.47 34.37 38.38
+ sound 1 33.40 32.40 40.45
+ sound 2 33.16 - -
+ NICAM 33.05 33.05 39.80
+ */
+#define PHILIPS_MF_SET_BG 0x01 /* Bit 2 must be zero, Bit 3 is system output */
+#define PHILIPS_MF_SET_PAL_L 0x03 // France
+#define PHILIPS_MF_SET_PAL_L2 0x02 // L'
+
+
+/* ---------------------------------------------------------------------- */
+
+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.
+ */
+static struct tunertype tuners[] = {
+ { "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},
+ { "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},
+
+ { "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},
+ { "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*160.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},
+
+ { "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},
+ { "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 */ },
+ { "LG PAL (TAPE series)", LGINNOTEK, PAL,
+ 16*170.00, 16*450.00, 0x01,0x02,0x08,0xce,623},
+
+ { "Philips PAL/SECAM multi (FQ1216AME MK4)", Philips, PAL,
+ 16*160.00,16*442.00,0x01,0x02,0x04,0xce,623 },
+ { "Philips FQ1236A MK4", Philips, NTSC,
+ 16*160.00,16*442.00,0x01,0x02,0x04,0x8e,732 },
+
+};
+unsigned const int tuner_count = ARRAY_SIZE(tuners);
+
+/* ---------------------------------------------------------------------- */
+
+static int tuner_getstatus(struct i2c_client *c)
+{
+ unsigned char byte;
+
+ if (1 != i2c_master_recv(c,&byte,1))
+ return 0;
+ return byte;
+}
+
+#define TUNER_POR 0x80
+#define TUNER_FL 0x40
+#define TUNER_MODE 0x38
+#define TUNER_AFC 0x07
+
+#define TUNER_STEREO 0x10 /* radio mode */
+#define TUNER_SIGNAL 0x07 /* radio mode */
+
+static int tuner_signal(struct i2c_client *c)
+{
+ return (tuner_getstatus(c) & TUNER_SIGNAL)<<13;
+}
+
+static int tuner_stereo(struct i2c_client *c)
+{
+ return (tuner_getstatus (c) & TUNER_STEREO);
+}
+
+#if 0 /* unused */
+static int tuner_islocked (struct i2c_client *c)
+{
+ return (tuner_getstatus (c) & TUNER_FL);
+}
+
+static int tuner_afcstatus (struct i2c_client *c)
+{
+ return (tuner_getstatus (c) & TUNER_AFC) - 2;
+}
+
+static int tuner_mode (struct i2c_client *c)
+{
+ return (tuner_getstatus (c) & TUNER_MODE) >> 3;
+}
+#endif
+
+/* ---------------------------------------------------------------------- */
+
+static void default_set_tv_freq(struct i2c_client *c, unsigned int freq)
+{
+ struct tuner *t = i2c_get_clientdata(c);
+ u8 config;
+ u16 div;
+ struct tunertype *tun;
+ unsigned char buffer[4];
+ int rc;
+
+ 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");
+ }
+
+
+ /* tv norm specific stuff for multi-norm tuners */
+ switch (t->type) {
+ case TUNER_PHILIPS_SECAM: // FI1216MF
+ /* 0x01 -> ??? no change ??? */
+ /* 0x02 -> PAL BDGHI / SECAM L */
+ /* 0x04 -> ??? PAL others / SECAM others ??? */
+ config &= ~0x02;
+ if (t->std & V4L2_STD_SECAM)
+ config |= 0x02;
+ break;
+
+ case TUNER_TEMIC_4046FM5:
+ config &= ~0x0f;
+
+ if (t->std & V4L2_STD_PAL_BG) {
+ config |= TEMIC_SET_PAL_BG;
+
+ } else if (t->std & V4L2_STD_PAL_I) {
+ config |= TEMIC_SET_PAL_I;
+
+ } else if (t->std & V4L2_STD_PAL_DK) {
+ config |= TEMIC_SET_PAL_DK;
+
+ } else if (t->std & V4L2_STD_SECAM_L) {
+ config |= TEMIC_SET_PAL_L;
+
+ }
+ break;
+
+ case TUNER_PHILIPS_FQ1216ME:
+ config &= ~0x0f;
+
+ if (t->std & (V4L2_STD_PAL_BG|V4L2_STD_PAL_DK)) {
+ config |= PHILIPS_SET_PAL_BGDK;
+
+ } else if (t->std & V4L2_STD_PAL_I) {
+ config |= PHILIPS_SET_PAL_I;
+
+ } else if (t->std & V4L2_STD_SECAM_L) {
+ config |= PHILIPS_SET_PAL_L;
+
+ }
+ break;
+
+ case TUNER_PHILIPS_ATSC:
+ /* 0x00 -> ATSC antenna input 1 */
+ /* 0x01 -> ATSC antenna input 2 */
+ /* 0x02 -> NTSC antenna input 1 */
+ /* 0x03 -> NTSC antenna input 2 */
+ config &= ~0x03;
+ if (!(t->std & V4L2_STD_ATSC))
+ config |= 2;
+ /* FIXME: input */
+ break;
+
+ case TUNER_MICROTUNE_4042FI5:
+ /* Set the charge pump for fast tuning */
+ tun->config |= 0x40;
+ 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;
+ 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[3] = config;
+ }
+ tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n",
+ buffer[0],buffer[1],buffer[2],buffer[3]);
+
+ if (4 != (rc = i2c_master_send(c,buffer,4)))
+ tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc);
+
+ if (t->type == TUNER_MICROTUNE_4042FI5) {
+ // FIXME - this may also work for other tuners
+ unsigned long timeout = jiffies + msecs_to_jiffies(1);
+ u8 status_byte = 0;
+
+ /* Wait until the PLL locks */
+ for (;;) {
+ if (time_after(jiffies,timeout))
+ return;
+ if (1 != (rc = i2c_master_recv(c,&status_byte,1))) {
+ tuner_warn("i2c i/o read error: rc == %d (should be 1)\n",rc);
+ break;
+ }
+ /* bit 6 is PLL locked indicator */
+ if (status_byte & 0x40)
+ break;
+ udelay(10);
+ }
+
+ /* Set the charge pump for optimized phase noise figure */
+ tun->config &= ~0x40;
+ buffer[0] = (div>>8) & 0x7f;
+ buffer[1] = div & 0xff;
+ buffer[2] = tun->config;
+ buffer[3] = config;
+ tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n",
+ buffer[0],buffer[1],buffer[2],buffer[3]);
+
+ if (4 != (rc = i2c_master_send(c,buffer,4)))
+ tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc);
+ }
+}
+
+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;
+
+ tun=&tuners[t->type];
+ div = freq + (int)(16*10.7);
+ buffer[2] = tun->config;
+
+ switch (t->type) {
+ case TUNER_PHILIPS_FM1216ME_MK3:
+ case TUNER_PHILIPS_FM1236_MK3:
+ buffer[3] = 0x19;
+ break;
+ case TUNER_PHILIPS_FM1256_IH3:
+ div = (20 * freq)/16 + 333 * 2;
+ buffer[2] = 0x80;
+ buffer[3] = 0x19;
+ break;
+ case TUNER_LG_PAL_FM:
+ buffer[3] = 0xa5;
+ break;
+ default:
+ buffer[3] = 0xa4;
+ break;
+ }
+ 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]);
+
+ if (4 != (rc = i2c_master_send(c,buffer,4)))
+ tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc);
+}
+
+int default_tuner_init(struct i2c_client *c)
+{
+ struct tuner *t = i2c_get_clientdata(c);
+
+ tuner_info("type set to %d (%s)\n",
+ 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->has_signal = tuner_signal;
+ t->is_stereo = tuner_stereo;
+ return 0;
+}
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/video/tuner.c b/drivers/media/video/tuner.c
deleted file mode 100644
index 67181ea1b9f53..0000000000000
--- a/drivers/media/video/tuner.c
+++ /dev/null
@@ -1,1425 +0,0 @@
-/*
- * $Id: tuner.c,v 1.36 2005/01/14 13:29:40 kraxel Exp $
- */
-
-#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/poll.h>
-#include <linux/i2c.h>
-#include <linux/types.h>
-#include <linux/videodev.h>
-#include <linux/init.h>
-
-#include <media/tuner.h>
-#include <media/audiochip.h>
-
-#define UNSET (-1U)
-
-/* standard i2c insmod options */
-static unsigned short normal_i2c[] = {I2C_CLIENT_END};
-static unsigned short normal_i2c_range[] = {0x60,0x6f,I2C_CLIENT_END};
-I2C_CLIENT_INSMOD;
-
-/* insmod options used at init time => read/only */
-static unsigned int type = UNSET;
-static unsigned int addr = 0;
-module_param(type, int, 0444);
-module_param(addr, int, 0444);
-
-/* insmod options used at runtime => read/write */
-static unsigned int debug = 0;
-static unsigned int tv_antenna = 1;
-static unsigned int radio_antenna = 0;
-static unsigned int optimize_vco = 1;
-module_param(debug, int, 0644);
-module_param(tv_antenna, int, 0644);
-module_param(radio_antenna, int, 0644);
-module_param(optimize_vco, int, 0644);
-
-static unsigned int tv_range[2] = { 44, 958 };
-static unsigned int radio_range[2] = { 65, 108 };
-
-module_param_array(tv_range, int, NULL, 0644);
-module_param_array(radio_range, int, NULL, 0644);
-
-MODULE_DESCRIPTION("device driver for various TV and TV+FM radio tuners");
-MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer");
-MODULE_LICENSE("GPL");
-
-static int this_adap;
-#define dprintk if (debug) printk
-
-struct tuner {
- unsigned int type; /* chip type */
- unsigned int freq; /* keep track of the current settings */
- v4l2_std_id std;
- int using_v4l2;
-
- enum v4l2_tuner_type mode;
- unsigned int input;
-
- // only for MT2032
- unsigned int xogc;
- unsigned int radio_if2;
-
- void (*tv_freq)(struct i2c_client *c, unsigned int freq);
- void (*radio_freq)(struct i2c_client *c, unsigned int freq);
-};
-
-static struct i2c_driver driver;
-static struct i2c_client client_template;
-
-/* ---------------------------------------------------------------------- */
-
-/* tv standard selection for Temic 4046 FM5
- this value takes the low bits of control byte 2
- from datasheet Rev.01, Feb.00
- standard BG I L L2 D
- picture IF 38.9 38.9 38.9 33.95 38.9
- sound 1 33.4 32.9 32.4 40.45 32.4
- sound 2 33.16
- NICAM 33.05 32.348 33.05 33.05
- */
-#define TEMIC_SET_PAL_I 0x05
-#define TEMIC_SET_PAL_DK 0x09
-#define TEMIC_SET_PAL_L 0x0a // SECAM ?
-#define TEMIC_SET_PAL_L2 0x0b // change IF !
-#define TEMIC_SET_PAL_BG 0x0c
-
-/* tv tuner system standard selection for Philips FQ1216ME
- this value takes the low bits of control byte 2
- from datasheet "1999 Nov 16" (supersedes "1999 Mar 23")
- standard BG DK I L L`
- picture carrier 38.90 38.90 38.90 38.90 33.95
- colour 34.47 34.47 34.47 34.47 38.38
- sound 1 33.40 32.40 32.90 32.40 40.45
- sound 2 33.16 - - - -
- NICAM 33.05 33.05 32.35 33.05 39.80
- */
-#define PHILIPS_SET_PAL_I 0x01 /* Bit 2 always zero !*/
-#define PHILIPS_SET_PAL_BGDK 0x09
-#define PHILIPS_SET_PAL_L2 0x0a
-#define PHILIPS_SET_PAL_L 0x0b
-
-/* system switching for Philips FI1216MF MK2
- from datasheet "1996 Jul 09",
- standard BG L L'
- picture carrier 38.90 38.90 33.95
- colour 34.47 34.37 38.38
- sound 1 33.40 32.40 40.45
- sound 2 33.16 - -
- NICAM 33.05 33.05 39.80
- */
-#define PHILIPS_MF_SET_BG 0x01 /* Bit 2 must be zero, Bit 3 is system output */
-#define PHILIPS_MF_SET_PAL_L 0x03 // France
-#define PHILIPS_MF_SET_PAL_L2 0x02 // L'
-
-
-/* ---------------------------------------------------------------------- */
-
-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.
- */
-static struct tunertype tuners[] = {
- { "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},
- { "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},
-
- { "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},
- { "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,
- 0,0,0,0,0,0,0},
- { "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*160.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},
-
- { "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},
- { "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
-
-};
-#define TUNERS ARRAY_SIZE(tuners)
-
-/* ---------------------------------------------------------------------- */
-
-static int tuner_getstatus(struct i2c_client *c)
-{
- unsigned char byte;
-
- struct tuner *t = i2c_get_clientdata(c);
-
- if (t->type == TUNER_MT2032)
- return 0;
-
- if (1 != i2c_master_recv(c,&byte,1))
- return 0;
- return byte;
-}
-
-#define TUNER_POR 0x80
-#define TUNER_FL 0x40
-#define TUNER_MODE 0x38
-#define TUNER_AFC 0x07
-
-#define TUNER_STEREO 0x10 /* radio mode */
-#define TUNER_SIGNAL 0x07 /* radio mode */
-
-static int tuner_signal(struct i2c_client *c)
-{
- return (tuner_getstatus(c) & TUNER_SIGNAL)<<13;
-}
-
-static int tuner_stereo(struct i2c_client *c)
-{
- return (tuner_getstatus (c) & TUNER_STEREO);
-}
-
-#if 0 /* unused */
-static int tuner_islocked (struct i2c_client *c)
-{
- return (tuner_getstatus (c) & TUNER_FL);
-}
-
-static int tuner_afcstatus (struct i2c_client *c)
-{
- return (tuner_getstatus (c) & TUNER_AFC) - 2;
-}
-
-static int tuner_mode (struct i2c_client *c)
-{
- return (tuner_getstatus (c) & TUNER_MODE) >> 3;
-}
-#endif
-
-/* ---------------------------------------------------------------------- */
-
-#define MT2032 0x04
-#define MT2030 0x06
-#define MT2040 0x07
-#define MT2050 0x42
-
-static char *microtune_part[] = {
- [ MT2030 ] = "MT2030",
- [ MT2032 ] = "MT2032",
- [ MT2040 ] = "MT2040",
- [ MT2050 ] = "MT2050",
-};
-
-// IsSpurInBand()?
-static int mt2032_spurcheck(int f1, int f2, int spectrum_from,int spectrum_to)
-{
- int n1=1,n2,f;
-
- f1=f1/1000; //scale to kHz to avoid 32bit overflows
- f2=f2/1000;
- spectrum_from/=1000;
- spectrum_to/=1000;
-
- dprintk("spurcheck f1=%d f2=%d from=%d to=%d\n",f1,f2,spectrum_from,spectrum_to);
-
- do {
- n2=-n1;
- f=n1*(f1-f2);
- do {
- n2--;
- f=f-f2;
- dprintk(" spurtest n1=%d n2=%d ftest=%d\n",n1,n2,f);
-
- if( (f>spectrum_from) && (f<spectrum_to))
- printk("mt2032 spurcheck triggered: %d\n",n1);
- } while ( (f>(f2-spectrum_to)) || (n2>-5));
- n1++;
- } while (n1<5);
-
- return 1;
-}
-
-static int mt2032_compute_freq(unsigned int rfin,
- unsigned int if1, unsigned int if2,
- unsigned int spectrum_from,
- unsigned int spectrum_to,
- unsigned char *buf,
- int *ret_sel,
- unsigned int xogc) //all in Hz
-{
- unsigned int fref,lo1,lo1n,lo1a,s,sel,lo1freq, desired_lo1,
- desired_lo2,lo2,lo2n,lo2a,lo2num,lo2freq;
-
- fref= 5250 *1000; //5.25MHz
- desired_lo1=rfin+if1;
-
- lo1=(2*(desired_lo1/1000)+(fref/1000)) / (2*fref/1000);
- lo1n=lo1/8;
- lo1a=lo1-(lo1n*8);
-
- s=rfin/1000/1000+1090;
-
- if(optimize_vco) {
- if(s>1890) sel=0;
- else if(s>1720) sel=1;
- else if(s>1530) sel=2;
- else if(s>1370) sel=3;
- else sel=4; // >1090
- }
- else {
- if(s>1790) sel=0; // <1958
- else if(s>1617) sel=1;
- else if(s>1449) sel=2;
- else if(s>1291) sel=3;
- else sel=4; // >1090
- }
- *ret_sel=sel;
-
- lo1freq=(lo1a+8*lo1n)*fref;
-
- dprintk("mt2032: rfin=%d lo1=%d lo1n=%d lo1a=%d sel=%d, lo1freq=%d\n",
- rfin,lo1,lo1n,lo1a,sel,lo1freq);
-
- desired_lo2=lo1freq-rfin-if2;
- lo2=(desired_lo2)/fref;
- lo2n=lo2/8;
- lo2a=lo2-(lo2n*8);
- lo2num=((desired_lo2/1000)%(fref/1000))* 3780/(fref/1000); //scale to fit in 32bit arith
- lo2freq=(lo2a+8*lo2n)*fref + lo2num*(fref/1000)/3780*1000;
-
- dprintk("mt2032: rfin=%d lo2=%d lo2n=%d lo2a=%d num=%d lo2freq=%d\n",
- rfin,lo2,lo2n,lo2a,lo2num,lo2freq);
-
- if(lo1a<0 || lo1a>7 || lo1n<17 ||lo1n>48 || lo2a<0 ||lo2a >7 ||lo2n<17 || lo2n>30) {
- printk("mt2032: frequency parameters out of range: %d %d %d %d\n",
- lo1a, lo1n, lo2a,lo2n);
- return(-1);
- }
-
- mt2032_spurcheck(lo1freq, desired_lo2, spectrum_from, spectrum_to);
- // should recalculate lo1 (one step up/down)
-
- // set up MT2032 register map for transfer over i2c
- buf[0]=lo1n-1;
- buf[1]=lo1a | (sel<<4);
- buf[2]=0x86; // LOGC
- buf[3]=0x0f; //reserved
- buf[4]=0x1f;
- buf[5]=(lo2n-1) | (lo2a<<5);
- if(rfin >400*1000*1000)
- buf[6]=0xe4;
- else
- buf[6]=0xf4; // set PKEN per rev 1.2
- buf[7]=8+xogc;
- buf[8]=0xc3; //reserved
- buf[9]=0x4e; //reserved
- buf[10]=0xec; //reserved
- buf[11]=(lo2num&0xff);
- buf[12]=(lo2num>>8) |0x80; // Lo2RST
-
- return 0;
-}
-
-static int mt2032_check_lo_lock(struct i2c_client *c)
-{
- int try,lock=0;
- unsigned char buf[2];
- for(try=0;try<10;try++) {
- buf[0]=0x0e;
- i2c_master_send(c,buf,1);
- i2c_master_recv(c,buf,1);
- dprintk("mt2032 Reg.E=0x%02x\n",buf[0]);
- lock=buf[0] &0x06;
-
- if (lock==6)
- break;
-
- dprintk("mt2032: pll wait 1ms for lock (0x%2x)\n",buf[0]);
- udelay(1000);
- }
- return lock;
-}
-
-static int mt2032_optimize_vco(struct i2c_client *c,int sel,int lock)
-{
- unsigned char buf[2];
- int tad1;
-
- buf[0]=0x0f;
- i2c_master_send(c,buf,1);
- i2c_master_recv(c,buf,1);
- dprintk("mt2032 Reg.F=0x%02x\n",buf[0]);
- tad1=buf[0]&0x07;
-
- if(tad1 ==0) return lock;
- if(tad1 ==1) return lock;
-
- if(tad1==2) {
- if(sel==0)
- return lock;
- else sel--;
- }
- else {
- if(sel<4)
- sel++;
- else
- return lock;
- }
-
- dprintk("mt2032 optimize_vco: sel=%d\n",sel);
-
- buf[0]=0x0f;
- buf[1]=sel;
- i2c_master_send(c,buf,2);
- lock=mt2032_check_lo_lock(c);
- return lock;
-}
-
-
-static void mt2032_set_if_freq(struct i2c_client *c, unsigned int rfin,
- unsigned int if1, unsigned int if2,
- unsigned int from, unsigned int to)
-{
- unsigned char buf[21];
- int lint_try,ret,sel,lock=0;
- struct tuner *t = i2c_get_clientdata(c);
-
- dprintk("mt2032_set_if_freq rfin=%d if1=%d if2=%d from=%d to=%d\n",rfin,if1,if2,from,to);
-
- buf[0]=0;
- ret=i2c_master_send(c,buf,1);
- i2c_master_recv(c,buf,21);
-
- buf[0]=0;
- ret=mt2032_compute_freq(rfin,if1,if2,from,to,&buf[1],&sel,t->xogc);
- if (ret<0)
- return;
-
- // send only the relevant registers per Rev. 1.2
- buf[0]=0;
- ret=i2c_master_send(c,buf,4);
- buf[5]=5;
- ret=i2c_master_send(c,buf+5,4);
- buf[11]=11;
- ret=i2c_master_send(c,buf+11,3);
- if(ret!=3)
- printk("mt2032_set_if_freq failed with %d\n",ret);
-
- // wait for PLLs to lock (per manual), retry LINT if not.
- for(lint_try=0; lint_try<2; lint_try++) {
- lock=mt2032_check_lo_lock(c);
-
- if(optimize_vco)
- lock=mt2032_optimize_vco(c,sel,lock);
- if(lock==6) break;
-
- printk("mt2032: re-init PLLs by LINT\n");
- buf[0]=7;
- buf[1]=0x80 +8+t->xogc; // set LINT to re-init PLLs
- i2c_master_send(c,buf,2);
- mdelay(10);
- buf[1]=8+t->xogc;
- i2c_master_send(c,buf,2);
- }
-
- if (lock!=6)
- printk("MT2032 Fatal Error: PLLs didn't lock.\n");
-
- buf[0]=2;
- buf[1]=0x20; // LOGC for optimal phase noise
- ret=i2c_master_send(c,buf,2);
- if (ret!=2)
- printk("mt2032_set_if_freq2 failed with %d\n",ret);
-}
-
-
-static void mt2032_set_tv_freq(struct i2c_client *c, unsigned int freq)
-{
- struct tuner *t = i2c_get_clientdata(c);
- int if2,from,to;
-
- // signal bandwidth and picture carrier
- if (t->std & V4L2_STD_525_60) {
- // NTSC
- from = 40750*1000;
- to = 46750*1000;
- if2 = 45750*1000;
- } else {
- // PAL
- from = 32900*1000;
- to = 39900*1000;
- if2 = 38900*1000;
- }
-
- mt2032_set_if_freq(c, freq*62500 /* freq*1000*1000/16 */,
- 1090*1000*1000, if2, from, to);
-}
-
-static void mt2032_set_radio_freq(struct i2c_client *c, unsigned int freq)
-{
- struct tuner *t = i2c_get_clientdata(c);
- int if2 = t->radio_if2;
-
- // per Manual for FM tuning: first if center freq. 1085 MHz
- mt2032_set_if_freq(c, freq*62500 /* freq*1000*1000/16 */,
- 1085*1000*1000,if2,if2,if2);
-}
-
-// Initalization as described in "MT203x Programming Procedures", Rev 1.2, Feb.2001
-static int mt2032_init(struct i2c_client *c)
-{
- struct tuner *t = i2c_get_clientdata(c);
- unsigned char buf[21];
- int ret,xogc,xok=0;
-
- // Initialize Registers per spec.
- buf[1]=2; // Index to register 2
- buf[2]=0xff;
- buf[3]=0x0f;
- buf[4]=0x1f;
- ret=i2c_master_send(c,buf+1,4);
-
- buf[5]=6; // Index register 6
- buf[6]=0xe4;
- buf[7]=0x8f;
- buf[8]=0xc3;
- buf[9]=0x4e;
- buf[10]=0xec;
- ret=i2c_master_send(c,buf+5,6);
-
- buf[12]=13; // Index register 13
- buf[13]=0x32;
- ret=i2c_master_send(c,buf+12,2);
-
- // Adjust XOGC (register 7), wait for XOK
- xogc=7;
- do {
- dprintk("mt2032: xogc = 0x%02x\n",xogc&0x07);
- mdelay(10);
- buf[0]=0x0e;
- i2c_master_send(c,buf,1);
- i2c_master_recv(c,buf,1);
- xok=buf[0]&0x01;
- dprintk("mt2032: xok = 0x%02x\n",xok);
- if (xok == 1) break;
-
- xogc--;
- dprintk("mt2032: xogc = 0x%02x\n",xogc&0x07);
- if (xogc == 3) {
- xogc=4; // min. 4 per spec
- break;
- }
- buf[0]=0x07;
- buf[1]=0x88 + xogc;
- ret=i2c_master_send(c,buf,2);
- if (ret!=2)
- printk("mt2032_init failed with %d\n",ret);
- } while (xok != 1 );
- t->xogc=xogc;
-
- t->tv_freq = mt2032_set_tv_freq;
- t->radio_freq = mt2032_set_radio_freq;
- return(1);
-}
-
-static void mt2050_set_antenna(struct i2c_client *c, unsigned char antenna)
-{
- unsigned char buf[2];
- int ret;
-
- buf[0] = 6;
- buf[1] = antenna ? 0x11 : 0x10;
- ret=i2c_master_send(c,buf,2);
- dprintk("mt2050: enabled antenna connector %d\n", antenna);
-}
-
-static void mt2050_set_if_freq(struct i2c_client *c,unsigned int freq, unsigned int if2)
-{
- unsigned int if1=1218*1000*1000;
- unsigned int f_lo1,f_lo2,lo1,lo2,f_lo1_modulo,f_lo2_modulo,num1,num2,div1a,div1b,div2a,div2b;
- int ret;
- unsigned char buf[6];
-
- dprintk("mt2050_set_if_freq freq=%d if1=%d if2=%d\n",
- freq,if1,if2);
-
- f_lo1=freq+if1;
- f_lo1=(f_lo1/1000000)*1000000;
-
- f_lo2=f_lo1-freq-if2;
- f_lo2=(f_lo2/50000)*50000;
-
- lo1=f_lo1/4000000;
- lo2=f_lo2/4000000;
-
- f_lo1_modulo= f_lo1-(lo1*4000000);
- f_lo2_modulo= f_lo2-(lo2*4000000);
-
- num1=4*f_lo1_modulo/4000000;
- num2=4096*(f_lo2_modulo/1000)/4000;
-
- // todo spurchecks
-
- div1a=(lo1/12)-1;
- div1b=lo1-(div1a+1)*12;
-
- div2a=(lo2/8)-1;
- div2b=lo2-(div2a+1)*8;
-
- if (debug > 1) {
- printk("lo1 lo2 = %d %d\n", lo1, lo2);
- printk("num1 num2 div1a div1b div2a div2b= %x %x %x %x %x %x\n",num1,num2,div1a,div1b,div2a,div2b);
- }
-
- buf[0]=1;
- buf[1]= 4*div1b + num1;
- if(freq<275*1000*1000) buf[1] = buf[1]|0x80;
-
- buf[2]=div1a;
- buf[3]=32*div2b + num2/256;
- buf[4]=num2-(num2/256)*256;
- buf[5]=div2a;
- if(num2!=0) buf[5]=buf[5]|0x40;
-
- if (debug > 1) {
- int i;
- printk("bufs is: ");
- for(i=0;i<6;i++)
- printk("%x ",buf[i]);
- printk("\n");
- }
-
- ret=i2c_master_send(c,buf,6);
- if (ret!=6)
- printk("mt2050_set_if_freq failed with %d\n",ret);
-}
-
-static void mt2050_set_tv_freq(struct i2c_client *c, unsigned int freq)
-{
- struct tuner *t = i2c_get_clientdata(c);
- unsigned int if2;
-
- if (t->std & V4L2_STD_525_60) {
- // NTSC
- if2 = 45750*1000;
- } else {
- // PAL
- if2 = 38900*1000;
- }
- if (V4L2_TUNER_DIGITAL_TV == t->mode) {
- // testing for DVB ...
- if2 = 36150*1000;
- }
- mt2050_set_if_freq(c, freq*62500, if2);
- mt2050_set_antenna(c, tv_antenna);
-}
-
-static void mt2050_set_radio_freq(struct i2c_client *c, unsigned int freq)
-{
- struct tuner *t = i2c_get_clientdata(c);
- int if2 = t->radio_if2;
-
- mt2050_set_if_freq(c, freq*62500, if2);
- mt2050_set_antenna(c, radio_antenna);
-}
-
-static int mt2050_init(struct i2c_client *c)
-{
- struct tuner *t = i2c_get_clientdata(c);
- unsigned char buf[2];
- int ret;
-
- buf[0]=6;
- buf[1]=0x10;
- ret=i2c_master_send(c,buf,2); // power
-
- buf[0]=0x0f;
- buf[1]=0x0f;
- ret=i2c_master_send(c,buf,2); // m1lo
-
- buf[0]=0x0d;
- ret=i2c_master_send(c,buf,1);
- i2c_master_recv(c,buf,1);
-
- dprintk("mt2050: sro is %x\n",buf[0]);
- t->tv_freq = mt2050_set_tv_freq;
- t->radio_freq = mt2050_set_radio_freq;
- return 0;
-}
-
-static int microtune_init(struct i2c_client *c)
-{
- struct tuner *t = i2c_get_clientdata(c);
- char *name;
- unsigned char buf[21];
- int company_code;
-
- memset(buf,0,sizeof(buf));
- t->tv_freq = NULL;
- t->radio_freq = NULL;
- name = "unknown";
-
- i2c_master_send(c,buf,1);
- i2c_master_recv(c,buf,21);
- if(debug) {
- int i;
- printk(KERN_DEBUG "tuner: MT2032 hexdump:\n");
- for(i=0;i<21;i++) {
- printk(" %02x",buf[i]);
- if(((i+1)%8)==0) printk(" ");
- if(((i+1)%16)==0) printk("\n ");
- }
- printk("\n ");
- }
- company_code = buf[0x11] << 8 | buf[0x12];
- printk("tuner: microtune: companycode=%04x part=%02x rev=%02x\n",
- company_code,buf[0x13],buf[0x14]);
-
-#if 0
- /* seems to cause more problems than it solves ... */
- switch (company_code) {
- case 0x30bf:
- case 0x3cbf:
- case 0x3dbf:
- case 0x4d54:
- case 0x8e81:
- case 0x8e91:
- /* ok (?) */
- break;
- default:
- printk("tuner: microtune: unknown companycode\n");
- return 0;
- }
-#endif
-
- if (buf[0x13] < ARRAY_SIZE(microtune_part) &&
- NULL != microtune_part[buf[0x13]])
- name = microtune_part[buf[0x13]];
- switch (buf[0x13]) {
- case MT2032:
- mt2032_init(c);
- break;
- case MT2050:
- mt2050_init(c);
- break;
- default:
- printk("tuner: microtune %s found, not (yet?) supported, sorry :-/\n",
- name);
- return 0;
- }
- printk("tuner: microtune %s found, OK\n",name);
- return 0;
-}
-
-/* ---------------------------------------------------------------------- */
-
-static void default_set_tv_freq(struct i2c_client *c, unsigned int freq)
-{
- struct tuner *t = i2c_get_clientdata(c);
- u8 config;
- u16 div;
- struct tunertype *tun;
- unsigned char buffer[4];
- int rc;
-
- tun = &tuners[t->type];
- if (freq < tun->thresh1) {
- config = tun->VHF_L;
- dprintk("tv: VHF lowrange\n");
- } else if (freq < tun->thresh2) {
- config = tun->VHF_H;
- dprintk("tv: VHF high range\n");
- } else {
- config = tun->UHF;
- dprintk("tv: UHF range\n");
- }
-
-
- /* tv norm specific stuff for multi-norm tuners */
- switch (t->type) {
- case TUNER_PHILIPS_SECAM: // FI1216MF
- /* 0x01 -> ??? no change ??? */
- /* 0x02 -> PAL BDGHI / SECAM L */
- /* 0x04 -> ??? PAL others / SECAM others ??? */
- config &= ~0x02;
- if (t->std & V4L2_STD_SECAM)
- config |= 0x02;
- break;
-
- case TUNER_TEMIC_4046FM5:
- config &= ~0x0f;
-
- if (t->std & V4L2_STD_PAL_BG) {
- config |= TEMIC_SET_PAL_BG;
-
- } else if (t->std & V4L2_STD_PAL_I) {
- config |= TEMIC_SET_PAL_I;
-
- } else if (t->std & V4L2_STD_PAL_DK) {
- config |= TEMIC_SET_PAL_DK;
-
- } else if (t->std & V4L2_STD_SECAM_L) {
- config |= TEMIC_SET_PAL_L;
-
- }
- break;
-
- case TUNER_PHILIPS_FQ1216ME:
- config &= ~0x0f;
-
- if (t->std & (V4L2_STD_PAL_BG|V4L2_STD_PAL_DK)) {
- config |= PHILIPS_SET_PAL_BGDK;
-
- } else if (t->std & V4L2_STD_PAL_I) {
- config |= PHILIPS_SET_PAL_I;
-
- } else if (t->std & V4L2_STD_SECAM_L) {
- config |= PHILIPS_SET_PAL_L;
-
- }
- break;
-
- case TUNER_PHILIPS_ATSC:
- /* 0x00 -> ATSC antenna input 1 */
- /* 0x01 -> ATSC antenna input 2 */
- /* 0x02 -> NTSC antenna input 1 */
- /* 0x03 -> NTSC antenna input 2 */
- config &= ~0x03;
- if (!(t->std & V4L2_STD_ATSC))
- config |= 2;
- /* FIXME: input */
- break;
-
- case TUNER_MICROTUNE_4042FI5:
- /* Set the charge pump for fast tuning */
- tun->config |= 0x40;
- 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;
- 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[3] = config;
- }
- dprintk("tuner: tv 0x%02x 0x%02x 0x%02x 0x%02x\n",
- buffer[0],buffer[1],buffer[2],buffer[3]);
-
- if (4 != (rc = i2c_master_send(c,buffer,4)))
- printk("tuner: i2c i/o error: rc == %d (should be 4)\n",rc);
-
- if (t->type == TUNER_MICROTUNE_4042FI5) {
- // FIXME - this may also work for other tuners
- unsigned long timeout = jiffies + msecs_to_jiffies(1);
- u8 status_byte = 0;
-
- /* Wait until the PLL locks */
- for (;;) {
- if (time_after(jiffies,timeout))
- return;
- if (1 != (rc = i2c_master_recv(c,&status_byte,1))) {
- dprintk("tuner: i2c i/o read error: rc == %d (should be 1)\n",rc);
- break;
- }
- /* bit 6 is PLL locked indicator */
- if (status_byte & 0x40)
- break;
- udelay(10);
- }
-
- /* Set the charge pump for optimized phase noise figure */
- tun->config &= ~0x40;
- buffer[0] = (div>>8) & 0x7f;
- buffer[1] = div & 0xff;
- buffer[2] = tun->config;
- buffer[3] = config;
- dprintk("tuner: tv 0x%02x 0x%02x 0x%02x 0x%02x\n",
- buffer[0],buffer[1],buffer[2],buffer[3]);
-
- if (4 != (rc = i2c_master_send(c,buffer,4)))
- dprintk("tuner: i2c i/o error: rc == %d (should be 4)\n",rc);
- }
-}
-
-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;
-
- tun=&tuners[t->type];
- div = freq + (int)(16*10.7);
- buffer[2] = tun->config;
-
- switch (t->type) {
- case TUNER_PHILIPS_FM1216ME_MK3:
- case TUNER_PHILIPS_FM1236_MK3:
- buffer[3] = 0x19;
- break;
- case TUNER_PHILIPS_FM1256_IH3:
- div = (20 * freq)/16 + 333 * 2;
- buffer[2] = 0x80;
- buffer[3] = 0x19;
- break;
- case TUNER_LG_PAL_FM:
- buffer[3] = 0xa5;
- break;
- default:
- buffer[3] = 0xa4;
- break;
- }
- buffer[0] = (div>>8) & 0x7f;
- buffer[1] = div & 0xff;
-
- dprintk("tuner: radio 0x%02x 0x%02x 0x%02x 0x%02x\n",
- buffer[0],buffer[1],buffer[2],buffer[3]);
-
- if (4 != (rc = i2c_master_send(c,buffer,4)))
- printk("tuner: i2c i/o error: rc == %d (should be 4)\n",rc);
-}
-
-/* ---------------------------------------------------------------------- */
-
-// Set tuner frequency, freq in Units of 62.5kHz = 1/16MHz
-static void set_tv_freq(struct i2c_client *c, unsigned int freq)
-{
- struct tuner *t = i2c_get_clientdata(c);
-
- if (t->type == UNSET) {
- printk("tuner: tuner type not set\n");
- return;
- }
- if (NULL == t->tv_freq) {
- printk("tuner: Huh? tv_set is NULL?\n");
- return;
- }
- if (freq < tv_range[0]*16 || freq > tv_range[1]*16) {
- /* FIXME: better do that chip-specific, but
- right now we don't have that in the config
- struct and this way is still better than no
- check at all */
- printk("tuner: TV freq (%d.%02d) out of range (%d-%d)\n",
- freq/16,freq%16*100/16,tv_range[0],tv_range[1]);
- return;
- }
- t->tv_freq(c,freq);
-}
-
-static void set_radio_freq(struct i2c_client *c, unsigned int freq)
-{
- struct tuner *t = i2c_get_clientdata(c);
-
- if (t->type == UNSET) {
- printk("tuner: tuner type not set\n");
- return;
- }
- if (NULL == t->radio_freq) {
- printk("tuner: no radio tuning for this one, sorry.\n");
- return;
- }
- if (freq < radio_range[0]*16 || freq > radio_range[1]*16) {
- printk("tuner: radio freq (%d.%02d) out of range (%d-%d)\n",
- freq/16,freq%16*100/16,
- radio_range[0],radio_range[1]);
- return;
- }
- t->radio_freq(c,freq);
-}
-
-static void set_freq(struct i2c_client *c, unsigned long freq)
-{
- struct tuner *t = i2c_get_clientdata(c);
-
- switch (t->mode) {
- case V4L2_TUNER_RADIO:
- dprintk("tuner: radio freq set to %lu.%02lu\n",
- freq/16,freq%16*100/16);
- set_radio_freq(c,freq);
- break;
- case V4L2_TUNER_ANALOG_TV:
- case V4L2_TUNER_DIGITAL_TV:
- dprintk("tuner: tv freq set to %lu.%02lu\n",
- freq/16,freq%16*100/16);
- set_tv_freq(c, freq);
- break;
- }
- t->freq = freq;
-}
-
-static void set_type(struct i2c_client *c, unsigned int type, char *source)
-{
- struct tuner *t = i2c_get_clientdata(c);
-
- if (t->type != UNSET && t->type != TUNER_ABSENT) {
- if (t->type != type)
- printk("tuner: type already set to %d, "
- "ignoring request for %d\n", t->type, type);
- return;
- }
- if (type >= TUNERS)
- return;
-
- t->type = type;
- printk("tuner: type set to %d (%s) by %s\n",
- t->type,tuners[t->type].name, source);
- strlcpy(c->name, tuners[t->type].name, sizeof(c->name));
-
- switch (t->type) {
- case TUNER_MT2032:
- microtune_init(c);
- break;
- default:
- t->tv_freq = default_set_tv_freq;
- t->radio_freq = default_set_radio_freq;
- break;
- }
-}
-
-static char pal[] = "-";
-module_param_string(pal, pal, 0644, sizeof(pal));
-
-static int tuner_fixup_std(struct tuner *t)
-{
- if ((t->std & V4L2_STD_PAL) == V4L2_STD_PAL) {
- /* get more precise norm info from insmod option */
- switch (pal[0]) {
- case 'b':
- case 'B':
- case 'g':
- case 'G':
- dprintk("insmod fixup: PAL => PAL-BG\n");
- t->std = V4L2_STD_PAL_BG;
- break;
- case 'i':
- case 'I':
- dprintk("insmod fixup: PAL => PAL-I\n");
- t->std = V4L2_STD_PAL_I;
- break;
- case 'd':
- case 'D':
- case 'k':
- case 'K':
- dprintk("insmod fixup: PAL => PAL-DK\n");
- t->std = V4L2_STD_PAL_DK;
- break;
- }
- }
- return 0;
-}
-
-/* ---------------------------------------------------------------------- */
-
-static int tuner_attach(struct i2c_adapter *adap, int addr, int kind)
-{
- struct tuner *t;
- struct i2c_client *client;
-
- if (this_adap > 0)
- return -1;
- this_adap++;
-
- client_template.adapter = adap;
- client_template.addr = addr;
-
- printk("tuner: chip found at addr 0x%x i2c-bus %s\n",
- addr<<1, adap->name);
-
- if (NULL == (client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL)))
- return -ENOMEM;
- memcpy(client,&client_template,sizeof(struct i2c_client));
- t = kmalloc(sizeof(struct tuner),GFP_KERNEL);
- if (NULL == t) {
- kfree(client);
- return -ENOMEM;
- }
- memset(t,0,sizeof(struct tuner));
- i2c_set_clientdata(client, t);
- t->type = UNSET;
- t->radio_if2 = 10700*1000; // 10.7MHz - FM radio
-
- i2c_attach_client(client);
- if (type < TUNERS) {
- set_type(client, type, "insmod option");
- printk("tuner: The type=<n> insmod option will go away soon.\n");
- printk("tuner: Please use the tuner=<n> option provided by\n");
- printk("tuner: tv aard core driver (bttv, saa7134, ...) instead.\n");
- }
- return 0;
-}
-
-static int tuner_probe(struct i2c_adapter *adap)
-{
- if (0 != addr) {
- normal_i2c_range[0] = addr;
- normal_i2c_range[1] = addr;
- }
- this_adap = 0;
-
-#ifdef I2C_CLASS_TV_ANALOG
- if (adap->class & I2C_CLASS_TV_ANALOG)
- return i2c_probe(adap, &addr_data, tuner_attach);
-#else
- switch (adap->id) {
- case I2C_ALGO_BIT | I2C_HW_SMBUS_VOODOO3:
- case I2C_ALGO_BIT | I2C_HW_B_BT848:
- case I2C_ALGO_BIT | I2C_HW_B_RIVA:
- case I2C_ALGO_SAA7134:
- case I2C_ALGO_SAA7146:
- return i2c_probe(adap, &addr_data, tuner_attach);
- break;
- }
-#endif
- return 0;
-}
-
-static int tuner_detach(struct i2c_client *client)
-{
- struct tuner *t = i2c_get_clientdata(client);
-
- i2c_detach_client(client);
- kfree(t);
- kfree(client);
- return 0;
-}
-
-#define SWITCH_V4L2 if (!t->using_v4l2 && debug) \
- printk("tuner: switching to v4l2\n"); \
- t->using_v4l2 = 1;
-#define CHECK_V4L2 if (t->using_v4l2) { if (debug) \
- printk("tuner: ignore v4l1 call\n"); \
- return 0; }
-
-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;
-
- switch (cmd) {
-
- /* --- configuration --- */
- case TUNER_SET_TYPE:
- set_type(client,*iarg,client->adapter->name);
- break;
- case AUDC_SET_RADIO:
- if (V4L2_TUNER_RADIO != t->mode) {
- set_tv_freq(client,400 * 16);
- t->mode = V4L2_TUNER_RADIO;
- }
- break;
- case AUDC_CONFIG_PINNACLE:
- switch (*iarg) {
- case 2:
- dprintk("tuner: pinnacle pal\n");
- t->radio_if2 = 33300 * 1000;
- break;
- case 3:
- dprintk("tuner: pinnacle ntsc\n");
- t->radio_if2 = 41300 * 1000;
- break;
- }
- break;
-
- /* --- v4l ioctls --- */
- /* take care: bttv does userspace copying, we'll get a
- kernel pointer here... */
- case VIDIOCSCHAN:
- {
- static const v4l2_std_id map[] = {
- [ VIDEO_MODE_PAL ] = V4L2_STD_PAL,
- [ VIDEO_MODE_NTSC ] = V4L2_STD_NTSC_M,
- [ VIDEO_MODE_SECAM ] = V4L2_STD_SECAM,
- [ 4 /* bttv */ ] = V4L2_STD_PAL_M,
- [ 5 /* bttv */ ] = V4L2_STD_PAL_N,
- [ 6 /* bttv */ ] = V4L2_STD_NTSC_M_JP,
- };
- struct video_channel *vc = arg;
-
- CHECK_V4L2;
- t->mode = V4L2_TUNER_ANALOG_TV;
- if (vc->norm < ARRAY_SIZE(map))
- t->std = map[vc->norm];
- tuner_fixup_std(t);
- if (t->freq)
- set_tv_freq(client,t->freq);
- return 0;
- }
- case VIDIOCSFREQ:
- {
- unsigned long *v = arg;
-
- CHECK_V4L2;
- set_freq(client,*v);
- return 0;
- }
- case VIDIOCGTUNER:
- {
- struct video_tuner *vt = arg;
-
- CHECK_V4L2;
- if (V4L2_TUNER_RADIO == t->mode)
- vt->signal = tuner_signal(client);
- return 0;
- }
- case VIDIOCGAUDIO:
- {
- struct video_audio *va = arg;
-
- CHECK_V4L2;
- if (V4L2_TUNER_RADIO == t->mode)
- va->mode = (tuner_stereo(client) ? VIDEO_SOUND_STEREO : VIDEO_SOUND_MONO);
- return 0;
- }
-
- case VIDIOC_S_STD:
- {
- v4l2_std_id *id = arg;
-
- SWITCH_V4L2;
- t->mode = V4L2_TUNER_ANALOG_TV;
- t->std = *id;
- tuner_fixup_std(t);
- if (t->freq)
- set_freq(client,t->freq);
- break;
- }
- case VIDIOC_S_FREQUENCY:
- {
- struct v4l2_frequency *f = arg;
-
- SWITCH_V4L2;
- if (V4L2_TUNER_RADIO == f->type &&
- V4L2_TUNER_RADIO != t->mode)
- set_tv_freq(client,400*16);
- t->mode = f->type;
- t->freq = f->frequency;
- set_freq(client,t->freq);
- break;
- }
- case VIDIOC_G_TUNER:
- {
- struct v4l2_tuner *tuner = arg;
-
- SWITCH_V4L2;
- if (V4L2_TUNER_RADIO == t->mode)
- tuner->signal = tuner_signal(client);
- break;
- }
- default:
- /* nothing */
- break;
- }
-
- return 0;
-}
-
-static int tuner_suspend(struct device * dev, u32 state, u32 level)
-{
- dprintk("tuner: suspend\n");
- /* FIXME: power down ??? */
- return 0;
-}
-
-static int tuner_resume(struct device * dev, u32 level)
-{
- struct i2c_client *c = container_of(dev, struct i2c_client, dev);
- struct tuner *t = i2c_get_clientdata(c);
-
- dprintk("tuner: resume\n");
- if (t->freq)
- set_freq(c,t->freq);
- return 0;
-}
-
-/* ----------------------------------------------------------------------- */
-
-static struct i2c_driver driver = {
- .owner = THIS_MODULE,
- .name = "i2c TV tuner driver",
- .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,
- },
-};
-static struct i2c_client client_template =
-{
- I2C_DEVNAME("(tuner unset)"),
- .flags = I2C_CLIENT_ALLOW_USE,
- .driver = &driver,
-};
-
-static int __init tuner_init_module(void)
-{
- return i2c_add_driver(&driver);
-}
-
-static void __exit tuner_cleanup_module(void)
-{
- i2c_del_driver(&driver);
-}
-
-module_init(tuner_init_module);
-module_exit(tuner_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/tvaudio.c b/drivers/media/video/tvaudio.c
index 540a6b1461f7f..065eb4007b1d1 100644
--- a/drivers/media/video/tvaudio.c
+++ b/drivers/media/video/tvaudio.c
@@ -286,6 +286,7 @@ static int chip_thread(void *data)
schedule();
}
remove_wait_queue(&chip->wq, &wait);
+ try_to_freeze(PF_FREEZE);
if (chip->done || signal_pending(current))
break;
dprintk("%s: thread wakeup\n", i2c_clientname(&chip->c));
diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c
index 21b844a6c13f7..e1443a0937e3c 100644
--- a/drivers/media/video/tveeprom.c
+++ b/drivers/media/video/tveeprom.c
@@ -30,10 +30,12 @@
#include <linux/module.h>
+#include <linux/moduleparam.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/types.h>
+#include <linux/videodev.h>
#include <linux/i2c.h>
#include <media/tuner.h>
@@ -190,11 +192,13 @@ hauppauge_tuner[] =
{ TUNER_ABSENT, "TCL MFPE05 2"},
/* 90-99 */
{ TUNER_ABSENT, "LG TALN H202T"},
- { TUNER_ABSENT, "Philips FQ1216AME MK4"},
- { TUNER_ABSENT, "Philips FQ1236A MK4"},
+ { TUNER_PHILIPS_FQ1216AME_MK4, "Philips FQ1216AME MK4"},
+ { TUNER_PHILIPS_FQ1236A_MK4, "Philips FQ1236A MK4"},
{ TUNER_ABSENT, "Philips FQ1286A MK4"},
{ TUNER_ABSENT, "Philips FQ1216ME MK5"},
{ TUNER_ABSENT, "Philips FQ1236 MK5"},
+ { TUNER_ABSENT, "Unspecified"},
+ { TUNER_LG_PAL_TAPE, "LG PAL (TAPE Series)"},
};
static char *sndtype[] = {
@@ -240,6 +244,7 @@ static int hasRadioTuner(int tunerType)
case 61: //PNPEnv_TUNER_TAPE_M001D_MK3:
case 78: //PNPEnv_TUNER_TDA8275C1_8290_FM:
case 89: //PNPEnv_TUNER_TCL_MFPE05_2:
+ case 92: //PNPEnv_TUNER_PHILIPS_FQ1236A_MK4:
return 1;
}
return 0;
@@ -255,8 +260,8 @@ void tveeprom_hauppauge_analog(struct tveeprom *tvee, unsigned char *eeprom_data
** if packet[0] & f8 == f8, then EOD and packet[1] == checksum
**
** In our (ivtv) case we're interested in the following:
- ** tuner type: tag [00].05 or [0a].01 (index into hauppauge_tuners)
- ** tuner fmts: tag [00].04 or [0a].00 (bitmask index into hauppauge_fmts)
+ ** tuner type: tag [00].05 or [0a].01 (index into hauppauge_tuner)
+ ** tuner fmts: tag [00].04 or [0a].00 (bitmask index into hauppauge_tuner_fmt)
** radio: tag [00].{last} or [0e].00 (bitmask. bit2=FM)
** audio proc: tag [02].01 or [05].00 (lower nibble indexes lut?)
@@ -268,11 +273,11 @@ void tveeprom_hauppauge_analog(struct tveeprom *tvee, unsigned char *eeprom_data
** # of inputs/outputs ???
*/
- int i, j, len, done, tag, tuner = 0, t_format = 0;
+ int i, j, len, done, beenhere, tag, tuner = 0, t_format = 0;
char *t_name = NULL, *t_fmt_name = NULL;
dprintk(1, "%s\n",__FUNCTION__);
- tvee->revision = done = len = 0;
+ tvee->revision = done = len = beenhere = 0;
for (i = 0; !done && i < 256; i += len) {
dprintk(2, "processing pos = %02x (%02x, %02x)\n",
i, eeprom_data[i], eeprom_data[i + 1]);
@@ -341,9 +346,14 @@ void tveeprom_hauppauge_analog(struct tveeprom *tvee, unsigned char *eeprom_data
(eeprom_data[i+7] << 16);
break;
case 0x0a:
- tuner = eeprom_data[i+2];
- t_format = eeprom_data[i+1];
- break;
+ if(beenhere == 0) {
+ tuner = eeprom_data[i+2];
+ t_format = eeprom_data[i+1];
+ beenhere = 1;
+ break;
+ } else {
+ break;
+ }
case 0x0e:
tvee->has_radio = eeprom_data[i+1];
break;
diff --git a/drivers/media/video/video-buf.c b/drivers/media/video/video-buf.c
index 5bac907dc9deb..5afdc78526103 100644
--- a/drivers/media/video/video-buf.c
+++ b/drivers/media/video/video-buf.c
@@ -1,5 +1,5 @@
/*
- * $Id: video-buf.c,v 1.17 2004/12/10 12:33:40 kraxel Exp $
+ * $Id: video-buf.c,v 1.18 2005/02/24 13:32:30 kraxel Exp $
*
* generic helper functions for video4linux capture buffers, to handle
* memory management and PCI DMA. Right now bttv + saa7134 use it.
@@ -217,9 +217,18 @@ int videobuf_dma_pci_map(struct pci_dev *dev, struct videobuf_dmabuf *dma)
return -ENOMEM;
}
- if (!dma->bus_addr)
+ if (!dma->bus_addr) {
dma->sglen = pci_map_sg(dev,dma->sglist,dma->nr_pages,
dma->direction);
+ if (0 == dma->sglen) {
+ printk(KERN_WARNING
+ "%s: pci_map_sg failed\n",__FUNCTION__);
+ kfree(dma->sglist);
+ dma->sglist = NULL;
+ dma->sglen = 0;
+ return -EIO;
+ }
+ }
return 0;
}
diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c
index 9d4c74f25e869..06df15f75de94 100644
--- a/drivers/media/video/videodev.c
+++ b/drivers/media/video/videodev.c
@@ -46,15 +46,7 @@ static ssize_t show_name(struct class_device *cd, char *buf)
return sprintf(buf,"%.*s\n",(int)sizeof(vfd->name),vfd->name);
}
-static ssize_t show_dev(struct class_device *cd, char *buf)
-{
- struct video_device *vfd = container_of(cd, struct video_device, class_dev);
- dev_t dev = MKDEV(VIDEO_MAJOR, vfd->minor);
- return print_dev_t(buf,dev);
-}
-
static CLASS_DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
-static CLASS_DEVICE_ATTR(dev, S_IRUGO, show_dev, NULL);
struct video_device *video_device_alloc(void)
{
@@ -347,12 +339,11 @@ 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);
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_create_file(&vfd->class_dev,
- &class_device_attr_dev);
#if 1 /* needed until all drivers are fixed */
if (!vfd->release)
diff --git a/drivers/media/video/vpx3220.c b/drivers/media/video/vpx3220.c
index 917d0d2760b3a..0fd6c9a709179 100644
--- a/drivers/media/video/vpx3220.c
+++ b/drivers/media/video/vpx3220.c
@@ -587,7 +587,6 @@ static struct i2c_client_address_data addr_data = {
.force = force
};
-static int vpx3220_i2c_id = 0;
static struct i2c_driver vpx3220_i2c_driver;
static int
@@ -634,7 +633,6 @@ vpx3220_detect_client (struct i2c_adapter *adapter,
client->adapter = adapter;
client->driver = &vpx3220_i2c_driver;
client->flags = I2C_CLIENT_ALLOW_USE;
- client->id = vpx3220_i2c_id++;
/* Check for manufacture ID and part number */
if (kind < 0) {
@@ -655,16 +653,16 @@ vpx3220_detect_client (struct i2c_adapter *adapter,
vpx3220_read(client, 0x01);
switch (pn) {
case 0x4680:
- snprintf(I2C_NAME(client), sizeof(I2C_NAME(client)) - 1,
- "vpx3220a[%d]", client->id);
+ strlcpy(I2C_NAME(client), "vpx3220a",
+ sizeof(I2C_NAME(client)));
break;
case 0x4260:
- snprintf(I2C_NAME(client), sizeof(I2C_NAME(client)) - 1,
- "vpx3216b[%d]", client->id);
+ strlcpy(I2C_NAME(client), "vpx3216b",
+ sizeof(I2C_NAME(client)));
break;
case 0x4280:
- snprintf(I2C_NAME(client), sizeof(I2C_NAME(client)) - 1,
- "vpx3214c[%d]", client->id);
+ strlcpy(I2C_NAME(client), "vpx3214c",
+ sizeof(I2C_NAME(client)));
break;
default:
dprintk(1,
@@ -675,9 +673,8 @@ vpx3220_detect_client (struct i2c_adapter *adapter,
return 0;
}
} else {
- snprintf(I2C_NAME(client), sizeof(I2C_NAME(client)) - 1,
- "forced vpx32xx[%d]",
- client->id);
+ strlcpy(I2C_NAME(client), "forced vpx32xx",
+ sizeof(I2C_NAME(client)));
}
decoder = kmalloc(sizeof(struct vpx3220), GFP_KERNEL);
diff --git a/drivers/media/video/zoran_card.c b/drivers/media/video/zoran_card.c
index 227ba2fb3f368..25743085b2d5a 100644
--- a/drivers/media/video/zoran_card.c
+++ b/drivers/media/video/zoran_card.c
@@ -41,6 +41,7 @@
#include <linux/spinlock.h>
#include <linux/sem.h>
#include <linux/kmod.h>
+#include <linux/wait.h>
#include <linux/pci.h>
#include <linux/interrupt.h>
@@ -968,6 +969,7 @@ zoran_open_init_params (struct zoran *zr)
static void __devinit
test_interrupts (struct zoran *zr)
{
+ DEFINE_WAIT(wait);
int timeout, icr;
clear_interrupt_counters(zr);
@@ -975,7 +977,9 @@ test_interrupts (struct zoran *zr)
zr->testing = 1;
icr = btread(ZR36057_ICR);
btwrite(0x78000000 | ZR36057_ICR_IntPinEn, ZR36057_ICR);
- timeout = interruptible_sleep_on_timeout(&zr->test_q, 1 * HZ);
+ prepare_to_wait(&zr->test_q, &wait, TASK_INTERRUPTIBLE);
+ timeout = schedule_timeout(HZ);
+ finish_wait(&zr->test_q, &wait);
btwrite(0, ZR36057_ICR);
btwrite(0x78000000, ZR36057_ISR);
zr->testing = 0;
diff --git a/drivers/media/video/zoran_device.c b/drivers/media/video/zoran_device.c
index 5409db41a58ee..4e15afdec4c9d 100644
--- a/drivers/media/video/zoran_device.c
+++ b/drivers/media/video/zoran_device.c
@@ -46,6 +46,7 @@
#include <linux/video_decoder.h>
#include <linux/video_encoder.h>
#include <linux/delay.h>
+#include <linux/wait.h>
#include <asm/io.h>
@@ -696,11 +697,10 @@ wait_grab_pending (struct zoran *zr)
if (!zr->v4l_memgrab_active)
return 0;
- while (zr->v4l_pend_tail != zr->v4l_pend_head) {
- interruptible_sleep_on(&zr->v4l_capq);
- if (signal_pending(current))
- return -ERESTARTSYS;
- }
+ wait_event_interruptible(zr->v4l_capq,
+ (zr->v4l_pend_tail == zr->v4l_pend_head));
+ if (signal_pending(current))
+ return -ERESTARTSYS;
spin_lock_irqsave(&zr->spinlock, flags);
zr36057_set_memgrab(zr, 0);
diff --git a/drivers/media/video/zoran_driver.c b/drivers/media/video/zoran_driver.c
index 8af43a633663f..ba838a42ec806 100644
--- a/drivers/media/video/zoran_driver.c
+++ b/drivers/media/video/zoran_driver.c
@@ -52,6 +52,7 @@
#include <linux/slab.h>
#include <linux/pci.h>
#include <linux/vmalloc.h>
+#include <linux/wait.h>
#include <linux/byteorder/generic.h>
#include <linux/interrupt.h>
@@ -918,12 +919,12 @@ v4l_sync (struct file *file,
}
/* wait on this buffer to get ready */
- while (zr->v4l_buffers.buffer[frame].state == BUZ_STATE_PEND) {
- if (!interruptible_sleep_on_timeout(&zr->v4l_capq, 10 * HZ))
- return -ETIME;
- else if (signal_pending(current))
- return -ERESTARTSYS;
- }
+ if (!wait_event_interruptible_timeout(zr->v4l_capq,
+ (zr->v4l_buffers.buffer[frame].state != BUZ_STATE_PEND),
+ 10*HZ))
+ return -ETIME;
+ if (signal_pending(current))
+ return -ERESTARTSYS;
/* buffer should now be in BUZ_STATE_DONE */
if (zr->v4l_buffers.buffer[frame].state != BUZ_STATE_DONE)
@@ -1107,7 +1108,7 @@ jpg_sync (struct file *file,
struct zoran_fh *fh = file->private_data;
struct zoran *zr = fh->zr;
unsigned long flags;
- int frame, timeout;
+ int frame;
if (fh->jpg_buffers.active == ZORAN_FREE) {
dprintk(1,
@@ -1124,29 +1125,26 @@ jpg_sync (struct file *file,
ZR_DEVNAME(zr));
return -EINVAL;
}
- while (zr->jpg_que_tail == zr->jpg_dma_tail) {
- if (zr->jpg_dma_tail == zr->jpg_dma_head)
- break;
+ if (!wait_event_interruptible_timeout(zr->jpg_capq,
+ (zr->jpg_que_tail != zr->jpg_dma_tail ||
+ zr->jpg_dma_tail == zr->jpg_dma_head),
+ 10*HZ)) {
+ int isr;
- timeout =
- interruptible_sleep_on_timeout(&zr->jpg_capq, 10 * HZ);
- if (!timeout) {
- int isr;
-
- btand(~ZR36057_JMC_Go_en, ZR36057_JMC);
- udelay(1);
- zr->codec->control(zr->codec, CODEC_G_STATUS,
+ btand(~ZR36057_JMC_Go_en, ZR36057_JMC);
+ udelay(1);
+ zr->codec->control(zr->codec, CODEC_G_STATUS,
sizeof(isr), &isr);
- dprintk(1,
- KERN_ERR
- "%s: jpg_sync() - timeout: codec isr=0x%02x\n",
- ZR_DEVNAME(zr), isr);
+ dprintk(1,
+ KERN_ERR
+ "%s: jpg_sync() - timeout: codec isr=0x%02x\n",
+ ZR_DEVNAME(zr), isr);
- return -ETIME;
+ return -ETIME;
- } else if (signal_pending(current))
- return -ERESTARTSYS;
}
+ if (signal_pending(current))
+ return -ERESTARTSYS;
spin_lock_irqsave(&zr->spinlock, flags);
@@ -2694,7 +2692,7 @@ zoran_do_ioctl (struct inode *inode,
strncpy(cap->card, ZR_DEVNAME(zr), sizeof(cap->card));
strncpy(cap->driver, "zoran", sizeof(cap->driver));
snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s",
- zr->pci_dev->slot_name);
+ pci_name(zr->pci_dev));
cap->version =
KERNEL_VERSION(MAJOR_VERSION, MINOR_VERSION,
RELEASE_VERSION);
@@ -3761,7 +3759,7 @@ zoran_do_ioctl (struct inode *inode,
v4l2_std_id *std = arg;
dprintk(3, KERN_DEBUG "%s: VIDIOC_S_STD - norm=0x%llx\n",
- ZR_DEVNAME(zr), *std);
+ ZR_DEVNAME(zr), (unsigned long long)*std);
if (*std == V4L2_STD_PAL)
norm = VIDEO_MODE_PAL;
@@ -3775,7 +3773,7 @@ zoran_do_ioctl (struct inode *inode,
dprintk(1,
KERN_ERR
"%s: VIDIOC_S_STD - invalid norm 0x%llx\n",
- ZR_DEVNAME(zr), *std);
+ ZR_DEVNAME(zr), (unsigned long long)*std);
return -EINVAL;
}
@@ -4108,7 +4106,7 @@ zoran_do_ioctl (struct inode *inode,
dprintk(3,
KERN_DEBUG "%s: VIDIOC_QUERY_STD - std=0x%llx\n",
- ZR_DEVNAME(zr), *std);
+ ZR_DEVNAME(zr), (unsigned long long)*std);
if (*std == V4L2_STD_ALL || *std == V4L2_STD_NTSC ||
*std == V4L2_STD_PAL || (*std == V4L2_STD_SECAM &&
diff --git a/drivers/media/video/zr36050.c b/drivers/media/video/zr36050.c
index 1e1bec697a560..13b1e7b6fd6eb 100644
--- a/drivers/media/video/zr36050.c
+++ b/drivers/media/video/zr36050.c
@@ -419,7 +419,7 @@ zr36050_set_dri (struct zr36050 *ptr)
dri_data[2] = 0x00;
dri_data[3] = 0x04;
dri_data[4] = ptr->dri >> 8;
- dri_data[5] = ptr->dri * 0xff;
+ dri_data[5] = ptr->dri & 0xff;
return zr36050_pushit(ptr, ZR050_DRI_IDX, 6, dri_data);
}
diff --git a/drivers/media/video/zr36120.c b/drivers/media/video/zr36120.c
index 7899c63984a3d..c33533155cc72 100644
--- a/drivers/media/video/zr36120.c
+++ b/drivers/media/video/zr36120.c
@@ -30,6 +30,7 @@
#include <linux/mm.h>
#include <linux/pci.h>
#include <linux/signal.h>
+#include <linux/wait.h>
#include <asm/io.h>
#include <asm/pgtable.h>
#include <asm/page.h>
@@ -899,12 +900,11 @@ long zoran_read(struct video_device* dev, char* buf, unsigned long count, int no
zoran_cap(ztv, 1);
/* wait till this buffer gets grabbed */
- while (unused->status == FBUFFER_BUSY) {
- interruptible_sleep_on(&ztv->grabq);
- /* see if a signal did it */
- if (signal_pending(current))
- return -EINTR;
- }
+ wait_event_interruptible(ztv->grabq,
+ (unused->status != FBUFFER_BUSY));
+ /* see if a signal did it */
+ if (signal_pending(current))
+ return -EINTR;
done = unused;
}
else
@@ -1326,12 +1326,11 @@ int zoran_ioctl(struct video_device* dev, unsigned int cmd, void *arg)
return -EINVAL;
case FBUFFER_BUSY:
/* wait till this buffer gets grabbed */
- while (ztv->grabinfo[i].status == FBUFFER_BUSY) {
- interruptible_sleep_on(&ztv->grabq);
- /* see if a signal did it */
- if (signal_pending(current))
- return -EINTR;
- }
+ wait_event_interruptible(ztv->grabq,
+ (ztv->grabinfo[i].status != FBUFFER_BUSY));
+ /* see if a signal did it */
+ if (signal_pending(current))
+ return -EINTR;
/* don't fall through; a DONE buffer is not UNUSED */
break;
case FBUFFER_DONE:
@@ -1640,12 +1639,11 @@ long vbi_read(struct video_device* dev, char* buf, unsigned long count, int nonb
zoran_cap(ztv, 1);
/* wait till this buffer gets grabbed */
- while (unused->status == FBUFFER_BUSY) {
- interruptible_sleep_on(&ztv->vbiq);
- /* see if a signal did it */
- if (signal_pending(current))
- return -EINTR;
- }
+ wait_event_interruptible(ztv->vbiq,
+ (unused->status != FBUFFER_BUSY));
+ /* see if a signal did it */
+ if (signal_pending(current))
+ return -EINTR;
done = unused;
}
else
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
index e13a041cedd2b..942cc1c2a186c 100644
--- a/drivers/message/fusion/mptbase.c
+++ b/drivers/message/fusion/mptbase.c
@@ -3137,8 +3137,7 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
/* wait 1 sec */
if (sleepFlag == CAN_SLEEP) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1000 * HZ / 1000);
+ ssleep(1);
} else {
mdelay (1000);
}
@@ -5914,7 +5913,7 @@ fusion_init(void)
#ifdef CONFIG_PROC_FS
(void) procmpt_create();
#endif
- r = pci_module_init(&mptbase_driver);
+ r = pci_register_driver(&mptbase_driver);
if(r)
return(r);
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
index d9184ac016620..be673070bc34e 100644
--- a/drivers/message/fusion/mptbase.h
+++ b/drivers/message/fusion/mptbase.h
@@ -83,8 +83,8 @@
#define COPYRIGHT "Copyright (c) 1999-2004 " MODULEAUTHOR
#endif
-#define MPT_LINUX_VERSION_COMMON "3.01.18"
-#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.01.18"
+#define MPT_LINUX_VERSION_COMMON "3.01.20"
+#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.01.20"
#define WHAT_MAGIC_STRING "@" "(" "#" ")"
#define show_mptmod_ver(s,ver) \
@@ -420,7 +420,6 @@ do { \
typedef struct _MPT_IOCTL {
struct _MPT_ADAPTER *ioc;
- struct timer_list timer; /* timer function for this adapter */
u8 ReplyFrame[MPT_DEFAULT_FRAME_SIZE]; /* reply frame data */
u8 sense[MPT_SENSE_BUFFER_ALLOC];
int wait_done; /* wake-up value for this ioc */
@@ -428,8 +427,6 @@ typedef struct _MPT_IOCTL {
u8 status; /* current command status */
u8 reset; /* 1 if bus reset allowed */
u8 target; /* target for reset */
- void *tmPtr;
- struct timer_list TMtimer; /* timer function for this adapter */
struct semaphore sem_ioc;
} MPT_IOCTL;
@@ -882,11 +879,9 @@ typedef struct _MPT_SCSI_HOST {
int port;
u32 pad0;
struct scsi_cmnd **ScsiLookup;
- u32 qtag_tick;
VirtDevice **Targets;
MPT_LOCAL_REPLY *pLocal; /* used for internal commands */
struct timer_list timer;
- struct timer_list TMtimer; /* Timer for TM commands ONLY */
/* Pool of memory for holding SCpnts before doing
* OS callbacks. freeQ is the free pool.
*/
@@ -896,7 +891,6 @@ typedef struct _MPT_SCSI_HOST {
u8 pad1;
u8 tmState;
u8 rsvd[2];
- MPT_FRAME_HDR *tmPtr; /* Ptr to TM request*/
MPT_FRAME_HDR *cmdPtr; /* Ptr to nonOS request */
struct scsi_cmnd *abortSCpnt;
MPT_LOCAL_REPLY localReply; /* internal cmd reply struct */
diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c
index 91153cf47fa9a..70b0cfb5ac5c1 100644
--- a/drivers/message/fusion/mptctl.c
+++ b/drivers/message/fusion/mptctl.c
@@ -81,6 +81,7 @@
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/pci.h>
+#include <linux/delay.h> /* for mdelay */
#include <linux/miscdevice.h>
#include <linux/smp_lock.h>
#include <linux/compat.h>
@@ -142,6 +143,9 @@ static int mptctl_hp_targetinfo(unsigned long arg);
static int mptctl_probe(struct pci_dev *, const struct pci_device_id *);
static void mptctl_remove(struct pci_dev *);
+#ifdef CONFIG_COMPAT
+static long compat_mpctl_ioctl(struct file *f, unsigned cmd, unsigned long arg);
+#endif
/*
* Private function calls.
*/
@@ -151,7 +155,7 @@ static MptSge_t *kbuf_alloc_2_sgl( int bytes, u32 dir, int sge_offset, int *frag
struct buflist **blp, dma_addr_t *sglbuf_dma, MPT_ADAPTER *ioc);
static void kfree_sgl( MptSge_t *sgl, dma_addr_t sgl_dma,
struct buflist *buflist, MPT_ADAPTER *ioc);
-static void mptctl_timer_expired (unsigned long data);
+static void mptctl_timeout_expired (MPT_IOCTL *ioctl);
static int mptctl_bus_reset(MPT_IOCTL *ioctl);
static int mptctl_set_tm_flags(MPT_SCSI_HOST *hd);
static void mptctl_free_tm_flags(MPT_ADAPTER *ioc);
@@ -184,9 +188,6 @@ static int mptctl_ioc_reset(MPT_ADAPTER *ioc, int reset_phase);
#define MPT_IOCTL_DEFAULT_TIMEOUT 10 /* Default timeout value (seconds) */
-static u32 fwReplyBuffer[16];
-static pMPIDefaultReply_t ReplyMsg = NULL;
-
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/**
* mptctl_syscall_down - Down the MPT adapter syscall semaphore.
@@ -204,11 +205,6 @@ mptctl_syscall_down(MPT_ADAPTER *ioc, int nonblock)
int rc = 0;
dctlprintk((KERN_INFO MYNAM "::mptctl_syscall_down(%p,%d) called\n", ioc, nonblock));
- if (ioc->ioctl->tmPtr != NULL) {
- dctlprintk((KERN_INFO MYNAM "::mptctl_syscall_down BUSY\n"));
- return -EBUSY;
- }
-
if (nonblock) {
if (down_trylock(&ioc->ioctl->sem_ioc))
rc = -EAGAIN;
@@ -235,131 +231,101 @@ mptctl_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply)
u16 iocStatus;
u8 cmd;
- dctlprintk((MYIOC_s_INFO_FMT ": mptctl_reply()!\n", ioc->name));
+ dctlprintk(("mptctl_reply()!\n"));
if (req)
cmd = req->u.hdr.Function;
else
return 1;
if (ioc->ioctl) {
- /* If timer is not running, then an error occurred.
- * A timeout will call the reset routine to reload the messaging
- * queues.
- * Main callback will free message and reply frames.
- */
- if (reply && (cmd == MPI_FUNCTION_SCSI_TASK_MGMT) &&
- (ioc->ioctl->status & MPT_IOCTL_STATUS_TMTIMER_ACTIVE)) {
- /* This is internally generated TM
- */
- del_timer (&ioc->ioctl->TMtimer);
- ioc->ioctl->status &= ~MPT_IOCTL_STATUS_TMTIMER_ACTIVE;
-
- mptctl_free_tm_flags(ioc);
- /* If TM failed, reset the timer on the existing command,
- * will trigger an adapter reset.
- */
- iocStatus = reply->u.reply.IOCStatus & MPI_IOCSTATUS_MASK;
- if (iocStatus == MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED) {
- if (ioc->ioctl->status & MPT_IOCTL_STATUS_TIMER_ACTIVE) {
- ioc->ioctl->reset &= ~MPTCTL_RESET_OK;
- del_timer (&ioc->ioctl->timer);
- ioc->ioctl->timer.expires = jiffies + HZ;
- add_timer(&ioc->ioctl->timer);
- }
- }
- ioc->ioctl->tmPtr = NULL;
+ if (reply==NULL) {
- } else if (ioc->ioctl->status & MPT_IOCTL_STATUS_TIMER_ACTIVE) {
- /* Delete this timer
- */
- del_timer (&ioc->ioctl->timer);
- ioc->ioctl->status &= ~MPT_IOCTL_STATUS_TIMER_ACTIVE;
+ dctlprintk(("mptctl_reply() NULL Reply "
+ "Function=%x!\n", cmd));
- /* Set the overall status byte. Good if:
- * IOC status is good OR if no reply and a SCSI IO request
- */
- if (reply) {
- /* Copy the reply frame (which much exist
- * for non-SCSI I/O) to the IOC structure.
- */
- dctlprintk((MYIOC_s_INFO_FMT ": Copying Reply Frame @%p to IOC!\n",
- ioc->name, reply));
- memcpy(ioc->ioctl->ReplyFrame, reply,
- min(ioc->reply_sz, 4*reply->u.reply.MsgLength));
- ioc->ioctl->status |= MPT_IOCTL_STATUS_RF_VALID;
-
- /* Set the command status to GOOD if IOC Status is GOOD
- * OR if SCSI I/O cmd and data underrun or recovered error.
- */
- iocStatus = reply->u.reply.IOCStatus & MPI_IOCSTATUS_MASK;
- if (iocStatus == MPI_IOCSTATUS_SUCCESS)
- ioc->ioctl->status |= MPT_IOCTL_STATUS_COMMAND_GOOD;
+ ioc->ioctl->status |= MPT_IOCTL_STATUS_COMMAND_GOOD;
+ ioc->ioctl->reset &= ~MPTCTL_RESET_OK;
- if ((cmd == MPI_FUNCTION_SCSI_IO_REQUEST) ||
- (cmd == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) {
- ioc->ioctl->reset &= ~MPTCTL_RESET_OK;
+ /* We are done, issue wake up
+ */
+ ioc->ioctl->wait_done = 1;
+ wake_up (&mptctl_wait);
+ return 1;
- if ((iocStatus == MPI_IOCSTATUS_SCSI_DATA_UNDERRUN) ||
- (iocStatus == MPI_IOCSTATUS_SCSI_RECOVERED_ERROR)) {
- ioc->ioctl->status |= MPT_IOCTL_STATUS_COMMAND_GOOD;
- }
- }
+ }
- /* Copy the sense data - if present
- */
- if ((cmd == MPI_FUNCTION_SCSI_IO_REQUEST) &&
- (reply->u.sreply.SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID)){
-
- sz = req->u.scsireq.SenseBufferLength;
- req_index = le16_to_cpu(req->u.frame.hwhdr.msgctxu.fld.req_idx);
- sense_data = ((u8 *)ioc->sense_buf_pool + (req_index * MPT_SENSE_BUFFER_ALLOC));
- memcpy(ioc->ioctl->sense, sense_data, sz);
- ioc->ioctl->status |= MPT_IOCTL_STATUS_SENSE_VALID;
- }
+ dctlprintk(("mptctl_reply() with req=%p "
+ "reply=%p Function=%x!\n", req, reply, cmd));
- if (cmd == MPI_FUNCTION_SCSI_TASK_MGMT)
- mptctl_free_tm_flags(ioc);
+ /* Copy the reply frame (which much exist
+ * for non-SCSI I/O) to the IOC structure.
+ */
+ dctlprintk(("Copying Reply Frame @%p to ioc%d!\n",
+ reply, ioc->id));
+ memcpy(ioc->ioctl->ReplyFrame, reply,
+ min(ioc->reply_sz, 4*reply->u.reply.MsgLength));
+ ioc->ioctl->status |= MPT_IOCTL_STATUS_RF_VALID;
+
+ /* Set the command status to GOOD if IOC Status is GOOD
+ * OR if SCSI I/O cmd and data underrun or recovered error.
+ */
+ iocStatus = reply->u.reply.IOCStatus & MPI_IOCSTATUS_MASK;
+ if (iocStatus == MPI_IOCSTATUS_SUCCESS)
+ ioc->ioctl->status |= MPT_IOCTL_STATUS_COMMAND_GOOD;
+ if ((cmd == MPI_FUNCTION_SCSI_IO_REQUEST) ||
+ (cmd == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) {
+ ioc->ioctl->reset &= ~MPTCTL_RESET_OK;
- } else if ((cmd == MPI_FUNCTION_SCSI_IO_REQUEST) ||
- (cmd == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) {
- ioc->ioctl->status |= MPT_IOCTL_STATUS_COMMAND_GOOD;
- ioc->ioctl->reset &= ~MPTCTL_RESET_OK;
+ if ((iocStatus == MPI_IOCSTATUS_SCSI_DATA_UNDERRUN) ||
+ (iocStatus == MPI_IOCSTATUS_SCSI_RECOVERED_ERROR)) {
+ ioc->ioctl->status |= MPT_IOCTL_STATUS_COMMAND_GOOD;
}
+ }
- /* We are done, issue wake up
- */
- ioc->ioctl->wait_done = 1;
- wake_up (&mptctl_wait);
- } else if (reply && cmd == MPI_FUNCTION_FW_DOWNLOAD) {
- /* Two paths to FW DOWNLOAD! */
- // NOTE: Expects/requires non-Turbo reply!
- dctlprintk((MYIOC_s_INFO_FMT ":Caching MPI_FUNCTION_FW_DOWNLOAD reply!\n",
- ioc->name));
- memcpy(fwReplyBuffer, reply, min_t(int, sizeof(fwReplyBuffer), 4*reply->u.reply.MsgLength));
- ReplyMsg = (pMPIDefaultReply_t) fwReplyBuffer;
+ /* Copy the sense data - if present
+ */
+ if ((cmd == MPI_FUNCTION_SCSI_IO_REQUEST) &&
+ (reply->u.sreply.SCSIState &
+ MPI_SCSI_STATE_AUTOSENSE_VALID)){
+ sz = req->u.scsireq.SenseBufferLength;
+ req_index =
+ le16_to_cpu(req->u.frame.hwhdr.msgctxu.fld.req_idx);
+ sense_data =
+ ((u8 *)ioc->sense_buf_pool +
+ (req_index * MPT_SENSE_BUFFER_ALLOC));
+ memcpy(ioc->ioctl->sense, sense_data, sz);
+ ioc->ioctl->status |= MPT_IOCTL_STATUS_SENSE_VALID;
}
+
+ if (cmd == MPI_FUNCTION_SCSI_TASK_MGMT)
+ mptctl_free_tm_flags(ioc);
+
+ /* We are done, issue wake up
+ */
+ ioc->ioctl->wait_done = 1;
+ wake_up (&mptctl_wait);
}
return 1;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/* mptctl_timer_expired
+/* mptctl_timeout_expired
*
- * Call back for timer process. Used only for ioctl functionality.
+ * Expecting an interrupt, however timed out.
*
*/
-static void mptctl_timer_expired (unsigned long data)
+static void mptctl_timeout_expired (MPT_IOCTL *ioctl)
{
- MPT_IOCTL *ioctl = (MPT_IOCTL *) data;
int rc = 1;
- dctlprintk((KERN_NOTICE MYNAM ": Timer Expired! Host %d\n",
+ dctlprintk((KERN_NOTICE MYNAM ": Timeout Expired! Host %d\n",
ioctl->ioc->id));
if (ioctl == NULL)
return;
+ ioctl->wait_done = 0;
if (ioctl->reset & MPTCTL_RESET_OK)
rc = mptctl_bus_reset(ioctl);
@@ -367,6 +333,8 @@ static void mptctl_timer_expired (unsigned long data)
/* Issue a reset for this device.
* The IOC is not responding.
*/
+ dctlprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n",
+ ioctl->ioc->name));
mpt_HardResetHandler(ioctl->ioc, NO_SLEEP);
}
return;
@@ -391,7 +359,7 @@ static int mptctl_bus_reset(MPT_IOCTL *ioctl)
if (ioctl->ioc->sh == NULL)
return -EPERM;
-
+
hd = (MPT_SCSI_HOST *) ioctl->ioc->sh->hostdata;
if (hd == NULL)
return -EPERM;
@@ -431,26 +399,34 @@ static int mptctl_bus_reset(MPT_IOCTL *ioctl)
pScsiTm->Reserved2[ii] = 0;
pScsiTm->TaskMsgContext = 0;
- dtmprintk((MYIOC_s_INFO_FMT "mptctl_bus_reset: issued.\n", ioctl->ioc->name));
+ dtmprintk((MYIOC_s_INFO_FMT
+ "mptctl_bus_reset: issued.\n", ioctl->ioc->name));
- ioctl->tmPtr = mf;
- ioctl->TMtimer.expires = jiffies + HZ * 20; /* 20 seconds */
- ioctl->status |= MPT_IOCTL_STATUS_TMTIMER_ACTIVE;
- add_timer(&ioctl->TMtimer);
+ DBG_DUMP_TM_REQUEST_FRAME((u32 *)mf);
- retval = mpt_send_handshake_request(mptctl_id, ioctl->ioc,
- sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, NO_SLEEP);
+ ioctl->wait_done=0;
+ if ((retval = mpt_send_handshake_request(mptctl_id, ioctl->ioc,
+ sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, CAN_SLEEP)) != 0) {
+ dfailprintk((MYIOC_s_ERR_FMT "_send_handshake FAILED!"
+ " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd,
+ hd->ioc, mf));
+ goto mptctl_bus_reset_done;
+ }
- if (retval != 0) {
- dtmprintk((MYIOC_s_WARN_FMT "_send_handshake FAILED!"
- " (hd %p, ioc %p, mf %p) \n", ioctl->ioc->name, hd, hd->ioc, mf));
+ /* Now wait for the command to complete */
+ ii = wait_event_interruptible_timeout(mptctl_wait,
+ ioctl->wait_done == 1,
+ HZ*5 /* 5 second timeout */);
- mptctl_free_tm_flags(ioctl->ioc);
- del_timer(&ioctl->TMtimer);
- mpt_free_msg_frame(ioctl->ioc, mf);
- ioctl->tmPtr = NULL;
+ if(ii <=0 && (ioctl->wait_done != 1 )) {
+ ioctl->wait_done = 0;
+ retval = -1; /* return failure */
}
+mptctl_bus_reset_done:
+
+ mpt_free_msg_frame(hd->ioc, mf);
+ mptctl_free_tm_flags(ioctl->ioc);
return retval;
}
@@ -491,7 +467,6 @@ mptctl_free_tm_flags(MPT_ADAPTER *ioc)
return;
}
-
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/* mptctl_ioc_reset
*
@@ -504,43 +479,22 @@ mptctl_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
{
MPT_IOCTL *ioctl = ioc->ioctl;
dctlprintk((KERN_INFO MYNAM ": IOC %s_reset routed to IOCTL driver!\n",
- reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
- reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
-
- if (reset_phase == MPT_IOC_SETUP_RESET){
- ;
- } else if (reset_phase == MPT_IOC_PRE_RESET){
-
- /* Someone has called the reset handler to
- * do a hard reset. No more replies from the FW.
- * Delete the timer. TM flags cleaned up by SCSI driver.
- * Do not need to free msg frame, as re-initialized
- */
- if (ioctl && (ioctl->status & MPT_IOCTL_STATUS_TIMER_ACTIVE)){
- del_timer(&ioctl->timer);
- }
- if (ioctl && (ioctl->status & MPT_IOCTL_STATUS_TMTIMER_ACTIVE)){
- ioctl->status &= ~MPT_IOCTL_STATUS_TMTIMER_ACTIVE;
- del_timer(&ioctl->TMtimer);
- mpt_free_msg_frame(ioc, ioctl->tmPtr);
- }
-
- } else {
- ioctl->tmPtr = NULL;
+ reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
+ reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
- /* Set the status and continue IOCTL
- * processing. All memory will be free'd
- * by originating thread after wake_up is
- * called.
- */
- if (ioctl && (ioctl->status & MPT_IOCTL_STATUS_TIMER_ACTIVE)){
- ioctl->status |= MPT_IOCTL_STATUS_DID_IOCRESET;
+ if(ioctl == NULL)
+ return 1;
- /* Wake up the calling process
- */
- ioctl->wait_done = 1;
- wake_up(&mptctl_wait);
- }
+ switch(reset_phase) {
+ case MPT_IOC_SETUP_RESET:
+ ioctl->status |= MPT_IOCTL_STATUS_DID_IOCRESET;
+ break;
+ case MPT_IOC_POST_RESET:
+ ioctl->status &= ~MPT_IOCTL_STATUS_DID_IOCRESET;
+ break;
+ case MPT_IOC_PRE_RESET:
+ default:
+ break;
}
return 1;
@@ -552,8 +506,8 @@ mptctl_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
* cmd - specify the particular IOCTL command to be issued
* arg - data specific to the command. Must not be null.
*/
-static int
-mptctl_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+static long
+__mptctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
mpt_ioctl_header __user *uhdr = (void __user *) arg;
mpt_ioctl_header khdr;
@@ -637,6 +591,16 @@ mptctl_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned
return ret;
}
+static long
+mptctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ long ret;
+ lock_kernel();
+ ret = __mptctl_ioctl(file, cmd, arg);
+ unlock_kernel();
+ return ret;
+}
+
static int mptctl_do_reset(unsigned long arg)
{
struct mpt_ioctl_diag_reset __user *urinfo = (void __user *) arg;
@@ -735,9 +699,9 @@ mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen)
u32 nib;
int fw_bytes_copied = 0;
int i;
- int cntdn;
int sge_offset = 0;
u16 iocstat;
+ pFWDownloadReply_t ReplyMsg = NULL;
dctlprintk((KERN_INFO "mptctl_do_fwdl called. mptctl_id = %xh.\n", mptctl_id));
@@ -868,31 +832,25 @@ mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen)
/*
* Finally, perform firmware download.
*/
- ReplyMsg = NULL;
+ iocp->ioctl->wait_done = 0;
mpt_put_msg_frame(mptctl_id, iocp, mf);
- /*
- * Wait until the reply has been received
- */
- for (cntdn=HZ*60, i=1; ReplyMsg == NULL; cntdn--, i++) {
- if (!cntdn) {
- ret = -ETIME;
- goto fwdl_out;
- }
+ /* Now wait for the command to complete */
+ ret = wait_event_interruptible_timeout(mptctl_wait,
+ iocp->ioctl->wait_done == 1,
+ HZ*60);
- if (!(i%HZ)) {
- dctlprintk((KERN_INFO "DbG::_do_fwdl: "
- "In ReplyMsg loop - iteration %d\n",
- i));
- }
-
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
+ if(ret <=0 && (iocp->ioctl->wait_done != 1 )) {
+ /* Now we need to reset the board */
+ mptctl_timeout_expired(iocp->ioctl);
+ ret = -ENODATA;
+ goto fwdl_out;
}
if (sgl)
kfree_sgl(sgl, sgl_dma, buflist, iocp);
+ ReplyMsg = (pFWDownloadReply_t)iocp->ioctl->ReplyFrame;
iocstat = le16_to_cpu(ReplyMsg->IOCStatus) & MPI_IOCSTATUS_MASK;
if (iocstat == MPI_IOCSTATUS_SUCCESS) {
printk(KERN_INFO MYNAM ": F/W update successfully sent to %s!\n", iocp->name);
@@ -1180,14 +1138,14 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size)
cim_rev = 0; /* obsolete */
else
return -EFAULT;
-
+
karg = kmalloc(data_size, GFP_KERNEL);
if (karg == NULL) {
printk(KERN_ERR "%s::mpt_ioctl_iocinfo() @%d - no memory available!\n",
__FILE__, __LINE__);
return -ENOMEM;
}
-
+
if (copy_from_user(karg, uarg, data_size)) {
printk(KERN_ERR "%s@%d::mptctl_getiocinfo - "
"Unable to read in mpt_ioctl_iocinfo struct @ %p\n",
@@ -1812,8 +1770,8 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
int iocnum, flagsLength;
int sz, rc = 0;
int msgContext;
- int tm_flags_set = 0;
u16 req_idx;
+ ulong timeout;
dctlprintk(("mptctl_do_mpt_command called.\n"));
bufIn.kptr = bufOut.kptr = NULL;
@@ -2029,7 +1987,6 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
rc = -EPERM;
goto done_free_mem;
}
- tm_flags_set = 1;
}
break;
@@ -2181,136 +2138,108 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
mpt_add_sge(psge, flagsLength, (dma_addr_t) -1);
}
- /* The request is complete. Set the timer parameters
- * and issue the request.
- */
- if (karg.timeout > 0) {
- ioc->ioctl->timer.expires = jiffies + HZ*karg.timeout;
- } else {
- ioc->ioctl->timer.expires = jiffies + HZ*MPT_IOCTL_DEFAULT_TIMEOUT;
- }
-
ioc->ioctl->wait_done = 0;
- ioc->ioctl->status |= MPT_IOCTL_STATUS_TIMER_ACTIVE;
- add_timer(&ioc->ioctl->timer);
-
if (hdr->Function == MPI_FUNCTION_SCSI_TASK_MGMT) {
+
DBG_DUMP_TM_REQUEST_FRAME((u32 *)mf);
- rc = mpt_send_handshake_request(mptctl_id, ioc,
- sizeof(SCSITaskMgmt_t), (u32*)mf, CAN_SLEEP);
- if (rc == 0) {
- wait_event(mptctl_wait, ioc->ioctl->wait_done);
- } else {
+
+ if (mpt_send_handshake_request(mptctl_id, ioc,
+ sizeof(SCSITaskMgmt_t), (u32*)mf,
+ CAN_SLEEP) != 0) {
+ dfailprintk((MYIOC_s_ERR_FMT "_send_handshake FAILED!"
+ " (ioc %p, mf %p) \n", ioc->name,
+ ioc, mf));
mptctl_free_tm_flags(ioc);
- tm_flags_set= 0;
- del_timer(&ioc->ioctl->timer);
- ioc->ioctl->status &= ~MPT_IOCTL_STATUS_TIMER_ACTIVE;
- ioc->ioctl->status |= MPT_IOCTL_STATUS_TM_FAILED;
- mpt_free_msg_frame(ioc, mf);
+ rc = -ENODATA;
+ goto done_free_mem;
}
- } else {
+
+ } else
mpt_put_msg_frame(mptctl_id, ioc, mf);
- wait_event(mptctl_wait, ioc->ioctl->wait_done);
- }
- mf = NULL;
+ /* Now wait for the command to complete */
+ timeout = (karg.timeout > 0) ? karg.timeout : MPT_IOCTL_DEFAULT_TIMEOUT;
+ timeout = wait_event_interruptible_timeout(mptctl_wait,
+ ioc->ioctl->wait_done == 1,
+ HZ*timeout);
- /* MF Cleanup:
- * If command failed and failure triggered a diagnostic reset
- * OR a diagnostic reset happens during command processing,
- * no data, messaging queues are reset (mf cannot be accessed),
- * and status is DID_IOCRESET
- *
- * If a user-requested bus reset fails to be handshaked, then
- * mf is returned to free queue and status is TM_FAILED.
- *
- * Otherise, the command completed and the mf was freed
- # by ISR (mf cannot be touched).
- */
- if (ioc->ioctl->status & MPT_IOCTL_STATUS_DID_IOCRESET) {
- /* The timer callback deleted the
- * timer and reset the adapter queues.
- */
- printk(KERN_WARNING "%s@%d::mptctl_do_mpt_command - "
- "Timeout Occurred on IOCTL! Reset IOC.\n", __FILE__, __LINE__);
- tm_flags_set= 0;
- rc = -ETIME;
- } else if (ioc->ioctl->status & MPT_IOCTL_STATUS_TM_FAILED) {
- /* User TM request failed! mf has not been freed.
- */
+ if(timeout <=0 && (ioc->ioctl->wait_done != 1 )) {
+ /* Now we need to reset the board */
+
+ if (hdr->Function == MPI_FUNCTION_SCSI_TASK_MGMT)
+ mptctl_free_tm_flags(ioc);
+
+ mptctl_timeout_expired(ioc->ioctl);
rc = -ENODATA;
- } else {
- /* If a valid reply frame, copy to the user.
- * Offset 2: reply length in U32's
- */
- if (ioc->ioctl->status & MPT_IOCTL_STATUS_RF_VALID) {
- if (karg.maxReplyBytes < ioc->reply_sz) {
- sz = min(karg.maxReplyBytes, 4*ioc->ioctl->ReplyFrame[2]);
- } else {
- sz = min(ioc->reply_sz, 4*ioc->ioctl->ReplyFrame[2]);
- }
+ goto done_free_mem;
+ }
- if (sz > 0) {
- if (copy_to_user(karg.replyFrameBufPtr,
- &ioc->ioctl->ReplyFrame, sz)){
+ mf = NULL;
- printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
- "Unable to write out reply frame %p\n",
- __FILE__, __LINE__, karg.replyFrameBufPtr);
- rc = -ENODATA;
- goto done_free_mem;
- }
- }
+ /* If a valid reply frame, copy to the user.
+ * Offset 2: reply length in U32's
+ */
+ if (ioc->ioctl->status & MPT_IOCTL_STATUS_RF_VALID) {
+ if (karg.maxReplyBytes < ioc->reply_sz) {
+ sz = min(karg.maxReplyBytes, 4*ioc->ioctl->ReplyFrame[2]);
+ } else {
+ sz = min(ioc->reply_sz, 4*ioc->ioctl->ReplyFrame[2]);
}
- /* If valid sense data, copy to user.
- */
- if (ioc->ioctl->status & MPT_IOCTL_STATUS_SENSE_VALID) {
- sz = min(karg.maxSenseBytes, MPT_SENSE_BUFFER_SIZE);
- if (sz > 0) {
- if (copy_to_user(karg.senseDataPtr, ioc->ioctl->sense, sz)) {
- printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
- "Unable to write sense data to user %p\n",
- __FILE__, __LINE__,
- karg.senseDataPtr);
- rc = -ENODATA;
- goto done_free_mem;
- }
+ if (sz > 0) {
+ if (copy_to_user(karg.replyFrameBufPtr,
+ &ioc->ioctl->ReplyFrame, sz)){
+ printk(KERN_ERR
+ "%s@%d::mptctl_do_mpt_command - "
+ "Unable to write out reply frame %p\n",
+ __FILE__, __LINE__, karg.replyFrameBufPtr);
+ rc = -ENODATA;
+ goto done_free_mem;
}
}
+ }
- /* If the overall status is _GOOD and data in, copy data
- * to user.
- */
- if ((ioc->ioctl->status & MPT_IOCTL_STATUS_COMMAND_GOOD) &&
- (karg.dataInSize > 0) && (bufIn.kptr)) {
-
- if (copy_to_user(karg.dataInBufPtr,
- bufIn.kptr, karg.dataInSize)) {
+ /* If valid sense data, copy to user.
+ */
+ if (ioc->ioctl->status & MPT_IOCTL_STATUS_SENSE_VALID) {
+ sz = min(karg.maxSenseBytes, MPT_SENSE_BUFFER_SIZE);
+ if (sz > 0) {
+ if (copy_to_user(karg.senseDataPtr, ioc->ioctl->sense, sz)) {
printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
- "Unable to write data to user %p\n",
- __FILE__, __LINE__,
- karg.dataInBufPtr);
+ "Unable to write sense data to user %p\n",
+ __FILE__, __LINE__,
+ karg.senseDataPtr);
rc = -ENODATA;
+ goto done_free_mem;
}
}
}
-done_free_mem:
- /* Clear all status bits except TMTIMER_ACTIVE, this bit is cleared
- * upon completion of the TM command.
- * ioc->ioctl->status = 0;
+ /* If the overall status is _GOOD and data in, copy data
+ * to user.
*/
- ioc->ioctl->status &= ~(MPT_IOCTL_STATUS_TIMER_ACTIVE | MPT_IOCTL_STATUS_TM_FAILED |
- MPT_IOCTL_STATUS_COMMAND_GOOD | MPT_IOCTL_STATUS_SENSE_VALID |
- MPT_IOCTL_STATUS_RF_VALID | MPT_IOCTL_STATUS_DID_IOCRESET);
+ if ((ioc->ioctl->status & MPT_IOCTL_STATUS_COMMAND_GOOD) &&
+ (karg.dataInSize > 0) && (bufIn.kptr)) {
- if (tm_flags_set)
- mptctl_free_tm_flags(ioc);
+ if (copy_to_user(karg.dataInBufPtr,
+ bufIn.kptr, karg.dataInSize)) {
+ printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - "
+ "Unable to write data to user %p\n",
+ __FILE__, __LINE__,
+ karg.dataInBufPtr);
+ rc = -ENODATA;
+ }
+ }
+
+done_free_mem:
+
+ ioc->ioctl->status &= ~(MPT_IOCTL_STATUS_COMMAND_GOOD |
+ MPT_IOCTL_STATUS_SENSE_VALID |
+ MPT_IOCTL_STATUS_RF_VALID );
/* Free the allocated memory.
*/
- if (bufOut.kptr != NULL) {
+ if (bufOut.kptr != NULL) {
pci_free_consistent(ioc->pcidev,
bufOut.len, (void *) bufOut.kptr, dma_addr_out);
}
@@ -2549,7 +2478,7 @@ mptctl_hp_targetinfo(unsigned long arg)
__FILE__, __LINE__, uarg);
return -EFAULT;
}
-
+
if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
(ioc == NULL)) {
dctlprintk((KERN_ERR "%s::mptctl_hp_targetinfo() @%d - ioc%d not found!\n",
@@ -2567,7 +2496,7 @@ mptctl_hp_targetinfo(unsigned long arg)
if (ioc->sh->host_no != karg.hdr.host)
return -ENODEV;
-
+
/* Get the data transfer speeds
*/
data_sz = ioc->spi_data.sdp0length * 4;
@@ -2669,7 +2598,10 @@ mptctl_hp_targetinfo(unsigned long arg)
static struct file_operations mptctl_fops = {
.owner = THIS_MODULE,
.llseek = no_llseek,
- .ioctl = mptctl_ioctl,
+ .unlocked_ioctl = mptctl_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = compat_mpctl_ioctl,
+#endif
};
static struct miscdevice mptctl_miscdev = {
@@ -2684,29 +2616,9 @@ static struct miscdevice mptctl_miscdev = {
#include <linux/ioctl32.h>
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/* compat_XXX functions are used to provide a conversion between
- * pointers and u32's. If the arg does not contain any pointers, then
- * a specialized function (compat_XXX) is not needed. If the arg
- * does contain pointer(s), then the specialized function is used
- * to ensure the structure contents is properly processed by mptctl.
- */
static int
-compat_mptctl_ioctl(unsigned int fd, unsigned int cmd,
- unsigned long arg, struct file *filp)
-{
- int ret;
-
- lock_kernel();
- dctlprintk((KERN_INFO MYNAM "::compat_mptctl_ioctl() called\n"));
- ret = mptctl_ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
- unlock_kernel();
- return ret;
-}
-
-static int
-compat_mptfwxfer_ioctl(unsigned int fd, unsigned int cmd,
- unsigned long arg, struct file *filp)
+compat_mptfwxfer_ioctl(struct file *filp, unsigned int cmd,
+ unsigned long arg)
{
struct mpt_fw_xfer32 kfw32;
struct mpt_fw_xfer kfw;
@@ -2744,8 +2656,8 @@ compat_mptfwxfer_ioctl(unsigned int fd, unsigned int cmd,
}
static int
-compat_mpt_command(unsigned int fd, unsigned int cmd,
- unsigned long arg, struct file *filp)
+compat_mpt_command(struct file *filp, unsigned int cmd,
+ unsigned long arg)
{
struct mpt_ioctl_command32 karg32;
struct mpt_ioctl_command32 __user *uarg = (struct mpt_ioctl_command32 __user *) arg;
@@ -2797,6 +2709,38 @@ compat_mpt_command(unsigned int fd, unsigned int cmd,
return ret;
}
+static long compat_mpctl_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
+{
+ long ret;
+ lock_kernel();
+ switch (cmd) {
+ case MPTIOCINFO:
+ case MPTIOCINFO1:
+ case MPTIOCINFO2:
+ case MPTTARGETINFO:
+ case MPTEVENTQUERY:
+ case MPTEVENTENABLE:
+ case MPTEVENTREPORT:
+ case MPTHARDRESET:
+ case HP_GETHOSTINFO:
+ case HP_GETTARGETINFO:
+ case MPTTEST:
+ ret = __mptctl_ioctl(f, cmd, arg);
+ break;
+ case MPTCOMMAND32:
+ ret = compat_mpt_command(f, cmd, arg);
+ break;
+ case MPTFWDOWNLOAD32:
+ ret = compat_mptfwxfer_ioctl(f, cmd, arg);
+ break;
+ default:
+ ret = -ENOIOCTLCMD;
+ break;
+ }
+ unlock_kernel();
+ return ret;
+}
+
#endif
@@ -2830,12 +2774,6 @@ 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;
- init_timer (&ioc->ioctl->timer);
- ioc->ioctl->timer.data = (unsigned long) ioc->ioctl;
- ioc->ioctl->timer.function = mptctl_timer_expired;
- init_timer (&ioc->ioctl->TMtimer);
- ioc->ioctl->TMtimer.data = (unsigned long) ioc->ioctl;
- ioc->ioctl->TMtimer.function = mptctl_timer_expired;
sema_init(&ioc->ioctl->sem_ioc, 1);
return 0;
@@ -2879,36 +2817,6 @@ static int __init mptctl_init(void)
": failed to register dd callbacks\n"));
}
-#ifdef CONFIG_COMPAT
- err = register_ioctl32_conversion(MPTIOCINFO, compat_mptctl_ioctl);
- if (++where && err) goto out_fail;
- err = register_ioctl32_conversion(MPTIOCINFO1, compat_mptctl_ioctl);
- if (++where && err) goto out_fail;
- err = register_ioctl32_conversion(MPTIOCINFO2, compat_mptctl_ioctl);
- if (++where && err) goto out_fail;
- err = register_ioctl32_conversion(MPTTARGETINFO, compat_mptctl_ioctl);
- if (++where && err) goto out_fail;
- err = register_ioctl32_conversion(MPTTEST, compat_mptctl_ioctl);
- if (++where && err) goto out_fail;
- err = register_ioctl32_conversion(MPTEVENTQUERY, compat_mptctl_ioctl);
- if (++where && err) goto out_fail;
- err = register_ioctl32_conversion(MPTEVENTENABLE, compat_mptctl_ioctl);
- if (++where && err) goto out_fail;
- err = register_ioctl32_conversion(MPTEVENTREPORT, compat_mptctl_ioctl);
- if (++where && err) goto out_fail;
- err = register_ioctl32_conversion(MPTHARDRESET, compat_mptctl_ioctl);
- if (++where && err) goto out_fail;
- err = register_ioctl32_conversion(MPTCOMMAND32, compat_mpt_command);
- if (++where && err) goto out_fail;
- err = register_ioctl32_conversion(MPTFWDOWNLOAD32,
- compat_mptfwxfer_ioctl);
- if (++where && err) goto out_fail;
- err = register_ioctl32_conversion(HP_GETHOSTINFO, compat_mptctl_ioctl);
- if (++where && err) goto out_fail;
- err = register_ioctl32_conversion(HP_GETTARGETINFO, compat_mptctl_ioctl);
- if (++where && err) goto out_fail;
-#endif
-
/* Register this device */
err = misc_register(&mptctl_miscdev);
if (err < 0) {
@@ -2940,24 +2848,6 @@ static int __init mptctl_init(void)
out_fail:
-#ifdef CONFIG_COMPAT
- printk(KERN_ERR MYNAM ": ERROR: Failed to register ioctl32_conversion!"
- " (%d:err=%d)\n", where, err);
- unregister_ioctl32_conversion(MPTIOCINFO);
- unregister_ioctl32_conversion(MPTIOCINFO1);
- unregister_ioctl32_conversion(MPTIOCINFO2);
- unregister_ioctl32_conversion(MPTTARGETINFO);
- unregister_ioctl32_conversion(MPTTEST);
- unregister_ioctl32_conversion(MPTEVENTQUERY);
- unregister_ioctl32_conversion(MPTEVENTENABLE);
- unregister_ioctl32_conversion(MPTEVENTREPORT);
- unregister_ioctl32_conversion(MPTHARDRESET);
- unregister_ioctl32_conversion(MPTCOMMAND32);
- unregister_ioctl32_conversion(MPTFWDOWNLOAD32);
- unregister_ioctl32_conversion(HP_GETHOSTINFO);
- unregister_ioctl32_conversion(HP_GETTARGETINFO);
-#endif
-
mpt_device_driver_deregister(MPTCTL_DRIVER);
return err;
@@ -2980,22 +2870,6 @@ static void mptctl_exit(void)
mpt_device_driver_deregister(MPTCTL_DRIVER);
-#ifdef CONFIG_COMPAT
- unregister_ioctl32_conversion(MPTIOCINFO);
- unregister_ioctl32_conversion(MPTIOCINFO1);
- unregister_ioctl32_conversion(MPTIOCINFO2);
- unregister_ioctl32_conversion(MPTTARGETINFO);
- unregister_ioctl32_conversion(MPTTEST);
- unregister_ioctl32_conversion(MPTEVENTQUERY);
- unregister_ioctl32_conversion(MPTEVENTENABLE);
- unregister_ioctl32_conversion(MPTEVENTREPORT);
- unregister_ioctl32_conversion(MPTHARDRESET);
- unregister_ioctl32_conversion(MPTCOMMAND32);
- unregister_ioctl32_conversion(MPTFWDOWNLOAD32);
- unregister_ioctl32_conversion(HP_GETHOSTINFO);
- unregister_ioctl32_conversion(HP_GETTARGETINFO);
-#endif
-
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
index 0a11f963f3a2f..c98d6257ec02f 100644
--- a/drivers/message/fusion/mptscsih.c
+++ b/drivers/message/fusion/mptscsih.c
@@ -96,23 +96,26 @@ MODULE_AUTHOR(MODULEAUTHOR);
MODULE_DESCRIPTION(my_NAME);
MODULE_LICENSE("GPL");
-#ifdef MODULE
-static int dv = MPTSCSIH_DOMAIN_VALIDATION;
-module_param(dv, int, 0);
-MODULE_PARM_DESC(dv, "DV Algorithm: enhanced = 1, basic = 0 (default=MPTSCSIH_DOMAIN_VALIDATION=1)");
-
-static int width = MPTSCSIH_MAX_WIDTH;
-module_param(width, int, 0);
-MODULE_PARM_DESC(width, "Max Bus Width: wide = 1, narrow = 0 (default=MPTSCSIH_MAX_WIDTH=1)");
-
-static ushort factor = MPTSCSIH_MIN_SYNC;
-module_param(factor, ushort, 0);
-MODULE_PARM_DESC(factor, "Min Sync Factor: (default=MPTSCSIH_MIN_SYNC=0x08)");
-
-static int saf_te = MPTSCSIH_SAF_TE;
-module_param(saf_te, int, 0);
-MODULE_PARM_DESC(saf_te, "Force enabling SEP Processor: (default=MPTSCSIH_SAF_TE=0)");
-#endif
+/* Command line args */
+static int mpt_dv = MPTSCSIH_DOMAIN_VALIDATION;
+MODULE_PARM(mpt_dv, "i");
+MODULE_PARM_DESC(mpt_dv, " DV Algorithm: enhanced=1, basic=0 (default=MPTSCSIH_DOMAIN_VALIDATION=1)");
+
+static int mpt_width = MPTSCSIH_MAX_WIDTH;
+MODULE_PARM(mpt_width, "i");
+MODULE_PARM_DESC(mpt_width, " Max Bus Width: wide=1, narrow=0 (default=MPTSCSIH_MAX_WIDTH=1)");
+
+static int mpt_factor = MPTSCSIH_MIN_SYNC;
+MODULE_PARM(mpt_factor, "h");
+MODULE_PARM_DESC(mpt_factor, " Min Sync Factor (default=MPTSCSIH_MIN_SYNC=0x08)");
+
+static int mpt_saf_te = MPTSCSIH_SAF_TE;
+MODULE_PARM(mpt_saf_te, "i");
+MODULE_PARM_DESC(mpt_saf_te, " Force enabling SEP Processor: enable=1 (default=MPTSCSIH_SAF_TE=0)");
+
+static int mpt_pq_filter = 0;
+MODULE_PARM(mpt_pq_filter, "i");
+MODULE_PARM_DESC(mpt_pq_filter, " Enable peripheral qualifier filter: enable=1 (default=0)");
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -179,10 +182,11 @@ static int mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt,
static void mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx);
static void copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply);
static int mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd);
+static int mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout );
static u32 SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc);
-static int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout, int sleepFlag);
-static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout, int sleepFlag);
+static int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout);
+static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout);
static int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
static int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
@@ -196,13 +200,9 @@ static int mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target, int fl
static int mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus);
static int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
static void mptscsih_timer_expired(unsigned long data);
-static void mptscsih_taskmgmt_timeout(unsigned long data);
-static void mptscsih_schedule_reset(void *hd);
static int mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd);
static int mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum);
-static struct work_struct mptscsih_rstTask;
-
#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);
@@ -256,7 +256,6 @@ static int scandv_wait_done = 1;
/* Driver command line structure
*/
-static struct mptscsih_driver_setup driver_setup;
static struct scsi_host_template driver_template;
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -1207,7 +1206,6 @@ mptscsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
hd->tmState = TM_STATE_NONE;
hd->resetPending = 0;
hd->abortSCpnt = NULL;
- hd->tmPtr = NULL;
/* Clear the pointer used to store
* single-threaded commands, i.e., those
@@ -1224,41 +1222,27 @@ mptscsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
hd->timer.data = (unsigned long) hd;
hd->timer.function = mptscsih_timer_expired;
- init_timer(&hd->TMtimer);
- hd->TMtimer.data = (unsigned long) hd;
- hd->TMtimer.function = mptscsih_taskmgmt_timeout;
- hd->qtag_tick = jiffies;
-
- /* Moved Earlier Pam D */
- /* ioc->sh = sh; */
-
if (ioc->bus_type == SCSI) {
/* Update with the driver setup
* values.
*/
- if (ioc->spi_data.maxBusWidth >
- driver_setup.max_width) {
- ioc->spi_data.maxBusWidth =
- driver_setup.max_width;
- }
-
- if (ioc->spi_data.minSyncFactor <
- driver_setup.min_sync_factor) {
- ioc->spi_data.minSyncFactor =
- driver_setup.min_sync_factor;
- }
+ if (ioc->spi_data.maxBusWidth > mpt_width)
+ ioc->spi_data.maxBusWidth = mpt_width;
+ if (ioc->spi_data.minSyncFactor < mpt_factor)
+ ioc->spi_data.minSyncFactor = mpt_factor;
if (ioc->spi_data.minSyncFactor == MPT_ASYNC) {
ioc->spi_data.maxSyncOffset = 0;
}
- ioc->spi_data.Saf_Te = driver_setup.saf_te;
+ ioc->spi_data.Saf_Te = mpt_saf_te;
hd->negoNvram = 0;
#ifndef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
hd->negoNvram = MPT_SCSICFG_USE_NVRAM;
#endif
ioc->spi_data.forceDv = 0;
+ ioc->spi_data.noQas = 0;
for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
ioc->spi_data.dvStatus[ii] =
MPT_SCSICFG_NEGOTIATE;
@@ -1268,12 +1252,12 @@ mptscsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
ioc->spi_data.dvStatus[ii] |=
MPT_SCSICFG_DV_NOT_DONE;
- ddvprintk((MYIOC_s_INFO_FMT
+ dinitprintk((MYIOC_s_INFO_FMT
"dv %x width %x factor %x saf_te %x\n",
- ioc->name, driver_setup.dv,
- driver_setup.max_width,
- driver_setup.min_sync_factor,
- driver_setup.saf_te));
+ ioc->name, mpt_dv,
+ mpt_width,
+ mpt_factor,
+ mpt_saf_te));
}
mpt_scsi_hosts++;
@@ -1489,18 +1473,6 @@ mptscsih_init(void)
": Registered for IOC reset notifications\n"));
}
-#ifdef MODULE
- dinitprintk((KERN_INFO MYNAM
- ": Command Line Args: dv=%d max_width=%d "
- "factor=0x%x saf_te=%d\n",
- dv, width, factor, saf_te));
-
- driver_setup.dv = (dv) ? 1 : 0;
- driver_setup.max_width = (width) ? 1 : 0;
- driver_setup.min_sync_factor = factor;
- driver_setup.saf_te = (saf_te) ? 1 : 0;;
-#endif
-
if(mpt_device_driver_register(&mptscsih_driver,
MPTSCSIH_DRIVER) != 0 ) {
dprintk((KERN_INFO MYNAM
@@ -1925,7 +1897,6 @@ mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx)
* @target: Logical Target ID for reset (if appropriate)
* @lun: Logical Unit for reset (if appropriate)
* @ctx2abort: Context for the task to be aborted (if appropriate)
- * @sleepFlag: If set, use udelay instead of schedule in handshake code.
*
* Remark: Currently invoked from a non-interrupt thread (_bh).
*
@@ -1935,7 +1906,7 @@ mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx)
* Returns 0 for SUCCESS or -1 if FAILED.
*/
static int
-mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout, int sleepFlag)
+mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout)
{
MPT_ADAPTER *ioc;
int rc = -1;
@@ -2015,7 +1986,7 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, in
*/
if (hd->hard_resets < -1)
hd->hard_resets++;
- rc = mptscsih_IssueTaskMgmt(hd, type, channel, target, lun, ctx2abort, timeout, sleepFlag);
+ rc = mptscsih_IssueTaskMgmt(hd, type, channel, target, lun, ctx2abort, timeout);
if (rc) {
printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt failed!\n", hd->ioc->name);
} else {
@@ -2029,7 +2000,7 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, in
ioc->reload_fw || (ioc->alt_ioc && ioc->alt_ioc->reload_fw))) {
dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n",
hd->ioc->name));
- rc = mpt_HardResetHandler(hd->ioc, sleepFlag);
+ rc = mpt_HardResetHandler(hd->ioc, CAN_SLEEP);
}
dtmprintk((MYIOC_s_INFO_FMT "TMHandler rc = %d!\n", hd->ioc->name, rc));
@@ -2046,7 +2017,6 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, in
* @target: Logical Target ID for reset (if appropriate)
* @lun: Logical Unit for reset (if appropriate)
* @ctx2abort: Context for the task to be aborted (if appropriate)
- * @sleepFlag: If set, use udelay instead of schedule in handshake code.
*
* Remark: _HardResetHandler can be invoked from an interrupt thread (timer)
* or a non-interrupt thread. In the former, must not call schedule().
@@ -2057,7 +2027,7 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, in
* else other non-zero value returned.
*/
static int
-mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout, int sleepFlag)
+mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout)
{
MPT_FRAME_HDR *mf;
SCSITaskMgmt_t *pScsiTm;
@@ -2087,7 +2057,7 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun
pScsiTm->TaskType = type;
pScsiTm->Reserved1 = 0;
pScsiTm->MsgFlags = (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS)
- ? MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION : 0;
+ ? MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION : 0;
for (ii= 0; ii < 8; ii++) {
pScsiTm->LUN[ii] = 0;
@@ -2099,29 +2069,32 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun
pScsiTm->TaskMsgContext = ctx2abort;
- /* MPI v0.10 requires SCSITaskMgmt requests be sent via Doorbell/handshake
- mpt_put_msg_frame(hd->ioc->id, mf);
- * Save the MF pointer in case the request times out.
- */
- hd->tmPtr = mf;
- hd->TMtimer.expires = jiffies + timeout;
- add_timer(&hd->TMtimer);
-
- dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt: ctx2abort (0x%08x) type=%d\n",
- hd->ioc->name, ctx2abort, type));
+ dtmprintk((MYIOC_s_INFO_FMT
+ "IssueTaskMgmt: ctx2abort (0x%08x) type=%d\n",
+ hd->ioc->name, ctx2abort, type));
DBG_DUMP_TM_REQUEST_FRAME((u32 *)pScsiTm);
if ((retval = mpt_send_handshake_request(ScsiTaskCtx, hd->ioc,
- sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, sleepFlag))
- != 0) {
+ sizeof(SCSITaskMgmt_t), (u32*)pScsiTm,
+ CAN_SLEEP)) != 0) {
dfailprintk((MYIOC_s_ERR_FMT "_send_handshake FAILED!"
- " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd, hd->ioc, mf));
- hd->tmPtr = NULL;
- del_timer(&hd->TMtimer);
+ " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd,
+ hd->ioc, mf));
mpt_free_msg_frame(hd->ioc, mf);
+ return retval;
}
-
+
+ if(mptscsih_tm_wait_for_completion(hd, timeout) == FAILED) {
+ dfailprintk((MYIOC_s_ERR_FMT "_wait_for_completion FAILED!"
+ " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd,
+ hd->ioc, mf));
+ mpt_free_msg_frame(hd->ioc, mf);
+ dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n",
+ hd->ioc->name));
+ retval = mpt_HardResetHandler(hd->ioc, CAN_SLEEP);
+ }
+
return retval;
}
@@ -2187,13 +2160,13 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
*/
mf = MPT_INDEX_2_MFPTR(hd->ioc, scpnt_idx);
ctx2abort = mf->u.frame.hwhdr.msgctxu.MsgContext;
-
+
hd->abortSCpnt = SCpnt;
spin_unlock_irq(host_lock);
if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
SCpnt->device->channel, SCpnt->device->id, SCpnt->device->lun,
- ctx2abort, (HZ*2) /* 2 second timeout */,CAN_SLEEP)
+ ctx2abort, 2 /* 2 second timeout */)
< 0) {
/* The TM request failed and the subsequent FW-reload failed!
@@ -2206,7 +2179,7 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
*/
hd->tmPending = 0;
hd->tmState = TM_STATE_NONE;
-
+
spin_lock_irq(host_lock);
/* Unmap the DMA buffers, if any. */
@@ -2226,7 +2199,6 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
}
spin_lock_irq(host_lock);
return SUCCESS;
-
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -2259,15 +2231,10 @@ mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
printk(KERN_WARNING MYNAM ": %s: >> Attempting target reset! (sc=%p)\n",
hd->ioc->name, SCpnt);
- /* Supported for FC only.
- */
- if (hd->ioc->bus_type == SCSI)
- return FAILED;
-
spin_unlock_irq(host_lock);
if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
SCpnt->device->channel, SCpnt->device->id,
- 0, 0, (HZ*5) /* 5 second timeout */, CAN_SLEEP)
+ 0, 0, 5 /* 5 second timeout */)
< 0){
/* The TM request failed and the subsequent FW-reload failed!
* Fatal error case.
@@ -2317,7 +2284,7 @@ mptscsih_bus_reset(struct scsi_cmnd * SCpnt)
/* We are now ready to execute the task management request. */
spin_unlock_irq(host_lock);
if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
- SCpnt->device->channel, 0, 0, 0, (HZ*5) /* 5 second timeout */, CAN_SLEEP)
+ SCpnt->device->channel, 0, 0, 0, 5 /* 5 second timeout */)
< 0){
/* The TM request failed and the subsequent FW-reload failed!
@@ -2398,7 +2365,7 @@ static int
mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd)
{
unsigned long flags;
- int loop_count = 10 * 4; /* Wait 10 seconds */
+ int loop_count = 4 * 10; /* Wait 10 seconds */
int status = FAILED;
do {
@@ -2406,8 +2373,8 @@ mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd)
if (hd->tmState == TM_STATE_NONE) {
hd->tmState = TM_STATE_IN_PROGRESS;
hd->tmPending = 1;
- spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
status = SUCCESS;
+ spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
break;
}
spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
@@ -2419,6 +2386,34 @@ mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd)
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/**
+ * mptscsih_tm_wait_for_completion - wait for completion of TM task
+ * @hd: Pointer to MPT host structure.
+ *
+ * Returns {SUCCESS,FAILED}.
+ */
+static int
+mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout )
+{
+ unsigned long flags;
+ int loop_count = 4 * timeout;
+ int status = FAILED;
+
+ do {
+ spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
+ if(hd->tmPending == 0) {
+ status = SUCCESS;
+ spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
+ break;
+ }
+ spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
+ msleep_interruptible(250);
+ } while (--loop_count);
+
+ return status;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
* mptscsih_taskmgmt_complete - Registered with Fusion MPT base driver
* @ioc: Pointer to MPT_ADAPTER structure
* @mf: Pointer to SCSI task mgmt request frame
@@ -2449,9 +2444,6 @@ mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *m
* Decrement count of outstanding TM requests.
*/
hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
- if (hd->tmPtr) {
- del_timer(&hd->TMtimer);
- }
} else {
dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt Complete: NULL Scsi Host Ptr\n",
ioc->name));
@@ -2505,7 +2497,6 @@ mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *m
}
}
- hd->tmPtr = NULL;
spin_lock_irqsave(&ioc->FreeQlock, flags);
hd->tmPending = 0;
spin_unlock_irqrestore(&ioc->FreeQlock, flags);
@@ -2913,14 +2904,6 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
mpt_free_msg_frame(ioc, hd->cmdPtr);
}
- /* 2d. If a task management has not completed,
- * free resources associated with this request.
- */
- if (hd->tmPtr) {
- del_timer(&hd->TMtimer);
- mpt_free_msg_frame(ioc, hd->tmPtr);
- }
-
dtmprintk((MYIOC_s_WARN_FMT "Pre-Reset complete.\n", ioc->name));
} else {
@@ -2942,12 +2925,6 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
/* 2. Chain Buffer initialization
*/
- /* 3. tmPtr clear
- */
- if (hd->tmPtr) {
- hd->tmPtr = NULL;
- }
-
/* 4. Renegotiate to all devices, if SCSI
*/
if (ioc->bus_type == SCSI) {
@@ -3172,6 +3149,18 @@ mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char *
dinitprintk((MYIOC_s_INFO_FMT "initTarget bus=%d id=%d lun=%d hd=%p\n",
hd->ioc->name, bus_id, target_id, lun, hd));
+ /*
+ * If the peripheral qualifier filter is enabled then if the target reports a 0x1
+ * (i.e. The targer is capable of supporting the specified peripheral device type
+ * on this logical unit; however, the physical device is not currently connected
+ * to this logical unit) it will be converted to a 0x3 (i.e. The target is not
+ * capable of supporting a physical device on this logical unit). This is to work
+ * around a bug in th emid-layer in some distributions in which the mid-layer will
+ * continue to try to communicate to the LUN and evntually create a dummy LUN.
+ */
+ if (mpt_pq_filter && dlen && (data[0] & 0xE0))
+ data[0] |= 0x40;
+
/* Is LUN supported? If so, upper 2 bits will be 0
* in first byte of inquiry data.
*/
@@ -3811,60 +3800,6 @@ mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus)
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/* mptscsih_taskmgmt_timeout - Call back for timeout on a
- * task management request.
- * @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
- *
- */
-static void mptscsih_taskmgmt_timeout(unsigned long data)
-{
- MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) data;
-
- dtmprintk((KERN_WARNING MYNAM ": %s: mptscsih_taskmgmt_timeout: "
- "TM request timed out!\n", hd->ioc->name));
-
- /* Delete the timer that triggered this callback.
- * Remark: del_timer checks to make sure timer is active
- * before deleting.
- */
- del_timer(&hd->TMtimer);
-
- /* Call the reset handler. Already had a TM request
- * timeout - so issue a diagnostic reset
- */
- INIT_WORK(&mptscsih_rstTask, mptscsih_schedule_reset, (void *)hd);
- schedule_work(&mptscsih_rstTask);
- return;
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/* mptscsih_schedule_reset - Call back for timeout on a
- * task management request.
- * @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
- *
- */
-static void
-mptscsih_schedule_reset(void *arg)
-{
- MPT_SCSI_HOST *hd;
- hd = (MPT_SCSI_HOST *) arg;
-
- if (mpt_HardResetHandler(hd->ioc, CAN_SLEEP) < 0) {
- printk((KERN_WARNING " Firmware Reload FAILED!!\n"));
- } else {
- /* Because we have reset the IOC, no TM requests can be
- * pending. So let's make sure the tmPending flag is reset.
- */
- dtmprintk((KERN_WARNING MYNAM
- ": %s: mptscsih_taskmgmt_timeout\n",
- hd->ioc->name));
- hd->tmPending = 0;
- }
-
- return;
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
* Bus Scan and Domain Validation functionality ...
*/
@@ -5222,7 +5157,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
}
ddvprintk((MYIOC_s_NOTE_FMT "DV: Basic test on id=%d completed OK.\n", ioc->name, id));
- if (driver_setup.dv == 0)
+ if (mpt_dv == 0)
goto target_done;
inq0 = (*pbuf1) & 0x1F;
diff --git a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h
index 893f3c761f286..5cb2fd45c38f1 100644
--- a/drivers/message/fusion/mptscsih.h
+++ b/drivers/message/fusion/mptscsih.h
@@ -91,12 +91,4 @@
#define MPTSCSIH_MIN_SYNC 0x08
#define MPTSCSIH_SAF_TE 0
-struct mptscsih_driver_setup
-{
- u8 dv;
- u8 max_width;
- u8 min_sync_factor;
- u8 saf_te;
-};
-
#endif
diff --git a/drivers/message/i2o/pci.c b/drivers/message/i2o/pci.c
index b3fc7f27468a0..e772752f056d3 100644
--- a/drivers/message/i2o/pci.c
+++ b/drivers/message/i2o/pci.c
@@ -525,3 +525,4 @@ void __exit i2o_pci_exit(void)
};
EXPORT_SYMBOL(i2o_dma_realloc);
+MODULE_DEVICE_TABLE(pci, i2o_pci_ids);
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 67775b7bb35d0..19c2b85249c30 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -4,3 +4,4 @@
obj- := misc.o # Dummy rule to force built-in.o to be made
obj-$(CONFIG_IBM_ASM) += ibmasm/
+obj-$(CONFIG_HDPU_FEATURES) += hdpuftrs/
diff --git a/drivers/misc/hdpuftrs/Makefile b/drivers/misc/hdpuftrs/Makefile
new file mode 100644
index 0000000000000..ac74ae679230b
--- /dev/null
+++ b/drivers/misc/hdpuftrs/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_HDPU_FEATURES) := hdpu_cpustate.o hdpu_nexus.o
diff --git a/drivers/misc/hdpuftrs/hdpu_cpustate.c b/drivers/misc/hdpuftrs/hdpu_cpustate.c
new file mode 100644
index 0000000000000..7501fab349e4c
--- /dev/null
+++ b/drivers/misc/hdpuftrs/hdpu_cpustate.c
@@ -0,0 +1,234 @@
+/*
+ * Sky CPU State Driver
+ *
+ * Copyright (C) 2002 Brian Waite
+ *
+ * This driver allows use of the CPU state bits
+ * It exports the /dev/sky_cpustate and also
+ * /proc/sky_cpustate pseudo-file for status 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/version.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/miscdevice.h>
+#include <linux/pci.h>
+#include <linux/proc_fs.h>
+#include <linux/device.h>
+#include <asm/uaccess.h>
+#include <linux/hdpu_features.h>
+
+#define SKY_CPUSTATE_VERSION "1.1"
+
+static int hdpu_cpustate_probe(struct device *ddev);
+static int hdpu_cpustate_remove(struct device *ddev);
+
+struct cpustate_t cpustate;
+
+static int cpustate_get_ref(int excl)
+{
+
+ int retval = -EBUSY;
+
+ spin_lock(&cpustate.lock);
+
+ if (cpustate.excl)
+ goto out_busy;
+
+ if (excl) {
+ if (cpustate.open_count)
+ goto out_busy;
+ cpustate.excl = 1;
+ }
+
+ cpustate.open_count++;
+ retval = 0;
+
+ out_busy:
+ spin_unlock(&cpustate.lock);
+ return retval;
+}
+
+static int cpustate_free_ref(void)
+{
+
+ spin_lock(&cpustate.lock);
+
+ cpustate.excl = 0;
+ cpustate.open_count--;
+
+ spin_unlock(&cpustate.lock);
+ return 0;
+}
+
+unsigned char cpustate_get_state(void)
+{
+
+ return cpustate.cached_val;
+}
+
+void cpustate_set_state(unsigned char new_state)
+{
+ unsigned int state = (new_state << 21);
+
+#ifdef DEBUG_CPUSTATE
+ printk("CPUSTATE -> 0x%x\n", new_state);
+#endif
+ spin_lock(&cpustate.lock);
+ cpustate.cached_val = new_state;
+ writel((0xff << 21), cpustate.clr_addr);
+ writel(state, cpustate.set_addr);
+ spin_unlock(&cpustate.lock);
+}
+
+/*
+ * Now all the various file operations that we export.
+ */
+
+static ssize_t cpustate_read(struct file *file, char *buf,
+ size_t count, loff_t * ppos)
+{
+ unsigned char data;
+
+ if (count < 0)
+ return -EFAULT;
+ if (count == 0)
+ return 0;
+
+ data = cpustate_get_state();
+ if (copy_to_user(buf, &data, sizeof(unsigned char)))
+ return -EFAULT;
+ return sizeof(unsigned char);
+}
+
+static ssize_t cpustate_write(struct file *file, const char *buf,
+ size_t count, loff_t * ppos)
+{
+ unsigned char data;
+
+ if (count < 0)
+ return -EFAULT;
+
+ if (count == 0)
+ return 0;
+
+ if (copy_from_user((unsigned char *)&data, buf, sizeof(unsigned char)))
+ return -EFAULT;
+
+ cpustate_set_state(data);
+ return sizeof(unsigned char);
+}
+
+static int cpustate_open(struct inode *inode, struct file *file)
+{
+ return cpustate_get_ref((file->f_flags & O_EXCL));
+}
+
+static int cpustate_release(struct inode *inode, struct file *file)
+{
+ return cpustate_free_ref();
+}
+
+/*
+ * Info exported via "/proc/sky_cpustate".
+ */
+static int cpustate_read_proc(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ char *p = page;
+ int len = 0;
+
+ p += sprintf(p, "CPU State: %04x\n", cpustate_get_state());
+ len = p - page;
+
+ if (len <= off + count)
+ *eof = 1;
+ *start = page + off;
+ len -= off;
+ if (len > count)
+ len = count;
+ if (len < 0)
+ len = 0;
+ return len;
+}
+
+static struct device_driver hdpu_cpustate_driver = {
+ .name = HDPU_CPUSTATE_NAME,
+ .bus = &platform_bus_type,
+ .probe = hdpu_cpustate_probe,
+ .remove = hdpu_cpustate_remove,
+};
+
+/*
+ * The various file operations we support.
+ */
+static struct file_operations cpustate_fops = {
+ owner:THIS_MODULE,
+ open:cpustate_open,
+ release:cpustate_release,
+ read:cpustate_read,
+ write:cpustate_write,
+ fasync:NULL,
+ poll:NULL,
+ ioctl:NULL,
+ llseek:no_llseek,
+
+};
+
+static struct miscdevice cpustate_dev = {
+ MISC_DYNAMIC_MINOR,
+ "sky_cpustate",
+ &cpustate_fops
+};
+
+static int hdpu_cpustate_probe(struct device *ddev)
+{
+ struct platform_device *pdev = to_platform_device(ddev);
+ struct resource *res;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ cpustate.set_addr = (unsigned long *)res->start;
+ cpustate.clr_addr = (unsigned long *)res->end - 1;
+
+ misc_register(&cpustate_dev);
+ create_proc_read_entry("sky_cpustate", 0, 0, cpustate_read_proc, NULL);
+
+ printk(KERN_INFO "Sky CPU State Driver v" SKY_CPUSTATE_VERSION "\n");
+ return 0;
+}
+static int hdpu_cpustate_remove(struct device *ddev)
+{
+
+ cpustate.set_addr = 0;
+ cpustate.clr_addr = 0;
+
+ remove_proc_entry("sky_cpustate", NULL);
+ misc_deregister(&cpustate_dev);
+ return 0;
+
+}
+
+static int __init cpustate_init(void)
+{
+ int rc;
+ rc = driver_register(&hdpu_cpustate_driver);
+ return rc;
+}
+
+static void __exit cpustate_exit(void)
+{
+ driver_unregister(&hdpu_cpustate_driver);
+}
+
+module_init(cpustate_init);
+module_exit(cpustate_exit);
+
+MODULE_AUTHOR("Brian Waite");
+MODULE_LICENSE("GPL");
diff --git a/drivers/misc/hdpuftrs/hdpu_nexus.c b/drivers/misc/hdpuftrs/hdpu_nexus.c
new file mode 100644
index 0000000000000..c203b27269ea7
--- /dev/null
+++ b/drivers/misc/hdpuftrs/hdpu_nexus.c
@@ -0,0 +1,111 @@
+/*
+ * Sky Nexus Register Driver
+ *
+ * Copyright (C) 2002 Brian Waite
+ *
+ * This driver allows reading the Nexus register
+ * It exports the /proc/sky_chassis_id and also
+ * /proc/sky_slot_id pseudo-file for status 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/version.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/proc_fs.h>
+#include <linux/hdpu_features.h>
+#include <linux/pci.h>
+
+#include <linux/device.h>
+
+static int hdpu_nexus_probe(struct device *ddev);
+static int hdpu_nexus_remove(struct device *ddev);
+
+static struct proc_dir_entry *hdpu_slot_id;
+static struct proc_dir_entry *hdpu_chassis_id;
+static int slot_id = -1;
+static int chassis_id = -1;
+
+static struct device_driver hdpu_nexus_driver = {
+ .name = HDPU_NEXUS_NAME,
+ .bus = &platform_bus_type,
+ .probe = hdpu_nexus_probe,
+ .remove = hdpu_nexus_remove,
+};
+
+int hdpu_slot_id_read(char *buffer, char **buffer_location, off_t offset,
+ int buffer_length, int *zero, void *ptr)
+{
+
+ if (offset > 0)
+ return 0;
+ return sprintf(buffer, "%d\n", slot_id);
+}
+
+int hdpu_chassis_id_read(char *buffer, char **buffer_location, off_t offset,
+ int buffer_length, int *zero, void *ptr)
+{
+
+ if (offset > 0)
+ return 0;
+ return sprintf(buffer, "%d\n", chassis_id);
+}
+
+static int hdpu_nexus_probe(struct device *ddev)
+{
+ struct platform_device *pdev = to_platform_device(ddev);
+ struct resource *res;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ int *nexus_id_addr;
+ nexus_id_addr =
+ ioremap(res->start, (unsigned long)(res->end - res->start));
+ if (nexus_id_addr) {
+ slot_id = (*nexus_id_addr >> 8) & 0x1f;
+ chassis_id = *nexus_id_addr & 0xff;
+ iounmap(nexus_id_addr);
+ } else
+ printk("Could not map slot id\n");
+ hdpu_slot_id = create_proc_entry("sky_slot_id", 0666, &proc_root);
+ hdpu_slot_id->read_proc = hdpu_slot_id_read;
+ hdpu_slot_id->nlink = 1;
+
+ hdpu_chassis_id = create_proc_entry("sky_chassis_id", 0666, &proc_root);
+ hdpu_chassis_id->read_proc = hdpu_chassis_id_read;
+ hdpu_chassis_id->nlink = 1;
+ return 0;
+}
+
+static int hdpu_nexus_remove(struct device *ddev)
+{
+ slot_id = -1;
+ chassis_id = -1;
+ remove_proc_entry("sky_slot_id", &proc_root);
+ remove_proc_entry("sky_chassis_id", &proc_root);
+ hdpu_slot_id = 0;
+ hdpu_chassis_id = 0;
+ return 0;
+}
+
+static int __init nexus_init(void)
+{
+ int rc;
+ rc = driver_register(&hdpu_nexus_driver);
+ return rc;
+}
+
+static void __exit nexus_exit(void)
+{
+ driver_unregister(&hdpu_nexus_driver);
+}
+
+module_init(nexus_init);
+module_exit(nexus_exit);
+
+MODULE_AUTHOR("Brian Waite");
+MODULE_LICENSE("GPL");
diff --git a/drivers/misc/ibmasm/module.c b/drivers/misc/ibmasm/module.c
index c46da50699ba1..777432ae764aa 100644
--- a/drivers/misc/ibmasm/module.c
+++ b/drivers/misc/ibmasm/module.c
@@ -224,4 +224,5 @@ module_exit(ibmasm_exit);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, ibmasm_pci_table);
diff --git a/drivers/mmc/mmc_block.c b/drivers/mmc/mmc_block.c
index ea2927ee4085b..b5b4a7b119034 100644
--- a/drivers/mmc/mmc_block.c
+++ b/drivers/mmc/mmc_block.c
@@ -437,7 +437,7 @@ static void mmc_blk_remove(struct mmc_card *card)
}
#ifdef CONFIG_PM
-static int mmc_blk_suspend(struct mmc_card *card, u32 state)
+static int mmc_blk_suspend(struct mmc_card *card, pm_message_t state)
{
struct mmc_blk_data *md = mmc_get_drvdata(card);
diff --git a/drivers/mmc/mmc_sysfs.c b/drivers/mmc/mmc_sysfs.c
index 2b7ebdac77b48..29a56e9cd5b3a 100644
--- a/drivers/mmc/mmc_sysfs.c
+++ b/drivers/mmc/mmc_sysfs.c
@@ -21,6 +21,41 @@
#define dev_to_mmc_card(d) container_of(d, struct mmc_card, dev)
#define to_mmc_driver(d) container_of(d, struct mmc_driver, drv)
+#define MMC_ATTR(name, fmt, args...) \
+static ssize_t mmc_##name##_show (struct device *dev, char *buf) \
+{ \
+ struct mmc_card *card = dev_to_mmc_card(dev); \
+ return sprintf(buf, fmt, args); \
+}
+
+MMC_ATTR(cid, "%08x%08x%08x%08x\n", card->raw_cid[0], card->raw_cid[1],
+ card->raw_cid[2], card->raw_cid[3]);
+MMC_ATTR(csd, "%08x%08x%08x%08x\n", card->raw_csd[0], card->raw_csd[1],
+ card->raw_csd[2], card->raw_csd[3]);
+MMC_ATTR(date, "%02d/%04d\n", card->cid.month, card->cid.year);
+MMC_ATTR(fwrev, "0x%x\n", card->cid.fwrev);
+MMC_ATTR(hwrev, "0x%x\n", card->cid.hwrev);
+MMC_ATTR(manfid, "0x%06x\n", card->cid.manfid);
+MMC_ATTR(name, "%s\n", card->cid.prod_name);
+MMC_ATTR(oemid, "0x%04x\n", card->cid.oemid);
+MMC_ATTR(serial, "0x%08x\n", card->cid.serial);
+
+#define MMC_ATTR_RO(name) __ATTR(name, S_IRUGO, mmc_##name##_show, NULL)
+
+static struct device_attribute mmc_dev_attrs[] = {
+ MMC_ATTR_RO(cid),
+ MMC_ATTR_RO(csd),
+ MMC_ATTR_RO(date),
+ MMC_ATTR_RO(fwrev),
+ MMC_ATTR_RO(hwrev),
+ MMC_ATTR_RO(manfid),
+ MMC_ATTR_RO(name),
+ MMC_ATTR_RO(oemid),
+ MMC_ATTR_RO(serial),
+ __ATTR_NULL
+};
+
+
static void mmc_release_card(struct device *dev)
{
struct mmc_card *card = dev_to_mmc_card(dev);
@@ -74,7 +109,7 @@ mmc_bus_hotplug(struct device *dev, char **envp, int num_envp, char *buf,
return 0;
}
-static int mmc_bus_suspend(struct device *dev, u32 state)
+static int mmc_bus_suspend(struct device *dev, pm_message_t state)
{
struct mmc_driver *drv = to_mmc_driver(dev->driver);
struct mmc_card *card = dev_to_mmc_card(dev);
@@ -98,6 +133,7 @@ static int mmc_bus_resume(struct device *dev)
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,
@@ -151,38 +187,6 @@ void mmc_unregister_driver(struct mmc_driver *drv)
EXPORT_SYMBOL(mmc_unregister_driver);
-#define MMC_ATTR(name, fmt, args...) \
-static ssize_t mmc_dev_show_##name (struct device *dev, char *buf) \
-{ \
- struct mmc_card *card = dev_to_mmc_card(dev); \
- return sprintf(buf, fmt, args); \
-} \
-static DEVICE_ATTR(name, S_IRUGO, mmc_dev_show_##name, NULL)
-
-MMC_ATTR(cid, "%08x%08x%08x%08x\n", card->raw_cid[0], card->raw_cid[1],
- card->raw_cid[2], card->raw_cid[3]);
-MMC_ATTR(csd, "%08x%08x%08x%08x\n", card->raw_csd[0], card->raw_csd[1],
- card->raw_csd[2], card->raw_csd[3]);
-MMC_ATTR(date, "%02d/%04d\n", card->cid.month, card->cid.year);
-MMC_ATTR(fwrev, "0x%x\n", card->cid.fwrev);
-MMC_ATTR(hwrev, "0x%x\n", card->cid.hwrev);
-MMC_ATTR(manfid, "0x%06x\n", card->cid.manfid);
-MMC_ATTR(name, "%s\n", card->cid.prod_name);
-MMC_ATTR(oemid, "0x%04x\n", card->cid.oemid);
-MMC_ATTR(serial, "0x%08x\n", card->cid.serial);
-
-static struct device_attribute *mmc_dev_attributes[] = {
- &dev_attr_cid,
- &dev_attr_csd,
- &dev_attr_date,
- &dev_attr_fwrev,
- &dev_attr_hwrev,
- &dev_attr_manfid,
- &dev_attr_name,
- &dev_attr_oemid,
- &dev_attr_serial,
-};
-
/*
* Internal function. Initialise a MMC card structure.
*/
@@ -201,17 +205,10 @@ void mmc_init_card(struct mmc_card *card, struct mmc_host *host)
*/
int mmc_register_card(struct mmc_card *card)
{
- int ret, i;
-
snprintf(card->dev.bus_id, sizeof(card->dev.bus_id),
"%s:%04x", card->host->host_name, card->rca);
- ret = device_add(&card->dev);
- if (ret == 0)
- for (i = 0; i < ARRAY_SIZE(mmc_dev_attributes); i++)
- device_create_file(&card->dev, mmc_dev_attributes[i]);
-
- return ret;
+ return device_add(&card->dev);
}
/*
diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
index afd0b67c48e9e..027054dea032b 100644
--- a/drivers/mtd/Kconfig
+++ b/drivers/mtd/Kconfig
@@ -27,6 +27,15 @@ config MTD_DEBUG_VERBOSE
help
Determines the verbosity level of the MTD debugging messages.
+config MTD_CONCAT
+ tristate "MTD concatenating support"
+ depends on MTD
+ help
+ Support for concatenating several MTD devices into a single
+ (virtual) one. This allows you to have -for example- a JFFS(2)
+ file system spanning multiple physical flash chips. If unsure,
+ say 'Y'.
+
config MTD_PARTITIONS
bool "MTD partitioning support"
depends on MTD
@@ -40,15 +49,6 @@ config MTD_PARTITIONS
devices. Partitioning on NFTL 'devices' is a different - that's the
'normal' form of partitioning used on a block device.
-config MTD_CONCAT
- tristate "MTD concatenating support"
- depends on MTD
- help
- Support for concatenating several MTD devices into a single
- (virtual) one. This allows you to have -for example- a JFFS(2)
- file system spanning multiple physical flash chips. If unsure,
- say 'Y'.
-
config MTD_REDBOOT_PARTS
tristate "RedBoot partition table parsing"
depends on MTD_PARTITIONS
diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c
index 1cbdfce588cb5..cfe6ccf07972e 100644
--- a/drivers/mtd/devices/block2mtd.c
+++ b/drivers/mtd/devices/block2mtd.c
@@ -59,7 +59,7 @@ void cache_readahead(struct address_space *mapping, int index)
end_index = ((isize - 1) >> PAGE_CACHE_SHIFT);
- spin_lock_irq(&mapping->tree_lock);
+ read_lock_irq(&mapping->tree_lock);
for (i = 0; i < PAGE_READAHEAD; i++) {
pagei = index + i;
if (pagei > end_index) {
@@ -71,16 +71,16 @@ void cache_readahead(struct address_space *mapping, int index)
break;
if (page)
continue;
- spin_unlock_irq(&mapping->tree_lock);
+ read_unlock_irq(&mapping->tree_lock);
page = page_cache_alloc_cold(mapping);
- spin_lock_irq(&mapping->tree_lock);
+ read_lock_irq(&mapping->tree_lock);
if (!page)
break;
page->index = pagei;
list_add(&page->lru, &page_pool);
ret++;
}
- spin_unlock_irq(&mapping->tree_lock);
+ read_unlock_irq(&mapping->tree_lock);
if (ret)
read_cache_pages(mapping, &page_pool, filler, NULL);
}
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
index f00f24f23ee6a..8480057eadb49 100644
--- a/drivers/mtd/maps/Kconfig
+++ b/drivers/mtd/maps/Kconfig
@@ -159,7 +159,7 @@ config MTD_VMAX
config MTD_SCx200_DOCFLASH
tristate "Flash device mapped with DOCCS on NatSemi SCx200"
- depends on X86 && MTD_CFI && MTD_PARTITIONS
+ depends on SCx200 && MTD_CFI && MTD_PARTITIONS
help
Enable support for a flash chip mapped using the DOCCS signal on a
National Semiconductor SCx200 processor.
@@ -405,14 +405,6 @@ config MTD_REDWOOD
Redwood board. If you have one of these boards and would like to
use the flash chips on it, say 'Y'.
-config MTD_CHESTNUT
- tristate "CFI Flash devices mapped on IBM 750FX or IBM 750GX Eval Boards"
- depends on MTD_CFI && PPC32 && CHESTNUT && MTD_PARTITIONS
- help
- This enables access routines for the flash chips on the IBM
- 750FX and 750GX Eval Boards. If you have one of these boards and
- would like to use the flash chips on it, say 'Y'
-
config MTD_CSTM_MIPS_IXX
tristate "Flash chip mapping on ITE QED-4N-S01B, Globespan IVR or custom board"
depends on MIPS && MTD_CFI && MTD_JEDECPROBE && MTD_PARTITIONS
diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile
index be797693039d2..7ffe02b853016 100644
--- a/drivers/mtd/maps/Makefile
+++ b/drivers/mtd/maps/Makefile
@@ -54,7 +54,6 @@ obj-$(CONFIG_MTD_EDB7312) += edb7312.o
obj-$(CONFIG_MTD_IMPA7) += impa7.o
obj-$(CONFIG_MTD_FORTUNET) += fortunet.o
obj-$(CONFIG_MTD_REDWOOD) += redwood.o
-obj-$(CONFIG_MTD_CHESTNUT) += chestnut.o
obj-$(CONFIG_MTD_UCLINUX) += uclinux.o
obj-$(CONFIG_MTD_NETtel) += nettel.o
obj-$(CONFIG_MTD_SCB2_FLASH) += scb2_flash.o
diff --git a/drivers/mtd/maps/chestnut.c b/drivers/mtd/maps/chestnut.c
deleted file mode 100644
index 1cb5f15272796..0000000000000
--- a/drivers/mtd/maps/chestnut.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * drivers/mtd/maps/chestnut.c
- *
- * $Id: chestnut.c,v 1.1 2005/01/05 16:59:50 dwmw2 Exp $
- *
- * Flash map driver for IBM Chestnut (750FXGX Eval)
- *
- * Chose not to enable 8 bit flash as it contains the firmware and board
- * info. Thus only the 32bit flash is supported.
- *
- * Author: <source@mvista.com>
- *
- * 2004 (c) MontaVista Software, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <asm/io.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/map.h>
-#include <linux/mtd/partitions.h>
-#include <platforms/chestnut.h>
-
-static struct map_info chestnut32_map = {
- .name = "User FS",
- .size = CHESTNUT_32BIT_SIZE,
- .bankwidth = 4,
- .phys = CHESTNUT_32BIT_BASE,
-};
-
-static struct mtd_partition chestnut32_partitions[] = {
- {
- .name = "User FS",
- .offset = 0,
- .size = CHESTNUT_32BIT_SIZE,
- }
-};
-
-static struct mtd_info *flash32;
-
-int __init init_chestnut(void)
-{
- /* 32-bit FLASH */
-
- chestnut32_map.virt = ioremap(chestnut32_map.phys, chestnut32_map.size);
-
- if (!chestnut32_map.virt) {
- printk(KERN_NOTICE "Failed to ioremap 32-bit flash\n");
- return -EIO;
- }
-
- simple_map_init(&chestnut32_map);
-
- flash32 = do_map_probe("cfi_probe", &chestnut32_map);
- if (flash32) {
- flash32->owner = THIS_MODULE;
- add_mtd_partitions(flash32, chestnut32_partitions,
- ARRAY_SIZE(chestnut32_partitions));
- } else {
- printk(KERN_NOTICE "map probe failed for 32-bit flash\n");
- return -ENXIO;
- }
-
- return 0;
-}
-
-static void __exit
-cleanup_chestnut(void)
-{
- if (flash32) {
- del_mtd_partitions(flash32);
- map_destroy(flash32);
- }
-
- if (chestnut32_map.virt) {
- iounmap((void *)chestnut32_map.virt);
- chestnut32_map.virt = 0;
- }
-}
-
-module_init(init_chestnut);
-module_exit(cleanup_chestnut);
-
-MODULE_DESCRIPTION("MTD map and partitions for IBM Chestnut (750fxgx Eval)");
-MODULE_AUTHOR("<source@mvista.com>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/mtd/maps/ich2rom.c b/drivers/mtd/maps/ich2rom.c
deleted file mode 100644
index 2f3e9e2f22054..0000000000000
--- a/drivers/mtd/maps/ich2rom.c
+++ /dev/null
@@ -1,316 +0,0 @@
-/*
- * ich2rom.c
- *
- * Normal mappings of chips in physical memory
- * $Id: ich2rom.c,v 1.7 2003/05/21 12:45:18 dwmw2 Exp $
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <asm/io.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/map.h>
-#include <linux/config.h>
-#include <linux/pci.h>
-#include <linux/pci_ids.h>
-
-#define RESERVE_MEM_REGION 0
-
-#define ICH2_FWH_REGION_START 0xFF000000UL
-#define ICH2_FWH_REGION_SIZE 0x01000000UL
-#define BIOS_CNTL 0x4e
-#define FWH_DEC_EN1 0xE3
-#define FWH_DEC_EN2 0xF0
-#define FWH_SEL1 0xE8
-#define FWH_SEL2 0xEE
-
-struct ich2rom_map_info {
- struct map_info map;
- struct mtd_info *mtd;
- unsigned long window_addr;
-};
-
-static inline unsigned long addr(struct map_info *map, unsigned long ofs)
-{
- unsigned long offset;
- offset = ((8*1024*1024) - map->size) + ofs;
- if (offset >= (4*1024*1024)) {
- offset += 0x400000;
- }
- return map->map_priv_1 + 0x400000 + offset;
-}
-
-static inline unsigned long dbg_addr(struct map_info *map, unsigned long addr)
-{
- return addr - map->map_priv_1 + ICH2_FWH_REGION_START;
-}
-
-static __u8 ich2rom_read8(struct map_info *map, unsigned long ofs)
-{
- return __raw_readb(addr(map, ofs));
-}
-
-static __u16 ich2rom_read16(struct map_info *map, unsigned long ofs)
-{
- return __raw_readw(addr(map, ofs));
-}
-
-static __u32 ich2rom_read32(struct map_info *map, unsigned long ofs)
-{
- return __raw_readl(addr(map, ofs));
-}
-
-static void ich2rom_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
-{
- memcpy_fromio(to, addr(map, from), len);
-}
-
-static void ich2rom_write8(struct map_info *map, __u8 d, unsigned long ofs)
-{
- __raw_writeb(d, addr(map,ofs));
- mb();
-}
-
-static void ich2rom_write16(struct map_info *map, __u16 d, unsigned long ofs)
-{
- __raw_writew(d, addr(map, ofs));
- mb();
-}
-
-static void ich2rom_write32(struct map_info *map, __u32 d, unsigned long ofs)
-{
- __raw_writel(d, addr(map, ofs));
- mb();
-}
-
-static void ich2rom_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
-{
- memcpy_toio(addr(map, to), from, len);
-}
-
-static struct ich2rom_map_info ich2rom_map = {
- .map = {
- .name = "ICH2 rom",
- .phys = NO_XIP,
- .size = 0,
- .buswidth = 1,
- .read8 = ich2rom_read8,
- .read16 = ich2rom_read16,
- .read32 = ich2rom_read32,
- .copy_from = ich2rom_copy_from,
- .write8 = ich2rom_write8,
- .write16 = ich2rom_write16,
- .write32 = ich2rom_write32,
- .copy_to = ich2rom_copy_to,
- /* Firmware hubs only use vpp when being programmed
- * in a factory setting. So in place programming
- * needs to use a different method.
- */
- },
- .mtd = NULL,
- .window_addr = 0,
-};
-
-enum fwh_lock_state {
- FWH_DENY_WRITE = 1,
- FWH_IMMUTABLE = 2,
- FWH_DENY_READ = 4,
-};
-
-static int ich2rom_set_lock_state(struct mtd_info *mtd, loff_t ofs, size_t len,
- enum fwh_lock_state state)
-{
- struct map_info *map = mtd->priv;
- unsigned long start = ofs;
- unsigned long end = start + len -1;
-
- /* FIXME do I need to guard against concurrency here? */
- /* round down to 64K boundaries */
- start = start & ~0xFFFF;
- end = end & ~0xFFFF;
- while (start <= end) {
- unsigned long ctrl_addr;
- ctrl_addr = addr(map, start) - 0x400000 + 2;
- writeb(state, ctrl_addr);
- start = start + 0x10000;
- }
- return 0;
-}
-
-static int ich2rom_lock(struct mtd_info *mtd, loff_t ofs, size_t len)
-{
- return ich2rom_set_lock_state(mtd, ofs, len, FWH_DENY_WRITE);
-}
-
-static int ich2rom_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
-{
- return ich2rom_set_lock_state(mtd, ofs, len, 0);
-}
-
-static int __devinit ich2rom_init_one (struct pci_dev *pdev,
- const struct pci_device_id *ent)
-{
- u16 word;
- struct ich2rom_map_info *info = &ich2rom_map;
- unsigned long map_size;
-
- /* For now I just handle the ich2 and I assume there
- * are not a lot of resources up at the top of the address
- * space. It is possible to handle other devices in the
- * top 16MB but it is very painful. Also since
- * you can only really attach a FWH to an ICH2 there
- * a number of simplifications you can make.
- *
- * Also you can page firmware hubs if an 8MB window isn't enough
- * but don't currently handle that case either.
- */
-
-#if RESERVE_MEM_REGION
- /* Some boards have this reserved and I haven't found a good work
- * around to say I know what I'm doing!
- */
- if (!request_mem_region(ICH2_FWH_REGION_START, ICH2_FWH_REGION_SIZE, "ich2rom")) {
- printk(KERN_ERR "ich2rom: cannot reserve rom window\n");
- goto err_out_none;
- }
-#endif /* RESERVE_MEM_REGION */
-
- /* Enable writes through the rom window */
- pci_read_config_word(pdev, BIOS_CNTL, &word);
- if (!(word & 1) && (word & (1<<1))) {
- /* The BIOS will generate an error if I enable
- * this device, so don't even try.
- */
- printk(KERN_ERR "ich2rom: firmware access control, I can't enable writes\n");
- goto err_out_none;
- }
- pci_write_config_word(pdev, BIOS_CNTL, word | 1);
-
-
- /* Map the firmware hub into my address space. */
- /* Does this use to much virtual address space? */
- info->window_addr = (unsigned long)ioremap(
- ICH2_FWH_REGION_START, ICH2_FWH_REGION_SIZE);
- if (!info->window_addr) {
- printk(KERN_ERR "Failed to ioremap\n");
- goto err_out_free_mmio_region;
- }
-
- /* For now assume the firmware has setup all relevant firmware
- * windows. We don't have enough information to handle this case
- * intelligently.
- */
-
- /* FIXME select the firmware hub and enable a window to it. */
-
- info->mtd = NULL;
- info->map.map_priv_1 = info->window_addr;
-
- map_size = ICH2_FWH_REGION_SIZE;
- while(!info->mtd && (map_size > 0)) {
- info->map.size = map_size;
- info->mtd = do_map_probe("jedec_probe", &ich2rom_map.map);
- map_size -= 512*1024;
- }
- if (!info->mtd) {
- goto err_out_iounmap;
- }
- /* I know I can only be a firmware hub here so put
- * in the special lock and unlock routines.
- */
- info->mtd->lock = ich2rom_lock;
- info->mtd->unlock = ich2rom_unlock;
-
- info->mtd->owner = THIS_MODULE;
- add_mtd_device(info->mtd);
- return 0;
-
-err_out_iounmap:
- iounmap((void *)(info->window_addr));
-err_out_free_mmio_region:
-#if RESERVE_MEM_REGION
- release_mem_region(ICH2_FWH_REGION_START, ICH2_FWH_REGION_SIZE);
-#endif
-err_out_none:
- return -ENODEV;
-}
-
-
-static void __devexit ich2rom_remove_one (struct pci_dev *pdev)
-{
- struct ich2rom_map_info *info = &ich2rom_map;
- u16 word;
-
- del_mtd_device(info->mtd);
- map_destroy(info->mtd);
- info->mtd = NULL;
- info->map.map_priv_1 = 0;
-
- iounmap((void *)(info->window_addr));
- info->window_addr = 0;
-
- /* Disable writes through the rom window */
- pci_read_config_word(pdev, BIOS_CNTL, &word);
- pci_write_config_word(pdev, BIOS_CNTL, word & ~1);
-
-#if RESERVE_MEM_REGION
- release_mem_region(ICH2_FWH_REGION_START, ICH2_FWH_REGION_SIZE);
-#endif
-}
-
-static struct pci_device_id ich2rom_pci_tbl[] = {
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0,
- PCI_ANY_ID, PCI_ANY_ID, },
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0,
- PCI_ANY_ID, PCI_ANY_ID, },
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0,
- PCI_ANY_ID, PCI_ANY_ID, },
- { 0, },
-};
-
-MODULE_DEVICE_TABLE(pci, ich2rom_pci_tbl);
-
-#if 0
-static struct pci_driver ich2rom_driver = {
- .name = "ich2rom",
- .id_table = ich2rom_pci_tbl,
- .probe = ich2rom_init_one,
- .remove = ich2rom_remove_one,
-};
-#endif
-
-static struct pci_dev *mydev;
-int __init init_ich2rom(void)
-{
- struct pci_dev *pdev;
- struct pci_device_id *id;
- pdev = NULL;
- for(id = ich2rom_pci_tbl; id->vendor; id++) {
- pdev = pci_find_device(id->vendor, id->device, NULL);
- if (pdev) {
- break;
- }
- }
- if (pdev) {
- mydev = pdev;
- return ich2rom_init_one(pdev, &ich2rom_pci_tbl[0]);
- }
- return -ENXIO;
-#if 0
- return pci_module_init(&ich2rom_driver);
-#endif
-}
-
-static void __exit cleanup_ich2rom(void)
-{
- ich2rom_remove_one(mydev);
-}
-
-module_init(init_ich2rom);
-module_exit(cleanup_ich2rom);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Eric Biederman <ebiederman@lnxi.com>");
-MODULE_DESCRIPTION("MTD map driver for BIOS chips on the ICH2 southbridge");
diff --git a/drivers/mtd/maps/scx200_docflash.c b/drivers/mtd/maps/scx200_docflash.c
index 62df7e6f00e10..0ece3786d6ea5 100644
--- a/drivers/mtd/maps/scx200_docflash.c
+++ b/drivers/mtd/maps/scx200_docflash.c
@@ -92,17 +92,16 @@ static int __init init_scx200_docflash(void)
PCI_DEVICE_ID_NS_SCx200_BRIDGE,
NULL)) == NULL)
return -ENODEV;
-
- if (!scx200_cb_probe(SCx200_CB_BASE)) {
- printk(KERN_WARNING NAME ": no configuration block found\n");
+
+ /* check that we have found the configuration block */
+ if (!scx200_cb_present())
return -ENODEV;
- }
if (probe) {
/* Try to use the present flash mapping if any */
pci_read_config_dword(bridge, SCx200_DOCCS_BASE, &base);
pci_read_config_dword(bridge, SCx200_DOCCS_CTRL, &ctrl);
- pmr = inl(SCx200_CB_BASE + SCx200_PMR);
+ pmr = inl(scx200_cb_base + SCx200_PMR);
if (base == 0
|| (ctrl & 0x07000000) != 0x07000000
@@ -155,14 +154,14 @@ static int __init init_scx200_docflash(void)
pci_write_config_dword(bridge, SCx200_DOCCS_BASE, docmem.start);
pci_write_config_dword(bridge, SCx200_DOCCS_CTRL, ctrl);
- pmr = inl(SCx200_CB_BASE + SCx200_PMR);
+ pmr = inl(scx200_cb_base + SCx200_PMR);
if (width == 8) {
pmr &= ~(1<<6);
} else {
pmr |= (1<<6);
}
- outl(pmr, SCx200_CB_BASE + SCx200_PMR);
+ outl(pmr, scx200_cb_base + SCx200_PMR);
}
printk(KERN_INFO NAME ": DOCCS mapped at 0x%lx-0x%lx, width %d\n",
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index 3792140054177..510ad78312cc6 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -285,12 +285,12 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
size = (cmd & IOCSIZE_MASK) >> IOCSIZE_SHIFT;
if (cmd & IOC_IN) {
- ret = verify_area(VERIFY_READ, argp, size);
- if (ret) return ret;
+ if (!access_ok(VERIFY_READ, argp, size))
+ return -EFAULT;
}
if (cmd & IOC_OUT) {
- ret = verify_area(VERIFY_WRITE, argp, size);
- if (ret) return ret;
+ if (!access_ok(VERIFY_WRITE, argp, size))
+ return -EFAULT;
}
switch (cmd) {
@@ -389,7 +389,8 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
if (!mtd->write_oob)
ret = -EOPNOTSUPP;
else
- ret = verify_area(VERIFY_READ, buf.ptr, buf.length);
+ ret = access_ok(VERIFY_READ, buf.ptr,
+ buf.length) ? 0 : EFAULT;
if (ret)
return ret;
@@ -428,7 +429,8 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
if (!mtd->read_oob)
ret = -EOPNOTSUPP;
else
- ret = verify_area(VERIFY_WRITE, buf.ptr, buf.length);
+ ret = access_ok(VERIFY_WRITE, buf.ptr,
+ buf.length) ? 0 : -EFAULT;
if (ret)
return ret;
diff --git a/drivers/net/3c503.c b/drivers/net/3c503.c
index 4453fe43b5e5d..29dfd47f41d2b 100644
--- a/drivers/net/3c503.c
+++ b/drivers/net/3c503.c
@@ -103,8 +103,15 @@ static int __init do_el2_probe(struct net_device *dev)
return -ENXIO;
for (addr = addrs; *addr; addr++) {
- unsigned base_bits = isa_readb(*addr);
- int i = ffs(base_bits) - 1;
+ void __iomem *p = ioremap(*addr, 1);
+ unsigned base_bits;
+ int i;
+
+ if (!p)
+ continue;
+ base_bits = readb(p);
+ iounmap(p);
+ i = ffs(base_bits) - 1;
if (i == -1 || base_bits != (1 << i))
continue;
if (el2_probe1(dev, netcard_portlist[i]) == 0)
@@ -145,6 +152,8 @@ 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
@@ -262,42 +271,46 @@ el2_probe1(struct net_device *dev, int ioaddr)
if ((membase_reg & 0xf0) == 0) {
dev->mem_start = 0;
ei_status.name = "3c503-PIO";
+ ei_status.mem = NULL;
} else {
dev->mem_start = ((membase_reg & 0xc0) ? 0xD8000 : 0xC8000) +
((membase_reg & 0xA0) ? 0x4000 : 0);
-
#define EL2_MEMSIZE (EL2_MB1_STOP_PG - EL2_MB1_START_PG)*256
+ ei_status.mem = ioremap(dev->mem_start, EL2_MEMSIZE);
+
#ifdef EL2MEMTEST
/* This has never found an error, but someone might care.
Note that it only tests the 2nd 8kB on 16kB 3c503/16
cards between card addr. 0x2000 and 0x3fff. */
{ /* Check the card's memory. */
- unsigned long mem_base = dev->mem_start;
+ void __iomem *mem_base = ei_status.mem;
unsigned int test_val = 0xbbadf00d;
- isa_writel(0xba5eba5e, mem_base);
+ writel(0xba5eba5e, mem_base);
for (i = sizeof(test_val); i < EL2_MEMSIZE; i+=sizeof(test_val)) {
- isa_writel(test_val, mem_base + i);
- if (isa_readl(mem_base) != 0xba5eba5e
- || isa_readl(mem_base + i) != test_val) {
+ writel(test_val, mem_base + i);
+ if (readl(mem_base) != 0xba5eba5e
+ || readl(mem_base + i) != test_val) {
printk("3c503: memory failure or memory address conflict.\n");
dev->mem_start = 0;
ei_status.name = "3c503-PIO";
+ iounmap(mem_base);
+ ei_status.mem = NULL;
break;
}
test_val += 0x55555555;
- isa_writel(0, mem_base + i);
+ writel(0, mem_base + i);
}
}
#endif /* EL2MEMTEST */
if (dev->mem_start)
- dev->mem_end = ei_status.rmem_end = dev->mem_start + EL2_MEMSIZE;
+ dev->mem_end = dev->mem_start + EL2_MEMSIZE;
if (wordlength) { /* No Tx pages to skip over to get to Rx */
- ei_status.rmem_start = dev->mem_start;
+ ei_status.priv = 0;
ei_status.name = "3c503/16";
} else {
- ei_status.rmem_start = TX_PAGES*256 + dev->mem_start;
+ ei_status.priv = TX_PAGES * 256;
ei_status.name = "3c503";
}
}
@@ -471,16 +484,16 @@ el2_block_output(struct net_device *dev, int count,
unsigned short int *wrd;
int boguscount; /* timeout counter */
unsigned short word; /* temporary for better machine code */
+ void __iomem *base = ei_status.mem;
if (ei_status.word16) /* Tx packets go into bank 0 on EL2/16 card */
outb(EGACFR_RSEL|EGACFR_TCM, E33G_GACFR);
else
outb(EGACFR_NORM, E33G_GACFR);
- if (dev->mem_start) { /* Shared memory transfer */
- unsigned long dest_addr = dev->mem_start +
- ((start_page - ei_status.tx_start_page) << 8);
- isa_memcpy_toio(dest_addr, buf, count);
+ if (base) { /* Shared memory transfer */
+ memcpy_toio(base + ((start_page - ei_status.tx_start_page) << 8),
+ buf, count);
outb(EGACFR_NORM, E33G_GACFR); /* Back to bank1 in case on bank0 */
return;
}
@@ -541,11 +554,12 @@ static void
el2_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
{
int boguscount;
- unsigned long hdr_start = dev->mem_start + ((ring_page - EL2_MB1_START_PG)<<8);
+ void __iomem *base = ei_status.mem;
unsigned short word;
- if (dev->mem_start) { /* Use the shared memory. */
- isa_memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
+ if (base) { /* Use the shared memory. */
+ void __iomem *hdr_start = base + ((ring_page - EL2_MB1_START_PG)<<8);
+ memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
hdr->count = le16_to_cpu(hdr->count);
return;
}
@@ -581,23 +595,22 @@ static void
el2_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
{
int boguscount = 0;
+ void __iomem *base = ei_status.mem;
unsigned short int *buf;
unsigned short word;
- int end_of_ring = ei_status.rmem_end;
-
/* Maybe enable shared memory just be to be safe... nahh.*/
- if (dev->mem_start) { /* Use the shared memory. */
+ if (base) { /* Use the shared memory. */
ring_offset -= (EL2_MB1_START_PG<<8);
- if (dev->mem_start + ring_offset + count > end_of_ring) {
+ if (ring_offset + count > EL2_MEMSIZE) {
/* We must wrap the input move. */
- int semi_count = end_of_ring - (dev->mem_start + ring_offset);
- isa_memcpy_fromio(skb->data, dev->mem_start + ring_offset, semi_count);
+ int semi_count = EL2_MEMSIZE - ring_offset;
+ memcpy_fromio(skb->data, base + ring_offset, semi_count);
count -= semi_count;
- isa_memcpy_fromio(skb->data + semi_count, ei_status.rmem_start, count);
+ memcpy_fromio(skb->data + semi_count, base + ei_status.priv, count);
} else {
/* Packet is in one chunk -- we can copy + cksum. */
- isa_eth_io_copy_and_sum(skb, dev->mem_start + ring_offset, count, 0);
+ eth_io_copy_and_sum(skb, base + ring_offset, count, 0);
}
return;
}
diff --git a/drivers/net/3c505.c b/drivers/net/3c505.c
index 8e9887fa26c88..76fa8cc240859 100644
--- a/drivers/net/3c505.c
+++ b/drivers/net/3c505.c
@@ -32,7 +32,7 @@
* Linux 1.3.0 changes by
* Alan Cox <Alan.Cox@linux.org>
* More debugging, DMA support, currently maintained by
- * Philip Blundell <Philip.Blundell@pobox.com>
+ * Philip Blundell <philb@gnu.org>
* Multicard/soft configurable dma channel/rev 2 hardware support
* by Christopher Collins <ccollins@pcug.org.au>
* Ethtool support (jgarzik), 11/17/2001
diff --git a/drivers/net/3c509.c b/drivers/net/3c509.c
index d474ba6238262..e843109d4f62d 100644
--- a/drivers/net/3c509.c
+++ b/drivers/net/3c509.c
@@ -214,7 +214,7 @@ static void el3_poll_controller(struct net_device *dev);
#endif
#ifdef CONFIG_EISA
-struct eisa_device_id el3_eisa_ids[] = {
+static struct eisa_device_id el3_eisa_ids[] = {
{ "TCM5092" },
{ "TCM5093" },
{ "" }
@@ -222,7 +222,7 @@ struct eisa_device_id el3_eisa_ids[] = {
static int el3_eisa_probe (struct device *device);
-struct eisa_driver el3_eisa_driver = {
+static struct eisa_driver el3_eisa_driver = {
.id_table = el3_eisa_ids,
.driver = {
.name = "3c509",
diff --git a/drivers/net/3c515.c b/drivers/net/3c515.c
index ad46ab8c31ce9..c4cf4fcd13444 100644
--- a/drivers/net/3c515.c
+++ b/drivers/net/3c515.c
@@ -86,6 +86,7 @@ static int max_interrupt_work = 20;
MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
MODULE_DESCRIPTION("3Com 3c515 Corkscrew driver");
MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
/* "Knobs" for adjusting internal parameters. */
/* Put out somewhat more debugging messages. (0 - no msg, 1 minimal msgs). */
@@ -472,7 +473,7 @@ static int check_device(unsigned ioaddr)
static void cleanup_card(struct net_device *dev)
{
- struct corkscrew_private *vp = (struct corkscrew_private *) dev->priv;
+ struct corkscrew_private *vp = netdev_priv(dev);
list_del_init(&vp->list);
if (dev->dma)
free_dma(dev->dma);
@@ -570,7 +571,7 @@ no_pnp:
static void corkscrew_setup(struct net_device *dev, int ioaddr,
struct pnp_dev *idev, int card_number)
{
- struct corkscrew_private *vp = (struct corkscrew_private *) dev->priv;
+ struct corkscrew_private *vp = netdev_priv(dev);
unsigned int eeprom[0x40], checksum = 0; /* EEPROM contents */
int i;
int irq;
@@ -696,8 +697,7 @@ static void corkscrew_setup(struct net_device *dev, int ioaddr,
static int corkscrew_open(struct net_device *dev)
{
int ioaddr = dev->base_addr;
- struct corkscrew_private *vp =
- (struct corkscrew_private *) dev->priv;
+ struct corkscrew_private *vp = netdev_priv(dev);
union wn3_config config;
int i;
@@ -862,7 +862,7 @@ static void corkscrew_timer(unsigned long data)
{
#ifdef AUTOMEDIA
struct net_device *dev = (struct net_device *) data;
- struct corkscrew_private *vp = (struct corkscrew_private *) dev->priv;
+ struct corkscrew_private *vp = netdev_priv(dev);
int ioaddr = dev->base_addr;
unsigned long flags;
int ok = 0;
@@ -954,8 +954,7 @@ static void corkscrew_timer(unsigned long data)
static void corkscrew_timeout(struct net_device *dev)
{
int i;
- struct corkscrew_private *vp =
- (struct corkscrew_private *) dev->priv;
+ struct corkscrew_private *vp = netdev_priv(dev);
int ioaddr = dev->base_addr;
printk(KERN_WARNING
@@ -994,8 +993,7 @@ static void corkscrew_timeout(struct net_device *dev)
static int corkscrew_start_xmit(struct sk_buff *skb,
struct net_device *dev)
{
- struct corkscrew_private *vp =
- (struct corkscrew_private *) dev->priv;
+ struct corkscrew_private *vp = netdev_priv(dev);
int ioaddr = dev->base_addr;
/* Block a timer-based transmit from overlapping. */
@@ -1123,14 +1121,13 @@ static irqreturn_t corkscrew_interrupt(int irq, void *dev_id,
{
/* Use the now-standard shared IRQ implementation. */
struct net_device *dev = dev_id;
- struct corkscrew_private *lp;
+ struct corkscrew_private *lp = netdev_priv(dev);
int ioaddr, status;
int latency;
int i = max_interrupt_work;
ioaddr = dev->base_addr;
latency = inb(ioaddr + Timer);
- lp = (struct corkscrew_private *) dev->priv;
spin_lock(&lp->lock);
@@ -1262,7 +1259,7 @@ static irqreturn_t corkscrew_interrupt(int irq, void *dev_id,
static int corkscrew_rx(struct net_device *dev)
{
- struct corkscrew_private *vp = (struct corkscrew_private *) dev->priv;
+ struct corkscrew_private *vp = netdev_priv(dev);
int ioaddr = dev->base_addr;
int i;
short rx_status;
@@ -1329,8 +1326,7 @@ static int corkscrew_rx(struct net_device *dev)
static int boomerang_rx(struct net_device *dev)
{
- struct corkscrew_private *vp =
- (struct corkscrew_private *) dev->priv;
+ struct corkscrew_private *vp = netdev_priv(dev);
int entry = vp->cur_rx % RX_RING_SIZE;
int ioaddr = dev->base_addr;
int rx_status;
@@ -1420,8 +1416,7 @@ static int boomerang_rx(struct net_device *dev)
static int corkscrew_close(struct net_device *dev)
{
- struct corkscrew_private *vp =
- (struct corkscrew_private *) dev->priv;
+ struct corkscrew_private *vp = netdev_priv(dev);
int ioaddr = dev->base_addr;
int i;
@@ -1476,7 +1471,7 @@ static int corkscrew_close(struct net_device *dev)
static struct net_device_stats *corkscrew_get_stats(struct net_device *dev)
{
- struct corkscrew_private *vp = (struct corkscrew_private *) dev->priv;
+ struct corkscrew_private *vp = netdev_priv(dev);
unsigned long flags;
if (netif_running(dev)) {
@@ -1496,8 +1491,7 @@ static struct net_device_stats *corkscrew_get_stats(struct net_device *dev)
*/
static void update_stats(int ioaddr, struct net_device *dev)
{
- struct corkscrew_private *vp =
- (struct corkscrew_private *) dev->priv;
+ struct corkscrew_private *vp = netdev_priv(dev);
/* Unlike the 3c5x9 we need not turn off stats updates while reading. */
/* Switch to the stats window, and read everything. */
diff --git a/drivers/net/3c527.c b/drivers/net/3c527.c
index 15550b1442f84..6db3301e7965a 100644
--- a/drivers/net/3c527.c
+++ b/drivers/net/3c527.c
@@ -197,7 +197,7 @@ struct mca_adapters_t {
char *name;
};
-const struct mca_adapters_t mc32_adapters[] = {
+static const struct mca_adapters_t mc32_adapters[] = {
{ 0x0041, "3COM EtherLink MC/32" },
{ 0x8EF5, "IBM High Performance Lan Adapter" },
{ 0x0000, NULL }
diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c
index b22ed57811433..43e2ac532f82e 100644
--- a/drivers/net/3c59x.c
+++ b/drivers/net/3c59x.c
@@ -964,7 +964,7 @@ static void poll_vortex(struct net_device *dev)
#ifdef CONFIG_PM
-static int vortex_suspend (struct pci_dev *pdev, u32 state)
+static int vortex_suspend (struct pci_dev *pdev, pm_message_t state)
{
struct net_device *dev = pci_get_drvdata(pdev);
diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c
index 7d5b69adbed77..d4bd20c21a1f2 100644
--- a/drivers/net/8139too.c
+++ b/drivers/net/8139too.c
@@ -389,8 +389,14 @@ enum rx_mode_bits {
/* Bits in TxConfig. */
enum tx_config_bits {
- TxIFG1 = (1 << 25), /* Interframe Gap Time */
- TxIFG0 = (1 << 24), /* Enabling these bits violates IEEE 802.3 */
+
+ /* Interframe Gap Time. Only TxIFG96 doesn't violate IEEE 802.3 */
+ TxIFGShift = 24,
+ TxIFG84 = (0 << TxIFGShift), /* 8.4us / 840ns (10 / 100Mbps) */
+ TxIFG88 = (1 << TxIFGShift), /* 8.8us / 880ns (10 / 100Mbps) */
+ TxIFG92 = (2 << TxIFGShift), /* 9.2us / 920ns (10 / 100Mbps) */
+ TxIFG96 = (3 << TxIFGShift), /* 9.6us / 960ns (10 / 100Mbps) */
+
TxLoopBack = (1 << 18) | (1 << 17), /* enable loopback test mode */
TxCRC = (1 << 16), /* DISABLE appending CRC to end of Tx packets */
TxClearAbt = (1 << 0), /* Clear abort (WO) */
@@ -723,17 +729,14 @@ static const unsigned int rtl8139_rx_config =
#endif
static const unsigned int rtl8139_tx_config =
- (TX_DMA_BURST << TxDMAShift) | (TX_RETRY << TxRetryShift);
+ TxIFG96 | (TX_DMA_BURST << TxDMAShift) | (TX_RETRY << TxRetryShift);
static void __rtl8139_cleanup_dev (struct net_device *dev)
{
- struct rtl8139_private *tp;
+ struct rtl8139_private *tp = netdev_priv(dev);
struct pci_dev *pdev;
assert (dev != NULL);
- assert (dev->priv != NULL);
-
- tp = dev->priv;
assert (tp->pci_dev != NULL);
pdev = tp->pci_dev;
@@ -746,7 +749,6 @@ static void __rtl8139_cleanup_dev (struct net_device *dev)
pci_release_regions (pdev);
free_netdev(dev);
-
pci_set_drvdata (pdev, NULL);
}
@@ -775,7 +777,7 @@ static int __devinit rtl8139_init_board (struct pci_dev *pdev,
struct net_device *dev;
struct rtl8139_private *tp;
u8 tmp8;
- int rc;
+ int rc, disable_dev_on_err = 0;
unsigned int i;
unsigned long pio_start, pio_end, pio_flags, pio_len;
unsigned long mmio_start, mmio_end, mmio_flags, mmio_len;
@@ -785,7 +787,7 @@ static int __devinit rtl8139_init_board (struct pci_dev *pdev,
*dev_out = NULL;
- /* dev and dev->priv zeroed in alloc_etherdev */
+ /* dev and priv zeroed in alloc_etherdev */
dev = alloc_etherdev (sizeof (*tp));
if (dev == NULL) {
printk (KERN_ERR PFX "%s: Unable to alloc new net device\n", pci_name(pdev));
@@ -794,7 +796,7 @@ static int __devinit rtl8139_init_board (struct pci_dev *pdev,
SET_MODULE_OWNER(dev);
SET_NETDEV_DEV(dev, &pdev->dev);
- tp = dev->priv;
+ tp = netdev_priv(dev);
tp->pci_dev = pdev;
/* enable device (incl. PCI PM wakeup and hotplug setup) */
@@ -847,6 +849,7 @@ static int __devinit rtl8139_init_board (struct pci_dev *pdev,
rc = pci_request_regions (pdev, "8139too");
if (rc)
goto err_out;
+ disable_dev_on_err = 1;
/* enable PCI bus-mastering */
pci_set_master (pdev);
@@ -932,6 +935,8 @@ match:
err_out:
__rtl8139_cleanup_dev (dev);
+ if (disable_dev_on_err)
+ pci_disable_device (pdev);
return rc;
}
@@ -976,8 +981,8 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
return i;
assert (dev != NULL);
- tp = dev->priv;
- assert (tp != NULL);
+ tp = netdev_priv(dev);
+
ioaddr = tp->mmio_addr;
assert (ioaddr != NULL);
@@ -1010,8 +1015,8 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
dev->irq = pdev->irq;
- /* dev->priv/tp zeroed and aligned in alloc_etherdev */
- tp = dev->priv;
+ /* tp zeroed and aligned in alloc_etherdev */
+ tp = netdev_priv(dev);
/* note: tp->chipset set in rtl8139_init_board */
tp->drv_flags = board_info[ent->driver_data].hw_flags;
@@ -1109,6 +1114,7 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
err_out:
__rtl8139_cleanup_dev (dev);
+ pci_disable_device (pdev);
return i;
}
@@ -1116,15 +1122,13 @@ err_out:
static void __devexit rtl8139_remove_one (struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata (pdev);
- struct rtl8139_private *np;
assert (dev != NULL);
- np = dev->priv;
- assert (np != NULL);
unregister_netdev (dev);
__rtl8139_cleanup_dev (dev);
+ pci_disable_device (pdev);
}
@@ -1234,7 +1238,7 @@ static void mdio_sync (void *mdio_addr)
static int mdio_read (struct net_device *dev, int phy_id, int location)
{
- struct rtl8139_private *tp = dev->priv;
+ struct rtl8139_private *tp = netdev_priv(dev);
int retval = 0;
#ifdef CONFIG_8139TOO_8129
void *mdio_addr = tp->mmio_addr + Config4;
@@ -1276,7 +1280,7 @@ static int mdio_read (struct net_device *dev, int phy_id, int location)
static void mdio_write (struct net_device *dev, int phy_id, int location,
int value)
{
- struct rtl8139_private *tp = dev->priv;
+ struct rtl8139_private *tp = netdev_priv(dev);
#ifdef CONFIG_8139TOO_8129
void *mdio_addr = tp->mmio_addr + Config4;
int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location << 18) | value;
@@ -1319,7 +1323,7 @@ static void mdio_write (struct net_device *dev, int phy_id, int location,
static int rtl8139_open (struct net_device *dev)
{
- struct rtl8139_private *tp = dev->priv;
+ struct rtl8139_private *tp = netdev_priv(dev);
int retval;
void *ioaddr = tp->mmio_addr;
@@ -1367,7 +1371,7 @@ static int rtl8139_open (struct net_device *dev)
static void rtl_check_media (struct net_device *dev, unsigned int init_media)
{
- struct rtl8139_private *tp = dev->priv;
+ struct rtl8139_private *tp = netdev_priv(dev);
if (tp->phys[0] >= 0) {
mii_check_media(&tp->mii, netif_msg_link(tp), init_media);
@@ -1377,7 +1381,7 @@ static void rtl_check_media (struct net_device *dev, unsigned int init_media)
/* Start the hardware at open or resume. */
static void rtl8139_hw_start (struct net_device *dev)
{
- struct rtl8139_private *tp = dev->priv;
+ struct rtl8139_private *tp = netdev_priv(dev);
void *ioaddr = tp->mmio_addr;
u32 i;
u8 tmp;
@@ -1399,8 +1403,6 @@ static void rtl8139_hw_start (struct net_device *dev)
tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys;
RTL_W32 (RxConfig, tp->rx_config);
-
- /* Check this value: the documentation for IFG contradicts ifself. */
RTL_W32 (TxConfig, rtl8139_tx_config);
tp->cur_rx = 0;
@@ -1446,7 +1448,7 @@ static void rtl8139_hw_start (struct net_device *dev)
/* Initialize the Rx and Tx rings, along with various 'dev' bits. */
static void rtl8139_init_ring (struct net_device *dev)
{
- struct rtl8139_private *tp = dev->priv;
+ struct rtl8139_private *tp = netdev_priv(dev);
int i;
tp->cur_rx = 0;
@@ -1613,7 +1615,7 @@ static inline void rtl8139_thread_iter (struct net_device *dev,
static int rtl8139_thread (void *data)
{
struct net_device *dev = data;
- struct rtl8139_private *tp = dev->priv;
+ struct rtl8139_private *tp = netdev_priv(dev);
unsigned long timeout;
daemonize("%s", dev->name);
@@ -1645,7 +1647,7 @@ static int rtl8139_thread (void *data)
static void rtl8139_start_thread(struct net_device *dev)
{
- struct rtl8139_private *tp = dev->priv;
+ struct rtl8139_private *tp = netdev_priv(dev);
tp->thr_pid = -1;
tp->twistie = 0;
@@ -1673,7 +1675,7 @@ static inline void rtl8139_tx_clear (struct rtl8139_private *tp)
static void rtl8139_tx_timeout (struct net_device *dev)
{
- struct rtl8139_private *tp = dev->priv;
+ struct rtl8139_private *tp = netdev_priv(dev);
void *ioaddr = tp->mmio_addr;
int i;
u8 tmp8;
@@ -1718,7 +1720,7 @@ static void rtl8139_tx_timeout (struct net_device *dev)
static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev)
{
- struct rtl8139_private *tp = dev->priv;
+ struct rtl8139_private *tp = netdev_priv(dev);
void *ioaddr = tp->mmio_addr;
unsigned int entry;
unsigned int len = skb->len;
@@ -1766,7 +1768,6 @@ static void rtl8139_tx_interrupt (struct net_device *dev,
unsigned long dirty_tx, tx_left;
assert (dev != NULL);
- assert (tp != NULL);
assert (ioaddr != NULL);
dirty_tx = tp->dirty_tx;
@@ -2125,7 +2126,7 @@ static void rtl8139_weird_interrupt (struct net_device *dev,
static int rtl8139_poll(struct net_device *dev, int *budget)
{
- struct rtl8139_private *tp = dev->priv;
+ struct rtl8139_private *tp = netdev_priv(dev);
void *ioaddr = tp->mmio_addr;
int orig_budget = min(*budget, dev->quota);
int done = 1;
@@ -2163,7 +2164,7 @@ static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance,
struct pt_regs *regs)
{
struct net_device *dev = (struct net_device *) dev_instance;
- struct rtl8139_private *tp = dev->priv;
+ struct rtl8139_private *tp = netdev_priv(dev);
void *ioaddr = tp->mmio_addr;
u16 status, ackstat;
int link_changed = 0; /* avoid bogus "uninit" warning */
@@ -2239,7 +2240,7 @@ static void rtl8139_poll_controller(struct net_device *dev)
static int rtl8139_close (struct net_device *dev)
{
- struct rtl8139_private *tp = dev->priv;
+ struct rtl8139_private *tp = netdev_priv(dev);
void *ioaddr = tp->mmio_addr;
int ret = 0;
unsigned long flags;
@@ -2302,7 +2303,7 @@ static int rtl8139_close (struct net_device *dev)
other threads or interrupts aren't messing with the 8139. */
static void rtl8139_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
{
- struct rtl8139_private *np = dev->priv;
+ struct rtl8139_private *np = netdev_priv(dev);
void *ioaddr = np->mmio_addr;
spin_lock_irq(&np->lock);
@@ -2336,7 +2337,7 @@ static void rtl8139_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
aren't messing with the 8139. */
static int rtl8139_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
{
- struct rtl8139_private *np = dev->priv;
+ struct rtl8139_private *np = netdev_priv(dev);
void *ioaddr = np->mmio_addr;
u32 support;
u8 cfg3, cfg5;
@@ -2376,7 +2377,7 @@ static int rtl8139_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
static void rtl8139_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
{
- struct rtl8139_private *np = dev->priv;
+ struct rtl8139_private *np = netdev_priv(dev);
strcpy(info->driver, DRV_NAME);
strcpy(info->version, DRV_VERSION);
strcpy(info->bus_info, pci_name(np->pci_dev));
@@ -2385,7 +2386,7 @@ static void rtl8139_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *
static int rtl8139_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
- struct rtl8139_private *np = dev->priv;
+ struct rtl8139_private *np = netdev_priv(dev);
spin_lock_irq(&np->lock);
mii_ethtool_gset(&np->mii, cmd);
spin_unlock_irq(&np->lock);
@@ -2394,7 +2395,7 @@ static int rtl8139_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
static int rtl8139_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
- struct rtl8139_private *np = dev->priv;
+ struct rtl8139_private *np = netdev_priv(dev);
int rc;
spin_lock_irq(&np->lock);
rc = mii_ethtool_sset(&np->mii, cmd);
@@ -2404,25 +2405,25 @@ static int rtl8139_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
static int rtl8139_nway_reset(struct net_device *dev)
{
- struct rtl8139_private *np = dev->priv;
+ struct rtl8139_private *np = netdev_priv(dev);
return mii_nway_restart(&np->mii);
}
static u32 rtl8139_get_link(struct net_device *dev)
{
- struct rtl8139_private *np = dev->priv;
+ struct rtl8139_private *np = netdev_priv(dev);
return mii_link_ok(&np->mii);
}
static u32 rtl8139_get_msglevel(struct net_device *dev)
{
- struct rtl8139_private *np = dev->priv;
+ struct rtl8139_private *np = netdev_priv(dev);
return np->msg_enable;
}
static void rtl8139_set_msglevel(struct net_device *dev, u32 datum)
{
- struct rtl8139_private *np = dev->priv;
+ struct rtl8139_private *np = netdev_priv(dev);
np->msg_enable = datum;
}
@@ -2433,13 +2434,13 @@ static void rtl8139_set_msglevel(struct net_device *dev, u32 datum)
#else
static int rtl8139_get_regs_len(struct net_device *dev)
{
- struct rtl8139_private *np = dev->priv;
+ struct rtl8139_private *np = netdev_priv(dev);
return np->regs_len;
}
static void rtl8139_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf)
{
- struct rtl8139_private *np = dev->priv;
+ struct rtl8139_private *np = netdev_priv(dev);
regs->version = RTL_REGS_VER;
@@ -2456,7 +2457,7 @@ static int rtl8139_get_stats_count(struct net_device *dev)
static void rtl8139_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, u64 *data)
{
- struct rtl8139_private *np = dev->priv;
+ struct rtl8139_private *np = netdev_priv(dev);
data[0] = np->xstats.early_rx;
data[1] = np->xstats.tx_buf_mapped;
@@ -2488,7 +2489,7 @@ static struct ethtool_ops rtl8139_ethtool_ops = {
static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
- struct rtl8139_private *np = dev->priv;
+ struct rtl8139_private *np = netdev_priv(dev);
int rc;
if (!netif_running(dev))
@@ -2504,7 +2505,7 @@ static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
static struct net_device_stats *rtl8139_get_stats (struct net_device *dev)
{
- struct rtl8139_private *tp = dev->priv;
+ struct rtl8139_private *tp = netdev_priv(dev);
void *ioaddr = tp->mmio_addr;
unsigned long flags;
@@ -2523,7 +2524,7 @@ static struct net_device_stats *rtl8139_get_stats (struct net_device *dev)
static void __set_rx_mode (struct net_device *dev)
{
- struct rtl8139_private *tp = dev->priv;
+ struct rtl8139_private *tp = netdev_priv(dev);
void *ioaddr = tp->mmio_addr;
u32 mc_filter[2]; /* Multicast hash filter */
int i, rx_mode;
@@ -2572,7 +2573,7 @@ static void __set_rx_mode (struct net_device *dev)
static void rtl8139_set_rx_mode (struct net_device *dev)
{
unsigned long flags;
- struct rtl8139_private *tp = dev->priv;
+ struct rtl8139_private *tp = netdev_priv(dev);
spin_lock_irqsave (&tp->lock, flags);
__set_rx_mode(dev);
@@ -2581,10 +2582,10 @@ static void rtl8139_set_rx_mode (struct net_device *dev)
#ifdef CONFIG_PM
-static int rtl8139_suspend (struct pci_dev *pdev, u32 state)
+static int rtl8139_suspend (struct pci_dev *pdev, pm_message_t state)
{
struct net_device *dev = pci_get_drvdata (pdev);
- struct rtl8139_private *tp = dev->priv;
+ struct rtl8139_private *tp = netdev_priv(dev);
void *ioaddr = tp->mmio_addr;
unsigned long flags;
diff --git a/drivers/net/8390.c b/drivers/net/8390.c
index 0486d3ecb1e84..bab16bcc9ae5d 100644
--- a/drivers/net/8390.c
+++ b/drivers/net/8390.c
@@ -999,6 +999,7 @@ static void ethdev_setup(struct net_device *dev)
/**
* alloc_ei_netdev - alloc_etherdev counterpart for 8390
+ * @size: extra bytes to allocate
*
* Allocate 8390-specific net_device.
*/
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index fd2a9290bc9bc..74d57865a819f 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -44,19 +44,17 @@ config DUMMY
config BONDING
tristate "Bonding driver support"
depends on NETDEVICES
+ depends on INET
---help---
Say 'Y' or 'M' if you wish to be able to 'bond' multiple Ethernet
Channels together. This is called 'Etherchannel' by Cisco,
- 'Trunking' by Sun, and 'Bonding' in Linux.
+ 'Trunking' by Sun, 802.3ad by the IEEE, and 'Bonding' in Linux.
- If you have two Ethernet connections to some other computer, you can
- make them behave like one double speed connection using this driver.
- Naturally, this has to be supported at the other end as well, either
- with a similar Bonding Linux driver, a Cisco 5500 switch or a
- SunTrunking SunSoft driver.
+ The driver supports multiple bonding modes to allow for both high
+ perfomance and high availability operation.
- This is similar to the EQL driver, but it merges Ethernet segments
- instead of serial lines.
+ Refer to <file:Documentation/networking/bonding.txt> for more
+ information.
To compile this driver as a module, choose M here: the module
will be called bonding.
@@ -105,29 +103,6 @@ config TUN
If you don't know what to use this for, you don't need it.
-config ETHERTAP
- tristate "Ethertap network tap"
- depends on NETDEVICES && EXPERIMENTAL && NETLINK_DEV
- ---help---
- If you say Y here (and have said Y to "Kernel/User network link
- driver", above) and create a character special file /dev/tap0 with
- major number 36 and minor number 16 using mknod ("man mknod"), you
- will be able to have a user space program read and write raw
- Ethernet frames from/to that special file. tap0 can be configured
- with ifconfig and route like any other Ethernet device but it is not
- connected to any physical LAN; everything written by the user to
- /dev/tap0 is treated by the kernel as if it had come in from a LAN
- to the device tap0; everything the kernel wants to send out over the
- device tap0 can instead be read by the user from /dev/tap0: the user
- mode program replaces the LAN that would be attached to an ordinary
- Ethernet device. Please read the file
- <file:Documentation/networking/ethertap.txt> for more information.
-
- To compile this driver as a module, choose M here: the module
- will be called ethertap.
-
- If you don't know what to use this for, you don't need it.
-
config NET_SB1000
tristate "General Instruments Surfboard 1000"
depends on NETDEVICES && PNP
@@ -161,7 +136,7 @@ endif
#
menu "Ethernet (10 or 100Mbit)"
- depends on NETDEVICES
+ depends on NETDEVICES && !UML
config NET_ETHERNET
bool "Ethernet (10 or 100Mbit)"
@@ -445,7 +420,7 @@ config LASI_82596
config MIPS_JAZZ_SONIC
tristate "MIPS JAZZ onboard SONIC Ethernet support"
- depends on NET_ETHERNET && MIPS_JAZZ
+ depends on NET_ETHERNET && MACH_JAZZ
help
This is the driver for the onboard card of MIPS Magnum 4000,
Acer PICA, Olivetti M700-10 and a few other identical OEM systems.
@@ -470,7 +445,7 @@ config NET_SB1250_MAC
config SGI_IOC3_ETH
bool "SGI IOC3 Ethernet"
- depends on NET_ETHERNET && SGI_IP27
+ depends on NET_ETHERNET && PCI && SGI_IP27
select CRC32
select MII
help
@@ -638,7 +613,7 @@ config EL16
will be called 3c507.
config EL3
- tristate "3c509/3c529 (MCA)/3c569B (98)/3c579 \"EtherLink III\" support"
+ tristate "3c509/3c529 (MCA)/3c579 \"EtherLink III\" support"
depends on NET_VENDOR_3COM && (ISA || EISA || MCA)
---help---
If you have a network (Ethernet) card belonging to the 3Com
@@ -819,7 +794,7 @@ config SMC91X
tristate "SMC 91C9x/91C1xxx support"
select CRC32
select MII
- depends on NET_ETHERNET && (ARM || REDWOOD_5 || REDWOOD_6 || M32R)
+ depends on NET_ETHERNET && (ARM || REDWOOD_5 || REDWOOD_6 || M32R || SUPERH)
help
This is a driver for SMC's 91x series of Ethernet chipsets,
including the SMC91C94 and the SMC91C111. Say Y if you want it
@@ -902,7 +877,7 @@ config NI65
source "drivers/net/tulip/Kconfig"
config AT1700
- tristate "AT1700/1720/RE1000Plus(C-Bus) support (EXPERIMENTAL)"
+ tristate "AT1700/1720 support (EXPERIMENTAL)"
depends on NET_ETHERNET && (ISA || MCA_LEGACY) && EXPERIMENTAL
select CRC32
---help---
@@ -1428,23 +1403,6 @@ config E100
<file:Documentation/networking/net-modules.txt>. The module
will be called e100.
-config E100_NAPI
- bool "Use Rx Polling (NAPI)"
- depends on E100
- help
- NAPI is a new driver API designed to reduce CPU and interrupt load
- when the driver is receiving lots of packets from the card. It is
- still somewhat experimental and thus not yet enabled by default.
-
- If your estimated Rx load is 10kpps or more, or if the card will be
- deployed on potentially unfriendly networks (e.g. in a firewall),
- then say Y here.
-
- See <file:Documentation/networking/NAPI_HOWTO.txt> for more
- information.
-
- If in doubt, say N.
-
config LNE390
tristate "Mylex EISA LNE390A/B support (EXPERIMENTAL)"
depends on NET_PCI && EISA && EXPERIMENTAL
@@ -1780,14 +1738,6 @@ config DECLANCE
DEC (now Compaq) based on the AMD Lance chipset, including the
DEPCA series. (This chipset is better known via the NE2100 cards.)
-config BAGETLANCE
- tristate "Baget AMD LANCE support"
- depends on NET_ETHERNET && BAGET_MIPS
- help
- Say Y to enable kernel support for AMD Lance Ethernet cards on the
- MIPS-32-based Baget embedded system. This chipset is better known
- via the NE2100 cards.
-
config 68360_ENET
bool "Motorola 68360 ethernet controller"
depends on M68360
@@ -1818,7 +1768,7 @@ endmenu
#
menu "Ethernet (1000 Mbit)"
- depends on NETDEVICES
+ depends on NETDEVICES && !UML
config ACENIC
tristate "Alteon AceNIC/3Com 3C985/NetGear GA620 Gigabit support"
@@ -2083,7 +2033,7 @@ config TIGON3
config GIANFAR
tristate "Gianfar Ethernet"
- depends on 85xx
+ depends on 85xx || 83xx
help
This driver supports the Gigabit TSEC on the MPC85xx
family of chips, and the FEC on the 8540
@@ -2094,10 +2044,11 @@ config GFAR_NAPI
config MV643XX_ETH
tristate "MV-643XX Ethernet support"
- depends on MOMENCO_OCELOT_C || MOMENCO_JAGUAR_ATX
+ depends on MOMENCO_OCELOT_C || MOMENCO_JAGUAR_ATX || MV64360 || MOMENCO_OCELOT_3
help
This driver supports the gigabit Ethernet on the Marvell MV643XX
- chipset which is used in the Momenco Ocelot C and Jaguar ATX.
+ chipset which is used in the Momenco Ocelot C and Jaguar ATX and
+ Pegasos II, amongst other PPC and MIPS boards.
config MV643XX_ETH_0
bool "MV-643XX Port 0"
@@ -2127,7 +2078,7 @@ endmenu
#
menu "Ethernet (10000 Mbit)"
- depends on NETDEVICES
+ depends on NETDEVICES && !UML
config IXGB
tristate "Intel(R) PRO/10GbE support"
@@ -2206,11 +2157,13 @@ config 2BUFF_MODE
endmenu
+if !UML
source "drivers/net/tokenring/Kconfig"
source "drivers/net/wireless/Kconfig"
source "drivers/net/pcmcia/Kconfig"
+endif
source "drivers/net/wan/Kconfig"
@@ -2555,15 +2508,6 @@ config NET_FC
adaptor below. You also should have said Y to "SCSI support" and
"SCSI generic support".
-config IPHASE5526
- tristate "Interphase 5526 Tachyon chipset based adapter support"
- depends on NET_FC && SCSI && PCI && BROKEN
- help
- Say Y here if you have a Fibre Channel adaptor of this kind.
-
- To compile this driver as a module, choose M here: the module
- will be called iph5526.
-
config SHAPER
tristate "Traffic Shaper (EXPERIMENTAL)"
depends on NETDEVICES && EXPERIMENTAL
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index b9ec40d06972e..6202b10dbb4df 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -68,7 +68,6 @@ obj-$(CONFIG_SUNDANCE) += sundance.o
obj-$(CONFIG_HAMACHI) += hamachi.o
obj-$(CONFIG_NET) += Space.o loopback.o
obj-$(CONFIG_SEEQ8005) += seeq8005.o
-obj-$(CONFIG_ETHERTAP) += ethertap.o
obj-$(CONFIG_NET_SB1000) += sb1000.o
obj-$(CONFIG_MAC8390) += mac8390.o 8390.o
obj-$(CONFIG_APNE) += apne.o 8390.o
@@ -162,7 +161,6 @@ obj-$(CONFIG_MIPS_JAZZ_SONIC) += jazzsonic.o
obj-$(CONFIG_MIPS_GT96100ETH) += gt96100eth.o
obj-$(CONFIG_MIPS_AU1X00_ENET) += au1000_eth.o
obj-$(CONFIG_SGI_IOC3_ETH) += ioc3-eth.o
-obj-$(CONFIG_BAGETLANCE) += bagetlance.o
obj-$(CONFIG_DECLANCE) += declance.o
obj-$(CONFIG_ATARILANCE) += atarilance.o
obj-$(CONFIG_ATARI_BIONET) += atari_bionet.o
@@ -184,7 +182,6 @@ obj-$(CONFIG_SMC91X) += smc91x.o
obj-$(CONFIG_FEC_8XX) += fec_8xx/
obj-$(CONFIG_ARM) += arm/
-obj-$(CONFIG_NET_FC) += fc/
obj-$(CONFIG_DEV_APPLETALK) += appletalk/
obj-$(CONFIG_TR) += tokenring/
obj-$(CONFIG_WAN) += wan/
diff --git a/drivers/net/Space.c b/drivers/net/Space.c
index dbc3ec7545cf5..fc519377b5aa9 100644
--- a/drivers/net/Space.c
+++ b/drivers/net/Space.c
@@ -302,16 +302,6 @@ static struct devprobe2 m68k_probes[] __initdata = {
{NULL, 0},
};
-static struct devprobe2 mips_probes[] __initdata = {
-#ifdef CONFIG_MIPS_JAZZ_SONIC
- {sonic_probe, 0},
-#endif
-#ifdef CONFIG_BAGETLANCE /* Lance-based Baget ethernet boards */
- {bagetlance_probe, 0},
-#endif
- {NULL, 0},
-};
-
/*
* Unified ethernet device probe, segmented per architecture and
* per bus interface. This drives the legacy devices only for now.
@@ -325,7 +315,6 @@ static void __init ethif_probe2(int unit)
return;
(void)( probe_list2(unit, m68k_probes, base_addr == 0) &&
- probe_list2(unit, mips_probes, base_addr == 0) &&
probe_list2(unit, eisa_probes, base_addr == 0) &&
probe_list2(unit, mca_probes, base_addr == 0) &&
probe_list2(unit, isa_probes, base_addr == 0) &&
diff --git a/drivers/net/amd8111e.c b/drivers/net/amd8111e.c
index f1d81901ecf1f..f2e937abf7b4d 100755
--- a/drivers/net/amd8111e.c
+++ b/drivers/net/amd8111e.c
@@ -105,6 +105,7 @@ Revision History:
MODULE_AUTHOR("Advanced Micro Devices, Inc.");
MODULE_DESCRIPTION ("AMD8111 based 10/100 Ethernet Controller. Driver Version 3.0.3");
MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, amd8111e_pci_tbl);
module_param_array(speed_duplex, int, NULL, 0);
MODULE_PARM_DESC(speed_duplex, "Set device speed and duplex modes, 0: Auto Negotitate, 1: 10Mbps Half Duplex, 2: 10Mbps Full Duplex, 3: 100Mbps Half Duplex, 4: 100Mbps Full Duplex");
module_param_array(coalesce, bool, NULL, 0);
@@ -1381,6 +1382,8 @@ static int amd8111e_open(struct net_device * dev )
if(amd8111e_restart(dev)){
spin_unlock_irq(&lp->lock);
+ if (dev->irq)
+ free_irq(dev->irq, dev);
return -ENOMEM;
}
/* Start ipg timer */
@@ -1487,7 +1490,7 @@ static void amd8111e_read_regs(struct amd8111e_priv *lp, u32 *buf)
amd8111e crc generator implementation is different from the kernel
ether_crc() function.
*/
-int amd8111e_ether_crc(int len, char* mac_addr)
+static int amd8111e_ether_crc(int len, char* mac_addr)
{
int i,byte;
unsigned char octet;
@@ -1715,7 +1718,7 @@ static int amd8111e_set_mac_address(struct net_device *dev, void *p)
/*
This function changes the mtu of the device. It restarts the device to initialize the descriptor with new receive buffers.
*/
-int amd8111e_change_mtu(struct net_device *dev, int new_mtu)
+static int amd8111e_change_mtu(struct net_device *dev, int new_mtu)
{
struct amd8111e_priv *lp = netdev_priv(dev);
int err;
@@ -1797,7 +1800,7 @@ static void amd8111e_tx_timeout(struct net_device *dev)
if(!err)
netif_wake_queue(dev);
}
-static int amd8111e_suspend(struct pci_dev *pci_dev, u32 state)
+static int amd8111e_suspend(struct pci_dev *pci_dev, pm_message_t state)
{
struct net_device *dev = pci_get_drvdata(pci_dev);
struct amd8111e_priv *lp = netdev_priv(dev);
diff --git a/drivers/net/arcnet/arc-rawmode.c b/drivers/net/arcnet/arc-rawmode.c
index 925574cc6b328..e1ea29b0cd142 100644
--- a/drivers/net/arcnet/arc-rawmode.c
+++ b/drivers/net/arcnet/arc-rawmode.c
@@ -87,7 +87,7 @@ MODULE_LICENSE("GPL");
static void rx(struct net_device *dev, int bufnum,
struct archdr *pkthdr, int length)
{
- struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+ struct arcnet_local *lp = dev->priv;
struct sk_buff *skb;
struct archdr *pkt = pkthdr;
int ofs;
@@ -168,7 +168,7 @@ static int build_header(struct sk_buff *skb, struct net_device *dev,
static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length,
int bufnum)
{
- struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+ struct arcnet_local *lp = dev->priv;
struct arc_hardware *hard = &pkt->hard;
int ofs;
diff --git a/drivers/net/arcnet/arc-rimi.c b/drivers/net/arcnet/arc-rimi.c
index edcc38761999f..38c3f033f7396 100644
--- a/drivers/net/arcnet/arc-rimi.c
+++ b/drivers/net/arcnet/arc-rimi.c
@@ -230,7 +230,7 @@ err_free_irq:
*/
static int arcrimi_reset(struct net_device *dev, int really_reset)
{
- struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+ struct arcnet_local *lp = dev->priv;
void __iomem *ioaddr = lp->mem_start + 0x800;
BUGMSG(D_INIT, "Resetting %s (status=%02Xh)\n", dev->name, ASTATUS());
@@ -251,7 +251,7 @@ static int arcrimi_reset(struct net_device *dev, int really_reset)
static void arcrimi_setmask(struct net_device *dev, int mask)
{
- struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+ struct arcnet_local *lp = dev->priv;
void __iomem *ioaddr = lp->mem_start + 0x800;
AINTMASK(mask);
@@ -259,7 +259,7 @@ static void arcrimi_setmask(struct net_device *dev, int mask)
static int arcrimi_status(struct net_device *dev)
{
- struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+ struct arcnet_local *lp = dev->priv;
void __iomem *ioaddr = lp->mem_start + 0x800;
return ASTATUS();
@@ -267,7 +267,7 @@ static int arcrimi_status(struct net_device *dev)
static void arcrimi_command(struct net_device *dev, int cmd)
{
- struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+ struct arcnet_local *lp = dev->priv;
void __iomem *ioaddr = lp->mem_start + 0x800;
ACOMMAND(cmd);
@@ -276,7 +276,7 @@ static void arcrimi_command(struct net_device *dev, int cmd)
static void arcrimi_copy_to_card(struct net_device *dev, int bufnum, int offset,
void *buf, int count)
{
- struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+ struct arcnet_local *lp = dev->priv;
void __iomem *memaddr = lp->mem_start + 0x800 + bufnum * 512 + offset;
TIME("memcpy_toio", count, memcpy_toio(memaddr, buf, count));
}
@@ -285,7 +285,7 @@ static void arcrimi_copy_to_card(struct net_device *dev, int bufnum, int offset,
static void arcrimi_copy_from_card(struct net_device *dev, int bufnum, int offset,
void *buf, int count)
{
- struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+ struct arcnet_local *lp = dev->priv;
void __iomem *memaddr = lp->mem_start + 0x800 + bufnum * 512 + offset;
TIME("memcpy_fromio", count, memcpy_fromio(buf, memaddr, count));
}
@@ -331,7 +331,7 @@ static int __init arc_rimi_init(void)
static void __exit arc_rimi_exit(void)
{
struct net_device *dev = my_dev;
- struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+ struct arcnet_local *lp = dev->priv;
unregister_netdev(dev);
iounmap(lp->mem_start);
diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c
index fdd83f141a50e..4f9f69e22c1bd 100644
--- a/drivers/net/arcnet/arcnet.c
+++ b/drivers/net/arcnet/arcnet.c
@@ -181,7 +181,7 @@ EXPORT_SYMBOL(arcnet_dump_skb);
void arcnet_dump_packet(struct net_device *dev, int bufnum, char *desc,
int take_arcnet_lock)
{
- struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+ struct arcnet_local *lp = dev->priv;
int i, length;
unsigned long flags = 0;
static uint8_t buf[512];
@@ -244,7 +244,7 @@ void arcnet_unregister_proto(struct ArcProto *proto)
*/
static void release_arcbuf(struct net_device *dev, int bufnum)
{
- struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+ struct arcnet_local *lp = dev->priv;
int i;
lp->buf_queue[lp->first_free_buf++] = bufnum;
@@ -253,7 +253,7 @@ static void release_arcbuf(struct net_device *dev, int bufnum)
BUGLVL(D_DURING) {
BUGMSG(D_DURING, "release_arcbuf: freed #%d; buffer queue is now: ",
bufnum);
- for (i = lp->next_buf; i != lp->first_free_buf; i = ++i % 5)
+ for (i = lp->next_buf; i != lp->first_free_buf; i = (i+1) % 5)
BUGMSG2(D_DURING, "#%d ", lp->buf_queue[i]);
BUGMSG2(D_DURING, "\n");
}
@@ -266,7 +266,7 @@ static void release_arcbuf(struct net_device *dev, int bufnum)
*/
static int get_arcbuf(struct net_device *dev)
{
- struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+ struct arcnet_local *lp = dev->priv;
int buf = -1, i;
if (!atomic_dec_and_test(&lp->buf_lock)) {
@@ -289,7 +289,7 @@ static int get_arcbuf(struct net_device *dev)
BUGLVL(D_DURING) {
BUGMSG(D_DURING, "get_arcbuf: got #%d; buffer queue is now: ", buf);
- for (i = lp->next_buf; i != lp->first_free_buf; i = ++i % 5)
+ for (i = lp->next_buf; i != lp->first_free_buf; i = (i+1) % 5)
BUGMSG2(D_DURING, "#%d ", lp->buf_queue[i]);
BUGMSG2(D_DURING, "\n");
}
@@ -367,7 +367,7 @@ struct net_device *alloc_arcdev(char *name)
*/
static int arcnet_open(struct net_device *dev)
{
- struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+ struct arcnet_local *lp = dev->priv;
int count, newmtu, error;
BUGMSG(D_INIT,"opened.");
@@ -467,7 +467,7 @@ static int arcnet_open(struct net_device *dev)
/* The inverse routine to arcnet_open - shuts down the card. */
static int arcnet_close(struct net_device *dev)
{
- struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+ struct arcnet_local *lp = dev->priv;
netif_stop_queue(dev);
@@ -488,7 +488,7 @@ static int arcnet_header(struct sk_buff *skb, struct net_device *dev,
unsigned short type, void *daddr, void *saddr,
unsigned len)
{
- struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+ struct arcnet_local *lp = dev->priv;
uint8_t _daddr, proto_num;
struct ArcProto *proto;
@@ -546,7 +546,7 @@ static int arcnet_header(struct sk_buff *skb, struct net_device *dev,
static int arcnet_rebuild_header(struct sk_buff *skb)
{
struct net_device *dev = skb->dev;
- struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+ struct arcnet_local *lp = dev->priv;
int status = 0; /* default is failure */
unsigned short type;
uint8_t daddr=0;
@@ -591,7 +591,7 @@ static int arcnet_rebuild_header(struct sk_buff *skb)
/* Called by the kernel in order to transmit a packet. */
static int arcnet_send_packet(struct sk_buff *skb, struct net_device *dev)
{
- struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+ struct arcnet_local *lp = dev->priv;
struct archdr *pkt;
struct arc_rfc1201 *soft;
struct ArcProto *proto;
@@ -674,7 +674,7 @@ static int arcnet_send_packet(struct sk_buff *skb, struct net_device *dev)
*/
static int go_tx(struct net_device *dev)
{
- struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+ struct arcnet_local *lp = dev->priv;
BUGMSG(D_DURING, "go_tx: status=%Xh, intmask=%Xh, next_tx=%d, cur_tx=%d\n",
ASTATUS(), lp->intmask, lp->next_tx, lp->cur_tx);
@@ -705,7 +705,7 @@ static int go_tx(struct net_device *dev)
static void arcnet_timeout(struct net_device *dev)
{
unsigned long flags;
- struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+ struct arcnet_local *lp = dev->priv;
int status = ASTATUS();
char *msg;
@@ -754,7 +754,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id, struct pt_regs *regs)
BUGMSG(D_DURING, "in arcnet_interrupt\n");
- lp = (struct arcnet_local *) dev->priv;
+ lp = dev->priv;
if (!lp)
BUG();
@@ -989,7 +989,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id, struct pt_regs *regs)
*/
void arcnet_rx(struct net_device *dev, int bufnum)
{
- struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+ struct arcnet_local *lp = dev->priv;
struct archdr pkt;
struct arc_rfc1201 *soft;
int length, ofs;
@@ -1053,7 +1053,7 @@ void arcnet_rx(struct net_device *dev, int bufnum)
*/
static struct net_device_stats *arcnet_get_stats(struct net_device *dev)
{
- struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+ struct arcnet_local *lp = dev->priv;
return &lp->stats;
}
@@ -1070,7 +1070,7 @@ static void null_rx(struct net_device *dev, int bufnum,
static int null_build_header(struct sk_buff *skb, struct net_device *dev,
unsigned short type, uint8_t daddr)
{
- struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+ struct arcnet_local *lp = dev->priv;
BUGMSG(D_PROTO,
"tx: can't build header for encap %02Xh; load a protocol driver.\n",
@@ -1085,7 +1085,7 @@ static int null_build_header(struct sk_buff *skb, struct net_device *dev,
static int null_prepare_tx(struct net_device *dev, struct archdr *pkt,
int length, int bufnum)
{
- struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+ struct arcnet_local *lp = dev->priv;
struct arc_hardware newpkt;
BUGMSG(D_PROTO, "tx: no encap for this host; load a protocol driver.\n");
diff --git a/drivers/net/arcnet/com20020.c b/drivers/net/arcnet/com20020.c
index b40ee3ff7fb48..0dc70c7b7940a 100644
--- a/drivers/net/arcnet/com20020.c
+++ b/drivers/net/arcnet/com20020.c
@@ -159,7 +159,7 @@ int com20020_found(struct net_device *dev, int shared)
/* Initialize the rest of the device structure. */
- lp = (struct arcnet_local *) dev->priv;
+ lp = dev->priv;
lp->hw.owner = THIS_MODULE;
lp->hw.command = com20020_command;
@@ -233,7 +233,7 @@ int com20020_found(struct net_device *dev, int shared)
*/
static int com20020_reset(struct net_device *dev, int really_reset)
{
- struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+ struct arcnet_local *lp = dev->priv;
u_int ioaddr = dev->base_addr;
u_char inbyte;
@@ -300,7 +300,7 @@ static int com20020_status(struct net_device *dev)
static void com20020_close(struct net_device *dev)
{
- struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+ struct arcnet_local *lp = dev->priv;
int ioaddr = dev->base_addr;
/* disable transmitter */
diff --git a/drivers/net/arcnet/com90io.c b/drivers/net/arcnet/com90io.c
index ac2e0ffb2dc24..52c77cbe8c62c 100644
--- a/drivers/net/arcnet/com90io.c
+++ b/drivers/net/arcnet/com90io.c
@@ -248,7 +248,7 @@ static int __init com90io_found(struct net_device *dev)
return -EBUSY;
}
- lp = (struct arcnet_local *) (dev->priv);
+ lp = dev->priv;
lp->card_name = "COM90xx I/O";
lp->hw.command = com90io_command;
lp->hw.status = com90io_status;
@@ -290,7 +290,7 @@ static int __init com90io_found(struct net_device *dev)
*/
static int com90io_reset(struct net_device *dev, int really_reset)
{
- struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+ struct arcnet_local *lp = dev->priv;
short ioaddr = dev->base_addr;
BUGMSG(D_INIT, "Resetting %s (status=%02Xh)\n", dev->name, ASTATUS());
diff --git a/drivers/net/arcnet/com90xx.c b/drivers/net/arcnet/com90xx.c
index ba0f8a2eba60b..6c2c9b9ac6db1 100644
--- a/drivers/net/arcnet/com90xx.c
+++ b/drivers/net/arcnet/com90xx.c
@@ -529,7 +529,7 @@ static void com90xx_setmask(struct net_device *dev, int mask)
*/
int com90xx_reset(struct net_device *dev, int really_reset)
{
- struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+ struct arcnet_local *lp = dev->priv;
short ioaddr = dev->base_addr;
BUGMSG(D_INIT, "Resetting (status=%02Xh)\n", ASTATUS());
@@ -565,7 +565,7 @@ int com90xx_reset(struct net_device *dev, int really_reset)
static void com90xx_copy_to_card(struct net_device *dev, int bufnum, int offset,
void *buf, int count)
{
- struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+ struct arcnet_local *lp = dev->priv;
void __iomem *memaddr = lp->mem_start + bufnum * 512 + offset;
TIME("memcpy_toio", count, memcpy_toio(memaddr, buf, count));
}
@@ -574,7 +574,7 @@ static void com90xx_copy_to_card(struct net_device *dev, int bufnum, int offset,
static void com90xx_copy_from_card(struct net_device *dev, int bufnum, int offset,
void *buf, int count)
{
- struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+ struct arcnet_local *lp = dev->priv;
void __iomem *memaddr = lp->mem_start + bufnum * 512 + offset;
TIME("memcpy_fromio", count, memcpy_fromio(buf, memaddr, count));
}
@@ -600,7 +600,7 @@ static void __exit com90xx_exit(void)
for (count = 0; count < numcards; count++) {
dev = cards[count];
- lp = (struct arcnet_local *) dev->priv;
+ lp = dev->priv;
unregister_netdev(dev);
free_irq(dev->irq, dev);
diff --git a/drivers/net/arcnet/rfc1051.c b/drivers/net/arcnet/rfc1051.c
index fd959cb3ef7d5..6d7913704fb51 100644
--- a/drivers/net/arcnet/rfc1051.c
+++ b/drivers/net/arcnet/rfc1051.c
@@ -88,7 +88,7 @@ MODULE_LICENSE("GPL");
*/
static unsigned short type_trans(struct sk_buff *skb, struct net_device *dev)
{
- struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+ struct arcnet_local *lp = dev->priv;
struct archdr *pkt = (struct archdr *) skb->data;
struct arc_rfc1051 *soft = &pkt->soft.rfc1051;
int hdr_size = ARC_HDR_SIZE + RFC1051_HDR_SIZE;
@@ -125,7 +125,7 @@ static unsigned short type_trans(struct sk_buff *skb, struct net_device *dev)
static void rx(struct net_device *dev, int bufnum,
struct archdr *pkthdr, int length)
{
- struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+ struct arcnet_local *lp = dev->priv;
struct sk_buff *skb;
struct archdr *pkt = pkthdr;
int ofs;
@@ -169,7 +169,7 @@ static void rx(struct net_device *dev, int bufnum,
static int build_header(struct sk_buff *skb, struct net_device *dev,
unsigned short type, uint8_t daddr)
{
- struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+ struct arcnet_local *lp = dev->priv;
int hdr_size = ARC_HDR_SIZE + RFC1051_HDR_SIZE;
struct archdr *pkt = (struct archdr *) skb_push(skb, hdr_size);
struct arc_rfc1051 *soft = &pkt->soft.rfc1051;
@@ -220,7 +220,7 @@ static int build_header(struct sk_buff *skb, struct net_device *dev,
static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length,
int bufnum)
{
- struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+ struct arcnet_local *lp = dev->priv;
struct arc_hardware *hard = &pkt->hard;
int ofs;
diff --git a/drivers/net/arcnet/rfc1201.c b/drivers/net/arcnet/rfc1201.c
index ed793b15f0eec..6b6ae4bf3d39d 100644
--- a/drivers/net/arcnet/rfc1201.c
+++ b/drivers/net/arcnet/rfc1201.c
@@ -92,7 +92,7 @@ static unsigned short type_trans(struct sk_buff *skb, struct net_device *dev)
{
struct archdr *pkt = (struct archdr *) skb->data;
struct arc_rfc1201 *soft = &pkt->soft.rfc1201;
- struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+ struct arcnet_local *lp = dev->priv;
int hdr_size = ARC_HDR_SIZE + RFC1201_HDR_SIZE;
/* Pull off the arcnet header. */
@@ -134,7 +134,7 @@ static unsigned short type_trans(struct sk_buff *skb, struct net_device *dev)
static void rx(struct net_device *dev, int bufnum,
struct archdr *pkthdr, int length)
{
- struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+ struct arcnet_local *lp = dev->priv;
struct sk_buff *skb;
struct archdr *pkt = pkthdr;
struct arc_rfc1201 *soft = &pkthdr->soft.rfc1201;
@@ -376,7 +376,7 @@ static void rx(struct net_device *dev, int bufnum,
static int build_header(struct sk_buff *skb, struct net_device *dev,
unsigned short type, uint8_t daddr)
{
- struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+ struct arcnet_local *lp = dev->priv;
int hdr_size = ARC_HDR_SIZE + RFC1201_HDR_SIZE;
struct archdr *pkt = (struct archdr *) skb_push(skb, hdr_size);
struct arc_rfc1201 *soft = &pkt->soft.rfc1201;
@@ -443,7 +443,7 @@ static int build_header(struct sk_buff *skb, struct net_device *dev,
static void load_pkt(struct net_device *dev, struct arc_hardware *hard,
struct arc_rfc1201 *soft, int softlen, int bufnum)
{
- struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+ struct arcnet_local *lp = dev->priv;
int ofs;
/* assume length <= XMTU: someone should have handled that by now. */
@@ -476,7 +476,7 @@ static void load_pkt(struct net_device *dev, struct arc_hardware *hard,
static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length,
int bufnum)
{
- struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+ struct arcnet_local *lp = dev->priv;
const int maxsegsize = XMTU - RFC1201_HDR_SIZE;
struct Outgoing *out;
@@ -511,7 +511,7 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length,
static int continue_tx(struct net_device *dev, int bufnum)
{
- struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+ struct arcnet_local *lp = dev->priv;
struct Outgoing *out = &lp->outgoing;
struct arc_hardware *hard = &out->pkt->hard;
struct arc_rfc1201 *soft = &out->pkt->soft.rfc1201, *newsoft;
diff --git a/drivers/net/arm/ether1.c b/drivers/net/arm/ether1.c
index 6118f09c63cf3..36475eb2727f6 100644
--- a/drivers/net/arm/ether1.c
+++ b/drivers/net/arm/ether1.c
@@ -86,8 +86,8 @@ static char version[] __initdata = "ether1 ethernet driver (c) 2000 Russell King
#define DISABLEIRQS 1
#define NORMALIRQS 0
-#define ether1_inw(dev, addr, type, offset, svflgs) ether1_inw_p (dev, addr + (int)(&((type *)0)->offset), svflgs)
-#define ether1_outw(dev, val, addr, type, offset, svflgs) ether1_outw_p (dev, val, addr + (int)(&((type *)0)->offset), svflgs)
+#define ether1_readw(dev, addr, type, offset, svflgs) ether1_inw_p (dev, addr + (int)(&((type *)0)->offset), svflgs)
+#define ether1_writew(dev, val, addr, type, offset, svflgs) ether1_outw_p (dev, val, addr + (int)(&((type *)0)->offset), svflgs)
static inline unsigned short
ether1_inw_p (struct net_device *dev, int addr, int svflgs)
@@ -98,8 +98,8 @@ ether1_inw_p (struct net_device *dev, int addr, int svflgs)
if (svflgs)
local_irq_save (flags);
- outb (addr >> 12, REG_PAGE);
- ret = inw (ETHER1_RAM + ((addr & 4095) >> 1));
+ writeb(addr >> 12, REG_PAGE);
+ ret = readw(ETHER1_RAM + ((addr & 4095) << 1));
if (svflgs)
local_irq_restore (flags);
return ret;
@@ -113,8 +113,8 @@ ether1_outw_p (struct net_device *dev, unsigned short val, int addr, int svflgs)
if (svflgs)
local_irq_save (flags);
- outb (addr >> 12, REG_PAGE);
- outw (val, ETHER1_RAM + ((addr & 4095) >> 1));
+ writeb(addr >> 12, REG_PAGE);
+ writew(val, ETHER1_RAM + ((addr & 4095) << 1));
if (svflgs)
local_irq_restore (flags);
}
@@ -131,11 +131,12 @@ ether1_outw_p (struct net_device *dev, unsigned short val, int addr, int svflgs)
static void
ether1_writebuffer (struct net_device *dev, void *data, unsigned int start, unsigned int length)
{
- unsigned int page, thislen, offset, addr;
+ unsigned int page, thislen, offset;
+ void __iomem *addr;
offset = start & 4095;
page = start >> 12;
- addr = ioaddr(ETHER1_RAM + (offset >> 1));
+ addr = ETHER1_RAM + (offset << 1);
if (offset + length > 4096)
thislen = 4096 - offset;
@@ -145,7 +146,7 @@ ether1_writebuffer (struct net_device *dev, void *data, unsigned int start, unsi
do {
int used;
- outb(page, REG_PAGE);
+ writeb(page, REG_PAGE);
length -= thislen;
__asm__ __volatile__(
@@ -181,7 +182,7 @@ ether1_writebuffer (struct net_device *dev, void *data, unsigned int start, unsi
: "=&r" (used), "=&r" (data)
: "r" (addr), "r" (thislen), "1" (data));
- addr = ioaddr(ETHER1_RAM);
+ addr = ETHER1_RAM;
thislen = length;
if (thislen > 4096)
@@ -193,11 +194,12 @@ ether1_writebuffer (struct net_device *dev, void *data, unsigned int start, unsi
static void
ether1_readbuffer (struct net_device *dev, void *data, unsigned int start, unsigned int length)
{
- unsigned int page, thislen, offset, addr;
+ unsigned int page, thislen, offset;
+ void __iomem *addr;
offset = start & 4095;
page = start >> 12;
- addr = ioaddr(ETHER1_RAM + (offset >> 1));
+ addr = ETHER1_RAM + (offset << 1);
if (offset + length > 4096)
thislen = 4096 - offset;
@@ -207,7 +209,7 @@ ether1_readbuffer (struct net_device *dev, void *data, unsigned int start, unsig
do {
int used;
- outb(page, REG_PAGE);
+ writeb(page, REG_PAGE);
length -= thislen;
__asm__ __volatile__(
@@ -243,7 +245,7 @@ ether1_readbuffer (struct net_device *dev, void *data, unsigned int start, unsig
: "=&r" (used), "=&r" (data)
: "r" (addr), "r" (thislen), "1" (data));
- addr = ioaddr(ETHER1_RAM);
+ addr = ETHER1_RAM;
thislen = length;
if (thislen > 4096)
@@ -302,7 +304,7 @@ ether1_ramtest(struct net_device *dev, unsigned char byte)
static int
ether1_reset (struct net_device *dev)
{
- outb (CTRL_RST|CTRL_ACK, REG_CONTROL);
+ writeb(CTRL_RST|CTRL_ACK, REG_CONTROL);
return BUS_16;
}
@@ -447,12 +449,11 @@ static rbd_t init_rbd = {
static int
ether1_init_for_open (struct net_device *dev)
{
- struct ether1_priv *priv = netdev_priv(dev);
int i, status, addr, next, next2;
int failures = 0;
unsigned long timeout;
- outb (CTRL_RST|CTRL_ACK, REG_CONTROL);
+ writeb(CTRL_RST|CTRL_ACK, REG_CONTROL);
for (i = 0; i < 6; i++)
init_sa.sa_addr[i] = dev->dev_addr[i];
@@ -467,7 +468,7 @@ ether1_init_for_open (struct net_device *dev)
ether1_writebuffer (dev, &init_tdr, TDR_ADDR, TDR_SIZE);
ether1_writebuffer (dev, &init_nop, NOP_ADDR, NOP_SIZE);
- if (ether1_inw (dev, CFG_ADDR, cfg_t, cfg_command, NORMALIRQS) != CMD_CONFIG) {
+ if (ether1_readw(dev, CFG_ADDR, cfg_t, cfg_command, NORMALIRQS) != CMD_CONFIG) {
printk (KERN_ERR "%s: detected either RAM fault or compiler bug\n",
dev->name);
return 1;
@@ -487,7 +488,7 @@ ether1_init_for_open (struct net_device *dev)
if (next2 >= RX_AREA_END) {
next = RX_AREA_START;
init_rfd.rfd_command = RFD_CMDEL | RFD_CMDSUSPEND;
- priv->rx_tail = addr;
+ priv(dev)->rx_tail = addr;
} else
init_rfd.rfd_command = 0;
if (addr == RX_AREA_START)
@@ -503,21 +504,21 @@ ether1_init_for_open (struct net_device *dev)
addr = next;
} while (next2 < RX_AREA_END);
- priv->tx_link = NOP_ADDR;
- priv->tx_head = NOP_ADDR + NOP_SIZE;
- priv->tx_tail = TDR_ADDR;
- priv->rx_head = RX_AREA_START;
+ priv(dev)->tx_link = NOP_ADDR;
+ priv(dev)->tx_head = NOP_ADDR + NOP_SIZE;
+ priv(dev)->tx_tail = TDR_ADDR;
+ priv(dev)->rx_head = RX_AREA_START;
/* release reset & give 586 a prod */
- priv->resetting = 1;
- priv->initialising = 1;
- outb (CTRL_RST, REG_CONTROL);
- outb (0, REG_CONTROL);
- outb (CTRL_CA, REG_CONTROL);
+ priv(dev)->resetting = 1;
+ priv(dev)->initialising = 1;
+ writeb(CTRL_RST, REG_CONTROL);
+ writeb(0, REG_CONTROL);
+ writeb(CTRL_CA, REG_CONTROL);
/* 586 should now unset iscp.busy */
timeout = jiffies + HZ/2;
- while (ether1_inw (dev, ISCP_ADDR, iscp_t, iscp_busy, DISABLEIRQS) == 1) {
+ while (ether1_readw(dev, ISCP_ADDR, iscp_t, iscp_busy, DISABLEIRQS) == 1) {
if (time_after(jiffies, timeout)) {
printk (KERN_WARNING "%s: can't initialise 82586: iscp is busy\n", dev->name);
return 1;
@@ -526,7 +527,7 @@ ether1_init_for_open (struct net_device *dev)
/* check status of commands that we issued */
timeout += HZ/10;
- while (((status = ether1_inw (dev, CFG_ADDR, cfg_t, cfg_status, DISABLEIRQS))
+ while (((status = ether1_readw(dev, CFG_ADDR, cfg_t, cfg_status, DISABLEIRQS))
& STAT_COMPLETE) == 0) {
if (time_after(jiffies, timeout))
break;
@@ -535,15 +536,15 @@ ether1_init_for_open (struct net_device *dev)
if ((status & (STAT_COMPLETE | STAT_OK)) != (STAT_COMPLETE | STAT_OK)) {
printk (KERN_WARNING "%s: can't initialise 82586: config status %04X\n", dev->name, status);
printk (KERN_DEBUG "%s: SCB=[STS=%04X CMD=%04X CBL=%04X RFA=%04X]\n", dev->name,
- ether1_inw (dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS),
- ether1_inw (dev, SCB_ADDR, scb_t, scb_command, NORMALIRQS),
- ether1_inw (dev, SCB_ADDR, scb_t, scb_cbl_offset, NORMALIRQS),
- ether1_inw (dev, SCB_ADDR, scb_t, scb_rfa_offset, NORMALIRQS));
+ ether1_readw(dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS),
+ ether1_readw(dev, SCB_ADDR, scb_t, scb_command, NORMALIRQS),
+ ether1_readw(dev, SCB_ADDR, scb_t, scb_cbl_offset, NORMALIRQS),
+ ether1_readw(dev, SCB_ADDR, scb_t, scb_rfa_offset, NORMALIRQS));
failures += 1;
}
timeout += HZ/10;
- while (((status = ether1_inw (dev, SA_ADDR, sa_t, sa_status, DISABLEIRQS))
+ while (((status = ether1_readw(dev, SA_ADDR, sa_t, sa_status, DISABLEIRQS))
& STAT_COMPLETE) == 0) {
if (time_after(jiffies, timeout))
break;
@@ -552,15 +553,15 @@ ether1_init_for_open (struct net_device *dev)
if ((status & (STAT_COMPLETE | STAT_OK)) != (STAT_COMPLETE | STAT_OK)) {
printk (KERN_WARNING "%s: can't initialise 82586: set address status %04X\n", dev->name, status);
printk (KERN_DEBUG "%s: SCB=[STS=%04X CMD=%04X CBL=%04X RFA=%04X]\n", dev->name,
- ether1_inw (dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS),
- ether1_inw (dev, SCB_ADDR, scb_t, scb_command, NORMALIRQS),
- ether1_inw (dev, SCB_ADDR, scb_t, scb_cbl_offset, NORMALIRQS),
- ether1_inw (dev, SCB_ADDR, scb_t, scb_rfa_offset, NORMALIRQS));
+ ether1_readw(dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS),
+ ether1_readw(dev, SCB_ADDR, scb_t, scb_command, NORMALIRQS),
+ ether1_readw(dev, SCB_ADDR, scb_t, scb_cbl_offset, NORMALIRQS),
+ ether1_readw(dev, SCB_ADDR, scb_t, scb_rfa_offset, NORMALIRQS));
failures += 1;
}
timeout += HZ/10;
- while (((status = ether1_inw (dev, MC_ADDR, mc_t, mc_status, DISABLEIRQS))
+ while (((status = ether1_readw(dev, MC_ADDR, mc_t, mc_status, DISABLEIRQS))
& STAT_COMPLETE) == 0) {
if (time_after(jiffies, timeout))
break;
@@ -569,15 +570,15 @@ ether1_init_for_open (struct net_device *dev)
if ((status & (STAT_COMPLETE | STAT_OK)) != (STAT_COMPLETE | STAT_OK)) {
printk (KERN_WARNING "%s: can't initialise 82586: set multicast status %04X\n", dev->name, status);
printk (KERN_DEBUG "%s: SCB=[STS=%04X CMD=%04X CBL=%04X RFA=%04X]\n", dev->name,
- ether1_inw (dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS),
- ether1_inw (dev, SCB_ADDR, scb_t, scb_command, NORMALIRQS),
- ether1_inw (dev, SCB_ADDR, scb_t, scb_cbl_offset, NORMALIRQS),
- ether1_inw (dev, SCB_ADDR, scb_t, scb_rfa_offset, NORMALIRQS));
+ ether1_readw(dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS),
+ ether1_readw(dev, SCB_ADDR, scb_t, scb_command, NORMALIRQS),
+ ether1_readw(dev, SCB_ADDR, scb_t, scb_cbl_offset, NORMALIRQS),
+ ether1_readw(dev, SCB_ADDR, scb_t, scb_rfa_offset, NORMALIRQS));
failures += 1;
}
timeout += HZ;
- while (((status = ether1_inw (dev, TDR_ADDR, tdr_t, tdr_status, DISABLEIRQS))
+ while (((status = ether1_readw(dev, TDR_ADDR, tdr_t, tdr_status, DISABLEIRQS))
& STAT_COMPLETE) == 0) {
if (time_after(jiffies, timeout))
break;
@@ -586,12 +587,12 @@ ether1_init_for_open (struct net_device *dev)
if ((status & (STAT_COMPLETE | STAT_OK)) != (STAT_COMPLETE | STAT_OK)) {
printk (KERN_WARNING "%s: can't tdr (ignored)\n", dev->name);
printk (KERN_DEBUG "%s: SCB=[STS=%04X CMD=%04X CBL=%04X RFA=%04X]\n", dev->name,
- ether1_inw (dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS),
- ether1_inw (dev, SCB_ADDR, scb_t, scb_command, NORMALIRQS),
- ether1_inw (dev, SCB_ADDR, scb_t, scb_cbl_offset, NORMALIRQS),
- ether1_inw (dev, SCB_ADDR, scb_t, scb_rfa_offset, NORMALIRQS));
+ ether1_readw(dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS),
+ ether1_readw(dev, SCB_ADDR, scb_t, scb_command, NORMALIRQS),
+ ether1_readw(dev, SCB_ADDR, scb_t, scb_cbl_offset, NORMALIRQS),
+ ether1_readw(dev, SCB_ADDR, scb_t, scb_rfa_offset, NORMALIRQS));
} else {
- status = ether1_inw (dev, TDR_ADDR, tdr_t, tdr_result, DISABLEIRQS);
+ status = ether1_readw(dev, TDR_ADDR, tdr_t, tdr_result, DISABLEIRQS);
if (status & TDR_XCVRPROB)
printk (KERN_WARNING "%s: i/f failed tdr: transceiver problem\n", dev->name);
else if ((status & (TDR_SHORT|TDR_OPEN)) && (status & TDR_TIME)) {
@@ -616,24 +617,23 @@ ether1_init_for_open (struct net_device *dev)
static int
ether1_txalloc (struct net_device *dev, int size)
{
- struct ether1_priv *priv = netdev_priv(dev);
int start, tail;
size = (size + 1) & ~1;
- tail = priv->tx_tail;
+ tail = priv(dev)->tx_tail;
- if (priv->tx_head + size > TX_AREA_END) {
- if (tail > priv->tx_head)
+ if (priv(dev)->tx_head + size > TX_AREA_END) {
+ if (tail > priv(dev)->tx_head)
return -1;
start = TX_AREA_START;
if (start + size > tail)
return -1;
- priv->tx_head = start + size;
+ priv(dev)->tx_head = start + size;
} else {
- if (priv->tx_head < tail && (priv->tx_head + size) > tail)
+ if (priv(dev)->tx_head < tail && (priv(dev)->tx_head + size) > tail)
return -1;
- start = priv->tx_head;
- priv->tx_head += size;
+ start = priv(dev)->tx_head;
+ priv(dev)->tx_head += size;
}
return start;
@@ -642,8 +642,6 @@ ether1_txalloc (struct net_device *dev, int size)
static int
ether1_open (struct net_device *dev)
{
- struct ether1_priv *priv = netdev_priv(dev);
-
if (!is_valid_ether_addr(dev->dev_addr)) {
printk(KERN_WARNING "%s: invalid ethernet MAC address\n",
dev->name);
@@ -653,7 +651,7 @@ ether1_open (struct net_device *dev)
if (request_irq(dev->irq, ether1_interrupt, 0, "ether1", dev))
return -EAGAIN;
- memset (&priv->stats, 0, sizeof (struct net_device_stats));
+ memset (&priv(dev)->stats, 0, sizeof (struct net_device_stats));
if (ether1_init_for_open (dev)) {
free_irq (dev->irq, dev);
@@ -668,8 +666,6 @@ ether1_open (struct net_device *dev)
static void
ether1_timeout(struct net_device *dev)
{
- struct ether1_priv *priv = netdev_priv(dev);
-
printk(KERN_WARNING "%s: transmit timeout, network cable problem?\n",
dev->name);
printk(KERN_WARNING "%s: resetting device\n", dev->name);
@@ -679,21 +675,20 @@ ether1_timeout(struct net_device *dev)
if (ether1_init_for_open (dev))
printk (KERN_ERR "%s: unable to restart interface\n", dev->name);
- priv->stats.tx_errors++;
+ priv(dev)->stats.tx_errors++;
netif_wake_queue(dev);
}
static int
ether1_sendpacket (struct sk_buff *skb, struct net_device *dev)
{
- struct ether1_priv *priv = netdev_priv(dev);
int tmp, tst, nopaddr, txaddr, tbdaddr, dataddr;
unsigned long flags;
tx_t tx;
tbd_t tbd;
nop_t nop;
- if (priv->restart) {
+ if (priv(dev)->restart) {
printk(KERN_WARNING "%s: resetting device\n", dev->name);
ether1_reset(dev);
@@ -701,7 +696,7 @@ ether1_sendpacket (struct sk_buff *skb, struct net_device *dev)
if (ether1_init_for_open(dev))
printk(KERN_ERR "%s: unable to restart interface\n", dev->name);
else
- priv->restart = 0;
+ priv(dev)->restart = 0;
}
if (skb->len < ETH_ZLEN) {
@@ -735,11 +730,11 @@ ether1_sendpacket (struct sk_buff *skb, struct net_device *dev)
ether1_writebuffer (dev, &tbd, tbdaddr, TBD_SIZE);
ether1_writebuffer (dev, skb->data, dataddr, skb->len);
ether1_writebuffer (dev, &nop, nopaddr, NOP_SIZE);
- tmp = priv->tx_link;
- priv->tx_link = nopaddr;
+ tmp = priv(dev)->tx_link;
+ priv(dev)->tx_link = nopaddr;
/* now reset the previous nop pointer */
- ether1_outw (dev, txaddr, tmp, nop_t, nop_link, NORMALIRQS);
+ ether1_writew(dev, txaddr, tmp, nop_t, nop_link, NORMALIRQS);
local_irq_restore(flags);
@@ -747,9 +742,9 @@ ether1_sendpacket (struct sk_buff *skb, struct net_device *dev)
dev->trans_start = jiffies;
/* check to see if we have room for a full sized ether frame */
- tmp = priv->tx_head;
+ tmp = priv(dev)->tx_head;
tst = ether1_txalloc (dev, TX_SIZE + TBD_SIZE + NOP_SIZE + ETH_FRAME_LEN);
- priv->tx_head = tmp;
+ priv(dev)->tx_head = tmp;
dev_kfree_skb (skb);
if (tst == -1)
@@ -762,11 +757,10 @@ ether1_sendpacket (struct sk_buff *skb, struct net_device *dev)
static void
ether1_xmit_done (struct net_device *dev)
{
- struct ether1_priv *priv = netdev_priv(dev);
nop_t nop;
int caddr, tst;
- caddr = priv->tx_tail;
+ caddr = priv(dev)->tx_tail;
again:
ether1_readbuffer (dev, &nop, caddr, NOP_SIZE);
@@ -774,21 +768,21 @@ again:
switch (nop.nop_command & CMD_MASK) {
case CMD_TDR:
/* special case */
- if (ether1_inw (dev, SCB_ADDR, scb_t, scb_cbl_offset, NORMALIRQS)
+ if (ether1_readw(dev, SCB_ADDR, scb_t, scb_cbl_offset, NORMALIRQS)
!= (unsigned short)I82586_NULL) {
- ether1_outw(dev, SCB_CMDCUCSTART | SCB_CMDRXSTART, SCB_ADDR, scb_t,
+ ether1_writew(dev, SCB_CMDCUCSTART | SCB_CMDRXSTART, SCB_ADDR, scb_t,
scb_command, NORMALIRQS);
- outb (CTRL_CA, REG_CONTROL);
+ writeb(CTRL_CA, REG_CONTROL);
}
- priv->tx_tail = NOP_ADDR;
+ priv(dev)->tx_tail = NOP_ADDR;
return;
case CMD_NOP:
if (nop.nop_link == caddr) {
- if (priv->initialising == 0)
+ if (priv(dev)->initialising == 0)
printk (KERN_WARNING "%s: strange command complete with no tx command!\n", dev->name);
else
- priv->initialising = 0;
+ priv(dev)->initialising = 0;
return;
}
if (caddr == nop.nop_link)
@@ -800,33 +794,33 @@ again:
if (nop.nop_status & STAT_COMPLETE)
break;
printk (KERN_ERR "%s: strange command complete without completed command\n", dev->name);
- priv->restart = 1;
+ priv(dev)->restart = 1;
return;
default:
printk (KERN_WARNING "%s: strange command %d complete! (offset %04X)", dev->name,
nop.nop_command & CMD_MASK, caddr);
- priv->restart = 1;
+ priv(dev)->restart = 1;
return;
}
while (nop.nop_status & STAT_COMPLETE) {
if (nop.nop_status & STAT_OK) {
- priv->stats.tx_packets ++;
- priv->stats.collisions += (nop.nop_status & STAT_COLLISIONS);
+ priv(dev)->stats.tx_packets ++;
+ priv(dev)->stats.collisions += (nop.nop_status & STAT_COLLISIONS);
} else {
- priv->stats.tx_errors ++;
+ priv(dev)->stats.tx_errors ++;
if (nop.nop_status & STAT_COLLAFTERTX)
- priv->stats.collisions ++;
+ priv(dev)->stats.collisions ++;
if (nop.nop_status & STAT_NOCARRIER)
- priv->stats.tx_carrier_errors ++;
+ priv(dev)->stats.tx_carrier_errors ++;
if (nop.nop_status & STAT_TXLOSTCTS)
printk (KERN_WARNING "%s: cts lost\n", dev->name);
if (nop.nop_status & STAT_TXSLOWDMA)
- priv->stats.tx_fifo_errors ++;
+ priv(dev)->stats.tx_fifo_errors ++;
if (nop.nop_status & STAT_COLLEXCESSIVE)
- priv->stats.collisions += 16;
+ priv(dev)->stats.collisions += 16;
}
if (nop.nop_link == caddr) {
@@ -851,11 +845,11 @@ again:
break;
}
}
- priv->tx_tail = caddr;
+ priv(dev)->tx_tail = caddr;
- caddr = priv->tx_head;
+ caddr = priv(dev)->tx_head;
tst = ether1_txalloc (dev, TX_SIZE + TBD_SIZE + NOP_SIZE + ETH_FRAME_LEN);
- priv->tx_head = caddr;
+ priv(dev)->tx_head = caddr;
if (tst != -1)
netif_wake_queue(dev);
}
@@ -863,17 +857,16 @@ again:
static void
ether1_recv_done (struct net_device *dev)
{
- struct ether1_priv *priv = netdev_priv(dev);
int status;
int nexttail, rbdaddr;
rbd_t rbd;
do {
- status = ether1_inw (dev, priv->rx_head, rfd_t, rfd_status, NORMALIRQS);
+ status = ether1_readw(dev, priv(dev)->rx_head, rfd_t, rfd_status, NORMALIRQS);
if ((status & RFD_COMPLETE) == 0)
break;
- rbdaddr = ether1_inw (dev, priv->rx_head, rfd_t, rfd_rbdoffset, NORMALIRQS);
+ rbdaddr = ether1_readw(dev, priv(dev)->rx_head, rfd_t, rfd_rbdoffset, NORMALIRQS);
ether1_readbuffer (dev, &rbd, rbdaddr, RBD_SIZE);
if ((rbd.rbd_status & (RBD_EOF | RBD_ACNTVALID)) == (RBD_EOF | RBD_ACNTVALID)) {
@@ -891,27 +884,27 @@ ether1_recv_done (struct net_device *dev)
skb->protocol = eth_type_trans (skb, dev);
netif_rx (skb);
- priv->stats.rx_packets ++;
+ priv(dev)->stats.rx_packets ++;
} else
- priv->stats.rx_dropped ++;
+ priv(dev)->stats.rx_dropped ++;
} else {
printk(KERN_WARNING "%s: %s\n", dev->name,
(rbd.rbd_status & RBD_EOF) ? "oversized packet" : "acnt not valid");
- priv->stats.rx_dropped ++;
+ priv(dev)->stats.rx_dropped ++;
}
- nexttail = ether1_inw (dev, priv->rx_tail, rfd_t, rfd_link, NORMALIRQS);
+ nexttail = ether1_readw(dev, priv(dev)->rx_tail, rfd_t, rfd_link, NORMALIRQS);
/* nexttail should be rx_head */
- if (nexttail != priv->rx_head)
+ if (nexttail != priv(dev)->rx_head)
printk(KERN_ERR "%s: receiver buffer chaining error (%04X != %04X)\n",
- dev->name, nexttail, priv->rx_head);
- ether1_outw (dev, RFD_CMDEL | RFD_CMDSUSPEND, nexttail, rfd_t, rfd_command, NORMALIRQS);
- ether1_outw (dev, 0, priv->rx_tail, rfd_t, rfd_command, NORMALIRQS);
- ether1_outw (dev, 0, priv->rx_tail, rfd_t, rfd_status, NORMALIRQS);
- ether1_outw (dev, 0, priv->rx_tail, rfd_t, rfd_rbdoffset, NORMALIRQS);
+ dev->name, nexttail, priv(dev)->rx_head);
+ ether1_writew(dev, RFD_CMDEL | RFD_CMDSUSPEND, nexttail, rfd_t, rfd_command, NORMALIRQS);
+ ether1_writew(dev, 0, priv(dev)->rx_tail, rfd_t, rfd_command, NORMALIRQS);
+ ether1_writew(dev, 0, priv(dev)->rx_tail, rfd_t, rfd_status, NORMALIRQS);
+ ether1_writew(dev, 0, priv(dev)->rx_tail, rfd_t, rfd_rbdoffset, NORMALIRQS);
- priv->rx_tail = nexttail;
- priv->rx_head = ether1_inw (dev, priv->rx_head, rfd_t, rfd_link, NORMALIRQS);
+ priv(dev)->rx_tail = nexttail;
+ priv(dev)->rx_head = ether1_readw(dev, priv(dev)->rx_head, rfd_t, rfd_link, NORMALIRQS);
} while (1);
}
@@ -919,48 +912,47 @@ static irqreturn_t
ether1_interrupt (int irq, void *dev_id, struct pt_regs *regs)
{
struct net_device *dev = (struct net_device *)dev_id;
- struct ether1_priv *priv = netdev_priv(dev);
int status;
- status = ether1_inw (dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS);
+ status = ether1_readw(dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS);
if (status) {
- ether1_outw(dev, status & (SCB_STRNR | SCB_STCNA | SCB_STFR | SCB_STCX),
+ ether1_writew(dev, status & (SCB_STRNR | SCB_STCNA | SCB_STFR | SCB_STCX),
SCB_ADDR, scb_t, scb_command, NORMALIRQS);
- outb (CTRL_CA | CTRL_ACK, REG_CONTROL);
+ writeb(CTRL_CA | CTRL_ACK, REG_CONTROL);
if (status & SCB_STCX) {
ether1_xmit_done (dev);
}
if (status & SCB_STCNA) {
- if (priv->resetting == 0)
+ if (priv(dev)->resetting == 0)
printk (KERN_WARNING "%s: CU went not ready ???\n", dev->name);
else
- priv->resetting += 1;
- if (ether1_inw (dev, SCB_ADDR, scb_t, scb_cbl_offset, NORMALIRQS)
+ priv(dev)->resetting += 1;
+ if (ether1_readw(dev, SCB_ADDR, scb_t, scb_cbl_offset, NORMALIRQS)
!= (unsigned short)I82586_NULL) {
- ether1_outw (dev, SCB_CMDCUCSTART, SCB_ADDR, scb_t, scb_command, NORMALIRQS);
- outb (CTRL_CA, REG_CONTROL);
+ ether1_writew(dev, SCB_CMDCUCSTART, SCB_ADDR, scb_t, scb_command, NORMALIRQS);
+ writeb(CTRL_CA, REG_CONTROL);
}
- if (priv->resetting == 2)
- priv->resetting = 0;
+ if (priv(dev)->resetting == 2)
+ priv(dev)->resetting = 0;
}
if (status & SCB_STFR) {
ether1_recv_done (dev);
}
if (status & SCB_STRNR) {
- if (ether1_inw (dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS) & SCB_STRXSUSP) {
+ if (ether1_readw(dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS) & SCB_STRXSUSP) {
printk (KERN_WARNING "%s: RU went not ready: RU suspended\n", dev->name);
- ether1_outw (dev, SCB_CMDRXRESUME, SCB_ADDR, scb_t, scb_command, NORMALIRQS);
- outb (CTRL_CA, REG_CONTROL);
- priv->stats.rx_dropped ++; /* we suspended due to lack of buffer space */
+ ether1_writew(dev, SCB_CMDRXRESUME, SCB_ADDR, scb_t, scb_command, NORMALIRQS);
+ writeb(CTRL_CA, REG_CONTROL);
+ priv(dev)->stats.rx_dropped ++; /* we suspended due to lack of buffer space */
} else
printk(KERN_WARNING "%s: RU went not ready: %04X\n", dev->name,
- ether1_inw (dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS));
- printk (KERN_WARNING "RU ptr = %04X\n", ether1_inw (dev, SCB_ADDR, scb_t, scb_rfa_offset,
+ ether1_readw(dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS));
+ printk (KERN_WARNING "RU ptr = %04X\n", ether1_readw(dev, SCB_ADDR, scb_t, scb_rfa_offset,
NORMALIRQS));
}
} else
- outb (CTRL_ACK, REG_CONTROL);
+ writeb(CTRL_ACK, REG_CONTROL);
return IRQ_HANDLED;
}
@@ -978,8 +970,7 @@ ether1_close (struct net_device *dev)
static struct net_device_stats *
ether1_getstats (struct net_device *dev)
{
- struct ether1_priv *priv = netdev_priv(dev);
- return &priv->stats;
+ return &priv(dev)->stats;
}
/*
@@ -1008,40 +999,42 @@ static int __devinit
ether1_probe(struct expansion_card *ec, const struct ecard_id *id)
{
struct net_device *dev;
- struct ether1_priv *priv;
int i, ret = 0;
ether1_banner();
+ ret = ecard_request_resources(ec);
+ if (ret)
+ goto out;
+
dev = alloc_etherdev(sizeof(struct ether1_priv));
if (!dev) {
ret = -ENOMEM;
- goto out;
+ goto release;
}
SET_MODULE_OWNER(dev);
+ SET_NETDEV_DEV(dev, &ec->dev);
- dev->base_addr = ecard_address(ec, ECARD_IOC, ECARD_FAST);
- dev->irq = ec->irq;
-
- /*
- * these will not fail - the nature of the bus ensures this
- */
- request_region(dev->base_addr, 16, dev->name);
- request_region(dev->base_addr + 0x800, 4096, dev->name);
+ dev->irq = ec->irq;
+ priv(dev)->base = ioremap(ecard_resource_start(ec, ECARD_RES_IOCFAST),
+ ecard_resource_len(ec, ECARD_RES_IOCFAST));
+ if (!priv(dev)->base) {
+ ret = -ENOMEM;
+ goto free;
+ }
- priv = netdev_priv(dev);
- if ((priv->bus_type = ether1_reset(dev)) == 0) {
+ if ((priv(dev)->bus_type = ether1_reset(dev)) == 0) {
ret = -ENODEV;
- goto release;
+ goto free;
}
for (i = 0; i < 6; i++)
- dev->dev_addr[i] = inb(IDPROM_ADDRESS + i);
+ dev->dev_addr[i] = readb(IDPROM_ADDRESS + (i << 2));
if (ether1_init_2(dev)) {
ret = -ENODEV;
- goto release;
+ goto free;
}
dev->open = ether1_open;
@@ -1054,7 +1047,7 @@ ether1_probe(struct expansion_card *ec, const struct ecard_id *id)
ret = register_netdev(dev);
if (ret)
- goto release;
+ goto free;
printk(KERN_INFO "%s: ether1 in slot %d, ",
dev->name, ec->slot_no);
@@ -1065,11 +1058,13 @@ ether1_probe(struct expansion_card *ec, const struct ecard_id *id)
ecard_set_drvdata(ec, dev);
return 0;
-release:
- release_region(dev->base_addr, 16);
- release_region(dev->base_addr + 0x800, 4096);
+ free:
+ if (priv(dev)->base)
+ iounmap(priv(dev)->base);
free_netdev(dev);
-out:
+ release:
+ ecard_release_resources(ec);
+ out:
return ret;
}
@@ -1080,10 +1075,9 @@ static void __devexit ether1_remove(struct expansion_card *ec)
ecard_set_drvdata(ec, NULL);
unregister_netdev(dev);
-
- release_region(dev->base_addr, 16);
- release_region(dev->base_addr + 0x800, 4096);
+ iounmap(priv(dev)->base);
free_netdev(dev);
+ ecard_release_resources(ec);
}
static const struct ecard_id ether1_ids[] = {
diff --git a/drivers/net/arm/ether1.h b/drivers/net/arm/ether1.h
index 790bb97cac292..c8a4b2389d854 100644
--- a/drivers/net/arm/ether1.h
+++ b/drivers/net/arm/ether1.h
@@ -19,22 +19,25 @@
#define NET_DEBUG 0
#endif
+#define priv(dev) ((struct ether1_priv *)netdev_priv(dev))
+
/* Page register */
-#define REG_PAGE (dev->base_addr + 0x00)
+#define REG_PAGE (priv(dev)->base + 0x0000)
/* Control register */
-#define REG_CONTROL (dev->base_addr + 0x01)
+#define REG_CONTROL (priv(dev)->base + 0x0004)
#define CTRL_RST 0x01
#define CTRL_LOOPBACK 0x02
#define CTRL_CA 0x04
#define CTRL_ACK 0x08
-#define ETHER1_RAM (dev->base_addr + 0x800)
+#define ETHER1_RAM (priv(dev)->base + 0x2000)
/* HW address */
-#define IDPROM_ADDRESS (dev->base_addr + 0x09)
+#define IDPROM_ADDRESS (priv(dev)->base + 0x0024)
struct ether1_priv {
+ void __iomem *base;
struct net_device_stats stats;
unsigned int tx_link;
unsigned int tx_head;
diff --git a/drivers/net/arm/ether3.c b/drivers/net/arm/ether3.c
index e0d22a31ea121..1cc53abc3a390 100644
--- a/drivers/net/arm/ether3.c
+++ b/drivers/net/arm/ether3.c
@@ -78,8 +78,8 @@ static char version[] __initdata = "ether3 ethernet driver (c) 1995-2000 R.M.Kin
static unsigned int net_debug = NET_DEBUG;
static void ether3_setmulticastlist(struct net_device *dev);
-static int ether3_rx(struct net_device *dev, struct dev_priv *priv, unsigned int maxcnt);
-static void ether3_tx(struct net_device *dev, struct dev_priv *priv);
+static int ether3_rx(struct net_device *dev, unsigned int maxcnt);
+static void ether3_tx(struct net_device *dev);
static int ether3_open (struct net_device *dev);
static int ether3_sendpacket (struct sk_buff *skb, struct net_device *dev);
static irqreturn_t ether3_interrupt (int irq, void *dev_id, struct pt_regs *regs);
@@ -104,33 +104,32 @@ typedef enum {
* The SEEQ8005 doesn't like us writing to its registers
* too quickly.
*/
-static inline void ether3_outb(int v, const int r)
+static inline void ether3_outb(int v, const void __iomem *r)
{
- outb(v, r);
+ writeb(v, r);
udelay(1);
}
-static inline void ether3_outw(int v, const int r)
+static inline void ether3_outw(int v, const void __iomem *r)
{
- outw(v, r);
+ writew(v, r);
udelay(1);
}
-#define ether3_inb(r) ({ unsigned int __v = inb((r)); udelay(1); __v; })
-#define ether3_inw(r) ({ unsigned int __v = inw((r)); udelay(1); __v; })
+#define ether3_inb(r) ({ unsigned int __v = readb((r)); udelay(1); __v; })
+#define ether3_inw(r) ({ unsigned int __v = readw((r)); udelay(1); __v; })
static int
ether3_setbuffer(struct net_device *dev, buffer_rw_t read, int start)
{
- struct dev_priv *priv = netdev_priv(dev);
int timeout = 1000;
- ether3_outw(priv->regs.config1 | CFG1_LOCBUFMEM, REG_CONFIG1);
- ether3_outw(priv->regs.command | CMD_FIFOWRITE, REG_COMMAND);
+ ether3_outw(priv(dev)->regs.config1 | CFG1_LOCBUFMEM, REG_CONFIG1);
+ ether3_outw(priv(dev)->regs.command | CMD_FIFOWRITE, REG_COMMAND);
while ((ether3_inw(REG_STATUS) & STAT_FIFOEMPTY) == 0) {
if (!timeout--) {
printk("%s: setbuffer broken\n", dev->name);
- priv->broken = 1;
+ priv(dev)->broken = 1;
return 1;
}
udelay(1);
@@ -138,9 +137,9 @@ ether3_setbuffer(struct net_device *dev, buffer_rw_t read, int start)
if (read == buffer_read) {
ether3_outw(start, REG_DMAADDR);
- ether3_outw(priv->regs.command | CMD_FIFOREAD, REG_COMMAND);
+ ether3_outw(priv(dev)->regs.command | CMD_FIFOREAD, REG_COMMAND);
} else {
- ether3_outw(priv->regs.command | CMD_FIFOWRITE, REG_COMMAND);
+ ether3_outw(priv(dev)->regs.command | CMD_FIFOWRITE, REG_COMMAND);
ether3_outw(start, REG_DMAADDR);
}
return 0;
@@ -150,53 +149,50 @@ ether3_setbuffer(struct net_device *dev, buffer_rw_t read, int start)
* write data to the buffer memory
*/
#define ether3_writebuffer(dev,data,length) \
- outsw(REG_BUFWIN, (data), (length) >> 1)
+ writesw(REG_BUFWIN, (data), (length) >> 1)
#define ether3_writeword(dev,data) \
- outw((data), REG_BUFWIN)
+ writew((data), REG_BUFWIN)
#define ether3_writelong(dev,data) { \
- unsigned long reg_bufwin = REG_BUFWIN; \
- outw((data), reg_bufwin); \
- outw((data) >> 16, reg_bufwin); \
+ void __iomem *reg_bufwin = REG_BUFWIN; \
+ writew((data), reg_bufwin); \
+ writew((data) >> 16, reg_bufwin); \
}
/*
* read data from the buffer memory
*/
#define ether3_readbuffer(dev,data,length) \
- insw(REG_BUFWIN, (data), (length) >> 1)
+ readsw(REG_BUFWIN, (data), (length) >> 1)
#define ether3_readword(dev) \
- inw(REG_BUFWIN)
+ readw(REG_BUFWIN)
#define ether3_readlong(dev) \
- inw(REG_BUFWIN) | (inw(REG_BUFWIN) << 16)
+ readw(REG_BUFWIN) | (readw(REG_BUFWIN) << 16)
/*
* Switch LED off...
*/
-static void
-ether3_ledoff(unsigned long data)
+static void ether3_ledoff(unsigned long data)
{
struct net_device *dev = (struct net_device *)data;
- struct dev_priv *priv = netdev_priv(dev);
- ether3_outw(priv->regs.config2 |= CFG2_CTRLO, REG_CONFIG2);
+ ether3_outw(priv(dev)->regs.config2 |= CFG2_CTRLO, REG_CONFIG2);
}
/*
* switch LED on...
*/
-static inline void
-ether3_ledon(struct net_device *dev, struct dev_priv *priv)
+static inline void ether3_ledon(struct net_device *dev)
{
- del_timer(&priv->timer);
- priv->timer.expires = jiffies + HZ / 50; /* leave on for 1/50th second */
- priv->timer.data = (unsigned long)dev;
- priv->timer.function = ether3_ledoff;
- add_timer(&priv->timer);
- if (priv->regs.config2 & CFG2_CTRLO)
- ether3_outw(priv->regs.config2 &= ~CFG2_CTRLO, REG_CONFIG2);
+ del_timer(&priv(dev)->timer);
+ priv(dev)->timer.expires = jiffies + HZ / 50; /* leave on for 1/50th second */
+ priv(dev)->timer.data = (unsigned long)dev;
+ priv(dev)->timer.function = ether3_ledoff;
+ add_timer(&priv(dev)->timer);
+ if (priv(dev)->regs.config2 & CFG2_CTRLO)
+ ether3_outw(priv(dev)->regs.config2 &= ~CFG2_CTRLO, REG_CONFIG2);
}
/*
@@ -277,43 +273,41 @@ ether3_ramtest(struct net_device *dev, unsigned char byte)
/* ------------------------------------------------------------------------------- */
-static int __init
-ether3_init_2(struct net_device *dev)
+static int __init ether3_init_2(struct net_device *dev)
{
- struct dev_priv *priv = netdev_priv(dev);
int i;
- priv->regs.config1 = CFG1_RECVCOMPSTAT0|CFG1_DMABURST8;
- priv->regs.config2 = CFG2_CTRLO|CFG2_RECVCRC|CFG2_ERRENCRC;
- priv->regs.command = 0;
+ priv(dev)->regs.config1 = CFG1_RECVCOMPSTAT0|CFG1_DMABURST8;
+ priv(dev)->regs.config2 = CFG2_CTRLO|CFG2_RECVCRC|CFG2_ERRENCRC;
+ priv(dev)->regs.command = 0;
/*
* Set up our hardware address
*/
- ether3_outw(priv->regs.config1 | CFG1_BUFSELSTAT0, REG_CONFIG1);
+ ether3_outw(priv(dev)->regs.config1 | CFG1_BUFSELSTAT0, REG_CONFIG1);
for (i = 0; i < 6; i++)
ether3_outb(dev->dev_addr[i], REG_BUFWIN);
if (dev->flags & IFF_PROMISC)
- priv->regs.config1 |= CFG1_RECVPROMISC;
+ priv(dev)->regs.config1 |= CFG1_RECVPROMISC;
else if (dev->flags & IFF_MULTICAST)
- priv->regs.config1 |= CFG1_RECVSPECBRMULTI;
+ priv(dev)->regs.config1 |= CFG1_RECVSPECBRMULTI;
else
- priv->regs.config1 |= CFG1_RECVSPECBROAD;
+ priv(dev)->regs.config1 |= CFG1_RECVSPECBROAD;
/*
* There is a problem with the NQ8005 in that it occasionally loses the
* last two bytes. To get round this problem, we receive the CRC as
* well. That way, if we do lose the last two, then it doesn't matter.
*/
- ether3_outw(priv->regs.config1 | CFG1_TRANSEND, REG_CONFIG1);
+ ether3_outw(priv(dev)->regs.config1 | CFG1_TRANSEND, REG_CONFIG1);
ether3_outw((TX_END>>8) - 1, REG_BUFWIN);
- ether3_outw(priv->rx_head, REG_RECVPTR);
+ ether3_outw(priv(dev)->rx_head, REG_RECVPTR);
ether3_outw(0, REG_TRANSMITPTR);
- ether3_outw(priv->rx_head >> 8, REG_RECVEND);
- ether3_outw(priv->regs.config2, REG_CONFIG2);
- ether3_outw(priv->regs.config1 | CFG1_LOCBUFMEM, REG_CONFIG1);
- ether3_outw(priv->regs.command, REG_COMMAND);
+ ether3_outw(priv(dev)->rx_head >> 8, REG_RECVEND);
+ ether3_outw(priv(dev)->regs.config2, REG_CONFIG2);
+ ether3_outw(priv(dev)->regs.config1 | CFG1_LOCBUFMEM, REG_CONFIG1);
+ ether3_outw(priv(dev)->regs.command, REG_COMMAND);
i = ether3_ramtest(dev, 0x5A);
if(i)
@@ -330,41 +324,41 @@ ether3_init_2(struct net_device *dev)
static void
ether3_init_for_open(struct net_device *dev)
{
- struct dev_priv *priv = netdev_priv(dev);
int i;
- memset(&priv->stats, 0, sizeof(struct net_device_stats));
+ memset(&priv(dev)->stats, 0, sizeof(struct net_device_stats));
/* Reset the chip */
ether3_outw(CFG2_RESET, REG_CONFIG2);
udelay(4);
- priv->regs.command = 0;
+ priv(dev)->regs.command = 0;
ether3_outw(CMD_RXOFF|CMD_TXOFF, REG_COMMAND);
- while (ether3_inw(REG_STATUS) & (STAT_RXON|STAT_TXON));
+ while (ether3_inw(REG_STATUS) & (STAT_RXON|STAT_TXON))
+ barrier();
- ether3_outw(priv->regs.config1 | CFG1_BUFSELSTAT0, REG_CONFIG1);
+ ether3_outw(priv(dev)->regs.config1 | CFG1_BUFSELSTAT0, REG_CONFIG1);
for (i = 0; i < 6; i++)
ether3_outb(dev->dev_addr[i], REG_BUFWIN);
- priv->tx_head = 0;
- priv->tx_tail = 0;
- priv->regs.config2 |= CFG2_CTRLO;
- priv->rx_head = RX_START;
+ priv(dev)->tx_head = 0;
+ priv(dev)->tx_tail = 0;
+ priv(dev)->regs.config2 |= CFG2_CTRLO;
+ priv(dev)->rx_head = RX_START;
- ether3_outw(priv->regs.config1 | CFG1_TRANSEND, REG_CONFIG1);
+ ether3_outw(priv(dev)->regs.config1 | CFG1_TRANSEND, REG_CONFIG1);
ether3_outw((TX_END>>8) - 1, REG_BUFWIN);
- ether3_outw(priv->rx_head, REG_RECVPTR);
- ether3_outw(priv->rx_head >> 8, REG_RECVEND);
+ ether3_outw(priv(dev)->rx_head, REG_RECVPTR);
+ ether3_outw(priv(dev)->rx_head >> 8, REG_RECVEND);
ether3_outw(0, REG_TRANSMITPTR);
- ether3_outw(priv->regs.config2, REG_CONFIG2);
- ether3_outw(priv->regs.config1 | CFG1_LOCBUFMEM, REG_CONFIG1);
+ ether3_outw(priv(dev)->regs.config2, REG_CONFIG2);
+ ether3_outw(priv(dev)->regs.config1 | CFG1_LOCBUFMEM, REG_CONFIG1);
ether3_setbuffer(dev, buffer_write, 0);
ether3_writelong(dev, 0);
- priv->regs.command = CMD_ENINTRX | CMD_ENINTTX;
- ether3_outw(priv->regs.command | CMD_RXON, REG_COMMAND);
+ priv(dev)->regs.command = CMD_ENINTRX | CMD_ENINTTX;
+ ether3_outw(priv(dev)->regs.command | CMD_RXON, REG_COMMAND);
}
static inline int
@@ -378,10 +372,10 @@ ether3_probe_bus_8(struct net_device *dev, int val)
printk(KERN_DEBUG "ether3_probe: write8 [%02X:%02X]", write_high, write_low);
ether3_outb(write_low, REG_RECVPTR);
- ether3_outb(write_high, REG_RECVPTR + 1);
+ ether3_outb(write_high, REG_RECVPTR + 4);
read_low = ether3_inb(REG_RECVPTR);
- read_high = ether3_inb(REG_RECVPTR + 1);
+ read_high = ether3_inb(REG_RECVPTR + 4);
printk(", read8 [%02X:%02X]\n", read_high, read_low);
@@ -434,16 +428,15 @@ ether3_open(struct net_device *dev)
static int
ether3_close(struct net_device *dev)
{
- struct dev_priv *priv = netdev_priv(dev);
-
netif_stop_queue(dev);
disable_irq(dev->irq);
ether3_outw(CMD_RXOFF|CMD_TXOFF, REG_COMMAND);
- priv->regs.command = 0;
- while (ether3_inw(REG_STATUS) & (STAT_RXON|STAT_TXON));
- ether3_outb(0x80, REG_CONFIG2 + 1);
+ priv(dev)->regs.command = 0;
+ while (ether3_inw(REG_STATUS) & (STAT_RXON|STAT_TXON))
+ barrier();
+ ether3_outb(0x80, REG_CONFIG2 + 4);
ether3_outw(0, REG_COMMAND);
free_irq(dev->irq, dev);
@@ -457,8 +450,7 @@ ether3_close(struct net_device *dev)
*/
static struct net_device_stats *ether3_getstats(struct net_device *dev)
{
- struct dev_priv *priv = netdev_priv(dev);
- return &priv->stats;
+ return &priv(dev)->stats;
}
/*
@@ -469,28 +461,24 @@ static struct net_device_stats *ether3_getstats(struct net_device *dev)
*/
static void ether3_setmulticastlist(struct net_device *dev)
{
- struct dev_priv *priv = netdev_priv(dev);
-
- priv->regs.config1 &= ~CFG1_RECVPROMISC;
+ priv(dev)->regs.config1 &= ~CFG1_RECVPROMISC;
if (dev->flags & IFF_PROMISC) {
/* promiscuous mode */
- priv->regs.config1 |= CFG1_RECVPROMISC;
+ priv(dev)->regs.config1 |= CFG1_RECVPROMISC;
} else if (dev->flags & IFF_ALLMULTI) {
- priv->regs.config1 |= CFG1_RECVSPECBRMULTI;
+ priv(dev)->regs.config1 |= CFG1_RECVSPECBRMULTI;
} else
- priv->regs.config1 |= CFG1_RECVSPECBROAD;
+ priv(dev)->regs.config1 |= CFG1_RECVSPECBROAD;
- ether3_outw(priv->regs.config1 | CFG1_LOCBUFMEM, REG_CONFIG1);
+ ether3_outw(priv(dev)->regs.config1 | CFG1_LOCBUFMEM, REG_CONFIG1);
}
-static void
-ether3_timeout(struct net_device *dev)
+static void ether3_timeout(struct net_device *dev)
{
- struct dev_priv *priv = netdev_priv(dev);
unsigned long flags;
- del_timer(&priv->timer);
+ del_timer(&priv(dev)->timer);
local_irq_save(flags);
printk(KERN_ERR "%s: transmit timed out, network cable problem?\n", dev->name);
@@ -499,15 +487,15 @@ ether3_timeout(struct net_device *dev)
printk(KERN_ERR "%s: { rpr=%04X rea=%04X tpr=%04X }\n", dev->name,
ether3_inw(REG_RECVPTR), ether3_inw(REG_RECVEND), ether3_inw(REG_TRANSMITPTR));
printk(KERN_ERR "%s: tx head=%X tx tail=%X\n", dev->name,
- priv->tx_head, priv->tx_tail);
- ether3_setbuffer(dev, buffer_read, priv->tx_tail);
+ priv(dev)->tx_head, priv(dev)->tx_tail);
+ ether3_setbuffer(dev, buffer_read, priv(dev)->tx_tail);
printk(KERN_ERR "%s: packet status = %08X\n", dev->name, ether3_readlong(dev));
local_irq_restore(flags);
- priv->regs.config2 |= CFG2_CTRLO;
- priv->stats.tx_errors += 1;
- ether3_outw(priv->regs.config2, REG_CONFIG2);
- priv->tx_head = priv->tx_tail = 0;
+ priv(dev)->regs.config2 |= CFG2_CTRLO;
+ priv(dev)->stats.tx_errors += 1;
+ ether3_outw(priv(dev)->regs.config2, REG_CONFIG2);
+ priv(dev)->tx_head = priv(dev)->tx_tail = 0;
netif_wake_queue(dev);
}
@@ -518,14 +506,13 @@ ether3_timeout(struct net_device *dev)
static int
ether3_sendpacket(struct sk_buff *skb, struct net_device *dev)
{
- struct dev_priv *priv = netdev_priv(dev);
unsigned long flags;
unsigned int length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
unsigned int ptr, next_ptr;
- if (priv->broken) {
+ if (priv(dev)->broken) {
dev_kfree_skb(skb);
- priv->stats.tx_dropped ++;
+ priv(dev)->stats.tx_dropped ++;
netif_start_queue(dev);
return 0;
}
@@ -537,18 +524,18 @@ ether3_sendpacket(struct sk_buff *skb, struct net_device *dev)
goto out;
}
- next_ptr = (priv->tx_head + 1) & 15;
+ next_ptr = (priv(dev)->tx_head + 1) & 15;
local_irq_save(flags);
- if (priv->tx_tail == next_ptr) {
+ if (priv(dev)->tx_tail == next_ptr) {
local_irq_restore(flags);
return 1; /* unable to queue */
}
dev->trans_start = jiffies;
- ptr = 0x600 * priv->tx_head;
- priv->tx_head = next_ptr;
+ ptr = 0x600 * priv(dev)->tx_head;
+ priv(dev)->tx_head = next_ptr;
next_ptr *= 0x600;
#define TXHDR_FLAGS (TXHDR_TRANSMIT|TXHDR_CHAINCONTINUE|TXHDR_DATAFOLLOWS|TXHDR_ENSUCCESS)
@@ -563,19 +550,19 @@ ether3_sendpacket(struct sk_buff *skb, struct net_device *dev)
ether3_setbuffer(dev, buffer_write, ptr);
ether3_writeword(dev, htons((ptr + length + 4)));
ether3_writeword(dev, TXHDR_FLAGS >> 16);
- ether3_ledon(dev, priv);
+ ether3_ledon(dev);
if (!(ether3_inw(REG_STATUS) & STAT_TXON)) {
ether3_outw(ptr, REG_TRANSMITPTR);
- ether3_outw(priv->regs.command | CMD_TXON, REG_COMMAND);
+ ether3_outw(priv(dev)->regs.command | CMD_TXON, REG_COMMAND);
}
- next_ptr = (priv->tx_head + 1) & 15;
+ next_ptr = (priv(dev)->tx_head + 1) & 15;
local_irq_restore(flags);
dev_kfree_skb(skb);
- if (priv->tx_tail == next_ptr)
+ if (priv(dev)->tx_tail == next_ptr)
netif_stop_queue(dev);
out:
@@ -586,7 +573,6 @@ static irqreturn_t
ether3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
struct net_device *dev = (struct net_device *)dev_id;
- struct dev_priv *priv;
unsigned int status, handled = IRQ_NONE;
#if NET_DEBUG > 1
@@ -594,19 +580,17 @@ ether3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
printk("eth3irq: %d ", irq);
#endif
- priv = netdev_priv(dev);
-
status = ether3_inw(REG_STATUS);
if (status & STAT_INTRX) {
- ether3_outw(CMD_ACKINTRX | priv->regs.command, REG_COMMAND);
- ether3_rx(dev, priv, 12);
+ ether3_outw(CMD_ACKINTRX | priv(dev)->regs.command, REG_COMMAND);
+ ether3_rx(dev, 12);
handled = IRQ_HANDLED;
}
if (status & STAT_INTTX) {
- ether3_outw(CMD_ACKINTTX | priv->regs.command, REG_COMMAND);
- ether3_tx(dev, priv);
+ ether3_outw(CMD_ACKINTTX | priv(dev)->regs.command, REG_COMMAND);
+ ether3_tx(dev);
handled = IRQ_HANDLED;
}
@@ -620,11 +604,11 @@ ether3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
/*
* If we have a good packet(s), get it/them out of the buffers.
*/
-static int
-ether3_rx(struct net_device *dev, struct dev_priv *priv, unsigned int maxcnt)
+static int ether3_rx(struct net_device *dev, unsigned int maxcnt)
{
- unsigned int next_ptr = priv->rx_head, received = 0;
- ether3_ledon(dev, priv);
+ unsigned int next_ptr = priv(dev)->rx_head, received = 0;
+
+ ether3_ledon(dev);
do {
unsigned int this_ptr, status;
@@ -653,12 +637,12 @@ ether3_rx(struct net_device *dev, struct dev_priv *priv, unsigned int maxcnt)
if (next_ptr < RX_START || next_ptr >= RX_END) {
int i;
- printk("%s: bad next pointer @%04X: ", dev->name, priv->rx_head);
+ printk("%s: bad next pointer @%04X: ", dev->name, priv(dev)->rx_head);
printk("%02X %02X %02X %02X ", next_ptr >> 8, next_ptr & 255, status & 255, status >> 8);
for (i = 2; i < 14; i++)
printk("%02X ", addrs[i]);
printk("\n");
- next_ptr = priv->rx_head;
+ next_ptr = priv(dev)->rx_head;
break;
}
/*
@@ -695,7 +679,7 @@ if (next_ptr < RX_START || next_ptr >= RX_END) {
} else
goto dropping;
} else {
- struct net_device_stats *stats = &priv->stats;
+ struct net_device_stats *stats = &priv(dev)->stats;
ether3_outw(next_ptr >> 8, REG_RECVEND);
if (status & RXSTAT_OVERSIZE) stats->rx_over_errors ++;
if (status & RXSTAT_CRCERROR) stats->rx_crc_errors ++;
@@ -707,16 +691,16 @@ if (next_ptr < RX_START || next_ptr >= RX_END) {
while (-- maxcnt);
done:
- priv->stats.rx_packets += received;
- priv->rx_head = next_ptr;
+ priv(dev)->stats.rx_packets += received;
+ priv(dev)->rx_head = next_ptr;
/*
* If rx went off line, then that means that the buffer may be full. We
* have dropped at least one packet.
*/
if (!(ether3_inw(REG_STATUS) & STAT_RXON)) {
- priv->stats.rx_dropped ++;
+ priv(dev)->stats.rx_dropped ++;
ether3_outw(next_ptr, REG_RECVPTR);
- ether3_outw(priv->regs.command | CMD_RXON, REG_COMMAND);
+ ether3_outw(priv(dev)->regs.command | CMD_RXON, REG_COMMAND);
}
return maxcnt;
@@ -732,7 +716,7 @@ dropping:{
last_warned = jiffies;
printk("%s: memory squeeze, dropping packet.\n", dev->name);
}
- priv->stats.rx_dropped ++;
+ priv(dev)->stats.rx_dropped ++;
goto done;
}
}
@@ -740,10 +724,9 @@ dropping:{
/*
* Update stats for the transmitted packet(s)
*/
-static void
-ether3_tx(struct net_device *dev, struct dev_priv *priv)
+static void ether3_tx(struct net_device *dev)
{
- unsigned int tx_tail = priv->tx_tail;
+ unsigned int tx_tail = priv(dev)->tx_tail;
int max_work = 14;
do {
@@ -766,18 +749,20 @@ ether3_tx(struct net_device *dev, struct dev_priv *priv)
* Update errors
*/
if (!(status & (TXSTAT_BABBLED | TXSTAT_16COLLISIONS)))
- priv->stats.tx_packets++;
+ priv(dev)->stats.tx_packets++;
else {
- priv->stats.tx_errors ++;
- if (status & TXSTAT_16COLLISIONS) priv->stats.collisions += 16;
- if (status & TXSTAT_BABBLED) priv->stats.tx_fifo_errors ++;
+ priv(dev)->stats.tx_errors ++;
+ if (status & TXSTAT_16COLLISIONS)
+ priv(dev)->stats.collisions += 16;
+ if (status & TXSTAT_BABBLED)
+ priv(dev)->stats.tx_fifo_errors ++;
}
tx_tail = (tx_tail + 1) & 15;
} while (--max_work);
- if (priv->tx_tail != tx_tail) {
- priv->tx_tail = tx_tail;
+ if (priv(dev)->tx_tail != tx_tail) {
+ priv(dev)->tx_tail = tx_tail;
netif_wake_queue(dev);
}
}
@@ -790,66 +775,48 @@ static void __init ether3_banner(void)
printk(KERN_INFO "%s", version);
}
-static const char * __init
-ether3_get_dev(struct net_device *dev, struct expansion_card *ec)
-{
- const char *name = "ether3";
-
- dev->base_addr = ecard_address(ec, ECARD_MEMC, 0);
- dev->irq = ec->irq;
-
- if (ec->cid.manufacturer == MANU_ANT &&
- ec->cid.product == PROD_ANT_ETHERB) {
- dev->base_addr += 0x200;
- name = "etherb";
- }
-
- ec->irqaddr = (volatile unsigned char *)ioaddr(dev->base_addr);
- ec->irqmask = 0xf0;
-
- ether3_addr(dev->dev_addr, ec);
-
- return name;
-}
-
static int __devinit
ether3_probe(struct expansion_card *ec, const struct ecard_id *id)
{
+ const struct ether3_data *data = id->data;
struct net_device *dev;
- struct dev_priv *priv;
- const char *name;
int i, bus_type, ret;
ether3_banner();
+ ret = ecard_request_resources(ec);
+ if (ret)
+ goto out;
+
dev = alloc_etherdev(sizeof(struct dev_priv));
if (!dev) {
ret = -ENOMEM;
- goto out;
+ goto release;
}
SET_MODULE_OWNER(dev);
+ SET_NETDEV_DEV(dev, &ec->dev);
- name = ether3_get_dev(dev, ec);
- if (!name) {
- ret = -ENODEV;
+ priv(dev)->base = ioremap(ecard_resource_start(ec, ECARD_RES_MEMC),
+ ecard_resource_len(ec, ECARD_RES_MEMC));
+ if (!priv(dev)->base) {
+ ret = -ENOMEM;
goto free;
}
- /*
- * this will not fail - the nature of the bus ensures this
- */
- if (!request_region(dev->base_addr, 128, dev->name)) {
- ret = -EBUSY;
- goto free;
- }
+ ec->irqaddr = priv(dev)->base + data->base_offset;
+ ec->irqmask = 0xf0;
+
+ priv(dev)->seeq = priv(dev)->base + data->base_offset;
+ dev->irq = ec->irq;
- priv = netdev_priv(dev);
- init_timer(&priv->timer);
+ ether3_addr(dev->dev_addr, ec);
+
+ init_timer(&priv(dev)->timer);
/* Reset card...
*/
- ether3_outb(0x80, REG_CONFIG2 + 1);
+ ether3_outb(0x80, REG_CONFIG2 + 4);
bus_type = BUS_UNKNOWN;
udelay(4);
@@ -869,13 +836,13 @@ ether3_probe(struct expansion_card *ec, const struct ecard_id *id)
case BUS_UNKNOWN:
printk(KERN_ERR "%s: unable to identify bus width\n", dev->name);
ret = -ENODEV;
- goto failed;
+ goto free;
case BUS_8:
printk(KERN_ERR "%s: %s found, but is an unsupported "
- "8-bit card\n", dev->name, name);
+ "8-bit card\n", dev->name, data->name);
ret = -ENODEV;
- goto failed;
+ goto free;
default:
break;
@@ -883,7 +850,7 @@ ether3_probe(struct expansion_card *ec, const struct ecard_id *id)
if (ether3_init_2(dev)) {
ret = -ENODEV;
- goto failed;
+ goto free;
}
dev->open = ether3_open;
@@ -896,20 +863,22 @@ ether3_probe(struct expansion_card *ec, const struct ecard_id *id)
ret = register_netdev(dev);
if (ret)
- goto failed;
+ goto free;
- printk("%s: %s in slot %d, ", dev->name, name, ec->slot_no);
+ printk("%s: %s in slot %d, ", dev->name, data->name, ec->slot_no);
for (i = 0; i < 6; i++)
printk("%2.2x%c", dev->dev_addr[i], i == 5 ? '\n' : ':');
ecard_set_drvdata(ec, dev);
return 0;
-failed:
- release_region(dev->base_addr, 128);
-free:
+ free:
+ if (priv(dev)->base)
+ iounmap(priv(dev)->base);
free_netdev(dev);
-out:
+ release:
+ ecard_release_resources(ec);
+ out:
return ret;
}
@@ -920,14 +889,25 @@ static void __devexit ether3_remove(struct expansion_card *ec)
ecard_set_drvdata(ec, NULL);
unregister_netdev(dev);
- release_region(dev->base_addr, 128);
+ iounmap(priv(dev)->base);
free_netdev(dev);
+ ecard_release_resources(ec);
}
+static struct ether3_data ether3 = {
+ .name = "ether3",
+ .base_offset = 0,
+};
+
+static struct ether3_data etherb = {
+ .name = "etherb",
+ .base_offset = 0x800,
+};
+
static const struct ecard_id ether3_ids[] = {
- { MANU_ANT2, PROD_ANT_ETHER3 },
- { MANU_ANT, PROD_ANT_ETHER3 },
- { MANU_ANT, PROD_ANT_ETHERB },
+ { MANU_ANT2, PROD_ANT_ETHER3, &ether3 },
+ { MANU_ANT, PROD_ANT_ETHER3, &ether3 },
+ { MANU_ANT, PROD_ANT_ETHERB, &etherb },
{ 0xffff, 0xffff }
};
diff --git a/drivers/net/arm/ether3.h b/drivers/net/arm/ether3.h
index fd0c2edf57fe8..1921a3a07da70 100644
--- a/drivers/net/arm/ether3.h
+++ b/drivers/net/arm/ether3.h
@@ -22,8 +22,10 @@
#define NET_DEBUG 0
#endif
+#define priv(dev) ((struct dev_priv *)netdev_priv(dev))
+
/* Command register definitions & bits */
-#define REG_COMMAND (dev->base_addr + 0x00)
+#define REG_COMMAND (priv(dev)->seeq + 0x0000)
#define CMD_ENINTDMA 0x0001
#define CMD_ENINTRX 0x0002
#define CMD_ENINTTX 0x0004
@@ -42,7 +44,7 @@
#define CMD_FIFOWRITE 0x8000
/* status register */
-#define REG_STATUS (dev->base_addr + 0x00)
+#define REG_STATUS (priv(dev)->seeq + 0x0000)
#define STAT_ENINTSTAT 0x0001
#define STAT_ENINTRX 0x0002
#define STAT_ENINTTX 0x0004
@@ -59,7 +61,7 @@
#define STAT_FIFODIR 0x8000
/* configuration register 1 */
-#define REG_CONFIG1 (dev->base_addr + 0x10)
+#define REG_CONFIG1 (priv(dev)->seeq + 0x0040)
#define CFG1_BUFSELSTAT0 0x0000
#define CFG1_BUFSELSTAT1 0x0001
#define CFG1_BUFSELSTAT2 0x0002
@@ -92,7 +94,7 @@
#define CFG1_RECVCOMPSTAT5 0x2000
/* configuration register 2 */
-#define REG_CONFIG2 (dev->base_addr + 0x20)
+#define REG_CONFIG2 (priv(dev)->seeq + 0x0080)
#define CFG2_BYTESWAP 0x0001
#define CFG2_ERRENCRC 0x0008
#define CFG2_ERRENDRIBBLE 0x0010
@@ -106,15 +108,15 @@
#define CFG2_CTRLO 0x1000
#define CFG2_RESET 0x8000
-#define REG_RECVEND (dev->base_addr + 0x30)
+#define REG_RECVEND (priv(dev)->seeq + 0x00c0)
-#define REG_BUFWIN (dev->base_addr + 0x40)
+#define REG_BUFWIN (priv(dev)->seeq + 0x0100)
-#define REG_RECVPTR (dev->base_addr + 0x50)
+#define REG_RECVPTR (priv(dev)->seeq + 0x0140)
-#define REG_TRANSMITPTR (dev->base_addr + 0x60)
+#define REG_TRANSMITPTR (priv(dev)->seeq + 0x0180)
-#define REG_DMAADDR (dev->base_addr + 0x70)
+#define REG_DMAADDR (priv(dev)->seeq + 0x01c0)
/*
* Cards transmit/receive headers
@@ -152,6 +154,8 @@
#define MAX_TX_BUFFERED 10
struct dev_priv {
+ void __iomem *base;
+ void __iomem *seeq;
struct {
unsigned int command;
unsigned int config1;
@@ -165,4 +169,9 @@ struct dev_priv {
int broken; /* 0 = ok, 1 = something went wrong */
};
+struct ether3_data {
+ const char name[8];
+ unsigned long base_offset;
+};
+
#endif
diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c
index 3328ed511bf8a..5a2efd343db48 100644
--- a/drivers/net/au1000_eth.c
+++ b/drivers/net/au1000_eth.c
@@ -1,10 +1,19 @@
/*
- * Alchemy Semi Au1000 ethernet driver
*
- * Copyright 2001 MontaVista Software Inc.
+ * Alchemy Au1x00 ethernet driver
+ *
+ * Copyright 2001,2002,2003 MontaVista Software Inc.
+ * Copyright 2002 TimeSys Corp.
+ * Added ethtool/mii-tool support,
+ * Copyright 2004 Matt Porter <mporter@kernel.crashing.org>
+ * Update: 2004 Bjoern Riemer, riemer@fokus.fraunhofer.de
+ * or riemer@riemer-nt.de: fixed the link beat detection with
+ * ioctls (SIOCGMIIPHY)
* Author: MontaVista Software, Inc.
* ppopov@mvista.com or source@mvista.com
*
+ * ########################################################################
+ *
* This program is free software; you can distribute it and/or modify it
* under the terms of the GNU General Public License (Version 2) as
* published by the Free Software Foundation.
@@ -17,46 +26,59 @@
* You should have received a copy of the 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/kernel.h>
+#include <linux/sched.h>
#include <linux/string.h>
#include <linux/timer.h>
#include <linux/errno.h>
#include <linux/in.h>
#include <linux/ioport.h>
+#include <linux/bitops.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/mii.h>
#include <linux/skbuff.h>
#include <linux/delay.h>
-#include <linux/crc32.h>
-#include <linux/bitops.h>
-
#include <asm/mipsregs.h>
#include <asm/irq.h>
#include <asm/io.h>
-#include <asm/au1000.h>
+#include <asm/processor.h>
+#include <asm/mach-au1x00/au1000.h>
+#include <asm/cpu.h>
#include "au1000_eth.h"
#ifdef AU1000_ETH_DEBUG
-static int au1000_debug = 10;
+static int au1000_debug = 5;
#else
static int au1000_debug = 3;
#endif
+#define DRV_NAME "au1000eth"
+#define DRV_VERSION "1.5"
+#define DRV_AUTHOR "Pete Popov <ppopov@embeddedalley.com>"
+#define DRV_DESC "Au1xxx on-chip Ethernet driver"
+
+MODULE_AUTHOR(DRV_AUTHOR);
+MODULE_DESCRIPTION(DRV_DESC);
+MODULE_LICENSE("GPL");
+
// prototypes
-static void *dma_alloc(size_t, dma_addr_t *);
-static void dma_free(void *, size_t);
static void hard_stop(struct net_device *);
static void enable_rx_tx(struct net_device *dev);
-static int __init au1000_probe1(long, int, int);
+static struct net_device * au1000_probe(u32 ioaddr, int irq, int port_num);
static int au1000_init(struct net_device *);
static int au1000_open(struct net_device *);
static int au1000_close(struct net_device *);
@@ -78,8 +100,7 @@ static void dump_mii(struct net_device *dev, int phy_id);
// externs
extern void ack_rise_edge_irq(unsigned int);
extern int get_ethernet_addr(char *ethernet_addr);
-extern inline void str2eaddr(unsigned char *ea, unsigned char *str);
-extern inline unsigned char str2hexnum(unsigned char c);
+extern void str2eaddr(unsigned char *ea, unsigned char *str);
extern char * __init prom_getcmdline(void);
/*
@@ -97,29 +118,6 @@ extern char * __init prom_getcmdline(void);
* complete immediately.
*/
-
-/*
- * Base address and interrupt of the Au1xxx ethernet macs
- */
-static struct {
- unsigned int port;
- int irq;
-} au1000_iflist[NUM_INTERFACES] = {
- {AU1000_ETH0_BASE, AU1000_ETH0_IRQ},
- {AU1000_ETH1_BASE, AU1000_ETH1_IRQ}
- },
- au1500_iflist[NUM_INTERFACES] = {
- {AU1500_ETH0_BASE, AU1000_ETH0_IRQ},
- {AU1500_ETH1_BASE, AU1000_ETH1_IRQ}
- },
- au1100_iflist[NUM_INTERFACES] = {
- {AU1000_ETH0_BASE, AU1000_ETH0_IRQ},
- {0, 0}
- };
-
-static char version[] __devinitdata =
- "au1000eth.c:1.0 ppopov@mvista.com\n";
-
/* These addresses are only used if yamon doesn't tell us what
* the mac address is, and the mac address is not passed on the
* command line.
@@ -135,18 +133,36 @@ static unsigned char au1000_mac_addr[6] __devinitdata = {
#define cpu_to_dma32 cpu_to_be32
#define dma32_to_cpu be32_to_cpu
+struct au1000_private *au_macs[NUM_ETH_INTERFACES];
/* FIXME
* All of the PHY code really should be detached from the MAC
* code.
*/
+/* Default advertise */
+#define GENMII_DEFAULT_ADVERTISE \
+ ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | \
+ ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full | \
+ ADVERTISED_Autoneg
+
+#define GENMII_DEFAULT_FEATURES \
+ SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | \
+ SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | \
+ SUPPORTED_Autoneg
+
+static char *phy_link[] =
+{ "unknown",
+ "10Base2", "10BaseT",
+ "AUI",
+ "100BaseT", "100BaseTX", "100BaseFX"
+};
+
int bcm_5201_init(struct net_device *dev, int phy_addr)
{
s16 data;
/* Stop auto-negotiation */
- //printk("bcm_5201_init\n");
data = mdio_read(dev, phy_addr, MII_CONTROL);
mdio_write(dev, phy_addr, MII_CONTROL, data & ~MII_CNTL_AUTO);
@@ -161,17 +177,8 @@ int bcm_5201_init(struct net_device *dev, int phy_addr)
data |= MII_CNTL_RST_AUTO | MII_CNTL_AUTO;
mdio_write(dev, phy_addr, MII_CONTROL, data);
- /* Enable TX LED instead of FDX */
- data = mdio_read(dev, phy_addr, MII_INT);
- data &= ~MII_FDX_LED;
- mdio_write(dev, phy_addr, MII_INT, data);
-
- /* Enable TX LED instead of FDX */
- data = mdio_read(dev, phy_addr, MII_INT);
- data &= ~MII_FDX_LED;
- mdio_write(dev, phy_addr, MII_INT, data);
-
- if (au1000_debug > 4) dump_mii(dev, phy_addr);
+ if (au1000_debug > 4)
+ dump_mii(dev, phy_addr);
return 0;
}
@@ -179,7 +186,6 @@ int bcm_5201_reset(struct net_device *dev, int phy_addr)
{
s16 mii_control, timeout;
- //printk("bcm_5201_reset\n");
mii_control = mdio_read(dev, phy_addr, MII_CONTROL);
mdio_write(dev, phy_addr, MII_CONTROL, mii_control | MII_CNTL_RESET);
mdelay(1);
@@ -242,12 +248,16 @@ int lsi_80227_init(struct net_device *dev, int phy_addr)
printk("lsi_80227_init\n");
/* restart auto-negotiation */
- mdio_write(dev, phy_addr, 0, 0x3200);
-
+ mdio_write(dev, phy_addr, MII_CONTROL,
+ MII_CNTL_F100 | MII_CNTL_AUTO | MII_CNTL_RST_AUTO); // | MII_CNTL_FDX);
mdelay(1);
/* set up LEDs to correct display */
+#ifdef CONFIG_MIPS_MTX1
+ mdio_write(dev, phy_addr, 17, 0xff80);
+#else
mdio_write(dev, phy_addr, 17, 0xffc0);
+#endif
if (au1000_debug > 4)
dump_mii(dev, phy_addr);
@@ -294,9 +304,9 @@ lsi_80227_status(struct net_device *dev, int phy_addr, u16 *link, u16 *speed)
mii_data = mdio_read(dev, aup->phy_addr, MII_STATUS);
if (mii_data & MII_STAT_LINK) {
*link = 1;
- mii_data = mdio_read(dev, aup->phy_addr, MII_LSI_STAT);
- if (mii_data & MII_LSI_STAT_SPD) {
- if (mii_data & MII_LSI_STAT_FDX) {
+ mii_data = mdio_read(dev, aup->phy_addr, MII_LSI_PHY_STAT);
+ if (mii_data & MII_LSI_PHY_STAT_SPD) {
+ if (mii_data & MII_LSI_PHY_STAT_FDX) {
*speed = IF_PORT_100BASEFX;
dev->if_port = IF_PORT_100BASEFX;
}
@@ -337,12 +347,396 @@ am79c901_status(struct net_device *dev, int phy_addr, u16 *link, u16 *speed)
return 0;
}
+int am79c874_init(struct net_device *dev, int phy_addr)
+{
+ s16 data;
+
+ /* 79c874 has quit resembled bit assignments to BCM5201 */
+ if (au1000_debug > 4)
+ printk("am79c847_init\n");
+
+ /* Stop auto-negotiation */
+ data = mdio_read(dev, phy_addr, MII_CONTROL);
+ mdio_write(dev, phy_addr, MII_CONTROL, data & ~MII_CNTL_AUTO);
+
+ /* Set advertisement to 10/100 and Half/Full duplex
+ * (full capabilities) */
+ data = mdio_read(dev, phy_addr, MII_ANADV);
+ data |= MII_NWAY_TX | MII_NWAY_TX_FDX | MII_NWAY_T_FDX | MII_NWAY_T;
+ mdio_write(dev, phy_addr, MII_ANADV, data);
+
+ /* Restart auto-negotiation */
+ data = mdio_read(dev, phy_addr, MII_CONTROL);
+ data |= MII_CNTL_RST_AUTO | MII_CNTL_AUTO;
+
+ mdio_write(dev, phy_addr, MII_CONTROL, data);
+
+ if (au1000_debug > 4) dump_mii(dev, phy_addr);
+ return 0;
+}
+
+int am79c874_reset(struct net_device *dev, int phy_addr)
+{
+ s16 mii_control, timeout;
+
+ if (au1000_debug > 4)
+ printk("am79c874_reset\n");
+
+ mii_control = mdio_read(dev, phy_addr, MII_CONTROL);
+ mdio_write(dev, phy_addr, MII_CONTROL, mii_control | MII_CNTL_RESET);
+ mdelay(1);
+ for (timeout = 100; timeout > 0; --timeout) {
+ mii_control = mdio_read(dev, phy_addr, MII_CONTROL);
+ if ((mii_control & MII_CNTL_RESET) == 0)
+ break;
+ mdelay(1);
+ }
+ if (mii_control & MII_CNTL_RESET) {
+ printk(KERN_ERR "%s PHY reset timeout !\n", dev->name);
+ return -1;
+ }
+ return 0;
+}
+
+int
+am79c874_status(struct net_device *dev, int phy_addr, u16 *link, u16 *speed)
+{
+ u16 mii_data;
+ struct au1000_private *aup;
+
+ // printk("am79c874_status\n");
+ if (!dev) {
+ printk(KERN_ERR "am79c874_status error: NULL dev\n");
+ return -1;
+ }
+
+ aup = (struct au1000_private *) dev->priv;
+ mii_data = mdio_read(dev, aup->phy_addr, MII_STATUS);
+
+ if (mii_data & MII_STAT_LINK) {
+ *link = 1;
+ mii_data = mdio_read(dev, aup->phy_addr, MII_AMD_PHY_STAT);
+ if (mii_data & MII_AMD_PHY_STAT_SPD) {
+ if (mii_data & MII_AMD_PHY_STAT_FDX) {
+ *speed = IF_PORT_100BASEFX;
+ dev->if_port = IF_PORT_100BASEFX;
+ }
+ else {
+ *speed = IF_PORT_100BASETX;
+ dev->if_port = IF_PORT_100BASETX;
+ }
+ }
+ else {
+ *speed = IF_PORT_10BASET;
+ dev->if_port = IF_PORT_10BASET;
+ }
+
+ }
+ else {
+ *link = 0;
+ *speed = 0;
+ dev->if_port = IF_PORT_UNKNOWN;
+ }
+ return 0;
+}
+
+int lxt971a_init(struct net_device *dev, int phy_addr)
+{
+ if (au1000_debug > 4)
+ printk("lxt971a_init\n");
+
+ /* restart auto-negotiation */
+ mdio_write(dev, phy_addr, MII_CONTROL,
+ MII_CNTL_F100 | MII_CNTL_AUTO | MII_CNTL_RST_AUTO | MII_CNTL_FDX);
+
+ /* set up LEDs to correct display */
+ mdio_write(dev, phy_addr, 20, 0x0422);
+
+ if (au1000_debug > 4)
+ dump_mii(dev, phy_addr);
+ return 0;
+}
+
+int lxt971a_reset(struct net_device *dev, int phy_addr)
+{
+ s16 mii_control, timeout;
+
+ if (au1000_debug > 4) {
+ printk("lxt971a_reset\n");
+ dump_mii(dev, phy_addr);
+ }
+
+ mii_control = mdio_read(dev, phy_addr, MII_CONTROL);
+ mdio_write(dev, phy_addr, MII_CONTROL, mii_control | MII_CNTL_RESET);
+ mdelay(1);
+ for (timeout = 100; timeout > 0; --timeout) {
+ mii_control = mdio_read(dev, phy_addr, MII_CONTROL);
+ if ((mii_control & MII_CNTL_RESET) == 0)
+ break;
+ mdelay(1);
+ }
+ if (mii_control & MII_CNTL_RESET) {
+ printk(KERN_ERR "%s PHY reset timeout !\n", dev->name);
+ return -1;
+ }
+ return 0;
+}
+
+int
+lxt971a_status(struct net_device *dev, int phy_addr, u16 *link, u16 *speed)
+{
+ u16 mii_data;
+ struct au1000_private *aup;
+
+ if (!dev) {
+ printk(KERN_ERR "lxt971a_status error: NULL dev\n");
+ return -1;
+ }
+ aup = (struct au1000_private *) dev->priv;
+
+ mii_data = mdio_read(dev, aup->phy_addr, MII_STATUS);
+ if (mii_data & MII_STAT_LINK) {
+ *link = 1;
+ mii_data = mdio_read(dev, aup->phy_addr, MII_INTEL_PHY_STAT);
+ if (mii_data & MII_INTEL_PHY_STAT_SPD) {
+ if (mii_data & MII_INTEL_PHY_STAT_FDX) {
+ *speed = IF_PORT_100BASEFX;
+ dev->if_port = IF_PORT_100BASEFX;
+ }
+ else {
+ *speed = IF_PORT_100BASETX;
+ dev->if_port = IF_PORT_100BASETX;
+ }
+ }
+ else {
+ *speed = IF_PORT_10BASET;
+ dev->if_port = IF_PORT_10BASET;
+ }
+
+ }
+ else {
+ *link = 0;
+ *speed = 0;
+ dev->if_port = IF_PORT_UNKNOWN;
+ }
+ return 0;
+}
+
+int ks8995m_init(struct net_device *dev, int phy_addr)
+{
+ s16 data;
+
+// printk("ks8995m_init\n");
+ /* Stop auto-negotiation */
+ data = mdio_read(dev, phy_addr, MII_CONTROL);
+ mdio_write(dev, phy_addr, MII_CONTROL, data & ~MII_CNTL_AUTO);
+
+ /* Set advertisement to 10/100 and Half/Full duplex
+ * (full capabilities) */
+ data = mdio_read(dev, phy_addr, MII_ANADV);
+ data |= MII_NWAY_TX | MII_NWAY_TX_FDX | MII_NWAY_T_FDX | MII_NWAY_T;
+ mdio_write(dev, phy_addr, MII_ANADV, data);
+
+ /* Restart auto-negotiation */
+ data = mdio_read(dev, phy_addr, MII_CONTROL);
+ data |= MII_CNTL_RST_AUTO | MII_CNTL_AUTO;
+ mdio_write(dev, phy_addr, MII_CONTROL, data);
+
+ if (au1000_debug > 4) dump_mii(dev, phy_addr);
+
+ return 0;
+}
+
+int ks8995m_reset(struct net_device *dev, int phy_addr)
+{
+ s16 mii_control, timeout;
+
+// printk("ks8995m_reset\n");
+ mii_control = mdio_read(dev, phy_addr, MII_CONTROL);
+ mdio_write(dev, phy_addr, MII_CONTROL, mii_control | MII_CNTL_RESET);
+ mdelay(1);
+ for (timeout = 100; timeout > 0; --timeout) {
+ mii_control = mdio_read(dev, phy_addr, MII_CONTROL);
+ if ((mii_control & MII_CNTL_RESET) == 0)
+ break;
+ mdelay(1);
+ }
+ if (mii_control & MII_CNTL_RESET) {
+ printk(KERN_ERR "%s PHY reset timeout !\n", dev->name);
+ return -1;
+ }
+ return 0;
+}
+
+int ks8995m_status(struct net_device *dev, int phy_addr, u16 *link, u16 *speed)
+{
+ u16 mii_data;
+ struct au1000_private *aup;
+
+ if (!dev) {
+ printk(KERN_ERR "ks8995m_status error: NULL dev\n");
+ return -1;
+ }
+ aup = (struct au1000_private *) dev->priv;
+
+ mii_data = mdio_read(dev, aup->phy_addr, MII_STATUS);
+ if (mii_data & MII_STAT_LINK) {
+ *link = 1;
+ mii_data = mdio_read(dev, aup->phy_addr, MII_AUX_CNTRL);
+ if (mii_data & MII_AUX_100) {
+ if (mii_data & MII_AUX_FDX) {
+ *speed = IF_PORT_100BASEFX;
+ dev->if_port = IF_PORT_100BASEFX;
+ }
+ else {
+ *speed = IF_PORT_100BASETX;
+ dev->if_port = IF_PORT_100BASETX;
+ }
+ }
+ else {
+ *speed = IF_PORT_10BASET;
+ dev->if_port = IF_PORT_10BASET;
+ }
+
+ }
+ else {
+ *link = 0;
+ *speed = 0;
+ dev->if_port = IF_PORT_UNKNOWN;
+ }
+ return 0;
+}
+
+int
+smsc_83C185_init (struct net_device *dev, int phy_addr)
+{
+ s16 data;
+
+ if (au1000_debug > 4)
+ printk("smsc_83C185_init\n");
+
+ /* Stop auto-negotiation */
+ data = mdio_read(dev, phy_addr, MII_CONTROL);
+ mdio_write(dev, phy_addr, MII_CONTROL, data & ~MII_CNTL_AUTO);
+
+ /* Set advertisement to 10/100 and Half/Full duplex
+ * (full capabilities) */
+ data = mdio_read(dev, phy_addr, MII_ANADV);
+ data |= MII_NWAY_TX | MII_NWAY_TX_FDX | MII_NWAY_T_FDX | MII_NWAY_T;
+ mdio_write(dev, phy_addr, MII_ANADV, data);
+
+ /* Restart auto-negotiation */
+ data = mdio_read(dev, phy_addr, MII_CONTROL);
+ data |= MII_CNTL_RST_AUTO | MII_CNTL_AUTO;
+
+ mdio_write(dev, phy_addr, MII_CONTROL, data);
+
+ if (au1000_debug > 4) dump_mii(dev, phy_addr);
+ return 0;
+}
+
+int
+smsc_83C185_reset (struct net_device *dev, int phy_addr)
+{
+ s16 mii_control, timeout;
+
+ if (au1000_debug > 4)
+ printk("smsc_83C185_reset\n");
+
+ mii_control = mdio_read(dev, phy_addr, MII_CONTROL);
+ mdio_write(dev, phy_addr, MII_CONTROL, mii_control | MII_CNTL_RESET);
+ mdelay(1);
+ for (timeout = 100; timeout > 0; --timeout) {
+ mii_control = mdio_read(dev, phy_addr, MII_CONTROL);
+ if ((mii_control & MII_CNTL_RESET) == 0)
+ break;
+ mdelay(1);
+ }
+ if (mii_control & MII_CNTL_RESET) {
+ printk(KERN_ERR "%s PHY reset timeout !\n", dev->name);
+ return -1;
+ }
+ return 0;
+}
+
+int
+smsc_83C185_status (struct net_device *dev, int phy_addr, u16 *link, u16 *speed)
+{
+ u16 mii_data;
+ struct au1000_private *aup;
+
+ if (!dev) {
+ printk(KERN_ERR "smsc_83C185_status error: NULL dev\n");
+ return -1;
+ }
+
+ aup = (struct au1000_private *) dev->priv;
+ mii_data = mdio_read(dev, aup->phy_addr, MII_STATUS);
+
+ if (mii_data & MII_STAT_LINK) {
+ *link = 1;
+ mii_data = mdio_read(dev, aup->phy_addr, 0x1f);
+ if (mii_data & (1<<3)) {
+ if (mii_data & (1<<4)) {
+ *speed = IF_PORT_100BASEFX;
+ dev->if_port = IF_PORT_100BASEFX;
+ }
+ else {
+ *speed = IF_PORT_100BASETX;
+ dev->if_port = IF_PORT_100BASETX;
+ }
+ }
+ else {
+ *speed = IF_PORT_10BASET;
+ dev->if_port = IF_PORT_10BASET;
+ }
+ }
+ else {
+ *link = 0;
+ *speed = 0;
+ dev->if_port = IF_PORT_UNKNOWN;
+ }
+ return 0;
+}
+
+
+#ifdef CONFIG_MIPS_BOSPORUS
+int stub_init(struct net_device *dev, int phy_addr)
+{
+ //printk("PHY stub_init\n");
+ return 0;
+}
+
+int stub_reset(struct net_device *dev, int phy_addr)
+{
+ //printk("PHY stub_reset\n");
+ return 0;
+}
+
+int
+stub_status(struct net_device *dev, int phy_addr, u16 *link, u16 *speed)
+{
+ //printk("PHY stub_status\n");
+ *link = 1;
+ /* hmmm, revisit */
+ *speed = IF_PORT_100BASEFX;
+ dev->if_port = IF_PORT_100BASEFX;
+ return 0;
+}
+#endif
+
struct phy_ops bcm_5201_ops = {
bcm_5201_init,
bcm_5201_reset,
bcm_5201_status,
};
+struct phy_ops am79c874_ops = {
+ am79c874_init,
+ am79c874_reset,
+ am79c874_status,
+};
+
struct phy_ops am79c901_ops = {
am79c901_init,
am79c901_reset,
@@ -355,26 +749,89 @@ struct phy_ops lsi_80227_ops = {
lsi_80227_status,
};
+struct phy_ops lxt971a_ops = {
+ lxt971a_init,
+ lxt971a_reset,
+ lxt971a_status,
+};
+
+struct phy_ops ks8995m_ops = {
+ ks8995m_init,
+ ks8995m_reset,
+ ks8995m_status,
+};
+
+struct phy_ops smsc_83C185_ops = {
+ smsc_83C185_init,
+ smsc_83C185_reset,
+ smsc_83C185_status,
+};
+
+#ifdef CONFIG_MIPS_BOSPORUS
+struct phy_ops stub_ops = {
+ stub_init,
+ stub_reset,
+ stub_status,
+};
+#endif
+
static struct mii_chip_info {
const char * name;
u16 phy_id0;
u16 phy_id1;
struct phy_ops *phy_ops;
+ int dual_phy;
} mii_chip_table[] = {
- {"Broadcom BCM5201 10/100 BaseT PHY", 0x0040, 0x6212, &bcm_5201_ops },
- {"AMD 79C901 HomePNA PHY", 0x0000, 0x35c8, &am79c901_ops },
- {"LSI 80227 10/100 BaseT PHY", 0x0016, 0xf840, &lsi_80227_ops },
- {"Broadcom BCM5221 10/100 BaseT PHY", 0x0040, 0x61e4, &bcm_5201_ops },
+ {"Broadcom BCM5201 10/100 BaseT PHY",0x0040,0x6212, &bcm_5201_ops,0},
+ {"Broadcom BCM5221 10/100 BaseT PHY",0x0040,0x61e4, &bcm_5201_ops,0},
+ {"Broadcom BCM5222 10/100 BaseT PHY",0x0040,0x6322, &bcm_5201_ops,1},
+ {"AMD 79C901 HomePNA PHY",0x0000,0x35c8, &am79c901_ops,0},
+ {"AMD 79C874 10/100 BaseT PHY",0x0022,0x561b, &am79c874_ops,0},
+ {"LSI 80227 10/100 BaseT PHY",0x0016,0xf840, &lsi_80227_ops,0},
+ {"Intel LXT971A Dual Speed PHY",0x0013,0x78e2, &lxt971a_ops,0},
+ {"Kendin KS8995M 10/100 BaseT PHY",0x0022,0x1450, &ks8995m_ops,0},
+ {"SMSC LAN83C185 10/100 BaseT PHY",0x0007,0xc0a3, &smsc_83C185_ops,0},
+#ifdef CONFIG_MIPS_BOSPORUS
+ {"Stub", 0x1234, 0x5678, &stub_ops },
+#endif
{0,},
};
static int mdio_read(struct net_device *dev, int phy_id, int reg)
{
struct au1000_private *aup = (struct au1000_private *) dev->priv;
+ volatile u32 *mii_control_reg;
+ volatile u32 *mii_data_reg;
u32 timedout = 20;
u32 mii_control;
- while (aup->mac->mii_control & MAC_MII_BUSY) {
+ #ifdef CONFIG_BCM5222_DUAL_PHY
+ /* First time we probe, it's for the mac0 phy.
+ * Since we haven't determined yet that we have a dual phy,
+ * aup->mii->mii_control_reg won't be setup and we'll
+ * default to the else statement.
+ * By the time we probe for the mac1 phy, the mii_control_reg
+ * will be setup to be the address of the mac0 phy control since
+ * both phys are controlled through mac0.
+ */
+ if (aup->mii && aup->mii->mii_control_reg) {
+ mii_control_reg = aup->mii->mii_control_reg;
+ mii_data_reg = aup->mii->mii_data_reg;
+ }
+ else if (au_macs[0]->mii && au_macs[0]->mii->mii_control_reg) {
+ /* assume both phys are controlled through mac0 */
+ mii_control_reg = au_macs[0]->mii->mii_control_reg;
+ mii_data_reg = au_macs[0]->mii->mii_data_reg;
+ }
+ else
+ #endif
+ {
+ /* default control and data reg addresses */
+ mii_control_reg = &aup->mac->mii_control;
+ mii_data_reg = &aup->mac->mii_data;
+ }
+
+ while (*mii_control_reg & MAC_MII_BUSY) {
mdelay(1);
if (--timedout == 0) {
printk(KERN_ERR "%s: read_MII busy timeout!!\n",
@@ -386,10 +843,10 @@ static int mdio_read(struct net_device *dev, int phy_id, int reg)
mii_control = MAC_SET_MII_SELECT_REG(reg) |
MAC_SET_MII_SELECT_PHY(phy_id) | MAC_MII_READ;
- aup->mac->mii_control = mii_control;
+ *mii_control_reg = mii_control;
timedout = 20;
- while (aup->mac->mii_control & MAC_MII_BUSY) {
+ while (*mii_control_reg & MAC_MII_BUSY) {
mdelay(1);
if (--timedout == 0) {
printk(KERN_ERR "%s: mdio_read busy timeout!!\n",
@@ -397,16 +854,36 @@ static int mdio_read(struct net_device *dev, int phy_id, int reg)
return -1;
}
}
- return (int)aup->mac->mii_data;
+ return (int)*mii_data_reg;
}
static void mdio_write(struct net_device *dev, int phy_id, int reg, u16 value)
{
struct au1000_private *aup = (struct au1000_private *) dev->priv;
+ volatile u32 *mii_control_reg;
+ volatile u32 *mii_data_reg;
u32 timedout = 20;
u32 mii_control;
- while (aup->mac->mii_control & MAC_MII_BUSY) {
+ #ifdef CONFIG_BCM5222_DUAL_PHY
+ if (aup->mii && aup->mii->mii_control_reg) {
+ mii_control_reg = aup->mii->mii_control_reg;
+ mii_data_reg = aup->mii->mii_data_reg;
+ }
+ else if (au_macs[0]->mii && au_macs[0]->mii->mii_control_reg) {
+ /* assume both phys are controlled through mac0 */
+ mii_control_reg = au_macs[0]->mii->mii_control_reg;
+ mii_data_reg = au_macs[0]->mii->mii_data_reg;
+ }
+ else
+ #endif
+ {
+ /* default control and data reg addresses */
+ mii_control_reg = &aup->mac->mii_control;
+ mii_data_reg = &aup->mac->mii_data;
+ }
+
+ while (*mii_control_reg & MAC_MII_BUSY) {
mdelay(1);
if (--timedout == 0) {
printk(KERN_ERR "%s: mdio_write busy timeout!!\n",
@@ -418,8 +895,8 @@ static void mdio_write(struct net_device *dev, int phy_id, int reg, u16 value)
mii_control = MAC_SET_MII_SELECT_REG(reg) |
MAC_SET_MII_SELECT_PHY(phy_id) | MAC_MII_WRITE;
- aup->mac->mii_data = value;
- aup->mac->mii_control = mii_control;
+ *mii_data_reg = value;
+ *mii_control_reg = mii_control;
}
@@ -437,12 +914,13 @@ static void dump_mii(struct net_device *dev, int phy_id)
}
}
-static int __init mii_probe (struct net_device * dev)
+static int mii_probe (struct net_device * dev)
{
struct au1000_private *aup = (struct au1000_private *) dev->priv;
int phy_addr;
-
- aup->mii = NULL;
+#ifdef CONFIG_MIPS_BOSPORUS
+ int phy_found=0;
+#endif
/* search for total of 32 possible mii phy addresses */
for (phy_addr = 0; phy_addr < 32; phy_addr++) {
@@ -450,9 +928,17 @@ static int __init mii_probe (struct net_device * dev)
u16 phy_id0, phy_id1;
int i;
+ #ifdef CONFIG_BCM5222_DUAL_PHY
+ /* Mask the already found phy, try next one */
+ if (au_macs[0]->mii && au_macs[0]->mii->mii_control_reg) {
+ if (au_macs[0]->phy_addr == phy_addr)
+ continue;
+ }
+ #endif
+
mii_status = mdio_read(dev, phy_addr, MII_STATUS);
if (mii_status == 0xffff || mii_status == 0x0000)
- /* the mii is not accessible, try next one */
+ /* the mii is not accessable, try next one */
continue;
phy_id0 = mdio_read(dev, phy_addr, MII_PHY_ID0);
@@ -462,6 +948,66 @@ static int __init mii_probe (struct net_device * dev)
for (i = 0; mii_chip_table[i].phy_id1; i++) {
if (phy_id0 == mii_chip_table[i].phy_id0 &&
phy_id1 == mii_chip_table[i].phy_id1) {
+ struct mii_phy * mii_phy = aup->mii;
+
+ printk(KERN_INFO "%s: %s at phy address %d\n",
+ dev->name, mii_chip_table[i].name,
+ phy_addr);
+#ifdef CONFIG_MIPS_BOSPORUS
+ phy_found = 1;
+#endif
+ mii_phy->chip_info = mii_chip_table+i;
+ aup->phy_addr = phy_addr;
+ aup->want_autoneg = 1;
+ aup->phy_ops = mii_chip_table[i].phy_ops;
+ aup->phy_ops->phy_init(dev,phy_addr);
+
+ // Check for dual-phy and then store required
+ // values and set indicators. We need to do
+ // this now since mdio_{read,write} need the
+ // control and data register addresses.
+ #ifdef CONFIG_BCM5222_DUAL_PHY
+ if ( mii_chip_table[i].dual_phy) {
+
+ /* assume both phys are controlled
+ * through MAC0. Board specific? */
+
+ /* sanity check */
+ if (!au_macs[0] || !au_macs[0]->mii)
+ return -1;
+ aup->mii->mii_control_reg = (u32 *)
+ &au_macs[0]->mac->mii_control;
+ aup->mii->mii_data_reg = (u32 *)
+ &au_macs[0]->mac->mii_data;
+ }
+ #endif
+ goto found;
+ }
+ }
+ }
+found:
+
+#ifdef CONFIG_MIPS_BOSPORUS
+ /* This is a workaround for the Micrel/Kendin 5 port switch
+ The second MAC doesn't see a PHY connected... so we need to
+ trick it into thinking we have one.
+
+ If this kernel is run on another Au1500 development board
+ the stub will be found as well as the actual PHY. However,
+ the last found PHY will be used... usually at Addr 31 (Db1500).
+ */
+ if ( (!phy_found) )
+ {
+ u16 phy_id0, phy_id1;
+ int i;
+
+ phy_id0 = 0x1234;
+ phy_id1 = 0x5678;
+
+ /* search our mii table for the current mii */
+ for (i = 0; mii_chip_table[i].phy_id1; i++) {
+ if (phy_id0 == mii_chip_table[i].phy_id0 &&
+ phy_id1 == mii_chip_table[i].phy_id1) {
struct mii_phy * mii_phy;
printk(KERN_INFO "%s: %s at phy address %d\n",
@@ -471,31 +1017,39 @@ static int __init mii_probe (struct net_device * dev)
GFP_KERNEL);
if (mii_phy) {
mii_phy->chip_info = mii_chip_table+i;
- mii_phy->phy_addr = phy_addr;
+ aup->phy_addr = phy_addr;
mii_phy->next = aup->mii;
aup->phy_ops =
mii_chip_table[i].phy_ops;
aup->mii = mii_phy;
aup->phy_ops->phy_init(dev,phy_addr);
} else {
- printk(KERN_ERR "%s: out of memory\n",
+ printk(KERN_ERR "%s: out of memory\n",
dev->name);
return -1;
}
- /* the current mii is on our mii_info_table,
- try next address */
+ mii_phy->chip_info = mii_chip_table+i;
+ aup->phy_addr = phy_addr;
+ aup->phy_ops = mii_chip_table[i].phy_ops;
+ aup->phy_ops->phy_init(dev,phy_addr);
break;
}
}
}
+ if (aup->mac_id == 0) {
+ /* the Bosporus phy responds to addresses 0-5 but
+ * 5 is the correct one.
+ */
+ aup->phy_addr = 5;
+ }
+#endif
- if (aup->mii == NULL) {
- printk(KERN_ERR "%s: No MII transceivers found!\n", dev->name);
+ if (aup->mii->chip_info == NULL) {
+ printk(KERN_ERR "%s: Au1x No MII transceivers found!\n",
+ dev->name);
return -1;
}
- /* use last PHY */
- aup->phy_addr = aup->mii->phy_addr;
printk(KERN_INFO "%s: Using %s as default\n",
dev->name, aup->mii->chip_info->name);
@@ -516,7 +1070,6 @@ static db_dest_t *GetFreeDB(struct au1000_private *aup)
if (pDB) {
aup->pDBfree = pDB->pnext;
}
- //printk("GetFreeDB: %x\n", pDB);
return pDB;
}
@@ -528,35 +1081,6 @@ void ReleaseDB(struct au1000_private *aup, db_dest_t *pDB)
aup->pDBfree = pDB;
}
-
-/*
- DMA memory allocation, derived from pci_alloc_consistent.
- However, the Au1000 data cache is coherent (when programmed
- so), therefore we return KSEG0 address, not KSEG1.
-*/
-static void *dma_alloc(size_t size, dma_addr_t * dma_handle)
-{
- void *ret;
- int gfp = GFP_ATOMIC | GFP_DMA;
-
- ret = (void *) __get_free_pages(gfp, get_order(size));
-
- if (ret != NULL) {
- memset(ret, 0, size);
- *dma_handle = virt_to_bus(ret);
- ret = (void *)KSEG0ADDR(ret);
- }
- return ret;
-}
-
-
-static void dma_free(void *vaddr, size_t size)
-{
- vaddr = (void *)KSEG0ADDR(vaddr);
- free_pages((unsigned long) vaddr, get_order(size));
-}
-
-
static void enable_rx_tx(struct net_device *dev)
{
struct au1000_private *aup = (struct au1000_private *) dev->priv;
@@ -582,6 +1106,7 @@ static void hard_stop(struct net_device *dev)
static void reset_mac(struct net_device *dev)
{
+ int i;
u32 flags;
struct au1000_private *aup = (struct au1000_private *) dev->priv;
@@ -590,13 +1115,32 @@ static void reset_mac(struct net_device *dev)
dev->name, (unsigned)aup);
spin_lock_irqsave(&aup->lock, flags);
- del_timer(&aup->timer);
+ if (aup->timer.function == &au1000_timer) {/* check if timer initted */
+ del_timer(&aup->timer);
+ }
+
hard_stop(dev);
- *aup->enable = MAC_EN_CLOCK_ENABLE;
- au_sync_delay(2);
- *aup->enable = 0;
- au_sync_delay(2);
+ #ifdef CONFIG_BCM5222_DUAL_PHY
+ if (aup->mac_id != 0) {
+ #endif
+ /* If BCM5222, we can't leave MAC0 in reset because then
+ * we can't access the dual phy for ETH1 */
+ *aup->enable = MAC_EN_CLOCK_ENABLE;
+ au_sync_delay(2);
+ *aup->enable = 0;
+ au_sync_delay(2);
+ #ifdef CONFIG_BCM5222_DUAL_PHY
+ }
+ #endif
aup->tx_full = 0;
+ for (i = 0; i < NUM_RX_DMA; i++) {
+ /* reset control bits */
+ aup->rx_dma_ring[i]->buff_stat &= ~0xf;
+ }
+ for (i = 0; i < NUM_TX_DMA; i++) {
+ /* reset control bits */
+ aup->tx_dma_ring[i]->buff_stat &= ~0xf;
+ }
spin_unlock_irqrestore(&aup->lock, flags);
}
@@ -611,93 +1155,348 @@ setup_hw_rings(struct au1000_private *aup, u32 rx_base, u32 tx_base)
{
int i;
- for (i=0; i<NUM_RX_DMA; i++) {
+ for (i = 0; i < NUM_RX_DMA; i++) {
aup->rx_dma_ring[i] =
(volatile rx_dma_t *) (rx_base + sizeof(rx_dma_t)*i);
}
- for (i=0; i<NUM_TX_DMA; i++) {
+ for (i = 0; i < NUM_TX_DMA; i++) {
aup->tx_dma_ring[i] =
(volatile tx_dma_t *) (tx_base + sizeof(tx_dma_t)*i);
}
}
+static struct {
+ int port;
+ u32 base_addr;
+ u32 macen_addr;
+ int irq;
+ struct net_device *dev;
+} iflist[2];
+
+static int num_ifs;
+
+/*
+ * Setup the base address and interupt of the Au1xxx ethernet macs
+ * based on cpu type and whether the interface is enabled in sys_pinfunc
+ * register. The last interface is enabled if SYS_PF_NI2 (bit 4) is 0.
+ */
static int __init au1000_init_module(void)
{
- int i;
- int prid;
- int base_addr, irq;
-
- prid = read_c0_prid();
- for (i=0; i<NUM_INTERFACES; i++) {
- if ( (prid & 0xffff0000) == 0x00030000 ) {
- base_addr = au1000_iflist[i].port;
- irq = au1000_iflist[i].irq;
- } else if ( (prid & 0xffff0000) == 0x01030000 ) {
- base_addr = au1500_iflist[i].port;
- irq = au1500_iflist[i].irq;
- } else if ( (prid & 0xffff0000) == 0x02030000 ) {
- base_addr = au1100_iflist[i].port;
- irq = au1100_iflist[i].irq;
+ struct cpuinfo_mips *c = &current_cpu_data;
+ int ni = (int)((au_readl(SYS_PINFUNC) & (u32)(SYS_PF_NI2)) >> 4);
+ struct net_device *dev;
+ int i, found_one = 0;
+
+ switch (c->cputype) {
+#ifdef CONFIG_SOC_AU1000
+ case CPU_AU1000:
+ num_ifs = 2 - ni;
+ iflist[0].base_addr = AU1000_ETH0_BASE;
+ iflist[1].base_addr = AU1000_ETH1_BASE;
+ iflist[0].macen_addr = AU1000_MAC0_ENABLE;
+ iflist[1].macen_addr = AU1000_MAC1_ENABLE;
+ iflist[0].irq = AU1000_MAC0_DMA_INT;
+ iflist[1].irq = AU1000_MAC1_DMA_INT;
+ break;
+#endif
+#ifdef CONFIG_SOC_AU1100
+ case CPU_AU1100:
+ num_ifs = 1 - ni;
+ iflist[0].base_addr = AU1100_ETH0_BASE;
+ iflist[0].macen_addr = AU1100_MAC0_ENABLE;
+ iflist[0].irq = AU1100_MAC0_DMA_INT;
+ break;
+#endif
+#ifdef CONFIG_SOC_AU1500
+ case CPU_AU1500:
+ num_ifs = 2 - ni;
+ iflist[0].base_addr = AU1500_ETH0_BASE;
+ iflist[1].base_addr = AU1500_ETH1_BASE;
+ iflist[0].macen_addr = AU1500_MAC0_ENABLE;
+ iflist[1].macen_addr = AU1500_MAC1_ENABLE;
+ iflist[0].irq = AU1500_MAC0_DMA_INT;
+ iflist[1].irq = AU1500_MAC1_DMA_INT;
+ break;
+#endif
+#ifdef CONFIG_SOC_AU1550
+ case CPU_AU1550:
+ num_ifs = 2 - ni;
+ iflist[0].base_addr = AU1550_ETH0_BASE;
+ iflist[1].base_addr = AU1550_ETH1_BASE;
+ iflist[0].macen_addr = AU1550_MAC0_ENABLE;
+ iflist[1].macen_addr = AU1550_MAC1_ENABLE;
+ iflist[0].irq = AU1550_MAC0_DMA_INT;
+ iflist[1].irq = AU1550_MAC1_DMA_INT;
+ break;
+#endif
+ default:
+ num_ifs = 0;
+ }
+ for(i = 0; i < num_ifs; i++) {
+ dev = au1000_probe(iflist[i].base_addr, iflist[i].irq, i);
+ iflist[i].dev = dev;
+ if (dev)
+ found_one++;
+ }
+ if (!found_one)
+ return -ENODEV;
+ return 0;
+}
+
+static int au1000_setup_aneg(struct net_device *dev, u32 advertise)
+{
+ struct au1000_private *aup = (struct au1000_private *)dev->priv;
+ u16 ctl, adv;
+
+ /* Setup standard advertise */
+ adv = mdio_read(dev, aup->phy_addr, MII_ADVERTISE);
+ adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
+ if (advertise & ADVERTISED_10baseT_Half)
+ adv |= ADVERTISE_10HALF;
+ if (advertise & ADVERTISED_10baseT_Full)
+ adv |= ADVERTISE_10FULL;
+ if (advertise & ADVERTISED_100baseT_Half)
+ adv |= ADVERTISE_100HALF;
+ if (advertise & ADVERTISED_100baseT_Full)
+ adv |= ADVERTISE_100FULL;
+ mdio_write(dev, aup->phy_addr, MII_ADVERTISE, adv);
+
+ /* Start/Restart aneg */
+ ctl = mdio_read(dev, aup->phy_addr, MII_BMCR);
+ ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
+ mdio_write(dev, aup->phy_addr, MII_BMCR, ctl);
+
+ return 0;
+}
+
+static int au1000_setup_forced(struct net_device *dev, int speed, int fd)
+{
+ struct au1000_private *aup = (struct au1000_private *)dev->priv;
+ u16 ctl;
+
+ ctl = mdio_read(dev, aup->phy_addr, MII_BMCR);
+ ctl &= ~(BMCR_FULLDPLX | BMCR_SPEED100 | BMCR_ANENABLE);
+
+ /* First reset the PHY */
+ mdio_write(dev, aup->phy_addr, MII_BMCR, ctl | BMCR_RESET);
+
+ /* Select speed & duplex */
+ switch (speed) {
+ case SPEED_10:
+ break;
+ case SPEED_100:
+ ctl |= BMCR_SPEED100;
+ break;
+ case SPEED_1000:
+ default:
+ return -EINVAL;
+ }
+ if (fd == DUPLEX_FULL)
+ ctl |= BMCR_FULLDPLX;
+ mdio_write(dev, aup->phy_addr, MII_BMCR, ctl);
+
+ return 0;
+}
+
+
+static void
+au1000_start_link(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+ struct au1000_private *aup = (struct au1000_private *)dev->priv;
+ u32 advertise;
+ int autoneg;
+ int forced_speed;
+ int forced_duplex;
+
+ /* Default advertise */
+ advertise = GENMII_DEFAULT_ADVERTISE;
+ autoneg = aup->want_autoneg;
+ forced_speed = SPEED_100;
+ forced_duplex = DUPLEX_FULL;
+
+ /* Setup link parameters */
+ if (cmd) {
+ if (cmd->autoneg == AUTONEG_ENABLE) {
+ advertise = cmd->advertising;
+ autoneg = 1;
} else {
- printk(KERN_ERR "au1000 eth: unknown Processor ID\n");
- return -ENODEV;
- }
- // check for valid entries, au1100 only has one entry
- if (base_addr && irq) {
- if (au1000_probe1(base_addr, irq, i) != 0)
- return -ENODEV;
+ autoneg = 0;
+
+ forced_speed = cmd->speed;
+ forced_duplex = cmd->duplex;
}
}
+
+ /* Configure PHY & start aneg */
+ aup->want_autoneg = autoneg;
+ if (autoneg)
+ au1000_setup_aneg(dev, advertise);
+ else
+ au1000_setup_forced(dev, forced_speed, forced_duplex);
+ mod_timer(&aup->timer, jiffies + HZ);
+}
+
+static int au1000_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+ struct au1000_private *aup = (struct au1000_private *)dev->priv;
+ u16 link, speed;
+
+ cmd->supported = GENMII_DEFAULT_FEATURES;
+ cmd->advertising = GENMII_DEFAULT_ADVERTISE;
+ cmd->port = PORT_MII;
+ cmd->transceiver = XCVR_EXTERNAL;
+ cmd->phy_address = aup->phy_addr;
+ spin_lock_irq(&aup->lock);
+ cmd->autoneg = aup->want_autoneg;
+ aup->phy_ops->phy_status(dev, aup->phy_addr, &link, &speed);
+ if ((speed == IF_PORT_100BASETX) || (speed == IF_PORT_100BASEFX))
+ cmd->speed = SPEED_100;
+ else if (speed == IF_PORT_10BASET)
+ cmd->speed = SPEED_10;
+ if (link && (dev->if_port == IF_PORT_100BASEFX))
+ cmd->duplex = DUPLEX_FULL;
+ else
+ cmd->duplex = DUPLEX_HALF;
+ spin_unlock_irq(&aup->lock);
return 0;
}
-static int __init
-au1000_probe1(long ioaddr, int irq, int port_num)
+static int au1000_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+ struct au1000_private *aup = (struct au1000_private *)dev->priv;
+ unsigned long features = GENMII_DEFAULT_FEATURES;
+
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+
+ if (cmd->autoneg != AUTONEG_ENABLE && cmd->autoneg != AUTONEG_DISABLE)
+ return -EINVAL;
+ if (cmd->autoneg == AUTONEG_ENABLE && cmd->advertising == 0)
+ return -EINVAL;
+ if (cmd->duplex != DUPLEX_HALF && cmd->duplex != DUPLEX_FULL)
+ return -EINVAL;
+ if (cmd->autoneg == AUTONEG_DISABLE)
+ switch (cmd->speed) {
+ case SPEED_10:
+ if (cmd->duplex == DUPLEX_HALF &&
+ (features & SUPPORTED_10baseT_Half) == 0)
+ return -EINVAL;
+ if (cmd->duplex == DUPLEX_FULL &&
+ (features & SUPPORTED_10baseT_Full) == 0)
+ return -EINVAL;
+ break;
+ case SPEED_100:
+ if (cmd->duplex == DUPLEX_HALF &&
+ (features & SUPPORTED_100baseT_Half) == 0)
+ return -EINVAL;
+ if (cmd->duplex == DUPLEX_FULL &&
+ (features & SUPPORTED_100baseT_Full) == 0)
+ return -EINVAL;
+ break;
+ default:
+ return -EINVAL;
+ }
+ else if ((features & SUPPORTED_Autoneg) == 0)
+ return -EINVAL;
+
+ spin_lock_irq(&aup->lock);
+ au1000_start_link(dev, cmd);
+ spin_unlock_irq(&aup->lock);
+ return 0;
+}
+
+static int au1000_nway_reset(struct net_device *dev)
+{
+ struct au1000_private *aup = (struct au1000_private *)dev->priv;
+
+ if (!aup->want_autoneg)
+ return -EINVAL;
+ spin_lock_irq(&aup->lock);
+ au1000_start_link(dev, NULL);
+ spin_unlock_irq(&aup->lock);
+ return 0;
+}
+
+static void
+au1000_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+{
+ struct au1000_private *aup = (struct au1000_private *)dev->priv;
+
+ strcpy(info->driver, DRV_NAME);
+ strcpy(info->version, DRV_VERSION);
+ info->fw_version[0] = '\0';
+ sprintf(info->bus_info, "%s %d", DRV_NAME, aup->mac_id);
+ info->regdump_len = 0;
+}
+
+static u32 au1000_get_link(struct net_device *dev)
+{
+ return netif_carrier_ok(dev);
+}
+
+static struct ethtool_ops au1000_ethtool_ops = {
+ .get_settings = au1000_get_settings,
+ .set_settings = au1000_set_settings,
+ .get_drvinfo = au1000_get_drvinfo,
+ .nway_reset = au1000_nway_reset,
+ .get_link = au1000_get_link
+};
+
+static struct net_device *
+au1000_probe(u32 ioaddr, int irq, int port_num)
{
- struct net_device *dev;
static unsigned version_printed = 0;
struct au1000_private *aup = NULL;
- int i, retval = 0;
+ struct net_device *dev = NULL;
db_dest_t *pDB, *pDBfree;
char *pmac, *argptr;
char ethaddr[6];
+ int i, err;
- if (!request_region(PHYSADDR(ioaddr), MAC_IOSIZE, "Au1000 ENET"))
- return -ENODEV;
+ if (!request_mem_region(CPHYSADDR(ioaddr), MAC_IOSIZE, "Au1x00 ENET"))
+ return NULL;
- if (version_printed++ == 0)
- printk(version);
-
- retval = -ENOMEM;
+ if (version_printed++ == 0)
+ printk("%s version %s %s\n", DRV_NAME, DRV_VERSION, DRV_AUTHOR);
dev = alloc_etherdev(sizeof(struct au1000_private));
if (!dev) {
printk (KERN_ERR "au1000 eth: alloc_etherdev failed\n");
- goto out;
+ return NULL;
}
- SET_MODULE_OWNER(dev);
+ if ((err = register_netdev(dev))) {
+ printk(KERN_ERR "Au1x_eth Cannot register net device err %d\n",
+ err);
+ free_netdev(dev);
+ return NULL;
+ }
- printk("%s: Au1xxx ethernet found at 0x%lx, irq %d\n",
- dev->name, ioaddr, irq);
+ printk("%s: Au1x Ethernet found at 0x%x, irq %d\n",
+ dev->name, ioaddr, irq);
aup = dev->priv;
/* Allocate the data buffers */
- aup->vaddr = (u32)dma_alloc(MAX_BUF_SIZE *
- (NUM_TX_BUFFS+NUM_RX_BUFFS), &aup->dma_addr);
- if (!aup->vaddr)
- goto out1;
+ /* Snooping works fine with eth on all au1xxx */
+ aup->vaddr = (u32)dma_alloc_noncoherent(NULL,
+ MAX_BUF_SIZE * (NUM_TX_BUFFS+NUM_RX_BUFFS),
+ &aup->dma_addr,
+ 0);
+ if (!aup->vaddr) {
+ free_netdev(dev);
+ release_mem_region(CPHYSADDR(ioaddr), MAC_IOSIZE);
+ return NULL;
+ }
/* aup->mac is the base address of the MAC's registers */
aup->mac = (volatile mac_reg_t *)((unsigned long)ioaddr);
/* Setup some variables for quick register address access */
- switch (ioaddr) {
- case AU1000_ETH0_BASE:
- case AU1500_ETH0_BASE:
+ if (ioaddr == iflist[0].base_addr)
+ {
/* check env variables first */
if (!get_ethernet_addr(ethaddr)) {
- memcpy(au1000_mac_addr, ethaddr, sizeof(dev->dev_addr));
+ memcpy(au1000_mac_addr, ethaddr, sizeof(au1000_mac_addr));
} else {
/* Check command line */
argptr = prom_getcmdline();
@@ -708,38 +1507,32 @@ au1000_probe1(long ioaddr, int irq, int port_num)
} else {
str2eaddr(ethaddr, pmac + strlen("ethaddr="));
memcpy(au1000_mac_addr, ethaddr,
- sizeof(dev->dev_addr));
+ sizeof(au1000_mac_addr));
}
}
- if (ioaddr == AU1000_ETH0_BASE)
- aup->enable = (volatile u32 *)
- ((unsigned long)AU1000_MAC0_ENABLE);
- else
aup->enable = (volatile u32 *)
- ((unsigned long)AU1500_MAC0_ENABLE);
- memcpy(dev->dev_addr, au1000_mac_addr, sizeof(dev->dev_addr));
+ ((unsigned long)iflist[0].macen_addr);
+ memcpy(dev->dev_addr, au1000_mac_addr, sizeof(au1000_mac_addr));
setup_hw_rings(aup, MAC0_RX_DMA_ADDR, MAC0_TX_DMA_ADDR);
- break;
- case AU1000_ETH1_BASE:
- case AU1500_ETH1_BASE:
- if (ioaddr == AU1000_ETH1_BASE)
- aup->enable = (volatile u32 *)
- ((unsigned long)AU1000_MAC1_ENABLE);
+ aup->mac_id = 0;
+ au_macs[0] = aup;
+ }
else
+ if (ioaddr == iflist[1].base_addr)
+ {
aup->enable = (volatile u32 *)
- ((unsigned long)AU1500_MAC1_ENABLE);
- memcpy(dev->dev_addr, au1000_mac_addr, sizeof(dev->dev_addr));
+ ((unsigned long)iflist[1].macen_addr);
+ memcpy(dev->dev_addr, au1000_mac_addr, sizeof(au1000_mac_addr));
dev->dev_addr[4] += 0x10;
setup_hw_rings(aup, MAC1_RX_DMA_ADDR, MAC1_TX_DMA_ADDR);
- break;
- default:
+ aup->mac_id = 1;
+ au_macs[1] = aup;
+ }
+ else
+ {
printk(KERN_ERR "%s: bad ioaddr\n", dev->name);
- break;
-
}
- aup->phy_addr = PHY_ADDRESS;
-
/* bring the device out of reset, otherwise probing the mii
* will hang */
*aup->enable = MAC_EN_CLOCK_ENABLE;
@@ -748,15 +1541,22 @@ au1000_probe1(long ioaddr, int irq, int port_num)
MAC_EN_RESET2 | MAC_EN_CLOCK_ENABLE;
au_sync_delay(2);
- retval = mii_probe(dev);
- if (retval)
- goto out2;
+ aup->mii = kmalloc(sizeof(struct mii_phy), GFP_KERNEL);
+ if (!aup->mii) {
+ printk(KERN_ERR "%s: out of memory\n", dev->name);
+ goto err_out;
+ }
+ aup->mii->mii_control_reg = 0;
+ aup->mii->mii_data_reg = 0;
+
+ if (mii_probe(dev) != 0) {
+ goto err_out;
+ }
- retval = -EINVAL;
pDBfree = NULL;
/* setup the data buffer descriptors and attach a buffer to each one */
pDB = aup->db;
- for (i=0; i<(NUM_TX_BUFFS+NUM_RX_BUFFS); i++) {
+ for (i = 0; i < (NUM_TX_BUFFS+NUM_RX_BUFFS); i++) {
pDB->pnext = pDBfree;
pDBfree = pDB;
pDB->vaddr = (u32 *)((unsigned)aup->vaddr + MAX_BUF_SIZE*i);
@@ -765,15 +1565,19 @@ au1000_probe1(long ioaddr, int irq, int port_num)
}
aup->pDBfree = pDBfree;
- for (i=0; i<NUM_RX_DMA; i++) {
+ for (i = 0; i < NUM_RX_DMA; i++) {
pDB = GetFreeDB(aup);
- if (!pDB) goto out2;
+ if (!pDB) {
+ goto err_out;
+ }
aup->rx_dma_ring[i]->buff_stat = (unsigned)pDB->dma_addr;
aup->rx_db_inuse[i] = pDB;
}
- for (i=0; i<NUM_TX_DMA; i++) {
+ for (i = 0; i < NUM_TX_DMA; i++) {
pDB = GetFreeDB(aup);
- if (!pDB) goto out2;
+ if (!pDB) {
+ goto err_out;
+ }
aup->tx_dma_ring[i]->buff_stat = (unsigned)pDB->dma_addr;
aup->tx_dma_ring[i]->len = 0;
aup->tx_db_inuse[i] = pDB;
@@ -788,6 +1592,7 @@ au1000_probe1(long ioaddr, int irq, int port_num)
dev->get_stats = au1000_get_stats;
dev->set_multicast_list = &set_rx_mode;
dev->do_ioctl = &au1000_ioctl;
+ SET_ETHTOOL_OPS(dev, &au1000_ethtool_ops);
dev->set_config = &au1000_set_config;
dev->tx_timeout = au1000_tx_timeout;
dev->watchdog_timeo = ETH_TX_TIMEOUT;
@@ -798,23 +1603,32 @@ au1000_probe1(long ioaddr, int irq, int port_num)
*/
reset_mac(dev);
- retval = register_netdev(dev);
- if (retval)
- goto out2;
- return 0;
+ return dev;
-out2:
- dma_free(aup->vaddr, MAX_BUF_SIZE * (NUM_TX_BUFFS+NUM_RX_BUFFS));
-out1:
+err_out:
+ /* here we should have a valid dev plus aup-> register addresses
+ * so we can reset the mac properly.*/
+ reset_mac(dev);
+ if (aup->mii)
+ kfree(aup->mii);
+ for (i = 0; i < NUM_RX_DMA; i++) {
+ if (aup->rx_db_inuse[i])
+ ReleaseDB(aup, aup->rx_db_inuse[i]);
+ }
+ for (i = 0; i < NUM_TX_DMA; i++) {
+ if (aup->tx_db_inuse[i])
+ ReleaseDB(aup, aup->tx_db_inuse[i]);
+ }
+ dma_free_noncoherent(NULL,
+ MAX_BUF_SIZE * (NUM_TX_BUFFS+NUM_RX_BUFFS),
+ (void *)aup->vaddr,
+ aup->dma_addr);
+ unregister_netdev(dev);
free_netdev(dev);
-out:
- release_region(PHYSADDR(ioaddr), MAC_IOSIZE);
- printk(KERN_ERR "%s: au1000_probe1 failed. Returns %d\n",
- dev->name, retval);
- return retval;
+ release_mem_region(CPHYSADDR(ioaddr), MAC_IOSIZE);
+ return NULL;
}
-
/*
* Initialize the interface.
*
@@ -832,7 +1646,8 @@ static int au1000_init(struct net_device *dev)
u32 control;
u16 link, speed;
- if (au1000_debug > 4) printk("%s: au1000_init\n", dev->name);
+ if (au1000_debug > 4)
+ printk("%s: au1000_init\n", dev->name);
spin_lock_irqsave(&aup->lock, flags);
@@ -852,7 +1667,7 @@ static int au1000_init(struct net_device *dev)
aup->mac->mac_addr_low = dev->dev_addr[3]<<24 | dev->dev_addr[2]<<16 |
dev->dev_addr[1]<<8 | dev->dev_addr[0];
- for (i=0; i<NUM_RX_DMA; i++) {
+ for (i = 0; i < NUM_RX_DMA; i++) {
aup->rx_dma_ring[i]->buff_stat |= RX_DMA_ENABLE;
}
au_sync();
@@ -865,7 +1680,13 @@ static int au1000_init(struct net_device *dev)
if (link && (dev->if_port == IF_PORT_100BASEFX)) {
control |= MAC_FULL_DUPLEX;
}
+
+ /* fix for startup without cable */
+ if (!link)
+ dev->flags &= ~IFF_RUNNING;
+
aup->mac->control = control;
+ aup->mac->vlan1_tag = 0x8100; /* activate vlan support */
au_sync();
spin_unlock_irqrestore(&aup->lock, flags);
@@ -949,6 +1770,7 @@ static int au1000_open(struct net_device *dev)
return retval;
}
+ init_timer(&aup->timer); /* used in ioctl() */
aup->timer.expires = RUN_AT((3*HZ));
aup->timer.data = (unsigned long)dev;
aup->timer.function = &au1000_timer; /* timer handler */
@@ -968,22 +1790,49 @@ static int au1000_close(struct net_device *dev)
if (au1000_debug > 4)
printk("%s: close: dev=%p\n", dev->name, dev);
+ reset_mac(dev);
+
spin_lock_irqsave(&aup->lock, flags);
/* stop the device */
- if (netif_device_present(dev))
- netif_stop_queue(dev);
+ netif_stop_queue(dev);
/* disable the interrupt */
free_irq(dev->irq, dev);
spin_unlock_irqrestore(&aup->lock, flags);
- reset_mac(dev);
return 0;
}
static void __exit au1000_cleanup_module(void)
{
+ int i, j;
+ struct net_device *dev;
+ struct au1000_private *aup;
+
+ for (i = 0; i < num_ifs; i++) {
+ dev = iflist[i].dev;
+ if (dev) {
+ aup = (struct au1000_private *) dev->priv;
+ unregister_netdev(dev);
+ if (aup->mii)
+ kfree(aup->mii);
+ for (j = 0; j < NUM_RX_DMA; j++) {
+ if (aup->rx_db_inuse[j])
+ ReleaseDB(aup, aup->rx_db_inuse[j]);
+ }
+ for (j = 0; j < NUM_TX_DMA; j++) {
+ if (aup->tx_db_inuse[j])
+ ReleaseDB(aup, aup->tx_db_inuse[j]);
+ }
+ dma_free_noncoherent(NULL,
+ MAX_BUF_SIZE * (NUM_TX_BUFFS+NUM_RX_BUFFS),
+ (void *)aup->vaddr,
+ aup->dma_addr);
+ free_netdev(dev);
+ release_mem_region(CPHYSADDR(iflist[i].base_addr), MAC_IOSIZE);
+ }
+ }
}
@@ -1028,9 +1877,8 @@ static void au1000_tx_ack(struct net_device *dev)
ptxd = aup->tx_dma_ring[aup->tx_tail];
while (ptxd->buff_stat & TX_T_DONE) {
- update_tx_stats(dev, ptxd->status, aup->tx_len[aup->tx_tail] & 0x3ff);
+ update_tx_stats(dev, ptxd->status, ptxd->len & 0x3ff);
ptxd->buff_stat &= ~TX_T_DONE;
- aup->tx_len[aup->tx_tail] = 0;
ptxd->len = 0;
au_sync();
@@ -1056,7 +1904,7 @@ static int au1000_tx(struct sk_buff *skb, struct net_device *dev)
db_dest_t *pDB;
int i;
- if (au1000_debug > 4)
+ if (au1000_debug > 5)
printk("%s: tx: aup %x len=%d, data=%p, head %d\n",
dev->name, (unsigned)aup, skb->len,
skb->data, aup->tx_head);
@@ -1070,8 +1918,7 @@ static int au1000_tx(struct sk_buff *skb, struct net_device *dev)
return 1;
}
else if (buff_stat & TX_T_DONE) {
- update_tx_stats(dev, ptxd->status, aup->tx_len[aup->tx_head] & 0x3ff);
- aup->tx_len[aup->tx_head] = 0;
+ update_tx_stats(dev, ptxd->status, ptxd->len & 0x3ff);
ptxd->len = 0;
}
@@ -1082,17 +1929,15 @@ static int au1000_tx(struct sk_buff *skb, struct net_device *dev)
pDB = aup->tx_db_inuse[aup->tx_head];
memcpy((void *)pDB->vaddr, skb->data, skb->len);
- if (skb->len < MAC_MIN_PKT_SIZE) {
- for (i=skb->len; i<MAC_MIN_PKT_SIZE; i++) {
+ if (skb->len < ETH_ZLEN) {
+ for (i=skb->len; i<ETH_ZLEN; i++) {
((char *)pDB->vaddr)[i] = 0;
}
- aup->tx_len[aup->tx_head] = MAC_MIN_PKT_SIZE;
- ptxd->len = MAC_MIN_PKT_SIZE;
+ ptxd->len = ETH_ZLEN;
}
- else {
- aup->tx_len[aup->tx_head] = skb->len;
+ else
ptxd->len = skb->len;
- }
+
ptxd->buff_stat = pDB->dma_addr | TX_DMA_ENABLE;
au_sync();
dev_kfree_skb(skb);
@@ -1137,8 +1982,9 @@ static int au1000_rx(struct net_device *dev)
volatile rx_dma_t *prxd;
u32 buff_stat, status;
db_dest_t *pDB;
+ u32 frmlen;
- if (au1000_debug > 4)
+ if (au1000_debug > 5)
printk("%s: au1000_rx head %d\n", dev->name, aup->rx_head);
prxd = aup->rx_dma_ring[aup->rx_head];
@@ -1150,7 +1996,9 @@ static int au1000_rx(struct net_device *dev)
if (!(status & RX_ERROR)) {
/* good frame */
- skb = dev_alloc_skb((status & RX_FRAME_LEN_MASK) + 2);
+ frmlen = (status & RX_FRAME_LEN_MASK);
+ frmlen -= 4; /* Remove FCS */
+ skb = dev_alloc_skb(frmlen + 2);
if (skb == NULL) {
printk(KERN_ERR
"%s: Memory squeeze, dropping packet.\n",
@@ -1160,9 +2008,9 @@ static int au1000_rx(struct net_device *dev)
}
skb->dev = dev;
skb_reserve(skb, 2); /* 16 byte IP header align */
- eth_copy_and_sum(skb, (unsigned char *)pDB->vaddr,
- status & RX_FRAME_LEN_MASK, 0);
- skb_put(skb, status & RX_FRAME_LEN_MASK);
+ eth_copy_and_sum(skb,
+ (unsigned char *)pDB->vaddr, frmlen, 0);
+ skb_put(skb, frmlen);
skb->protocol = eth_type_trans(skb, dev);
netif_rx(skb); /* pass the packet to upper layers */
}
@@ -1206,17 +2054,20 @@ static int au1000_rx(struct net_device *dev)
/*
* Au1000 interrupt service routine.
*/
-irqreturn_t au1000_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t au1000_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
struct net_device *dev = (struct net_device *) dev_id;
if (dev == NULL) {
printk(KERN_ERR "%s: isr: null dev ptr\n", dev->name);
- return IRQ_NONE;
+ return IRQ_RETVAL(1);
}
- au1000_tx_ack(dev);
+
+ /* Handle RX interrupts first to minimize chance of overrun */
+
au1000_rx(dev);
- return IRQ_HANDLED;
+ au1000_tx_ack(dev);
+ return IRQ_RETVAL(1);
}
@@ -1233,6 +2084,23 @@ static void au1000_tx_timeout(struct net_device *dev)
netif_wake_queue(dev);
}
+
+static unsigned const ethernet_polynomial = 0x04c11db7U;
+static inline u32 ether_crc(int length, unsigned char *data)
+{
+ int crc = -1;
+
+ while(--length >= 0) {
+ unsigned char current_octet = *data++;
+ int bit;
+ for (bit = 0; bit < 8; bit++, current_octet >>= 1)
+ crc = (crc << 1) ^
+ ((crc < 0) ^ (current_octet & 1) ?
+ ethernet_polynomial : 0);
+ }
+ return crc;
+}
+
static void set_rx_mode(struct net_device *dev)
{
struct au1000_private *aup = (struct au1000_private *) dev->priv;
@@ -1256,8 +2124,8 @@ static void set_rx_mode(struct net_device *dev)
mc_filter[1] = mc_filter[0] = 0;
for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
i++, mclist = mclist->next) {
- set_bit(ether_crc_le(ETH_ALEN, mclist->dmi_addr)>>26,
- mc_filter);
+ set_bit(ether_crc(ETH_ALEN, mclist->dmi_addr)>>26,
+ (long *)mc_filter);
}
aup->mac->multi_hash_high = mc_filter[1];
aup->mac->multi_hash_low = mc_filter[0];
@@ -1269,28 +2137,28 @@ static void set_rx_mode(struct net_device *dev)
static int au1000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
+ struct au1000_private *aup = (struct au1000_private *)dev->priv;
u16 *data = (u16 *)&rq->ifr_ifru;
- /* fixme */
switch(cmd) {
- case SIOCGMIIPHY: /* Get the address of the PHY in use. */
- data[0] = PHY_ADDRESS;
- return 0;
-
- case SIOCGMIIREG: /* Read the specified MII register. */
- //data[3] = mdio_read(ioaddr, data[0], data[1]);
- return 0;
-
- case SIOCSMIIREG: /* Write the specified MII register */
- if (!capable(CAP_NET_ADMIN))
- return -EPERM;
-
- //mdio_write(ioaddr, data[0], data[1], data[2]);
- return 0;
-
- default:
- return -EOPNOTSUPP;
+ case SIOCDEVPRIVATE: /* Get the address of the PHY in use. */
+ case SIOCGMIIPHY:
+ if (!netif_running(dev)) return -EINVAL;
+ data[0] = aup->phy_addr;
+ case SIOCDEVPRIVATE+1: /* Read the specified MII register. */
+ case SIOCGMIIREG:
+ data[3] = mdio_read(dev, data[0], data[1]);
+ return 0;
+ case SIOCDEVPRIVATE+2: /* Write the specified MII register */
+ case SIOCSMIIREG:
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+ mdio_write(dev, data[0], data[1],data[2]);
+ return 0;
+ default:
+ return -EOPNOTSUPP;
}
+
}
@@ -1352,7 +2220,6 @@ static int au1000_set_config(struct net_device *dev, struct ifmap *map)
/* set Speed to 100Mbps, Half Duplex */
/* disable auto negotiation and enable 100MBit Mode */
control = mdio_read(dev, aup->phy_addr, MII_CONTROL);
- printk("read control %x\n", control);
control &= ~(MII_CNTL_AUTO | MII_CNTL_FDX);
control |= MII_CNTL_F100;
mdio_write(dev, aup->phy_addr, MII_CONTROL, control);
diff --git a/drivers/net/au1000_eth.h b/drivers/net/au1000_eth.h
index a17f0b1a8a1b2..7f9326e39cc0b 100644
--- a/drivers/net/au1000_eth.h
+++ b/drivers/net/au1000_eth.h
@@ -1,10 +1,13 @@
/*
- * Alchemy Semi Au1000 ethernet driver include file
+ *
+ * Alchemy Au1x00 ethernet driver include file
*
* Author: Pete Popov <ppopov@mvista.com>
*
* Copyright 2001 MontaVista Software Inc.
*
+ * ########################################################################
+ *
* This program is free software; you can distribute it and/or modify it
* under the terms of the GNU General Public License (Version 2) as
* published by the Free Software Foundation.
@@ -17,14 +20,16 @@
* You should have received a copy of the 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>
-#define NUM_INTERFACES 2
#define MAC_IOSIZE 0x10000
-#define NUM_RX_DMA 4 /* Au1000 has 4 rx hardware descriptors */
-#define NUM_TX_DMA 4 /* Au1000 has 4 tx hardware descriptors */
+#define NUM_RX_DMA 4 /* Au1x00 has 4 rx hardware descriptors */
+#define NUM_TX_DMA 4 /* Au1x00 has 4 tx hardware descriptors */
#define NUM_RX_BUFFS 4
#define NUM_TX_BUFFS 4
@@ -33,12 +38,6 @@
#define ETH_TX_TIMEOUT HZ/4
#define MAC_MIN_PKT_SIZE 64
-#if defined(CONFIG_MIPS_PB1000) || defined(CONFIG_MIPS_PB1500) || defined(CONFIG_MIPS_PB1100)
-#define PHY_ADDRESS 0
-#define PHY_CONTROL_DEFAULT 0x3000
-#define PHY_CONTROL_REG_ADDR 0
-#endif
-
#define MULTICAST_FILTER_LIMIT 64
/* FIXME
@@ -54,11 +53,13 @@
#define MII_ANLPAR 0x0005
#define MII_AEXP 0x0006
#define MII_ANEXT 0x0007
-#define MII_LSI_CONFIG 0x0011
-#define MII_LSI_STAT 0x0012
-#define MII_AUX_CNTRL 0x0018
-#define MII_INT 0x001A
+#define MII_LSI_PHY_CONFIG 0x0011
+/* Status register */
+#define MII_LSI_PHY_STAT 0x0012
+#define MII_AMD_PHY_STAT MII_LSI_PHY_STAT
+#define MII_INTEL_PHY_STAT 0x0011
+#define MII_AUX_CNTRL 0x0018
/* mii registers specific to AMD 79C901 */
#define MII_STATUS_SUMMARY = 0x0018
@@ -121,23 +122,30 @@
#define MII_STSSUM_AUTO 0x0002
#define MII_STSSUM_SPD 0x0001
-/* lsi status register */
+/* lsi phy status register */
+#define MII_LSI_PHY_STAT_FDX 0x0040
+#define MII_LSI_PHY_STAT_SPD 0x0080
+
+/* amd phy status register */
+#define MII_AMD_PHY_STAT_FDX 0x0800
+#define MII_AMD_PHY_STAT_SPD 0x0400
-#define MII_LSI_STAT_FDX 0x0040
-#define MII_LSI_STAT_SPD 0x0080
+/* intel phy status register */
+#define MII_INTEL_PHY_STAT_FDX 0x0200
+#define MII_INTEL_PHY_STAT_SPD 0x4000
/* Auxilliary Control/Status Register */
#define MII_AUX_FDX 0x0001
#define MII_AUX_100 0x0002
#define MII_AUX_F100 0x0004
#define MII_AUX_ANEG 0x0008
-#define MII_FDX_LED 0x8000
typedef struct mii_phy {
struct mii_phy * next;
struct mii_chip_info * chip_info;
- int phy_addr;
u16 status;
+ u32 *mii_control_reg;
+ u32 *mii_data_reg;
} mii_phy_t;
struct phy_ops {
@@ -197,7 +205,6 @@ struct au1000_private {
db_dest_t db[NUM_RX_BUFFS+NUM_TX_BUFFS];
volatile rx_dma_t *rx_dma_ring[NUM_RX_DMA];
volatile tx_dma_t *tx_dma_ring[NUM_TX_DMA];
- int tx_len[NUM_TX_DMA];
db_dest_t *rx_db_inuse[NUM_RX_DMA];
db_dest_t *tx_db_inuse[NUM_TX_DMA];
u32 rx_head;
@@ -205,6 +212,7 @@ struct au1000_private {
u32 tx_tail;
u32 tx_full;
+ int mac_id;
mii_phy_t *mii;
struct phy_ops *phy_ops;
@@ -218,9 +226,10 @@ struct au1000_private {
u8 *hash_table;
u32 hash_mode;
u32 intr_work_done; /* number of Rx and Tx pkts processed in the isr */
- u32 phy_addr; /* PHY address */
+ int phy_addr; /* phy address */
u32 options; /* User-settable misc. driver options. */
u32 drv_flags;
+ int want_autoneg;
struct net_device_stats stats;
struct timer_list timer;
spinlock_t lock; /* Serialise access to device */
diff --git a/drivers/net/b44.c b/drivers/net/b44.c
index f6fd4090a0cec..3fe8ba992c38b 100644
--- a/drivers/net/b44.c
+++ b/drivers/net/b44.c
@@ -907,6 +907,7 @@ static void b44_tx_timeout(struct net_device *dev)
static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct b44 *bp = netdev_priv(dev);
+ struct sk_buff *bounce_skb;
dma_addr_t mapping;
u32 len, entry, ctrl;
@@ -922,15 +923,31 @@ static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev)
return 1;
}
- entry = bp->tx_prod;
mapping = pci_map_single(bp->pdev, skb->data, len, PCI_DMA_TODEVICE);
if(mapping+len > B44_DMA_MASK) {
/* Chip can't handle DMA to/from >1GB, use bounce buffer */
- pci_unmap_single(bp->pdev, mapping, len,PCI_DMA_TODEVICE);
- memcpy(bp->tx_bufs+entry*TX_PKT_BUF_SZ,skb->data,skb->len);
- mapping = pci_map_single(bp->pdev, bp->tx_bufs+entry*TX_PKT_BUF_SZ, len, PCI_DMA_TODEVICE);
+ pci_unmap_single(bp->pdev, mapping, len, PCI_DMA_TODEVICE);
+
+ bounce_skb = __dev_alloc_skb(TX_PKT_BUF_SZ,
+ GFP_ATOMIC|GFP_DMA);
+ if (!bounce_skb)
+ return NETDEV_TX_BUSY;
+
+ mapping = pci_map_single(bp->pdev, bounce_skb->data,
+ len, PCI_DMA_TODEVICE);
+ if(mapping+len > B44_DMA_MASK) {
+ pci_unmap_single(bp->pdev, mapping,
+ len, PCI_DMA_TODEVICE);
+ dev_kfree_skb_any(bounce_skb);
+ return NETDEV_TX_BUSY;
+ }
+
+ memcpy(skb_put(bounce_skb, len), skb->data, skb->len);
+ dev_kfree_skb_any(skb);
+ skb = bounce_skb;
}
+ entry = bp->tx_prod;
bp->tx_buffers[entry].skb = skb;
pci_unmap_addr_set(&bp->tx_buffers[entry], mapping, mapping);
@@ -1077,11 +1094,6 @@ static void b44_free_consistent(struct b44 *bp)
bp->tx_ring, bp->tx_ring_dma);
bp->tx_ring = NULL;
}
- if (bp->tx_bufs) {
- pci_free_consistent(bp->pdev, B44_TX_RING_SIZE * TX_PKT_BUF_SZ,
- bp->tx_bufs, bp->tx_bufs_dma);
- bp->tx_bufs = NULL;
- }
}
/*
@@ -1104,12 +1116,6 @@ static int b44_alloc_consistent(struct b44 *bp)
goto out_err;
memset(bp->tx_buffers, 0, size);
- size = B44_TX_RING_SIZE * TX_PKT_BUF_SZ;
- bp->tx_bufs = pci_alloc_consistent(bp->pdev, size, &bp->tx_bufs_dma);
- if (!bp->tx_bufs)
- goto out_err;
- memset(bp->tx_bufs, 0, size);
-
size = DMA_TABLE_BYTES;
bp->rx_ring = pci_alloc_consistent(bp->pdev, size, &bp->rx_ring_dma);
if (!bp->rx_ring)
@@ -1903,7 +1909,7 @@ static void __devexit b44_remove_one(struct pci_dev *pdev)
}
}
-static int b44_suspend(struct pci_dev *pdev, u32 state)
+static int b44_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct net_device *dev = pci_get_drvdata(pdev);
struct b44 *bp = netdev_priv(dev);
diff --git a/drivers/net/b44.h b/drivers/net/b44.h
index f886692f20b44..11c40a2e71c70 100644
--- a/drivers/net/b44.h
+++ b/drivers/net/b44.h
@@ -302,20 +302,6 @@
#define B44_MII_TLEDCTRL 27 /* Traffic Meter LED */
#define MII_TLEDCTRL_ENABLE 0x0040
-/* XXX Add this to mii.h */
-#ifndef ADVERTISE_PAUSE
-#define ADVERTISE_PAUSE_CAP 0x0400
-#endif
-#ifndef ADVERTISE_PAUSE_ASYM
-#define ADVERTISE_PAUSE_ASYM 0x0800
-#endif
-#ifndef LPA_PAUSE
-#define LPA_PAUSE_CAP 0x0400
-#endif
-#ifndef LPA_PAUSE_ASYM
-#define LPA_PAUSE_ASYM 0x0800
-#endif
-
struct dma_desc {
u32 ctrl;
u32 addr;
@@ -397,7 +383,6 @@ struct b44 {
struct ring_info *rx_buffers;
struct ring_info *tx_buffers;
- unsigned char *tx_bufs;
u32 dma_offset;
u32 flags;
@@ -429,7 +414,7 @@ struct b44 {
struct pci_dev *pdev;
struct net_device *dev;
- dma_addr_t rx_ring_dma, tx_ring_dma,tx_bufs_dma;
+ dma_addr_t rx_ring_dma, tx_ring_dma;
u32 rx_pending;
u32 tx_pending;
diff --git a/drivers/net/bagetlance.c b/drivers/net/bagetlance.c
deleted file mode 100644
index 55a0f66f6cf80..0000000000000
--- a/drivers/net/bagetlance.c
+++ /dev/null
@@ -1,1368 +0,0 @@
-/*
- * bagetlance.c: Ethernet driver for VME Lance cards on Baget/MIPS
- * This code stealed and adopted from linux/drivers/net/atarilance.c
- * See that for author info
- *
- * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov
- */
-
-/*
- * Driver code for Baget/Lance taken from atarilance.c, which also
- * works well in case of Besta. Most significant changes made here
- * related with 16BIT-only access to A24 space.
- */
-
-static char *version = "bagetlance.c: v1.1 11/10/98\n";
-
-#include <linux/module.h>
-#include <linux/stddef.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/bitops.h>
-
-#include <asm/irq.h>
-#include <asm/io.h>
-#include <asm/baget/baget.h>
-
-#define BAGET_LANCE_IRQ BAGET_IRQ_MASK(0xdf)
-
-/*
- * Define following if you don't need 16BIT-only access to Lance memory
- * (Normally BAGET needs it)
- */
-#undef NORMAL_MEM_ACCESS
-
-/* Debug level:
- * 0 = silent, print only serious errors
- * 1 = normal, print error messages
- * 2 = debug, print debug infos
- * 3 = debug, print even more debug infos (packet data)
- */
-
-#define LANCE_DEBUG 1
-
-#ifdef LANCE_DEBUG
-static int lance_debug = LANCE_DEBUG;
-#else
-static int lance_debug = 1;
-#endif
-MODULE_PARM(lance_debug, "i");
-MODULE_PARM_DESC(lance_debug, "Lance debug level (0-3)");
-MODULE_LICENSE("GPL");
-
-/* Print debug messages on probing? */
-#undef LANCE_DEBUG_PROBE
-
-#define DPRINTK(n,a) \
- do { \
- if (lance_debug >= n) \
- printk a; \
- } while( 0 )
-
-#ifdef LANCE_DEBUG_PROBE
-# define PROBE_PRINT(a) printk a
-#else
-# define PROBE_PRINT(a)
-#endif
-
-/* These define the number of Rx and Tx buffers as log2. (Only powers
- * of two are valid)
- * Much more rx buffers (32) are reserved than tx buffers (8), since receiving
- * is more time critical then sending and packets may have to remain in the
- * board's memory when main memory is low.
- */
-
-/* Baget Lance has 64K on-board memory, so it looks we can't increase
- buffer quantity (40*1.5K is about 64K) */
-
-#define TX_LOG_RING_SIZE 3
-#define RX_LOG_RING_SIZE 5
-
-/* These are the derived values */
-
-#define TX_RING_SIZE (1 << TX_LOG_RING_SIZE)
-#define TX_RING_LEN_BITS (TX_LOG_RING_SIZE << 5)
-#define TX_RING_MOD_MASK (TX_RING_SIZE - 1)
-
-#define RX_RING_SIZE (1 << RX_LOG_RING_SIZE)
-#define RX_RING_LEN_BITS (RX_LOG_RING_SIZE << 5)
-#define RX_RING_MOD_MASK (RX_RING_SIZE - 1)
-
-/* The LANCE Rx and Tx ring descriptors. */
-struct lance_rx_head {
- volatile unsigned short base; /* Low word of base addr */
-#ifdef NORMAL_MEM_ACCESS
- /* Following two fields are joined into one short to guarantee
- 16BIT access to Baget lance registers */
- volatile unsigned char flag;
- unsigned char base_hi; /* High word of base addr (unused) */
-#else
-/* Following macros are used as replecements to 8BIT fields */
-#define GET_FLAG(h) (((h)->flag_base_hi >> 8) & 0xff)
-#define SET_FLAG(h,f) (h)->flag_base_hi = ((h)->flag_base_hi & 0xff) | \
- (((unsigned)(f)) << 8)
- volatile unsigned short flag_base_hi;
-#endif
- volatile short buf_length; /* This length is 2s complement! */
- volatile short msg_length; /* This length is "normal". */
-};
-
-
-struct lance_tx_head {
- volatile unsigned short base; /* Low word of base addr */
-#ifdef NORMAL_MEM_ACCESS
-/* See comments above about 8BIT-access Baget A24-space problems */
- volatile unsigned char flag;
- unsigned char base_hi; /* High word of base addr (unused) */
-#else
- volatile unsigned short flag_base_hi;
-#endif
- volatile short length; /* Length is 2s complement! */
- volatile short misc;
-};
-
-struct ringdesc {
- volatile unsigned short adr_lo; /* Low 16 bits of address */
-#ifdef NORMAL_MEM_ACCESS
-/* See comments above about 8BIT-access Bage A24-space problems */
- unsigned char len; /* Length bits */
- unsigned char adr_hi; /* High 8 bits of address (unused) */
-#else
- volatile unsigned short len_adr_hi;
-#endif
-};
-
-/* The LANCE initialization block, described in databook. */
-struct lance_init_block {
- unsigned short mode; /* Pre-set mode */
- unsigned char hwaddr[6]; /* Physical ethernet address */
- unsigned filter[2]; /* Multicast filter (unused). */
- /* Receive and transmit ring base, along with length bits. */
- struct ringdesc rx_ring;
- struct ringdesc tx_ring;
-};
-
-/* The whole layout of the Lance shared memory */
-struct lance_memory {
- struct lance_init_block init;
- struct lance_tx_head tx_head[TX_RING_SIZE];
- struct lance_rx_head rx_head[RX_RING_SIZE];
- char packet_area[0]; /* packet data follow after the
- * init block and the ring
- * descriptors and are located
- * at runtime */
-};
-
-/* RieblCard specifics:
- * The original TOS driver for these cards reserves the area from offset
- * 0xee70 to 0xeebb for storing configuration data. Of interest to us is the
- * Ethernet address there, and the magic for verifying the data's validity.
- * The reserved area isn't touch by packet buffers. Furthermore, offset 0xfffe
- * is reserved for the interrupt vector number.
- */
-#define RIEBL_RSVD_START 0xee70
-#define RIEBL_RSVD_END 0xeec0
-#define RIEBL_MAGIC 0x09051990
-#define RIEBL_MAGIC_ADDR ((unsigned long *)(((char *)MEM) + 0xee8a))
-#define RIEBL_HWADDR_ADDR ((unsigned char *)(((char *)MEM) + 0xee8e))
-#define RIEBL_IVEC_ADDR ((unsigned short *)(((char *)MEM) + 0xfffe))
-
-/* This is a default address for the old RieblCards without a battery
- * that have no ethernet address at boot time. 00:00:36:04 is the
- * prefix for Riebl cards, the 00:00 at the end is arbitrary.
- */
-
-static unsigned char OldRieblDefHwaddr[6] = {
- 0x00, 0x00, 0x36, 0x04, 0x00, 0x00
-};
-
-/* I/O registers of the Lance chip */
-
-struct lance_ioreg {
-/* base+0x0 */ volatile unsigned short data;
-/* base+0x2 */ volatile unsigned short addr;
- unsigned char _dummy1[3];
-/* base+0x7 */ volatile unsigned char ivec;
- unsigned char _dummy2[5];
-/* base+0xd */ volatile unsigned char eeprom;
- unsigned char _dummy3;
-/* base+0xf */ volatile unsigned char mem;
-};
-
-/* Types of boards this driver supports */
-
-enum lance_type {
- OLD_RIEBL, /* old Riebl card without battery */
- NEW_RIEBL, /* new Riebl card with battery */
- PAM_CARD /* PAM card with EEPROM */
-};
-
-static char *lance_names[] = {
- "Riebl-Card (without battery)",
- "Riebl-Card (with battery)",
- "PAM intern card"
-};
-
-/* The driver's private device structure */
-
-struct lance_private {
- enum lance_type cardtype;
- struct lance_ioreg *iobase;
- struct lance_memory *mem;
- int cur_rx, cur_tx; /* The next free ring entry */
- int dirty_tx; /* Ring entries to be freed. */
- /* copy function */
- void *(*memcpy_f)( void *, const void *, size_t );
- struct net_device_stats stats;
-/* These two must be longs for set_bit() */
- long tx_full;
- long lock;
-};
-
-/* I/O register access macros */
-
-#define MEM lp->mem
-#define DREG IO->data
-#define AREG IO->addr
-#define REGA(a) ( AREG = (a), DREG )
-
-/* Definitions for packet buffer access: */
-#define PKT_BUF_SZ 1544
-/* Get the address of a packet buffer corresponding to a given buffer head */
-#define PKTBUF_ADDR(head) (((unsigned char *)(MEM)) + (head)->base)
-
-/* Possible memory/IO addresses for probing */
-
-struct lance_addr {
- unsigned long memaddr;
- unsigned long ioaddr;
- int slow_flag;
-} lance_addr_list[] = {
- { BAGET_LANCE_MEM_BASE, BAGET_LANCE_IO_BASE, 1 } /* Baget Lance */
-};
-
-#define N_LANCE_ADDR (sizeof(lance_addr_list)/sizeof(*lance_addr_list))
-
-
-#define LANCE_HI_BASE (0xff & (BAGET_LANCE_MEM_BASE >> 16))
-
-/* Definitions for the Lance */
-
-/* tx_head flags */
-#define TMD1_ENP 0x01 /* end of packet */
-#define TMD1_STP 0x02 /* start of packet */
-#define TMD1_DEF 0x04 /* deferred */
-#define TMD1_ONE 0x08 /* one retry needed */
-#define TMD1_MORE 0x10 /* more than one retry needed */
-#define TMD1_ERR 0x40 /* error summary */
-#define TMD1_OWN 0x80 /* ownership (set: chip owns) */
-
-#define TMD1_OWN_CHIP TMD1_OWN
-#define TMD1_OWN_HOST 0
-
-/* tx_head misc field */
-#define TMD3_TDR 0x03FF /* Time Domain Reflectometry counter */
-#define TMD3_RTRY 0x0400 /* failed after 16 retries */
-#define TMD3_LCAR 0x0800 /* carrier lost */
-#define TMD3_LCOL 0x1000 /* late collision */
-#define TMD3_UFLO 0x4000 /* underflow (late memory) */
-#define TMD3_BUFF 0x8000 /* buffering error (no ENP) */
-
-/* rx_head flags */
-#define RMD1_ENP 0x01 /* end of packet */
-#define RMD1_STP 0x02 /* start of packet */
-#define RMD1_BUFF 0x04 /* buffer error */
-#define RMD1_CRC 0x08 /* CRC error */
-#define RMD1_OFLO 0x10 /* overflow */
-#define RMD1_FRAM 0x20 /* framing error */
-#define RMD1_ERR 0x40 /* error summary */
-#define RMD1_OWN 0x80 /* ownership (set: ship owns) */
-
-#define RMD1_OWN_CHIP RMD1_OWN
-#define RMD1_OWN_HOST 0
-
-/* register names */
-#define CSR0 0 /* mode/status */
-#define CSR1 1 /* init block addr (low) */
-#define CSR2 2 /* init block addr (high) */
-#define CSR3 3 /* misc */
-#define CSR8 8 /* address filter */
-#define CSR15 15 /* promiscuous mode */
-
-/* CSR0 */
-/* (R=readable, W=writeable, S=set on write, C=clear on write) */
-#define CSR0_INIT 0x0001 /* initialize (RS) */
-#define CSR0_STRT 0x0002 /* start (RS) */
-#define CSR0_STOP 0x0004 /* stop (RS) */
-#define CSR0_TDMD 0x0008 /* transmit demand (RS) */
-#define CSR0_TXON 0x0010 /* transmitter on (R) */
-#define CSR0_RXON 0x0020 /* receiver on (R) */
-#define CSR0_INEA 0x0040 /* interrupt enable (RW) */
-#define CSR0_INTR 0x0080 /* interrupt active (R) */
-#define CSR0_IDON 0x0100 /* initialization done (RC) */
-#define CSR0_TINT 0x0200 /* transmitter interrupt (RC) */
-#define CSR0_RINT 0x0400 /* receiver interrupt (RC) */
-#define CSR0_MERR 0x0800 /* memory error (RC) */
-#define CSR0_MISS 0x1000 /* missed frame (RC) */
-#define CSR0_CERR 0x2000 /* carrier error (no heartbeat :-) (RC) */
-#define CSR0_BABL 0x4000 /* babble: tx-ed too many bits (RC) */
-#define CSR0_ERR 0x8000 /* error (RC) */
-
-/* CSR3 */
-#define CSR3_BCON 0x0001 /* byte control */
-#define CSR3_ACON 0 // fixme: 0x0002 /* ALE control */
-#define CSR3_BSWP 0x0004 /* byte swap (1=big endian) */
-
-
-
-/***************************** Prototypes *****************************/
-
-static int addr_accessible( volatile void *regp, int wordflag, int
- writeflag );
-static int lance_probe1( struct net_device *dev, struct lance_addr *init_rec );
-static int lance_open( struct net_device *dev );
-static void lance_init_ring( struct net_device *dev );
-static int lance_start_xmit( struct sk_buff *skb, struct net_device *dev );
-static irqreturn_t lance_interrupt( int irq, void *dev_id, struct pt_regs *fp );
-static int lance_rx( struct net_device *dev );
-static int lance_close( struct net_device *dev );
-static struct net_device_stats *lance_get_stats( struct net_device *dev );
-static void set_multicast_list( struct net_device *dev );
-static int lance_set_mac_address( struct net_device *dev, void *addr );
-
-/************************* End of Prototypes **************************/
-
-/* Network traffic statistic (bytes) */
-
-int lance_stat = 0;
-
-static void update_lance_stat (int len) {
- lance_stat += len;
-}
-
-/*
- This function is used to access Baget/Lance memory to avoid
- 8/32BIT access to VAC A24 space
- ALL memcpy calls was chenged to this function to avoid dbe problems
- Don't confuse with function name -- it stays from original code
-*/
-
-void *slow_memcpy( void *dst, const void *src, size_t len )
-
-{
- unsigned long to = (unsigned long)dst;
- unsigned long from = (unsigned long)src;
- unsigned long to_end = to +len;
-
- /* Unaligned flags */
-
- int odd_from = from & 1;
- int odd_to = to & 1;
- int odd_to_end = to_end & 1;
-
- /* Align for 16BIT-access first */
-
- register unsigned short *from_a = (unsigned short*) (from & ~1);
- register unsigned short *to_a = (unsigned short*) (to & ~1);
- register unsigned short *to_end_a = (unsigned short*) (to_end & ~1);
-
- /* Caching values -- not in loop invariant */
-
- register unsigned short from_v;
- register unsigned short to_v;
-
- /* Invariant is: from_a and to_a are pointers before or exactly to
- currently copying byte */
-
- if (odd_to) {
- /* First byte unaligned case */
- from_v = *from_a;
- to_v = *to_a;
-
- to_v &= ~0xff;
- to_v |= 0xff & (from_v >> (odd_from ? 0 : 8));
- *to_a++ = to_v;
-
- if (odd_from) from_a++;
- }
- if (odd_from == odd_to) {
- /* Same parity */
- while (to_a + 7 < to_end_a) {
- unsigned long dummy1, dummy2;
- unsigned long reg1, reg2, reg3, reg4;
-
- __asm__ __volatile__(
- ".set\tnoreorder\n\t"
- ".set\tnoat\n\t"
- "lh\t%2,0(%1)\n\t"
- "nop\n\t"
- "lh\t%3,2(%1)\n\t"
- "sh\t%2,0(%0)\n\t"
- "lh\t%4,4(%1)\n\t"
- "sh\t%3,2(%0)\n\t"
- "lh\t%5,6(%1)\n\t"
- "sh\t%4,4(%0)\n\t"
- "lh\t%2,8(%1)\n\t"
- "sh\t%5,6(%0)\n\t"
- "lh\t%3,10(%1)\n\t"
- "sh\t%2,8(%0)\n\t"
- "lh\t%4,12(%1)\n\t"
- "sh\t%3,10(%0)\n\t"
- "lh\t%5,14(%1)\n\t"
- "sh\t%4,12(%0)\n\t"
- "nop\n\t"
- "sh\t%5,14(%0)\n\t"
- ".set\tat\n\t"
- ".set\treorder"
- :"=r" (dummy1), "=r" (dummy2),
- "=&r" (reg1), "=&r" (reg2), "=&r" (reg3), "=&r" (reg4)
- :"0" (to_a), "1" (from_a)
- :"memory");
-
- to_a += 8;
- from_a += 8;
-
- }
- while (to_a < to_end_a) {
- *to_a++ = *from_a++;
- }
- } else {
- /* Different parity */
- from_v = *from_a;
- while (to_a < to_end_a) {
- unsigned short from_v_next;
- from_v_next = *++from_a;
- *to_a++ = ((from_v & 0xff)<<8) | ((from_v_next>>8) & 0xff);
- from_v = from_v_next;
- }
-
- }
- if (odd_to_end) {
- /* Last byte unaligned case */
- to_v = *to_a;
- from_v = *from_a;
-
- to_v &= ~0xff00;
- if (odd_from == odd_to) {
- to_v |= from_v & 0xff00;
- } else {
- to_v |= (from_v<<8) & 0xff00;
- }
-
- *to_a = to_v;
- }
-
- update_lance_stat( len );
-
- return( dst );
-}
-
-
-struct net_device * __init bagetlance_probe(int unit)
-{
- struct net_device *dev;
- int i;
- static int found;
- int err = -ENODEV;
-
- if (found)
- /* Assume there's only one board possible... That seems true, since
- * the Riebl/PAM board's address cannot be changed. */
- return ERR_PTR(-ENODEV);
-
- dev = alloc_etherdev(sizeof(struct lance_private));
- if (!dev)
- return ERR_PTR(-ENOMEM);
-
- SET_MODULE_OWNER(dev);
-
- for( i = 0; i < N_LANCE_ADDR; ++i ) {
- if (lance_probe1( dev, &lance_addr_list[i] )) {
- found = 1;
- break;
- }
- }
- if (!found)
- goto out;
- err = register_netdev(dev);
- if (err)
- goto out1;
- return dev;
-out1:
- free_irq(dev->irq, dev);
-out:
- free_netdev(dev);
- return ERR_PTR(err);
-}
-
-/* Derived from hwreg_present() in vme/config.c: */
-
-static int __init addr_accessible( volatile void *regp,
- int wordflag,
- int writeflag )
-{
- /* We have a fine function to do it */
- extern int try_read(unsigned long, int);
- return try_read((unsigned long)regp, sizeof(short)) != -1;
-}
-
-
-
-/* Original atari driver uses it */
-#define IRQ_TYPE_PRIO SA_INTERRUPT
-#define IRQ_SOURCE_TO_VECTOR(x) (x)
-
-static int __init lance_probe1( struct net_device *dev,
- struct lance_addr *init_rec )
-
-{ volatile unsigned short *memaddr =
- (volatile unsigned short *)init_rec->memaddr;
- volatile unsigned short *ioaddr =
- (volatile unsigned short *)init_rec->ioaddr;
- struct lance_private *lp;
- struct lance_ioreg *IO;
- int i;
- static int did_version;
- unsigned short save1, save2;
-
- PROBE_PRINT(( "Probing for Lance card at mem %#lx io %#lx\n",
- (long)memaddr, (long)ioaddr ));
-
- /* Test whether memory readable and writable */
- PROBE_PRINT(( "lance_probe1: testing memory to be accessible\n" ));
- if (!addr_accessible( memaddr, 1, 1 )) goto probe_fail;
-
- if ((unsigned long)memaddr >= KSEG2) {
- /* FIXME: do we need to undo that on cleanup paths? */
- extern int kseg2_alloc_io (unsigned long addr, unsigned long size);
- if (kseg2_alloc_io((unsigned long)memaddr, BAGET_LANCE_MEM_SIZE)) {
- printk("bagetlance: unable map lance memory\n");
- goto probe_fail;
- }
- }
-
- /* Written values should come back... */
- PROBE_PRINT(( "lance_probe1: testing memory to be writable (1)\n" ));
- save1 = *memaddr;
- *memaddr = 0x0001;
- if (*memaddr != 0x0001) goto probe_fail;
- PROBE_PRINT(( "lance_probe1: testing memory to be writable (2)\n" ));
- *memaddr = 0x0000;
- if (*memaddr != 0x0000) goto probe_fail;
- *memaddr = save1;
-
- /* First port should be readable and writable */
- PROBE_PRINT(( "lance_probe1: testing ioport to be accessible\n" ));
- if (!addr_accessible( ioaddr, 1, 1 )) goto probe_fail;
-
- /* and written values should be readable */
- PROBE_PRINT(( "lance_probe1: testing ioport to be writeable\n" ));
- save2 = ioaddr[1];
- ioaddr[1] = 0x0001;
- if (ioaddr[1] != 0x0001) goto probe_fail;
-
- /* The CSR0_INIT bit should not be readable */
- PROBE_PRINT(( "lance_probe1: testing CSR0 register function (1)\n" ));
- save1 = ioaddr[0];
- ioaddr[1] = CSR0;
- ioaddr[0] = CSR0_INIT | CSR0_STOP;
- if (ioaddr[0] != CSR0_STOP) {
- ioaddr[0] = save1;
- ioaddr[1] = save2;
- goto probe_fail;
- }
- PROBE_PRINT(( "lance_probe1: testing CSR0 register function (2)\n" ));
- ioaddr[0] = CSR0_STOP;
- if (ioaddr[0] != CSR0_STOP) {
- ioaddr[0] = save1;
- ioaddr[1] = save2;
- goto probe_fail;
- }
-
- /* Now ok... */
- PROBE_PRINT(( "lance_probe1: Lance card detected\n" ));
- goto probe_ok;
-
- probe_fail:
- return( 0 );
-
- probe_ok:
- lp = netdev_priv(dev);
- MEM = (struct lance_memory *)memaddr;
- IO = lp->iobase = (struct lance_ioreg *)ioaddr;
- dev->base_addr = (unsigned long)ioaddr; /* informational only */
- lp->memcpy_f = init_rec->slow_flag ? slow_memcpy : memcpy;
-
- REGA( CSR0 ) = CSR0_STOP;
-
- /* Now test for type: If the eeprom I/O port is readable, it is a
- * PAM card */
- if (addr_accessible( &(IO->eeprom), 0, 0 )) {
- /* Switch back to Ram */
- i = IO->mem;
- lp->cardtype = PAM_CARD;
- }
-#ifdef NORMAL_MEM_ACCESS
- else if (*RIEBL_MAGIC_ADDR == RIEBL_MAGIC) {
-#else
- else if (({
- unsigned short *a = (unsigned short*)RIEBL_MAGIC_ADDR;
- (((int)a[0]) << 16) + ((int)a[1]) == RIEBL_MAGIC;
- })) {
-#endif
- lp->cardtype = NEW_RIEBL;
- }
- else
- lp->cardtype = OLD_RIEBL;
-
- if (lp->cardtype == PAM_CARD ||
- memaddr == (unsigned short *)0xffe00000) {
- /* PAMs card and Riebl on ST use level 5 autovector */
- if (request_irq(BAGET_LANCE_IRQ, lance_interrupt, IRQ_TYPE_PRIO,
- "PAM/Riebl-ST Ethernet", dev))
- goto probe_fail;
- dev->irq = (unsigned short)BAGET_LANCE_IRQ;
- }
- else {
- /* For VME-RieblCards, request a free VME int;
- * (This must be unsigned long, since dev->irq is short and the
- * IRQ_MACHSPEC bit would be cut off...)
- */
- unsigned long irq = BAGET_LANCE_IRQ;
- if (!irq) {
- printk( "Lance: request for VME interrupt failed\n" );
- goto probe_fail;
- }
- if (request_irq(irq, lance_interrupt, IRQ_TYPE_PRIO,
- "Riebl-VME Ethernet", dev))
- goto probe_fail;
- dev->irq = irq;
- }
-
- printk("%s: %s at io %#lx, mem %#lx, irq %d%s, hwaddr ",
- dev->name, lance_names[lp->cardtype],
- (unsigned long)ioaddr,
- (unsigned long)memaddr,
- dev->irq,
- init_rec->slow_flag ? " (slow memcpy)" : "" );
-
- /* Get the ethernet address */
- switch( lp->cardtype ) {
- case OLD_RIEBL:
- /* No ethernet address! (Set some default address) */
- slow_memcpy( dev->dev_addr, OldRieblDefHwaddr, 6 );
- break;
- case NEW_RIEBL:
- lp->memcpy_f( dev->dev_addr, RIEBL_HWADDR_ADDR, 6 );
- break;
- case PAM_CARD:
- i = IO->eeprom;
- for( i = 0; i < 6; ++i )
- dev->dev_addr[i] =
- ((((unsigned short *)MEM)[i*2] & 0x0f) << 4) |
- ((((unsigned short *)MEM)[i*2+1] & 0x0f));
- i = IO->mem;
- break;
- }
- for( i = 0; i < 6; ++i )
- printk( "%02x%s", dev->dev_addr[i], (i < 5) ? ":" : "\n" );
- if (lp->cardtype == OLD_RIEBL) {
- printk( "%s: Warning: This is a default ethernet address!\n",
- dev->name );
- printk( " Use \"ifconfig hw ether ...\" to set the address.\n" );
- }
-
- MEM->init.mode = 0x0000; /* Disable Rx and Tx. */
-
- {
- unsigned char hwaddr[6];
- for( i = 0; i < 6; i++ )
- hwaddr[i] = dev->dev_addr[i^1]; /* <- 16 bit swap! */
- slow_memcpy(MEM->init.hwaddr, hwaddr, sizeof(hwaddr));
- }
-
- MEM->init.filter[0] = 0x00000000;
- MEM->init.filter[1] = 0x00000000;
- MEM->init.rx_ring.adr_lo = offsetof( struct lance_memory, rx_head );
-
-#ifdef NORMAL_MEM_ACCESS
- MEM->init.rx_ring.adr_hi = LANCE_HI_BASE;
- MEM->init.rx_ring.len = RX_RING_LEN_BITS;
-#else
- MEM->init.rx_ring.len_adr_hi =
- ((unsigned)RX_RING_LEN_BITS << 8) | LANCE_HI_BASE;
-#endif
-
-
- MEM->init.tx_ring.adr_lo = offsetof( struct lance_memory, tx_head );
-
-#ifdef NORMAL_MEM_ACCESS
- MEM->init.tx_ring.adr_hi = LANCE_HI_BASE;
- MEM->init.tx_ring.len = TX_RING_LEN_BITS;
-#else
- MEM->init.tx_ring.len_adr_hi =
- ((unsigned)TX_RING_LEN_BITS<<8) | LANCE_HI_BASE;
-#endif
-
- if (lp->cardtype == PAM_CARD)
- IO->ivec = IRQ_SOURCE_TO_VECTOR(dev->irq);
- else
- *RIEBL_IVEC_ADDR = IRQ_SOURCE_TO_VECTOR(dev->irq);
-
- if (did_version++ == 0)
- DPRINTK( 1, ( version ));
-
- /* The LANCE-specific entries in the device structure. */
- dev->open = &lance_open;
- dev->hard_start_xmit = &lance_start_xmit;
- dev->stop = &lance_close;
- dev->get_stats = &lance_get_stats;
- dev->set_multicast_list = &set_multicast_list;
- dev->set_mac_address = &lance_set_mac_address;
- dev->start = 0;
-
- memset( &lp->stats, 0, sizeof(lp->stats) );
-
- return( 1 );
-}
-
-
-static int lance_open( struct net_device *dev )
-
-{ struct lance_private *lp = netdev_priv(dev);
- struct lance_ioreg *IO = lp->iobase;
- int i;
-
- DPRINTK( 2, ( "%s: lance_open()\n", dev->name ));
-
- lance_init_ring(dev);
- /* Re-initialize the LANCE, and start it when done. */
-
- REGA( CSR3 ) = CSR3_BSWP | (lp->cardtype == PAM_CARD ? CSR3_ACON : 0);
- REGA( CSR2 ) = 0;
- REGA( CSR1 ) = 0;
- REGA( CSR0 ) = CSR0_INIT;
- /* From now on, AREG is kept to point to CSR0 */
-
- i = 1000000;
- while (--i > 0)
- if (DREG & CSR0_IDON)
- break;
- if (i < 0 || (DREG & CSR0_ERR)) {
- DPRINTK( 2, ( "lance_open(): opening %s failed, i=%d, csr0=%04x\n",
- dev->name, i, DREG ));
- DREG = CSR0_STOP;
- return( -EIO );
- }
- DREG = CSR0_IDON;
- DREG = CSR0_STRT;
- DREG = CSR0_INEA;
-
- dev->tbusy = 0;
- dev->interrupt = 0;
- dev->start = 1;
-
- DPRINTK( 2, ( "%s: LANCE is open, csr0 %04x\n", dev->name, DREG ));
- return( 0 );
-}
-
-
-/* Initialize the LANCE Rx and Tx rings. */
-
-static void lance_init_ring( struct net_device *dev )
-
-{ struct lance_private *lp = netdev_priv(dev);
- int i;
- unsigned offset;
-
- lp->lock = 0;
- lp->tx_full = 0;
- lp->cur_rx = lp->cur_tx = 0;
- lp->dirty_tx = 0;
-
- offset = offsetof( struct lance_memory, packet_area );
-
-/* If the packet buffer at offset 'o' would conflict with the reserved area
- * of RieblCards, advance it */
-#define CHECK_OFFSET(o) \
- do { \
- if (lp->cardtype == OLD_RIEBL || lp->cardtype == NEW_RIEBL) { \
- if (((o) < RIEBL_RSVD_START) ? (o)+PKT_BUF_SZ > RIEBL_RSVD_START \
- : (o) < RIEBL_RSVD_END) \
- (o) = RIEBL_RSVD_END; \
- } \
- } while(0)
-
- for( i = 0; i < TX_RING_SIZE; i++ ) {
- CHECK_OFFSET(offset);
- MEM->tx_head[i].base = offset;
-#ifdef NORMAL_MEM_ACCESS
- MEM->tx_head[i].flag = TMD1_OWN_HOST;
- MEM->tx_head[i].base_hi = LANCE_HI_BASE;
-#else
- MEM->tx_head[i].flag_base_hi =
- (TMD1_OWN_HOST<<8) | LANCE_HI_BASE;
-#endif
- MEM->tx_head[i].length = 0;
- MEM->tx_head[i].misc = 0;
- offset += PKT_BUF_SZ;
- }
-
- for( i = 0; i < RX_RING_SIZE; i++ ) {
- CHECK_OFFSET(offset);
- MEM->rx_head[i].base = offset;
-#ifdef NORMAL_MEM_ACCESS
- MEM->rx_head[i].flag = TMD1_OWN_CHIP;
- MEM->rx_head[i].base_hi = LANCE_HI_BASE;
-#else
- MEM->rx_head[i].flag_base_hi =
- (TMD1_OWN_CHIP<<8) | LANCE_HI_BASE;
-#endif
- MEM->rx_head[i].buf_length = -PKT_BUF_SZ;
- MEM->rx_head[i].msg_length = 0;
- offset += PKT_BUF_SZ;
- }
-}
-
-
-static int lance_start_xmit( struct sk_buff *skb, struct net_device *dev )
-
-{ struct lance_private *lp = netdev_priv(dev);
- struct lance_ioreg *IO = lp->iobase;
- int entry, len;
- struct lance_tx_head *head;
- unsigned long flags;
-
- /* The old LANCE chips doesn't automatically pad buffers to min. size. */
- len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN;
- /* PAM-Card has a bug: Can only send packets with even number of bytes! */
- if (lp->cardtype == PAM_CARD && (len & 1))
- ++len;
-
- if (len > skb->len) {
- skb = skb_padto(skb, len);
- if (skb == NULL)
- return 0;
- }
-
- /* Transmitter timeout, serious problems. */
- if (dev->tbusy) {
- int tickssofar = jiffies - dev->trans_start;
- if (tickssofar < 20)
- return( 1 );
- AREG = CSR0;
- DPRINTK( 1, ( "%s: transmit timed out, status %04x, resetting.\n",
- dev->name, DREG ));
- DREG = CSR0_STOP;
- /*
- * Always set BSWP after a STOP as STOP puts it back into
- * little endian mode.
- */
- REGA( CSR3 ) = CSR3_BSWP | (lp->cardtype == PAM_CARD ? CSR3_ACON : 0);
- lp->stats.tx_errors++;
-#ifndef final_version
- { int i;
- DPRINTK( 2, ( "Ring data: dirty_tx %d cur_tx %d%s cur_rx %d\n",
- lp->dirty_tx, lp->cur_tx,
- lp->tx_full ? " (full)" : "",
- lp->cur_rx ));
- for( i = 0 ; i < RX_RING_SIZE; i++ )
- DPRINTK( 2, ( "rx #%d: base=%04x blen=%04x mlen=%04x\n",
- i, MEM->rx_head[i].base,
- -MEM->rx_head[i].buf_length,
- MEM->rx_head[i].msg_length ));
- for( i = 0 ; i < TX_RING_SIZE; i++ )
- DPRINTK( 2, ( "tx #%d: base=%04x len=%04x misc=%04x\n",
- i, MEM->tx_head[i].base,
- -MEM->tx_head[i].length,
- MEM->tx_head[i].misc ));
- }
-#endif
- lance_init_ring(dev);
- REGA( CSR0 ) = CSR0_INEA | CSR0_INIT | CSR0_STRT;
-
- dev->tbusy = 0;
- dev->trans_start = jiffies;
-
- return( 0 );
- }
-
- DPRINTK( 2, ( "%s: lance_start_xmit() called, csr0 %4.4x.\n",
- dev->name, DREG ));
-
- /* Block a timer-based transmit from overlapping. This could better be
- done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
- if (test_and_set_bit( 0, (void*)&dev->tbusy ) != 0) {
- DPRINTK( 0, ( "%s: Transmitter access conflict.\n", dev->name ));
- return 1;
- }
-
- if (test_and_set_bit( 0, (void*)&lp->lock ) != 0) {
- DPRINTK( 0, ( "%s: tx queue lock!.\n", dev->name ));
- /* don't clear dev->tbusy flag. */
- return 1;
- }
-
- /* Fill in a Tx ring entry */
- if (lance_debug >= 3) {
- u_char *p;
- int i;
- printk( "%s: TX pkt type 0x%04x from ", dev->name,
- ((u_short *)skb->data)[6]);
- for( p = &((u_char *)skb->data)[6], i = 0; i < 6; i++ )
- printk("%02x%s", *p++, i != 5 ? ":" : "" );
- printk(" to ");
- for( p = (u_char *)skb->data, i = 0; i < 6; i++ )
- printk("%02x%s", *p++, i != 5 ? ":" : "" );
- printk(" data at 0x%08x len %d\n", (int)skb->data,
- (int)skb->len );
- }
-
- /* We're not prepared for the int until the last flags are set/reset. And
- * the int may happen already after setting the OWN_CHIP... */
- save_flags(flags);
- cli();
-
- /* Mask to ring buffer boundary. */
- entry = lp->cur_tx & TX_RING_MOD_MASK;
- head = &(MEM->tx_head[entry]);
-
- /* Caution: the write order is important here, set the "ownership" bits
- * last.
- */
-
- head->length = -len;
- head->misc = 0;
- lp->memcpy_f( PKTBUF_ADDR(head), (void *)skb->data, skb->len );
-#ifdef NORMAL_MEM_ACCESS
- head->flag = TMD1_OWN_CHIP | TMD1_ENP | TMD1_STP;
-#else
- SET_FLAG(head,(TMD1_OWN_CHIP | TMD1_ENP | TMD1_STP));
-#endif
- lp->stats.tx_bytes += skb->len;
- dev_kfree_skb( skb );
- lp->cur_tx++;
- while( lp->cur_tx >= TX_RING_SIZE && lp->dirty_tx >= TX_RING_SIZE ) {
- lp->cur_tx -= TX_RING_SIZE;
- lp->dirty_tx -= TX_RING_SIZE;
- }
-
- /* Trigger an immediate send poll. */
- DREG = CSR0_INEA | CSR0_TDMD;
- dev->trans_start = jiffies;
-
- lp->lock = 0;
-#ifdef NORMAL_MEM_ACCESS
- if ((MEM->tx_head[(entry+1) & TX_RING_MOD_MASK].flag & TMD1_OWN) ==
-#else
- if ((GET_FLAG(&MEM->tx_head[(entry+1) & TX_RING_MOD_MASK]) & TMD1_OWN) ==
-#endif
- TMD1_OWN_HOST)
- dev->tbusy = 0;
- else
- lp->tx_full = 1;
- restore_flags(flags);
-
- return 0;
-}
-
-/* The LANCE interrupt handler. */
-
-static irqreturn_t lance_interrupt( int irq, void *dev_id, struct pt_regs *fp)
-{
- struct net_device *dev = dev_id;
- struct lance_private *lp;
- struct lance_ioreg *IO;
- int csr0, boguscnt = 10;
- int handled = 0;
-
- if (dev == NULL) {
- DPRINTK( 1, ( "lance_interrupt(): interrupt for unknown device.\n" ));
- return IRQ_NONE;
- }
-
- lp = netdev_priv(dev);
- IO = lp->iobase;
- AREG = CSR0;
-
- if (dev->interrupt) {
- DPRINTK( 1, ( "Re-entering CAUSE=%08x STATUS=%08x\n",
- read_32bit_cp0_register(CP0_CAUSE),
- read_32bit_cp0_register(CP0_STATUS) ));
- panic("lance: interrupt handler reentered !");
- }
-
- dev->interrupt = 1;
-
- while( ((csr0 = DREG) & (CSR0_ERR | CSR0_TINT | CSR0_RINT)) &&
- --boguscnt >= 0) {
- handled = 1;
- /* Acknowledge all of the current interrupt sources ASAP. */
- DREG = csr0 & ~(CSR0_INIT | CSR0_STRT | CSR0_STOP |
- CSR0_TDMD | CSR0_INEA);
-
- DPRINTK( 2, ( "%s: interrupt csr0=%04x new csr=%04x.\n",
- dev->name, csr0, DREG ));
-
- if (csr0 & CSR0_RINT) /* Rx interrupt */
- lance_rx( dev );
-
- if (csr0 & CSR0_TINT) { /* Tx-done interrupt */
- int dirty_tx = lp->dirty_tx;
-
- while( dirty_tx < lp->cur_tx) {
- int entry = dirty_tx & TX_RING_MOD_MASK;
-#ifdef NORMAL_MEM_ACCESS
- int status = MEM->tx_head[entry].flag;
-#else
- int status = GET_FLAG(&MEM->tx_head[entry]);
-#endif
- if (status & TMD1_OWN_CHIP)
- break; /* It still hasn't been Txed */
-
-#ifdef NORMAL_MEM_ACCESS
- MEM->tx_head[entry].flag = 0;
-#else
- SET_FLAG(&MEM->tx_head[entry],0);
-#endif
-
- if (status & TMD1_ERR) {
- /* There was an major error, log it. */
- int err_status = MEM->tx_head[entry].misc;
- lp->stats.tx_errors++;
- if (err_status & TMD3_RTRY) lp->stats.tx_aborted_errors++;
- if (err_status & TMD3_LCAR) lp->stats.tx_carrier_errors++;
- if (err_status & TMD3_LCOL) lp->stats.tx_window_errors++;
- if (err_status & TMD3_UFLO) {
- /* Ackk! On FIFO errors the Tx unit is turned off! */
- lp->stats.tx_fifo_errors++;
- /* Remove this verbosity later! */
- DPRINTK( 1, ( "%s: Tx FIFO error! Status %04x\n",
- dev->name, csr0 ));
- /* Restart the chip. */
- DREG = CSR0_STRT;
- }
- } else {
- if (status & (TMD1_MORE | TMD1_ONE | TMD1_DEF))
- lp->stats.collisions++;
- lp->stats.tx_packets++;
- }
- dirty_tx++;
- }
-
-#ifndef final_version
- if (lp->cur_tx - dirty_tx >= TX_RING_SIZE) {
- DPRINTK( 0, ( "out-of-sync dirty pointer,"
- " %d vs. %d, full=%d.\n",
- dirty_tx, lp->cur_tx, lp->tx_full ));
- dirty_tx += TX_RING_SIZE;
- }
-#endif
-
- if (lp->tx_full && dev->tbusy
- && dirty_tx > lp->cur_tx - TX_RING_SIZE + 2) {
- /* The ring is no longer full, clear tbusy. */
- lp->tx_full = 0;
- dev->tbusy = 0;
- mark_bh( NET_BH );
- }
-
- lp->dirty_tx = dirty_tx;
- }
-
- /* Log misc errors. */
- if (csr0 & CSR0_BABL) lp->stats.tx_errors++; /* Tx babble. */
- if (csr0 & CSR0_MISS) lp->stats.rx_errors++; /* Missed a Rx frame. */
- if (csr0 & CSR0_MERR) {
- DPRINTK( 1, ( "%s: Bus master arbitration failure (?!?), "
- "status %04x.\n", dev->name, csr0 ));
- /* Restart the chip. */
- DREG = CSR0_STRT;
- }
- }
-
- /* Clear any other interrupt, and set interrupt enable. */
- DREG = CSR0_BABL | CSR0_CERR | CSR0_MISS | CSR0_MERR |
- CSR0_IDON | CSR0_INEA;
-
- DPRINTK( 2, ( "%s: exiting interrupt, csr0=%#04x.\n",
- dev->name, DREG ));
- dev->interrupt = 0;
- return IRQ_RETVAL(handled);
-}
-
-
-static int lance_rx( struct net_device *dev )
-
-{ struct lance_private *lp = netdev_priv(dev);
- int entry = lp->cur_rx & RX_RING_MOD_MASK;
- int i;
-
-#ifdef NORMAL_MEM_ACCESS
- DPRINTK( 2, ( "%s: rx int, flag=%04x\n", dev->name,
- MEM->rx_head[entry].flag ));
-#else
- DPRINTK( 2, ( "%s: rx int, flag=%04x\n", dev->name,
- GET_FLAG(&MEM->rx_head[entry]) ));
-#endif
-
- /* If we own the next entry, it's a new packet. Send it up. */
-#ifdef NORMAL_MEM_ACCESS
- while( (MEM->rx_head[entry].flag & RMD1_OWN) == RMD1_OWN_HOST ) {
-#else
- while( (GET_FLAG(&MEM->rx_head[entry]) & RMD1_OWN) == RMD1_OWN_HOST ) {
-#endif
- struct lance_rx_head *head = &(MEM->rx_head[entry]);
-#ifdef NORMAL_MEM_ACCESS
- int status = head->flag;
-#else
- int status = GET_FLAG(head);
-#endif
-
- if (status != (RMD1_ENP|RMD1_STP)) { /* There was an error. */
- /* There is a tricky error noted by John Murphy,
- <murf@perftech.com> to Russ Nelson: Even with full-sized
- buffers it's possible for a jabber packet to use two
- buffers, with only the last correctly noting the error. */
- if (status & RMD1_ENP) /* Only count a general error at the */
- lp->stats.rx_errors++; /* end of a packet.*/
- if (status & RMD1_FRAM) lp->stats.rx_frame_errors++;
- if (status & RMD1_OFLO) lp->stats.rx_over_errors++;
- if (status & RMD1_CRC) lp->stats.rx_crc_errors++;
- if (status & RMD1_BUFF) lp->stats.rx_fifo_errors++;
-#ifdef NORMAL_MEM_ACCESS
- head->flag &= (RMD1_ENP|RMD1_STP);
-#else
- SET_FLAG(head,GET_FLAG(head) & (RMD1_ENP|RMD1_STP));
-#endif
- } else {
- /* Malloc up new buffer, compatible with net-3. */
- short pkt_len = head->msg_length & 0xfff;
- struct sk_buff *skb;
-
- if (pkt_len < 60) {
- printk( "%s: Runt packet!\n", dev->name );
- lp->stats.rx_errors++;
- }
- else {
- skb = dev_alloc_skb( pkt_len+2 );
- if (skb == NULL) {
- DPRINTK( 1, ( "%s: Memory squeeze, deferring packet.\n",
- dev->name ));
- for( i = 0; i < RX_RING_SIZE; i++ )
-#ifdef NORMAL_MEM_ACCESS
- if (MEM->rx_head[(entry+i) & RX_RING_MOD_MASK].flag &
-#else
- if (GET_FLAG(&MEM->rx_head[(entry+i) & \
- RX_RING_MOD_MASK]) &
-#endif
- RMD1_OWN_CHIP)
- break;
-
- if (i > RX_RING_SIZE - 2) {
- lp->stats.rx_dropped++;
-#ifdef NORMAL_MEM_ACCESS
- head->flag |= RMD1_OWN_CHIP;
-#else
- SET_FLAG(head,GET_FLAG(head) | RMD1_OWN_CHIP);
-#endif
- lp->cur_rx++;
- }
- break;
- }
-
- if (lance_debug >= 3) {
- u_char *data = PKTBUF_ADDR(head), *p;
- printk( "%s: RX pkt type 0x%04x from ", dev->name,
- ((u_short *)data)[6]);
- for( p = &data[6], i = 0; i < 6; i++ )
- printk("%02x%s", *p++, i != 5 ? ":" : "" );
- printk(" to ");
- for( p = data, i = 0; i < 6; i++ )
- printk("%02x%s", *p++, i != 5 ? ":" : "" );
- printk(" data %02x %02x %02x %02x %02x %02x %02x %02x "
- "len %d\n",
- data[15], data[16], data[17], data[18],
- data[19], data[20], data[21], data[22],
- pkt_len );
- }
-
- skb->dev = dev;
- skb_reserve( skb, 2 ); /* 16 byte align */
- skb_put( skb, pkt_len ); /* Make room */
- lp->memcpy_f( skb->data, PKTBUF_ADDR(head), pkt_len );
- skb->protocol = eth_type_trans( skb, dev );
- netif_rx( skb );
- dev->last_rx = jiffies;
- lp->stats.rx_packets++;
- lp->stats.rx_bytes += pkt_len;
- }
- }
-
-#ifdef NORMAL_MEM_ACCESS
- head->flag |= RMD1_OWN_CHIP;
-#else
- SET_FLAG(head,GET_FLAG(head) | RMD1_OWN_CHIP);
-#endif
- entry = (++lp->cur_rx) & RX_RING_MOD_MASK;
- }
- lp->cur_rx &= RX_RING_MOD_MASK;
-
- /* From lance.c (Donald Becker): */
- /* We should check that at least two ring entries are free. If not,
- we should free one and mark stats->rx_dropped++. */
-
- return 0;
-}
-
-
-static int lance_close( struct net_device *dev )
-
-{ struct lance_private *lp = netdev_priv(dev);
- struct lance_ioreg *IO = lp->iobase;
-
- dev->start = 0;
- dev->tbusy = 1;
-
- AREG = CSR0;
-
- DPRINTK( 2, ( "%s: Shutting down ethercard, status was %2.2x.\n",
- dev->name, DREG ));
-
- /* We stop the LANCE here -- it occasionally polls
- memory if we don't. */
- DREG = CSR0_STOP;
-
- return 0;
-}
-
-
-static struct net_device_stats *lance_get_stats( struct net_device *dev )
-
-{
- struct lance_private *lp = netdev_priv(dev);
- return &lp->stats;
-}
-
-
-/* Set or clear the multicast filter for this adaptor.
- num_addrs == -1 Promiscuous mode, receive all packets
- num_addrs == 0 Normal mode, clear multicast list
- num_addrs > 0 Multicast mode, receive normal and MC packets, and do
- best-effort filtering.
- */
-
-static void set_multicast_list( struct net_device *dev )
-
-{ struct lance_private *lp = netdev_priv(dev);
- struct lance_ioreg *IO = lp->iobase;
-
- if (!dev->start)
- /* Only possible if board is already started */
- return;
-
- /* We take the simple way out and always enable promiscuous mode. */
- DREG = CSR0_STOP; /* Temporarily stop the lance. */
-
- if (dev->flags & IFF_PROMISC) {
- /* Log any net taps. */
- DPRINTK( 1, ( "%s: Promiscuous mode enabled.\n", dev->name ));
- REGA( CSR15 ) = 0x8000; /* Set promiscuous mode */
- } else {
- short multicast_table[4];
- int num_addrs = dev->mc_count;
- int i;
- /* We don't use the multicast table, but rely on upper-layer
- * filtering. */
- memset( multicast_table, (num_addrs == 0) ? 0 : -1,
- sizeof(multicast_table) );
- for( i = 0; i < 4; i++ )
- REGA( CSR8+i ) = multicast_table[i];
- REGA( CSR15 ) = 0; /* Unset promiscuous mode */
- }
-
- /*
- * Always set BSWP after a STOP as STOP puts it back into
- * little endian mode.
- */
- REGA( CSR3 ) = CSR3_BSWP | (lp->cardtype == PAM_CARD ? CSR3_ACON : 0);
-
- /* Resume normal operation and reset AREG to CSR0 */
- REGA( CSR0 ) = CSR0_IDON | CSR0_INEA | CSR0_STRT;
-}
-
-
-/* This is needed for old RieblCards and possible for new RieblCards */
-
-static int lance_set_mac_address( struct net_device *dev, void *addr )
-
-{ struct lance_private *lp = netdev_priv(dev);
- struct sockaddr *saddr = addr;
- int i;
-
- if (lp->cardtype != OLD_RIEBL && lp->cardtype != NEW_RIEBL)
- return( -EOPNOTSUPP );
-
- if (dev->start) {
- /* Only possible while card isn't started */
- DPRINTK( 1, ( "%s: hwaddr can be set only while card isn't open.\n",
- dev->name ));
- return( -EIO );
- }
-
- slow_memcpy( dev->dev_addr, saddr->sa_data, dev->addr_len );
-
- {
- unsigned char hwaddr[6];
- for( i = 0; i < 6; i++ )
- hwaddr[i] = dev->dev_addr[i^1]; /* <- 16 bit swap! */
- slow_memcpy(MEM->init.hwaddr, hwaddr, sizeof(hwaddr));
- }
-
- lp->memcpy_f( RIEBL_HWADDR_ADDR, dev->dev_addr, 6 );
- /* set also the magic for future sessions */
-#ifdef NORMAL_MEM_ACCESS
- *RIEBL_MAGIC_ADDR = RIEBL_MAGIC;
-#else
- {
- unsigned long magic = RIEBL_MAGIC;
- slow_memcpy(RIEBL_MAGIC_ADDR, &magic, sizeof(*RIEBL_MAGIC_ADDR));
- }
-#endif
- return( 0 );
-}
-
-
-#ifdef MODULE
-static struct net_device *bagetlance_dev;
-
-int init_module(void)
-{
- bagetlance_dev = bagetlance_probe(-1);
- if (IS_ERR(bagetlance_dev))
- return PTR_ERR(bagetlance_dev);
- return 0;
-}
-
-void cleanup_module(void)
-{
- unregister_netdev(bagetlance_dev);
- free_irq(bagetlance_dev->irq, bagetlance_dev);
- free_netdev(bagetlance_dev);
-}
-
-#endif /* MODULE */
-
-/*
- * Local variables:
- * c-indent-level: 4
- * tab-width: 4
- * End:
- */
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
index 27e0d8e098dec..6233c4ffb8051 100644
--- a/drivers/net/bonding/bond_3ad.c
+++ b/drivers/net/bonding/bond_3ad.c
@@ -2175,7 +2175,7 @@ out:
* received frames (loopback). Since only the payload is given to this
* function, it check for loopback.
*/
-void bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave, u16 length)
+static void bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave, u16 length)
{
struct port *port;
diff --git a/drivers/net/bonding/bond_3ad.h b/drivers/net/bonding/bond_3ad.h
index 4119f0feba101..f46823894187f 100644
--- a/drivers/net/bonding/bond_3ad.h
+++ b/drivers/net/bonding/bond_3ad.h
@@ -290,7 +290,6 @@ void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution, int lacp_fas
int bond_3ad_bind_slave(struct slave *slave);
void bond_3ad_unbind_slave(struct slave *slave);
void bond_3ad_state_machine_handler(struct bonding *bond);
-void bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave, u16 length);
void bond_3ad_adapter_speed_changed(struct slave *slave);
void bond_3ad_adapter_duplex_changed(struct slave *slave);
void bond_3ad_handle_link_change(struct slave *slave, char link);
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index a76519afa036c..5ce606d9dc03f 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -54,6 +54,7 @@
#include <linux/if_ether.h>
#include <linux/if_bonding.h>
#include <linux/if_vlan.h>
+#include <linux/in.h>
#include <net/ipx.h>
#include <net/arp.h>
#include <asm/byteorder.h>
@@ -275,7 +276,7 @@ static struct slave *tlb_get_least_loaded_slave(struct bonding *bond)
}
/* Caller must hold bond lock for read */
-struct slave *tlb_choose_channel(struct bonding *bond, u32 hash_index, u32 skb_len)
+static struct slave *tlb_choose_channel(struct bonding *bond, u32 hash_index, u32 skb_len)
{
struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
struct tlb_client_info *hash_table;
@@ -627,7 +628,7 @@ static void rlb_req_update_subnet_clients(struct bonding *bond, u32 src_ip)
}
/* Caller must hold both bond and ptr locks for read */
-struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bond)
+static struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bond)
{
struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
struct arp_pkt *arp = (struct arp_pkt *)skb->nh.raw;
@@ -954,9 +955,9 @@ static int alb_set_slave_mac_addr(struct slave *slave, u8 addr[], int hw)
/* each slave will receive packets destined to a different mac */
memcpy(s_addr.sa_data, addr, dev->addr_len);
s_addr.sa_family = dev->type;
- if (dev->set_mac_address(dev, &s_addr)) {
+ if (dev_set_mac_address(dev, &s_addr)) {
printk(KERN_ERR DRV_NAME
- ": Error: dev->set_mac_address of dev %s failed! ALB "
+ ": 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",
@@ -1209,7 +1210,7 @@ static int alb_set_mac_address(struct bonding *bond, void *addr)
/* save net_device's current hw address */
memcpy(tmp_addr, slave->dev->dev_addr, ETH_ALEN);
- res = slave->dev->set_mac_address(slave->dev, addr);
+ res = dev_set_mac_address(slave->dev, addr);
/* restore net_device's hw address */
memcpy(slave->dev->dev_addr, tmp_addr, ETH_ALEN);
@@ -1229,7 +1230,7 @@ unwind:
stop_at = slave;
bond_for_each_slave_from_to(bond, slave, i, bond->first_slave, stop_at) {
memcpy(tmp_addr, slave->dev->dev_addr, ETH_ALEN);
- slave->dev->set_mac_address(slave->dev, &sa);
+ dev_set_mac_address(slave->dev, &sa);
memcpy(slave->dev->dev_addr, tmp_addr, ETH_ALEN);
}
@@ -1300,7 +1301,8 @@ int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev)
switch (ntohs(skb->protocol)) {
case ETH_P_IP:
if ((memcmp(eth_data->h_dest, mac_bcast, ETH_ALEN) == 0) ||
- (skb->nh.iph->daddr == ip_bcast)) {
+ (skb->nh.iph->daddr == ip_bcast) ||
+ (skb->nh.iph->protocol == IPPROTO_IGMP)) {
do_tx_balance = 0;
break;
}
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 2a4b7cb97523d..96a870866ace7 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1719,7 +1719,7 @@ static int bond_enslave(struct net_device *bond_dev, struct net_device *slave_de
*/
memcpy(addr.sa_data, bond_dev->dev_addr, bond_dev->addr_len);
addr.sa_family = slave_dev->type;
- res = slave_dev->set_mac_address(slave_dev, &addr);
+ res = dev_set_mac_address(slave_dev, &addr);
if (res) {
dprintk("Error %d calling set_mac_address\n", res);
goto err_free;
@@ -1849,8 +1849,8 @@ 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/duplex from %s, speed "
- "forced to 100Mbps, duplex forced to Full.\n",
+ ": Warning: failed to get speed and duplex from %s, "
+ "assumed to be 100Mb/sec and Full.\n",
new_slave->dev->name);
if (bond->params.mode == BOND_MODE_8023AD) {
@@ -1991,7 +1991,7 @@ err_close:
err_restore_mac:
memcpy(addr.sa_data, new_slave->perm_hwaddr, ETH_ALEN);
addr.sa_family = slave_dev->type;
- slave_dev->set_mac_address(slave_dev, &addr);
+ dev_set_mac_address(slave_dev, &addr);
err_free:
kfree(new_slave);
@@ -2171,7 +2171,7 @@ static int bond_release(struct net_device *bond_dev, struct net_device *slave_de
/* restore original ("permanent") mac address */
memcpy(addr.sa_data, slave->perm_hwaddr, ETH_ALEN);
addr.sa_family = slave_dev->type;
- slave_dev->set_mac_address(slave_dev, &addr);
+ dev_set_mac_address(slave_dev, &addr);
}
/* restore the original state of the
@@ -2262,7 +2262,7 @@ static int bond_release_all(struct net_device *bond_dev)
/* restore original ("permanent") mac address*/
memcpy(addr.sa_data, slave->perm_hwaddr, ETH_ALEN);
addr.sa_family = slave_dev->type;
- slave_dev->set_mac_address(slave_dev, &addr);
+ dev_set_mac_address(slave_dev, &addr);
}
/* restore the original state of the IFF_NOARP flag that might have
@@ -3898,12 +3898,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);
- if (slave->dev->change_mtu) {
- res = slave->dev->change_mtu(slave->dev, new_mtu);
- } else {
- slave->dev->mtu = new_mtu;
- res = 0;
- }
+ res = dev_set_mtu(slave->dev, new_mtu);
if (res) {
/* If we failed to set the slave's mtu to the new value
@@ -3929,14 +3924,10 @@ unwind:
bond_for_each_slave_from_to(bond, slave, i, bond->first_slave, stop_at) {
int tmp_res;
- if (slave->dev->change_mtu) {
- tmp_res = slave->dev->change_mtu(slave->dev, bond_dev->mtu);
- if (tmp_res) {
- dprintk("unwind err %d dev %s\n", tmp_res,
- slave->dev->name);
- }
- } else {
- slave->dev->mtu = bond_dev->mtu;
+ tmp_res = dev_set_mtu(slave->dev, bond_dev->mtu);
+ if (tmp_res) {
+ dprintk("unwind err %d dev %s\n", tmp_res,
+ slave->dev->name);
}
}
@@ -3988,7 +3979,7 @@ static int bond_set_mac_address(struct net_device *bond_dev, void *addr)
goto unwind;
}
- res = slave->dev->set_mac_address(slave->dev, addr);
+ res = dev_set_mac_address(slave->dev, addr);
if (res) {
/* TODO: consider downing the slave
* and retry ?
@@ -4014,7 +4005,7 @@ unwind:
bond_for_each_slave_from_to(bond, slave, i, bond->first_slave, stop_at) {
int tmp_res;
- tmp_res = slave->dev->set_mac_address(slave->dev, &tmp_sa);
+ tmp_res = dev_set_mac_address(slave->dev, &tmp_sa);
if (tmp_res) {
dprintk("unwind err %d dev %s\n", tmp_res,
slave->dev->name);
@@ -4306,6 +4297,10 @@ static int __init bond_init(struct net_device *bond_dev, struct bond_params *par
*/
bond_dev->features |= NETIF_F_VLAN_CHALLENGED;
+ /* don't acquire bond device's xmit_lock when
+ * transmitting */
+ bond_dev->features |= NETIF_F_LLTX;
+
/* By default, we declare the bond to be fully
* VLAN hardware accelerated capable. Special
* care is taken in the various xmit functions
diff --git a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c
index 8171b10926eb7..5c5f540da26a2 100644
--- a/drivers/net/cs89x0.c
+++ b/drivers/net/cs89x0.c
@@ -136,6 +136,7 @@
#include <linux/string.h>
#include <linux/init.h>
#include <linux/bitops.h>
+#include <linux/delay.h>
#include <asm/system.h>
#include <asm/io.h>
@@ -909,8 +910,7 @@ void __init reset_chip(struct net_device *dev)
writereg(dev, PP_SelfCTL, readreg(dev, PP_SelfCTL) | POWER_ON_RESET);
/* wait 30 ms */
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(30*HZ/1000);
+ msleep(30);
#ifndef CONFIG_ARCH_IXDP2X01
if (lp->chip_type != CS8900) {
diff --git a/drivers/net/defxx.c b/drivers/net/defxx.c
index 4dce49305ba06..a6aa56598f271 100644
--- a/drivers/net/defxx.c
+++ b/drivers/net/defxx.c
@@ -420,7 +420,7 @@ static int __devinit dfx_init_one_pci_or_eisa(struct pci_dev *pdev, long ioaddr)
}
if (pdev != NULL)
- print_name = pdev->slot_name;
+ print_name = pci_name(pdev);
dev = alloc_fddidev(sizeof(*bp));
if (!dev) {
diff --git a/drivers/net/depca.c b/drivers/net/depca.c
index ec6d9d096163f..c4aa5fe2840e7 100644
--- a/drivers/net/depca.c
+++ b/drivers/net/depca.c
@@ -342,14 +342,15 @@ static char depca_string[] = "depca";
static int depca_device_remove (struct device *device);
#ifdef CONFIG_EISA
-struct eisa_device_id depca_eisa_ids[] = {
+static struct eisa_device_id depca_eisa_ids[] = {
{ "DEC4220", de422 },
{ "" }
};
+MODULE_DEVICE_TABLE(eisa, depca_eisa_ids);
static int depca_eisa_probe (struct device *device);
-struct eisa_driver depca_eisa_driver = {
+static struct eisa_driver depca_eisa_driver = {
.id_table = depca_eisa_ids,
.driver = {
.name = depca_string,
@@ -1826,7 +1827,7 @@ static int load_packet(struct net_device *dev, struct sk_buff *skb)
/* set up the buffer descriptors */
len = (skb->len < ETH_ZLEN) ? ETH_ZLEN : skb->len;
- for (i = entry; i != end; i = (++i) & lp->txRingMask) {
+ for (i = entry; i != end; i = (i+1) & lp->txRingMask) {
/* clean out flags */
writel(readl(&lp->tx_ring[i].base) & ~T_FLAGS, &lp->tx_ring[i].base);
writew(0x0000, &lp->tx_ring[i].misc); /* clears other error flags */
diff --git a/drivers/net/dgrs.c b/drivers/net/dgrs.c
index 91d32f77486e1..7809838e6c4c1 100644
--- a/drivers/net/dgrs.c
+++ b/drivers/net/dgrs.c
@@ -454,7 +454,7 @@ do_plx_dma(
* up some state variables to let the host CPU continue doing
* other things until a DMA completion interrupt comes along.
*/
-void
+static void
dgrs_rcv_frame(
struct net_device *dev0,
DGRS_PRIV *priv0,
@@ -1150,7 +1150,7 @@ dgrs_download(struct net_device *dev0)
/*
* Probe (init) a board
*/
-int __init
+static int __init
dgrs_probe1(struct net_device *dev)
{
DGRS_PRIV *priv = (DGRS_PRIV *) dev->priv;
@@ -1228,7 +1228,7 @@ err_out:
return rc;
}
-int __init
+static int __init
dgrs_initclone(struct net_device *dev)
{
DGRS_PRIV *priv = (DGRS_PRIV *) dev->priv;
diff --git a/drivers/net/dl2k.c b/drivers/net/dl2k.c
index 0c6c4ade0e743..aa42b7a277359 100644
--- a/drivers/net/dl2k.c
+++ b/drivers/net/dl2k.c
@@ -1199,7 +1199,7 @@ set_multicast (struct net_device *dev)
static void rio_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
{
struct netdev_private *np = netdev_priv(dev);
- strcpy(info->driver, "DL2K");
+ strcpy(info->driver, "dl2k");
strcpy(info->version, DRV_VERSION);
strcpy(info->bus_info, pci_name(np->pdev));
}
diff --git a/drivers/net/e100.c b/drivers/net/e100.c
index 3acb810a137f9..1b68dd5a49b65 100644
--- a/drivers/net/e100.c
+++ b/drivers/net/e100.c
@@ -2310,7 +2310,7 @@ static void __devexit e100_remove(struct pci_dev *pdev)
}
#ifdef CONFIG_PM
-static int e100_suspend(struct pci_dev *pdev, u32 state)
+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);
@@ -2321,7 +2321,7 @@ static int e100_suspend(struct pci_dev *pdev, u32 state)
netif_device_detach(netdev);
pci_save_state(pdev);
- pci_enable_wake(pdev, state, nic->flags & (wol_magic | e100_asf(nic)));
+ pci_enable_wake(pdev, pci_choose_state(pdev, state), nic->flags & (wol_magic | e100_asf(nic)));
pci_disable_device(pdev);
pci_set_power_state(pdev, pci_choose_state(pdev, state));
diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h
index 77db789604309..148930d4e9bda 100644
--- a/drivers/net/e1000/e1000.h
+++ b/drivers/net/e1000/e1000.h
@@ -138,6 +138,7 @@ struct e1000_adapter;
#define E1000_RX_BUFFER_WRITE 16 /* Must be power of 2 */
#define AUTO_ALL_MODES 0
+#define E1000_EEPROM_82544_APM 0x0004
#define E1000_EEPROM_APME 0x0400
#ifndef E1000_MASTER_SLAVE
@@ -202,6 +203,7 @@ struct e1000_adapter {
spinlock_t stats_lock;
atomic_t irq_sem;
struct work_struct tx_timeout_task;
+ struct work_struct watchdog_task;
uint8_t fc_autoneg;
struct timer_list blink_timer;
@@ -209,6 +211,7 @@ struct e1000_adapter {
/* TX */
struct e1000_desc_ring tx_ring;
+ struct e1000_buffer previous_buffer_info;
spinlock_t tx_lock;
uint32_t txd_cmd;
uint32_t tx_int_delay;
@@ -222,6 +225,7 @@ struct e1000_adapter {
uint32_t tx_fifo_size;
atomic_t tx_fifo_stall;
boolean_t pcix_82544;
+ boolean_t detect_tx_hung;
/* RX */
struct e1000_desc_ring rx_ring;
diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c
index e4061ffc48aaf..0a2ca7c73a412 100644
--- a/drivers/net/e1000/e1000_ethtool.c
+++ b/drivers/net/e1000/e1000_ethtool.c
@@ -1310,7 +1310,7 @@ e1000_run_loopback_test(struct e1000_adapter *adapter)
struct e1000_desc_ring *txdr = &adapter->test_tx_ring;
struct e1000_desc_ring *rxdr = &adapter->test_rx_ring;
struct pci_dev *pdev = adapter->pdev;
- int i;
+ int i, ret_val;
E1000_WRITE_REG(&adapter->hw, RDT, rxdr->count - 1);
@@ -1330,11 +1330,12 @@ e1000_run_loopback_test(struct e1000_adapter *adapter)
rxdr->buffer_info[i].length,
PCI_DMA_FROMDEVICE);
- if (!e1000_check_lbtest_frame(rxdr->buffer_info[i++].skb, 1024))
- return 0;
- } while (i < 64);
+ ret_val = e1000_check_lbtest_frame(rxdr->buffer_info[i].skb,
+ 1024);
+ i++;
+ } while (ret_val != 0 && i < 64);
- return 13;
+ return ret_val;
}
static int
diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c
index f140e2c7eab0e..786a9b935659f 100644
--- a/drivers/net/e1000/e1000_hw.c
+++ b/drivers/net/e1000/e1000_hw.c
@@ -1572,7 +1572,8 @@ e1000_phy_force_speed_duplex(struct e1000_hw *hw)
if(mii_status_reg & MII_SR_LINK_STATUS) break;
msec_delay(100);
}
- if((i == 0) && (hw->phy_type == e1000_phy_m88)) {
+ if((i == 0) &&
+ (hw->phy_type == e1000_phy_m88)) {
/* We didn't get link. Reset the DSP and wait again for link. */
ret_val = e1000_phy_reset_dsp(hw);
if(ret_val) {
@@ -2503,7 +2504,7 @@ e1000_read_phy_reg(struct e1000_hw *hw,
}
}
- ret_val = e1000_read_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT & reg_addr,
+ ret_val = e1000_read_phy_reg_ex(hw, MAX_PHY_REG_ADDRESS & reg_addr,
phy_data);
return ret_val;
@@ -2609,7 +2610,7 @@ e1000_write_phy_reg(struct e1000_hw *hw,
}
}
- ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT & reg_addr,
+ ret_val = e1000_write_phy_reg_ex(hw, MAX_PHY_REG_ADDRESS & reg_addr,
phy_data);
return ret_val;
@@ -2955,8 +2956,7 @@ e1000_phy_m88_get_info(struct e1000_hw *hw,
/* Check polarity status */
ret_val = e1000_check_polarity(hw, &polarity);
if(ret_val)
- return ret_val;
-
+ return ret_val;
phy_info->cable_polarity = polarity;
ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
@@ -2966,9 +2966,9 @@ e1000_phy_m88_get_info(struct e1000_hw *hw,
phy_info->mdix_mode = (phy_data & M88E1000_PSSR_MDIX) >>
M88E1000_PSSR_MDIX_SHIFT;
- if(phy_data & M88E1000_PSSR_1000MBS) {
- /* Cable Length Estimation and Local/Remote Receiver Informatoion
- * are only valid at 1000 Mbps
+ if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS) {
+ /* Cable Length Estimation and Local/Remote Receiver Information
+ * are only valid at 1000 Mbps.
*/
phy_info->cable_length = ((phy_data & M88E1000_PSSR_CABLE_LENGTH) >>
M88E1000_PSSR_CABLE_LENGTH_SHIFT);
@@ -4639,41 +4639,44 @@ e1000_get_bus_info(struct e1000_hw *hw)
{
uint32_t status;
- if(hw->mac_type < e1000_82543) {
+ switch (hw->mac_type) {
+ case e1000_82542_rev2_0:
+ case e1000_82542_rev2_1:
hw->bus_type = e1000_bus_type_unknown;
hw->bus_speed = e1000_bus_speed_unknown;
hw->bus_width = e1000_bus_width_unknown;
- return;
- }
-
- status = E1000_READ_REG(hw, STATUS);
- hw->bus_type = (status & E1000_STATUS_PCIX_MODE) ?
- e1000_bus_type_pcix : e1000_bus_type_pci;
-
- if(hw->device_id == E1000_DEV_ID_82546EB_QUAD_COPPER) {
- hw->bus_speed = (hw->bus_type == e1000_bus_type_pci) ?
- e1000_bus_speed_66 : e1000_bus_speed_120;
- } else if(hw->bus_type == e1000_bus_type_pci) {
- hw->bus_speed = (status & E1000_STATUS_PCI66) ?
- e1000_bus_speed_66 : e1000_bus_speed_33;
- } else {
- switch (status & E1000_STATUS_PCIX_SPEED) {
- case E1000_STATUS_PCIX_SPEED_66:
- hw->bus_speed = e1000_bus_speed_66;
- break;
- case E1000_STATUS_PCIX_SPEED_100:
- hw->bus_speed = e1000_bus_speed_100;
- break;
- case E1000_STATUS_PCIX_SPEED_133:
- hw->bus_speed = e1000_bus_speed_133;
- break;
- default:
- hw->bus_speed = e1000_bus_speed_reserved;
- break;
+ break;
+ default:
+ status = E1000_READ_REG(hw, STATUS);
+ hw->bus_type = (status & E1000_STATUS_PCIX_MODE) ?
+ e1000_bus_type_pcix : e1000_bus_type_pci;
+
+ if(hw->device_id == E1000_DEV_ID_82546EB_QUAD_COPPER) {
+ hw->bus_speed = (hw->bus_type == e1000_bus_type_pci) ?
+ e1000_bus_speed_66 : e1000_bus_speed_120;
+ } else if(hw->bus_type == e1000_bus_type_pci) {
+ hw->bus_speed = (status & E1000_STATUS_PCI66) ?
+ e1000_bus_speed_66 : e1000_bus_speed_33;
+ } else {
+ switch (status & E1000_STATUS_PCIX_SPEED) {
+ case E1000_STATUS_PCIX_SPEED_66:
+ hw->bus_speed = e1000_bus_speed_66;
+ break;
+ case E1000_STATUS_PCIX_SPEED_100:
+ hw->bus_speed = e1000_bus_speed_100;
+ break;
+ case E1000_STATUS_PCIX_SPEED_133:
+ hw->bus_speed = e1000_bus_speed_133;
+ break;
+ default:
+ hw->bus_speed = e1000_bus_speed_reserved;
+ break;
+ }
}
+ hw->bus_width = (status & E1000_STATUS_BUS64) ?
+ e1000_bus_width_64 : e1000_bus_width_32;
+ break;
}
- hw->bus_width = (status & E1000_STATUS_BUS64) ?
- e1000_bus_width_64 : e1000_bus_width_32;
}
/******************************************************************************
* Reads a value from one of the devices registers using port I/O (as opposed
@@ -4738,6 +4741,7 @@ e1000_get_cable_length(struct e1000_hw *hw,
uint16_t agc_value = 0;
uint16_t cur_agc, min_agc = IGP01E1000_AGC_LENGTH_TABLE_SIZE;
uint16_t i, phy_data;
+ uint16_t cable_length;
DEBUGFUNC("e1000_get_cable_length");
@@ -4749,10 +4753,11 @@ e1000_get_cable_length(struct e1000_hw *hw,
&phy_data);
if(ret_val)
return ret_val;
+ cable_length = (phy_data & M88E1000_PSSR_CABLE_LENGTH) >>
+ M88E1000_PSSR_CABLE_LENGTH_SHIFT;
/* Convert the enum value to ranged values */
- switch((phy_data & M88E1000_PSSR_CABLE_LENGTH) >>
- M88E1000_PSSR_CABLE_LENGTH_SHIFT) {
+ switch (cable_length) {
case e1000_cable_length_50:
*min_length = 0;
*max_length = e1000_igp_cable_length_50;
@@ -4919,8 +4924,7 @@ e1000_check_downshift(struct e1000_hw *hw)
return ret_val;
hw->speed_downgraded = (phy_data & IGP01E1000_PLHR_SS_DOWNGRADE) ? 1 : 0;
- }
- else if(hw->phy_type == e1000_phy_m88) {
+ } else if(hw->phy_type == e1000_phy_m88) {
ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS,
&phy_data);
if(ret_val)
diff --git a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h
index 756727eb434ab..f397e637a3c58 100644
--- a/drivers/net/e1000/e1000_hw.h
+++ b/drivers/net/e1000/e1000_hw.h
@@ -369,6 +369,7 @@ int32_t e1000_set_d3_lplu_state(struct e1000_hw *hw, boolean_t active);
#define E1000_DEV_ID_82546GB_SERDES 0x107B
#define E1000_DEV_ID_82546GB_PCIE 0x108A
#define E1000_DEV_ID_82547EI 0x1019
+
#define NODE_ADDRESS_SIZE 6
#define ETH_LENGTH_OF_ADDRESS 6
@@ -1734,6 +1735,9 @@ struct e1000_hw {
#define PHY_1000T_STATUS 0x0A /* 1000Base-T Status Reg */
#define PHY_EXT_STATUS 0x0F /* Extended Status Reg */
+#define MAX_PHY_REG_ADDRESS 0x1F /* 5 bit address bus (0-0x1F) */
+#define MAX_PHY_MULTI_PAGE_REG 0xF /* Registers equal on all pages */
+
/* M88E1000 Specific Registers */
#define M88E1000_PHY_SPEC_CTRL 0x10 /* PHY Specific Control Register */
#define M88E1000_PHY_SPEC_STATUS 0x11 /* PHY Specific Status Register */
@@ -1794,8 +1798,7 @@ struct e1000_hw {
#define IGP01E1000_ANALOG_REGS_PAGE 0x20C0
-#define MAX_PHY_REG_ADDRESS 0x1F /* 5 bit address bus (0-0x1F) */
-#define MAX_PHY_MULTI_PAGE_REG 0xF /*Registers that are equal on all pages*/
+
/* PHY Control Register */
#define MII_CR_SPEED_SELECT_MSB 0x0040 /* bits 6,13: 10=1000, 01=100, 00=10 */
#define MII_CR_COLL_TEST_ENABLE 0x0080 /* Collision test enable */
@@ -2098,7 +2101,11 @@ struct e1000_hw {
#define IGP01E1000_ANALOG_FUSE_FINE_1 0x0080
#define IGP01E1000_ANALOG_FUSE_FINE_10 0x0500
+
/* Bit definitions for valid PHY IDs. */
+/* I = Integrated
+ * E = External
+ */
#define M88E1000_E_PHY_ID 0x01410C50
#define M88E1000_I_PHY_ID 0x01410C30
#define M88E1011_I_PHY_ID 0x01410C20
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index aa5ad41acf245..82549a6fcfb39 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -35,6 +35,14 @@
* - More errlogging support from Jon Mason <jonmason@us.ibm.com>
* - Fix TSO issues on PPC64 machines -- Jon Mason <jonmason@us.ibm.com>
*
+ * 5.7.1 12/16/04
+ * - Resurrect 82547EI/GI related fix in e1000_intr to avoid deadlocks. This
+ * fix was removed as it caused system instability. The suspected cause of
+ * this is the called to e1000_irq_disable in e1000_intr. Inlined the
+ * required piece of e1000_irq_disable into e1000_intr - Anton Blanchard
+ * 5.7.0 12/10/04
+ * - include fix to the condition that determines when to quit NAPI - Robert Olsson
+ * - use netif_poll_{disable/enable} to synchronize between NAPI and i/f up/down
* 5.6.5 11/01/04
* - Enabling NETIF_F_SG without checksum offload is illegal -
John Mason <jdmason@us.ibm.com>
@@ -57,7 +65,8 @@ char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver";
#else
#define DRIVERNAPI "-NAPI"
#endif
-char e1000_driver_version[] = "5.6.10.1-k2"DRIVERNAPI;
+#define DRV_VERSION "5.7.6-k2"DRIVERNAPI
+char e1000_driver_version[] = DRV_VERSION;
char e1000_copyright[] = "Copyright (c) 1999-2004 Intel Corporation.";
/* e1000_pci_tbl - PCI Device ID Table
@@ -81,6 +90,7 @@ static struct pci_device_id e1000_pci_tbl[] = {
INTEL_E1000_ETHERNET_DEVICE(0x1011),
INTEL_E1000_ETHERNET_DEVICE(0x1012),
INTEL_E1000_ETHERNET_DEVICE(0x1013),
+ INTEL_E1000_ETHERNET_DEVICE(0x1014),
INTEL_E1000_ETHERNET_DEVICE(0x1015),
INTEL_E1000_ETHERNET_DEVICE(0x1016),
INTEL_E1000_ETHERNET_DEVICE(0x1017),
@@ -133,6 +143,7 @@ static void e1000_clean_rx_ring(struct e1000_adapter *adapter);
static void e1000_set_multi(struct net_device *netdev);
static void e1000_update_phy_info(unsigned long data);
static void e1000_watchdog(unsigned long data);
+static void e1000_watchdog_task(struct e1000_adapter *adapter);
static void e1000_82547_tx_fifo_stall(unsigned long data);
static int e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev);
static struct net_device_stats * e1000_get_stats(struct net_device *netdev);
@@ -201,6 +212,7 @@ static struct pci_driver e1000_driver = {
MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>");
MODULE_DESCRIPTION("Intel(R) PRO/1000 Network Driver");
MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
static int debug = NETIF_MSG_DRV | NETIF_MSG_PROBE;
module_param(debug, int, 0);
@@ -308,6 +320,9 @@ e1000_up(struct e1000_adapter *adapter)
mod_timer(&adapter->watchdog_timer, jiffies);
e1000_irq_enable(adapter);
+#ifdef CONFIG_E1000_NAPI
+ netif_poll_enable(netdev);
+#endif
return 0;
}
@@ -321,6 +336,10 @@ e1000_down(struct e1000_adapter *adapter)
del_timer_sync(&adapter->tx_fifo_stall_timer);
del_timer_sync(&adapter->watchdog_timer);
del_timer_sync(&adapter->phy_info_timer);
+
+#ifdef CONFIG_E1000_NAPI
+ netif_poll_disable(netdev);
+#endif
adapter->link_speed = 0;
adapter->link_duplex = 0;
netif_carrier_off(netdev);
@@ -414,6 +433,7 @@ e1000_probe(struct pci_dev *pdev,
int i;
int err;
uint16_t eeprom_data;
+ uint16_t eeprom_apme_mask = E1000_EEPROM_APME;
if((err = pci_enable_device(pdev)))
return err;
@@ -510,9 +530,6 @@ e1000_probe(struct pci_dev *pdev,
}
#ifdef NETIF_F_TSO
- /* Disbaled for now until root-cause is found for
- * hangs reported against non-IA archs. TSO can be
- * enabled using ethtool -K eth<x> tso on */
if((adapter->hw.mac_type >= e1000_82544) &&
(adapter->hw.mac_type != e1000_82547))
netdev->features |= NETIF_F_TSO;
@@ -560,6 +577,9 @@ e1000_probe(struct pci_dev *pdev,
adapter->watchdog_timer.function = &e1000_watchdog;
adapter->watchdog_timer.data = (unsigned long) adapter;
+ INIT_WORK(&adapter->watchdog_task,
+ (void (*)(void *))e1000_watchdog_task, adapter);
+
init_timer(&adapter->phy_info_timer);
adapter->phy_info_timer.function = &e1000_update_phy_info;
adapter->phy_info_timer.data = (unsigned long) adapter;
@@ -584,6 +604,11 @@ e1000_probe(struct pci_dev *pdev,
case e1000_82542_rev2_1:
case e1000_82543:
break;
+ case e1000_82544:
+ e1000_read_eeprom(&adapter->hw,
+ EEPROM_INIT_CONTROL2_REG, 1, &eeprom_data);
+ eeprom_apme_mask = E1000_EEPROM_82544_APM;
+ break;
case e1000_82546:
case e1000_82546_rev_3:
if((E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_FUNC_1)
@@ -598,7 +623,7 @@ e1000_probe(struct pci_dev *pdev,
EEPROM_INIT_CONTROL3_PORT_A, 1, &eeprom_data);
break;
}
- if(eeprom_data & E1000_EEPROM_APME)
+ if(eeprom_data & eeprom_apme_mask)
adapter->wol |= E1000_WUFC_MAG;
/* reset the hardware with the new settings */
@@ -641,6 +666,8 @@ e1000_remove(struct pci_dev *pdev)
struct e1000_adapter *adapter = netdev->priv;
uint32_t manc;
+ flush_scheduled_work();
+
if(adapter->hw.mac_type >= e1000_82540 &&
adapter->hw.media_type == e1000_media_type_copper) {
manc = E1000_READ_REG(&adapter->hw, MANC);
@@ -807,6 +834,31 @@ e1000_close(struct net_device *netdev)
}
/**
+ * e1000_check_64k_bound - check that memory doesn't cross 64kB boundary
+ * @adapter: address of board private structure
+ * @begin: address of beginning of memory
+ * @end: address of end of memory
+ **/
+static inline boolean_t
+e1000_check_64k_bound(struct e1000_adapter *adapter,
+ void *start, unsigned long len)
+{
+ unsigned long begin = (unsigned long) start;
+ unsigned long end = begin + len;
+
+ /* first rev 82545 and 82546 need to not allow any memory
+ * write location to cross a 64k boundary due to errata 23 */
+ if (adapter->hw.mac_type == e1000_82545 ||
+ adapter->hw.mac_type == e1000_82546 ) {
+
+ /* check buffer doesn't cross 64kB */
+ return ((begin ^ (end - 1)) >> 16) != 0 ? FALSE : TRUE;
+ }
+
+ return TRUE;
+}
+
+/**
* e1000_setup_tx_resources - allocate Tx resources (Descriptors)
* @adapter: board private structure
*
@@ -824,7 +876,7 @@ e1000_setup_tx_resources(struct e1000_adapter *adapter)
txdr->buffer_info = vmalloc(size);
if(!txdr->buffer_info) {
DPRINTK(PROBE, ERR,
- "Unble to Allocate Memory for the Transmit descriptor ring\n");
+ "Unable to Allocate Memory for the Transmit descriptor ring\n");
return -ENOMEM;
}
memset(txdr->buffer_info, 0, size);
@@ -836,11 +888,42 @@ e1000_setup_tx_resources(struct e1000_adapter *adapter)
txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma);
if(!txdr->desc) {
+setup_tx_desc_die:
DPRINTK(PROBE, ERR,
- "Unble to Allocate Memory for the Transmit descriptor ring\n");
+ "Unable to Allocate Memory for the Transmit descriptor ring\n");
vfree(txdr->buffer_info);
return -ENOMEM;
}
+
+ /* fix for errata 23, cant cross 64kB boundary */
+ if (!e1000_check_64k_bound(adapter, txdr->desc, txdr->size)) {
+ void *olddesc = txdr->desc;
+ dma_addr_t olddma = txdr->dma;
+ DPRINTK(TX_ERR,ERR,"txdr align check failed: %u bytes at %p\n",
+ txdr->size, txdr->desc);
+ /* try again, without freeing the previous */
+ txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma);
+ /* failed allocation, critial failure */
+ if(!txdr->desc) {
+ pci_free_consistent(pdev, txdr->size, olddesc, olddma);
+ goto setup_tx_desc_die;
+ }
+
+ if (!e1000_check_64k_bound(adapter, txdr->desc, txdr->size)) {
+ /* give up */
+ pci_free_consistent(pdev, txdr->size,
+ txdr->desc, txdr->dma);
+ pci_free_consistent(pdev, txdr->size, olddesc, olddma);
+ DPRINTK(PROBE, ERR,
+ "Unable to Allocate aligned Memory for the Transmit"
+ " descriptor ring\n");
+ vfree(txdr->buffer_info);
+ return -ENOMEM;
+ } else {
+ /* free old, move on with the new one since its okay */
+ pci_free_consistent(pdev, txdr->size, olddesc, olddma);
+ }
+ }
memset(txdr->desc, 0, txdr->size);
txdr->next_to_use = 0;
@@ -945,7 +1028,7 @@ e1000_setup_rx_resources(struct e1000_adapter *adapter)
rxdr->buffer_info = vmalloc(size);
if(!rxdr->buffer_info) {
DPRINTK(PROBE, ERR,
- "Unble to Allocate Memory for the Recieve descriptor ring\n");
+ "Unable to Allocate Memory for the Recieve descriptor ring\n");
return -ENOMEM;
}
memset(rxdr->buffer_info, 0, size);
@@ -958,11 +1041,43 @@ e1000_setup_rx_resources(struct e1000_adapter *adapter)
rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma);
if(!rxdr->desc) {
+setup_rx_desc_die:
DPRINTK(PROBE, ERR,
"Unble to Allocate Memory for the Recieve descriptor ring\n");
vfree(rxdr->buffer_info);
return -ENOMEM;
}
+
+ /* fix for errata 23, cant cross 64kB boundary */
+ if (!e1000_check_64k_bound(adapter, rxdr->desc, rxdr->size)) {
+ void *olddesc = rxdr->desc;
+ dma_addr_t olddma = rxdr->dma;
+ DPRINTK(RX_ERR,ERR,
+ "rxdr align check failed: %u bytes at %p\n",
+ rxdr->size, rxdr->desc);
+ /* try again, without freeing the previous */
+ rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma);
+ /* failed allocation, critial failure */
+ if(!rxdr->desc) {
+ pci_free_consistent(pdev, rxdr->size, olddesc, olddma);
+ goto setup_rx_desc_die;
+ }
+
+ if (!e1000_check_64k_bound(adapter, rxdr->desc, rxdr->size)) {
+ /* give up */
+ pci_free_consistent(pdev, rxdr->size,
+ rxdr->desc, rxdr->dma);
+ pci_free_consistent(pdev, rxdr->size, olddesc, olddma);
+ DPRINTK(PROBE, ERR,
+ "Unable to Allocate aligned Memory for the"
+ " Receive descriptor ring\n");
+ vfree(rxdr->buffer_info);
+ return -ENOMEM;
+ } else {
+ /* free old, move on with the new one since its okay */
+ pci_free_consistent(pdev, rxdr->size, olddesc, olddma);
+ }
+ }
memset(rxdr->desc, 0, rxdr->size);
rxdr->next_to_clean = 0;
@@ -1096,6 +1211,7 @@ e1000_unmap_and_free_tx_resource(struct e1000_adapter *adapter,
struct e1000_buffer *buffer_info)
{
struct pci_dev *pdev = adapter->pdev;
+
if(buffer_info->dma) {
pci_unmap_page(pdev,
buffer_info->dma,
@@ -1124,6 +1240,11 @@ e1000_clean_tx_ring(struct e1000_adapter *adapter)
/* Free all the Tx ring sk_buffs */
+ if (likely(adapter->previous_buffer_info.skb != NULL)) {
+ e1000_unmap_and_free_tx_resource(adapter,
+ &adapter->previous_buffer_info);
+ }
+
for(i = 0; i < tx_ring->count; i++) {
buffer_info = &tx_ring->buffer_info[i];
e1000_unmap_and_free_tx_resource(adapter, buffer_info);
@@ -1416,16 +1537,22 @@ e1000_82547_tx_fifo_stall(unsigned long data)
/**
* e1000_watchdog - Timer Call-back
- * @data: pointer to netdev cast into an unsigned long
+ * @data: pointer to adapter cast into an unsigned long
**/
-
static void
e1000_watchdog(unsigned long data)
{
struct e1000_adapter *adapter = (struct e1000_adapter *) data;
+
+ /* Do the rest outside of interrupt context */
+ schedule_work(&adapter->watchdog_task);
+}
+
+static void
+e1000_watchdog_task(struct e1000_adapter *adapter)
+{
struct net_device *netdev = adapter->netdev;
struct e1000_desc_ring *txdr = &adapter->tx_ring;
- unsigned int i;
uint32_t link;
e1000_check_for_link(&adapter->hw);
@@ -1505,12 +1632,8 @@ e1000_watchdog(unsigned long data)
/* Cause software interrupt to ensure rx ring is cleaned */
E1000_WRITE_REG(&adapter->hw, ICS, E1000_ICS_RXDMT0);
- /* Early detection of hung controller */
- i = txdr->next_to_clean;
- if(txdr->buffer_info[i].dma &&
- time_after(jiffies, txdr->buffer_info[i].time_stamp + HZ) &&
- !(E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_TXOFF))
- netif_stop_queue(netdev);
+ /* Force detection of hung controller every watchdog period*/
+ adapter->detect_tx_hung = TRUE;
/* Reset the timer */
mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);
@@ -1522,7 +1645,7 @@ e1000_watchdog(unsigned long data)
#define E1000_TX_FLAGS_VLAN_MASK 0xffff0000
#define E1000_TX_FLAGS_VLAN_SHIFT 16
-static inline boolean_t
+static inline int
e1000_tso(struct e1000_adapter *adapter, struct sk_buff *skb)
{
#ifdef NETIF_F_TSO
@@ -1531,8 +1654,15 @@ e1000_tso(struct e1000_adapter *adapter, struct sk_buff *skb)
uint32_t cmd_length = 0;
uint16_t ipcse, tucse, mss;
uint8_t ipcss, ipcso, tucss, tucso, hdr_len;
+ int err;
if(skb_shinfo(skb)->tso_size) {
+ if (skb_header_cloned(skb)) {
+ err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
+ if (err)
+ return err;
+ }
+
hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2));
mss = skb_shinfo(skb)->tso_size;
skb->nh.iph->tot_len = 0;
@@ -1569,11 +1699,11 @@ e1000_tso(struct e1000_adapter *adapter, struct sk_buff *skb)
if(++i == adapter->tx_ring.count) i = 0;
adapter->tx_ring.next_to_use = i;
- return TRUE;
+ return 1;
}
#endif
- return FALSE;
+ return 0;
}
static inline boolean_t
@@ -1798,6 +1928,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;
unsigned int f;
len -= skb->data_len;
@@ -1869,7 +2000,13 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
first = adapter->tx_ring.next_to_use;
- if(likely(e1000_tso(adapter, skb)))
+ tso = e1000_tso(adapter, skb);
+ if (tso < 0) {
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
+ }
+
+ if (likely(tso))
tx_flags |= E1000_TX_FLAGS_TSO;
else if(likely(e1000_tx_csum(adapter, skb)))
tx_flags |= E1000_TX_FLAGS_CSUM;
@@ -2151,10 +2288,28 @@ e1000_intr(int irq, void *data, struct pt_regs *regs)
__netif_rx_schedule(netdev);
}
#else
+ /* 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){
+ atomic_inc(&adapter->irq_sem);
+ E1000_WRITE_REG(&adapter->hw, IMC, ~0);
+ }
+
for(i = 0; i < E1000_MAX_INTR; i++)
if(unlikely(!e1000_clean_rx_irq(adapter) &
!e1000_clean_tx_irq(adapter)))
break;
+
+ if(hw->mac_type == e1000_82547 || hw->mac_type == e1000_82547_rev_2)
+ e1000_irq_enable(adapter);
#endif
return IRQ_HANDLED;
@@ -2174,24 +2329,21 @@ e1000_clean(struct net_device *netdev, int *budget)
int tx_cleaned;
int work_done = 0;
- if (!netif_carrier_ok(netdev))
- goto quit_polling;
-
tx_cleaned = e1000_clean_tx_irq(adapter);
e1000_clean_rx_irq(adapter, &work_done, work_to_do);
*budget -= work_done;
netdev->quota -= work_done;
- /* if no Rx and Tx cleanup work was done, exit the polling mode */
- if(!tx_cleaned || (work_done < work_to_do) ||
+ /* if no Tx and not enough Rx work done, exit the polling mode */
+ if((!tx_cleaned && (work_done < work_to_do)) ||
!netif_running(netdev)) {
-quit_polling: netif_rx_complete(netdev);
+ netif_rx_complete(netdev);
e1000_irq_enable(adapter);
return 0;
}
- return (work_done >= work_to_do);
+ return 1;
}
#endif
@@ -2215,11 +2367,34 @@ 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)) {
+ /* pre-mature writeback of Tx descriptors */
+ /* clear (free buffers and unmap pci_mapping) */
+ /* previous_buffer_info */
+ if (likely(adapter->previous_buffer_info.skb != NULL)) {
+ e1000_unmap_and_free_tx_resource(adapter,
+ &adapter->previous_buffer_info);
+ }
+
for(cleaned = FALSE; !cleaned; ) {
tx_desc = E1000_TX_DESC(*tx_ring, i);
buffer_info = &tx_ring->buffer_info[i];
+ cleaned = (i == eop);
+
+ /* pre-mature writeback of Tx descriptors */
+ /* save the cleaning of the this for the */
+ /* next iteration */
+ if (cleaned) {
+ memcpy(&adapter->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);
+ }
- e1000_unmap_and_free_tx_resource(adapter, buffer_info);
tx_desc->buffer_addr = 0;
tx_desc->lower.data = 0;
tx_desc->upper.data = 0;
@@ -2241,6 +2416,16 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter)
netif_wake_queue(netdev);
spin_unlock(&adapter->tx_lock);
+
+ if(adapter->detect_tx_hung) {
+ /* 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) &&
+ !(E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_TXOFF))
+ netif_stop_queue(netdev);
+ }
return cleaned;
}
@@ -2407,19 +2592,43 @@ e1000_alloc_rx_buffers(struct e1000_adapter *adapter)
struct e1000_rx_desc *rx_desc;
struct e1000_buffer *buffer_info;
struct sk_buff *skb;
- unsigned int i;
+ unsigned int i, bufsz;
i = rx_ring->next_to_use;
buffer_info = &rx_ring->buffer_info[i];
while(!buffer_info->skb) {
- skb = dev_alloc_skb(adapter->rx_buffer_len + NET_IP_ALIGN);
+ bufsz = adapter->rx_buffer_len + NET_IP_ALIGN;
+ skb = dev_alloc_skb(bufsz);
if(unlikely(!skb)) {
/* Better luck next round */
break;
}
+ /* fix for errata 23, cant cross 64kB boundary */
+ if (!e1000_check_64k_bound(adapter, skb->data, bufsz)) {
+ struct sk_buff *oldskb = skb;
+ DPRINTK(RX_ERR,ERR,
+ "skb align check failed: %u bytes at %p\n",
+ bufsz, skb->data);
+ /* try again, without freeing the previous */
+ skb = dev_alloc_skb(bufsz);
+ if (!skb) {
+ dev_kfree_skb(oldskb);
+ break;
+ }
+ if (!e1000_check_64k_bound(adapter, skb->data, bufsz)) {
+ /* give up */
+ dev_kfree_skb(skb);
+ dev_kfree_skb(oldskb);
+ break; /* while !buffer_info->skb */
+ } else {
+ /* move on with the new one */
+ dev_kfree_skb(oldskb);
+ }
+ }
+
/* Make buffer alignment 2 beyond a 16 byte boundary
* this will result in a 16 byte aligned IP header after
* the 14 byte MAC header is removed
@@ -2435,6 +2644,25 @@ e1000_alloc_rx_buffers(struct e1000_adapter *adapter)
adapter->rx_buffer_len,
PCI_DMA_FROMDEVICE);
+ /* fix for errata 23, cant cross 64kB boundary */
+ if(!e1000_check_64k_bound(adapter,
+ (void *)(unsigned long)buffer_info->dma,
+ adapter->rx_buffer_len)) {
+ DPRINTK(RX_ERR,ERR,
+ "dma align check failed: %u bytes at %ld\n",
+ adapter->rx_buffer_len, (unsigned long)buffer_info->dma);
+
+ dev_kfree_skb(skb);
+ buffer_info->skb = NULL;
+
+ pci_unmap_single(pdev,
+ buffer_info->dma,
+ adapter->rx_buffer_len,
+ PCI_DMA_FROMDEVICE);
+
+ break; /* while !buffer_info->skb */
+ }
+
rx_desc = E1000_RX_DESC(*rx_ring, i);
rx_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c
index ab5146fe5c8a2..98b3a2fdce90d 100644
--- a/drivers/net/eepro100.c
+++ b/drivers/net/eepro100.c
@@ -144,24 +144,14 @@ MODULE_PARM_DESC(full_duplex, "full duplex setting(s) (1)");
MODULE_PARM_DESC(congenb, "Enable congestion control (1)");
MODULE_PARM_DESC(txfifo, "Tx FIFO threshold in 4 byte units, (0-15)");
MODULE_PARM_DESC(rxfifo, "Rx FIFO threshold in 4 byte units, (0-15)");
-MODULE_PARM_DESC(txdmaccount, "Tx DMA burst length; 128 - disable (0-128)");
-MODULE_PARM_DESC(rxdmaccount, "Rx DMA burst length; 128 - disable (0-128)");
+MODULE_PARM_DESC(txdmacount, "Tx DMA burst length; 128 - disable (0-128)");
+MODULE_PARM_DESC(rxdmacount, "Rx DMA burst length; 128 - disable (0-128)");
MODULE_PARM_DESC(rx_copybreak, "copy breakpoint for copy-only-tiny-frames");
MODULE_PARM_DESC(max_interrupt_work, "maximum events handled per interrupt");
MODULE_PARM_DESC(multicast_filter_limit, "maximum number of filtered multicast addresses");
#define RUN_AT(x) (jiffies + (x))
-/* ACPI power states don't universally work (yet) */
-#ifndef CONFIG_PM
-#undef pci_set_power_state
-#define pci_set_power_state null_set_power_state
-static inline int null_set_power_state(struct pci_dev *dev, int state)
-{
- return 0;
-}
-#endif /* CONFIG_PM */
-
#define netdevice_start(dev)
#define netdevice_stop(dev)
#define netif_set_tx_timeout(dev, tf, tm) \
@@ -2281,7 +2271,7 @@ static void set_rx_mode(struct net_device *dev)
}
#ifdef CONFIG_PM
-static int eepro100_suspend(struct pci_dev *pdev, u32 state)
+static int eepro100_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct net_device *dev = pci_get_drvdata (pdev);
struct speedo_private *sp = netdev_priv(dev);
@@ -2299,7 +2289,7 @@ static int eepro100_suspend(struct pci_dev *pdev, u32 state)
/* XXX call pci_set_power_state ()? */
pci_disable_device(pdev);
- pci_set_power_state (pdev, 3);
+ pci_set_power_state (pdev, PCI_D3hot);
return 0;
}
@@ -2309,7 +2299,7 @@ static int eepro100_resume(struct pci_dev *pdev)
struct speedo_private *sp = netdev_priv(dev);
void __iomem *ioaddr = sp->regs;
- pci_set_power_state(pdev, 0);
+ pci_set_power_state(pdev, PCI_D0);
pci_restore_state(pdev);
pci_enable_device(pdev);
pci_set_master(pdev);
@@ -2355,12 +2345,8 @@ static void __devexit eepro100_remove_one (struct pci_dev *pdev)
}
static struct pci_device_id eepro100_pci_tbl[] = {
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82557,
- PCI_ANY_ID, PCI_ANY_ID, },
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82559ER,
- PCI_ANY_ID, PCI_ANY_ID, },
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_7,
- PCI_ANY_ID, PCI_ANY_ID, },
+ { PCI_VENDOR_ID_INTEL, 0x1229, PCI_ANY_ID, PCI_ANY_ID, },
+ { PCI_VENDOR_ID_INTEL, 0x1209, PCI_ANY_ID, PCI_ANY_ID, },
{ PCI_VENDOR_ID_INTEL, 0x1029, PCI_ANY_ID, PCI_ANY_ID, },
{ PCI_VENDOR_ID_INTEL, 0x1030, PCI_ANY_ID, PCI_ANY_ID, },
{ PCI_VENDOR_ID_INTEL, 0x1031, PCI_ANY_ID, PCI_ANY_ID, },
@@ -2380,7 +2366,6 @@ static struct pci_device_id eepro100_pci_tbl[] = {
{ PCI_VENDOR_ID_INTEL, 0x1050, PCI_ANY_ID, PCI_ANY_ID, },
{ PCI_VENDOR_ID_INTEL, 0x1059, PCI_ANY_ID, PCI_ANY_ID, },
{ PCI_VENDOR_ID_INTEL, 0x1227, PCI_ANY_ID, PCI_ANY_ID, },
- { PCI_VENDOR_ID_INTEL, 0x1228, PCI_ANY_ID, PCI_ANY_ID, },
{ PCI_VENDOR_ID_INTEL, 0x2449, PCI_ANY_ID, PCI_ANY_ID, },
{ PCI_VENDOR_ID_INTEL, 0x2459, PCI_ANY_ID, PCI_ANY_ID, },
{ PCI_VENDOR_ID_INTEL, 0x245D, PCI_ANY_ID, PCI_ANY_ID, },
diff --git a/drivers/net/eexpress.c b/drivers/net/eexpress.c
index 335fde87fce7b..fc8e7947b3346 100644
--- a/drivers/net/eexpress.c
+++ b/drivers/net/eexpress.c
@@ -7,7 +7,7 @@
* Support for 8-bit mode by Zoltan Szilagyi <zoltans@cs.arizona.edu>
*
* Many modifications, and currently maintained, by
- * Philip Blundell <Philip.Blundell@pobox.com>
+ * Philip Blundell <philb@gnu.org>
* Added the Compaq LTE Alan Cox <alan@redhat.com>
* Added MCA support Adam Fritzler <mid@auk.cx>
*
diff --git a/drivers/net/epic100.c b/drivers/net/epic100.c
index b283f1a7ce562..81ebaedaa2408 100644
--- a/drivers/net/epic100.c
+++ b/drivers/net/epic100.c
@@ -1624,7 +1624,7 @@ static void __devexit epic_remove_one (struct pci_dev *pdev)
#ifdef CONFIG_PM
-static int epic_suspend (struct pci_dev *pdev, u32 state)
+static int epic_suspend (struct pci_dev *pdev, pm_message_t state)
{
struct net_device *dev = pci_get_drvdata(pdev);
long ioaddr = dev->base_addr;
diff --git a/drivers/net/eql.c b/drivers/net/eql.c
index fd66d2722adac..dd68658203725 100644
--- a/drivers/net/eql.c
+++ b/drivers/net/eql.c
@@ -499,8 +499,6 @@ static int eql_g_slave_cfg(struct net_device *dev, slave_config_t __user *scp)
return -ENODEV;
ret = -EINVAL;
- if (!slave_dev)
- return ret;
spin_lock_bh(&eql->queue.lock);
if (eql_is_slave(slave_dev)) {
@@ -536,8 +534,6 @@ static int eql_s_slave_cfg(struct net_device *dev, slave_config_t __user *scp)
return -ENODEV;
ret = -EINVAL;
- if (!slave_dev)
- return ret;
eql = netdev_priv(dev);
spin_lock_bh(&eql->queue.lock);
diff --git a/drivers/net/es3210.c b/drivers/net/es3210.c
index 96866a42c00de..f1e8150ed2a09 100644
--- a/drivers/net/es3210.c
+++ b/drivers/net/es3210.c
@@ -159,6 +159,7 @@ 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
@@ -271,9 +272,14 @@ static int __init es_probe1(struct net_device *dev, int ioaddr)
printk(" assigning ");
}
- dev->mem_end = ei_status.rmem_end = dev->mem_start
- + (ES_STOP_PG - ES_START_PG)*256;
- ei_status.rmem_start = dev->mem_start + TX_PAGES*256;
+ ei_status.mem = ioremap(dev->mem_start, (ES_STOP_PG - ES_START_PG)*256);
+ if (!ei_status.mem) {
+ printk("ioremap failed - giving up\n");
+ retval = -ENXIO;
+ goto out1;
+ }
+
+ dev->mem_end = dev->mem_start + (ES_STOP_PG - ES_START_PG)*256;
printk("mem %#lx-%#lx\n", dev->mem_start, dev->mem_end-1);
@@ -353,8 +359,8 @@ static void es_reset_8390(struct net_device *dev)
static void
es_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
{
- unsigned long hdr_start = dev->mem_start + ((ring_page - ES_START_PG)<<8);
- isa_memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
+ void __iomem *hdr_start = ei_status.mem + ((ring_page - ES_START_PG)<<8);
+ memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
hdr->count = (hdr->count + 3) & ~3; /* Round up allocation. */
}
@@ -367,27 +373,27 @@ es_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page
static void es_block_input(struct net_device *dev, int count, struct sk_buff *skb,
int ring_offset)
{
- unsigned long xfer_start = dev->mem_start + ring_offset - (ES_START_PG<<8);
+ void __iomem *xfer_start = ei_status.mem + ring_offset - ES_START_PG*256;
- if (xfer_start + count > ei_status.rmem_end) {
+ if (ring_offset + count > ES_STOP_PG*256) {
/* Packet wraps over end of ring buffer. */
- int semi_count = ei_status.rmem_end - xfer_start;
- isa_memcpy_fromio(skb->data, xfer_start, semi_count);
+ int semi_count = ES_STOP_PG*256 - ring_offset;
+ memcpy_fromio(skb->data, xfer_start, semi_count);
count -= semi_count;
- isa_memcpy_fromio(skb->data + semi_count, ei_status.rmem_start, count);
+ memcpy_fromio(skb->data + semi_count, ei_status.mem, count);
} else {
/* Packet is in one chunk. */
- isa_eth_io_copy_and_sum(skb, xfer_start, count, 0);
+ eth_io_copy_and_sum(skb, xfer_start, count, 0);
}
}
static void es_block_output(struct net_device *dev, int count,
const unsigned char *buf, int start_page)
{
- unsigned long shmem = dev->mem_start + ((start_page - ES_START_PG)<<8);
+ void __iomem *shmem = ei_status.mem + ((start_page - ES_START_PG)<<8);
count = (count + 3) & ~3; /* Round up to doubleword */
- isa_memcpy_toio(shmem, buf, count);
+ memcpy_toio(shmem, buf, count);
}
static int es_open(struct net_device *dev)
diff --git a/drivers/net/ethertap.c b/drivers/net/ethertap.c
deleted file mode 100644
index 24f237b22a753..0000000000000
--- a/drivers/net/ethertap.c
+++ /dev/null
@@ -1,390 +0,0 @@
-/*
- * Ethertap: A network device for bouncing packets via user space
- *
- * This is a very simple ethernet driver. It bounces ethernet frames
- * to user space on /dev/tap0->/dev/tap15 and expects ethernet frames
- * to be written back to it. By default it does not ARP. If you turn ARP
- * on it will attempt to ARP the user space and reply to ARPS from the
- * user space.
- *
- * As this is an ethernet device you can use it for appletalk, IPX etc
- * even for building bridging tunnels.
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/kernel.h>
-#include <linux/jiffies.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-
-#include <linux/netdevice.h>
-#include <linux/inetdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/init.h>
-
-#include <net/sock.h>
-#include <linux/netlink.h>
-
-/*
- * Index to functions.
- */
-
-static int ethertap_open(struct net_device *dev);
-static int ethertap_start_xmit(struct sk_buff *skb, struct net_device *dev);
-static int ethertap_close(struct net_device *dev);
-static struct net_device_stats *ethertap_get_stats(struct net_device *dev);
-static void ethertap_rx(struct sock *sk, int len);
-#ifdef CONFIG_ETHERTAP_MC
-static void set_multicast_list(struct net_device *dev);
-#endif
-
-static int ethertap_debug;
-
-static int max_taps = 1;
-module_param(max_taps, int, 0);
-MODULE_PARM_DESC(max_taps,"Max number of ethernet tap devices");
-
-static struct net_device **tap_map; /* Returns the tap device for a given netlink */
-
-/*
- * Board-specific info in dev->priv.
- */
-
-struct net_local
-{
- struct sock *nl;
-#ifdef CONFIG_ETHERTAP_MC
- __u32 groups;
-#endif
- struct net_device_stats stats;
-};
-
-/*
- * To call this a probe is a bit misleading, however for real
- * hardware it would have to check what was present.
- */
-static int __init ethertap_probe(int unit)
-{
- struct net_device *dev;
- int err = -ENOMEM;
-
- dev = alloc_etherdev(sizeof(struct net_local));
-
- if (!dev)
- goto out;
-
- SET_MODULE_OWNER(dev);
-
- sprintf(dev->name, "tap%d", unit);
- dev->base_addr = unit + NETLINK_TAPBASE;
-
- netdev_boot_setup_check(dev);
-
- memcpy(dev->dev_addr, "\xFE\xFD\x00\x00\x00\x00", 6);
- if (dev->mem_start & 0xf)
- ethertap_debug = dev->mem_start & 0x7;
-
- /*
- * The tap specific entries in the device structure.
- */
-
- dev->open = ethertap_open;
- dev->hard_start_xmit = ethertap_start_xmit;
- dev->stop = ethertap_close;
- dev->get_stats = ethertap_get_stats;
-#ifdef CONFIG_ETHERTAP_MC
- dev->set_multicast_list = set_multicast_list;
-#endif
-
- dev->tx_queue_len = 0;
- dev->flags|=IFF_NOARP;
-
- err = register_netdev(dev);
- if (err)
- goto out_free;
-
- tap_map[unit]=dev;
- return 0;
-out_free:
- free_netdev(dev);
-out:
- return err;
-}
-
-/*
- * Open/initialize the board.
- */
-
-static int ethertap_open(struct net_device *dev)
-{
- struct net_local *lp = netdev_priv(dev);
-
- if (ethertap_debug > 2)
- printk(KERN_DEBUG "%s: Doing ethertap_open()...\n", dev->name);
-
- lp->nl = netlink_kernel_create(dev->base_addr, ethertap_rx);
- if (lp->nl == NULL)
- return -ENOBUFS;
-
- netif_start_queue(dev);
- return 0;
-}
-
-#ifdef CONFIG_ETHERTAP_MC
-static unsigned ethertap_mc_hash(__u8 *dest)
-{
- unsigned idx = 0;
- idx ^= dest[0];
- idx ^= dest[1];
- idx ^= dest[2];
- idx ^= dest[3];
- idx ^= dest[4];
- idx ^= dest[5];
- return 1U << (idx&0x1F);
-}
-
-static void set_multicast_list(struct net_device *dev)
-{
- unsigned groups = ~0;
- struct net_local *lp = netdev_priv(dev);
-
- if (!(dev->flags&(IFF_NOARP|IFF_PROMISC|IFF_ALLMULTI))) {
- struct dev_mc_list *dmi;
-
- groups = ethertap_mc_hash(dev->broadcast);
-
- for (dmi=dev->mc_list; dmi; dmi=dmi->next) {
- if (dmi->dmi_addrlen != 6)
- continue;
- groups |= ethertap_mc_hash(dmi->dmi_addr);
- }
- }
- lp->groups = groups;
- if (lp->nl)
- lp->nl->protinfo.af_netlink.groups = groups;
-}
-#endif
-
-/*
- * We transmit by throwing the packet at netlink. We have to clone
- * it for 2.0 so that we dev_kfree_skb() the locked original.
- */
-
-static int ethertap_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
- struct net_local *lp = netdev_priv(dev);
-#ifdef CONFIG_ETHERTAP_MC
- struct ethhdr *eth = (struct ethhdr*)skb->data;
-#endif
-
- if (skb_headroom(skb) < 2) {
- static int once;
- struct sk_buff *skb2;
-
- if (!once) {
- once = 1;
- printk(KERN_DEBUG "%s: not aligned xmit by protocol %04x\n", dev->name, skb->protocol);
- }
-
- skb2 = skb_realloc_headroom(skb, 2);
- dev_kfree_skb(skb);
- if (skb2 == NULL)
- return 0;
- skb = skb2;
- }
- __skb_push(skb, 2);
-
- /* Make the same thing, which loopback does. */
- if (skb_shared(skb)) {
- struct sk_buff *skb2 = skb;
- skb = skb_clone(skb, GFP_ATOMIC); /* Clone the buffer */
- if (skb==NULL) {
- dev_kfree_skb(skb2);
- return 0;
- }
- dev_kfree_skb(skb2);
- }
- /* ... but do not orphan it here, netlink does it in any case. */
-
- lp->stats.tx_bytes+=skb->len;
- lp->stats.tx_packets++;
-
-#ifndef CONFIG_ETHERTAP_MC
- netlink_broadcast(lp->nl, skb, 0, ~0, GFP_ATOMIC);
-#else
- if (dev->flags&IFF_NOARP) {
- netlink_broadcast(lp->nl, skb, 0, ~0, GFP_ATOMIC);
- return 0;
- }
-
- if (!(eth->h_dest[0]&1)) {
- /* Unicast packet */
- __u32 pid;
- memcpy(&pid, eth->h_dest+2, 4);
- netlink_unicast(lp->nl, skb, ntohl(pid), MSG_DONTWAIT);
- } else
- netlink_broadcast(lp->nl, skb, 0, ethertap_mc_hash(eth->h_dest), GFP_ATOMIC);
-#endif
- return 0;
-}
-
-static __inline__ int ethertap_rx_skb(struct sk_buff *skb, struct net_device *dev)
-{
- struct net_local *lp = netdev_priv(dev);
-#ifdef CONFIG_ETHERTAP_MC
- struct ethhdr *eth = (struct ethhdr*)(skb->data + 2);
-#endif
- int len = skb->len;
-
- if (len < 16) {
- printk(KERN_DEBUG "%s : rx len = %d\n", dev->name, len);
- kfree_skb(skb);
- return -EINVAL;
- }
- if (NETLINK_CREDS(skb)->uid) {
- printk(KERN_INFO "%s : user %d\n", dev->name, NETLINK_CREDS(skb)->uid);
- kfree_skb(skb);
- return -EPERM;
- }
-
-#ifdef CONFIG_ETHERTAP_MC
- if (!(dev->flags&(IFF_NOARP|IFF_PROMISC))) {
- int drop = 0;
-
- if (eth->h_dest[0]&1) {
- if (!(ethertap_mc_hash(eth->h_dest)&lp->groups))
- drop = 1;
- } else if (memcmp(eth->h_dest, dev->dev_addr, 6) != 0)
- drop = 1;
-
- if (drop) {
- if (ethertap_debug > 3)
- printk(KERN_DEBUG "%s : not for us\n", dev->name);
- kfree_skb(skb);
- return -EINVAL;
- }
- }
-#endif
-
- if (skb_shared(skb)) {
- struct sk_buff *skb2 = skb;
- skb = skb_clone(skb, GFP_KERNEL); /* Clone the buffer */
- if (skb==NULL) {
- kfree_skb(skb2);
- return -ENOBUFS;
- }
- kfree_skb(skb2);
- } else
- skb_orphan(skb);
-
- skb_pull(skb, 2);
- skb->dev = dev;
- skb->protocol=eth_type_trans(skb,dev);
- memset(skb->cb, 0, sizeof(skb->cb));
- lp->stats.rx_packets++;
- lp->stats.rx_bytes+=len;
- netif_rx(skb);
- dev->last_rx = jiffies;
- return len;
-}
-
-/*
- * The typical workload of the driver:
- * Handle the ether interface interrupts.
- *
- * (In this case handle the packets posted from user space..)
- */
-
-static void ethertap_rx(struct sock *sk, int len)
-{
- unsigned unit = sk->sk_protocol - NETLINK_TAPBASE;
- struct net_device *dev;
- struct sk_buff *skb;
-
- if (unit >= max_taps || (dev = tap_map[unit]) == NULL) {
- printk(KERN_CRIT "ethertap: bad unit %u!\n", unit);
- skb_queue_purge(&sk->sk_receive_queue);
- return;
- }
-
- if (ethertap_debug > 3)
- printk(KERN_DEBUG "%s: ethertap_rx()\n", dev->name);
-
- while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL)
- ethertap_rx_skb(skb, dev);
-}
-
-static int ethertap_close(struct net_device *dev)
-{
- struct net_local *lp = netdev_priv(dev);
- struct sock *sk = lp->nl;
-
- if (ethertap_debug > 2)
- printk(KERN_DEBUG "%s: Shutting down.\n", dev->name);
-
- netif_stop_queue(dev);
-
- if (sk) {
- lp->nl = NULL;
- sock_release(sk->sk_socket);
- }
-
- return 0;
-}
-
-static struct net_device_stats *ethertap_get_stats(struct net_device *dev)
-{
- struct net_local *lp = netdev_priv(dev);
- return &lp->stats;
-}
-
-
-int __init ethertap_init(void)
-{
- int i, err = 0;
-
- /* netlink can only hande 16 entries unless modified */
- if (max_taps > MAX_LINKS - NETLINK_TAPBASE)
- return -E2BIG;
-
- tap_map = kmalloc(sizeof(struct net_device *)*max_taps, GFP_KERNEL);
- if (!tap_map)
- return -ENOMEM;
-
- for (i = 0; i < max_taps; i++) {
- err = ethertap_probe(i);
- if (err) {
- while (--i > 0) {
- unregister_netdev(tap_map[i]);
- free_netdev(tap_map[i]);
- }
- break;
- }
- }
- if (err)
- kfree(tap_map);
- return err;
-}
-module_init(ethertap_init);
-
-void __exit ethertap_cleanup(void)
-{
- int i;
-
- for (i = 0; i < max_taps; i++) {
- struct net_device *dev = tap_map[i];
- if (dev) {
- tap_map[i] = NULL;
- unregister_netdev(dev);
- free_netdev(dev);
- }
- }
- kfree(tap_map);
-}
-module_exit(ethertap_cleanup);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/net/ewrk3.c b/drivers/net/ewrk3.c
index b208b0aa30341..dcf969b20be90 100644
--- a/drivers/net/ewrk3.c
+++ b/drivers/net/ewrk3.c
@@ -273,6 +273,7 @@ struct ewrk3_stats {
struct ewrk3_private {
char adapter_name[80]; /* Name exported to /proc/ioports */
u_long shmem_base; /* Shared memory start address */
+ void __iomem *shmem;
u_long shmem_length; /* Shared memory window length */
struct net_device_stats stats; /* Public stats */
struct ewrk3_stats pktStats; /* Private stats counters */
@@ -281,7 +282,7 @@ struct ewrk3_private {
u_char lemac; /* Chip rev. level */
u_char hard_strapped; /* Don't allow a full open */
u_char txc; /* Transmit cut through */
- u_char *mctbl; /* Pointer to the multicast table */
+ void __iomem *mctbl; /* Pointer to the multicast table */
u_char led_mask; /* Used to reserve LED access for ethtool */
spinlock_t hw_lock;
};
@@ -535,6 +536,9 @@ ewrk3_hw_init(struct net_device *dev, u_long iobase)
lp = netdev_priv(dev);
lp->shmem_base = mem_start;
+ lp->shmem = ioremap(mem_start, shmem_length);
+ if (!lp->shmem)
+ return -ENOMEM;
lp->shmem_length = shmem_length;
lp->lemac = lemac;
lp->hard_strapped = hard_strapped;
@@ -590,6 +594,7 @@ ewrk3_hw_init(struct net_device *dev, u_long iobase)
} else {
printk(", but incorrect IRQ line detected.\n");
}
+ iounmap(lp->shmem);
return -ENXIO;
}
@@ -768,7 +773,7 @@ static int ewrk3_queue_pkt (struct sk_buff *skb, struct net_device *dev)
{
struct ewrk3_private *lp = netdev_priv(dev);
u_long iobase = dev->base_addr;
- u_long buf = 0;
+ void __iomem *buf = NULL;
u_char icr;
u_char page;
@@ -801,13 +806,13 @@ static int ewrk3_queue_pkt (struct sk_buff *skb, struct net_device *dev)
if (lp->shmem_length == IO_ONLY) {
outb (page, EWRK3_IOPR);
} else if (lp->shmem_length == SHMEM_2K) {
- buf = lp->shmem_base;
+ buf = lp->shmem;
outb (page, EWRK3_MPR);
} else if (lp->shmem_length == SHMEM_32K) {
- buf = ((((short) page << 11) & 0x7800) + lp->shmem_base);
+ buf = (((short) page << 11) & 0x7800) + lp->shmem;
outb ((page >> 4), EWRK3_MPR);
} else if (lp->shmem_length == SHMEM_64K) {
- buf = ((((short) page << 11) & 0xf800) + lp->shmem_base);
+ buf = (((short) page << 11) & 0xf800) + lp->shmem;
outb ((page >> 5), EWRK3_MPR);
} else {
printk (KERN_ERR "%s: Oops - your private data area is hosed!\n",
@@ -831,30 +836,28 @@ static int ewrk3_queue_pkt (struct sk_buff *skb, struct net_device *dev)
}
outb (page, EWRK3_TQ); /* Start sending pkt */
} else {
- isa_writeb ((char) (TCR_QMODE | TCR_PAD | TCR_IFC), buf); /* ctrl byte */
+ writeb ((char) (TCR_QMODE | TCR_PAD | TCR_IFC), buf); /* ctrl byte */
buf += 1;
- isa_writeb ((char) (skb->len & 0xff), buf); /* length (16 bit xfer) */
+ writeb ((char) (skb->len & 0xff), buf); /* length (16 bit xfer) */
buf += 1;
if (lp->txc) {
- isa_writeb ((char)
- (((skb->len >> 8) & 0xff) | XCT), buf);
+ writeb(((skb->len >> 8) & 0xff) | XCT, buf);
buf += 1;
- isa_writeb (0x04, buf); /* index byte */
+ writeb (0x04, buf); /* index byte */
buf += 1;
- isa_writeb (0x00, (buf + skb->len)); /* Write the XCT flag */
- isa_memcpy_toio (buf, skb->data, PRELOAD); /* Write PRELOAD bytes */
+ writeb (0x00, (buf + skb->len)); /* Write the XCT flag */
+ memcpy_toio (buf, skb->data, PRELOAD); /* Write PRELOAD bytes */
outb (page, EWRK3_TQ); /* Start sending pkt */
- isa_memcpy_toio (buf + PRELOAD,
+ memcpy_toio (buf + PRELOAD,
skb->data + PRELOAD,
skb->len - PRELOAD);
- isa_writeb (0xff, (buf + skb->len)); /* Write the XCT flag */
+ writeb (0xff, (buf + skb->len)); /* Write the XCT flag */
} else {
- isa_writeb ((char)
- ((skb->len >> 8) & 0xff), buf);
+ writeb ((skb->len >> 8) & 0xff, buf);
buf += 1;
- isa_writeb (0x04, buf); /* index byte */
+ writeb (0x04, buf); /* index byte */
buf += 1;
- isa_memcpy_toio (buf, skb->data, skb->len); /* Write data bytes */
+ memcpy_toio (buf, skb->data, skb->len); /* Write data bytes */
outb (page, EWRK3_TQ); /* Start sending pkt */
}
}
@@ -940,7 +943,7 @@ static int ewrk3_rx(struct net_device *dev)
u_long iobase = dev->base_addr;
int i, status = 0;
u_char page;
- u_long buf = 0;
+ void __iomem *buf = NULL;
while (inb(EWRK3_RQC) && !status) { /* Whilst there's incoming data */
if ((page = inb(EWRK3_RQ)) < lp->mPage) { /* Get next entry's buffer page */
@@ -950,13 +953,13 @@ static int ewrk3_rx(struct net_device *dev)
if (lp->shmem_length == IO_ONLY) {
outb(page, EWRK3_IOPR);
} else if (lp->shmem_length == SHMEM_2K) {
- buf = lp->shmem_base;
+ buf = lp->shmem;
outb(page, EWRK3_MPR);
} else if (lp->shmem_length == SHMEM_32K) {
- buf = ((((short) page << 11) & 0x7800) + lp->shmem_base);
+ buf = (((short) page << 11) & 0x7800) + lp->shmem;
outb((page >> 4), EWRK3_MPR);
} else if (lp->shmem_length == SHMEM_64K) {
- buf = ((((short) page << 11) & 0xf800) + lp->shmem_base);
+ buf = (((short) page << 11) & 0xf800) + lp->shmem;
outb((page >> 5), EWRK3_MPR);
} else {
status = -1;
@@ -972,9 +975,9 @@ static int ewrk3_rx(struct net_device *dev)
pkt_len = inb(EWRK3_DATA);
pkt_len |= ((u_short) inb(EWRK3_DATA) << 8);
} else {
- rx_status = isa_readb(buf);
+ rx_status = readb(buf);
buf += 1;
- pkt_len = isa_readw(buf);
+ pkt_len = readw(buf);
buf += 3;
}
@@ -1001,7 +1004,7 @@ static int ewrk3_rx(struct net_device *dev)
*p++ = inb(EWRK3_DATA);
}
} else {
- isa_memcpy_fromio(p, buf, pkt_len);
+ memcpy_fromio(p, buf, pkt_len);
}
for (i = 1; i < EWRK3_PKT_STAT_SZ - 1; i++) {
@@ -1153,9 +1156,9 @@ static void set_multicast_list(struct net_device *dev)
csr = inb(EWRK3_CSR);
if (lp->shmem_length == IO_ONLY) {
- lp->mctbl = (char *) PAGE0_HTE;
+ lp->mctbl = NULL;
} else {
- lp->mctbl = (char *) (lp->shmem_base + PAGE0_HTE);
+ lp->mctbl = lp->shmem + PAGE0_HTE;
}
csr &= ~(CSR_PME | CSR_MCE);
@@ -1184,7 +1187,7 @@ static void SetMulticastFilter(struct net_device *dev)
u_long iobase = dev->base_addr;
int i;
char *addrs, bit, byte;
- short *p = (short *) lp->mctbl;
+ short __iomem *p = lp->mctbl;
u16 hashcode;
u32 crc;
@@ -1192,7 +1195,7 @@ static void SetMulticastFilter(struct net_device *dev)
if (lp->shmem_length == IO_ONLY) {
outb(0, EWRK3_IOPR);
- outw(EEPROM_OFFSET(lp->mctbl), EWRK3_PIR1);
+ outw(PAGE0_HTE, EWRK3_PIR1);
} else {
outb(0, EWRK3_MPR);
}
@@ -1202,7 +1205,7 @@ static void SetMulticastFilter(struct net_device *dev)
if (lp->shmem_length == IO_ONLY) {
outb(0xff, EWRK3_DATA);
} else { /* memset didn't work here */
- isa_writew(0xffff, (int) p);
+ writew(0xffff, p);
p++;
i++;
}
@@ -1219,8 +1222,8 @@ static void SetMulticastFilter(struct net_device *dev)
outb(0x00, EWRK3_DATA);
}
} else {
- isa_memset_io((int) lp->mctbl, 0, (HASH_TABLE_LEN >> 3));
- isa_writeb(0x80, (int) (lp->mctbl + (HASH_TABLE_LEN >> 4) - 1));
+ memset_io(lp->mctbl, 0, HASH_TABLE_LEN >> 3);
+ writeb(0x80, lp->mctbl + (HASH_TABLE_LEN >> 4) - 1);
}
/* Update table */
@@ -1237,13 +1240,13 @@ static void SetMulticastFilter(struct net_device *dev)
if (lp->shmem_length == IO_ONLY) {
u_char tmp;
- outw((short) ((long) lp->mctbl) + byte, EWRK3_PIR1);
+ outw(PAGE0_HTE + byte, EWRK3_PIR1);
tmp = inb(EWRK3_DATA);
tmp |= bit;
- outw((short) ((long) lp->mctbl) + byte, EWRK3_PIR1);
+ outw(PAGE0_HTE + byte, EWRK3_PIR1);
outb(tmp, EWRK3_DATA);
} else {
- isa_writeb(isa_readb((int)(lp->mctbl + byte)) | bit, (int)(lp->mctbl + byte));
+ writeb(readb(lp->mctbl + byte) | bit, lp->mctbl + byte);
}
}
}
@@ -1654,8 +1657,7 @@ static int ewrk3_phys_id(struct net_device *dev, u32 data)
/* Wait a little while */
spin_unlock_irqrestore(&lp->hw_lock, flags);
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(HZ>>2);
+ msleep(250);
spin_lock_irqsave(&lp->hw_lock, flags);
/* Exit if we got a signal */
@@ -1784,7 +1786,7 @@ static int ewrk3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
}
} else {
outb(0, EWRK3_MPR);
- isa_memcpy_fromio(tmp->addr, lp->shmem_base + PAGE0_HTE, (HASH_TABLE_LEN >> 3));
+ memcpy_fromio(tmp->addr, lp->shmem + PAGE0_HTE, (HASH_TABLE_LEN >> 3));
}
spin_unlock_irqrestore(&lp->hw_lock, flags);
@@ -1954,10 +1956,13 @@ static __exit void ewrk3_exit_module(void)
int i;
for( i=0; i<ndevs; i++ ) {
- unregister_netdev(ewrk3_devs[i]);
- release_region(ewrk3_devs[i]->base_addr, EWRK3_TOTAL_SIZE);
- free_netdev(ewrk3_devs[i]);
+ struct net_device *dev = ewrk3_devs[i];
+ struct ewrk3_private *lp = netdev_priv(dev);
ewrk3_devs[i] = NULL;
+ unregister_netdev(dev);
+ release_region(dev->base_addr, EWRK3_TOTAL_SIZE);
+ iounmap(lp->shmem);
+ free_netdev(dev);
}
}
diff --git a/drivers/net/fc/Makefile b/drivers/net/fc/Makefile
deleted file mode 100644
index 8f31f2e5483dd..0000000000000
--- a/drivers/net/fc/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-#
-# Makefile for linux/drivers/net/fc
-#
-# 9 Aug 2000, Christoph Hellwig <hch@infradead.org>
-# Rewritten to use lists instead of if-statements.
-#
-
-obj-$(CONFIG_IPHASE5526) += iph5526.o
diff --git a/drivers/net/fc/iph5526.c b/drivers/net/fc/iph5526.c
deleted file mode 100644
index a5e12b2af3d9e..0000000000000
--- a/drivers/net/fc/iph5526.c
+++ /dev/null
@@ -1,4645 +0,0 @@
-/**********************************************************************
- * iph5526.c: IP/SCSI driver for the Interphase 5526 PCI Fibre Channel
- * Card.
- * Copyright (C) 1999 Vineet M Abraham <vmabraham@hotmail.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.
- *********************************************************************/
-/**********************************************************************
-Log:
-Vineet M Abraham
-02.12.99 Support multiple cards.
-03.15.99 Added Fabric support.
-04.04.99 Added N_Port support.
-04.15.99 Added SCSI support.
-06.18.99 Added ABTS Protocol.
-06.24.99 Fixed data corruption when multiple XFER_RDYs are received.
-07.07.99 Can be loaded as part of the Kernel. Changed semaphores. Added
- more checks before invalidating SEST entries.
-07.08.99 Added Broadcast IP stuff and fixed an unicast timeout bug.
-***********************************************************************/
-/* TODO:
- R_T_TOV set to 15msec in Loop topology. Need to be 100 msec.
- SMP testing.
- Fix ADISC Tx before completing FLOGI.
-*/
-
-static const char *version =
- "iph5526.c:v1.0 07.08.99 Vineet Abraham (vmabraham@hotmail.com)\n";
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/mm.h>
-#include <linux/delay.h>
-#include <linux/skbuff.h>
-#include <linux/if_arp.h>
-#include <linux/timer.h>
-#include <linux/spinlock.h>
-#include <linux/netdevice.h>
-#include <linux/fcdevice.h> /* had the declarations for init_fcdev among
- others + includes if_fcdevice.h */
-
-#include "../../scsi/scsi.h"
-#include <scsi/scsi_host.h>
-#include "../../fc4/fcp.h"
-
-#include <asm/system.h>
-#include <asm/io.h>
-
-/* driver specific header files */
-#include "tach.h"
-#include "tach_structs.h"
-#include "iph5526_ip.h"
-#include "iph5526_scsi.h"
-#include "iph5526_novram.c"
-
-#define RUN_AT(x) (jiffies + (x))
-
-#define DEBUG_5526_0 0
-#define DEBUG_5526_1 0
-#define DEBUG_5526_2 0
-
-#if DEBUG_5526_0
-#define DPRINTK(format, a...) {printk("%s: ", fi->name); \
- printk(format, ##a); \
- printk("\n");}
-#define ENTER(x) {printk("%s: ", fi->name); \
- printk("iph5526.c : entering %s()\n", x);}
-#define LEAVE(x) {printk("%s: ", fi->name); \
- printk("iph5526.c : leaving %s()\n",x);}
-
-#else
-#define DPRINTK(format, a...) {}
-#define ENTER(x) {}
-#define LEAVE(x) {}
-#endif
-
-#if DEBUG_5526_1
-#define DPRINTK1(format, a...) {printk("%s: ", fi->name); \
- printk(format, ##a); \
- printk("\n");}
-#else
-#define DPRINTK1(format, a...) {}
-#endif
-
-#if DEBUG_5526_2
-#define DPRINTK2(format, a...) {printk("%s: ", fi->name); \
- printk(format, ##a); \
- printk("\n");}
-#else
-#define DPRINTK2(format, a...) {}
-#endif
-
-#define T_MSG(format, a...) {printk("%s: ", fi->name); \
- printk(format, ##a);\
- printk("\n");}
-
-#define ALIGNED_SFS_ADDR(addr) ((((unsigned long)(addr) + (SFS_BUFFER_SIZE - 1)) & ~(SFS_BUFFER_SIZE - 1)) - (unsigned long)(addr))
-#define ALIGNED_ADDR(addr, len) ((((unsigned long)(addr) + (len - 1)) & ~(len - 1)) - (unsigned long)(addr))
-
-
-static struct pci_device_id iph5526_pci_tbl[] = {
- { PCI_VENDOR_ID_INTERPHASE, PCI_DEVICE_ID_INTERPHASE_5526, PCI_ANY_ID, PCI_ANY_ID, },
- { PCI_VENDOR_ID_INTERPHASE, PCI_DEVICE_ID_INTERPHASE_55x6, PCI_ANY_ID, PCI_ANY_ID, },
- { } /* Terminating entry */
-};
-MODULE_DEVICE_TABLE(pci, iph5526_pci_tbl);
-
-MODULE_LICENSE("GPL");
-
-#define MAX_FC_CARDS 2
-static struct fc_info *fc[MAX_FC_CARDS+1];
-static unsigned int pci_irq_line;
-static struct {
- unsigned short vendor_id;
- unsigned short device_id;
- char *name;
-}
-clone_list[] __initdata = {
- {PCI_VENDOR_ID_INTERPHASE, PCI_DEVICE_ID_INTERPHASE_5526, "Interphase Fibre Channel HBA"},
- {PCI_VENDOR_ID_INTERPHASE, PCI_DEVICE_ID_INTERPHASE_55x6, "Interphase Fibre Channel HBA"},
- {0,}
-};
-
-static irqreturn_t tachyon_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static void tachyon_interrupt_handler(int irq, void* dev_id, struct pt_regs* regs);
-
-static int initialize_register_pointers(struct fc_info *fi);
-void clean_up_memory(struct fc_info *fi);
-
-static int tachyon_init(struct fc_info *fi);
-static int build_queues(struct fc_info *fi);
-static void build_tachyon_header(struct fc_info *fi, u_int my_id, u_int r_ctl, u_int d_id, u_int type, u_char seq_id, u_char df_ctl, u_short ox_id, u_short rx_id, char *data);
-static int get_free_header(struct fc_info *fi);
-static void build_EDB(struct fc_info *fi, char *data, u_short flags, u_short len);
-static int get_free_EDB(struct fc_info *fi);
-static void build_ODB(struct fc_info *fi, u_char seq_id, u_int d_id, u_int len, u_int cntl, u_short mtu, u_short ox_id, u_short rx_id, int NW_header, int int_required, u_int frame_class);
-static void write_to_tachyon_registers(struct fc_info *fi);
-static void reset_latch(struct fc_info *fi);
-static void reset_tachyon(struct fc_info *fi, u_int value);
-static void take_tachyon_offline(struct fc_info *fi);
-static void read_novram(struct fc_info *fi);
-static void reset_ichip(struct fc_info *fi);
-static void update_OCQ_indx(struct fc_info *fi);
-static void update_IMQ_indx(struct fc_info *fi, int count);
-static void update_SFSBQ_indx(struct fc_info *fi);
-static void update_MFSBQ_indx(struct fc_info *fi, int count);
-static void update_tachyon_header_indx(struct fc_info *fi);
-static void update_EDB_indx(struct fc_info *fi);
-static void handle_FM_interrupt(struct fc_info *fi);
-static void handle_MFS_interrupt(struct fc_info *fi);
-static void handle_OOO_interrupt(struct fc_info *fi);
-static void handle_SFS_interrupt(struct fc_info *fi);
-static void handle_OCI_interrupt(struct fc_info *fi);
-static void handle_SFS_BUF_WARN_interrupt(struct fc_info *fi);
-static void handle_MFS_BUF_WARN_interrupt(struct fc_info *fi);
-static void handle_IMQ_BUF_WARN_interrupt(struct fc_info *fi);
-static void handle_Unknown_Frame_interrupt(struct fc_info *fi);
-static void handle_Busied_Frame_interrupt(struct fc_info *fi);
-static void handle_Bad_SCSI_Frame_interrupt(struct fc_info *fi);
-static void handle_Inbound_SCSI_Status_interrupt(struct fc_info *fi);
-static void handle_Inbound_SCSI_Command_interrupt(struct fc_info *fi);
-static void completion_message_handler(struct fc_info *fi, u_int imq_int_type);
-static void fill_login_frame(struct fc_info *fi, u_int logi);
-
-static int tx_exchange(struct fc_info *fi, char *data, u_int len, u_int r_ctl, u_int type, u_int d_id, u_int mtu, int int_required, u_short ox_id, u_int frame_class);
-static int tx_sequence(struct fc_info *fi, char *data, u_int len, u_int mtu, u_int d_id, u_short ox_id, u_short rx_id, u_char seq_id, int NW_flag, int int_required, u_int frame_class);
-static int validate_login(struct fc_info *fi, u_int *base_ptr);
-static void add_to_address_cache(struct fc_info *fi, u_int *base_ptr);
-static void remove_from_address_cache(struct fc_info *fi, u_int *data, u_int cmnd_code);
-static int node_logged_in_prev(struct fc_info *fi, u_int *buff_addr);
-static int sid_logged_in(struct fc_info *fi, u_int s_id);
-static struct fc_node_info *look_up_cache(struct fc_info *fi, char *data);
-static int display_cache(struct fc_info *fi);
-
-static void tx_logi(struct fc_info *fi, u_int logi, u_int d_id);
-static void tx_logi_acc(struct fc_info *fi, u_int logi, u_int d_id, u_short received_ox_id);
-static void tx_prli(struct fc_info *fi, u_int command_code, u_int d_id, u_short received_ox_id);
-static void tx_logo(struct fc_info *fi, u_int d_id, u_short received_ox_id);
-static void tx_adisc(struct fc_info *fi, u_int cmnd_code, u_int d_id, u_short received_ox_id);
-static void tx_ls_rjt(struct fc_info *fi, u_int d_id, u_short received_ox_id, u_short reason_code, u_short expln_code);
-static u_int plogi_ok(struct fc_info *fi, u_int *buff_addr, int size);
-static void tx_acc(struct fc_info *fi, u_int d_id, u_short received_ox_id);
-static void tx_name_server_req(struct fc_info *fi, u_int req);
-static void rscn_handler(struct fc_info *fi, u_int node_id);
-static void tx_scr(struct fc_info *fi);
-static void scr_timer(unsigned long data);
-static void explore_fabric(struct fc_info *fi, u_int *buff_addr);
-static void perform_adisc(struct fc_info *fi);
-static void local_port_discovery(struct fc_info *fi);
-static void add_to_ox_id_list(struct fc_info *fi, u_int transaction_id, u_int cmnd_code);
-static u_int remove_from_ox_id_list(struct fc_info *fi, u_short received_ox_id);
-static void add_display_cache_timer(struct fc_info *fi);
-
-/* Timers... */
-static void nos_ols_timer(unsigned long data);
-static void loop_timer(unsigned long data);
-static void fabric_explore_timer(unsigned long data);
-static void port_discovery_timer(unsigned long data);
-static void display_cache_timer(unsigned long data);
-
-/* SCSI Stuff */
-static int add_to_sest(struct fc_info *fi, Scsi_Cmnd *Cmnd, struct fc_node_info *ni);
-static struct fc_node_info *resolve_target(struct fc_info *fi, u_char target);
-static void update_FCP_CMND_indx(struct fc_info *fi);
-static int get_free_SDB(struct fc_info *fi);
-static void update_SDB_indx(struct fc_info *fi);
-static void mark_scsi_sid(struct fc_info *fi, u_int *buff_addr, u_char action);
-static void invalidate_SEST_entry(struct fc_info *fi, u_short received_ox_id);
-static int abort_exchange(struct fc_info *fi, u_short ox_id);
-static void flush_tachyon_cache(struct fc_info *fi, u_short ox_id);
-static int get_scsi_oxid(struct fc_info *fi);
-static void update_scsi_oxid(struct fc_info *fi);
-
-static Scsi_Host_Template driver_template = IPH5526_SCSI_FC;
-
-static void iph5526_timeout(struct net_device *dev);
-
-static int iph5526_probe_pci(struct net_device *dev);
-
-int __init iph5526_probe(struct net_device *dev)
-{
- if (iph5526_probe_pci(dev) == 0)
- return 0;
- return -ENODEV;
-}
-
-static int __init iph5526_probe_pci(struct net_device *dev)
-{
- struct fc_info *fi = dev->priv;
- fi->dev = dev;
- dev->base_addr = fi->base_addr;
- dev->irq = fi->irq;
- if (dev->priv == NULL)
- dev->priv = fi;
- fcdev_init(dev);
- /* Assign ur MAC address.
- */
- dev->dev_addr[0] = (fi->g.my_port_name_high & 0x0000FF00) >> 8;
- dev->dev_addr[1] = fi->g.my_port_name_high;
- dev->dev_addr[2] = (fi->g.my_port_name_low & 0xFF000000) >> 24;
- dev->dev_addr[3] = (fi->g.my_port_name_low & 0x00FF0000) >> 16;
- dev->dev_addr[4] = (fi->g.my_port_name_low & 0x0000FF00) >> 8;
- dev->dev_addr[5] = fi->g.my_port_name_low;
- display_cache(fi);
- return 0;
-}
-
-static int __init fcdev_init(struct net_device *dev)
-{
- SET_MODULE_OWNER(dev);
- dev->open = iph5526_open;
- dev->stop = iph5526_close;
- dev->hard_start_xmit = iph5526_send_packet;
- dev->get_stats = iph5526_get_stats;
- dev->set_multicast_list = NULL;
- dev->change_mtu = iph5526_change_mtu;
- dev->tx_timeout = iph5526_timeout;
- dev->watchdog_timeo = 5*HZ;
- return 0;
-}
-
-/* initialize tachyon and take it OnLine */
-static int tachyon_init(struct fc_info *fi)
-{
- ENTER("tachyon_init");
- if (build_queues(fi) == 0) {
- T_MSG("build_queues() failed");
- return 0;
- }
-
- /* Retrieve your port/node name.
- */
- read_novram(fi);
-
- reset_ichip(fi);
-
- reset_tachyon(fi, SOFTWARE_RESET);
-
- LEAVE("tachyon_init");
- return 1;
-}
-
-/* Build the 4 Qs - IMQ, OCQ, MFSBQ, SFSBQ */
-/* Lots of dma_pages needed as Tachyon DMAs almost everything into
- * host memory.
- */
-static int build_queues(struct fc_info *fi)
-{
-int i,j;
-u_char *addr;
- ENTER("build_queues");
- /* Initializing Queue Variables.
- */
- fi->q.ptr_host_ocq_cons_indx = NULL;
- fi->q.ptr_host_hpcq_cons_indx = NULL;
- fi->q.ptr_host_imq_prod_indx = NULL;
-
- fi->q.ptr_ocq_base = NULL;
- fi->q.ocq_len = 0;
- fi->q.ocq_end = 0;
- fi->q.ocq_prod_indx = 0;
-
- fi->q.ptr_imq_base = NULL;
- fi->q.imq_len = 0;
- fi->q.imq_end = 0;
- fi->q.imq_cons_indx = 0;
- fi->q.imq_prod_indx = 0;
-
- fi->q.ptr_mfsbq_base = NULL;
- fi->q.mfsbq_len = 0;
- fi->q.mfsbq_end = 0;
- fi->q.mfsbq_prod_indx = 0;
- fi->q.mfsbq_cons_indx = 0;
- fi->q.mfsbuff_len = 0;
- fi->q.mfsbuff_end = 0;
- fi->g.mfs_buffer_count = 0;
-
- fi->q.ptr_sfsbq_base = NULL;
- fi->q.sfsbq_len = 0;
- fi->q.sfsbq_end = 0;
- fi->q.sfsbq_prod_indx = 0;
- fi->q.sfsbq_cons_indx = 0;
- fi->q.sfsbuff_len = 0;
- fi->q.sfsbuff_end = 0;
-
- fi->q.sdb_indx = 0;
- fi->q.fcp_cmnd_indx = 0;
-
- fi->q.ptr_edb_base = NULL;
- fi->q.edb_buffer_indx = 0;
- fi->q.ptr_tachyon_header_base = NULL;
- fi->q.tachyon_header_indx = 0;
- fi->node_info_list = NULL;
- fi->ox_id_list = NULL;
- fi->g.loop_up = FALSE;
- fi->g.ptp_up = FALSE;
- fi->g.link_up = FALSE;
- fi->g.fabric_present = FALSE;
- fi->g.n_port_try = FALSE;
- fi->g.dont_init = FALSE;
- fi->g.nport_timer_set = FALSE;
- fi->g.lport_timer_set = FALSE;
- fi->g.no_of_targets = 0;
- fi->g.sem = 0;
- fi->g.perform_adisc = FALSE;
- fi->g.e_i = 0;
-
- /* build OCQ */
- if ( (fi->q.ptr_ocq_base = (u_int *)__get_free_pages(GFP_KERNEL, 0)) == 0) {
- T_MSG("failed to get OCQ page");
- return 0;
- }
- /* set up the OCQ structures */
- for (i = 0; i < OCQ_LENGTH; i++)
- fi->q.ptr_odb[i] = fi->q.ptr_ocq_base + NO_OF_ENTRIES*i;
-
- /* build IMQ */
- if ( (fi->q.ptr_imq_base = (u_int *)__get_free_pages(GFP_KERNEL, 0)) == 0) {
- T_MSG("failed to get IMQ page");
- return 0;
- }
- for (i = 0; i < IMQ_LENGTH; i++)
- fi->q.ptr_imqe[i] = fi->q.ptr_imq_base + NO_OF_ENTRIES*i;
-
- /* build MFSBQ */
- if ( (fi->q.ptr_mfsbq_base = (u_int *)__get_free_pages(GFP_KERNEL, 0)) == 0) {
- T_MSG("failed to get MFSBQ page");
- return 0;
- }
- memset((char *)fi->q.ptr_mfsbq_base, 0, MFSBQ_LENGTH * 32);
- /* Allocate one huge chunk of memory... helps while reassembling
- * frames.
- */
- if ( (addr = (u_char *)__get_free_pages(GFP_KERNEL, 5) ) == 0) {
- T_MSG("failed to get MFSBQ page");
- return 0;
- }
- /* fill in addresses of empty buffers */
- for (i = 0; i < MFSBQ_LENGTH; i++) {
- for (j = 0; j < NO_OF_ENTRIES; j++) {
- *(fi->q.ptr_mfsbq_base + i*NO_OF_ENTRIES + j) = htonl(virt_to_bus(addr));
- addr += MFS_BUFFER_SIZE;
- }
- }
-
- /* The number of entries in each MFS buffer is 8. There are 8
- * MFS buffers. That leaves us with 4096-256 bytes. We use them
- * as temporary space for ELS frames. This is done to make sure that
- * the addresses are aligned.
- */
- fi->g.els_buffer[0] = fi->q.ptr_mfsbq_base + MFSBQ_LENGTH*NO_OF_ENTRIES;
- for (i = 1; i < MAX_PENDING_FRAMES; i++)
- fi->g.els_buffer[i] = fi->g.els_buffer[i-1] + 64;
-
- /* build SFSBQ */
- if ( (fi->q.ptr_sfsbq_base = (u_int *)__get_free_pages(GFP_KERNEL, 0)) == 0) {
- T_MSG("failed to get SFSBQ page");
- return 0;
- }
- memset((char *)fi->q.ptr_sfsbq_base, 0, SFSBQ_LENGTH * 32);
- /* fill in addresses of empty buffers */
- for (i = 0; i < SFSBQ_LENGTH; i++)
- for (j = 0; j < NO_OF_ENTRIES; j++){
- addr = kmalloc(SFS_BUFFER_SIZE*2, GFP_KERNEL);
- if (addr == NULL){
- T_MSG("ptr_sfs_buffer : memory not allocated");
- return 0;
- }
- else {
- int offset = ALIGNED_SFS_ADDR(addr);
- memset((char *)addr, 0, SFS_BUFFER_SIZE);
- fi->q.ptr_sfs_buffers[i*NO_OF_ENTRIES +j] = (u_int *)addr;
- addr += offset;
- *(fi->q.ptr_sfsbq_base + i*NO_OF_ENTRIES + j) = htonl(virt_to_bus(addr));
- }
- }
-
- /* The number of entries in each SFS buffer is 8. There are 8
- * MFS buffers. That leaves us with 4096-256 bytes. We use them
- * as temporary space for ARP frames. This is done inorder to
- * support HW_Types of 0x1 and 0x6.
- */
- fi->g.arp_buffer = (char *)fi->q.ptr_sfsbq_base + SFSBQ_LENGTH*NO_OF_ENTRIES*4;
-
- /* build EDB */
- if ((fi->q.ptr_edb_base = (u_int *)__get_free_pages(GFP_KERNEL, 5) ) == 0) {
- T_MSG("failed to get EDB page");
- return 0;
- }
- for (i = 0; i < EDB_LEN; i++)
- fi->q.ptr_edb[i] = fi->q.ptr_edb_base + 2*i;
-
- /* build SEST */
-
- /* OX_IDs range from 0x0 - 0x4FFF.
- */
- if ((fi->q.ptr_sest_base = (u_int *)__get_free_pages(GFP_KERNEL, 5)) == 0) {
- T_MSG("failed to get SEST page");
- return 0;
- }
- for (i = 0; i < SEST_LENGTH; i++)
- fi->q.ptr_sest[i] = fi->q.ptr_sest_base + NO_OF_ENTRIES*i;
-
- if ((fi->q.ptr_sdb_base = (u_int *)__get_free_pages(GFP_KERNEL, 5)) == 0) {
- T_MSG("failed to get SDB page");
- return 0;
- }
- for (i = 0 ; i < NO_OF_SDB_ENTRIES; i++)
- fi->q.ptr_sdb_slot[i] = fi->q.ptr_sdb_base + (SDB_SIZE/4)*i;
-
- if ((fi->q.ptr_fcp_cmnd_base = (u_int *)__get_free_pages(GFP_KERNEL, 0)) == 0) {
- T_MSG("failed to get FCP_CMND page");
- return 0;
- }
- for (i = 0; i < NO_OF_FCP_CMNDS; i++)
- fi->q.ptr_fcp_cmnd[i] = fi->q.ptr_fcp_cmnd_base + NO_OF_ENTRIES*i;
-
- /* Allocate space for Tachyon Header as well...
- */
- if ((fi->q.ptr_tachyon_header_base = (u_int *)__get_free_pages(GFP_KERNEL, 0) ) == 0) {
- T_MSG("failed to get tachyon_header page");
- return 0;
- }
- for (i = 0; i < NO_OF_TACH_HEADERS; i++)
- fi->q.ptr_tachyon_header[i] = fi->q.ptr_tachyon_header_base + 16*i;
-
- /* Allocate memory for indices.
- * Indices should be aligned on 32 byte boundaries.
- */
- fi->q.host_ocq_cons_indx = kmalloc(2*32, GFP_KERNEL);
- if (fi->q.host_ocq_cons_indx == NULL){
- T_MSG("fi->q.host_ocq_cons_indx : memory not allocated");
- return 0;
- }
- fi->q.ptr_host_ocq_cons_indx = fi->q.host_ocq_cons_indx;
- if ((u_long)(fi->q.host_ocq_cons_indx) % 32)
- fi->q.host_ocq_cons_indx++;
-
- fi->q.host_hpcq_cons_indx = kmalloc(2*32, GFP_KERNEL);
- if (fi->q.host_hpcq_cons_indx == NULL){
- T_MSG("fi->q.host_hpcq_cons_indx : memory not allocated");
- return 0;
- }
- fi->q.ptr_host_hpcq_cons_indx= fi->q.host_hpcq_cons_indx;
- if ((u_long)(fi->q.host_hpcq_cons_indx) % 32)
- fi->q.host_hpcq_cons_indx++;
-
- fi->q.host_imq_prod_indx = kmalloc(2*32, GFP_KERNEL);
- if (fi->q.host_imq_prod_indx == NULL){
- T_MSG("fi->q.host_imq_prod_indx : memory not allocated");
- return 0;
- }
- fi->q.ptr_host_imq_prod_indx = fi->q.host_imq_prod_indx;
- if ((u_long)(fi->q.host_imq_prod_indx) % 32)
- fi->q.host_imq_prod_indx++;
-
- LEAVE("build_queues");
- return 1;
-}
-
-
-static void write_to_tachyon_registers(struct fc_info *fi)
-{
-u_int bus_addr, bus_indx_addr, i;
-
- ENTER("write_to_tachyon_registers");
-
- /* Clear Queues each time Tachyon is reset */
- memset((char *)fi->q.ptr_ocq_base, 0, OCQ_LENGTH * 32);
- memset((char *)fi->q.ptr_imq_base, 0, IMQ_LENGTH * 32);
- memset((char *)fi->q.ptr_edb_base, 0, EDB_LEN * 8);
- memset((char *)fi->q.ptr_sest_base, 0, SEST_LENGTH * 32);
- memset((char *)fi->q.ptr_sdb_base, 0, NO_OF_SDB_ENTRIES * SDB_SIZE);
- memset((char *)fi->q.ptr_tachyon_header_base, 0xFF, NO_OF_TACH_HEADERS * TACH_HEADER_SIZE);
- for (i = 0; i < SEST_LENGTH; i++)
- fi->q.free_scsi_oxid[i] = OXID_AVAILABLE;
- for (i = 0; i < NO_OF_SDB_ENTRIES; i++)
- fi->q.sdb_slot_status[i] = SDB_FREE;
-
- take_tachyon_offline(fi);
- writel(readl(fi->t_r.ptr_tach_config_reg) | SCSI_ENABLE | WRITE_STREAM_SIZE | READ_STREAM_SIZE | PARITY_EVEN | OOO_REASSEMBLY_DISABLE, fi->t_r.ptr_tach_config_reg);
-
- /* Write OCQ registers */
- fi->q.ocq_prod_indx = 0;
- *(fi->q.host_ocq_cons_indx) = 0;
-
- /* The Tachyon needs to be passed the "real" address */
- bus_addr = virt_to_bus(fi->q.ptr_ocq_base);
- writel(bus_addr, fi->t_r.ptr_ocq_base_reg);
- writel(OCQ_LENGTH - 1, fi->t_r. ptr_ocq_len_reg);
- bus_indx_addr = virt_to_bus(fi->q.host_ocq_cons_indx);
- writel(bus_indx_addr, fi->t_r.ptr_ocq_cons_indx_reg);
-
- /* Write IMQ registers */
- fi->q.imq_cons_indx = 0;
- *(fi->q.host_imq_prod_indx) = 0;
- bus_addr = virt_to_bus(fi->q.ptr_imq_base);
- writel(bus_addr, fi->t_r.ptr_imq_base_reg);
- writel(IMQ_LENGTH - 1, fi->t_r.ptr_imq_len_reg);
- bus_indx_addr = virt_to_bus(fi->q.host_imq_prod_indx);
- writel(bus_indx_addr, fi->t_r.ptr_imq_prod_indx_reg);
-
- /* Write MFSBQ registers */
- fi->q.mfsbq_prod_indx = MFSBQ_LENGTH - 1;
- fi->q.mfsbuff_end = MFS_BUFFER_SIZE - 1;
- fi->q.mfsbq_cons_indx = 0;
- bus_addr = virt_to_bus(fi->q.ptr_mfsbq_base);
- writel(bus_addr, fi->t_r.ptr_mfsbq_base_reg);
- writel(MFSBQ_LENGTH - 1, fi->t_r.ptr_mfsbq_len_reg);
- writel(fi->q.mfsbuff_end, fi->t_r.ptr_mfsbuff_len_reg);
- /* Do this last as tachyon will prefetch the
- * first entry as soon as we write to it.
- */
- writel(fi->q.mfsbq_prod_indx, fi->t_r.ptr_mfsbq_prod_reg);
-
- /* Write SFSBQ registers */
- fi->q.sfsbq_prod_indx = SFSBQ_LENGTH - 1;
- fi->q.sfsbuff_end = SFS_BUFFER_SIZE - 1;
- fi->q.sfsbq_cons_indx = 0;
- bus_addr = virt_to_bus(fi->q.ptr_sfsbq_base);
- writel(bus_addr, fi->t_r.ptr_sfsbq_base_reg);
- writel(SFSBQ_LENGTH - 1, fi->t_r.ptr_sfsbq_len_reg);
- writel(fi->q.sfsbuff_end, fi->t_r.ptr_sfsbuff_len_reg);
- /* Do this last as tachyon will prefetch the first
- * entry as soon as we write to it.
- */
- writel(fi->q.sfsbq_prod_indx, fi->t_r.ptr_sfsbq_prod_reg);
-
- /* Write SEST registers */
- bus_addr = virt_to_bus(fi->q.ptr_sest_base);
- writel(bus_addr, fi->t_r.ptr_sest_base_reg);
- writel(SEST_LENGTH - 1, fi->t_r.ptr_sest_len_reg);
- /* the last 2 bits _should_ be 1 */
- writel(SEST_BUFFER_SIZE - 1, fi->t_r.ptr_scsibuff_len_reg);
-
- /* write AL_TIME & E_D_TOV into the registers */
- writel(TOV_VALUES, fi->t_r.ptr_fm_tov_reg);
- /* Tell Tachyon to pick a Soft Assigned AL_PA */
- writel(LOOP_INIT_SOFT_ADDRESS, fi->t_r.ptr_fm_config_reg);
-
- /* Read the WWN from EEPROM . But, for now we assign it here. */
- writel(WORLD_WIDE_NAME_LOW, fi->t_r.ptr_fm_wwn_low_reg);
- writel(WORLD_WIDE_NAME_HIGH, fi->t_r.ptr_fm_wwn_hi_reg);
-
- DPRINTK1("TACHYON initializing as L_Port...\n");
- writel(INITIALIZE, fi->t_r.ptr_fm_control_reg);
-
- LEAVE("write_to_tachyon_registers");
-}
-
-
-static irqreturn_t tachyon_interrupt(int irq, void* dev_id, struct pt_regs* regs)
-{
-struct Scsi_Host *host = dev_id;
-struct iph5526_hostdata *hostdata = (struct iph5526_hostdata *)host->hostdata;
-struct fc_info *fi = hostdata->fi;
-u_long flags;
- spin_lock_irqsave(&fi->fc_lock, flags);
- tachyon_interrupt_handler(irq, dev_id, regs);
- spin_unlock_irqrestore(&fi->fc_lock, flags);
- return IRQ_HANDLED;
-}
-
-static void tachyon_interrupt_handler(int irq, void* dev_id, struct pt_regs* regs)
-{
-struct Scsi_Host *host = dev_id;
-struct iph5526_hostdata *hostdata = (struct iph5526_hostdata *)host->hostdata;
-struct fc_info *fi = hostdata->fi;
-u_int *ptr_imq_entry;
-u_int imq_int_type, current_IMQ_index = 0, prev_IMQ_index;
-int index, no_of_entries = 0;
-
- DPRINTK("\n");
- ENTER("tachyon_interrupt");
- if (fi->q.host_imq_prod_indx != NULL) {
- current_IMQ_index = ntohl(*(fi->q.host_imq_prod_indx));
- }
- else {
- /* _Should not_ happen */
- T_MSG("IMQ_indx NULL. DISABLING INTERRUPTS!!!\n");
- writel(0x0, fi->i_r.ptr_ichip_hw_control_reg);
- }
-
- if (current_IMQ_index > fi->q.imq_cons_indx)
- no_of_entries = current_IMQ_index - fi->q.imq_cons_indx;
- else
- if (current_IMQ_index < fi->q.imq_cons_indx)
- no_of_entries = IMQ_LENGTH - (fi->q.imq_cons_indx - current_IMQ_index);
-
- if (no_of_entries == 0) {
- u_int ichip_status;
- ichip_status = readl(fi->i_r.ptr_ichip_hw_status_reg);
- if (ichip_status & 0x20) {
- /* Should _never_ happen. Might require a hard reset */
- T_MSG("Too bad... PCI Bus Error. Resetting (i)chip");
- reset_ichip(fi);
- T_MSG("DISABLING INTERRUPTS!!!\n");
- writel(0x0, fi->i_r.ptr_ichip_hw_control_reg);
- }
- }
-
- prev_IMQ_index = current_IMQ_index;
- for (index = 0; index < no_of_entries; index++) {
- ptr_imq_entry = fi->q.ptr_imqe[fi->q.imq_cons_indx];
- imq_int_type = ntohl(*ptr_imq_entry);
-
- completion_message_handler(fi, imq_int_type);
- if ((fi->g.link_up == FALSE) && ((imq_int_type == MFS_BUF_WARN) || (imq_int_type == SFS_BUF_WARN) || (imq_int_type == IMQ_BUF_WARN)))
- break;
- update_IMQ_indx(fi, 1);
-
- /* Check for more entries */
- current_IMQ_index = ntohl(*(fi->q.host_imq_prod_indx));
- if (current_IMQ_index != prev_IMQ_index) {
- no_of_entries++;
- prev_IMQ_index = current_IMQ_index;
- }
- } /*end of for loop*/
- LEAVE("tachyon_interrupt");
- return;
-}
-
-
-static void handle_SFS_BUF_WARN_interrupt(struct fc_info *fi)
-{
-int i;
- ENTER("handle_SFS_BUF_WARN_interrupt");
- if (fi->g.link_up == FALSE) {
- reset_tachyon(fi, SOFTWARE_RESET);
- return;
- }
- /* Free up all but one entry in the Q.
- */
- for (i = 0; i < ((SFSBQ_LENGTH - 1) * NO_OF_ENTRIES); i++) {
- handle_SFS_interrupt(fi);
- update_IMQ_indx(fi, 1);
- }
- LEAVE("handle_SFS_BUF_WARN_interrupt");
-}
-
-/* Untested_Code_Begin */
-static void handle_MFS_BUF_WARN_interrupt(struct fc_info *fi)
-{
-int i;
- ENTER("handle_MFS_BUF_WARN_interrupt");
- if (fi->g.link_up == FALSE) {
- reset_tachyon(fi, SOFTWARE_RESET);
- return;
- }
- /* FIXME: freeing up 8 entries.
- */
- for (i = 0; i < NO_OF_ENTRIES; i++) {
- handle_MFS_interrupt(fi);
- update_IMQ_indx(fi, 1);
- }
- LEAVE("handle_MFS_BUF_WARN_interrupt");
-}
-/*Untested_Code_End */
-
-static void handle_IMQ_BUF_WARN_interrupt(struct fc_info *fi)
-{
-u_int *ptr_imq_entry;
-u_int imq_int_type, current_IMQ_index = 0, temp_imq_cons_indx;
-int index, no_of_entries = 0;
-
- ENTER("handle_IMQ_BUF_WARN_interrupt");
- if (fi->g.link_up == FALSE) {
- reset_tachyon(fi, SOFTWARE_RESET);
- return;
- }
- current_IMQ_index = ntohl(*(fi->q.host_imq_prod_indx));
-
- if (current_IMQ_index > fi->q.imq_cons_indx)
- no_of_entries = current_IMQ_index - fi->q.imq_cons_indx;
- else
- if (current_IMQ_index < fi->q.imq_cons_indx)
- no_of_entries = IMQ_LENGTH - (fi->q.imq_cons_indx - current_IMQ_index);
- /* We don't want to look at the same IMQ entry again.
- */
- temp_imq_cons_indx = fi->q.imq_cons_indx + 1;
- if (no_of_entries != 0)
- no_of_entries -= 1;
- for (index = 0; index < no_of_entries; index++) {
- ptr_imq_entry = fi->q.ptr_imqe[temp_imq_cons_indx];
- imq_int_type = ntohl(*ptr_imq_entry);
- if (imq_int_type != IMQ_BUF_WARN)
- completion_message_handler(fi, imq_int_type);
- temp_imq_cons_indx++;
- if (temp_imq_cons_indx == IMQ_LENGTH)
- temp_imq_cons_indx = 0;
- } /*end of for loop*/
- if (no_of_entries != 0)
- update_IMQ_indx(fi, no_of_entries);
- LEAVE("handle_IMQ_BUF_WARN_interrupt");
-}
-
-static void completion_message_handler(struct fc_info *fi, u_int imq_int_type)
-{
- switch(imq_int_type) {
- case OUTBOUND_COMPLETION:
- DPRINTK("OUTBOUND_COMPLETION message received");
- break;
- case OUTBOUND_COMPLETION_I:
- DPRINTK("OUTBOUND_COMPLETION_I message received");
- handle_OCI_interrupt(fi);
- break;
- case OUT_HI_PRI_COMPLETION:
- DPRINTK("OUT_HI_PRI_COMPLETION message received");
- break;
- case OUT_HI_PRI_COMPLETION_I:
- DPRINTK("OUT_HI_PRI_COMPLETION_I message received");
- break;
- case INBOUND_MFS_COMPLETION:
- DPRINTK("INBOUND_MFS_COMPLETION message received");
- handle_MFS_interrupt(fi);
- break;
- case INBOUND_OOO_COMPLETION:
- DPRINTK("INBOUND_OOO_COMPLETION message received");
- handle_OOO_interrupt(fi);
- break;
- case INBOUND_SFS_COMPLETION:
- DPRINTK("INBOUND_SFS_COMPLETION message received");
- handle_SFS_interrupt(fi);
- break;
- case INBOUND_UNKNOWN_FRAME_I:
- DPRINTK("INBOUND_UNKNOWN_FRAME message received");
- handle_Unknown_Frame_interrupt(fi);
- break;
- case INBOUND_BUSIED_FRAME:
- DPRINTK("INBOUND_BUSIED_FRAME message received");
- handle_Busied_Frame_interrupt(fi);
- break;
- case FRAME_MGR_INTERRUPT:
- DPRINTK("FRAME_MGR_INTERRUPT message received");
- handle_FM_interrupt(fi);
- break;
- case READ_STATUS:
- DPRINTK("READ_STATUS message received");
- break;
- case SFS_BUF_WARN:
- DPRINTK("SFS_BUF_WARN message received");
- handle_SFS_BUF_WARN_interrupt(fi);
- break;
- case MFS_BUF_WARN:
- DPRINTK("MFS_BUF_WARN message received");
- handle_MFS_BUF_WARN_interrupt(fi);
- break;
- case IMQ_BUF_WARN:
- DPRINTK("IMQ_BUF_WARN message received");
- handle_IMQ_BUF_WARN_interrupt(fi);
- break;
- case INBOUND_C1_TIMEOUT:
- DPRINTK("INBOUND_C1_TIMEOUT message received");
- break;
- case BAD_SCSI_FRAME:
- DPRINTK("BAD_SCSI_FRAME message received");
- handle_Bad_SCSI_Frame_interrupt(fi);
- break;
- case INB_SCSI_STATUS_COMPLETION:
- DPRINTK("INB_SCSI_STATUS_COMPL message received");
- handle_Inbound_SCSI_Status_interrupt(fi);
- break;
- case INBOUND_SCSI_COMMAND:
- DPRINTK("INBOUND_SCSI_COMMAND message received");
- handle_Inbound_SCSI_Command_interrupt(fi);
- break;
- case INBOUND_SCSI_DATA_COMPLETION:
- DPRINTK("INBOUND_SCSI_DATA message received");
- /* Only for targets */
- break;
- default:
- T_MSG("DEFAULT message received, type = %x", imq_int_type);
- return;
- }
- reset_latch(fi);
-}
-
-static void handle_OCI_interrupt(struct fc_info *fi)
-{
-u_int *ptr_imq_entry;
-u_long transaction_id = 0;
-unsigned short status, seq_count, transmitted_ox_id;
-struct Scsi_Host *host = fi->host;
-struct iph5526_hostdata *hostdata = (struct iph5526_hostdata *)host->hostdata;
-Scsi_Cmnd *Cmnd;
-u_int tag;
-
- ENTER("handle_OCI_interrupt");
- ptr_imq_entry = fi->q.ptr_imqe[fi->q.imq_cons_indx];
- transaction_id = ntohl(*(ptr_imq_entry + 1));
- status = ntohl(*(ptr_imq_entry + 2)) >> 16;
- seq_count = ntohl(*(ptr_imq_entry + 3));
- DPRINTK("transaction_id= %x", (u_int)transaction_id);
- tag = transaction_id & 0xFFFF0000;
- transmitted_ox_id = transaction_id;
-
- /* The INT could be either due to TIME_OUT | BAD_ALPA.
- * But we check only for TimeOuts. Bad AL_PA will
- * caught by FM_interrupt handler.
- */
-
- if ((status == OCM_TIMEOUT_OR_BAD_ALPA) && (!fi->g.port_discovery) && (!fi->g.perform_adisc)){
- DPRINTK("Frame TimeOut on OX_ID = %x", (u_int)transaction_id);
-
- /* Is it a SCSI frame that is timing out ? Not a very good check...
- */
- if ((transmitted_ox_id <= MAX_SCSI_OXID) && ((tag == FC_SCSI_BAD_TARGET) || (tag < 0x00FF0000))) {
- /* If it is a Bad AL_PA, we report it as BAD_TARGET.
- * Else, we allow the command to time-out. A Link
- * re-initialization could be taking place.
- */
- if (tag == FC_SCSI_BAD_TARGET) {
- Cmnd = hostdata->cmnd_handler[transmitted_ox_id & MAX_SCSI_XID];
- hostdata->cmnd_handler[transmitted_ox_id & MAX_SCSI_XID] = NULL;
- if (Cmnd != NULL) {
- Cmnd->result = DID_BAD_TARGET << 16;
- (*Cmnd->scsi_done) (Cmnd);
- }
- else
- T_MSG("NULL Command out of handler!");
- } /* if Bad Target */
- else {
- u_char missing_target = tag >> 16;
- struct fc_node_info *q = fi->node_info_list;
- /* A Node that we thought was logged in has gone
- * away. We are the optimistic kind and we keep
- * hoping that our dear little Target will come back
- * to us. For now we log him out.
- */
- DPRINTK2("Missing Target = %d", missing_target);
- while (q != NULL) {
- if (q->target_id == missing_target) {
- T_MSG("Target %d Logged out", q->target_id);
- q->login = LOGIN_ATTEMPTED;
- if (fi->num_nodes > 0)
- fi->num_nodes--;
- tx_logi(fi, ELS_PLOGI, q->d_id);
- break;
- }
- else
- q = q->next;
- }
- }
- } /* End of SCSI frame timing out. */
- else {
- if (seq_count > 1) {
- /* An IP frame was transmitted to a Bad AL_PA. Free up
- * the skb used.
- */
- dev_kfree_skb_irq((struct sk_buff *)(bus_to_virt(transaction_id)));
- netif_wake_queue(fi->dev);
- }
- } /* End of IP frame timing out. */
- } /* End of frame timing out. */
- else {
- /* Frame was transmitted successfully. Check if it was an ELS
- * frame or an IP frame or a Bad_Target_Notification frame (in
- * case of a ptp_link). Ugly!
- */
- if ((status == 0) && (seq_count == 0)) {
- u_int tag = transaction_id & 0xFFFF0000;
- /* Continue with port discovery after an ELS is successfully
- * transmitted. (status == 0).
- */
- DPRINTK("tag = %x", tag);
- switch(tag) {
- case ELS_FLOGI:
- /* Letz use the Name Server instead */
- fi->g.explore_fabric = TRUE;
- fi->g.port_discovery = FALSE;
- fi->g.alpa_list_index = MAX_NODES;
- add_to_ox_id_list(fi, transaction_id, tag);
- break;
- case ELS_PLOGI:
- if (fi->g.fabric_present && (fi->g.name_server == FALSE))
- add_to_ox_id_list(fi,transaction_id,ELS_NS_PLOGI);
- else
- add_to_ox_id_list(fi, transaction_id, tag);
- break;
- case FC_SCSI_BAD_TARGET:
- Cmnd = hostdata->cmnd_handler[transmitted_ox_id & MAX_SCSI_XID];
- hostdata->cmnd_handler[transmitted_ox_id & MAX_SCSI_XID] = NULL;
- if (Cmnd != NULL) {
- Cmnd->result = DID_BAD_TARGET << 16;
- (*Cmnd->scsi_done) (Cmnd);
- }
- else
- T_MSG("NULL Command out of handler!");
- break;
- default:
- add_to_ox_id_list(fi, transaction_id, tag);
- }
-
- if (fi->g.alpa_list_index >= MAX_NODES) {
- if (fi->g.port_discovery == TRUE) {
- fi->g.port_discovery = FALSE;
- add_display_cache_timer(fi);
- }
- fi->g.alpa_list_index = MAX_NODES;
- }
- if (fi->g.port_discovery == TRUE)
- local_port_discovery(fi);
- }
- else {
- /* An IP frame has been successfully transmitted.
- * Free the skb that was used for this IP frame.
- */
- if ((status == 0) && (seq_count > 1)) {
- dev_kfree_skb_irq((struct sk_buff *)(bus_to_virt(transaction_id)));
- netif_wake_queue(fi->dev);
- }
- }
- }
- LEAVE("handle_OCI_interrupt");
-}
-
-/* Right now we discard OOO frames */
-static void handle_OOO_interrupt(struct fc_info *fi)
-{
-u_int *ptr_imq_entry;
-int queue_indx, offset, payload_size;
-int no_of_buffers = 1; /* header is in a separate buffer */
- ptr_imq_entry = fi->q.ptr_imqe[fi->q.imq_cons_indx];
- offset = ntohl(*(ptr_imq_entry + 1)) & 0x00000007;
- queue_indx = ntohl(*(ptr_imq_entry + 1)) & 0xFFFF0000;
- queue_indx = queue_indx >> 16;
- payload_size = ntohl(*(ptr_imq_entry + 2)) - TACHYON_HEADER_LEN;
- /* Calculate total number of buffers */
- no_of_buffers += payload_size / MFS_BUFFER_SIZE;
- if (payload_size % MFS_BUFFER_SIZE)
- no_of_buffers++;
-
- /* provide Tachyon will another set of buffers */
- fi->g.mfs_buffer_count += no_of_buffers;
- if (fi->g.mfs_buffer_count >= NO_OF_ENTRIES) {
- int count = fi->g.mfs_buffer_count / NO_OF_ENTRIES;
- fi->g.mfs_buffer_count -= NO_OF_ENTRIES * count;
- update_MFSBQ_indx(fi, count);
- }
-}
-
-static void handle_MFS_interrupt(struct fc_info *fi)
-{
-u_int *ptr_imq_entry, *buff_addr;
-u_int type_of_frame, s_id;
-int queue_indx, offset, payload_size, starting_indx, starting_offset;
-u_short received_ox_id;
-int no_of_buffers = 1; /* header is in a separate buffer */
-struct sk_buff *skb;
-int wrap_around = FALSE, no_of_wrap_buffs = NO_OF_ENTRIES - 1;
- ENTER("handle_MFS_interrupt");
- ptr_imq_entry = fi->q.ptr_imqe[fi->q.imq_cons_indx];
- offset = ntohl(*(ptr_imq_entry + 1)) & 0x00000007;
- queue_indx = ntohl(*(ptr_imq_entry + 1)) & 0xFFFF0000;
- queue_indx = queue_indx >> 16;
- DPRINTK("queue_indx = %d, offset = %d\n", queue_indx, offset);
- payload_size = ntohl(*(ptr_imq_entry + 2)) - TACHYON_HEADER_LEN;
- DPRINTK("payload_size = %d", payload_size);
- /* Calculate total number of buffers */
- no_of_buffers += payload_size / MFS_BUFFER_SIZE;
- if (payload_size % MFS_BUFFER_SIZE)
- no_of_buffers++;
- DPRINTK("no_of_buffers = %d", no_of_buffers);
-
- if ((no_of_buffers - 1) <= offset) {
- starting_offset = offset - (no_of_buffers - 1);
- starting_indx = queue_indx;
- }
- else {
- int temp = no_of_buffers - (offset + 1);
- int no_of_queues = temp / NO_OF_ENTRIES;
- starting_offset = temp % NO_OF_ENTRIES;
- if (starting_offset != 0) {
- no_of_wrap_buffs = starting_offset - 1; //exclude header
- starting_offset = NO_OF_ENTRIES - starting_offset;
- no_of_queues++;
- }
- starting_indx = queue_indx - no_of_queues;
- if (starting_indx < 0) {
- no_of_wrap_buffs -= (starting_indx + 1) * NO_OF_ENTRIES;
- starting_indx = MFSBQ_LENGTH + starting_indx;
- wrap_around = TRUE;
- }
- }
-
- DPRINTK("starting_indx = %d, starting offset = %d no_of_wrap_buffs = %d\n", starting_indx, starting_offset, no_of_wrap_buffs);
- /* Get Tachyon Header from first buffer */
- buff_addr = bus_to_virt(ntohl(*(fi->q.ptr_mfsbq_base + starting_indx*NO_OF_ENTRIES + starting_offset)));
-
-
- /* extract Type of Frame */
- type_of_frame = (u_int)ntohl(*(buff_addr + 4)) & 0xFF000000;
- s_id = (u_int)ntohl(*(buff_addr + 3)) & 0x00FFFFFF;
- received_ox_id = ntohl(*(buff_addr + 6)) >> 16;
- buff_addr += MFS_BUFFER_SIZE/4;
- DPRINTK("type_of_frame = %x, s_id = %x, ox_id = %x", type_of_frame, s_id, received_ox_id);
-
- switch(type_of_frame) {
- case TYPE_LLC_SNAP:
- skb = dev_alloc_skb(payload_size);
- if (skb == NULL) {
- printk(KERN_NOTICE "%s: In handle_MFS_interrupt() Memory squeeze, dropping packet.\n", fi->name);
- fi->fc_stats.rx_dropped++;
- fi->g.mfs_buffer_count += no_of_buffers;
- if (fi->g.mfs_buffer_count >= NO_OF_ENTRIES) {
- int count = fi->g.mfs_buffer_count / NO_OF_ENTRIES;
- fi->g.mfs_buffer_count -= NO_OF_ENTRIES * count;
- update_MFSBQ_indx(fi, count);
- }
- return;
- }
- if (wrap_around) {
- int wrap_size = no_of_wrap_buffs * MFS_BUFFER_SIZE;
- int tail_size = payload_size - wrap_size;
- DPRINTK("wrap_size = %d, tail_size = %d\n", wrap_size, tail_size);
- if (no_of_wrap_buffs)
- memcpy(skb_put(skb, wrap_size), buff_addr, wrap_size);
- buff_addr = bus_to_virt(ntohl(*(fi->q.ptr_mfsbq_base)));
- memcpy(skb_put(skb, tail_size), buff_addr, tail_size);
- }
- else
- memcpy(skb_put(skb, payload_size), buff_addr, payload_size);
- rx_net_mfs_packet(fi, skb);
- break;
- default:
- T_MSG("Unknown Frame Type received. Type = %x", type_of_frame);
- }
-
- /* provide Tachyon will another set of buffers */
- fi->g.mfs_buffer_count += no_of_buffers;
- if (fi->g.mfs_buffer_count >= NO_OF_ENTRIES) {
- int count = fi->g.mfs_buffer_count / NO_OF_ENTRIES;
- fi->g.mfs_buffer_count -= NO_OF_ENTRIES * count;
- update_MFSBQ_indx(fi, count);
- }
- LEAVE("handle_MFS_interrupt");
-}
-
-static void handle_Unknown_Frame_interrupt(struct fc_info *fi)
-{
-u_int *ptr_imq_entry;
-int queue_indx, offset;
- ENTER("handle_Unknown_Frame_interrupt");
- ptr_imq_entry = fi->q.ptr_imqe[fi->q.imq_cons_indx];
- offset = ntohl(*(ptr_imq_entry + 1)) & 0x00000007;
- queue_indx = ntohl(*(ptr_imq_entry + 1)) & 0xFFFF0000;
- queue_indx = queue_indx >> 16;
- /* We discard the "unknown" frame */
- /* provide Tachyon will another set of buffers */
- if (offset == (NO_OF_ENTRIES - 1))
- update_SFSBQ_indx(fi);
- LEAVE("handle_Unknown_Frame_interrupt");
-}
-
-static void handle_Busied_Frame_interrupt(struct fc_info *fi)
-{
-u_int *ptr_imq_entry;
-int queue_indx, offset;
- ENTER("handle_Busied_Frame_interrupt");
- ptr_imq_entry = fi->q.ptr_imqe[fi->q.imq_cons_indx];
- offset = ntohl(*(ptr_imq_entry + 1)) & 0x00000007;
- queue_indx = ntohl(*(ptr_imq_entry + 1)) & 0xFFFF0000;
- queue_indx = queue_indx >> 16;
- /* We discard the "busied" frame */
- /* provide Tachyon will another set of buffers */
- if (offset == (NO_OF_ENTRIES - 1))
- update_SFSBQ_indx(fi);
- LEAVE("handle_Busied_Frame_interrupt");
-}
-
-static void handle_Bad_SCSI_Frame_interrupt(struct fc_info *fi)
-{
-u_int *ptr_imq_entry, *buff_addr, *tach_header, *ptr_edb;
-u_int s_id, rctl, frame_class, burst_len, transfered_len, len = 0;
-int queue_indx, offset, payload_size, i;
-u_short ox_id, rx_id, x_id, mtu = 512;
-u_char target_id = 0xFF;
-
- ENTER("handle_Bad_SCSI_Frame_interrupt");
- ptr_imq_entry = fi->q.ptr_imqe[fi->q.imq_cons_indx];
- offset = ntohl(*(ptr_imq_entry + 1)) & 0x00000007;
- queue_indx = ntohl(*(ptr_imq_entry + 1)) & 0xFFFF0000;
- queue_indx = queue_indx >> 16;
- payload_size = ntohl(*(ptr_imq_entry + 2));
-
- buff_addr = bus_to_virt(ntohl(*(fi->q.ptr_sfsbq_base + queue_indx*NO_OF_ENTRIES + offset)));
-
- rctl = ntohl(*(buff_addr + 2)) & 0xFF000000;
- s_id = ntohl(*(buff_addr + 3)) & 0x00FFFFFF;
- ox_id = ntohl(*(buff_addr + 6)) >> 16;
- rx_id = ntohl(*(buff_addr + 6));
- x_id = ox_id & MAX_SCSI_XID;
-
- /* Any frame that comes in with OX_ID that matches an OX_ID
- * that has been allocated for SCSI, will be called a Bad
- * SCSI frame if the Exchange is not valid any more.
- *
- * We will also get a Bad SCSI frame interrupt if we receive
- * a XFER_RDY with offset != 0. Tachyon washes its hands off
- * this Exchange. We have to take care of ourselves. Grrr...
- */
- if (rctl == DATA_DESCRIPTOR) {
- struct fc_node_info *q = fi->node_info_list;
- while (q != NULL) {
- if (q->d_id == s_id) {
- target_id = q->target_id;
- mtu = q->mtu;
- break;
- }
- else
- q = q->next;
- }
- frame_class = target_id;
- transfered_len = ntohl(*(buff_addr + 8));
- burst_len = ntohl(*(buff_addr + 9));
-
- build_ODB(fi, fi->g.seq_id, s_id, burst_len, 0, mtu, ox_id, rx_id, 0, 0, frame_class << 16);
- /* Update the SEQ_ID and Relative Offset in the
- * Tachyon Header Structure.
- */
- tach_header = bus_to_virt(ntohl(*(fi->q.ptr_sest[x_id] + 5)));
- *(tach_header + 5) = htonl(fi->g.seq_id << 24);
- *(tach_header + 7) = htonl(transfered_len);
- fi->g.odb.hdr_addr = *(fi->q.ptr_sest[x_id] + 5);
-
- /* Invalidate the EDBs used
- */
- ptr_edb = bus_to_virt(ntohl(*(fi->q.ptr_sest[x_id] + 7)));
-
- for (i = 0; i < EDB_LEN; i++)
- if (fi->q.ptr_edb[i] == ptr_edb)
- break;
- ptr_edb--;
-
- if (i < EDB_LEN) {
- int j;
- do {
- ptr_edb += 2;
- len += (htonl(*ptr_edb) & 0xFFFF);
- j = i;
- fi->q.free_edb_list[i++] = EDB_FREE;
- if (i == EDB_LEN) {
- i = 0;
- ptr_edb = fi->q.ptr_edb_base - 1;
- }
- } while (len < transfered_len);
- if (len > transfered_len) {
- ptr_edb--;
- fi->q.free_edb_list[j] = EDB_BUSY;
- }
- else
- ptr_edb++;
- }
- else {
- T_MSG("EDB not found while freeing");
- if (offset == (NO_OF_ENTRIES - 1))
- update_SFSBQ_indx(fi);
- return;
- }
-
- /* Update the EDB pointer in the ODB.
- */
- fi->g.odb.edb_addr = htonl(virt_to_bus(ptr_edb));
- memcpy(fi->q.ptr_odb[fi->q.ocq_prod_indx], &(fi->g.odb), sizeof(ODB));
- /* Update the EDB pointer in the SEST entry. We might need
- * this if get another XFER_RDY for the same Exchange.
- */
- *(fi->q.ptr_sest[x_id] + 7) = htonl(virt_to_bus(ptr_edb));
-
- update_OCQ_indx(fi);
- if (fi->g.seq_id == MAX_SEQ_ID)
- fi->g.seq_id = 0;
- else
- fi->g.seq_id++;
- }
- else
- /* Could be a BA_ACC or a BA_RJT.
- */
- if (rctl == RCTL_BASIC_ACC) {
- u_int bls_type = remove_from_ox_id_list(fi, ox_id);
- DPRINTK1("BA_ACC received from S_ID 0x%x with OX_ID = %x in response to %x", s_id, ox_id, bls_type);
- if (bls_type == RCTL_BASIC_ABTS) {
- u_int STE_bit;
- /* Invalidate resources for that Exchange.
- */
- STE_bit = ntohl(*fi->q.ptr_sest[x_id]);
- if (STE_bit & SEST_V) {
- *(fi->q.ptr_sest[x_id]) &= htonl(SEST_INV);
- invalidate_SEST_entry(fi, ox_id);
- }
- }
- }
- else
- if (rctl == RCTL_BASIC_RJT) {
- u_int bls_type = remove_from_ox_id_list(fi, ox_id);
- DPRINTK1("BA_RJT received from S_ID 0x%x with OX_ID = %x in response to %x", s_id, ox_id, bls_type);
- if (bls_type == RCTL_BASIC_ABTS) {
- u_int STE_bit;
- /* Invalidate resources for that Exchange.
- */
- STE_bit = ntohl(*fi->q.ptr_sest[x_id]);
- if (STE_bit & SEST_V) {
- *(fi->q.ptr_sest[x_id]) &= htonl(SEST_INV);
- invalidate_SEST_entry(fi, ox_id);
- }
- }
- }
- else
- DPRINTK1("Frame with R_CTL = %x received from S_ID 0x%x with OX_ID %x", rctl, s_id, ox_id);
-
- /* Else, discard the "Bad" SCSI frame.
- */
-
- /* provide Tachyon will another set of buffers
- */
- if (offset == (NO_OF_ENTRIES - 1))
- update_SFSBQ_indx(fi);
- LEAVE("handle_Bad_SCSI_Frame_interrupt");
-}
-
-static void handle_Inbound_SCSI_Status_interrupt(struct fc_info *fi)
-{
-struct Scsi_Host *host = fi->host;
-struct iph5526_hostdata *hostdata = (struct iph5526_hostdata *)host->hostdata;
-u_int *ptr_imq_entry, *buff_addr, *ptr_rsp_info, *ptr_sense_info = NULL;
-int queue_indx, offset, payload_size;
-u_short received_ox_id, x_id;
-Scsi_Cmnd *Cmnd;
-u_int fcp_status, fcp_rsp_info_len = 0, fcp_sense_info_len = 0, s_id;
- ENTER("handle_SCSI_status_interrupt");
-
- ptr_imq_entry = fi->q.ptr_imqe[fi->q.imq_cons_indx];
- offset = ntohl(*(ptr_imq_entry + 1)) & 0x00000007;
- queue_indx = ntohl(*(ptr_imq_entry + 1)) & 0xFFFF0000;
- queue_indx = queue_indx >> 16;
- buff_addr = bus_to_virt(ntohl(*(fi->q.ptr_sfsbq_base + queue_indx*NO_OF_ENTRIES + offset)));
- payload_size = ntohl(*(ptr_imq_entry + 2));
- received_ox_id = ntohl(*(buff_addr + 6)) >> 16;
-
- buff_addr = bus_to_virt(ntohl(*(fi->q.ptr_sfsbq_base + queue_indx*NO_OF_ENTRIES + offset)));
-
- fcp_status = ntohl(*(buff_addr + 10));
- ptr_rsp_info = buff_addr + 14;
- if (fcp_status & FCP_STATUS_RSP_LEN)
- fcp_rsp_info_len = ntohl(*(buff_addr + 13));
-
- if (fcp_status & FCP_STATUS_SENSE_LEN) {
- ptr_sense_info = ptr_rsp_info + fcp_rsp_info_len / 4;
- fcp_sense_info_len = ntohl(*(buff_addr + 12));
- DPRINTK("sense_info = %x", (u_int)ntohl(*ptr_sense_info));
- }
- DPRINTK("fcp_status = %x, fcp_rsp_len = %x", fcp_status, fcp_rsp_info_len);
- x_id = received_ox_id & MAX_SCSI_XID;
- Cmnd = hostdata->cmnd_handler[x_id];
- hostdata->cmnd_handler[x_id] = NULL;
- if (Cmnd != NULL) {
- memset(Cmnd->sense_buffer, 0, sizeof(Cmnd->sense_buffer));
- /* Check if there is a Sense field */
- if (fcp_status & FCP_STATUS_SENSE_LEN) {
- int size = sizeof(Cmnd->sense_buffer);
- if (fcp_sense_info_len < size)
- size = fcp_sense_info_len;
- memcpy(Cmnd->sense_buffer, (char *)ptr_sense_info, size);
- }
- Cmnd->result = fcp_status & FCP_STATUS_MASK;
- (*Cmnd->scsi_done) (Cmnd);
- }
- else
- T_MSG("NULL Command out of handler!");
-
- invalidate_SEST_entry(fi, received_ox_id);
- s_id = ntohl(*(buff_addr + 3)) & 0x00FFFFFF;
- fi->q.free_scsi_oxid[x_id] = OXID_AVAILABLE;
-
- /* provide Tachyon will another set of buffers */
- if (offset == (NO_OF_ENTRIES - 1))
- update_SFSBQ_indx(fi);
- LEAVE("handle_SCSI_status_interrupt");
-}
-
-static void invalidate_SEST_entry(struct fc_info *fi, u_short received_ox_id)
-{
-u_short x_id = received_ox_id & MAX_SCSI_XID;
- /* Invalidate SEST entry if it is an OutBound SEST Entry
- */
- if (!(received_ox_id & SCSI_READ_BIT)) {
- u_int *ptr_tach_header, *ptr_edb;
- u_short temp_ox_id = NOT_SCSI_XID;
- int i;
- *(fi->q.ptr_sest[x_id]) &= htonl(SEST_INV);
-
- /* Invalidate the Tachyon Header structure
- */
- ptr_tach_header = bus_to_virt(ntohl(*(fi->q.ptr_sest[x_id] + 5)));
- for (i = 0; i < NO_OF_TACH_HEADERS; i++)
- if(fi->q.ptr_tachyon_header[i] == ptr_tach_header)
- break;
- if (i < NO_OF_TACH_HEADERS)
- memset(ptr_tach_header, 0xFF, 32);
- else
- T_MSG("Tachyon Header not found while freeing in invalidate_SEST_entry()");
-
- /* Invalidate the EDB used
- */
- ptr_edb = bus_to_virt(ntohl(*(fi->q.ptr_sest[x_id] + 7)));
- for (i = 0; i < EDB_LEN; i++)
- if (fi->q.ptr_edb[i] == ptr_edb)
- break;
- ptr_edb--;
- if (i < EDB_LEN) {
- do {
- ptr_edb += 2;
- fi->q.free_edb_list[i++] = EDB_FREE;
- if (i == EDB_LEN) {
- i = 0;
- ptr_edb = fi->q.ptr_edb_base - 1;
- }
- } while ((htonl(*ptr_edb) & 0x80000000) != 0x80000000);
- }
- else
- T_MSG("EDB not found while freeing in invalidate_SEST_entry()");
-
- /* Search for its other header structure and destroy it!
- */
- if ((ptr_tach_header + 16) < (fi->q.ptr_tachyon_header_base + (MY_PAGE_SIZE/4)))
- ptr_tach_header += 16;
- else
- ptr_tach_header = fi->q.ptr_tachyon_header_base;
- while (temp_ox_id != x_id) {
- temp_ox_id = ntohl(*(ptr_tach_header + 6)) >> 16;
- if (temp_ox_id == x_id) {
- /* Paranoid checking...
- */
- for (i = 0; i < NO_OF_TACH_HEADERS; i++)
- if(fi->q.ptr_tachyon_header[i] == ptr_tach_header)
- break;
- if (i < NO_OF_TACH_HEADERS)
- memset(ptr_tach_header, 0xFF, 32);
- else
- T_MSG("Tachyon Header not found while freeing in invalidate_SEST_entry()");
- break;
- }
- else {
- if ((ptr_tach_header + 16) < (fi->q.ptr_tachyon_header_base + (MY_PAGE_SIZE/4)))
- ptr_tach_header += 16;
- else
- ptr_tach_header = fi->q.ptr_tachyon_header_base;
- }
- }
- }
- else {
- u_short sdb_table_indx;
- /* An Inbound Command has completed or needs to be Aborted.
- * Clear up the SDB buffers.
- */
- sdb_table_indx = *(fi->q.ptr_sest[x_id] + 5);
- fi->q.sdb_slot_status[sdb_table_indx] = SDB_FREE;
- }
-}
-
-static void handle_Inbound_SCSI_Command_interrupt(struct fc_info *fi)
-{
-u_int *ptr_imq_entry;
-int queue_indx, offset;
- ENTER("handle_Inbound_SCSI_Command_interrupt");
- ptr_imq_entry = fi->q.ptr_imqe[fi->q.imq_cons_indx];
- offset = ntohl(*(ptr_imq_entry + 1)) & 0x00000007;
- queue_indx = ntohl(*(ptr_imq_entry + 1)) & 0xFFFF0000;
- queue_indx = queue_indx >> 16;
- /* We discard the SCSI frame as we shouldn't be receiving
- * a SCSI Command in the first place
- */
- /* provide Tachyon will another set of buffers */
- if (offset == (NO_OF_ENTRIES - 1))
- update_SFSBQ_indx(fi);
- LEAVE("handle_Inbound_SCSI_Command_interrupt");
-}
-
-static void handle_SFS_interrupt(struct fc_info *fi)
-{
-u_int *ptr_imq_entry, *buff_addr;
-u_int class_of_frame, type_of_frame, s_id, els_type = 0, rctl;
-int queue_indx, offset, payload_size, login_state;
-u_short received_ox_id, fs_cmnd_code;
- ENTER("handle_SFS_interrupt");
- ptr_imq_entry = fi->q.ptr_imqe[fi->q.imq_cons_indx];
- offset = ntohl(*(ptr_imq_entry + 1)) & 0x00000007;
- queue_indx = ntohl(*(ptr_imq_entry + 1)) & 0xFFFF0000;
- queue_indx = queue_indx >> 16;
- DPRINTK("queue_indx = %d, offset = %d\n", queue_indx, offset);
- payload_size = ntohl(*(ptr_imq_entry + 2));
- DPRINTK("payload_size = %d", payload_size);
-
- buff_addr = bus_to_virt(ntohl(*(fi->q.ptr_sfsbq_base + queue_indx*NO_OF_ENTRIES + offset)));
-
- /* extract Type of Frame */
- type_of_frame = ntohl(*(buff_addr + 4)) & 0xFF000000;
- s_id = ntohl(*(buff_addr + 3)) & 0x00FFFFFF;
- received_ox_id = ntohl(*(buff_addr + 6)) >> 16;
- switch(type_of_frame) {
- case TYPE_BLS:
- rctl = ntohl(*(buff_addr + 2)) & 0xFF000000;
- switch(rctl) {
- case RCTL_BASIC_ABTS:
- /* As an Initiator, we should never be receiving
- * this.
- */
- DPRINTK1("ABTS received from S_ID 0x%x with OX_ID = %x", s_id, received_ox_id);
- break;
- }
- break;
- case TYPE_ELS:
- class_of_frame = ntohl(*(buff_addr + 8));
- login_state = sid_logged_in(fi, s_id);
- switch(class_of_frame & 0xFF000000) {
- case ELS_PLOGI:
- if (s_id != fi->g.my_id) {
- u_int ret_code;
- DPRINTK1("PLOGI received from D_ID 0x%x with 0X_ID = %x", s_id, received_ox_id);
- if ((ret_code = plogi_ok(fi, buff_addr, payload_size)) == 0){
- tx_logi_acc(fi, ELS_ACC, s_id, received_ox_id);
- add_to_address_cache(fi, buff_addr);
- }
- else {
- u_short cmnd_code = ret_code >> 16;
- u_short expln_code = ret_code;
- tx_ls_rjt(fi, s_id, received_ox_id, cmnd_code, expln_code);
- }
- }
- break;
- case ELS_ACC:
- els_type = remove_from_ox_id_list(fi, received_ox_id);
- DPRINTK1("ELS_ACC received from D_ID 0x%x in response to ELS %x", s_id, els_type);
- switch(els_type) {
- case ELS_PLOGI:
- add_to_address_cache(fi, buff_addr);
- tx_prli(fi, ELS_PRLI, s_id, OX_ID_FIRST_SEQUENCE);
- break;
- case ELS_FLOGI:
- add_to_address_cache(fi, buff_addr);
- fi->g.my_id = ntohl(*(buff_addr + 2)) & 0x00FFFFFF;
- fi->g.fabric_present = TRUE;
- fi->g.my_ddaa = fi->g.my_id & 0xFFFF00;
- /* Login to the Name Server
- */
- tx_logi(fi, ELS_PLOGI, DIRECTORY_SERVER);
- break;
- case ELS_NS_PLOGI:
- fi->g.name_server = TRUE;
- add_to_address_cache(fi, buff_addr);
- tx_name_server_req(fi, FCS_RFC_4);
- tx_scr(fi);
- /* Some devices have a delay before
- * registering with the Name Server
- */
- udelay(500);
- tx_name_server_req(fi, FCS_GP_ID4);
- break;
- case ELS_PRLI:
- mark_scsi_sid(fi, buff_addr, ADD_ENTRY);
- break;
- case ELS_ADISC:
- if (!(validate_login(fi, buff_addr)))
- tx_logo(fi, s_id, OX_ID_FIRST_SEQUENCE);
- break;
- }
- break;
- case ELS_PDISC:
- DPRINTK1("ELS_PDISC received from D_ID 0x%x", s_id);
- tx_logo(fi, s_id, received_ox_id);
- break;
- case ELS_ADISC:
- DPRINTK1("ELS_ADISC received from D_ID 0x%x", s_id);
- if (node_logged_in_prev(fi, buff_addr))
- tx_adisc(fi, ELS_ACC, s_id, received_ox_id);
- else
- tx_logo(fi, s_id, received_ox_id);
- break;
- case ELS_PRLI:
- DPRINTK1("ELS_PRLI received from D_ID 0x%x", s_id);
- if ((login_state == NODE_LOGGED_IN) || (login_state == NODE_PROCESS_LOGGED_IN)) {
- tx_prli(fi, ELS_ACC, s_id, received_ox_id);
- mark_scsi_sid(fi, buff_addr, ADD_ENTRY);
- }
- else
- tx_logo(fi, s_id, received_ox_id);
- break;
- case ELS_PRLO:
- DPRINTK1("ELS_PRLO received from D_ID 0x%x", s_id);
- if ((login_state == NODE_LOGGED_OUT) || (login_state == NODE_NOT_PRESENT))
- tx_logo(fi, s_id, received_ox_id);
- else
- if (login_state == NODE_LOGGED_IN)
-
- tx_ls_rjt(fi, s_id, received_ox_id, CMND_NOT_SUPP, NO_EXPLN);
- else
- if (login_state == NODE_PROCESS_LOGGED_IN) {
- tx_prli(fi, ELS_ACC, s_id, received_ox_id);
- mark_scsi_sid(fi, buff_addr, DELETE_ENTRY);
- }
- break;
- case ELS_LS_RJT:
- els_type = remove_from_ox_id_list(fi, received_ox_id);
- DPRINTK1("ELS_LS_RJT received from D_ID 0x%x in response to %x", s_id, els_type);
- /* We should be chking the reason code.
- */
- switch (els_type) {
- case ELS_ADISC:
- tx_logi(fi, ELS_PLOGI, s_id);
- break;
- }
- break;
- case ELS_LOGO:
- els_type = remove_from_ox_id_list(fi, received_ox_id);
- DPRINTK1("ELS_LOGO received from D_ID 0x%x in response to %x", s_id, els_type);
- remove_from_address_cache(fi, buff_addr, ELS_LOGO);
- tx_acc(fi, s_id, received_ox_id);
- if (els_type == ELS_ADISC)
- tx_logi(fi, ELS_PLOGI, s_id);
- break;
- case ELS_RSCN:
- DPRINTK1("ELS_RSCN received from D_ID 0x%x", s_id);
- tx_acc(fi, s_id, received_ox_id);
- remove_from_address_cache(fi, buff_addr, ELS_RSCN);
- break;
- case ELS_FARP_REQ:
- /* We do not support FARP.
- So, silently discard it */
- DPRINTK1("ELS_FARP_REQ received from D_ID 0x%x", s_id);
- break;
- case ELS_ABTX:
- DPRINTK1("ELS_ABTX received from D_ID 0x%x", s_id);
- if ((login_state == NODE_LOGGED_IN) || (login_state == NODE_PROCESS_LOGGED_IN))
- tx_ls_rjt(fi, s_id, received_ox_id, CMND_NOT_SUPP, NO_EXPLN);
- else
- tx_logo(fi, s_id, received_ox_id);
- break;
- case ELS_FLOGI:
- DPRINTK1("ELS_FLOGI received from D_ID 0x%x", s_id);
- if (fi->g.ptp_up == TRUE) {
- /* The node could have come up as an N_Port
- * in a Loop! So,try initializing as an NL_port
- */
- take_tachyon_offline(fi);
- /* write AL_TIME & E_D_TOV into the registers */
- writel(TOV_VALUES, fi->t_r.ptr_fm_tov_reg);
- writel(LOOP_INIT_SOFT_ADDRESS, fi->t_r.ptr_fm_config_reg);
- DPRINTK1("FLOGI received, TACHYON initializing as L_Port...\n");
- writel(INITIALIZE, fi->t_r.ptr_fm_control_reg);
- }
- else {
- if ((login_state == NODE_LOGGED_IN) || (login_state == NODE_PROCESS_LOGGED_IN))
- tx_ls_rjt(fi, s_id, received_ox_id, CMND_NOT_SUPP, NO_EXPLN);
- else
- tx_logo(fi, s_id, received_ox_id);
- }
- break;
- case ELS_ADVC:
- DPRINTK1("ELS_ADVC received from D_ID 0x%x", s_id);
- if ((login_state == NODE_LOGGED_IN) || (login_state == NODE_PROCESS_LOGGED_IN))
- tx_ls_rjt(fi, s_id, received_ox_id, CMND_NOT_SUPP, NO_EXPLN);
- else
- tx_logo(fi, s_id, received_ox_id);
- break;
- case ELS_ECHO:
- DPRINTK1("ELS_ECHO received from D_ID 0x%x", s_id);
- if ((login_state == NODE_LOGGED_IN) || (login_state == NODE_PROCESS_LOGGED_IN))
- tx_ls_rjt(fi, s_id, received_ox_id, CMND_NOT_SUPP, NO_EXPLN);
- else
- tx_logo(fi, s_id, received_ox_id);
- break;
- case ELS_ESTC:
- DPRINTK1("ELS_ESTC received from D_ID 0x%x", s_id);
- if ((login_state == NODE_LOGGED_IN) || (login_state == NODE_PROCESS_LOGGED_IN))
- tx_ls_rjt(fi, s_id, received_ox_id, CMND_NOT_SUPP, NO_EXPLN);
- else
- tx_logo(fi, s_id, received_ox_id);
- break;
- case ELS_ESTS:
- DPRINTK1("ELS_ESTS received from D_ID 0x%x", s_id);
- if ((login_state == NODE_LOGGED_IN) || (login_state == NODE_PROCESS_LOGGED_IN))
- tx_ls_rjt(fi, s_id, received_ox_id, CMND_NOT_SUPP, NO_EXPLN);
- else
- tx_logo(fi, s_id, received_ox_id);
- break;
- case ELS_RCS:
- DPRINTK1("ELS_RCS received from D_ID 0x%x", s_id);
- if ((login_state == NODE_LOGGED_IN) || (login_state == NODE_PROCESS_LOGGED_IN))
- tx_ls_rjt(fi, s_id, received_ox_id, CMND_NOT_SUPP, NO_EXPLN);
- else
- tx_logo(fi, s_id, received_ox_id);
- break;
- case ELS_RES:
- DPRINTK1("ELS_RES received from D_ID 0x%x", s_id);
- if ((login_state == NODE_LOGGED_IN) || (login_state == NODE_PROCESS_LOGGED_IN))
- tx_ls_rjt(fi, s_id, received_ox_id, CMND_NOT_SUPP, NO_EXPLN);
- else
- tx_logo(fi, s_id, received_ox_id);
- break;
- case ELS_RLS:
- DPRINTK1("ELS_RLS received from D_ID 0x%x", s_id);
- if ((login_state == NODE_LOGGED_IN) || (login_state == NODE_PROCESS_LOGGED_IN))
- tx_ls_rjt(fi, s_id, received_ox_id, CMND_NOT_SUPP, NO_EXPLN);
- else
- tx_logo(fi, s_id, received_ox_id);
- break;
- case ELS_RRQ:
- DPRINTK1("ELS_RRQ received from D_ID 0x%x", s_id);
- if ((login_state == NODE_LOGGED_IN) || (login_state == NODE_PROCESS_LOGGED_IN))
- tx_ls_rjt(fi, s_id, received_ox_id, CMND_NOT_SUPP, NO_EXPLN);
- else
- tx_logo(fi, s_id, received_ox_id);
- break;
- case ELS_RSS:
- DPRINTK1("ELS_RSS received from D_ID 0x%x", s_id);
- if ((login_state == NODE_LOGGED_IN) || (login_state == NODE_PROCESS_LOGGED_IN))
- tx_ls_rjt(fi, s_id, received_ox_id, CMND_NOT_SUPP, NO_EXPLN);
- else
- tx_logo(fi, s_id, received_ox_id);
- break;
- case ELS_RTV:
- DPRINTK1("ELS_RTV received from D_ID 0x%x", s_id);
- if ((login_state == NODE_LOGGED_IN) || (login_state == NODE_PROCESS_LOGGED_IN))
- tx_ls_rjt(fi, s_id, received_ox_id, CMND_NOT_SUPP, NO_EXPLN);
- else
- tx_logo(fi, s_id, received_ox_id);
- break;
- case ELS_RSI:
- DPRINTK1("ELS_RSI received from D_ID 0x%x", s_id);
- if ((login_state == NODE_LOGGED_IN) || (login_state == NODE_PROCESS_LOGGED_IN))
- tx_ls_rjt(fi, s_id, received_ox_id, CMND_NOT_SUPP, NO_EXPLN);
- else
- tx_logo(fi, s_id, received_ox_id);
- break;
- case ELS_TEST:
- /* No reply sequence */
- DPRINTK1("ELS_TEST received from D_ID 0x%x", s_id);
- break;
- case ELS_RNC:
- DPRINTK1("ELS_RNC received from D_ID 0x%x", s_id);
- if ((login_state == NODE_LOGGED_IN) || (login_state == NODE_PROCESS_LOGGED_IN))
- tx_ls_rjt(fi, s_id, received_ox_id, CMND_NOT_SUPP, NO_EXPLN);
- else
- tx_logo(fi, s_id, received_ox_id);
- break;
- case ELS_RVCS:
- DPRINTK1("ELS_RVCS received from D_ID 0x%x", s_id);
- if ((login_state == NODE_LOGGED_IN) || (login_state == NODE_PROCESS_LOGGED_IN))
- tx_ls_rjt(fi, s_id, received_ox_id, CMND_NOT_SUPP, NO_EXPLN);
- else
- tx_logo(fi, s_id, received_ox_id);
- break;
- case ELS_TPLS:
- DPRINTK1("ELS_TPLS received from D_ID 0x%x", s_id);
- if ((login_state == NODE_LOGGED_IN) || (login_state == NODE_PROCESS_LOGGED_IN))
- tx_ls_rjt(fi, s_id, received_ox_id, CMND_NOT_SUPP, NO_EXPLN);
- else
- tx_logo(fi, s_id, received_ox_id);
- break;
- case ELS_GAID:
- DPRINTK1("ELS_GAID received from D_ID 0x%x", s_id);
- if ((login_state == NODE_LOGGED_IN) || (login_state == NODE_PROCESS_LOGGED_IN))
- tx_ls_rjt(fi, s_id, received_ox_id, CMND_NOT_SUPP, NO_EXPLN);
- else
- tx_logo(fi, s_id, received_ox_id);
- break;
- case ELS_FACT:
- DPRINTK1("ELS_FACT received from D_ID 0x%x", s_id);
- if ((login_state == NODE_LOGGED_IN) || (login_state == NODE_PROCESS_LOGGED_IN))
- tx_ls_rjt(fi, s_id, received_ox_id, CMND_NOT_SUPP, NO_EXPLN);
- else
- tx_logo(fi, s_id, received_ox_id);
- break;
- case ELS_FAN:
- /* Hmmm... You don't support FAN ??? */
- DPRINTK1("ELS_FAN received from D_ID 0x%x", s_id);
- tx_ls_rjt(fi, s_id, received_ox_id, CMND_NOT_SUPP, NO_EXPLN);
- break;
- case ELS_FDACT:
- DPRINTK1("ELS_FDACT received from D_ID 0x%x", s_id);
- if ((login_state == NODE_LOGGED_IN) || (login_state == NODE_PROCESS_LOGGED_IN))
- tx_ls_rjt(fi, s_id, received_ox_id, CMND_NOT_SUPP, NO_EXPLN);
- else
- tx_logo(fi, s_id, received_ox_id);
- break;
- case ELS_NACT:
- DPRINTK1("ELS_NACT received from D_ID 0x%x", s_id);
- if ((login_state == NODE_LOGGED_IN) || (login_state == NODE_PROCESS_LOGGED_IN))
- tx_ls_rjt(fi, s_id, received_ox_id, CMND_NOT_SUPP, NO_EXPLN);
- else
- tx_logo(fi, s_id, received_ox_id);
- break;
- case ELS_NDACT:
- DPRINTK1("ELS_NDACT received from D_ID 0x%x", s_id);
- if ((login_state == NODE_LOGGED_IN) || (login_state == NODE_PROCESS_LOGGED_IN))
- tx_ls_rjt(fi, s_id, received_ox_id, CMND_NOT_SUPP, NO_EXPLN);
- else
- tx_logo(fi, s_id, received_ox_id);
- break;
- case ELS_QoSR:
- DPRINTK1("ELS_QoSR received from D_ID 0x%x", s_id);
- if ((login_state == NODE_LOGGED_IN) || (login_state == NODE_PROCESS_LOGGED_IN))
- tx_ls_rjt(fi, s_id, received_ox_id, CMND_NOT_SUPP, NO_EXPLN);
- else
- tx_logo(fi, s_id, received_ox_id);
- break;
- case ELS_FDISC:
- DPRINTK1("ELS_FDISC received from D_ID 0x%x", s_id);
- if ((login_state == NODE_LOGGED_IN) || (login_state == NODE_PROCESS_LOGGED_IN))
- tx_ls_rjt(fi, s_id, received_ox_id, CMND_NOT_SUPP, NO_EXPLN);
- else
- tx_logo(fi, s_id, received_ox_id);
- break;
- default:
- DPRINTK1("ELS Frame %x received from D_ID 0x%x", class_of_frame, s_id);
- if ((login_state == NODE_LOGGED_IN) || (login_state == NODE_PROCESS_LOGGED_IN))
- tx_ls_rjt(fi, s_id, received_ox_id, CMND_NOT_SUPP, NO_EXPLN);
- else
- tx_logo(fi, s_id, received_ox_id);
- break;
- }
- break;
- case TYPE_FC_SERVICES:
- fs_cmnd_code = (ntohl(*(buff_addr + 10)) & 0xFFFF0000) >>16;
- switch(fs_cmnd_code) {
- case FCS_ACC:
- els_type = remove_from_ox_id_list(fi, received_ox_id);
- DPRINTK1("FCS_ACC received from D_ID 0x%x in response to %x", s_id, els_type);
- if (els_type == FCS_GP_ID4)
- explore_fabric(fi, buff_addr);
- break;
- case FCS_REJECT:
- DPRINTK1("FCS_REJECT received from D_ID 0x%x in response to %x", s_id, els_type);
- break;
- }
- break;
- case TYPE_LLC_SNAP:
- rx_net_packet(fi, (u_char *)buff_addr, payload_size);
- break;
- default:
- T_MSG("Frame Type %x received from %x", type_of_frame, s_id);
- }
-
- /* provide Tachyon will another set of buffers */
- if (offset == (NO_OF_ENTRIES - 1))
- update_SFSBQ_indx(fi);
- LEAVE("handle_SFS_interrupt");
-}
-
-static void handle_FM_interrupt(struct fc_info *fi)
-{
-u_int fm_status;
-u_int tachyon_status;
-
- ENTER("handle_FM_interrupt");
- fm_status = readl(fi->t_r.ptr_fm_status_reg);
- tachyon_status = readl(fi->t_r.ptr_tach_status_reg);
- DPRINTK("FM_status = %x, Tachyon_status = %x", fm_status, tachyon_status);
- if (fm_status & LINK_DOWN) {
- T_MSG("Fibre Channel Link DOWN");
- fm_status = readl(fi->t_r.ptr_fm_status_reg);
-
- del_timer(&fi->explore_timer);
- del_timer(&fi->nport_timer);
- del_timer(&fi->lport_timer);
- del_timer(&fi->display_cache_timer);
- fi->g.link_up = FALSE;
- if (fi->g.ptp_up == TRUE)
- fi->g.n_port_try = FALSE;
- fi->g.ptp_up = FALSE;
- fi->g.port_discovery = FALSE;
- fi->g.explore_fabric = FALSE;
- fi->g.perform_adisc = FALSE;
-
- /* Logout will all nodes */
- if (fi->node_info_list) {
- struct fc_node_info *temp_list = fi->node_info_list;
- while(temp_list) {
- temp_list->login = LOGIN_ATTEMPTED;
- temp_list = temp_list->next;
- }
- fi->num_nodes = 0;
- }
-
- if ((fi->g.n_port_try == FALSE) && (fi->g.dont_init == FALSE)){
- take_tachyon_offline(fi);
- /* write AL_TIME & E_D_TOV into the registers */
- writel(TOV_VALUES, fi->t_r.ptr_fm_tov_reg);
-
- if ((fi->g.fabric_present == TRUE) && (fi->g.loop_up == TRUE)) {
- u_int al_pa = fi->g.my_id & 0xFF;
- writel((al_pa << 24) | LOOP_INIT_FABRIC_ADDRESS | LOOP_INIT_PREVIOUS_ADDRESS, fi->t_r.ptr_fm_config_reg);
- }
- else
- if (fi->g.loop_up == TRUE) {
- u_int al_pa = fi->g.my_id & 0xFF;
- writel((al_pa << 24) | LOOP_INIT_PREVIOUS_ADDRESS, fi->t_r.ptr_fm_config_reg);
- }
- else
- writel(LOOP_INIT_SOFT_ADDRESS, fi->t_r.ptr_fm_config_reg);
- fi->g.loop_up = FALSE;
- DPRINTK1("In LDWN TACHYON initializing as L_Port...\n");
- writel(INITIALIZE, fi->t_r.ptr_fm_control_reg);
- }
- }
-
- if (fm_status & NON_PARTICIPATING) {
- T_MSG("Did not acquire an AL_PA. I am not participating");
- }
- else
- if ((fm_status & LINK_UP) && ((fm_status & LINK_DOWN) == 0)) {
- T_MSG("Fibre Channel Link UP");
- if ((fm_status & NON_PARTICIPATING) != TRUE) {
- fi->g.link_up = TRUE;
- if (tachyon_status & OSM_FROZEN) {
- reset_tachyon(fi, ERROR_RELEASE);
- reset_tachyon(fi, OCQ_RESET);
- }
- init_timer(&fi->explore_timer);
- init_timer(&fi->nport_timer);
- init_timer(&fi->lport_timer);
- init_timer(&fi->display_cache_timer);
- if ((fm_status & OLD_PORT) == 0) {
- fi->g.loop_up = TRUE;
- fi->g.ptp_up = FALSE;
- fi->g.my_id = readl(fi->t_r.ptr_fm_config_reg) >> 24;
- DPRINTK1("My AL_PA = %x", fi->g.my_id);
- fi->g.port_discovery = TRUE;
- fi->g.explore_fabric = FALSE;
- }
- else
- if (((fm_status & 0xF0) == OLD_PORT) && ((fm_status & 0x0F) == PORT_STATE_ACTIVE)) {
- fi->g.loop_up = FALSE;
- fi->g.my_id = 0x0;
- /* In a point-to-point configuration, we expect to be
- * connected to an F_Port. This driver does not yet support
- * a configuration where it is connected to another N_Port
- * directly.
- */
- fi->g.explore_fabric = TRUE;
- fi->g.port_discovery = FALSE;
- if (fi->g.n_port_try == FALSE) {
- take_tachyon_offline(fi);
- /* write R_T_TOV & E_D_TOV into the registers */
- writel(PTP_TOV_VALUES, fi->t_r.ptr_fm_tov_reg);
- writel(BB_CREDIT | NPORT, fi->t_r.ptr_fm_config_reg);
- fi->g.n_port_try = TRUE;
- DPRINTK1("In LUP TACHYON initializing as N_Port...\n");
- writel(INITIALIZE, fi->t_r.ptr_fm_control_reg);
- }
- else {
- fi->g.ptp_up = TRUE;
- tx_logi(fi, ELS_FLOGI, F_PORT);
- }
- }
- fi->g.my_ddaa = 0x0;
- fi->g.fabric_present = FALSE;
- /* We havn't sent out any Name Server Reqs */
- fi->g.name_server = FALSE;
- fi->g.alpa_list_index = 0;
- fi->g.ox_id = NOT_SCSI_XID;
- fi->g.my_mtu = TACH_FRAME_SIZE;
-
- /* Implicitly LOGO with all logged-in nodes.
- */
- if (fi->node_info_list) {
- struct fc_node_info *temp_list = fi->node_info_list;
- while(temp_list) {
- temp_list->login = LOGIN_ATTEMPTED;
- temp_list = temp_list->next;
- }
- fi->num_nodes = 0;
- fi->g.perform_adisc = TRUE;
- //fi->g.perform_adisc = FALSE;
- fi->g.port_discovery = FALSE;
- tx_logi(fi, ELS_FLOGI, F_PORT);
- }
- else {
- /* If Link coming up for the _first_ time or no nodes
- * were logged in before...
- */
- fi->g.scsi_oxid = 0;
- fi->g.seq_id = 0x00;
- fi->g.perform_adisc = FALSE;
- }
-
- /* reset OX_ID table */
- while (fi->ox_id_list) {
- struct ox_id_els_map *temp = fi->ox_id_list;
- fi->ox_id_list = fi->ox_id_list->next;
- kfree(temp);
- }
- fi->ox_id_list = NULL;
- } /* End of if partipating */
- }
-
- if (fm_status & ELASTIC_STORE_ERROR) {
- /* Too much junk on the Link
- */
- /* Trying to clear it up by Txing PLOGI to urself */
- if (fi->g.link_up == TRUE)
- tx_logi(fi, ELS_PLOGI, fi->g.my_id);
- }
-
- if (fm_status & LOOP_UP) {
- if (tachyon_status & OSM_FROZEN) {
- reset_tachyon(fi, ERROR_RELEASE);
- reset_tachyon(fi, OCQ_RESET);
- }
- }
-
- if (fm_status & NOS_OLS_RECEIVED){
- if (fi->g.nport_timer_set == FALSE) {
- DPRINTK("NOS/OLS Received");
- DPRINTK("FM_status = %x", fm_status);
- fi->nport_timer.function = nos_ols_timer;
- fi->nport_timer.data = (unsigned long)fi;
- fi->nport_timer.expires = RUN_AT((3*HZ)/100); /* 30 msec */
- init_timer(&fi->nport_timer);
- add_timer(&fi->nport_timer);
- fi->g.nport_timer_set = TRUE;
- }
- }
-
- if (((fm_status & 0xF0) == OLD_PORT) && (((fm_status & 0x0F) == PORT_STATE_LF1) || ((fm_status & 0x0F) == PORT_STATE_LF2))) {
- DPRINTK1("Link Fail-I in OLD-PORT.");
- take_tachyon_offline(fi);
- reset_tachyon(fi, SOFTWARE_RESET);
- }
-
- if (fm_status & LOOP_STATE_TIMEOUT){
- if ((fm_status & 0xF0) == ARBITRATING)
- DPRINTK1("ED_TOV timesout.In ARBITRATING state...");
- if ((fm_status & 0xF0) == ARB_WON)
- DPRINTK1("ED_TOV timesout.In ARBITRATION WON state...");
- if ((fm_status & 0xF0) == OPEN)
- DPRINTK1("ED_TOV timesout.In OPEN state...");
- if ((fm_status & 0xF0) == OPENED)
- DPRINTK1("ED_TOV timesout.In OPENED state...");
- if ((fm_status & 0xF0) == TX_CLS)
- DPRINTK1("ED_TOV timesout.In XMITTED CLOSE state...");
- if ((fm_status & 0xF0) == RX_CLS)
- DPRINTK1("ED_TOV timesout.In RECEIVED CLOSE state...");
- if ((fm_status & 0xF0) == INITIALIZING)
- DPRINTK1("ED_TOV timesout.In INITIALIZING state...");
- DPRINTK1("Initializing Loop...");
- writel(INITIALIZE, fi->t_r.ptr_fm_control_reg);
- }
-
- if ((fm_status & BAD_ALPA) && (fi->g.loop_up == TRUE)) {
- u_char bad_alpa = (readl(fi->t_r.ptr_fm_rx_al_pa_reg) & 0xFF00) >> 8;
- if (tachyon_status & OSM_FROZEN) {
- reset_tachyon(fi, ERROR_RELEASE);
- reset_tachyon(fi, OCQ_RESET);
- }
- /* Fix for B34 */
- tx_logi(fi, ELS_PLOGI, fi->g.my_id);
-
- if (!fi->g.port_discovery && !fi->g.perform_adisc) {
- if (bad_alpa != 0xFE)
- DPRINTK("Bad AL_PA = %x", bad_alpa);
- }
- else {
- if ((fi->g.perform_adisc == TRUE) && (bad_alpa == 0x00)) {
- DPRINTK1("Performing ADISC...");
- fi->g.fabric_present = FALSE;
- perform_adisc(fi);
- }
- }
- }
-
- if (fm_status & LIPF_RECEIVED){
- DPRINTK("LIP(F8) Received");
- }
-
- if (fm_status & LINK_FAILURE) {
- if (fm_status & LOSS_OF_SIGNAL)
- DPRINTK1("Detected Loss of Signal.");
- if (fm_status & OUT_OF_SYNC)
- DPRINTK1("Detected Loss of Synchronization.");
- }
-
- if (fm_status & TRANSMIT_PARITY_ERROR) {
- /* Bad! Should not happen. Solution-> Hard Reset.
- */
- T_MSG("Parity Error. Perform Hard Reset!");
- }
-
- if (fi->g.alpa_list_index >= MAX_NODES){
- if (fi->g.port_discovery == TRUE) {
- fi->g.port_discovery = FALSE;
- add_display_cache_timer(fi);
- }
- fi->g.alpa_list_index = MAX_NODES;
- }
-
- if (fi->g.port_discovery == TRUE)
- local_port_discovery(fi);
-
- LEAVE("handle_FM_interrupt");
- return;
-}
-
-static void local_port_discovery(struct fc_info *fi)
-{
- if (fi->g.loop_up == TRUE) {
- /* If this is not here, some of the Bad AL_PAs are missed.
- */
- udelay(20);
- if ((fi->g.alpa_list_index == 0) && (fi->g.fabric_present == FALSE)){
- tx_logi(fi, ELS_FLOGI, F_PORT);
- }
- else {
- int login_state = sid_logged_in(fi, fi->g.my_ddaa | alpa_list[fi->g.alpa_list_index]);
- while ((fi->g.alpa_list_index == 0) || ((fi->g.alpa_list_index < MAX_NODES) && ((login_state == NODE_LOGGED_IN) || (login_state == NODE_PROCESS_LOGGED_IN) || (alpa_list[fi->g.alpa_list_index] == (fi->g.my_id & 0xFF)))))
- fi->g.alpa_list_index++;
- if (fi->g.alpa_list_index < MAX_NODES)
- tx_logi(fi, ELS_PLOGI, alpa_list[fi->g.alpa_list_index]);
- }
- fi->g.alpa_list_index++;
- if (fi->g.alpa_list_index >= MAX_NODES){
- if (fi->g.port_discovery == TRUE) {
- fi->g.port_discovery = FALSE;
- add_display_cache_timer(fi);
- }
- fi->g.alpa_list_index = MAX_NODES;
- }
- }
-}
-
-static void nos_ols_timer(unsigned long data)
-{
-struct fc_info *fi = (struct fc_info*)data;
-u_int fm_status;
- fm_status = readl(fi->t_r.ptr_fm_status_reg);
- DPRINTK1("FM_status in timer= %x", fm_status);
- fi->g.nport_timer_set = FALSE;
- del_timer(&fi->nport_timer);
- if ((fi->g.ptp_up == TRUE) || (fi->g.loop_up == TRUE))
- return;
- if (((fm_status & 0xF0) == OLD_PORT) && (((fm_status & 0x0F) == PORT_STATE_ACTIVE) || ((fm_status & 0x0F) == PORT_STATE_OFFLINE))) {
- DPRINTK1("In OLD-PORT after E_D_TOV.");
- take_tachyon_offline(fi);
- /* write R_T_TOV & E_D_TOV into the registers */
- writel(PTP_TOV_VALUES, fi->t_r.ptr_fm_tov_reg);
- writel(BB_CREDIT | NPORT, fi->t_r.ptr_fm_config_reg);
- fi->g.n_port_try = TRUE;
- DPRINTK1("In timer, TACHYON initializing as N_Port...\n");
- writel(INITIALIZE, fi->t_r.ptr_fm_control_reg);
- }
- else
- if ((fi->g.lport_timer_set == FALSE) && ((fm_status & 0xF0) == LOOP_FAIL)) {
- DPRINTK1("Loop Fail after E_D_TOV.");
- fi->lport_timer.function = loop_timer;
- fi->lport_timer.data = (unsigned long)fi;
- fi->lport_timer.expires = RUN_AT((8*HZ)/100);
- init_timer(&fi->lport_timer);
- add_timer(&fi->lport_timer);
- fi->g.lport_timer_set = TRUE;
- take_tachyon_offline(fi);
- reset_tachyon(fi, SOFTWARE_RESET);
- }
- else
- if (((fm_status & 0xF0) == OLD_PORT) && (((fm_status & 0x0F) == PORT_STATE_LF1) || ((fm_status & 0x0F) == PORT_STATE_LF2))) {
- DPRINTK1("Link Fail-II in OLD-PORT.");
- take_tachyon_offline(fi);
- reset_tachyon(fi, SOFTWARE_RESET);
- }
-}
-
-static void loop_timer(unsigned long data)
-{
-struct fc_info *fi = (struct fc_info*)data;
- fi->g.lport_timer_set = FALSE;
- del_timer(&fi->lport_timer);
- if ((fi->g.ptp_up == TRUE) || (fi->g.loop_up == TRUE))
- return;
-}
-
-static void add_display_cache_timer(struct fc_info *fi)
-{
- fi->display_cache_timer.function = display_cache_timer;
- fi->display_cache_timer.data = (unsigned long)fi;
- fi->display_cache_timer.expires = RUN_AT(fi->num_nodes * HZ);
- init_timer(&fi->display_cache_timer);
- add_timer(&fi->display_cache_timer);
-}
-
-static void display_cache_timer(unsigned long data)
-{
-struct fc_info *fi = (struct fc_info*)data;
- del_timer(&fi->display_cache_timer);
- display_cache(fi);
- return;
-}
-
-static void reset_tachyon(struct fc_info *fi, u_int value)
-{
-u_int tachyon_status, reset_done = OCQ_RESET_STATUS | SCSI_FREEZE_STATUS;
-int not_done = 1, i = 0;
- writel(value, fi->t_r.ptr_tach_control_reg);
- if (value == OCQ_RESET)
- fi->q.ocq_prod_indx = 0;
- tachyon_status = readl(fi->t_r.ptr_tach_status_reg);
-
- /* Software resets are immediately done, whereas other aren't. It
- about 30 clocks to do the reset */
- if (value != SOFTWARE_RESET) {
- while(not_done) {
- if (i++ > 100000) {
- T_MSG("Reset was unsuccessful! Tachyon Status = %x", tachyon_status);
- break;
- }
- tachyon_status = readl(fi->t_r.ptr_tach_status_reg);
- if ((tachyon_status & reset_done) == 0)
- not_done = 0;
- }
- }
- else {
- write_to_tachyon_registers(fi);
- }
-}
-
-static void take_tachyon_offline(struct fc_info *fi)
-{
-u_int fm_status = readl(fi->t_r.ptr_fm_status_reg);
-
- /* The first two conditions will never be true. The Manual and
- * the errata say this. But the current implementation is
- * decently stable.
- */
- //if ((fm_status & 0xF0) == LOOP_FAIL) {
- if (fm_status == LOOP_FAIL) {
- // workaround as in P. 89
- writel(HOST_CONTROL, fi->t_r.ptr_fm_control_reg);
- if (fi->g.loop_up == TRUE)
- writel(SOFTWARE_RESET, fi->t_r.ptr_tach_control_reg);
- else {
- writel(OFFLINE, fi->t_r.ptr_fm_control_reg);
- writel(EXIT_HOST_CONTROL, fi->t_r.ptr_fm_control_reg);
- }
- }
- else
- //if ((fm_status & LOOP_UP) == LOOP_UP) {
- if (fm_status == LOOP_UP) {
- writel(SOFTWARE_RESET, fi->t_r.ptr_tach_control_reg);
- }
- else
- writel(OFFLINE, fi->t_r.ptr_fm_control_reg);
-}
-
-
-static void read_novram(struct fc_info *fi)
-{
-int off = 0;
- fi->n_r.ptr_novram_hw_control_reg = fi->i_r.ptr_ichip_hw_control_reg;
- fi->n_r.ptr_novram_hw_status_reg = fi->i_r.ptr_ichip_hw_status_reg;
- iph5526_nr_do_init(fi);
- if (fi->clone_id == PCI_VENDOR_ID_INTERPHASE)
- off = 32;
-
- fi->g.my_node_name_high = (fi->n_r.data[off] << 16) | fi->n_r.data[off+1];
- fi->g.my_node_name_low = (fi->n_r.data[off+2] << 16) | fi->n_r.data[off+3];
- fi->g.my_port_name_high = (fi->n_r.data[off+4] << 16) | fi->n_r.data[off+5];
- fi->g.my_port_name_low = (fi->n_r.data[off+6] << 16) | fi->n_r.data[off+7];
- DPRINTK("node_name = %x %x", fi->g.my_node_name_high, fi->g.my_node_name_low);
- DPRINTK("port_name = %x %x", fi->g.my_port_name_high, fi->g.my_port_name_low);
-}
-
-static void reset_ichip(struct fc_info *fi)
-{
- /* (i)chip reset */
- writel(ICHIP_HCR_RESET, fi->i_r.ptr_ichip_hw_control_reg);
- /*wait for chip to get reset */
- mdelay(10);
- /*de-assert reset */
- writel(ICHIP_HCR_DERESET, fi->i_r.ptr_ichip_hw_control_reg);
-
- /* enable INT lines on the (i)chip */
- writel(ICHIP_HCR_ENABLE_INTA , fi->i_r.ptr_ichip_hw_control_reg);
- /* enable byte swap */
- writel(ICHIP_HAMR_BYTE_SWAP_ADDR_TR, fi->i_r.ptr_ichip_hw_addr_mask_reg);
-}
-
-static void tx_logi(struct fc_info *fi, u_int logi, u_int d_id)
-{
-int int_required = 1;
-u_short ox_id = OX_ID_FIRST_SEQUENCE;
-u_int r_ctl = RCTL_ELS_UCTL;
-u_int type = TYPE_ELS | SEQUENCE_INITIATIVE | FIRST_SEQUENCE;
-u_int my_mtu = fi->g.my_mtu;
- ENTER("tx_logi");
- /* We don't want interrupted for our own logi.
- * It screws up the port discovery process.
- */
- if (d_id == fi->g.my_id)
- int_required = 0;
- fill_login_frame(fi, logi);
- fi->g.type_of_frame = FC_ELS;
- memcpy(fi->g.els_buffer[fi->g.e_i], &fi->g.login, sizeof(LOGIN));
- tx_exchange(fi, (char *)(fi->g.els_buffer[fi->g.e_i]),sizeof(LOGIN), r_ctl, type, d_id, my_mtu, int_required, ox_id, logi);
- fi->g.e_i++;
- if (fi->g.e_i == MAX_PENDING_FRAMES)
- fi->g.e_i = 0;
- LEAVE("tx_logi");
- return;
-}
-
-static void tx_logi_acc(struct fc_info *fi, u_int logi, u_int d_id, u_short received_ox_id)
-{
-int int_required = 0;
-u_int r_ctl = RCTL_ELS_SCTL;
-u_int type = TYPE_ELS | EXCHANGE_RESPONDER | LAST_SEQUENCE;
-u_int my_mtu = fi->g.my_mtu;
- ENTER("tx_logi_acc");
- fill_login_frame(fi, logi);
- fi->g.type_of_frame = FC_ELS;
- memcpy(fi->g.els_buffer[fi->g.e_i], &fi->g.login, sizeof(LOGIN));
- tx_exchange(fi, (char *)(fi->g.els_buffer[fi->g.e_i]),sizeof(LOGIN), r_ctl, type, d_id, my_mtu, int_required, received_ox_id, logi);
- fi->g.e_i++;
- if (fi->g.e_i == MAX_PENDING_FRAMES)
- fi->g.e_i = 0;
- LEAVE("tx_logi_acc");
- return;
-}
-
-static void tx_prli(struct fc_info *fi, u_int command_code, u_int d_id, u_short received_ox_id)
-{
-int int_required = 1;
-u_int r_ctl = RCTL_ELS_UCTL;
-u_int type = TYPE_ELS | SEQUENCE_INITIATIVE | FIRST_SEQUENCE;
-u_int my_mtu = fi->g.my_mtu;
- ENTER("tx_prli");
- if (command_code == ELS_PRLI)
- fi->g.prli.cmnd_code = htons((ELS_PRLI | PAGE_LEN) >> 16);
- else {
- fi->g.prli.cmnd_code = htons((ELS_ACC | PAGE_LEN) >> 16);
- int_required = 0;
- type = TYPE_ELS | EXCHANGE_RESPONDER | LAST_SEQUENCE;
- r_ctl = RCTL_ELS_SCTL;
- }
- fi->g.prli.payload_length = htons(PRLI_LEN);
- fi->g.prli.type_code = htons(FCP_TYPE_CODE);
- fi->g.prli.est_image_pair = htons(IMAGE_PAIR);
- fi->g.prli.responder_pa = 0;
- fi->g.prli.originator_pa = 0;
- fi->g.prli.service_params = htonl(INITIATOR_FUNC | READ_XFER_RDY_DISABLED);
- fi->g.type_of_frame = FC_ELS;
- memcpy(fi->g.els_buffer[fi->g.e_i], &fi->g.prli, sizeof(PRLI));
- tx_exchange(fi, (char *)(fi->g.els_buffer[fi->g.e_i]), sizeof(PRLI), r_ctl, type, d_id, my_mtu, int_required, received_ox_id, command_code);
- fi->g.e_i++;
- if (fi->g.e_i == MAX_PENDING_FRAMES)
- fi->g.e_i = 0;
- LEAVE("tx_prli");
- return;
-}
-
-static void tx_logo(struct fc_info *fi, u_int d_id, u_short received_ox_id)
-{
-int int_required = 1;
-u_int r_ctl = RCTL_ELS_UCTL;
-u_int type = TYPE_ELS | EXCHANGE_RESPONDER | SEQUENCE_RESPONDER | FIRST_SEQUENCE | END_SEQUENCE | SEQUENCE_INITIATIVE;
-int size = sizeof(LOGO);
-char fc_id[3];
-u_int my_mtu = fi->g.my_mtu;
- ENTER("tx_logo");
- fi->g.logo.logo_cmnd = htonl(ELS_LOGO);
- fi->g.logo.reserved = 0;
- memcpy(fc_id, &(fi->g.my_id), 3);
- fi->g.logo.n_port_id_0 = fc_id[0];
- fi->g.logo.n_port_id_1 = fc_id[1];
- fi->g.logo.n_port_id_2 = fc_id[2];
- fi->g.logo.port_name_up = htonl(N_PORT_NAME_HIGH);
- fi->g.logo.port_name_low = htonl(N_PORT_NAME_LOW);
- fi->g.type_of_frame = FC_ELS;
- memcpy(fi->g.els_buffer[fi->g.e_i], &fi->g.logo, sizeof(LOGO));
- tx_exchange(fi, (char *)(fi->g.els_buffer[fi->g.e_i]),size, r_ctl, type, d_id, my_mtu, int_required, received_ox_id, ELS_LOGO);
- fi->g.e_i++;
- if (fi->g.e_i == MAX_PENDING_FRAMES)
- fi->g.e_i = 0;
- LEAVE("tx_logo");
-}
-
-static void tx_adisc(struct fc_info *fi, u_int cmnd_code, u_int d_id, u_short received_ox_id)
-{
-int int_required = 0;
-u_int r_ctl = RCTL_ELS_SCTL;
-u_int type = TYPE_ELS | EXCHANGE_RESPONDER | SEQUENCE_RESPONDER | FIRST_SEQUENCE | END_SEQUENCE;
-int size = sizeof(ADISC);
-u_int my_mtu = fi->g.my_mtu;
- fi->g.adisc.ls_cmnd_code = htonl(cmnd_code);
- fi->g.adisc.hard_address = htonl(0);
- fi->g.adisc.port_name_high = htonl(N_PORT_NAME_HIGH);
- fi->g.adisc.port_name_low = htonl(N_PORT_NAME_LOW);
- fi->g.adisc.node_name_high = htonl(NODE_NAME_HIGH);
- fi->g.adisc.node_name_low = htonl(NODE_NAME_LOW);
- fi->g.adisc.n_port_id = htonl(fi->g.my_id);
- if (cmnd_code == ELS_ADISC) {
- int_required = 1;
- r_ctl = RCTL_ELS_UCTL;
- type = TYPE_ELS | SEQUENCE_INITIATIVE | FIRST_SEQUENCE;
- }
- fi->g.type_of_frame = FC_ELS;
- memcpy(fi->g.els_buffer[fi->g.e_i], &fi->g.adisc, size);
- tx_exchange(fi, (char *)(fi->g.els_buffer[fi->g.e_i]),size, r_ctl, type, d_id, my_mtu, int_required, received_ox_id, cmnd_code);
- fi->g.e_i++;
- if (fi->g.e_i == MAX_PENDING_FRAMES)
- fi->g.e_i = 0;
-}
-
-static void tx_ls_rjt(struct fc_info *fi, u_int d_id, u_short received_ox_id, u_short reason_code, u_short expln_code)
-{
-int int_required = 0;
-u_int r_ctl = RCTL_ELS_SCTL;
-u_int type = TYPE_ELS | EXCHANGE_RESPONDER | LAST_SEQUENCE;
-int size = sizeof(LS_RJT);
-u_int my_mtu = fi->g.my_mtu;
- ENTER("tx_ls_rjt");
- fi->g.ls_rjt.cmnd_code = htonl(ELS_LS_RJT);
- fi->g.ls_rjt.reason_code = htonl((reason_code << 16) | expln_code);
- fi->g.type_of_frame = FC_ELS;
- memcpy(fi->g.els_buffer[fi->g.e_i], &fi->g.ls_rjt, size);
- tx_exchange(fi, (char *)(fi->g.els_buffer[fi->g.e_i]),size, r_ctl, type, d_id, my_mtu, int_required, received_ox_id, ELS_LS_RJT);
- fi->g.e_i++;
- if (fi->g.e_i == MAX_PENDING_FRAMES)
- fi->g.e_i = 0;
- LEAVE("tx_ls_rjt");
-}
-
-static void tx_abts(struct fc_info *fi, u_int d_id, u_short ox_id)
-{
-int int_required = 1;
-u_int r_ctl = RCTL_BASIC_ABTS;
-u_int type = TYPE_BLS | SEQUENCE_INITIATIVE | FIRST_SEQUENCE;
-int size = 0;
-u_int my_mtu = fi->g.my_mtu;
- ENTER("tx_abts");
- fi->g.type_of_frame = FC_BLS;
- tx_exchange(fi, NULL, size, r_ctl, type, d_id, my_mtu, int_required, ox_id, RCTL_BASIC_ABTS);
- LEAVE("tx_abts");
-}
-
-static u_int plogi_ok(struct fc_info *fi, u_int *buff_addr, int size)
-{
-int ret_code = 0;
-u_short mtu = ntohl(*(buff_addr + 10)) & 0x00000FFF;
-u_short class3 = ntohl(*(buff_addr + 25)) >> 16;
-u_short class3_conc_seq = ntohl(*(buff_addr + 27)) >> 16;
-u_short open_seq = ntohl(*(buff_addr + 28)) >> 16;
- DPRINTK1("mtu = %x class3 = %x conc_seq = %x open_seq = %x", mtu, class3, class3_conc_seq, open_seq);
- size -= TACHYON_HEADER_LEN;
- if (!(class3 & 0x8000)) {
- DPRINTK1("Received PLOGI with class3 = %x", class3);
- ret_code = (LOGICAL_ERR << 16) | NO_EXPLN;
- return ret_code;
- }
- if (mtu < 256) {
- DPRINTK1("Received PLOGI with MTU set to %x", mtu);
- ret_code = (LOGICAL_ERR << 16) | RECV_FIELD_SIZE;
- return ret_code;
- }
- if (size != PLOGI_LEN) {
- DPRINTK1("Received PLOGI of size %x", size);
- ret_code = (LOGICAL_ERR << 16) | INV_PAYLOAD_LEN;
- return ret_code;
- }
- if (class3_conc_seq == 0) {
- DPRINTK1("Received PLOGI with conc_seq == 0");
- ret_code = (LOGICAL_ERR << 16) | CONC_SEQ;
- return ret_code;
- }
- if (open_seq == 0) {
- DPRINTK1("Received PLOGI with open_seq == 0");
- ret_code = (LOGICAL_ERR << 16) | NO_EXPLN;
- return ret_code;
- }
-
- /* Could potentially check for more fields, but might end up
- not talking to most of the devices. ;-) */
- /* Things that could get checked are:
- common_features = 0x8800
- total_concurrent_seq = at least 1
- */
- return ret_code;
-}
-
-static void tx_acc(struct fc_info *fi, u_int d_id, u_short received_ox_id)
-{
-int int_required = 0;
-u_int r_ctl = RCTL_ELS_SCTL;
-u_int type = TYPE_ELS | EXCHANGE_RESPONDER | LAST_SEQUENCE;
-int size = sizeof(ACC);
-u_int my_mtu = fi->g.my_mtu;
- ENTER("tx_acc");
- fi->g.acc.cmnd_code = htonl(ELS_ACC);
- fi->g.type_of_frame = FC_ELS;
- memcpy(fi->g.els_buffer[fi->g.e_i], &fi->g.acc, size);
- tx_exchange(fi, (char *)(fi->g.els_buffer[fi->g.e_i]),size, r_ctl, type, d_id, my_mtu, int_required, received_ox_id, ELS_ACC);
- fi->g.e_i++;
- if (fi->g.e_i == MAX_PENDING_FRAMES)
- fi->g.e_i = 0;
- LEAVE("tx_acc");
-}
-
-
-static void tx_name_server_req(struct fc_info *fi, u_int req)
-{
-int int_required = 1, i, size = 0;
-u_short ox_id = OX_ID_FIRST_SEQUENCE;
-u_int type = TYPE_FC_SERVICES | SEQUENCE_INITIATIVE | FIRST_SEQUENCE;
-u_int r_ctl = FC4_DEVICE_DATA | UNSOLICITED_CONTROL;
-u_int my_mtu = fi->g.my_mtu, d_id = DIRECTORY_SERVER;
-CT_HDR ct_hdr;
- ENTER("tx_name_server_req");
- /* Fill up CT_Header */
- ct_hdr.rev_in_id = htonl(FC_CT_REV);
- ct_hdr.fs_type = DIRECTORY_SERVER_APP;
- ct_hdr.fs_subtype = NAME_SERVICE;
- ct_hdr.options = 0;
- ct_hdr.resv1 = 0;
- ct_hdr.cmnd_resp_code = htons(req >> 16);
- ct_hdr.max_res_size = 0;
- ct_hdr.resv2 = 0;
- ct_hdr.reason_code = 0;
- ct_hdr.expln_code = 0;
- ct_hdr.vendor_unique = 0;
-
- fi->g.type_of_frame = FC_ELS;
- switch(req) {
- case FCS_RFC_4:
- memcpy(&(fi->g.rfc_4.ct_hdr), &ct_hdr, sizeof(CT_HDR));
- fi->g.rfc_4.s_id = htonl(fi->g.my_id);
- for (i = 0; i < 32; i++)
- fi->g.rfc_4.bit_map[i] = 0;
- /* We support IP & SCSI */
- fi->g.rfc_4.bit_map[2] = 0x01;
- fi->g.rfc_4.bit_map[3] = 0x20;
- size = sizeof(RFC_4);
- memcpy(fi->g.els_buffer[fi->g.e_i], &fi->g.rfc_4, size);
- tx_exchange(fi, (char *)(fi->g.els_buffer[fi->g.e_i]),size, r_ctl, type, d_id, my_mtu, int_required, ox_id, req);
- break;
- case FCS_GP_ID4:
- memcpy(&(fi->g.gp_id4.ct_hdr), &ct_hdr, sizeof(CT_HDR));
- fi->g.gp_id4.port_type = htonl(PORT_TYPE_NX_PORTS);
- size = sizeof(GP_ID4);
- memcpy(fi->g.els_buffer[fi->g.e_i], &fi->g.gp_id4, size);
- tx_exchange(fi, (char *)(fi->g.els_buffer[fi->g.e_i]),size, r_ctl, type, d_id, my_mtu, int_required, ox_id, req);
- break;
- }
- fi->g.e_i++;
- if (fi->g.e_i == MAX_PENDING_FRAMES)
- fi->g.e_i = 0;
- LEAVE("tx_name_server_req");
-}
-
-static void tx_scr(struct fc_info *fi)
-{
-int int_required = 1, size = sizeof(SCR);
-u_short ox_id = OX_ID_FIRST_SEQUENCE;
-u_int type = TYPE_ELS | SEQUENCE_INITIATIVE | FIRST_SEQUENCE;
-u_int r_ctl = RCTL_ELS_UCTL;
-u_int my_mtu = fi->g.my_mtu, d_id = FABRIC_CONTROLLER;
- ENTER("tx_scr");
- fi->g.scr.cmnd_code = htonl(ELS_SCR);
- fi->g.scr.reg_function = htonl(FULL_REGISTRATION);
- fi->g.type_of_frame = FC_ELS;
- memcpy(fi->g.els_buffer[fi->g.e_i], &fi->g.scr, size);
- tx_exchange(fi, (char *)(fi->g.els_buffer[fi->g.e_i]),size, r_ctl, type, d_id, my_mtu, int_required, ox_id, ELS_SCR);
- fi->g.e_i++;
- if (fi->g.e_i == MAX_PENDING_FRAMES)
- fi->g.e_i = 0;
- LEAVE("tx_scr");
-}
-
-static void perform_adisc(struct fc_info *fi)
-{
-int count = 0;
- /* Will be set to TRUE when timer expires in a PLDA environment.
- */
- fi->g.port_discovery = FALSE;
-
- if (fi->node_info_list) {
- struct fc_node_info *temp_list = fi->node_info_list;
- while(temp_list) {
- /* Tx ADISC to all non-fabric based
- * entities.
- */
- if ((temp_list->d_id & 0xFF0000) != 0xFF0000)
- tx_adisc(fi, ELS_ADISC, temp_list->d_id, OX_ID_FIRST_SEQUENCE);
- temp_list = temp_list->next;
- udelay(20);
- count++;
- }
- }
- /* Perform Port Discovery after timer expires.
- * We are giving time for the ADISCed nodes to respond
- * so that we don't have to perform PLOGI to those whose
- * login are _still_ valid.
- */
- fi->explore_timer.function = port_discovery_timer;
- fi->explore_timer.data = (unsigned long)fi;
- fi->explore_timer.expires = RUN_AT((count*3*HZ)/100);
- init_timer(&fi->explore_timer);
- add_timer(&fi->explore_timer);
-}
-
-static void explore_fabric(struct fc_info *fi, u_int *buff_addr)
-{
-u_int *addr = buff_addr + 12; /* index into payload */
-u_char control_code;
-u_int d_id;
-int count = 0;
- ENTER("explore_fabric");
- DPRINTK1("entering explore_fabric");
-
- /*fi->g.perform_adisc = TRUE;
- fi->g.explore_fabric = TRUE;
- perform_adisc(fi);*/
-
- do {
- d_id = ntohl(*addr) & 0x00FFFFFF;
- if (d_id != fi->g.my_id) {
- if (sid_logged_in(fi, d_id) == NODE_NOT_PRESENT)
- tx_logi(fi, ELS_PLOGI, d_id);
- else
- if (sid_logged_in(fi, d_id) == NODE_LOGGED_OUT)
- tx_adisc(fi, ELS_ADISC, d_id, OX_ID_FIRST_SEQUENCE);
- count++;
- }
- control_code = (ntohl(*addr) & 0xFF000000) >> 24;
- addr++;
- DPRINTK1("cc = %x, d_id = %x", control_code, d_id);
- } while (control_code != 0x80);
-
- fi->explore_timer.function = fabric_explore_timer;
- fi->explore_timer.data = (unsigned long)fi;
- /* We give 30 msec for each device to respond and then send out
- * our SCSI enquiries.
- */
- fi->explore_timer.expires = RUN_AT((count*3*HZ)/100);
- init_timer(&fi->explore_timer);
- add_timer(&fi->explore_timer);
-
- DPRINTK1("leaving explore_fabric");
- LEAVE("explore_fabric");
-}
-
-static void fabric_explore_timer(unsigned long data)
-{
-struct fc_info *fi = (struct fc_info*)data;
- del_timer(&fi->explore_timer);
-
- if ((fi->g.loop_up == TRUE) && (fi->g.ptp_up == FALSE)) {
- /* Initiate Local Port Discovery on the Local Loop.
- */
- fi->g.port_discovery = TRUE;
- fi->g.alpa_list_index = 1;
- local_port_discovery(fi);
- }
- fi->g.explore_fabric = FALSE;
- return;
-}
-
-static void port_discovery_timer(unsigned long data)
-{
-struct fc_info *fi = (struct fc_info*)data;
- del_timer(&fi->explore_timer);
-
- if ((fi->g.loop_up == TRUE) && (fi->g.explore_fabric != TRUE)) {
- fi->g.port_discovery = TRUE;
- fi->g.alpa_list_index = 1;
- local_port_discovery(fi);
- }
- fi->g.perform_adisc = FALSE;
- return;
-}
-
-static void add_to_ox_id_list(struct fc_info *fi, u_int transaction_id, u_int cmnd_code)
-{
-struct ox_id_els_map *p, *q = fi->ox_id_list, *r = NULL;
-int size = sizeof(struct ox_id_els_map);
- while (q != NULL) {
- r = q;
- q = q->next;
- }
- p = (struct ox_id_els_map *)kmalloc(size, GFP_ATOMIC);
- if (p == NULL) {
- T_MSG("kmalloc failed in add_to_ox_id_list()");
- return;
- }
- p->ox_id = transaction_id;
- p->els = cmnd_code;
- p->next = NULL;
- if (fi->ox_id_list == NULL)
- fi->ox_id_list = p;
- else
- r->next = p;
- return;
-}
-
-static u_int remove_from_ox_id_list(struct fc_info *fi, u_short received_ox_id)
-{
-struct ox_id_els_map *p = fi->ox_id_list, *q = fi->ox_id_list;
-u_int els_type;
- while (q != NULL) {
- if (q->ox_id == received_ox_id) {
-
- if (q == fi->ox_id_list)
- fi->ox_id_list = fi->ox_id_list->next;
- else
- if (q->next == NULL)
- p->next = NULL;
- else
- p->next = q->next;
-
- els_type = q->els;
- kfree(q);
- return els_type;
- }
- p = q;
- q = q->next;
- }
- if (q == NULL)
- DPRINTK2("Could not find ox_id %x in ox_id_els_map", received_ox_id);
- return 0;
-}
-
-static void build_tachyon_header(struct fc_info *fi, u_int my_id, u_int r_ctl, u_int d_id, u_int type, u_char seq_id, u_char df_ctl, u_short ox_id, u_short rx_id, char *data)
-{
-u_char alpa = d_id & 0x0000FF;
-u_int dest_ddaa = d_id &0xFFFF00;
-
- ENTER("build_tachyon_header");
- DPRINTK("d_id = %x, my_ddaa = %x", d_id, fi->g.my_ddaa);
- /* Does it have to go to/thru a Fabric? */
- if ((dest_ddaa != 0) && ((d_id == F_PORT) || (fi->g.fabric_present && (dest_ddaa != fi->g.my_ddaa))))
- alpa = 0x00;
- fi->g.tach_header.resv = 0x00000000;
- fi->g.tach_header.sof_and_eof = SOFI3 | EOFN;
- fi->g.tach_header.dest_alpa = alpa;
- /* Set LCr properly to have enuff credit */
- if (alpa == REPLICATE)
- fi->g.tach_header.lcr_and_time_stamp = htons(0xC00);/* LCr=3 */
- else
- fi->g.tach_header.lcr_and_time_stamp = 0;
- fi->g.tach_header.r_ctl_and_d_id = htonl(r_ctl | d_id);
- fi->g.tach_header.vc_id_and_s_id = htonl(my_id);
- fi->g.tach_header.type_and_f_cntl = htonl(type);
- fi->g.tach_header.seq_id = seq_id;
- fi->g.tach_header.df_cntl = df_ctl;
- fi->g.tach_header.seq_cnt = 0;
- fi->g.tach_header.ox_id = htons(ox_id);
- fi->g.tach_header.rx_id = htons(rx_id);
- fi->g.tach_header.ro = 0;
- if (data) {
- /* We use the Seq_Count to keep track of IP frames in the
- * OCI_interrupt handler. Initial Seq_Count of IP frames is 1.
- */
- if (fi->g.type_of_frame == FC_BROADCAST)
- fi->g.tach_header.seq_cnt = htons(0x1);
- else
- fi->g.tach_header.seq_cnt = htons(0x2);
- fi->g.tach_header.nw_header.d_naa = htons(0x1000);
- fi->g.tach_header.nw_header.s_naa = htons(0x1000);
- memcpy(&(fi->g.tach_header.nw_header.dest_high), data, 2);
- memcpy(&(fi->g.tach_header.nw_header.dest_low), data + 2, 4);
- memcpy(&(fi->g.tach_header.nw_header.source_high), data + 6, 2);
- memcpy(&(fi->g.tach_header.nw_header.source_low), data + 8, 4);
- }
- LEAVE("build_tachyon_header");
-}
-
-static void build_EDB(struct fc_info *fi, char *data, u_short flags, u_short len)
-{
- fi->g.edb.buf_addr = ntohl((u_int)virt_to_bus(data));
- fi->g.edb.ehf = ntohs(flags);
- if (len % 4)
- len += (4 - (len % 4));
- fi->g.edb.buf_len = ntohs(len);
-}
-
-static void build_ODB(struct fc_info *fi, u_char seq_id, u_int d_id, u_int len, u_int cntl, u_short mtu, u_short ox_id, u_short rx_id, int NW_header, int int_required, u_int frame_class)
-{
- fi->g.odb.seq_d_id = htonl(seq_id << 24 | d_id);
- fi->g.odb.tot_len = len;
- if (NW_header)
- fi->g.odb.tot_len += NW_HEADER_LEN;
- if (fi->g.odb.tot_len % 4)
- fi->g.odb.tot_len += (4 - (fi->g.odb.tot_len % 4));
- fi->g.odb.tot_len = htonl(fi->g.odb.tot_len);
- switch(int_required) {
- case NO_COMP_AND_INT:
- fi->g.odb.cntl = htons(ODB_CLASS_3 | ODB_EE_CREDIT | ODB_NO_INT | ODB_NO_COMP | cntl);
- break;
- case INT_AND_COMP_REQ:
- fi->g.odb.cntl = htons(ODB_CLASS_3 | ODB_EE_CREDIT | cntl);
- break;
- case NO_INT_COMP_REQ:
- fi->g.odb.cntl = htons(ODB_CLASS_3 | ODB_EE_CREDIT | ODB_NO_INT | cntl);
- break;
- }
- fi->g.odb.rx_id = htons(rx_id);
- fi->g.odb.cs_enable = 0;
- fi->g.odb.cs_seed = htons(1);
-
- fi->g.odb.hdr_addr = htonl(virt_to_bus(fi->q.ptr_tachyon_header[fi->q.tachyon_header_indx]));
- fi->g.odb.frame_len = htons(mtu);
-
- if (NW_header) {
- /* The pointer to the sk_buff is in here. Freed up when the
- * OCI_interrupt is received.
- */
- fi->g.odb.trans_id = htonl(frame_class);
- fi->g.odb.hdr_len = TACHYON_HEADER_LEN + NW_HEADER_LEN;
- }
- else {
- /* helps in tracking transmitted OX_IDs */
- fi->g.odb.trans_id = htonl((frame_class & 0xFFFF0000) | ox_id);
- fi->g.odb.hdr_len = TACHYON_HEADER_LEN;
- }
- fi->g.odb.hdr_len = htons(fi->g.odb.hdr_len);
-
- fi->g.odb.edb_addr = htonl(virt_to_bus(fi->q.ptr_edb[fi->q.edb_buffer_indx]));
-}
-
-static void fill_login_frame(struct fc_info *fi, u_int logi)
-{
-int i;
- fi->g.login.ls_cmnd_code= htonl(logi);
- fi->g.login.fc_ph_version = htons(PH_VERSION);
- if (fi->g.loop_up)
- fi->g.login.buff_to_buff_credit = htons(LOOP_BB_CREDIT);
- else
- if (fi->g.ptp_up)
- fi->g.login.buff_to_buff_credit = htons(PT2PT_BB_CREDIT);
- if ((logi != ELS_FLOGI) || (logi == ELS_ACC))
- fi->g.login.common_features = htons(PLOGI_C_F);
- else
- if (logi == ELS_FLOGI)
- fi->g.login.common_features = htons(FLOGI_C_F);
- fi->g.login.recv_data_field_size = htons(TACH_FRAME_SIZE);
- fi->g.login.n_port_total_conc_seq = htons(CONCURRENT_SEQUENCES);
- fi->g.login.rel_off_by_info_cat = htons(RO_INFO_CATEGORY);
- fi->g.login.ED_TOV = htonl(E_D_TOV);
- fi->g.login.n_port_name_high = htonl(N_PORT_NAME_HIGH);
- fi->g.login.n_port_name_low = htonl(N_PORT_NAME_LOW);
- fi->g.login.node_name_high = htonl(NODE_NAME_HIGH);
- fi->g.login.node_name_low = htonl(NODE_NAME_LOW);
-
- /* Fill Class 1 parameters */
- fi->g.login.c_of_s[0].service_options = htons(0);
- fi->g.login.c_of_s[0].initiator_ctl = htons(0);
- fi->g.login.c_of_s[0].recipient_ctl = htons(0);
- fi->g.login.c_of_s[0].recv_data_field_size = htons(0);
- fi->g.login.c_of_s[0].concurrent_sequences = htons(0);
- fi->g.login.c_of_s[0].n_port_end_to_end_credit = htons(0);
- fi->g.login.c_of_s[0].open_seq_per_exchange = htons(0);
- fi->g.login.c_of_s[0].resv = htons(0);
-
- /* Fill Class 2 parameters */
- fi->g.login.c_of_s[1].service_options = htons(0);
- fi->g.login.c_of_s[1].initiator_ctl = htons(0);
- fi->g.login.c_of_s[1].recipient_ctl = htons(0);
- fi->g.login.c_of_s[1].recv_data_field_size = htons(0);
- fi->g.login.c_of_s[1].concurrent_sequences = htons(0);
- fi->g.login.c_of_s[1].n_port_end_to_end_credit = htons(0);
- fi->g.login.c_of_s[1].open_seq_per_exchange = htons(0);
- fi->g.login.c_of_s[1].resv = htons(0);
-
- /* Fill Class 3 parameters */
- if (logi == ELS_FLOGI)
- fi->g.login.c_of_s[2].service_options = htons(SERVICE_VALID | SEQUENCE_DELIVERY);
- else
- fi->g.login.c_of_s[2].service_options = htons(SERVICE_VALID);
- fi->g.login.c_of_s[2].initiator_ctl = htons(0);
- fi->g.login.c_of_s[2].recipient_ctl = htons(0);
- fi->g.login.c_of_s[2].recv_data_field_size = htons(TACH_FRAME_SIZE);
- fi->g.login.c_of_s[2].concurrent_sequences = htons(CLASS3_CONCURRENT_SEQUENCE);
- fi->g.login.c_of_s[2].n_port_end_to_end_credit = htons(0);
- fi->g.login.c_of_s[2].open_seq_per_exchange = htons(CLASS3_OPEN_SEQUENCE);
- fi->g.login.c_of_s[2].resv = htons(0);
-
- for(i = 0; i < 4; i++) {
- fi->g.login.resv[i] = 0;
- fi->g.login.vendor_version_level[i] = 0;
- }
-}
-
-
-/* clear the Interrupt Latch on the (i)chip, so that you can receive
- * Interrupts from Tachyon in future
- */
-static void reset_latch(struct fc_info *fi)
-{
- writel(readl(fi->i_r.ptr_ichip_hw_status_reg) | ICHIP_HSR_INT_LATCH, fi->i_r.ptr_ichip_hw_status_reg);
-}
-
-static void update_OCQ_indx(struct fc_info *fi)
-{
- fi->q.ocq_prod_indx++;
- if (fi->q.ocq_prod_indx == OCQ_LENGTH)
- fi->q.ocq_prod_indx = 0;
- writel(fi->q.ocq_prod_indx, fi->t_r.ptr_ocq_prod_indx_reg);
-}
-
-static void update_IMQ_indx(struct fc_info *fi, int count)
-{
- fi->q.imq_cons_indx += count;
- if (fi->q.imq_cons_indx >= IMQ_LENGTH)
- fi->q.imq_cons_indx -= IMQ_LENGTH;
- writel(fi->q.imq_cons_indx, fi->t_r.ptr_imq_cons_indx_reg);
-}
-
-static void update_SFSBQ_indx(struct fc_info *fi)
-{
- fi->q.sfsbq_prod_indx++;
- if (fi->q.sfsbq_prod_indx == SFSBQ_LENGTH)
- fi->q.sfsbq_prod_indx = 0;
- writel(fi->q.sfsbq_prod_indx, fi->t_r.ptr_sfsbq_prod_reg);
-}
-
-static void update_MFSBQ_indx(struct fc_info *fi, int count)
-{
- fi->q.mfsbq_prod_indx += count;
- if (fi->q.mfsbq_prod_indx >= MFSBQ_LENGTH)
- fi->q.mfsbq_prod_indx -= MFSBQ_LENGTH;
- writel(fi->q.mfsbq_prod_indx, fi->t_r.ptr_mfsbq_prod_reg);
-}
-
-
-static void update_tachyon_header_indx(struct fc_info *fi)
-{
- fi->q.tachyon_header_indx++;
- if (fi->q.tachyon_header_indx == NO_OF_TACH_HEADERS)
- fi->q.tachyon_header_indx = 0;
-}
-
-static void update_EDB_indx(struct fc_info *fi)
-{
- fi->q.edb_buffer_indx++;
- if (fi->q.edb_buffer_indx == EDB_LEN)
- fi->q.edb_buffer_indx = 0;
-}
-
-static int iph5526_open(struct net_device *dev)
-{
- netif_start_queue(dev);
- return 0;
-}
-
-static int iph5526_close(struct net_device *dev)
-{
- netif_stop_queue(dev);
- return 0;
-}
-
-static void iph5526_timeout(struct net_device *dev)
-{
- struct fc_info *fi = dev->priv;
- printk(KERN_WARNING "%s: timed out on send.\n", dev->name);
- fi->fc_stats.tx_dropped++;
- dev->trans_start = jiffies;
- netif_wake_queue(dev);
-}
-
-static int iph5526_send_packet(struct sk_buff *skb, struct net_device *dev)
-{
- struct fc_info *fi = dev->priv;
- int status = 0;
- short type = 0;
- u_long flags;
- struct fcllc *fcllc;
-
- ENTER("iph5526_send_packet");
-
- netif_stop_queue(dev);
- /* Strip off the pseudo header.
- */
- skb->data = skb->data + 2*FC_ALEN;
- skb->len = skb->len - 2*FC_ALEN;
- fcllc = (struct fcllc *)skb->data;
- type = ntohs(fcllc->ethertype);
-
- spin_lock_irqsave(&fi->fc_lock, flags);
- switch(type) {
- case ETH_P_IP:
- status = tx_ip_packet(skb, skb->len, fi);
- break;
- case ETH_P_ARP:
- status = tx_arp_packet(skb->data, skb->len, fi);
- break;
- default:
- T_MSG("WARNING!!! Received Unknown Packet Type... Discarding...");
- fi->fc_stats.rx_dropped++;
- break;
- }
- spin_unlock_irqrestore(&fi->fc_lock, flags);
-
- if (status) {
- fi->fc_stats.tx_bytes += skb->len;
- fi->fc_stats.tx_packets++;
- }
- else
- fi->fc_stats.tx_dropped++;
- dev->trans_start = jiffies;
- /* We free up the IP buffers in the OCI_interrupt handler.
- * status == 0 implies that the frame was not transmitted. So the
- * skb is freed here.
- */
- if ((type == ETH_P_ARP) || (status == 0))
- dev_kfree_skb(skb);
- netif_wake_queue(dev);
- LEAVE("iph5526_send_packet");
- return 0;
-}
-
-static int iph5526_change_mtu(struct net_device *dev, int mtu)
-{
- return 0;
-}
-
-static int tx_ip_packet(struct sk_buff *skb, unsigned long len, struct fc_info *fi)
-{
-u_int d_id;
-int int_required = 1;
-u_int r_ctl = FC4_DEVICE_DATA | UNSOLICITED_DATA;
-u_int type = TYPE_LLC_SNAP;
-u_short ox_id = OX_ID_FIRST_SEQUENCE;
-u_int mtu;
-struct fc_node_info *q;
-
- ENTER("tx_ip_packet");
- q = look_up_cache(fi, skb->data - 2*FC_ALEN);
- if (q != NULL) {
- d_id = q->d_id;
- DPRINTK("Look-Up Cache Succeeded for d_id = %x", d_id);
- mtu = q->mtu;
- if (q->login == LOGIN_COMPLETED){
- fi->g.type_of_frame = FC_IP;
- return tx_exchange(fi, skb->data, len, r_ctl, type, d_id, mtu, int_required, ox_id, virt_to_bus(skb));
- }
-
- if (q->d_id == BROADCAST) {
- struct fc_node_info *p = fi->node_info_list;
- int return_value = FALSE;
- fi->g.type_of_frame = FC_BROADCAST;
- /* Do unicast to local nodes.
- */
- int_required = 0;
- while(p != NULL) {
- d_id = p->d_id;
- if ((d_id & 0xFFFF00) == fi->g.my_ddaa)
- return_value |= tx_exchange(fi, skb->data, len, r_ctl, type, d_id, fi->g.my_mtu, int_required, ox_id, TYPE_LLC_SNAP);
- p = p->next;
- }
- kfree(q);
- return return_value;
- }
-
- if (q->login != LOGIN_COMPLETED) {
- DPRINTK1("Node not logged in... Txing PLOGI to %x", d_id);
- /* FIXME: we are dumping the frame here */
- tx_logi(fi, ELS_PLOGI, d_id);
- }
- }
- DPRINTK2("Look-Up Cache Failed");
- LEAVE("tx_ip_packet");
- return 0;
-}
-
-static int tx_arp_packet(char *data, unsigned long len, struct fc_info *fi)
-{
-u_int opcode = data[ARP_OPCODE_0];
-u_int d_id;
-int int_required = 0, return_value = FALSE;
-u_int r_ctl = FC4_DEVICE_DATA | UNSOLICITED_DATA;
-u_int type = TYPE_LLC_SNAP;
-u_short ox_id = OX_ID_FIRST_SEQUENCE;
-u_int my_mtu = fi->g.my_mtu;
- ENTER("tx_arp_packet");
-
- opcode = opcode << 8 | data[ARP_OPCODE_1];
- fi->g.type_of_frame = FC_IP;
-
- if (opcode == ARPOP_REQUEST) {
- struct fc_node_info *q = fi->node_info_list;
- d_id = BROADCAST;
- return_value |= tx_exchange(fi, data, len, r_ctl, type, d_id, my_mtu, int_required, ox_id, TYPE_LLC_SNAP);
- /* Some devices support HW_TYPE 0x01 */
- memcpy(fi->g.arp_buffer, data - 2*FC_ALEN, len + 2*FC_ALEN);
- fi->g.arp_buffer[9 + 2*FC_ALEN] = 0x01;
- return_value |= tx_exchange(fi, (char *)(fi->g.arp_buffer + 2*FC_ALEN), len, r_ctl, type, d_id, my_mtu, int_required, ox_id, TYPE_LLC_SNAP);
-
- /* Do unicast to local nodes.
- */
- while(q != NULL) {
- fi->g.type_of_frame = FC_BROADCAST;
- d_id = q->d_id;
- if ((d_id & 0xFFFF00) == fi->g.my_ddaa) {
- return_value |= tx_exchange(fi, data, len, r_ctl, type, d_id, my_mtu, int_required, ox_id, TYPE_LLC_SNAP);
- // Some devices support HW_TYPE 0x01
- memcpy(fi->g.arp_buffer, data - 2*FC_ALEN, len + 2*FC_ALEN);
- fi->g.arp_buffer[9 + 2*FC_ALEN] = 0x01;
- return_value |= tx_exchange(fi, (char *)(fi->g.arp_buffer + 2*FC_ALEN), len, r_ctl, type, d_id, my_mtu, int_required, ox_id, TYPE_LLC_SNAP);
- }
- q = q->next;
- }
- return return_value;
- }
- else
- if (opcode == ARPOP_REPLY) {
- struct fc_node_info *q; u_int mtu;
- DPRINTK("We are sending out an ARP reply");
- q = look_up_cache(fi, data - 2*FC_ALEN);
- if (q != NULL) {
- d_id = q->d_id;
- DPRINTK("Look-Up Cache Succeeded for d_id = %x", d_id);
- mtu = q->mtu;
- if (q->login == LOGIN_COMPLETED){
- tx_exchange(fi, data, len, r_ctl, type, d_id, mtu, int_required, ox_id, TYPE_LLC_SNAP);
- /* Some devices support HW_TYPE 0x01 */
- memcpy(fi->g.arp_buffer, data - 2*FC_ALEN, len + 2*FC_ALEN);
- fi->g.arp_buffer[9 + 2*FC_ALEN] = 0x01;
- return tx_exchange(fi, (char *)(fi->g.arp_buffer + 2*FC_ALEN), len, r_ctl, type, d_id, my_mtu, int_required, ox_id, TYPE_LLC_SNAP);
- }
- else {
- DPRINTK1("Node not logged in... Txing PLOGI to %x", d_id);
- tx_logi(fi, ELS_PLOGI, d_id); /* FIXME: we are dumping the frame here */
- }
- }
- DPRINTK2("Look-Up Cache Failed");
- }
- else {
- T_MSG("Warning!!! Invalid Opcode in ARP Packet!");
- }
- LEAVE("tx_arp_packet");
- return 0;
-}
-
-
-static void rx_net_packet(struct fc_info *fi, u_char *buff_addr, int payload_size)
-{
-struct net_device *dev = fi->dev;
-struct sk_buff *skb;
-u_int skb_size = 0;
-struct fch_hdr fch;
- ENTER("rx_net_packet");
- skb_size = payload_size - TACHYON_HEADER_LEN;
- DPRINTK("skb_size = %d", skb_size);
- fi->fc_stats.rx_bytes += skb_size - 2;
- skb = dev_alloc_skb(skb_size);
- if (skb == NULL) {
- printk(KERN_NOTICE "%s: In rx_net_packet() Memory squeeze, dropping packet.\n", dev->name);
- fi->fc_stats.rx_dropped++;
- return;
- }
- /* Skip over the Tachyon Frame Header.
- */
- buff_addr += TACHYON_HEADER_LEN;
-
- memcpy(fch.daddr, buff_addr + 2, FC_ALEN);
- memcpy(fch.saddr, buff_addr + 10, FC_ALEN);
- buff_addr += 2;
- memcpy(buff_addr, fch.daddr, FC_ALEN);
- memcpy(buff_addr + 6, fch.saddr, FC_ALEN);
- skb_reserve(skb, 2);
- memcpy(skb_put(skb, skb_size - 2), buff_addr, skb_size - 2);
- skb->dev = dev;
- skb->protocol = fc_type_trans(skb, dev);
- DPRINTK("protocol = %x", skb->protocol);
-
- /* Hmmm... to accept HW Type 0x01 as well...
- */
- if (skb->protocol == ntohs(ETH_P_ARP))
- skb->data[1] = 0x06;
- netif_rx(skb);
- dev->last_rx = jiffies;
- fi->fc_stats.rx_packets++;
- LEAVE("rx_net_packet");
-}
-
-
-static void rx_net_mfs_packet(struct fc_info *fi, struct sk_buff *skb)
-{
-struct net_device *dev = fi->dev;
-struct fch_hdr fch;
- ENTER("rx_net_mfs_packet");
- /* Construct your Hard Header */
- memcpy(fch.daddr, skb->data + 2, FC_ALEN);
- memcpy(fch.saddr, skb->data + 10, FC_ALEN);
- skb_pull(skb, 2);
- memcpy(skb->data, fch.daddr, FC_ALEN);
- memcpy(skb->data + 6, fch.saddr, FC_ALEN);
- skb->dev = dev;
- skb->protocol = fc_type_trans(skb, dev);
- DPRINTK("protocol = %x", skb->protocol);
- netif_rx(skb);
- dev->last_rx = jiffies;
- LEAVE("rx_net_mfs_packet");
-}
-
-static int tx_exchange(struct fc_info *fi, char *data, u_int len, u_int r_ctl, u_int type, u_int d_id, u_int mtu, int int_required, u_short tx_ox_id, u_int frame_class)
-{
-u_char df_ctl;
-int NW_flag = 0, h_size, return_value;
-u_short rx_id = RX_ID_FIRST_SEQUENCE;
-u_int tachyon_status;
-u_int my_id = fi->g.my_id;
- ENTER("tx_exchange");
-
- tachyon_status = readl(fi->t_r.ptr_tach_status_reg);
- DPRINTK("Tachyon Status = %x len = %d MTU = %d", tachyon_status, len, mtu);
- if (tachyon_status & OSM_FROZEN) {
- reset_tachyon(fi, ERROR_RELEASE);
- reset_tachyon(fi, OCQ_RESET);
- DPRINTK("Tachyon Status = %x len = %d MTU = %d", tachyon_status, len, mtu);
- }
- if (tx_ox_id == OX_ID_FIRST_SEQUENCE) {
- switch(fi->g.type_of_frame) {
- case FC_SCSI_READ:
- tx_ox_id = fi->g.scsi_oxid | SCSI_READ_BIT;
- break;
- case FC_SCSI_WRITE:
- tx_ox_id = fi->g.scsi_oxid;
- break;
- default:
- tx_ox_id = fi->g.ox_id;
- break;
- }
- }
- else {
- switch(fi->g.type_of_frame) {
- case FC_SCSI_READ:
- rx_id = fi->g.scsi_oxid | SCSI_READ_BIT;
- break;
- case FC_SCSI_WRITE:
- rx_id = fi->g.scsi_oxid;
- break;
- case FC_BLS:
- rx_id = RX_ID_FIRST_SEQUENCE;
- break;
- default:
- rx_id = fi->g.ox_id;
- break;
- }
- }
-
- if (type == TYPE_LLC_SNAP) {
- df_ctl = 0x20;
- NW_flag = 1;
- /* Multi Frame Sequence ? If yes, set RO bit */
- if (len > mtu)
- type |= RELATIVE_OFF_PRESENT;
- build_tachyon_header(fi, my_id, r_ctl, d_id, type, fi->g.seq_id, df_ctl, tx_ox_id, rx_id, data - 2*FC_ALEN);
- }
- else {
- df_ctl = 0;
- /* Multi Frame Sequence ? If yes, set RO bit */
- if (len > mtu)
- type |= RELATIVE_OFF_PRESENT;
- build_tachyon_header(fi, my_id, r_ctl, d_id, type, fi->g.seq_id, df_ctl, tx_ox_id, rx_id, NULL);
- }
-
- /* Get free Tachyon Headers and EDBs */
- if (get_free_header(fi) || get_free_EDB(fi))
- return 0;
-
- if ((type & 0xFF000000) == TYPE_LLC_SNAP) {
- h_size = TACHYON_HEADER_LEN + NW_HEADER_LEN;
- memcpy(fi->q.ptr_tachyon_header[fi->q.tachyon_header_indx], &(fi->g.tach_header), h_size);
- }
- else
- memcpy(fi->q.ptr_tachyon_header[fi->q.tachyon_header_indx], &(fi->g.tach_header), TACHYON_HEADER_LEN);
-
- return_value = tx_sequence(fi, data, len, mtu, d_id, tx_ox_id, rx_id, fi->g.seq_id, NW_flag, int_required, frame_class);
-
- switch(fi->g.type_of_frame) {
- case FC_SCSI_READ:
- case FC_SCSI_WRITE:
- update_scsi_oxid(fi);
- break;
- case FC_BLS:
- break;
- default:
- fi->g.ox_id++;
- if (fi->g.ox_id == 0xFFFF)
- fi->g.ox_id = NOT_SCSI_XID;
- break;
- }
-
- if (fi->g.seq_id == MAX_SEQ_ID)
- fi->g.seq_id = 0;
- else
- fi->g.seq_id++;
- LEAVE("tx_exchange");
- return return_value;
-}
-
-static int tx_sequence(struct fc_info *fi, char *data, u_int len, u_int mtu, u_int d_id, u_short ox_id, u_short rx_id, u_char seq_id, int NW_flag, int int_required, u_int frame_class)
-{
-u_int cntl = 0;
-int return_value;
- ENTER("tx_sequence");
- build_EDB(fi, data, EDB_END, len);
- memcpy(fi->q.ptr_edb[fi->q.edb_buffer_indx], &(fi->g.edb), sizeof(EDB));
- build_ODB(fi, seq_id, d_id, len, cntl, mtu, ox_id, rx_id, NW_flag, int_required, frame_class);
- memcpy(fi->q.ptr_odb[fi->q.ocq_prod_indx], &(fi->g.odb), sizeof(ODB));
- if (fi->g.link_up != TRUE) {
- DPRINTK2("Fibre Channel Link not up. Dropping Exchange!");
- return_value = FALSE;
- }
- else {
- /* To be on the safe side, a check should be included
- * at this point to check if we are overrunning
- * Tachyon.
- */
- update_OCQ_indx(fi);
- return_value = TRUE;
- }
- update_EDB_indx(fi);
- update_tachyon_header_indx(fi);
- LEAVE("tx_sequence");
- return return_value;
-}
-
-static int get_free_header(struct fc_info *fi)
-{
-u_short temp_ox_id;
-u_int *tach_header, initial_indx = fi->q.tachyon_header_indx;
- /* Check if the header is in use.
- * We could have an outstanding command.
- * We should find a free slot as we can queue a
- * maximum of 32 SCSI commands only.
- */
- tach_header = fi->q.ptr_tachyon_header[fi->q.tachyon_header_indx];
- temp_ox_id = ntohl(*(tach_header + 6)) >> 16;
- /* We care about the SCSI writes only. Those are the wicked ones
- * that need an additional set of buffers.
- */
- while(temp_ox_id <= MAX_SCSI_XID) {
- update_tachyon_header_indx(fi);
- if (fi->q.tachyon_header_indx == initial_indx) {
- /* Should never happen.
- */
- T_MSG("No free Tachyon headers available");
- reset_tachyon(fi, SOFTWARE_RESET);
- return 1;
- }
- tach_header = fi->q.ptr_tachyon_header[fi->q.tachyon_header_indx];
- temp_ox_id = ntohl(*(tach_header + 6)) >> 16;
- }
- return 0;
-}
-
-static int get_free_EDB(struct fc_info *fi)
-{
-unsigned int initial_indx = fi->q.edb_buffer_indx;
- /* Check if the EDB is in use.
- * We could have an outstanding SCSI Write command.
- * We should find a free slot as we can queue a
- * maximum of 32 SCSI commands only.
- */
- while (fi->q.free_edb_list[fi->q.edb_buffer_indx] != EDB_FREE) {
- update_EDB_indx(fi);
- if (fi->q.edb_buffer_indx == initial_indx) {
- T_MSG("No free EDB buffers avaliable")
- reset_tachyon(fi, SOFTWARE_RESET);
- return 1;
- }
- }
- return 0;
-}
-
-static int validate_login(struct fc_info *fi, u_int *base_ptr)
-{
-struct fc_node_info *q = fi->node_info_list;
-char n_port_name[PORT_NAME_LEN];
-char node_name[NODE_NAME_LEN];
-u_int s_id;
- ENTER("validate_login");
- /*index to Port Name in the payload. We need the 8 byte Port Name */
- memcpy(n_port_name, base_ptr + 10, PORT_NAME_LEN);
- memcpy(node_name, base_ptr + 12, NODE_NAME_LEN);
- s_id = ntohl(*(base_ptr + 3)) & 0x00FFFFFF;
-
- /* check if Fibre Channel IDs have changed */
- while(q != NULL) {
- if (memcmp(n_port_name, q->hw_addr, PORT_NAME_LEN) == 0) {
- if ((s_id != q->d_id) || (memcmp(node_name, q->node_name, NODE_NAME_LEN) != 0)) {
- DPRINTK1("Fibre Channel ID of Node has changed. Txing LOGO.");
- return 0;
- }
- q->login = LOGIN_COMPLETED;
-#if DEBUG_5526_2
- display_cache(fi);
-#endif
- return 1;
- }
- q = q->next;
- }
- DPRINTK1("Port Name does not match. Txing LOGO.");
- LEAVE("validate_login");
- return 0;
-}
-
-static void add_to_address_cache(struct fc_info *fi, u_int *base_ptr)
-{
-int size = sizeof(struct fc_node_info);
-struct fc_node_info *p, *q = fi->node_info_list, *r = NULL;
-char n_port_name[PORT_NAME_LEN];
-u_int s_id;
- ENTER("add_to_address_cache");
- /*index to Port Name in the payload. We need the 8 byte Port Name */
- memcpy(n_port_name, base_ptr + 13, PORT_NAME_LEN);
- s_id = ntohl(*(base_ptr + 3)) & 0x00FFFFFF;
-
- /* check if info already exists */
- while(q != NULL) {
- if (memcmp(n_port_name, q->hw_addr, PORT_NAME_LEN) == 0) {
- if (s_id != q->d_id) {
- memcpy(&(q->c_of_s[0]), base_ptr + 17, 3 * sizeof(CLASS_OF_SERVICE));
- q->mtu = ntohl(*(base_ptr + 10)) & 0x00000FFF;
- q->d_id = s_id;
- memcpy(q->node_name, base_ptr + 15, NODE_NAME_LEN);
- }
- q->login = LOGIN_COMPLETED;
- q->scsi = FALSE;
- fi->num_nodes++;
-#if DEBUG_5526_2
- display_cache(fi);
-#endif
- return;
- }
- r = q;
- q = q->next;
- }
- p = (struct fc_node_info *)kmalloc(size, GFP_ATOMIC);
- if (p == NULL) {
- T_MSG("kmalloc failed in add_to_address_cache()");
- return;
- }
- memcpy(&(p->c_of_s[0]), base_ptr + 17, 3 * sizeof(CLASS_OF_SERVICE));
- p->mtu = ntohl(*(base_ptr + 10)) & 0x00000FFF;
- p->d_id = s_id;
- memcpy(p->hw_addr, base_ptr + 13, PORT_NAME_LEN);
- memcpy(p->node_name, base_ptr + 15, NODE_NAME_LEN);
- p->login = LOGIN_COMPLETED;
- p->scsi = FALSE;
- p->target_id = 0xFF;
- p->next = NULL;
- if (fi->node_info_list == NULL)
- fi->node_info_list = p;
- else
- r->next = p;
- fi->num_nodes++;
-#if DEBUG_5526_2
- display_cache(fi);
-#endif
- LEAVE("add_to_address_cache");
- return;
-}
-
-static void remove_from_address_cache(struct fc_info *fi, u_int *base_ptr, u_int cmnd_code)
-{
-struct fc_node_info *q = fi->node_info_list;
-u_int s_id;
- ENTER("remove_from_address_cache");
- s_id = ntohl(*(base_ptr + 3)) & 0x00FFFFFF;
- switch(cmnd_code) {
- case ELS_LOGO:
- /* check if info exists */
- while (q != NULL) {
- if (s_id == q->d_id) {
- if (q->login == LOGIN_COMPLETED)
- q->login = LOGIN_ATTEMPTED;
- if (fi->num_nodes > 0)
- fi->num_nodes--;
-#if DEBUG_5526_2
- display_cache(fi);
-#endif
- return;
- }
- q = q->next;
- }
- DPRINTK1("ELS_LOGO received from node 0x%x which is not logged-in", s_id);
- break;
- case ELS_RSCN:
- {
- int payload_len = ntohl(*(base_ptr + 8)) & 0xFF;
- int no_of_pages, i;
- u_char address_format;
- u_short received_ox_id = ntohl(*(base_ptr + 6)) >> 16;
- u_int node_id, mask, *page_ptr = base_ptr + 9;
- if ((payload_len < 4) || (payload_len > 256)) {
- DPRINTK1("RSCN with invalid payload length received");
- tx_ls_rjt(fi, s_id, received_ox_id, LOGICAL_ERR, RECV_FIELD_SIZE);
- return;
- }
- /* Page_size includes the Command Code */
- no_of_pages = (payload_len / 4) - 1;
- for (i = 0; i < no_of_pages; i++) {
- address_format = ntohl(*page_ptr) >> 24;
- node_id = ntohl(*page_ptr) & 0x00FFFFFF;
- switch(address_format) {
- case PORT_ADDRESS_FORMAT:
- rscn_handler(fi, node_id);
- break;
- case AREA_ADDRESS_FORMAT:
- case DOMAIN_ADDRESS_FORMAT:
- if (address_format == AREA_ADDRESS_FORMAT)
- mask = 0xFFFF00;
- else
- mask = 0xFF0000;
- while(q != NULL) {
- if ((q->d_id & mask) == (node_id & mask))
- rscn_handler(fi, q->d_id);
- q = q->next;
- }
- /* There might be some new nodes to be
- * discovered. But, some of the earlier
- * requests as a result of the RSCN might be
- * in progress. We don't want to duplicate that
- * effort. So letz call SCR after a lag.
- */
- fi->explore_timer.function = scr_timer;
- fi->explore_timer.data = (unsigned long)fi;
- fi->explore_timer.expires = RUN_AT((no_of_pages*3*HZ)/100);
- init_timer(&fi->explore_timer);
- add_timer(&fi->explore_timer);
- break;
- default:
- T_MSG("RSCN with invalid address format received");
- tx_ls_rjt(fi, s_id, received_ox_id, LOGICAL_ERR, NO_EXPLN);
- }
- page_ptr += 1;
- } /* end of for loop */
- } /* end of case RSCN: */
- break;
- }
-#if DEBUG_5526_2
- display_cache(fi);
-#endif
- LEAVE("remove_from_address_cache");
-}
-
-static void rscn_handler(struct fc_info *fi, u_int node_id)
-{
-struct fc_node_info *q = fi->node_info_list;
-int login_state = sid_logged_in(fi, node_id);
- if ((login_state == NODE_LOGGED_IN) || (login_state == NODE_PROCESS_LOGGED_IN)) {
- while(q != NULL) {
- if (q->d_id == node_id) {
- q->login = LOGIN_ATTEMPTED;
- if (fi->num_nodes > 0)
- fi->num_nodes--;
- break;
- }
- else
- q = q->next;
- }
- }
- else
- if (login_state == NODE_LOGGED_OUT)
- tx_adisc(fi, ELS_ADISC, node_id, OX_ID_FIRST_SEQUENCE);
- else
- if (login_state == NODE_LOGGED_OUT)
- tx_logi(fi, ELS_PLOGI, node_id);
-}
-
-static void scr_timer(unsigned long data)
-{
-struct fc_info *fi = (struct fc_info *)data;
- del_timer(&fi->explore_timer);
- tx_name_server_req(fi, FCS_GP_ID4);
-}
-
-static int sid_logged_in(struct fc_info *fi, u_int s_id)
-{
-struct fc_node_info *temp = fi->node_info_list;
- while(temp != NULL)
- if ((temp->d_id == s_id) && (temp->login == LOGIN_COMPLETED)) {
- if (temp->scsi != FALSE)
- return NODE_PROCESS_LOGGED_IN;
- else
- return NODE_LOGGED_IN;
- }
- else
- if ((temp->d_id == s_id) && (temp->login != LOGIN_COMPLETED))
- return NODE_LOGGED_OUT;
- else
- temp = temp->next;
- return NODE_NOT_PRESENT;
-}
-
-static void mark_scsi_sid(struct fc_info *fi, u_int *buff_addr, u_char action)
-{
-struct fc_node_info *temp = fi->node_info_list;
-u_int s_id;
-u_int service_params;
- s_id = ntohl(*(buff_addr + 3)) & 0x00FFFFFF;
- service_params = ntohl(*(buff_addr + 12)) & 0x000000F0;
- while(temp != NULL)
- if ((temp->d_id == s_id) && (temp->login == LOGIN_COMPLETED)) {
- if (action == DELETE_ENTRY) {
- temp->scsi = FALSE;
-#if DEBUG_5526_2
- display_cache(fi);
-#endif
- return;
- }
- /* Check if it is a SCSI Target */
- if (!(service_params & TARGET_FUNC)) {
- temp->scsi = INITIATOR;
-#if DEBUG_5526_2
- display_cache(fi);
-#endif
- return;
- }
- temp->scsi = TARGET;
- /* This helps to maintain the target_id no matter what your
- * Fibre Channel ID is.
- */
- if (temp->target_id == 0xFF) {
- if (fi->g.no_of_targets <= MAX_SCSI_TARGETS)
- temp->target_id = fi->g.no_of_targets++;
- else
- T_MSG("MAX TARGETS reached!");
- }
- else
- DPRINTK1("Target_id %d already present", temp->target_id);
-#if DEBUG_5526_2
- display_cache(fi);
-#endif
- return;
- }
- else
- temp = temp->next;
- return;
-}
-
-static int node_logged_in_prev(struct fc_info *fi, u_int *buff_addr)
-{
-struct fc_node_info *temp;
-u_char *data = (u_char *)buff_addr;
-u_int s_id;
-char node_name[NODE_NAME_LEN];
- s_id = ntohl(*(buff_addr + 3)) & 0x00FFFFFF;
- memcpy(node_name, buff_addr + 12, NODE_NAME_LEN);
- /* point to port_name in the ADISC payload */
- data += 10 * 4;
- /* point to last 6 bytes of port_name */
- data += 2;
- temp = look_up_cache(fi, data);
- if (temp != NULL) {
- if ((temp->d_id == s_id) && (memcmp(node_name, temp->node_name, NODE_NAME_LEN) == 0)) {
- temp->login = LOGIN_COMPLETED;
-#if DEBUG_5526_2
- display_cache(fi);
-#endif
- return TRUE;
- }
- }
- return FALSE;
-}
-
-static struct fc_node_info *look_up_cache(struct fc_info *fi, char *data)
-{
-struct fc_node_info *temp_list = fi->node_info_list, *q;
-u_char n_port_name[FC_ALEN], temp_addr[FC_ALEN];
- ENTER("look_up_cache");
- memcpy(n_port_name, data, FC_ALEN);
- while(temp_list) {
- if (memcmp(n_port_name, &(temp_list->hw_addr[2]), FC_ALEN) == 0)
- return temp_list;
- else
- temp_list = temp_list->next;
- }
-
- /* Broadcast IP ?
- */
- temp_addr[0] = temp_addr[1] = temp_addr[2] = 0xFF;
- temp_addr[3] = temp_addr[4] = temp_addr[5] = 0xFF;
- if (memcmp(n_port_name, temp_addr, FC_ALEN) == 0) {
- q = (struct fc_node_info *)kmalloc(sizeof(struct fc_node_info), GFP_ATOMIC);
- if (q == NULL) {
- T_MSG("kmalloc failed in look_up_cache()");
- return NULL;
- }
- q->d_id = BROADCAST;
- return q;
- }
- LEAVE("look_up_cache");
- return NULL;
-}
-
-static int display_cache(struct fc_info *fi)
-{
-struct fc_node_info *q = fi->node_info_list;
-#if DEBUG_5526_2
-struct ox_id_els_map *temp_ox_id_list = fi->ox_id_list;
-#endif
-int count = 0, j;
- printk("\nFibre Channel Node Information for %s\n", fi->name);
- printk("My FC_ID = %x, My WWN = %x %x, ", fi->g.my_id, fi->g.my_node_name_high, fi->g.my_node_name_low);
- if (fi->g.ptp_up == TRUE)
- printk("Port_Type = N_Port\n");
- if (fi->g.loop_up == TRUE)
- printk("Port_Type = L_Port\n");
- while(q != NULL) {
- printk("WWN = ");
- for (j = 0; j < PORT_NAME_LEN; j++)
- printk("%x ", q->hw_addr[j]);
- printk("FC_ID = %x, ", q->d_id);
- printk("Login = ");
- if (q->login == LOGIN_COMPLETED)
- printk("ON ");
- else
- printk("OFF ");
- if (q->scsi == TARGET)
- printk("Target_ID = %d ", q->target_id);
- printk("\n");
- q = q->next;
- count++;
- }
-
-#if DEBUG_5526_2
- printk("OX_ID -> ELS Map\n");
- while(temp_ox_id_list) {
- printk("ox_id = %x, ELS = %x\n", temp_ox_id_list->ox_id, temp_ox_id_list->els);
- temp_ox_id_list = temp_ox_id_list->next;
- }
-#endif
-
- return 0;
-}
-
-static struct net_device_stats * iph5526_get_stats(struct net_device *dev)
-{
-struct fc_info *fi = dev->priv;
- return (struct net_device_stats *) &fi->fc_stats;
-}
-
-
-/* SCSI stuff starts here */
-
-int iph5526_detect(Scsi_Host_Template *tmpt)
-{
- struct Scsi_Host *host = NULL;
- struct iph5526_hostdata *hostdata;
- struct fc_info *fi = NULL;
- int no_of_hosts = 0, i, j, count = 0;
- u_int pci_maddr = 0;
- struct pci_dev *pdev = NULL;
- unsigned long timeout;
-
- tmpt->proc_name = "iph5526";
-
- for (i = 0; i <= MAX_FC_CARDS; i++)
- fc[i] = NULL;
-
- for (i = 0; clone_list[i].vendor_id != 0; i++)
- while ((pdev = pci_find_device(clone_list[i].vendor_id, clone_list[i].device_id, pdev))) {
- unsigned short pci_command;
- if (pci_enable_device(pdev))
- continue;
- if (count < MAX_FC_CARDS) {
- fc[count] = kmalloc(sizeof(struct fc_info), GFP_ATOMIC);
- if (fc[count] == NULL) {
- printk("iph5526.c: Unable to register card # %d\n", count + 1);
- return no_of_hosts;
- }
- memset(fc[count], 0, sizeof(struct fc_info));
- }
- else {
- printk("iph5526.c: Maximum Number of cards reached.\n");
- return no_of_hosts;
- }
-
- fi = fc[count];
- sprintf(fi->name, "fc%d", count);
-
- host = scsi_register(tmpt, sizeof(struct iph5526_hostdata));
- if(host==NULL) {
- kfree(fc[count]);
- return no_of_hosts;
- }
-
- hostdata = (struct iph5526_hostdata *)host->hostdata;
- memset(hostdata, 0 , sizeof(struct iph5526_hostdata));
- for (j = 0; j < MAX_SCSI_TARGETS; j++)
- hostdata->tag_ages[j] = jiffies;
- hostdata->fi = fi;
- fi->host = host;
- //host->max_id = MAX_SCSI_TARGETS;
- host->max_id = 5;
- host->this_id = tmpt->this_id;
-
- pci_maddr = pci_resource_start(pdev, 0);
- if (pci_resource_flags(pdev, 0) & IORESOURCE_IO) {
- printk("iph5526.c : Cannot find proper PCI device base address.\n");
- scsi_unregister(host);
- kfree(fc[count]);
- fc[count] = NULL;
- continue;
- }
-
- DPRINTK("pci_maddr = %x", pci_maddr);
- pci_read_config_word(pdev, PCI_COMMAND, &pci_command);
-
- pci_irq_line = pdev->irq;
- printk("iph5526.c: PCI BIOS reports %s at i/o %#x, irq %d.\n", clone_list[i].name, pci_maddr, pci_irq_line);
- fi->g.mem_base = ioremap(pci_maddr & PAGE_MASK, 1024);
-
- /* We use Memory Mapped IO. The initial space contains the
- * PCI Configuration registers followed by the (i) chip
- * registers followed by the Tachyon registers.
- */
- /* Thatz where (i)chip maps Tachyon Address Space.
- */
- fi->g.tachyon_base = (u_long)fi->g.mem_base + TACHYON_OFFSET + ( pci_maddr & ~PAGE_MASK );
- DPRINTK("fi->g.tachyon_base = %x", (u_int)fi->g.tachyon_base);
- if (fi->g.mem_base == NULL) {
- printk("iph5526.c : ioremap failed!!!\n");
- scsi_unregister(host);
- kfree(fc[count]);
- fc[count] = NULL;
- continue;
- }
- DPRINTK("IRQ1 = %d\n", pci_irq_line);
- printk(version);
- fi->base_addr = (long) pdev;
-
- if (pci_irq_line) {
- int irqval = 0;
- /* Found it, get IRQ.
- */
- irqval = request_irq(pci_irq_line, &tachyon_interrupt, pci_irq_line ? SA_SHIRQ : 0, fi->name, host);
- if (irqval) {
- printk("iph5526.c : Unable to get IRQ %d (irqval = %d).\n", pci_irq_line, irqval);
- scsi_unregister(host);
- kfree(fc[count]);
- fc[count] = NULL;
- continue;
- }
- host->irq = fi->irq = pci_irq_line;
- pci_irq_line = 0;
- fi->clone_id = clone_list[i].vendor_id;
- }
-
- if (!initialize_register_pointers(fi) || !tachyon_init(fi)) {
- printk("iph5526.c: TACHYON initialization failed for card # %d!!!\n", count + 1);
- free_irq(host->irq, host);
- scsi_unregister(host);
- if (fi)
- clean_up_memory(fi);
- kfree(fc[count]);
- fc[count] = NULL;
- break;
- }
- DPRINTK1("Fibre Channel card initialized");
- /* Wait for the Link to come up and the login process
- * to complete.
- */
- for(timeout = jiffies + 10*HZ; time_before(jiffies, timeout) && ((fi->g.link_up == FALSE) || (fi->g.port_discovery == TRUE) || (fi->g.explore_fabric == TRUE) || (fi->g.perform_adisc == TRUE));)
- {
- cpu_relax();
- barrier();
- }
-
- count++;
- no_of_hosts++;
- }
- DPRINTK1("no_of_hosts = %d",no_of_hosts);
-
- /* This is to make sure that the ACC to the PRLI comes in
- * for the last ALPA.
- */
- mdelay(1000); /* Ugly! Let the Gods forgive me */
-
- DPRINTK1("leaving iph5526_detect\n");
- return no_of_hosts;
-}
-
-
-int iph5526_biosparam(struct scsi_device *sdev, struct block_device *n,
- sector_t capacity, int ip[])
-{
-int size = capacity;
- ip[0] = 64;
- ip[1] = 32;
- ip[2] = size >> 11;
- if (ip[2] > 1024) {
- ip[0] = 255;
- ip[1] = 63;
- ip[2] = size / (ip[0] * ip[1]);
- }
- return 0;
-}
-
-int iph5526_queuecommand(Scsi_Cmnd *Cmnd, void (*done) (Scsi_Cmnd *))
-{
-int int_required = 0;
-u_int r_ctl = FC4_DEVICE_DATA | UNSOLICITED_COMMAND;
-u_int type = TYPE_FCP | SEQUENCE_INITIATIVE;
-u_int frame_class = Cmnd->device->id;
-u_short ox_id = OX_ID_FIRST_SEQUENCE;
-struct Scsi_Host *host = Cmnd->device->host;
-struct iph5526_hostdata *hostdata = (struct iph5526_hostdata*)host->hostdata;
-struct fc_info *fi = hostdata->fi;
-struct fc_node_info *q;
-u_long flags;
- ENTER("iph5526_queuecommand");
-
- spin_lock_irqsave(&fi->fc_lock, flags);
- Cmnd->scsi_done = done;
-
- if (Cmnd->device->tagged_supported) {
- switch(Cmnd->tag) {
- case SIMPLE_QUEUE_TAG:
- hostdata->cmnd.fcp_cntl = FCP_CNTL_QTYPE_SIMPLE;
- break;
- case HEAD_OF_QUEUE_TAG:
- hostdata->cmnd.fcp_cntl = FCP_CNTL_QTYPE_HEAD_OF_Q;
- break;
- case ORDERED_QUEUE_TAG:
- hostdata->cmnd.fcp_cntl = FCP_CNTL_QTYPE_ORDERED;
- break;
- default:
- if ((jiffies - hostdata->tag_ages[Cmnd->device->id]) > (5 * HZ)) {
- hostdata->cmnd.fcp_cntl = FCP_CNTL_QTYPE_ORDERED;
- hostdata->tag_ages[Cmnd->device->id] = jiffies;
- }
- else
- hostdata->cmnd.fcp_cntl = FCP_CNTL_QTYPE_SIMPLE;
- break;
- }
- }
- /*else
- hostdata->cmnd.fcp_cntl = FCP_CNTL_QTYPE_UNTAGGED;
- */
-
- hostdata->cmnd.fcp_addr[3] = 0;
- hostdata->cmnd.fcp_addr[2] = 0;
- hostdata->cmnd.fcp_addr[1] = 0;
- hostdata->cmnd.fcp_addr[0] = htons(Cmnd->device->lun);
-
- memcpy(&hostdata->cmnd.fcp_cdb, Cmnd->cmnd, Cmnd->cmd_len);
- hostdata->cmnd.fcp_data_len = htonl(Cmnd->request_bufflen);
-
- /* Get an used OX_ID. We could have pending commands.
- */
- if (get_scsi_oxid(fi)) {
- spin_unlock_irqrestore(&fi->fc_lock, flags);
- return 1;
- }
- fi->q.free_scsi_oxid[fi->g.scsi_oxid] = OXID_INUSE;
-
- /* Maintain a handler so that we can associate the done() function
- * on completion of the SCSI command.
- */
- hostdata->cmnd_handler[fi->g.scsi_oxid] = Cmnd;
-
- switch(Cmnd->cmnd[0]) {
- case WRITE_6:
- case WRITE_10:
- case WRITE_12:
- fi->g.type_of_frame = FC_SCSI_WRITE;
- hostdata->cmnd.fcp_cntl = htonl(FCP_CNTL_WRITE | hostdata->cmnd.fcp_cntl);
- break;
- default:
- fi->g.type_of_frame = FC_SCSI_READ;
- hostdata->cmnd.fcp_cntl = htonl(FCP_CNTL_READ | hostdata->cmnd.fcp_cntl);
- }
-
- memcpy(fi->q.ptr_fcp_cmnd[fi->q.fcp_cmnd_indx], &(hostdata->cmnd), sizeof(fcp_cmd));
-
- q = resolve_target(fi, Cmnd->device->id);
-
- if (q == NULL) {
- u_int bad_id = fi->g.my_ddaa | 0xFE;
- /* We transmit to an non-existant AL_PA so that the "done"
- * function can be called while receiving the interrupt
- * due to a Timeout for a bad AL_PA. In a PTP configuration,
- * the int_required field is set, since there is no notion
- * of AL_PAs. This approach sucks, but works alright!
- */
- if (fi->g.ptp_up == TRUE)
- int_required = 1;
- tx_exchange(fi, (char *)(&(hostdata->cmnd)), sizeof(fcp_cmd), r_ctl, type, bad_id, fi->g.my_mtu, int_required, ox_id, FC_SCSI_BAD_TARGET);
- spin_unlock_irqrestore(&fi->fc_lock, flags);
- DPRINTK1("Target ID %x not present", Cmnd->target);
- return 0;
- }
- if (q->login == LOGIN_COMPLETED) {
- if (add_to_sest(fi, Cmnd, q)) {
- DPRINTK1("add_to_sest() failed.");
- spin_unlock_irqrestore(&fi->fc_lock, flags);
- return 0;
- }
- tx_exchange(fi, (char *)(fi->q.ptr_fcp_cmnd[fi->q.fcp_cmnd_indx]), sizeof(fcp_cmd), r_ctl, type, q->d_id, q->mtu, int_required, ox_id, frame_class << 16);
- update_FCP_CMND_indx(fi);
- }
- spin_unlock_irqrestore(&fi->fc_lock, flags);
- /* If q != NULL, then we have a SCSI Target.
- * If q->login != LOGIN_COMPLETED, then that device could be
- * offline temporarily. So we let the command to time-out.
- */
- LEAVE("iph5526_queuecommand");
- return 0;
-}
-
-int iph5526_abort(Scsi_Cmnd *Cmnd)
-{
-struct Scsi_Host *host = Cmnd->device->host;
-struct iph5526_hostdata *hostdata = (struct iph5526_hostdata *)host->hostdata;
-struct fc_info *fi = hostdata->fi;
-struct fc_node_info *q;
-u_int r_ctl = FC4_DEVICE_DATA | UNSOLICITED_COMMAND;
-u_int type = TYPE_FCP | SEQUENCE_INITIATIVE;
-u_short ox_id = OX_ID_FIRST_SEQUENCE;
-int int_required = 1, i, abort_status = FALSE;
-u_long flags;
-
- ENTER("iph5526_abort");
-
- spin_lock_irqsave(&fi->fc_lock, flags);
-
- q = resolve_target(fi, Cmnd->device->id);
- if (q == NULL) {
- u_int bad_id = fi->g.my_ddaa | 0xFE;
- /* This should not happen as we should always be able to
- * resolve a target id. But, jus in case...
- * We transmit to an non-existant AL_PA so that the done
- * function can be called while receiving the interrupt
- * for a bad AL_PA.
- */
- DPRINTK1("Unresolved Target ID!");
- tx_exchange(fi, (char *)(&(hostdata->cmnd)), sizeof(fcp_cmd), r_ctl, type, bad_id, fi->g.my_mtu, int_required, ox_id, FC_SCSI_BAD_TARGET);
- DPRINTK1("Target ID %x not present", Cmnd->target);
- spin_unlock_irqrestore(&fi->fc_lock, flags);
- return FAILED;
- }
-
- /* If q != NULL, then we have a SCSI Target. If
- * q->login != LOGIN_COMPLETED, then that device could
- * be offline temporarily. So we let the command to time-out.
- */
-
- /* Get the OX_ID for the Command to be aborted.
- */
- for (i = 0; i <= MAX_SCSI_XID; i++) {
- if (hostdata->cmnd_handler[i] == Cmnd) {
- hostdata->cmnd_handler[i] = NULL;
- ox_id = i;
- break;
- }
- }
- if (i > MAX_SCSI_XID) {
- T_MSG("Command could not be resolved to OX_ID");
- spin_unlock_irqrestore(&fi->fc_lock, flags);
- return FAILED;
- }
-
- switch(Cmnd->cmnd[0]) {
- case WRITE_6:
- case WRITE_10:
- case WRITE_12:
- break;
- default:
- ox_id |= SCSI_READ_BIT;
- }
- abort_status = abort_exchange(fi, ox_id);
-
- if ((q->login == LOGIN_COMPLETED) && (abort_status == TRUE)) {
- /* Then, transmit an ABTS to the target. The rest
- * is done when the BA_ACC is received for the ABTS.
- */
- tx_abts(fi, q->d_id, ox_id);
- }
- else {
- u_int STE_bit;
- u_short x_id;
- /* Invalidate resources for that Exchange.
- */
- x_id = ox_id & MAX_SCSI_XID;
- STE_bit = ntohl(*fi->q.ptr_sest[x_id]);
- if (STE_bit & SEST_V) {
- *(fi->q.ptr_sest[x_id]) &= htonl(SEST_INV);
- invalidate_SEST_entry(fi, ox_id);
- }
- }
-
- LEAVE("iph5526_abort");
- spin_unlock_irqrestore(&fi->fc_lock, flags);
- return SUCCESS;
-}
-
-static int abort_exchange(struct fc_info *fi, u_short ox_id)
-{
-u_short x_id;
-volatile u_int flush_SEST, STE_bit;
- x_id = ox_id & MAX_SCSI_XID;
- DPRINTK1("Aborting Exchange %x", ox_id);
-
- STE_bit = ntohl(*fi->q.ptr_sest[x_id]);
- /* Is the Exchange still active?.
- */
- if (STE_bit & SEST_V) {
- if (ox_id & SCSI_READ_BIT) {
- /* If the Exchange to be aborted is Inbound,
- * Flush the SEST Entry from Tachyon's Cache.
- */
- *(fi->q.ptr_sest[x_id]) &= htonl(SEST_INV);
- flush_tachyon_cache(fi, ox_id);
- flush_SEST = readl(fi->t_r.ptr_tach_flush_oxid_reg);
- while ((flush_SEST & 0x80000000) != 0)
- flush_SEST = readl(fi->t_r.ptr_tach_flush_oxid_reg);
- STE_bit = ntohl(*fi->q.ptr_sest[x_id]);
- while ((STE_bit & 0x80000000) != 0)
- STE_bit = ntohl(*fi->q.ptr_sest[x_id]);
- flush_SEST = readl(fi->t_r.ptr_tach_flush_oxid_reg);
- invalidate_SEST_entry(fi, ox_id);
- }
- else {
- int i;
- u_int *ptr_edb;
- /* For In-Order Reassembly, the following is done:
- * First, write zero as the buffer length in the EDB.
- */
- ptr_edb = bus_to_virt(ntohl(*(fi->q.ptr_sest[x_id] + 7)));
- for (i = 0; i < EDB_LEN; i++)
- if (fi->q.ptr_edb[i] == ptr_edb)
- break;
- if (i < EDB_LEN)
- *ptr_edb = *ptr_edb & 0x0000FFFF;
- else
- T_MSG("EDB not found while clearing in abort_exchange()");
- }
- DPRINTK1("Exchange %x invalidated", ox_id);
- return TRUE;
- }
- else {
- DPRINTK1("SEST Entry for exchange %x not valid", ox_id);
- return FALSE;
- }
-}
-
-static void flush_tachyon_cache(struct fc_info *fi, u_short ox_id)
-{
-volatile u_int tachyon_status;
- if (fi->g.loop_up == TRUE) {
- writel(HOST_CONTROL, fi->t_r.ptr_fm_control_reg);
- /* Make sure that the Inbound FIFO is empty.
- */
- do {
- tachyon_status = readl(fi->t_r.ptr_tach_status_reg);
- udelay(200);
- }while ((tachyon_status & RECEIVE_FIFO_EMPTY) == 0);
- /* Ok. Go ahead and flushhhhhhhhh!
- */
- writel(0x80000000 | ox_id, fi->t_r.ptr_tach_flush_oxid_reg);
- writel(EXIT_HOST_CONTROL, fi->t_r.ptr_fm_control_reg);
- return;
- }
- if (fi->g.ptp_up == TRUE) {
- take_tachyon_offline(fi);
- /* Make sure that the Inbound FIFO is empty.
- */
- do {
- tachyon_status = readl(fi->t_r.ptr_tach_status_reg);
- udelay(200);
- }while ((tachyon_status & RECEIVE_FIFO_EMPTY) == 0);
- writel(0x80000000 | ox_id, fi->t_r.ptr_tach_flush_oxid_reg);
- /* Write the Initialize command to the FM Control reg.
- */
- fi->g.n_port_try = TRUE;
- DPRINTK1("In abort_exchange, TACHYON initializing as N_Port...\n");
- writel(INITIALIZE, fi->t_r.ptr_fm_control_reg);
- }
-}
-
-static struct fc_node_info *resolve_target(struct fc_info *fi, u_char target)
-{
-struct fc_node_info *temp = fi->node_info_list;
- while(temp != NULL)
- if (temp->target_id == target) {
- if ((temp->scsi == TARGET) && (temp->login == LOGIN_COMPLETED))
- return temp;
- else {
- if (temp->login != LOGIN_COMPLETED) {
- /* The Target is not currently logged in.
- * It could be a Target on the Local Loop or
- * on a Remote Loop connected through a switch.
- * In either case, we will know whenever the Target
- * comes On-Line again. We let the command to
- * time-out so that it gets retried.
- */
- T_MSG("Target %d not logged in.", temp->target_id);
- tx_logi(fi, ELS_PLOGI, temp->d_id);
- return temp;
- }
- else {
- if (temp->scsi != TARGET) {
- /* For some reason, we did not get a response to
- * PRLI. Letz try it again...
- */
- DPRINTK1("Node not PRLIied. Txing PRLI...");
- tx_prli(fi, ELS_PRLI, temp->d_id, OX_ID_FIRST_SEQUENCE);
- }
- }
- return temp;
- }
- }
- else
- temp = temp->next;
- return NULL;
-}
-
-static int add_to_sest(struct fc_info *fi, Scsi_Cmnd *Cmnd, struct fc_node_info *ni)
-{
-/* we have at least 1 buffer, the terminator */
-int no_of_sdb_buffers = 1, i;
-int no_of_edb_buffers = 0;
-u_int *req_buffer = (u_int *)Cmnd->request_buffer;
-u_int *ptr_sdb = NULL;
-struct scatterlist *sl1, *sl2 = NULL;
-int no_of_sg = 0;
-
- switch(fi->g.type_of_frame) {
- case FC_SCSI_READ:
- fi->g.inb_sest_entry.flags_and_byte_offset = htonl(INB_SEST_VED);
- fi->g.inb_sest_entry.byte_count = 0;
- fi->g.inb_sest_entry.no_of_recvd_frames = 0;
- fi->g.inb_sest_entry.no_of_expected_frames = 0;
- fi->g.inb_sest_entry.last_fctl = 0;
-
- if (Cmnd->use_sg) {
- no_of_sg = Cmnd->use_sg;
- sl1 = sl2 = (struct scatterlist *)Cmnd->request_buffer;
- for (i = 0; i < no_of_sg; i++) {
- no_of_sdb_buffers += sl1->length / SEST_BUFFER_SIZE;
- if (sl1->length % SEST_BUFFER_SIZE)
- no_of_sdb_buffers++;
- sl1++;
- }
- }
- else {
- no_of_sdb_buffers += Cmnd->request_bufflen / SEST_BUFFER_SIZE;
- if (Cmnd->request_bufflen % SEST_BUFFER_SIZE)
- no_of_sdb_buffers++;
- } /* if !use_sg */
-
- /* We are working with the premise that at the max we would
- * get a scatter-gather buffer containing 63 buffers
- * of size 1024 bytes each. Is it a _bad_ assumption?
- */
- if (no_of_sdb_buffers > 512) {
- T_MSG("Number of SDB buffers needed = %d", no_of_sdb_buffers);
- T_MSG("Disable Scatter-Gather!!!");
- return 1;
- }
-
-
- /* Store it in the sdb_table so that we can retrieve that
- * free up the memory when the Read Command completes.
- */
- if (get_free_SDB(fi))
- return 1;
- ptr_sdb = fi->q.ptr_sdb_slot[fi->q.sdb_indx];
- fi->q.sdb_slot_status[fi->q.sdb_indx] = SDB_BUSY;
- fi->g.inb_sest_entry.sdb_address = htonl(virt_to_bus(ptr_sdb));
-
- if (Cmnd->use_sg) {
- int count = 0, j;
- for(i = 0; i < no_of_sg; i++) {
- char *addr_ptr = sl2->address;
- count = sl2->length / SEST_BUFFER_SIZE;
- if (sl2->length % SEST_BUFFER_SIZE)
- count++;
- for (j = 0; j < count; j++) {
- *(ptr_sdb) = htonl(virt_to_bus(addr_ptr));
- addr_ptr += SEST_BUFFER_SIZE;
- ptr_sdb++;
- }
- count = 0;
- sl2++;
- }
- }
- else {
- for (i = 0; i < no_of_sdb_buffers - 1; i++) {
- *(ptr_sdb) = htonl(virt_to_bus(req_buffer));
- req_buffer += SEST_BUFFER_SIZE/4;
- ptr_sdb++;
- }
- }
- *(ptr_sdb) = htonl(0x1); /* Terminator */
-
- /* The scratch pad is used to hold the index into the SDB.
- */
- fi->g.inb_sest_entry.scratch_pad = fi->q.sdb_indx;
- fi->g.inb_sest_entry.expected_ro = 0;
- fi->g.inb_sest_entry.buffer_index = 0;
- fi->g.inb_sest_entry.buffer_offset = 0;
- memcpy(fi->q.ptr_sest[fi->g.scsi_oxid], &fi->g.inb_sest_entry, sizeof(INB_SEST_ENTRY));
- break;
- case FC_SCSI_WRITE:
- fi->g.outb_sest_entry.flags_and_did = htonl(OUTB_SEST_VED | ni->d_id);
- fi->g.outb_sest_entry.max_frame_len = htons(ni->mtu << 4);
- fi->g.outb_sest_entry.cntl = htons(ODB_CLASS_3 | ODB_EE_CREDIT | ODB_NO_INT | ODB_NO_COMP);
- fi->g.outb_sest_entry.total_seq_length = INV_SEQ_LEN;
- fi->g.outb_sest_entry.link = htons(OUTB_SEST_LINK);
- fi->g.outb_sest_entry.transaction_id = htonl(fi->g.scsi_oxid);
- fi->g.outb_sest_entry.seq_id = fi->g.seq_id;
- fi->g.outb_sest_entry.reserved = 0x0;
- fi->g.outb_sest_entry.header_length = htons(TACHYON_HEADER_LEN);
-
- {
- u_char df_ctl = 0;
- u_short rx_id = RX_ID_FIRST_SEQUENCE;
- u_int r_ctl = FC4_DEVICE_DATA | SOLICITED_DATA;
- u_int type = TYPE_FCP | SEQUENCE_INITIATIVE;
- /* Multi Frame Sequence ? If yes, set RO bit.
- */
- if (Cmnd->request_bufflen > ni->mtu)
- type |= RELATIVE_OFF_PRESENT;
- build_tachyon_header(fi, fi->g.my_id, r_ctl, ni->d_id, type, fi->g.seq_id, df_ctl, fi->g.scsi_oxid, rx_id, NULL);
- if (get_free_header(fi) || get_free_EDB(fi))
- return 1;
- memcpy(fi->q.ptr_tachyon_header[fi->q.tachyon_header_indx], &(fi->g.tach_header), TACHYON_HEADER_LEN);
- fi->g.outb_sest_entry.header_address = htonl(virt_to_bus(fi->q.ptr_tachyon_header[fi->q.tachyon_header_indx]));
- update_tachyon_header_indx(fi);
- }
-
- if (Cmnd->use_sg) {
- no_of_sg = Cmnd->use_sg;
- sl1 = sl2 = (struct scatterlist *)Cmnd->request_buffer;
- for (i = 0; i < no_of_sg; i++) {
- no_of_edb_buffers += sl1->length / SEST_BUFFER_SIZE;
- if (sl1->length % SEST_BUFFER_SIZE)
- no_of_edb_buffers++;
- sl1++;
- }
- }
- else {
- no_of_edb_buffers += Cmnd->request_bufflen / SEST_BUFFER_SIZE;
- if (Cmnd->request_bufflen % SEST_BUFFER_SIZE)
- no_of_edb_buffers++;
- } /* if !use_sg */
-
-
- /* We need "no_of_edb_buffers" _contiguous_ EDBs
- * that are FREE. Check for that first.
- */
- for (i = 0; i < no_of_edb_buffers; i++) {
- int j;
- if ((fi->q.edb_buffer_indx + no_of_edb_buffers) >= EDB_LEN)
- fi->q.edb_buffer_indx = 0;
- if (fi->q.free_edb_list[fi->q.edb_buffer_indx + i] != EDB_FREE) {
- for (j = 0; j < i; j++)
- update_EDB_indx(fi);
- if (get_free_EDB(fi))
- return 1;
- i = 0;
- }
- }
-
- /* We got enuff FREE EDBs.
- */
- if (Cmnd->use_sg) {
- fi->g.outb_sest_entry.edb_address = htonl(virt_to_bus(fi->q.ptr_edb[fi->q.edb_buffer_indx]));
- sl1 = (struct scatterlist *)Cmnd->request_buffer;
- for(i = 0; i < no_of_sg; i++) {
- int count = 0, j;
- count = sl1->length / SEST_BUFFER_SIZE;
- for (j = 0; j < count; j++) {
- build_EDB(fi, (char *)sl1->address, 0, SEST_BUFFER_SIZE);
- memcpy(fi->q.ptr_edb[fi->q.edb_buffer_indx], &(fi->g.edb), sizeof(EDB));
- /* Mark this EDB as being in use */
- fi->q.free_edb_list[fi->q.edb_buffer_indx] = EDB_BUSY;
- /* We have already made sure that we have enuff
- * free EDBs that are contiguous. So this is
- * safe.
- */
- update_EDB_indx(fi);
- sl1->address += SEST_BUFFER_SIZE;
- }
- /* Just in case itz not a multiple of
- * SEST_BUFFER_SIZE bytes.
- */
- if (sl1->length % SEST_BUFFER_SIZE) {
- build_EDB(fi, (char *)sl1->address, 0, sl1->length % SEST_BUFFER_SIZE);
- memcpy(fi->q.ptr_edb[fi->q.edb_buffer_indx], &(fi->g.edb), sizeof(EDB));
- fi->q.free_edb_list[fi->q.edb_buffer_indx] = EDB_BUSY;
- update_EDB_indx(fi);
- }
- sl1++;
- }
- /* The last EDB is special. It needs the "end bit" to
- * be set.
- */
- *(fi->q.ptr_edb[fi->q.edb_buffer_indx - 1] + 1) = *(fi->q.ptr_edb[fi->q.edb_buffer_indx - 1] + 1) | ntohs(EDB_END);
- }
- else {
- int count = 0, j;
- fi->g.outb_sest_entry.edb_address = htonl(virt_to_bus(fi->q.ptr_edb[fi->q.edb_buffer_indx]));
- count = Cmnd->request_bufflen / SEST_BUFFER_SIZE;
- for (j = 0; j < count; j++) {
- build_EDB(fi, (char *)req_buffer, 0, SEST_BUFFER_SIZE);
- memcpy(fi->q.ptr_edb[fi->q.edb_buffer_indx], &(fi->g.edb), sizeof(EDB));
- /* Mark this EDB as being in use */
- fi->q.free_edb_list[fi->q.edb_buffer_indx] = EDB_BUSY;
- /* We have already made sure that we have enuff
- * free EDBs that are contiguous. So this is
- * safe.
- */
- update_EDB_indx(fi);
- req_buffer += SEST_BUFFER_SIZE;
- }
- /* Just in case itz not a multiple of
- * SEST_BUFFER_SIZE bytes.
- */
- if (Cmnd->request_bufflen % SEST_BUFFER_SIZE) {
- build_EDB(fi, (char *)req_buffer, EDB_END, Cmnd->request_bufflen % SEST_BUFFER_SIZE);
- memcpy(fi->q.ptr_edb[fi->q.edb_buffer_indx], &(fi->g.edb), sizeof(EDB));
- fi->q.free_edb_list[fi->q.edb_buffer_indx] = EDB_BUSY;
- update_EDB_indx(fi);
- }
- else {
- /* Mark the last EDB as the "end edb".
- */
- *(fi->q.ptr_edb[fi->q.edb_buffer_indx - 1] + 1) = *(fi->q.ptr_edb[fi->q.edb_buffer_indx - 1] + 1) | htons(EDB_END);
- }
- }
-
- /* Finally we have something to send!.
- */
- memcpy(fi->q.ptr_sest[fi->g.scsi_oxid], &fi->g.outb_sest_entry, sizeof(OUTB_SEST_ENTRY));
- break;
- }
- return 0;
-}
-
-static void update_FCP_CMND_indx(struct fc_info *fi)
-{
- fi->q.fcp_cmnd_indx++;
- if (fi->q.fcp_cmnd_indx == NO_OF_FCP_CMNDS)
- fi->q.fcp_cmnd_indx = 0;
-}
-
-static int get_scsi_oxid(struct fc_info *fi)
-{
-u_short initial_oxid = fi->g.scsi_oxid;
- /* Check if the OX_ID is in use.
- * We could have an outstanding SCSI command.
- */
- while (fi->q.free_scsi_oxid[fi->g.scsi_oxid] != OXID_AVAILABLE) {
- update_scsi_oxid(fi);
- if (fi->g.scsi_oxid == initial_oxid) {
- T_MSG("No free OX_IDs avaliable")
- reset_tachyon(fi, SOFTWARE_RESET);
- return 1;
- }
- }
- return 0;
-}
-
-static void update_scsi_oxid(struct fc_info *fi)
-{
- fi->g.scsi_oxid++;
- if (fi->g.scsi_oxid == (MAX_SCSI_XID + 1))
- fi->g.scsi_oxid = 0;
-}
-
-static int get_free_SDB(struct fc_info *fi)
-{
-unsigned int initial_indx = fi->q.sdb_indx;
- /* Check if the SDB is in use.
- * We could have an outstanding SCSI Read command.
- * We should find a free slot as we can queue a
- * maximum of 32 SCSI commands only.
- */
- while (fi->q.sdb_slot_status[fi->q.sdb_indx] != SDB_FREE) {
- update_SDB_indx(fi);
- if (fi->q.sdb_indx == initial_indx) {
- T_MSG("No free SDB buffers avaliable")
- reset_tachyon(fi, SOFTWARE_RESET);
- return 1;
- }
- }
- return 0;
-}
-
-static void update_SDB_indx(struct fc_info *fi)
-{
- fi->q.sdb_indx++;
- if (fi->q.sdb_indx == NO_OF_SDB_ENTRIES)
- fi->q.sdb_indx = 0;
-}
-
-int iph5526_release(struct Scsi_Host *host)
-{
-struct iph5526_hostdata *hostdata = (struct iph5526_hostdata*)host->hostdata;
-struct fc_info *fi = hostdata->fi;
- free_irq(host->irq, host);
- iounmap(fi->g.mem_base);
- return 0;
-}
-
-const char *iph5526_info(struct Scsi_Host *host)
-{
-static char buf[80];
- sprintf(buf, "Interphase 5526 Fibre Channel PCI SCSI Adapter using IRQ %d\n", host->irq);
- return buf;
-}
-
-#define NAMELEN 8 /* # of chars for storing dev->name */
-
-static struct net_device *dev_fc[MAX_FC_CARDS];
-
-static int io;
-static int irq;
-static int bad; /* 0xbad = bad sig or no reset ack */
-static int scsi_registered;
-
-
-static int __init iph5526_init(void)
-{
- int i = 0;
-
- driver_template.module = THIS_MODULE;
- scsi_register_host(&driver_template);
- if (driver_template.present)
- scsi_registered = TRUE;
- else {
- printk("iph5526: SCSI registeration failed!!!\n");
- scsi_registered = FALSE;
- scsi_unregister_host(&driver_template);
- }
-
- while(fc[i] != NULL) {
- struct net_device *dev = alloc_fcdev(0);
- int err;
-
- if (!dev) {
- printk("iph5526.c: init_fcdev failed for card #%d\n", i+1);
- break;
- }
- dev->priv = fc[i];
- iph5526_probe_pci(dev);
- err = register_netdev(dev);
- if (err < 0) {
- free_netdev(dev);
- printk("iph5526.c: init_fcdev failed for card #%d\n", i+1);
- break;
- }
- dev_fc[i] = dev;
- i++;
- }
- if (i == 0)
- return -ENODEV;
-
- return 0;
-}
-
-static void __exit iph5526_exit(void)
-{
- int i = 0;
- while(fc[i] != NULL) {
- struct net_device *dev = fc[i]->dev;
- void *priv = dev->priv;
- fc[i]->g.dont_init = TRUE;
- take_tachyon_offline(fc[i]);
- unregister_netdev(dev);
- clean_up_memory(fc[i]);
- if (dev->priv)
- kfree(priv);
- free_netdev(dev);
- dev = NULL;
- i++;
- }
- if (scsi_registered == TRUE)
- scsi_unregister_host(&driver_template);
-}
-
-module_init(iph5526_init);
-module_exit(iph5526_exit);
-
-void clean_up_memory(struct fc_info *fi)
-{
-int i,j;
- ENTER("clean_up_memory");
- if (fi->q.ptr_mfsbq_base)
- free_pages((u_long)bus_to_virt(ntohl(*(fi->q.ptr_mfsbq_base))), 5);
- DPRINTK("after kfree2");
- for (i = 0; i < SFSBQ_LENGTH; i++)
- for (j = 0; j < NO_OF_ENTRIES; j++)
- if (fi->q.ptr_sfs_buffers[i*NO_OF_ENTRIES + j])
- kfree(fi->q.ptr_sfs_buffers[i*NO_OF_ENTRIES + j]);
- DPRINTK("after kfree1");
- if (fi->q.ptr_ocq_base)
- free_page((u_long)fi->q.ptr_ocq_base);
- if (fi->q.ptr_imq_base)
- free_page((u_long)fi->q.ptr_imq_base);
- if (fi->q.ptr_mfsbq_base)
- free_page((u_long)fi->q.ptr_mfsbq_base);
- if (fi->q.ptr_sfsbq_base)
- free_page((u_long)fi->q.ptr_sfsbq_base);
- if (fi->q.ptr_edb_base)
- free_pages((u_long)fi->q.ptr_edb_base, 5);
- if (fi->q.ptr_sest_base)
- free_pages((u_long)fi->q.ptr_sest_base, 5);
- if (fi->q.ptr_tachyon_header_base)
- free_page((u_long)fi->q.ptr_tachyon_header_base);
- if (fi->q.ptr_sdb_base)
- free_pages((u_long)fi->q.ptr_sdb_base, 5);
- if (fi->q.ptr_fcp_cmnd_base)
- free_page((u_long)fi->q.ptr_fcp_cmnd_base);
- DPRINTK("after free_pages");
- if (fi->q.ptr_host_ocq_cons_indx)
- kfree(fi->q.ptr_host_ocq_cons_indx);
- if (fi->q.ptr_host_hpcq_cons_indx)
- kfree(fi->q.ptr_host_hpcq_cons_indx);
- if (fi->q.ptr_host_imq_prod_indx)
- kfree(fi->q.ptr_host_imq_prod_indx);
- DPRINTK("after kfree3");
- while (fi->node_info_list) {
- struct fc_node_info *temp_list = fi->node_info_list;
- fi->node_info_list = fi->node_info_list->next;
- kfree(temp_list);
- }
- while (fi->ox_id_list) {
- struct ox_id_els_map *temp = fi->ox_id_list;
- fi->ox_id_list = fi->ox_id_list->next;
- kfree(temp);
- }
- LEAVE("clean_up_memory");
-}
-
-static int initialize_register_pointers(struct fc_info *fi)
-{
-ENTER("initialize_register_pointers");
-if(fi->g.tachyon_base == 0)
- return -ENOMEM;
-
-fi->i_r.ptr_ichip_hw_control_reg = ICHIP_HW_CONTROL_REG_OFF + fi->g.tachyon_base;
-fi->i_r.ptr_ichip_hw_status_reg = ICHIP_HW_STATUS_REG_OFF + fi->g.tachyon_base;
-fi->i_r.ptr_ichip_hw_addr_mask_reg = ICHIP_HW_ADDR_MASK_REG_OFF + fi->g.tachyon_base;
-fi->t_r.ptr_ocq_base_reg = OCQ_BASE_REGISTER_OFFSET + fi->g.tachyon_base;
-fi->t_r.ptr_ocq_len_reg = OCQ_LENGTH_REGISTER_OFFSET + fi->g.tachyon_base;
-fi->t_r.ptr_ocq_prod_indx_reg = OCQ_PRODUCER_REGISTER_OFFSET + fi->g.tachyon_base;
-fi->t_r.ptr_ocq_cons_indx_reg = OCQ_CONSUMER_REGISTER_OFFSET + fi->g.tachyon_base;
-fi->t_r.ptr_imq_base_reg = IMQ_BASE_REGISTER_OFFSET + fi->g.tachyon_base;
-fi->t_r.ptr_imq_len_reg = IMQ_LENGTH_REGISTER_OFFSET + fi->g.tachyon_base;
-fi->t_r.ptr_imq_cons_indx_reg = IMQ_CONSUMER_REGISTER_OFFSET + fi->g.tachyon_base;
-fi->t_r.ptr_imq_prod_indx_reg = IMQ_PRODUCER_REGISTER_OFFSET + fi->g.tachyon_base;
-fi->t_r.ptr_mfsbq_base_reg = MFSBQ_BASE_REGISTER_OFFSET + fi->g.tachyon_base;
-fi->t_r.ptr_mfsbq_len_reg = MFSBQ_LENGTH_REGISTER_OFFSET + fi->g.tachyon_base;
-fi->t_r.ptr_mfsbq_prod_reg = MFSBQ_PRODUCER_REGISTER_OFFSET + fi->g.tachyon_base;
-fi->t_r.ptr_mfsbq_cons_reg = MFSBQ_CONSUMER_REGISTER_OFFSET + fi->g.tachyon_base;
-fi->t_r.ptr_mfsbuff_len_reg = MFS_LENGTH_REGISTER_OFFSET + fi->g.tachyon_base;
-fi->t_r.ptr_sfsbq_base_reg = SFSBQ_BASE_REGISTER_OFFSET + fi->g.tachyon_base;
-fi->t_r.ptr_sfsbq_len_reg = SFSBQ_LENGTH_REGISTER_OFFSET + fi->g.tachyon_base;
-fi->t_r.ptr_sfsbq_prod_reg = SFSBQ_PRODUCER_REGISTER_OFFSET + fi->g.tachyon_base;
-fi->t_r.ptr_sfsbq_cons_reg = SFSBQ_CONSUMER_REGISTER_OFFSET + fi->g.tachyon_base;
-fi->t_r.ptr_sfsbuff_len_reg = SFS_LENGTH_REGISTER_OFFSET + fi->g.tachyon_base;
-fi->t_r.ptr_sest_base_reg = SEST_BASE_REGISTER_OFFSET + fi->g.tachyon_base;
-fi->t_r.ptr_sest_len_reg = SEST_LENGTH_REGISTER_OFFSET + fi->g.tachyon_base;
-fi->t_r.ptr_scsibuff_len_reg = SCSI_LENGTH_REGISTER_OFFSET + fi->g.tachyon_base;
-fi->t_r.ptr_tach_config_reg = TACHYON_CONFIG_REGISTER_OFFSET + fi->g.tachyon_base;
-fi->t_r.ptr_tach_control_reg = TACHYON_CONTROL_REGISTER_OFFSET + fi->g.tachyon_base;
-fi->t_r.ptr_tach_status_reg = TACHYON_STATUS_REGISTER_OFFSET + fi->g.tachyon_base;
-fi->t_r.ptr_tach_flush_oxid_reg = TACHYON_FLUSH_SEST_REGISTER_OFFSET + fi->g.tachyon_base;
-fi->t_r.ptr_fm_config_reg = FMGR_CONFIG_REGISTER_OFFSET + fi->g.tachyon_base;
-fi->t_r.ptr_fm_control_reg = FMGR_CONTROL_REGISTER_OFFSET + fi->g.tachyon_base;
-fi->t_r.ptr_fm_status_reg = FMGR_STATUS_REGISTER_OFFSET + fi->g.tachyon_base;
-fi->t_r.ptr_fm_tov_reg = FMGR_TIMER_REGISTER_OFFSET + fi->g.tachyon_base;
-fi->t_r.ptr_fm_wwn_hi_reg = FMGR_WWN_HI_REGISTER_OFFSET + fi->g.tachyon_base;
-fi->t_r.ptr_fm_wwn_low_reg = FMGR_WWN_LO_REGISTER_OFFSET + fi->g.tachyon_base;
-fi->t_r.ptr_fm_rx_al_pa_reg = FMGR_RCVD_ALPA_REGISTER_OFFSET + fi->g.tachyon_base;
-
-LEAVE("initialize_register_pointers");
-return 1;
-}
-
-
-
-/*
- * Local variables:
- * compile-command: "gcc -DKERNEL -Wall -O6 -fomit-frame-pointer -I/usr/src/linux/net/tcp -c iph5526.c"
- * version-control: t
- * kept-new-versions: 5
- * End:
- */
diff --git a/drivers/net/fc/iph5526_ip.h b/drivers/net/fc/iph5526_ip.h
deleted file mode 100644
index 9fae3b002fec9..0000000000000
--- a/drivers/net/fc/iph5526_ip.h
+++ /dev/null
@@ -1,24 +0,0 @@
-#ifndef IPH5526_IP_H
-#define IPH5526_IP_H
-
-#define LLC_SNAP_LEN 0x8
-
-/* Offsets into the ARP frame */
-#define ARP_OPCODE_0 (0x6 + LLC_SNAP_LEN)
-#define ARP_OPCODE_1 (0x7 + LLC_SNAP_LEN)
-
-int iph5526_probe(struct net_device *dev);
-static int fcdev_init(struct net_device *dev);
-static int iph5526_open(struct net_device *dev);
-static int iph5526_close(struct net_device *dev);
-static int iph5526_send_packet(struct sk_buff *skb, struct net_device *dev);
-static struct net_device_stats * iph5526_get_stats(struct net_device *dev);
-static int iph5526_change_mtu(struct net_device *dev, int mtu);
-
-
-static void rx_net_packet(struct fc_info *fi, u_char *buff_addr, int payload_size);
-static void rx_net_mfs_packet(struct fc_info *fi, struct sk_buff *skb);
-static int tx_ip_packet(struct sk_buff *skb, unsigned long len, struct fc_info *fi);
-static int tx_arp_packet(char *data, unsigned long len, struct fc_info *fi);
-#endif
-
diff --git a/drivers/net/fc/iph5526_novram.c b/drivers/net/fc/iph5526_novram.c
deleted file mode 100644
index d73587be03257..0000000000000
--- a/drivers/net/fc/iph5526_novram.c
+++ /dev/null
@@ -1,278 +0,0 @@
-/**********************************************************************
- * Reading the NVRAM on the Interphase 5526 PCI Fibre Channel Card.
- * All contents in this file : courtesy Interphase Corporation.
- * Special thanks to Kevin Quick, kquick@iphase.com.
- **********************************************************************/
-
-#define FF_MAGIC 0x4646
-#define DB_MAGIC 0x4442
-#define DL_MAGIC 0x444d
-
-
-#define CMD_LEN 9
-
-/***********
- *
- * Switches and defines for header files.
- *
- * The following defines are used to turn on and off
- * various options in the header files. Primarily useful
- * for debugging.
- *
- ***********/
-
-static const unsigned short novram_default[4] = {
- FF_MAGIC,
- DB_MAGIC,
- DL_MAGIC,
- 0 };
-
-
-/*
- * a list of the commands that can be sent to the NOVRAM
- */
-
-#define NR_EXTEND 0x100
-#define NR_WRITE 0x140
-#define NR_READ 0x180
-#define NR_ERASE 0x1c0
-
-#define EWDS 0x00
-#define WRAL 0x10
-#define ERAL 0x20
-#define EWEN 0x30
-
-/*
- * Defines for the pins on the NOVRAM
- */
-
-#define BIT(x) (1 << (x))
-
-#define NVDI_B 31
-#define NVDI BIT(NVDI_B)
-#define NVDO BIT(9)
-#define NVCE BIT(30)
-#define NVSK BIT(29)
-#define NV_MANUAL BIT(28)
-
-/***********
- *
- * Include files.
- *
- ***********/
-
-#define KeStallExecutionProcessor(x) {volatile int d, p;\
- for (d=0; d<x; d++) for (p=0; p<10; p++);\
- }
-
-
-/***********************
- *
- * This define ands the value and the current config register and puts
- * the result in the config register
- *
- ***********************/
-
-#define CFG_AND(val) { volatile int t; \
- t = readl(fi->n_r.ptr_novram_hw_control_reg); \
- t &= (val); \
- writel(t, fi->n_r.ptr_novram_hw_control_reg); \
- }
-
-/***********************
- *
- * This define ors the value and the current config register and puts
- * the result in the config register
- *
- ***********************/
-
-#define CFG_OR(val) { volatile int t; \
- t = readl(fi->n_r.ptr_novram_hw_control_reg); \
- t |= (val); \
- writel(t, fi->n_r.ptr_novram_hw_control_reg); \
- }
-
-/***********************
- *
- * Send a command to the NOVRAM, the command is in cmd.
- *
- * clear CE and SK. Then assert CE.
- * Clock each of the command bits out in the correct order with SK
- * exit with CE still asserted
- *
- ***********************/
-
-#define NVRAM_CMD(cmd) { int i; \
- int c = cmd; \
- CFG_AND(~(NVCE|NVSK)); \
- CFG_OR(NVCE); \
- for (i=0; i<CMD_LEN; i++) { \
- NVRAM_CLKOUT((c & (1 << (CMD_LEN - 1))) ? 1 : 0);\
- c <<= 1; } }
-
-/***********************
- *
- * clear the CE, this must be used after each command is complete
- *
- ***********************/
-
-#define NVRAM_CLR_CE CFG_AND(~NVCE)
-
-/***********************
- *
- * clock the data bit in bitval out to the NOVRAM. The bitval must be
- * a 1 or 0, or the clockout operation is undefined
- *
- ***********************/
-
-#define NVRAM_CLKOUT(bitval) {\
- CFG_AND(~NVDI); \
- CFG_OR((bitval) << NVDI_B); \
- KeStallExecutionProcessor(5);\
- CFG_OR(NVSK); \
- KeStallExecutionProcessor(5);\
- CFG_AND( ~NVSK); \
- }
-
-/***********************
- *
- * clock the data bit in and return a 1 or 0, depending on the value
- * that was received from the NOVRAM
- *
- ***********************/
-
-#define NVRAM_CLKIN(val) {\
- CFG_OR(NVSK); \
- KeStallExecutionProcessor(5);\
- CFG_AND(~NVSK); \
- KeStallExecutionProcessor(5);\
- val = (readl(fi->n_r.ptr_novram_hw_status_reg) & NVDO) ? 1 : 0; \
- }
-
-/***********
- *
- * Function Prototypes
- *
- ***********/
-
-static int iph5526_nr_get(struct fc_info *fi, int addr);
-static void iph5526_nr_do_init(struct fc_info *fi);
-static void iph5526_nr_checksum(struct fc_info *fi);
-
-
-/*******************************************************************
- *
- * Local routine: iph5526_nr_do_init
- * Purpose: initialize novram server
- * Description:
- *
- * iph5526_nr_do_init reads the novram into the temporary holding place.
- * A checksum is done on the area and the Magic Cookies are checked.
- * If any of them are bad, the NOVRAM is initialized with the
- * default values and a warning message is displayed.
- *
- *******************************************************************/
-
-static void iph5526_nr_do_init(struct fc_info *fi)
-{
- int i;
- unsigned short chksum = 0;
- int bad = 0;
-
- for (i=0; i<IPH5526_NOVRAM_SIZE; i++) {
- fi->n_r.data[i] = iph5526_nr_get(fi, i);
- chksum += fi->n_r.data[i];
- }
-
- if (chksum)
- bad = 1;
-
- if (fi->n_r.data[IPH5526_NOVRAM_SIZE - 4] != FF_MAGIC)
- bad = 1;
- if (fi->n_r.data[IPH5526_NOVRAM_SIZE - 3] != DB_MAGIC)
- bad = 1;
- if (fi->n_r.data[IPH5526_NOVRAM_SIZE - 2] != DL_MAGIC)
- bad = 1;
-
- if (bad) {
- for (i=0; i<IPH5526_NOVRAM_SIZE; i++) {
- if (i < (IPH5526_NOVRAM_SIZE - 4)) {
- fi->n_r.data[i] = 0xffff;
- } else {
- fi->n_r.data[i] = novram_default[i - (IPH5526_NOVRAM_SIZE - 4)];
- }
- }
- iph5526_nr_checksum(fi);
- }
-}
-
-
-/*******************************************************************
- *
- * Local routine: iph5526_nr_get
- * Purpose: read a single word of NOVRAM
- * Description:
- *
- * read the 16 bits that make up a word addr of the novram.
- * The 16 bits of data that are read are returned as the return value
- *
- *******************************************************************/
-
-static int iph5526_nr_get(struct fc_info *fi, int addr)
-{
- int i;
- int t;
- int val = 0;
-
- CFG_OR(NV_MANUAL);
-
- /*
- * read the first bit that was clocked with the falling edge of the
- * the last command data clock
- */
-
- NVRAM_CMD(NR_READ + addr);
-
- /*
- * Now read the rest of the bits, the next bit read is D1, then D2,
- * and so on
- */
-
- val = 0;
- for (i=0; i<16; i++) {
- NVRAM_CLKIN(t);
- val <<= 1;
- val |= t;
- }
- NVRAM_CLR_CE;
-
- CFG_OR(NVDI);
- CFG_AND(~NV_MANUAL);
-
- return(val);
-}
-
-
-
-
-/*******************************************************************
- *
- * Local routine: iph5526_nr_checksum
- * Purpose: calculate novram checksum on fi->n_r.data
- * Description:
- *
- * calculate a checksum for the novram on the image that is
- * currently in fi->n_r.data
- *
- *******************************************************************/
-
-static void iph5526_nr_checksum(struct fc_info *fi)
-{
- int i;
- unsigned short chksum = 0;
-
- for (i=0; i<(IPH5526_NOVRAM_SIZE - 1); i++)
- chksum += fi->n_r.data[i];
-
- fi->n_r.data[i] = -chksum;
-}
diff --git a/drivers/net/fc/iph5526_scsi.h b/drivers/net/fc/iph5526_scsi.h
deleted file mode 100644
index 1cd4eb1b42d60..0000000000000
--- a/drivers/net/fc/iph5526_scsi.h
+++ /dev/null
@@ -1,31 +0,0 @@
-#ifndef IPH5526_SCSI_H
-#define IPH5526_SCSI_H
-
-#define IPH5526_CAN_QUEUE 32
-#define IPH5526_SCSI_FC { \
- .name = "Interphase 5526 Fibre Channel SCSI Adapter", \
- .detect = iph5526_detect, \
- .release = iph5526_release, \
- .info = iph5526_info, \
- .queuecommand = iph5526_queuecommand, \
- .bios_param = iph5526_biosparam, \
- .can_queue = IPH5526_CAN_QUEUE, \
- .this_id = -1, \
- .sg_tablesize = 255, \
- .cmd_per_lun = 8, \
- .use_clustering = DISABLE_CLUSTERING, \
- .eh_abort_handler = iph5526_abort, \
- .eh_device_reset_handler = NULL, \
- .eh_bus_reset_handler = NULL, \
- .eh_host_reset_handler = NULL, \
-}
-
-int iph5526_detect(Scsi_Host_Template *tmpt);
-int iph5526_queuecommand(Scsi_Cmnd *Cmnd, void (*done) (Scsi_Cmnd *));
-int iph5526_release(struct Scsi_Host *host);
-int iph5526_abort(Scsi_Cmnd *Cmnd);
-const char *iph5526_info(struct Scsi_Host *host);
-int iph5526_biosparam(struct Scsi_Disk * disk, struct block_device *n, int ip[]);
-
-#endif
-
diff --git a/drivers/net/fc/tach.h b/drivers/net/fc/tach.h
deleted file mode 100644
index 3e90ec06786ed..0000000000000
--- a/drivers/net/fc/tach.h
+++ /dev/null
@@ -1,475 +0,0 @@
-/**********************************************************************
- * Defines for the Tachyon Fibre Channel Controller and the Interphase
- * (i)chip TPI.
- *********************************************************************/
-
-#ifndef _TACH_H
-#define _TACH_H
-
-#define MY_PAGE_SIZE 4096
-#define REPLICATE 0xFF
-#define MAX_NODES 127
-#define BROADCAST 0xFFFFFF
-#define BROADCAST_ADDR 0xFFFFFFFFFFFF
-#define LOGIN_COMPLETED 2
-#define LOGIN_ATTEMPTED 1
-#define LOGIN_NOT_ATTEMPTED 0
-#define TRUE 1
-#define FALSE 0
-
-#define TACHYON_LIMIT 0x01EF
-#define TACHYON_OFFSET 0x200
-
-/* Offsets to the (i) chip */
-#define ICHIP_HW_CONTROL_REG_OFF (0x080 - TACHYON_OFFSET)
-#define ICHIP_HW_STATUS_REG_OFF (0x084 - TACHYON_OFFSET)
-#define ICHIP_HW_ADDR_MASK_REG_OFF (0x090 - TACHYON_OFFSET)
-
-/* (i)chip Hardware Control Register defines */
-#define ICHIP_HCR_RESET 0x01
-#define ICHIP_HCR_DERESET 0x0
-#define ICHIP_HCR_ENABLE_INTA 0x0000003E
-#define ICHIP_HCR_ENABLE_INTB 0x003E0000
-#define ICHIP_HCR_IWDATA_FIFO 0x800000
-
-/* (i)chip Hardware Status Register defines */
-#define ICHIP_HSR_INT_LATCH 0x02
-
-/* (i)chip Hardware Address Mask Register defines */
-#define ICHIP_HAMR_BYTE_SWAP_ADDR_TR 0x08
-#define ICHIP_HAMR_BYTE_SWAP_NO_ADDR_TR 0x04
-
-/* NOVRAM defines */
-#define IPH5526_NOVRAM_SIZE 64
-
-
-/* Offsets for the registers that correspond to the
- * Qs on the Tachyon (As defined in the Tachyon Manual).
- */
-
-/* Outbound Command Queue (OCQ).
- */
-#define OCQ_BASE_REGISTER_OFFSET 0x000
-#define OCQ_LENGTH_REGISTER_OFFSET 0x004
-#define OCQ_PRODUCER_REGISTER_OFFSET 0x008
-#define OCQ_CONSUMER_REGISTER_OFFSET 0x00C
-
-/* Inbound Message Queue (IMQ).
- */
-#define IMQ_BASE_REGISTER_OFFSET 0x080
-#define IMQ_LENGTH_REGISTER_OFFSET 0x084
-#define IMQ_CONSUMER_REGISTER_OFFSET 0x088
-#define IMQ_PRODUCER_REGISTER_OFFSET 0x08C
-
-/* Multiframe Sequence Buffer Queue (MFSBQ)
- */
-#define MFSBQ_BASE_REGISTER_OFFSET 0x0C0
-#define MFSBQ_LENGTH_REGISTER_OFFSET 0x0C4
-#define MFSBQ_PRODUCER_REGISTER_OFFSET 0x0C8
-#define MFSBQ_CONSUMER_REGISTER_OFFSET 0x0CC
-#define MFS_LENGTH_REGISTER_OFFSET 0x0D0
-
-/* Single Frame Sequence Buffer Queue (SFSBQ)
- */
-#define SFSBQ_BASE_REGISTER_OFFSET 0x100
-#define SFSBQ_LENGTH_REGISTER_OFFSET 0x104
-#define SFSBQ_PRODUCER_REGISTER_OFFSET 0x108
-#define SFSBQ_CONSUMER_REGISTER_OFFSET 0x10C
-#define SFS_LENGTH_REGISTER_OFFSET 0x110
-
-/* SCSI Exchange State Table (SEST)
- */
-#define SEST_BASE_REGISTER_OFFSET 0x140
-#define SEST_LENGTH_REGISTER_OFFSET 0x144
-#define SCSI_LENGTH_REGISTER_OFFSET 0x148
-
-/* Length of the various Qs
- */
-#define NO_OF_ENTRIES 8
-#define OCQ_LENGTH (MY_PAGE_SIZE/32)
-#define IMQ_LENGTH (MY_PAGE_SIZE/32)
-#define MFSBQ_LENGTH 8
-#define SFSBQ_LENGTH 8
-#define SEST_LENGTH MY_PAGE_SIZE
-
-/* Size of the various buffers.
- */
-#define TACH_FRAME_SIZE 2048
-#define MFS_BUFFER_SIZE TACH_FRAME_SIZE
-#define SFS_BUFFER_SIZE (TACH_FRAME_SIZE + TACHYON_HEADER_LEN)
-#define SEST_BUFFER_SIZE 512
-#define TACH_HEADER_SIZE 64
-#define NO_OF_TACH_HEADERS ((MY_PAGE_SIZE)/TACH_HEADER_SIZE)
-
-#define NO_OF_FCP_CMNDS (MY_PAGE_SIZE/32)
-#define SDB_SIZE 2048
-#define NO_OF_SDB_ENTRIES ((32*MY_PAGE_SIZE)/SDB_SIZE)
-
-
-/* Offsets to the other Tachyon registers.
- * (As defined in the Tachyon manual)
- */
-#define TACHYON_CONFIG_REGISTER_OFFSET 0x184
-#define TACHYON_CONTROL_REGISTER_OFFSET 0x188
-#define TACHYON_STATUS_REGISTER_OFFSET 0x18C
-#define TACHYON_FLUSH_SEST_REGISTER_OFFSET 0x190
-
-/* Defines for the Tachyon Configuration register.
- */
-#define SCSI_ENABLE 0x40000000
-#define WRITE_STREAM_SIZE 0x800 /* size = 16 */
-#define READ_STREAM_SIZE 0x300 /* size = 64 */
-#define PARITY_EVEN 0x2
-#define OOO_REASSEMBLY_DISABLE 0x40
-
-/* Defines for the Tachyon Control register.
- */
-#define SOFTWARE_RESET 0x80000000
-#define OCQ_RESET 0x4
-#define ERROR_RELEASE 0x2
-
-/* Defines for the Tachyon Status register.
- */
-#define RECEIVE_FIFO_EMPTY 0x10
-#define OSM_FROZEN 0x1
-#define OCQ_RESET_STATUS 0x20
-#define SCSI_FREEZE_STATUS 0x40
-
-
-/* Offsets to the Frame Manager registers.
- */
-#define FMGR_CONFIG_REGISTER_OFFSET 0x1C0
-#define FMGR_CONTROL_REGISTER_OFFSET 0x1C4
-#define FMGR_STATUS_REGISTER_OFFSET 0x1C8
-#define FMGR_TIMER_REGISTER_OFFSET 0x1CC
-#define FMGR_WWN_HI_REGISTER_OFFSET 0x1E0
-#define FMGR_WWN_LO_REGISTER_OFFSET 0x1E4
-#define FMGR_RCVD_ALPA_REGISTER_OFFSET 0x1E8
-
-/* Defines for the Frame Manager Configuration register.
- */
-#define BB_CREDIT 0x10000
-#define NPORT 0x8000
-#define LOOP_INIT_FABRIC_ADDRESS 0x400
-#define LOOP_INIT_PREVIOUS_ADDRESS 0x200
-#define LOOP_INIT_SOFT_ADDRESS 0x80
-
-/* Defines for the Frame Manager Control register.
- */
-#define HOST_CONTROL 0x02
-#define EXIT_HOST_CONTROL 0x03
-#define OFFLINE 0x05
-#define INITIALIZE 0x06
-#define CLEAR_LF 0x07
-
-/* Defines for the Frame Manager Status register.
- */
-#define LOOP_UP 0x80000000
-#define TRANSMIT_PARITY_ERROR 0x40000000
-#define NON_PARTICIPATING 0x20000000
-#define OUT_OF_SYNC 0x02000000
-#define LOSS_OF_SIGNAL 0x01000000
-#define NOS_OLS_RECEIVED 0x00080000
-#define LOOP_STATE_TIMEOUT 0x00040000
-#define LIPF_RECEIVED 0x00020000
-#define BAD_ALPA 0x00010000
-#define LINK_FAILURE 0x00001000
-#define ELASTIC_STORE_ERROR 0x00000400
-#define LINK_UP 0x00000200
-#define LINK_DOWN 0x00000100
-#define ARBITRATING 0x00000010
-#define ARB_WON 0x00000020
-#define OPEN 0x00000030
-#define OPENED 0x00000040
-#define TX_CLS 0x00000050
-#define RX_CLS 0x00000060
-#define TRANSFER 0x00000070
-#define INITIALIZING 0x00000080
-#define LOOP_FAIL 0x000000D0
-#define OLD_PORT 0x000000F0
-#define PORT_STATE_ACTIVE 0x0000000F
-#define PORT_STATE_OFFLINE 0x00000000
-#define PORT_STATE_LF1 0x00000009
-#define PORT_STATE_LF2 0x0000000A
-
-/* Completion Message Types
- * (defined in P.177 of the Tachyon manual)
- */
-#define OUTBOUND_COMPLETION 0x000
-#define OUTBOUND_COMPLETION_I 0x100
-#define OUT_HI_PRI_COMPLETION 0x001
-#define OUT_HI_PRI_COMPLETION_I 0x101
-#define INBOUND_MFS_COMPLETION 0x102
-#define INBOUND_OOO_COMPLETION 0x003
-#define INBOUND_SFS_COMPLETION 0x104
-#define INBOUND_C1_TIMEOUT 0x105
-#define INBOUND_UNKNOWN_FRAME_I 0x106
-#define INBOUND_BUSIED_FRAME 0x006
-#define SFS_BUF_WARN 0x107
-#define MFS_BUF_WARN 0x108
-#define IMQ_BUF_WARN 0x109
-#define FRAME_MGR_INTERRUPT 0x10A
-#define READ_STATUS 0x10B
-#define INBOUND_SCSI_DATA_COMPLETION 0x10C
-#define INBOUND_SCSI_COMMAND 0x10D
-#define BAD_SCSI_FRAME 0x10E
-#define INB_SCSI_STATUS_COMPLETION 0x10F
-
-/* One of the things that we care about when we receive an
- * Outbound Completion Message (OCM).
- */
-#define OCM_TIMEOUT_OR_BAD_ALPA 0x0800
-
-/* Defines for the Tachyon Header structure.
- */
-#define SOFI3 0x70
-#define SOFN3 0xB0
-#define EOFN 0x5
-
-/* R_CTL */
-#define FC4_DEVICE_DATA 0
-#define EXTENDED_LINK_DATA 0x20000000
-#define FC4_LINK_DATA 0x30000000
-#define BASIC_LINK_DATA 0x80000000
-#define LINK_CONTROL 0xC0000000
-#define SOLICITED_DATA 0x1000000
-#define UNSOLICITED_CONTROL 0x2000000
-#define SOLICITED_CONTROL 0x3000000
-#define UNSOLICITED_DATA 0x4000000
-#define DATA_DESCRIPTOR 0x5000000
-#define UNSOLICITED_COMMAND 0x6000000
-
-#define RCTL_ELS_UCTL 0x22000000
-#define RCTL_ELS_SCTL 0x23000000
-#define RCTL_BASIC_ABTS 0x81000000
-#define RCTL_BASIC_ACC 0x84000000
-#define RCTL_BASIC_RJT 0x85000000
-
-/* TYPE */
-#define TYPE_BLS 0x00000000
-#define TYPE_ELS 0x01000000
-#define TYPE_FC_SERVICES 0x20000000
-#define TYPE_LLC_SNAP 0x05000000
-#define TYPE_FCP 0x08000000
-
-/* F_CTL */
-#define EXCHANGE_RESPONDER 0x800000
-#define SEQUENCE_RESPONDER 0x400000
-#define FIRST_SEQUENCE 0x200000
-#define LAST_SEQUENCE 0x100000
-#define SEQUENCE_INITIATIVE 0x10000
-#define RELATIVE_OFF_PRESENT 0x8
-#define END_SEQUENCE 0x80000
-
-#define TACHYON_HEADER_LEN 32
-#define NW_HEADER_LEN 16
-/* Defines for the Outbound Descriptor Block (ODB).
- */
-#define ODB_CLASS_3 0xC000
-#define ODB_NO_COMP 0x400
-#define ODB_NO_INT 0x200
-#define ODB_EE_CREDIT 0xF
-
-/* Defines for the Extended Descriptor Block (EDB).
- */
-#define EDB_LEN ((32*MY_PAGE_SIZE)/8)
-#define EDB_END 0x8000
-#define EDB_FREE 0
-#define EDB_BUSY 1
-
-/* Command Codes */
-#define ELS_LS_RJT 0x01000000
-#define ELS_ACC 0x02000000
-#define ELS_PLOGI 0x03000000
-#define ELS_FLOGI 0x04000000
-#define ELS_LOGO 0x05000000
-#define ELS_TPRLO 0x24000000
-#define ELS_ADISC 0x52000000
-#define ELS_PDISC 0x50000000
-#define ELS_PRLI 0x20000000
-#define ELS_PRLO 0x21000000
-#define ELS_SCR 0x62000000
-#define ELS_RSCN 0x61000000
-#define ELS_FARP_REQ 0x54000000
-#define ELS_ABTX 0x06000000
-#define ELS_ADVC 0x0D000000
-#define ELS_ECHO 0x10000000
-#define ELS_ESTC 0x0C000000
-#define ELS_ESTS 0x0B000000
-#define ELS_RCS 0x07000000
-#define ELS_RES 0x08000000
-#define ELS_RLS 0x0F000000
-#define ELS_RRQ 0x12000000
-#define ELS_RSS 0x09000000
-#define ELS_RTV 0x0E000000
-#define ELS_RSI 0x0A000000
-#define ELS_TEST 0x11000000
-#define ELS_RNC 0x53000000
-#define ELS_RVCS 0x41000000
-#define ELS_TPLS 0x23000000
-#define ELS_GAID 0x30000000
-#define ELS_FACT 0x31000000
-#define ELS_FAN 0x60000000
-#define ELS_FDACT 0x32000000
-#define ELS_NACT 0x33000000
-#define ELS_NDACT 0x34000000
-#define ELS_QoSR 0x40000000
-#define ELS_FDISC 0x51000000
-
-#define ELS_NS_PLOGI 0x03FFFFFC
-
-/* LS_RJT reason codes.
- */
-#define INV_LS_CMND_CODE 0x0001
-#define LOGICAL_ERR 0x0003
-#define LOGICAL_BUSY 0x0005
-#define PROTOCOL_ERR 0x0007
-#define UNABLE_TO_PERFORM 0x0009
-#define CMND_NOT_SUPP 0x000B
-
-/* LS_RJT explanation codes.
- */
-#define NO_EXPLN 0x0000
-#define RECV_FIELD_SIZE 0x0700
-#define CONC_SEQ 0x0900
-#define REQ_NOT_SUPPORTED 0x2C00
-#define INV_PAYLOAD_LEN 0x2D00
-
-/* Payload Length defines.
- */
-#define PLOGI_LEN 116
-
-#define CONCURRENT_SEQUENCES 0x01
-#define RO_INFO_CATEGORY 0xFE
-#define E_D_TOV 0x07D0 /* 2 Secs */
-#define AL_TIME 0x0010 /* ~15 msec */
-#define TOV_VALUES (AL_TIME << 16) | E_D_TOV
-#define RT_TOV 0x64 /* 100 msec */
-#define PTP_TOV_VALUES (RT_TOV << 16) | E_D_TOV
-#define SERVICE_VALID 0x8000
-#define SEQUENCE_DELIVERY 0x0800
-#define CLASS3_CONCURRENT_SEQUENCE 0x01
-#define CLASS3_OPEN_SEQUENCE 0x01
-
-/* These are retrieved from the NOVRAM.
- */
-#define WORLD_WIDE_NAME_LOW fi->g.my_port_name_low
-#define WORLD_WIDE_NAME_HIGH fi->g.my_port_name_high
-#define N_PORT_NAME_HIGH fi->g.my_port_name_high
-#define N_PORT_NAME_LOW fi->g.my_port_name_low
-#define NODE_NAME_HIGH fi->g.my_node_name_high
-#define NODE_NAME_LOW fi->g.my_node_name_low
-
-#define PORT_NAME_LEN 8
-#define NODE_NAME_LEN 8
-
-
-#define PH_VERSION 0x0909
-
-#define LOOP_BB_CREDIT 0x00
-#define PT2PT_BB_CREDIT 0x01
-#define FLOGI_C_F 0x0800 /* Alternate BB_Credit Mgmnt */
-#define PLOGI_C_F 0x8800 /* Continuously Increasing + Alternate BB_Credit Management */
-
-/* Fabric defines */
-#define DIRECTORY_SERVER 0xFFFFFC
-#define FABRIC_CONTROLLER 0xFFFFFD
-#define F_PORT 0xFFFFFE
-
-#define FLOGI_DID 0xFFFE
-#define NS_PLOGI_DID 0xFFFC
-
-/* Fibre Channel Services defines */
-#define FCS_RFC_4 0x02170000
-#define FCS_GP_ID4 0x01A10000
-#define FCS_ACC 0x8002
-#define FCS_REJECT 0x8001
-
-/* CT Header defines */
-#define FC_CT_REV 0x01000000
-#define DIRECTORY_SERVER_APP 0xFC
-#define NAME_SERVICE 0x02
-
-/* Port Type defines */
-#define PORT_TYPE_IP 0x05000000
-#define PORT_TYPE_NX_PORTS 0x7F000000
-
-/* SCR defines */
-#define FABRIC_DETECTED_REG 0x00000001
-#define N_PORT_DETECTED_REG 0x00000002
-#define FULL_REGISTRATION 0x00000003
-#define CLEAR_REGISTRATION 0x000000FF
-
-/* Command structure has only one byte to address targets
- */
-#define MAX_SCSI_TARGETS 0xFF
-
-#define FC_SCSI_READ 0x80
-#define FC_SCSI_WRITE 0x81
-#define FC_ELS 0x01
-#define FC_BLS 0x00
-#define FC_IP 0x05
-#define FC_BROADCAST 0xFF
-
-/* SEST defines.
- */
-#define SEST_V 0x80000000 /* V = 1 */
-#define INB_SEST_VED 0xA0000000 /* V = 1, D = 1 */
-#define SEST_INV 0x7FFFFFFF
-#define OUTB_SEST_VED 0x80000000 /* V = 1 */
-#define INV_SEQ_LEN 0xFFFFFFFF
-#define OUTB_SEST_LINK 0xFFFF
-
-/* PRLI defines.
- */
-#define PAGE_LEN 0x100000 /* 3rd byte - 0x10 */
-#define PRLI_LEN 0x0014 /* 20 bytes */
-#define FCP_TYPE_CODE 0x0800 /* FCP-SCSI */
-#define IMAGE_PAIR 0x2000 /* establish image pair */
-#define INITIATOR_FUNC 0x00000020
-#define TARGET_FUNC 0x00000010
-#define READ_XFER_RDY_DISABLED 0x00000002
-
-#define NODE_PROCESS_LOGGED_IN 0x3
-#define NODE_NOT_PRESENT 0x2
-#define NODE_LOGGED_IN 0x1
-#define NODE_LOGGED_OUT 0x0
-
-/* Defines to determine what should be returned when a SCSI frame
- * times out.
- */
-#define FC_SCSI_BAD_TARGET 0xFFFE0000
-
-/* RSCN Address formats */
-#define PORT_ADDRESS_FORMAT 0x00
-#define AREA_ADDRESS_FORMAT 0x01
-#define DOMAIN_ADDRESS_FORMAT 0x02
-
-/* Defines used to determine whether a frame transmission should
- * be indicated by an interrupt or not.
- */
-#define NO_COMP_AND_INT 0
-#define INT_AND_COMP_REQ 1
-#define NO_INT_COMP_REQ 2
-
-/* Other junk...
- */
-#define SDB_FREE 0
-#define SDB_BUSY 1
-#define MAX_PENDING_FRAMES 15
-#define RX_ID_FIRST_SEQUENCE 0xFFFF
-#define OX_ID_FIRST_SEQUENCE 0xFFFF
-#define NOT_SCSI_XID 0x8000
-#define MAX_SCSI_XID 0x0FFF /* X_IDs are from 0-4095 */
-#define SCSI_READ_BIT 0x4000
-#define MAX_SCSI_OXID 0x4FFF
-#define OXID_AVAILABLE 0
-#define OXID_INUSE 1
-#define MAX_SEQ_ID 0xFF
-
-#define INITIATOR 2
-#define TARGET 1
-#define DELETE_ENTRY 1
-#define ADD_ENTRY 2
-
-#endif /* _TACH_H */
diff --git a/drivers/net/fc/tach_structs.h b/drivers/net/fc/tach_structs.h
deleted file mode 100644
index f59a3d0e84d73..0000000000000
--- a/drivers/net/fc/tach_structs.h
+++ /dev/null
@@ -1,428 +0,0 @@
-/**********************************************************************
- * iph5526.c: Structures for the Interphase 5526 PCI Fibre Channel
- * IP/SCSI driver.
- * Copyright (C) 1999 Vineet M Abraham <vmabraham@hotmail.com>
- **********************************************************************/
-
-#ifndef _TACH_STRUCT_H
-#define _TACH_STRUCT_H
-
-typedef struct {
- u_short cmnd_code;
- u_short payload_length;
- u_short type_code;
- u_short est_image_pair;
- u_int originator_pa;
- u_int responder_pa;
- u_int service_params;
-} PRLI;
-
-typedef struct {
- u_int flags_and_byte_offset;
- u_int byte_count;
- u_short no_of_recvd_frames;
- u_short no_of_expected_frames;
- u_int last_fctl;
- u_int sdb_address;
- u_int scratch_pad;
- u_int expected_ro;
- u_short buffer_index;
- u_short buffer_offset;
- } INB_SEST_ENTRY;
-
-typedef struct {
- u_int flags_and_did;
- u_short max_frame_len;
- u_short cntl;
- u_int total_seq_length;
- u_short link;
- u_short rx_id;
- u_int transaction_id;
- u_int header_address;
- u_char seq_id;
- u_char reserved;
- u_short header_length;
- u_int edb_address;
- } OUTB_SEST_ENTRY;
-
-typedef struct {
- u_short d_naa;
- u_short dest_high;
- u_int dest_low;
- u_short s_naa;
- u_short source_high;
- u_int source_low;
- } NW_HEADER;
-
-typedef struct {
- u_int resv;
- u_char sof_and_eof;
- u_char dest_alpa;
- u_short lcr_and_time_stamp;
- u_int r_ctl_and_d_id;
- u_int vc_id_and_s_id;
- u_int type_and_f_cntl;
- u_char seq_id;
- u_char df_cntl;
- u_short seq_cnt;
- u_short ox_id;
- u_short rx_id;
- u_int ro;
- NW_HEADER nw_header;
- } TACHYON_HEADER;
-
-typedef struct {
- u_short service_options;
- u_short initiator_ctl;
- u_short recipient_ctl;
- u_short recv_data_field_size;
- u_short concurrent_sequences;
- u_short n_port_end_to_end_credit;
- u_short open_seq_per_exchange;
- u_short resv;
- }CLASS_OF_SERVICE;
-
-typedef struct {
- u_int logo_cmnd;
- u_char reserved;
- u_char n_port_id_2;
- u_char n_port_id_1;
- u_char n_port_id_0;
- u_int port_name_up;
- u_int port_name_low;
- } LOGO;
-
-typedef struct {
- u_int ls_cmnd_code;
- u_int hard_address;
- u_int port_name_high;
- u_int port_name_low;
- u_int node_name_high;
- u_int node_name_low;
- u_int n_port_id;
- } ADISC;
-
-typedef struct {
- u_int cmnd_code;
- u_int reason_code;
- } LS_RJT;
-
-typedef struct {
- u_int cmnd_code;
- } ACC;
-
-typedef struct {
- u_int seq_d_id;
- u_int tot_len;
- u_short cntl;
- u_short rx_id;
- u_short cs_enable;
- u_short cs_seed;
- u_int trans_id;
- u_int hdr_addr;
- u_short frame_len;
- u_short hdr_len;
- u_int edb_addr;
- }ODB;
-
-typedef struct {
- u_int cmnd_code;
- u_int reg_function; /* in the last byte */
- } SCR;
-
-typedef struct {
- u_int rev_in_id;
- u_char fs_type;
- u_char fs_subtype;
- u_char options;
- u_char resv1;
- u_short cmnd_resp_code;
- u_short max_res_size;
- u_char resv2;
- u_char reason_code;
- u_char expln_code;
- u_char vendor_unique;
- } CT_HDR;
-
-typedef struct {
- CT_HDR ct_hdr;
- u_int s_id;
- u_char bit_map[32]; /* 32 byte bit map */
- } RFC_4;
-
-typedef struct {
- u_int ls_cmnd_code;
- u_short fc_ph_version;
- u_short buff_to_buff_credit;
- u_short common_features;
- u_short recv_data_field_size;
- u_short n_port_total_conc_seq;
- u_short rel_off_by_info_cat;
- u_int ED_TOV;
- u_int n_port_name_high;
- u_int n_port_name_low;
- u_int node_name_high;
- u_int node_name_low;
- CLASS_OF_SERVICE c_of_s[3];
- u_int resv[4];
- u_int vendor_version_level[4];
- }LOGIN;
-
-typedef struct {
- CT_HDR ct_hdr;
- u_int port_type; /* in the first byte */
- } GP_ID4;
-
-typedef struct {
- u_int buf_addr;
- u_short ehf;
- u_short buf_len;
- }EDB;
-
-/* (i)chip Registers */
-struct i_chip_regs {
- u_int ptr_ichip_hw_control_reg;
- u_int ptr_ichip_hw_status_reg;
- u_int ptr_ichip_hw_addr_mask_reg;
-};
-
-struct iph5526_novram {
- u_int ptr_novram_hw_control_reg;
- u_int ptr_novram_hw_status_reg;
- u_short data[IPH5526_NOVRAM_SIZE];
-};
-
-/* Tachyon Registers */
-struct tachyon_regs {
- u_int ptr_ocq_base_reg;
- u_int ptr_ocq_len_reg;
- u_int ptr_ocq_prod_indx_reg;
- u_int ptr_ocq_cons_indx_reg;
-
- u_int ptr_imq_base_reg;
- u_int ptr_imq_len_reg;
- u_int ptr_imq_cons_indx_reg;
- u_int ptr_imq_prod_indx_reg;
-
- u_int ptr_mfsbq_base_reg;
- u_int ptr_mfsbq_len_reg;
- u_int ptr_mfsbq_prod_reg;
- u_int ptr_mfsbq_cons_reg;
- u_int ptr_mfsbuff_len_reg;
-
- u_int ptr_sfsbq_base_reg;
- u_int ptr_sfsbq_len_reg;
- u_int ptr_sfsbq_prod_reg;
- u_int ptr_sfsbq_cons_reg;
- u_int ptr_sfsbuff_len_reg;
-
- u_int ptr_sest_base_reg;
- u_int ptr_sest_len_reg;
- u_int ptr_scsibuff_len_reg;
-
- u_int ptr_tach_config_reg;
- u_int ptr_tach_control_reg;
- u_int ptr_tach_status_reg;
- u_int ptr_tach_flush_oxid_reg;
-
- u_int ptr_fm_config_reg;
- u_int ptr_fm_control_reg;
- u_int ptr_fm_status_reg;
- u_int ptr_fm_tov_reg;
- u_int ptr_fm_wwn_hi_reg;
- u_int ptr_fm_wwn_low_reg;
- u_int ptr_fm_rx_al_pa_reg;
-};
-
-struct globals {
- u_long tachyon_base;
- u_int *mem_base;
- u_short ox_id; /* OX_ID used for IP and ELS frames */
- u_short scsi_oxid; /* OX_ID for SEST entry */
- u_char seq_id;
- u_int my_id;
- u_int my_ddaa; /* my domain and area in a fabric */
- volatile u_char loop_up;
- volatile u_char ptp_up; /* we have a point-to-point link */
- volatile u_char link_up;
- volatile u_char n_port_try;
- volatile u_char nport_timer_set;
- volatile u_char lport_timer_set;
- /* Hmmm... We don't want to Initialize while closing */
- u_char dont_init;
- u_int my_node_name_high;
- u_int my_node_name_low;
- u_int my_port_name_high;
- u_int my_port_name_low;
- u_char fabric_present;
- u_char explore_fabric;
- u_char name_server;
- u_int my_mtu;
- u_int *els_buffer[MAX_PENDING_FRAMES]; /* temp space for ELS frames */
- char *arp_buffer; /* temp space for ARP frames */
- u_int mfs_buffer_count; /* keep track of MFS buffers used*/
- u_char scsi_registered;
- /* variables for port discovery */
- volatile u_char port_discovery;
- volatile u_char perform_adisc;
- u_short alpa_list_index;
- u_short type_of_frame; /* Could be IP/SCSI Read/SCSI Write*/
- u_char no_of_targets; /* used to assign target_ids */
- u_long sem; /* to synchronize between IP and SCSI */
- u_char e_i;
-
- /* the frames */
- TACHYON_HEADER tach_header;
- LOGIN login;
- PRLI prli;
- LOGO logo;
- ADISC adisc;
- LS_RJT ls_rjt;
- ODB odb;
- INB_SEST_ENTRY inb_sest_entry;
- OUTB_SEST_ENTRY outb_sest_entry;
- ACC acc;
- SCR scr;
- EDB edb;
- RFC_4 rfc_4;
- GP_ID4 gp_id4;
-};
-
-struct queue_variables {
- /* Indices maintained in host memory.
- */
- u_int *host_ocq_cons_indx, *host_hpcq_cons_indx, *host_imq_prod_indx;
- u_int *ptr_host_ocq_cons_indx, *ptr_host_hpcq_cons_indx, *ptr_host_imq_prod_indx;
-
- /* Variables for Outbound Command Queue (OCQ).
- */
- u_int *ptr_ocq_base;
- u_int ocq_len, ocq_end;
- u_int ocq_prod_indx;
- u_int *ptr_odb[OCQ_LENGTH];
-
- /* Variables for Inbound Message Queue (IMQ).
- */
- u_int *ptr_imq_base;
- u_int imq_len, imq_end;
- u_int imq_cons_indx;
- u_int imq_prod_indx;
- u_int *ptr_imqe[IMQ_LENGTH];
-
- u_int *ptr_mfsbq_base;
- u_int mfsbq_len, mfsbq_end;
- u_int mfsbq_prod_indx;
- u_int mfsbq_cons_indx;
- u_int mfsbuff_len, mfsbuff_end;
-
- u_int *ptr_sfsbq_base;
- u_int sfsbq_len, sfsbq_end;
- u_int sfsbq_prod_indx;
- u_int sfsbq_cons_indx;
- u_int sfsbuff_len, sfsbuff_end;
- u_int *ptr_sfs_buffers[SFSBQ_LENGTH * NO_OF_ENTRIES];
-
- /* Tables for SCSI Transactions */
- u_int *ptr_sest_base;
- u_int *ptr_sest[SEST_LENGTH];
- u_char free_scsi_oxid[SEST_LENGTH];
- u_int *ptr_sdb_base;
- u_int *ptr_sdb_slot[NO_OF_SDB_ENTRIES];
- u_char sdb_slot_status[NO_OF_SDB_ENTRIES];
- u_int sdb_indx;
- u_int *ptr_fcp_cmnd_base;
- u_int *ptr_fcp_cmnd[NO_OF_FCP_CMNDS];
- u_int fcp_cmnd_indx;
-
- /* Table for data to be transmitted.
- */
- u_int *ptr_edb_base;
- u_int *ptr_edb[EDB_LEN];
- u_int edb_buffer_indx;
- volatile u_char free_edb_list[EDB_LEN];
-
- /* Table of Tachyon Headers.
- */
- u_int *ptr_tachyon_header[NO_OF_TACH_HEADERS];
- u_int *ptr_tachyon_header_base;
- u_int tachyon_header_indx;
-};
-
-/* Used to match incoming ACCs to ELS requests sent out */
-struct ox_id_els_map {
- u_short ox_id;
- u_int els;
- struct ox_id_els_map *next;
-};
-
-
-/* Carries info about individual nodes... stores the info got at login
- * time. Also maintains mapping between MAC->FC addresses
- */
-struct fc_node_info {
- /* Itz the WWN (8 bytes), the last 6 bytes is the MAC address */
- u_char hw_addr[PORT_NAME_LEN];
- u_char node_name[NODE_NAME_LEN];
- u_int d_id; /*real FC address, 3 bytes */
- int mtu;
- /* login = 1 if login attempted
- * login = 2 if login completed
- */
- int login;
- u_char scsi; /* = 1 if device is a SCSI Target */
- u_char target_id;
- CLASS_OF_SERVICE c_of_s[3];
- struct fc_node_info *next;
-};
-
-struct fc_info {
- char name[8];
- u_long base_addr;
- int irq;
- struct net_device_stats fc_stats;
- struct fc_node_info *node_info_list;
- int num_nodes;
- struct ox_id_els_map *ox_id_list;
- struct i_chip_regs i_r;
- struct tachyon_regs t_r;
- struct queue_variables q;
- struct globals g;
- struct iph5526_novram n_r;
- u_short clone_id;
- struct timer_list nport_timer;
- struct timer_list lport_timer;
- struct timer_list explore_timer;
- struct timer_list display_cache_timer;
- struct net_device *dev;
- struct Scsi_Host *host;
- spinlock_t fc_lock;
-};
-
-struct iph5526_hostdata {
- struct fc_info *fi;
- fcp_cmd cmnd;
- Scsi_Cmnd *cmnd_handler[SEST_LENGTH];
- u_int tag_ages[MAX_SCSI_TARGETS];
-};
-
-/* List of valid AL_PAs */
-u_char alpa_list[127] = {
- 0x00, 0x01, 0x02, 0x04, 0x08, 0x0F, 0x10, 0x17,
- 0x18, 0x1B, 0x1D, 0x1E, 0x1F, 0x23, 0x25, 0x26,
- 0x27, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x31,
- 0x32, 0x33, 0x34, 0x35, 0x36, 0x39, 0x3A, 0x3C,
- 0x43, 0x45, 0x46, 0x47, 0x49, 0x4A, 0x4B, 0x4C,
- 0x4D, 0x4E, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56,
- 0x59, 0x5A, 0x5C, 0x63, 0x65, 0x66, 0x67, 0x69,
- 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x71, 0x72, 0x73,
- 0x74, 0x75, 0x76, 0x79, 0x7A, 0x7C, 0x80, 0x81,
- 0x82, 0x84, 0x88, 0x8F, 0x90, 0x97, 0x98, 0x9B,
- 0x9D, 0x9E, 0x9F, 0xA3, 0xA5, 0xA6, 0xA7, 0xA9,
- 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xB1, 0xB2, 0xB3,
- 0xB4, 0xB5, 0xB6, 0xB9, 0xBA, 0xBC, 0xC3, 0xC5,
- 0xC6, 0xC7, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE,
- 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD9, 0xDA,
- 0xDC, 0xE0, 0xE1, 0xE2, 0xE4, 0xE8, 0xEF
-};
-
-#endif /* _TACH_STRUCT_H */
diff --git a/drivers/net/fealnx.c b/drivers/net/fealnx.c
index bd4e571ba827d..d05e9dd1e1401 100644
--- a/drivers/net/fealnx.c
+++ b/drivers/net/fealnx.c
@@ -102,21 +102,6 @@ KERN_INFO DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE "\n";
#define USE_IO_OPS
#endif
-#ifdef USE_IO_OPS
-#undef readb
-#undef readw
-#undef readl
-#undef writeb
-#undef writew
-#undef writel
-#define readb inb
-#define readw inw
-#define readl inl
-#define writeb outb
-#define writew outw
-#define writel outl
-#endif
-
/* Kernel compatibility defines, some common to David Hinds' PCMCIA package. */
/* This is only in the support-all-kernels source code. */
@@ -444,6 +429,7 @@ struct netdev_private {
int mii_cnt; /* MII device addresses. */
unsigned char phys[2]; /* MII device addresses. */
struct mii_if_info mii;
+ void __iomem *mem;
};
@@ -468,23 +454,23 @@ static int netdev_close(struct net_device *dev);
static void reset_rx_descriptors(struct net_device *dev);
static void reset_tx_descriptors(struct net_device *dev);
-static void stop_nic_rx(long ioaddr, long crvalue)
+static void stop_nic_rx(void __iomem *ioaddr, long crvalue)
{
int delay = 0x1000;
- writel(crvalue & ~(CR_W_RXEN), ioaddr + TCRRCR);
+ iowrite32(crvalue & ~(CR_W_RXEN), ioaddr + TCRRCR);
while (--delay) {
- if ( (readl(ioaddr + TCRRCR) & CR_R_RXSTOP) == CR_R_RXSTOP)
+ if ( (ioread32(ioaddr + TCRRCR) & CR_R_RXSTOP) == CR_R_RXSTOP)
break;
}
}
-static void stop_nic_rxtx(long ioaddr, long crvalue)
+static void stop_nic_rxtx(void __iomem *ioaddr, long crvalue)
{
int delay = 0x1000;
- writel(crvalue & ~(CR_W_RXEN+CR_W_TXEN), ioaddr + TCRRCR);
+ iowrite32(crvalue & ~(CR_W_RXEN+CR_W_TXEN), ioaddr + TCRRCR);
while (--delay) {
- if ( (readl(ioaddr + TCRRCR) & (CR_R_RXSTOP+CR_R_TXSTOP))
+ if ( (ioread32(ioaddr + TCRRCR) & (CR_R_RXSTOP+CR_R_TXSTOP))
== (CR_R_RXSTOP+CR_R_TXSTOP) )
break;
}
@@ -498,11 +484,17 @@ static int __devinit fealnx_init_one(struct pci_dev *pdev,
int i, option, err, irq;
static int card_idx = -1;
char boardname[12];
- long ioaddr;
+ void __iomem *ioaddr;
+ unsigned long len;
unsigned int chip_id = ent->driver_data;
struct net_device *dev;
void *ring_space;
dma_addr_t ring_dma;
+#ifdef USE_IO_OPS
+ int bar = 0;
+#else
+ int bar = 1;
+#endif
/* when built into the kernel, we only print version if device is found */
#ifndef MODULE
@@ -520,14 +512,10 @@ static int __devinit fealnx_init_one(struct pci_dev *pdev,
if (i) return i;
pci_set_master(pdev);
-#ifdef USE_IO_OPS
- ioaddr = pci_resource_len(pdev, 0);
-#else
- ioaddr = pci_resource_len(pdev, 1);
-#endif
- if (ioaddr < MIN_REGION_SIZE) {
+ len = pci_resource_len(pdev, bar);
+ if (len < MIN_REGION_SIZE) {
printk(KERN_ERR "%s: region size %ld too small, aborting\n",
- boardname, ioaddr);
+ boardname, len);
return -ENODEV;
}
@@ -536,17 +524,12 @@ static int __devinit fealnx_init_one(struct pci_dev *pdev,
irq = pdev->irq;
-#ifdef USE_IO_OPS
- ioaddr = pci_resource_start(pdev, 0);
-#else
- ioaddr = (long) ioremap(pci_resource_start(pdev, 1),
- pci_resource_len(pdev, 1));
+ ioaddr = pci_iomap(pdev, bar, len);
if (!ioaddr) {
err = -ENOMEM;
goto err_out_res;
}
-#endif
-
+
dev = alloc_etherdev(sizeof(struct netdev_private));
if (!dev) {
err = -ENOMEM;
@@ -557,16 +540,17 @@ static int __devinit fealnx_init_one(struct pci_dev *pdev,
/* read ethernet id */
for (i = 0; i < 6; ++i)
- dev->dev_addr[i] = readb(ioaddr + PAR0 + i);
+ dev->dev_addr[i] = ioread8(ioaddr + PAR0 + i);
/* Reset the chip to erase previous misconfiguration. */
- writel(0x00000001, ioaddr + BCR);
+ iowrite32(0x00000001, ioaddr + BCR);
- dev->base_addr = ioaddr;
+ dev->base_addr = (unsigned long)ioaddr;
dev->irq = irq;
/* Make certain the descriptor lists are aligned. */
- np = dev->priv;
+ np = netdev_priv(dev);
+ np->mem = ioaddr;
spin_lock_init(&np->lock);
np->pci_dev = pdev;
np->flags = skel_netdrv_tbl[chip_id].flags;
@@ -635,7 +619,7 @@ static int __devinit fealnx_init_one(struct pci_dev *pdev,
np->phys[0] = 32;
/* 89/6/23 add, (begin) */
/* get phy type */
- if (readl(ioaddr + PHYIDENTIFIER) == MysonPHYID)
+ if (ioread32(ioaddr + PHYIDENTIFIER) == MysonPHYID)
np->PHYType = MysonPHY;
else
np->PHYType = OtherPHY;
@@ -670,7 +654,7 @@ static int __devinit fealnx_init_one(struct pci_dev *pdev,
if (np->flags == HAS_MII_XCVR)
mdio_write(dev, np->phys[0], MII_ADVERTISE, ADVERTISE_FULL);
else
- writel(ADVERTISE_FULL, ioaddr + ANARANLPAR);
+ iowrite32(ADVERTISE_FULL, ioaddr + ANARANLPAR);
np->mii.force_media = 1;
}
@@ -689,7 +673,7 @@ static int __devinit fealnx_init_one(struct pci_dev *pdev,
if (err)
goto err_out_free_tx;
- printk(KERN_INFO "%s: %s at 0x%lx, ",
+ printk(KERN_INFO "%s: %s at %p, ",
dev->name, skel_netdrv_tbl[chip_id].chip_name, ioaddr);
for (i = 0; i < 5; i++)
printk("%2.2x:", dev->dev_addr[i]);
@@ -704,10 +688,8 @@ err_out_free_rx:
err_out_free_dev:
free_netdev(dev);
err_out_unmap:
-#ifndef USE_IO_OPS
- iounmap((void *)ioaddr);
+ pci_iounmap(pdev, ioaddr);
err_out_res:
-#endif
pci_release_regions(pdev);
return err;
}
@@ -718,16 +700,14 @@ static void __devexit fealnx_remove_one(struct pci_dev *pdev)
struct net_device *dev = pci_get_drvdata(pdev);
if (dev) {
- struct netdev_private *np = dev->priv;
+ struct netdev_private *np = netdev_priv(dev);
pci_free_consistent(pdev, TX_TOTAL_SIZE, np->tx_ring,
np->tx_ring_dma);
pci_free_consistent(pdev, RX_TOTAL_SIZE, np->rx_ring,
np->rx_ring_dma);
unregister_netdev(dev);
-#ifndef USE_IO_OPS
- iounmap((void *)dev->base_addr);
-#endif
+ pci_iounmap(pdev, np->mem);
free_netdev(dev);
pci_release_regions(pdev);
pci_set_drvdata(pdev, NULL);
@@ -736,14 +716,14 @@ static void __devexit fealnx_remove_one(struct pci_dev *pdev)
}
-static ulong m80x_send_cmd_to_phy(long miiport, int opcode, int phyad, int regad)
+static ulong m80x_send_cmd_to_phy(void __iomem *miiport, int opcode, int phyad, int regad)
{
ulong miir;
int i;
unsigned int mask, data;
/* enable MII output */
- miir = (ulong) readl(miiport);
+ miir = (ulong) ioread32(miiport);
miir &= 0xfffffff0;
miir |= MASK_MIIR_MII_WRITE + MASK_MIIR_MII_MDO;
@@ -752,11 +732,11 @@ static ulong m80x_send_cmd_to_phy(long miiport, int opcode, int phyad, int regad
for (i = 0; i < 32; i++) {
/* low MDC; MDO is already high (miir) */
miir &= ~MASK_MIIR_MII_MDC;
- writel(miir, miiport);
+ iowrite32(miir, miiport);
/* high MDC */
miir |= MASK_MIIR_MII_MDC;
- writel(miir, miiport);
+ iowrite32(miir, miiport);
}
/* calculate ST+OP+PHYAD+REGAD+TA */
@@ -770,10 +750,10 @@ static ulong m80x_send_cmd_to_phy(long miiport, int opcode, int phyad, int regad
if (mask & data)
miir |= MASK_MIIR_MII_MDO;
- writel(miir, miiport);
+ iowrite32(miir, miiport);
/* high MDC */
miir |= MASK_MIIR_MII_MDC;
- writel(miir, miiport);
+ iowrite32(miir, miiport);
udelay(30);
/* next */
@@ -787,7 +767,8 @@ static ulong m80x_send_cmd_to_phy(long miiport, int opcode, int phyad, int regad
static int mdio_read(struct net_device *dev, int phyad, int regad)
{
- long miiport = dev->base_addr + MANAGEMENT;
+ struct netdev_private *np = netdev_priv(dev);
+ void __iomem *miiport = np->mem + MANAGEMENT;
ulong miir;
unsigned int mask, data;
@@ -799,16 +780,16 @@ static int mdio_read(struct net_device *dev, int phyad, int regad)
while (mask) {
/* low MDC */
miir &= ~MASK_MIIR_MII_MDC;
- writel(miir, miiport);
+ iowrite32(miir, miiport);
/* read MDI */
- miir = readl(miiport);
+ miir = ioread32(miiport);
if (miir & MASK_MIIR_MII_MDI)
data |= mask;
/* high MDC, and wait */
miir |= MASK_MIIR_MII_MDC;
- writel(miir, miiport);
+ iowrite32(miir, miiport);
udelay(30);
/* next */
@@ -817,7 +798,7 @@ static int mdio_read(struct net_device *dev, int phyad, int regad)
/* low MDC */
miir &= ~MASK_MIIR_MII_MDC;
- writel(miir, miiport);
+ iowrite32(miir, miiport);
return data & 0xffff;
}
@@ -825,7 +806,8 @@ static int mdio_read(struct net_device *dev, int phyad, int regad)
static void mdio_write(struct net_device *dev, int phyad, int regad, int data)
{
- long miiport = dev->base_addr + MANAGEMENT;
+ struct netdev_private *np = netdev_priv(dev);
+ void __iomem *miiport = np->mem + MANAGEMENT;
ulong miir;
unsigned int mask;
@@ -838,11 +820,11 @@ static void mdio_write(struct net_device *dev, int phyad, int regad, int data)
miir &= ~(MASK_MIIR_MII_MDC + MASK_MIIR_MII_MDO);
if (mask & data)
miir |= MASK_MIIR_MII_MDO;
- writel(miir, miiport);
+ iowrite32(miir, miiport);
/* high MDC */
miir |= MASK_MIIR_MII_MDC;
- writel(miir, miiport);
+ iowrite32(miir, miiport);
/* next */
mask >>= 1;
@@ -850,29 +832,29 @@ static void mdio_write(struct net_device *dev, int phyad, int regad, int data)
/* low MDC */
miir &= ~MASK_MIIR_MII_MDC;
- writel(miir, miiport);
+ iowrite32(miir, miiport);
}
static int netdev_open(struct net_device *dev)
{
- struct netdev_private *np = dev->priv;
- long ioaddr = dev->base_addr;
+ struct netdev_private *np = netdev_priv(dev);
+ void __iomem *ioaddr = np->mem;
int i;
- writel(0x00000001, ioaddr + BCR); /* Reset */
+ iowrite32(0x00000001, ioaddr + BCR); /* Reset */
if (request_irq(dev->irq, &intr_handler, SA_SHIRQ, dev->name, dev))
return -EAGAIN;
for (i = 0; i < 3; i++)
- writew(((unsigned short*)dev->dev_addr)[i],
+ iowrite16(((unsigned short*)dev->dev_addr)[i],
ioaddr + PAR0 + i*2);
init_ring(dev);
- writel(np->rx_ring_dma, ioaddr + RXLBA);
- writel(np->tx_ring_dma, ioaddr + TXLBA);
+ iowrite32(np->rx_ring_dma, ioaddr + RXLBA);
+ iowrite32(np->tx_ring_dma, ioaddr + TXLBA);
/* Initialize other registers. */
/* Configure the PCI bus bursts and FIFO thresholds.
@@ -933,12 +915,12 @@ static int netdev_open(struct net_device *dev)
np->crvalue |= CR_W_ENH; /* set enhanced bit */
np->imrvalue |= ETI;
}
- writel(np->bcrvalue, ioaddr + BCR);
+ iowrite32(np->bcrvalue, ioaddr + BCR);
if (dev->if_port == 0)
dev->if_port = np->default_port;
- writel(0, ioaddr + RXPDR);
+ iowrite32(0, ioaddr + RXPDR);
// 89/9/1 modify,
// np->crvalue = 0x00e40001; /* tx store and forward, tx/rx enable */
np->crvalue |= 0x00e40001; /* tx store and forward, tx/rx enable */
@@ -951,8 +933,8 @@ static int netdev_open(struct net_device *dev)
netif_start_queue(dev);
/* Clear and Enable interrupts by setting the interrupt mask. */
- writel(FBE | TUNF | CNTOVF | RBU | TI | RI, ioaddr + ISR);
- writel(np->imrvalue, ioaddr + IMR);
+ iowrite32(FBE | TUNF | CNTOVF | RBU | TI | RI, ioaddr + ISR);
+ iowrite32(np->imrvalue, ioaddr + IMR);
if (debug)
printk(KERN_DEBUG "%s: Done netdev_open().\n", dev->name);
@@ -980,14 +962,14 @@ static void getlinkstatus(struct net_device *dev)
/* input : dev... pointer to the adapter block. */
/* output : none. */
{
- struct netdev_private *np = dev->priv;
+ struct netdev_private *np = netdev_priv(dev);
unsigned int i, DelayTime = 0x1000;
np->linkok = 0;
if (np->PHYType == MysonPHY) {
for (i = 0; i < DelayTime; ++i) {
- if (readl(dev->base_addr + BMCRSR) & LinkIsUp2) {
+ if (ioread32(np->mem + BMCRSR) & LinkIsUp2) {
np->linkok = 1;
return;
}
@@ -1007,14 +989,14 @@ static void getlinkstatus(struct net_device *dev)
static void getlinktype(struct net_device *dev)
{
- struct netdev_private *np = dev->priv;
+ struct netdev_private *np = netdev_priv(dev);
if (np->PHYType == MysonPHY) { /* 3-in-1 case */
- if (readl(dev->base_addr + TCRRCR) & CR_R_FD)
+ if (ioread32(np->mem + TCRRCR) & CR_R_FD)
np->duplexmode = 2; /* full duplex */
else
np->duplexmode = 1; /* half duplex */
- if (readl(dev->base_addr + TCRRCR) & CR_R_PS10)
+ if (ioread32(np->mem + TCRRCR) & CR_R_PS10)
np->line_speed = 1; /* 10M */
else
np->line_speed = 2; /* 100M */
@@ -1110,7 +1092,7 @@ static void getlinktype(struct net_device *dev)
/* Take lock before calling this */
static void allocate_rx_buffers(struct net_device *dev)
{
- struct netdev_private *np = dev->priv;
+ struct netdev_private *np = netdev_priv(dev);
/* allocate skb for rx buffers */
while (np->really_rx_count != RX_RING_SIZE) {
@@ -1136,16 +1118,16 @@ static void allocate_rx_buffers(struct net_device *dev)
static void netdev_timer(unsigned long data)
{
struct net_device *dev = (struct net_device *) data;
- struct netdev_private *np = dev->priv;
- long ioaddr = dev->base_addr;
+ struct netdev_private *np = netdev_priv(dev);
+ void __iomem *ioaddr = np->mem;
int old_crvalue = np->crvalue;
unsigned int old_linkok = np->linkok;
unsigned long flags;
if (debug)
printk(KERN_DEBUG "%s: Media selection timer tick, status %8.8x "
- "config %8.8x.\n", dev->name, readl(ioaddr + ISR),
- readl(ioaddr + TCRRCR));
+ "config %8.8x.\n", dev->name, ioread32(ioaddr + ISR),
+ ioread32(ioaddr + TCRRCR));
spin_lock_irqsave(&np->lock, flags);
@@ -1155,7 +1137,7 @@ static void netdev_timer(unsigned long data)
getlinktype(dev);
if (np->crvalue != old_crvalue) {
stop_nic_rxtx(ioaddr, np->crvalue);
- writel(np->crvalue, ioaddr + TCRRCR);
+ iowrite32(np->crvalue, ioaddr + TCRRCR);
}
}
}
@@ -1173,22 +1155,23 @@ static void netdev_timer(unsigned long data)
/* Reset chip and disable rx, tx and interrupts */
static void reset_and_disable_rxtx(struct net_device *dev)
{
- long ioaddr = dev->base_addr;
+ struct netdev_private *np = netdev_priv(dev);
+ void __iomem *ioaddr = np->mem;
int delay=51;
/* Reset the chip's Tx and Rx processes. */
stop_nic_rxtx(ioaddr, 0);
/* Disable interrupts by clearing the interrupt mask. */
- writel(0, ioaddr + IMR);
+ iowrite32(0, ioaddr + IMR);
/* Reset the chip to erase previous misconfiguration. */
- writel(0x00000001, ioaddr + BCR);
+ iowrite32(0x00000001, ioaddr + BCR);
/* Ueimor: wait for 50 PCI cycles (and flush posted writes btw).
We surely wait too long (address+data phase). Who cares? */
while (--delay) {
- readl(ioaddr + BCR);
+ ioread32(ioaddr + BCR);
rmb();
}
}
@@ -1198,33 +1181,33 @@ static void reset_and_disable_rxtx(struct net_device *dev)
/* Restore chip after reset */
static void enable_rxtx(struct net_device *dev)
{
- struct netdev_private *np = dev->priv;
- long ioaddr = dev->base_addr;
+ struct netdev_private *np = netdev_priv(dev);
+ void __iomem *ioaddr = np->mem;
reset_rx_descriptors(dev);
- writel(np->tx_ring_dma + ((char*)np->cur_tx - (char*)np->tx_ring),
+ iowrite32(np->tx_ring_dma + ((char*)np->cur_tx - (char*)np->tx_ring),
ioaddr + TXLBA);
- writel(np->rx_ring_dma + ((char*)np->cur_rx - (char*)np->rx_ring),
+ iowrite32(np->rx_ring_dma + ((char*)np->cur_rx - (char*)np->rx_ring),
ioaddr + RXLBA);
- writel(np->bcrvalue, ioaddr + BCR);
+ iowrite32(np->bcrvalue, ioaddr + BCR);
- writel(0, ioaddr + RXPDR);
+ iowrite32(0, ioaddr + RXPDR);
__set_rx_mode(dev); /* changes np->crvalue, writes it into TCRRCR */
/* Clear and Enable interrupts by setting the interrupt mask. */
- writel(FBE | TUNF | CNTOVF | RBU | TI | RI, ioaddr + ISR);
- writel(np->imrvalue, ioaddr + IMR);
+ iowrite32(FBE | TUNF | CNTOVF | RBU | TI | RI, ioaddr + ISR);
+ iowrite32(np->imrvalue, ioaddr + IMR);
- writel(0, ioaddr + TXPDR);
+ iowrite32(0, ioaddr + TXPDR);
}
static void reset_timer(unsigned long data)
{
struct net_device *dev = (struct net_device *) data;
- struct netdev_private *np = dev->priv;
+ struct netdev_private *np = netdev_priv(dev);
unsigned long flags;
printk(KERN_WARNING "%s: resetting tx and rx machinery\n", dev->name);
@@ -1247,13 +1230,13 @@ static void reset_timer(unsigned long data)
static void tx_timeout(struct net_device *dev)
{
- struct netdev_private *np = dev->priv;
- long ioaddr = dev->base_addr;
+ struct netdev_private *np = netdev_priv(dev);
+ void __iomem *ioaddr = np->mem;
unsigned long flags;
int i;
printk(KERN_WARNING "%s: Transmit timed out, status %8.8x,"
- " resetting...\n", dev->name, readl(ioaddr + ISR));
+ " resetting...\n", dev->name, ioread32(ioaddr + ISR));
{
printk(KERN_DEBUG " Rx ring %p: ", np->rx_ring);
@@ -1282,7 +1265,7 @@ static void tx_timeout(struct net_device *dev)
/* Initialize the Rx and Tx rings, along with various 'dev' bits. */
static void init_ring(struct net_device *dev)
{
- struct netdev_private *np = dev->priv;
+ struct netdev_private *np = netdev_priv(dev);
int i;
/* initialize rx variables */
@@ -1346,7 +1329,7 @@ static void init_ring(struct net_device *dev)
static int start_tx(struct sk_buff *skb, struct net_device *dev)
{
- struct netdev_private *np = dev->priv;
+ struct netdev_private *np = netdev_priv(dev);
unsigned long flags;
spin_lock_irqsave(&np->lock, flags);
@@ -1413,7 +1396,7 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev)
if (np->free_tx_count < 2)
netif_stop_queue(dev);
++np->really_tx_count;
- writel(0, dev->base_addr + TXPDR);
+ iowrite32(0, np->mem + TXPDR);
dev->trans_start = jiffies;
spin_unlock_irqrestore(&np->lock, flags);
@@ -1425,7 +1408,7 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev)
/* Chip probably hosed tx ring. Clean up. */
static void reset_tx_descriptors(struct net_device *dev)
{
- struct netdev_private *np = dev->priv;
+ struct netdev_private *np = netdev_priv(dev);
struct fealnx_desc *cur;
int i;
@@ -1460,7 +1443,7 @@ static void reset_tx_descriptors(struct net_device *dev)
/* Take lock and stop rx before calling this */
static void reset_rx_descriptors(struct net_device *dev)
{
- struct netdev_private *np = dev->priv;
+ struct netdev_private *np = netdev_priv(dev);
struct fealnx_desc *cur = np->cur_rx;
int i;
@@ -1472,8 +1455,8 @@ static void reset_rx_descriptors(struct net_device *dev)
cur = cur->next_desc_logical;
}
- writel(np->rx_ring_dma + ((char*)np->cur_rx - (char*)np->rx_ring),
- dev->base_addr + RXLBA);
+ iowrite32(np->rx_ring_dma + ((char*)np->cur_rx - (char*)np->rx_ring),
+ np->mem + RXLBA);
}
@@ -1482,21 +1465,21 @@ static void reset_rx_descriptors(struct net_device *dev)
static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *rgs)
{
struct net_device *dev = (struct net_device *) dev_instance;
- struct netdev_private *np = dev->priv;
- long ioaddr = dev->base_addr;
+ struct netdev_private *np = netdev_priv(dev);
+ void __iomem *ioaddr = np->mem;
long boguscnt = max_interrupt_work;
unsigned int num_tx = 0;
int handled = 0;
spin_lock(&np->lock);
- writel(0, ioaddr + IMR);
+ iowrite32(0, ioaddr + IMR);
do {
- u32 intr_status = readl(ioaddr + ISR);
+ u32 intr_status = ioread32(ioaddr + ISR);
/* Acknowledge all of the current interrupt sources ASAP. */
- writel(intr_status, ioaddr + ISR);
+ iowrite32(intr_status, ioaddr + ISR);
if (debug)
printk(KERN_DEBUG "%s: Interrupt, status %4.4x.\n", dev->name,
@@ -1517,15 +1500,15 @@ static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *rgs
// };
if (intr_status & TUNF)
- writel(0, ioaddr + TXPDR);
+ iowrite32(0, ioaddr + TXPDR);
if (intr_status & CNTOVF) {
/* missed pkts */
- np->stats.rx_missed_errors += readl(ioaddr + TALLY) & 0x7fff;
+ np->stats.rx_missed_errors += ioread32(ioaddr + TALLY) & 0x7fff;
/* crc error */
np->stats.rx_crc_errors +=
- (readl(ioaddr + TALLY) & 0x7fff0000) >> 16;
+ (ioread32(ioaddr + TALLY) & 0x7fff0000) >> 16;
}
if (intr_status & (RI | RBU)) {
@@ -1534,7 +1517,7 @@ static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *rgs
else {
stop_nic_rx(ioaddr, np->crvalue);
reset_rx_descriptors(dev);
- writel(np->crvalue, ioaddr + TCRRCR);
+ iowrite32(np->crvalue, ioaddr + TCRRCR);
}
}
@@ -1605,7 +1588,7 @@ static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *rgs
if (np->crvalue & CR_W_ENH) {
long data;
- data = readl(ioaddr + TSR);
+ data = ioread32(ioaddr + TSR);
np->stats.tx_errors += (data & 0xff000000) >> 24;
np->stats.tx_aborted_errors += (data & 0xff000000) >> 24;
np->stats.tx_window_errors += (data & 0x00ff0000) >> 16;
@@ -1635,16 +1618,16 @@ static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *rgs
/* read the tally counters */
/* missed pkts */
- np->stats.rx_missed_errors += readl(ioaddr + TALLY) & 0x7fff;
+ np->stats.rx_missed_errors += ioread32(ioaddr + TALLY) & 0x7fff;
/* crc error */
- np->stats.rx_crc_errors += (readl(ioaddr + TALLY) & 0x7fff0000) >> 16;
+ np->stats.rx_crc_errors += (ioread32(ioaddr + TALLY) & 0x7fff0000) >> 16;
if (debug)
printk(KERN_DEBUG "%s: exiting interrupt, status=%#4.4x.\n",
- dev->name, readl(ioaddr + ISR));
+ dev->name, ioread32(ioaddr + ISR));
- writel(np->imrvalue, ioaddr + IMR);
+ iowrite32(np->imrvalue, ioaddr + IMR);
spin_unlock(&np->lock);
@@ -1656,8 +1639,8 @@ static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *rgs
for clarity and better register allocation. */
static int netdev_rx(struct net_device *dev)
{
- struct netdev_private *np = dev->priv;
- long ioaddr = dev->base_addr;
+ struct netdev_private *np = netdev_priv(dev);
+ void __iomem *ioaddr = np->mem;
/* If EOP is set on the next entry, it's a new packet. Send it up. */
while (!(np->cur_rx->status & RXOWN) && np->cur_rx->skbuff) {
@@ -1725,7 +1708,7 @@ static int netdev_rx(struct net_device *dev)
} else { /* rx error, need to reset this chip */
stop_nic_rx(ioaddr, np->crvalue);
reset_rx_descriptors(dev);
- writel(np->crvalue, ioaddr + TCRRCR);
+ iowrite32(np->crvalue, ioaddr + TCRRCR);
}
break; /* exit the while loop */
}
@@ -1793,13 +1776,13 @@ static int netdev_rx(struct net_device *dev)
static struct net_device_stats *get_stats(struct net_device *dev)
{
- long ioaddr = dev->base_addr;
- struct netdev_private *np = dev->priv;
+ struct netdev_private *np = netdev_priv(dev);
+ void __iomem *ioaddr = np->mem;
/* The chip only need report frame silently dropped. */
if (netif_running(dev)) {
- np->stats.rx_missed_errors += readl(ioaddr + TALLY) & 0x7fff;
- np->stats.rx_crc_errors += (readl(ioaddr + TALLY) & 0x7fff0000) >> 16;
+ np->stats.rx_missed_errors += ioread32(ioaddr + TALLY) & 0x7fff;
+ np->stats.rx_crc_errors += (ioread32(ioaddr + TALLY) & 0x7fff0000) >> 16;
}
return &np->stats;
@@ -1809,7 +1792,7 @@ static struct net_device_stats *get_stats(struct net_device *dev)
/* for dev->set_multicast_list */
static void set_rx_mode(struct net_device *dev)
{
- spinlock_t *lp = &((struct netdev_private *)dev->priv)->lock;
+ spinlock_t *lp = &((struct netdev_private *)netdev_priv(dev))->lock;
unsigned long flags;
spin_lock_irqsave(lp, flags);
__set_rx_mode(dev);
@@ -1820,8 +1803,8 @@ static void set_rx_mode(struct net_device *dev)
/* Take lock before calling */
static void __set_rx_mode(struct net_device *dev)
{
- struct netdev_private *np = dev->priv;
- long ioaddr = dev->base_addr;
+ struct netdev_private *np = netdev_priv(dev);
+ void __iomem *ioaddr = np->mem;
u32 mc_filter[2]; /* Multicast hash filter */
u32 rx_mode;
@@ -1851,16 +1834,16 @@ static void __set_rx_mode(struct net_device *dev)
stop_nic_rxtx(ioaddr, np->crvalue);
- writel(mc_filter[0], ioaddr + MAR0);
- writel(mc_filter[1], ioaddr + MAR1);
+ iowrite32(mc_filter[0], ioaddr + MAR0);
+ iowrite32(mc_filter[1], ioaddr + MAR1);
np->crvalue &= ~CR_W_RXMODEMASK;
np->crvalue |= rx_mode;
- writel(np->crvalue, ioaddr + TCRRCR);
+ iowrite32(np->crvalue, ioaddr + TCRRCR);
}
static void netdev_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
{
- struct netdev_private *np = dev->priv;
+ struct netdev_private *np = netdev_priv(dev);
strcpy(info->driver, DRV_NAME);
strcpy(info->version, DRV_VERSION);
@@ -1869,7 +1852,7 @@ static void netdev_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *i
static int netdev_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
- struct netdev_private *np = dev->priv;
+ struct netdev_private *np = netdev_priv(dev);
int rc;
spin_lock_irq(&np->lock);
@@ -1881,7 +1864,7 @@ static int netdev_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
static int netdev_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
- struct netdev_private *np = dev->priv;
+ struct netdev_private *np = netdev_priv(dev);
int rc;
spin_lock_irq(&np->lock);
@@ -1893,13 +1876,13 @@ static int netdev_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
static int netdev_nway_reset(struct net_device *dev)
{
- struct netdev_private *np = dev->priv;
+ struct netdev_private *np = netdev_priv(dev);
return mii_nway_restart(&np->mii);
}
static u32 netdev_get_link(struct net_device *dev)
{
- struct netdev_private *np = dev->priv;
+ struct netdev_private *np = netdev_priv(dev);
return mii_link_ok(&np->mii);
}
@@ -1927,7 +1910,7 @@ static struct ethtool_ops netdev_ethtool_ops = {
static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
- struct netdev_private *np = dev->priv;
+ struct netdev_private *np = netdev_priv(dev);
int rc;
if (!netif_running(dev))
@@ -1943,14 +1926,14 @@ static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
static int netdev_close(struct net_device *dev)
{
- long ioaddr = dev->base_addr;
- struct netdev_private *np = dev->priv;
+ struct netdev_private *np = netdev_priv(dev);
+ void __iomem *ioaddr = np->mem;
int i;
netif_stop_queue(dev);
/* Disable interrupts by clearing the interrupt mask. */
- writel(0x0000, ioaddr + IMR);
+ iowrite32(0x0000, ioaddr + IMR);
/* Stop the chip's Tx and Rx processes. */
stop_nic_rxtx(ioaddr, 0);
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index 8b5596945976c..b43b2b11aacd7 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -377,6 +377,8 @@ static int init_phy(struct net_device *dev)
ADVERTISED_1000baseT_Full);
mii_info->autoneg = 1;
+ spin_lock_init(&mii_info->mdio_lock);
+
mii_info->mii_id = priv->einfo->phyid;
mii_info->dev = dev;
diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c
index 48af4c20ffa1d..067b353e1cbda 100644
--- a/drivers/net/hamradio/6pack.c
+++ b/drivers/net/hamradio/6pack.c
@@ -756,12 +756,12 @@ static int sixpack_ioctl(struct tty_struct *tty, struct file *file,
switch(cmd) {
case SIOCGIFNAME:
- err = copy_to_user((void *) arg, dev->name,
+ err = copy_to_user((void __user *) arg, dev->name,
strlen(dev->name) + 1) ? -EFAULT : 0;
break;
case SIOCGIFENCAP:
- err = put_user(0, (int __user *)arg);
+ err = put_user(0, (int __user *) arg);
break;
case SIOCSIFENCAP:
diff --git a/drivers/net/hamradio/baycom_epp.c b/drivers/net/hamradio/baycom_epp.c
index 274d15cc4688e..e8cb87d906fcf 100644
--- a/drivers/net/hamradio/baycom_epp.c
+++ b/drivers/net/hamradio/baycom_epp.c
@@ -68,25 +68,7 @@
/* --------------------------------------------------------------------- */
static const char paranoia_str[] = KERN_ERR
-"baycom_epp: bad magic number for hdlcdrv_state struct in routine %s\n";
-
-#define baycom_paranoia_check(dev,routine,retval) \
-({ \
- if (!dev || !dev->priv || ((struct baycom_state *)dev->priv)->magic != BAYCOM_MAGIC) { \
- printk(paranoia_str, routine); \
- return retval; \
- } \
-})
-
-#define baycom_paranoia_check_void(dev,routine) \
-({ \
- if (!dev || !dev->priv || ((struct baycom_state *)dev->priv)->magic != BAYCOM_MAGIC) { \
- printk(paranoia_str, routine); \
- return; \
- } \
-})
-
-/* --------------------------------------------------------------------- */
+ "baycom_epp: bad magic number for hdlcdrv_state struct in routine %s\n";
static const char bc_drvname[] = "baycom_epp";
static const char bc_drvinfo[] = KERN_INFO "baycom_epp: (C) 1998-2000 Thomas Sailer, HB9JNX/AE4WA\n"
@@ -747,7 +729,6 @@ static void epp_bh(struct net_device *dev)
unsigned int time1 = 0, time2 = 0, time3 = 0;
int cnt, cnt2;
- baycom_paranoia_check_void(dev, "epp_bh");
bc = netdev_priv(dev);
if (!bc->work_running)
return;
@@ -863,10 +844,8 @@ static void epp_bh(struct net_device *dev)
static int baycom_send_packet(struct sk_buff *skb, struct net_device *dev)
{
- struct baycom_state *bc;
+ struct baycom_state *bc = netdev_priv(dev);
- baycom_paranoia_check(dev, "baycom_send_packet", 0);
- bc = netdev_priv(dev);
if (skb->data[0] != 0) {
do_kiss_params(bc, skb->data, skb->len);
dev_kfree_skb(skb);
@@ -899,10 +878,8 @@ static int baycom_set_mac_address(struct net_device *dev, void *addr)
static struct net_device_stats *baycom_get_stats(struct net_device *dev)
{
- struct baycom_state *bc;
+ struct baycom_state *bc = netdev_priv(dev);
- baycom_paranoia_check(dev, "baycom_get_stats", NULL);
- bc = netdev_priv(dev);
/*
* Get the current statistics. This may be called with the
* card open or closed.
@@ -915,10 +892,8 @@ static struct net_device_stats *baycom_get_stats(struct net_device *dev)
static void epp_wakeup(void *handle)
{
struct net_device *dev = (struct net_device *)handle;
- struct baycom_state *bc;
+ struct baycom_state *bc = netdev_priv(dev);
- baycom_paranoia_check_void(dev, "epp_wakeup");
- bc = netdev_priv(dev);
printk(KERN_DEBUG "baycom_epp: %s: why am I being woken up?\n", dev->name);
if (!parport_claim(bc->pdev))
printk(KERN_DEBUG "baycom_epp: %s: I'm broken.\n", dev->name);
@@ -937,16 +912,13 @@ static void epp_wakeup(void *handle)
static int epp_open(struct net_device *dev)
{
- struct baycom_state *bc;
- struct parport *pp;
+ struct baycom_state *bc = netdev_priv(dev);
+ struct parport *pp = parport_find_base(dev->base_addr);
unsigned int i, j;
unsigned char tmp[128];
unsigned char stat;
unsigned long tstart;
- baycom_paranoia_check(dev, "epp_open", -ENXIO);
- bc = netdev_priv(dev);
- pp = parport_find_base(dev->base_addr);
if (!pp) {
printk(KERN_ERR "%s: parport at 0x%lx unknown\n", bc_drvname, dev->base_addr);
return -ENXIO;
@@ -1055,13 +1027,10 @@ static int epp_open(struct net_device *dev)
static int epp_close(struct net_device *dev)
{
- struct baycom_state *bc;
- struct parport *pp;
+ struct baycom_state *bc = netdev_priv(dev);
+ struct parport *pp = bc->pdev->port;
unsigned char tmp[1];
- baycom_paranoia_check(dev, "epp_close", -EINVAL);
- bc = netdev_priv(dev);
- pp = bc->pdev->port;
bc->work_running = 0;
flush_scheduled_work();
bc->stat = EPP_DCDBIT;
@@ -1117,11 +1086,9 @@ static int baycom_setmode(struct baycom_state *bc, const char *modestr)
static int baycom_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
- struct baycom_state *bc;
+ struct baycom_state *bc = netdev_priv(dev);
struct hdlcdrv_ioctl hi;
- baycom_paranoia_check(dev, "baycom_ioctl", -EINVAL);
- bc = netdev_priv(dev);
if (cmd != SIOCDEVPRIVATE)
return -ENOIOCTLCMD;
@@ -1354,7 +1321,7 @@ static int __init init_baycomepp(void)
free_netdev(dev);
break;
}
- if (set_hw && baycom_setmode(dev->priv, mode[i]))
+ if (set_hw && baycom_setmode(netdev_priv(dev), mode[i]))
set_hw = 0;
baycom_device[i] = dev;
found++;
diff --git a/drivers/net/hamradio/baycom_par.c b/drivers/net/hamradio/baycom_par.c
index eb9a680092b20..612ad452bee03 100644
--- a/drivers/net/hamradio/baycom_par.c
+++ b/drivers/net/hamradio/baycom_par.c
@@ -85,6 +85,7 @@
#include <linux/parport.h>
#include <linux/bitops.h>
+#include <asm/bug.h>
#include <asm/system.h>
#include <asm/uaccess.h>
@@ -415,12 +416,11 @@ static int baycom_ioctl(struct net_device *dev, struct ifreq *ifr,
struct baycom_state *bc;
struct baycom_ioctl bi;
- if (!dev || !dev->priv ||
- ((struct baycom_state *)dev->priv)->hdrv.magic != HDLCDRV_MAGIC) {
- printk(KERN_ERR "bc_ioctl: invalid device struct\n");
+ if (!dev)
return -EINVAL;
- }
+
bc = netdev_priv(dev);
+ BUG_ON(bc->hdrv.magic != HDLCDRV_MAGIC);
if (cmd != SIOCDEVPRIVATE)
return -ENOIOCTLCMD;
diff --git a/drivers/net/hamradio/baycom_ser_fdx.c b/drivers/net/hamradio/baycom_ser_fdx.c
index 454dff0c48622..25f270b053788 100644
--- a/drivers/net/hamradio/baycom_ser_fdx.c
+++ b/drivers/net/hamradio/baycom_ser_fdx.c
@@ -530,12 +530,11 @@ static int baycom_ioctl(struct net_device *dev, struct ifreq *ifr,
struct baycom_state *bc;
struct baycom_ioctl bi;
- if (!dev || !dev->priv ||
- ((struct baycom_state *)dev->priv)->hdrv.magic != HDLCDRV_MAGIC) {
- printk(KERN_ERR "bc_ioctl: invalid device struct\n");
+ if (!dev)
return -EINVAL;
- }
+
bc = netdev_priv(dev);
+ BUG_ON(bc->hdrv.magic != HDLCDRV_MAGIC);
if (cmd != SIOCDEVPRIVATE)
return -ENOIOCTLCMD;
diff --git a/drivers/net/hamradio/baycom_ser_hdx.c b/drivers/net/hamradio/baycom_ser_hdx.c
index 14267aaeb0060..eead85d009627 100644
--- a/drivers/net/hamradio/baycom_ser_hdx.c
+++ b/drivers/net/hamradio/baycom_ser_hdx.c
@@ -570,12 +570,11 @@ static int baycom_ioctl(struct net_device *dev, struct ifreq *ifr,
struct baycom_state *bc;
struct baycom_ioctl bi;
- if (!dev || !dev->priv ||
- ((struct baycom_state *)dev->priv)->hdrv.magic != HDLCDRV_MAGIC) {
- printk(KERN_ERR "bc_ioctl: invalid device struct\n");
+ if (!dev)
return -EINVAL;
- }
+
bc = netdev_priv(dev);
+ BUG_ON(bc->hdrv.magic != HDLCDRV_MAGIC);
if (cmd != SIOCDEVPRIVATE)
return -ENOIOCTLCMD;
diff --git a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c
index 803d5a13715a0..ef1a359e22734 100644
--- a/drivers/net/hamradio/bpqether.c
+++ b/drivers/net/hamradio/bpqether.c
@@ -112,8 +112,6 @@ static struct notifier_block bpq_dev_notifier = {
};
-#define MAXBPQDEV 100
-
struct bpqdev {
struct list_head bpq_list; /* list of bpq devices chain */
struct net_device *ethdev; /* link to ethernet device */
@@ -134,7 +132,7 @@ static LIST_HEAD(bpq_devices);
*/
static inline struct net_device *bpq_get_ether_dev(struct net_device *dev)
{
- struct bpqdev *bpq = (struct bpqdev *) dev->priv;
+ struct bpqdev *bpq = netdev_priv(dev);
return bpq ? bpq->ethdev : NULL;
}
@@ -191,7 +189,7 @@ static int bpq_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_ty
* we check the source address of the sender.
*/
- bpq = (struct bpqdev *)dev->priv;
+ bpq = netdev_priv(dev);
eth = eth_hdr(skb);
@@ -281,7 +279,7 @@ static int bpq_xmit(struct sk_buff *skb, struct net_device *dev)
*ptr++ = (size + 5) % 256;
*ptr++ = (size + 5) / 256;
- bpq = (struct bpqdev *)dev->priv;
+ bpq = netdev_priv(dev);
if ((dev = bpq_get_ether_dev(dev)) == NULL) {
bpq->stats.tx_dropped++;
@@ -305,7 +303,7 @@ static int bpq_xmit(struct sk_buff *skb, struct net_device *dev)
*/
static struct net_device_stats *bpq_get_stats(struct net_device *dev)
{
- struct bpqdev *bpq = (struct bpqdev *) dev->priv;
+ struct bpqdev *bpq = netdev_priv(dev);
return &bpq->stats;
}
@@ -332,15 +330,12 @@ static int bpq_set_mac_address(struct net_device *dev, void *addr)
static int bpq_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
struct bpq_ethaddr __user *ethaddr = ifr->ifr_data;
- struct bpqdev *bpq = dev->priv;
+ struct bpqdev *bpq = netdev_priv(dev);
struct bpq_req req;
if (!capable(CAP_NET_ADMIN))
return -EPERM;
- if (bpq == NULL) /* woops! */
- return -ENODEV;
-
switch (cmd) {
case SIOCSBPQETHOPT:
if (copy_from_user(&req, ifr->ifr_data, sizeof(struct bpq_req)))
@@ -525,7 +520,7 @@ static int bpq_new_device(struct net_device *edev)
return -ENOMEM;
- bpq = ndev->priv;
+ bpq = netdev_priv(ndev);
dev_hold(edev);
bpq->ethdev = edev;
bpq->axdev = ndev;
@@ -554,7 +549,7 @@ static int bpq_new_device(struct net_device *edev)
static void bpq_free_device(struct net_device *ndev)
{
- struct bpqdev *bpq = ndev->priv;
+ struct bpqdev *bpq = netdev_priv(ndev);
dev_put(bpq->ethdev);
list_del_rcu(&bpq->bpq_list);
diff --git a/drivers/net/hamradio/dmascc.c b/drivers/net/hamradio/dmascc.c
index 94191fdb8e130..f3269b70a8c59 100644
--- a/drivers/net/hamradio/dmascc.c
+++ b/drivers/net/hamradio/dmascc.c
@@ -1,6 +1,4 @@
/*
- * $Id: dmascc.c,v 1.27 2000/06/01 14:46:23 oe1kib Exp $
- *
* Driver for high-speed SCC boards (those with DMA support)
* Copyright (C) 1997-2000 Klaus Kudielka
*
@@ -19,7 +17,6 @@
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
*/
@@ -49,9 +46,9 @@
/* Number of buffers per channel */
-#define NUM_TX_BUF 2 /* NUM_TX_BUF >= 1 (min. 2 recommended) */
-#define NUM_RX_BUF 6 /* NUM_RX_BUF >= 1 (min. 2 recommended) */
-#define BUF_SIZE 1576 /* BUF_SIZE >= mtu + hard_header_len */
+#define NUM_TX_BUF 2 /* NUM_TX_BUF >= 1 (min. 2 recommended) */
+#define NUM_RX_BUF 6 /* NUM_RX_BUF >= 1 (min. 2 recommended) */
+#define BUF_SIZE 1576 /* BUF_SIZE >= mtu + hard_header_len */
/* Cards supported */
@@ -67,7 +64,7 @@
#define HARDWARE { HW_PI, HW_PI2, HW_TWIN, HW_S5 }
-#define TMR_0_HZ 25600 /* Frequency of timer 0 */
+#define TMR_0_HZ 25600 /* Frequency of timer 0 */
#define TYPE_PI 0
#define TYPE_PI2 1
@@ -164,69 +161,69 @@
/* Data types */
struct scc_param {
- int pclk_hz; /* frequency of BRG input (don't change) */
- int brg_tc; /* BRG terminal count; BRG disabled if < 0 */
- int nrzi; /* 0 (nrz), 1 (nrzi) */
- int clocks; /* see dmascc_cfg documentation */
- int txdelay; /* [1/TMR_0_HZ] */
- int txtimeout; /* [1/HZ] */
- int txtail; /* [1/TMR_0_HZ] */
- int waittime; /* [1/TMR_0_HZ] */
- int slottime; /* [1/TMR_0_HZ] */
- int persist; /* 1 ... 256 */
- int dma; /* -1 (disable), 0, 1, 3 */
- int txpause; /* [1/TMR_0_HZ] */
- int rtsoff; /* [1/TMR_0_HZ] */
- int dcdon; /* [1/TMR_0_HZ] */
- int dcdoff; /* [1/TMR_0_HZ] */
+ int pclk_hz; /* frequency of BRG input (don't change) */
+ int brg_tc; /* BRG terminal count; BRG disabled if < 0 */
+ int nrzi; /* 0 (nrz), 1 (nrzi) */
+ int clocks; /* see dmascc_cfg documentation */
+ int txdelay; /* [1/TMR_0_HZ] */
+ int txtimeout; /* [1/HZ] */
+ int txtail; /* [1/TMR_0_HZ] */
+ int waittime; /* [1/TMR_0_HZ] */
+ int slottime; /* [1/TMR_0_HZ] */
+ int persist; /* 1 ... 256 */
+ int dma; /* -1 (disable), 0, 1, 3 */
+ int txpause; /* [1/TMR_0_HZ] */
+ int rtsoff; /* [1/TMR_0_HZ] */
+ int dcdon; /* [1/TMR_0_HZ] */
+ int dcdoff; /* [1/TMR_0_HZ] */
};
struct scc_hardware {
- char *name;
- int io_region;
- int io_delta;
- int io_size;
- int num_devs;
- int scc_offset;
- int tmr_offset;
- int tmr_hz;
- int pclk_hz;
+ char *name;
+ int io_region;
+ int io_delta;
+ int io_size;
+ int num_devs;
+ int scc_offset;
+ int tmr_offset;
+ int tmr_hz;
+ int pclk_hz;
};
struct scc_priv {
- int type;
- int chip;
- struct net_device *dev;
- struct scc_info *info;
- struct net_device_stats stats;
- int channel;
- int card_base, scc_cmd, scc_data;
- int tmr_cnt, tmr_ctrl, tmr_mode;
- struct scc_param param;
- char rx_buf[NUM_RX_BUF][BUF_SIZE];
- int rx_len[NUM_RX_BUF];
- int rx_ptr;
- struct work_struct rx_work;
- int rx_head, rx_tail, rx_count;
- int rx_over;
- char tx_buf[NUM_TX_BUF][BUF_SIZE];
- int tx_len[NUM_TX_BUF];
- int tx_ptr;
- int tx_head, tx_tail, tx_count;
- int state;
- unsigned long tx_start;
- int rr0;
- spinlock_t *register_lock; /* Per scc_info */
- spinlock_t ring_lock;
+ int type;
+ int chip;
+ struct net_device *dev;
+ struct scc_info *info;
+ struct net_device_stats stats;
+ int channel;
+ int card_base, scc_cmd, scc_data;
+ int tmr_cnt, tmr_ctrl, tmr_mode;
+ struct scc_param param;
+ char rx_buf[NUM_RX_BUF][BUF_SIZE];
+ int rx_len[NUM_RX_BUF];
+ int rx_ptr;
+ struct work_struct rx_work;
+ int rx_head, rx_tail, rx_count;
+ int rx_over;
+ char tx_buf[NUM_TX_BUF][BUF_SIZE];
+ int tx_len[NUM_TX_BUF];
+ int tx_ptr;
+ int tx_head, tx_tail, tx_count;
+ int state;
+ unsigned long tx_start;
+ int rr0;
+ spinlock_t *register_lock; /* Per scc_info */
+ spinlock_t ring_lock;
};
struct scc_info {
- int irq_used;
- int twin_serial_cfg;
- struct net_device *dev[2];
- struct scc_priv priv[2];
- struct scc_info *next;
- spinlock_t register_lock; /* Per device register lock */
+ int irq_used;
+ int twin_serial_cfg;
+ struct net_device *dev[2];
+ struct scc_priv priv[2];
+ struct scc_info *next;
+ spinlock_t register_lock; /* Per device register lock */
};
@@ -252,7 +249,7 @@ static void start_timer(struct scc_priv *priv, int t, int r15);
static inline unsigned char random(void);
static inline void z8530_isr(struct scc_info *info);
-static irqreturn_t scc_isr(int irq, void *dev_id, struct pt_regs * regs);
+static irqreturn_t scc_isr(int irq, void *dev_id, struct pt_regs *regs);
static void rx_isr(struct scc_priv *priv);
static void special_condition(struct scc_priv *priv, int rc);
static void rx_bh(void *arg);
@@ -264,12 +261,15 @@ static void tm_isr(struct scc_priv *priv);
/* Initialization variables */
static int io[MAX_NUM_DEVS] __initdata = { 0, };
+
/* Beware! hw[] is also used in cleanup_module(). */
static struct scc_hardware hw[NUM_TYPES] __initdata_or_module = HARDWARE;
static char ax25_broadcast[7] __initdata =
- { 'Q'<<1, 'S'<<1, 'T'<<1, ' '<<1, ' '<<1, ' '<<1, '0'<<1 };
+ { 'Q' << 1, 'S' << 1, 'T' << 1, ' ' << 1, ' ' << 1, ' ' << 1,
+'0' << 1 };
static char ax25_test[7] __initdata =
- { 'L'<<1, 'I'<<1, 'N'<<1, 'U'<<1, 'X'<<1, ' '<<1, '1'<<1 };
+ { 'L' << 1, 'I' << 1, 'N' << 1, 'U' << 1, 'X' << 1, ' ' << 1,
+'1' << 1 };
/* Global variables */
@@ -283,143 +283,164 @@ MODULE_DESCRIPTION("Driver for high-speed SCC boards");
MODULE_PARM(io, "1-" __MODULE_STRING(MAX_NUM_DEVS) "i");
MODULE_LICENSE("GPL");
-static void __exit dmascc_exit(void) {
- int i;
- struct scc_info *info;
+static void __exit dmascc_exit(void)
+{
+ int i;
+ struct scc_info *info;
- while (first) {
- info = first;
+ while (first) {
+ info = first;
- /* Unregister devices */
- for (i = 0; i < 2; i++)
- unregister_netdev(info->dev[i]);
+ /* Unregister devices */
+ for (i = 0; i < 2; i++)
+ unregister_netdev(info->dev[i]);
- /* Reset board */
- if (info->priv[0].type == TYPE_TWIN)
- outb(0, info->dev[0]->base_addr + TWIN_SERIAL_CFG);
- write_scc(&info->priv[0], R9, FHWRES);
- release_region(info->dev[0]->base_addr,
- hw[info->priv[0].type].io_size);
+ /* Reset board */
+ if (info->priv[0].type == TYPE_TWIN)
+ outb(0, info->dev[0]->base_addr + TWIN_SERIAL_CFG);
+ write_scc(&info->priv[0], R9, FHWRES);
+ release_region(info->dev[0]->base_addr,
+ hw[info->priv[0].type].io_size);
- for (i = 0; i < 2; i++)
- free_netdev(info->dev[i]);
+ for (i = 0; i < 2; i++)
+ free_netdev(info->dev[i]);
- /* Free memory */
- first = info->next;
- kfree(info);
- }
+ /* Free memory */
+ first = info->next;
+ kfree(info);
+ }
}
#ifndef MODULE
-void __init dmascc_setup(char *str, int *ints) {
- int i;
+void __init dmascc_setup(char *str, int *ints)
+{
+ int i;
- for (i = 0; i < MAX_NUM_DEVS && i < ints[0]; i++)
- io[i] = ints[i+1];
+ for (i = 0; i < MAX_NUM_DEVS && i < ints[0]; i++)
+ io[i] = ints[i + 1];
}
#endif
-static int __init dmascc_init(void) {
- int h, i, j, n;
- int base[MAX_NUM_DEVS], tcmd[MAX_NUM_DEVS], t0[MAX_NUM_DEVS],
- t1[MAX_NUM_DEVS];
- unsigned t_val;
- unsigned long time, start[MAX_NUM_DEVS], delay[MAX_NUM_DEVS],
- counting[MAX_NUM_DEVS];
-
- /* Initialize random number generator */
- rand = jiffies;
- /* Cards found = 0 */
- n = 0;
- /* Warning message */
- if (!io[0]) printk(KERN_INFO "dmascc: autoprobing (dangerous)\n");
-
- /* Run autodetection for each card type */
- for (h = 0; h < NUM_TYPES; h++) {
-
- if (io[0]) {
- /* User-specified I/O address regions */
- for (i = 0; i < hw[h].num_devs; i++) base[i] = 0;
- for (i = 0; i < MAX_NUM_DEVS && io[i]; i++) {
- j = (io[i] - hw[h].io_region) / hw[h].io_delta;
- if (j >= 0 &&
- j < hw[h].num_devs &&
- hw[h].io_region + j * hw[h].io_delta == io[i]) {
- base[j] = io[i];
- }
- }
- } else {
- /* Default I/O address regions */
- for (i = 0; i < hw[h].num_devs; i++) {
- base[i] = hw[h].io_region + i * hw[h].io_delta;
- }
- }
-
- /* Check valid I/O address regions */
- for (i = 0; i < hw[h].num_devs; i++)
- if (base[i]) {
- if (!request_region(base[i], hw[h].io_size, "dmascc"))
- base[i] = 0;
- else {
- tcmd[i] = base[i] + hw[h].tmr_offset + TMR_CTRL;
- t0[i] = base[i] + hw[h].tmr_offset + TMR_CNT0;
- t1[i] = base[i] + hw[h].tmr_offset + TMR_CNT1;
- }
- }
-
- /* Start timers */
- for (i = 0; i < hw[h].num_devs; i++)
- if (base[i]) {
- /* Timer 0: LSB+MSB, Mode 3, TMR_0_HZ */
- outb(0x36, tcmd[i]);
- outb((hw[h].tmr_hz/TMR_0_HZ) & 0xFF, t0[i]);
- outb((hw[h].tmr_hz/TMR_0_HZ) >> 8, t0[i]);
- /* Timer 1: LSB+MSB, Mode 0, HZ/10 */
- outb(0x70, tcmd[i]);
- outb((TMR_0_HZ/HZ*10) & 0xFF, t1[i]);
- outb((TMR_0_HZ/HZ*10) >> 8, t1[i]);
- start[i] = jiffies;
- delay[i] = 0;
- counting[i] = 1;
- /* Timer 2: LSB+MSB, Mode 0 */
- outb(0xb0, tcmd[i]);
- }
- time = jiffies;
- /* Wait until counter registers are loaded */
- udelay(2000000/TMR_0_HZ);
-
- /* Timing loop */
- while (jiffies - time < 13) {
- for (i = 0; i < hw[h].num_devs; i++)
- if (base[i] && counting[i]) {
- /* Read back Timer 1: latch; read LSB; read MSB */
- outb(0x40, tcmd[i]);
- t_val = inb(t1[i]) + (inb(t1[i]) << 8);
- /* Also check whether counter did wrap */
- if (t_val == 0 || t_val > TMR_0_HZ/HZ*10) counting[i] = 0;
- delay[i] = jiffies - start[i];
- }
- }
-
- /* Evaluate measurements */
- for (i = 0; i < hw[h].num_devs; i++)
- if (base[i]) {
- if ((delay[i] >= 9 && delay[i] <= 11)&&
- /* Ok, we have found an adapter */
- (setup_adapter(base[i], h, n) == 0))
- n++;
- else
- release_region(base[i], hw[h].io_size);
- }
-
- } /* NUM_TYPES */
+static int __init dmascc_init(void)
+{
+ int h, i, j, n;
+ int base[MAX_NUM_DEVS], tcmd[MAX_NUM_DEVS], t0[MAX_NUM_DEVS],
+ t1[MAX_NUM_DEVS];
+ unsigned t_val;
+ unsigned long time, start[MAX_NUM_DEVS], delay[MAX_NUM_DEVS],
+ counting[MAX_NUM_DEVS];
+
+ /* Initialize random number generator */
+ rand = jiffies;
+ /* Cards found = 0 */
+ n = 0;
+ /* Warning message */
+ if (!io[0])
+ printk(KERN_INFO "dmascc: autoprobing (dangerous)\n");
+
+ /* Run autodetection for each card type */
+ for (h = 0; h < NUM_TYPES; h++) {
+
+ if (io[0]) {
+ /* User-specified I/O address regions */
+ for (i = 0; i < hw[h].num_devs; i++)
+ base[i] = 0;
+ for (i = 0; i < MAX_NUM_DEVS && io[i]; i++) {
+ j = (io[i] -
+ hw[h].io_region) / hw[h].io_delta;
+ if (j >= 0 && j < hw[h].num_devs
+ && hw[h].io_region +
+ j * hw[h].io_delta == io[i]) {
+ base[j] = io[i];
+ }
+ }
+ } else {
+ /* Default I/O address regions */
+ for (i = 0; i < hw[h].num_devs; i++) {
+ base[i] =
+ hw[h].io_region + i * hw[h].io_delta;
+ }
+ }
- /* If any adapter was successfully initialized, return ok */
- if (n) return 0;
+ /* Check valid I/O address regions */
+ for (i = 0; i < hw[h].num_devs; i++)
+ if (base[i]) {
+ if (!request_region
+ (base[i], hw[h].io_size, "dmascc"))
+ base[i] = 0;
+ else {
+ tcmd[i] =
+ base[i] + hw[h].tmr_offset +
+ TMR_CTRL;
+ t0[i] =
+ base[i] + hw[h].tmr_offset +
+ TMR_CNT0;
+ t1[i] =
+ base[i] + hw[h].tmr_offset +
+ TMR_CNT1;
+ }
+ }
+
+ /* Start timers */
+ for (i = 0; i < hw[h].num_devs; i++)
+ if (base[i]) {
+ /* Timer 0: LSB+MSB, Mode 3, TMR_0_HZ */
+ outb(0x36, tcmd[i]);
+ outb((hw[h].tmr_hz / TMR_0_HZ) & 0xFF,
+ t0[i]);
+ outb((hw[h].tmr_hz / TMR_0_HZ) >> 8,
+ t0[i]);
+ /* Timer 1: LSB+MSB, Mode 0, HZ/10 */
+ outb(0x70, tcmd[i]);
+ outb((TMR_0_HZ / HZ * 10) & 0xFF, t1[i]);
+ outb((TMR_0_HZ / HZ * 10) >> 8, t1[i]);
+ start[i] = jiffies;
+ delay[i] = 0;
+ counting[i] = 1;
+ /* Timer 2: LSB+MSB, Mode 0 */
+ outb(0xb0, tcmd[i]);
+ }
+ time = jiffies;
+ /* Wait until counter registers are loaded */
+ udelay(2000000 / TMR_0_HZ);
+
+ /* Timing loop */
+ while (jiffies - time < 13) {
+ for (i = 0; i < hw[h].num_devs; i++)
+ if (base[i] && counting[i]) {
+ /* Read back Timer 1: latch; read LSB; read MSB */
+ outb(0x40, tcmd[i]);
+ t_val =
+ inb(t1[i]) + (inb(t1[i]) << 8);
+ /* Also check whether counter did wrap */
+ if (t_val == 0
+ || t_val > TMR_0_HZ / HZ * 10)
+ counting[i] = 0;
+ delay[i] = jiffies - start[i];
+ }
+ }
- /* If no adapter found, return error */
- printk(KERN_INFO "dmascc: no adapters found\n");
- return -EIO;
+ /* Evaluate measurements */
+ for (i = 0; i < hw[h].num_devs; i++)
+ if (base[i]) {
+ if ((delay[i] >= 9 && delay[i] <= 11) &&
+ /* Ok, we have found an adapter */
+ (setup_adapter(base[i], h, n) == 0))
+ n++;
+ else
+ release_region(base[i],
+ hw[h].io_size);
+ }
+
+ } /* NUM_TYPES */
+
+ /* If any adapter was successfully initialized, return ok */
+ if (n)
+ return 0;
+
+ /* If no adapter found, return error */
+ printk(KERN_INFO "dmascc: no adapters found\n");
+ return -EIO;
}
module_init(dmascc_init);
@@ -452,8 +473,8 @@ static int __init setup_adapter(int card_base, int type, int n)
info = kmalloc(sizeof(struct scc_info), GFP_KERNEL | GFP_DMA);
if (!info) {
printk(KERN_ERR "dmascc: "
- "could not allocate memory for %s at %#3x\n",
- hw[type].name, card_base);
+ "could not allocate memory for %s at %#3x\n",
+ hw[type].name, card_base);
goto out;
}
@@ -463,16 +484,16 @@ static int __init setup_adapter(int card_base, int type, int n)
info->dev[0] = alloc_netdev(0, "", dev_setup);
if (!info->dev[0]) {
printk(KERN_ERR "dmascc: "
- "could not allocate memory for %s at %#3x\n",
- hw[type].name, card_base);
+ "could not allocate memory for %s at %#3x\n",
+ hw[type].name, card_base);
goto out1;
}
info->dev[1] = alloc_netdev(0, "", dev_setup);
if (!info->dev[1]) {
printk(KERN_ERR "dmascc: "
- "could not allocate memory for %s at %#3x\n",
- hw[type].name, card_base);
+ "could not allocate memory for %s at %#3x\n",
+ hw[type].name, card_base);
goto out2;
}
spin_lock_init(&info->register_lock);
@@ -526,7 +547,8 @@ static int __init setup_adapter(int card_base, int type, int n)
outb(0, tmr_base + TMR_CNT1);
/* Wait and detect IRQ */
- time = jiffies; while (jiffies - time < 2 + HZ / TMR_0_HZ);
+ time = jiffies;
+ while (jiffies - time < 2 + HZ / TMR_0_HZ);
irq = probe_irq_off(irqs);
/* Clear pending interrupt, disable interrupts */
@@ -539,8 +561,9 @@ static int __init setup_adapter(int card_base, int type, int n)
}
if (irq <= 0) {
- printk(KERN_ERR "dmascc: could not find irq of %s at %#3x (irq=%d)\n",
- hw[type].name, card_base, irq);
+ printk(KERN_ERR
+ "dmascc: could not find irq of %s at %#3x (irq=%d)\n",
+ hw[type].name, card_base, irq);
goto out3;
}
@@ -568,7 +591,7 @@ static int __init setup_adapter(int card_base, int type, int n)
priv->param.dma = -1;
INIT_WORK(&priv->rx_work, rx_bh, priv);
dev->priv = priv;
- sprintf(dev->name, "dmascc%i", 2*n+i);
+ sprintf(dev->name, "dmascc%i", 2 * n + i);
SET_MODULE_OWNER(dev);
dev->base_addr = card_base;
dev->irq = irq;
@@ -583,820 +606,888 @@ static int __init setup_adapter(int card_base, int type, int n)
}
if (register_netdev(info->dev[0])) {
printk(KERN_ERR "dmascc: could not register %s\n",
- info->dev[0]->name);
+ info->dev[0]->name);
goto out3;
}
if (register_netdev(info->dev[1])) {
printk(KERN_ERR "dmascc: could not register %s\n",
- info->dev[1]->name);
+ info->dev[1]->name);
goto out4;
}
info->next = first;
first = info;
- printk(KERN_INFO "dmascc: found %s (%s) at %#3x, irq %d\n", hw[type].name,
- chipnames[chip], card_base, irq);
+ printk(KERN_INFO "dmascc: found %s (%s) at %#3x, irq %d\n",
+ hw[type].name, chipnames[chip], card_base, irq);
return 0;
-out4:
+ out4:
unregister_netdev(info->dev[0]);
-out3:
+ out3:
if (info->priv[0].type == TYPE_TWIN)
outb(0, info->dev[0]->base_addr + TWIN_SERIAL_CFG);
write_scc(&info->priv[0], R9, FHWRES);
free_netdev(info->dev[1]);
-out2:
+ out2:
free_netdev(info->dev[0]);
-out1:
+ out1:
kfree(info);
-out:
+ out:
return -1;
}
/* Driver functions */
-static void write_scc(struct scc_priv *priv, int reg, int val) {
- unsigned long flags;
- switch (priv->type) {
- case TYPE_S5:
- if (reg) outb(reg, priv->scc_cmd);
- outb(val, priv->scc_cmd);
- return;
- case TYPE_TWIN:
- if (reg) outb_p(reg, priv->scc_cmd);
- outb_p(val, priv->scc_cmd);
- return;
- default:
- spin_lock_irqsave(priv->register_lock, flags);
- outb_p(0, priv->card_base + PI_DREQ_MASK);
- if (reg) outb_p(reg, priv->scc_cmd);
- outb_p(val, priv->scc_cmd);
- outb(1, priv->card_base + PI_DREQ_MASK);
- spin_unlock_irqrestore(priv->register_lock, flags);
- return;
- }
+static void write_scc(struct scc_priv *priv, int reg, int val)
+{
+ unsigned long flags;
+ switch (priv->type) {
+ case TYPE_S5:
+ if (reg)
+ outb(reg, priv->scc_cmd);
+ outb(val, priv->scc_cmd);
+ return;
+ case TYPE_TWIN:
+ if (reg)
+ outb_p(reg, priv->scc_cmd);
+ outb_p(val, priv->scc_cmd);
+ return;
+ default:
+ spin_lock_irqsave(priv->register_lock, flags);
+ outb_p(0, priv->card_base + PI_DREQ_MASK);
+ if (reg)
+ outb_p(reg, priv->scc_cmd);
+ outb_p(val, priv->scc_cmd);
+ outb(1, priv->card_base + PI_DREQ_MASK);
+ spin_unlock_irqrestore(priv->register_lock, flags);
+ return;
+ }
}
-static void write_scc_data(struct scc_priv *priv, int val, int fast) {
- unsigned long flags;
- switch (priv->type) {
- case TYPE_S5:
- outb(val, priv->scc_data);
- return;
- case TYPE_TWIN:
- outb_p(val, priv->scc_data);
- return;
- default:
- if (fast) outb_p(val, priv->scc_data);
- else {
- spin_lock_irqsave(priv->register_lock, flags);
- outb_p(0, priv->card_base + PI_DREQ_MASK);
- outb_p(val, priv->scc_data);
- outb(1, priv->card_base + PI_DREQ_MASK);
- spin_unlock_irqrestore(priv->register_lock, flags);
- }
- return;
- }
+static void write_scc_data(struct scc_priv *priv, int val, int fast)
+{
+ unsigned long flags;
+ switch (priv->type) {
+ case TYPE_S5:
+ outb(val, priv->scc_data);
+ return;
+ case TYPE_TWIN:
+ outb_p(val, priv->scc_data);
+ return;
+ default:
+ if (fast)
+ outb_p(val, priv->scc_data);
+ else {
+ spin_lock_irqsave(priv->register_lock, flags);
+ outb_p(0, priv->card_base + PI_DREQ_MASK);
+ outb_p(val, priv->scc_data);
+ outb(1, priv->card_base + PI_DREQ_MASK);
+ spin_unlock_irqrestore(priv->register_lock, flags);
+ }
+ return;
+ }
}
-static int read_scc(struct scc_priv *priv, int reg) {
- int rc;
- unsigned long flags;
- switch (priv->type) {
- case TYPE_S5:
- if (reg) outb(reg, priv->scc_cmd);
- return inb(priv->scc_cmd);
- case TYPE_TWIN:
- if (reg) outb_p(reg, priv->scc_cmd);
- return inb_p(priv->scc_cmd);
- default:
- spin_lock_irqsave(priv->register_lock, flags);
- outb_p(0, priv->card_base + PI_DREQ_MASK);
- if (reg) outb_p(reg, priv->scc_cmd);
- rc = inb_p(priv->scc_cmd);
- outb(1, priv->card_base + PI_DREQ_MASK);
- spin_unlock_irqrestore(priv->register_lock, flags);
- return rc;
- }
+static int read_scc(struct scc_priv *priv, int reg)
+{
+ int rc;
+ unsigned long flags;
+ switch (priv->type) {
+ case TYPE_S5:
+ if (reg)
+ outb(reg, priv->scc_cmd);
+ return inb(priv->scc_cmd);
+ case TYPE_TWIN:
+ if (reg)
+ outb_p(reg, priv->scc_cmd);
+ return inb_p(priv->scc_cmd);
+ default:
+ spin_lock_irqsave(priv->register_lock, flags);
+ outb_p(0, priv->card_base + PI_DREQ_MASK);
+ if (reg)
+ outb_p(reg, priv->scc_cmd);
+ rc = inb_p(priv->scc_cmd);
+ outb(1, priv->card_base + PI_DREQ_MASK);
+ spin_unlock_irqrestore(priv->register_lock, flags);
+ return rc;
+ }
}
-static int read_scc_data(struct scc_priv *priv) {
- int rc;
- unsigned long flags;
- switch (priv->type) {
- case TYPE_S5:
- return inb(priv->scc_data);
- case TYPE_TWIN:
- return inb_p(priv->scc_data);
- default:
- spin_lock_irqsave(priv->register_lock, flags);
- outb_p(0, priv->card_base + PI_DREQ_MASK);
- rc = inb_p(priv->scc_data);
- outb(1, priv->card_base + PI_DREQ_MASK);
- spin_unlock_irqrestore(priv->register_lock, flags);
- return rc;
- }
+static int read_scc_data(struct scc_priv *priv)
+{
+ int rc;
+ unsigned long flags;
+ switch (priv->type) {
+ case TYPE_S5:
+ return inb(priv->scc_data);
+ case TYPE_TWIN:
+ return inb_p(priv->scc_data);
+ default:
+ spin_lock_irqsave(priv->register_lock, flags);
+ outb_p(0, priv->card_base + PI_DREQ_MASK);
+ rc = inb_p(priv->scc_data);
+ outb(1, priv->card_base + PI_DREQ_MASK);
+ spin_unlock_irqrestore(priv->register_lock, flags);
+ return rc;
+ }
}
-static int scc_open(struct net_device *dev) {
- struct scc_priv *priv = dev->priv;
- struct scc_info *info = priv->info;
- int card_base = priv->card_base;
-
- /* Request IRQ if not already used by other channel */
- if (!info->irq_used) {
- if (request_irq(dev->irq, scc_isr, 0, "dmascc", info)) {
- return -EAGAIN;
- }
- }
- info->irq_used++;
-
- /* Request DMA if required */
- if (priv->param.dma >= 0) {
- if (request_dma(priv->param.dma, "dmascc")) {
- if (--info->irq_used == 0) free_irq(dev->irq, info);
- return -EAGAIN;
- } else {
- unsigned long flags = claim_dma_lock();
- clear_dma_ff(priv->param.dma);
- release_dma_lock(flags);
- }
- }
-
- /* Initialize local variables */
- priv->rx_ptr = 0;
- priv->rx_over = 0;
- priv->rx_head = priv->rx_tail = priv->rx_count = 0;
- priv->state = IDLE;
- priv->tx_head = priv->tx_tail = priv->tx_count = 0;
- priv->tx_ptr = 0;
-
- /* Reset channel */
- write_scc(priv, R9, (priv->channel ? CHRB : CHRA) | MIE | NV);
- /* X1 clock, SDLC mode */
- write_scc(priv, R4, SDLC | X1CLK);
- /* DMA */
- write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN);
- /* 8 bit RX char, RX disable */
- write_scc(priv, R3, Rx8);
- /* 8 bit TX char, TX disable */
- write_scc(priv, R5, Tx8);
- /* SDLC address field */
- write_scc(priv, R6, 0);
- /* SDLC flag */
- write_scc(priv, R7, FLAG);
- switch (priv->chip) {
- case Z85C30:
- /* Select WR7' */
- write_scc(priv, R15, SHDLCE);
- /* Auto EOM reset */
- write_scc(priv, R7, AUTOEOM);
- write_scc(priv, R15, 0);
- break;
- case Z85230:
- /* Select WR7' */
- write_scc(priv, R15, SHDLCE);
- /* The following bits are set (see 2.5.2.1):
- - Automatic EOM reset
- - Interrupt request if RX FIFO is half full
- This bit should be ignored in DMA mode (according to the
- documentation), but actually isn't. The receiver doesn't work if
- it is set. Thus, we have to clear it in DMA mode.
- - Interrupt/DMA request if TX FIFO is completely empty
- a) If set, the ESCC behaves as if it had no TX FIFO (Z85C30
- compatibility).
- b) If cleared, DMA requests may follow each other very quickly,
- filling up the TX FIFO.
- Advantage: TX works even in case of high bus latency.
- Disadvantage: Edge-triggered DMA request circuitry may miss
- a request. No more data is delivered, resulting
- in a TX FIFO underrun.
- Both PI2 and S5SCC/DMA seem to work fine with TXFIFOE cleared.
- The PackeTwin doesn't. I don't know about the PI, but let's
- assume it behaves like the PI2.
- */
- if (priv->param.dma >= 0) {
- if (priv->type == TYPE_TWIN) write_scc(priv, R7, AUTOEOM | TXFIFOE);
- else write_scc(priv, R7, AUTOEOM);
- } else {
- write_scc(priv, R7, AUTOEOM | RXFIFOH);
- }
- write_scc(priv, R15, 0);
- break;
- }
- /* Preset CRC, NRZ(I) encoding */
- write_scc(priv, R10, CRCPS | (priv->param.nrzi ? NRZI : NRZ));
-
- /* Configure baud rate generator */
- if (priv->param.brg_tc >= 0) {
- /* Program BR generator */
- write_scc(priv, R12, priv->param.brg_tc & 0xFF);
- write_scc(priv, R13, (priv->param.brg_tc>>8) & 0xFF);
- /* BRG source = SYS CLK; enable BRG; DTR REQ function (required by
- PackeTwin, not connected on the PI2); set DPLL source to BRG */
- write_scc(priv, R14, SSBR | DTRREQ | BRSRC | BRENABL);
- /* Enable DPLL */
- write_scc(priv, R14, SEARCH | DTRREQ | BRSRC | BRENABL);
- } else {
- /* Disable BR generator */
- write_scc(priv, R14, DTRREQ | BRSRC);
- }
-
- /* Configure clocks */
- if (priv->type == TYPE_TWIN) {
- /* Disable external TX clock receiver */
- outb((info->twin_serial_cfg &=
- ~(priv->channel ? TWIN_EXTCLKB : TWIN_EXTCLKA)),
- card_base + TWIN_SERIAL_CFG);
- }
- write_scc(priv, R11, priv->param.clocks);
- if ((priv->type == TYPE_TWIN) && !(priv->param.clocks & TRxCOI)) {
- /* Enable external TX clock receiver */
- outb((info->twin_serial_cfg |=
- (priv->channel ? TWIN_EXTCLKB : TWIN_EXTCLKA)),
- card_base + TWIN_SERIAL_CFG);
- }
-
- /* Configure PackeTwin */
- if (priv->type == TYPE_TWIN) {
- /* Assert DTR, enable interrupts */
- outb((info->twin_serial_cfg |= TWIN_EI |
- (priv->channel ? TWIN_DTRB_ON : TWIN_DTRA_ON)),
- card_base + TWIN_SERIAL_CFG);
- }
-
- /* Read current status */
- priv->rr0 = read_scc(priv, R0);
- /* Enable DCD interrupt */
- write_scc(priv, R15, DCDIE);
-
- netif_start_queue(dev);
-
- return 0;
-}
+static int scc_open(struct net_device *dev)
+{
+ struct scc_priv *priv = dev->priv;
+ struct scc_info *info = priv->info;
+ int card_base = priv->card_base;
+
+ /* Request IRQ if not already used by other channel */
+ if (!info->irq_used) {
+ if (request_irq(dev->irq, scc_isr, 0, "dmascc", info)) {
+ return -EAGAIN;
+ }
+ }
+ info->irq_used++;
+
+ /* Request DMA if required */
+ if (priv->param.dma >= 0) {
+ if (request_dma(priv->param.dma, "dmascc")) {
+ if (--info->irq_used == 0)
+ free_irq(dev->irq, info);
+ return -EAGAIN;
+ } else {
+ unsigned long flags = claim_dma_lock();
+ clear_dma_ff(priv->param.dma);
+ release_dma_lock(flags);
+ }
+ }
+ /* Initialize local variables */
+ priv->rx_ptr = 0;
+ priv->rx_over = 0;
+ priv->rx_head = priv->rx_tail = priv->rx_count = 0;
+ priv->state = IDLE;
+ priv->tx_head = priv->tx_tail = priv->tx_count = 0;
+ priv->tx_ptr = 0;
+
+ /* Reset channel */
+ write_scc(priv, R9, (priv->channel ? CHRB : CHRA) | MIE | NV);
+ /* X1 clock, SDLC mode */
+ write_scc(priv, R4, SDLC | X1CLK);
+ /* DMA */
+ write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN);
+ /* 8 bit RX char, RX disable */
+ write_scc(priv, R3, Rx8);
+ /* 8 bit TX char, TX disable */
+ write_scc(priv, R5, Tx8);
+ /* SDLC address field */
+ write_scc(priv, R6, 0);
+ /* SDLC flag */
+ write_scc(priv, R7, FLAG);
+ switch (priv->chip) {
+ case Z85C30:
+ /* Select WR7' */
+ write_scc(priv, R15, SHDLCE);
+ /* Auto EOM reset */
+ write_scc(priv, R7, AUTOEOM);
+ write_scc(priv, R15, 0);
+ break;
+ case Z85230:
+ /* Select WR7' */
+ write_scc(priv, R15, SHDLCE);
+ /* The following bits are set (see 2.5.2.1):
+ - Automatic EOM reset
+ - Interrupt request if RX FIFO is half full
+ This bit should be ignored in DMA mode (according to the
+ documentation), but actually isn't. The receiver doesn't work if
+ it is set. Thus, we have to clear it in DMA mode.
+ - Interrupt/DMA request if TX FIFO is completely empty
+ a) If set, the ESCC behaves as if it had no TX FIFO (Z85C30
+ compatibility).
+ b) If cleared, DMA requests may follow each other very quickly,
+ filling up the TX FIFO.
+ Advantage: TX works even in case of high bus latency.
+ Disadvantage: Edge-triggered DMA request circuitry may miss
+ a request. No more data is delivered, resulting
+ in a TX FIFO underrun.
+ Both PI2 and S5SCC/DMA seem to work fine with TXFIFOE cleared.
+ The PackeTwin doesn't. I don't know about the PI, but let's
+ assume it behaves like the PI2.
+ */
+ if (priv->param.dma >= 0) {
+ if (priv->type == TYPE_TWIN)
+ write_scc(priv, R7, AUTOEOM | TXFIFOE);
+ else
+ write_scc(priv, R7, AUTOEOM);
+ } else {
+ write_scc(priv, R7, AUTOEOM | RXFIFOH);
+ }
+ write_scc(priv, R15, 0);
+ break;
+ }
+ /* Preset CRC, NRZ(I) encoding */
+ write_scc(priv, R10, CRCPS | (priv->param.nrzi ? NRZI : NRZ));
+
+ /* Configure baud rate generator */
+ if (priv->param.brg_tc >= 0) {
+ /* Program BR generator */
+ write_scc(priv, R12, priv->param.brg_tc & 0xFF);
+ write_scc(priv, R13, (priv->param.brg_tc >> 8) & 0xFF);
+ /* BRG source = SYS CLK; enable BRG; DTR REQ function (required by
+ PackeTwin, not connected on the PI2); set DPLL source to BRG */
+ write_scc(priv, R14, SSBR | DTRREQ | BRSRC | BRENABL);
+ /* Enable DPLL */
+ write_scc(priv, R14, SEARCH | DTRREQ | BRSRC | BRENABL);
+ } else {
+ /* Disable BR generator */
+ write_scc(priv, R14, DTRREQ | BRSRC);
+ }
-static int scc_close(struct net_device *dev) {
- struct scc_priv *priv = dev->priv;
- struct scc_info *info = priv->info;
- int card_base = priv->card_base;
+ /* Configure clocks */
+ if (priv->type == TYPE_TWIN) {
+ /* Disable external TX clock receiver */
+ outb((info->twin_serial_cfg &=
+ ~(priv->channel ? TWIN_EXTCLKB : TWIN_EXTCLKA)),
+ card_base + TWIN_SERIAL_CFG);
+ }
+ write_scc(priv, R11, priv->param.clocks);
+ if ((priv->type == TYPE_TWIN) && !(priv->param.clocks & TRxCOI)) {
+ /* Enable external TX clock receiver */
+ outb((info->twin_serial_cfg |=
+ (priv->channel ? TWIN_EXTCLKB : TWIN_EXTCLKA)),
+ card_base + TWIN_SERIAL_CFG);
+ }
- netif_stop_queue(dev);
+ /* Configure PackeTwin */
+ if (priv->type == TYPE_TWIN) {
+ /* Assert DTR, enable interrupts */
+ outb((info->twin_serial_cfg |= TWIN_EI |
+ (priv->channel ? TWIN_DTRB_ON : TWIN_DTRA_ON)),
+ card_base + TWIN_SERIAL_CFG);
+ }
- if (priv->type == TYPE_TWIN) {
- /* Drop DTR */
- outb((info->twin_serial_cfg &=
- (priv->channel ? ~TWIN_DTRB_ON : ~TWIN_DTRA_ON)),
- card_base + TWIN_SERIAL_CFG);
- }
+ /* Read current status */
+ priv->rr0 = read_scc(priv, R0);
+ /* Enable DCD interrupt */
+ write_scc(priv, R15, DCDIE);
- /* Reset channel, free DMA and IRQ */
- write_scc(priv, R9, (priv->channel ? CHRB : CHRA) | MIE | NV);
- if (priv->param.dma >= 0) {
- if (priv->type == TYPE_TWIN) outb(0, card_base + TWIN_DMA_CFG);
- free_dma(priv->param.dma);
- }
- if (--info->irq_used == 0) free_irq(dev->irq, info);
+ netif_start_queue(dev);
- return 0;
+ return 0;
}
-static int scc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) {
- struct scc_priv *priv = dev->priv;
-
- switch (cmd) {
- case SIOCGSCCPARAM:
- if (copy_to_user(ifr->ifr_data, &priv->param, sizeof(struct scc_param)))
- return -EFAULT;
- return 0;
- case SIOCSSCCPARAM:
- if (!capable(CAP_NET_ADMIN)) return -EPERM;
- if (netif_running(dev)) return -EAGAIN;
- if (copy_from_user(&priv->param, ifr->ifr_data, sizeof(struct scc_param)))
- return -EFAULT;
- return 0;
- default:
- return -EINVAL;
- }
-}
+static int scc_close(struct net_device *dev)
+{
+ struct scc_priv *priv = dev->priv;
+ struct scc_info *info = priv->info;
+ int card_base = priv->card_base;
+ netif_stop_queue(dev);
-static int scc_send_packet(struct sk_buff *skb, struct net_device *dev) {
- struct scc_priv *priv = dev->priv;
- unsigned long flags;
- int i;
+ if (priv->type == TYPE_TWIN) {
+ /* Drop DTR */
+ outb((info->twin_serial_cfg &=
+ (priv->channel ? ~TWIN_DTRB_ON : ~TWIN_DTRA_ON)),
+ card_base + TWIN_SERIAL_CFG);
+ }
- /* Temporarily stop the scheduler feeding us packets */
- netif_stop_queue(dev);
+ /* Reset channel, free DMA and IRQ */
+ write_scc(priv, R9, (priv->channel ? CHRB : CHRA) | MIE | NV);
+ if (priv->param.dma >= 0) {
+ if (priv->type == TYPE_TWIN)
+ outb(0, card_base + TWIN_DMA_CFG);
+ free_dma(priv->param.dma);
+ }
+ if (--info->irq_used == 0)
+ free_irq(dev->irq, info);
- /* Transfer data to DMA buffer */
- i = priv->tx_head;
- memcpy(priv->tx_buf[i], skb->data+1, skb->len-1);
- priv->tx_len[i] = skb->len-1;
+ return 0;
+}
- /* Clear interrupts while we touch our circular buffers */
- spin_lock_irqsave(&priv->ring_lock, flags);
- /* Move the ring buffer's head */
- priv->tx_head = (i + 1) % NUM_TX_BUF;
- priv->tx_count++;
+static int scc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+ struct scc_priv *priv = dev->priv;
+
+ switch (cmd) {
+ case SIOCGSCCPARAM:
+ if (copy_to_user
+ (ifr->ifr_data, &priv->param,
+ sizeof(struct scc_param)))
+ return -EFAULT;
+ return 0;
+ case SIOCSSCCPARAM:
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+ if (netif_running(dev))
+ return -EAGAIN;
+ if (copy_from_user
+ (&priv->param, ifr->ifr_data,
+ sizeof(struct scc_param)))
+ return -EFAULT;
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
- /* If we just filled up the last buffer, leave queue stopped.
- The higher layers must wait until we have a DMA buffer
- to accept the data. */
- if (priv->tx_count < NUM_TX_BUF) netif_wake_queue(dev);
- /* Set new TX state */
- if (priv->state == IDLE) {
- /* Assert RTS, start timer */
- priv->state = TX_HEAD;
- priv->tx_start = jiffies;
- write_scc(priv, R5, TxCRC_ENAB | RTS | TxENAB | Tx8);
- write_scc(priv, R15, 0);
- start_timer(priv, priv->param.txdelay, 0);
- }
+static int scc_send_packet(struct sk_buff *skb, struct net_device *dev)
+{
+ struct scc_priv *priv = dev->priv;
+ unsigned long flags;
+ int i;
+
+ /* Temporarily stop the scheduler feeding us packets */
+ netif_stop_queue(dev);
+
+ /* Transfer data to DMA buffer */
+ i = priv->tx_head;
+ memcpy(priv->tx_buf[i], skb->data + 1, skb->len - 1);
+ priv->tx_len[i] = skb->len - 1;
+
+ /* Clear interrupts while we touch our circular buffers */
+
+ spin_lock_irqsave(&priv->ring_lock, flags);
+ /* Move the ring buffer's head */
+ priv->tx_head = (i + 1) % NUM_TX_BUF;
+ priv->tx_count++;
+
+ /* If we just filled up the last buffer, leave queue stopped.
+ The higher layers must wait until we have a DMA buffer
+ to accept the data. */
+ if (priv->tx_count < NUM_TX_BUF)
+ netif_wake_queue(dev);
+
+ /* Set new TX state */
+ if (priv->state == IDLE) {
+ /* Assert RTS, start timer */
+ priv->state = TX_HEAD;
+ priv->tx_start = jiffies;
+ write_scc(priv, R5, TxCRC_ENAB | RTS | TxENAB | Tx8);
+ write_scc(priv, R15, 0);
+ start_timer(priv, priv->param.txdelay, 0);
+ }
- /* Turn interrupts back on and free buffer */
- spin_unlock_irqrestore(&priv->ring_lock, flags);
- dev_kfree_skb(skb);
+ /* Turn interrupts back on and free buffer */
+ spin_unlock_irqrestore(&priv->ring_lock, flags);
+ dev_kfree_skb(skb);
- return 0;
+ return 0;
}
-static struct net_device_stats *scc_get_stats(struct net_device *dev) {
- struct scc_priv *priv = dev->priv;
+static struct net_device_stats *scc_get_stats(struct net_device *dev)
+{
+ struct scc_priv *priv = dev->priv;
- return &priv->stats;
+ return &priv->stats;
}
-static int scc_set_mac_address(struct net_device *dev, void *sa) {
- memcpy(dev->dev_addr, ((struct sockaddr *)sa)->sa_data, dev->addr_len);
- return 0;
+static int scc_set_mac_address(struct net_device *dev, void *sa)
+{
+ memcpy(dev->dev_addr, ((struct sockaddr *) sa)->sa_data,
+ dev->addr_len);
+ return 0;
}
-static inline void tx_on(struct scc_priv *priv) {
- int i, n;
- unsigned long flags;
-
- if (priv->param.dma >= 0) {
- n = (priv->chip == Z85230) ? 3 : 1;
- /* Program DMA controller */
- flags = claim_dma_lock();
- set_dma_mode(priv->param.dma, DMA_MODE_WRITE);
- set_dma_addr(priv->param.dma, (int) priv->tx_buf[priv->tx_tail]+n);
- set_dma_count(priv->param.dma, priv->tx_len[priv->tx_tail]-n);
- release_dma_lock(flags);
- /* Enable TX underrun interrupt */
- write_scc(priv, R15, TxUIE);
- /* Configure DREQ */
- if (priv->type == TYPE_TWIN)
- outb((priv->param.dma == 1) ? TWIN_DMA_HDX_T1 : TWIN_DMA_HDX_T3,
- priv->card_base + TWIN_DMA_CFG);
- else
- write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN | WT_RDY_ENAB);
- /* Write first byte(s) */
- spin_lock_irqsave(priv->register_lock, flags);
- for (i = 0; i < n; i++)
- write_scc_data(priv, priv->tx_buf[priv->tx_tail][i], 1);
- enable_dma(priv->param.dma);
- spin_unlock_irqrestore(priv->register_lock, flags);
- } else {
- write_scc(priv, R15, TxUIE);
- write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN | TxINT_ENAB);
- tx_isr(priv);
- }
- /* Reset EOM latch if we do not have the AUTOEOM feature */
- if (priv->chip == Z8530) write_scc(priv, R0, RES_EOM_L);
+static inline void tx_on(struct scc_priv *priv)
+{
+ int i, n;
+ unsigned long flags;
+
+ if (priv->param.dma >= 0) {
+ n = (priv->chip == Z85230) ? 3 : 1;
+ /* Program DMA controller */
+ flags = claim_dma_lock();
+ set_dma_mode(priv->param.dma, DMA_MODE_WRITE);
+ set_dma_addr(priv->param.dma,
+ (int) priv->tx_buf[priv->tx_tail] + n);
+ set_dma_count(priv->param.dma,
+ priv->tx_len[priv->tx_tail] - n);
+ release_dma_lock(flags);
+ /* Enable TX underrun interrupt */
+ write_scc(priv, R15, TxUIE);
+ /* Configure DREQ */
+ if (priv->type == TYPE_TWIN)
+ outb((priv->param.dma ==
+ 1) ? TWIN_DMA_HDX_T1 : TWIN_DMA_HDX_T3,
+ priv->card_base + TWIN_DMA_CFG);
+ else
+ write_scc(priv, R1,
+ EXT_INT_ENAB | WT_FN_RDYFN |
+ WT_RDY_ENAB);
+ /* Write first byte(s) */
+ spin_lock_irqsave(priv->register_lock, flags);
+ for (i = 0; i < n; i++)
+ write_scc_data(priv,
+ priv->tx_buf[priv->tx_tail][i], 1);
+ enable_dma(priv->param.dma);
+ spin_unlock_irqrestore(priv->register_lock, flags);
+ } else {
+ write_scc(priv, R15, TxUIE);
+ write_scc(priv, R1,
+ EXT_INT_ENAB | WT_FN_RDYFN | TxINT_ENAB);
+ tx_isr(priv);
+ }
+ /* Reset EOM latch if we do not have the AUTOEOM feature */
+ if (priv->chip == Z8530)
+ write_scc(priv, R0, RES_EOM_L);
}
-static inline void rx_on(struct scc_priv *priv) {
- unsigned long flags;
-
- /* Clear RX FIFO */
- while (read_scc(priv, R0) & Rx_CH_AV) read_scc_data(priv);
- priv->rx_over = 0;
- if (priv->param.dma >= 0) {
- /* Program DMA controller */
- flags = claim_dma_lock();
- set_dma_mode(priv->param.dma, DMA_MODE_READ);
- set_dma_addr(priv->param.dma, (int) priv->rx_buf[priv->rx_head]);
- set_dma_count(priv->param.dma, BUF_SIZE);
- release_dma_lock(flags);
- enable_dma(priv->param.dma);
- /* Configure PackeTwin DMA */
- if (priv->type == TYPE_TWIN) {
- outb((priv->param.dma == 1) ? TWIN_DMA_HDX_R1 : TWIN_DMA_HDX_R3,
- priv->card_base + TWIN_DMA_CFG);
- }
- /* Sp. cond. intr. only, ext int enable, RX DMA enable */
- write_scc(priv, R1, EXT_INT_ENAB | INT_ERR_Rx |
- WT_RDY_RT | WT_FN_RDYFN | WT_RDY_ENAB);
- } else {
- /* Reset current frame */
- priv->rx_ptr = 0;
- /* Intr. on all Rx characters and Sp. cond., ext int enable */
- write_scc(priv, R1, EXT_INT_ENAB | INT_ALL_Rx | WT_RDY_RT |
- WT_FN_RDYFN);
- }
- write_scc(priv, R0, ERR_RES);
- write_scc(priv, R3, RxENABLE | Rx8 | RxCRC_ENAB);
+static inline void rx_on(struct scc_priv *priv)
+{
+ unsigned long flags;
+
+ /* Clear RX FIFO */
+ while (read_scc(priv, R0) & Rx_CH_AV)
+ read_scc_data(priv);
+ priv->rx_over = 0;
+ if (priv->param.dma >= 0) {
+ /* Program DMA controller */
+ flags = claim_dma_lock();
+ set_dma_mode(priv->param.dma, DMA_MODE_READ);
+ set_dma_addr(priv->param.dma,
+ (int) priv->rx_buf[priv->rx_head]);
+ set_dma_count(priv->param.dma, BUF_SIZE);
+ release_dma_lock(flags);
+ enable_dma(priv->param.dma);
+ /* Configure PackeTwin DMA */
+ if (priv->type == TYPE_TWIN) {
+ outb((priv->param.dma ==
+ 1) ? TWIN_DMA_HDX_R1 : TWIN_DMA_HDX_R3,
+ priv->card_base + TWIN_DMA_CFG);
+ }
+ /* Sp. cond. intr. only, ext int enable, RX DMA enable */
+ write_scc(priv, R1, EXT_INT_ENAB | INT_ERR_Rx |
+ WT_RDY_RT | WT_FN_RDYFN | WT_RDY_ENAB);
+ } else {
+ /* Reset current frame */
+ priv->rx_ptr = 0;
+ /* Intr. on all Rx characters and Sp. cond., ext int enable */
+ write_scc(priv, R1, EXT_INT_ENAB | INT_ALL_Rx | WT_RDY_RT |
+ WT_FN_RDYFN);
+ }
+ write_scc(priv, R0, ERR_RES);
+ write_scc(priv, R3, RxENABLE | Rx8 | RxCRC_ENAB);
}
-static inline void rx_off(struct scc_priv *priv) {
- /* Disable receiver */
- write_scc(priv, R3, Rx8);
- /* Disable DREQ / RX interrupt */
- if (priv->param.dma >= 0 && priv->type == TYPE_TWIN)
- outb(0, priv->card_base + TWIN_DMA_CFG);
- else
- write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN);
- /* Disable DMA */
- if (priv->param.dma >= 0) disable_dma(priv->param.dma);
+static inline void rx_off(struct scc_priv *priv)
+{
+ /* Disable receiver */
+ write_scc(priv, R3, Rx8);
+ /* Disable DREQ / RX interrupt */
+ if (priv->param.dma >= 0 && priv->type == TYPE_TWIN)
+ outb(0, priv->card_base + TWIN_DMA_CFG);
+ else
+ write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN);
+ /* Disable DMA */
+ if (priv->param.dma >= 0)
+ disable_dma(priv->param.dma);
}
-static void start_timer(struct scc_priv *priv, int t, int r15) {
- unsigned long flags;
-
- outb(priv->tmr_mode, priv->tmr_ctrl);
- if (t == 0) {
- tm_isr(priv);
- } else if (t > 0) {
- save_flags(flags);
- cli();
- outb(t & 0xFF, priv->tmr_cnt);
- outb((t >> 8) & 0xFF, priv->tmr_cnt);
- if (priv->type != TYPE_TWIN) {
- write_scc(priv, R15, r15 | CTSIE);
- priv->rr0 |= CTS;
- }
- restore_flags(flags);
- }
+static void start_timer(struct scc_priv *priv, int t, int r15)
+{
+ unsigned long flags;
+
+ outb(priv->tmr_mode, priv->tmr_ctrl);
+ if (t == 0) {
+ tm_isr(priv);
+ } else if (t > 0) {
+ save_flags(flags);
+ cli();
+ outb(t & 0xFF, priv->tmr_cnt);
+ outb((t >> 8) & 0xFF, priv->tmr_cnt);
+ if (priv->type != TYPE_TWIN) {
+ write_scc(priv, R15, r15 | CTSIE);
+ priv->rr0 |= CTS;
+ }
+ restore_flags(flags);
+ }
}
-static inline unsigned char random(void) {
- /* See "Numerical Recipes in C", second edition, p. 284 */
- rand = rand * 1664525L + 1013904223L;
- return (unsigned char) (rand >> 24);
+static inline unsigned char random(void)
+{
+ /* See "Numerical Recipes in C", second edition, p. 284 */
+ rand = rand * 1664525L + 1013904223L;
+ return (unsigned char) (rand >> 24);
}
-static inline void z8530_isr(struct scc_info *info) {
- int is, i = 100;
-
- while ((is = read_scc(&info->priv[0], R3)) && i--) {
- if (is & CHARxIP) {
- rx_isr(&info->priv[0]);
- } else if (is & CHATxIP) {
- tx_isr(&info->priv[0]);
- } else if (is & CHAEXT) {
- es_isr(&info->priv[0]);
- } else if (is & CHBRxIP) {
- rx_isr(&info->priv[1]);
- } else if (is & CHBTxIP) {
- tx_isr(&info->priv[1]);
- } else {
- es_isr(&info->priv[1]);
- }
- write_scc(&info->priv[0], R0, RES_H_IUS);
- i++;
- }
- if (i < 0) {
- printk(KERN_ERR "dmascc: stuck in ISR with RR3=0x%02x.\n", is);
- }
- /* Ok, no interrupts pending from this 8530. The INT line should
- be inactive now. */
+static inline void z8530_isr(struct scc_info *info)
+{
+ int is, i = 100;
+
+ while ((is = read_scc(&info->priv[0], R3)) && i--) {
+ if (is & CHARxIP) {
+ rx_isr(&info->priv[0]);
+ } else if (is & CHATxIP) {
+ tx_isr(&info->priv[0]);
+ } else if (is & CHAEXT) {
+ es_isr(&info->priv[0]);
+ } else if (is & CHBRxIP) {
+ rx_isr(&info->priv[1]);
+ } else if (is & CHBTxIP) {
+ tx_isr(&info->priv[1]);
+ } else {
+ es_isr(&info->priv[1]);
+ }
+ write_scc(&info->priv[0], R0, RES_H_IUS);
+ i++;
+ }
+ if (i < 0) {
+ printk(KERN_ERR "dmascc: stuck in ISR with RR3=0x%02x.\n",
+ is);
+ }
+ /* Ok, no interrupts pending from this 8530. The INT line should
+ be inactive now. */
}
-static irqreturn_t scc_isr(int irq, void *dev_id, struct pt_regs * regs) {
- struct scc_info *info = dev_id;
-
- spin_lock(info->priv[0].register_lock);
- /* At this point interrupts are enabled, and the interrupt under service
- is already acknowledged, but masked off.
-
- Interrupt processing: We loop until we know that the IRQ line is
- low. If another positive edge occurs afterwards during the ISR,
- another interrupt will be triggered by the interrupt controller
- as soon as the IRQ level is enabled again (see asm/irq.h).
-
- Bottom-half handlers will be processed after scc_isr(). This is
- important, since we only have small ringbuffers and want new data
- to be fetched/delivered immediately. */
-
- if (info->priv[0].type == TYPE_TWIN) {
- int is, card_base = info->priv[0].card_base;
- while ((is = ~inb(card_base + TWIN_INT_REG)) &
- TWIN_INT_MSK) {
- if (is & TWIN_SCC_MSK) {
- z8530_isr(info);
- } else if (is & TWIN_TMR1_MSK) {
- inb(card_base + TWIN_CLR_TMR1);
- tm_isr(&info->priv[0]);
- } else {
- inb(card_base + TWIN_CLR_TMR2);
- tm_isr(&info->priv[1]);
- }
- }
- } else z8530_isr(info);
- spin_unlock(info->priv[0].register_lock);
- return IRQ_HANDLED;
+static irqreturn_t scc_isr(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct scc_info *info = dev_id;
+
+ spin_lock(info->priv[0].register_lock);
+ /* At this point interrupts are enabled, and the interrupt under service
+ is already acknowledged, but masked off.
+
+ Interrupt processing: We loop until we know that the IRQ line is
+ low. If another positive edge occurs afterwards during the ISR,
+ another interrupt will be triggered by the interrupt controller
+ as soon as the IRQ level is enabled again (see asm/irq.h).
+
+ Bottom-half handlers will be processed after scc_isr(). This is
+ important, since we only have small ringbuffers and want new data
+ to be fetched/delivered immediately. */
+
+ if (info->priv[0].type == TYPE_TWIN) {
+ int is, card_base = info->priv[0].card_base;
+ while ((is = ~inb(card_base + TWIN_INT_REG)) &
+ TWIN_INT_MSK) {
+ if (is & TWIN_SCC_MSK) {
+ z8530_isr(info);
+ } else if (is & TWIN_TMR1_MSK) {
+ inb(card_base + TWIN_CLR_TMR1);
+ tm_isr(&info->priv[0]);
+ } else {
+ inb(card_base + TWIN_CLR_TMR2);
+ tm_isr(&info->priv[1]);
+ }
+ }
+ } else
+ z8530_isr(info);
+ spin_unlock(info->priv[0].register_lock);
+ return IRQ_HANDLED;
}
-static void rx_isr(struct scc_priv *priv) {
- if (priv->param.dma >= 0) {
- /* Check special condition and perform error reset. See 2.4.7.5. */
- special_condition(priv, read_scc(priv, R1));
- write_scc(priv, R0, ERR_RES);
- } else {
- /* Check special condition for each character. Error reset not necessary.
- Same algorithm for SCC and ESCC. See 2.4.7.1 and 2.4.7.4. */
- int rc;
- while (read_scc(priv, R0) & Rx_CH_AV) {
- rc = read_scc(priv, R1);
- if (priv->rx_ptr < BUF_SIZE)
- priv->rx_buf[priv->rx_head][priv->rx_ptr++] =
- read_scc_data(priv);
- else {
- priv->rx_over = 2;
- read_scc_data(priv);
- }
- special_condition(priv, rc);
- }
- }
+static void rx_isr(struct scc_priv *priv)
+{
+ if (priv->param.dma >= 0) {
+ /* Check special condition and perform error reset. See 2.4.7.5. */
+ special_condition(priv, read_scc(priv, R1));
+ write_scc(priv, R0, ERR_RES);
+ } else {
+ /* Check special condition for each character. Error reset not necessary.
+ Same algorithm for SCC and ESCC. See 2.4.7.1 and 2.4.7.4. */
+ int rc;
+ while (read_scc(priv, R0) & Rx_CH_AV) {
+ rc = read_scc(priv, R1);
+ if (priv->rx_ptr < BUF_SIZE)
+ priv->rx_buf[priv->rx_head][priv->
+ rx_ptr++] =
+ read_scc_data(priv);
+ else {
+ priv->rx_over = 2;
+ read_scc_data(priv);
+ }
+ special_condition(priv, rc);
+ }
+ }
}
-static void special_condition(struct scc_priv *priv, int rc) {
- int cb;
- unsigned long flags;
-
- /* See Figure 2-15. Only overrun and EOF need to be checked. */
-
- if (rc & Rx_OVR) {
- /* Receiver overrun */
- priv->rx_over = 1;
- if (priv->param.dma < 0) write_scc(priv, R0, ERR_RES);
- } else if (rc & END_FR) {
- /* End of frame. Get byte count */
- if (priv->param.dma >= 0) {
- flags = claim_dma_lock();
- cb = BUF_SIZE - get_dma_residue(priv->param.dma) - 2;
- release_dma_lock(flags);
- } else {
- cb = priv->rx_ptr - 2;
- }
- if (priv->rx_over) {
- /* We had an overrun */
- priv->stats.rx_errors++;
- if (priv->rx_over == 2) priv->stats.rx_length_errors++;
- else priv->stats.rx_fifo_errors++;
- priv->rx_over = 0;
- } else if (rc & CRC_ERR) {
- /* Count invalid CRC only if packet length >= minimum */
- if (cb >= 15) {
- priv->stats.rx_errors++;
- priv->stats.rx_crc_errors++;
- }
- } else {
- if (cb >= 15) {
- if (priv->rx_count < NUM_RX_BUF - 1) {
- /* Put good frame in FIFO */
- priv->rx_len[priv->rx_head] = cb;
- priv->rx_head = (priv->rx_head + 1) % NUM_RX_BUF;
- priv->rx_count++;
- schedule_work(&priv->rx_work);
- } else {
- priv->stats.rx_errors++;
- priv->stats.rx_over_errors++;
+static void special_condition(struct scc_priv *priv, int rc)
+{
+ int cb;
+ unsigned long flags;
+
+ /* See Figure 2-15. Only overrun and EOF need to be checked. */
+
+ if (rc & Rx_OVR) {
+ /* Receiver overrun */
+ priv->rx_over = 1;
+ if (priv->param.dma < 0)
+ write_scc(priv, R0, ERR_RES);
+ } else if (rc & END_FR) {
+ /* End of frame. Get byte count */
+ if (priv->param.dma >= 0) {
+ flags = claim_dma_lock();
+ cb = BUF_SIZE - get_dma_residue(priv->param.dma) -
+ 2;
+ release_dma_lock(flags);
+ } else {
+ cb = priv->rx_ptr - 2;
+ }
+ if (priv->rx_over) {
+ /* We had an overrun */
+ priv->stats.rx_errors++;
+ if (priv->rx_over == 2)
+ priv->stats.rx_length_errors++;
+ else
+ priv->stats.rx_fifo_errors++;
+ priv->rx_over = 0;
+ } else if (rc & CRC_ERR) {
+ /* Count invalid CRC only if packet length >= minimum */
+ if (cb >= 15) {
+ priv->stats.rx_errors++;
+ priv->stats.rx_crc_errors++;
+ }
+ } else {
+ if (cb >= 15) {
+ if (priv->rx_count < NUM_RX_BUF - 1) {
+ /* Put good frame in FIFO */
+ priv->rx_len[priv->rx_head] = cb;
+ priv->rx_head =
+ (priv->rx_head +
+ 1) % NUM_RX_BUF;
+ priv->rx_count++;
+ schedule_work(&priv->rx_work);
+ } else {
+ priv->stats.rx_errors++;
+ priv->stats.rx_over_errors++;
+ }
+ }
+ }
+ /* Get ready for new frame */
+ if (priv->param.dma >= 0) {
+ flags = claim_dma_lock();
+ set_dma_addr(priv->param.dma,
+ (int) priv->rx_buf[priv->rx_head]);
+ set_dma_count(priv->param.dma, BUF_SIZE);
+ release_dma_lock(flags);
+ } else {
+ priv->rx_ptr = 0;
+ }
}
- }
- }
- /* Get ready for new frame */
- if (priv->param.dma >= 0) {
- flags = claim_dma_lock();
- set_dma_addr(priv->param.dma, (int) priv->rx_buf[priv->rx_head]);
- set_dma_count(priv->param.dma, BUF_SIZE);
- release_dma_lock(flags);
- } else {
- priv->rx_ptr = 0;
- }
- }
}
-static void rx_bh(void *arg) {
- struct scc_priv *priv = arg;
- int i = priv->rx_tail;
- int cb;
- unsigned long flags;
- struct sk_buff *skb;
- unsigned char *data;
-
- spin_lock_irqsave(&priv->ring_lock, flags);
- while (priv->rx_count) {
- spin_unlock_irqrestore(&priv->ring_lock, flags);
- cb = priv->rx_len[i];
- /* Allocate buffer */
- skb = dev_alloc_skb(cb+1);
- if (skb == NULL) {
- /* Drop packet */
- priv->stats.rx_dropped++;
- } else {
- /* Fill buffer */
- data = skb_put(skb, cb+1);
- data[0] = 0;
- memcpy(&data[1], priv->rx_buf[i], cb);
- skb->dev = priv->dev;
- skb->protocol = ntohs(ETH_P_AX25);
- skb->mac.raw = skb->data;
- netif_rx(skb);
- priv->dev->last_rx = jiffies;
- priv->stats.rx_packets++;
- priv->stats.rx_bytes += cb;
- }
- spin_lock_irqsave(&priv->ring_lock, flags);
- /* Move tail */
- priv->rx_tail = i = (i + 1) % NUM_RX_BUF;
- priv->rx_count--;
- }
- spin_unlock_irqrestore(&priv->ring_lock, flags);
+static void rx_bh(void *arg)
+{
+ struct scc_priv *priv = arg;
+ int i = priv->rx_tail;
+ int cb;
+ unsigned long flags;
+ struct sk_buff *skb;
+ unsigned char *data;
+
+ spin_lock_irqsave(&priv->ring_lock, flags);
+ while (priv->rx_count) {
+ spin_unlock_irqrestore(&priv->ring_lock, flags);
+ cb = priv->rx_len[i];
+ /* Allocate buffer */
+ skb = dev_alloc_skb(cb + 1);
+ if (skb == NULL) {
+ /* Drop packet */
+ priv->stats.rx_dropped++;
+ } else {
+ /* Fill buffer */
+ data = skb_put(skb, cb + 1);
+ data[0] = 0;
+ memcpy(&data[1], priv->rx_buf[i], cb);
+ skb->dev = priv->dev;
+ skb->protocol = ntohs(ETH_P_AX25);
+ skb->mac.raw = skb->data;
+ netif_rx(skb);
+ priv->dev->last_rx = jiffies;
+ priv->stats.rx_packets++;
+ priv->stats.rx_bytes += cb;
+ }
+ spin_lock_irqsave(&priv->ring_lock, flags);
+ /* Move tail */
+ priv->rx_tail = i = (i + 1) % NUM_RX_BUF;
+ priv->rx_count--;
+ }
+ spin_unlock_irqrestore(&priv->ring_lock, flags);
}
-static void tx_isr(struct scc_priv *priv) {
- int i = priv->tx_tail, p = priv->tx_ptr;
+static void tx_isr(struct scc_priv *priv)
+{
+ int i = priv->tx_tail, p = priv->tx_ptr;
- /* Suspend TX interrupts if we don't want to send anything.
- See Figure 2-22. */
- if (p == priv->tx_len[i]) {
- write_scc(priv, R0, RES_Tx_P);
- return;
- }
+ /* Suspend TX interrupts if we don't want to send anything.
+ See Figure 2-22. */
+ if (p == priv->tx_len[i]) {
+ write_scc(priv, R0, RES_Tx_P);
+ return;
+ }
- /* Write characters */
- while ((read_scc(priv, R0) & Tx_BUF_EMP) && p < priv->tx_len[i]) {
- write_scc_data(priv, priv->tx_buf[i][p++], 0);
- }
+ /* Write characters */
+ while ((read_scc(priv, R0) & Tx_BUF_EMP) && p < priv->tx_len[i]) {
+ write_scc_data(priv, priv->tx_buf[i][p++], 0);
+ }
- /* Reset EOM latch of Z8530 */
- if (!priv->tx_ptr && p && priv->chip == Z8530)
- write_scc(priv, R0, RES_EOM_L);
+ /* Reset EOM latch of Z8530 */
+ if (!priv->tx_ptr && p && priv->chip == Z8530)
+ write_scc(priv, R0, RES_EOM_L);
- priv->tx_ptr = p;
+ priv->tx_ptr = p;
}
-static void es_isr(struct scc_priv *priv) {
- int i, rr0, drr0, res;
- unsigned long flags;
-
- /* Read status, reset interrupt bit (open latches) */
- rr0 = read_scc(priv, R0);
- write_scc(priv, R0, RES_EXT_INT);
- drr0 = priv->rr0 ^ rr0;
- priv->rr0 = rr0;
-
- /* Transmit underrun (2.4.9.6). We can't check the TxEOM flag, since
- it might have already been cleared again by AUTOEOM. */
- if (priv->state == TX_DATA) {
- /* Get remaining bytes */
- i = priv->tx_tail;
- if (priv->param.dma >= 0) {
- disable_dma(priv->param.dma);
- flags = claim_dma_lock();
- res = get_dma_residue(priv->param.dma);
- release_dma_lock(flags);
- } else {
- res = priv->tx_len[i] - priv->tx_ptr;
- priv->tx_ptr = 0;
- }
- /* Disable DREQ / TX interrupt */
- if (priv->param.dma >= 0 && priv->type == TYPE_TWIN)
- outb(0, priv->card_base + TWIN_DMA_CFG);
- else
- write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN);
- if (res) {
- /* Update packet statistics */
- priv->stats.tx_errors++;
- priv->stats.tx_fifo_errors++;
- /* Other underrun interrupts may already be waiting */
- write_scc(priv, R0, RES_EXT_INT);
- write_scc(priv, R0, RES_EXT_INT);
- } else {
- /* Update packet statistics */
- priv->stats.tx_packets++;
- priv->stats.tx_bytes += priv->tx_len[i];
- /* Remove frame from FIFO */
- priv->tx_tail = (i + 1) % NUM_TX_BUF;
- priv->tx_count--;
- /* Inform upper layers */
- netif_wake_queue(priv->dev);
- }
- /* Switch state */
- write_scc(priv, R15, 0);
- if (priv->tx_count &&
- (jiffies - priv->tx_start) < priv->param.txtimeout) {
- priv->state = TX_PAUSE;
- start_timer(priv, priv->param.txpause, 0);
- } else {
- priv->state = TX_TAIL;
- start_timer(priv, priv->param.txtail, 0);
- }
- }
-
- /* DCD transition */
- if (drr0 & DCD) {
- if (rr0 & DCD) {
- switch (priv->state) {
- case IDLE:
- case WAIT:
- priv->state = DCD_ON;
- write_scc(priv, R15, 0);
- start_timer(priv, priv->param.dcdon, 0);
- }
- } else {
- switch (priv->state) {
- case RX_ON:
- rx_off(priv);
- priv->state = DCD_OFF;
- write_scc(priv, R15, 0);
- start_timer(priv, priv->param.dcdoff, 0);
- }
- }
- }
+static void es_isr(struct scc_priv *priv)
+{
+ int i, rr0, drr0, res;
+ unsigned long flags;
+
+ /* Read status, reset interrupt bit (open latches) */
+ rr0 = read_scc(priv, R0);
+ write_scc(priv, R0, RES_EXT_INT);
+ drr0 = priv->rr0 ^ rr0;
+ priv->rr0 = rr0;
+
+ /* Transmit underrun (2.4.9.6). We can't check the TxEOM flag, since
+ it might have already been cleared again by AUTOEOM. */
+ if (priv->state == TX_DATA) {
+ /* Get remaining bytes */
+ i = priv->tx_tail;
+ if (priv->param.dma >= 0) {
+ disable_dma(priv->param.dma);
+ flags = claim_dma_lock();
+ res = get_dma_residue(priv->param.dma);
+ release_dma_lock(flags);
+ } else {
+ res = priv->tx_len[i] - priv->tx_ptr;
+ priv->tx_ptr = 0;
+ }
+ /* Disable DREQ / TX interrupt */
+ if (priv->param.dma >= 0 && priv->type == TYPE_TWIN)
+ outb(0, priv->card_base + TWIN_DMA_CFG);
+ else
+ write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN);
+ if (res) {
+ /* Update packet statistics */
+ priv->stats.tx_errors++;
+ priv->stats.tx_fifo_errors++;
+ /* Other underrun interrupts may already be waiting */
+ write_scc(priv, R0, RES_EXT_INT);
+ write_scc(priv, R0, RES_EXT_INT);
+ } else {
+ /* Update packet statistics */
+ priv->stats.tx_packets++;
+ priv->stats.tx_bytes += priv->tx_len[i];
+ /* Remove frame from FIFO */
+ priv->tx_tail = (i + 1) % NUM_TX_BUF;
+ priv->tx_count--;
+ /* Inform upper layers */
+ netif_wake_queue(priv->dev);
+ }
+ /* Switch state */
+ write_scc(priv, R15, 0);
+ if (priv->tx_count &&
+ (jiffies - priv->tx_start) < priv->param.txtimeout) {
+ priv->state = TX_PAUSE;
+ start_timer(priv, priv->param.txpause, 0);
+ } else {
+ priv->state = TX_TAIL;
+ start_timer(priv, priv->param.txtail, 0);
+ }
+ }
+
+ /* DCD transition */
+ if (drr0 & DCD) {
+ if (rr0 & DCD) {
+ switch (priv->state) {
+ case IDLE:
+ case WAIT:
+ priv->state = DCD_ON;
+ write_scc(priv, R15, 0);
+ start_timer(priv, priv->param.dcdon, 0);
+ }
+ } else {
+ switch (priv->state) {
+ case RX_ON:
+ rx_off(priv);
+ priv->state = DCD_OFF;
+ write_scc(priv, R15, 0);
+ start_timer(priv, priv->param.dcdoff, 0);
+ }
+ }
+ }
- /* CTS transition */
- if ((drr0 & CTS) && (~rr0 & CTS) && priv->type != TYPE_TWIN)
- tm_isr(priv);
+ /* CTS transition */
+ if ((drr0 & CTS) && (~rr0 & CTS) && priv->type != TYPE_TWIN)
+ tm_isr(priv);
}
-static void tm_isr(struct scc_priv *priv) {
- switch (priv->state) {
- case TX_HEAD:
- case TX_PAUSE:
- tx_on(priv);
- priv->state = TX_DATA;
- break;
- case TX_TAIL:
- write_scc(priv, R5, TxCRC_ENAB | Tx8);
- priv->state = RTS_OFF;
- if (priv->type != TYPE_TWIN) write_scc(priv, R15, 0);
- start_timer(priv, priv->param.rtsoff, 0);
- break;
- case RTS_OFF:
- write_scc(priv, R15, DCDIE);
- priv->rr0 = read_scc(priv, R0);
- if (priv->rr0 & DCD) {
- priv->stats.collisions++;
- rx_on(priv);
- priv->state = RX_ON;
- } else {
- priv->state = WAIT;
- start_timer(priv, priv->param.waittime, DCDIE);
- }
- break;
- case WAIT:
- if (priv->tx_count) {
- priv->state = TX_HEAD;
- priv->tx_start = jiffies;
- write_scc(priv, R5, TxCRC_ENAB | RTS | TxENAB | Tx8);
- write_scc(priv, R15, 0);
- start_timer(priv, priv->param.txdelay, 0);
- } else {
- priv->state = IDLE;
- if (priv->type != TYPE_TWIN) write_scc(priv, R15, DCDIE);
- }
- break;
- case DCD_ON:
- case DCD_OFF:
- write_scc(priv, R15, DCDIE);
- priv->rr0 = read_scc(priv, R0);
- if (priv->rr0 & DCD) {
- rx_on(priv);
- priv->state = RX_ON;
- } else {
- priv->state = WAIT;
- start_timer(priv,
- random()/priv->param.persist*priv->param.slottime,
- DCDIE);
- }
- break;
- }
+static void tm_isr(struct scc_priv *priv)
+{
+ switch (priv->state) {
+ case TX_HEAD:
+ case TX_PAUSE:
+ tx_on(priv);
+ priv->state = TX_DATA;
+ break;
+ case TX_TAIL:
+ write_scc(priv, R5, TxCRC_ENAB | Tx8);
+ priv->state = RTS_OFF;
+ if (priv->type != TYPE_TWIN)
+ write_scc(priv, R15, 0);
+ start_timer(priv, priv->param.rtsoff, 0);
+ break;
+ case RTS_OFF:
+ write_scc(priv, R15, DCDIE);
+ priv->rr0 = read_scc(priv, R0);
+ if (priv->rr0 & DCD) {
+ priv->stats.collisions++;
+ rx_on(priv);
+ priv->state = RX_ON;
+ } else {
+ priv->state = WAIT;
+ start_timer(priv, priv->param.waittime, DCDIE);
+ }
+ break;
+ case WAIT:
+ if (priv->tx_count) {
+ priv->state = TX_HEAD;
+ priv->tx_start = jiffies;
+ write_scc(priv, R5,
+ TxCRC_ENAB | RTS | TxENAB | Tx8);
+ write_scc(priv, R15, 0);
+ start_timer(priv, priv->param.txdelay, 0);
+ } else {
+ priv->state = IDLE;
+ if (priv->type != TYPE_TWIN)
+ write_scc(priv, R15, DCDIE);
+ }
+ break;
+ case DCD_ON:
+ case DCD_OFF:
+ write_scc(priv, R15, DCDIE);
+ priv->rr0 = read_scc(priv, R0);
+ if (priv->rr0 & DCD) {
+ rx_on(priv);
+ priv->state = RX_ON;
+ } else {
+ priv->state = WAIT;
+ start_timer(priv,
+ random() / priv->param.persist *
+ priv->param.slottime, DCDIE);
+ }
+ break;
+ }
}
diff --git a/drivers/net/hamradio/hdlcdrv.c b/drivers/net/hamradio/hdlcdrv.c
index 8e115b5a6a118..b89959a596d7f 100644
--- a/drivers/net/hamradio/hdlcdrv.c
+++ b/drivers/net/hamradio/hdlcdrv.c
@@ -427,27 +427,10 @@ void hdlcdrv_arbitrate(struct net_device *dev, struct hdlcdrv_state *s)
* ===================== network driver interface =========================
*/
-static inline int hdlcdrv_paranoia_check(struct net_device *dev,
- const char *routine)
-{
- if (!dev || !dev->priv ||
- ((struct hdlcdrv_state *)dev->priv)->magic != HDLCDRV_MAGIC) {
- printk(KERN_ERR "hdlcdrv: bad magic number for hdlcdrv_state "
- "struct in routine %s\n", routine);
- return 1;
- }
- return 0;
-}
-
-/* --------------------------------------------------------------------- */
-
static int hdlcdrv_send_packet(struct sk_buff *skb, struct net_device *dev)
{
- struct hdlcdrv_state *sm;
+ struct hdlcdrv_state *sm = netdev_priv(dev);
- if (hdlcdrv_paranoia_check(dev, "hdlcdrv_send_packet"))
- return 0;
- sm = (struct hdlcdrv_state *)dev->priv;
if (skb->data[0] != 0) {
do_kiss_params(sm, skb->data, skb->len);
dev_kfree_skb(skb);
@@ -475,11 +458,8 @@ static int hdlcdrv_set_mac_address(struct net_device *dev, void *addr)
static struct net_device_stats *hdlcdrv_get_stats(struct net_device *dev)
{
- struct hdlcdrv_state *sm;
+ struct hdlcdrv_state *sm = netdev_priv(dev);
- if (hdlcdrv_paranoia_check(dev, "hdlcdrv_get_stats"))
- return NULL;
- sm = (struct hdlcdrv_state *)dev->priv;
/*
* Get the current statistics. This may be called with the
* card open or closed.
@@ -499,13 +479,9 @@ static struct net_device_stats *hdlcdrv_get_stats(struct net_device *dev)
static int hdlcdrv_open(struct net_device *dev)
{
- struct hdlcdrv_state *s;
+ struct hdlcdrv_state *s = netdev_priv(dev);
int i;
- if (hdlcdrv_paranoia_check(dev, "hdlcdrv_open"))
- return -EINVAL;
- s = (struct hdlcdrv_state *)dev->priv;
-
if (!s->ops || !s->ops->open)
return -ENODEV;
@@ -540,13 +516,9 @@ static int hdlcdrv_open(struct net_device *dev)
static int hdlcdrv_close(struct net_device *dev)
{
- struct hdlcdrv_state *s;
+ struct hdlcdrv_state *s = netdev_priv(dev);
int i = 0;
- if (hdlcdrv_paranoia_check(dev, "hdlcdrv_close"))
- return -EINVAL;
- s = (struct hdlcdrv_state *)dev->priv;
-
netif_stop_queue(dev);
if (s->ops && s->ops->close)
@@ -562,12 +534,8 @@ static int hdlcdrv_close(struct net_device *dev)
static int hdlcdrv_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
- struct hdlcdrv_state *s;
+ struct hdlcdrv_state *s = netdev_priv(dev);
struct hdlcdrv_ioctl bi;
-
- if (hdlcdrv_paranoia_check(dev, "hdlcdrv_ioctl"))
- return -EINVAL;
- s = (struct hdlcdrv_state *)dev->priv;
if (cmd != SIOCDEVPRIVATE) {
if (s->ops && s->ops->ioctl)
@@ -698,7 +666,7 @@ static void hdlcdrv_setup(struct net_device *dev)
static const struct hdlcdrv_channel_params dflt_ch_params = {
20, 2, 10, 40, 0
};
- struct hdlcdrv_state *s = dev->priv;
+ struct hdlcdrv_state *s = netdev_priv(dev);
/*
* initialize the hdlcdrv_state struct
@@ -782,7 +750,7 @@ struct net_device *hdlcdrv_register(const struct hdlcdrv_ops *ops,
/*
* initialize part of the hdlcdrv_state struct
*/
- s = dev->priv;
+ s = netdev_priv(dev);
s->magic = HDLCDRV_MAGIC;
s->ops = ops;
dev->base_addr = baseaddr;
@@ -803,7 +771,7 @@ struct net_device *hdlcdrv_register(const struct hdlcdrv_ops *ops,
void hdlcdrv_unregister(struct net_device *dev)
{
- struct hdlcdrv_state *s = dev->priv;
+ struct hdlcdrv_state *s = netdev_priv(dev);
BUG_ON(s->magic != HDLCDRV_MAGIC);
diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c
index 1b8663f5f8c14..d9ea080aea0f3 100644
--- a/drivers/net/hamradio/mkiss.c
+++ b/drivers/net/hamradio/mkiss.c
@@ -419,7 +419,7 @@ static void ax25_write_wakeup(struct tty_struct *tty)
/* Encapsulate an AX.25 packet and kick it into a TTY queue. */
static int ax_xmit(struct sk_buff *skb, struct net_device *dev)
{
- struct ax_disp *ax = (struct ax_disp *) dev->priv;
+ struct ax_disp *ax = netdev_priv(dev);
if (!netif_running(dev)) {
printk(KERN_ERR "mkiss: %s: xmit call when iface is down\n", dev->name);
@@ -483,7 +483,7 @@ static int ax_rebuild_header(struct sk_buff *skb)
/* Open the low-level part of the AX25 channel. Easy! */
static int ax_open(struct net_device *dev)
{
- struct ax_disp *ax = (struct ax_disp *) dev->priv;
+ struct ax_disp *ax = netdev_priv(dev);
unsigned long len;
if (ax->tty == NULL)
@@ -534,7 +534,7 @@ norbuff:
/* Close the low-level part of the AX25 channel. Easy! */
static int ax_close(struct net_device *dev)
{
- struct ax_disp *ax = (struct ax_disp *) dev->priv;
+ struct ax_disp *ax = netdev_priv(dev);
if (ax->tty == NULL)
return -EBUSY;
@@ -634,7 +634,7 @@ static void ax25_close(struct tty_struct *tty)
static struct net_device_stats *ax_get_stats(struct net_device *dev)
{
static struct net_device_stats stats;
- struct ax_disp *ax = (struct ax_disp *) dev->priv;
+ struct ax_disp *ax = netdev_priv(dev);
memset(&stats, 0, sizeof(struct net_device_stats));
@@ -827,7 +827,7 @@ static int ax25_disp_ioctl(struct tty_struct *tty, void *file, int cmd, void __u
static int ax_open_dev(struct net_device *dev)
{
- struct ax_disp *ax = (struct ax_disp *) dev->priv;
+ struct ax_disp *ax = netdev_priv(dev);
if (ax->tty == NULL)
return -ENODEV;
@@ -839,7 +839,7 @@ static int ax_open_dev(struct net_device *dev)
/* Initialize the driver. Called by network startup. */
static int ax25_init(struct net_device *dev)
{
- struct ax_disp *ax = (struct ax_disp *) dev->priv;
+ struct ax_disp *ax = netdev_priv(dev);
static char ax25_bcast[AX25_ADDR_LEN] =
{'Q'<<1,'S'<<1,'T'<<1,' '<<1,' '<<1,' '<<1,'0'<<1};
diff --git a/drivers/net/hamradio/yam.c b/drivers/net/hamradio/yam.c
index acae5949a9ea6..fd7b00fe38e5e 100644
--- a/drivers/net/hamradio/yam.c
+++ b/drivers/net/hamradio/yam.c
@@ -442,7 +442,7 @@ static int fpga_download(int iobase, int bitrate)
static void yam_set_uart(struct net_device *dev)
{
- struct yam_port *yp = (struct yam_port *) dev->priv;
+ struct yam_port *yp = netdev_priv(dev);
int divisor = 115200 / yp->baudrate;
outb(0, IER(dev->base_addr));
@@ -565,7 +565,7 @@ static void ptt_off(struct net_device *dev)
static int yam_send_packet(struct sk_buff *skb, struct net_device *dev)
{
- struct yam_port *yp = dev->priv;
+ struct yam_port *yp = netdev_priv(dev);
skb_queue_tail(&yp->send_queue, skb);
dev->trans_start = jiffies;
@@ -592,12 +592,11 @@ static inline unsigned short random_num(void)
static void yam_arbitrate(struct net_device *dev)
{
- struct yam_port *yp = dev->priv;
+ struct yam_port *yp = netdev_priv(dev);
- if (!yp || yp->magic != YAM_MAGIC
- || yp->tx_state != TX_OFF || skb_queue_empty(&yp->send_queue)) {
+ if (yp->magic != YAM_MAGIC || yp->tx_state != TX_OFF ||
+ skb_queue_empty(&yp->send_queue))
return;
- }
/* tx_state is TX_OFF and there is data to send */
if (yp->dupmode) {
@@ -725,7 +724,7 @@ static irqreturn_t yam_interrupt(int irq, void *dev_id, struct pt_regs *regs)
for (i = 0; i < NR_PORTS; i++) {
dev = yam_devs[i];
- yp = dev->priv;
+ yp = netdev_priv(dev);
if (!netif_running(dev))
continue;
@@ -784,8 +783,8 @@ static void yam_seq_stop(struct seq_file *seq, void *v)
static int yam_seq_show(struct seq_file *seq, void *v)
{
- const struct net_device *dev = v;
- const struct yam_port *yp = dev->priv;
+ struct net_device *dev = v;
+ const struct yam_port *yp = netdev_priv(dev);
seq_printf(seq, "Device %s\n", dev->name);
seq_printf(seq, " Up %d\n", netif_running(dev));
@@ -838,10 +837,10 @@ static struct net_device_stats *yam_get_stats(struct net_device *dev)
{
struct yam_port *yp;
- if (!dev || !dev->priv)
+ if (!dev)
return NULL;
- yp = (struct yam_port *) dev->priv;
+ yp = netdev_priv(dev);
if (yp->magic != YAM_MAGIC)
return NULL;
@@ -856,14 +855,14 @@ static struct net_device_stats *yam_get_stats(struct net_device *dev)
static int yam_open(struct net_device *dev)
{
- struct yam_port *yp = (struct yam_port *) dev->priv;
+ struct yam_port *yp = netdev_priv(dev);
enum uart u;
int i;
int ret=0;
printk(KERN_INFO "Trying %s at iobase 0x%lx irq %u\n", dev->name, dev->base_addr, dev->irq);
- if (!dev || !yp || !yp->bitrate)
+ if (!dev || !yp->bitrate)
return -ENXIO;
if (!dev->base_addr || dev->base_addr > 0x1000 - YAM_EXTENT ||
dev->irq < 2 || dev->irq > 15) {
@@ -900,7 +899,7 @@ static int yam_open(struct net_device *dev)
/* Reset overruns for all ports - FPGA programming makes overruns */
for (i = 0; i < NR_PORTS; i++) {
struct net_device *dev = yam_devs[i];
- struct yam_port *yp = dev->priv;
+ struct yam_port *yp = netdev_priv(dev);
inb(LSR(dev->base_addr));
yp->stats.rx_fifo_errors = 0;
}
@@ -919,10 +918,11 @@ out_release_base:
static int yam_close(struct net_device *dev)
{
struct sk_buff *skb;
- struct yam_port *yp = (struct yam_port *) dev->priv;
+ struct yam_port *yp = netdev_priv(dev);
- if (!dev || !yp)
+ if (!dev)
return -EINVAL;
+
/*
* disable interrupts
*/
@@ -944,7 +944,7 @@ static int yam_close(struct net_device *dev)
static int yam_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
- struct yam_port *yp = (struct yam_port *) dev->priv;
+ struct yam_port *yp = netdev_priv(dev);
struct yamdrv_ioctl_cfg yi;
struct yamdrv_ioctl_mcs *ym;
int ioctl_cmd;
@@ -952,7 +952,7 @@ static int yam_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
if (copy_from_user(&ioctl_cmd, ifr->ifr_data, sizeof(int)))
return -EFAULT;
- if (yp == NULL || yp->magic != YAM_MAGIC)
+ if (yp->magic != YAM_MAGIC)
return -EINVAL;
if (!capable(CAP_NET_ADMIN))
@@ -1091,7 +1091,7 @@ static int yam_set_mac_address(struct net_device *dev, void *addr)
static void yam_setup(struct net_device *dev)
{
- struct yam_port *yp = dev->priv;
+ struct yam_port *yp = netdev_priv(dev);
yp->magic = YAM_MAGIC;
yp->bitrate = DEFAULT_BITRATE;
diff --git a/drivers/net/hp100.c b/drivers/net/hp100.c
index 84fcb71895937..acb170152bbdd 100644
--- a/drivers/net/hp100.c
+++ b/drivers/net/hp100.c
@@ -306,7 +306,7 @@ static void wait(void)
* Read board id and convert to string.
* Effectively same code as decode_eisa_sig
*/
-static __init const char *hp100_read_id(int ioaddr)
+static __devinit const char *hp100_read_id(int ioaddr)
{
int i;
static char str[HP100_SIG_LEN];
@@ -429,8 +429,8 @@ struct net_device * __init hp100_probe(int unit)
}
#endif
-static int __init hp100_probe1(struct net_device *dev, int ioaddr,
- u_char bus, struct pci_dev *pci_dev)
+static int __devinit hp100_probe1(struct net_device *dev, int ioaddr,
+ u_char bus, struct pci_dev *pci_dev)
{
int i;
int err = -ENODEV;
diff --git a/drivers/net/ibm_emac/ibm_emac.h b/drivers/net/ibm_emac/ibm_emac.h
index 9d9b59e61351a..15d5a0e828626 100644
--- a/drivers/net/ibm_emac/ibm_emac.h
+++ b/drivers/net/ibm_emac/ibm_emac.h
@@ -237,6 +237,10 @@ typedef struct emac_regs {
#define EMAC_RWMR_DEFAULT 0x1000a200
#define EMAC_TMR0_DEFAULT EMAC_TMR0_TFAE_2_32
#define EMAC_TMR1_DEFAULT 0xa00f0000
+#elif defined(CONFIG_440SP)
+#define EMAC_RWMR_DEFAULT 0x08002000
+#define EMAC_TMR0_DEFAULT EMAC_TMR0_TFAE_128_2048
+#define EMAC_TMR1_DEFAULT 0xf8200000
#else
#define EMAC_RWMR_DEFAULT 0x0f002000
#define EMAC_TMR0_DEFAULT 0x00000000
diff --git a/drivers/net/ibm_emac/ibm_emac_core.c b/drivers/net/ibm_emac/ibm_emac_core.c
index cac939732d5d4..ab44358ddbfc9 100644
--- a/drivers/net/ibm_emac/ibm_emac_core.c
+++ b/drivers/net/ibm_emac/ibm_emac_core.c
@@ -1041,7 +1041,7 @@ static int emac_adjust_to_link(struct ocp_enet_private *fep)
/* set speed (default is 10Mb) */
switch (speed) {
case SPEED_1000:
- mode_reg |= EMAC_M1_JUMBO_ENABLE | EMAC_M1_RFS_16K;
+ mode_reg |= EMAC_M1_RFS_16K;
if (fep->rgmii_dev) {
struct ibm_ocp_rgmii *rgmii = RGMII_PRIV(fep->rgmii_dev);
@@ -1118,6 +1118,7 @@ static int emac_change_mtu(struct net_device *dev, int new_mtu)
{
struct ocp_enet_private *fep = dev->priv;
int old_mtu = dev->mtu;
+ unsigned long mode_reg;
emac_t *emacp = fep->emacp;
u32 em0mr0;
int i, full;
@@ -1160,10 +1161,17 @@ static int emac_change_mtu(struct net_device *dev, int new_mtu)
fep->rx_skb[i] = NULL;
}
- /* Set new rx_buffer_size and advertise new mtu */
- fep->rx_buffer_size =
- new_mtu + ENET_HEADER_SIZE + ENET_FCS_SIZE;
+ /* Set new rx_buffer_size, jumbo cap, and advertise new mtu */
+ mode_reg = in_be32(&emacp->em0mr1);
+ if (new_mtu > ENET_DEF_MTU_SIZE) {
+ mode_reg |= EMAC_M1_JUMBO_ENABLE;
+ fep->rx_buffer_size = EMAC_MAX_FRAME;
+ } else {
+ mode_reg &= ~EMAC_M1_JUMBO_ENABLE;
+ fep->rx_buffer_size = ENET_DEF_BUF_SIZE;
+ }
dev->mtu = new_mtu;
+ out_be32(&emacp->em0mr1, mode_reg);
/* Re-init rx skbs */
fep->rx_slot = 0;
diff --git a/drivers/net/ibm_emac/ibm_emac_core.h b/drivers/net/ibm_emac/ibm_emac_core.h
index 026a01cf78e52..97e6e1ea8c89e 100644
--- a/drivers/net/ibm_emac/ibm_emac_core.h
+++ b/drivers/net/ibm_emac/ibm_emac_core.h
@@ -77,6 +77,8 @@
#define ENET_HEADER_SIZE 14
#define ENET_FCS_SIZE 4
+#define ENET_DEF_MTU_SIZE 1500
+#define ENET_DEF_BUF_SIZE (ENET_DEF_MTU_SIZE + ENET_HEADER_SIZE + ENET_FCS_SIZE)
#define EMAC_MIN_FRAME 64
#define EMAC_MAX_FRAME 9018
#define EMAC_MIN_MTU (EMAC_MIN_FRAME - ENET_HEADER_SIZE - ENET_FCS_SIZE)
diff --git a/drivers/net/ibmlana.c b/drivers/net/ibmlana.c
index 79c3fbfcbfefa..01ad904215a15 100644
--- a/drivers/net/ibmlana.c
+++ b/drivers/net/ibmlana.c
@@ -133,13 +133,14 @@ static void dumpregs(struct net_device *dev)
static void dumpmem(struct net_device *dev, u32 start, u32 len)
{
+ ibmlana_priv *priv = netdev_priv(dev);
int z;
printk("Address %04x:\n", start);
for (z = 0; z < len; z++) {
if ((z & 15) == 0)
printk("%04x:", z);
- printk(" %02x", isa_readb(dev->mem_start + start + z));
+ printk(" %02x", readb(priv->base + start + z));
if ((z & 15) == 15)
printk("\n");
}
@@ -231,7 +232,7 @@ static void ResetBoard(struct net_device *dev)
static void InitDscrs(struct net_device *dev)
{
- ibmlana_priv *priv = (ibmlana_priv *) dev->priv;
+ ibmlana_priv *priv = netdev_priv(dev);
u32 addr, baddr, raddr;
int z;
tda_t tda;
@@ -240,8 +241,8 @@ static void InitDscrs(struct net_device *dev)
/* initialize RAM */
- isa_memset_io(dev->mem_start, 0xaa,
- dev->mem_start - dev->mem_start);
+ memset_io(priv->base, 0xaa,
+ dev->mem_start - dev->mem_start); /* XXX: typo? */
/* setup n TX descriptors - independent of RAM size */
@@ -260,7 +261,7 @@ static void InitDscrs(struct net_device *dev)
else
tda.link = addr + sizeof(tda_t);
tda.link |= 1;
- isa_memcpy_toio(dev->mem_start + addr, &tda, sizeof(tda_t));
+ memcpy_toio(priv->base + addr, &tda, sizeof(tda_t));
addr += sizeof(tda_t);
baddr += PKTSIZE;
}
@@ -280,7 +281,7 @@ static void InitDscrs(struct net_device *dev)
rra.starthi = 0;
rra.cntlo = PKTSIZE >> 1;
rra.cnthi = 0;
- isa_memcpy_toio(dev->mem_start + raddr, &rra, sizeof(rra_t));
+ memcpy_toio(priv->base + raddr, &rra, sizeof(rra_t));
rda.status = 0;
rda.length = 0;
@@ -292,7 +293,7 @@ static void InitDscrs(struct net_device *dev)
else
rda.link = 1;
rda.inuse = 1;
- isa_memcpy_toio(dev->mem_start + addr, &rda, sizeof(rda_t));
+ memcpy_toio(priv->base + addr, &rda, sizeof(rda_t));
baddr += PKTSIZE;
raddr += sizeof(rra_t);
@@ -313,7 +314,7 @@ static void InitDscrs(struct net_device *dev)
static int InitSONIC(struct net_device *dev)
{
- ibmlana_priv *priv = (ibmlana_priv *) dev->priv;
+ ibmlana_priv *priv = netdev_priv(dev);
/* set up start & end of resource area */
@@ -379,6 +380,7 @@ static void putcam(camentry_t * cams, int *camcnt, char *addr)
static void InitBoard(struct net_device *dev)
{
+ ibmlana_priv *priv = netdev_priv(dev);
int camcnt;
camentry_t cams[16];
u32 cammask;
@@ -429,8 +431,8 @@ static void InitBoard(struct net_device *dev)
/* feed CDA into SONIC, initialize RCR value (always get broadcasts) */
- isa_memcpy_toio(dev->mem_start, cams, sizeof(camentry_t) * camcnt);
- isa_memcpy_toio(dev->mem_start + (sizeof(camentry_t) * camcnt), &cammask, sizeof(cammask));
+ memcpy_toio(priv->base, cams, sizeof(camentry_t) * camcnt);
+ memcpy_toio(priv->base + (sizeof(camentry_t) * camcnt), &cammask, sizeof(cammask));
#ifdef DEBUG
printk("CAM setup:\n");
@@ -520,7 +522,7 @@ static void InitBoard(struct net_device *dev)
static void StartTx(struct net_device *dev, int descr)
{
- ibmlana_priv *priv = (ibmlana_priv *) dev->priv;
+ ibmlana_priv *priv = netdev_priv(dev);
int addr;
addr = priv->tdastart + (descr * sizeof(tda_t));
@@ -543,7 +545,7 @@ static void StartTx(struct net_device *dev, int descr)
static void irqrbe_handler(struct net_device *dev)
{
- ibmlana_priv *priv = (ibmlana_priv *) dev->priv;
+ ibmlana_priv *priv = netdev_priv(dev);
/* point the SONIC back to the RRA start */
@@ -555,7 +557,7 @@ static void irqrbe_handler(struct net_device *dev)
static void irqrx_handler(struct net_device *dev)
{
- ibmlana_priv *priv = (ibmlana_priv *) dev->priv;
+ ibmlana_priv *priv = netdev_priv(dev);
rda_t rda;
u32 rdaaddr, lrdaaddr;
@@ -566,7 +568,7 @@ static void irqrx_handler(struct net_device *dev)
rdaaddr = priv->rdastart + (priv->nextrxdescr * sizeof(rda_t));
lrdaaddr = priv->rdastart + (priv->lastrxdescr * sizeof(rda_t));
- isa_memcpy_fromio(&rda, dev->mem_start + rdaaddr, sizeof(rda_t));
+ memcpy_fromio(&rda, priv->base + rdaaddr, sizeof(rda_t));
/* iron out upper word halves of fields we use - SONIC will duplicate
bits 0..15 to 16..31 */
@@ -593,8 +595,8 @@ static void irqrx_handler(struct net_device *dev)
else {
/* copy out data */
- isa_memcpy_fromio(skb_put(skb, rda.length),
- dev->mem_start +
+ memcpy_fromio(skb_put(skb, rda.length),
+ priv->base +
rda.startlo, rda.length);
/* set up skb fields */
@@ -627,14 +629,14 @@ static void irqrx_handler(struct net_device *dev)
rda.link = 1;
rda.inuse = 1;
- isa_memcpy_toio(dev->mem_start + rdaaddr, &rda,
+ memcpy_toio(priv->base + rdaaddr, &rda,
sizeof(rda_t));
/* set up link and EOL = 0 in currently last descriptor. Only write
the link field since the SONIC may currently already access the
other fields. */
- isa_memcpy_toio(dev->mem_start + lrdaaddr + 20, &rdaaddr, 4);
+ memcpy_toio(priv->base + lrdaaddr + 20, &rdaaddr, 4);
/* advance indices */
@@ -648,11 +650,11 @@ static void irqrx_handler(struct net_device *dev)
static void irqtx_handler(struct net_device *dev)
{
- ibmlana_priv *priv = (ibmlana_priv *) dev->priv;
+ ibmlana_priv *priv = netdev_priv(dev);
tda_t tda;
/* fetch descriptor (we forgot the size ;-) */
- isa_memcpy_fromio(&tda, dev->mem_start + priv->tdastart + (priv->currtxdescr * sizeof(tda_t)), sizeof(tda_t));
+ memcpy_fromio(&tda, priv->base + priv->tdastart + (priv->currtxdescr * sizeof(tda_t)), sizeof(tda_t));
/* update statistics */
priv->stat.tx_packets++;
@@ -672,11 +674,11 @@ static void irqtx_handler(struct net_device *dev)
static void irqtxerr_handler(struct net_device *dev)
{
- ibmlana_priv *priv = (ibmlana_priv *) dev->priv;
+ ibmlana_priv *priv = netdev_priv(dev);
tda_t tda;
/* fetch descriptor to check status */
- isa_memcpy_fromio(&tda, dev->mem_start + priv->tdastart + (priv->currtxdescr * sizeof(tda_t)), sizeof(tda_t));
+ memcpy_fromio(&tda, priv->base + priv->tdastart + (priv->currtxdescr * sizeof(tda_t)), sizeof(tda_t));
/* update statistics */
priv->stat.tx_errors++;
@@ -753,9 +755,7 @@ static int ibmlana_getinfo(char *buf, int slot, void *d)
if (dev == NULL)
return len;
- if (dev->priv == NULL)
- return len;
- priv = (ibmlana_priv *) dev->priv;
+ priv = netdev_priv(dev);
/* print info */
@@ -778,7 +778,7 @@ static int ibmlana_getinfo(char *buf, int slot, void *d)
static int ibmlana_open(struct net_device *dev)
{
int result;
- ibmlana_priv *priv = (ibmlana_priv *) dev->priv;
+ ibmlana_priv *priv = netdev_priv(dev);
/* register resources - only necessary for IRQ */
@@ -814,7 +814,7 @@ static int ibmlana_close(struct net_device *dev)
static int ibmlana_tx(struct sk_buff *skb, struct net_device *dev)
{
- ibmlana_priv *priv = (ibmlana_priv *) dev->priv;
+ ibmlana_priv *priv = netdev_priv(dev);
int retval = 0, tmplen, addr;
unsigned long flags;
tda_t tda;
@@ -834,7 +834,7 @@ static int ibmlana_tx(struct sk_buff *skb, struct net_device *dev)
if (tmplen < 60)
tmplen = 60;
baddr = priv->txbufstart + (priv->nexttxdescr * PKTSIZE);
- isa_memcpy_toio(dev->mem_start + baddr, skb->data, skb->len);
+ memcpy_toio(priv->base + baddr, skb->data, skb->len);
/* copy filler into RAM - in case we're filling up...
we're filling a bit more than necessary, but that doesn't harm
@@ -846,16 +846,16 @@ static int ibmlana_tx(struct sk_buff *skb, struct net_device *dev)
unsigned int destoffs = skb->len, l = strlen(fill);
while (destoffs < tmplen) {
- isa_memcpy_toio(dev->mem_start + baddr + destoffs, fill, l);
+ memcpy_toio(priv->base + baddr + destoffs, fill, l);
destoffs += l;
}
}
/* set up the new frame descriptor */
addr = priv->tdastart + (priv->nexttxdescr * sizeof(tda_t));
- isa_memcpy_fromio(&tda, dev->mem_start + addr, sizeof(tda_t));
+ memcpy_fromio(&tda, priv->base + addr, sizeof(tda_t));
tda.length = tda.fraglength = tmplen;
- isa_memcpy_toio(dev->mem_start + addr, &tda, sizeof(tda_t));
+ memcpy_toio(priv->base + addr, &tda, sizeof(tda_t));
/* if there were no active descriptors, trigger the SONIC */
spin_lock_irqsave(&priv->lock, flags);
@@ -881,7 +881,7 @@ tx_done:
static struct net_device_stats *ibmlana_stats(struct net_device *dev)
{
- ibmlana_priv *priv = (ibmlana_priv *) dev->priv;
+ ibmlana_priv *priv = netdev_priv(dev);
return &priv->stat;
}
@@ -903,7 +903,6 @@ static int startslot; /* counts through slots when probing multiple devices */
static int ibmlana_probe(struct net_device *dev)
{
- int force_detect = 0;
int slot, z;
int base = 0, irq = 0, iobase = 0, memlen = 0;
ibmlana_priv *priv;
@@ -915,10 +914,6 @@ static int ibmlana_probe(struct net_device *dev)
if (MCA_bus == 0)
return -ENODEV;
- /* start address of 1 --> forced detection */
- if (dev->mem_start == 1)
- force_detect = 1;
-
base = dev->mem_start;
irq = dev->irq;
@@ -952,18 +947,12 @@ static int ibmlana_probe(struct net_device *dev)
return -EBUSY;
}
- /* make procfs entries */
- mca_set_adapter_name(slot, "IBM LAN Adapter/A");
- mca_set_adapter_procfn(slot, (MCA_ProcFn) ibmlana_getinfo, dev);
-
- mca_mark_as_used(slot);
-
- /* allocate structure */
- priv = dev->priv;
+ priv = netdev_priv(dev);
priv->slot = slot;
priv->realirq = irq;
priv->medium = medium;
spin_lock_init(&priv->lock);
+
/* set base + irq for this device (irq not allocated so far) */
@@ -972,6 +961,20 @@ static int ibmlana_probe(struct net_device *dev)
dev->mem_end = base + memlen;
dev->base_addr = iobase;
+ priv->base = ioremap(base, memlen);
+ if (!priv->base) {
+ printk(KERN_ERR "%s: cannot remap memory!\n", DRV_NAME);
+ startslot = slot + 1;
+ release_region(iobase, IBM_LANA_IORANGE);
+ return -EBUSY;
+ }
+
+ /* make procfs entries */
+ mca_set_adapter_name(slot, "IBM LAN Adapter/A");
+ mca_set_adapter_procfn(slot, (MCA_ProcFn) ibmlana_getinfo, dev);
+
+ mca_mark_as_used(slot);
+
/* set methods */
dev->open = ibmlana_open;
@@ -1042,11 +1045,12 @@ int init_module(void)
break;
}
if (register_netdev(dev)) {
- ibmlana_priv *priv = dev->priv;
+ ibmlana_priv *priv = netdev_priv(dev);
release_region(dev->base_addr, IBM_LANA_IORANGE);
mca_mark_as_unused(priv->slot);
mca_set_adapter_name(priv->slot, "");
mca_set_adapter_procfn(priv->slot, NULL, NULL);
+ iounmap(priv->base);
free_netdev(dev);
break;
}
@@ -1061,13 +1065,14 @@ void cleanup_module(void)
for (z = 0; z < DEVMAX; z++) {
struct net_device *dev = moddevs[z];
if (dev) {
- ibmlana_priv *priv = (ibmlana_priv *) dev->priv;
+ ibmlana_priv *priv = netdev_priv(dev);
unregister_netdev(dev);
/*DeinitBoard(dev); */
release_region(dev->base_addr, IBM_LANA_IORANGE);
mca_mark_as_unused(priv->slot);
mca_set_adapter_name(priv->slot, "");
mca_set_adapter_procfn(priv->slot, NULL, NULL);
+ iounmap(priv->base);
free_netdev(dev);
}
}
diff --git a/drivers/net/ibmlana.h b/drivers/net/ibmlana.h
index 1b535e8441cc7..458ee226e5372 100644
--- a/drivers/net/ibmlana.h
+++ b/drivers/net/ibmlana.h
@@ -37,6 +37,7 @@ typedef struct {
nexttxdescr, /* last tx descriptor to be used */
currtxdescr, /* tx descriptor currently tx'ed */
txused[TXBUFCNT]; /* busy flags */
+ void __iomem *base;
spinlock_t lock;
} ibmlana_priv;
diff --git a/drivers/net/ioc3-eth.c b/drivers/net/ioc3-eth.c
index e16f8b20ae18d..d520b5920d6cc 100644
--- a/drivers/net/ioc3-eth.c
+++ b/drivers/net/ioc3-eth.c
@@ -56,7 +56,6 @@
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
#include <linux/skbuff.h>
-#include <linux/dp83840.h>
#include <net/ip.h>
#include <asm/byteorder.h>
@@ -463,6 +462,29 @@ static void ioc3_get_eaddr(struct ioc3_private *ip)
printk(".\n");
}
+static void __ioc3_set_mac_address(struct net_device *dev)
+{
+ struct ioc3_private *ip = netdev_priv(dev);
+ struct ioc3 *ioc3 = ip->regs;
+
+ ioc3_w_emar_h((dev->dev_addr[5] << 8) | dev->dev_addr[4]);
+ ioc3_w_emar_l((dev->dev_addr[3] << 24) | (dev->dev_addr[2] << 16) |
+ (dev->dev_addr[1] << 8) | dev->dev_addr[0]);
+}
+
+static int ioc3_set_mac_address(struct net_device *dev, void *addr)
+{
+ struct ioc3_private *ip = netdev_priv(dev);
+ struct sockaddr *sa = addr;
+
+ memcpy(dev->dev_addr, sa->sa_data, dev->addr_len);
+
+ spin_lock_irq(&ip->ioc3_lock);
+ __ioc3_set_mac_address(dev);
+ spin_unlock_irq(&ip->ioc3_lock);
+
+ return 0;
+}
/*
* Caller must hold the ioc3_lock ever for MII readers. This is also
@@ -1014,9 +1036,7 @@ static void ioc3_init(struct net_device *dev)
(void) ioc3_r_etcdc(); /* Clear on read */
ioc3_w_ercsr(15); /* RX low watermark */
ioc3_w_ertr(0); /* Interrupt immediately */
- ioc3_w_emar_h((dev->dev_addr[5] << 8) | dev->dev_addr[4]);
- ioc3_w_emar_l((dev->dev_addr[3] << 24) | (dev->dev_addr[2] << 16) |
- (dev->dev_addr[1] << 8) | dev->dev_addr[0]);
+ __ioc3_set_mac_address(dev);
ioc3_w_ehar_h(ip->ehar_h);
ioc3_w_ehar_l(ip->ehar_l);
ioc3_w_ersr(42); /* XXX should be random */
@@ -1100,6 +1120,7 @@ static inline int ioc3_is_menet(struct pci_dev *pdev)
&& dev->device == PCI_DEVICE_ID_SGI_IOC3;
}
+#ifdef CONFIG_SERIAL_8250
/*
* Note about serial ports and consoles:
* For console output, everyone uses the IOC3 UARTA (offset 0x178)
@@ -1121,15 +1142,14 @@ static inline int ioc3_is_menet(struct pci_dev *pdev)
* "device" routine referred to in this console structure
* (ip27prom_console_dev).
*
- * Also look in ip27-pci.c:pci_fixuop_ioc3() for some comments on working
+ * Also look in ip27-pci.c:pci_fixup_ioc3() for some comments on working
* around ioc3 oddities in this respect.
*
* The IOC3 serials use a 22MHz clock rate with an additional divider by 3.
* (IOC3_BAUD = (22000000 / (3*16)))
*/
-static inline void ioc3_serial_probe(struct pci_dev *pdev,
- struct ioc3 *ioc3)
+static void __devinit ioc3_serial_probe(struct pci_dev *pdev, struct ioc3 *ioc3)
{
struct serial_struct req;
@@ -1160,9 +1180,9 @@ static inline void ioc3_serial_probe(struct pci_dev *pdev,
req.iomem_base = (unsigned char *) &ioc3->sregs.uartb;
register_serial(&req);
}
+#endif
-static int __devinit ioc3_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int ioc3_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
unsigned int sw_physid1, sw_physid2;
struct net_device *dev = NULL;
@@ -1170,11 +1190,39 @@ static int __devinit ioc3_probe(struct pci_dev *pdev,
struct ioc3 *ioc3;
unsigned long ioc3_base, ioc3_size;
u32 vendor, model, rev;
- int err;
+ int err, pci_using_dac;
+
+ /* Configure DMA attributes. */
+ err = pci_set_dma_mask(pdev, 0xffffffffffffffffULL);
+ if (!err) {
+ pci_using_dac = 1;
+ err = pci_set_consistent_dma_mask(pdev, 0xffffffffffffffffULL);
+ if (err < 0) {
+ printk(KERN_ERR "%s: Unable to obtain 64 bit DMA "
+ "for consistent allocations\n", pci_name(pdev));
+ goto out;
+ }
+ } else {
+ err = pci_set_dma_mask(pdev, 0xffffffffULL);
+ if (err) {
+ printk(KERN_ERR "%s: No usable DMA configuration, "
+ "aborting.\n", pci_name(pdev));
+ goto out;
+ }
+ pci_using_dac = 0;
+ }
+
+ if (pci_enable_device(pdev))
+ return -ENODEV;
dev = alloc_etherdev(sizeof(struct ioc3_private));
- if (!dev)
- return -ENOMEM;
+ if (!dev) {
+ err = -ENOMEM;
+ goto out_disable;
+ }
+
+ if (pci_using_dac)
+ dev->features |= NETIF_F_HIGHDMA;
err = pci_request_regions(pdev, "ioc3");
if (err)
@@ -1237,6 +1285,7 @@ static int __devinit ioc3_probe(struct pci_dev *pdev,
dev->get_stats = ioc3_get_stats;
dev->do_ioctl = ioc3_ioctl;
dev->set_multicast_list = ioc3_set_multicast_list;
+ dev->set_mac_address = ioc3_set_mac_address;
dev->ethtool_ops = &ioc3_ethtool_ops;
#ifdef CONFIG_SGI_IOC3_ETH_HW_TX_CSUM
dev->features = NETIF_F_IP_CSUM;
@@ -1269,6 +1318,12 @@ out_res:
pci_release_regions(pdev);
out_free:
free_netdev(dev);
+out_disable:
+ /*
+ * We should call pci_disable_device(pdev); here if the IOC3 wasn't
+ * such a weird device ...
+ */
+out:
return err;
}
@@ -1282,6 +1337,10 @@ static void __devexit ioc3_remove_one (struct pci_dev *pdev)
iounmap(ioc3);
pci_release_regions(pdev);
free_netdev(dev);
+ /*
+ * We should call pci_disable_device(pdev); here if the IOC3 wasn't
+ * such a weird device ...
+ */
}
static struct pci_device_id ioc3_pci_tbl[] = {
diff --git a/drivers/net/irda/act200l-sir.c b/drivers/net/irda/act200l-sir.c
index dac04fad01b5d..d8b89c74aabd8 100644
--- a/drivers/net/irda/act200l-sir.c
+++ b/drivers/net/irda/act200l-sir.c
@@ -177,8 +177,7 @@ static int act200l_change_speed(struct sir_dev *dev, unsigned speed)
/* Write control bytes */
sirdev_raw_write(dev, control, 3);
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(msecs_to_jiffies(5));
+ msleep(5);
/* Go back to normal mode */
sirdev_set_dtr_rts(dev, TRUE, TRUE);
@@ -241,7 +240,7 @@ static int act200l_reset(struct sir_dev *dev)
dev->speed = 9600;
break;
default:
- ERROR("%s(), unknown state %d\n", __FUNCTION__, state);
+ IRDA_ERROR("%s(), unknown state %d\n", __FUNCTION__, state);
ret = -1;
break;
}
diff --git a/drivers/net/irda/act200l.c b/drivers/net/irda/act200l.c
index e18de72c46905..756cd44e857a3 100644
--- a/drivers/net/irda/act200l.c
+++ b/drivers/net/irda/act200l.c
@@ -152,7 +152,8 @@ static int act200l_change_speed(struct irda_task *task)
}
break;
case IRDA_TASK_CHILD_WAIT:
- WARNING("%s(), resetting dongle timed out!\n", __FUNCTION__);
+ IRDA_WARNING("%s(), resetting dongle timed out!\n",
+ __FUNCTION__);
ret = -1;
break;
case IRDA_TASK_CHILD_DONE:
@@ -197,7 +198,8 @@ static int act200l_change_speed(struct irda_task *task)
self->speed_task = NULL;
break;
default:
- ERROR("%s(), unknown state %d\n", __FUNCTION__, task->state);
+ IRDA_ERROR("%s(), unknown state %d\n",
+ __FUNCTION__, task->state);
irda_task_next_state(task, IRDA_TASK_DONE);
self->speed_task = NULL;
ret = -1;
@@ -263,7 +265,8 @@ static int act200l_reset(struct irda_task *task)
self->reset_task = NULL;
break;
default:
- ERROR("%s(), unknown state %d\n", __FUNCTION__, task->state);
+ IRDA_ERROR("%s(), unknown state %d\n",
+ __FUNCTION__, task->state);
irda_task_next_state(task, IRDA_TASK_DONE);
self->reset_task = NULL;
ret = -1;
diff --git a/drivers/net/irda/actisys.c b/drivers/net/irda/actisys.c
index 75344d6486fe1..b2e31f4a384c9 100644
--- a/drivers/net/irda/actisys.c
+++ b/drivers/net/irda/actisys.c
@@ -227,7 +227,7 @@ static int actisys_reset(struct irda_task *task)
dongle_t *self = (dongle_t *) task->instance;
int ret = 0;
- ASSERT(task != NULL, return -1;);
+ IRDA_ASSERT(task != NULL, return -1;);
self->reset_task = task;
@@ -254,7 +254,8 @@ static int actisys_reset(struct irda_task *task)
self->speed = 9600; /* That's the default */
break;
default:
- ERROR("%s(), unknown state %d\n", __FUNCTION__, task->state);
+ IRDA_ERROR("%s(), unknown state %d\n",
+ __FUNCTION__, task->state);
irda_task_next_state(task, IRDA_TASK_DONE);
self->reset_task = NULL;
ret = -1;
diff --git a/drivers/net/irda/ali-ircc.c b/drivers/net/irda/ali-ircc.c
index c9595a1a3b862..9bf34681d3dfe 100644
--- a/drivers/net/irda/ali-ircc.c
+++ b/drivers/net/irda/ali-ircc.c
@@ -260,7 +260,8 @@ static int ali_ircc_open(int i, chipio_t *info)
dev = alloc_irdadev(sizeof(*self));
if (dev == NULL) {
- ERROR("%s(), can't allocate memory for control block!\n", __FUNCTION__);
+ IRDA_ERROR("%s(), can't allocate memory for control block!\n",
+ __FUNCTION__);
return -ENOMEM;
}
@@ -283,7 +284,7 @@ static int ali_ircc_open(int i, chipio_t *info)
/* Reserve the ioports that we need */
if (!request_region(self->io.fir_base, self->io.fir_ext, driver_name)) {
- WARNING("%s(), can't get iobase of 0x%03x\n", __FUNCTION__,
+ IRDA_WARNING("%s(), can't get iobase of 0x%03x\n", __FUNCTION__,
self->io.fir_base);
err = -ENODEV;
goto err_out1;
@@ -345,14 +346,14 @@ static int ali_ircc_open(int i, chipio_t *info)
err = register_netdev(dev);
if (err) {
- ERROR("%s(), register_netdev() failed!\n", __FUNCTION__);
+ IRDA_ERROR("%s(), register_netdev() failed!\n", __FUNCTION__);
goto err_out4;
}
- MESSAGE("IrDA: Registered device %s\n", dev->name);
+ IRDA_MESSAGE("IrDA: Registered device %s\n", dev->name);
/* Check dongle id */
dongle_id = ali_ircc_read_dongle_id(i, info);
- MESSAGE("%s(), %s, Found dongle: %s\n", __FUNCTION__, driver_name, dongle_types[dongle_id]);
+ IRDA_MESSAGE("%s(), %s, Found dongle: %s\n", __FUNCTION__, driver_name, dongle_types[dongle_id]);
self->io.dongle_id = dongle_id;
@@ -391,7 +392,7 @@ static int __exit ali_ircc_close(struct ali_ircc_cb *self)
IRDA_DEBUG(4, "%s(), ---------------- Start ----------------\n", __FUNCTION__);
- ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
iobase = self->io.fir_base;
@@ -489,7 +490,7 @@ static int ali_ircc_probe_53(ali_chip_t *chip, chipio_t *info)
info->dma = reg & 0x07;
if(info->dma == 0x04)
- WARNING("%s(), No DMA channel assigned !\n", __FUNCTION__);
+ IRDA_WARNING("%s(), No DMA channel assigned !\n", __FUNCTION__);
else
IRDA_DEBUG(2, "%s(), probing dma=%d\n", __FUNCTION__, info->dma);
@@ -546,11 +547,11 @@ static int ali_ircc_setup(chipio_t *info)
/* Should be 0x00 in the M1535/M1535D */
if(version != 0x00)
{
- ERROR("%s, Wrong chip version %02x\n", driver_name, version);
+ IRDA_ERROR("%s, Wrong chip version %02x\n", driver_name, version);
return -1;
}
- // MESSAGE("%s, Found chip at base=0x%03x\n", driver_name, info->cfg_base);
+ // IRDA_MESSAGE("%s, Found chip at base=0x%03x\n", driver_name, info->cfg_base);
/* Set FIR FIFO Threshold Register */
switch_bank(iobase, BANK1);
@@ -581,7 +582,7 @@ static int ali_ircc_setup(chipio_t *info)
/* Switch to SIR space */
FIR2SIR(iobase);
- MESSAGE("%s, driver loaded (Benjamin Kong)\n", driver_name);
+ IRDA_MESSAGE("%s, driver loaded (Benjamin Kong)\n", driver_name);
/* Enable receive interrupts */
// outb(UART_IER_RDI, iobase+UART_IER); //benjamin 2000/11/23 01:25PM
@@ -645,7 +646,7 @@ static irqreturn_t ali_ircc_interrupt(int irq, void *dev_id,
IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__);
if (!dev) {
- WARNING("%s: irq %d for unknown device.\n", driver_name, irq);
+ IRDA_WARNING("%s: irq %d for unknown device.\n", driver_name, irq);
return IRQ_NONE;
}
@@ -851,7 +852,7 @@ static void ali_ircc_sir_receive(struct ali_ircc_cb *self)
int iobase;
IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__);
- ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self != NULL, return;);
iobase = self->io.sir_base;
@@ -885,7 +886,7 @@ static void ali_ircc_sir_write_wakeup(struct ali_ircc_cb *self)
int actual = 0;
int iobase;
- ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self != NULL, return;);
IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__ );
@@ -994,7 +995,7 @@ static void ali_ircc_fir_change_speed(struct ali_ircc_cb *priv, __u32 baud)
IRDA_DEBUG(1, "%s(), ---------------- Start ----------------\n", __FUNCTION__ );
- ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self != NULL, return;);
dev = self->netdev;
iobase = self->io.fir_base;
@@ -1035,7 +1036,7 @@ static void ali_ircc_sir_change_speed(struct ali_ircc_cb *priv, __u32 speed)
IRDA_DEBUG(1, "%s(), Setting speed to: %d\n", __FUNCTION__ , speed);
- ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self != NULL, return;);
iobase = self->io.sir_base;
@@ -1315,19 +1316,19 @@ static int ali_ircc_net_open(struct net_device *dev)
IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__ );
- ASSERT(dev != NULL, return -1;);
+ IRDA_ASSERT(dev != NULL, return -1;);
self = (struct ali_ircc_cb *) dev->priv;
- ASSERT(self != NULL, return 0;);
+ IRDA_ASSERT(self != NULL, return 0;);
iobase = self->io.fir_base;
/* Request IRQ and install Interrupt Handler */
if (request_irq(self->io.irq, ali_ircc_interrupt, 0, dev->name, dev))
{
- WARNING("%s, unable to allocate irq=%d\n", driver_name,
- self->io.irq);
+ IRDA_WARNING("%s, unable to allocate irq=%d\n", driver_name,
+ self->io.irq);
return -EAGAIN;
}
@@ -1336,8 +1337,8 @@ static int ali_ircc_net_open(struct net_device *dev)
* failure.
*/
if (request_dma(self->io.dma, dev->name)) {
- WARNING("%s, unable to allocate dma=%d\n", driver_name,
- self->io.dma);
+ IRDA_WARNING("%s, unable to allocate dma=%d\n", driver_name,
+ self->io.dma);
free_irq(self->io.irq, self);
return -EAGAIN;
}
@@ -1376,10 +1377,10 @@ static int ali_ircc_net_close(struct net_device *dev)
IRDA_DEBUG(4, "%s(), ---------------- Start ----------------\n", __FUNCTION__ );
- ASSERT(dev != NULL, return -1;);
+ IRDA_ASSERT(dev != NULL, return -1;);
self = (struct ali_ircc_cb *) dev->priv;
- ASSERT(self != NULL, return 0;);
+ IRDA_ASSERT(self != NULL, return 0;);
/* Stop device */
netif_stop_queue(dev);
@@ -1643,7 +1644,7 @@ static int ali_ircc_dma_xmit_complete(struct ali_ircc_cb *self)
if((inb(iobase+FIR_LSR) & LSR_FRAME_ABORT) == LSR_FRAME_ABORT)
{
- ERROR("%s(), ********* LSR_FRAME_ABORT *********\n", __FUNCTION__);
+ IRDA_ERROR("%s(), ********* LSR_FRAME_ABORT *********\n", __FUNCTION__);
self->stats.tx_errors++;
self->stats.tx_fifo_errors++;
}
@@ -1890,8 +1891,9 @@ static int ali_ircc_dma_receive_complete(struct ali_ircc_cb *self)
skb = dev_alloc_skb(len+1);
if (skb == NULL)
{
- WARNING("%s(), memory squeeze, "
- "dropping frame.\n", __FUNCTION__);
+ IRDA_WARNING("%s(), memory squeeze, "
+ "dropping frame.\n",
+ __FUNCTION__);
self->stats.rx_dropped++;
return FALSE;
@@ -1940,10 +1942,10 @@ static int ali_ircc_sir_hard_xmit(struct sk_buff *skb, struct net_device *dev)
IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__ );
- ASSERT(dev != NULL, return 0;);
+ IRDA_ASSERT(dev != NULL, return 0;);
self = (struct ali_ircc_cb *) dev->priv;
- ASSERT(self != NULL, return 0;);
+ IRDA_ASSERT(self != NULL, return 0;);
iobase = self->io.sir_base;
@@ -2008,11 +2010,11 @@ static int ali_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__ );
- ASSERT(dev != NULL, return -1;);
+ IRDA_ASSERT(dev != NULL, return -1;);
self = dev->priv;
- ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
IRDA_DEBUG(2, "%s(), %s, (cmd=0x%X)\n", __FUNCTION__ , dev->name, cmd);
@@ -2065,7 +2067,7 @@ static int ali_ircc_is_receiving(struct ali_ircc_cb *self)
IRDA_DEBUG(2, "%s(), ---------------- Start -----------------\n", __FUNCTION__ );
- ASSERT(self != NULL, return FALSE;);
+ IRDA_ASSERT(self != NULL, return FALSE;);
spin_lock_irqsave(&self->lock, flags);
@@ -2109,7 +2111,7 @@ static void ali_ircc_suspend(struct ali_ircc_cb *self)
{
IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__ );
- MESSAGE("%s, Suspending\n", driver_name);
+ IRDA_MESSAGE("%s, Suspending\n", driver_name);
if (self->io.suspended)
return;
@@ -2130,7 +2132,7 @@ static void ali_ircc_wakeup(struct ali_ircc_cb *self)
ali_ircc_net_open(self->netdev);
- MESSAGE("%s, Waking up\n", driver_name);
+ IRDA_MESSAGE("%s, Waking up\n", driver_name);
self->io.suspended = 0;
diff --git a/drivers/net/irda/donauboe.c b/drivers/net/irda/donauboe.c
index 0da9d83a9a757..0a08c539c0510 100644
--- a/drivers/net/irda/donauboe.c
+++ b/drivers/net/irda/donauboe.c
@@ -587,9 +587,9 @@ toshoboe_startchip (struct toshoboe_cb *self)
/*Find out where the rings live */
physaddr = virt_to_bus (self->ring);
- ASSERT ((physaddr & 0x3ff) == 0,
- printk (KERN_ERR DRIVER_NAME "ring not correctly aligned\n");
- return;);
+ IRDA_ASSERT ((physaddr & 0x3ff) == 0,
+ printk (KERN_ERR DRIVER_NAME "ring not correctly aligned\n");
+ return;);
OUTB ((physaddr >> 10) & 0xff, OBOE_RING_BASE0);
OUTB ((physaddr >> 18) & 0xff, OBOE_RING_BASE1);
@@ -994,7 +994,7 @@ toshoboe_hard_xmit (struct sk_buff *skb, struct net_device *dev)
self = (struct toshoboe_cb *) dev->priv;
- ASSERT (self != NULL, return 0; );
+ IRDA_ASSERT (self != NULL, return 0; );
IRDA_DEBUG (1, "%s.tx:%x(%x)%x\n", __FUNCTION__
,skb->len,self->txpending,INB (OBOE_ENABLEH));
@@ -1360,10 +1360,10 @@ toshoboe_net_open (struct net_device *dev)
IRDA_DEBUG (4, "%s()\n", __FUNCTION__);
- ASSERT (dev != NULL, return -1; );
+ IRDA_ASSERT (dev != NULL, return -1; );
self = (struct toshoboe_cb *) dev->priv;
- ASSERT (self != NULL, return 0; );
+ IRDA_ASSERT (self != NULL, return 0; );
if (self->async)
return -EBUSY;
@@ -1402,7 +1402,7 @@ toshoboe_net_close (struct net_device *dev)
IRDA_DEBUG (4, "%s()\n", __FUNCTION__);
- ASSERT (dev != NULL, return -1; );
+ IRDA_ASSERT (dev != NULL, return -1; );
self = (struct toshoboe_cb *) dev->priv;
/* Stop device */
@@ -1439,11 +1439,11 @@ toshoboe_net_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
unsigned long flags;
int ret = 0;
- ASSERT (dev != NULL, return -1; );
+ IRDA_ASSERT (dev != NULL, return -1; );
self = dev->priv;
- ASSERT (self != NULL, return -1; );
+ IRDA_ASSERT (self != NULL, return -1; );
IRDA_DEBUG (5, "%s(), %s, (cmd=0x%X)\n", __FUNCTION__, dev->name, cmd);
@@ -1509,7 +1509,7 @@ toshoboe_close (struct pci_dev *pci_dev)
IRDA_DEBUG (4, "%s()\n", __FUNCTION__);
- ASSERT (self != NULL, return; );
+ IRDA_ASSERT (self != NULL, return; );
if (!self->stopped)
{
@@ -1712,7 +1712,7 @@ freeself:
}
static int
-toshoboe_gotosleep (struct pci_dev *pci_dev, u32 crap)
+toshoboe_gotosleep (struct pci_dev *pci_dev, pm_message_t crap)
{
struct toshoboe_cb *self = (struct toshoboe_cb*)pci_get_drvdata(pci_dev);
unsigned long flags;
diff --git a/drivers/net/irda/girbil-sir.c b/drivers/net/irda/girbil-sir.c
index d3c56ee64345f..0d2fe87fb9b78 100644
--- a/drivers/net/irda/girbil-sir.c
+++ b/drivers/net/irda/girbil-sir.c
@@ -179,7 +179,7 @@ static int girbil_change_speed(struct sir_dev *dev, unsigned speed)
break;
default:
- ERROR("%s - undefined state %d\n", __FUNCTION__, state);
+ IRDA_ERROR("%s - undefined state %d\n", __FUNCTION__, state);
ret = -EINVAL;
break;
}
@@ -241,7 +241,7 @@ static int girbil_reset(struct sir_dev *dev)
break;
default:
- ERROR("%s(), undefined state %d\n", __FUNCTION__, state);
+ IRDA_ERROR("%s(), undefined state %d\n", __FUNCTION__, state);
ret = -1;
break;
}
diff --git a/drivers/net/irda/girbil.c b/drivers/net/irda/girbil.c
index ecac87df93f2b..248aeb0c726ca 100644
--- a/drivers/net/irda/girbil.c
+++ b/drivers/net/irda/girbil.c
@@ -123,7 +123,8 @@ static int girbil_change_speed(struct irda_task *task)
}
break;
case IRDA_TASK_CHILD_WAIT:
- WARNING("%s(), resetting dongle timed out!\n", __FUNCTION__);
+ IRDA_WARNING("%s(), resetting dongle timed out!\n",
+ __FUNCTION__);
ret = -1;
break;
case IRDA_TASK_CHILD_DONE:
@@ -162,7 +163,8 @@ static int girbil_change_speed(struct irda_task *task)
self->speed_task = NULL;
break;
default:
- ERROR("%s(), unknown state %d\n", __FUNCTION__, task->state);
+ IRDA_ERROR("%s(), unknown state %d\n",
+ __FUNCTION__, task->state);
irda_task_next_state(task, IRDA_TASK_DONE);
self->speed_task = NULL;
ret = -1;
@@ -215,7 +217,8 @@ static int girbil_reset(struct irda_task *task)
self->reset_task = NULL;
break;
default:
- ERROR("%s(), unknown state %d\n", __FUNCTION__, task->state);
+ IRDA_ERROR("%s(), unknown state %d\n",
+ __FUNCTION__, task->state);
irda_task_next_state(task, IRDA_TASK_DONE);
self->reset_task = NULL;
ret = -1;
diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c
index 9e93080d2a13b..46e0022d3258a 100644
--- a/drivers/net/irda/irda-usb.c
+++ b/drivers/net/irda/irda-usb.c
@@ -251,7 +251,7 @@ static void irda_usb_change_speed_xbofs(struct irda_usb_cb *self)
/* Grab the speed URB */
urb = self->speed_urb;
if (urb->status != 0) {
- WARNING("%s(), URB still in use!\n", __FUNCTION__);
+ IRDA_WARNING("%s(), URB still in use!\n", __FUNCTION__);
return;
}
@@ -271,7 +271,7 @@ static void irda_usb_change_speed_xbofs(struct irda_usb_cb *self)
/* Irq disabled -> GFP_ATOMIC */
if ((ret = usb_submit_urb(urb, GFP_ATOMIC))) {
- WARNING("%s(), failed Speed URB\n", __FUNCTION__);
+ IRDA_WARNING("%s(), failed Speed URB\n", __FUNCTION__);
}
}
@@ -287,9 +287,9 @@ static void speed_bulk_callback(struct urb *urb, struct pt_regs *regs)
IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
/* We should always have a context */
- ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self != NULL, return;);
/* We should always be called for the speed URB */
- ASSERT(urb == self->speed_urb, return;);
+ IRDA_ASSERT(urb == self->speed_urb, return;);
/* Check for timeout and other USB nasties */
if (urb->status != 0) {
@@ -374,7 +374,7 @@ static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *netdev)
}
if (urb->status != 0) {
- WARNING("%s(), URB still in use!\n", __FUNCTION__);
+ IRDA_WARNING("%s(), URB still in use!\n", __FUNCTION__);
goto drop;
}
@@ -385,7 +385,7 @@ static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *netdev)
if (skb_headroom(skb) < USB_IRDA_HEADER) {
IRDA_DEBUG(0, "%s(), Insuficient skb headroom.\n", __FUNCTION__);
if (skb_cow(skb, USB_IRDA_HEADER)) {
- WARNING("%s(), failed skb_cow() !!!\n", __FUNCTION__);
+ IRDA_WARNING("%s(), failed skb_cow() !!!\n", __FUNCTION__);
goto drop;
}
}
@@ -457,7 +457,7 @@ static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *netdev)
/* Ask USB to send the packet - Irq disabled -> GFP_ATOMIC */
if ((res = usb_submit_urb(urb, GFP_ATOMIC))) {
- WARNING("%s(), failed Tx URB\n", __FUNCTION__);
+ IRDA_WARNING("%s(), failed Tx URB\n", __FUNCTION__);
self->stats.tx_errors++;
/* Let USB recover : We will catch that in the watchdog */
/*netif_start_queue(netdev);*/
@@ -492,9 +492,9 @@ static void write_bulk_callback(struct urb *urb, struct pt_regs *regs)
IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
/* We should always have a context */
- ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self != NULL, return;);
/* We should always be called for the speed URB */
- ASSERT(urb == self->tx_urb, return;);
+ IRDA_ASSERT(urb == self->tx_urb, return;);
/* Free up the skb */
dev_kfree_skb_any(skb);
@@ -566,14 +566,14 @@ static void irda_usb_net_timeout(struct net_device *netdev)
int done = 0; /* If we have made any progress */
IRDA_DEBUG(0, "%s(), Network layer thinks we timed out!\n", __FUNCTION__);
- ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self != NULL, return;);
/* Protect us from USB callbacks, net Tx and else. */
spin_lock_irqsave(&self->lock, flags);
/* self->present *MUST* be read under spinlock */
if (!self->present) {
- WARNING("%s(), device not present!\n", __FUNCTION__);
+ IRDA_WARNING("%s(), device not present!\n", __FUNCTION__);
netif_stop_queue(netdev);
spin_unlock_irqrestore(&self->lock, flags);
return;
@@ -699,8 +699,8 @@ static void irda_usb_submit(struct irda_usb_cb *self, struct sk_buff *skb, struc
IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
/* This should never happen */
- ASSERT(skb != NULL, return;);
- ASSERT(urb != NULL, return;);
+ IRDA_ASSERT(skb != NULL, return;);
+ IRDA_ASSERT(urb != NULL, return;);
/* Save ourselves in the skb */
cb = (struct irda_skb_cb *) skb->cb;
@@ -720,7 +720,8 @@ static void irda_usb_submit(struct irda_usb_cb *self, struct sk_buff *skb, struc
if (ret) {
/* If this ever happen, we are in deep s***.
* Basically, the Rx path will stop... */
- WARNING("%s(), Failed to submit Rx URB %d\n", __FUNCTION__, ret);
+ IRDA_WARNING("%s(), Failed to submit Rx URB %d\n",
+ __FUNCTION__, ret);
}
}
@@ -744,9 +745,9 @@ static void irda_usb_receive(struct urb *urb, struct pt_regs *regs)
/* Find ourselves */
cb = (struct irda_skb_cb *) skb->cb;
- ASSERT(cb != NULL, return;);
+ IRDA_ASSERT(cb != NULL, return;);
self = (struct irda_usb_cb *) cb->context;
- ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self != NULL, return;);
/* If the network is closed or the device gone, stop everything */
if ((!self->netopen) || (!self->present)) {
@@ -777,7 +778,7 @@ static void irda_usb_receive(struct urb *urb, struct pt_regs *regs)
/* Check for empty frames */
if (urb->actual_length <= USB_IRDA_HEADER) {
- WARNING("%s(), empty frame!\n", __FUNCTION__);
+ IRDA_WARNING("%s(), empty frame!\n", __FUNCTION__);
goto done;
}
@@ -910,13 +911,13 @@ static int irda_usb_net_open(struct net_device *netdev)
IRDA_DEBUG(1, "%s()\n", __FUNCTION__);
- ASSERT(netdev != NULL, return -1;);
+ IRDA_ASSERT(netdev != NULL, return -1;);
self = (struct irda_usb_cb *) netdev->priv;
- ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
/* Can only open the device if it's there */
if(!self->present) {
- WARNING("%s(), device not present!\n", __FUNCTION__);
+ IRDA_WARNING("%s(), device not present!\n", __FUNCTION__);
return -1;
}
@@ -938,7 +939,7 @@ static int irda_usb_net_open(struct net_device *netdev)
*/
sprintf(hwname, "usb#%d", self->usbdev->devnum);
self->irlap = irlap_open(netdev, &self->qos, hwname);
- ASSERT(self->irlap != NULL, return -1;);
+ IRDA_ASSERT(self->irlap != NULL, return -1;);
/* Allow IrLAP to send data to us */
netif_start_queue(netdev);
@@ -957,7 +958,8 @@ static int irda_usb_net_open(struct net_device *netdev)
if (!skb) {
/* If this ever happen, we are in deep s***.
* Basically, we can't start the Rx path... */
- WARNING("%s(), Failed to allocate Rx skb\n", __FUNCTION__);
+ IRDA_WARNING("%s(), Failed to allocate Rx skb\n",
+ __FUNCTION__);
return -1;
}
//skb_reserve(newskb, USB_IRDA_HEADER - 1);
@@ -982,9 +984,9 @@ static int irda_usb_net_close(struct net_device *netdev)
IRDA_DEBUG(1, "%s()\n", __FUNCTION__);
- ASSERT(netdev != NULL, return -1;);
+ IRDA_ASSERT(netdev != NULL, return -1;);
self = (struct irda_usb_cb *) netdev->priv;
- ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
/* Clear this flag *before* unlinking the urbs and *before*
* stopping the network Tx queue - Jean II */
@@ -998,7 +1000,7 @@ static int irda_usb_net_close(struct net_device *netdev)
struct urb *urb = self->rx_urb[i];
struct sk_buff *skb = (struct sk_buff *) urb->context;
/* Cancel the receive command */
- usb_unlink_urb(urb);
+ usb_kill_urb(urb);
/* The skb is ours, free it */
if(skb) {
dev_kfree_skb(skb);
@@ -1030,9 +1032,9 @@ static int irda_usb_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
struct irda_usb_cb *self;
int ret = 0;
- ASSERT(dev != NULL, return -1;);
+ IRDA_ASSERT(dev != NULL, return -1;);
self = dev->priv;
- ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
IRDA_DEBUG(2, "%s(), %s, (cmd=0x%X)\n", __FUNCTION__, dev->name, cmd);
@@ -1239,7 +1241,7 @@ static inline int irda_usb_parse_endpoints(struct irda_usb_cb *self, struct usb_
/* This is our interrupt endpoint */
self->bulk_int_ep = ep;
} else {
- ERROR("%s(), Unrecognised endpoint %02X.\n", __FUNCTION__, ep);
+ IRDA_ERROR("%s(), Unrecognised endpoint %02X.\n", __FUNCTION__, ep);
}
}
}
@@ -1247,7 +1249,7 @@ static inline int irda_usb_parse_endpoints(struct irda_usb_cb *self, struct usb_
IRDA_DEBUG(0, "%s(), And our endpoints are : in=%02X, out=%02X (%d), int=%02X\n",
__FUNCTION__, self->bulk_in_ep, self->bulk_out_ep, self->bulk_out_mtu, self->bulk_int_ep);
/* Should be 8, 16, 32 or 64 bytes */
- ASSERT(self->bulk_out_mtu == 64, ;);
+ IRDA_ASSERT(self->bulk_out_mtu == 64, ;);
return((self->bulk_in_ep != 0) && (self->bulk_out_ep != 0));
}
@@ -1308,15 +1310,15 @@ static inline struct irda_class_desc *irda_usb_find_class_desc(struct usb_interf
IU_REQ_GET_CLASS_DESC,
USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
0, intf->altsetting->desc.bInterfaceNumber, desc,
- sizeof(*desc), msecs_to_jiffies(500));
+ sizeof(*desc), 500);
IRDA_DEBUG(1, "%s(), ret=%d\n", __FUNCTION__, ret);
if (ret < sizeof(*desc)) {
- WARNING("usb-irda: class_descriptor read %s (%d)\n",
- (ret<0) ? "failed" : "too short", ret);
+ IRDA_WARNING("usb-irda: class_descriptor read %s (%d)\n",
+ (ret<0) ? "failed" : "too short", ret);
}
else if (desc->bDescriptorType != USB_DT_IRDA) {
- WARNING("usb-irda: bad class_descriptor type\n");
+ IRDA_WARNING("usb-irda: bad class_descriptor type\n");
}
else {
#ifdef IU_DUMP_CLASS_DESC
@@ -1359,20 +1361,20 @@ static int irda_usb_probe(struct usb_interface *intf,
* don't need to check if the dongle is really ours.
* Jean II */
- MESSAGE("IRDA-USB found at address %d, Vendor: %x, Product: %x\n",
- dev->devnum, le16_to_cpu(dev->descriptor.idVendor),
- le16_to_cpu(dev->descriptor.idProduct));
+ IRDA_MESSAGE("IRDA-USB found at address %d, Vendor: %x, Product: %x\n",
+ dev->devnum, le16_to_cpu(dev->descriptor.idVendor),
+ le16_to_cpu(dev->descriptor.idProduct));
net = alloc_irdadev(sizeof(*self));
if (!net)
goto err_out;
+ SET_MODULE_OWNER(net);
+ SET_NETDEV_DEV(net, &intf->dev);
self = net->priv;
self->netdev = net;
spin_lock_init(&self->lock);
- SET_MODULE_OWNER(net);
-
/* Create all of the needed urbs */
for (i = 0; i < IU_MAX_RX_URBS; i++) {
self->rx_urb[i] = usb_alloc_urb(0, GFP_KERNEL);
@@ -1421,7 +1423,7 @@ static int irda_usb_probe(struct usb_interface *intf,
interface = intf->cur_altsetting;
if(!irda_usb_parse_endpoints(self, interface->endpoint,
interface->desc.bNumEndpoints)) {
- ERROR("%s(), Bogus endpoints...\n", __FUNCTION__);
+ IRDA_ERROR("%s(), Bogus endpoints...\n", __FUNCTION__);
ret = -EIO;
goto err_out_3;
}
@@ -1453,7 +1455,7 @@ static int irda_usb_probe(struct usb_interface *intf,
if (ret)
goto err_out_4;
- MESSAGE("IrDA: Registered device %s\n", net->name);
+ IRDA_MESSAGE("IrDA: Registered device %s\n", net->name);
usb_set_intfdata(intf, self);
return 0;
@@ -1516,7 +1518,7 @@ static void irda_usb_disconnect(struct usb_interface *intf)
netif_stop_queue(self->netdev);
/* Stop all the receive URBs */
for (i = 0; i < IU_MAX_RX_URBS; i++)
- usb_unlink_urb(self->rx_urb[i]);
+ usb_kill_urb(self->rx_urb[i]);
/* Cancel Tx and speed URB.
* Toggle flags to make sure it's synchronous. */
self->tx_urb->transfer_flags &= ~URB_ASYNC_UNLINK;
@@ -1573,7 +1575,7 @@ static int __init usb_irda_init(void)
if (ret < 0)
return ret;
- MESSAGE("USB IrDA support registered\n");
+ IRDA_MESSAGE("USB IrDA support registered\n");
return 0;
}
module_init(usb_irda_init);
diff --git a/drivers/net/irda/irport.c b/drivers/net/irda/irport.c
index c2c26b605357a..5971315f3fa0c 100644
--- a/drivers/net/irda/irport.c
+++ b/drivers/net/irda/irport.c
@@ -87,50 +87,14 @@ static struct net_device_stats *irport_net_get_stats(struct net_device *dev);
static int irport_change_speed_complete(struct irda_task *task);
static void irport_timeout(struct net_device *dev);
-EXPORT_SYMBOL(irport_open);
-EXPORT_SYMBOL(irport_close);
-EXPORT_SYMBOL(irport_start);
-EXPORT_SYMBOL(irport_stop);
-EXPORT_SYMBOL(irport_interrupt);
-EXPORT_SYMBOL(irport_hard_xmit);
-EXPORT_SYMBOL(irport_timeout);
-EXPORT_SYMBOL(irport_change_speed);
-EXPORT_SYMBOL(irport_net_open);
-EXPORT_SYMBOL(irport_net_close);
-
-static int __init irport_init(void)
-{
- int i;
-
- for (i=0; (io[i] < 2000) && (i < 4); i++) {
- if (irport_open(i, io[i], irq[i]) != NULL)
- return 0;
- }
- /*
- * Maybe something failed, but we can still be usable for FIR drivers
- */
- return 0;
-}
-
-/*
- * Function irport_cleanup ()
- *
- * Close all configured ports
- *
- */
-static void __exit irport_cleanup(void)
-{
- int i;
-
- IRDA_DEBUG( 4, "%s()\n", __FUNCTION__);
-
- for (i=0; i < 4; i++) {
- if (dev_self[i])
- irport_close(dev_self[i]);
- }
-}
-
-struct irport_cb *
+static irqreturn_t irport_interrupt(int irq, void *dev_id,
+ struct pt_regs *regs);
+static int irport_hard_xmit(struct sk_buff *skb, struct net_device *dev);
+static void irport_change_speed(void *priv, __u32 speed);
+static int irport_net_open(struct net_device *dev);
+static int irport_net_close(struct net_device *dev);
+
+static struct irport_cb *
irport_open(int i, unsigned int iobase, unsigned int irq)
{
struct net_device *dev;
@@ -150,8 +114,8 @@ irport_open(int i, unsigned int iobase, unsigned int irq)
*/
dev = alloc_irdadev(sizeof(struct irport_cb));
if (!dev) {
- ERROR("%s(), can't allocate memory for "
- "irda device!\n", __FUNCTION__);
+ IRDA_ERROR("%s(), can't allocate memory for "
+ "irda device!\n", __FUNCTION__);
goto err_out2;
}
@@ -183,8 +147,8 @@ irport_open(int i, unsigned int iobase, unsigned int irq)
self->rx_buff.skb = __dev_alloc_skb(self->rx_buff.truesize,
GFP_KERNEL);
if (self->rx_buff.skb == NULL) {
- ERROR("%s(), can't allocate memory for "
- "receive buffer!\n", __FUNCTION__);
+ IRDA_ERROR("%s(), can't allocate memory for "
+ "receive buffer!\n", __FUNCTION__);
goto err_out3;
}
skb_reserve(self->rx_buff.skb, 1);
@@ -204,8 +168,8 @@ irport_open(int i, unsigned int iobase, unsigned int irq)
self->tx_buff.head = (__u8 *) kmalloc(self->tx_buff.truesize,
GFP_KERNEL);
if (self->tx_buff.head == NULL) {
- ERROR("%s(), can't allocate memory for "
- "transmit buffer!\n", __FUNCTION__);
+ IRDA_ERROR("%s(), can't allocate memory for "
+ "transmit buffer!\n", __FUNCTION__);
goto err_out4;
}
memset(self->tx_buff.head, 0, self->tx_buff.truesize);
@@ -234,10 +198,10 @@ irport_open(int i, unsigned int iobase, unsigned int irq)
dev->irq = irq;
if (register_netdev(dev)) {
- ERROR("%s(), register_netdev() failed!\n", __FUNCTION__);
+ IRDA_ERROR("%s(), register_netdev() failed!\n", __FUNCTION__);
goto err_out5;
}
- MESSAGE("IrDA: Registered device %s (irport io=0x%X irq=%d)\n",
+ IRDA_MESSAGE("IrDA: Registered device %s (irport io=0x%X irq=%d)\n",
dev->name, iobase, irq);
return self;
@@ -254,9 +218,9 @@ irport_open(int i, unsigned int iobase, unsigned int irq)
return NULL;
}
-int irport_close(struct irport_cb *self)
+static int irport_close(struct irport_cb *self)
{
- ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
/* We are not using any dongle anymore! */
if (self->dongle)
@@ -285,40 +249,40 @@ int irport_close(struct irport_cb *self)
return 0;
}
-void irport_start(struct irport_cb *self)
+static void irport_stop(struct irport_cb *self)
{
int iobase;
iobase = self->io.sir_base;
- irport_stop(self);
-
/* We can't lock, we may be called from a FIR driver - Jean II */
- /* Initialize UART */
- outb(UART_LCR_WLEN8, iobase+UART_LCR); /* Reset DLAB */
- outb((UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2), iobase+UART_MCR);
+ /* We are not transmitting any more */
+ self->transmitting = 0;
+
+ /* Reset UART */
+ outb(0, iobase+UART_MCR);
- /* Turn on interrups */
- outb(UART_IER_RLSI | UART_IER_RDI |UART_IER_THRI, iobase+UART_IER);
+ /* Turn off interrupts */
+ outb(0, iobase+UART_IER);
}
-void irport_stop(struct irport_cb *self)
+static void irport_start(struct irport_cb *self)
{
int iobase;
iobase = self->io.sir_base;
+ irport_stop(self);
+
/* We can't lock, we may be called from a FIR driver - Jean II */
- /* We are not transmitting any more */
- self->transmitting = 0;
-
- /* Reset UART */
- outb(0, iobase+UART_MCR);
+ /* Initialize UART */
+ outb(UART_LCR_WLEN8, iobase+UART_LCR); /* Reset DLAB */
+ outb((UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2), iobase+UART_MCR);
- /* Turn off interrupts */
- outb(0, iobase+UART_IER);
+ /* Turn on interrups */
+ outb(UART_IER_RLSI | UART_IER_RDI |UART_IER_THRI, iobase+UART_IER);
}
/*
@@ -368,7 +332,7 @@ static inline unsigned int irport_get_fcr(__u32 speed)
*
* This function should be called with irq off and spin-lock.
*/
-void irport_change_speed(void *priv, __u32 speed)
+static void irport_change_speed(void *priv, __u32 speed)
{
struct irport_cb *self = (struct irport_cb *) priv;
int iobase;
@@ -376,8 +340,8 @@ void irport_change_speed(void *priv, __u32 speed)
unsigned int lcr; /* Line control reg */
int divisor;
- ASSERT(self != NULL, return;);
- ASSERT(speed != 0, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(speed != 0, return;);
IRDA_DEBUG(1, "%s(), Setting speed to: %d - iobase=%#x\n",
__FUNCTION__, speed, self->io.sir_base);
@@ -431,7 +395,7 @@ int __irport_change_speed(struct irda_task *task)
self = (struct irport_cb *) task->instance;
- ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
/* Locking notes : this function may be called from irq context with
* spinlock, via irport_write_wakeup(), or from non-interrupt without
@@ -480,7 +444,7 @@ int __irport_change_speed(struct irda_task *task)
irda_task_next_state(task, IRDA_TASK_CHILD_DONE);
break;
case IRDA_TASK_CHILD_WAIT:
- WARNING("%s(), changing speed of dongle timed out!\n", __FUNCTION__);
+ IRDA_WARNING("%s(), changing speed of dongle timed out!\n", __FUNCTION__);
ret = -1;
break;
case IRDA_TASK_CHILD_DONE:
@@ -490,7 +454,8 @@ int __irport_change_speed(struct irda_task *task)
irda_task_next_state(task, IRDA_TASK_DONE);
break;
default:
- ERROR("%s(), unknown state %d\n", __FUNCTION__, task->state);
+ IRDA_ERROR("%s(), unknown state %d\n",
+ __FUNCTION__, task->state);
irda_task_next_state(task, IRDA_TASK_DONE);
ret = -1;
break;
@@ -517,8 +482,8 @@ static int irport_change_speed_complete(struct irda_task *task)
self = (struct irport_cb *) task->instance;
- ASSERT(self != NULL, return -1;);
- ASSERT(self->netdev != NULL, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->netdev != NULL, return -1;);
/* Finished changing speed, so we are not busy any longer */
/* Signal network layer so it can try to send the frame */
@@ -543,10 +508,10 @@ static void irport_timeout(struct net_device *dev)
unsigned long flags;
self = (struct irport_cb *) dev->priv;
- ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self != NULL, return;);
iobase = self->io.sir_base;
- WARNING("%s: transmit timed out, jiffies = %ld, trans_start = %ld\n",
+ IRDA_WARNING("%s: transmit timed out, jiffies = %ld, trans_start = %ld\n",
dev->name, jiffies, dev->trans_start);
spin_lock_irqsave(&self->lock, flags);
@@ -619,7 +584,7 @@ static void irport_wait_hw_transmitter_finish(struct irport_cb *self)
* waits until the next transmitt interrupt, and continues until the
* frame is transmitted.
*/
-int irport_hard_xmit(struct sk_buff *skb, struct net_device *dev)
+static int irport_hard_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct irport_cb *self;
unsigned long flags;
@@ -628,10 +593,10 @@ int irport_hard_xmit(struct sk_buff *skb, struct net_device *dev)
IRDA_DEBUG(1, "%s()\n", __FUNCTION__);
- ASSERT(dev != NULL, return 0;);
+ IRDA_ASSERT(dev != NULL, return 0;);
self = (struct irport_cb *) dev->priv;
- ASSERT(self != NULL, return 0;);
+ IRDA_ASSERT(self != NULL, return 0;);
iobase = self->io.sir_base;
@@ -728,7 +693,7 @@ static inline void irport_write_wakeup(struct irport_cb *self)
int iobase;
unsigned int fcr;
- ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self != NULL, return;);
IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
@@ -789,7 +754,7 @@ static inline void irport_receive(struct irport_cb *self)
int boguscount = 0;
int iobase;
- ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self != NULL, return;);
iobase = self->io.sir_base;
@@ -814,7 +779,8 @@ static inline void irport_receive(struct irport_cb *self)
*
* Interrupt handler
*/
-irqreturn_t irport_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t irport_interrupt(int irq, void *dev_id,
+ struct pt_regs *regs)
{
struct net_device *dev = (struct net_device *) dev_id;
struct irport_cb *self;
@@ -824,7 +790,7 @@ irqreturn_t irport_interrupt(int irq, void *dev_id, struct pt_regs *regs)
int handled = 0;
if (!dev) {
- WARNING("%s() irq %d for unknown device.\n", __FUNCTION__, irq);
+ IRDA_WARNING("%s() irq %d for unknown device.\n", __FUNCTION__, irq);
return IRQ_NONE;
}
self = (struct irport_cb *) dev->priv;
@@ -861,8 +827,8 @@ irqreturn_t irport_interrupt(int irq, void *dev_id, struct pt_regs *regs)
/* Make sure we don't stay here to long */
if (boguscount++ > 10) {
- WARNING("%s() irq handler looping : lsr=%02x\n",
- __FUNCTION__, lsr);
+ IRDA_WARNING("%s() irq handler looping : lsr=%02x\n",
+ __FUNCTION__, lsr);
break;
}
@@ -888,7 +854,7 @@ irqreturn_t irport_interrupt(int irq, void *dev_id, struct pt_regs *regs)
* Network device is taken up. Usually this is done by "ifconfig irda0 up"
*
*/
-int irport_net_open(struct net_device *dev)
+static int irport_net_open(struct net_device *dev)
{
struct irport_cb *self;
int iobase;
@@ -897,7 +863,7 @@ int irport_net_open(struct net_device *dev)
IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
- ASSERT(dev != NULL, return -1;);
+ IRDA_ASSERT(dev != NULL, return -1;);
self = (struct irport_cb *) dev->priv;
iobase = self->io.sir_base;
@@ -941,7 +907,7 @@ int irport_net_open(struct net_device *dev)
* Network device is taken down. Usually this is done by
* "ifconfig irda0 down"
*/
-int irport_net_close(struct net_device *dev)
+static int irport_net_close(struct net_device *dev)
{
struct irport_cb *self;
int iobase;
@@ -949,10 +915,10 @@ int irport_net_close(struct net_device *dev)
IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
- ASSERT(dev != NULL, return -1;);
+ IRDA_ASSERT(dev != NULL, return -1;);
self = (struct irport_cb *) dev->priv;
- ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
iobase = self->io.sir_base;
@@ -995,7 +961,7 @@ static int irport_set_dtr_rts(struct net_device *dev, int dtr, int rts)
struct irport_cb *self = dev->priv;
int iobase;
- ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
iobase = self->io.sir_base;
@@ -1015,7 +981,7 @@ static int irport_raw_write(struct net_device *dev, __u8 *buf, int len)
int actual = 0;
int iobase;
- ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
iobase = self->io.sir_base;
@@ -1049,11 +1015,11 @@ static int irport_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
unsigned long flags;
int ret = 0;
- ASSERT(dev != NULL, return -1;);
+ IRDA_ASSERT(dev != NULL, return -1;);
self = dev->priv;
- ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
IRDA_DEBUG(2, "%s(), %s, (cmd=0x%X)\n", __FUNCTION__, dev->name, cmd);
@@ -1134,6 +1100,38 @@ static struct net_device_stats *irport_net_get_stats(struct net_device *dev)
return &self->stats;
}
+static int __init irport_init(void)
+{
+ int i;
+
+ for (i=0; (io[i] < 2000) && (i < 4); i++) {
+ if (irport_open(i, io[i], irq[i]) != NULL)
+ return 0;
+ }
+ /*
+ * Maybe something failed, but we can still be usable for FIR drivers
+ */
+ return 0;
+}
+
+/*
+ * Function irport_cleanup ()
+ *
+ * Close all configured ports
+ *
+ */
+static void __exit irport_cleanup(void)
+{
+ int i;
+
+ IRDA_DEBUG( 4, "%s()\n", __FUNCTION__);
+
+ for (i=0; i < 4; i++) {
+ if (dev_self[i])
+ irport_close(dev_self[i]);
+ }
+}
+
MODULE_PARM(io, "1-4i");
MODULE_PARM_DESC(io, "Base I/O addresses");
MODULE_PARM(irq, "1-4i");
diff --git a/drivers/net/irda/irport.h b/drivers/net/irda/irport.h
index 991f956c096cf..fc89c8c3dd7f6 100644
--- a/drivers/net/irda/irport.h
+++ b/drivers/net/irda/irport.h
@@ -77,14 +77,4 @@ struct irport_cb {
int (*interrupt)(int irq, void *dev_id, struct pt_regs *regs);
};
-struct irport_cb *irport_open(int i, unsigned int iobase, unsigned int irq);
-int irport_close(struct irport_cb *self);
-void irport_start(struct irport_cb *self);
-void irport_stop(struct irport_cb *self);
-void irport_change_speed(void *priv, __u32 speed);
-irqreturn_t irport_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-int irport_hard_xmit(struct sk_buff *skb, struct net_device *dev);
-int irport_net_open(struct net_device *dev);
-int irport_net_close(struct net_device *dev);
-
#endif /* IRPORT_H */
diff --git a/drivers/net/irda/irtty-sir.c b/drivers/net/irda/irtty-sir.c
index d865375d7a4d9..7d23aa3759089 100644
--- a/drivers/net/irda/irtty-sir.c
+++ b/drivers/net/irda/irtty-sir.c
@@ -32,6 +32,7 @@
#include <linux/init.h>
#include <asm/uaccess.h>
#include <linux/smp_lock.h>
+#include <linux/delay.h>
#include <net/irda/irda.h>
#include <net/irda/irda_device.h>
@@ -59,8 +60,8 @@ static int irtty_chars_in_buffer(struct sir_dev *dev)
{
struct sirtty_cb *priv = dev->priv;
- ASSERT(priv != NULL, return -1;);
- ASSERT(priv->magic == IRTTY_MAGIC, return -1;);
+ IRDA_ASSERT(priv != NULL, return -1;);
+ IRDA_ASSERT(priv->magic == IRTTY_MAGIC, return -1;);
return priv->tty->driver->chars_in_buffer(priv->tty);
}
@@ -87,8 +88,8 @@ static void irtty_wait_until_sent(struct sir_dev *dev)
struct sirtty_cb *priv = dev->priv;
struct tty_struct *tty;
- ASSERT(priv != NULL, return;);
- ASSERT(priv->magic == IRTTY_MAGIC, return;);
+ IRDA_ASSERT(priv != NULL, return;);
+ IRDA_ASSERT(priv->magic == IRTTY_MAGIC, return;);
tty = priv->tty;
if (tty->driver->wait_until_sent) {
@@ -97,8 +98,7 @@ static void irtty_wait_until_sent(struct sir_dev *dev)
unlock_kernel();
}
else {
- set_task_state(current, TASK_UNINTERRUPTIBLE);
- schedule_timeout(msecs_to_jiffies(USBSERIAL_TX_DONE_DELAY));
+ msleep(USBSERIAL_TX_DONE_DELAY);
}
}
@@ -119,8 +119,8 @@ static int irtty_change_speed(struct sir_dev *dev, unsigned speed)
struct termios old_termios;
int cflag;
- ASSERT(priv != NULL, return -1;);
- ASSERT(priv->magic == IRTTY_MAGIC, return -1;);
+ IRDA_ASSERT(priv != NULL, return -1;);
+ IRDA_ASSERT(priv->magic == IRTTY_MAGIC, return -1;);
tty = priv->tty;
@@ -183,8 +183,8 @@ static int irtty_set_dtr_rts(struct sir_dev *dev, int dtr, int rts)
int set = 0;
int clear = 0;
- ASSERT(priv != NULL, return -1;);
- ASSERT(priv->magic == IRTTY_MAGIC, return -1;);
+ IRDA_ASSERT(priv != NULL, return -1;);
+ IRDA_ASSERT(priv->magic == IRTTY_MAGIC, return -1;);
if (rts)
set |= TIOCM_RTS;
@@ -201,7 +201,7 @@ static int irtty_set_dtr_rts(struct sir_dev *dev, int dtr, int rts)
* This function is not yet defined for all tty driver, so
* let's be careful... Jean II
*/
- ASSERT(priv->tty->driver->tiocmset != NULL, return -1;);
+ IRDA_ASSERT(priv->tty->driver->tiocmset != NULL, return -1;);
priv->tty->driver->tiocmset(priv->tty, NULL, set, clear);
return 0;
@@ -220,8 +220,8 @@ static int irtty_do_write(struct sir_dev *dev, const unsigned char *ptr, size_t
struct tty_struct *tty;
int writelen;
- ASSERT(priv != NULL, return -1;);
- ASSERT(priv->magic == IRTTY_MAGIC, return -1;);
+ IRDA_ASSERT(priv != NULL, return -1;);
+ IRDA_ASSERT(priv->magic == IRTTY_MAGIC, return -1;);
tty = priv->tty;
if (!tty->driver->write)
@@ -262,15 +262,15 @@ static void irtty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
struct sirtty_cb *priv = tty->disc_data;
int i;
- ASSERT(priv != NULL, return;);
- ASSERT(priv->magic == IRTTY_MAGIC, return;);
+ IRDA_ASSERT(priv != NULL, return;);
+ IRDA_ASSERT(priv->magic == IRTTY_MAGIC, return;);
if (unlikely(count==0)) /* yes, this happens */
return;
dev = priv->dev;
if (!dev) {
- WARNING("%s(), not ready yet!\n", __FUNCTION__);
+ IRDA_WARNING("%s(), not ready yet!\n", __FUNCTION__);
return;
}
@@ -298,8 +298,8 @@ static int irtty_receive_room(struct tty_struct *tty)
{
struct sirtty_cb *priv = tty->disc_data;
- ASSERT(priv != NULL, return 0;);
- ASSERT(priv->magic == IRTTY_MAGIC, return 0;);
+ IRDA_ASSERT(priv != NULL, return 0;);
+ IRDA_ASSERT(priv->magic == IRTTY_MAGIC, return 0;);
return 65536; /* We can handle an infinite amount of data. :-) */
}
@@ -315,8 +315,8 @@ static void irtty_write_wakeup(struct tty_struct *tty)
{
struct sirtty_cb *priv = tty->disc_data;
- ASSERT(priv != NULL, return;);
- ASSERT(priv->magic == IRTTY_MAGIC, return;);
+ IRDA_ASSERT(priv != NULL, return;);
+ IRDA_ASSERT(priv->magic == IRTTY_MAGIC, return;);
tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
@@ -413,7 +413,7 @@ static int irtty_stop_dev(struct sir_dev *dev)
/* ------------------------------------------------------- */
-struct sir_driver sir_tty_drv = {
+static struct sir_driver sir_tty_drv = {
.owner = THIS_MODULE,
.driver_name = "sir_tty",
.start_dev = irtty_start_dev,
@@ -440,13 +440,13 @@ static int irtty_ioctl(struct tty_struct *tty, struct file *file, unsigned int c
struct sirtty_cb *priv = tty->disc_data;
int err = 0;
- ASSERT(priv != NULL, return -ENODEV;);
- ASSERT(priv->magic == IRTTY_MAGIC, return -EBADR;);
+ IRDA_ASSERT(priv != NULL, return -ENODEV;);
+ IRDA_ASSERT(priv->magic == IRTTY_MAGIC, return -EBADR;);
IRDA_DEBUG(3, "%s(cmd=0x%X)\n", __FUNCTION__, cmd);
dev = priv->dev;
- ASSERT(dev != NULL, return -1;);
+ IRDA_ASSERT(dev != NULL, return -1;);
switch (cmd) {
case TCGETS:
@@ -460,7 +460,7 @@ static int irtty_ioctl(struct tty_struct *tty, struct file *file, unsigned int c
break;
case IRTTY_IOCGET:
- ASSERT(dev->netdev != NULL, return -1;);
+ IRDA_ASSERT(dev->netdev != NULL, return -1;);
memset(&info, 0, sizeof(info));
strncpy(info.name, dev->netdev->name, sizeof(info.name)-1);
@@ -558,8 +558,8 @@ static void irtty_close(struct tty_struct *tty)
{
struct sirtty_cb *priv = tty->disc_data;
- ASSERT(priv != NULL, return;);
- ASSERT(priv->magic == IRTTY_MAGIC, return;);
+ IRDA_ASSERT(priv != NULL, return;);
+ IRDA_ASSERT(priv->magic == IRTTY_MAGIC, return;);
/* Hm, with a dongle attached the dongle driver wants
* to close the dongle - which requires the use of
@@ -617,8 +617,8 @@ static int __init irtty_sir_init(void)
int err;
if ((err = tty_register_ldisc(N_IRDA, &irda_ldisc)) != 0)
- ERROR("IrDA: can't register line discipline (err = %d)\n",
- err);
+ IRDA_ERROR("IrDA: can't register line discipline (err = %d)\n",
+ err);
return err;
}
@@ -627,8 +627,8 @@ static void __exit irtty_sir_cleanup(void)
int err;
if ((err = tty_register_ldisc(N_IRDA, NULL))) {
- ERROR("%s(), can't unregister line discipline (err = %d)\n",
- __FUNCTION__, err);
+ IRDA_ERROR("%s(), can't unregister line discipline (err = %d)\n",
+ __FUNCTION__, err);
}
}
diff --git a/drivers/net/irda/ma600-sir.c b/drivers/net/irda/ma600-sir.c
index 9c0a5d60d62c9..ebed168b7da67 100644
--- a/drivers/net/irda/ma600-sir.c
+++ b/drivers/net/irda/ma600-sir.c
@@ -191,8 +191,7 @@ static int ma600_change_speed(struct sir_dev *dev, unsigned speed)
sirdev_raw_write(dev, &byte, sizeof(byte));
/* Wait at least 10ms: fake wait_until_sent - 10 bits at 9600 baud*/
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(msecs_to_jiffies(15)); /* old ma600 uses 15ms */
+ msleep(15); /* old ma600 uses 15ms */
#if 1
/* read-back of the control byte. ma600 is the first dongle driver
@@ -202,9 +201,9 @@ static int ma600_change_speed(struct sir_dev *dev, unsigned speed)
sirdev_raw_read(dev, &byte, sizeof(byte));
if (byte != get_control_byte(speed)) {
- WARNING("%s(): bad control byte read-back %02x != %02x\n",
- __FUNCTION__, (unsigned) byte,
- (unsigned) get_control_byte(speed));
+ IRDA_WARNING("%s(): bad control byte read-back %02x != %02x\n",
+ __FUNCTION__, (unsigned) byte,
+ (unsigned) get_control_byte(speed));
return -1;
}
else
@@ -215,8 +214,7 @@ static int ma600_change_speed(struct sir_dev *dev, unsigned speed)
sirdev_set_dtr_rts(dev, TRUE, TRUE);
/* Wait at least 10ms */
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(msecs_to_jiffies(10));
+ msleep(10);
/* dongle is now switched to the new speed */
dev->speed = speed;
@@ -245,13 +243,11 @@ int ma600_reset(struct sir_dev *dev)
/* Reset the dongle : set DTR low for 10 ms */
sirdev_set_dtr_rts(dev, FALSE, TRUE);
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(msecs_to_jiffies(10));
+ msleep(10);
/* Go back to normal mode */
sirdev_set_dtr_rts(dev, TRUE, TRUE);
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(msecs_to_jiffies(10));
+ msleep(10);
dev->speed = 9600; /* That's the dongle-default */
diff --git a/drivers/net/irda/ma600.c b/drivers/net/irda/ma600.c
index c3dfd34d71ba3..f5e6836667fd2 100644
--- a/drivers/net/irda/ma600.c
+++ b/drivers/net/irda/ma600.c
@@ -209,7 +209,8 @@ static int ma600_change_speed(struct irda_task *task)
break;
case IRDA_TASK_CHILD_WAIT:
- WARNING("%s(), resetting dongle timed out!\n", __FUNCTION__);
+ IRDA_WARNING("%s(), resetting dongle timed out!\n",
+ __FUNCTION__);
ret = -1;
break;
@@ -267,7 +268,8 @@ static int ma600_change_speed(struct irda_task *task)
break;
default:
- ERROR("%s(), unknown state %d\n", __FUNCTION__, task->state);
+ IRDA_ERROR("%s(), unknown state %d\n",
+ __FUNCTION__, task->state);
irda_task_next_state(task, IRDA_TASK_DONE);
self->speed_task = NULL;
ret = -1;
@@ -320,7 +322,8 @@ int ma600_reset(struct irda_task *task)
self->reset_task = NULL;
break;
default:
- ERROR("%s(), unknown state %d\n", __FUNCTION__, task->state);
+ IRDA_ERROR("%s(), unknown state %d\n",
+ __FUNCTION__, task->state);
irda_task_next_state(task, IRDA_TASK_DONE);
self->reset_task = NULL;
ret = -1;
diff --git a/drivers/net/irda/mcp2120-sir.c b/drivers/net/irda/mcp2120-sir.c
index 25908ffa4a176..67bd016e4df89 100644
--- a/drivers/net/irda/mcp2120-sir.c
+++ b/drivers/net/irda/mcp2120-sir.c
@@ -155,7 +155,7 @@ static int mcp2120_change_speed(struct sir_dev *dev, unsigned speed)
break;
default:
- ERROR("%s(), undefine state %d\n", __FUNCTION__, state);
+ IRDA_ERROR("%s(), undefine state %d\n", __FUNCTION__, state);
ret = -EINVAL;
break;
}
@@ -213,7 +213,7 @@ static int mcp2120_reset(struct sir_dev *dev)
break;
default:
- ERROR("%s(), undefined state %d\n", __FUNCTION__, state);
+ IRDA_ERROR("%s(), undefined state %d\n", __FUNCTION__, state);
ret = -EINVAL;
break;
}
diff --git a/drivers/net/irda/mcp2120.c b/drivers/net/irda/mcp2120.c
index d170df507b6ff..5e6199eeef4fe 100644
--- a/drivers/net/irda/mcp2120.c
+++ b/drivers/net/irda/mcp2120.c
@@ -103,7 +103,8 @@ static int mcp2120_change_speed(struct irda_task *task)
}
break;
case IRDA_TASK_CHILD_WAIT:
- WARNING("%s(), resetting dongle timed out!\n", __FUNCTION__);
+ IRDA_WARNING("%s(), resetting dongle timed out!\n",
+ __FUNCTION__);
ret = -1;
break;
case IRDA_TASK_CHILD_DONE:
@@ -151,7 +152,8 @@ static int mcp2120_change_speed(struct irda_task *task)
//printk("mcp2120_change_speed irda_task_wait\n");
break;
default:
- ERROR("%s(), unknown state %d\n", __FUNCTION__, task->state);
+ IRDA_ERROR("%s(), unknown state %d\n",
+ __FUNCTION__, task->state);
irda_task_next_state(task, IRDA_TASK_DONE);
self->speed_task = NULL;
ret = -1;
@@ -206,7 +208,8 @@ static int mcp2120_reset(struct irda_task *task)
self->reset_task = NULL;
break;
default:
- ERROR("%s(), unknown state %d\n", __FUNCTION__, task->state);
+ IRDA_ERROR("%s(), unknown state %d\n",
+ __FUNCTION__, task->state);
irda_task_next_state(task, IRDA_TASK_DONE);
self->reset_task = NULL;
ret = -1;
diff --git a/drivers/net/irda/nsc-ircc.c b/drivers/net/irda/nsc-ircc.c
index b9b66a7fe0326..805714ec9a8a1 100644
--- a/drivers/net/irda/nsc-ircc.c
+++ b/drivers/net/irda/nsc-ircc.c
@@ -94,16 +94,13 @@ static nsc_chip_t chips[] = {
nsc_ircc_probe_108, nsc_ircc_init_108 },
{ "PC87338", { 0x398, 0x15c, 0x2e }, 0x08, 0xb0, 0xf8,
nsc_ircc_probe_338, nsc_ircc_init_338 },
+ /* Contributed by Steffen Pingel - IBM X40 */
+ { "PC8738x", { 0x164e, 0x4e, 0x0 }, 0x20, 0xf4, 0xff,
+ nsc_ircc_probe_39x, nsc_ircc_init_39x },
/* Contributed by Jan Frey - IBM A30/A31 */
{ "PC8739x", { 0x2e, 0x4e, 0x0 }, 0x20, 0xea, 0xff,
nsc_ircc_probe_39x, nsc_ircc_init_39x },
{ NULL }
-#if 0
- /* Probably bogus, "PC8739x" should be the real thing. Jean II */
- /* Contributed by Kevin Thayer - OmniBook 6100 */
- { "PC87338?", { 0x2e, 0x15c, 0x398 }, 0x08, 0x00, 0xf8,
- nsc_ircc_probe_338, nsc_ircc_init_338 },
-#endif
};
/* Max 4 instances for now */
@@ -253,18 +250,18 @@ static int __init nsc_ircc_open(int i, chipio_t *info)
IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
- MESSAGE("%s, Found chip at base=0x%03x\n", driver_name,
- info->cfg_base);
+ IRDA_MESSAGE("%s, Found chip at base=0x%03x\n", driver_name,
+ info->cfg_base);
if ((nsc_ircc_setup(info)) == -1)
return -1;
- MESSAGE("%s, driver loaded (Dag Brattli)\n", driver_name);
+ IRDA_MESSAGE("%s, driver loaded (Dag Brattli)\n", driver_name);
dev = alloc_irdadev(sizeof(struct nsc_ircc_cb));
if (dev == NULL) {
- ERROR("%s(), can't allocate memory for "
- "control block!\n", __FUNCTION__);
+ IRDA_ERROR("%s(), can't allocate memory for "
+ "control block!\n", __FUNCTION__);
return -ENOMEM;
}
@@ -287,8 +284,8 @@ static int __init nsc_ircc_open(int i, chipio_t *info)
/* Reserve the ioports that we need */
ret = request_region(self->io.fir_base, self->io.fir_ext, driver_name);
if (!ret) {
- WARNING("%s(), can't get iobase of 0x%03x\n",
- __FUNCTION__, self->io.fir_base);
+ IRDA_WARNING("%s(), can't get iobase of 0x%03x\n",
+ __FUNCTION__, self->io.fir_base);
err = -ENODEV;
goto out1;
}
@@ -346,21 +343,21 @@ static int __init nsc_ircc_open(int i, chipio_t *info)
err = register_netdev(dev);
if (err) {
- ERROR("%s(), register_netdev() failed!\n", __FUNCTION__);
+ IRDA_ERROR("%s(), register_netdev() failed!\n", __FUNCTION__);
goto out4;
}
- MESSAGE("IrDA: Registered device %s\n", dev->name);
+ IRDA_MESSAGE("IrDA: Registered device %s\n", dev->name);
/* Check if user has supplied a valid dongle id or not */
if ((dongle_id <= 0) ||
(dongle_id >= (sizeof(dongle_types) / sizeof(dongle_types[0]))) ) {
dongle_id = nsc_ircc_read_dongle_id(self->io.fir_base);
- MESSAGE("%s, Found dongle: %s\n", driver_name,
- dongle_types[dongle_id]);
+ IRDA_MESSAGE("%s, Found dongle: %s\n", driver_name,
+ dongle_types[dongle_id]);
} else {
- MESSAGE("%s, Using dongle: %s\n", driver_name,
- dongle_types[dongle_id]);
+ IRDA_MESSAGE("%s, Using dongle: %s\n", driver_name,
+ dongle_types[dongle_id]);
}
self->io.dongle_id = dongle_id;
@@ -397,7 +394,7 @@ static int __exit nsc_ircc_close(struct nsc_ircc_cb *self)
IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
- ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
iobase = self->io.fir_base;
@@ -444,7 +441,7 @@ static int nsc_ircc_init_108(nsc_chip_t *chip, chipio_t *info)
case 0x2e8: outb(0x15, cfg_base+1); break;
case 0x3f8: outb(0x16, cfg_base+1); break;
case 0x2f8: outb(0x17, cfg_base+1); break;
- default: ERROR("%s(), invalid base_address", __FUNCTION__);
+ default: IRDA_ERROR("%s(), invalid base_address", __FUNCTION__);
}
/* Control Signal Routing Register (CSRT) */
@@ -456,7 +453,7 @@ static int nsc_ircc_init_108(nsc_chip_t *chip, chipio_t *info)
case 9: temp = 0x05; break;
case 11: temp = 0x06; break;
case 15: temp = 0x07; break;
- default: ERROR("%s(), invalid irq", __FUNCTION__);
+ default: IRDA_ERROR("%s(), invalid irq", __FUNCTION__);
}
outb(CFG_108_CSRT, cfg_base);
@@ -464,7 +461,7 @@ static int nsc_ircc_init_108(nsc_chip_t *chip, chipio_t *info)
case 0: outb(0x08+temp, cfg_base+1); break;
case 1: outb(0x10+temp, cfg_base+1); break;
case 3: outb(0x18+temp, cfg_base+1); break;
- default: ERROR("%s(), invalid dma", __FUNCTION__);
+ default: IRDA_ERROR("%s(), invalid dma", __FUNCTION__);
}
outb(CFG_108_MCTL, cfg_base); /* Mode Control Register (MCTL) */
@@ -828,7 +825,8 @@ static int nsc_ircc_setup(chipio_t *info)
/* Should be 0x2? */
if (0x20 != (version & 0xf0)) {
- ERROR("%s, Wrong chip version %02x\n", driver_name, version);
+ IRDA_ERROR("%s, Wrong chip version %02x\n",
+ driver_name, version);
return -1;
}
@@ -1092,7 +1090,7 @@ static __u8 nsc_ircc_change_speed(struct nsc_ircc_cb *self, __u32 speed)
IRDA_DEBUG(2, "%s(), speed=%d\n", __FUNCTION__, speed);
- ASSERT(self != NULL, return 0;);
+ IRDA_ASSERT(self != NULL, return 0;);
iobase = self->io.fir_base;
@@ -1200,7 +1198,7 @@ static int nsc_ircc_hard_xmit_sir(struct sk_buff *skb, struct net_device *dev)
self = (struct nsc_ircc_cb *) dev->priv;
- ASSERT(self != NULL, return 0;);
+ IRDA_ASSERT(self != NULL, return 0;);
iobase = self->io.fir_base;
@@ -1705,8 +1703,9 @@ static int nsc_ircc_dma_receive_complete(struct nsc_ircc_cb *self, int iobase)
skb = dev_alloc_skb(len+1);
if (skb == NULL) {
- WARNING("%s(), memory squeeze, "
- "dropping frame.\n", __FUNCTION__);
+ IRDA_WARNING("%s(), memory squeeze, "
+ "dropping frame.\n",
+ __FUNCTION__);
self->stats.rx_dropped++;
/* Restore bank register */
@@ -1892,9 +1891,9 @@ static void nsc_ircc_fir_interrupt(struct nsc_ircc_cb *self, int iobase,
nsc_ircc_dma_receive(self);
self->ier = IER_SFIF_IE;
} else
- WARNING("%s(), potential "
- "Tx queue lockup !\n",
- __FUNCTION__);
+ IRDA_WARNING("%s(), potential "
+ "Tx queue lockup !\n",
+ __FUNCTION__);
}
} else {
/* Not finished yet, so interrupt on DMA again */
@@ -1927,7 +1926,8 @@ static irqreturn_t nsc_ircc_interrupt(int irq, void *dev_id,
int iobase;
if (!dev) {
- WARNING("%s: irq %d for unknown device.\n", driver_name, irq);
+ IRDA_WARNING("%s: irq %d for unknown device.\n",
+ driver_name, irq);
return IRQ_NONE;
}
self = (struct nsc_ircc_cb *) dev->priv;
@@ -1972,7 +1972,7 @@ static int nsc_ircc_is_receiving(struct nsc_ircc_cb *self)
int iobase;
__u8 bank;
- ASSERT(self != NULL, return FALSE;);
+ IRDA_ASSERT(self != NULL, return FALSE;);
spin_lock_irqsave(&self->lock, flags);
@@ -2010,16 +2010,16 @@ static int nsc_ircc_net_open(struct net_device *dev)
IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
- ASSERT(dev != NULL, return -1;);
+ IRDA_ASSERT(dev != NULL, return -1;);
self = (struct nsc_ircc_cb *) dev->priv;
- ASSERT(self != NULL, return 0;);
+ IRDA_ASSERT(self != NULL, return 0;);
iobase = self->io.fir_base;
if (request_irq(self->io.irq, nsc_ircc_interrupt, 0, dev->name, dev)) {
- WARNING("%s, unable to allocate irq=%d\n", driver_name,
- self->io.irq);
+ IRDA_WARNING("%s, unable to allocate irq=%d\n",
+ driver_name, self->io.irq);
return -EAGAIN;
}
/*
@@ -2027,8 +2027,8 @@ static int nsc_ircc_net_open(struct net_device *dev)
* failure.
*/
if (request_dma(self->io.dma, dev->name)) {
- WARNING("%s, unable to allocate dma=%d\n", driver_name,
- self->io.dma);
+ IRDA_WARNING("%s, unable to allocate dma=%d\n",
+ driver_name, self->io.dma);
free_irq(self->io.irq, dev);
return -EAGAIN;
}
@@ -2072,10 +2072,10 @@ static int nsc_ircc_net_close(struct net_device *dev)
IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
- ASSERT(dev != NULL, return -1;);
+ IRDA_ASSERT(dev != NULL, return -1;);
self = (struct nsc_ircc_cb *) dev->priv;
- ASSERT(self != NULL, return 0;);
+ IRDA_ASSERT(self != NULL, return 0;);
/* Stop device */
netif_stop_queue(dev);
@@ -2118,11 +2118,11 @@ static int nsc_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
unsigned long flags;
int ret = 0;
- ASSERT(dev != NULL, return -1;);
+ IRDA_ASSERT(dev != NULL, return -1;);
self = dev->priv;
- ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
IRDA_DEBUG(2, "%s(), %s, (cmd=0x%X)\n", __FUNCTION__, dev->name, cmd);
@@ -2162,7 +2162,7 @@ static struct net_device_stats *nsc_ircc_net_get_stats(struct net_device *dev)
static void nsc_ircc_suspend(struct nsc_ircc_cb *self)
{
- MESSAGE("%s, Suspending\n", driver_name);
+ IRDA_MESSAGE("%s, Suspending\n", driver_name);
if (self->io.suspended)
return;
@@ -2180,7 +2180,7 @@ static void nsc_ircc_wakeup(struct nsc_ircc_cb *self)
nsc_ircc_setup(&self->io);
nsc_ircc_net_open(self->netdev);
- MESSAGE("%s, Waking up\n", driver_name);
+ IRDA_MESSAGE("%s, Waking up\n", driver_name);
self->io.suspended = 0;
}
diff --git a/drivers/net/irda/sir_dev.c b/drivers/net/irda/sir_dev.c
index 2d7f183d76614..efc5a88705652 100644
--- a/drivers/net/irda/sir_dev.c
+++ b/drivers/net/irda/sir_dev.c
@@ -15,6 +15,7 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/smp_lock.h>
+#include <linux/delay.h>
#include <net/irda/irda.h>
#include <net/irda/wrapper.h>
@@ -73,8 +74,7 @@ int sirdev_raw_write(struct sir_dev *dev, const char *buf, int len)
spin_lock_irqsave(&dev->tx_lock, flags); /* serialize with other tx operations */
while (dev->tx_buff.len > 0) { /* wait until tx idle */
spin_unlock_irqrestore(&dev->tx_lock, flags);
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(msecs_to_jiffies(10));
+ msleep(10);
spin_lock_irqsave(&dev->tx_lock, flags);
}
@@ -154,7 +154,8 @@ void sirdev_write_complete(struct sir_dev *dev)
}
else if (unlikely(actual<0)) {
/* could be dropped later when we have tx_timeout to recover */
- ERROR("%s: drv->do_write failed (%d)\n", __FUNCTION__, actual);
+ IRDA_ERROR("%s: drv->do_write failed (%d)\n",
+ __FUNCTION__, actual);
if ((skb=dev->tx_skb) != NULL) {
dev->tx_skb = NULL;
dev_kfree_skb_any(skb);
@@ -208,7 +209,8 @@ void sirdev_write_complete(struct sir_dev *dev)
/* should never happen
* forget the speed change and hope the stack recovers
*/
- ERROR("%s - schedule speed change failed: %d\n", __FUNCTION__, err);
+ IRDA_ERROR("%s - schedule speed change failed: %d\n",
+ __FUNCTION__, err);
netif_wake_queue(dev->netdev);
}
/* else: success
@@ -234,13 +236,13 @@ done:
int sirdev_receive(struct sir_dev *dev, const unsigned char *cp, size_t count)
{
if (!dev || !dev->netdev) {
- WARNING("%s(), not ready yet!\n", __FUNCTION__);
+ IRDA_WARNING("%s(), not ready yet!\n", __FUNCTION__);
return -1;
}
if (!dev->irlap) {
- WARNING("%s - too early: %p / %zd!\n",
- __FUNCTION__, cp, count);
+ IRDA_WARNING("%s - too early: %p / %zd!\n",
+ __FUNCTION__, cp, count);
return -1;
}
@@ -297,7 +299,7 @@ static int sirdev_hard_xmit(struct sk_buff *skb, struct net_device *ndev)
int err;
s32 speed;
- ASSERT(dev != NULL, return 0;);
+ IRDA_ASSERT(dev != NULL, return 0;);
netif_stop_queue(ndev);
@@ -366,7 +368,8 @@ static int sirdev_hard_xmit(struct sk_buff *skb, struct net_device *ndev)
}
else if (unlikely(actual < 0)) {
/* could be dropped later when we have tx_timeout to recover */
- ERROR("%s: drv->do_write failed (%d)\n", __FUNCTION__, actual);
+ IRDA_ERROR("%s: drv->do_write failed (%d)\n",
+ __FUNCTION__, actual);
dev_kfree_skb_any(skb);
dev->stats.tx_errors++;
dev->stats.tx_dropped++;
@@ -385,7 +388,7 @@ static int sirdev_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd)
struct sir_dev *dev = ndev->priv;
int ret = 0;
- ASSERT(dev != NULL, return -1;);
+ IRDA_ASSERT(dev != NULL, return -1;);
IRDA_DEBUG(3, "%s(), %s, (cmd=0x%X)\n", __FUNCTION__, ndev->name, cmd);
@@ -593,7 +596,7 @@ struct sir_dev * sirdev_get_instance(const struct sir_driver *drv, const char *n
*/
ndev = alloc_irdadev(sizeof(*dev));
if (ndev == NULL) {
- ERROR("%s - Can't allocate memory for IrDA control block!\n", __FUNCTION__);
+ IRDA_ERROR("%s - Can't allocate memory for IrDA control block!\n", __FUNCTION__);
goto out;
}
dev = ndev->priv;
@@ -628,7 +631,7 @@ struct sir_dev * sirdev_get_instance(const struct sir_driver *drv, const char *n
ndev->do_ioctl = sirdev_ioctl;
if (register_netdev(ndev)) {
- ERROR("%s(), register_netdev() failed!\n", __FUNCTION__);
+ IRDA_ERROR("%s(), register_netdev() failed!\n", __FUNCTION__);
goto out_freenetdev;
}
@@ -654,7 +657,7 @@ int sirdev_put_instance(struct sir_dev *dev)
if (dev->dongle_drv)
err = sirdev_schedule_dongle_close(dev);
if (err)
- ERROR("%s - error %d\n", __FUNCTION__, err);
+ IRDA_ERROR("%s - error %d\n", __FUNCTION__, err);
sirdev_close(dev->netdev);
diff --git a/drivers/net/irda/sir_kthread.c b/drivers/net/irda/sir_kthread.c
index 45b36190151a0..18cea1099530a 100644
--- a/drivers/net/irda/sir_kthread.c
+++ b/drivers/net/irda/sir_kthread.c
@@ -222,7 +222,7 @@ static int irda_tx_complete_fsm(struct sir_dev *dev)
return 0;
default:
- ERROR("%s - undefined state\n", __FUNCTION__);
+ IRDA_ERROR("%s - undefined state\n", __FUNCTION__);
return -EINVAL;
}
fsm->substate = next_state;
@@ -391,12 +391,12 @@ static void irda_config_fsm(void *data)
break;
default:
- ERROR("%s - undefined state\n", __FUNCTION__);
+ IRDA_ERROR("%s - undefined state\n", __FUNCTION__);
fsm->result = -EINVAL;
/* fall thru */
case SIRDEV_STATE_ERROR:
- ERROR("%s - error: %d\n", __FUNCTION__, fsm->result);
+ IRDA_ERROR("%s - error: %d\n", __FUNCTION__, fsm->result);
#if 0 /* don't enable this before we have netdev->tx_timeout to recover */
netif_stop_queue(dev->netdev);
@@ -439,7 +439,7 @@ int sirdev_schedule_request(struct sir_dev *dev, int initial_state, unsigned par
if (fsm->state == SIRDEV_STATE_DEAD) {
/* race with sirdev_close should never happen */
- ERROR("%s(), instance staled!\n", __FUNCTION__);
+ IRDA_ERROR("%s(), instance staled!\n", __FUNCTION__);
up(&fsm->sem);
return -ESTALE; /* or better EPIPE? */
}
diff --git a/drivers/net/irda/smsc-ircc2.c b/drivers/net/irda/smsc-ircc2.c
index 792ba02a4c005..10125a1dba22b 100644
--- a/drivers/net/irda/smsc-ircc2.c
+++ b/drivers/net/irda/smsc-ircc2.c
@@ -203,7 +203,7 @@ static int smsc_ircc_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data);
/* Transceivers for SMSC-ircc */
-smsc_transceiver_t smsc_transceivers[]=
+static smsc_transceiver_t smsc_transceivers[]=
{
{ "Toshiba Satellite 1800 (GP data pin select)", smsc_ircc_set_transceiver_toshiba_sat1800, smsc_ircc_probe_transceiver_toshiba_sat1800},
{ "Fast pin select", smsc_ircc_set_transceiver_smsc_ircc_fast_pin_select, smsc_ircc_probe_transceiver_smsc_ircc_fast_pin_select},
@@ -334,8 +334,8 @@ static int __init smsc_ircc_init(void)
dev_count=0;
if ((ircc_fir>0)&&(ircc_sir>0)) {
- MESSAGE(" Overriding FIR address 0x%04x\n", ircc_fir);
- MESSAGE(" Overriding SIR address 0x%04x\n", ircc_sir);
+ IRDA_MESSAGE(" Overriding FIR address 0x%04x\n", ircc_fir);
+ IRDA_MESSAGE(" Overriding SIR address 0x%04x\n", ircc_sir);
if (smsc_ircc_open(ircc_fir, ircc_sir, ircc_dma, ircc_irq) == 0)
return 0;
@@ -345,7 +345,8 @@ static int __init smsc_ircc_init(void)
/* try user provided configuration register base address */
if (ircc_cfg>0) {
- MESSAGE(" Overriding configuration address 0x%04x\n", ircc_cfg);
+ IRDA_MESSAGE(" Overriding configuration address 0x%04x\n",
+ ircc_cfg);
if (!smsc_superio_fdc(ircc_cfg))
ret = 0;
if (!smsc_superio_lpc(ircc_cfg))
@@ -377,7 +378,7 @@ static int __init smsc_ircc_open(unsigned int fir_base, unsigned int sir_base, u
err = -ENOMEM;
if (dev_count > DIM(dev_self)) {
- WARNING("%s(), too many devices!\n", __FUNCTION__);
+ IRDA_WARNING("%s(), too many devices!\n", __FUNCTION__);
goto err_out1;
}
@@ -386,7 +387,7 @@ static int __init smsc_ircc_open(unsigned int fir_base, unsigned int sir_base, u
*/
dev = alloc_irdadev(sizeof(struct smsc_ircc_cb));
if (!dev) {
- WARNING("%s() can't allocate net device\n", __FUNCTION__);
+ IRDA_WARNING("%s() can't allocate net device\n", __FUNCTION__);
goto err_out1;
}
@@ -420,8 +421,8 @@ static int __init smsc_ircc_open(unsigned int fir_base, unsigned int sir_base, u
dma_alloc_coherent(NULL, self->rx_buff.truesize,
&self->rx_buff_dma, GFP_KERNEL);
if (self->rx_buff.head == NULL) {
- ERROR("%s, Can't allocate memory for receive buffer!\n",
- driver_name);
+ IRDA_ERROR("%s, Can't allocate memory for receive buffer!\n",
+ driver_name);
goto err_out2;
}
@@ -429,8 +430,8 @@ static int __init smsc_ircc_open(unsigned int fir_base, unsigned int sir_base, u
dma_alloc_coherent(NULL, self->tx_buff.truesize,
&self->tx_buff_dma, GFP_KERNEL);
if (self->tx_buff.head == NULL) {
- ERROR("%s, Can't allocate memory for transmit buffer!\n",
- driver_name);
+ IRDA_ERROR("%s, Can't allocate memory for transmit buffer!\n",
+ driver_name);
goto err_out3;
}
@@ -456,8 +457,8 @@ static int __init smsc_ircc_open(unsigned int fir_base, unsigned int sir_base, u
err = register_netdev(self->netdev);
if(err) {
- ERROR("%s, Network device registration failed!\n",
- driver_name);
+ IRDA_ERROR("%s, Network device registration failed!\n",
+ driver_name);
goto err_out4;
}
@@ -465,7 +466,7 @@ static int __init smsc_ircc_open(unsigned int fir_base, unsigned int sir_base, u
if (self->pmdev)
self->pmdev->data = self;
- MESSAGE("IrDA: Registered device %s\n", dev->name);
+ IRDA_MESSAGE("IrDA: Registered device %s\n", dev->name);
return 0;
err_out4:
@@ -496,15 +497,15 @@ static int smsc_ircc_present(unsigned int fir_base, unsigned int sir_base)
if (!request_region(fir_base, SMSC_IRCC2_FIR_CHIP_IO_EXTENT,
driver_name)) {
- WARNING("%s: can't get fir_base of 0x%03x\n",
- __FUNCTION__, fir_base);
+ IRDA_WARNING("%s: can't get fir_base of 0x%03x\n",
+ __FUNCTION__, fir_base);
goto out1;
}
if (!request_region(sir_base, SMSC_IRCC2_SIR_CHIP_IO_EXTENT,
driver_name)) {
- WARNING("%s: can't get sir_base of 0x%03x\n",
- __FUNCTION__, sir_base);
+ IRDA_WARNING("%s: can't get sir_base of 0x%03x\n",
+ __FUNCTION__, sir_base);
goto out2;
}
@@ -519,13 +520,13 @@ static int smsc_ircc_present(unsigned int fir_base, unsigned int sir_base)
irq = (config & IRCC_INTERFACE_IRQ_MASK) >> 4;
if (high != 0x10 || low != 0xb8 || (chip != 0xf1 && chip != 0xf2)) {
- WARNING("%s(), addr 0x%04x - no device found!\n",
- __FUNCTION__, fir_base);
+ IRDA_WARNING("%s(), addr 0x%04x - no device found!\n",
+ __FUNCTION__, fir_base);
goto out3;
}
- MESSAGE("SMsC IrDA Controller found\n IrCC version %d.%d, "
- "firport 0x%03x, sirport 0x%03x dma=%d, irq=%d\n",
- chip & 0x0f, version, fir_base, sir_base, dma, irq);
+ IRDA_MESSAGE("SMsC IrDA Controller found\n IrCC version %d.%d, "
+ "firport 0x%03x, sirport 0x%03x dma=%d, irq=%d\n",
+ chip & 0x0f, version, fir_base, sir_base, dma, irq);
return 0;
out3:
@@ -562,8 +563,8 @@ static void smsc_ircc_setup_io(struct smsc_ircc_cb *self,
if (irq < 255) {
if (irq != chip_irq)
- MESSAGE("%s, Overriding IRQ - chip says %d, using %d\n",
- driver_name, chip_irq, irq);
+ IRDA_MESSAGE("%s, Overriding IRQ - chip says %d, using %d\n",
+ driver_name, chip_irq, irq);
self->io.irq = irq;
}
else
@@ -571,8 +572,8 @@ static void smsc_ircc_setup_io(struct smsc_ircc_cb *self,
if (dma < 255) {
if (dma != chip_dma)
- MESSAGE("%s, Overriding DMA - chip says %d, using %d\n",
- driver_name, chip_dma, dma);
+ IRDA_MESSAGE("%s, Overriding DMA - chip says %d, using %d\n",
+ driver_name, chip_dma, dma);
self->io.dma = dma;
}
else
@@ -609,7 +610,7 @@ static void smsc_ircc_init_chip(struct smsc_ircc_cb *self)
{
int iobase, ir_mode, ctrl, fast;
- ASSERT( self != NULL, return; );
+ IRDA_ASSERT( self != NULL, return; );
iobase = self->io.fir_base;
ir_mode = IRCC_CFGA_IRDA_SIR_A;
@@ -659,11 +660,11 @@ static int smsc_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd
unsigned long flags;
int ret = 0;
- ASSERT(dev != NULL, return -1;);
+ IRDA_ASSERT(dev != NULL, return -1;);
self = dev->priv;
- ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
IRDA_DEBUG(2, "%s(), %s, (cmd=0x%X)\n", __FUNCTION__, dev->name, cmd);
@@ -728,7 +729,8 @@ static void smsc_ircc_timeout(struct net_device *dev)
self = (struct smsc_ircc_cb *) dev->priv;
- WARNING("%s: transmit timed out, changing speed to: %d\n", dev->name, self->io.speed);
+ IRDA_WARNING("%s: transmit timed out, changing speed to: %d\n",
+ dev->name, self->io.speed);
spin_lock_irqsave(&self->lock, flags);
smsc_ircc_sir_start(self);
smsc_ircc_change_speed(self, self->io.speed);
@@ -754,10 +756,10 @@ int smsc_ircc_hard_xmit_sir(struct sk_buff *skb, struct net_device *dev)
IRDA_DEBUG(1, "%s\n", __FUNCTION__);
- ASSERT(dev != NULL, return 0;);
+ IRDA_ASSERT(dev != NULL, return 0;);
self = (struct smsc_ircc_cb *) dev->priv;
- ASSERT(self != NULL, return 0;);
+ IRDA_ASSERT(self != NULL, return 0;);
iobase = self->io.sir_base;
@@ -819,7 +821,7 @@ static void smsc_ircc_set_fir_speed(struct smsc_ircc_cb *self, u32 speed)
{
int fir_base, ir_mode, ctrl, fast;
- ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self != NULL, return;);
fir_base = self->io.fir_base;
self->io.speed = speed;
@@ -874,9 +876,9 @@ static void smsc_ircc_fir_start(struct smsc_ircc_cb *self)
IRDA_DEBUG(1, "%s\n", __FUNCTION__);
- ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self != NULL, return;);
dev = self->netdev;
- ASSERT(dev != NULL, return;);
+ IRDA_ASSERT(dev != NULL, return;);
fir_base = self->io.fir_base;
@@ -922,7 +924,7 @@ static void smsc_ircc_fir_stop(struct smsc_ircc_cb *self)
IRDA_DEBUG(1, "%s\n", __FUNCTION__);
- ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self != NULL, return;);
fir_base = self->io.fir_base;
register_bank(fir_base, 0);
@@ -948,7 +950,7 @@ static void smsc_ircc_change_speed(void *priv, u32 speed)
IRDA_DEBUG(0, "%s() changing speed to: %d\n", __FUNCTION__, speed);
- ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self != NULL, return;);
dev = self->netdev;
iobase = self->io.fir_base;
@@ -1018,7 +1020,7 @@ void smsc_ircc_set_sir_speed(void *priv, __u32 speed)
IRDA_DEBUG(0, "%s(), Setting speed to: %d\n", __FUNCTION__, speed);
- ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self != NULL, return;);
iobase = self->io.sir_base;
/* Update accounting for new speed */
@@ -1071,9 +1073,9 @@ static int smsc_ircc_hard_xmit_fir(struct sk_buff *skb, struct net_device *dev)
int iobase;
int mtt;
- ASSERT(dev != NULL, return 0;);
+ IRDA_ASSERT(dev != NULL, return 0;);
self = (struct smsc_ircc_cb *) dev->priv;
- ASSERT(self != NULL, return 0;);
+ IRDA_ASSERT(self != NULL, return 0;);
iobase = self->io.fir_base;
@@ -1325,15 +1327,15 @@ static void smsc_ircc_dma_receive_complete(struct smsc_ircc_cb *self, int iobase
len -= 4;
if ((len < 2) || (len > 2050)) {
- WARNING("%s(), bogus len=%d\n", __FUNCTION__, len);
+ IRDA_WARNING("%s(), bogus len=%d\n", __FUNCTION__, len);
return;
}
IRDA_DEBUG(2, "%s: msgcnt = %d, len=%d\n", __FUNCTION__, msgcnt, len);
skb = dev_alloc_skb(len+1);
if (!skb) {
- WARNING("%s(), memory squeeze, dropping frame.\n",
- __FUNCTION__);
+ IRDA_WARNING("%s(), memory squeeze, dropping frame.\n",
+ __FUNCTION__);
return;
}
/* Make sure IP header gets aligned */
@@ -1360,7 +1362,7 @@ static void smsc_ircc_sir_receive(struct smsc_ircc_cb *self)
int boguscount = 0;
int iobase;
- ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self != NULL, return;);
iobase = self->io.sir_base;
@@ -1400,7 +1402,7 @@ static irqreturn_t smsc_ircc_interrupt(int irq, void *dev_id, struct pt_regs *re
goto irq_ret;
}
self = (struct smsc_ircc_cb *) dev->priv;
- ASSERT(self != NULL, return IRQ_NONE;);
+ IRDA_ASSERT(self != NULL, return IRQ_NONE;);
/* Serialise the interrupt handler in various CPUs, stop Tx path */
spin_lock(&self->lock);
@@ -1521,7 +1523,7 @@ static int ircc_is_receiving(struct smsc_ircc_cb *self)
IRDA_DEBUG(1, "%s\n", __FUNCTION__);
- ASSERT(self != NULL, return FALSE;);
+ IRDA_ASSERT(self != NULL, return FALSE;);
IRDA_DEBUG(0, "%s: dma count = %d\n", __FUNCTION__,
get_dma_residue(self->io.dma));
@@ -1548,9 +1550,9 @@ static int smsc_ircc_net_open(struct net_device *dev)
IRDA_DEBUG(1, "%s\n", __FUNCTION__);
- ASSERT(dev != NULL, return -1;);
+ IRDA_ASSERT(dev != NULL, return -1;);
self = (struct smsc_ircc_cb *) dev->priv;
- ASSERT(self != NULL, return 0;);
+ IRDA_ASSERT(self != NULL, return 0;);
iobase = self->io.fir_base;
@@ -1584,8 +1586,8 @@ static int smsc_ircc_net_open(struct net_device *dev)
if (request_dma(self->io.dma, dev->name)) {
smsc_ircc_net_close(dev);
- WARNING("%s(), unable to allocate DMA=%d\n",
- __FUNCTION__, self->io.dma);
+ IRDA_WARNING("%s(), unable to allocate DMA=%d\n",
+ __FUNCTION__, self->io.dma);
return -EAGAIN;
}
@@ -1607,9 +1609,9 @@ static int smsc_ircc_net_close(struct net_device *dev)
IRDA_DEBUG(1, "%s\n", __FUNCTION__);
- ASSERT(dev != NULL, return -1;);
+ IRDA_ASSERT(dev != NULL, return -1;);
self = (struct smsc_ircc_cb *) dev->priv;
- ASSERT(self != NULL, return 0;);
+ IRDA_ASSERT(self != NULL, return 0;);
iobase = self->io.fir_base;
@@ -1633,7 +1635,7 @@ static int smsc_ircc_net_close(struct net_device *dev)
static void smsc_ircc_suspend(struct smsc_ircc_cb *self)
{
- MESSAGE("%s, Suspending\n", driver_name);
+ IRDA_MESSAGE("%s, Suspending\n", driver_name);
if (self->io.suspended)
return;
@@ -1654,7 +1656,7 @@ static void smsc_ircc_wakeup(struct smsc_ircc_cb *self)
smsc_ircc_net_open(self->netdev);
- MESSAGE("%s, Waking up\n", driver_name);
+ IRDA_MESSAGE("%s, Waking up\n", driver_name);
}
static int smsc_ircc_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data)
@@ -1686,7 +1688,7 @@ static int __exit smsc_ircc_close(struct smsc_ircc_cb *self)
IRDA_DEBUG(1, "%s\n", __FUNCTION__);
- ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
iobase = self->io.fir_base;
@@ -1761,9 +1763,9 @@ void smsc_ircc_sir_start(struct smsc_ircc_cb *self)
IRDA_DEBUG(3, "%s\n", __FUNCTION__);
- ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self != NULL, return;);
dev= self->netdev;
- ASSERT(dev != NULL, return;);
+ IRDA_ASSERT(dev != NULL, return;);
dev->hard_start_xmit = &smsc_ircc_hard_xmit_sir;
fir_base = self->io.fir_base;
@@ -1820,7 +1822,7 @@ static void smsc_ircc_sir_write_wakeup(struct smsc_ircc_cb *self)
int iobase;
int fcr;
- ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self != NULL, return;);
IRDA_DEBUG(4, "%s\n", __FUNCTION__);
@@ -1885,7 +1887,7 @@ static int smsc_ircc_sir_write(int iobase, int fifo_size, __u8 *buf, int len)
/* Tx FIFO should be empty! */
if (!(inb(iobase+UART_LSR) & UART_LSR_THRE)) {
- WARNING("%s(), failed, fifo not empty!\n", __FUNCTION__);
+ IRDA_WARNING("%s(), failed, fifo not empty!\n", __FUNCTION__);
return 0;
}
@@ -1920,15 +1922,17 @@ static void smsc_ircc_probe_transceiver(struct smsc_ircc_cb *self)
{
unsigned int i;
- ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self != NULL, return;);
for(i=0; smsc_transceivers[i].name!=NULL; i++)
if((*smsc_transceivers[i].probe)(self->io.fir_base)) {
- MESSAGE(" %s transceiver found\n", smsc_transceivers[i].name);
+ IRDA_MESSAGE(" %s transceiver found\n",
+ smsc_transceivers[i].name);
self->transceiver= i+1;
return;
}
- MESSAGE("No transceiver found. Defaulting to %s\n", smsc_transceivers[SMSC_IRCC2_C_DEFAULT_TRANSCEIVER].name);
+ IRDA_MESSAGE("No transceiver found. Defaulting to %s\n",
+ smsc_transceivers[SMSC_IRCC2_C_DEFAULT_TRANSCEIVER].name);
self->transceiver= SMSC_IRCC2_C_DEFAULT_TRANSCEIVER;
}
@@ -2052,7 +2056,7 @@ static int __init smsc_superio_flat(const smsc_chip_t *chips, unsigned short cfg
/*printk(KERN_WARNING "%s(): mode: 0x%02x\n", __FUNCTION__, mode);*/
if(!(mode & SMSCSIOFLAT_UART2MODE_VAL_IRDA))
- WARNING("%s(): IrDA not enabled\n", __FUNCTION__);
+ IRDA_WARNING("%s(): IrDA not enabled\n", __FUNCTION__);
outb(SMSCSIOFLAT_UART2BASEADDR_REG, cfgbase);
sirbase = inb(cfgbase+1) << 2;
@@ -2069,7 +2073,7 @@ static int __init smsc_superio_flat(const smsc_chip_t *chips, unsigned short cfg
outb(SMSCSIOFLAT_UARTIRQSELECT_REG, cfgbase);
irq = inb(cfgbase+1) & SMSCSIOFLAT_UART2IRQSELECT_MASK;
- MESSAGE("%s(): fir: 0x%02x, sir: 0x%02x, dma: %02d, irq: %d, mode: 0x%02x\n", __FUNCTION__, firbase, sirbase, dma, irq, mode);
+ IRDA_MESSAGE("%s(): fir: 0x%02x, sir: 0x%02x, dma: %02d, irq: %d, mode: 0x%02x\n", __FUNCTION__, firbase, sirbase, dma, irq, mode);
if (firbase) {
if (smsc_ircc_open(firbase, sirbase, dma, irq) == 0)
@@ -2201,15 +2205,15 @@ static const smsc_chip_t * __init smsc_ircc_probe(unsigned short cfg_base,u8 reg
return NULL;
}
- MESSAGE("found SMC SuperIO Chip (devid=0x%02x rev=%02X base=0x%04x): %s%s\n",devid,rev,cfg_base,type,chip->name);
+ IRDA_MESSAGE("found SMC SuperIO Chip (devid=0x%02x rev=%02X base=0x%04x): %s%s\n",devid,rev,cfg_base,type,chip->name);
if (chip->rev>rev){
- MESSAGE("Revision higher than expected\n");
+ IRDA_MESSAGE("Revision higher than expected\n");
return NULL;
}
if (chip->flags&NoIRDA)
- MESSAGE("chipset does not support IRDA\n");
+ IRDA_MESSAGE("chipset does not support IRDA\n");
return chip;
}
@@ -2219,8 +2223,8 @@ static int __init smsc_superio_fdc(unsigned short cfg_base)
int ret = -1;
if (!request_region(cfg_base, 2, driver_name)) {
- WARNING("%s: can't get cfg_base of 0x%03x\n",
- __FUNCTION__, cfg_base);
+ IRDA_WARNING("%s: can't get cfg_base of 0x%03x\n",
+ __FUNCTION__, cfg_base);
} else {
if (!smsc_superio_flat(fdc_chips_flat,cfg_base,"FDC")
||!smsc_superio_paged(fdc_chips_paged,cfg_base,"FDC"))
@@ -2237,8 +2241,8 @@ static int __init smsc_superio_lpc(unsigned short cfg_base)
int ret = -1;
if (!request_region(cfg_base, 2, driver_name)) {
- WARNING("%s: can't get cfg_base of 0x%03x\n",
- __FUNCTION__, cfg_base);
+ IRDA_WARNING("%s: can't get cfg_base of 0x%03x\n",
+ __FUNCTION__, cfg_base);
} else {
if (!smsc_superio_flat(lpc_chips_flat,cfg_base,"LPC")
||!smsc_superio_paged(lpc_chips_paged,cfg_base,"LPC"))
@@ -2275,8 +2279,8 @@ static void smsc_ircc_set_transceiver_smsc_ircc_atc(int fir_base, u32 speed)
outb((inb(fir_base+IRCC_ATC) & IRCC_ATC_MASK) |IRCC_ATC_nPROGREADY|IRCC_ATC_ENABLE, fir_base+IRCC_ATC);
while((val=(inb(fir_base+IRCC_ATC) & IRCC_ATC_nPROGREADY)) && !time_after(jiffies, jiffies_timeout));
if(val)
- WARNING("%s(): ATC: 0x%02x\n", __FUNCTION__,
- inb(fir_base+IRCC_ATC));
+ IRDA_WARNING("%s(): ATC: 0x%02x\n", __FUNCTION__,
+ inb(fir_base+IRCC_ATC));
}
/*
diff --git a/drivers/net/irda/stir4200.c b/drivers/net/irda/stir4200.c
index 648a7134ba774..83c605e8824c8 100644
--- a/drivers/net/irda/stir4200.c
+++ b/drivers/net/irda/stir4200.c
@@ -208,7 +208,7 @@ static int write_reg(struct stir_cb *stir, __u16 reg, __u8 value)
REQ_WRITE_SINGLE,
USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_DEVICE,
value, reg, NULL, 0,
- msecs_to_jiffies(CTRL_TIMEOUT));
+ CTRL_TIMEOUT);
}
/* Send control message to read multiple registers */
@@ -221,7 +221,7 @@ static inline int read_reg(struct stir_cb *stir, __u16 reg,
REQ_READ_REG,
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0, reg, data, count,
- msecs_to_jiffies(CTRL_TIMEOUT));
+ CTRL_TIMEOUT);
}
static inline int isfir(u32 speed)
@@ -671,7 +671,8 @@ static void turnaround_delay(const struct stir_cb *stir, long us)
return;
do_gettimeofday(&now);
- us -= (now.tv_sec - stir->rx_time.tv_sec) * USEC_PER_SEC;
+ if (now.tv_sec - stir->rx_time.tv_sec > 0)
+ us -= USEC_PER_SEC;
us -= now.tv_usec - stir->rx_time.tv_usec;
if (us < 10)
return;
@@ -740,7 +741,7 @@ static void stir_send(struct stir_cb *stir, struct sk_buff *skb)
if (usb_bulk_msg(stir->usbdev, usb_sndbulkpipe(stir->usbdev, 1),
stir->io_buf, wraplen,
- NULL, msecs_to_jiffies(TRANSMIT_TIMEOUT)))
+ NULL, TRANSMIT_TIMEOUT))
stir->stats.tx_errors++;
}
@@ -787,7 +788,7 @@ static int stir_transmit_thread(void *arg)
stir_send(stir, skb);
dev_kfree_skb(skb);
- if (stir->speed != new_speed) {
+ if ((new_speed != -1) && (stir->speed != new_speed)) {
if (fifo_txwait(stir, -1) ||
change_speed(stir, new_speed))
break;
diff --git a/drivers/net/irda/tekram-sir.c b/drivers/net/irda/tekram-sir.c
index 62708801ad687..0dd6bc7af3f2b 100644
--- a/drivers/net/irda/tekram-sir.c
+++ b/drivers/net/irda/tekram-sir.c
@@ -179,7 +179,7 @@ static int tekram_change_speed(struct sir_dev *dev, unsigned speed)
break;
default:
- ERROR("%s - undefined state %d\n", __FUNCTION__, state);
+ IRDA_ERROR("%s - undefined state %d\n", __FUNCTION__, state);
ret = -EINVAL;
break;
}
@@ -210,8 +210,7 @@ static int tekram_reset(struct sir_dev *dev)
sirdev_set_dtr_rts(dev, FALSE, TRUE);
/* Should sleep 1 ms */
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(msecs_to_jiffies(1));
+ msleep(1);
/* Set DTR, Set RTS */
sirdev_set_dtr_rts(dev, TRUE, TRUE);
diff --git a/drivers/net/irda/tekram.c b/drivers/net/irda/tekram.c
index d0de866fd9c59..8f6258221cb03 100644
--- a/drivers/net/irda/tekram.c
+++ b/drivers/net/irda/tekram.c
@@ -109,7 +109,7 @@ static int tekram_change_speed(struct irda_task *task)
IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
- ASSERT(task != NULL, return -1;);
+ IRDA_ASSERT(task != NULL, return -1;);
if (self->speed_task && self->speed_task != task) {
IRDA_DEBUG(0, "%s(), busy!\n", __FUNCTION__ );
@@ -155,7 +155,8 @@ static int tekram_change_speed(struct irda_task *task)
irda_task_next_state(task, IRDA_TASK_CHILD_DONE);
break;
case IRDA_TASK_CHILD_WAIT:
- WARNING("%s(), resetting dongle timed out!\n", __FUNCTION__);
+ IRDA_WARNING("%s(), resetting dongle timed out!\n",
+ __FUNCTION__);
ret = -1;
break;
case IRDA_TASK_CHILD_DONE:
@@ -181,7 +182,8 @@ static int tekram_change_speed(struct irda_task *task)
self->speed_task = NULL;
break;
default:
- ERROR("%s(), unknown state %d\n", __FUNCTION__, task->state);
+ IRDA_ERROR("%s(), unknown state %d\n",
+ __FUNCTION__, task->state);
irda_task_next_state(task, IRDA_TASK_DONE);
self->speed_task = NULL;
ret = -1;
@@ -210,7 +212,7 @@ int tekram_reset(struct irda_task *task)
IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
- ASSERT(task != NULL, return -1;);
+ IRDA_ASSERT(task != NULL, return -1;);
if (self->reset_task && self->reset_task != task) {
IRDA_DEBUG(0, "%s(), busy!\n", __FUNCTION__ );
@@ -249,7 +251,8 @@ int tekram_reset(struct irda_task *task)
self->reset_task = NULL;
break;
default:
- ERROR("%s(), unknown state %d\n", __FUNCTION__, task->state);
+ IRDA_ERROR("%s(), unknown state %d\n",
+ __FUNCTION__, task->state);
irda_task_next_state(task, IRDA_TASK_DONE);
self->reset_task = NULL;
ret = -1;
diff --git a/drivers/net/irda/via-ircc.c b/drivers/net/irda/via-ircc.c
index ec4cba25f5924..8bafb455c102d 100644
--- a/drivers/net/irda/via-ircc.c
+++ b/drivers/net/irda/via-ircc.c
@@ -83,7 +83,7 @@ static struct via_ircc_cb *dev_self[] = { NULL, NULL, NULL, NULL };
/* Some prototypes */
static int via_ircc_open(int i, chipio_t * info, unsigned int id);
-static int __exit via_ircc_close(struct via_ircc_cb *self);
+static int via_ircc_close(struct via_ircc_cb *self);
static int via_ircc_dma_receive(struct via_ircc_cb *self);
static int via_ircc_dma_receive_complete(struct via_ircc_cb *self,
int iobase);
@@ -111,7 +111,7 @@ static void hwreset(struct via_ircc_cb *self);
static int via_ircc_dma_xmit(struct via_ircc_cb *self, u16 iobase);
static int upload_rxdata(struct via_ircc_cb *self, int iobase);
static int __devinit via_init_one (struct pci_dev *pcidev, const struct pci_device_id *id);
-static void __exit via_remove_one (struct pci_dev *pdev);
+static void __devexit via_remove_one (struct pci_dev *pdev);
/* FIXME : Should use udelay() instead, even if we are x86 only - Jean II */
static void iodelay(int udelay)
@@ -140,7 +140,7 @@ static struct pci_driver via_driver = {
.name = VIA_MODULE_NAME,
.id_table = via_pci_tbl,
.probe = via_init_one,
- .remove = via_remove_one,
+ .remove = __devexit_p(via_remove_one),
};
@@ -273,7 +273,7 @@ static int __devinit via_init_one (struct pci_dev *pcidev, const struct pci_devi
* Close all configured chips
*
*/
-static void __exit via_ircc_clean(void)
+static void via_ircc_clean(void)
{
int i;
@@ -285,7 +285,7 @@ static void __exit via_ircc_clean(void)
}
}
-static void __exit via_remove_one (struct pci_dev *pdev)
+static void __devexit via_remove_one (struct pci_dev *pdev)
{
IRDA_DEBUG(3, "%s()\n", __FUNCTION__);
@@ -441,7 +441,7 @@ static __devinit int via_ircc_open(int i, chipio_t * info, unsigned int id)
if (err)
goto err_out4;
- MESSAGE("IrDA: Registered device %s (via-ircc)\n", dev->name);
+ IRDA_MESSAGE("IrDA: Registered device %s (via-ircc)\n", dev->name);
/* Initialise the hardware..
*/
@@ -468,13 +468,13 @@ static __devinit int via_ircc_open(int i, chipio_t * info, unsigned int id)
* Close driver instance
*
*/
-static int __exit via_ircc_close(struct via_ircc_cb *self)
+static int via_ircc_close(struct via_ircc_cb *self)
{
int iobase;
IRDA_DEBUG(3, "%s()\n", __FUNCTION__);
- ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
iobase = self->io.fir_base;
@@ -565,7 +565,7 @@ static int via_ircc_read_dongle_id(int iobase)
{
int dongle_id = 9; /* Default to IBM */
- ERROR("via-ircc: dongle probing not supported, please specify dongle_id module parameter.\n");
+ IRDA_ERROR("via-ircc: dongle probing not supported, please specify dongle_id module parameter.\n");
return dongle_id;
}
@@ -707,8 +707,8 @@ static void via_ircc_change_dongle_speed(int iobase, int speed,
break;
default:
- ERROR("%s: Error: dongle_id %d unsupported !\n",
- __FUNCTION__, dongle_id);
+ IRDA_ERROR("%s: Error: dongle_id %d unsupported !\n",
+ __FUNCTION__, dongle_id);
}
}
@@ -826,7 +826,7 @@ static int via_ircc_hard_xmit_sir(struct sk_buff *skb,
__u32 speed;
self = (struct via_ircc_cb *) dev->priv;
- ASSERT(self != NULL, return 0;);
+ IRDA_ASSERT(self != NULL, return 0;);
iobase = self->io.fir_base;
netif_stop_queue(dev);
@@ -1351,8 +1351,8 @@ static irqreturn_t via_ircc_interrupt(int irq, void *dev_id,
u8 iHostIntType, iRxIntType, iTxIntType;
if (!dev) {
- WARNING("%s: irq %d for unknown device.\n", driver_name,
- irq);
+ IRDA_WARNING("%s: irq %d for unknown device.\n", driver_name,
+ irq);
return IRQ_NONE;
}
self = (struct via_ircc_cb *) dev->priv;
@@ -1498,7 +1498,7 @@ static int via_ircc_is_receiving(struct via_ircc_cb *self)
int status = FALSE;
int iobase;
- ASSERT(self != NULL, return FALSE;);
+ IRDA_ASSERT(self != NULL, return FALSE;);
iobase = self->io.fir_base;
if (CkRxRecv(iobase, self))
@@ -1524,14 +1524,14 @@ static int via_ircc_net_open(struct net_device *dev)
IRDA_DEBUG(3, "%s()\n", __FUNCTION__);
- ASSERT(dev != NULL, return -1;);
+ IRDA_ASSERT(dev != NULL, return -1;);
self = (struct via_ircc_cb *) dev->priv;
self->stats.rx_packets = 0;
- ASSERT(self != NULL, return 0;);
+ IRDA_ASSERT(self != NULL, return 0;);
iobase = self->io.fir_base;
if (request_irq(self->io.irq, via_ircc_interrupt, 0, dev->name, dev)) {
- WARNING("%s, unable to allocate irq=%d\n", driver_name,
- self->io.irq);
+ IRDA_WARNING("%s, unable to allocate irq=%d\n", driver_name,
+ self->io.irq);
return -EAGAIN;
}
/*
@@ -1539,15 +1539,15 @@ static int via_ircc_net_open(struct net_device *dev)
* failure.
*/
if (request_dma(self->io.dma, dev->name)) {
- WARNING("%s, unable to allocate dma=%d\n", driver_name,
- self->io.dma);
+ IRDA_WARNING("%s, unable to allocate dma=%d\n", driver_name,
+ self->io.dma);
free_irq(self->io.irq, self);
return -EAGAIN;
}
if (self->io.dma2 != self->io.dma) {
if (request_dma(self->io.dma2, dev->name)) {
- WARNING("%s, unable to allocate dma2=%d\n",
- driver_name, self->io.dma2);
+ IRDA_WARNING("%s, unable to allocate dma2=%d\n",
+ driver_name, self->io.dma2);
free_irq(self->io.irq, self);
return -EAGAIN;
}
@@ -1590,9 +1590,9 @@ static int via_ircc_net_close(struct net_device *dev)
IRDA_DEBUG(3, "%s()\n", __FUNCTION__);
- ASSERT(dev != NULL, return -1;);
+ IRDA_ASSERT(dev != NULL, return -1;);
self = (struct via_ircc_cb *) dev->priv;
- ASSERT(self != NULL, return 0;);
+ IRDA_ASSERT(self != NULL, return 0;);
/* Stop device */
netif_stop_queue(dev);
@@ -1627,9 +1627,9 @@ static int via_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq,
unsigned long flags;
int ret = 0;
- ASSERT(dev != NULL, return -1;);
+ IRDA_ASSERT(dev != NULL, return -1;);
self = dev->priv;
- ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
IRDA_DEBUG(1, "%s(), %s, (cmd=0x%X)\n", __FUNCTION__, dev->name,
cmd);
/* Disable interrupts & save flags */
diff --git a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c
index f7cd2269490c7..35fad8171a01b 100644
--- a/drivers/net/irda/vlsi_ir.c
+++ b/drivers/net/irda/vlsi_ir.c
@@ -435,8 +435,8 @@ static struct vlsi_ring *vlsi_alloc_ring(struct pci_dev *pdev, struct ring_descr
if (rd->buf == NULL
|| !(busaddr = pci_map_single(pdev, rd->buf, len, dir))) {
if (rd->buf) {
- ERROR("%s: failed to create PCI-MAP for %p",
- __FUNCTION__, rd->buf);
+ IRDA_ERROR("%s: failed to create PCI-MAP for %p",
+ __FUNCTION__, rd->buf);
kfree(rd->buf);
rd->buf = NULL;
}
@@ -490,7 +490,8 @@ static int vlsi_create_hwif(vlsi_irda_dev_t *idev)
ringarea = pci_alloc_consistent(idev->pdev, HW_RING_AREA_SIZE, &idev->busaddr);
if (!ringarea) {
- ERROR("%s: insufficient memory for descriptor rings\n", __FUNCTION__);
+ IRDA_ERROR("%s: insufficient memory for descriptor rings\n",
+ __FUNCTION__);
goto out;
}
memset(ringarea, 0, HW_RING_AREA_SIZE);
@@ -587,7 +588,7 @@ static int vlsi_process_rx(struct vlsi_ring *r, struct ring_descr *rd)
}
if (!rd->skb) {
- WARNING("%s: rx packet lost\n", __FUNCTION__);
+ IRDA_WARNING("%s: rx packet lost\n", __FUNCTION__);
ret |= VLSI_RX_DROP;
goto done;
}
@@ -617,8 +618,8 @@ static void vlsi_fill_rx(struct vlsi_ring *r)
for (rd = ring_last(r); rd != NULL; rd = ring_put(r)) {
if (rd_is_active(rd)) {
- WARNING("%s: driver bug: rx descr race with hw\n",
- __FUNCTION__);
+ IRDA_WARNING("%s: driver bug: rx descr race with hw\n",
+ __FUNCTION__);
vlsi_ring_debug(r);
break;
}
@@ -677,7 +678,7 @@ static void vlsi_rx_interrupt(struct net_device *ndev)
if (ring_first(r) == NULL) {
/* we are in big trouble, if this should ever happen */
- ERROR("%s: rx ring exhausted!\n", __FUNCTION__);
+ IRDA_ERROR("%s: rx ring exhausted!\n", __FUNCTION__);
vlsi_ring_debug(r);
}
else
@@ -789,8 +790,8 @@ static int vlsi_set_baud(vlsi_irda_dev_t *idev, unsigned iobase)
config = IRCFG_SIR | IRCFG_SIRFILT | IRCFG_RXANY;
switch(baudrate) {
default:
- WARNING("%s: undefined baudrate %d - fallback to 9600!\n",
- __FUNCTION__, baudrate);
+ IRDA_WARNING("%s: undefined baudrate %d - fallback to 9600!\n",
+ __FUNCTION__, baudrate);
baudrate = 9600;
/* fallthru */
case 2400:
@@ -831,14 +832,14 @@ static int vlsi_set_baud(vlsi_irda_dev_t *idev, unsigned iobase)
config ^= IRENABLE_SIR_ON;
if (config != (IRENABLE_PHYANDCLOCK|IRENABLE_ENRXST)) {
- WARNING("%s: failed to set %s mode!\n", __FUNCTION__,
+ IRDA_WARNING("%s: failed to set %s mode!\n", __FUNCTION__,
(mode==IFF_SIR)?"SIR":((mode==IFF_MIR)?"MIR":"FIR"));
ret = -1;
}
else {
if (inw(iobase+VLSI_PIO_PHYCTL) != nphyctl) {
- WARNING("%s: failed to apply baudrate %d\n",
- __FUNCTION__, baudrate);
+ IRDA_WARNING("%s: failed to apply baudrate %d\n",
+ __FUNCTION__, baudrate);
ret = -1;
}
else {
@@ -982,8 +983,8 @@ static int vlsi_hard_start_xmit(struct sk_buff *skb, struct net_device *ndev)
*/
if (len >= r->len-5)
- WARNING("%s: possible buffer overflow with SIR wrapping!\n",
- __FUNCTION__);
+ IRDA_WARNING("%s: possible buffer overflow with SIR wrapping!\n",
+ __FUNCTION__);
}
else {
/* hw deals with MIR/FIR mode wrapping */
@@ -1050,7 +1051,7 @@ static int vlsi_hard_start_xmit(struct sk_buff *skb, struct net_device *ndev)
drop_unlock:
spin_unlock_irqrestore(&idev->lock, flags);
drop:
- WARNING("%s: dropping packet - %s\n", __FUNCTION__, msg);
+ IRDA_WARNING("%s: dropping packet - %s\n", __FUNCTION__, msg);
dev_kfree_skb_any(skb);
idev->stats.tx_errors++;
idev->stats.tx_dropped++;
@@ -1188,7 +1189,8 @@ static int vlsi_start_clock(struct pci_dev *pdev)
}
if (count < 3) {
if (clksrc == 1) { /* explicitly asked for PLL hence bail out */
- ERROR("%s: no PLL or failed to lock!\n", __FUNCTION__);
+ IRDA_ERROR("%s: no PLL or failed to lock!\n",
+ __FUNCTION__);
clkctl = CLKCTL_CLKSTP;
pci_write_config_byte(pdev, VLSI_PCI_CLKCTL, clkctl);
return -1;
@@ -1269,7 +1271,7 @@ static int vlsi_init_chip(struct pci_dev *pdev)
/* start the clock and clean the registers */
if (vlsi_start_clock(pdev)) {
- ERROR("%s: no valid clock source\n", __FUNCTION__);
+ IRDA_ERROR("%s: no valid clock source\n", __FUNCTION__);
return -1;
}
iobase = ndev->base_addr;
@@ -1400,8 +1402,8 @@ static void vlsi_tx_timeout(struct net_device *ndev)
idev->new_baud = idev->baud; /* keep current baudrate */
if (vlsi_start_hw(idev))
- ERROR("%s: failed to restart hw - %s(%s) unusable!\n",
- __FUNCTION__, PCIDEV_NAME(idev->pdev), ndev->name);
+ IRDA_ERROR("%s: failed to restart hw - %s(%s) unusable!\n",
+ __FUNCTION__, PCIDEV_NAME(idev->pdev), ndev->name);
else
netif_start_queue(ndev);
}
@@ -1445,7 +1447,8 @@ static int vlsi_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd)
irq->ifr_receiving = (fifocnt!=0) ? 1 : 0;
break;
default:
- WARNING("%s: notsupp - cmd=%04x\n", __FUNCTION__, cmd);
+ IRDA_WARNING("%s: notsupp - cmd=%04x\n",
+ __FUNCTION__, cmd);
ret = -EOPNOTSUPP;
}
@@ -1490,7 +1493,8 @@ static irqreturn_t vlsi_interrupt(int irq, void *dev_instance,
spin_unlock_irqrestore(&idev->lock,flags);
if (boguscount <= 0)
- MESSAGE("%s: too much work in interrupt!\n", __FUNCTION__);
+ IRDA_MESSAGE("%s: too much work in interrupt!\n",
+ __FUNCTION__);
return IRQ_RETVAL(handled);
}
@@ -1503,7 +1507,7 @@ static int vlsi_open(struct net_device *ndev)
char hwname[32];
if (pci_request_regions(idev->pdev, drivername)) {
- WARNING("%s: io resource busy\n", __FUNCTION__);
+ IRDA_WARNING("%s: io resource busy\n", __FUNCTION__);
goto errout;
}
ndev->base_addr = pci_resource_start(idev->pdev,0);
@@ -1517,7 +1521,8 @@ static int vlsi_open(struct net_device *ndev)
if (request_irq(ndev->irq, vlsi_interrupt, SA_SHIRQ,
drivername, ndev)) {
- WARNING("%s: couldn't get IRQ: %d\n", __FUNCTION__, ndev->irq);
+ IRDA_WARNING("%s: couldn't get IRQ: %d\n",
+ __FUNCTION__, ndev->irq);
goto errout_io;
}
@@ -1538,7 +1543,7 @@ static int vlsi_open(struct net_device *ndev)
netif_start_queue(ndev);
- MESSAGE("%s: device %s operational\n", __FUNCTION__, ndev->name);
+ IRDA_MESSAGE("%s: device %s operational\n", __FUNCTION__, ndev->name);
return 0;
@@ -1572,7 +1577,7 @@ static int vlsi_close(struct net_device *ndev)
pci_release_regions(idev->pdev);
- MESSAGE("%s: device %s stopped\n", __FUNCTION__, ndev->name);
+ IRDA_MESSAGE("%s: device %s stopped\n", __FUNCTION__, ndev->name);
return 0;
}
@@ -1593,7 +1598,7 @@ static int vlsi_irda_init(struct net_device *ndev)
if (pci_set_dma_mask(pdev,DMA_MASK_USED_BY_HW)
|| pci_set_dma_mask(pdev,DMA_MASK_MSTRPAGE)) {
- ERROR("%s: aborting due to PCI BM-DMA address limitations\n", __FUNCTION__);
+ IRDA_ERROR("%s: aborting due to PCI BM-DMA address limitations\n", __FUNCTION__);
return -1;
}
@@ -1640,18 +1645,19 @@ vlsi_irda_probe(struct pci_dev *pdev, const struct pci_device_id *id)
else
pdev->current_state = 0; /* hw must be running now */
- MESSAGE("%s: IrDA PCI controller %s detected\n",
- drivername, PCIDEV_NAME(pdev));
+ IRDA_MESSAGE("%s: IrDA PCI controller %s detected\n",
+ drivername, PCIDEV_NAME(pdev));
if ( !pci_resource_start(pdev,0)
|| !(pci_resource_flags(pdev,0) & IORESOURCE_IO) ) {
- ERROR("%s: bar 0 invalid", __FUNCTION__);
+ IRDA_ERROR("%s: bar 0 invalid", __FUNCTION__);
goto out_disable;
}
ndev = alloc_irdadev(sizeof(*idev));
if (ndev==NULL) {
- ERROR("%s: Unable to allocate device memory.\n", __FUNCTION__);
+ IRDA_ERROR("%s: Unable to allocate device memory.\n",
+ __FUNCTION__);
goto out_disable;
}
@@ -1666,7 +1672,7 @@ vlsi_irda_probe(struct pci_dev *pdev, const struct pci_device_id *id)
goto out_freedev;
if (register_netdev(ndev) < 0) {
- ERROR("%s: register_netdev failed\n", __FUNCTION__);
+ IRDA_ERROR("%s: register_netdev failed\n", __FUNCTION__);
goto out_freedev;
}
@@ -1675,7 +1681,8 @@ vlsi_irda_probe(struct pci_dev *pdev, const struct pci_device_id *id)
ent = create_proc_entry(ndev->name, S_IFREG|S_IRUGO, vlsi_proc_root);
if (!ent) {
- WARNING("%s: failed to create proc entry\n", __FUNCTION__);
+ IRDA_WARNING("%s: failed to create proc entry\n",
+ __FUNCTION__);
} else {
ent->data = ndev;
ent->proc_fops = VLSI_PROC_FOPS;
@@ -1683,7 +1690,7 @@ vlsi_irda_probe(struct pci_dev *pdev, const struct pci_device_id *id)
}
idev->proc_entry = ent;
}
- MESSAGE("%s: registered device %s\n", drivername, ndev->name);
+ IRDA_MESSAGE("%s: registered device %s\n", drivername, ndev->name);
pci_set_drvdata(pdev, ndev);
up(&idev->sem);
@@ -1706,7 +1713,7 @@ static void __devexit vlsi_irda_remove(struct pci_dev *pdev)
vlsi_irda_dev_t *idev;
if (!ndev) {
- ERROR("%s: lost netdevice?\n", drivername);
+ IRDA_ERROR("%s: lost netdevice?\n", drivername);
return;
}
@@ -1724,7 +1731,7 @@ static void __devexit vlsi_irda_remove(struct pci_dev *pdev)
pci_set_drvdata(pdev, NULL);
- MESSAGE("%s: %s removed\n", drivername, PCIDEV_NAME(pdev));
+ IRDA_MESSAGE("%s: %s removed\n", drivername, PCIDEV_NAME(pdev));
}
#ifdef CONFIG_PM
@@ -1743,12 +1750,13 @@ static int vlsi_irda_suspend(struct pci_dev *pdev, u32 state)
vlsi_irda_dev_t *idev;
if (state < 1 || state > 3 ) {
- ERROR("%s - %s: invalid pm state request: %u\n",
- __FUNCTION__, PCIDEV_NAME(pdev), state);
+ IRDA_ERROR("%s - %s: invalid pm state request: %u\n",
+ __FUNCTION__, PCIDEV_NAME(pdev), state);
return 0;
}
if (!ndev) {
- ERROR("%s - %s: no netdevice \n", __FUNCTION__, PCIDEV_NAME(pdev));
+ IRDA_ERROR("%s - %s: no netdevice \n",
+ __FUNCTION__, PCIDEV_NAME(pdev));
return 0;
}
idev = ndev->priv;
@@ -1759,8 +1767,7 @@ static int vlsi_irda_suspend(struct pci_dev *pdev, u32 state)
pdev->current_state = state;
}
else
- ERROR("%s - %s: invalid suspend request %u -> %u\n",
- __FUNCTION__, PCIDEV_NAME(pdev), pdev->current_state, state);
+ IRDA_ERROR("%s - %s: invalid suspend request %u -> %u\n", __FUNCTION__, PCIDEV_NAME(pdev), pdev->current_state, state);
up(&idev->sem);
return 0;
}
@@ -1787,14 +1794,16 @@ static int vlsi_irda_resume(struct pci_dev *pdev)
vlsi_irda_dev_t *idev;
if (!ndev) {
- ERROR("%s - %s: no netdevice \n", __FUNCTION__, PCIDEV_NAME(pdev));
+ IRDA_ERROR("%s - %s: no netdevice \n",
+ __FUNCTION__, PCIDEV_NAME(pdev));
return 0;
}
idev = ndev->priv;
down(&idev->sem);
if (pdev->current_state == 0) {
up(&idev->sem);
- WARNING("%s - %s: already resumed\n", __FUNCTION__, PCIDEV_NAME(pdev));
+ IRDA_WARNING("%s - %s: already resumed\n",
+ __FUNCTION__, PCIDEV_NAME(pdev));
return 0;
}
@@ -1813,7 +1822,7 @@ static int vlsi_irda_resume(struct pci_dev *pdev)
* now we explicitly set pdev->current_state = 0 after enabling the
* device and independently resume_ok should catch any garbage config.
*/
- WARNING("%s - hm, nothing to resume?\n", __FUNCTION__);
+ IRDA_WARNING("%s - hm, nothing to resume?\n", __FUNCTION__);
up(&idev->sem);
return 0;
}
@@ -1850,7 +1859,7 @@ static int __init vlsi_mod_init(void)
int i, ret;
if (clksrc < 0 || clksrc > 3) {
- ERROR("%s: invalid clksrc=%d\n", drivername, clksrc);
+ IRDA_ERROR("%s: invalid clksrc=%d\n", drivername, clksrc);
return -1;
}
@@ -1863,8 +1872,7 @@ static int __init vlsi_mod_init(void)
case 64:
break;
default:
- WARNING("%s: invalid %s ringsize %d, using default=8",
- drivername, (i)?"rx":"tx", ringsize[i]);
+ IRDA_WARNING("%s: invalid %s ringsize %d, using default=8", drivername, (i)?"rx":"tx", ringsize[i]);
ringsize[i] = 8;
break;
}
diff --git a/drivers/net/irda/vlsi_ir.h b/drivers/net/irda/vlsi_ir.h
index 1e947e6ad134a..414694abf588f 100644
--- a/drivers/net/irda/vlsi_ir.h
+++ b/drivers/net/irda/vlsi_ir.h
@@ -656,7 +656,7 @@ static inline void rd_set_addr_status(struct ring_descr *rd, dma_addr_t a, u8 s)
*/
if ((a & ~DMA_MASK_MSTRPAGE)>>24 != MSTRPAGE_VALUE) {
- ERROR("%s: pci busaddr inconsistency!\n", __FUNCTION__);
+ IRDA_ERROR("%s: pci busaddr inconsistency!\n", __FUNCTION__);
dump_stack();
return;
}
diff --git a/drivers/net/irda/w83977af_ir.c b/drivers/net/irda/w83977af_ir.c
index 6968584cd4d88..0ea65c4c6f854 100644
--- a/drivers/net/irda/w83977af_ir.c
+++ b/drivers/net/irda/w83977af_ir.c
@@ -245,10 +245,10 @@ int w83977af_open(int i, unsigned int iobase, unsigned int irq,
err = register_netdev(dev);
if (err) {
- ERROR("%s(), register_netdevice() failed!\n", __FUNCTION__);
+ IRDA_ERROR("%s(), register_netdevice() failed!\n", __FUNCTION__);
goto err_out3;
}
- MESSAGE("IrDA: Registered device %s\n", dev->name);
+ IRDA_MESSAGE("IrDA: Registered device %s\n", dev->name);
/* Need to store self somewhere */
dev_self[i] = self;
@@ -401,8 +401,8 @@ int w83977af_probe( int iobase, int irq, int dma)
switch_bank(iobase, SET7);
outb(0x40, iobase+7);
- MESSAGE("W83977AF (IR) driver loaded. "
- "Version: 0x%02x\n", version);
+ IRDA_MESSAGE("W83977AF (IR) driver loaded. "
+ "Version: 0x%02x\n", version);
return 0;
} else {
@@ -691,7 +691,7 @@ static void w83977af_dma_xmit_complete(struct w83977af_ir *self)
IRDA_DEBUG(4, "%s(%ld)\n", __FUNCTION__ , jiffies);
- ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self != NULL, return;);
iobase = self->io.fir_base;
@@ -743,7 +743,7 @@ int w83977af_dma_receive(struct w83977af_ir *self)
unsigned long flags;
__u8 hcr;
#endif
- ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
IRDA_DEBUG(4, "%s\n", __FUNCTION__ );
@@ -945,7 +945,7 @@ static void w83977af_pio_receive(struct w83977af_ir *self)
IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
- ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self != NULL, return;);
iobase = self->io.fir_base;
@@ -1163,7 +1163,7 @@ static int w83977af_is_receiving(struct w83977af_ir *self)
int iobase;
__u8 set;
- ASSERT(self != NULL, return FALSE;);
+ IRDA_ASSERT(self != NULL, return FALSE;);
if (self->io.speed > 115200) {
iobase = self->io.fir_base;
@@ -1197,10 +1197,10 @@ static int w83977af_net_open(struct net_device *dev)
IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
- ASSERT(dev != NULL, return -1;);
+ IRDA_ASSERT(dev != NULL, return -1;);
self = (struct w83977af_ir *) dev->priv;
- ASSERT(self != NULL, return 0;);
+ IRDA_ASSERT(self != NULL, return 0;);
iobase = self->io.fir_base;
@@ -1260,11 +1260,11 @@ static int w83977af_net_close(struct net_device *dev)
IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
- ASSERT(dev != NULL, return -1;);
+ IRDA_ASSERT(dev != NULL, return -1;);
self = (struct w83977af_ir *) dev->priv;
- ASSERT(self != NULL, return 0;);
+ IRDA_ASSERT(self != NULL, return 0;);
iobase = self->io.fir_base;
@@ -1307,11 +1307,11 @@ static int w83977af_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
unsigned long flags;
int ret = 0;
- ASSERT(dev != NULL, return -1;);
+ IRDA_ASSERT(dev != NULL, return -1;);
self = dev->priv;
- ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
IRDA_DEBUG(2, "%s(), %s, (cmd=0x%X)\n", __FUNCTION__ , dev->name, cmd);
diff --git a/drivers/net/ixgb/ixgb.h b/drivers/net/ixgb/ixgb.h
index 3426020a915b5..26c4f15f7fc0b 100644
--- a/drivers/net/ixgb/ixgb.h
+++ b/drivers/net/ixgb/ixgb.h
@@ -1,7 +1,7 @@
/*******************************************************************************
- Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
+ Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the Free
@@ -176,6 +176,7 @@ struct ixgb_adapter {
uint64_t hw_csum_tx_error;
uint32_t tx_int_delay;
boolean_t tx_int_delay_enable;
+ boolean_t detect_tx_hung;
/* RX */
struct ixgb_desc_ring rx_ring;
diff --git a/drivers/net/ixgb/ixgb_ee.c b/drivers/net/ixgb/ixgb_ee.c
index 97b5b1665ed6a..653e99f919cee 100644
--- a/drivers/net/ixgb/ixgb_ee.c
+++ b/drivers/net/ixgb/ixgb_ee.c
@@ -1,7 +1,7 @@
/*******************************************************************************
- Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
+ Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the Free
@@ -372,11 +372,11 @@ ixgb_update_eeprom_checksum(struct ixgb_hw *hw)
*
*****************************************************************************/
void
-ixgb_write_eeprom(struct ixgb_hw *hw,
- uint16_t offset,
- uint16_t data)
+ixgb_write_eeprom(struct ixgb_hw *hw, uint16_t offset, uint16_t data)
{
- /* Prepare the EEPROM for writing */
+ struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
+
+ /* Prepare the EEPROM for writing */
ixgb_setup_eeprom(hw);
/* Send the 9-bit EWEN (write enable) command to the EEPROM (5-bit opcode
@@ -410,6 +410,9 @@ ixgb_write_eeprom(struct ixgb_hw *hw,
/* Done with writing */
ixgb_cleanup_eeprom(hw);
+ /* clear the init_ctrl_reg_1 to signify that the cache is invalidated */
+ ee_map->init_ctrl_reg_1 = EEPROM_ICW1_SIGNATURE_CLEAR;
+
return;
}
@@ -478,6 +481,9 @@ ixgb_get_eeprom_data(struct ixgb_hw *hw)
if (checksum != (uint16_t) EEPROM_SUM) {
DEBUGOUT("ixgb_ee: Checksum invalid.\n");
+ /* clear the init_ctrl_reg_1 to signify that the cache is
+ * invalidated */
+ ee_map->init_ctrl_reg_1 = EEPROM_ICW1_SIGNATURE_CLEAR;
return (FALSE);
}
diff --git a/drivers/net/ixgb/ixgb_ee.h b/drivers/net/ixgb/ixgb_ee.h
index 5c473572f7fdc..5190aa8761a29 100644
--- a/drivers/net/ixgb/ixgb_ee.h
+++ b/drivers/net/ixgb/ixgb_ee.h
@@ -1,7 +1,7 @@
/*******************************************************************************
- Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
+ Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the Free
@@ -63,6 +63,7 @@
#define EEPROM_ICW1_SIGNATURE_MASK 0xC000
#define EEPROM_ICW1_SIGNATURE_VALID 0x4000
+#define EEPROM_ICW1_SIGNATURE_CLEAR 0x0000
/* For checksumming, the sum of all words in the EEPROM should equal 0xBABA. */
#define EEPROM_SUM 0xBABA
diff --git a/drivers/net/ixgb/ixgb_ethtool.c b/drivers/net/ixgb/ixgb_ethtool.c
index e3ba1410af48f..aea10e8aaa722 100644
--- a/drivers/net/ixgb/ixgb_ethtool.c
+++ b/drivers/net/ixgb/ixgb_ethtool.c
@@ -1,7 +1,7 @@
/*******************************************************************************
- Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
+ Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the Free
@@ -63,6 +63,7 @@ static struct ixgb_stats ixgb_gstrings_stats[] = {
{"tx_dropped", IXGB_STAT(net_stats.tx_dropped)},
{"multicast", IXGB_STAT(net_stats.multicast)},
{"collisions", IXGB_STAT(net_stats.collisions)},
+
/* { "rx_length_errors", IXGB_STAT(net_stats.rx_length_errors) }, */
{"rx_over_errors", IXGB_STAT(net_stats.rx_over_errors)},
{"rx_crc_errors", IXGB_STAT(net_stats.rx_crc_errors)},
@@ -98,6 +99,7 @@ static int
ixgb_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
{
struct ixgb_adapter *adapter = netdev->priv;
+
ecmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE);
ecmd->advertising = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE);
ecmd->port = PORT_FIBRE;
@@ -119,6 +121,7 @@ static int
ixgb_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
{
struct ixgb_adapter *adapter = netdev->priv;
+
if(ecmd->autoneg == AUTONEG_ENABLE ||
ecmd->speed + ecmd->duplex != SPEED_10000 + DUPLEX_FULL)
return -EINVAL;
diff --git a/drivers/net/ixgb/ixgb_hw.c b/drivers/net/ixgb/ixgb_hw.c
index 230f0d80d2f24..69329c73095ab 100644
--- a/drivers/net/ixgb/ixgb_hw.c
+++ b/drivers/net/ixgb/ixgb_hw.c
@@ -1,7 +1,7 @@
/*******************************************************************************
- Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
+ Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the Free
diff --git a/drivers/net/ixgb/ixgb_hw.h b/drivers/net/ixgb/ixgb_hw.h
index 28489285e2cef..97898efe7cc80 100644
--- a/drivers/net/ixgb/ixgb_hw.h
+++ b/drivers/net/ixgb/ixgb_hw.h
@@ -1,7 +1,7 @@
/*******************************************************************************
- Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
+ Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the Free
diff --git a/drivers/net/ixgb/ixgb_ids.h b/drivers/net/ixgb/ixgb_ids.h
index 6384643e24134..aee207eaa287e 100644
--- a/drivers/net/ixgb/ixgb_ids.h
+++ b/drivers/net/ixgb/ixgb_ids.h
@@ -1,7 +1,7 @@
/*******************************************************************************
- Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
+ Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the Free
diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c
index 435cfa165a552..7d26623d85927 100644
--- a/drivers/net/ixgb/ixgb_main.c
+++ b/drivers/net/ixgb/ixgb_main.c
@@ -1,7 +1,7 @@
/*******************************************************************************
- Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
+ Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the Free
@@ -29,6 +29,9 @@
#include "ixgb.h"
/* Change Log
+ * 1.0.88 01/05/05
+ * - include fix to the condition that determines when to quit NAPI - Robert Olsson
+ * - use netif_poll_{disable/enable} to synchronize between NAPI and i/f up/down
* 1.0.84 10/26/04
* - reset buffer_info->dma in Tx resource cleanup logic
* 1.0.83 10/12/04
@@ -38,13 +41,14 @@
char ixgb_driver_name[] = "ixgb";
char ixgb_driver_string[] = "Intel(R) PRO/10GbE Network Driver";
+
#ifndef CONFIG_IXGB_NAPI
#define DRIVERNAPI
#else
#define DRIVERNAPI "-NAPI"
#endif
-char ixgb_driver_version[] = "1.0.87-k2"DRIVERNAPI;
-char ixgb_copyright[] = "Copyright (c) 1999-2004 Intel Corporation.";
+char ixgb_driver_version[] = "1.0.90-k2"DRIVERNAPI;
+char ixgb_copyright[] = "Copyright (c) 1999-2005 Intel Corporation.";
/* ixgb_pci_tbl - PCI Device ID Table
*
@@ -292,6 +296,9 @@ ixgb_up(struct ixgb_adapter *adapter)
mod_timer(&adapter->watchdog_timer, jiffies);
ixgb_irq_enable(adapter);
+#ifdef CONFIG_IXGB_NAPI
+ netif_poll_enable(netdev);
+#endif
return 0;
}
@@ -309,6 +316,9 @@ ixgb_down(struct ixgb_adapter *adapter, boolean_t kill_watchdog)
#endif
if(kill_watchdog)
del_timer_sync(&adapter->watchdog_timer);
+#ifdef CONFIG_IXGB_NAPI
+ netif_poll_disable(netdev);
+#endif
adapter->link_speed = 0;
adapter->link_duplex = 0;
netif_carrier_off(netdev);
@@ -709,14 +719,8 @@ ixgb_configure_tx(struct ixgb_adapter *adapter)
IXGB_WRITE_REG(hw, TDH, 0);
IXGB_WRITE_REG(hw, TDT, 0);
- /* don't set up txdctl, it induces performance problems if
- * configured incorrectly
- txdctl = TXDCTL_PTHRESH_DEFAULT; // prefetch txds below this threshold
- txdctl |= (TXDCTL_HTHRESH_DEFAULT // only prefetch if there are this many ready
- << IXGB_TXDCTL_HTHRESH_SHIFT);
- IXGB_WRITE_REG (hw, TXDCTL, txdctl);
- */
-
+ /* don't set up txdctl, it induces performance problems if configured
+ * incorrectly */
/* Set the Tx Interrupt Delay register */
IXGB_WRITE_REG(hw, TIDV, adapter->tx_int_delay);
@@ -849,10 +853,17 @@ ixgb_configure_rx(struct ixgb_adapter *adapter)
IXGB_WRITE_REG(hw, RDH, 0);
IXGB_WRITE_REG(hw, RDT, 0);
- /* burst 16 or burst when RXT0*/
- rxdctl = RXDCTL_WTHRESH_DEFAULT << IXGB_RXDCTL_WTHRESH_SHIFT
- | RXDCTL_HTHRESH_DEFAULT << IXGB_RXDCTL_HTHRESH_SHIFT
- | RXDCTL_PTHRESH_DEFAULT << IXGB_RXDCTL_PTHRESH_SHIFT;
+ /* set up pre-fetching of receive buffers so we get some before we
+ * run out (default hardware behavior is to run out before fetching
+ * more). This sets up to fetch if HTHRESH rx descriptors are avail
+ * and the descriptors in hw cache are below PTHRESH. This avoids
+ * the hardware behavior of fetching <=512 descriptors in a single
+ * burst that pre-empts all other activity, usually causing fifo
+ * overflows. */
+ /* use WTHRESH to burst write 16 descriptors or burst when RXT0 */
+ rxdctl = RXDCTL_WTHRESH_DEFAULT << IXGB_RXDCTL_WTHRESH_SHIFT |
+ RXDCTL_HTHRESH_DEFAULT << IXGB_RXDCTL_HTHRESH_SHIFT |
+ RXDCTL_PTHRESH_DEFAULT << IXGB_RXDCTL_PTHRESH_SHIFT;
IXGB_WRITE_REG(hw, RXDCTL, rxdctl);
/* Enable Receive Checksum Offload for TCP and UDP */
@@ -1094,7 +1105,6 @@ ixgb_watchdog(unsigned long data)
struct ixgb_adapter *adapter = (struct ixgb_adapter *)data;
struct net_device *netdev = adapter->netdev;
struct ixgb_desc_ring *txdr = &adapter->tx_ring;
- unsigned int i;
ixgb_check_for_link(&adapter->hw);
@@ -1137,12 +1147,8 @@ ixgb_watchdog(unsigned long data)
}
}
- /* Early detection of hung controller */
- i = txdr->next_to_clean;
- if(txdr->buffer_info[i].dma &&
- time_after(jiffies, txdr->buffer_info[i].time_stamp + HZ) &&
- !(IXGB_READ_REG(&adapter->hw, STATUS) & IXGB_STATUS_TXOFF))
- netif_stop_queue(netdev);
+ /* Force detection of hung controller every watchdog period */
+ adapter->detect_tx_hung = TRUE;
/* generate an interrupt to force clean up of any stragglers */
IXGB_WRITE_REG(&adapter->hw, ICS, IXGB_INT_TXDW);
@@ -1155,7 +1161,7 @@ ixgb_watchdog(unsigned long data)
#define IXGB_TX_FLAGS_VLAN 0x00000002
#define IXGB_TX_FLAGS_TSO 0x00000004
-static inline boolean_t
+static inline int
ixgb_tso(struct ixgb_adapter *adapter, struct sk_buff *skb)
{
#ifdef NETIF_F_TSO
@@ -1163,8 +1169,15 @@ ixgb_tso(struct ixgb_adapter *adapter, struct sk_buff *skb)
unsigned int i;
uint8_t ipcss, ipcso, tucss, tucso, hdr_len;
uint16_t ipcse, tucse, mss;
+ int err;
if(likely(skb_shinfo(skb)->tso_size)) {
+ if (skb_header_cloned(skb)) {
+ err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
+ if (err)
+ return err;
+ }
+
hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2));
mss = skb_shinfo(skb)->tso_size;
skb->nh.iph->tot_len = 0;
@@ -1203,11 +1216,11 @@ ixgb_tso(struct ixgb_adapter *adapter, struct sk_buff *skb)
if(++i == adapter->tx_ring.count) i = 0;
adapter->tx_ring.next_to_use = i;
- return TRUE;
+ return 1;
}
#endif
- return FALSE;
+ return 0;
}
static inline boolean_t
@@ -1378,6 +1391,7 @@ ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
unsigned int tx_flags = 0;
unsigned long flags;
int vlan_id = 0;
+ int tso;
if(skb->len <= 0) {
dev_kfree_skb_any(skb);
@@ -1399,7 +1413,13 @@ ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
first = adapter->tx_ring.next_to_use;
- if(ixgb_tso(adapter, skb))
+ tso = ixgb_tso(adapter, skb);
+ if (tso < 0) {
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
+ }
+
+ if (tso)
tx_flags |= IXGB_TX_FLAGS_TSO;
else if(ixgb_tx_csum(adapter, skb))
tx_flags |= IXGB_TX_FLAGS_CSUM;
@@ -1668,20 +1688,16 @@ ixgb_clean(struct net_device *netdev, int *budget)
int work_to_do = min(*budget, netdev->quota);
int tx_cleaned;
int work_done = 0;
-
- if (!netif_carrier_ok(netdev))
- goto quit_polling;
tx_cleaned = ixgb_clean_tx_irq(adapter);
ixgb_clean_rx_irq(adapter, &work_done, work_to_do);
*budget -= work_done;
netdev->quota -= work_done;
-
- /* if no Tx cleanup and not enough Rx work done, exit the polling mode */
- if((!tx_cleaned && (work_done < work_to_do)) ||
- !netif_running(netdev)) {
-quit_polling: netif_rx_complete(netdev);
+
+ /* if no Tx and not enough Rx work done, exit the polling mode */
+ if((!tx_cleaned && (work_done == 0)) || !netif_running(netdev)) {
+ netif_rx_complete(netdev);
ixgb_irq_enable(adapter);
return 0;
}
@@ -1742,6 +1758,17 @@ ixgb_clean_tx_irq(struct ixgb_adapter *adapter)
}
spin_unlock(&adapter->tx_lock);
+ if(adapter->detect_tx_hung) {
+ /* 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)
+ && !(IXGB_READ_REG(&adapter->hw, STATUS) &
+ IXGB_STATUS_TXOFF))
+ netif_stop_queue(netdev);
+ }
+
return cleaned;
}
diff --git a/drivers/net/ixgb/ixgb_osdep.h b/drivers/net/ixgb/ixgb_osdep.h
index 5d254b30b93a7..9eba928919018 100644
--- a/drivers/net/ixgb/ixgb_osdep.h
+++ b/drivers/net/ixgb/ixgb_osdep.h
@@ -1,7 +1,7 @@
/*******************************************************************************
- Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
+ Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the Free
diff --git a/drivers/net/ixgb/ixgb_param.c b/drivers/net/ixgb/ixgb_param.c
index 23379279ea1a5..8a83dfdf746d6 100644
--- a/drivers/net/ixgb/ixgb_param.c
+++ b/drivers/net/ixgb/ixgb_param.c
@@ -1,7 +1,7 @@
/*******************************************************************************
- Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
+ Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the Free
diff --git a/drivers/net/jazzsonic.c b/drivers/net/jazzsonic.c
index 7046c43952660..7fec613e16754 100644
--- a/drivers/net/jazzsonic.c
+++ b/drivers/net/jazzsonic.c
@@ -14,6 +14,7 @@
*/
#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/types.h>
#include <linux/fcntl.h>
#include <linux/interrupt.h>
@@ -28,6 +29,7 @@
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/bitops.h>
+#include <linux/device.h>
#include <asm/bootinfo.h>
#include <asm/system.h>
@@ -37,7 +39,10 @@
#include <asm/jazz.h>
#include <asm/jazzdma.h>
-#define DRV_NAME "jazzsonic"
+static char jazz_sonic_string[] = "jazzsonic";
+static struct platform_device *jazz_sonic_device;
+
+#define SONIC_MEM_SIZE 0x100
#define SREGS_PAD(n) u16 n;
@@ -50,8 +55,8 @@
#define SONIC_WRITE(reg,val) \
do { \
- *((volatile unsigned int *)base_addr+reg) = val; \
-}
+ *((volatile unsigned int *)base_addr+(reg)) = (val); \
+} while (0)
/* use 0 for production, 1 for verification, >2 for debug */
@@ -80,70 +85,7 @@ static unsigned short known_revisions[] =
0xffff /* end of list */
};
-/* Index to functions, as function prototypes. */
-
-static int sonic_probe1(struct net_device *dev, unsigned int base_addr,
- unsigned int irq);
-
-
-/*
- * Probe for a SONIC ethernet controller on a Mips Jazz board.
- * Actually probing is superfluous but we're paranoid.
- */
-struct net_device * __init sonic_probe(int unit)
-{
- struct net_device *dev;
- struct sonic_local *lp;
- unsigned int base_addr;
- int err = 0;
- int i;
-
- /*
- * Don't probe if we're not running on a Jazz board.
- */
- if (mips_machgroup != MACH_GROUP_JAZZ)
- return ERR_PTR(-ENODEV);
-
- dev = alloc_etherdev(0);
- if (!dev)
- return ERR_PTR(-ENOMEM);
-
- sprintf(dev->name, "eth%d", unit);
- netdev_boot_setup_check(dev);
- base_addr = dev->base_addr;
-
- if (base_addr >= KSEG0) { /* Check a single specified location. */
- err = sonic_probe1(dev, base_addr, dev->irq);
- } else if (base_addr != 0) { /* Don't probe at all. */
- err = -ENXIO;
- } else {
- for (i = 0; sonic_portlist[i].port; i++) {
- int io = sonic_portlist[i].port;
- if (sonic_probe1(dev, io, sonic_portlist[i].irq) == 0)
- break;
- }
- if (!sonic_portlist[i].port)
- err = -ENODEV;
- }
- if (err)
- goto out;
- err = register_netdev(dev);
- if (err)
- goto out1;
- return dev;
-out1:
- lp = dev->priv;
- vdma_free(lp->rba_laddr);
- kfree(lp->rba);
- vdma_free(lp->cda_laddr);
- kfree(lp);
- release_region(dev->base_addr, 0x100);
-out:
- free_netdev(dev);
- return ERR_PTR(err);
-}
-
-static int __init sonic_probe1(struct net_device *dev, unsigned int base_addr,
+static int __init sonic_probe1(struct net_device *dev, unsigned long base_addr,
unsigned int irq)
{
static unsigned version_printed;
@@ -153,7 +95,7 @@ static int __init sonic_probe1(struct net_device *dev, unsigned int base_addr,
int err = -ENODEV;
int i;
- if (!request_region(base_addr, 0x100, DRV_NAME))
+ if (!request_mem_region(base_addr, SONIC_MEM_SIZE, jazz_sonic_string))
return -EBUSY;
/*
* get the Silicon Revision ID. If this is one of the known
@@ -233,7 +175,7 @@ static int __init sonic_probe1(struct net_device *dev, unsigned int base_addr,
memset(lp, 0, sizeof(struct sonic_local));
/* get the virtual dma address */
- lp->cda_laddr = vdma_alloc(PHYSADDR(lp),sizeof(*lp));
+ lp->cda_laddr = vdma_alloc(CPHYSADDR(lp),sizeof(*lp));
if (lp->cda_laddr == ~0UL) {
printk("%s: couldn't get DMA page entry for "
"descriptors\n", dev->name);
@@ -254,7 +196,7 @@ static int __init sonic_probe1(struct net_device *dev, unsigned int base_addr,
}
/* get virtual dma address */
- lp->rba_laddr = vdma_alloc(PHYSADDR(lp->rba),
+ lp->rba_laddr = vdma_alloc(CPHYSADDR(lp->rba),
SONIC_NUM_RRS * SONIC_RBSIZE);
if (lp->rba_laddr == ~0UL) {
printk("%s: couldn't get DMA page entry for receive "
@@ -291,7 +233,66 @@ out2:
out1:
kfree(lp);
out:
- release_region(base_addr, 0x100);
+ release_region(base_addr, SONIC_MEM_SIZE);
+ return err;
+}
+
+/*
+ * Probe for a SONIC ethernet controller on a Mips Jazz board.
+ * Actually probing is superfluous but we're paranoid.
+ */
+static int __init jazz_sonic_probe(struct device *device)
+{
+ struct net_device *dev;
+ struct sonic_local *lp;
+ unsigned long base_addr;
+ int err = 0;
+ int i;
+
+ /*
+ * Don't probe if we're not running on a Jazz board.
+ */
+ if (mips_machgroup != MACH_GROUP_JAZZ)
+ return -ENODEV;
+
+ dev = alloc_etherdev(0);
+ if (!dev)
+ return -ENOMEM;
+
+ netdev_boot_setup_check(dev);
+ base_addr = dev->base_addr;
+
+ if (base_addr >= KSEG0) { /* Check a single specified location. */
+ err = sonic_probe1(dev, base_addr, dev->irq);
+ } else if (base_addr != 0) { /* Don't probe at all. */
+ err = -ENXIO;
+ } else {
+ for (i = 0; sonic_portlist[i].port; i++) {
+ int io = sonic_portlist[i].port;
+ if (sonic_probe1(dev, io, sonic_portlist[i].irq) == 0)
+ break;
+ }
+ if (!sonic_portlist[i].port)
+ err = -ENODEV;
+ }
+ if (err)
+ goto out;
+ err = register_netdev(dev);
+ if (err)
+ goto out1;
+
+ return 0;
+
+out1:
+ lp = dev->priv;
+ vdma_free(lp->rba_laddr);
+ kfree(lp->rba);
+ vdma_free(lp->cda_laddr);
+ kfree(lp);
+ release_region(dev->base_addr, SONIC_MEM_SIZE);
+out:
+ free_netdev(dev);
+
return err;
}
@@ -304,3 +305,77 @@ out:
#define sonic_chiptomem(x) KSEG1ADDR(vdma_log2phys(x))
#include "sonic.c"
+
+static int __devexit jazz_sonic_device_remove (struct device *device)
+{
+ struct net_device *dev = device->driver_data;
+
+ unregister_netdev (dev);
+ release_region (dev->base_addr, SONIC_MEM_SIZE);
+ free_netdev (dev);
+
+ return 0;
+}
+
+static struct device_driver jazz_sonic_driver = {
+ .name = jazz_sonic_string,
+ .bus = &platform_bus_type,
+ .probe = jazz_sonic_probe,
+ .remove = __devexit_p(jazz_sonic_device_remove),
+};
+
+static void jazz_sonic_platform_release (struct device *device)
+{
+ struct platform_device *pldev;
+
+ /* free device */
+ pldev = to_platform_device (device);
+ kfree (pldev);
+}
+
+static int __init jazz_sonic_init_module(void)
+{
+ struct platform_device *pldev;
+
+ if (driver_register(&jazz_sonic_driver)) {
+ printk(KERN_ERR "Driver registration failed\n");
+ return -ENOMEM;
+ }
+
+ jazz_sonic_device = NULL;
+
+ if (!(pldev = kmalloc (sizeof (*pldev), GFP_KERNEL))) {
+ goto out_unregister;
+ }
+
+ memset(pldev, 0, sizeof (*pldev));
+ pldev->name = jazz_sonic_string;
+ pldev->id = 0;
+ pldev->dev.release = jazz_sonic_platform_release;
+ jazz_sonic_device = pldev;
+
+ if (platform_device_register (pldev)) {
+ kfree(pldev);
+ jazz_sonic_device = NULL;
+ }
+
+ return 0;
+
+out_unregister:
+ platform_device_unregister(pldev);
+
+ return -ENOMEM;
+}
+
+static void __exit jazz_sonic_cleanup_module(void)
+{
+ driver_unregister(&jazz_sonic_driver);
+
+ if (jazz_sonic_device) {
+ platform_device_unregister(jazz_sonic_device);
+ jazz_sonic_device = NULL;
+ }
+}
+
+module_init(jazz_sonic_init_module);
+module_exit(jazz_sonic_cleanup_module);
diff --git a/drivers/net/lance.c b/drivers/net/lance.c
index bc952029e145f..dec557fb6a99f 100644
--- a/drivers/net/lance.c
+++ b/drivers/net/lance.c
@@ -47,6 +47,7 @@ static const char version[] = "lance.c:v1.15ac 1999/11/13 dplatt@3do.com, becker
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/string.h>
+#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/ioport.h>
#include <linux/slab.h>
diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c
index 4bca692d62273..2ffc31708d5f4 100644
--- a/drivers/net/loopback.c
+++ b/drivers/net/loopback.c
@@ -184,7 +184,7 @@ static struct net_device_stats *get_stats(struct net_device *dev)
return stats;
}
-u32 loopback_get_link(struct net_device *dev)
+static u32 loopback_get_link(struct net_device *dev)
{
return 1;
}
diff --git a/drivers/net/lp486e.c b/drivers/net/lp486e.c
index 643a787c8cc0e..6139f06d7d2b9 100644
--- a/drivers/net/lp486e.c
+++ b/drivers/net/lp486e.c
@@ -112,8 +112,10 @@ enum commands {
CmdDiagnose = 7
};
-char *CUcmdnames[8] = { "NOP", "IASetup", "Configure", "MulticastList",
- "Tx", "TDR", "Dump", "Diagnose" };
+#if 0
+static const char *CUcmdnames[8] = { "NOP", "IASetup", "Configure", "MulticastList",
+ "Tx", "TDR", "Dump", "Diagnose" };
+#endif
/* Status word bits */
#define STAT_CX 0x8000 /* The CU finished executing a command
@@ -960,7 +962,7 @@ static void print_eth(char *add)
(unsigned char) add[12], (unsigned char) add[13]);
}
-int __init lp486e_probe(struct net_device *dev) {
+static int __init lp486e_probe(struct net_device *dev) {
struct i596_private *lp;
unsigned char eth_addr[6] = { 0, 0xaa, 0, 0, 0, 0 };
unsigned char *bios;
diff --git a/drivers/net/macsonic.c b/drivers/net/macsonic.c
index a4dde8181d253..be28c65de729e 100644
--- a/drivers/net/macsonic.c
+++ b/drivers/net/macsonic.c
@@ -638,6 +638,7 @@ cleanup_module(void)
#define vdma_free(baz)
#define sonic_chiptomem(bat) (bat)
#define PHYSADDR(quux) (quux)
+#define CPHYSADDR(quux) (quux)
#define sonic_request_irq request_irq
#define sonic_free_irq free_irq
diff --git a/drivers/net/meth.c b/drivers/net/meth.c
index 2c0f2aaadba05..e23655f5049fa 100644
--- a/drivers/net/meth.c
+++ b/drivers/net/meth.c
@@ -27,7 +27,7 @@
#include <linux/ip.h> /* struct iphdr */
#include <linux/tcp.h> /* struct tcphdr */
#include <linux/skbuff.h>
-#include <linux/mii.h> /*MII definitions */
+#include <linux/mii.h> /* MII definitions */
#include <asm/ip32/mace.h>
#include <asm/ip32/ip32_ints.h>
@@ -105,27 +105,27 @@ static inline void load_eaddr(struct net_device *dev)
(int)o2meth_eaddr[3]&0xFF,(int)o2meth_eaddr[4]&0xFF,(int)o2meth_eaddr[5]&0xFF);
for (i = 0; i < 6; i++)
dev->dev_addr[i] = o2meth_eaddr[i];
- mace_eth_write((*(u64*)o2meth_eaddr)>>16, mac_addr);
+ mace->eth.mac_addr = (*(unsigned long*)o2meth_eaddr) >> 16;
}
/*
* Waits for BUSY status of mdio bus to clear
*/
-#define WAIT_FOR_PHY(___rval) \
- while ((___rval = mace_eth_read(phy_data)) & MDIO_BUSY) { \
- udelay(25); \
+#define WAIT_FOR_PHY(___rval) \
+ while ((___rval = mace->eth.phy_data) & MDIO_BUSY) { \
+ udelay(25); \
}
/*read phy register, return value read */
static unsigned long mdio_read(struct meth_private *priv, unsigned long phyreg)
{
unsigned long rval;
WAIT_FOR_PHY(rval);
- mace_eth_write((priv->phy_addr << 5) | (phyreg & 0x1f), phy_regs);
+ mace->eth.phy_regs = (priv->phy_addr << 5) | (phyreg & 0x1f);
udelay(25);
- mace_eth_write(1, phy_trans_go);
+ mace->eth.phy_trans_go = 1;
udelay(25);
WAIT_FOR_PHY(rval);
- return rval&MDIO_DATA_MASK;
+ return rval & MDIO_DATA_MASK;
}
static int mdio_probe(struct meth_private *priv)
@@ -191,7 +191,7 @@ static void meth_check_link(struct net_device *dev)
priv->mac_ctrl |= METH_PHY_FDX;
else
priv->mac_ctrl &= ~METH_PHY_FDX;
- mace_eth_write(priv->mac_ctrl, mac_ctrl);
+ mace->eth.mac_ctrl = priv->mac_ctrl;
}
if ((priv->mac_ctrl & METH_100MBIT) ^ speed) {
@@ -200,7 +200,7 @@ static void meth_check_link(struct net_device *dev)
priv->mac_ctrl |= METH_100MBIT;
else
priv->mac_ctrl &= ~METH_100MBIT;
- mace_eth_write(priv->mac_ctrl, mac_ctrl);
+ mace->eth.mac_ctrl = priv->mac_ctrl;
}
}
@@ -214,26 +214,28 @@ static int meth_init_tx_ring(struct meth_private *priv)
return -ENOMEM;
memset(priv->tx_ring, 0, TX_RING_BUFFER_SIZE);
priv->tx_count = priv->tx_read = priv->tx_write = 0;
- mace_eth_write(priv->tx_ring_dma, tx_ring_base);
+ mace->eth.tx_ring_base = priv->tx_ring_dma;
/* Now init skb save area */
- memset(priv->tx_skbs,0,sizeof(priv->tx_skbs));
- memset(priv->tx_skb_dmas,0,sizeof(priv->tx_skb_dmas));
+ memset(priv->tx_skbs, 0, sizeof(priv->tx_skbs));
+ memset(priv->tx_skb_dmas, 0, sizeof(priv->tx_skb_dmas));
return 0;
}
static int meth_init_rx_ring(struct meth_private *priv)
{
int i;
- for(i=0;i<RX_RING_ENTRIES;i++){
- priv->rx_skbs[i]=alloc_skb(METH_RX_BUFF_SIZE,0);
- /* 8byte status vector+3quad padding + 2byte padding,
- to put data on 64bit aligned boundary */
+
+ for (i = 0; i < RX_RING_ENTRIES; i++) {
+ priv->rx_skbs[i] = alloc_skb(METH_RX_BUFF_SIZE, 0);
+ /* 8byte status vector + 3quad padding + 2byte padding,
+ * to put data on 64bit aligned boundary */
skb_reserve(priv->rx_skbs[i],METH_RX_HEAD);
priv->rx_ring[i]=(rx_packet*)(priv->rx_skbs[i]->head);
/* I'll need to re-sync it after each RX */
- priv->rx_ring_dmas[i]=dma_map_single(NULL,priv->rx_ring[i],
- METH_RX_BUFF_SIZE,DMA_FROM_DEVICE);
- mace_eth_write(priv->rx_ring_dmas[i], rx_fifo);
+ priv->rx_ring_dmas[i] =
+ dma_map_single(NULL, priv->rx_ring[i],
+ METH_RX_BUFF_SIZE, DMA_FROM_DEVICE);
+ mace->eth.rx_fifo = priv->rx_ring_dmas[i];
}
priv->rx_write = 0;
return 0;
@@ -257,10 +259,11 @@ static void meth_free_rx_ring(struct meth_private *priv)
{
int i;
- for(i=0;i<RX_RING_ENTRIES;i++) {
- dma_unmap_single(NULL,priv->rx_ring_dmas[i],METH_RX_BUFF_SIZE,DMA_FROM_DEVICE);
- priv->rx_ring[i]=0;
- priv->rx_ring_dmas[i]=0;
+ for (i = 0; i < RX_RING_ENTRIES; i++) {
+ dma_unmap_single(NULL, priv->rx_ring_dmas[i],
+ METH_RX_BUFF_SIZE, DMA_FROM_DEVICE);
+ priv->rx_ring[i] = 0;
+ priv->rx_ring_dmas[i] = 0;
kfree_skb(priv->rx_skbs[i]);
}
}
@@ -270,8 +273,9 @@ int meth_reset(struct net_device *dev)
struct meth_private *priv = (struct meth_private *) dev->priv;
/* Reset card */
- mace_eth_write(SGI_MAC_RESET, mac_ctrl);
- mace_eth_write(0, mac_ctrl);
+ mace->eth.mac_ctrl = SGI_MAC_RESET;
+ udelay(1);
+ mace->eth.mac_ctrl = 0;
udelay(25);
/* Load ethernet address */
@@ -279,24 +283,24 @@ int meth_reset(struct net_device *dev)
/* Should load some "errata", but later */
/* Check for device */
- if(mdio_probe(priv) < 0) {
+ if (mdio_probe(priv) < 0) {
DPRINTK("Unable to find PHY\n");
return -ENODEV;
}
/* Initial mode: 10 | Half-duplex | Accept normal packets */
priv->mac_ctrl = METH_ACCEPT_MCAST | METH_DEFAULT_IPG;
- if(dev->flags | IFF_PROMISC)
+ if (dev->flags | IFF_PROMISC)
priv->mac_ctrl |= METH_PROMISC;
- mace_eth_write(priv->mac_ctrl, mac_ctrl);
+ mace->eth.mac_ctrl = priv->mac_ctrl;
/* Autonegotiate speed and duplex mode */
meth_check_link(dev);
/* Now set dma control, but don't enable DMA, yet */
- priv->dma_ctrl= (4 << METH_RX_OFFSET_SHIFT) |
- (RX_RING_ENTRIES << METH_RX_DEPTH_SHIFT);
- mace_eth_write(priv->dma_ctrl, dma_ctrl);
+ priv->dma_ctrl = (4 << METH_RX_OFFSET_SHIFT) |
+ (RX_RING_ENTRIES << METH_RX_DEPTH_SHIFT);
+ mace->eth.dma_ctrl = priv->dma_ctrl;
return 0;
}
@@ -335,7 +339,7 @@ static int meth_open(struct net_device *dev)
/* Start DMA */
priv->dma_ctrl |= METH_DMA_TX_EN | /*METH_DMA_TX_INT_EN |*/
METH_DMA_RX_EN | METH_DMA_RX_INT_EN;
- mace_eth_write(priv->dma_ctrl, dma_ctrl);
+ mace->eth.dma_ctrl = priv->dma_ctrl;
DPRINTK("About to start queue\n");
netif_start_queue(dev);
@@ -359,7 +363,7 @@ static int meth_release(struct net_device *dev)
/* shut down DMA */
priv->dma_ctrl &= ~(METH_DMA_TX_EN | METH_DMA_TX_INT_EN |
METH_DMA_RX_EN | METH_DMA_RX_INT_EN);
- mace_eth_write(priv->dma_ctrl, dma_ctrl);
+ mace->eth.dma_ctrl = priv->dma_ctrl;
free_irq(dev->irq, dev);
meth_free_tx_ring(priv);
meth_free_rx_ring(priv);
@@ -373,56 +377,57 @@ static int meth_release(struct net_device *dev)
static void meth_rx(struct net_device* dev, unsigned long int_status)
{
struct sk_buff *skb;
+ unsigned long status;
struct meth_private *priv = (struct meth_private *) dev->priv;
- unsigned long fifo_rptr=(int_status&METH_INT_RX_RPTR_MASK)>>8;
+ unsigned long fifo_rptr = (int_status & METH_INT_RX_RPTR_MASK) >> 8;
+
spin_lock(&priv->meth_lock);
- priv->dma_ctrl&=~METH_DMA_RX_INT_EN;
- mace_eth_write(priv->dma_ctrl, dma_ctrl);
+ priv->dma_ctrl &= ~METH_DMA_RX_INT_EN;
+ mace->eth.dma_ctrl = priv->dma_ctrl;
spin_unlock(&priv->meth_lock);
- if (int_status & METH_INT_RX_UNDERFLOW){
- fifo_rptr=(fifo_rptr-1)&(0xF);
+ if (int_status & METH_INT_RX_UNDERFLOW) {
+ fifo_rptr = (fifo_rptr - 1) & 0x0f;
}
- while(priv->rx_write != fifo_rptr) {
- u64 status;
- dma_unmap_single(NULL,priv->rx_ring_dmas[priv->rx_write],
- METH_RX_BUFF_SIZE,DMA_FROM_DEVICE);
- status=priv->rx_ring[priv->rx_write]->status.raw;
+ while (priv->rx_write != fifo_rptr) {
+ dma_unmap_single(NULL, priv->rx_ring_dmas[priv->rx_write],
+ METH_RX_BUFF_SIZE, DMA_FROM_DEVICE);
+ status = priv->rx_ring[priv->rx_write]->status.raw;
#if MFE_DEBUG
- if(!(status&METH_RX_ST_VALID)) {
+ if (!(status & METH_RX_ST_VALID)) {
DPRINTK("Not received? status=%016lx\n",status);
}
#endif
- if((!(status&METH_RX_STATUS_ERRORS))&&(status&METH_RX_ST_VALID)){
- int len=(status&0xFFFF) - 4; /* omit CRC */
+ if ((!(status & METH_RX_STATUS_ERRORS)) && (status & METH_RX_ST_VALID)) {
+ int len = (status & 0xffff) - 4; /* omit CRC */
/* length sanity check */
- if(len < 60 || len > 1518) {
- printk(KERN_DEBUG "%s: bogus packet size: %d, status=%#2lx.\n",
+ if (len < 60 || len > 1518) {
+ printk(KERN_DEBUG "%s: bogus packet size: %ld, status=%#2lx.\n",
dev->name, priv->rx_write,
priv->rx_ring[priv->rx_write]->status.raw);
priv->stats.rx_errors++;
priv->stats.rx_length_errors++;
- skb=priv->rx_skbs[priv->rx_write];
+ skb = priv->rx_skbs[priv->rx_write];
} else {
- skb=alloc_skb(METH_RX_BUFF_SIZE,GFP_ATOMIC|GFP_DMA);
- if(!skb){
+ skb = alloc_skb(METH_RX_BUFF_SIZE, GFP_ATOMIC | GFP_DMA);
+ if (!skb) {
/* Ouch! No memory! Drop packet on the floor */
DPRINTK("No mem: dropping packet\n");
priv->stats.rx_dropped++;
- skb=priv->rx_skbs[priv->rx_write];
+ skb = priv->rx_skbs[priv->rx_write];
} else {
- struct sk_buff *skb_c=priv->rx_skbs[priv->rx_write];
- /* 8byte status vector+3quad padding + 2byte padding,
- to put data on 64bit aligned boundary */
- skb_reserve(skb,METH_RX_HEAD);
+ struct sk_buff *skb_c = priv->rx_skbs[priv->rx_write];
+ /* 8byte status vector + 3quad padding + 2byte padding,
+ * to put data on 64bit aligned boundary */
+ skb_reserve(skb, METH_RX_HEAD);
/* Write metadata, and then pass to the receive level */
- skb_put(skb_c,len);
- priv->rx_skbs[priv->rx_write]=skb;
+ skb_put(skb_c, len);
+ priv->rx_skbs[priv->rx_write] = skb;
skb_c->dev = dev;
skb_c->protocol = eth_type_trans(skb_c, dev);
dev->last_rx = jiffies;
priv->stats.rx_packets++;
- priv->stats.rx_bytes+=len;
+ priv->stats.rx_bytes += len;
netif_rx(skb_c);
}
}
@@ -445,18 +450,19 @@ static void meth_rx(struct net_device* dev, unsigned long int_status)
printk(KERN_WARNING "Carrier Event Seen\n");
#endif
}
- priv->rx_ring[priv->rx_write]=(rx_packet*)skb->head;
- priv->rx_ring[priv->rx_write]->status.raw=0;
- priv->rx_ring_dmas[priv->rx_write]=dma_map_single(NULL,priv->rx_ring[priv->rx_write],
- METH_RX_BUFF_SIZE,DMA_FROM_DEVICE);
- mace_eth_write(priv->rx_ring_dmas[priv->rx_write], rx_fifo);
+ priv->rx_ring[priv->rx_write] = (rx_packet*)skb->head;
+ priv->rx_ring[priv->rx_write]->status.raw = 0;
+ priv->rx_ring_dmas[priv->rx_write] =
+ dma_map_single(NULL, priv->rx_ring[priv->rx_write],
+ METH_RX_BUFF_SIZE, DMA_FROM_DEVICE);
+ mace->eth.rx_fifo = priv->rx_ring_dmas[priv->rx_write];
ADVANCE_RX_PTR(priv->rx_write);
}
spin_lock(&priv->meth_lock);
/* In case there was underflow, and Rx DMA was disabled */
- priv->dma_ctrl|=METH_DMA_RX_INT_EN|METH_DMA_RX_EN;
- mace_eth_write(priv->dma_ctrl, dma_ctrl);
- mace_eth_write(METH_INT_RX_THRESHOLD, int_stat);
+ priv->dma_ctrl |= METH_DMA_RX_INT_EN | METH_DMA_RX_EN;
+ mace->eth.dma_ctrl = priv->dma_ctrl;
+ mace->eth.int_stat = METH_INT_RX_THRESHOLD;
spin_unlock(&priv->meth_lock);
}
@@ -464,31 +470,31 @@ static int meth_tx_full(struct net_device *dev)
{
struct meth_private *priv = (struct meth_private *) dev->priv;
- return(priv->tx_count >= TX_RING_ENTRIES-1);
+ return (priv->tx_count >= TX_RING_ENTRIES - 1);
}
static void meth_tx_cleanup(struct net_device* dev, unsigned long int_status)
{
struct meth_private *priv = dev->priv;
- u64 status;
+ unsigned long status;
struct sk_buff *skb;
- unsigned long rptr=(int_status&TX_INFO_RPTR)>>16;
+ unsigned long rptr = (int_status&TX_INFO_RPTR) >> 16;
spin_lock(&priv->meth_lock);
/* Stop DMA notification */
priv->dma_ctrl &= ~(METH_DMA_TX_INT_EN);
- mace_eth_write(priv->dma_ctrl, dma_ctrl);
+ mace->eth.dma_ctrl = priv->dma_ctrl;
- while(priv->tx_read != rptr){
+ while (priv->tx_read != rptr) {
skb = priv->tx_skbs[priv->tx_read];
status = priv->tx_ring[priv->tx_read].header.raw;
#if MFE_DEBUG>=1
- if(priv->tx_read==priv->tx_write)
- DPRINTK("Auchi! tx_read=%d,tx_write=%d,rptr=%d?\n",priv->tx_read,priv->tx_write,rptr);
+ if (priv->tx_read == priv->tx_write)
+ DPRINTK("Auchi! tx_read=%d,tx_write=%d,rptr=%d?\n", priv->tx_read, priv->tx_write,rptr);
#endif
- if(status & METH_TX_ST_DONE) {
- if(status & METH_TX_ST_SUCCESS){
+ if (status & METH_TX_ST_DONE) {
+ if (status & METH_TX_ST_SUCCESS){
priv->stats.tx_packets++;
priv->stats.tx_bytes += skb->len;
} else {
@@ -518,19 +524,19 @@ static void meth_tx_cleanup(struct net_device* dev, unsigned long int_status)
priv->tx_skbs[priv->tx_read] = NULL;
priv->tx_ring[priv->tx_read].header.raw = 0;
priv->tx_read = (priv->tx_read+1)&(TX_RING_ENTRIES-1);
- priv->tx_count --;
+ priv->tx_count--;
}
/* wake up queue if it was stopped */
- if (netif_queue_stopped(dev) && ! meth_tx_full(dev)) {
+ if (netif_queue_stopped(dev) && !meth_tx_full(dev)) {
netif_wake_queue(dev);
}
- mace_eth_write(METH_INT_TX_EMPTY | METH_INT_TX_PKT, int_stat);
+ mace->eth.int_stat = METH_INT_TX_EMPTY | METH_INT_TX_PKT;
spin_unlock(&priv->meth_lock);
}
-static void meth_error(struct net_device* dev, u32 status)
+static void meth_error(struct net_device* dev, unsigned status)
{
struct meth_private *priv = (struct meth_private *) dev->priv;
@@ -548,17 +554,16 @@ static void meth_error(struct net_device* dev, u32 status)
if (status & (METH_INT_RX_UNDERFLOW)) {
printk(KERN_WARNING "meth: Rx underflow\n");
spin_lock(&priv->meth_lock);
- mace_eth_write(METH_INT_RX_UNDERFLOW, int_stat);
+ mace->eth.int_stat = METH_INT_RX_UNDERFLOW;
/* more underflow interrupts will be delivered,
- effectively throwing us into an infinite loop.
- Thus I stop processing Rx in this case.
- */
- priv->dma_ctrl&=~METH_DMA_RX_EN;
- mace_eth_write(priv->dma_ctrl, dma_ctrl);
+ * effectively throwing us into an infinite loop.
+ * Thus I stop processing Rx in this case. */
+ priv->dma_ctrl &= ~METH_DMA_RX_EN;
+ mace->eth.dma_ctrl = priv->dma_ctrl;
DPRINTK("Disabled meth Rx DMA temporarily\n");
spin_unlock(&priv->meth_lock);
}
- mace_eth_write(METH_INT_ERROR, int_stat);
+ mace->eth.int_stat = METH_INT_ERROR;
}
/*
@@ -570,12 +575,12 @@ static irqreturn_t meth_interrupt(int irq, void *dev_id, struct pt_regs *pregs)
struct meth_private *priv = (struct meth_private *) dev->priv;
unsigned long status;
- status = mace_eth_read(int_stat);
- while (status & 0xFF) {
+ status = mace->eth.int_stat;
+ while (status & 0xff) {
/* First handle errors - if we get Rx underflow,
- Rx DMA will be disabled, and Rx handler will reenable
- it. I don't think it's possible to get Rx underflow,
- without getting Rx interrupt */
+ * Rx DMA will be disabled, and Rx handler will reenable
+ * it. I don't think it's possible to get Rx underflow,
+ * without getting Rx interrupt */
if (status & METH_INT_ERROR) {
meth_error(dev, status);
}
@@ -589,7 +594,7 @@ static irqreturn_t meth_interrupt(int irq, void *dev_id, struct pt_regs *pregs)
/* send it to meth_rx for handling */
meth_rx(dev, status);
}
- status = mace_eth_read(int_stat);
+ status = mace->eth.int_stat;
}
return IRQ_HANDLED;
@@ -601,45 +606,45 @@ static irqreturn_t meth_interrupt(int irq, void *dev_id, struct pt_regs *pregs)
static void meth_tx_short_prepare(struct meth_private *priv,
struct sk_buff *skb)
{
- tx_packet *desc=&priv->tx_ring[priv->tx_write];
- int len = (skb->len<ETH_ZLEN)?ETH_ZLEN:skb->len;
+ tx_packet *desc = &priv->tx_ring[priv->tx_write];
+ int len = (skb->len < ETH_ZLEN) ? ETH_ZLEN : skb->len;
- desc->header.raw=METH_TX_CMD_INT_EN|(len-1)|((128-len)<<16);
+ desc->header.raw = METH_TX_CMD_INT_EN | (len-1) | ((128-len) << 16);
/* maybe I should set whole thing to 0 first... */
- memcpy(desc->data.dt+(120-len),skb->data,skb->len);
- if(skb->len < len)
- memset(desc->data.dt+120-len+skb->len,0,len-skb->len);
+ memcpy(desc->data.dt + (120 - len), skb->data, skb->len);
+ if (skb->len < len)
+ memset(desc->data.dt + 120 - len + skb->len, 0, len-skb->len);
}
#define TX_CATBUF1 BIT(25)
static void meth_tx_1page_prepare(struct meth_private *priv,
struct sk_buff *skb)
{
- tx_packet *desc=&priv->tx_ring[priv->tx_write];
+ tx_packet *desc = &priv->tx_ring[priv->tx_write];
void *buffer_data = (void *)(((unsigned long)skb->data + 7) & ~7);
int unaligned_len = (int)((unsigned long)buffer_data - (unsigned long)skb->data);
int buffer_len = skb->len - unaligned_len;
dma_addr_t catbuf;
- desc->header.raw=METH_TX_CMD_INT_EN|TX_CATBUF1|(skb->len-1);
+ desc->header.raw = METH_TX_CMD_INT_EN | TX_CATBUF1 | (skb->len - 1);
/* unaligned part */
- if(unaligned_len){
- memcpy(desc->data.dt+(120-unaligned_len),
+ if (unaligned_len) {
+ memcpy(desc->data.dt + (120 - unaligned_len),
skb->data, unaligned_len);
- desc->header.raw |= (128-unaligned_len) << 16;
+ desc->header.raw |= (128 - unaligned_len) << 16;
}
/* first page */
catbuf = dma_map_single(NULL, buffer_data, buffer_len,
DMA_TO_DEVICE);
desc->data.cat_buf[0].form.start_addr = catbuf >> 3;
- desc->data.cat_buf[0].form.len = buffer_len-1;
+ desc->data.cat_buf[0].form.len = buffer_len - 1;
}
#define TX_CATBUF2 BIT(26)
static void meth_tx_2page_prepare(struct meth_private *priv,
struct sk_buff *skb)
{
- tx_packet *desc=&priv->tx_ring[priv->tx_write];
+ tx_packet *desc = &priv->tx_ring[priv->tx_write];
void *buffer1_data = (void *)(((unsigned long)skb->data + 7) & ~7);
void *buffer2_data = (void *)PAGE_ALIGN((unsigned long)skb->data);
int unaligned_len = (int)((unsigned long)buffer1_data - (unsigned long)skb->data);
@@ -647,44 +652,44 @@ static void meth_tx_2page_prepare(struct meth_private *priv,
int buffer2_len = skb->len - buffer1_len - unaligned_len;
dma_addr_t catbuf1, catbuf2;
- desc->header.raw=METH_TX_CMD_INT_EN|TX_CATBUF1|TX_CATBUF2|(skb->len-1);
+ desc->header.raw = METH_TX_CMD_INT_EN | TX_CATBUF1 | TX_CATBUF2| (skb->len - 1);
/* unaligned part */
- if(unaligned_len){
- memcpy(desc->data.dt+(120-unaligned_len),
+ if (unaligned_len){
+ memcpy(desc->data.dt + (120 - unaligned_len),
skb->data, unaligned_len);
- desc->header.raw |= (128-unaligned_len) << 16;
+ desc->header.raw |= (128 - unaligned_len) << 16;
}
/* first page */
catbuf1 = dma_map_single(NULL, buffer1_data, buffer1_len,
DMA_TO_DEVICE);
desc->data.cat_buf[0].form.start_addr = catbuf1 >> 3;
- desc->data.cat_buf[0].form.len = buffer1_len-1;
+ desc->data.cat_buf[0].form.len = buffer1_len - 1;
/* second page */
catbuf2 = dma_map_single(NULL, buffer2_data, buffer2_len,
DMA_TO_DEVICE);
desc->data.cat_buf[1].form.start_addr = catbuf2 >> 3;
- desc->data.cat_buf[1].form.len = buffer2_len-1;
+ desc->data.cat_buf[1].form.len = buffer2_len - 1;
}
static void meth_add_to_tx_ring(struct meth_private *priv, struct sk_buff *skb)
{
/* Remember the skb, so we can free it at interrupt time */
priv->tx_skbs[priv->tx_write] = skb;
- if(skb->len <= 120) {
+ if (skb->len <= 120) {
/* Whole packet fits into descriptor */
- meth_tx_short_prepare(priv,skb);
- } else if(PAGE_ALIGN((unsigned long)skb->data) !=
- PAGE_ALIGN((unsigned long)skb->data+skb->len-1)) {
+ meth_tx_short_prepare(priv, skb);
+ } else if (PAGE_ALIGN((unsigned long)skb->data) !=
+ PAGE_ALIGN((unsigned long)skb->data + skb->len - 1)) {
/* Packet crosses page boundary */
- meth_tx_2page_prepare(priv,skb);
+ meth_tx_2page_prepare(priv, skb);
} else {
/* Packet is in one page */
- meth_tx_1page_prepare(priv,skb);
+ meth_tx_1page_prepare(priv, skb);
}
- priv->tx_write = (priv->tx_write+1) & (TX_RING_ENTRIES-1);
- mace_eth_write(priv->tx_write, tx_info);
- priv->tx_count ++;
+ priv->tx_write = (priv->tx_write + 1) & (TX_RING_ENTRIES - 1);
+ mace->eth.tx_info = priv->tx_write;
+ priv->tx_count++;
}
/*
@@ -695,10 +700,10 @@ static int meth_tx(struct sk_buff *skb, struct net_device *dev)
struct meth_private *priv = (struct meth_private *) dev->priv;
unsigned long flags;
- spin_lock_irqsave(&priv->meth_lock,flags);
+ spin_lock_irqsave(&priv->meth_lock, flags);
/* Stop DMA notification */
priv->dma_ctrl &= ~(METH_DMA_TX_INT_EN);
- mace_eth_write(priv->dma_ctrl, dma_ctrl);
+ mace->eth.dma_ctrl = priv->dma_ctrl;
meth_add_to_tx_ring(priv, skb);
dev->trans_start = jiffies; /* save the timestamp */
@@ -711,9 +716,9 @@ static int meth_tx(struct sk_buff *skb, struct net_device *dev)
/* Restart DMA notification */
priv->dma_ctrl |= METH_DMA_TX_INT_EN;
- mace_eth_write(priv->dma_ctrl, dma_ctrl);
+ mace->eth.dma_ctrl = priv->dma_ctrl;
- spin_unlock_irqrestore(&priv->meth_lock,flags);
+ spin_unlock_irqrestore(&priv->meth_lock, flags);
return 0;
}
@@ -743,11 +748,11 @@ static void meth_tx_timeout(struct net_device *dev)
meth_init_rx_ring(priv);
/* Restart dma */
- priv->dma_ctrl|=METH_DMA_TX_EN|METH_DMA_RX_EN|METH_DMA_RX_INT_EN;
- mace_eth_write(priv->dma_ctrl, dma_ctrl);
+ priv->dma_ctrl |= METH_DMA_TX_EN | METH_DMA_RX_EN | METH_DMA_RX_INT_EN;
+ mace->eth.dma_ctrl = priv->dma_ctrl;
/* Enable interrupt */
- spin_unlock_irqrestore(&priv->meth_lock,flags);
+ spin_unlock_irqrestore(&priv->meth_lock, flags);
dev->trans_start = jiffies;
netif_wake_queue(dev);
@@ -760,8 +765,14 @@ static void meth_tx_timeout(struct net_device *dev)
*/
static int meth_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
- DPRINTK("ioctl\n");
- return 0;
+ /* XXX Not yet implemented */
+ switch(cmd) {
+ case SIOCGMIIPHY:
+ case SIOCGMIIREG:
+ case SIOCSMIIREG:
+ default:
+ return -EOPNOTSUPP;
+ }
}
/*
@@ -808,7 +819,7 @@ static struct net_device *meth_init(void)
}
printk(KERN_INFO "%s: SGI MACE Ethernet rev. %d\n",
- dev->name, (unsigned int)mace_eth_read(mac_ctrl) >> 29);
+ dev->name, (unsigned int)(mace->eth.mac_ctrl >> 29));
return 0;
}
diff --git a/drivers/net/meth.h b/drivers/net/meth.h
index 3390b19856910..84960dae2a223 100644
--- a/drivers/net/meth.h
+++ b/drivers/net/meth.h
@@ -29,7 +29,7 @@
#define RX_BUCKET_SIZE 256
#undef BIT
-#define BIT(x) (1 << (x))
+#define BIT(x) (1UL << (x))
/* For more detailed explanations of what each field menas,
see Nick's great comments to #defines below (or docs, if
diff --git a/drivers/net/mii.c b/drivers/net/mii.c
index 3de5e46045d6c..c33cb3dc942b7 100644
--- a/drivers/net/mii.c
+++ b/drivers/net/mii.c
@@ -37,11 +37,15 @@ int mii_ethtool_gset(struct mii_if_info *mii, struct ethtool_cmd *ecmd)
{
struct net_device *dev = mii->dev;
u32 advert, bmcr, lpa, nego;
+ u32 advert2 = 0, bmcr2 = 0, lpa2 = 0;
ecmd->supported =
(SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |
SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII);
+ if (mii->supports_gmii)
+ ecmd->supported |= SUPPORTED_1000baseT_Half |
+ SUPPORTED_1000baseT_Full;
/* only supports twisted-pair */
ecmd->port = PORT_MII;
@@ -54,6 +58,9 @@ int mii_ethtool_gset(struct mii_if_info *mii, struct ethtool_cmd *ecmd)
ecmd->advertising = ADVERTISED_TP | ADVERTISED_MII;
advert = mii->mdio_read(dev, mii->phy_id, MII_ADVERTISE);
+ if (mii->supports_gmii)
+ advert2 = mii->mdio_read(dev, mii->phy_id, MII_CTRL1000);
+
if (advert & ADVERTISE_10HALF)
ecmd->advertising |= ADVERTISED_10baseT_Half;
if (advert & ADVERTISE_10FULL)
@@ -62,19 +69,31 @@ int mii_ethtool_gset(struct mii_if_info *mii, struct ethtool_cmd *ecmd)
ecmd->advertising |= ADVERTISED_100baseT_Half;
if (advert & ADVERTISE_100FULL)
ecmd->advertising |= ADVERTISED_100baseT_Full;
+ if (advert2 & ADVERTISE_1000HALF)
+ ecmd->advertising |= ADVERTISED_1000baseT_Half;
+ if (advert2 & ADVERTISE_1000FULL)
+ ecmd->advertising |= ADVERTISED_1000baseT_Full;
bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR);
lpa = mii->mdio_read(dev, mii->phy_id, MII_LPA);
+ if (mii->supports_gmii) {
+ bmcr2 = mii->mdio_read(dev, mii->phy_id, MII_CTRL1000);
+ lpa2 = mii->mdio_read(dev, mii->phy_id, MII_STAT1000);
+ }
if (bmcr & BMCR_ANENABLE) {
ecmd->advertising |= ADVERTISED_Autoneg;
ecmd->autoneg = AUTONEG_ENABLE;
nego = mii_nway_result(advert & lpa);
- if (nego == LPA_100FULL || nego == LPA_100HALF)
+ if ((bmcr2 & (ADVERTISE_1000HALF | ADVERTISE_1000FULL)) &
+ (lpa2 >> 2))
+ ecmd->speed = SPEED_1000;
+ else if (nego == LPA_100FULL || nego == LPA_100HALF)
ecmd->speed = SPEED_100;
else
ecmd->speed = SPEED_10;
- if (nego == LPA_100FULL || nego == LPA_10FULL) {
+ if ((lpa2 & LPA_1000FULL) || nego == LPA_100FULL ||
+ nego == LPA_10FULL) {
ecmd->duplex = DUPLEX_FULL;
mii->full_duplex = 1;
} else {
@@ -84,7 +103,9 @@ int mii_ethtool_gset(struct mii_if_info *mii, struct ethtool_cmd *ecmd)
} else {
ecmd->autoneg = AUTONEG_DISABLE;
- ecmd->speed = (bmcr & BMCR_SPEED100) ? SPEED_100 : SPEED_10;
+ ecmd->speed = ((bmcr & BMCR_SPEED1000 &&
+ (bmcr & BMCR_SPEED100) == 0) ? SPEED_1000 :
+ (bmcr & BMCR_SPEED100) ? SPEED_100 : SPEED_10);
ecmd->duplex = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF;
}
@@ -97,7 +118,9 @@ int mii_ethtool_sset(struct mii_if_info *mii, struct ethtool_cmd *ecmd)
{
struct net_device *dev = mii->dev;
- if (ecmd->speed != SPEED_10 && ecmd->speed != SPEED_100)
+ if (ecmd->speed != SPEED_10 &&
+ ecmd->speed != SPEED_100 &&
+ ecmd->speed != SPEED_1000)
return -EINVAL;
if (ecmd->duplex != DUPLEX_HALF && ecmd->duplex != DUPLEX_FULL)
return -EINVAL;
@@ -109,21 +132,30 @@ int mii_ethtool_sset(struct mii_if_info *mii, struct ethtool_cmd *ecmd)
return -EINVAL;
if (ecmd->autoneg != AUTONEG_DISABLE && ecmd->autoneg != AUTONEG_ENABLE)
return -EINVAL;
+ if ((ecmd->speed == SPEED_1000) && (!mii->supports_gmii))
+ return -EINVAL;
/* ignore supported, maxtxpkt, maxrxpkt */
if (ecmd->autoneg == AUTONEG_ENABLE) {
u32 bmcr, advert, tmp;
+ u32 advert2 = 0, tmp2 = 0;
if ((ecmd->advertising & (ADVERTISED_10baseT_Half |
ADVERTISED_10baseT_Full |
ADVERTISED_100baseT_Half |
- ADVERTISED_100baseT_Full)) == 0)
+ ADVERTISED_100baseT_Full |
+ ADVERTISED_1000baseT_Half |
+ ADVERTISED_1000baseT_Full)) == 0)
return -EINVAL;
/* advertise only what has been requested */
advert = mii->mdio_read(dev, mii->phy_id, MII_ADVERTISE);
tmp = advert & ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
+ if (mii->supports_gmii) {
+ advert2 = mii->mdio_read(dev, mii->phy_id, MII_CTRL1000);
+ tmp2 = advert2 & ~(ADVERTISE_1000HALF | ADVERTISE_1000FULL);
+ }
if (ecmd->advertising & ADVERTISED_10baseT_Half)
tmp |= ADVERTISE_10HALF;
if (ecmd->advertising & ADVERTISED_10baseT_Full)
@@ -132,10 +164,18 @@ int mii_ethtool_sset(struct mii_if_info *mii, struct ethtool_cmd *ecmd)
tmp |= ADVERTISE_100HALF;
if (ecmd->advertising & ADVERTISED_100baseT_Full)
tmp |= ADVERTISE_100FULL;
+ if (mii->supports_gmii) {
+ if (ecmd->advertising & ADVERTISED_1000baseT_Half)
+ tmp2 |= ADVERTISE_1000HALF;
+ if (ecmd->advertising & ADVERTISED_1000baseT_Full)
+ tmp2 |= ADVERTISE_1000FULL;
+ }
if (advert != tmp) {
mii->mdio_write(dev, mii->phy_id, MII_ADVERTISE, tmp);
mii->advertising = tmp;
}
+ if ((mii->supports_gmii) && (advert2 != tmp2))
+ mii->mdio_write(dev, mii->phy_id, MII_CTRL1000, tmp2);
/* turn on autonegotiation, and force a renegotiate */
bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR);
@@ -148,8 +188,11 @@ int mii_ethtool_sset(struct mii_if_info *mii, struct ethtool_cmd *ecmd)
/* turn off auto negotiation, set speed and duplexity */
bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR);
- tmp = bmcr & ~(BMCR_ANENABLE | BMCR_SPEED100 | BMCR_FULLDPLX);
- if (ecmd->speed == SPEED_100)
+ tmp = bmcr & ~(BMCR_ANENABLE | BMCR_SPEED100 |
+ BMCR_SPEED1000 | BMCR_FULLDPLX);
+ if (ecmd->speed == SPEED_1000)
+ tmp |= BMCR_SPEED1000;
+ else if (ecmd->speed == SPEED_100)
tmp |= BMCR_SPEED100;
if (ecmd->duplex == DUPLEX_FULL) {
tmp |= BMCR_FULLDPLX;
@@ -207,6 +250,7 @@ unsigned int mii_check_media (struct mii_if_info *mii,
{
unsigned int old_carrier, new_carrier;
int advertise, lpa, media, duplex;
+ int lpa2 = 0;
/* if forced media, go no further */
if (mii->force_media)
@@ -243,16 +287,20 @@ unsigned int mii_check_media (struct mii_if_info *mii,
mii->advertising = advertise;
}
lpa = mii->mdio_read(mii->dev, mii->phy_id, MII_LPA);
+ if (mii->supports_gmii)
+ lpa2 = mii->mdio_read(mii->dev, mii->phy_id, MII_STAT1000);
/* figure out media and duplex from advertise and LPA values */
media = mii_nway_result(lpa & advertise);
duplex = (media & ADVERTISE_FULL) ? 1 : 0;
+ if (lpa2 & LPA_1000FULL)
+ duplex = 1;
if (ok_to_print)
printk(KERN_INFO "%s: link up, %sMbps, %s-duplex, lpa 0x%04X\n",
mii->dev->name,
- media & (ADVERTISE_100FULL | ADVERTISE_100HALF) ?
- "100" : "10",
+ lpa2 & (LPA_1000FULL | LPA_1000HALF) ? "1000" :
+ media & (ADVERTISE_100FULL | ADVERTISE_100HALF) ? "100" : "10",
duplex ? "full" : "half",
lpa);
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c
index 362fee325e0ac..d6de213720f41 100644
--- a/drivers/net/mv643xx_eth.c
+++ b/drivers/net/mv643xx_eth.c
@@ -1,5 +1,5 @@
/*
- * drivers/net/mv64340_eth.c - Driver for MV64340X ethernet ports
+ * drivers/net/mv643xx_eth.c - Driver for MV643XX ethernet ports
* Copyright (C) 2002 Matthew Dharm <mdharm@momenco.com>
*
* Based on the 64360 driver from:
@@ -10,6 +10,12 @@
*
* Copyright (C) 2003 Ralf Baechle <ralf@linux-mips.org>
*
+ * Copyright (C) 2004-2005 MontaVista Software, Inc.
+ * Dale Farnsworth <dale@farnsworth.org>
+ *
+ * Copyright (C) 2004 Steven J. Hill <sjhill1@rockwellcollins.com>
+ * <sjhill@realitydiluted.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
@@ -24,80 +30,100 @@
* 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/version.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/config.h>
-#include <linux/sched.h>
-#include <linux/ptrace.h>
-#include <linux/fcntl.h>
-#include <linux/ioport.h>
-#include <linux/interrupt.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/ip.h>
#include <linux/init.h>
-#include <linux/in.h>
-#include <linux/pci.h>
-#include <linux/workqueue.h>
-#include <asm/smp.h>
-#include <linux/skbuff.h>
+#include <linux/dma-mapping.h>
#include <linux/tcp.h>
-#include <linux/netdevice.h>
+#include <linux/udp.h>
#include <linux/etherdevice.h>
-#include <net/ip.h>
#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/ethtool.h>
#include <asm/io.h>
#include <asm/types.h>
#include <asm/pgtable.h>
#include <asm/system.h>
+#include <asm/delay.h>
#include "mv643xx_eth.h"
/*
- * The first part is the high level driver of the gigE ethernet ports.
+ * The first part is the high level driver of the gigE ethernet ports.
*/
-/* Definition for configuring driver */
-#undef MV64340_RX_QUEUE_FILL_ON_TASK
-
/* Constants */
-#define EXTRA_BYTES 32
-#define WRAP ETH_HLEN + 2 + 4 + 16
-#define BUFFER_MTU dev->mtu + WRAP
+#define VLAN_HLEN 4
+#define FCS_LEN 4
+#define WRAP NET_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
-#ifdef MV64340_RX_FILL_ON_TASK
+#ifdef MV643XX_RX_QUEUE_FILL_ON_TASK
#define INT_CAUSE_MASK_ALL 0x00000000
#define INT_CAUSE_CHECK_BITS INT_CAUSE_UNMASK_ALL
#define INT_CAUSE_CHECK_BITS_EXT INT_CAUSE_UNMASK_ALL_EXT
#endif
+#ifdef MV643XX_CHECKSUM_OFFLOAD_TX
+#define MAX_DESCS_PER_SKB (MAX_SKB_FRAGS + 1)
+#else
+#define MAX_DESCS_PER_SKB 1
+#endif
+
+#define PHY_WAIT_ITERATIONS 1000 /* 1000 iterations * 10uS = 10mS max */
+#define PHY_WAIT_MICRO_SECONDS 10
+
/* Static function declarations */
-static int mv64340_eth_real_open(struct net_device *);
-static int mv64340_eth_real_stop(struct net_device *);
-static int mv64340_eth_change_mtu(struct net_device *, int);
-static struct net_device_stats *mv64340_eth_get_stats(struct net_device *);
+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 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);
-#ifdef MV64340_NAPI
-static int mv64340_poll(struct net_device *dev, int *budget);
+#ifdef MV643XX_NAPI
+static int mv643xx_poll(struct net_device *dev, int *budget);
#endif
+static void ethernet_phy_set(unsigned int eth_port_num, int phy_addr);
+static int ethernet_phy_detect(unsigned int eth_port_num);
+static struct ethtool_ops mv643xx_ethtool_ops;
+
+static char mv643xx_driver_name[] = "mv643xx_eth";
+static char mv643xx_driver_version[] = "1.0";
+
+static void __iomem *mv643xx_eth_shared_base;
+
+/* used to protect MV643XX_ETH_SMI_REG, which is shared across ports */
+static spinlock_t mv643xx_eth_phy_lock = SPIN_LOCK_UNLOCKED;
+
+static inline u32 mv_read(int offset)
+{
+ void *__iomem reg_base;
+
+ reg_base = mv643xx_eth_shared_base - MV643XX_ETH_SHARED_REGS;
+
+ return readl(reg_base + offset);
+}
+
+static inline void mv_write(int offset, u32 data)
+{
+ void * __iomem reg_base;
-unsigned char prom_mac_addr_base[6];
-unsigned long mv64340_sram_base;
+ reg_base = mv643xx_eth_shared_base - MV643XX_ETH_SHARED_REGS;
+ writel(data, reg_base + offset);
+}
/*
* Changes MTU (maximum transfer unit) of the gigabit ethenret port
*
- * Input : pointer to ethernet interface network device structure
- * new mtu size
- * Output : 0 upon success, -EINVAL upon failure
+ * Input : pointer to ethernet interface network device structure
+ * new mtu size
+ * Output : 0 upon success, -EINVAL upon failure
*/
-static int mv64340_eth_change_mtu(struct net_device *dev, int new_mtu)
+static int mv643xx_eth_change_mtu(struct net_device *dev, int new_mtu)
{
- struct mv64340_private *mp = netdev_priv(dev);
+ struct mv643xx_private *mp = netdev_priv(dev);
unsigned long flags;
spin_lock_irqsave(&mp->lock, flags);
@@ -108,21 +134,21 @@ static int mv64340_eth_change_mtu(struct net_device *dev, int new_mtu)
}
dev->mtu = new_mtu;
- /*
+ /*
* Stop then re-open the interface. This will allocate RX skb's with
* the new MTU.
* There is a possible danger that the open will not successed, due
* to memory is full, which might fail the open function.
*/
if (netif_running(dev)) {
- if (mv64340_eth_real_stop(dev))
+ if (mv643xx_eth_real_stop(dev))
printk(KERN_ERR
- "%s: Fatal error on stopping device\n",
- dev->name);
- if (mv64340_eth_real_open(dev))
+ "%s: Fatal error on stopping device\n",
+ dev->name);
+ if (mv643xx_eth_real_open(dev))
printk(KERN_ERR
- "%s: Fatal error on opening device\n",
- dev->name);
+ "%s: Fatal error on opening device\n",
+ dev->name);
}
spin_unlock_irqrestore(&mp->lock, flags);
@@ -130,17 +156,17 @@ static int mv64340_eth_change_mtu(struct net_device *dev, int new_mtu)
}
/*
- * mv64340_eth_rx_task
- *
+ * mv643xx_eth_rx_task
+ *
* Fills / refills RX queue on a certain gigabit ethernet port
*
- * Input : pointer to ethernet interface network device structure
- * Output : N/A
+ * Input : pointer to ethernet interface network device structure
+ * Output : N/A
*/
-static void mv64340_eth_rx_task(void *data)
+static void mv643xx_eth_rx_task(void *data)
{
- struct net_device *dev = (struct net_device *) data;
- struct mv64340_private *mp = netdev_priv(dev);
+ struct net_device *dev = (struct net_device *)data;
+ struct mv643xx_private *mp = netdev_priv(dev);
struct pkt_info pkt_info;
struct sk_buff *skb;
@@ -148,28 +174,18 @@ static void mv64340_eth_rx_task(void *data)
panic("%s: Error in test_set_bit / clear_bit", dev->name);
while (mp->rx_ring_skbs < (mp->rx_ring_size - 5)) {
- /* The +8 for buffer allignment and another 32 byte extra */
-
- skb = dev_alloc_skb(BUFFER_MTU + 8 + EXTRA_BYTES);
+ skb = dev_alloc_skb(RX_SKB_SIZE);
if (!skb)
- /* Better luck next time */
break;
mp->rx_ring_skbs++;
pkt_info.cmd_sts = ETH_RX_ENABLE_INTERRUPT;
- pkt_info.byte_cnt = dev->mtu + ETH_HLEN + 4 + 2 + EXTRA_BYTES;
- /* Allign buffer to 8 bytes */
- if (pkt_info.byte_cnt & ~0x7) {
- pkt_info.byte_cnt &= ~0x7;
- pkt_info.byte_cnt += 8;
- }
- pkt_info.buf_ptr =
- pci_map_single(0, skb->data,
- dev->mtu + ETH_HLEN + 4 + 2 + EXTRA_BYTES,
- PCI_DMA_FROMDEVICE);
+ pkt_info.byte_cnt = RX_SKB_SIZE;
+ pkt_info.buf_ptr = dma_map_single(NULL, skb->data, RX_SKB_SIZE,
+ DMA_FROM_DEVICE);
pkt_info.return_info = skb;
if (eth_rx_return_buff(mp, &pkt_info) != ETH_OK) {
printk(KERN_ERR
- "%s: Error allocating RX Ring\n", dev->name);
+ "%s: Error allocating RX Ring\n", dev->name);
break;
}
skb_reserve(skb, 2);
@@ -186,46 +202,45 @@ static void mv64340_eth_rx_task(void *data)
add_timer(&mp->timeout);
mp->rx_timer_flag = 1;
}
-#if MV64340_RX_QUEUE_FILL_ON_TASK
+#ifdef MV643XX_RX_QUEUE_FILL_ON_TASK
else {
/* Return interrupts */
- MV_WRITE(MV64340_ETH_INTERRUPT_MASK_REG(mp->port_num),
- INT_CAUSE_UNMASK_ALL);
+ mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(mp->port_num),
+ INT_CAUSE_UNMASK_ALL);
}
#endif
}
/*
- * mv64340_eth_rx_task_timer_wrapper
- *
+ * mv643xx_eth_rx_task_timer_wrapper
+ *
* Timer routine to wake up RX queue filling task. This function is
* used only in case the RX queue is empty, and all alloc_skb has
* failed (due to out of memory event).
*
- * Input : pointer to ethernet interface network device structure
- * Output : N/A
+ * Input : pointer to ethernet interface network device structure
+ * Output : N/A
*/
-static void mv64340_eth_rx_task_timer_wrapper(unsigned long data)
+static void mv643xx_eth_rx_task_timer_wrapper(unsigned long data)
{
- struct net_device *dev = (struct net_device *) data;
- struct mv64340_private *mp = netdev_priv(dev);
+ struct net_device *dev = (struct net_device *)data;
+ struct mv643xx_private *mp = netdev_priv(dev);
mp->rx_timer_flag = 0;
- mv64340_eth_rx_task((void *) data);
+ mv643xx_eth_rx_task((void *)data);
}
-
/*
- * mv64340_eth_update_mac_address
- *
+ * mv643xx_eth_update_mac_address
+ *
* Update the MAC address of the port in the address table
*
- * Input : pointer to ethernet interface network device structure
- * Output : N/A
+ * Input : pointer to ethernet interface network device structure
+ * Output : N/A
*/
-static void mv64340_eth_update_mac_address(struct net_device *dev)
+static void mv643xx_eth_update_mac_address(struct net_device *dev)
{
- struct mv64340_private *mp = netdev_priv(dev);
+ struct mv643xx_private *mp = netdev_priv(dev);
unsigned int port_num = mp->port_num;
eth_port_init_mac_tables(port_num);
@@ -234,64 +249,59 @@ static void mv64340_eth_update_mac_address(struct net_device *dev)
}
/*
- * mv64340_eth_set_rx_mode
- *
+ * mv643xx_eth_set_rx_mode
+ *
* Change from promiscuos to regular rx mode
*
- * Input : pointer to ethernet interface network device structure
- * Output : N/A
+ * Input : pointer to ethernet interface network device structure
+ * Output : N/A
*/
-static void mv64340_eth_set_rx_mode(struct net_device *dev)
+static void mv643xx_eth_set_rx_mode(struct net_device *dev)
{
- struct mv64340_private *mp = netdev_priv(dev);
+ struct mv643xx_private *mp = netdev_priv(dev);
+ u32 config_reg;
- if (dev->flags & IFF_PROMISC) {
- ethernet_set_config_reg
- (mp->port_num,
- ethernet_get_config_reg(mp->port_num) |
- ETH_UNICAST_PROMISCUOUS_MODE);
- } else {
- ethernet_set_config_reg
- (mp->port_num,
- ethernet_get_config_reg(mp->port_num) &
- ~(unsigned int) ETH_UNICAST_PROMISCUOUS_MODE);
- }
+ config_reg = ethernet_get_config_reg(mp->port_num);
+ if (dev->flags & IFF_PROMISC)
+ config_reg |= (u32) MV643XX_ETH_UNICAST_PROMISCUOUS_MODE;
+ else
+ config_reg &= ~(u32) MV643XX_ETH_UNICAST_PROMISCUOUS_MODE;
+ ethernet_set_config_reg(mp->port_num, config_reg);
}
-
/*
- * mv64340_eth_set_mac_address
- *
+ * mv643xx_eth_set_mac_address
+ *
* Change the interface's mac address.
* No special hardware thing should be done because interface is always
* put in promiscuous mode.
*
- * Input : pointer to ethernet interface network device structure and
- * a pointer to the designated entry to be added to the cache.
- * Output : zero upon success, negative upon failure
+ * Input : pointer to ethernet interface network device structure and
+ * a pointer to the designated entry to be added to the cache.
+ * Output : zero upon success, negative upon failure
*/
-static int mv64340_eth_set_mac_address(struct net_device *dev, void *addr)
+static int mv643xx_eth_set_mac_address(struct net_device *dev, void *addr)
{
int i;
for (i = 0; i < 6; i++)
/* +2 is for the offset of the HW addr type */
- dev->dev_addr[i] = ((unsigned char *) addr)[i + 2];
- mv64340_eth_update_mac_address(dev);
+ dev->dev_addr[i] = ((unsigned char *)addr)[i + 2];
+ mv643xx_eth_update_mac_address(dev);
return 0;
}
/*
- * mv64340_eth_tx_timeout
- *
+ * mv643xx_eth_tx_timeout
+ *
* Called upon a timeout on transmitting a packet
*
- * Input : pointer to ethernet interface network device structure.
- * Output : N/A
+ * Input : pointer to ethernet interface network device structure.
+ * Output : N/A
*/
-static void mv64340_eth_tx_timeout(struct net_device *dev)
+static void mv643xx_eth_tx_timeout(struct net_device *dev)
{
- struct mv64340_private *mp = netdev_priv(dev);
+ struct mv643xx_private *mp = netdev_priv(dev);
printk(KERN_INFO "%s: TX timeout ", dev->name);
@@ -300,31 +310,31 @@ static void mv64340_eth_tx_timeout(struct net_device *dev)
}
/*
- * mv64340_eth_tx_timeout_task
+ * mv643xx_eth_tx_timeout_task
*
* Actual routine to reset the adapter when a timeout on Tx has occurred
*/
-static void mv64340_eth_tx_timeout_task(struct net_device *dev)
+static void mv643xx_eth_tx_timeout_task(struct net_device *dev)
{
- struct mv64340_private *mp = netdev_priv(dev);
+ struct mv643xx_private *mp = netdev_priv(dev);
- netif_device_detach(dev);
- eth_port_reset(mp->port_num);
- eth_port_start(mp);
- netif_device_attach(dev);
+ netif_device_detach(dev);
+ eth_port_reset(mp->port_num);
+ eth_port_start(mp);
+ netif_device_attach(dev);
}
/*
- * mv64340_eth_free_tx_queue
+ * mv643xx_eth_free_tx_queue
*
- * Input : dev - a pointer to the required interface
+ * Input : dev - a pointer to the required interface
*
- * Output : 0 if was able to release skb , nonzero otherwise
+ * Output : 0 if was able to release skb , nonzero otherwise
*/
-static int mv64340_eth_free_tx_queue(struct net_device *dev,
- unsigned int eth_int_cause_ext)
+static int mv643xx_eth_free_tx_queue(struct net_device *dev,
+ unsigned int eth_int_cause_ext)
{
- struct mv64340_private *mp = netdev_priv(dev);
+ struct mv643xx_private *mp = netdev_priv(dev);
struct net_device_stats *stats = &mp->stats;
struct pkt_info pkt_info;
int released = 1;
@@ -341,33 +351,36 @@ static int mv64340_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) {
- dev_kfree_skb_irq((struct sk_buff *)
- pkt_info.return_info);
- released = 0;
if (skb_shinfo(pkt_info.return_info)->nr_frags)
- pci_unmap_page(NULL, pkt_info.buf_ptr,
- pkt_info.byte_cnt, PCI_DMA_TODEVICE);
-
- if (mp->tx_ring_skbs != 1)
- mp->tx_ring_skbs--;
- } else
- pci_unmap_page(NULL, pkt_info.buf_ptr,
- pkt_info.byte_cnt, PCI_DMA_TODEVICE);
-
- /*
- * Decrement the number of outstanding skbs counter on
- * the TX queue.
- */
- if (mp->tx_ring_skbs == 0)
- panic("ERROR - TX outstanding SKBs counter is corrupted");
+ 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);
+
+ dev_kfree_skb_irq(pkt_info.return_info);
+ released = 0;
+ /*
+ * Decrement the number of outstanding skbs counter on
+ * the TX queue.
+ */
+ if (mp->tx_ring_skbs == 0)
+ panic("ERROR - TX outstanding SKBs"
+ " counter is corrupted");
+ mp->tx_ring_skbs--;
+ } else
+ dma_unmap_page(NULL, pkt_info.buf_ptr,
+ pkt_info.byte_cnt, DMA_TO_DEVICE);
}
spin_unlock(&mp->lock);
@@ -376,60 +389,59 @@ static int mv64340_eth_free_tx_queue(struct net_device *dev,
}
/*
- * mv64340_eth_receive
+ * mv643xx_eth_receive
*
* This function is forward packets that are received from the port's
* queues toward kernel core or FastRoute them to another interface.
*
- * Input : dev - a pointer to the required interface
- * max - maximum number to receive (0 means unlimted)
+ * Input : dev - a pointer to the required interface
+ * max - maximum number to receive (0 means unlimted)
*
- * Output : number of served packets
+ * Output : number of served packets
*/
-#ifdef MV64340_NAPI
-static int mv64340_eth_receive_queue(struct net_device *dev, unsigned int max,
- int budget)
+#ifdef MV643XX_NAPI
+static int mv643xx_eth_receive_queue(struct net_device *dev, int budget)
#else
-static int mv64340_eth_receive_queue(struct net_device *dev, unsigned int max)
+static int mv643xx_eth_receive_queue(struct net_device *dev)
#endif
{
- struct mv64340_private *mp = netdev_priv(dev);
+ struct mv643xx_private *mp = netdev_priv(dev);
struct net_device_stats *stats = &mp->stats;
unsigned int received_packets = 0;
struct sk_buff *skb;
struct pkt_info pkt_info;
-#ifdef MV64340_NAPI
+#ifdef MV643XX_NAPI
while (eth_port_receive(mp, &pkt_info) == ETH_OK && budget > 0) {
#else
- while ((--max) && eth_port_receive(mp, &pkt_info) == ETH_OK) {
+ while (eth_port_receive(mp, &pkt_info) == ETH_OK) {
#endif
mp->rx_ring_skbs--;
received_packets++;
-#ifdef MV64340_NAPI
+#ifdef MV643XX_NAPI
budget--;
#endif
/* Update statistics. Note byte count includes 4 byte CRC count */
stats->rx_packets++;
stats->rx_bytes += pkt_info.byte_cnt;
- skb = (struct sk_buff *) pkt_info.return_info;
+ skb = pkt_info.return_info;
/*
* In case received a packet without first / last bits on OR
* the error summary bit is on, the packets needs to be dropeed.
*/
if (((pkt_info.cmd_sts
- & (ETH_RX_FIRST_DESC | ETH_RX_LAST_DESC)) !=
- (ETH_RX_FIRST_DESC | ETH_RX_LAST_DESC))
- || (pkt_info.cmd_sts & ETH_ERROR_SUMMARY)) {
+ & (ETH_RX_FIRST_DESC | ETH_RX_LAST_DESC)) !=
+ (ETH_RX_FIRST_DESC | ETH_RX_LAST_DESC))
+ || (pkt_info.cmd_sts & ETH_ERROR_SUMMARY)) {
stats->rx_dropped++;
if ((pkt_info.cmd_sts & (ETH_RX_FIRST_DESC |
- ETH_RX_LAST_DESC)) !=
- (ETH_RX_FIRST_DESC | ETH_RX_LAST_DESC)) {
+ ETH_RX_LAST_DESC)) !=
+ (ETH_RX_FIRST_DESC | ETH_RX_LAST_DESC)) {
if (net_ratelimit())
printk(KERN_ERR
- "%s: Received packet spread on multiple"
- " descriptors\n",
- dev->name);
+ "%s: Received packet spread "
+ "on multiple descriptors\n",
+ dev->name);
}
if (pkt_info.cmd_sts & ETH_ERROR_SUMMARY)
stats->rx_errors++;
@@ -445,11 +457,11 @@ static int mv64340_eth_receive_queue(struct net_device *dev, unsigned int max)
if (pkt_info.cmd_sts & ETH_LAYER_4_CHECKSUM_OK) {
skb->ip_summed = CHECKSUM_UNNECESSARY;
- skb->csum = htons((pkt_info.cmd_sts
- & 0x0007fff8) >> 3);
+ skb->csum = htons(
+ (pkt_info.cmd_sts & 0x0007fff8) >> 3);
}
skb->protocol = eth_type_trans(skb, dev);
-#ifdef MV64340_NAPI
+#ifdef MV643XX_NAPI
netif_receive_skb(skb);
#else
netif_rx(skb);
@@ -461,74 +473,74 @@ static int mv64340_eth_receive_queue(struct net_device *dev, unsigned int max)
}
/*
- * mv64340_eth_int_handler
+ * mv643xx_eth_int_handler
*
* Main interrupt handler for the gigbit ethernet ports
*
- * Input : irq - irq number (not used)
- * dev_id - a pointer to the required interface's data structure
- * regs - not used
- * Output : N/A
+ * Input : irq - irq number (not used)
+ * dev_id - a pointer to the required interface's data structure
+ * regs - not used
+ * Output : N/A
*/
-static irqreturn_t mv64340_eth_int_handler(int irq, void *dev_id,
- struct pt_regs *regs)
+static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id,
+ struct pt_regs *regs)
{
- struct net_device *dev = (struct net_device *) dev_id;
- struct mv64340_private *mp = netdev_priv(dev);
+ struct net_device *dev = (struct net_device *)dev_id;
+ struct mv643xx_private *mp = netdev_priv(dev);
u32 eth_int_cause, eth_int_cause_ext = 0;
unsigned int port_num = mp->port_num;
/* Read interrupt cause registers */
- eth_int_cause = MV_READ(MV64340_ETH_INTERRUPT_CAUSE_REG(port_num)) &
- INT_CAUSE_UNMASK_ALL;
+ eth_int_cause = mv_read(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num)) &
+ INT_CAUSE_UNMASK_ALL;
if (eth_int_cause & BIT1)
- eth_int_cause_ext =
- MV_READ(MV64340_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num)) &
- INT_CAUSE_UNMASK_ALL_EXT;
+ eth_int_cause_ext = mv_read(
+ MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num)) &
+ INT_CAUSE_UNMASK_ALL_EXT;
-#ifdef MV64340_NAPI
+#ifdef MV643XX_NAPI
if (!(eth_int_cause & 0x0007fffd)) {
- /* Dont ack the Rx interrupt */
+ /* Dont ack the Rx interrupt */
#endif
/*
- * Clear specific ethernet port intrerrupt registers by
+ * Clear specific ethernet port intrerrupt registers by
* acknowleding relevant bits.
*/
- MV_WRITE(MV64340_ETH_INTERRUPT_CAUSE_REG(port_num),
- ~eth_int_cause);
+ mv_write(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num),
+ ~eth_int_cause);
if (eth_int_cause_ext != 0x0)
- MV_WRITE(MV64340_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num),
- ~eth_int_cause_ext);
+ mv_write(MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG
+ (port_num), ~eth_int_cause_ext);
/* UDP change : We may need this */
if ((eth_int_cause_ext & 0x0000ffff) &&
- (mv64340_eth_free_tx_queue(dev, eth_int_cause_ext) == 0) &&
- (MV64340_TX_QUEUE_SIZE > mp->tx_ring_skbs + 1))
- netif_wake_queue(dev);
-#ifdef MV64340_NAPI
+ (mv643xx_eth_free_tx_queue(dev, eth_int_cause_ext) == 0) &&
+ (mp->tx_ring_size > mp->tx_ring_skbs + MAX_DESCS_PER_SKB))
+ netif_wake_queue(dev);
+#ifdef MV643XX_NAPI
} else {
if (netif_rx_schedule_prep(dev)) {
/* Mask all the interrupts */
- MV_WRITE(MV64340_ETH_INTERRUPT_MASK_REG(port_num),0);
- MV_WRITE(MV64340_ETH_INTERRUPT_EXTEND_MASK_REG(port_num), 0);
+ mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), 0);
+ mv_write(MV643XX_ETH_INTERRUPT_EXTEND_MASK_REG
+ (port_num), 0);
__netif_rx_schedule(dev);
}
#else
- {
if (eth_int_cause & (BIT2 | BIT11))
- mv64340_eth_receive_queue(dev, 0);
+ mv643xx_eth_receive_queue(dev, 0);
/*
- * After forwarded received packets to upper layer, add a task
+ * After forwarded received packets to upper layer, add a task
* in an interrupts enabled context that refills the RX ring
* with skb's.
*/
-#if MV64340_RX_QUEUE_FILL_ON_TASK
+#ifdef MV643XX_RX_QUEUE_FILL_ON_TASK
/* Unmask all interrupts on ethernet port */
- MV_WRITE(MV64340_ETH_INTERRUPT_MASK_REG(port_num),
- INT_CAUSE_MASK_ALL);
+ mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num),
+ INT_CAUSE_MASK_ALL);
queue_task(&mp->rx_task, &tq_immediate);
mark_bh(IMMEDIATE_BH);
#else
@@ -538,25 +550,15 @@ static irqreturn_t mv64340_eth_int_handler(int irq, void *dev_id,
}
/* PHY status changed */
if (eth_int_cause_ext & (BIT16 | BIT20)) {
- unsigned int phy_reg_data;
-
- /* Check Link status on ethernet port */
- eth_port_read_smi_reg(port_num, 1, &phy_reg_data);
- if (!(phy_reg_data & 0x20)) {
- netif_stop_queue(dev);
- } else {
+ if (eth_port_link_is_up(port_num)) {
+ netif_carrier_on(dev);
netif_wake_queue(dev);
-
- /*
- * Start all TX queues on ethernet port. This is good in
- * case of previous packets where not transmitted, due
- * to link down and this command re-enables all TX
- * queues.
- * Note that it is possible to get a TX resource error
- * interrupt after issuing this, since not all TX queues
- * are enabled, or has anything to send.
- */
- MV_WRITE(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(port_num), 1);
+ /* Start TX queue */
+ mv_write(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG
+ (port_num), 1);
+ } else {
+ netif_carrier_off(dev);
+ netif_stop_queue(dev);
}
}
@@ -570,7 +572,7 @@ static irqreturn_t mv64340_eth_int_handler(int irq, void *dev_id,
return IRQ_HANDLED;
}
-#ifdef MV64340_COAL
+#ifdef MV643XX_COAL
/*
* eth_port_set_rx_coal - Sets coalescing interrupt mechanism on RX path
@@ -584,9 +586,9 @@ static irqreturn_t mv64340_eth_int_handler(int irq, void *dev_id,
* , and the required delay of the interrupt in usec.
*
* INPUT:
- * unsigned int eth_port_num Ethernet port number
- * unsigned int t_clk t_clk of the MV-643xx chip in HZ units
- * unsigned int delay Delay in usec
+ * unsigned int eth_port_num Ethernet port number
+ * unsigned int t_clk t_clk of the MV-643xx chip in HZ units
+ * unsigned int delay Delay in usec
*
* OUTPUT:
* Interrupt coalescing mechanism value is set in MV-643xx chip.
@@ -596,15 +598,15 @@ static irqreturn_t mv64340_eth_int_handler(int irq, void *dev_id,
*
*/
static unsigned int eth_port_set_rx_coal(unsigned int eth_port_num,
- unsigned int t_clk, unsigned int delay)
+ unsigned int t_clk, unsigned int delay)
{
unsigned int coal = ((t_clk / 1000000) * delay) / 64;
/* Set RX Coalescing mechanism */
- MV_WRITE(MV64340_ETH_SDMA_CONFIG_REG(eth_port_num),
- ((coal & 0x3fff) << 8) |
- (MV_READ(MV64340_ETH_SDMA_CONFIG_REG(eth_port_num))
- & 0xffc000ff));
+ mv_write(MV643XX_ETH_SDMA_CONFIG_REG(eth_port_num),
+ ((coal & 0x3fff) << 8) |
+ (mv_read(MV643XX_ETH_SDMA_CONFIG_REG(eth_port_num))
+ & 0xffc000ff));
return coal;
}
@@ -618,13 +620,13 @@ static unsigned int eth_port_set_rx_coal(unsigned int eth_port_num,
* This parameter is a timeout counter, that counts in 64 t_clk
* chunks ; that when timeout event occurs a maskable interrupt
* occurs.
- * The parameter is calculated using the t_cLK frequency of the
+ * The parameter is calculated using the t_cLK frequency of the
* MV-643xx chip and the required delay in the interrupt in uSec
*
* INPUT:
- * unsigned int eth_port_num Ethernet port number
- * unsigned int t_clk t_clk of the MV-643xx chip in HZ units
- * unsigned int delay Delay in uSeconds
+ * unsigned int eth_port_num Ethernet port number
+ * unsigned int t_clk t_clk of the MV-643xx chip in HZ units
+ * unsigned int delay Delay in uSeconds
*
* OUTPUT:
* Interrupt coalescing mechanism value is set in MV-643xx chip.
@@ -634,48 +636,48 @@ static unsigned int eth_port_set_rx_coal(unsigned int eth_port_num,
*
*/
static unsigned int eth_port_set_tx_coal(unsigned int eth_port_num,
- unsigned int t_clk, unsigned int delay)
+ unsigned int t_clk, unsigned int delay)
{
unsigned int coal;
coal = ((t_clk / 1000000) * delay) / 64;
/* Set TX Coalescing mechanism */
- MV_WRITE(MV64340_ETH_TX_FIFO_URGENT_THRESHOLD_REG(eth_port_num),
- coal << 4);
+ mv_write(MV643XX_ETH_TX_FIFO_URGENT_THRESHOLD_REG(eth_port_num),
+ coal << 4);
return coal;
}
/*
- * mv64340_eth_open
+ * 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
+ * Input : a pointer to the network device structure
*
- * Output : zero of success , nonzero if fails.
+ * Output : zero of success , nonzero if fails.
*/
-static int mv64340_eth_open(struct net_device *dev)
+static int mv643xx_eth_open(struct net_device *dev)
{
- struct mv64340_private *mp = netdev_priv(dev);
+ struct mv643xx_private *mp = netdev_priv(dev);
unsigned int port_num = mp->port_num;
- int err = err;
+ int err;
spin_lock_irq(&mp->lock);
- err = request_irq(dev->irq, mv64340_eth_int_handler,
- SA_INTERRUPT | SA_SAMPLE_RANDOM, dev->name, dev);
+ err = request_irq(dev->irq, mv643xx_eth_int_handler,
+ SA_INTERRUPT | SA_SAMPLE_RANDOM, dev->name, dev);
if (err) {
- printk(KERN_ERR "Can not assign IRQ number to MV64340_eth%d\n",
- port_num);
+ printk(KERN_ERR "Can not assign IRQ number to MV643XX_eth%d\n",
+ port_num);
err = -EAGAIN;
goto out;
}
- if (mv64340_eth_real_open(dev)) {
+ if (mv643xx_eth_real_open(dev)) {
printk("%s: Error opening interface\n", dev->name);
err = -EBUSY;
goto out_free;
@@ -698,66 +700,35 @@ out:
* ether_init_rx_desc_ring - Curve a Rx chain desc list and buffer in memory.
*
* DESCRIPTION:
- * This function prepares a Rx chained list of descriptors and packet
- * buffers in a form of a ring. The routine must be called after port
- * initialization routine and before port start routine.
- * The Ethernet SDMA engine uses CPU bus addresses to access the various
- * devices in the system (i.e. DRAM). This function uses the ethernet
- * struct 'virtual to physical' routine (set by the user) to set the ring
- * with physical addresses.
+ * This function prepares a Rx chained list of descriptors and packet
+ * buffers in a form of a ring. The routine must be called after port
+ * initialization routine and before port start routine.
+ * The Ethernet SDMA engine uses CPU bus addresses to access the various
+ * devices in the system (i.e. DRAM). This function uses the ethernet
+ * struct 'virtual to physical' routine (set by the user) to set the ring
+ * with physical addresses.
*
* INPUT:
- * struct mv64340_private *mp Ethernet Port Control srtuct.
- * int rx_desc_num Number of Rx descriptors
- * int rx_buff_size Size of Rx buffer
- * unsigned int rx_desc_base_addr Rx descriptors memory area base addr.
- * unsigned int rx_buff_base_addr Rx buffer memory area base addr.
+ * struct mv643xx_private *mp Ethernet Port Control srtuct.
*
* OUTPUT:
- * The routine updates the Ethernet port control struct with information
- * regarding the Rx descriptors and buffers.
+ * The routine updates the Ethernet port control struct with information
+ * regarding the Rx descriptors and buffers.
*
* RETURN:
- * false if the given descriptors memory area is not aligned according to
- * Ethernet SDMA specifications.
- * true otherwise.
+ * None.
*/
-static int ether_init_rx_desc_ring(struct mv64340_private * mp,
- unsigned long rx_buff_base_addr)
+static void ether_init_rx_desc_ring(struct mv643xx_private *mp)
{
- unsigned long buffer_addr = rx_buff_base_addr;
volatile struct eth_rx_desc *p_rx_desc;
int rx_desc_num = mp->rx_ring_size;
- unsigned long rx_desc_base_addr = (unsigned long) mp->p_rx_desc_area;
- int rx_buff_size = 1536; /* Dummy, will be replaced later */
int i;
- p_rx_desc = (struct eth_rx_desc *) rx_desc_base_addr;
-
- /* Rx desc Must be 4LW aligned (i.e. Descriptor_Address[3:0]=0000). */
- if (rx_buff_base_addr & 0xf)
- return 0;
-
- /* Rx buffers are limited to 64K bytes and Minimum size is 8 bytes */
- if ((rx_buff_size < 8) || (rx_buff_size > RX_BUFFER_MAX_SIZE))
- return 0;
-
- /* Rx buffers must be 64-bit aligned. */
- if ((rx_buff_base_addr + rx_buff_size) & 0x7)
- return 0;
-
- /* initialize the Rx descriptors ring */
+ /* initialize the next_desc_ptr links in the Rx descriptors ring */
+ p_rx_desc = (struct eth_rx_desc *)mp->p_rx_desc_area;
for (i = 0; i < rx_desc_num; i++) {
- p_rx_desc[i].buf_size = rx_buff_size;
- p_rx_desc[i].byte_cnt = 0x0000;
- p_rx_desc[i].cmd_sts =
- ETH_BUFFER_OWNED_BY_DMA | ETH_RX_ENABLE_INTERRUPT;
p_rx_desc[i].next_desc_ptr = mp->rx_desc_dma +
((i + 1) % rx_desc_num) * sizeof(struct eth_rx_desc);
- p_rx_desc[i].buf_ptr = buffer_addr;
-
- mp->rx_skb[i] = NULL;
- buffer_addr += rx_buff_size;
}
/* Save Rx desc pointer to driver struct. */
@@ -766,293 +737,288 @@ static int ether_init_rx_desc_ring(struct mv64340_private * mp,
mp->rx_desc_area_size = rx_desc_num * sizeof(struct eth_rx_desc);
+ /* Add the queue to the list of RX queues of this port */
mp->port_rx_queue_command |= 1;
-
- return 1;
}
/*
* ether_init_tx_desc_ring - Curve a Tx chain desc list and buffer in memory.
*
* DESCRIPTION:
- * This function prepares a Tx chained list of descriptors and packet
- * buffers in a form of a ring. The routine must be called after port
- * initialization routine and before port start routine.
- * The Ethernet SDMA engine uses CPU bus addresses to access the various
- * devices in the system (i.e. DRAM). This function uses the ethernet
- * struct 'virtual to physical' routine (set by the user) to set the ring
- * with physical addresses.
+ * This function prepares a Tx chained list of descriptors and packet
+ * buffers in a form of a ring. The routine must be called after port
+ * initialization routine and before port start routine.
+ * The Ethernet SDMA engine uses CPU bus addresses to access the various
+ * devices in the system (i.e. DRAM). This function uses the ethernet
+ * struct 'virtual to physical' routine (set by the user) to set the ring
+ * with physical addresses.
*
* INPUT:
- * struct mv64340_private *mp Ethernet Port Control srtuct.
- * int tx_desc_num Number of Tx descriptors
- * int tx_buff_size Size of Tx buffer
- * unsigned int tx_desc_base_addr Tx descriptors memory area base addr.
+ * struct mv643xx_private *mp Ethernet Port Control srtuct.
*
* OUTPUT:
- * The routine updates the Ethernet port control struct with information
- * regarding the Tx descriptors and buffers.
+ * The routine updates the Ethernet port control struct with information
+ * regarding the Tx descriptors and buffers.
*
* RETURN:
- * false if the given descriptors memory area is not aligned according to
- * Ethernet SDMA specifications.
- * true otherwise.
+ * None.
*/
-static int ether_init_tx_desc_ring(struct mv64340_private *mp)
+static void ether_init_tx_desc_ring(struct mv643xx_private *mp)
{
- unsigned long tx_desc_base_addr = (unsigned long) mp->p_tx_desc_area;
int tx_desc_num = mp->tx_ring_size;
struct eth_tx_desc *p_tx_desc;
int i;
- /* Tx desc Must be 4LW aligned (i.e. Descriptor_Address[3:0]=0000). */
- if (tx_desc_base_addr & 0xf)
- return 0;
-
- /* save the first desc pointer to link with the last descriptor */
- p_tx_desc = (struct eth_tx_desc *) tx_desc_base_addr;
-
- /* Initialize the Tx descriptors ring */
+ /* Initialize the next_desc_ptr links in the Tx descriptors ring */
+ p_tx_desc = (struct eth_tx_desc *)mp->p_tx_desc_area;
for (i = 0; i < tx_desc_num; i++) {
- p_tx_desc[i].byte_cnt = 0x0000;
- p_tx_desc[i].l4i_chk = 0x0000;
- p_tx_desc[i].cmd_sts = 0x00000000;
p_tx_desc[i].next_desc_ptr = mp->tx_desc_dma +
((i + 1) % tx_desc_num) * sizeof(struct eth_tx_desc);
- p_tx_desc[i].buf_ptr = 0x00000000;
- mp->tx_skb[i] = NULL;
}
- /* Set Tx desc pointer in driver struct. */
mp->tx_curr_desc_q = 0;
mp->tx_used_desc_q = 0;
-#ifdef MV64340_CHECKSUM_OFFLOAD_TX
- mp->tx_first_desc_q = 0;
+#ifdef MV643XX_CHECKSUM_OFFLOAD_TX
+ mp->tx_first_desc_q = 0;
#endif
- /* Init Tx ring base and size parameters */
- mp->tx_desc_area_size = tx_desc_num * sizeof(struct eth_tx_desc);
+
+ mp->tx_desc_area_size = tx_desc_num * sizeof(struct eth_tx_desc);
/* Add the queue to the list of Tx queues of this port */
mp->port_tx_queue_command |= 1;
-
- return 1;
}
-/* Helper function for mv64340_eth_open */
-static int mv64340_eth_real_open(struct net_device *dev)
+/* Helper function for mv643xx_eth_open */
+static int mv643xx_eth_real_open(struct net_device *dev)
{
- struct mv64340_private *mp = netdev_priv(dev);
+ struct mv643xx_private *mp = netdev_priv(dev);
unsigned int port_num = mp->port_num;
- u32 phy_reg_data;
unsigned int size;
/* Stop RX Queues */
- MV_WRITE(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num),
- 0x0000ff00);
+ mv_write(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num), 0x0000ff00);
/* Clear the ethernet port interrupts */
- MV_WRITE(MV64340_ETH_INTERRUPT_CAUSE_REG(port_num), 0);
- MV_WRITE(MV64340_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num), 0);
+ 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(MV64340_ETH_INTERRUPT_MASK_REG(port_num),
- INT_CAUSE_UNMASK_ALL);
+ mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num),
+ INT_CAUSE_UNMASK_ALL);
/* Unmask phy and link status changes interrupts */
- MV_WRITE(MV64340_ETH_INTERRUPT_EXTEND_MASK_REG(port_num),
- INT_CAUSE_UNMASK_ALL_EXT);
+ 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);
eth_port_init(mp);
- INIT_WORK(&mp->rx_task, (void (*)(void *)) mv64340_eth_rx_task, dev);
+ INIT_WORK(&mp->rx_task, (void (*)(void *))mv643xx_eth_rx_task, dev);
memset(&mp->timeout, 0, sizeof(struct timer_list));
- mp->timeout.function = mv64340_eth_rx_task_timer_wrapper;
- mp->timeout.data = (unsigned long) dev;
+ mp->timeout.function = mv643xx_eth_rx_task_timer_wrapper;
+ mp->timeout.data = (unsigned long)dev;
mp->rx_task_busy = 0;
mp->rx_timer_flag = 0;
+ /* Allocate RX and TX skb rings */
+ mp->rx_skb = kmalloc(sizeof(*mp->rx_skb) * mp->rx_ring_size,
+ GFP_KERNEL);
+ if (!mp->rx_skb) {
+ printk(KERN_ERR "%s: Cannot allocate Rx skb ring\n", dev->name);
+ return -ENOMEM;
+ }
+ 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;
+ }
+
/* Allocate TX ring */
mp->tx_ring_skbs = 0;
- mp->tx_ring_size = MV64340_TX_QUEUE_SIZE;
size = mp->tx_ring_size * sizeof(struct eth_tx_desc);
mp->tx_desc_area_size = size;
- /* Assumes allocated ring is 16 bytes alligned */
- mp->p_tx_desc_area = pci_alloc_consistent(NULL, size, &mp->tx_desc_dma);
+ if (mp->tx_sram_size) {
+ mp->p_tx_desc_area = ioremap(mp->tx_sram_addr,
+ mp->tx_sram_size);
+ mp->tx_desc_dma = mp->tx_sram_addr;
+ } else
+ mp->p_tx_desc_area = dma_alloc_coherent(NULL, size,
+ &mp->tx_desc_dma,
+ GFP_KERNEL);
+
if (!mp->p_tx_desc_area) {
printk(KERN_ERR "%s: Cannot allocate Tx Ring (size %d bytes)\n",
- dev->name, size);
+ dev->name, size);
+ kfree(mp->rx_skb);
+ kfree(mp->tx_skb);
return -ENOMEM;
}
- memset((void *) mp->p_tx_desc_area, 0, mp->tx_desc_area_size);
+ 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);
- /* Dummy will be replaced upon real tx */
ether_init_tx_desc_ring(mp);
/* Allocate RX ring */
- /* Meantime RX Ring are fixed - but must be configurable by user */
- mp->rx_ring_size = MV64340_RX_QUEUE_SIZE;
mp->rx_ring_skbs = 0;
size = mp->rx_ring_size * sizeof(struct eth_rx_desc);
mp->rx_desc_area_size = size;
- /* Assumes allocated ring is 16 bytes aligned */
-
- mp->p_rx_desc_area = pci_alloc_consistent(NULL, size, &mp->rx_desc_dma);
+ if (mp->rx_sram_size) {
+ mp->p_rx_desc_area = ioremap(mp->rx_sram_addr,
+ mp->rx_sram_size);
+ mp->rx_desc_dma = mp->rx_sram_addr;
+ } else
+ mp->p_rx_desc_area = dma_alloc_coherent(NULL, size,
+ &mp->rx_desc_dma,
+ GFP_KERNEL);
if (!mp->p_rx_desc_area) {
printk(KERN_ERR "%s: Cannot allocate Rx ring (size %d bytes)\n",
- dev->name, size);
+ dev->name, size);
printk(KERN_ERR "%s: Freeing previously allocated TX queues...",
- dev->name);
- pci_free_consistent(0, mp->tx_desc_area_size,
- (void *) mp->p_tx_desc_area,
- mp->tx_desc_dma);
+ dev->name);
+ if (mp->rx_sram_size)
+ iounmap(mp->p_rx_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;
}
- memset(mp->p_rx_desc_area, 0, size);
+ memset((void *)mp->p_rx_desc_area, 0, size);
- if (!(ether_init_rx_desc_ring(mp, 0)))
- panic("%s: Error initializing RX Ring", dev->name);
+ ether_init_rx_desc_ring(mp);
- mv64340_eth_rx_task(dev); /* Fill RX ring with skb's */
+ mv643xx_eth_rx_task(dev); /* Fill RX ring with skb's */
eth_port_start(mp);
/* Interrupt Coalescing */
-#ifdef MV64340_COAL
+#ifdef MV643XX_COAL
mp->rx_int_coal =
- eth_port_set_rx_coal(port_num, 133000000, MV64340_RX_COAL);
+ eth_port_set_rx_coal(port_num, 133000000, MV643XX_RX_COAL);
#endif
mp->tx_int_coal =
- eth_port_set_tx_coal (port_num, 133000000, MV64340_TX_COAL);
-
- /* Increase the Rx side buffer size */
+ eth_port_set_tx_coal(port_num, 133000000, MV643XX_TX_COAL);
- MV_WRITE (MV64340_ETH_PORT_SERIAL_CONTROL_REG(port_num), (0x5 << 17) |
- (MV_READ(MV64340_ETH_PORT_SERIAL_CONTROL_REG(port_num))
- & 0xfff1ffff));
-
- /* Check Link status on phy */
- eth_port_read_smi_reg(port_num, 1, &phy_reg_data);
- if (!(phy_reg_data & 0x20))
- netif_stop_queue(dev);
- else
- netif_start_queue(dev);
+ netif_start_queue(dev);
return 0;
}
-static void mv64340_eth_free_tx_rings(struct net_device *dev)
+static void mv643xx_eth_free_tx_rings(struct net_device *dev)
{
- struct mv64340_private *mp = netdev_priv(dev);
+ struct mv643xx_private *mp = netdev_priv(dev);
unsigned int port_num = mp->port_num;
unsigned int curr;
/* Stop Tx Queues */
- MV_WRITE(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(port_num),
- 0x0000ff00);
+ mv_write(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(port_num), 0x0000ff00);
- /* Free TX rings */
/* Free outstanding skb's on TX rings */
- for (curr = 0;
- (mp->tx_ring_skbs) && (curr < MV64340_TX_QUEUE_SIZE);
- curr++) {
+ 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]);
mp->tx_ring_skbs--;
}
}
- if (mp->tx_ring_skbs != 0)
+ if (mp->tx_ring_skbs)
printk("%s: Error on Tx descriptor free - could not free %d"
- " descriptors\n", dev->name,
- mp->tx_ring_skbs);
- pci_free_consistent(0, mp->tx_desc_area_size,
- (void *) mp->p_tx_desc_area, mp->tx_desc_dma);
+ " descriptors\n", dev->name, mp->tx_ring_skbs);
+
+ /* Free TX ring */
+ if (mp->tx_sram_size)
+ 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);
}
-static void mv64340_eth_free_rx_rings(struct net_device *dev)
+static void mv643xx_eth_free_rx_rings(struct net_device *dev)
{
- struct mv64340_private *mp = netdev_priv(dev);
+ struct mv643xx_private *mp = netdev_priv(dev);
unsigned int port_num = mp->port_num;
int curr;
/* Stop RX Queues */
- MV_WRITE(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num),
- 0x0000ff00);
+ mv_write(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num), 0x0000ff00);
- /* Free RX rings */
/* Free preallocated skb's on RX rings */
- for (curr = 0;
- mp->rx_ring_skbs && (curr < MV64340_RX_QUEUE_SIZE);
- curr++) {
+ for (curr = 0; mp->rx_ring_skbs && curr < mp->rx_ring_size; curr++) {
if (mp->rx_skb[curr]) {
dev_kfree_skb(mp->rx_skb[curr]);
mp->rx_ring_skbs--;
}
}
- if (mp->rx_ring_skbs != 0)
+ if (mp->rx_ring_skbs)
printk(KERN_ERR
- "%s: Error in freeing Rx Ring. %d skb's still"
- " stuck in RX Ring - ignoring them\n", dev->name,
- mp->rx_ring_skbs);
- pci_free_consistent(0, mp->rx_desc_area_size,
- (void *) mp->p_rx_desc_area,
- mp->rx_desc_dma);
+ "%s: Error in freeing Rx Ring. %d skb's still"
+ " stuck in RX Ring - ignoring them\n", dev->name,
+ mp->rx_ring_skbs);
+ /* Free RX ring */
+ if (mp->rx_sram_size)
+ iounmap(mp->p_rx_desc_area);
+ else
+ dma_free_coherent(NULL, mp->rx_desc_area_size,
+ mp->p_rx_desc_area, mp->rx_desc_dma);
}
/*
- * mv64340_eth_stop
+ * mv643xx_eth_stop
*
- * This function is used when closing the network device.
- * It updates the hardware,
+ * This function is used when closing the network device.
+ * It updates the hardware,
* release all memory that holds buffers and descriptors and release the IRQ.
- * Input : a pointer to the device structure
- * Output : zero if success , nonzero if fails
+ * Input : a pointer to the device structure
+ * Output : zero if success , nonzero if fails
*/
-/* Helper function for mv64340_eth_stop */
+/* Helper function for mv643xx_eth_stop */
-static int mv64340_eth_real_stop(struct net_device *dev)
+static int mv643xx_eth_real_stop(struct net_device *dev)
{
- struct mv64340_private *mp = netdev_priv(dev);
+ struct mv643xx_private *mp = netdev_priv(dev);
unsigned int port_num = mp->port_num;
+ netif_carrier_off(dev);
netif_stop_queue(dev);
- mv64340_eth_free_tx_rings(dev);
- mv64340_eth_free_rx_rings(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(MV64340_ETH_INTERRUPT_CAUSE_REG(port_num), 0);
- MV_WRITE(MV64340_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num), 0);
+ 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(MV64340_ETH_INTERRUPT_MASK_REG(port_num), 0);
+ mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), 0);
/* Mask phy and link status changes interrupts */
- MV_WRITE(MV64340_ETH_INTERRUPT_EXTEND_MASK_REG(port_num), 0);
+ mv_write(MV643XX_ETH_INTERRUPT_EXTEND_MASK_REG(port_num), 0);
return 0;
}
-static int mv64340_eth_stop(struct net_device *dev)
+static int mv643xx_eth_stop(struct net_device *dev)
{
- struct mv64340_private *mp = netdev_priv(dev);
+ struct mv643xx_private *mp = netdev_priv(dev);
spin_lock_irq(&mp->lock);
- mv64340_eth_real_stop(dev);
+ mv643xx_eth_real_stop(dev);
free_irq(dev->irq, dev);
spin_unlock_irq(&mp->lock);
@@ -1060,59 +1026,64 @@ static int mv64340_eth_stop(struct net_device *dev)
return 0;
}
-#ifdef MV64340_NAPI
-static void mv64340_tx(struct net_device *dev)
+#ifdef MV643XX_NAPI
+static void mv643xx_tx(struct net_device *dev)
{
- struct mv64340_private *mp = netdev_priv(dev);
- struct pkt_info pkt_info;
+ struct mv643xx_private *mp = netdev_priv(dev);
+ struct pkt_info pkt_info;
while (eth_tx_return_desc(mp, &pkt_info) == ETH_OK) {
if (pkt_info.return_info) {
- dev_kfree_skb_irq((struct sk_buff *)
- pkt_info.return_info);
- if (skb_shinfo(pkt_info.return_info)->nr_frags)
- pci_unmap_page(NULL, pkt_info.buf_ptr,
- pkt_info.byte_cnt,
- PCI_DMA_TODEVICE);
-
- if (mp->tx_ring_skbs != 1)
- mp->tx_ring_skbs--;
- } else
- pci_unmap_page(NULL, pkt_info.buf_ptr, pkt_info.byte_cnt,
- PCI_DMA_TODEVICE);
+ 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);
+
+ dev_kfree_skb_irq(pkt_info.return_info);
+
+ if (mp->tx_ring_skbs)
+ mp->tx_ring_skbs--;
+ } else
+ dma_unmap_page(NULL, pkt_info.buf_ptr,
+ pkt_info.byte_cnt, DMA_TO_DEVICE);
}
if (netif_queue_stopped(dev) &&
- MV64340_TX_QUEUE_SIZE > mp->tx_ring_skbs + 1)
- netif_wake_queue(dev);
+ mp->tx_ring_size > mp->tx_ring_skbs + MAX_DESCS_PER_SKB)
+ netif_wake_queue(dev);
}
/*
- * mv64340_poll
+ * mv643xx_poll
*
* This function is used in case of NAPI
*/
-static int mv64340_poll(struct net_device *dev, int *budget)
+static int mv643xx_poll(struct net_device *dev, int *budget)
{
- struct mv64340_private *mp = netdev_priv(dev);
- int done = 1, orig_budget, work_done;
+ 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 MV64340_TX_FAST_REFILL
+#ifdef MV643XX_TX_FAST_REFILL
if (++mp->tx_clean_threshold > 5) {
spin_lock_irqsave(&mp->lock, flags);
- mv64340_tx(dev);
+ mv643xx_tx(dev);
mp->tx_clean_threshold = 0;
spin_unlock_irqrestore(&mp->lock, flags);
}
#endif
- if ((u32)(MV_READ(MV64340_ETH_RX_CURRENT_QUEUE_DESC_PTR_0(port_num))) != (u32)mp->rx_used_desc_q) {
+ if ((mv_read(MV643XX_ETH_RX_CURRENT_QUEUE_DESC_PTR_0(port_num)))
+ != (u32) mp->rx_used_desc_q) {
orig_budget = *budget;
if (orig_budget > dev->quota)
orig_budget = dev->quota;
- work_done = mv64340_eth_receive_queue(dev, 0, orig_budget);
+ work_done = mv643xx_eth_receive_queue(dev, orig_budget);
mp->rx_task.func(dev);
*budget -= work_done;
dev->quota -= work_done;
@@ -1123,12 +1094,12 @@ static int mv64340_poll(struct net_device *dev, int *budget)
if (done) {
spin_lock_irqsave(&mp->lock, flags);
__netif_rx_complete(dev);
- MV_WRITE(MV64340_ETH_INTERRUPT_CAUSE_REG(port_num),0);
- MV_WRITE(MV64340_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num),0);
- MV_WRITE(MV64340_ETH_INTERRUPT_MASK_REG(port_num),
+ 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(MV64340_ETH_INTERRUPT_EXTEND_MASK_REG(port_num),
- INT_CAUSE_UNMASK_ALL_EXT);
+ mv_write(MV643XX_ETH_INTERRUPT_EXTEND_MASK_REG(port_num),
+ INT_CAUSE_UNMASK_ALL_EXT);
spin_unlock_irqrestore(&mp->lock, flags);
}
@@ -1137,19 +1108,19 @@ static int mv64340_poll(struct net_device *dev, int *budget)
#endif
/*
- * mv64340_eth_start_xmit
+ * mv643xx_eth_start_xmit
*
- * This function is queues a packet in the Tx descriptor for
+ * This function is queues a packet in the Tx descriptor for
* required port.
*
- * Input : skb - a pointer to socket buffer
- * dev - a pointer to the required port
+ * Input : skb - a pointer to socket buffer
+ * dev - a pointer to the required port
*
- * Output : zero upon success
+ * Output : zero upon success
*/
-static int mv64340_eth_start_xmit(struct sk_buff *skb, struct net_device *dev)
+static int mv643xx_eth_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
- struct mv64340_private *mp = netdev_priv(dev);
+ struct mv643xx_private *mp = netdev_priv(dev);
struct net_device_stats *stats = &mp->stats;
ETH_FUNC_RET_STATUS status;
unsigned long flags;
@@ -1157,119 +1128,195 @@ static int mv64340_eth_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (netif_queue_stopped(dev)) {
printk(KERN_ERR
- "%s: Tried sending packet when interface is stopped\n",
- dev->name);
+ "%s: Tried sending packet when interface is stopped\n",
+ dev->name);
return 1;
}
/* This is a hard error, log it. */
- if ((MV64340_TX_QUEUE_SIZE - mp->tx_ring_skbs) <=
- (skb_shinfo(skb)->nr_frags + 1)) {
+ if ((mp->tx_ring_size - mp->tx_ring_skbs) <=
+ (skb_shinfo(skb)->nr_frags + 1)) {
netif_stop_queue(dev);
printk(KERN_ERR
- "%s: Bug in mv64340_eth - Trying to transmit when"
- " queue full !\n", dev->name);
+ "%s: Bug in mv643xx_eth - Trying to transmit when"
+ " queue full !\n", dev->name);
return 1;
}
/* Paranoid check - this shouldn't happen */
if (skb == NULL) {
stats->tx_dropped++;
+ printk(KERN_ERR "mv64320_eth paranoid check failed\n");
return 1;
}
spin_lock_irqsave(&mp->lock, flags);
/* Update packet info data structure -- DMA owned, first last */
-#ifdef MV64340_CHECKSUM_OFFLOAD_TX
- if (!skb_shinfo(skb)->nr_frags || (skb_shinfo(skb)->nr_frags > 3)) {
-#endif
- pkt_info.cmd_sts = ETH_TX_ENABLE_INTERRUPT |
- ETH_TX_FIRST_DESC | ETH_TX_LAST_DESC;
+#ifdef MV643XX_CHECKSUM_OFFLOAD_TX
+ if (!skb_shinfo(skb)->nr_frags) {
+linear:
+ if (skb->ip_summed != CHECKSUM_HW) {
+ pkt_info.cmd_sts = ETH_TX_ENABLE_INTERRUPT |
+ ETH_TX_FIRST_DESC | ETH_TX_LAST_DESC;
+ pkt_info.l4i_chk = 0;
+ } else {
+ u32 ipheader = skb->nh.iph->ihl << 11;
+ pkt_info.cmd_sts = ETH_TX_ENABLE_INTERRUPT |
+ ETH_TX_FIRST_DESC | ETH_TX_LAST_DESC |
+ ETH_GEN_TCP_UDP_CHECKSUM |
+ ETH_GEN_IP_V_4_CHECKSUM | ipheader;
+ /* CPU already calculated pseudo header checksum. */
+ if (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)
+ pkt_info.l4i_chk = skb->h.th->check;
+ else {
+ printk(KERN_ERR
+ "%s: chksum proto != TCP or UDP\n",
+ dev->name);
+ spin_unlock_irqrestore(&mp->lock, flags);
+ return 1;
+ }
+ }
pkt_info.byte_cnt = skb->len;
- pkt_info.buf_ptr = pci_map_single(0, skb->data, skb->len,
- PCI_DMA_TODEVICE);
-
-
+ pkt_info.buf_ptr = dma_map_single(NULL, skb->data, skb->len,
+ DMA_TO_DEVICE);
pkt_info.return_info = skb;
+ mp->tx_ring_skbs++;
status = eth_port_send(mp, &pkt_info);
if ((status == ETH_ERROR) || (status == ETH_QUEUE_FULL))
printk(KERN_ERR "%s: Error on transmitting packet\n",
- dev->name);
- mp->tx_ring_skbs++;
-#ifdef MV64340_CHECKSUM_OFFLOAD_TX
+ dev->name);
+ stats->tx_bytes += pkt_info.byte_cnt;
} else {
- unsigned int frag;
- u32 ipheader;
-
- /* first frag which is skb header */
- pkt_info.byte_cnt = skb_headlen(skb);
- pkt_info.buf_ptr = pci_map_single(0, skb->data,
- skb_headlen(skb), PCI_DMA_TODEVICE);
- pkt_info.return_info = 0;
- ipheader = skb->nh.iph->ihl << 11;
- pkt_info.cmd_sts = ETH_TX_FIRST_DESC |
- ETH_GEN_TCP_UDP_CHECKSUM |
- ETH_GEN_IP_V_4_CHECKSUM |
- ipheader;
- /* CPU already calculated pseudo header checksum. So, use it */
- pkt_info.l4i_chk = skb->h.th->check;
- status = eth_port_send(mp, &pkt_info);
+ unsigned int frag;
+ u32 ipheader;
+
+ /* 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,
+ skb_headlen(skb),
+ DMA_TO_DEVICE);
+ pkt_info.l4i_chk = 0;
+ pkt_info.return_info = 0;
+ pkt_info.cmd_sts = ETH_TX_FIRST_DESC;
+
+ if (skb->ip_summed == CHECKSUM_HW) {
+ ipheader = skb->nh.iph->ihl << 11;
+ pkt_info.cmd_sts |= ETH_GEN_TCP_UDP_CHECKSUM |
+ ETH_GEN_IP_V_4_CHECKSUM | ipheader;
+ /* CPU already calculated pseudo header checksum. */
+ if (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)
+ pkt_info.l4i_chk = skb->h.th->check;
+ else {
+ printk(KERN_ERR
+ "%s: chksum proto != TCP or UDP\n",
+ dev->name);
+ spin_unlock_irqrestore(&mp->lock, flags);
+ return 1;
+ }
+ }
+
+ status = eth_port_send(mp, &pkt_info);
if (status != ETH_OK) {
- if ((status == ETH_ERROR))
- printk(KERN_ERR "%s: Error on transmitting packet\n", dev->name);
- if (status == ETH_QUEUE_FULL)
- printk("Error on Queue Full \n");
- if (status == ETH_QUEUE_LAST_RESOURCE)
- printk("Tx resource error \n");
+ if ((status == ETH_ERROR))
+ printk(KERN_ERR
+ "%s: Error on transmitting packet\n",
+ dev->name);
+ if (status == ETH_QUEUE_FULL)
+ printk("Error on Queue Full \n");
+ if (status == ETH_QUEUE_LAST_RESOURCE)
+ printk("Tx resource error \n");
}
+ stats->tx_bytes += pkt_info.byte_cnt;
+
+ /* Check for the remaining frags */
+ for (frag = 0; frag < skb_shinfo(skb)->nr_frags; frag++) {
+ skb_frag_t *this_frag = &skb_shinfo(skb)->frags[frag];
+ pkt_info.l4i_chk = 0x0000;
+ pkt_info.cmd_sts = 0x00000000;
+
+ /* Last Frag enables interrupt and frees the skb */
+ if (frag == (skb_shinfo(skb)->nr_frags - 1)) {
+ pkt_info.cmd_sts |= ETH_TX_ENABLE_INTERRUPT |
+ ETH_TX_LAST_DESC;
+ pkt_info.return_info = skb;
+ mp->tx_ring_skbs++;
+ } else {
+ pkt_info.return_info = 0;
+ }
+ pkt_info.l4i_chk = 0;
+ pkt_info.byte_cnt = this_frag->size;
- /* Check for the remaining frags */
- for (frag = 0; frag < skb_shinfo(skb)->nr_frags; frag++) {
- skb_frag_t *this_frag = &skb_shinfo(skb)->frags[frag];
- pkt_info.l4i_chk = 0x0000;
- pkt_info.cmd_sts = 0x00000000;
-
- /* Last Frag enables interrupt and frees the skb */
- if (frag == (skb_shinfo(skb)->nr_frags - 1)) {
- pkt_info.cmd_sts |= ETH_TX_ENABLE_INTERRUPT |
- ETH_TX_LAST_DESC;
- pkt_info.return_info = skb;
- mp->tx_ring_skbs++;
- }
- else {
- pkt_info.return_info = 0;
- }
- pkt_info.byte_cnt = this_frag->size;
- if (this_frag->size < 8)
- printk("%d : \n", skb_shinfo(skb)->nr_frags);
-
- pkt_info.buf_ptr = pci_map_page(NULL, this_frag->page,
- this_frag->page_offset,
- this_frag->size, PCI_DMA_TODEVICE);
-
- status = eth_port_send(mp, &pkt_info);
+ pkt_info.buf_ptr = dma_map_page(NULL, this_frag->page,
+ this_frag->page_offset,
+ this_frag->size,
+ DMA_TO_DEVICE);
+
+ status = eth_port_send(mp, &pkt_info);
if (status != ETH_OK) {
- if ((status == ETH_ERROR))
- printk(KERN_ERR "%s: Error on transmitting packet\n", dev->name);
+ if ((status == ETH_ERROR))
+ printk(KERN_ERR "%s: Error on "
+ "transmitting packet\n",
+ dev->name);
- if (status == ETH_QUEUE_LAST_RESOURCE)
- printk("Tx resource error \n");
+ if (status == ETH_QUEUE_LAST_RESOURCE)
+ printk("Tx resource error \n");
- if (status == ETH_QUEUE_FULL)
- printk("Queue is full \n");
+ if (status == ETH_QUEUE_FULL)
+ printk("Queue is full \n");
}
- }
- }
+ stats->tx_bytes += pkt_info.byte_cnt;
+ }
+ }
+#else
+ pkt_info.cmd_sts = ETH_TX_ENABLE_INTERRUPT | ETH_TX_FIRST_DESC |
+ ETH_TX_LAST_DESC;
+ pkt_info.l4i_chk = 0;
+ pkt_info.byte_cnt = skb->len;
+ pkt_info.buf_ptr = dma_map_single(NULL, skb->data, skb->len,
+ DMA_TO_DEVICE);
+ pkt_info.return_info = skb;
+ mp->tx_ring_skbs++;
+ status = eth_port_send(mp, &pkt_info);
+ if ((status == ETH_ERROR) || (status == ETH_QUEUE_FULL))
+ printk(KERN_ERR "%s: Error on transmitting packet\n",
+ dev->name);
+ stats->tx_bytes += pkt_info.byte_cnt;
#endif
/* Check if TX queue can handle another skb. If not, then
* signal higher layers to stop requesting TX
*/
- if (MV64340_TX_QUEUE_SIZE <= (mp->tx_ring_skbs + 1))
- /*
+ if (mp->tx_ring_size <= (mp->tx_ring_skbs + MAX_DESCS_PER_SKB))
+ /*
* Stop getting skb's from upper layers.
* Getting skb's from upper layers will be enabled again after
* packets are released.
@@ -1277,7 +1324,6 @@ static int mv64340_eth_start_xmit(struct sk_buff *skb, struct net_device *dev)
netif_stop_queue(dev);
/* Update statistics and start of transmittion time */
- stats->tx_bytes += skb->len;
stats->tx_packets++;
dev->trans_start = jiffies;
@@ -1287,214 +1333,302 @@ static int mv64340_eth_start_xmit(struct sk_buff *skb, struct net_device *dev)
}
/*
- * mv64340_eth_get_stats
+ * mv643xx_eth_get_stats
*
* Returns a pointer to the interface statistics.
*
- * Input : dev - a pointer to the required interface
+ * Input : dev - a pointer to the required interface
*
- * Output : a pointer to the interface's statistics
+ * Output : a pointer to the interface's statistics
*/
-static struct net_device_stats *mv64340_eth_get_stats(struct net_device *dev)
+static struct net_device_stats *mv643xx_eth_get_stats(struct net_device *dev)
{
- struct mv64340_private *mp = netdev_priv(dev);
+ struct mv643xx_private *mp = netdev_priv(dev);
return &mp->stats;
}
/*/
- * mv64340_eth_init
- *
- * First function called after registering the network device.
- * It's purpose is to initialize the device as an ethernet device,
- * fill the structure that was given in registration with pointers
- * to functions, and setting the MAC address of the interface
- *
- * Input : number of port to initialize
- * Output : -ENONMEM if failed , 0 if success
+ * mv643xx_eth_probe
+ *
+ * First function called after registering the network device.
+ * It's purpose is to initialize the device as an ethernet device,
+ * fill the ethernet device structure with pointers * to functions,
+ * and set the MAC address of the interface
+ *
+ * Input : struct device *
+ * Output : -ENOMEM if failed , 0 if success
*/
-static struct net_device *mv64340_eth_init(int port_num)
+static int mv643xx_eth_probe(struct device *ddev)
{
- struct mv64340_private *mp;
+ struct platform_device *pdev = to_platform_device(ddev);
+ struct mv643xx_eth_platform_data *pd;
+ int port_num = pdev->id;
+ struct mv643xx_private *mp;
struct net_device *dev;
+ u8 *p;
+ struct resource *res;
int err;
- dev = alloc_etherdev(sizeof(struct mv64340_private));
+ dev = alloc_etherdev(sizeof(struct mv643xx_private));
if (!dev)
- return NULL;
+ return -ENOMEM;
+
+ dev_set_drvdata(ddev, dev);
mp = netdev_priv(dev);
- dev->irq = ETH_PORT0_IRQ_NUM + port_num;
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ BUG_ON(!res);
+ dev->irq = res->start;
- dev->open = mv64340_eth_open;
- dev->stop = mv64340_eth_stop;
- dev->hard_start_xmit = mv64340_eth_start_xmit;
- dev->get_stats = mv64340_eth_get_stats;
- dev->set_mac_address = mv64340_eth_set_mac_address;
- dev->set_multicast_list = mv64340_eth_set_rx_mode;
+ mp->port_num = port_num;
+
+ dev->open = mv643xx_eth_open;
+ dev->stop = mv643xx_eth_stop;
+ dev->hard_start_xmit = mv643xx_eth_start_xmit;
+ dev->get_stats = mv643xx_eth_get_stats;
+ dev->set_mac_address = mv643xx_eth_set_mac_address;
+ dev->set_multicast_list = mv643xx_eth_set_rx_mode;
/* No need to Tx Timeout */
- dev->tx_timeout = mv64340_eth_tx_timeout;
-#ifdef MV64340_NAPI
- dev->poll = mv64340_poll;
- dev->weight = 64;
+ dev->tx_timeout = mv643xx_eth_tx_timeout;
+#ifdef MV643XX_NAPI
+ dev->poll = mv643xx_poll;
+ dev->weight = 64;
#endif
dev->watchdog_timeo = 2 * HZ;
- dev->tx_queue_len = MV64340_TX_QUEUE_SIZE;
+ dev->tx_queue_len = mp->tx_ring_size;
dev->base_addr = 0;
- dev->change_mtu = mv64340_eth_change_mtu;
+ dev->change_mtu = mv643xx_eth_change_mtu;
+ SET_ETHTOOL_OPS(dev, &mv643xx_ethtool_ops);
-#ifdef MV64340_CHECKSUM_OFFLOAD_TX
+#ifdef MV643XX_CHECKSUM_OFFLOAD_TX
#ifdef MAX_SKB_FRAGS
-#ifndef CONFIG_JAGUAR_DMALOW
- /*
- * 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;
-#endif
+ /*
+ * 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;
#endif
#endif
- mp->port_num = port_num;
-
/* Configure the timeout task */
- INIT_WORK(&mp->tx_timeout_task,
- (void (*)(void *))mv64340_eth_tx_timeout_task, dev);
+ INIT_WORK(&mp->tx_timeout_task,
+ (void (*)(void *))mv643xx_eth_tx_timeout_task, dev);
spin_lock_init(&mp->lock);
- /* set MAC addresses */
- memcpy(dev->dev_addr, prom_mac_addr_base, 6);
- dev->dev_addr[5] += port_num;
+ /* set default config values */
+ eth_port_uc_addr_get(dev, dev->dev_addr);
+ mp->port_config = MV643XX_ETH_PORT_CONFIG_DEFAULT_VALUE;
+ mp->port_config_extend = MV643XX_ETH_PORT_CONFIG_EXTEND_DEFAULT_VALUE;
+ mp->port_sdma_config = MV643XX_ETH_PORT_SDMA_CONFIG_DEFAULT_VALUE;
+ mp->port_serial_control = MV643XX_ETH_PORT_SERIAL_CONTROL_DEFAULT_VALUE;
+ mp->rx_ring_size = MV643XX_ETH_PORT_DEFAULT_RECEIVE_QUEUE_SIZE;
+ mp->tx_ring_size = MV643XX_ETH_PORT_DEFAULT_TRANSMIT_QUEUE_SIZE;
+
+ pd = pdev->dev.platform_data;
+ if (pd) {
+ if (pd->mac_addr != NULL)
+ memcpy(dev->dev_addr, pd->mac_addr, 6);
+
+ if (pd->phy_addr || pd->force_phy_addr)
+ ethernet_phy_set(port_num, pd->phy_addr);
+
+ if (pd->port_config || pd->force_port_config)
+ mp->port_config = pd->port_config;
+
+ if (pd->port_config_extend || pd->force_port_config_extend)
+ mp->port_config_extend = pd->port_config_extend;
+
+ if (pd->port_sdma_config || pd->force_port_sdma_config)
+ mp->port_sdma_config = pd->port_sdma_config;
+
+ if (pd->port_serial_control || pd->force_port_serial_control)
+ mp->port_serial_control = pd->port_serial_control;
+
+ if (pd->rx_queue_size)
+ mp->rx_ring_size = pd->rx_queue_size;
+
+ if (pd->tx_queue_size)
+ mp->tx_ring_size = pd->tx_queue_size;
+
+ if (pd->tx_sram_size) {
+ mp->tx_sram_size = pd->tx_sram_size;
+ mp->tx_sram_addr = pd->tx_sram_addr;
+ }
+
+ if (pd->rx_sram_size) {
+ mp->rx_sram_size = pd->rx_sram_size;
+ mp->rx_sram_addr = pd->rx_sram_addr;
+ }
+ }
+
+ err = ethernet_phy_detect(port_num);
+ if (err) {
+ pr_debug("MV643xx ethernet port %d: "
+ "No PHY detected at addr %d\n",
+ port_num, ethernet_phy_get(port_num));
+ return err;
+ }
err = register_netdev(dev);
if (err)
- goto out_free_dev;
+ goto out;
- printk(KERN_NOTICE "%s: port %d with MAC address %02x:%02x:%02x:%02x:%02x:%02x\n",
- dev->name, port_num,
- dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
- dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
+ p = dev->dev_addr;
+ printk(KERN_NOTICE
+ "%s: port %d with MAC address %02x:%02x:%02x:%02x:%02x:%02x\n",
+ dev->name, port_num, p[0], p[1], p[2], p[3], p[4], p[5]);
if (dev->features & NETIF_F_SG)
- printk("Scatter Gather Enabled ");
+ printk(KERN_NOTICE "%s: Scatter Gather Enabled\n", dev->name);
if (dev->features & NETIF_F_IP_CSUM)
- printk("TX TCP/IP Checksumming Supported \n");
+ printk(KERN_NOTICE "%s: TX TCP/IP Checksumming Supported\n",
+ dev->name);
- printk("RX TCP/UDP Checksum Offload ON, \n");
- printk("TX and RX Interrupt Coalescing ON \n");
+#ifdef MV643XX_CHECKSUM_OFFLOAD_TX
+ printk(KERN_NOTICE "%s: RX TCP/UDP Checksum Offload ON \n", dev->name);
+#endif
+
+#ifdef MV643XX_COAL
+ printk(KERN_NOTICE "%s: TX and RX Interrupt Coalescing ON \n",
+ dev->name);
+#endif
-#ifdef MV64340_NAPI
- printk("RX NAPI Enabled \n");
+#ifdef MV643XX_NAPI
+ printk(KERN_NOTICE "%s: RX NAPI Enabled \n", dev->name);
#endif
- return dev;
+ return 0;
-out_free_dev:
+out:
free_netdev(dev);
- return NULL;
+ return err;
}
-static void mv64340_eth_remove(struct net_device *dev)
+static int mv643xx_eth_remove(struct device *ddev)
{
- struct mv64340_private *mp = netdev_priv(dev);
+ struct net_device *dev = dev_get_drvdata(ddev);
unregister_netdev(dev);
flush_scheduled_work();
+
free_netdev(dev);
+ dev_set_drvdata(ddev, NULL);
+ return 0;
+}
+
+static int mv643xx_eth_shared_probe(struct device *ddev)
+{
+ struct platform_device *pdev = to_platform_device(ddev);
+ struct resource *res;
+
+ printk(KERN_NOTICE "MV-643xx 10/100/1000 Ethernet Driver\n");
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (res == NULL)
+ return -ENODEV;
+
+ mv643xx_eth_shared_base = ioremap(res->start,
+ MV643XX_ETH_SHARED_REGS_SIZE);
+ if (mv643xx_eth_shared_base == NULL)
+ return -ENOMEM;
+
+ return 0;
+
+}
+
+static int mv643xx_eth_shared_remove(struct device *ddev)
+{
+ iounmap(mv643xx_eth_shared_base);
+ mv643xx_eth_shared_base = NULL;
+
+ return 0;
}
-static struct net_device *mv64340_dev0;
-static struct net_device *mv64340_dev1;
-static struct net_device *mv64340_dev2;
+static struct device_driver mv643xx_eth_driver = {
+ .name = MV643XX_ETH_NAME,
+ .bus = &platform_bus_type,
+ .probe = mv643xx_eth_probe,
+ .remove = mv643xx_eth_remove,
+};
+
+static struct device_driver mv643xx_eth_shared_driver = {
+ .name = MV643XX_ETH_SHARED_NAME,
+ .bus = &platform_bus_type,
+ .probe = mv643xx_eth_shared_probe,
+ .remove = mv643xx_eth_shared_remove,
+};
/*
- * mv64340_init_module
+ * mv643xx_init_module
*
* Registers the network drivers into the Linux kernel
*
- * Input : N/A
+ * Input : N/A
*
- * Output : N/A
+ * Output : N/A
*/
-static int __init mv64340_init_module(void)
+static int __init mv643xx_init_module(void)
{
- printk(KERN_NOTICE "MV-643xx 10/100/1000 Ethernet Driver\n");
+ int rc;
-#ifdef CONFIG_MV643XX_ETH_0
- mv64340_dev0 = mv64340_eth_init(0);
- if (!mv64340_dev0) {
- printk(KERN_ERR
- "Error registering MV-64360 ethernet port 0\n");
- }
-#endif
-#ifdef CONFIG_MV643XX_ETH_1
- mv64340_dev1 = mv64340_eth_init(1);
- if (!mv64340_dev1) {
- printk(KERN_ERR
- "Error registering MV-64360 ethernet port 1\n");
+ rc = driver_register(&mv643xx_eth_shared_driver);
+ if (!rc) {
+ rc = driver_register(&mv643xx_eth_driver);
+ if (rc)
+ driver_unregister(&mv643xx_eth_shared_driver);
}
-#endif
-#ifdef CONFIG_MV643XX_ETH_2
- mv64340_dev2 = mv64340_eth_init(2);
- if (!mv64340_dev2) {
- printk(KERN_ERR
- "Error registering MV-64360 ethernet port 2\n");
- }
-#endif
- return 0;
+ return rc;
}
/*
- * mv64340_cleanup_module
+ * mv643xx_cleanup_module
*
* Registers the network drivers into the Linux kernel
*
- * Input : N/A
+ * Input : N/A
*
- * Output : N/A
+ * Output : N/A
*/
-static void __exit mv64340_cleanup_module(void)
+static void __exit mv643xx_cleanup_module(void)
{
- if (mv64340_dev2)
- mv64340_eth_remove(mv64340_dev2);
- if (mv64340_dev1)
- mv64340_eth_remove(mv64340_dev1);
- if (mv64340_dev0)
- mv64340_eth_remove(mv64340_dev0);
+ driver_unregister(&mv643xx_eth_driver);
+ driver_unregister(&mv643xx_eth_shared_driver);
}
-module_init(mv64340_init_module);
-module_exit(mv64340_cleanup_module);
+module_init(mv643xx_init_module);
+module_exit(mv643xx_cleanup_module);
MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Rabeeh Khoury, Assaf Hoffman, Matthew Dharm and Manish Lachwani");
-MODULE_DESCRIPTION("Ethernet driver for Marvell MV64340");
+MODULE_AUTHOR( "Rabeeh Khoury, Assaf Hoffman, Matthew Dharm, Manish Lachwani"
+ " and Dale Farnsworth");
+MODULE_DESCRIPTION("Ethernet driver for Marvell MV643XX");
/*
- * The second part is the low level driver of the gigE ethernet ports.
+ * The second part is the low level driver of the gigE ethernet ports.
*/
/*
* Marvell's Gigabit Ethernet controller low level driver
*
* DESCRIPTION:
- * This file introduce low level API to Marvell's Gigabit Ethernet
+ * This file introduce low level API to Marvell's Gigabit Ethernet
* controller. This Gigabit Ethernet Controller driver API controls
* 1) Operations (i.e. port init, start, reset etc').
* 2) Data flow (i.e. port send, receive etc').
* Each Gigabit Ethernet port is controlled via
- * struct mv64340_private.
+ * struct mv643xx_private.
* This struct includes user configuration information as well as
* driver internal data needed for its operations.
*
- * Supported Features:
+ * Supported Features:
* - This low level driver is OS independent. Allocating memory for
* the descriptor rings and buffers are not within the scope of
* this driver.
@@ -1511,12 +1645,12 @@ MODULE_DESCRIPTION("Ethernet driver for Marvell MV64340");
* - PHY access and control API.
* - Port control register configuration API.
* - Full control over Unicast and Multicast MAC configurations.
- *
+ *
* Operation flow:
*
* Initialization phase
- * This phase complete the initialization of the the mv64340_private
- * struct.
+ * This phase complete the initialization of the the
+ * mv643xx_private struct.
* User information regarding port configuration has to be set
* prior to calling the port initialization routine.
*
@@ -1525,7 +1659,7 @@ MODULE_DESCRIPTION("Ethernet driver for Marvell MV64340");
* access to DRAM and internal SRAM memory spaces.
*
* Driver ring initialization
- * Allocating memory for the descriptor rings and buffers is not
+ * Allocating memory for the descriptor rings and buffers is not
* within the scope of this driver. Thus, the user is required to
* allocate memory for the descriptors ring and buffers. Those
* memory parameters are used by the Rx and Tx ring initialization
@@ -1533,49 +1667,50 @@ MODULE_DESCRIPTION("Ethernet driver for Marvell MV64340");
* of a ring.
* Note: Pay special attention to alignment issues when using
* cached descriptors/buffers. In this phase the driver store
- * information in the mv64340_private struct regarding each queue
+ * information in the mv643xx_private struct regarding each queue
* ring.
*
- * Driver start
+ * Driver start
* This phase prepares the Ethernet port for Rx and Tx activity.
- * It uses the information stored in the mv64340_private struct to
+ * It uses the information stored in the mv643xx_private struct to
* initialize the various port registers.
*
* Data flow:
* All packet references to/from the driver are done using
- * struct pkt_info.
- * This struct is a unified struct used with Rx and Tx operations.
+ * struct pkt_info.
+ * This struct is a unified struct used with Rx and Tx operations.
* This way the user is not required to be familiar with neither
* Tx nor Rx descriptors structures.
* The driver's descriptors rings are management by indexes.
* Those indexes controls the ring resources and used to indicate
* a SW resource error:
- * 'current'
- * This index points to the current available resource for use. For
- * example in Rx process this index will point to the descriptor
- * that will be passed to the user upon calling the receive routine.
- * In Tx process, this index will point to the descriptor
+ * 'current'
+ * This index points to the current available resource for use. For
+ * example in Rx process this index will point to the descriptor
+ * that will be passed to the user upon calling the receive
+ * routine. In Tx process, this index will point to the descriptor
* that will be assigned with the user packet info and transmitted.
- * 'used'
- * This index points to the descriptor that need to restore its
+ * 'used'
+ * This index points to the descriptor that need to restore its
* resources. For example in Rx process, using the Rx buffer return
* API will attach the buffer returned in packet info to the
* descriptor pointed by 'used'. In Tx process, using the Tx
* descriptor return will merely return the user packet info with
- * the command status of the transmitted buffer pointed by the
+ * the command status of the transmitted buffer pointed by the
* 'used' index. Nevertheless, it is essential to use this routine
* to update the 'used' index.
* 'first'
- * This index supports Tx Scatter-Gather. It points to the first
- * descriptor of a packet assembled of multiple buffers. For example
- * when in middle of Such packet we have a Tx resource error the
- * 'curr' index get the value of 'first' to indicate that the ring
- * returned to its state before trying to transmit this packet.
+ * This index supports Tx Scatter-Gather. It points to the first
+ * descriptor of a packet assembled of multiple buffers. For
+ * example when in middle of Such packet we have a Tx resource
+ * error the 'curr' index get the value of 'first' to indicate
+ * that the ring returned to its state before trying to transmit
+ * this packet.
*
* Receive operation:
* The eth_port_receive API set the packet information struct,
- * passed by the caller, with received information from the
- * 'current' SDMA descriptor.
+ * passed by the caller, with received information from the
+ * 'current' SDMA descriptor.
* It is the user responsibility to return this resource back
* to the Rx descriptor ring to enable the reuse of this source.
* Return Rx resource is done using the eth_rx_return_buff API.
@@ -1596,27 +1731,21 @@ MODULE_DESCRIPTION("Ethernet driver for Marvell MV64340");
*
* EXTERNAL INTERFACE
*
- * Prior to calling the initialization routine eth_port_init() the user
- * must set the following fields under mv64340_private struct:
- * port_num User Ethernet port number.
- * port_mac_addr[6] User defined port MAC address.
- * port_config User port configuration value.
- * port_config_extend User port config extend value.
- * port_sdma_config User port SDMA config value.
- * port_serial_control User port serial control value.
- *
- * This driver introduce a set of default values:
- * PORT_CONFIG_VALUE Default port configuration value
- * PORT_CONFIG_EXTEND_VALUE Default port extend configuration value
- * PORT_SDMA_CONFIG_VALUE Default sdma control value
- * PORT_SERIAL_CONTROL_VALUE Default port serial control value
+ * Prior to calling the initialization routine eth_port_init() the user
+ * must set the following fields under mv643xx_private struct:
+ * port_num User Ethernet port number.
+ * port_mac_addr[6] User defined port MAC address.
+ * port_config User port configuration value.
+ * port_config_extend User port config extend value.
+ * port_sdma_config User port SDMA config value.
+ * port_serial_control User port serial control value.
*
* This driver data flow is done using the struct pkt_info which
- * is a unified struct for Rx and Tx operations:
+ * is a unified struct for Rx and Tx operations:
*
* byte_cnt Tx/Rx descriptor buffer byte count.
* l4i_chk CPU provided TCP Checksum. For Tx operation
- * only.
+ * only.
* cmd_sts Tx/Rx descriptor command status.
* buf_ptr Tx/Rx descriptor buffer pointer.
* return_info Tx/Rx user resource return information.
@@ -1625,70 +1754,44 @@ MODULE_DESCRIPTION("Ethernet driver for Marvell MV64340");
/* defines */
/* SDMA command macros */
#define ETH_ENABLE_TX_QUEUE(eth_port) \
- MV_WRITE(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(eth_port), 1)
-
-#define ETH_DISABLE_TX_QUEUE(eth_port) \
- MV_WRITE(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(eth_port), \
- (1 << 8))
-
-#define ETH_ENABLE_RX_QUEUE(rx_queue, eth_port) \
- MV_WRITE(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(eth_port), \
- (1 << rx_queue))
-
-#define ETH_DISABLE_RX_QUEUE(rx_queue, eth_port) \
- MV_WRITE(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(eth_port), \
- (1 << (8 + rx_queue)))
-
-#define LINK_UP_TIMEOUT 100000
-#define PHY_BUSY_TIMEOUT 10000000
+ mv_write(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(eth_port), 1)
/* locals */
/* PHY routines */
static int ethernet_phy_get(unsigned int eth_port_num);
+static void ethernet_phy_set(unsigned int eth_port_num, int phy_addr);
/* Ethernet Port routines */
static int eth_port_uc_addr(unsigned int eth_port_num, unsigned char uc_nibble,
- int option);
+ int option);
/*
* eth_port_init - Initialize the Ethernet port driver
*
* DESCRIPTION:
- * This function prepares the ethernet port to start its activity:
- * 1) Completes the ethernet port driver struct initialization toward port
- * start routine.
- * 2) Resets the device to a quiescent state in case of warm reboot.
- * 3) Enable SDMA access to all four DRAM banks as well as internal SRAM.
- * 4) Clean MAC tables. The reset status of those tables is unknown.
- * 5) Set PHY address.
- * Note: Call this routine prior to eth_port_start routine and after
- * setting user values in the user fields of Ethernet port control
- * struct.
+ * This function prepares the ethernet port to start its activity:
+ * 1) Completes the ethernet port driver struct initialization toward port
+ * start routine.
+ * 2) Resets the device to a quiescent state in case of warm reboot.
+ * 3) Enable SDMA access to all four DRAM banks as well as internal SRAM.
+ * 4) Clean MAC tables. The reset status of those tables is unknown.
+ * 5) Set PHY address.
+ * Note: Call this routine prior to eth_port_start routine and after
+ * setting user values in the user fields of Ethernet port control
+ * struct.
*
* INPUT:
- * struct mv64340_private *mp Ethernet port control struct
+ * struct mv643xx_private *mp Ethernet port control struct
*
* OUTPUT:
- * See description.
+ * See description.
*
* RETURN:
- * None.
+ * None.
*/
-static void eth_port_init(struct mv64340_private * mp)
+static void eth_port_init(struct mv643xx_private *mp)
{
- mp->port_config = PORT_CONFIG_VALUE;
- mp->port_config_extend = PORT_CONFIG_EXTEND_VALUE;
-#if defined(__BIG_ENDIAN)
- mp->port_sdma_config = PORT_SDMA_CONFIG_VALUE;
-#elif defined(__LITTLE_ENDIAN)
- mp->port_sdma_config = PORT_SDMA_CONFIG_VALUE |
- ETH_BLM_RX_NO_SWAP | ETH_BLM_TX_NO_SWAP;
-#else
-#error One of __LITTLE_ENDIAN or __BIG_ENDIAN must be defined!
-#endif
- mp->port_serial_control = PORT_SERIAL_CONTROL_VALUE;
-
mp->port_rx_queue_command = 0;
mp->port_tx_queue_command = 0;
@@ -1706,77 +1809,73 @@ static void eth_port_init(struct mv64340_private * mp)
* eth_port_start - Start the Ethernet port activity.
*
* DESCRIPTION:
- * This routine prepares the Ethernet port for Rx and Tx activity:
- * 1. Initialize Tx and Rx Current Descriptor Pointer for each queue that
- * has been initialized a descriptor's ring (using
- * ether_init_tx_desc_ring for Tx and ether_init_rx_desc_ring for Rx)
- * 2. Initialize and enable the Ethernet configuration port by writing to
- * the port's configuration and command registers.
- * 3. Initialize and enable the SDMA by writing to the SDMA's
- * configuration and command registers. After completing these steps,
- * the ethernet port SDMA can starts to perform Rx and Tx activities.
- *
- * Note: Each Rx and Tx queue descriptor's list must be initialized prior
- * to calling this function (use ether_init_tx_desc_ring for Tx queues
- * and ether_init_rx_desc_ring for Rx queues).
+ * This routine prepares the Ethernet port for Rx and Tx activity:
+ * 1. Initialize Tx and Rx Current Descriptor Pointer for each queue that
+ * has been initialized a descriptor's ring (using
+ * ether_init_tx_desc_ring for Tx and ether_init_rx_desc_ring for Rx)
+ * 2. Initialize and enable the Ethernet configuration port by writing to
+ * the port's configuration and command registers.
+ * 3. Initialize and enable the SDMA by writing to the SDMA's
+ * configuration and command registers. After completing these steps,
+ * the ethernet port SDMA can starts to perform Rx and Tx activities.
+ *
+ * Note: Each Rx and Tx queue descriptor's list must be initialized prior
+ * to calling this function (use ether_init_tx_desc_ring for Tx queues
+ * and ether_init_rx_desc_ring for Rx queues).
*
* INPUT:
- * struct mv64340_private *mp Ethernet port control struct
+ * struct mv643xx_private *mp Ethernet port control struct
*
* OUTPUT:
- * Ethernet port is ready to receive and transmit.
+ * Ethernet port is ready to receive and transmit.
*
* RETURN:
- * false if the port PHY is not up.
- * true otherwise.
+ * None.
*/
-static int eth_port_start(struct mv64340_private *mp)
+static void eth_port_start(struct mv643xx_private *mp)
{
- unsigned int eth_port_num = mp->port_num;
+ unsigned int port_num = mp->port_num;
int tx_curr_desc, rx_curr_desc;
- unsigned int phy_reg_data;
/* Assignment of Tx CTRP of given queue */
tx_curr_desc = mp->tx_curr_desc_q;
- MV_WRITE(MV64340_ETH_TX_CURRENT_QUEUE_DESC_PTR_0(eth_port_num),
- (struct eth_tx_desc *) mp->tx_desc_dma + tx_curr_desc);
+ mv_write(MV643XX_ETH_TX_CURRENT_QUEUE_DESC_PTR_0(port_num),
+ (u32)((struct eth_tx_desc *)mp->tx_desc_dma + tx_curr_desc));
/* Assignment of Rx CRDP of given queue */
rx_curr_desc = mp->rx_curr_desc_q;
- MV_WRITE(MV64340_ETH_RX_CURRENT_QUEUE_DESC_PTR_0(eth_port_num),
- (struct eth_rx_desc *) mp->rx_desc_dma + rx_curr_desc);
+ mv_write(MV643XX_ETH_RX_CURRENT_QUEUE_DESC_PTR_0(port_num),
+ (u32)((struct eth_rx_desc *)mp->rx_desc_dma + rx_curr_desc));
/* Add the assigned Ethernet address to the port's address table */
- eth_port_uc_addr_set(mp->port_num, mp->port_mac_addr);
+ eth_port_uc_addr_set(port_num, mp->port_mac_addr);
/* Assign port configuration and command. */
- MV_WRITE(MV64340_ETH_PORT_CONFIG_REG(eth_port_num),
- mp->port_config);
+ mv_write(MV643XX_ETH_PORT_CONFIG_REG(port_num), mp->port_config);
+
+ mv_write(MV643XX_ETH_PORT_CONFIG_EXTEND_REG(port_num),
+ mp->port_config_extend);
- MV_WRITE(MV64340_ETH_PORT_CONFIG_EXTEND_REG(eth_port_num),
- mp->port_config_extend);
- MV_WRITE(MV64340_ETH_PORT_SERIAL_CONTROL_REG(eth_port_num),
- mp->port_serial_control);
+ /* Increase the Rx side buffer size if supporting GigE */
+ if (mp->port_serial_control & MV643XX_ETH_SET_GMII_SPEED_TO_1000)
+ mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num),
+ (mp->port_serial_control & 0xfff1ffff) | (0x5 << 17));
+ else
+ mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num),
+ mp->port_serial_control);
- MV_SET_REG_BITS(MV64340_ETH_PORT_SERIAL_CONTROL_REG(eth_port_num),
- ETH_SERIAL_PORT_ENABLE);
+ mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num),
+ mv_read(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num)) |
+ MV643XX_ETH_SERIAL_PORT_ENABLE);
/* Assign port SDMA configuration */
- MV_WRITE(MV64340_ETH_SDMA_CONFIG_REG(eth_port_num),
- mp->port_sdma_config);
+ mv_write(MV643XX_ETH_SDMA_CONFIG_REG(port_num),
+ mp->port_sdma_config);
/* Enable port Rx. */
- MV_WRITE(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(eth_port_num),
- mp->port_rx_queue_command);
-
- /* Check if link is up */
- eth_port_read_smi_reg(eth_port_num, 1, &phy_reg_data);
-
- if (!(phy_reg_data & 0x20))
- return 0;
-
- return 1;
+ mv_write(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num),
+ mp->port_rx_queue_command);
}
/*
@@ -1786,29 +1885,29 @@ static int eth_port_start(struct mv64340_private *mp)
* This function Set the port Ethernet MAC address.
*
* INPUT:
- * unsigned int eth_port_num Port number.
- * char * p_addr Address to be set
+ * unsigned int eth_port_num Port number.
+ * char * p_addr Address to be set
*
* OUTPUT:
- * Set MAC address low and high registers. also calls eth_port_uc_addr()
- * To set the unicast table with the proper information.
+ * Set MAC address low and high registers. also calls eth_port_uc_addr()
+ * To set the unicast table with the proper information.
*
* RETURN:
* N/A.
*
*/
static void eth_port_uc_addr_set(unsigned int eth_port_num,
- unsigned char *p_addr)
+ unsigned char *p_addr)
{
unsigned int mac_h;
unsigned int mac_l;
mac_l = (p_addr[4] << 8) | (p_addr[5]);
- mac_h = (p_addr[0] << 24) | (p_addr[1] << 16) |
- (p_addr[2] << 8) | (p_addr[3] << 0);
+ mac_h = (p_addr[0] << 24) | (p_addr[1] << 16) | (p_addr[2] << 8) |
+ (p_addr[3] << 0);
- MV_WRITE(MV64340_ETH_MAC_ADDR_LOW(eth_port_num), mac_l);
- MV_WRITE(MV64340_ETH_MAC_ADDR_HIGH(eth_port_num), mac_h);
+ mv_write(MV643XX_ETH_MAC_ADDR_LOW(eth_port_num), mac_l);
+ mv_write(MV643XX_ETH_MAC_ADDR_HIGH(eth_port_num), mac_h);
/* Accept frames of this address */
eth_port_uc_addr(eth_port_num, p_addr[5], ACCEPT_MAC_ADDR);
@@ -1817,29 +1916,64 @@ static void eth_port_uc_addr_set(unsigned int eth_port_num,
}
/*
+ * eth_port_uc_addr_get - This function retrieves the port Unicast address
+ * (MAC address) from the ethernet hw registers.
+ *
+ * DESCRIPTION:
+ * This function retrieves the port Ethernet MAC address.
+ *
+ * INPUT:
+ * unsigned int eth_port_num Port number.
+ * char *MacAddr pointer where the MAC address is stored
+ *
+ * OUTPUT:
+ * Copy the MAC address to the location pointed to by MacAddr
+ *
+ * RETURN:
+ * N/A.
+ *
+ */
+static void eth_port_uc_addr_get(struct net_device *dev, unsigned char *p_addr)
+{
+ struct mv643xx_private *mp = netdev_priv(dev);
+ unsigned int mac_h;
+ unsigned int mac_l;
+
+ mac_h = mv_read(MV643XX_ETH_MAC_ADDR_HIGH(mp->port_num));
+ mac_l = mv_read(MV643XX_ETH_MAC_ADDR_LOW(mp->port_num));
+
+ p_addr[0] = (mac_h >> 24) & 0xff;
+ p_addr[1] = (mac_h >> 16) & 0xff;
+ p_addr[2] = (mac_h >> 8) & 0xff;
+ p_addr[3] = mac_h & 0xff;
+ p_addr[4] = (mac_l >> 8) & 0xff;
+ p_addr[5] = mac_l & 0xff;
+}
+
+/*
* eth_port_uc_addr - This function Set the port unicast address table
*
* DESCRIPTION:
- * This function locates the proper entry in the Unicast table for the
- * specified MAC nibble and sets its properties according to function
+ * This function locates the proper entry in the Unicast table for the
+ * specified MAC nibble and sets its properties according to function
* parameters.
*
* INPUT:
- * unsigned int eth_port_num Port number.
- * unsigned char uc_nibble Unicast MAC Address last nibble.
- * int option 0 = Add, 1 = remove address.
+ * unsigned int eth_port_num Port number.
+ * unsigned char uc_nibble Unicast MAC Address last nibble.
+ * int option 0 = Add, 1 = remove address.
*
* OUTPUT:
* This function add/removes MAC addresses from the port unicast address
- * table.
+ * table.
*
* RETURN:
* true is output succeeded.
* false if option parameter is invalid.
*
*/
-static int eth_port_uc_addr(unsigned int eth_port_num,
- unsigned char uc_nibble, int option)
+static int eth_port_uc_addr(unsigned int eth_port_num, unsigned char uc_nibble,
+ int option)
{
unsigned int unicast_reg;
unsigned int tbl_offset;
@@ -1852,29 +1986,26 @@ static int eth_port_uc_addr(unsigned int eth_port_num,
switch (option) {
case REJECT_MAC_ADDR:
- /* Clear accepts frame bit at specified unicast DA table entry */
- unicast_reg = MV_READ((MV64340_ETH_DA_FILTER_UNICAST_TABLE_BASE
- (eth_port_num) + tbl_offset));
+ /* Clear accepts frame bit at given unicast DA table entry */
+ unicast_reg = mv_read((MV643XX_ETH_DA_FILTER_UNICAST_TABLE_BASE
+ (eth_port_num) + tbl_offset));
unicast_reg &= (0x0E << (8 * reg_offset));
- MV_WRITE(
- (MV64340_ETH_DA_FILTER_UNICAST_TABLE_BASE
- (eth_port_num) + tbl_offset), unicast_reg);
+ mv_write((MV643XX_ETH_DA_FILTER_UNICAST_TABLE_BASE
+ (eth_port_num) + tbl_offset), unicast_reg);
break;
case ACCEPT_MAC_ADDR:
/* Set accepts frame bit at unicast DA filter table entry */
unicast_reg =
- MV_READ(
- (MV64340_ETH_DA_FILTER_UNICAST_TABLE_BASE
- (eth_port_num) + tbl_offset));
+ mv_read((MV643XX_ETH_DA_FILTER_UNICAST_TABLE_BASE
+ (eth_port_num) + tbl_offset));
unicast_reg |= (0x01 << (8 * reg_offset));
- MV_WRITE(
- (MV64340_ETH_DA_FILTER_UNICAST_TABLE_BASE
- (eth_port_num) + tbl_offset), unicast_reg);
+ mv_write((MV643XX_ETH_DA_FILTER_UNICAST_TABLE_BASE
+ (eth_port_num) + tbl_offset), unicast_reg);
break;
@@ -1889,17 +2020,17 @@ static int eth_port_uc_addr(unsigned int eth_port_num,
* eth_port_init_mac_tables - Clear all entrance in the UC, SMC and OMC tables
*
* DESCRIPTION:
- * Go through all the DA filter tables (Unicast, Special Multicast &
- * Other Multicast) and set each entry to 0.
+ * Go through all the DA filter tables (Unicast, Special Multicast &
+ * Other Multicast) and set each entry to 0.
*
* INPUT:
- * unsigned int eth_port_num Ethernet Port number.
+ * unsigned int eth_port_num Ethernet Port number.
*
* OUTPUT:
- * Multicast and Unicast packets are rejected.
+ * Multicast and Unicast packets are rejected.
*
* RETURN:
- * None.
+ * None.
*/
static void eth_port_init_mac_tables(unsigned int eth_port_num)
{
@@ -1907,18 +2038,16 @@ static void eth_port_init_mac_tables(unsigned int eth_port_num)
/* Clear DA filter unicast table (Ex_dFUT) */
for (table_index = 0; table_index <= 0xC; table_index += 4)
- MV_WRITE(
- (MV64340_ETH_DA_FILTER_UNICAST_TABLE_BASE
- (eth_port_num) + table_index), 0);
+ mv_write((MV643XX_ETH_DA_FILTER_UNICAST_TABLE_BASE
+ (eth_port_num) + table_index), 0);
for (table_index = 0; table_index <= 0xFC; table_index += 4) {
/* Clear DA filter special multicast table (Ex_dFSMT) */
- MV_WRITE(
- (MV64340_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((MV64340_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);
}
}
@@ -1926,17 +2055,17 @@ static void eth_port_init_mac_tables(unsigned int eth_port_num)
* eth_clear_mib_counters - Clear all MIB counters
*
* DESCRIPTION:
- * This function clears all MIB counters of a specific ethernet port.
- * A read from the MIB counter will reset the counter.
+ * This function clears all MIB counters of a specific ethernet port.
+ * A read from the MIB counter will reset the counter.
*
* INPUT:
- * unsigned int eth_port_num Ethernet Port number.
+ * unsigned int eth_port_num Ethernet Port number.
*
* OUTPUT:
- * After reading all MIB counters, the counters resets.
+ * After reading all MIB counters, the counters resets.
*
* RETURN:
- * MIB counter value.
+ * MIB counter value.
*
*/
static void eth_clear_mib_counters(unsigned int eth_port_num)
@@ -1944,72 +2073,155 @@ static void eth_clear_mib_counters(unsigned int eth_port_num)
int i;
/* Perform dummy reads from MIB counters */
- for (i = ETH_MIB_GOOD_OCTETS_RECEIVED_LOW; i < ETH_MIB_LATE_COLLISION; i += 4)
- MV_READ(MV64340_ETH_MIB_COUNTERS_BASE(eth_port_num) + i);
+ for (i = ETH_MIB_GOOD_OCTETS_RECEIVED_LOW; i < ETH_MIB_LATE_COLLISION;
+ i += 4)
+ mv_read(MV643XX_ETH_MIB_COUNTERS_BASE(eth_port_num) + i);
+}
+
+static inline u32 read_mib(struct mv643xx_private *mp, int offset)
+{
+ return mv_read(MV643XX_ETH_MIB_COUNTERS_BASE(mp->port_num) + offset);
+}
+
+static void eth_update_mib_counters(struct mv643xx_private *mp)
+{
+ struct mv643xx_mib_counters *p = &mp->mib_counters;
+ int offset;
+
+ p->good_octets_received +=
+ read_mib(mp, ETH_MIB_GOOD_OCTETS_RECEIVED_LOW);
+ p->good_octets_received +=
+ (u64)read_mib(mp, ETH_MIB_GOOD_OCTETS_RECEIVED_HIGH) << 32;
+
+ for (offset = ETH_MIB_BAD_OCTETS_RECEIVED;
+ offset <= ETH_MIB_FRAMES_1024_TO_MAX_OCTETS;
+ offset += 4)
+ *(u32 *)((char *)p + offset) = read_mib(mp, offset);
+
+ p->good_octets_sent += read_mib(mp, ETH_MIB_GOOD_OCTETS_SENT_LOW);
+ p->good_octets_sent +=
+ (u64)read_mib(mp, ETH_MIB_GOOD_OCTETS_SENT_HIGH) << 32;
+
+ for (offset = ETH_MIB_GOOD_FRAMES_SENT;
+ offset <= ETH_MIB_LATE_COLLISION;
+ offset += 4)
+ *(u32 *)((char *)p + offset) = read_mib(mp, offset);
}
+/*
+ * ethernet_phy_detect - Detect whether a phy is present
+ *
+ * DESCRIPTION:
+ * This function tests whether there is a PHY present on
+ * the specified port.
+ *
+ * INPUT:
+ * unsigned int eth_port_num Ethernet Port number.
+ *
+ * OUTPUT:
+ * None
+ *
+ * RETURN:
+ * 0 on success
+ * -ENODEV on failure
+ *
+ */
+static int ethernet_phy_detect(unsigned int port_num)
+{
+ unsigned int phy_reg_data0;
+ int auto_neg;
+
+ eth_port_read_smi_reg(port_num, 0, &phy_reg_data0);
+ auto_neg = phy_reg_data0 & 0x1000;
+ phy_reg_data0 ^= 0x1000; /* invert auto_neg */
+ eth_port_write_smi_reg(port_num, 0, phy_reg_data0);
+
+ eth_port_read_smi_reg(port_num, 0, &phy_reg_data0);
+ if ((phy_reg_data0 & 0x1000) == auto_neg)
+ return -ENODEV; /* change didn't take */
+
+ phy_reg_data0 ^= 0x1000;
+ eth_port_write_smi_reg(port_num, 0, phy_reg_data0);
+ return 0;
+}
/*
* ethernet_phy_get - Get the ethernet port PHY address.
*
* DESCRIPTION:
- * This routine returns the given ethernet port PHY address.
+ * This routine returns the given ethernet port PHY address.
*
* INPUT:
- * unsigned int eth_port_num Ethernet Port number.
+ * unsigned int eth_port_num Ethernet Port number.
*
* OUTPUT:
- * None.
+ * None.
*
* RETURN:
- * PHY address.
+ * PHY address.
*
*/
static int ethernet_phy_get(unsigned int eth_port_num)
{
unsigned int reg_data;
- reg_data = MV_READ(MV64340_ETH_PHY_ADDR_REG);
+ reg_data = mv_read(MV643XX_ETH_PHY_ADDR_REG);
return ((reg_data >> (5 * eth_port_num)) & 0x1f);
}
/*
+ * ethernet_phy_set - Set the ethernet port PHY address.
+ *
+ * DESCRIPTION:
+ * This routine sets the given ethernet port PHY address.
+ *
+ * INPUT:
+ * unsigned int eth_port_num Ethernet Port number.
+ * int phy_addr PHY address.
+ *
+ * OUTPUT:
+ * None.
+ *
+ * RETURN:
+ * None.
+ *
+ */
+static void ethernet_phy_set(unsigned int eth_port_num, int phy_addr)
+{
+ u32 reg_data;
+ int addr_shift = 5 * eth_port_num;
+
+ reg_data = mv_read(MV643XX_ETH_PHY_ADDR_REG);
+ reg_data &= ~(0x1f << addr_shift);
+ reg_data |= (phy_addr & 0x1f) << addr_shift;
+ mv_write(MV643XX_ETH_PHY_ADDR_REG, reg_data);
+}
+
+/*
* ethernet_phy_reset - Reset Ethernet port PHY.
*
* DESCRIPTION:
- * This routine utilize the SMI interface to reset the ethernet port PHY.
- * The routine waits until the link is up again or link up is timeout.
+ * This routine utilizes the SMI interface to reset the ethernet port PHY.
*
* INPUT:
- * unsigned int eth_port_num Ethernet Port number.
+ * unsigned int eth_port_num Ethernet Port number.
*
* OUTPUT:
- * The ethernet port PHY renew its link.
+ * The PHY is reset.
*
* RETURN:
- * None.
+ * None.
*
*/
-static int ethernet_phy_reset(unsigned int eth_port_num)
+static void ethernet_phy_reset(unsigned int eth_port_num)
{
- unsigned int time_out = 50;
unsigned int phy_reg_data;
/* Reset the PHY */
eth_port_read_smi_reg(eth_port_num, 0, &phy_reg_data);
phy_reg_data |= 0x8000; /* Set bit 15 to reset the PHY */
eth_port_write_smi_reg(eth_port_num, 0, phy_reg_data);
-
- /* Poll on the PHY LINK */
- do {
- eth_port_read_smi_reg(eth_port_num, 1, &phy_reg_data);
-
- if (time_out-- == 0)
- return 0;
- } while (!(phy_reg_data & 0x20));
-
- return 1;
}
/*
@@ -2017,381 +2229,358 @@ static int ethernet_phy_reset(unsigned int eth_port_num)
*
* DESCRIPTION:
* This routine resets the chip by aborting any SDMA engine activity and
- * clearing the MIB counters. The Receiver and the Transmit unit are in
- * idle state after this command is performed and the port is disabled.
+ * clearing the MIB counters. The Receiver and the Transmit unit are in
+ * idle state after this command is performed and the port is disabled.
*
* INPUT:
- * unsigned int eth_port_num Ethernet Port number.
+ * unsigned int eth_port_num Ethernet Port number.
*
* OUTPUT:
- * Channel activity is halted.
+ * Channel activity is halted.
*
* RETURN:
- * None.
+ * None.
*
*/
-static void eth_port_reset(unsigned int eth_port_num)
+static void eth_port_reset(unsigned int port_num)
{
unsigned int reg_data;
/* Stop Tx port activity. Check port Tx activity. */
- reg_data =
- MV_READ(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(eth_port_num));
+ reg_data = mv_read(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(port_num));
if (reg_data & 0xFF) {
/* Issue stop command for active channels only */
- MV_WRITE(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG
- (eth_port_num), (reg_data << 8));
+ mv_write(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(port_num),
+ (reg_data << 8));
/* Wait for all Tx activity to terminate. */
- do {
- /* Check port cause register that all Tx queues are stopped */
- reg_data =
- MV_READ
- (MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG
- (eth_port_num));
- }
- while (reg_data & 0xFF);
+ /* Check port cause register that all Tx queues are stopped */
+ while (mv_read(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(port_num))
+ & 0xFF)
+ udelay(10);
}
/* Stop Rx port activity. Check port Rx activity. */
- reg_data =
- MV_READ(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG
- (eth_port_num));
+ reg_data = mv_read(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num));
if (reg_data & 0xFF) {
/* Issue stop command for active channels only */
- MV_WRITE(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG
- (eth_port_num), (reg_data << 8));
+ mv_write(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num),
+ (reg_data << 8));
/* Wait for all Rx activity to terminate. */
- do {
- /* Check port cause register that all Rx queues are stopped */
- reg_data =
- MV_READ
- (MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG
- (eth_port_num));
- }
- while (reg_data & 0xFF);
+ /* Check port cause register that all Rx queues are stopped */
+ while (mv_read(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num))
+ & 0xFF)
+ udelay(10);
}
-
/* Clear all MIB counters */
- eth_clear_mib_counters(eth_port_num);
+ eth_clear_mib_counters(port_num);
/* Reset the Enable bit in the Configuration Register */
- reg_data =
- MV_READ(MV64340_ETH_PORT_SERIAL_CONTROL_REG (eth_port_num));
- reg_data &= ~ETH_SERIAL_PORT_ENABLE;
- MV_WRITE(MV64340_ETH_PORT_SERIAL_CONTROL_REG(eth_port_num), reg_data);
-
- return;
+ reg_data = mv_read(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num));
+ reg_data &= ~MV643XX_ETH_SERIAL_PORT_ENABLE;
+ mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num), reg_data);
}
/*
* ethernet_set_config_reg - Set specified bits in configuration register.
*
* DESCRIPTION:
- * This function sets specified bits in the given ethernet
- * configuration register.
+ * This function sets specified bits in the given ethernet
+ * configuration register.
*
* INPUT:
- * unsigned int eth_port_num Ethernet Port number.
- * unsigned int value 32 bit value.
+ * unsigned int eth_port_num Ethernet Port number.
+ * unsigned int value 32 bit value.
*
* OUTPUT:
- * The set bits in the value parameter are set in the configuration
- * register.
+ * The set bits in the value parameter are set in the configuration
+ * register.
*
* RETURN:
- * None.
+ * None.
*
*/
static void ethernet_set_config_reg(unsigned int eth_port_num,
- unsigned int value)
+ unsigned int value)
{
unsigned int eth_config_reg;
- eth_config_reg =
- MV_READ(MV64340_ETH_PORT_CONFIG_REG(eth_port_num));
+ eth_config_reg = mv_read(MV643XX_ETH_PORT_CONFIG_REG(eth_port_num));
eth_config_reg |= value;
- MV_WRITE(MV64340_ETH_PORT_CONFIG_REG(eth_port_num),
- eth_config_reg);
+ mv_write(MV643XX_ETH_PORT_CONFIG_REG(eth_port_num), eth_config_reg);
+}
+
+static int eth_port_autoneg_supported(unsigned int eth_port_num)
+{
+ unsigned int phy_reg_data0;
+
+ eth_port_read_smi_reg(eth_port_num, 0, &phy_reg_data0);
+
+ return phy_reg_data0 & 0x1000;
+}
+
+static int eth_port_link_is_up(unsigned int eth_port_num)
+{
+ unsigned int phy_reg_data1;
+
+ eth_port_read_smi_reg(eth_port_num, 1, &phy_reg_data1);
+
+ if (eth_port_autoneg_supported(eth_port_num)) {
+ if (phy_reg_data1 & 0x20) /* auto-neg complete */
+ return 1;
+ } else if (phy_reg_data1 & 0x4) /* link up */
+ return 1;
+
+ return 0;
}
/*
* ethernet_get_config_reg - Get the port configuration register
*
* DESCRIPTION:
- * This function returns the configuration register value of the given
- * ethernet port.
+ * This function returns the configuration register value of the given
+ * ethernet port.
*
* INPUT:
- * unsigned int eth_port_num Ethernet Port number.
+ * unsigned int eth_port_num Ethernet Port number.
*
* OUTPUT:
- * None.
+ * None.
*
* RETURN:
- * Port configuration register value.
+ * Port configuration register value.
*/
static unsigned int ethernet_get_config_reg(unsigned int eth_port_num)
{
unsigned int eth_config_reg;
- eth_config_reg = MV_READ(MV64340_ETH_PORT_CONFIG_EXTEND_REG
- (eth_port_num));
+ eth_config_reg = mv_read(MV643XX_ETH_PORT_CONFIG_EXTEND_REG
+ (eth_port_num));
return eth_config_reg;
}
-
/*
* eth_port_read_smi_reg - Read PHY registers
*
* DESCRIPTION:
- * This routine utilize the SMI interface to interact with the PHY in
- * order to perform PHY register read.
+ * This routine utilize the SMI interface to interact with the PHY in
+ * order to perform PHY register read.
*
* INPUT:
- * unsigned int eth_port_num Ethernet Port number.
- * unsigned int phy_reg PHY register address offset.
- * unsigned int *value Register value buffer.
+ * unsigned int port_num Ethernet Port number.
+ * unsigned int phy_reg PHY register address offset.
+ * unsigned int *value Register value buffer.
*
* OUTPUT:
- * Write the value of a specified PHY register into given buffer.
+ * Write the value of a specified PHY register into given buffer.
*
* RETURN:
- * false if the PHY is busy or read data is not in valid state.
- * true otherwise.
+ * false if the PHY is busy or read data is not in valid state.
+ * true otherwise.
*
*/
-static int eth_port_read_smi_reg(unsigned int eth_port_num,
- unsigned int phy_reg, unsigned int *value)
+static void eth_port_read_smi_reg(unsigned int port_num,
+ unsigned int phy_reg, unsigned int *value)
{
- int phy_addr = ethernet_phy_get(eth_port_num);
- unsigned int time_out = PHY_BUSY_TIMEOUT;
- unsigned int reg_value;
-
- /* first check that it is not busy */
- do {
- reg_value = MV_READ(MV64340_ETH_SMI_REG);
- if (time_out-- == 0)
- return 0;
- } while (reg_value & ETH_SMI_BUSY);
-
- /* not busy */
-
- MV_WRITE(MV64340_ETH_SMI_REG,
- (phy_addr << 16) | (phy_reg << 21) | ETH_SMI_OPCODE_READ);
-
- time_out = PHY_BUSY_TIMEOUT; /* initialize the time out var again */
+ int phy_addr = ethernet_phy_get(port_num);
+ unsigned long flags;
+ int i;
- do {
- reg_value = MV_READ(MV64340_ETH_SMI_REG);
- if (time_out-- == 0)
- return 0;
- } while (reg_value & ETH_SMI_READ_VALID);
+ /* the SMI register is a shared resource */
+ spin_lock_irqsave(&mv643xx_eth_phy_lock, flags);
- /* Wait for the data to update in the SMI register */
- for (time_out = 0; time_out < PHY_BUSY_TIMEOUT; time_out++);
+ /* wait for the SMI register to become available */
+ for (i = 0; mv_read(MV643XX_ETH_SMI_REG) & ETH_SMI_BUSY; i++) {
+ if (i == PHY_WAIT_ITERATIONS) {
+ printk("mv643xx PHY busy timeout, port %d\n", port_num);
+ goto out;
+ }
+ udelay(PHY_WAIT_MICRO_SECONDS);
+ }
- reg_value = MV_READ(MV64340_ETH_SMI_REG);
+ mv_write(MV643XX_ETH_SMI_REG,
+ (phy_addr << 16) | (phy_reg << 21) | ETH_SMI_OPCODE_READ);
- *value = reg_value & 0xffff;
+ /* now wait for the data to be valid */
+ for (i = 0; !(mv_read(MV643XX_ETH_SMI_REG) & ETH_SMI_READ_VALID); i++) {
+ if (i == PHY_WAIT_ITERATIONS) {
+ printk("mv643xx PHY read timeout, port %d\n", port_num);
+ goto out;
+ }
+ udelay(PHY_WAIT_MICRO_SECONDS);
+ }
- return 1;
+ *value = mv_read(MV643XX_ETH_SMI_REG) & 0xffff;
+out:
+ spin_unlock_irqrestore(&mv643xx_eth_phy_lock, flags);
}
/*
* eth_port_write_smi_reg - Write to PHY registers
*
* DESCRIPTION:
- * This routine utilize the SMI interface to interact with the PHY in
- * order to perform writes to PHY registers.
+ * This routine utilize the SMI interface to interact with the PHY in
+ * order to perform writes to PHY registers.
*
* INPUT:
- * unsigned int eth_port_num Ethernet Port number.
- * unsigned int phy_reg PHY register address offset.
- * unsigned int value Register value.
+ * unsigned int eth_port_num Ethernet Port number.
+ * unsigned int phy_reg PHY register address offset.
+ * unsigned int value Register value.
*
* OUTPUT:
- * Write the given value to the specified PHY register.
+ * Write the given value to the specified PHY register.
*
* RETURN:
- * false if the PHY is busy.
- * true otherwise.
+ * false if the PHY is busy.
+ * true otherwise.
*
*/
-static int eth_port_write_smi_reg(unsigned int eth_port_num,
- unsigned int phy_reg, unsigned int value)
+static void eth_port_write_smi_reg(unsigned int eth_port_num,
+ unsigned int phy_reg, unsigned int value)
{
- unsigned int time_out = PHY_BUSY_TIMEOUT;
- unsigned int reg_value;
int phy_addr;
+ int i;
+ unsigned long flags;
phy_addr = ethernet_phy_get(eth_port_num);
- /* first check that it is not busy */
- do {
- reg_value = MV_READ(MV64340_ETH_SMI_REG);
- if (time_out-- == 0)
- return 0;
- } while (reg_value & ETH_SMI_BUSY);
+ /* the SMI register is a shared resource */
+ spin_lock_irqsave(&mv643xx_eth_phy_lock, flags);
- /* not busy */
- MV_WRITE(MV64340_ETH_SMI_REG, (phy_addr << 16) | (phy_reg << 21) |
- ETH_SMI_OPCODE_WRITE | (value & 0xffff));
+ /* wait for the SMI register to become available */
+ for (i = 0; mv_read(MV643XX_ETH_SMI_REG) & ETH_SMI_BUSY; i++) {
+ if (i == PHY_WAIT_ITERATIONS) {
+ printk("mv643xx PHY busy timeout, port %d\n",
+ eth_port_num);
+ goto out;
+ }
+ udelay(PHY_WAIT_MICRO_SECONDS);
+ }
- return 1;
+ mv_write(MV643XX_ETH_SMI_REG, (phy_addr << 16) | (phy_reg << 21) |
+ ETH_SMI_OPCODE_WRITE | (value & 0xffff));
+out:
+ spin_unlock_irqrestore(&mv643xx_eth_phy_lock, flags);
}
/*
* eth_port_send - Send an Ethernet packet
*
* DESCRIPTION:
- * This routine send a given packet described by p_pktinfo parameter. It
- * supports transmitting of a packet spaned over multiple buffers. The
- * routine updates 'curr' and 'first' indexes according to the packet
- * segment passed to the routine. In case the packet segment is first,
- * the 'first' index is update. In any case, the 'curr' index is updated.
- * If the routine get into Tx resource error it assigns 'curr' index as
- * 'first'. This way the function can abort Tx process of multiple
- * descriptors per packet.
+ * This routine send a given packet described by p_pktinfo parameter. It
+ * supports transmitting of a packet spaned over multiple buffers. The
+ * routine updates 'curr' and 'first' indexes according to the packet
+ * segment passed to the routine. In case the packet segment is first,
+ * the 'first' index is update. In any case, the 'curr' index is updated.
+ * If the routine get into Tx resource error it assigns 'curr' index as
+ * 'first'. This way the function can abort Tx process of multiple
+ * descriptors per packet.
*
* INPUT:
- * struct mv64340_private *mp Ethernet Port Control srtuct.
- * struct pkt_info *p_pkt_info User packet buffer.
+ * struct mv643xx_private *mp Ethernet Port Control srtuct.
+ * struct pkt_info *p_pkt_info User packet buffer.
*
* OUTPUT:
- * Tx ring 'curr' and 'first' indexes are updated.
+ * Tx ring 'curr' and 'first' indexes are updated.
*
* RETURN:
- * ETH_QUEUE_FULL in case of Tx resource error.
+ * ETH_QUEUE_FULL in case of Tx resource error.
* ETH_ERROR in case the routine can not access Tx desc ring.
* ETH_QUEUE_LAST_RESOURCE if the routine uses the last Tx resource.
- * ETH_OK otherwise.
+ * ETH_OK otherwise.
*
*/
-#ifdef MV64340_CHECKSUM_OFFLOAD_TX
+#ifdef MV643XX_CHECKSUM_OFFLOAD_TX
/*
* Modified to include the first descriptor pointer in case of SG
*/
-static ETH_FUNC_RET_STATUS eth_port_send(struct mv64340_private * mp,
- struct pkt_info * p_pkt_info)
+static ETH_FUNC_RET_STATUS eth_port_send(struct mv643xx_private *mp,
+ struct pkt_info *p_pkt_info)
{
int tx_desc_curr, tx_desc_used, tx_first_desc, tx_next_desc;
- volatile struct eth_tx_desc *current_descriptor;
- volatile struct eth_tx_desc *first_descriptor;
- u32 command_status, first_chip_ptr;
+ struct eth_tx_desc *current_descriptor;
+ struct eth_tx_desc *first_descriptor;
+ u32 command;
/* Do not process Tx ring in case of Tx ring resource error */
if (mp->tx_resource_err)
return ETH_QUEUE_FULL;
+ /*
+ * The hardware requires that each buffer that is <= 8 bytes
+ * in length must be aligned on an 8 byte boundary.
+ */
+ if (p_pkt_info->byte_cnt <= 8 && p_pkt_info->buf_ptr & 0x7) {
+ printk(KERN_ERR
+ "mv643xx_eth port %d: packet size <= 8 problem\n",
+ mp->port_num);
+ return ETH_ERROR;
+ }
+
/* Get the Tx Desc ring indexes */
tx_desc_curr = mp->tx_curr_desc_q;
tx_desc_used = mp->tx_used_desc_q;
current_descriptor = &mp->p_tx_desc_area[tx_desc_curr];
- if (current_descriptor == NULL)
- return ETH_ERROR;
- tx_next_desc = (tx_desc_curr + 1) % MV64340_TX_QUEUE_SIZE;
- command_status = p_pkt_info->cmd_sts | ETH_ZERO_PADDING | ETH_GEN_CRC;
+ tx_next_desc = (tx_desc_curr + 1) % mp->tx_ring_size;
+
+ current_descriptor->buf_ptr = p_pkt_info->buf_ptr;
+ current_descriptor->byte_cnt = p_pkt_info->byte_cnt;
+ current_descriptor->l4i_chk = p_pkt_info->l4i_chk;
+ mp->tx_skb[tx_desc_curr] = p_pkt_info->return_info;
- if (command_status & ETH_TX_FIRST_DESC) {
+ command = p_pkt_info->cmd_sts | ETH_ZERO_PADDING | ETH_GEN_CRC |
+ ETH_BUFFER_OWNED_BY_DMA;
+ if (command & ETH_TX_FIRST_DESC) {
tx_first_desc = tx_desc_curr;
mp->tx_first_desc_q = tx_first_desc;
+ first_descriptor = current_descriptor;
+ mp->tx_first_command = command;
+ } else {
+ tx_first_desc = mp->tx_first_desc_q;
+ first_descriptor = &mp->p_tx_desc_area[tx_first_desc];
+ BUG_ON(first_descriptor == NULL);
+ current_descriptor->cmd_sts = command;
+ }
- /* fill first descriptor */
- first_descriptor = &mp->p_tx_desc_area[tx_desc_curr];
- first_descriptor->l4i_chk = p_pkt_info->l4i_chk;
- first_descriptor->cmd_sts = command_status;
- first_descriptor->byte_cnt = p_pkt_info->byte_cnt;
- first_descriptor->buf_ptr = p_pkt_info->buf_ptr;
- first_descriptor->next_desc_ptr = mp->tx_desc_dma +
- tx_next_desc * sizeof(struct eth_tx_desc);
+ if (command & ETH_TX_LAST_DESC) {
wmb();
- } else {
- tx_first_desc = mp->tx_first_desc_q;
- first_descriptor = &mp->p_tx_desc_area[tx_first_desc];
- if (first_descriptor == NULL) {
- printk("First desc is NULL !!\n");
- return ETH_ERROR;
- }
- if (command_status & ETH_TX_LAST_DESC)
- current_descriptor->next_desc_ptr = 0x00000000;
- else {
- command_status |= ETH_BUFFER_OWNED_BY_DMA;
- current_descriptor->next_desc_ptr = mp->tx_desc_dma +
- tx_next_desc * sizeof(struct eth_tx_desc);
- }
- }
-
- if (p_pkt_info->byte_cnt < 8) {
- printk(" < 8 problem \n");
- return ETH_ERROR;
- }
-
- current_descriptor->buf_ptr = p_pkt_info->buf_ptr;
- current_descriptor->byte_cnt = p_pkt_info->byte_cnt;
- current_descriptor->l4i_chk = p_pkt_info->l4i_chk;
- current_descriptor->cmd_sts = command_status;
-
- mp->tx_skb[tx_desc_curr] = (struct sk_buff*) p_pkt_info->return_info;
-
- wmb();
-
- /* Set last desc with DMA ownership and interrupt enable. */
- if (command_status & ETH_TX_LAST_DESC) {
- current_descriptor->cmd_sts = command_status |
- ETH_TX_ENABLE_INTERRUPT |
- ETH_BUFFER_OWNED_BY_DMA;
-
- if (!(command_status & ETH_TX_FIRST_DESC))
- first_descriptor->cmd_sts |= ETH_BUFFER_OWNED_BY_DMA;
- wmb();
-
- first_chip_ptr = MV_READ(MV64340_ETH_CURRENT_SERVED_TX_DESC_PTR(mp->port_num));
-
- /* Apply send command */
- if (first_chip_ptr == 0x00000000)
- MV_WRITE(MV64340_ETH_TX_CURRENT_QUEUE_DESC_PTR_0(mp->port_num), (struct eth_tx_desc *) mp->tx_desc_dma + tx_first_desc);
+ first_descriptor->cmd_sts = mp->tx_first_command;
- ETH_ENABLE_TX_QUEUE(mp->port_num);
+ wmb();
+ ETH_ENABLE_TX_QUEUE(mp->port_num);
/*
* Finish Tx packet. Update first desc in case of Tx resource
* error */
- tx_first_desc = tx_next_desc;
- mp->tx_first_desc_q = tx_first_desc;
- } else {
- if (! (command_status & ETH_TX_FIRST_DESC) ) {
- current_descriptor->cmd_sts = command_status;
- wmb();
- }
+ tx_first_desc = tx_next_desc;
+ mp->tx_first_desc_q = tx_first_desc;
}
- /* Check for ring index overlap in the Tx desc ring */
- if (tx_next_desc == tx_desc_used) {
- mp->tx_resource_err = 1;
- mp->tx_curr_desc_q = tx_first_desc;
+ /* Check for ring index overlap in the Tx desc ring */
+ if (tx_next_desc == tx_desc_used) {
+ mp->tx_resource_err = 1;
+ mp->tx_curr_desc_q = tx_first_desc;
- return ETH_QUEUE_LAST_RESOURCE;
+ return ETH_QUEUE_LAST_RESOURCE;
}
- mp->tx_curr_desc_q = tx_next_desc;
- wmb();
+ mp->tx_curr_desc_q = tx_next_desc;
- return ETH_OK;
+ return ETH_OK;
}
#else
-static ETH_FUNC_RET_STATUS eth_port_send(struct mv64340_private * mp,
- struct pkt_info * p_pkt_info)
+static ETH_FUNC_RET_STATUS eth_port_send(struct mv643xx_private *mp,
+ struct pkt_info *p_pkt_info)
{
int tx_desc_curr;
int tx_desc_used;
- volatile struct eth_tx_desc* current_descriptor;
+ struct eth_tx_desc *current_descriptor;
unsigned int command_status;
/* Do not process Tx ring in case of Tx ring resource error */
@@ -2403,39 +2592,24 @@ static ETH_FUNC_RET_STATUS eth_port_send(struct mv64340_private * mp,
tx_desc_used = mp->tx_used_desc_q;
current_descriptor = &mp->p_tx_desc_area[tx_desc_curr];
- if (current_descriptor == NULL)
- return ETH_ERROR;
-
command_status = p_pkt_info->cmd_sts | ETH_ZERO_PADDING | ETH_GEN_CRC;
-
-/* XXX Is this for real ?!?!? */
- /* Buffers with a payload smaller than 8 bytes must be aligned to a
- * 64-bit boundary. We use the memory allocated for Tx descriptor.
- * This memory is located in TX_BUF_OFFSET_IN_DESC offset within the
- * Tx descriptor. */
- if (p_pkt_info->byte_cnt <= 8) {
- printk(KERN_ERR
- "You have failed in the < 8 bytes errata - fixme\n");
- return ETH_ERROR;
- }
current_descriptor->buf_ptr = p_pkt_info->buf_ptr;
current_descriptor->byte_cnt = p_pkt_info->byte_cnt;
- mp->tx_skb[tx_desc_curr] = (struct sk_buff *) p_pkt_info->return_info;
-
- mb();
+ mp->tx_skb[tx_desc_curr] = p_pkt_info->return_info;
/* Set last desc with DMA ownership and interrupt enable. */
+ wmb();
current_descriptor->cmd_sts = command_status |
ETH_BUFFER_OWNED_BY_DMA | ETH_TX_ENABLE_INTERRUPT;
- /* Apply send command */
+ wmb();
ETH_ENABLE_TX_QUEUE(mp->port_num);
/* Finish Tx packet. Update first desc in case of Tx resource error */
- tx_desc_curr = (tx_desc_curr + 1) % MV64340_TX_QUEUE_SIZE;
+ tx_desc_curr = (tx_desc_curr + 1) % mp->tx_ring_size;
/* Update the current descriptor */
- mp->tx_curr_desc_q = tx_desc_curr;
+ mp->tx_curr_desc_q = tx_desc_curr;
/* Check for ring index overlap in the Tx desc ring */
if (tx_desc_curr == tx_desc_used) {
@@ -2452,62 +2626,55 @@ static ETH_FUNC_RET_STATUS eth_port_send(struct mv64340_private * mp,
*
* DESCRIPTION:
* This routine returns the transmitted packet information to the caller.
- * It uses the 'first' index to support Tx desc return in case a transmit
- * of a packet spanned over multiple buffer still in process.
- * In case the Tx queue was in "resource error" condition, where there are
- * no available Tx resources, the function resets the resource error flag.
+ * It uses the 'first' index to support Tx desc return in case a transmit
+ * of a packet spanned over multiple buffer still in process.
+ * In case the Tx queue was in "resource error" condition, where there are
+ * no available Tx resources, the function resets the resource error flag.
*
* INPUT:
- * struct mv64340_private *mp Ethernet Port Control srtuct.
- * struct pkt_info *p_pkt_info User packet buffer.
+ * struct mv643xx_private *mp Ethernet Port Control srtuct.
+ * struct pkt_info *p_pkt_info User packet buffer.
*
* OUTPUT:
- * Tx ring 'first' and 'used' indexes are updated.
+ * 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_RETRY in case there is transmission in process.
* ETH_END_OF_JOB if the routine has nothing to release.
- * ETH_OK otherwise.
+ * ETH_OK otherwise.
*
*/
-static ETH_FUNC_RET_STATUS eth_tx_return_desc(struct mv64340_private * mp,
- struct pkt_info * p_pkt_info)
+static ETH_FUNC_RET_STATUS eth_tx_return_desc(struct mv643xx_private *mp,
+ struct pkt_info *p_pkt_info)
{
- int tx_desc_used, tx_desc_curr;
-#ifdef MV64340_CHECKSUM_OFFLOAD_TX
- int tx_first_desc;
+ int tx_desc_used;
+#ifdef MV643XX_CHECKSUM_OFFLOAD_TX
+ int tx_busy_desc = mp->tx_first_desc_q;
+#else
+ int tx_busy_desc = mp->tx_curr_desc_q;
#endif
- volatile struct eth_tx_desc *p_tx_desc_used;
+ struct eth_tx_desc *p_tx_desc_used;
unsigned int command_status;
/* Get the Tx Desc ring indexes */
- tx_desc_curr = mp->tx_curr_desc_q;
tx_desc_used = mp->tx_used_desc_q;
-#ifdef MV64340_CHECKSUM_OFFLOAD_TX
- tx_first_desc = mp->tx_first_desc_q;
-#endif
+
p_tx_desc_used = &mp->p_tx_desc_area[tx_desc_used];
- /* XXX Sanity check */
+ /* Sanity check */
if (p_tx_desc_used == NULL)
return ETH_ERROR;
+ /* 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;
+
command_status = p_tx_desc_used->cmd_sts;
/* Still transmitting... */
-#ifndef MV64340_CHECKSUM_OFFLOAD_TX
if (command_status & (ETH_BUFFER_OWNED_BY_DMA))
return ETH_RETRY;
-#endif
- /* Stop release. About to overlap the current available Tx descriptor */
-#ifdef MV64340_CHECKSUM_OFFLOAD_TX
- if (tx_desc_used == tx_first_desc && !mp->tx_resource_err)
- return ETH_END_OF_JOB;
-#else
- if (tx_desc_used == tx_desc_curr && !mp->tx_resource_err)
- return ETH_END_OF_JOB;
-#endif
/* Pass the packet information to the caller */
p_pkt_info->cmd_sts = command_status;
@@ -2515,7 +2682,7 @@ static ETH_FUNC_RET_STATUS eth_tx_return_desc(struct mv64340_private * mp,
mp->tx_skb[tx_desc_used] = NULL;
/* Update the next descriptor to release. */
- mp->tx_used_desc_q = (tx_desc_used + 1) % MV64340_TX_QUEUE_SIZE;
+ mp->tx_used_desc_q = (tx_desc_used + 1) % mp->tx_ring_size;
/* Any Tx return cancels the Tx resource error status */
mp->tx_resource_err = 0;
@@ -2527,30 +2694,30 @@ static ETH_FUNC_RET_STATUS eth_tx_return_desc(struct mv64340_private * mp,
* eth_port_receive - Get received information from Rx ring.
*
* DESCRIPTION:
- * This routine returns the received data to the caller. There is no
- * data copying during routine operation. All information is returned
- * using pointer to packet information struct passed from the caller.
- * If the routine exhausts Rx ring resources then the resource error flag
- * is set.
+ * This routine returns the received data to the caller. There is no
+ * data copying during routine operation. All information is returned
+ * using pointer to packet information struct passed from the caller.
+ * If the routine exhausts Rx ring resources then the resource error flag
+ * is set.
*
* INPUT:
- * struct mv64340_private *mp Ethernet Port Control srtuct.
- * struct pkt_info *p_pkt_info User packet buffer.
+ * struct mv643xx_private *mp Ethernet Port Control srtuct.
+ * struct pkt_info *p_pkt_info User packet buffer.
*
* OUTPUT:
- * Rx ring current and used indexes are updated.
+ * Rx ring current and used indexes are updated.
*
* RETURN:
* ETH_ERROR in case the routine can not access Rx desc ring.
* ETH_QUEUE_FULL if Rx ring resources are exhausted.
* ETH_END_OF_JOB if there is no received data.
- * ETH_OK otherwise.
+ * ETH_OK otherwise.
*/
-static ETH_FUNC_RET_STATUS eth_port_receive(struct mv64340_private * mp,
- struct pkt_info * p_pkt_info)
+static ETH_FUNC_RET_STATUS eth_port_receive(struct mv643xx_private *mp,
+ struct pkt_info *p_pkt_info)
{
int rx_next_curr_desc, rx_curr_desc, rx_used_desc;
- volatile struct eth_rx_desc * p_rx_desc;
+ volatile struct eth_rx_desc *p_rx_desc;
unsigned int command_status;
/* Do not process Rx ring in case of Rx ring resource error */
@@ -2565,6 +2732,7 @@ static ETH_FUNC_RET_STATUS eth_port_receive(struct mv64340_private * mp,
/* The following parameters are used to save readings from memory */
command_status = p_rx_desc->cmd_sts;
+ rmb();
/* Nothing to receive... */
if (command_status & (ETH_BUFFER_OWNED_BY_DMA))
@@ -2577,18 +2745,17 @@ static ETH_FUNC_RET_STATUS eth_port_receive(struct mv64340_private * mp,
p_pkt_info->l4i_chk = p_rx_desc->buf_size;
/* Clean the return info field to indicate that the packet has been */
- /* moved to the upper layers */
+ /* moved to the upper layers */
mp->rx_skb[rx_curr_desc] = NULL;
/* Update current index in data structure */
- rx_next_curr_desc = (rx_curr_desc + 1) % MV64340_RX_QUEUE_SIZE;
+ rx_next_curr_desc = (rx_curr_desc + 1) % mp->rx_ring_size;
mp->rx_curr_desc_q = rx_next_curr_desc;
/* Rx descriptors exhausted. Set the Rx ring resource error flag */
if (rx_next_curr_desc == rx_used_desc)
mp->rx_resource_err = 1;
- mb();
return ETH_OK;
}
@@ -2596,27 +2763,27 @@ static ETH_FUNC_RET_STATUS eth_port_receive(struct mv64340_private * mp,
* eth_rx_return_buff - Returns a Rx buffer back to the Rx ring.
*
* DESCRIPTION:
- * This routine returns a Rx buffer back to the Rx ring. It retrieves the
- * next 'used' descriptor and attached the returned buffer to it.
- * In case the Rx ring was in "resource error" condition, where there are
- * no available Rx resources, the function resets the resource error flag.
+ * This routine returns a Rx buffer back to the Rx ring. It retrieves the
+ * next 'used' descriptor and attached the returned buffer to it.
+ * In case the Rx ring was in "resource error" condition, where there are
+ * no available Rx resources, the function resets the resource error flag.
*
* INPUT:
- * struct mv64340_private *mp Ethernet Port Control srtuct.
- * struct pkt_info *p_pkt_info Information on the returned buffer.
+ * struct mv643xx_private *mp Ethernet Port Control srtuct.
+ * struct pkt_info *p_pkt_info Information on returned buffer.
*
* OUTPUT:
* New available Rx resource in Rx descriptor ring.
*
* RETURN:
* ETH_ERROR in case the routine can not access Rx desc ring.
- * ETH_OK otherwise.
+ * ETH_OK otherwise.
*/
-static ETH_FUNC_RET_STATUS eth_rx_return_buff(struct mv64340_private * mp,
- struct pkt_info * p_pkt_info)
+static ETH_FUNC_RET_STATUS eth_rx_return_buff(struct mv643xx_private *mp,
+ struct pkt_info *p_pkt_info)
{
int used_rx_desc; /* Where to return Rx resource */
- volatile struct eth_rx_desc* p_used_rx_desc;
+ volatile struct eth_rx_desc *p_used_rx_desc;
/* Get 'used' Rx descriptor */
used_rx_desc = mp->rx_used_desc_q;
@@ -2627,20 +2794,240 @@ static ETH_FUNC_RET_STATUS eth_rx_return_buff(struct mv64340_private * mp,
mp->rx_skb[used_rx_desc] = p_pkt_info->return_info;
/* Flush the write pipe */
- mb();
/* Return the descriptor to DMA ownership */
+ wmb();
p_used_rx_desc->cmd_sts =
- ETH_BUFFER_OWNED_BY_DMA | ETH_RX_ENABLE_INTERRUPT;
-
- /* Flush descriptor and CPU pipe */
- mb();
+ ETH_BUFFER_OWNED_BY_DMA | ETH_RX_ENABLE_INTERRUPT;
+ wmb();
/* Move the used descriptor pointer to the next descriptor */
- mp->rx_used_desc_q = (used_rx_desc + 1) % MV64340_RX_QUEUE_SIZE;
+ mp->rx_used_desc_q = (used_rx_desc + 1) % mp->rx_ring_size;
/* Any Rx return cancels the Rx resource error status */
mp->rx_resource_err = 0;
return ETH_OK;
}
+
+/************* Begin ethtool support *************************/
+
+struct mv643xx_stats {
+ char stat_string[ETH_GSTRING_LEN];
+ int sizeof_stat;
+ int stat_offset;
+};
+
+#define MV643XX_STAT(m) sizeof(((struct mv643xx_private *)0)->m), \
+ offsetof(struct mv643xx_private, m)
+
+static const struct mv643xx_stats mv643xx_gstrings_stats[] = {
+ { "rx_packets", MV643XX_STAT(stats.rx_packets) },
+ { "tx_packets", MV643XX_STAT(stats.tx_packets) },
+ { "rx_bytes", MV643XX_STAT(stats.rx_bytes) },
+ { "tx_bytes", MV643XX_STAT(stats.tx_bytes) },
+ { "rx_errors", MV643XX_STAT(stats.rx_errors) },
+ { "tx_errors", MV643XX_STAT(stats.tx_errors) },
+ { "rx_dropped", MV643XX_STAT(stats.rx_dropped) },
+ { "tx_dropped", MV643XX_STAT(stats.tx_dropped) },
+ { "good_octets_received", MV643XX_STAT(mib_counters.good_octets_received) },
+ { "bad_octets_received", MV643XX_STAT(mib_counters.bad_octets_received) },
+ { "internal_mac_transmit_err", MV643XX_STAT(mib_counters.internal_mac_transmit_err) },
+ { "good_frames_received", MV643XX_STAT(mib_counters.good_frames_received) },
+ { "bad_frames_received", MV643XX_STAT(mib_counters.bad_frames_received) },
+ { "broadcast_frames_received", MV643XX_STAT(mib_counters.broadcast_frames_received) },
+ { "multicast_frames_received", MV643XX_STAT(mib_counters.multicast_frames_received) },
+ { "frames_64_octets", MV643XX_STAT(mib_counters.frames_64_octets) },
+ { "frames_65_to_127_octets", MV643XX_STAT(mib_counters.frames_65_to_127_octets) },
+ { "frames_128_to_255_octets", MV643XX_STAT(mib_counters.frames_128_to_255_octets) },
+ { "frames_256_to_511_octets", MV643XX_STAT(mib_counters.frames_256_to_511_octets) },
+ { "frames_512_to_1023_octets", MV643XX_STAT(mib_counters.frames_512_to_1023_octets) },
+ { "frames_1024_to_max_octets", MV643XX_STAT(mib_counters.frames_1024_to_max_octets) },
+ { "good_octets_sent", MV643XX_STAT(mib_counters.good_octets_sent) },
+ { "good_frames_sent", MV643XX_STAT(mib_counters.good_frames_sent) },
+ { "excessive_collision", MV643XX_STAT(mib_counters.excessive_collision) },
+ { "multicast_frames_sent", MV643XX_STAT(mib_counters.multicast_frames_sent) },
+ { "broadcast_frames_sent", MV643XX_STAT(mib_counters.broadcast_frames_sent) },
+ { "unrec_mac_control_received", MV643XX_STAT(mib_counters.unrec_mac_control_received) },
+ { "fc_sent", MV643XX_STAT(mib_counters.fc_sent) },
+ { "good_fc_received", MV643XX_STAT(mib_counters.good_fc_received) },
+ { "bad_fc_received", MV643XX_STAT(mib_counters.bad_fc_received) },
+ { "undersize_received", MV643XX_STAT(mib_counters.undersize_received) },
+ { "fragments_received", MV643XX_STAT(mib_counters.fragments_received) },
+ { "oversize_received", MV643XX_STAT(mib_counters.oversize_received) },
+ { "jabber_received", MV643XX_STAT(mib_counters.jabber_received) },
+ { "mac_receive_error", MV643XX_STAT(mib_counters.mac_receive_error) },
+ { "bad_crc_event", MV643XX_STAT(mib_counters.bad_crc_event) },
+ { "collision", MV643XX_STAT(mib_counters.collision) },
+ { "late_collision", MV643XX_STAT(mib_counters.late_collision) },
+};
+
+#define MV643XX_STATS_LEN \
+ sizeof(mv643xx_gstrings_stats) / sizeof(struct mv643xx_stats)
+
+static int
+mv643xx_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
+{
+ struct mv643xx_private *mp = netdev->priv;
+ int port_num = mp->port_num;
+ int autoneg = eth_port_autoneg_supported(port_num);
+ int mode_10_bit;
+ int auto_duplex;
+ int half_duplex = 0;
+ int full_duplex = 0;
+ int auto_speed;
+ int speed_10 = 0;
+ int speed_100 = 0;
+ int speed_1000 = 0;
+
+ u32 pcs = mv_read(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num));
+ u32 psr = mv_read(MV643XX_ETH_PORT_STATUS_REG(port_num));
+
+ mode_10_bit = psr & MV643XX_ETH_PORT_STATUS_MODE_10_BIT;
+
+ if (mode_10_bit) {
+ ecmd->supported = SUPPORTED_10baseT_Half;
+ } else {
+ ecmd->supported = (SUPPORTED_10baseT_Half |
+ SUPPORTED_10baseT_Full |
+ SUPPORTED_100baseT_Half |
+ SUPPORTED_100baseT_Full |
+ SUPPORTED_1000baseT_Full |
+ (autoneg ? SUPPORTED_Autoneg : 0) |
+ SUPPORTED_TP);
+
+ auto_duplex = !(pcs & MV643XX_ETH_DISABLE_AUTO_NEG_FOR_DUPLX);
+ auto_speed = !(pcs & MV643XX_ETH_DISABLE_AUTO_NEG_SPEED_GMII);
+
+ ecmd->advertising = ADVERTISED_TP;
+
+ if (autoneg) {
+ ecmd->advertising |= ADVERTISED_Autoneg;
+
+ if (auto_duplex) {
+ half_duplex = 1;
+ full_duplex = 1;
+ } else {
+ if (pcs & MV643XX_ETH_SET_FULL_DUPLEX_MODE)
+ full_duplex = 1;
+ else
+ half_duplex = 1;
+ }
+
+ if (auto_speed) {
+ speed_10 = 1;
+ speed_100 = 1;
+ speed_1000 = 1;
+ } else {
+ if (pcs & MV643XX_ETH_SET_GMII_SPEED_TO_1000)
+ speed_1000 = 1;
+ else if (pcs & MV643XX_ETH_SET_MII_SPEED_TO_100)
+ speed_100 = 1;
+ else
+ speed_10 = 1;
+ }
+
+ if (speed_10 & half_duplex)
+ ecmd->advertising |= ADVERTISED_10baseT_Half;
+ if (speed_10 & full_duplex)
+ ecmd->advertising |= ADVERTISED_10baseT_Full;
+ if (speed_100 & half_duplex)
+ ecmd->advertising |= ADVERTISED_100baseT_Half;
+ if (speed_100 & full_duplex)
+ ecmd->advertising |= ADVERTISED_100baseT_Full;
+ if (speed_1000)
+ ecmd->advertising |= ADVERTISED_1000baseT_Full;
+ }
+ }
+
+ ecmd->port = PORT_TP;
+ ecmd->phy_address = ethernet_phy_get(port_num);
+
+ ecmd->transceiver = XCVR_EXTERNAL;
+
+ if (netif_carrier_ok(netdev)) {
+ if (mode_10_bit)
+ ecmd->speed = SPEED_10;
+ else {
+ if (psr & MV643XX_ETH_PORT_STATUS_GMII_1000)
+ ecmd->speed = SPEED_1000;
+ else if (psr & MV643XX_ETH_PORT_STATUS_MII_100)
+ ecmd->speed = SPEED_100;
+ else
+ ecmd->speed = SPEED_10;
+ }
+
+ if (psr & MV643XX_ETH_PORT_STATUS_FULL_DUPLEX)
+ ecmd->duplex = DUPLEX_FULL;
+ else
+ ecmd->duplex = DUPLEX_HALF;
+ } else {
+ ecmd->speed = -1;
+ ecmd->duplex = -1;
+ }
+
+ ecmd->autoneg = autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE;
+ return 0;
+}
+
+static void
+mv643xx_get_drvinfo(struct net_device *netdev,
+ struct ethtool_drvinfo *drvinfo)
+{
+ strncpy(drvinfo->driver, mv643xx_driver_name, 32);
+ strncpy(drvinfo->version, mv643xx_driver_version, 32);
+ strncpy(drvinfo->fw_version, "N/A", 32);
+ strncpy(drvinfo->bus_info, "mv643xx", 32);
+ drvinfo->n_stats = MV643XX_STATS_LEN;
+}
+
+static int
+mv643xx_get_stats_count(struct net_device *netdev)
+{
+ return MV643XX_STATS_LEN;
+}
+
+static void
+mv643xx_get_ethtool_stats(struct net_device *netdev,
+ struct ethtool_stats *stats, uint64_t *data)
+{
+ struct mv643xx_private *mp = netdev->priv;
+ int i;
+
+ eth_update_mib_counters(mp);
+
+ for(i = 0; i < MV643XX_STATS_LEN; i++) {
+ char *p = (char *)mp+mv643xx_gstrings_stats[i].stat_offset;
+ data[i] = (mv643xx_gstrings_stats[i].sizeof_stat ==
+ sizeof(uint64_t)) ? *(uint64_t *)p : *(uint32_t *)p;
+ }
+}
+
+static void
+mv643xx_get_strings(struct net_device *netdev, uint32_t stringset, uint8_t *data)
+{
+ int i;
+
+ switch(stringset) {
+ case ETH_SS_STATS:
+ for (i=0; i < MV643XX_STATS_LEN; i++) {
+ memcpy(data + i * ETH_GSTRING_LEN,
+ mv643xx_gstrings_stats[i].stat_string,
+ ETH_GSTRING_LEN);
+ }
+ break;
+ }
+}
+
+static struct ethtool_ops mv643xx_ethtool_ops = {
+ .get_settings = mv643xx_get_settings,
+ .get_drvinfo = mv643xx_get_drvinfo,
+ .get_link = ethtool_op_get_link,
+ .get_sg = ethtool_op_get_sg,
+ .set_sg = ethtool_op_set_sg,
+ .get_strings = mv643xx_get_strings,
+ .get_stats_count = mv643xx_get_stats_count,
+ .get_ethtool_stats = mv643xx_get_ethtool_stats,
+};
+
+/************* End ethtool support *************************/
diff --git a/drivers/net/mv643xx_eth.h b/drivers/net/mv643xx_eth.h
index 46a057d0c31f4..57c4f8fbfdb62 100644
--- a/drivers/net/mv643xx_eth.h
+++ b/drivers/net/mv643xx_eth.h
@@ -1,5 +1,5 @@
-#ifndef __MV64340_ETH_H__
-#define __MV64340_ETH_H__
+#ifndef __MV643XX_ETH_H__
+#define __MV643XX_ETH_H__
#include <linux/version.h>
#include <linux/module.h>
@@ -46,17 +46,16 @@
* The first part is the high level driver of the gigE ethernet ports.
*/
-#define ETH_PORT0_IRQ_NUM 48 /* main high register, bit0 */
-#define ETH_PORT1_IRQ_NUM ETH_PORT0_IRQ_NUM+1 /* main high register, bit1 */
-#define ETH_PORT2_IRQ_NUM ETH_PORT0_IRQ_NUM+2 /* main high register, bit1 */
-
-/* Checksum offload for Tx works */
-#define MV64340_CHECKSUM_OFFLOAD_TX
-#define MV64340_NAPI
-#define MV64340_TX_FAST_REFILL
-#undef MV64340_COAL
+/* Checksum offload for Tx works for most packets, but
+ * fails if previous packet sent did not use hw csum
+ */
+#undef MV643XX_CHECKSUM_OFFLOAD_TX
+#define MV643XX_NAPI
+#define MV643XX_TX_FAST_REFILL
+#undef MV643XX_RX_QUEUE_FILL_ON_TASK /* Does not work, yet */
+#undef MV643XX_COAL
-/*
+/*
* Number of RX / TX descriptors on RX / TX rings.
* Note that allocating RX descriptors is done by allocating the RX
* ring AND a preallocated RX buffers (skb's) for each descriptor.
@@ -65,89 +64,35 @@
*/
/* Default TX ring size is 1000 descriptors */
-#define MV64340_TX_QUEUE_SIZE 1000
+#define MV643XX_DEFAULT_TX_QUEUE_SIZE 1000
/* Default RX ring size is 400 descriptors */
-#define MV64340_RX_QUEUE_SIZE 400
+#define MV643XX_DEFAULT_RX_QUEUE_SIZE 400
-#define MV64340_TX_COAL 100
-#ifdef MV64340_COAL
-#define MV64340_RX_COAL 100
+#define MV643XX_TX_COAL 100
+#ifdef MV643XX_COAL
+#define MV643XX_RX_COAL 100
#endif
-
/*
- * The second part is the low level driver of the gigE ethernet ports. *
+ * The second part is the low level driver of the gigE ethernet ports.
*/
-
/*
- * Header File for : MV-643xx network interface header
+ * Header File for : MV-643xx network interface header
*
* DESCRIPTION:
- * This header file contains macros typedefs and function declaration for
- * the Marvell Gig Bit Ethernet Controller.
+ * This header file contains macros typedefs and function declaration for
+ * the Marvell Gig Bit Ethernet Controller.
*
* DEPENDENCIES:
- * None.
+ * None.
*
*/
-/* Default port configuration value */
-#define PORT_CONFIG_VALUE \
- ETH_UNICAST_NORMAL_MODE | \
- ETH_DEFAULT_RX_QUEUE_0 | \
- ETH_DEFAULT_RX_ARP_QUEUE_0 | \
- ETH_RECEIVE_BC_IF_NOT_IP_OR_ARP | \
- ETH_RECEIVE_BC_IF_IP | \
- ETH_RECEIVE_BC_IF_ARP | \
- ETH_CAPTURE_TCP_FRAMES_DIS | \
- ETH_CAPTURE_UDP_FRAMES_DIS | \
- ETH_DEFAULT_RX_TCP_QUEUE_0 | \
- ETH_DEFAULT_RX_UDP_QUEUE_0 | \
- ETH_DEFAULT_RX_BPDU_QUEUE_0
-
-/* Default port extend configuration value */
-#define PORT_CONFIG_EXTEND_VALUE \
- ETH_SPAN_BPDU_PACKETS_AS_NORMAL | \
- ETH_PARTITION_DISABLE
-
-
-/* Default sdma control value */
-#define PORT_SDMA_CONFIG_VALUE \
- ETH_RX_BURST_SIZE_16_64BIT | \
- GT_ETH_IPG_INT_RX(0) | \
- ETH_TX_BURST_SIZE_16_64BIT;
-
-#define GT_ETH_IPG_INT_RX(value) \
- ((value & 0x3fff) << 8)
-
-/* Default port serial control value */
-#define PORT_SERIAL_CONTROL_VALUE \
- ETH_FORCE_LINK_PASS | \
- ETH_ENABLE_AUTO_NEG_FOR_DUPLX | \
- ETH_DISABLE_AUTO_NEG_FOR_FLOW_CTRL | \
- ETH_ADV_SYMMETRIC_FLOW_CTRL | \
- ETH_FORCE_FC_MODE_NO_PAUSE_DIS_TX | \
- ETH_FORCE_BP_MODE_NO_JAM | \
- BIT9 | \
- ETH_DO_NOT_FORCE_LINK_FAIL | \
- ETH_RETRANSMIT_16_ATTEMPTS | \
- ETH_ENABLE_AUTO_NEG_SPEED_GMII | \
- ETH_DTE_ADV_0 | \
- ETH_DISABLE_AUTO_NEG_BYPASS | \
- ETH_AUTO_NEG_NO_CHANGE | \
- ETH_MAX_RX_PACKET_9700BYTE | \
- ETH_CLR_EXT_LOOPBACK | \
- ETH_SET_FULL_DUPLEX_MODE | \
- ETH_ENABLE_FLOW_CTRL_TX_RX_IN_FULL_DUPLEX
-
-#define RX_BUFFER_MAX_SIZE 0x4000000
-#define TX_BUFFER_MAX_SIZE 0x4000000
-
/* MAC accepet/reject macros */
-#define ACCEPT_MAC_ADDR 0
-#define REJECT_MAC_ADDR 1
+#define ACCEPT_MAC_ADDR 0
+#define REJECT_MAC_ADDR 1
/* Buffer offset from buffer pointer */
#define RX_BUF_OFFSET 0x2
@@ -155,277 +100,132 @@
/* Gigabit Ethernet Unit Global Registers */
/* MIB Counters register definitions */
-#define ETH_MIB_GOOD_OCTETS_RECEIVED_LOW 0x0
-#define ETH_MIB_GOOD_OCTETS_RECEIVED_HIGH 0x4
-#define ETH_MIB_BAD_OCTETS_RECEIVED 0x8
-#define ETH_MIB_INTERNAL_MAC_TRANSMIT_ERR 0xc
-#define ETH_MIB_GOOD_FRAMES_RECEIVED 0x10
-#define ETH_MIB_BAD_FRAMES_RECEIVED 0x14
-#define ETH_MIB_BROADCAST_FRAMES_RECEIVED 0x18
-#define ETH_MIB_MULTICAST_FRAMES_RECEIVED 0x1c
-#define ETH_MIB_FRAMES_64_OCTETS 0x20
-#define ETH_MIB_FRAMES_65_TO_127_OCTETS 0x24
-#define ETH_MIB_FRAMES_128_TO_255_OCTETS 0x28
-#define ETH_MIB_FRAMES_256_TO_511_OCTETS 0x2c
-#define ETH_MIB_FRAMES_512_TO_1023_OCTETS 0x30
-#define ETH_MIB_FRAMES_1024_TO_MAX_OCTETS 0x34
-#define ETH_MIB_GOOD_OCTETS_SENT_LOW 0x38
-#define ETH_MIB_GOOD_OCTETS_SENT_HIGH 0x3c
-#define ETH_MIB_GOOD_FRAMES_SENT 0x40
-#define ETH_MIB_EXCESSIVE_COLLISION 0x44
-#define ETH_MIB_MULTICAST_FRAMES_SENT 0x48
-#define ETH_MIB_BROADCAST_FRAMES_SENT 0x4c
-#define ETH_MIB_UNREC_MAC_CONTROL_RECEIVED 0x50
-#define ETH_MIB_FC_SENT 0x54
-#define ETH_MIB_GOOD_FC_RECEIVED 0x58
-#define ETH_MIB_BAD_FC_RECEIVED 0x5c
-#define ETH_MIB_UNDERSIZE_RECEIVED 0x60
-#define ETH_MIB_FRAGMENTS_RECEIVED 0x64
-#define ETH_MIB_OVERSIZE_RECEIVED 0x68
-#define ETH_MIB_JABBER_RECEIVED 0x6c
-#define ETH_MIB_MAC_RECEIVE_ERROR 0x70
-#define ETH_MIB_BAD_CRC_EVENT 0x74
-#define ETH_MIB_COLLISION 0x78
-#define ETH_MIB_LATE_COLLISION 0x7c
+#define ETH_MIB_GOOD_OCTETS_RECEIVED_LOW 0x0
+#define ETH_MIB_GOOD_OCTETS_RECEIVED_HIGH 0x4
+#define ETH_MIB_BAD_OCTETS_RECEIVED 0x8
+#define ETH_MIB_INTERNAL_MAC_TRANSMIT_ERR 0xc
+#define ETH_MIB_GOOD_FRAMES_RECEIVED 0x10
+#define ETH_MIB_BAD_FRAMES_RECEIVED 0x14
+#define ETH_MIB_BROADCAST_FRAMES_RECEIVED 0x18
+#define ETH_MIB_MULTICAST_FRAMES_RECEIVED 0x1c
+#define ETH_MIB_FRAMES_64_OCTETS 0x20
+#define ETH_MIB_FRAMES_65_TO_127_OCTETS 0x24
+#define ETH_MIB_FRAMES_128_TO_255_OCTETS 0x28
+#define ETH_MIB_FRAMES_256_TO_511_OCTETS 0x2c
+#define ETH_MIB_FRAMES_512_TO_1023_OCTETS 0x30
+#define ETH_MIB_FRAMES_1024_TO_MAX_OCTETS 0x34
+#define ETH_MIB_GOOD_OCTETS_SENT_LOW 0x38
+#define ETH_MIB_GOOD_OCTETS_SENT_HIGH 0x3c
+#define ETH_MIB_GOOD_FRAMES_SENT 0x40
+#define ETH_MIB_EXCESSIVE_COLLISION 0x44
+#define ETH_MIB_MULTICAST_FRAMES_SENT 0x48
+#define ETH_MIB_BROADCAST_FRAMES_SENT 0x4c
+#define ETH_MIB_UNREC_MAC_CONTROL_RECEIVED 0x50
+#define ETH_MIB_FC_SENT 0x54
+#define ETH_MIB_GOOD_FC_RECEIVED 0x58
+#define ETH_MIB_BAD_FC_RECEIVED 0x5c
+#define ETH_MIB_UNDERSIZE_RECEIVED 0x60
+#define ETH_MIB_FRAGMENTS_RECEIVED 0x64
+#define ETH_MIB_OVERSIZE_RECEIVED 0x68
+#define ETH_MIB_JABBER_RECEIVED 0x6c
+#define ETH_MIB_MAC_RECEIVE_ERROR 0x70
+#define ETH_MIB_BAD_CRC_EVENT 0x74
+#define ETH_MIB_COLLISION 0x78
+#define ETH_MIB_LATE_COLLISION 0x7c
/* Port serial status reg (PSR) */
-#define ETH_INTERFACE_GMII_MII 0
-#define ETH_INTERFACE_PCM BIT0
-#define ETH_LINK_IS_DOWN 0
-#define ETH_LINK_IS_UP BIT1
-#define ETH_PORT_AT_HALF_DUPLEX 0
-#define ETH_PORT_AT_FULL_DUPLEX BIT2
-#define ETH_RX_FLOW_CTRL_DISABLED 0
-#define ETH_RX_FLOW_CTRL_ENBALED BIT3
-#define ETH_GMII_SPEED_100_10 0
-#define ETH_GMII_SPEED_1000 BIT4
-#define ETH_MII_SPEED_10 0
-#define ETH_MII_SPEED_100 BIT5
-#define ETH_NO_TX 0
-#define ETH_TX_IN_PROGRESS BIT7
-#define ETH_BYPASS_NO_ACTIVE 0
-#define ETH_BYPASS_ACTIVE BIT8
-#define ETH_PORT_NOT_AT_PARTITION_STATE 0
-#define ETH_PORT_AT_PARTITION_STATE BIT9
-#define ETH_PORT_TX_FIFO_NOT_EMPTY 0
-#define ETH_PORT_TX_FIFO_EMPTY BIT10
-
-
-/* These macros describes the Port configuration reg (Px_cR) bits */
-#define ETH_UNICAST_NORMAL_MODE 0
-#define ETH_UNICAST_PROMISCUOUS_MODE BIT0
-#define ETH_DEFAULT_RX_QUEUE_0 0
-#define ETH_DEFAULT_RX_QUEUE_1 BIT1
-#define ETH_DEFAULT_RX_QUEUE_2 BIT2
-#define ETH_DEFAULT_RX_QUEUE_3 (BIT2 | BIT1)
-#define ETH_DEFAULT_RX_QUEUE_4 BIT3
-#define ETH_DEFAULT_RX_QUEUE_5 (BIT3 | BIT1)
-#define ETH_DEFAULT_RX_QUEUE_6 (BIT3 | BIT2)
-#define ETH_DEFAULT_RX_QUEUE_7 (BIT3 | BIT2 | BIT1)
-#define ETH_DEFAULT_RX_ARP_QUEUE_0 0
-#define ETH_DEFAULT_RX_ARP_QUEUE_1 BIT4
-#define ETH_DEFAULT_RX_ARP_QUEUE_2 BIT5
-#define ETH_DEFAULT_RX_ARP_QUEUE_3 (BIT5 | BIT4)
-#define ETH_DEFAULT_RX_ARP_QUEUE_4 BIT6
-#define ETH_DEFAULT_RX_ARP_QUEUE_5 (BIT6 | BIT4)
-#define ETH_DEFAULT_RX_ARP_QUEUE_6 (BIT6 | BIT5)
-#define ETH_DEFAULT_RX_ARP_QUEUE_7 (BIT6 | BIT5 | BIT4)
-#define ETH_RECEIVE_BC_IF_NOT_IP_OR_ARP 0
-#define ETH_REJECT_BC_IF_NOT_IP_OR_ARP BIT7
-#define ETH_RECEIVE_BC_IF_IP 0
-#define ETH_REJECT_BC_IF_IP BIT8
-#define ETH_RECEIVE_BC_IF_ARP 0
-#define ETH_REJECT_BC_IF_ARP BIT9
-#define ETH_TX_AM_NO_UPDATE_ERROR_SUMMARY BIT12
-#define ETH_CAPTURE_TCP_FRAMES_DIS 0
-#define ETH_CAPTURE_TCP_FRAMES_EN BIT14
-#define ETH_CAPTURE_UDP_FRAMES_DIS 0
-#define ETH_CAPTURE_UDP_FRAMES_EN BIT15
-#define ETH_DEFAULT_RX_TCP_QUEUE_0 0
-#define ETH_DEFAULT_RX_TCP_QUEUE_1 BIT16
-#define ETH_DEFAULT_RX_TCP_QUEUE_2 BIT17
-#define ETH_DEFAULT_RX_TCP_QUEUE_3 (BIT17 | BIT16)
-#define ETH_DEFAULT_RX_TCP_QUEUE_4 BIT18
-#define ETH_DEFAULT_RX_TCP_QUEUE_5 (BIT18 | BIT16)
-#define ETH_DEFAULT_RX_TCP_QUEUE_6 (BIT18 | BIT17)
-#define ETH_DEFAULT_RX_TCP_QUEUE_7 (BIT18 | BIT17 | BIT16)
-#define ETH_DEFAULT_RX_UDP_QUEUE_0 0
-#define ETH_DEFAULT_RX_UDP_QUEUE_1 BIT19
-#define ETH_DEFAULT_RX_UDP_QUEUE_2 BIT20
-#define ETH_DEFAULT_RX_UDP_QUEUE_3 (BIT20 | BIT19)
-#define ETH_DEFAULT_RX_UDP_QUEUE_4 (BIT21
-#define ETH_DEFAULT_RX_UDP_QUEUE_5 (BIT21 | BIT19)
-#define ETH_DEFAULT_RX_UDP_QUEUE_6 (BIT21 | BIT20)
-#define ETH_DEFAULT_RX_UDP_QUEUE_7 (BIT21 | BIT20 | BIT19)
-#define ETH_DEFAULT_RX_BPDU_QUEUE_0 0
-#define ETH_DEFAULT_RX_BPDU_QUEUE_1 BIT22
-#define ETH_DEFAULT_RX_BPDU_QUEUE_2 BIT23
-#define ETH_DEFAULT_RX_BPDU_QUEUE_3 (BIT23 | BIT22)
-#define ETH_DEFAULT_RX_BPDU_QUEUE_4 BIT24
-#define ETH_DEFAULT_RX_BPDU_QUEUE_5 (BIT24 | BIT22)
-#define ETH_DEFAULT_RX_BPDU_QUEUE_6 (BIT24 | BIT23)
-#define ETH_DEFAULT_RX_BPDU_QUEUE_7 (BIT24 | BIT23 | BIT22)
-
-
-/* These macros describes the Port configuration extend reg (Px_cXR) bits*/
-#define ETH_CLASSIFY_EN BIT0
-#define ETH_SPAN_BPDU_PACKETS_AS_NORMAL 0
-#define ETH_SPAN_BPDU_PACKETS_TO_RX_QUEUE_7 BIT1
-#define ETH_PARTITION_DISABLE 0
-#define ETH_PARTITION_ENABLE BIT2
-
-
-/* Tx/Rx queue command reg (RQCR/TQCR)*/
-#define ETH_QUEUE_0_ENABLE BIT0
-#define ETH_QUEUE_1_ENABLE BIT1
-#define ETH_QUEUE_2_ENABLE BIT2
-#define ETH_QUEUE_3_ENABLE BIT3
-#define ETH_QUEUE_4_ENABLE BIT4
-#define ETH_QUEUE_5_ENABLE BIT5
-#define ETH_QUEUE_6_ENABLE BIT6
-#define ETH_QUEUE_7_ENABLE BIT7
-#define ETH_QUEUE_0_DISABLE BIT8
-#define ETH_QUEUE_1_DISABLE BIT9
-#define ETH_QUEUE_2_DISABLE BIT10
-#define ETH_QUEUE_3_DISABLE BIT11
-#define ETH_QUEUE_4_DISABLE BIT12
-#define ETH_QUEUE_5_DISABLE BIT13
-#define ETH_QUEUE_6_DISABLE BIT14
-#define ETH_QUEUE_7_DISABLE BIT15
-
-
-/* These macros describes the Port Sdma configuration reg (SDCR) bits */
-#define ETH_RIFB BIT0
-#define ETH_RX_BURST_SIZE_1_64BIT 0
-#define ETH_RX_BURST_SIZE_2_64BIT BIT1
-#define ETH_RX_BURST_SIZE_4_64BIT BIT2
-#define ETH_RX_BURST_SIZE_8_64BIT (BIT2 | BIT1)
-#define ETH_RX_BURST_SIZE_16_64BIT BIT3
-#define ETH_BLM_RX_NO_SWAP BIT4
-#define ETH_BLM_RX_BYTE_SWAP 0
-#define ETH_BLM_TX_NO_SWAP BIT5
-#define ETH_BLM_TX_BYTE_SWAP 0
-#define ETH_DESCRIPTORS_BYTE_SWAP BIT6
-#define ETH_DESCRIPTORS_NO_SWAP 0
-#define ETH_TX_BURST_SIZE_1_64BIT 0
-#define ETH_TX_BURST_SIZE_2_64BIT BIT22
-#define ETH_TX_BURST_SIZE_4_64BIT BIT23
-#define ETH_TX_BURST_SIZE_8_64BIT (BIT23 | BIT22)
-#define ETH_TX_BURST_SIZE_16_64BIT BIT24
-
-
-
-/* These macros describes the Port serial control reg (PSCR) bits */
-#define ETH_SERIAL_PORT_DISABLE 0
-#define ETH_SERIAL_PORT_ENABLE BIT0
-#define ETH_FORCE_LINK_PASS BIT1
-#define ETH_DO_NOT_FORCE_LINK_PASS 0
-#define ETH_ENABLE_AUTO_NEG_FOR_DUPLX 0
-#define ETH_DISABLE_AUTO_NEG_FOR_DUPLX BIT2
-#define ETH_ENABLE_AUTO_NEG_FOR_FLOW_CTRL 0
-#define ETH_DISABLE_AUTO_NEG_FOR_FLOW_CTRL BIT3
-#define ETH_ADV_NO_FLOW_CTRL 0
-#define ETH_ADV_SYMMETRIC_FLOW_CTRL BIT4
-#define ETH_FORCE_FC_MODE_NO_PAUSE_DIS_TX 0
-#define ETH_FORCE_FC_MODE_TX_PAUSE_DIS BIT5
-#define ETH_FORCE_BP_MODE_NO_JAM 0
-#define ETH_FORCE_BP_MODE_JAM_TX BIT7
-#define ETH_FORCE_BP_MODE_JAM_TX_ON_RX_ERR BIT8
-#define ETH_FORCE_LINK_FAIL 0
-#define ETH_DO_NOT_FORCE_LINK_FAIL BIT10
-#define ETH_RETRANSMIT_16_ATTEMPTS 0
-#define ETH_RETRANSMIT_FOREVER BIT11
-#define ETH_DISABLE_AUTO_NEG_SPEED_GMII BIT13
-#define ETH_ENABLE_AUTO_NEG_SPEED_GMII 0
-#define ETH_DTE_ADV_0 0
-#define ETH_DTE_ADV_1 BIT14
-#define ETH_DISABLE_AUTO_NEG_BYPASS 0
-#define ETH_ENABLE_AUTO_NEG_BYPASS BIT15
-#define ETH_AUTO_NEG_NO_CHANGE 0
-#define ETH_RESTART_AUTO_NEG BIT16
-#define ETH_MAX_RX_PACKET_1518BYTE 0
-#define ETH_MAX_RX_PACKET_1522BYTE BIT17
-#define ETH_MAX_RX_PACKET_1552BYTE BIT18
-#define ETH_MAX_RX_PACKET_9022BYTE (BIT18 | BIT17)
-#define ETH_MAX_RX_PACKET_9192BYTE BIT19
-#define ETH_MAX_RX_PACKET_9700BYTE (BIT19 | BIT17)
-#define ETH_SET_EXT_LOOPBACK BIT20
-#define ETH_CLR_EXT_LOOPBACK 0
-#define ETH_SET_FULL_DUPLEX_MODE BIT21
-#define ETH_SET_HALF_DUPLEX_MODE 0
-#define ETH_ENABLE_FLOW_CTRL_TX_RX_IN_FULL_DUPLEX BIT22
-#define ETH_DISABLE_FLOW_CTRL_TX_RX_IN_FULL_DUPLEX 0
-#define ETH_SET_GMII_SPEED_TO_10_100 0
-#define ETH_SET_GMII_SPEED_TO_1000 BIT23
-#define ETH_SET_MII_SPEED_TO_10 0
-#define ETH_SET_MII_SPEED_TO_100 BIT24
-
+#define ETH_INTERFACE_GMII_MII 0
+#define ETH_INTERFACE_PCM BIT0
+#define ETH_LINK_IS_DOWN 0
+#define ETH_LINK_IS_UP BIT1
+#define ETH_PORT_AT_HALF_DUPLEX 0
+#define ETH_PORT_AT_FULL_DUPLEX BIT2
+#define ETH_RX_FLOW_CTRL_DISABLED 0
+#define ETH_RX_FLOW_CTRL_ENBALED BIT3
+#define ETH_GMII_SPEED_100_10 0
+#define ETH_GMII_SPEED_1000 BIT4
+#define ETH_MII_SPEED_10 0
+#define ETH_MII_SPEED_100 BIT5
+#define ETH_NO_TX 0
+#define ETH_TX_IN_PROGRESS BIT7
+#define ETH_BYPASS_NO_ACTIVE 0
+#define ETH_BYPASS_ACTIVE BIT8
+#define ETH_PORT_NOT_AT_PARTITION_STATE 0
+#define ETH_PORT_AT_PARTITION_STATE BIT9
+#define ETH_PORT_TX_FIFO_NOT_EMPTY 0
+#define ETH_PORT_TX_FIFO_EMPTY BIT10
+
+#define ETH_DEFAULT_RX_BPDU_QUEUE_3 (BIT23 | BIT22)
+#define ETH_DEFAULT_RX_BPDU_QUEUE_4 BIT24
+#define ETH_DEFAULT_RX_BPDU_QUEUE_5 (BIT24 | BIT22)
+#define ETH_DEFAULT_RX_BPDU_QUEUE_6 (BIT24 | BIT23)
+#define ETH_DEFAULT_RX_BPDU_QUEUE_7 (BIT24 | BIT23 | BIT22)
/* SMI reg */
-#define ETH_SMI_BUSY BIT28 /* 0 - Write, 1 - Read */
-#define ETH_SMI_READ_VALID BIT27 /* 0 - Write, 1 - Read */
+#define ETH_SMI_BUSY BIT28 /* 0 - Write, 1 - Read */
+#define ETH_SMI_READ_VALID BIT27 /* 0 - Write, 1 - Read */
#define ETH_SMI_OPCODE_WRITE 0 /* Completion of Read operation */
-#define ETH_SMI_OPCODE_READ BIT26 /* Operation is in progress */
+#define ETH_SMI_OPCODE_READ BIT26 /* Operation is in progress */
/* SDMA command status fields macros */
/* Tx & Rx descriptors status */
-#define ETH_ERROR_SUMMARY (BIT0)
+#define ETH_ERROR_SUMMARY (BIT0)
/* Tx & Rx descriptors command */
-#define ETH_BUFFER_OWNED_BY_DMA (BIT31)
+#define ETH_BUFFER_OWNED_BY_DMA (BIT31)
/* Tx descriptors status */
-#define ETH_LC_ERROR (0 )
-#define ETH_UR_ERROR (BIT1 )
-#define ETH_RL_ERROR (BIT2 )
-#define ETH_LLC_SNAP_FORMAT (BIT9 )
+#define ETH_LC_ERROR (0 )
+#define ETH_UR_ERROR (BIT1 )
+#define ETH_RL_ERROR (BIT2 )
+#define ETH_LLC_SNAP_FORMAT (BIT9 )
/* Rx descriptors status */
-#define ETH_CRC_ERROR (0 )
-#define ETH_OVERRUN_ERROR (BIT1 )
-#define ETH_MAX_FRAME_LENGTH_ERROR (BIT2 )
-#define ETH_RESOURCE_ERROR ((BIT2 | BIT1))
-#define ETH_VLAN_TAGGED (BIT19)
-#define ETH_BPDU_FRAME (BIT20)
-#define ETH_TCP_FRAME_OVER_IP_V_4 (0 )
-#define ETH_UDP_FRAME_OVER_IP_V_4 (BIT21)
-#define ETH_OTHER_FRAME_TYPE (BIT22)
-#define ETH_LAYER_2_IS_ETH_V_2 (BIT23)
-#define ETH_FRAME_TYPE_IP_V_4 (BIT24)
-#define ETH_FRAME_HEADER_OK (BIT25)
-#define ETH_RX_LAST_DESC (BIT26)
-#define ETH_RX_FIRST_DESC (BIT27)
-#define ETH_UNKNOWN_DESTINATION_ADDR (BIT28)
-#define ETH_RX_ENABLE_INTERRUPT (BIT29)
-#define ETH_LAYER_4_CHECKSUM_OK (BIT30)
+#define ETH_CRC_ERROR (0 )
+#define ETH_OVERRUN_ERROR (BIT1 )
+#define ETH_MAX_FRAME_LENGTH_ERROR (BIT2 )
+#define ETH_RESOURCE_ERROR ((BIT2 | BIT1))
+#define ETH_VLAN_TAGGED (BIT19)
+#define ETH_BPDU_FRAME (BIT20)
+#define ETH_TCP_FRAME_OVER_IP_V_4 (0 )
+#define ETH_UDP_FRAME_OVER_IP_V_4 (BIT21)
+#define ETH_OTHER_FRAME_TYPE (BIT22)
+#define ETH_LAYER_2_IS_ETH_V_2 (BIT23)
+#define ETH_FRAME_TYPE_IP_V_4 (BIT24)
+#define ETH_FRAME_HEADER_OK (BIT25)
+#define ETH_RX_LAST_DESC (BIT26)
+#define ETH_RX_FIRST_DESC (BIT27)
+#define ETH_UNKNOWN_DESTINATION_ADDR (BIT28)
+#define ETH_RX_ENABLE_INTERRUPT (BIT29)
+#define ETH_LAYER_4_CHECKSUM_OK (BIT30)
/* Rx descriptors byte count */
-#define ETH_FRAME_FRAGMENTED (BIT2)
+#define ETH_FRAME_FRAGMENTED (BIT2)
/* Tx descriptors command */
#define ETH_LAYER_4_CHECKSUM_FIRST_DESC (BIT10)
-#define ETH_FRAME_SET_TO_VLAN (BIT15)
-#define ETH_TCP_FRAME (0 )
-#define ETH_UDP_FRAME (BIT16)
-#define ETH_GEN_TCP_UDP_CHECKSUM (BIT17)
-#define ETH_GEN_IP_V_4_CHECKSUM (BIT18)
-#define ETH_ZERO_PADDING (BIT19)
-#define ETH_TX_LAST_DESC (BIT20)
-#define ETH_TX_FIRST_DESC (BIT21)
-#define ETH_GEN_CRC (BIT22)
-#define ETH_TX_ENABLE_INTERRUPT (BIT23)
-#define ETH_AUTO_MODE (BIT30)
+#define ETH_FRAME_SET_TO_VLAN (BIT15)
+#define ETH_TCP_FRAME (0 )
+#define ETH_UDP_FRAME (BIT16)
+#define ETH_GEN_TCP_UDP_CHECKSUM (BIT17)
+#define ETH_GEN_IP_V_4_CHECKSUM (BIT18)
+#define ETH_ZERO_PADDING (BIT19)
+#define ETH_TX_LAST_DESC (BIT20)
+#define ETH_TX_FIRST_DESC (BIT21)
+#define ETH_GEN_CRC (BIT22)
+#define ETH_TX_ENABLE_INTERRUPT (BIT23)
+#define ETH_AUTO_MODE (BIT30)
/* typedefs */
typedef enum _eth_func_ret_status {
- ETH_OK, /* Returned as expected. */
- ETH_ERROR, /* Fundamental error. */
- ETH_RETRY, /* Could not process request. Try later. */
- ETH_END_OF_JOB, /* Ring has nothing to process. */
- ETH_QUEUE_FULL, /* Ring resource error. */
- ETH_QUEUE_LAST_RESOURCE /* Ring resources about to exhaust. */
+ ETH_OK, /* Returned as expected. */
+ ETH_ERROR, /* Fundamental error. */
+ ETH_RETRY, /* Could not process request. Try later.*/
+ ETH_END_OF_JOB, /* Ring has nothing to process. */
+ ETH_QUEUE_FULL, /* Ring resource error. */
+ ETH_QUEUE_LAST_RESOURCE /* Ring resources about to exhaust. */
} ETH_FUNC_RET_STATUS;
typedef enum _eth_target {
@@ -441,66 +241,103 @@ typedef enum _eth_target {
*/
#if defined(__BIG_ENDIAN)
struct eth_rx_desc {
- u16 byte_cnt; /* Descriptor buffer byte count */
- u16 buf_size; /* Buffer size */
- u32 cmd_sts; /* Descriptor command status */
- u32 next_desc_ptr; /* Next descriptor pointer */
- u32 buf_ptr; /* Descriptor buffer pointer */
+ u16 byte_cnt; /* Descriptor buffer byte count */
+ u16 buf_size; /* Buffer size */
+ u32 cmd_sts; /* Descriptor command status */
+ u32 next_desc_ptr; /* Next descriptor pointer */
+ u32 buf_ptr; /* Descriptor buffer pointer */
};
struct eth_tx_desc {
- u16 byte_cnt; /* buffer byte count */
- u16 l4i_chk; /* CPU provided TCP checksum */
- u32 cmd_sts; /* Command/status field */
- u32 next_desc_ptr; /* Pointer to next descriptor */
- u32 buf_ptr; /* pointer to buffer for this descriptor */
+ u16 byte_cnt; /* buffer byte count */
+ u16 l4i_chk; /* CPU provided TCP checksum */
+ u32 cmd_sts; /* Command/status field */
+ u32 next_desc_ptr; /* Pointer to next descriptor */
+ u32 buf_ptr; /* pointer to buffer for this descriptor*/
};
#elif defined(__LITTLE_ENDIAN)
struct eth_rx_desc {
- u32 cmd_sts; /* Descriptor command status */
- u16 buf_size; /* Buffer size */
- u16 byte_cnt; /* Descriptor buffer byte count */
- u32 buf_ptr; /* Descriptor buffer pointer */
- u32 next_desc_ptr; /* Next descriptor pointer */
+ u32 cmd_sts; /* Descriptor command status */
+ u16 buf_size; /* Buffer size */
+ u16 byte_cnt; /* Descriptor buffer byte count */
+ u32 buf_ptr; /* Descriptor buffer pointer */
+ u32 next_desc_ptr; /* Next descriptor pointer */
};
struct eth_tx_desc {
- u32 cmd_sts; /* Command/status field */
- u16 l4i_chk; /* CPU provided TCP checksum */
- u16 byte_cnt; /* buffer byte count */
- u32 buf_ptr; /* pointer to buffer for this descriptor */
- u32 next_desc_ptr; /* Pointer to next descriptor */
+ u32 cmd_sts; /* Command/status field */
+ u16 l4i_chk; /* CPU provided TCP checksum */
+ u16 byte_cnt; /* buffer byte count */
+ u32 buf_ptr; /* pointer to buffer for this descriptor*/
+ u32 next_desc_ptr; /* Pointer to next descriptor */
};
#else
#error One of __BIG_ENDIAN or __LITTLE_ENDIAN must be defined
#endif
-/* Unified struct for Rx and Tx operations. The user is not required to */
-/* be familier with neither Tx nor Rx descriptors. */
+/* Unified struct for Rx and Tx operations. The user is not required to */
+/* be familier with neither Tx nor Rx descriptors. */
struct pkt_info {
- unsigned short byte_cnt; /* Descriptor buffer byte count */
- unsigned short l4i_chk; /* Tx CPU provided TCP Checksum */
- unsigned int cmd_sts; /* Descriptor command status */
- dma_addr_t buf_ptr; /* Descriptor buffer pointer */
- struct sk_buff * return_info; /* User resource return information */
+ unsigned short byte_cnt; /* Descriptor buffer byte count */
+ unsigned short l4i_chk; /* Tx CPU provided TCP Checksum */
+ unsigned int cmd_sts; /* Descriptor command status */
+ dma_addr_t buf_ptr; /* Descriptor buffer pointer */
+ struct sk_buff *return_info; /* User resource return information */
};
-
/* Ethernet port specific infomation */
-struct mv64340_private {
- int port_num; /* User Ethernet port number */
- u8 port_mac_addr[6]; /* User defined port MAC address. */
- u32 port_config; /* User port configuration value */
- u32 port_config_extend; /* User port config extend value */
- u32 port_sdma_config; /* User port SDMA config value */
- u32 port_serial_control; /* User port serial control value */
- u32 port_tx_queue_command; /* Port active Tx queues summary */
- u32 port_rx_queue_command; /* Port active Rx queues summary */
+struct mv643xx_mib_counters {
+ u64 good_octets_received;
+ u32 bad_octets_received;
+ u32 internal_mac_transmit_err;
+ u32 good_frames_received;
+ u32 bad_frames_received;
+ u32 broadcast_frames_received;
+ u32 multicast_frames_received;
+ u32 frames_64_octets;
+ u32 frames_65_to_127_octets;
+ u32 frames_128_to_255_octets;
+ u32 frames_256_to_511_octets;
+ u32 frames_512_to_1023_octets;
+ u32 frames_1024_to_max_octets;
+ u64 good_octets_sent;
+ u32 good_frames_sent;
+ u32 excessive_collision;
+ u32 multicast_frames_sent;
+ u32 broadcast_frames_sent;
+ u32 unrec_mac_control_received;
+ u32 fc_sent;
+ u32 good_fc_received;
+ u32 bad_fc_received;
+ u32 undersize_received;
+ u32 fragments_received;
+ u32 oversize_received;
+ u32 jabber_received;
+ u32 mac_receive_error;
+ u32 bad_crc_event;
+ u32 collision;
+ u32 late_collision;
+};
+
+struct mv643xx_private {
+ int port_num; /* User Ethernet port number */
+ u8 port_mac_addr[6]; /* User defined port MAC address.*/
+ u32 port_config; /* User port configuration value*/
+ u32 port_config_extend; /* User port config extend value*/
+ u32 port_sdma_config; /* User port SDMA config value */
+ u32 port_serial_control; /* User port serial control value */
+ u32 port_tx_queue_command; /* Port active Tx queues summary*/
+ u32 port_rx_queue_command; /* Port active Rx queues summary*/
+
+ u32 rx_sram_addr; /* Base address of rx sram area */
+ u32 rx_sram_size; /* Size of rx sram area */
+ u32 tx_sram_addr; /* Base address of tx sram area */
+ u32 tx_sram_size; /* Size of tx sram area */
- int rx_resource_err; /* Rx ring resource error flag */
- int tx_resource_err; /* Tx ring resource error flag */
+ int rx_resource_err; /* Rx ring resource error flag */
+ int tx_resource_err; /* Tx ring resource error flag */
/* Tx/Rx rings managment indexes fields. For driver use */
@@ -509,30 +346,32 @@ struct mv64340_private {
/* Next available and first returning Tx resource */
int tx_curr_desc_q, tx_used_desc_q;
-#ifdef MV64340_CHECKSUM_OFFLOAD_TX
- int tx_first_desc_q;
+#ifdef MV643XX_CHECKSUM_OFFLOAD_TX
+ int tx_first_desc_q;
+ u32 tx_first_command;
#endif
-#ifdef MV64340_TX_FAST_REFILL
- u32 tx_clean_threshold;
+#ifdef MV643XX_TX_FAST_REFILL
+ u32 tx_clean_threshold;
#endif
- volatile struct eth_rx_desc * p_rx_desc_area;
- dma_addr_t rx_desc_dma;
- unsigned int rx_desc_area_size;
- struct sk_buff * rx_skb[MV64340_RX_QUEUE_SIZE];
+ struct eth_rx_desc *p_rx_desc_area;
+ dma_addr_t rx_desc_dma;
+ unsigned int rx_desc_area_size;
+ struct sk_buff **rx_skb;
- volatile struct eth_tx_desc * p_tx_desc_area;
- dma_addr_t tx_desc_dma;
- unsigned int tx_desc_area_size;
- struct sk_buff * tx_skb[MV64340_TX_QUEUE_SIZE];
+ struct eth_tx_desc *p_tx_desc_area;
+ dma_addr_t tx_desc_dma;
+ unsigned int tx_desc_area_size;
+ struct sk_buff **tx_skb;
- struct work_struct tx_timeout_task;
+ struct work_struct tx_timeout_task;
/*
- * Former struct mv64340_eth_priv members start here
+ * Former struct mv643xx_eth_priv members start here
*/
struct net_device_stats stats;
+ struct mv643xx_mib_counters mib_counters;
spinlock_t lock;
/* Size of Tx Ring per queue */
unsigned int tx_ring_size;
@@ -544,13 +383,13 @@ struct mv64340_private {
unsigned int rx_ring_skbs;
/*
- * rx_task used to fill RX ring out of bottom half context
+ * rx_task used to fill RX ring out of bottom half context
*/
struct work_struct rx_task;
- /*
- * Used in case RX Ring is empty, which can be caused when
- * system does not have resources (skb's)
+ /*
+ * Used in case RX Ring is empty, which can be caused when
+ * system does not have resources (skb's)
*/
struct timer_list timeout;
long rx_task_busy __attribute__ ((aligned(SMP_CACHE_BYTES)));
@@ -563,9 +402,9 @@ struct mv64340_private {
/* ethernet.h API list */
/* Port operation control routines */
-static void eth_port_init(struct mv64340_private *mp);
+static void eth_port_init(struct mv643xx_private *mp);
static void eth_port_reset(unsigned int eth_port_num);
-static int eth_port_start(struct mv64340_private *mp);
+static void eth_port_start(struct mv643xx_private *mp);
static void ethernet_set_config_reg(unsigned int eth_port_num,
unsigned int value);
@@ -576,26 +415,24 @@ static void eth_port_uc_addr_set(unsigned int eth_port_num,
unsigned char *p_addr);
/* PHY and MIB routines */
-static int ethernet_phy_reset(unsigned int eth_port_num);
+static void ethernet_phy_reset(unsigned int eth_port_num);
-static int eth_port_write_smi_reg(unsigned int eth_port_num,
- unsigned int phy_reg,
- unsigned int value);
+static void eth_port_write_smi_reg(unsigned int eth_port_num,
+ unsigned int phy_reg, unsigned int value);
-static int eth_port_read_smi_reg(unsigned int eth_port_num,
- unsigned int phy_reg,
- unsigned int *value);
+static void eth_port_read_smi_reg(unsigned int eth_port_num,
+ unsigned int phy_reg, unsigned int *value);
static void eth_clear_mib_counters(unsigned int eth_port_num);
/* Port data flow control routines */
-static ETH_FUNC_RET_STATUS eth_port_send(struct mv64340_private *mp,
- struct pkt_info * p_pkt_info);
-static ETH_FUNC_RET_STATUS eth_tx_return_desc(struct mv64340_private *mp,
- struct pkt_info * p_pkt_info);
-static ETH_FUNC_RET_STATUS eth_port_receive(struct mv64340_private *mp,
- struct pkt_info * p_pkt_info);
-static ETH_FUNC_RET_STATUS eth_rx_return_buff(struct mv64340_private *mp,
- struct pkt_info * p_pkt_info);
-
-#endif /* __MV64340_ETH_H__ */
+static ETH_FUNC_RET_STATUS eth_port_send(struct mv643xx_private *mp,
+ struct pkt_info *p_pkt_info);
+static ETH_FUNC_RET_STATUS eth_tx_return_desc(struct mv643xx_private *mp,
+ struct pkt_info *p_pkt_info);
+static ETH_FUNC_RET_STATUS eth_port_receive(struct mv643xx_private *mp,
+ struct pkt_info *p_pkt_info);
+static ETH_FUNC_RET_STATUS eth_rx_return_buff(struct mv643xx_private *mp,
+ struct pkt_info *p_pkt_info);
+
+#endif /* __MV643XX_ETH_H__ */
diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c
index df0961ab99fac..223bdadd4c0d5 100644
--- a/drivers/net/natsemi.c
+++ b/drivers/net/natsemi.c
@@ -3162,7 +3162,7 @@ static void __devexit natsemi_remove1 (struct pci_dev *pdev)
* Interrupts must be disabled, otherwise hands_off can cause irq storms.
*/
-static int natsemi_suspend (struct pci_dev *pdev, u32 state)
+static int natsemi_suspend (struct pci_dev *pdev, pm_message_t state)
{
struct net_device *dev = pci_get_drvdata (pdev);
struct netdev_private *np = netdev_priv(dev);
diff --git a/drivers/net/ne2k-pci.c b/drivers/net/ne2k-pci.c
index 7d43a87963860..a1a6c08e7dcf2 100644
--- a/drivers/net/ne2k-pci.c
+++ b/drivers/net/ne2k-pci.c
@@ -654,13 +654,13 @@ static void __devexit ne2k_pci_remove_one (struct pci_dev *pdev)
}
#ifdef CONFIG_PM
-static int ne2k_pci_suspend (struct pci_dev *pdev, u32 state)
+static int ne2k_pci_suspend (struct pci_dev *pdev, pm_message_t state)
{
struct net_device *dev = pci_get_drvdata (pdev);
netif_device_detach(dev);
pci_save_state(pdev);
- pci_set_power_state(pdev, state);
+ pci_set_power_state(pdev, pci_choose_state(pdev, state));
return 0;
}
diff --git a/drivers/net/ne3210.c b/drivers/net/ne3210.c
index f744f8ecd9efe..6c92f09690151 100644
--- a/drivers/net/ne3210.c
+++ b/drivers/net/ne3210.c
@@ -358,6 +358,7 @@ static struct eisa_driver ne3210_eisa_driver = {
MODULE_DESCRIPTION("NE3210 EISA Ethernet driver");
MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(eisa, ne3210_ids);
int ne3210_init(void)
{
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index 29c98d6555d31..edd1b5306b16e 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -60,6 +60,7 @@ static struct netpoll np = {
.local_port = 6665,
.remote_port = 6666,
.remote_mac = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+ .drop = netpoll_queue,
};
static int configured = 0;
diff --git a/drivers/net/ni65.c b/drivers/net/ni65.c
index 1dffbbf83ccb7..925d1dfcc4dc1 100644
--- a/drivers/net/ni65.c
+++ b/drivers/net/ni65.c
@@ -526,8 +526,7 @@ static int __init ni65_probe1(struct net_device *dev,int ioaddr)
ni65_init_lance(p,dev->dev_addr,0,0);
irq_mask = probe_irq_on();
writereg(CSR0_INIT|CSR0_INEA,CSR0); /* trigger interrupt */
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(HZ/50);
+ msleep(20);
dev->irq = probe_irq_off(irq_mask);
if(!dev->irq)
{
diff --git a/drivers/net/ns83820.c b/drivers/net/ns83820.c
index 7b9d83b07e8c3..2fcc181a8624c 100644
--- a/drivers/net/ns83820.c
+++ b/drivers/net/ns83820.c
@@ -2007,8 +2007,7 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_
if (reset_phy) {
printk(KERN_INFO "%s: resetting phy\n", ndev->name);
writel(dev->CFG_cache | CFG_PHY_RST, dev->base + CFG);
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout((HZ+99)/100);
+ msleep(10);
writel(dev->CFG_cache, dev->base + CFG);
}
@@ -2204,7 +2203,7 @@ static void __exit ns83820_exit(void)
pci_unregister_driver(&driver);
}
-MODULE_AUTHOR("Benjamin LaHaise <bcrl@redhat.com>");
+MODULE_AUTHOR("Benjamin LaHaise <bcrl@kvack.org>");
MODULE_DESCRIPTION("National Semiconductor DP83820 10/100/1000 driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c
index a2a8e95f41e3b..3107ccfe8f3d7 100644
--- a/drivers/net/pcmcia/ibmtr_cs.c
+++ b/drivers/net/pcmcia/ibmtr_cs.c
@@ -343,7 +343,8 @@ static void ibmtr_config(dev_link_t *link)
CS_CHECK(MapMemPage, pcmcia_map_mem_page(info->sram_win_handle, &mem));
ti->sram_base = mem.CardOffset >> 12;
- ti->sram_virt = (u_long)ioremap(req.Base, req.Size);
+ ti->sram_virt = ioremap(req.Base, req.Size);
+ ti->sram_phys = req.Base;
CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
@@ -401,7 +402,7 @@ static void ibmtr_release(dev_link_t *link)
pcmcia_release_irq(link->handle, &link->irq);
if (link->win) {
struct tok_info *ti = netdev_priv(dev);
- iounmap((void *)ti->mmio);
+ iounmap(ti->mmio);
pcmcia_release_window(link->win);
pcmcia_release_window(info->sram_win_handle);
}
@@ -433,7 +434,7 @@ static int ibmtr_event(event_t event, int priority,
if (link->state & DEV_CONFIG) {
/* set flag to bypass normal interrupt code */
struct tok_info *priv = netdev_priv(dev);
- priv->sram_virt |= 1;
+ priv->sram_phys |= 1;
netif_device_detach(dev);
}
break;
diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c
index 2d637defe2ec2..58177d67ea128 100644
--- a/drivers/net/pcmcia/xirc2ps_cs.c
+++ b/drivers/net/pcmcia/xirc2ps_cs.c
@@ -415,11 +415,6 @@ next_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
#define PutByte(reg,value) outb((value), ioaddr+(reg))
#define PutWord(reg,value) outw((value), ioaddr+(reg))
-#define Wait(n) do { \
- set_current_state(TASK_UNINTERRUPTIBLE); \
- schedule_timeout(n); \
-} while (0)
-
/*====== Functions used for debugging =================================*/
#if defined(PCMCIA_DEBUG) && 0 /* reading regs may change system status */
static void
@@ -1707,12 +1702,12 @@ hardreset(struct net_device *dev)
SelectPage(4);
udelay(1);
PutByte(XIRCREG4_GPR1, 0); /* clear bit 0: power down */
- Wait(HZ/25); /* wait 40 msec */
+ msleep(40); /* wait 40 msec */
if (local->mohawk)
PutByte(XIRCREG4_GPR1, 1); /* set bit 0: power up */
else
PutByte(XIRCREG4_GPR1, 1 | 4); /* set bit 0: power up, bit 2: AIC */
- Wait(HZ/50); /* wait 20 msec */
+ msleep(20); /* wait 20 msec */
}
static void
@@ -1726,9 +1721,9 @@ do_reset(struct net_device *dev, int full)
hardreset(dev);
PutByte(XIRCREG_CR, SoftReset); /* set */
- Wait(HZ/50); /* wait 20 msec */
+ msleep(20); /* wait 20 msec */
PutByte(XIRCREG_CR, 0); /* clear */
- Wait(HZ/25); /* wait 40 msec */
+ msleep(40); /* wait 40 msec */
if (local->mohawk) {
SelectPage(4);
/* set pin GP1 and GP2 to output (0x0c)
@@ -1739,7 +1734,7 @@ do_reset(struct net_device *dev, int full)
}
/* give the circuits some time to power up */
- Wait(HZ/2); /* about 500ms */
+ msleep(500); /* about 500ms */
local->last_ptr_value = 0;
local->silicon = local->mohawk ? (GetByte(XIRCREG4_BOV) & 0x70) >> 4
@@ -1758,7 +1753,7 @@ do_reset(struct net_device *dev, int full)
SelectPage(0x42);
PutByte(XIRCREG42_SWC1, 0x80);
}
- Wait(HZ/25); /* wait 40 msec to let it complete */
+ msleep(40); /* wait 40 msec to let it complete */
#ifdef PCMCIA_DEBUG
if (pc_debug) {
@@ -1817,7 +1812,7 @@ do_reset(struct net_device *dev, int full)
printk(KERN_INFO "%s: MII selected\n", dev->name);
SelectPage(2);
PutByte(XIRCREG2_MSR, GetByte(XIRCREG2_MSR) | 0x08);
- Wait(HZ/50);
+ msleep(20);
} else {
printk(KERN_INFO "%s: MII detected; using 10mbs\n",
dev->name);
@@ -1826,7 +1821,7 @@ do_reset(struct net_device *dev, int full)
PutByte(XIRCREG42_SWC1, 0xC0);
else /* enable 10BaseT */
PutByte(XIRCREG42_SWC1, 0x80);
- Wait(HZ/25); /* wait 40 msec to let it complete */
+ msleep(40); /* wait 40 msec to let it complete */
}
if (full_duplex)
PutByte(XIRCREG1_ECR, GetByte(XIRCREG1_ECR | FullDuplex));
@@ -1919,7 +1914,7 @@ init_mii(struct net_device *dev)
* Fixme: Better to use a timer here!
*/
for (i=0; i < 35; i++) {
- Wait(HZ/10); /* wait 100 msec */
+ msleep(100); /* wait 100 msec */
status = mii_rd(ioaddr, 0, 1);
if ((status & 0x0020) && (status & 0x0004))
break;
diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c
index 381b785906ce2..17947e6c87937 100644
--- a/drivers/net/pcnet32.c
+++ b/drivers/net/pcnet32.c
@@ -1351,7 +1351,8 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
printk(KERN_INFO "%s: registered as %s\n", dev->name, lp->name);
cards_found++;
- a->write_bcr(ioaddr, 2, 0x1002); /* enable LED writes */
+ /* enable LED writes */
+ a->write_bcr(ioaddr, 2, a->read_bcr(ioaddr, 2) | 0x1000);
return 0;
@@ -1429,25 +1430,36 @@ pcnet32_open(struct net_device *dev)
val |= 0x10;
lp->a.write_csr (ioaddr, 124, val);
- /* 24 Jun 2004 according AMD, in order to change the PHY,
- * DANAS (or DISPM for 79C976) must be set; then select the speed,
- * duplex, and/or enable auto negotiation, and clear DANAS */
- if (lp->mii && !(lp->options & PCNET32_PORT_ASEL)) {
- lp->a.write_bcr(ioaddr, 32, lp->a.read_bcr(ioaddr, 32) | 0x0080);
- /* disable Auto Negotiation, set 10Mpbs, HD */
- val = lp->a.read_bcr(ioaddr, 32) & ~0xb8;
- if (lp->options & PCNET32_PORT_FD)
- val |= 0x10;
- if (lp->options & PCNET32_PORT_100)
- val |= 0x08;
- lp->a.write_bcr (ioaddr, 32, val);
+ /* Allied Telesyn AT 2700/2701 FX looses the link, so skip that */
+ if (lp->pci_dev->subsystem_vendor == PCI_VENDOR_ID_AT &&
+ (lp->pci_dev->subsystem_device == PCI_SUBDEVICE_ID_AT_2700FX ||
+ lp->pci_dev->subsystem_device == PCI_SUBDEVICE_ID_AT_2701FX)) {
+ printk(KERN_DEBUG "%s: Skipping PHY selection.\n", dev->name);
} else {
- if (lp->options & PCNET32_PORT_ASEL) {
- lp->a.write_bcr(ioaddr, 32, lp->a.read_bcr(ioaddr, 32) | 0x0080);
- /* enable auto negotiate, setup, disable fd */
- val = lp->a.read_bcr(ioaddr, 32) & ~0x98;
- val |= 0x20;
- lp->a.write_bcr(ioaddr, 32, val);
+ /*
+ * 24 Jun 2004 according AMD, in order to change the PHY,
+ * DANAS (or DISPM for 79C976) must be set; then select the speed,
+ * duplex, and/or enable auto negotiation, and clear DANAS
+ */
+ if (lp->mii && !(lp->options & PCNET32_PORT_ASEL)) {
+ lp->a.write_bcr(ioaddr, 32,
+ lp->a.read_bcr(ioaddr, 32) | 0x0080);
+ /* disable Auto Negotiation, set 10Mpbs, HD */
+ val = lp->a.read_bcr(ioaddr, 32) & ~0xb8;
+ if (lp->options & PCNET32_PORT_FD)
+ val |= 0x10;
+ if (lp->options & PCNET32_PORT_100)
+ val |= 0x08;
+ lp->a.write_bcr (ioaddr, 32, val);
+ } else {
+ if (lp->options & PCNET32_PORT_ASEL) {
+ lp->a.write_bcr(ioaddr, 32,
+ lp->a.read_bcr(ioaddr, 32) | 0x0080);
+ /* enable auto negotiate, setup, disable fd */
+ val = lp->a.read_bcr(ioaddr, 32) & ~0x98;
+ val |= 0x20;
+ lp->a.write_bcr(ioaddr, 32, val);
+ }
}
}
diff --git a/drivers/net/ppp_async.c b/drivers/net/ppp_async.c
index a48e19391208f..33b9d79b1aada 100644
--- a/drivers/net/ppp_async.c
+++ b/drivers/net/ppp_async.c
@@ -1000,7 +1000,7 @@ static void async_lcp_peek(struct asyncppp *ap, unsigned char *data,
data += 4;
dlen -= 4;
/* data[0] is code, data[1] is length */
- while (dlen >= 2 && dlen >= data[1]) {
+ while (dlen >= 2 && dlen >= data[1] && data[1] >= 2) {
switch (data[0]) {
case LCP_MRU:
val = (data[2] << 8) + data[3];
diff --git a/drivers/net/ppp_deflate.c b/drivers/net/ppp_deflate.c
index df75c94e1d0c4..507d6328d4eb0 100644
--- a/drivers/net/ppp_deflate.c
+++ b/drivers/net/ppp_deflate.c
@@ -600,7 +600,7 @@ extern void ppp_unregister_compressor (struct compressor *cp);
/*
* Procedures exported to if_ppp.c.
*/
-struct compressor ppp_deflate = {
+static struct compressor ppp_deflate = {
.compress_proto = CI_DEFLATE,
.comp_alloc = z_comp_alloc,
.comp_free = z_comp_free,
@@ -618,7 +618,7 @@ struct compressor ppp_deflate = {
.owner = THIS_MODULE
};
-struct compressor ppp_deflate_draft = {
+static struct compressor ppp_deflate_draft = {
.compress_proto = CI_DEFLATE_DRAFT,
.comp_alloc = z_comp_alloc,
.comp_free = z_comp_free,
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
index f5c918a7992df..c456dc81b8730 100644
--- a/drivers/net/ppp_generic.c
+++ b/drivers/net/ppp_generic.c
@@ -2741,8 +2741,6 @@ EXPORT_SYMBOL(ppp_input_error);
EXPORT_SYMBOL(ppp_output_wakeup);
EXPORT_SYMBOL(ppp_register_compressor);
EXPORT_SYMBOL(ppp_unregister_compressor);
-EXPORT_SYMBOL(all_ppp_units); /* for debugging */
-EXPORT_SYMBOL(all_channels); /* for debugging */
MODULE_LICENSE("GPL");
MODULE_ALIAS_CHARDEV_MAJOR(PPP_MAJOR);
MODULE_ALIAS("/dev/ppp");
diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c
index 44e182efb3655..d597a051bc7df 100644
--- a/drivers/net/pppoe.c
+++ b/drivers/net/pppoe.c
@@ -120,17 +120,17 @@ static int hash_item(unsigned long sid, unsigned char *addr)
}
/* zeroed because its in .bss */
-static struct pppox_opt *item_hash_table[PPPOE_HASH_SIZE];
+static struct pppox_sock *item_hash_table[PPPOE_HASH_SIZE];
/**********************************************************************
*
* Set/get/delete/rehash items (internal versions)
*
**********************************************************************/
-static struct pppox_opt *__get_item(unsigned long sid, unsigned char *addr)
+static struct pppox_sock *__get_item(unsigned long sid, unsigned char *addr)
{
int hash = hash_item(sid, addr);
- struct pppox_opt *ret;
+ struct pppox_sock *ret;
ret = item_hash_table[hash];
@@ -140,10 +140,10 @@ static struct pppox_opt *__get_item(unsigned long sid, unsigned char *addr)
return ret;
}
-static int __set_item(struct pppox_opt *po)
+static int __set_item(struct pppox_sock *po)
{
int hash = hash_item(po->pppoe_pa.sid, po->pppoe_pa.remote);
- struct pppox_opt *ret;
+ struct pppox_sock *ret;
ret = item_hash_table[hash];
while (ret) {
@@ -161,10 +161,10 @@ static int __set_item(struct pppox_opt *po)
return 0;
}
-static struct pppox_opt *__delete_item(unsigned long sid, char *addr)
+static struct pppox_sock *__delete_item(unsigned long sid, char *addr)
{
int hash = hash_item(sid, addr);
- struct pppox_opt *ret, **src;
+ struct pppox_sock *ret, **src;
ret = item_hash_table[hash];
src = &item_hash_table[hash];
@@ -187,26 +187,26 @@ static struct pppox_opt *__delete_item(unsigned long sid, char *addr)
* Set/get/delete/rehash items
*
**********************************************************************/
-static inline struct pppox_opt *get_item(unsigned long sid,
+static inline struct pppox_sock *get_item(unsigned long sid,
unsigned char *addr)
{
- struct pppox_opt *po;
+ struct pppox_sock *po;
read_lock_bh(&pppoe_hash_lock);
po = __get_item(sid, addr);
if (po)
- sock_hold(po->sk);
+ sock_hold(sk_pppox(po));
read_unlock_bh(&pppoe_hash_lock);
return po;
}
-static inline struct pppox_opt *get_item_by_addr(struct sockaddr_pppox *sp)
+static inline struct pppox_sock *get_item_by_addr(struct sockaddr_pppox *sp)
{
return get_item(sp->sa_addr.pppoe.sid, sp->sa_addr.pppoe.remote);
}
-static inline int set_item(struct pppox_opt *po)
+static inline int set_item(struct pppox_sock *po)
{
int i;
@@ -220,9 +220,9 @@ static inline int set_item(struct pppox_opt *po)
return i;
}
-static inline struct pppox_opt *delete_item(unsigned long sid, char *addr)
+static inline struct pppox_sock *delete_item(unsigned long sid, char *addr)
{
- struct pppox_opt *ret;
+ struct pppox_sock *ret;
write_lock_bh(&pppoe_hash_lock);
ret = __delete_item(sid, addr);
@@ -248,11 +248,11 @@ static void pppoe_flush_dev(struct net_device *dev)
read_lock_bh(&pppoe_hash_lock);
for (hash = 0; hash < PPPOE_HASH_SIZE; hash++) {
- struct pppox_opt *po = item_hash_table[hash];
+ struct pppox_sock *po = item_hash_table[hash];
while (po != NULL) {
if (po->pppoe_dev == dev) {
- struct sock *sk = po->sk;
+ struct sock *sk = sk_pppox(po);
sock_hold(sk);
po->pppoe_dev = NULL;
@@ -331,14 +331,16 @@ static struct notifier_block pppoe_notifier = {
***********************************************************************/
static int pppoe_rcv_core(struct sock *sk, struct sk_buff *skb)
{
- struct pppox_opt *po = pppox_sk(sk);
- struct pppox_opt *relay_po = NULL;
+ struct pppox_sock *po = pppox_sk(sk);
+ struct pppox_sock *relay_po = NULL;
if (sk->sk_state & PPPOX_BOUND) {
struct pppoe_hdr *ph = (struct pppoe_hdr *) skb->nh.raw;
int len = ntohs(ph->length);
skb_pull(skb, sizeof(struct pppoe_hdr));
- skb_trim(skb, len);
+ skb_postpull_rcsum(skb, ph, sizeof(*ph));
+ if (pskb_trim_rcsum(skb, len))
+ goto abort_kfree;
ppp_input(&po->chan, skb);
} else if (sk->sk_state & PPPOX_RELAY) {
@@ -347,11 +349,11 @@ static int pppoe_rcv_core(struct sock *sk, struct sk_buff *skb)
if (relay_po == NULL)
goto abort_kfree;
- if ((relay_po->sk->sk_state & PPPOX_CONNECTED) == 0)
+ if ((sk_pppox(relay_po)->sk_state & PPPOX_CONNECTED) == 0)
goto abort_put;
skb_pull(skb, sizeof(struct pppoe_hdr));
- if (!__pppoe_xmit( relay_po->sk, skb))
+ if (!__pppoe_xmit(sk_pppox(relay_po), skb))
goto abort_put;
} else {
if (sock_queue_rcv_skb(sk, skb))
@@ -361,7 +363,7 @@ static int pppoe_rcv_core(struct sock *sk, struct sk_buff *skb)
return NET_RX_SUCCESS;
abort_put:
- sock_put(relay_po->sk);
+ sock_put(sk_pppox(relay_po));
abort_kfree:
kfree_skb(skb);
@@ -379,7 +381,7 @@ static int pppoe_rcv(struct sk_buff *skb,
{
struct pppoe_hdr *ph;
- struct pppox_opt *po;
+ struct pppox_sock *po;
struct sock *sk;
int ret;
@@ -395,7 +397,7 @@ static int pppoe_rcv(struct sk_buff *skb,
if (!po)
goto drop;
- sk = po->sk;
+ sk = sk_pppox(po);
bh_lock_sock(sk);
/* Socket state is unknown, must put skb into backlog. */
@@ -428,7 +430,7 @@ static int pppoe_disc_rcv(struct sk_buff *skb,
{
struct pppoe_hdr *ph;
- struct pppox_opt *po;
+ struct pppox_sock *po;
if (!pskb_may_pull(skb, sizeof(struct pppoe_hdr)))
goto abort;
@@ -442,7 +444,7 @@ static int pppoe_disc_rcv(struct sk_buff *skb,
po = get_item((unsigned long) ph->sid, eth_hdr(skb)->h_source);
if (po) {
- struct sock *sk = po->sk;
+ struct sock *sk = sk_pppox(po);
bh_lock_sock(sk);
@@ -480,20 +482,6 @@ static struct packet_type pppoed_ptype = {
/***********************************************************************
*
- * Really kill the socket. (Called from pppox_sk_free if refcnt == 0.)
- *
- **********************************************************************/
-static void pppoe_sk_free(struct sock *sk)
-{
- struct pppox_opt *po = pppox_sk(sk);
-
- if (po)
- kfree(po);
-}
-
-
-/***********************************************************************
- *
* Initialize a new struct sock.
*
**********************************************************************/
@@ -501,9 +489,8 @@ static int pppoe_create(struct socket *sock)
{
int error = -ENOMEM;
struct sock *sk;
- struct pppox_opt *po;
- sk = sk_alloc(PF_PPPOX, GFP_KERNEL, 1, NULL);
+ sk = sk_alloc(PF_PPPOX, GFP_KERNEL, sizeof(struct pppox_sock), NULL);
if (!sk)
goto out;
@@ -517,23 +504,15 @@ static int pppoe_create(struct socket *sock)
sk->sk_type = SOCK_STREAM;
sk->sk_family = PF_PPPOX;
sk->sk_protocol = PX_PROTO_OE;
- sk->sk_destruct = pppoe_sk_free;
- po = sk->sk_protinfo = kmalloc(sizeof(*po), GFP_KERNEL);
- if (!po)
- goto frees;
- memset(po, 0, sizeof(*po));
- po->sk = sk;
error = 0;
out: return error;
-frees: sk_free(sk);
- goto out;
}
static int pppoe_release(struct socket *sock)
{
struct sock *sk = sock->sk;
- struct pppox_opt *po;
+ struct pppox_sock *po;
int error = 0;
if (!sk)
@@ -573,7 +552,7 @@ static int pppoe_connect(struct socket *sock, struct sockaddr *uservaddr,
struct sock *sk = sock->sk;
struct net_device *dev = NULL;
struct sockaddr_pppox *sp = (struct sockaddr_pppox *) uservaddr;
- struct pppox_opt *po = pppox_sk(sk);
+ struct pppox_sock *po = pppox_sk(sk);
int error;
lock_sock(sk);
@@ -602,8 +581,8 @@ static int pppoe_connect(struct socket *sock, struct sockaddr *uservaddr,
if(po->pppoe_dev)
dev_put(po->pppoe_dev);
- memset(po, 0, sizeof(struct pppox_opt));
- po->sk = sk;
+ memset(sk_pppox(po) + 1, 0,
+ sizeof(struct pppox_sock) - sizeof(struct sock));
sk->sk_state = PPPOX_NONE;
}
@@ -679,7 +658,7 @@ static int pppoe_ioctl(struct socket *sock, unsigned int cmd,
unsigned long arg)
{
struct sock *sk = sock->sk;
- struct pppox_opt *po = pppox_sk(sk);
+ struct pppox_sock *po = pppox_sk(sk);
int val = 0;
int err = 0;
@@ -725,7 +704,7 @@ static int pppoe_ioctl(struct socket *sock, unsigned int cmd,
case PPPOEIOCSFWD:
{
- struct pppox_opt *relay_po;
+ struct pppox_sock *relay_po;
err = -EBUSY;
if (sk->sk_state & (PPPOX_BOUND | PPPOX_ZOMBIE | PPPOX_DEAD))
@@ -755,7 +734,7 @@ static int pppoe_ioctl(struct socket *sock, unsigned int cmd,
if (!relay_po)
break;
- sock_put(relay_po->sk);
+ sock_put(sk_pppox(relay_po));
sk->sk_state |= PPPOX_RELAY;
err = 0;
break;
@@ -782,7 +761,7 @@ static int pppoe_sendmsg(struct kiocb *iocb, struct socket *sock,
{
struct sk_buff *skb = NULL;
struct sock *sk = sock->sk;
- struct pppox_opt *po = pppox_sk(sk);
+ struct pppox_sock *po = pppox_sk(sk);
int error = 0;
struct pppoe_hdr hdr;
struct pppoe_hdr *ph;
@@ -857,7 +836,7 @@ end:
***********************************************************************/
static int __pppoe_xmit(struct sock *sk, struct sk_buff *skb)
{
- struct pppox_opt *po = pppox_sk(sk);
+ struct pppox_sock *po = pppox_sk(sk);
struct net_device *dev = po->pppoe_dev;
struct pppoe_hdr hdr;
struct pppoe_hdr *ph;
@@ -984,7 +963,7 @@ end:
#ifdef CONFIG_PROC_FS
static int pppoe_seq_show(struct seq_file *seq, void *v)
{
- struct pppox_opt *po;
+ struct pppox_sock *po;
char *dev_name;
if (v == SEQ_START_TOKEN) {
@@ -1004,9 +983,9 @@ out:
return 0;
}
-static __inline__ struct pppox_opt *pppoe_get_idx(loff_t pos)
+static __inline__ struct pppox_sock *pppoe_get_idx(loff_t pos)
{
- struct pppox_opt *po = NULL;
+ struct pppox_sock *po = NULL;
int i = 0;
for (; i < PPPOE_HASH_SIZE; i++) {
@@ -1031,7 +1010,7 @@ static void *pppoe_seq_start(struct seq_file *seq, loff_t *pos)
static void *pppoe_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
- struct pppox_opt *po;
+ struct pppox_sock *po;
++*pos;
if (v == SEQ_START_TOKEN) {
@@ -1059,7 +1038,7 @@ static void pppoe_seq_stop(struct seq_file *seq, void *v)
read_unlock_bh(&pppoe_hash_lock);
}
-struct seq_operations pppoe_seq_ops = {
+static struct seq_operations pppoe_seq_ops = {
.start = pppoe_seq_start,
.next = pppoe_seq_next,
.stop = pppoe_seq_stop,
diff --git a/drivers/net/pppox.c b/drivers/net/pppox.c
index 0a585bc369c56..0c1e114527fb3 100644
--- a/drivers/net/pppox.c
+++ b/drivers/net/pppox.c
@@ -72,7 +72,7 @@ static int pppox_ioctl(struct socket* sock, unsigned int cmd,
unsigned long arg)
{
struct sock *sk = sock->sk;
- struct pppox_opt *po = pppox_sk(sk);
+ struct pppox_sock *po = pppox_sk(sk);
int rc = 0;
lock_sock(sk);
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index a0584ab6f574e..434e4ff967b2d 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -41,7 +41,14 @@ VERSION 1.6LK <2004/04/14>
- Suspend/resume
- Endianness
- Misc Rx/Tx bugs
-*/
+
+VERSION 2.2LK <2005/01/25>
+
+ - RX csum, TX csum/SG, TSO
+ - VLAN
+ - baby (< 7200) Jumbo frames support
+ - Merge of Realtek's version 2.2 (new phy)
+ */
#include <linux/module.h>
#include <linux/moduleparam.h>
@@ -62,7 +69,7 @@ VERSION 1.6LK <2004/04/14>
#include <asm/io.h>
#include <asm/irq.h>
-#define RTL8169_VERSION "1.6LK"
+#define RTL8169_VERSION "2.2LK"
#define MODULENAME "r8169"
#define PFX MODULENAME ": "
@@ -72,7 +79,7 @@ VERSION 1.6LK <2004/04/14>
printk( "Assertion failed! %s,%s,%s,line=%d\n", \
#expr,__FILE__,__FUNCTION__,__LINE__); \
}
-#define dprintk(fmt, args...) do { printk(PFX fmt, ## args) } while (0)
+#define dprintk(fmt, args...) do { printk(PFX fmt, ## args); } while (0)
#else
#define assert(expr) do {} while (0)
#define dprintk(fmt, args...) do {} while (0)
@@ -100,15 +107,13 @@ static int num_media = 0;
static int max_interrupt_work = 20;
/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast).
- The RTL chips use a 64 element hash table based on the Ethernet CRC. */
+ The RTL chips use a 64 element hash table based on the Ethernet CRC. */
static int multicast_filter_limit = 32;
-/* MAC address length*/
+/* MAC address length */
#define MAC_ADDR_LEN 6
-#define TX_FIFO_THRESH 256 /* In bytes */
-
-#define RX_FIFO_THRESH 7 /* 7 means NO threshold, Rx buffer level before first PCI xfer. */
+#define RX_FIFO_THRESH 7 /* 7 means NO threshold, Rx buffer level before first PCI xfer. */
#define RX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */
#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */
#define EarlyTxThld 0x3F /* 0x3F means NO early transmit */
@@ -149,6 +154,7 @@ enum phy_version {
RTL_GIGA_PHY_VER_E = 0x05, /* PHY Reg 0x03 bit0-3 == 0x0000 */
RTL_GIGA_PHY_VER_F = 0x06, /* PHY Reg 0x03 bit0-3 == 0x0001 */
RTL_GIGA_PHY_VER_G = 0x07, /* PHY Reg 0x03 bit0-3 == 0x0002 */
+ RTL_GIGA_PHY_VER_H = 0x08, /* PHY Reg 0x03 bit0-3 == 0x0003 */
};
@@ -162,7 +168,8 @@ const static struct {
} rtl_chip_info[] = {
_R("RTL8169", RTL_GIGA_MAC_VER_B, 0xff7e1880),
_R("RTL8169s/8110s", RTL_GIGA_MAC_VER_D, 0xff7e1880),
- _R("RTL8169s/8110s", RTL_GIGA_MAC_VER_E, 0xff7e1880)
+ _R("RTL8169s/8110s", RTL_GIGA_MAC_VER_E, 0xff7e1880),
+ _R("RTL8169s/8110s", RTL_GIGA_MAC_VER_X, 0xff7e1880),
};
#undef _R
@@ -208,6 +215,7 @@ enum RTL8169_registers {
PHYstatus = 0x6C,
RxMaxSize = 0xDA,
CPlusCmd = 0xE0,
+ IntrMitigate = 0xE2,
RxDescAddrLow = 0xE4,
RxDescAddrHigh = 0xE8,
EarlyTxThres = 0xEC,
@@ -218,7 +226,7 @@ enum RTL8169_registers {
};
enum RTL8169_register_content {
- /*InterruptStatusBits */
+ /* InterruptStatusBits */
SYSErr = 0x8000,
PCSTimeout = 0x4000,
SWInt = 0x0100,
@@ -231,23 +239,23 @@ enum RTL8169_register_content {
RxErr = 0x02,
RxOK = 0x01,
- /*RxStatusDesc */
+ /* RxStatusDesc */
RxRES = 0x00200000,
RxCRC = 0x00080000,
RxRUNT = 0x00100000,
RxRWT = 0x00400000,
- /*ChipCmdBits */
+ /* ChipCmdBits */
CmdReset = 0x10,
CmdRxEnb = 0x08,
CmdTxEnb = 0x04,
RxBufEmpty = 0x01,
- /*Cfg9346Bits */
+ /* Cfg9346Bits */
Cfg9346_Lock = 0x00,
Cfg9346_Unlock = 0xC0,
- /*rx_mode_bits */
+ /* rx_mode_bits */
AcceptErr = 0x20,
AcceptRunt = 0x10,
AcceptBroadcast = 0x08,
@@ -255,11 +263,11 @@ enum RTL8169_register_content {
AcceptMyPhys = 0x02,
AcceptAllPhys = 0x01,
- /*RxConfigBits */
+ /* RxConfigBits */
RxCfgFIFOShift = 13,
RxCfgDMAShift = 8,
- /*TxConfigBits */
+ /* TxConfigBits */
TxInterFrameGapShift = 24,
TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */
@@ -277,7 +285,7 @@ enum RTL8169_register_content {
PCIDAC = (1 << 4),
PCIMulRW = (1 << 3),
- /*rtl8169_PHYstatus */
+ /* rtl8169_PHYstatus */
TBI_Enable = 0x80,
TxFlowCtrl = 0x40,
RxFlowCtrl = 0x20,
@@ -287,38 +295,38 @@ enum RTL8169_register_content {
LinkStatus = 0x02,
FullDup = 0x01,
- /*GIGABIT_PHY_registers */
+ /* GIGABIT_PHY_registers */
PHY_CTRL_REG = 0,
PHY_STAT_REG = 1,
PHY_AUTO_NEGO_REG = 4,
PHY_1000_CTRL_REG = 9,
- /*GIGABIT_PHY_REG_BIT */
+ /* GIGABIT_PHY_REG_BIT */
PHY_Restart_Auto_Nego = 0x0200,
PHY_Enable_Auto_Nego = 0x1000,
- //PHY_STAT_REG = 1;
+ /* PHY_STAT_REG = 1 */
PHY_Auto_Neco_Comp = 0x0020,
- //PHY_AUTO_NEGO_REG = 4;
+ /* PHY_AUTO_NEGO_REG = 4 */
PHY_Cap_10_Half = 0x0020,
PHY_Cap_10_Full = 0x0040,
PHY_Cap_100_Half = 0x0080,
PHY_Cap_100_Full = 0x0100,
- //PHY_1000_CTRL_REG = 9;
+ /* PHY_1000_CTRL_REG = 9 */
PHY_Cap_1000_Full = 0x0200,
PHY_Cap_Null = 0x0,
- /*_MediaType*/
+ /* _MediaType */
_10_Half = 0x01,
_10_Full = 0x02,
_100_Half = 0x04,
_100_Full = 0x08,
_1000_Full = 0x10,
- /*_TBICSRBit*/
+ /* _TBICSRBit */
TBILinkOK = 0x02000000,
};
@@ -374,7 +382,7 @@ struct ring_info {
struct rtl8169_private {
void __iomem *mmio_addr; /* memory map physical address */
- struct pci_dev *pci_dev; /* Index of PCI device */
+ struct pci_dev *pci_dev; /* Index of PCI device */
struct net_device_stats stats; /* statistics of net device */
spinlock_t lock; /* spin lock flag */
int chipset;
@@ -407,7 +415,7 @@ struct rtl8169_private {
struct work_struct task;
};
-MODULE_AUTHOR("Realtek");
+MODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@oss.sgi.com>");
MODULE_DESCRIPTION("RealTek RTL-8169 Gigabit Ethernet driver");
module_param_array(media, int, &num_media, 0);
module_param(rx_copybreak, int, 0);
@@ -455,7 +463,7 @@ static void mdio_write(void __iomem *ioaddr, int RegAddr, int value)
udelay(1000);
for (i = 2000; i > 0; i--) {
- // Check if the RTL8169 has completed writing to the specified MII register
+ /* Check if the RTL8169 has completed writing to the specified MII register */
if (!(RTL_R32(PHYAR) & 0x80000000))
break;
udelay(100);
@@ -470,7 +478,7 @@ static int mdio_read(void __iomem *ioaddr, int RegAddr)
udelay(1000);
for (i = 2000; i > 0; i--) {
- // Check if the RTL8169 has completed retrieving data from the specified MII register
+ /* Check if the RTL8169 has completed retrieving data from the specified MII register */
if (RTL_R32(PHYAR) & 0x80000000) {
value = (int) (RTL_R32(PHYAR) & 0xFFFF);
break;
@@ -480,6 +488,20 @@ static int mdio_read(void __iomem *ioaddr, int RegAddr)
return value;
}
+static void rtl8169_irq_mask_and_ack(void __iomem *ioaddr)
+{
+ RTL_W16(IntrMask, 0x0000);
+
+ RTL_W16(IntrStatus, 0xffff);
+}
+
+static void rtl8169_asic_down(void __iomem *ioaddr)
+{
+ RTL_W8(ChipCmd, 0x00);
+ rtl8169_irq_mask_and_ack(ioaddr);
+ RTL_R16(CPlusCmd);
+}
+
static unsigned int rtl8169_tbi_reset_pending(void __iomem *ioaddr)
{
return RTL_R32(TBICSR) & TBIReset;
@@ -698,7 +720,7 @@ static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp,
struct sk_buff *skb)
{
return (tp->vlgrp && vlan_tx_tag_present(skb)) ?
- TxVlanTag | cpu_to_be16(vlan_tx_tag_get(skb)) : 0x00;
+ TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00;
}
static void rtl8169_vlan_rx_register(struct net_device *dev,
@@ -733,12 +755,12 @@ static void rtl8169_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc,
struct sk_buff *skb)
{
- u32 opts2 = desc->opts2;
+ u32 opts2 = le32_to_cpu(desc->opts2);
int ret;
if (tp->vlgrp && (opts2 & RxVlanTag)) {
rtl8169_rx_hwaccel_skb(skb, tp->vlgrp,
- be16_to_cpu(opts2 & 0xffff));
+ swab16(opts2 & 0xffff));
ret = 0;
} else
ret = -1;
@@ -1002,7 +1024,7 @@ static void rtl8169_hw_phy_config(struct net_device *dev)
if (tp->mac_version <= RTL_GIGA_MAC_VER_B)
return;
- if (tp->phy_version >= RTL_GIGA_PHY_VER_F)
+ if (tp->phy_version >= RTL_GIGA_PHY_VER_H)
return;
dprintk("MAC version != 0 && PHY version == 0 or 1\n");
@@ -1010,7 +1032,19 @@ static void rtl8169_hw_phy_config(struct net_device *dev)
/* Shazam ! */
- // phy config for RTL8169s mac_version C chip
+ if (tp->mac_version == RTL_GIGA_MAC_VER_X) {
+ mdio_write(ioaddr, 31, 0x0001);
+ mdio_write(ioaddr, 9, 0x273a);
+ mdio_write(ioaddr, 14, 0x7bfb);
+ mdio_write(ioaddr, 27, 0x841e);
+
+ mdio_write(ioaddr, 31, 0x0002);
+ mdio_write(ioaddr, 1, 0x90d0);
+ mdio_write(ioaddr, 31, 0x0000);
+ return;
+ }
+
+ /* phy config for RTL8169s mac_version C chip */
mdio_write(ioaddr, 31, 0x0001); //w 31 2 0 1
mdio_write(ioaddr, 21, 0x1000); //w 21 15 0 1000
mdio_write(ioaddr, 24, 0x65c7); //w 24 15 0 65c7
@@ -1038,7 +1072,7 @@ static void rtl8169_phy_timer(unsigned long __opaque)
unsigned long timeout = RTL8169_PHY_TIMEOUT;
assert(tp->mac_version > RTL_GIGA_MAC_VER_B);
- assert(tp->phy_version < RTL_GIGA_PHY_VER_G);
+ assert(tp->phy_version < RTL_GIGA_PHY_VER_H);
if (!(tp->phy_1000_ctrl_reg & PHY_Cap_1000_Full))
return;
@@ -1073,7 +1107,7 @@ static inline void rtl8169_delete_timer(struct net_device *dev)
struct timer_list *timer = &tp->timer;
if ((tp->mac_version <= RTL_GIGA_MAC_VER_B) ||
- (tp->phy_version >= RTL_GIGA_PHY_VER_G))
+ (tp->phy_version >= RTL_GIGA_PHY_VER_H))
return;
del_timer_sync(timer);
@@ -1085,7 +1119,7 @@ static inline void rtl8169_request_timer(struct net_device *dev)
struct timer_list *timer = &tp->timer;
if ((tp->mac_version <= RTL_GIGA_MAC_VER_B) ||
- (tp->phy_version >= RTL_GIGA_PHY_VER_G))
+ (tp->phy_version >= RTL_GIGA_PHY_VER_H))
return;
init_timer(timer);
@@ -1132,7 +1166,7 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out,
assert(ioaddr_out != NULL);
- // dev zeroed in alloc_etherdev
+ /* dev zeroed in alloc_etherdev */
dev = alloc_etherdev(sizeof (*tp));
if (dev == NULL) {
printk(KERN_ERR PFX "unable to alloc new ethernet\n");
@@ -1143,10 +1177,10 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out,
SET_NETDEV_DEV(dev, &pdev->dev);
tp = netdev_priv(dev);
- // enable device (incl. PCI PM wakeup and hotplug setup)
+ /* enable device (incl. PCI PM wakeup and hotplug setup) */
rc = pci_enable_device(pdev);
if (rc) {
- printk(KERN_ERR PFX "%s: enable failure\n", pdev->slot_name);
+ printk(KERN_ERR PFX "%s: enable failure\n", pci_name(pdev));
goto err_out_free_dev;
}
@@ -1167,14 +1201,14 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out,
goto err_out_mwi;
}
- // make sure PCI base addr 1 is MMIO
+ /* make sure PCI base addr 1 is MMIO */
if (!(pci_resource_flags(pdev, 1) & IORESOURCE_MEM)) {
printk(KERN_ERR PFX
"region #1 not an MMIO resource, aborting\n");
rc = -ENODEV;
goto err_out_mwi;
}
- // check for weird/broken PCI region reporting
+ /* check for weird/broken PCI region reporting */
if (pci_resource_len(pdev, 1) < R8169_REGS_SIZE) {
printk(KERN_ERR PFX "Invalid PCI region size(s), aborting\n");
rc = -ENODEV;
@@ -1184,7 +1218,7 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out,
rc = pci_request_regions(pdev, MODULENAME);
if (rc) {
printk(KERN_ERR PFX "%s: could not request regions.\n",
- pdev->slot_name);
+ pci_name(pdev));
goto err_out_mwi;
}
@@ -1204,7 +1238,7 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out,
pci_set_master(pdev);
- // ioremap MMIO region
+ /* ioremap MMIO region */
ioaddr = ioremap(pci_resource_start(pdev, 1), R8169_REGS_SIZE);
if (ioaddr == NULL) {
printk(KERN_ERR PFX "cannot remap MMIO, aborting\n");
@@ -1212,17 +1246,20 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out,
goto err_out_free_res;
}
- // Soft reset the chip.
+ /* Unneeded ? Don't mess with Mrs. Murphy. */
+ rtl8169_irq_mask_and_ack(ioaddr);
+
+ /* Soft reset the chip. */
RTL_W8(ChipCmd, CmdReset);
- // Check that the chip has finished the reset.
+ /* Check that the chip has finished the reset. */
for (i = 1000; i > 0; i--) {
if ((RTL_R8(ChipCmd) & CmdReset) == 0)
break;
udelay(10);
}
- // Identify chip attached to board
+ /* Identify chip attached to board */
rtl8169_get_mac_version(tp, ioaddr);
rtl8169_get_phy_version(tp, ioaddr);
@@ -1310,7 +1347,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
tp->link_ok = rtl8169_xmii_link_ok;
}
- // Get MAC address. FIXME: read EEPROM
+ /* Get MAC address. FIXME: read EEPROM */
for (i = 0; i < MAC_ADDR_LEN; i++)
dev->dev_addr[i] = RTL_R8(MAC0 + i);
@@ -1518,7 +1555,7 @@ err_free_irq:
static void rtl8169_hw_reset(void __iomem *ioaddr)
{
/* Disable interrupts */
- RTL_W16(IntrMask, 0x0000);
+ rtl8169_irq_mask_and_ack(ioaddr);
/* Reset the chipset */
RTL_W8(ChipCmd, CmdReset);
@@ -1548,10 +1585,10 @@ rtl8169_hw_start(struct net_device *dev)
RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
RTL_W8(EarlyTxThres, EarlyTxThld);
- // For gigabit rtl8169, MTU + header + CRC + VLAN
+ /* For gigabit rtl8169, MTU + header + CRC + VLAN */
RTL_W16(RxMaxSize, tp->rx_buf_sz);
- // Set Rx Config register
+ /* Set Rx Config register */
i = rtl8169_rx_config |
(RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask);
RTL_W32(RxConfig, i);
@@ -1563,13 +1600,20 @@ rtl8169_hw_start(struct net_device *dev)
tp->cp_cmd |= RTL_R16(CPlusCmd);
RTL_W16(CPlusCmd, tp->cp_cmd);
- if (tp->mac_version == RTL_GIGA_MAC_VER_D) {
+ if ((tp->mac_version == RTL_GIGA_MAC_VER_D) ||
+ (tp->mac_version == RTL_GIGA_MAC_VER_E)) {
dprintk(KERN_INFO PFX "Set MAC Reg C+CR Offset 0xE0. "
"Bit-3 and bit-14 MUST be 1\n");
tp->cp_cmd |= (1 << 14) | PCIMulRW;
RTL_W16(CPlusCmd, tp->cp_cmd);
}
+ /*
+ * Undocumented corner. Supposedly:
+ * (TxTimer << 12) | (TxPackets << 8) | (RxTimer << 4) | RxPackets
+ */
+ RTL_W16(IntrMitigate, 0x0000);
+
RTL_W32(TxDescStartAddrLow, ((u64) tp->TxPhyAddr & DMA_32BIT_MASK));
RTL_W32(TxDescStartAddrHigh, ((u64) tp->TxPhyAddr >> 32));
RTL_W32(RxDescAddrLow, ((u64) tp->RxPhyAddr & DMA_32BIT_MASK));
@@ -1611,10 +1655,10 @@ static int rtl8169_change_mtu(struct net_device *dev, int new_mtu)
if (ret < 0)
goto out;
- rtl8169_hw_start(dev);
-
netif_poll_enable(dev);
+ rtl8169_hw_start(dev);
+
rtl8169_request_timer(dev);
out:
@@ -1639,16 +1683,19 @@ static void rtl8169_free_rx_skb(struct rtl8169_private *tp,
rtl8169_make_unusable_by_asic(desc);
}
-static inline void rtl8169_return_to_asic(struct RxDesc *desc, int rx_buf_sz)
+static inline void rtl8169_mark_to_asic(struct RxDesc *desc, u32 rx_buf_sz)
{
- desc->opts1 |= cpu_to_le32(DescOwn + rx_buf_sz);
+ u32 eor = le32_to_cpu(desc->opts1) & RingEnd;
+
+ desc->opts1 = cpu_to_le32(DescOwn | eor | rx_buf_sz);
}
-static inline void rtl8169_give_to_asic(struct RxDesc *desc, dma_addr_t mapping,
- int rx_buf_sz)
+static inline void rtl8169_map_to_asic(struct RxDesc *desc, dma_addr_t mapping,
+ u32 rx_buf_sz)
{
desc->addr = cpu_to_le64(mapping);
- desc->opts1 |= cpu_to_le32(DescOwn + rx_buf_sz);
+ wmb();
+ rtl8169_mark_to_asic(desc, rx_buf_sz);
}
static int rtl8169_alloc_rx_skb(struct pci_dev *pdev, struct sk_buff **sk_buff,
@@ -1658,17 +1705,17 @@ static int rtl8169_alloc_rx_skb(struct pci_dev *pdev, struct sk_buff **sk_buff,
dma_addr_t mapping;
int ret = 0;
- skb = dev_alloc_skb(rx_buf_sz);
+ skb = dev_alloc_skb(rx_buf_sz + NET_IP_ALIGN);
if (!skb)
goto err_out;
- skb_reserve(skb, 2);
+ skb_reserve(skb, NET_IP_ALIGN);
*sk_buff = skb;
mapping = pci_map_single(pdev, skb->tail, rx_buf_sz,
PCI_DMA_FROMDEVICE);
- rtl8169_give_to_asic(desc, mapping, rx_buf_sz);
+ rtl8169_map_to_asic(desc, mapping, rx_buf_sz);
out:
return ret;
@@ -1795,9 +1842,7 @@ static void rtl8169_wait_for_quiescence(struct net_device *dev)
/* Wait for any pending NAPI task to complete */
netif_poll_disable(dev);
- RTL_W16(IntrMask, 0x0000);
-
- RTL_W16(IntrStatus, 0xffff);
+ rtl8169_irq_mask_and_ack(ioaddr);
netif_poll_enable(dev);
}
@@ -1974,7 +2019,7 @@ static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev)
smp_wmb();
- RTL_W8(TxPoll, 0x40); //set polling bit
+ RTL_W8(TxPoll, 0x40); /* set polling bit */
if (TX_BUFFS_AVAIL(tp) < MAX_SKB_FRAGS) {
netif_stop_queue(dev);
@@ -2084,7 +2129,7 @@ rtl8169_tx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
static inline void rtl8169_rx_csum(struct sk_buff *skb, struct RxDesc *desc)
{
- u32 opts1 = desc->opts1;
+ u32 opts1 = le32_to_cpu(desc->opts1);
u32 status = opts1 & RxProtoMask;
if (((status == RxProtoTCP) && !(opts1 & TCPFail)) ||
@@ -2103,12 +2148,12 @@ static inline int rtl8169_try_rx_copy(struct sk_buff **sk_buff, int pkt_size,
if (pkt_size < rx_copybreak) {
struct sk_buff *skb;
- skb = dev_alloc_skb(pkt_size + 2);
+ skb = dev_alloc_skb(pkt_size + NET_IP_ALIGN);
if (skb) {
- skb_reserve(skb, 2);
+ skb_reserve(skb, NET_IP_ALIGN);
eth_copy_and_sum(skb, sk_buff[0]->tail, pkt_size, 0);
*sk_buff = skb;
- rtl8169_return_to_asic(desc, rx_buf_sz);
+ rtl8169_mark_to_asic(desc, rx_buf_sz);
ret = 0;
}
}
@@ -2119,8 +2164,8 @@ static int
rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
void __iomem *ioaddr)
{
- unsigned int cur_rx, rx_left, count;
- int delta;
+ unsigned int cur_rx, rx_left;
+ unsigned int delta, count;
assert(dev != NULL);
assert(tp != NULL);
@@ -2188,10 +2233,8 @@ rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
tp->cur_rx = cur_rx;
delta = rtl8169_rx_fill(tp, dev, tp->dirty_rx, tp->cur_rx);
- if (delta < 0) {
+ if (!delta && count)
printk(KERN_INFO "%s: no Rx buffer allocated\n", dev->name);
- delta = 0;
- }
tp->dirty_rx += delta;
/*
@@ -2215,12 +2258,9 @@ rtl8169_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
struct rtl8169_private *tp = netdev_priv(dev);
int boguscnt = max_interrupt_work;
void __iomem *ioaddr = tp->mmio_addr;
- int status = 0;
+ int status;
int handled = 0;
- if (unlikely(!netif_running(dev)))
- goto out;
-
do {
status = RTL_R16(IntrStatus);
@@ -2230,6 +2270,11 @@ rtl8169_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
handled = 1;
+ if (unlikely(!netif_running(dev))) {
+ rtl8169_asic_down(ioaddr);
+ goto out;
+ }
+
status &= tp->intr_mask;
RTL_W16(IntrStatus,
(status & RxFIFOOver) ? (status | RxOverflow) : status);
@@ -2257,11 +2302,11 @@ rtl8169_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
}
break;
#else
- // Rx interrupt
+ /* Rx interrupt */
if (status & (RxOK | RxOverflow | RxFIFOOver)) {
rtl8169_rx_interrupt(dev, tp, ioaddr);
}
- // Tx interrupt
+ /* Tx interrupt */
if (status & (TxOK | TxErr))
rtl8169_tx_interrupt(dev, tp, ioaddr);
#endif
@@ -2292,7 +2337,7 @@ static int rtl8169_poll(struct net_device *dev, int *budget)
*budget -= work_done;
dev->quota -= work_done;
- if ((work_done < work_to_do) || !netif_running(dev)) {
+ if (work_done < work_to_do) {
netif_rx_complete(dev);
tp->intr_mask = 0xffff;
/*
@@ -2313,6 +2358,7 @@ static void rtl8169_down(struct net_device *dev)
{
struct rtl8169_private *tp = netdev_priv(dev);
void __iomem *ioaddr = tp->mmio_addr;
+ unsigned int poll_locked = 0;
rtl8169_delete_timer(dev);
@@ -2320,13 +2366,10 @@ static void rtl8169_down(struct net_device *dev)
flush_scheduled_work();
+core_down:
spin_lock_irq(&tp->lock);
- /* Stop the chip's Tx and Rx DMA processes. */
- RTL_W8(ChipCmd, 0x00);
-
- /* Disable interrupts by clearing the interrupt mask. */
- RTL_W16(IntrMask, 0x0000);
+ rtl8169_asic_down(ioaddr);
/* Update the error counts. */
tp->stats.rx_missed_errors += RTL_R32(RxMissed);
@@ -2336,11 +2379,27 @@ static void rtl8169_down(struct net_device *dev)
synchronize_irq(dev->irq);
- netif_poll_disable(dev);
+ if (!poll_locked) {
+ netif_poll_disable(dev);
+ poll_locked++;
+ }
/* Give a racing hard_start_xmit a few cycles to complete. */
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
+ synchronize_kernel();
+
+ /*
+ * And now for the 50k$ question: are IRQ disabled or not ?
+ *
+ * Two paths lead here:
+ * 1) dev->close
+ * -> netif_running() is available to sync the current code and the
+ * IRQ handler. See rtl8169_interrupt for details.
+ * 2) dev->change_mtu
+ * -> rtl8169_poll can not be issued again and re-enable the
+ * interruptions. Let's simply issue the IRQ down sequence again.
+ */
+ if (RTL_R16(IntrMask))
+ goto core_down;
rtl8169_tx_clear(tp);
@@ -2356,6 +2415,8 @@ static int rtl8169_close(struct net_device *dev)
free_irq(dev->irq, dev);
+ netif_poll_enable(dev);
+
pci_free_consistent(pdev, R8169_RX_RING_BYTES, tp->RxDescArray,
tp->RxPhyAddr);
pci_free_consistent(pdev, R8169_TX_RING_BYTES, tp->TxDescArray,
diff --git a/drivers/net/rrunner.c b/drivers/net/rrunner.c
index 4108b287bb62a..12a86f96d973d 100644
--- a/drivers/net/rrunner.c
+++ b/drivers/net/rrunner.c
@@ -62,7 +62,7 @@ MODULE_AUTHOR("Jes Sorensen <jes@wildopensource.com>");
MODULE_DESCRIPTION("Essential RoadRunner HIPPI driver");
MODULE_LICENSE("GPL");
-static char version[] __initdata = "rrunner.c: v0.50 11/11/2002 Jes Sorensen (jes@wildopensource.com)\n";
+static char version[] __devinitdata = "rrunner.c: v0.50 11/11/2002 Jes Sorensen (jes@wildopensource.com)\n";
/*
* Implementation notes:
diff --git a/drivers/net/s2io-regs.h b/drivers/net/s2io-regs.h
index aaa5f584c86f7..7092ca6b277e3 100644
--- a/drivers/net/s2io-regs.h
+++ b/drivers/net/s2io-regs.h
@@ -1,6 +1,6 @@
/************************************************************************
* regs.h: A Linux PCI-X Ethernet driver for S2IO 10GbE Server NIC
- * Copyright 2002 Raghavendra Koushik (raghavendra.koushik@s2io.com)
+ * Copyright(c) 2002-2005 Neterion Inc.
* This software may be used and distributed according to the terms of
* the GNU General Public License (GPL), incorporated herein by reference.
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index 001a56254efc1..9c224eba057d5 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -1,6 +1,6 @@
/************************************************************************
* s2io.c: A Linux PCI-X Ethernet driver for S2IO 10GbE Server NIC
- * Copyright(c) 2002-2005 S2IO Technologies
+ * Copyright(c) 2002-2005 Neterion Inc.
* This software may be used and distributed according to the terms of
* the GNU General Public License (GPL), incorporated herein by reference.
@@ -36,28 +36,29 @@
* in PCI Configuration space.
************************************************************************/
-#include<linux/config.h>
-#include<linux/module.h>
-#include<linux/types.h>
-#include<linux/errno.h>
-#include<linux/ioport.h>
-#include<linux/pci.h>
-#include<linux/kernel.h>
-#include<linux/netdevice.h>
-#include<linux/etherdevice.h>
-#include<linux/skbuff.h>
-#include<linux/init.h>
-#include<linux/delay.h>
-#include<linux/stddef.h>
-#include<linux/ioctl.h>
-#include<linux/timex.h>
-#include<linux/sched.h>
-#include<linux/ethtool.h>
-#include<asm/system.h>
-#include<asm/uaccess.h>
-#include<linux/version.h>
-#include<asm/io.h>
-#include<linux/workqueue.h>
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/stddef.h>
+#include <linux/ioctl.h>
+#include <linux/timex.h>
+#include <linux/sched.h>
+#include <linux/ethtool.h>
+#include <linux/version.h>
+#include <linux/workqueue.h>
+
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
/* local include */
#include "s2io.h"
@@ -65,7 +66,7 @@
/* S2io Driver name & version. */
static char s2io_driver_name[] = "s2io";
-static char s2io_driver_version[] = "Version 1.7.5.1";
+static char s2io_driver_version[] = "Version 1.7.7.1";
/*
* Cards with following subsystem_id have a link state indication
@@ -244,6 +245,10 @@ static struct pci_device_id s2io_tbl[] __devinitdata = {
PCI_ANY_ID, PCI_ANY_ID},
{PCI_VENDOR_ID_S2IO, PCI_DEVICE_ID_S2IO_UNI,
PCI_ANY_ID, PCI_ANY_ID},
+ {PCI_VENDOR_ID_S2IO, PCI_DEVICE_ID_HERC_WIN,
+ PCI_ANY_ID, PCI_ANY_ID},
+ {PCI_VENDOR_ID_S2IO, PCI_DEVICE_ID_HERC_UNI,
+ PCI_ANY_ID, PCI_ANY_ID},
{0,}
};
@@ -619,87 +624,22 @@ static int init_nic(struct s2io_nic *nic)
mac_info_t *mac_control;
struct config_param *config;
int mdio_cnt = 0, dtx_cnt = 0;
- unsigned long long print_var, mem_share;
+ unsigned long long mem_share;
mac_control = &nic->mac_control;
config = &nic->config;
- /*
- * Set proper endian settings and verify the same by
- * reading the PIF Feed-back register.
- */
-#ifdef __BIG_ENDIAN
- /*
- * The device by default set to a big endian format, so
- * a big endian driver need not set anything.
- */
- writeq(0xffffffffffffffffULL, &bar0->swapper_ctrl);
- val64 = (SWAPPER_CTRL_PIF_R_FE |
- SWAPPER_CTRL_PIF_R_SE |
- SWAPPER_CTRL_PIF_W_FE |
- SWAPPER_CTRL_PIF_W_SE |
- SWAPPER_CTRL_TXP_FE |
- SWAPPER_CTRL_TXP_SE |
- SWAPPER_CTRL_TXD_R_FE |
- SWAPPER_CTRL_TXD_W_FE |
- SWAPPER_CTRL_TXF_R_FE |
- SWAPPER_CTRL_RXD_R_FE |
- SWAPPER_CTRL_RXD_W_FE |
- SWAPPER_CTRL_RXF_W_FE |
- SWAPPER_CTRL_XMSI_FE |
- SWAPPER_CTRL_XMSI_SE |
- SWAPPER_CTRL_STATS_FE | SWAPPER_CTRL_STATS_SE);
- writeq(val64, &bar0->swapper_ctrl);
-#else
- /*
- * Initially we enable all bits to make it accessible by
- * the driver, then we selectively enable only those bits
- * that we want to set.
- */
- writeq(0xffffffffffffffffULL, &bar0->swapper_ctrl);
- val64 = (SWAPPER_CTRL_PIF_R_FE |
- SWAPPER_CTRL_PIF_R_SE |
- SWAPPER_CTRL_PIF_W_FE |
- SWAPPER_CTRL_PIF_W_SE |
- SWAPPER_CTRL_TXP_FE |
- SWAPPER_CTRL_TXP_SE |
- SWAPPER_CTRL_TXD_R_FE |
- SWAPPER_CTRL_TXD_R_SE |
- SWAPPER_CTRL_TXD_W_FE |
- SWAPPER_CTRL_TXD_W_SE |
- SWAPPER_CTRL_TXF_R_FE |
- SWAPPER_CTRL_RXD_R_FE |
- SWAPPER_CTRL_RXD_R_SE |
- SWAPPER_CTRL_RXD_W_FE |
- SWAPPER_CTRL_RXD_W_SE |
- SWAPPER_CTRL_RXF_W_FE |
- SWAPPER_CTRL_XMSI_FE |
- SWAPPER_CTRL_XMSI_SE |
- SWAPPER_CTRL_STATS_FE | SWAPPER_CTRL_STATS_SE);
- writeq(val64, &bar0->swapper_ctrl);
-#endif
-
- /*
- * Verifying if endian settings are accurate by
- * reading a feedback register.
- */
- val64 = readq(&bar0->pif_rd_swapper_fb);
- if (val64 != 0x0123456789ABCDEFULL) {
- /* Endian settings are incorrect, calls for another dekko. */
- print_var = (unsigned long long) val64;
- DBG_PRINT(INIT_DBG, "%s: Endian settings are wrong",
- dev->name);
- DBG_PRINT(ERR_DBG, ", feedback read %llx\n", print_var);
-
- return FAILURE;
+ /* Initialize swapper control register */
+ if (s2io_set_swapper(nic)) {
+ DBG_PRINT(ERR_DBG,"ERROR: Setting Swapper failed\n");
+ return -1;
}
/* Remove XGXS from reset state */
val64 = 0;
writeq(val64, &bar0->sw_reset);
val64 = readq(&bar0->sw_reset);
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(HZ / 2);
+ msleep(500);
/* Enable Receiving broadcasts */
add = &bar0->mac_cfg;
@@ -920,11 +860,15 @@ static int init_nic(struct s2io_nic *nic)
* Initializing the Transmit and Receive Traffic Interrupt
* Scheme.
*/
- /* TTI Initialization */
- val64 = TTI_DATA1_MEM_TX_TIMER_VAL(0xFFF) |
+ /* TTI Initialization. Default Tx timer gets us about
+ * 250 interrupts per sec. Continuous interrupts are enabled
+ * by default.
+ */
+ val64 = TTI_DATA1_MEM_TX_TIMER_VAL(0x2078) |
TTI_DATA1_MEM_TX_URNG_A(0xA) |
TTI_DATA1_MEM_TX_URNG_B(0x10) |
- TTI_DATA1_MEM_TX_URNG_C(0x30) | TTI_DATA1_MEM_TX_TIMER_AC_EN;
+ TTI_DATA1_MEM_TX_URNG_C(0x30) | TTI_DATA1_MEM_TX_TIMER_AC_EN |
+ TTI_DATA1_MEM_TX_TIMER_CI_EN;
writeq(val64, &bar0->tti_data1_mem);
val64 = TTI_DATA2_MEM_TX_UFC_A(0x10) |
@@ -952,8 +896,7 @@ static int init_nic(struct s2io_nic *nic)
dev->name);
return -1;
}
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(HZ / 20);
+ msleep(50);
time++;
}
@@ -991,8 +934,7 @@ static int init_nic(struct s2io_nic *nic)
return -1;
}
time++;
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(HZ / 20);
+ msleep(50);
}
/*
@@ -1352,7 +1294,7 @@ static int verify_xena_quiescence(u64 val64, int flag)
*
*/
-void fix_mac_address(nic_t * sp)
+static void fix_mac_address(nic_t * sp)
{
XENA_dev_config_t __iomem *bar0 = sp->bar0;
u64 val64;
@@ -1421,8 +1363,7 @@ static int start_nic(struct s2io_nic *nic)
SPECIAL_REG_WRITE(val64, &bar0->mc_rldram_mrs, UF);
val64 = readq(&bar0->mc_rldram_mrs);
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(HZ / 10); /* Delay by around 100 ms. */
+ msleep(100); /* Delay by around 100 ms. */
/* Enabling ECC Protection. */
val64 = readq(&bar0->adapter_control);
@@ -1509,7 +1450,7 @@ static int start_nic(struct s2io_nic *nic)
* Return Value: void
*/
-void free_tx_buffers(struct s2io_nic *nic)
+static void free_tx_buffers(struct s2io_nic *nic)
{
struct net_device *dev = nic->dev;
struct sk_buff *skb;
@@ -1600,7 +1541,7 @@ static void stop_nic(struct s2io_nic *nic)
* SUCCESS on success or an appropriate -ve value on failure.
*/
-int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
+static int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
{
struct net_device *dev = nic->dev;
struct sk_buff *skb;
@@ -2425,7 +2366,7 @@ static void alarm_intr_handler(struct s2io_nic *nic)
* SUCCESS on success and FAILURE on failure.
*/
-int wait_for_cmd_complete(nic_t * sp)
+static int wait_for_cmd_complete(nic_t * sp)
{
XENA_dev_config_t __iomem *bar0 = sp->bar0;
int ret = FAILURE, cnt = 0;
@@ -2437,8 +2378,7 @@ int wait_for_cmd_complete(nic_t * sp)
ret = SUCCESS;
break;
}
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(HZ / 20);
+ msleep(50);
if (cnt++ > 10)
break;
}
@@ -2456,7 +2396,7 @@ int wait_for_cmd_complete(nic_t * sp)
* void.
*/
-void s2io_reset(nic_t * sp)
+static void s2io_reset(nic_t * sp)
{
XENA_dev_config_t __iomem *bar0 = sp->bar0;
u64 val64;
@@ -2477,15 +2417,13 @@ void s2io_reset(nic_t * sp)
* As of now I'am just giving a 250ms delay and hoping that the
* PCI write to sw_reset register is done by this time.
*/
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(HZ / 4);
+ msleep(250);
/* Restore the PCI state saved during initializarion. */
pci_restore_state(sp->pdev);
s2io_init_pci(sp);
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(HZ / 4);
+ msleep(250);
/* SXE-002: Configure link and activity LED to turn it off */
subid = sp->pdev->subsystem_device;
@@ -2510,27 +2448,78 @@ void s2io_reset(nic_t * sp)
* SUCCESS on success and FAILURE on failure.
*/
-int s2io_set_swapper(nic_t * sp)
+static int s2io_set_swapper(nic_t * sp)
{
struct net_device *dev = sp->dev;
XENA_dev_config_t __iomem *bar0 = sp->bar0;
- u64 val64;
+ u64 val64, valt, valr;
/*
* Set proper endian settings and verify the same by reading
* the PIF Feed-back register.
*/
+
+ val64 = readq(&bar0->pif_rd_swapper_fb);
+ if (val64 != 0x0123456789ABCDEFULL) {
+ int i = 0;
+ u64 value[] = { 0xC30000C3C30000C3ULL, /* FE=1, SE=1 */
+ 0x8100008181000081ULL, /* FE=1, SE=0 */
+ 0x4200004242000042ULL, /* FE=0, SE=1 */
+ 0}; /* FE=0, SE=0 */
+
+ while(i<4) {
+ writeq(value[i], &bar0->swapper_ctrl);
+ val64 = readq(&bar0->pif_rd_swapper_fb);
+ if (val64 == 0x0123456789ABCDEFULL)
+ break;
+ i++;
+ }
+ if (i == 4) {
+ DBG_PRINT(ERR_DBG, "%s: Endian settings are wrong, ",
+ dev->name);
+ DBG_PRINT(ERR_DBG, "feedback read %llx\n",
+ (unsigned long long) val64);
+ return FAILURE;
+ }
+ valr = value[i];
+ } else {
+ valr = readq(&bar0->swapper_ctrl);
+ }
+
+ valt = 0x0123456789ABCDEFULL;
+ writeq(valt, &bar0->xmsi_address);
+ val64 = readq(&bar0->xmsi_address);
+
+ if(val64 != valt) {
+ int i = 0;
+ u64 value[] = { 0x00C3C30000C3C300ULL, /* FE=1, SE=1 */
+ 0x0081810000818100ULL, /* FE=1, SE=0 */
+ 0x0042420000424200ULL, /* FE=0, SE=1 */
+ 0}; /* FE=0, SE=0 */
+
+ while(i<4) {
+ writeq((value[i] | valr), &bar0->swapper_ctrl);
+ writeq(valt, &bar0->xmsi_address);
+ val64 = readq(&bar0->xmsi_address);
+ if(val64 == valt)
+ break;
+ i++;
+ }
+ if(i == 4) {
+ DBG_PRINT(ERR_DBG, "Write failed, Xmsi_addr ");
+ DBG_PRINT(ERR_DBG, "reads:0x%llx\n",val64);
+ return FAILURE;
+ }
+ }
+ val64 = readq(&bar0->swapper_ctrl);
+ val64 &= 0xFFFF000000000000ULL;
+
#ifdef __BIG_ENDIAN
/*
* The device by default set to a big endian format, so a
* big endian driver need not set anything.
*/
- writeq(0xffffffffffffffffULL, &bar0->swapper_ctrl);
- val64 = (SWAPPER_CTRL_PIF_R_FE |
- SWAPPER_CTRL_PIF_R_SE |
- SWAPPER_CTRL_PIF_W_FE |
- SWAPPER_CTRL_PIF_W_SE |
- SWAPPER_CTRL_TXP_FE |
+ val64 |= (SWAPPER_CTRL_TXP_FE |
SWAPPER_CTRL_TXP_SE |
SWAPPER_CTRL_TXD_R_FE |
SWAPPER_CTRL_TXD_W_FE |
@@ -2548,12 +2537,7 @@ int s2io_set_swapper(nic_t * sp)
* driver, then we selectively enable only those bits that
* we want to set.
*/
- writeq(0xffffffffffffffffULL, &bar0->swapper_ctrl);
- val64 = (SWAPPER_CTRL_PIF_R_FE |
- SWAPPER_CTRL_PIF_R_SE |
- SWAPPER_CTRL_PIF_W_FE |
- SWAPPER_CTRL_PIF_W_SE |
- SWAPPER_CTRL_TXP_FE |
+ val64 |= (SWAPPER_CTRL_TXP_FE |
SWAPPER_CTRL_TXP_SE |
SWAPPER_CTRL_TXD_R_FE |
SWAPPER_CTRL_TXD_R_SE |
@@ -2570,6 +2554,7 @@ int s2io_set_swapper(nic_t * sp)
SWAPPER_CTRL_STATS_FE | SWAPPER_CTRL_STATS_SE);
writeq(val64, &bar0->swapper_ctrl);
#endif
+ val64 = readq(&bar0->swapper_ctrl);
/*
* Verifying if endian settings are accurate by reading a
@@ -2604,7 +2589,7 @@ int s2io_set_swapper(nic_t * sp)
* file on failure.
*/
-int s2io_open(struct net_device *dev)
+static int s2io_open(struct net_device *dev)
{
nic_t *sp = dev->priv;
int err = 0;
@@ -2656,7 +2641,7 @@ int s2io_open(struct net_device *dev)
* file on failure.
*/
-int s2io_close(struct net_device *dev)
+static int s2io_close(struct net_device *dev)
{
nic_t *sp = dev->priv;
@@ -2683,7 +2668,7 @@ int s2io_close(struct net_device *dev)
* 0 on success & 1 on failure.
*/
-int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
+static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
{
nic_t *sp = dev->priv;
u16 frg_cnt, frg_len, i, queue, queue_len, put_off, get_off;
@@ -2903,7 +2888,7 @@ static irqreturn_t s2io_isr(int irq, void *dev_id, struct pt_regs *regs)
* pointer to the updated net_device_stats structure.
*/
-struct net_device_stats *s2io_get_stats(struct net_device *dev)
+static struct net_device_stats *s2io_get_stats(struct net_device *dev)
{
nic_t *sp = dev->priv;
mac_info_t *mac_control;
@@ -3156,7 +3141,7 @@ static int s2io_ethtool_sset(struct net_device *dev,
* return 0 on success.
*/
-int s2io_ethtool_gset(struct net_device *dev, struct ethtool_cmd *info)
+static int s2io_ethtool_gset(struct net_device *dev, struct ethtool_cmd *info)
{
nic_t *sp = dev->priv;
info->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE);
@@ -3197,7 +3182,7 @@ static void s2io_ethtool_gdrvinfo(struct net_device *dev,
strncpy(info->version, s2io_driver_version,
sizeof(s2io_driver_version));
strncpy(info->fw_version, "", 32);
- strncpy(info->bus_info, sp->pdev->slot_name, 32);
+ strncpy(info->bus_info, pci_name(sp->pdev), 32);
info->regdump_len = XENA_REG_SPACE;
info->eedump_len = XENA_EEPROM_SPACE;
info->testinfo_len = S2IO_TEST_LEN;
@@ -3303,11 +3288,10 @@ static int s2io_ethtool_idnic(struct net_device *dev, u32 data)
sp->id_timer.data = (unsigned long) sp;
}
mod_timer(&sp->id_timer, jiffies);
- set_current_state(TASK_INTERRUPTIBLE);
if (data)
- schedule_timeout(data * HZ);
+ msleep(data * 1000);
else
- schedule_timeout(MAX_SCHEDULE_TIMEOUT);
+ msleep(0xFFFFFFFF);
del_timer_sync(&sp->id_timer);
if (CARDS_WITH_FAULTY_LINK_INDICATORS(subid)) {
@@ -3354,8 +3338,8 @@ static void s2io_ethtool_getpause_data(struct net_device *dev,
* int, returns 0 on Success
*/
-int s2io_ethtool_setpause_data(struct net_device *dev,
- struct ethtool_pauseparam *ep)
+static int s2io_ethtool_setpause_data(struct net_device *dev,
+ struct ethtool_pauseparam *ep)
{
u64 val64;
nic_t *sp = dev->priv;
@@ -3410,8 +3394,7 @@ static int read_eeprom(nic_t * sp, int off, u32 * data)
ret = 0;
break;
}
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(HZ / 20);
+ msleep(50);
exit_cnt++;
}
@@ -3451,8 +3434,7 @@ static int write_eeprom(nic_t * sp, int off, u32 data, int cnt)
ret = 0;
break;
}
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(HZ / 20);
+ msleep(50);
exit_cnt++;
}
@@ -3472,8 +3454,8 @@ static int write_eeprom(nic_t * sp, int off, u32 data, int cnt)
* int 0 on success
*/
-int s2io_ethtool_geeprom(struct net_device *dev,
- struct ethtool_eeprom *eeprom, u8 * data_buf)
+static int s2io_ethtool_geeprom(struct net_device *dev,
+ struct ethtool_eeprom *eeprom, u8 * data_buf)
{
u32 data, i, valid;
nic_t *sp = dev->priv;
@@ -3708,8 +3690,7 @@ static int s2io_bist_test(nic_t * sp, uint64_t * data)
ret = 0;
break;
}
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(HZ / 10);
+ msleep(100);
cnt++;
}
@@ -3810,8 +3791,7 @@ static int s2io_rldram_test(nic_t * sp, uint64_t * data)
val64 = readq(&bar0->mc_rldram_test_ctrl);
if (val64 & MC_RLDRAM_TEST_DONE)
break;
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(HZ / 5);
+ msleep(200);
}
if (cnt == 5)
@@ -3827,8 +3807,7 @@ static int s2io_rldram_test(nic_t * sp, uint64_t * data)
val64 = readq(&bar0->mc_rldram_test_ctrl);
if (val64 & MC_RLDRAM_TEST_DONE)
break;
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(HZ / 2);
+ msleep(500);
}
if (cnt == 5)
@@ -3932,60 +3911,61 @@ static void s2io_get_ethtool_stats(struct net_device *dev,
nic_t *sp = dev->priv;
StatInfo_t *stat_info = sp->mac_control.stats_info;
- tmp_stats[i++] = stat_info->tmac_frms;
- tmp_stats[i++] = stat_info->tmac_data_octets;
- tmp_stats[i++] = stat_info->tmac_drop_frms;
- tmp_stats[i++] = stat_info->tmac_mcst_frms;
- tmp_stats[i++] = stat_info->tmac_bcst_frms;
- tmp_stats[i++] = stat_info->tmac_pause_ctrl_frms;
- tmp_stats[i++] = stat_info->tmac_any_err_frms;
- tmp_stats[i++] = stat_info->tmac_vld_ip_octets;
- tmp_stats[i++] = stat_info->tmac_vld_ip;
- tmp_stats[i++] = stat_info->tmac_drop_ip;
- tmp_stats[i++] = stat_info->tmac_icmp;
- tmp_stats[i++] = stat_info->tmac_rst_tcp;
- tmp_stats[i++] = stat_info->tmac_tcp;
- tmp_stats[i++] = stat_info->tmac_udp;
- tmp_stats[i++] = stat_info->rmac_vld_frms;
- tmp_stats[i++] = stat_info->rmac_data_octets;
- tmp_stats[i++] = stat_info->rmac_fcs_err_frms;
- tmp_stats[i++] = stat_info->rmac_drop_frms;
- tmp_stats[i++] = stat_info->rmac_vld_mcst_frms;
- tmp_stats[i++] = stat_info->rmac_vld_bcst_frms;
- tmp_stats[i++] = stat_info->rmac_in_rng_len_err_frms;
- tmp_stats[i++] = stat_info->rmac_long_frms;
- tmp_stats[i++] = stat_info->rmac_pause_ctrl_frms;
- tmp_stats[i++] = stat_info->rmac_discarded_frms;
- tmp_stats[i++] = stat_info->rmac_usized_frms;
- tmp_stats[i++] = stat_info->rmac_osized_frms;
- tmp_stats[i++] = stat_info->rmac_frag_frms;
- tmp_stats[i++] = stat_info->rmac_jabber_frms;
- tmp_stats[i++] = stat_info->rmac_ip;
- tmp_stats[i++] = stat_info->rmac_ip_octets;
- tmp_stats[i++] = stat_info->rmac_hdr_err_ip;
- tmp_stats[i++] = stat_info->rmac_drop_ip;
- tmp_stats[i++] = stat_info->rmac_icmp;
- tmp_stats[i++] = stat_info->rmac_tcp;
- tmp_stats[i++] = stat_info->rmac_udp;
- tmp_stats[i++] = stat_info->rmac_err_drp_udp;
- tmp_stats[i++] = stat_info->rmac_pause_cnt;
- tmp_stats[i++] = stat_info->rmac_accepted_ip;
- tmp_stats[i++] = stat_info->rmac_err_tcp;
+ tmp_stats[i++] = le32_to_cpu(stat_info->tmac_frms);
+ tmp_stats[i++] = le32_to_cpu(stat_info->tmac_data_octets);
+ tmp_stats[i++] = le64_to_cpu(stat_info->tmac_drop_frms);
+ tmp_stats[i++] = le32_to_cpu(stat_info->tmac_mcst_frms);
+ tmp_stats[i++] = le32_to_cpu(stat_info->tmac_bcst_frms);
+ tmp_stats[i++] = le64_to_cpu(stat_info->tmac_pause_ctrl_frms);
+ tmp_stats[i++] = le32_to_cpu(stat_info->tmac_any_err_frms);
+ tmp_stats[i++] = le64_to_cpu(stat_info->tmac_vld_ip_octets);
+ tmp_stats[i++] = le32_to_cpu(stat_info->tmac_vld_ip);
+ tmp_stats[i++] = le32_to_cpu(stat_info->tmac_drop_ip);
+ tmp_stats[i++] = le32_to_cpu(stat_info->tmac_icmp);
+ tmp_stats[i++] = le32_to_cpu(stat_info->tmac_rst_tcp);
+ tmp_stats[i++] = le64_to_cpu(stat_info->tmac_tcp);
+ tmp_stats[i++] = le32_to_cpu(stat_info->tmac_udp);
+ tmp_stats[i++] = le32_to_cpu(stat_info->rmac_vld_frms);
+ tmp_stats[i++] = le32_to_cpu(stat_info->rmac_data_octets);
+ tmp_stats[i++] = le64_to_cpu(stat_info->rmac_fcs_err_frms);
+ tmp_stats[i++] = le64_to_cpu(stat_info->rmac_drop_frms);
+ tmp_stats[i++] = le32_to_cpu(stat_info->rmac_vld_mcst_frms);
+ tmp_stats[i++] = le32_to_cpu(stat_info->rmac_vld_bcst_frms);
+ tmp_stats[i++] = le32_to_cpu(stat_info->rmac_in_rng_len_err_frms);
+ tmp_stats[i++] = le64_to_cpu(stat_info->rmac_long_frms);
+ tmp_stats[i++] = le64_to_cpu(stat_info->rmac_pause_ctrl_frms);
+ tmp_stats[i++] = le32_to_cpu(stat_info->rmac_discarded_frms);
+ tmp_stats[i++] = le32_to_cpu(stat_info->rmac_usized_frms);
+ tmp_stats[i++] = le32_to_cpu(stat_info->rmac_osized_frms);
+ tmp_stats[i++] = le32_to_cpu(stat_info->rmac_frag_frms);
+ tmp_stats[i++] = le32_to_cpu(stat_info->rmac_jabber_frms);
+ tmp_stats[i++] = le32_to_cpu(stat_info->rmac_ip);
+ tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ip_octets);
+ tmp_stats[i++] = le32_to_cpu(stat_info->rmac_hdr_err_ip);
+ tmp_stats[i++] = le32_to_cpu(stat_info->rmac_drop_ip);
+ tmp_stats[i++] = le32_to_cpu(stat_info->rmac_icmp);
+ tmp_stats[i++] = le64_to_cpu(stat_info->rmac_tcp);
+ tmp_stats[i++] = le32_to_cpu(stat_info->rmac_udp);
+ tmp_stats[i++] = le32_to_cpu(stat_info->rmac_err_drp_udp);
+ tmp_stats[i++] = le32_to_cpu(stat_info->rmac_pause_cnt);
+ tmp_stats[i++] = le32_to_cpu(stat_info->rmac_accepted_ip);
+ tmp_stats[i++] = le32_to_cpu(stat_info->rmac_err_tcp);
}
-int s2io_ethtool_get_regs_len(struct net_device *dev)
+static int s2io_ethtool_get_regs_len(struct net_device *dev)
{
return (XENA_REG_SPACE);
}
-u32 s2io_ethtool_get_rx_csum(struct net_device * dev)
+static u32 s2io_ethtool_get_rx_csum(struct net_device * dev)
{
nic_t *sp = dev->priv;
return (sp->rx_csum);
}
-int s2io_ethtool_set_rx_csum(struct net_device *dev, u32 data)
+
+static int s2io_ethtool_set_rx_csum(struct net_device *dev, u32 data)
{
nic_t *sp = dev->priv;
@@ -3996,17 +3976,19 @@ int s2io_ethtool_set_rx_csum(struct net_device *dev, u32 data)
return 0;
}
-int s2io_get_eeprom_len(struct net_device *dev)
+
+static int s2io_get_eeprom_len(struct net_device *dev)
{
return (XENA_EEPROM_SPACE);
}
-int s2io_ethtool_self_test_count(struct net_device *dev)
+static int s2io_ethtool_self_test_count(struct net_device *dev)
{
return (S2IO_TEST_LEN);
}
-void s2io_ethtool_get_strings(struct net_device *dev,
- u32 stringset, u8 * data)
+
+static void s2io_ethtool_get_strings(struct net_device *dev,
+ u32 stringset, u8 * data)
{
switch (stringset) {
case ETH_SS_TEST:
@@ -4017,12 +3999,13 @@ void s2io_ethtool_get_strings(struct net_device *dev,
sizeof(ethtool_stats_keys));
}
}
+
static int s2io_ethtool_get_stats_count(struct net_device *dev)
{
return (S2IO_STAT_LEN);
}
-int s2io_ethtool_op_set_tx_csum(struct net_device *dev, u32 data)
+static int s2io_ethtool_op_set_tx_csum(struct net_device *dev, u32 data)
{
if (data)
dev->features |= NETIF_F_IP_CSUM;
@@ -4078,7 +4061,7 @@ static struct ethtool_ops netdev_ethtool_ops = {
* function returns OP NOT SUPPORTED value.
*/
-int s2io_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+static int s2io_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
return -EOPNOTSUPP;
}
@@ -4094,7 +4077,7 @@ int s2io_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
* file on failure.
*/
-int s2io_change_mtu(struct net_device *dev, int new_mtu)
+static int s2io_change_mtu(struct net_device *dev, int new_mtu)
{
nic_t *sp = dev->priv;
XENA_dev_config_t __iomem *bar0 = sp->bar0;
@@ -4188,8 +4171,7 @@ static void s2io_set_link(unsigned long data)
* Allow a small delay for the NICs self initiated
* cleanup to complete.
*/
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(HZ / 10);
+ msleep(100);
val64 = readq(&bar0->adapter_status);
if (verify_xena_quiescence(val64, nic->device_enabled_once)) {
@@ -4243,10 +4225,8 @@ static void s2io_card_down(nic_t * sp)
register u64 val64 = 0;
/* If s2io_set_link task is executing, wait till it completes. */
- while (test_and_set_bit(0, &(sp->link_state))) {
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(HZ / 20);
- }
+ while (test_and_set_bit(0, &(sp->link_state)))
+ msleep(50);
atomic_set(&sp->card_state, CARD_DOWN);
/* disable Tx and Rx traffic on the NIC */
@@ -4262,8 +4242,7 @@ static void s2io_card_down(nic_t * sp)
break;
}
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(HZ / 20);
+ msleep(50);
cnt++;
if (cnt == 10) {
DBG_PRINT(ERR_DBG,
@@ -4492,7 +4471,7 @@ static int rx_osm_handler(nic_t * sp, RxD_t * rxdp, int ring_no,
* void.
*/
-void s2io_link(nic_t * sp, int link)
+static void s2io_link(nic_t * sp, int link)
{
struct net_device *dev = (struct net_device *) sp->dev;
@@ -4509,23 +4488,6 @@ void s2io_link(nic_t * sp, int link)
}
/**
- * get_xena_rev_id - to identify revision ID of xena.
- * @pdev : PCI Dev structure
- * Description:
- * Function to identify the Revision ID of xena.
- * Return value:
- * returns the revision ID of the device.
- */
-
-int get_xena_rev_id(struct pci_dev *pdev)
-{
- u8 id = 0;
- int ret;
- ret = pci_read_config_byte(pdev, PCI_REVISION_ID, (u8 *) & id);
- return id;
-}
-
-/**
* s2io_init_pci -Initialization of PCI and PCI-X configuration registers .
* @sp : private member of the device structure, which is a pointer to the
* s2io_nic structure.
@@ -4576,7 +4538,7 @@ static void s2io_init_pci(nic_t * sp)
&(sp->pcix_cmd));
}
-MODULE_AUTHOR("Raghavendra Koushik <raghavendra.koushik@s2io.com>");
+MODULE_AUTHOR("Raghavendra Koushik <raghavendra.koushik@neterion.com>");
MODULE_LICENSE("GPL");
module_param(tx_fifo_num, int, 0);
module_param_array(tx_fifo_len, int, NULL, 0);
@@ -4978,7 +4940,7 @@ int __init s2io_starter(void)
* Description: This function is the cleanup routine for the driver. It unregist * ers the driver.
*/
-void s2io_closer(void)
+static void s2io_closer(void)
{
pci_unregister_driver(&s2io_driver);
DBG_PRINT(INIT_DBG, "cleanup done\n");
diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h
index 9a1737522f0f1..1711c8c3dc99f 100644
--- a/drivers/net/s2io.h
+++ b/drivers/net/s2io.h
@@ -1,6 +1,6 @@
/************************************************************************
* s2io.h: A Linux PCI-X Ethernet driver for S2IO 10GbE Server NIC
- * Copyright 2002 Raghavendra Koushik (raghavendra.koushik@s2io.com)
+ * Copyright(c) 2002-2005 Neterion Inc.
* This software may be used and distributed according to the terms of
* the GNU General Public License (GPL), incorporated herein by reference.
@@ -73,121 +73,6 @@ static int debug_level = ERR_DBG; /* Default level. */
/* The statistics block of Xena */
typedef struct stat_block {
-#ifdef __BIG_ENDIAN
-/* Tx MAC statistics counters. */
- u32 tmac_frms;
- u32 tmac_data_octets;
- u64 tmac_drop_frms;
- u32 tmac_mcst_frms;
- u32 tmac_bcst_frms;
- u64 tmac_pause_ctrl_frms;
- u32 tmac_ttl_octets;
- u32 tmac_ucst_frms;
- u32 tmac_nucst_frms;
- u32 tmac_any_err_frms;
- u64 tmac_ttl_less_fb_octets;
- u64 tmac_vld_ip_octets;
- u32 tmac_vld_ip;
- u32 tmac_drop_ip;
- u32 tmac_icmp;
- u32 tmac_rst_tcp;
- u64 tmac_tcp;
- u32 tmac_udp;
- u32 reserved_0;
-
-/* Rx MAC Statistics counters. */
- u32 rmac_vld_frms;
- u32 rmac_data_octets;
- u64 rmac_fcs_err_frms;
- u64 rmac_drop_frms;
- u32 rmac_vld_mcst_frms;
- u32 rmac_vld_bcst_frms;
- u32 rmac_in_rng_len_err_frms;
- u32 rmac_out_rng_len_err_frms;
- u64 rmac_long_frms;
- u64 rmac_pause_ctrl_frms;
- u64 rmac_unsup_ctrl_frms;
- u32 rmac_ttl_octets;
- u32 rmac_accepted_ucst_frms;
- u32 rmac_accepted_nucst_frms;
- u32 rmac_discarded_frms;
- u32 rmac_drop_events;
- u32 reserved_1;
- u64 rmac_ttl_less_fb_octets;
- u64 rmac_ttl_frms;
- u64 reserved_2;
- u32 reserved_3;
- u32 rmac_usized_frms;
- u32 rmac_osized_frms;
- u32 rmac_frag_frms;
- u32 rmac_jabber_frms;
- u32 reserved_4;
- u64 rmac_ttl_64_frms;
- u64 rmac_ttl_65_127_frms;
- u64 reserved_5;
- u64 rmac_ttl_128_255_frms;
- u64 rmac_ttl_256_511_frms;
- u64 reserved_6;
- u64 rmac_ttl_512_1023_frms;
- u64 rmac_ttl_1024_1518_frms;
- u32 reserved_7;
- u32 rmac_ip;
- u64 rmac_ip_octets;
- u32 rmac_hdr_err_ip;
- u32 rmac_drop_ip;
- u32 rmac_icmp;
- u32 reserved_8;
- u64 rmac_tcp;
- u32 rmac_udp;
- u32 rmac_err_drp_udp;
- u64 rmac_xgmii_err_sym;
- u64 rmac_frms_q0;
- u64 rmac_frms_q1;
- u64 rmac_frms_q2;
- u64 rmac_frms_q3;
- u64 rmac_frms_q4;
- u64 rmac_frms_q5;
- u64 rmac_frms_q6;
- u64 rmac_frms_q7;
- u16 rmac_full_q0;
- u16 rmac_full_q1;
- u16 rmac_full_q2;
- u16 rmac_full_q3;
- u16 rmac_full_q4;
- u16 rmac_full_q5;
- u16 rmac_full_q6;
- u16 rmac_full_q7;
- u32 rmac_pause_cnt;
- u32 reserved_9;
- u64 rmac_xgmii_data_err_cnt;
- u64 rmac_xgmii_ctrl_err_cnt;
- u32 rmac_accepted_ip;
- u32 rmac_err_tcp;
-
-/* PCI/PCI-X Read transaction statistics. */
- u32 rd_req_cnt;
- u32 new_rd_req_cnt;
- u32 new_rd_req_rtry_cnt;
- u32 rd_rtry_cnt;
- u32 wr_rtry_rd_ack_cnt;
-
-/* PCI/PCI-X write transaction statistics. */
- u32 wr_req_cnt;
- u32 new_wr_req_cnt;
- u32 new_wr_req_rtry_cnt;
- u32 wr_rtry_cnt;
- u32 wr_disc_cnt;
- u32 rd_rtry_wr_ack_cnt;
-
-/* DMA Transaction statistics. */
- u32 txp_wr_cnt;
- u32 txd_rd_cnt;
- u32 txd_wr_cnt;
- u32 rxd_rd_cnt;
- u32 rxd_wr_cnt;
- u32 txf_rd_cnt;
- u32 rxf_wr_cnt;
-#else
/* Tx MAC statistics counters. */
u32 tmac_data_octets;
u32 tmac_frms;
@@ -301,7 +186,6 @@ typedef struct stat_block {
u32 rxd_rd_cnt;
u32 rxf_wr_cnt;
u32 txf_rd_cnt;
-#endif
} StatInfo_t;
/* Structures representing different init time configuration
@@ -848,7 +732,7 @@ static void tx_intr_handler(struct s2io_nic *sp);
static void alarm_intr_handler(struct s2io_nic *sp);
static int s2io_starter(void);
-void s2io_closer(void);
+static void s2io_closer(void);
static void s2io_tx_watchdog(struct net_device *dev);
static void s2io_tasklet(unsigned long dev_addr);
static void s2io_set_multicast(struct net_device *dev);
@@ -858,17 +742,18 @@ static int rx_osm_handler(nic_t * sp, u16 len, RxD_t * rxdp, int ring_no);
static int rx_osm_handler(nic_t * sp, RxD_t * rxdp, int ring_no,
buffAdd_t * ba);
#endif
-void s2io_link(nic_t * sp, int link);
-void s2io_reset(nic_t * sp);
+static void s2io_link(nic_t * sp, int link);
+static void s2io_reset(nic_t * sp);
#ifdef CONFIG_S2IO_NAPI
static int s2io_poll(struct net_device *dev, int *budget);
#endif
static void s2io_init_pci(nic_t * sp);
-int s2io_set_mac_addr(struct net_device *dev, u8 * addr);
+static int s2io_set_mac_addr(struct net_device *dev, u8 * addr);
static irqreturn_t s2io_isr(int irq, void *dev_id, struct pt_regs *regs);
static int verify_xena_quiescence(u64 val64, int flag);
static struct ethtool_ops netdev_ethtool_ops;
static void s2io_set_link(unsigned long data);
+static int s2io_set_swapper(nic_t * sp);
static void s2io_card_down(nic_t * nic);
static int s2io_card_up(nic_t * nic);
diff --git a/drivers/net/sb1000.c b/drivers/net/sb1000.c
index dcc64eb8dc4a0..e15369c8d1651 100644
--- a/drivers/net/sb1000.c
+++ b/drivers/net/sb1000.c
@@ -57,9 +57,9 @@ static char version[] = "sb1000.c:v1.1.2 6/01/98 (fventuri@mediaone.net)\n";
#include <asm/uaccess.h>
#ifdef SB1000_DEBUG
-int sb1000_debug = SB1000_DEBUG;
+static int sb1000_debug = SB1000_DEBUG;
#else
-int sb1000_debug = 1;
+static int sb1000_debug = 1;
#endif
static const int SB1000_IO_EXTENT = 8;
@@ -116,15 +116,15 @@ static inline int sb1000_start_get_set_command(const int ioaddr[],
static inline int sb1000_end_get_set_command(const int ioaddr[],
const char* name);
static inline int sb1000_activate(const int ioaddr[], const char* name);
-static inline int sb1000_get_firmware_version(const int ioaddr[],
+static int sb1000_get_firmware_version(const int ioaddr[],
const char* name, unsigned char version[], int do_end);
-static inline int sb1000_get_frequency(const int ioaddr[], const char* name,
+static int sb1000_get_frequency(const int ioaddr[], const char* name,
int* frequency);
-static inline int sb1000_set_frequency(const int ioaddr[], const char* name,
+static int sb1000_set_frequency(const int ioaddr[], const char* name,
int frequency);
-static inline int sb1000_get_PIDs(const int ioaddr[], const char* name,
+static int sb1000_get_PIDs(const int ioaddr[], const char* name,
short PID[]);
-static inline int sb1000_set_PIDs(const int ioaddr[], const char* name,
+static int sb1000_set_PIDs(const int ioaddr[], const char* name,
const short PID[]);
/* SB1000 commands for frame rx interrupt */
@@ -252,7 +252,7 @@ static struct pnp_driver sb1000_driver = {
* SB1000 hardware routines to be used during open/configuration phases
*/
-const int TimeOutJiffies = (875 * HZ) / 100;
+static const int TimeOutJiffies = (875 * HZ) / 100;
static inline void nicedelay(unsigned long usecs)
{
@@ -363,7 +363,7 @@ card_send_command(const int ioaddr[], const char* name,
/*
* SB1000 hardware routines to be used during frame rx interrupt
*/
-const int Sb1000TimeOutJiffies = 7 * HZ;
+static const int Sb1000TimeOutJiffies = 7 * HZ;
/* Card Wait For Ready (to be used during frame rx) */
static inline int
@@ -552,7 +552,7 @@ sb1000_activate(const int ioaddr[], const char* name)
}
/* get SB1000 firmware version */
-static inline int
+static int
sb1000_get_firmware_version(const int ioaddr[], const char* name,
unsigned char version[], int do_end)
{
@@ -575,7 +575,7 @@ sb1000_get_firmware_version(const int ioaddr[], const char* name,
}
/* get SB1000 frequency */
-static inline int
+static int
sb1000_get_frequency(const int ioaddr[], const char* name, int* frequency)
{
unsigned char st[7];
@@ -592,7 +592,7 @@ sb1000_get_frequency(const int ioaddr[], const char* name, int* frequency)
}
/* set SB1000 frequency */
-static inline int
+static int
sb1000_set_frequency(const int ioaddr[], const char* name, int frequency)
{
unsigned char st[7];
@@ -622,7 +622,7 @@ sb1000_set_frequency(const int ioaddr[], const char* name, int frequency)
}
/* get SB1000 PIDs */
-static inline int
+static int
sb1000_get_PIDs(const int ioaddr[], const char* name, short PID[])
{
unsigned char st[7];
@@ -656,7 +656,7 @@ sb1000_get_PIDs(const int ioaddr[], const char* name, short PID[])
}
/* set SB1000 PIDs */
-static inline int
+static int
sb1000_set_PIDs(const int ioaddr[], const char* name, const short PID[])
{
unsigned char st[7];
diff --git a/drivers/net/sb1250-mac.c b/drivers/net/sb1250-mac.c
index 1534679529d27..fd2e7c3749064 100644
--- a/drivers/net/sb1250-mac.c
+++ b/drivers/net/sb1250-mac.c
@@ -14,47 +14,11 @@
* You should have received a copy of the 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 driver is designed for the Broadcom SiByte SOC built-in
+ * Ethernet controllers. Written by Mitch Lichtenberg at Broadcom Corp.
*/
-
-/*
- This driver is designed for the Broadcom SiByte SOC built-in
- Ethernet controllers.
-
- Written by Mitch Lichtenberg at Broadcom Corp.
-*/
-
-
-
-#define CONFIG_SBMAC_COALESCE
-
-/* A few user-configurable values.
- These may be modified when a driver module is loaded. */
-
-static int debug = 1; /* 1 normal messages, 0 quiet .. 7 verbose. */
-static int noisy_mii = 1; /* mii status msgs */
-
-/* Used to pass the media type, etc.
- Both 'options[]' and 'full_duplex[]' should exist for driver
- interoperability.
- The media type is usually passed in 'options[]'.
-*/
-
-#define MAX_UNITS 3 /* More are supported, limit only on options */
-#ifdef MODULE
-static int options[MAX_UNITS] = {-1, -1, -1};
-static int full_duplex[MAX_UNITS] = {-1, -1, -1};
-#endif
-
-#ifdef CONFIG_SBMAC_COALESCE
-static int int_pktcnt = 0;
-static int int_timeout = 0;
-#endif
-
-/* Operational parameters that usually are not changed. */
-
-/* Time in jiffies before concluding the transmitter is hung. */
-#define TX_TIMEOUT (2*HZ)
-
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/string.h>
@@ -89,16 +53,56 @@ static char version1[] __devinitdata =
#endif
+/* Operational parameters that usually are not changed. */
+
+#define CONFIG_SBMAC_COALESCE
+
+#define MAX_UNITS 3 /* More are supported, limit only on options */
+
+/* Time in jiffies before concluding the transmitter is hung. */
+#define TX_TIMEOUT (2*HZ)
+
MODULE_AUTHOR("Mitch Lichtenberg (Broadcom Corp.)");
MODULE_DESCRIPTION("Broadcom SiByte SOC GB Ethernet driver");
-MODULE_PARM(debug, "i");
-MODULE_PARM(noisy_mii, "i");
-MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i");
-MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
-MODULE_PARM(int_pktcnt, "i");
-MODULE_PARM(int_timeout, "i");
+/* A few user-configurable values which may be modified when a driver
+ module is loaded. */
+
+/* 1 normal messages, 0 quiet .. 7 verbose. */
+static int debug = 1;
+module_param(debug, int, S_IRUGO);
+MODULE_PARM_DESC(debug, "Debug messages");
+
+/* mii status msgs */
+static int noisy_mii = 1;
+module_param(noisy_mii, int, S_IRUGO);
+MODULE_PARM_DESC(noisy_mii, "MII status messages");
+
+/* Used to pass the media type, etc.
+ Both 'options[]' and 'full_duplex[]' should exist for driver
+ interoperability.
+ The media type is usually passed in 'options[]'.
+*/
+#ifdef MODULE
+static int options[MAX_UNITS] = {-1, -1, -1};
+module_param_array(options, int, NULL, S_IRUGO);
+MODULE_PARM_DESC(options, "1-" __MODULE_STRING(MAX_UNITS));
+
+static int full_duplex[MAX_UNITS] = {-1, -1, -1};
+module_param_array(full_duplex, int, NULL, S_IRUGO);
+MODULE_PARM_DESC(full_duplex, "1-" __MODULE_STRING(MAX_UNITS));
+#endif
+
+#ifdef CONFIG_SBMAC_COALESCE
+static int int_pktcnt = 0;
+module_param(int_pktcnt, int, S_IRUGO);
+MODULE_PARM_DESC(int_pktcnt, "Packet count");
+
+static int int_timeout = 0;
+module_param(int_timeout, int, S_IRUGO);
+MODULE_PARM_DESC(int_timeout, "Timeout value");
+#endif
#include <asm/sibyte/sb1250.h>
#include <asm/sibyte/sb1250_defs.h>
@@ -1811,8 +1815,6 @@ static void sbmac_set_iphdr_offset(struct sbmac_softc *sc)
/* read system identification to determine revision */
if (periph_rev >= 2) {
- printk(KERN_INFO "%s: enabling TCP rcv checksum\n",
- sc->sbm_dev->name);
sc->rx_hw_checksum = ENABLE;
} else {
sc->rx_hw_checksum = DISABLE;
@@ -2417,6 +2419,11 @@ static int sbmac_init(struct net_device *dev, int idx)
if (err)
goto out_uninit;
+ if (periph_rev >= 2) {
+ printk(KERN_INFO "%s: enabling TCP rcv checksum\n",
+ sc->sbm_dev->name);
+ }
+
/*
* Display Ethernet address (this is called during the config
* process so we need to finish off the config message that
@@ -2879,12 +2886,12 @@ sbmac_init_module(void)
dev->mem_end = 0;
if (sbmac_init(dev, idx)) {
port = A_MAC_CHANNEL_BASE(idx);
- SBMAC_WRITECSR(KSEG1ADDR(port+R_MAC_ETHERNET_ADDR),
- sbmac_orig_hwaddr[idx] );
+ SBMAC_WRITECSR(IOADDR(port+R_MAC_ETHERNET_ADDR),
+ sbmac_orig_hwaddr[idx]);
free_netdev(dev);
continue;
}
- dev_sbmac[idx++] = dev;
+ dev_sbmac[idx] = dev;
}
return 0;
}
diff --git a/drivers/net/sgiseeq.c b/drivers/net/sgiseeq.c
index 4385cd1677a00..9bc3b1c0dd6a2 100644
--- a/drivers/net/sgiseeq.c
+++ b/drivers/net/sgiseeq.c
@@ -136,9 +136,10 @@ static inline void seeq_go(struct sgiseeq_private *sp,
hregs->rx_ctrl = HPC3_ERXCTRL_ACTIVE;
}
-static inline void seeq_load_eaddr(struct net_device *dev,
- struct sgiseeq_regs *sregs)
+static inline void __sgiseeq_set_mac_address(struct net_device *dev)
{
+ struct sgiseeq_private *sp = netdev_priv(dev);
+ struct sgiseeq_regs *sregs = sp->sregs;
int i;
sregs->tstat = SEEQ_TCMD_RB0;
@@ -146,6 +147,20 @@ static inline void seeq_load_eaddr(struct net_device *dev,
sregs->rw.eth_addr[i] = dev->dev_addr[i];
}
+static int sgiseeq_set_mac_address(struct net_device *dev, void *addr)
+{
+ struct sgiseeq_private *sp = netdev_priv(dev);
+ struct sockaddr *sa = addr;
+
+ memcpy(dev->dev_addr, sa->sa_data, dev->addr_len);
+
+ spin_lock_irq(&sp->tx_lock);
+ __sgiseeq_set_mac_address(dev);
+ spin_unlock_irq(&sp->tx_lock);
+
+ return 0;
+}
+
#define TCNTINFO_INIT (HPCDMA_EOX | HPCDMA_ETXD)
#define RCNTCFG_INIT (HPCDMA_OWN | HPCDMA_EORP | HPCDMA_XIE)
#define RCNTINFO_INIT (RCNTCFG_INIT | (PKT_BUF_SZ & HPCDMA_BCNT))
@@ -159,13 +174,7 @@ static int seeq_init_ring(struct net_device *dev)
sp->rx_new = sp->tx_new = 0;
sp->rx_old = sp->tx_old = 0;
- seeq_load_eaddr(dev, sp->sregs);
-
- /* XXX for now just accept packets directly to us
- * XXX and ether-broadcast. Will do multicast and
- * XXX promiscuous mode later. -davem
- */
- sp->mode = SEEQ_RCMD_RBCAST;
+ __sgiseeq_set_mac_address(dev);
/* Setup tx ring. */
for(i = 0; i < SEEQ_TX_BUFFERS; i++) {
@@ -175,7 +184,7 @@ static int seeq_init_ring(struct net_device *dev)
buffer = (unsigned long) kmalloc(PKT_BUF_SZ, GFP_KERNEL);
if (!buffer)
return -ENOMEM;
- sp->tx_desc[i].buf_vaddr = KSEG1ADDR(buffer);
+ sp->tx_desc[i].buf_vaddr = CKSEG1ADDR(buffer);
sp->tx_desc[i].tdma.pbuf = CPHYSADDR(buffer);
}
sp->tx_desc[i].tdma.cntinfo = TCNTINFO_INIT;
@@ -189,7 +198,7 @@ static int seeq_init_ring(struct net_device *dev)
buffer = (unsigned long) kmalloc(PKT_BUF_SZ, GFP_KERNEL);
if (!buffer)
return -ENOMEM;
- sp->rx_desc[i].buf_vaddr = KSEG1ADDR(buffer);
+ sp->rx_desc[i].buf_vaddr = CKSEG1ADDR(buffer);
sp->rx_desc[i].rdma.pbuf = CPHYSADDR(buffer);
}
sp->rx_desc[i].rdma.cntinfo = RCNTINFO_INIT;
@@ -331,10 +340,17 @@ static inline void sgiseeq_rx(struct net_device *dev, struct sgiseeq_private *sp
/* Copy out of kseg1 to avoid silly cache flush. */
eth_copy_and_sum(skb, pkt_pointer + 2, len, 0);
skb->protocol = eth_type_trans(skb, dev);
- netif_rx(skb);
- dev->last_rx = jiffies;
- sp->stats.rx_packets++;
- sp->stats.rx_bytes += len;
+
+ /* We don't want to receive our own packets */
+ if (memcmp(eth_hdr(skb)->h_source, dev->dev_addr, ETH_ALEN)) {
+ netif_rx(skb);
+ dev->last_rx = jiffies;
+ sp->stats.rx_packets++;
+ sp->stats.rx_bytes += len;
+ } else {
+ /* Silently drop my own packets */
+ dev_kfree_skb_irq(skb);
+ }
} else {
printk (KERN_NOTICE "%s: Memory squeeze, deferring packet.\n",
dev->name);
@@ -373,7 +389,7 @@ static inline void kick_tx(struct sgiseeq_tx_desc *td,
*/
while ((td->tdma.cntinfo & (HPCDMA_XIU | HPCDMA_ETXD)) ==
(HPCDMA_XIU | HPCDMA_ETXD))
- td = (struct sgiseeq_tx_desc *)(long) KSEG1ADDR(td->tdma.pnext);
+ td = (struct sgiseeq_tx_desc *)(long) CKSEG1ADDR(td->tdma.pnext);
if (td->tdma.cntinfo & HPCDMA_XIU) {
hregs->tx_ndptr = CPHYSADDR(td);
hregs->tx_ctrl = HPC3_ETXCTRL_ACTIVE;
@@ -583,6 +599,22 @@ static struct net_device_stats *sgiseeq_get_stats(struct net_device *dev)
static void sgiseeq_set_multicast(struct net_device *dev)
{
+ struct sgiseeq_private *sp = (struct sgiseeq_private *) dev->priv;
+ unsigned char oldmode = sp->mode;
+
+ if(dev->flags & IFF_PROMISC)
+ sp->mode = SEEQ_RCMD_RANY;
+ else if ((dev->flags & IFF_ALLMULTI) || dev->mc_count)
+ sp->mode = SEEQ_RCMD_RBMCAST;
+ else
+ sp->mode = SEEQ_RCMD_RBCAST;
+
+ /* XXX I know this sucks, but is there a better way to reprogram
+ * XXX the receiver? At least, this shouldn't happen too often.
+ */
+
+ if (oldmode != sp->mode)
+ sgiseeq_reset(dev);
}
static inline void setup_tx_ring(struct sgiseeq_tx_desc *buf, int nbufs)
@@ -651,13 +683,14 @@ static int sgiseeq_init(struct hpc3_regs* regs, int irq)
sp->sregs = (struct sgiseeq_regs *) &hpc3c0->eth_ext[0];
sp->hregs = &hpc3c0->ethregs;
sp->name = sgiseeqstr;
+ sp->mode = SEEQ_RCMD_RBCAST;
sp->rx_desc = (struct sgiseeq_rx_desc *)
- KSEG1ADDR(ALIGNED(&sp->srings->rxvector[0]));
+ CKSEG1ADDR(ALIGNED(&sp->srings->rxvector[0]));
dma_cache_wback_inv((unsigned long)&sp->srings->rxvector,
sizeof(sp->srings->rxvector));
sp->tx_desc = (struct sgiseeq_tx_desc *)
- KSEG1ADDR(ALIGNED(&sp->srings->txvector[0]));
+ CKSEG1ADDR(ALIGNED(&sp->srings->txvector[0]));
dma_cache_wback_inv((unsigned long)&sp->srings->txvector,
sizeof(sp->srings->txvector));
@@ -681,6 +714,7 @@ static int sgiseeq_init(struct hpc3_regs* regs, int irq)
dev->watchdog_timeo = (200 * HZ) / 1000;
dev->get_stats = sgiseeq_get_stats;
dev->set_multicast_list = sgiseeq_set_multicast;
+ dev->set_mac_address = sgiseeq_set_mac_address;
dev->irq = irq;
if (register_netdev(dev)) {
diff --git a/drivers/net/shaper.c b/drivers/net/shaper.c
index 269e7f7f78ee9..e68cf5fb4920f 100644
--- a/drivers/net/shaper.c
+++ b/drivers/net/shaper.c
@@ -96,7 +96,7 @@ struct shaper_cb {
};
#define SHAPERCB(skb) ((struct shaper_cb *) ((skb)->cb))
-int sh_debug; /* Debug flag */
+static int sh_debug; /* Debug flag */
#define SHAPER_BANNER "CymruNet Traffic Shaper BETA 0.04 for Linux 2.1\n"
diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c
index d2a9fff5e76f5..3e9d9aab05887 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.06 Sep. 24 2002
+ Revision: 1.08.08 Jan. 22 2005
Modified from the driver which is originally written by Donald Becker.
@@ -16,8 +16,8 @@
preliminary Rev. 1.0 Nov. 10, 1998
SiS 7014 Single Chip 100BASE-TX/10BASE-T Physical Layer Solution,
preliminary Rev. 1.0 Jan. 18, 1998
- http://www.sis.com.tw/support/databook.htm
+ 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
Rev 1.08.05 Jun. 6 2002 Mufasa Yang bug fix for read_eeprom & Tx descriptor over-boundary
@@ -69,12 +69,13 @@
#include <asm/processor.h> /* Processor type for cache alignment. */
#include <asm/io.h>
+#include <asm/irq.h>
#include <asm/uaccess.h> /* User space memory access functions */
#include "sis900.h"
#define SIS900_MODULE_NAME "sis900"
-#define SIS900_DRV_VERSION "v1.08.07 11/02/2003"
+#define SIS900_DRV_VERSION "v1.08.08 Jan. 22 2005"
static char version[] __devinitdata =
KERN_INFO "sis900.c: " SIS900_DRV_VERSION "\n";
@@ -82,8 +83,13 @@ KERN_INFO "sis900.c: " SIS900_DRV_VERSION "\n";
static int max_interrupt_work = 40;
static int multicast_filter_limit = 128;
-#define sis900_debug debug
-static int sis900_debug;
+static int sis900_debug = -1; /* Use SIS900_DEF_MSG as value */
+
+#define SIS900_DEF_MSG \
+ (NETIF_MSG_DRV | \
+ NETIF_MSG_LINK | \
+ NETIF_MSG_RX_ERR | \
+ NETIF_MSG_TX_ERR)
/* Time in jiffies before concluding the transmitter is hung. */
#define TX_TIMEOUT (4*HZ)
@@ -160,6 +166,8 @@ struct sis900_private {
struct timer_list timer; /* Link status detection timer. */
u8 autong_complete; /* 1: auto-negotiate complete */
+ u32 msg_enable;
+
unsigned int cur_rx, dirty_rx; /* producer/comsumer pointers for Tx/Rx ring */
unsigned int cur_tx, dirty_tx;
@@ -174,6 +182,7 @@ struct sis900_private {
unsigned int tx_full; /* The Tx queue is full. */
u8 host_bridge_rev;
+ u8 chipset_rev;
};
MODULE_AUTHOR("Jim Huang <cmhuang@sis.com.tw>, Ollie Lho <ollie@sis.com.tw>");
@@ -182,11 +191,14 @@ MODULE_LICENSE("GPL");
module_param(multicast_filter_limit, int, 0444);
module_param(max_interrupt_work, int, 0444);
-module_param(debug, int, 0444);
+module_param(sis900_debug, int, 0444);
MODULE_PARM_DESC(multicast_filter_limit, "SiS 900/7016 maximum number of filtered multicast addresses");
MODULE_PARM_DESC(max_interrupt_work, "SiS 900/7016 maximum events handled per interrupt");
-MODULE_PARM_DESC(debug, "SiS 900/7016 debug level (2-4)");
+MODULE_PARM_DESC(sis900_debug, "SiS 900/7016 bitmapped debugging message level");
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void sis900_poll(struct net_device *dev);
+#endif
static int sis900_open(struct net_device *net_dev);
static int sis900_mii_probe (struct net_device * net_dev);
static void sis900_init_rxfilter (struct net_device * net_dev);
@@ -235,8 +247,8 @@ static int __devinit sis900_get_mac_addr(struct pci_dev * pci_dev, struct net_de
/* check to see if we have sane EEPROM */
signature = (u16) read_eeprom(ioaddr, EEPROMSignature);
if (signature == 0xffff || signature == 0x0000) {
- printk (KERN_INFO "%s: Error EERPOM read %x\n",
- net_dev->name, signature);
+ printk (KERN_WARNING "%s: Error EERPOM read %x\n",
+ pci_name(pci_dev), signature);
return 0;
}
@@ -268,7 +280,8 @@ static int __devinit sis630e_get_mac_addr(struct pci_dev * pci_dev,
if (!isa_bridge)
isa_bridge = pci_get_device(PCI_VENDOR_ID_SI, 0x0018, isa_bridge);
if (!isa_bridge) {
- printk("%s: Can not find ISA bridge\n", net_dev->name);
+ printk(KERN_WARNING "%s: Can not find ISA bridge\n",
+ pci_name(pci_dev));
return 0;
}
pci_read_config_byte(isa_bridge, 0x48, &reg);
@@ -386,8 +399,8 @@ static int __devinit sis900_probe(struct pci_dev *pci_dev,
void *ring_space;
long ioaddr;
int i, ret;
- u8 revision;
char *card_name = card_names[pci_id->driver_data];
+ const char *dev_name = pci_name(pci_dev);
/* when built into the kernel, we only print version if device is found */
#ifndef MODULE
@@ -456,37 +469,49 @@ static int __devinit sis900_probe(struct pci_dev *pci_dev,
net_dev->tx_timeout = sis900_tx_timeout;
net_dev->watchdog_timeo = TX_TIMEOUT;
net_dev->ethtool_ops = &sis900_ethtool_ops;
-
- ret = register_netdev(net_dev);
- if (ret)
- goto err_unmap_rx;
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ net_dev->poll_controller = &sis900_poll;
+#endif
+
+ if (sis900_debug > 0)
+ sis_priv->msg_enable = sis900_debug;
+ else
+ sis_priv->msg_enable = SIS900_DEF_MSG;
/* Get Mac address according to the chip revision */
- pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &revision);
+ pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &(sis_priv->chipset_rev));
+ if(netif_msg_probe(sis_priv))
+ printk(KERN_DEBUG "%s: detected revision %2.2x, "
+ "trying to get MAC address...\n",
+ dev_name, sis_priv->chipset_rev);
+
ret = 0;
-
- if (revision == SIS630E_900_REV)
+ if (sis_priv->chipset_rev == SIS630E_900_REV)
ret = sis630e_get_mac_addr(pci_dev, net_dev);
- else if ((revision > 0x81) && (revision <= 0x90) )
+ else if ((sis_priv->chipset_rev > 0x81) && (sis_priv->chipset_rev <= 0x90) )
ret = sis635_get_mac_addr(pci_dev, net_dev);
- else if (revision == SIS96x_900_REV)
+ else if (sis_priv->chipset_rev == SIS96x_900_REV)
ret = sis96x_get_mac_addr(pci_dev, net_dev);
else
ret = sis900_get_mac_addr(pci_dev, net_dev);
if (ret == 0) {
+ printk(KERN_WARNING "%s: Cannot read MAC address.\n", dev_name);
ret = -ENODEV;
- goto err_out_unregister;
+ goto err_unmap_rx;
}
/* 630ET : set the mii access mode as software-mode */
- if (revision == SIS630ET_900_REV)
+ if (sis_priv->chipset_rev == SIS630ET_900_REV)
outl(ACCESSMODE | inl(ioaddr + cr), ioaddr + cr);
/* probe for mii transceiver */
if (sis900_mii_probe(net_dev) == 0) {
+ printk(KERN_WARNING "%s: Error probing MII device.\n",
+ dev_name);
ret = -ENODEV;
- goto err_out_unregister;
+ goto err_unmap_rx;
}
/* save our host bridge revision */
@@ -496,6 +521,10 @@ static int __devinit sis900_probe(struct pci_dev *pci_dev,
pci_dev_put(dev);
}
+ ret = register_netdev(net_dev);
+ if (ret)
+ goto err_unmap_rx;
+
/* print some information about our NIC */
printk(KERN_INFO "%s: %s at %#lx, IRQ %d, ", net_dev->name,
card_name, ioaddr, net_dev->irq);
@@ -505,8 +534,6 @@ static int __devinit sis900_probe(struct pci_dev *pci_dev,
return 0;
- err_out_unregister:
- unregister_netdev(net_dev);
err_unmap_rx:
pci_free_consistent(pci_dev, RX_TOTAL_SIZE, sis_priv->rx_ring,
sis_priv->rx_ring_dma);
@@ -533,10 +560,10 @@ static int __devinit sis900_probe(struct pci_dev *pci_dev,
static int __init sis900_mii_probe(struct net_device * net_dev)
{
struct sis900_private * sis_priv = net_dev->priv;
+ const char *dev_name = pci_name(sis_priv->pci_dev);
u16 poll_bit = MII_STAT_LINK, status = 0;
unsigned long timeout = jiffies + 5 * HZ;
int phy_addr;
- u8 revision;
sis_priv->mii = NULL;
@@ -550,12 +577,16 @@ static int __init sis900_mii_probe(struct net_device * net_dev)
for(i = 0; i < 2; i++)
mii_status = mdio_read(net_dev, phy_addr, MII_STATUS);
- if (mii_status == 0xffff || mii_status == 0x0000)
- /* the mii is not accessible, try next one */
+ if (mii_status == 0xffff || mii_status == 0x0000) {
+ if (netif_msg_probe(sis_priv))
+ printk(KERN_DEBUG "%s: MII at address %d"
+ " not accessible\n",
+ dev_name, phy_addr);
continue;
+ }
if ((mii_phy = kmalloc(sizeof(struct mii_phy), GFP_KERNEL)) == NULL) {
- printk(KERN_INFO "Cannot allocate mem for struct mii_phy\n");
+ printk(KERN_WARNING "Cannot allocate mem for struct mii_phy\n");
mii_phy = sis_priv->first_mii;
while (mii_phy) {
struct mii_phy *phy;
@@ -581,22 +612,23 @@ static int __init sis900_mii_probe(struct net_device * net_dev)
if (mii_chip_table[i].phy_types == MIX)
mii_phy->phy_types =
(mii_status & (MII_STAT_CAN_TX_FDX | MII_STAT_CAN_TX)) ? LAN : HOME;
- printk(KERN_INFO "%s: %s transceiver found at address %d.\n",
- net_dev->name, mii_chip_table[i].name,
- phy_addr);
+ printk(KERN_INFO "%s: %s transceiver found "
+ "at address %d.\n",
+ dev_name,
+ mii_chip_table[i].name,
+ phy_addr);
break;
}
if( !mii_chip_table[i].phy_id1 ) {
printk(KERN_INFO "%s: Unknown PHY transceiver found at address %d.\n",
- net_dev->name, phy_addr);
+ dev_name, phy_addr);
mii_phy->phy_types = UNKNOWN;
}
}
if (sis_priv->mii == NULL) {
- printk(KERN_INFO "%s: No MII transceivers found!\n",
- net_dev->name);
+ printk(KERN_INFO "%s: No MII transceivers found!\n", dev_name);
return 0;
}
@@ -621,14 +653,13 @@ static int __init sis900_mii_probe(struct net_device * net_dev)
poll_bit ^= (mdio_read(net_dev, sis_priv->cur_phy, MII_STATUS) & poll_bit);
if (time_after_eq(jiffies, timeout)) {
printk(KERN_WARNING "%s: reset phy and link down now\n",
- net_dev->name);
+ dev_name);
return -ETIME;
}
}
}
- pci_read_config_byte(sis_priv->pci_dev, PCI_CLASS_REVISION, &revision);
- if (revision == SIS630E_900_REV) {
+ if (sis_priv->chipset_rev == SIS630E_900_REV) {
/* SiS 630E has some bugs on default value of PHY registers */
mdio_write(net_dev, sis_priv->cur_phy, MII_ANADV, 0x05e1);
mdio_write(net_dev, sis_priv->cur_phy, MII_CONFIG1, 0x22);
@@ -691,7 +722,7 @@ static u16 sis900_default_phy(struct net_device * net_dev)
sis_priv->mii = default_phy;
sis_priv->cur_phy = default_phy->phy_addr;
printk(KERN_INFO "%s: Using transceiver found at address %d as default\n",
- net_dev->name,sis_priv->cur_phy);
+ pci_name(sis_priv->pci_dev), sis_priv->cur_phy);
}
status = mdio_read(net_dev, sis_priv->cur_phy, MII_CONTROL);
@@ -930,6 +961,20 @@ static u16 sis900_reset_phy(struct net_device *net_dev, int phy_addr)
return status;
}
+#ifdef CONFIG_NET_POLL_CONTROLLER
+/*
+ * Polling 'interrupt' - used by things like netconsole to send skbs
+ * without having to re-enable interrupts. It's not called while
+ * the interrupt routine is executing.
+*/
+static void sis900_poll(struct net_device *dev)
+{
+ disable_irq(dev->irq);
+ sis900_interrupt(dev->irq, dev, NULL);
+ enable_irq(dev->irq);
+}
+#endif
+
/**
* sis900_open - open sis900 device
* @net_dev: the net device to open
@@ -943,15 +988,13 @@ sis900_open(struct net_device *net_dev)
{
struct sis900_private *sis_priv = net_dev->priv;
long ioaddr = net_dev->base_addr;
- u8 revision;
int ret;
/* Soft reset the chip. */
sis900_reset(net_dev);
/* Equalizer workaround Rule */
- pci_read_config_byte(sis_priv->pci_dev, PCI_CLASS_REVISION, &revision);
- sis630_set_eq(net_dev, revision);
+ sis630_set_eq(net_dev, sis_priv->chipset_rev);
ret = request_irq(net_dev->irq, &sis900_interrupt, SA_SHIRQ,
net_dev->name, net_dev);
@@ -999,6 +1042,7 @@ sis900_open(struct net_device *net_dev)
static void
sis900_init_rxfilter (struct net_device * net_dev)
{
+ struct sis900_private *sis_priv = net_dev->priv;
long ioaddr = net_dev->base_addr;
u32 rfcrSave;
u32 i;
@@ -1016,8 +1060,8 @@ sis900_init_rxfilter (struct net_device * net_dev)
outl((i << RFADDR_shift), ioaddr + rfcr);
outl(w, ioaddr + rfdr);
- if (sis900_debug > 2) {
- printk(KERN_INFO "%s: Receive Filter Addrss[%d]=%x\n",
+ if (netif_msg_hw(sis_priv)) {
+ printk(KERN_DEBUG "%s: Receive Filter Addrss[%d]=%x\n",
net_dev->name, i, inl(ioaddr + rfdr));
}
}
@@ -1054,8 +1098,8 @@ sis900_init_tx_ring(struct net_device *net_dev)
/* load Transmit Descriptor Register */
outl(sis_priv->tx_ring_dma, ioaddr + txdp);
- if (sis900_debug > 2)
- printk(KERN_INFO "%s: TX descriptor register loaded with: %8.8x\n",
+ if (netif_msg_hw(sis_priv))
+ printk(KERN_DEBUG "%s: TX descriptor register loaded with: %8.8x\n",
net_dev->name, inl(ioaddr + txdp));
}
@@ -1108,8 +1152,8 @@ sis900_init_rx_ring(struct net_device *net_dev)
/* load Receive Descriptor Register */
outl(sis_priv->rx_ring_dma, ioaddr + rxdp);
- if (sis900_debug > 2)
- printk(KERN_INFO "%s: RX descriptor register loaded with: %8.8x\n",
+ if (netif_msg_hw(sis_priv))
+ printk(KERN_DEBUG "%s: RX descriptor register loaded with: %8.8x\n",
net_dev->name, inl(ioaddr + rxdp));
}
@@ -1219,7 +1263,6 @@ static void sis900_timer(unsigned long data)
struct mii_phy *mii_phy = sis_priv->mii;
static int next_tick = 5*HZ;
u16 status;
- u8 revision;
if (!sis_priv->autong_complete){
int speed, duplex = 0;
@@ -1227,9 +1270,7 @@ static void sis900_timer(unsigned long data)
sis900_read_mode(net_dev, &speed, &duplex);
if (duplex){
sis900_set_mode(net_dev->base_addr, speed, duplex);
- pci_read_config_byte(sis_priv->pci_dev,
- PCI_CLASS_REVISION, &revision);
- sis630_set_eq(net_dev, revision);
+ sis630_set_eq(net_dev, sis_priv->chipset_rev);
netif_start_queue(net_dev);
}
@@ -1256,16 +1297,15 @@ static void sis900_timer(unsigned long data)
/* Link ON -> OFF */
if (!(status & MII_STAT_LINK)){
netif_carrier_off(net_dev);
- printk(KERN_INFO "%s: Media Link Off\n", net_dev->name);
+ if(netif_msg_link(sis_priv))
+ printk(KERN_INFO "%s: Media Link Off\n", net_dev->name);
/* Change mode issue */
if ((mii_phy->phy_id0 == 0x001D) &&
((mii_phy->phy_id1 & 0xFFF0) == 0x8000))
sis900_reset_phy(net_dev, sis_priv->cur_phy);
- pci_read_config_byte(sis_priv->pci_dev,
- PCI_CLASS_REVISION, &revision);
- sis630_set_eq(net_dev, revision);
+ sis630_set_eq(net_dev, sis_priv->chipset_rev);
goto LookForLink;
}
@@ -1371,7 +1411,8 @@ static void sis900_auto_negotiate(struct net_device *net_dev, int phy_addr)
status = mdio_read(net_dev, phy_addr, MII_STATUS);
if (!(status & MII_STAT_LINK)){
- printk(KERN_INFO "%s: Media Link Off\n", net_dev->name);
+ if(netif_msg_link(sis_priv))
+ printk(KERN_INFO "%s: Media Link Off\n", net_dev->name);
sis_priv->autong_complete = 1;
netif_carrier_off(net_dev);
return;
@@ -1433,7 +1474,8 @@ static void sis900_read_mode(struct net_device *net_dev, int *speed, int *duplex
*speed = HW_SPEED_100_MBPS;
}
- printk(KERN_INFO "%s: Media Link On %s %s-duplex \n",
+ if(netif_msg_link(sis_priv))
+ printk(KERN_INFO "%s: Media Link On %s %s-duplex \n",
net_dev->name,
*speed == HW_SPEED_100_MBPS ?
"100mbps" : "10mbps",
@@ -1456,8 +1498,9 @@ static void sis900_tx_timeout(struct net_device *net_dev)
unsigned long flags;
int i;
- printk(KERN_INFO "%s: Transmit timeout, status %8.8x %8.8x \n",
- net_dev->name, inl(ioaddr + cr), inl(ioaddr + isr));
+ if(netif_msg_tx_err(sis_priv))
+ printk(KERN_INFO "%s: Transmit timeout, status %8.8x %8.8x \n",
+ net_dev->name, inl(ioaddr + cr), inl(ioaddr + isr));
/* Disable interrupts by clearing the interrupt mask. */
outl(0x0000, ioaddr + imr);
@@ -1558,8 +1601,8 @@ sis900_start_xmit(struct sk_buff *skb, struct net_device *net_dev)
net_dev->trans_start = jiffies;
- if (sis900_debug > 3)
- printk(KERN_INFO "%s: Queued Tx packet at %p size %d "
+ if (netif_msg_tx_queued(sis_priv))
+ printk(KERN_DEBUG "%s: Queued Tx packet at %p size %d "
"to slot %d.\n",
net_dev->name, skb->data, (int)skb->len, entry);
@@ -1606,20 +1649,22 @@ static irqreturn_t sis900_interrupt(int irq, void *dev_instance, struct pt_regs
/* something strange happened !!! */
if (status & HIBERR) {
- printk(KERN_INFO "%s: Abnormal interrupt,"
- "status %#8.8x.\n", net_dev->name, status);
+ if(netif_msg_intr(sis_priv))
+ printk(KERN_INFO "%s: Abnormal interrupt,"
+ "status %#8.8x.\n", net_dev->name, status);
break;
}
if (--boguscnt < 0) {
- printk(KERN_INFO "%s: Too much work at interrupt, "
- "interrupt status = %#8.8x.\n",
- net_dev->name, status);
+ if(netif_msg_intr(sis_priv))
+ printk(KERN_INFO "%s: Too much work at interrupt, "
+ "interrupt status = %#8.8x.\n",
+ net_dev->name, status);
break;
}
} while (1);
- if (sis900_debug > 3)
- printk(KERN_INFO "%s: exiting interrupt, "
+ if(netif_msg_intr(sis_priv))
+ printk(KERN_DEBUG "%s: exiting interrupt, "
"interrupt status = 0x%#8.8x.\n",
net_dev->name, inl(ioaddr + isr));
@@ -1644,8 +1689,8 @@ static int sis900_rx(struct net_device *net_dev)
unsigned int entry = sis_priv->cur_rx % NUM_RX_DESC;
u32 rx_status = sis_priv->rx_ring[entry].cmdsts;
- if (sis900_debug > 3)
- printk(KERN_INFO "sis900_rx, cur_rx:%4.4d, dirty_rx:%4.4d "
+ if (netif_msg_rx_status(sis_priv))
+ printk(KERN_DEBUG "sis900_rx, cur_rx:%4.4d, dirty_rx:%4.4d "
"status:0x%8.8x\n",
sis_priv->cur_rx, sis_priv->dirty_rx, rx_status);
@@ -1656,8 +1701,8 @@ static int sis900_rx(struct net_device *net_dev)
if (rx_status & (ABORT|OVERRUN|TOOLONG|RUNT|RXISERR|CRCERR|FAERR)) {
/* corrupted packet received */
- if (sis900_debug > 3)
- printk(KERN_INFO "%s: Corrupted packet "
+ if (netif_msg_rx_err(sis_priv))
+ printk(KERN_DEBUG "%s: Corrupted packet "
"received, buffer status = 0x%8.8x.\n",
net_dev->name, rx_status);
sis_priv->stats.rx_errors++;
@@ -1678,9 +1723,10 @@ static int sis900_rx(struct net_device *net_dev)
some unknow bugs, it is possible that
we are working on NULL sk_buff :-( */
if (sis_priv->rx_skbuff[entry] == NULL) {
- printk(KERN_INFO "%s: NULL pointer "
- "encountered in Rx ring, skipping\n",
- net_dev->name);
+ if (netif_msg_rx_err(sis_priv))
+ printk(KERN_INFO "%s: NULL pointer "
+ "encountered in Rx ring, skipping\n",
+ net_dev->name);
break;
}
@@ -1707,9 +1753,10 @@ static int sis900_rx(struct net_device *net_dev)
* "hole" on the buffer ring, it is not clear
* how the hardware will react to this kind
* of degenerated buffer */
- printk(KERN_INFO "%s: Memory squeeze,"
- "deferring packet.\n",
- net_dev->name);
+ if (netif_msg_rx_status(sis_priv))
+ printk(KERN_INFO "%s: Memory squeeze,"
+ "deferring packet.\n",
+ net_dev->name);
sis_priv->rx_skbuff[entry] = NULL;
/* reset buffer descriptor state */
sis_priv->rx_ring[entry].cmdsts = 0;
@@ -1743,9 +1790,10 @@ static int sis900_rx(struct net_device *net_dev)
* "hole" on the buffer ring, it is not clear
* how the hardware will react to this kind
* of degenerated buffer */
- printk(KERN_INFO "%s: Memory squeeze,"
- "deferring packet.\n",
- net_dev->name);
+ if (netif_msg_rx_err(sis_priv))
+ printk(KERN_INFO "%s: Memory squeeze,"
+ "deferring packet.\n",
+ net_dev->name);
sis_priv->stats.rx_dropped++;
break;
}
@@ -1794,8 +1842,8 @@ static void sis900_finish_xmit (struct net_device *net_dev)
if (tx_status & (ABORT | UNDERRUN | OWCOLL)) {
/* packet unsuccessfully transmitted */
- if (sis900_debug > 3)
- printk(KERN_INFO "%s: Transmit "
+ if (netif_msg_tx_err(sis_priv))
+ printk(KERN_DEBUG "%s: Transmit "
"error, Tx status %8.8x.\n",
net_dev->name, tx_status);
sis_priv->stats.tx_errors++;
@@ -1906,8 +1954,22 @@ static void sis900_get_drvinfo(struct net_device *net_dev,
strcpy (info->bus_info, pci_name(sis_priv->pci_dev));
}
+static u32 sis900_get_msglevel(struct net_device *net_dev)
+{
+ struct sis900_private *sis_priv = net_dev->priv;
+ return sis_priv->msg_enable;
+}
+
+static void sis900_set_msglevel(struct net_device *net_dev, u32 value)
+{
+ struct sis900_private *sis_priv = net_dev->priv;
+ sis_priv->msg_enable = value;
+}
+
static struct ethtool_ops sis900_ethtool_ops = {
- .get_drvinfo = sis900_get_drvinfo,
+ .get_drvinfo = sis900_get_drvinfo,
+ .get_msglevel = sis900_get_msglevel,
+ .set_msglevel = sis900_set_msglevel,
};
/**
@@ -2048,12 +2110,10 @@ static int sis900_set_config(struct net_device *dev, struct ifmap *map)
case IF_PORT_AUI: /* AUI */
case IF_PORT_100BASEFX: /* 100BaseFx */
/* These Modes are not supported (are they?)*/
- printk(KERN_INFO "Not supported");
return -EOPNOTSUPP;
break;
default:
- printk(KERN_INFO "Invalid");
return -EINVAL;
}
}
@@ -2099,11 +2159,10 @@ static void set_rx_mode(struct net_device *net_dev)
u16 mc_filter[16] = {0}; /* 256/128 bits multicast hash table */
int i, table_entries;
u32 rx_mode;
- u8 revision;
/* 635 Hash Table entires = 256(2^16) */
- pci_read_config_byte(sis_priv->pci_dev, PCI_CLASS_REVISION, &revision);
- if((revision >= SIS635A_900_REV) || (revision == SIS900B_900_REV))
+ if((sis_priv->chipset_rev >= SIS635A_900_REV) ||
+ (sis_priv->chipset_rev == SIS900B_900_REV))
table_entries = 16;
else
table_entries = 8;
@@ -2129,7 +2188,7 @@ static void set_rx_mode(struct net_device *net_dev)
mclist && i < net_dev->mc_count;
i++, mclist = mclist->next) {
unsigned int bit_nr =
- sis900_mcast_bitnr(mclist->dmi_addr, revision);
+ sis900_mcast_bitnr(mclist->dmi_addr, sis_priv->chipset_rev);
mc_filter[bit_nr >> 4] |= (1 << (bit_nr & 0xf));
}
}
@@ -2175,7 +2234,6 @@ static void sis900_reset(struct net_device *net_dev)
long ioaddr = net_dev->base_addr;
int i = 0;
u32 status = TxRCMP | RxRCMP;
- u8 revision;
outl(0, ioaddr + ier);
outl(0, ioaddr + imr);
@@ -2188,8 +2246,8 @@ static void sis900_reset(struct net_device *net_dev)
status ^= (inl(isr + ioaddr) & status);
}
- pci_read_config_byte(sis_priv->pci_dev, PCI_CLASS_REVISION, &revision);
- if( (revision >= SIS635A_900_REV) || (revision == SIS900B_900_REV) )
+ if( (sis_priv->chipset_rev >= SIS635A_900_REV) ||
+ (sis_priv->chipset_rev == SIS900B_900_REV) )
outl(PESEL | RND_CNT, ioaddr + cfg);
else
outl(PESEL, ioaddr + cfg);
@@ -2226,7 +2284,7 @@ static void __devexit sis900_remove(struct pci_dev *pci_dev)
#ifdef CONFIG_PM
-static int sis900_suspend(struct pci_dev *pci_dev, u32 state)
+static int sis900_suspend(struct pci_dev *pci_dev, pm_message_t state)
{
struct net_device *net_dev = pci_get_drvdata(pci_dev);
long ioaddr = net_dev->base_addr;
diff --git a/drivers/net/sk98lin/h/skdrv1st.h b/drivers/net/sk98lin/h/skdrv1st.h
index e65a19f8794ae..308440bd0e126 100644
--- a/drivers/net/sk98lin/h/skdrv1st.h
+++ b/drivers/net/sk98lin/h/skdrv1st.h
@@ -69,6 +69,7 @@ typedef struct s_AC SK_AC;
#include <linux/bitops.h>
#include <asm/byteorder.h>
#include <asm/io.h>
+#include <asm/irq.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
diff --git a/drivers/net/sk98lin/skethtool.c b/drivers/net/sk98lin/skethtool.c
index 0aed3b9aa51fb..fb639959292b3 100644
--- a/drivers/net/sk98lin/skethtool.c
+++ b/drivers/net/sk98lin/skethtool.c
@@ -257,7 +257,7 @@ static void getDriverInfo(struct net_device *dev, struct ethtool_drvinfo *info)
strlcpy(info->driver, DRIVER_FILE_NAME, sizeof(info->driver));
strcpy(info->version, vers);
strcpy(info->fw_version, "N/A");
- strlcpy(info->bus_info, pAC->PciDev->slot_name, ETHTOOL_BUSINFO_LEN);
+ strlcpy(info->bus_info, pci_name(pAC->PciDev), ETHTOOL_BUSINFO_LEN);
}
/*
@@ -437,9 +437,6 @@ static int locateDevice(struct net_device *dev, u32 data)
pAC->LedsOn = 0;
mod_timer(&pAC->BlinkTimer, jiffies);
msleep_interruptible(data * 1000);
-
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(data * HZ);
del_timer_sync(&pAC->BlinkTimer);
toggleLeds(pNet, 0);
diff --git a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c
index 5eb7bc1398912..05b827f79f54a 100644
--- a/drivers/net/sk98lin/skge.c
+++ b/drivers/net/sk98lin/skge.c
@@ -3058,7 +3058,7 @@ fault_gen:
*/
* ((SK_U32 *)pMemBuf) = 0;
* ((SK_U32 *)pMemBuf + 1) = pdev->bus->number;
- * ((SK_U32 *)pMemBuf + 2) = ParseDeviceNbrFromSlotName(pdev->slot_name);
+ * ((SK_U32 *)pMemBuf + 2) = ParseDeviceNbrFromSlotName(pci_name(pdev));
if(copy_to_user(Ioctl.pData, pMemBuf, Length) ) {
Err = -EFAULT;
goto fault_diag;
@@ -5152,8 +5152,10 @@ static struct pci_device_id skge_pci_tbl[] = {
{ 0, }
};
+MODULE_DEVICE_TABLE(pci, skge_pci_tbl);
+
static struct pci_driver skge_driver = {
- .name = "skge",
+ .name = "sk98lin",
.id_table = skge_pci_tbl,
.probe = skge_probe_one,
.remove = __devexit_p(skge_remove_one),
diff --git a/drivers/net/sk_mca.c b/drivers/net/sk_mca.c
index ef640f9082974..4c56b8d8221b2 100644
--- a/drivers/net/sk_mca.c
+++ b/drivers/net/sk_mca.c
@@ -127,12 +127,13 @@ static unsigned char poly[] =
#ifdef DEBUG
static void dumpmem(struct net_device *dev, u32 start, u32 len)
{
+ skmca_priv *priv = netdev_priv(dev);
int z;
for (z = 0; z < len; z++) {
if ((z & 15) == 0)
printk("%04x:", z);
- printk(" %02x", SKMCA_READB(dev->mem_start + start + z));
+ printk(" %02x", readb(priv->base + start + z));
if ((z & 15) == 15)
printk("\n");
}
@@ -220,21 +221,21 @@ static int __init dofind(int *junior, int firstslot)
static void ResetBoard(struct net_device *dev)
{
- skmca_priv *priv = (skmca_priv *) dev->priv;
+ skmca_priv *priv = netdev_priv(dev);
- SKMCA_WRITEB(CTRL_RESET_ON, priv->ctrladdr);
+ writeb(CTRL_RESET_ON, priv->ctrladdr);
udelay(10);
- SKMCA_WRITEB(CTRL_RESET_OFF, priv->ctrladdr);
+ writeb(CTRL_RESET_OFF, priv->ctrladdr);
}
/* wait for LANCE interface to become not busy */
static int WaitLANCE(struct net_device *dev)
{
- skmca_priv *priv = (skmca_priv *) dev->priv;
+ skmca_priv *priv = netdev_priv(dev);
int t = 0;
- while ((SKMCA_READB(priv->ctrladdr) & STAT_IO_BUSY) ==
+ while ((readb(priv->ctrladdr) & STAT_IO_BUSY) ==
STAT_IO_BUSY) {
udelay(1);
if (++t > 1000) {
@@ -250,7 +251,7 @@ static int WaitLANCE(struct net_device *dev)
static void SetLANCE(struct net_device *dev, u16 addr, u16 value)
{
- skmca_priv *priv = (skmca_priv *) dev->priv;
+ skmca_priv *priv = netdev_priv(dev);
unsigned long flags;
/* disable interrupts */
@@ -263,19 +264,17 @@ static void SetLANCE(struct net_device *dev, u16 addr, u16 value)
/* transfer register address to RAP */
- SKMCA_WRITEB(CTRL_RESET_OFF | CTRL_RW_WRITE | CTRL_ADR_RAP,
- priv->ctrladdr);
- SKMCA_WRITEW(addr, priv->ioregaddr);
- SKMCA_WRITEB(IOCMD_GO, priv->cmdaddr);
+ writeb(CTRL_RESET_OFF | CTRL_RW_WRITE | CTRL_ADR_RAP, priv->ctrladdr);
+ writew(addr, priv->ioregaddr);
+ writeb(IOCMD_GO, priv->cmdaddr);
udelay(1);
WaitLANCE(dev);
/* transfer data to register */
- SKMCA_WRITEB(CTRL_RESET_OFF | CTRL_RW_WRITE | CTRL_ADR_DATA,
- priv->ctrladdr);
- SKMCA_WRITEW(value, priv->ioregaddr);
- SKMCA_WRITEB(IOCMD_GO, priv->cmdaddr);
+ writeb(CTRL_RESET_OFF | CTRL_RW_WRITE | CTRL_ADR_DATA, priv->ctrladdr);
+ writew(value, priv->ioregaddr);
+ writeb(IOCMD_GO, priv->cmdaddr);
udelay(1);
WaitLANCE(dev);
@@ -288,7 +287,7 @@ static void SetLANCE(struct net_device *dev, u16 addr, u16 value)
static u16 GetLANCE(struct net_device *dev, u16 addr)
{
- skmca_priv *priv = (skmca_priv *) dev->priv;
+ skmca_priv *priv = netdev_priv(dev);
unsigned long flags;
unsigned int res;
@@ -302,21 +301,19 @@ static u16 GetLANCE(struct net_device *dev, u16 addr)
/* transfer register address to RAP */
- SKMCA_WRITEB(CTRL_RESET_OFF | CTRL_RW_WRITE | CTRL_ADR_RAP,
- priv->ctrladdr);
- SKMCA_WRITEW(addr, priv->ioregaddr);
- SKMCA_WRITEB(IOCMD_GO, priv->cmdaddr);
+ writeb(CTRL_RESET_OFF | CTRL_RW_WRITE | CTRL_ADR_RAP, priv->ctrladdr);
+ writew(addr, priv->ioregaddr);
+ writeb(IOCMD_GO, priv->cmdaddr);
udelay(1);
WaitLANCE(dev);
/* transfer data from register */
- SKMCA_WRITEB(CTRL_RESET_OFF | CTRL_RW_READ | CTRL_ADR_DATA,
- priv->ctrladdr);
- SKMCA_WRITEB(IOCMD_GO, priv->cmdaddr);
+ writeb(CTRL_RESET_OFF | CTRL_RW_READ | CTRL_ADR_DATA, priv->ctrladdr);
+ writeb(IOCMD_GO, priv->cmdaddr);
udelay(1);
WaitLANCE(dev);
- res = SKMCA_READW(priv->ioregaddr);
+ res = readw(priv->ioregaddr);
/* reenable interrupts */
@@ -329,6 +326,7 @@ static u16 GetLANCE(struct net_device *dev, u16 addr)
static void InitDscrs(struct net_device *dev)
{
+ skmca_priv *priv = netdev_priv(dev);
u32 bufaddr;
/* Set up Tx descriptors. The board has only 16K RAM so bits 16..23
@@ -344,11 +342,10 @@ static void InitDscrs(struct net_device *dev)
descr.Flags = 0;
descr.Len = 0xf000;
descr.Status = 0;
- SKMCA_TOIO(dev->mem_start + RAM_TXBASE +
+ memcpy_toio(priv->base + RAM_TXBASE +
(z * sizeof(LANCE_TxDescr)), &descr,
sizeof(LANCE_TxDescr));
- SKMCA_SETIO(dev->mem_start + bufaddr, 0,
- RAM_BUFSIZE);
+ memset_io(priv->base + bufaddr, 0, RAM_BUFSIZE);
bufaddr += RAM_BUFSIZE;
}
}
@@ -364,11 +361,10 @@ static void InitDscrs(struct net_device *dev)
descr.Flags = RXDSCR_FLAGS_OWN;
descr.MaxLen = -RAM_BUFSIZE;
descr.Len = 0;
- SKMCA_TOIO(dev->mem_start + RAM_RXBASE +
+ memcpy_toio(priv->base + RAM_RXBASE +
(z * sizeof(LANCE_RxDescr)), &descr,
sizeof(LANCE_RxDescr));
- SKMCA_SETIO(dev->mem_start + bufaddr, 0,
- RAM_BUFSIZE);
+ memset_io(priv->base + bufaddr, 0, RAM_BUFSIZE);
bufaddr += RAM_BUFSIZE;
}
}
@@ -425,7 +421,7 @@ static unsigned int GetHash(char *address)
static void InitLANCE(struct net_device *dev)
{
- skmca_priv *priv = (skmca_priv *) dev->priv;
+ skmca_priv *priv = netdev_priv(dev);
/* build up descriptors. */
@@ -478,6 +474,7 @@ static void StopLANCE(struct net_device *dev)
static void InitBoard(struct net_device *dev)
{
+ skmca_priv *priv = netdev_priv(dev);
LANCE_InitBlock block;
/* Lay out the shared RAM - first we create the init block for the LANCE.
@@ -492,7 +489,7 @@ static void InitBoard(struct net_device *dev)
block.RdrP = (RAM_RXBASE & 0xffffff) | (LRXCOUNT << 29);
block.TdrP = (RAM_TXBASE & 0xffffff) | (LTXCOUNT << 29);
- SKMCA_TOIO(dev->mem_start + RAM_INITBASE, &block, sizeof(block));
+ memcpy_toio(priv->base + RAM_INITBASE, &block, sizeof(block));
/* initialize LANCE. Implicitly sets up other structures in RAM. */
@@ -572,7 +569,7 @@ static u16 irqstart_handler(struct net_device *dev, u16 oldcsr0)
static u16 irqmiss_handler(struct net_device *dev, u16 oldcsr0)
{
- skmca_priv *priv = (skmca_priv *) dev->priv;
+ skmca_priv *priv = netdev_priv(dev);
/* update statistics */
@@ -588,7 +585,7 @@ static u16 irqmiss_handler(struct net_device *dev, u16 oldcsr0)
static u16 irqrx_handler(struct net_device *dev, u16 oldcsr0)
{
- skmca_priv *priv = (skmca_priv *) dev->priv;
+ skmca_priv *priv = netdev_priv(dev);
LANCE_RxDescr descr;
unsigned int descraddr;
@@ -597,7 +594,7 @@ static u16 irqrx_handler(struct net_device *dev, u16 oldcsr0)
descraddr = RAM_RXBASE + (priv->nextrx * sizeof(LANCE_RxDescr));
while (1) {
/* read descriptor */
- SKMCA_FROMIO(&descr, dev->mem_start + descraddr,
+ memcpy_fromio(&descr, priv->base + descraddr,
sizeof(LANCE_RxDescr));
/* if we reach a descriptor we do not own, we're done */
@@ -629,8 +626,8 @@ static u16 irqrx_handler(struct net_device *dev, u16 oldcsr0)
if (skb == NULL)
priv->stat.rx_dropped++;
else {
- SKMCA_FROMIO(skb_put(skb, descr.Len),
- dev->mem_start +
+ memcpy_fromio(skb_put(skb, descr.Len),
+ priv->base +
descr.LowAddr, descr.Len);
skb->dev = dev;
skb->protocol = eth_type_trans(skb, dev);
@@ -647,7 +644,7 @@ static u16 irqrx_handler(struct net_device *dev, u16 oldcsr0)
descr.Flags |= RXDSCR_FLAGS_OWN;
/* update descriptor in shared RAM */
- SKMCA_TOIO(dev->mem_start + descraddr, &descr,
+ memcpy_toio(priv->base + descraddr, &descr,
sizeof(LANCE_RxDescr));
/* go to next descriptor */
@@ -669,7 +666,7 @@ static u16 irqrx_handler(struct net_device *dev, u16 oldcsr0)
static u16 irqtx_handler(struct net_device *dev, u16 oldcsr0)
{
- skmca_priv *priv = (skmca_priv *) dev->priv;
+ skmca_priv *priv = netdev_priv(dev);
LANCE_TxDescr descr;
unsigned int descraddr;
@@ -679,7 +676,7 @@ static u16 irqtx_handler(struct net_device *dev, u16 oldcsr0)
RAM_TXBASE + (priv->nexttxdone * sizeof(LANCE_TxDescr));
while (priv->txbusy > 0) {
/* read descriptor */
- SKMCA_FROMIO(&descr, dev->mem_start + descraddr,
+ memcpy_fromio(&descr, priv->base + descraddr,
sizeof(LANCE_TxDescr));
/* if the LANCE still owns this one, we've worked out all sent packets */
@@ -798,9 +795,7 @@ static int skmca_getinfo(char *buf, int slot, void *d)
if (dev == NULL)
return len;
- if (dev->priv == NULL)
- return len;
- priv = (skmca_priv *) dev->priv;
+ priv = netdev_priv(dev);
/* print info */
@@ -825,7 +820,7 @@ static int skmca_getinfo(char *buf, int slot, void *d)
static int skmca_open(struct net_device *dev)
{
int result;
- skmca_priv *priv = (skmca_priv *) dev->priv;
+ skmca_priv *priv = netdev_priv(dev);
/* register resources - only necessary for IRQ */
result =
@@ -868,7 +863,7 @@ static int skmca_close(struct net_device *dev)
static int skmca_tx(struct sk_buff *skb, struct net_device *dev)
{
- skmca_priv *priv = (skmca_priv *) dev->priv;
+ skmca_priv *priv = netdev_priv(dev);
LANCE_TxDescr descr;
unsigned int address;
int tmplen, retval = 0;
@@ -894,8 +889,7 @@ static int skmca_tx(struct sk_buff *skb, struct net_device *dev)
/* get TX descriptor */
address = RAM_TXBASE + (priv->nexttxput * sizeof(LANCE_TxDescr));
- SKMCA_FROMIO(&descr, dev->mem_start + address,
- sizeof(LANCE_TxDescr));
+ memcpy_fromio(&descr, priv->base + address, sizeof(LANCE_TxDescr));
/* enter packet length as 2s complement - assure minimum length */
tmplen = skb->len;
@@ -911,14 +905,14 @@ static int skmca_tx(struct sk_buff *skb, struct net_device *dev)
unsigned int destoffs = 0, l = strlen(fill);
while (destoffs < tmplen) {
- SKMCA_TOIO(dev->mem_start + descr.LowAddr +
+ memcpy_toio(priv->base + descr.LowAddr +
destoffs, fill, l);
destoffs += l;
}
}
/* do the real data copying */
- SKMCA_TOIO(dev->mem_start + descr.LowAddr, skb->data, skb->len);
+ memcpy_toio(priv->base + descr.LowAddr, skb->data, skb->len);
/* hand descriptor over to LANCE - this is the first and last chunk */
descr.Flags =
@@ -945,8 +939,7 @@ static int skmca_tx(struct sk_buff *skb, struct net_device *dev)
netif_stop_queue(dev);
/* write descriptor back to RAM */
- SKMCA_TOIO(dev->mem_start + address, &descr,
- sizeof(LANCE_TxDescr));
+ memcpy_toio(priv->base + address, &descr, sizeof(LANCE_TxDescr));
/* if no descriptors were active, give the LANCE a hint to read it
immediately */
@@ -967,7 +960,7 @@ static int skmca_tx(struct sk_buff *skb, struct net_device *dev)
static struct net_device_stats *skmca_stats(struct net_device *dev)
{
- skmca_priv *priv = (skmca_priv *) dev->priv;
+ skmca_priv *priv = netdev_priv(dev);
return &(priv->stat);
}
@@ -977,13 +970,14 @@ static struct net_device_stats *skmca_stats(struct net_device *dev)
static void skmca_set_multicast_list(struct net_device *dev)
{
+ skmca_priv *priv = netdev_priv(dev);
LANCE_InitBlock block;
/* first stop the LANCE... */
StopLANCE(dev);
/* ...then modify the initialization block... */
- SKMCA_FROMIO(&block, dev->mem_start + RAM_INITBASE, sizeof(block));
+ memcpy_fromio(&block, priv->base + RAM_INITBASE, sizeof(block));
if (dev->flags & IFF_PROMISC)
block.Mode |= LANCE_INIT_PROM;
else
@@ -1003,7 +997,7 @@ static void skmca_set_multicast_list(struct net_device *dev)
}
}
- SKMCA_TOIO(dev->mem_start + RAM_INITBASE, &block, sizeof(block));
+ memcpy_toio(priv->base + RAM_INITBASE, &block, sizeof(block));
/* ...then reinit LANCE with the correct flags */
InitLANCE(dev);
@@ -1017,10 +1011,11 @@ static int startslot; /* counts through slots when probing multiple devices */
static void cleanup_card(struct net_device *dev)
{
- skmca_priv *priv = dev->priv;
+ skmca_priv *priv = netdev_priv(dev);
DeinitBoard(dev);
if (dev->irq != 0)
free_irq(dev->irq, dev);
+ iounmap(priv->base);
mca_mark_as_unused(priv->slot);
mca_set_adapter_procfn(priv->slot, NULL, NULL);
}
@@ -1104,13 +1099,20 @@ struct net_device * __init skmca_probe(int unit)
printk("%s: SKNet %s adapter found in slot %d\n", dev->name,
junior ? "Junior MC2" : "MC2+", slot + 1);
- /* allocate structure */
- priv = dev->priv;
+ priv = netdev_priv(dev);
+ priv->base = ioremap(base, 0x4000);
+ if (!priv->base) {
+ mca_set_adapter_procfn(slot, NULL, NULL);
+ mca_mark_as_unused(slot);
+ free_netdev(dev);
+ return ERR_PTR(-ENOMEM);
+ }
+
priv->slot = slot;
- priv->macbase = base + 0x3fc0;
- priv->ioregaddr = base + 0x3ff0;
- priv->ctrladdr = base + 0x3ff2;
- priv->cmdaddr = base + 0x3ff3;
+ priv->macbase = priv->base + 0x3fc0;
+ priv->ioregaddr = priv->base + 0x3ff0;
+ priv->ctrladdr = priv->base + 0x3ff2;
+ priv->cmdaddr = priv->base + 0x3ff3;
priv->medium = medium;
memset(&priv->stat, 0, sizeof(struct net_device_stats));
spin_lock_init(&priv->lock);
@@ -1147,7 +1149,7 @@ struct net_device * __init skmca_probe(int unit)
/* copy out MAC address */
for (i = 0; i < 6; i++)
- dev->dev_addr[i] = SKMCA_READB(priv->macbase + (i << 1));
+ dev->dev_addr[i] = readb(priv->macbase + (i << 1));
/* print config */
printk("%s: IRQ %d, memory %#lx-%#lx, "
diff --git a/drivers/net/sk_mca.h b/drivers/net/sk_mca.h
index acf21be7bde39..7e7c995827460 100644
--- a/drivers/net/sk_mca.h
+++ b/drivers/net/sk_mca.h
@@ -5,16 +5,6 @@
#ifdef _SK_MCA_DRIVER_
-/* version-dependent functions/structures */
-
-#define SKMCA_READB(addr) isa_readb(addr)
-#define SKMCA_READW(addr) isa_readw(addr)
-#define SKMCA_WRITEB(data, addr) isa_writeb(data, addr)
-#define SKMCA_WRITEW(data, addr) isa_writew(data, addr)
-#define SKMCA_TOIO(dest, src, len) isa_memcpy_toio(dest, src, len)
-#define SKMCA_FROMIO(dest, src, len) isa_memcpy_fromio(dest, src, len)
-#define SKMCA_SETIO(dest, val, len) isa_memset_io(dest, val, len)
-
/* Adapter ID's */
#define SKNET_MCA_ID 0x6afd
#define SKNET_JUNIOR_MCA_ID 0x6be9
@@ -29,10 +19,11 @@ typedef enum { Media_10Base2, Media_10BaseT,
/* private structure */
typedef struct {
unsigned int slot; /* MCA-Slot-# */
- unsigned int macbase; /* base address of MAC address PROM */
- unsigned int ioregaddr; /* address of I/O-register (Lo) */
- unsigned int ctrladdr; /* address of control/stat register */
- unsigned int cmdaddr; /* address of I/O-command register */
+ void __iomem *base;
+ void __iomem *macbase; /* base address of MAC address PROM */
+ void __iomem *ioregaddr;/* address of I/O-register (Lo) */
+ void __iomem *ctrladdr; /* address of control/stat register */
+ void __iomem *cmdaddr; /* address of I/O-command register */
int nextrx; /* index of next RX descriptor to
be read */
int nexttxput; /* index of next free TX descriptor */
diff --git a/drivers/net/slhc.c b/drivers/net/slhc.c
index a3521c2773a5d..c6fbb1ede0ed2 100644
--- a/drivers/net/slhc.c
+++ b/drivers/net/slhc.c
@@ -693,33 +693,6 @@ slhc_toss(struct slcompress *comp)
}
-void slhc_i_status(struct slcompress *comp)
-{
- if (comp != NULLSLCOMPR) {
- printk("\t%d Cmp, %d Uncmp, %d Bad, %d Tossed\n",
- comp->sls_i_compressed,
- comp->sls_i_uncompressed,
- comp->sls_i_error,
- comp->sls_i_tossed);
- }
-}
-
-
-void slhc_o_status(struct slcompress *comp)
-{
- if (comp != NULLSLCOMPR) {
- printk("\t%d Cmp, %d Uncmp, %d AsIs, %d NotTCP\n",
- comp->sls_o_compressed,
- comp->sls_o_uncompressed,
- comp->sls_o_tcp,
- comp->sls_o_nontcp);
- printk("\t%10d Searches, %10d Misses\n",
- comp->sls_o_searches,
- comp->sls_o_misses);
- }
-}
-
-/* Should this be surrounded with "#ifdef CONFIG_MODULES" ? */
/* VJ header compression */
EXPORT_SYMBOL(slhc_init);
EXPORT_SYMBOL(slhc_free);
diff --git a/drivers/net/smc-mca.c b/drivers/net/smc-mca.c
index b7c5a4cdb6aa1..990201f42ba04 100644
--- a/drivers/net/smc-mca.c
+++ b/drivers/net/smc-mca.c
@@ -310,9 +310,13 @@ int __init ultramca_probe(struct device *gen_dev)
ei_status.rx_start_page = START_PG + TX_PAGES;
ei_status.stop_page = num_pages;
- ei_status.rmem_start = dev->mem_start + TX_PAGES * 256;
- dev->mem_end = ei_status.rmem_end =
- dev->mem_start + (ei_status.stop_page - START_PG) * 256;
+ ei_status.mem = ioremap(dev->mem_start, (ei_status.stop_page - START_PG) * 256);
+ if (!ei_status.mem) {
+ rc = -ENOMEM;
+ goto err_release_region;
+ }
+
+ dev->mem_end = dev->mem_start + (ei_status.stop_page - START_PG) * 256;
printk(", IRQ %d memory %#lx-%#lx.\n",
dev->irq, dev->mem_start, dev->mem_end - 1);
@@ -334,10 +338,12 @@ int __init ultramca_probe(struct device *gen_dev)
rc = register_netdev(dev);
if (rc)
- goto err_release_region;
+ goto err_unmap;
return 0;
+err_unmap:
+ iounmap(ei_status.mem);
err_release_region:
release_region(ioaddr, ULTRA_IO_EXTENT);
err_unclaim:
@@ -395,13 +401,13 @@ static void ultramca_reset_8390(struct net_device *dev)
static void ultramca_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
{
- unsigned long hdr_start = dev->mem_start + ((ring_page - START_PG) << 8);
+ void __iomem *hdr_start = ei_status.mem + ((ring_page - START_PG) << 8);
#ifdef notdef
/* Officially this is what we are doing, but the readl() is faster */
- isa_memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
+ memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
#else
- ((unsigned int*)hdr)[0] = isa_readl(hdr_start);
+ ((unsigned int*)hdr)[0] = readl(hdr_start);
#endif
}
@@ -411,17 +417,17 @@ static void ultramca_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *
static void ultramca_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
{
- unsigned long xfer_start = dev->mem_start + ring_offset - (START_PG << 8);
+ void __iomem *xfer_start = ei_status.mem + ring_offset - START_PG * 256;
- if (xfer_start + count > ei_status.rmem_end) {
+ if (ring_offset + count > ei_status.stop_page * 256) {
/* We must wrap the input move. */
- int semi_count = ei_status.rmem_end - xfer_start;
- isa_memcpy_fromio(skb->data, xfer_start, semi_count);
+ int semi_count = ei_status.stop_page * 256 - ring_offset;
+ memcpy_fromio(skb->data, xfer_start, semi_count);
count -= semi_count;
- isa_memcpy_fromio(skb->data + semi_count, ei_status.rmem_start, count);
+ memcpy_fromio(skb->data + semi_count, ei_status.mem + TX_PAGES * 256, count);
} else {
/* Packet is in one chunk -- we can copy + cksum. */
- isa_eth_io_copy_and_sum(skb, xfer_start, count, 0);
+ eth_io_copy_and_sum(skb, xfer_start, count, 0);
}
}
@@ -429,9 +435,9 @@ static void ultramca_block_input(struct net_device *dev, int count, struct sk_bu
static void ultramca_block_output(struct net_device *dev, int count, const unsigned char *buf,
int start_page)
{
- unsigned long shmem = dev->mem_start + ((start_page - START_PG) << 8);
+ void __iomem *shmem = ei_status.mem + ((start_page - START_PG) << 8);
- isa_memcpy_toio(shmem, buf, count);
+ memcpy_toio(shmem, buf, count);
}
static int ultramca_close_card(struct net_device *dev)
@@ -466,6 +472,7 @@ static int ultramca_remove(struct device *gen_dev)
unregister_netdev(dev);
mca_device_set_claim(mca_dev, 0);
release_region(ioaddr, ULTRA_IO_EXTENT);
+ iounmap(ei_status.mem);
free_netdev(dev);
}
return 0;
diff --git a/drivers/net/smc-ultra.c b/drivers/net/smc-ultra.c
index a29ac20969231..b564c677c6d25 100644
--- a/drivers/net/smc-ultra.c
+++ b/drivers/net/smc-ultra.c
@@ -176,6 +176,7 @@ static void cleanup_card(struct net_device *dev)
pnp_device_detach(idev);
#endif
release_region(dev->base_addr - ULTRA_NIC_OFFSET, ULTRA_IO_EXTENT);
+ iounmap(ei_status.mem);
}
#ifndef MODULE
@@ -294,9 +295,14 @@ static int __init ultra_probe1(struct net_device *dev, int ioaddr)
ei_status.rx_start_page = START_PG + TX_PAGES;
ei_status.stop_page = num_pages;
- ei_status.rmem_start = dev->mem_start + TX_PAGES*256;
- dev->mem_end = ei_status.rmem_end
- = dev->mem_start + (ei_status.stop_page - START_PG)*256;
+ ei_status.mem = ioremap(dev->mem_start, (ei_status.stop_page - START_PG)*256);
+ if (!ei_status.mem) {
+ printk(", failed to ioremap.\n");
+ retval = -ENOMEM;
+ goto out;
+ }
+
+ dev->mem_end = dev->mem_start + (ei_status.stop_page - START_PG)*256;
if (piomode) {
printk(",%s IRQ %d programmed-I/O mode.\n",
@@ -430,16 +436,16 @@ ultra_reset_8390(struct net_device *dev)
static void
ultra_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
{
- unsigned long hdr_start = dev->mem_start + ((ring_page - START_PG)<<8);
+ void __iomem *hdr_start = ei_status.mem + ((ring_page - START_PG)<<8);
outb(ULTRA_MEMENB, dev->base_addr - ULTRA_NIC_OFFSET); /* shmem on */
#ifdef __BIG_ENDIAN
/* Officially this is what we are doing, but the readl() is faster */
/* unfortunately it isn't endian aware of the struct */
- isa_memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
+ memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
hdr->count = le16_to_cpu(hdr->count);
#else
- ((unsigned int*)hdr)[0] = isa_readl(hdr_start);
+ ((unsigned int*)hdr)[0] = readl(hdr_start);
#endif
outb(0x00, dev->base_addr - ULTRA_NIC_OFFSET); /* shmem off */
}
@@ -450,20 +456,20 @@ ultra_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_p
static void
ultra_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
{
- unsigned long xfer_start = dev->mem_start + ring_offset - (START_PG<<8);
+ void __iomem *xfer_start = ei_status.mem + ring_offset - (START_PG<<8);
/* Enable shared memory. */
outb(ULTRA_MEMENB, dev->base_addr - ULTRA_NIC_OFFSET);
- if (xfer_start + count > ei_status.rmem_end) {
+ if (ring_offset + count > ei_status.stop_page*256) {
/* We must wrap the input move. */
- int semi_count = ei_status.rmem_end - xfer_start;
- isa_memcpy_fromio(skb->data, xfer_start, semi_count);
+ int semi_count = ei_status.stop_page*256 - ring_offset;
+ memcpy_fromio(skb->data, xfer_start, semi_count);
count -= semi_count;
- isa_memcpy_fromio(skb->data + semi_count, ei_status.rmem_start, count);
+ memcpy_fromio(skb->data + semi_count, ei_status.mem + TX_PAGES * 256, count);
} else {
/* Packet is in one chunk -- we can copy + cksum. */
- isa_eth_io_copy_and_sum(skb, xfer_start, count, 0);
+ eth_io_copy_and_sum(skb, xfer_start, count, 0);
}
outb(0x00, dev->base_addr - ULTRA_NIC_OFFSET); /* Disable memory. */
@@ -473,12 +479,12 @@ static void
ultra_block_output(struct net_device *dev, int count, const unsigned char *buf,
int start_page)
{
- unsigned long shmem = dev->mem_start + ((start_page - START_PG)<<8);
+ void __iomem *shmem = ei_status.mem + ((start_page - START_PG)<<8);
/* Enable shared memory. */
outb(ULTRA_MEMENB, dev->base_addr - ULTRA_NIC_OFFSET);
- isa_memcpy_toio(shmem, buf, count);
+ memcpy_toio(shmem, buf, count);
outb(0x00, dev->base_addr - ULTRA_NIC_OFFSET); /* Disable memory. */
}
diff --git a/drivers/net/smc-ultra32.c b/drivers/net/smc-ultra32.c
index 8080a37670d6f..b3e397d7ca858 100644
--- a/drivers/net/smc-ultra32.c
+++ b/drivers/net/smc-ultra32.c
@@ -104,6 +104,7 @@ static void cleanup_card(struct net_device *dev)
int ioaddr = dev->base_addr - ULTRA32_NIC_OFFSET;
/* NB: ultra32_close_card() does free_irq */
release_region(ioaddr, ULTRA32_IO_EXTENT);
+ iounmap(ei_status.mem);
}
/* Probe for the Ultra32. This looks like a 8013 with the station
@@ -259,8 +260,13 @@ static int __init ultra32_probe1(struct net_device *dev, int ioaddr)
/* All Ultra32 cards have 32KB memory with an 8KB window. */
ei_status.stop_page = 128;
- ei_status.rmem_start = dev->mem_start + TX_PAGES*256;
- dev->mem_end = ei_status.rmem_end = dev->mem_start + 0x1fff;
+ ei_status.mem = ioremap(dev->mem_start, 0x2000);
+ if (!ei_status.mem) {
+ printk(", failed to ioremap.\n");
+ retval = -ENOMEM;
+ goto out;
+ }
+ dev->mem_end = dev->mem_start + 0x1fff;
printk(", IRQ %d, 32KB memory, 8KB window at 0x%lx-0x%lx.\n",
dev->irq, dev->mem_start, dev->mem_end);
@@ -345,7 +351,7 @@ static void ultra32_get_8390_hdr(struct net_device *dev,
struct e8390_pkt_hdr *hdr,
int ring_page)
{
- unsigned long hdr_start = dev->mem_start + ((ring_page & 0x1f) << 8);
+ void __iomem *hdr_start = ei_status.mem + ((ring_page & 0x1f) << 8);
unsigned int RamReg = dev->base_addr - ULTRA32_NIC_OFFSET + ULTRA32_CFG3;
/* Select correct 8KB Window. */
@@ -354,10 +360,10 @@ static void ultra32_get_8390_hdr(struct net_device *dev,
#ifdef __BIG_ENDIAN
/* Officially this is what we are doing, but the readl() is faster */
/* unfortunately it isn't endian aware of the struct */
- isa_memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
+ memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
hdr->count = le16_to_cpu(hdr->count);
#else
- ((unsigned int*)hdr)[0] = isa_readl(hdr_start);
+ ((unsigned int*)hdr)[0] = readl(hdr_start);
#endif
}
@@ -371,26 +377,26 @@ static void ultra32_block_input(struct net_device *dev,
struct sk_buff *skb,
int ring_offset)
{
- unsigned long xfer_start = dev->mem_start + (ring_offset & 0x1fff);
+ void __iomem *xfer_start = ei_status.mem + (ring_offset & 0x1fff);
unsigned int RamReg = dev->base_addr - ULTRA32_NIC_OFFSET + ULTRA32_CFG3;
if ((ring_offset & ~0x1fff) != ((ring_offset + count - 1) & ~0x1fff)) {
int semi_count = 8192 - (ring_offset & 0x1FFF);
- isa_memcpy_fromio(skb->data, xfer_start, semi_count);
+ memcpy_fromio(skb->data, xfer_start, semi_count);
count -= semi_count;
if (ring_offset < 96*256) {
/* Select next 8KB Window. */
ring_offset += semi_count;
outb(ei_status.reg0 | ((ring_offset & 0x6000) >> 13), RamReg);
- isa_memcpy_fromio(skb->data + semi_count, dev->mem_start, count);
+ memcpy_fromio(skb->data + semi_count, ei_status.mem, count);
} else {
/* Select first 8KB Window. */
outb(ei_status.reg0, RamReg);
- isa_memcpy_fromio(skb->data + semi_count, ei_status.rmem_start, count);
+ memcpy_fromio(skb->data + semi_count, ei_status.mem + TX_PAGES * 256, count);
}
} else {
/* Packet is in one chunk -- we can copy + cksum. */
- isa_eth_io_copy_and_sum(skb, xfer_start, count, 0);
+ eth_io_copy_and_sum(skb, xfer_start, count, 0);
}
}
@@ -399,13 +405,13 @@ static void ultra32_block_output(struct net_device *dev,
const unsigned char *buf,
int start_page)
{
- unsigned long xfer_start = dev->mem_start + (start_page<<8);
+ void __iomem *xfer_start = ei_status.mem + (start_page<<8);
unsigned int RamReg = dev->base_addr - ULTRA32_NIC_OFFSET + ULTRA32_CFG3;
/* Select first 8KB Window. */
outb(ei_status.reg0, RamReg);
- isa_memcpy_toio(xfer_start, buf, count);
+ memcpy_toio(xfer_start, buf, count);
}
#ifdef MODULE
diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c
index fb9935b670ac2..6766bacbb199d 100644
--- a/drivers/net/smc91x.c
+++ b/drivers/net/smc91x.c
@@ -210,10 +210,15 @@ struct smc_local {
spinlock_t lock;
+#ifdef SMC_CAN_USE_DATACS
+ u32 __iomem *datacs;
+#endif
+
#ifdef SMC_USE_PXA_DMA
/* DMA needs the physical address of the chip */
u_long physaddr;
#endif
+ void __iomem *base;
};
#if SMC_DEBUG > 0
@@ -307,8 +312,8 @@ static void PRINT_PKT(u_char *buf, int length)
*/
static void smc_reset(struct net_device *dev)
{
- unsigned long ioaddr = dev->base_addr;
struct smc_local *lp = netdev_priv(dev);
+ void __iomem *ioaddr = lp->base;
unsigned int ctl, cfg;
DBG(2, "%s: %s\n", dev->name, __FUNCTION__);
@@ -399,8 +404,8 @@ static void smc_reset(struct net_device *dev)
*/
static void smc_enable(struct net_device *dev)
{
- unsigned long ioaddr = dev->base_addr;
struct smc_local *lp = netdev_priv(dev);
+ void __iomem *ioaddr = lp->base;
int mask;
DBG(2, "%s: %s\n", dev->name, __FUNCTION__);
@@ -433,8 +438,8 @@ static void smc_enable(struct net_device *dev)
*/
static void smc_shutdown(struct net_device *dev)
{
- unsigned long ioaddr = dev->base_addr;
struct smc_local *lp = netdev_priv(dev);
+ void __iomem *ioaddr = lp->base;
DBG(2, "%s: %s\n", CARDNAME, __FUNCTION__);
@@ -462,7 +467,7 @@ static void smc_shutdown(struct net_device *dev)
static inline void smc_rcv(struct net_device *dev)
{
struct smc_local *lp = netdev_priv(dev);
- unsigned long ioaddr = dev->base_addr;
+ void __iomem *ioaddr = lp->base;
unsigned int packet_number, status, packet_len;
DBG(3, "%s: %s\n", dev->name, __FUNCTION__);
@@ -483,7 +488,19 @@ static inline void smc_rcv(struct net_device *dev)
dev->name, packet_number, status,
packet_len, packet_len);
- if (unlikely(status & RS_ERRORS)) {
+ back:
+ if (unlikely(packet_len < 6 || status & RS_ERRORS)) {
+ if (status & RS_TOOLONG && packet_len <= (1514 + 4 + 6)) {
+ /* accept VLAN packets */
+ status &= ~RS_TOOLONG;
+ goto back;
+ }
+ if (packet_len < 6) {
+ /* bloody hardware */
+ printk(KERN_ERR "%s: fubar (rxlen %u status %x\n",
+ dev->name, packet_len, status);
+ status |= RS_TOOSHORT;
+ }
SMC_WAIT_MMU_BUSY();
SMC_SET_MMU_CMD(MC_RELEASE);
lp->stats.rx_errors++;
@@ -508,7 +525,7 @@ static inline void smc_rcv(struct net_device *dev)
* (2 bytes, possibly containing the payload odd byte).
* Furthermore, we add 2 bytes to allow rounding up to
* multiple of 4 bytes on 32 bit buses.
- * Ence packet_len - 6 + 2 + 2 + 2.
+ * Hence packet_len - 6 + 2 + 2 + 2.
*/
skb = dev_alloc_skb(packet_len);
if (unlikely(skb == NULL)) {
@@ -596,7 +613,7 @@ static void smc_hardware_send_pkt(unsigned long data)
{
struct net_device *dev = (struct net_device *)data;
struct smc_local *lp = netdev_priv(dev);
- unsigned long ioaddr = dev->base_addr;
+ void __iomem *ioaddr = lp->base;
struct sk_buff *skb;
unsigned int packet_no, len;
unsigned char *buf;
@@ -680,7 +697,7 @@ done: if (!THROTTLE_TX_PKTS)
static int smc_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct smc_local *lp = netdev_priv(dev);
- unsigned long ioaddr = dev->base_addr;
+ void __iomem *ioaddr = lp->base;
unsigned int numPages, poll_count, status;
DBG(3, "%s: %s\n", dev->name, __FUNCTION__);
@@ -752,8 +769,8 @@ static int smc_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
*/
static void smc_tx(struct net_device *dev)
{
- unsigned long ioaddr = dev->base_addr;
struct smc_local *lp = netdev_priv(dev);
+ void __iomem *ioaddr = lp->base;
unsigned int saved_packet, packet_no, tx_status, pkt_len;
DBG(3, "%s: %s\n", dev->name, __FUNCTION__);
@@ -809,7 +826,8 @@ static void smc_tx(struct net_device *dev)
static void smc_mii_out(struct net_device *dev, unsigned int val, int bits)
{
- unsigned long ioaddr = dev->base_addr;
+ struct smc_local *lp = netdev_priv(dev);
+ void __iomem *ioaddr = lp->base;
unsigned int mii_reg, mask;
mii_reg = SMC_GET_MII() & ~(MII_MCLK | MII_MDOE | MII_MDO);
@@ -830,7 +848,8 @@ static void smc_mii_out(struct net_device *dev, unsigned int val, int bits)
static unsigned int smc_mii_in(struct net_device *dev, int bits)
{
- unsigned long ioaddr = dev->base_addr;
+ struct smc_local *lp = netdev_priv(dev);
+ void __iomem *ioaddr = lp->base;
unsigned int mii_reg, mask, val;
mii_reg = SMC_GET_MII() & ~(MII_MCLK | MII_MDOE | MII_MDO);
@@ -854,7 +873,8 @@ static unsigned int smc_mii_in(struct net_device *dev, int bits)
*/
static int smc_phy_read(struct net_device *dev, int phyaddr, int phyreg)
{
- unsigned long ioaddr = dev->base_addr;
+ struct smc_local *lp = netdev_priv(dev);
+ void __iomem *ioaddr = lp->base;
unsigned int phydata;
SMC_SELECT_BANK(3);
@@ -884,7 +904,8 @@ static int smc_phy_read(struct net_device *dev, int phyaddr, int phyreg)
static void smc_phy_write(struct net_device *dev, int phyaddr, int phyreg,
int phydata)
{
- unsigned long ioaddr = dev->base_addr;
+ struct smc_local *lp = netdev_priv(dev);
+ void __iomem *ioaddr = lp->base;
SMC_SELECT_BANK(3);
@@ -946,7 +967,7 @@ static void smc_phy_detect(struct net_device *dev)
static int smc_phy_fixed(struct net_device *dev)
{
struct smc_local *lp = netdev_priv(dev);
- unsigned long ioaddr = dev->base_addr;
+ void __iomem *ioaddr = lp->base;
int phyaddr = lp->mii.phy_id;
int bmcr, cfg1;
@@ -1017,13 +1038,29 @@ static int smc_phy_reset(struct net_device *dev, int phy)
/*
* smc_phy_powerdown - powerdown phy
* @dev: net device
- * @phy: phy address
*
* Power down the specified PHY
*/
-static void smc_phy_powerdown(struct net_device *dev, int phy)
+static void smc_phy_powerdown(struct net_device *dev)
{
+ struct smc_local *lp = netdev_priv(dev);
unsigned int bmcr;
+ int phy = lp->mii.phy_id;
+
+ if (lp->phy_type == 0)
+ return;
+
+ /* We need to ensure that no calls to smc_phy_configure are
+ pending.
+
+ flush_scheduled_work() cannot be called because we are
+ running with the netlink semaphore held (from
+ devinet_ioctl()) and the pending work queue contains
+ linkwatch_event() (scheduled by netif_carrier_off()
+ above). linkwatch_event() also wants the netlink semaphore.
+ */
+ while(lp->work_pending)
+ schedule();
bmcr = smc_phy_read(dev, phy, MII_BMCR);
smc_phy_write(dev, phy, MII_BMCR, bmcr | BMCR_PDOWN);
@@ -1040,7 +1077,7 @@ static void smc_phy_powerdown(struct net_device *dev, int phy)
static void smc_phy_check_media(struct net_device *dev, int init)
{
struct smc_local *lp = netdev_priv(dev);
- unsigned long ioaddr = dev->base_addr;
+ void __iomem *ioaddr = lp->base;
if (mii_check_media(&lp->mii, netif_msg_link(lp), init)) {
/* duplex state has changed */
@@ -1068,7 +1105,7 @@ static void smc_phy_configure(void *data)
{
struct net_device *dev = data;
struct smc_local *lp = netdev_priv(dev);
- unsigned long ioaddr = dev->base_addr;
+ void __iomem *ioaddr = lp->base;
int phyaddr = lp->mii.phy_id;
int my_phy_caps; /* My PHY capabilities */
int my_ad_caps; /* My Advertised capabilities */
@@ -1193,7 +1230,7 @@ static void smc_phy_interrupt(struct net_device *dev)
static void smc_10bt_check_media(struct net_device *dev, int init)
{
struct smc_local *lp = netdev_priv(dev);
- unsigned long ioaddr = dev->base_addr;
+ void __iomem *ioaddr = lp->base;
unsigned int old_carrier, new_carrier;
old_carrier = netif_carrier_ok(dev) ? 1 : 0;
@@ -1216,7 +1253,8 @@ static void smc_10bt_check_media(struct net_device *dev, int init)
static void smc_eph_interrupt(struct net_device *dev)
{
- unsigned long ioaddr = dev->base_addr;
+ struct smc_local *lp = netdev_priv(dev);
+ void __iomem *ioaddr = lp->base;
unsigned int ctl;
smc_10bt_check_media(dev, 0);
@@ -1235,8 +1273,8 @@ static void smc_eph_interrupt(struct net_device *dev)
static irqreturn_t smc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
struct net_device *dev = dev_id;
- unsigned long ioaddr = dev->base_addr;
struct smc_local *lp = netdev_priv(dev);
+ void __iomem *ioaddr = lp->base;
int status, mask, timeout, card_stats;
int saved_pointer;
@@ -1350,7 +1388,7 @@ static void smc_poll_controller(struct net_device *dev)
static void smc_timeout(struct net_device *dev)
{
struct smc_local *lp = netdev_priv(dev);
- unsigned long ioaddr = dev->base_addr;
+ void __iomem *ioaddr = lp->base;
int status, mask, meminfo, fifo;
DBG(2, "%s: %s\n", dev->name, __FUNCTION__);
@@ -1394,7 +1432,7 @@ static void smc_timeout(struct net_device *dev)
static void smc_set_multicast_list(struct net_device *dev)
{
struct smc_local *lp = netdev_priv(dev);
- unsigned long ioaddr = dev->base_addr;
+ void __iomem *ioaddr = lp->base;
unsigned char multicast_table[8];
int update_multicast = 0;
@@ -1561,21 +1599,7 @@ static int smc_close(struct net_device *dev)
/* clear everything */
smc_shutdown(dev);
- if (lp->phy_type != 0) {
- /* We need to ensure that no calls to
- smc_phy_configure are pending.
-
- flush_scheduled_work() cannot be called because we
- are running with the netlink semaphore held (from
- devinet_ioctl()) and the pending work queue
- contains linkwatch_event() (scheduled by
- netif_carrier_off() above). linkwatch_event() also
- wants the netlink semaphore.
- */
- while(lp->work_pending)
- schedule();
- smc_phy_powerdown(dev, lp->mii.phy_id);
- }
+ smc_phy_powerdown(dev);
if (lp->pending_tx_skb) {
dev_kfree_skb(lp->pending_tx_skb);
@@ -1723,7 +1747,7 @@ static struct ethtool_ops smc_ethtool_ops = {
* I just deleted auto_irq.c, since it was never built...
* --jgarzik
*/
-static int __init smc_findirq(unsigned long ioaddr)
+static int __init smc_findirq(void __iomem *ioaddr)
{
int timeout = 20;
unsigned long cookie;
@@ -1796,7 +1820,7 @@ static int __init smc_findirq(unsigned long ioaddr)
* o actually GRAB the irq.
* o GRAB the region
*/
-static int __init smc_probe(struct net_device *dev, unsigned long ioaddr)
+static int __init smc_probe(struct net_device *dev, void __iomem *ioaddr)
{
struct smc_local *lp = netdev_priv(dev);
static int version_printed = 0;
@@ -1813,7 +1837,7 @@ static int __init smc_probe(struct net_device *dev, unsigned long ioaddr)
if ((val & 0xFF) == 0x33) {
printk(KERN_WARNING
"%s: Detected possible byte-swapped interface"
- " at IOADDR 0x%lx\n", CARDNAME, ioaddr);
+ " at IOADDR %p\n", CARDNAME, ioaddr);
}
retval = -ENODEV;
goto err_out;
@@ -1839,8 +1863,8 @@ static int __init smc_probe(struct net_device *dev, unsigned long ioaddr)
SMC_SELECT_BANK(1);
val = SMC_GET_BASE();
val = ((val & 0x1F00) >> 3) << SMC_IO_SHIFT;
- if ((ioaddr & ((PAGE_SIZE-1)<<SMC_IO_SHIFT)) != val) {
- printk("%s: IOADDR %lx doesn't match configuration (%x).\n",
+ if (((unsigned long)ioaddr & ((PAGE_SIZE-1)<<SMC_IO_SHIFT)) != val) { /*XXX: WTF? */
+ printk("%s: IOADDR %p doesn't match configuration (%x).\n",
CARDNAME, ioaddr, val);
}
@@ -1855,7 +1879,7 @@ static int __init smc_probe(struct net_device *dev, unsigned long ioaddr)
version_string = chip_ids[ (revision_register >> 4) & 0xF];
if (!version_string || (revision_register & 0xff00) != 0x3300) {
/* I don't recognize this chip, so... */
- printk("%s: IO 0x%lx: Unrecognized revision register 0x%04x"
+ printk("%s: IO %p: Unrecognized revision register 0x%04x"
", Contact author.\n", CARDNAME,
ioaddr, revision_register);
@@ -1868,7 +1892,8 @@ static int __init smc_probe(struct net_device *dev, unsigned long ioaddr)
printk("%s", version);
/* fill in some of the fields */
- dev->base_addr = ioaddr;
+ dev->base_addr = (unsigned long)ioaddr;
+ lp->base = ioaddr;
lp->version = revision_register & 0xff;
spin_lock_init(&lp->lock);
@@ -1974,9 +1999,9 @@ static int __init smc_probe(struct net_device *dev, unsigned long ioaddr)
retval = register_netdev(dev);
if (retval == 0) {
/* now, print out the card info, in a short format.. */
- printk("%s: %s (rev %d) at %#lx IRQ %d",
+ printk("%s: %s (rev %d) at %p IRQ %d",
dev->name, version_string, revision_register & 0x0f,
- dev->base_addr, dev->irq);
+ lp->base, dev->irq);
if (dev->dma != (unsigned char)-1)
printk(" DMA %d", dev->dma);
@@ -2012,16 +2037,21 @@ err_out:
return retval;
}
-static int smc_enable_device(unsigned long attrib_phys)
+static int smc_enable_device(struct platform_device *pdev)
{
unsigned long flags;
unsigned char ecor, ecsr;
- void *addr;
+ void __iomem *addr;
+ struct resource * res;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-attrib");
+ if (!res)
+ return 0;
/*
* Map the attribute space. This is overkill, but clean.
*/
- addr = ioremap(attrib_phys, ATTRIB_SIZE);
+ addr = ioremap(res->start, ATTRIB_SIZE);
if (!addr)
return -ENOMEM;
@@ -2069,6 +2099,62 @@ static int smc_enable_device(unsigned long attrib_phys)
return 0;
}
+static int smc_request_attrib(struct platform_device *pdev)
+{
+ struct resource * res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-attrib");
+
+ if (!res)
+ return 0;
+
+ if (!request_mem_region(res->start, ATTRIB_SIZE, CARDNAME))
+ return -EBUSY;
+
+ return 0;
+}
+
+static void smc_release_attrib(struct platform_device *pdev)
+{
+ struct resource * res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-attrib");
+
+ if (res)
+ release_mem_region(res->start, ATTRIB_SIZE);
+}
+
+#ifdef SMC_CAN_USE_DATACS
+static void smc_request_datacs(struct platform_device *pdev, struct net_device *ndev)
+{
+ struct resource * res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-data32");
+ struct smc_local *lp = netdev_priv(ndev);
+
+ if (!res)
+ return;
+
+ if(!request_mem_region(res->start, SMC_DATA_EXTENT, CARDNAME)) {
+ printk(KERN_INFO "%s: failed to request datacs memory region.\n", CARDNAME);
+ return;
+ }
+
+ lp->datacs = ioremap(res->start, SMC_DATA_EXTENT);
+}
+
+static void smc_release_datacs(struct platform_device *pdev, struct net_device *ndev)
+{
+ struct smc_local *lp = netdev_priv(ndev);
+ struct resource * res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-data32");
+
+ if (lp->datacs)
+ iounmap(lp->datacs);
+
+ lp->datacs = NULL;
+
+ if (res)
+ release_mem_region(res->start, SMC_DATA_EXTENT);
+}
+#else
+static void smc_request_datacs(struct platform_device *pdev, struct net_device *ndev) {}
+static void smc_release_datacs(struct platform_device *pdev, struct net_device *ndev) {}
+#endif
+
/*
* smc_init(void)
* Input parameters:
@@ -2084,20 +2170,20 @@ static int smc_drv_probe(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct net_device *ndev;
- struct resource *res, *ext = NULL;
- unsigned int *addr;
+ struct resource *res;
+ unsigned int __iomem *addr;
int ret;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-regs");
+ if (!res)
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
ret = -ENODEV;
goto out;
}
- /*
- * Request the regions.
- */
- if (!request_mem_region(res->start, SMC_IO_EXTENT, "smc91x")) {
+
+ if (!request_mem_region(res->start, SMC_IO_EXTENT, CARDNAME)) {
ret = -EBUSY;
goto out;
}
@@ -2106,7 +2192,7 @@ static int smc_drv_probe(struct device *dev)
if (!ndev) {
printk("%s: could not allocate device.\n", CARDNAME);
ret = -ENOMEM;
- goto release_1;
+ goto out_release_io;
}
SET_MODULE_OWNER(ndev);
SET_NETDEV_DEV(ndev, dev);
@@ -2114,42 +2200,26 @@ static int smc_drv_probe(struct device *dev)
ndev->dma = (unsigned char)-1;
ndev->irq = platform_get_irq(pdev, 0);
- ext = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- if (ext) {
- if (!request_mem_region(ext->start, ATTRIB_SIZE, ndev->name)) {
- ret = -EBUSY;
- goto release_1;
- }
-
+ ret = smc_request_attrib(pdev);
+ if (ret)
+ goto out_free_netdev;
#if defined(CONFIG_SA1100_ASSABET)
- NCR_0 |= NCR_ENET_OSC_EN;
+ NCR_0 |= NCR_ENET_OSC_EN;
#endif
-
- ret = smc_enable_device(ext->start);
- if (ret)
- goto release_both;
- }
+ ret = smc_enable_device(pdev);
+ if (ret)
+ goto out_release_attrib;
addr = ioremap(res->start, SMC_IO_EXTENT);
if (!addr) {
ret = -ENOMEM;
- goto release_both;
+ goto out_release_attrib;
}
dev_set_drvdata(dev, ndev);
- ret = smc_probe(ndev, (unsigned long)addr);
- if (ret != 0) {
- dev_set_drvdata(dev, NULL);
- iounmap(addr);
- release_both:
- if (ext)
- release_mem_region(ext->start, ATTRIB_SIZE);
- free_netdev(ndev);
- release_1:
- release_mem_region(res->start, SMC_IO_EXTENT);
- out:
- printk("%s: not found (%d).\n", CARDNAME, ret);
- }
+ ret = smc_probe(ndev, addr);
+ if (ret != 0)
+ goto out_iounmap;
#ifdef SMC_USE_PXA_DMA
else {
struct smc_local *lp = netdev_priv(ndev);
@@ -2157,6 +2227,22 @@ static int smc_drv_probe(struct device *dev)
}
#endif
+ smc_request_datacs(pdev, ndev);
+
+ return 0;
+
+ out_iounmap:
+ dev_set_drvdata(dev, NULL);
+ iounmap(addr);
+ out_release_attrib:
+ smc_release_attrib(pdev);
+ out_free_netdev:
+ free_netdev(ndev);
+ out_release_io:
+ release_mem_region(res->start, SMC_IO_EXTENT);
+ out:
+ printk("%s: not found (%d).\n", CARDNAME, ret);
+
return ret;
}
@@ -2164,6 +2250,7 @@ static int smc_drv_remove(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct net_device *ndev = dev_get_drvdata(dev);
+ struct smc_local *lp = netdev_priv(ndev);
struct resource *res;
dev_set_drvdata(dev, NULL);
@@ -2176,11 +2263,14 @@ static int smc_drv_remove(struct device *dev)
if (ndev->dma != (unsigned char)-1)
pxa_free_dma(ndev->dma);
#endif
- iounmap((void *)ndev->base_addr);
- res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- if (res)
- release_mem_region(res->start, ATTRIB_SIZE);
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ iounmap(lp->base);
+
+ smc_release_datacs(pdev,ndev);
+ smc_release_attrib(pdev);
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-regs");
+ if (!res)
+ platform_get_resource(pdev, IORESOURCE_MEM, 0);
release_mem_region(res->start, SMC_IO_EXTENT);
free_netdev(ndev);
@@ -2196,6 +2286,7 @@ static int smc_drv_suspend(struct device *dev, u32 state, u32 level)
if (netif_running(ndev)) {
netif_device_detach(ndev);
smc_shutdown(ndev);
+ smc_phy_powerdown(ndev);
}
}
return 0;
@@ -2208,9 +2299,7 @@ static int smc_drv_resume(struct device *dev, u32 level)
if (ndev && level == RESUME_ENABLE) {
struct smc_local *lp = netdev_priv(ndev);
-
- if (pdev->num_resources == 3)
- smc_enable_device(pdev->resource[2].start);
+ smc_enable_device(pdev);
if (netif_running(ndev)) {
smc_reset(ndev);
smc_enable(ndev);
diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h
index fad8c04373342..ddd2688e7d33e 100644
--- a/drivers/net/smc91x.h
+++ b/drivers/net/smc91x.h
@@ -162,6 +162,45 @@ SMC_outw(u16 val, unsigned long ioaddr, int reg)
}
}
+#elif defined(CONFIG_ARCH_OMAP)
+
+/* We can only do 16-bit reads and writes in the static memory space. */
+#define SMC_CAN_USE_8BIT 0
+#define SMC_CAN_USE_16BIT 1
+#define SMC_CAN_USE_32BIT 0
+#define SMC_IO_SHIFT 0
+#define SMC_NOWAIT 1
+
+#define SMC_inb(a, r) readb((a) + (r))
+#define SMC_outb(v, a, r) writeb(v, (a) + (r))
+#define SMC_inw(a, r) readw((a) + (r))
+#define SMC_outw(v, a, r) writew(v, (a) + (r))
+#define SMC_insw(a, r, p, l) readsw((a) + (r), p, l)
+#define SMC_outsw(a, r, p, l) writesw((a) + (r), p, l)
+#define SMC_inl(a, r) readl((a) + (r))
+#define SMC_outl(v, a, r) writel(v, (a) + (r))
+#define SMC_insl(a, r, p, l) readsl((a) + (r), p, l)
+#define SMC_outsl(a, r, p, l) writesl((a) + (r), p, l)
+
+#elif defined(CONFIG_SH_SH4202_MICRODEV)
+
+#define SMC_CAN_USE_8BIT 0
+#define SMC_CAN_USE_16BIT 1
+#define SMC_CAN_USE_32BIT 0
+
+#define SMC_inb(a, r) inb((a) + (r) - 0xa0000000)
+#define SMC_inw(a, r) inw((a) + (r) - 0xa0000000)
+#define SMC_inl(a, r) inl((a) + (r) - 0xa0000000)
+#define SMC_outb(v, a, r) outb(v, (a) + (r) - 0xa0000000)
+#define SMC_outw(v, a, r) outw(v, (a) + (r) - 0xa0000000)
+#define SMC_outl(v, a, r) outl(v, (a) + (r) - 0xa0000000)
+#define SMC_insl(a, r, p, l) insl((a) + (r) - 0xa0000000, p, l)
+#define SMC_outsl(a, r, p, l) outsl((a) + (r) - 0xa0000000, p, l)
+#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)
+
#elif defined(CONFIG_ISA)
#define SMC_CAN_USE_8BIT 1
@@ -362,7 +401,7 @@ smc_pxa_dma_irq(int dma, void *dummy, struct pt_regs *regs)
#define SMC_IO_SHIFT 0
#endif
#define SMC_IO_EXTENT (16 << SMC_IO_SHIFT)
-
+#define SMC_DATA_EXTENT (4)
/*
. Bank Select Register:
@@ -883,7 +922,7 @@ static const char * chip_ids[ 16 ] = {
#endif
#if SMC_CAN_USE_32BIT
-#define SMC_PUSH_DATA(p, l) \
+#define _SMC_PUSH_DATA(p, l) \
do { \
char *__ptr = (p); \
int __len = (l); \
@@ -898,7 +937,7 @@ static const char * chip_ids[ 16 ] = {
SMC_outw( *((u16 *)__ptr), ioaddr, DATA_REG ); \
} \
} while (0)
-#define SMC_PULL_DATA(p, l) \
+#define _SMC_PULL_DATA(p, l) \
do { \
char *__ptr = (p); \
int __len = (l); \
@@ -918,11 +957,11 @@ static const char * chip_ids[ 16 ] = {
SMC_insl( ioaddr, DATA_REG, __ptr, __len >> 2); \
} while (0)
#elif SMC_CAN_USE_16BIT
-#define SMC_PUSH_DATA(p, l) SMC_outsw( ioaddr, DATA_REG, p, (l) >> 1 )
-#define SMC_PULL_DATA(p, l) SMC_insw ( ioaddr, DATA_REG, p, (l) >> 1 )
+#define _SMC_PUSH_DATA(p, l) SMC_outsw( ioaddr, DATA_REG, p, (l) >> 1 )
+#define _SMC_PULL_DATA(p, l) SMC_insw ( ioaddr, DATA_REG, p, (l) >> 1 )
#elif SMC_CAN_USE_8BIT
-#define SMC_PUSH_DATA(p, l) SMC_outsb( ioaddr, DATA_REG, p, l )
-#define SMC_PULL_DATA(p, l) SMC_insb ( ioaddr, DATA_REG, p, l )
+#define _SMC_PUSH_DATA(p, l) SMC_outsb( ioaddr, DATA_REG, p, l )
+#define _SMC_PULL_DATA(p, l) SMC_insb ( ioaddr, DATA_REG, p, l )
#endif
#if ! SMC_CAN_USE_16BIT
@@ -941,6 +980,51 @@ static const char * chip_ids[ 16 ] = {
})
#endif
+#if SMC_CAN_USE_DATACS
+#define SMC_PUSH_DATA(p, l) \
+ if ( lp->datacs ) { \
+ unsigned char *__ptr = (p); \
+ int __len = (l); \
+ if (__len >= 2 && (unsigned long)__ptr & 2) { \
+ __len -= 2; \
+ SMC_outw( *((u16 *)__ptr), ioaddr, DATA_REG ); \
+ __ptr += 2; \
+ } \
+ outsl(lp->datacs, __ptr, __len >> 2); \
+ if (__len & 2) { \
+ __ptr += (__len & ~3); \
+ SMC_outw( *((u16 *)__ptr), ioaddr, DATA_REG ); \
+ } \
+ } else { \
+ _SMC_PUSH_DATA(p, l); \
+ }
+
+#define SMC_PULL_DATA(p, l) \
+ if ( lp->datacs ) { \
+ unsigned char *__ptr = (p); \
+ int __len = (l); \
+ if ((unsigned long)__ptr & 2) { \
+ /* \
+ * We want 32bit alignment here. \
+ * Since some buses perform a full 32bit \
+ * fetch even for 16bit data we can't use \
+ * SMC_inw() here. Back both source (on chip \
+ * and destination) pointers of 2 bytes. \
+ */ \
+ __ptr -= 2; \
+ __len += 2; \
+ SMC_SET_PTR( 2|PTR_READ|PTR_RCV|PTR_AUTOINC ); \
+ } \
+ __len += 2; \
+ insl( lp->datacs, __ptr, __len >> 2); \
+ } else { \
+ _SMC_PULL_DATA(p, l); \
+ }
+#else
+#define SMC_PUSH_DATA(p, l) _SMC_PUSH_DATA(p, l)
+#define SMC_PULL_DATA(p, l) _SMC_PULL_DATA(p, l)
+#endif
+
#if !defined (SMC_INTERRUPT_PREAMBLE)
# define SMC_INTERRUPT_PREAMBLE
#endif
diff --git a/drivers/net/sonic.c b/drivers/net/sonic.c
index 2f6e30984134c..cdc9cc873e067 100644
--- a/drivers/net/sonic.c
+++ b/drivers/net/sonic.c
@@ -116,7 +116,7 @@ static int sonic_send_packet(struct sk_buff *skb, struct net_device *dev)
/*
* Map the packet data into the logical DMA address space
*/
- if ((laddr = vdma_alloc(PHYSADDR(skb->data), skb->len)) == ~0UL) {
+ if ((laddr = vdma_alloc(CPHYSADDR(skb->data), skb->len)) == ~0UL) {
printk("%s: no VDMA entry for transmit available.\n",
dev->name);
dev_kfree_skb(skb);
@@ -223,7 +223,7 @@ static irqreturn_t sonic_interrupt(int irq, void *dev_id, struct pt_regs *regs)
/* We must free the original skb */
if (lp->tx_skb[entry]) {
- dev_kfree_skb(lp->tx_skb[entry]);
+ dev_kfree_skb_irq(lp->tx_skb[entry]);
lp->tx_skb[entry] = 0;
}
/* and the VDMA address */
diff --git a/drivers/net/sundance.c b/drivers/net/sundance.c
index f3e4876d02fcd..08cb7177a1759 100644
--- a/drivers/net/sundance.c
+++ b/drivers/net/sundance.c
@@ -1210,9 +1210,11 @@ static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *rgs
}
/* Yup, this is a documentation bug. It cost me *hours*. */
iowrite16 (0, ioaddr + TxStatus);
- tx_status = ioread16 (ioaddr + TxStatus);
- if (tx_cnt < 0)
+ if (tx_cnt < 0) {
+ iowrite32(5000, ioaddr + DownCounter);
break;
+ }
+ tx_status = ioread16 (ioaddr + TxStatus);
}
hw_frame_id = (tx_status >> 8) & 0xff;
} else {
@@ -1278,7 +1280,6 @@ static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *rgs
if (netif_msg_intr(np))
printk(KERN_DEBUG "%s: exiting interrupt, status=%#4.4x.\n",
dev->name, ioread16(ioaddr + IntrStatus));
- iowrite32(5000, ioaddr + DownCounter);
return IRQ_RETVAL(handled);
}
diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c
index 38e94961e1a48..5cd50fd53c125 100644
--- a/drivers/net/sungem.c
+++ b/drivers/net/sungem.c
@@ -3,16 +3,32 @@
*
* Copyright (C) 2000, 2001, 2002, 2003 David S. Miller (davem@redhat.com)
*
- * Support for Apple GMAC and assorted PHYs by
- * Benjamin Herrenscmidt (benh@kernel.crashing.org)
+ * Support for Apple GMAC and assorted PHYs, WOL, Power Management
+ * (C) 2001,2002,2003 Benjamin Herrenscmidt (benh@kernel.crashing.org)
+ * (C) 2004,2005 Benjamin Herrenscmidt, IBM Corp.
*
* NAPI and NETPOLL support
* (C) 2004 by Eric Lemoine (eric.lemoine@gmail.com)
*
* TODO:
- * - Get rid of all those nasty mdelay's and replace them
- * with schedule_timeout.
- * - Implement WOL
+ * - Now that the driver was significantly simplified, I need to rework
+ * the locking. I'm sure we don't need _2_ spinlocks, and we probably
+ * can avoid taking most of them for so long period of time (and schedule
+ * instead). The main issues at this point are caused by the netdev layer
+ * though:
+ *
+ * gem_change_mtu() and gem_set_multicast() are called with a read_lock()
+ * help by net/core/dev.c, thus they can't schedule. That means they can't
+ * call netif_poll_disable() neither, thus force gem_poll() to keep a spinlock
+ * where it could have been dropped. change_mtu especially would love also to
+ * be able to msleep instead of horrid locked delays when resetting the HW,
+ * but that read_lock() makes it impossible, unless I defer it's action to
+ * the reset task, which means it'll be asynchronous (won't take effect until
+ * the system schedules a bit).
+ *
+ * Also, it would probably be possible to also remove most of the long-life
+ * locking in open/resume code path (gem_reinit_chip) by beeing more careful
+ * about when we can start taking interrupts or get xmit() called...
*/
#include <linux/module.h>
@@ -109,6 +125,8 @@ static struct pci_device_id gem_pci_tbl[] = {
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
{ PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_K2_GMAC,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+ { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_SH_SUNGEM,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
{0, }
};
@@ -196,6 +214,33 @@ static inline void gem_disable_ints(struct gem *gp)
writel(GREG_STAT_NAPI | GREG_STAT_TXDONE, gp->regs + GREG_IMASK);
}
+static void gem_get_cell(struct gem *gp)
+{
+ BUG_ON(gp->cell_enabled < 0);
+ gp->cell_enabled++;
+#ifdef CONFIG_PPC_PMAC
+ if (gp->cell_enabled == 1) {
+ mb();
+ pmac_call_feature(PMAC_FTR_GMAC_ENABLE, gp->of_node, 0, 1);
+ udelay(10);
+ }
+#endif /* CONFIG_PPC_PMAC */
+}
+
+/* Turn off the chip's clock */
+static void gem_put_cell(struct gem *gp)
+{
+ BUG_ON(gp->cell_enabled <= 0);
+ gp->cell_enabled--;
+#ifdef CONFIG_PPC_PMAC
+ if (gp->cell_enabled == 0) {
+ mb();
+ pmac_call_feature(PMAC_FTR_GMAC_ENABLE, gp->of_node, 0, 0);
+ udelay(10);
+ }
+#endif /* CONFIG_PPC_PMAC */
+}
+
static void gem_handle_mif_event(struct gem *gp, u32 reg_val, u32 changed_bits)
{
if (netif_msg_intr(gp))
@@ -319,7 +364,19 @@ static int gem_rxmac_reset(struct gem *gp)
u64 desc_dma;
u32 val;
- /* First, reset MAC RX. */
+ /* First, reset & disable MAC RX. */
+ writel(MAC_RXRST_CMD, gp->regs + MAC_RXRST);
+ for (limit = 0; limit < 5000; limit++) {
+ if (!(readl(gp->regs + MAC_RXRST) & MAC_RXRST_CMD))
+ break;
+ udelay(10);
+ }
+ if (limit == 5000) {
+ printk(KERN_ERR "%s: RX MAC will not reset, resetting whole "
+ "chip.\n", dev->name);
+ return 1;
+ }
+
writel(gp->mac_rx_cfg & ~MAC_RXCFG_ENAB,
gp->regs + MAC_RXCFG);
for (limit = 0; limit < 5000; limit++) {
@@ -597,7 +654,7 @@ static int gem_abnormal_irq(struct net_device *dev, struct gem *gp, u32 gem_stat
return 0;
do_reset:
- gp->reset_task_pending = 2;
+ gp->reset_task_pending = 1;
schedule_work(&gp->reset_task);
return 1;
@@ -823,6 +880,9 @@ static int gem_poll(struct net_device *dev, int *budget)
struct gem *gp = dev->priv;
unsigned long flags;
+ /*
+ * NAPI locking nightmare: See comment at head of driver
+ */
spin_lock_irqsave(&gp->lock, flags);
do {
@@ -874,8 +934,11 @@ static irqreturn_t gem_interrupt(int irq, void *dev_id, struct pt_regs *regs)
struct gem *gp = dev->priv;
unsigned long flags;
- /* Swallow interrupts when shutting the chip down */
- if (!gp->hw_running)
+ /* Swallow interrupts when shutting the chip down, though
+ * that shouldn't happen, we should have done free_irq() at
+ * this point...
+ */
+ if (!gp->running)
return IRQ_HANDLED;
spin_lock_irqsave(&gp->lock, flags);
@@ -916,7 +979,7 @@ static void gem_tx_timeout(struct net_device *dev)
struct gem *gp = dev->priv;
printk(KERN_ERR "%s: transmit timed out, resetting\n", dev->name);
- if (!gp->hw_running) {
+ if (!gp->running) {
printk("%s: hrm.. hw not running !\n", dev->name);
return;
}
@@ -934,7 +997,7 @@ static void gem_tx_timeout(struct net_device *dev)
spin_lock_irq(&gp->lock);
spin_lock(&gp->tx_lock);
- gp->reset_task_pending = 2;
+ gp->reset_task_pending = 1;
schedule_work(&gp->reset_task);
spin_unlock(&gp->tx_lock);
@@ -975,6 +1038,11 @@ static int gem_start_xmit(struct sk_buff *skb, struct net_device *dev)
local_irq_restore(flags);
return NETDEV_TX_LOCKED;
}
+ /* We raced with gem_do_stop() */
+ if (!gp->running) {
+ spin_unlock_irqrestore(&gp->tx_lock, flags);
+ return NETDEV_TX_BUSY;
+ }
/* This is a hard error, log it. */
if (TX_BUFFS_AVAIL(gp) <= (skb_shinfo(skb)->nr_frags + 1)) {
@@ -1073,46 +1141,10 @@ static int gem_start_xmit(struct sk_buff *skb, struct net_device *dev)
return NETDEV_TX_OK;
}
-/* Jumbo-grams don't seem to work :-( */
-#define GEM_MIN_MTU 68
-#if 1
-#define GEM_MAX_MTU 1500
-#else
-#define GEM_MAX_MTU 9000
-#endif
-
-static int gem_change_mtu(struct net_device *dev, int new_mtu)
-{
- struct gem *gp = dev->priv;
-
- if (new_mtu < GEM_MIN_MTU || new_mtu > GEM_MAX_MTU)
- return -EINVAL;
-
- if (!netif_running(dev) || !netif_device_present(dev)) {
- /* We'll just catch it later when the
- * device is up'd or resumed.
- */
- dev->mtu = new_mtu;
- return 0;
- }
-
- spin_lock_irq(&gp->lock);
- spin_lock(&gp->tx_lock);
- dev->mtu = new_mtu;
- gp->reset_task_pending = 1;
- schedule_work(&gp->reset_task);
- spin_unlock(&gp->tx_lock);
- spin_unlock_irq(&gp->lock);
-
- flush_scheduled_work();
-
- return 0;
-}
-
#define STOP_TRIES 32
/* Must be invoked under gp->lock and gp->tx_lock. */
-static void gem_stop(struct gem *gp)
+static void gem_reset(struct gem *gp)
{
int limit;
u32 val;
@@ -1140,7 +1172,7 @@ static void gem_stop(struct gem *gp)
/* Must be invoked under gp->lock and gp->tx_lock. */
static void gem_start_dma(struct gem *gp)
{
- unsigned long val;
+ u32 val;
/* We are ready to rock, turn everything on. */
val = readl(gp->regs + TXDMA_CFG);
@@ -1155,10 +1187,31 @@ static void gem_start_dma(struct gem *gp)
(void) readl(gp->regs + MAC_RXCFG);
udelay(100);
- writel(GREG_STAT_TXDONE, gp->regs + GREG_IMASK);
+ gem_enable_ints(gp);
writel(RX_RING_SIZE - 4, gp->regs + RXDMA_KICK);
+}
+
+/* Must be invoked under gp->lock and gp->tx_lock. DMA won't be
+ * actually stopped before about 4ms tho ...
+ */
+static void gem_stop_dma(struct gem *gp)
+{
+ u32 val;
+
+ /* We are done rocking, turn everything off. */
+ val = readl(gp->regs + TXDMA_CFG);
+ writel(val & ~TXDMA_CFG_ENABLE, gp->regs + TXDMA_CFG);
+ val = readl(gp->regs + RXDMA_CFG);
+ writel(val & ~RXDMA_CFG_ENABLE, gp->regs + RXDMA_CFG);
+ val = readl(gp->regs + MAC_TXCFG);
+ writel(val & ~MAC_TXCFG_ENAB, gp->regs + MAC_TXCFG);
+ val = readl(gp->regs + MAC_RXCFG);
+ writel(val & ~MAC_RXCFG_ENAB, gp->regs + MAC_RXCFG);
+
+ (void) readl(gp->regs + MAC_RXCFG);
+ /* Need to wait a bit ... done by the caller */
}
@@ -1219,10 +1272,10 @@ start_aneg:
if (speed == 0)
speed = SPEED_10;
- /* If HW is down, we don't try to actually setup the PHY, we
+ /* If we are asleep, we don't try to actually setup the PHY, we
* just store the settings
*/
- if (!gp->hw_running) {
+ if (gp->asleep) {
gp->phy_mii.autoneg = gp->want_autoneg = autoneg;
gp->phy_mii.speed = speed;
gp->phy_mii.duplex = duplex;
@@ -1279,6 +1332,9 @@ static int gem_set_link_modes(struct gem *gp)
printk(KERN_INFO "%s: Link is up at %d Mbps, %s-duplex.\n",
gp->dev->name, speed, (full_duplex ? "full" : "half"));
+ if (!gp->running)
+ return 0;
+
val = (MAC_TXCFG_EIPG0 | MAC_TXCFG_NGU);
if (full_duplex) {
val |= (MAC_TXCFG_ICS | MAC_TXCFG_ICOLL);
@@ -1405,48 +1461,19 @@ static int gem_mdio_link_not_up(struct gem *gp)
}
}
-static void gem_init_rings(struct gem *);
-static void gem_init_hw(struct gem *, int);
-
-static void gem_reset_task(void *data)
-{
- struct gem *gp = (struct gem *) data;
-
- netif_poll_disable(gp->dev);
- spin_lock_irq(&gp->lock);
- spin_lock(&gp->tx_lock);
-
- if (gp->hw_running && gp->opened) {
- netif_stop_queue(gp->dev);
-
- /* Reset the chip & rings */
- gem_stop(gp);
- gem_init_rings(gp);
-
- gem_init_hw(gp,
- (gp->reset_task_pending == 2));
-
- netif_wake_queue(gp->dev);
- }
- gp->reset_task_pending = 0;
-
- spin_unlock(&gp->tx_lock);
- spin_unlock_irq(&gp->lock);
- netif_poll_enable(gp->dev);
-}
-
static void gem_link_timer(unsigned long data)
{
struct gem *gp = (struct gem *) data;
int restart_aneg = 0;
- if (!gp->hw_running)
+ if (gp->asleep)
return;
spin_lock_irq(&gp->lock);
spin_lock(&gp->tx_lock);
+ gem_get_cell(gp);
- /* If the link of task is still pending, we just
+ /* If the reset task is still pending, we just
* reschedule the link timer
*/
if (gp->reset_task_pending)
@@ -1462,8 +1489,7 @@ static void gem_link_timer(unsigned long data)
if ((val & PCS_MIISTAT_LS) != 0) {
gp->lstate = link_up;
netif_carrier_on(gp->dev);
- if (gp->opened)
- (void)gem_set_link_modes(gp);
+ (void)gem_set_link_modes(gp);
}
goto restart;
}
@@ -1484,7 +1510,7 @@ static void gem_link_timer(unsigned long data)
} else if (gp->lstate != link_up) {
gp->lstate = link_up;
netif_carrier_on(gp->dev);
- if (gp->opened && gem_set_link_modes(gp))
+ if (gem_set_link_modes(gp))
restart_aneg = 1;
}
} else {
@@ -1497,7 +1523,7 @@ static void gem_link_timer(unsigned long data)
printk(KERN_INFO "%s: Link down\n",
gp->dev->name);
netif_carrier_off(gp->dev);
- gp->reset_task_pending = 2;
+ gp->reset_task_pending = 1;
schedule_work(&gp->reset_task);
restart_aneg = 1;
} else if (++gp->timer_ticks > 10) {
@@ -1514,6 +1540,7 @@ static void gem_link_timer(unsigned long data)
restart:
mod_timer(&gp->link_timer, jiffies + ((12 * HZ) / 10));
out_unlock:
+ gem_put_cell(gp);
spin_unlock(&gp->tx_lock);
spin_unlock_irq(&gp->lock);
}
@@ -1619,59 +1646,40 @@ static void gem_init_rings(struct gem *gp)
wmb();
}
-/* Must be invoked under gp->lock and gp->tx_lock. */
+/* Init PHY interface and start link poll state machine */
static void gem_init_phy(struct gem *gp)
{
u32 mifcfg;
-
+
/* Revert MIF CFG setting done on stop_phy */
mifcfg = readl(gp->regs + MIF_CFG);
mifcfg &= ~MIF_CFG_BBMODE;
writel(mifcfg, gp->regs + MIF_CFG);
-#ifdef CONFIG_PPC_PMAC
if (gp->pdev->vendor == PCI_VENDOR_ID_APPLE) {
- int i, j;
+ int i;
/* Those delay sucks, the HW seem to love them though, I'll
* serisouly consider breaking some locks here to be able
* to schedule instead
*/
- pmac_call_feature(PMAC_FTR_GMAC_PHY_RESET, gp->of_node, 0, 0);
- for (j = 0; j < 3; j++) {
+ for (i = 0; i < 3; i++) {
+#ifdef CONFIG_PPC_PMAC
+ pmac_call_feature(PMAC_FTR_GMAC_PHY_RESET, gp->of_node, 0, 0);
+ msleep(20);
+#endif
/* Some PHYs used by apple have problem getting back to us,
- * we _know_ it's actually at addr 0 or 1, that's a hack, but
- * it helps to do that reset now. I suspect some motherboards
- * don't wire the PHY reset line properly, thus the PHY doesn't
- * come back with the above pmac_call_feature.
+ * we do an additional reset here
*/
- gp->mii_phy_addr = 0;
- phy_write(gp, MII_BMCR, BMCR_RESET);
- gp->mii_phy_addr = 1;
phy_write(gp, MII_BMCR, BMCR_RESET);
- /* We should probably break some locks here and schedule... */
- mdelay(10);
-
- /* On K2, we only probe the internal PHY at address 1, other
- * addresses tend to return garbage.
- */
- if (gp->pdev->device == PCI_DEVICE_ID_APPLE_K2_GMAC)
+ msleep(20);
+ if (phy_read(gp, MII_BMCR) != 0xffff)
break;
-
- for (i = 0; i < 32; i++) {
- gp->mii_phy_addr = i;
- if (phy_read(gp, MII_BMCR) != 0xffff)
- break;
- }
- if (i == 32) {
+ if (i == 2)
printk(KERN_WARNING "%s: GMAC PHY not responding !\n",
gp->dev->name);
- gp->mii_phy_addr = 0;
- } else
- break;
}
}
-#endif /* CONFIG_PPC_PMAC */
if (gp->pdev->vendor == PCI_VENDOR_ID_SUN &&
gp->pdev->device == PCI_DEVICE_ID_SUN_GEM) {
@@ -1755,6 +1763,16 @@ static void gem_init_phy(struct gem *gp)
val |= PCS_SCTRL_LOOP;
writel(val, gp->regs + PCS_SCTRL);
}
+
+ /* Default aneg parameters */
+ gp->timer_ticks = 0;
+ gp->lstate = link_down;
+ netif_carrier_off(gp->dev);
+
+ /* Can I advertise gigabit here ? I'd need BCM PHY docs... */
+ spin_lock_irq(&gp->lock);
+ gem_begin_auto_negotiation(gp, NULL);
+ spin_unlock_irq(&gp->lock);
}
/* Must be invoked under gp->lock and gp->tx_lock. */
@@ -1796,8 +1814,7 @@ static void gem_init_dma(struct gem *gp)
}
/* Must be invoked under gp->lock and gp->tx_lock. */
-static u32
-gem_setup_multicast(struct gem *gp)
+static u32 gem_setup_multicast(struct gem *gp)
{
u32 rxcfg = 0;
int i;
@@ -1914,6 +1931,11 @@ static void gem_init_mac(struct gem *gp)
* make no use of those events other than to record them.
*/
writel(0xffffffff, gp->regs + MAC_MCMASK);
+
+ /* Don't enable GEM's WOL in normal operations
+ */
+ if (gp->has_wol)
+ writel(0, gp->regs + WOL_WAKECSR);
}
/* Must be invoked under gp->lock and gp->tx_lock. */
@@ -1975,6 +1997,23 @@ static int gem_check_invariants(struct gem *gp)
gp->tx_fifo_sz = readl(gp->regs + TXDMA_FSZ) * 64;
gp->rx_fifo_sz = readl(gp->regs + RXDMA_FSZ) * 64;
gp->swrst_base = 0;
+
+ mif_cfg = readl(gp->regs + MIF_CFG);
+ mif_cfg &= ~(MIF_CFG_PSELECT|MIF_CFG_POLL|MIF_CFG_BBMODE|MIF_CFG_MDI1);
+ mif_cfg |= MIF_CFG_MDI0;
+ writel(mif_cfg, gp->regs + MIF_CFG);
+ writel(PCS_DMODE_MGM, gp->regs + PCS_DMODE);
+ writel(MAC_XIFCFG_OE, gp->regs + MAC_XIFCFG);
+
+ /* We hard-code the PHY address so we can properly bring it out of
+ * reset later on, we can't really probe it at this point, though
+ * that isn't an issue.
+ */
+ if (gp->pdev->device == PCI_DEVICE_ID_APPLE_K2_GMAC)
+ gp->mii_phy_addr = 1;
+ else
+ gp->mii_phy_addr = 0;
+
return 0;
}
@@ -2053,68 +2092,28 @@ static int gem_check_invariants(struct gem *gp)
}
/* Must be invoked under gp->lock and gp->tx_lock. */
-static void gem_init_hw(struct gem *gp, int restart_link)
+static void gem_reinit_chip(struct gem *gp)
{
- /* On Apple's gmac, I initialize the PHY only after
- * setting up the chip. It appears the gigabit PHYs
- * don't quite like beeing talked to on the GII when
- * the chip is not running, I suspect it might not
- * be clocked at that point. --BenH
- */
- if (restart_link)
- gem_init_phy(gp);
- gem_init_pause_thresholds(gp);
- gem_init_dma(gp);
- gem_init_mac(gp);
-
- if (restart_link) {
- /* Default aneg parameters */
- gp->timer_ticks = 0;
- gp->lstate = link_down;
- netif_carrier_off(gp->dev);
-
- /* Can I advertise gigabit here ? I'd need BCM PHY docs... */
- gem_begin_auto_negotiation(gp, NULL);
- } else {
- if (gp->lstate == link_up) {
- netif_carrier_on(gp->dev);
- gem_set_link_modes(gp);
- }
- }
-}
+ /* Reset the chip */
+ gem_reset(gp);
-#ifdef CONFIG_PPC_PMAC
-/* Enable the chip's clock and make sure it's config space is
- * setup properly. There appear to be no need to restore the
- * base addresses.
- */
-static void gem_apple_powerup(struct gem *gp)
-{
- u32 mif_cfg;
+ /* Make sure ints are disabled */
+ gem_disable_ints(gp);
- mb();
- pmac_call_feature(PMAC_FTR_GMAC_ENABLE, gp->of_node, 0, 1);
+ /* Allocate & setup ring buffers */
+ gem_init_rings(gp);
- udelay(3);
-
- mif_cfg = readl(gp->regs + MIF_CFG);
- mif_cfg &= ~(MIF_CFG_PSELECT|MIF_CFG_POLL|MIF_CFG_BBMODE|MIF_CFG_MDI1);
- mif_cfg |= MIF_CFG_MDI0;
- writel(mif_cfg, gp->regs + MIF_CFG);
- writel(PCS_DMODE_MGM, gp->regs + PCS_DMODE);
- writel(MAC_XIFCFG_OE, gp->regs + MAC_XIFCFG);
-}
+ /* Configure pause thresholds */
+ gem_init_pause_thresholds(gp);
-/* Turn off the chip's clock */
-static void gem_apple_powerdown(struct gem *gp)
-{
- pmac_call_feature(PMAC_FTR_GMAC_ENABLE, gp->of_node, 0, 0);
+ /* Init DMA & MAC engines */
+ gem_init_dma(gp);
+ gem_init_mac(gp);
}
-#endif /* CONFIG_PPC_PMAC */
/* Must be invoked with no lock held. */
-static void gem_stop_phy(struct gem *gp)
+static void gem_stop_phy(struct gem *gp, int wol)
{
u32 mifcfg;
unsigned long flags;
@@ -2131,8 +2130,22 @@ static void gem_stop_phy(struct gem *gp)
mifcfg &= ~MIF_CFG_POLL;
writel(mifcfg, gp->regs + MIF_CFG);
- if (gp->wake_on_lan) {
- /* Setup wake-on-lan */
+ if (wol && gp->has_wol) {
+ unsigned char *e = &gp->dev->dev_addr[0];
+ u32 csr;
+
+ /* Setup wake-on-lan for MAGIC packet */
+ writel(MAC_RXCFG_HFE | MAC_RXCFG_SFCS | MAC_RXCFG_ENAB,
+ gp->regs + MAC_RXCFG);
+ writel((e[4] << 8) | e[5], gp->regs + WOL_MATCH0);
+ writel((e[2] << 8) | e[3], gp->regs + WOL_MATCH1);
+ writel((e[0] << 8) | e[1], gp->regs + WOL_MATCH2);
+
+ writel(WOL_MCOUNT_N | WOL_MCOUNT_M, gp->regs + WOL_MCOUNT);
+ csr = WOL_WAKECSR_ENABLE;
+ if ((readl(gp->regs + MAC_XIFCFG) & MAC_XIFCFG_GMII) == 0)
+ csr |= WOL_WAKECSR_MII;
+ writel(csr, gp->regs + WOL_WAKECSR);
} else {
writel(0, gp->regs + MAC_RXCFG);
(void)readl(gp->regs + MAC_RXCFG);
@@ -2148,20 +2161,20 @@ static void gem_stop_phy(struct gem *gp)
writel(0, gp->regs + TXDMA_CFG);
writel(0, gp->regs + RXDMA_CFG);
- if (!gp->wake_on_lan) {
+ if (!wol) {
spin_lock_irqsave(&gp->lock, flags);
spin_lock(&gp->tx_lock);
- gem_stop(gp);
+ gem_reset(gp);
writel(MAC_TXRST_CMD, gp->regs + MAC_TXRST);
writel(MAC_RXRST_CMD, gp->regs + MAC_RXRST);
spin_unlock(&gp->tx_lock);
spin_unlock_irqrestore(&gp->lock, flags);
- }
- if (found_mii_phy(gp) && gp->phy_mii.def->ops->suspend)
- gp->phy_mii.def->ops->suspend(&gp->phy_mii, 0 /* wake on lan options */);
+ /* No need to take the lock here */
+
+ if (found_mii_phy(gp) && gp->phy_mii.def->ops->suspend)
+ gp->phy_mii.def->ops->suspend(&gp->phy_mii);
- if (!gp->wake_on_lan) {
/* According to Apple, we must set the MDIO pins to this begnign
* state or we may 1) eat more current, 2) damage some PHYs
*/
@@ -2174,181 +2187,160 @@ static void gem_stop_phy(struct gem *gp)
}
}
-/* Shut down the chip, must be called with pm_sem held. */
-static void gem_shutdown(struct gem *gp)
+
+static int gem_do_start(struct net_device *dev)
{
- /* Make us not-running to avoid timers respawning
- * and swallow irqs
- */
- gp->hw_running = 0;
- wmb();
+ struct gem *gp = dev->priv;
+ unsigned long flags;
- /* Stop the link timer */
- del_timer_sync(&gp->link_timer);
+ spin_lock_irqsave(&gp->lock, flags);
+ spin_lock(&gp->tx_lock);
- /* Stop the reset task */
- while (gp->reset_task_pending)
- yield();
-
- /* Actually stop the chip */
- if (gp->pdev->vendor == PCI_VENDOR_ID_APPLE) {
- gem_stop_phy(gp);
+ /* Enable the cell */
+ gem_get_cell(gp);
-#ifdef CONFIG_PPC_PMAC
- /* Power down the chip */
- gem_apple_powerdown(gp);
-#endif /* CONFIG_PPC_PMAC */
- } else{
- unsigned long flags;
+ /* Init & setup chip hardware */
+ gem_reinit_chip(gp);
+
+ gp->running = 1;
+
+ if (gp->lstate == link_up) {
+ netif_carrier_on(gp->dev);
+ gem_set_link_modes(gp);
+ }
+
+ netif_wake_queue(gp->dev);
+
+ spin_unlock(&gp->tx_lock);
+ spin_unlock_irqrestore(&gp->lock, flags);
+
+ if (request_irq(gp->pdev->irq, gem_interrupt,
+ SA_SHIRQ, dev->name, (void *)dev)) {
+ printk(KERN_ERR "%s: failed to request irq !\n", gp->dev->name);
spin_lock_irqsave(&gp->lock, flags);
spin_lock(&gp->tx_lock);
- gem_stop(gp);
+
+ gp->running = 0;
+ gem_reset(gp);
+ gem_clean_rings(gp);
+ gem_put_cell(gp);
+
spin_unlock(&gp->tx_lock);
spin_unlock_irqrestore(&gp->lock, flags);
+
+ return -EAGAIN;
}
+
+ return 0;
}
-static void gem_pm_task(void *data)
+static void gem_do_stop(struct net_device *dev, int wol)
{
- struct gem *gp = (struct gem *) data;
+ struct gem *gp = dev->priv;
+ unsigned long flags;
- /* We assume if we can't lock the pm_sem, then open() was
- * called again (or suspend()), and we can safely ignore
- * the PM request
- */
- if (down_trylock(&gp->pm_sem))
- return;
+ spin_lock_irqsave(&gp->lock, flags);
+ spin_lock(&gp->tx_lock);
- /* Driver was re-opened or already shut down */
- if (gp->opened || !gp->hw_running) {
- up(&gp->pm_sem);
- return;
- }
+ gp->running = 0;
- gem_shutdown(gp);
+ /* Stop netif queue */
+ netif_stop_queue(dev);
- up(&gp->pm_sem);
-}
+ /* Make sure ints are disabled */
+ gem_disable_ints(gp);
-static void gem_pm_timer(unsigned long data)
-{
- struct gem *gp = (struct gem *) data;
+ /* We can drop the lock now */
+ spin_unlock(&gp->tx_lock);
+ spin_unlock_irqrestore(&gp->lock, flags);
+
+ /* If we are going to sleep with WOL */
+ gem_stop_dma(gp);
+ msleep(10);
+ if (!wol)
+ gem_reset(gp);
+ msleep(10);
+
+ /* Get rid of rings */
+ gem_clean_rings(gp);
+
+ /* No irq needed anymore */
+ free_irq(gp->pdev->irq, (void *) dev);
- schedule_work(&gp->pm_task);
+ /* Cell not needed neither if no WOL */
+ if (!wol) {
+ spin_lock_irqsave(&gp->lock, flags);
+ gem_put_cell(gp);
+ spin_unlock_irqrestore(&gp->lock, flags);
+ }
}
-static int gem_open(struct net_device *dev)
+static void gem_reset_task(void *data)
{
- struct gem *gp = dev->priv;
- int hw_was_up;
+ struct gem *gp = (struct gem *) data;
down(&gp->pm_sem);
- hw_was_up = gp->hw_running;
+ netif_poll_disable(gp->dev);
- /* Stop the PM timer/task */
- del_timer(&gp->pm_timer);
- flush_scheduled_work();
+ spin_lock_irq(&gp->lock);
+ spin_lock(&gp->tx_lock);
- /* The power-management semaphore protects the hw_running
- * etc. state so it is safe to do this bit without gp->lock
- */
- if (!gp->hw_running) {
-#ifdef CONFIG_PPC_PMAC
- /* First, we need to bring up the chip */
- if (gp->pdev->vendor == PCI_VENDOR_ID_APPLE) {
- gem_apple_powerup(gp);
- gem_check_invariants(gp);
- }
-#endif /* CONFIG_PPC_PMAC */
+ if (gp->running == 0)
+ goto not_running;
- /* Reset the chip */
- spin_lock_irq(&gp->lock);
- spin_lock(&gp->tx_lock);
- gem_stop(gp);
- spin_unlock(&gp->tx_lock);
- spin_unlock_irq(&gp->lock);
+ if (gp->running) {
+ netif_stop_queue(gp->dev);
- gp->hw_running = 1;
+ /* Reset the chip & rings */
+ gem_reinit_chip(gp);
+ if (gp->lstate == link_up)
+ gem_set_link_modes(gp);
+ netif_wake_queue(gp->dev);
}
+ not_running:
+ gp->reset_task_pending = 0;
- /* We can now request the interrupt as we know it's masked
- * on the controller
- */
- if (request_irq(gp->pdev->irq, gem_interrupt,
- SA_SHIRQ, dev->name, (void *)dev)) {
- printk(KERN_ERR "%s: failed to request irq !\n", gp->dev->name);
-
- spin_lock_irq(&gp->lock);
- spin_lock(&gp->tx_lock);
-#ifdef CONFIG_PPC_PMAC
- if (!hw_was_up && gp->pdev->vendor == PCI_VENDOR_ID_APPLE)
- gem_apple_powerdown(gp);
-#endif /* CONFIG_PPC_PMAC */
- /* Fire the PM timer that will shut us down in about 10 seconds */
- gp->pm_timer.expires = jiffies + 10*HZ;
- add_timer(&gp->pm_timer);
- up(&gp->pm_sem);
- spin_unlock(&gp->tx_lock);
- spin_unlock_irq(&gp->lock);
+ spin_unlock(&gp->tx_lock);
+ spin_unlock_irq(&gp->lock);
- return -EAGAIN;
- }
+ netif_poll_enable(gp->dev);
- spin_lock_irq(&gp->lock);
- spin_lock(&gp->tx_lock);
+ up(&gp->pm_sem);
+}
- /* Allocate & setup ring buffers */
- gem_init_rings(gp);
- /* Init & setup chip hardware */
- gem_init_hw(gp, !hw_was_up);
+static int gem_open(struct net_device *dev)
+{
+ struct gem *gp = dev->priv;
+ int rc = 0;
- gp->opened = 1;
+ down(&gp->pm_sem);
- spin_unlock(&gp->tx_lock);
- spin_unlock_irq(&gp->lock);
+ /* We need the cell enabled */
+ if (!gp->asleep)
+ rc = gem_do_start(dev);
+ gp->opened = (rc == 0);
up(&gp->pm_sem);
- return 0;
+ return rc;
}
static int gem_close(struct net_device *dev)
{
struct gem *gp = dev->priv;
- /* Make sure we don't get distracted by suspend/resume */
- down(&gp->pm_sem);
-
/* Note: we don't need to call netif_poll_disable() here because
* our caller (dev_close) already did it for us
*/
- /* Stop traffic, mark us closed */
- spin_lock_irq(&gp->lock);
- spin_lock(&gp->tx_lock);
+ down(&gp->pm_sem);
gp->opened = 0;
-
- netif_stop_queue(dev);
-
- /* Stop chip */
- gem_stop(gp);
-
- /* Get rid of rings */
- gem_clean_rings(gp);
-
- /* Bye, the pm timer will finish the job */
- free_irq(gp->pdev->irq, (void *) dev);
-
- spin_unlock(&gp->tx_lock);
- spin_unlock_irq(&gp->lock);
-
- /* Fire the PM timer that will shut us down in about 10 seconds */
- gp->pm_timer.expires = jiffies + 10*HZ;
- add_timer(&gp->pm_timer);
+ if (!gp->asleep)
+ gem_do_stop(dev, 0);
up(&gp->pm_sem);
@@ -2356,49 +2348,66 @@ static int gem_close(struct net_device *dev)
}
#ifdef CONFIG_PM
-static int gem_suspend(struct pci_dev *pdev, u32 state)
+static int gem_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct net_device *dev = pci_get_drvdata(pdev);
struct gem *gp = dev->priv;
+ unsigned long flags;
- netif_poll_disable(dev);
-
- /* We hold the PM semaphore during entire driver
- * sleep time
- */
down(&gp->pm_sem);
+ netif_poll_disable(dev);
+
printk(KERN_INFO "%s: suspending, WakeOnLan %s\n",
- dev->name, gp->wake_on_lan ? "enabled" : "disabled");
+ dev->name,
+ (gp->wake_on_lan && gp->opened) ? "enabled" : "disabled");
- /* If the driver is opened, we stop the DMA */
- if (gp->opened) {
- spin_lock_irq(&gp->lock);
- spin_lock(&gp->tx_lock);
+ /* Keep the cell enabled during the entire operation */
+ spin_lock_irqsave(&gp->lock, flags);
+ spin_lock(&gp->tx_lock);
+ gem_get_cell(gp);
+ spin_unlock(&gp->tx_lock);
+ spin_unlock_irqrestore(&gp->lock, flags);
+ /* If the driver is opened, we stop the MAC */
+ if (gp->opened) {
/* Stop traffic, mark us closed */
netif_device_detach(dev);
- /* Stop chip */
- gem_stop(gp);
+ /* Switch off MAC, remember WOL setting */
+ gp->asleep_wol = gp->wake_on_lan;
+ gem_do_stop(dev, gp->asleep_wol);
+ } else
+ gp->asleep_wol = 0;
- /* Get rid of ring buffers */
- gem_clean_rings(gp);
+ /* Mark us asleep */
+ gp->asleep = 1;
+ wmb();
- spin_unlock(&gp->tx_lock);
- spin_unlock_irq(&gp->lock);
+ /* Stop the link timer */
+ del_timer_sync(&gp->link_timer);
- if (gp->pdev->vendor == PCI_VENDOR_ID_APPLE)
- disable_irq(gp->pdev->irq);
- }
+ /* Now we release the semaphore to not block the reset task who
+ * can take it too. We are marked asleep, so there will be no
+ * conflict here
+ */
+ up(&gp->pm_sem);
- if (gp->hw_running) {
- /* Kill PM timer if any */
- del_timer_sync(&gp->pm_timer);
- flush_scheduled_work();
+ /* Wait for a pending reset task to complete */
+ while (gp->reset_task_pending)
+ yield();
+ flush_scheduled_work();
- gem_shutdown(gp);
- }
+ /* Shut the PHY down eventually and setup WOL */
+ gem_stop_phy(gp, gp->asleep_wol);
+
+ /* Make sure bus master is disabled */
+ pci_disable_device(gp->pdev);
+
+ /* Release the cell, no need to take a lock at this point since
+ * nothing else can happen now
+ */
+ gem_put_cell(gp);
return 0;
}
@@ -2407,36 +2416,74 @@ static int gem_resume(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
struct gem *gp = dev->priv;
+ unsigned long flags;
printk(KERN_INFO "%s: resuming\n", dev->name);
- if (gp->opened) {
-#ifdef CONFIG_PPC_PMAC
- /* First, we need to bring up the chip */
- if (gp->pdev->vendor == PCI_VENDOR_ID_APPLE) {
- gem_apple_powerup(gp);
- gem_check_invariants(gp);
- }
-#endif /* CONFIG_PPC_PMAC */
- spin_lock_irq(&gp->lock);
- spin_lock(&gp->tx_lock);
+ down(&gp->pm_sem);
- gem_stop(gp);
- gp->hw_running = 1;
- gem_init_rings(gp);
- gem_init_hw(gp, 1);
+ /* Keep the cell enabled during the entire operation, no need to
+ * take a lock here tho since nothing else can happen while we are
+ * marked asleep
+ */
+ gem_get_cell(gp);
- spin_unlock(&gp->tx_lock);
- spin_unlock_irq(&gp->lock);
+ /* Make sure PCI access and bus master are enabled */
+ if (pci_enable_device(gp->pdev)) {
+ printk(KERN_ERR "%s: Can't re-enable chip !\n",
+ dev->name);
+ /* Put cell and forget it for now, it will be considered as
+ * still asleep, a new sleep cycle may bring it back
+ */
+ gem_put_cell(gp);
+ up(&gp->pm_sem);
+ return 0;
+ }
+ pci_set_master(gp->pdev);
+ /* Reset everything */
+ gem_reset(gp);
+
+ /* Mark us woken up */
+ gp->asleep = 0;
+ wmb();
+
+ /* Bring the PHY back. Again, lock is useless at this point as
+ * nothing can be happening until we restart the whole thing
+ */
+ gem_init_phy(gp);
+
+ /* If we were opened, bring everything back */
+ if (gp->opened) {
+ /* Restart MAC */
+ gem_do_start(dev);
+
+ /* Re-attach net device */
netif_device_attach(dev);
- if (gp->pdev->vendor == PCI_VENDOR_ID_APPLE)
- enable_irq(gp->pdev->irq);
+
}
- up(&gp->pm_sem);
+
+ spin_lock_irqsave(&gp->lock, flags);
+ spin_lock(&gp->tx_lock);
+
+ /* If we had WOL enabled, the cell clock was never turned off during
+ * sleep, so we end up beeing unbalanced. Fix that here
+ */
+ if (gp->asleep_wol)
+ gem_put_cell(gp);
+
+ /* This function doesn't need to hold the cell, it will be held if the
+ * driver is open by gem_do_start().
+ */
+ gem_put_cell(gp);
+
+ spin_unlock(&gp->tx_lock);
+ spin_unlock_irqrestore(&gp->lock, flags);
netif_poll_enable(dev);
+ up(&gp->pm_sem);
+
return 0;
}
#endif /* CONFIG_PM */
@@ -2449,7 +2496,10 @@ static struct net_device_stats *gem_get_stats(struct net_device *dev)
spin_lock_irq(&gp->lock);
spin_lock(&gp->tx_lock);
- if (gp->hw_running) {
+ /* I have seen this being called while the PM was in progress,
+ * so we shield against this
+ */
+ if (gp->running) {
stats->rx_crc_errors += readl(gp->regs + MAC_FCSERR);
writel(0, gp->regs + MAC_FCSERR);
@@ -2479,12 +2529,13 @@ static void gem_set_multicast(struct net_device *dev)
u32 rxcfg, rxcfg_new;
int limit = 10000;
- if (!gp->hw_running)
- return;
-
+
spin_lock_irq(&gp->lock);
spin_lock(&gp->tx_lock);
+ if (!gp->running)
+ goto bail;
+
netif_stop_queue(dev);
rxcfg = readl(gp->regs + MAC_RXCFG);
@@ -2508,10 +2559,50 @@ static void gem_set_multicast(struct net_device *dev)
netif_wake_queue(dev);
+ bail:
spin_unlock(&gp->tx_lock);
spin_unlock_irq(&gp->lock);
}
+/* Jumbo-grams don't seem to work :-( */
+#define GEM_MIN_MTU 68
+#if 1
+#define GEM_MAX_MTU 1500
+#else
+#define GEM_MAX_MTU 9000
+#endif
+
+static int gem_change_mtu(struct net_device *dev, int new_mtu)
+{
+ struct gem *gp = dev->priv;
+
+ if (new_mtu < GEM_MIN_MTU || new_mtu > GEM_MAX_MTU)
+ return -EINVAL;
+
+ if (!netif_running(dev) || !netif_device_present(dev)) {
+ /* We'll just catch it later when the
+ * device is up'd or resumed.
+ */
+ dev->mtu = new_mtu;
+ return 0;
+ }
+
+ down(&gp->pm_sem);
+ spin_lock_irq(&gp->lock);
+ spin_lock(&gp->tx_lock);
+ dev->mtu = new_mtu;
+ if (gp->running) {
+ gem_reinit_chip(gp);
+ if (gp->lstate == link_up)
+ gem_set_link_modes(gp);
+ }
+ spin_unlock(&gp->tx_lock);
+ spin_unlock_irq(&gp->lock);
+ up(&gp->pm_sem);
+
+ return 0;
+}
+
static void gem_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
{
struct gem *gp = dev->priv;
@@ -2540,7 +2631,6 @@ static int gem_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
/* Return current PHY settings */
spin_lock_irq(&gp->lock);
- spin_lock(&gp->tx_lock);
cmd->autoneg = gp->want_autoneg;
cmd->speed = gp->phy_mii.speed;
cmd->duplex = gp->phy_mii.duplex;
@@ -2552,7 +2642,6 @@ static int gem_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
*/
if (cmd->advertising == 0)
cmd->advertising = cmd->supported;
- spin_unlock(&gp->tx_lock);
spin_unlock_irq(&gp->lock);
} else { // XXX PCS ?
cmd->supported =
@@ -2592,9 +2681,9 @@ static int gem_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
/* Apply settings and restart link process. */
spin_lock_irq(&gp->lock);
- spin_lock(&gp->tx_lock);
+ gem_get_cell(gp);
gem_begin_auto_negotiation(gp, cmd);
- spin_unlock(&gp->tx_lock);
+ gem_put_cell(gp);
spin_unlock_irq(&gp->lock);
return 0;
@@ -2609,9 +2698,9 @@ static int gem_nway_reset(struct net_device *dev)
/* Restart link process. */
spin_lock_irq(&gp->lock);
- spin_lock(&gp->tx_lock);
+ gem_get_cell(gp);
gem_begin_auto_negotiation(gp, NULL);
- spin_unlock(&gp->tx_lock);
+ gem_put_cell(gp);
spin_unlock_irq(&gp->lock);
return 0;
@@ -2628,7 +2717,37 @@ static void gem_set_msglevel(struct net_device *dev, u32 value)
struct gem *gp = dev->priv;
gp->msg_enable = value;
}
-
+
+
+/* Add more when I understand how to program the chip */
+/* like WAKE_UCAST | WAKE_MCAST | WAKE_BCAST */
+
+#define WOL_SUPPORTED_MASK (WAKE_MAGIC)
+
+static void gem_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+ struct gem *gp = dev->priv;
+
+ /* Add more when I understand how to program the chip */
+ if (gp->has_wol) {
+ wol->supported = WOL_SUPPORTED_MASK;
+ wol->wolopts = gp->wake_on_lan;
+ } else {
+ wol->supported = 0;
+ wol->wolopts = 0;
+ }
+}
+
+static int gem_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+ struct gem *gp = dev->priv;
+
+ if (!gp->has_wol)
+ return -EOPNOTSUPP;
+ gp->wake_on_lan = wol->wolopts & WOL_SUPPORTED_MASK;
+ return 0;
+}
+
static struct ethtool_ops gem_ethtool_ops = {
.get_drvinfo = gem_get_drvinfo,
.get_link = ethtool_op_get_link,
@@ -2637,6 +2756,8 @@ static struct ethtool_ops gem_ethtool_ops = {
.nway_reset = gem_nway_reset,
.get_msglevel = gem_get_msglevel,
.set_msglevel = gem_set_msglevel,
+ .get_wol = gem_get_wol,
+ .set_wol = gem_set_wol,
};
static int gem_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
@@ -2644,22 +2765,28 @@ static int gem_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
struct gem *gp = dev->priv;
struct mii_ioctl_data *data = if_mii(ifr);
int rc = -EOPNOTSUPP;
-
+ unsigned long flags;
+
/* Hold the PM semaphore while doing ioctl's or we may collide
- * with open/close and power management and oops.
+ * with power management.
*/
down(&gp->pm_sem);
-
+
+ spin_lock_irqsave(&gp->lock, flags);
+ gem_get_cell(gp);
+ spin_unlock_irqrestore(&gp->lock, flags);
+
switch (cmd) {
case SIOCGMIIPHY: /* Get address of MII PHY in use. */
data->phy_id = gp->mii_phy_addr;
/* Fallthrough... */
case SIOCGMIIREG: /* Read MII PHY register. */
- if (!gp->hw_running)
- rc = -EIO;
+ if (!gp->running)
+ rc = -EAGAIN;
else {
- data->val_out = __phy_read(gp, data->phy_id & 0x1f, data->reg_num & 0x1f);
+ data->val_out = __phy_read(gp, data->phy_id & 0x1f,
+ data->reg_num & 0x1f);
rc = 0;
}
break;
@@ -2667,14 +2794,19 @@ static int gem_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
case SIOCSMIIREG: /* Write MII PHY register. */
if (!capable(CAP_NET_ADMIN))
rc = -EPERM;
- else if (!gp->hw_running)
- rc = -EIO;
+ else if (!gp->running)
+ rc = -EAGAIN;
else {
- __phy_write(gp, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in);
+ __phy_write(gp, data->phy_id & 0x1f, data->reg_num & 0x1f,
+ data->val_in);
rc = 0;
}
break;
};
+
+ spin_lock_irqsave(&gp->lock, flags);
+ gem_put_cell(gp);
+ spin_unlock_irqrestore(&gp->lock, flags);
up(&gp->pm_sem);
@@ -2779,6 +2911,47 @@ static int __devinit gem_get_device_address(struct gem *gp)
return 0;
}
+static void __devexit gem_remove_one(struct pci_dev *pdev)
+{
+ struct net_device *dev = pci_get_drvdata(pdev);
+
+ if (dev) {
+ struct gem *gp = dev->priv;
+
+ unregister_netdev(dev);
+
+ /* Stop the link timer */
+ del_timer_sync(&gp->link_timer);
+
+ /* We shouldn't need any locking here */
+ gem_get_cell(gp);
+
+ /* Wait for a pending reset task to complete */
+ while (gp->reset_task_pending)
+ yield();
+ flush_scheduled_work();
+
+ /* Shut the PHY down */
+ gem_stop_phy(gp, 0);
+
+ gem_put_cell(gp);
+
+ /* Make sure bus master is disabled */
+ pci_disable_device(gp->pdev);
+
+ /* Free resources */
+ pci_free_consistent(pdev,
+ sizeof(struct gem_init_block),
+ gp->init_block,
+ gp->gblock_dvma);
+ iounmap(gp->regs);
+ pci_release_regions(pdev);
+ free_netdev(dev);
+
+ pci_set_drvdata(pdev, NULL);
+ }
+}
+
static int __devinit gem_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
@@ -2827,7 +3000,7 @@ static int __devinit gem_init_one(struct pci_dev *pdev,
}
pci_using_dac = 0;
}
-
+
gemreg_base = pci_resource_start(pdev, 0);
gemreg_len = pci_resource_len(pdev, 0);
@@ -2870,11 +3043,6 @@ static int __devinit gem_init_one(struct pci_dev *pdev,
gp->link_timer.function = gem_link_timer;
gp->link_timer.data = (unsigned long) gp;
- init_timer(&gp->pm_timer);
- gp->pm_timer.function = gem_pm_timer;
- gp->pm_timer.data = (unsigned long) gp;
-
- INIT_WORK(&gp->pm_task, gem_pm_task, gp);
INIT_WORK(&gp->reset_task, gem_reset_task, gp);
gp->lstate = link_down;
@@ -2889,20 +3057,22 @@ static int __devinit gem_init_one(struct pci_dev *pdev,
goto err_out_free_res;
}
- /* On Apple, we power the chip up now in order for check
- * invariants to work, but also because the firmware might
- * not have properly shut down the PHY.
+ /* On Apple, we want a reference to the Open Firmware device-tree
+ * node. We use it for clock control.
*/
#ifdef CONFIG_PPC_PMAC
gp->of_node = pci_device_to_OF_node(pdev);
- if (pdev->vendor == PCI_VENDOR_ID_APPLE)
- gem_apple_powerup(gp);
#endif
- spin_lock_irq(&gp->lock);
- spin_lock(&gp->tx_lock);
- gem_stop(gp);
- spin_unlock(&gp->tx_lock);
- spin_unlock_irq(&gp->lock);
+
+ /* Only Apple version supports WOL afaik */
+ if (pdev->vendor == PCI_VENDOR_ID_APPLE)
+ gp->has_wol = 1;
+
+ /* Make sure cell is enabled */
+ gem_get_cell(gp);
+
+ /* Make sure everything is stopped and in init state */
+ gem_reset(gp);
/* Fill up the mii_phy structure (even if we won't use it) */
gp->phy_mii.dev = dev;
@@ -2911,7 +3081,8 @@ static int __devinit gem_init_one(struct pci_dev *pdev,
/* By default, we start with autoneg */
gp->want_autoneg = 1;
-
+
+ /* Check fifo sizes, PHY type, etc... */
if (gem_check_invariants(gp)) {
err = -ENODEV;
goto err_out_iounmap;
@@ -2951,6 +3122,19 @@ static int __devinit gem_init_one(struct pci_dev *pdev,
dev->poll_controller = gem_poll_controller;
#endif
+ /* Set that now, in case PM kicks in now */
+ pci_set_drvdata(pdev, dev);
+
+ /* Detect & init PHY, start autoneg, we release the cell now
+ * too, it will be managed by whoever needs it
+ */
+ gem_init_phy(gp);
+
+ spin_lock_irq(&gp->lock);
+ gem_put_cell(gp);
+ spin_unlock_irq(&gp->lock);
+
+ /* Register with kernel */
if (register_netdev(dev)) {
printk(KERN_ERR PFX "Cannot register net device, "
"aborting.\n");
@@ -2965,48 +3149,22 @@ static int __devinit gem_init_one(struct pci_dev *pdev,
i == 5 ? ' ' : ':');
printk("\n");
- /* Detect & init PHY, start autoneg */
- spin_lock_irq(&gp->lock);
- spin_lock(&gp->tx_lock);
- gp->hw_running = 1;
- gem_init_phy(gp);
- gem_begin_auto_negotiation(gp, NULL);
- spin_unlock(&gp->tx_lock);
- spin_unlock_irq(&gp->lock);
-
if (gp->phy_type == phy_mii_mdio0 ||
gp->phy_type == phy_mii_mdio1)
printk(KERN_INFO "%s: Found %s PHY\n", dev->name,
gp->phy_mii.def ? gp->phy_mii.def->name : "no");
- pci_set_drvdata(pdev, dev);
-
/* GEM can do it all... */
dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_LLTX;
if (pci_using_dac)
dev->features |= NETIF_F_HIGHDMA;
- /* Fire the PM timer that will shut us down in about 10 seconds */
- gp->pm_timer.expires = jiffies + 10*HZ;
- add_timer(&gp->pm_timer);
-
return 0;
err_out_free_consistent:
- pci_free_consistent(pdev,
- sizeof(struct gem_init_block),
- gp->init_block,
- gp->gblock_dvma);
-
+ gem_remove_one(pdev);
err_out_iounmap:
- down(&gp->pm_sem);
- /* Stop the PM timer & task */
- del_timer_sync(&gp->pm_timer);
- flush_scheduled_work();
- if (gp->hw_running)
- gem_shutdown(gp);
- up(&gp->pm_sem);
-
+ gem_put_cell(gp);
iounmap(gp->regs);
err_out_free_res:
@@ -3020,34 +3178,6 @@ err_disable_device:
}
-static void __devexit gem_remove_one(struct pci_dev *pdev)
-{
- struct net_device *dev = pci_get_drvdata(pdev);
-
- if (dev) {
- struct gem *gp = dev->priv;
-
- unregister_netdev(dev);
-
- down(&gp->pm_sem);
- /* Stop the PM timer & task */
- del_timer_sync(&gp->pm_timer);
- flush_scheduled_work();
- if (gp->hw_running)
- gem_shutdown(gp);
- up(&gp->pm_sem);
-
- pci_free_consistent(pdev,
- sizeof(struct gem_init_block),
- gp->init_block,
- gp->gblock_dvma);
- iounmap(gp->regs);
- pci_release_regions(pdev);
- free_netdev(dev);
-
- pci_set_drvdata(pdev, NULL);
- }
-}
static struct pci_driver gem_driver = {
.name = GEM_MODULE_NAME,
diff --git a/drivers/net/sungem.h b/drivers/net/sungem.h
index 00343226fb71e..7143fd7cf3f84 100644
--- a/drivers/net/sungem.h
+++ b/drivers/net/sungem.h
@@ -170,6 +170,27 @@
* them later. -DaveM
*/
+/* WakeOnLan Registers */
+#define WOL_MATCH0 0x3000UL
+#define WOL_MATCH1 0x3004UL
+#define WOL_MATCH2 0x3008UL
+#define WOL_MCOUNT 0x300CUL
+#define WOL_WAKECSR 0x3010UL
+
+/* WOL Match count register
+ */
+#define WOL_MCOUNT_N 0x00000010
+#define WOL_MCOUNT_M 0x00000000 /* 0 << 8 */
+
+#define WOL_WAKECSR_ENABLE 0x00000001
+#define WOL_WAKECSR_MII 0x00000002
+#define WOL_WAKECSR_SEEN 0x00000004
+#define WOL_WAKECSR_FILT_UCAST 0x00000008
+#define WOL_WAKECSR_FILT_MCAST 0x00000010
+#define WOL_WAKECSR_FILT_BCAST 0x00000020
+#define WOL_WAKECSR_FILT_SEEN 0x00000040
+
+
/* Receive DMA Registers */
#define RXDMA_CFG 0x4000UL /* RX Configuration Register */
#define RXDMA_DBLOW 0x4004UL /* RX Descriptor Base Low */
@@ -952,45 +973,38 @@ enum link_state {
};
struct gem {
- spinlock_t lock;
- spinlock_t tx_lock;
- void __iomem *regs;
- int rx_new, rx_old;
- int tx_new, tx_old;
-
- /* Set when chip is actually in operational state
- * (ie. not power managed)
- */
- int hw_running;
- int opened;
- struct semaphore pm_sem;
- struct work_struct pm_task;
- struct timer_list pm_timer;
-
- struct gem_init_block *init_block;
-
- struct sk_buff *rx_skbs[RX_RING_SIZE];
- struct sk_buff *tx_skbs[RX_RING_SIZE];
+ spinlock_t lock;
+ spinlock_t tx_lock;
+ void __iomem *regs;
+ int rx_new, rx_old;
+ int tx_new, tx_old;
+
+ unsigned int has_wol : 1; /* chip supports wake-on-lan */
+ unsigned int asleep : 1; /* chip asleep, protected by pm_sem */
+ unsigned int asleep_wol : 1; /* was asleep with WOL enabled */
+ unsigned int opened : 1; /* driver opened, protected by pm_sem */
+ unsigned int running : 1; /* chip running, protected by lock */
+
+ /* cell enable count, protected by lock */
+ int cell_enabled;
+
+ struct semaphore pm_sem;
u32 msg_enable;
u32 status;
struct net_device_stats net_stats;
- enum gem_phy_type phy_type;
- struct mii_phy phy_mii;
-
int tx_fifo_sz;
int rx_fifo_sz;
int rx_pause_off;
int rx_pause_on;
int rx_buf_sz;
- int mii_phy_addr;
-
+ u64 pause_entered;
+ u16 pause_last_time_recvd;
u32 mac_rx_cfg;
u32 swrst_base;
- /* Autoneg & PHY control */
int want_autoneg;
int last_forced_speed;
enum link_state lstate;
@@ -999,14 +1013,18 @@ struct gem {
int wake_on_lan;
struct work_struct reset_task;
volatile int reset_task_pending;
-
- /* Diagnostic counters and state. */
- u64 pause_entered;
- u16 pause_last_time_recvd;
- dma_addr_t gblock_dvma;
- struct pci_dev *pdev;
- struct net_device *dev;
+ enum gem_phy_type phy_type;
+ struct mii_phy phy_mii;
+ int mii_phy_addr;
+
+ struct gem_init_block *init_block;
+ struct sk_buff *rx_skbs[RX_RING_SIZE];
+ struct sk_buff *tx_skbs[RX_RING_SIZE];
+ dma_addr_t gblock_dvma;
+
+ struct pci_dev *pdev;
+ struct net_device *dev;
#ifdef CONFIG_PPC_PMAC
struct device_node *of_node;
#endif
diff --git a/drivers/net/sungem_phy.c b/drivers/net/sungem_phy.c
index dd3786097bbcf..0fca414d3657f 100644
--- a/drivers/net/sungem_phy.c
+++ b/drivers/net/sungem_phy.c
@@ -98,25 +98,15 @@ static int bcm5201_init(struct mii_phy* phy)
data &= ~MII_BCM5201_MULTIPHY_SUPERISOLATE;
phy_write(phy, MII_BCM5201_MULTIPHY, data);
+ phy_write(phy, MII_BCM5201_INTERRUPT, 0);
+
return 0;
}
-static int bcm5201_suspend(struct mii_phy* phy, int wol_options)
+static int bcm5201_suspend(struct mii_phy* phy)
{
- if (!wol_options)
- phy_write(phy, MII_BCM5201_INTERRUPT, 0);
-
- /* Here's a strange hack used by both MacOS 9 and X */
- phy_write(phy, MII_LPA, phy_read(phy, MII_LPA));
-
- if (!wol_options) {
-#if 0 /* Commented out in Darwin... someone has those dawn docs ? */
- u16 val = phy_read(phy, MII_BCM5201_AUXMODE2)
- phy_write(phy, MII_BCM5201_AUXMODE2,
- val & ~MII_BCM5201_AUXMODE2_LOWPOWER);
-#endif
- phy_write(phy, MII_BCM5201_MULTIPHY, MII_BCM5201_MULTIPHY_SUPERISOLATE);
- }
+ phy_write(phy, MII_BCM5201_INTERRUPT, 0);
+ phy_write(phy, MII_BCM5201_MULTIPHY, MII_BCM5201_MULTIPHY_SUPERISOLATE);
return 0;
}
@@ -144,6 +134,21 @@ static int bcm5221_init(struct mii_phy* phy)
return 0;
}
+static int bcm5221_suspend(struct mii_phy* phy)
+{
+ u16 data;
+
+ data = phy_read(phy, MII_BCM5221_TEST);
+ phy_write(phy, MII_BCM5221_TEST,
+ data | MII_BCM5221_TEST_ENABLE_SHADOWS);
+
+ data = phy_read(phy, MII_BCM5221_SHDOW_AUX_MODE4);
+ phy_write(phy, MII_BCM5221_SHDOW_AUX_MODE4,
+ data | MII_BCM5221_SHDOW_AUX_MODE4_IDDQMODE);
+
+ return 0;
+}
+
static int bcm5400_init(struct mii_phy* phy)
{
u16 data;
@@ -173,7 +178,7 @@ static int bcm5400_init(struct mii_phy* phy)
return 0;
}
-static int bcm5400_suspend(struct mii_phy* phy, int wol_options)
+static int bcm5400_suspend(struct mii_phy* phy)
{
#if 0 /* Commented out in Darwin... someone has those dawn docs ? */
phy_write(phy, MII_BMCR, BMCR_PDOWN);
@@ -229,7 +234,7 @@ static int bcm5401_init(struct mii_phy* phy)
return 0;
}
-static int bcm5401_suspend(struct mii_phy* phy, int wol_options)
+static int bcm5401_suspend(struct mii_phy* phy)
{
#if 0 /* Commented out in Darwin... someone has those dawn docs ? */
phy_write(phy, MII_BMCR, BMCR_PDOWN);
@@ -266,7 +271,7 @@ static int bcm5411_init(struct mii_phy* phy)
return 0;
}
-static int bcm5411_suspend(struct mii_phy* phy, int wol_options)
+static int bcm5411_suspend(struct mii_phy* phy)
{
phy_write(phy, MII_BMCR, BMCR_PDOWN);
@@ -662,7 +667,7 @@ static struct mii_phy_def bcm5201_phy_def = {
/* Broadcom BCM 5221 */
static struct mii_phy_ops bcm5221_phy_ops = {
- .suspend = bcm5201_suspend,
+ .suspend = bcm5221_suspend,
.init = bcm5221_init,
.setup_aneg = genmii_setup_aneg,
.setup_forced = genmii_setup_forced,
diff --git a/drivers/net/sungem_phy.h b/drivers/net/sungem_phy.h
index b86573804e620..822cb58174ea2 100644
--- a/drivers/net/sungem_phy.h
+++ b/drivers/net/sungem_phy.h
@@ -7,7 +7,7 @@ struct mii_phy;
struct mii_phy_ops
{
int (*init)(struct mii_phy *phy);
- int (*suspend)(struct mii_phy *phy, int wol_options);
+ int (*suspend)(struct mii_phy *phy);
int (*setup_aneg)(struct mii_phy *phy, u32 advertise);
int (*setup_forced)(struct mii_phy *phy, int speed, int fd);
int (*poll_link)(struct mii_phy *phy);
@@ -80,6 +80,7 @@ extern int mii_phy_probe(struct mii_phy *phy, int mii_id);
#define MII_BCM5221_SHDOW_AUX_STAT2 0x1b
#define MII_BCM5221_SHDOW_AUX_STAT2_APD 0x0020
#define MII_BCM5221_SHDOW_AUX_MODE4 0x1a
+#define MII_BCM5221_SHDOW_AUX_MODE4_IDDQMODE 0x0001
#define MII_BCM5221_SHDOW_AUX_MODE4_CLKLOPWR 0x0004
/* MII BCM5400 1000-BASET Control register */
diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c
index 1b2c4b9274b84..d837b3c357231 100644
--- a/drivers/net/sunhme.c
+++ b/drivers/net/sunhme.c
@@ -175,13 +175,13 @@ static __inline__ void tx_dump_ring(struct happy_meal *hp)
#define DEFAULT_IPG2 4 /* For all modes */
#define DEFAULT_JAMSIZE 4 /* Toe jam */
-#ifdef CONFIG_PCI
+#if defined(CONFIG_PCI) && defined(MODULE)
/* This happy_pci_ids is declared __initdata because it is only used
as an advisory to depmod. If this is ported to the new PCI interface
where it could be referenced at any time due to hot plugging,
the __initdata reference should be removed. */
-struct pci_device_id happymeal_pci_ids[] = {
+static struct pci_device_id happymeal_pci_ids[] = {
{
.vendor = PCI_VENDOR_ID_SUN,
.device = PCI_DEVICE_ID_SUN_HAPPYMEAL,
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index b5931a0c76642..12de80884b1aa 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -4,6 +4,7 @@
* Copyright (C) 2001, 2002, 2003, 2004 David S. Miller (davem@redhat.com)
* Copyright (C) 2001, 2002, 2003 Jeff Garzik (jgarzik@pobox.com)
* Copyright (C) 2004 Sun Microsystems Inc.
+ * Copyright (C) 2005 Broadcom Corporation.
*
* Firmware is:
* Copyright (C) 2000-2003 Broadcom Corporation.
@@ -60,8 +61,8 @@
#define DRV_MODULE_NAME "tg3"
#define PFX DRV_MODULE_NAME ": "
-#define DRV_MODULE_VERSION "3.23"
-#define DRV_MODULE_RELDATE "February 15, 2005"
+#define DRV_MODULE_VERSION "3.25"
+#define DRV_MODULE_RELDATE "March 24, 2005"
#define TG3_DEF_MAC_MODE 0
#define TG3_DEF_RX_MODE 0
@@ -103,9 +104,7 @@
* replace things like '% foo' with '& (foo - 1)'.
*/
#define TG3_RX_RCB_RING_SIZE(tp) \
- ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 || \
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) ? \
- 512 : 1024)
+ ((tp->tg3_flags2 & TG3_FLG2_5705_PLUS) ? 512 : 1024)
#define TG3_TX_RING_SIZE 512
#define TG3_DEF_TX_RING_PENDING (TG3_TX_RING_SIZE - 1)
@@ -468,8 +467,7 @@ static void tg3_switch_clocks(struct tg3 *tp)
0x1f);
tp->pci_clock_ctrl = clock_ctrl;
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) {
+ if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) {
if (orig_clock_ctrl & CLOCK_CTRL_625_CORE) {
tw32_f(TG3PCI_CLOCK_CTRL,
clock_ctrl | CLOCK_CTRL_625_CORE);
@@ -871,6 +869,19 @@ out:
!tg3_readphy(tp, MII_TG3_AUX_CTRL, &phy_reg))
tg3_writephy(tp, MII_TG3_AUX_CTRL, phy_reg | 0x4000);
}
+
+ /* Set phy register 0x10 bit 0 to high fifo elasticity to support
+ * jumbo frames transmission.
+ */
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 &&
+ GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750) {
+ u32 phy_reg;
+
+ if (!tg3_readphy(tp, MII_TG3_EXT_CTRL, &phy_reg))
+ tg3_writephy(tp, MII_TG3_EXT_CTRL,
+ phy_reg | MII_TG3_EXT_CTRL_FIFO_ELASTIC);
+ }
+
tg3_phy_set_wirespeed(tp);
return 0;
}
@@ -969,6 +980,7 @@ static int tg3_setup_phy(struct tg3 *, int);
#define RESET_KIND_SUSPEND 2
static void tg3_write_sig_post_reset(struct tg3 *, int);
+static int tg3_halt_cpu(struct tg3 *, u32);
static int tg3_set_power_state(struct tg3 *tp, int state)
{
@@ -1093,8 +1105,7 @@ static int tg3_set_power_state(struct tg3 *tp, int state)
CLOCK_CTRL_TXCLK_DISABLE |
CLOCK_CTRL_ALTCLK);
newbits2 = newbits1 | CLOCK_CTRL_44MHZ_CORE;
- } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) {
+ } else if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) {
newbits1 = CLOCK_CTRL_625_CORE;
newbits2 = newbits1 | CLOCK_CTRL_ALTCLK;
} else {
@@ -1108,8 +1119,7 @@ static int tg3_set_power_state(struct tg3 *tp, int state)
tw32_f(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl | newbits2);
udelay(40);
- if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 &&
- GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750) {
+ if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) {
u32 newbits3;
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
@@ -1129,6 +1139,17 @@ static int tg3_set_power_state(struct tg3 *tp, int state)
tg3_frob_aux_power(tp);
+ /* Workaround for unstable PLL clock */
+ if ((GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5750_AX) ||
+ (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5750_BX)) {
+ u32 val = tr32(0x7d00);
+
+ val &= ~((1 << 16) | (1 << 4) | (1 << 2) | (1 << 1) | 1);
+ tw32(0x7d00, val);
+ if (!(tp->tg3_flags & TG3_FLAG_ENABLE_ASF))
+ tg3_halt_cpu(tp, RX_CPU_BASE);
+ }
+
/* Finally, set the new power state. */
pci_write_config_word(tp->pdev, pm + PCI_PM_CTRL, power_control);
@@ -2448,8 +2469,7 @@ static int tg3_setup_phy(struct tg3 *tp, int force_reset)
(6 << TX_LENGTHS_IPG_SHIFT) |
(32 << TX_LENGTHS_SLOT_TIME_SHIFT)));
- if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 &&
- GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750) {
+ if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) {
if (netif_carrier_ok(tp->dev)) {
tw32(HOSTCC_STAT_COAL_TICKS,
DEFAULT_STAT_COAL_TICKS);
@@ -2892,7 +2912,13 @@ static irqreturn_t tg3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
spin_lock_irqsave(&tp->lock, flags);
- if (sblk->status & SD_STATUS_UPDATED) {
+ /* In INTx mode, it is possible for the interrupt to arrive at
+ * the CPU before the status block posted prior to the interrupt.
+ * Reading the PCI State register will confirm whether the
+ * interrupt is ours and will flush the status block.
+ */
+ if ((sblk->status & SD_STATUS_UPDATED) ||
+ !(tr32(TG3PCI_PCISTATE) & PCISTATE_INT_NOT_ACTIVE)) {
/*
* writing any value to intr-mbox-0 clears PCI INTA# and
* chip-internal interrupt pending events.
@@ -3017,6 +3043,7 @@ static int tigon3_4gb_hwbug_workaround(struct tg3 *tp, struct sk_buff *skb,
tp->tx_buffers[entry].skb = NULL;
}
entry = NEXT_TX(entry);
+ i++;
}
dev_kfree_skb(skb);
@@ -3110,6 +3137,12 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
(mss = skb_shinfo(skb)->tso_size) != 0) {
int tcp_opt_len, ip_tcp_len;
+ if (skb_header_cloned(skb) &&
+ pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) {
+ dev_kfree_skb(skb);
+ goto out_unlock;
+ }
+
tcp_opt_len = ((skb->h.th->doff - 5) * 4);
ip_tcp_len = (skb->nh.iph->ihl * 4) + sizeof(struct tcphdr);
@@ -3562,8 +3595,7 @@ static int tg3_stop_block(struct tg3 *tp, unsigned long ofs, u32 enable_bit)
unsigned int i;
u32 val;
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) {
+ if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) {
switch (ofs) {
case RCVLSC_MODE:
case DMAC_MODE:
@@ -3697,8 +3729,9 @@ static void tg3_nvram_unlock(struct tg3 *tp)
/* tp->lock is held. */
static void tg3_write_sig_pre_reset(struct tg3 *tp, int kind)
{
- tg3_write_mem(tp, NIC_SRAM_FIRMWARE_MBOX,
- NIC_SRAM_FIRMWARE_MBOX_MAGIC1);
+ if (!(tp->tg3_flags2 & TG3_FLG2_SUN_570X))
+ tg3_write_mem(tp, NIC_SRAM_FIRMWARE_MBOX,
+ NIC_SRAM_FIRMWARE_MBOX_MAGIC1);
if (tp->tg3_flags2 & TG3_FLG2_ASF_NEW_HANDSHAKE) {
switch (kind) {
@@ -3804,8 +3837,7 @@ static int tg3_chip_reset(struct tg3 *tp)
}
}
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750)
+ if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS)
val |= GRC_MISC_CFG_KEEP_GPHY_POWER;
tw32(GRC_MISC_CFG, val);
@@ -3902,19 +3934,20 @@ static int tg3_chip_reset(struct tg3 *tp)
tw32_f(MAC_MODE, 0);
udelay(40);
- /* Wait for firmware initialization to complete. */
- for (i = 0; i < 100000; i++) {
- tg3_read_mem(tp, NIC_SRAM_FIRMWARE_MBOX, &val);
- if (val == ~NIC_SRAM_FIRMWARE_MBOX_MAGIC1)
- break;
- udelay(10);
- }
- if (i >= 100000 &&
- !(tp->tg3_flags2 & TG3_FLG2_SUN_570X)) {
- printk(KERN_ERR PFX "tg3_reset_hw timed out for %s, "
- "firmware will not restart magic=%08x\n",
- tp->dev->name, val);
- return -ENODEV;
+ if (!(tp->tg3_flags2 & TG3_FLG2_SUN_570X)) {
+ /* Wait for firmware initialization to complete. */
+ for (i = 0; i < 100000; i++) {
+ tg3_read_mem(tp, NIC_SRAM_FIRMWARE_MBOX, &val);
+ if (val == ~NIC_SRAM_FIRMWARE_MBOX_MAGIC1)
+ break;
+ udelay(10);
+ }
+ if (i >= 100000) {
+ printk(KERN_ERR PFX "tg3_reset_hw timed out for %s, "
+ "firmware will not restart magic=%08x\n",
+ tp->dev->name, val);
+ return -ENODEV;
+ }
}
if ((tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) &&
@@ -4119,7 +4152,7 @@ static int tg3_halt_cpu(struct tg3 *tp, u32 offset)
int i;
if (offset == TX_CPU_BASE &&
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705)
+ (tp->tg3_flags2 & TG3_FLG2_5705_PLUS))
BUG();
if (offset == RX_CPU_BASE) {
@@ -4173,14 +4206,14 @@ static int tg3_load_firmware_cpu(struct tg3 *tp, u32 cpu_base, u32 cpu_scratch_b
void (*write_op)(struct tg3 *, u32, u32);
if (cpu_base == TX_CPU_BASE &&
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) {
+ (tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) {
printk(KERN_ERR PFX "tg3_load_firmware_cpu: Trying to load "
"TX cpu firmware on %s which is 5705.\n",
tp->dev->name);
return -EINVAL;
}
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705)
+ if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS)
write_op = tg3_write_mem;
else
write_op = tg3_write_indirect_reg32;
@@ -4920,8 +4953,7 @@ static void tg3_set_bdinfo(struct tg3 *tp, u32 bdinfo_addr,
(bdinfo_addr + TG3_BDINFO_MAXLEN_FLAGS),
maxlen_flags);
- if ((GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) &&
- (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750))
+ if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS))
tg3_write_mem(tp,
(bdinfo_addr + TG3_BDINFO_NIC_ADDR),
nic_addr);
@@ -5099,8 +5131,7 @@ static int tg3_reset_hw(struct tg3 *tp)
/* Don't even try to program the JUMBO/MINI buffer descriptor
* configs on 5705.
*/
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) {
+ if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) {
tw32(RCVDBDI_STD_BD + TG3_BDINFO_MAXLEN_FLAGS,
RX_STD_MAX_SIZE_5705 << BDINFO_FLAGS_MAXLEN_SHIFT);
} else {
@@ -5132,8 +5163,7 @@ static int tg3_reset_hw(struct tg3 *tp)
/* There is only one send ring on 5705/5750, no need to explicitly
* disable the others.
*/
- if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 &&
- GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750) {
+ if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) {
/* Clear out send RCB ring in SRAM. */
for (i = NIC_SRAM_SEND_RCB; i < NIC_SRAM_RCV_RET_RCB; i += TG3_BDINFO_SIZE)
tg3_write_mem(tp, i + TG3_BDINFO_MAXLEN_FLAGS,
@@ -5154,8 +5184,7 @@ static int tg3_reset_hw(struct tg3 *tp)
/* There is only one receive return ring on 5705/5750, no need
* to explicitly disable the others.
*/
- if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 &&
- GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750) {
+ if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) {
for (i = NIC_SRAM_RCV_RET_RCB; i < NIC_SRAM_STATS_BLK;
i += TG3_BDINFO_SIZE) {
tg3_write_mem(tp, i + TG3_BDINFO_MAXLEN_FLAGS,
@@ -5254,8 +5283,7 @@ static int tg3_reset_hw(struct tg3 *tp)
tw32(HOSTCC_TXCOL_TICKS, LOW_TXCOL_TICKS);
tw32(HOSTCC_RXMAX_FRAMES, 1);
tw32(HOSTCC_TXMAX_FRAMES, LOW_RXMAX_FRAMES);
- if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 &&
- GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750) {
+ if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) {
tw32(HOSTCC_RXCOAL_TICK_INT, 0);
tw32(HOSTCC_TXCOAL_TICK_INT, 0);
}
@@ -5268,8 +5296,7 @@ static int tg3_reset_hw(struct tg3 *tp)
tw32(HOSTCC_STATUS_BLK_HOST_ADDR + TG3_64BIT_REG_LOW,
((u64) tp->status_mapping & 0xffffffff));
- if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 &&
- GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750) {
+ if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) {
/* Status/statistics block address. See tg3_timer,
* the tg3_periodic_fetch_stats call there, and
* tg3_get_stats to see how this works for 5705/5750 chips.
@@ -5288,8 +5315,7 @@ static int tg3_reset_hw(struct tg3 *tp)
tw32(RCVCC_MODE, RCVCC_MODE_ENABLE | RCVCC_MODE_ATTN_ENABLE);
tw32(RCVLPC_MODE, RCVLPC_MODE_ENABLE);
- if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 &&
- GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750)
+ if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS))
tw32(RCVLSC_MODE, RCVLSC_MODE_ENABLE | RCVLSC_MODE_ATTN_ENABLE);
/* Clear statistics/status block in chip, and status block in ram. */
@@ -5316,8 +5342,7 @@ static int tg3_reset_hw(struct tg3 *tp)
tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0);
tr32(MAILBOX_INTERRUPT_0);
- if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 &&
- GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750) {
+ if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) {
tw32_f(DMAC_MODE, DMAC_MODE_ENABLE);
udelay(40);
}
@@ -5364,8 +5389,7 @@ static int tg3_reset_hw(struct tg3 *tp)
udelay(40);
tw32(RCVDCC_MODE, RCVDCC_MODE_ENABLE | RCVDCC_MODE_ATTN_ENABLE);
- if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 &&
- GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750)
+ if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS))
tw32(MBFREE_MODE, MBFREE_MODE_ENABLE);
tw32(SNDDATAC_MODE, SNDDATAC_MODE_ENABLE);
tw32(SNDBDC_MODE, SNDBDC_MODE_ENABLE | SNDBDC_MODE_ATTN_ENABLE);
@@ -5469,8 +5493,7 @@ static int tg3_reset_hw(struct tg3 *tp)
tw32(MAC_RCV_RULE_1, 0x86000004 & RCV_RULE_DISABLE_MASK);
tw32(MAC_RCV_VALUE_1, 0xffffffff & RCV_RULE_DISABLE_MASK);
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750)
+ if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS)
limit = 8;
else
limit = 16;
@@ -5614,8 +5637,7 @@ static void tg3_timer(unsigned long __opaque)
return;
}
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750)
+ if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS)
tg3_periodic_fetch_stats(tp);
/* This part only runs once per second. */
@@ -6524,10 +6546,6 @@ static int tg3_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
struct tg3 *tp = netdev_priv(dev);
- if (!(tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) ||
- tp->link_config.phy_is_low_power)
- return -EAGAIN;
-
cmd->supported = (SUPPORTED_Autoneg);
if (!(tp->tg3_flags & TG3_FLAG_10_100_ONLY))
@@ -6544,8 +6562,10 @@ static int tg3_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
cmd->supported |= SUPPORTED_FIBRE;
cmd->advertising = tp->link_config.advertising;
- cmd->speed = tp->link_config.active_speed;
- cmd->duplex = tp->link_config.active_duplex;
+ if (netif_running(dev)) {
+ cmd->speed = tp->link_config.active_speed;
+ cmd->duplex = tp->link_config.active_duplex;
+ }
cmd->port = 0;
cmd->phy_address = PHY_ADDR;
cmd->transceiver = 0;
@@ -6559,10 +6579,6 @@ static int tg3_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
struct tg3 *tp = netdev_priv(dev);
- if (!(tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) ||
- tp->link_config.phy_is_low_power)
- return -EAGAIN;
-
if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) {
/* These are the only valid advertisement bits allowed. */
if (cmd->autoneg == AUTONEG_ENABLE &&
@@ -6587,7 +6603,9 @@ static int tg3_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
tp->link_config.duplex = cmd->duplex;
}
- tg3_setup_phy(tp, 1);
+ if (netif_running(dev))
+ tg3_setup_phy(tp, 1);
+
spin_unlock(&tp->tx_lock);
spin_unlock_irq(&tp->lock);
@@ -6667,6 +6685,9 @@ static int tg3_nway_reset(struct net_device *dev)
u32 bmcr;
int r;
+ if (!netif_running(dev))
+ return -EAGAIN;
+
spin_lock_irq(&tp->lock);
r = -EINVAL;
tg3_readphy(tp, MII_BMCR, &bmcr);
@@ -6703,7 +6724,9 @@ static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *e
(ering->tx_pending > TG3_TX_RING_SIZE - 1))
return -EINVAL;
- tg3_netif_stop(tp);
+ if (netif_running(dev))
+ tg3_netif_stop(tp);
+
spin_lock_irq(&tp->lock);
spin_lock(&tp->tx_lock);
@@ -6715,9 +6738,12 @@ static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *e
tp->rx_jumbo_pending = ering->rx_jumbo_pending;
tp->tx_pending = ering->tx_pending;
- tg3_halt(tp);
- tg3_init_hw(tp);
- tg3_netif_start(tp);
+ if (netif_running(dev)) {
+ tg3_halt(tp);
+ tg3_init_hw(tp);
+ tg3_netif_start(tp);
+ }
+
spin_unlock(&tp->tx_lock);
spin_unlock_irq(&tp->lock);
@@ -6737,7 +6763,9 @@ static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam
{
struct tg3 *tp = netdev_priv(dev);
- tg3_netif_stop(tp);
+ if (netif_running(dev))
+ tg3_netif_stop(tp);
+
spin_lock_irq(&tp->lock);
spin_lock(&tp->tx_lock);
if (epause->autoneg)
@@ -6752,9 +6780,12 @@ static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam
tp->tg3_flags |= TG3_FLAG_TX_PAUSE;
else
tp->tg3_flags &= ~TG3_FLAG_TX_PAUSE;
- tg3_halt(tp);
- tg3_init_hw(tp);
- tg3_netif_start(tp);
+
+ if (netif_running(dev)) {
+ tg3_halt(tp);
+ tg3_init_hw(tp);
+ tg3_netif_start(tp);
+ }
spin_unlock(&tp->tx_lock);
spin_unlock_irq(&tp->lock);
@@ -7829,6 +7860,19 @@ static int __devinit tg3_is_sun_570X(struct tg3 *tp)
static int __devinit tg3_get_invariants(struct tg3 *tp)
{
+ static struct pci_device_id write_reorder_chipsets[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_82801AA_8) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_82801AB_8) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_82801BA_11) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_82801BA_6) },
+ { PCI_DEVICE(PCI_VENDOR_ID_AMD,
+ PCI_DEVICE_ID_AMD_FE_GATE_700C) },
+ { },
+ };
u32 misc_ctrl_reg;
u32 cacheline_sz_reg;
u32 pci_state_reg, grc_misc_cfg;
@@ -7847,16 +7891,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
* every mailbox register write to force the writes to be
* posted to the chip in order.
*/
- if (pci_find_device(PCI_VENDOR_ID_INTEL,
- PCI_DEVICE_ID_INTEL_82801AA_8, NULL) ||
- pci_find_device(PCI_VENDOR_ID_INTEL,
- PCI_DEVICE_ID_INTEL_82801AB_8, NULL) ||
- pci_find_device(PCI_VENDOR_ID_INTEL,
- PCI_DEVICE_ID_INTEL_82801BA_11, NULL) ||
- pci_find_device(PCI_VENDOR_ID_INTEL,
- PCI_DEVICE_ID_INTEL_82801BA_6, NULL) ||
- pci_find_device(PCI_VENDOR_ID_AMD,
- PCI_DEVICE_ID_AMD_FE_GATE_700C, NULL))
+ if (pci_dev_present(write_reorder_chipsets))
tp->tg3_flags |= TG3_FLAG_MBOX_WRITE_REORDER;
/* Force memory write invalidate off. If we leave it on,
@@ -7896,6 +7931,10 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
tp->pci_hdr_type = (cacheline_sz_reg >> 16) & 0xff;
tp->pci_bist = (cacheline_sz_reg >> 24) & 0xff;
+ if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) ||
+ (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750))
+ tp->tg3_flags2 |= TG3_FLG2_5705_PLUS;
+
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750)
tp->tg3_flags2 |= TG3_FLG2_HW_TSO;
@@ -8783,8 +8822,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
goto err_out_iounmap;
}
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) {
+ if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) {
tp->bufmgr_config.mbuf_read_dma_low_water =
DEFAULT_MB_RDMA_LOW_WATER_5705;
tp->bufmgr_config.mbuf_mac_rx_low_water =
@@ -8940,7 +8978,7 @@ static void __devexit tg3_remove_one(struct pci_dev *pdev)
}
}
-static int tg3_suspend(struct pci_dev *pdev, u32 state)
+static int tg3_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct net_device *dev = pci_get_drvdata(pdev);
struct tg3 *tp = netdev_priv(dev);
@@ -8967,7 +9005,7 @@ static int tg3_suspend(struct pci_dev *pdev, u32 state)
spin_unlock(&tp->tx_lock);
spin_unlock_irq(&tp->lock);
- err = tg3_set_power_state(tp, state);
+ err = tg3_set_power_state(tp, pci_choose_state(pdev, state));
if (err) {
spin_lock_irq(&tp->lock);
spin_lock(&tp->tx_lock);
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index 629f1897e3224..d48887d903250 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -140,6 +140,8 @@
#define CHIPREV_5703_AX 0x10
#define CHIPREV_5704_AX 0x20
#define CHIPREV_5704_BX 0x21
+#define CHIPREV_5750_AX 0x40
+#define CHIPREV_5750_BX 0x41
#define GET_METAL_REV(CHIP_REV_ID) ((CHIP_REV_ID) & 0xff)
#define METAL_REV_A0 0x00
#define METAL_REV_A1 0x01
@@ -1516,6 +1518,7 @@
#define MII_TG3_CTRL_ENABLE_AS_MASTER 0x1000
#define MII_TG3_EXT_CTRL 0x10 /* Extended control register */
+#define MII_TG3_EXT_CTRL_FIFO_ELASTIC 0x0001
#define MII_TG3_EXT_CTRL_LNK3_LED_MODE 0x0002
#define MII_TG3_EXT_CTRL_TBI 0x8000
@@ -1548,20 +1551,6 @@
#define MII_TG3_INT_DUPLEXCHG 0x0008
#define MII_TG3_INT_ANEG_PAGE_RX 0x0400
-/* XXX Add this to mii.h */
-#ifndef ADVERTISE_PAUSE
-#define ADVERTISE_PAUSE_CAP 0x0400
-#endif
-#ifndef ADVERTISE_PAUSE_ASYM
-#define ADVERTISE_PAUSE_ASYM 0x0800
-#endif
-#ifndef LPA_PAUSE
-#define LPA_PAUSE_CAP 0x0400
-#endif
-#ifndef LPA_PAUSE_ASYM
-#define LPA_PAUSE_ASYM 0x0800
-#endif
-
/* There are two ways to manage the TX descriptors on the tigon3.
* Either the descriptors are in host DMA'able memory, or they
* exist only in the cards on-chip SRAM. All 16 send bds are under
@@ -2110,6 +2099,7 @@ struct tg3 {
#define TG3_FLG2_FLASH 0x00008000
#define TG3_FLG2_HW_TSO 0x00010000
#define TG3_FLG2_SERDES_PREEMPHASIS 0x00020000
+#define TG3_FLG2_5705_PLUS 0x00040000
u32 split_mode_max_reqs;
#define SPLIT_MODE_5704_MAX_REQ 3
diff --git a/drivers/net/tokenring/ibmtr.c b/drivers/net/tokenring/ibmtr.c
index 4e5b1c5742828..c098863bdd9d4 100644
--- a/drivers/net/tokenring/ibmtr.c
+++ b/drivers/net/tokenring/ibmtr.c
@@ -227,7 +227,7 @@ static void __devinit PrtChanID(char *pcid, short stride)
printk("\n");
}
-static void __devinit HWPrtChanID(void * pcid, short stride)
+static void __devinit HWPrtChanID(void __iomem *pcid, short stride)
{
short i, j;
for (i = 0, j = 0; i < 24; i++, j += stride)
@@ -239,15 +239,16 @@ static void __devinit HWPrtChanID(void * pcid, short stride)
* going away.
*/
-static void __devinit find_turbo_adapters(int *iolist) {
+static void __devinit find_turbo_adapters(int *iolist)
+{
int ram_addr;
int index=0;
- void *chanid;
+ void __iomem *chanid;
int found_turbo=0;
unsigned char *tchanid, ctemp;
int i, j;
unsigned long jif;
- void *ram_mapped ;
+ void __iomem *ram_mapped ;
if (turbo_searched == 1) return;
turbo_searched=1;
@@ -328,8 +329,8 @@ static void ibmtr_cleanup_card(struct net_device *dev)
{
struct tok_info *ti = (struct tok_info *) dev->priv;
- iounmap((u32 *)ti->mmio);
- iounmap((u32 *)ti->sram_virt);
+ iounmap(ti->mmio);
+ iounmap(ti->sram_virt);
}
#endif
}
@@ -383,9 +384,9 @@ static int __devinit ibmtr_probe1(struct net_device *dev, int PIOaddr)
{
unsigned char segment, intr=0, irq=0, i, j, cardpresent=NOTOK, temp=0;
- void * t_mmio = NULL;
+ void __iomem * t_mmio = NULL;
struct tok_info *ti = dev->priv;
- void *cd_chanid;
+ void __iomem *cd_chanid;
unsigned char *tchanid, ctemp;
#ifndef PCMCIA
unsigned char t_irq=0;
@@ -428,7 +429,7 @@ static int __devinit ibmtr_probe1(struct net_device *dev, int PIOaddr)
*/
#ifdef PCMCIA
iounmap(t_mmio);
- t_mmio = (void *)ti->mmio; /*BMS to get virtual address */
+ t_mmio = ti->mmio; /*BMS to get virtual address */
irq = ti->irq; /*BMS to display the irq! */
#endif
cd_chanid = (CHANNEL_ID + t_mmio); /* for efficiency */
@@ -515,7 +516,7 @@ static int __devinit ibmtr_probe1(struct net_device *dev, int PIOaddr)
if (intr == 3) irq = 11;
ti->global_int_enable = 0;
ti->adapter_int_enable = 0;
- ti->sram_virt=(__u32)(inb(PIOaddr+ADAPTRESETREL) & 0xfe) << 12;
+ ti->sram_phys=(__u32)(inb(PIOaddr+ADAPTRESETREL) & 0xfe) << 12;
break;
case TR_ISAPNP:
if (!t_irq) {
@@ -533,7 +534,7 @@ static int __devinit ibmtr_probe1(struct net_device *dev, int PIOaddr)
kfree(ti);
return -ENODEV;
}
- ti->sram_virt =
+ ti->sram_phys =
((__u32)readb(ti->mmio+ACA_OFFSET+ACA_RW+RRR_EVEN)<<12);
ti->adapter_int_enable = PIOaddr + ADAPTINTREL;
break;
@@ -542,7 +543,7 @@ static int __devinit ibmtr_probe1(struct net_device *dev, int PIOaddr)
if (ibmtr_debug_trace & TRC_INIT) { /* just report int */
DPRINTK("irq=%d", irq);
- printk(", sram_virt=0x%x", ti->sram_virt);
+ printk(", sram_phys=0x%x", ti->sram_phys);
if(ibmtr_debug_trace&TRC_INITV){ /* full chat in verbose only */
DPRINTK(", ti->mmio=%p", ti->mmio);
printk(", segment=%02X", segment);
@@ -681,7 +682,7 @@ static int __devinit ibmtr_probe1(struct net_device *dev, int PIOaddr)
ibmtr_mem_base = chk_base;
}
}
- else ti->sram_base = ti->sram_virt >> 12;
+ else ti->sram_base = ti->sram_phys >> 12;
/* The PCMCIA has already got the interrupt line and the io port,
so no chance of anybody else getting it - MLP */
@@ -893,7 +894,7 @@ static int tok_open(struct net_device *dev)
*/
dev->flags &= ~IFF_RUNNING;
- ti->sram_virt &= ~1; /* to reverse what we do in tok_close */
+ ti->sram_phys &= ~1; /* to reverse what we do in tok_close */
/* init the spinlock */
spin_lock_init(&ti->lock);
init_timer(&ti->tr_timer);
@@ -1068,7 +1069,7 @@ static int tok_close(struct net_device *dev)
/* unloading the module from memory, and then if a timer pops, ouch */
del_timer_sync(&ti->tr_timer);
outb(0, dev->base_addr + ADAPTRESET);
- ti->sram_virt |= 1;
+ ti->sram_phys |= 1;
ti->open_status = CLOSED;
netif_stop_queue(dev);
@@ -1094,30 +1095,33 @@ static char *printerror[]={"Function failure","Signal loss","Reserved",
"IMPL force received","Duplicate modifier",
"No monitor detected","Monitor contention failed for RPL"};
-void dir_open_adapter (struct net_device *dev) {
+static void __iomem *map_address(struct tok_info *ti, unsigned index, __u8 *page)
+{
+ if (ti->page_mask) {
+ *page = (index >> 8) & ti->page_mask;
+ index &= ~(ti->page_mask << 8);
+ }
+ return ti->sram_virt + index;
+}
+void dir_open_adapter (struct net_device *dev)
+{
struct tok_info *ti = (struct tok_info *) dev->priv;
unsigned char ret_code;
__u16 err;
- ti->srb = ntohs(readw(ti->init_srb + SRB_ADDRESS_OFST));
- ti->ssb = ntohs(readw(ti->init_srb + SSB_ADDRESS_OFST));
- ti->arb = ntohs(readw(ti->init_srb + ARB_ADDRESS_OFST));
- ti->asb = ntohs(readw(ti->init_srb + ASB_ADDRESS_OFST));
- if (ti->page_mask) {
- ti->srb_page = (ti->srb >> 8) & ti->page_mask;
- ti->srb &= ~(ti->page_mask << 8);
- ti->ssb_page = (ti->ssb >> 8) & ti->page_mask;
- ti->ssb &= ~(ti->page_mask << 8);
- ti->arb_page = (ti->arb >> 8) & ti->page_mask;
- ti->arb &= ~(ti->page_mask << 8);
- ti->asb_page = (ti->asb >> 8) & ti->page_mask;
- ti->asb &= ~(ti->page_mask << 8);
- }
- ti->srb += ti->sram_virt;
- ti->ssb += ti->sram_virt;
- ti->arb += ti->sram_virt;
- ti->asb += ti->sram_virt;
+ ti->srb = map_address(ti,
+ ntohs(readw(ti->init_srb + SRB_ADDRESS_OFST)),
+ &ti->srb_page);
+ ti->ssb = map_address(ti,
+ ntohs(readw(ti->init_srb + SSB_ADDRESS_OFST)),
+ &ti->ssb_page);
+ ti->arb = map_address(ti,
+ ntohs(readw(ti->init_srb + ARB_ADDRESS_OFST)),
+ &ti->arb_page);
+ ti->asb = map_address(ti,
+ ntohs(readw(ti->init_srb + ASB_ADDRESS_OFST)),
+ &ti->asb_page);
ti->current_skb = NULL;
ret_code = readb(ti->init_srb + RETCODE_OFST);
err = ntohs(readw(ti->init_srb + OPEN_ERROR_CODE_OFST));
@@ -1188,7 +1192,7 @@ irqreturn_t tok_interrupt(int irq, void *dev_id, struct pt_regs *regs)
DPRINTK("Int from tok_driver, dev : %p irq%d regs=%p\n", dev,irq,regs);
#endif
ti = (struct tok_info *) dev->priv;
- if (ti->sram_virt & 1)
+ if (ti->sram_phys & 1)
return IRQ_NONE; /* PCMCIA card extraction flag */
spin_lock(&(ti->lock));
#ifdef ENABLE_PAGING
@@ -1220,15 +1224,11 @@ irqreturn_t tok_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (status & ADAP_CHK_INT) {
int i;
- __u32 check_reason;
+ void __iomem *check_reason;
__u8 check_reason_page = 0;
- check_reason =
- ntohs(readw(ti->mmio+ ACA_OFFSET+ACA_RW + WWCR_EVEN));
- if (ti->page_mask) {
- check_reason_page = (check_reason >> 8) & ti->page_mask;
- check_reason &= ~(ti->page_mask << 8);
- }
- check_reason += ti->sram_virt;
+ check_reason = map_address(ti,
+ ntohs(readw(ti->mmio+ ACA_OFFSET+ACA_RW + WWCR_EVEN)),
+ &check_reason_page);
SET_PAGE(check_reason_page);
DPRINTK("Adapter check interrupt\n");
@@ -1517,23 +1517,20 @@ static void initial_tok_int(struct net_device *dev)
/* we assign the shared-ram address for ISA devices */
writeb(ti->sram_base, ti->mmio + ACA_OFFSET + ACA_RW + RRR_EVEN);
#ifndef PCMCIA
- ti->sram_virt = (u32)ioremap(((__u32)ti->sram_base << 12), ti->avail_shared_ram);
+ ti->sram_virt = ioremap(((__u32)ti->sram_base << 12), ti->avail_shared_ram);
#endif
- ti->init_srb = ntohs(readw(ti->mmio + ACA_OFFSET + WRBR_EVEN));
- if (ti->page_mask) {
- ti->init_srb_page = (ti->init_srb >> 8) & ti->page_mask;
- ti->init_srb &= ~(ti->page_mask << 8);
- }
- ti->init_srb += ti->sram_virt;
+ ti->init_srb = map_address(ti,
+ ntohs(readw(ti->mmio + ACA_OFFSET + WRBR_EVEN)),
+ &ti->init_srb_page);
if (ti->page_mask && ti->avail_shared_ram == 127) {
- int last_512 = 0xfe00, i;
- int last_512_page=0;
- last_512_page=(last_512>>8)&ti->page_mask;
- last_512 &= ~(ti->page_mask << 8);
+ void __iomem *last_512;
+ __u8 last_512_page=0;
+ int i;
+ last_512 = map_address(ti, 0xfe00, &last_512_page);
/* initialize high section of ram (if necessary) */
SET_PAGE(last_512_page);
for (i = 0; i < 512; i++)
- writeb(0, ti->sram_virt + last_512 + i);
+ writeb(0, last_512 + i);
}
SET_PAGE(ti->init_srb_page);
@@ -1542,7 +1539,7 @@ static void initial_tok_int(struct net_device *dev)
int i;
DPRINTK("ti->init_srb_page=0x%x\n", ti->init_srb_page);
- DPRINTK("init_srb(%x):", (ti->init_srb) );
+ DPRINTK("init_srb(%p):", ti->init_srb );
for (i = 0; i < 20; i++)
printk("%02X ", (int) readb(ti->init_srb + i));
printk("\n");
@@ -1579,6 +1576,7 @@ static void tr_tx(struct net_device *dev)
struct trh_hdr *trhdr = (struct trh_hdr *) ti->current_skb->data;
unsigned int hdr_len;
__u32 dhb=0,dhb_base;
+ void __iomem *dhbuf = NULL;
unsigned char xmit_command;
int i,dhb_len=0x4000,src_len,src_offset;
struct trllc *llc;
@@ -1600,7 +1598,7 @@ static void tr_tx(struct net_device *dev)
dhb_page = (dhb_base >> 8) & ti->page_mask;
dhb=dhb_base & ~(ti->page_mask << 8);
}
- dhb += ti->sram_virt;
+ dhbuf = ti->sram_virt + dhb;
/* Figure out the size of the 802.5 header */
if (!(trhdr->saddr[0] & 0x80)) /* RIF present? */
@@ -1626,12 +1624,12 @@ static void tr_tx(struct net_device *dev)
writew(htons(0x11), ti->asb + FRAME_LENGTH_OFST);
writeb(0x0e, ti->asb + HEADER_LENGTH_OFST);
SET_PAGE(dhb_page);
- writeb(AC, dhb);
- writeb(LLC_FRAME, dhb + 1);
+ writeb(AC, dhbuf);
+ writeb(LLC_FRAME, dhbuf + 1);
for (i = 0; i < TR_ALEN; i++)
- writeb((int) 0x0FF, dhb + i + 2);
+ writeb((int) 0x0FF, dhbuf + i + 2);
for (i = 0; i < TR_ALEN; i++)
- writeb(0, dhb + i + TR_ALEN + 2);
+ writeb(0, dhbuf + i + TR_ALEN + 2);
writeb(RESP_IN_ASB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD);
return;
}
@@ -1650,10 +1648,10 @@ static void tr_tx(struct net_device *dev)
dhb=dhb & ~(ti->page_mask << 8);
dhb_len=0x4000-dhb; /* remaining size of this page */
}
- dhb+=ti->sram_virt;
+ dhbuf = ti->sram_virt + dhb;
SET_PAGE(dhb_page);
if (src_len > dhb_len) {
- memcpy_toio(dhb,&ti->current_skb->data[src_offset],
+ memcpy_toio(dhbuf,&ti->current_skb->data[src_offset],
dhb_len);
src_len -= dhb_len;
src_offset += dhb_len;
@@ -1661,7 +1659,7 @@ static void tr_tx(struct net_device *dev)
dhb=dhb_base;
continue;
}
- memcpy_toio(dhb, &ti->current_skb->data[src_offset], src_len);
+ memcpy_toio(dhbuf, &ti->current_skb->data[src_offset], src_len);
break;
}
writeb(RESP_IN_ASB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD);
@@ -1689,9 +1687,9 @@ static void tr_tx(struct net_device *dev)
static void tr_rx(struct net_device *dev)
{
struct tok_info *ti = (struct tok_info *) dev->priv;
- __u32 rbuffer, rbufdata;
+ __u32 rbuffer;
+ void __iomem *rbuf, *rbufdata, *llc;
__u8 rbuffer_page = 0;
- __u32 llc;
unsigned char *data;
unsigned int rbuffer_len, lan_hdr_len, hdr_len, ip_len, length;
unsigned char dlc_hdr_len;
@@ -1705,11 +1703,7 @@ static void tr_rx(struct net_device *dev)
SET_PAGE(ti->arb_page);
memcpy_fromio(&rarb, ti->arb, sizeof(rarb));
rbuffer = ntohs(rarb.rec_buf_addr) ;
- if (ti->page_mask) {
- rbuffer_page = (rbuffer >> 8) & ti->page_mask;
- rbuffer &= ~(ti->page_mask << 8);
- }
- rbuffer += ti->sram_virt;
+ rbuf = map_address(ti, rbuffer, &rbuffer_page);
SET_PAGE(ti->asb_page);
@@ -1728,7 +1722,7 @@ static void tr_rx(struct net_device *dev)
hdr_len = lan_hdr_len + sizeof(struct trllc) + sizeof(struct iphdr);
SET_PAGE(rbuffer_page);
- llc = (rbuffer + offsetof(struct rec_buf, data) + lan_hdr_len);
+ llc = rbuf + offsetof(struct rec_buf, data) + lan_hdr_len;
#if TR_VERBOSE
DPRINTK("offsetof data: %02X lan_hdr_len: %02X\n",
@@ -1759,9 +1753,7 @@ static void tr_rx(struct net_device *dev)
if (!IPv4_p) {
- __u32 trhhdr;
-
- trhhdr = (rbuffer + offsetof(struct rec_buf, data));
+ void __iomem *trhhdr = rbuf + offsetof(struct rec_buf, data);
DPRINTK("Probably non-IP frame received.\n");
DPRINTK("ssap: %02X dsap: %02X "
@@ -1793,8 +1785,8 @@ static void tr_rx(struct net_device *dev)
skb_put(skb, length);
skb->dev = dev;
data = skb->data;
- rbuffer_len = ntohs(readw(rbuffer + offsetof(struct rec_buf, buf_len)));
- rbufdata = rbuffer + offsetof(struct rec_buf, data);
+ rbuffer_len = ntohs(readw(rbuf + offsetof(struct rec_buf, buf_len)));
+ rbufdata = rbuf + offsetof(struct rec_buf, data);
if (IPv4_p) {
/* Copy the headers without checksumming */
@@ -1822,20 +1814,16 @@ static void tr_rx(struct net_device *dev)
data,length<rbuffer_len?length:rbuffer_len,chksum);
else
memcpy_fromio(data, rbufdata, rbuffer_len);
- rbuffer = ntohs(readw(rbuffer+BUFFER_POINTER_OFST)) ;
+ rbuffer = ntohs(readw(rbuf+BUFFER_POINTER_OFST)) ;
if (!rbuffer)
break;
rbuffer -= 2;
length -= rbuffer_len;
data += rbuffer_len;
- if (ti->page_mask) {
- rbuffer_page = (rbuffer >> 8) & ti->page_mask;
- rbuffer &= ~(ti->page_mask << 8);
- }
- rbuffer += ti->sram_virt;
+ rbuf = map_address(ti, rbuffer, &rbuffer_page);
SET_PAGE(rbuffer_page);
- rbuffer_len = ntohs(readw(rbuffer + BUFFER_LENGTH_OFST));
- rbufdata = rbuffer + offsetof(struct rec_buf, data);
+ rbuffer_len = ntohs(readw(rbuf + BUFFER_LENGTH_OFST));
+ rbufdata = rbuf + offsetof(struct rec_buf, data);
}
SET_PAGE(ti->asb_page);
diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c
index ad41876ec9a67..008e19210e66f 100644
--- a/drivers/net/tulip/de2104x.c
+++ b/drivers/net/tulip/de2104x.c
@@ -1927,7 +1927,7 @@ bad_srom:
goto fill_defaults;
}
-static int __devinit de_init_one (struct pci_dev *pdev,
+static int __init de_init_one (struct pci_dev *pdev,
const struct pci_device_id *ent)
{
struct net_device *dev;
diff --git a/drivers/net/tulip/de4x5.c b/drivers/net/tulip/de4x5.c
index 5160ef2daf755..93800c126e866 100644
--- a/drivers/net/tulip/de4x5.c
+++ b/drivers/net/tulip/de4x5.c
@@ -2124,6 +2124,7 @@ static struct eisa_driver de4x5_eisa_driver = {
.remove = __devexit_p (de4x5_eisa_remove),
}
};
+MODULE_DEVICE_TABLE(eisa, de4x5_eisa_ids);
#endif
#ifdef CONFIG_PCI
diff --git a/drivers/net/tulip/interrupt.c b/drivers/net/tulip/interrupt.c
index 7650fd97c3673..afb5cda9d8e1e 100644
--- a/drivers/net/tulip/interrupt.c
+++ b/drivers/net/tulip/interrupt.c
@@ -26,7 +26,7 @@ unsigned int tulip_max_interrupt_work;
#define MIT_SIZE 15
#define MIT_TABLE 15 /* We use 0 or max */
-unsigned int mit_table[MIT_SIZE+1] =
+static unsigned int mit_table[MIT_SIZE+1] =
{
/* CRS11 21143 hardware Mitigation Control Interrupt
We use only RX mitigation we other techniques for
diff --git a/drivers/net/tulip/media.c b/drivers/net/tulip/media.c
index 091a0e07a5865..edae09a4b021e 100644
--- a/drivers/net/tulip/media.c
+++ b/drivers/net/tulip/media.c
@@ -88,7 +88,7 @@ int tulip_mdio_read(struct net_device *dev, int phy_id, int location)
value = ioread32(ioaddr + CSR9);
iowrite32(value & 0xFFEFFFFF, ioaddr + CSR9);
- value = (phy_id << 21) | (location << 16) | 0x80000000;
+ value = (phy_id << 21) | (location << 16) | 0x08000000;
iowrite32(value, ioaddr + CSR10);
while(--i > 0) {
@@ -166,7 +166,7 @@ void tulip_mdio_write(struct net_device *dev, int phy_id, int location, int val)
value = ioread32(ioaddr + CSR9);
iowrite32(value & 0xFFEFFFFF, ioaddr + CSR9);
- value = (phy_id << 21) | (location << 16) | 0x40000000 | (val & 0xFFFF);
+ value = (phy_id << 21) | (location << 16) | 0x04000000 | (val & 0xFFFF);
iowrite32(value, ioaddr + CSR10);
while(--i > 0) {
diff --git a/drivers/net/tulip/tulip.h b/drivers/net/tulip/tulip.h
index 063a1f05a3d8f..20346d847d9e1 100644
--- a/drivers/net/tulip/tulip.h
+++ b/drivers/net/tulip/tulip.h
@@ -476,7 +476,7 @@ static inline void tulip_stop_rxtx(struct tulip_private *tp)
if (!i)
printk(KERN_DEBUG "%s: tulip_stop_rxtx() failed\n",
- tp->pdev->slot_name);
+ pci_name(tp->pdev));
}
}
diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c
index 6b5ba2964ac8f..d098b3ba35384 100644
--- a/drivers/net/tulip/tulip_core.c
+++ b/drivers/net/tulip/tulip_core.c
@@ -1102,15 +1102,18 @@ static void set_rx_mode(struct net_device *dev)
entry = tp->cur_tx++ % TX_RING_SIZE;
if (entry != 0) {
- /* Avoid a chip errata by prefixing a dummy entry. */
- tp->tx_buffers[entry].skb = NULL;
- tp->tx_buffers[entry].mapping = 0;
- tp->tx_ring[entry].length =
- (entry == TX_RING_SIZE-1) ? cpu_to_le32(DESC_RING_WRAP) : 0;
- tp->tx_ring[entry].buffer1 = 0;
- /* Must set DescOwned later to avoid race with chip */
- dummy = entry;
- entry = tp->cur_tx++ % TX_RING_SIZE;
+ /* Avoid a chip errata by prefixing a dummy entry. Don't do
+ this on the ULI526X as it triggers a different problem */
+ if (!(tp->chip_id == ULI526X && (tp->revision = 0x40 || tp->revision == 0x50))) {
+ tp->tx_buffers[entry].skb = NULL;
+ tp->tx_buffers[entry].mapping = 0;
+ tp->tx_ring[entry].length =
+ (entry == TX_RING_SIZE-1) ? cpu_to_le32(DESC_RING_WRAP) : 0;
+ tp->tx_ring[entry].buffer1 = 0;
+ /* Must set DescOwned later to avoid race with chip */
+ dummy = entry;
+ entry = tp->cur_tx++ % TX_RING_SIZE;
+ }
}
tp->tx_buffers[entry].skb = NULL;
@@ -1749,7 +1752,7 @@ err_out_free_netdev:
#ifdef CONFIG_PM
-static int tulip_suspend (struct pci_dev *pdev, u32 state)
+static int tulip_suspend (struct pci_dev *pdev, pm_message_t state)
{
struct net_device *dev = pci_get_drvdata(pdev);
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 420c9e26fd15f..7bfee366297b6 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -226,22 +226,26 @@ static __inline__ ssize_t tun_get_user(struct tun_struct *tun, struct iovec *iv,
{
struct tun_pi pi = { 0, __constant_htons(ETH_P_IP) };
struct sk_buff *skb;
- size_t len = count;
+ size_t len = count, align = 0;
if (!(tun->flags & TUN_NO_PI)) {
- if ((len -= sizeof(pi)) > len)
+ if ((len -= sizeof(pi)) > count)
return -EINVAL;
if(memcpy_fromiovec((void *)&pi, iv, sizeof(pi)))
return -EFAULT;
}
+
+ if ((tun->flags & TUN_TYPE_MASK) == TUN_TAP_DEV)
+ align = NET_IP_ALIGN;
- if (!(skb = alloc_skb(len + 2, GFP_KERNEL))) {
+ if (!(skb = alloc_skb(len + align, GFP_KERNEL))) {
tun->stats.rx_dropped++;
return -ENOMEM;
}
- skb_reserve(skb, 2);
+ if (align)
+ skb_reserve(skb, align);
if (memcpy_fromiovec(skb_put(skb, len), iv, len))
return -EFAULT;
@@ -843,7 +847,7 @@ static struct ethtool_ops tun_ethtool_ops = {
.set_rx_csum = tun_set_rx_csum
};
-int __init tun_init(void)
+static int __init tun_init(void)
{
int ret = 0;
@@ -856,7 +860,7 @@ int __init tun_init(void)
return ret;
}
-void tun_cleanup(void)
+static void tun_cleanup(void)
{
struct tun_struct *tun, *nxt;
diff --git a/drivers/net/typhoon-firmware.h b/drivers/net/typhoon-firmware.h
index 7c1f06dabaf58..2bf47d93b7844 100644
--- a/drivers/net/typhoon-firmware.h
+++ b/drivers/net/typhoon-firmware.h
@@ -1,5 +1,5 @@
/*
- * Copyright 1999-2003 3Com Corporation. All Rights Reserved.
+ * Copyright 1999-2004 3Com Corporation. All Rights Reserved.
*
* Redistribution and use in source and binary forms of the 3c990img.h
* microcode software are permitted provided that the following conditions
@@ -31,14 +31,15 @@
* COMBINATION WITH THE 3c990img.h MICROCODE SOFTWARE
*/
-const u8 typhoon_firmware_image[] = {
+ /* ver 03.001.008 */
+static const u8 typhoon_firmware_image[] = {
0x54, 0x59, 0x50, 0x48, 0x4f, 0x4f, 0x4e, 0x00, 0x02, 0x00, 0x00, 0x00,
-0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xbf, 0xcd, 0x57, 0xc3,
-0xba, 0x01, 0x2c, 0xe8, 0xcd, 0xef, 0xa9, 0xd9, 0x6f, 0xbb, 0x76, 0x2f,
-0x86, 0x49, 0xac, 0x1b, 0x40, 0x01, 0x00, 0x00, 0x8a, 0xe4, 0x00, 0x00,
+0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcb, 0x99, 0xb1, 0xd4,
+0x4c, 0xb8, 0xd0, 0x4b, 0x32, 0x02, 0xd4, 0xee, 0x73, 0x7e, 0x0b, 0x13,
+0x9b, 0xc0, 0xae, 0xf4, 0x40, 0x01, 0x00, 0x00, 0xe8, 0xfc, 0x00, 0x00,
0x00, 0x00, 0xff, 0xff, 0x39, 0x00, 0x00, 0xea, 0x05, 0x00, 0x00, 0xea,
0x04, 0x00, 0x00, 0xea, 0x03, 0x00, 0x00, 0xea, 0x02, 0x00, 0x00, 0xea,
-0x01, 0x00, 0x00, 0xea, 0x32, 0x02, 0x00, 0xea, 0xc0, 0x14, 0x00, 0xea,
+0x01, 0x00, 0x00, 0xea, 0x32, 0x02, 0x00, 0xea, 0xc5, 0x14, 0x00, 0xea,
0x07, 0x00, 0x2d, 0xe9, 0x0e, 0x00, 0xa0, 0xe1, 0x00, 0x10, 0x0f, 0xe1,
0xd0, 0x20, 0x9f, 0xe5, 0x12, 0xff, 0x2f, 0xe1, 0xfe, 0xff, 0xff, 0xea,
0x01, 0x00, 0x80, 0xe0, 0x04, 0x20, 0x81, 0xe4, 0x01, 0x00, 0x50, 0xe1,
@@ -50,7 +51,7 @@ const u8 typhoon_firmware_image[] = {
0x88, 0xd0, 0x9f, 0xe5, 0xdb, 0x00, 0xa0, 0xe3, 0x00, 0xf0, 0x21, 0xe1,
0x7c, 0xd0, 0x9f, 0xe5, 0xd2, 0x00, 0xa0, 0xe3, 0x00, 0xf0, 0x21, 0xe1,
0x74, 0xd0, 0x9f, 0xe5, 0xd1, 0x00, 0xa0, 0xe3, 0x00, 0xf0, 0x21, 0xe1,
-0x6c, 0xd0, 0x9f, 0xe5, 0x96, 0x14, 0x00, 0xeb, 0xd3, 0x00, 0xa0, 0xe3,
+0x6c, 0xd0, 0x9f, 0xe5, 0x9b, 0x14, 0x00, 0xeb, 0xd3, 0x00, 0xa0, 0xe3,
0x00, 0xf0, 0x21, 0xe1, 0x60, 0xd0, 0x9f, 0xe5, 0x60, 0x00, 0x9f, 0xe5,
0x60, 0x10, 0x9f, 0xe5, 0x60, 0x20, 0x9f, 0xe5, 0xdb, 0xff, 0xff, 0xeb,
0x5c, 0x00, 0x9f, 0xe5, 0x5c, 0x10, 0x9f, 0xe5, 0x00, 0x20, 0xa0, 0xe3,
@@ -58,21 +59,21 @@ const u8 typhoon_firmware_image[] = {
0xd4, 0xff, 0xff, 0xeb, 0x0a, 0x00, 0xa0, 0xe1, 0x0b, 0xf0, 0xa0, 0xe1,
0xd3, 0x10, 0xa0, 0xe3, 0x01, 0xf0, 0x21, 0xe1, 0xd4, 0xff, 0xff, 0xeb,
0x3c, 0xa0, 0x9f, 0xe5, 0x1a, 0xff, 0x2f, 0xe1, 0xc6, 0xff, 0xff, 0xea,
-0x01, 0x21, 0xff, 0xff, 0x0c, 0x00, 0x10, 0x00, 0x1c, 0x00, 0x10, 0x00,
+0x15, 0x21, 0xff, 0xff, 0x0c, 0x00, 0x10, 0x00, 0x1c, 0x00, 0x10, 0x00,
0x3c, 0x38, 0x00, 0x80, 0xfc, 0x37, 0x00, 0x80, 0xfc, 0x3f, 0x00, 0x80,
0x7c, 0x34, 0x00, 0x80, 0x80, 0x0f, 0x00, 0x00, 0x80, 0x30, 0x00, 0x80,
-0xad, 0xde, 0xad, 0xde, 0x5c, 0xbc, 0x00, 0x00, 0x24, 0xab, 0x20, 0x40,
-0x48, 0x29, 0x00, 0x00, 0x28, 0x05, 0x00, 0x80, 0x8d, 0xd2, 0x21, 0x40,
+0xad, 0xde, 0xad, 0xde, 0xb0, 0xbb, 0x00, 0x00, 0x24, 0xab, 0x20, 0x40,
+0x48, 0x29, 0x00, 0x00, 0x28, 0x05, 0x00, 0x80, 0xbd, 0xba, 0x21, 0x40,
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x44, 0x57, 0x00, 0x00, 0x71, 0xaf, 0x00, 0x00, 0x60, 0x01, 0xff, 0xff,
-0xb0, 0xb5, 0x07, 0x1c, 0x12, 0x4c, 0x00, 0x25, 0x20, 0x68, 0x00, 0x28,
-0x1d, 0xd0, 0x38, 0x1c, 0x10, 0x49, 0x04, 0xf0, 0x71, 0xfd, 0x21, 0x68,
-0xc0, 0x46, 0x08, 0x60, 0x00, 0x28, 0x14, 0xd0, 0x38, 0x01, 0x0d, 0x49,
+0x58, 0x57, 0x00, 0x00, 0x86, 0x4b, 0x00, 0x00, 0x60, 0x01, 0xff, 0xff,
+0xb0, 0xb5, 0x07, 0x1c, 0x12, 0x4d, 0x00, 0x24, 0x28, 0x68, 0x00, 0x28,
+0x1e, 0xd0, 0x38, 0x1c, 0x10, 0x49, 0x04, 0xf0, 0x7b, 0xfd, 0x29, 0x68,
+0xc0, 0x46, 0x08, 0x60, 0x00, 0x28, 0x15, 0xd0, 0x38, 0x01, 0x0d, 0x49,
0x40, 0x18, 0x19, 0x23, 0xdb, 0x01, 0xc0, 0x18, 0x41, 0x6b, 0x80, 0x29,
-0x0b, 0xd2, 0x01, 0x31, 0x41, 0x63, 0x20, 0x68, 0xc1, 0x69, 0xc0, 0x46,
-0x21, 0x60, 0x39, 0x07, 0x41, 0x60, 0xc7, 0x62, 0xb0, 0xbc, 0x08, 0xbc,
-0x18, 0x47, 0x28, 0x1c, 0xfa, 0xe7, 0x00, 0x00, 0xe8, 0x17, 0x00, 0x80,
+0x0c, 0xd2, 0x01, 0x31, 0x41, 0x63, 0x28, 0x68, 0xc1, 0x69, 0xc0, 0x46,
+0x29, 0x60, 0x39, 0x07, 0x41, 0x60, 0x04, 0x62, 0xc7, 0x62, 0xb0, 0xbc,
+0x08, 0xbc, 0x18, 0x47, 0x20, 0x1c, 0xfa, 0xe7, 0xe8, 0x17, 0x00, 0x80,
0xee, 0x05, 0x00, 0x00, 0xa0, 0x1c, 0x00, 0x80, 0x02, 0x49, 0x0a, 0x68,
0xc0, 0x46, 0xc2, 0x61, 0x08, 0x60, 0x70, 0x47,
0xe8, 0x17, 0x00, 0x80, 0x70, 0x47, 0x00, 0x00, 0x70, 0x47, 0x00, 0x00,
@@ -91,7 +92,7 @@ const u8 typhoon_firmware_image[] = {
0x1e, 0xff, 0x2f, 0xe1, 0x01, 0x20, 0x80, 0xe0, 0x01, 0x00, 0x80, 0xe0,
0x1e, 0xff, 0x2f, 0xe1, 0x80, 0xb5, 0x08, 0x4f, 0x64, 0x28, 0x04, 0xd3,
0x64, 0x20, 0x38, 0x63, 0x00, 0x20, 0xc0, 0x43, 0x03, 0xe0, 0x38, 0x63,
-0x04, 0x49, 0x05, 0xf0, 0xf7, 0xfa, 0x78, 0x63, 0xb8, 0x63, 0x80, 0xbc,
+0x04, 0x49, 0x05, 0xf0, 0x01, 0xfb, 0x78, 0x63, 0xb8, 0x63, 0x80, 0xbc,
0x08, 0xbc, 0x18, 0x47, 0x68, 0x0e, 0x00, 0x80, 0x88, 0x13, 0x00, 0x00,
0x80, 0xb4, 0x10, 0x4b, 0x00, 0x22, 0x1f, 0x6b, 0x64, 0x2f, 0x03, 0xd2,
0x09, 0x68, 0x09, 0x68, 0x49, 0x08, 0x02, 0xd2, 0x10, 0x1c, 0x80, 0xbc,
@@ -104,7 +105,7 @@ const u8 typhoon_firmware_image[] = {
0x49, 0x08, 0x08, 0xd3, 0x21, 0x6c, 0xa2, 0x6b, 0x91, 0x42, 0x07, 0xd2,
0xfa, 0x1d, 0x39, 0x32, 0x52, 0x8b, 0x89, 0x18, 0x21, 0x64, 0x90, 0xbc,
0x08, 0xbc, 0x18, 0x47, 0x78, 0x6a, 0x39, 0x6b, 0xc0, 0x46, 0x48, 0x62,
-0x38, 0x6b, 0x02, 0xf0, 0x23, 0xfe, 0x38, 0x1c, 0x02, 0xf0, 0xde, 0xfa,
+0x38, 0x6b, 0x02, 0xf0, 0x2d, 0xfe, 0x38, 0x1c, 0x02, 0xf0, 0xe8, 0xfa,
0x01, 0x20, 0xbb, 0x23, 0x1b, 0x01, 0xe1, 0x18, 0xc8, 0x73, 0x05, 0x49,
0x0a, 0x6c, 0x12, 0x18, 0x0a, 0x64, 0x04, 0x49, 0x8a, 0x6d, 0x12, 0x18,
0x8a, 0x65, 0xe4, 0xe7, 0x68, 0x0e, 0x00, 0x80, 0x0c, 0x2b, 0x00, 0x80,
@@ -333,8 +334,8 @@ const u8 typhoon_firmware_image[] = {
0xc9, 0x68, 0x40, 0x18, 0x01, 0x23, 0x9b, 0x07, 0x02, 0x30, 0x18, 0x43,
0x00, 0x68, 0x00, 0x04, 0x00, 0x0c, 0x11, 0x23, 0x9b, 0x02, 0x98, 0x42,
0x18, 0xd1, 0x78, 0x6a, 0x39, 0x6b, 0xc0, 0x46,
-0x48, 0x62, 0x38, 0x6b, 0x02, 0xf0, 0xd0, 0xf8, 0x38, 0x1c, 0x01, 0xf0,
-0x8b, 0xfd, 0x01, 0x20, 0x07, 0x49, 0xc0, 0x46, 0xc8, 0x73, 0x07, 0x49,
+0x48, 0x62, 0x38, 0x6b, 0x02, 0xf0, 0xda, 0xf8, 0x38, 0x1c, 0x01, 0xf0,
+0x95, 0xfd, 0x01, 0x20, 0x07, 0x49, 0xc0, 0x46, 0xc8, 0x73, 0x07, 0x49,
0x4a, 0x6c, 0x12, 0x18, 0x4a, 0x64, 0x06, 0x49, 0x8a, 0x6d, 0x12, 0x18,
0x8a, 0x65, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x20, 0xfa, 0xe7,
0x18, 0x1a, 0x00, 0x80, 0x0c, 0x2b, 0x00, 0x80, 0xa4, 0x2a, 0x00, 0x80,
@@ -370,7 +371,7 @@ const u8 typhoon_firmware_image[] = {
0xc2, 0x60, 0x38, 0x1c, 0x00, 0xf0, 0xce, 0xfa, 0x38, 0x6a, 0x01, 0x30,
0x38, 0x62, 0x38, 0x1c, 0x00, 0xf0, 0x0a, 0xf8, 0x80, 0xbc, 0x08, 0xbc,
0x18, 0x47, 0x10, 0x1c, 0xfa, 0xe7, 0x00, 0x00, 0x6c, 0x06, 0x00, 0x80,
-0x1c, 0xad, 0x20, 0x40, 0xf0, 0xb5, 0x07, 0x1c, 0xf9, 0x1d, 0xf9, 0x31,
+0xac, 0xab, 0x20, 0x40, 0xf0, 0xb5, 0x07, 0x1c, 0xf9, 0x1d, 0xf9, 0x31,
0x88, 0x6a, 0xc2, 0x1d, 0x2d, 0x32, 0x01, 0x23, 0x9b, 0x07, 0x08, 0x32,
0x1a, 0x43, 0xc8, 0x6a, 0x12, 0x68, 0x12, 0x04, 0x12, 0x0c, 0x80, 0x18,
0x82, 0x79, 0xc3, 0x79, 0x1b, 0x02, 0x1a, 0x43, 0x13, 0x02, 0x12, 0x0a,
@@ -381,7 +382,7 @@ const u8 typhoon_firmware_image[] = {
0xc2, 0x1d, 0x0d, 0x32, 0x1a, 0x43, 0x12, 0x68, 0x12, 0x04, 0x12, 0x30,
0x18, 0x43, 0x00, 0x68, 0x00, 0x04, 0x00, 0x0c, 0x10, 0x43, 0x03, 0x1c,
0xf8, 0x1d, 0xff, 0x30, 0x4a, 0x30, 0x82, 0x78, 0xc8, 0x6b, 0x19, 0x1c,
-0x01, 0xf0, 0xf8, 0xff, 0x00, 0x28, 0x04, 0xda, 0x20, 0x8a, 0xff, 0x23,
+0x02, 0xf0, 0x02, 0xf8, 0x00, 0x28, 0x04, 0xda, 0x20, 0x8a, 0xff, 0x23,
0x01, 0x33, 0x18, 0x43, 0x0e, 0xe0, 0xf9, 0x1d, 0xff, 0x31, 0x3a, 0x31,
0x08, 0x60, 0x01, 0x04, 0x09, 0x0c, 0x38, 0x1c, 0x00, 0xf0, 0x1c, 0xf8,
0x00, 0x28, 0x14, 0xd1, 0x20, 0x8a, 0x01, 0x23, 0x5b, 0x02, 0x18, 0x43,
@@ -398,7 +399,7 @@ const u8 typhoon_firmware_image[] = {
0x60, 0x6b, 0x81, 0x42, 0xf8, 0xd8, 0x69, 0x89, 0xea, 0x88, 0x89, 0x18,
0x81, 0x42, 0xf3, 0xd8, 0x00, 0x98, 0x01, 0x28, 0x25, 0xd1, 0xe0, 0x6a,
0xf1, 0x6b, 0x40, 0x18, 0x71, 0x6c, 0xfa, 0x1d, 0xcd, 0x32, 0x01, 0xf0,
-0x29, 0xf9, 0xfa, 0x1d, 0xff, 0x32, 0x3a, 0x32, 0xe0, 0x6a, 0x51, 0x69,
+0x33, 0xf9, 0xfa, 0x1d, 0xff, 0x32, 0x3a, 0x32, 0xe0, 0x6a, 0x51, 0x69,
0x40, 0x18, 0xc3, 0x1d, 0x03, 0x33, 0x00, 0x20, 0x81, 0x00, 0x5e, 0x58,
0xc9, 0x19, 0xff, 0x31, 0x01, 0x31, 0x4e, 0x61, 0x01, 0x30, 0x04, 0x28,
0xf6, 0xd3, 0xe0, 0x6a, 0x51, 0x69, 0x40, 0x18, 0xc1, 0x1d, 0x05, 0x31,
@@ -419,7 +420,7 @@ const u8 typhoon_firmware_image[] = {
0xc0, 0x46, 0x09, 0x90, 0xff, 0x23, 0x1b, 0x02, 0x18, 0x40, 0x00, 0x0a,
0x0a, 0x90, 0x0a, 0x98, 0xa4, 0x4e, 0x01, 0x28, 0x59, 0xd1, 0x28, 0x6b,
0xa2, 0x68, 0x80, 0x18, 0xa2, 0x4a, 0x21, 0x69,
-0x09, 0x04, 0x09, 0x0c, 0x01, 0xf0, 0x1c, 0xf9, 0x28, 0x6b, 0x79, 0x69,
+0x09, 0x04, 0x09, 0x0c, 0x01, 0xf0, 0x26, 0xf9, 0x28, 0x6b, 0x79, 0x69,
0x40, 0x18, 0xc1, 0x1d, 0x05, 0x31, 0x00, 0x20, 0x82, 0x00, 0x98, 0x4b,
0xd3, 0x18, 0xff, 0x33, 0x01, 0x33, 0x5b, 0x69, 0xc0, 0x46, 0x8b, 0x50,
0x01, 0x30, 0x04, 0x28, 0xf4, 0xd3, 0x00, 0x20, 0x31, 0x1c, 0x82, 0x00,
@@ -429,7 +430,7 @@ const u8 typhoon_firmware_image[] = {
0x8e, 0x48, 0xc1, 0x89, 0x01, 0x31, 0xc1, 0x81, 0xb8, 0x68, 0x00, 0x28,
0x03, 0xd1, 0x38, 0x8a, 0x10, 0x23, 0x18, 0x43, 0x71, 0xe0, 0x38, 0x8a,
0x40, 0x23, 0x18, 0x43, 0x6d, 0xe0, 0x00, 0xf0, 0x11, 0xf9, 0x01, 0xf0,
-0x5d, 0xff, 0xf5, 0xe0, 0x01, 0x30, 0x06, 0x28, 0xe3, 0xd3, 0x08, 0x98,
+0x67, 0xff, 0xf5, 0xe0, 0x01, 0x30, 0x06, 0x28, 0xe3, 0xd3, 0x08, 0x98,
0x00, 0x28, 0x0c, 0xd1, 0xb8, 0x68, 0x41, 0x1c, 0xb9, 0x60, 0x00, 0x28,
0x03, 0xd1, 0x38, 0x8a, 0x01, 0x23, 0x18, 0x43, 0x02, 0xe0, 0x38, 0x8a,
0x04, 0x23, 0x18, 0x43, 0x38, 0x82, 0x78, 0x68, 0x01, 0x30, 0x78, 0x60,
@@ -470,10 +471,10 @@ const u8 typhoon_firmware_image[] = {
0xff, 0xf7, 0xc0, 0xfd, 0x00, 0x28, 0x11, 0xd1, 0x0e, 0xe0, 0x00, 0x20,
0x30, 0x72, 0x11, 0xe0, 0x33, 0x29, 0x01, 0xd0, 0x32, 0x29, 0x0d, 0xd1,
0x07, 0x1c, 0x00, 0xf0, 0x71, 0xf8, 0x38, 0x1c, 0xff, 0xf7, 0xb0, 0xfd,
-0x00, 0x28, 0x01, 0xd1, 0x01, 0xf0, 0x66, 0xfe, 0x0d, 0xb0, 0xf0, 0xbc,
+0x00, 0x28, 0x01, 0xd1, 0x01, 0xf0, 0x70, 0xfe, 0x0d, 0xb0, 0xf0, 0xbc,
0x08, 0xbc, 0x18, 0x47, 0x00, 0xf0, 0x12, 0xf8, 0xf6, 0xe7, 0x00, 0x00,
0x6c, 0x06, 0x00, 0x80, 0x00, 0x00, 0x00, 0xb0, 0x4c, 0x2a, 0x00, 0x80,
-0x1c, 0xad, 0x20, 0x40, 0x40, 0x07, 0x00, 0x80, 0x82, 0x07, 0x00, 0x80,
+0xac, 0xab, 0x20, 0x40, 0x40, 0x07, 0x00, 0x80, 0x82, 0x07, 0x00, 0x80,
0x0c, 0x2b, 0x00, 0x80, 0x6c, 0x07, 0x00, 0x80, 0xf0, 0xb5, 0x25, 0x48,
0x41, 0x68, 0x01, 0x31, 0x41, 0x60, 0x24, 0x4f, 0xf9, 0x1d, 0xf9, 0x31,
0x00, 0x24, 0x88, 0x6a, 0xfa, 0x68, 0xc0, 0x46, 0x94, 0x61, 0x04, 0x22,
@@ -485,7 +486,7 @@ const u8 typhoon_firmware_image[] = {
0x4a, 0x6b, 0xfb, 0x68, 0xc0, 0x46, 0xda, 0x81, 0x0a, 0x6b, 0xc0, 0x46,
0x82, 0x62, 0xc4, 0x62, 0xc3, 0x1d, 0x39, 0x33, 0x4a, 0x6b, 0xc0, 0x46,
0x5a, 0x83, 0x04, 0x23, 0x02, 0x68, 0x1a, 0x43, 0x02, 0x60, 0x88, 0x6a,
-0x01, 0xf0, 0x28, 0xfa, 0xf8, 0x68, 0x01, 0x23, 0x9b, 0x07, 0x54, 0x30,
+0x01, 0xf0, 0x32, 0xfa, 0xf8, 0x68, 0x01, 0x23, 0x9b, 0x07, 0x54, 0x30,
0x18, 0x43, 0x00, 0x68, 0xc0, 0x46, 0xf8, 0x60, 0xf0, 0xbc, 0x08, 0xbc,
0x18, 0x47, 0x00, 0x00, 0x0c, 0x2b, 0x00, 0x80, 0x6c, 0x06, 0x00, 0x80,
0xac, 0x07, 0x00, 0x80, 0x80, 0xb5, 0xc1, 0x1d, 0xf9, 0x31, 0x8a, 0x6a,
@@ -546,7 +547,7 @@ const u8 typhoon_firmware_image[] = {
0x04, 0x23, 0x90, 0x6a, 0xc0, 0x46, 0xc3, 0x60, 0x10, 0x23, 0x83, 0x61,
0xcb, 0x0a, 0x01, 0xd3, 0x18, 0x23, 0x83, 0x61, 0xc1, 0x83, 0x51, 0x6b,
0xc0, 0x46, 0xc1, 0x81, 0x51, 0x6b, 0xc2, 0x1d, 0x39, 0x32, 0x51, 0x83,
-0x04, 0x23, 0x01, 0x68, 0x19, 0x43, 0x01, 0x60, 0x01, 0xf0, 0xb8, 0xf8,
+0x04, 0x23, 0x01, 0x68, 0x19, 0x43, 0x01, 0x60, 0x01, 0xf0, 0xc2, 0xf8,
0x08, 0xbc, 0x18, 0x47, 0x0c, 0x2b, 0x00, 0x80,
0xb0, 0xb5, 0x1b, 0x4c, 0x20, 0x6a, 0x02, 0x28, 0x1b, 0xd2, 0x00, 0x20,
0xe7, 0x1d, 0x19, 0x37, 0x38, 0x71, 0xe1, 0x68, 0xe0, 0x1d, 0xf9, 0x30,
@@ -555,1331 +556,1331 @@ const u8 typhoon_firmware_image[] = {
0x02, 0x28, 0x00, 0xd3, 0x3d, 0x71, 0xe0, 0x68, 0x00, 0x28, 0x02, 0xd0,
0x38, 0x79, 0x00, 0x28, 0xf1, 0xd0, 0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47,
0x40, 0x6a, 0x00, 0x28, 0xf9, 0xd1, 0x00, 0x29, 0xf7, 0xd1, 0x60, 0x69,
-0x00, 0x28, 0x04, 0xd0, 0x06, 0x48, 0x00, 0x68, 0x03, 0xf0, 0x9e, 0xfc,
-0xef, 0xe7, 0x60, 0x68, 0x00, 0x28, 0xec, 0xd0, 0x00, 0xf0, 0x50, 0xf8,
+0x00, 0x28, 0x04, 0xd0, 0x06, 0x48, 0x00, 0x68, 0x03, 0xf0, 0xa8, 0xfc,
+0xef, 0xe7, 0x60, 0x68, 0x00, 0x28, 0xec, 0xd0, 0x00, 0xf0, 0x5a, 0xf8,
0xe9, 0xe7, 0x00, 0x00, 0x6c, 0x06, 0x00, 0x80, 0x34, 0x04, 0x00, 0x80,
-0xb0, 0xb5, 0x07, 0x1c, 0x20, 0x23, 0xb8, 0x68, 0x18, 0x40, 0x00, 0x25,
-0x00, 0x28, 0x03, 0xd1, 0x28, 0x1c, 0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47,
-0xc4, 0x23, 0x48, 0x68, 0x18, 0x40, 0x01, 0x24, 0x00, 0x28, 0x03, 0xd1,
-0x38, 0x6a, 0x00, 0xf0, 0x09, 0xfc, 0x2f, 0xe0, 0x38, 0x1c, 0x00, 0xf0,
-0x19, 0xfc, 0x38, 0x1c, 0x00, 0xf0, 0x78, 0xfa, 0xb8, 0x68, 0xc0, 0x08,
-0x02, 0xd3, 0x38, 0x6a, 0x00, 0xf0, 0xce, 0xfb, 0xb8, 0x68, 0x39, 0x6a,
-0xc0, 0x46, 0x88, 0x60, 0x38, 0x6a, 0xc0, 0x46, 0xc5, 0x60, 0x0f, 0x48,
-0x41, 0x68, 0x00, 0x29, 0x11, 0xd1, 0xc1, 0x68, 0x00, 0x29, 0x09, 0xd1,
-0x41, 0x69, 0x00, 0x29, 0x06, 0xd1, 0x39, 0x6a, 0xc0, 0x46, 0x81, 0x60,
-0x41, 0x60, 0x00, 0xf0, 0x11, 0xf8, 0x0b, 0xe0, 0x39, 0x6a, 0xc0, 0x46,
-0x81, 0x60, 0x41, 0x60, 0x06, 0xe0, 0x39, 0x6a, 0x82, 0x68, 0xc0, 0x46,
-0xd1, 0x60, 0x39, 0x6a, 0xc0, 0x46, 0x81, 0x60, 0x20, 0x1c, 0xc0, 0xe7,
-0x6c, 0x06, 0x00, 0x80, 0x90, 0xb5, 0x0b, 0x4c, 0x67, 0x68, 0x00, 0x2f,
-0x0f, 0xd0, 0x38, 0x1c, 0x00, 0xf0, 0x12, 0xf8, 0x00, 0x28, 0x0a, 0xd1,
-0x60, 0x68, 0xc0, 0x68, 0xc0, 0x46, 0x60, 0x60, 0x38, 0x1c, 0x00, 0xf0,
-0xc3, 0xfb, 0x00, 0x20, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x01, 0x20,
-0xfa, 0xe7, 0x00, 0x00, 0x6c, 0x06, 0x00, 0x80, 0xf0, 0xb5, 0x07, 0x1c,
-0xfe, 0x1d, 0x49, 0x36, 0x30, 0x78, 0x40, 0x00, 0xc0, 0x19, 0x85, 0x8b,
-0x33, 0x4c, 0x34, 0x4b, 0x9d, 0x42, 0x3c, 0xd0, 0x38, 0x1c, 0x21, 0x1c,
-0x2a, 0x1c, 0x00, 0xf0, 0x1d, 0xf9, 0x31, 0x48, 0x80, 0x6a, 0x58, 0x21,
-0x69, 0x43, 0x40, 0x18, 0x01, 0x23, 0x9b, 0x07, 0x18, 0x43, 0x00, 0x68,
-0x00, 0x04, 0x00, 0x0c, 0x2c, 0x4d, 0x01, 0x28, 0x1a, 0xd1, 0x30, 0x78,
-0xc0, 0x19, 0xc1, 0x1d, 0x19, 0x31, 0x08, 0x7a, 0x3a, 0x68, 0x80, 0x18,
-0x09, 0x7b, 0xea, 0x1d, 0x21, 0x32, 0x00, 0xf0, 0xe3, 0xfc, 0x30, 0x78,
-0xc0, 0x19, 0x20, 0x30, 0x00, 0x79, 0x39, 0x68, 0x40, 0x18, 0xc1, 0x1d,
-0x05, 0x31, 0x00, 0x20, 0x00, 0x23, 0x42, 0x00, 0x8b, 0x52, 0x01, 0x30,
-0x06, 0x28, 0xfa, 0xd3, 0xa0, 0x88, 0x41, 0x07, 0x0b, 0xd1, 0x21, 0x89,
-0x09, 0x18, 0x78, 0x68, 0x00, 0x04, 0x00, 0x0c, 0x81, 0x42, 0x04, 0xd8,
-0x61, 0x89, 0xe2, 0x88, 0x89, 0x18, 0x81, 0x42, 0x03, 0xd9, 0x00, 0x20,
-0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x21, 0x1c, 0x14, 0x4a, 0x00, 0x20,
-0xfe, 0xf7, 0x64, 0xff, 0x01, 0x22, 0x52, 0x04, 0x78, 0x68, 0x02, 0x43,
-0x01, 0x20, 0x39, 0x68, 0xfe, 0xf7, 0x5c, 0xff, 0x01, 0x22, 0x52, 0x04,
-0x78, 0x68, 0x02, 0x43, 0x00, 0x20, 0x39, 0x68,
-0xfe, 0xf7, 0x54, 0xff, 0x0b, 0x49, 0x0c, 0x4a, 0x01, 0x20, 0xfe, 0xf7,
-0x4f, 0xff, 0x01, 0x20, 0xe9, 0x1d, 0x19, 0x31, 0x48, 0x71, 0x02, 0x21,
-0xea, 0x1d, 0xf9, 0x32, 0x51, 0x62, 0xd9, 0xe7, 0x98, 0xad, 0x20, 0x40,
-0xff, 0xff, 0x00, 0x00, 0x4c, 0x2a, 0x00, 0x80, 0x6c, 0x06, 0x00, 0x80,
-0x54, 0x00, 0x03, 0x00, 0x84, 0xad, 0x20, 0x40, 0x14, 0x00, 0x07, 0x00,
-0xf0, 0xb5, 0x83, 0xb0, 0x00, 0x21, 0x4f, 0x48, 0xc2, 0x1d, 0xf9, 0x32,
-0x51, 0x62, 0x01, 0x21, 0xc9, 0x04, 0x4d, 0x4a, 0xc0, 0x46, 0x11, 0x60,
-0xc1, 0x1d, 0x19, 0x31, 0x49, 0x79, 0x00, 0x29, 0x04, 0xd1, 0x4a, 0x48,
-0x00, 0x68, 0x03, 0xf0, 0x9b, 0xfb, 0x87, 0xe0, 0x45, 0x48, 0x47, 0x68,
-0xfc, 0x1d, 0x49, 0x34, 0x21, 0x78, 0x48, 0x00, 0xc0, 0x19, 0x80, 0x8b,
-0x44, 0x4a, 0x92, 0x6a, 0x58, 0x23, 0x58, 0x43, 0x15, 0x18, 0x01, 0x23,
-0x9b, 0x07, 0xea, 0x1d, 0x05, 0x32, 0x1a, 0x43, 0x12, 0x68, 0x08, 0x35,
-0x2b, 0x43, 0x1d, 0x68, 0xff, 0x23, 0x1b, 0x02, 0x2b, 0x40, 0x1b, 0x0a,
-0x3c, 0x4d, 0x01, 0x2b, 0x24, 0xd1, 0xc8, 0x19, 0xc1, 0x1d, 0x19, 0x31,
-0x08, 0x7a, 0x3a, 0x68, 0x80, 0x18, 0x39, 0x4a, 0x09, 0x7b, 0x00, 0xf0,
-0xc5, 0xfc, 0x20, 0x78, 0xc0, 0x19, 0x20, 0x30, 0x00, 0x79, 0x39, 0x68,
-0x41, 0x18, 0x00, 0x20, 0x82, 0x00, 0x53, 0x19, 0x9b, 0x6e, 0x6e, 0x46,
-0xb3, 0x50, 0x01, 0x30, 0x03, 0x28, 0xf7, 0xd3, 0xca, 0x1d, 0x05, 0x32,
-0x69, 0x46, 0x00, 0x20, 0x43, 0x00, 0xcd, 0x5a, 0xc0, 0x46, 0xd5, 0x52,
-0x01, 0x30, 0x06, 0x28, 0xf8, 0xd3, 0x2d, 0xe0, 0x02, 0x2b, 0x2b, 0xd1,
-0x11, 0x0a, 0x29, 0xd3, 0x00, 0x21, 0x8a, 0x00, 0x53, 0x19, 0x9b, 0x6e,
-0x6e, 0x46, 0xb3, 0x50, 0x01, 0x31, 0x03, 0x29, 0xf7, 0xd3, 0x21, 0x78,
-0x49, 0x00, 0xc9, 0x19, 0x09, 0x8f, 0x3a, 0x68, 0x8b, 0x18, 0x6a, 0x46,
-0x00, 0x21, 0x4d, 0x00, 0x56, 0x5b, 0xc0, 0x46, 0x5e, 0x53, 0x01, 0x31,
-0x06, 0x29, 0xf8, 0xd3, 0x19, 0x49, 0x8a, 0x6a, 0x13, 0x18, 0x1a, 0x6d,
-0x00, 0x9d, 0x55, 0x40, 0x19, 0x4a, 0xd6, 0x68, 0x75, 0x40, 0x1d, 0x65,
-0x89, 0x6a, 0x08, 0x18, 0x41, 0x6d, 0x02, 0x9b, 0x59, 0x40, 0x92, 0x69,
-0x51, 0x40, 0x41, 0x65, 0x20, 0x78, 0x41, 0x1e, 0x21, 0x70, 0x00, 0x28,
-0x0d, 0xd0, 0x38, 0x1c, 0xff, 0xf7, 0xf4, 0xfe, 0x00, 0x28, 0x0d, 0xd1,
-0x08, 0x4a, 0x50, 0x68, 0xc0, 0x68, 0xc0, 0x46, 0x50, 0x60, 0x38, 0x1c,
-0x00, 0xf0, 0xa4, 0xfa, 0x02, 0xe0, 0x38, 0x1c, 0x00, 0xf0, 0x73, 0xfa,
-0x01, 0xf0, 0xde, 0xfa, 0x03, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47,
-0x6c, 0x06, 0x00, 0x80, 0x00, 0x00, 0x00, 0xb0, 0x38, 0x04, 0x00, 0x80,
-0x4c, 0x2a, 0x00, 0x80, 0x1c, 0xad, 0x20, 0x40, 0x94, 0x06, 0x00, 0x80,
-0x08, 0x83, 0x20, 0x40, 0xf0, 0xb5, 0x82, 0xb0, 0x69, 0x4b, 0x9f, 0x6a,
-0x58, 0x23, 0x5a, 0x43, 0xba, 0x18, 0xc3, 0x1d, 0x49, 0x33, 0x1f, 0x78,
-0x01, 0x23, 0x9b, 0x07, 0xd4, 0x1d, 0x01, 0x34, 0x23, 0x43, 0x1d, 0x68,
-0x43, 0x68, 0x1c, 0x04, 0x01, 0x23, 0x9b, 0x07, 0xd6, 0x1d, 0x05, 0x36,
-0x33, 0x43, 0x1b, 0x68, 0x1c, 0x43, 0x42, 0x23, 0x1c, 0x43, 0x0c, 0x60,
-0xff, 0x26, 0x36, 0x02, 0x2e, 0x40, 0x01, 0x23, 0x5b, 0x02, 0x9e, 0x42,
-0x74, 0xd1, 0x6b, 0x0c, 0x2b, 0xd3, 0xc3, 0x19, 0x20, 0x33, 0x1b, 0x79,
+0xb0, 0xb5, 0x07, 0x1c, 0x20, 0x23, 0xb8, 0x68, 0x18, 0x40, 0x01, 0x24,
+0x00, 0x25, 0x00, 0x28, 0x0b, 0xd1, 0x38, 0x6a, 0x00, 0x28, 0x03, 0xd1,
+0x28, 0x1c, 0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x1f, 0x48, 0x01, 0x6e,
+0x01, 0x31, 0x01, 0x66, 0x03, 0xe0, 0x48, 0x68, 0xc4, 0x23, 0x18, 0x40,
+0x03, 0xd1, 0x38, 0x6a, 0x00, 0xf0, 0x0c, 0xfc, 0x2f, 0xe0, 0x38, 0x1c,
+0x00, 0xf0, 0x1c, 0xfc, 0x38, 0x1c, 0x00, 0xf0, 0x7b, 0xfa, 0xb8, 0x68,
+0xc0, 0x08, 0x02, 0xd3, 0x38, 0x6a, 0x00, 0xf0, 0xd1, 0xfb, 0xb8, 0x68,
+0x39, 0x6a, 0xc0, 0x46, 0x88, 0x60, 0x38, 0x6a, 0xc0, 0x46, 0xc5, 0x60,
+0x10, 0x48, 0x41, 0x68, 0x00, 0x29, 0x11, 0xd1, 0xc1, 0x68, 0x00, 0x29,
+0x09, 0xd1, 0x41, 0x69, 0x00, 0x29, 0x06, 0xd1, 0x39, 0x6a, 0xc0, 0x46,
+0x81, 0x60, 0x41, 0x60, 0x00, 0xf0, 0x14, 0xf8, 0x0b, 0xe0, 0x39, 0x6a,
+0xc0, 0x46, 0x81, 0x60, 0x41, 0x60, 0x06, 0xe0, 0x39, 0x6a, 0x82, 0x68,
+0xc0, 0x46, 0xd1, 0x60, 0x39, 0x6a, 0xc0, 0x46, 0x81, 0x60, 0x20, 0x1c,
+0xbd, 0xe7, 0x00, 0x00, 0xa4, 0x2a, 0x00, 0x80, 0x6c, 0x06, 0x00, 0x80,
+0x90, 0xb5, 0x0b, 0x4c, 0x67, 0x68, 0x00, 0x2f, 0x0f, 0xd0, 0x38, 0x1c,
+0x00, 0xf0, 0x12, 0xf8, 0x00, 0x28, 0x0a, 0xd1, 0x60, 0x68, 0xc0, 0x68,
+0xc0, 0x46, 0x60, 0x60, 0x38, 0x1c, 0x00, 0xf0, 0xc3, 0xfb, 0x00, 0x20,
+0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x01, 0x20, 0xfa, 0xe7, 0x00, 0x00,
+0x6c, 0x06, 0x00, 0x80, 0xf0, 0xb5, 0x07, 0x1c, 0xfe, 0x1d, 0x49, 0x36,
+0x30, 0x78, 0x40, 0x00, 0xc0, 0x19, 0x85, 0x8b, 0x33, 0x4c, 0x34, 0x4b,
+0x9d, 0x42, 0x3c, 0xd0, 0x38, 0x1c, 0x21, 0x1c, 0x2a, 0x1c, 0x00, 0xf0,
+0x1d, 0xf9, 0x31, 0x48, 0x80, 0x6a, 0x58, 0x21, 0x69, 0x43, 0x40, 0x18,
+0x01, 0x23, 0x9b, 0x07, 0x18, 0x43, 0x00, 0x68, 0x00, 0x04, 0x00, 0x0c,
+0x2c, 0x4d, 0x01, 0x28, 0x1a, 0xd1, 0x30, 0x78, 0xc0, 0x19, 0xc1, 0x1d,
+0x19, 0x31, 0x08, 0x7a, 0x3a, 0x68, 0x80, 0x18, 0x09, 0x7b, 0xea, 0x1d,
+0x21, 0x32, 0x00, 0xf0, 0xe3, 0xfc, 0x30, 0x78, 0xc0, 0x19, 0x20, 0x30,
+0x00, 0x79, 0x39, 0x68, 0x40, 0x18, 0xc1, 0x1d, 0x05, 0x31, 0x00, 0x20,
+0x00, 0x23, 0x42, 0x00, 0x8b, 0x52, 0x01, 0x30, 0x06, 0x28, 0xfa, 0xd3,
+0xa0, 0x88, 0x41, 0x07, 0x0b, 0xd1, 0x21, 0x89, 0x09, 0x18, 0x78, 0x68,
+0x00, 0x04, 0x00, 0x0c, 0x81, 0x42, 0x04, 0xd8, 0x61, 0x89, 0xe2, 0x88,
+0x89, 0x18, 0x81, 0x42, 0x03, 0xd9, 0x00, 0x20, 0xf0, 0xbc, 0x08, 0xbc,
+0x18, 0x47, 0x21, 0x1c, 0x14, 0x4a, 0x00, 0x20, 0xfe, 0xf7, 0x5a, 0xff,
+0x01, 0x22, 0x52, 0x04, 0x78, 0x68, 0x02, 0x43,
+0x01, 0x20, 0x39, 0x68, 0xfe, 0xf7, 0x52, 0xff, 0x01, 0x22, 0x52, 0x04,
+0x78, 0x68, 0x02, 0x43, 0x00, 0x20, 0x39, 0x68, 0xfe, 0xf7, 0x4a, 0xff,
+0x0b, 0x49, 0x0c, 0x4a, 0x01, 0x20, 0xfe, 0xf7, 0x45, 0xff, 0x01, 0x20,
+0xe9, 0x1d, 0x19, 0x31, 0x48, 0x71, 0x02, 0x21, 0xea, 0x1d, 0xf9, 0x32,
+0x51, 0x62, 0xd9, 0xe7, 0x28, 0xac, 0x20, 0x40, 0xff, 0xff, 0x00, 0x00,
+0x4c, 0x2a, 0x00, 0x80, 0x6c, 0x06, 0x00, 0x80, 0x54, 0x00, 0x03, 0x00,
+0x14, 0xac, 0x20, 0x40, 0x14, 0x00, 0x07, 0x00, 0xf0, 0xb5, 0x83, 0xb0,
+0x00, 0x21, 0x4f, 0x48, 0xc2, 0x1d, 0xf9, 0x32, 0x51, 0x62, 0x01, 0x21,
+0xc9, 0x04, 0x4d, 0x4a, 0xc0, 0x46, 0x11, 0x60, 0xc1, 0x1d, 0x19, 0x31,
+0x49, 0x79, 0x00, 0x29, 0x04, 0xd1, 0x4a, 0x48, 0x00, 0x68, 0x03, 0xf0,
+0x9b, 0xfb, 0x87, 0xe0, 0x45, 0x48, 0x47, 0x68, 0xfc, 0x1d, 0x49, 0x34,
+0x21, 0x78, 0x48, 0x00, 0xc0, 0x19, 0x80, 0x8b, 0x44, 0x4a, 0x92, 0x6a,
+0x58, 0x23, 0x58, 0x43, 0x15, 0x18, 0x01, 0x23, 0x9b, 0x07, 0xea, 0x1d,
+0x05, 0x32, 0x1a, 0x43, 0x12, 0x68, 0x08, 0x35, 0x2b, 0x43, 0x1d, 0x68,
+0xff, 0x23, 0x1b, 0x02, 0x2b, 0x40, 0x1b, 0x0a, 0x3c, 0x4d, 0x01, 0x2b,
+0x24, 0xd1, 0xc8, 0x19, 0xc1, 0x1d, 0x19, 0x31, 0x08, 0x7a, 0x3a, 0x68,
+0x80, 0x18, 0x39, 0x4a, 0x09, 0x7b, 0x00, 0xf0, 0xc5, 0xfc, 0x20, 0x78,
+0xc0, 0x19, 0x20, 0x30, 0x00, 0x79, 0x39, 0x68, 0x41, 0x18, 0x00, 0x20,
+0x82, 0x00, 0x53, 0x19, 0x9b, 0x6e, 0x6e, 0x46, 0xb3, 0x50, 0x01, 0x30,
+0x03, 0x28, 0xf7, 0xd3, 0xca, 0x1d, 0x05, 0x32, 0x69, 0x46, 0x00, 0x20,
+0x43, 0x00, 0xcd, 0x5a, 0xc0, 0x46, 0xd5, 0x52, 0x01, 0x30, 0x06, 0x28,
+0xf8, 0xd3, 0x2d, 0xe0, 0x02, 0x2b, 0x2b, 0xd1, 0x11, 0x0a, 0x29, 0xd3,
+0x00, 0x21, 0x8a, 0x00, 0x53, 0x19, 0x9b, 0x6e, 0x6e, 0x46, 0xb3, 0x50,
+0x01, 0x31, 0x03, 0x29, 0xf7, 0xd3, 0x21, 0x78, 0x49, 0x00, 0xc9, 0x19,
+0x09, 0x8f, 0x3a, 0x68, 0x8b, 0x18, 0x6a, 0x46, 0x00, 0x21, 0x4d, 0x00,
+0x56, 0x5b, 0xc0, 0x46, 0x5e, 0x53, 0x01, 0x31, 0x06, 0x29, 0xf8, 0xd3,
+0x19, 0x49, 0x8a, 0x6a, 0x13, 0x18, 0x1a, 0x6d, 0x00, 0x9d, 0x55, 0x40,
+0x19, 0x4a, 0xd6, 0x68, 0x75, 0x40, 0x1d, 0x65, 0x89, 0x6a, 0x08, 0x18,
+0x41, 0x6d, 0x02, 0x9b, 0x59, 0x40, 0x92, 0x69, 0x51, 0x40, 0x41, 0x65,
+0x20, 0x78, 0x41, 0x1e, 0x21, 0x70, 0x00, 0x28, 0x0d, 0xd0, 0x38, 0x1c,
+0xff, 0xf7, 0xf4, 0xfe, 0x00, 0x28, 0x0d, 0xd1, 0x08, 0x4a, 0x50, 0x68,
+0xc0, 0x68, 0xc0, 0x46, 0x50, 0x60, 0x38, 0x1c, 0x00, 0xf0, 0xa4, 0xfa,
+0x02, 0xe0, 0x38, 0x1c, 0x00, 0xf0, 0x73, 0xfa, 0x01, 0xf0, 0xde, 0xfa,
+0x03, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x6c, 0x06, 0x00, 0x80,
+0x00, 0x00, 0x00, 0xb0, 0x38, 0x04, 0x00, 0x80, 0x4c, 0x2a, 0x00, 0x80,
+0xac, 0xab, 0x20, 0x40, 0x94, 0x06, 0x00, 0x80, 0x08, 0x83, 0x20, 0x40,
+0xf0, 0xb5, 0x82, 0xb0, 0x69, 0x4b, 0x9f, 0x6a, 0x58, 0x23, 0x5a, 0x43,
+0xba, 0x18, 0xc3, 0x1d, 0x49, 0x33, 0x1f, 0x78, 0x01, 0x23, 0x9b, 0x07,
+0xd4, 0x1d, 0x01, 0x34, 0x23, 0x43, 0x1d, 0x68, 0x43, 0x68, 0x1c, 0x04,
+0x01, 0x23, 0x9b, 0x07, 0xd6, 0x1d, 0x05, 0x36, 0x33, 0x43, 0x1b, 0x68,
+0x1c, 0x43, 0x42, 0x23, 0x1c, 0x43, 0x0c, 0x60, 0xff, 0x26, 0x36, 0x02,
+0x2e, 0x40, 0x01, 0x23, 0x5b, 0x02, 0x9e, 0x42, 0x74, 0xd1, 0x6b, 0x0c,
+0x2b, 0xd3, 0xc3, 0x19, 0x20, 0x33, 0x1b, 0x79,
0xc0, 0x46, 0x4b, 0x81, 0x7b, 0x00, 0x1b, 0x18, 0x1b, 0x8f, 0x4c, 0x89,
-0x1b, 0x1b, 0xcb, 0x80, 0x00, 0x24, 0xa6, 0x00,
-0x01, 0x96, 0xb3, 0x18, 0xde, 0x1d, 0x09, 0x36, 0x01, 0x23, 0x9b, 0x07,
-0x33, 0x43, 0x1b, 0x68, 0x01, 0x9e, 0x76, 0x18, 0x73, 0x61, 0x01, 0x34,
-0x05, 0x2c, 0xf0, 0xd3, 0x00, 0x24, 0xa6, 0x00, 0x00, 0x96, 0xb3, 0x18,
-0xde, 0x1d, 0x1d, 0x36, 0x01, 0x23, 0x9b, 0x07, 0x33, 0x43, 0x1b, 0x68,
-0x00, 0x9e, 0x76, 0x18, 0xb3, 0x62, 0x01, 0x34, 0x05, 0x2c, 0xf0, 0xd3,
-0x06, 0xe0, 0x00, 0x23, 0x4b, 0x81, 0xcb, 0x80, 0x40, 0x23, 0x9c, 0x43,
-0x0c, 0x60, 0x23, 0x1c, 0x6b, 0x0e, 0x4a, 0xd3, 0xc3, 0x19, 0x20, 0x33,
-0x1b, 0x79, 0x10, 0x33, 0x0b, 0x81, 0x7b, 0x00, 0x1b, 0x18, 0x1b, 0x8f,
-0x0f, 0x89, 0xdb, 0x1b, 0x8b, 0x80, 0x01, 0x23, 0x9b, 0x07, 0xd4, 0x1d,
-0x35, 0x34, 0x23, 0x43, 0x1b, 0x68, 0xc0, 0x46, 0xcb, 0x63, 0x01, 0x23,
-0x9b, 0x07, 0xd4, 0x1d, 0x31, 0x34, 0x23, 0x43, 0x1b, 0x68, 0xc0, 0x46,
-0x0b, 0x64, 0xab, 0x0e, 0x21, 0xd2, 0x01, 0x23, 0x9b, 0x07, 0xd4, 0x1d,
-0x3d, 0x34, 0x23, 0x43, 0x1b, 0x68, 0xc0, 0x46, 0x4b, 0x64, 0x01, 0x23,
-0x9b, 0x07, 0xd4, 0x1d, 0x39, 0x34, 0x23, 0x43, 0x1b, 0x68, 0xc0, 0x46,
-0x8b, 0x64, 0x01, 0x23, 0x9b, 0x07, 0xd4, 0x1d, 0x45, 0x34, 0x23, 0x43,
-0x1b, 0x68, 0xc0, 0x46, 0xcb, 0x64, 0x01, 0x23, 0x9b, 0x07, 0xd4, 0x1d,
-0x41, 0x34, 0x23, 0x43, 0x1b, 0x68, 0xc0, 0x46, 0x0b, 0x65, 0x00, 0xe0,
-0x0f, 0xe0, 0xfb, 0x1f, 0x01, 0x3b, 0x1b, 0x04, 0x1b, 0x0c, 0x07, 0x68,
-0xff, 0x18, 0x03, 0x69, 0x08, 0x1c, 0x39, 0x1c, 0x00, 0xf0, 0x34, 0xf8,
-0x2c, 0xe0, 0x00, 0x23, 0x0b, 0x81, 0x8b, 0x80, 0x28, 0xe0, 0x00, 0x23,
-0x8b, 0x80, 0x0b, 0x81, 0xc3, 0x19, 0x20, 0x33, 0x1b, 0x7a, 0xc0, 0x46,
-0x4b, 0x81, 0x7b, 0x00, 0x18, 0x18, 0x00, 0x8e, 0xc0, 0x46, 0xc8, 0x80,
-0x00, 0x20, 0x87, 0x00, 0xbb, 0x18, 0xdc, 0x1d, 0x09, 0x34, 0x01, 0x23,
-0x9b, 0x07, 0x23, 0x43, 0x1b, 0x68, 0x7f, 0x18, 0x7b, 0x61, 0x01, 0x30,
-0x05, 0x28, 0xf2, 0xd3, 0x00, 0x20, 0x87, 0x00, 0xbb, 0x18, 0xdc, 0x1d,
-0x1d, 0x34, 0x01, 0x23, 0x9b, 0x07, 0x23, 0x43, 0x1b, 0x68, 0x7f, 0x18,
-0xbb, 0x62, 0x01, 0x30, 0x05, 0x28, 0xf2, 0xd3, 0x02, 0xb0, 0xf0, 0xbc,
-0x08, 0xbc, 0x18, 0x47, 0x4c, 0x2a, 0x00, 0x80, 0x80, 0xb4, 0x1f, 0x1c,
-0x3b, 0x0c, 0x18, 0xd2, 0x17, 0x6d, 0x11, 0x4b, 0xc0, 0x46, 0xdf, 0x60,
-0x52, 0x6d, 0xc0, 0x46, 0x1a, 0x61, 0xc7, 0x60, 0x1a, 0x69, 0xc0, 0x46,
-0x02, 0x61, 0xd8, 0x68, 0xc0, 0x46, 0x08, 0x80, 0xd8, 0x68, 0x00, 0x0c,
-0x48, 0x80, 0x18, 0x69, 0xc0, 0x46, 0x88, 0x80, 0x18, 0x69, 0x00, 0x0c,
-0xc8, 0x80, 0x80, 0xbc, 0x70, 0x47, 0x4a, 0x88, 0x12, 0x04, 0x0b, 0x88,
-0x1a, 0x43, 0xc2, 0x60, 0x8a, 0x88, 0xc9, 0x88, 0x09, 0x04, 0x11, 0x43,
-0x01, 0x61, 0xf2, 0xe7, 0x2c, 0x07, 0x00, 0x80, 0xf1, 0xb5, 0x88, 0xb0,
-0x00, 0x22, 0x08, 0x98, 0x00, 0x6a, 0x08, 0x9b, 0x99, 0x68, 0x49, 0x0a,
-0x02, 0xd3, 0x01, 0x27, 0xff, 0x03, 0x00, 0xe0, 0x00, 0x27, 0x03, 0x8b,
-0x00, 0x2b, 0x19, 0xd0, 0xa3, 0x49, 0x89, 0x6a, 0x1c, 0x1c, 0x58, 0x23,
-0x63, 0x43, 0xc9, 0x18, 0x01, 0x23, 0x9b, 0x07, 0x58, 0x39, 0x19, 0x43,
-0x09, 0x68, 0x09, 0x04, 0x09, 0x0c, 0x02, 0x29, 0x02, 0xd1, 0x08, 0x23,
-0x1f, 0x43, 0x07, 0xe0, 0x41, 0x8b, 0x00, 0x29, 0x02, 0xd0, 0x0c, 0x23,
+0x1b, 0x1b, 0xcb, 0x80, 0x00, 0x24, 0xa6, 0x00, 0x01, 0x96, 0xb3, 0x18,
+0xde, 0x1d, 0x09, 0x36, 0x01, 0x23, 0x9b, 0x07, 0x33, 0x43, 0x1b, 0x68,
+0x01, 0x9e, 0x76, 0x18, 0x73, 0x61, 0x01, 0x34, 0x05, 0x2c, 0xf0, 0xd3,
+0x00, 0x24, 0xa6, 0x00, 0x00, 0x96, 0xb3, 0x18, 0xde, 0x1d, 0x1d, 0x36,
+0x01, 0x23, 0x9b, 0x07, 0x33, 0x43, 0x1b, 0x68, 0x00, 0x9e, 0x76, 0x18,
+0xb3, 0x62, 0x01, 0x34, 0x05, 0x2c, 0xf0, 0xd3, 0x06, 0xe0, 0x00, 0x23,
+0x4b, 0x81, 0xcb, 0x80, 0x40, 0x23, 0x9c, 0x43, 0x0c, 0x60, 0x23, 0x1c,
+0x6b, 0x0e, 0x4a, 0xd3, 0xc3, 0x19, 0x20, 0x33, 0x1b, 0x79, 0x10, 0x33,
+0x0b, 0x81, 0x7b, 0x00, 0x1b, 0x18, 0x1b, 0x8f, 0x0f, 0x89, 0xdb, 0x1b,
+0x8b, 0x80, 0x01, 0x23, 0x9b, 0x07, 0xd4, 0x1d, 0x35, 0x34, 0x23, 0x43,
+0x1b, 0x68, 0xc0, 0x46, 0xcb, 0x63, 0x01, 0x23, 0x9b, 0x07, 0xd4, 0x1d,
+0x31, 0x34, 0x23, 0x43, 0x1b, 0x68, 0xc0, 0x46, 0x0b, 0x64, 0xab, 0x0e,
+0x21, 0xd2, 0x01, 0x23, 0x9b, 0x07, 0xd4, 0x1d, 0x3d, 0x34, 0x23, 0x43,
+0x1b, 0x68, 0xc0, 0x46, 0x4b, 0x64, 0x01, 0x23, 0x9b, 0x07, 0xd4, 0x1d,
+0x39, 0x34, 0x23, 0x43, 0x1b, 0x68, 0xc0, 0x46, 0x8b, 0x64, 0x01, 0x23,
+0x9b, 0x07, 0xd4, 0x1d, 0x45, 0x34, 0x23, 0x43, 0x1b, 0x68, 0xc0, 0x46,
+0xcb, 0x64, 0x01, 0x23, 0x9b, 0x07, 0xd4, 0x1d, 0x41, 0x34, 0x23, 0x43,
+0x1b, 0x68, 0xc0, 0x46, 0x0b, 0x65, 0x00, 0xe0, 0x0f, 0xe0, 0xfb, 0x1f,
+0x01, 0x3b, 0x1b, 0x04, 0x1b, 0x0c, 0x07, 0x68, 0xff, 0x18, 0x03, 0x69,
+0x08, 0x1c, 0x39, 0x1c, 0x00, 0xf0, 0x34, 0xf8, 0x2c, 0xe0, 0x00, 0x23,
+0x0b, 0x81, 0x8b, 0x80, 0x28, 0xe0, 0x00, 0x23, 0x8b, 0x80, 0x0b, 0x81,
+0xc3, 0x19, 0x20, 0x33, 0x1b, 0x7a, 0xc0, 0x46, 0x4b, 0x81, 0x7b, 0x00,
+0x18, 0x18, 0x00, 0x8e, 0xc0, 0x46, 0xc8, 0x80, 0x00, 0x20, 0x87, 0x00,
+0xbb, 0x18, 0xdc, 0x1d, 0x09, 0x34, 0x01, 0x23, 0x9b, 0x07, 0x23, 0x43,
+0x1b, 0x68, 0x7f, 0x18, 0x7b, 0x61, 0x01, 0x30, 0x05, 0x28, 0xf2, 0xd3,
+0x00, 0x20, 0x87, 0x00, 0xbb, 0x18, 0xdc, 0x1d, 0x1d, 0x34, 0x01, 0x23,
+0x9b, 0x07, 0x23, 0x43, 0x1b, 0x68, 0x7f, 0x18, 0xbb, 0x62, 0x01, 0x30,
+0x05, 0x28, 0xf2, 0xd3, 0x02, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47,
+0x4c, 0x2a, 0x00, 0x80, 0x80, 0xb4, 0x1f, 0x1c, 0x3b, 0x0c, 0x18, 0xd2,
+0x17, 0x6d, 0x11, 0x4b, 0xc0, 0x46, 0xdf, 0x60, 0x52, 0x6d, 0xc0, 0x46,
+0x1a, 0x61, 0xc7, 0x60, 0x1a, 0x69, 0xc0, 0x46, 0x02, 0x61, 0xd8, 0x68,
+0xc0, 0x46, 0x08, 0x80, 0xd8, 0x68, 0x00, 0x0c, 0x48, 0x80, 0x18, 0x69,
+0xc0, 0x46, 0x88, 0x80, 0x18, 0x69, 0x00, 0x0c, 0xc8, 0x80, 0x80, 0xbc,
+0x70, 0x47, 0x4a, 0x88, 0x12, 0x04, 0x0b, 0x88, 0x1a, 0x43, 0xc2, 0x60,
+0x8a, 0x88, 0xc9, 0x88, 0x09, 0x04, 0x11, 0x43, 0x01, 0x61, 0xf2, 0xe7,
+0x2c, 0x07, 0x00, 0x80, 0xf1, 0xb5, 0x88, 0xb0, 0x00, 0x22, 0x08, 0x98,
+0x00, 0x6a, 0x08, 0x9b, 0x99, 0x68, 0x49, 0x0a, 0x02, 0xd3, 0x01, 0x27,
+0xff, 0x03, 0x00, 0xe0, 0x00, 0x27, 0x03, 0x8b, 0x00, 0x2b, 0x19, 0xd0,
+0xa3, 0x49, 0x89, 0x6a, 0x1c, 0x1c, 0x58, 0x23, 0x63, 0x43, 0xc9, 0x18,
+0x01, 0x23, 0x9b, 0x07, 0x58, 0x39, 0x19, 0x43, 0x09, 0x68, 0x09, 0x04,
+0x09, 0x0c, 0x02, 0x29, 0x02, 0xd1, 0x08, 0x23, 0x1f, 0x43, 0x07, 0xe0,
+0x41, 0x8b, 0x00, 0x29, 0x02, 0xd0, 0x0c, 0x23,
0x1f, 0x43, 0x01, 0xe0, 0x04, 0x23, 0x1f, 0x43, 0x83, 0x8a, 0x00, 0x2b,
-0x18, 0xd0, 0x95, 0x49, 0x89, 0x6a, 0x1c, 0x1c,
-0x58, 0x23, 0x63, 0x43, 0xc9, 0x18, 0x01, 0x23, 0x9b, 0x07, 0x58, 0x39,
-0x19, 0x43, 0x09, 0x68, 0x09, 0x04, 0x09, 0x0c, 0x02, 0x29, 0x01, 0xd1,
-0x0f, 0x43, 0x07, 0xe0, 0xc1, 0x8a, 0x00, 0x29, 0x02, 0xd0, 0x03, 0x23,
-0x1f, 0x43, 0x01, 0xe0, 0x01, 0x23, 0x1f, 0x43, 0xc1, 0x1d, 0x39, 0x31,
-0x07, 0x91, 0x4b, 0x89, 0x0c, 0x89, 0x1c, 0x19, 0x24, 0x04, 0x24, 0x0c,
-0x08, 0x9d, 0x2d, 0x68, 0xc0, 0x46, 0x01, 0x95, 0xc9, 0x88, 0x7d, 0x08,
-0x1a, 0xd3, 0x1a, 0x1c, 0xc3, 0x1d, 0x19, 0x33, 0x1a, 0x72, 0x07, 0x9a,
-0x92, 0x89, 0xc0, 0x46, 0x1a, 0x73, 0x07, 0x9a, 0x12, 0x89, 0xc0, 0x46,
-0x02, 0x86, 0x04, 0x87, 0x82, 0x8a, 0x01, 0x3a, 0x82, 0x83, 0x01, 0x22,
-0x19, 0x71, 0x08, 0x9b, 0x1b, 0x68, 0x5b, 0x18, 0x5b, 0x78, 0x9b, 0x00,
-0x1b, 0x04, 0x1b, 0x0c, 0x08, 0x33, 0x59, 0x18, 0xbb, 0x08, 0x47, 0xd3,
-0x07, 0x9b, 0x5b, 0x89, 0x85, 0x18, 0x06, 0x95, 0x20, 0x35, 0x2b, 0x72,
-0x07, 0x9b, 0x9b, 0x89, 0xc0, 0x46, 0x2b, 0x73, 0x07, 0x9b, 0x1b, 0x89,
-0x2e, 0x1c, 0x55, 0x00, 0x2d, 0x18, 0x05, 0x95, 0x2b, 0x86, 0x00, 0x2a,
-0x01, 0xd0, 0xc3, 0x8a, 0x00, 0xe0, 0x83, 0x8a, 0x01, 0x3b, 0x05, 0x9d,
-0xc0, 0x46, 0xab, 0x83, 0x31, 0x71, 0x65, 0x4b, 0x9d, 0x6a, 0x05, 0x9b,
+0x18, 0xd0, 0x95, 0x49, 0x89, 0x6a, 0x1c, 0x1c, 0x58, 0x23, 0x63, 0x43,
+0xc9, 0x18, 0x01, 0x23, 0x9b, 0x07, 0x58, 0x39, 0x19, 0x43, 0x09, 0x68,
+0x09, 0x04, 0x09, 0x0c, 0x02, 0x29, 0x01, 0xd1, 0x0f, 0x43, 0x07, 0xe0,
+0xc1, 0x8a, 0x00, 0x29, 0x02, 0xd0, 0x03, 0x23, 0x1f, 0x43, 0x01, 0xe0,
+0x01, 0x23, 0x1f, 0x43, 0xc1, 0x1d, 0x39, 0x31, 0x07, 0x91, 0x4b, 0x89,
+0x0c, 0x89, 0x1c, 0x19, 0x24, 0x04, 0x24, 0x0c, 0x08, 0x9d, 0x2d, 0x68,
+0xc0, 0x46, 0x01, 0x95, 0xc9, 0x88, 0x7d, 0x08, 0x1a, 0xd3, 0x1a, 0x1c,
+0xc3, 0x1d, 0x19, 0x33, 0x1a, 0x72, 0x07, 0x9a, 0x92, 0x89, 0xc0, 0x46,
+0x1a, 0x73, 0x07, 0x9a, 0x12, 0x89, 0xc0, 0x46, 0x02, 0x86, 0x04, 0x87,
+0x82, 0x8a, 0x01, 0x3a, 0x82, 0x83, 0x01, 0x22, 0x19, 0x71, 0x08, 0x9b,
+0x1b, 0x68, 0x5b, 0x18, 0x5b, 0x78, 0x9b, 0x00, 0x1b, 0x04, 0x1b, 0x0c,
+0x08, 0x33, 0x59, 0x18, 0xbb, 0x08, 0x47, 0xd3, 0x07, 0x9b, 0x5b, 0x89,
+0x85, 0x18, 0x06, 0x95, 0x20, 0x35, 0x2b, 0x72, 0x07, 0x9b, 0x9b, 0x89,
+0xc0, 0x46, 0x2b, 0x73, 0x07, 0x9b, 0x1b, 0x89, 0x2e, 0x1c, 0x55, 0x00,
+0x2d, 0x18, 0x05, 0x95, 0x2b, 0x86, 0x00, 0x2a, 0x01, 0xd0, 0xc3, 0x8a,
+0x00, 0xe0, 0x83, 0x8a, 0x01, 0x3b, 0x05, 0x9d, 0xc0, 0x46, 0xab, 0x83,
+0x31, 0x71, 0x65, 0x4b, 0x9d, 0x6a, 0x05, 0x9b, 0x9e, 0x8b, 0x58, 0x23,
+0x73, 0x43, 0xeb, 0x18, 0xdd, 0x1d, 0x01, 0x35, 0x01, 0x23, 0x9b, 0x07,
+0x2b, 0x43, 0x1d, 0x68, 0x2b, 0x0e, 0x5b, 0x06, 0x01, 0xd1, 0x08, 0x31,
+0x00, 0xe0, 0x10, 0x31, 0x81, 0x23, 0x5b, 0x02, 0x1d, 0x40, 0x9d, 0x42,
+0x03, 0xd1, 0xe3, 0x1f, 0x05, 0x3b, 0x1c, 0x04, 0x24, 0x0c, 0x05, 0x9b,
+0xc0, 0x46, 0x1c, 0x87, 0x08, 0x9b, 0x1b, 0x68, 0x1b, 0x19, 0x10, 0x3b,
+0x9b, 0x7b, 0x06, 0x9d, 0x40, 0x35, 0x2b, 0x70, 0x2b, 0x78, 0x02, 0x33,
+0xe3, 0x1a, 0x1c, 0x04, 0x24, 0x0c, 0x01, 0x32, 0xbb, 0x08, 0x9b, 0x07,
+0x6d, 0xd0, 0x83, 0x18, 0x20, 0x33, 0x04, 0x93, 0x19, 0x72, 0x01, 0x9b,
+0x5d, 0x18, 0x01, 0x23, 0x9b, 0x07, 0x2b, 0x43, 0x1b, 0x68, 0x1b, 0x07,
+0x1b, 0x0f, 0x9b, 0x00, 0x04, 0x9e, 0xc0, 0x46, 0x33, 0x73, 0x00, 0x95,
+0x2b, 0x78, 0x1b, 0x07, 0x1b, 0x0f, 0x9b, 0x00, 0x04, 0x9d, 0xc0, 0x46,
+0x2b, 0x73, 0x00, 0x9d, 0xeb, 0x78, 0xad, 0x78, 0x1b, 0x02, 0x1d, 0x43,
+0x2b, 0x02, 0x2d, 0x0a, 0x2d, 0x06, 0x2d, 0x0e, 0x2b, 0x43, 0x55, 0x00,
+0x2d, 0x18, 0x2b, 0x86, 0x04, 0x9b, 0xc0, 0x46, 0x59, 0x72, 0x04, 0x9b,
+0x1b, 0x7b, 0x2e, 0x1c, 0x04, 0x9d, 0xc0, 0x46, 0x6b, 0x73, 0x33, 0x8e,
+0xc0, 0x46, 0x73, 0x86, 0x00, 0x9d, 0x2b, 0x78, 0x1b, 0x07, 0x1b, 0x0f,
+0x9b, 0x00, 0x1b, 0x04, 0x1b, 0x0c, 0x59, 0x18, 0x04, 0x25, 0x3d, 0x40,
+0x0e, 0xd0, 0x34, 0x87, 0x03, 0x8b, 0x01, 0x3b, 0xb3, 0x83, 0x13, 0x1c,
+0x1b, 0x18, 0x20, 0x33, 0x19, 0x71, 0x01, 0x9b, 0x5b, 0x18, 0x5b, 0x78,
+0x9b, 0x00, 0x59, 0x18, 0x08, 0x31, 0x01, 0x32, 0x3b, 0x09, 0x37, 0xd3,
+0x00, 0x2d, 0x01, 0xd0, 0x43, 0x8b, 0x00, 0xe0, 0x03, 0x8b, 0x55, 0x00,
+0x2d, 0x18, 0x01, 0x3b, 0xab, 0x83, 0x83, 0x18, 0x03, 0x93, 0x20, 0x33,
+0x19, 0x71, 0x20, 0x4b, 0x9d, 0x6a, 0x53, 0x00, 0x1b, 0x18, 0x02, 0x93,
0x9e, 0x8b, 0x58, 0x23, 0x73, 0x43, 0xeb, 0x18, 0xdd, 0x1d, 0x01, 0x35,
-0x01, 0x23, 0x9b, 0x07, 0x2b, 0x43, 0x1d, 0x68, 0x2b, 0x0e, 0x5b, 0x06,
-0x01, 0xd1, 0x08, 0x31, 0x00, 0xe0, 0x10, 0x31, 0x81, 0x23, 0x5b, 0x02,
-0x1d, 0x40, 0x9d, 0x42, 0x03, 0xd1, 0xe3, 0x1f, 0x05, 0x3b, 0x1c, 0x04,
-0x24, 0x0c, 0x05, 0x9b, 0xc0, 0x46, 0x1c, 0x87, 0x08, 0x9b, 0x1b, 0x68,
-0x1b, 0x19, 0x10, 0x3b, 0x9b, 0x7b, 0x06, 0x9d, 0x40, 0x35, 0x2b, 0x70,
-0x2b, 0x78, 0x02, 0x33, 0xe3, 0x1a, 0x1c, 0x04, 0x24, 0x0c, 0x01, 0x32,
-0xbb, 0x08, 0x9b, 0x07, 0x6d, 0xd0, 0x83, 0x18, 0x20, 0x33, 0x04, 0x93,
-0x19, 0x72, 0x01, 0x9b, 0x5d, 0x18, 0x01, 0x23, 0x9b, 0x07, 0x2b, 0x43,
-0x1b, 0x68, 0x1b, 0x07, 0x1b, 0x0f, 0x9b, 0x00, 0x04, 0x9e, 0xc0, 0x46,
-0x33, 0x73, 0x00, 0x95, 0x2b, 0x78, 0x1b, 0x07, 0x1b, 0x0f, 0x9b, 0x00,
-0x04, 0x9d, 0xc0, 0x46, 0x2b, 0x73, 0x00, 0x9d, 0xeb, 0x78, 0xad, 0x78,
-0x1b, 0x02, 0x1d, 0x43, 0x2b, 0x02, 0x2d, 0x0a, 0x2d, 0x06, 0x2d, 0x0e,
-0x2b, 0x43, 0x55, 0x00, 0x2d, 0x18, 0x2b, 0x86, 0x04, 0x9b, 0xc0, 0x46,
-0x59, 0x72, 0x04, 0x9b, 0x1b, 0x7b, 0x2e, 0x1c, 0x04, 0x9d, 0xc0, 0x46,
-0x6b, 0x73, 0x33, 0x8e, 0xc0, 0x46, 0x73, 0x86, 0x00, 0x9d, 0x2b, 0x78,
-0x1b, 0x07, 0x1b, 0x0f, 0x9b, 0x00, 0x1b, 0x04, 0x1b, 0x0c, 0x59, 0x18,
-0x04, 0x25, 0x3d, 0x40, 0x0e, 0xd0, 0x34, 0x87, 0x03, 0x8b, 0x01, 0x3b,
-0xb3, 0x83, 0x13, 0x1c, 0x1b, 0x18, 0x20, 0x33, 0x19, 0x71, 0x01, 0x9b,
-0x5b, 0x18, 0x5b, 0x78, 0x9b, 0x00, 0x59, 0x18, 0x08, 0x31, 0x01, 0x32,
-0x3b, 0x09, 0x37, 0xd3, 0x00, 0x2d, 0x01, 0xd0, 0x43, 0x8b, 0x00, 0xe0,
-0x03, 0x8b, 0x55, 0x00, 0x2d, 0x18, 0x01, 0x3b, 0xab, 0x83, 0x83, 0x18,
-0x03, 0x93, 0x20, 0x33, 0x19, 0x71, 0x20, 0x4b, 0x9d, 0x6a, 0x53, 0x00,
-0x1b, 0x18, 0x02, 0x93, 0x9e, 0x8b, 0x58, 0x23, 0x73, 0x43, 0xeb, 0x18,
-0xdd, 0x1d, 0x01, 0x35, 0x01, 0x23, 0x9b, 0x07, 0x2b, 0x43, 0x1d, 0x68,
+0x01, 0x23, 0x9b, 0x07, 0x2b, 0x43, 0x1d, 0x68,
0x2b, 0x0e, 0x5b, 0x06, 0x02, 0xd1, 0x08, 0x31, 0x01, 0xe0, 0x15, 0xe0,
-0x10, 0x31, 0x81, 0x23, 0x5b, 0x02, 0x1d, 0x40,
-0x9d, 0x42, 0x03, 0xd1, 0xe3, 0x1f, 0x05, 0x3b, 0x1c, 0x04, 0x24, 0x0c,
-0x02, 0x9b, 0xc0, 0x46, 0x1c, 0x87, 0x08, 0x9b, 0x1b, 0x68, 0x1b, 0x19,
-0x10, 0x3b, 0x9b, 0x7b, 0x03, 0x9c, 0x40, 0x34, 0x23, 0x70, 0x01, 0x32,
-0x07, 0x9b, 0xc0, 0x46, 0xd9, 0x80, 0x51, 0x1e, 0xc3, 0x1d, 0x49, 0x33,
-0x19, 0x70, 0x07, 0x61, 0x04, 0x2a, 0x06, 0xd2, 0x06, 0x49, 0x53, 0x00,
-0x1b, 0x18, 0x99, 0x83, 0x01, 0x32, 0x04, 0x2a, 0xf9, 0xd3, 0x09, 0xb0,
-0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x4c, 0x2a, 0x00, 0x80,
-0xff, 0xff, 0x00, 0x00, 0x70, 0x47, 0x80, 0xb5, 0x8c, 0xb0, 0x07, 0x1c,
-0x12, 0x48, 0x01, 0x68, 0x01, 0x31, 0x01, 0x60, 0x38, 0x68, 0xc0, 0x46,
-0x00, 0x90, 0x78, 0x68, 0xc0, 0x46, 0x01, 0x90, 0xb8, 0x68, 0xc0, 0x46,
-0x02, 0x90, 0x0d, 0x48, 0x41, 0x68, 0xc9, 0x68, 0xc0, 0x46, 0x41, 0x60,
-0x38, 0x1c, 0x00, 0xf0, 0x4f, 0xf8, 0xb8, 0x68, 0x40, 0x09, 0x06, 0xd3,
-0x10, 0x23, 0x02, 0x98, 0x18, 0x43, 0x02, 0x90, 0x68, 0x46, 0x02, 0xf0,
-0xe1, 0xff, 0x68, 0x46, 0x02, 0xf0, 0x9a, 0xfe, 0x0c, 0xb0, 0x80, 0xbc,
-0x08, 0xbc, 0x18, 0x47, 0x0c, 0x2b, 0x00, 0x80, 0x6c, 0x06, 0x00, 0x80,
-0x00, 0xb5, 0x8c, 0xb0, 0x01, 0x68, 0xc0, 0x46, 0x00, 0x91, 0x41, 0x68,
-0x05, 0x4b, 0x19, 0x43, 0x01, 0x91, 0x00, 0xf0, 0x2f, 0xf8, 0x68, 0x46,
-0x02, 0xf0, 0x84, 0xfe, 0x0c, 0xb0, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00,
-0x00, 0x00, 0x00, 0xa0, 0x02, 0x6a, 0x03, 0x68, 0xc0, 0x46, 0x13, 0x60,
-0x40, 0x68, 0xc0, 0x46, 0x50, 0x60, 0x40, 0x32, 0x48, 0x68, 0xc0, 0x46,
-0x90, 0x80, 0xc8, 0x68, 0xc0, 0x46, 0xd0, 0x80, 0x48, 0x69, 0xc0, 0x46,
-0x10, 0x81, 0x88, 0x68, 0xc0, 0x46, 0x50, 0x81, 0x08, 0x7e, 0xc0, 0x46,
-0x90, 0x73, 0x08, 0x69, 0xc0, 0x46, 0x90, 0x81, 0x70, 0x47, 0x04, 0x49,
-0x08, 0x68, 0x00, 0x28, 0x00, 0xd1, 0x70, 0x47, 0xc2, 0x68, 0xc0, 0x46,
-0x0a, 0x60, 0xfa, 0xe7, 0x6c, 0x06, 0x00, 0x80, 0x02, 0x49, 0x0a, 0x68,
-0xc0, 0x46, 0xc2, 0x60, 0x08, 0x60, 0x70, 0x47, 0x6c, 0x06, 0x00, 0x80,
-0xb0, 0xb4, 0x00, 0x22, 0x12, 0x4f, 0x7c, 0x7f, 0x01, 0x34, 0x7c, 0x77,
-0x03, 0x23, 0xfc, 0x1d, 0x19, 0x34, 0x38, 0x62, 0x79, 0x62, 0x23, 0x72,
-0x0e, 0x4c, 0x25, 0x68, 0x6b, 0x0c, 0x05, 0xd2, 0x23, 0x68, 0x1b, 0x0c,
-0x10, 0xd1, 0x24, 0x68, 0xa3, 0x0a, 0x0d, 0xd3, 0x01, 0x23, 0x0a, 0x4f,
-0xc0, 0x46, 0xfb, 0x62, 0x09, 0x4f, 0x0a, 0x4b, 0xc0, 0x46, 0xdf, 0x60,
-0x99, 0x60, 0x58, 0x60, 0x10, 0x1c, 0x18, 0x60, 0x01, 0x32, 0xfb, 0xe7,
-0x10, 0x1c, 0x38, 0x64, 0x01, 0x32, 0xfb, 0xe7, 0x00, 0x00, 0x00, 0x80,
-0x00, 0x00, 0x10, 0x40, 0xc0, 0x00, 0x18, 0x00, 0x02, 0x81, 0x00, 0x00,
-0x40, 0x01, 0x18, 0x00, 0xf0, 0xb5, 0x47, 0x4f, 0x38, 0x68, 0x47, 0x4e,
-0x47, 0x4d, 0x07, 0x23, 0x5b, 0x02, 0xec, 0x18, 0x00, 0x28, 0x1d, 0xd1,
-0x20, 0x6b, 0x01, 0x30, 0x20, 0x63, 0x44, 0x49, 0xc0, 0x46, 0x08, 0x60,
-0x43, 0x48, 0x41, 0x69, 0x00, 0x29, 0x13, 0xd0, 0xc1, 0x1d, 0x69, 0x31,
-0x09, 0x7b, 0x00, 0x29, 0x0e, 0xd0, 0x01, 0x23, 0x9b, 0x07, 0x01, 0x6d,
-0x19, 0x43, 0x09, 0x68, 0xc0, 0x46, 0x81, 0x61, 0xc2, 0x69, 0x91, 0x42,
-0x04, 0xd0, 0xf1, 0x6c, 0x01, 0x31, 0xf1, 0x64, 0x01, 0xf0, 0x50, 0xfe,
+0x10, 0x31, 0x81, 0x23, 0x5b, 0x02, 0x1d, 0x40, 0x9d, 0x42, 0x03, 0xd1,
+0xe3, 0x1f, 0x05, 0x3b, 0x1c, 0x04, 0x24, 0x0c, 0x02, 0x9b, 0xc0, 0x46,
+0x1c, 0x87, 0x08, 0x9b, 0x1b, 0x68, 0x1b, 0x19, 0x10, 0x3b, 0x9b, 0x7b,
+0x03, 0x9c, 0x40, 0x34, 0x23, 0x70, 0x01, 0x32, 0x07, 0x9b, 0xc0, 0x46,
+0xd9, 0x80, 0x51, 0x1e, 0xc3, 0x1d, 0x49, 0x33, 0x19, 0x70, 0x07, 0x61,
+0x04, 0x2a, 0x06, 0xd2, 0x06, 0x49, 0x53, 0x00, 0x1b, 0x18, 0x99, 0x83,
+0x01, 0x32, 0x04, 0x2a, 0xf9, 0xd3, 0x09, 0xb0, 0xf0, 0xbc, 0x08, 0xbc,
+0x18, 0x47, 0x00, 0x00, 0x4c, 0x2a, 0x00, 0x80, 0xff, 0xff, 0x00, 0x00,
+0x70, 0x47, 0x80, 0xb5, 0x8c, 0xb0, 0x07, 0x1c, 0x12, 0x48, 0x01, 0x68,
+0x01, 0x31, 0x01, 0x60, 0x38, 0x68, 0xc0, 0x46, 0x00, 0x90, 0x78, 0x68,
+0xc0, 0x46, 0x01, 0x90, 0xb8, 0x68, 0xc0, 0x46, 0x02, 0x90, 0x0d, 0x48,
+0x41, 0x68, 0xc9, 0x68, 0xc0, 0x46, 0x41, 0x60, 0x38, 0x1c, 0x00, 0xf0,
+0x4f, 0xf8, 0xb8, 0x68, 0x40, 0x09, 0x06, 0xd3, 0x10, 0x23, 0x02, 0x98,
+0x18, 0x43, 0x02, 0x90, 0x68, 0x46, 0x02, 0xf0, 0xe1, 0xff, 0x68, 0x46,
+0x02, 0xf0, 0x9a, 0xfe, 0x0c, 0xb0, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47,
+0x0c, 0x2b, 0x00, 0x80, 0x6c, 0x06, 0x00, 0x80, 0x00, 0xb5, 0x8c, 0xb0,
+0x01, 0x68, 0xc0, 0x46, 0x00, 0x91, 0x41, 0x68, 0x05, 0x4b, 0x19, 0x43,
+0x01, 0x91, 0x00, 0xf0, 0x2f, 0xf8, 0x68, 0x46, 0x02, 0xf0, 0x84, 0xfe,
+0x0c, 0xb0, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0,
+0x02, 0x6a, 0x03, 0x68, 0xc0, 0x46, 0x13, 0x60, 0x40, 0x68, 0xc0, 0x46,
+0x50, 0x60, 0x40, 0x32, 0x48, 0x68, 0xc0, 0x46, 0x90, 0x80, 0xc8, 0x68,
+0xc0, 0x46, 0xd0, 0x80, 0x48, 0x69, 0xc0, 0x46, 0x10, 0x81, 0x88, 0x68,
+0xc0, 0x46, 0x50, 0x81, 0x08, 0x7e, 0xc0, 0x46, 0x90, 0x73, 0x08, 0x69,
+0xc0, 0x46, 0x90, 0x81, 0x70, 0x47, 0x04, 0x49, 0x08, 0x68, 0x00, 0x28,
+0x00, 0xd1, 0x70, 0x47, 0xc2, 0x68, 0xc0, 0x46, 0x0a, 0x60, 0xfa, 0xe7,
+0x6c, 0x06, 0x00, 0x80, 0x02, 0x49, 0x0a, 0x68, 0xc0, 0x46, 0xc2, 0x60,
+0x08, 0x60, 0x70, 0x47, 0x6c, 0x06, 0x00, 0x80, 0xb0, 0xb4, 0x00, 0x22,
+0x12, 0x4f, 0x7c, 0x7f, 0x01, 0x34, 0x7c, 0x77, 0x03, 0x23, 0xfc, 0x1d,
+0x19, 0x34, 0x38, 0x62, 0x79, 0x62, 0x23, 0x72, 0x0e, 0x4c, 0x25, 0x68,
+0x6b, 0x0c, 0x05, 0xd2, 0x23, 0x68, 0x1b, 0x0c, 0x10, 0xd1, 0x24, 0x68,
+0xa3, 0x0a, 0x0d, 0xd3, 0x01, 0x23, 0x0a, 0x4f, 0xc0, 0x46, 0xfb, 0x62,
+0x09, 0x4f, 0x0a, 0x4b, 0xc0, 0x46, 0xdf, 0x60, 0x99, 0x60, 0x58, 0x60,
+0x10, 0x1c, 0x18, 0x60, 0x01, 0x32, 0xfb, 0xe7, 0x10, 0x1c, 0x38, 0x64,
+0x01, 0x32, 0xfb, 0xe7, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x10, 0x40,
+0xc0, 0x00, 0x18, 0x00, 0x02, 0x81, 0x00, 0x00, 0x40, 0x01, 0x18, 0x00,
+0xf0, 0xb5, 0x47, 0x4f, 0x38, 0x68, 0x47, 0x4e, 0x47, 0x4d, 0x07, 0x23,
+0x5b, 0x02, 0xec, 0x18, 0x00, 0x28, 0x1d, 0xd1, 0x20, 0x6b, 0x01, 0x30,
+0x20, 0x63, 0x44, 0x49, 0xc0, 0x46, 0x08, 0x60, 0x43, 0x48, 0x41, 0x69,
+0x00, 0x29, 0x13, 0xd0, 0xc1, 0x1d, 0x69, 0x31, 0x09, 0x7b, 0x00, 0x29,
+0x0e, 0xd0, 0x01, 0x23, 0x9b, 0x07, 0x01, 0x6d, 0x19, 0x43, 0x09, 0x68,
+0xc0, 0x46, 0x81, 0x61, 0xc2, 0x69, 0x91, 0x42, 0x04, 0xd0, 0xf1, 0x6c,
+0x01, 0x31, 0xf1, 0x64, 0x01, 0xf0, 0x50, 0xfe,
0x38, 0x68, 0x01, 0x28, 0x17, 0xd1, 0x37, 0x48, 0x41, 0x69, 0x00, 0x29,
-0x13, 0xd0, 0xc1, 0x1d, 0x69, 0x31, 0x09, 0x7b,
-0x00, 0x29, 0x0e, 0xd0, 0x01, 0x23, 0x9b, 0x07, 0x01, 0x6d, 0x19, 0x43,
-0x09, 0x68, 0xc0, 0x46, 0x81, 0x61, 0xc2, 0x69, 0x91, 0x42, 0x04, 0xd0,
-0xf1, 0x6c, 0x01, 0x31, 0xf1, 0x64, 0x01, 0xf0, 0x35, 0xfe, 0x38, 0x68,
-0x02, 0x28, 0x2f, 0xd1, 0xbb, 0x23, 0x1b, 0x01, 0xee, 0x18, 0x70, 0x7b,
-0x00, 0x28, 0x03, 0xd0, 0x00, 0x20, 0x70, 0x73, 0x00, 0xf0, 0x4a, 0xfd,
-0x30, 0x7b, 0x00, 0x28, 0x02, 0xd0, 0x78, 0x68, 0x02, 0xf0, 0xaa, 0xff,
-0x1b, 0x23, 0xdb, 0x01, 0xe8, 0x18, 0xc0, 0x8b, 0x04, 0x26, 0x06, 0x40,
-0xe0, 0x6a, 0xb0, 0x42, 0x14, 0xd0, 0xf8, 0x68, 0x01, 0x30, 0xf8, 0x60,
-0x19, 0x28, 0x11, 0xd3, 0x1b, 0x48, 0x01, 0x7b, 0x00, 0x29, 0x0d, 0xd1,
-0xff, 0x30, 0x41, 0x30, 0x40, 0x78, 0x00, 0x28, 0x08, 0xd1, 0xb8, 0x68,
-0x02, 0xf0, 0x90, 0xff, 0x00, 0x20, 0xf8, 0x60, 0xe6, 0x62, 0x01, 0xe0,
-0x00, 0x20, 0xf8, 0x60, 0x38, 0x68, 0x03, 0x28, 0x0b, 0xd1, 0xec, 0x1d,
-0x79, 0x34, 0xe0, 0x6b, 0x80, 0x08, 0x02, 0xd3, 0x02, 0x20, 0x02, 0xf0,
-0x07, 0xfc, 0x02, 0x23, 0xe0, 0x6b, 0x98, 0x43, 0xe0, 0x63, 0x38, 0x68,
-0x01, 0x30, 0x38, 0x60, 0x03, 0x28, 0x01, 0xd9, 0x00, 0x20, 0x38, 0x60,
-0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x3c, 0x04, 0x00, 0x80,
-0xa0, 0x82, 0x20, 0x40, 0x68, 0x0e, 0x00, 0x80, 0x40, 0x01, 0x18, 0x00,
-0x64, 0x2d, 0x00, 0x80, 0xe4, 0x2c, 0x00, 0x80, 0x28, 0x05, 0x00, 0x80,
-0xb0, 0xb4, 0x1d, 0x48, 0x84, 0x8a, 0x1d, 0x4a, 0x13, 0x8a, 0xc1, 0x1d,
-0x09, 0x31, 0x01, 0x27, 0x9c, 0x42, 0x03, 0xd1, 0x43, 0x8a, 0x54, 0x8a,
-0xa3, 0x42, 0x10, 0xd0, 0x0b, 0x78, 0x00, 0x2b, 0x0d, 0xd0, 0x4b, 0x78,
-0x00, 0x2b, 0x0a, 0xd0, 0x44, 0x8b, 0x93, 0x8a, 0x9c, 0x42, 0x04, 0xdc,
-0x13, 0x4b, 0xc0, 0x46, 0x5f, 0x60, 0x97, 0x82, 0x01, 0xe0, 0x01, 0x33,
-0x93, 0x82, 0xc3, 0x8b, 0x5c, 0x1c, 0xc4, 0x83, 0x84, 0x8b, 0xa3, 0x42,
-0x0e, 0xdb, 0x84, 0x8a, 0x05, 0x8b, 0x00, 0x23, 0xac, 0x42, 0x05, 0xda,
-0x44, 0x8a, 0xc5, 0x8a, 0xac, 0x42, 0x01, 0xda, 0x4b, 0x70, 0x00, 0xe0,
-0x4f, 0x70, 0x43, 0x82, 0x83, 0x82, 0xc3, 0x83, 0x41, 0x8a, 0xc0, 0x46,
-0x51, 0x82, 0x80, 0x8a, 0xc0, 0x46, 0x10, 0x82, 0xb0, 0xbc, 0x70, 0x47,
-0xe8, 0x0e, 0x00, 0x80, 0x3c, 0x04, 0x00, 0x80, 0x40, 0x01, 0x18, 0x00,
-0xf7, 0xb5, 0x91, 0xb0, 0x6b, 0x46, 0x84, 0x1e, 0x12, 0x99, 0x14, 0x29,
-0x1a, 0xd9, 0x00, 0x20, 0x81, 0x00, 0x67, 0x58, 0xc0, 0x46, 0x57, 0x50,
-0x01, 0x30, 0x00, 0x06, 0x00, 0x0e, 0x10, 0x28, 0xf6, 0xd3, 0x00, 0x21,
-0x05, 0x20, 0x87, 0x00, 0xd6, 0x59, 0x4f, 0x1c, 0x3d, 0x06, 0x2d, 0x0e,
-0x0f, 0x1c, 0xbf, 0x00, 0xde, 0x51, 0x29, 0x1c, 0x01, 0x30, 0x00, 0x06,
-0x00, 0x0e, 0x10, 0x28, 0xf1, 0xd3, 0x09, 0xe0, 0x00, 0x20, 0x81, 0x00,
-0x63, 0x58, 0xc0, 0x46, 0x53, 0x50, 0x01, 0x30, 0x00, 0x06, 0x00, 0x0e,
-0x06, 0x28, 0xf6, 0xd3, 0x00, 0x20, 0xe0, 0x70, 0x20, 0x72, 0x60, 0x72,
-0xa0, 0x72, 0x20, 0x73, 0x60, 0x73, 0x12, 0x99, 0x14, 0x29, 0x37, 0xd9,
-0x69, 0x46, 0x8e, 0x1c, 0x91, 0x78, 0x09, 0x07, 0x09, 0x0f, 0x89, 0x00,
-0x14, 0x39, 0x0d, 0x06, 0x2d, 0x16, 0x00, 0x27, 0x00, 0x2d, 0x1b, 0xdd,
-0xf0, 0x19, 0x10, 0xa9, 0x00, 0xf0, 0x3d, 0xf8, 0x00, 0x28, 0x0e, 0xd0,
+0x13, 0xd0, 0xc1, 0x1d, 0x69, 0x31, 0x09, 0x7b, 0x00, 0x29, 0x0e, 0xd0,
+0x01, 0x23, 0x9b, 0x07, 0x01, 0x6d, 0x19, 0x43, 0x09, 0x68, 0xc0, 0x46,
+0x81, 0x61, 0xc2, 0x69, 0x91, 0x42, 0x04, 0xd0, 0xf1, 0x6c, 0x01, 0x31,
+0xf1, 0x64, 0x01, 0xf0, 0x35, 0xfe, 0x38, 0x68, 0x02, 0x28, 0x2f, 0xd1,
+0xbb, 0x23, 0x1b, 0x01, 0xee, 0x18, 0x70, 0x7b, 0x00, 0x28, 0x03, 0xd0,
+0x00, 0x20, 0x70, 0x73, 0x00, 0xf0, 0x4a, 0xfd, 0x30, 0x7b, 0x00, 0x28,
+0x02, 0xd0, 0x78, 0x68, 0x02, 0xf0, 0xaa, 0xff, 0x1b, 0x23, 0xdb, 0x01,
+0xe8, 0x18, 0xc0, 0x8b, 0x04, 0x26, 0x06, 0x40, 0xe0, 0x6a, 0xb0, 0x42,
+0x14, 0xd0, 0xf8, 0x68, 0x01, 0x30, 0xf8, 0x60, 0x19, 0x28, 0x11, 0xd3,
+0x1b, 0x48, 0x01, 0x7b, 0x00, 0x29, 0x0d, 0xd1, 0xff, 0x30, 0x41, 0x30,
+0x40, 0x78, 0x00, 0x28, 0x08, 0xd1, 0xb8, 0x68, 0x02, 0xf0, 0x90, 0xff,
+0x00, 0x20, 0xf8, 0x60, 0xe6, 0x62, 0x01, 0xe0, 0x00, 0x20, 0xf8, 0x60,
+0x38, 0x68, 0x03, 0x28, 0x0b, 0xd1, 0xec, 0x1d, 0x79, 0x34, 0xe0, 0x6b,
+0x80, 0x08, 0x02, 0xd3, 0x02, 0x20, 0x02, 0xf0, 0x07, 0xfc, 0x02, 0x23,
+0xe0, 0x6b, 0x98, 0x43, 0xe0, 0x63, 0x38, 0x68, 0x01, 0x30, 0x38, 0x60,
+0x03, 0x28, 0x01, 0xd9, 0x00, 0x20, 0x38, 0x60, 0xf0, 0xbc, 0x08, 0xbc,
+0x18, 0x47, 0x00, 0x00, 0x3c, 0x04, 0x00, 0x80, 0xa0, 0x82, 0x20, 0x40,
+0x68, 0x0e, 0x00, 0x80, 0x40, 0x01, 0x18, 0x00, 0x64, 0x2d, 0x00, 0x80,
+0xe4, 0x2c, 0x00, 0x80, 0x28, 0x05, 0x00, 0x80, 0xb0, 0xb4, 0x1d, 0x48,
+0x84, 0x8a, 0x1d, 0x4a, 0x13, 0x8a, 0xc1, 0x1d, 0x09, 0x31, 0x01, 0x27,
+0x9c, 0x42, 0x03, 0xd1, 0x43, 0x8a, 0x54, 0x8a, 0xa3, 0x42, 0x10, 0xd0,
+0x0b, 0x78, 0x00, 0x2b, 0x0d, 0xd0, 0x4b, 0x78, 0x00, 0x2b, 0x0a, 0xd0,
+0x44, 0x8b, 0x93, 0x8a, 0x9c, 0x42, 0x04, 0xdc, 0x13, 0x4b, 0xc0, 0x46,
+0x5f, 0x60, 0x97, 0x82, 0x01, 0xe0, 0x01, 0x33, 0x93, 0x82, 0xc3, 0x8b,
+0x5c, 0x1c, 0xc4, 0x83, 0x84, 0x8b, 0xa3, 0x42, 0x0e, 0xdb, 0x84, 0x8a,
+0x05, 0x8b, 0x00, 0x23, 0xac, 0x42, 0x05, 0xda, 0x44, 0x8a, 0xc5, 0x8a,
+0xac, 0x42, 0x01, 0xda, 0x4b, 0x70, 0x00, 0xe0, 0x4f, 0x70, 0x43, 0x82,
+0x83, 0x82, 0xc3, 0x83, 0x41, 0x8a, 0xc0, 0x46, 0x51, 0x82, 0x80, 0x8a,
+0xc0, 0x46, 0x10, 0x82, 0xb0, 0xbc, 0x70, 0x47, 0xe8, 0x0e, 0x00, 0x80,
+0x3c, 0x04, 0x00, 0x80, 0x40, 0x01, 0x18, 0x00, 0xf7, 0xb5, 0x91, 0xb0,
+0x6b, 0x46, 0x84, 0x1e, 0x12, 0x99, 0x14, 0x29, 0x1a, 0xd9, 0x00, 0x20,
+0x81, 0x00, 0x67, 0x58, 0xc0, 0x46, 0x57, 0x50, 0x01, 0x30, 0x00, 0x06,
+0x00, 0x0e, 0x10, 0x28, 0xf6, 0xd3, 0x00, 0x21, 0x05, 0x20, 0x87, 0x00,
+0xd6, 0x59, 0x4f, 0x1c, 0x3d, 0x06, 0x2d, 0x0e, 0x0f, 0x1c, 0xbf, 0x00,
+0xde, 0x51, 0x29, 0x1c, 0x01, 0x30, 0x00, 0x06, 0x00, 0x0e, 0x10, 0x28,
+0xf1, 0xd3, 0x09, 0xe0, 0x00, 0x20, 0x81, 0x00, 0x63, 0x58, 0xc0, 0x46,
+0x53, 0x50, 0x01, 0x30, 0x00, 0x06, 0x00, 0x0e, 0x06, 0x28, 0xf6, 0xd3,
+0x00, 0x20, 0xe0, 0x70, 0x20, 0x72, 0x60, 0x72, 0xa0, 0x72, 0x20, 0x73,
+0x60, 0x73, 0x12, 0x99, 0x14, 0x29, 0x37, 0xd9, 0x69, 0x46, 0x8e, 0x1c,
+0x91, 0x78, 0x09, 0x07, 0x09, 0x0f, 0x89, 0x00, 0x14, 0x39, 0x0d, 0x06,
+0x2d, 0x16, 0x00, 0x27, 0x00, 0x2d, 0x1b, 0xdd, 0xf0, 0x19, 0x10, 0xa9,
+0x00, 0xf0, 0x3d, 0xf8, 0x00, 0x28, 0x0e, 0xd0,
0x00, 0x20, 0x10, 0xa9, 0x09, 0x78, 0x00, 0x29, 0x09, 0xdd, 0x00, 0x22,
-0x39, 0x18, 0x72, 0x54, 0x01, 0x30, 0x00, 0x06,
-0x00, 0x0e, 0x10, 0xa9, 0x09, 0x78, 0x88, 0x42, 0xf6, 0xdb, 0x10, 0xa8,
-0x00, 0x78, 0x38, 0x18, 0x07, 0x06, 0x3f, 0x0e, 0xaf, 0x42, 0xe3, 0xdb,
-0x68, 0x46, 0xe2, 0x1d, 0x0d, 0x32, 0x00, 0x21, 0xab, 0x08, 0x5f, 0x1c,
-0x08, 0xd0, 0x8b, 0x00, 0xc4, 0x58, 0xc0, 0x46, 0xd4, 0x50, 0x01, 0x31,
-0x09, 0x06, 0x09, 0x0e, 0x8f, 0x42, 0xf6, 0xd8, 0x14, 0xb0, 0xf0, 0xbc,
-0x08, 0xbc, 0x18, 0x47, 0x90, 0xb4, 0x87, 0x1e, 0x00, 0x20, 0x89, 0x08,
-0x4b, 0x1c, 0x08, 0xd0, 0x81, 0x00, 0x54, 0x58, 0xc0, 0x46, 0x7c, 0x50,
-0x01, 0x30, 0x00, 0x06, 0x00, 0x0e, 0x83, 0x42, 0xf6, 0xd8, 0x90, 0xbc,
-0x70, 0x47, 0x80, 0xb4, 0x02, 0x78, 0xd2, 0x06, 0xd2, 0x0e, 0x00, 0x23,
-0x01, 0x27, 0x01, 0x2a, 0x01, 0xdc, 0x0f, 0x70, 0x11, 0xe0, 0x40, 0x78,
-0xc0, 0x46, 0x08, 0x70, 0x14, 0x2a, 0x04, 0xd1, 0x08, 0x48, 0x01, 0x7a,
-0x01, 0x31, 0x01, 0x72, 0x07, 0xe0, 0x02, 0x2a, 0x05, 0xd0, 0x05, 0x2a,
-0x03, 0xd0, 0x06, 0x2a, 0x01, 0xd0, 0x15, 0x2a, 0x02, 0xd1, 0x18, 0x1c,
-0x80, 0xbc, 0x70, 0x47, 0x38, 0x1c, 0xfb, 0xe7, 0xe0, 0x82, 0x20, 0x40,
-0x00, 0xb5, 0x0f, 0x48, 0x01, 0x23, 0x1b, 0x06, 0x41, 0x69, 0x99, 0x43,
-0x1a, 0x09, 0x41, 0x61, 0xd1, 0x60, 0x00, 0x21, 0xa1, 0x22, 0x52, 0x03,
-0x91, 0x61, 0x19, 0x1c, 0x09, 0x4a, 0xc0, 0x46, 0x11, 0x60, 0x1b, 0x23,
-0xdb, 0x01, 0xc0, 0x18, 0x80, 0x69, 0x00, 0x28, 0x03, 0xd0, 0x02, 0xf0,
-0x61, 0xfe, 0x08, 0xbc, 0x18, 0x47, 0x04, 0x48, 0x41, 0x88, 0x01, 0x31,
-0x41, 0x80, 0xf8, 0xe7, 0x68, 0x0e, 0x00, 0x80, 0x00, 0x00, 0x00, 0xb0,
-0xe0, 0x82, 0x20, 0x40, 0x70, 0x47, 0x00, 0x00, 0xf0, 0xb5, 0x86, 0xb0,
-0x95, 0x4a, 0xd0, 0x68, 0xd7, 0x1d, 0x79, 0x37, 0x01, 0x28, 0x09, 0xd1,
-0x38, 0x89, 0x00, 0x28, 0x06, 0xd1, 0xd0, 0x6f, 0x02, 0x23, 0x01, 0x68,
-0x99, 0x43, 0x01, 0x60, 0x14, 0x20, 0x38, 0x81, 0x8e, 0x4c, 0x61, 0x6a,
-0x8e, 0x48, 0xc3, 0x6b, 0x59, 0x18, 0xc1, 0x63, 0xa0, 0x6a, 0x19, 0x23,
-0xdb, 0x01, 0xd4, 0x18, 0xa0, 0x62, 0x21, 0x6a, 0x09, 0x03, 0x09, 0x0b,
-0x81, 0x42, 0x05, 0xd1, 0x01, 0x20, 0x40, 0x04, 0x87, 0x49, 0xc0, 0x46,
-0x08, 0x60, 0xf3, 0xe0, 0xbb, 0x8a, 0x58, 0x1c, 0xb8, 0x82, 0x3d, 0x8b,
-0x01, 0x20, 0x00, 0x21, 0xab, 0x42, 0x04, 0xdb, 0xd3, 0x1d, 0x89, 0x33,
-0x58, 0x70, 0xb9, 0x82, 0xf9, 0x83, 0x33, 0x23, 0x9b, 0x01, 0xd3, 0x18,
-0x05, 0x93, 0x5b, 0x69, 0x0f, 0x2b, 0x73, 0xd2, 0x00, 0x21, 0x7c, 0x4f,
-0xc0, 0x46, 0x39, 0x61, 0x21, 0x6a, 0x8a, 0x68, 0x12, 0x04, 0x12, 0x0c,
-0x4b, 0x68, 0x1e, 0x0c, 0x36, 0x04, 0xfd, 0x1f, 0x09, 0x3d, 0x00, 0x2e,
-0x05, 0xd1, 0x3b, 0x2a, 0x03, 0xd3, 0x01, 0x23, 0xdb, 0x02, 0x9a, 0x42,
-0x01, 0xd9, 0xa8, 0x73, 0xc8, 0xe0, 0x01, 0x23, 0x9b, 0x07, 0x08, 0x31,
-0x19, 0x43, 0x09, 0x68, 0xc0, 0x46, 0x03, 0x91, 0x03, 0xa9, 0x09, 0x88,
-0x01, 0x31, 0x09, 0x04, 0x09, 0x0c, 0x79, 0x82, 0x49, 0x09, 0x05, 0x31,
-0x09, 0x06, 0x09, 0x0e, 0x69, 0x4e, 0xc0, 0x46, 0x02, 0x96, 0x69, 0x48,
-0x43, 0x6a, 0xc0, 0x46, 0x01, 0x93, 0x83, 0x6a, 0xc0, 0x46, 0x00, 0x93,
-0xc2, 0x1d, 0x11, 0x32, 0x80, 0x69, 0x00, 0x03, 0x00, 0x0b, 0x92, 0x68,
-0xb3, 0x07, 0x1a, 0x43, 0x12, 0x68, 0x90, 0x42, 0x01, 0xd1, 0x01, 0x20,
+0x39, 0x18, 0x72, 0x54, 0x01, 0x30, 0x00, 0x06, 0x00, 0x0e, 0x10, 0xa9,
+0x09, 0x78, 0x88, 0x42, 0xf6, 0xdb, 0x10, 0xa8, 0x00, 0x78, 0x38, 0x18,
+0x07, 0x06, 0x3f, 0x0e, 0xaf, 0x42, 0xe3, 0xdb, 0x68, 0x46, 0xe2, 0x1d,
+0x0d, 0x32, 0x00, 0x21, 0xab, 0x08, 0x5f, 0x1c, 0x08, 0xd0, 0x8b, 0x00,
+0xc4, 0x58, 0xc0, 0x46, 0xd4, 0x50, 0x01, 0x31, 0x09, 0x06, 0x09, 0x0e,
+0x8f, 0x42, 0xf6, 0xd8, 0x14, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47,
+0x90, 0xb4, 0x87, 0x1e, 0x00, 0x20, 0x89, 0x08, 0x4b, 0x1c, 0x08, 0xd0,
+0x81, 0x00, 0x54, 0x58, 0xc0, 0x46, 0x7c, 0x50, 0x01, 0x30, 0x00, 0x06,
+0x00, 0x0e, 0x83, 0x42, 0xf6, 0xd8, 0x90, 0xbc, 0x70, 0x47, 0x80, 0xb4,
+0x02, 0x78, 0xd2, 0x06, 0xd2, 0x0e, 0x00, 0x23, 0x01, 0x27, 0x01, 0x2a,
+0x01, 0xdc, 0x0f, 0x70, 0x11, 0xe0, 0x40, 0x78, 0xc0, 0x46, 0x08, 0x70,
+0x14, 0x2a, 0x04, 0xd1, 0x08, 0x48, 0x01, 0x7a, 0x01, 0x31, 0x01, 0x72,
+0x07, 0xe0, 0x02, 0x2a, 0x05, 0xd0, 0x05, 0x2a, 0x03, 0xd0, 0x06, 0x2a,
+0x01, 0xd0, 0x15, 0x2a, 0x02, 0xd1, 0x18, 0x1c, 0x80, 0xbc, 0x70, 0x47,
+0x38, 0x1c, 0xfb, 0xe7, 0xe0, 0x82, 0x20, 0x40, 0x00, 0xb5, 0x0f, 0x48,
+0x01, 0x23, 0x1b, 0x06, 0x41, 0x69, 0x99, 0x43, 0x1a, 0x09, 0x41, 0x61,
+0xd1, 0x60, 0x00, 0x21, 0xa1, 0x22, 0x52, 0x03, 0x91, 0x61, 0x19, 0x1c,
+0x09, 0x4a, 0xc0, 0x46, 0x11, 0x60, 0x1b, 0x23, 0xdb, 0x01, 0xc0, 0x18,
+0x80, 0x69, 0x00, 0x28, 0x03, 0xd0, 0x02, 0xf0, 0x61, 0xfe, 0x08, 0xbc,
+0x18, 0x47, 0x04, 0x48, 0x41, 0x88, 0x01, 0x31, 0x41, 0x80, 0xf8, 0xe7,
+0x68, 0x0e, 0x00, 0x80, 0x00, 0x00, 0x00, 0xb0, 0xe0, 0x82, 0x20, 0x40,
+0x70, 0x47, 0x00, 0x00, 0xf0, 0xb5, 0x86, 0xb0, 0x95, 0x4a, 0xd0, 0x68,
+0xd7, 0x1d, 0x79, 0x37, 0x01, 0x28, 0x09, 0xd1, 0x38, 0x89, 0x00, 0x28,
+0x06, 0xd1, 0xd0, 0x6f, 0x02, 0x23, 0x01, 0x68, 0x99, 0x43, 0x01, 0x60,
+0x14, 0x20, 0x38, 0x81, 0x8e, 0x4c, 0x61, 0x6a, 0x8e, 0x48, 0xc3, 0x6b,
+0x59, 0x18, 0xc1, 0x63, 0xa0, 0x6a, 0x19, 0x23, 0xdb, 0x01, 0xd4, 0x18,
+0xa0, 0x62, 0x21, 0x6a, 0x09, 0x03, 0x09, 0x0b, 0x81, 0x42, 0x05, 0xd1,
+0x01, 0x20, 0x40, 0x04, 0x87, 0x49, 0xc0, 0x46, 0x08, 0x60, 0xf3, 0xe0,
+0xbb, 0x8a, 0x58, 0x1c, 0xb8, 0x82, 0x3d, 0x8b, 0x01, 0x20, 0x00, 0x21,
+0xab, 0x42, 0x04, 0xdb, 0xd3, 0x1d, 0x89, 0x33, 0x58, 0x70, 0xb9, 0x82,
+0xf9, 0x83, 0x33, 0x23, 0x9b, 0x01, 0xd3, 0x18, 0x05, 0x93, 0x5b, 0x69,
+0x0f, 0x2b, 0x73, 0xd2, 0x00, 0x21, 0x7c, 0x4f, 0xc0, 0x46, 0x39, 0x61,
+0x21, 0x6a, 0x8a, 0x68, 0x12, 0x04, 0x12, 0x0c, 0x4b, 0x68, 0x1e, 0x0c,
+0x36, 0x04, 0xfd, 0x1f, 0x09, 0x3d, 0x00, 0x2e, 0x05, 0xd1, 0x3b, 0x2a,
+0x03, 0xd3, 0x01, 0x23, 0xdb, 0x02, 0x9a, 0x42, 0x01, 0xd9, 0xa8, 0x73,
+0xc8, 0xe0, 0x01, 0x23, 0x9b, 0x07, 0x08, 0x31, 0x19, 0x43, 0x09, 0x68,
+0xc0, 0x46, 0x03, 0x91, 0x03, 0xa9, 0x09, 0x88, 0x01, 0x31, 0x09, 0x04,
+0x09, 0x0c, 0x79, 0x82, 0x49, 0x09, 0x05, 0x31, 0x09, 0x06, 0x09, 0x0e,
+0x69, 0x4e, 0xc0, 0x46, 0x02, 0x96, 0x69, 0x48, 0x43, 0x6a, 0xc0, 0x46,
+0x01, 0x93, 0x83, 0x6a, 0xc0, 0x46, 0x00, 0x93, 0xc2, 0x1d, 0x11, 0x32,
+0x80, 0x69, 0x00, 0x03, 0x00, 0x0b, 0x92, 0x68, 0xb3, 0x07, 0x1a, 0x43,
+0x12, 0x68, 0x90, 0x42, 0x01, 0xd1, 0x01, 0x20,
0x0d, 0xe0, 0x90, 0x42, 0x05, 0xd9, 0x00, 0x9b, 0x18, 0x1a, 0x01, 0x9b,
-0xd2, 0x1a, 0x82, 0x18, 0x00, 0xe0, 0x12, 0x1a,
-0x01, 0x20, 0x09, 0x01, 0x91, 0x42, 0x00, 0xd3, 0x00, 0x20, 0x01, 0x28,
-0x65, 0xd1, 0x51, 0x49, 0x20, 0x69, 0x00, 0x28, 0x62, 0xd0, 0x05, 0x99,
-0x48, 0x69, 0x01, 0x30, 0x48, 0x61, 0x02, 0x20, 0x21, 0x6a, 0xc0, 0x46,
-0x08, 0x60, 0x00, 0xf0, 0xa7, 0xfc, 0x78, 0x63, 0xbe, 0x60, 0x49, 0x49,
-0x22, 0x6a, 0xa3, 0x6b, 0xd3, 0x18, 0x66, 0x6b, 0xb3, 0x42, 0x00, 0xd9,
-0x22, 0x6b, 0xc0, 0x46, 0xba, 0x62, 0xba, 0x6a, 0x0c, 0x32, 0xfa, 0x62,
-0x00, 0x22, 0xfa, 0x61, 0x03, 0xaa, 0x52, 0x88, 0xd2, 0x09, 0x03, 0xd3,
-0x01, 0x22, 0x00, 0xe0, 0x7b, 0xe0, 0x00, 0xe0, 0x00, 0x22, 0x7a, 0x60,
-0x7a, 0x68, 0xc0, 0x46, 0x02, 0x60, 0x78, 0x8a, 0x41, 0x4e, 0x60, 0x28,
-0x04, 0xdc, 0xb0, 0x83, 0x78, 0x8a, 0xc0, 0x46, 0xf0, 0x83, 0x08, 0xe0,
-0x60, 0x20, 0xb0, 0x83, 0x79, 0x8a, 0xf8, 0x6a, 0x42, 0x18, 0x63, 0x6b,
-0x9a, 0x42, 0x03, 0xd8, 0xf1, 0x83, 0x00, 0x22, 0x3a, 0x63, 0x05, 0xe0,
-0x21, 0x6b, 0xc0, 0x46, 0x39, 0x63, 0x61, 0x6b, 0x08, 0x1a, 0xf0, 0x83,
-0x2d, 0x49, 0x78, 0x6b, 0x42, 0x68, 0xc0, 0x46, 0xba, 0x60, 0x82, 0x68,
-0xc0, 0x46, 0xfa, 0x60, 0x02, 0x69, 0xc0, 0x46, 0x7a, 0x61, 0x40, 0x69,
-0xc0, 0x46, 0xb8, 0x61, 0x2e, 0x4b, 0xc8, 0x18, 0x04, 0x90, 0x00, 0xf0,
-0x37, 0xf9, 0x04, 0x98, 0x00, 0xf0, 0x88, 0xf8, 0x00, 0xf0, 0xf6, 0xfa,
-0x78, 0x8a, 0xf1, 0x8b, 0x88, 0x42, 0x04, 0xd1, 0xf9, 0x6a, 0x08, 0x18,
-0x04, 0xe0, 0x38, 0xe0, 0x32, 0xe0, 0x3a, 0x6b, 0x10, 0x18, 0x40, 0x1a,
-0x81, 0x07, 0x02, 0xd0, 0x80, 0x08, 0x80, 0x00, 0x04, 0x30, 0x61, 0x6b,
-0x09, 0x1a, 0xa2, 0x6b, 0x91, 0x42, 0x00, 0xd2, 0x20, 0x6b, 0xc0, 0x46,
-0x20, 0x62, 0xe8, 0x7b, 0x00, 0x28, 0x08, 0xd0, 0x00, 0x22, 0xea, 0x73,
-0x05, 0x99, 0x48, 0x69, 0x01, 0x38, 0x48, 0x61, 0x78, 0x6b, 0x00, 0xf0,
-0x73, 0xfa, 0x18, 0x48, 0x80, 0x6a, 0x80, 0x06, 0x80, 0x0e, 0x01, 0x28,
-0x0a, 0xd1, 0x20, 0x6a, 0x00, 0x03, 0x00, 0x0b, 0x0b, 0x4c, 0xa1, 0x6a,
-0x88, 0x42, 0x03, 0xd0, 0x06, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47,
-0x01, 0x20, 0x40, 0x04, 0x08, 0x49, 0xc0, 0x46, 0x08, 0x60, 0x06, 0xe0,
-0xe0, 0x68, 0x00, 0x28, 0x01, 0xd0, 0x00, 0xf0, 0xb5, 0xfa, 0x01, 0x20,
-0xa8, 0x73, 0xed, 0xe7, 0x68, 0x0e, 0x00, 0x80, 0x00, 0x40, 0x14, 0x40,
-0xa4, 0x2a, 0x00, 0x80, 0x00, 0x00, 0x00, 0xb0, 0x28, 0x1a, 0x00, 0x80,
-0x55, 0x55, 0x55, 0x55, 0xa8, 0x03, 0x00, 0x80, 0x68, 0x1a, 0x00, 0x80,
-0xc4, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, 0x80, 0xb5, 0x07, 0x1c,
-0x78, 0x6a, 0x40, 0x89, 0xff, 0x21, 0x01, 0x31, 0x01, 0x40, 0x10, 0x48,
-0x02, 0xd1, 0x81, 0x6c, 0x01, 0x31, 0x81, 0x64, 0x79, 0x6a, 0x49, 0x89,
-0x49, 0x0b, 0x02, 0xd2, 0x41, 0x6c, 0x01, 0x31, 0x41, 0x64, 0x0b, 0x48,
-0x41, 0x6a, 0x01, 0x31, 0x41, 0x62, 0x78, 0x6a, 0x39, 0x6b, 0xc0, 0x46,
-0x48, 0x62, 0x38, 0x6b, 0x00, 0xf0, 0xf8, 0xfb, 0x38, 0x1c, 0x00, 0xf0,
-0xb3, 0xf8, 0x01, 0x20, 0x04, 0x49, 0xc0, 0x46, 0xc8, 0x73, 0x80, 0xbc,
-0x08, 0xbc, 0x18, 0x47, 0xa4, 0x2a, 0x00, 0x80, 0xa0, 0x82, 0x20, 0x40,
-0x18, 0x1a, 0x00, 0x80, 0xf8, 0xb5, 0x07, 0x1c, 0x00, 0x22, 0xf9, 0x1d,
-0x61, 0x31, 0x0d, 0x1c, 0x78, 0x6a, 0xc0, 0x46, 0x00, 0x90, 0x40, 0x89,
+0xd2, 0x1a, 0x82, 0x18, 0x00, 0xe0, 0x12, 0x1a, 0x01, 0x20, 0x09, 0x01,
+0x91, 0x42, 0x00, 0xd3, 0x00, 0x20, 0x01, 0x28, 0x65, 0xd1, 0x51, 0x49,
+0x20, 0x69, 0x00, 0x28, 0x62, 0xd0, 0x05, 0x99, 0x48, 0x69, 0x01, 0x30,
+0x48, 0x61, 0x02, 0x20, 0x21, 0x6a, 0xc0, 0x46, 0x08, 0x60, 0x00, 0xf0,
+0xa7, 0xfc, 0x78, 0x63, 0xbe, 0x60, 0x49, 0x49, 0x22, 0x6a, 0xa3, 0x6b,
+0xd3, 0x18, 0x66, 0x6b, 0xb3, 0x42, 0x00, 0xd9, 0x22, 0x6b, 0xc0, 0x46,
+0xba, 0x62, 0xba, 0x6a, 0x0c, 0x32, 0xfa, 0x62, 0x00, 0x22, 0xfa, 0x61,
+0x03, 0xaa, 0x52, 0x88, 0xd2, 0x09, 0x03, 0xd3, 0x01, 0x22, 0x00, 0xe0,
+0x7b, 0xe0, 0x00, 0xe0, 0x00, 0x22, 0x7a, 0x60, 0x7a, 0x68, 0xc0, 0x46,
+0x02, 0x60, 0x78, 0x8a, 0x41, 0x4e, 0x60, 0x28, 0x04, 0xdc, 0xb0, 0x83,
+0x78, 0x8a, 0xc0, 0x46, 0xf0, 0x83, 0x08, 0xe0, 0x60, 0x20, 0xb0, 0x83,
+0x79, 0x8a, 0xf8, 0x6a, 0x42, 0x18, 0x63, 0x6b, 0x9a, 0x42, 0x03, 0xd8,
+0xf1, 0x83, 0x00, 0x22, 0x3a, 0x63, 0x05, 0xe0, 0x21, 0x6b, 0xc0, 0x46,
+0x39, 0x63, 0x61, 0x6b, 0x08, 0x1a, 0xf0, 0x83, 0x2d, 0x49, 0x78, 0x6b,
+0x42, 0x68, 0xc0, 0x46, 0xba, 0x60, 0x82, 0x68, 0xc0, 0x46, 0xfa, 0x60,
+0x02, 0x69, 0xc0, 0x46, 0x7a, 0x61, 0x40, 0x69, 0xc0, 0x46, 0xb8, 0x61,
+0x2e, 0x4b, 0xc8, 0x18, 0x04, 0x90, 0x00, 0xf0, 0x37, 0xf9, 0x04, 0x98,
+0x00, 0xf0, 0x88, 0xf8, 0x00, 0xf0, 0xf6, 0xfa, 0x78, 0x8a, 0xf1, 0x8b,
+0x88, 0x42, 0x04, 0xd1, 0xf9, 0x6a, 0x08, 0x18, 0x04, 0xe0, 0x38, 0xe0,
+0x32, 0xe0, 0x3a, 0x6b, 0x10, 0x18, 0x40, 0x1a, 0x81, 0x07, 0x02, 0xd0,
+0x80, 0x08, 0x80, 0x00, 0x04, 0x30, 0x61, 0x6b, 0x09, 0x1a, 0xa2, 0x6b,
+0x91, 0x42, 0x00, 0xd2, 0x20, 0x6b, 0xc0, 0x46, 0x20, 0x62, 0xe8, 0x7b,
+0x00, 0x28, 0x08, 0xd0, 0x00, 0x22, 0xea, 0x73, 0x05, 0x99, 0x48, 0x69,
+0x01, 0x38, 0x48, 0x61, 0x78, 0x6b, 0x00, 0xf0, 0x73, 0xfa, 0x18, 0x48,
+0x80, 0x6a, 0x80, 0x06, 0x80, 0x0e, 0x01, 0x28, 0x0a, 0xd1, 0x20, 0x6a,
+0x00, 0x03, 0x00, 0x0b, 0x0b, 0x4c, 0xa1, 0x6a, 0x88, 0x42, 0x03, 0xd0,
+0x06, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x01, 0x20, 0x40, 0x04,
+0x08, 0x49, 0xc0, 0x46, 0x08, 0x60, 0x06, 0xe0, 0xe0, 0x68, 0x00, 0x28,
+0x01, 0xd0, 0x00, 0xf0, 0xb5, 0xfa, 0x01, 0x20, 0xa8, 0x73, 0xed, 0xe7,
+0x68, 0x0e, 0x00, 0x80, 0x00, 0x40, 0x14, 0x40, 0xa4, 0x2a, 0x00, 0x80,
+0x00, 0x00, 0x00, 0xb0, 0x28, 0x1a, 0x00, 0x80, 0x55, 0x55, 0x55, 0x55,
+0xa8, 0x03, 0x00, 0x80, 0x68, 0x1a, 0x00, 0x80, 0xc4, 0x0b, 0x00, 0x00,
+0x00, 0x00, 0x10, 0x40, 0x80, 0xb5, 0x07, 0x1c, 0x78, 0x6a, 0x40, 0x89,
+0xff, 0x21, 0x01, 0x31, 0x01, 0x40, 0x10, 0x48, 0x02, 0xd1, 0x81, 0x6c,
+0x01, 0x31, 0x81, 0x64, 0x79, 0x6a, 0x49, 0x89, 0x49, 0x0b, 0x02, 0xd2,
+0x41, 0x6c, 0x01, 0x31, 0x41, 0x64, 0x0b, 0x48, 0x41, 0x6a, 0x01, 0x31,
+0x41, 0x62, 0x78, 0x6a, 0x39, 0x6b, 0xc0, 0x46, 0x48, 0x62, 0x38, 0x6b,
+0x00, 0xf0, 0xf8, 0xfb, 0x38, 0x1c, 0x00, 0xf0, 0xb3, 0xf8, 0x01, 0x20,
+0x04, 0x49, 0xc0, 0x46, 0xc8, 0x73, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47,
+0xa4, 0x2a, 0x00, 0x80, 0xa0, 0x82, 0x20, 0x40, 0x18, 0x1a, 0x00, 0x80,
+0xf8, 0xb5, 0x07, 0x1c, 0x00, 0x22, 0xf9, 0x1d, 0x61, 0x31, 0x0d, 0x1c,
+0x78, 0x6a, 0xc0, 0x46, 0x00, 0x90, 0x40, 0x89,
0x03, 0x0c, 0x01, 0xd2, 0x40, 0x0a, 0x03, 0xd2, 0x38, 0x1c, 0xff, 0xf7,
-0xc1, 0xff, 0x67, 0xe0, 0x35, 0x48, 0xc0, 0x6b,
-0x00, 0x09, 0x1f, 0xd3, 0x08, 0x78, 0x40, 0x08, 0x1c, 0xd2, 0x00, 0x20,
-0x43, 0x00, 0xcc, 0x5a, 0x31, 0x4e, 0x9e, 0x19, 0x33, 0x23, 0x9b, 0x01,
-0xf3, 0x18, 0x1b, 0x88, 0x9c, 0x42, 0x0e, 0xd0, 0xb8, 0x69, 0x39, 0x6b,
-0xc0, 0x46, 0x88, 0x61, 0xf8, 0x68, 0x39, 0x6b, 0xc0, 0x46, 0xc8, 0x60,
-0x38, 0x1c, 0x00, 0xf0, 0x27, 0xf9, 0x38, 0x1c, 0x00, 0xf0, 0x74, 0xf8,
-0x46, 0xe0, 0x01, 0x30, 0x03, 0x28, 0xe3, 0xdb, 0x02, 0x20, 0x43, 0x00,
-0x5c, 0x18, 0xe4, 0x88, 0x22, 0x4e, 0x9e, 0x19, 0x33, 0x23, 0x9b, 0x01,
-0xf3, 0x18, 0x1b, 0x88, 0x9c, 0x42, 0x03, 0xd1, 0x01, 0x23, 0x01, 0x38,
-0xd8, 0x42, 0xf0, 0xdc, 0x01, 0x23, 0xd8, 0x42, 0xc4, 0xd0, 0x1b, 0x4e,
-0x0b, 0x23, 0x1b, 0x02, 0xf0, 0x18, 0x40, 0x69, 0x00, 0x28, 0x24, 0xd0,
-0x7d, 0x63, 0x00, 0x98, 0x40, 0x89, 0x00, 0x0c, 0x1f, 0xd2, 0x00, 0x24,
-0x2d, 0x23, 0x9b, 0x01, 0xf0, 0x18, 0xc0, 0x6b, 0x35, 0x1c, 0x00, 0x28,
-0x17, 0xd0, 0xfe, 0x1d, 0x2d, 0x36, 0xa2, 0x00, 0x52, 0x19, 0x2d, 0x23,
-0x9b, 0x01, 0xd2, 0x18, 0xd2, 0x6b, 0x38, 0x1c, 0x31, 0x1c, 0x02, 0xf0,
-0x7b, 0xfc, 0x01, 0x28, 0x0e, 0xd0, 0x01, 0x34, 0xa0, 0x00, 0x40, 0x19,
-0x2d, 0x23, 0x9b, 0x01, 0xc0, 0x18, 0xc0, 0x6b, 0x00, 0x28, 0xea, 0xd1,
-0x01, 0xe0, 0x01, 0x2a, 0x02, 0xd0, 0x38, 0x1c, 0x00, 0xf0, 0x08, 0xf8,
-0xf8, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0xe8, 0x1a, 0x00, 0x80,
-0x68, 0x0e, 0x00, 0x80, 0x80, 0xb5, 0x07, 0x1c, 0xb8, 0x69, 0x39, 0x6b,
-0xc0, 0x46, 0x88, 0x61, 0xf8, 0x68, 0x39, 0x6b, 0xc0, 0x46, 0xc8, 0x60,
-0x78, 0x6a, 0x40, 0x89, 0x01, 0x0c, 0x0e, 0xd2, 0x40, 0x0a, 0x0c, 0xd3,
-0x38, 0x68, 0x40, 0x08, 0x02, 0xd3, 0x38, 0x1c, 0x02, 0xf0, 0x0c, 0xfc,
-0x38, 0x1c, 0x00, 0xf0, 0xbb, 0xf8, 0x38, 0x1c, 0x00, 0xf0, 0x08, 0xf8,
-0x02, 0xe0, 0x38, 0x1c, 0xff, 0xf7, 0x30, 0xff, 0x01, 0x20, 0x80, 0xbc,
-0x08, 0xbc, 0x18, 0x47, 0x01, 0x21, 0x00, 0x6b, 0x40, 0x6a, 0xc0, 0x46,
-0x01, 0x60, 0x70, 0x47, 0xb0, 0xb4, 0xc1, 0x1d, 0x39, 0x31, 0x09, 0x8b,
-0x89, 0x08, 0x09, 0x04, 0x09, 0x0c, 0x84, 0x6a, 0xc2, 0x1d, 0x61, 0x32,
-0x00, 0x20, 0x00, 0x29, 0x0c, 0xdd, 0x87, 0x00, 0x3d, 0x19, 0x01, 0x23,
-0x9b, 0x07, 0x2b, 0x43, 0x1b, 0x68, 0xc0, 0x46, 0xd3, 0x51, 0x01, 0x30,
-0x00, 0x04, 0x00, 0x0c, 0x88, 0x42, 0xf2, 0xdb, 0xb0, 0xbc, 0x70, 0x47,
-0xf0, 0xb5, 0xa0, 0xb0, 0x01, 0x23, 0x9b, 0x07, 0xc1, 0x1d, 0x21, 0x31,
-0x19, 0x43, 0x09, 0x68, 0xc0, 0x46, 0x0b, 0x91, 0xc1, 0x1d, 0x53, 0x31,
-0x19, 0x43, 0x1f, 0x91, 0x09, 0x68, 0x01, 0xaf, 0xfa, 0x1d, 0x39, 0x32,
-0x1e, 0x92, 0x17, 0xab, 0x59, 0x80, 0x3a, 0x49, 0x01, 0x23, 0x9b, 0x07,
-0x0a, 0x6a, 0x13, 0x43, 0xcc, 0x1d, 0x11, 0x34, 0x89, 0x69, 0x09, 0x03,
-0x09, 0x0b, 0x22, 0x69, 0xe5, 0x68, 0xc0, 0x46, 0x1d, 0x95, 0xfc, 0x1d,
-0x39, 0x34, 0x64, 0x8b, 0x64, 0x09, 0x05, 0x34, 0x24, 0x06, 0x24, 0x0e,
-0x1c, 0x94, 0x56, 0x1a, 0x1b, 0x96, 0x1c, 0x9c, 0x2e, 0x4a, 0xc0, 0x46,
-0x00, 0x92, 0x01, 0x26, 0x1d, 0x9d, 0x1a, 0x68, 0x91, 0x42, 0x01, 0xd1,
-0x32, 0x1c, 0x0b, 0xe0, 0x91, 0x42, 0x03, 0xd9, 0x52, 0x1b, 0x1b, 0x9e,
-0xb5, 0x18, 0x00, 0xe0, 0x55, 0x1a, 0x01, 0x22, 0x24, 0x01, 0xac, 0x42,
+0xc1, 0xff, 0x67, 0xe0, 0x35, 0x48, 0xc0, 0x6b, 0x00, 0x09, 0x1f, 0xd3,
+0x08, 0x78, 0x40, 0x08, 0x1c, 0xd2, 0x00, 0x20, 0x43, 0x00, 0xcc, 0x5a,
+0x31, 0x4e, 0x9e, 0x19, 0x33, 0x23, 0x9b, 0x01, 0xf3, 0x18, 0x1b, 0x88,
+0x9c, 0x42, 0x0e, 0xd0, 0xb8, 0x69, 0x39, 0x6b, 0xc0, 0x46, 0x88, 0x61,
+0xf8, 0x68, 0x39, 0x6b, 0xc0, 0x46, 0xc8, 0x60, 0x38, 0x1c, 0x00, 0xf0,
+0x27, 0xf9, 0x38, 0x1c, 0x00, 0xf0, 0x74, 0xf8, 0x46, 0xe0, 0x01, 0x30,
+0x03, 0x28, 0xe3, 0xdb, 0x02, 0x20, 0x43, 0x00, 0x5c, 0x18, 0xe4, 0x88,
+0x22, 0x4e, 0x9e, 0x19, 0x33, 0x23, 0x9b, 0x01, 0xf3, 0x18, 0x1b, 0x88,
+0x9c, 0x42, 0x03, 0xd1, 0x01, 0x23, 0x01, 0x38, 0xd8, 0x42, 0xf0, 0xdc,
+0x01, 0x23, 0xd8, 0x42, 0xc4, 0xd0, 0x1b, 0x4e, 0x0b, 0x23, 0x1b, 0x02,
+0xf0, 0x18, 0x40, 0x69, 0x00, 0x28, 0x24, 0xd0, 0x7d, 0x63, 0x00, 0x98,
+0x40, 0x89, 0x00, 0x0c, 0x1f, 0xd2, 0x00, 0x24, 0x2d, 0x23, 0x9b, 0x01,
+0xf0, 0x18, 0xc0, 0x6b, 0x35, 0x1c, 0x00, 0x28, 0x17, 0xd0, 0xfe, 0x1d,
+0x2d, 0x36, 0xa2, 0x00, 0x52, 0x19, 0x2d, 0x23, 0x9b, 0x01, 0xd2, 0x18,
+0xd2, 0x6b, 0x38, 0x1c, 0x31, 0x1c, 0x02, 0xf0, 0x7b, 0xfc, 0x01, 0x28,
+0x0e, 0xd0, 0x01, 0x34, 0xa0, 0x00, 0x40, 0x19, 0x2d, 0x23, 0x9b, 0x01,
+0xc0, 0x18, 0xc0, 0x6b, 0x00, 0x28, 0xea, 0xd1, 0x01, 0xe0, 0x01, 0x2a,
+0x02, 0xd0, 0x38, 0x1c, 0x00, 0xf0, 0x08, 0xf8, 0xf8, 0xbc, 0x08, 0xbc,
+0x18, 0x47, 0x00, 0x00, 0xe8, 0x1a, 0x00, 0x80, 0x68, 0x0e, 0x00, 0x80,
+0x80, 0xb5, 0x07, 0x1c, 0xb8, 0x69, 0x39, 0x6b, 0xc0, 0x46, 0x88, 0x61,
+0xf8, 0x68, 0x39, 0x6b, 0xc0, 0x46, 0xc8, 0x60, 0x78, 0x6a, 0x40, 0x89,
+0x01, 0x0c, 0x0e, 0xd2, 0x40, 0x0a, 0x0c, 0xd3, 0x38, 0x68, 0x40, 0x08,
+0x02, 0xd3, 0x38, 0x1c, 0x02, 0xf0, 0x0c, 0xfc, 0x38, 0x1c, 0x00, 0xf0,
+0xbb, 0xf8, 0x38, 0x1c, 0x00, 0xf0, 0x08, 0xf8, 0x02, 0xe0, 0x38, 0x1c,
+0xff, 0xf7, 0x30, 0xff, 0x01, 0x20, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47,
+0x01, 0x21, 0x00, 0x6b, 0x40, 0x6a, 0xc0, 0x46, 0x01, 0x60, 0x70, 0x47,
+0xb0, 0xb4, 0xc1, 0x1d, 0x39, 0x31, 0x09, 0x8b, 0x89, 0x08, 0x09, 0x04,
+0x09, 0x0c, 0x84, 0x6a, 0xc2, 0x1d, 0x61, 0x32, 0x00, 0x20, 0x00, 0x29,
+0x0c, 0xdd, 0x87, 0x00, 0x3d, 0x19, 0x01, 0x23, 0x9b, 0x07, 0x2b, 0x43,
+0x1b, 0x68, 0xc0, 0x46, 0xd3, 0x51, 0x01, 0x30, 0x00, 0x04, 0x00, 0x0c,
+0x88, 0x42, 0xf2, 0xdb, 0xb0, 0xbc, 0x70, 0x47, 0xf0, 0xb5, 0xa0, 0xb0,
+0x01, 0x23, 0x9b, 0x07, 0xc1, 0x1d, 0x21, 0x31, 0x19, 0x43, 0x09, 0x68,
+0xc0, 0x46, 0x0b, 0x91, 0xc1, 0x1d, 0x53, 0x31, 0x19, 0x43, 0x1f, 0x91,
+0x09, 0x68, 0x01, 0xaf, 0xfa, 0x1d, 0x39, 0x32, 0x1e, 0x92, 0x17, 0xab,
+0x59, 0x80, 0x3a, 0x49, 0x01, 0x23, 0x9b, 0x07, 0x0a, 0x6a, 0x13, 0x43,
+0xcc, 0x1d, 0x11, 0x34, 0x89, 0x69, 0x09, 0x03, 0x09, 0x0b, 0x22, 0x69,
+0xe5, 0x68, 0xc0, 0x46, 0x1d, 0x95, 0xfc, 0x1d, 0x39, 0x34, 0x64, 0x8b,
+0x64, 0x09, 0x05, 0x34, 0x24, 0x06, 0x24, 0x0e, 0x1c, 0x94, 0x56, 0x1a,
+0x1b, 0x96, 0x1c, 0x9c, 0x2e, 0x4a, 0xc0, 0x46, 0x00, 0x92, 0x01, 0x26,
+0x1d, 0x9d, 0x1a, 0x68, 0x91, 0x42, 0x01, 0xd1, 0x32, 0x1c, 0x0b, 0xe0,
+0x91, 0x42, 0x03, 0xd9, 0x52, 0x1b, 0x1b, 0x9e, 0xb5, 0x18, 0x00, 0xe0,
+0x55, 0x1a, 0x01, 0x22, 0x24, 0x01, 0xac, 0x42,
0x00, 0xd3, 0x00, 0x22, 0x01, 0x2a, 0xe6, 0xd1, 0x91, 0x07, 0x01, 0x43,
-0x09, 0x68, 0xc0, 0x46, 0x39, 0x60, 0x93, 0x07,
-0x01, 0x1d, 0x19, 0x43, 0x09, 0x68, 0xc0, 0x46, 0x79, 0x60, 0xc1, 0x1d,
-0x01, 0x31, 0x19, 0x43, 0x09, 0x68, 0xc0, 0x46, 0xb9, 0x60, 0x1f, 0x99,
-0x09, 0x68, 0x1e, 0x9a, 0xc0, 0x46, 0x51, 0x83, 0xc1, 0x1d, 0x1d, 0x31,
-0x19, 0x43, 0x09, 0x68, 0xc0, 0x46, 0x38, 0x63, 0x79, 0x62, 0xc1, 0x1d,
-0x11, 0x31, 0x19, 0x43, 0x09, 0x68, 0xc0, 0x46, 0xb9, 0x61, 0xc1, 0x1d,
-0x05, 0x31, 0x19, 0x43, 0x09, 0x68, 0xc0, 0x46, 0xf9, 0x60, 0xc1, 0x1d,
-0x17, 0x31, 0x19, 0x43, 0x09, 0x68, 0xc0, 0x46, 0xf9, 0x83, 0x0e, 0x30,
-0x18, 0x43, 0x00, 0x68, 0xc0, 0x46, 0xf8, 0x81, 0x38, 0x68, 0x40, 0x08,
-0x02, 0xd3, 0x38, 0x1c, 0x02, 0xf0, 0x5c, 0xfb, 0x38, 0x1c, 0x00, 0xf0,
-0x0b, 0xf8, 0x38, 0x1c, 0xff, 0xf7, 0x58, 0xff, 0x20, 0xb0, 0xf0, 0xbc,
-0x08, 0xbc, 0x18, 0x47, 0xa8, 0x03, 0x00, 0x80, 0x55, 0x55, 0x55, 0x55,
-0xf8, 0xb5, 0x07, 0x1c, 0xf8, 0x1d, 0x39, 0x30, 0x41, 0x8b, 0x39, 0x4a,
-0x91, 0x42, 0x00, 0xdd, 0x42, 0x83, 0x42, 0x8b, 0xc0, 0x46, 0x00, 0x92,
-0x01, 0x20, 0x3a, 0x1d, 0x06, 0xca, 0xbb, 0x6a, 0x02, 0xf0, 0x0e, 0xff,
-0x33, 0x4a, 0xc0, 0x46, 0x00, 0x92, 0x33, 0x4e, 0x30, 0x6a, 0x33, 0x4c,
-0xe1, 0x6d, 0x41, 0x18, 0x38, 0x6b, 0xc3, 0x1d, 0x05, 0x33, 0x01, 0x20,
-0x72, 0x6a, 0x02, 0xf0, 0xfb, 0xfe, 0xe0, 0x6d, 0x18, 0x30, 0x00, 0x25,
-0xb1, 0x6a, 0x81, 0x42, 0x01, 0xd8, 0xe5, 0x65, 0x00, 0xe0, 0xe0, 0x65,
-0x2f, 0x23, 0x9b, 0x01, 0x20, 0x1c, 0xe1, 0x6d, 0xe4, 0x18, 0x22, 0x68,
-0x92, 0x00, 0x27, 0x4b, 0xc0, 0x46, 0x99, 0x50, 0x26, 0x48, 0xc1, 0x6b,
-0x4a, 0x08, 0x05, 0xd3, 0x49, 0x08, 0x49, 0x00, 0xc1, 0x63, 0x01, 0x20,
-0x01, 0xf0, 0xd6, 0xff, 0x22, 0x4a, 0x1f, 0x48, 0xc1, 0x1d, 0x89, 0x31,
-0x0b, 0x78, 0x00, 0x2b, 0x02, 0xd0, 0x49, 0x78, 0x00, 0x29, 0x00, 0xd1,
-0x1e, 0x4a, 0xc0, 0x46, 0x00, 0x92, 0x20, 0x68, 0x80, 0x00, 0x19, 0x4b,
-0xc3, 0x18, 0x05, 0xce, 0xc1, 0x1d, 0x11, 0x31, 0x01, 0x20, 0x02, 0xf0,
-0xc7, 0xfe, 0x14, 0x48, 0x21, 0x68, 0x01, 0x31, 0x21, 0x60, 0x17, 0x29,
-0x00, 0xd3, 0x25, 0x60, 0x39, 0x6b, 0xc0, 0x46, 0x0d, 0x65, 0x79, 0x6a,
-0x3a, 0x6b, 0xc0, 0x46, 0x51, 0x62, 0x33, 0x23, 0x9b, 0x01, 0xc0, 0x18,
-0x81, 0x68, 0x00, 0x29, 0x03, 0xd1, 0x39, 0x6b, 0xc0, 0x46, 0x81, 0x60,
-0x04, 0xe0, 0x39, 0x6b, 0xc2, 0x68, 0xc0, 0x46, 0x11, 0x65, 0x39, 0x6b,
-0xc0, 0x46, 0xc1, 0x60, 0xf8, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00,
-0xea, 0x05, 0x00, 0x00, 0x18, 0x00, 0x14, 0x02, 0x7c, 0x29, 0x00, 0x80,
-0x68, 0x0e, 0x00, 0x80, 0x44, 0x82, 0x20, 0x40, 0xe8, 0x0e, 0x00, 0x80,
-0x04, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x03, 0xf0, 0xb5, 0x11, 0x4e,
-0xff, 0x25, 0x01, 0x35, 0x10, 0x4f, 0xc0, 0x46, 0x35, 0x60, 0x78, 0x69,
-0x01, 0x38, 0x78, 0x61, 0xbc, 0x68, 0x00, 0x2c, 0x10, 0xd0, 0x20, 0x6d,
-0xc0, 0x46, 0xb8, 0x60, 0x20, 0x1c, 0x00, 0xf0, 0x21, 0xf8, 0x20, 0x1c,
-0x00, 0xf0, 0x04, 0xfa, 0x08, 0x48, 0x80, 0x6a, 0x00, 0x0c, 0x00, 0x07,
-0xe9, 0xd1, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x05, 0x48, 0xc1, 0x79,
-0x01, 0x31, 0xc1, 0x71, 0xf7, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0,
-0x28, 0x1b, 0x00, 0x80, 0x00, 0x00, 0x10, 0x40, 0xa0, 0x82, 0x20, 0x40,
+0x09, 0x68, 0xc0, 0x46, 0x39, 0x60, 0x93, 0x07, 0x01, 0x1d, 0x19, 0x43,
+0x09, 0x68, 0xc0, 0x46, 0x79, 0x60, 0xc1, 0x1d, 0x01, 0x31, 0x19, 0x43,
+0x09, 0x68, 0xc0, 0x46, 0xb9, 0x60, 0x1f, 0x99, 0x09, 0x68, 0x1e, 0x9a,
+0xc0, 0x46, 0x51, 0x83, 0xc1, 0x1d, 0x1d, 0x31, 0x19, 0x43, 0x09, 0x68,
+0xc0, 0x46, 0x38, 0x63, 0x79, 0x62, 0xc1, 0x1d, 0x11, 0x31, 0x19, 0x43,
+0x09, 0x68, 0xc0, 0x46, 0xb9, 0x61, 0xc1, 0x1d, 0x05, 0x31, 0x19, 0x43,
+0x09, 0x68, 0xc0, 0x46, 0xf9, 0x60, 0xc1, 0x1d, 0x17, 0x31, 0x19, 0x43,
+0x09, 0x68, 0xc0, 0x46, 0xf9, 0x83, 0x0e, 0x30, 0x18, 0x43, 0x00, 0x68,
+0xc0, 0x46, 0xf8, 0x81, 0x38, 0x68, 0x40, 0x08, 0x02, 0xd3, 0x38, 0x1c,
+0x02, 0xf0, 0x5c, 0xfb, 0x38, 0x1c, 0x00, 0xf0, 0x0b, 0xf8, 0x38, 0x1c,
+0xff, 0xf7, 0x58, 0xff, 0x20, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47,
+0xa8, 0x03, 0x00, 0x80, 0x55, 0x55, 0x55, 0x55, 0xf8, 0xb5, 0x07, 0x1c,
+0xf8, 0x1d, 0x39, 0x30, 0x41, 0x8b, 0x39, 0x4a, 0x91, 0x42, 0x00, 0xdd,
+0x42, 0x83, 0x42, 0x8b, 0xc0, 0x46, 0x00, 0x92, 0x01, 0x20, 0x3a, 0x1d,
+0x06, 0xca, 0xbb, 0x6a, 0x02, 0xf0, 0x0e, 0xff, 0x33, 0x4a, 0xc0, 0x46,
+0x00, 0x92, 0x33, 0x4e, 0x30, 0x6a, 0x33, 0x4c, 0xe1, 0x6d, 0x41, 0x18,
+0x38, 0x6b, 0xc3, 0x1d, 0x05, 0x33, 0x01, 0x20, 0x72, 0x6a, 0x02, 0xf0,
+0xfb, 0xfe, 0xe0, 0x6d, 0x18, 0x30, 0x00, 0x25, 0xb1, 0x6a, 0x81, 0x42,
+0x01, 0xd8, 0xe5, 0x65, 0x00, 0xe0, 0xe0, 0x65, 0x2f, 0x23, 0x9b, 0x01,
+0x20, 0x1c, 0xe1, 0x6d, 0xe4, 0x18, 0x22, 0x68, 0x92, 0x00, 0x27, 0x4b,
+0xc0, 0x46, 0x99, 0x50, 0x26, 0x48, 0xc1, 0x6b, 0x4a, 0x08, 0x05, 0xd3,
+0x49, 0x08, 0x49, 0x00, 0xc1, 0x63, 0x01, 0x20, 0x01, 0xf0, 0xd6, 0xff,
+0x22, 0x4a, 0x1f, 0x48, 0xc1, 0x1d, 0x89, 0x31, 0x0b, 0x78, 0x00, 0x2b,
+0x02, 0xd0, 0x49, 0x78, 0x00, 0x29, 0x00, 0xd1, 0x1e, 0x4a, 0xc0, 0x46,
+0x00, 0x92, 0x20, 0x68, 0x80, 0x00, 0x19, 0x4b, 0xc3, 0x18, 0x05, 0xce,
+0xc1, 0x1d, 0x11, 0x31, 0x01, 0x20, 0x02, 0xf0, 0xc7, 0xfe, 0x14, 0x48,
+0x21, 0x68, 0x01, 0x31, 0x21, 0x60, 0x17, 0x29, 0x00, 0xd3, 0x25, 0x60,
+0x39, 0x6b, 0xc0, 0x46, 0x0d, 0x65, 0x79, 0x6a, 0x3a, 0x6b, 0xc0, 0x46,
+0x51, 0x62, 0x33, 0x23, 0x9b, 0x01, 0xc0, 0x18, 0x81, 0x68, 0x00, 0x29,
+0x03, 0xd1, 0x39, 0x6b, 0xc0, 0x46, 0x81, 0x60, 0x04, 0xe0, 0x39, 0x6b,
+0xc2, 0x68, 0xc0, 0x46, 0x11, 0x65, 0x39, 0x6b, 0xc0, 0x46, 0xc1, 0x60,
+0xf8, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0xea, 0x05, 0x00, 0x00,
+0x18, 0x00, 0x14, 0x02, 0x7c, 0x29, 0x00, 0x80, 0x68, 0x0e, 0x00, 0x80,
+0x44, 0x82, 0x20, 0x40, 0xe8, 0x0e, 0x00, 0x80, 0x04, 0x00, 0x00, 0x02,
+0x04, 0x00, 0x00, 0x03, 0xf0, 0xb5, 0x11, 0x4e, 0xff, 0x25, 0x01, 0x35,
+0x10, 0x4f, 0xc0, 0x46, 0x35, 0x60, 0x78, 0x69, 0x01, 0x38, 0x78, 0x61,
+0xbc, 0x68, 0x00, 0x2c, 0x10, 0xd0, 0x20, 0x6d, 0xc0, 0x46, 0xb8, 0x60,
+0x20, 0x1c, 0x00, 0xf0, 0x21, 0xf8, 0x20, 0x1c, 0x00, 0xf0, 0x04, 0xfa,
+0x08, 0x48, 0x80, 0x6a, 0x00, 0x0c, 0x00, 0x07, 0xe9, 0xd1, 0xf0, 0xbc,
+0x08, 0xbc, 0x18, 0x47, 0x05, 0x48, 0xc1, 0x79, 0x01, 0x31, 0xc1, 0x71,
+0xf7, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x28, 0x1b, 0x00, 0x80,
+0x00, 0x00, 0x10, 0x40, 0xa0, 0x82, 0x20, 0x40,
0x01, 0x20, 0x80, 0x03, 0x01, 0x49, 0xc0, 0x46, 0x08, 0x60, 0x70, 0x47,
-0x00, 0x00, 0x00, 0xb0, 0x90, 0xb5, 0x07, 0x1c,
-0x38, 0x68, 0xc0, 0x08, 0x09, 0xd3, 0x1d, 0x48, 0x01, 0x6a, 0x01, 0x39,
-0x01, 0x62, 0x20, 0x30, 0x00, 0x79, 0x00, 0x28, 0x01, 0xd0, 0xfe, 0xf7,
-0xf3, 0xfd, 0x01, 0x23, 0x9b, 0x07, 0xf8, 0x1d, 0x1d, 0x30, 0x18, 0x43,
-0x00, 0x68, 0x16, 0x4c, 0x61, 0x6a, 0x81, 0x42, 0x21, 0xd1, 0x01, 0x1c,
-0x19, 0x43, 0x09, 0x68, 0x09, 0x04, 0x09, 0x0c, 0x01, 0x29, 0x1a, 0xd1,
-0x00, 0xf0, 0x22, 0xf8, 0x60, 0x62, 0x60, 0x6a, 0x21, 0x6a, 0x88, 0x42,
-0x05, 0xd0, 0x01, 0x21, 0x89, 0x07, 0x01, 0x43, 0x09, 0x68, 0x09, 0x04,
-0xf2, 0xd0, 0x51, 0x21, 0x89, 0x03, 0x62, 0x6a, 0x23, 0x6b, 0x9a, 0x42,
-0x02, 0xd1, 0x60, 0x6b, 0xa2, 0x6b, 0x80, 0x1a, 0x04, 0x38, 0xc8, 0x60,
-0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x20, 0x79, 0x6a, 0xc0, 0x46,
-0x08, 0x60, 0xf7, 0xe7, 0x6c, 0x06, 0x00, 0x80, 0xe8, 0x1a, 0x00, 0x80,
-0x01, 0x23, 0x9b, 0x07, 0xc1, 0x1d, 0x01, 0x31, 0x19, 0x43, 0x09, 0x68,
-0x09, 0x04, 0x09, 0x0c, 0x08, 0x18, 0x0d, 0x30, 0x81, 0x07, 0x02, 0xd0,
-0x80, 0x08, 0x80, 0x00, 0x04, 0x30, 0x04, 0x49, 0x8a, 0x6b, 0x12, 0x18,
-0x4b, 0x6b, 0x9a, 0x42, 0x00, 0xd9, 0x08, 0x6b, 0x70, 0x47, 0x00, 0x00,
-0xe8, 0x1a, 0x00, 0x80, 0x00, 0xb5, 0x04, 0x48, 0xc0, 0x68, 0x10, 0x28,
-0x01, 0xd3, 0x00, 0xf0, 0x05, 0xf8, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00,
-0xe8, 0x1a, 0x00, 0x80, 0x88, 0xb5, 0x0c, 0x4f, 0x38, 0x79, 0x00, 0x28,
-0x11, 0xd1, 0x0b, 0x49, 0x10, 0x20, 0x02, 0xf0, 0xf5, 0xfd, 0x00, 0x28,
-0x0b, 0xd0, 0x01, 0x20, 0x38, 0x71, 0x08, 0x4a, 0xc0, 0x46, 0x00, 0x92,
-0x07, 0x48, 0x42, 0x68, 0x07, 0x4b, 0x01, 0x68, 0x00, 0x20, 0x02, 0xf0,
-0xdf, 0xfd, 0x88, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xf8, 0x1a, 0x00, 0x80,
-0xe1, 0x2c, 0xff, 0xff, 0x10, 0x00, 0x35, 0x02, 0x7c, 0x29, 0x00, 0x80,
-0x44, 0x80, 0x20, 0x40, 0x90, 0xb5, 0x01, 0x20, 0x40, 0x02, 0x10, 0x49,
-0xc0, 0x46, 0x08, 0x60, 0x0f, 0x4f, 0x10, 0x21, 0xf8, 0x1d, 0x3d, 0x30,
-0x02, 0xf0, 0x4c, 0xfc, 0x19, 0x23, 0xdb, 0x01, 0xfc, 0x18, 0xe0, 0x68,
-0x00, 0x28, 0x01, 0xd0, 0x00, 0xf0, 0x14, 0xf8, 0x00, 0x20, 0xc9, 0x23,
-0x1b, 0x01, 0xf9, 0x18, 0x08, 0x71, 0xe0, 0x68, 0x10, 0x28, 0x04, 0xd3,
-0x01, 0x20, 0xbb, 0x23, 0x1b, 0x01, 0xf9, 0x18, 0x48, 0x73, 0x90, 0xbc,
-0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x00, 0xb0, 0x68, 0x0e, 0x00, 0x80,
-0xf8, 0xb5, 0x37, 0x48, 0x19, 0x23, 0xdb, 0x01, 0xc1, 0x18, 0xc9, 0x68,
-0x35, 0x4d, 0x10, 0x29, 0x00, 0xd9, 0x10, 0x21, 0x69, 0x62, 0x32, 0x48,
-0xc1, 0x6c, 0x00, 0x6e, 0x81, 0x42, 0x07, 0xd9, 0x08, 0x1a, 0x07, 0x09,
-0x00, 0x24, 0x68, 0x6a, 0xb8, 0x42, 0x12, 0xd2, 0x07, 0x1c, 0x10, 0xe0,
-0x81, 0x42, 0x2a, 0xd2, 0x2c, 0x4a, 0x52, 0x6b, 0x10, 0x1a, 0x07, 0x09,
-0x68, 0x6a, 0xb8, 0x42, 0x05, 0xd9, 0x0c, 0x09, 0x39, 0x19, 0x88, 0x42,
-0x03, 0xd2, 0xc4, 0x1b, 0x01, 0xe0, 0x00, 0x24, 0x07, 0x1c, 0x3e, 0x19,
-0x30, 0x01, 0x25, 0x49, 0x02, 0xf0, 0x84, 0xfd, 0x00, 0x28, 0x3d, 0xd0,
-0x23, 0x48, 0x00, 0x2c, 0x1a, 0xd1, 0x1e, 0x49, 0x3a, 0x01, 0x6f, 0x62,
-0x09, 0x6e, 0x8c, 0x18, 0x1d, 0x4d, 0x6b, 0x6b, 0xa3, 0x42, 0x00, 0xd8,
-0xe4, 0x1a, 0x1e, 0x4b, 0x1a, 0x43, 0x00, 0x92, 0xea, 0x6a, 0x51, 0x18,
+0x00, 0x00, 0x00, 0xb0, 0x90, 0xb5, 0x07, 0x1c, 0x38, 0x68, 0xc0, 0x08,
+0x09, 0xd3, 0x1d, 0x48, 0x01, 0x6a, 0x01, 0x39, 0x01, 0x62, 0x20, 0x30,
+0x00, 0x79, 0x00, 0x28, 0x01, 0xd0, 0xfe, 0xf7, 0xe9, 0xfd, 0x01, 0x23,
+0x9b, 0x07, 0xf8, 0x1d, 0x1d, 0x30, 0x18, 0x43, 0x00, 0x68, 0x16, 0x4c,
+0x61, 0x6a, 0x81, 0x42, 0x21, 0xd1, 0x01, 0x1c, 0x19, 0x43, 0x09, 0x68,
+0x09, 0x04, 0x09, 0x0c, 0x01, 0x29, 0x1a, 0xd1, 0x00, 0xf0, 0x22, 0xf8,
+0x60, 0x62, 0x60, 0x6a, 0x21, 0x6a, 0x88, 0x42, 0x05, 0xd0, 0x01, 0x21,
+0x89, 0x07, 0x01, 0x43, 0x09, 0x68, 0x09, 0x04, 0xf2, 0xd0, 0x51, 0x21,
+0x89, 0x03, 0x62, 0x6a, 0x23, 0x6b, 0x9a, 0x42, 0x02, 0xd1, 0x60, 0x6b,
+0xa2, 0x6b, 0x80, 0x1a, 0x04, 0x38, 0xc8, 0x60, 0x90, 0xbc, 0x08, 0xbc,
+0x18, 0x47, 0x00, 0x20, 0x79, 0x6a, 0xc0, 0x46, 0x08, 0x60, 0xf7, 0xe7,
+0x6c, 0x06, 0x00, 0x80, 0xe8, 0x1a, 0x00, 0x80, 0x01, 0x23, 0x9b, 0x07,
+0xc1, 0x1d, 0x01, 0x31, 0x19, 0x43, 0x09, 0x68, 0x09, 0x04, 0x09, 0x0c,
+0x08, 0x18, 0x0d, 0x30, 0x81, 0x07, 0x02, 0xd0, 0x80, 0x08, 0x80, 0x00,
+0x04, 0x30, 0x04, 0x49, 0x8a, 0x6b, 0x12, 0x18, 0x4b, 0x6b, 0x9a, 0x42,
+0x00, 0xd9, 0x08, 0x6b, 0x70, 0x47, 0x00, 0x00, 0xe8, 0x1a, 0x00, 0x80,
+0x00, 0xb5, 0x04, 0x48, 0xc0, 0x68, 0x10, 0x28, 0x01, 0xd3, 0x00, 0xf0,
+0x05, 0xf8, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0xe8, 0x1a, 0x00, 0x80,
+0x88, 0xb5, 0x0c, 0x4f, 0x38, 0x79, 0x00, 0x28, 0x11, 0xd1, 0x0b, 0x49,
+0x10, 0x20, 0x02, 0xf0, 0xf5, 0xfd, 0x00, 0x28, 0x0b, 0xd0, 0x01, 0x20,
+0x38, 0x71, 0x08, 0x4a, 0xc0, 0x46, 0x00, 0x92, 0x07, 0x48, 0x42, 0x68,
+0x07, 0x4b, 0x01, 0x68, 0x00, 0x20, 0x02, 0xf0, 0xdf, 0xfd, 0x88, 0xbc,
+0x08, 0xbc, 0x18, 0x47, 0xf8, 0x1a, 0x00, 0x80, 0xf5, 0x2c, 0xff, 0xff,
+0x10, 0x00, 0x35, 0x02, 0x7c, 0x29, 0x00, 0x80, 0x44, 0x80, 0x20, 0x40,
+0x90, 0xb5, 0x01, 0x20, 0x40, 0x02, 0x10, 0x49, 0xc0, 0x46, 0x08, 0x60,
+0x0f, 0x4f, 0x10, 0x21, 0xf8, 0x1d, 0x3d, 0x30, 0x02, 0xf0, 0x4c, 0xfc,
+0x19, 0x23, 0xdb, 0x01, 0xfc, 0x18, 0xe0, 0x68, 0x00, 0x28, 0x01, 0xd0,
+0x00, 0xf0, 0x14, 0xf8, 0x00, 0x20, 0xc9, 0x23, 0x1b, 0x01, 0xf9, 0x18,
+0x08, 0x71, 0xe0, 0x68, 0x10, 0x28, 0x04, 0xd3, 0x01, 0x20, 0xbb, 0x23,
+0x1b, 0x01, 0xf9, 0x18, 0x48, 0x73, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47,
+0x00, 0x00, 0x00, 0xb0, 0x68, 0x0e, 0x00, 0x80, 0xf8, 0xb5, 0x37, 0x48,
+0x19, 0x23, 0xdb, 0x01, 0xc1, 0x18, 0xc9, 0x68, 0x35, 0x4d, 0x10, 0x29,
+0x00, 0xd9, 0x10, 0x21, 0x69, 0x62, 0x32, 0x48, 0xc1, 0x6c, 0x00, 0x6e,
+0x81, 0x42, 0x07, 0xd9, 0x08, 0x1a, 0x07, 0x09, 0x00, 0x24, 0x68, 0x6a,
+0xb8, 0x42, 0x12, 0xd2, 0x07, 0x1c, 0x10, 0xe0, 0x81, 0x42, 0x2a, 0xd2,
+0x2c, 0x4a, 0x52, 0x6b, 0x10, 0x1a, 0x07, 0x09, 0x68, 0x6a, 0xb8, 0x42,
+0x05, 0xd9, 0x0c, 0x09, 0x39, 0x19, 0x88, 0x42, 0x03, 0xd2, 0xc4, 0x1b,
+0x01, 0xe0, 0x00, 0x24, 0x07, 0x1c, 0x3e, 0x19, 0x30, 0x01, 0x25, 0x49,
+0x02, 0xf0, 0x84, 0xfd, 0x00, 0x28, 0x3d, 0xd0, 0x23, 0x48, 0x00, 0x2c,
+0x1a, 0xd1, 0x1e, 0x49, 0x3a, 0x01, 0x6f, 0x62, 0x09, 0x6e, 0x8c, 0x18,
+0x1d, 0x4d, 0x6b, 0x6b, 0xa3, 0x42, 0x00, 0xd8, 0xe4, 0x1a, 0x1e, 0x4b,
+0x1a, 0x43, 0x00, 0x92, 0xea, 0x6a, 0x51, 0x18,
0x2a, 0x6b, 0x03, 0x1c, 0x20, 0xe0, 0x1b, 0x48, 0x01, 0x6b, 0x01, 0x31,
-0x01, 0x63, 0x00, 0x20, 0x68, 0x62, 0xf8, 0xbc,
-0x08, 0xbc, 0x18, 0x47, 0x10, 0x49, 0x24, 0x01, 0x3f, 0x01, 0x11, 0x22,
-0x52, 0x05, 0x3a, 0x43, 0x6e, 0x62, 0x00, 0x92, 0x0e, 0x4d, 0xea, 0x6a,
-0x09, 0x6e, 0x51, 0x18, 0x03, 0x1c, 0x06, 0x1c, 0x00, 0x20, 0x2a, 0x6b,
-0x02, 0xf0, 0x4a, 0xfd, 0x0c, 0x4a, 0x22, 0x43, 0x00, 0x92, 0xbb, 0x19,
-0xe9, 0x6a, 0x2a, 0x6b, 0x00, 0x20, 0x02, 0xf0, 0x41, 0xfd, 0x03, 0x48,
-0xc0, 0x46, 0x04, 0x66, 0x00, 0xf0, 0x10, 0xf8, 0x01, 0x20, 0xda, 0xe7,
-0x68, 0x0e, 0x00, 0x80, 0x28, 0x1b, 0x00, 0x80, 0x7c, 0x29, 0x00, 0x80,
-0x49, 0x2e, 0xff, 0xff, 0x44, 0x80, 0x20, 0x40, 0x00, 0x00, 0x36, 0x02,
-0xa0, 0x82, 0x20, 0x40, 0x04, 0x48, 0x01, 0x6e, 0x04, 0x4a, 0x80, 0x30,
-0xd1, 0x60, 0x02, 0x23, 0xc1, 0x6b, 0x19, 0x43, 0xc1, 0x63, 0x70, 0x47,
-0x68, 0x0e, 0x00, 0x80, 0x3c, 0xef, 0x20, 0x40, 0xf0, 0xb5, 0x84, 0xb0,
-0x01, 0x20, 0x80, 0x02, 0x1c, 0x49, 0xc0, 0x46, 0x08, 0x60, 0x00, 0x27,
-0x1b, 0x4e, 0x33, 0x23, 0x9b, 0x01, 0xf5, 0x18, 0x68, 0x6a, 0x00, 0x28,
-0x1d, 0xd9, 0x19, 0x4c, 0x68, 0x46, 0x10, 0x21, 0x02, 0xf0, 0x90, 0xfb,
-0x68, 0x46, 0x00, 0xf0, 0x33, 0xf8, 0x00, 0x28, 0x04, 0xd0, 0x15, 0x49,
-0x48, 0x69, 0x01, 0x30, 0x48, 0x61, 0x0a, 0xe0, 0x13, 0x49, 0x60, 0x7b,
-0x01, 0x30, 0x60, 0x73, 0x88, 0x79, 0x01, 0x30, 0x88, 0x71, 0x11, 0x48,
-0x00, 0x68, 0x02, 0xf0, 0x65, 0xf9, 0x68, 0x6a, 0x01, 0x37, 0xb8, 0x42,
-0xe2, 0xd8, 0xbb, 0x23, 0x1b, 0x01, 0xf0, 0x18, 0x81, 0x7b, 0x00, 0x29,
-0x03, 0xd0, 0x00, 0x21, 0x81, 0x73, 0xff, 0xf7, 0x05, 0xfb, 0xff, 0xf7,
-0xe3, 0xfe, 0x04, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00,
-0x00, 0x00, 0x00, 0xb0, 0x68, 0x0e, 0x00, 0x80, 0xb0, 0x82, 0x20, 0x40,
-0x08, 0x83, 0x20, 0x40, 0xa0, 0x82, 0x20, 0x40, 0x58, 0x04, 0x00, 0x80,
-0x90, 0xb4, 0x17, 0x4f, 0x19, 0x23, 0xdb, 0x01, 0xf9, 0x18, 0x00, 0x22,
-0xcb, 0x68, 0x00, 0x2b, 0x23, 0xd0, 0x01, 0x3b, 0xcb, 0x60, 0x33, 0x23,
-0x9b, 0x01, 0xff, 0x18, 0xbb, 0x69, 0x1c, 0x6d, 0xc0, 0x46, 0xbc, 0x61,
-0x04, 0x68, 0xc0, 0x46, 0x5c, 0x60, 0x44, 0x68, 0xc0, 0x46, 0x9c, 0x60,
-0x84, 0x68, 0xc0, 0x46, 0x1c, 0x61, 0xc0, 0x68, 0xc0, 0x46, 0x58, 0x61,
-0x1a, 0x65, 0x08, 0x69, 0x42, 0x1c, 0x0a, 0x61, 0x00, 0x28, 0x03, 0xd0,
-0x38, 0x6a, 0xc0, 0x46, 0x03, 0x65, 0x00, 0xe0, 0xfb, 0x61, 0x3b, 0x62,
-0x18, 0x1c, 0x90, 0xbc, 0x70, 0x47, 0x10, 0x1c, 0xfb, 0xe7, 0x00, 0x00,
-0x68, 0x0e, 0x00, 0x80, 0x0a, 0x4a, 0x33, 0x23, 0x9b, 0x01, 0xd1, 0x18,
-0xc8, 0x69, 0x19, 0x23, 0xdb, 0x01, 0xd2, 0x18, 0x13, 0x69, 0x00, 0x2b,
-0x06, 0xd0, 0x01, 0x3b, 0x13, 0x61, 0xca, 0x69, 0x12, 0x6d, 0xc0, 0x46,
-0xca, 0x61, 0x70, 0x47, 0x00, 0x21, 0x11, 0x61, 0xfb, 0xe7, 0x00, 0x00,
-0x68, 0x0e, 0x00, 0x80, 0x06, 0x4a, 0x11, 0x69, 0x4b, 0x1c, 0x13, 0x61,
-0x40, 0x32, 0x00, 0x29, 0x01, 0xd0, 0xd1, 0x69, 0x00, 0xe0, 0x00, 0x21,
-0x01, 0x65, 0xd0, 0x61, 0x70, 0x47, 0x00, 0x00, 0xe8, 0x1a, 0x00, 0x80,
-0x06, 0x4a, 0xd1, 0x68, 0x4b, 0x1c, 0xd3, 0x60, 0x40, 0x32, 0x00, 0x29,
-0x01, 0xd0, 0x91, 0x69, 0x00, 0xe0, 0x00, 0x21, 0x01, 0x65, 0x90, 0x61,
-0x70, 0x47, 0x00, 0x00, 0xe8, 0x1a, 0x00, 0x80, 0x90, 0xb4, 0x00, 0x21,
+0x01, 0x63, 0x00, 0x20, 0x68, 0x62, 0xf8, 0xbc, 0x08, 0xbc, 0x18, 0x47,
+0x10, 0x49, 0x24, 0x01, 0x3f, 0x01, 0x11, 0x22, 0x52, 0x05, 0x3a, 0x43,
+0x6e, 0x62, 0x00, 0x92, 0x0e, 0x4d, 0xea, 0x6a, 0x09, 0x6e, 0x51, 0x18,
+0x03, 0x1c, 0x06, 0x1c, 0x00, 0x20, 0x2a, 0x6b, 0x02, 0xf0, 0x4a, 0xfd,
+0x0c, 0x4a, 0x22, 0x43, 0x00, 0x92, 0xbb, 0x19, 0xe9, 0x6a, 0x2a, 0x6b,
+0x00, 0x20, 0x02, 0xf0, 0x41, 0xfd, 0x03, 0x48, 0xc0, 0x46, 0x04, 0x66,
+0x00, 0xf0, 0x10, 0xf8, 0x01, 0x20, 0xda, 0xe7, 0x68, 0x0e, 0x00, 0x80,
+0x28, 0x1b, 0x00, 0x80, 0x7c, 0x29, 0x00, 0x80, 0x5d, 0x2e, 0xff, 0xff,
+0x44, 0x80, 0x20, 0x40, 0x00, 0x00, 0x36, 0x02, 0xa0, 0x82, 0x20, 0x40,
+0x04, 0x48, 0x01, 0x6e, 0x04, 0x4a, 0x80, 0x30, 0xd1, 0x60, 0x02, 0x23,
+0xc1, 0x6b, 0x19, 0x43, 0xc1, 0x63, 0x70, 0x47, 0x68, 0x0e, 0x00, 0x80,
+0x90, 0xee, 0x20, 0x40, 0xf0, 0xb5, 0x84, 0xb0, 0x01, 0x20, 0x80, 0x02,
+0x1c, 0x49, 0xc0, 0x46, 0x08, 0x60, 0x00, 0x27, 0x1b, 0x4e, 0x33, 0x23,
+0x9b, 0x01, 0xf5, 0x18, 0x68, 0x6a, 0x00, 0x28, 0x1d, 0xd9, 0x19, 0x4c,
+0x68, 0x46, 0x10, 0x21, 0x02, 0xf0, 0x90, 0xfb, 0x68, 0x46, 0x00, 0xf0,
+0x33, 0xf8, 0x00, 0x28, 0x04, 0xd0, 0x15, 0x49, 0x48, 0x69, 0x01, 0x30,
+0x48, 0x61, 0x0a, 0xe0, 0x13, 0x49, 0x60, 0x7b, 0x01, 0x30, 0x60, 0x73,
+0x88, 0x79, 0x01, 0x30, 0x88, 0x71, 0x11, 0x48, 0x00, 0x68, 0x02, 0xf0,
+0x65, 0xf9, 0x68, 0x6a, 0x01, 0x37, 0xb8, 0x42, 0xe2, 0xd8, 0xbb, 0x23,
+0x1b, 0x01, 0xf0, 0x18, 0x81, 0x7b, 0x00, 0x29, 0x03, 0xd0, 0x00, 0x21,
+0x81, 0x73, 0xff, 0xf7, 0x05, 0xfb, 0xff, 0xf7, 0xe3, 0xfe, 0x04, 0xb0,
+0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0,
+0x68, 0x0e, 0x00, 0x80, 0xb0, 0x82, 0x20, 0x40, 0x08, 0x83, 0x20, 0x40,
+0xa0, 0x82, 0x20, 0x40, 0x58, 0x04, 0x00, 0x80, 0x90, 0xb4, 0x17, 0x4f,
+0x19, 0x23, 0xdb, 0x01, 0xf9, 0x18, 0x00, 0x22, 0xcb, 0x68, 0x00, 0x2b,
+0x23, 0xd0, 0x01, 0x3b, 0xcb, 0x60, 0x33, 0x23, 0x9b, 0x01, 0xff, 0x18,
+0xbb, 0x69, 0x1c, 0x6d, 0xc0, 0x46, 0xbc, 0x61, 0x04, 0x68, 0xc0, 0x46,
+0x5c, 0x60, 0x44, 0x68, 0xc0, 0x46, 0x9c, 0x60, 0x84, 0x68, 0xc0, 0x46,
+0x1c, 0x61, 0xc0, 0x68, 0xc0, 0x46, 0x58, 0x61, 0x1a, 0x65, 0x08, 0x69,
+0x42, 0x1c, 0x0a, 0x61, 0x00, 0x28, 0x03, 0xd0, 0x38, 0x6a, 0xc0, 0x46,
+0x03, 0x65, 0x00, 0xe0, 0xfb, 0x61, 0x3b, 0x62, 0x18, 0x1c, 0x90, 0xbc,
+0x70, 0x47, 0x10, 0x1c, 0xfb, 0xe7, 0x00, 0x00, 0x68, 0x0e, 0x00, 0x80,
+0x0a, 0x4a, 0x33, 0x23, 0x9b, 0x01, 0xd1, 0x18, 0xc8, 0x69, 0x19, 0x23,
+0xdb, 0x01, 0xd2, 0x18, 0x13, 0x69, 0x00, 0x2b, 0x06, 0xd0, 0x01, 0x3b,
+0x13, 0x61, 0xca, 0x69, 0x12, 0x6d, 0xc0, 0x46, 0xca, 0x61, 0x70, 0x47,
+0x00, 0x21, 0x11, 0x61, 0xfb, 0xe7, 0x00, 0x00, 0x68, 0x0e, 0x00, 0x80,
+0x06, 0x4a, 0x11, 0x69, 0x4b, 0x1c, 0x13, 0x61, 0x40, 0x32, 0x00, 0x29,
+0x01, 0xd0, 0xd1, 0x69, 0x00, 0xe0, 0x00, 0x21, 0x01, 0x65, 0xd0, 0x61,
+0x70, 0x47, 0x00, 0x00, 0xe8, 0x1a, 0x00, 0x80, 0x06, 0x4a, 0xd1, 0x68,
+0x4b, 0x1c, 0xd3, 0x60, 0x40, 0x32, 0x00, 0x29, 0x01, 0xd0, 0x91, 0x69,
+0x00, 0xe0, 0x00, 0x21, 0x01, 0x65, 0x90, 0x61, 0x70, 0x47, 0x00, 0x00,
+0xe8, 0x1a, 0x00, 0x80, 0x90, 0xb4, 0x00, 0x21,
0x0f, 0x4a, 0x97, 0x89, 0x92, 0x6a, 0x4b, 0x00, 0x1b, 0x18, 0x9b, 0x8a,
-0x00, 0x2b, 0x12, 0xd0, 0xbb, 0x42, 0x10, 0xdc,
-0x1c, 0x1c, 0x58, 0x23, 0x63, 0x43, 0xd3, 0x18, 0xdc, 0x1f, 0x49, 0x3c,
-0x01, 0x23, 0x9b, 0x07, 0x23, 0x43, 0x1b, 0x68, 0x1b, 0x06, 0x1b, 0x0e,
-0x03, 0x2b, 0x02, 0xd0, 0x00, 0x20, 0x90, 0xbc, 0x70, 0x47, 0x01, 0x31,
-0x04, 0x29, 0xe4, 0xd3, 0x01, 0x20, 0xf8, 0xe7, 0x4c, 0x2a, 0x00, 0x80,
-0xf7, 0xb5, 0x86, 0xb0, 0x3d, 0x4a, 0x07, 0x1c, 0xd1, 0x69, 0x8f, 0x40,
-0x03, 0x1c, 0x14, 0x6a, 0xe3, 0x40, 0x5f, 0x40, 0x07, 0x9e, 0x8e, 0x40,
-0x77, 0x40, 0xcf, 0x40, 0x94, 0x69, 0xc0, 0x46, 0x05, 0x94, 0x03, 0x1c,
-0xa3, 0x40, 0x00, 0x25, 0x14, 0x69, 0xc0, 0x46, 0x04, 0x94, 0x00, 0x2c,
-0x5d, 0xd9, 0x1c, 0x1c, 0x32, 0x4e, 0x26, 0x43, 0x94, 0x69, 0xe6, 0x40,
-0x33, 0x1c, 0x03, 0x96, 0x53, 0x6a, 0xc0, 0x46, 0x02, 0x93, 0xd2, 0x6a,
-0xc0, 0x46, 0x01, 0x92, 0xbb, 0x00, 0x02, 0x9a, 0xd2, 0x58, 0x13, 0x1c,
-0x05, 0x9c, 0xe3, 0x40, 0x03, 0x9c, 0xa3, 0x42, 0x3e, 0xd1, 0x8a, 0x40,
-0xca, 0x40, 0x14, 0x1c, 0x63, 0x00, 0x1b, 0x19, 0x5b, 0x01, 0x01, 0x9a,
-0xd2, 0x18, 0x01, 0x23, 0x9b, 0x07, 0xd6, 0x1d, 0x01, 0x36, 0x33, 0x43,
-0x1b, 0x68, 0x1b, 0x06, 0x1b, 0x0e, 0x03, 0x2b, 0x2c, 0xd1, 0x01, 0x23,
-0x9b, 0x07, 0xd6, 0x1d, 0x51, 0x36, 0x33, 0x43, 0x1b, 0x68, 0x07, 0x9e,
-0x1e, 0x40, 0x00, 0x96, 0x01, 0x23, 0x9b, 0x07, 0xd6, 0x1d, 0x49, 0x36,
-0x33, 0x43, 0x1b, 0x68, 0x83, 0x42, 0x1b, 0xd1, 0x01, 0x23, 0x9b, 0x07,
-0xd6, 0x1d, 0x4d, 0x36, 0x33, 0x43, 0x1b, 0x68, 0x00, 0x9e, 0xb3, 0x42,
-0x12, 0xd1, 0x01, 0x23, 0x9b, 0x07, 0x1a, 0x43, 0x12, 0x68, 0x12, 0x04,
-0x12, 0x0c, 0x08, 0x9b, 0x32, 0x2b, 0x04, 0xd1, 0x02, 0x2a, 0x07, 0xd1,
-0x20, 0x04, 0x00, 0x14, 0x0f, 0xe0, 0x08, 0x9b, 0x33, 0x2b, 0x01, 0xd1,
-0x01, 0x2a, 0xf7, 0xd0, 0x04, 0x9a, 0x01, 0x37, 0x97, 0x42, 0x00, 0xd3,
-0x00, 0x27, 0x04, 0x9a, 0x01, 0x35, 0xaa, 0x42, 0xae, 0xd8, 0x00, 0x20,
-0xc0, 0x43, 0x09, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00,
-0x4c, 0x2a, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0xf0, 0xb5, 0x27, 0x4d,
-0x68, 0x69, 0x00, 0x28, 0x06, 0xd0, 0x26, 0x48, 0x00, 0x68, 0x02, 0xf0,
-0x2b, 0xf8, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x23, 0x4c, 0x00, 0x26,
-0xa0, 0x68, 0x23, 0x4f, 0x00, 0x28, 0x16, 0xd0, 0x0f, 0xe0, 0x28, 0x6a,
-0x02, 0x28, 0x02, 0xd3, 0x01, 0x20, 0x38, 0x71, 0x0f, 0xe0, 0xa6, 0x60,
-0xfd, 0xf7, 0xe8, 0xfe, 0x00, 0x28, 0xea, 0xd1, 0x28, 0x6a, 0x02, 0x28,
-0x01, 0xd3, 0x01, 0x20, 0x38, 0x71, 0xe8, 0x68, 0x00, 0x28, 0x02, 0xd0,
-0x38, 0x79, 0x00, 0x28, 0xe9, 0xd0, 0x68, 0x68, 0x00, 0x28, 0x1b, 0xd0,
-0x01, 0x20, 0xa0, 0x60, 0xfe, 0xf7, 0xbc, 0xfb, 0x00, 0x28, 0xd6, 0xd1,
-0x68, 0x68, 0x00, 0x28, 0xf6, 0xd1, 0x11, 0xe0, 0x00, 0x28, 0xd0, 0xd1,
-0x28, 0x6a, 0x02, 0x28, 0x02, 0xd3, 0x01, 0x20, 0x38, 0x71, 0xca, 0xe7,
-0xa6, 0x60, 0xfd, 0xf7, 0xc3, 0xfe, 0x00, 0x28, 0xc5, 0xd1, 0x28, 0x6a,
-0x02, 0x28, 0x01, 0xd3, 0x01, 0x20, 0x38, 0x71, 0xe8, 0x68, 0x00, 0x28,
-0xbd, 0xd0, 0x38, 0x79, 0x00, 0x28, 0xe7, 0xd0, 0xb9, 0xe7, 0x00, 0x00,
-0x6c, 0x06, 0x00, 0x80, 0x5c, 0x04, 0x00, 0x80, 0x4c, 0x2a, 0x00, 0x80,
-0x8c, 0x06, 0x00, 0x80, 0x70, 0x47, 0x00, 0x00, 0x70, 0x47, 0x00, 0x00,
+0x00, 0x2b, 0x12, 0xd0, 0xbb, 0x42, 0x10, 0xdc, 0x1c, 0x1c, 0x58, 0x23,
+0x63, 0x43, 0xd3, 0x18, 0xdc, 0x1f, 0x49, 0x3c, 0x01, 0x23, 0x9b, 0x07,
+0x23, 0x43, 0x1b, 0x68, 0x1b, 0x06, 0x1b, 0x0e, 0x03, 0x2b, 0x02, 0xd0,
+0x00, 0x20, 0x90, 0xbc, 0x70, 0x47, 0x01, 0x31, 0x04, 0x29, 0xe4, 0xd3,
+0x01, 0x20, 0xf8, 0xe7, 0x4c, 0x2a, 0x00, 0x80, 0xf7, 0xb5, 0x86, 0xb0,
+0x3d, 0x4a, 0x07, 0x1c, 0xd1, 0x69, 0x8f, 0x40, 0x03, 0x1c, 0x14, 0x6a,
+0xe3, 0x40, 0x5f, 0x40, 0x07, 0x9e, 0x8e, 0x40, 0x77, 0x40, 0xcf, 0x40,
+0x94, 0x69, 0xc0, 0x46, 0x05, 0x94, 0x03, 0x1c, 0xa3, 0x40, 0x00, 0x25,
+0x14, 0x69, 0xc0, 0x46, 0x04, 0x94, 0x00, 0x2c, 0x5d, 0xd9, 0x1c, 0x1c,
+0x32, 0x4e, 0x26, 0x43, 0x94, 0x69, 0xe6, 0x40, 0x33, 0x1c, 0x03, 0x96,
+0x53, 0x6a, 0xc0, 0x46, 0x02, 0x93, 0xd2, 0x6a, 0xc0, 0x46, 0x01, 0x92,
+0xbb, 0x00, 0x02, 0x9a, 0xd2, 0x58, 0x13, 0x1c, 0x05, 0x9c, 0xe3, 0x40,
+0x03, 0x9c, 0xa3, 0x42, 0x3e, 0xd1, 0x8a, 0x40, 0xca, 0x40, 0x14, 0x1c,
+0x63, 0x00, 0x1b, 0x19, 0x5b, 0x01, 0x01, 0x9a, 0xd2, 0x18, 0x01, 0x23,
+0x9b, 0x07, 0xd6, 0x1d, 0x01, 0x36, 0x33, 0x43, 0x1b, 0x68, 0x1b, 0x06,
+0x1b, 0x0e, 0x03, 0x2b, 0x2c, 0xd1, 0x01, 0x23, 0x9b, 0x07, 0xd6, 0x1d,
+0x51, 0x36, 0x33, 0x43, 0x1b, 0x68, 0x07, 0x9e, 0x1e, 0x40, 0x00, 0x96,
+0x01, 0x23, 0x9b, 0x07, 0xd6, 0x1d, 0x49, 0x36, 0x33, 0x43, 0x1b, 0x68,
+0x83, 0x42, 0x1b, 0xd1, 0x01, 0x23, 0x9b, 0x07, 0xd6, 0x1d, 0x4d, 0x36,
+0x33, 0x43, 0x1b, 0x68, 0x00, 0x9e, 0xb3, 0x42, 0x12, 0xd1, 0x01, 0x23,
+0x9b, 0x07, 0x1a, 0x43, 0x12, 0x68, 0x12, 0x04, 0x12, 0x0c, 0x08, 0x9b,
+0x32, 0x2b, 0x04, 0xd1, 0x02, 0x2a, 0x07, 0xd1, 0x20, 0x04, 0x00, 0x14,
+0x0f, 0xe0, 0x08, 0x9b, 0x33, 0x2b, 0x01, 0xd1, 0x01, 0x2a, 0xf7, 0xd0,
+0x04, 0x9a, 0x01, 0x37, 0x97, 0x42, 0x00, 0xd3, 0x00, 0x27, 0x04, 0x9a,
+0x01, 0x35, 0xaa, 0x42, 0xae, 0xd8, 0x00, 0x20, 0xc0, 0x43, 0x09, 0xb0,
+0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x4c, 0x2a, 0x00, 0x80,
+0x00, 0x00, 0x00, 0x80, 0xf0, 0xb5, 0x27, 0x4d, 0x68, 0x69, 0x00, 0x28,
+0x06, 0xd0, 0x26, 0x48, 0x00, 0x68, 0x02, 0xf0, 0x2b, 0xf8, 0xf0, 0xbc,
+0x08, 0xbc, 0x18, 0x47, 0x23, 0x4c, 0x00, 0x26, 0xa0, 0x68, 0x23, 0x4f,
+0x00, 0x28, 0x16, 0xd0, 0x0f, 0xe0, 0x28, 0x6a, 0x02, 0x28, 0x02, 0xd3,
+0x01, 0x20, 0x38, 0x71, 0x0f, 0xe0, 0xa6, 0x60, 0xfd, 0xf7, 0xde, 0xfe,
+0x00, 0x28, 0xea, 0xd1, 0x28, 0x6a, 0x02, 0x28, 0x01, 0xd3, 0x01, 0x20,
+0x38, 0x71, 0xe8, 0x68, 0x00, 0x28, 0x02, 0xd0, 0x38, 0x79, 0x00, 0x28,
+0xe9, 0xd0, 0x68, 0x68, 0x00, 0x28, 0x1b, 0xd0, 0x01, 0x20, 0xa0, 0x60,
+0xfe, 0xf7, 0xbc, 0xfb, 0x00, 0x28, 0xd6, 0xd1, 0x68, 0x68, 0x00, 0x28,
+0xf6, 0xd1, 0x11, 0xe0, 0x00, 0x28, 0xd0, 0xd1, 0x28, 0x6a, 0x02, 0x28,
+0x02, 0xd3, 0x01, 0x20, 0x38, 0x71, 0xca, 0xe7, 0xa6, 0x60, 0xfd, 0xf7,
+0xb9, 0xfe, 0x00, 0x28, 0xc5, 0xd1, 0x28, 0x6a, 0x02, 0x28, 0x01, 0xd3,
+0x01, 0x20, 0x38, 0x71, 0xe8, 0x68, 0x00, 0x28, 0xbd, 0xd0, 0x38, 0x79,
+0x00, 0x28, 0xe7, 0xd0, 0xb9, 0xe7, 0x00, 0x00, 0x6c, 0x06, 0x00, 0x80,
+0x5c, 0x04, 0x00, 0x80, 0x4c, 0x2a, 0x00, 0x80, 0x8c, 0x06, 0x00, 0x80,
+0x70, 0x47, 0x00, 0x00, 0x70, 0x47, 0x00, 0x00,
0x70, 0x47, 0x00, 0x00, 0x90, 0xb5, 0x40, 0x20, 0x1d, 0x49, 0xc0, 0x46,
-0x08, 0x60, 0x01, 0xf0, 0x9d, 0xfc, 0x03, 0x23,
-0x1b, 0x07, 0x41, 0x68, 0x19, 0x40, 0x0c, 0x0f, 0x61, 0x01, 0x09, 0x1b,
-0x89, 0x00, 0x18, 0x4a, 0x8f, 0x18, 0x01, 0x21, 0x39, 0x80, 0x81, 0x6a,
-0xc0, 0x46, 0x79, 0x65, 0x41, 0x6a, 0xc0, 0x46, 0x79, 0x67, 0xb9, 0x6c,
-0xfa, 0x6c, 0x89, 0x18, 0xb9, 0x64, 0x00, 0x21, 0xf9, 0x64, 0xba, 0x6b,
-0x3b, 0x6d, 0xd2, 0x18, 0xba, 0x63, 0x39, 0x65, 0x42, 0x6a, 0x20, 0x32,
-0x51, 0x71, 0x79, 0x6d, 0x7a, 0x6f, 0xd2, 0x6d, 0xc0, 0x46, 0x11, 0x60,
-0xfc, 0xf7, 0xd4, 0xff, 0x20, 0x01, 0x09, 0x49, 0x40, 0x18, 0x19, 0x23,
-0xdb, 0x01, 0xc0, 0x18, 0x41, 0x6b, 0x01, 0x39, 0x41, 0x63, 0x78, 0x6f,
-0x01, 0xf0, 0xc6, 0xfb, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00,
-0x00, 0x00, 0x00, 0xb0, 0x5c, 0x2b, 0x00, 0x80, 0xa0, 0x1c, 0x00, 0x80,
-0xf0, 0xb5, 0x40, 0x20, 0x12, 0x49, 0xc0, 0x46, 0x08, 0x60, 0x01, 0xf0,
-0x59, 0xfc, 0x07, 0x1c, 0x40, 0x68, 0x03, 0x23, 0x1b, 0x07, 0x18, 0x40,
-0x06, 0x0f, 0x70, 0x01, 0x80, 0x1b, 0x80, 0x00, 0x0c, 0x49, 0x44, 0x18,
-0xb8, 0x6a, 0xc0, 0x46, 0x60, 0x65, 0x78, 0x6a, 0xc0, 0x46, 0x60, 0x67,
-0x80, 0x6f, 0x05, 0x1d, 0xe5, 0x63, 0xb9, 0x69, 0x28, 0x1c, 0x02, 0xf0,
-0x89, 0xf9, 0x38, 0x1c, 0x21, 0x1c, 0x32, 0x1c, 0x2b, 0x1c, 0x00, 0xf0,
-0x20, 0xf8, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x00, 0xb0,
-0x5c, 0x2b, 0x00, 0x80, 0xf0, 0xb5, 0x4b, 0x6f, 0x9b, 0x6f, 0x1f, 0x1d,
-0xcf, 0x63, 0x05, 0x68, 0x00, 0x23, 0x84, 0x69, 0xa4, 0x08, 0x08, 0xd0,
-0x9c, 0x00, 0x2e, 0x59, 0xc0, 0x46, 0x3e, 0x51, 0x84, 0x69, 0xa4, 0x08,
-0x01, 0x33, 0x9c, 0x42, 0xf6, 0xd8, 0x3b, 0x1c, 0x00, 0xf0, 0x03, 0xf8,
-0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xff, 0xb5, 0x81, 0xb0, 0x04, 0x1c,
-0x1d, 0x1c, 0x0f, 0x1c, 0x46, 0x48, 0x01, 0x69, 0x01, 0x31, 0x01, 0x61,
-0xf9, 0x1d, 0x51, 0x31, 0xbd, 0x65, 0x00, 0x91, 0x20, 0x1c, 0xfd, 0xf7,
-0x67, 0xfc, 0xf8, 0x6d, 0x40, 0x09, 0x36, 0xd2, 0xb8, 0x6d, 0x06, 0x7b,
-0x43, 0x7b, 0x1b, 0x02, 0x1e, 0x43, 0x17, 0x21, 0x49, 0x02, 0x01, 0x73,
-0x0b, 0x0a, 0x43, 0x73, 0x00, 0x99, 0x20, 0x1c, 0xfd, 0xf7, 0x56, 0xfc,
-0xb8, 0x6d, 0xc0, 0x46, 0x06, 0x73, 0x33, 0x0a, 0x43, 0x73, 0xf8, 0x6d,
-0x40, 0x09, 0x20, 0xd2, 0x60, 0x68, 0x01, 0x04, 0x09, 0x0c, 0x03, 0x98,
-0x01, 0xf0, 0xcc, 0xfc, 0x60, 0x68, 0x32, 0x4b, 0x18, 0x43, 0x60, 0x60,
-0x20, 0x1c, 0x01, 0xf0, 0x35, 0xfd, 0x00, 0x25, 0x7d, 0x60, 0xbd, 0x60,
-0x3d, 0x64, 0x7d, 0x64, 0x20, 0x1c, 0xfc, 0xf7, 0x3b, 0xff, 0x38, 0x88,
-0x40, 0x23, 0x18, 0x43, 0x38, 0x80, 0x7d, 0x62, 0x29, 0x48, 0xc0, 0x46,
-0xb8, 0x62, 0x38, 0x1c, 0x00, 0xf0, 0xa0, 0xfb, 0x44, 0xe0, 0x20, 0x68,
-0x01, 0x23, 0x9b, 0x07, 0x08, 0x38, 0x18, 0x43, 0x00, 0x68, 0xc0, 0x46,
-0x78, 0x64, 0x60, 0x68, 0x02, 0x04, 0x12, 0x0c, 0x78, 0x6e, 0x01, 0x26,
-0xc1, 0x1d, 0x0d, 0x31, 0x8a, 0x42, 0x02, 0xd2, 0x3a, 0x64, 0x08, 0x1c,
-0x0e, 0xe0, 0x41, 0x19, 0x89, 0x89, 0xf0, 0x23, 0x19, 0x40, 0x09, 0x09,
-0x89, 0x00, 0x40, 0x18, 0xf8, 0x60, 0xf9, 0x61, 0x61, 0x68, 0x09, 0x04,
-0x09, 0x0c, 0x81, 0x42, 0x16, 0xd2, 0x39, 0x64, 0x63, 0x68, 0x19, 0x04,
+0x08, 0x60, 0x01, 0xf0, 0x9d, 0xfc, 0x03, 0x23, 0x1b, 0x07, 0x41, 0x68,
+0x19, 0x40, 0x0c, 0x0f, 0x61, 0x01, 0x09, 0x1b, 0x89, 0x00, 0x18, 0x4a,
+0x8f, 0x18, 0x01, 0x21, 0x39, 0x80, 0x81, 0x6a, 0xc0, 0x46, 0x79, 0x65,
+0x41, 0x6a, 0xc0, 0x46, 0x79, 0x67, 0xb9, 0x6c, 0xfa, 0x6c, 0x89, 0x18,
+0xb9, 0x64, 0x00, 0x21, 0xf9, 0x64, 0xba, 0x6b, 0x3b, 0x6d, 0xd2, 0x18,
+0xba, 0x63, 0x39, 0x65, 0x42, 0x6a, 0x20, 0x32, 0x51, 0x71, 0x79, 0x6d,
+0x7a, 0x6f, 0xd2, 0x6d, 0xc0, 0x46, 0x11, 0x60, 0xfc, 0xf7, 0xca, 0xff,
+0x20, 0x01, 0x09, 0x49, 0x40, 0x18, 0x19, 0x23, 0xdb, 0x01, 0xc0, 0x18,
+0x41, 0x6b, 0x01, 0x39, 0x41, 0x63, 0x78, 0x6f, 0x01, 0xf0, 0xc6, 0xfb,
+0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0,
+0x5c, 0x2b, 0x00, 0x80, 0xa0, 0x1c, 0x00, 0x80, 0xf0, 0xb5, 0x40, 0x20,
+0x12, 0x49, 0xc0, 0x46, 0x08, 0x60, 0x01, 0xf0, 0x59, 0xfc, 0x07, 0x1c,
+0x40, 0x68, 0x03, 0x23, 0x1b, 0x07, 0x18, 0x40, 0x06, 0x0f, 0x70, 0x01,
+0x80, 0x1b, 0x80, 0x00, 0x0c, 0x49, 0x44, 0x18, 0xb8, 0x6a, 0xc0, 0x46,
+0x60, 0x65, 0x78, 0x6a, 0xc0, 0x46, 0x60, 0x67, 0x80, 0x6f, 0x05, 0x1d,
+0xe5, 0x63, 0xb9, 0x69, 0x28, 0x1c, 0x02, 0xf0, 0x89, 0xf9, 0x38, 0x1c,
+0x21, 0x1c, 0x32, 0x1c, 0x2b, 0x1c, 0x00, 0xf0, 0x20, 0xf8, 0xf0, 0xbc,
+0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x00, 0xb0, 0x5c, 0x2b, 0x00, 0x80,
+0xf0, 0xb5, 0x4b, 0x6f, 0x9b, 0x6f, 0x1f, 0x1d, 0xcf, 0x63, 0x05, 0x68,
+0x00, 0x23, 0x84, 0x69, 0xa4, 0x08, 0x08, 0xd0, 0x9c, 0x00, 0x2e, 0x59,
+0xc0, 0x46, 0x3e, 0x51, 0x84, 0x69, 0xa4, 0x08, 0x01, 0x33, 0x9c, 0x42,
+0xf6, 0xd8, 0x3b, 0x1c, 0x00, 0xf0, 0x03, 0xf8, 0xf0, 0xbc, 0x08, 0xbc,
+0x18, 0x47, 0xff, 0xb5, 0x81, 0xb0, 0x04, 0x1c, 0x1d, 0x1c, 0x0f, 0x1c,
+0x46, 0x48, 0x01, 0x69, 0x01, 0x31, 0x01, 0x61, 0xf9, 0x1d, 0x51, 0x31,
+0xbd, 0x65, 0x00, 0x91, 0x20, 0x1c, 0xfd, 0xf7, 0x5d, 0xfc, 0xf8, 0x6d,
+0x40, 0x09, 0x36, 0xd2, 0xb8, 0x6d, 0x06, 0x7b, 0x43, 0x7b, 0x1b, 0x02,
+0x1e, 0x43, 0x17, 0x21, 0x49, 0x02, 0x01, 0x73, 0x0b, 0x0a, 0x43, 0x73,
+0x00, 0x99, 0x20, 0x1c, 0xfd, 0xf7, 0x4c, 0xfc, 0xb8, 0x6d, 0xc0, 0x46,
+0x06, 0x73, 0x33, 0x0a, 0x43, 0x73, 0xf8, 0x6d, 0x40, 0x09, 0x20, 0xd2,
+0x60, 0x68, 0x01, 0x04, 0x09, 0x0c, 0x03, 0x98, 0x01, 0xf0, 0xcc, 0xfc,
+0x60, 0x68, 0x32, 0x4b, 0x18, 0x43, 0x60, 0x60, 0x20, 0x1c, 0x01, 0xf0,
+0x35, 0xfd, 0x00, 0x25, 0x7d, 0x60, 0xbd, 0x60, 0x3d, 0x64, 0x7d, 0x64,
+0x20, 0x1c, 0xfc, 0xf7, 0x31, 0xff, 0x38, 0x88, 0x40, 0x23, 0x18, 0x43,
+0x38, 0x80, 0x7d, 0x62, 0x29, 0x48, 0xc0, 0x46, 0xb8, 0x62, 0x38, 0x1c,
+0x00, 0xf0, 0xa0, 0xfb, 0x44, 0xe0, 0x20, 0x68, 0x01, 0x23, 0x9b, 0x07,
+0x08, 0x38, 0x18, 0x43, 0x00, 0x68, 0xc0, 0x46, 0x78, 0x64, 0x60, 0x68,
+0x02, 0x04, 0x12, 0x0c, 0x78, 0x6e, 0x01, 0x26, 0xc1, 0x1d, 0x0d, 0x31,
+0x8a, 0x42, 0x02, 0xd2, 0x3a, 0x64, 0x08, 0x1c, 0x0e, 0xe0, 0x41, 0x19,
+0x89, 0x89, 0xf0, 0x23, 0x19, 0x40, 0x09, 0x09, 0x89, 0x00, 0x40, 0x18,
+0xf8, 0x60, 0xf9, 0x61, 0x61, 0x68, 0x09, 0x04, 0x09, 0x0c, 0x81, 0x42,
+0x16, 0xd2, 0x39, 0x64, 0x63, 0x68, 0x19, 0x04, 0x09, 0x0c, 0x40, 0x1a,
+0x03, 0x30, 0x80, 0x08, 0x82, 0x00, 0xa0, 0x61,
+0x20, 0x68, 0x09, 0x18, 0x9b, 0x18, 0x63, 0x60, 0xc3, 0x1f, 0x05, 0x3b,
+0x38, 0x1c, 0x00, 0xf0, 0xb6, 0xfa, 0x7e, 0x80, 0x20, 0x1c, 0x00, 0xf0,
+0xbf, 0xfb, 0x0b, 0xe0, 0xb9, 0x68, 0x08, 0x1a, 0x00, 0x25, 0x78, 0x62,
+0xbd, 0x62, 0x38, 0x1c, 0x00, 0xf0, 0x3c, 0xfc, 0x20, 0x1c, 0x39, 0x1c,
+0x00, 0xf0, 0x64, 0xf8, 0x05, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47,
+0x0c, 0x2b, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0xc0,
+0xf0, 0xb5, 0x04, 0x1c, 0x0f, 0x1c, 0x38, 0x6c, 0xf9, 0x6b, 0x0d, 0x18,
+0x21, 0x68, 0x41, 0x18, 0x00, 0x20, 0xa2, 0x69, 0x00, 0x2a, 0x0b, 0xd9,
+0x82, 0x00, 0x56, 0x18, 0x01, 0x23, 0x9b, 0x07, 0x33, 0x43, 0x1b, 0x68,
+0xc0, 0x46, 0xab, 0x50, 0xa2, 0x69, 0x01, 0x30, 0x82, 0x42, 0xf3, 0xd8,
+0x78, 0x6e, 0xf9, 0x6b, 0x09, 0x18, 0x89, 0x89, 0xf0, 0x23, 0x19, 0x40,
+0x09, 0x09, 0x89, 0x00, 0x40, 0x18, 0xf8, 0x60, 0xf9, 0x61, 0x20, 0x68,
+0x01, 0x23, 0x9b, 0x07, 0x08, 0x38, 0x18, 0x43, 0x01, 0x68, 0x78, 0x6c,
+0xfc, 0xf7, 0x95, 0xff, 0x78, 0x64, 0x60, 0x68, 0x01, 0x04, 0x09, 0x0c,
+0xf8, 0x68, 0x81, 0x42, 0x19, 0xd2, 0x39, 0x64, 0x63, 0x68, 0x19, 0x04,
0x09, 0x0c, 0x40, 0x1a, 0x03, 0x30, 0x80, 0x08, 0x82, 0x00, 0xa0, 0x61,
0x20, 0x68, 0x09, 0x18, 0x9b, 0x18, 0x63, 0x60, 0xc3, 0x1f, 0x05, 0x3b,
-0x38, 0x1c, 0x00, 0xf0, 0xb6, 0xfa, 0x7e, 0x80,
-0x20, 0x1c, 0x00, 0xf0, 0xbf, 0xfb, 0x0b, 0xe0, 0xb9, 0x68, 0x08, 0x1a,
-0x00, 0x25, 0x78, 0x62, 0xbd, 0x62, 0x38, 0x1c, 0x00, 0xf0, 0x3c, 0xfc,
-0x20, 0x1c, 0x39, 0x1c, 0x00, 0xf0, 0x64, 0xf8, 0x05, 0xb0, 0xf0, 0xbc,
-0x08, 0xbc, 0x18, 0x47, 0x0c, 0x2b, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80,
-0x01, 0x00, 0x00, 0xc0, 0xf0, 0xb5, 0x04, 0x1c, 0x0f, 0x1c, 0x38, 0x6c,
-0xf9, 0x6b, 0x0d, 0x18, 0x21, 0x68, 0x41, 0x18, 0x00, 0x20, 0xa2, 0x69,
-0x00, 0x2a, 0x0b, 0xd9, 0x82, 0x00, 0x56, 0x18, 0x01, 0x23, 0x9b, 0x07,
-0x33, 0x43, 0x1b, 0x68, 0xc0, 0x46, 0xab, 0x50, 0xa2, 0x69, 0x01, 0x30,
-0x82, 0x42, 0xf3, 0xd8, 0x78, 0x6e, 0xf9, 0x6b, 0x09, 0x18, 0x89, 0x89,
-0xf0, 0x23, 0x19, 0x40, 0x09, 0x09, 0x89, 0x00, 0x40, 0x18, 0xf8, 0x60,
-0xf9, 0x61, 0x20, 0x68, 0x01, 0x23, 0x9b, 0x07, 0x08, 0x38, 0x18, 0x43,
-0x01, 0x68, 0x78, 0x6c, 0xfc, 0xf7, 0x9f, 0xff, 0x78, 0x64, 0x60, 0x68,
-0x01, 0x04, 0x09, 0x0c, 0xf8, 0x68, 0x81, 0x42, 0x19, 0xd2, 0x39, 0x64,
-0x63, 0x68, 0x19, 0x04, 0x09, 0x0c, 0x40, 0x1a, 0x03, 0x30, 0x80, 0x08,
-0x82, 0x00, 0xa0, 0x61, 0x20, 0x68, 0x09, 0x18, 0x9b, 0x18, 0x63, 0x60,
-0xc3, 0x1f, 0x05, 0x3b, 0x38, 0x1c, 0x00, 0xf0, 0x56, 0xfa, 0x01, 0x20,
-0x78, 0x80, 0x20, 0x1c, 0x00, 0xf0, 0x5e, 0xfb, 0xf0, 0xbc, 0x08, 0xbc,
-0x18, 0x47, 0xb9, 0x68, 0x08, 0x1a, 0x78, 0x62, 0x00, 0x20, 0xb8, 0x62,
-0x38, 0x1c, 0x00, 0xf0, 0xd9, 0xfb, 0x20, 0x1c, 0x39, 0x1c, 0x00, 0xf0,
-0x01, 0xf8, 0xef, 0xe7, 0xf0, 0xb5, 0x84, 0xb0, 0x04, 0x1c, 0x0f, 0x1c,
-0x8e, 0x48, 0x41, 0x69, 0x01, 0x31, 0x41, 0x61, 0x03, 0x20, 0x00, 0x07,
-0x61, 0x68, 0x08, 0x40, 0x06, 0x0f, 0x0a, 0x04, 0x12, 0x0c, 0x20, 0x68,
-0x11, 0x18, 0xfb, 0x68, 0xd2, 0x1a, 0x7b, 0x68, 0x9d, 0x1a, 0xc3, 0x1f,
-0x05, 0x3b, 0x38, 0x1c, 0x2a, 0x1c, 0x00, 0xf0, 0x26, 0xfa, 0x00, 0x20,
-0x78, 0x80, 0x20, 0x1c, 0x00, 0xf0, 0x2e, 0xfb, 0x60, 0x68, 0x40, 0x19,
-0x01, 0x04, 0x09, 0x0c, 0x60, 0x60, 0x30, 0x1c, 0x01, 0xf0, 0xe0, 0xfb,
-0x7d, 0x4e, 0x0b, 0x23, 0x1b, 0x02, 0xf0, 0x18, 0x00, 0x69, 0x00, 0x28,
-0x19, 0xd0, 0x00, 0x25, 0x2d, 0x23, 0x9b, 0x01, 0xf0, 0x18, 0xc0, 0x68,
-0x00, 0x28, 0x12, 0xd0, 0xaa, 0x00, 0x92, 0x19, 0x2d, 0x23, 0x9b, 0x01,
-0xd2, 0x18, 0xd2, 0x68, 0x20, 0x1c, 0x39, 0x1c, 0x01, 0xf0, 0x1c, 0xfe,
-0x01, 0x35, 0xa8, 0x00, 0x80, 0x19, 0x2d, 0x23, 0x9b, 0x01, 0xc0, 0x18,
-0xc0, 0x68, 0x00, 0x28, 0xec, 0xd1, 0xf8, 0x6b, 0x01, 0x1f, 0x8a, 0x1c,
-0xfa, 0x63, 0xfa, 0x68, 0x7d, 0x6c, 0x00, 0xf0, 0xbb, 0xf9, 0xc0, 0x43,
-0x01, 0x04, 0x09, 0x0c, 0x28, 0x1c, 0xfc, 0xf7, 0x1a, 0xff, 0x03, 0x90,
-0xf9, 0x6b, 0x3a, 0x6e, 0x8e, 0x18, 0x20, 0x68, 0x12, 0x18, 0x01, 0x92,
-0x7a, 0x6e, 0x8d, 0x18, 0x11, 0x18, 0x02, 0x91, 0xc8, 0x1d, 0x09, 0x30,
-0xe0, 0x60, 0xb1, 0x88, 0x08, 0x02, 0x09, 0x0a, 0x09, 0x06, 0x09, 0x0e,
-0x08, 0x43, 0x00, 0x04, 0x00, 0x0c, 0x78, 0x61, 0x68, 0x68, 0x01, 0x0e,
-0xff, 0x22, 0x12, 0x04, 0x02, 0x40, 0x12, 0x0a, 0x11, 0x43, 0xff, 0x22,
-0x12, 0x02, 0x02, 0x40, 0x12, 0x02, 0x11, 0x43, 0x00, 0x06, 0x08, 0x43,
-0x38, 0x61, 0xa8, 0x89, 0x09, 0x23, 0x1b, 0x02, 0x18, 0x40, 0xb8, 0x61,
+0x38, 0x1c, 0x00, 0xf0, 0x56, 0xfa, 0x01, 0x20, 0x78, 0x80, 0x20, 0x1c,
+0x00, 0xf0, 0x5e, 0xfb, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xb9, 0x68,
+0x08, 0x1a, 0x78, 0x62, 0x00, 0x20, 0xb8, 0x62, 0x38, 0x1c, 0x00, 0xf0,
+0xd9, 0xfb, 0x20, 0x1c, 0x39, 0x1c, 0x00, 0xf0, 0x01, 0xf8, 0xef, 0xe7,
+0xf0, 0xb5, 0x84, 0xb0, 0x04, 0x1c, 0x0f, 0x1c, 0x8e, 0x48, 0x41, 0x69,
+0x01, 0x31, 0x41, 0x61, 0x03, 0x20, 0x00, 0x07, 0x61, 0x68, 0x08, 0x40,
+0x06, 0x0f, 0x0a, 0x04, 0x12, 0x0c, 0x20, 0x68, 0x11, 0x18, 0xfb, 0x68,
+0xd2, 0x1a, 0x7b, 0x68, 0x9d, 0x1a, 0xc3, 0x1f, 0x05, 0x3b, 0x38, 0x1c,
+0x2a, 0x1c, 0x00, 0xf0, 0x26, 0xfa, 0x00, 0x20, 0x78, 0x80, 0x20, 0x1c,
+0x00, 0xf0, 0x2e, 0xfb, 0x60, 0x68, 0x40, 0x19, 0x01, 0x04, 0x09, 0x0c,
+0x60, 0x60, 0x30, 0x1c, 0x01, 0xf0, 0xe0, 0xfb, 0x7d, 0x4e, 0x0b, 0x23,
+0x1b, 0x02, 0xf0, 0x18, 0x00, 0x69, 0x00, 0x28, 0x19, 0xd0, 0x00, 0x25,
+0x2d, 0x23, 0x9b, 0x01, 0xf0, 0x18, 0xc0, 0x68, 0x00, 0x28, 0x12, 0xd0,
+0xaa, 0x00, 0x92, 0x19, 0x2d, 0x23, 0x9b, 0x01, 0xd2, 0x18, 0xd2, 0x68,
+0x20, 0x1c, 0x39, 0x1c, 0x01, 0xf0, 0x1c, 0xfe, 0x01, 0x35, 0xa8, 0x00,
+0x80, 0x19, 0x2d, 0x23, 0x9b, 0x01, 0xc0, 0x18, 0xc0, 0x68, 0x00, 0x28,
+0xec, 0xd1, 0xf8, 0x6b, 0x01, 0x1f, 0x8a, 0x1c, 0xfa, 0x63, 0xfa, 0x68,
+0x7d, 0x6c, 0x00, 0xf0, 0xbb, 0xf9, 0xc0, 0x43, 0x01, 0x04, 0x09, 0x0c,
+0x28, 0x1c, 0xfc, 0xf7, 0x10, 0xff, 0x03, 0x90, 0xf9, 0x6b, 0x3a, 0x6e,
+0x8e, 0x18, 0x20, 0x68, 0x12, 0x18, 0x01, 0x92, 0x7a, 0x6e, 0x8d, 0x18,
+0x11, 0x18, 0x02, 0x91, 0xc8, 0x1d, 0x09, 0x30, 0xe0, 0x60, 0xb1, 0x88,
+0x08, 0x02, 0x09, 0x0a, 0x09, 0x06, 0x09, 0x0e, 0x08, 0x43, 0x00, 0x04,
+0x00, 0x0c, 0x78, 0x61, 0x68, 0x68, 0x01, 0x0e, 0xff, 0x22, 0x12, 0x04,
+0x02, 0x40, 0x12, 0x0a, 0x11, 0x43, 0xff, 0x22, 0x12, 0x02, 0x02, 0x40,
+0x12, 0x02, 0x11, 0x43, 0x00, 0x06, 0x08, 0x43, 0x38, 0x61, 0xa8, 0x89,
+0x09, 0x23, 0x1b, 0x02, 0x18, 0x40, 0xb8, 0x61,
0xa8, 0x89, 0x98, 0x43, 0xa8, 0x81, 0xa8, 0x89, 0x02, 0x99, 0xc0, 0x46,
-0x88, 0x81, 0x00, 0x20, 0x70, 0x80, 0xb0, 0x80,
-0x70, 0x81, 0x68, 0x60, 0x28, 0x82, 0xb9, 0x6e, 0x30, 0x1c, 0xfc, 0xf7,
-0xf2, 0xfe, 0x38, 0x86, 0xfa, 0x69, 0x30, 0x1c, 0x29, 0x1c, 0xfc, 0xf7,
-0x0d, 0xff, 0x78, 0x86, 0x3d, 0x8e, 0x78, 0x8e, 0x03, 0x99, 0xfc, 0xf7,
-0xd2, 0xfe, 0x00, 0x90, 0x60, 0x68, 0x00, 0x04, 0x00, 0x0c, 0x39, 0x6e,
-0x41, 0x1a, 0x09, 0x04, 0x09, 0x0c, 0x7a, 0x6e, 0x82, 0x1a, 0x13, 0x04,
-0x1b, 0x0c, 0x1a, 0x02, 0x1b, 0x0a, 0x1a, 0x43, 0x16, 0x04, 0x36, 0x0c,
-0xba, 0x68, 0x82, 0x42, 0x01, 0xd2, 0x00, 0x20, 0x00, 0xe0, 0x10, 0x1a,
-0xb8, 0x60, 0x08, 0x02, 0x09, 0x12, 0x09, 0x06, 0x09, 0x0e, 0x08, 0x43,
-0x01, 0x04, 0x09, 0x0c, 0x01, 0x98, 0xc0, 0x46, 0x41, 0x80, 0x28, 0x1c,
-0xfc, 0xf7, 0xad, 0xfe, 0x05, 0x1c, 0x00, 0x98, 0x31, 0x1c, 0xfc, 0xf7,
-0xa8, 0xfe, 0x06, 0x1c, 0x78, 0x69, 0x00, 0x04, 0x00, 0x0c, 0x01, 0x02,
-0x00, 0x0a, 0x08, 0x43, 0x01, 0x04, 0x09, 0x0c, 0x01, 0x98, 0xc0, 0x46,
-0x81, 0x80, 0x28, 0x1c, 0xfc, 0xf7, 0x99, 0xfe, 0x79, 0x69, 0x01, 0x31,
-0xc0, 0x43, 0x79, 0x61, 0x01, 0x9a, 0xc0, 0x46, 0x50, 0x81, 0x38, 0x69,
-0x01, 0x0e, 0xff, 0x22, 0x12, 0x04, 0x02, 0x40, 0x12, 0x0a, 0x11, 0x43,
-0xff, 0x22, 0x12, 0x02, 0x02, 0x40, 0x12, 0x02, 0x11, 0x43, 0x00, 0x06,
-0x01, 0x43, 0x30, 0x1c, 0xfc, 0xf7, 0x81, 0xfe, 0x39, 0x69, 0x7a, 0x68,
-0x89, 0x18, 0x39, 0x61, 0xb9, 0x68, 0x00, 0x29, 0x09, 0xd1, 0x02, 0x99,
-0x89, 0x89, 0xba, 0x69, 0x11, 0x43, 0x02, 0x9a, 0xc0, 0x46, 0x91, 0x81,
-0xb9, 0x69, 0xfc, 0xf7, 0x70, 0xfe, 0x20, 0x82, 0x00, 0x20, 0x60, 0x82,
-0xf8, 0x6d, 0x41, 0x08, 0x16, 0xd3, 0x80, 0x0a, 0x0a, 0xd3, 0x60, 0x68,
-0x10, 0x38, 0x01, 0x04, 0x09, 0x0c, 0x08, 0x02, 0x09, 0x0a, 0x08, 0x43,
-0x21, 0x68, 0xc0, 0x46, 0x08, 0x82, 0x09, 0xe0, 0x60, 0x68, 0x0c, 0x38,
-0x01, 0x04, 0x09, 0x0c, 0x08, 0x02, 0x09, 0x0a, 0x08, 0x43, 0x21, 0x68,
-0xc0, 0x46, 0x88, 0x81, 0x04, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47,
-0x0c, 0x2b, 0x00, 0x80, 0x68, 0x0e, 0x00, 0x80, 0xf1, 0xb5, 0x84, 0xb0,
-0x6e, 0x4d, 0x28, 0x69, 0x01, 0x22, 0x04, 0x99, 0x8a, 0x40, 0x90, 0x43,
-0x28, 0x61, 0x04, 0x98, 0x43, 0x01, 0x18, 0x1a, 0x80, 0x00, 0x16, 0x1c,
-0x69, 0x49, 0x44, 0x18, 0xe0, 0x6b, 0xc0, 0x46, 0x00, 0x90, 0xa0, 0x68,
-0x00, 0x28, 0x01, 0xd1, 0x00, 0x26, 0x26, 0xe0, 0x65, 0x48, 0x41, 0x69,
-0x01, 0x31, 0x41, 0x61, 0x04, 0x98, 0xfc, 0xf7, 0x13, 0xfd, 0x07, 0x1c,
-0x03, 0xd1, 0x28, 0x69, 0x30, 0x43, 0x28, 0x61, 0xb5, 0xe0, 0xa0, 0x68,
-0x65, 0x68, 0xa8, 0x42, 0x00, 0xd2, 0x05, 0x1c, 0xa1, 0x6c, 0xa9, 0x42,
-0x16, 0xd2, 0x40, 0x1a, 0x62, 0x6a, 0x10, 0x1a, 0x00, 0x26, 0x60, 0x62,
-0xa6, 0x60, 0xa6, 0x62, 0x20, 0x88, 0x48, 0x23, 0x18, 0x43, 0x20, 0x80,
-0x0d, 0x1c, 0x09, 0xd1, 0x38, 0x1c, 0xfc, 0xf7, 0x23, 0xfd, 0x03, 0x20,
-0x60, 0x80, 0x66, 0x60, 0x20, 0x1c, 0x00, 0xf0, 0x8d, 0xf9, 0x96, 0xe0,
-0xe1, 0x68, 0x38, 0x68, 0x09, 0x18, 0xc3, 0x1f, 0x05, 0x3b, 0x20, 0x1c,
-0x02, 0x39, 0x2a, 0x1c, 0x00, 0xf0, 0xcd, 0xf8, 0x38, 0x1c, 0x00, 0xf0,
-0xd7, 0xf9, 0xe0, 0x68, 0x46, 0x19, 0x78, 0x68, 0x30, 0x43, 0x78, 0x60,
-0x04, 0x98, 0x31, 0x1c, 0x01, 0xf0, 0x88, 0xfa, 0x21, 0x6e, 0x00, 0x98,
+0x88, 0x81, 0x00, 0x20, 0x70, 0x80, 0xb0, 0x80, 0x70, 0x81, 0x68, 0x60,
+0x28, 0x82, 0xb9, 0x6e, 0x30, 0x1c, 0xfc, 0xf7, 0xe8, 0xfe, 0x38, 0x86,
+0xfa, 0x69, 0x30, 0x1c, 0x29, 0x1c, 0xfc, 0xf7, 0x03, 0xff, 0x78, 0x86,
+0x3d, 0x8e, 0x78, 0x8e, 0x03, 0x99, 0xfc, 0xf7, 0xc8, 0xfe, 0x00, 0x90,
+0x60, 0x68, 0x00, 0x04, 0x00, 0x0c, 0x39, 0x6e, 0x41, 0x1a, 0x09, 0x04,
+0x09, 0x0c, 0x7a, 0x6e, 0x82, 0x1a, 0x13, 0x04, 0x1b, 0x0c, 0x1a, 0x02,
+0x1b, 0x0a, 0x1a, 0x43, 0x16, 0x04, 0x36, 0x0c, 0xba, 0x68, 0x82, 0x42,
+0x01, 0xd2, 0x00, 0x20, 0x00, 0xe0, 0x10, 0x1a, 0xb8, 0x60, 0x08, 0x02,
+0x09, 0x12, 0x09, 0x06, 0x09, 0x0e, 0x08, 0x43, 0x01, 0x04, 0x09, 0x0c,
+0x01, 0x98, 0xc0, 0x46, 0x41, 0x80, 0x28, 0x1c, 0xfc, 0xf7, 0xa3, 0xfe,
+0x05, 0x1c, 0x00, 0x98, 0x31, 0x1c, 0xfc, 0xf7, 0x9e, 0xfe, 0x06, 0x1c,
+0x78, 0x69, 0x00, 0x04, 0x00, 0x0c, 0x01, 0x02, 0x00, 0x0a, 0x08, 0x43,
+0x01, 0x04, 0x09, 0x0c, 0x01, 0x98, 0xc0, 0x46, 0x81, 0x80, 0x28, 0x1c,
+0xfc, 0xf7, 0x8f, 0xfe, 0x79, 0x69, 0x01, 0x31, 0xc0, 0x43, 0x79, 0x61,
+0x01, 0x9a, 0xc0, 0x46, 0x50, 0x81, 0x38, 0x69, 0x01, 0x0e, 0xff, 0x22,
+0x12, 0x04, 0x02, 0x40, 0x12, 0x0a, 0x11, 0x43, 0xff, 0x22, 0x12, 0x02,
+0x02, 0x40, 0x12, 0x02, 0x11, 0x43, 0x00, 0x06, 0x01, 0x43, 0x30, 0x1c,
+0xfc, 0xf7, 0x77, 0xfe, 0x39, 0x69, 0x7a, 0x68, 0x89, 0x18, 0x39, 0x61,
+0xb9, 0x68, 0x00, 0x29, 0x09, 0xd1, 0x02, 0x99, 0x89, 0x89, 0xba, 0x69,
+0x11, 0x43, 0x02, 0x9a, 0xc0, 0x46, 0x91, 0x81, 0xb9, 0x69, 0xfc, 0xf7,
+0x66, 0xfe, 0x20, 0x82, 0x00, 0x20, 0x60, 0x82, 0xf8, 0x6d, 0x41, 0x08,
+0x16, 0xd3, 0x80, 0x0a, 0x0a, 0xd3, 0x60, 0x68, 0x10, 0x38, 0x01, 0x04,
+0x09, 0x0c, 0x08, 0x02, 0x09, 0x0a, 0x08, 0x43, 0x21, 0x68, 0xc0, 0x46,
+0x08, 0x82, 0x09, 0xe0, 0x60, 0x68, 0x0c, 0x38, 0x01, 0x04, 0x09, 0x0c,
+0x08, 0x02, 0x09, 0x0a, 0x08, 0x43, 0x21, 0x68, 0xc0, 0x46, 0x88, 0x81,
+0x04, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x0c, 0x2b, 0x00, 0x80,
+0x68, 0x0e, 0x00, 0x80, 0xf1, 0xb5, 0x84, 0xb0, 0x6e, 0x4d, 0x28, 0x69,
+0x01, 0x22, 0x04, 0x99, 0x8a, 0x40, 0x90, 0x43, 0x28, 0x61, 0x04, 0x98,
+0x43, 0x01, 0x18, 0x1a, 0x80, 0x00, 0x16, 0x1c, 0x69, 0x49, 0x44, 0x18,
+0xe0, 0x6b, 0xc0, 0x46, 0x00, 0x90, 0xa0, 0x68, 0x00, 0x28, 0x01, 0xd1,
+0x00, 0x26, 0x26, 0xe0, 0x65, 0x48, 0x41, 0x69, 0x01, 0x31, 0x41, 0x61,
+0x04, 0x98, 0xfc, 0xf7, 0x09, 0xfd, 0x07, 0x1c, 0x03, 0xd1, 0x28, 0x69,
+0x30, 0x43, 0x28, 0x61, 0xb5, 0xe0, 0xa0, 0x68, 0x65, 0x68, 0xa8, 0x42,
+0x00, 0xd2, 0x05, 0x1c, 0xa1, 0x6c, 0xa9, 0x42, 0x16, 0xd2, 0x40, 0x1a,
+0x62, 0x6a, 0x10, 0x1a, 0x00, 0x26, 0x60, 0x62, 0xa6, 0x60, 0xa6, 0x62,
+0x20, 0x88, 0x48, 0x23, 0x18, 0x43, 0x20, 0x80, 0x0d, 0x1c, 0x09, 0xd1,
+0x38, 0x1c, 0xfc, 0xf7, 0x19, 0xfd, 0x03, 0x20, 0x60, 0x80, 0x66, 0x60,
+0x20, 0x1c, 0x00, 0xf0, 0x8d, 0xf9, 0x96, 0xe0, 0xe1, 0x68, 0x38, 0x68,
+0x09, 0x18, 0xc3, 0x1f, 0x05, 0x3b, 0x20, 0x1c, 0x02, 0x39, 0x2a, 0x1c,
+0x00, 0xf0, 0xcd, 0xf8, 0x38, 0x1c, 0x00, 0xf0, 0xd7, 0xf9, 0xe0, 0x68,
+0x46, 0x19, 0x78, 0x68, 0x30, 0x43, 0x78, 0x60, 0x04, 0x98, 0x31, 0x1c,
+0x01, 0xf0, 0x88, 0xfa, 0x21, 0x6e, 0x00, 0x98,
0x08, 0x18, 0x01, 0x90, 0x70, 0x1a, 0x00, 0x04, 0x00, 0x0c, 0x61, 0x6e,
-0x71, 0x1a, 0x0a, 0x04, 0x12, 0x0c, 0x11, 0x02,
-0x12, 0x0a, 0x11, 0x43, 0x09, 0x04, 0x09, 0x0c, 0x02, 0x91, 0x01, 0x02,
-0x00, 0x0a, 0x08, 0x43, 0x01, 0x04, 0x09, 0x0c, 0x01, 0x98, 0xc0, 0x46,
-0x41, 0x80, 0x20, 0x8e, 0xfc, 0xf7, 0xd5, 0xfd, 0x06, 0x1c, 0x60, 0x8e,
-0x02, 0x99, 0xfc, 0xf7, 0xd0, 0xfd, 0x03, 0x90, 0x60, 0x69, 0x01, 0x04,
-0x09, 0x0c, 0x08, 0x02, 0x09, 0x0a, 0x08, 0x43, 0x01, 0x04, 0x09, 0x0c,
-0x01, 0x98, 0xc0, 0x46, 0x81, 0x80, 0x30, 0x1c, 0xfc, 0xf7, 0xc1, 0xfd,
-0x61, 0x69, 0x01, 0x31, 0xc0, 0x43, 0x61, 0x61, 0x01, 0x99, 0xc0, 0x46,
-0x48, 0x81, 0x60, 0x6e, 0x00, 0x99, 0x46, 0x18, 0x20, 0x69, 0x01, 0x0e,
-0xff, 0x22, 0x12, 0x04, 0x02, 0x40, 0x12, 0x0a, 0x11, 0x43, 0xff, 0x22,
-0x12, 0x02, 0x02, 0x40, 0x12, 0x02, 0x11, 0x43, 0x00, 0x06, 0x01, 0x43,
-0x71, 0x60, 0x03, 0x98, 0xfc, 0xf7, 0xa5, 0xfd, 0x21, 0x69, 0x49, 0x19,
-0x21, 0x61, 0xa1, 0x68, 0x49, 0x1b, 0xa1, 0x60, 0x06, 0xd1, 0xb1, 0x89,
-0xa2, 0x69, 0x11, 0x43, 0xb1, 0x81, 0xa1, 0x69, 0xfc, 0xf7, 0x97, 0xfd,
-0x38, 0x82, 0x61, 0x6e, 0x38, 0x68, 0x09, 0x18, 0x0e, 0x31, 0xf9, 0x60,
-0xe2, 0x68, 0x00, 0x99, 0x04, 0x38, 0x00, 0xf0, 0x4c, 0xf8, 0x02, 0x20,
-0x78, 0x82, 0xe0, 0x6d, 0x41, 0x08, 0x16, 0xd3, 0x80, 0x0a, 0x0a, 0xd3,
-0x78, 0x68, 0x10, 0x38, 0x01, 0x04, 0x09, 0x0c, 0x08, 0x02, 0x09, 0x0a,
-0x08, 0x43, 0x39, 0x68, 0xc0, 0x46, 0xc8, 0x81, 0x09, 0xe0, 0x78, 0x68,
-0x0c, 0x38, 0x01, 0x04, 0x09, 0x0c, 0x08, 0x02, 0x09, 0x0a, 0x08, 0x43,
-0x39, 0x68, 0xc0, 0x46, 0x48, 0x81, 0x05, 0xb0, 0xf0, 0xbc, 0x08, 0xbc,
-0x18, 0x47, 0x00, 0x00, 0xd0, 0x2c, 0x00, 0x80, 0x5c, 0x2b, 0x00, 0x80,
-0x0c, 0x2b, 0x00, 0x80, 0xf7, 0xb5, 0x03, 0x1c, 0x0f, 0x1c, 0x00, 0x20,
-0x1c, 0x68, 0x26, 0x04, 0x31, 0x1c, 0x1d, 0x1d, 0xfc, 0xf7, 0x5b, 0xfd,
-0x40, 0xc7, 0x02, 0x9a, 0xd1, 0x1c, 0x89, 0x08, 0x01, 0x39, 0x4a, 0x1e,
-0x02, 0x92, 0x00, 0x29, 0x0d, 0xd0, 0x21, 0x0c, 0x10, 0xcd, 0x22, 0x04,
-0x0a, 0x43, 0x11, 0x1c, 0x16, 0x1c, 0xfc, 0xf7, 0x4a, 0xfd, 0x40, 0xc7,
-0x02, 0x99, 0x4a, 0x1e, 0x02, 0x92, 0x00, 0x29, 0xf1, 0xd1, 0x03, 0xb0,
-0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x80, 0x08, 0x80, 0x00, 0x89, 0x08,
-0x89, 0x00, 0x03, 0x32, 0x93, 0x08, 0x5a, 0x1e, 0x00, 0x2b, 0x05, 0xd0,
-0x08, 0xc9, 0x08, 0xc0, 0x13, 0x1c, 0x01, 0x3a, 0x00, 0x2b, 0xf9, 0xd1,
-0x70, 0x47, 0xff, 0xb5, 0x86, 0xb0, 0x17, 0x1c, 0x00, 0x26, 0x06, 0x98,
-0x80, 0x6c, 0xc0, 0x1b, 0x06, 0x99, 0xc0, 0x46, 0x88, 0x64, 0x01, 0x20,
-0xc0, 0x05, 0x06, 0x99, 0x89, 0x6b, 0xc0, 0x46, 0x01, 0x91, 0x06, 0x99,
-0x4c, 0x6b, 0x67, 0xe0, 0x21, 0x68, 0xc0, 0x46, 0x02, 0x91, 0x61, 0x68,
-0xc0, 0x46, 0x03, 0x91, 0xa1, 0x68, 0xc0, 0x46, 0x04, 0x91, 0x02, 0xa9,
-0x49, 0x88, 0xb9, 0x42, 0x08, 0xd2, 0x02, 0xad, 0x6d, 0x88, 0x02, 0xa9,
-0x49, 0x88, 0x7f, 0x1a, 0x00, 0x21, 0x02, 0xab, 0x59, 0x80, 0x19, 0xe0,
-0x02, 0xa9, 0x49, 0x88, 0xc9, 0x1b, 0x02, 0xab, 0x59, 0x80, 0x3d, 0x1c,
-0x00, 0x27, 0x01, 0x21, 0x49, 0x06, 0x07, 0x9b, 0x9a, 0x07, 0x92, 0x0f,
-0x0d, 0xd0, 0xeb, 0x06, 0xdb, 0x0e, 0x08, 0xd0, 0x1e, 0x2b, 0x08, 0xd3,
-0x1e, 0x2b, 0x02, 0xd1, 0x03, 0x2a, 0x04, 0xd1, 0x01, 0xe0, 0x02, 0x2a,
+0x71, 0x1a, 0x0a, 0x04, 0x12, 0x0c, 0x11, 0x02, 0x12, 0x0a, 0x11, 0x43,
+0x09, 0x04, 0x09, 0x0c, 0x02, 0x91, 0x01, 0x02, 0x00, 0x0a, 0x08, 0x43,
+0x01, 0x04, 0x09, 0x0c, 0x01, 0x98, 0xc0, 0x46, 0x41, 0x80, 0x20, 0x8e,
+0xfc, 0xf7, 0xcb, 0xfd, 0x06, 0x1c, 0x60, 0x8e, 0x02, 0x99, 0xfc, 0xf7,
+0xc6, 0xfd, 0x03, 0x90, 0x60, 0x69, 0x01, 0x04, 0x09, 0x0c, 0x08, 0x02,
+0x09, 0x0a, 0x08, 0x43, 0x01, 0x04, 0x09, 0x0c, 0x01, 0x98, 0xc0, 0x46,
+0x81, 0x80, 0x30, 0x1c, 0xfc, 0xf7, 0xb7, 0xfd, 0x61, 0x69, 0x01, 0x31,
+0xc0, 0x43, 0x61, 0x61, 0x01, 0x99, 0xc0, 0x46, 0x48, 0x81, 0x60, 0x6e,
+0x00, 0x99, 0x46, 0x18, 0x20, 0x69, 0x01, 0x0e, 0xff, 0x22, 0x12, 0x04,
+0x02, 0x40, 0x12, 0x0a, 0x11, 0x43, 0xff, 0x22, 0x12, 0x02, 0x02, 0x40,
+0x12, 0x02, 0x11, 0x43, 0x00, 0x06, 0x01, 0x43, 0x71, 0x60, 0x03, 0x98,
+0xfc, 0xf7, 0x9b, 0xfd, 0x21, 0x69, 0x49, 0x19, 0x21, 0x61, 0xa1, 0x68,
+0x49, 0x1b, 0xa1, 0x60, 0x06, 0xd1, 0xb1, 0x89, 0xa2, 0x69, 0x11, 0x43,
+0xb1, 0x81, 0xa1, 0x69, 0xfc, 0xf7, 0x8d, 0xfd, 0x38, 0x82, 0x61, 0x6e,
+0x38, 0x68, 0x09, 0x18, 0x0e, 0x31, 0xf9, 0x60, 0xe2, 0x68, 0x00, 0x99,
+0x04, 0x38, 0x00, 0xf0, 0x4c, 0xf8, 0x02, 0x20, 0x78, 0x82, 0xe0, 0x6d,
+0x41, 0x08, 0x16, 0xd3, 0x80, 0x0a, 0x0a, 0xd3, 0x78, 0x68, 0x10, 0x38,
+0x01, 0x04, 0x09, 0x0c, 0x08, 0x02, 0x09, 0x0a, 0x08, 0x43, 0x39, 0x68,
+0xc0, 0x46, 0xc8, 0x81, 0x09, 0xe0, 0x78, 0x68, 0x0c, 0x38, 0x01, 0x04,
+0x09, 0x0c, 0x08, 0x02, 0x09, 0x0a, 0x08, 0x43, 0x39, 0x68, 0xc0, 0x46,
+0x48, 0x81, 0x05, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00,
+0xd0, 0x2c, 0x00, 0x80, 0x5c, 0x2b, 0x00, 0x80, 0x0c, 0x2b, 0x00, 0x80,
+0xf7, 0xb5, 0x03, 0x1c, 0x0f, 0x1c, 0x00, 0x20, 0x1c, 0x68, 0x26, 0x04,
+0x31, 0x1c, 0x1d, 0x1d, 0xfc, 0xf7, 0x51, 0xfd, 0x40, 0xc7, 0x02, 0x9a,
+0xd1, 0x1c, 0x89, 0x08, 0x01, 0x39, 0x4a, 0x1e, 0x02, 0x92, 0x00, 0x29,
+0x0d, 0xd0, 0x21, 0x0c, 0x10, 0xcd, 0x22, 0x04, 0x0a, 0x43, 0x11, 0x1c,
+0x16, 0x1c, 0xfc, 0xf7, 0x40, 0xfd, 0x40, 0xc7, 0x02, 0x99, 0x4a, 0x1e,
+0x02, 0x92, 0x00, 0x29, 0xf1, 0xd1, 0x03, 0xb0, 0xf0, 0xbc, 0x08, 0xbc,
+0x18, 0x47, 0x80, 0x08, 0x80, 0x00, 0x89, 0x08, 0x89, 0x00, 0x03, 0x32,
+0x93, 0x08, 0x5a, 0x1e, 0x00, 0x2b, 0x05, 0xd0, 0x08, 0xc9, 0x08, 0xc0,
+0x13, 0x1c, 0x01, 0x3a, 0x00, 0x2b, 0xf9, 0xd1, 0x70, 0x47, 0xff, 0xb5,
+0x86, 0xb0, 0x17, 0x1c, 0x00, 0x26, 0x06, 0x98, 0x80, 0x6c, 0xc0, 0x1b,
+0x06, 0x99, 0xc0, 0x46, 0x88, 0x64, 0x01, 0x20, 0xc0, 0x05, 0x06, 0x99,
+0x89, 0x6b, 0xc0, 0x46, 0x01, 0x91, 0x06, 0x99, 0x4c, 0x6b, 0x67, 0xe0,
+0x21, 0x68, 0xc0, 0x46, 0x02, 0x91, 0x61, 0x68, 0xc0, 0x46, 0x03, 0x91,
+0xa1, 0x68, 0xc0, 0x46, 0x04, 0x91, 0x02, 0xa9, 0x49, 0x88, 0xb9, 0x42,
+0x08, 0xd2, 0x02, 0xad, 0x6d, 0x88, 0x02, 0xa9, 0x49, 0x88, 0x7f, 0x1a,
+0x00, 0x21, 0x02, 0xab, 0x59, 0x80, 0x19, 0xe0, 0x02, 0xa9, 0x49, 0x88,
+0xc9, 0x1b, 0x02, 0xab, 0x59, 0x80, 0x3d, 0x1c, 0x00, 0x27, 0x01, 0x21,
+0x49, 0x06, 0x07, 0x9b, 0x9a, 0x07, 0x92, 0x0f, 0x0d, 0xd0, 0xeb, 0x06,
+0xdb, 0x0e, 0x08, 0xd0, 0x1e, 0x2b, 0x08, 0xd3, 0x1e, 0x2b, 0x02, 0xd1,
+0x03, 0x2a, 0x04, 0xd1, 0x01, 0xe0, 0x02, 0x2a,
0x01, 0xd3, 0x01, 0x26, 0x00, 0x21, 0x29, 0x43, 0x01, 0x43, 0x0a, 0x1c,
-0x00, 0x91, 0x00, 0x20, 0x03, 0x99, 0x04, 0x9a,
-0x07, 0x9b, 0x01, 0xf0, 0x5b, 0xff, 0x07, 0x99, 0x49, 0x19, 0x07, 0x91,
-0x00, 0x2e, 0x0a, 0xd0, 0x1d, 0x4a, 0xc0, 0x46, 0x00, 0x92, 0x1d, 0x48,
-0x01, 0x6d, 0x42, 0x6d, 0x00, 0x20, 0x07, 0x9b, 0x01, 0xf0, 0x4c, 0xff,
-0x00, 0x26, 0x02, 0xa8, 0x40, 0x88, 0x00, 0x28, 0x0c, 0xd0, 0x03, 0x98,
-0x40, 0x19, 0x03, 0x90, 0x02, 0x98, 0xc0, 0x46, 0x20, 0x60, 0x03, 0x98,
-0xc0, 0x46, 0x60, 0x60, 0x04, 0x98, 0xc0, 0x46, 0xa0, 0x60, 0x03, 0xe0,
-0x01, 0x98, 0x01, 0x38, 0x01, 0x90, 0x10, 0x34, 0x06, 0x98, 0xc0, 0x46,
-0x44, 0x63, 0x01, 0x98, 0x06, 0x99, 0xc0, 0x46, 0x88, 0x63, 0x00, 0x20,
-0x00, 0x2f, 0x02, 0xd0, 0x01, 0x99, 0x00, 0x29, 0x92, 0xd1, 0x09, 0x4a,
-0xc0, 0x46, 0x00, 0x92, 0x06, 0x48, 0x01, 0x6d, 0x42, 0x6d, 0x00, 0x20,
-0x09, 0x9b, 0x01, 0xf0, 0x1f, 0xff, 0x0a, 0xb0, 0xf0, 0xbc, 0x08, 0xbc,
-0x18, 0x47, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x7c, 0x29, 0x00, 0x80,
-0x04, 0x00, 0x53, 0x02, 0x90, 0xb5, 0x0c, 0x1c, 0x07, 0x1c, 0x38, 0x68,
-0x01, 0x23, 0x9b, 0x07, 0x08, 0x38, 0x18, 0x43, 0x01, 0x68, 0x38, 0x8a,
-0xfc, 0xf7, 0x8f, 0xfc, 0xc0, 0x43, 0xf9, 0x68, 0xc0, 0x46, 0x08, 0x80,
-0x78, 0x8a, 0x39, 0x68, 0x08, 0x1a, 0x38, 0x60, 0x38, 0x1c, 0x01, 0xf0,
-0x8b, 0xf9, 0x38, 0x1c, 0xfc, 0xf7, 0x96, 0xfb, 0x20, 0x1c, 0xff, 0xf7,
-0x33, 0xfe, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x80, 0xb5, 0x01, 0x88,
-0x8a, 0x09, 0x21, 0xd3, 0xca, 0x09, 0x1f, 0xd2, 0x8a, 0x08, 0x1d, 0xd3,
-0x00, 0x21, 0x01, 0x80, 0x41, 0x80, 0x47, 0x6f, 0x40, 0x6d, 0xfa, 0x1d,
-0x19, 0x32, 0x51, 0x71, 0xfa, 0x6d, 0xc0, 0x46, 0x10, 0x60, 0x3a, 0x6e,
-0xc0, 0x46, 0x10, 0x60, 0x0c, 0x48, 0xc0, 0x46, 0x81, 0x63, 0xc1, 0x6b,
-0x49, 0x08, 0x49, 0x00, 0xc1, 0x63, 0x01, 0x20, 0x00, 0xf0, 0xcc, 0xff,
-0x38, 0x1c, 0x00, 0xf0, 0x6b, 0xff, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47,
-0x80, 0x23, 0x19, 0x43, 0x01, 0x80, 0x01, 0x88, 0x49, 0x09, 0xf6, 0xd2,
-0x00, 0xf0, 0xb0, 0xf8, 0xf3, 0xe7, 0x00, 0x00, 0xe8, 0x0e, 0x00, 0x80,
-0xf0, 0xb5, 0x07, 0x1c, 0x10, 0x1c, 0x0d, 0x1c, 0x00, 0x24, 0x5e, 0x1e,
-0x00, 0x2b, 0x19, 0xd0, 0x01, 0x68, 0xc0, 0x46, 0x39, 0x60, 0x41, 0x88,
-0x0c, 0x19, 0x41, 0x68, 0xc0, 0x46, 0x79, 0x60, 0x81, 0x68, 0xc0, 0x46,
-0xb9, 0x60, 0xc1, 0x68, 0xc0, 0x46, 0xf9, 0x60, 0x10, 0x30, 0x10, 0x37,
-0xe9, 0x6a, 0x81, 0x42, 0x02, 0xd8, 0x28, 0x1c, 0x00, 0xf0, 0xec, 0xff,
-0x31, 0x1c, 0x01, 0x3e, 0x00, 0x29, 0xe5, 0xd1, 0x20, 0x1c, 0xf0, 0xbc,
-0x08, 0xbc, 0x18, 0x47, 0x00, 0x21, 0xc1, 0x61, 0x05, 0x49, 0x0a, 0x68,
-0x00, 0x2a, 0x01, 0xd1, 0x08, 0x60, 0x02, 0xe0, 0x4a, 0x68, 0xc0, 0x46,
-0xd0, 0x61, 0x48, 0x60, 0x70, 0x47, 0x00, 0x00, 0xd0, 0x2c, 0x00, 0x80,
-0x03, 0x49, 0x08, 0x68, 0x00, 0x28, 0x02, 0xd0, 0xc2, 0x69, 0xc0, 0x46,
-0x0a, 0x60, 0x70, 0x47, 0xd0, 0x2c, 0x00, 0x80, 0x00, 0x21, 0x81, 0x67,
-0x05, 0x49, 0x8a, 0x68, 0x00, 0x2a, 0x01, 0xd1, 0x88, 0x60, 0x02, 0xe0,
-0xca, 0x68, 0xc0, 0x46, 0x90, 0x67, 0xc8, 0x60, 0x70, 0x47, 0x00, 0x00,
-0xd0, 0x2c, 0x00, 0x80, 0x03, 0x49, 0x88, 0x68, 0x00, 0x28, 0x02, 0xd0,
-0x82, 0x6f, 0xc0, 0x46, 0x8a, 0x60, 0x70, 0x47, 0xd0, 0x2c, 0x00, 0x80,
+0x00, 0x91, 0x00, 0x20, 0x03, 0x99, 0x04, 0x9a, 0x07, 0x9b, 0x01, 0xf0,
+0x5b, 0xff, 0x07, 0x99, 0x49, 0x19, 0x07, 0x91, 0x00, 0x2e, 0x0a, 0xd0,
+0x1d, 0x4a, 0xc0, 0x46, 0x00, 0x92, 0x1d, 0x48, 0x01, 0x6d, 0x42, 0x6d,
+0x00, 0x20, 0x07, 0x9b, 0x01, 0xf0, 0x4c, 0xff, 0x00, 0x26, 0x02, 0xa8,
+0x40, 0x88, 0x00, 0x28, 0x0c, 0xd0, 0x03, 0x98, 0x40, 0x19, 0x03, 0x90,
+0x02, 0x98, 0xc0, 0x46, 0x20, 0x60, 0x03, 0x98, 0xc0, 0x46, 0x60, 0x60,
+0x04, 0x98, 0xc0, 0x46, 0xa0, 0x60, 0x03, 0xe0, 0x01, 0x98, 0x01, 0x38,
+0x01, 0x90, 0x10, 0x34, 0x06, 0x98, 0xc0, 0x46, 0x44, 0x63, 0x01, 0x98,
+0x06, 0x99, 0xc0, 0x46, 0x88, 0x63, 0x00, 0x20, 0x00, 0x2f, 0x02, 0xd0,
+0x01, 0x99, 0x00, 0x29, 0x92, 0xd1, 0x09, 0x4a, 0xc0, 0x46, 0x00, 0x92,
+0x06, 0x48, 0x01, 0x6d, 0x42, 0x6d, 0x00, 0x20, 0x09, 0x9b, 0x01, 0xf0,
+0x1f, 0xff, 0x0a, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00,
+0x01, 0x00, 0x00, 0x02, 0x7c, 0x29, 0x00, 0x80, 0x04, 0x00, 0x53, 0x02,
+0x90, 0xb5, 0x0c, 0x1c, 0x07, 0x1c, 0x38, 0x68, 0x01, 0x23, 0x9b, 0x07,
+0x08, 0x38, 0x18, 0x43, 0x01, 0x68, 0x38, 0x8a, 0xfc, 0xf7, 0x85, 0xfc,
+0xc0, 0x43, 0xf9, 0x68, 0xc0, 0x46, 0x08, 0x80, 0x78, 0x8a, 0x39, 0x68,
+0x08, 0x1a, 0x38, 0x60, 0x38, 0x1c, 0x01, 0xf0, 0x8b, 0xf9, 0x38, 0x1c,
+0xfc, 0xf7, 0x8c, 0xfb, 0x20, 0x1c, 0xff, 0xf7, 0x33, 0xfe, 0x90, 0xbc,
+0x08, 0xbc, 0x18, 0x47, 0x80, 0xb5, 0x01, 0x88, 0x8a, 0x09, 0x21, 0xd3,
+0xca, 0x09, 0x1f, 0xd2, 0x8a, 0x08, 0x1d, 0xd3, 0x00, 0x21, 0x01, 0x80,
+0x41, 0x80, 0x47, 0x6f, 0x40, 0x6d, 0xfa, 0x1d, 0x19, 0x32, 0x51, 0x71,
+0xfa, 0x6d, 0xc0, 0x46, 0x10, 0x60, 0x3a, 0x6e, 0xc0, 0x46, 0x10, 0x60,
+0x0c, 0x48, 0xc0, 0x46, 0x81, 0x63, 0xc1, 0x6b, 0x49, 0x08, 0x49, 0x00,
+0xc1, 0x63, 0x01, 0x20, 0x00, 0xf0, 0xcc, 0xff, 0x38, 0x1c, 0x00, 0xf0,
+0x6b, 0xff, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x80, 0x23, 0x19, 0x43,
+0x01, 0x80, 0x01, 0x88, 0x49, 0x09, 0xf6, 0xd2, 0x00, 0xf0, 0xb0, 0xf8,
+0xf3, 0xe7, 0x00, 0x00, 0xe8, 0x0e, 0x00, 0x80, 0xf0, 0xb5, 0x07, 0x1c,
+0x10, 0x1c, 0x0d, 0x1c, 0x00, 0x24, 0x5e, 0x1e, 0x00, 0x2b, 0x19, 0xd0,
+0x01, 0x68, 0xc0, 0x46, 0x39, 0x60, 0x41, 0x88, 0x0c, 0x19, 0x41, 0x68,
+0xc0, 0x46, 0x79, 0x60, 0x81, 0x68, 0xc0, 0x46, 0xb9, 0x60, 0xc1, 0x68,
+0xc0, 0x46, 0xf9, 0x60, 0x10, 0x30, 0x10, 0x37, 0xe9, 0x6a, 0x81, 0x42,
+0x02, 0xd8, 0x28, 0x1c, 0x00, 0xf0, 0xec, 0xff, 0x31, 0x1c, 0x01, 0x3e,
+0x00, 0x29, 0xe5, 0xd1, 0x20, 0x1c, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47,
+0x00, 0x21, 0xc1, 0x61, 0x05, 0x49, 0x0a, 0x68, 0x00, 0x2a, 0x01, 0xd1,
+0x08, 0x60, 0x02, 0xe0, 0x4a, 0x68, 0xc0, 0x46, 0xd0, 0x61, 0x48, 0x60,
+0x70, 0x47, 0x00, 0x00, 0xd0, 0x2c, 0x00, 0x80, 0x03, 0x49, 0x08, 0x68,
+0x00, 0x28, 0x02, 0xd0, 0xc2, 0x69, 0xc0, 0x46, 0x0a, 0x60, 0x70, 0x47,
+0xd0, 0x2c, 0x00, 0x80, 0x00, 0x21, 0x81, 0x67, 0x05, 0x49, 0x8a, 0x68,
+0x00, 0x2a, 0x01, 0xd1, 0x88, 0x60, 0x02, 0xe0, 0xca, 0x68, 0xc0, 0x46,
+0x90, 0x67, 0xc8, 0x60, 0x70, 0x47, 0x00, 0x00, 0xd0, 0x2c, 0x00, 0x80,
+0x03, 0x49, 0x88, 0x68, 0x00, 0x28, 0x02, 0xd0, 0x82, 0x6f, 0xc0, 0x46,
+0x8a, 0x60, 0x70, 0x47, 0xd0, 0x2c, 0x00, 0x80,
0x00, 0xb5, 0x80, 0x20, 0x13, 0x49, 0xc0, 0x46, 0x08, 0x60, 0xff, 0xf7,
-0xd5, 0xff, 0x00, 0x28, 0x1b, 0xd0, 0x03, 0x23,
-0x1b, 0x07, 0x41, 0x68, 0x19, 0x40, 0x0a, 0x0f, 0x51, 0x01, 0x89, 0x1a,
-0x89, 0x00, 0x0d, 0x4b, 0xc9, 0x18, 0x4b, 0x88, 0x00, 0x2b, 0x04, 0xd1,
-0x11, 0x1c, 0xff, 0xf7, 0x3b, 0xff, 0x08, 0xbc, 0x18, 0x47, 0x01, 0x2b,
-0x02, 0xd1, 0xff, 0xf7, 0x05, 0xfc, 0xf8, 0xe7, 0x02, 0x2b, 0xf6, 0xd1,
-0xff, 0xf7, 0x4e, 0xfb, 0xf3, 0xe7, 0x04, 0x48, 0x01, 0x6d, 0x01, 0x31,
-0x01, 0x65, 0xee, 0xe7, 0x00, 0x00, 0x00, 0xb0, 0x5c, 0x2b, 0x00, 0x80,
-0xa0, 0x82, 0x20, 0x40, 0x00, 0xb5, 0x20, 0x20, 0x0d, 0x49, 0xc0, 0x46,
-0x08, 0x60, 0xff, 0xf7, 0xbf, 0xff, 0x00, 0x28, 0x0e, 0xd0, 0x01, 0x88,
-0x20, 0x23, 0x19, 0x43, 0x01, 0x80, 0x01, 0x88, 0x10, 0x23, 0x99, 0x43,
-0x01, 0x80, 0x01, 0x88, 0x09, 0x0a, 0x01, 0xd3, 0xff, 0xf7, 0x2e, 0xff,
-0x08, 0xbc, 0x18, 0x47, 0x03, 0x48, 0x01, 0x6d, 0x01, 0x31, 0x01, 0x65,
-0xf8, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0xa0, 0x82, 0x20, 0x40,
-0x98, 0xb5, 0x07, 0x1c, 0x22, 0x48, 0xc0, 0x46, 0x00, 0x90, 0x22, 0x48,
-0xc3, 0x1d, 0x41, 0x33, 0x41, 0x6d, 0x82, 0x6d, 0x80, 0x6c, 0x00, 0x03,
-0x00, 0x0b, 0x9c, 0x68, 0x01, 0x23, 0x9b, 0x07, 0x23, 0x43, 0x1b, 0x68,
-0x98, 0x42, 0x00, 0xd1, 0x0c, 0xe0, 0x98, 0x42, 0x03, 0xd9, 0x10, 0x1a,
-0x59, 0x1a, 0x41, 0x18, 0x00, 0xe0, 0x19, 0x1a, 0x01, 0x20, 0x10, 0x29,
-0x00, 0xd8, 0x00, 0x20, 0x00, 0x28, 0x1f, 0xd0, 0x78, 0x6a, 0xf9, 0x6a,
-0xc0, 0x46, 0x08, 0x60, 0xb8, 0x6a, 0xf9, 0x6a, 0xc0, 0x46, 0x48, 0x60,
-0x10, 0x4a, 0xc0, 0x46, 0x00, 0x92, 0xfb, 0x6a, 0x0f, 0x48, 0x42, 0x6d,
-0x03, 0x20, 0x39, 0x6a, 0x01, 0xf0, 0xe2, 0xfd, 0x38, 0x88, 0x10, 0x23,
-0x18, 0x43, 0x38, 0x80, 0x38, 0x88, 0x40, 0x23, 0x98, 0x43, 0x38, 0x80,
-0x38, 0x1c, 0xff, 0xf7, 0x55, 0xff, 0x98, 0xbc, 0x08, 0xbc, 0x18, 0x47,
-0x38, 0x88, 0x40, 0x23, 0x18, 0x43, 0x38, 0x80, 0xf7, 0xe7, 0x00, 0x00,
-0x55, 0x55, 0x55, 0x55, 0xa8, 0x03, 0x00, 0x80, 0x08, 0x00, 0x11, 0x02,
-0x7c, 0x29, 0x00, 0x80, 0xb0, 0xb5, 0x40, 0x20, 0x2c, 0x49, 0xc0, 0x46,
-0x08, 0x60, 0x00, 0xf0, 0xfd, 0xfe, 0x07, 0x1c, 0x40, 0x68, 0x03, 0x23,
-0x1b, 0x07, 0x18, 0x40, 0x05, 0x0f, 0x68, 0x01, 0x40, 0x1b, 0x80, 0x00,
-0x26, 0x49, 0x44, 0x18, 0x20, 0x88, 0x02, 0x23, 0x18, 0x43, 0x20, 0x80,
-0x20, 0x88, 0x41, 0x08, 0x34, 0xd3, 0x40, 0x08, 0x40, 0x00, 0x20, 0x80,
-0xa0, 0x6c, 0xe1, 0x6c, 0x40, 0x18, 0xa0, 0x64, 0x00, 0x20, 0xe0, 0x64,
-0xa1, 0x6b, 0x22, 0x6d, 0x89, 0x18, 0xa1, 0x63, 0x20, 0x65, 0xb8, 0x6a,
-0xc0, 0x46, 0x60, 0x65, 0x03, 0x23, 0x1b, 0x07, 0x78, 0x68, 0x18, 0x40,
-0x78, 0x60, 0x61, 0x68, 0x36, 0x31, 0x94, 0x29, 0x04, 0xd8, 0x38, 0x23,
-0x18, 0x43, 0x78, 0x60, 0x38, 0x20, 0x03, 0xe0, 0x94, 0x23, 0x18, 0x43,
-0x78, 0x60, 0x94, 0x20, 0xb8, 0x61, 0x39, 0x68, 0x78, 0x68, 0x02, 0x04,
-0x12, 0x0c, 0x20, 0x1c, 0xcb, 0x1f, 0x05, 0x3b, 0xff, 0xf7, 0xd7, 0xfd,
-0x02, 0x20, 0x60, 0x80, 0x38, 0x1c, 0xff, 0xf7, 0xdf, 0xfe, 0xb0, 0xbc,
-0x08, 0xbc, 0x18, 0x47, 0x38, 0x1c, 0xfc, 0xf7, 0x11, 0xfa, 0x28, 0x01,
-0x06, 0x49, 0x40, 0x18, 0x19, 0x23, 0xdb, 0x01, 0xc0, 0x18, 0x41, 0x6b,
-0x01, 0x39, 0x41, 0x63, 0xef, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0,
+0xd5, 0xff, 0x00, 0x28, 0x1b, 0xd0, 0x03, 0x23, 0x1b, 0x07, 0x41, 0x68,
+0x19, 0x40, 0x0a, 0x0f, 0x51, 0x01, 0x89, 0x1a, 0x89, 0x00, 0x0d, 0x4b,
+0xc9, 0x18, 0x4b, 0x88, 0x00, 0x2b, 0x04, 0xd1, 0x11, 0x1c, 0xff, 0xf7,
+0x3b, 0xff, 0x08, 0xbc, 0x18, 0x47, 0x01, 0x2b, 0x02, 0xd1, 0xff, 0xf7,
+0x05, 0xfc, 0xf8, 0xe7, 0x02, 0x2b, 0xf6, 0xd1, 0xff, 0xf7, 0x4e, 0xfb,
+0xf3, 0xe7, 0x04, 0x48, 0x01, 0x6d, 0x01, 0x31, 0x01, 0x65, 0xee, 0xe7,
+0x00, 0x00, 0x00, 0xb0, 0x5c, 0x2b, 0x00, 0x80, 0xa0, 0x82, 0x20, 0x40,
+0x00, 0xb5, 0x20, 0x20, 0x0d, 0x49, 0xc0, 0x46, 0x08, 0x60, 0xff, 0xf7,
+0xbf, 0xff, 0x00, 0x28, 0x0e, 0xd0, 0x01, 0x88, 0x20, 0x23, 0x19, 0x43,
+0x01, 0x80, 0x01, 0x88, 0x10, 0x23, 0x99, 0x43, 0x01, 0x80, 0x01, 0x88,
+0x09, 0x0a, 0x01, 0xd3, 0xff, 0xf7, 0x2e, 0xff, 0x08, 0xbc, 0x18, 0x47,
+0x03, 0x48, 0x01, 0x6d, 0x01, 0x31, 0x01, 0x65, 0xf8, 0xe7, 0x00, 0x00,
+0x00, 0x00, 0x00, 0xb0, 0xa0, 0x82, 0x20, 0x40, 0x98, 0xb5, 0x07, 0x1c,
+0x22, 0x48, 0xc0, 0x46, 0x00, 0x90, 0x22, 0x48, 0xc3, 0x1d, 0x41, 0x33,
+0x41, 0x6d, 0x82, 0x6d, 0x80, 0x6c, 0x00, 0x03, 0x00, 0x0b, 0x9c, 0x68,
+0x01, 0x23, 0x9b, 0x07, 0x23, 0x43, 0x1b, 0x68, 0x98, 0x42, 0x00, 0xd1,
+0x0c, 0xe0, 0x98, 0x42, 0x03, 0xd9, 0x10, 0x1a, 0x59, 0x1a, 0x41, 0x18,
+0x00, 0xe0, 0x19, 0x1a, 0x01, 0x20, 0x10, 0x29, 0x00, 0xd8, 0x00, 0x20,
+0x00, 0x28, 0x1f, 0xd0, 0x78, 0x6a, 0xf9, 0x6a, 0xc0, 0x46, 0x08, 0x60,
+0xb8, 0x6a, 0xf9, 0x6a, 0xc0, 0x46, 0x48, 0x60, 0x10, 0x4a, 0xc0, 0x46,
+0x00, 0x92, 0xfb, 0x6a, 0x0f, 0x48, 0x42, 0x6d, 0x03, 0x20, 0x39, 0x6a,
+0x01, 0xf0, 0xe2, 0xfd, 0x38, 0x88, 0x10, 0x23, 0x18, 0x43, 0x38, 0x80,
+0x38, 0x88, 0x40, 0x23, 0x98, 0x43, 0x38, 0x80, 0x38, 0x1c, 0xff, 0xf7,
+0x55, 0xff, 0x98, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x38, 0x88, 0x40, 0x23,
+0x18, 0x43, 0x38, 0x80, 0xf7, 0xe7, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55,
+0xa8, 0x03, 0x00, 0x80, 0x08, 0x00, 0x11, 0x02, 0x7c, 0x29, 0x00, 0x80,
+0xb0, 0xb5, 0x40, 0x20, 0x2c, 0x49, 0xc0, 0x46, 0x08, 0x60, 0x00, 0xf0,
+0xfd, 0xfe, 0x07, 0x1c, 0x40, 0x68, 0x03, 0x23, 0x1b, 0x07, 0x18, 0x40,
+0x05, 0x0f, 0x68, 0x01, 0x40, 0x1b, 0x80, 0x00, 0x26, 0x49, 0x44, 0x18,
+0x20, 0x88, 0x02, 0x23, 0x18, 0x43, 0x20, 0x80, 0x20, 0x88, 0x41, 0x08,
+0x34, 0xd3, 0x40, 0x08, 0x40, 0x00, 0x20, 0x80, 0xa0, 0x6c, 0xe1, 0x6c,
+0x40, 0x18, 0xa0, 0x64, 0x00, 0x20, 0xe0, 0x64, 0xa1, 0x6b, 0x22, 0x6d,
+0x89, 0x18, 0xa1, 0x63, 0x20, 0x65, 0xb8, 0x6a, 0xc0, 0x46, 0x60, 0x65,
+0x03, 0x23, 0x1b, 0x07, 0x78, 0x68, 0x18, 0x40, 0x78, 0x60, 0x61, 0x68,
+0x36, 0x31, 0x94, 0x29, 0x04, 0xd8, 0x38, 0x23, 0x18, 0x43, 0x78, 0x60,
+0x38, 0x20, 0x03, 0xe0, 0x94, 0x23, 0x18, 0x43, 0x78, 0x60, 0x94, 0x20,
+0xb8, 0x61, 0x39, 0x68, 0x78, 0x68, 0x02, 0x04, 0x12, 0x0c, 0x20, 0x1c,
+0xcb, 0x1f, 0x05, 0x3b, 0xff, 0xf7, 0xd7, 0xfd, 0x02, 0x20, 0x60, 0x80,
+0x38, 0x1c, 0xff, 0xf7, 0xdf, 0xfe, 0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47,
+0x38, 0x1c, 0xfc, 0xf7, 0x07, 0xfa, 0x28, 0x01, 0x06, 0x49, 0x40, 0x18,
+0x19, 0x23, 0xdb, 0x01, 0xc0, 0x18, 0x41, 0x6b, 0x01, 0x39, 0x41, 0x63,
+0xef, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0,
0x5c, 0x2b, 0x00, 0x80, 0xa0, 0x1c, 0x00, 0x80, 0x90, 0xb5, 0x00, 0x27,
-0x0f, 0x4c, 0x0d, 0xe0, 0x42, 0x6b, 0x01, 0x3a,
-0x42, 0x63, 0x00, 0x2a, 0x05, 0xdc, 0x02, 0x6b, 0xc0, 0x46, 0x42, 0x63,
-0xc0, 0x6a, 0x01, 0xf0, 0xc6, 0xf9, 0x01, 0x37, 0x0b, 0x2f, 0x07, 0xd2,
-0x38, 0x01, 0x00, 0x19, 0x33, 0x23, 0x9b, 0x01, 0xc0, 0x18, 0x81, 0x6a,
-0x00, 0x29, 0xe9, 0xd1, 0x01, 0x20, 0x40, 0x06, 0x03, 0x49, 0xc0, 0x46,
-0x08, 0x60, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x68, 0x0e, 0x00, 0x80,
-0x00, 0x00, 0x00, 0xb0, 0x10, 0x48, 0xc1, 0x68, 0x01, 0x31, 0xc1, 0x60,
-0x0f, 0x49, 0xc8, 0x68, 0x01, 0x28, 0x17, 0xd1, 0xc8, 0x1d, 0x79, 0x30,
-0x02, 0x89, 0x00, 0x2a, 0x12, 0xd0, 0x01, 0x3a, 0x02, 0x81, 0x02, 0x89,
-0x00, 0x2a, 0x0d, 0xd1, 0x42, 0x89, 0x00, 0x2a, 0x08, 0xd1, 0xc9, 0x6f,
-0x02, 0x23, 0x0a, 0x68, 0x1a, 0x43, 0x0a, 0x60, 0x04, 0x21, 0x01, 0x81,
-0x01, 0x21, 0x00, 0xe0, 0x00, 0x21, 0x41, 0x81, 0x70, 0x47, 0x00, 0x00,
-0x08, 0x83, 0x20, 0x40, 0x68, 0x0e, 0x00, 0x80, 0xb0, 0xb5, 0x07, 0x1c,
-0x01, 0x23, 0xf8, 0x1d, 0x69, 0x30, 0x03, 0x73, 0x1e, 0x48, 0xc2, 0x1d,
-0x79, 0x32, 0x54, 0x8a, 0x61, 0x1c, 0x51, 0x82, 0xd5, 0x8a, 0x00, 0x21,
-0xac, 0x42, 0x04, 0xdb, 0xc4, 0x1d, 0x89, 0x34, 0x63, 0x70, 0x51, 0x82,
-0xd1, 0x83, 0x01, 0x23, 0x9b, 0x07, 0x3a, 0x6d, 0x1a, 0x43, 0x12, 0x68,
-0xc0, 0x46, 0xba, 0x61, 0xfb, 0x69, 0x9a, 0x42, 0x06, 0xd1, 0xf8, 0x6c,
-0x12, 0x49, 0xc0, 0x46, 0x08, 0x60, 0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47,
-0x79, 0x61, 0x41, 0x69, 0xfa, 0x6c, 0x91, 0x43, 0x41, 0x61, 0x01, 0x20,
-0x00, 0x05, 0xc1, 0x60, 0x38, 0x69, 0x02, 0x28, 0xf1, 0xd0, 0xb8, 0x69,
-0xf9, 0x69, 0x41, 0x1a, 0x01, 0xd5, 0x78, 0x6d, 0x41, 0x18, 0x38, 0x1c,
-0x00, 0xf0, 0x0e, 0xf8, 0xf9, 0x69, 0x09, 0x18, 0xf9, 0x61, 0x78, 0x6d,
-0x81, 0x42, 0xe2, 0xd3, 0x08, 0x1a, 0xf8, 0x61, 0xdf, 0xe7, 0x00, 0x00,
-0x68, 0x0e, 0x00, 0x80, 0x00, 0x00, 0x00, 0xb0, 0xf8, 0xb5, 0x04, 0x1c,
-0x0f, 0x1c, 0xff, 0x23, 0x21, 0x33, 0x9f, 0x42, 0x01, 0xd9, 0xff, 0x27,
-0x21, 0x37, 0xe1, 0x6e, 0x38, 0x1c, 0x01, 0xf0, 0xcb, 0xfc, 0x2d, 0x4d,
-0x00, 0x28, 0x13, 0xd1, 0xe0, 0x1d, 0x49, 0x30, 0x01, 0x7a, 0x01, 0x23,
-0x19, 0x43, 0x01, 0x72, 0x29, 0x4a, 0xc0, 0x46, 0x00, 0x92, 0x29, 0x48,
-0x01, 0x6d, 0x42, 0x6d, 0x00, 0x20, 0x2b, 0x1c, 0x01, 0xf0, 0xb0, 0xfc,
-0x00, 0x20, 0xf8, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x20, 0x69, 0x01, 0x30,
-0x20, 0x61, 0x23, 0x49, 0xc8, 0x1d, 0xb9, 0x30, 0x02, 0x6b, 0x92, 0x00,
-0x51, 0x18, 0xc0, 0x31, 0x0f, 0x61, 0x01, 0x6b, 0x01, 0x31, 0x89, 0x07,
-0x89, 0x0f, 0x01, 0x63, 0x20, 0x6b, 0xc2, 0x19, 0x61, 0x6d, 0x8a, 0x42,
-0x03, 0xd8, 0x23, 0x22, 0x12, 0x05, 0x3a, 0x43, 0x05, 0xe0, 0x09, 0x1a,
-0x7e, 0x1a, 0x07, 0xd1, 0x23, 0x22, 0x12, 0x05, 0x0a, 0x43, 0x00, 0x92,
-0x61, 0x6e, 0x09, 0x18, 0xa2, 0x6e, 0x10, 0xe0, 0x11, 0x22, 0x52, 0x05,
-0x0a, 0x43, 0x00, 0x92, 0x61, 0x6e, 0x09, 0x18, 0x00, 0x20, 0xa2, 0x6e,
-0x2b, 0x1c, 0x01, 0xf0, 0x7d, 0xfc, 0x23, 0x22, 0x12, 0x05, 0x32, 0x43,
-0x00, 0x92, 0x61, 0x6e, 0xa2, 0x6e, 0x00, 0x20, 0x2b, 0x1c, 0x01, 0xf0,
-0x73, 0xfc, 0x20, 0x6b, 0xc0, 0x19, 0x00, 0x09, 0x00, 0x01, 0x61, 0x6d,
-0x81, 0x42, 0x00, 0xd8, 0x40, 0x1a, 0x20, 0x63, 0x38, 0x1c, 0xb8, 0xe7,
+0x0f, 0x4c, 0x0d, 0xe0, 0x42, 0x6b, 0x01, 0x3a, 0x42, 0x63, 0x00, 0x2a,
+0x05, 0xdc, 0x02, 0x6b, 0xc0, 0x46, 0x42, 0x63, 0xc0, 0x6a, 0x01, 0xf0,
+0xc6, 0xf9, 0x01, 0x37, 0x0b, 0x2f, 0x07, 0xd2, 0x38, 0x01, 0x00, 0x19,
+0x33, 0x23, 0x9b, 0x01, 0xc0, 0x18, 0x81, 0x6a, 0x00, 0x29, 0xe9, 0xd1,
+0x01, 0x20, 0x40, 0x06, 0x03, 0x49, 0xc0, 0x46, 0x08, 0x60, 0x90, 0xbc,
+0x08, 0xbc, 0x18, 0x47, 0x68, 0x0e, 0x00, 0x80, 0x00, 0x00, 0x00, 0xb0,
+0x10, 0x48, 0xc1, 0x68, 0x01, 0x31, 0xc1, 0x60, 0x0f, 0x49, 0xc8, 0x68,
+0x01, 0x28, 0x17, 0xd1, 0xc8, 0x1d, 0x79, 0x30, 0x02, 0x89, 0x00, 0x2a,
+0x12, 0xd0, 0x01, 0x3a, 0x02, 0x81, 0x02, 0x89, 0x00, 0x2a, 0x0d, 0xd1,
+0x42, 0x89, 0x00, 0x2a, 0x08, 0xd1, 0xc9, 0x6f, 0x02, 0x23, 0x0a, 0x68,
+0x1a, 0x43, 0x0a, 0x60, 0x04, 0x21, 0x01, 0x81, 0x01, 0x21, 0x00, 0xe0,
+0x00, 0x21, 0x41, 0x81, 0x70, 0x47, 0x00, 0x00, 0x08, 0x83, 0x20, 0x40,
+0x68, 0x0e, 0x00, 0x80, 0xb0, 0xb5, 0x07, 0x1c, 0x01, 0x23, 0xf8, 0x1d,
+0x69, 0x30, 0x03, 0x73, 0x1e, 0x48, 0xc2, 0x1d, 0x79, 0x32, 0x54, 0x8a,
+0x61, 0x1c, 0x51, 0x82, 0xd5, 0x8a, 0x00, 0x21, 0xac, 0x42, 0x04, 0xdb,
+0xc4, 0x1d, 0x89, 0x34, 0x63, 0x70, 0x51, 0x82, 0xd1, 0x83, 0x01, 0x23,
+0x9b, 0x07, 0x3a, 0x6d, 0x1a, 0x43, 0x12, 0x68, 0xc0, 0x46, 0xba, 0x61,
+0xfb, 0x69, 0x9a, 0x42, 0x06, 0xd1, 0xf8, 0x6c, 0x12, 0x49, 0xc0, 0x46,
+0x08, 0x60, 0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x79, 0x61, 0x41, 0x69,
+0xfa, 0x6c, 0x91, 0x43, 0x41, 0x61, 0x01, 0x20, 0x00, 0x05, 0xc1, 0x60,
+0x38, 0x69, 0x02, 0x28, 0xf1, 0xd0, 0xb8, 0x69, 0xf9, 0x69, 0x41, 0x1a,
+0x01, 0xd5, 0x78, 0x6d, 0x41, 0x18, 0x38, 0x1c, 0x00, 0xf0, 0x0e, 0xf8,
+0xf9, 0x69, 0x09, 0x18, 0xf9, 0x61, 0x78, 0x6d, 0x81, 0x42, 0xe2, 0xd3,
+0x08, 0x1a, 0xf8, 0x61, 0xdf, 0xe7, 0x00, 0x00, 0x68, 0x0e, 0x00, 0x80,
+0x00, 0x00, 0x00, 0xb0, 0xf8, 0xb5, 0x04, 0x1c, 0x0f, 0x1c, 0xff, 0x23,
+0x21, 0x33, 0x9f, 0x42, 0x01, 0xd9, 0xff, 0x27, 0x21, 0x37, 0xe1, 0x6e,
+0x38, 0x1c, 0x01, 0xf0, 0xcb, 0xfc, 0x2d, 0x4d, 0x00, 0x28, 0x13, 0xd1,
+0xe0, 0x1d, 0x49, 0x30, 0x01, 0x7a, 0x01, 0x23, 0x19, 0x43, 0x01, 0x72,
+0x29, 0x4a, 0xc0, 0x46, 0x00, 0x92, 0x29, 0x48, 0x01, 0x6d, 0x42, 0x6d,
+0x00, 0x20, 0x2b, 0x1c, 0x01, 0xf0, 0xb0, 0xfc, 0x00, 0x20, 0xf8, 0xbc,
+0x08, 0xbc, 0x18, 0x47, 0x20, 0x69, 0x01, 0x30, 0x20, 0x61, 0x23, 0x49,
+0xc8, 0x1d, 0xb9, 0x30, 0x02, 0x6b, 0x92, 0x00, 0x51, 0x18, 0xc0, 0x31,
+0x0f, 0x61, 0x01, 0x6b, 0x01, 0x31, 0x89, 0x07, 0x89, 0x0f, 0x01, 0x63,
+0x20, 0x6b, 0xc2, 0x19, 0x61, 0x6d, 0x8a, 0x42, 0x03, 0xd8, 0x23, 0x22,
+0x12, 0x05, 0x3a, 0x43, 0x05, 0xe0, 0x09, 0x1a, 0x7e, 0x1a, 0x07, 0xd1,
+0x23, 0x22, 0x12, 0x05, 0x0a, 0x43, 0x00, 0x92, 0x61, 0x6e, 0x09, 0x18,
+0xa2, 0x6e, 0x10, 0xe0, 0x11, 0x22, 0x52, 0x05, 0x0a, 0x43, 0x00, 0x92,
+0x61, 0x6e, 0x09, 0x18, 0x00, 0x20, 0xa2, 0x6e, 0x2b, 0x1c, 0x01, 0xf0,
+0x7d, 0xfc, 0x23, 0x22, 0x12, 0x05, 0x32, 0x43, 0x00, 0x92, 0x61, 0x6e,
+0xa2, 0x6e, 0x00, 0x20, 0x2b, 0x1c, 0x01, 0xf0, 0x73, 0xfc, 0x20, 0x6b,
+0xc0, 0x19, 0x00, 0x09, 0x00, 0x01, 0x61, 0x6d, 0x81, 0x42, 0x00, 0xd8,
+0x40, 0x1a, 0x20, 0x63, 0x38, 0x1c, 0xb8, 0xe7,
0x44, 0x80, 0x20, 0x40, 0x04, 0x00, 0x1b, 0x02, 0x7c, 0x29, 0x00, 0x80,
-0x68, 0x0e, 0x00, 0x80, 0x80, 0xb5, 0x01, 0x20,
-0xc0, 0x03, 0x0d, 0x49, 0xc0, 0x46, 0x08, 0x60, 0x0c, 0x49, 0xc8, 0x1d,
-0x49, 0x30, 0x02, 0x7a, 0x00, 0x27, 0x00, 0x2a, 0x03, 0xd0, 0x07, 0x72,
-0x08, 0x1c, 0xff, 0xf7, 0x37, 0xff, 0x08, 0x49, 0xc8, 0x1d, 0x49, 0x30,
-0x02, 0x7a, 0x00, 0x2a, 0x03, 0xd0, 0x07, 0x72, 0x08, 0x1c, 0xff, 0xf7,
-0x2d, 0xff, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x00, 0xb0,
-0x64, 0x2d, 0x00, 0x80, 0xe4, 0x2c, 0x00, 0x80, 0x90, 0xb5, 0x07, 0x1c,
-0x10, 0x20, 0x18, 0x49, 0xc0, 0x46, 0x08, 0x60, 0xf8, 0x68, 0x01, 0x30,
-0xf8, 0x60, 0x16, 0x48, 0xc4, 0x1d, 0xb9, 0x34, 0x61, 0x6b, 0x89, 0x00,
-0x09, 0x18, 0xc0, 0x31, 0x09, 0x69, 0x7a, 0x68, 0x92, 0x00, 0xd2, 0x19,
-0x51, 0x64, 0x61, 0x6b, 0x89, 0x00, 0x08, 0x18, 0xc0, 0x30, 0x01, 0x69,
-0x78, 0x68, 0x80, 0x00, 0xc0, 0x19, 0xc0, 0x6b, 0x01, 0xf0, 0xa2, 0xfa,
-0x01, 0x23, 0x78, 0x68, 0x58, 0x40, 0x78, 0x60, 0x60, 0x6b, 0x01, 0x30,
-0x80, 0x07, 0x80, 0x0f, 0x60, 0x63, 0xf8, 0x1d, 0x19, 0x30, 0x40, 0x79,
-0x00, 0x28, 0x02, 0xd1, 0x38, 0x1c, 0x00, 0xf0, 0x07, 0xf8, 0x90, 0xbc,
-0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x00, 0xb0, 0x68, 0x0e, 0x00, 0x80,
-0x90, 0xb5, 0x07, 0x1c, 0x39, 0x48, 0xc0, 0x68, 0x00, 0x28, 0x05, 0xd0,
-0xb8, 0x6a, 0xc0, 0x68, 0x80, 0x09, 0x01, 0xd3, 0x02, 0x20, 0x00, 0xe0,
-0x78, 0x6f, 0xfc, 0xf7, 0x63, 0xf8, 0x04, 0x1c, 0x06, 0xd1, 0x01, 0x20,
-0xf9, 0x1d, 0x19, 0x31, 0x08, 0x71, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47,
-0xf8, 0x6c, 0x2f, 0x49, 0xc0, 0x46, 0x08, 0x60, 0xba, 0x6a, 0x38, 0x1c,
-0x21, 0x1c, 0x00, 0xf0, 0x59, 0xf8, 0x67, 0x62, 0x00, 0x28, 0x03, 0xd1,
-0x20, 0x1c, 0x00, 0xf0, 0x0b, 0xfd, 0xec, 0xe7, 0xf9, 0x6d, 0x09, 0x68,
-0x09, 0x18, 0x09, 0x09, 0x09, 0x01, 0x7a, 0x6d, 0x8a, 0x42, 0x00, 0xd8,
-0x89, 0x1a, 0xa1, 0x62, 0xb9, 0x68, 0x89, 0x00, 0xc9, 0x19, 0x4a, 0x6c,
-0x00, 0x2a, 0x07, 0xd0, 0x4a, 0x6c, 0x12, 0x1a, 0x4a, 0x64, 0x80, 0x08,
-0x80, 0x00, 0xb9, 0x6a, 0x08, 0x18, 0xb8, 0x62, 0x38, 0x68, 0xb9, 0x6a,
-0x80, 0x00, 0xc0, 0x19, 0x42, 0x6b, 0x91, 0x42, 0x0e, 0xd3, 0x00, 0x21,
-0x41, 0x64, 0xb8, 0x6a, 0x39, 0x68, 0x89, 0x00, 0xc9, 0x19, 0x49, 0x6b,
-0x40, 0x1a, 0xb8, 0x62, 0xb9, 0x68, 0x89, 0x00, 0xc9, 0x19, 0xc9, 0x6b,
-0x40, 0x18, 0xb8, 0x62, 0xb8, 0x68, 0x81, 0x00, 0xc9, 0x19, 0x49, 0x6c,
-0x00, 0x29, 0xb8, 0xd1, 0xb9, 0x6a, 0xfa, 0x6b, 0x91, 0x42, 0xb4, 0xd0,
-0x3a, 0x6c, 0x91, 0x42, 0xb1, 0xd0, 0x01, 0x23, 0x58, 0x40, 0xb8, 0x60,
-0x80, 0x00, 0xc0, 0x19, 0xc0, 0x6b, 0xc0, 0x46, 0xb8, 0x62, 0xf8, 0x68,
-0x00, 0x28, 0x01, 0xd0, 0x01, 0x38, 0xf8, 0x60, 0x38, 0x69, 0x00, 0x28,
-0xa1, 0xd0, 0x01, 0x38, 0x38, 0x61, 0x9e, 0xe7, 0x68, 0x19, 0x00, 0x80,
-0x00, 0x00, 0x00, 0xb0, 0xf7, 0xb5, 0x90, 0xb0, 0x04, 0x1c, 0x0d, 0x1c,
-0x00, 0x20, 0x05, 0x90, 0x02, 0x90, 0x00, 0x22, 0x01, 0x92, 0xf9, 0x48,
-0xc0, 0x6a, 0xc0, 0x46, 0xa8, 0x61, 0xa0, 0x68, 0x81, 0x00, 0x09, 0x19,
-0x49, 0x6b, 0xc0, 0x46, 0x20, 0x60, 0xe1, 0x62, 0x12, 0x9a, 0xd0, 0x68,
-0xc0, 0x46, 0xa8, 0x60, 0x12, 0x9a, 0x51, 0x78, 0xc0, 0x46, 0x0c, 0x91,
-0xf0, 0x48, 0xc0, 0x46, 0x03, 0x90, 0xd7, 0x1d, 0x09, 0x37, 0xe0, 0x6a,
+0x68, 0x0e, 0x00, 0x80, 0x80, 0xb5, 0x01, 0x20, 0xc0, 0x03, 0x0d, 0x49,
+0xc0, 0x46, 0x08, 0x60, 0x0c, 0x49, 0xc8, 0x1d, 0x49, 0x30, 0x02, 0x7a,
+0x00, 0x27, 0x00, 0x2a, 0x03, 0xd0, 0x07, 0x72, 0x08, 0x1c, 0xff, 0xf7,
+0x37, 0xff, 0x08, 0x49, 0xc8, 0x1d, 0x49, 0x30, 0x02, 0x7a, 0x00, 0x2a,
+0x03, 0xd0, 0x07, 0x72, 0x08, 0x1c, 0xff, 0xf7, 0x2d, 0xff, 0x80, 0xbc,
+0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x00, 0xb0, 0x64, 0x2d, 0x00, 0x80,
+0xe4, 0x2c, 0x00, 0x80, 0x90, 0xb5, 0x07, 0x1c, 0x10, 0x20, 0x18, 0x49,
+0xc0, 0x46, 0x08, 0x60, 0xf8, 0x68, 0x01, 0x30, 0xf8, 0x60, 0x16, 0x48,
+0xc4, 0x1d, 0xb9, 0x34, 0x61, 0x6b, 0x89, 0x00, 0x09, 0x18, 0xc0, 0x31,
+0x09, 0x69, 0x7a, 0x68, 0x92, 0x00, 0xd2, 0x19, 0x51, 0x64, 0x61, 0x6b,
+0x89, 0x00, 0x08, 0x18, 0xc0, 0x30, 0x01, 0x69, 0x78, 0x68, 0x80, 0x00,
+0xc0, 0x19, 0xc0, 0x6b, 0x01, 0xf0, 0xa2, 0xfa, 0x01, 0x23, 0x78, 0x68,
+0x58, 0x40, 0x78, 0x60, 0x60, 0x6b, 0x01, 0x30, 0x80, 0x07, 0x80, 0x0f,
+0x60, 0x63, 0xf8, 0x1d, 0x19, 0x30, 0x40, 0x79, 0x00, 0x28, 0x02, 0xd1,
+0x38, 0x1c, 0x00, 0xf0, 0x07, 0xf8, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47,
+0x00, 0x00, 0x00, 0xb0, 0x68, 0x0e, 0x00, 0x80, 0x90, 0xb5, 0x07, 0x1c,
+0x39, 0x48, 0xc0, 0x68, 0x00, 0x28, 0x05, 0xd0, 0xb8, 0x6a, 0xc0, 0x68,
+0x80, 0x09, 0x01, 0xd3, 0x02, 0x20, 0x00, 0xe0, 0x78, 0x6f, 0xfc, 0xf7,
+0x59, 0xf8, 0x04, 0x1c, 0x06, 0xd1, 0x01, 0x20, 0xf9, 0x1d, 0x19, 0x31,
+0x08, 0x71, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xf8, 0x6c, 0x2f, 0x49,
+0xc0, 0x46, 0x08, 0x60, 0xba, 0x6a, 0x38, 0x1c, 0x21, 0x1c, 0x00, 0xf0,
+0x59, 0xf8, 0x67, 0x62, 0x00, 0x28, 0x03, 0xd1, 0x20, 0x1c, 0x00, 0xf0,
+0x0b, 0xfd, 0xec, 0xe7, 0xf9, 0x6d, 0x09, 0x68, 0x09, 0x18, 0x09, 0x09,
+0x09, 0x01, 0x7a, 0x6d, 0x8a, 0x42, 0x00, 0xd8, 0x89, 0x1a, 0xa1, 0x62,
+0xb9, 0x68, 0x89, 0x00, 0xc9, 0x19, 0x4a, 0x6c, 0x00, 0x2a, 0x07, 0xd0,
+0x4a, 0x6c, 0x12, 0x1a, 0x4a, 0x64, 0x80, 0x08, 0x80, 0x00, 0xb9, 0x6a,
+0x08, 0x18, 0xb8, 0x62, 0x38, 0x68, 0xb9, 0x6a, 0x80, 0x00, 0xc0, 0x19,
+0x42, 0x6b, 0x91, 0x42, 0x0e, 0xd3, 0x00, 0x21, 0x41, 0x64, 0xb8, 0x6a,
+0x39, 0x68, 0x89, 0x00, 0xc9, 0x19, 0x49, 0x6b, 0x40, 0x1a, 0xb8, 0x62,
+0xb9, 0x68, 0x89, 0x00, 0xc9, 0x19, 0xc9, 0x6b, 0x40, 0x18, 0xb8, 0x62,
+0xb8, 0x68, 0x81, 0x00, 0xc9, 0x19, 0x49, 0x6c, 0x00, 0x29, 0xb8, 0xd1,
+0xb9, 0x6a, 0xfa, 0x6b, 0x91, 0x42, 0xb4, 0xd0, 0x3a, 0x6c, 0x91, 0x42,
+0xb1, 0xd0, 0x01, 0x23, 0x58, 0x40, 0xb8, 0x60, 0x80, 0x00, 0xc0, 0x19,
+0xc0, 0x6b, 0xc0, 0x46, 0xb8, 0x62, 0xf8, 0x68, 0x00, 0x28, 0x01, 0xd0,
+0x01, 0x38, 0xf8, 0x60, 0x38, 0x69, 0x00, 0x28, 0xa1, 0xd0, 0x01, 0x38,
+0x38, 0x61, 0x9e, 0xe7, 0x68, 0x19, 0x00, 0x80, 0x00, 0x00, 0x00, 0xb0,
+0xf7, 0xb5, 0x90, 0xb0, 0x04, 0x1c, 0x0d, 0x1c, 0x00, 0x20, 0x05, 0x90,
+0x02, 0x90, 0x00, 0x22, 0x01, 0x92, 0xf9, 0x48, 0xc0, 0x6a, 0xc0, 0x46,
+0xa8, 0x61, 0xa0, 0x68, 0x81, 0x00, 0x09, 0x19, 0x49, 0x6b, 0xc0, 0x46,
+0x20, 0x60, 0xe1, 0x62, 0x12, 0x9a, 0xd0, 0x68, 0xc0, 0x46, 0xa8, 0x60,
+0x12, 0x9a, 0x51, 0x78, 0xc0, 0x46, 0x0c, 0x91, 0xf0, 0x48, 0xc0, 0x46,
+0x03, 0x90, 0xd7, 0x1d, 0x09, 0x37, 0xe0, 0x6a,
0xc1, 0x1b, 0x09, 0x09, 0xe3, 0x1d, 0x19, 0x33, 0x0c, 0x9a, 0xc0, 0x46,
-0x0f, 0x93, 0xeb, 0x4b, 0xc0, 0x46, 0x0e, 0x93,
-0x91, 0x42, 0x01, 0xd3, 0xb8, 0x42, 0x21, 0xd8, 0xe1, 0x68, 0x02, 0x29,
-0x1e, 0xd2, 0x01, 0x20, 0x0f, 0x99, 0xc0, 0x46, 0x48, 0x71, 0x00, 0x20,
-0x03, 0x99, 0x01, 0xf0, 0x57, 0xfb, 0x00, 0x28, 0x03, 0xd1, 0x0e, 0x9b,
-0xd8, 0x6b, 0x01, 0x30, 0xd8, 0x63, 0x01, 0x20, 0x80, 0x06, 0x00, 0x27,
-0x68, 0x60, 0xaf, 0x61, 0xdd, 0x4a, 0xc0, 0x46, 0x00, 0x92, 0xdd, 0x48,
-0x01, 0x6d, 0x42, 0x6d, 0xdc, 0x4b, 0x00, 0x20, 0x01, 0xf0, 0x3a, 0xfb,
-0x38, 0x1c, 0x5c, 0xe3, 0xb8, 0x42, 0x03, 0xd8, 0x20, 0x1c, 0x00, 0xf0,
-0x7b, 0xfc, 0x07, 0x1c, 0xd7, 0x48, 0xc0, 0x68, 0x00, 0x28, 0x64, 0xd0,
-0x38, 0x78, 0x40, 0x07, 0x40, 0x0f, 0x03, 0x28, 0x60, 0xd1, 0x05, 0x98,
-0x01, 0x30, 0x00, 0x06, 0x00, 0x0e, 0x05, 0x90, 0x38, 0x78, 0xf0, 0x23,
-0x18, 0x40, 0x58, 0xd1, 0xe0, 0x6a, 0xc0, 0x1b, 0x00, 0x09, 0x0c, 0x99,
-0x88, 0x42, 0x02, 0xd2, 0xe0, 0x68, 0x02, 0x28, 0x05, 0xd3, 0xcb, 0x49,
-0x88, 0x68, 0x00, 0xf0, 0x83, 0xff, 0x06, 0x1c, 0x06, 0xd1, 0x03, 0x9b,
-0x28, 0x1c, 0x39, 0x1c, 0x22, 0x1c, 0x00, 0xf0, 0x8b, 0xfc, 0x16, 0xe1,
-0x2e, 0x62, 0xf8, 0x68, 0x00, 0x28, 0x0d, 0xd0, 0xb8, 0x89, 0x00, 0x28,
-0x03, 0xd0, 0xc1, 0x49, 0xc9, 0x68, 0x00, 0xf0, 0x70, 0xff, 0xf8, 0x89,
-0x00, 0x28, 0x03, 0xd0, 0xbd, 0x49, 0xc9, 0x68, 0x00, 0xf0, 0x69, 0xff,
-0x7a, 0x68, 0xc0, 0x46, 0x72, 0x61, 0xb9, 0x68, 0xc0, 0x46, 0xb1, 0x61,
-0x30, 0x1c, 0xb8, 0x49, 0x09, 0x68, 0x00, 0xf0, 0x5e, 0xff, 0x00, 0x28,
-0x17, 0xd1, 0x30, 0x1c, 0xb4, 0x49, 0x49, 0x68, 0x00, 0xf0, 0x57, 0xff,
-0x10, 0x37, 0xe0, 0x6a, 0xb8, 0x42, 0x03, 0xd8, 0x20, 0x1c, 0x00, 0xf0,
-0x27, 0xfc, 0x07, 0x1c, 0x68, 0x68, 0xaf, 0x4b, 0x18, 0x43, 0x68, 0x60,
-0x00, 0x20, 0xa8, 0x61, 0xac, 0x23, 0xa8, 0x68, 0x98, 0x43, 0xa8, 0x60,
-0xb0, 0xe0, 0xa8, 0x69, 0xa8, 0x28, 0x01, 0xd2, 0xa8, 0x20, 0xa8, 0x61,
-0x10, 0x37, 0xe0, 0x6a, 0xb8, 0x42, 0x6c, 0xd8, 0x9c, 0xe0, 0xa5, 0xe0,
-0xa4, 0xe0, 0x10, 0x28, 0x68, 0xd1, 0x03, 0x23, 0x1b, 0x07, 0x68, 0x68,
-0x18, 0x40, 0x01, 0x0f, 0x48, 0x01, 0x40, 0x1a, 0x80, 0x00, 0xa0, 0x4a,
-0x82, 0x18, 0x01, 0x92, 0x78, 0x88, 0x42, 0x0b, 0x31, 0xd3, 0x82, 0x0b,
-0x2f, 0xd3, 0x9d, 0x48, 0xc0, 0x46, 0x03, 0x90, 0x02, 0x20, 0x01, 0x9a,
-0xc0, 0x46, 0x10, 0x80, 0x78, 0x88, 0x00, 0x05, 0x00, 0x0d, 0x01, 0x9a,
-0xc0, 0x46, 0x50, 0x60, 0xb8, 0x68, 0x01, 0x9a, 0xc0, 0x46, 0x90, 0x60,
-0x78, 0x68, 0x01, 0x9a, 0xc0, 0x46, 0x10, 0x62, 0x00, 0x20, 0x01, 0x9a,
-0xc0, 0x46, 0x90, 0x64, 0x01, 0x9a, 0xc0, 0x46, 0x90, 0x63, 0x88, 0x02,
-0x8f, 0x49, 0x40, 0x18, 0x01, 0x9a, 0xc0, 0x46, 0x50, 0x63, 0x01, 0x9a,
-0x50, 0x68, 0x36, 0x30, 0x94, 0x28, 0x01, 0xd8, 0x38, 0x20, 0x00, 0xe0,
-0x94, 0x20, 0xa8, 0x61, 0x10, 0x37, 0xe0, 0x6a, 0xb8, 0x42, 0x28, 0xd8,
-0x58, 0xe0, 0x7a, 0x88, 0x92, 0x0b, 0x03, 0xd3, 0x85, 0x48, 0xc0, 0x46,
-0x03, 0x90, 0x23, 0xe0, 0x01, 0x22, 0x12, 0x03, 0x02, 0x40, 0x83, 0x4b,
-0x1d, 0xd0, 0x03, 0x93, 0x00, 0x05, 0x00, 0x0d, 0x01, 0x9a, 0xc0, 0x46,
-0x50, 0x60, 0xb8, 0x68, 0x01, 0x9a, 0xc0, 0x46, 0x90, 0x60, 0x78, 0x68,
-0x01, 0x9a, 0xc0, 0x46, 0x10, 0x62, 0x00, 0x20, 0x01, 0x9a, 0xc0, 0x46,
+0x0f, 0x93, 0xeb, 0x4b, 0xc0, 0x46, 0x0e, 0x93, 0x91, 0x42, 0x01, 0xd3,
+0xb8, 0x42, 0x21, 0xd8, 0xe1, 0x68, 0x02, 0x29, 0x1e, 0xd2, 0x01, 0x20,
+0x0f, 0x99, 0xc0, 0x46, 0x48, 0x71, 0x00, 0x20, 0x03, 0x99, 0x01, 0xf0,
+0x57, 0xfb, 0x00, 0x28, 0x03, 0xd1, 0x0e, 0x9b, 0xd8, 0x6b, 0x01, 0x30,
+0xd8, 0x63, 0x01, 0x20, 0x80, 0x06, 0x00, 0x27, 0x68, 0x60, 0xaf, 0x61,
+0xdd, 0x4a, 0xc0, 0x46, 0x00, 0x92, 0xdd, 0x48, 0x01, 0x6d, 0x42, 0x6d,
+0xdc, 0x4b, 0x00, 0x20, 0x01, 0xf0, 0x3a, 0xfb, 0x38, 0x1c, 0x5c, 0xe3,
+0xb8, 0x42, 0x03, 0xd8, 0x20, 0x1c, 0x00, 0xf0, 0x7b, 0xfc, 0x07, 0x1c,
+0xd7, 0x48, 0xc0, 0x68, 0x00, 0x28, 0x64, 0xd0, 0x38, 0x78, 0x40, 0x07,
+0x40, 0x0f, 0x03, 0x28, 0x60, 0xd1, 0x05, 0x98, 0x01, 0x30, 0x00, 0x06,
+0x00, 0x0e, 0x05, 0x90, 0x38, 0x78, 0xf0, 0x23, 0x18, 0x40, 0x58, 0xd1,
+0xe0, 0x6a, 0xc0, 0x1b, 0x00, 0x09, 0x0c, 0x99, 0x88, 0x42, 0x02, 0xd2,
+0xe0, 0x68, 0x02, 0x28, 0x05, 0xd3, 0xcb, 0x49, 0x88, 0x68, 0x00, 0xf0,
+0x83, 0xff, 0x06, 0x1c, 0x06, 0xd1, 0x03, 0x9b, 0x28, 0x1c, 0x39, 0x1c,
+0x22, 0x1c, 0x00, 0xf0, 0x8b, 0xfc, 0x16, 0xe1, 0x2e, 0x62, 0xf8, 0x68,
+0x00, 0x28, 0x0d, 0xd0, 0xb8, 0x89, 0x00, 0x28, 0x03, 0xd0, 0xc1, 0x49,
+0xc9, 0x68, 0x00, 0xf0, 0x70, 0xff, 0xf8, 0x89, 0x00, 0x28, 0x03, 0xd0,
+0xbd, 0x49, 0xc9, 0x68, 0x00, 0xf0, 0x69, 0xff, 0x7a, 0x68, 0xc0, 0x46,
+0x72, 0x61, 0xb9, 0x68, 0xc0, 0x46, 0xb1, 0x61, 0x30, 0x1c, 0xb8, 0x49,
+0x09, 0x68, 0x00, 0xf0, 0x5e, 0xff, 0x00, 0x28, 0x17, 0xd1, 0x30, 0x1c,
+0xb4, 0x49, 0x49, 0x68, 0x00, 0xf0, 0x57, 0xff, 0x10, 0x37, 0xe0, 0x6a,
+0xb8, 0x42, 0x03, 0xd8, 0x20, 0x1c, 0x00, 0xf0, 0x27, 0xfc, 0x07, 0x1c,
+0x68, 0x68, 0xaf, 0x4b, 0x18, 0x43, 0x68, 0x60, 0x00, 0x20, 0xa8, 0x61,
+0xac, 0x23, 0xa8, 0x68, 0x98, 0x43, 0xa8, 0x60, 0xb0, 0xe0, 0xa8, 0x69,
+0xa8, 0x28, 0x01, 0xd2, 0xa8, 0x20, 0xa8, 0x61, 0x10, 0x37, 0xe0, 0x6a,
+0xb8, 0x42, 0x6c, 0xd8, 0x9c, 0xe0, 0xa5, 0xe0, 0xa4, 0xe0, 0x10, 0x28,
+0x68, 0xd1, 0x03, 0x23, 0x1b, 0x07, 0x68, 0x68, 0x18, 0x40, 0x01, 0x0f,
+0x48, 0x01, 0x40, 0x1a, 0x80, 0x00, 0xa0, 0x4a, 0x82, 0x18, 0x01, 0x92,
+0x78, 0x88, 0x42, 0x0b, 0x31, 0xd3, 0x82, 0x0b, 0x2f, 0xd3, 0x9d, 0x48,
+0xc0, 0x46, 0x03, 0x90, 0x02, 0x20, 0x01, 0x9a, 0xc0, 0x46, 0x10, 0x80,
+0x78, 0x88, 0x00, 0x05, 0x00, 0x0d, 0x01, 0x9a, 0xc0, 0x46, 0x50, 0x60,
+0xb8, 0x68, 0x01, 0x9a, 0xc0, 0x46, 0x90, 0x60, 0x78, 0x68, 0x01, 0x9a,
+0xc0, 0x46, 0x10, 0x62, 0x00, 0x20, 0x01, 0x9a, 0xc0, 0x46, 0x90, 0x64,
+0x01, 0x9a, 0xc0, 0x46, 0x90, 0x63, 0x88, 0x02, 0x8f, 0x49, 0x40, 0x18,
+0x01, 0x9a, 0xc0, 0x46, 0x50, 0x63, 0x01, 0x9a, 0x50, 0x68, 0x36, 0x30,
+0x94, 0x28, 0x01, 0xd8, 0x38, 0x20, 0x00, 0xe0, 0x94, 0x20, 0xa8, 0x61,
+0x10, 0x37, 0xe0, 0x6a, 0xb8, 0x42, 0x28, 0xd8, 0x58, 0xe0, 0x7a, 0x88,
+0x92, 0x0b, 0x03, 0xd3, 0x85, 0x48, 0xc0, 0x46, 0x03, 0x90, 0x23, 0xe0,
+0x01, 0x22, 0x12, 0x03, 0x02, 0x40, 0x83, 0x4b, 0x1d, 0xd0, 0x03, 0x93,
+0x00, 0x05, 0x00, 0x0d, 0x01, 0x9a, 0xc0, 0x46, 0x50, 0x60, 0xb8, 0x68,
+0x01, 0x9a, 0xc0, 0x46, 0x90, 0x60, 0x78, 0x68, 0x01, 0x9a, 0xc0, 0x46,
+0x10, 0x62, 0x00, 0x20, 0x01, 0x9a, 0xc0, 0x46,
0x90, 0x64, 0x01, 0x9a, 0xc0, 0x46, 0x90, 0x63, 0x88, 0x02, 0x75, 0x49,
-0x40, 0x18, 0x01, 0x9a, 0xc0, 0x46, 0x50, 0x63,
-0x02, 0xe0, 0x33, 0xe0, 0x2a, 0xe0, 0x03, 0x93, 0x01, 0x20, 0x0f, 0x99,
-0xc0, 0x46, 0x48, 0x71, 0x12, 0x9a, 0x50, 0x78, 0x05, 0x99, 0x43, 0x1a,
-0x0b, 0x93, 0x10, 0x37, 0xe0, 0x6a, 0xb8, 0x42, 0x03, 0xd8, 0x20, 0x1c,
-0x00, 0xf0, 0x92, 0xfb, 0x07, 0x1c, 0x01, 0x9a, 0x50, 0x6b, 0x91, 0x6b,
-0x09, 0x01, 0x40, 0x18, 0x0b, 0x9b, 0x21, 0x1c, 0x3a, 0x1c, 0xff, 0xf7,
-0x7d, 0xfb, 0x01, 0x9a, 0xc0, 0x46, 0xd0, 0x64, 0x01, 0x9a, 0x0b, 0x9b,
-0xc0, 0x46, 0x13, 0x65, 0x01, 0x23, 0x5b, 0x06, 0x68, 0x68, 0x18, 0x43,
-0x68, 0x60, 0x00, 0x20, 0xa8, 0x61, 0x0d, 0xe0, 0x10, 0x37, 0xe0, 0x6a,
-0xb8, 0x42, 0x03, 0xd8, 0x20, 0x1c, 0x00, 0xf0, 0x71, 0xfb, 0x07, 0x1c,
-0x38, 0x78, 0x40, 0x07, 0x40, 0x0f, 0x03, 0x28, 0x00, 0xd1, 0xf8, 0xe6,
-0xa8, 0x69, 0x03, 0x99, 0x01, 0xf0, 0x26, 0xfa, 0x00, 0x28, 0x2a, 0xd1,
-0x38, 0x1c, 0x21, 0x1c, 0x00, 0xf0, 0x79, 0xfb, 0xa8, 0x68, 0x80, 0x09,
-0x04, 0xd3, 0x30, 0x1c, 0x49, 0x49, 0x49, 0x68, 0x00, 0xf0, 0x81, 0xfe,
-0x41, 0x49, 0x00, 0x20, 0x01, 0xf0, 0x14, 0xfa, 0x00, 0x28, 0x04, 0xd1,
-0x0e, 0x9b, 0xd8, 0x6b, 0x01, 0x30, 0xd8, 0x63, 0x11, 0xe0, 0x01, 0x20,
-0x0f, 0x99, 0xc0, 0x46, 0x48, 0x71, 0x80, 0x06, 0x00, 0x27, 0x68, 0x60,
-0xaf, 0x61, 0x3a, 0x4a, 0xc0, 0x46, 0x00, 0x92, 0x39, 0x48, 0x01, 0x6d,
-0x42, 0x6d, 0x39, 0x4b, 0x00, 0x20, 0x01, 0xf0, 0xf3, 0xf9, 0x00, 0x20,
-0x15, 0xe2, 0x05, 0x98, 0x0c, 0x99, 0x08, 0x1a, 0x00, 0x04, 0x00, 0x0c,
-0x0c, 0x90, 0x0b, 0x90, 0x0c, 0x98, 0x00, 0x28, 0x03, 0xd0, 0x01, 0x20,
-0x0f, 0x99, 0xc0, 0x46, 0x48, 0x71, 0x28, 0x68, 0xc0, 0x46, 0x04, 0x90,
-0x00, 0x26, 0x00, 0x20, 0x08, 0x90, 0x00, 0x22, 0x0a, 0x92, 0x0c, 0x98,
-0x01, 0x38, 0x0d, 0x90, 0xa3, 0xe0, 0x78, 0x88, 0x8a, 0x1b, 0x12, 0x04,
-0x12, 0x0c, 0x90, 0x42, 0x05, 0xdd, 0x07, 0x92, 0x80, 0x1a, 0x00, 0x04,
-0x00, 0x0c, 0x08, 0x90, 0x00, 0xe0, 0x07, 0x90, 0x08, 0x98, 0x00, 0x28,
-0x07, 0xd1, 0x0d, 0x98, 0x0a, 0x9a, 0x90, 0x42, 0x07, 0xdd, 0x07, 0x98,
-0x30, 0x18, 0x88, 0x42, 0x03, 0xd8, 0x01, 0x20, 0x40, 0x05, 0x06, 0x90,
-0x1c, 0xe0, 0x11, 0x20, 0x40, 0x05, 0x06, 0x90, 0xa8, 0x68, 0x8c, 0x23,
-0x18, 0x40, 0x02, 0xd1, 0x20, 0x48, 0xc0, 0x46, 0x06, 0x90, 0xb1, 0x07,
-0x89, 0x0f, 0x0f, 0xd0, 0x07, 0x98, 0xc0, 0x06, 0xc0, 0x0e, 0x08, 0xd0,
-0x1e, 0x28, 0x09, 0xdb, 0x1e, 0x28, 0x02, 0xd1, 0x03, 0x29, 0x05, 0xd1,
-0x01, 0xe0, 0x02, 0x29, 0x02, 0xd3, 0x01, 0x20, 0x02, 0x90, 0xde, 0xe7,
-0x0a, 0x9a, 0x00, 0x2a, 0x04, 0xd1, 0x01, 0x23, 0xdb, 0x05, 0x06, 0x98,
-0x18, 0x43, 0x06, 0x90, 0x07, 0x98, 0x06, 0x99, 0x08, 0x43, 0x02, 0x1c,
-0x00, 0x90, 0x04, 0x98, 0x83, 0x19, 0x1d, 0xe0, 0xe8, 0x0e, 0x00, 0x80,
-0xed, 0x48, 0xff, 0xff, 0x28, 0x0f, 0x00, 0x80, 0x04, 0x00, 0x12, 0x02,
-0x7c, 0x29, 0x00, 0x80, 0x44, 0x80, 0x20, 0x40, 0x68, 0x19, 0x00, 0x80,
-0x60, 0x04, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x5c, 0x2b, 0x00, 0x80,
-0x41, 0x32, 0xff, 0xff, 0x58, 0x5f, 0x21, 0x40, 0xf9, 0x3c, 0xff, 0xff,
-0xb9, 0x31, 0xff, 0xff, 0x00, 0x00, 0x32, 0x02, 0x00, 0x20, 0x3a, 0x1d,
-0x06, 0xca, 0x01, 0xf0, 0x6b, 0xf9, 0x07, 0x98, 0x36, 0x18, 0x02, 0x98,
+0x40, 0x18, 0x01, 0x9a, 0xc0, 0x46, 0x50, 0x63, 0x02, 0xe0, 0x33, 0xe0,
+0x2a, 0xe0, 0x03, 0x93, 0x01, 0x20, 0x0f, 0x99, 0xc0, 0x46, 0x48, 0x71,
+0x12, 0x9a, 0x50, 0x78, 0x05, 0x99, 0x43, 0x1a, 0x0b, 0x93, 0x10, 0x37,
+0xe0, 0x6a, 0xb8, 0x42, 0x03, 0xd8, 0x20, 0x1c, 0x00, 0xf0, 0x92, 0xfb,
+0x07, 0x1c, 0x01, 0x9a, 0x50, 0x6b, 0x91, 0x6b, 0x09, 0x01, 0x40, 0x18,
+0x0b, 0x9b, 0x21, 0x1c, 0x3a, 0x1c, 0xff, 0xf7, 0x7d, 0xfb, 0x01, 0x9a,
+0xc0, 0x46, 0xd0, 0x64, 0x01, 0x9a, 0x0b, 0x9b, 0xc0, 0x46, 0x13, 0x65,
+0x01, 0x23, 0x5b, 0x06, 0x68, 0x68, 0x18, 0x43, 0x68, 0x60, 0x00, 0x20,
+0xa8, 0x61, 0x0d, 0xe0, 0x10, 0x37, 0xe0, 0x6a, 0xb8, 0x42, 0x03, 0xd8,
+0x20, 0x1c, 0x00, 0xf0, 0x71, 0xfb, 0x07, 0x1c, 0x38, 0x78, 0x40, 0x07,
+0x40, 0x0f, 0x03, 0x28, 0x00, 0xd1, 0xf8, 0xe6, 0xa8, 0x69, 0x03, 0x99,
+0x01, 0xf0, 0x26, 0xfa, 0x00, 0x28, 0x2a, 0xd1, 0x38, 0x1c, 0x21, 0x1c,
+0x00, 0xf0, 0x79, 0xfb, 0xa8, 0x68, 0x80, 0x09, 0x04, 0xd3, 0x30, 0x1c,
+0x49, 0x49, 0x49, 0x68, 0x00, 0xf0, 0x81, 0xfe, 0x41, 0x49, 0x00, 0x20,
+0x01, 0xf0, 0x14, 0xfa, 0x00, 0x28, 0x04, 0xd1, 0x0e, 0x9b, 0xd8, 0x6b,
+0x01, 0x30, 0xd8, 0x63, 0x11, 0xe0, 0x01, 0x20, 0x0f, 0x99, 0xc0, 0x46,
+0x48, 0x71, 0x80, 0x06, 0x00, 0x27, 0x68, 0x60, 0xaf, 0x61, 0x3a, 0x4a,
+0xc0, 0x46, 0x00, 0x92, 0x39, 0x48, 0x01, 0x6d, 0x42, 0x6d, 0x39, 0x4b,
+0x00, 0x20, 0x01, 0xf0, 0xf3, 0xf9, 0x00, 0x20, 0x15, 0xe2, 0x05, 0x98,
+0x0c, 0x99, 0x08, 0x1a, 0x00, 0x04, 0x00, 0x0c, 0x0c, 0x90, 0x0b, 0x90,
+0x0c, 0x98, 0x00, 0x28, 0x03, 0xd0, 0x01, 0x20, 0x0f, 0x99, 0xc0, 0x46,
+0x48, 0x71, 0x28, 0x68, 0xc0, 0x46, 0x04, 0x90, 0x00, 0x26, 0x00, 0x20,
+0x08, 0x90, 0x00, 0x22, 0x0a, 0x92, 0x0c, 0x98, 0x01, 0x38, 0x0d, 0x90,
+0xa3, 0xe0, 0x78, 0x88, 0x8a, 0x1b, 0x12, 0x04, 0x12, 0x0c, 0x90, 0x42,
+0x05, 0xdd, 0x07, 0x92, 0x80, 0x1a, 0x00, 0x04, 0x00, 0x0c, 0x08, 0x90,
+0x00, 0xe0, 0x07, 0x90, 0x08, 0x98, 0x00, 0x28, 0x07, 0xd1, 0x0d, 0x98,
+0x0a, 0x9a, 0x90, 0x42, 0x07, 0xdd, 0x07, 0x98, 0x30, 0x18, 0x88, 0x42,
+0x03, 0xd8, 0x01, 0x20, 0x40, 0x05, 0x06, 0x90, 0x1c, 0xe0, 0x11, 0x20,
+0x40, 0x05, 0x06, 0x90, 0xa8, 0x68, 0x8c, 0x23, 0x18, 0x40, 0x02, 0xd1,
+0x20, 0x48, 0xc0, 0x46, 0x06, 0x90, 0xb1, 0x07, 0x89, 0x0f, 0x0f, 0xd0,
+0x07, 0x98, 0xc0, 0x06, 0xc0, 0x0e, 0x08, 0xd0, 0x1e, 0x28, 0x09, 0xdb,
+0x1e, 0x28, 0x02, 0xd1, 0x03, 0x29, 0x05, 0xd1, 0x01, 0xe0, 0x02, 0x29,
+0x02, 0xd3, 0x01, 0x20, 0x02, 0x90, 0xde, 0xe7, 0x0a, 0x9a, 0x00, 0x2a,
+0x04, 0xd1, 0x01, 0x23, 0xdb, 0x05, 0x06, 0x98, 0x18, 0x43, 0x06, 0x90,
+0x07, 0x98, 0x06, 0x99, 0x08, 0x43, 0x02, 0x1c, 0x00, 0x90, 0x04, 0x98,
+0x83, 0x19, 0x1d, 0xe0, 0xe8, 0x0e, 0x00, 0x80, 0x01, 0x49, 0xff, 0xff,
+0x28, 0x0f, 0x00, 0x80, 0x04, 0x00, 0x12, 0x02, 0x7c, 0x29, 0x00, 0x80,
+0x44, 0x80, 0x20, 0x40, 0x68, 0x19, 0x00, 0x80, 0x60, 0x04, 0x00, 0x80,
+0x00, 0x00, 0x00, 0x80, 0x5c, 0x2b, 0x00, 0x80, 0x55, 0x32, 0xff, 0xff,
+0xac, 0x5e, 0x21, 0x40, 0x0d, 0x3d, 0xff, 0xff, 0xcd, 0x31, 0xff, 0xff,
+0x00, 0x00, 0x32, 0x02, 0x00, 0x20, 0x3a, 0x1d, 0x06, 0xca, 0x01, 0xf0,
+0x6b, 0xf9, 0x07, 0x98, 0x36, 0x18, 0x02, 0x98,
0x00, 0x28, 0x16, 0xd0, 0xa8, 0x68, 0x8c, 0x23, 0x18, 0x40, 0x04, 0xd1,
-0x09, 0x23, 0x5b, 0x04, 0x06, 0x98, 0x18, 0x43,
-0x06, 0x90, 0x06, 0x98, 0xc2, 0x4a, 0x02, 0x43, 0x00, 0x92, 0x04, 0x98,
-0x83, 0x19, 0xc1, 0x48, 0x01, 0x6d, 0x42, 0x6d, 0x00, 0x20, 0x01, 0xf0,
-0x51, 0xf9, 0x00, 0x20, 0x02, 0x90, 0x08, 0x98, 0x00, 0x28, 0x0b, 0xd1,
-0x0b, 0x9b, 0x01, 0x3b, 0x0b, 0x93, 0x10, 0x37, 0xe0, 0x6a, 0xb8, 0x42,
-0x0c, 0xd8, 0x20, 0x1c, 0x00, 0xf0, 0x8a, 0xfa, 0x07, 0x1c, 0x07, 0xe0,
-0x78, 0x68, 0x07, 0x9a, 0x80, 0x18, 0x78, 0x60, 0x78, 0x88, 0x07, 0x9a,
-0x80, 0x1a, 0x78, 0x80, 0x0a, 0x9a, 0x50, 0x1c, 0x02, 0x04, 0x12, 0x0c,
-0x0a, 0x92, 0x0c, 0x98, 0x0a, 0x9a, 0x82, 0x42, 0x03, 0xda, 0xa9, 0x69,
-0xb1, 0x42, 0x00, 0xd9, 0x53, 0xe7, 0xa8, 0x69, 0xb0, 0x42, 0x6b, 0xd1,
-0xa8, 0x68, 0x01, 0x09, 0x69, 0xd2, 0x08, 0x9a, 0x00, 0x2a, 0x56, 0xd0,
-0x0c, 0x99, 0x0a, 0x9a, 0x8a, 0x42, 0x3e, 0xdb, 0xb1, 0x07, 0x89, 0x0f,
-0x0c, 0xd0, 0x08, 0x9a, 0xd2, 0x06, 0xd2, 0x0e, 0x0b, 0xd0, 0x1e, 0x2a,
-0x06, 0xdb, 0x1e, 0x2a, 0x02, 0xd1, 0x03, 0x29, 0x05, 0xd0, 0x01, 0xe0,
-0x02, 0x29, 0x02, 0xd2, 0x02, 0x99, 0x00, 0x29, 0x21, 0xd0, 0x08, 0x9a,
+0x09, 0x23, 0x5b, 0x04, 0x06, 0x98, 0x18, 0x43, 0x06, 0x90, 0x06, 0x98,
+0xc2, 0x4a, 0x02, 0x43, 0x00, 0x92, 0x04, 0x98, 0x83, 0x19, 0xc1, 0x48,
+0x01, 0x6d, 0x42, 0x6d, 0x00, 0x20, 0x01, 0xf0, 0x51, 0xf9, 0x00, 0x20,
+0x02, 0x90, 0x08, 0x98, 0x00, 0x28, 0x0b, 0xd1, 0x0b, 0x9b, 0x01, 0x3b,
+0x0b, 0x93, 0x10, 0x37, 0xe0, 0x6a, 0xb8, 0x42, 0x0c, 0xd8, 0x20, 0x1c,
+0x00, 0xf0, 0x8a, 0xfa, 0x07, 0x1c, 0x07, 0xe0, 0x78, 0x68, 0x07, 0x9a,
+0x80, 0x18, 0x78, 0x60, 0x78, 0x88, 0x07, 0x9a, 0x80, 0x1a, 0x78, 0x80,
+0x0a, 0x9a, 0x50, 0x1c, 0x02, 0x04, 0x12, 0x0c, 0x0a, 0x92, 0x0c, 0x98,
+0x0a, 0x9a, 0x82, 0x42, 0x03, 0xda, 0xa9, 0x69, 0xb1, 0x42, 0x00, 0xd9,
+0x53, 0xe7, 0xa8, 0x69, 0xb0, 0x42, 0x6b, 0xd1, 0xa8, 0x68, 0x01, 0x09,
+0x69, 0xd2, 0x08, 0x9a, 0x00, 0x2a, 0x56, 0xd0, 0x0c, 0x99, 0x0a, 0x9a,
+0x8a, 0x42, 0x3e, 0xdb, 0xb1, 0x07, 0x89, 0x0f, 0x0c, 0xd0, 0x08, 0x9a,
+0xd2, 0x06, 0xd2, 0x0e, 0x0b, 0xd0, 0x1e, 0x2a, 0x06, 0xdb, 0x1e, 0x2a,
+0x02, 0xd1, 0x03, 0x29, 0x05, 0xd0, 0x01, 0xe0, 0x02, 0x29, 0x02, 0xd2,
+0x02, 0x99, 0x00, 0x29, 0x21, 0xd0, 0x08, 0x9a, 0xc0, 0x46, 0x00, 0x92,
+0x04, 0x98, 0x83, 0x19, 0x00, 0x20, 0x3a, 0x1d, 0x06, 0xca, 0x01, 0xf0,
+0x01, 0xf9, 0x08, 0x98, 0x36, 0x18, 0xa8, 0x68, 0x8c, 0x23, 0x18, 0x40,
+0x02, 0xd0, 0x01, 0x20, 0x40, 0x06, 0x00, 0xe0, 0x92, 0x48, 0x01, 0x22,
+0x02, 0x43, 0x00, 0x92, 0x04, 0x98, 0x83, 0x19, 0x8e, 0x48, 0x01, 0x6d,
+0x42, 0x6d, 0x00, 0x20, 0x01, 0xf0, 0xec, 0xf8, 0x00, 0x20, 0x02, 0x90,
+0x15, 0xe0, 0x8c, 0x23, 0x18, 0x40, 0x02, 0xd0, 0x01, 0x20, 0x40, 0x06,
+0x00, 0xe0, 0x88, 0x48, 0x08, 0x9a, 0x02, 0x43, 0x00, 0xe0, 0x08, 0x9a,
0xc0, 0x46, 0x00, 0x92, 0x04, 0x98, 0x83, 0x19, 0x00, 0x20, 0x3a, 0x1d,
-0x06, 0xca, 0x01, 0xf0, 0x01, 0xf9, 0x08, 0x98, 0x36, 0x18, 0xa8, 0x68,
-0x8c, 0x23, 0x18, 0x40, 0x02, 0xd0, 0x01, 0x20, 0x40, 0x06, 0x00, 0xe0,
-0x92, 0x48, 0x01, 0x22, 0x02, 0x43, 0x00, 0x92, 0x04, 0x98, 0x83, 0x19,
-0x8e, 0x48, 0x01, 0x6d, 0x42, 0x6d, 0x00, 0x20, 0x01, 0xf0, 0xec, 0xf8,
-0x00, 0x20, 0x02, 0x90, 0x15, 0xe0, 0x8c, 0x23, 0x18, 0x40, 0x02, 0xd0,
-0x01, 0x20, 0x40, 0x06, 0x00, 0xe0, 0x88, 0x48, 0x08, 0x9a, 0x02, 0x43,
-0x00, 0xe0, 0x08, 0x9a, 0xc0, 0x46, 0x00, 0x92, 0x04, 0x98, 0x83, 0x19,
-0x00, 0x20, 0x3a, 0x1d, 0x06, 0xca, 0x01, 0xf0, 0xd5, 0xf8, 0x08, 0x98,
-0x36, 0x18, 0x10, 0x37, 0xe0, 0x6a, 0xb8, 0x42, 0x03, 0xd8, 0x20, 0x1c,
-0x00, 0xf0, 0x14, 0xfa, 0x07, 0x1c, 0x68, 0x68, 0x80, 0x0e, 0x6b, 0xd2,
-0x0a, 0x98, 0xc0, 0x46, 0x09, 0x90, 0x0c, 0x99, 0x88, 0x42, 0x5c, 0xda,
-0x0d, 0x98, 0x09, 0x99, 0x88, 0x42, 0x03, 0xd0, 0x7a, 0x88, 0x1e, 0xe0,
-0x5f, 0xe0, 0x5e, 0xe0, 0x78, 0x88, 0x01, 0x22, 0x52, 0x06, 0x02, 0x43,
-0xa9, 0x68, 0x8c, 0x23, 0x19, 0x40, 0x02, 0xd1, 0x09, 0x23, 0x5b, 0x04,
-0x1a, 0x43, 0xb1, 0x07, 0x89, 0x0f, 0x0e, 0xd0, 0xc3, 0x06, 0xdb, 0x0e,
-0x08, 0xd0, 0x1e, 0x2b, 0x09, 0xdb, 0x1e, 0x2b, 0x02, 0xd1, 0x03, 0x29,
-0x05, 0xd1, 0x01, 0xe0, 0x02, 0x29, 0x02, 0xd3, 0x01, 0x21, 0x02, 0x91,
-0x02, 0x1c, 0x09, 0x98, 0x00, 0x28, 0x02, 0xd1, 0x01, 0x23, 0xdb, 0x05,
-0x1a, 0x43, 0x00, 0x92, 0x04, 0x98, 0x83, 0x19, 0x00, 0x20, 0x3a, 0x1d,
-0x06, 0xca, 0x01, 0xf0, 0x8f, 0xf8, 0x78, 0x88, 0x86, 0x19, 0x10, 0x37,
-0x02, 0x98, 0x00, 0x28, 0x14, 0xd0, 0xa8, 0x68, 0x8c, 0x23, 0x18, 0x40,
-0x02, 0xd0, 0x01, 0x20, 0x40, 0x06, 0x00, 0xe0, 0x57, 0x48, 0x01, 0x22,
-0x02, 0x43, 0x00, 0x92, 0x04, 0x98, 0x83, 0x19, 0x53, 0x48, 0x01, 0x6d,
-0x42, 0x6d, 0x00, 0x20, 0x01, 0xf0, 0x76, 0xf8, 0x00, 0x20, 0x02, 0x90,
-0xe0, 0x6a, 0xb8, 0x42, 0x03, 0xd8, 0x20, 0x1c, 0x00, 0xf0, 0xb6, 0xf9,
-0x07, 0x1c, 0x09, 0x98, 0x01, 0x30, 0x00, 0x04, 0x00, 0x0c, 0x09, 0x90,
+0x06, 0xca, 0x01, 0xf0, 0xd5, 0xf8, 0x08, 0x98, 0x36, 0x18, 0x10, 0x37,
+0xe0, 0x6a, 0xb8, 0x42, 0x03, 0xd8, 0x20, 0x1c, 0x00, 0xf0, 0x14, 0xfa,
+0x07, 0x1c, 0x68, 0x68, 0x80, 0x0e, 0x6b, 0xd2, 0x0a, 0x98, 0xc0, 0x46,
+0x09, 0x90, 0x0c, 0x99, 0x88, 0x42, 0x5c, 0xda, 0x0d, 0x98, 0x09, 0x99,
+0x88, 0x42, 0x03, 0xd0, 0x7a, 0x88, 0x1e, 0xe0, 0x5f, 0xe0, 0x5e, 0xe0,
+0x78, 0x88, 0x01, 0x22, 0x52, 0x06, 0x02, 0x43, 0xa9, 0x68, 0x8c, 0x23,
+0x19, 0x40, 0x02, 0xd1, 0x09, 0x23, 0x5b, 0x04, 0x1a, 0x43, 0xb1, 0x07,
+0x89, 0x0f, 0x0e, 0xd0, 0xc3, 0x06, 0xdb, 0x0e, 0x08, 0xd0, 0x1e, 0x2b,
+0x09, 0xdb, 0x1e, 0x2b, 0x02, 0xd1, 0x03, 0x29, 0x05, 0xd1, 0x01, 0xe0,
+0x02, 0x29, 0x02, 0xd3, 0x01, 0x21, 0x02, 0x91, 0x02, 0x1c, 0x09, 0x98,
+0x00, 0x28, 0x02, 0xd1, 0x01, 0x23, 0xdb, 0x05, 0x1a, 0x43, 0x00, 0x92,
+0x04, 0x98, 0x83, 0x19, 0x00, 0x20, 0x3a, 0x1d, 0x06, 0xca, 0x01, 0xf0,
+0x8f, 0xf8, 0x78, 0x88, 0x86, 0x19, 0x10, 0x37, 0x02, 0x98, 0x00, 0x28,
+0x14, 0xd0, 0xa8, 0x68, 0x8c, 0x23, 0x18, 0x40, 0x02, 0xd0, 0x01, 0x20,
+0x40, 0x06, 0x00, 0xe0, 0x57, 0x48, 0x01, 0x22, 0x02, 0x43, 0x00, 0x92,
+0x04, 0x98, 0x83, 0x19, 0x53, 0x48, 0x01, 0x6d, 0x42, 0x6d, 0x00, 0x20,
+0x01, 0xf0, 0x76, 0xf8, 0x00, 0x20, 0x02, 0x90, 0xe0, 0x6a, 0xb8, 0x42,
+0x03, 0xd8, 0x20, 0x1c, 0x00, 0xf0, 0xb6, 0xf9, 0x07, 0x1c, 0x09, 0x98,
+0x01, 0x30, 0x00, 0x04, 0x00, 0x0c, 0x09, 0x90,
0x0c, 0x99, 0x88, 0x42, 0xa2, 0xdb, 0x68, 0x68, 0x30, 0x43, 0x01, 0x04,
-0x09, 0x0c, 0x68, 0x60, 0xe8, 0x6a, 0x00, 0xf0,
-0x7b, 0xfa, 0x28, 0xe0, 0x27, 0xe0, 0xa8, 0x68, 0x00, 0x09, 0x14, 0xd3,
-0x68, 0x68, 0x80, 0x0e, 0x15, 0xd2, 0x01, 0x9a, 0x00, 0x2a, 0x12, 0xd0,
-0x01, 0x9a, 0x50, 0x6b, 0x0b, 0x9b, 0x21, 0x1c, 0x3a, 0x1c, 0xff, 0xf7,
-0x89, 0xf9, 0x01, 0x9a, 0xc0, 0x46, 0x90, 0x64, 0x01, 0x9a, 0x0b, 0x9b,
-0xc0, 0x46, 0x93, 0x63, 0x03, 0xe0, 0xe8, 0x6a, 0x31, 0x1c, 0x00, 0xf0,
-0x5d, 0xfa, 0x68, 0x68, 0x30, 0x43, 0x68, 0x60, 0xa8, 0x69, 0xb0, 0x42,
-0x05, 0xd9, 0x00, 0x04, 0x00, 0x0c, 0x80, 0x1b, 0x00, 0xf0, 0xee, 0xf9,
-0xae, 0x61, 0xa8, 0x68, 0x8c, 0x23, 0x18, 0x40, 0x0b, 0xd0, 0x2f, 0x4a,
-0xc0, 0x46, 0x00, 0x92, 0x04, 0x98, 0xc3, 0x1f, 0x05, 0x3b, 0x2a, 0x48,
-0x01, 0x6d, 0x42, 0x6d, 0x00, 0x20, 0x01, 0xf0, 0x23, 0xf8, 0x01, 0x23,
-0x9b, 0x07, 0x20, 0x6d, 0x18, 0x43, 0x00, 0x68, 0xc0, 0x46, 0xa0, 0x61,
-0xe1, 0x69, 0x81, 0x42, 0x12, 0xd0, 0x22, 0x69, 0x02, 0x2a, 0x0f, 0xd2,
-0x41, 0x1a, 0x01, 0xd5, 0x60, 0x6d, 0x41, 0x18, 0x20, 0x1c, 0xff, 0xf7,
-0x3f, 0xfb, 0xe1, 0x69, 0x40, 0x18, 0xe0, 0x61, 0x61, 0x6d, 0x88, 0x42,
-0x24, 0xd3, 0x40, 0x1a, 0xe0, 0x61, 0x21, 0xe0, 0x81, 0x42, 0x1f, 0xd1,
-0x20, 0x69, 0x02, 0x28, 0x1c, 0xd2, 0x01, 0x20, 0x60, 0x61, 0x18, 0x48,
-0x41, 0x69, 0xe2, 0x6c, 0x0a, 0x43, 0x42, 0x61, 0x81, 0x69, 0xe3, 0x6c,
-0x99, 0x43, 0x81, 0x61, 0x01, 0x21, 0x09, 0x05, 0xca, 0x60, 0x80, 0x69,
-0xc0, 0x46, 0x08, 0x61, 0x8b, 0x02, 0x20, 0x6d, 0x18, 0x43, 0x00, 0x68,
-0xc0, 0x46, 0xa0, 0x61, 0xe1, 0x69, 0x81, 0x42, 0x02, 0xd0, 0x20, 0x1c,
-0xff, 0xf7, 0xcc, 0xfa, 0x28, 0x1c, 0x00, 0xf0, 0x0f, 0xf9, 0x0c, 0x98,
-0x05, 0x99, 0x40, 0x18, 0x00, 0x01, 0x10, 0x30, 0x68, 0x61, 0x13, 0xb0,
-0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02,
-0x7c, 0x29, 0x00, 0x80, 0x00, 0x00, 0x12, 0x02, 0x04, 0x00, 0x52, 0x02,
-0x68, 0x0e, 0x00, 0x80, 0xf0, 0xb5, 0x40, 0x20, 0x2d, 0x49, 0xc0, 0x46,
-0x08, 0x60, 0x00, 0xf0, 0x03, 0xf9, 0x07, 0x1c, 0x81, 0x69, 0x44, 0x6a,
-0xa0, 0x6f, 0x00, 0xf0, 0x45, 0xfe, 0x00, 0x20, 0xe1, 0x1d, 0x19, 0x31,
-0x48, 0x71, 0x79, 0x68, 0xc9, 0x0e, 0x09, 0xd3, 0xf8, 0x6a, 0x00, 0x01,
-0x24, 0x49, 0x40, 0x18, 0x24, 0x4b, 0xc0, 0x18, 0x01, 0x68, 0x01, 0x39,
-0x01, 0x60, 0x36, 0xe0, 0xe1, 0x6d, 0x09, 0x68, 0x22, 0x6e, 0xc0, 0x46,
-0x11, 0x60, 0x20, 0x4e, 0xf5, 0x1d, 0x79, 0x35, 0x01, 0x23, 0xe9, 0x6b,
-0x19, 0x43, 0xe9, 0x63, 0xb9, 0x6a, 0xe2, 0x6d, 0xc0, 0x46, 0x11, 0x60,
-0xb9, 0x6a, 0x22, 0x6e, 0xc0, 0x46, 0x11, 0x60, 0x61, 0x69, 0x00, 0x29,
-0x04, 0xd1, 0xa9, 0x6b, 0x01, 0x31, 0xa9, 0x63, 0x08, 0x29, 0x07, 0xd3,
-0xa8, 0x63, 0x01, 0x20, 0x00, 0xf0, 0x86, 0xf8, 0xe8, 0x6b, 0x40, 0x08,
-0x40, 0x00, 0xe8, 0x63, 0x78, 0x68, 0x81, 0x0e, 0x0f, 0xd2, 0x0b, 0x23,
-0x1b, 0x02, 0xf1, 0x18, 0xc9, 0x68, 0x00, 0x29, 0x06, 0xd0, 0x00, 0x08,
-0x04, 0xd2, 0x20, 0x1c, 0x39, 0x1c, 0x00, 0xf0, 0x43, 0xf8, 0x02, 0xe0,
-0x38, 0x1c, 0x00, 0xf0, 0x05, 0xfa, 0x38, 0x1c, 0xfb, 0xf7, 0x10, 0xfc,
-0x20, 0x1c, 0x00, 0xf0, 0x0b, 0xf8, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47,
-0x00, 0x00, 0x00, 0xb0, 0xa0, 0x1c, 0x00, 0x80, 0xb4, 0x0c, 0x00, 0x00,
+0x09, 0x0c, 0x68, 0x60, 0xe8, 0x6a, 0x00, 0xf0, 0x7b, 0xfa, 0x28, 0xe0,
+0x27, 0xe0, 0xa8, 0x68, 0x00, 0x09, 0x14, 0xd3, 0x68, 0x68, 0x80, 0x0e,
+0x15, 0xd2, 0x01, 0x9a, 0x00, 0x2a, 0x12, 0xd0, 0x01, 0x9a, 0x50, 0x6b,
+0x0b, 0x9b, 0x21, 0x1c, 0x3a, 0x1c, 0xff, 0xf7, 0x89, 0xf9, 0x01, 0x9a,
+0xc0, 0x46, 0x90, 0x64, 0x01, 0x9a, 0x0b, 0x9b, 0xc0, 0x46, 0x93, 0x63,
+0x03, 0xe0, 0xe8, 0x6a, 0x31, 0x1c, 0x00, 0xf0, 0x5d, 0xfa, 0x68, 0x68,
+0x30, 0x43, 0x68, 0x60, 0xa8, 0x69, 0xb0, 0x42, 0x05, 0xd9, 0x00, 0x04,
+0x00, 0x0c, 0x80, 0x1b, 0x00, 0xf0, 0xee, 0xf9, 0xae, 0x61, 0xa8, 0x68,
+0x8c, 0x23, 0x18, 0x40, 0x0b, 0xd0, 0x2f, 0x4a, 0xc0, 0x46, 0x00, 0x92,
+0x04, 0x98, 0xc3, 0x1f, 0x05, 0x3b, 0x2a, 0x48, 0x01, 0x6d, 0x42, 0x6d,
+0x00, 0x20, 0x01, 0xf0, 0x23, 0xf8, 0x01, 0x23, 0x9b, 0x07, 0x20, 0x6d,
+0x18, 0x43, 0x00, 0x68, 0xc0, 0x46, 0xa0, 0x61, 0xe1, 0x69, 0x81, 0x42,
+0x12, 0xd0, 0x22, 0x69, 0x02, 0x2a, 0x0f, 0xd2, 0x41, 0x1a, 0x01, 0xd5,
+0x60, 0x6d, 0x41, 0x18, 0x20, 0x1c, 0xff, 0xf7, 0x3f, 0xfb, 0xe1, 0x69,
+0x40, 0x18, 0xe0, 0x61, 0x61, 0x6d, 0x88, 0x42, 0x24, 0xd3, 0x40, 0x1a,
+0xe0, 0x61, 0x21, 0xe0, 0x81, 0x42, 0x1f, 0xd1, 0x20, 0x69, 0x02, 0x28,
+0x1c, 0xd2, 0x01, 0x20, 0x60, 0x61, 0x18, 0x48, 0x41, 0x69, 0xe2, 0x6c,
+0x0a, 0x43, 0x42, 0x61, 0x81, 0x69, 0xe3, 0x6c, 0x99, 0x43, 0x81, 0x61,
+0x01, 0x21, 0x09, 0x05, 0xca, 0x60, 0x80, 0x69, 0xc0, 0x46, 0x08, 0x61,
+0x8b, 0x02, 0x20, 0x6d, 0x18, 0x43, 0x00, 0x68, 0xc0, 0x46, 0xa0, 0x61,
+0xe1, 0x69, 0x81, 0x42, 0x02, 0xd0, 0x20, 0x1c, 0xff, 0xf7, 0xcc, 0xfa,
+0x28, 0x1c, 0x00, 0xf0, 0x0f, 0xf9, 0x0c, 0x98, 0x05, 0x99, 0x40, 0x18,
+0x00, 0x01, 0x10, 0x30, 0x68, 0x61, 0x13, 0xb0, 0xf0, 0xbc, 0x08, 0xbc,
+0x18, 0x47, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x7c, 0x29, 0x00, 0x80,
+0x00, 0x00, 0x12, 0x02, 0x04, 0x00, 0x52, 0x02, 0x68, 0x0e, 0x00, 0x80,
+0xf0, 0xb5, 0x40, 0x20, 0x2d, 0x49, 0xc0, 0x46, 0x08, 0x60, 0x00, 0xf0,
+0x03, 0xf9, 0x07, 0x1c, 0x81, 0x69, 0x44, 0x6a, 0xa0, 0x6f, 0x00, 0xf0,
+0x45, 0xfe, 0x00, 0x20, 0xe1, 0x1d, 0x19, 0x31, 0x48, 0x71, 0x79, 0x68,
+0xc9, 0x0e, 0x09, 0xd3, 0xf8, 0x6a, 0x00, 0x01, 0x24, 0x49, 0x40, 0x18,
+0x24, 0x4b, 0xc0, 0x18, 0x01, 0x68, 0x01, 0x39, 0x01, 0x60, 0x36, 0xe0,
+0xe1, 0x6d, 0x09, 0x68, 0x22, 0x6e, 0xc0, 0x46, 0x11, 0x60, 0x20, 0x4e,
+0xf5, 0x1d, 0x79, 0x35, 0x01, 0x23, 0xe9, 0x6b, 0x19, 0x43, 0xe9, 0x63,
+0xb9, 0x6a, 0xe2, 0x6d, 0xc0, 0x46, 0x11, 0x60, 0xb9, 0x6a, 0x22, 0x6e,
+0xc0, 0x46, 0x11, 0x60, 0x61, 0x69, 0x00, 0x29, 0x04, 0xd1, 0xa9, 0x6b,
+0x01, 0x31, 0xa9, 0x63, 0x08, 0x29, 0x07, 0xd3, 0xa8, 0x63, 0x01, 0x20,
+0x00, 0xf0, 0x86, 0xf8, 0xe8, 0x6b, 0x40, 0x08, 0x40, 0x00, 0xe8, 0x63,
+0x78, 0x68, 0x81, 0x0e, 0x0f, 0xd2, 0x0b, 0x23, 0x1b, 0x02, 0xf1, 0x18,
+0xc9, 0x68, 0x00, 0x29, 0x06, 0xd0, 0x00, 0x08, 0x04, 0xd2, 0x20, 0x1c,
+0x39, 0x1c, 0x00, 0xf0, 0x43, 0xf8, 0x02, 0xe0, 0x38, 0x1c, 0x00, 0xf0,
+0x05, 0xfa, 0x38, 0x1c, 0xfb, 0xf7, 0x06, 0xfc, 0x20, 0x1c, 0x00, 0xf0,
+0x0b, 0xf8, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x00, 0xb0,
+0xa0, 0x1c, 0x00, 0x80, 0xb4, 0x0c, 0x00, 0x00,
0x68, 0x0e, 0x00, 0x80, 0x80, 0xb5, 0x07, 0x1c, 0xf8, 0x1d, 0x19, 0x30,
-0x01, 0x79, 0x00, 0x29, 0x04, 0xd0, 0x00, 0x21,
-0x01, 0x71, 0x38, 0x1c, 0xff, 0xf7, 0x56, 0xfb, 0xf8, 0x68, 0x02, 0x28,
-0x0d, 0xd0, 0xb8, 0x68, 0x80, 0x00, 0xc2, 0x19, 0x50, 0x6c, 0x00, 0x28,
-0x11, 0xd0, 0xb8, 0x6a, 0x41, 0x78, 0x09, 0x01, 0x10, 0x31, 0x52, 0x6b,
-0x10, 0x1a, 0x88, 0x42, 0x05, 0xd3, 0x38, 0x1c, 0xff, 0xf7, 0x42, 0xfb,
-0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x38, 0x1c, 0xff, 0xf7, 0x28, 0xfa,
-0xf8, 0xe7, 0x78, 0x68, 0x80, 0x00, 0xc0, 0x19, 0xc0, 0x6b, 0xc0, 0x46,
-0xb8, 0x62, 0xf1, 0xe7, 0xb0, 0xb5, 0x87, 0xb0, 0x0f, 0x1c, 0x80, 0x6f,
-0xc0, 0x46, 0x00, 0x90, 0x00, 0x24, 0x13, 0x4d, 0x0b, 0x23, 0x1b, 0x02,
-0xe8, 0x18, 0x80, 0x69, 0x00, 0x28, 0x17, 0xd0, 0x69, 0x46, 0xa2, 0x00,
-0x52, 0x19, 0x0b, 0x23, 0x1b, 0x02, 0xd2, 0x18, 0x92, 0x69, 0x38, 0x1c,
-0x00, 0xf0, 0x92, 0xfb, 0x00, 0x28, 0x09, 0xd1, 0x01, 0x34, 0xa0, 0x00,
-0x40, 0x19, 0x0b, 0x23, 0x1b, 0x02, 0xc0, 0x18, 0x80, 0x69, 0x00, 0x28,
-0xea, 0xd1, 0x01, 0xe0, 0x01, 0x28, 0x02, 0xd0, 0x38, 0x1c, 0x00, 0xf0,
-0x9d, 0xf9, 0x07, 0xb0, 0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00,
-0x68, 0x0e, 0x00, 0x80, 0xb8, 0xb5, 0xc2, 0x07, 0xd2, 0x0f, 0x16, 0x4c,
-0x16, 0x49, 0x01, 0xd0, 0x08, 0x22, 0x08, 0xe0, 0x82, 0x08, 0x05, 0xd3,
-0x0c, 0x22, 0xa4, 0x18, 0x0b, 0x68, 0xdf, 0x1d, 0x15, 0x37, 0x03, 0xe0,
-0x1c, 0x22, 0x0b, 0x68, 0xdf, 0x1d, 0x09, 0x37, 0x0f, 0x4b, 0x1d, 0x78,
-0x00, 0x2d, 0x13, 0xd0, 0x5b, 0x78, 0x00, 0x2b, 0x10, 0xd0, 0x01, 0x23,
-0x5b, 0x06, 0x1a, 0x43, 0x00, 0x28, 0x01, 0xd1, 0x5b, 0x08, 0x1a, 0x43,
-0x00, 0x92, 0x4a, 0x68, 0x01, 0x20, 0x39, 0x1c, 0x23, 0x1c, 0x00, 0xf0,
-0xdf, 0xfe, 0xb8, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x03, 0x23, 0x1b, 0x06,
-0x1a, 0x43, 0xf1, 0xe7, 0x3c, 0xef, 0x20, 0x40, 0x7c, 0x29, 0x00, 0x80,
-0xf8, 0x0e, 0x00, 0x80, 0x00, 0x21, 0xc1, 0x61, 0x05, 0x49, 0x8a, 0x68,
-0x00, 0x2a, 0x01, 0xd1, 0x88, 0x60, 0x02, 0xe0, 0xca, 0x68, 0xc0, 0x46,
-0xd0, 0x61, 0xc8, 0x60, 0x70, 0x47, 0x00, 0x00, 0x28, 0x0f, 0x00, 0x80,
-0x03, 0x49, 0x88, 0x68, 0x00, 0x28, 0x02, 0xd0, 0xc2, 0x69, 0xc0, 0x46,
-0x8a, 0x60, 0x70, 0x47, 0x28, 0x0f, 0x00, 0x80, 0x01, 0x1c, 0x01, 0x23,
-0x88, 0x68, 0x58, 0x40, 0x88, 0x60, 0xca, 0x68, 0x01, 0x3a, 0xca, 0x60,
-0x0a, 0x69, 0x01, 0x3a, 0x80, 0x00, 0x0a, 0x61, 0x42, 0x18, 0xd0, 0x6b,
-0x53, 0x6b, 0xc0, 0x46, 0xcb, 0x62, 0x0b, 0x68, 0x9b, 0x00, 0x59, 0x18,
-0x49, 0x6c, 0x53, 0x6c, 0xc9, 0x18, 0x51, 0x64, 0x70, 0x47, 0x8a, 0x68,
-0x92, 0x00, 0x52, 0x18, 0xd3, 0x6b, 0x83, 0x42, 0x17, 0xd1, 0xd0, 0x1d,
-0x3d, 0x30, 0x0a, 0x68, 0x92, 0x00, 0x52, 0x18, 0x52, 0x6c, 0x03, 0x68,
-0x9a, 0x1a, 0x02, 0x60, 0x01, 0x23, 0x88, 0x68, 0x58, 0x40, 0x88, 0x60,
-0xca, 0x68, 0x01, 0x32, 0xca, 0x60, 0x0a, 0x69, 0x01, 0x32, 0x80, 0x00,
-0x40, 0x18, 0x0a, 0x61, 0x40, 0x6b, 0xc0, 0x46, 0xc8, 0x62, 0x70, 0x47,
-0xb8, 0xb5, 0x04, 0x1c, 0x1d, 0x1c, 0x17, 0x1c, 0x08, 0x1c, 0x39, 0x1c,
-0xff, 0xf7, 0xd9, 0xff, 0x00, 0x20, 0x29, 0x1c, 0x00, 0xf0, 0x7c, 0xfe,
-0x01, 0x20, 0xf9, 0x1d, 0x19, 0x31, 0x48, 0x71, 0x80, 0x06, 0x60, 0x60,
-0x00, 0x20, 0xa0, 0x61, 0x06, 0x4a, 0xc0, 0x46, 0x00, 0x92, 0x06, 0x48,
+0x01, 0x79, 0x00, 0x29, 0x04, 0xd0, 0x00, 0x21, 0x01, 0x71, 0x38, 0x1c,
+0xff, 0xf7, 0x56, 0xfb, 0xf8, 0x68, 0x02, 0x28, 0x0d, 0xd0, 0xb8, 0x68,
+0x80, 0x00, 0xc2, 0x19, 0x50, 0x6c, 0x00, 0x28, 0x11, 0xd0, 0xb8, 0x6a,
+0x41, 0x78, 0x09, 0x01, 0x10, 0x31, 0x52, 0x6b, 0x10, 0x1a, 0x88, 0x42,
+0x05, 0xd3, 0x38, 0x1c, 0xff, 0xf7, 0x42, 0xfb, 0x80, 0xbc, 0x08, 0xbc,
+0x18, 0x47, 0x38, 0x1c, 0xff, 0xf7, 0x28, 0xfa, 0xf8, 0xe7, 0x78, 0x68,
+0x80, 0x00, 0xc0, 0x19, 0xc0, 0x6b, 0xc0, 0x46, 0xb8, 0x62, 0xf1, 0xe7,
+0xb0, 0xb5, 0x87, 0xb0, 0x0f, 0x1c, 0x80, 0x6f, 0xc0, 0x46, 0x00, 0x90,
+0x00, 0x24, 0x13, 0x4d, 0x0b, 0x23, 0x1b, 0x02, 0xe8, 0x18, 0x80, 0x69,
+0x00, 0x28, 0x17, 0xd0, 0x69, 0x46, 0xa2, 0x00, 0x52, 0x19, 0x0b, 0x23,
+0x1b, 0x02, 0xd2, 0x18, 0x92, 0x69, 0x38, 0x1c, 0x00, 0xf0, 0x92, 0xfb,
+0x00, 0x28, 0x09, 0xd1, 0x01, 0x34, 0xa0, 0x00, 0x40, 0x19, 0x0b, 0x23,
+0x1b, 0x02, 0xc0, 0x18, 0x80, 0x69, 0x00, 0x28, 0xea, 0xd1, 0x01, 0xe0,
+0x01, 0x28, 0x02, 0xd0, 0x38, 0x1c, 0x00, 0xf0, 0x9d, 0xf9, 0x07, 0xb0,
+0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x68, 0x0e, 0x00, 0x80,
+0xb8, 0xb5, 0xc2, 0x07, 0xd2, 0x0f, 0x16, 0x4c, 0x16, 0x49, 0x01, 0xd0,
+0x08, 0x22, 0x08, 0xe0, 0x82, 0x08, 0x05, 0xd3, 0x0c, 0x22, 0xa4, 0x18,
+0x0b, 0x68, 0xdf, 0x1d, 0x15, 0x37, 0x03, 0xe0, 0x1c, 0x22, 0x0b, 0x68,
+0xdf, 0x1d, 0x09, 0x37, 0x0f, 0x4b, 0x1d, 0x78, 0x00, 0x2d, 0x13, 0xd0,
+0x5b, 0x78, 0x00, 0x2b, 0x10, 0xd0, 0x01, 0x23, 0x5b, 0x06, 0x1a, 0x43,
+0x00, 0x28, 0x01, 0xd1, 0x5b, 0x08, 0x1a, 0x43, 0x00, 0x92, 0x4a, 0x68,
+0x01, 0x20, 0x39, 0x1c, 0x23, 0x1c, 0x00, 0xf0, 0xdf, 0xfe, 0xb8, 0xbc,
+0x08, 0xbc, 0x18, 0x47, 0x03, 0x23, 0x1b, 0x06, 0x1a, 0x43, 0xf1, 0xe7,
+0x90, 0xee, 0x20, 0x40, 0x7c, 0x29, 0x00, 0x80, 0xf8, 0x0e, 0x00, 0x80,
+0x00, 0x21, 0xc1, 0x61, 0x05, 0x49, 0x8a, 0x68, 0x00, 0x2a, 0x01, 0xd1,
+0x88, 0x60, 0x02, 0xe0, 0xca, 0x68, 0xc0, 0x46, 0xd0, 0x61, 0xc8, 0x60,
+0x70, 0x47, 0x00, 0x00, 0x28, 0x0f, 0x00, 0x80, 0x03, 0x49, 0x88, 0x68,
+0x00, 0x28, 0x02, 0xd0, 0xc2, 0x69, 0xc0, 0x46, 0x8a, 0x60, 0x70, 0x47,
+0x28, 0x0f, 0x00, 0x80, 0x01, 0x1c, 0x01, 0x23, 0x88, 0x68, 0x58, 0x40,
+0x88, 0x60, 0xca, 0x68, 0x01, 0x3a, 0xca, 0x60, 0x0a, 0x69, 0x01, 0x3a,
+0x80, 0x00, 0x0a, 0x61, 0x42, 0x18, 0xd0, 0x6b, 0x53, 0x6b, 0xc0, 0x46,
+0xcb, 0x62, 0x0b, 0x68, 0x9b, 0x00, 0x59, 0x18, 0x49, 0x6c, 0x53, 0x6c,
+0xc9, 0x18, 0x51, 0x64, 0x70, 0x47, 0x8a, 0x68, 0x92, 0x00, 0x52, 0x18,
+0xd3, 0x6b, 0x83, 0x42, 0x17, 0xd1, 0xd0, 0x1d, 0x3d, 0x30, 0x0a, 0x68,
+0x92, 0x00, 0x52, 0x18, 0x52, 0x6c, 0x03, 0x68, 0x9a, 0x1a, 0x02, 0x60,
+0x01, 0x23, 0x88, 0x68, 0x58, 0x40, 0x88, 0x60, 0xca, 0x68, 0x01, 0x32,
+0xca, 0x60, 0x0a, 0x69, 0x01, 0x32, 0x80, 0x00, 0x40, 0x18, 0x0a, 0x61,
+0x40, 0x6b, 0xc0, 0x46, 0xc8, 0x62, 0x70, 0x47, 0xb8, 0xb5, 0x04, 0x1c,
+0x1d, 0x1c, 0x17, 0x1c, 0x08, 0x1c, 0x39, 0x1c, 0xff, 0xf7, 0xd9, 0xff,
+0x00, 0x20, 0x29, 0x1c, 0x00, 0xf0, 0x7c, 0xfe, 0x01, 0x20, 0xf9, 0x1d,
+0x19, 0x31, 0x48, 0x71, 0x80, 0x06, 0x60, 0x60, 0x00, 0x20, 0xa0, 0x61,
+0x06, 0x4a, 0xc0, 0x46, 0x00, 0x92, 0x06, 0x48,
0x01, 0x6d, 0x42, 0x6d, 0x05, 0x4b, 0x00, 0x20, 0x00, 0xf0, 0x62, 0xfe,
-0xb8, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00,
-0x04, 0x00, 0x12, 0x02, 0x7c, 0x29, 0x00, 0x80, 0x44, 0x80, 0x20, 0x40,
+0xb8, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x04, 0x00, 0x12, 0x02,
+0x7c, 0x29, 0x00, 0x80, 0x44, 0x80, 0x20, 0x40, 0x06, 0x49, 0x0a, 0x68,
+0x10, 0x18, 0x08, 0x60, 0x01, 0x23, 0x5b, 0x02, 0x98, 0x42, 0x03, 0xd9,
+0x03, 0x49, 0x0a, 0x79, 0x01, 0x32, 0x0a, 0x71, 0x70, 0x47, 0x00, 0x00,
+0xe4, 0x2d, 0x00, 0x80, 0xa0, 0x82, 0x20, 0x40, 0x80, 0x08, 0x80, 0x00,
0x06, 0x49, 0x0a, 0x68, 0x10, 0x18, 0x08, 0x60, 0x01, 0x23, 0x5b, 0x02,
0x98, 0x42, 0x03, 0xd9, 0x03, 0x49, 0x0a, 0x79, 0x01, 0x32, 0x0a, 0x71,
0x70, 0x47, 0x00, 0x00, 0xe4, 0x2d, 0x00, 0x80, 0xa0, 0x82, 0x20, 0x40,
-0x80, 0x08, 0x80, 0x00, 0x06, 0x49, 0x0a, 0x68, 0x10, 0x18, 0x08, 0x60,
-0x01, 0x23, 0x5b, 0x02, 0x98, 0x42, 0x03, 0xd9, 0x03, 0x49, 0x0a, 0x79,
-0x01, 0x32, 0x0a, 0x71, 0x70, 0x47, 0x00, 0x00, 0xe4, 0x2d, 0x00, 0x80,
-0xa0, 0x82, 0x20, 0x40, 0x03, 0x30, 0x80, 0x08, 0x80, 0x00, 0x06, 0x49,
-0x0a, 0x68, 0x10, 0x18, 0x08, 0x60, 0x01, 0x23, 0x5b, 0x02, 0x98, 0x42,
-0x03, 0xd9, 0x03, 0x49, 0x0a, 0x79, 0x01, 0x32, 0x0a, 0x71, 0x70, 0x47,
-0xe4, 0x2d, 0x00, 0x80, 0xa0, 0x82, 0x20, 0x40, 0x02, 0x48, 0x41, 0x79,
-0x01, 0x31, 0x41, 0x71, 0x70, 0x47, 0x00, 0x00, 0xa0, 0x82, 0x20, 0x40,
-0x90, 0xb4, 0x82, 0x00, 0x17, 0x4b, 0x9a, 0x58, 0x8b, 0x07, 0x02, 0xd0,
-0x89, 0x08, 0x0b, 0x1d, 0x01, 0xe0, 0x89, 0x08, 0xcb, 0x1c, 0x11, 0x69,
-0xd7, 0x68, 0x12, 0x4c, 0x80, 0x00, 0x20, 0x58, 0x40, 0x68, 0xb9, 0x42,
-0x03, 0xd1, 0x81, 0x42, 0x19, 0xd9, 0x11, 0x68, 0x17, 0xe0, 0x00, 0x24,
-0xb9, 0x42, 0x09, 0xd9, 0x81, 0x42, 0x12, 0xd9, 0x11, 0x68, 0x78, 0x1a,
-0x00, 0xd5, 0x03, 0x30, 0x80, 0x10, 0x98, 0x42, 0x0b, 0xd8, 0x07, 0xe0,
-0x81, 0x42, 0x05, 0xd8, 0x78, 0x1a, 0x00, 0xd5, 0x03, 0x30, 0x80, 0x10,
-0x98, 0x42, 0x02, 0xd8, 0x20, 0x1c, 0x90, 0xbc, 0x70, 0x47, 0xc8, 0x1d,
-0x05, 0x30, 0xfa, 0xe7, 0x70, 0x04, 0x00, 0x80, 0x80, 0xb5, 0x80, 0x00,
-0x0f, 0x4a, 0x17, 0x58, 0x88, 0x07, 0x02, 0xd0, 0x88, 0x08, 0x04, 0x30,
-0x01, 0xe0, 0x88, 0x08, 0x03, 0x30, 0x39, 0x69, 0x7a, 0x68, 0x91, 0x42,
-0x09, 0xd9, 0x39, 0x68, 0xc0, 0x46, 0x39, 0x61, 0xf9, 0x68, 0x7a, 0x68,
+0x03, 0x30, 0x80, 0x08, 0x80, 0x00, 0x06, 0x49, 0x0a, 0x68, 0x10, 0x18,
+0x08, 0x60, 0x01, 0x23, 0x5b, 0x02, 0x98, 0x42, 0x03, 0xd9, 0x03, 0x49,
+0x0a, 0x79, 0x01, 0x32, 0x0a, 0x71, 0x70, 0x47, 0xe4, 0x2d, 0x00, 0x80,
+0xa0, 0x82, 0x20, 0x40, 0x02, 0x48, 0x41, 0x79, 0x01, 0x31, 0x41, 0x71,
+0x70, 0x47, 0x00, 0x00, 0xa0, 0x82, 0x20, 0x40, 0x90, 0xb4, 0x82, 0x00,
+0x17, 0x4b, 0x9a, 0x58, 0x8b, 0x07, 0x02, 0xd0, 0x89, 0x08, 0x0b, 0x1d,
+0x01, 0xe0, 0x89, 0x08, 0xcb, 0x1c, 0x11, 0x69, 0xd7, 0x68, 0x12, 0x4c,
+0x80, 0x00, 0x20, 0x58, 0x40, 0x68, 0xb9, 0x42, 0x03, 0xd1, 0x81, 0x42,
+0x19, 0xd9, 0x11, 0x68, 0x17, 0xe0, 0x00, 0x24, 0xb9, 0x42, 0x09, 0xd9,
+0x81, 0x42, 0x12, 0xd9, 0x11, 0x68, 0x78, 0x1a, 0x00, 0xd5, 0x03, 0x30,
+0x80, 0x10, 0x98, 0x42, 0x0b, 0xd8, 0x07, 0xe0, 0x81, 0x42, 0x05, 0xd8,
+0x78, 0x1a, 0x00, 0xd5, 0x03, 0x30, 0x80, 0x10, 0x98, 0x42, 0x02, 0xd8,
+0x20, 0x1c, 0x90, 0xbc, 0x70, 0x47, 0xc8, 0x1d, 0x05, 0x30, 0xfa, 0xe7,
+0x70, 0x04, 0x00, 0x80, 0x80, 0xb5, 0x80, 0x00, 0x0f, 0x4a, 0x17, 0x58,
+0x88, 0x07, 0x02, 0xd0, 0x88, 0x08, 0x04, 0x30, 0x01, 0xe0, 0x88, 0x08,
+0x03, 0x30, 0x39, 0x69, 0x7a, 0x68, 0x91, 0x42, 0x09, 0xd9, 0x39, 0x68,
+0xc0, 0x46, 0x39, 0x61, 0xf9, 0x68, 0x7a, 0x68, 0x91, 0x42, 0x02, 0xd9,
+0x39, 0x68, 0xc0, 0x46, 0xf9, 0x60, 0x81, 0x00, 0x38, 0x69, 0x00, 0xf0,
+0xd1, 0xfd, 0x38, 0x61, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00,
+0x70, 0x04, 0x00, 0x80, 0x90, 0xb5, 0x03, 0x21, 0x09, 0x07, 0x01, 0x40,
+0x0c, 0x0f, 0x01, 0x04, 0x09, 0x0c, 0x01, 0x22, 0x92, 0x07, 0x02, 0x40,
+0xa3, 0x00, 0x1c, 0x4f, 0xff, 0x58, 0x89, 0x07, 0x89, 0x0f, 0x00, 0x04,
+0x00, 0x0c, 0x80, 0x08, 0x00, 0x29, 0x00, 0xd0, 0x01, 0x30, 0x00, 0x2a,
+0x01, 0xd0, 0x02, 0x30, 0x00, 0xe0, 0x03, 0x30, 0xf9, 0x68, 0x7a, 0x68,
0x91, 0x42, 0x02, 0xd9, 0x39, 0x68, 0xc0, 0x46, 0xf9, 0x60, 0x81, 0x00,
-0x38, 0x69, 0x00, 0xf0, 0xd1, 0xfd, 0x38, 0x61, 0x80, 0xbc, 0x08, 0xbc,
-0x18, 0x47, 0x00, 0x00, 0x70, 0x04, 0x00, 0x80, 0x90, 0xb5, 0x03, 0x21,
-0x09, 0x07, 0x01, 0x40, 0x0c, 0x0f, 0x01, 0x04, 0x09, 0x0c, 0x01, 0x22,
-0x92, 0x07, 0x02, 0x40, 0xa3, 0x00, 0x1c, 0x4f, 0xff, 0x58, 0x89, 0x07,
-0x89, 0x0f, 0x00, 0x04, 0x00, 0x0c, 0x80, 0x08, 0x00, 0x29, 0x00, 0xd0,
-0x01, 0x30, 0x00, 0x2a, 0x01, 0xd0, 0x02, 0x30, 0x00, 0xe0, 0x03, 0x30,
-0xf9, 0x68, 0x7a, 0x68, 0x91, 0x42, 0x02, 0xd9, 0x39, 0x68, 0xc0, 0x46,
-0xf9, 0x60, 0x81, 0x00, 0xf8, 0x68, 0x00, 0xf0, 0xa5, 0xfd, 0xf8, 0x60,
-0x0f, 0x48, 0x00, 0x69, 0x00, 0x28, 0x05, 0xd0, 0x01, 0x20, 0xa0, 0x40,
-0x02, 0xd0, 0x20, 0x1c, 0xfe, 0xf7, 0xca, 0xfc, 0x0b, 0x49, 0xc8, 0x1d,
-0x19, 0x30, 0x03, 0x79, 0x00, 0x22, 0x00, 0x2b, 0x05, 0xd1, 0x09, 0x49,
-0xc8, 0x1d, 0x19, 0x30, 0x03, 0x79, 0x00, 0x2b, 0x03, 0xd0, 0x02, 0x71,
-0x08, 0x1c, 0xff, 0xf7, 0x79, 0xf9, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47,
-0x70, 0x04, 0x00, 0x80, 0xd0, 0x2c, 0x00, 0x80, 0x64, 0x2d, 0x00, 0x80,
-0xe4, 0x2c, 0x00, 0x80, 0xb0, 0xb5, 0x2b, 0x49, 0x09, 0x79, 0x00, 0x29,
-0x03, 0xd1, 0x41, 0x68, 0x29, 0x4b, 0x19, 0x43, 0x41, 0x60, 0x81, 0x68,
+0xf8, 0x68, 0x00, 0xf0, 0xa5, 0xfd, 0xf8, 0x60, 0x0f, 0x48, 0x00, 0x69,
+0x00, 0x28, 0x05, 0xd0, 0x01, 0x20, 0xa0, 0x40, 0x02, 0xd0, 0x20, 0x1c,
+0xfe, 0xf7, 0xca, 0xfc, 0x0b, 0x49, 0xc8, 0x1d, 0x19, 0x30, 0x03, 0x79,
+0x00, 0x22, 0x00, 0x2b, 0x05, 0xd1, 0x09, 0x49, 0xc8, 0x1d, 0x19, 0x30,
+0x03, 0x79, 0x00, 0x2b, 0x03, 0xd0, 0x02, 0x71, 0x08, 0x1c, 0xff, 0xf7,
+0x79, 0xf9, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x70, 0x04, 0x00, 0x80,
+0xd0, 0x2c, 0x00, 0x80, 0x64, 0x2d, 0x00, 0x80, 0xe4, 0x2c, 0x00, 0x80,
+0xb0, 0xb5, 0x2b, 0x49, 0x09, 0x79, 0x00, 0x29, 0x03, 0xd1, 0x41, 0x68,
+0x29, 0x4b, 0x19, 0x43, 0x41, 0x60, 0x81, 0x68,
0x49, 0x08, 0x02, 0xd3, 0x09, 0x21, 0x09, 0x04, 0x01, 0xe0, 0x0d, 0x21,
-0x09, 0x04, 0x0c, 0xc8, 0x08, 0x38, 0x19, 0x43,
-0x87, 0x68, 0xbb, 0x0a, 0x03, 0xd3, 0x43, 0x68, 0x5b, 0x08, 0x00, 0xd3,
-0x01, 0x31, 0x40, 0x68, 0x03, 0x23, 0x1b, 0x07, 0x18, 0x40, 0x07, 0x0f,
-0xf8, 0x00, 0x1d, 0x4c, 0x00, 0x19, 0x23, 0x68, 0xc0, 0x18, 0x50, 0x30,
-0x00, 0x79, 0x01, 0x28, 0x10, 0xd1, 0x60, 0x68, 0x01, 0x28, 0x0d, 0xd0,
-0x10, 0x1c, 0x00, 0xf0, 0x71, 0xf8, 0x38, 0x01, 0x00, 0x19, 0x19, 0x23,
-0xdb, 0x01, 0xc0, 0x18, 0x41, 0x6b, 0x01, 0x39, 0x41, 0x63, 0xb0, 0xbc,
-0x08, 0xbc, 0x18, 0x47, 0x38, 0x01, 0x00, 0x19, 0x19, 0x23, 0xdb, 0x01,
-0xc0, 0x18, 0x03, 0x6b, 0x5d, 0x1c, 0x05, 0x63, 0xbd, 0x02, 0x2d, 0x19,
-0xdb, 0x00, 0xeb, 0x18, 0x80, 0x33, 0x19, 0x63, 0xda, 0x62, 0x81, 0x6b,
-0x01, 0x31, 0x81, 0x63, 0x01, 0x21, 0xb9, 0x40, 0x22, 0x68, 0x11, 0x43,
-0x21, 0x60, 0x01, 0x6b, 0x80, 0x29, 0xe2, 0xd3, 0x00, 0x21, 0x01, 0x63,
-0xdf, 0xe7, 0x00, 0x00, 0x28, 0x0f, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80,
-0xa0, 0x1c, 0x00, 0x80, 0xf0, 0xb5, 0x1f, 0x4e, 0x70, 0x68, 0x00, 0x28,
-0x36, 0xd1, 0x00, 0x24, 0xb1, 0x68, 0x48, 0x1c, 0xc9, 0x00, 0x89, 0x19,
-0xb0, 0x60, 0x32, 0x68, 0x89, 0x18, 0x60, 0x31, 0x0d, 0x7b, 0x08, 0x28,
-0x00, 0xd3, 0xb4, 0x60, 0x28, 0x01, 0x80, 0x19, 0x19, 0x23, 0xdb, 0x01,
-0xc0, 0x18, 0x87, 0x6b, 0x00, 0x2f, 0x21, 0xd0, 0xc1, 0x6a, 0x4b, 0x1c,
-0xaa, 0x02, 0x92, 0x19, 0xc9, 0x00, 0x51, 0x18, 0x80, 0x31, 0xc3, 0x62,
-0xca, 0x6a, 0x09, 0x6b, 0x01, 0x3f, 0x87, 0x63, 0x80, 0x2b, 0x00, 0xd3,
-0xc4, 0x62, 0x00, 0x2f, 0x06, 0xd1, 0x01, 0x27, 0xaf, 0x40, 0x3b, 0x1c,
-0xdb, 0x43, 0x37, 0x68, 0x3b, 0x40, 0x33, 0x60, 0x43, 0x6b, 0x01, 0x3b,
-0x43, 0x63, 0x10, 0x1c, 0x37, 0x1c, 0x00, 0xf0, 0x09, 0xf8, 0x78, 0x68,
-0x00, 0x28, 0xc9, 0xd0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00,
-0xa0, 0x1c, 0x00, 0x80, 0xf0, 0xb5, 0xcd, 0x0f, 0xed, 0x07, 0x01, 0x24,
-0x00, 0x27, 0x2e, 0x4b, 0x2e, 0x4a, 0x00, 0x2d, 0x1d, 0xd0, 0xd8, 0x6a,
-0x01, 0x30, 0xd8, 0x62, 0x10, 0x1c, 0x52, 0x69, 0x00, 0x2a, 0x12, 0xd0,
-0x02, 0x69, 0x53, 0x1c, 0x92, 0x00, 0x12, 0x18, 0x03, 0x61, 0x91, 0x61,
-0x41, 0x69, 0x01, 0x31, 0x41, 0x61, 0x02, 0x69, 0x0f, 0x2a, 0x00, 0xd3,
-0x07, 0x61, 0x0f, 0x29, 0x00, 0xd3, 0x44, 0x60, 0xf0, 0xbc, 0x08, 0xbc,
-0x18, 0x47, 0x08, 0x1c, 0xff, 0xf7, 0xee, 0xfe, 0xf8, 0xe7, 0x15, 0x69,
-0x6e, 0x1c, 0xad, 0x00, 0xad, 0x18, 0x16, 0x61, 0xa9, 0x61, 0x55, 0x69,
-0x01, 0x35, 0x55, 0x61, 0x16, 0x69, 0x0f, 0x2e, 0x00, 0xd3, 0x17, 0x61,
-0x0f, 0x2d, 0x00, 0xd3, 0x54, 0x60, 0x8c, 0x02, 0xa4, 0x0a, 0x16, 0x4f,
-0x3a, 0x6f, 0xfd, 0x68, 0xf9, 0x1d, 0x79, 0x31, 0x01, 0x2d, 0x0c, 0xd1,
-0xdb, 0x6d, 0x5b, 0x08, 0x09, 0xd3, 0x0b, 0x89, 0x00, 0x2b, 0x06, 0xd1,
-0xfd, 0x6f, 0x03, 0x3b, 0x2e, 0x68, 0x33, 0x40, 0x2b, 0x60, 0x14, 0x23,
-0x0b, 0x81, 0x10, 0x60, 0x80, 0x07, 0x80, 0x0a, 0x20, 0x43, 0x03, 0x04,
-0x00, 0xd0, 0x01, 0x38, 0x50, 0x60, 0x09, 0x6a, 0x08, 0x32, 0x91, 0x42,
-0x00, 0xd8, 0x07, 0x4a, 0x00, 0x0d, 0x02, 0xd3, 0x51, 0x20, 0x80, 0x03,
-0x82, 0x61, 0x3a, 0x67, 0xbe, 0xe7, 0x00, 0x00, 0xa4, 0x2a, 0x00, 0x80,
-0xa0, 0x1c, 0x00, 0x80, 0x68, 0x0e, 0x00, 0x80, 0x24, 0xa7, 0x20, 0x40,
+0x09, 0x04, 0x0c, 0xc8, 0x08, 0x38, 0x19, 0x43, 0x87, 0x68, 0xbb, 0x0a,
+0x03, 0xd3, 0x43, 0x68, 0x5b, 0x08, 0x00, 0xd3, 0x01, 0x31, 0x40, 0x68,
+0x03, 0x23, 0x1b, 0x07, 0x18, 0x40, 0x07, 0x0f, 0xf8, 0x00, 0x1d, 0x4c,
+0x00, 0x19, 0x23, 0x68, 0xc0, 0x18, 0x50, 0x30, 0x00, 0x79, 0x01, 0x28,
+0x10, 0xd1, 0x60, 0x68, 0x01, 0x28, 0x0d, 0xd0, 0x10, 0x1c, 0x00, 0xf0,
+0x71, 0xf8, 0x38, 0x01, 0x00, 0x19, 0x19, 0x23, 0xdb, 0x01, 0xc0, 0x18,
+0x41, 0x6b, 0x01, 0x39, 0x41, 0x63, 0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47,
+0x38, 0x01, 0x00, 0x19, 0x19, 0x23, 0xdb, 0x01, 0xc0, 0x18, 0x03, 0x6b,
+0x5d, 0x1c, 0x05, 0x63, 0xbd, 0x02, 0x2d, 0x19, 0xdb, 0x00, 0xeb, 0x18,
+0x80, 0x33, 0x19, 0x63, 0xda, 0x62, 0x81, 0x6b, 0x01, 0x31, 0x81, 0x63,
+0x01, 0x21, 0xb9, 0x40, 0x22, 0x68, 0x11, 0x43, 0x21, 0x60, 0x01, 0x6b,
+0x80, 0x29, 0xe2, 0xd3, 0x00, 0x21, 0x01, 0x63, 0xdf, 0xe7, 0x00, 0x00,
+0x28, 0x0f, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0xa0, 0x1c, 0x00, 0x80,
+0xf0, 0xb5, 0x1f, 0x4e, 0x70, 0x68, 0x00, 0x28, 0x36, 0xd1, 0x00, 0x24,
+0xb1, 0x68, 0x48, 0x1c, 0xc9, 0x00, 0x89, 0x19, 0xb0, 0x60, 0x32, 0x68,
+0x89, 0x18, 0x60, 0x31, 0x0d, 0x7b, 0x08, 0x28, 0x00, 0xd3, 0xb4, 0x60,
+0x28, 0x01, 0x80, 0x19, 0x19, 0x23, 0xdb, 0x01, 0xc0, 0x18, 0x87, 0x6b,
+0x00, 0x2f, 0x21, 0xd0, 0xc1, 0x6a, 0x4b, 0x1c, 0xaa, 0x02, 0x92, 0x19,
+0xc9, 0x00, 0x51, 0x18, 0x80, 0x31, 0xc3, 0x62, 0xca, 0x6a, 0x09, 0x6b,
+0x01, 0x3f, 0x87, 0x63, 0x80, 0x2b, 0x00, 0xd3, 0xc4, 0x62, 0x00, 0x2f,
+0x06, 0xd1, 0x01, 0x27, 0xaf, 0x40, 0x3b, 0x1c, 0xdb, 0x43, 0x37, 0x68,
+0x3b, 0x40, 0x33, 0x60, 0x43, 0x6b, 0x01, 0x3b, 0x43, 0x63, 0x10, 0x1c,
+0x37, 0x1c, 0x00, 0xf0, 0x09, 0xf8, 0x78, 0x68, 0x00, 0x28, 0xc9, 0xd0,
+0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0xa0, 0x1c, 0x00, 0x80,
+0xf0, 0xb5, 0xcd, 0x0f, 0xed, 0x07, 0x01, 0x24, 0x00, 0x27, 0x2e, 0x4b,
+0x2e, 0x4a, 0x00, 0x2d, 0x1d, 0xd0, 0xd8, 0x6a, 0x01, 0x30, 0xd8, 0x62,
+0x10, 0x1c, 0x52, 0x69, 0x00, 0x2a, 0x12, 0xd0, 0x02, 0x69, 0x53, 0x1c,
+0x92, 0x00, 0x12, 0x18, 0x03, 0x61, 0x91, 0x61, 0x41, 0x69, 0x01, 0x31,
+0x41, 0x61, 0x02, 0x69, 0x0f, 0x2a, 0x00, 0xd3, 0x07, 0x61, 0x0f, 0x29,
+0x00, 0xd3, 0x44, 0x60, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x08, 0x1c,
+0xff, 0xf7, 0xee, 0xfe, 0xf8, 0xe7, 0x15, 0x69, 0x6e, 0x1c, 0xad, 0x00,
+0xad, 0x18, 0x16, 0x61, 0xa9, 0x61, 0x55, 0x69, 0x01, 0x35, 0x55, 0x61,
+0x16, 0x69, 0x0f, 0x2e, 0x00, 0xd3, 0x17, 0x61, 0x0f, 0x2d, 0x00, 0xd3,
+0x54, 0x60, 0x8c, 0x02, 0xa4, 0x0a, 0x16, 0x4f, 0x3a, 0x6f, 0xfd, 0x68,
+0xf9, 0x1d, 0x79, 0x31, 0x01, 0x2d, 0x0c, 0xd1, 0xdb, 0x6d, 0x5b, 0x08,
+0x09, 0xd3, 0x0b, 0x89, 0x00, 0x2b, 0x06, 0xd1, 0xfd, 0x6f, 0x03, 0x3b,
+0x2e, 0x68, 0x33, 0x40, 0x2b, 0x60, 0x14, 0x23, 0x0b, 0x81, 0x10, 0x60,
+0x80, 0x07, 0x80, 0x0a, 0x20, 0x43, 0x03, 0x04, 0x00, 0xd0, 0x01, 0x38,
+0x50, 0x60, 0x09, 0x6a, 0x08, 0x32, 0x91, 0x42, 0x00, 0xd8, 0x07, 0x4a,
+0x00, 0x0d, 0x02, 0xd3, 0x51, 0x20, 0x80, 0x03, 0x82, 0x61, 0x3a, 0x67,
+0xbe, 0xe7, 0x00, 0x00, 0xa4, 0x2a, 0x00, 0x80, 0xa0, 0x1c, 0x00, 0x80,
+0x68, 0x0e, 0x00, 0x80, 0x24, 0xa7, 0x20, 0x40,
0xb0, 0xb5, 0x00, 0x28, 0x04, 0xd1, 0x01, 0x20, 0xc0, 0x05, 0x16, 0x49,
-0xc0, 0x46, 0x08, 0x60, 0x15, 0x4c, 0x00, 0x25,
-0x67, 0x69, 0x00, 0x2f, 0x16, 0xd0, 0xe0, 0x68, 0x41, 0x1c, 0x80, 0x00,
-0x00, 0x19, 0xe1, 0x60, 0x80, 0x69, 0x01, 0x3f, 0xff, 0xf7, 0x94, 0xfe,
-0xe0, 0x68, 0x0f, 0x28, 0x00, 0xd3, 0xe5, 0x60, 0xe0, 0x68, 0x80, 0x00,
-0x00, 0x19, 0x80, 0x69, 0x00, 0x08, 0x01, 0xd3, 0x00, 0x2f, 0xea, 0xd1,
-0x67, 0x61, 0x03, 0xe0, 0x08, 0x48, 0x01, 0x6d, 0x01, 0x31, 0x01, 0x65,
-0x65, 0x60, 0x20, 0x68, 0x00, 0x28, 0x01, 0xd0, 0xff, 0xf7, 0x26, 0xff,
-0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0,
-0xa0, 0x1c, 0x00, 0x80, 0xa0, 0x82, 0x20, 0x40, 0x00, 0x20, 0x70, 0x47,
-0xb0, 0xb4, 0x10, 0x23, 0x82, 0x68, 0x13, 0x40, 0x00, 0x21, 0x00, 0x2b,
-0x15, 0xd0, 0x0c, 0x4b, 0x1a, 0x40, 0x12, 0x01, 0x81, 0x24, 0x14, 0x43,
-0x02, 0x68, 0x15, 0x68, 0x13, 0x1d, 0x80, 0xcb, 0x1b, 0x68, 0x04, 0x3a,
-0x02, 0x60, 0x20, 0xc2, 0x80, 0xc2, 0x08, 0xc2, 0x14, 0x60, 0x42, 0x68,
-0x01, 0x23, 0x9b, 0x07, 0x04, 0x32, 0x1a, 0x43, 0x42, 0x60, 0x08, 0x1c,
-0xb0, 0xbc, 0x70, 0x47, 0x00, 0xf0, 0xff, 0x0f, 0xf0, 0xb4, 0x82, 0x68,
-0x53, 0x09, 0x34, 0xd3, 0x1b, 0x4b, 0x1a, 0x40, 0x12, 0x01, 0x81, 0x26,
-0x16, 0x43, 0x03, 0x68, 0x1d, 0x68, 0x1f, 0x1d, 0x10, 0xcf, 0x3f, 0x68,
-0x04, 0x3b, 0x03, 0x60, 0x20, 0xc3, 0x10, 0xc3, 0x80, 0xc3, 0x1e, 0x60,
-0x43, 0x68, 0x1f, 0x1d, 0x01, 0x23, 0x9b, 0x07, 0x3b, 0x43, 0x43, 0x60,
-0xcb, 0x6b, 0x18, 0x1f, 0xc8, 0x63, 0x80, 0xcb, 0x80, 0xc0, 0x1c, 0x68,
-0x1f, 0x1d, 0x03, 0x1d, 0x04, 0x60, 0x38, 0x1c, 0x3f, 0x68, 0xc0, 0x46,
-0x1f, 0x60, 0x1f, 0x1d, 0x43, 0x68, 0x1c, 0x04, 0x24, 0x0c, 0x81, 0x23,
-0x23, 0x43, 0x3b, 0x60, 0x40, 0x68, 0x00, 0x0c, 0x00, 0x04, 0x10, 0x43,
-0x78, 0x60, 0x08, 0x6e, 0x04, 0x30, 0x08, 0x66, 0x48, 0x6e, 0x04, 0x30,
-0x48, 0x66, 0x00, 0x20, 0xf0, 0xbc, 0x70, 0x47, 0x00, 0xf0, 0xff, 0x0f,
-0x80, 0xb4, 0x81, 0x6a, 0x01, 0x23, 0x9b, 0x07, 0xca, 0x1d, 0x05, 0x32,
-0x1a, 0x43, 0x12, 0x68, 0xcf, 0x1d, 0x01, 0x37, 0x3b, 0x43, 0x1b, 0x68,
-0xc0, 0x46, 0xcb, 0x60, 0x01, 0x23, 0x9b, 0x07, 0x0f, 0x1d, 0x3b, 0x43,
-0x1b, 0x68, 0xc0, 0x46, 0x8b, 0x60, 0x01, 0x23, 0x9b, 0x07, 0x0b, 0x43,
-0x1b, 0x68, 0x0c, 0xc1, 0x02, 0x62, 0x01, 0x6b, 0xc0, 0x46, 0x0a, 0x62,
-0x04, 0x23, 0x81, 0x69, 0x19, 0x43, 0x81, 0x61, 0x02, 0x6b, 0xc0, 0x46,
-0x91, 0x61, 0x81, 0x6a, 0x04, 0x31, 0x81, 0x62, 0x02, 0x6b, 0xc0, 0x46,
-0x91, 0x62, 0xc1, 0x1d, 0x39, 0x31, 0x4a, 0x8b, 0x04, 0x3a, 0x4a, 0x83,
-0x49, 0x8b, 0x02, 0x6b, 0x40, 0x32, 0x51, 0x83, 0xc1, 0x89, 0x04, 0x39,
-0xc1, 0x81, 0xc1, 0x68, 0x00, 0x6b, 0xc0, 0x46, 0xc1, 0x60, 0x00, 0x20,
-0x80, 0xbc, 0x70, 0x47, 0x00, 0x47, 0x08, 0x47, 0x10, 0x47, 0x18, 0x47,
-0x20, 0x47, 0x28, 0x47, 0x30, 0x47, 0x38, 0x47, 0x30, 0x40, 0x2d, 0xe9,
-0x0c, 0xc0, 0x9d, 0xe5, 0x0c, 0x48, 0xa0, 0xe1, 0x24, 0x48, 0xb0, 0xe1,
-0x1e, 0x00, 0x00, 0x0a, 0x01, 0xc0, 0x4c, 0xe2, 0x18, 0x40, 0xa0, 0xe3,
-0x64, 0x51, 0x9f, 0xe5, 0x94, 0x50, 0x20, 0xe0, 0x00, 0x50, 0x90, 0xe5,
-0x14, 0x40, 0x90, 0xe5, 0x00, 0x30, 0x85, 0xe5, 0x04, 0xc0, 0x85, 0xe5,
-0x08, 0x10, 0x85, 0xe5, 0x0c, 0x20, 0x85, 0xe5, 0x10, 0x10, 0x90, 0xe5,
+0xc0, 0x46, 0x08, 0x60, 0x15, 0x4c, 0x00, 0x25, 0x67, 0x69, 0x00, 0x2f,
+0x16, 0xd0, 0xe0, 0x68, 0x41, 0x1c, 0x80, 0x00, 0x00, 0x19, 0xe1, 0x60,
+0x80, 0x69, 0x01, 0x3f, 0xff, 0xf7, 0x94, 0xfe, 0xe0, 0x68, 0x0f, 0x28,
+0x00, 0xd3, 0xe5, 0x60, 0xe0, 0x68, 0x80, 0x00, 0x00, 0x19, 0x80, 0x69,
+0x00, 0x08, 0x01, 0xd3, 0x00, 0x2f, 0xea, 0xd1, 0x67, 0x61, 0x03, 0xe0,
+0x08, 0x48, 0x01, 0x6d, 0x01, 0x31, 0x01, 0x65, 0x65, 0x60, 0x20, 0x68,
+0x00, 0x28, 0x01, 0xd0, 0xff, 0xf7, 0x26, 0xff, 0xb0, 0xbc, 0x08, 0xbc,
+0x18, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0xa0, 0x1c, 0x00, 0x80,
+0xa0, 0x82, 0x20, 0x40, 0x00, 0x20, 0x70, 0x47, 0xb0, 0xb4, 0x10, 0x23,
+0x82, 0x68, 0x13, 0x40, 0x00, 0x21, 0x00, 0x2b, 0x15, 0xd0, 0x0c, 0x4b,
+0x1a, 0x40, 0x12, 0x01, 0x81, 0x24, 0x14, 0x43, 0x02, 0x68, 0x15, 0x68,
+0x13, 0x1d, 0x80, 0xcb, 0x1b, 0x68, 0x04, 0x3a, 0x02, 0x60, 0x20, 0xc2,
+0x80, 0xc2, 0x08, 0xc2, 0x14, 0x60, 0x42, 0x68, 0x01, 0x23, 0x9b, 0x07,
+0x04, 0x32, 0x1a, 0x43, 0x42, 0x60, 0x08, 0x1c, 0xb0, 0xbc, 0x70, 0x47,
+0x00, 0xf0, 0xff, 0x0f, 0xf0, 0xb4, 0x82, 0x68, 0x53, 0x09, 0x34, 0xd3,
+0x1b, 0x4b, 0x1a, 0x40, 0x12, 0x01, 0x81, 0x26, 0x16, 0x43, 0x03, 0x68,
+0x1d, 0x68, 0x1f, 0x1d, 0x10, 0xcf, 0x3f, 0x68, 0x04, 0x3b, 0x03, 0x60,
+0x20, 0xc3, 0x10, 0xc3, 0x80, 0xc3, 0x1e, 0x60, 0x43, 0x68, 0x1f, 0x1d,
+0x01, 0x23, 0x9b, 0x07, 0x3b, 0x43, 0x43, 0x60, 0xcb, 0x6b, 0x18, 0x1f,
+0xc8, 0x63, 0x80, 0xcb, 0x80, 0xc0, 0x1c, 0x68, 0x1f, 0x1d, 0x03, 0x1d,
+0x04, 0x60, 0x38, 0x1c, 0x3f, 0x68, 0xc0, 0x46, 0x1f, 0x60, 0x1f, 0x1d,
+0x43, 0x68, 0x1c, 0x04, 0x24, 0x0c, 0x81, 0x23, 0x23, 0x43, 0x3b, 0x60,
+0x40, 0x68, 0x00, 0x0c, 0x00, 0x04, 0x10, 0x43, 0x78, 0x60, 0x08, 0x6e,
+0x04, 0x30, 0x08, 0x66, 0x48, 0x6e, 0x04, 0x30, 0x48, 0x66, 0x00, 0x20,
+0xf0, 0xbc, 0x70, 0x47, 0x00, 0xf0, 0xff, 0x0f, 0x80, 0xb4, 0x81, 0x6a,
+0x01, 0x23, 0x9b, 0x07, 0xca, 0x1d, 0x05, 0x32, 0x1a, 0x43, 0x12, 0x68,
+0xcf, 0x1d, 0x01, 0x37, 0x3b, 0x43, 0x1b, 0x68, 0xc0, 0x46, 0xcb, 0x60,
+0x01, 0x23, 0x9b, 0x07, 0x0f, 0x1d, 0x3b, 0x43, 0x1b, 0x68, 0xc0, 0x46,
+0x8b, 0x60, 0x01, 0x23, 0x9b, 0x07, 0x0b, 0x43, 0x1b, 0x68, 0x0c, 0xc1,
+0x02, 0x62, 0x01, 0x6b, 0xc0, 0x46, 0x0a, 0x62, 0x04, 0x23, 0x81, 0x69,
+0x19, 0x43, 0x81, 0x61, 0x02, 0x6b, 0xc0, 0x46, 0x91, 0x61, 0x81, 0x6a,
+0x04, 0x31, 0x81, 0x62, 0x02, 0x6b, 0xc0, 0x46, 0x91, 0x62, 0xc1, 0x1d,
+0x39, 0x31, 0x4a, 0x8b, 0x04, 0x3a, 0x4a, 0x83, 0x49, 0x8b, 0x02, 0x6b,
+0x40, 0x32, 0x51, 0x83, 0xc1, 0x89, 0x04, 0x39, 0xc1, 0x81, 0xc1, 0x68,
+0x00, 0x6b, 0xc0, 0x46, 0xc1, 0x60, 0x00, 0x20, 0x80, 0xbc, 0x70, 0x47,
+0x00, 0x47, 0x08, 0x47, 0x10, 0x47, 0x18, 0x47, 0x20, 0x47, 0x28, 0x47,
+0x30, 0x47, 0x38, 0x47, 0x30, 0x40, 0x2d, 0xe9, 0x0c, 0xc0, 0x9d, 0xe5,
+0x0c, 0x48, 0xa0, 0xe1, 0x24, 0x48, 0xb0, 0xe1, 0x1e, 0x00, 0x00, 0x0a,
+0x01, 0xc0, 0x4c, 0xe2, 0x18, 0x40, 0xa0, 0xe3, 0x64, 0x51, 0x9f, 0xe5,
+0x94, 0x50, 0x20, 0xe0, 0x00, 0x50, 0x90, 0xe5, 0x14, 0x40, 0x90, 0xe5,
+0x00, 0x30, 0x85, 0xe5, 0x04, 0xc0, 0x85, 0xe5, 0x08, 0x10, 0x85, 0xe5,
+0x0c, 0x20, 0x85, 0xe5, 0x10, 0x10, 0x90, 0xe5,
0x10, 0x50, 0x85, 0xe2, 0x01, 0x00, 0x55, 0xe1, 0x0c, 0x50, 0x90, 0x55,
-0x04, 0x00, 0x55, 0xe1, 0x05, 0x00, 0x00, 0x0a,
-0x04, 0x10, 0x90, 0xe5, 0x00, 0x50, 0x80, 0xe5, 0x00, 0x50, 0x81, 0xe5,
-0x00, 0x00, 0xa0, 0xe3, 0x30, 0x40, 0xbd, 0xe8, 0x1e, 0xff, 0x2f, 0xe1,
-0x00, 0x30, 0x93, 0xe5, 0x08, 0x20, 0x90, 0xe5, 0x01, 0x31, 0x83, 0xe3,
-0x02, 0x36, 0x83, 0xe3, 0x03, 0x00, 0x55, 0xe1, 0x14, 0x30, 0x80, 0xe5,
-0xf2, 0xff, 0xff, 0x1a, 0x01, 0x00, 0xa0, 0xe3, 0xf4, 0xff, 0xff, 0xea,
-0x01, 0x06, 0x1c, 0xe3, 0xf1, 0xff, 0xff, 0x0a, 0xec, 0x10, 0x9f, 0xe5,
-0x02, 0xc6, 0xcc, 0xe3, 0x54, 0x20, 0x91, 0xe5, 0xe4, 0x30, 0x9f, 0xe5,
-0x50, 0x10, 0x91, 0xe5, 0xd9, 0xff, 0xff, 0xea, 0xf0, 0x47, 0x2d, 0xe9,
-0x20, 0xc0, 0x9d, 0xe5, 0x0c, 0x68, 0xa0, 0xe1, 0x26, 0x68, 0xb0, 0xe1,
-0x25, 0x00, 0x00, 0x0a, 0x18, 0x40, 0xa0, 0xe3, 0xb8, 0x50, 0x9f, 0xe5,
-0x94, 0x00, 0x00, 0xe0, 0x05, 0x00, 0x80, 0xe0, 0x08, 0x40, 0x90, 0xe5,
-0x04, 0x80, 0x90, 0xe5, 0x00, 0x70, 0xa0, 0xe3, 0x1f, 0xc0, 0xa0, 0xe3,
-0x02, 0xc4, 0x8c, 0xe3, 0x00, 0x50, 0x90, 0xe5, 0x10, 0x90, 0x90, 0xe5,
-0x14, 0xa0, 0x90, 0xe5, 0x00, 0x30, 0x85, 0xe5, 0x04, 0xc0, 0x85, 0xe5,
-0x08, 0x10, 0x85, 0xe5, 0x0c, 0x20, 0x85, 0xe5, 0x10, 0x50, 0x85, 0xe2,
-0x09, 0x00, 0x55, 0xe1, 0x0c, 0x50, 0x90, 0x55, 0x0a, 0x00, 0x55, 0xe1,
-0x15, 0x00, 0x00, 0x0a, 0x03, 0x70, 0x17, 0xe2, 0x20, 0x10, 0x81, 0xe2,
-0x20, 0x30, 0x83, 0xe2, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x60, 0x96, 0xe2,
-0x01, 0x70, 0x87, 0xe2, 0x09, 0x00, 0x00, 0x0a, 0x20, 0x60, 0x46, 0xe2,
-0x20, 0x00, 0x56, 0xe3, 0xec, 0xff, 0xff, 0xca, 0x00, 0x70, 0xa0, 0xe3,
-0x01, 0xc0, 0x46, 0xe2, 0x02, 0xc4, 0x8c, 0xe3, 0x00, 0x60, 0xa0, 0xe3,
-0xe7, 0xff, 0xff, 0xea, 0x00, 0x50, 0x88, 0xe5, 0xf2, 0xff, 0xff, 0xea,
-0x00, 0x10, 0xa0, 0xe3, 0x00, 0x50, 0x80, 0xe5, 0x01, 0x00, 0xa0, 0xe1,
-0xf0, 0x47, 0xbd, 0xe8, 0x1e, 0xff, 0x2f, 0xe1, 0x00, 0xa0, 0x94, 0xe5,
-0x0a, 0x00, 0x55, 0xe1, 0x14, 0xa0, 0x80, 0xe5, 0xe5, 0xff, 0xff, 0x1a,
-0x01, 0x10, 0xa0, 0xe3, 0xf5, 0xff, 0xff, 0xea, 0xa8, 0x03, 0x00, 0x80,
-0x7c, 0x29, 0x00, 0x80, 0x00, 0x80, 0x20, 0x40, 0x68, 0x82, 0x9f, 0xe5,
-0x0b, 0x92, 0xa0, 0xe3, 0x64, 0xa2, 0x9f, 0xe5, 0x58, 0xb0, 0x9a, 0xe5,
-0x0e, 0xf0, 0xa0, 0xe1, 0x54, 0xb0, 0x9a, 0xe5, 0x1e, 0xff, 0x2f, 0xe1,
-0x3f, 0x40, 0x2d, 0xe9, 0x00, 0x00, 0x4f, 0xe1, 0x1f, 0x00, 0x00, 0xe2,
-0x12, 0x00, 0x50, 0xe3, 0x54, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0f, 0xe1,
-0x80, 0x00, 0xc0, 0xe3, 0x00, 0xf0, 0x21, 0xe1, 0x04, 0x50, 0xa0, 0xe3,
-0x00, 0x40, 0x99, 0xe5, 0x09, 0x00, 0x00, 0xea, 0x02, 0x00, 0x14, 0xe3,
-0x53, 0x00, 0x00, 0x1b, 0x80, 0x00, 0x14, 0xe3, 0x59, 0x00, 0x00, 0x1b,
-0x20, 0x00, 0x14, 0xe3, 0x59, 0x00, 0x00, 0x1b, 0x02, 0x07, 0x14, 0xe3,
-0x59, 0x00, 0x00, 0x1b, 0x01, 0x06, 0x14, 0xe3, 0x59, 0x00, 0x00, 0x1b,
-0x08, 0x00, 0x14, 0xe3, 0x45, 0x00, 0x00, 0x1b, 0x02, 0x05, 0x14, 0xe3,
-0x4a, 0x00, 0x00, 0x1b, 0x02, 0x08, 0x14, 0xe3, 0x4b, 0x00, 0x00, 0x1b,
-0xe5, 0x0e, 0x14, 0xe3, 0x07, 0x00, 0x00, 0x0a, 0x04, 0x20, 0x98, 0xe5,
-0x0c, 0x10, 0x98, 0xe5, 0x04, 0x30, 0x52, 0xe2, 0x3c, 0x30, 0xa0, 0xb3,
-0x04, 0x30, 0x88, 0xe5, 0x02, 0x00, 0x91, 0xe7, 0x0f, 0xe0, 0xa0, 0xe1,
+0x04, 0x00, 0x55, 0xe1, 0x05, 0x00, 0x00, 0x0a, 0x04, 0x10, 0x90, 0xe5,
+0x00, 0x50, 0x80, 0xe5, 0x00, 0x50, 0x81, 0xe5, 0x00, 0x00, 0xa0, 0xe3,
+0x30, 0x40, 0xbd, 0xe8, 0x1e, 0xff, 0x2f, 0xe1, 0x00, 0x30, 0x93, 0xe5,
+0x08, 0x20, 0x90, 0xe5, 0x01, 0x31, 0x83, 0xe3, 0x02, 0x36, 0x83, 0xe3,
+0x03, 0x00, 0x55, 0xe1, 0x14, 0x30, 0x80, 0xe5, 0xf2, 0xff, 0xff, 0x1a,
+0x01, 0x00, 0xa0, 0xe3, 0xf4, 0xff, 0xff, 0xea, 0x01, 0x06, 0x1c, 0xe3,
+0xf1, 0xff, 0xff, 0x0a, 0xec, 0x10, 0x9f, 0xe5, 0x02, 0xc6, 0xcc, 0xe3,
+0x54, 0x20, 0x91, 0xe5, 0xe4, 0x30, 0x9f, 0xe5, 0x50, 0x10, 0x91, 0xe5,
+0xd9, 0xff, 0xff, 0xea, 0xf0, 0x47, 0x2d, 0xe9, 0x20, 0xc0, 0x9d, 0xe5,
+0x0c, 0x68, 0xa0, 0xe1, 0x26, 0x68, 0xb0, 0xe1, 0x25, 0x00, 0x00, 0x0a,
+0x18, 0x40, 0xa0, 0xe3, 0xb8, 0x50, 0x9f, 0xe5, 0x94, 0x00, 0x00, 0xe0,
+0x05, 0x00, 0x80, 0xe0, 0x08, 0x40, 0x90, 0xe5, 0x04, 0x80, 0x90, 0xe5,
+0x00, 0x70, 0xa0, 0xe3, 0x1f, 0xc0, 0xa0, 0xe3, 0x02, 0xc4, 0x8c, 0xe3,
+0x00, 0x50, 0x90, 0xe5, 0x10, 0x90, 0x90, 0xe5, 0x14, 0xa0, 0x90, 0xe5,
+0x00, 0x30, 0x85, 0xe5, 0x04, 0xc0, 0x85, 0xe5, 0x08, 0x10, 0x85, 0xe5,
+0x0c, 0x20, 0x85, 0xe5, 0x10, 0x50, 0x85, 0xe2, 0x09, 0x00, 0x55, 0xe1,
+0x0c, 0x50, 0x90, 0x55, 0x0a, 0x00, 0x55, 0xe1, 0x15, 0x00, 0x00, 0x0a,
+0x03, 0x70, 0x17, 0xe2, 0x20, 0x10, 0x81, 0xe2, 0x20, 0x30, 0x83, 0xe2,
+0x0a, 0x00, 0x00, 0x0a, 0x00, 0x60, 0x96, 0xe2, 0x01, 0x70, 0x87, 0xe2,
+0x09, 0x00, 0x00, 0x0a, 0x20, 0x60, 0x46, 0xe2, 0x20, 0x00, 0x56, 0xe3,
+0xec, 0xff, 0xff, 0xca, 0x00, 0x70, 0xa0, 0xe3, 0x01, 0xc0, 0x46, 0xe2,
+0x02, 0xc4, 0x8c, 0xe3, 0x00, 0x60, 0xa0, 0xe3, 0xe7, 0xff, 0xff, 0xea,
+0x00, 0x50, 0x88, 0xe5, 0xf2, 0xff, 0xff, 0xea, 0x00, 0x10, 0xa0, 0xe3,
+0x00, 0x50, 0x80, 0xe5, 0x01, 0x00, 0xa0, 0xe1, 0xf0, 0x47, 0xbd, 0xe8,
+0x1e, 0xff, 0x2f, 0xe1, 0x00, 0xa0, 0x94, 0xe5, 0x0a, 0x00, 0x55, 0xe1,
+0x14, 0xa0, 0x80, 0xe5, 0xe5, 0xff, 0xff, 0x1a, 0x01, 0x10, 0xa0, 0xe3,
+0xf5, 0xff, 0xff, 0xea, 0xa8, 0x03, 0x00, 0x80, 0x7c, 0x29, 0x00, 0x80,
+0x00, 0x80, 0x20, 0x40, 0x68, 0x82, 0x9f, 0xe5, 0x0b, 0x92, 0xa0, 0xe3,
+0x64, 0xa2, 0x9f, 0xe5, 0x58, 0xb0, 0x9a, 0xe5, 0x0e, 0xf0, 0xa0, 0xe1,
+0x54, 0xb0, 0x9a, 0xe5, 0x1e, 0xff, 0x2f, 0xe1, 0x3f, 0x40, 0x2d, 0xe9,
+0x00, 0x00, 0x4f, 0xe1, 0x1f, 0x00, 0x00, 0xe2, 0x12, 0x00, 0x50, 0xe3,
+0x54, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0f, 0xe1, 0x80, 0x00, 0xc0, 0xe3,
+0x00, 0xf0, 0x21, 0xe1, 0x04, 0x50, 0xa0, 0xe3, 0x00, 0x40, 0x99, 0xe5,
+0x09, 0x00, 0x00, 0xea, 0x02, 0x00, 0x14, 0xe3, 0x53, 0x00, 0x00, 0x1b,
+0x80, 0x00, 0x14, 0xe3, 0x59, 0x00, 0x00, 0x1b, 0x20, 0x00, 0x14, 0xe3,
+0x59, 0x00, 0x00, 0x1b, 0x02, 0x07, 0x14, 0xe3, 0x59, 0x00, 0x00, 0x1b,
+0x01, 0x06, 0x14, 0xe3, 0x59, 0x00, 0x00, 0x1b, 0x08, 0x00, 0x14, 0xe3,
+0x45, 0x00, 0x00, 0x1b, 0x02, 0x05, 0x14, 0xe3, 0x4a, 0x00, 0x00, 0x1b,
+0x02, 0x08, 0x14, 0xe3, 0x4b, 0x00, 0x00, 0x1b, 0xe5, 0x0e, 0x14, 0xe3,
+0x07, 0x00, 0x00, 0x0a, 0x04, 0x20, 0x98, 0xe5, 0x0c, 0x10, 0x98, 0xe5,
+0x04, 0x30, 0x52, 0xe2, 0x3c, 0x30, 0xa0, 0xb3, 0x04, 0x30, 0x88, 0xe5,
+0x02, 0x00, 0x91, 0xe7, 0x0f, 0xe0, 0xa0, 0xe1,
0x10, 0xff, 0x2f, 0xe1, 0x01, 0x50, 0x55, 0xe2, 0x03, 0x00, 0x00, 0x0a,
-0x00, 0x40, 0x99, 0xe5, 0x0c, 0x00, 0x9a, 0xe5,
-0x00, 0x00, 0x14, 0xe1, 0x1b, 0xff, 0x2f, 0x11, 0x08, 0x00, 0x9a, 0xe5,
-0x00, 0x00, 0x14, 0xe1, 0x0b, 0x00, 0x00, 0x0a, 0x01, 0x0c, 0x14, 0xe3,
-0x98, 0x01, 0x9f, 0x15, 0x0f, 0xe0, 0xa0, 0x11, 0x10, 0xff, 0x2f, 0x11,
-0x02, 0x04, 0x14, 0xe3, 0x8c, 0x01, 0x9f, 0x15, 0x0f, 0xe0, 0xa0, 0x11,
-0x10, 0xff, 0x2f, 0x11, 0x01, 0x09, 0x14, 0xe3, 0x80, 0x01, 0x9f, 0x15,
-0x0f, 0xe0, 0xa0, 0x11, 0x10, 0xff, 0x2f, 0x11, 0x04, 0x00, 0x9a, 0xe5,
-0x00, 0x00, 0x14, 0xe1, 0x16, 0x00, 0x00, 0x0a, 0x54, 0xe0, 0x8f, 0xe2,
-0x04, 0x00, 0x14, 0xe3, 0x40, 0x00, 0x9a, 0x15, 0x10, 0xff, 0x2f, 0x11,
-0x02, 0x0a, 0x14, 0xe3, 0x44, 0x00, 0x9a, 0x15, 0x10, 0xff, 0x2f, 0x11,
-0x02, 0x09, 0x14, 0xe3, 0x48, 0x00, 0x9a, 0x15, 0x10, 0xff, 0x2f, 0x11,
-0x01, 0x02, 0x14, 0xe3, 0x4c, 0x00, 0x9a, 0x15, 0x10, 0xff, 0x2f, 0x11,
-0x01, 0x04, 0x14, 0xe3, 0x50, 0x00, 0x9a, 0x15, 0x10, 0xff, 0x2f, 0x11,
-0x01, 0x0a, 0x14, 0xe3, 0x21, 0x00, 0x00, 0x1b, 0x02, 0x00, 0x14, 0xe3,
-0x0e, 0x00, 0x00, 0x1b, 0x10, 0x00, 0x9a, 0xe5, 0x00, 0x00, 0x14, 0xe1,
-0x1c, 0x00, 0x00, 0x1b, 0x00, 0x40, 0x99, 0xe5, 0x04, 0x50, 0xa0, 0xe3,
-0x00, 0x40, 0x94, 0xe2, 0x1b, 0xff, 0x2f, 0x11, 0x3f, 0x40, 0xbd, 0xe8,
-0x04, 0xf0, 0x5e, 0xe2, 0xc0, 0x00, 0x80, 0xe3, 0x00, 0xf0, 0x61, 0xe1,
-0xfa, 0xff, 0xff, 0xea, 0x18, 0x00, 0x9a, 0xe5, 0x1c, 0x10, 0x9a, 0xe5,
-0x11, 0xff, 0x2f, 0xe1, 0x54, 0xb0, 0x9a, 0xe5, 0x1c, 0x10, 0x9a, 0xe5,
-0x14, 0x00, 0x9a, 0xe5, 0x11, 0xff, 0x2f, 0xe1, 0x20, 0x10, 0x9a, 0xe5,
-0x00, 0x00, 0xa0, 0xe3, 0x11, 0xff, 0x2f, 0xe1, 0x24, 0x10, 0x9a, 0xe5,
-0x11, 0xff, 0x2f, 0xe1, 0x28, 0x10, 0x9a, 0xe5, 0x11, 0xff, 0x2f, 0xe1,
-0x2c, 0x10, 0x9a, 0xe5, 0x11, 0xff, 0x2f, 0xe1, 0x30, 0x10, 0x9a, 0xe5,
-0x11, 0xff, 0x2f, 0xe1, 0x34, 0x10, 0x9a, 0xe5, 0x11, 0xff, 0x2f, 0xe1,
-0xfe, 0xff, 0xff, 0xea, 0x38, 0xe0, 0x9a, 0xe5, 0x3c, 0x10, 0x9a, 0xe5,
-0x18, 0x00, 0x9a, 0xe5, 0x11, 0xff, 0x2f, 0xe1, 0x38, 0xe0, 0x9a, 0xe5,
-0x3c, 0x10, 0x9a, 0xe5, 0x14, 0x00, 0x9a, 0xe5, 0x11, 0xff, 0x2f, 0xe1,
-0x64, 0x20, 0x9f, 0xe5, 0x00, 0x30, 0x92, 0xe5, 0x00, 0x30, 0x53, 0xe0,
-0x0a, 0x00, 0x00, 0xba, 0x00, 0x30, 0x82, 0xe5, 0x0c, 0x00, 0x92, 0xe5,
-0x08, 0x30, 0x92, 0xe5, 0x00, 0x10, 0x91, 0xe2, 0x03, 0x00, 0x00, 0x0a,
-0x03, 0x10, 0x80, 0xe7, 0x04, 0x30, 0x53, 0xe2, 0x3c, 0x30, 0xa0, 0xb3,
-0x08, 0x30, 0x82, 0xe5, 0x01, 0x00, 0xa0, 0xe3, 0x1e, 0xff, 0x2f, 0xe1,
-0x3c, 0x10, 0x9f, 0xe5, 0x00, 0x00, 0x91, 0xe5, 0x01, 0x00, 0x80, 0xe2,
-0x00, 0x00, 0x81, 0xe5, 0x00, 0x00, 0xa0, 0xe3, 0xf8, 0xff, 0xff, 0xea,
-0x10, 0x00, 0x9f, 0xe5, 0x08, 0x10, 0x90, 0xe5, 0x04, 0x10, 0x51, 0xe2,
-0x3c, 0x10, 0xa0, 0xb3, 0x08, 0x10, 0x80, 0xe5, 0x1e, 0xff, 0x2f, 0xe1,
-0xe4, 0x2d, 0x00, 0x80, 0xcc, 0x04, 0x00, 0x80, 0x5d, 0x2b, 0xff, 0xff,
-0xbd, 0x3d, 0xff, 0xff, 0xb5, 0x2b, 0xff, 0xff, 0xa0, 0x82, 0x20, 0x40,
-0xc9, 0x1c, 0x89, 0x08, 0x89, 0x00, 0x01, 0x23, 0x85, 0x4a, 0x5b, 0x07,
-0x18, 0x43, 0x13, 0x68, 0x5b, 0x18, 0x13, 0x60, 0x00, 0x1f, 0x81, 0xa3,
-0x5b, 0x1a, 0x18, 0x47, 0x04, 0x20, 0xa0, 0xe5, 0x04, 0x20, 0xa0, 0xe5,
-0x04, 0x20, 0xa0, 0xe5, 0x04, 0x20, 0xa0, 0xe5, 0x04, 0x20, 0xa0, 0xe5,
+0x00, 0x40, 0x99, 0xe5, 0x0c, 0x00, 0x9a, 0xe5, 0x00, 0x00, 0x14, 0xe1,
+0x1b, 0xff, 0x2f, 0x11, 0x08, 0x00, 0x9a, 0xe5, 0x00, 0x00, 0x14, 0xe1,
+0x0b, 0x00, 0x00, 0x0a, 0x01, 0x0c, 0x14, 0xe3, 0x98, 0x01, 0x9f, 0x15,
+0x0f, 0xe0, 0xa0, 0x11, 0x10, 0xff, 0x2f, 0x11, 0x02, 0x04, 0x14, 0xe3,
+0x8c, 0x01, 0x9f, 0x15, 0x0f, 0xe0, 0xa0, 0x11, 0x10, 0xff, 0x2f, 0x11,
+0x01, 0x09, 0x14, 0xe3, 0x80, 0x01, 0x9f, 0x15, 0x0f, 0xe0, 0xa0, 0x11,
+0x10, 0xff, 0x2f, 0x11, 0x04, 0x00, 0x9a, 0xe5, 0x00, 0x00, 0x14, 0xe1,
+0x16, 0x00, 0x00, 0x0a, 0x54, 0xe0, 0x8f, 0xe2, 0x04, 0x00, 0x14, 0xe3,
+0x40, 0x00, 0x9a, 0x15, 0x10, 0xff, 0x2f, 0x11, 0x02, 0x0a, 0x14, 0xe3,
+0x44, 0x00, 0x9a, 0x15, 0x10, 0xff, 0x2f, 0x11, 0x02, 0x09, 0x14, 0xe3,
+0x48, 0x00, 0x9a, 0x15, 0x10, 0xff, 0x2f, 0x11, 0x01, 0x02, 0x14, 0xe3,
+0x4c, 0x00, 0x9a, 0x15, 0x10, 0xff, 0x2f, 0x11, 0x01, 0x04, 0x14, 0xe3,
+0x50, 0x00, 0x9a, 0x15, 0x10, 0xff, 0x2f, 0x11, 0x01, 0x0a, 0x14, 0xe3,
+0x21, 0x00, 0x00, 0x1b, 0x02, 0x00, 0x14, 0xe3, 0x0e, 0x00, 0x00, 0x1b,
+0x10, 0x00, 0x9a, 0xe5, 0x00, 0x00, 0x14, 0xe1, 0x1c, 0x00, 0x00, 0x1b,
+0x00, 0x40, 0x99, 0xe5, 0x04, 0x50, 0xa0, 0xe3, 0x00, 0x40, 0x94, 0xe2,
+0x1b, 0xff, 0x2f, 0x11, 0x3f, 0x40, 0xbd, 0xe8, 0x04, 0xf0, 0x5e, 0xe2,
+0xc0, 0x00, 0x80, 0xe3, 0x00, 0xf0, 0x61, 0xe1, 0xfa, 0xff, 0xff, 0xea,
+0x18, 0x00, 0x9a, 0xe5, 0x1c, 0x10, 0x9a, 0xe5, 0x11, 0xff, 0x2f, 0xe1,
+0x54, 0xb0, 0x9a, 0xe5, 0x1c, 0x10, 0x9a, 0xe5, 0x14, 0x00, 0x9a, 0xe5,
+0x11, 0xff, 0x2f, 0xe1, 0x20, 0x10, 0x9a, 0xe5, 0x00, 0x00, 0xa0, 0xe3,
+0x11, 0xff, 0x2f, 0xe1, 0x24, 0x10, 0x9a, 0xe5, 0x11, 0xff, 0x2f, 0xe1,
+0x28, 0x10, 0x9a, 0xe5, 0x11, 0xff, 0x2f, 0xe1, 0x2c, 0x10, 0x9a, 0xe5,
+0x11, 0xff, 0x2f, 0xe1, 0x30, 0x10, 0x9a, 0xe5, 0x11, 0xff, 0x2f, 0xe1,
+0x34, 0x10, 0x9a, 0xe5, 0x11, 0xff, 0x2f, 0xe1, 0xfe, 0xff, 0xff, 0xea,
+0x38, 0xe0, 0x9a, 0xe5, 0x3c, 0x10, 0x9a, 0xe5, 0x18, 0x00, 0x9a, 0xe5,
+0x11, 0xff, 0x2f, 0xe1, 0x38, 0xe0, 0x9a, 0xe5, 0x3c, 0x10, 0x9a, 0xe5,
+0x14, 0x00, 0x9a, 0xe5, 0x11, 0xff, 0x2f, 0xe1, 0x64, 0x20, 0x9f, 0xe5,
+0x00, 0x30, 0x92, 0xe5, 0x00, 0x30, 0x53, 0xe0, 0x0a, 0x00, 0x00, 0xba,
+0x00, 0x30, 0x82, 0xe5, 0x0c, 0x00, 0x92, 0xe5, 0x08, 0x30, 0x92, 0xe5,
+0x00, 0x10, 0x91, 0xe2, 0x03, 0x00, 0x00, 0x0a, 0x03, 0x10, 0x80, 0xe7,
+0x04, 0x30, 0x53, 0xe2, 0x3c, 0x30, 0xa0, 0xb3, 0x08, 0x30, 0x82, 0xe5,
+0x01, 0x00, 0xa0, 0xe3, 0x1e, 0xff, 0x2f, 0xe1, 0x3c, 0x10, 0x9f, 0xe5,
+0x00, 0x00, 0x91, 0xe5, 0x01, 0x00, 0x80, 0xe2, 0x00, 0x00, 0x81, 0xe5,
+0x00, 0x00, 0xa0, 0xe3, 0xf8, 0xff, 0xff, 0xea, 0x10, 0x00, 0x9f, 0xe5,
+0x08, 0x10, 0x90, 0xe5, 0x04, 0x10, 0x51, 0xe2, 0x3c, 0x10, 0xa0, 0xb3,
+0x08, 0x10, 0x80, 0xe5, 0x1e, 0xff, 0x2f, 0xe1, 0xe4, 0x2d, 0x00, 0x80,
+0xcc, 0x04, 0x00, 0x80, 0x71, 0x2b, 0xff, 0xff, 0xd1, 0x3d, 0xff, 0xff,
+0xc9, 0x2b, 0xff, 0xff, 0xa0, 0x82, 0x20, 0x40, 0xc9, 0x1c, 0x89, 0x08,
+0x89, 0x00, 0x01, 0x23, 0x85, 0x4a, 0x5b, 0x07, 0x18, 0x43, 0x13, 0x68,
+0x5b, 0x18, 0x13, 0x60, 0x00, 0x1f, 0x81, 0xa3, 0x5b, 0x1a, 0x18, 0x47,
0x04, 0x20, 0xa0, 0xe5, 0x04, 0x20, 0xa0, 0xe5,
0x04, 0x20, 0xa0, 0xe5, 0x04, 0x20, 0xa0, 0xe5, 0x04, 0x20, 0xa0, 0xe5,
0x04, 0x20, 0xa0, 0xe5, 0x04, 0x20, 0xa0, 0xe5, 0x04, 0x20, 0xa0, 0xe5,
@@ -1921,204 +1922,143 @@ const u8 typhoon_firmware_image[] = {
0x04, 0x20, 0xa0, 0xe5, 0x04, 0x20, 0xa0, 0xe5, 0x04, 0x20, 0xa0, 0xe5,
0x04, 0x20, 0xa0, 0xe5, 0x04, 0x20, 0xa0, 0xe5, 0x04, 0x20, 0xa0, 0xe5,
0x04, 0x20, 0xa0, 0xe5, 0x04, 0x20, 0xa0, 0xe5, 0x04, 0x20, 0xa0, 0xe5,
-0x04, 0x20, 0xa0, 0xe5, 0x1e, 0xff, 0x2f, 0xe1, 0xe4, 0x2d, 0x00, 0x80,
+0x04, 0x20, 0xa0, 0xe5, 0x04, 0x20, 0xa0, 0xe5, 0x04, 0x20, 0xa0, 0xe5,
+0x04, 0x20, 0xa0, 0xe5, 0x04, 0x20, 0xa0, 0xe5, 0x04, 0x20, 0xa0, 0xe5,
+0x1e, 0xff, 0x2f, 0xe1, 0xe4, 0x2d, 0x00, 0x80,
0x98, 0x00, 0x9f, 0xe5, 0x98, 0x10, 0x9f, 0xe5, 0x01, 0x20, 0x40, 0xe0,
-0x94, 0x30, 0x9f, 0xe5, 0x00, 0x00, 0x91, 0xe5,
+0x94, 0x30, 0x9f, 0xe5, 0x00, 0x00, 0x91, 0xe5, 0x03, 0x00, 0x50, 0xe1,
+0x03, 0x00, 0x00, 0x1a, 0x04, 0x10, 0x81, 0xe2, 0x04, 0x20, 0x52, 0xe2,
+0x00, 0x00, 0x00, 0x0a, 0xf8, 0xff, 0xff, 0xea, 0x78, 0x00, 0x9f, 0xe5,
+0x00, 0x20, 0x80, 0xe5, 0x74, 0x00, 0x9f, 0xe5, 0x74, 0x10, 0x9f, 0xe5,
+0x01, 0x20, 0x40, 0xe0, 0x60, 0x30, 0x9f, 0xe5, 0x00, 0x00, 0x91, 0xe5,
0x03, 0x00, 0x50, 0xe1, 0x03, 0x00, 0x00, 0x1a, 0x04, 0x10, 0x81, 0xe2,
0x04, 0x20, 0x52, 0xe2, 0x00, 0x00, 0x00, 0x0a, 0xf8, 0xff, 0xff, 0xea,
-0x78, 0x00, 0x9f, 0xe5, 0x00, 0x20, 0x80, 0xe5, 0x74, 0x00, 0x9f, 0xe5,
-0x74, 0x10, 0x9f, 0xe5, 0x01, 0x20, 0x40, 0xe0, 0x60, 0x30, 0x9f, 0xe5,
+0x50, 0x00, 0x9f, 0xe5, 0x00, 0x20, 0x80, 0xe5, 0x4c, 0x00, 0x9f, 0xe5,
+0x4c, 0x10, 0x9f, 0xe5, 0x01, 0x20, 0x40, 0xe0, 0x2c, 0x30, 0x9f, 0xe5,
0x00, 0x00, 0x91, 0xe5, 0x03, 0x00, 0x50, 0xe1, 0x03, 0x00, 0x00, 0x1a,
0x04, 0x10, 0x81, 0xe2, 0x04, 0x20, 0x52, 0xe2, 0x00, 0x00, 0x00, 0x0a,
-0xf8, 0xff, 0xff, 0xea, 0x50, 0x00, 0x9f, 0xe5, 0x00, 0x20, 0x80, 0xe5,
-0x4c, 0x00, 0x9f, 0xe5, 0x4c, 0x10, 0x9f, 0xe5, 0x01, 0x20, 0x40, 0xe0,
-0x2c, 0x30, 0x9f, 0xe5, 0x00, 0x00, 0x91, 0xe5, 0x03, 0x00, 0x50, 0xe1,
-0x03, 0x00, 0x00, 0x1a, 0x04, 0x10, 0x81, 0xe2, 0x04, 0x20, 0x52, 0xe2,
-0x00, 0x00, 0x00, 0x0a, 0xf8, 0xff, 0xff, 0xea, 0x28, 0x00, 0x9f, 0xe5,
-0x00, 0x20, 0x80, 0xe5, 0x1e, 0xff, 0x2f, 0xe1, 0x7c, 0x34, 0x00, 0x80,
-0x80, 0x30, 0x00, 0x80, 0xad, 0xde, 0xad, 0xde, 0xc0, 0x04, 0x00, 0x80,
-0xfc, 0x37, 0x00, 0x80, 0x80, 0x34, 0x00, 0x80, 0xc4, 0x04, 0x00, 0x80,
-0xfc, 0x3f, 0x00, 0x80, 0x40, 0x38, 0x00, 0x80, 0xc8, 0x04, 0x00, 0x80,
-0x78, 0x47, 0x00, 0x00, 0x76, 0xea, 0xff, 0xea, 0x78, 0x47, 0x00, 0x00,
-0x39, 0xfe, 0xff, 0xea, 0x78, 0x47, 0x00, 0x00, 0x63, 0xfe, 0xff, 0xea,
-0x78, 0x47, 0x00, 0x00, 0x1b, 0xff, 0xff, 0xea, 0x78, 0x47, 0x00, 0x00,
-0x70, 0xea, 0xff, 0xea, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x80, 0x28, 0x04, 0x00, 0x00, 0x95, 0x22, 0x00, 0x00,
-0x00, 0x01, 0x00, 0x80, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0xb9, 0x0b, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xd5, 0x0b, 0xff, 0xff,
-0x03, 0xff, 0x06, 0x54, 0x03, 0x00, 0x00, 0x00, 0x75, 0x04, 0xff, 0xff,
-0x00, 0x00, 0x00, 0x00, 0xa1, 0x05, 0xff, 0xff, 0x04, 0xff, 0x07, 0x54,
-0x03, 0x00, 0x00, 0x00, 0xb5, 0x04, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
-0xf1, 0x05, 0xff, 0xff, 0x05, 0xff, 0x05, 0x54, 0x03, 0x00, 0x00, 0x00,
-0x39, 0x04, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x55, 0x05, 0xff, 0xff,
-0x01, 0xff, 0x04, 0x00, 0x03, 0x00, 0x00, 0x00, 0x41, 0x18, 0xff, 0xff,
-0x00, 0x00, 0x00, 0x00, 0x61, 0x0e, 0xff, 0xff, 0x02, 0xff, 0x02, 0x08,
-0x00, 0x00, 0x00, 0x00, 0xa1, 0x02, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
-0xf1, 0x02, 0xff, 0xff, 0xff, 0xff, 0x01, 0x44, 0x03, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9d, 0x0d, 0xff, 0xff,
-0x06, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x50, 0xff, 0xff,
-0x6d, 0x50, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0xf8, 0xff, 0xff, 0xea, 0x28, 0x00, 0x9f, 0xe5, 0x00, 0x20, 0x80, 0xe5,
+0x1e, 0xff, 0x2f, 0xe1, 0x7c, 0x34, 0x00, 0x80, 0x80, 0x30, 0x00, 0x80,
+0xad, 0xde, 0xad, 0xde, 0xc0, 0x04, 0x00, 0x80, 0xfc, 0x37, 0x00, 0x80,
+0x80, 0x34, 0x00, 0x80, 0xc4, 0x04, 0x00, 0x80, 0xfc, 0x3f, 0x00, 0x80,
+0x40, 0x38, 0x00, 0x80, 0xc8, 0x04, 0x00, 0x80, 0x78, 0x47, 0x00, 0x00,
+0x71, 0xea, 0xff, 0xea, 0x78, 0x47, 0x00, 0x00, 0x39, 0xfe, 0xff, 0xea,
+0x78, 0x47, 0x00, 0x00, 0x63, 0xfe, 0xff, 0xea, 0x78, 0x47, 0x00, 0x00,
+0x1b, 0xff, 0xff, 0xea, 0x78, 0x47, 0x00, 0x00, 0x6b, 0xea, 0xff, 0xea,
+0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0x28, 0x04, 0x00, 0x00, 0xf8, 0x3d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x80,
+0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb9, 0x0b, 0xff, 0xff,
+0x00, 0x00, 0x00, 0x00, 0xd5, 0x0b, 0xff, 0xff, 0x03, 0xff, 0x06, 0x54,
+0x03, 0x00, 0x00, 0x00, 0x75, 0x04, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
+0xa1, 0x05, 0xff, 0xff, 0x04, 0xff, 0x07, 0x54, 0x03, 0x00, 0x00, 0x00,
+0xb5, 0x04, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xf1, 0x05, 0xff, 0xff,
+0x05, 0xff, 0x05, 0x54, 0x03, 0x00, 0x00, 0x00, 0x39, 0x04, 0xff, 0xff,
+0x00, 0x00, 0x00, 0x00, 0x55, 0x05, 0xff, 0xff, 0x01, 0xff, 0x04, 0x00,
+0x03, 0x00, 0x00, 0x00, 0x41, 0x18, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
+0x61, 0x0e, 0xff, 0xff, 0x02, 0xff, 0x02, 0x08, 0x00, 0x00, 0x00, 0x00,
+0xa1, 0x02, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xf1, 0x02, 0xff, 0xff,
+0xff, 0xff, 0x01, 0x44, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x9d, 0x0d, 0xff, 0xff, 0x06, 0x00, 0xff, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x3d, 0x50, 0xff, 0xff, 0x81, 0x50, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x48, 0x05, 0x00, 0x80, 0x19, 0x78, 0x21, 0x40,
-0x23, 0x78, 0x21, 0x40, 0x39, 0x78, 0x21, 0x40, 0x51, 0x78, 0x21, 0x40,
-0x5d, 0x78, 0x21, 0x40, 0x6b, 0x78, 0x21, 0x40, 0x85, 0x78, 0x21, 0x40,
-0xb1, 0x78, 0x21, 0x40, 0x75, 0x79, 0x21, 0x40,
-0xcd, 0x79, 0x21, 0x40, 0xdb, 0x79, 0x21, 0x40, 0xe5, 0x79, 0x21, 0x40,
-0xef, 0x79, 0x21, 0x40, 0x8d, 0x7a, 0x21, 0x40, 0x9b, 0x7a, 0x21, 0x40,
-0xa9, 0x7a, 0x21, 0x40, 0x51, 0x7b, 0x21, 0x40, 0x4f, 0x7f, 0x21, 0x40,
-0xc9, 0x7f, 0x21, 0x40, 0x69, 0x80, 0x21, 0x40, 0x9d, 0x81, 0x21, 0x40,
-0xa9, 0x81, 0x21, 0x40, 0x09, 0x82, 0x21, 0x40, 0x6d, 0x82, 0x21, 0x40,
-0x99, 0x82, 0x21, 0x40, 0xbd, 0x82, 0x21, 0x40, 0xfd, 0x82, 0x21, 0x40,
-0x25, 0x83, 0x21, 0x40, 0x6d, 0x83, 0x21, 0x40, 0x7d, 0x83, 0x21, 0x40,
-0xa5, 0x83, 0x21, 0x40, 0xb5, 0x83, 0x21, 0x40, 0xfd, 0x83, 0x21, 0x40,
-0x3b, 0x84, 0x21, 0x40, 0x91, 0x84, 0x21, 0x40, 0xf1, 0x84, 0x21, 0x40,
-0xfb, 0x84, 0x21, 0x40, 0xff, 0x84, 0x21, 0x40, 0x6d, 0x85, 0x21, 0x40,
-0xb9, 0x85, 0x21, 0x40, 0x11, 0x86, 0x21, 0x40, 0x4d, 0x86, 0x21, 0x40,
-0xb1, 0x86, 0x21, 0x40, 0xe9, 0x86, 0x21, 0x40, 0xf9, 0x86, 0x21, 0x40,
-0x31, 0x87, 0x21, 0x40, 0x41, 0x87, 0x21, 0x40, 0x55, 0x87, 0x21, 0x40,
-0x7d, 0x87, 0x21, 0x40, 0x87, 0x87, 0x21, 0x40, 0x91, 0x87, 0x21, 0x40,
-0xf5, 0x87, 0x21, 0x40, 0x25, 0x88, 0x21, 0x40, 0x31, 0x88, 0x21, 0x40,
-0xa5, 0x88, 0x21, 0x40, 0xaf, 0x88, 0x21, 0x40, 0xb9, 0x88, 0x21, 0x40,
-0xc3, 0x88, 0x21, 0x40, 0xcd, 0x88, 0x21, 0x40, 0xd7, 0x88, 0x21, 0x40,
-0xe1, 0x88, 0x21, 0x40, 0xeb, 0x88, 0x21, 0x40, 0xf5, 0x88, 0x21, 0x40,
-0xe9, 0x8b, 0x21, 0x40, 0xff, 0x88, 0x21, 0x40, 0x09, 0x89, 0x21, 0x40,
-0x13, 0x89, 0x21, 0x40, 0x1d, 0x89, 0x21, 0x40, 0x45, 0x89, 0x21, 0x40,
-0x4f, 0x89, 0x21, 0x40, 0xb1, 0x89, 0x21, 0x40, 0xbb, 0x89, 0x21, 0x40,
-0xc5, 0x89, 0x21, 0x40, 0xcf, 0x89, 0x21, 0x40, 0xd9, 0x89, 0x21, 0x40,
-0xa5, 0x77, 0x21, 0x40, 0xe3, 0x89, 0x21, 0x40, 0x49, 0x8a, 0x21, 0x40,
-0x95, 0x8a, 0x21, 0x40, 0xe1, 0x8a, 0x21, 0x40, 0xf1, 0x8a, 0x21, 0x40,
-0xa5, 0x77, 0x21, 0x40, 0x3d, 0x8b, 0x21, 0x40, 0x41, 0x8b, 0x21, 0x40,
-0x45, 0x8b, 0x21, 0x40, 0x9d, 0x8b, 0x21, 0x40, 0xc5, 0x8b, 0x21, 0x40,
-0xd1, 0x8b, 0x21, 0x40, 0xd5, 0x8b, 0x21, 0x40, 0xd9, 0x8b, 0x21, 0x40,
-0xdd, 0x8b, 0x21, 0x40, 0xe1, 0x8b, 0x21, 0x40, 0xe5, 0x8b, 0x21, 0x40,
-0x0d, 0x88, 0x21, 0x40, 0x69, 0x88, 0x21, 0x40, 0xa5, 0x77, 0x21, 0x40,
-0xa5, 0x77, 0x21, 0x40, 0xf5, 0x8b, 0x21, 0x40, 0xe1, 0xc9, 0x21, 0x40,
-0xe9, 0x77, 0x21, 0x40, 0xa5, 0x77, 0x21, 0x40, 0xa5, 0x77, 0x21, 0x40,
-0xdd, 0xca, 0x21, 0x40, 0x13, 0xcb, 0x21, 0x40, 0x45, 0xcb, 0x21, 0x40,
-0x4d, 0x8c, 0x21, 0x40, 0x5b, 0x7b, 0x21, 0x40, 0xe5, 0x7e, 0x21, 0x40,
-0x21, 0x7f, 0x21, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x01, 0x18, 0x40,
-0x58, 0x01, 0x18, 0x40, 0x24, 0xa3, 0x20, 0x40, 0x24, 0xa7, 0x20, 0x40,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x01, 0x18, 0x40,
-0x68, 0x01, 0x18, 0x40, 0x24, 0x83, 0x20, 0x40, 0x24, 0xa3, 0x20, 0x40,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x01, 0x18, 0x40,
-0x78, 0x01, 0x18, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8c, 0x01, 0x18, 0x40,
-0x88, 0x01, 0x18, 0x40, 0x24, 0xa9, 0x20, 0x40, 0x24, 0xab, 0x20, 0x40,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x12, 0x00, 0x18, 0x00, 0x12, 0x00,
-0x0c, 0x00, 0x12, 0x00, 0x1c, 0x00, 0x12, 0x00, 0x24, 0xa8, 0x20, 0x40,
-0xa4, 0xa8, 0x20, 0x40, 0xa4, 0xa8, 0x20, 0x40, 0x24, 0xa9, 0x20, 0x40,
-0x00, 0x00, 0x00, 0x00, 0xa5, 0xb9, 0x21, 0x40, 0x01, 0xbb, 0x21, 0x40,
-0x00, 0x00, 0x00, 0x00, 0x91, 0x73, 0x21, 0x40, 0x19, 0xb2, 0x21, 0x40,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0xa7, 0x99, 0x21, 0x40, 0xa5, 0xb9, 0x21, 0x40,
-0xb1, 0x2f, 0xff, 0xff, 0xf1, 0x20, 0xff, 0xff, 0xdb, 0x20, 0xff, 0xff,
-0x2d, 0xb8, 0x21, 0x40, 0x34, 0x2e, 0x00, 0x80, 0x48, 0x2e, 0x00, 0x80,
-0x5c, 0x2e, 0x00, 0x80, 0x30, 0x33, 0x3a, 0x31, 0x31, 0x3a, 0x31, 0x31,
-0x00, 0x30, 0x37, 0x2f, 0x32, 0x33, 0x2f, 0x30, 0x31, 0x00, 0x30, 0x30,
-0x30, 0x30, 0x31, 0x35, 0x36, 0x39, 0x00, 0x43, 0x6f, 0x70, 0x79, 0x72,
-0x69, 0x67, 0x68, 0x74, 0x20, 0x28, 0x63, 0x29, 0x20, 0x32, 0x30, 0x30,
-0x31, 0x20, 0x33, 0x43, 0x6f, 0x6d, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f,
-0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x00, 0x02, 0x10, 0x00, 0x03,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x78, 0x53, 0xff, 0xff, 0x27, 0xf0, 0x7d, 0xfd, 0x00, 0x01, 0x00, 0x02,
-0xda, 0x0e, 0x82, 0x00, 0x01, 0x40, 0x64, 0x04, 0x64, 0x2d, 0x00, 0x80,
-0xe4, 0x2c, 0x00, 0x80, 0x55, 0x3e, 0xff, 0xff, 0xb5, 0x4f, 0xff, 0xff,
-0xc1, 0x24, 0xff, 0xff, 0xb5, 0x3b, 0xff, 0xff, 0x15, 0x3c, 0xff, 0xff,
-0x05, 0x1a, 0xff, 0xff, 0x65, 0x11, 0xff, 0xff, 0xb8, 0x53, 0xff, 0xff,
-0x0d, 0x40, 0xff, 0xff, 0x91, 0x73, 0x21, 0x40, 0x51, 0x75, 0x21, 0x40,
-0xc5, 0x3f, 0xff, 0xff, 0x71, 0xaa, 0x21, 0x40, 0x71, 0x24, 0xff, 0xff,
-0x50, 0x53, 0xff, 0xff, 0x78, 0x53, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
-0xff, 0xff, 0x00, 0x00, 0x80, 0x30, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00,
-0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x20, 0x40, 0xec, 0x68, 0x00, 0x00,
-0x10, 0x5c, 0x00, 0x00, 0x00, 0x6e, 0x21, 0x40, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
-0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
-0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
-0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
-0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
-0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
-0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
-0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
-0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x3d, 0x9a, 0x21, 0x40,
-0xdb, 0x99, 0x21, 0x40, 0xf5, 0x9c, 0x21, 0x40, 0x55, 0x9d, 0x21, 0x40,
-0x1d, 0x9e, 0x21, 0x40, 0xdb, 0x9b, 0x21, 0x40, 0xf9, 0x9e, 0x21, 0x40,
-0x65, 0x9f, 0x21, 0x40, 0xb9, 0x9b, 0x21, 0x40, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x48, 0x05, 0x00, 0x80, 0x11, 0x75, 0x21, 0x40, 0x1b, 0x75, 0x21, 0x40,
+0x31, 0x75, 0x21, 0x40, 0x49, 0x75, 0x21, 0x40,
+0x55, 0x75, 0x21, 0x40, 0x63, 0x75, 0x21, 0x40, 0x7d, 0x75, 0x21, 0x40,
+0xa9, 0x75, 0x21, 0x40, 0x6d, 0x76, 0x21, 0x40, 0xc5, 0x76, 0x21, 0x40,
+0xd3, 0x76, 0x21, 0x40, 0xdd, 0x76, 0x21, 0x40, 0xe7, 0x76, 0x21, 0x40,
+0x99, 0x77, 0x21, 0x40, 0xa7, 0x77, 0x21, 0x40, 0xb5, 0x77, 0x21, 0x40,
+0x61, 0x78, 0x21, 0x40, 0x5f, 0x7c, 0x21, 0x40, 0xe9, 0x7c, 0x21, 0x40,
+0x89, 0x7d, 0x21, 0x40, 0xbd, 0x7e, 0x21, 0x40, 0xc9, 0x7e, 0x21, 0x40,
+0x29, 0x7f, 0x21, 0x40, 0x8d, 0x7f, 0x21, 0x40, 0xb9, 0x7f, 0x21, 0x40,
+0xdd, 0x7f, 0x21, 0x40, 0x1d, 0x80, 0x21, 0x40, 0x45, 0x80, 0x21, 0x40,
+0x8d, 0x80, 0x21, 0x40, 0x9d, 0x80, 0x21, 0x40, 0xc5, 0x80, 0x21, 0x40,
+0xd5, 0x80, 0x21, 0x40, 0x1d, 0x81, 0x21, 0x40, 0x5b, 0x81, 0x21, 0x40,
+0xb1, 0x81, 0x21, 0x40, 0x11, 0x82, 0x21, 0x40, 0x1b, 0x82, 0x21, 0x40,
+0x1f, 0x82, 0x21, 0x40, 0x8d, 0x82, 0x21, 0x40, 0xd9, 0x82, 0x21, 0x40,
+0x31, 0x83, 0x21, 0x40, 0x6d, 0x83, 0x21, 0x40, 0xd1, 0x83, 0x21, 0x40,
+0x09, 0x84, 0x21, 0x40, 0x19, 0x84, 0x21, 0x40, 0x51, 0x84, 0x21, 0x40,
+0x61, 0x84, 0x21, 0x40, 0x75, 0x84, 0x21, 0x40, 0x9d, 0x84, 0x21, 0x40,
+0xa7, 0x84, 0x21, 0x40, 0xb1, 0x84, 0x21, 0x40, 0x15, 0x85, 0x21, 0x40,
+0x45, 0x85, 0x21, 0x40, 0x51, 0x85, 0x21, 0x40, 0xc5, 0x85, 0x21, 0x40,
+0xcf, 0x85, 0x21, 0x40, 0xd9, 0x85, 0x21, 0x40, 0xe3, 0x85, 0x21, 0x40,
+0xed, 0x85, 0x21, 0x40, 0xf7, 0x85, 0x21, 0x40, 0x01, 0x86, 0x21, 0x40,
+0x0b, 0x86, 0x21, 0x40, 0x15, 0x86, 0x21, 0x40, 0x01, 0x89, 0x21, 0x40,
+0x1f, 0x86, 0x21, 0x40, 0x29, 0x86, 0x21, 0x40, 0x33, 0x86, 0x21, 0x40,
+0x3d, 0x86, 0x21, 0x40, 0x65, 0x86, 0x21, 0x40, 0x6f, 0x86, 0x21, 0x40,
+0xd1, 0x86, 0x21, 0x40, 0xdb, 0x86, 0x21, 0x40, 0xe5, 0x86, 0x21, 0x40,
+0xef, 0x86, 0x21, 0x40, 0xf9, 0x86, 0x21, 0x40, 0x9d, 0x74, 0x21, 0x40,
+0x03, 0x87, 0x21, 0x40, 0x69, 0x87, 0x21, 0x40, 0xb5, 0x87, 0x21, 0x40,
+0xf9, 0x87, 0x21, 0x40, 0x09, 0x88, 0x21, 0x40, 0x9d, 0x74, 0x21, 0x40,
+0x55, 0x88, 0x21, 0x40, 0x59, 0x88, 0x21, 0x40, 0x5d, 0x88, 0x21, 0x40,
+0xb5, 0x88, 0x21, 0x40, 0xdd, 0x88, 0x21, 0x40, 0xe9, 0x88, 0x21, 0x40,
+0xed, 0x88, 0x21, 0x40, 0xf1, 0x88, 0x21, 0x40, 0xf5, 0x88, 0x21, 0x40,
+0xf9, 0x88, 0x21, 0x40, 0xfd, 0x88, 0x21, 0x40, 0x2d, 0x85, 0x21, 0x40,
+0x89, 0x85, 0x21, 0x40, 0x9d, 0x74, 0x21, 0x40, 0x9d, 0x74, 0x21, 0x40,
+0x0d, 0x89, 0x21, 0x40, 0x9d, 0x74, 0x21, 0x40, 0xe1, 0x74, 0x21, 0x40,
+0x9d, 0x74, 0x21, 0x40, 0x9d, 0x74, 0x21, 0x40, 0x9d, 0x74, 0x21, 0x40,
+0x9d, 0x74, 0x21, 0x40, 0x9d, 0x74, 0x21, 0x40, 0x9d, 0x74, 0x21, 0x40,
+0x6b, 0x78, 0x21, 0x40, 0xf5, 0x7b, 0x21, 0x40, 0x31, 0x7c, 0x21, 0x40,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x5c, 0x01, 0x18, 0x40, 0x58, 0x01, 0x18, 0x40,
+0x24, 0xa3, 0x20, 0x40, 0x24, 0xa7, 0x20, 0x40, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x6c, 0x01, 0x18, 0x40, 0x68, 0x01, 0x18, 0x40,
+0x24, 0x83, 0x20, 0x40, 0x24, 0xa3, 0x20, 0x40, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x7c, 0x01, 0x18, 0x40, 0x78, 0x01, 0x18, 0x40,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x8c, 0x01, 0x18, 0x40,
+0x88, 0x01, 0x18, 0x40, 0x24, 0xa9, 0x20, 0x40, 0x24, 0xab, 0x20, 0x40,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x08, 0x00, 0x12, 0x00, 0x18, 0x00, 0x12, 0x00, 0x0c, 0x00, 0x12, 0x00,
+0x1c, 0x00, 0x12, 0x00, 0x24, 0xa8, 0x20, 0x40, 0xa4, 0xa8, 0x20, 0x40,
+0xa4, 0xa8, 0x20, 0x40, 0x24, 0xa9, 0x20, 0x40, 0x00, 0x00, 0x00, 0x00,
+0xd1, 0xa8, 0x21, 0x40, 0x2d, 0xaa, 0x21, 0x40, 0x00, 0x00, 0x00, 0x00,
+0x89, 0x70, 0x21, 0x40, 0xc9, 0xa1, 0x21, 0x40, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x57, 0x89, 0x21, 0x40, 0xd1, 0xa8, 0x21, 0x40, 0xc5, 0x2f, 0xff, 0xff,
+0x05, 0x21, 0xff, 0xff, 0xef, 0x20, 0xff, 0xff, 0x59, 0xa7, 0x21, 0x40,
+0x34, 0x2e, 0x00, 0x80, 0x48, 0x2e, 0x00, 0x80, 0x5c, 0x2e, 0x00, 0x80,
+0x30, 0x33, 0x3a, 0x31, 0x31, 0x3a, 0x31, 0x31, 0x00, 0x30, 0x37, 0x2f,
+0x32, 0x33, 0x2f, 0x30, 0x31, 0x00, 0x30, 0x30, 0x30, 0x30, 0x31, 0x35,
+0x36, 0x39, 0x00, 0x43, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0x74,
+0x20, 0x28, 0x63, 0x29, 0x20, 0x32, 0x30, 0x30, 0x31, 0x20, 0x33, 0x43,
+0x6f, 0x6d, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69,
+0x6f, 0x6e, 0x0a, 0x00, 0x08, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8c, 0x53, 0xff, 0xff,
+0x27, 0xf0, 0x7d, 0xfd, 0x00, 0x01, 0x00, 0x02, 0xda, 0x0e, 0x82, 0x00,
+0x01, 0x40, 0x64, 0x04, 0x64, 0x2d, 0x00, 0x80, 0xe4, 0x2c, 0x00, 0x80,
+0x69, 0x3e, 0xff, 0xff, 0xc9, 0x4f, 0xff, 0xff, 0xd5, 0x24, 0xff, 0xff,
+0xc9, 0x3b, 0xff, 0xff, 0x29, 0x3c, 0xff, 0xff, 0x19, 0x1a, 0xff, 0xff,
+0x65, 0x11, 0xff, 0xff, 0xcc, 0x53, 0xff, 0xff, 0x21, 0x40, 0xff, 0xff,
+0x89, 0x70, 0x21, 0x40, 0x49, 0x72, 0x21, 0x40, 0xd9, 0x3f, 0xff, 0xff,
+0x21, 0x9a, 0x21, 0x40, 0x85, 0x24, 0xff, 0xff, 0x64, 0x53, 0xff, 0xff,
+0x8c, 0x53, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
+0x80, 0x30, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
+0x00, 0x00, 0x20, 0x40, 0xb0, 0x50, 0x00, 0x00, 0x7b, 0x0e, 0x00, 0x00,
+0x00, 0x6e, 0x21, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0xed, 0x89, 0x21, 0x40, 0x8b, 0x89, 0x21, 0x40, 0xa5, 0x8c, 0x21, 0x40,
+0x05, 0x8d, 0x21, 0x40, 0xcd, 0x8d, 0x21, 0x40, 0x8b, 0x8b, 0x21, 0x40,
+0xa9, 0x8e, 0x21, 0x40, 0x15, 0x8f, 0x21, 0x40, 0x69, 0x8b, 0x21, 0x40,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
-0xe9, 0xd6, 0x21, 0x40, 0x00, 0x00, 0x00, 0x00, 0xb9, 0xcb, 0x21, 0x40,
-0x55, 0xcd, 0x21, 0x40, 0x00, 0x00, 0x00, 0x00, 0x25, 0xd5, 0x21, 0x40,
-0x8d, 0xd5, 0x21, 0x40, 0xf9, 0xd5, 0x21, 0x40, 0x09, 0x29, 0x09, 0xd1,
-0x20, 0x28, 0x07, 0xd2, 0x04, 0x48, 0x01, 0x78, 0x00, 0x29, 0x03, 0xd1,
-0x01, 0x21, 0x01, 0x70, 0x02, 0x48, 0x70, 0x47, 0x00, 0x20, 0xfc, 0xe7,
-0x00, 0x6e, 0x21, 0x40, 0x24, 0xab, 0x20, 0x40, 0x03, 0x49, 0x88, 0x42,
-0x03, 0xd1, 0x00, 0x20, 0x02, 0x49, 0xc0, 0x46, 0x08, 0x70, 0x70, 0x47,
-0x24, 0xab, 0x20, 0x40, 0x00, 0x6e, 0x21, 0x40, 0x00, 0xb5, 0x00, 0x20,
-0x0b, 0x4a, 0x0b, 0x23, 0x1b, 0x02, 0xd1, 0x18, 0x2d, 0x23, 0x9b, 0x01,
-0xd3, 0x18, 0x88, 0x61, 0xd8, 0x60, 0xd8, 0x63, 0x80, 0x32, 0xc8, 0x60,
-0x08, 0x61, 0x48, 0x61, 0xd0, 0x62, 0x05, 0x48, 0xc0, 0x46, 0x48, 0x60,
-0x88, 0x60, 0x05, 0xf0, 0xcb, 0xfd, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00,
-0x68, 0x0e, 0x00, 0x80, 0xfe, 0x03, 0x00, 0x00, 0xf0, 0xb5, 0x84, 0xb0,
-0x0c, 0x1c, 0x05, 0x1c, 0x00, 0x23, 0x00, 0x93, 0xff, 0xf7, 0xda, 0xff,
-0x68, 0x49, 0x0b, 0x23, 0x1b, 0x02, 0xcf, 0x18, 0x78, 0x68, 0x28, 0x40,
+0x59, 0xbd, 0x21, 0x40, 0xc1, 0xbd, 0x21, 0x40, 0x2d, 0xbe, 0x21, 0x40,
+0x00, 0x20, 0x0a, 0x4a, 0x0b, 0x23, 0x1b, 0x02, 0xd1, 0x18, 0x2d, 0x23,
+0x9b, 0x01, 0xd3, 0x18, 0x88, 0x61, 0xd8, 0x60, 0xd8, 0x63, 0x80, 0x32,
+0xc8, 0x60, 0x08, 0x61, 0x48, 0x61, 0xd0, 0x62, 0x03, 0x48, 0xc0, 0x46,
+0x48, 0x60, 0x88, 0x60, 0x70, 0x47, 0x00, 0x00, 0x68, 0x0e, 0x00, 0x80,
+0xfe, 0x03, 0x00, 0x00, 0xf0, 0xb5, 0x84, 0xb0, 0x0c, 0x1c, 0x05, 0x1c,
+0x00, 0x23, 0x00, 0x93, 0xff, 0xf7, 0xde, 0xff, 0x68, 0x49, 0x0b, 0x23,
+0x1b, 0x02, 0xcf, 0x18, 0x78, 0x68, 0x28, 0x40,
0x00, 0x22, 0xf8, 0x60, 0x3a, 0x61, 0xba, 0x68, 0x22, 0x40, 0x7a, 0x61,
0x0c, 0x1c, 0x41, 0x09, 0x03, 0xd2, 0x51, 0x09, 0x01, 0xd2, 0x80, 0x0a,
0x02, 0xd3, 0x60, 0x48, 0x00, 0xf0, 0xc2, 0xf8, 0x01, 0x20, 0xf9, 0x68,
0x49, 0x09, 0x03, 0xd2, 0x79, 0x69, 0x49, 0x09, 0x00, 0xd2, 0x00, 0x20,
-0x00, 0x06, 0x00, 0x0e, 0x04, 0xf0, 0xc8, 0xf9, 0xf8, 0x68, 0x00, 0x28,
+0x00, 0x06, 0x00, 0x0e, 0x03, 0xf0, 0xd4, 0xfa, 0xf8, 0x68, 0x00, 0x28,
0x70, 0xd0, 0x00, 0x23, 0x02, 0x93, 0x01, 0x93, 0x54, 0x4a, 0x01, 0x23,
0x18, 0x43, 0xf8, 0x60, 0x00, 0x20, 0xd5, 0x1d, 0x79, 0x35, 0x03, 0x95,
0x01, 0x24, 0x00, 0x21, 0x4f, 0x4d, 0xfa, 0x68, 0x22, 0x40, 0x39, 0xd0,
@@ -2138,300 +2078,301 @@ const u8 typhoon_firmware_image[] = {
0x9b, 0x01, 0xc9, 0x18, 0xc8, 0x60, 0x00, 0x9b, 0x00, 0x2b, 0x0c, 0xd1,
0x81, 0x00, 0x89, 0x18, 0x0b, 0x23, 0x1b, 0x02, 0xc9, 0x18, 0xcb, 0x69,
0xc0, 0x46, 0x8b, 0x61, 0x01, 0x30, 0x0b, 0x28, 0xf4, 0xd3, 0x08, 0xe0,
-0x07, 0xe0, 0x03, 0x9d, 0xe8, 0x6a, 0x30, 0x28,
-0x03, 0xd2, 0x30, 0x20, 0x03, 0x9d, 0xc0, 0x46, 0xe8, 0x62, 0x19, 0x4a,
-0x78, 0x69, 0x00, 0x28, 0x2a, 0xd0, 0x00, 0x21, 0x01, 0x23, 0x18, 0x43,
-0x78, 0x61, 0x00, 0x20, 0x01, 0x24, 0x00, 0x22, 0x13, 0x4e, 0x7b, 0x69,
-0x23, 0x40, 0x10, 0xd0, 0x93, 0x00, 0x9b, 0x18, 0x9b, 0x00, 0x12, 0x4d,
-0x5b, 0x19, 0x9d, 0x78, 0x85, 0x42, 0x08, 0xd1, 0x1d, 0x69, 0x0b, 0x1c,
-0x9b, 0x00, 0x9e, 0x19, 0x2d, 0x23, 0x9b, 0x01, 0xf3, 0x18, 0xdd, 0x63,
-0x01, 0x31, 0x64, 0x00, 0x01, 0x32, 0x0b, 0x2a, 0xe6, 0xd3, 0x01, 0x30,
-0x09, 0x28, 0xe1, 0xd3, 0x00, 0x20, 0x89, 0x00, 0x04, 0x4a, 0x89, 0x18,
-0x2d, 0x23, 0x9b, 0x01, 0xc9, 0x18, 0xc8, 0x63, 0x04, 0xb0, 0xf0, 0xbc,
-0x08, 0xbc, 0x18, 0x47, 0x68, 0x0e, 0x00, 0x80, 0x1c, 0x53, 0xff, 0xff,
-0x00, 0x01, 0x00, 0x80, 0x00, 0x47, 0x08, 0x47, 0x10, 0x47, 0x18, 0x47,
-0x78, 0x47, 0xc0, 0x46, 0x34, 0xc0, 0x9f, 0xe5, 0x1c, 0xff, 0x2f, 0xe1,
-0x78, 0x47, 0xc0, 0x46, 0x2c, 0xc0, 0x9f, 0xe5, 0x1c, 0xff, 0x2f, 0xe1,
-0x78, 0x47, 0xc0, 0x46, 0x24, 0xc0, 0x9f, 0xe5, 0x1c, 0xff, 0x2f, 0xe1,
-0xc0, 0x46, 0xff, 0xb4, 0x75, 0x46, 0x20, 0xb4, 0x01, 0x21, 0x08, 0x43,
-0x01, 0xa4, 0xa6, 0x46, 0x00, 0x47, 0xc0, 0x46, 0x20, 0xbc, 0xae, 0x46,
-0xff, 0xbc, 0xf7, 0x46, 0x24, 0x52, 0xff, 0xff, 0x74, 0x51, 0xff, 0xff,
-0x51, 0xc0, 0x21, 0x40, 0xf0, 0xb5, 0x04, 0x20, 0x1a, 0x49, 0x01, 0x25,
-0x08, 0x60, 0x1a, 0x4f, 0xbb, 0x23, 0x1b, 0x01, 0xf8, 0x18, 0x05, 0x73,
-0x18, 0x48, 0x41, 0x6b, 0x2c, 0x05, 0x00, 0x20, 0x7a, 0x6e, 0x17, 0x4b,
-0x8a, 0x42, 0x1d, 0xd0, 0x19, 0x7b, 0x00, 0x29, 0x17, 0xd1, 0xd9, 0x1d,
-0xff, 0x31, 0x3a, 0x31, 0x49, 0x78, 0x1e, 0x1c, 0x00, 0x29, 0x10, 0xd1,
-0xb0, 0x60, 0x10, 0x20, 0x70, 0x60, 0x10, 0x4a, 0x10, 0x49, 0xff, 0xf7,
-0xb5, 0xff, 0x00, 0x28, 0x07, 0xd0, 0x35, 0x73, 0x04, 0x23, 0xb8, 0x69,
-0x18, 0x43, 0xb8, 0x61, 0x20, 0x61, 0x00, 0xf0, 0x17, 0xf8, 0xf0, 0xbc,
-0x08, 0xbc, 0x18, 0x47, 0x18, 0x73, 0x04, 0x23, 0xb8, 0x69, 0x98, 0x43,
-0xb8, 0x61, 0x20, 0x61, 0xf5, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0,
-0x68, 0x0e, 0x00, 0x80, 0x00, 0x01, 0x18, 0x40, 0x28, 0x05, 0x00, 0x80,
-0x0c, 0x55, 0xff, 0xff, 0x85, 0x74, 0x21, 0x40, 0xf8, 0xb5, 0x15, 0x4f,
-0x39, 0x6c, 0x15, 0x48, 0x40, 0x6e, 0x0c, 0x1a, 0x14, 0x4e, 0x71, 0x68,
-0x14, 0x4d, 0xa1, 0x42, 0x06, 0xd8, 0x14, 0x4a, 0x0a, 0x43, 0x00, 0x92,
-0xb9, 0x6b, 0x09, 0x18, 0xfa, 0x6b, 0x11, 0xe0, 0x11, 0x22, 0x52, 0x05,
-0x22, 0x43, 0x00, 0x92, 0xb9, 0x6b, 0x09, 0x18, 0x00, 0x20, 0xfa, 0x6b,
-0x2b, 0x1c, 0xff, 0xf7, 0x7f, 0xff, 0x70, 0x68, 0x00, 0x1b, 0x0a, 0x4a,
-0x02, 0x43, 0x00, 0x92, 0xb9, 0x6b, 0xfa, 0x6b, 0x00, 0x20, 0x2b, 0x1c,
-0xff, 0xf7, 0x74, 0xff, 0xf8, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00,
-0x7c, 0x29, 0x00, 0x80, 0x68, 0x0e, 0x00, 0x80, 0x28, 0x05, 0x00, 0x80,
-0x44, 0x80, 0x20, 0x40, 0x00, 0x00, 0x37, 0x02, 0xf0, 0xb5, 0x2b, 0x4f,
-0xb8, 0x68, 0x79, 0x68, 0xc0, 0x19, 0x20, 0x30, 0x29, 0x4a, 0xff, 0xf7,
-0x55, 0xff, 0x01, 0x20, 0xc0, 0x02, 0x28, 0x49, 0xc0, 0x46, 0x08, 0x60,
-0xb9, 0x68, 0x38, 0x1c, 0x26, 0x4d, 0x00, 0x24, 0x26, 0x4e, 0xef, 0x1d,
-0x79, 0x37, 0x00, 0x29, 0x31, 0xd1, 0x31, 0x68, 0x0a, 0x78, 0x12, 0x0a,
-0x03, 0xd2, 0x04, 0x73, 0xf0, 0xbc, 0x08, 0xbc,
-0x18, 0x47, 0x49, 0x78, 0x00, 0x29, 0x0c, 0xd1, 0x05, 0x1c, 0x40, 0x68,
-0x00, 0xf0, 0x3e, 0xf9, 0x30, 0x68, 0x00, 0xf0, 0x67, 0xf8, 0x00, 0x28,
-0x26, 0xd1, 0x2c, 0x73, 0xff, 0xf7, 0x58, 0xff, 0x22, 0xe0, 0x09, 0x01,
-0x07, 0x1c, 0x41, 0x60, 0x08, 0x1c, 0x17, 0x4a, 0x17, 0x49, 0xff, 0xf7,
-0x27, 0xff, 0x00, 0x28, 0x07, 0xd1, 0x3c, 0x73, 0x04, 0x23, 0xa8, 0x69,
-0x98, 0x43, 0x99, 0x04, 0xa8, 0x61, 0x08, 0x61, 0xda, 0xe7, 0x10, 0x20,
-0x00, 0xf0, 0x20, 0xf9, 0x10, 0x20, 0xb8, 0x60, 0xff, 0xf7, 0x82, 0xff,
-0xd2, 0xe7, 0x05, 0x1c, 0x40, 0x68, 0x00, 0xf0, 0x17, 0xf9, 0x30, 0x68,
-0x00, 0xf0, 0x40, 0xf8, 0x00, 0x28, 0xd8, 0xd0, 0x02, 0x23, 0xf8, 0x6b,
-0x18, 0x43, 0xf8, 0x63, 0xc4, 0xe7, 0x00, 0x00, 0x28, 0x05, 0x00, 0x80,
-0x91, 0x55, 0xff, 0xff, 0x00, 0x00, 0x00, 0xb0, 0x68, 0x0e, 0x00, 0x80,
-0xe4, 0x01, 0x00, 0x80, 0x0c, 0x55, 0xff, 0xff, 0x85, 0x74, 0x21, 0x40,
-0x90, 0xb5, 0x01, 0x20, 0x40, 0x03, 0x10, 0x49, 0x00, 0x27, 0x08, 0x60,
-0x0f, 0x4c, 0xe0, 0x1d, 0xff, 0x30, 0x3a, 0x30, 0x47, 0x70, 0xe0, 0x69,
-0x80, 0x00, 0x00, 0x19, 0x00, 0x69, 0x00, 0xf0, 0xd7, 0xf8, 0xe0, 0x69,
-0x00, 0x28, 0x01, 0xd0, 0xe7, 0x61, 0x01, 0xe0, 0x01, 0x20, 0xe0, 0x61,
-0x07, 0x48, 0x02, 0x23, 0xc1, 0x6b, 0x19, 0x43, 0xc1, 0x63, 0x27, 0x73,
-0xff, 0xf7, 0x00, 0xff, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00,
-0x00, 0x00, 0x00, 0xb0, 0x28, 0x05, 0x00, 0x80, 0xe8, 0x0e, 0x00, 0x80,
-0x80, 0xb5, 0x84, 0xb0, 0x07, 0x1c, 0x78, 0x88, 0x6d, 0x28, 0x03, 0xdb,
-0x38, 0x1c, 0x00, 0xf0, 0xf7, 0xf8, 0x17, 0xe0, 0x80, 0x00, 0x0d, 0x49,
-0x09, 0x58, 0x38, 0x1c, 0xff, 0xf7, 0xbd, 0xfe, 0x00, 0x28, 0x0f, 0xd1,
-0x39, 0x78, 0xc9, 0x09, 0x0c, 0xd3, 0x69, 0x46, 0x38, 0x1c, 0x00, 0xf0,
-0xcf, 0xf8, 0x68, 0x46, 0x00, 0x21, 0x00, 0xf0, 0x0b, 0xf8, 0x00, 0x28,
-0x01, 0xd1, 0x01, 0x20, 0x00, 0xe0, 0x00, 0x20, 0x04, 0xb0, 0x80, 0xbc,
-0x08, 0xbc, 0x18, 0x47, 0xe8, 0x01, 0x00, 0x80, 0xf0, 0xb5, 0x82, 0xb0,
-0x02, 0x1c, 0x41, 0x4b, 0xdd, 0x1d, 0xff, 0x35, 0x3a, 0x35, 0x2f, 0x78,
-0x00, 0x2f, 0x01, 0xd0, 0x00, 0x27, 0x00, 0xe0, 0x01, 0x27, 0x2f, 0x70,
-0x2f, 0x78, 0xfb, 0x00, 0xdb, 0x19, 0x5b, 0x01, 0x3a, 0x4f, 0xdc, 0x19,
-0x40, 0x78, 0x00, 0x01, 0xc7, 0x1d, 0x09, 0x37, 0x00, 0x20, 0x83, 0x00,
-0xd6, 0x58, 0xc0, 0x46, 0xe6, 0x50, 0x01, 0x30, 0x04, 0x28, 0xf8, 0xd3,
-0x00, 0x29, 0x0f, 0xd0, 0x00, 0x22, 0xbb, 0x08, 0x01, 0x93, 0x83, 0x42,
-0x0b, 0xd9, 0x13, 0x1c, 0x9b, 0x00, 0xcb, 0x58, 0x86, 0x00, 0xa3, 0x51,
-0x01, 0x9b, 0x01, 0x30, 0x01, 0x32, 0x83, 0x42, 0xf5, 0xd8, 0x00, 0xe0,
-0x10, 0x27, 0x2b, 0x48, 0x02, 0x6d, 0x80, 0x6e, 0x2a, 0x49, 0x82, 0x42,
-0x03, 0xd8, 0x82, 0x1a, 0xcb, 0x6c, 0x9a, 0x1a, 0x00, 0xe0, 0x12, 0x1a,
-0xba, 0x42, 0x05, 0xd8, 0x26, 0x48, 0x81, 0x6b, 0x01, 0x31, 0x81, 0x63,
-0x01, 0x20, 0x37, 0xe0, 0xc3, 0x19, 0xca, 0x6c, 0x93, 0x42, 0x08, 0xd8,
-0x22, 0x4a, 0x3a, 0x43, 0x00, 0x92, 0x0a, 0x1c, 0x49, 0x6c, 0x09, 0x18,
-0x92, 0x6c, 0x23, 0x1c, 0x12, 0xe0, 0x16, 0x1a, 0x00, 0x96, 0x1b, 0x49,
-0x49, 0x6c, 0x09, 0x18, 0x19, 0x48, 0x82, 0x6c, 0x03, 0x20, 0x23, 0x1c,
-0xff, 0xf7, 0x50, 0xfe, 0xb8, 0x1b, 0x18, 0x4a, 0x02, 0x43, 0x00, 0x92,
-0xa3, 0x19, 0x14, 0x48, 0x82, 0x6c, 0x41, 0x6c,
-0x03, 0x20, 0xff, 0xf7, 0x45, 0xfe, 0x01, 0x20, 0x0d, 0x49, 0xc0, 0x46,
-0x68, 0x70, 0x8a, 0x69, 0x92, 0x00, 0x52, 0x18, 0x17, 0x61, 0x8a, 0x69,
-0x00, 0x2a, 0x02, 0xd0, 0x00, 0x27, 0x8f, 0x61, 0x00, 0xe0, 0x88, 0x61,
-0x0c, 0x48, 0x02, 0x23, 0xc1, 0x6b, 0x19, 0x43, 0xc1, 0x63, 0x00, 0x20,
-0x01, 0x27, 0x0a, 0x49, 0xc0, 0x46, 0x4f, 0x73, 0x02, 0xb0, 0xf0, 0xbc,
-0x08, 0xbc, 0x18, 0x47, 0x28, 0x05, 0x00, 0x80, 0xfc, 0xba, 0x20, 0x40,
-0x68, 0x0e, 0x00, 0x80, 0x7c, 0x29, 0x00, 0x80, 0xa0, 0x82, 0x20, 0x40,
-0x00, 0x00, 0x19, 0x02, 0xe8, 0x0e, 0x00, 0x80, 0x18, 0x1a, 0x00, 0x80,
-0x07, 0x49, 0x8a, 0x6e, 0x10, 0x18, 0x07, 0x4a, 0xd2, 0x6c, 0x13, 0x04,
-0x1b, 0x0c, 0x83, 0x42, 0x00, 0xd8, 0x80, 0x1a, 0x88, 0x66, 0x88, 0x6e,
-0x03, 0x49, 0xc0, 0x46, 0x48, 0x61, 0x70, 0x47, 0x68, 0x0e, 0x00, 0x80,
-0x7c, 0x29, 0x00, 0x80, 0x3c, 0xef, 0x20, 0x40, 0x06, 0x49, 0x4a, 0x6e,
-0x10, 0x18, 0x06, 0x4a, 0x12, 0x6c, 0x82, 0x42, 0x00, 0xd8, 0x80, 0x1a,
-0x48, 0x66, 0x48, 0x6e, 0x03, 0x49, 0xc0, 0x46, 0x08, 0x61, 0x70, 0x47,
-0x68, 0x0e, 0x00, 0x80, 0x7c, 0x29, 0x00, 0x80, 0x3c, 0xef, 0x20, 0x40,
-0x05, 0x22, 0x0a, 0x60, 0x82, 0x88, 0xc0, 0x46, 0x8a, 0x80, 0x00, 0x22,
-0x4a, 0x70, 0x40, 0x88, 0xc0, 0x46, 0x48, 0x80, 0xca, 0x80, 0x8a, 0x60,
-0xca, 0x60, 0x70, 0x47, 0x05, 0x22, 0x02, 0x60, 0x00, 0x22, 0x82, 0x80,
-0x42, 0x70, 0x41, 0x80, 0xc2, 0x80, 0x82, 0x60, 0xc2, 0x60, 0x70, 0x47,
-0x80, 0xb5, 0x84, 0xb0, 0x07, 0x1c, 0x0e, 0x48, 0x41, 0x6b, 0x01, 0x31,
-0x41, 0x63, 0x69, 0x46, 0x38, 0x1c, 0xff, 0xf7, 0xdd, 0xff, 0x38, 0x68,
-0xc0, 0x46, 0x00, 0x90, 0x45, 0x20, 0x00, 0xab, 0x18, 0x70, 0x01, 0x27,
-0xdf, 0x80, 0x68, 0x46, 0x00, 0x21, 0xff, 0xf7, 0x11, 0xff, 0x00, 0x28,
-0x01, 0xd1, 0x38, 0x1c, 0x00, 0xe0, 0x00, 0x20, 0x04, 0xb0, 0x80, 0xbc,
-0x08, 0xbc, 0x18, 0x47, 0xa0, 0x82, 0x20, 0x40, 0x00, 0xb5, 0x84, 0xb0,
-0xc1, 0x88, 0x09, 0x4a, 0xc0, 0x46, 0x91, 0x81, 0x69, 0x46, 0xff, 0xf7,
-0xbd, 0xff, 0x01, 0x20, 0x40, 0x02, 0x01, 0xab, 0x58, 0x80, 0x68, 0x46,
-0x00, 0x21, 0xff, 0xf7, 0xf5, 0xfe, 0x01, 0x20, 0x04, 0xb0, 0x08, 0xbc,
-0x18, 0x47, 0x00, 0x00, 0xe8, 0x0e, 0x00, 0x80, 0x00, 0xb5, 0xff, 0xf7,
-0xc3, 0xff, 0x08, 0xbc, 0x18, 0x47, 0x01, 0x20, 0x03, 0x49, 0xc0, 0x46,
-0x08, 0x71, 0xa1, 0x21, 0x49, 0x03, 0x88, 0x60, 0x00, 0x20, 0x70, 0x47,
-0x28, 0x0f, 0x00, 0x80, 0x00, 0x20, 0x04, 0x49, 0xc0, 0x46, 0x08, 0x71,
-0xff, 0x21, 0xa1, 0x22, 0x52, 0x03, 0x01, 0x31, 0x91, 0x60, 0x70, 0x47,
-0x28, 0x0f, 0x00, 0x80, 0x02, 0x20, 0xa1, 0x21, 0x49, 0x03, 0x88, 0x60,
-0x00, 0x20, 0x70, 0x47, 0x01, 0x20, 0x40, 0x02, 0xa1, 0x21, 0x49, 0x03,
-0x88, 0x60, 0x00, 0x20, 0x70, 0x47, 0xc0, 0x88, 0xc0, 0x06, 0xc0, 0x0e,
-0xa1, 0x21, 0x49, 0x03, 0x48, 0x61, 0x02, 0x49, 0xc0, 0x46, 0xc8, 0x63,
-0x00, 0x20, 0x70, 0x47, 0xe8, 0x1a, 0x00, 0x80, 0x80, 0xb5, 0x84, 0xb0,
-0x08, 0x49, 0x0f, 0x6b, 0x69, 0x46, 0xff, 0xf7, 0x71, 0xff, 0xf8, 0x06,
-0xc0, 0x0e, 0x01, 0xab, 0x58, 0x80, 0x68, 0x46, 0x00, 0x21, 0xff, 0xf7,
-0xa9, 0xfe, 0x01, 0x20, 0x04, 0xb0, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47,
-0x80, 0x00, 0x14, 0x40, 0x80, 0xb5, 0x85, 0xb0, 0x07, 0x1c, 0x69, 0x46,
-0x38, 0x1c, 0xff, 0xf7, 0x5b, 0xff, 0xf8, 0x88,
-0x04, 0xa9, 0x05, 0xf0, 0xf7, 0xf9, 0x01, 0xab, 0x58, 0x80, 0x01, 0xa8,
-0x40, 0x88, 0x00, 0x28, 0x0f, 0xd0, 0x01, 0xa8, 0x40, 0x88, 0x80, 0x08,
-0x03, 0x38, 0x80, 0x08, 0x01, 0x30, 0x04, 0x3b, 0x58, 0x70, 0x04, 0x98,
-0x01, 0x68, 0xc0, 0x46, 0x02, 0x91, 0x40, 0x68, 0xc0, 0x46, 0x03, 0x90,
-0x05, 0xe0, 0x00, 0xa8, 0x00, 0x78, 0x40, 0x23, 0x18, 0x43, 0x00, 0xab,
-0x18, 0x70, 0x04, 0x98, 0xc1, 0x1d, 0x01, 0x31, 0x68, 0x46, 0xff, 0xf7,
-0x75, 0xfe, 0x01, 0x20, 0x05, 0xb0, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47,
-0x90, 0xb5, 0x84, 0xb0, 0x14, 0x4f, 0x39, 0x7b, 0x00, 0x29, 0x20, 0xd1,
-0xf9, 0x1d, 0xff, 0x31, 0x3a, 0x31, 0x49, 0x78, 0x00, 0x29, 0x1a, 0xd1,
-0x10, 0x49, 0x05, 0x22, 0x00, 0x92, 0x08, 0x22, 0x00, 0xab, 0x5a, 0x80,
-0x98, 0x80, 0x06, 0x20, 0x00, 0xab, 0x58, 0x70, 0x00, 0x24, 0xdc, 0x80,
-0x08, 0x68, 0xc0, 0x46, 0x02, 0x90, 0x48, 0x68, 0xc0, 0x46, 0x03, 0x90,
-0x01, 0x20, 0x38, 0x73, 0x68, 0x46, 0x08, 0x31, 0xff, 0xf7, 0x4c, 0xfe,
-0x00, 0x28, 0x00, 0xd0, 0x3c, 0x73, 0x04, 0xb0, 0x90, 0xbc, 0x08, 0xbc,
-0x18, 0x47, 0x00, 0x00, 0x28, 0x05, 0x00, 0x80, 0xa4, 0x2a, 0x00, 0x80,
-0x90, 0xb5, 0x84, 0xb0, 0x07, 0x1c, 0x69, 0x46, 0x38, 0x1c, 0xff, 0xf7,
-0xf9, 0xfe, 0xba, 0x68, 0x0d, 0x4c, 0x0e, 0x48, 0x00, 0x2a, 0x05, 0xd1,
-0x0d, 0x49, 0xff, 0xf7, 0xd6, 0xfc, 0x00, 0x28, 0x0c, 0xda, 0x05, 0xe0,
-0xb9, 0x88, 0x0b, 0x4b, 0xff, 0xf7, 0xd1, 0xfc, 0x00, 0x28, 0x05, 0xda,
-0x01, 0xab, 0x5c, 0x80, 0x68, 0x46, 0x00, 0x21, 0xff, 0xf7, 0x22, 0xfe,
-0x00, 0x20, 0x04, 0xb0, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00,
-0xff, 0xff, 0x00, 0x00, 0x15, 0x79, 0x21, 0x40, 0x8d, 0xd5, 0x21, 0x40,
-0x25, 0xd5, 0x21, 0x40, 0x00, 0xb5, 0xc0, 0x88, 0x05, 0xf0, 0x5c, 0xf9,
-0x00, 0x20, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0xff, 0xf7, 0xe2, 0xfe,
-0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0xff, 0xf7, 0xdd, 0xfe, 0x08, 0xbc,
-0x18, 0x47, 0x00, 0xb5, 0x01, 0x1c, 0x02, 0x20, 0x00, 0xf0, 0x02, 0xf8,
-0x08, 0xbc, 0x18, 0x47, 0xb0, 0xb5, 0xc6, 0xb0, 0x04, 0x1c, 0x08, 0x1c,
-0x69, 0x46, 0xff, 0xf7, 0xb5, 0xfe, 0x1c, 0x48, 0xff, 0xf7, 0x96, 0xfc,
-0x07, 0x1c, 0x1b, 0x4a, 0x00, 0x21, 0x20, 0x1c, 0xff, 0xf7, 0x92, 0xfc,
-0x00, 0x28, 0x1d, 0xd0, 0x04, 0xa9, 0x18, 0x4a, 0x20, 0x1c, 0xff, 0xf7,
-0x8b, 0xfc, 0x04, 0x98, 0x04, 0x28, 0x05, 0xd9, 0x04, 0x98, 0x80, 0x08,
-0x03, 0x38, 0x80, 0x08, 0x01, 0x30, 0x00, 0xe0, 0x00, 0x20, 0x00, 0xab,
-0x58, 0x70, 0x06, 0xa8, 0x00, 0x78, 0xc0, 0x46, 0xd8, 0x80, 0x04, 0x98,
-0xc0, 0x46, 0x02, 0x90, 0x07, 0x98, 0xc0, 0x46, 0x03, 0x90, 0x04, 0x33,
-0x08, 0xad, 0x02, 0xe0, 0x45, 0x20, 0x00, 0xab, 0x18, 0x70, 0x09, 0x49,
-0x38, 0x1c, 0xff, 0xf7, 0x6a, 0xfc, 0x68, 0x46, 0x29, 0x1c, 0xff, 0xf7,
-0xc1, 0xfd, 0x01, 0x20, 0x46, 0xb0, 0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47,
-0x24, 0x02, 0xff, 0xff, 0xcd, 0xc0, 0x21, 0x40, 0x29, 0xbf, 0x21, 0x40,
-0x3c, 0x02, 0xff, 0xff, 0x00, 0xb5, 0x01, 0x1c, 0x02, 0x20, 0x00, 0xf0,
-0x10, 0xf8, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0x01, 0x1c, 0x01, 0x20,
-0xff, 0xf7, 0xac, 0xff, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0x01, 0x1c,
-0x01, 0x20, 0x00, 0xf0, 0x02, 0xf8, 0x08, 0xbc, 0x18, 0x47, 0xf3, 0xb5,
-0xc6, 0xb0, 0x0f, 0x1c, 0x69, 0x46, 0x38, 0x1c,
-0xff, 0xf7, 0x58, 0xfe, 0x20, 0x48, 0xff, 0xf7, 0x39, 0xfc, 0x04, 0x1c,
-0x78, 0x78, 0x00, 0x01, 0xba, 0x68, 0x04, 0x30, 0xfc, 0x2a, 0x23, 0xd8,
-0xff, 0x23, 0x09, 0x33, 0x98, 0x42, 0x1f, 0xd8, 0xfd, 0x88, 0xf8, 0x68,
-0xc0, 0x46, 0x04, 0x90, 0x05, 0xa9, 0xfb, 0x1d, 0x09, 0x33, 0x00, 0x20,
-0x7e, 0x78, 0x00, 0x2e, 0x0d, 0xdd, 0x40, 0xcb, 0x40, 0xc1, 0x40, 0xcb,
-0x40, 0xc1, 0x40, 0xcb, 0x40, 0xc1, 0x40, 0xcb, 0x40, 0xc1, 0x01, 0x30,
-0x00, 0x04, 0x00, 0x0c, 0x7e, 0x78, 0x86, 0x42, 0xf1, 0xdc, 0x46, 0x98,
-0x04, 0xa9, 0x2b, 0x1c, 0xff, 0xf7, 0x20, 0xfc, 0x00, 0x28, 0x05, 0xd0,
-0x00, 0xa8, 0x00, 0x78, 0x40, 0x23, 0x18, 0x43, 0x00, 0xab, 0x18, 0x70,
-0x07, 0x49, 0x20, 0x1c, 0xff, 0xf7, 0x05, 0xfc, 0x68, 0x46, 0x00, 0x21,
-0xff, 0xf7, 0x5c, 0xfd, 0x01, 0x20, 0x48, 0xb0, 0xf0, 0xbc, 0x08, 0xbc,
-0x18, 0x47, 0x00, 0x00, 0x24, 0x02, 0xff, 0xff, 0x3c, 0x02, 0xff, 0xff,
-0x00, 0xb5, 0xff, 0xf7, 0x27, 0xfe, 0x08, 0xbc, 0x18, 0x47, 0xf0, 0xb5,
-0xc6, 0xb0, 0x07, 0x1c, 0xfc, 0x88, 0x25, 0x4d, 0x68, 0x68, 0x01, 0x30,
-0x69, 0x46, 0x68, 0x60, 0x38, 0x1c, 0xff, 0xf7, 0x01, 0xfe, 0x10, 0x2c,
-0x08, 0xd3, 0x00, 0xa8, 0x00, 0x78, 0x40, 0x23, 0x18, 0x43, 0x00, 0xab,
-0x18, 0x70, 0x02, 0x20, 0xd8, 0x80, 0x17, 0xe0, 0x78, 0x78, 0x82, 0x00,
-0xfb, 0x1d, 0x09, 0x33, 0x00, 0x20, 0xb9, 0x68, 0x00, 0x2a, 0x15, 0xd9,
-0x40, 0xcb, 0x0f, 0x1c, 0x01, 0x31, 0xbe, 0x42, 0x0d, 0xd0, 0x00, 0xaa,
-0x12, 0x78, 0x40, 0x23, 0x1a, 0x43, 0x00, 0xab, 0x1a, 0x70, 0x04, 0x22,
-0xda, 0x80, 0x02, 0x90, 0x03, 0x91, 0x04, 0x33, 0x68, 0x46, 0x00, 0x21,
-0x15, 0xe0, 0x01, 0x30, 0x90, 0x42, 0xe9, 0xd3, 0x00, 0xab, 0x5c, 0x70,
-0x02, 0x94, 0x69, 0x68, 0xc0, 0x46, 0x03, 0x91, 0xa2, 0x00, 0x00, 0x20,
-0x10, 0x33, 0x00, 0x2a, 0x05, 0xd9, 0x0f, 0x1c, 0x80, 0xc3, 0x01, 0x30,
-0x01, 0x31, 0x90, 0x42, 0xf9, 0xd3, 0x68, 0x46, 0x04, 0xa9, 0xff, 0xf7,
-0x03, 0xfd, 0x01, 0x20, 0x46, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47,
-0x9c, 0x03, 0x00, 0x80, 0x90, 0xb4, 0x23, 0x48, 0x00, 0x68, 0x01, 0x21,
-0x42, 0x09, 0x00, 0xd3, 0x00, 0x21, 0x00, 0x27, 0x3a, 0x1c, 0x43, 0x0b,
-0x00, 0xd2, 0x02, 0x22, 0x11, 0x43, 0x1e, 0x4a, 0x20, 0x24, 0xd3, 0x68,
-0x01, 0x2b, 0x2e, 0xd1, 0x80, 0x0a, 0x00, 0xd2, 0x00, 0x24, 0x0c, 0x43,
-0x20, 0x1c, 0x1b, 0x23, 0xdb, 0x01, 0xd1, 0x18, 0x89, 0x8b, 0x09, 0x0b,
-0x00, 0xd2, 0x04, 0x27, 0x38, 0x43, 0xd1, 0x6f, 0x09, 0x68, 0x09, 0x0a,
-0x07, 0xd2, 0xd1, 0x1d, 0x79, 0x31, 0x09, 0x68, 0x09, 0x68, 0x09, 0x0a,
-0x01, 0xd3, 0x08, 0x23, 0x18, 0x43, 0xe3, 0x23, 0x1b, 0x01, 0xd1, 0x18,
-0x89, 0x79, 0x03, 0x29, 0x02, 0xd1, 0xff, 0x23, 0x01, 0x33, 0x18, 0x43,
-0x0b, 0x49, 0x09, 0x6a, 0x10, 0x22, 0x4b, 0x0a, 0x00, 0xd2, 0x00, 0x22,
-0x10, 0x43, 0x89, 0x07, 0x89, 0x0f, 0x89, 0x01, 0x08, 0x43, 0x90, 0xbc,
-0x70, 0x47, 0x40, 0x0c, 0x00, 0xd2, 0x00, 0x24, 0x0c, 0x43, 0x20, 0x1c,
-0xec, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, 0x68, 0x0e, 0x00, 0x80,
-0xc0, 0x00, 0x18, 0x40, 0xf0, 0xb5, 0x3a, 0x4c, 0x20, 0x1c, 0x05, 0xf0,
-0x75, 0xfc, 0x39, 0x48, 0xe3, 0x23, 0x1b, 0x01, 0xc7, 0x18, 0xb9, 0x79,
-0x37, 0x4e, 0xc5, 0x1d, 0x79, 0x35, 0x06, 0x29, 0x62, 0xd2, 0x02, 0xa3,
-0x5b, 0x5c, 0x5b, 0x00, 0x9f, 0x44, 0x00, 0x1c,
-0x03, 0x0e, 0x1e, 0x37, 0x4e, 0x55, 0x01, 0x20, 0xb8, 0x71, 0x00, 0x20,
-0xb0, 0x60, 0xff, 0xf7, 0x95, 0xff, 0x05, 0x23, 0x98, 0x43, 0x00, 0xf0,
-0x6f, 0xf8, 0x0c, 0xe0, 0xff, 0xf7, 0x8e, 0xff, 0xc0, 0x08, 0x06, 0xd3,
-0xb0, 0x68, 0x41, 0x1c, 0xb1, 0x60, 0x0a, 0x28, 0x03, 0xd9, 0x04, 0x20,
-0x00, 0xe0, 0x02, 0x20, 0xb8, 0x71, 0x64, 0x22, 0x20, 0x1c, 0x2b, 0xe0,
-0x06, 0x1c, 0xc0, 0x6f, 0x80, 0x23, 0x01, 0x68, 0x19, 0x43, 0x01, 0x60,
-0x03, 0x20, 0xb8, 0x71, 0x20, 0x1c, 0x20, 0x4a, 0x00, 0x21, 0x05, 0xf0,
-0x07, 0xfc, 0xf0, 0x6f, 0x04, 0x23, 0x01, 0x68, 0x99, 0x43, 0x01, 0x60,
-0x28, 0x68, 0x01, 0x68, 0x19, 0x43, 0x01, 0x60, 0xf0, 0xbc, 0x08, 0xbc,
-0x18, 0x47, 0x05, 0x21, 0xb9, 0x71, 0x29, 0x68, 0x04, 0x23, 0x0a, 0x68,
-0x9a, 0x43, 0x0a, 0x60, 0xc0, 0x6f, 0x01, 0x68, 0x19, 0x43, 0x01, 0x60,
-0xff, 0xf7, 0x5a, 0xff, 0x08, 0x23, 0x18, 0x43, 0x00, 0xf0, 0x34, 0xf8,
-0x20, 0x1c, 0x10, 0x4a, 0x00, 0x21, 0x05, 0xf0, 0xe5, 0xfb, 0xe5, 0xe7,
-0xff, 0xf7, 0x4e, 0xff, 0x04, 0x23, 0x18, 0x43, 0x00, 0xf0, 0x28, 0xf8,
-0xde, 0xe7, 0x00, 0x20, 0x29, 0x68, 0x60, 0x23, 0x0a, 0x68, 0x9a, 0x43,
-0x0a, 0x60, 0xff, 0xf7, 0xe1, 0xfa, 0xd5, 0xe7, 0x06, 0x20, 0xb8, 0x71,
-0xd2, 0xe7, 0x00, 0x00, 0x99, 0x7c, 0x21, 0x40, 0x68, 0x0e, 0x00, 0x80,
-0x9c, 0x03, 0x00, 0x80, 0x30, 0x75, 0x00, 0x00, 0x10, 0x27, 0x00, 0x00,
-0x00, 0xb5, 0x00, 0x20, 0x04, 0x49, 0xc0, 0x46, 0x88, 0x71, 0x04, 0x48,
-0x01, 0x22, 0x00, 0x21, 0x05, 0xf0, 0xbc, 0xfb, 0x08, 0xbc, 0x18, 0x47,
-0x98, 0x1c, 0x00, 0x80, 0x99, 0x7c, 0x21, 0x40, 0x90, 0xb5, 0x07, 0x1c,
-0x31, 0x48, 0x00, 0x68, 0x79, 0x08, 0x03, 0xd3, 0x10, 0x23, 0x01, 0x1c,
-0x99, 0x43, 0x01, 0xe0, 0x10, 0x21, 0x01, 0x43, 0x2d, 0x4c, 0xe2, 0x68,
-0x01, 0x2a, 0x05, 0xd1, 0x22, 0x79, 0x00, 0x2a, 0x02, 0xd0, 0x01, 0x23,
-0x9b, 0x02, 0x19, 0x43, 0x81, 0x42, 0x02, 0xd0, 0x01, 0x20, 0x00, 0x05,
-0x01, 0x60, 0xe0, 0x68, 0x01, 0x28, 0x20, 0xd1, 0x1b, 0x23, 0xdb, 0x01,
-0xe0, 0x18, 0x80, 0x8b, 0xf9, 0x08, 0x04, 0xd3, 0x01, 0x23, 0xdb, 0x02,
-0x01, 0x1c, 0x99, 0x43, 0x01, 0xe0, 0x01, 0x21, 0xc9, 0x02, 0x81, 0x42,
-0x02, 0xd0, 0x00, 0x20, 0x03, 0xf0, 0xca, 0xf9, 0x38, 0x09, 0x07, 0xd3,
-0xe0, 0x6f, 0x80, 0x23, 0x01, 0x68, 0x99, 0x43, 0x01, 0x60, 0xe0, 0x18,
-0x00, 0x68, 0x00, 0xe0, 0xe0, 0x6f, 0x80, 0x23, 0x01, 0x68, 0x19, 0x43,
-0x01, 0x60, 0x15, 0x48, 0x01, 0x6a, 0x78, 0x09, 0x03, 0xd3, 0xff, 0x20,
-0x01, 0x30, 0x08, 0x43, 0x03, 0xe0, 0xff, 0x23, 0x08, 0x1c, 0x01, 0x33,
-0x98, 0x43, 0x80, 0x08, 0x80, 0x00, 0xba, 0x09, 0x92, 0x07, 0x92, 0x0f,
-0x10, 0x43, 0x88, 0x42, 0x02, 0xd0, 0x0c, 0x49, 0xc0, 0x46, 0x08, 0x62,
-0xe1, 0x68, 0x01, 0x29, 0x08, 0xd1, 0x79, 0x0a, 0x06, 0xd3, 0xff, 0x23,
-0x04, 0x33, 0x18, 0x40, 0x03, 0x28, 0x01, 0xd1, 0xff, 0xf7, 0x8e, 0xff,
-0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40,
-0x68, 0x0e, 0x00, 0x80, 0xc0, 0x00, 0x18, 0x40, 0xc0, 0x00, 0x18, 0x00,
-0x80, 0xb5, 0xff, 0xf7, 0xb1, 0xfe, 0x80, 0x09, 0x1b, 0xd2, 0x0f, 0x48,
-0xe3, 0x23, 0x1b, 0x01, 0xc1, 0x18, 0x4a, 0x79, 0x00, 0x2a, 0x14, 0xd1,
-0x01, 0x22, 0x4a, 0x71, 0x00, 0x27, 0x80, 0x30, 0x00, 0x68, 0x60, 0x23,
-0x01, 0x68, 0x99, 0x43, 0x01, 0x60, 0x08, 0x48,
-0x06, 0xe0, 0x02, 0x20, 0x03, 0xf0, 0x7e, 0xfb, 0x07, 0x20, 0x03, 0xf0,
-0x4d, 0xfb, 0x38, 0x1c, 0xff, 0xf7, 0x34, 0xfa, 0xf5, 0xe7, 0x80, 0xbc,
-0x08, 0xbc, 0x18, 0x47, 0x68, 0x0e, 0x00, 0x80, 0xf4, 0x01, 0xff, 0xff,
-0x00, 0xb5, 0x84, 0xb0, 0x69, 0x46, 0xff, 0xf7, 0x43, 0xfc, 0xff, 0xf7,
-0x85, 0xfe, 0x01, 0xab, 0x58, 0x80, 0x08, 0x48, 0x00, 0x68, 0xc0, 0x46,
-0x02, 0x90, 0x07, 0x48, 0x00, 0x6a, 0xc0, 0x46, 0x03, 0x90, 0x68, 0x46,
-0x00, 0x21, 0xff, 0xf7, 0x73, 0xfb, 0x01, 0x20, 0x04, 0xb0, 0x08, 0xbc,
-0x18, 0x47, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, 0xc0, 0x00, 0x18, 0x40,
-0x80, 0xb5, 0x84, 0xb0, 0x07, 0x1c, 0x69, 0x46, 0x38, 0x1c, 0xff, 0xf7,
-0x23, 0xfc, 0xf8, 0x88, 0xff, 0xf7, 0x42, 0xff, 0xff, 0xf7, 0x62, 0xfe,
-0x01, 0xab, 0x58, 0x80, 0x68, 0x46, 0x00, 0x21, 0xff, 0xf7, 0x58, 0xfb,
-0x01, 0x20, 0x04, 0xb0, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xb0, 0xb5,
-0xc6, 0xb0, 0xc7, 0x88, 0x69, 0x46, 0xff, 0xf7, 0x0d, 0xfc, 0x01, 0x24,
-0x16, 0x4b, 0x9f, 0x42, 0x0a, 0xd9, 0x00, 0xa8, 0x00, 0x78, 0x40, 0x23,
-0x18, 0x43, 0x00, 0xab, 0x18, 0x70, 0x02, 0x20, 0xd8, 0x80, 0x68, 0x46,
-0x00, 0x21, 0x17, 0xe0, 0x10, 0x48, 0xff, 0xf7, 0xdf, 0xf9, 0x05, 0x1c,
-0x0f, 0x4a, 0x38, 0x1c, 0x04, 0xa9, 0xff, 0xf7, 0xdb, 0xf9, 0x0e, 0x49,
-0x28, 0x1c, 0xff, 0xf7, 0xd6, 0xf9, 0x10, 0x20, 0x00, 0xab, 0x58, 0x70,
-0x04, 0x98, 0xc0, 0x46, 0x02, 0x90, 0x05, 0x98, 0xc0, 0x46, 0x03, 0x90,
-0x68, 0x46, 0x06, 0xa9, 0xff, 0xf7, 0x24, 0xfb, 0x20, 0x1c, 0x46, 0xb0,
-0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00,
-0x24, 0x02, 0xff, 0xff, 0x29, 0xbf, 0x21, 0x40, 0x3c, 0x02, 0xff, 0xff,
+0x07, 0xe0, 0x03, 0x9d, 0xe8, 0x6a, 0x30, 0x28, 0x03, 0xd2, 0x30, 0x20,
+0x03, 0x9d, 0xc0, 0x46, 0xe8, 0x62, 0x19, 0x4a, 0x78, 0x69, 0x00, 0x28,
+0x2a, 0xd0, 0x00, 0x21, 0x01, 0x23, 0x18, 0x43, 0x78, 0x61, 0x00, 0x20,
+0x01, 0x24, 0x00, 0x22, 0x13, 0x4e, 0x7b, 0x69, 0x23, 0x40, 0x10, 0xd0,
+0x93, 0x00, 0x9b, 0x18, 0x9b, 0x00, 0x12, 0x4d, 0x5b, 0x19, 0x9d, 0x78,
+0x85, 0x42, 0x08, 0xd1, 0x1d, 0x69, 0x0b, 0x1c, 0x9b, 0x00, 0x9e, 0x19,
+0x2d, 0x23, 0x9b, 0x01, 0xf3, 0x18, 0xdd, 0x63, 0x01, 0x31, 0x64, 0x00,
+0x01, 0x32, 0x0b, 0x2a, 0xe6, 0xd3, 0x01, 0x30, 0x09, 0x28, 0xe1, 0xd3,
+0x00, 0x20, 0x89, 0x00, 0x04, 0x4a, 0x89, 0x18, 0x2d, 0x23, 0x9b, 0x01,
+0xc9, 0x18, 0xc8, 0x63, 0x04, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47,
+0x68, 0x0e, 0x00, 0x80, 0x30, 0x53, 0xff, 0xff, 0x00, 0x01, 0x00, 0x80,
+0x00, 0x47, 0x08, 0x47, 0x10, 0x47, 0x18, 0x47, 0x78, 0x47, 0xc0, 0x46,
+0x18, 0xc0, 0x9f, 0xe5, 0x1c, 0xff, 0x2f, 0xe1, 0x78, 0x47, 0xc0, 0x46,
+0x10, 0xc0, 0x9f, 0xe5, 0x1c, 0xff, 0x2f, 0xe1, 0x78, 0x47, 0xc0, 0x46,
+0x08, 0xc0, 0x9f, 0xe5, 0x1c, 0xff, 0x2f, 0xe1, 0x38, 0x52, 0xff, 0xff,
+0x88, 0x51, 0xff, 0xff, 0xd5, 0xb0, 0x21, 0x40, 0xf0, 0xb5, 0x04, 0x20,
+0x1a, 0x49, 0x01, 0x25, 0x08, 0x60, 0x1a, 0x4f, 0xbb, 0x23, 0x1b, 0x01,
+0xf8, 0x18, 0x05, 0x73, 0x18, 0x48, 0x41, 0x6b, 0x2c, 0x05, 0x00, 0x20,
+0x7a, 0x6e, 0x17, 0x4b, 0x8a, 0x42, 0x1d, 0xd0,
+0x19, 0x7b, 0x00, 0x29, 0x17, 0xd1, 0xd9, 0x1d, 0xff, 0x31, 0x3a, 0x31,
+0x49, 0x78, 0x1e, 0x1c, 0x00, 0x29, 0x10, 0xd1, 0xb0, 0x60, 0x10, 0x20,
+0x70, 0x60, 0x10, 0x4a, 0x10, 0x49, 0xff, 0xf7, 0xc3, 0xff, 0x00, 0x28,
+0x07, 0xd0, 0x35, 0x73, 0x04, 0x23, 0xb8, 0x69, 0x18, 0x43, 0xb8, 0x61,
+0x20, 0x61, 0x00, 0xf0, 0x17, 0xf8, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47,
+0x18, 0x73, 0x04, 0x23, 0xb8, 0x69, 0x98, 0x43, 0xb8, 0x61, 0x20, 0x61,
+0xf5, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x68, 0x0e, 0x00, 0x80,
+0x00, 0x01, 0x18, 0x40, 0x28, 0x05, 0x00, 0x80, 0x20, 0x55, 0xff, 0xff,
+0x7d, 0x71, 0x21, 0x40, 0xf8, 0xb5, 0x15, 0x4f, 0x39, 0x6c, 0x15, 0x48,
+0x40, 0x6e, 0x0c, 0x1a, 0x14, 0x4e, 0x71, 0x68, 0x14, 0x4d, 0xa1, 0x42,
+0x06, 0xd8, 0x14, 0x4a, 0x0a, 0x43, 0x00, 0x92, 0xb9, 0x6b, 0x09, 0x18,
+0xfa, 0x6b, 0x11, 0xe0, 0x11, 0x22, 0x52, 0x05, 0x22, 0x43, 0x00, 0x92,
+0xb9, 0x6b, 0x09, 0x18, 0x00, 0x20, 0xfa, 0x6b, 0x2b, 0x1c, 0xff, 0xf7,
+0x8d, 0xff, 0x70, 0x68, 0x00, 0x1b, 0x0a, 0x4a, 0x02, 0x43, 0x00, 0x92,
+0xb9, 0x6b, 0xfa, 0x6b, 0x00, 0x20, 0x2b, 0x1c, 0xff, 0xf7, 0x82, 0xff,
+0xf8, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x7c, 0x29, 0x00, 0x80,
+0x68, 0x0e, 0x00, 0x80, 0x28, 0x05, 0x00, 0x80, 0x44, 0x80, 0x20, 0x40,
+0x00, 0x00, 0x37, 0x02, 0xf0, 0xb5, 0x2b, 0x4f, 0xb8, 0x68, 0x79, 0x68,
+0xc0, 0x19, 0x20, 0x30, 0x29, 0x4a, 0xff, 0xf7, 0x63, 0xff, 0x01, 0x20,
+0xc0, 0x02, 0x28, 0x49, 0xc0, 0x46, 0x08, 0x60, 0xb9, 0x68, 0x38, 0x1c,
+0x26, 0x4d, 0x00, 0x24, 0x26, 0x4e, 0xef, 0x1d, 0x79, 0x37, 0x00, 0x29,
+0x31, 0xd1, 0x31, 0x68, 0x0a, 0x78, 0x12, 0x0a, 0x03, 0xd2, 0x04, 0x73,
+0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x49, 0x78, 0x00, 0x29, 0x0c, 0xd1,
+0x05, 0x1c, 0x40, 0x68, 0x00, 0xf0, 0x3e, 0xf9, 0x30, 0x68, 0x00, 0xf0,
+0x67, 0xf8, 0x00, 0x28, 0x26, 0xd1, 0x2c, 0x73, 0xff, 0xf7, 0x58, 0xff,
+0x22, 0xe0, 0x09, 0x01, 0x07, 0x1c, 0x41, 0x60, 0x08, 0x1c, 0x17, 0x4a,
+0x17, 0x49, 0xff, 0xf7, 0x35, 0xff, 0x00, 0x28, 0x07, 0xd1, 0x3c, 0x73,
+0x04, 0x23, 0xa8, 0x69, 0x98, 0x43, 0x99, 0x04, 0xa8, 0x61, 0x08, 0x61,
+0xda, 0xe7, 0x10, 0x20, 0x00, 0xf0, 0x20, 0xf9, 0x10, 0x20, 0xb8, 0x60,
+0xff, 0xf7, 0x82, 0xff, 0xd2, 0xe7, 0x05, 0x1c, 0x40, 0x68, 0x00, 0xf0,
+0x17, 0xf9, 0x30, 0x68, 0x00, 0xf0, 0x40, 0xf8, 0x00, 0x28, 0xd8, 0xd0,
+0x02, 0x23, 0xf8, 0x6b, 0x18, 0x43, 0xf8, 0x63, 0xc4, 0xe7, 0x00, 0x00,
+0x28, 0x05, 0x00, 0x80, 0xa5, 0x55, 0xff, 0xff, 0x00, 0x00, 0x00, 0xb0,
+0x68, 0x0e, 0x00, 0x80, 0xe4, 0x01, 0x00, 0x80, 0x20, 0x55, 0xff, 0xff,
+0x7d, 0x71, 0x21, 0x40, 0x90, 0xb5, 0x01, 0x20, 0x40, 0x03, 0x10, 0x49,
+0x00, 0x27, 0x08, 0x60, 0x0f, 0x4c, 0xe0, 0x1d, 0xff, 0x30, 0x3a, 0x30,
+0x47, 0x70, 0xe0, 0x69, 0x80, 0x00, 0x00, 0x19, 0x00, 0x69, 0x00, 0xf0,
+0xd7, 0xf8, 0xe0, 0x69, 0x00, 0x28, 0x01, 0xd0, 0xe7, 0x61, 0x01, 0xe0,
+0x01, 0x20, 0xe0, 0x61, 0x07, 0x48, 0x02, 0x23, 0xc1, 0x6b, 0x19, 0x43,
+0xc1, 0x63, 0x27, 0x73, 0xff, 0xf7, 0x00, 0xff, 0x90, 0xbc, 0x08, 0xbc,
+0x18, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x28, 0x05, 0x00, 0x80,
+0xe8, 0x0e, 0x00, 0x80, 0x80, 0xb5, 0x84, 0xb0, 0x07, 0x1c, 0x78, 0x88,
+0x6d, 0x28, 0x03, 0xdb, 0x38, 0x1c, 0x00, 0xf0,
+0xf7, 0xf8, 0x17, 0xe0, 0x80, 0x00, 0x0d, 0x49, 0x09, 0x58, 0x38, 0x1c,
+0xff, 0xf7, 0xcb, 0xfe, 0x00, 0x28, 0x0f, 0xd1, 0x39, 0x78, 0xc9, 0x09,
+0x0c, 0xd3, 0x69, 0x46, 0x38, 0x1c, 0x00, 0xf0, 0xcf, 0xf8, 0x68, 0x46,
+0x00, 0x21, 0x00, 0xf0, 0x0b, 0xf8, 0x00, 0x28, 0x01, 0xd1, 0x01, 0x20,
+0x00, 0xe0, 0x00, 0x20, 0x04, 0xb0, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47,
+0xe8, 0x01, 0x00, 0x80, 0xf0, 0xb5, 0x82, 0xb0, 0x02, 0x1c, 0x41, 0x4b,
+0xdd, 0x1d, 0xff, 0x35, 0x3a, 0x35, 0x2f, 0x78, 0x00, 0x2f, 0x01, 0xd0,
+0x00, 0x27, 0x00, 0xe0, 0x01, 0x27, 0x2f, 0x70, 0x2f, 0x78, 0xfb, 0x00,
+0xdb, 0x19, 0x5b, 0x01, 0x3a, 0x4f, 0xdc, 0x19, 0x40, 0x78, 0x00, 0x01,
+0xc7, 0x1d, 0x09, 0x37, 0x00, 0x20, 0x83, 0x00, 0xd6, 0x58, 0xc0, 0x46,
+0xe6, 0x50, 0x01, 0x30, 0x04, 0x28, 0xf8, 0xd3, 0x00, 0x29, 0x0f, 0xd0,
+0x00, 0x22, 0xbb, 0x08, 0x01, 0x93, 0x83, 0x42, 0x0b, 0xd9, 0x13, 0x1c,
+0x9b, 0x00, 0xcb, 0x58, 0x86, 0x00, 0xa3, 0x51, 0x01, 0x9b, 0x01, 0x30,
+0x01, 0x32, 0x83, 0x42, 0xf5, 0xd8, 0x00, 0xe0, 0x10, 0x27, 0x2b, 0x48,
+0x02, 0x6d, 0x80, 0x6e, 0x2a, 0x49, 0x82, 0x42, 0x03, 0xd8, 0x82, 0x1a,
+0xcb, 0x6c, 0x9a, 0x1a, 0x00, 0xe0, 0x12, 0x1a, 0xba, 0x42, 0x05, 0xd8,
+0x26, 0x48, 0x81, 0x6b, 0x01, 0x31, 0x81, 0x63, 0x01, 0x20, 0x37, 0xe0,
+0xc3, 0x19, 0xca, 0x6c, 0x93, 0x42, 0x08, 0xd8, 0x22, 0x4a, 0x3a, 0x43,
+0x00, 0x92, 0x0a, 0x1c, 0x49, 0x6c, 0x09, 0x18, 0x92, 0x6c, 0x23, 0x1c,
+0x12, 0xe0, 0x16, 0x1a, 0x00, 0x96, 0x1b, 0x49, 0x49, 0x6c, 0x09, 0x18,
+0x19, 0x48, 0x82, 0x6c, 0x03, 0x20, 0x23, 0x1c, 0xff, 0xf7, 0x5e, 0xfe,
+0xb8, 0x1b, 0x18, 0x4a, 0x02, 0x43, 0x00, 0x92, 0xa3, 0x19, 0x14, 0x48,
+0x82, 0x6c, 0x41, 0x6c, 0x03, 0x20, 0xff, 0xf7, 0x53, 0xfe, 0x01, 0x20,
+0x0d, 0x49, 0xc0, 0x46, 0x68, 0x70, 0x8a, 0x69, 0x92, 0x00, 0x52, 0x18,
+0x17, 0x61, 0x8a, 0x69, 0x00, 0x2a, 0x02, 0xd0, 0x00, 0x27, 0x8f, 0x61,
+0x00, 0xe0, 0x88, 0x61, 0x0c, 0x48, 0x02, 0x23, 0xc1, 0x6b, 0x19, 0x43,
+0xc1, 0x63, 0x00, 0x20, 0x01, 0x27, 0x0a, 0x49, 0xc0, 0x46, 0x4f, 0x73,
+0x02, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x28, 0x05, 0x00, 0x80,
+0x50, 0xba, 0x20, 0x40, 0x68, 0x0e, 0x00, 0x80, 0x7c, 0x29, 0x00, 0x80,
+0xa0, 0x82, 0x20, 0x40, 0x00, 0x00, 0x19, 0x02, 0xe8, 0x0e, 0x00, 0x80,
+0x18, 0x1a, 0x00, 0x80, 0x07, 0x49, 0x8a, 0x6e, 0x10, 0x18, 0x07, 0x4a,
+0xd2, 0x6c, 0x13, 0x04, 0x1b, 0x0c, 0x83, 0x42, 0x00, 0xd8, 0x80, 0x1a,
+0x88, 0x66, 0x88, 0x6e, 0x03, 0x49, 0xc0, 0x46, 0x48, 0x61, 0x70, 0x47,
+0x68, 0x0e, 0x00, 0x80, 0x7c, 0x29, 0x00, 0x80, 0x90, 0xee, 0x20, 0x40,
+0x06, 0x49, 0x4a, 0x6e, 0x10, 0x18, 0x06, 0x4a, 0x12, 0x6c, 0x82, 0x42,
+0x00, 0xd8, 0x80, 0x1a, 0x48, 0x66, 0x48, 0x6e, 0x03, 0x49, 0xc0, 0x46,
+0x08, 0x61, 0x70, 0x47, 0x68, 0x0e, 0x00, 0x80, 0x7c, 0x29, 0x00, 0x80,
+0x90, 0xee, 0x20, 0x40, 0x05, 0x22, 0x0a, 0x60, 0x82, 0x88, 0xc0, 0x46,
+0x8a, 0x80, 0x00, 0x22, 0x4a, 0x70, 0x40, 0x88, 0xc0, 0x46, 0x48, 0x80,
+0xca, 0x80, 0x8a, 0x60, 0xca, 0x60, 0x70, 0x47, 0x05, 0x22, 0x02, 0x60,
+0x00, 0x22, 0x82, 0x80, 0x42, 0x70, 0x41, 0x80, 0xc2, 0x80, 0x82, 0x60,
+0xc2, 0x60, 0x70, 0x47, 0x80, 0xb5, 0x84, 0xb0, 0x07, 0x1c, 0x0e, 0x48,
+0x41, 0x6b, 0x01, 0x31, 0x41, 0x63, 0x69, 0x46,
+0x38, 0x1c, 0xff, 0xf7, 0xdd, 0xff, 0x38, 0x68, 0xc0, 0x46, 0x00, 0x90,
+0x45, 0x20, 0x00, 0xab, 0x18, 0x70, 0x01, 0x27, 0xdf, 0x80, 0x68, 0x46,
+0x00, 0x21, 0xff, 0xf7, 0x11, 0xff, 0x00, 0x28, 0x01, 0xd1, 0x38, 0x1c,
+0x00, 0xe0, 0x00, 0x20, 0x04, 0xb0, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47,
+0xa0, 0x82, 0x20, 0x40, 0x00, 0xb5, 0x84, 0xb0, 0xc1, 0x88, 0x09, 0x4a,
+0xc0, 0x46, 0x91, 0x81, 0x69, 0x46, 0xff, 0xf7, 0xbd, 0xff, 0x01, 0x20,
+0x40, 0x02, 0x01, 0xab, 0x58, 0x80, 0x68, 0x46, 0x00, 0x21, 0xff, 0xf7,
+0xf5, 0xfe, 0x01, 0x20, 0x04, 0xb0, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00,
+0xe8, 0x0e, 0x00, 0x80, 0x00, 0xb5, 0xff, 0xf7, 0xc3, 0xff, 0x08, 0xbc,
+0x18, 0x47, 0x01, 0x20, 0x03, 0x49, 0xc0, 0x46, 0x08, 0x71, 0xa1, 0x21,
+0x49, 0x03, 0x88, 0x60, 0x00, 0x20, 0x70, 0x47, 0x28, 0x0f, 0x00, 0x80,
+0x00, 0x20, 0x04, 0x49, 0xc0, 0x46, 0x08, 0x71, 0xff, 0x21, 0xa1, 0x22,
+0x52, 0x03, 0x01, 0x31, 0x91, 0x60, 0x70, 0x47, 0x28, 0x0f, 0x00, 0x80,
+0x02, 0x20, 0xa1, 0x21, 0x49, 0x03, 0x88, 0x60, 0x00, 0x20, 0x70, 0x47,
+0x01, 0x20, 0x40, 0x02, 0xa1, 0x21, 0x49, 0x03, 0x88, 0x60, 0x00, 0x20,
+0x70, 0x47, 0xc0, 0x88, 0xc0, 0x06, 0xc0, 0x0e, 0xa1, 0x21, 0x49, 0x03,
+0x48, 0x61, 0x02, 0x49, 0xc0, 0x46, 0xc8, 0x63, 0x00, 0x20, 0x70, 0x47,
+0xe8, 0x1a, 0x00, 0x80, 0x80, 0xb5, 0x84, 0xb0, 0x08, 0x49, 0x0f, 0x6b,
+0x69, 0x46, 0xff, 0xf7, 0x71, 0xff, 0xf8, 0x06, 0xc0, 0x0e, 0x01, 0xab,
+0x58, 0x80, 0x68, 0x46, 0x00, 0x21, 0xff, 0xf7, 0xa9, 0xfe, 0x01, 0x20,
+0x04, 0xb0, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x80, 0x00, 0x14, 0x40,
+0x80, 0xb5, 0x85, 0xb0, 0x07, 0x1c, 0x69, 0x46, 0x38, 0x1c, 0xff, 0xf7,
+0x5b, 0xff, 0xf8, 0x88, 0x04, 0xa9, 0x03, 0xf0, 0xc9, 0xff, 0x01, 0xab,
+0x58, 0x80, 0x01, 0xa8, 0x40, 0x88, 0x00, 0x28, 0x0f, 0xd0, 0x01, 0xa8,
+0x40, 0x88, 0x80, 0x08, 0x03, 0x38, 0x80, 0x08, 0x01, 0x30, 0x04, 0x3b,
+0x58, 0x70, 0x04, 0x98, 0x01, 0x68, 0xc0, 0x46, 0x02, 0x91, 0x40, 0x68,
+0xc0, 0x46, 0x03, 0x90, 0x05, 0xe0, 0x00, 0xa8, 0x00, 0x78, 0x40, 0x23,
+0x18, 0x43, 0x00, 0xab, 0x18, 0x70, 0x04, 0x98, 0xc1, 0x1d, 0x01, 0x31,
+0x68, 0x46, 0xff, 0xf7, 0x75, 0xfe, 0x01, 0x20, 0x05, 0xb0, 0x80, 0xbc,
+0x08, 0xbc, 0x18, 0x47, 0x90, 0xb5, 0x84, 0xb0, 0x14, 0x4f, 0x39, 0x7b,
+0x00, 0x29, 0x20, 0xd1, 0xf9, 0x1d, 0xff, 0x31, 0x3a, 0x31, 0x49, 0x78,
+0x00, 0x29, 0x1a, 0xd1, 0x10, 0x49, 0x05, 0x22, 0x00, 0x92, 0x08, 0x22,
+0x00, 0xab, 0x5a, 0x80, 0x98, 0x80, 0x06, 0x20, 0x00, 0xab, 0x58, 0x70,
+0x00, 0x24, 0xdc, 0x80, 0x08, 0x68, 0xc0, 0x46, 0x02, 0x90, 0x48, 0x68,
+0xc0, 0x46, 0x03, 0x90, 0x01, 0x20, 0x38, 0x73, 0x68, 0x46, 0x08, 0x31,
+0xff, 0xf7, 0x4c, 0xfe, 0x00, 0x28, 0x00, 0xd0, 0x3c, 0x73, 0x04, 0xb0,
+0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x28, 0x05, 0x00, 0x80,
+0xa4, 0x2a, 0x00, 0x80, 0x90, 0xb5, 0x84, 0xb0, 0x07, 0x1c, 0x69, 0x46,
+0x38, 0x1c, 0xff, 0xf7, 0xf9, 0xfe, 0xba, 0x68, 0x0d, 0x4c, 0x0e, 0x48,
+0x00, 0x2a, 0x05, 0xd1, 0x0d, 0x49, 0xff, 0xf7, 0xe4, 0xfc, 0x00, 0x28,
+0x0c, 0xda, 0x05, 0xe0, 0xb9, 0x88, 0x0b, 0x4b, 0xff, 0xf7, 0xdf, 0xfc,
+0x00, 0x28, 0x05, 0xda, 0x01, 0xab, 0x5c, 0x80, 0x68, 0x46, 0x00, 0x21,
+0xff, 0xf7, 0x22, 0xfe, 0x00, 0x20, 0x04, 0xb0,
+0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
+0x0d, 0x76, 0x21, 0x40, 0xc1, 0xbd, 0x21, 0x40, 0x59, 0xbd, 0x21, 0x40,
+0x00, 0xb5, 0xc0, 0x88, 0x03, 0xf0, 0x2e, 0xff, 0x00, 0x20, 0x08, 0xbc,
+0x18, 0x47, 0x00, 0xb5, 0xff, 0xf7, 0xe2, 0xfe, 0x08, 0xbc, 0x18, 0x47,
+0x00, 0xb5, 0xff, 0xf7, 0xdd, 0xfe, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5,
+0x01, 0x1c, 0x02, 0x20, 0x00, 0xf0, 0x02, 0xf8, 0x08, 0xbc, 0x18, 0x47,
+0xb0, 0xb5, 0xc6, 0xb0, 0x07, 0x1c, 0x08, 0x1c, 0x69, 0x46, 0xff, 0xf7,
+0xb5, 0xfe, 0x21, 0x48, 0xff, 0xf7, 0xa4, 0xfc, 0x04, 0x1c, 0x20, 0x4a,
+0x00, 0x21, 0x38, 0x1c, 0xff, 0xf7, 0xa0, 0xfc, 0x00, 0x28, 0x27, 0xd0,
+0x04, 0xa9, 0x1d, 0x4a, 0x38, 0x1c, 0xff, 0xf7, 0x99, 0xfc, 0x04, 0xa8,
+0x00, 0x23, 0x01, 0x2f, 0x06, 0xd1, 0x0c, 0xaa, 0x02, 0x32, 0x00, 0x21,
+0x13, 0x60, 0x01, 0x31, 0x10, 0x29, 0xfb, 0xd3, 0x01, 0x68, 0x04, 0x29,
+0x04, 0xd9, 0x89, 0x08, 0x03, 0x39, 0x89, 0x08, 0x01, 0x31, 0x00, 0xe0,
+0x19, 0x1c, 0x00, 0xab, 0x59, 0x70, 0x06, 0xa9, 0x09, 0x78, 0xc0, 0x46,
+0xd9, 0x80, 0x00, 0x68, 0xc0, 0x46, 0x02, 0x90, 0x07, 0x98, 0xc0, 0x46,
+0x03, 0x90, 0x04, 0x33, 0x08, 0xad, 0x02, 0xe0, 0x45, 0x20, 0x00, 0xab,
+0x18, 0x70, 0x09, 0x49, 0x20, 0x1c, 0xff, 0xf7, 0x6e, 0xfc, 0x68, 0x46,
+0x29, 0x1c, 0xff, 0xf7, 0xb7, 0xfd, 0x01, 0x20, 0x46, 0xb0, 0xb0, 0xbc,
+0x08, 0xbc, 0x18, 0x47, 0x24, 0x02, 0xff, 0xff, 0x59, 0xb1, 0x21, 0x40,
+0x9d, 0xaf, 0x21, 0x40, 0x3c, 0x02, 0xff, 0xff, 0x00, 0xb5, 0x01, 0x1c,
+0x02, 0x20, 0x00, 0xf0, 0x10, 0xf8, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5,
+0x01, 0x1c, 0x01, 0x20, 0xff, 0xf7, 0xa2, 0xff, 0x08, 0xbc, 0x18, 0x47,
+0x00, 0xb5, 0x01, 0x1c, 0x01, 0x20, 0x00, 0xf0, 0x02, 0xf8, 0x08, 0xbc,
+0x18, 0x47, 0xf0, 0xb5, 0xc7, 0xb0, 0x04, 0x1c, 0x0f, 0x1c, 0x38, 0x1c,
+0x01, 0xa9, 0xff, 0xf7, 0x4d, 0xfe, 0x21, 0x48, 0xff, 0xf7, 0x3c, 0xfc,
+0x00, 0x90, 0x78, 0x78, 0x00, 0x01, 0xba, 0x68, 0x04, 0x30, 0xfc, 0x2a,
+0x25, 0xd8, 0xff, 0x23, 0x09, 0x33, 0x98, 0x42, 0x21, 0xd8, 0x19, 0x2c,
+0x1f, 0xd8, 0xfd, 0x88, 0xf8, 0x68, 0xc0, 0x46, 0x05, 0x90, 0xf9, 0x1d,
+0x09, 0x31, 0x06, 0xab, 0x00, 0x20, 0x7e, 0x78, 0x00, 0x2e, 0x0d, 0xdd,
+0x40, 0xc9, 0x40, 0xc3, 0x40, 0xc9, 0x40, 0xc3, 0x40, 0xc9, 0x40, 0xc3,
+0x40, 0xc9, 0x40, 0xc3, 0x01, 0x30, 0x00, 0x04, 0x00, 0x0c, 0x7e, 0x78,
+0x86, 0x42, 0xf1, 0xdc, 0x20, 0x1c, 0x05, 0xa9, 0x2b, 0x1c, 0xff, 0xf7,
+0x21, 0xfc, 0x00, 0x28, 0x05, 0xd0, 0x01, 0xa8, 0x00, 0x78, 0x40, 0x23,
+0x18, 0x43, 0x01, 0xab, 0x18, 0x70, 0x07, 0x49, 0x00, 0x98, 0xff, 0xf7,
+0x06, 0xfc, 0x00, 0x21, 0x01, 0xa8, 0xff, 0xf7, 0x4f, 0xfd, 0x01, 0x20,
+0x47, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x24, 0x02, 0xff, 0xff,
+0x3c, 0x02, 0xff, 0xff, 0x00, 0xb5, 0xff, 0xf7, 0x1b, 0xfe, 0x08, 0xbc,
+0x18, 0x47, 0xf0, 0xb5, 0xc6, 0xb0, 0x07, 0x1c, 0xfc, 0x88, 0x25, 0x4d,
+0x68, 0x68, 0x01, 0x30, 0x69, 0x46, 0x68, 0x60, 0x38, 0x1c, 0xff, 0xf7,
+0xf5, 0xfd, 0x10, 0x2c, 0x08, 0xd3, 0x00, 0xa8, 0x00, 0x78, 0x40, 0x23,
+0x18, 0x43, 0x00, 0xab, 0x18, 0x70, 0x02, 0x20, 0xd8, 0x80, 0x17, 0xe0,
+0x78, 0x78, 0x82, 0x00, 0xfb, 0x1d, 0x09, 0x33, 0x00, 0x20, 0xb9, 0x68,
+0x00, 0x2a, 0x15, 0xd9, 0x40, 0xcb, 0x0f, 0x1c,
+0x01, 0x31, 0xbe, 0x42, 0x0d, 0xd0, 0x00, 0xaa, 0x12, 0x78, 0x40, 0x23,
+0x1a, 0x43, 0x00, 0xab, 0x1a, 0x70, 0x04, 0x22, 0xda, 0x80, 0x02, 0x90,
+0x03, 0x91, 0x04, 0x33, 0x68, 0x46, 0x00, 0x21, 0x15, 0xe0, 0x01, 0x30,
+0x90, 0x42, 0xe9, 0xd3, 0x00, 0xab, 0x5c, 0x70, 0x02, 0x94, 0x69, 0x68,
+0xc0, 0x46, 0x03, 0x91, 0xa2, 0x00, 0x00, 0x20, 0x10, 0x33, 0x00, 0x2a,
+0x05, 0xd9, 0x0f, 0x1c, 0x80, 0xc3, 0x01, 0x30, 0x01, 0x31, 0x90, 0x42,
+0xf9, 0xd3, 0x68, 0x46, 0x04, 0xa9, 0xff, 0xf7, 0xf7, 0xfc, 0x01, 0x20,
+0x46, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x9c, 0x03, 0x00, 0x80,
+0x90, 0xb4, 0x23, 0x48, 0x00, 0x68, 0x01, 0x21, 0x42, 0x09, 0x00, 0xd3,
+0x00, 0x21, 0x00, 0x27, 0x3a, 0x1c, 0x43, 0x0b, 0x00, 0xd2, 0x02, 0x22,
+0x11, 0x43, 0x1e, 0x4a, 0x20, 0x24, 0xd3, 0x68, 0x01, 0x2b, 0x2e, 0xd1,
+0x80, 0x0a, 0x00, 0xd2, 0x00, 0x24, 0x0c, 0x43, 0x20, 0x1c, 0x1b, 0x23,
+0xdb, 0x01, 0xd1, 0x18, 0x89, 0x8b, 0x09, 0x0b, 0x00, 0xd2, 0x04, 0x27,
+0x38, 0x43, 0xd1, 0x6f, 0x09, 0x68, 0x09, 0x0a, 0x07, 0xd2, 0xd1, 0x1d,
+0x79, 0x31, 0x09, 0x68, 0x09, 0x68, 0x09, 0x0a, 0x01, 0xd3, 0x08, 0x23,
+0x18, 0x43, 0xe3, 0x23, 0x1b, 0x01, 0xd1, 0x18, 0x89, 0x79, 0x03, 0x29,
+0x02, 0xd1, 0xff, 0x23, 0x01, 0x33, 0x18, 0x43, 0x0b, 0x49, 0x09, 0x6a,
+0x10, 0x22, 0x4b, 0x0a, 0x00, 0xd2, 0x00, 0x22, 0x10, 0x43, 0x89, 0x07,
+0x89, 0x0f, 0x89, 0x01, 0x08, 0x43, 0x90, 0xbc, 0x70, 0x47, 0x40, 0x0c,
+0x00, 0xd2, 0x00, 0x24, 0x0c, 0x43, 0x20, 0x1c, 0xec, 0xe7, 0x00, 0x00,
+0x00, 0x00, 0x10, 0x40, 0x68, 0x0e, 0x00, 0x80, 0xc0, 0x00, 0x18, 0x40,
+0xf0, 0xb5, 0x3a, 0x4c, 0x20, 0x1c, 0x04, 0xf0, 0x07, 0xfa, 0x39, 0x48,
+0xe3, 0x23, 0x1b, 0x01, 0xc7, 0x18, 0xb9, 0x79, 0x37, 0x4e, 0xc5, 0x1d,
+0x79, 0x35, 0x06, 0x29, 0x62, 0xd2, 0x02, 0xa3, 0x5b, 0x5c, 0x5b, 0x00,
+0x9f, 0x44, 0x00, 0x1c, 0x03, 0x0e, 0x1e, 0x37, 0x4e, 0x55, 0x01, 0x20,
+0xb8, 0x71, 0x00, 0x20, 0xb0, 0x60, 0xff, 0xf7, 0x95, 0xff, 0x05, 0x23,
+0x98, 0x43, 0x00, 0xf0, 0x6f, 0xf8, 0x0c, 0xe0, 0xff, 0xf7, 0x8e, 0xff,
+0xc0, 0x08, 0x06, 0xd3, 0xb0, 0x68, 0x41, 0x1c, 0xb1, 0x60, 0x0a, 0x28,
+0x03, 0xd9, 0x04, 0x20, 0x00, 0xe0, 0x02, 0x20, 0xb8, 0x71, 0x64, 0x22,
+0x20, 0x1c, 0x2b, 0xe0, 0x06, 0x1c, 0xc0, 0x6f, 0x80, 0x23, 0x01, 0x68,
+0x19, 0x43, 0x01, 0x60, 0x03, 0x20, 0xb8, 0x71, 0x20, 0x1c, 0x20, 0x4a,
+0x00, 0x21, 0x04, 0xf0, 0x99, 0xf9, 0xf0, 0x6f, 0x04, 0x23, 0x01, 0x68,
+0x99, 0x43, 0x01, 0x60, 0x28, 0x68, 0x01, 0x68, 0x19, 0x43, 0x01, 0x60,
+0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x05, 0x21, 0xb9, 0x71, 0x29, 0x68,
+0x04, 0x23, 0x0a, 0x68, 0x9a, 0x43, 0x0a, 0x60, 0xc0, 0x6f, 0x01, 0x68,
+0x19, 0x43, 0x01, 0x60, 0xff, 0xf7, 0x5a, 0xff, 0x08, 0x23, 0x18, 0x43,
+0x00, 0xf0, 0x34, 0xf8, 0x20, 0x1c, 0x10, 0x4a, 0x00, 0x21, 0x04, 0xf0,
+0x77, 0xf9, 0xe5, 0xe7, 0xff, 0xf7, 0x4e, 0xff, 0x04, 0x23, 0x18, 0x43,
+0x00, 0xf0, 0x28, 0xf8, 0xde, 0xe7, 0x00, 0x20, 0x29, 0x68, 0x60, 0x23,
+0x0a, 0x68, 0x9a, 0x43, 0x0a, 0x60, 0xff, 0xf7, 0xe3, 0xfa, 0xd5, 0xe7,
+0x06, 0x20, 0xb8, 0x71, 0xd2, 0xe7, 0x00, 0x00, 0xa9, 0x79, 0x21, 0x40,
+0x68, 0x0e, 0x00, 0x80, 0x9c, 0x03, 0x00, 0x80, 0x30, 0x75, 0x00, 0x00,
+0x10, 0x27, 0x00, 0x00, 0x00, 0xb5, 0x00, 0x20,
+0x04, 0x49, 0xc0, 0x46, 0x88, 0x71, 0x04, 0x48, 0x01, 0x22, 0x00, 0x21,
+0x04, 0xf0, 0x4e, 0xf9, 0x08, 0xbc, 0x18, 0x47, 0x98, 0x1c, 0x00, 0x80,
+0xa9, 0x79, 0x21, 0x40, 0x90, 0xb5, 0x07, 0x1c, 0x31, 0x48, 0x00, 0x68,
+0x79, 0x08, 0x03, 0xd3, 0x10, 0x23, 0x01, 0x1c, 0x99, 0x43, 0x01, 0xe0,
+0x10, 0x21, 0x01, 0x43, 0x2d, 0x4c, 0xe2, 0x68, 0x01, 0x2a, 0x05, 0xd1,
+0x22, 0x79, 0x00, 0x2a, 0x02, 0xd0, 0x01, 0x23, 0x9b, 0x02, 0x19, 0x43,
+0x81, 0x42, 0x02, 0xd0, 0x01, 0x20, 0x00, 0x05, 0x01, 0x60, 0xe0, 0x68,
+0x01, 0x28, 0x20, 0xd1, 0x1b, 0x23, 0xdb, 0x01, 0xe0, 0x18, 0x80, 0x8b,
+0xf9, 0x08, 0x04, 0xd3, 0x01, 0x23, 0xdb, 0x02, 0x01, 0x1c, 0x99, 0x43,
+0x01, 0xe0, 0x01, 0x21, 0xc9, 0x02, 0x81, 0x42, 0x02, 0xd0, 0x00, 0x20,
+0x02, 0xf0, 0x1a, 0xfb, 0x38, 0x09, 0x07, 0xd3, 0xe0, 0x6f, 0x80, 0x23,
+0x01, 0x68, 0x99, 0x43, 0x01, 0x60, 0xe0, 0x18, 0x00, 0x68, 0x00, 0xe0,
+0xe0, 0x6f, 0x80, 0x23, 0x01, 0x68, 0x19, 0x43, 0x01, 0x60, 0x15, 0x48,
+0x01, 0x6a, 0x78, 0x09, 0x03, 0xd3, 0xff, 0x20, 0x01, 0x30, 0x08, 0x43,
+0x03, 0xe0, 0xff, 0x23, 0x08, 0x1c, 0x01, 0x33, 0x98, 0x43, 0x80, 0x08,
+0x80, 0x00, 0xba, 0x09, 0x92, 0x07, 0x92, 0x0f, 0x10, 0x43, 0x88, 0x42,
+0x02, 0xd0, 0x0c, 0x49, 0xc0, 0x46, 0x08, 0x62, 0xe1, 0x68, 0x01, 0x29,
+0x08, 0xd1, 0x79, 0x0a, 0x06, 0xd3, 0xff, 0x23, 0x04, 0x33, 0x18, 0x40,
+0x03, 0x28, 0x01, 0xd1, 0xff, 0xf7, 0x8e, 0xff, 0x90, 0xbc, 0x08, 0xbc,
+0x18, 0x47, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, 0x68, 0x0e, 0x00, 0x80,
+0xc0, 0x00, 0x18, 0x40, 0xc0, 0x00, 0x18, 0x00, 0x80, 0xb5, 0xff, 0xf7,
+0xb1, 0xfe, 0x80, 0x09, 0x1b, 0xd2, 0x0f, 0x48, 0xe3, 0x23, 0x1b, 0x01,
+0xc1, 0x18, 0x4a, 0x79, 0x00, 0x2a, 0x14, 0xd1, 0x01, 0x22, 0x4a, 0x71,
+0x00, 0x27, 0x80, 0x30, 0x00, 0x68, 0x60, 0x23, 0x01, 0x68, 0x99, 0x43,
+0x01, 0x60, 0x08, 0x48, 0x06, 0xe0, 0x02, 0x20, 0x02, 0xf0, 0x8c, 0xfc,
+0x07, 0x20, 0x02, 0xf0, 0x5b, 0xfc, 0x38, 0x1c, 0xff, 0xf7, 0x36, 0xfa,
+0xf5, 0xe7, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x68, 0x0e, 0x00, 0x80,
+0xf4, 0x01, 0xff, 0xff, 0x00, 0xb5, 0x84, 0xb0, 0x69, 0x46, 0xff, 0xf7,
+0x37, 0xfc, 0xff, 0xf7, 0x85, 0xfe, 0x01, 0xab, 0x58, 0x80, 0x08, 0x48,
+0x00, 0x68, 0xc0, 0x46, 0x02, 0x90, 0x07, 0x48, 0x00, 0x6a, 0xc0, 0x46,
+0x03, 0x90, 0x68, 0x46, 0x00, 0x21, 0xff, 0xf7, 0x67, 0xfb, 0x01, 0x20,
+0x04, 0xb0, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40,
+0xc0, 0x00, 0x18, 0x40, 0x80, 0xb5, 0x84, 0xb0, 0x07, 0x1c, 0x69, 0x46,
+0x38, 0x1c, 0xff, 0xf7, 0x17, 0xfc, 0xf8, 0x88, 0xff, 0xf7, 0x42, 0xff,
+0xff, 0xf7, 0x62, 0xfe, 0x01, 0xab, 0x58, 0x80, 0x68, 0x46, 0x00, 0x21,
+0xff, 0xf7, 0x4c, 0xfb, 0x01, 0x20, 0x04, 0xb0, 0x80, 0xbc, 0x08, 0xbc,
+0x18, 0x47, 0xb0, 0xb5, 0xc6, 0xb0, 0xc7, 0x88, 0x69, 0x46, 0xff, 0xf7,
+0x01, 0xfc, 0x01, 0x24, 0x1a, 0x4b, 0x9f, 0x42, 0x0a, 0xd9, 0x00, 0xa8,
+0x00, 0x78, 0x40, 0x23, 0x18, 0x43, 0x00, 0xab, 0x18, 0x70, 0x02, 0x20,
+0xd8, 0x80, 0x68, 0x46, 0x00, 0x21, 0x20, 0xe0, 0x14, 0x48, 0xff, 0xf7,
+0xe1, 0xf9, 0x05, 0x1c, 0x13, 0x4a, 0x38, 0x1c, 0x04, 0xa9, 0xff, 0xf7,
+0xdd, 0xf9, 0x12, 0x49, 0x28, 0x1c, 0xff, 0xf7, 0xd8, 0xf9, 0x01, 0x2f,
+0x06, 0xd1, 0x0c, 0xa9, 0x00, 0x20, 0x00, 0x22,
+0x0a, 0x60, 0x01, 0x30, 0x10, 0x28, 0xfb, 0xd3, 0x10, 0x20, 0x00, 0xab,
+0x58, 0x70, 0x04, 0x98, 0xc0, 0x46, 0x02, 0x90, 0x05, 0x98, 0xc0, 0x46,
+0x03, 0x90, 0x68, 0x46, 0x06, 0xa9, 0xff, 0xf7, 0x0f, 0xfb, 0x20, 0x1c,
+0x46, 0xb0, 0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xff, 0x01, 0x00, 0x00,
+0x24, 0x02, 0xff, 0xff, 0x9d, 0xaf, 0x21, 0x40, 0x3c, 0x02, 0xff, 0xff,
0xf0, 0xb5, 0xc6, 0xb0, 0x07, 0x1c, 0x69, 0x46, 0x38, 0x1c, 0xff, 0xf7,
-0xcf, 0xfb, 0xfc, 0x88, 0x78, 0x78, 0x01, 0x25, 0x10, 0x28, 0x02, 0xd1,
-0x43, 0x01, 0x9c, 0x42, 0x09, 0xd3, 0x00, 0xa8, 0x00, 0x78, 0x40, 0x23,
-0x18, 0x43, 0x00, 0xab, 0x18, 0x70, 0x02, 0x20, 0xd8, 0x80, 0x04, 0x33,
-0x27, 0xe0, 0xb8, 0x68, 0xc0, 0x46, 0x04, 0x90, 0xf8, 0x68, 0xc0, 0x46,
-0x05, 0x90, 0x06, 0xaa, 0xfb, 0x1d, 0x09, 0x33, 0x00, 0x21, 0x78, 0x78,
-0x00, 0x28, 0x0d, 0xdd, 0x00, 0x20, 0x40, 0xcb, 0x40, 0xc2, 0x01, 0x30,
-0x00, 0x04, 0x00, 0x0c, 0x04, 0x28, 0xf8, 0xdb, 0x48, 0x1c, 0x01, 0x04,
-0x09, 0x0c, 0x78, 0x78, 0x88, 0x42, 0xf1, 0xdc, 0x0a, 0x48, 0xff, 0xf7,
-0x83, 0xf9, 0x07, 0x1c, 0x09, 0x4a, 0x20, 0x1c, 0x04, 0xa9, 0xff, 0xf7,
-0x7f, 0xf9, 0x08, 0x49, 0x38, 0x1c, 0xff, 0xf7, 0x7a, 0xf9, 0x68, 0x46,
-0x00, 0x21, 0xff, 0xf7, 0xd1, 0xfa, 0x28, 0x1c, 0x46, 0xb0, 0xf0, 0xbc,
-0x08, 0xbc, 0x18, 0x47, 0x24, 0x02, 0xff, 0xff, 0x51, 0xbf, 0x21, 0x40,
+0xbb, 0xfb, 0xfc, 0x88, 0x78, 0x78, 0x01, 0x25, 0x10, 0x28, 0x01, 0xd1,
+0x19, 0x2c, 0x09, 0xd9, 0x00, 0xa8, 0x00, 0x78, 0x40, 0x23, 0x18, 0x43,
+0x00, 0xab, 0x18, 0x70, 0x02, 0x20, 0xd8, 0x80, 0x04, 0x33, 0x27, 0xe0,
+0xb8, 0x68, 0xc0, 0x46, 0x04, 0x90, 0xf8, 0x68, 0xc0, 0x46, 0x05, 0x90,
+0x06, 0xaa, 0xfb, 0x1d, 0x09, 0x33, 0x00, 0x21, 0x78, 0x78, 0x00, 0x28,
+0x0d, 0xdd, 0x00, 0x20, 0x40, 0xcb, 0x40, 0xc2, 0x01, 0x30, 0x00, 0x04,
+0x00, 0x0c, 0x04, 0x28, 0xf8, 0xdb, 0x48, 0x1c, 0x01, 0x04, 0x09, 0x0c,
+0x78, 0x78, 0x88, 0x42, 0xf1, 0xdc, 0x0b, 0x48, 0xff, 0xf7, 0x7e, 0xf9,
+0x07, 0x1c, 0x0a, 0x4a, 0x20, 0x1c, 0x04, 0xa9, 0xff, 0xf7, 0x7a, 0xf9,
+0x08, 0x49, 0x38, 0x1c, 0xff, 0xf7, 0x75, 0xf9, 0x68, 0x46, 0x00, 0x21,
+0xff, 0xf7, 0xbe, 0xfa, 0x28, 0x1c, 0x46, 0xb0, 0xf0, 0xbc, 0x08, 0xbc,
+0x18, 0x47, 0x00, 0x00, 0x24, 0x02, 0xff, 0xff, 0xc5, 0xaf, 0x21, 0x40,
0x3c, 0x02, 0xff, 0xff, 0xf0, 0xb5, 0x84, 0xb0, 0x04, 0x1c, 0x00, 0x27,
0xe6, 0x88, 0xa2, 0x68, 0x47, 0x49, 0x08, 0x79, 0x00, 0x28, 0x08, 0xd0,
0x00, 0x2e, 0x01, 0xd0, 0x01, 0x2e, 0x01, 0xd1, 0x01, 0x27, 0x01, 0xe0,
@@ -2439,110 +2380,110 @@ const u8 typhoon_firmware_image[] = {
0x66, 0xd2, 0x02, 0xa3, 0x9b, 0x5d, 0x5b, 0x00, 0x9f, 0x44, 0x00, 0x1c,
0x03, 0x06, 0x08, 0x0c, 0x10, 0x00, 0x05, 0x80, 0x00, 0x23, 0x03, 0xe0,
0x05, 0x80, 0x05, 0xe0, 0x00, 0x23, 0x03, 0x80, 0x43, 0x80, 0x06, 0xe0,
-0x00, 0x23, 0x03, 0x80, 0x45, 0x80, 0x02, 0xe0,
-0xff, 0x23, 0x01, 0x33, 0x03, 0x80, 0xcb, 0x1d, 0x79, 0x33, 0x9e, 0x89,
-0x01, 0x23, 0x5b, 0x02, 0x9e, 0x42, 0x02, 0xdb, 0xd2, 0x07, 0xd2, 0x0f,
-0x00, 0xe0, 0x01, 0x22, 0x6d, 0x23, 0x5b, 0x01, 0xc9, 0x18, 0x89, 0x88,
-0xff, 0x23, 0xe1, 0x33, 0x99, 0x43, 0x01, 0x23, 0x19, 0x43, 0x06, 0x88,
-0xff, 0x33, 0x9e, 0x42, 0x0d, 0xd1, 0xff, 0x20, 0xe1, 0x30, 0x08, 0x43,
-0x00, 0x2a, 0x04, 0xd1, 0x01, 0x23, 0x9b, 0x02, 0x98, 0x43, 0x01, 0x1c,
-0x20, 0xe0, 0x01, 0x21, 0x89, 0x02, 0x01, 0x43, 0x1c, 0xe0, 0x01, 0x2e,
-0x0a, 0xd1, 0x40, 0x88, 0x01, 0x28, 0x04, 0xd1, 0x60, 0x23, 0x19, 0x43,
-0x00, 0x2a, 0x13, 0xd0, 0x0c, 0xe0, 0x20, 0x23, 0x19, 0x43, 0x0f, 0xe0,
-0x00, 0x2e, 0x0d, 0xd1, 0x40, 0x88, 0x01, 0x28, 0x08, 0xd1, 0xff, 0x23,
-0x81, 0x33, 0x19, 0x43, 0x00, 0x2a, 0x05, 0xd0, 0x01, 0x23, 0x9b, 0x02,
-0x19, 0x43, 0x01, 0xe0, 0x80, 0x23, 0x19, 0x43, 0x04, 0x20, 0x03, 0xf0,
-0x2d, 0xf8, 0x09, 0x21, 0x49, 0x02, 0x00, 0x20, 0x03, 0xf0, 0x28, 0xf8,
-0x00, 0x2f, 0x02, 0xd1, 0x00, 0x20, 0x12, 0xe0, 0xff, 0xe7, 0x69, 0x46,
-0x20, 0x1c, 0xff, 0xf7, 0x03, 0xfb, 0x00, 0xa8, 0x00, 0x78, 0x40, 0x23,
-0x18, 0x43, 0x00, 0xab, 0x18, 0x70, 0x02, 0x20, 0xd8, 0x80, 0x68, 0x46,
-0x00, 0x21, 0x04, 0x33, 0xff, 0xf7, 0x36, 0xfa, 0x28, 0x1c, 0x04, 0xb0,
+0x00, 0x23, 0x03, 0x80, 0x45, 0x80, 0x02, 0xe0, 0xff, 0x23, 0x01, 0x33,
+0x03, 0x80, 0xcb, 0x1d, 0x79, 0x33, 0x9e, 0x89, 0x01, 0x23, 0x5b, 0x02,
+0x9e, 0x42, 0x02, 0xdb, 0xd2, 0x07, 0xd2, 0x0f, 0x00, 0xe0, 0x01, 0x22,
+0x6d, 0x23, 0x5b, 0x01, 0xc9, 0x18, 0x89, 0x88, 0xff, 0x23, 0xe1, 0x33,
+0x99, 0x43, 0x01, 0x23, 0x19, 0x43, 0x06, 0x88, 0xff, 0x33, 0x9e, 0x42,
+0x0d, 0xd1, 0xff, 0x20, 0xe1, 0x30, 0x08, 0x43, 0x00, 0x2a, 0x04, 0xd1,
+0x01, 0x23, 0x9b, 0x02, 0x98, 0x43, 0x01, 0x1c, 0x20, 0xe0, 0x01, 0x21,
+0x89, 0x02, 0x01, 0x43, 0x1c, 0xe0, 0x01, 0x2e, 0x0a, 0xd1, 0x40, 0x88,
+0x01, 0x28, 0x04, 0xd1, 0x60, 0x23, 0x19, 0x43, 0x00, 0x2a, 0x13, 0xd0,
+0x0c, 0xe0, 0x20, 0x23, 0x19, 0x43, 0x0f, 0xe0, 0x00, 0x2e, 0x0d, 0xd1,
+0x40, 0x88, 0x01, 0x28, 0x08, 0xd1, 0xff, 0x23, 0x81, 0x33, 0x19, 0x43,
+0x00, 0x2a, 0x05, 0xd0, 0x01, 0x23, 0x9b, 0x02, 0x19, 0x43, 0x01, 0xe0,
+0x80, 0x23, 0x19, 0x43, 0x04, 0x20, 0x02, 0xf0, 0x75, 0xf9, 0x09, 0x21,
+0x49, 0x02, 0x00, 0x20, 0x02, 0xf0, 0x70, 0xf9, 0x00, 0x2f, 0x02, 0xd1,
+0x00, 0x20, 0x12, 0xe0, 0xff, 0xe7, 0x69, 0x46, 0x20, 0x1c, 0xff, 0xf7,
+0xef, 0xfa, 0x00, 0xa8, 0x00, 0x78, 0x40, 0x23, 0x18, 0x43, 0x00, 0xab,
+0x18, 0x70, 0x02, 0x20, 0xd8, 0x80, 0x68, 0x46, 0x00, 0x21, 0x04, 0x33,
+0xff, 0xf7, 0x22, 0xfa, 0x28, 0x1c, 0x04, 0xb0,
0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x68, 0x0e, 0x00, 0x80,
0x88, 0x1c, 0x00, 0x80, 0xc0, 0x88, 0x51, 0x21, 0x89, 0x03, 0x08, 0x62,
0x00, 0x20, 0x70, 0x47, 0x80, 0xb5, 0x16, 0x4f, 0xf8, 0x68, 0x01, 0x28,
0x07, 0xd1, 0x37, 0x23, 0x9b, 0x01, 0xf8, 0x18, 0x40, 0x8a, 0x80, 0x21,
0x01, 0x43, 0x1b, 0x20, 0x07, 0xe0, 0x6d, 0x23, 0x5b, 0x01, 0xf8, 0x18,
0x80, 0x8b, 0x01, 0x21, 0x49, 0x03, 0x01, 0x43, 0x10, 0x20, 0x02, 0xf0,
-0xeb, 0xff, 0x01, 0x20, 0x71, 0x23, 0x5b, 0x01, 0xf9, 0x18, 0x08, 0x80,
+0x33, 0xf9, 0x01, 0x20, 0x71, 0x23, 0x5b, 0x01, 0xf9, 0x18, 0x08, 0x80,
0x48, 0x80, 0x1b, 0x23, 0xdb, 0x01, 0xf8, 0x18, 0x80, 0x8b, 0x01, 0x23,
0x1b, 0x03, 0x98, 0x43, 0x41, 0x21, 0x09, 0x02, 0x01, 0x43, 0x00, 0x20,
-0x02, 0xf0, 0xd8, 0xff, 0x00, 0x20, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47,
+0x02, 0xf0, 0x20, 0xf9, 0x00, 0x20, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47,
0x68, 0x0e, 0x00, 0x80, 0x80, 0xb5, 0x17, 0x4f, 0xf8, 0x68, 0x01, 0x28,
0x08, 0xd1, 0x37, 0x23, 0x9b, 0x01, 0xf8, 0x18, 0x40, 0x8a, 0x80, 0x23,
0x98, 0x43, 0x01, 0x1c, 0x1b, 0x20, 0x08, 0xe0, 0x6d, 0x23, 0x5b, 0x01,
0xf8, 0x18, 0x80, 0x8b, 0x01, 0x23, 0x5b, 0x03, 0x98, 0x43, 0x01, 0x1c,
-0x10, 0x20, 0x02, 0xf0, 0xb9, 0xff, 0xff, 0x20, 0x71, 0x23, 0x5b, 0x01,
+0x10, 0x20, 0x02, 0xf0, 0x01, 0xf9, 0xff, 0x20, 0x71, 0x23, 0x5b, 0x01,
0xf9, 0x18, 0x01, 0x30, 0x08, 0x80, 0x1b, 0x23, 0xdb, 0x01, 0xf8, 0x18,
0x80, 0x8b, 0x41, 0x23, 0x1b, 0x02, 0x98, 0x43, 0x09, 0x21, 0x49, 0x02,
-0x01, 0x43, 0x00, 0x20, 0x02, 0xf0, 0xa6, 0xff, 0x00, 0x20, 0x80, 0xbc,
+0x01, 0x43, 0x00, 0x20, 0x02, 0xf0, 0xee, 0xf8, 0x00, 0x20, 0x80, 0xbc,
0x08, 0xbc, 0x18, 0x47, 0x68, 0x0e, 0x00, 0x80, 0x80, 0xb5, 0x84, 0xb0,
-0x08, 0x49, 0xcf, 0x6a, 0x69, 0x46, 0xff, 0xf7, 0x7d, 0xfa, 0xb8, 0x05,
+0x08, 0x49, 0xcf, 0x6a, 0x69, 0x46, 0xff, 0xf7, 0x69, 0xfa, 0xb8, 0x05,
0x80, 0x0d, 0x01, 0xab, 0x58, 0x80, 0x68, 0x46, 0x00, 0x21, 0xff, 0xf7,
-0xb5, 0xf9, 0x01, 0x20, 0x04, 0xb0, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47,
+0xa1, 0xf9, 0x01, 0x20, 0x04, 0xb0, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47,
0x40, 0x00, 0x14, 0x40, 0xc0, 0x88, 0x9f, 0x23, 0x18, 0x40, 0x05, 0x49,
0xc9, 0x6a, 0x1b, 0x23, 0x5b, 0x01, 0x19, 0x40, 0x08, 0x43, 0x03, 0x49,
0xc0, 0x46, 0xc8, 0x62, 0x00, 0x20, 0x70, 0x47, 0x40, 0x00, 0x14, 0x40,
-0x40, 0x00, 0x14, 0x00, 0x80, 0xb5, 0x84, 0xb0,
-0x0d, 0x49, 0x0f, 0x6a, 0x01, 0x2f, 0x01, 0xd1, 0xff, 0x03, 0x07, 0xe0,
-0x02, 0x2f, 0x01, 0xd1, 0x3f, 0x03, 0x03, 0xe0, 0x00, 0x2f, 0x01, 0xd1,
-0x01, 0x27, 0xff, 0x02, 0x69, 0x46, 0xff, 0xf7, 0x49, 0xfa, 0x01, 0xab,
-0x5f, 0x80, 0x68, 0x46, 0x00, 0x21, 0xff, 0xf7, 0x83, 0xf9, 0x01, 0x20,
-0x04, 0xb0, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x20, 0x14, 0x40,
-0xc2, 0x88, 0xa1, 0x20, 0x40, 0x03, 0x00, 0x21, 0x01, 0x23, 0x5b, 0x03,
-0x9a, 0x42, 0x01, 0xd1, 0x02, 0x22, 0x04, 0xe0, 0x01, 0x23, 0xdb, 0x03,
-0x9a, 0x42, 0x02, 0xd1, 0x01, 0x22, 0x02, 0x62, 0x00, 0xe0, 0x01, 0x62,
-0x08, 0x1c, 0x70, 0x47, 0x90, 0xb5, 0x84, 0xb0, 0x07, 0x1c, 0x02, 0xf0,
-0x57, 0xff, 0x69, 0x46, 0x04, 0x1c, 0x38, 0x1c, 0xff, 0xf7, 0x1e, 0xfa,
-0x01, 0xab, 0x5c, 0x80, 0x09, 0x4f, 0xf8, 0x6d, 0xc0, 0x46, 0x02, 0x90,
-0x68, 0x46, 0x00, 0x21, 0xff, 0xf7, 0x54, 0xf9, 0xf8, 0x6d, 0xc0, 0x07,
-0xc0, 0x0f, 0x05, 0x49, 0xc0, 0x46, 0xc8, 0x62, 0x01, 0x20, 0x04, 0xb0,
-0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0xa4, 0x2a, 0x00, 0x80,
-0x68, 0x1c, 0x00, 0x80, 0xc0, 0x88, 0x02, 0x49, 0xc0, 0x46, 0x48, 0x61,
-0x00, 0x20, 0x70, 0x47, 0x80, 0x00, 0x14, 0x00, 0x00, 0xb5, 0x84, 0xb0,
-0x69, 0x46, 0xff, 0xf7, 0xf7, 0xf9, 0x06, 0x48, 0xc0, 0x68, 0x01, 0xab,
-0x58, 0x80, 0x68, 0x46, 0x00, 0x21, 0xff, 0xf7, 0x2f, 0xf9, 0x01, 0x20,
+0x40, 0x00, 0x14, 0x00, 0x80, 0xb5, 0x84, 0xb0, 0x0d, 0x49, 0x0f, 0x6a,
+0x01, 0x2f, 0x01, 0xd1, 0xff, 0x03, 0x07, 0xe0, 0x02, 0x2f, 0x01, 0xd1,
+0x3f, 0x03, 0x03, 0xe0, 0x00, 0x2f, 0x01, 0xd1, 0x01, 0x27, 0xff, 0x02,
+0x69, 0x46, 0xff, 0xf7, 0x35, 0xfa, 0x01, 0xab, 0x5f, 0x80, 0x68, 0x46,
+0x00, 0x21, 0xff, 0xf7, 0x6f, 0xf9, 0x01, 0x20, 0x04, 0xb0, 0x80, 0xbc,
+0x08, 0xbc, 0x18, 0x47, 0x00, 0x20, 0x14, 0x40, 0xc2, 0x88, 0xa1, 0x20,
+0x40, 0x03, 0x00, 0x21, 0x01, 0x23, 0x5b, 0x03, 0x9a, 0x42, 0x01, 0xd1,
+0x02, 0x22, 0x04, 0xe0, 0x01, 0x23, 0xdb, 0x03, 0x9a, 0x42, 0x02, 0xd1,
+0x01, 0x22, 0x02, 0x62, 0x00, 0xe0, 0x01, 0x62, 0x08, 0x1c, 0x70, 0x47,
+0x90, 0xb5, 0x84, 0xb0, 0x07, 0x1c, 0x02, 0xf0, 0x9f, 0xf8, 0x69, 0x46,
+0x04, 0x1c, 0x38, 0x1c, 0xff, 0xf7, 0x0a, 0xfa, 0x01, 0xab, 0x5c, 0x80,
+0x09, 0x4f, 0xf8, 0x6d, 0xc0, 0x46, 0x02, 0x90, 0x68, 0x46, 0x00, 0x21,
+0xff, 0xf7, 0x40, 0xf9, 0xf8, 0x6d, 0xc0, 0x07, 0xc0, 0x0f, 0x05, 0x49,
+0xc0, 0x46, 0xc8, 0x62, 0x01, 0x20, 0x04, 0xb0, 0x90, 0xbc, 0x08, 0xbc,
+0x18, 0x47, 0x00, 0x00, 0xa4, 0x2a, 0x00, 0x80, 0x68, 0x1c, 0x00, 0x80,
+0xc0, 0x88, 0x02, 0x49, 0xc0, 0x46, 0x48, 0x61, 0x00, 0x20, 0x70, 0x47,
+0x80, 0x00, 0x14, 0x00, 0x00, 0xb5, 0x84, 0xb0, 0x69, 0x46, 0xff, 0xf7,
+0xe3, 0xf9, 0x06, 0x48, 0xc0, 0x68, 0x01, 0xab,
+0x58, 0x80, 0x68, 0x46, 0x00, 0x21, 0xff, 0xf7, 0x1b, 0xf9, 0x01, 0x20,
0x04, 0xb0, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x80, 0x00, 0x14, 0x40,
0xc0, 0x88, 0x02, 0x49, 0xc0, 0x46, 0xc8, 0x60, 0x00, 0x20, 0x70, 0x47,
0x80, 0x00, 0x14, 0x00, 0x80, 0xb5, 0x84, 0xb0, 0x69, 0x46, 0x87, 0x68,
-0xff, 0xf7, 0xda, 0xf9, 0x20, 0x2f, 0x07, 0xd2, 0x78, 0x00, 0x0c, 0x49,
+0xff, 0xf7, 0xc6, 0xf9, 0x20, 0x2f, 0x07, 0xd2, 0x78, 0x00, 0x0c, 0x49,
0x40, 0x18, 0x1b, 0x23, 0xdb, 0x01, 0xc0, 0x18, 0x80, 0x8b, 0x06, 0xe0,
0x00, 0xa8, 0x00, 0x78, 0x40, 0x23, 0x18, 0x43, 0x00, 0xab, 0x18, 0x70,
0x02, 0x20, 0x01, 0xab, 0x58, 0x80, 0x68, 0x46, 0x00, 0x21, 0xff, 0xf7,
-0x03, 0xf9, 0x01, 0x20, 0x04, 0xb0, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47,
+0xef, 0xf8, 0x01, 0x20, 0x04, 0xb0, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47,
0x68, 0x0e, 0x00, 0x80, 0x00, 0xb5, 0x84, 0xb0, 0xc1, 0x88, 0x82, 0x68,
-0x20, 0x2a, 0x04, 0xd2, 0x10, 0x1c, 0x02, 0xf0, 0xcf, 0xfe, 0x00, 0x20,
-0x10, 0xe0, 0x69, 0x46, 0xff, 0xf7, 0xae, 0xf9, 0x00, 0xa8, 0x00, 0x78,
+0x20, 0x2a, 0x04, 0xd2, 0x10, 0x1c, 0x02, 0xf0, 0x17, 0xf8, 0x00, 0x20,
+0x10, 0xe0, 0x69, 0x46, 0xff, 0xf7, 0x9a, 0xf9, 0x00, 0xa8, 0x00, 0x78,
0x40, 0x23, 0x18, 0x43, 0x00, 0xab, 0x18, 0x70, 0x02, 0x20, 0xd8, 0x80,
-0x68, 0x46, 0x00, 0x21, 0x04, 0x33, 0xff, 0xf7, 0xe1, 0xf8, 0x01, 0x20,
+0x68, 0x46, 0x00, 0x21, 0x04, 0x33, 0xff, 0xf7, 0xcd, 0xf8, 0x01, 0x20,
0x04, 0xb0, 0x08, 0xbc, 0x18, 0x47, 0x90, 0xb5, 0x84, 0xb0, 0xc7, 0x88,
-0x69, 0x46, 0xff, 0xf7, 0x97, 0xf9, 0x10, 0x48, 0xfe, 0xf7, 0x78, 0xff,
-0x02, 0x20, 0x39, 0x1c, 0x03, 0xf0, 0x3c, 0xfe, 0x00, 0x28, 0x06, 0xd0,
-0x02, 0x20, 0x39, 0x1c, 0x03, 0xf0, 0x8c, 0xfd, 0x01, 0xab, 0x58, 0x80,
+0x69, 0x46, 0xff, 0xf7, 0x83, 0xf9, 0x10, 0x48, 0xfe, 0xf7, 0x72, 0xff,
+0x02, 0x20, 0x39, 0x1c, 0x02, 0xf0, 0xf2, 0xff, 0x00, 0x28, 0x06, 0xd0,
+0x02, 0x20, 0x39, 0x1c, 0x02, 0xf0, 0x36, 0xff, 0x01, 0xab, 0x58, 0x80,
0x02, 0xe0, 0x45, 0x20, 0x00, 0xab, 0x18, 0x70, 0x07, 0x49, 0x20, 0x1c,
-0xfe, 0xf7, 0x65, 0xff, 0x68, 0x46, 0x00, 0x21, 0xff, 0xf7, 0xbc, 0xf8,
+0xfe, 0xf7, 0x5f, 0xff, 0x68, 0x46, 0x00, 0x21, 0xff, 0xf7, 0xa8, 0xf8,
0x01, 0x20, 0x04, 0xb0, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00,
0x24, 0x02, 0xff, 0xff, 0x3c, 0x02, 0xff, 0xff, 0xb0, 0xb5, 0x84, 0xb0,
-0xc7, 0x88, 0x69, 0x46, 0x84, 0x68, 0xff, 0xf7, 0x6b, 0xf9, 0x10, 0x48,
-0xfe, 0xf7, 0x4c, 0xff, 0x0f, 0x4a, 0x02, 0x20, 0x39, 0x1c, 0xfe, 0xf7,
-0x49, 0xff, 0x00, 0x28, 0x06, 0xd0, 0x0d, 0x4b, 0x02, 0x20, 0x39, 0x1c,
-0x22, 0x1c, 0xfe, 0xf7, 0x42, 0xff, 0x02, 0xe0,
-0x45, 0x20, 0x00, 0xab, 0x18, 0x70, 0x09, 0x49, 0x28, 0x1c, 0xfe, 0xf7,
-0x38, 0xff, 0x68, 0x46, 0x00, 0x21, 0xff, 0xf7, 0x8f, 0xf8, 0x01, 0x20,
-0x04, 0xb0, 0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x24, 0x02, 0xff, 0xff,
-0xcd, 0xc0, 0x21, 0x40, 0xd9, 0xbf, 0x21, 0x40, 0x3c, 0x02, 0xff, 0xff,
-0x00, 0xb5, 0xff, 0xf7, 0x57, 0xf9, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x20,
-0x70, 0x47, 0x80, 0xb4, 0xc2, 0x88, 0x19, 0x4b, 0xa1, 0x21, 0x49, 0x03,
-0x00, 0x2a, 0x03, 0xd1, 0x18, 0x6b, 0x10, 0x23, 0x98, 0x43, 0x04, 0xe0,
-0x01, 0x2a, 0x04, 0xd1, 0x18, 0x6b, 0x10, 0x23, 0x18, 0x43, 0x48, 0x61,
-0x1f, 0xe0, 0x02, 0x2a, 0x1d, 0xd1, 0xc2, 0x68, 0x87, 0x68, 0x00, 0x20,
-0x3b, 0x1c, 0xc3, 0x40, 0xdb, 0x07, 0xdb, 0x0f, 0x9b, 0x02, 0x03, 0x43,
-0x0b, 0x61, 0x01, 0x30, 0x00, 0x04, 0x00, 0x0c, 0x20, 0x28, 0xf3, 0xdb,
-0x00, 0x20, 0x13, 0x1c, 0xc3, 0x40, 0xdb, 0x07, 0xdb, 0x0f, 0x9b, 0x02,
-0xc7, 0x1d, 0x19, 0x37, 0x3b, 0x43, 0x0b, 0x61, 0x01, 0x30, 0x00, 0x04,
-0x00, 0x0c, 0x20, 0x28, 0xf1, 0xdb, 0x00, 0x20, 0x80, 0xbc, 0x70, 0x47,
-0x80, 0x00, 0x14, 0x40, 0x80, 0xb4, 0xc2, 0x88, 0x81, 0x68, 0x10, 0x02,
-0x12, 0x0a, 0x10, 0x43, 0x02, 0x04, 0x12, 0x0c, 0x0c, 0x48, 0xc0, 0x46,
-0x02, 0x60, 0x0c, 0x4b, 0xc0, 0x46, 0x1a, 0x80, 0x0a, 0x0c, 0x17, 0x02,
+0xc7, 0x88, 0x69, 0x46, 0x84, 0x68, 0xff, 0xf7, 0x57, 0xf9, 0x10, 0x48,
+0xfe, 0xf7, 0x46, 0xff, 0x0f, 0x4a, 0x02, 0x20, 0x39, 0x1c, 0xfe, 0xf7,
+0x43, 0xff, 0x00, 0x28, 0x06, 0xd0, 0x0d, 0x4b, 0x02, 0x20, 0x39, 0x1c,
+0x22, 0x1c, 0xfe, 0xf7, 0x3c, 0xff, 0x02, 0xe0, 0x45, 0x20, 0x00, 0xab,
+0x18, 0x70, 0x09, 0x49, 0x28, 0x1c, 0xfe, 0xf7, 0x32, 0xff, 0x68, 0x46,
+0x00, 0x21, 0xff, 0xf7, 0x7b, 0xf8, 0x01, 0x20, 0x04, 0xb0, 0xb0, 0xbc,
+0x08, 0xbc, 0x18, 0x47, 0x24, 0x02, 0xff, 0xff, 0x59, 0xb1, 0x21, 0x40,
+0x59, 0xb0, 0x21, 0x40, 0x3c, 0x02, 0xff, 0xff, 0x00, 0xb5, 0xff, 0xf7,
+0x43, 0xf9, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x20, 0x70, 0x47, 0x80, 0xb4,
+0xc2, 0x88, 0x19, 0x4b, 0xa1, 0x21, 0x49, 0x03, 0x00, 0x2a, 0x03, 0xd1,
+0x18, 0x6b, 0x10, 0x23, 0x98, 0x43, 0x04, 0xe0, 0x01, 0x2a, 0x04, 0xd1,
+0x18, 0x6b, 0x10, 0x23, 0x18, 0x43, 0x48, 0x61, 0x1f, 0xe0, 0x02, 0x2a,
+0x1d, 0xd1, 0xc2, 0x68, 0x87, 0x68, 0x00, 0x20, 0x3b, 0x1c, 0xc3, 0x40,
+0xdb, 0x07, 0xdb, 0x0f, 0x9b, 0x02, 0x03, 0x43, 0x0b, 0x61, 0x01, 0x30,
+0x00, 0x04, 0x00, 0x0c, 0x20, 0x28, 0xf3, 0xdb, 0x00, 0x20, 0x13, 0x1c,
+0xc3, 0x40, 0xdb, 0x07, 0xdb, 0x0f, 0x9b, 0x02, 0xc7, 0x1d, 0x19, 0x37,
+0x3b, 0x43, 0x0b, 0x61, 0x01, 0x30, 0x00, 0x04, 0x00, 0x0c, 0x20, 0x28,
+0xf1, 0xdb, 0x00, 0x20, 0x80, 0xbc, 0x70, 0x47, 0x80, 0x00, 0x14, 0x40,
+0x80, 0xb4, 0xc2, 0x88, 0x81, 0x68, 0x10, 0x02, 0x12, 0x0a, 0x10, 0x43,
+0x02, 0x04, 0x12, 0x0c, 0x0c, 0x48, 0xc0, 0x46, 0x02, 0x60, 0x0c, 0x4b,
+0xc0, 0x46, 0x1a, 0x80, 0x0a, 0x0c, 0x17, 0x02,
0x12, 0x12, 0x3a, 0x43, 0x12, 0x04, 0x12, 0x0c, 0x42, 0x60, 0x5a, 0x80,
0x09, 0x04, 0x09, 0x0c, 0x0a, 0x02, 0x09, 0x0a, 0x11, 0x43, 0x09, 0x04,
0x09, 0x0c, 0x81, 0x60, 0x99, 0x80, 0x00, 0x20, 0x80, 0xbc, 0x70, 0x47,
@@ -2551,8 +2492,8 @@ const u8 typhoon_firmware_image[] = {
0x13, 0x43, 0x4a, 0x68, 0x12, 0x04, 0x12, 0x0c, 0x1f, 0x1c, 0x13, 0x02,
0x12, 0x12, 0x13, 0x43, 0x89, 0x68, 0x09, 0x04, 0x09, 0x0c, 0x0a, 0x02,
0x09, 0x12, 0x11, 0x43, 0x0c, 0x04, 0x24, 0x0c, 0x69, 0x46, 0x1d, 0x1c,
-0xff, 0xf7, 0xc2, 0xf8, 0x01, 0xab, 0x5f, 0x80, 0x28, 0x04, 0x20, 0x43,
-0x02, 0x90, 0x68, 0x46, 0x00, 0x21, 0xfe, 0xf7, 0xf9, 0xff, 0x01, 0x20,
+0xff, 0xf7, 0xae, 0xf8, 0x01, 0xab, 0x5f, 0x80, 0x28, 0x04, 0x20, 0x43,
+0x02, 0x90, 0x68, 0x46, 0x00, 0x21, 0xfe, 0xf7, 0xe5, 0xff, 0x01, 0x20,
0x04, 0xb0, 0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x40, 0x00, 0x14, 0x40,
0xc1, 0x88, 0x82, 0x68, 0x08, 0x02, 0x09, 0x0a, 0x08, 0x43, 0x00, 0x04,
0x00, 0x0c, 0x0a, 0x49, 0xc0, 0x46, 0xc8, 0x60, 0x10, 0x0c, 0x03, 0x02,
@@ -2566,415 +2507,126 @@ const u8 typhoon_firmware_image[] = {
0x00, 0x93, 0x84, 0x88, 0x01, 0xab, 0x1c, 0x80, 0x00, 0x24, 0x04, 0x3b,
0x5c, 0x70, 0x40, 0x88, 0x00, 0xab, 0x58, 0x80, 0xd9, 0x80, 0x10, 0x04,
0x38, 0x43, 0x02, 0x90, 0x03, 0x94, 0x68, 0x46, 0x00, 0x21, 0xfe, 0xf7,
-0xa9, 0xff, 0x01, 0x20, 0x04, 0xb0, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47,
+0x95, 0xff, 0x01, 0x20, 0x04, 0xb0, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47,
0x40, 0x00, 0x14, 0x40, 0x00, 0xb5, 0x84, 0xb0, 0x0b, 0x49, 0x8a, 0x6a,
-0x05, 0x21, 0x00, 0x91, 0x81, 0x88, 0x01, 0xab,
-0x19, 0x80, 0x00, 0x21, 0x04, 0x3b, 0x59, 0x70, 0x40, 0x88, 0x00, 0xab,
-0x58, 0x80, 0xda, 0x80, 0x02, 0x91, 0x03, 0x91, 0x68, 0x46, 0xfe, 0xf7,
-0x8d, 0xff, 0x01, 0x20, 0x04, 0xb0, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00,
-0xc0, 0x00, 0x14, 0x40, 0xc0, 0x88, 0x02, 0x49, 0xc0, 0x46, 0x88, 0x62,
-0x00, 0x20, 0x70, 0x47, 0xc0, 0x00, 0x14, 0x00, 0x00, 0xb5, 0x84, 0xb0,
-0x0b, 0x49, 0x0a, 0x6a, 0x05, 0x21, 0x00, 0x91, 0x81, 0x88, 0x01, 0xab,
-0x19, 0x80, 0x00, 0x21, 0x04, 0x3b, 0x59, 0x70, 0x40, 0x88, 0x00, 0xab,
-0x58, 0x80, 0xda, 0x80, 0x02, 0x91, 0x03, 0x91, 0x68, 0x46, 0xfe, 0xf7,
-0x69, 0xff, 0x01, 0x20, 0x04, 0xb0, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00,
-0xc0, 0x00, 0x14, 0x40, 0xc0, 0x88, 0x02, 0x49, 0xc0, 0x46, 0x08, 0x62,
-0x00, 0x20, 0x70, 0x47, 0xc0, 0x00, 0x14, 0x00, 0x00, 0xb5, 0xc0, 0x88,
-0x02, 0x49, 0xfe, 0xf7, 0xfa, 0xfd, 0x00, 0x20, 0x08, 0xbc, 0x18, 0x47,
-0x75, 0x02, 0xff, 0xff, 0x00, 0xb5, 0x84, 0xb0, 0x69, 0x46, 0xff, 0xf7,
-0x0b, 0xf8, 0x06, 0x48, 0x00, 0x6b, 0x01, 0xab, 0x58, 0x80, 0x68, 0x46,
-0x00, 0x21, 0xfe, 0xf7, 0x43, 0xff, 0x01, 0x20, 0x04, 0xb0, 0x08, 0xbc,
-0x18, 0x47, 0x00, 0x00, 0x68, 0x0e, 0x00, 0x80, 0x00, 0xb5, 0xff, 0xf7,
-0x11, 0xf8, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0xff, 0xf7, 0x0c, 0xf8,
-0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0xff, 0xf7, 0x07, 0xf8, 0x08, 0xbc,
-0x18, 0x47, 0x80, 0xb5, 0x07, 0x1c, 0x10, 0x48, 0xfe, 0xf7, 0xcc, 0xfd,
+0x05, 0x21, 0x00, 0x91, 0x81, 0x88, 0x01, 0xab, 0x19, 0x80, 0x00, 0x21,
+0x04, 0x3b, 0x59, 0x70, 0x40, 0x88, 0x00, 0xab, 0x58, 0x80, 0xda, 0x80,
+0x02, 0x91, 0x03, 0x91, 0x68, 0x46, 0xfe, 0xf7, 0x79, 0xff, 0x01, 0x20,
+0x04, 0xb0, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0xc0, 0x00, 0x14, 0x40,
+0xc0, 0x88, 0x02, 0x49, 0xc0, 0x46, 0x88, 0x62, 0x00, 0x20, 0x70, 0x47,
+0xc0, 0x00, 0x14, 0x00, 0x00, 0xb5, 0x84, 0xb0, 0x0b, 0x49, 0x0a, 0x6a,
+0x05, 0x21, 0x00, 0x91, 0x81, 0x88, 0x01, 0xab, 0x19, 0x80, 0x00, 0x21,
+0x04, 0x3b, 0x59, 0x70, 0x40, 0x88, 0x00, 0xab, 0x58, 0x80, 0xda, 0x80,
+0x02, 0x91, 0x03, 0x91, 0x68, 0x46, 0xfe, 0xf7, 0x55, 0xff, 0x01, 0x20,
+0x04, 0xb0, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0xc0, 0x00, 0x14, 0x40,
+0xc0, 0x88, 0x02, 0x49, 0xc0, 0x46, 0x08, 0x62, 0x00, 0x20, 0x70, 0x47,
+0xc0, 0x00, 0x14, 0x00, 0x00, 0xb5, 0xc0, 0x88, 0x02, 0x49, 0xfe, 0xf7,
+0xf4, 0xfd, 0x00, 0x20, 0x08, 0xbc, 0x18, 0x47, 0x75, 0x02, 0xff, 0xff,
+0x00, 0xb5, 0x84, 0xb0, 0x69, 0x46, 0xfe, 0xf7, 0xf7, 0xff, 0x06, 0x48,
+0x00, 0x6b, 0x01, 0xab, 0x58, 0x80, 0x68, 0x46, 0x00, 0x21, 0xfe, 0xf7,
+0x2f, 0xff, 0x01, 0x20, 0x04, 0xb0, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00,
+0x68, 0x0e, 0x00, 0x80, 0x00, 0xb5, 0xfe, 0xf7, 0xfd, 0xff, 0x08, 0xbc,
+0x18, 0x47, 0x00, 0xb5, 0xfe, 0xf7, 0xf8, 0xff,
+0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0xfe, 0xf7, 0xf3, 0xff, 0x08, 0xbc,
+0x18, 0x47, 0x80, 0xb5, 0x07, 0x1c, 0x10, 0x48, 0xfe, 0xf7, 0xc6, 0xfd,
0x01, 0x20, 0x40, 0x02, 0xa1, 0x21, 0x49, 0x03, 0x88, 0x60, 0x00, 0x21,
0x0c, 0x48, 0xc0, 0x46, 0x01, 0x71, 0x0c, 0x48, 0x02, 0x68, 0x52, 0x0c,
0x05, 0xd2, 0x02, 0x68, 0x12, 0x0c, 0x06, 0xd1, 0x00, 0x68, 0x80, 0x0a,
0x03, 0xd3, 0x08, 0x48, 0xc0, 0x46, 0xc7, 0x60, 0x02, 0xe0, 0x07, 0x48,
0xc0, 0x46, 0x07, 0x64, 0x08, 0x1c, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47,
-0x21, 0xa5, 0x21, 0x40, 0x28, 0x0f, 0x00, 0x80, 0x00, 0x00, 0x10, 0x40,
+0xd5, 0x94, 0x21, 0x40, 0x28, 0x0f, 0x00, 0x80, 0x00, 0x00, 0x10, 0x40,
0x40, 0x01, 0x18, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0xb5, 0x01, 0x20,
0x03, 0x49, 0xc0, 0x46, 0x08, 0x72, 0x12, 0x20, 0xff, 0xf7, 0xcb, 0xff,
0x08, 0xbc, 0x18, 0x47, 0x88, 0x1c, 0x00, 0x80, 0x00, 0xb5, 0x01, 0x20,
0x03, 0x49, 0xc0, 0x46, 0x48, 0x72, 0x15, 0x20, 0xff, 0xf7, 0xbf, 0xff,
-0x08, 0xbc, 0x18, 0x47, 0x88, 0x1c, 0x00, 0x80, 0x00, 0xb5, 0x02, 0xf0,
-0xf3, 0xfe, 0x01, 0x20, 0x08, 0xbc, 0x18, 0x47, 0x80, 0xb5, 0x84, 0xb0,
-0x07, 0x1c, 0xf8, 0x88, 0x02, 0xf0, 0xf8, 0xff, 0x00, 0x28, 0x0c, 0xd1,
-0x69, 0x46, 0x38, 0x1c, 0xfe, 0xf7, 0x96, 0xff, 0x06, 0x48, 0x01, 0xab,
-0x58, 0x80, 0x68, 0x46, 0x00, 0x21, 0xfe, 0xf7, 0xcf, 0xfe, 0x01, 0x20,
+0x08, 0xbc, 0x18, 0x47, 0x88, 0x1c, 0x00, 0x80, 0x00, 0xb5, 0x01, 0xf0,
+0xf9, 0xff, 0x01, 0x20, 0x08, 0xbc, 0x18, 0x47, 0x80, 0xb5, 0x84, 0xb0,
+0x07, 0x1c, 0xf8, 0x88, 0x02, 0xf0, 0xfe, 0xf8, 0x00, 0x28, 0x0c, 0xd1,
+0x69, 0x46, 0x38, 0x1c, 0xfe, 0xf7, 0x82, 0xff, 0x06, 0x48, 0x01, 0xab,
+0x58, 0x80, 0x68, 0x46, 0x00, 0x21, 0xfe, 0xf7, 0xbb, 0xfe, 0x01, 0x20,
0x00, 0xe0, 0x00, 0x20, 0x04, 0xb0, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47,
-0xff, 0xff, 0x00, 0x00, 0x00, 0xb5, 0x84, 0xb0, 0x69, 0x46, 0xfe, 0xf7,
-0x81, 0xff, 0x04, 0xf0, 0x47, 0xfa, 0x01, 0xab, 0x58, 0x80, 0x09, 0x48,
-0x81, 0x89, 0x09, 0x04, 0xc2, 0x89, 0x11, 0x43, 0x02, 0x91, 0x81, 0x88,
-0x09, 0x04, 0xc0, 0x88, 0x08, 0x43, 0x03, 0x90, 0x68, 0x46, 0x00, 0x21,
-0xfe, 0xf7, 0xae, 0xfe, 0x01, 0x20, 0x04, 0xb0, 0x08, 0xbc, 0x18, 0x47,
-0x4c, 0x2a, 0x00, 0x80, 0x00, 0xb5, 0xfe, 0xf7, 0x7d, 0xff, 0x08, 0xbc,
-0x18, 0x47, 0x00, 0xb5, 0xfe, 0xf7, 0x78, 0xff, 0x08, 0xbc, 0x18, 0x47,
-0x00, 0xb5, 0xfe, 0xf7, 0x73, 0xff, 0x08, 0xbc,
-0x18, 0x47, 0x00, 0xb5, 0xfe, 0xf7, 0x6e, 0xff, 0x08, 0xbc, 0x18, 0x47,
-0x00, 0xb5, 0xfe, 0xf7, 0x69, 0xff, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5,
-0xfe, 0xf7, 0x64, 0xff, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0xfe, 0xf7,
-0x5f, 0xff, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0xfe, 0xf7, 0x5a, 0xff,
-0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0xfe, 0xf7, 0x55, 0xff, 0x08, 0xbc,
-0x18, 0x47, 0x00, 0xb5, 0xfe, 0xf7, 0x50, 0xff, 0x08, 0xbc, 0x18, 0x47,
-0x00, 0xb5, 0xfe, 0xf7, 0x4b, 0xff, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5,
-0xfe, 0xf7, 0x46, 0xff, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0x8c, 0xb0,
-0x08, 0xa9, 0xfe, 0xf7, 0x27, 0xff, 0x69, 0x46, 0x08, 0xa8, 0x04, 0xf0,
-0x75, 0xfa, 0x02, 0x20, 0x08, 0xab, 0x58, 0x70, 0x69, 0x46, 0x08, 0xa8,
-0xfe, 0xf7, 0x5c, 0xfe, 0x01, 0x20, 0x0c, 0xb0, 0x08, 0xbc, 0x18, 0x47,
-0x00, 0xb5, 0xfe, 0xf7, 0x2d, 0xff, 0x08, 0xbc, 0x18, 0x47, 0x90, 0xb5,
-0x84, 0xb0, 0x07, 0x1c, 0x69, 0x46, 0x38, 0x1c, 0xfe, 0xf7, 0x0c, 0xff,
-0xfa, 0x88, 0x12, 0x49, 0x01, 0x24, 0xc8, 0x1d, 0x89, 0x30, 0x00, 0x2a,
-0x0f, 0xd0, 0x04, 0x70, 0x44, 0x70, 0xb8, 0x68, 0x00, 0x0c, 0x80, 0x31,
-0xc8, 0x82, 0xb8, 0x68, 0xc0, 0x46, 0x08, 0x83, 0xf8, 0x68, 0x00, 0x0c,
-0x48, 0x83, 0xf8, 0x68, 0xc0, 0x46, 0x88, 0x83, 0x02, 0xe0, 0x00, 0x21,
+0xff, 0xff, 0x00, 0x00, 0x80, 0xb5, 0x84, 0xb0, 0x69, 0x46, 0xfe, 0xf7,
+0x6d, 0xff, 0x01, 0x27, 0x01, 0xab, 0x5f, 0x80, 0x09, 0x48, 0x81, 0x89,
+0x09, 0x04, 0xc2, 0x89, 0x11, 0x43, 0x02, 0x91, 0x81, 0x88, 0x09, 0x04,
+0xc0, 0x88, 0x08, 0x43, 0x03, 0x90, 0x68, 0x46, 0x00, 0x21, 0xfe, 0xf7,
+0x9b, 0xfe, 0x38, 0x1c, 0x04, 0xb0, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47,
+0x4c, 0x2a, 0x00, 0x80, 0x00, 0xb5, 0xfe, 0xf7, 0x69, 0xff, 0x08, 0xbc,
+0x18, 0x47, 0x00, 0xb5, 0xfe, 0xf7, 0x64, 0xff, 0x08, 0xbc, 0x18, 0x47,
+0x00, 0xb5, 0xfe, 0xf7, 0x5f, 0xff, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5,
+0xfe, 0xf7, 0x5a, 0xff, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0xfe, 0xf7,
+0x55, 0xff, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0xfe, 0xf7, 0x50, 0xff,
+0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0xfe, 0xf7, 0x4b, 0xff, 0x08, 0xbc,
+0x18, 0x47, 0x00, 0xb5, 0xfe, 0xf7, 0x46, 0xff, 0x08, 0xbc, 0x18, 0x47,
+0x00, 0xb5, 0xfe, 0xf7, 0x41, 0xff, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5,
+0xfe, 0xf7, 0x3c, 0xff, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0xfe, 0xf7,
+0x37, 0xff, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0xfe, 0xf7, 0x32, 0xff,
+0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0x8c, 0xb0, 0x08, 0xa9, 0xfe, 0xf7,
+0x13, 0xff, 0x69, 0x46, 0x08, 0xa8, 0x02, 0xf0, 0xa9, 0xff, 0x02, 0x20,
+0x08, 0xab, 0x58, 0x70, 0x69, 0x46, 0x08, 0xa8, 0xfe, 0xf7, 0x48, 0xfe,
+0x01, 0x20, 0x0c, 0xb0, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0xfe, 0xf7,
+0x19, 0xff, 0x08, 0xbc, 0x18, 0x47, 0x90, 0xb5, 0x84, 0xb0, 0x07, 0x1c,
+0x69, 0x46, 0x38, 0x1c, 0xfe, 0xf7, 0xf8, 0xfe, 0xfa, 0x88, 0x12, 0x49,
+0x01, 0x24, 0xc8, 0x1d, 0x89, 0x30, 0x00, 0x2a, 0x0f, 0xd0, 0x04, 0x70,
+0x44, 0x70, 0xb8, 0x68, 0x00, 0x0c, 0x80, 0x31, 0xc8, 0x82, 0xb8, 0x68,
+0xc0, 0x46, 0x08, 0x83, 0xf8, 0x68, 0x00, 0x0c, 0x48, 0x83, 0xf8, 0x68,
+0xc0, 0x46, 0x88, 0x83, 0x02, 0xe0, 0x00, 0x21,
0x01, 0x70, 0x41, 0x70, 0x06, 0x48, 0x01, 0xab, 0x58, 0x80, 0x68, 0x46,
-0x00, 0x21, 0xfe, 0xf7, 0x2b, 0xfe, 0x20, 0x1c, 0x04, 0xb0, 0x90, 0xbc,
+0x00, 0x21, 0xfe, 0xf7, 0x17, 0xfe, 0x20, 0x1c, 0x04, 0xb0, 0x90, 0xbc,
0x08, 0xbc, 0x18, 0x47, 0x68, 0x0e, 0x00, 0x80, 0xff, 0xff, 0x00, 0x00,
-0x00, 0xb5, 0xfe, 0xf7, 0xf7, 0xfe, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5,
-0xfe, 0xf7, 0xf2, 0xfe, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0xfe, 0xf7,
-0xed, 0xfe, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0xfe, 0xf7, 0xe8, 0xfe,
-0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0xfe, 0xf7, 0xe3, 0xfe, 0x08, 0xbc,
+0x00, 0xb5, 0xfe, 0xf7, 0xe3, 0xfe, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5,
+0xfe, 0xf7, 0xde, 0xfe, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0xfe, 0xf7,
+0xd9, 0xfe, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0xfe, 0xf7, 0xd4, 0xfe,
+0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0xfe, 0xf7, 0xcf, 0xfe, 0x08, 0xbc,
0x18, 0x47, 0x90, 0xb5, 0x84, 0xb0, 0x07, 0x1c, 0x69, 0x46, 0x38, 0x1c,
-0xfe, 0xf7, 0xc2, 0xfe, 0xf8, 0x88, 0x03, 0x24, 0xe4, 0x04, 0x04, 0x43,
+0xfe, 0xf7, 0xae, 0xfe, 0xf8, 0x88, 0x03, 0x24, 0xe4, 0x04, 0x04, 0x43,
0x03, 0x23, 0xdb, 0x04, 0x9c, 0x42, 0x02, 0xd3, 0x0f, 0x4b, 0x9c, 0x42,
0x06, 0xd9, 0x0f, 0x48, 0x01, 0xab, 0x58, 0x80, 0x68, 0x46, 0x00, 0x21,
-0xfe, 0xf7, 0xf0, 0xfd, 0x01, 0x20, 0x80, 0x07, 0x20, 0x43, 0x00, 0x68,
+0xfe, 0xf7, 0xdc, 0xfd, 0x01, 0x20, 0x80, 0x07, 0x20, 0x43, 0x00, 0x68,
0x00, 0x21, 0x00, 0xab, 0x59, 0x70, 0xfa, 0x88, 0xc0, 0x46, 0xda, 0x80,
-0x02, 0x90, 0x03, 0x91, 0x68, 0x46, 0x04, 0x33, 0xfe, 0xf7, 0xe0, 0xfd,
+0x02, 0x90, 0x03, 0x91, 0x68, 0x46, 0x04, 0x33, 0xfe, 0xf7, 0xcc, 0xfd,
0x01, 0x20, 0x04, 0xb0, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00,
0xe0, 0x00, 0x18, 0x00, 0xff, 0xff, 0x00, 0x00, 0x80, 0xb5, 0x84, 0xb0,
-0x07, 0x1c, 0x69, 0x46, 0x38, 0x1c, 0xfe, 0xf7, 0x8f, 0xfe, 0xf8, 0x88,
+0x07, 0x1c, 0x69, 0x46, 0x38, 0x1c, 0xfe, 0xf7, 0x7b, 0xfe, 0xf8, 0x88,
0x03, 0x23, 0xdb, 0x04, 0x18, 0x43, 0x98, 0x42, 0x02, 0xd3, 0x0a, 0x4b,
0x98, 0x42, 0x08, 0xd9, 0x09, 0x48, 0x01, 0xab, 0x58, 0x80, 0x68, 0x46,
-0x00, 0x21, 0xfe, 0xf7, 0xbf, 0xfd, 0x01, 0x20, 0x03, 0xe0, 0xb9, 0x68,
+0x00, 0x21, 0xfe, 0xf7, 0xab, 0xfd, 0x01, 0x20, 0x03, 0xe0, 0xb9, 0x68,
0xc0, 0x46, 0x01, 0x60, 0x00, 0x20, 0x04, 0xb0, 0x80, 0xbc, 0x08, 0xbc,
0x18, 0x47, 0x00, 0x00, 0xe0, 0x00, 0x18, 0x00, 0xff, 0xff, 0x00, 0x00,
-0x80, 0xb5, 0x86, 0xb0, 0x07, 0x1c, 0x04, 0xf0, 0x33, 0xf9, 0x38, 0x1c,
-0x02, 0xa9, 0xfe, 0xf7, 0x67, 0xfe, 0x01, 0x27, 0x02, 0xab, 0x5f, 0x70,
-0x00, 0x20, 0xd8, 0x80, 0x0a, 0x48, 0x41, 0x68, 0xc0, 0x46, 0x04, 0x91,
-0x81, 0x68, 0xc0, 0x46, 0x05, 0x91, 0xc1, 0x68,
+0x80, 0xb5, 0x86, 0xb0, 0x02, 0xa9, 0xfe, 0xf7, 0x57, 0xfe, 0x01, 0x27,
+0x02, 0xab, 0x5f, 0x70, 0x00, 0x20, 0xd8, 0x80, 0x0a, 0x48, 0x41, 0x68,
+0xc0, 0x46, 0x04, 0x91, 0x81, 0x68, 0xc0, 0x46, 0x05, 0x91, 0xc1, 0x68,
0xc0, 0x46, 0x00, 0x91, 0x40, 0x69, 0xc0, 0x46, 0x01, 0x90, 0x69, 0x46,
-0x02, 0xa8, 0xfe, 0xf7, 0x91, 0xfd, 0x38, 0x1c, 0x06, 0xb0, 0x80, 0xbc,
+0x02, 0xa8, 0xfe, 0xf7, 0x81, 0xfd, 0x38, 0x1c, 0x06, 0xb0, 0x80, 0xbc,
0x08, 0xbc, 0x18, 0x47, 0x68, 0x19, 0x00, 0x80, 0x00, 0xb5, 0xc1, 0x68,
-0x80, 0x68, 0xfe, 0xf7, 0x49, 0xfb, 0x00, 0x20, 0x08, 0xbc, 0x18, 0x47,
+0x80, 0x68, 0xfe, 0xf7, 0x47, 0xfb, 0x00, 0x20, 0x08, 0xbc, 0x18, 0x47,
0x00, 0x20, 0x70, 0x47, 0x90, 0xb5, 0x84, 0xb0, 0x04, 0x1c, 0x0f, 0x1c,
-0x68, 0x46, 0x50, 0x21, 0xfe, 0xf7, 0x46, 0xfe, 0x01, 0xab, 0x5c, 0x80,
-0x02, 0x97, 0x68, 0x46, 0x00, 0x21, 0xfe, 0xf7, 0x71, 0xfd, 0x04, 0xb0,
+0x68, 0x46, 0x50, 0x21, 0xfe, 0xf7, 0x36, 0xfe, 0x01, 0xab, 0x5c, 0x80,
+0x02, 0x97, 0x68, 0x46, 0x00, 0x21, 0xfe, 0xf7, 0x61, 0xfd, 0x04, 0xb0,
0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x80, 0xb5, 0x84, 0xb0, 0x07, 0x1c,
-0x68, 0x46, 0x51, 0x21, 0xfe, 0xf7, 0x34, 0xfe, 0x01, 0xab, 0x5f, 0x80,
-0x68, 0x46, 0x00, 0x21, 0xfe, 0xf7, 0x60, 0xfd, 0x04, 0xb0, 0x80, 0xbc,
+0x68, 0x46, 0x51, 0x21, 0xfe, 0xf7, 0x24, 0xfe, 0x01, 0xab, 0x5f, 0x80,
+0x68, 0x46, 0x00, 0x21, 0xfe, 0xf7, 0x50, 0xfd, 0x04, 0xb0, 0x80, 0xbc,
0x08, 0xbc, 0x18, 0x47, 0x00, 0x20, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47,
0x90, 0xb5, 0x84, 0xb0, 0x00, 0x27, 0x12, 0x49, 0x09, 0x68, 0x12, 0x4a,
0x12, 0x6b, 0x10, 0x23, 0x1a, 0x40, 0x01, 0x24, 0x00, 0x2a, 0x00, 0xd0,
0x01, 0x27, 0x8a, 0x0c, 0x03, 0xd3, 0x3a, 0x04, 0x12, 0x0c, 0x02, 0x27,
0x17, 0x43, 0xc9, 0x0c, 0x03, 0xd3, 0x39, 0x04, 0x09, 0x0c, 0x04, 0x27,
-0x0f, 0x43, 0x69, 0x46, 0xfe, 0xf7, 0xfc, 0xfd, 0x01, 0xab, 0x5f, 0x80,
-0x68, 0x46, 0x00, 0x21, 0xfe, 0xf7, 0x36, 0xfd, 0x20, 0x1c, 0x04, 0xb0,
-0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40,
-0xc0, 0x00, 0x18, 0x40, 0x00, 0xb5, 0x84, 0xb0, 0x69, 0x46, 0xfe, 0xf7,
-0xe7, 0xfd, 0x06, 0x48, 0xc0, 0x6d, 0x01, 0xab, 0x58, 0x80, 0x68, 0x46,
-0x00, 0x21, 0xfe, 0xf7, 0x1f, 0xfd, 0x01, 0x20, 0x04, 0xb0, 0x08, 0xbc,
-0x18, 0x47, 0x00, 0x00, 0xa4, 0x2a, 0x00, 0x80, 0x00, 0xb5, 0xfe, 0xf7,
-0xed, 0xfd, 0x08, 0xbc, 0x18, 0x47, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47,
+0x0f, 0x43, 0x69, 0x46, 0xfe, 0xf7, 0xec, 0xfd, 0x01, 0xab, 0x5f, 0x80,
+0x68, 0x46, 0x00, 0x21, 0xfe, 0xf7, 0x26, 0xfd, 0x20, 0x1c, 0x04, 0xb0,
+0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00,
+0x00, 0x00, 0x10, 0x40, 0xc0, 0x00, 0x18, 0x40, 0x00, 0xb5, 0x84, 0xb0,
+0x69, 0x46, 0xfe, 0xf7, 0xd7, 0xfd, 0x06, 0x48, 0xc0, 0x6d, 0x01, 0xab,
+0x58, 0x80, 0x68, 0x46, 0x00, 0x21, 0xfe, 0xf7, 0x0f, 0xfd, 0x01, 0x20,
+0x04, 0xb0, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0xa4, 0x2a, 0x00, 0x80,
+0x00, 0xb5, 0xfe, 0xf7, 0xdd, 0xfd, 0x08, 0xbc, 0x18, 0x47, 0x70, 0x47,
+0x00, 0x20, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47,
0x00, 0x20, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47,
-0x00, 0x20, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x00, 0xb5, 0xfe, 0xf7,
-0xdb, 0xfd, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x80, 0xb5, 0x85, 0xb0,
-0x01, 0xa9, 0xfe, 0xf7, 0xbb, 0xfd, 0x00, 0x20, 0x01, 0xab, 0x58, 0x70,
-0x10, 0x49, 0xc9, 0x68, 0x01, 0x27, 0x01, 0x29, 0x0a, 0xd1, 0x04, 0xf0,
-0xc7, 0xf8, 0x03, 0x90, 0x04, 0x97, 0x03, 0x98, 0x00, 0x28, 0x06, 0xd0,
-0x68, 0x46, 0x02, 0xf0, 0xe5, 0xfb, 0x04, 0xe0, 0x03, 0x97, 0x04, 0x90,
-0xf8, 0xe7, 0x00, 0x20, 0x00, 0x90, 0x02, 0xab, 0x00, 0x98, 0xc0, 0x46,
-0x58, 0x80, 0x00, 0x21, 0x01, 0xa8, 0xfe, 0xf7, 0xdb, 0xfc, 0x38, 0x1c,
+0x00, 0xb5, 0xfe, 0xf7, 0xcb, 0xfd, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00,
+0x80, 0xb5, 0x85, 0xb0, 0x01, 0xa9, 0xfe, 0xf7, 0xab, 0xfd, 0x00, 0x20,
+0x01, 0xab, 0x58, 0x70, 0x0c, 0x49, 0xc9, 0x68, 0x01, 0x27, 0x01, 0x29,
+0x02, 0xd1, 0x03, 0x97, 0x04, 0x97, 0x01, 0xe0, 0x03, 0x97, 0x04, 0x90,
+0x68, 0x46, 0x01, 0xf0, 0x33, 0xfd, 0x02, 0xab, 0x00, 0x98, 0xc0, 0x46,
+0x58, 0x80, 0x00, 0x21, 0x01, 0xa8, 0xfe, 0xf7, 0xd3, 0xfc, 0x38, 0x1c,
0x05, 0xb0, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x68, 0x0e, 0x00, 0x80,
-0x90, 0xb5, 0x84, 0xb0, 0x07, 0x1c, 0x69, 0x46, 0x38, 0x1c, 0xfe, 0xf7,
-0x8d, 0xfd, 0x00, 0x20, 0x00, 0xab, 0x58, 0x70, 0x01, 0x24, 0x20, 0x1c,
-0x12, 0x49, 0xc9, 0x68, 0x01, 0x29, 0x00, 0xd0, 0x00, 0x20, 0x00, 0x06,
-0x00, 0x0e, 0x13, 0xd0, 0xf8, 0x88, 0x0f, 0x4a, 0x90, 0x42, 0x02, 0xd0,
-0x0e, 0x4b, 0x98, 0x42, 0x08, 0xd1, 0xb9, 0x68, 0x27, 0x1c, 0x90, 0x42,
-0x00, 0xd0, 0x00, 0x27, 0x38, 0x06, 0x00, 0x0e, 0x04, 0xf0, 0x88, 0xf8,
-0x04, 0xf0, 0x84, 0xf8, 0x02, 0x90, 0x00, 0xe0, 0x02, 0x94, 0x68, 0x46,
-0x00, 0x21, 0xfe, 0xf7, 0xa7, 0xfc, 0x20, 0x1c, 0x04, 0xb0, 0x90, 0xbc,
-0x08, 0xbc, 0x18, 0x47, 0x68, 0x0e, 0x00, 0x80, 0xed, 0xfe, 0x00, 0x00,
-0xfe, 0xca, 0x00, 0x00, 0xf1, 0xb5, 0xd6, 0xb0,
-0x00, 0x20, 0x81, 0x00, 0x56, 0x9c, 0x0a, 0x19, 0x12, 0x6a, 0x6b, 0x46,
-0x5a, 0x50, 0x01, 0x30, 0x10, 0x28, 0xf6, 0xdb, 0x10, 0x20, 0x82, 0x00,
-0x11, 0x1c, 0x69, 0x44, 0x40, 0x39, 0x4b, 0x6b, 0x0f, 0x6a, 0x7b, 0x40,
-0x8f, 0x68, 0x7b, 0x40, 0x09, 0x68, 0x59, 0x40, 0x4b, 0x00, 0xc9, 0x0f,
-0x19, 0x43, 0x6b, 0x46, 0x99, 0x50, 0x01, 0x30, 0x50, 0x28, 0xec, 0xdb,
-0x56, 0x98, 0x01, 0x68, 0xc0, 0x46, 0x55, 0x91, 0x42, 0x68, 0xc0, 0x46,
-0x54, 0x92, 0x86, 0x68, 0xc0, 0x46, 0x53, 0x96, 0xc5, 0x68, 0xc0, 0x46,
-0x52, 0x95, 0x04, 0x69, 0xc0, 0x46, 0x51, 0x94, 0x48, 0x01, 0xcb, 0x0e,
-0x18, 0x43, 0x13, 0x1c, 0x33, 0x40, 0x07, 0x1c, 0x28, 0x1c, 0x90, 0x43,
-0x18, 0x43, 0x38, 0x18, 0x00, 0x19, 0x00, 0x9b, 0xc0, 0x18, 0xcf, 0x4b,
-0xc0, 0x18, 0x93, 0x07, 0x92, 0x08, 0x13, 0x43, 0x42, 0x01, 0x1f, 0x1c,
-0xc3, 0x0e, 0x1a, 0x43, 0x0b, 0x1c, 0x3b, 0x40, 0x14, 0x1c, 0x32, 0x1c,
-0x8a, 0x43, 0x1a, 0x43, 0xa2, 0x18, 0x52, 0x19, 0x01, 0x9b, 0xd2, 0x18,
-0xc5, 0x4b, 0xd4, 0x18, 0x8a, 0x07, 0x89, 0x08, 0x11, 0x43, 0x62, 0x01,
-0xe3, 0x0e, 0x1a, 0x43, 0x03, 0x1c, 0x0b, 0x40, 0x15, 0x1c, 0x3a, 0x1c,
-0x82, 0x43, 0x1a, 0x43, 0xaa, 0x18, 0x92, 0x19, 0x02, 0x9b, 0xd2, 0x18,
-0xbc, 0x4b, 0xd2, 0x18, 0x3b, 0x1c, 0x87, 0x07, 0x80, 0x08, 0x38, 0x43,
-0x57, 0x01, 0xd5, 0x0e, 0x3d, 0x43, 0x27, 0x1c, 0x07, 0x40, 0x0e, 0x1c,
-0xa6, 0x43, 0x37, 0x43, 0xed, 0x19, 0xeb, 0x18, 0x03, 0x9f, 0xdf, 0x19,
-0xb3, 0x4b, 0xff, 0x18, 0xa3, 0x07, 0xa4, 0x08, 0x1c, 0x43, 0x7b, 0x01,
-0xfd, 0x0e, 0x2b, 0x43, 0x15, 0x1c, 0x25, 0x40, 0x1e, 0x1c, 0x03, 0x1c,
-0x93, 0x43, 0x2b, 0x43, 0xf3, 0x18, 0x59, 0x18, 0x04, 0x9b, 0xc9, 0x18,
-0xaa, 0x4b, 0xc9, 0x18, 0x93, 0x07, 0x92, 0x08, 0x1a, 0x43, 0x4b, 0x01,
-0xcd, 0x0e, 0x1d, 0x43, 0x3e, 0x1c, 0x16, 0x40, 0x23, 0x1c, 0xbb, 0x43,
-0x33, 0x43, 0xeb, 0x18, 0x18, 0x18, 0x05, 0x9b, 0xc0, 0x18, 0xa2, 0x4b,
-0xc0, 0x18, 0xbb, 0x07, 0xbf, 0x08, 0x1f, 0x43, 0x43, 0x01, 0xc5, 0x0e,
-0x2b, 0x43, 0x0d, 0x1c, 0x3d, 0x40, 0x1e, 0x1c, 0x13, 0x1c, 0x8b, 0x43,
-0x2b, 0x43, 0xf3, 0x18, 0x1b, 0x19, 0x06, 0x9c, 0x1c, 0x19, 0x99, 0x4b,
-0xe4, 0x18, 0x8b, 0x07, 0x89, 0x08, 0x19, 0x43, 0x63, 0x01, 0xe5, 0x0e,
-0x1d, 0x43, 0x03, 0x1c, 0x0b, 0x40, 0x3e, 0x1c, 0x86, 0x43, 0x33, 0x43,
-0xeb, 0x18, 0x9a, 0x18, 0x07, 0x9b, 0xd2, 0x18, 0x90, 0x4b, 0xd2, 0x18,
-0x3b, 0x1c, 0x87, 0x07, 0x80, 0x08, 0x38, 0x43, 0x57, 0x01, 0xd5, 0x0e,
-0x2f, 0x43, 0x25, 0x1c, 0x05, 0x40, 0x3e, 0x1c, 0x0f, 0x1c, 0xa7, 0x43,
-0x2f, 0x43, 0xf5, 0x19, 0xeb, 0x18, 0x08, 0x9f, 0xdf, 0x19, 0x87, 0x4b,
-0xff, 0x18, 0xa3, 0x07, 0xa4, 0x08, 0x1c, 0x43, 0x7b, 0x01, 0xfd, 0x0e,
-0x1d, 0x43, 0x16, 0x1c, 0x26, 0x40, 0x03, 0x1c, 0x93, 0x43, 0x33, 0x43,
-0xeb, 0x18, 0x59, 0x18, 0x09, 0x9b, 0xc9, 0x18, 0x7e, 0x4b, 0xc9, 0x18,
-0x93, 0x07, 0x92, 0x08, 0x1a, 0x43, 0x4b, 0x01, 0xcd, 0x0e, 0x1d, 0x43,
-0x3b, 0x1c, 0x13, 0x40, 0x26, 0x1c, 0xbe, 0x43, 0x33, 0x43, 0xeb, 0x18,
-0x18, 0x18, 0x0a, 0x9b, 0xc0, 0x18, 0x76, 0x4b, 0xc0, 0x18, 0x23, 0x1c,
-0xbc, 0x07, 0xbf, 0x08, 0x27, 0x43, 0x44, 0x01, 0xc5, 0x0e, 0x2c, 0x43,
-0x0d, 0x1c, 0x3d, 0x40, 0x26, 0x1c, 0x14, 0x1c, 0x8c, 0x43, 0x2c, 0x43,
-0x35, 0x19, 0xeb, 0x18, 0x0b, 0x9c, 0x1c, 0x19,
-0x6c, 0x4b, 0xe4, 0x18, 0x8b, 0x07, 0x89, 0x08, 0x19, 0x43, 0x63, 0x01,
-0xe5, 0x0e, 0x1d, 0x43, 0x03, 0x1c, 0x0b, 0x40, 0x3e, 0x1c, 0x86, 0x43,
-0x33, 0x43, 0xeb, 0x18, 0x9a, 0x18, 0x0c, 0x9b, 0xd2, 0x18, 0x64, 0x4b,
-0xd2, 0x18, 0x3b, 0x1c, 0x87, 0x07, 0x80, 0x08, 0x38, 0x43, 0x57, 0x01,
-0xd5, 0x0e, 0x3d, 0x43, 0x27, 0x1c, 0x07, 0x40, 0x0e, 0x1c, 0xa6, 0x43,
-0x37, 0x43, 0xed, 0x19, 0xeb, 0x18, 0x0d, 0x9f, 0xdf, 0x19, 0x5b, 0x4b,
-0xff, 0x18, 0xa3, 0x07, 0xa4, 0x08, 0x1c, 0x43, 0x7b, 0x01, 0xfd, 0x0e,
-0x1d, 0x43, 0x13, 0x1c, 0x23, 0x40, 0x06, 0x1c, 0x96, 0x43, 0x33, 0x43,
-0xeb, 0x18, 0x59, 0x18, 0x0e, 0x9b, 0xc9, 0x18, 0x52, 0x4b, 0xc9, 0x18,
-0x93, 0x07, 0x92, 0x08, 0x1a, 0x43, 0x4b, 0x01, 0xcd, 0x0e, 0x2b, 0x43,
-0x3d, 0x1c, 0x15, 0x40, 0x1e, 0x1c, 0x23, 0x1c, 0xbb, 0x43, 0x2b, 0x43,
-0xf3, 0x18, 0x18, 0x18, 0x0f, 0x9b, 0xc0, 0x18, 0x49, 0x4b, 0xc0, 0x18,
-0x23, 0x1c, 0xbc, 0x07, 0xbf, 0x08, 0x27, 0x43, 0x10, 0x24, 0x50, 0x94,
-0x44, 0x01, 0xc5, 0x0e, 0x25, 0x43, 0x0e, 0x1c, 0x3e, 0x40, 0x14, 0x1c,
-0x8c, 0x43, 0x34, 0x43, 0x2c, 0x19, 0xe3, 0x18, 0x50, 0x9c, 0xa5, 0x00,
-0x6c, 0x46, 0x64, 0x59, 0x1c, 0x19, 0x3e, 0x4b, 0xe4, 0x18, 0x13, 0x1c,
-0x3a, 0x1c, 0x8f, 0x07, 0x89, 0x08, 0x0f, 0x43, 0x01, 0x1c, 0x20, 0x1c,
-0x50, 0x9c, 0x01, 0x34, 0x50, 0x94, 0x14, 0x2c, 0xe2, 0xdb, 0x14, 0x24,
-0x45, 0x01, 0xc6, 0x0e, 0x2e, 0x43, 0x0d, 0x1c, 0x7d, 0x40, 0x55, 0x40,
-0x75, 0x19, 0xeb, 0x18, 0xa5, 0x00, 0x6e, 0x46, 0x75, 0x59, 0x5d, 0x19,
-0x31, 0x4b, 0xed, 0x18, 0x13, 0x1c, 0x3a, 0x1c, 0x8f, 0x07, 0x89, 0x08,
-0x0f, 0x43, 0x01, 0x1c, 0x28, 0x1c, 0x01, 0x34, 0x28, 0x2c, 0xe7, 0xdb,
-0x28, 0x24, 0x50, 0x94, 0x44, 0x01, 0xc5, 0x0e, 0x25, 0x43, 0x3c, 0x1c,
-0x14, 0x43, 0x0c, 0x40, 0x3e, 0x1c, 0x16, 0x40, 0x34, 0x43, 0x2c, 0x19,
-0xe3, 0x18, 0x50, 0x9c, 0xa5, 0x00, 0x6c, 0x46, 0x64, 0x59, 0x1c, 0x19,
-0x23, 0x4b, 0xe4, 0x18, 0x13, 0x1c, 0x3a, 0x1c, 0x8f, 0x07, 0x89, 0x08,
-0x0f, 0x43, 0x01, 0x1c, 0x20, 0x1c, 0x50, 0x9c, 0x01, 0x34, 0x50, 0x94,
-0x3c, 0x2c, 0xe1, 0xdb, 0x3c, 0x24, 0x45, 0x01, 0xc6, 0x0e, 0x2e, 0x43,
-0x0d, 0x1c, 0x7d, 0x40, 0x55, 0x40, 0x75, 0x19, 0xeb, 0x18, 0xa6, 0x00,
-0x6d, 0x46, 0xad, 0x59, 0x5d, 0x19, 0x17, 0x4b, 0xed, 0x18, 0x13, 0x1c,
-0x3a, 0x1c, 0x8f, 0x07, 0x89, 0x08, 0x0f, 0x43, 0x01, 0x1c, 0x28, 0x1c,
-0x01, 0x34, 0x50, 0x2c, 0xe7, 0xdb, 0x55, 0x9c, 0x20, 0x18, 0x56, 0x9c,
-0xc0, 0x46, 0x20, 0x60, 0x54, 0x98, 0x40, 0x18, 0x56, 0x9c, 0xc0, 0x46,
-0x60, 0x60, 0x53, 0x9e, 0xf0, 0x19, 0x56, 0x9c, 0xc0, 0x46, 0xa0, 0x60,
-0x52, 0x9d, 0xa8, 0x18, 0x56, 0x9c, 0xc0, 0x46, 0xe0, 0x60, 0x51, 0x9c,
-0xe0, 0x18, 0x56, 0x9c, 0xc0, 0x46, 0x20, 0x61, 0x57, 0xb0, 0xf0, 0xbc,
-0x08, 0xbc, 0x18, 0x47, 0x99, 0x79, 0x82, 0x5a, 0xa1, 0xeb, 0xd9, 0x6e,
-0xdc, 0xbc, 0x1b, 0x8f, 0xd6, 0xc1, 0x62, 0xca, 0x88, 0xb4, 0x8a, 0x08,
-0x89, 0x07, 0x00, 0xd0, 0x01, 0x32, 0x00, 0x21, 0x00, 0x2a, 0x1e, 0xdd,
-0x07, 0x78, 0x00, 0xab, 0x1f, 0x70, 0x47, 0x78, 0xc0, 0x46, 0x5f, 0x70,
-0x87, 0x78, 0xc0, 0x46, 0x9f, 0x70, 0xc7, 0x78, 0xc0, 0x46, 0xdf, 0x70,
-0xdb, 0x78, 0xc0, 0x46, 0x03, 0x70, 0x00, 0xab, 0x9b, 0x78, 0xc0, 0x46,
-0x43, 0x70, 0x00, 0xab, 0x5b, 0x78, 0xc0, 0x46,
-0x83, 0x70, 0x00, 0xab, 0x1b, 0x78, 0xc0, 0x46, 0xc3, 0x70, 0x04, 0x30,
-0x01, 0x31, 0x91, 0x42, 0xe0, 0xdb, 0x88, 0xbc, 0x70, 0x47, 0x00, 0x21,
-0xc1, 0x61, 0x09, 0x4a, 0xc0, 0x46, 0x02, 0x60, 0x08, 0x4a, 0xc0, 0x46,
-0x42, 0x60, 0x08, 0x4a, 0xc0, 0x46, 0x82, 0x60, 0x07, 0x4a, 0xc0, 0x46,
-0xc2, 0x60, 0x07, 0x4a, 0xc0, 0x46, 0x02, 0x61, 0x41, 0x61, 0x81, 0x61,
-0x70, 0x47, 0x00, 0x00, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
-0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, 0xf0, 0xe1, 0xd2, 0xc3,
-0xf0, 0xb5, 0x14, 0x1c, 0x0d, 0x1c, 0x07, 0x1c, 0xe1, 0x00, 0x78, 0x69,
-0x41, 0x18, 0x81, 0x42, 0x02, 0xd2, 0xb8, 0x69, 0x01, 0x30, 0xb8, 0x61,
-0x79, 0x61, 0x61, 0x0f, 0xb8, 0x69, 0x40, 0x18, 0xb8, 0x61, 0x40, 0x2c,
-0x14, 0xdb, 0xfe, 0x1d, 0x19, 0x36, 0x00, 0x20, 0x29, 0x78, 0x3a, 0x18,
-0x20, 0x32, 0x11, 0x70, 0x01, 0x35, 0x01, 0x30, 0x40, 0x28, 0xf7, 0xd3,
-0x40, 0x21, 0x30, 0x1c, 0xff, 0xf7, 0x96, 0xff, 0x38, 0x1c, 0xff, 0xf7,
-0xaf, 0xfd, 0x40, 0x3c, 0x40, 0x2c, 0xec, 0xda, 0x00, 0x20, 0x00, 0x2c,
-0x07, 0xd9, 0x29, 0x78, 0x3a, 0x18, 0x20, 0x32, 0x11, 0x70, 0x01, 0x35,
-0x01, 0x30, 0xa0, 0x42, 0xf7, 0xd3, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47,
-0xf8, 0xb5, 0x07, 0x1c, 0xd3, 0x00, 0x78, 0x69, 0xc6, 0x18, 0x86, 0x42,
-0x02, 0xd2, 0xb8, 0x69, 0x01, 0x30, 0xb8, 0x61, 0x7e, 0x61, 0x53, 0x0f,
-0xb8, 0x69, 0xc0, 0x18, 0xb8, 0x61, 0x00, 0x90, 0x00, 0x20, 0x00, 0x2a,
-0x07, 0xdd, 0x0b, 0x78, 0x3c, 0x18, 0x20, 0x34, 0x23, 0x70, 0x01, 0x31,
-0x01, 0x30, 0x90, 0x42, 0xf7, 0xdb, 0x80, 0x20, 0xd1, 0x19, 0x20, 0x31,
-0x08, 0x70, 0x54, 0x1c, 0xfd, 0x1d, 0x19, 0x35, 0x38, 0x2c, 0x1c, 0xdd,
-0x38, 0x19, 0x20, 0x30, 0x00, 0x21, 0x40, 0x22, 0x12, 0x1b, 0x00, 0x2a,
-0x05, 0xdd, 0x00, 0x23, 0x03, 0x70, 0x01, 0x30, 0x01, 0x31, 0x8a, 0x42,
-0xfa, 0xdc, 0x28, 0x1c, 0x21, 0x1c, 0xff, 0xf7, 0x4d, 0xff, 0x38, 0x1c,
-0xff, 0xf7, 0x66, 0xfd, 0x28, 0x1c, 0x00, 0x21, 0x00, 0x23, 0x03, 0x70,
-0x01, 0x30, 0x01, 0x31, 0x38, 0x29, 0xfa, 0xdb, 0x0c, 0xe0, 0x38, 0x19,
-0x20, 0x30, 0x00, 0x21, 0x38, 0x22, 0x12, 0x1b, 0x00, 0x2a, 0x05, 0xdd,
-0x00, 0x23, 0x03, 0x70, 0x01, 0x30, 0x01, 0x31, 0x8a, 0x42, 0xfa, 0xdc,
-0x28, 0x1c, 0x21, 0x1c, 0xff, 0xf7, 0x30, 0xff, 0x00, 0x98, 0xc0, 0x46,
-0xb8, 0x65, 0xfe, 0x65, 0x38, 0x1c, 0xff, 0xf7, 0x45, 0xfd, 0x01, 0x20,
-0xf8, 0x61, 0xf8, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xf0, 0xb5, 0x0c, 0x1c,
-0x05, 0x1c, 0x17, 0x1c, 0x38, 0x1c, 0x00, 0x2f, 0x04, 0xda, 0x40, 0x42,
-0x80, 0x06, 0x80, 0x0e, 0x40, 0x42, 0x01, 0xe0, 0x80, 0x06, 0x80, 0x0e,
-0x00, 0x28, 0x07, 0xd1, 0x28, 0x1c, 0x21, 0x1c, 0x3a, 0x1c, 0xff, 0xf7,
-0x57, 0xff, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x38, 0x1c, 0x00, 0x2f,
-0x00, 0xda, 0x3f, 0x30, 0x80, 0x11, 0x00, 0x28, 0x07, 0xdd, 0x86, 0x01,
-0x28, 0x1c, 0x21, 0x1c, 0x32, 0x1c, 0xff, 0xf7, 0x47, 0xff, 0xa4, 0x19,
-0xbf, 0x1b, 0x00, 0x2f, 0xeb, 0xd0, 0x28, 0x1c, 0x21, 0x1c, 0x3a, 0x1c,
-0xff, 0xf7, 0x74, 0xff, 0xe5, 0xe7, 0x98, 0xb5, 0x04, 0x1c, 0x0f, 0x1c,
-0x30, 0x20, 0x00, 0xab, 0x18, 0x70, 0xf8, 0x69, 0x00, 0x28, 0x04, 0xd1,
-0x69, 0x46, 0x00, 0x22, 0x38, 0x1c, 0xff, 0xf7, 0x65, 0xff, 0x14, 0x21,
-0x38, 0x1c, 0xff, 0xf7, 0xe3, 0xfe, 0x00, 0x20,
-0x81, 0x00, 0x79, 0x58, 0x02, 0xc4, 0x01, 0x30, 0x05, 0x28, 0xf9, 0xdb,
-0x98, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xb0, 0xb5, 0x98, 0xb0, 0x07, 0x1c,
-0x78, 0x68, 0x40, 0x28, 0x10, 0xd9, 0x68, 0x46, 0xff, 0xf7, 0xf9, 0xfe,
-0x68, 0x46, 0x06, 0xcf, 0x08, 0x3f, 0xff, 0xf7, 0xa7, 0xff, 0xf8, 0x1d,
-0xc5, 0x30, 0x69, 0x46, 0x04, 0x1c, 0xff, 0xf7, 0xd0, 0xff, 0x14, 0x20,
-0x78, 0x60, 0x3c, 0x60, 0x00, 0x20, 0x00, 0x24, 0x39, 0x18, 0xca, 0x1d,
-0x39, 0x32, 0x14, 0x72, 0x80, 0x31, 0x4c, 0x72, 0x7b, 0x68, 0x83, 0x42,
-0x06, 0xd9, 0x3b, 0x68, 0x5d, 0x1c, 0x3d, 0x60, 0x1b, 0x78, 0xc0, 0x46,
-0x13, 0x72, 0x4b, 0x72, 0x15, 0x7a, 0x36, 0x23, 0x6b, 0x40, 0x13, 0x72,
-0x4a, 0x7a, 0x5c, 0x23, 0x5a, 0x40, 0x4a, 0x72, 0x01, 0x30, 0x40, 0x28,
-0xe4, 0xd3, 0x18, 0xb0, 0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xf7, 0xb5,
-0xe0, 0xb0, 0x14, 0x1c, 0x0f, 0x1c, 0x00, 0x25, 0xae, 0x00, 0x01, 0x20,
-0xf1, 0x1d, 0x1d, 0x31, 0x02, 0xf0, 0x10, 0xfe, 0x01, 0x04, 0x00, 0x91,
-0x01, 0x20, 0xf1, 0x1d, 0x1b, 0x31, 0x02, 0xf0, 0x09, 0xfe, 0x00, 0x99,
-0x08, 0x43, 0x19, 0xa9, 0x71, 0x18, 0x88, 0x60, 0x01, 0x35, 0x10, 0x2d,
-0xea, 0xd3, 0x1b, 0xa8, 0x19, 0x90, 0x40, 0x20, 0x1a, 0x90, 0x19, 0xa8,
-0xff, 0xf7, 0xa7, 0xff, 0x01, 0xa8, 0xff, 0xf7, 0xa6, 0xfe, 0x40, 0x22,
-0x01, 0xa8, 0x2b, 0xa9, 0xff, 0xf7, 0x54, 0xff, 0x00, 0x2f, 0x0b, 0xd0,
-0x40, 0x2f, 0x01, 0xd9, 0x40, 0x25, 0x00, 0xe0, 0x3d, 0x1c, 0x60, 0x99,
-0x01, 0xa8, 0x2a, 0x1c, 0xff, 0xf7, 0x48, 0xff, 0x7f, 0x1b, 0xf3, 0xd1,
-0x51, 0xa8, 0x01, 0xa9, 0x07, 0x1c, 0xff, 0xf7, 0x70, 0xff, 0x01, 0xa8,
-0xff, 0xf7, 0x8b, 0xfe, 0x40, 0x22, 0x01, 0xa8, 0x3b, 0xa9, 0x01, 0x31,
-0xff, 0xf7, 0x38, 0xff, 0x14, 0x22, 0x01, 0xa8, 0x39, 0x1c, 0xff, 0xf7,
-0x33, 0xff, 0x56, 0xa8, 0x01, 0xa9, 0xff, 0xf7, 0x5e, 0xff, 0x00, 0x20,
-0x82, 0x00, 0x19, 0xa9, 0x51, 0x18, 0xc0, 0x31, 0x49, 0x6b, 0x02, 0xc4,
-0x01, 0x30, 0x05, 0x28, 0xf6, 0xd3, 0x63, 0xb0, 0xf0, 0xbc, 0x08, 0xbc,
-0x18, 0x47, 0x00, 0x00, 0x90, 0xb5, 0x07, 0x1c, 0x00, 0x24, 0x00, 0x2f,
-0x04, 0xd3, 0x04, 0xf0, 0x15, 0xf9, 0x01, 0x34, 0xbc, 0x42, 0xfa, 0xd9,
-0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xf0, 0xb5, 0x14, 0x1c, 0x0d, 0x1c,
-0x06, 0x1c, 0x1f, 0x1c, 0x1b, 0x4b, 0x32, 0x04, 0x12, 0x0c, 0x3c, 0x21,
-0x02, 0x20, 0xfd, 0xf7, 0x8a, 0xff, 0x32, 0x0c, 0x17, 0x4b, 0x3e, 0x21,
-0x02, 0x20, 0xfd, 0xf7, 0x84, 0xff, 0x15, 0x4b, 0x2a, 0x04, 0x12, 0x0c,
-0x40, 0x21, 0x02, 0x20, 0xfd, 0xf7, 0x7d, 0xff, 0x2a, 0x0c, 0x11, 0x4b,
-0x42, 0x21, 0x02, 0x20, 0xfd, 0xf7, 0x77, 0xff, 0x0e, 0x4b, 0x22, 0x04,
-0x12, 0x0c, 0x44, 0x21, 0x02, 0x20, 0xfd, 0xf7, 0x70, 0xff, 0x22, 0x0c,
-0x0a, 0x4b, 0x46, 0x21, 0x02, 0x20, 0xfd, 0xf7, 0x6a, 0xff, 0x08, 0x4b,
-0x3a, 0x04, 0x12, 0x0c, 0x48, 0x21, 0x02, 0x20, 0xfd, 0xf7, 0x63, 0xff,
-0x3a, 0x0c, 0x04, 0x4b, 0x4a, 0x21, 0x02, 0x20, 0xfd, 0xf7, 0x5d, 0xff,
-0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0xd9, 0xbf, 0x21, 0x40,
-0x88, 0xb5, 0x11, 0x27, 0x3f, 0x04, 0x38, 0x62, 0x79, 0x62, 0xba, 0x62,
-0xfb, 0x62, 0x04, 0x20, 0xff, 0xf7, 0xaa, 0xff, 0x07, 0x48, 0x40, 0x6b,
-0xc0, 0x46, 0x00, 0x90, 0x00, 0x98, 0x80, 0x07, 0x80, 0x0f, 0x03, 0x28,
-0x01, 0xd1, 0x01, 0x20, 0x00, 0xe0, 0x00, 0x20,
-0x88, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x00, 0x00, 0x11, 0x40,
-0xf0, 0xb5, 0x8a, 0xb0, 0x00, 0x24, 0x05, 0x94, 0x69, 0x49, 0xc9, 0x68,
-0xc0, 0x46, 0x00, 0x91, 0x68, 0x4a, 0x11, 0x68, 0x01, 0x22, 0x12, 0x04,
-0x0a, 0x40, 0x17, 0x21, 0x66, 0x4e, 0x00, 0x2a, 0x06, 0xd1, 0x64, 0x4a,
-0x13, 0x68, 0x1b, 0x0c, 0x04, 0xd1, 0x12, 0x68, 0x92, 0x0a, 0x01, 0xd3,
-0xf1, 0x60, 0x02, 0xe0, 0x61, 0x4a, 0xc0, 0x46, 0x11, 0x64, 0x61, 0x49,
-0x89, 0x68, 0x09, 0x04, 0x09, 0x0c, 0x03, 0x29, 0x54, 0xd1, 0xe9, 0x21,
-0x01, 0x91, 0x02, 0x99, 0xc0, 0x46, 0xb1, 0x60, 0x06, 0x94, 0x06, 0x99,
-0x8a, 0x00, 0x5b, 0x49, 0x8a, 0x58, 0x00, 0x2a, 0x73, 0xd0, 0x80, 0x20,
-0x02, 0x90, 0x06, 0x98, 0x81, 0x00, 0x57, 0x48, 0x41, 0x58, 0x02, 0x9a,
-0x11, 0x43, 0x02, 0x91, 0x00, 0x24, 0x00, 0x27, 0x25, 0x02, 0x28, 0x1c,
-0x38, 0x43, 0x09, 0x90, 0x09, 0x98, 0x00, 0x04, 0x51, 0x4b, 0x18, 0x43,
-0x04, 0x90, 0x09, 0x98, 0xef, 0x23, 0xdb, 0x05, 0x18, 0x43, 0x03, 0x90,
-0x06, 0x98, 0x80, 0x00, 0x4b, 0x49, 0x08, 0x58, 0x00, 0x04, 0x03, 0x99,
-0x08, 0x43, 0x03, 0x90, 0x00, 0x2f, 0x02, 0xd1, 0x03, 0x98, 0xc0, 0x46,
-0x70, 0x60, 0x01, 0x9b, 0x03, 0x9a, 0x02, 0x99, 0x04, 0x98, 0xff, 0xf7,
-0x89, 0xff, 0x00, 0x28, 0x06, 0xd0, 0x02, 0x99, 0xc0, 0x46, 0xb1, 0x60,
-0x03, 0x99, 0xc0, 0x46, 0x71, 0x60, 0x5c, 0xe0, 0x79, 0x1c, 0x0f, 0x04,
-0x3f, 0x0c, 0x17, 0x2f, 0xd1, 0xdd, 0x61, 0x1c, 0x0c, 0x04, 0x24, 0x0c,
-0x16, 0x2c, 0xca, 0xdd, 0x06, 0x99, 0x01, 0x31, 0x06, 0x91, 0x06, 0x99,
-0x89, 0x00, 0x37, 0x4a, 0x51, 0x58, 0x00, 0x29, 0xb7, 0xd1, 0x48, 0xe0,
-0xbf, 0x21, 0xc9, 0x43, 0x04, 0x91, 0xff, 0x21, 0x02, 0x91, 0x97, 0x21,
-0x01, 0x91, 0x06, 0x94, 0x06, 0x99, 0x89, 0x00, 0x31, 0x4f, 0x79, 0x58,
-0x00, 0x29, 0x1c, 0xd0, 0x09, 0x94, 0x08, 0x94, 0x06, 0x98, 0x80, 0x00,
-0x38, 0x58, 0xc0, 0x46, 0x07, 0x90, 0x07, 0x98, 0x00, 0x04, 0x26, 0xe0,
-0x05, 0x98, 0x15, 0x23, 0x1b, 0x06, 0x18, 0x43, 0x03, 0x90, 0x01, 0x9b,
-0x03, 0x9a, 0x02, 0x99, 0x04, 0x98, 0xff, 0xf7, 0x49, 0xff, 0x00, 0x28,
-0x23, 0xd1, 0x09, 0x99, 0x01, 0x31, 0x09, 0x91, 0x17, 0x29, 0x06, 0xd8,
-0x00, 0xe0, 0x1c, 0xe0, 0x08, 0x98, 0x00, 0x02, 0x09, 0x99, 0x08, 0x43,
-0x07, 0xe0, 0x08, 0x99, 0x01, 0x31, 0x08, 0x91, 0x17, 0x29, 0x0a, 0xd8,
-0x09, 0x94, 0x08, 0x98, 0x00, 0x02, 0x07, 0x99, 0x09, 0x04, 0x08, 0x43,
-0x15, 0x23, 0x1b, 0x06, 0x18, 0x43, 0x05, 0x90, 0xd6, 0xe7, 0x06, 0x99,
-0x01, 0x31, 0x06, 0x91, 0x06, 0x99, 0x89, 0x00, 0x79, 0x58, 0x00, 0x29,
-0xc4, 0xd1, 0x0c, 0x4a, 0x11, 0x68, 0x49, 0x0c, 0x05, 0xd2, 0x11, 0x68,
-0x09, 0x0c, 0x06, 0xd1, 0x11, 0x68, 0x89, 0x0a, 0x03, 0xd3, 0x00, 0x99,
-0xc0, 0x46, 0xf1, 0x60, 0x03, 0xe0, 0x00, 0x99, 0x06, 0x4a, 0xc0, 0x46,
-0x11, 0x64, 0x0a, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00,
-0x40, 0x01, 0x18, 0x40, 0x00, 0x00, 0x10, 0x40, 0x40, 0x01, 0x18, 0x00,
-0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x18, 0x40, 0x30, 0x6e, 0x21, 0x40,
-0x43, 0xff, 0x00, 0x00, 0x0c, 0x6e, 0x21, 0x40, 0x80, 0xb5, 0x82, 0xb0,
-0x00, 0x20, 0x01, 0x90, 0x1e, 0x48, 0xc1, 0x68, 0x01, 0x29, 0x1b, 0xd1,
-0x40, 0x88, 0x00, 0x28, 0x18, 0xd1, 0x68, 0x46, 0x01, 0xf0, 0x9a, 0xfe,
-0x00, 0x28, 0x13, 0xd1, 0xa8, 0x20, 0x01, 0xf0,
-0xdb, 0xfe, 0x18, 0x4f, 0x00, 0x28, 0x11, 0xd0, 0x04, 0x20, 0xff, 0xf7,
-0x97, 0xfe, 0x78, 0x6b, 0xc0, 0x46, 0x01, 0x90, 0x01, 0x98, 0x80, 0x07,
-0x80, 0x0f, 0x03, 0x28, 0x06, 0xd1, 0x00, 0x20, 0x01, 0xf0, 0xca, 0xfe,
-0x02, 0xb0, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x23, 0x00, 0x22,
-0x00, 0x21, 0x00, 0x20, 0xff, 0xf7, 0x8f, 0xfe, 0x00, 0x23, 0xdb, 0x43,
-0x18, 0x1c, 0x19, 0x1c, 0x1a, 0x1c, 0xff, 0xf7, 0xc7, 0xfe, 0x00, 0x28,
-0x03, 0xd1, 0xff, 0xf7, 0xdf, 0xfe, 0x00, 0x28, 0xe5, 0xd0, 0x38, 0x6a,
-0x79, 0x6a, 0xba, 0x6a, 0xfb, 0x6a, 0xff, 0xf7, 0x7c, 0xfe, 0xde, 0xe7,
-0x68, 0x0e, 0x00, 0x80, 0x00, 0x00, 0x11, 0x40, 0xff, 0xb5, 0x85, 0xb0,
-0x14, 0x1c, 0x1f, 0x1c, 0x00, 0x20, 0x01, 0x90, 0x01, 0x23, 0x5b, 0x04,
-0x9f, 0x42, 0x01, 0xd9, 0x0f, 0x20, 0x82, 0xe0, 0x26, 0x1c, 0x43, 0x4d,
-0xaf, 0x42, 0x00, 0xd2, 0x3d, 0x1c, 0x21, 0x0d, 0x09, 0x05, 0x41, 0x48,
-0x41, 0x4b, 0x99, 0x42, 0x04, 0xd0, 0x80, 0x25, 0x06, 0x1c, 0x80, 0x2f,
-0x00, 0xd8, 0x3d, 0x1c, 0x3e, 0x4a, 0x51, 0x69, 0xc0, 0x46, 0x03, 0x91,
-0x92, 0x69, 0xc0, 0x46, 0x02, 0x92, 0xff, 0x23, 0x01, 0x33, 0x19, 0x43,
-0x39, 0x4b, 0xc0, 0x46, 0x59, 0x61, 0xff, 0x23, 0x01, 0x33, 0x9a, 0x43,
-0x36, 0x4b, 0xc0, 0x46, 0x9a, 0x61, 0x01, 0x22, 0x12, 0x05, 0xd1, 0x60,
-0x33, 0x4a, 0x91, 0x69, 0x01, 0x22, 0x12, 0x05, 0x11, 0x61, 0x31, 0x4a,
-0xff, 0x23, 0x01, 0x33, 0x91, 0x69, 0x19, 0x43, 0x91, 0x61, 0x01, 0x22,
-0x12, 0x05, 0x11, 0x61, 0x85, 0x21, 0x89, 0x04, 0x04, 0x91, 0x00, 0x2f,
-0x34, 0xd0, 0x28, 0x48, 0x86, 0x42, 0x04, 0xd1, 0x30, 0x1c, 0x21, 0x1c,
-0x2a, 0x1c, 0x03, 0xf0, 0x4f, 0xff, 0x2a, 0x1c, 0x04, 0x98, 0x02, 0x43,
-0x00, 0x92, 0x01, 0x20, 0x06, 0x99, 0x05, 0x9a, 0x33, 0x1c, 0xfd, 0xf7,
-0xbd, 0xfd, 0x22, 0x48, 0x22, 0x49, 0x4a, 0x68, 0x52, 0x0a, 0x09, 0xd3,
-0xff, 0x21, 0x01, 0x31, 0x20, 0x4a, 0xc0, 0x46, 0x11, 0x60, 0x00, 0x28,
-0x05, 0xd1, 0x11, 0x20, 0x01, 0x90, 0x13, 0xe0, 0x01, 0x38, 0xf0, 0xd1,
-0xf9, 0xe7, 0x7f, 0x1b, 0x0e, 0xd0, 0x15, 0x48, 0x86, 0x42, 0x01, 0xd1,
-0x64, 0x19, 0x00, 0xe0, 0x76, 0x19, 0x06, 0x99, 0x49, 0x19, 0x06, 0x91,
-0x38, 0x1c, 0xaf, 0x42, 0x00, 0xd3, 0x28, 0x1c, 0x05, 0x1c, 0xca, 0xe7,
-0x0f, 0x48, 0x41, 0x69, 0x03, 0x9b, 0x19, 0x43, 0x41, 0x61, 0x82, 0x69,
-0x03, 0x9b, 0x9a, 0x43, 0x82, 0x61, 0x01, 0x22, 0x12, 0x05, 0xd1, 0x60,
-0x81, 0x69, 0xc0, 0x46, 0x11, 0x61, 0x81, 0x69, 0x02, 0x9b, 0x19, 0x43,
-0x81, 0x61, 0x11, 0x61, 0x01, 0x98, 0x09, 0xb0, 0xf0, 0xbc, 0x08, 0xbc,
-0x18, 0x47, 0x00, 0x00, 0xf0, 0xff, 0x00, 0x00, 0x50, 0xab, 0x20, 0x40,
-0x00, 0x00, 0x20, 0x40, 0x68, 0x0e, 0x00, 0x80, 0xff, 0xff, 0x00, 0x00,
-0x00, 0x00, 0x10, 0x40, 0x00, 0x00, 0x00, 0xb0, 0xff, 0xb5, 0x85, 0xb0,
-0x04, 0x1c, 0x1f, 0x1c, 0x00, 0x20, 0x01, 0x90, 0x01, 0x23, 0x5b, 0x04,
-0x9f, 0x42, 0x01, 0xd9, 0x0f, 0x20, 0x7d, 0xe0, 0x26, 0x1c, 0x40, 0x4d,
-0xaf, 0x42, 0x00, 0xd2, 0x3d, 0x1c, 0x21, 0x0d, 0x09, 0x05, 0x3e, 0x48,
-0x3e, 0x4b, 0x99, 0x42, 0x04, 0xd0, 0x80, 0x25, 0x06, 0x1c, 0x80, 0x2f,
-0x00, 0xd8, 0x3d, 0x1c, 0x3b, 0x4a, 0x51, 0x69, 0xc0, 0x46, 0x03, 0x91,
-0x92, 0x69, 0xc0, 0x46, 0x02, 0x92, 0x10, 0x23, 0x19, 0x43, 0x37, 0x4b,
-0xc0, 0x46, 0x59, 0x61, 0x10, 0x23, 0x9a, 0x43,
-0x34, 0x4b, 0xc0, 0x46, 0x9a, 0x61, 0x01, 0x22, 0x12, 0x05, 0xd1, 0x60,
-0x31, 0x4a, 0x91, 0x69, 0x01, 0x22, 0x12, 0x05, 0x11, 0x61, 0x2f, 0x4a,
-0x10, 0x23, 0x91, 0x69, 0x19, 0x43, 0x91, 0x61, 0x1a, 0x04, 0x11, 0x61,
-0x21, 0x21, 0x09, 0x05, 0x04, 0x91, 0x00, 0x2f, 0x33, 0xd0, 0x2a, 0x1c,
-0x04, 0x98, 0x02, 0x43, 0x00, 0x92, 0x00, 0x20, 0x06, 0x99, 0x07, 0x9a,
-0x33, 0x1c, 0xfd, 0xf7, 0x27, 0xfd, 0x25, 0x48, 0x25, 0x49, 0x4a, 0x68,
-0x52, 0x09, 0x08, 0xd3, 0x10, 0x21, 0x24, 0x4a, 0xc0, 0x46, 0x11, 0x60,
-0x00, 0x28, 0x05, 0xd1, 0x11, 0x20, 0x01, 0x90, 0x1b, 0xe0, 0x01, 0x38,
-0xf1, 0xd1, 0xf9, 0xe7, 0x19, 0x48, 0x86, 0x42, 0x04, 0xd1, 0x20, 0x1c,
-0x31, 0x1c, 0x2a, 0x1c, 0x03, 0xf0, 0x96, 0xfe, 0x7f, 0x1b, 0x0e, 0xd0,
-0x14, 0x48, 0x86, 0x42, 0x01, 0xd0, 0x76, 0x19, 0x00, 0xe0, 0x64, 0x19,
-0x06, 0x99, 0x49, 0x19, 0x06, 0x91, 0x38, 0x1c, 0xaf, 0x42, 0x00, 0xd3,
-0x28, 0x1c, 0x05, 0x1c, 0xcb, 0xe7, 0x0f, 0x48, 0x41, 0x69, 0x03, 0x9b,
-0x19, 0x43, 0x41, 0x61, 0x82, 0x69, 0x03, 0x9b, 0x9a, 0x43, 0x82, 0x61,
-0x01, 0x22, 0x12, 0x05, 0xd1, 0x60, 0x81, 0x69, 0xc0, 0x46, 0x11, 0x61,
-0x81, 0x69, 0x02, 0x9b, 0x19, 0x43, 0x81, 0x61, 0x11, 0x61, 0x01, 0x98,
-0x09, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xf0, 0xff, 0x00, 0x00,
-0x50, 0xab, 0x20, 0x40, 0x00, 0x00, 0x20, 0x40, 0x68, 0x0e, 0x00, 0x80,
-0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, 0x00, 0x00, 0x00, 0xb0,
0x70, 0x47, 0x04, 0x49, 0x00, 0x20, 0x00, 0x22, 0x0a, 0x70, 0x01, 0x30,
0x01, 0x31, 0x68, 0x28, 0xfa, 0xd3, 0x70, 0x47, 0xa0, 0x82, 0x20, 0x40,
0x00, 0x22, 0x88, 0x42, 0x03, 0xd3, 0x40, 0x1a, 0x01, 0x32, 0x88, 0x42,
@@ -2987,7 +2639,7 @@ const u8 typhoon_firmware_image[] = {
0xc0, 0x46, 0x93, 0x60, 0x0b, 0x69, 0xc0, 0x46, 0x13, 0x61, 0x4b, 0x69,
0xc0, 0x46, 0x53, 0x61, 0xc9, 0x68, 0xc0, 0x46, 0xd1, 0x60, 0x90, 0xbc,
0x70, 0x47, 0x01, 0x30, 0x00, 0x06, 0x00, 0x0e, 0x04, 0x28, 0xd9, 0xdb,
-0x38, 0x1c, 0xf6, 0xe7, 0xd0, 0xab, 0x20, 0x40, 0xf7, 0xb5, 0xc4, 0xb0,
+0x38, 0x1c, 0xf6, 0xe7, 0x40, 0xab, 0x20, 0x40, 0xf7, 0xb5, 0xc4, 0xb0,
0x04, 0x1c, 0x00, 0x20, 0x46, 0x9a, 0x11, 0x21, 0x11, 0x40, 0x6e, 0xd0,
0x00, 0x27, 0x79, 0x00, 0xc9, 0x19, 0xc9, 0x00, 0x57, 0x4a, 0x51, 0x58,
0x49, 0x0c, 0x03, 0xd2, 0x01, 0x30, 0x00, 0x06, 0x00, 0x0e, 0x04, 0xe0,
@@ -2998,12 +2650,12 @@ const u8 typhoon_firmware_image[] = {
0x72, 0x1c, 0x16, 0x06, 0x36, 0x0e, 0x04, 0xe0, 0x01, 0x30, 0x00, 0x06,
0x00, 0x0e, 0x10, 0x28, 0xf0, 0xdb, 0x00, 0x2e, 0x3d, 0xd0, 0x04, 0x2c,
0x3e, 0xd1, 0x80, 0x00, 0x08, 0x58, 0x40, 0x01, 0x80, 0x0d, 0x00, 0x22,
-0x00, 0x92, 0x10, 0x23, 0x00, 0x21, 0x02, 0xaa,
-0x00, 0xf0, 0x68, 0xfa, 0x00, 0x21, 0x01, 0x91, 0x02, 0xa8, 0x05, 0x99,
-0x49, 0x0c, 0x89, 0x05, 0x29, 0xd0, 0xc1, 0x68, 0x0a, 0x06, 0x12, 0x0e,
-0x45, 0x9b, 0x9a, 0x42, 0x11, 0xd1, 0xc0, 0x68, 0x40, 0x01, 0x86, 0x0d,
-0x00, 0x22, 0x00, 0x92, 0x0c, 0x23, 0x00, 0x21, 0x30, 0x1c, 0x02, 0xaa,
-0x00, 0xf0, 0x50, 0xfa, 0x01, 0x99, 0x02, 0x9d, 0x48, 0x1c, 0x01, 0x06,
+0x00, 0x92, 0x10, 0x23, 0x00, 0x21, 0x02, 0xaa, 0x00, 0xf0, 0x68, 0xfa,
+0x00, 0x21, 0x01, 0x91, 0x02, 0xa8, 0x05, 0x99, 0x49, 0x0c, 0x89, 0x05,
+0x29, 0xd0, 0xc1, 0x68, 0x0a, 0x06, 0x12, 0x0e, 0x45, 0x9b, 0x9a, 0x42,
+0x11, 0xd1, 0xc0, 0x68, 0x40, 0x01, 0x86, 0x0d, 0x00, 0x22, 0x00, 0x92,
+0x0c, 0x23, 0x00, 0x21, 0x30, 0x1c, 0x02, 0xaa, 0x00, 0xf0, 0x50, 0xfa,
+0x01, 0x99, 0x02, 0x9d, 0x48, 0x1c, 0x01, 0x06,
0x09, 0x0e, 0x01, 0x91, 0x0e, 0xe0, 0x48, 0x01, 0x86, 0x0d, 0x00, 0x22,
0x00, 0x92, 0x10, 0x23, 0x00, 0x21, 0x30, 0x1c, 0x02, 0xaa, 0x00, 0xf0,
0x3f, 0xfa, 0x02, 0xa8, 0x05, 0x99, 0x49, 0x0c, 0x89, 0x05, 0xd8, 0xd1,
@@ -3019,7 +2671,7 @@ const u8 typhoon_firmware_image[] = {
0x18, 0x18, 0xc0, 0x00, 0x00, 0x1b, 0x70, 0x61, 0x00, 0x20, 0x50, 0x21,
0x46, 0x9a, 0x11, 0x40, 0x50, 0x29, 0x00, 0xd1, 0x28, 0x1c, 0xf0, 0x60,
0x38, 0x1c, 0x47, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xff, 0x20,
-0xf9, 0xe7, 0x00, 0x00, 0xd0, 0xab, 0x20, 0x40, 0x80, 0xb4, 0x00, 0x23,
+0xf9, 0xe7, 0x00, 0x00, 0x40, 0xab, 0x20, 0x40, 0x80, 0xb4, 0x00, 0x23,
0x00, 0x22, 0x00, 0x29, 0x06, 0xd9, 0x87, 0x5c, 0x7b, 0x40, 0x1b, 0x06,
0x1b, 0x0e, 0x01, 0x32, 0x8a, 0x42, 0xf8, 0xd3, 0xd8, 0x43, 0x00, 0x06,
0x00, 0x0e, 0x80, 0xbc, 0x70, 0x47, 0xf0, 0xb5, 0xc6, 0xb0, 0x04, 0x28,
@@ -3041,12 +2693,12 @@ const u8 typhoon_firmware_image[] = {
0x05, 0x98, 0x00, 0x0a, 0x00, 0x02, 0x39, 0x06, 0x09, 0x0e, 0x08, 0x43,
0x05, 0x90, 0xff, 0x23, 0x1b, 0x02, 0x98, 0x43, 0x05, 0x90, 0x0c, 0x21,
0x03, 0xa8, 0xff, 0xf7, 0x83, 0xff, 0xff, 0x23, 0x1b, 0x02, 0x05, 0x99,
-0x99, 0x43, 0x00, 0x06, 0x00, 0x0e, 0x00, 0x02,
-0x08, 0x43, 0x05, 0x90, 0x0c, 0x23, 0x00, 0x21, 0x60, 0x68, 0x03, 0xaa,
-0x00, 0xf0, 0xca, 0xf9, 0x00, 0x20, 0x45, 0x99, 0x06, 0x4a, 0xc0, 0x46,
-0x50, 0x50, 0xc1, 0x43, 0x61, 0x60, 0xa1, 0x60, 0xe1, 0x60, 0x21, 0x61,
-0x61, 0x61, 0x46, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00,
-0xd0, 0xab, 0x20, 0x40, 0xb0, 0xb4, 0x4c, 0x42, 0x00, 0x29, 0x00, 0xdb,
+0x99, 0x43, 0x00, 0x06, 0x00, 0x0e, 0x00, 0x02, 0x08, 0x43, 0x05, 0x90,
+0x0c, 0x23, 0x00, 0x21, 0x60, 0x68, 0x03, 0xaa, 0x00, 0xf0, 0xca, 0xf9,
+0x00, 0x20, 0x45, 0x99, 0x06, 0x4a, 0xc0, 0x46, 0x50, 0x50, 0xc1, 0x43,
+0x61, 0x60, 0xa1, 0x60, 0xe1, 0x60, 0x21, 0x61, 0x61, 0x61, 0x46, 0xb0,
+0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x40, 0xab, 0x20, 0x40,
+0xb0, 0xb4, 0x4c, 0x42, 0x00, 0x29, 0x00, 0xdb,
0x0c, 0x1c, 0x00, 0x27, 0xff, 0x43, 0x04, 0x28, 0x21, 0xda, 0x12, 0x4d,
0x43, 0x00, 0x18, 0x18, 0xc0, 0x00, 0x40, 0x19, 0x01, 0x2a, 0x05, 0xd0,
0x02, 0x2a, 0x09, 0xd0, 0x03, 0x2a, 0x16, 0xd1, 0x01, 0x69, 0x0b, 0xe0,
@@ -3054,7 +2706,7 @@ const u8 typhoon_firmware_image[] = {
0x00, 0x29, 0x07, 0xda, 0xc1, 0x68, 0xa1, 0x42, 0x09, 0xd3, 0x09, 0x1b,
0xc1, 0x60, 0xc0, 0x68, 0xb0, 0xbc, 0x70, 0x47, 0xc1, 0x68, 0x09, 0x19,
0x02, 0x69, 0x91, 0x42, 0xf6, 0xd9, 0x38, 0x1c, 0xf6, 0xe7, 0x00, 0x00,
-0xd0, 0xab, 0x20, 0x40, 0xf0, 0xb5, 0x84, 0xb0, 0x17, 0x1c, 0x0d, 0x1c,
+0x40, 0xab, 0x20, 0x40, 0xf0, 0xb5, 0x84, 0xb0, 0x17, 0x1c, 0x0d, 0x1c,
0x00, 0x21, 0x02, 0x91, 0x42, 0x00, 0x12, 0x18, 0xd2, 0x00, 0x2c, 0x49,
0x8b, 0x58, 0x1b, 0x06, 0x1b, 0x0e, 0x01, 0x93, 0x00, 0x23, 0xdb, 0x43,
0x04, 0x28, 0x02, 0xda, 0x01, 0x98, 0x40, 0x08, 0x01, 0xd2, 0x18, 0x1c,
@@ -3070,7 +2722,7 @@ const u8 typhoon_firmware_image[] = {
0x00, 0x92, 0x01, 0x1c, 0x30, 0x1c, 0x2a, 0x1c, 0x3b, 0x1c, 0x00, 0xf0,
0xcd, 0xf8, 0xe0, 0x68, 0xc0, 0x19, 0xed, 0x19, 0xe0, 0x60, 0x02, 0x98,
0xc0, 0x19, 0x02, 0x90, 0x00, 0x27, 0x00, 0x2f, 0xc2, 0xd8, 0x02, 0x98,
-0x04, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xd0, 0xab, 0x20, 0x40,
+0x04, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x40, 0xab, 0x20, 0x40,
0xf0, 0xb5, 0x83, 0xb0, 0x17, 0x1c, 0x0d, 0x1c, 0x00, 0x21, 0x01, 0x91,
0x42, 0x00, 0x12, 0x18, 0xd2, 0x00, 0x02, 0x92, 0x30, 0x49, 0x8a, 0x58,
0x12, 0x06, 0x12, 0x0e, 0x00, 0x24, 0xe4, 0x43, 0x04, 0x28, 0x01, 0xda,
@@ -3084,12 +2736,12 @@ const u8 typhoon_firmware_image[] = {
0x91, 0x42, 0x13, 0xd9, 0x13, 0x1a, 0x01, 0x1c, 0x00, 0x98, 0x2a, 0x1c,
0x1e, 0x1c, 0x00, 0xf0, 0xdf, 0xf8, 0xe0, 0x68, 0x80, 0x19, 0x75, 0x19,
0xe0, 0x60, 0x21, 0x69, 0x88, 0x42, 0x00, 0xd9, 0x20, 0x61, 0xbf, 0x1b,
-0x01, 0x98, 0x30, 0x18, 0x01, 0x90, 0x12, 0xe0,
-0x01, 0x1c, 0x00, 0x9e, 0x30, 0x1c, 0x2a, 0x1c, 0x3b, 0x1c, 0x00, 0xf0,
-0xcb, 0xf8, 0xe0, 0x68, 0xc0, 0x19, 0xed, 0x19, 0xe0, 0x60, 0x21, 0x69,
-0x88, 0x42, 0x00, 0xd9, 0x20, 0x61, 0x01, 0x98, 0xc0, 0x19, 0x01, 0x90,
-0x00, 0x27, 0x00, 0x2f, 0xb9, 0xd8, 0x01, 0x98, 0x03, 0xb0, 0xf0, 0xbc,
-0x08, 0xbc, 0x18, 0x47, 0xd0, 0xab, 0x20, 0x40, 0xb0, 0xb5, 0xc3, 0xb0,
+0x01, 0x98, 0x30, 0x18, 0x01, 0x90, 0x12, 0xe0, 0x01, 0x1c, 0x00, 0x9e,
+0x30, 0x1c, 0x2a, 0x1c, 0x3b, 0x1c, 0x00, 0xf0, 0xcb, 0xf8, 0xe0, 0x68,
+0xc0, 0x19, 0xed, 0x19, 0xe0, 0x60, 0x21, 0x69, 0x88, 0x42, 0x00, 0xd9,
+0x20, 0x61, 0x01, 0x98, 0xc0, 0x19, 0x01, 0x90, 0x00, 0x27, 0x00, 0x2f,
+0xb9, 0xd8, 0x01, 0x98, 0x03, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47,
+0x40, 0xab, 0x20, 0x40, 0xb0, 0xb5, 0xc3, 0xb0,
0x0c, 0x1c, 0x00, 0x27, 0xfa, 0x43, 0x04, 0x28, 0x06, 0xda, 0x41, 0x00,
0x09, 0x18, 0xc9, 0x00, 0x14, 0x48, 0x45, 0x58, 0x6b, 0x0c, 0x04, 0xd2,
0x10, 0x1c, 0x43, 0xb0, 0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x62, 0x09,
@@ -3098,222 +2750,222 @@ const u8 typhoon_firmware_image[] = {
0x12, 0x2c, 0x0d, 0xd0, 0x13, 0x2c, 0x05, 0xd0, 0x14, 0x2c, 0x0a, 0xd1,
0x03, 0x98, 0x00, 0x04, 0x07, 0x0e, 0x06, 0xe0, 0x03, 0x98, 0x07, 0x06,
0x3f, 0x0e, 0x02, 0xe0, 0x01, 0x9f, 0x00, 0xe0, 0x02, 0x9f, 0x38, 0x1c,
-0xdb, 0xe7, 0x00, 0x00, 0xd0, 0xab, 0x20, 0x40, 0x03, 0x49, 0x00, 0x20,
+0xdb, 0xe7, 0x00, 0x00, 0x40, 0xab, 0x20, 0x40, 0x03, 0x49, 0x00, 0x20,
0x00, 0x22, 0x0a, 0x54, 0x01, 0x30, 0x60, 0x28, 0xfb, 0xd3, 0x70, 0x47,
-0xd0, 0xab, 0x20, 0x40, 0x00, 0xb5, 0x02, 0xf0, 0x01, 0xfa, 0x57, 0x20,
-0x02, 0xf0, 0x5e, 0xf9, 0x02, 0xf0, 0xd2, 0xf8, 0x00, 0x0a, 0xfb, 0xd3,
-0x02, 0xf0, 0xe0, 0xf9, 0x08, 0xbc, 0x18, 0x47, 0xf0, 0xb5, 0x82, 0xb0,
+0x40, 0xab, 0x20, 0x40, 0x00, 0xb5, 0x02, 0xf0, 0x6f, 0xfa, 0x57, 0x20,
+0x02, 0xf0, 0xcc, 0xf9, 0x02, 0xf0, 0x40, 0xf9, 0x00, 0x0a, 0xfb, 0xd3,
+0x02, 0xf0, 0x4e, 0xfa, 0x08, 0xbc, 0x18, 0x47, 0xf0, 0xb5, 0x82, 0xb0,
0x07, 0x9d, 0x14, 0x1c, 0x1f, 0x1c, 0x30, 0x4a, 0xd2, 0x6f, 0x20, 0x23,
0x16, 0x68, 0x9e, 0x43, 0x16, 0x60, 0x33, 0x1c, 0xff, 0x22, 0x01, 0x32,
0x2a, 0x40, 0x40, 0x02, 0x08, 0x43, 0x05, 0x0a, 0x06, 0x1c, 0x00, 0x0c,
-0x01, 0x90, 0x00, 0x2a, 0x20, 0xd0, 0x02, 0xf0, 0xdd, 0xf9, 0x53, 0x20,
-0x02, 0xf0, 0x3a, 0xf9, 0x01, 0x98, 0xc0, 0x46, 0x00, 0x90, 0x02, 0xf0,
-0x35, 0xf9, 0x28, 0x1c, 0x02, 0xf0, 0x32, 0xf9, 0x30, 0x1c, 0x02, 0xf0,
-0x2f, 0xf9, 0x02, 0xf0, 0xb5, 0xf9, 0xff, 0xf7, 0xc7, 0xff, 0x02, 0xf0,
-0xc9, 0xf9, 0x54, 0x20, 0x02, 0xf0, 0x26, 0xf9, 0x00, 0x98, 0x02, 0xf0,
-0x23, 0xf9, 0x28, 0x1c, 0x02, 0xf0, 0x20, 0xf9, 0x30, 0x1c, 0x14, 0xe0,
-0x02, 0xf0, 0xbc, 0xf9, 0x52, 0x20, 0x02, 0xf0, 0x19, 0xf9, 0x01, 0x98,
-0x02, 0xf0, 0x16, 0xf9, 0x28, 0x1c, 0x02, 0xf0, 0x13, 0xf9, 0x30, 0x1c,
-0x02, 0xf0, 0x10, 0xf9, 0x00, 0x20, 0x02, 0xf0, 0x0d, 0xf9, 0x00, 0x20,
-0x02, 0xf0, 0x0a, 0xf9, 0x00, 0x20, 0x02, 0xf0, 0x07, 0xf9, 0x00, 0x20,
-0x02, 0xf0, 0x04, 0xf9, 0x00, 0x2f, 0x05, 0xd9, 0x02, 0xf0, 0x76, 0xf8,
-0x20, 0x70, 0x01, 0x34, 0x01, 0x3f, 0xf9, 0xd1, 0x02, 0xf0, 0x82, 0xf9,
+0x01, 0x90, 0x00, 0x2a, 0x20, 0xd0, 0x02, 0xf0, 0x4b, 0xfa, 0x53, 0x20,
+0x02, 0xf0, 0xa8, 0xf9, 0x01, 0x98, 0xc0, 0x46, 0x00, 0x90, 0x02, 0xf0,
+0xa3, 0xf9, 0x28, 0x1c, 0x02, 0xf0, 0xa0, 0xf9, 0x30, 0x1c, 0x02, 0xf0,
+0x9d, 0xf9, 0x02, 0xf0, 0x23, 0xfa, 0xff, 0xf7, 0xc7, 0xff, 0x02, 0xf0,
+0x37, 0xfa, 0x54, 0x20, 0x02, 0xf0, 0x94, 0xf9, 0x00, 0x98, 0x02, 0xf0,
+0x91, 0xf9, 0x28, 0x1c, 0x02, 0xf0, 0x8e, 0xf9, 0x30, 0x1c, 0x14, 0xe0,
+0x02, 0xf0, 0x2a, 0xfa, 0x52, 0x20, 0x02, 0xf0, 0x87, 0xf9, 0x01, 0x98,
+0x02, 0xf0, 0x84, 0xf9, 0x28, 0x1c, 0x02, 0xf0, 0x81, 0xf9, 0x30, 0x1c,
+0x02, 0xf0, 0x7e, 0xf9, 0x00, 0x20, 0x02, 0xf0, 0x7b, 0xf9, 0x00, 0x20,
+0x02, 0xf0, 0x78, 0xf9, 0x00, 0x20, 0x02, 0xf0, 0x75, 0xf9, 0x00, 0x20,
+0x02, 0xf0, 0x72, 0xf9, 0x00, 0x2f, 0x05, 0xd9, 0x02, 0xf0, 0xe4, 0xf8,
+0x20, 0x70, 0x01, 0x34, 0x01, 0x3f, 0xf9, 0xd1, 0x02, 0xf0, 0xf0, 0xf9,
0x04, 0x4a, 0xd0, 0x6f, 0x20, 0x23, 0x01, 0x68, 0x19, 0x43, 0x01, 0x60,
0x02, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x68, 0x0e, 0x00, 0x80,
-0xf0, 0xb5, 0x82, 0xb0, 0x14, 0x1c, 0x1f, 0x1c, 0x40, 0x02, 0x08, 0x43,
-0x05, 0x1c, 0x2c, 0x49, 0xc8, 0x6f, 0x20, 0x23, 0x02, 0x68, 0x9a, 0x43,
-0x02, 0x60, 0xc8, 0x6f, 0x40, 0x23, 0x01, 0x68, 0x19, 0x43, 0x01, 0x60,
-0x02, 0xf0, 0x7a, 0xf9, 0x53, 0x20, 0x02, 0xf0, 0xd7, 0xf8, 0x28, 0x0c,
-0x06, 0x1c, 0x02, 0xf0, 0xd3, 0xf8, 0x28, 0x0a, 0x01, 0x90, 0x00, 0x90,
-0x02, 0xf0, 0xce, 0xf8, 0x28, 0x1c, 0x02, 0xf0, 0xcb, 0xf8, 0x02, 0xf0,
-0x51, 0xf9, 0xff, 0xf7, 0x63, 0xff, 0x02, 0xf0, 0x65, 0xf9, 0x84, 0x20,
-0x02, 0xf0, 0xc2, 0xf8, 0x30, 0x1c, 0x02, 0xf0,
-0xbf, 0xf8, 0x00, 0x98, 0x02, 0xf0, 0xbc, 0xf8, 0x28, 0x1c, 0x02, 0xf0,
-0xb9, 0xf8, 0x00, 0x2f, 0x05, 0xd9, 0x20, 0x78, 0x01, 0x34, 0x02, 0xf0,
-0xb3, 0xf8, 0x01, 0x3f, 0xf9, 0xd1, 0x02, 0xf0, 0x37, 0xf9, 0x02, 0xf0,
-0x4d, 0xf9, 0x83, 0x20, 0x02, 0xf0, 0xaa, 0xf8, 0x30, 0x1c, 0x02, 0xf0,
-0xa7, 0xf8, 0x01, 0x98, 0x02, 0xf0, 0xa4, 0xf8, 0x28, 0x1c, 0x02, 0xf0,
-0xa1, 0xf8, 0x02, 0xf0, 0x27, 0xf9, 0xff, 0xf7, 0x39, 0xff, 0x07, 0x49,
-0xc8, 0x6f, 0x40, 0x23, 0x02, 0x68, 0x9a, 0x43, 0x02, 0x60, 0xc8, 0x6f,
-0x20, 0x23, 0x01, 0x68, 0x19, 0x43, 0x01, 0x60, 0x02, 0xb0, 0xf0, 0xbc,
-0x08, 0xbc, 0x18, 0x47, 0x68, 0x0e, 0x00, 0x80, 0x70, 0x47, 0x00, 0x00,
-0x80, 0xb5, 0x01, 0xf0, 0x91, 0xf8, 0x06, 0x4f, 0xc0, 0x46, 0xf8, 0x60,
-0x01, 0xf0, 0xf4, 0xf8, 0x78, 0x80, 0x01, 0xf0, 0xb3, 0xf8, 0x38, 0x71,
-0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x68, 0x0e, 0x00, 0x80,
-0x00, 0xb5, 0x01, 0xf0, 0x07, 0xf9, 0x02, 0x49, 0xc0, 0x46, 0x08, 0x80,
-0x08, 0xbc, 0x18, 0x47, 0x68, 0x0e, 0x00, 0x80, 0x0b, 0x48, 0xc1, 0x68,
-0x01, 0x29, 0x11, 0xd1, 0xc1, 0x6f, 0x02, 0x23, 0x0a, 0x68, 0x1a, 0x43,
-0x0a, 0x60, 0xc1, 0x6f, 0x80, 0x23, 0x0a, 0x68, 0x1a, 0x43, 0x0a, 0x60,
-0xc1, 0x18, 0x08, 0x68, 0x82, 0x23, 0x02, 0x68, 0x1a, 0x43, 0x02, 0x60,
-0x00, 0x20, 0x08, 0x81, 0x70, 0x47, 0x00, 0x00, 0x68, 0x0e, 0x00, 0x80,
-0xf0, 0xb4, 0x4a, 0x49, 0xca, 0x1d, 0x9d, 0x32, 0x00, 0x20, 0x00, 0x27,
-0x83, 0x00, 0xd7, 0x50, 0x01, 0x30, 0x17, 0x28, 0xfa, 0xd3, 0x46, 0x4c,
-0x00, 0x20, 0x82, 0x00, 0xa7, 0x50, 0x01, 0x30, 0x20, 0x28, 0xfa, 0xd3,
-0x43, 0x4a, 0x00, 0x20, 0x83, 0x00, 0xd7, 0x50, 0x01, 0x30, 0x20, 0x28,
-0xfa, 0xd3, 0xa7, 0x61, 0x97, 0x61, 0x4f, 0x65, 0x8f, 0x65, 0x3f, 0x4d,
-0xc0, 0x46, 0x2f, 0x60, 0x6f, 0x60, 0xaf, 0x60, 0xaf, 0x61, 0xef, 0x60,
-0x2f, 0x61, 0x6f, 0x61, 0x00, 0x20, 0xc1, 0x00, 0x09, 0x18, 0x49, 0x01,
-0x35, 0x4b, 0xc9, 0x18, 0x86, 0x00, 0xcb, 0x1d, 0xf9, 0x33, 0x34, 0x4c,
-0x34, 0x19, 0xe3, 0x63, 0x11, 0x23, 0x5b, 0x01, 0xcb, 0x18, 0x63, 0x63,
-0x0d, 0x23, 0x9b, 0x01, 0xcb, 0x18, 0xb4, 0x18, 0xe3, 0x63, 0x23, 0x23,
-0x5b, 0x01, 0xc9, 0x18, 0x61, 0x63, 0x01, 0x30, 0x02, 0x28, 0xe4, 0xdb,
-0x29, 0x48, 0xc1, 0x1d, 0xf9, 0x31, 0x29, 0x4c, 0xc0, 0x46, 0xa1, 0x62,
-0x61, 0x6b, 0x0d, 0x23, 0x9b, 0x01, 0xe1, 0x62, 0xc1, 0x18, 0x91, 0x62,
-0x51, 0x6b, 0xc0, 0x46, 0xd1, 0x62, 0x08, 0x21, 0xe1, 0x64, 0x25, 0x49,
-0xc0, 0x46, 0x21, 0x65, 0x24, 0x49, 0x0b, 0x69, 0xc0, 0x46, 0x63, 0x65,
-0xc3, 0x1d, 0x4d, 0x33, 0xe3, 0x65, 0x25, 0x66, 0x8b, 0x68, 0xc0, 0x46,
-0x63, 0x66, 0xcb, 0x68, 0xc0, 0x46, 0xa3, 0x66, 0x1e, 0x4b, 0xc0, 0x46,
-0xe3, 0x66, 0x27, 0x67, 0x0b, 0x23, 0xdb, 0x01, 0xc3, 0x18, 0xa3, 0x67,
-0x67, 0x67, 0x01, 0x26, 0xe3, 0x1d, 0x69, 0x33, 0x66, 0x61, 0xe7, 0x61,
-0x1f, 0x73, 0x02, 0x23, 0xd3, 0x64, 0x17, 0x4b, 0xc0, 0x46, 0x13, 0x65,
-0xcb, 0x69, 0xc0, 0x46, 0x53, 0x65, 0xc3, 0x1d, 0x51, 0x33, 0xd3, 0x65,
-0x2b, 0x1d, 0x13, 0x66, 0x4b, 0x69, 0xc0, 0x46, 0x53, 0x66, 0x89, 0x69,
-0xc0, 0x46, 0x91, 0x66, 0x0f, 0x49, 0xc0, 0x46, 0xd1, 0x66, 0x16, 0x67,
-0x0f, 0x23, 0xdb, 0x01, 0xc0, 0x18, 0x90, 0x67, 0x56, 0x67, 0xd7, 0x61,
-0xd0, 0x1d, 0x69, 0x30, 0x56, 0x61, 0x07, 0x73,
+0xf0, 0xb5, 0x82, 0xb0, 0x14, 0x1c, 0x1f, 0x1c, 0x42, 0x02, 0x0a, 0x43,
+0x15, 0x1c, 0x01, 0x28, 0x54, 0xd0, 0x2c, 0x49, 0xc8, 0x6f, 0x20, 0x23,
+0x02, 0x68, 0x9a, 0x43, 0x02, 0x60, 0xc8, 0x6f, 0x40, 0x23, 0x01, 0x68,
+0x19, 0x43, 0x01, 0x60, 0x02, 0xf0, 0xe6, 0xf9, 0x53, 0x20, 0x02, 0xf0,
+0x43, 0xf9, 0x28, 0x0c, 0x06, 0x1c, 0x02, 0xf0, 0x3f, 0xf9, 0x28, 0x0a,
+0x01, 0x90, 0x00, 0x90, 0x02, 0xf0, 0x3a, 0xf9, 0x28, 0x1c, 0x02, 0xf0,
+0x37, 0xf9, 0x02, 0xf0, 0xbd, 0xf9, 0xff, 0xf7, 0x61, 0xff, 0x02, 0xf0,
+0xd1, 0xf9, 0x84, 0x20, 0x02, 0xf0, 0x2e, 0xf9, 0x30, 0x1c, 0x02, 0xf0,
+0x2b, 0xf9, 0x00, 0x98, 0x02, 0xf0, 0x28, 0xf9, 0x28, 0x1c, 0x02, 0xf0,
+0x25, 0xf9, 0x00, 0x2f, 0x05, 0xd9, 0x20, 0x78, 0x01, 0x34, 0x02, 0xf0,
+0x1f, 0xf9, 0x01, 0x3f, 0xf9, 0xd1, 0x02, 0xf0, 0xa3, 0xf9, 0x02, 0xf0,
+0xb9, 0xf9, 0x83, 0x20, 0x02, 0xf0, 0x16, 0xf9, 0x30, 0x1c, 0x02, 0xf0,
+0x13, 0xf9, 0x01, 0x98, 0x02, 0xf0, 0x10, 0xf9,
+0x28, 0x1c, 0x02, 0xf0, 0x0d, 0xf9, 0x02, 0xf0, 0x93, 0xf9, 0xff, 0xf7,
+0x37, 0xff, 0x07, 0x49, 0xc8, 0x6f, 0x40, 0x23, 0x02, 0x68, 0x9a, 0x43,
+0x02, 0x60, 0xc8, 0x6f, 0x20, 0x23, 0x01, 0x68, 0x19, 0x43, 0x01, 0x60,
+0x02, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x68, 0x0e, 0x00, 0x80,
+0x70, 0x47, 0x00, 0x00, 0x80, 0xb5, 0x01, 0xf0, 0x8f, 0xf8, 0x06, 0x4f,
+0xc0, 0x46, 0xf8, 0x60, 0x01, 0xf0, 0xf2, 0xf8, 0x78, 0x80, 0x01, 0xf0,
+0xb1, 0xf8, 0x38, 0x71, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00,
+0x68, 0x0e, 0x00, 0x80, 0x00, 0xb5, 0x01, 0xf0, 0x05, 0xf9, 0x02, 0x49,
+0xc0, 0x46, 0x08, 0x80, 0x08, 0xbc, 0x18, 0x47, 0x68, 0x0e, 0x00, 0x80,
+0x0b, 0x48, 0xc1, 0x68, 0x01, 0x29, 0x11, 0xd1, 0xc1, 0x6f, 0x02, 0x23,
+0x0a, 0x68, 0x1a, 0x43, 0x0a, 0x60, 0xc1, 0x6f, 0x80, 0x23, 0x0a, 0x68,
+0x1a, 0x43, 0x0a, 0x60, 0xc1, 0x18, 0x08, 0x68, 0x82, 0x23, 0x02, 0x68,
+0x1a, 0x43, 0x02, 0x60, 0x00, 0x20, 0x08, 0x81, 0x70, 0x47, 0x00, 0x00,
+0x68, 0x0e, 0x00, 0x80, 0xf0, 0xb4, 0x4a, 0x49, 0xca, 0x1d, 0x9d, 0x32,
+0x00, 0x20, 0x00, 0x27, 0x83, 0x00, 0xd7, 0x50, 0x01, 0x30, 0x17, 0x28,
+0xfa, 0xd3, 0x46, 0x4c, 0x00, 0x20, 0x82, 0x00, 0xa7, 0x50, 0x01, 0x30,
+0x20, 0x28, 0xfa, 0xd3, 0x43, 0x4a, 0x00, 0x20, 0x83, 0x00, 0xd7, 0x50,
+0x01, 0x30, 0x20, 0x28, 0xfa, 0xd3, 0xa7, 0x61, 0x97, 0x61, 0x4f, 0x65,
+0x8f, 0x65, 0x3f, 0x4d, 0xc0, 0x46, 0x2f, 0x60, 0x6f, 0x60, 0xaf, 0x60,
+0xaf, 0x61, 0xef, 0x60, 0x2f, 0x61, 0x6f, 0x61, 0x00, 0x20, 0xc1, 0x00,
+0x09, 0x18, 0x49, 0x01, 0x35, 0x4b, 0xc9, 0x18, 0x86, 0x00, 0xcb, 0x1d,
+0xf9, 0x33, 0x34, 0x4c, 0x34, 0x19, 0xe3, 0x63, 0x11, 0x23, 0x5b, 0x01,
+0xcb, 0x18, 0x63, 0x63, 0x0d, 0x23, 0x9b, 0x01, 0xcb, 0x18, 0xb4, 0x18,
+0xe3, 0x63, 0x23, 0x23, 0x5b, 0x01, 0xc9, 0x18, 0x61, 0x63, 0x01, 0x30,
+0x02, 0x28, 0xe4, 0xdb, 0x29, 0x48, 0xc1, 0x1d, 0xf9, 0x31, 0x29, 0x4c,
+0xc0, 0x46, 0xa1, 0x62, 0x61, 0x6b, 0x0d, 0x23, 0x9b, 0x01, 0xe1, 0x62,
+0xc1, 0x18, 0x91, 0x62, 0x51, 0x6b, 0xc0, 0x46, 0xd1, 0x62, 0x08, 0x21,
+0xe1, 0x64, 0x25, 0x49, 0xc0, 0x46, 0x21, 0x65, 0x24, 0x49, 0x0b, 0x69,
+0xc0, 0x46, 0x63, 0x65, 0xc3, 0x1d, 0x4d, 0x33, 0xe3, 0x65, 0x25, 0x66,
+0x8b, 0x68, 0xc0, 0x46, 0x63, 0x66, 0xcb, 0x68, 0xc0, 0x46, 0xa3, 0x66,
+0x1e, 0x4b, 0xc0, 0x46, 0xe3, 0x66, 0x27, 0x67, 0x0b, 0x23, 0xdb, 0x01,
+0xc3, 0x18, 0xa3, 0x67, 0x67, 0x67, 0x01, 0x26, 0xe3, 0x1d, 0x69, 0x33,
+0x66, 0x61, 0xe7, 0x61, 0x1f, 0x73, 0x02, 0x23, 0xd3, 0x64, 0x17, 0x4b,
+0xc0, 0x46, 0x13, 0x65, 0xcb, 0x69, 0xc0, 0x46, 0x53, 0x65, 0xc3, 0x1d,
+0x51, 0x33, 0xd3, 0x65, 0x2b, 0x1d, 0x13, 0x66, 0x4b, 0x69, 0xc0, 0x46,
+0x53, 0x66, 0x89, 0x69, 0xc0, 0x46, 0x91, 0x66, 0x0f, 0x49, 0xc0, 0x46,
+0xd1, 0x66, 0x16, 0x67, 0x0f, 0x23, 0xdb, 0x01, 0xc0, 0x18, 0x90, 0x67,
+0x56, 0x67, 0xd7, 0x61, 0xd0, 0x1d, 0x69, 0x30, 0x56, 0x61, 0x07, 0x73,
0xf0, 0xbc, 0x70, 0x47, 0x68, 0x0e, 0x00, 0x80, 0xe4, 0x2c, 0x00, 0x80,
-0x64, 0x2d, 0x00, 0x80, 0x3c, 0xef, 0x20, 0x40, 0x30, 0x01, 0x18, 0x00,
-0x7c, 0x29, 0x00, 0x80, 0xec, 0x54, 0xff, 0xff, 0x38, 0x01, 0x18, 0x00,
-0xfc, 0x54, 0xff, 0xff, 0x90, 0xb4, 0x00, 0x21, 0x1e, 0x4a, 0xbb, 0x23,
-0x1b, 0x01, 0xd7, 0x18, 0xf9, 0x73, 0x19, 0x23, 0xdb, 0x01, 0xd0, 0x18,
-0x01, 0x24, 0xcd, 0x23, 0x1b, 0x01, 0xd3, 0x18, 0xc1, 0x61, 0x1c, 0x70,
-0x33, 0x23, 0x9b, 0x01, 0xd3, 0x18, 0x99, 0x60, 0xb9, 0x73, 0x59, 0x61,
-0x2f, 0x23, 0x9b, 0x01, 0xd3, 0x18, 0x19, 0x60, 0x13, 0x4b, 0x51, 0x27,
-0xbf, 0x03, 0x03, 0x63, 0x3b, 0x60, 0x84, 0x69, 0xe4, 0x18, 0x44, 0x63,
-0x04, 0x3c, 0x7c, 0x60, 0x01, 0x24, 0xe4, 0x02, 0x84, 0x63, 0x0e, 0x4c,
-0xc0, 0x46, 0xbc, 0x60, 0x04, 0x6b, 0xc0, 0x46, 0x44, 0x62, 0x84, 0x69,
-0xe4, 0x18, 0x0b, 0x4b, 0xe3, 0x18, 0xfb, 0x60, 0x03, 0x6b, 0xc0, 0x46,
-0x83, 0x62, 0x43, 0x6a, 0xc0, 0x46, 0x03, 0x62, 0xc1, 0x63, 0x51, 0x64,
-0x91, 0x64, 0xd1, 0x65, 0xd1, 0x66, 0x90, 0xbc, 0x70, 0x47, 0x00, 0x00,
-0x68, 0x0e, 0x00, 0x80, 0x00, 0x00, 0x20, 0x40, 0xfc, 0x07, 0x00, 0x00,
-0xfc, 0xf7, 0xff, 0xff, 0x90, 0xb4, 0x00, 0x22, 0x1b, 0x49, 0xc9, 0x23,
-0x1b, 0x01, 0xc8, 0x18, 0x02, 0x71, 0x01, 0x20, 0xbb, 0x23, 0x1b, 0x01,
-0xcb, 0x18, 0x58, 0x73, 0x17, 0x48, 0x03, 0x1c, 0x00, 0x27, 0xdc, 0x1d,
-0xc1, 0x34, 0x1c, 0x65, 0x23, 0x1c, 0x01, 0x37, 0x3f, 0x2f, 0xf8, 0xd3,
-0x1a, 0x65, 0x19, 0x23, 0xdb, 0x01, 0xcf, 0x18, 0x33, 0x23, 0x9b, 0x01,
-0xcb, 0x18, 0x3a, 0x61, 0x98, 0x61, 0x40, 0x20, 0xf8, 0x60, 0xda, 0x61,
-0x1a, 0x62, 0xca, 0x64, 0x0a, 0x66, 0x0c, 0x48, 0xc0, 0x46, 0xc2, 0x60,
-0x0b, 0x48, 0x00, 0x6b, 0xc0, 0x06, 0xc0, 0x0e, 0xf8, 0x63, 0x0a, 0x48,
-0x01, 0x68, 0xc0, 0x46, 0x19, 0x80, 0x41, 0x68, 0xc0, 0x46, 0x59, 0x80,
-0x80, 0x68, 0xc0, 0x46, 0x98, 0x80, 0x90, 0xbc, 0x70, 0x47, 0x00, 0x00,
-0x68, 0x0e, 0x00, 0x80, 0x3c, 0xbd, 0x20, 0x40, 0x3c, 0xef, 0x20, 0x40,
-0x80, 0x00, 0x14, 0x40, 0x40, 0x00, 0x14, 0x40, 0x00, 0x20, 0x0a, 0x49,
-0xc0, 0x46, 0x08, 0x73, 0xcb, 0x1d, 0xff, 0x33, 0x3a, 0x33, 0x88, 0x61,
-0xc8, 0x61, 0x18, 0x70, 0x06, 0x4a, 0xc0, 0x46, 0x10, 0x65, 0x50, 0x66,
-0x90, 0x66, 0x08, 0x70, 0x58, 0x70, 0xbb, 0x23, 0x1b, 0x01, 0xd1, 0x18,
-0x08, 0x73, 0x70, 0x47, 0x28, 0x05, 0x00, 0x80, 0x68, 0x0e, 0x00, 0x80,
-0xf0, 0xb4, 0x2f, 0x49, 0x2f, 0x4a, 0xc0, 0x46, 0x11, 0x61, 0x01, 0x23,
-0x9b, 0x02, 0xc8, 0x18, 0x50, 0x61, 0x2d, 0x48, 0xc0, 0x46, 0x10, 0x62,
-0xdb, 0x00, 0xc3, 0x18, 0x53, 0x62, 0x00, 0x23, 0x13, 0x63, 0x53, 0x63,
-0x29, 0x4a, 0x2a, 0x4f, 0xd4, 0x1d, 0xff, 0x34, 0xfa, 0x34, 0x14, 0xc7,
-0x08, 0x3f, 0x3b, 0x61, 0x1c, 0x1f, 0x7c, 0x61, 0x26, 0x4f, 0xc0, 0x46,
-0x39, 0x60, 0xb8, 0x61, 0x79, 0x61, 0xf8, 0x62, 0x3b, 0x63, 0x7b, 0x64,
-0xba, 0x64, 0xfa, 0x65, 0x22, 0x4f, 0xfe, 0x1d, 0xf9, 0x36, 0x22, 0x4d,
-0xec, 0x1d, 0x79, 0x34, 0x26, 0x62, 0x51, 0x26, 0xb6, 0x03, 0x37, 0x61,
-0x24, 0x6a, 0xc0, 0x46, 0x74, 0x61, 0x2f, 0x67, 0x1d, 0x4d, 0x09, 0x27,
-0x7f, 0x04, 0xec, 0x1d, 0x75, 0x34, 0x7c, 0x60, 0x3d, 0x60, 0x1b, 0x4c,
-0xc0, 0x46, 0x3c, 0x61, 0xe6, 0x1d, 0x75, 0x36, 0x7e, 0x61, 0x19, 0x4f,
-0xc0, 0x46, 0x7c, 0x60, 0x3d, 0x60, 0x0f, 0x1c,
+0x64, 0x2d, 0x00, 0x80, 0x90, 0xee, 0x20, 0x40, 0x30, 0x01, 0x18, 0x00,
+0x7c, 0x29, 0x00, 0x80, 0x00, 0x55, 0xff, 0xff, 0x38, 0x01, 0x18, 0x00,
+0x10, 0x55, 0xff, 0xff, 0x90, 0xb4, 0x00, 0x21, 0x1e, 0x4a, 0xbb, 0x23,
+0x1b, 0x01, 0xd7, 0x18, 0xf9, 0x73, 0x19, 0x23,
+0xdb, 0x01, 0xd0, 0x18, 0x01, 0x24, 0xcd, 0x23, 0x1b, 0x01, 0xd3, 0x18,
+0xc1, 0x61, 0x1c, 0x70, 0x33, 0x23, 0x9b, 0x01, 0xd3, 0x18, 0x99, 0x60,
+0xb9, 0x73, 0x59, 0x61, 0x2f, 0x23, 0x9b, 0x01, 0xd3, 0x18, 0x19, 0x60,
+0x13, 0x4b, 0x51, 0x27, 0xbf, 0x03, 0x03, 0x63, 0x3b, 0x60, 0x84, 0x69,
+0xe4, 0x18, 0x44, 0x63, 0x04, 0x3c, 0x7c, 0x60, 0x01, 0x24, 0xe4, 0x02,
+0x84, 0x63, 0x0e, 0x4c, 0xc0, 0x46, 0xbc, 0x60, 0x04, 0x6b, 0xc0, 0x46,
+0x44, 0x62, 0x84, 0x69, 0xe4, 0x18, 0x0b, 0x4b, 0xe3, 0x18, 0xfb, 0x60,
+0x03, 0x6b, 0xc0, 0x46, 0x83, 0x62, 0x43, 0x6a, 0xc0, 0x46, 0x03, 0x62,
+0xc1, 0x63, 0x51, 0x64, 0x91, 0x64, 0xd1, 0x65, 0xd1, 0x66, 0x90, 0xbc,
+0x70, 0x47, 0x00, 0x00, 0x68, 0x0e, 0x00, 0x80, 0x00, 0x00, 0x20, 0x40,
+0xfc, 0x07, 0x00, 0x00, 0xfc, 0xf7, 0xff, 0xff, 0x90, 0xb4, 0x00, 0x22,
+0x1b, 0x49, 0xc9, 0x23, 0x1b, 0x01, 0xc8, 0x18, 0x02, 0x71, 0x01, 0x20,
+0xbb, 0x23, 0x1b, 0x01, 0xcb, 0x18, 0x58, 0x73, 0x17, 0x48, 0x03, 0x1c,
+0x00, 0x27, 0xdc, 0x1d, 0xc1, 0x34, 0x1c, 0x65, 0x23, 0x1c, 0x01, 0x37,
+0x3f, 0x2f, 0xf8, 0xd3, 0x1a, 0x65, 0x19, 0x23, 0xdb, 0x01, 0xcf, 0x18,
+0x33, 0x23, 0x9b, 0x01, 0xcb, 0x18, 0x3a, 0x61, 0x98, 0x61, 0x40, 0x20,
+0xf8, 0x60, 0xda, 0x61, 0x1a, 0x62, 0xca, 0x64, 0x0a, 0x66, 0x0c, 0x48,
+0xc0, 0x46, 0xc2, 0x60, 0x0b, 0x48, 0x00, 0x6b, 0xc0, 0x06, 0xc0, 0x0e,
+0xf8, 0x63, 0x0a, 0x48, 0x01, 0x68, 0xc0, 0x46, 0x19, 0x80, 0x41, 0x68,
+0xc0, 0x46, 0x59, 0x80, 0x80, 0x68, 0xc0, 0x46, 0x98, 0x80, 0x90, 0xbc,
+0x70, 0x47, 0x00, 0x00, 0x68, 0x0e, 0x00, 0x80, 0x90, 0xbc, 0x20, 0x40,
+0x90, 0xee, 0x20, 0x40, 0x80, 0x00, 0x14, 0x40, 0x40, 0x00, 0x14, 0x40,
+0x00, 0x20, 0x0a, 0x49, 0xc0, 0x46, 0x08, 0x73, 0xcb, 0x1d, 0xff, 0x33,
+0x3a, 0x33, 0x88, 0x61, 0xc8, 0x61, 0x18, 0x70, 0x06, 0x4a, 0xc0, 0x46,
+0x10, 0x65, 0x50, 0x66, 0x90, 0x66, 0x08, 0x70, 0x58, 0x70, 0xbb, 0x23,
+0x1b, 0x01, 0xd1, 0x18, 0x08, 0x73, 0x70, 0x47, 0x28, 0x05, 0x00, 0x80,
+0x68, 0x0e, 0x00, 0x80, 0xf0, 0xb4, 0x2f, 0x49, 0x2f, 0x4a, 0xc0, 0x46,
+0x11, 0x61, 0x01, 0x23, 0x9b, 0x02, 0xc8, 0x18, 0x50, 0x61, 0x2d, 0x48,
+0xc0, 0x46, 0x10, 0x62, 0xdb, 0x00, 0xc3, 0x18, 0x53, 0x62, 0x00, 0x23,
+0x13, 0x63, 0x53, 0x63, 0x29, 0x4a, 0x2a, 0x4f, 0xd4, 0x1d, 0xff, 0x34,
+0xfa, 0x34, 0x14, 0xc7, 0x08, 0x3f, 0x3b, 0x61, 0x1c, 0x1f, 0x7c, 0x61,
+0x26, 0x4f, 0xc0, 0x46, 0x39, 0x60, 0xb8, 0x61, 0x79, 0x61, 0xf8, 0x62,
+0x3b, 0x63, 0x7b, 0x64, 0xba, 0x64, 0xfa, 0x65, 0x22, 0x4f, 0xfe, 0x1d,
+0xf9, 0x36, 0x22, 0x4d, 0xec, 0x1d, 0x79, 0x34, 0x26, 0x62, 0x51, 0x26,
+0xb6, 0x03, 0x37, 0x61, 0x24, 0x6a, 0xc0, 0x46, 0x74, 0x61, 0x2f, 0x67,
+0x1d, 0x4d, 0x09, 0x27, 0x7f, 0x04, 0xec, 0x1d, 0x75, 0x34, 0x7c, 0x60,
+0x3d, 0x60, 0x1b, 0x4c, 0xc0, 0x46, 0x3c, 0x61, 0xe6, 0x1d, 0x75, 0x36,
+0x7e, 0x61, 0x19, 0x4f, 0xc0, 0x46, 0x7c, 0x60, 0x3d, 0x60, 0x0f, 0x1c,
0x00, 0x21, 0xff, 0x24, 0x01, 0x34, 0x1d, 0x1c, 0x8b, 0x00, 0xfd, 0x50,
0x01, 0x31, 0xa1, 0x42, 0xfa, 0xd3, 0x01, 0x1c, 0x00, 0x20, 0x01, 0x27,
0xff, 0x02, 0x83, 0x00, 0xcd, 0x50, 0x01, 0x30, 0xb8, 0x42, 0xfa, 0xd3,
0x00, 0x20, 0x81, 0x00, 0x55, 0x50, 0x01, 0x30, 0x80, 0x28, 0xfa, 0xd3,
-0xf0, 0xbc, 0x70, 0x47, 0x24, 0xa3, 0x20, 0x40, 0x40, 0x01, 0x18, 0x00,
-0x24, 0x83, 0x20, 0x40, 0x24, 0xa9, 0x20, 0x40, 0x80, 0x01, 0x18, 0x00,
-0xa8, 0x03, 0x00, 0x80, 0x24, 0xa7, 0x20, 0x40, 0x68, 0x0e, 0x00, 0x80,
-0x24, 0xa8, 0x20, 0x40, 0xa4, 0xa8, 0x20, 0x40, 0x08, 0x04, 0x00, 0x80,
-0xb8, 0xb5, 0x2c, 0x48, 0xfc, 0xf7, 0x0a, 0xff, 0x01, 0x20, 0x2b, 0x49,
-0x0a, 0x68, 0x52, 0x0c, 0x06, 0xd2, 0x0a, 0x68, 0x12, 0x0c, 0x02, 0xd1,
-0x0a, 0x68, 0x92, 0x0a, 0x00, 0xd2, 0x00, 0x20, 0x04, 0x06, 0x24, 0x0e,
-0x25, 0x4a, 0xd7, 0x1d, 0x0d, 0x37, 0x00, 0x23, 0x00, 0x20, 0x9d, 0x00,
-0x78, 0x51, 0x01, 0x33, 0x04, 0x2b, 0xfa, 0xd3, 0x01, 0x27, 0x3f, 0x05,
-0x50, 0x61, 0xf8, 0x60, 0xd0, 0x61, 0xf8, 0x61, 0x00, 0x23, 0xdb, 0x43,
-0x93, 0x61, 0x3b, 0x61, 0x13, 0x62, 0x3b, 0x62, 0x00, 0x27, 0x1b, 0x4b,
-0x8d, 0x68, 0xc0, 0x46, 0x00, 0x95, 0x8d, 0x69, 0xc0, 0x46, 0x00, 0x95,
-0x00, 0x2c, 0x0b, 0xd0, 0xdd, 0x6b, 0xc0, 0x46, 0x00, 0x95, 0x9d, 0x6b,
-0xc0, 0x46, 0x00, 0x95, 0x5d, 0x6b, 0xc0, 0x46, 0x00, 0x95, 0x1d, 0x6b,
-0xc0, 0x46, 0x00, 0x95, 0x01, 0x37, 0x40, 0x2f, 0xe8, 0xd3, 0x00, 0x27,
-0x6c, 0x46, 0x01, 0x23, 0x5b, 0x07, 0x1c, 0x43, 0x01, 0xe0, 0x20, 0x60,
-0x01, 0x37, 0x0d, 0x68, 0x2b, 0x09, 0x02, 0xd2, 0x80, 0x2f, 0xf8, 0xd3,
-0x01, 0xe0, 0x80, 0x2f, 0x03, 0xd3, 0x08, 0x49, 0x4b, 0x6e, 0x01, 0x33,
-0x4b, 0x66, 0xd0, 0x62, 0xb8, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00,
-0xf4, 0x01, 0xff, 0xff, 0x00, 0x00, 0x10, 0x40, 0x68, 0x0e, 0x00, 0x80,
-0x00, 0x01, 0x18, 0x40, 0xa0, 0x82, 0x20, 0x40, 0x90, 0xb4, 0x00, 0x21,
-0x0e, 0x4f, 0x0f, 0x4a, 0x00, 0x20, 0x4c, 0x01, 0x64, 0x1a, 0xa4, 0x00,
-0xa3, 0x18, 0x58, 0x60, 0x98, 0x60, 0x18, 0x64, 0x58, 0x64, 0x10, 0x53,
-0x58, 0x80, 0xcc, 0x00, 0xe4, 0x19, 0x98, 0x67, 0xdc, 0x62, 0x01, 0x31,
-0x03, 0x29, 0xee, 0xd3, 0x06, 0x49, 0xc0, 0x46, 0x08, 0x60, 0x48, 0x60,
-0x88, 0x60, 0xc8, 0x60, 0x08, 0x61, 0x90, 0xbc, 0x70, 0x47, 0x00, 0x00,
-0x58, 0x67, 0x21, 0x40, 0x5c, 0x2b, 0x00, 0x80, 0xd0, 0x2c, 0x00, 0x80,
-0x64, 0x21, 0x05, 0x48, 0xc0, 0x46, 0x01, 0x63, 0x00, 0x21, 0xc9, 0x43,
-0x41, 0x63, 0x81, 0x63, 0x00, 0x21, 0xc1, 0x63, 0x01, 0x64, 0x70, 0x47,
-0x68, 0x0e, 0x00, 0x80, 0x80, 0xb4, 0x01, 0x20, 0x40, 0x02, 0x0a, 0x49,
-0xc0, 0x46, 0x08, 0x60, 0x3c, 0x20, 0x48, 0x60, 0x88, 0x60, 0x08, 0x48,
-0xc0, 0x46, 0xc8, 0x60, 0x00, 0x20, 0x07, 0x4a, 0x87, 0x00, 0xcb, 0x68,
-0xc0, 0x46, 0xda, 0x51, 0x01, 0x30, 0x10, 0x28, 0xf8, 0xd3, 0x80, 0xbc,
-0x70, 0x47, 0x00, 0x00, 0xe4, 0x2d, 0x00, 0x80, 0xf4, 0x2d, 0x00, 0x80,
-0x49, 0x4c, 0xff, 0xff, 0x12, 0x49, 0x13, 0x48, 0x67, 0x23, 0x9b, 0x01,
-0xca, 0x18, 0x06, 0xc0, 0x08, 0x38, 0x11, 0x4b, 0xca, 0x18, 0xc1, 0x60,
-0x82, 0x60, 0x01, 0x61, 0x0f, 0x49, 0x10, 0x48, 0xa7, 0x23, 0x9b, 0x01,
-0xca, 0x18, 0x06, 0xc0, 0x08, 0x38, 0x0e, 0x4b, 0xca, 0x18, 0xc1, 0x60,
-0x82, 0x60, 0x01, 0x61, 0x0c, 0x48, 0x0d, 0x49,
+0xf0, 0xbc, 0x70, 0x47, 0x24, 0xa3, 0x20, 0x40,
+0x40, 0x01, 0x18, 0x00, 0x24, 0x83, 0x20, 0x40, 0x24, 0xa9, 0x20, 0x40,
+0x80, 0x01, 0x18, 0x00, 0xa8, 0x03, 0x00, 0x80, 0x24, 0xa7, 0x20, 0x40,
+0x68, 0x0e, 0x00, 0x80, 0x24, 0xa8, 0x20, 0x40, 0xa4, 0xa8, 0x20, 0x40,
+0x08, 0x04, 0x00, 0x80, 0xb8, 0xb5, 0x2c, 0x48, 0xfd, 0xf7, 0xba, 0xfd,
+0x01, 0x20, 0x2b, 0x49, 0x0a, 0x68, 0x52, 0x0c, 0x06, 0xd2, 0x0a, 0x68,
+0x12, 0x0c, 0x02, 0xd1, 0x0a, 0x68, 0x92, 0x0a, 0x00, 0xd2, 0x00, 0x20,
+0x04, 0x06, 0x24, 0x0e, 0x25, 0x4a, 0xd7, 0x1d, 0x0d, 0x37, 0x00, 0x23,
+0x00, 0x20, 0x9d, 0x00, 0x78, 0x51, 0x01, 0x33, 0x04, 0x2b, 0xfa, 0xd3,
+0x01, 0x27, 0x3f, 0x05, 0x50, 0x61, 0xf8, 0x60, 0xd0, 0x61, 0xf8, 0x61,
+0x00, 0x23, 0xdb, 0x43, 0x93, 0x61, 0x3b, 0x61, 0x13, 0x62, 0x3b, 0x62,
+0x00, 0x27, 0x1b, 0x4b, 0x8d, 0x68, 0xc0, 0x46, 0x00, 0x95, 0x8d, 0x69,
+0xc0, 0x46, 0x00, 0x95, 0x00, 0x2c, 0x0b, 0xd0, 0xdd, 0x6b, 0xc0, 0x46,
+0x00, 0x95, 0x9d, 0x6b, 0xc0, 0x46, 0x00, 0x95, 0x5d, 0x6b, 0xc0, 0x46,
+0x00, 0x95, 0x1d, 0x6b, 0xc0, 0x46, 0x00, 0x95, 0x01, 0x37, 0x40, 0x2f,
+0xe8, 0xd3, 0x00, 0x27, 0x6c, 0x46, 0x01, 0x23, 0x5b, 0x07, 0x1c, 0x43,
+0x01, 0xe0, 0x20, 0x60, 0x01, 0x37, 0x0d, 0x68, 0x2b, 0x09, 0x02, 0xd2,
+0x80, 0x2f, 0xf8, 0xd3, 0x01, 0xe0, 0x80, 0x2f, 0x03, 0xd3, 0x08, 0x49,
+0x4b, 0x6e, 0x01, 0x33, 0x4b, 0x66, 0xd0, 0x62, 0xb8, 0xbc, 0x08, 0xbc,
+0x18, 0x47, 0x00, 0x00, 0xf4, 0x01, 0xff, 0xff, 0x00, 0x00, 0x10, 0x40,
+0x68, 0x0e, 0x00, 0x80, 0x00, 0x01, 0x18, 0x40, 0xa0, 0x82, 0x20, 0x40,
+0x90, 0xb4, 0x00, 0x21, 0x0e, 0x4f, 0x0f, 0x4a, 0x00, 0x20, 0x4c, 0x01,
+0x64, 0x1a, 0xa4, 0x00, 0xa3, 0x18, 0x58, 0x60, 0x98, 0x60, 0x18, 0x64,
+0x58, 0x64, 0x10, 0x53, 0x58, 0x80, 0xcc, 0x00, 0xe4, 0x19, 0x98, 0x67,
+0xdc, 0x62, 0x01, 0x31, 0x03, 0x29, 0xee, 0xd3, 0x06, 0x49, 0xc0, 0x46,
+0x08, 0x60, 0x48, 0x60, 0x88, 0x60, 0xc8, 0x60, 0x08, 0x61, 0x90, 0xbc,
+0x70, 0x47, 0x00, 0x00, 0xac, 0x66, 0x21, 0x40, 0x5c, 0x2b, 0x00, 0x80,
+0xd0, 0x2c, 0x00, 0x80, 0x64, 0x21, 0x05, 0x48, 0xc0, 0x46, 0x01, 0x63,
+0x00, 0x21, 0xc9, 0x43, 0x41, 0x63, 0x81, 0x63, 0x00, 0x21, 0xc1, 0x63,
+0x01, 0x64, 0x70, 0x47, 0x68, 0x0e, 0x00, 0x80, 0x80, 0xb4, 0x01, 0x20,
+0x40, 0x02, 0x0a, 0x49, 0xc0, 0x46, 0x08, 0x60, 0x3c, 0x20, 0x48, 0x60,
+0x88, 0x60, 0x08, 0x48, 0xc0, 0x46, 0xc8, 0x60, 0x00, 0x20, 0x07, 0x4a,
+0x87, 0x00, 0xcb, 0x68, 0xc0, 0x46, 0xda, 0x51, 0x01, 0x30, 0x10, 0x28,
+0xf8, 0xd3, 0x80, 0xbc, 0x70, 0x47, 0x00, 0x00, 0xe4, 0x2d, 0x00, 0x80,
+0xf4, 0x2d, 0x00, 0x80, 0x5d, 0x4c, 0xff, 0xff, 0x12, 0x49, 0x13, 0x48,
+0x67, 0x23, 0x9b, 0x01, 0xca, 0x18, 0x06, 0xc0, 0x08, 0x38, 0x11, 0x4b,
+0xca, 0x18, 0xc1, 0x60, 0x82, 0x60, 0x01, 0x61, 0x0f, 0x49, 0x10, 0x48,
+0xa7, 0x23, 0x9b, 0x01, 0xca, 0x18, 0x06, 0xc0, 0x08, 0x38, 0x0e, 0x4b,
+0xca, 0x18, 0xc1, 0x60, 0x82, 0x60, 0x01, 0x61, 0x0c, 0x48, 0x0d, 0x49,
0x67, 0x23, 0x9b, 0x01, 0xc2, 0x18, 0x05, 0xc1, 0x08, 0x39, 0x05, 0x4b,
0xc2, 0x18, 0xc8, 0x60, 0x8a, 0x60, 0x08, 0x61, 0x70, 0x47, 0x00, 0x00,
-0x58, 0x1f, 0x21, 0x40, 0x48, 0x2e, 0x00, 0x80, 0xfc, 0x1f, 0x00, 0x00,
-0x58, 0xef, 0x20, 0x40, 0x34, 0x2e, 0x00, 0x80, 0xfc, 0x2f, 0x00, 0x00,
-0x58, 0x3f, 0x21, 0x40, 0x5c, 0x2e, 0x00, 0x80, 0x90, 0xb4, 0x00, 0x21,
-0x40, 0x4c, 0x00, 0x20, 0x0a, 0x01, 0x12, 0x19, 0x19, 0x23, 0xdb, 0x01,
-0xd2, 0x18, 0xd0, 0x62, 0x10, 0x63, 0x50, 0x63, 0x90, 0x63, 0x01, 0x31,
-0x03, 0x29, 0xf3, 0xd3, 0x3a, 0x49, 0xc0, 0x46, 0x08, 0x63, 0x48, 0x63,
-0x88, 0x63, 0x20, 0x60, 0x01, 0x21, 0xe3, 0x1d, 0x59, 0x33, 0x60, 0x60,
-0x19, 0x71, 0x18, 0x72, 0x98, 0x71, 0x98, 0x72, 0x59, 0x71, 0x58, 0x72,
-0xd8, 0x71, 0xd8, 0x72, 0xe2, 0x1d, 0x49, 0x32, 0x11, 0x73, 0x19, 0x70,
-0x90, 0x73, 0x98, 0x70, 0x51, 0x73, 0x59, 0x70, 0xd0, 0x73, 0xd8, 0x70,
-0x11, 0x71, 0x11, 0x72, 0x90, 0x71, 0x90, 0x72, 0x50, 0x71, 0x50, 0x72,
-0xd0, 0x71, 0xd0, 0x72, 0x18, 0x73, 0x02, 0x22, 0xe7, 0x1d, 0x69, 0x37,
-0x3a, 0x70, 0x99, 0x73, 0xba, 0x70, 0x58, 0x73, 0x78, 0x70, 0xd8, 0x73,
-0xf8, 0x70, 0x39, 0x71, 0x3a, 0x72, 0xb9, 0x71, 0xb9, 0x72, 0x78, 0x71,
-0x7a, 0x72, 0xf9, 0x71, 0xf9, 0x72, 0x39, 0x73, 0xe3, 0x1d, 0x79, 0x33,
-0x1a, 0x70, 0xb9, 0x73, 0x99, 0x70, 0x78, 0x73, 0x5a, 0x70, 0xf9, 0x73,
-0xd9, 0x70, 0x1a, 0x71, 0x1a, 0x72, 0x99, 0x71, 0x9a, 0x72, 0x58, 0x71,
-0x5a, 0x72, 0xd9, 0x71, 0xda, 0x72, 0x19, 0x73, 0xe7, 0x1d, 0x89, 0x37,
-0x3a, 0x70, 0x99, 0x73, 0xb9, 0x70, 0x58, 0x73, 0x7a, 0x70, 0xd9, 0x73,
-0xf9, 0x70, 0x39, 0x71, 0x3a, 0x72, 0xb9, 0x71, 0xb9, 0x72, 0x78, 0x71,
-0x7a, 0x72, 0xf9, 0x71, 0xf9, 0x72, 0x3a, 0x73, 0xe3, 0x1d, 0x99, 0x33,
-0x1a, 0x70, 0xb9, 0x73, 0x9a, 0x70, 0x78, 0x73, 0x5a, 0x70, 0xf9, 0x73,
-0xda, 0x70, 0x19, 0x71, 0x1a, 0x72, 0x99, 0x71, 0x99, 0x72, 0x58, 0x71,
-0x5a, 0x72, 0xd9, 0x71, 0xd9, 0x72, 0x20, 0x61, 0xe0, 0x60, 0x60, 0x61,
-0xa0, 0x60, 0x90, 0xbc, 0x70, 0x47, 0x00, 0x00, 0xa0, 0x1c, 0x00, 0x80,
-0xe8, 0x19, 0x00, 0x80, 0x81, 0x20, 0x00, 0x02, 0x01, 0x49, 0xc0, 0x46,
-0x88, 0x62, 0x70, 0x47, 0xc0, 0x00, 0x14, 0x00, 0x09, 0x49, 0x0a, 0x4b,
-0xc8, 0x18, 0x04, 0x3b, 0xc9, 0x18, 0x08, 0x60, 0x00, 0x21, 0xc2, 0x1d,
-0x29, 0x32, 0xc2, 0x61, 0x10, 0x1c, 0x01, 0x31, 0x08, 0x29, 0xf8, 0xd3,
-0xc1, 0x1f, 0x29, 0x39, 0x00, 0x20, 0xc8, 0x61, 0x70, 0x47, 0x00, 0x00,
-0x68, 0x0e, 0x00, 0x80, 0x84, 0x09, 0x00, 0x00, 0x06, 0x48, 0x07, 0x49,
-0xc0, 0x46, 0x08, 0x80, 0x48, 0x80, 0x00, 0x20, 0x88, 0x80, 0xc8, 0x80,
-0x88, 0x60, 0x04, 0x49, 0xc0, 0x46, 0x48, 0x61, 0x88, 0x61, 0x70, 0x47,
-0xff, 0xff, 0x00, 0x00, 0x4c, 0x2a, 0x00, 0x80, 0x6c, 0x06, 0x00, 0x80,
-0x00, 0x21, 0x06, 0x48, 0xc2, 0x1d, 0x19, 0x32, 0xc1, 0x60, 0x01, 0x61,
-0xc1, 0x61, 0x01, 0x62, 0x11, 0x71, 0xff, 0x30, 0x01, 0x30, 0x41, 0x62,
-0x70, 0x47, 0x00, 0x00, 0x6c, 0x06, 0x00, 0x80, 0x09, 0x48, 0x0a, 0x4b,
-0xc0, 0x46, 0x18, 0x60, 0x00, 0x21, 0xc2, 0x1d, 0x4d, 0x32, 0xc2, 0x60,
-0x10, 0x1c, 0x01, 0x31, 0x14, 0x29, 0xf8, 0xd3, 0xc1, 0x1f, 0x4d, 0x39,
-0x00, 0x20, 0xc8, 0x60, 0x58, 0x60, 0x98, 0x60, 0x70, 0x47, 0x00, 0x00,
-0xd8, 0x07, 0x00, 0x80, 0x6c, 0x06, 0x00, 0x80,
-0x00, 0xb5, 0x0b, 0x49, 0x0b, 0x48, 0xfc, 0xf7, 0x3a, 0xfd, 0x0b, 0x48,
+0xac, 0x1e, 0x21, 0x40, 0x48, 0x2e, 0x00, 0x80, 0xfc, 0x1f, 0x00, 0x00,
+0xac, 0xee, 0x20, 0x40, 0x34, 0x2e, 0x00, 0x80, 0xfc, 0x2f, 0x00, 0x00,
+0xac, 0x3e, 0x21, 0x40, 0x5c, 0x2e, 0x00, 0x80,
+0x90, 0xb4, 0x00, 0x21, 0x40, 0x4c, 0x00, 0x20, 0x0a, 0x01, 0x12, 0x19,
+0x19, 0x23, 0xdb, 0x01, 0xd2, 0x18, 0xd0, 0x62, 0x10, 0x63, 0x50, 0x63,
+0x90, 0x63, 0x01, 0x31, 0x03, 0x29, 0xf3, 0xd3, 0x3a, 0x49, 0xc0, 0x46,
+0x08, 0x63, 0x48, 0x63, 0x88, 0x63, 0x20, 0x60, 0x01, 0x21, 0xe3, 0x1d,
+0x59, 0x33, 0x60, 0x60, 0x19, 0x71, 0x18, 0x72, 0x98, 0x71, 0x98, 0x72,
+0x59, 0x71, 0x58, 0x72, 0xd8, 0x71, 0xd8, 0x72, 0xe2, 0x1d, 0x49, 0x32,
+0x11, 0x73, 0x19, 0x70, 0x90, 0x73, 0x98, 0x70, 0x51, 0x73, 0x59, 0x70,
+0xd0, 0x73, 0xd8, 0x70, 0x11, 0x71, 0x11, 0x72, 0x90, 0x71, 0x90, 0x72,
+0x50, 0x71, 0x50, 0x72, 0xd0, 0x71, 0xd0, 0x72, 0x18, 0x73, 0x02, 0x22,
+0xe7, 0x1d, 0x69, 0x37, 0x3a, 0x70, 0x99, 0x73, 0xba, 0x70, 0x58, 0x73,
+0x78, 0x70, 0xd8, 0x73, 0xf8, 0x70, 0x39, 0x71, 0x3a, 0x72, 0xb9, 0x71,
+0xb9, 0x72, 0x78, 0x71, 0x7a, 0x72, 0xf9, 0x71, 0xf9, 0x72, 0x39, 0x73,
+0xe3, 0x1d, 0x79, 0x33, 0x1a, 0x70, 0xb9, 0x73, 0x99, 0x70, 0x78, 0x73,
+0x5a, 0x70, 0xf9, 0x73, 0xd9, 0x70, 0x1a, 0x71, 0x1a, 0x72, 0x99, 0x71,
+0x9a, 0x72, 0x58, 0x71, 0x5a, 0x72, 0xd9, 0x71, 0xda, 0x72, 0x19, 0x73,
+0xe7, 0x1d, 0x89, 0x37, 0x3a, 0x70, 0x99, 0x73, 0xb9, 0x70, 0x58, 0x73,
+0x7a, 0x70, 0xd9, 0x73, 0xf9, 0x70, 0x39, 0x71, 0x3a, 0x72, 0xb9, 0x71,
+0xb9, 0x72, 0x78, 0x71, 0x7a, 0x72, 0xf9, 0x71, 0xf9, 0x72, 0x3a, 0x73,
+0xe3, 0x1d, 0x99, 0x33, 0x1a, 0x70, 0xb9, 0x73, 0x9a, 0x70, 0x78, 0x73,
+0x5a, 0x70, 0xf9, 0x73, 0xda, 0x70, 0x19, 0x71, 0x1a, 0x72, 0x99, 0x71,
+0x99, 0x72, 0x58, 0x71, 0x5a, 0x72, 0xd9, 0x71, 0xd9, 0x72, 0x20, 0x61,
+0xe0, 0x60, 0x60, 0x61, 0xa0, 0x60, 0x90, 0xbc, 0x70, 0x47, 0x00, 0x00,
+0xa0, 0x1c, 0x00, 0x80, 0xe8, 0x19, 0x00, 0x80, 0x81, 0x20, 0x00, 0x02,
+0x01, 0x49, 0xc0, 0x46, 0x88, 0x62, 0x70, 0x47, 0xc0, 0x00, 0x14, 0x00,
+0x09, 0x49, 0x0a, 0x4b, 0xc8, 0x18, 0x04, 0x3b, 0xc9, 0x18, 0x08, 0x60,
+0x00, 0x21, 0xc2, 0x1d, 0x29, 0x32, 0xc2, 0x61, 0x10, 0x1c, 0x01, 0x31,
+0x08, 0x29, 0xf8, 0xd3, 0xc1, 0x1f, 0x29, 0x39, 0x00, 0x20, 0xc8, 0x61,
+0x70, 0x47, 0x00, 0x00, 0x68, 0x0e, 0x00, 0x80, 0x84, 0x09, 0x00, 0x00,
+0x06, 0x48, 0x07, 0x49, 0xc0, 0x46, 0x08, 0x80, 0x48, 0x80, 0x00, 0x20,
+0x88, 0x80, 0xc8, 0x80, 0x88, 0x60, 0x04, 0x49, 0xc0, 0x46, 0x48, 0x61,
+0x88, 0x61, 0x70, 0x47, 0xff, 0xff, 0x00, 0x00, 0x4c, 0x2a, 0x00, 0x80,
+0x6c, 0x06, 0x00, 0x80, 0x00, 0x21, 0x06, 0x48, 0xc2, 0x1d, 0x19, 0x32,
+0xc1, 0x60, 0x01, 0x61, 0xc1, 0x61, 0x01, 0x62, 0x11, 0x71, 0xff, 0x30,
+0x01, 0x30, 0x41, 0x62, 0x70, 0x47, 0x00, 0x00, 0x6c, 0x06, 0x00, 0x80,
+0x09, 0x48, 0x0a, 0x4b, 0xc0, 0x46, 0x18, 0x60, 0x00, 0x21, 0xc2, 0x1d,
+0x4d, 0x32, 0xc2, 0x60, 0x10, 0x1c, 0x01, 0x31, 0x14, 0x29, 0xf8, 0xd3,
+0xc1, 0x1f, 0x4d, 0x39, 0x00, 0x20, 0xc8, 0x60, 0x58, 0x60, 0x98, 0x60,
+0x70, 0x47, 0x00, 0x00, 0xd8, 0x07, 0x00, 0x80, 0x6c, 0x06, 0x00, 0x80,
+0x00, 0xb5, 0x0b, 0x49, 0x0b, 0x48, 0xfd, 0xf7, 0xea, 0xfb, 0x0b, 0x48,
0x00, 0x6a, 0x01, 0x23, 0xdb, 0x03, 0x98, 0x43, 0x09, 0x49, 0xc0, 0x46,
0x08, 0x62, 0x09, 0x48, 0xc1, 0x68, 0x01, 0x29, 0x04, 0xd1, 0xc0, 0x6f,
0x80, 0x23, 0x01, 0x68, 0x19, 0x43, 0x01, 0x60, 0x08, 0xbc, 0x18, 0x47,
-0x8d, 0xd5, 0x21, 0x40, 0xc1, 0xa8, 0x21, 0x40, 0xc0, 0x00, 0x18, 0x40,
-0xc0, 0x00, 0x18, 0x00, 0x68, 0x0e, 0x00, 0x80, 0x00, 0xb5, 0x0f, 0x48,
-0xc1, 0x68, 0x01, 0x29, 0x04, 0xd1, 0xc0, 0x6f, 0x80, 0x23, 0x01, 0x68,
-0x99, 0x43, 0x01, 0x60, 0x0b, 0x4b, 0x0c, 0x48, 0x0c, 0x4a, 0x00, 0x21,
-0xfc, 0xf7, 0x0f, 0xfd, 0x0b, 0x48, 0x41, 0x8d, 0x01, 0x31, 0x41, 0x85,
-0x00, 0x21, 0xc1, 0x85, 0x09, 0x48, 0x00, 0x6a, 0x01, 0x23, 0xdb, 0x03,
-0x18, 0x43, 0x08, 0x49, 0xc0, 0x46, 0x08, 0x62, 0x08, 0xbc, 0x18, 0x47,
-0x68, 0x0e, 0x00, 0x80, 0x25, 0xd5, 0x21, 0x40, 0xc1, 0xa8, 0x21, 0x40,
-0xb8, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0x00, 0x18, 0x40,
-0xc0, 0x00, 0x18, 0x00, 0xf0, 0xb5, 0xfe, 0xf7, 0x9b, 0xfe, 0x1b, 0x4c,
+0xc1, 0xbd, 0x21, 0x40, 0x75, 0x98, 0x21, 0x40,
+0xc0, 0x00, 0x18, 0x40, 0xc0, 0x00, 0x18, 0x00, 0x68, 0x0e, 0x00, 0x80,
+0x00, 0xb5, 0x0f, 0x48, 0xc1, 0x68, 0x01, 0x29, 0x04, 0xd1, 0xc0, 0x6f,
+0x80, 0x23, 0x01, 0x68, 0x99, 0x43, 0x01, 0x60, 0x0b, 0x4b, 0x0c, 0x48,
+0x0c, 0x4a, 0x00, 0x21, 0xfd, 0xf7, 0xbf, 0xfb, 0x0b, 0x48, 0x41, 0x8d,
+0x01, 0x31, 0x41, 0x85, 0x00, 0x21, 0xc1, 0x85, 0x09, 0x48, 0x00, 0x6a,
+0x01, 0x23, 0xdb, 0x03, 0x18, 0x43, 0x08, 0x49, 0xc0, 0x46, 0x08, 0x62,
+0x08, 0xbc, 0x18, 0x47, 0x68, 0x0e, 0x00, 0x80, 0x59, 0xbd, 0x21, 0x40,
+0x75, 0x98, 0x21, 0x40, 0xb8, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0xc0, 0x00, 0x18, 0x40, 0xc0, 0x00, 0x18, 0x00, 0xf0, 0xb5, 0x1b, 0x4c,
0x10, 0x26, 0xe0, 0x68, 0x01, 0x28, 0x08, 0xd1, 0x60, 0x88, 0x00, 0x28,
0x05, 0xd1, 0x20, 0x79, 0x00, 0x28, 0x02, 0xd1, 0x19, 0x20, 0xa0, 0x67,
0x00, 0xe0, 0xa6, 0x67, 0x00, 0x20, 0x07, 0x23, 0x5b, 0x02, 0xe5, 0x18,
@@ -3342,12 +2994,12 @@ const u8 typhoon_firmware_image[] = {
0x03, 0x03, 0x1b, 0x0b, 0x4e, 0x4c, 0x27, 0x6f, 0x3d, 0x03, 0x2d, 0x0b,
0xe7, 0x1d, 0x79, 0x37, 0xab, 0x42, 0x1c, 0xd0, 0xe3, 0x1d, 0x79, 0x33,
0x1b, 0x6a, 0xc0, 0x46, 0x40, 0x93, 0x01, 0x23, 0x9b, 0x07, 0x03, 0x43,
-0x1b, 0x68, 0xcc, 0x00, 0x6e, 0x46, 0x33, 0x51,
-0x01, 0x23, 0x9b, 0x07, 0x06, 0x1d, 0x33, 0x43, 0x1b, 0x68, 0x6c, 0x44,
-0x63, 0x60, 0x08, 0x30, 0x01, 0x31, 0x40, 0x9b, 0x83, 0x42, 0x00, 0xd8,
-0x3f, 0x48, 0x03, 0x03, 0x1b, 0x0b, 0xab, 0x42, 0xe7, 0xd1, 0x00, 0x20,
-0x01, 0x23, 0x1b, 0x03, 0x13, 0x40, 0x3c, 0x4c, 0x03, 0xd0, 0x63, 0x6a,
-0x01, 0x33, 0x63, 0x62, 0x09, 0xe0, 0x13, 0x0b, 0x03, 0xd3, 0x23, 0x6a,
+0x1b, 0x68, 0xcc, 0x00, 0x6e, 0x46, 0x33, 0x51, 0x01, 0x23, 0x9b, 0x07,
+0x06, 0x1d, 0x33, 0x43, 0x1b, 0x68, 0x6c, 0x44, 0x63, 0x60, 0x08, 0x30,
+0x01, 0x31, 0x40, 0x9b, 0x83, 0x42, 0x00, 0xd8, 0x3f, 0x48, 0x03, 0x03,
+0x1b, 0x0b, 0xab, 0x42, 0xe7, 0xd1, 0x00, 0x20, 0x01, 0x23, 0x1b, 0x03,
+0x13, 0x40, 0x3c, 0x4c, 0x03, 0xd0, 0x63, 0x6a, 0x01, 0x33, 0x63, 0x62,
+0x09, 0xe0, 0x13, 0x0b, 0x03, 0xd3, 0x23, 0x6a,
0x01, 0x33, 0x23, 0x62, 0x03, 0xe0, 0x37, 0x4b, 0x5c, 0x6d, 0x01, 0x34,
0x5c, 0x65, 0x00, 0x29, 0x09, 0xd0, 0x03, 0x1c, 0xdc, 0x00, 0x23, 0x1c,
0x6b, 0x44, 0x5c, 0x68, 0x01, 0x30, 0x23, 0x0d, 0x01, 0xd2, 0x88, 0x42,
@@ -3363,12 +3015,12 @@ const u8 typhoon_firmware_image[] = {
0x12, 0x4b, 0xc0, 0x46, 0x2b, 0x67, 0x03, 0x1c, 0xdb, 0x00, 0x6b, 0x44,
0x5c, 0x68, 0x01, 0x30, 0x23, 0x0d, 0x04, 0xd3, 0x51, 0x24, 0xa4, 0x03,
0x2b, 0x6f, 0xc0, 0x46, 0xa3, 0x61, 0x88, 0x42, 0xde, 0xd1, 0x10, 0x0b,
-0x03, 0xd3, 0x0e, 0x49, 0x01, 0x20, 0xfc, 0xf7, 0xc2, 0xfb, 0x41, 0xb0,
+0x03, 0xd3, 0x0e, 0x49, 0x01, 0x20, 0xfd, 0xf7, 0x74, 0xfa, 0x41, 0xb0,
0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0,
0x00, 0x01, 0x14, 0x40, 0x00, 0x40, 0x14, 0x40, 0x00, 0x00, 0x20, 0x40,
0x68, 0x0e, 0x00, 0x80, 0x24, 0xa7, 0x20, 0x40, 0xa4, 0x2a, 0x00, 0x80,
0xa0, 0x82, 0x20, 0x40, 0x00, 0x00, 0x10, 0x40, 0xc0, 0x00, 0x18, 0x00,
-0xb5, 0x4f, 0xff, 0xff, 0xf0, 0xb4, 0x00, 0x21, 0x00, 0x23, 0x07, 0x22,
+0xc9, 0x4f, 0xff, 0xff, 0xf0, 0xb4, 0x00, 0x21, 0x00, 0x23, 0x07, 0x22,
0x06, 0x24, 0x47, 0x4f, 0xc0, 0x46, 0x3c, 0x61, 0x3a, 0x61, 0x01, 0x33,
0x20, 0x2b, 0xf9, 0xd3, 0x04, 0x25, 0x3d, 0x61, 0x05, 0x23, 0x3b, 0x61,
0x3c, 0x61, 0x3a, 0x61, 0x3c, 0x61, 0x3a, 0x61, 0x3d, 0x61, 0x3b, 0x61,
@@ -3385,12 +3037,12 @@ const u8 typhoon_firmware_image[] = {
0x02, 0x23, 0x1d, 0x40, 0x04, 0x23, 0x2b, 0x43, 0x3b, 0x61, 0x05, 0x23,
0x2b, 0x43, 0x3b, 0x61, 0x45, 0x08, 0x02, 0x23, 0x1d, 0x40, 0x04, 0x23,
0x2b, 0x43, 0x3b, 0x61, 0x05, 0x23, 0x2b, 0x43, 0x3b, 0x61, 0x02, 0x25,
-0x05, 0x40, 0x04, 0x23, 0x2b, 0x43, 0x3b, 0x61,
-0x05, 0x23, 0x2b, 0x43, 0x3b, 0x61, 0x40, 0x00, 0x02, 0x23, 0x18, 0x40,
-0x04, 0x23, 0x03, 0x43, 0x3b, 0x61, 0x05, 0x23, 0x18, 0x43, 0x38, 0x61,
-0x00, 0x25, 0x3d, 0x61, 0x01, 0x23, 0x3b, 0x61, 0x3d, 0x61, 0x3b, 0x61,
-0x00, 0x20, 0x3d, 0x61, 0x0d, 0x4b, 0x1b, 0x69, 0x49, 0x00, 0x1e, 0x1c,
-0x02, 0x23, 0x33, 0x40, 0x19, 0x43, 0x01, 0x23, 0x3b, 0x61, 0x01, 0x30,
+0x05, 0x40, 0x04, 0x23, 0x2b, 0x43, 0x3b, 0x61, 0x05, 0x23, 0x2b, 0x43,
+0x3b, 0x61, 0x40, 0x00, 0x02, 0x23, 0x18, 0x40, 0x04, 0x23, 0x03, 0x43,
+0x3b, 0x61, 0x05, 0x23, 0x18, 0x43, 0x38, 0x61, 0x00, 0x25, 0x3d, 0x61,
+0x01, 0x23, 0x3b, 0x61, 0x3d, 0x61, 0x3b, 0x61, 0x00, 0x20, 0x3d, 0x61,
+0x0d, 0x4b, 0x1b, 0x69, 0x49, 0x00, 0x1e, 0x1c, 0x02, 0x23, 0x33, 0x40,
+0x19, 0x43, 0x01, 0x23, 0x3b, 0x61, 0x01, 0x30,
0x10, 0x28, 0xf2, 0xd3, 0x02, 0x20, 0x38, 0x61, 0x03, 0x20, 0x38, 0x61,
0x3c, 0x61, 0x3a, 0x61, 0x3c, 0x61, 0x3a, 0x61, 0x38, 0x61, 0x48, 0x08,
0xf0, 0xbc, 0x70, 0x47, 0x80, 0x00, 0x14, 0x00, 0x68, 0x0e, 0x00, 0x80,
@@ -3419,21 +3071,21 @@ const u8 typhoon_firmware_image[] = {
0x10, 0x28, 0xf1, 0xd3, 0x17, 0x61, 0x07, 0x23, 0x13, 0x61, 0x17, 0x61,
0x13, 0x61, 0x03, 0x20, 0x10, 0x61, 0xf0, 0xbc, 0x70, 0x47, 0x00, 0x00,
0x80, 0x00, 0x14, 0x00, 0x68, 0x0e, 0x00, 0x80, 0xf0, 0xb5, 0x4f, 0x4d,
-0x08, 0x21, 0x02, 0x20, 0x2a, 0x1c, 0xfc, 0xf7, 0x75, 0xfa, 0x4d, 0x4c,
+0x08, 0x21, 0x02, 0x20, 0x2a, 0x1c, 0xfd, 0xf7, 0x27, 0xf9, 0x4d, 0x4c,
0x71, 0x23, 0x5b, 0x01, 0xe7, 0x18, 0x38, 0x80, 0x1a, 0x21, 0x02, 0x20,
-0x2a, 0x1c, 0xfc, 0xf7, 0x6b, 0xfa, 0x78, 0x80, 0x20, 0x79, 0x00, 0x28,
+0x2a, 0x1c, 0xfd, 0xf7, 0x1d, 0xf9, 0x78, 0x80, 0x20, 0x79, 0x00, 0x28,
0x0b, 0xd0, 0x00, 0x20, 0x38, 0x80, 0xe0, 0x68, 0x01, 0x28, 0x10, 0xd1,
0x44, 0x48, 0x00, 0x68, 0x01, 0x23, 0x9b, 0x02, 0x18, 0x43, 0x99, 0x02,
0x08, 0x60, 0xe0, 0x68, 0x01, 0x28, 0x06, 0xd1, 0x60, 0x88, 0x00, 0x28,
0x03, 0xd1, 0xf9, 0x21, 0x12, 0x20, 0xff, 0xf7, 0x43, 0xff, 0x01, 0x21,
0xc9, 0x03, 0x00, 0x20, 0xff, 0xf7, 0x3e, 0xff, 0x00, 0x25, 0x7d, 0x26,
0xf6, 0x00, 0x00, 0xe0, 0x01, 0x35, 0x00, 0x20, 0xff, 0xf7, 0x9c, 0xfe,
-0x00, 0x0c, 0x01, 0xd3, 0xb5, 0x42, 0xf7, 0xd3,
-0x00, 0x25, 0x05, 0xe0, 0x03, 0x21, 0x09, 0x03, 0x00, 0x20, 0xff, 0xf7,
-0x2b, 0xff, 0x01, 0x35, 0x00, 0x20, 0xff, 0xf7, 0x8d, 0xfe, 0x40, 0x0b,
-0x01, 0xd2, 0xb5, 0x42, 0xf2, 0xd3, 0x04, 0x20, 0xff, 0xf7, 0x86, 0xfe,
-0xff, 0x23, 0xe1, 0x33, 0x98, 0x43, 0x01, 0x21, 0x01, 0x43, 0x38, 0x88,
-0xff, 0x23, 0x01, 0x33, 0x98, 0x42, 0x03, 0xd1, 0x2f, 0x23, 0x5b, 0x01,
+0x00, 0x0c, 0x01, 0xd3, 0xb5, 0x42, 0xf7, 0xd3, 0x00, 0x25, 0x05, 0xe0,
+0x03, 0x21, 0x09, 0x03, 0x00, 0x20, 0xff, 0xf7, 0x2b, 0xff, 0x01, 0x35,
+0x00, 0x20, 0xff, 0xf7, 0x8d, 0xfe, 0x40, 0x0b, 0x01, 0xd2, 0xb5, 0x42,
+0xf2, 0xd3, 0x04, 0x20, 0xff, 0xf7, 0x86, 0xfe, 0xff, 0x23, 0xe1, 0x33,
+0x98, 0x43, 0x01, 0x21, 0x01, 0x43, 0x38, 0x88, 0xff, 0x23, 0x01, 0x33,
+0x98, 0x42, 0x03, 0xd1, 0x2f, 0x23, 0x5b, 0x01,
0x19, 0x43, 0x16, 0xe0, 0x01, 0x28, 0x09, 0xd1, 0x78, 0x88, 0x01, 0x28,
0x03, 0xd1, 0x23, 0x23, 0x5b, 0x01, 0x19, 0x43, 0x0d, 0xe0, 0x20, 0x23,
0x19, 0x43, 0x0a, 0xe0, 0x00, 0x28, 0x08, 0xd1, 0x78, 0x88, 0x01, 0x28,
@@ -3445,7 +3097,7 @@ const u8 typhoon_firmware_image[] = {
0xe3, 0xfe, 0x00, 0x27, 0x03, 0xe0, 0x08, 0x2f, 0x01, 0xd3, 0x0f, 0x2f,
0x08, 0xd9, 0x38, 0x1c, 0xff, 0xf7, 0x40, 0xfe, 0x79, 0x00, 0x09, 0x19,
0x1b, 0x23, 0xdb, 0x01, 0xc9, 0x18, 0x88, 0x83, 0x01, 0x37, 0x20, 0x2f,
-0xef, 0xd3, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x79, 0xbf, 0x21, 0x40,
+0xef, 0xd3, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xed, 0xaf, 0x21, 0x40,
0x68, 0x0e, 0x00, 0x80, 0x00, 0x00, 0x10, 0x40, 0x81, 0xb0, 0x13, 0x48,
0x01, 0x68, 0xc0, 0x46, 0x00, 0x91, 0x41, 0x68, 0xc0, 0x46, 0x00, 0x91,
0x81, 0x68, 0xc0, 0x46, 0x00, 0x91, 0xc1, 0x68, 0xc0, 0x46, 0x00, 0x91,
@@ -3471,12 +3123,12 @@ const u8 typhoon_firmware_image[] = {
0x16, 0xd1, 0x51, 0x8b, 0xc9, 0x08, 0x13, 0xd2, 0x0f, 0xe0, 0x51, 0x8b,
0x09, 0x09, 0x0f, 0xd2, 0x0b, 0xe0, 0x0a, 0x79, 0x00, 0x2a, 0x0b, 0xd1,
0x6d, 0x23, 0x5b, 0x01, 0xc9, 0x18, 0x8a, 0x88, 0xc9, 0x88, 0x11, 0x40,
-0x49, 0x09, 0x09, 0x07, 0x02, 0xd1, 0x04, 0x23,
-0x98, 0x43, 0xf8, 0x83, 0xf8, 0x8b, 0x04, 0x21, 0x01, 0x40, 0x02, 0x9a,
-0x1f, 0xd0, 0xb9, 0x8b, 0x4a, 0x0b, 0x27, 0xd3, 0x80, 0x09, 0x25, 0xd3,
-0xff, 0x23, 0x01, 0x98, 0x01, 0x33, 0x98, 0x42, 0x20, 0xd0, 0x00, 0x25,
-0x00, 0x98, 0x01, 0x28, 0x00, 0xd1, 0x05, 0x02, 0x01, 0x98, 0x00, 0x28,
-0x02, 0xd1, 0x01, 0x23, 0x5b, 0x03, 0x1d, 0x43, 0xa9, 0x42, 0x13, 0xd0,
+0x49, 0x09, 0x09, 0x07, 0x02, 0xd1, 0x04, 0x23, 0x98, 0x43, 0xf8, 0x83,
+0xf8, 0x8b, 0x04, 0x21, 0x01, 0x40, 0x02, 0x9a, 0x1f, 0xd0, 0xb9, 0x8b,
+0x4a, 0x0b, 0x27, 0xd3, 0x80, 0x09, 0x25, 0xd3, 0xff, 0x23, 0x01, 0x98,
+0x01, 0x33, 0x98, 0x42, 0x20, 0xd0, 0x00, 0x25, 0x00, 0x98, 0x01, 0x28,
+0x00, 0xd1, 0x05, 0x02, 0x01, 0x98, 0x00, 0x28, 0x02, 0xd1, 0x01, 0x23,
+0x5b, 0x03, 0x1d, 0x43, 0xa9, 0x42, 0x13, 0xd0,
0x00, 0x20, 0x29, 0x1c, 0xff, 0xf7, 0x10, 0xfe, 0xbd, 0x83, 0x00, 0x20,
0xc0, 0x43, 0x60, 0x62, 0x0a, 0xe0, 0xb8, 0x8b, 0x40, 0x0b, 0x07, 0xd2,
0x09, 0x21, 0x49, 0x02, 0x00, 0x20, 0xff, 0xf7, 0x03, 0xfe, 0x09, 0x20,
@@ -3504,7 +3156,7 @@ const u8 typhoon_firmware_image[] = {
0xff, 0xf7, 0xde, 0xff, 0x01, 0x1c, 0x05, 0x20, 0x00, 0x90, 0x00, 0x20,
0x01, 0xab, 0x18, 0x80, 0x04, 0x3b, 0x58, 0x70, 0x1b, 0x22, 0x00, 0xab,
0x5a, 0x80, 0xd9, 0x80, 0x05, 0x49, 0xc9, 0x6d, 0xc0, 0x46, 0x02, 0x91,
-0x03, 0x90, 0x68, 0x46, 0x00, 0x21, 0xfc, 0xf7, 0xd5, 0xf9, 0x04, 0xb0,
+0x03, 0x90, 0x68, 0x46, 0x00, 0x21, 0xfd, 0xf7, 0x79, 0xf8, 0x04, 0xb0,
0x08, 0xbc, 0x18, 0x47, 0xa4, 0x2a, 0x00, 0x80, 0x0f, 0x48, 0x01, 0x68,
0x49, 0x0c, 0x05, 0xd2, 0x01, 0x68, 0x09, 0x0c, 0x06, 0xd1, 0x00, 0x68,
0x80, 0x0a, 0x03, 0xd3, 0x0b, 0x48, 0x00, 0x68, 0x00, 0x0c, 0x01, 0xe0,
@@ -3514,12 +3166,12 @@ const u8 typhoon_firmware_image[] = {
0x00, 0x00, 0x10, 0x40, 0x00, 0x00, 0x18, 0x40, 0x00, 0x00, 0x00, 0x80,
0x04, 0x99, 0x00, 0x00, 0x07, 0x99, 0x00, 0x00, 0x90, 0xb4, 0x01, 0x24,
0x21, 0x1c, 0x18, 0x48, 0x02, 0x68, 0x52, 0x0c, 0x06, 0xd2, 0x02, 0x68,
-0x12, 0x0c, 0x02, 0xd1, 0x00, 0x68, 0x80, 0x0a,
-0x00, 0xd2, 0x00, 0x21, 0x09, 0x06, 0x09, 0x0e, 0x12, 0x4f, 0x13, 0x4a,
-0x02, 0xd0, 0x38, 0x68, 0x00, 0x0c, 0x00, 0xe0, 0x90, 0x6c, 0x00, 0x04,
-0x00, 0x0c, 0x10, 0x4b, 0x98, 0x42, 0x08, 0xd0, 0x02, 0x33, 0x98, 0x42,
-0x05, 0xd0, 0x0e, 0x4b, 0x98, 0x42, 0x02, 0xd0, 0x02, 0x3b, 0x98, 0x42,
-0x0c, 0xd1, 0x00, 0x29, 0x02, 0xd0, 0xf8, 0x6a, 0x00, 0x0c, 0x00, 0xe0,
+0x12, 0x0c, 0x02, 0xd1, 0x00, 0x68, 0x80, 0x0a, 0x00, 0xd2, 0x00, 0x21,
+0x09, 0x06, 0x09, 0x0e, 0x12, 0x4f, 0x13, 0x4a, 0x02, 0xd0, 0x38, 0x68,
+0x00, 0x0c, 0x00, 0xe0, 0x90, 0x6c, 0x00, 0x04, 0x00, 0x0c, 0x10, 0x4b,
+0x98, 0x42, 0x08, 0xd0, 0x02, 0x33, 0x98, 0x42, 0x05, 0xd0, 0x0e, 0x4b,
+0x98, 0x42, 0x02, 0xd0, 0x02, 0x3b, 0x98, 0x42, 0x0c, 0xd1, 0x00, 0x29,
+0x02, 0xd0, 0xf8, 0x6a, 0x00, 0x0c, 0x00, 0xe0,
0xd0, 0x6c, 0x40, 0x0a, 0x00, 0xd2, 0x00, 0x24, 0x20, 0x06, 0x00, 0x0e,
0x90, 0xbc, 0x70, 0x47, 0x00, 0x20, 0xfb, 0xe7, 0x00, 0x00, 0x10, 0x40,
0x00, 0x00, 0x18, 0x40, 0x00, 0x00, 0x00, 0x80, 0x04, 0x99, 0x00, 0x00,
@@ -3549,47 +3201,36 @@ const u8 typhoon_firmware_image[] = {
0x5b, 0x00, 0x9f, 0x44, 0x05, 0x03, 0x07, 0x03, 0x07, 0x07, 0x05, 0x03,
0x03, 0x20, 0x02, 0xe0, 0x01, 0x20, 0x00, 0xe0, 0x00, 0x20, 0x01, 0x21,
0x38, 0x60, 0x80, 0x07, 0x00, 0xd1, 0x00, 0x21, 0x08, 0x06, 0x00, 0x0e,
-0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x98, 0x6e, 0x21, 0x40,
+0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x34, 0x6e, 0x21, 0x40,
0x00, 0x00, 0x11, 0x40, 0x00, 0x00, 0x10, 0x40, 0x00, 0x00, 0x18, 0x40,
-0x00, 0x00, 0x00, 0x80, 0xfe, 0x66, 0xff, 0xff, 0xf0, 0xb5, 0x83, 0xb0,
-0x07, 0x1c, 0x01, 0x20, 0x02, 0x90, 0x01, 0x25, 0x02, 0x24, 0x10, 0x26,
-0x20, 0x21, 0x00, 0x91, 0xff, 0xf7, 0xe2, 0xfe, 0x01, 0x28, 0x4d, 0xd1,
-0x38, 0x2f, 0x01, 0xd0, 0xa8, 0x2f, 0x3a, 0xd1, 0x2e, 0x4e, 0x3c, 0x21,
-0x02, 0x20, 0x32, 0x1c, 0xfb, 0xf7, 0x4c, 0xff, 0x3e, 0x21, 0x05, 0x1c,
-0x02, 0x20, 0x32, 0x1c, 0xfb, 0xf7, 0x46, 0xff, 0x00, 0x04, 0x05, 0x43,
-0x40, 0x21, 0x02, 0x20, 0x32, 0x1c, 0xfb, 0xf7,
-0x3f, 0xff, 0x01, 0x90, 0x42, 0x21, 0x02, 0x20, 0x32, 0x1c, 0xfb, 0xf7,
-0x39, 0xff, 0x00, 0x04, 0x01, 0x99, 0x08, 0x43, 0x06, 0x1c, 0xa8, 0x2f,
-0x1b, 0xd1, 0x1f, 0x4a, 0x44, 0x21, 0x02, 0x20, 0xfb, 0xf7, 0x2e, 0xff,
-0x04, 0x1c, 0x1c, 0x4a, 0x46, 0x21, 0x02, 0x20, 0xfb, 0xf7, 0x28, 0xff,
-0x00, 0x04, 0x04, 0x43, 0x18, 0x4a, 0x48, 0x21, 0x02, 0x20, 0xfb, 0xf7,
-0x21, 0xff, 0x00, 0x90, 0x15, 0x4a, 0x4a, 0x21, 0x02, 0x20, 0xfb, 0xf7,
-0x1b, 0xff, 0x00, 0x04, 0x00, 0x99, 0x01, 0x43, 0x00, 0x91, 0x28, 0x1c,
-0x30, 0x43, 0x20, 0x43, 0x00, 0x99, 0x08, 0x43, 0x00, 0xd1, 0x16, 0xe0,
-0x11, 0x20, 0x00, 0x04, 0x05, 0x62, 0x46, 0x62, 0x84, 0x62, 0x00, 0x99,
-0xc0, 0x46, 0xc1, 0x62, 0x00, 0x21, 0x0a, 0x48, 0xc0, 0x46, 0x01, 0x60,
-0x38, 0x2f, 0x01, 0xd0, 0xa8, 0x2f, 0x05, 0xd1, 0x01, 0x21, 0x01, 0x60,
-0xa8, 0x2f, 0x01, 0xd1, 0x03, 0x21, 0x01, 0x60, 0x02, 0x98, 0x03, 0xb0,
-0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x79, 0xbf, 0x21, 0x40,
-0x98, 0x6e, 0x21, 0x40, 0x70, 0x47, 0x00, 0x00, 0x70, 0x47, 0x00, 0x00,
-0x90, 0xb5, 0x07, 0x1c, 0x12, 0x4c, 0x21, 0x68, 0x12, 0x48, 0x81, 0x42,
-0x0b, 0xd0, 0x00, 0x23, 0x21, 0x1c, 0xe2, 0x1d, 0xc5, 0x32, 0x00, 0xe0,
-0x08, 0xc1, 0x91, 0x42, 0xfc, 0xd3, 0x20, 0x60, 0xcc, 0x20, 0xa0, 0x80,
+0x00, 0x00, 0x00, 0x80, 0xfe, 0x66, 0xff, 0xff, 0xf0, 0xb5, 0x82, 0xb0,
+0x07, 0x1c, 0x01, 0x20, 0x01, 0x90, 0xff, 0xf7, 0xe7, 0xfe, 0x01, 0x28,
+0x13, 0xd1, 0x38, 0x2f, 0x01, 0xd0, 0xa8, 0x2f, 0x07, 0xd1, 0x00, 0x26,
+0xf6, 0x43, 0x34, 0x1c, 0xa8, 0x2f, 0x02, 0xd1, 0x30, 0x1c, 0x00, 0x96,
+0x35, 0x1c, 0x11, 0x20, 0x00, 0x04, 0x06, 0x62, 0x44, 0x62, 0x85, 0x62,
+0x00, 0x99, 0xc0, 0x46, 0xc1, 0x62, 0x00, 0x21, 0x08, 0x48, 0xc0, 0x46,
+0x01, 0x60, 0x38, 0x2f, 0x01, 0xd0, 0xa8, 0x2f, 0x05, 0xd1, 0x01, 0x21,
+0x01, 0x60, 0xa8, 0x2f, 0x01, 0xd1, 0x03, 0x21, 0x01, 0x60, 0x01, 0x98,
+0x02, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x34, 0x6e, 0x21, 0x40,
+0x70, 0x47, 0x00, 0x00, 0x70, 0x47, 0x00, 0x00, 0x90, 0xb5, 0x07, 0x1c,
+0x12, 0x4c, 0x21, 0x68, 0x12, 0x48, 0x81, 0x42, 0x0b, 0xd0, 0x00, 0x23,
+0x21, 0x1c, 0xe2, 0x1d, 0xc1, 0x32, 0x00, 0xe0,
+0x08, 0xc1, 0x91, 0x42, 0xfc, 0xd3, 0x20, 0x60, 0xc8, 0x20, 0xa0, 0x80,
0x67, 0x72, 0x38, 0x01, 0x00, 0xf0, 0x18, 0xf8, 0x27, 0x72, 0x0a, 0x48,
0xc0, 0x46, 0xe0, 0x60, 0x09, 0x2f, 0x00, 0xdb, 0x00, 0x27, 0xe0, 0x19,
0x01, 0x7d, 0x01, 0x31, 0x01, 0x75, 0xe0, 0x88, 0x01, 0x30, 0xe0, 0x80,
0x01, 0x20, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x00, 0x80,
-0xee, 0xff, 0xc0, 0xd0, 0x02, 0x10, 0x00, 0x03, 0x80, 0xb4, 0x08, 0x4a,
-0xd1, 0x1d, 0x89, 0x31, 0x0b, 0x7b, 0x20, 0x2b, 0x01, 0xd3, 0x00, 0x23,
-0x0b, 0x73, 0x07, 0x1c, 0x08, 0x7b, 0x43, 0x1c, 0x0b, 0x73, 0x80, 0x18,
-0x90, 0x30, 0x47, 0x73, 0x80, 0xbc, 0x70, 0x47, 0x00, 0x00, 0x00, 0x80,
+0xee, 0xff, 0xc0, 0xd0, 0x08, 0x10, 0x00, 0x03, 0x80, 0xb4, 0x08, 0x4a,
+0xd1, 0x1d, 0x89, 0x31, 0x0b, 0x7a, 0x20, 0x2b, 0x01, 0xd3, 0x00, 0x23,
+0x0b, 0x72, 0x07, 0x1c, 0x08, 0x7a, 0x43, 0x1c, 0x0b, 0x72, 0x80, 0x18,
+0x90, 0x30, 0x47, 0x72, 0x80, 0xbc, 0x70, 0x47, 0x00, 0x00, 0x00, 0x80,
0x07, 0x49, 0x01, 0x22, 0x12, 0x04, 0x08, 0x68, 0x02, 0x40, 0x01, 0x20,
0x00, 0x2a, 0x06, 0xd1, 0x0a, 0x68, 0x12, 0x0c, 0x02, 0xd1, 0x09, 0x68,
0x89, 0x0a, 0x00, 0xd2, 0x00, 0x20, 0x70, 0x47, 0x00, 0x00, 0x10, 0x40,
0x90, 0xb5, 0x07, 0x1c, 0x09, 0x4c, 0x38, 0x1c, 0x21, 0x1c, 0xfc, 0xf7,
-0xab, 0xf8, 0x38, 0x1c, 0x00, 0xf0, 0x0e, 0xf8, 0x01, 0x23, 0xd8, 0x42,
-0x01, 0xd1, 0x00, 0x0c, 0xe0, 0x80, 0x00, 0x21, 0x20, 0x1c, 0xfb, 0xf7,
-0xdf, 0xff, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x70, 0x67, 0x21, 0x40,
+0x91, 0xff, 0x38, 0x1c, 0x00, 0xf0, 0x0e, 0xf8, 0x01, 0x23, 0xd8, 0x42,
+0x01, 0xd1, 0x00, 0x0c, 0xe0, 0x80, 0x00, 0x21, 0x20, 0x1c, 0xfc, 0xf7,
+0xc5, 0xfe, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xc4, 0x66, 0x21, 0x40,
0xf8, 0xb5, 0x07, 0x1c, 0x79, 0x7a, 0x76, 0x48, 0x00, 0x23, 0x76, 0x4c,
0x01, 0x29, 0x5d, 0xd1, 0xa2, 0x88, 0xc0, 0x46, 0x00, 0x92, 0xa1, 0x89,
0x8a, 0x42, 0x74, 0xda, 0xfa, 0x7a, 0x00, 0x2a, 0x15, 0xd0, 0x7a, 0x6c,
@@ -3600,23 +3241,23 @@ const u8 typhoon_firmware_image[] = {
0x12, 0x0c, 0x22, 0x80, 0x8a, 0x42, 0x00, 0xdb, 0x23, 0x80, 0x00, 0x22,
0x00, 0x29, 0x69, 0xdd, 0x5f, 0x4c, 0xa4, 0x6a, 0x5e, 0x4b, 0x1d, 0x88,
0x58, 0x23, 0x6b, 0x43, 0xe3, 0x18, 0xde, 0x1d, 0x01, 0x36, 0x01, 0x23,
-0x9b, 0x07, 0x33, 0x43, 0x1b, 0x68, 0x1b, 0x06,
-0x15, 0xd1, 0x58, 0x49, 0x00, 0x9a, 0x01, 0x32, 0x8a, 0x80, 0x8a, 0x88,
-0xc0, 0x46, 0x42, 0x81, 0x08, 0x88, 0x01, 0x30, 0x54, 0x4e, 0xc0, 0x46,
-0xf0, 0x80, 0x58, 0x20, 0x68, 0x43, 0x21, 0x18, 0x38, 0x1c, 0x00, 0xf0,
-0x8d, 0xfa, 0xf0, 0x88, 0x00, 0x04, 0x00, 0x14, 0x95, 0xe0, 0x4d, 0x4b,
-0x01, 0x35, 0x2d, 0x04, 0x2d, 0x0c, 0x1d, 0x80, 0x8d, 0x42, 0x01, 0xdb,
-0x00, 0x25, 0x1d, 0x80, 0x01, 0x32, 0x12, 0x04, 0x12, 0x14, 0x91, 0x42,
-0xce, 0xdc, 0x81, 0xe0, 0xe1, 0x88, 0xe2, 0x89, 0x91, 0x42, 0x18, 0xda,
-0xf9, 0x7a, 0x00, 0x29, 0x2f, 0xd0, 0x79, 0x6c, 0x49, 0x04, 0x49, 0x0c,
-0x79, 0x64, 0x2a, 0xd0, 0xe2, 0x89, 0x91, 0x42, 0x27, 0xd8, 0xe1, 0x88,
-0x01, 0x31, 0xe1, 0x80, 0xe1, 0x88, 0xc0, 0x46, 0x81, 0x81, 0x01, 0x23,
-0xdb, 0x03, 0x78, 0x6c, 0x18, 0x43, 0x3a, 0x4e, 0xc0, 0x46, 0xf0, 0x80,
-0x00, 0xe0, 0x63, 0xe0, 0xe0, 0x6a, 0x79, 0x6c, 0x4b, 0x00, 0x59, 0x18,
-0x49, 0x01, 0x40, 0x18, 0xc1, 0x1f, 0x59, 0x39, 0x38, 0x1c, 0x00, 0xf0,
-0x79, 0xfa, 0xe0, 0x6a, 0x79, 0x6c, 0x4a, 0x00, 0x52, 0x18, 0x52, 0x01,
-0x80, 0x18, 0x01, 0x39, 0x09, 0x04, 0x09, 0x0c, 0x60, 0x38, 0x00, 0xf0,
-0xf3, 0xfa, 0xb6, 0xe7, 0x4a, 0xe0, 0x61, 0x88, 0x01, 0x31, 0x09, 0x04,
+0x9b, 0x07, 0x33, 0x43, 0x1b, 0x68, 0x1b, 0x06, 0x15, 0xd1, 0x58, 0x49,
+0x00, 0x9a, 0x01, 0x32, 0x8a, 0x80, 0x8a, 0x88, 0xc0, 0x46, 0x42, 0x81,
+0x08, 0x88, 0x01, 0x30, 0x54, 0x4e, 0xc0, 0x46, 0xf0, 0x80, 0x58, 0x20,
+0x68, 0x43, 0x21, 0x18, 0x38, 0x1c, 0x00, 0xf0, 0x39, 0xfb, 0xf0, 0x88,
+0x00, 0x04, 0x00, 0x14, 0x95, 0xe0, 0x4d, 0x4b, 0x01, 0x35, 0x2d, 0x04,
+0x2d, 0x0c, 0x1d, 0x80, 0x8d, 0x42, 0x01, 0xdb, 0x00, 0x25, 0x1d, 0x80,
+0x01, 0x32, 0x12, 0x04, 0x12, 0x14, 0x91, 0x42, 0xce, 0xdc, 0x81, 0xe0,
+0xe1, 0x88, 0xe2, 0x89, 0x91, 0x42, 0x18, 0xda, 0xf9, 0x7a, 0x00, 0x29,
+0x2f, 0xd0, 0x79, 0x6c, 0x49, 0x04, 0x49, 0x0c, 0x79, 0x64, 0x2a, 0xd0,
+0xe2, 0x89, 0x91, 0x42, 0x27, 0xd8, 0xe1, 0x88, 0x01, 0x31, 0xe1, 0x80,
+0xe1, 0x88, 0xc0, 0x46, 0x81, 0x81, 0x01, 0x23, 0xdb, 0x03, 0x78, 0x6c,
+0x18, 0x43, 0x3a, 0x4e, 0xc0, 0x46, 0xf0, 0x80, 0x00, 0xe0, 0x63, 0xe0,
+0xe0, 0x6a, 0x79, 0x6c, 0x4b, 0x00, 0x59, 0x18, 0x49, 0x01, 0x40, 0x18,
+0xc1, 0x1f, 0x59, 0x39, 0x38, 0x1c, 0x00, 0xf0, 0x0f, 0xfb, 0xe0, 0x6a,
+0x79, 0x6c, 0x4a, 0x00, 0x52, 0x18, 0x52, 0x01, 0x80, 0x18, 0x01, 0x39,
+0x09, 0x04, 0x09, 0x0c, 0x60, 0x38, 0x00, 0xf0, 0x89, 0xfb, 0xb6, 0xe7,
+0x4a, 0xe0, 0x61, 0x88, 0x01, 0x31, 0x09, 0x04,
0x09, 0x0c, 0x61, 0x80, 0xe2, 0x89, 0x91, 0x42, 0x00, 0xdb, 0x63, 0x80,
0x00, 0x21, 0x00, 0x2a, 0x3e, 0xdd, 0x24, 0x4c, 0xe4, 0x6a, 0x23, 0x4b,
0x5d, 0x88, 0x6b, 0x00, 0x5b, 0x19, 0x5b, 0x01, 0xe3, 0x18, 0xde, 0x1d,
@@ -3624,14 +3265,14 @@ const u8 typhoon_firmware_image[] = {
0x20, 0xd1, 0x1c, 0x4e, 0xf1, 0x88, 0x01, 0x31, 0xf1, 0x80, 0xf1, 0x88,
0xc0, 0x46, 0x81, 0x81, 0x70, 0x88, 0x01, 0x23, 0xdb, 0x03, 0x01, 0x30,
0x18, 0x43, 0x17, 0x49, 0xc0, 0x46, 0xc8, 0x80, 0x68, 0x00, 0x40, 0x19,
-0x40, 0x01, 0x21, 0x18, 0x38, 0x1c, 0x00, 0xf0, 0x39, 0xfa, 0x71, 0x88,
+0x40, 0x01, 0x21, 0x18, 0x38, 0x1c, 0x00, 0xf0, 0xcf, 0xfa, 0x71, 0x88,
0x4a, 0x00, 0x52, 0x18, 0x52, 0x01, 0xf0, 0x6a, 0x80, 0x18, 0x00, 0xf0,
-0xb7, 0xfa, 0x0e, 0x49, 0xc8, 0x88, 0x79, 0xe7, 0x0b, 0x4b, 0x01, 0x35,
+0x4d, 0xfb, 0x0e, 0x49, 0xc8, 0x88, 0x79, 0xe7, 0x0b, 0x4b, 0x01, 0x35,
0x2d, 0x04, 0x2d, 0x0c, 0x5d, 0x80, 0x95, 0x42, 0x01, 0xdb, 0x00, 0x25,
0x5d, 0x80, 0x01, 0x31, 0x09, 0x04, 0x09, 0x14, 0x8a, 0x42, 0xc2, 0xdc,
0x01, 0x89, 0x01, 0x31, 0x01, 0x81, 0x00, 0x20, 0xc0, 0x43, 0xf8, 0xbc,
0x08, 0xbc, 0x18, 0x47, 0x4c, 0x2b, 0x00, 0x80, 0x4c, 0x2a, 0x00, 0x80,
-0x70, 0x67, 0x21, 0x40, 0xf0, 0xb4, 0x06, 0x1c, 0x01, 0x23, 0xdb, 0x03,
+0xc4, 0x66, 0x21, 0x40, 0xf0, 0xb4, 0x06, 0x1c, 0x01, 0x23, 0xdb, 0x03,
0x33, 0x40, 0x01, 0x24, 0x44, 0x4f, 0x00, 0x20, 0x44, 0x4a, 0x45, 0x4d,
0xd1, 0x1d, 0x39, 0x31, 0x00, 0x2b, 0x41, 0xd0, 0xe3, 0x03, 0xf3, 0x1a,
0x73, 0xd0, 0xee, 0x89, 0x9e, 0x42, 0x71, 0xd3, 0xee, 0x88, 0x00, 0x2e,
@@ -3643,23 +3284,23 @@ const u8 typhoon_firmware_image[] = {
0xd2, 0x18, 0x90, 0x63, 0xf2, 0x6a, 0xd2, 0x18, 0xd0, 0x63, 0xf2, 0x6a,
0xd2, 0x18, 0x10, 0x64, 0xf2, 0x6a, 0xd2, 0x18, 0x50, 0x64, 0xf2, 0x6a,
0xd2, 0x18, 0x90, 0x64, 0xf2, 0x6a, 0xd2, 0x18, 0xd0, 0x64, 0xf0, 0x88,
-0x01, 0x38, 0xf0, 0x80, 0xf0, 0x88, 0xc0, 0x46,
-0x88, 0x81, 0x24, 0x49, 0x00, 0x28, 0x39, 0xd1, 0x4f, 0x80, 0x37, 0xe0,
-0x00, 0x2e, 0x38, 0xd9, 0xab, 0x89, 0xb3, 0x42, 0x30, 0xd3, 0xab, 0x88,
-0x00, 0x2b, 0x2c, 0xd0, 0x53, 0x89, 0x01, 0x33, 0x53, 0x81, 0x2a, 0x1c,
-0xad, 0x6a, 0x58, 0x23, 0x01, 0x3e, 0x73, 0x43, 0xed, 0x18, 0xae, 0x68,
-0x36, 0x06, 0x36, 0x0e, 0x03, 0x2e, 0x02, 0xd0, 0xce, 0x89, 0x01, 0x36,
-0xce, 0x81, 0xa8, 0x60, 0x95, 0x6a, 0xed, 0x18, 0xa8, 0x63, 0x95, 0x6a,
-0xed, 0x18, 0xe8, 0x63, 0x95, 0x6a, 0xed, 0x18, 0x28, 0x64, 0x95, 0x6a,
-0xed, 0x18, 0x68, 0x64, 0x95, 0x6a, 0xed, 0x18, 0xa8, 0x64, 0x95, 0x6a,
-0xeb, 0x18, 0xd8, 0x64, 0x90, 0x88, 0x01, 0x38, 0x90, 0x80, 0x90, 0x88,
-0xc0, 0x46, 0x48, 0x81, 0x00, 0x28, 0x03, 0xd1, 0x01, 0xe0, 0x04, 0xe0,
-0x03, 0xe0, 0x17, 0x80, 0x20, 0x1c, 0xf0, 0xbc, 0x70, 0x47, 0xca, 0x89,
-0x01, 0x32, 0xca, 0x81, 0xf9, 0xe7, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
-0x0c, 0x2b, 0x00, 0x80, 0x4c, 0x2a, 0x00, 0x80, 0x00, 0xb5, 0x00, 0x21,
-0x41, 0x60, 0x10, 0x49, 0x4a, 0x68, 0x00, 0x2a, 0x10, 0xd1, 0xca, 0x68,
-0x00, 0x2a, 0x04, 0xd0, 0xca, 0x1d, 0x19, 0x32, 0x12, 0x79, 0x00, 0x2a,
-0x08, 0xd0, 0x4a, 0x69, 0x00, 0x2a, 0x0b, 0xd1, 0x88, 0x61, 0x48, 0x61,
+0x01, 0x38, 0xf0, 0x80, 0xf0, 0x88, 0xc0, 0x46, 0x88, 0x81, 0x24, 0x49,
+0x00, 0x28, 0x39, 0xd1, 0x4f, 0x80, 0x37, 0xe0, 0x00, 0x2e, 0x38, 0xd9,
+0xab, 0x89, 0xb3, 0x42, 0x30, 0xd3, 0xab, 0x88, 0x00, 0x2b, 0x2c, 0xd0,
+0x53, 0x89, 0x01, 0x33, 0x53, 0x81, 0x2a, 0x1c, 0xad, 0x6a, 0x58, 0x23,
+0x01, 0x3e, 0x73, 0x43, 0xed, 0x18, 0xae, 0x68, 0x36, 0x06, 0x36, 0x0e,
+0x03, 0x2e, 0x02, 0xd0, 0xce, 0x89, 0x01, 0x36, 0xce, 0x81, 0xa8, 0x60,
+0x95, 0x6a, 0xed, 0x18, 0xa8, 0x63, 0x95, 0x6a, 0xed, 0x18, 0xe8, 0x63,
+0x95, 0x6a, 0xed, 0x18, 0x28, 0x64, 0x95, 0x6a, 0xed, 0x18, 0x68, 0x64,
+0x95, 0x6a, 0xed, 0x18, 0xa8, 0x64, 0x95, 0x6a, 0xeb, 0x18, 0xd8, 0x64,
+0x90, 0x88, 0x01, 0x38, 0x90, 0x80, 0x90, 0x88, 0xc0, 0x46, 0x48, 0x81,
+0x00, 0x28, 0x03, 0xd1, 0x01, 0xe0, 0x04, 0xe0, 0x03, 0xe0, 0x17, 0x80,
+0x20, 0x1c, 0xf0, 0xbc, 0x70, 0x47, 0xca, 0x89, 0x01, 0x32, 0xca, 0x81,
+0xf9, 0xe7, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x0c, 0x2b, 0x00, 0x80,
+0x4c, 0x2a, 0x00, 0x80, 0x00, 0xb5, 0x00, 0x21, 0x41, 0x60, 0x10, 0x49,
+0x4a, 0x68, 0x00, 0x2a, 0x10, 0xd1, 0xca, 0x68, 0x00, 0x2a, 0x04, 0xd0,
+0xca, 0x1d, 0x19, 0x32, 0x12, 0x79, 0x00, 0x2a, 0x08, 0xd0, 0x4a, 0x69,
+0x00, 0x2a, 0x0b, 0xd1, 0x88, 0x61, 0x48, 0x61,
0x00, 0xf0, 0x10, 0xf8, 0x08, 0xbc, 0x18, 0x47, 0x4a, 0x69, 0x00, 0x2a,
0x02, 0xd1, 0x88, 0x61, 0x48, 0x61, 0xf7, 0xe7, 0x8a, 0x69, 0xc0, 0x46,
0x50, 0x60, 0x88, 0x61, 0xf2, 0xe7, 0x00, 0x00, 0x6c, 0x06, 0x00, 0x80,
@@ -3677,32 +3318,32 @@ const u8 typhoon_firmware_image[] = {
0x01, 0x31, 0x91, 0x42, 0xf4, 0xd3, 0x10, 0x29, 0x07, 0xd2, 0x8a, 0x00,
0xd2, 0x18, 0xff, 0x32, 0x01, 0x32, 0x57, 0x62, 0x01, 0x31, 0x10, 0x29,
0xf7, 0xd3, 0x11, 0x49, 0x00, 0xf0, 0x22, 0xf8, 0xb0, 0xbc, 0x08, 0xbc,
-0x18, 0x47, 0x00, 0x00, 0x6c, 0x06, 0x00, 0x80, 0x1c, 0xad, 0x20, 0x40,
+0x18, 0x47, 0x00, 0x00, 0x6c, 0x06, 0x00, 0x80, 0xac, 0xab, 0x20, 0x40,
0x28, 0x01, 0x40, 0x00, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, 0x20, 0x01, 0x40, 0x00,
0x67, 0x45, 0x23, 0x01, 0xef, 0xcd, 0xab, 0x89, 0x98, 0xba, 0xdc, 0xfe,
0x10, 0x32, 0x54, 0x76, 0xc3, 0xd2, 0xe1, 0xf0, 0x36, 0x36, 0x36, 0x36,
0x30, 0x80, 0x20, 0x40, 0xb0, 0xb5, 0x0f, 0x1c, 0x15, 0x4d, 0xe9, 0x1d,
-0xc9, 0x31, 0x15, 0x4c, 0x23, 0x1c, 0x15, 0x4a, 0x00, 0x20, 0xfb, 0xf7,
-0x50, 0xfc, 0xe9, 0x1d, 0xff, 0x31, 0x1e, 0x31, 0x23, 0x1c, 0x0d, 0x1c,
-0x11, 0x4a, 0x01, 0x20, 0xfb, 0xf7, 0x47, 0xfc, 0x29, 0x1c, 0x23, 0x1c,
-0x0e, 0x4a, 0x00, 0x20, 0xfb, 0xf7, 0x41, 0xfc,
-0x39, 0x1c, 0x23, 0x1c, 0x0c, 0x4a, 0x01, 0x20, 0xfb, 0xf7, 0x3b, 0xfc,
-0x00, 0x21, 0x0b, 0x48, 0xc2, 0x1d, 0x19, 0x32, 0x51, 0x71, 0x01, 0x21,
-0xff, 0x30, 0x01, 0x30, 0x41, 0x62, 0x08, 0x1c, 0xb0, 0xbc, 0x08, 0xbc,
-0x18, 0x47, 0x00, 0x00, 0x1c, 0xad, 0x20, 0x40, 0x75, 0x08, 0xff, 0xff,
-0x28, 0x00, 0x03, 0x00, 0x40, 0x00, 0x02, 0x00, 0x14, 0x00, 0x07, 0x00,
-0x6c, 0x06, 0x00, 0x80, 0xf0, 0xb5, 0x37, 0x4a, 0x50, 0x69, 0x01, 0x23,
-0x9b, 0x07, 0x08, 0x30, 0x18, 0x43, 0x00, 0x68, 0x01, 0x06, 0x09, 0x0e,
-0x33, 0x4b, 0x01, 0x29, 0x49, 0xd1, 0x1f, 0x68, 0x19, 0x1c, 0x32, 0x4b,
-0x9f, 0x42, 0x04, 0xd1, 0xff, 0xf7, 0x3e, 0xff, 0xf0, 0xbc, 0x08, 0xbc,
-0x18, 0x47, 0x00, 0x23, 0x9f, 0x00, 0xcc, 0x59, 0x55, 0x69, 0xef, 0x19,
-0x3c, 0x61, 0x01, 0x33, 0x05, 0x2b, 0xf7, 0xd3, 0x00, 0x0a, 0x00, 0x02,
-0x02, 0x23, 0x18, 0x43, 0x53, 0x69, 0xc0, 0x46, 0x98, 0x60, 0x50, 0x69,
-0x08, 0x23, 0xc2, 0x68, 0x13, 0x40, 0x25, 0x4f, 0xfa, 0x1d, 0xb9, 0x32,
-0x00, 0x2b, 0x02, 0xd0, 0x04, 0x23, 0x23, 0x4c, 0x01, 0xe0, 0x05, 0x23,
-0x22, 0x4c, 0xc0, 0x46, 0x14, 0x61, 0x40, 0x24, 0xd4, 0x82, 0x00, 0x24,
-0x54, 0x83, 0x20, 0x4c, 0x00, 0x22, 0x00, 0x2b, 0x0c, 0xd9, 0x95, 0x00,
+0xc9, 0x31, 0x15, 0x4c, 0x23, 0x1c, 0x15, 0x4a, 0x00, 0x20, 0xfc, 0xf7,
+0x44, 0xfb, 0xe9, 0x1d, 0xff, 0x31, 0x1e, 0x31, 0x23, 0x1c, 0x0d, 0x1c,
+0x11, 0x4a, 0x01, 0x20, 0xfc, 0xf7, 0x3b, 0xfb, 0x29, 0x1c, 0x23, 0x1c,
+0x0e, 0x4a, 0x00, 0x20, 0xfc, 0xf7, 0x35, 0xfb, 0x39, 0x1c, 0x23, 0x1c,
+0x0c, 0x4a, 0x01, 0x20, 0xfc, 0xf7, 0x2f, 0xfb, 0x00, 0x21, 0x0b, 0x48,
+0xc2, 0x1d, 0x19, 0x32, 0x51, 0x71, 0x01, 0x21, 0xff, 0x30, 0x01, 0x30,
+0x41, 0x62, 0x08, 0x1c, 0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00,
+0xac, 0xab, 0x20, 0x40, 0x75, 0x08, 0xff, 0xff, 0x28, 0x00, 0x03, 0x00,
+0x40, 0x00, 0x02, 0x00, 0x14, 0x00, 0x07, 0x00, 0x6c, 0x06, 0x00, 0x80,
+0xf0, 0xb5, 0x37, 0x4a, 0x50, 0x69, 0x01, 0x23, 0x9b, 0x07, 0x08, 0x30,
+0x18, 0x43, 0x00, 0x68, 0x01, 0x06, 0x09, 0x0e, 0x33, 0x4b, 0x01, 0x29,
+0x49, 0xd1, 0x1f, 0x68, 0x19, 0x1c, 0x32, 0x4b, 0x9f, 0x42, 0x04, 0xd1,
+0xff, 0xf7, 0x3e, 0xff, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x23,
+0x9f, 0x00, 0xcc, 0x59, 0x55, 0x69, 0xef, 0x19, 0x3c, 0x61, 0x01, 0x33,
+0x05, 0x2b, 0xf7, 0xd3, 0x00, 0x0a, 0x00, 0x02, 0x02, 0x23, 0x18, 0x43,
+0x53, 0x69, 0xc0, 0x46, 0x98, 0x60, 0x50, 0x69, 0x08, 0x23, 0xc2, 0x68,
+0x13, 0x40, 0x25, 0x4f, 0xfa, 0x1d, 0xb9, 0x32, 0x00, 0x2b, 0x02, 0xd0,
+0x04, 0x23, 0x23, 0x4c, 0x01, 0xe0, 0x05, 0x23, 0x22, 0x4c, 0xc0, 0x46,
+0x14, 0x61, 0x40, 0x24, 0xd4, 0x82, 0x00, 0x24, 0x54, 0x83, 0x20, 0x4c,
+0x00, 0x22, 0x00, 0x2b, 0x0c, 0xd9, 0x95, 0x00,
0x46, 0x19, 0x76, 0x6a, 0x66, 0x40, 0xed, 0x19, 0xff, 0x35, 0x01, 0x35,
0x6e, 0x62, 0x01, 0x32, 0x9a, 0x42, 0xf4, 0xd3, 0x10, 0x2a, 0x07, 0xd2,
0x93, 0x00, 0xdb, 0x19, 0xff, 0x33, 0x01, 0x33, 0x5c, 0x62, 0x01, 0x32,
@@ -3710,26 +3351,51 @@ const u8 typhoon_firmware_image[] = {
0x8f, 0x00, 0xdc, 0x59, 0x55, 0x69, 0xef, 0x19, 0x7c, 0x62, 0x01, 0x31,
0x05, 0x29, 0xf7, 0xd3, 0x00, 0x0a, 0x00, 0x02, 0x03, 0x23, 0x18, 0x43,
0x51, 0x69, 0xc0, 0x46, 0x88, 0x60, 0x50, 0x69, 0x40, 0x68, 0xc0, 0x46,
-0x50, 0x61, 0x09, 0x48, 0xfb, 0xf7, 0xb0, 0xfb, 0xa4, 0xe7, 0x00, 0x00,
+0x50, 0x61, 0x09, 0x48, 0xfc, 0xf7, 0xa4, 0xfa, 0xa4, 0xe7, 0x00, 0x00,
0x6c, 0x06, 0x00, 0x80, 0x30, 0x80, 0x20, 0x40, 0x67, 0x45, 0x23, 0x01,
-0x1c, 0xad, 0x20, 0x40, 0x28, 0x01, 0x40, 0x00, 0x20, 0x01, 0x40, 0x00,
-0x5c, 0x5c, 0x5c, 0x5c, 0xfd, 0x30, 0xff, 0xff, 0x80, 0xb5, 0x87, 0xb0,
-0x0f, 0x1c, 0x39, 0x1c, 0x00, 0xf0, 0x48, 0xf8, 0x0e, 0x49, 0xc8, 0x68,
-0x02, 0x04, 0x89, 0x69, 0x4a, 0x40, 0x05, 0x92, 0x09, 0x04, 0xc9, 0x43,
-0xc0, 0x43, 0x48, 0x40, 0x06, 0x90, 0x08, 0x21, 0x6a, 0x46, 0x05, 0xa8,
-0xfd, 0xf7, 0x8b, 0xfb, 0x00, 0x98, 0xc0, 0x46, 0x38, 0x65, 0x03, 0x98,
-0xc0, 0x46, 0x78, 0x65, 0x04, 0x48, 0x01, 0x89, 0x01, 0x31, 0x01, 0x81,
-0x07, 0xb0, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x08, 0x83, 0x20, 0x40,
-0x0c, 0x2b, 0x00, 0x80, 0x90, 0xb5, 0x04, 0x1c, 0x0f, 0x1c, 0x20, 0x1c,
-0x39, 0x1c, 0x00, 0xf0, 0x1f, 0xf8, 0xe0, 0x68, 0x01, 0x0e, 0xff, 0x22,
-0x12, 0x04, 0x02, 0x40, 0x12, 0x0a, 0x11, 0x43, 0xff, 0x22, 0x12, 0x02,
-0x02, 0x40, 0x12, 0x02, 0x11, 0x43, 0x00, 0x06, 0x08, 0x43, 0x38, 0x65,
-0x20, 0x69, 0xc0, 0x46, 0x78, 0x65, 0x60, 0x69, 0xc0, 0x46, 0xb8, 0x65,
-0x03, 0x48, 0x01, 0x89, 0x01, 0x31, 0x01, 0x81, 0x90, 0xbc, 0x08, 0xbc,
-0x18, 0x47, 0x00, 0x00, 0x0c, 0x2b, 0x00, 0x80, 0x90, 0xb5, 0x00, 0x22,
-0x93, 0x00, 0x1f, 0x18, 0xbf, 0x69, 0x5b, 0x18, 0x5f, 0x62, 0x01, 0x32,
-0x05, 0x2a, 0xf7, 0xd3, 0x07, 0x7a, 0xfb, 0x08, 0x03, 0xd3, 0x00, 0x23,
-0x92, 0x00, 0x52, 0x18, 0x13, 0x62, 0x07, 0x6b,
+0xac, 0xab, 0x20, 0x40, 0x28, 0x01, 0x40, 0x00, 0x20, 0x01, 0x40, 0x00,
+0x5c, 0x5c, 0x5c, 0x5c, 0x11, 0x31, 0xff, 0xff, 0xf0, 0xb5, 0x07, 0x1c,
+0x3b, 0x48, 0x3c, 0x4c, 0x08, 0x21, 0x20, 0x60, 0xa1, 0x80, 0x00, 0x20,
+0x20, 0x81, 0xe1, 0x80, 0x60, 0x81, 0x39, 0x48, 0xc0, 0x46, 0xe0, 0x60,
+0x38, 0x48, 0xc0, 0x46, 0x20, 0x61, 0x38, 0x48, 0xc0, 0x46, 0x60, 0x61,
+0x37, 0x48, 0xc0, 0x46, 0xa0, 0x61, 0x37, 0x48, 0xc0, 0x46, 0xe0, 0x61,
+0x36, 0x48, 0xc0, 0x46, 0x20, 0x62, 0x36, 0x48, 0xc0, 0x46, 0x60, 0x62,
+0x35, 0x48, 0xc0, 0x46, 0xa0, 0x62, 0x35, 0x48, 0xc0, 0x46, 0xe0, 0x62,
+0x34, 0x48, 0xc0, 0x46, 0x20, 0x63, 0x34, 0x48, 0xc0, 0x46, 0x60, 0x63,
+0x33, 0x48, 0xc0, 0x46, 0xa0, 0x63, 0x33, 0x48, 0xc0, 0x46, 0xe0, 0x63,
+0x32, 0x48, 0xc0, 0x46, 0x20, 0x64, 0x32, 0x48, 0xc0, 0x46, 0x60, 0x64,
+0x31, 0x48, 0xc0, 0x46, 0xa0, 0x64, 0x31, 0x48, 0xc0, 0x46, 0xe0, 0x64,
+0x30, 0x48, 0xc0, 0x46, 0x20, 0x65, 0x30, 0x49, 0xc8, 0x68, 0x02, 0x04,
+0x89, 0x69, 0x4a, 0x40, 0xe3, 0x1d, 0x79, 0x33, 0x09, 0x04, 0xc9, 0x43,
+0xc0, 0x43, 0x48, 0x40, 0xe1, 0x1d, 0xb9, 0x31, 0xda, 0x63, 0x08, 0x60,
+0x29, 0x4d, 0x21, 0x1c, 0x2b, 0x1c, 0x29, 0x4a, 0x00, 0x20, 0xfc, 0xf7,
+0x3e, 0xfa, 0x28, 0x4a, 0xe1, 0x1d, 0xb5, 0x31, 0x01, 0x20, 0x2b, 0x1c,
+0x0e, 0x1c, 0xfc, 0xf7, 0x36, 0xfa, 0x24, 0x4a, 0x00, 0x20, 0x31, 0x1c,
+0x2b, 0x1c, 0xfc, 0xf7, 0x30, 0xfa, 0xe1, 0x1d, 0x4d, 0x31, 0x2b, 0x1c,
+0x20, 0x4a, 0x01, 0x20, 0xfc, 0xf7, 0x29, 0xfa, 0xe0, 0x1d, 0x5d, 0x30,
+0x01, 0x68, 0x00, 0x29, 0xfc, 0xd0, 0x60, 0x6d, 0xc0, 0x46, 0x38, 0x65,
+0x20, 0x6e, 0xc0, 0x46, 0x78, 0x65, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47,
+0x80, 0x00, 0x08, 0x00, 0x8c, 0xb9, 0x20, 0x40, 0x81, 0x81, 0x48, 0xbd,
+0x79, 0x56, 0x23, 0x8c, 0x93, 0x0c, 0x82, 0x95, 0x1d, 0x0e, 0x12, 0xcf,
+0x9b, 0x3b, 0xc0, 0xe9, 0xe6, 0x55, 0x7c, 0x82, 0x99, 0xf6, 0x78, 0x02,
+0xd1, 0xd7, 0x25, 0x73, 0x72, 0x8c, 0x33, 0x10, 0xf7, 0x03, 0xf1, 0x42,
+0x6c, 0x9b, 0x4a, 0xa7, 0x82, 0x8e, 0x23, 0xa9, 0x90, 0xb1, 0x82, 0x8e,
+0xdc, 0x3f, 0xfb, 0x29, 0x00, 0x62, 0x22, 0x45, 0x88, 0x2b, 0xf1, 0x85,
+0x12, 0x61, 0xd1, 0x73, 0x6e, 0xb1, 0x11, 0x16, 0x08, 0x83, 0x20, 0x40,
+0x75, 0x08, 0xff, 0xff, 0x54, 0x00, 0x03, 0x00, 0x08, 0x00, 0x02, 0x00,
+0x14, 0x00, 0x03, 0x00, 0x80, 0xb5, 0x0f, 0x1c, 0x39, 0x1c, 0x00, 0xf0,
+0x33, 0xf8, 0x38, 0x1c, 0xff, 0xf7, 0x4c, 0xff, 0x03, 0x48, 0x01, 0x89,
+0x01, 0x31, 0x01, 0x81, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00,
+0x0c, 0x2b, 0x00, 0x80, 0x90, 0xb5, 0x04, 0x1c,
+0x0f, 0x1c, 0x20, 0x1c, 0x39, 0x1c, 0x00, 0xf0, 0x1f, 0xf8, 0xe0, 0x68,
+0x01, 0x0e, 0xff, 0x22, 0x12, 0x04, 0x02, 0x40, 0x12, 0x0a, 0x11, 0x43,
+0xff, 0x22, 0x12, 0x02, 0x02, 0x40, 0x12, 0x02, 0x11, 0x43, 0x00, 0x06,
+0x08, 0x43, 0x38, 0x65, 0x20, 0x69, 0xc0, 0x46, 0x78, 0x65, 0x60, 0x69,
+0xc0, 0x46, 0xb8, 0x65, 0x03, 0x48, 0x01, 0x89, 0x01, 0x31, 0x01, 0x81,
+0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x0c, 0x2b, 0x00, 0x80,
+0x90, 0xb5, 0x00, 0x22, 0x93, 0x00, 0x1f, 0x18, 0xbf, 0x69, 0x5b, 0x18,
+0x5f, 0x62, 0x01, 0x32, 0x05, 0x2a, 0xf7, 0xd3, 0x07, 0x7a, 0xfb, 0x08,
+0x03, 0xd3, 0x00, 0x23, 0x92, 0x00, 0x52, 0x18, 0x13, 0x62, 0x07, 0x6b,
0xc0, 0x46, 0x8f, 0x63, 0xc7, 0x6a, 0xc0, 0x46, 0xcf, 0x63, 0x87, 0x6b,
0xc0, 0x46, 0x0f, 0x64, 0x47, 0x6b, 0xc0, 0x46, 0x4f, 0x64, 0x07, 0x6c,
0xc0, 0x46, 0x8f, 0x64, 0xc2, 0x6b, 0xc0, 0x46, 0xca, 0x64, 0xc2, 0x88,
@@ -3740,7 +3406,7 @@ const u8 typhoon_firmware_image[] = {
0x00, 0x22, 0x00, 0x7a, 0x43, 0x08, 0x10, 0xd3, 0xc0, 0x08, 0x02, 0xd3,
0x88, 0x20, 0x10, 0x43, 0x01, 0xe0, 0x80, 0x20, 0x10, 0x43, 0x3a, 0x0a,
0x12, 0x02, 0x01, 0x23, 0x1a, 0x43, 0xc8, 0x60, 0x8a, 0x60, 0x08, 0x1c,
-0xff, 0xf7, 0x0e, 0xfe, 0x05, 0xe0, 0x38, 0x0a, 0x00, 0x02, 0x03, 0x23,
+0xff, 0xf7, 0x78, 0xfd, 0x05, 0xe0, 0x38, 0x0a, 0x00, 0x02, 0x03, 0x23,
0x18, 0x43, 0x88, 0x60, 0xca, 0x60, 0x03, 0x48, 0x01, 0x89, 0x01, 0x31,
0x01, 0x81, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x0c, 0x2b, 0x00, 0x80,
0xf0, 0xb4, 0x02, 0x6d, 0x14, 0x4c, 0x15, 0x1c, 0xe7, 0x69, 0xbd, 0x40,
@@ -3754,458 +3420,283 @@ const u8 typhoon_firmware_image[] = {
0x80, 0xb4, 0x00, 0x22, 0x00, 0x23, 0x00, 0x29, 0x05, 0xd9, 0x07, 0x78,
0x7a, 0x40, 0x01, 0x30, 0x01, 0x33, 0x8b, 0x42, 0xf9, 0xd3, 0xd0, 0x43,
0x00, 0x06, 0x00, 0x0e, 0x80, 0xbc, 0x70, 0x47, 0xf0, 0xb5, 0x07, 0x1c,
-0x00, 0x24, 0xff, 0x26, 0x09, 0x36, 0x20, 0x1c, 0x00, 0xf0, 0x8c, 0xf8,
-0x00, 0xf0, 0x9e, 0xf9, 0x05, 0x1c, 0x00, 0xf0, 0xad, 0xfa, 0x3d, 0x70,
+0x00, 0x24, 0xff, 0x26, 0x09, 0x36, 0x20, 0x1c, 0x00, 0xf0, 0x9a, 0xf8,
+0x00, 0xf0, 0xb8, 0xf9, 0x05, 0x1c, 0x00, 0xf0, 0xc7, 0xfa, 0x3d, 0x70,
0x28, 0x1c, 0x01, 0x37, 0x01, 0x34, 0xb4, 0x42, 0xf1, 0xd3, 0xf0, 0xbc,
-0x08, 0xbc, 0x18, 0x47, 0x80, 0xb5, 0x00, 0xf0, 0x85, 0xf8, 0x00, 0xf0,
-0x8d, 0xf9, 0x07, 0x1c, 0x00, 0xf0, 0x9c, 0xfa, 0x38, 0x0a, 0xf6, 0xd3,
-0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xf3, 0xb5, 0x81, 0xb0, 0x41, 0x02,
-0x53, 0x20, 0x00, 0xf0, 0x57, 0xf8, 0x00, 0xf0, 0x8f, 0xfa, 0xff, 0xf7,
-0xe9, 0xff, 0x00, 0x24, 0x00, 0x26, 0x00, 0x25, 0x00, 0x27, 0x30, 0x1c,
-0x01, 0x36, 0x00, 0xf0, 0x5f, 0xf8, 0x00, 0xf0, 0x71, 0xf9, 0x00, 0x90,
-0x00, 0xf0, 0x80, 0xfa, 0xf8, 0x00, 0x00, 0x99, 0x81, 0x40, 0x0d, 0x43,
-0x01, 0x34, 0x01, 0x37, 0x04, 0x2f, 0xee, 0xd3, 0x02, 0x99, 0x20, 0xc1,
-0x02, 0x91, 0xff, 0x23, 0x09, 0x33, 0x9c, 0x42, 0xe5, 0xd3, 0x03, 0xb0,
-0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xf0, 0xb5, 0x04, 0x1c, 0x0f, 0x1c,
-0x16, 0x48, 0xc0, 0x6f, 0x40, 0x23, 0x01, 0x68, 0x19, 0x43, 0x01, 0x60,
-0x00, 0x26, 0x20, 0xcf, 0xb1, 0x00, 0x84, 0x20, 0x00, 0xf0, 0x24, 0xf8,
-0x28, 0x1c, 0x00, 0xf0, 0xd3, 0xf9, 0x28, 0x0a, 0x00, 0xf0, 0xd0, 0xf9,
-0x28, 0x0c, 0x00, 0xf0, 0xcd, 0xf9, 0x28, 0x0e, 0x00, 0xf0, 0xca, 0xf9,
-0x00, 0xf0, 0x50, 0xfa, 0x01, 0x36, 0x42, 0x2e, 0xe9, 0xd3, 0x61, 0x02,
-0x83, 0x20, 0x00, 0xf0, 0x0f, 0xf8, 0x00, 0xf0,
-0x47, 0xfa, 0xff, 0xf7, 0xa1, 0xff, 0x04, 0x48, 0xc0, 0x6f, 0x40, 0x23,
-0x01, 0x68, 0x99, 0x43, 0x01, 0x60, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47,
-0x68, 0x0e, 0x00, 0x80, 0x90, 0xb5, 0x04, 0x1c, 0x0f, 0x1c, 0x00, 0xf0,
-0x4d, 0xfa, 0x20, 0x1c, 0x00, 0xf0, 0xaa, 0xf9, 0x38, 0x0c, 0x00, 0xf0,
-0xa7, 0xf9, 0x38, 0x0a, 0x00, 0xf0, 0xa4, 0xf9, 0x38, 0x1c, 0x00, 0xf0,
-0xa1, 0xf9, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0x01, 0x1c,
-0x54, 0x20, 0xff, 0xf7, 0xe7, 0xff, 0x00, 0x20, 0x00, 0xf0, 0x96, 0xf9,
-0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0x00, 0xf0, 0x31, 0xfa, 0x57, 0x20,
-0x00, 0xf0, 0x8e, 0xf9, 0x08, 0xbc, 0x18, 0x47, 0x90, 0xb5, 0x08, 0x4f,
-0xfa, 0x6f, 0x20, 0x23, 0x14, 0x68, 0x9c, 0x43, 0x14, 0x60, 0x23, 0x1c,
-0xff, 0xf7, 0x73, 0xff, 0xf8, 0x6f, 0x20, 0x23, 0x01, 0x68, 0x19, 0x43,
-0x01, 0x60, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x68, 0x0e, 0x00, 0x80,
+0x08, 0xbc, 0x18, 0x47, 0x80, 0xb5, 0x00, 0xf0, 0x93, 0xf8, 0x00, 0xf0,
+0xa7, 0xf9, 0x07, 0x1c, 0x00, 0xf0, 0xb6, 0xfa, 0x38, 0x0a, 0xf6, 0xd3,
+0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xf3, 0xb5, 0x82, 0xb0, 0x02, 0x98,
+0x41, 0x02, 0x53, 0x20, 0x00, 0xf0, 0x64, 0xf8, 0x00, 0xf0, 0xa8, 0xfa,
+0xff, 0xf7, 0xe8, 0xff, 0x00, 0x24, 0x00, 0x20, 0x01, 0x90, 0x2e, 0x20,
+0x00, 0x90, 0x00, 0x25, 0x00, 0x27, 0x02, 0x98, 0x01, 0x28, 0x04, 0xd1,
+0x00, 0x98, 0x84, 0x42, 0x01, 0xd3, 0x00, 0x26,
+0x09, 0xe0, 0x01, 0x98, 0x41, 0x1c, 0x01, 0x91, 0x00, 0xf0, 0x60, 0xf8,
+0x00, 0xf0, 0x7e, 0xf9, 0x06, 0x1c, 0x00, 0xf0, 0x8d, 0xfa, 0xf8, 0x00,
+0x86, 0x40, 0x35, 0x43, 0x01, 0x34, 0x01, 0x37, 0x04, 0x2f, 0xe6, 0xd3,
+0x03, 0x99, 0x20, 0xc1, 0x03, 0x91, 0xff, 0x23, 0x09, 0x33, 0x9c, 0x42,
+0xdd, 0xd3, 0x04, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xf0, 0xb5,
+0x04, 0x1c, 0x0f, 0x1c, 0x01, 0x2c, 0x2a, 0xd0, 0x16, 0x48, 0xc0, 0x6f,
+0x40, 0x23, 0x01, 0x68, 0x19, 0x43, 0x01, 0x60, 0x00, 0x26, 0x20, 0xcf,
+0xb1, 0x00, 0x84, 0x20, 0x00, 0xf0, 0x24, 0xf8, 0x28, 0x1c, 0x00, 0xf0,
+0xdf, 0xf9, 0x28, 0x0a, 0x00, 0xf0, 0xdc, 0xf9, 0x28, 0x0c, 0x00, 0xf0,
+0xd9, 0xf9, 0x28, 0x0e, 0x00, 0xf0, 0xd6, 0xf9, 0x00, 0xf0, 0x5c, 0xfa,
+0x01, 0x36, 0x42, 0x2e, 0xe9, 0xd3, 0x61, 0x02, 0x83, 0x20, 0x00, 0xf0,
+0x0f, 0xf8, 0x00, 0xf0, 0x53, 0xfa, 0xff, 0xf7, 0x93, 0xff, 0x04, 0x48,
+0xc0, 0x6f, 0x40, 0x23, 0x01, 0x68, 0x99, 0x43, 0x01, 0x60, 0xf0, 0xbc,
+0x08, 0xbc, 0x18, 0x47, 0x68, 0x0e, 0x00, 0x80, 0x90, 0xb5, 0x04, 0x1c,
+0x0f, 0x1c, 0x00, 0xf0, 0x59, 0xfa, 0x20, 0x1c, 0x00, 0xf0, 0xb6, 0xf9,
+0x38, 0x0c, 0x00, 0xf0, 0xb3, 0xf9, 0x38, 0x0a, 0x00, 0xf0, 0xb0, 0xf9,
+0x38, 0x1c, 0x00, 0xf0, 0xad, 0xf9, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47,
+0x00, 0xb5, 0x01, 0x1c, 0x54, 0x20, 0xff, 0xf7, 0xe7, 0xff, 0x00, 0x20,
+0x00, 0xf0, 0xa2, 0xf9, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0x00, 0xf0,
+0x3d, 0xfa, 0x57, 0x20, 0x00, 0xf0, 0x9a, 0xf9, 0x08, 0xbc, 0x18, 0x47,
0x90, 0xb5, 0x08, 0x4f, 0xfa, 0x6f, 0x20, 0x23, 0x14, 0x68, 0x9c, 0x43,
-0x14, 0x60, 0x23, 0x1c, 0xff, 0xf7, 0x89, 0xff, 0xf8, 0x6f, 0x20, 0x23,
+0x14, 0x60, 0x23, 0x1c, 0xff, 0xf7, 0x65, 0xff, 0xf8, 0x6f, 0x20, 0x23,
0x01, 0x68, 0x19, 0x43, 0x01, 0x60, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47,
-0x68, 0x0e, 0x00, 0x80, 0xb0, 0xb5, 0x0f, 0x1c, 0x15, 0x4d, 0xe9, 0x6f,
-0x20, 0x23, 0x0a, 0x68, 0x9a, 0x43, 0x0a, 0x60, 0x41, 0x02, 0x53, 0x20,
-0xff, 0xf7, 0xa6, 0xff, 0x00, 0xf0, 0xde, 0xf9, 0xff, 0xf7, 0x38, 0xff,
-0xf8, 0x1d, 0x05, 0x30, 0x44, 0x1c, 0xff, 0xf7, 0xb1, 0xff, 0x00, 0xf0,
-0xc3, 0xf8, 0x07, 0x1c, 0x00, 0xf0, 0xd2, 0xf9, 0x20, 0x1c, 0xff, 0xf7,
-0xa9, 0xff, 0x00, 0xf0, 0xbb, 0xf8, 0x04, 0x1c, 0x00, 0xf0, 0xca, 0xf9,
-0xe8, 0x6f, 0x20, 0x23, 0x01, 0x68, 0x19, 0x43, 0x01, 0x60, 0x21, 0x02,
-0x39, 0x43, 0x08, 0x1c, 0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00,
-0x68, 0x0e, 0x00, 0x80, 0xf0, 0xb5, 0xc2, 0xb0, 0x04, 0x1c, 0x0d, 0x1c,
-0x17, 0x1c, 0x61, 0x02, 0x19, 0x4e, 0xf0, 0x6f, 0x20, 0x23, 0x02, 0x68,
-0x9a, 0x43, 0x02, 0x60, 0x53, 0x20, 0xff, 0xf7, 0x73, 0xff, 0x00, 0xf0,
-0xab, 0xf9, 0xff, 0xf7, 0x05, 0xff, 0x68, 0x46, 0xff, 0xf7, 0xec, 0xfe,
-0x6a, 0x46, 0xe8, 0x1d, 0x05, 0x30, 0x17, 0x54, 0x39, 0x0a, 0x68, 0x44,
-0x41, 0x70, 0x68, 0x46, 0x00, 0x99, 0x0c, 0x30, 0xff, 0xf7, 0xd0, 0xfe,
-0x02, 0xab, 0x18, 0x70, 0x00, 0x20, 0x58, 0x70, 0x68, 0x46, 0x0c, 0x21,
-0xff, 0xf7, 0xc8, 0xfe, 0x02, 0xab, 0x58, 0x70, 0x69, 0x46, 0x20, 0x1c,
-0xff, 0xf7, 0x1f, 0xff, 0xf0, 0x6f, 0x20, 0x23, 0x01, 0x68, 0x19, 0x43,
+0x68, 0x0e, 0x00, 0x80, 0x90, 0xb5, 0x08, 0x4f, 0xfa, 0x6f, 0x20, 0x23,
+0x14, 0x68, 0x9c, 0x43, 0x14, 0x60, 0x23, 0x1c, 0xff, 0xf7, 0x87, 0xff,
+0xf8, 0x6f, 0x20, 0x23, 0x01, 0x68, 0x19, 0x43, 0x01, 0x60, 0x90, 0xbc,
+0x08, 0xbc, 0x18, 0x47, 0x68, 0x0e, 0x00, 0x80, 0xf0, 0xb5, 0x04, 0x1c,
+0x0f, 0x1c, 0x18, 0x4e, 0xf0, 0x6f, 0x20, 0x23, 0x01, 0x68, 0x99, 0x43,
+0x01, 0x60, 0x61, 0x02, 0x53, 0x20, 0xff, 0xf7, 0xa5, 0xff, 0x00, 0xf0,
+0xe9, 0xf9, 0xff, 0xf7, 0x29, 0xff, 0xf8, 0x1d, 0x05, 0x30, 0x01, 0x2c,
+0x03, 0xd1, 0x22, 0x2f, 0x01, 0xd3, 0x00, 0x27, 0x0f, 0xe0, 0x44, 0x1c,
+0xff, 0xf7, 0xaa, 0xff, 0x00, 0xf0, 0xc8, 0xf8, 0x07, 0x1c, 0x00, 0xf0,
+0xd7, 0xf9, 0x20, 0x1c, 0xff, 0xf7, 0xa2, 0xff, 0x00, 0xf0, 0xc0, 0xf8,
+0x05, 0x1c, 0x00, 0xf0, 0xcf, 0xf9, 0xf0, 0x6f, 0x20, 0x23, 0x01, 0x68,
+0x19, 0x43, 0x01, 0x60, 0x28, 0x02, 0x38, 0x43, 0xf0, 0xbc, 0x08, 0xbc,
+0x18, 0x47, 0x00, 0x00, 0x68, 0x0e, 0x00, 0x80, 0xf0, 0xb5, 0xc2, 0xb0,
+0x14, 0x1c, 0x0d, 0x1c, 0x07, 0x1c, 0x01, 0x2f, 0x2f, 0xd0, 0x79, 0x02,
+0x19, 0x4e, 0xf0, 0x6f, 0x20, 0x23, 0x02, 0x68, 0x9a, 0x43, 0x02, 0x60,
+0x53, 0x20, 0xff, 0xf7, 0x6b, 0xff, 0x00, 0xf0, 0xaf, 0xf9, 0xff, 0xf7,
+0xef, 0xfe, 0x68, 0x46, 0xff, 0xf7, 0xd6, 0xfe, 0x6a, 0x46, 0xe8, 0x1d,
+0x05, 0x30, 0x14, 0x54, 0x21, 0x0a, 0x68, 0x44, 0x41, 0x70, 0x68, 0x46,
+0x00, 0x99, 0x0c, 0x30, 0xff, 0xf7, 0xba, 0xfe, 0x02, 0xab, 0x18, 0x70,
+0x00, 0x20, 0x58, 0x70, 0x68, 0x46, 0x0c, 0x21,
+0xff, 0xf7, 0xb2, 0xfe, 0x02, 0xab, 0x58, 0x70, 0x69, 0x46, 0x38, 0x1c,
+0xff, 0xf7, 0x15, 0xff, 0xf0, 0x6f, 0x20, 0x23, 0x01, 0x68, 0x19, 0x43,
0x01, 0x60, 0x42, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00,
-0x68, 0x0e, 0x00, 0x80, 0xff, 0xb5, 0xc2, 0xb0, 0x07, 0x1c, 0x6b, 0x46,
-0x00, 0x20, 0xc4, 0x43, 0x10, 0xc3, 0x01, 0x30, 0x42, 0x28, 0xfb, 0xd3,
-0x68, 0x46, 0x0c, 0x30, 0x03, 0x1c, 0x00, 0x24, 0x00, 0x2a, 0x0a, 0xd9,
-0x0e, 0x88, 0xc0, 0x46, 0x06, 0x70, 0x0e, 0x88, 0x36, 0x12, 0x46, 0x70,
-0x02, 0x30, 0x02, 0x31, 0x02, 0x34, 0x94, 0x42, 0xf4, 0xd3, 0x00, 0x92,
-0x18, 0x1c, 0x11, 0x1c, 0xff, 0xf7, 0x96, 0xfe, 0x04, 0x1c, 0x00, 0x20,
-0x01, 0x90, 0x02, 0xab, 0x1c, 0x70, 0x58, 0x70, 0x9d, 0x70, 0x68, 0x46,
-0x0c, 0x21, 0xff, 0xf7, 0x8b, 0xfe, 0x02, 0xab, 0x58, 0x70, 0x45, 0x9b,
-0x1d, 0x06, 0x2d, 0x0e, 0xac, 0x42, 0x03, 0xd1, 0x69, 0x46, 0x38, 0x1c,
-0xff, 0xf7, 0x4a, 0xff, 0x01, 0x20, 0xac, 0x42,
-0x00, 0xd1, 0x00, 0x20, 0x46, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47,
-0xb0, 0xb5, 0xc2, 0xb0, 0x0f, 0x1c, 0x41, 0x02, 0x14, 0x4c, 0xe0, 0x6f,
-0x20, 0x23, 0x02, 0x68, 0x9a, 0x43, 0x02, 0x60, 0x53, 0x20, 0xff, 0xf7,
-0xfb, 0xfe, 0x00, 0xf0, 0x33, 0xf9, 0xff, 0xf7, 0x8d, 0xfe, 0x68, 0x46,
-0xff, 0xf7, 0x74, 0xfe, 0xe0, 0x6f, 0x20, 0x23, 0x01, 0x68, 0x19, 0x43,
-0x02, 0xad, 0x01, 0x60, 0x6d, 0x78, 0x00, 0x24, 0x02, 0xab, 0x5c, 0x70,
-0x68, 0x46, 0x0c, 0x21, 0xff, 0xf7, 0x56, 0xfe, 0xa8, 0x42, 0x02, 0xd1,
-0x00, 0x98, 0x87, 0x42, 0x01, 0xd3, 0x20, 0x1c, 0x00, 0xe0, 0x01, 0x20,
-0x42, 0xb0, 0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x68, 0x0e, 0x00, 0x80,
-0xfc, 0x46, 0x60, 0x47, 0x00, 0x00, 0xa0, 0xe3, 0xb4, 0x22, 0x9f, 0xe5,
-0xb4, 0x32, 0x9f, 0xe5, 0x01, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x82, 0xe5,
+0x68, 0x0e, 0x00, 0x80, 0xff, 0xb5, 0xc2, 0xb0, 0x07, 0x1c, 0x01, 0x2f,
+0x01, 0xd1, 0x01, 0x20, 0x36, 0xe0, 0x6b, 0x46, 0x00, 0x20, 0xc4, 0x43,
+0x10, 0xc3, 0x01, 0x30, 0x42, 0x28, 0xfb, 0xd3, 0x68, 0x46, 0x0c, 0x30,
+0x03, 0x1c, 0x00, 0x24, 0x00, 0x2a, 0x0a, 0xd9, 0x0e, 0x88, 0xc0, 0x46,
+0x06, 0x70, 0x0e, 0x88, 0x36, 0x12, 0x46, 0x70, 0x02, 0x30, 0x02, 0x31,
+0x02, 0x34, 0x94, 0x42, 0xf4, 0xd3, 0x00, 0x92, 0x18, 0x1c, 0x11, 0x1c,
+0xff, 0xf7, 0x7c, 0xfe, 0x04, 0x1c, 0x00, 0x20, 0x01, 0x90, 0x02, 0xab,
+0x1c, 0x70, 0x58, 0x70, 0x9d, 0x70, 0x68, 0x46, 0x0c, 0x21, 0xff, 0xf7,
+0x71, 0xfe, 0x02, 0xab, 0x58, 0x70, 0x45, 0x9b, 0x1d, 0x06, 0x2d, 0x0e,
+0xac, 0x42, 0x03, 0xd1, 0x69, 0x46, 0x38, 0x1c, 0xff, 0xf7, 0x3e, 0xff,
+0x01, 0x20, 0xac, 0x42, 0x00, 0xd1, 0x00, 0x20, 0x46, 0xb0, 0xf0, 0xbc,
+0x08, 0xbc, 0x18, 0x47, 0xb0, 0xb5, 0xc2, 0xb0, 0x0f, 0x1c, 0x41, 0x02,
+0x14, 0x4c, 0xe0, 0x6f, 0x20, 0x23, 0x02, 0x68, 0x9a, 0x43, 0x02, 0x60,
+0x53, 0x20, 0xff, 0xf7, 0xef, 0xfe, 0x00, 0xf0, 0x33, 0xf9, 0xff, 0xf7,
+0x73, 0xfe, 0x68, 0x46, 0xff, 0xf7, 0x5a, 0xfe, 0xe0, 0x6f, 0x20, 0x23,
+0x01, 0x68, 0x19, 0x43, 0x02, 0xad, 0x01, 0x60, 0x6d, 0x78, 0x00, 0x24,
+0x02, 0xab, 0x5c, 0x70, 0x68, 0x46, 0x0c, 0x21, 0xff, 0xf7, 0x3c, 0xfe,
+0xa8, 0x42, 0x02, 0xd1, 0x00, 0x98, 0x87, 0x42, 0x01, 0xd3, 0x20, 0x1c,
+0x00, 0xe0, 0x01, 0x20, 0x42, 0xb0, 0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47,
+0x68, 0x0e, 0x00, 0x80, 0xfc, 0x46, 0x60, 0x47, 0x00, 0x00, 0xa0, 0xe3,
+0xb4, 0x22, 0x9f, 0xe5, 0xb4, 0x32, 0x9f, 0xe5, 0x01, 0x10, 0xa0, 0xe3,
+0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0xa0, 0xe3,
+0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x93, 0xe5,
+0x81, 0x03, 0x80, 0xe1, 0x01, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x82, 0xe5,
0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x82, 0xe5,
-0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x93, 0xe5, 0x81, 0x03, 0x80, 0xe1,
+0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x93, 0xe5, 0x01, 0x03, 0x80, 0xe1,
0x01, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5,
0x00, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5,
-0x00, 0x10, 0x93, 0xe5, 0x01, 0x03, 0x80, 0xe1, 0x01, 0x10, 0xa0, 0xe3,
+0x00, 0x10, 0x93, 0xe5, 0x81, 0x02, 0x80, 0xe1, 0x01, 0x10, 0xa0, 0xe3,
0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0xa0, 0xe3,
0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x93, 0xe5,
-0x81, 0x02, 0x80, 0xe1, 0x01, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x82, 0xe5,
+0x01, 0x02, 0x80, 0xe1, 0x01, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x82, 0xe5,
0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x82, 0xe5,
-0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x93, 0xe5, 0x01, 0x02, 0x80, 0xe1,
+0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x93, 0xe5, 0x81, 0x01, 0x80, 0xe1,
0x01, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5,
0x00, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5,
-0x00, 0x10, 0x93, 0xe5, 0x81, 0x01, 0x80, 0xe1, 0x01, 0x10, 0xa0, 0xe3,
+0x00, 0x10, 0x93, 0xe5, 0x01, 0x01, 0x80, 0xe1, 0x01, 0x10, 0xa0, 0xe3,
+0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0xa0, 0xe3,
+0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x93, 0xe5,
+0x81, 0x00, 0x80, 0xe1, 0x01, 0x10, 0xa0, 0xe3,
0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0xa0, 0xe3,
0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x93, 0xe5,
-0x01, 0x01, 0x80, 0xe1, 0x01, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x82, 0xe5,
+0x01, 0x00, 0x80, 0xe1, 0x1e, 0xff, 0x2f, 0xe1, 0xfc, 0x46, 0x60, 0x47,
+0xa4, 0x21, 0x9f, 0xe5, 0xa8, 0x31, 0x9f, 0xe5, 0xa0, 0x13, 0xa0, 0xe1,
+0x00, 0x10, 0x83, 0xe5, 0x01, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x82, 0xe5,
0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x82, 0xe5,
-0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x93, 0xe5, 0x81, 0x00, 0x80, 0xe1,
+0x00, 0x10, 0x82, 0xe5, 0x20, 0x13, 0xa0, 0xe1, 0x00, 0x10, 0x83, 0xe5,
0x01, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5,
0x00, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5,
-0x00, 0x10, 0x93, 0xe5, 0x01, 0x00, 0x80, 0xe1, 0x1e, 0xff, 0x2f, 0xe1,
-0xfc, 0x46, 0x60, 0x47, 0xa4, 0x21, 0x9f, 0xe5, 0xa8, 0x31, 0x9f, 0xe5,
-0xa0, 0x13, 0xa0, 0xe1, 0x00, 0x10, 0x83, 0xe5, 0x01, 0x10, 0xa0, 0xe3,
+0xa0, 0x12, 0xa0, 0xe1, 0x00, 0x10, 0x83, 0xe5, 0x01, 0x10, 0xa0, 0xe3,
0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0xa0, 0xe3,
-0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5, 0x20, 0x13, 0xa0, 0xe1,
+0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5, 0x20, 0x12, 0xa0, 0xe1,
0x00, 0x10, 0x83, 0xe5, 0x01, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x82, 0xe5,
0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x82, 0xe5,
-0x00, 0x10, 0x82, 0xe5, 0xa0, 0x12, 0xa0, 0xe1, 0x00, 0x10, 0x83, 0xe5,
+0x00, 0x10, 0x82, 0xe5, 0xa0, 0x11, 0xa0, 0xe1, 0x00, 0x10, 0x83, 0xe5,
0x01, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5,
0x00, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5,
-0x20, 0x12, 0xa0, 0xe1, 0x00, 0x10, 0x83, 0xe5, 0x01, 0x10, 0xa0, 0xe3,
-0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5,
-0x00, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5,
-0xa0, 0x11, 0xa0, 0xe1, 0x00, 0x10, 0x83, 0xe5, 0x01, 0x10, 0xa0, 0xe3,
+0x20, 0x11, 0xa0, 0xe1, 0x00, 0x10, 0x83, 0xe5, 0x01, 0x10, 0xa0, 0xe3,
0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0xa0, 0xe3,
-0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5, 0x20, 0x11, 0xa0, 0xe1,
+0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5, 0xa0, 0x10, 0xa0, 0xe1,
0x00, 0x10, 0x83, 0xe5, 0x01, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x82, 0xe5,
0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x82, 0xe5,
-0x00, 0x10, 0x82, 0xe5, 0xa0, 0x10, 0xa0, 0xe1, 0x00, 0x10, 0x83, 0xe5,
+0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0xa0, 0xe1, 0x00, 0x10, 0x83, 0xe5,
0x01, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5,
0x00, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5,
-0x00, 0x10, 0xa0, 0xe1, 0x00, 0x10, 0x83, 0xe5, 0x01, 0x10, 0xa0, 0xe3,
-0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0xa0, 0xe3,
-0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5, 0x1e, 0xff, 0x2f, 0xe1,
-0xfc, 0x46, 0x60, 0x47, 0xa0, 0x30, 0x9f, 0xe5, 0x01, 0x10, 0xa0, 0xe3,
+0x1e, 0xff, 0x2f, 0xe1, 0xfc, 0x46, 0x60, 0x47, 0xa0, 0x30, 0x9f, 0xe5,
+0x01, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x83, 0xe5, 0x00, 0x10, 0x83, 0xe5,
0x00, 0x10, 0x83, 0xe5, 0x00, 0x10, 0x83, 0xe5, 0x00, 0x10, 0x83, 0xe5,
0x00, 0x10, 0x83, 0xe5, 0x00, 0x10, 0x83, 0xe5, 0x00, 0x10, 0x83, 0xe5,
-0x00, 0x10, 0x83, 0xe5, 0x00, 0x10, 0x83, 0xe5, 0x1e, 0xff, 0x2f, 0xe1,
-0xfc, 0x46, 0x60, 0x47, 0x70, 0x30, 0x9f, 0xe5, 0x00, 0x10, 0xa0, 0xe3,
+0x1e, 0xff, 0x2f, 0xe1, 0xfc, 0x46, 0x60, 0x47, 0x70, 0x30, 0x9f, 0xe5,
+0x00, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x83, 0xe5, 0x00, 0x10, 0x83, 0xe5,
0x00, 0x10, 0x83, 0xe5, 0x00, 0x10, 0x83, 0xe5, 0x00, 0x10, 0x83, 0xe5,
0x00, 0x10, 0x83, 0xe5, 0x00, 0x10, 0x83, 0xe5, 0x00, 0x10, 0x83, 0xe5,
-0x00, 0x10, 0x83, 0xe5, 0x00, 0x10, 0x83, 0xe5, 0x1e, 0xff, 0x2f, 0xe1,
-0xfc, 0x46, 0x60, 0x47, 0x34, 0x20, 0x9f, 0xe5, 0x3c, 0x30, 0x9f, 0xe5,
-0x00, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5,
-0x01, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x83, 0xe5, 0x00, 0x10, 0x83, 0xe5,
+0x1e, 0xff, 0x2f, 0xe1, 0xfc, 0x46, 0x60, 0x47, 0x34, 0x20, 0x9f, 0xe5,
+0x3c, 0x30, 0x9f, 0xe5, 0x00, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x82, 0xe5,
+0x00, 0x10, 0x82, 0xe5, 0x01, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x83, 0xe5,
0x00, 0x10, 0x83, 0xe5, 0x00, 0x10, 0x83, 0xe5, 0x00, 0x10, 0x83, 0xe5,
0x00, 0x10, 0x83, 0xe5, 0x00, 0x10, 0x83, 0xe5, 0x00, 0x10, 0x83, 0xe5,
-0x1e, 0xff, 0x2f, 0xe1, 0xf8, 0x00, 0x18, 0x40, 0x04, 0x01, 0x18, 0x40,
-0x00, 0x01, 0x18, 0x40, 0xfc, 0x00, 0x18, 0x40, 0x02, 0x1c, 0x00, 0x20,
-0x00, 0x29, 0x07, 0xdd, 0x13, 0x78, 0xc0, 0x18, 0x00, 0x06, 0x00, 0x0e,
-0x01, 0x32, 0x01, 0x39, 0x00, 0x29, 0xf7, 0xdc, 0x70, 0x47, 0x09, 0x4b,
-0xc9, 0x18, 0x04, 0x29, 0x08, 0xd8, 0x8c, 0x22, 0x4a, 0x43, 0x07, 0x4b,
-0xd2, 0x18, 0x13, 0x7a, 0x09, 0x06, 0x09, 0x0e, 0x8b, 0x42, 0x01, 0xd0,
-0x14, 0x20, 0x70, 0x47, 0x02, 0x60, 0x00, 0x20, 0xfb, 0xe7, 0x00, 0x00,
-0xf3, 0x0f, 0x01, 0x35, 0xb0, 0x6e, 0x21, 0x40, 0x01, 0x1c, 0x00, 0x22,
-0x06, 0x48, 0x03, 0x7a, 0xff, 0x2b, 0x04, 0xd0, 0x8c, 0x30, 0x01, 0x32,
-0x04, 0x2a, 0xf8, 0xd3, 0x01, 0xe0, 0x04, 0x2a, 0x00, 0xd3, 0x00, 0x20,
-0x0a, 0x60, 0x70, 0x47, 0xb0, 0x6e, 0x21, 0x40, 0xf0, 0xb5, 0x07, 0x1c,
-0x00, 0x24, 0x00, 0x2f, 0x21, 0xd0, 0x00, 0x26, 0xf8, 0x79, 0x00, 0x28,
-0x1b, 0xdd, 0x30, 0x01, 0xc0, 0x19, 0xc5, 0x1d, 0x05, 0x35, 0x00, 0x7b,
-0x00, 0x06, 0x00, 0x16, 0x00, 0xf0, 0x9e, 0xfb, 0x01, 0x1c, 0x8b, 0x68,
-0x00, 0x2b, 0x08, 0xd0, 0x68, 0x68, 0x00, 0x28, 0x05, 0xd0, 0xca, 0x68,
-0xa9, 0x68, 0xfa, 0xf7, 0x4e, 0xff, 0x00, 0x20, 0x68, 0x60, 0x70, 0x1c,
-0x06, 0x06, 0x36, 0x0e, 0xf8, 0x79, 0xb0, 0x42, 0xe3, 0xdc, 0xff, 0x20,
-0x38, 0x72, 0x20, 0x1c, 0xf0, 0xbc, 0x08, 0xbc,
-0x18, 0x47, 0xf3, 0xb5, 0x81, 0xb0, 0x0f, 0x1c, 0x68, 0x46, 0xff, 0xf7,
-0xbd, 0xff, 0x00, 0x28, 0x01, 0xd1, 0x0d, 0x20, 0x37, 0xe0, 0xb9, 0x88,
-0xc0, 0x46, 0x01, 0x80, 0xf9, 0x88, 0xc0, 0x46, 0x41, 0x80, 0xb9, 0x7a,
-0xc0, 0x46, 0x41, 0x71, 0xf9, 0x7a, 0xc0, 0x46, 0x81, 0x71, 0x8c, 0x21,
-0x01, 0x71, 0x3d, 0x7e, 0x00, 0x21, 0x00, 0x23, 0x00, 0x2d, 0x1f, 0xdd,
-0x1a, 0x01, 0xd2, 0x19, 0x1c, 0x32, 0x16, 0x78, 0x05, 0x2e, 0x0d, 0xdc,
-0x0c, 0x01, 0x24, 0x18, 0x26, 0x73, 0x96, 0x68, 0xc0, 0x46, 0x66, 0x61,
-0xd6, 0x68, 0xc0, 0x46, 0x26, 0x61, 0x00, 0x24, 0x01, 0x31, 0x09, 0x06,
-0x09, 0x0e, 0xd4, 0x60, 0x5a, 0x1c, 0x13, 0x06, 0x1b, 0x0e, 0xab, 0x42,
-0xe6, 0xdb, 0x00, 0x29, 0x04, 0xd0, 0xc1, 0x71, 0x00, 0x99, 0xc0, 0x46,
-0x01, 0x72, 0x00, 0xe0, 0x00, 0x20, 0x01, 0x99, 0xc0, 0x46, 0x08, 0x60,
-0x00, 0x20, 0x03, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xf0, 0xb5,
-0x07, 0x1c, 0x38, 0x7e, 0x00, 0x28, 0x28, 0xd0, 0x01, 0x38, 0x05, 0x06,
-0x2d, 0x0e, 0x00, 0x26, 0xff, 0x2d, 0x21, 0xd0, 0x28, 0x01, 0xc0, 0x19,
-0xc4, 0x1d, 0x15, 0x34, 0x00, 0x7f, 0x00, 0x06, 0x00, 0x16, 0x00, 0xf0,
-0x2b, 0xfb, 0x01, 0x1c, 0x11, 0xd0, 0x8a, 0x68, 0x00, 0x2a, 0x0c, 0xd0,
-0xe0, 0x68, 0x00, 0x28, 0x09, 0xd0, 0x00, 0x23, 0xcb, 0x56, 0x05, 0x2b,
-0x05, 0xdc, 0x13, 0x1c, 0xca, 0x68, 0xa1, 0x68, 0xfa, 0xf7, 0xd5, 0xfe,
-0xe6, 0x60, 0xff, 0x20, 0x20, 0x70, 0x68, 0x1e, 0x05, 0x06, 0x2d, 0x0e,
-0xff, 0x2d, 0xdd, 0xd1, 0x3e, 0x76, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47,
-0x13, 0x20, 0x70, 0x47, 0xf0, 0xb5, 0x82, 0xb0, 0x07, 0x1c, 0xf8, 0x1d,
-0xd5, 0x30, 0x39, 0x1c, 0xff, 0xf7, 0x7f, 0xff, 0x00, 0x90, 0x00, 0x98,
-0x00, 0x28, 0x3b, 0xd1, 0x38, 0x7e, 0xc0, 0x46, 0x01, 0x90, 0x00, 0x26,
-0x01, 0x98, 0x00, 0x28, 0x2d, 0xdd, 0x30, 0x01, 0xc0, 0x19, 0xc5, 0x1d,
-0x15, 0x35, 0x00, 0x7f, 0x00, 0x06, 0x00, 0x16, 0x00, 0xf0, 0xf0, 0xfa,
-0x04, 0x1c, 0x20, 0x69, 0x00, 0x28, 0x17, 0xd0, 0x28, 0x78, 0x05, 0x28,
-0x0d, 0xdd, 0xe9, 0x68, 0xaa, 0x68, 0x60, 0x68, 0x40, 0x08, 0x40, 0x00,
-0x01, 0xf0, 0x2c, 0xf8, 0x09, 0x22, 0xe8, 0x68, 0xa9, 0x68, 0xfa, 0xf7,
-0x8b, 0xfd, 0x00, 0x20, 0xe8, 0x60, 0x21, 0x69, 0x28, 0x1c, 0xfa, 0xf7,
-0x90, 0xfe, 0x00, 0x06, 0x00, 0x0e, 0x00, 0x90, 0x00, 0x98, 0x00, 0x28,
-0x0c, 0xd1, 0x70, 0x1c, 0x06, 0x06, 0x36, 0x0e, 0x01, 0x98, 0x86, 0x42,
-0xd1, 0xdb, 0x00, 0x20, 0x38, 0x76, 0x00, 0x98, 0x02, 0xb0, 0xf0, 0xbc,
-0x08, 0xbc, 0x18, 0x47, 0x38, 0x1c, 0xff, 0xf7, 0x82, 0xff, 0xf6, 0xe7,
-0xc1, 0x1d, 0x79, 0x31, 0x4a, 0x6b, 0xc0, 0x46, 0xca, 0x63, 0xc1, 0x1d,
-0xb9, 0x31, 0x0a, 0x60, 0x00, 0x22, 0x8a, 0x60, 0x04, 0x4a, 0xc0, 0x46,
-0x4a, 0x61, 0x8a, 0x61, 0x01, 0x21, 0xd0, 0x30, 0x41, 0x70, 0x08, 0x1c,
-0x70, 0x47, 0x00, 0x00, 0xb1, 0xc5, 0x21, 0x40, 0xf8, 0xb5, 0x07, 0x1c,
-0x00, 0x20, 0x00, 0x90, 0xfe, 0x1d, 0xc9, 0x36, 0x30, 0x78, 0x00, 0x01,
-0xc0, 0x19, 0xc4, 0x1d, 0x15, 0x34, 0x80, 0x6a, 0x45, 0x08, 0x6d, 0x00,
-0x04, 0x21, 0x38, 0x1c, 0xff, 0xf7, 0xb2, 0xfe, 0x31, 0x78, 0x40, 0x18,
-0x01, 0x06, 0x09, 0x0e, 0x00, 0x20, 0xa2, 0x68, 0x00, 0x2a, 0x0a, 0xd9,
-0x2a, 0x78, 0x4a, 0x40, 0x2a, 0x70, 0x01, 0x30, 0x09, 0x18, 0x09, 0x06,
-0x09, 0x0e, 0xa2, 0x68, 0x01, 0x35, 0x82, 0x42,
-0xf4, 0xd8, 0xe0, 0x68, 0xa1, 0x68, 0x40, 0x08, 0x40, 0x00, 0xff, 0xf7,
-0x99, 0xfe, 0x61, 0x78, 0x81, 0x42, 0x0a, 0xd0, 0x38, 0x1c, 0x00, 0xf0,
-0x0f, 0xf8, 0xf8, 0x1d, 0x79, 0x30, 0x80, 0x6b, 0xf9, 0x1d, 0xb9, 0x31,
-0xc8, 0x60, 0x0c, 0x20, 0x00, 0x90, 0x30, 0x78, 0x01, 0x30, 0x30, 0x70,
-0x00, 0x98, 0xf8, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xc2, 0x1d, 0xc9, 0x32,
-0x11, 0x78, 0x09, 0x01, 0x09, 0x18, 0x09, 0x6a, 0xc3, 0x1d, 0x79, 0x33,
-0xd9, 0x63, 0x13, 0x78, 0x1b, 0x01, 0x1b, 0x18, 0x5b, 0x6a, 0xcb, 0x18,
-0xc1, 0x1d, 0xb9, 0x31, 0x0b, 0x60, 0x13, 0x78, 0x1b, 0x01, 0x1b, 0x18,
-0x9b, 0x6a, 0xc0, 0x46, 0x8b, 0x60, 0x07, 0x4b, 0xc0, 0x46, 0x4b, 0x61,
-0x12, 0x78, 0x00, 0x7e, 0x01, 0x32, 0x82, 0x42, 0x01, 0xdb, 0x04, 0x48,
-0x00, 0xe0, 0x04, 0x48, 0xc0, 0x46, 0x88, 0x61, 0x00, 0x20, 0x70, 0x47,
-0x79, 0xc6, 0x21, 0x40, 0x4d, 0xc6, 0x21, 0x40, 0xf9, 0xc6, 0x21, 0x40,
-0xf8, 0xb5, 0x04, 0x1c, 0x00, 0x20, 0x00, 0x90, 0x25, 0x7e, 0x29, 0x01,
-0xe0, 0x1d, 0x15, 0x30, 0xff, 0xf7, 0x4e, 0xfe, 0xa1, 0x7e, 0x81, 0x42,
-0x0a, 0xd0, 0x20, 0x1c, 0x00, 0xf0, 0x61, 0xf8, 0xe0, 0x1d, 0x79, 0x30,
-0x80, 0x6b, 0xe1, 0x1d, 0xb9, 0x31, 0xc8, 0x60, 0x0b, 0x20, 0x55, 0xe0,
-0x00, 0x27, 0x00, 0x2d, 0x0f, 0xdd, 0x38, 0x01, 0x00, 0x19, 0x00, 0x7f,
-0x00, 0x06, 0x00, 0x16, 0x00, 0xf0, 0x1c, 0xfa, 0x00, 0x28, 0x01, 0xd1,
-0x09, 0x20, 0x47, 0xe0, 0x78, 0x1c, 0x07, 0x06, 0x3f, 0x0e, 0xaf, 0x42,
-0xef, 0xdb, 0x00, 0x26, 0x00, 0x2d, 0x38, 0xdd, 0x30, 0x01, 0x00, 0x19,
-0xc7, 0x1d, 0x15, 0x37, 0x00, 0x7f, 0x00, 0x06, 0x00, 0x16, 0x00, 0xf0,
-0x07, 0xfa, 0x00, 0x23, 0xc1, 0x56, 0x05, 0x29, 0x0c, 0xdc, 0x42, 0x68,
-0x00, 0x2a, 0x04, 0xd0, 0xc1, 0x68, 0xb8, 0x68, 0xfa, 0xf7, 0xb6, 0xfd,
-0xf8, 0x60, 0xf8, 0x68, 0x00, 0x28, 0x1b, 0xd1, 0x0e, 0x20, 0x17, 0xe0,
-0xc0, 0x68, 0x00, 0x28, 0x07, 0xd0, 0xfa, 0xf7, 0xa9, 0xfd, 0x00, 0x28,
-0x05, 0xda, 0x40, 0x42, 0xb9, 0x68, 0x81, 0x42, 0x04, 0xd0, 0x05, 0x20,
-0x0a, 0xe0, 0xb9, 0x68, 0x81, 0x42, 0xfa, 0xd8, 0x09, 0x21, 0xb8, 0x68,
-0xfa, 0xf7, 0x7e, 0xfc, 0xf8, 0x60, 0x00, 0x28, 0x02, 0xd1, 0x06, 0x20,
-0x00, 0x90, 0x07, 0xe0, 0x70, 0x1c, 0x06, 0x06, 0x36, 0x0e, 0xae, 0x42,
-0xc6, 0xdb, 0x00, 0x98, 0x00, 0x28, 0x02, 0xd0, 0x20, 0x1c, 0xff, 0xf7,
-0x92, 0xfe, 0x00, 0x98, 0xf8, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xc2, 0x1d,
-0x79, 0x32, 0x41, 0x69, 0xc0, 0x46, 0xd1, 0x63, 0x02, 0x7e, 0x12, 0x01,
-0x8a, 0x18, 0xc1, 0x1d, 0xb9, 0x31, 0x0a, 0x60, 0xc2, 0x1d, 0x15, 0x32,
-0x8a, 0x60, 0x05, 0x4a, 0xc0, 0x46, 0x4a, 0x61, 0x04, 0x4a, 0xc0, 0x46,
-0x8a, 0x61, 0x00, 0x21, 0xd0, 0x30, 0x01, 0x70, 0x08, 0x1c, 0x70, 0x47,
-0x51, 0xc7, 0x21, 0x40, 0xf9, 0xc6, 0x21, 0x40, 0x90, 0xb5, 0x07, 0x1c,
-0x38, 0x68, 0x1d, 0x4b, 0x98, 0x42, 0x03, 0xd0, 0x03, 0x20, 0x90, 0xbc,
-0x08, 0xbc, 0x18, 0x47, 0x1c, 0x21, 0x38, 0x1c, 0xff, 0xf7, 0xbc, 0xfd,
-0xfc, 0x1d, 0x79, 0x34, 0x00, 0x28, 0x09, 0xd0, 0x38, 0x1c, 0x00, 0xf0,
-0x2d, 0xf8, 0xf9, 0x1d, 0xb9, 0x31, 0xa0, 0x6b, 0xc0, 0x46, 0xc8, 0x60,
-0x0a, 0x20, 0xea, 0xe7, 0x38, 0x7a, 0x1c, 0x28, 0x04, 0xd0, 0x78, 0x7a,
-0x10, 0x28, 0x01, 0xd0, 0x04, 0x20, 0xe2, 0xe7, 0xb8, 0x7a, 0x01, 0x28,
-0x01, 0xd0, 0x07, 0x20, 0xdd, 0xe7, 0x60, 0x6b,
-0xf9, 0x68, 0x88, 0x42, 0x01, 0xd0, 0x05, 0x20, 0xd7, 0xe7, 0x38, 0x69,
-0x00, 0x28, 0x04, 0xd0, 0x06, 0x4b, 0x98, 0x42, 0x01, 0xd0, 0x08, 0x20,
-0xcf, 0xe7, 0x38, 0x7e, 0x08, 0x28, 0x01, 0xdd, 0x12, 0x20, 0xca, 0xe7,
-0x00, 0x20, 0xc8, 0xe7, 0x73, 0x6e, 0x69, 0x70, 0x02, 0x10, 0x00, 0x03,
-0xb8, 0xb5, 0x07, 0x1c, 0x38, 0x1c, 0xff, 0xf7, 0x2a, 0xfe, 0x00, 0x25,
-0xf8, 0x1d, 0xc9, 0x30, 0x45, 0x70, 0xfc, 0x1d, 0xb9, 0x34, 0xe5, 0x61,
-0x68, 0x46, 0xff, 0xf7, 0x9d, 0xfd, 0x00, 0x28, 0x01, 0xd1, 0x0d, 0x20,
-0x0d, 0xe0, 0xf8, 0x1d, 0x79, 0x30, 0x85, 0x63, 0xc5, 0x63, 0x1b, 0x20,
-0x20, 0x60, 0xa7, 0x60, 0x04, 0x48, 0xc0, 0x46, 0x60, 0x61, 0x04, 0x48,
-0xc0, 0x46, 0xa0, 0x61, 0x28, 0x1c, 0xb8, 0xbc, 0x08, 0xbc, 0x18, 0x47,
-0x6d, 0xc8, 0x21, 0x40, 0x33, 0xc8, 0x21, 0x40, 0xf0, 0xb5, 0x82, 0xb0,
-0x07, 0x1c, 0x00, 0x20, 0xfd, 0x1d, 0x79, 0x35, 0xfc, 0x1d, 0xb9, 0x34,
-0xe9, 0x6a, 0xc0, 0x46, 0x61, 0x60, 0x62, 0x68, 0xe9, 0x6b, 0x8a, 0x42,
-0x03, 0xd2, 0x61, 0x60, 0x2a, 0x6b, 0x91, 0x42, 0x34, 0xd2, 0x66, 0x68,
-0xc0, 0x46, 0x01, 0x96, 0xe9, 0x6b, 0x73, 0x1a, 0xe9, 0x6a, 0x71, 0x1a,
-0x26, 0x68, 0x2a, 0x6b, 0x96, 0x42, 0x00, 0xd2, 0x32, 0x1c, 0x01, 0x9e,
-0x96, 0x1b, 0xa2, 0x68, 0xc0, 0x46, 0x00, 0x92, 0x00, 0x2a, 0x09, 0xd0,
-0x28, 0x6a, 0x6a, 0x6a, 0x41, 0x18, 0x00, 0x98, 0xc0, 0x18, 0x33, 0x1c,
-0xfc, 0xf7, 0x68, 0xff, 0x00, 0x28, 0x1b, 0xd1, 0x61, 0x68, 0x89, 0x19,
-0x61, 0x60, 0x22, 0x68, 0x91, 0x42, 0x0d, 0xd1, 0x61, 0x69, 0x38, 0x1c,
-0xfa, 0xf7, 0xc5, 0xfc, 0x00, 0x06, 0x00, 0x0e, 0x0e, 0xd1, 0xa1, 0x69,
-0x38, 0x1c, 0xfa, 0xf7, 0xbe, 0xfc, 0x00, 0x06, 0x00, 0x0e, 0x07, 0xd1,
-0x61, 0x68, 0x2a, 0x6b, 0x91, 0x42, 0xc2, 0xd3, 0xa9, 0x6b, 0xaa, 0x6a,
-0x89, 0x18, 0xa9, 0x63, 0x02, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47,
-0xf0, 0xb5, 0x84, 0xb0, 0x07, 0x1c, 0x69, 0x46, 0x38, 0x1c, 0xfa, 0xf7,
-0xc3, 0xfe, 0xfa, 0x1d, 0x09, 0x32, 0x37, 0x49, 0x00, 0x20, 0xc0, 0x43,
-0xcc, 0x1d, 0xb9, 0x34, 0xe0, 0x60, 0xf8, 0x88, 0xcb, 0x1d, 0x89, 0x33,
-0x18, 0x73, 0xc8, 0x1d, 0x79, 0x30, 0xbd, 0x68, 0xc0, 0x46, 0x05, 0x62,
-0xff, 0x68, 0xc0, 0x46, 0x47, 0x62, 0x17, 0x68, 0xc0, 0x46, 0x87, 0x62,
-0x57, 0x68, 0xc0, 0x46, 0xc7, 0x62, 0x92, 0x68, 0xc0, 0x46, 0x42, 0x63,
-0xc2, 0x6a, 0x87, 0x6a, 0xd2, 0x19, 0x02, 0x63, 0x1a, 0x7b, 0x28, 0x4d,
-0x01, 0x2a, 0x0d, 0xd0, 0x02, 0x2a, 0x1c, 0xd0, 0x03, 0x2a, 0x35, 0xd1,
-0xca, 0x1d, 0xc9, 0x32, 0x52, 0x78, 0x00, 0x2a, 0x08, 0xd1, 0x10, 0x27,
-0x80, 0x6b, 0xc0, 0x46, 0xe0, 0x60, 0x2c, 0xe0, 0x08, 0x1c, 0xff, 0xf7,
-0x4b, 0xff, 0x22, 0xe0, 0x08, 0x1c, 0xff, 0xf7, 0xa9, 0xfd, 0x07, 0x1c,
-0x23, 0xd1, 0xe0, 0x69, 0x00, 0x28, 0x1c, 0xd0, 0x00, 0x7a, 0x1a, 0x4b,
-0xc0, 0x18, 0x02, 0x90, 0x17, 0xe0, 0x82, 0x6a, 0xc3, 0x6a, 0x9f, 0x18,
-0x46, 0x6b, 0xb7, 0x42, 0x05, 0xd8, 0x00, 0x2a, 0x03, 0xd0, 0x9f, 0x07,
-0x01, 0xd1, 0x92, 0x07, 0x01, 0xd0, 0x0f, 0x27, 0x0d, 0xe0, 0x80, 0x6b,
-0x98, 0x42, 0x01, 0xd0, 0xe0, 0x60, 0xf8, 0xe7, 0x08, 0x1c, 0xff, 0xf7,
-0x4f, 0xff, 0x07, 0x1c, 0x03, 0xd1, 0x00, 0xf0, 0x1f, 0xfe, 0x01, 0xe0,
-0x10, 0x27, 0x00, 0x20, 0x28, 0x65, 0x01, 0xab, 0x5f, 0x80, 0xe0, 0x68,
-0xc0, 0x46, 0x03, 0x90, 0x68, 0x46, 0x00, 0x21,
-0xfa, 0xf7, 0x98, 0xfd, 0x01, 0x20, 0x04, 0xb0, 0xf0, 0xbc, 0x08, 0xbc,
-0x18, 0x47, 0x00, 0x00, 0x3c, 0xac, 0x20, 0x40, 0x00, 0x00, 0x00, 0x80,
-0x0d, 0xf0, 0xfe, 0xca, 0x80, 0xb5, 0x85, 0xb0, 0x07, 0x1c, 0x38, 0x1c,
-0x01, 0xa9, 0xfa, 0xf7, 0x45, 0xfe, 0x68, 0x46, 0xb9, 0x68, 0xff, 0xf7,
-0x94, 0xfc, 0x00, 0x28, 0x02, 0xd1, 0x00, 0x98, 0xff, 0xf7, 0xb8, 0xfc,
-0x02, 0xab, 0x58, 0x80, 0x00, 0x21, 0x01, 0xa8, 0xfa, 0xf7, 0x76, 0xfd,
-0x01, 0x20, 0x05, 0xb0, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x80, 0xb5,
-0x85, 0xb0, 0x07, 0x1c, 0x38, 0x1c, 0x01, 0xa9, 0xfa, 0xf7, 0x2a, 0xfe,
-0x68, 0x46, 0xb9, 0x68, 0xff, 0xf7, 0x79, 0xfc, 0x00, 0x28, 0x00, 0xd1,
-0x02, 0x20, 0x02, 0xab, 0x58, 0x80, 0x00, 0x21, 0x01, 0xa8, 0xfa, 0xf7,
-0x5d, 0xfd, 0x01, 0x20, 0x05, 0xb0, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47,
-0x90, 0xb5, 0x85, 0xb0, 0x07, 0x1c, 0x38, 0x1c, 0x01, 0xa9, 0xfa, 0xf7,
-0x11, 0xfe, 0x3c, 0x69, 0x38, 0x1c, 0x01, 0xa9, 0xfa, 0xf7, 0x0c, 0xfe,
-0x68, 0x46, 0x21, 0x1c, 0xff, 0xf7, 0x5b, 0xfc, 0x8c, 0x24, 0x00, 0x28,
-0x0e, 0xd1, 0xb9, 0x68, 0x00, 0x29, 0x02, 0xd1, 0xfa, 0x68, 0x00, 0x2a,
-0x08, 0xd0, 0xf8, 0x88, 0x23, 0x1c, 0x8c, 0x28, 0x00, 0xd8, 0x03, 0x1c,
-0xf8, 0x68, 0x00, 0x9a, 0xfc, 0xf7, 0xd0, 0xfd, 0x02, 0xab, 0x58, 0x80,
-0x03, 0x94, 0x00, 0x21, 0x01, 0xa8, 0xfa, 0xf7, 0x2f, 0xfd, 0x01, 0x20,
-0x05, 0xb0, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x21, 0x04, 0x48,
-0xff, 0x22, 0x02, 0x72, 0x8c, 0x30, 0x01, 0x31, 0x04, 0x29, 0xfa, 0xd3,
-0x70, 0x47, 0x00, 0x00, 0xb0, 0x6e, 0x21, 0x40, 0x02, 0x48, 0x03, 0x49,
-0x40, 0x1a, 0x40, 0x42, 0x70, 0x47, 0x00, 0x00, 0xed, 0xd6, 0x21, 0x40,
-0xe9, 0xd6, 0x21, 0x40, 0x00, 0x21, 0x08, 0x4a, 0x8b, 0x00, 0x5b, 0x18,
-0x9b, 0x00, 0xd3, 0x56, 0x83, 0x42, 0x04, 0xd1, 0x88, 0x00, 0x40, 0x18,
-0x80, 0x00, 0x80, 0x18, 0x70, 0x47, 0x01, 0x31, 0x01, 0x29, 0xf1, 0xd3,
-0x00, 0x20, 0xf9, 0xe7, 0xe0, 0x70, 0x21, 0x40, 0x80, 0xb5, 0x00, 0xf0,
-0x0c, 0xf8, 0x00, 0x27, 0x38, 0x1c, 0x00, 0xf0, 0x45, 0xf8, 0x78, 0x1c,
-0x07, 0x04, 0x3f, 0x0c, 0x0c, 0x2f, 0xf7, 0xdd, 0x80, 0xbc, 0x08, 0xbc,
-0x18, 0x47, 0x1c, 0x48, 0x02, 0x68, 0x1c, 0x49, 0x8b, 0x69, 0xd2, 0x18,
-0x02, 0x60, 0x8a, 0x6a, 0x43, 0x68, 0x9b, 0x18, 0x43, 0x60, 0x93, 0x42,
-0x02, 0xd2, 0x82, 0x68, 0x01, 0x32, 0x82, 0x60, 0xc2, 0x68, 0x0b, 0x6a,
-0xd2, 0x18, 0xc2, 0x60, 0x42, 0x69, 0xcb, 0x68, 0xd2, 0x18, 0x42, 0x61,
-0xc2, 0x69, 0x8b, 0x68, 0xd2, 0x18, 0xc2, 0x61, 0x02, 0x69, 0x0b, 0x69,
-0xd2, 0x18, 0x02, 0x61, 0x82, 0x69, 0x0b, 0x68, 0xd2, 0x18, 0x82, 0x61,
-0x02, 0x6b, 0xcb, 0x69, 0xd2, 0x18, 0x02, 0x63, 0x4a, 0x6a, 0x43, 0x6b,
-0x9b, 0x18, 0x43, 0x63, 0x93, 0x42, 0x02, 0xd2, 0x82, 0x6b, 0x01, 0x32,
-0x82, 0x63, 0xc2, 0x6b, 0x4b, 0x69, 0xd2, 0x18, 0xc2, 0x63, 0x02, 0x6c,
-0xc9, 0x6a, 0x51, 0x18, 0x01, 0x64, 0x70, 0x47, 0xa4, 0x2a, 0x00, 0x80,
+0x00, 0x10, 0x83, 0xe5, 0x1e, 0xff, 0x2f, 0xe1, 0xf8, 0x00, 0x18, 0x40,
+0x04, 0x01, 0x18, 0x40, 0x00, 0x01, 0x18, 0x40, 0xfc, 0x00, 0x18, 0x40,
+0x80, 0xb5, 0x00, 0xf0, 0x0c, 0xf8, 0x00, 0x27, 0x38, 0x1c, 0x00, 0xf0,
+0x47, 0xf8, 0x78, 0x1c, 0x07, 0x04, 0x3f, 0x0c, 0x0c, 0x2f, 0xf7, 0xdd,
+0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x1d, 0x48,
+0x02, 0x68, 0x1d, 0x49, 0x8b, 0x69, 0xd2, 0x18, 0x02, 0x60, 0x02, 0x66,
+0x8a, 0x6a, 0x43, 0x68, 0x9b, 0x18, 0x43, 0x60, 0x93, 0x42, 0x02, 0xd2,
+0x82, 0x68, 0x01, 0x32, 0x82, 0x60, 0xc2, 0x68, 0x0b, 0x6a, 0xd2, 0x18,
+0xc2, 0x60, 0x42, 0x69, 0xcb, 0x68, 0xd2, 0x18, 0x42, 0x61, 0xc2, 0x69,
+0x8b, 0x68, 0xd2, 0x18, 0xc2, 0x61, 0x02, 0x69, 0x0b, 0x69, 0xd2, 0x18,
+0x02, 0x61, 0x82, 0x69, 0x0b, 0x68, 0xd2, 0x18, 0x82, 0x61, 0x02, 0x6b,
+0xcb, 0x69, 0xd2, 0x18, 0x02, 0x63, 0x4a, 0x6a, 0x43, 0x6b, 0x9b, 0x18,
+0x43, 0x63, 0x93, 0x42, 0x02, 0xd2, 0x82, 0x6b, 0x01, 0x32, 0x82, 0x63,
+0xc2, 0x6b, 0x4b, 0x69, 0xd2, 0x18, 0xc2, 0x63, 0x02, 0x6c, 0xc9, 0x6a,
+0x51, 0x18, 0x01, 0x64, 0x70, 0x47, 0x00, 0x00, 0xa4, 0x2a, 0x00, 0x80,
0x00, 0x08, 0x14, 0x40, 0x88, 0xb5, 0x69, 0x46, 0x00, 0xf0, 0x17, 0xf8,
0x81, 0x08, 0x0a, 0xd0, 0x00, 0x20, 0x00, 0x29, 0x07, 0xd9, 0x00, 0x22,
0x83, 0x00, 0x00, 0x9f, 0xc0, 0x46, 0xfa, 0x50, 0x01, 0x30, 0x88, 0x42,
0xf8, 0xd3, 0x88, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0x00, 0xf0,
-0x04, 0xf8, 0x00, 0x04, 0x00, 0x0c, 0x08, 0xbc,
-0x18, 0x47, 0x00, 0x22, 0x00, 0x28, 0x0a, 0xd0, 0x01, 0x28, 0x0a, 0xd0,
-0x02, 0x28, 0x0c, 0xd0, 0x03, 0x28, 0x02, 0xd1, 0x07, 0x48, 0x1c, 0x22,
-0x08, 0x60, 0x10, 0x1c, 0x70, 0x47, 0x06, 0x48, 0x04, 0xe0, 0x06, 0x48,
-0x50, 0x22, 0x08, 0x60, 0xf7, 0xe7, 0x05, 0x48, 0x68, 0x22, 0x08, 0x60,
-0xf3, 0xe7, 0x00, 0x00, 0x08, 0x83, 0x20, 0x40, 0xa4, 0x2a, 0x00, 0x80,
-0x0c, 0x2b, 0x00, 0x80, 0xa0, 0x82, 0x20, 0x40, 0x98, 0xb5, 0x00, 0x27,
-0x68, 0x46, 0xfe, 0xf7, 0x6f, 0xfb, 0x10, 0x4c, 0x00, 0x28, 0x0b, 0xd0,
-0x00, 0xf0, 0x44, 0xf8, 0x00, 0x28, 0x07, 0xd0, 0x01, 0x27, 0x10, 0x23,
-0x60, 0x68, 0x18, 0x43, 0x60, 0x60, 0xa0, 0x68, 0x18, 0x43, 0x0b, 0xe0,
-0x10, 0x23, 0xe0, 0x68, 0x98, 0x43, 0xe0, 0x60, 0x60, 0x69, 0x98, 0x43,
-0x60, 0x61, 0x60, 0x68, 0x98, 0x43, 0x60, 0x60, 0xa0, 0x68, 0x98, 0x43,
-0xa0, 0x60, 0x38, 0x1c, 0x98, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00,
-0x68, 0x19, 0x00, 0x80, 0x00, 0xb5, 0x00, 0xf0, 0xc7, 0xfc, 0x04, 0x49,
-0x09, 0x6d, 0x08, 0x43, 0xfe, 0xf7, 0x8a, 0xfb, 0x00, 0x20, 0x08, 0xbc,
-0x18, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xf0, 0xb5, 0x14, 0x24,
-0x00, 0x25, 0x00, 0x27, 0x08, 0x4e, 0x02, 0x20, 0x21, 0x1c, 0x32, 0x1c,
-0xfa, 0xf7, 0xde, 0xfa, 0x78, 0x40, 0x07, 0x04, 0x3f, 0x0c, 0x02, 0x34,
-0x01, 0x35, 0x03, 0x2d, 0xf3, 0xd3, 0x38, 0x1c, 0xf0, 0xbc, 0x08, 0xbc,
-0x18, 0x47, 0x00, 0x00, 0x79, 0xbf, 0x21, 0x40, 0x01, 0x20, 0x70, 0x47,
-0xb0, 0xb5, 0x01, 0x27, 0x3a, 0x1c, 0x18, 0x4b, 0xdb, 0x68, 0x01, 0x2b,
-0x00, 0xd0, 0x00, 0x22, 0x12, 0x06, 0x12, 0x0e, 0x00, 0x24, 0x00, 0x2a,
-0x23, 0xd0, 0x14, 0x4a, 0x53, 0x68, 0x1b, 0x04, 0x1b, 0x0c, 0x1d, 0x02,
-0x1b, 0x12, 0x2b, 0x43, 0x92, 0x68, 0x12, 0x04, 0x12, 0x0c, 0x15, 0x02,
-0x12, 0x12, 0x2a, 0x43, 0x12, 0x04, 0x12, 0x0c, 0x1b, 0x04, 0x1a, 0x43,
-0x51, 0x40, 0x01, 0x31, 0x0f, 0xd1, 0x00, 0x28, 0x02, 0xd0, 0xff, 0xf7,
-0xc1, 0xff, 0xc4, 0x43, 0x22, 0x04, 0x12, 0x0c, 0x07, 0x4b, 0x3a, 0x21,
-0x02, 0x20, 0xfa, 0xf7, 0xa2, 0xfa, 0x38, 0x1c, 0xb0, 0xbc, 0x08, 0xbc,
-0x18, 0x47, 0x20, 0x1c, 0xfa, 0xe7, 0x00, 0x00, 0x68, 0x0e, 0x00, 0x80,
-0x40, 0x00, 0x14, 0x40, 0xd9, 0xbf, 0x21, 0x40, 0x80, 0xb4, 0x03, 0x22,
-0xc2, 0x80, 0x15, 0x4a, 0xc0, 0x46, 0x82, 0x60, 0x14, 0x4a, 0x12, 0x88,
-0x01, 0x32, 0xc2, 0x60, 0x00, 0x20, 0x13, 0x4a, 0x13, 0x5c, 0xc0, 0x46,
-0x0b, 0x70, 0x01, 0x30, 0x01, 0x31, 0x08, 0x28, 0xf8, 0xd3, 0x20, 0x22,
-0x0a, 0x70, 0x01, 0x31, 0x00, 0x20, 0x0e, 0x4b, 0x1f, 0x5c, 0xc0, 0x46,
-0x0f, 0x70, 0x01, 0x30, 0x01, 0x31, 0x08, 0x28, 0xf8, 0xd3, 0x0a, 0x70,
-0x01, 0x31, 0x00, 0x20, 0x09, 0x4a, 0x13, 0x5c, 0xc0, 0x46, 0x0b, 0x70,
-0x01, 0x30, 0x01, 0x31, 0x08, 0x28, 0xf8, 0xd3, 0x00, 0x20, 0x08, 0x70,
-0x80, 0xbc, 0x70, 0x47, 0x02, 0x10, 0x00, 0x03, 0x68, 0x0e, 0x00, 0x80,
-0x7c, 0x04, 0x00, 0x80, 0x85, 0x04, 0x00, 0x80, 0x8e, 0x04, 0x00, 0x80,
-0x00, 0xb5, 0x01, 0x23, 0x0a, 0x48, 0xc1, 0x1d, 0x89, 0x31, 0x4b, 0x70,
-0x00, 0x22, 0x0a, 0x70, 0x64, 0x21, 0x80, 0x30, 0xc1, 0x82, 0x01, 0x83,
-0x43, 0x83, 0x7d, 0x21, 0xc9, 0x00, 0x81, 0x83, 0xc2, 0x83, 0x04, 0x48,
-0x01, 0x22, 0x00, 0x21, 0x00, 0xf0, 0x38, 0xfb, 0x08, 0xbc, 0x18, 0x47,
-0x68, 0x0e, 0x00, 0x80, 0xa1, 0x22, 0xff, 0xff,
-0x00, 0xb5, 0xff, 0xf7, 0xe1, 0xff, 0x13, 0x48, 0x02, 0x22, 0x00, 0x21,
-0x00, 0xf0, 0x2a, 0xfb, 0x01, 0x23, 0xd8, 0x42, 0x0a, 0xd1, 0x10, 0x48,
-0xc1, 0x1d, 0x39, 0x31, 0xca, 0x88, 0x01, 0x32, 0xca, 0x80, 0x81, 0x79,
-0x01, 0x31, 0x81, 0x71, 0xfc, 0xf7, 0x5c, 0xfd, 0x0b, 0x48, 0xc0, 0x68,
-0x01, 0x28, 0x05, 0xd1, 0x0a, 0x48, 0x7d, 0x22, 0xd2, 0x00, 0x00, 0x21,
-0x00, 0xf0, 0x12, 0xfb, 0x08, 0x48, 0xfa, 0xf7, 0x1b, 0xfa, 0x08, 0x48,
-0x28, 0x22, 0x00, 0x21, 0x00, 0xf0, 0x0a, 0xfb, 0x08, 0xbc, 0x18, 0x47,
-0x65, 0x21, 0xff, 0xff, 0xa0, 0x82, 0x20, 0x40, 0x68, 0x0e, 0x00, 0x80,
-0x95, 0x7e, 0x21, 0x40, 0x81, 0x2c, 0xff, 0xff, 0x59, 0x03, 0xff, 0xff,
-0x00, 0xb5, 0x10, 0x20, 0x0f, 0x49, 0xc0, 0x46, 0x08, 0x60, 0x0f, 0x4a,
-0x0f, 0x48, 0x64, 0x21, 0xfa, 0xf7, 0x00, 0xfa, 0x0e, 0x48, 0x01, 0x22,
-0x12, 0x04, 0x01, 0x68, 0x0a, 0x40, 0x08, 0x21, 0x00, 0x2a, 0x05, 0xd1,
-0x02, 0x68, 0x12, 0x0c, 0x07, 0xd1, 0x00, 0x68, 0x80, 0x0a, 0x04, 0xd3,
-0x08, 0x48, 0xc0, 0x46, 0xc1, 0x60, 0x08, 0xbc, 0x18, 0x47, 0x07, 0x48,
-0xc0, 0x46, 0x01, 0x64, 0xf9, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0,
-0x91, 0x55, 0xff, 0xff, 0x7c, 0x29, 0x00, 0x80, 0x00, 0x00, 0x10, 0x40,
-0x40, 0x01, 0x18, 0x00, 0x00, 0x00, 0x00, 0x80, 0xf8, 0xb5, 0x27, 0x48,
-0x01, 0x22, 0x12, 0x04, 0x01, 0x68, 0x0a, 0x40, 0x07, 0x21, 0x00, 0x2a,
-0x05, 0xd1, 0x02, 0x68, 0x12, 0x0c, 0x06, 0xd1, 0x00, 0x68, 0x80, 0x0a,
-0x03, 0xd3, 0x21, 0x48, 0xc0, 0x46, 0xc1, 0x60, 0x02, 0xe0, 0x20, 0x48,
-0xc0, 0x46, 0x01, 0x64, 0x1f, 0x48, 0xfa, 0xf7, 0xc1, 0xf9, 0x1f, 0x48,
-0xc1, 0x6b, 0xff, 0x29, 0xfc, 0xd1, 0x81, 0x6b, 0x42, 0x6b, 0x16, 0x1c,
-0x0f, 0x1c, 0x1c, 0x4c, 0x10, 0x23, 0x60, 0x69, 0x18, 0x43, 0x60, 0x61,
-0xa1, 0x69, 0x99, 0x43, 0x1d, 0x04, 0xa1, 0x61, 0xe8, 0x60, 0xa0, 0x69,
-0xc0, 0x46, 0x28, 0x61, 0x16, 0x4a, 0x17, 0x49, 0x64, 0x20, 0xfa, 0xf7,
-0xa9, 0xf9, 0x16, 0x4a, 0xc0, 0x46, 0x00, 0x92, 0x15, 0x4b, 0x00, 0x20,
-0x39, 0x1c, 0x32, 0x1c, 0xfa, 0xf7, 0xa8, 0xf9, 0x13, 0x48, 0xc1, 0x68,
-0x08, 0x29, 0xfc, 0xd1, 0x12, 0x48, 0xfa, 0xf7, 0x97, 0xf9, 0x10, 0x23,
-0x60, 0x69, 0x98, 0x43, 0x60, 0x61, 0xe8, 0x60, 0x01, 0x20, 0xe3, 0x23,
-0x1b, 0x01, 0xe1, 0x18, 0xc8, 0x71, 0xf8, 0xbc, 0x08, 0xbc, 0x18, 0x47,
-0x00, 0x00, 0x10, 0x40, 0x40, 0x01, 0x18, 0x00, 0x00, 0x00, 0x00, 0x80,
-0x04, 0x02, 0xff, 0xff, 0x00, 0x01, 0x18, 0x40, 0x68, 0x0e, 0x00, 0x80,
-0x0c, 0x55, 0xff, 0xff, 0x2d, 0xcf, 0x21, 0x40, 0x64, 0x00, 0x30, 0x02,
-0x44, 0x80, 0x20, 0x40, 0x40, 0x01, 0x18, 0x40, 0xf4, 0x01, 0xff, 0xff,
-0x00, 0xb5, 0xfd, 0xf7, 0xeb, 0xfa, 0x06, 0x48, 0xfa, 0xf7, 0x6c, 0xf9,
-0xfd, 0xf7, 0xc0, 0xfa, 0xfd, 0xf7, 0xee, 0xfb, 0xfd, 0xf7, 0x00, 0xfc,
-0xfd, 0xf7, 0x0e, 0xfc, 0x08, 0xbc, 0x18, 0x47, 0x91, 0x03, 0xff, 0xff,
-0x90, 0xb5, 0xfd, 0xf7, 0x55, 0xf8, 0x34, 0x4f, 0x00, 0x24, 0xf9, 0x68,
-0xf8, 0x1d, 0x79, 0x30, 0x01, 0x29, 0x0f, 0xd1, 0x31, 0x49, 0xc0, 0x46,
-0xf9, 0x67, 0x31, 0x49, 0xc0, 0x46, 0x01, 0x60, 0x30, 0x49, 0xc0, 0x46,
-0x0c, 0x60, 0x4c, 0x60, 0x8c, 0x60, 0xcc, 0x60, 0x0c, 0x61, 0x4c, 0x61,
-0x8c, 0x61, 0x04, 0xe0, 0xf9, 0x1d, 0x7d, 0x31, 0xf9, 0x67, 0x12, 0xc0,
-0x08, 0x38, 0x00, 0x68, 0x60, 0x23, 0x01, 0x68,
-0x19, 0x43, 0x01, 0x60, 0xf8, 0x6f, 0x20, 0x23, 0x01, 0x68, 0x19, 0x43,
-0x01, 0x60, 0xf8, 0x6f, 0x40, 0x23, 0x01, 0x68, 0x99, 0x43, 0x01, 0x60,
-0x00, 0xf0, 0x54, 0xf8, 0xfd, 0xf7, 0x38, 0xf8, 0x00, 0xf0, 0x08, 0xf9,
-0xfc, 0xf7, 0x5f, 0xfc, 0xff, 0xf7, 0x84, 0xfd, 0xfd, 0xf7, 0x18, 0xfa,
-0xfd, 0xf7, 0xa0, 0xf9, 0xfd, 0xf7, 0xac, 0xfa, 0xfd, 0xf7, 0x3e, 0xf9,
-0xfd, 0xf7, 0xf4, 0xf8, 0xfd, 0xf7, 0x7e, 0xf9, 0x00, 0xf0, 0xc4, 0xf9,
-0xfd, 0xf7, 0x86, 0xfb, 0xfd, 0xf7, 0xf4, 0xfa, 0xfd, 0xf7, 0xbc, 0xfa,
-0xfd, 0xf7, 0x26, 0xf8, 0xfa, 0xf7, 0x12, 0xf8, 0xff, 0xf7, 0x40, 0xfd,
-0x00, 0x20, 0xff, 0xf7, 0x17, 0xfe, 0xff, 0xf7, 0x97, 0xff, 0x71, 0x23,
-0x5b, 0x01, 0xf8, 0x18, 0x04, 0x72, 0x44, 0x72, 0x07, 0x23, 0x5b, 0x02,
-0xf8, 0x18, 0x04, 0x63, 0x09, 0x48, 0xc0, 0x46, 0x44, 0x62, 0x00, 0xf0,
-0xc3, 0xf9, 0x08, 0x48, 0xfa, 0xf7, 0xf8, 0xf8, 0x90, 0xbc, 0x08, 0xbc,
-0x18, 0x47, 0x00, 0x00, 0x68, 0x0e, 0x00, 0x80, 0x00, 0x01, 0x11, 0x40,
-0x04, 0x01, 0x11, 0x40, 0x00, 0x01, 0x11, 0x00, 0xc0, 0x00, 0x18, 0x00,
-0x65, 0x9f, 0x21, 0x40, 0x00, 0xb5, 0x04, 0x48, 0xfa, 0xf7, 0xe4, 0xf8,
-0xfd, 0xf7, 0x48, 0xfb, 0xfd, 0xf7, 0x0e, 0xf8, 0x08, 0xbc, 0x18, 0x47,
-0x61, 0xa9, 0x21, 0x40, 0xfa, 0x21, 0x03, 0x48, 0xc0, 0x46, 0x41, 0x62,
-0x40, 0x21, 0x41, 0x62, 0x70, 0x47, 0x00, 0x00, 0xc0, 0x00, 0x18, 0x00,
-0x07, 0x48, 0x41, 0x69, 0x07, 0x4b, 0x19, 0x43, 0x41, 0x61, 0x82, 0x69,
-0x9a, 0x43, 0x82, 0x61, 0x01, 0x22, 0x12, 0x05, 0xd1, 0x60, 0x80, 0x69,
-0xc0, 0x46, 0x10, 0x61, 0x70, 0x47, 0x00, 0x00, 0x68, 0x0e, 0x00, 0x80,
-0xfe, 0xaf, 0x9a, 0x10, 0x00, 0xb5, 0x02, 0x48, 0xfa, 0xf7, 0xba, 0xf8,
-0x08, 0xbc, 0x18, 0x47, 0xb4, 0x57, 0xff, 0xff, 0xf0, 0xb5, 0x24, 0x4c,
-0x01, 0x21, 0x09, 0x04, 0x20, 0x68, 0x01, 0x40, 0x09, 0x20, 0x22, 0x4e,
-0x22, 0x4d, 0x00, 0x29, 0x05, 0xd1, 0x21, 0x68, 0x09, 0x0c, 0x04, 0xd1,
-0x21, 0x68, 0x89, 0x0a, 0x01, 0xd3, 0xf0, 0x60, 0x00, 0xe0, 0x28, 0x64,
-0x1d, 0x48, 0xfa, 0xf7, 0x9f, 0xf8, 0x1d, 0x4f, 0x1d, 0x49, 0x88, 0x69,
-0x01, 0x30, 0x88, 0x61, 0x38, 0x7a, 0x00, 0x28, 0x02, 0xd1, 0x78, 0x7a,
-0x00, 0x28, 0x1f, 0xd0, 0x19, 0x48, 0xfa, 0xf7, 0x91, 0xf8, 0x19, 0x48,
-0xfa, 0xf7, 0x8e, 0xf8, 0x00, 0x28, 0xfa, 0xd1, 0x38, 0x7a, 0x00, 0x28,
-0x02, 0xd0, 0x16, 0x48, 0xfa, 0xf7, 0x86, 0xf8, 0x01, 0x21, 0x09, 0x04,
-0x20, 0x68, 0x01, 0x40, 0x14, 0x20, 0x00, 0x29, 0x05, 0xd1, 0x21, 0x68,
-0x09, 0x0c, 0x04, 0xd1, 0x21, 0x68, 0x89, 0x0a, 0x01, 0xd3, 0xf0, 0x60,
-0x01, 0xe0, 0x28, 0x64, 0xff, 0xe7, 0xfe, 0xe7, 0xff, 0xf7, 0xdd, 0xfc,
-0x0b, 0x48, 0xfa, 0xf7, 0x6f, 0xf8, 0xff, 0xf7, 0xaf, 0xff, 0xcd, 0xe7,
-0x00, 0x00, 0x10, 0x40, 0x40, 0x01, 0x18, 0x00, 0x00, 0x00, 0x00, 0x80,
-0x04, 0x02, 0xff, 0xff, 0x88, 0x1c, 0x00, 0x80, 0x08, 0x83, 0x20, 0x40,
-0xf4, 0x01, 0xff, 0xff, 0xb5, 0x07, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff,
-0xe9, 0xaf, 0x21, 0x40, 0x00, 0xb5, 0x16, 0x49, 0x01, 0x22, 0x12, 0x04,
+0x04, 0xf8, 0x00, 0x04, 0x00, 0x0c, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x22,
+0x00, 0x28, 0x0a, 0xd0, 0x01, 0x28, 0x0a, 0xd0, 0x02, 0x28, 0x0c, 0xd0,
+0x03, 0x28, 0x02, 0xd1, 0x07, 0x48, 0x1c, 0x22, 0x08, 0x60, 0x10, 0x1c,
+0x70, 0x47, 0x06, 0x48, 0x04, 0xe0, 0x06, 0x48, 0x50, 0x22, 0x08, 0x60,
+0xf7, 0xe7, 0x05, 0x48, 0x68, 0x22, 0x08, 0x60, 0xf3, 0xe7, 0x00, 0x00,
+0x08, 0x83, 0x20, 0x40, 0xa4, 0x2a, 0x00, 0x80, 0x0c, 0x2b, 0x00, 0x80,
+0xa0, 0x82, 0x20, 0x40, 0x80, 0xb4, 0x03, 0x22, 0xc2, 0x80, 0x15, 0x4a,
+0xc0, 0x46, 0x82, 0x60, 0x14, 0x4a, 0x12, 0x88, 0x01, 0x32, 0xc2, 0x60,
+0x00, 0x20, 0x13, 0x4a, 0x13, 0x5c, 0xc0, 0x46, 0x0b, 0x70, 0x01, 0x30,
+0x01, 0x31, 0x08, 0x28, 0xf8, 0xd3, 0x20, 0x22, 0x0a, 0x70, 0x01, 0x31,
+0x00, 0x20, 0x0e, 0x4b, 0x1f, 0x5c, 0xc0, 0x46, 0x0f, 0x70, 0x01, 0x30,
+0x01, 0x31, 0x08, 0x28, 0xf8, 0xd3, 0x0a, 0x70, 0x01, 0x31, 0x00, 0x20,
+0x09, 0x4a, 0x13, 0x5c, 0xc0, 0x46, 0x0b, 0x70, 0x01, 0x30, 0x01, 0x31,
+0x08, 0x28, 0xf8, 0xd3, 0x00, 0x20, 0x08, 0x70, 0x80, 0xbc, 0x70, 0x47,
+0x08, 0x10, 0x00, 0x03, 0x68, 0x0e, 0x00, 0x80, 0x7c, 0x04, 0x00, 0x80,
+0x85, 0x04, 0x00, 0x80, 0x8e, 0x04, 0x00, 0x80, 0x00, 0xb5, 0x01, 0x23,
+0x0a, 0x48, 0xc1, 0x1d, 0x89, 0x31, 0x4b, 0x70, 0x00, 0x22, 0x0a, 0x70,
+0x64, 0x21, 0x80, 0x30, 0xc1, 0x82, 0x01, 0x83, 0x43, 0x83, 0x7d, 0x21,
+0xc9, 0x00, 0x81, 0x83, 0xc2, 0x83, 0x04, 0x48, 0x01, 0x22, 0x00, 0x21,
+0x00, 0xf0, 0x8e, 0xfb, 0x08, 0xbc, 0x18, 0x47, 0x68, 0x0e, 0x00, 0x80,
+0xb5, 0x22, 0xff, 0xff, 0x00, 0xb5, 0xff, 0xf7, 0xe1, 0xff, 0x13, 0x48,
+0x02, 0x22, 0x00, 0x21, 0x00, 0xf0, 0x80, 0xfb, 0x01, 0x23, 0xd8, 0x42,
+0x0a, 0xd1, 0x10, 0x48, 0xc1, 0x1d, 0x39, 0x31, 0xca, 0x88, 0x01, 0x32,
+0xca, 0x80, 0x81, 0x79, 0x01, 0x31, 0x81, 0x71, 0xfd, 0xf7, 0x70, 0xf9,
+0x0b, 0x48, 0xc0, 0x68, 0x01, 0x28, 0x05, 0xd1, 0x0a, 0x48, 0x7d, 0x22,
+0xd2, 0x00, 0x00, 0x21, 0x00, 0xf0, 0x68, 0xfb, 0x08, 0x48, 0xfb, 0xf7,
+0xe1, 0xfc, 0x08, 0x48, 0x28, 0x22, 0x00, 0x21, 0x00, 0xf0, 0x60, 0xfb,
+0x08, 0xbc, 0x18, 0x47, 0x79, 0x21, 0xff, 0xff, 0xa0, 0x82, 0x20, 0x40,
+0x68, 0x0e, 0x00, 0x80, 0xa5, 0x7b, 0x21, 0x40,
+0x95, 0x2c, 0xff, 0xff, 0x59, 0x03, 0xff, 0xff, 0x00, 0xb5, 0x10, 0x20,
+0x0f, 0x49, 0xc0, 0x46, 0x08, 0x60, 0x0f, 0x4a, 0x0f, 0x48, 0x64, 0x21,
+0xfb, 0xf7, 0xc6, 0xfc, 0x0e, 0x48, 0x01, 0x22, 0x12, 0x04, 0x01, 0x68,
+0x0a, 0x40, 0x08, 0x21, 0x00, 0x2a, 0x05, 0xd1, 0x02, 0x68, 0x12, 0x0c,
+0x07, 0xd1, 0x00, 0x68, 0x80, 0x0a, 0x04, 0xd3, 0x08, 0x48, 0xc0, 0x46,
+0xc1, 0x60, 0x08, 0xbc, 0x18, 0x47, 0x07, 0x48, 0xc0, 0x46, 0x01, 0x64,
+0xf9, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0xa5, 0x55, 0xff, 0xff,
+0x7c, 0x29, 0x00, 0x80, 0x00, 0x00, 0x10, 0x40, 0x40, 0x01, 0x18, 0x00,
+0x00, 0x00, 0x00, 0x80, 0xf8, 0xb5, 0x27, 0x48, 0x01, 0x22, 0x12, 0x04,
+0x01, 0x68, 0x0a, 0x40, 0x07, 0x21, 0x00, 0x2a, 0x05, 0xd1, 0x02, 0x68,
+0x12, 0x0c, 0x06, 0xd1, 0x00, 0x68, 0x80, 0x0a, 0x03, 0xd3, 0x21, 0x48,
+0xc0, 0x46, 0xc1, 0x60, 0x02, 0xe0, 0x20, 0x48, 0xc0, 0x46, 0x01, 0x64,
+0x1f, 0x48, 0xfb, 0xf7, 0x87, 0xfc, 0x1f, 0x48, 0xc1, 0x6b, 0xff, 0x29,
+0xfc, 0xd1, 0x81, 0x6b, 0x42, 0x6b, 0x16, 0x1c, 0x0f, 0x1c, 0x1c, 0x4c,
+0x10, 0x23, 0x60, 0x69, 0x18, 0x43, 0x60, 0x61, 0xa1, 0x69, 0x99, 0x43,
+0x1d, 0x04, 0xa1, 0x61, 0xe8, 0x60, 0xa0, 0x69, 0xc0, 0x46, 0x28, 0x61,
+0x16, 0x4a, 0x17, 0x49, 0x64, 0x20, 0xfb, 0xf7, 0x6f, 0xfc, 0x16, 0x4a,
+0xc0, 0x46, 0x00, 0x92, 0x15, 0x4b, 0x00, 0x20, 0x39, 0x1c, 0x32, 0x1c,
+0xfb, 0xf7, 0x6e, 0xfc, 0x13, 0x48, 0xc1, 0x68, 0x08, 0x29, 0xfc, 0xd1,
+0x12, 0x48, 0xfb, 0xf7, 0x5d, 0xfc, 0x10, 0x23, 0x60, 0x69, 0x98, 0x43,
+0x60, 0x61, 0xe8, 0x60, 0x01, 0x20, 0xe3, 0x23, 0x1b, 0x01, 0xe1, 0x18,
+0xc8, 0x71, 0xf8, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x10, 0x40,
+0x40, 0x01, 0x18, 0x00, 0x00, 0x00, 0x00, 0x80, 0x04, 0x02, 0xff, 0xff,
+0x00, 0x01, 0x18, 0x40, 0x68, 0x0e, 0x00, 0x80, 0x20, 0x55, 0xff, 0xff,
+0xb5, 0xb6, 0x21, 0x40, 0x64, 0x00, 0x30, 0x02, 0x44, 0x80, 0x20, 0x40,
+0x40, 0x01, 0x18, 0x40, 0xf4, 0x01, 0xff, 0xff, 0x00, 0xb5, 0xfd, 0xf7,
+0x01, 0xff, 0x06, 0x48, 0xfb, 0xf7, 0x32, 0xfc, 0xfd, 0xf7, 0xd6, 0xfe,
+0xfe, 0xf7, 0x04, 0xf8, 0xfe, 0xf7, 0x16, 0xf8, 0xfe, 0xf7, 0x24, 0xf8,
+0x08, 0xbc, 0x18, 0x47, 0x91, 0x03, 0xff, 0xff, 0x90, 0xb5, 0xfd, 0xf7,
+0x6b, 0xfc, 0x34, 0x4f, 0x00, 0x24, 0xf9, 0x68, 0xf8, 0x1d, 0x79, 0x30,
+0x01, 0x29, 0x0f, 0xd1, 0x31, 0x49, 0xc0, 0x46, 0xf9, 0x67, 0x31, 0x49,
+0xc0, 0x46, 0x01, 0x60, 0x30, 0x49, 0xc0, 0x46, 0x0c, 0x60, 0x4c, 0x60,
+0x8c, 0x60, 0xcc, 0x60, 0x0c, 0x61, 0x4c, 0x61, 0x8c, 0x61, 0x04, 0xe0,
+0xf9, 0x1d, 0x7d, 0x31, 0xf9, 0x67, 0x12, 0xc0, 0x08, 0x38, 0x00, 0x68,
+0x60, 0x23, 0x01, 0x68, 0x19, 0x43, 0x01, 0x60, 0xf8, 0x6f, 0x20, 0x23,
+0x01, 0x68, 0x19, 0x43, 0x01, 0x60, 0xf8, 0x6f, 0x40, 0x23, 0x01, 0x68,
+0x99, 0x43, 0x01, 0x60, 0x00, 0xf0, 0x54, 0xf8, 0xfd, 0xf7, 0x4e, 0xfc,
+0x00, 0xf0, 0x5e, 0xf9, 0xfd, 0xf7, 0x73, 0xf8, 0xff, 0xf7, 0x0c, 0xfe,
+0xfd, 0xf7, 0x2e, 0xfe, 0xfd, 0xf7, 0xb6, 0xfd, 0xfd, 0xf7, 0xc2, 0xfe,
+0xfd, 0xf7, 0x54, 0xfd, 0xfd, 0xf7, 0x0a, 0xfd, 0xfd, 0xf7, 0x94, 0xfd,
+0x00, 0xf0, 0x1a, 0xfa, 0xfd, 0xf7, 0x9c, 0xff, 0xfd, 0xf7, 0x0a, 0xff,
+0xfd, 0xf7, 0xd2, 0xfe, 0xfd, 0xf7, 0x3c, 0xfc, 0xfb, 0xf7, 0xdc, 0xfa,
+0xff, 0xf7, 0x9c, 0xff, 0x71, 0x23, 0x5b, 0x01,
+0xf8, 0x18, 0x04, 0x72, 0x44, 0x72, 0x07, 0x23, 0x5b, 0x02, 0xf8, 0x18,
+0x04, 0x63, 0xf8, 0x68, 0x01, 0x28, 0x02, 0xd1, 0xa8, 0x20, 0xfe, 0xf7,
+0xb1, 0xfd, 0x09, 0x48, 0xc0, 0x46, 0x44, 0x62, 0x00, 0xf0, 0x18, 0xfa,
+0x07, 0x48, 0xfb, 0xf7, 0xbd, 0xfb, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47,
+0x68, 0x0e, 0x00, 0x80, 0x00, 0x01, 0x11, 0x40, 0x04, 0x01, 0x11, 0x40,
+0x00, 0x01, 0x11, 0x00, 0xc0, 0x00, 0x18, 0x00, 0x15, 0x8f, 0x21, 0x40,
+0x00, 0xb5, 0x04, 0x48, 0xfb, 0xf7, 0xaa, 0xfb, 0xfd, 0xf7, 0x5e, 0xff,
+0xfd, 0xf7, 0x24, 0xfc, 0x08, 0xbc, 0x18, 0x47, 0x15, 0x99, 0x21, 0x40,
+0xfa, 0x21, 0x03, 0x48, 0xc0, 0x46, 0x41, 0x62, 0x40, 0x21, 0x41, 0x62,
+0x70, 0x47, 0x00, 0x00, 0xc0, 0x00, 0x18, 0x00, 0x07, 0x48, 0x41, 0x69,
+0x07, 0x4b, 0x19, 0x43, 0x41, 0x61, 0x82, 0x69, 0x9a, 0x43, 0x82, 0x61,
+0x01, 0x22, 0x12, 0x05, 0xd1, 0x60, 0x80, 0x69, 0xc0, 0x46, 0x10, 0x61,
+0x70, 0x47, 0x00, 0x00, 0x68, 0x0e, 0x00, 0x80, 0xfe, 0xaf, 0x9a, 0x10,
+0x00, 0xb5, 0x02, 0x48, 0xfb, 0xf7, 0x80, 0xfb, 0x08, 0xbc, 0x18, 0x47,
+0xc8, 0x57, 0xff, 0xff, 0xf0, 0xb5, 0x24, 0x4c, 0x01, 0x21, 0x09, 0x04,
+0x20, 0x68, 0x01, 0x40, 0x09, 0x20, 0x22, 0x4e, 0x22, 0x4d, 0x00, 0x29,
+0x05, 0xd1, 0x21, 0x68, 0x09, 0x0c, 0x04, 0xd1, 0x21, 0x68, 0x89, 0x0a,
+0x01, 0xd3, 0xf0, 0x60, 0x00, 0xe0, 0x28, 0x64, 0x1d, 0x48, 0xfb, 0xf7,
+0x65, 0xfb, 0x1d, 0x4f, 0x1d, 0x49, 0x88, 0x69, 0x01, 0x30, 0x88, 0x61,
+0x38, 0x7a, 0x00, 0x28, 0x02, 0xd1, 0x78, 0x7a, 0x00, 0x28, 0x1f, 0xd0,
+0x19, 0x48, 0xfb, 0xf7, 0x57, 0xfb, 0x19, 0x48, 0xfb, 0xf7, 0x54, 0xfb,
+0x00, 0x28, 0xfa, 0xd1, 0x38, 0x7a, 0x00, 0x28, 0x02, 0xd0, 0x16, 0x48,
+0xfb, 0xf7, 0x4c, 0xfb, 0x01, 0x21, 0x09, 0x04, 0x20, 0x68, 0x01, 0x40,
+0x14, 0x20, 0x00, 0x29, 0x05, 0xd1, 0x21, 0x68, 0x09, 0x0c, 0x04, 0xd1,
+0x21, 0x68, 0x89, 0x0a, 0x01, 0xd3, 0xf0, 0x60, 0x01, 0xe0, 0x28, 0x64,
+0xff, 0xe7, 0xfe, 0xe7, 0xff, 0xf7, 0x65, 0xfd, 0x0b, 0x48, 0xfb, 0xf7,
+0x35, 0xfb, 0xff, 0xf7, 0xaf, 0xff, 0xcd, 0xe7, 0x00, 0x00, 0x10, 0x40,
+0x40, 0x01, 0x18, 0x00, 0x00, 0x00, 0x00, 0x80, 0x04, 0x02, 0xff, 0xff,
+0x88, 0x1c, 0x00, 0x80, 0x08, 0x83, 0x20, 0x40, 0xf4, 0x01, 0xff, 0xff,
+0xb5, 0x07, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x99, 0x9f, 0x21, 0x40,
+0x00, 0x20, 0x07, 0x4a, 0x01, 0x21, 0x09, 0x05, 0x50, 0x61, 0xc8, 0x60,
+0xd0, 0x61, 0xc8, 0x61, 0x03, 0x23, 0xdb, 0x04, 0x03, 0x4a, 0x01, 0x21,
+0xd1, 0x63, 0x58, 0x60, 0xfc, 0xe7, 0x00, 0x00, 0x68, 0x0e, 0x00, 0x80,
+0xc0, 0x00, 0x18, 0x00, 0x80, 0xb5, 0xc0, 0xb0, 0x01, 0x22, 0x00, 0x21,
+0x0a, 0x20, 0xfc, 0xf7, 0xd1, 0xff, 0x07, 0x1c, 0xff, 0x2f, 0x28, 0xd0,
+0x69, 0x46, 0xff, 0x22, 0x38, 0x1c, 0x01, 0x32, 0xfd, 0xf7, 0x54, 0xf9,
+0xff, 0x23, 0x01, 0x33, 0x98, 0x42, 0x1b, 0xd1, 0x0d, 0x98, 0x00, 0x09,
+0x18, 0xd3, 0x38, 0x1c, 0xfd, 0xf7, 0x8d, 0xf8, 0x0e, 0x49, 0x01, 0x22,
+0x12, 0x04, 0x08, 0x68, 0x02, 0x40, 0x0d, 0x48, 0x05, 0xd1, 0x0a, 0x68,
+0x12, 0x0c, 0x06, 0xd1, 0x09, 0x68, 0x89, 0x0a, 0x03, 0xd3, 0x0a, 0x49,
+0xc0, 0x46, 0xc8, 0x60, 0x02, 0xe0, 0x09, 0x49, 0xc0, 0x46, 0x08, 0x64,
+0xff, 0xf7, 0xbc, 0xff, 0x38, 0x1c, 0xfd, 0xf7, 0x74, 0xf8, 0x40, 0xb0,
+0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00,
+0x00, 0x00, 0x10, 0x40, 0x07, 0x80, 0x00, 0x00, 0x40, 0x01, 0x18, 0x00,
+0x00, 0x00, 0x00, 0x80, 0x00, 0xb5, 0x17, 0x49, 0x01, 0x22, 0x12, 0x04,
0x08, 0x68, 0x02, 0x40, 0x06, 0x20, 0x00, 0x2a, 0x05, 0xd1, 0x0a, 0x68,
-0x12, 0x0c, 0x06, 0xd1, 0x09, 0x68, 0x89, 0x0a, 0x03, 0xd3, 0x10, 0x49,
-0xc0, 0x46, 0xc8, 0x60, 0x02, 0xe0, 0x0f, 0x49, 0xc0, 0x46, 0x08, 0x64,
-0x03, 0x20, 0xfe, 0xf7, 0x55, 0xf9, 0xfa, 0xf7,
-0x9d, 0xfc, 0x01, 0x23, 0x18, 0x43, 0xfa, 0xf7, 0x77, 0xfd, 0xff, 0xf7,
-0xd7, 0xfe, 0xff, 0xf7, 0x5b, 0xfe, 0xff, 0xf7, 0x4b, 0xff, 0xff, 0xf7,
-0x5f, 0xff, 0xff, 0xf7, 0xf1, 0xfd, 0xff, 0xf7, 0x77, 0xff, 0x08, 0xbc,
+0x12, 0x0c, 0x06, 0xd1, 0x09, 0x68, 0x89, 0x0a, 0x03, 0xd3, 0x11, 0x49,
+0xc0, 0x46, 0xc8, 0x60, 0x02, 0xe0, 0x10, 0x49, 0xc0, 0x46, 0x08, 0x64,
+0x03, 0x20, 0xfe, 0xf7, 0xd3, 0xfc, 0xfb, 0xf7, 0x0d, 0xff, 0x01, 0x23,
+0x18, 0x43, 0xfb, 0xf7, 0xe7, 0xff, 0xff, 0xf7, 0x83, 0xfe, 0xff, 0xf7,
+0x9d, 0xff, 0xff, 0xf7, 0x05, 0xfe, 0xff, 0xf7, 0xf5, 0xfe, 0xff, 0xf7,
+0x09, 0xff, 0xff, 0xf7, 0x9b, 0xfd, 0xff, 0xf7, 0x21, 0xff, 0x08, 0xbc,
0x18, 0x47, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, 0x40, 0x01, 0x18, 0x00,
0x00, 0x00, 0x00, 0x80, 0xf0, 0xb4, 0x46, 0x4a, 0x01, 0x21, 0xc9, 0x03,
0x45, 0x4d, 0x19, 0x23, 0xdb, 0x01, 0xec, 0x18, 0xa1, 0x61, 0x28, 0x88,
@@ -4231,7 +3722,7 @@ const u8 typhoon_firmware_image[] = {
0x00, 0x2b, 0x07, 0xd9, 0x87, 0x00, 0x4b, 0x6a, 0xc0, 0x46, 0xda, 0x51,
0x0b, 0x69, 0x01, 0x30, 0x83, 0x42, 0xf7, 0xd8, 0x49, 0x6a, 0x80, 0x00,
0x08, 0x18, 0x04, 0x38, 0x28, 0x61, 0xf0, 0xbc, 0x70, 0x47, 0x00, 0x00,
-0xec, 0xd6, 0x21, 0x40, 0x68, 0x0e, 0x00, 0x80, 0x00, 0x00, 0x20, 0x40,
+0xb0, 0xbe, 0x21, 0x40, 0x68, 0x0e, 0x00, 0x80, 0x00, 0x00, 0x20, 0x40,
0x4c, 0x2a, 0x00, 0x80, 0x00, 0x00, 0x20, 0x40, 0x00, 0xad, 0xde, 0x00,
0x0a, 0x48, 0x01, 0x23, 0x1b, 0x06, 0x41, 0x69, 0x99, 0x43, 0x1a, 0x09,
0x41, 0x61, 0xd1, 0x60, 0x00, 0x21, 0xa1, 0x22, 0x52, 0x03, 0x91, 0x61,
@@ -4239,14 +3730,14 @@ const u8 typhoon_firmware_image[] = {
0x59, 0x05, 0x08, 0x60, 0x70, 0x47, 0x00, 0x00, 0x68, 0x0e, 0x00, 0x80,
0x80, 0xb4, 0x02, 0x1c, 0x0b, 0x48, 0x1b, 0x23, 0xdb, 0x01, 0xc3, 0x18,
0x9a, 0x61, 0x01, 0x23, 0x1b, 0x06, 0x42, 0x69, 0x1a, 0x43, 0x42, 0x61,
-0x87, 0x69, 0x9f, 0x43, 0x01, 0x23, 0x1b, 0x05, 0x87, 0x61, 0xda, 0x60,
-0x80, 0x69, 0xc0, 0x46, 0x18, 0x61, 0xa1, 0x20, 0x40, 0x03, 0x81, 0x61,
-0x80, 0xbc, 0x70, 0x47, 0x68, 0x0e, 0x00, 0x80, 0x80, 0xb5, 0xff, 0xf7,
-0xc9, 0xff, 0x00, 0x20, 0x00, 0xf0, 0x20, 0xf8, 0x00, 0x20, 0x09, 0x49,
-0x00, 0x22, 0x03, 0x01, 0x5f, 0x18, 0x33, 0x23, 0x9b, 0x01, 0xfb, 0x18,
-0x9a, 0x62, 0x01, 0x30, 0x0b, 0x28, 0xf6, 0xd3, 0x04, 0x48, 0x01, 0x22,
-0x00, 0x21, 0x00, 0xf0, 0x33, 0xf8, 0x80, 0xbc,
-0x08, 0xbc, 0x18, 0x47, 0x68, 0x0e, 0x00, 0x80, 0x09, 0x3e, 0xff, 0xff,
+0x87, 0x69, 0x9f, 0x43, 0x01, 0x23, 0x1b, 0x05,
+0x87, 0x61, 0xda, 0x60, 0x80, 0x69, 0xc0, 0x46, 0x18, 0x61, 0xa1, 0x20,
+0x40, 0x03, 0x81, 0x61, 0x80, 0xbc, 0x70, 0x47, 0x68, 0x0e, 0x00, 0x80,
+0x80, 0xb5, 0xff, 0xf7, 0xc9, 0xff, 0x00, 0x20, 0x00, 0xf0, 0x20, 0xf8,
+0x00, 0x20, 0x09, 0x49, 0x00, 0x22, 0x03, 0x01, 0x5f, 0x18, 0x33, 0x23,
+0x9b, 0x01, 0xfb, 0x18, 0x9a, 0x62, 0x01, 0x30, 0x0b, 0x28, 0xf6, 0xd3,
+0x04, 0x48, 0x01, 0x22, 0x00, 0x21, 0x00, 0xf0, 0x33, 0xf8, 0x80, 0xbc,
+0x08, 0xbc, 0x18, 0x47, 0x68, 0x0e, 0x00, 0x80, 0x1d, 0x3e, 0xff, 0xff,
0x00, 0xb5, 0x02, 0x48, 0x00, 0xf0, 0x04, 0xf8, 0x08, 0xbc, 0x18, 0x47,
0xa8, 0x61, 0x00, 0x00, 0x80, 0xb4, 0x01, 0x22, 0x12, 0x05, 0x0f, 0x4b,
0xa1, 0x21, 0x49, 0x03, 0x00, 0x28, 0x0e, 0xd0, 0xc8, 0x61, 0x18, 0x1c,
@@ -4280,17 +3771,8 @@ const u8 typhoon_firmware_image[] = {
0x90, 0xb4, 0x08, 0x4a, 0xd0, 0x69, 0x00, 0x21, 0x07, 0x4f, 0xd3, 0x69,
0x83, 0x42, 0x02, 0xd9, 0xfc, 0x1a, 0x20, 0x18, 0x00, 0xe0, 0xc0, 0x1a,
0x09, 0x18, 0x18, 0x1c, 0xb9, 0x42, 0xf4, 0xd9, 0x90, 0xbc, 0x70, 0x47,
-0x00, 0x20, 0x14, 0x40, 0xa8, 0x61, 0x00, 0x00, 0x43, 0x1a, 0x93, 0x42,
-0x30, 0xd3, 0x84, 0x46, 0x8b, 0x07, 0x07, 0xd0, 0x52, 0x1e, 0x29, 0xd3,
-0x0b, 0x78, 0x03, 0x70, 0x40, 0x1c, 0x49, 0x1c, 0x8b, 0x07, 0xf7, 0xd1,
-0x83, 0x07, 0x17, 0xd1, 0x10, 0x3a, 0x05, 0xd3, 0xb0, 0xb4, 0xb8, 0xc9,
-0xb8, 0xc0, 0x10, 0x3a, 0xfb, 0xd2, 0xb0, 0xbc, 0x0c, 0x32, 0x0f, 0xd3,
-0x08, 0xc9, 0x08, 0xc0, 0x12, 0x1f, 0xfb, 0xd2, 0x0a, 0xe0, 0x08, 0xc9,
-0x03, 0x70, 0x1b, 0x0a, 0x43, 0x70, 0x1b, 0x0a, 0x83, 0x70, 0x1b, 0x0a,
-0xc3, 0x70, 0x00, 0x1d, 0x12, 0x1f, 0xf4, 0xd2, 0xd2, 0x1c, 0x05, 0xd3,
-0x0b, 0x78, 0x03, 0x70, 0x49, 0x1c, 0x40, 0x1c,
-0x52, 0x1e, 0xf9, 0xd2, 0x60, 0x46, 0x70, 0x47, 0x03, 0x1c, 0x0b, 0x43,
-0x13, 0x43, 0x9b, 0x07, 0x04, 0xd1, 0x12, 0x1f, 0x8b, 0x58, 0x83, 0x50,
-0xfb, 0xd1, 0x70, 0x47, 0x52, 0x1e, 0x8b, 0x5c, 0x83, 0x54, 0xfb, 0xd1,
-0x70, 0x47, 0x00, 0x00, 0x00, 0x20, 0x70, 0x47,
+0x00, 0x20, 0x14, 0x40, 0xa8, 0x61, 0x00, 0x00, 0x90, 0xb5, 0x07, 0x1c,
+0x00, 0x24, 0x00, 0x2f, 0x04, 0xd3, 0xff, 0xf7, 0xe3, 0xff, 0x01, 0x34,
+0xbc, 0x42, 0xfa, 0xd9, 0x90, 0xbc, 0x08, 0xbc,
+0x18, 0x47, 0x00, 0x00,
};
diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c
index 5712cac903d41..b0d337f7f545c 100644
--- a/drivers/net/typhoon.c
+++ b/drivers/net/typhoon.c
@@ -50,6 +50,13 @@
*/
static int rx_copybreak = 200;
+/* Should we use MMIO or Port IO?
+ * 0: Port IO
+ * 1: MMIO
+ * 2: Try MMIO, fallback to Port IO
+ */
+static unsigned int use_mmio = 2;
+
/* end user-configurable values */
/* Maximum number of multicast addresses to filter (vs. rx-all-multicast).
@@ -93,8 +100,8 @@ static const int multicast_filter_limit = 32;
#define PKT_BUF_SZ 1536
#define DRV_MODULE_NAME "typhoon"
-#define DRV_MODULE_VERSION "1.5.4"
-#define DRV_MODULE_RELDATE "04/09/09"
+#define DRV_MODULE_VERSION "1.5.7"
+#define DRV_MODULE_RELDATE "05/01/07"
#define PFX DRV_MODULE_NAME ": "
#define ERR_PFX KERN_ERR PFX
@@ -131,9 +138,16 @@ static char version[] __devinitdata =
"typhoon.c: version " DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
MODULE_AUTHOR("David Dillow <dave@thedillows.org>");
+MODULE_VERSION(DRV_MODULE_VERSION);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("3Com Typhoon Family (3C990, 3CR990, and variants)");
-MODULE_PARM(rx_copybreak, "i");
+MODULE_PARM_DESC(rx_copybreak, "Packets smaller than this are copied and "
+ "the buffer given back to the NIC. Default "
+ "is 200.");
+MODULE_PARM_DESC(use_mmio, "Use MMIO (1) or PIO(0) to access the NIC. "
+ "Default is to try MMIO and fallback to PIO.");
+module_param(rx_copybreak, int, 0);
+module_param(use_mmio, int, 0);
#if defined(NETIF_F_TSO) && MAX_SKB_FRAGS > 32
#warning Typhoon only supports 32 entries in its SG list for TSO, disabling TSO
@@ -310,7 +324,7 @@ enum state_values {
* cannot pass a read, so this forces current writes to post.
*/
#define typhoon_post_pci_writes(x) \
- do { readl(x + TYPHOON_REG_HEARTBEAT); } while(0)
+ do { if(likely(use_mmio)) ioread32(x+TYPHOON_REG_HEARTBEAT); } while(0)
/* We'll wait up to six seconds for a reset, and half a second normally.
*/
@@ -391,17 +405,17 @@ typhoon_reset(void __iomem *ioaddr, int wait_type)
else
timeout = TYPHOON_RESET_TIMEOUT_SLEEP;
- writel(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_MASK);
- writel(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_STATUS);
+ iowrite32(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_MASK);
+ iowrite32(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_STATUS);
- writel(TYPHOON_RESET_ALL, ioaddr + TYPHOON_REG_SOFT_RESET);
+ iowrite32(TYPHOON_RESET_ALL, ioaddr + TYPHOON_REG_SOFT_RESET);
typhoon_post_pci_writes(ioaddr);
udelay(1);
- writel(TYPHOON_RESET_NONE, ioaddr + TYPHOON_REG_SOFT_RESET);
+ iowrite32(TYPHOON_RESET_NONE, ioaddr + TYPHOON_REG_SOFT_RESET);
if(wait_type != NoWait) {
for(i = 0; i < timeout; i++) {
- if(readl(ioaddr + TYPHOON_REG_STATUS) ==
+ if(ioread32(ioaddr + TYPHOON_REG_STATUS) ==
TYPHOON_STATUS_WAITING_FOR_HOST)
goto out;
@@ -416,8 +430,8 @@ typhoon_reset(void __iomem *ioaddr, int wait_type)
}
out:
- writel(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_MASK);
- writel(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_STATUS);
+ iowrite32(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_MASK);
+ iowrite32(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_STATUS);
/* The 3XP seems to need a little extra time to complete the load
* of the sleep image before we can reliably boot it. Failure to
@@ -442,7 +456,7 @@ typhoon_wait_status(void __iomem *ioaddr, u32 wait_value)
int i, err = 0;
for(i = 0; i < TYPHOON_WAIT_TIMEOUT; i++) {
- if(readl(ioaddr + TYPHOON_REG_STATUS) == wait_value)
+ if(ioread32(ioaddr + TYPHOON_REG_STATUS) == wait_value)
goto out;
udelay(TYPHOON_UDELAY);
}
@@ -478,7 +492,7 @@ typhoon_hello(struct typhoon *tp)
INIT_COMMAND_NO_RESPONSE(cmd, TYPHOON_CMD_HELLO_RESP);
smp_wmb();
- writel(ring->lastWrite, tp->ioaddr + TYPHOON_REG_CMD_READY);
+ iowrite32(ring->lastWrite, tp->ioaddr + TYPHOON_REG_CMD_READY);
spin_unlock(&tp->command_lock);
}
}
@@ -633,7 +647,7 @@ typhoon_issue_command(struct typhoon *tp, int num_cmd, struct cmd_desc *cmd,
/* "I feel a presence... another warrior is on the the mesa."
*/
wmb();
- writel(ring->lastWrite, tp->ioaddr + TYPHOON_REG_CMD_READY);
+ iowrite32(ring->lastWrite, tp->ioaddr + TYPHOON_REG_CMD_READY);
typhoon_post_pci_writes(tp->ioaddr);
if((cmd->flags & TYPHOON_CMD_RESPOND) == 0)
@@ -687,7 +701,7 @@ out:
* is the case.
*/
if(indexes->respCleared != indexes->respReady)
- writel(1, tp->ioaddr + TYPHOON_REG_SELF_INTERRUPT);
+ iowrite32(1, tp->ioaddr + TYPHOON_REG_SELF_INTERRUPT);
}
spin_unlock(&tp->command_lock);
@@ -889,7 +903,7 @@ typhoon_start_tx(struct sk_buff *skb, struct net_device *dev)
/* Kick the 3XP
*/
wmb();
- writel(txRing->lastWrite, tp->tx_ioaddr + txRing->writeRegister);
+ iowrite32(txRing->lastWrite, tp->tx_ioaddr + txRing->writeRegister);
dev->trans_start = jiffies;
@@ -1058,8 +1072,10 @@ typhoon_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
if(typhoon_issue_command(tp, 1, &xp_cmd, 3, xp_resp) < 0) {
strcpy(info->fw_version, "Unknown runtime");
} else {
- strncpy(info->fw_version, (char *) &xp_resp[1], 32);
- info->fw_version[31] = 0;
+ u32 sleep_ver = xp_resp[0].parm2;
+ snprintf(info->fw_version, 32, "%02x.%03x.%03x",
+ sleep_ver >> 24, (sleep_ver >> 12) & 0xfff,
+ sleep_ver & 0xfff);
}
}
@@ -1251,7 +1267,7 @@ typhoon_wait_interrupt(void __iomem *ioaddr)
int i, err = 0;
for(i = 0; i < TYPHOON_WAIT_TIMEOUT; i++) {
- if(readl(ioaddr + TYPHOON_REG_INTR_STATUS) &
+ if(ioread32(ioaddr + TYPHOON_REG_INTR_STATUS) &
TYPHOON_INTR_BOOTCMD)
goto out;
udelay(TYPHOON_UDELAY);
@@ -1260,7 +1276,7 @@ typhoon_wait_interrupt(void __iomem *ioaddr)
err = -ETIMEDOUT;
out:
- writel(TYPHOON_INTR_BOOTCMD, ioaddr + TYPHOON_REG_INTR_STATUS);
+ iowrite32(TYPHOON_INTR_BOOTCMD, ioaddr + TYPHOON_REG_INTR_STATUS);
return err;
}
@@ -1394,11 +1410,11 @@ typhoon_download_firmware(struct typhoon *tp)
goto err_out;
}
- irqEnabled = readl(ioaddr + TYPHOON_REG_INTR_ENABLE);
- writel(irqEnabled | TYPHOON_INTR_BOOTCMD,
+ irqEnabled = ioread32(ioaddr + TYPHOON_REG_INTR_ENABLE);
+ iowrite32(irqEnabled | TYPHOON_INTR_BOOTCMD,
ioaddr + TYPHOON_REG_INTR_ENABLE);
- irqMasked = readl(ioaddr + TYPHOON_REG_INTR_MASK);
- writel(irqMasked | TYPHOON_INTR_BOOTCMD,
+ irqMasked = ioread32(ioaddr + TYPHOON_REG_INTR_MASK);
+ iowrite32(irqMasked | TYPHOON_INTR_BOOTCMD,
ioaddr + TYPHOON_REG_INTR_MASK);
err = -ETIMEDOUT;
@@ -1410,24 +1426,24 @@ typhoon_download_firmware(struct typhoon *tp)
numSections = le32_to_cpu(fHdr->numSections);
load_addr = le32_to_cpu(fHdr->startAddr);
- writel(TYPHOON_INTR_BOOTCMD, ioaddr + TYPHOON_REG_INTR_STATUS);
- writel(load_addr, ioaddr + TYPHOON_REG_DOWNLOAD_BOOT_ADDR);
+ iowrite32(TYPHOON_INTR_BOOTCMD, ioaddr + TYPHOON_REG_INTR_STATUS);
+ iowrite32(load_addr, ioaddr + TYPHOON_REG_DOWNLOAD_BOOT_ADDR);
hmac = le32_to_cpu(fHdr->hmacDigest[0]);
- writel(hmac, ioaddr + TYPHOON_REG_DOWNLOAD_HMAC_0);
+ iowrite32(hmac, ioaddr + TYPHOON_REG_DOWNLOAD_HMAC_0);
hmac = le32_to_cpu(fHdr->hmacDigest[1]);
- writel(hmac, ioaddr + TYPHOON_REG_DOWNLOAD_HMAC_1);
+ iowrite32(hmac, ioaddr + TYPHOON_REG_DOWNLOAD_HMAC_1);
hmac = le32_to_cpu(fHdr->hmacDigest[2]);
- writel(hmac, ioaddr + TYPHOON_REG_DOWNLOAD_HMAC_2);
+ iowrite32(hmac, ioaddr + TYPHOON_REG_DOWNLOAD_HMAC_2);
hmac = le32_to_cpu(fHdr->hmacDigest[3]);
- writel(hmac, ioaddr + TYPHOON_REG_DOWNLOAD_HMAC_3);
+ iowrite32(hmac, ioaddr + TYPHOON_REG_DOWNLOAD_HMAC_3);
hmac = le32_to_cpu(fHdr->hmacDigest[4]);
- writel(hmac, ioaddr + TYPHOON_REG_DOWNLOAD_HMAC_4);
+ iowrite32(hmac, ioaddr + TYPHOON_REG_DOWNLOAD_HMAC_4);
typhoon_post_pci_writes(ioaddr);
- writel(TYPHOON_BOOTCMD_RUNTIME_IMAGE, ioaddr + TYPHOON_REG_COMMAND);
+ iowrite32(TYPHOON_BOOTCMD_RUNTIME_IMAGE, ioaddr + TYPHOON_REG_COMMAND);
image_data += sizeof(struct typhoon_file_header);
- /* The readl() in typhoon_wait_interrupt() will force the
+ /* The ioread32() in typhoon_wait_interrupt() will force the
* last write to the command register to post, so
* we don't need a typhoon_post_pci_writes() after it.
*/
@@ -1441,7 +1457,7 @@ typhoon_download_firmware(struct typhoon *tp)
len = min_t(u32, section_len, PAGE_SIZE);
if(typhoon_wait_interrupt(ioaddr) < 0 ||
- readl(ioaddr + TYPHOON_REG_STATUS) !=
+ ioread32(ioaddr + TYPHOON_REG_STATUS) !=
TYPHOON_STATUS_WAITING_FOR_SEGMENT) {
printk(KERN_ERR "%s: segment ready timeout\n",
tp->name);
@@ -1458,13 +1474,14 @@ typhoon_download_firmware(struct typhoon *tp)
csum = csum_fold(csum);
csum = le16_to_cpu(csum);
- writel(len, ioaddr + TYPHOON_REG_BOOT_LENGTH);
- writel(csum, ioaddr + TYPHOON_REG_BOOT_CHECKSUM);
- writel(load_addr, ioaddr + TYPHOON_REG_BOOT_DEST_ADDR);
- writel(0, ioaddr + TYPHOON_REG_BOOT_DATA_HI);
- writel(dpage_dma, ioaddr + TYPHOON_REG_BOOT_DATA_LO);
+ iowrite32(len, ioaddr + TYPHOON_REG_BOOT_LENGTH);
+ iowrite32(csum, ioaddr + TYPHOON_REG_BOOT_CHECKSUM);
+ iowrite32(load_addr,
+ ioaddr + TYPHOON_REG_BOOT_DEST_ADDR);
+ iowrite32(0, ioaddr + TYPHOON_REG_BOOT_DATA_HI);
+ iowrite32(dpage_dma, ioaddr + TYPHOON_REG_BOOT_DATA_LO);
typhoon_post_pci_writes(ioaddr);
- writel(TYPHOON_BOOTCMD_SEG_AVAILABLE,
+ iowrite32(TYPHOON_BOOTCMD_SEG_AVAILABLE,
ioaddr + TYPHOON_REG_COMMAND);
image_data += len;
@@ -1474,25 +1491,25 @@ typhoon_download_firmware(struct typhoon *tp)
}
if(typhoon_wait_interrupt(ioaddr) < 0 ||
- readl(ioaddr + TYPHOON_REG_STATUS) !=
+ ioread32(ioaddr + TYPHOON_REG_STATUS) !=
TYPHOON_STATUS_WAITING_FOR_SEGMENT) {
printk(KERN_ERR "%s: final segment ready timeout\n", tp->name);
goto err_out_irq;
}
- writel(TYPHOON_BOOTCMD_DNLD_COMPLETE, ioaddr + TYPHOON_REG_COMMAND);
+ iowrite32(TYPHOON_BOOTCMD_DNLD_COMPLETE, ioaddr + TYPHOON_REG_COMMAND);
if(typhoon_wait_status(ioaddr, TYPHOON_STATUS_WAITING_FOR_BOOT) < 0) {
printk(KERN_ERR "%s: boot ready timeout, status 0x%0x\n",
- tp->name, readl(ioaddr + TYPHOON_REG_STATUS));
+ tp->name, ioread32(ioaddr + TYPHOON_REG_STATUS));
goto err_out_irq;
}
err = 0;
err_out_irq:
- writel(irqMasked, ioaddr + TYPHOON_REG_INTR_MASK);
- writel(irqEnabled, ioaddr + TYPHOON_REG_INTR_ENABLE);
+ iowrite32(irqMasked, ioaddr + TYPHOON_REG_INTR_MASK);
+ iowrite32(irqEnabled, ioaddr + TYPHOON_REG_INTR_ENABLE);
pci_free_consistent(pdev, PAGE_SIZE, dpage, dpage_dma);
@@ -1510,24 +1527,25 @@ typhoon_boot_3XP(struct typhoon *tp, u32 initial_status)
goto out_timeout;
}
- writel(0, ioaddr + TYPHOON_REG_BOOT_RECORD_ADDR_HI);
- writel(tp->shared_dma, ioaddr + TYPHOON_REG_BOOT_RECORD_ADDR_LO);
+ iowrite32(0, ioaddr + TYPHOON_REG_BOOT_RECORD_ADDR_HI);
+ iowrite32(tp->shared_dma, ioaddr + TYPHOON_REG_BOOT_RECORD_ADDR_LO);
typhoon_post_pci_writes(ioaddr);
- writel(TYPHOON_BOOTCMD_REG_BOOT_RECORD, ioaddr + TYPHOON_REG_COMMAND);
+ iowrite32(TYPHOON_BOOTCMD_REG_BOOT_RECORD,
+ ioaddr + TYPHOON_REG_COMMAND);
if(typhoon_wait_status(ioaddr, TYPHOON_STATUS_RUNNING) < 0) {
printk(KERN_ERR "%s: boot finish timeout (status 0x%x)\n",
- tp->name, readl(ioaddr + TYPHOON_REG_STATUS));
+ tp->name, ioread32(ioaddr + TYPHOON_REG_STATUS));
goto out_timeout;
}
/* Clear the Transmit and Command ready registers
*/
- writel(0, ioaddr + TYPHOON_REG_TX_HI_READY);
- writel(0, ioaddr + TYPHOON_REG_CMD_READY);
- writel(0, ioaddr + TYPHOON_REG_TX_LO_READY);
+ iowrite32(0, ioaddr + TYPHOON_REG_TX_HI_READY);
+ iowrite32(0, ioaddr + TYPHOON_REG_CMD_READY);
+ iowrite32(0, ioaddr + TYPHOON_REG_TX_LO_READY);
typhoon_post_pci_writes(ioaddr);
- writel(TYPHOON_BOOTCMD_BOOT, ioaddr + TYPHOON_REG_COMMAND);
+ iowrite32(TYPHOON_BOOTCMD_BOOT, ioaddr + TYPHOON_REG_COMMAND);
return 0;
@@ -1806,7 +1824,8 @@ typhoon_poll(struct net_device *dev, int *total_budget)
if(done) {
netif_rx_complete(dev);
- writel(TYPHOON_INTR_NONE, tp->ioaddr + TYPHOON_REG_INTR_MASK);
+ iowrite32(TYPHOON_INTR_NONE,
+ tp->ioaddr + TYPHOON_REG_INTR_MASK);
typhoon_post_pci_writes(tp->ioaddr);
}
@@ -1821,14 +1840,14 @@ typhoon_interrupt(int irq, void *dev_instance, struct pt_regs *rgs)
void __iomem *ioaddr = tp->ioaddr;
u32 intr_status;
- intr_status = readl(ioaddr + TYPHOON_REG_INTR_STATUS);
+ intr_status = ioread32(ioaddr + TYPHOON_REG_INTR_STATUS);
if(!(intr_status & TYPHOON_INTR_HOST_INT))
return IRQ_NONE;
- writel(intr_status, ioaddr + TYPHOON_REG_INTR_STATUS);
+ iowrite32(intr_status, ioaddr + TYPHOON_REG_INTR_STATUS);
if(netif_rx_schedule_prep(dev)) {
- writel(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_MASK);
+ iowrite32(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_MASK);
typhoon_post_pci_writes(ioaddr);
__netif_rx_schedule(dev);
} else {
@@ -1855,7 +1874,7 @@ typhoon_free_rx_rings(struct typhoon *tp)
}
static int
-typhoon_sleep(struct typhoon *tp, int state, u16 events)
+typhoon_sleep(struct typhoon *tp, pci_power_t state, u16 events)
{
struct pci_dev *pdev = tp->pdev;
void __iomem *ioaddr = tp->ioaddr;
@@ -1905,7 +1924,7 @@ typhoon_wakeup(struct typhoon *tp, int wait_type)
* we can download the Runtime Image. But let's not make users of
* the old firmware pay for the reset.
*/
- writel(TYPHOON_BOOTCMD_WAKEUP, ioaddr + TYPHOON_REG_COMMAND);
+ iowrite32(TYPHOON_BOOTCMD_WAKEUP, ioaddr + TYPHOON_REG_COMMAND);
if(typhoon_wait_status(ioaddr, TYPHOON_STATUS_WAITING_FOR_HOST) < 0 ||
(tp->capabilities & TYPHOON_WAKEUP_NEEDS_RESET))
return typhoon_reset(ioaddr, wait_type);
@@ -1994,8 +2013,8 @@ typhoon_start_runtime(struct typhoon *tp)
tp->card_state = Running;
smp_wmb();
- writel(TYPHOON_INTR_ENABLE_ALL, ioaddr + TYPHOON_REG_INTR_ENABLE);
- writel(TYPHOON_INTR_NONE, ioaddr + TYPHOON_REG_INTR_MASK);
+ iowrite32(TYPHOON_INTR_ENABLE_ALL, ioaddr + TYPHOON_REG_INTR_ENABLE);
+ iowrite32(TYPHOON_INTR_NONE, ioaddr + TYPHOON_REG_INTR_MASK);
typhoon_post_pci_writes(ioaddr);
return 0;
@@ -2020,7 +2039,7 @@ typhoon_stop_runtime(struct typhoon *tp, int wait_type)
* when called with !netif_running(). This will be posted
* when we force the posting of the command.
*/
- writel(TYPHOON_INTR_NONE, ioaddr + TYPHOON_REG_INTR_ENABLE);
+ iowrite32(TYPHOON_INTR_NONE, ioaddr + TYPHOON_REG_INTR_ENABLE);
INIT_COMMAND_NO_RESPONSE(&xp_cmd, TYPHOON_CMD_RX_DISABLE);
typhoon_issue_command(tp, 1, &xp_cmd, 0, NULL);
@@ -2136,7 +2155,7 @@ out_sleep:
goto out;
}
- if(typhoon_sleep(tp, 3, 0) < 0)
+ if(typhoon_sleep(tp, PCI_D3hot, 0) < 0)
printk(KERN_ERR "%s: unable to go back to sleep\n", dev->name);
out:
@@ -2163,7 +2182,7 @@ typhoon_close(struct net_device *dev)
if(typhoon_boot_3XP(tp, TYPHOON_STATUS_WAITING_FOR_HOST) < 0)
printk(KERN_ERR "%s: unable to boot sleep image\n", dev->name);
- if(typhoon_sleep(tp, 3, 0) < 0)
+ if(typhoon_sleep(tp, PCI_D3hot, 0) < 0)
printk(KERN_ERR "%s: unable to put card to sleep\n", dev->name);
return 0;
@@ -2203,7 +2222,7 @@ reset:
}
static int
-typhoon_suspend(struct pci_dev *pdev, u32 state)
+typhoon_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct net_device *dev = pci_get_drvdata(pdev);
struct typhoon *tp = netdev_priv(dev);
@@ -2275,14 +2294,59 @@ typhoon_enable_wake(struct pci_dev *pdev, u32 state, int enable)
#endif
static int __devinit
+typhoon_test_mmio(struct pci_dev *pdev)
+{
+ void __iomem *ioaddr = pci_iomap(pdev, 1, 128);
+ int mode = 0;
+ u32 val;
+
+ if(!ioaddr)
+ goto out;
+
+ if(ioread32(ioaddr + TYPHOON_REG_STATUS) !=
+ TYPHOON_STATUS_WAITING_FOR_HOST)
+ goto out_unmap;
+
+ iowrite32(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_MASK);
+ iowrite32(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_STATUS);
+ iowrite32(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_ENABLE);
+
+ /* Ok, see if we can change our interrupt status register by
+ * sending ourselves an interrupt. If so, then MMIO works.
+ * The 50usec delay is arbitrary -- it could probably be smaller.
+ */
+ val = ioread32(ioaddr + TYPHOON_REG_INTR_STATUS);
+ if((val & TYPHOON_INTR_SELF) == 0) {
+ iowrite32(1, ioaddr + TYPHOON_REG_SELF_INTERRUPT);
+ ioread32(ioaddr + TYPHOON_REG_INTR_STATUS);
+ udelay(50);
+ val = ioread32(ioaddr + TYPHOON_REG_INTR_STATUS);
+ if(val & TYPHOON_INTR_SELF)
+ mode = 1;
+ }
+
+ iowrite32(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_MASK);
+ iowrite32(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_STATUS);
+ iowrite32(TYPHOON_INTR_NONE, ioaddr + TYPHOON_REG_INTR_ENABLE);
+ ioread32(ioaddr + TYPHOON_REG_INTR_STATUS);
+
+out_unmap:
+ pci_iounmap(pdev, ioaddr);
+
+out:
+ if(!mode)
+ printk(KERN_INFO PFX "falling back to port IO\n");
+ return mode;
+}
+
+static int __devinit
typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
static int did_version = 0;
struct net_device *dev;
struct typhoon *tp;
int card_id = (int) ent->driver_data;
- unsigned long ioaddr;
- void __iomem *ioaddr_mapped;
+ void __iomem *ioaddr;
void *shared;
dma_addr_t shared_dma;
struct cmd_desc xp_cmd;
@@ -2323,8 +2387,21 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
goto error_out_mwi;
}
- /* sanity checks, resource #1 is our mmio area
+ /* sanity checks on IO and MMIO BARs
*/
+ if(!(pci_resource_flags(pdev, 0) & IORESOURCE_IO)) {
+ printk(ERR_PFX
+ "%s: region #1 not a PCI IO resource, aborting\n",
+ pci_name(pdev));
+ err = -ENODEV;
+ goto error_out_mwi;
+ }
+ if(pci_resource_len(pdev, 0) < 128) {
+ printk(ERR_PFX "%s: Invalid PCI IO region size, aborting\n",
+ pci_name(pdev));
+ err = -ENODEV;
+ goto error_out_mwi;
+ }
if(!(pci_resource_flags(pdev, 1) & IORESOURCE_MEM)) {
printk(ERR_PFX
"%s: region #1 not a PCI MMIO resource, aborting\n",
@@ -2346,12 +2423,14 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
goto error_out_mwi;
}
- /* map our MMIO region
+ /* map our registers
*/
- ioaddr = pci_resource_start(pdev, 1);
- ioaddr_mapped = ioremap(ioaddr, 128);
- if (!ioaddr_mapped) {
- printk(ERR_PFX "%s: cannot remap MMIO, aborting\n",
+ if(use_mmio != 0 && use_mmio != 1)
+ use_mmio = typhoon_test_mmio(pdev);
+
+ ioaddr = pci_iomap(pdev, use_mmio, 128);
+ if (!ioaddr) {
+ printk(ERR_PFX "%s: cannot remap registers, aborting\n",
pci_name(pdev));
err = -EIO;
goto error_out_regions;
@@ -2374,13 +2453,10 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
tp->shared_dma = shared_dma;
tp->pdev = pdev;
tp->tx_pdev = pdev;
- tp->ioaddr = ioaddr_mapped;
- tp->tx_ioaddr = ioaddr_mapped;
+ tp->ioaddr = ioaddr;
+ tp->tx_ioaddr = ioaddr;
tp->dev = dev;
- /* need to be able to restore PCI state after a suspend */
- pci_save_state(pdev);
-
/* Init sequence:
* 1) Reset the adapter to clear any bad juju
* 2) Reload the sleep image
@@ -2388,16 +2464,18 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
* 4) Get the hardware address.
* 5) Put the card to sleep.
*/
- if (typhoon_reset(ioaddr_mapped, WaitSleep) < 0) {
+ if (typhoon_reset(ioaddr, WaitSleep) < 0) {
printk(ERR_PFX "%s: could not reset 3XP\n", pci_name(pdev));
err = -EIO;
goto error_out_dma;
}
/* Now that we've reset the 3XP and are sure it's not going to
- * write all over memory, enable bus mastering.
+ * write all over memory, enable bus mastering, and save our
+ * state for resuming after a suspend.
*/
pci_set_master(pdev);
+ pci_save_state(pdev);
/* dev->name is not valid until we register, but we need to
* use some common routines to initialize the card. So that those
@@ -2438,7 +2516,7 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
INIT_COMMAND_WITH_RESPONSE(&xp_cmd, TYPHOON_CMD_READ_VERSIONS);
if(typhoon_issue_command(tp, 1, &xp_cmd, 3, xp_resp) < 0) {
printk(ERR_PFX "%s: Could not get Sleep Image version\n",
- pdev->slot_name);
+ pci_name(pdev));
goto error_out_reset;
}
@@ -2454,7 +2532,7 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
if(xp_resp[0].numDesc != 0)
tp->capabilities |= TYPHOON_WAKEUP_NEEDS_RESET;
- if(typhoon_sleep(tp, 3, 0) < 0) {
+ if(typhoon_sleep(tp, PCI_D3hot, 0) < 0) {
printk(ERR_PFX "%s: cannot put adapter to sleep\n",
pci_name(pdev));
err = -EIO;
@@ -2491,8 +2569,9 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
pci_set_drvdata(pdev, dev);
- printk(KERN_INFO "%s: %s at 0x%lx, ",
- dev->name, typhoon_card_info[card_id].name, ioaddr);
+ printk(KERN_INFO "%s: %s at %s 0x%lx, ",
+ dev->name, typhoon_card_info[card_id].name,
+ use_mmio ? "MMIO" : "IO", pci_resource_start(pdev, use_mmio));
for(i = 0; i < 5; i++)
printk("%2.2x:", dev->dev_addr[i]);
printk("%2.2x\n", dev->dev_addr[i]);
@@ -2515,7 +2594,8 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
u8 *ver_string = (u8 *) &xp_resp[1];
ver_string[25] = 0;
printk(KERN_INFO "%s: Typhoon 1.1+ Sleep Image version "
- "%u.%u.%u.%u %s\n", dev->name, HIPQUAD(sleep_ver),
+ "%02x.%03x.%03x %s\n", dev->name, sleep_ver >> 24,
+ (sleep_ver >> 12) & 0xfff, sleep_ver & 0xfff,
ver_string);
} else {
printk(KERN_WARNING "%s: Unknown Sleep Image version "
@@ -2526,13 +2606,13 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
return 0;
error_out_reset:
- typhoon_reset(ioaddr_mapped, NoWait);
+ typhoon_reset(ioaddr, NoWait);
error_out_dma:
pci_free_consistent(pdev, sizeof(struct typhoon_shared),
shared, shared_dma);
error_out_remap:
- iounmap(ioaddr_mapped);
+ pci_iounmap(pdev, ioaddr);
error_out_regions:
pci_release_regions(pdev);
error_out_mwi:
@@ -2555,7 +2635,7 @@ typhoon_remove_one(struct pci_dev *pdev)
pci_set_power_state(pdev, PCI_D0);
pci_restore_state(pdev);
typhoon_reset(tp->ioaddr, NoWait);
- iounmap(tp->ioaddr);
+ pci_iounmap(pdev, tp->ioaddr);
pci_free_consistent(pdev, sizeof(struct typhoon_shared),
tp->shared, tp->shared_dma);
pci_release_regions(pdev);
diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c
index 26f3577327954..7b57d552094a4 100644
--- a/drivers/net/via-rhine.c
+++ b/drivers/net/via-rhine.c
@@ -390,7 +390,7 @@ enum backoff_bits {
#ifdef USE_MMIO
/* Registers we check that mmio and reg are the same. */
-int mmio_verify_registers[] = {
+static const int mmio_verify_registers[] = {
RxConfig, TxConfig, IntrEnable, ConfigA, ConfigB, ConfigC, ConfigD,
0
};
@@ -1197,8 +1197,10 @@ static int rhine_open(struct net_device *dev)
dev->name, rp->pdev->irq);
rc = alloc_ring(dev);
- if (rc)
+ if (rc) {
+ free_irq(rp->pdev->irq, dev);
return rc;
+ }
alloc_rbufs(dev);
alloc_tbufs(dev);
rhine_chip_reset(dev);
@@ -1899,6 +1901,9 @@ static void rhine_shutdown (struct device *gendev)
struct rhine_private *rp = netdev_priv(dev);
void __iomem *ioaddr = rp->base;
+ if (!(rp->quirks & rqWOL))
+ return; /* Nothing to do for non-WOL adapters */
+
rhine_power_init(dev);
/* Make sure we use pattern 0, 1 and not 4, 5 */
@@ -1937,7 +1942,7 @@ static void rhine_shutdown (struct device *gendev)
}
#ifdef CONFIG_PM
-static int rhine_suspend(struct pci_dev *pdev, u32 state)
+static int rhine_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct net_device *dev = pci_get_drvdata(pdev);
struct rhine_private *rp = netdev_priv(dev);
diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c
index 3102c689f5c45..15e710283493f 100644
--- a/drivers/net/via-velocity.c
+++ b/drivers/net/via-velocity.c
@@ -263,7 +263,7 @@ static int velocity_set_media_mode(struct velocity_info *vptr, u32 mii_status);
#ifdef CONFIG_PM
-static int velocity_suspend(struct pci_dev *pdev, u32 state);
+static int velocity_suspend(struct pci_dev *pdev, pm_message_t state);
static int velocity_resume(struct pci_dev *pdev);
static int velocity_netdev_event(struct notifier_block *nb, unsigned long notification, void *ptr);
@@ -2898,7 +2898,7 @@ static void velocity_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo
struct velocity_info *vptr = dev->priv;
strcpy(info->driver, VELOCITY_NAME);
strcpy(info->version, VELOCITY_VERSION);
- strcpy(info->bus_info, vptr->pdev->slot_name);
+ strcpy(info->bus_info, pci_name(vptr->pdev));
}
static void velocity_ethtool_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
@@ -3096,7 +3096,7 @@ static void velocity_restore_context(struct velocity_info *vptr, struct velocity
* we are interested in.
*/
-u16 wol_calc_crc(int size, u8 * pattern, u8 *mask_pattern)
+static u16 wol_calc_crc(int size, u8 * pattern, u8 *mask_pattern)
{
u16 crc = 0xFFFF;
u8 mask;
@@ -3210,9 +3210,10 @@ static int velocity_set_wol(struct velocity_info *vptr)
return 0;
}
-static int velocity_suspend(struct pci_dev *pdev, u32 state)
+static int velocity_suspend(struct pci_dev *pdev, pm_message_t state)
{
- struct velocity_info *vptr = pci_get_drvdata(pdev);
+ struct net_device *dev = pci_get_drvdata(pdev);
+ struct velocity_info *vptr = netdev_priv(dev);
unsigned long flags;
if(!netif_running(vptr->dev))
@@ -3245,7 +3246,8 @@ static int velocity_suspend(struct pci_dev *pdev, u32 state)
static int velocity_resume(struct pci_dev *pdev)
{
- struct velocity_info *vptr = pci_get_drvdata(pdev);
+ struct net_device *dev = pci_get_drvdata(pdev);
+ struct velocity_info *vptr = netdev_priv(dev);
unsigned long flags;
int i;
diff --git a/drivers/net/wan/Kconfig b/drivers/net/wan/Kconfig
index 5e6c71c7e1245..35791934a602e 100644
--- a/drivers/net/wan/Kconfig
+++ b/drivers/net/wan/Kconfig
@@ -155,7 +155,8 @@ config HDLC
Network) card supported by this driver and you are planning to
connect the box to a WAN.
- You will need supporting software from <http://hq.pm.waw.pl/hdlc/>.
+ You will need supporting software from
+ <http://www.kernel.org/pub/linux/utils/net/hdlc/>.
Generic HDLC driver currently supports raw HDLC, Cisco HDLC, Frame
Relay, synchronous Point-to-Point Protocol (PPP) and X.25.
@@ -225,7 +226,7 @@ config PCI200SYN
Driver for PCI200SYN cards by Goramo sp. j.
If you have such a card, say Y here and see
- <http://hq.pm.waw.pl/hdlc/>.
+ <http://www.kernel.org/pub/linux/utils/net/hdlc/>.
To compile this as a module, choose M here: the
module will be called pci200syn.
@@ -239,7 +240,7 @@ config WANXL
Driver for wanXL PCI cards by SBE Inc.
If you have such a card, say Y here and see
- <http://hq.pm.waw.pl/hdlc/>.
+ <http://www.kernel.org/pub/linux/utils/net/hdlc/>.
To compile this as a module, choose M here: the
module will be called wanxl.
@@ -292,7 +293,7 @@ config N2
SDL Communications Inc.
If you have such a card, say Y here and see
- <http://hq.pm.waw.pl/hdlc/>.
+ <http://www.kernel.org/pub/linux/utils/net/hdlc/>.
Note that N2csu and N2dds cards are not supported by this driver.
@@ -308,7 +309,7 @@ config C101
Driver for C101 SuperSync ISA cards by Moxa Technologies Co., Ltd.
If you have such a card, say Y here and see
- <http://hq.pm.waw.pl/pub/hdlc/>
+ <http://www.kernel.org/pub/linux/utils/net/hdlc/>.
To compile this driver as a module, choose M here: the
module will be called c101.
diff --git a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c
index 7a84ca7e7c40c..921a573372e94 100644
--- a/drivers/net/wan/cosa.c
+++ b/drivers/net/wan/cosa.c
@@ -543,7 +543,7 @@ static int cosa_probe(int base, int irq, int dma)
* FIXME: When this code is not used as module, we should
* probably call udelay() instead of the interruptible sleep.
*/
- current->state = TASK_INTERRUPTIBLE;
+ set_current_state(TASK_INTERRUPTIBLE);
cosa_putstatus(cosa, SR_TX_INT_ENA);
schedule_timeout(30);
irq = probe_irq_off(irqs);
@@ -1564,8 +1564,7 @@ static int cosa_reset_and_read_id(struct cosa_data *cosa, char *idstring)
cosa_getdata8(cosa);
cosa_putstatus(cosa, SR_RST);
#ifdef MODULE
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(HZ/2);
+ msleep(500);
#else
udelay(5*100000);
#endif
@@ -1618,7 +1617,7 @@ static int get_wait_data(struct cosa_data *cosa)
return r;
}
/* sleep if not ready to read */
- current->state = TASK_INTERRUPTIBLE;
+ set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(1);
}
printk(KERN_INFO "cosa: timeout in get_wait_data (status 0x%x)\n",
diff --git a/drivers/net/wan/hd6457x.c b/drivers/net/wan/hd6457x.c
index 05107bc0fd380..d3743321a9777 100644
--- a/drivers/net/wan/hd6457x.c
+++ b/drivers/net/wan/hd6457x.c
@@ -315,7 +315,7 @@ static inline void sca_rx(card_t *card, port_t *port, pkt_desc __iomem *desc, u1
#endif
stats->rx_packets++;
stats->rx_bytes += skb->len;
- skb->dev->last_rx = jiffies;
+ dev->last_rx = jiffies;
skb->protocol = hdlc_type_trans(skb, dev);
netif_rx(skb);
}
diff --git a/drivers/net/wan/sbni.c b/drivers/net/wan/sbni.c
index da388973375d3..db2c798ba89ef 100644
--- a/drivers/net/wan/sbni.c
+++ b/drivers/net/wan/sbni.c
@@ -176,7 +176,7 @@ static u32 mac[ SBNI_MAX_NUM_CARDS ] __initdata;
#ifndef MODULE
typedef u32 iarr[];
-static iarr *dest[5] = { &io, &irq, &baud, &rxl, &mac };
+static iarr __initdata *dest[5] = { &io, &irq, &baud, &rxl, &mac };
#endif
/* A zero-terminated list of I/O addresses to be probed on ISA bus */
diff --git a/drivers/net/wan/wanxl.c b/drivers/net/wan/wanxl.c
index e71b1800ef2f2..1e7b47704ad9e 100644
--- a/drivers/net/wan/wanxl.c
+++ b/drivers/net/wan/wanxl.c
@@ -72,7 +72,7 @@ typedef struct card_t {
u8 irq;
u8 __iomem *plx; /* PLX PCI9060 virtual base address */
- struct pci_dev *pdev; /* for pdev->slot_name */
+ struct pci_dev *pdev; /* for pci_name(pdev) */
int rx_in;
struct sk_buff *rx_skbs[RX_QUEUE_LENGTH];
card_status_t *status; /* shared between host and card */
@@ -88,12 +88,6 @@ static inline port_t* dev_to_port(struct net_device *dev)
}
-static inline const char* card_name(struct pci_dev *pdev)
-{
- return pdev->slot_name;
-}
-
-
static inline port_status_t* get_status(port_t *port)
{
return &port->card->status->port_status[port->node];
@@ -107,7 +101,7 @@ static inline dma_addr_t pci_map_single_debug(struct pci_dev *pdev, void *ptr,
dma_addr_t addr = pci_map_single(pdev, ptr, size, direction);
if (addr + size > 0x100000000LL)
printk(KERN_CRIT "wanXL %s: pci_map_single() returned memory"
- " at 0x%LX!\n", card_name(pdev),
+ " at 0x%LX!\n", pci_name(pdev),
(unsigned long long)addr);
return addr;
}
@@ -201,7 +195,7 @@ static inline void wanxl_rx_intr(card_t *card)
desc->stat != PACKET_EMPTY) {
if ((desc->stat & PACKET_PORT_MASK) > card->n_ports)
printk(KERN_CRIT "wanXL %s: received packet for"
- " nonexistent port\n", card_name(card->pdev));
+ " nonexistent port\n", pci_name(card->pdev));
else {
struct sk_buff *skb = card->rx_skbs[card->rx_in];
port_t *port = &card->ports[desc->stat &
@@ -604,7 +598,7 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
card = kmalloc(alloc_size, GFP_KERNEL);
if (card == NULL) {
printk(KERN_ERR "wanXL %s: unable to allocate memory\n",
- card_name(pdev));
+ pci_name(pdev));
pci_release_regions(pdev);
pci_disable_device(pdev);
return -ENOBUFS;
@@ -623,7 +617,7 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
#ifdef DEBUG_PCI
printk(KERN_DEBUG "wanXL %s: pci_alloc_consistent() returned memory"
- " at 0x%LX\n", card_name(pdev),
+ " at 0x%LX\n", pci_name(pdev),
(unsigned long long)card->status_address);
#endif
@@ -649,7 +643,7 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
while ((stat = readl(card->plx + PLX_MAILBOX_0)) != 0) {
if (time_before(timeout, jiffies)) {
printk(KERN_WARNING "wanXL %s: timeout waiting for"
- " PUTS to complete\n", card_name(pdev));
+ " PUTS to complete\n", pci_name(pdev));
wanxl_pci_remove_one(pdev);
return -ENODEV;
}
@@ -661,7 +655,7 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
default:
printk(KERN_WARNING "wanXL %s: PUTS test 0x%X"
- " failed\n", card_name(pdev), stat & 0x30);
+ " failed\n", pci_name(pdev), stat & 0x30);
wanxl_pci_remove_one(pdev);
return -ENODEV;
}
@@ -681,7 +675,7 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
(TX_BUFFERS + RX_BUFFERS) * BUFFER_LENGTH * ports) {
printk(KERN_WARNING "wanXL %s: no enough on-board RAM"
" (%u bytes detected, %u bytes required)\n",
- card_name(pdev), ramsize, BUFFERS_ADDR +
+ pci_name(pdev), ramsize, BUFFERS_ADDR +
(TX_BUFFERS + RX_BUFFERS) * BUFFER_LENGTH * ports);
wanxl_pci_remove_one(pdev);
return -ENODEV;
@@ -689,7 +683,7 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
if (wanxl_puts_command(card, MBX1_CMD_BSWAP)) {
printk(KERN_WARNING "wanXL %s: unable to Set Byte Swap"
- " Mode\n", card_name(pdev));
+ " Mode\n", pci_name(pdev));
wanxl_pci_remove_one(pdev);
return -ENODEV;
}
@@ -720,7 +714,7 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
if (wanxl_puts_command(card, MBX1_CMD_ABORTJ)) {
printk(KERN_WARNING "wanXL %s: unable to Abort and Jump\n",
- card_name(pdev));
+ pci_name(pdev));
wanxl_pci_remove_one(pdev);
return -ENODEV;
}
@@ -735,7 +729,7 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
if (!stat) {
printk(KERN_WARNING "wanXL %s: timeout while initializing card"
- "firmware\n", card_name(pdev));
+ "firmware\n", pci_name(pdev));
wanxl_pci_remove_one(pdev);
return -ENODEV;
}
@@ -745,12 +739,12 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
#endif
printk(KERN_INFO "wanXL %s: at 0x%X, %u KB of RAM at 0x%X, irq %u\n",
- card_name(pdev), plx_phy, ramsize / 1024, mem_phy, pdev->irq);
+ pci_name(pdev), plx_phy, ramsize / 1024, mem_phy, pdev->irq);
/* Allocate IRQ */
if (request_irq(pdev->irq, wanxl_intr, SA_SHIRQ, "wanXL", card)) {
printk(KERN_WARNING "wanXL %s: could not allocate IRQ%i.\n",
- card_name(pdev), pdev->irq);
+ pci_name(pdev), pdev->irq);
wanxl_pci_remove_one(pdev);
return -EBUSY;
}
@@ -762,7 +756,7 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
struct net_device *dev = alloc_hdlcdev(port);
if (!dev) {
printk(KERN_ERR "wanXL %s: unable to allocate"
- " memory\n", card_name(pdev));
+ " memory\n", pci_name(pdev));
wanxl_pci_remove_one(pdev);
return -ENOMEM;
}
@@ -783,7 +777,7 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
get_status(port)->clocking = CLOCK_EXT;
if (register_hdlc_device(dev)) {
printk(KERN_ERR "wanXL %s: unable to register hdlc"
- " device\n", card_name(pdev));
+ " device\n", pci_name(pdev));
free_netdev(dev);
wanxl_pci_remove_one(pdev);
return -ENOBUFS;
@@ -791,7 +785,7 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
card->n_ports++;
}
- printk(KERN_INFO "wanXL %s: port", card_name(pdev));
+ printk(KERN_INFO "wanXL %s: port", pci_name(pdev));
for (i = 0; i < ports; i++)
printk("%s #%i: %s", i ? "," : "", i,
card->ports[i].dev->name);
diff --git a/drivers/net/wan/z85230.c b/drivers/net/wan/z85230.c
index 76efbcb9272bd..caa48f12fd0ff 100644
--- a/drivers/net/wan/z85230.c
+++ b/drivers/net/wan/z85230.c
@@ -734,7 +734,7 @@ irqreturn_t z8530_interrupt(int irq, void *dev_id, struct pt_regs *regs)
u8 intr;
static volatile int locker=0;
int work=0;
- struct z8530_irqhandler *irqs=dev->chanA.irqs;
+ struct z8530_irqhandler *irqs;
if(locker)
{
@@ -758,6 +758,8 @@ irqreturn_t z8530_interrupt(int irq, void *dev_id, struct pt_regs *regs)
/* Now walk the chip and see what it is wanting - it may be
an IRQ for someone else remember */
+ irqs=dev->chanA.irqs;
+
if(intr & (CHARxIP|CHATxIP|CHAEXT))
{
if(intr&CHARxIP)
diff --git a/drivers/net/wd.c b/drivers/net/wd.c
index 5d2eeb0524178..1f05d9bd05e40 100644
--- a/drivers/net/wd.c
+++ b/drivers/net/wd.c
@@ -131,6 +131,7 @@ 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
@@ -317,16 +318,22 @@ static int __init wd_probe1(struct net_device *dev, int ioaddr)
ei_status.rx_start_page = WD_START_PG + TX_PAGES;
/* Don't map in the shared memory until the board is actually opened. */
- ei_status.rmem_start = dev->mem_start + TX_PAGES*256;
/* Some cards (eg WD8003EBT) can be jumpered for more (32k!) memory. */
if (dev->mem_end != 0) {
ei_status.stop_page = (dev->mem_end - dev->mem_start)/256;
+ ei_status.priv = dev->mem_end - dev->mem_start;
} else {
ei_status.stop_page = word16 ? WD13_STOP_PG : WD03_STOP_PG;
dev->mem_end = dev->mem_start + (ei_status.stop_page - WD_START_PG)*256;
+ ei_status.priv = (ei_status.stop_page - WD_START_PG)*256;
+ }
+
+ ei_status.mem = ioremap(dev->mem_start, ei_status.priv);
+ if (!ei_status.mem) {
+ free_irq(dev->irq, dev);
+ return -ENOMEM;
}
- ei_status.rmem_end = dev->mem_end;
printk(" %s, IRQ %d, shared memory at %#lx-%#lx.\n",
model_name, dev->irq, dev->mem_start, dev->mem_end-1);
@@ -397,7 +404,7 @@ wd_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page
{
int wd_cmdreg = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */
- unsigned long hdr_start = dev->mem_start + ((ring_page - WD_START_PG)<<8);
+ void __iomem *hdr_start = ei_status.mem + ((ring_page - WD_START_PG)<<8);
/* We'll always get a 4 byte header read followed by a packet read, so
we enable 16 bit mode before the header, and disable after the body. */
@@ -407,10 +414,10 @@ wd_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page
#ifdef __BIG_ENDIAN
/* Officially this is what we are doing, but the readl() is faster */
/* unfortunately it isn't endian aware of the struct */
- isa_memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
+ memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
hdr->count = le16_to_cpu(hdr->count);
#else
- ((unsigned int*)hdr)[0] = isa_readl(hdr_start);
+ ((unsigned int*)hdr)[0] = readl(hdr_start);
#endif
}
@@ -423,17 +430,18 @@ static void
wd_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
{
int wd_cmdreg = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */
- unsigned long xfer_start = dev->mem_start + ring_offset - (WD_START_PG<<8);
+ unsigned long offset = ring_offset - (WD_START_PG<<8);
+ void __iomem *xfer_start = ei_status.mem + offset;
- if (xfer_start + count > ei_status.rmem_end) {
+ if (offset + count > ei_status.priv) {
/* We must wrap the input move. */
- int semi_count = ei_status.rmem_end - xfer_start;
- isa_memcpy_fromio(skb->data, xfer_start, semi_count);
+ int semi_count = ei_status.priv - offset;
+ memcpy_fromio(skb->data, xfer_start, semi_count);
count -= semi_count;
- isa_memcpy_fromio(skb->data + semi_count, ei_status.rmem_start, count);
+ memcpy_fromio(skb->data + semi_count, ei_status.mem + TX_PAGES * 256, count);
} else {
/* Packet is in one chunk -- we can copy + cksum. */
- isa_eth_io_copy_and_sum(skb, xfer_start, count, 0);
+ eth_io_copy_and_sum(skb, xfer_start, count, 0);
}
/* Turn off 16 bit access so that reboot works. ISA brain-damage */
@@ -446,16 +454,16 @@ wd_block_output(struct net_device *dev, int count, const unsigned char *buf,
int start_page)
{
int wd_cmdreg = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */
- long shmem = dev->mem_start + ((start_page - WD_START_PG)<<8);
+ void __iomem *shmem = ei_status.mem + ((start_page - WD_START_PG)<<8);
if (ei_status.word16) {
/* Turn on and off 16 bit access so that reboot works. */
outb(ISA16 | ei_status.reg5, wd_cmdreg+WD_CMDREG5);
- isa_memcpy_toio(shmem, buf, count);
+ memcpy_toio(shmem, buf, count);
outb(ei_status.reg5, wd_cmdreg+WD_CMDREG5);
} else
- isa_memcpy_toio(shmem, buf, count);
+ memcpy_toio(shmem, buf, count);
}
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index 4bc0a2e9ae985..2899144f21537 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -1698,9 +1698,8 @@ static int readBSSListRid(struct airo_info *ai, int first,
issuecommand(ai, &cmd, &rsp);
up(&ai->sem);
/* Let the command take effect */
- set_current_state (TASK_INTERRUPTIBLE);
ai->task = current;
- schedule_timeout (3*HZ);
+ ssleep(3);
ai->task = NULL;
}
rc = PC4500_readrid(ai, first ? RID_BSSLISTFIRST : RID_BSSLISTNEXT,
@@ -2685,11 +2684,9 @@ int reset_card( struct net_device *dev , int lock) {
return -1;
waitbusy (ai);
OUT4500(ai,COMMAND,CMD_SOFTRESET);
- set_current_state (TASK_UNINTERRUPTIBLE);
- schedule_timeout (HZ/5);
+ msleep(200);
waitbusy (ai);
- set_current_state (TASK_UNINTERRUPTIBLE);
- schedule_timeout (HZ/5);
+ msleep(200);
if (lock)
up(&ai->sem);
return 0;
@@ -3443,7 +3440,7 @@ static void mpi_receive_802_3(struct airo_info *ai)
/* Make sure we got something */
if (rxd.rdy && rxd.valid == 0) {
len = rxd.len + 12;
- if (len < 12 && len > 2048)
+ if (len < 12 || len > 2048)
goto badrx;
skb = dev_alloc_skb(len);
@@ -5516,12 +5513,12 @@ static int airo_pci_resume(struct pci_dev *pdev)
} else {
OUT4500(ai, EVACK, EV_AWAKEN);
OUT4500(ai, EVACK, EV_AWAKEN);
- schedule_timeout(HZ/10);
+ msleep(100);
}
set_bit (FLAG_COMMIT, &ai->flags);
disable_MAC(ai, 0);
- schedule_timeout (HZ/5);
+ msleep(200);
if (ai->SSID) {
writeSsidRid(ai, ai->SSID, 0);
kfree(ai->SSID);
@@ -7470,8 +7467,7 @@ int cmdreset(struct airo_info *ai) {
OUT4500(ai,COMMAND,CMD_SOFTRESET);
- set_current_state (TASK_UNINTERRUPTIBLE);
- schedule_timeout (HZ); /* WAS 600 12/7/00 */
+ ssleep(1); /* WAS 600 12/7/00 */
if(!waitbusy (ai)){
printk(KERN_INFO "Waitbusy hang AFTER RESET\n");
@@ -7498,8 +7494,7 @@ int setflashmode (struct airo_info *ai) {
OUT4500(ai, SWS3, FLASH_COMMAND);
OUT4500(ai, COMMAND,0);
}
- set_current_state (TASK_UNINTERRUPTIBLE);
- schedule_timeout (HZ/2); /* 500ms delay */
+ msleep(500); /* 500ms delay */
if(!waitbusy(ai)) {
clear_bit (FLAG_FLASHING, &ai->flags);
@@ -7609,8 +7604,7 @@ int flashputbuf(struct airo_info *ai){
int flashrestart(struct airo_info *ai,struct net_device *dev){
int i,status;
- set_current_state (TASK_UNINTERRUPTIBLE);
- schedule_timeout (HZ); /* Added 12/7/00 */
+ ssleep(1); /* Added 12/7/00 */
clear_bit (FLAG_FLASHING, &ai->flags);
if (test_bit(FLAG_MPI, &ai->flags)) {
status = mpi_init_descriptors(ai);
@@ -7625,8 +7619,7 @@ int flashrestart(struct airo_info *ai,struct net_device *dev){
( ai, 2312, i >= MAX_FIDS / 2 );
}
- set_current_state (TASK_UNINTERRUPTIBLE);
- schedule_timeout (HZ); /* Added 12/7/00 */
+ ssleep(1); /* Added 12/7/00 */
return status;
}
#endif /* CISCO_EXT */
diff --git a/drivers/net/wireless/airport.c b/drivers/net/wireless/airport.c
index 51c54132c77c6..a1dc2a1960878 100644
--- a/drivers/net/wireless/airport.c
+++ b/drivers/net/wireless/airport.c
@@ -28,7 +28,6 @@
#include <linux/if_arp.h>
#include <linux/etherdevice.h>
#include <linux/wireless.h>
-#include <linux/delay.h>
#include <asm/io.h>
#include <asm/system.h>
@@ -45,7 +44,7 @@
struct airport {
struct macio_dev *mdev;
- void *vaddr;
+ void __iomem *vaddr;
int irq_requested;
int ndev_registered;
};
@@ -150,7 +149,7 @@ airport_detach(struct macio_dev *mdev)
ssleep(1);
macio_set_drvdata(mdev, NULL);
- free_netdev(dev);
+ free_orinocodev(dev);
return 0;
}
@@ -194,14 +193,14 @@ airport_attach(struct macio_dev *mdev, const struct of_match *match)
hermes_t *hw;
if (macio_resource_count(mdev) < 1 || macio_irq_count(mdev) < 1) {
- printk(KERN_ERR PFX "wrong interrupt/addresses in OF tree\n");
+ printk(KERN_ERR PFX "Wrong interrupt/addresses in OF tree\n");
return -ENODEV;
}
/* Allocate space for private device-specific data */
dev = alloc_orinocodev(sizeof(*card), airport_hard_reset);
if (! dev) {
- printk(KERN_ERR PFX "can't allocate device datas\n");
+ printk(KERN_ERR PFX "Cannot allocate network device\n");
return -ENODEV;
}
priv = netdev_priv(dev);
@@ -212,7 +211,7 @@ airport_attach(struct macio_dev *mdev, const struct of_match *match)
if (macio_request_resource(mdev, 0, "airport")) {
printk(KERN_ERR PFX "can't request IO resource !\n");
- free_netdev(dev);
+ free_orinocodev(dev);
return -EBUSY;
}
@@ -224,16 +223,15 @@ airport_attach(struct macio_dev *mdev, const struct of_match *match)
/* Setup interrupts & base address */
dev->irq = macio_irq(mdev, 0);
phys_addr = macio_resource_start(mdev, 0); /* Physical address */
- printk(KERN_DEBUG PFX "Airport at physical address %lx\n", phys_addr);
+ printk(KERN_DEBUG PFX "Physical address %lx\n", phys_addr);
dev->base_addr = phys_addr;
card->vaddr = ioremap(phys_addr, AIRPORT_IO_LEN);
if (!card->vaddr) {
- printk(PFX "ioremap() failed\n");
+ printk(KERN_ERR PFX "ioremap() failed\n");
goto failed;
}
- hermes_struct_init(hw, (ulong)card->vaddr,
- HERMES_MEM, HERMES_16BIT_REGSPACING);
+ hermes_struct_init(hw, card->vaddr, HERMES_16BIT_REGSPACING);
/* Power up card */
pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, macio_get_of_node(mdev), 0, 1);
@@ -242,7 +240,7 @@ airport_attach(struct macio_dev *mdev, const struct of_match *match)
/* Reset it before we get the interrupt */
hermes_init(hw);
- if (request_irq(dev->irq, orinoco_interrupt, 0, "Airport", dev)) {
+ if (request_irq(dev->irq, orinoco_interrupt, 0, dev->name, dev)) {
printk(KERN_ERR PFX "Couldn't get IRQ %d\n", dev->irq);
goto failed;
}
@@ -253,7 +251,7 @@ airport_attach(struct macio_dev *mdev, const struct of_match *match)
printk(KERN_ERR PFX "register_netdev() failed\n");
goto failed;
}
- printk(KERN_DEBUG PFX "card registered for interface %s\n", dev->name);
+ printk(KERN_DEBUG PFX "Card registered for interface %s\n", dev->name);
card->ndev_registered = 1;
return 0;
failed:
diff --git a/drivers/net/wireless/arlan.h b/drivers/net/wireless/arlan.h
index ce8e177b73ad7..70a6d7b83c4a0 100644
--- a/drivers/net/wireless/arlan.h
+++ b/drivers/net/wireless/arlan.h
@@ -43,8 +43,8 @@
extern int init_arlan_proc(void);
extern void cleanup_arlan_proc(void);
#else
-#define init_arlan_proc() (0)
-#define cleanup_arlan_proc() do { } while (0);
+#define init_arlan_proc() ({ 0; })
+#define cleanup_arlan_proc() do { } while (0)
#endif
extern struct net_device *arlan_device[MAX_ARLANS];
diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c
index 646011351b982..18a7d38d2a130 100644
--- a/drivers/net/wireless/atmel.c
+++ b/drivers/net/wireless/atmel.c
@@ -69,6 +69,7 @@
#include <linux/moduleparam.h>
#include <linux/firmware.h>
#include "ieee802_11.h"
+#include "atmel.h"
#define DRIVER_MAJOR 0
#define DRIVER_MINOR 96
@@ -83,6 +84,23 @@ MODULE_SUPPORTED_DEVICE("Atmel at76c50x wireless cards");
static char *firmware = NULL;
module_param(firmware, charp, 0);
+/* table of firmware file names */
+static struct {
+ AtmelFWType fw_type;
+ const char *fw_file;
+ const char *fw_file_ext;
+} fw_table[] = {
+ { ATMEL_FW_TYPE_502, "atmel_at76c502", "bin" },
+ { ATMEL_FW_TYPE_502D, "atmel_at76c502d", "bin" },
+ { ATMEL_FW_TYPE_502E, "atmel_at76c502e", "bin" },
+ { ATMEL_FW_TYPE_502_3COM, "atmel_at76c502_3com", "bin" },
+ { ATMEL_FW_TYPE_504, "atmel_at76c504", "bin" },
+ { ATMEL_FW_TYPE_504_2958, "atmel_at76c504_2958", "bin" },
+ { ATMEL_FW_TYPE_504A_2958,"atmel_at76c504a_2958","bin" },
+ { ATMEL_FW_TYPE_506, "atmel_at76c506", "bin" },
+ { ATMEL_FW_TYPE_NONE, NULL, NULL }
+};
+
#define MAX_SSID_LENGTH 32
#define MGMT_JIFFIES (256 * HZ / 100)
@@ -458,8 +476,8 @@ struct atmel_private {
void *card; /* Bus dependent stucture varies for PCcard */
int (*present_callback)(void *); /* And callback which uses it */
char firmware_id[32];
- char firmware_template[32];
- unsigned char *firmware;
+ AtmelFWType firmware_type;
+ u8 *firmware;
int firmware_length;
struct timer_list management_timer;
struct net_device *dev;
@@ -1293,17 +1311,21 @@ static struct iw_statistics *atmel_get_wireless_stats (struct net_device *dev)
if (priv->operating_mode == IW_MODE_INFRA) {
if (priv->station_state != STATION_STATE_READY) {
priv->wstats.qual.qual = 0;
- priv->wstats.qual.level = 0;
+ priv->wstats.qual.level = 0;
+ priv->wstats.qual.updated = (IW_QUAL_QUAL_INVALID
+ | IW_QUAL_LEVEL_INVALID);
}
priv->wstats.qual.noise = 0;
- priv->wstats.qual.updated = 7;
+ priv->wstats.qual.updated |= IW_QUAL_NOISE_INVALID;
} else {
/* Quality levels cannot be determined in ad-hoc mode,
because we can 'hear' more that one remote station. */
priv->wstats.qual.qual = 0;
priv->wstats.qual.level = 0;
priv->wstats.qual.noise = 0;
- priv->wstats.qual.updated = 0;
+ priv->wstats.qual.updated = IW_QUAL_QUAL_INVALID
+ | IW_QUAL_LEVEL_INVALID
+ | IW_QUAL_NOISE_INVALID;
priv->wstats.miss.beacon = 0;
}
@@ -1482,7 +1504,7 @@ static int atmel_read_proc(char *page, char **start, off_t off,
return len;
}
-struct net_device *init_atmel_card( unsigned short irq, int port, char *firmware_id,
+struct net_device *init_atmel_card( unsigned short irq, int port, const AtmelFWType fw_type,
struct device *sys_dev, int (*card_present)(void *), void *card)
{
struct net_device *dev;
@@ -1507,11 +1529,9 @@ struct net_device *init_atmel_card( unsigned short irq, int port, char *firmware
priv->card = card;
priv->firmware = NULL;
priv->firmware_id[0] = '\0';
- priv->firmware_template[0] = '\0';
+ priv->firmware_type = fw_type;
if (firmware) /* module parameter */
strcpy(priv->firmware_id, firmware);
- else if (firmware_id) /* from PCMCIA card-matching or PCI */
- strcpy(priv->firmware_template, firmware_id);
priv->bus_type = card_present ? BUS_TYPE_PCCARD : BUS_TYPE_PCI;
priv->station_state = STATION_STATE_DOWN;
priv->do_rx_crc = 0;
@@ -1579,6 +1599,8 @@ struct net_device *init_atmel_card( unsigned short irq, int port, char *firmware
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 );
goto err_out_free;
@@ -2218,6 +2240,13 @@ static int atmel_get_range(struct net_device *dev,
range->max_qual.qual = 100;
range->max_qual.level = 100;
range->max_qual.noise = 0;
+ range->max_qual.updated = IW_QUAL_NOISE_INVALID;
+
+ range->avg_qual.qual = 50;
+ range->avg_qual.level = 50;
+ range->avg_qual.noise = 0;
+ range->avg_qual.updated = IW_QUAL_NOISE_INVALID;
+
range->sensitivity = 0;
range->bitrate[0] = 1000000;
@@ -2247,9 +2276,6 @@ static int atmel_get_range(struct net_device *dev,
range->r_time_flags = 0;
range->min_retry = 1;
range->max_retry = 65535;
- range->avg_qual.qual = 50;
- range->avg_qual.level = 50;
- range->avg_qual.noise = 0;
return 0;
}
@@ -3025,16 +3051,23 @@ static void restart_search(struct atmel_private *priv)
static void smooth_rssi(struct atmel_private *priv, u8 rssi)
{
u8 old = priv->wstats.qual.level;
+ u8 max_rssi = 42; /* 502-rmfd-revd max by experiment, default for now */
- /* 502-rmfd-revd gives max signal level as 42, by experiment.
- This is going to break for other hardware variants. */
+ switch (priv->firmware_type) {
+ case ATMEL_FW_TYPE_502E:
+ max_rssi = 63; /* 502-rmfd-reve max by experiment */
+ break;
+ default:
+ break;
+ }
- rssi = rssi * 100 / 42;
+ rssi = rssi * 100 / max_rssi;
if((rssi + old) % 2)
priv->wstats.qual.level = ((rssi + old)/2) + 1;
else
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)
@@ -3047,8 +3080,10 @@ static void atmel_smooth_qual(struct atmel_private *priv)
priv->beacons_this_sec * priv->beacon_period * (priv->wstats.qual.level + 100) / 4000;
priv->beacons_this_sec = 0;
}
+ priv->wstats.qual.updated |= IW_QUAL_QUAL_UPDATED;
+ priv->wstats.qual.updated &= ~IW_QUAL_QUAL_INVALID;
}
-
+
/* deals with incoming managment frames. */
static void atmel_management_frame(struct atmel_private *priv, struct ieee802_11_hdr *header,
u16 frame_len, u8 rssi)
@@ -3611,8 +3646,8 @@ static int reset_atmel_card(struct net_device *dev)
const struct firmware *fw_entry = NULL;
unsigned char *fw;
int len = priv->firmware_length;
- if (!(fw = priv->firmware)) {
- if (strlen(priv->firmware_template) == 0) {
+ if (!(fw = priv->firmware)) {
+ if (priv->firmware_type == ATMEL_FW_TYPE_NONE) {
if (strlen(priv->firmware_id) == 0) {
printk(KERN_INFO
"%s: card type is unknown: assuming at76c502 firmware is OK.\n",
@@ -3627,24 +3662,36 @@ static int reset_atmel_card(struct net_device *dev)
"%s: firmware %s is missing, cannot continue.\n",
dev->name, priv->firmware_id);
return 0;
-
- }
+ }
} else {
- int i;
+ int fw_index = 0;
+ int success = 0;
+
+ /* get firmware filename entry based on firmware type ID */
+ while (fw_table[fw_index].fw_type != priv->firmware_type
+ && fw_table[fw_index].fw_type != ATMEL_FW_TYPE_NONE)
+ fw_index++;
- for (i = 0; firmware_modifier[i]; i++) {
- sprintf(priv->firmware_id, priv->firmware_template, firmware_modifier[i]);
- if (request_firmware(&fw_entry, priv->firmware_id, priv->sys_dev) == 0)
- break;
+ /* construct the actual firmware file name */
+ if (fw_table[fw_index].fw_type != ATMEL_FW_TYPE_NONE) {
+ int i;
+ for (i = 0; firmware_modifier[i]; i++) {
+ snprintf(priv->firmware_id, 32, "%s%s.%s", fw_table[fw_index].fw_file,
+ firmware_modifier[i], fw_table[fw_index].fw_file_ext);
+ priv->firmware_id[31] = '\0';
+ if (request_firmware(&fw_entry, priv->firmware_id, priv->sys_dev) == 0) {
+ success = 1;
+ break;
+ }
+ }
}
- if (!firmware_modifier[i]) {
+ if (!success) {
printk(KERN_ALERT
"%s: firmware %s is missing, cannot start.\n",
dev->name, priv->firmware_id);
priv->firmware_id[0] = '\0';
return 0;
}
- priv->firmware_template[0] = '\0';
}
fw = fw_entry->data;
diff --git a/drivers/net/wireless/atmel.h b/drivers/net/wireless/atmel.h
new file mode 100644
index 0000000000000..825000edfc2c9
--- /dev/null
+++ b/drivers/net/wireless/atmel.h
@@ -0,0 +1,43 @@
+/*** -*- linux-c -*- **********************************************************
+
+ Driver for Atmel at76c502 at76c504 and at76c506 wireless cards.
+
+ Copyright 2005 Dan Williams and Red Hat, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This software is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ 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
+
+******************************************************************************/
+
+#ifndef _ATMEL_H
+#define _ATMEL_H
+
+typedef enum {
+ ATMEL_FW_TYPE_NONE = 0,
+ ATMEL_FW_TYPE_502,
+ ATMEL_FW_TYPE_502D,
+ ATMEL_FW_TYPE_502E,
+ ATMEL_FW_TYPE_502_3COM,
+ ATMEL_FW_TYPE_504,
+ ATMEL_FW_TYPE_504_2958,
+ ATMEL_FW_TYPE_504A_2958,
+ ATMEL_FW_TYPE_506
+} AtmelFWType;
+
+struct net_device *init_atmel_card(unsigned short, int, const AtmelFWType, struct device *,
+ int (*present_func)(void *), void * );
+void stop_atmel_card( struct net_device *, int );
+int atmel_open( struct net_device * );
+
+#endif
diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c
index 1288d57f246b4..a91b507e0a7a2 100644
--- a/drivers/net/wireless/atmel_cs.c
+++ b/drivers/net/wireless/atmel_cs.c
@@ -55,6 +55,7 @@
#include <asm/system.h>
#include <linux/wireless.h>
+#include "atmel.h"
/*
All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If
@@ -90,11 +91,6 @@ MODULE_SUPPORTED_DEVICE("Atmel at76c50x PCMCIA cards");
event handler.
*/
-struct net_device *init_atmel_card(int, int, char *, struct device *,
- int (*present_func)(void *), void * );
-void stop_atmel_card( struct net_device *, int );
-int atmel_open( struct net_device * );
-
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,
@@ -307,28 +303,29 @@ static int card_present(void *arg)
static struct {
int manf, card;
char *ver1;
- char *firmware;
+ AtmelFWType firmware;
char *name;
} card_table[] = {
- { 0, 0, "WLAN/802.11b PC CARD", "atmel_at76c502d%s.bin", "Actiontec 802CAT1" },
- { 0, 0, "ATMEL/AT76C502AR", "atmel_at76c502%s.bin", "NoName-RFMD" },
- { 0, 0, "ATMEL/AT76C502AR_D", "atmel_at76c502d%s.bin", "NoName-revD" },
- { 0, 0, "ATMEL/AT76C502AR_E", "atmel_at76c502e%s.bin", "NoName-revE" },
- { 0, 0, "ATMEL/AT76C504", "atmel_at76c504%s.bin", "NoName-504" },
- { 0, 0, "ATMEL/AT76C504A", "atmel_at76c504a_2958%s.bin", "NoName-504a-2958" },
- { 0, 0, "ATMEL/AT76C504_R", "atmel_at76c504_2958%s.bin", "NoName-504-2958" },
- { MANFID_3COM, 0x0620, NULL, "atmel_at76c502_3com%s.bin", "3com 3CRWE62092B" },
- { MANFID_3COM, 0x0696, NULL, "atmel_at76c502_3com%s.bin", "3com 3CRSHPW196" },
- { 0, 0, "SMC/2632W-V2", "atmel_at76c502%s.bin", "SMC 2632W-V2" },
- { 0, 0, "SMC/2632W", "atmel_at76c502d%s.bin", "SMC 2632W-V3" },
- { 0xd601, 0x0007, NULL, "atmel_at76c502%s.bin", "Sitecom WLAN-011" },
- { 0x01bf, 0x3302, NULL, "atmel_at76c502e%s.bin", "Belkin F5D6020-V2" },
- { 0, 0, "BT/Voyager 1020 Laptop Adapter", "atmel_at76c502%s.bin", "BT Voyager 1020" },
- { 0, 0, "IEEE 802.11b/Wireless LAN PC Card", "atmel_at76c502%s.bin", "Siemens Gigaset PC Card II" },
- { 0, 0, "CNet/CNWLC 11Mbps Wireless PC Card V-5", "atmel_at76c502e%s.bin", "CNet CNWLC-811ARL" },
- { 0, 0, "Wireless/PC_CARD", "atmel_at76c502d%s.bin", "Planet WL-3552" },
- { 0, 0, "OEM/11Mbps Wireless LAN PC Card V-3", "atmel_at76c502%s.bin", "OEM 11Mbps WLAN PCMCIA Card" },
- { 0, 0, "11WAVE/11WP611AL-E", "atmel_at76c502e%s.bin", "11WAVE WaveBuddy" }
+ { 0, 0, "WLAN/802.11b PC CARD", ATMEL_FW_TYPE_502D, "Actiontec 802CAT1" },
+ { 0, 0, "ATMEL/AT76C502AR", ATMEL_FW_TYPE_502, "NoName-RFMD" },
+ { 0, 0, "ATMEL/AT76C502AR_D", ATMEL_FW_TYPE_502D, "NoName-revD" },
+ { 0, 0, "ATMEL/AT76C502AR_E", ATMEL_FW_TYPE_502E, "NoName-revE" },
+ { 0, 0, "ATMEL/AT76C504", ATMEL_FW_TYPE_504, "NoName-504" },
+ { 0, 0, "ATMEL/AT76C504A", ATMEL_FW_TYPE_504A_2958, "NoName-504a-2958" },
+ { 0, 0, "ATMEL/AT76C504_R", ATMEL_FW_TYPE_504_2958, "NoName-504-2958" },
+ { MANFID_3COM, 0x0620, NULL, ATMEL_FW_TYPE_502_3COM, "3com 3CRWE62092B" },
+ { MANFID_3COM, 0x0696, NULL, ATMEL_FW_TYPE_502_3COM, "3com 3CRSHPW196" },
+ { 0, 0, "SMC/2632W-V2", ATMEL_FW_TYPE_502, "SMC 2632W-V2" },
+ { 0, 0, "SMC/2632W", ATMEL_FW_TYPE_502D, "SMC 2632W-V3" },
+ { 0xd601, 0x0007, NULL, ATMEL_FW_TYPE_502, "Sitecom WLAN-011" },
+ { 0x01bf, 0x3302, NULL, ATMEL_FW_TYPE_502E, "Belkin F5D6020-V2" },
+ { 0, 0, "BT/Voyager 1020 Laptop Adapter", ATMEL_FW_TYPE_502, "BT Voyager 1020" },
+ { 0, 0, "IEEE 802.11b/Wireless LAN PC Card", ATMEL_FW_TYPE_502, "Siemens Gigaset PC Card II" },
+ { 0, 0, "CNet/CNWLC 11Mbps Wireless PC Card V-5", ATMEL_FW_TYPE_502E, "CNet CNWLC-811ARL" },
+ { 0, 0, "Wireless/PC_CARD", ATMEL_FW_TYPE_502D, "Planet WL-3552" },
+ { 0, 0, "OEM/11Mbps Wireless LAN PC Card V-3", ATMEL_FW_TYPE_502, "OEM 11Mbps WLAN PCMCIA Card" },
+ { 0, 0, "11WAVE/11WP611AL-E", ATMEL_FW_TYPE_502E, "11WAVE WaveBuddy" },
+ { 0, 0, "LG/LW2100N", ATMEL_FW_TYPE_502E, "LG LW2100N 11Mbps WLAN PCMCIA Card" },
};
static void atmel_config(dev_link_t *link)
@@ -520,7 +517,7 @@ static void atmel_config(dev_link_t *link)
((local_info_t*)link->priv)->eth_dev =
init_atmel_card(link->irq.AssignedIRQ,
link->io.BasePort1,
- card_index == -1 ? NULL : card_table[card_index].firmware,
+ card_index == -1 ? ATMEL_FW_TYPE_NONE : card_table[card_index].firmware,
&handle_to_dev(handle),
card_present,
link);
diff --git a/drivers/net/wireless/atmel_pci.c b/drivers/net/wireless/atmel_pci.c
index a7fe4d586878d..2eb00a957bbe5 100644
--- a/drivers/net/wireless/atmel_pci.c
+++ b/drivers/net/wireless/atmel_pci.c
@@ -25,6 +25,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/netdevice.h>
+#include "atmel.h"
MODULE_AUTHOR("Simon Kelley");
MODULE_DESCRIPTION("Support for Atmel at76c50x 802.11 wireless ethernet cards.");
@@ -40,9 +41,6 @@ MODULE_DEVICE_TABLE(pci, card_ids);
static int atmel_pci_probe(struct pci_dev *, const struct pci_device_id *);
static void atmel_pci_remove(struct pci_dev *);
-struct net_device *init_atmel_card(int, int, char *, struct device *,
- int (*present_func)(void *), void * );
-void stop_atmel_card( struct net_device *, int );
static struct pci_driver atmel_driver = {
.name = "atmel",
@@ -63,7 +61,7 @@ static int __devinit atmel_pci_probe(struct pci_dev *pdev,
pci_set_master(pdev);
dev = init_atmel_card(pdev->irq, pdev->resource[1].start,
- "atmel_at76c506%s.bin",
+ ATMEL_FW_TYPE_506,
&pdev->dev, NULL, NULL);
if (!dev)
return -ENODEV;
diff --git a/drivers/net/wireless/hermes.c b/drivers/net/wireless/hermes.c
index 7300901185d9d..21c3d0d227e62 100644
--- a/drivers/net/wireless/hermes.c
+++ b/drivers/net/wireless/hermes.c
@@ -48,6 +48,7 @@
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/kernel.h>
+#include <linux/net.h>
#include <asm/errno.h>
#include "hermes.h"
@@ -67,8 +68,7 @@ MODULE_LICENSE("Dual MPL/GPL");
* Debugging helpers
*/
-#define IO_TYPE(hw) ((hw)->io_space ? "IO " : "MEM ")
-#define DMSG(stuff...) do {printk(KERN_DEBUG "hermes @ %s0x%x: " , IO_TYPE(hw), hw->iobase); \
+#define DMSG(stuff...) do {printk(KERN_DEBUG "hermes @ %p: " , hw->iobase); \
printk(stuff);} while (0)
#undef HERMES_DEBUG
@@ -123,11 +123,9 @@ static int hermes_issue_cmd(hermes_t *hw, u16 cmd, u16 param0)
* Function definitions
*/
-void hermes_struct_init(hermes_t *hw, ulong address,
- int io_space, int reg_spacing)
+void hermes_struct_init(hermes_t *hw, void __iomem *address, int reg_spacing)
{
hw->iobase = address;
- hw->io_space = io_space;
hw->reg_spacing = reg_spacing;
hw->inten = 0x0;
@@ -200,9 +198,9 @@ int hermes_init(hermes_t *hw)
}
if (! (reg & HERMES_EV_CMD)) {
- printk(KERN_ERR "hermes @ %s0x%lx: "
+ printk(KERN_ERR "hermes @ %p: "
"Timeout waiting for card to reset (reg=0x%04x)!\n",
- IO_TYPE(hw), hw->iobase, reg);
+ hw->iobase, reg);
err = -ETIMEDOUT;
goto out;
}
@@ -235,13 +233,16 @@ int hermes_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0,
err = hermes_issue_cmd(hw, cmd, parm0);
if (err) {
if (! hermes_present(hw)) {
- printk(KERN_WARNING "hermes @ %s0x%lx: "
- "Card removed while issuing command.\n",
- IO_TYPE(hw), hw->iobase);
+ if (net_ratelimit())
+ printk(KERN_WARNING "hermes @ %p: "
+ "Card removed while issuing command "
+ "0x%04x.\n", hw->iobase, cmd);
err = -ENODEV;
} else
- printk(KERN_ERR "hermes @ %s0x%lx: Error %d issuing command.\n",
- IO_TYPE(hw), hw->iobase, err);
+ if (net_ratelimit())
+ printk(KERN_ERR "hermes @ %p: "
+ "Error %d issuing command 0x%04x.\n",
+ hw->iobase, err, cmd);
goto out;
}
@@ -254,17 +255,16 @@ int hermes_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0,
}
if (! hermes_present(hw)) {
- printk(KERN_WARNING "hermes @ %s0x%lx: "
- "Card removed while waiting for command completion.\n",
- IO_TYPE(hw), hw->iobase);
+ printk(KERN_WARNING "hermes @ %p: Card removed "
+ "while waiting for command 0x%04x completion.\n",
+ hw->iobase, cmd);
err = -ENODEV;
goto out;
}
if (! (reg & HERMES_EV_CMD)) {
- printk(KERN_ERR "hermes @ %s0x%lx: "
- "Timeout waiting for command completion.\n",
- IO_TYPE(hw), hw->iobase);
+ printk(KERN_ERR "hermes @ %p: Timeout waiting for "
+ "command 0x%04x completion.\n", hw->iobase, cmd);
err = -ETIMEDOUT;
goto out;
}
@@ -309,16 +309,16 @@ int hermes_allocate(hermes_t *hw, u16 size, u16 *fid)
}
if (! hermes_present(hw)) {
- printk(KERN_WARNING "hermes @ %s0x%lx: "
+ printk(KERN_WARNING "hermes @ %p: "
"Card removed waiting for frame allocation.\n",
- IO_TYPE(hw), hw->iobase);
+ hw->iobase);
return -ENODEV;
}
if (! (reg & HERMES_EV_ALLOC)) {
- printk(KERN_ERR "hermes @ %s0x%lx: "
+ printk(KERN_ERR "hermes @ %p: "
"Timeout waiting for frame allocation\n",
- IO_TYPE(hw), hw->iobase);
+ hw->iobase);
return -ETIMEDOUT;
}
@@ -383,12 +383,17 @@ static int hermes_bap_seek(hermes_t *hw, int bap, u16 id, u16 offset)
reg = hermes_read_reg(hw, oreg);
}
- if (reg & HERMES_OFFSET_BUSY) {
- return -ETIMEDOUT;
- }
+ if (reg != offset) {
+ printk(KERN_ERR "hermes @ %p: BAP%d offset %s: "
+ "reg=0x%x id=0x%x offset=0x%x\n", hw->iobase, bap,
+ (reg & HERMES_OFFSET_BUSY) ? "timeout" : "error",
+ reg, id, offset);
+
+ if (reg & HERMES_OFFSET_BUSY) {
+ return -ETIMEDOUT;
+ }
- if (reg & HERMES_OFFSET_ERR) {
- return -EIO;
+ return -EIO; /* error or wrong offset */
}
return 0;
@@ -476,7 +481,7 @@ int hermes_read_ltv(hermes_t *hw, int bap, u16 rid, unsigned bufsize,
rlength = hermes_read_reg(hw, dreg);
if (! rlength)
- return -ENOENT;
+ return -ENODATA;
rtype = hermes_read_reg(hw, dreg);
@@ -484,14 +489,13 @@ int hermes_read_ltv(hermes_t *hw, int bap, u16 rid, unsigned bufsize,
*length = rlength;
if (rtype != rid)
- printk(KERN_WARNING "hermes @ %s0x%lx: "
- "hermes_read_ltv(): rid (0x%04x) does not match type (0x%04x)\n",
- IO_TYPE(hw), hw->iobase, rid, rtype);
+ printk(KERN_WARNING "hermes @ %p: %s(): "
+ "rid (0x%04x) does not match type (0x%04x)\n",
+ hw->iobase, __FUNCTION__, rid, rtype);
if (HERMES_RECLEN_TO_BYTES(rlength) > bufsize)
- printk(KERN_WARNING "hermes @ %s0x%lx: "
+ printk(KERN_WARNING "hermes @ %p: "
"Truncating LTV record from %d to %d bytes. "
- "(rid=0x%04x, len=0x%04x)\n",
- IO_TYPE(hw), hw->iobase,
+ "(rid=0x%04x, len=0x%04x)\n", hw->iobase,
HERMES_RECLEN_TO_BYTES(rlength), bufsize, rid, rlength);
nwords = min((unsigned)rlength - 1, bufsize / 2);
diff --git a/drivers/net/wireless/hermes.h b/drivers/net/wireless/hermes.h
index 429d5724069d2..8c9e874c9118c 100644
--- a/drivers/net/wireless/hermes.h
+++ b/drivers/net/wireless/hermes.h
@@ -340,14 +340,11 @@ struct hermes_debug_entry {
#ifdef __KERNEL__
/* Timeouts */
-#define HERMES_BAP_BUSY_TIMEOUT (500) /* In iterations of ~1us */
+#define HERMES_BAP_BUSY_TIMEOUT (10000) /* In iterations of ~1us */
/* Basic control structure */
typedef struct hermes {
- unsigned long iobase;
- int io_space; /* 1 if we IO-mapped IO, 0 for memory-mapped IO? */
-#define HERMES_IO 1
-#define HERMES_MEM 0
+ void __iomem *iobase;
int reg_spacing;
#define HERMES_16BIT_REGSPACING 0
#define HERMES_32BIT_REGSPACING 1
@@ -362,21 +359,15 @@ typedef struct hermes {
} hermes_t;
/* Register access convenience macros */
-#define hermes_read_reg(hw, off) ((hw)->io_space ? \
- inw((hw)->iobase + ( (off) << (hw)->reg_spacing )) : \
- readw((hw)->iobase + ( (off) << (hw)->reg_spacing )))
-#define hermes_write_reg(hw, off, val) do { \
- if ((hw)->io_space) \
- outw_p((val), (hw)->iobase + ((off) << (hw)->reg_spacing)); \
- else \
- writew((val), (hw)->iobase + ((off) << (hw)->reg_spacing)); \
- } while (0)
+#define hermes_read_reg(hw, off) \
+ (ioread16((hw)->iobase + ( (off) << (hw)->reg_spacing )))
+#define hermes_write_reg(hw, off, val) \
+ (iowrite16((val), (hw)->iobase + ((off) << (hw)->reg_spacing)))
#define hermes_read_regn(hw, name) hermes_read_reg((hw), HERMES_##name)
#define hermes_write_regn(hw, name, val) hermes_write_reg((hw), HERMES_##name, (val))
/* Function prototypes */
-void hermes_struct_init(hermes_t *hw, ulong address, int io_space,
- int reg_spacing);
+void hermes_struct_init(hermes_t *hw, void __iomem *address, int reg_spacing);
int hermes_init(hermes_t *hw);
int hermes_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0,
struct hermes_response *resp);
@@ -430,41 +421,13 @@ static inline int hermes_inquire(hermes_t *hw, u16 rid)
static inline void hermes_read_words(struct hermes *hw, int off, void *buf, unsigned count)
{
off = off << hw->reg_spacing;
-
- if (hw->io_space) {
- insw(hw->iobase + off, buf, count);
- } else {
- unsigned i;
- u16 *p;
-
- /* This needs to *not* byteswap (like insw()) but
- * readw() does byteswap hence the conversion. I hope
- * gcc is smart enough to fold away the two swaps on
- * big-endian platforms. */
- for (i = 0, p = buf; i < count; i++) {
- *p++ = cpu_to_le16(readw(hw->iobase + off));
- }
- }
+ ioread16_rep(hw->iobase + off, buf, count);
}
static inline void hermes_write_words(struct hermes *hw, int off, const void *buf, unsigned count)
{
off = off << hw->reg_spacing;
-
- if (hw->io_space) {
- outsw(hw->iobase + off, buf, count);
- } else {
- unsigned i;
- const u16 *p;
-
- /* This needs to *not* byteswap (like outsw()) but
- * writew() does byteswap hence the conversion. I
- * hope gcc is smart enough to fold away the two swaps
- * on big-endian platforms. */
- for (i = 0, p = buf; i < count; i++) {
- writew(le16_to_cpu(*p++), hw->iobase + off);
- }
- }
+ iowrite16_rep(hw->iobase + off, buf, count);
}
static inline void hermes_clear_words(struct hermes *hw, int off, unsigned count)
@@ -473,13 +436,8 @@ static inline void hermes_clear_words(struct hermes *hw, int off, unsigned count
off = off << hw->reg_spacing;
- if (hw->io_space) {
- for (i = 0; i < count; i++)
- outw(0, hw->iobase + off);
- } else {
- for (i = 0; i < count; i++)
- writew(0, hw->iobase + off);
- }
+ for (i = 0; i < count; i++)
+ iowrite16(0, hw->iobase + off);
}
#define HERMES_READ_RECORD(hw, bap, rid, buf) \
diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c
index 8f746051af82d..a3a32430ae9d7 100644
--- a/drivers/net/wireless/orinoco.c
+++ b/drivers/net/wireless/orinoco.c
@@ -393,6 +393,29 @@
* in the rx_dropped statistics.
* o Provided a module parameter to suppress linkstatus messages.
*
+ * v0.13e -> v0.14alpha1 - 30 Sep 2003 - David Gibson
+ * o Replaced priv->connected logic with netif_carrier_on/off()
+ * calls.
+ * o Remove has_ibss_any and never set the CREATEIBSS RID when
+ * the ESSID is empty. Too many firmwares break if we do.
+ * o 2.6 merges: Replace pdev->slot_name with pci_name(), remove
+ * __devinitdata from PCI ID tables, use free_netdev().
+ * o Enabled shared-key authentication for Agere firmware (from
+ * Robert J. Moore <Robert.J.Moore AT allanbank.com>
+ * o Move netif_wake_queue() (back) to the Tx completion from the
+ * ALLOC event. This seems to prevent/mitigate the rolling
+ * error -110 problems at least on some Intersil firmwares.
+ * Theoretically reduces performance, but I can't measure it.
+ * Patch from Andrew Tridgell <tridge AT samba.org>
+ *
+ * v0.14alpha1 -> v0.14alpha2 - 20 Oct 2003 - David Gibson
+ * o Correctly turn off shared-key authentication when requested
+ * (bugfix from Robert J. Moore).
+ * o Correct airport sleep interfaces for current 2.6 kernels.
+ * o Add code for key change without disabling/enabling the MAC
+ * port. This is supposed to allow 802.1x to work sanely, but
+ * doesn't seem to yet.
+ *
* TODO
* o New wireless extensions API (patch from Moustafa
* Youssef, updated by Jim Carter and Pavel Roskin).
@@ -461,12 +484,14 @@ MODULE_LICENSE("Dual MPL/GPL");
/* Level of debugging. Used in the macros in orinoco.h */
#ifdef ORINOCO_DEBUG
int orinoco_debug = ORINOCO_DEBUG;
-module_param(orinoco_debug, int, 0);
+module_param(orinoco_debug, int, 0644);
+MODULE_PARM_DESC(orinoco_debug, "Debug level");
EXPORT_SYMBOL(orinoco_debug);
#endif
static int suppress_linkstatus; /* = 0 */
-module_param(suppress_linkstatus, bool, 0);
+module_param(suppress_linkstatus, bool, 0644);
+MODULE_PARM_DESC(suppress_linkstatus, "Don't log link status changes");
/********************************************************************/
/* Compile time configuration and compatibility stuff */
@@ -784,7 +809,7 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
return 1;
}
- if (! priv->connected) {
+ if (! netif_carrier_ok(dev)) {
/* Oops, the firmware hasn't established a connection,
silently drop the packet (this seems to be the
safest approach). */
@@ -805,8 +830,9 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
desc.tx_control = cpu_to_le16(HERMES_TXCTRL_TX_OK | HERMES_TXCTRL_TX_EX);
err = hermes_bap_pwrite(hw, USER_BAP, &desc, sizeof(desc), txfid, 0);
if (err) {
- printk(KERN_ERR "%s: Error %d writing Tx descriptor to BAP\n",
- dev->name, err);
+ if (net_ratelimit())
+ printk(KERN_ERR "%s: Error %d writing Tx descriptor "
+ "to BAP\n", dev->name, err);
stats->tx_errors++;
goto fail;
}
@@ -836,8 +862,9 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
err = hermes_bap_pwrite(hw, USER_BAP, &hdr, sizeof(hdr),
txfid, HERMES_802_3_OFFSET);
if (err) {
- printk(KERN_ERR "%s: Error %d writing packet header to BAP\n",
- dev->name, err);
+ if (net_ratelimit())
+ printk(KERN_ERR "%s: Error %d writing packet "
+ "header to BAP\n", dev->name, err);
stats->tx_errors++;
goto fail;
}
@@ -897,8 +924,6 @@ static void __orinoco_ev_alloc(struct net_device *dev, hermes_t *hw)
printk(KERN_WARNING "%s: Allocate event on unexpected fid (%04X)\n",
dev->name, fid);
return;
- } else {
- netif_wake_queue(dev);
}
hermes_write_regn(hw, ALLOCFID, DUMMY_FID);
@@ -911,6 +936,8 @@ static void __orinoco_ev_tx(struct net_device *dev, hermes_t *hw)
stats->tx_packets++;
+ netif_wake_queue(dev);
+
hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID);
}
@@ -937,6 +964,7 @@ static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw)
stats->tx_errors++;
+ netif_wake_queue(dev);
hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID);
}
@@ -962,15 +990,17 @@ static void orinoco_tx_timeout(struct net_device *dev)
/* Does the frame have a SNAP header indicating it should be
* de-encapsulated to Ethernet-II? */
-static inline int is_ethersnap(struct header_struct *hdr)
+static inline int is_ethersnap(void *_hdr)
{
+ u8 *hdr = _hdr;
+
/* We de-encapsulate all packets which, a) have SNAP headers
* (i.e. SSAP=DSAP=0xaa and CTRL=0x3 in the 802.2 LLC header
* and where b) the OUI of the SNAP header is 00:00:00 or
* 00:00:f8 - we need both because different APs appear to use
* different OUIs for some reason */
- return (memcmp(&hdr->dsap, &encaps_hdr, 5) == 0)
- && ( (hdr->oui[2] == 0x00) || (hdr->oui[2] == 0xf8) );
+ return (memcmp(hdr, &encaps_hdr, 5) == 0)
+ && ( (hdr[5] == 0x00) || (hdr[5] == 0xf8) );
}
static inline void orinoco_spy_gather(struct net_device *dev, u_char *mac,
@@ -1269,6 +1299,7 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
case HERMES_INQ_LINKSTATUS: {
struct hermes_linkstatus linkstatus;
u16 newstatus;
+ int connected;
if (len != sizeof(linkstatus)) {
printk(KERN_WARNING "%s: Unexpected size for linkstatus frame (%d bytes)\n",
@@ -1280,15 +1311,14 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
len / 2);
newstatus = le16_to_cpu(linkstatus.linkstatus);
- if ( (newstatus == HERMES_LINKSTATUS_CONNECTED)
- || (newstatus == HERMES_LINKSTATUS_AP_CHANGE)
- || (newstatus == HERMES_LINKSTATUS_AP_IN_RANGE) )
- priv->connected = 1;
- else if ( (newstatus == HERMES_LINKSTATUS_NOT_CONNECTED)
- || (newstatus == HERMES_LINKSTATUS_DISCONNECTED)
- || (newstatus == HERMES_LINKSTATUS_AP_OUT_OF_RANGE)
- || (newstatus == HERMES_LINKSTATUS_ASSOC_FAILED) )
- priv->connected = 0;
+ connected = (newstatus == HERMES_LINKSTATUS_CONNECTED)
+ || (newstatus == HERMES_LINKSTATUS_AP_CHANGE)
+ || (newstatus == HERMES_LINKSTATUS_AP_IN_RANGE);
+
+ if (connected)
+ netif_carrier_on(dev);
+ else
+ netif_carrier_off(dev);
if (newstatus != priv->last_linkstatus)
print_linkstatus(dev, newstatus);
@@ -1297,8 +1327,8 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
}
break;
default:
- printk(KERN_DEBUG "%s: Unknown information frame received "
- "(type %04x).\n", dev->name, type);
+ printk(KERN_DEBUG "%s: Unknown information frame received: "
+ "type 0x%04x, length %d\n", dev->name, type, len);
/* We don't actually do anything about it */
break;
}
@@ -1307,7 +1337,7 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
static void __orinoco_ev_infdrop(struct net_device *dev, hermes_t *hw)
{
if (net_ratelimit())
- printk(KERN_WARNING "%s: Information frame lost.\n", dev->name);
+ printk(KERN_DEBUG "%s: Information frame lost.\n", dev->name);
}
/********************************************************************/
@@ -1366,8 +1396,8 @@ int __orinoco_down(struct net_device *dev)
}
/* firmware will have to reassociate */
+ netif_carrier_off(dev);
priv->last_linkstatus = 0xffff;
- priv->connected = 0;
return 0;
}
@@ -1430,55 +1460,46 @@ static int __orinoco_hw_set_bitrate(struct orinoco_private *priv)
return err;
}
-static int __orinoco_hw_setup_wep(struct orinoco_private *priv)
+/* Change the WEP keys and/or the current keys. Can be called
+ * either from __orinoco_hw_setup_wep() or directly from
+ * orinoco_ioctl_setiwencode(). In the later case the association
+ * with the AP is not broken (if the firmware can handle it),
+ * which is needed for 802.1x implementations. */
+static int __orinoco_hw_setup_wepkeys(struct orinoco_private *priv)
{
hermes_t *hw = &priv->hw;
int err = 0;
- int master_wep_flag;
- int auth_flag;
switch (priv->firmware_type) {
- case FIRMWARE_TYPE_AGERE: /* Agere style WEP */
- if (priv->wep_on) {
- err = hermes_write_wordrec(hw, USER_BAP,
- HERMES_RID_CNFTXKEY_AGERE,
- priv->tx_key);
- if (err)
- return err;
-
- err = HERMES_WRITE_RECORD(hw, USER_BAP,
- HERMES_RID_CNFWEPKEYS_AGERE,
- &priv->keys);
- if (err)
- return err;
- }
+ case FIRMWARE_TYPE_AGERE:
+ err = HERMES_WRITE_RECORD(hw, USER_BAP,
+ HERMES_RID_CNFWEPKEYS_AGERE,
+ &priv->keys);
+ if (err)
+ return err;
err = hermes_write_wordrec(hw, USER_BAP,
- HERMES_RID_CNFWEPENABLED_AGERE,
- priv->wep_on);
+ HERMES_RID_CNFTXKEY_AGERE,
+ priv->tx_key);
if (err)
return err;
break;
-
- case FIRMWARE_TYPE_INTERSIL: /* Intersil style WEP */
- case FIRMWARE_TYPE_SYMBOL: /* Symbol style WEP */
- master_wep_flag = 0; /* Off */
- if (priv->wep_on) {
+ case FIRMWARE_TYPE_INTERSIL:
+ case FIRMWARE_TYPE_SYMBOL:
+ {
int keylen;
int i;
- /* Fudge around firmware weirdness */
+ /* Force uniform key length to work around firmware bugs */
keylen = le16_to_cpu(priv->keys[priv->tx_key].len);
+ if (keylen > LARGE_KEY_SIZE) {
+ printk(KERN_ERR "%s: BUG: Key %d has oversize length %d.\n",
+ priv->ndev->name, priv->tx_key, keylen);
+ return -E2BIG;
+ }
+
/* Write all 4 keys */
for(i = 0; i < ORINOCO_MAX_KEYS; i++) {
-/* int keylen = le16_to_cpu(priv->keys[i].len); */
-
- if (keylen > LARGE_KEY_SIZE) {
- printk(KERN_ERR "%s: BUG: Key %d has oversize length %d.\n",
- priv->ndev->name, i, keylen);
- return -E2BIG;
- }
-
err = hermes_write_ltv(hw, USER_BAP,
HERMES_RID_CNFDEFAULTKEY0 + i,
HERMES_BYTES_TO_RECLEN(keylen),
@@ -1493,27 +1514,63 @@ static int __orinoco_hw_setup_wep(struct orinoco_private *priv)
priv->tx_key);
if (err)
return err;
-
- if (priv->wep_restrict) {
- auth_flag = 2;
- master_wep_flag = 3;
- } else {
- /* Authentication is where Intersil and Symbol
- * firmware differ... */
- auth_flag = 1;
- if (priv->firmware_type == FIRMWARE_TYPE_SYMBOL)
- master_wep_flag = 3; /* Symbol */
- else
- master_wep_flag = 1; /* Intersil */
- }
+ }
+ break;
+ }
+ return 0;
+}
+
+static int __orinoco_hw_setup_wep(struct orinoco_private *priv)
+{
+ hermes_t *hw = &priv->hw;
+ int err = 0;
+ int master_wep_flag;
+ int auth_flag;
+
+ if (priv->wep_on)
+ __orinoco_hw_setup_wepkeys(priv);
+
+ if (priv->wep_restrict)
+ auth_flag = HERMES_AUTH_SHARED_KEY;
+ else
+ auth_flag = HERMES_AUTH_OPEN;
+
+ switch (priv->firmware_type) {
+ case FIRMWARE_TYPE_AGERE: /* Agere style WEP */
+ if (priv->wep_on) {
+ /* Enable the shared-key authentication. */
+ err = hermes_write_wordrec(hw, USER_BAP,
+ HERMES_RID_CNFAUTHENTICATION_AGERE,
+ auth_flag);
+ }
+ err = hermes_write_wordrec(hw, USER_BAP,
+ HERMES_RID_CNFWEPENABLED_AGERE,
+ priv->wep_on);
+ if (err)
+ return err;
+ break;
+
+ case FIRMWARE_TYPE_INTERSIL: /* Intersil style WEP */
+ case FIRMWARE_TYPE_SYMBOL: /* Symbol style WEP */
+ if (priv->wep_on) {
+ if (priv->wep_restrict ||
+ (priv->firmware_type == FIRMWARE_TYPE_SYMBOL))
+ master_wep_flag = HERMES_WEP_PRIVACY_INVOKED |
+ HERMES_WEP_EXCL_UNENCRYPTED;
+ else
+ master_wep_flag = HERMES_WEP_PRIVACY_INVOKED;
err = hermes_write_wordrec(hw, USER_BAP,
HERMES_RID_CNFAUTHENTICATION,
auth_flag);
if (err)
return err;
- }
+ } else
+ master_wep_flag = 0;
+
+ if (priv->iw_mode == IW_MODE_MONITOR)
+ master_wep_flag |= HERMES_WEP_HOST_DECRYPT;
/* Master WEP setting : on/off */
err = hermes_write_wordrec(hw, USER_BAP,
@@ -1523,13 +1580,6 @@ static int __orinoco_hw_setup_wep(struct orinoco_private *priv)
return err;
break;
-
- default:
- if (priv->wep_on) {
- printk(KERN_ERR "%s: WEP enabled, although not supported!\n",
- priv->ndev->name);
- return -EINVAL;
- }
}
return 0;
@@ -1574,21 +1624,26 @@ static int __orinoco_program_rids(struct net_device *dev)
}
if (priv->has_ibss) {
- err = hermes_write_wordrec(hw, USER_BAP,
- HERMES_RID_CNFCREATEIBSS,
- priv->createibss);
- if (err) {
- printk(KERN_ERR "%s: Error %d setting CREATEIBSS\n", dev->name, err);
- return err;
- }
+ u16 createibss;
- if ((strlen(priv->desired_essid) == 0) && (priv->createibss)
- && (!priv->has_ibss_any)) {
+ if ((strlen(priv->desired_essid) == 0) && (priv->createibss)) {
printk(KERN_WARNING "%s: This firmware requires an "
"ESSID in IBSS-Ad-Hoc mode.\n", dev->name);
/* With wvlan_cs, in this case, we would crash.
* hopefully, this driver will behave better...
* Jean II */
+ createibss = 0;
+ } else {
+ createibss = priv->createibss;
+ }
+
+ err = hermes_write_wordrec(hw, USER_BAP,
+ HERMES_RID_CNFCREATEIBSS,
+ createibss);
+ if (err) {
+ printk(KERN_ERR "%s: Error %d setting CREATEIBSS\n",
+ dev->name, err);
+ return err;
}
}
@@ -1785,7 +1840,8 @@ __orinoco_set_multicast_list(struct net_device *dev)
}
if (p)
- printk(KERN_WARNING "Multicast list is longer than mc_count\n");
+ printk(KERN_WARNING "%s: Multicast list is "
+ "longer than mc_count\n", dev->name);
err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFGROUPADDRESSES,
HERMES_BYTES_TO_RECLEN(priv->mc_count * ETH_ALEN),
@@ -1878,7 +1934,7 @@ static void orinoco_reset(struct net_device *dev)
priv->hw_unavailable++;
priv->last_linkstatus = 0xffff; /* firmware will have to reassociate */
- priv->connected = 0;
+ netif_carrier_off(dev);
orinoco_unlock(priv, &flags);
@@ -2014,51 +2070,81 @@ irqreturn_t orinoco_interrupt(int irq, void *dev_id, struct pt_regs *regs)
/* Initialization */
/********************************************************************/
-struct sta_id {
+struct comp_id {
u16 id, variant, major, minor;
} __attribute__ ((packed));
-static int determine_firmware_type(struct net_device *dev, struct sta_id *sta_id)
+static inline fwtype_t determine_firmware_type(struct comp_id *nic_id)
{
- /* FIXME: this is fundamentally broken */
- unsigned int firmver = ((u32)sta_id->major << 16) | sta_id->minor;
-
- if (sta_id->variant == 1)
+ if (nic_id->id < 0x8000)
return FIRMWARE_TYPE_AGERE;
- else if ((sta_id->variant == 2) &&
- ((firmver == 0x10001) || (firmver == 0x20001)))
+ else if (nic_id->id == 0x8000 && nic_id->major == 0)
return FIRMWARE_TYPE_SYMBOL;
else
return FIRMWARE_TYPE_INTERSIL;
}
-static void determine_firmware(struct net_device *dev)
+/* Set priv->firmware type, determine firmware properties */
+static int determine_firmware(struct net_device *dev)
{
struct orinoco_private *priv = netdev_priv(dev);
hermes_t *hw = &priv->hw;
int err;
- struct sta_id sta_id;
+ struct comp_id nic_id, sta_id;
unsigned int firmver;
char tmp[SYMBOL_MAX_VER_LEN+1];
+ /* Get the hardware version */
+ err = HERMES_READ_RECORD(hw, USER_BAP, HERMES_RID_NICID, &nic_id);
+ if (err) {
+ printk(KERN_ERR "%s: Cannot read hardware identity: error %d\n",
+ dev->name, err);
+ return err;
+ }
+
+ le16_to_cpus(&nic_id.id);
+ le16_to_cpus(&nic_id.variant);
+ le16_to_cpus(&nic_id.major);
+ le16_to_cpus(&nic_id.minor);
+ printk(KERN_DEBUG "%s: Hardware identity %04x:%04x:%04x:%04x\n",
+ dev->name, nic_id.id, nic_id.variant,
+ nic_id.major, nic_id.minor);
+
+ priv->firmware_type = determine_firmware_type(&nic_id);
+
/* Get the firmware version */
err = HERMES_READ_RECORD(hw, USER_BAP, HERMES_RID_STAID, &sta_id);
if (err) {
- printk(KERN_WARNING "%s: Error %d reading firmware info. Wildly guessing capabilities...\n",
+ printk(KERN_ERR "%s: Cannot read station identity: error %d\n",
dev->name, err);
- memset(&sta_id, 0, sizeof(sta_id));
+ return err;
}
le16_to_cpus(&sta_id.id);
le16_to_cpus(&sta_id.variant);
le16_to_cpus(&sta_id.major);
le16_to_cpus(&sta_id.minor);
- printk(KERN_DEBUG "%s: Station identity %04x:%04x:%04x:%04x\n",
+ printk(KERN_DEBUG "%s: Station identity %04x:%04x:%04x:%04x\n",
dev->name, sta_id.id, sta_id.variant,
sta_id.major, sta_id.minor);
- if (! priv->firmware_type)
- priv->firmware_type = determine_firmware_type(dev, &sta_id);
+ switch (sta_id.id) {
+ case 0x15:
+ printk(KERN_ERR "%s: Primary firmware is active\n",
+ dev->name);
+ return -ENODEV;
+ case 0x14b:
+ printk(KERN_ERR "%s: Tertiary firmware is active\n",
+ dev->name);
+ return -ENODEV;
+ case 0x1f: /* Intersil, Agere, Symbol Spectrum24 */
+ case 0x21: /* Symbol Spectrum24 Trilogy */
+ break;
+ default:
+ printk(KERN_NOTICE "%s: Unknown station ID, please report\n",
+ dev->name);
+ break;
+ }
/* Default capabilities */
priv->has_sensitivity = 1;
@@ -2066,7 +2152,6 @@ static void determine_firmware(struct net_device *dev)
priv->has_preamble = 0;
priv->has_port3 = 1;
priv->has_ibss = 1;
- priv->has_ibss_any = 0;
priv->has_wep = 0;
priv->has_big_wep = 0;
@@ -2075,14 +2160,12 @@ static void determine_firmware(struct net_device *dev)
case FIRMWARE_TYPE_AGERE:
/* Lucent Wavelan IEEE, Lucent Orinoco, Cabletron RoamAbout,
ELSA, Melco, HP, IBM, Dell 1150, Compaq 110/210 */
- printk(KERN_DEBUG "%s: Looks like a Lucent/Agere firmware "
- "version %d.%02d\n", dev->name,
- sta_id.major, sta_id.minor);
+ snprintf(priv->fw_name, sizeof(priv->fw_name) - 1,
+ "Lucent/Agere %d.%02d", sta_id.major, sta_id.minor);
firmver = ((unsigned long)sta_id.major << 16) | sta_id.minor;
priv->has_ibss = (firmver >= 0x60006);
- priv->has_ibss_any = (firmver >= 0x60010);
priv->has_wep = (firmver >= 0x40020);
priv->has_big_wep = 1; /* FIXME: this is wrong - how do we tell
Gold cards from the others? */
@@ -2121,14 +2204,15 @@ static void determine_firmware(struct net_device *dev)
tmp[SYMBOL_MAX_VER_LEN] = '\0';
}
- printk(KERN_DEBUG "%s: Looks like a Symbol firmware "
- "version [%s] (parsing to %X)\n", dev->name,
- tmp, firmver);
+ snprintf(priv->fw_name, sizeof(priv->fw_name) - 1,
+ "Symbol %s", tmp);
priv->has_ibss = (firmver >= 0x20000);
priv->has_wep = (firmver >= 0x15012);
priv->has_big_wep = (firmver >= 0x20000);
- priv->has_pm = (firmver >= 0x20000) && (firmver < 0x22000);
+ priv->has_pm = (firmver >= 0x20000 && firmver < 0x22000) ||
+ (firmver >= 0x29000 && firmver < 0x30000) ||
+ firmver >= 0x31000;
priv->has_preamble = (firmver >= 0x20000);
priv->ibss_port = 4;
/* Tested with Intel firmware : 0x20015 => Jean II */
@@ -2140,9 +2224,9 @@ static void determine_firmware(struct net_device *dev)
* different and less well tested */
/* D-Link MAC : 00:40:05:* */
/* Addtron MAC : 00:90:D1:* */
- printk(KERN_DEBUG "%s: Looks like an Intersil firmware "
- "version %d.%d.%d\n", dev->name,
- sta_id.major, sta_id.minor, sta_id.variant);
+ snprintf(priv->fw_name, sizeof(priv->fw_name) - 1,
+ "Intersil %d.%d.%d", sta_id.major, sta_id.minor,
+ sta_id.variant);
firmver = ((unsigned long)sta_id.major << 16) |
((unsigned long)sta_id.minor << 8) | sta_id.variant;
@@ -2160,9 +2244,11 @@ static void determine_firmware(struct net_device *dev)
priv->ibss_port = 1;
}
break;
- default:
- break;
}
+ printk(KERN_DEBUG "%s: Firmware determined as %s\n", dev->name,
+ priv->fw_name);
+
+ return 0;
}
static int orinoco_init(struct net_device *dev)
@@ -2188,7 +2274,12 @@ static int orinoco_init(struct net_device *dev)
goto out;
}
- determine_firmware(dev);
+ err = determine_firmware(dev);
+ if (err != 0) {
+ printk(KERN_ERR "%s: Incompatible firmware, aborting\n",
+ dev->name);
+ goto out;
+ }
if (priv->has_port3)
printk(KERN_DEBUG "%s: Ad-hoc demo mode supported\n", dev->name);
@@ -2388,13 +2479,18 @@ struct net_device *alloc_orinocodev(int sizeof_card,
* hardware */
INIT_WORK(&priv->reset_work, (void (*)(void *))orinoco_reset, dev);
+ netif_carrier_off(dev);
priv->last_linkstatus = 0xffff;
- priv->connected = 0;
return dev;
}
+void free_orinocodev(struct net_device *dev)
+{
+ free_netdev(dev);
+}
+
/********************************************************************/
/* Wireless extensions */
/********************************************************************/
@@ -2553,9 +2649,8 @@ static int orinoco_ioctl_getiwrange(struct net_device *dev, struct iw_point *rrq
TRACE_ENTER(dev->name);
- err = verify_area(VERIFY_WRITE, rrq->pointer, sizeof(range));
- if (err)
- return err;
+ if (!access_ok(VERIFY_WRITE, rrq->pointer, sizeof(range)))
+ return -EFAULT;
rrq->length = sizeof(range);
@@ -2686,11 +2781,17 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev, struct iw_point *er
int err = 0;
char keybuf[ORINOCO_MAX_KEY_SIZE];
unsigned long flags;
-
+
+ if (! priv->has_wep)
+ return -EOPNOTSUPP;
+
if (erq->pointer) {
- /* We actually have a key to set */
- if ( (erq->length < SMALL_KEY_SIZE) || (erq->length > ORINOCO_MAX_KEY_SIZE) )
- return -EINVAL;
+ /* We actually have a key to set - check its length */
+ if (erq->length > LARGE_KEY_SIZE)
+ return -E2BIG;
+
+ if ( (erq->length > SMALL_KEY_SIZE) && !priv->has_big_wep )
+ return -E2BIG;
if (copy_from_user(keybuf, erq->pointer, erq->length))
return -EFAULT;
@@ -2698,19 +2799,8 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev, struct iw_point *er
if (orinoco_lock(priv, &flags) != 0)
return -EBUSY;
-
+
if (erq->pointer) {
- if (erq->length > ORINOCO_MAX_KEY_SIZE) {
- err = -E2BIG;
- goto out;
- }
-
- if ( (erq->length > LARGE_KEY_SIZE)
- || ( ! priv->has_big_wep && (erq->length > SMALL_KEY_SIZE)) ) {
- err = -EINVAL;
- goto out;
- }
-
if ((index < 0) || (index >= ORINOCO_MAX_KEYS))
index = priv->tx_key;
@@ -2721,7 +2811,7 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev, struct iw_point *er
xlen = SMALL_KEY_SIZE;
} else
xlen = 0;
-
+
/* Switch on WEP if off */
if ((!enable) && (xlen > 0)) {
setindex = index;
@@ -2745,10 +2835,9 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev, struct iw_point *er
setindex = index;
}
}
-
+
if (erq->flags & IW_ENCODE_DISABLED)
enable = 0;
- /* Only for Prism2 & Symbol cards (so far) - Jean II */
if (erq->flags & IW_ENCODE_OPEN)
restricted = 0;
if (erq->flags & IW_ENCODE_RESTRICTED)
@@ -2761,6 +2850,15 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev, struct iw_point *er
memcpy(priv->keys[index].data, keybuf, erq->length);
}
priv->tx_key = setindex;
+
+ /* Try fast key change if connected and only keys are changed */
+ if (priv->wep_on && enable && (priv->wep_restrict == restricted) &&
+ netif_carrier_ok(dev)) {
+ err = __orinoco_hw_setup_wepkeys(priv);
+ /* No need to commit if successful */
+ goto out;
+ }
+
priv->wep_on = enable;
priv->wep_restrict = restricted;
@@ -2778,6 +2876,9 @@ static int orinoco_ioctl_getiwencode(struct net_device *dev, struct iw_point *er
char keybuf[ORINOCO_MAX_KEY_SIZE];
unsigned long flags;
+ if (! priv->has_wep)
+ return -EOPNOTSUPP;
+
if (orinoco_lock(priv, &flags) != 0)
return -EBUSY;
@@ -2788,23 +2889,18 @@ static int orinoco_ioctl_getiwencode(struct net_device *dev, struct iw_point *er
if (! priv->wep_on)
erq->flags |= IW_ENCODE_DISABLED;
erq->flags |= index + 1;
-
- /* Only for symbol cards - Jean II */
- if (priv->firmware_type != FIRMWARE_TYPE_AGERE) {
- if(priv->wep_restrict)
- erq->flags |= IW_ENCODE_RESTRICTED;
- else
- erq->flags |= IW_ENCODE_OPEN;
- }
+
+ if (priv->wep_restrict)
+ erq->flags |= IW_ENCODE_RESTRICTED;
+ else
+ erq->flags |= IW_ENCODE_OPEN;
xlen = le16_to_cpu(priv->keys[index].len);
erq->length = xlen;
- if (erq->pointer) {
- memcpy(keybuf, priv->keys[index].data, ORINOCO_MAX_KEY_SIZE);
- }
-
+ memcpy(keybuf, priv->keys[index].data, ORINOCO_MAX_KEY_SIZE);
+
orinoco_unlock(priv, &flags);
if (erq->pointer) {
@@ -3045,8 +3141,9 @@ static int orinoco_ioctl_setfrag(struct net_device *dev, struct iw_param *frq)
priv->mwo_robust = 0;
else {
if (frq->fixed)
- printk(KERN_WARNING "%s: Fixed fragmentation not \
-supported on this firmware. Using MWO robust instead.\n", dev->name);
+ printk(KERN_WARNING "%s: Fixed fragmentation is "
+ "not supported on this firmware. "
+ "Using MWO robust instead.\n", dev->name);
priv->mwo_robust = 1;
}
} else {
@@ -3518,7 +3615,7 @@ static int orinoco_ioctl_getspy(struct net_device *dev, struct iw_point *srq)
}
/* Copy stats */
/* In theory, we should disable irqs while copying the stats
- * because the rx path migh update it in the middle...
+ * because the rx path might update it in the middle...
* Bah, who care ? - Jean II */
memcpy(&spy_stat, priv->spy_stat,
sizeof(struct iw_quality) * IW_MAX_SPY);
@@ -3609,22 +3706,12 @@ orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
break;
case SIOCSIWENCODE:
- if (! priv->has_wep) {
- err = -EOPNOTSUPP;
- break;
- }
-
err = orinoco_ioctl_setiwencode(dev, &wrq->u.encoding);
if (! err)
changed = 1;
break;
case SIOCGIWENCODE:
- if (! priv->has_wep) {
- err = -EOPNOTSUPP;
- break;
- }
-
if (! capable(CAP_NET_ADMIN)) {
err = -EPERM;
break;
@@ -4127,6 +4214,7 @@ static void show_rx_frame(struct orinoco_rxframe_hdr *frame)
/********************************************************************/
EXPORT_SYMBOL(alloc_orinocodev);
+EXPORT_SYMBOL(free_orinocodev);
EXPORT_SYMBOL(__orinoco_up);
EXPORT_SYMBOL(__orinoco_down);
diff --git a/drivers/net/wireless/orinoco.h b/drivers/net/wireless/orinoco.h
index c2f5f78f512f8..13e42c2afb272 100644
--- a/drivers/net/wireless/orinoco.h
+++ b/drivers/net/wireless/orinoco.h
@@ -7,7 +7,7 @@
#ifndef _ORINOCO_H
#define _ORINOCO_H
-#define DRIVER_VERSION "0.13e"
+#define DRIVER_VERSION "0.14alpha2"
#include <linux/types.h>
#include <linux/spinlock.h>
@@ -30,6 +30,12 @@ struct orinoco_key {
char data[ORINOCO_MAX_KEY_SIZE];
} __attribute__ ((packed));
+typedef enum {
+ FIRMWARE_TYPE_AGERE,
+ FIRMWARE_TYPE_INTERSIL,
+ FIRMWARE_TYPE_SYMBOL
+} fwtype_t;
+
struct orinoco_private {
void *card; /* Pointer to card dependent structure */
int (*hard_reset)(struct orinoco_private *);
@@ -42,7 +48,6 @@ struct orinoco_private {
/* driver state */
int open;
u16 last_linkstatus;
- int connected;
/* Net device stuff */
struct net_device *ndev;
@@ -54,19 +59,22 @@ struct orinoco_private {
u16 txfid;
/* Capabilities of the hardware/firmware */
- int firmware_type;
-#define FIRMWARE_TYPE_AGERE 1
-#define FIRMWARE_TYPE_INTERSIL 2
-#define FIRMWARE_TYPE_SYMBOL 3
- int has_ibss, has_port3, has_ibss_any, ibss_port;
- int has_wep, has_big_wep;
- int has_mwo;
- int has_pm;
- int has_preamble;
- int has_sensitivity;
+ fwtype_t firmware_type;
+ char fw_name[32];
+ int ibss_port;
int nicbuf_size;
u16 channel_mask;
- int broken_disableport;
+
+ /* Boolean capabilities */
+ unsigned int has_ibss:1;
+ unsigned int has_port3:1;
+ unsigned int has_wep:1;
+ unsigned int has_big_wep:1;
+ unsigned int has_mwo:1;
+ unsigned int has_pm:1;
+ unsigned int has_preamble:1;
+ unsigned int has_sensitivity:1;
+ unsigned int broken_disableport:1;
/* Configuration paramaters */
u32 iw_mode;
@@ -108,6 +116,7 @@ extern int orinoco_debug;
extern struct net_device *alloc_orinocodev(int sizeof_card,
int (*hard_reset)(struct orinoco_private *));
+extern void free_orinocodev(struct net_device *dev);
extern int __orinoco_up(struct net_device *dev);
extern int __orinoco_down(struct net_device *dev);
extern int orinoco_stop(struct net_device *dev);
@@ -127,7 +136,7 @@ extern inline int orinoco_lock(struct orinoco_private *priv,
{
spin_lock_irqsave(&priv->lock, *flags);
if (priv->hw_unavailable) {
- printk(KERN_DEBUG "orinoco_lock() called with hw_unavailable (dev=%p)\n",
+ DEBUG(1, "orinoco_lock() called with hw_unavailable (dev=%p)\n",
priv->ndev);
spin_unlock_irqrestore(&priv->lock, *flags);
return -EBUSY;
diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c
index 34bacd7505a92..74a8227256aa3 100644
--- a/drivers/net/wireless/orinoco_cs.c
+++ b/drivers/net/wireless/orinoco_cs.c
@@ -57,8 +57,8 @@ MODULE_LICENSE("Dual MPL/GPL");
/* Some D-Link cards have buggy CIS. They do work at 5v properly, but
* don't have any CIS entry for it. This workaround it... */
static int ignore_cis_vcc; /* = 0 */
-
module_param(ignore_cis_vcc, int, 0);
+MODULE_PARM_DESC(ignore_cis_vcc, "Allow voltage mismatch between card and socket");
/********************************************************************/
/* Magic constants */
@@ -128,6 +128,7 @@ orinoco_cs_hard_reset(struct orinoco_private *priv)
if (err)
return err;
+ msleep(100);
clear_bit(0, &card->hard_reset_in_progress);
return 0;
@@ -166,9 +167,10 @@ orinoco_cs_attach(void)
link->priv = dev;
/* Interrupt setup */
- link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
+ link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
link->irq.IRQInfo1 = IRQ_LEVEL_ID;
- link->irq.Handler = NULL;
+ link->irq.Handler = orinoco_interrupt;
+ link->irq.Instance = dev;
/* General socket configuration defaults can go here. In this
* client, we assume very little, and rely on the CIS for
@@ -235,7 +237,7 @@ static void orinoco_cs_detach(dev_link_t *link)
dev);
unregister_netdev(dev);
}
- free_netdev(dev);
+ free_orinocodev(dev);
} /* orinoco_cs_detach */
/*
@@ -262,6 +264,7 @@ orinoco_cs_config(dev_link_t *link)
cisinfo_t info;
tuple_t tuple;
cisparse_t parse;
+ void __iomem *mem;
CS_CHECK(ValidateCIS, pcmcia_validate_cis(handle, &info));
@@ -308,8 +311,8 @@ orinoco_cs_config(dev_link_t *link)
cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
cistpl_cftable_entry_t dflt = { .index = 0 };
- if (pcmcia_get_tuple_data(handle, &tuple) != 0 ||
- pcmcia_parse_tuple(handle, &tuple, &parse) != 0)
+ if ( (pcmcia_get_tuple_data(handle, &tuple) != 0)
+ || (pcmcia_parse_tuple(handle, &tuple, &parse) != 0))
goto next_entry;
if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
@@ -348,8 +351,7 @@ orinoco_cs_config(dev_link_t *link)
dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
/* Do we need to allocate an interrupt? */
- if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1)
- link->conf.Attributes |= CONF_ENABLE_IRQ;
+ link->conf.Attributes |= CONF_ENABLE_IRQ;
/* IO window settings */
link->io.NumPorts1 = link->io.NumPorts2 = 0;
@@ -390,7 +392,7 @@ orinoco_cs_config(dev_link_t *link)
last_ret = pcmcia_get_next_tuple(handle, &tuple);
if (last_ret == CS_NO_MORE_ITEMS) {
printk(KERN_ERR PFX "GetNextTuple(): No matching "
- "CIS configuration, maybe you need the "
+ "CIS configuration. Maybe you need the "
"ignore_cis_vcc=1 parameter.\n");
goto cs_failed;
}
@@ -401,20 +403,16 @@ orinoco_cs_config(dev_link_t *link)
* a handler to the interrupt, unless the 'Handler' member of
* the irq structure is initialized.
*/
- if (link->conf.Attributes & CONF_ENABLE_IRQ) {
- link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
- link->irq.IRQInfo1 = IRQ_LEVEL_ID;
- link->irq.Handler = orinoco_interrupt;
- link->irq.Instance = dev;
-
- CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
- }
+ CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
/* We initialize the hermes structure before completing PCMCIA
* configuration just in case the interrupt handler gets
* called. */
- hermes_struct_init(hw, link->io.BasePort1,
- HERMES_IO, HERMES_16BIT_REGSPACING);
+ mem = ioport_map(link->io.BasePort1, link->io.NumPorts1);
+ if (!mem)
+ goto cs_failed;
+
+ hermes_struct_init(hw, mem, HERMES_16BIT_REGSPACING);
/*
* This actually configures the PCMCIA socket -- setting up
@@ -430,8 +428,6 @@ orinoco_cs_config(dev_link_t *link)
SET_MODULE_OWNER(dev);
card->node.major = card->node.minor = 0;
- /* register_netdev will give us an ethX name */
- dev->name[0] = '\0';
SET_NETDEV_DEV(dev, &handle_to_dev(handle));
/* Tell the stack we exist */
if (register_netdev(dev) != 0) {
@@ -454,8 +450,7 @@ orinoco_cs_config(dev_link_t *link)
if (link->conf.Vpp1)
printk(", Vpp %d.%d", link->conf.Vpp1 / 10,
link->conf.Vpp1 % 10);
- if (link->conf.Attributes & CONF_ENABLE_IRQ)
- printk(", irq %d", link->irq.AssignedIRQ);
+ printk(", irq %d", link->irq.AssignedIRQ);
if (link->io.NumPorts1)
printk(", io 0x%04x-0x%04x", link->io.BasePort1,
link->io.BasePort1 + link->io.NumPorts1 - 1);
@@ -498,6 +493,8 @@ orinoco_cs_release(dev_link_t *link)
if (link->irq.AssignedIRQ)
pcmcia_release_irq(link->handle, &link->irq);
link->state &= ~DEV_CONFIG;
+ if (priv->hw.iobase)
+ ioport_unmap(priv->hw.iobase);
} /* orinoco_cs_release */
/*
@@ -519,12 +516,12 @@ orinoco_cs_event(event_t event, int priority,
case CS_EVENT_CARD_REMOVAL:
link->state &= ~DEV_PRESENT;
if (link->state & DEV_CONFIG) {
- orinoco_lock(priv, &flags);
+ unsigned long flags;
+ spin_lock_irqsave(&priv->lock, flags);
netif_device_detach(dev);
priv->hw_unavailable++;
-
- orinoco_unlock(priv, &flags);
+ spin_unlock_irqrestore(&priv->lock, flags);
}
break;
diff --git a/drivers/net/wireless/orinoco_pci.c b/drivers/net/wireless/orinoco_pci.c
index 3e58b75837097..ff30d37e12e20 100644
--- a/drivers/net/wireless/orinoco_pci.c
+++ b/drivers/net/wireless/orinoco_pci.c
@@ -129,6 +129,11 @@
#define HERMES_PCI_COR_OFFT (500) /* ms */
#define HERMES_PCI_COR_BUSYT (500) /* ms */
+/* Orinoco PCI specific data */
+struct orinoco_pci_card {
+ void __iomem *pci_ioaddr;
+};
+
/*
* Do a soft reset of the PCI card using the Configuration Option Register
* We need this to get going...
@@ -151,25 +156,11 @@ orinoco_pci_cor_reset(struct orinoco_private *priv)
/* Assert the reset until the card notice */
hermes_write_regn(hw, PCI_COR, HERMES_PCI_COR_MASK);
- printk(KERN_NOTICE "Reset done");
- timeout = jiffies + (HERMES_PCI_COR_ONT * HZ / 1000);
- while(time_before(jiffies, timeout)) {
- printk(".");
- mdelay(1);
- }
- printk(";\n");
- //mdelay(HERMES_PCI_COR_ONT);
+ mdelay(HERMES_PCI_COR_ONT);
/* Give time for the card to recover from this hard effort */
hermes_write_regn(hw, PCI_COR, 0x0000);
- printk(KERN_NOTICE "Clear Reset");
- timeout = jiffies + (HERMES_PCI_COR_OFFT * HZ / 1000);
- while(time_before(jiffies, timeout)) {
- printk(".");
- mdelay(1);
- }
- printk(";\n");
- //mdelay(HERMES_PCI_COR_OFFT);
+ mdelay(HERMES_PCI_COR_OFFT);
/* The card is ready when it's no longer busy */
timeout = jiffies + (HERMES_PCI_COR_BUSYT * HZ / 1000);
@@ -178,12 +169,12 @@ orinoco_pci_cor_reset(struct orinoco_private *priv)
mdelay(1);
reg = hermes_read_regn(hw, CMD);
}
- /* Did we timeout ? */
- if(time_after_eq(jiffies, timeout)) {
+
+ /* Still busy? */
+ if (reg & HERMES_CMD_BUSY) {
printk(KERN_ERR PFX "Busy timeout\n");
return -ETIMEDOUT;
}
- printk(KERN_NOTICE "pci_cor : reg = 0x%X - %lX - %lX\n", reg, timeout, jiffies);
return 0;
}
@@ -196,84 +187,93 @@ static int orinoco_pci_init_one(struct pci_dev *pdev,
{
int err = 0;
unsigned long pci_iorange;
- u16 *pci_ioaddr = NULL;
+ u16 __iomem *pci_ioaddr = NULL;
unsigned long pci_iolen;
struct orinoco_private *priv = NULL;
+ struct orinoco_pci_card *card;
struct net_device *dev = NULL;
err = pci_enable_device(pdev);
- if (err)
- return -EIO;
+ if (err) {
+ printk(KERN_ERR PFX "Cannot enable PCI device\n");
+ return err;
+ }
+
+ err = pci_request_regions(pdev, DRIVER_NAME);
+ if (err != 0) {
+ printk(KERN_ERR PFX "Cannot obtain PCI resources\n");
+ goto fail_resources;
+ }
/* Resource 0 is mapped to the hermes registers */
pci_iorange = pci_resource_start(pdev, 0);
pci_iolen = pci_resource_len(pdev, 0);
pci_ioaddr = ioremap(pci_iorange, pci_iolen);
- if (! pci_iorange)
- goto fail;
+ if (!pci_iorange) {
+ printk(KERN_ERR PFX "Cannot remap hardware registers\n");
+ goto fail_map;
+ }
/* Allocate network device */
- dev = alloc_orinocodev(0, NULL);
+ dev = alloc_orinocodev(sizeof(*card), orinoco_pci_cor_reset);
if (! dev) {
err = -ENOMEM;
- goto fail;
+ goto fail_alloc;
}
priv = netdev_priv(dev);
- dev->base_addr = (unsigned long) pci_ioaddr;
+ card = priv->card;
+ card->pci_ioaddr = pci_ioaddr;
dev->mem_start = pci_iorange;
dev->mem_end = pci_iorange + pci_iolen - 1;
SET_MODULE_OWNER(dev);
SET_NETDEV_DEV(dev, &pdev->dev);
- printk(KERN_DEBUG PFX
- "Detected Orinoco/Prism2 PCI device at %s, mem:0x%lX to 0x%lX -> 0x%p, irq:%d\n",
- pci_name(pdev), dev->mem_start, dev->mem_end, pci_ioaddr, pdev->irq);
+ hermes_struct_init(&priv->hw, pci_ioaddr, HERMES_32BIT_REGSPACING);
- hermes_struct_init(&priv->hw, dev->base_addr,
- HERMES_MEM, HERMES_32BIT_REGSPACING);
- pci_set_drvdata(pdev, dev);
+ printk(KERN_DEBUG PFX "Detected device %s, mem:0x%lx-0x%lx, irq %d\n",
+ pci_name(pdev), dev->mem_start, dev->mem_end, pdev->irq);
err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ,
dev->name, dev);
if (err) {
- printk(KERN_ERR PFX "Error allocating IRQ %d.\n",
- pdev->irq);
+ printk(KERN_ERR PFX "Cannot allocate IRQ %d\n", pdev->irq);
err = -EBUSY;
- goto fail;
+ goto fail_irq;
}
dev->irq = pdev->irq;
/* Perform a COR reset to start the card */
- if(orinoco_pci_cor_reset(priv) != 0) {
- printk(KERN_ERR "%s: Failed to start the card\n", dev->name);
- err = -ETIMEDOUT;
+ err = orinoco_pci_cor_reset(priv);
+ if (err) {
+ printk(KERN_ERR PFX "Initial reset failed\n");
goto fail;
}
- /* Override the normal firmware detection - the Prism 2.5 PCI
- * cards look like Lucent firmware but are actually Intersil */
- priv->firmware_type = FIRMWARE_TYPE_INTERSIL;
-
err = register_netdev(dev);
if (err) {
- printk(KERN_ERR "%s: Failed to register net device\n", dev->name);
+ printk(KERN_ERR PFX "Failed to register net device\n");
goto fail;
}
+ pci_set_drvdata(pdev, dev);
+
return 0;
fail:
- if (dev) {
- if (dev->irq)
- free_irq(dev->irq, dev);
+ free_irq(pdev->irq, dev);
- free_netdev(dev);
- }
+ fail_irq:
+ pci_set_drvdata(pdev, NULL);
+ free_orinocodev(dev);
- if (pci_ioaddr)
- iounmap(pci_ioaddr);
+ fail_alloc:
+ iounmap(pci_ioaddr);
+ fail_map:
+ pci_release_regions(pdev);
+
+ fail_resources:
pci_disable_device(pdev);
return err;
@@ -283,18 +283,14 @@ static void __devexit orinoco_pci_remove_one(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_pci_card *card = priv->card;
unregister_netdev(dev);
-
- if (dev->irq)
- free_irq(dev->irq, dev);
-
- if (priv->hw.iobase)
- iounmap((unsigned char *) priv->hw.iobase);
-
+ free_irq(dev->irq, dev);
pci_set_drvdata(pdev, NULL);
- free_netdev(dev);
-
+ free_orinocodev(dev);
+ iounmap(card->pci_ioaddr);
+ pci_release_regions(pdev);
pci_disable_device(pdev);
}
@@ -326,6 +322,9 @@ static int orinoco_pci_suspend(struct pci_dev *pdev, u32 state)
orinoco_unlock(priv, &flags);
+ pci_save_state(pdev);
+ pci_set_power_state(pdev, 3);
+
return 0;
}
@@ -338,6 +337,9 @@ static int orinoco_pci_resume(struct pci_dev *pdev)
printk(KERN_DEBUG "%s: Orinoco-PCI waking up\n", dev->name);
+ pci_set_power_state(pdev, 0);
+ pci_restore_state(pdev);
+
err = orinoco_reinit_firmware(dev);
if (err) {
printk(KERN_ERR "%s: Error %d re-initializing firmware on orinoco_pci_resume()\n",
@@ -368,6 +370,8 @@ static struct pci_device_id orinoco_pci_pci_id_table[] = {
{0x1260, 0x3872, PCI_ANY_ID, PCI_ANY_ID,},
/* Intersil Prism 2.5 */
{0x1260, 0x3873, PCI_ANY_ID, PCI_ANY_ID,},
+ /* Samsung MagicLAN SWL-2210P */
+ {0x167d, 0xa000, PCI_ANY_ID, PCI_ANY_ID,},
{0,},
};
diff --git a/drivers/net/wireless/orinoco_plx.c b/drivers/net/wireless/orinoco_plx.c
index d21ca78f026f7..7ab05b89fb3f6 100644
--- a/drivers/net/wireless/orinoco_plx.c
+++ b/drivers/net/wireless/orinoco_plx.c
@@ -142,146 +142,199 @@
#include "hermes.h"
#include "orinoco.h"
-#define COR_OFFSET (0x3e0/2) /* COR attribute offset of Prism2 PC card */
+#define COR_OFFSET (0x3e0) /* COR attribute offset of Prism2 PC card */
#define COR_VALUE (COR_LEVEL_REQ | COR_FUNC_ENA) /* Enable PC card with interrupt in level trigger */
+#define COR_RESET (0x80) /* reset bit in the COR register */
+#define PLX_RESET_TIME (500) /* milliseconds */
#define PLX_INTCSR 0x4c /* Interrupt Control & Status Register */
#define PLX_INTCSR_INTEN (1<<6) /* Interrupt Enable bit */
-static const u16 cis_magic[] = {
- 0x0001, 0x0003, 0x0000, 0x0000, 0x00ff, 0x0017, 0x0004, 0x0067
+static const u8 cis_magic[] = {
+ 0x01, 0x03, 0x00, 0x00, 0xff, 0x17, 0x04, 0x67
};
+/* Orinoco PLX specific data */
+struct orinoco_plx_card {
+ void __iomem *attr_mem;
+};
+
+/*
+ * Do a soft reset of the card using the Configuration Option Register
+ */
+static int orinoco_plx_cor_reset(struct orinoco_private *priv)
+{
+ hermes_t *hw = &priv->hw;
+ struct orinoco_plx_card *card = priv->card;
+ u8 __iomem *attr_mem = card->attr_mem;
+ unsigned long timeout;
+ u16 reg;
+
+ writeb(COR_VALUE | COR_RESET, attr_mem + COR_OFFSET);
+ mdelay(1);
+
+ writeb(COR_VALUE, attr_mem + COR_OFFSET);
+ mdelay(1);
+
+ /* Just in case, wait more until the card is no longer busy */
+ timeout = jiffies + (PLX_RESET_TIME * HZ / 1000);
+ reg = hermes_read_regn(hw, CMD);
+ while (time_before(jiffies, timeout) && (reg & HERMES_CMD_BUSY)) {
+ mdelay(1);
+ reg = hermes_read_regn(hw, CMD);
+ }
+
+ /* Did we timeout ? */
+ if (reg & HERMES_CMD_BUSY) {
+ printk(KERN_ERR PFX "Busy timeout\n");
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
+
static int orinoco_plx_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
int err = 0;
- u16 *attr_mem = NULL;
- u32 reg, addr;
+ u8 __iomem *attr_mem = NULL;
+ u32 csr_reg, plx_addr;
struct orinoco_private *priv = NULL;
+ struct orinoco_plx_card *card;
unsigned long pccard_ioaddr = 0;
unsigned long pccard_iolen = 0;
struct net_device *dev = NULL;
+ void __iomem *mem;
int i;
err = pci_enable_device(pdev);
- if (err)
- return -EIO;
-
- /* Resource 2 is mapped to the PCMCIA space */
- attr_mem = ioremap(pci_resource_start(pdev, 2), PAGE_SIZE);
- if (! attr_mem)
- goto fail;
-
- printk(KERN_DEBUG "orinoco_plx: CIS: ");
- for (i = 0; i < 16; i++) {
- printk("%02X:", (int)attr_mem[i]);
+ if (err) {
+ printk(KERN_ERR PFX "Cannot enable PCI device\n");
+ return err;
}
- printk("\n");
- /* Verify whether PC card is present */
- /* FIXME: we probably need to be smarted about this */
- if (memcmp(attr_mem, cis_magic, sizeof(cis_magic)) != 0) {
- printk(KERN_ERR "orinoco_plx: The CIS value of Prism2 PC card is invalid.\n");
- err = -EIO;
- goto fail;
+ err = pci_request_regions(pdev, DRIVER_NAME);
+ if (err != 0) {
+ printk(KERN_ERR PFX "Cannot obtain PCI resources\n");
+ goto fail_resources;
}
- /* PCMCIA COR is the first byte following CIS: this write should
- * enable I/O mode and select level-triggered interrupts */
- attr_mem[COR_OFFSET] = COR_VALUE;
- mdelay(1);
- reg = attr_mem[COR_OFFSET];
- if (reg != COR_VALUE) {
- printk(KERN_ERR "orinoco_plx: Error setting COR value (reg=%x)\n", reg);
- goto fail;
- }
-
- iounmap(attr_mem);
- attr_mem = NULL; /* done with this now, it seems */
+ /* Resource 1 is mapped to PLX-specific registers */
+ plx_addr = pci_resource_start(pdev, 1);
- /* bjoern: We need to tell the card to enable interrupts, in
- case the serial eprom didn't do this already. See the
- PLX9052 data book, p8-1 and 8-24 for reference. */
- addr = pci_resource_start(pdev, 1);
- reg = 0;
- reg = inl(addr+PLX_INTCSR);
- if (reg & PLX_INTCSR_INTEN)
- printk(KERN_DEBUG "orinoco_plx: "
- "Local Interrupt already enabled\n");
- else {
- reg |= PLX_INTCSR_INTEN;
- outl(reg, addr+PLX_INTCSR);
- reg = inl(addr+PLX_INTCSR);
- if(!(reg & PLX_INTCSR_INTEN)) {
- printk(KERN_ERR "orinoco_plx: "
- "Couldn't enable Local Interrupts\n");
- goto fail;
- }
+ /* Resource 2 is mapped to the PCMCIA attribute memory */
+ attr_mem = ioremap(pci_resource_start(pdev, 2),
+ pci_resource_len(pdev, 2));
+ if (!attr_mem) {
+ printk(KERN_ERR PFX "Cannot remap PCMCIA space\n");
+ goto fail_map_attr;
}
- /* and 3 to the PCMCIA slot I/O address space */
+ /* Resource 3 is mapped to the PCMCIA I/O address space */
pccard_ioaddr = pci_resource_start(pdev, 3);
pccard_iolen = pci_resource_len(pdev, 3);
- if (! request_region(pccard_ioaddr, pccard_iolen, DRIVER_NAME)) {
- printk(KERN_ERR "orinoco_plx: I/O resource 0x%lx @ 0x%lx busy\n",
- pccard_iolen, pccard_ioaddr);
- pccard_ioaddr = 0;
- err = -EBUSY;
- goto fail;
+
+ mem = pci_iomap(pdev, 3, 0);
+ if (!mem) {
+ err = -ENOMEM;
+ goto fail_map_io;
}
/* Allocate network device */
- dev = alloc_orinocodev(0, NULL);
- if (! dev) {
+ dev = alloc_orinocodev(sizeof(*card), orinoco_plx_cor_reset);
+ if (!dev) {
+ printk(KERN_ERR PFX "Cannot allocate network device\n");
err = -ENOMEM;
- goto fail;
+ goto fail_alloc;
}
priv = netdev_priv(dev);
+ card = priv->card;
+ card->attr_mem = attr_mem;
dev->base_addr = pccard_ioaddr;
SET_MODULE_OWNER(dev);
SET_NETDEV_DEV(dev, &pdev->dev);
+ hermes_struct_init(&priv->hw, mem, HERMES_16BIT_REGSPACING);
+
printk(KERN_DEBUG PFX "Detected Orinoco/Prism2 PLX device "
"at %s irq:%d, io addr:0x%lx\n", pci_name(pdev), pdev->irq,
pccard_ioaddr);
- hermes_struct_init(&(priv->hw), dev->base_addr, HERMES_IO,
- HERMES_16BIT_REGSPACING);
- pci_set_drvdata(pdev, dev);
-
err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ,
dev->name, dev);
if (err) {
- printk(KERN_ERR PFX "Error allocating IRQ %d.\n", pdev->irq);
+ printk(KERN_ERR PFX "Cannot allocate IRQ %d\n", pdev->irq);
err = -EBUSY;
- goto fail;
+ goto fail_irq;
}
dev->irq = pdev->irq;
+ /* bjoern: We need to tell the card to enable interrupts, in
+ case the serial eprom didn't do this already. See the
+ PLX9052 data book, p8-1 and 8-24 for reference. */
+ csr_reg = inl(plx_addr + PLX_INTCSR);
+ if (!(csr_reg & PLX_INTCSR_INTEN)) {
+ csr_reg |= PLX_INTCSR_INTEN;
+ outl(csr_reg, plx_addr + PLX_INTCSR);
+ csr_reg = inl(plx_addr + PLX_INTCSR);
+ if (!(csr_reg & PLX_INTCSR_INTEN)) {
+ printk(KERN_ERR PFX "Cannot enable interrupts\n");
+ goto fail;
+ }
+ }
+
+ err = orinoco_plx_cor_reset(priv);
+ if (err) {
+ printk(KERN_ERR PFX "Initial reset failed\n");
+ goto fail;
+ }
+
+ printk(KERN_DEBUG PFX "CIS: ");
+ for (i = 0; i < 16; i++) {
+ printk("%02X:", readb(attr_mem + 2*i));
+ }
+ printk("\n");
+
+ /* Verify whether a supported PC card is present */
+ /* FIXME: we probably need to be smarted about this */
+ for (i = 0; i < sizeof(cis_magic); i++) {
+ if (cis_magic[i] != readb(attr_mem +2*i)) {
+ printk(KERN_ERR PFX "The CIS value of Prism2 PC "
+ "card is unexpected\n");
+ err = -EIO;
+ goto fail;
+ }
+ }
+
err = register_netdev(dev);
- if (err)
+ if (err) {
+ printk(KERN_ERR PFX "Cannot register network device\n");
goto fail;
+ }
+
+ pci_set_drvdata(pdev, dev);
return 0;
fail:
- printk(KERN_DEBUG PFX "init_one(), FAIL!\n");
+ free_irq(pdev->irq, dev);
- if (dev) {
- if (dev->irq)
- free_irq(dev->irq, dev);
-
- free_netdev(dev);
- }
+ fail_irq:
+ pci_set_drvdata(pdev, NULL);
+ free_orinocodev(dev);
- if (pccard_ioaddr)
- release_region(pccard_ioaddr, pccard_iolen);
+ fail_alloc:
+ pci_iounmap(pdev, mem);
+
+ fail_map_io:
+ iounmap(attr_mem);
- if (attr_mem)
- iounmap(attr_mem);
+ fail_map_attr:
+ pci_release_regions(pdev);
+ fail_resources:
pci_disable_device(pdev);
return err;
@@ -290,20 +343,19 @@ static int orinoco_plx_init_one(struct pci_dev *pdev,
static void __devexit orinoco_plx_remove_one(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
+ struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_plx_card *card = priv->card;
+ u8 __iomem *attr_mem = card->attr_mem;
BUG_ON(! dev);
unregister_netdev(dev);
-
- if (dev->irq)
- free_irq(dev->irq, dev);
-
+ free_irq(dev->irq, dev);
pci_set_drvdata(pdev, NULL);
-
- free_netdev(dev);
-
- release_region(pci_resource_start(pdev, 3), pci_resource_len(pdev, 3));
-
+ free_orinocodev(dev);
+ pci_iounmap(pdev, priv->hw.iobase);
+ iounmap(attr_mem);
+ pci_release_regions(pdev);
pci_disable_device(pdev);
}
@@ -352,8 +404,7 @@ static int __init orinoco_plx_init(void)
static void __exit orinoco_plx_exit(void)
{
pci_unregister_driver(&orinoco_plx_driver);
- current->state = TASK_UNINTERRUPTIBLE;
- schedule_timeout(HZ);
+ ssleep(1);
}
module_init(orinoco_plx_init);
diff --git a/drivers/net/wireless/orinoco_tmd.c b/drivers/net/wireless/orinoco_tmd.c
index b619f6deab84a..85893f42445be 100644
--- a/drivers/net/wireless/orinoco_tmd.c
+++ b/drivers/net/wireless/orinoco_tmd.c
@@ -79,90 +79,137 @@
#include "orinoco.h"
#define COR_VALUE (COR_LEVEL_REQ | COR_FUNC_ENA) /* Enable PC card with interrupt in level trigger */
+#define COR_RESET (0x80) /* reset bit in the COR register */
+#define TMD_RESET_TIME (500) /* milliseconds */
+
+/* Orinoco TMD specific data */
+struct orinoco_tmd_card {
+ u32 tmd_io;
+};
+
+
+/*
+ * Do a soft reset of the card using the Configuration Option Register
+ */
+static int orinoco_tmd_cor_reset(struct orinoco_private *priv)
+{
+ hermes_t *hw = &priv->hw;
+ struct orinoco_tmd_card *card = priv->card;
+ u32 addr = card->tmd_io;
+ unsigned long timeout;
+ u16 reg;
+
+ outb(COR_VALUE | COR_RESET, addr);
+ mdelay(1);
+
+ outb(COR_VALUE, addr);
+ mdelay(1);
+
+ /* Just in case, wait more until the card is no longer busy */
+ timeout = jiffies + (TMD_RESET_TIME * HZ / 1000);
+ reg = hermes_read_regn(hw, CMD);
+ while (time_before(jiffies, timeout) && (reg & HERMES_CMD_BUSY)) {
+ mdelay(1);
+ reg = hermes_read_regn(hw, CMD);
+ }
+
+ /* Did we timeout ? */
+ if (reg & HERMES_CMD_BUSY) {
+ printk(KERN_ERR PFX "Busy timeout\n");
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
static int orinoco_tmd_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
int err = 0;
- u32 reg, addr;
struct orinoco_private *priv = NULL;
- unsigned long pccard_ioaddr = 0;
- unsigned long pccard_iolen = 0;
+ struct orinoco_tmd_card *card;
struct net_device *dev = NULL;
+ void __iomem *mem;
err = pci_enable_device(pdev);
- if (err)
- return -EIO;
-
- printk(KERN_DEBUG PFX "TMD setup\n");
- pccard_ioaddr = pci_resource_start(pdev, 2);
- pccard_iolen = pci_resource_len(pdev, 2);
- if (! request_region(pccard_ioaddr, pccard_iolen, DRIVER_NAME)) {
- printk(KERN_ERR PFX "I/O resource at 0x%lx len 0x%lx busy\n",
- pccard_ioaddr, pccard_iolen);
- pccard_ioaddr = 0;
- err = -EBUSY;
- goto fail;
+ if (err) {
+ printk(KERN_ERR PFX "Cannot enable PCI device\n");
+ return err;
}
- addr = pci_resource_start(pdev, 1);
- outb(COR_VALUE, addr);
- mdelay(1);
- reg = inb(addr);
- if (reg != COR_VALUE) {
- printk(KERN_ERR PFX "Error setting TMD COR values %x should be %x\n", reg, COR_VALUE);
- err = -EIO;
- goto fail;
+
+ err = pci_request_regions(pdev, DRIVER_NAME);
+ if (err != 0) {
+ printk(KERN_ERR PFX "Cannot obtain PCI resources\n");
+ goto fail_resources;
+ }
+
+ mem = pci_iomap(pdev, 2, 0);
+ if (! mem) {
+ err = -ENOMEM;
+ goto fail_iomap;
}
/* Allocate network device */
- dev = alloc_orinocodev(0, NULL);
+ dev = alloc_orinocodev(sizeof(*card), orinoco_tmd_cor_reset);
if (! dev) {
+ printk(KERN_ERR PFX "Cannot allocate network device\n");
err = -ENOMEM;
- goto fail;
+ goto fail_alloc;
}
priv = netdev_priv(dev);
- dev->base_addr = pccard_ioaddr;
+ card = priv->card;
+ card->tmd_io = pci_resource_start(pdev, 1);
+ dev->base_addr = pci_resource_start(pdev, 2);
SET_MODULE_OWNER(dev);
SET_NETDEV_DEV(dev, &pdev->dev);
+ hermes_struct_init(&priv->hw, mem, HERMES_16BIT_REGSPACING);
+
printk(KERN_DEBUG PFX "Detected Orinoco/Prism2 TMD device "
"at %s irq:%d, io addr:0x%lx\n", pci_name(pdev), pdev->irq,
- pccard_ioaddr);
-
- hermes_struct_init(&(priv->hw), dev->base_addr,
- HERMES_IO, HERMES_16BIT_REGSPACING);
- pci_set_drvdata(pdev, dev);
+ dev->base_addr);
err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ,
dev->name, dev);
if (err) {
- printk(KERN_ERR PFX "Error allocating IRQ %d.\n",
- pdev->irq);
+ printk(KERN_ERR PFX "Cannot allocate IRQ %d\n", pdev->irq);
err = -EBUSY;
- goto fail;
+ goto fail_irq;
}
dev->irq = pdev->irq;
+ err = orinoco_tmd_cor_reset(priv);
+ if (err) {
+ printk(KERN_ERR PFX "Initial reset failed\n");
+ goto fail;
+ }
+
err = register_netdev(dev);
- if (err)
+ if (err) {
+ printk(KERN_ERR PFX "Cannot register network device\n");
goto fail;
+ }
+
+ pci_set_drvdata(pdev, dev);
return 0;
fail:
- printk(KERN_DEBUG PFX "init_one(), FAIL!\n");
+ free_irq(pdev->irq, dev);
- if (dev) {
- if (dev->irq)
- free_irq(dev->irq, dev);
-
- free_netdev(dev);
- }
+ fail_irq:
+ pci_set_drvdata(pdev, NULL);
+ free_orinocodev(dev);
+
+ fail_alloc:
+ pci_iounmap(pdev, mem);
- if (pccard_ioaddr)
- release_region(pccard_ioaddr, pccard_iolen);
+ fail_iomap:
+ pci_release_regions(pdev);
+ fail_resources:
pci_disable_device(pdev);
return err;
@@ -171,20 +218,16 @@ static int orinoco_tmd_init_one(struct pci_dev *pdev,
static void __devexit orinoco_tmd_remove_one(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
+ struct orinoco_private *priv = dev->priv;
BUG_ON(! dev);
unregister_netdev(dev);
-
- if (dev->irq)
- free_irq(dev->irq, dev);
-
+ free_irq(dev->irq, dev);
pci_set_drvdata(pdev, NULL);
-
- free_netdev(dev);
-
- release_region(pci_resource_start(pdev, 2), pci_resource_len(pdev, 2));
-
+ free_orinocodev(dev);
+ pci_iounmap(pdev, priv->hw.iobase);
+ pci_release_regions(pdev);
pci_disable_device(pdev);
}
@@ -218,8 +261,7 @@ static int __init orinoco_tmd_init(void)
static void __exit orinoco_tmd_exit(void)
{
pci_unregister_driver(&orinoco_tmd_driver);
- current->state = TASK_UNINTERRUPTIBLE;
- schedule_timeout(HZ);
+ ssleep(1);
}
module_init(orinoco_tmd_init);
diff --git a/drivers/net/wireless/prism54/Makefile b/drivers/net/wireless/prism54/Makefile
index ab2ea14c51e65..fad305c76737c 100644
--- a/drivers/net/wireless/prism54/Makefile
+++ b/drivers/net/wireless/prism54/Makefile
@@ -6,5 +6,3 @@ prism54-objs := islpci_eth.o islpci_mgt.o \
obj-$(CONFIG_PRISM54) += prism54.o
-EXTRA_CFLAGS = -I$(PWD) #-DCONFIG_PRISM54_WDS
-
diff --git a/drivers/net/wireless/prism54/isl_38xx.c b/drivers/net/wireless/prism54/isl_38xx.c
index 92eda51bded5f..4481ec18c5a08 100644
--- a/drivers/net/wireless/prism54/isl_38xx.c
+++ b/drivers/net/wireless/prism54/isl_38xx.c
@@ -125,11 +125,11 @@ isl38xx_trigger_device(int asleep, void __iomem *device_base)
#if VERBOSE > SHOW_ERROR_MESSAGES
do_gettimeofday(&current_time);
DEBUG(SHOW_TRACING, "%08li.%08li Device wakeup triggered\n",
- current_time.tv_sec, current_time.tv_usec);
+ current_time.tv_sec, (long)current_time.tv_usec);
#endif
DEBUG(SHOW_TRACING, "%08li.%08li Device register read %08x\n",
- current_time.tv_sec, current_time.tv_usec,
+ current_time.tv_sec, (long)current_time.tv_usec,
readl(device_base + ISL38XX_CTRL_STAT_REG));
udelay(ISL38XX_WRITEIO_DELAY);
@@ -139,7 +139,7 @@ isl38xx_trigger_device(int asleep, void __iomem *device_base)
do_gettimeofday(&current_time);
DEBUG(SHOW_TRACING,
"%08li.%08li Device register abadface\n",
- current_time.tv_sec, current_time.tv_usec);
+ current_time.tv_sec, (long)current_time.tv_usec);
#endif
/* read the Device Status Register until Sleepmode bit is set */
while (reg = readl(device_base + ISL38XX_CTRL_STAT_REG),
@@ -150,7 +150,7 @@ isl38xx_trigger_device(int asleep, void __iomem *device_base)
DEBUG(SHOW_TRACING,
"%08li.%08li Device register read %08x\n",
- current_time.tv_sec, current_time.tv_usec,
+ current_time.tv_sec, (long)current_time.tv_usec,
readl(device_base + ISL38XX_CTRL_STAT_REG));
udelay(ISL38XX_WRITEIO_DELAY);
@@ -158,7 +158,7 @@ isl38xx_trigger_device(int asleep, void __iomem *device_base)
do_gettimeofday(&current_time);
DEBUG(SHOW_TRACING,
"%08li.%08li Device asleep counter %i\n",
- current_time.tv_sec, current_time.tv_usec,
+ current_time.tv_sec, (long)current_time.tv_usec,
counter);
#endif
}
@@ -174,7 +174,7 @@ isl38xx_trigger_device(int asleep, void __iomem *device_base)
#if VERBOSE > SHOW_ERROR_MESSAGES
do_gettimeofday(&current_time);
DEBUG(SHOW_TRACING, "%08li.%08li Device register read %08x\n",
- current_time.tv_sec, current_time.tv_usec, reg);
+ current_time.tv_sec, (long)current_time.tv_usec, reg);
#endif
} else {
/* device is (still) awake */
diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c
index 6a8306668245c..0f29a9c7bc2cd 100644
--- a/drivers/net/wireless/prism54/isl_ioctl.c
+++ b/drivers/net/wireless/prism54/isl_ioctl.c
@@ -36,6 +36,14 @@
#include <net/iw_handler.h> /* New driver API */
+
+static void prism54_wpa_ie_add(islpci_private *priv, u8 *bssid,
+ u8 *wpa_ie, size_t wpa_ie_len);
+static size_t prism54_wpa_ie_get(islpci_private *priv, u8 *bssid, u8 *wpa_ie);
+static int prism54_set_wpa(struct net_device *, struct iw_request_info *,
+ __u32 *, char *);
+
+
/**
* prism54_mib_mode_helper - MIB change mode helper function
* @mib: the &struct islpci_mib object to modify
@@ -47,7 +55,7 @@
* Wireless API modes to Device firmware modes. It also checks for
* correct valid Linux wireless modes.
*/
-int
+static int
prism54_mib_mode_helper(islpci_private *priv, u32 iw_mode)
{
u32 config = INL_CONFIG_MANUALRUN;
@@ -647,7 +655,7 @@ prism54_translate_bss(struct net_device *ndev, char *current_ev,
return current_ev;
}
-int
+static int
prism54_get_scan(struct net_device *ndev, struct iw_request_info *info,
struct iw_point *dwrq, char *extra)
{
@@ -1586,7 +1594,7 @@ static u8 wpa_oid[4] = { 0x00, 0x50, 0xf2, 1 };
#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"
-void
+static void
prism54_wpa_ie_add(islpci_private *priv, u8 *bssid,
u8 *wpa_ie, size_t wpa_ie_len)
{
@@ -1653,7 +1661,7 @@ prism54_wpa_ie_add(islpci_private *priv, u8 *bssid,
up(&priv->wpa_sem);
}
-size_t
+static size_t
prism54_wpa_ie_get(islpci_private *priv, u8 *bssid, u8 *wpa_ie)
{
struct list_head *ptr;
@@ -1740,7 +1748,7 @@ handle_request(islpci_private *priv, struct obj_mlme *mlme, enum oid_num_t oid)
}
}
-int
+static int
prism54_process_trap_helper(islpci_private *priv, enum oid_num_t oid,
char *data)
{
@@ -1750,7 +1758,7 @@ prism54_process_trap_helper(islpci_private *priv, enum oid_num_t oid,
u8 wpa_ie[MAX_WPA_IE_LEN];
int wpa_ie_len;
size_t len = 0; /* u16, better? */
- u8 *payload = 0, *pos = 0;
+ u8 *payload = NULL, *pos = NULL;
int ret;
/* I think all trapable objects are listed here.
@@ -2318,7 +2326,7 @@ prism54_hostapd(struct net_device *ndev, struct iw_point *p)
return ret;
}
-int
+static int
prism54_set_wpa(struct net_device *ndev, struct iw_request_info *info,
__u32 * uwrq, char *extra)
{
@@ -2362,7 +2370,7 @@ prism54_set_wpa(struct net_device *ndev, struct iw_request_info *info,
return 0;
}
-int
+static int
prism54_get_wpa(struct net_device *ndev, struct iw_request_info *info,
__u32 * uwrq, char *extra)
{
@@ -2371,7 +2379,7 @@ prism54_get_wpa(struct net_device *ndev, struct iw_request_info *info,
return 0;
}
-int
+static int
prism54_set_prismhdr(struct net_device *ndev, struct iw_request_info *info,
__u32 * uwrq, char *extra)
{
@@ -2384,7 +2392,7 @@ prism54_set_prismhdr(struct net_device *ndev, struct iw_request_info *info,
return 0;
}
-int
+static int
prism54_get_prismhdr(struct net_device *ndev, struct iw_request_info *info,
__u32 * uwrq, char *extra)
{
@@ -2393,7 +2401,7 @@ prism54_get_prismhdr(struct net_device *ndev, struct iw_request_info *info,
return 0;
}
-int
+static int
prism54_debug_oid(struct net_device *ndev, struct iw_request_info *info,
__u32 * uwrq, char *extra)
{
@@ -2405,7 +2413,7 @@ prism54_debug_oid(struct net_device *ndev, struct iw_request_info *info,
return 0;
}
-int
+static int
prism54_debug_get_oid(struct net_device *ndev, struct iw_request_info *info,
struct iw_point *data, char *extra)
{
@@ -2441,7 +2449,7 @@ prism54_debug_get_oid(struct net_device *ndev, struct iw_request_info *info,
return ret;
}
-int
+static int
prism54_debug_set_oid(struct net_device *ndev, struct iw_request_info *info,
struct iw_point *data, char *extra)
{
diff --git a/drivers/net/wireless/prism54/isl_ioctl.h b/drivers/net/wireless/prism54/isl_ioctl.h
index f37f313e874ae..46d5cde80c85e 100644
--- a/drivers/net/wireless/prism54/isl_ioctl.h
+++ b/drivers/net/wireless/prism54/isl_ioctl.h
@@ -41,15 +41,10 @@ void prism54_process_trap(void *);
void prism54_wpa_ie_init(islpci_private *priv);
void prism54_wpa_ie_clean(islpci_private *priv);
-void prism54_wpa_ie_add(islpci_private *priv, u8 *bssid,
- u8 *wpa_ie, size_t wpa_ie_len);
-size_t prism54_wpa_ie_get(islpci_private *priv, u8 *bssid, u8 *wpa_ie);
int prism54_set_mac_address(struct net_device *, void *);
int prism54_ioctl(struct net_device *, struct ifreq *, int);
-int prism54_set_wpa(struct net_device *, struct iw_request_info *,
- __u32 *, char *);
extern const struct iw_handler_def prism54_handler_def;
diff --git a/drivers/net/wireless/prism54/islpci_dev.c b/drivers/net/wireless/prism54/islpci_dev.c
index f5fc41972f173..efab07e9e24e0 100644
--- a/drivers/net/wireless/prism54/islpci_dev.c
+++ b/drivers/net/wireless/prism54/islpci_dev.c
@@ -44,6 +44,7 @@
static int prism54_bring_down(islpci_private *);
static int islpci_alloc_memory(islpci_private *);
+static struct net_device_stats *islpci_statistics(struct net_device *);
/* Temporary dummy MAC address to use until firmware is loaded.
* The idea there is that some tools (such as nameif) may query
@@ -52,7 +53,7 @@ static int islpci_alloc_memory(islpci_private *);
* Of course, this is not the final/real MAC address. It doesn't
* matter, as you are suppose to be able to change it anytime via
* ndev->set_mac_address. Jean II */
-const unsigned char dummy_mac[6] = { 0x00, 0x30, 0xB4, 0x00, 0x00, 0x00 };
+static const unsigned char dummy_mac[6] = { 0x00, 0x30, 0xB4, 0x00, 0x00, 0x00 };
static int
isl_upload_firmware(islpci_private *priv)
@@ -607,7 +608,7 @@ islpci_reset(islpci_private *priv, int reload_firmware)
return rc;
}
-struct net_device_stats *
+static struct net_device_stats *
islpci_statistics(struct net_device *ndev)
{
islpci_private *priv = netdev_priv(ndev);
diff --git a/drivers/net/wireless/prism54/islpci_dev.h b/drivers/net/wireless/prism54/islpci_dev.h
index d71b8bb631dc9..32a1019f1b363 100644
--- a/drivers/net/wireless/prism54/islpci_dev.h
+++ b/drivers/net/wireless/prism54/islpci_dev.h
@@ -211,8 +211,6 @@ islpci_trigger(islpci_private *priv)
priv->device_base);
}
-struct net_device_stats *islpci_statistics(struct net_device *);
-
int islpci_free_memory(islpci_private *);
struct net_device *islpci_setup(struct pci_dev *);
#endif /* _ISLPCI_DEV_H */
diff --git a/drivers/net/wireless/prism54/islpci_hotplug.c b/drivers/net/wireless/prism54/islpci_hotplug.c
index 1fabf697683de..efd4d213ac3de 100644
--- a/drivers/net/wireless/prism54/islpci_hotplug.c
+++ b/drivers/net/wireless/prism54/islpci_hotplug.c
@@ -163,7 +163,7 @@ prism54_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (rvalue || !mem_addr) {
printk(KERN_ERR "%s: PCI device memory region not configured; fix your BIOS or CardBus bridge/drivers\n",
DRV_NAME);
- goto do_pci_disable_device;
+ goto do_pci_release_regions;
}
/* enable PCI bus-mastering */
diff --git a/drivers/net/wireless/prism54/islpci_mgt.c b/drivers/net/wireless/prism54/islpci_mgt.c
index b887beac988b4..b6f2e5a223be6 100644
--- a/drivers/net/wireless/prism54/islpci_mgt.c
+++ b/drivers/net/wireless/prism54/islpci_mgt.c
@@ -44,6 +44,7 @@ module_param(pc_debug, int, 0);
/******************************************************************************
Driver general functions
******************************************************************************/
+#if VERBOSE > SHOW_ERROR_MESSAGES
void
display_buffer(char *buffer, int length)
{
@@ -58,6 +59,7 @@ display_buffer(char *buffer, int length)
printk("\n");
}
+#endif
/*****************************************************************************
Queue handling for management frames
diff --git a/drivers/net/wireless/prism54/oid_mgt.c b/drivers/net/wireless/prism54/oid_mgt.c
index fa60a8f60f39e..12123e24b1133 100644
--- a/drivers/net/wireless/prism54/oid_mgt.c
+++ b/drivers/net/wireless/prism54/oid_mgt.c
@@ -24,8 +24,8 @@
#include "isl_ioctl.h"
/* to convert between channel and freq */
-const int frequency_list_bg[] = { 2412, 2417, 2422, 2427, 2432, 2437, 2442,
- 2447, 2452, 2457, 2462, 2467, 2472, 2484
+static const int frequency_list_bg[] = { 2412, 2417, 2422, 2427, 2432,
+ 2437, 2442, 2447, 2452, 2457, 2462, 2467, 2472, 2484
};
int
@@ -730,6 +730,7 @@ mgt_commit(islpci_private *priv)
*
* The way to do this is to set ESSID. Note though that they may get
* unlatch before though by setting another OID. */
+#if 0
void
mgt_unlatch_all(islpci_private *priv)
{
@@ -756,6 +757,7 @@ mgt_unlatch_all(islpci_private *priv)
if (rvalue)
printk(KERN_DEBUG "%s: Unlatching OIDs failed\n", priv->ndev->name);
}
+#endif
/* This will tell you if you are allowed to answer a mlme(ex) request .*/
diff --git a/drivers/net/wireless/prism54/oid_mgt.h b/drivers/net/wireless/prism54/oid_mgt.h
index dc0b76af66c7a..92c8a2d4acd80 100644
--- a/drivers/net/wireless/prism54/oid_mgt.h
+++ b/drivers/net/wireless/prism54/oid_mgt.h
@@ -28,8 +28,7 @@ int mgt_init(islpci_private *);
void mgt_clean(islpci_private *);
-/* I don't know where to put these 3 */
-extern const int frequency_list_bg[];
+/* I don't know where to put these 2 */
extern const int frequency_list_a[];
int channel_of_freq(int);
@@ -49,7 +48,6 @@ void mgt_set(islpci_private *, enum oid_num_t, void *);
void mgt_get(islpci_private *, enum oid_num_t, void *);
int mgt_commit(islpci_private *);
-void mgt_unlatch_all(islpci_private *);
int mgt_mlme_answer(islpci_private *);
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c
index 1268bf792fa41..6e5bda56b8f87 100644
--- a/drivers/net/wireless/ray_cs.c
+++ b/drivers/net/wireless/ray_cs.c
@@ -1215,6 +1215,9 @@ static int ray_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
#if WIRELESS_EXT > 7
struct iwreq *wrq = (struct iwreq *) ifr;
#endif /* WIRELESS_EXT > 7 */
+#ifdef WIRELESS_SPY
+ struct sockaddr address[IW_MAX_SPY];
+#endif /* WIRELESS_SPY */
if (!(link->state & DEV_PRESENT)) {
DEBUG(2,"ray_dev_ioctl - device not present\n");
@@ -1511,7 +1514,6 @@ static int ray_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
/* If there is some addresses to copy */
if(local->spy_number > 0)
{
- struct sockaddr address[IW_MAX_SPY];
int i;
/* Copy addresses to the driver */
@@ -1551,7 +1553,6 @@ static int ray_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
/* If the user want to have the addresses back... */
if((local->spy_number > 0) && (wrq->u.data.pointer != (caddr_t) 0))
{
- struct sockaddr address[IW_MAX_SPY];
int i;
/* Copy addresses from the lp structure */
diff --git a/drivers/net/wireless/strip.c b/drivers/net/wireless/strip.c
index 5d351973174fc..ec8cf29ffcedc 100644
--- a/drivers/net/wireless/strip.c
+++ b/drivers/net/wireless/strip.c
@@ -876,7 +876,7 @@ static int allocate_buffers(struct strip *strip_info, int mtu)
*/
static int strip_change_mtu(struct net_device *dev, int new_mtu)
{
- struct strip *strip_info = dev->priv;
+ struct strip *strip_info = netdev_priv(dev);
int old_mtu = strip_info->mtu;
unsigned char *orbuff = strip_info->rx_buff;
unsigned char *osbuff = strip_info->sx_buff;
@@ -1563,7 +1563,7 @@ static void strip_send(struct strip *strip_info, struct sk_buff *skb)
/* Encapsulate a datagram and kick it into a TTY queue. */
static int strip_xmit(struct sk_buff *skb, struct net_device *dev)
{
- struct strip *strip_info = (struct strip *) (dev->priv);
+ struct strip *strip_info = netdev_priv(dev);
if (!netif_running(dev)) {
printk(KERN_ERR "%s: xmit call when iface is down\n",
@@ -1639,7 +1639,7 @@ static int strip_header(struct sk_buff *skb, struct net_device *dev,
unsigned short type, void *daddr, void *saddr,
unsigned len)
{
- struct strip *strip_info = (struct strip *) (dev->priv);
+ struct strip *strip_info = netdev_priv(dev);
STRIP_Header *header = (STRIP_Header *) skb_push(skb, sizeof(STRIP_Header));
/*printk(KERN_INFO "%s: strip_header 0x%04X %s\n", dev->name, type,
@@ -1648,7 +1648,7 @@ static int strip_header(struct sk_buff *skb, struct net_device *dev,
header->src_addr = strip_info->true_dev_addr;
header->protocol = htons(type);
- /*HexDump("strip_header", (struct strip *)(dev->priv), skb->data, skb->data + skb->len); */
+ /*HexDump("strip_header", netdev_priv(dev), skb->data, skb->data + skb->len); */
if (!daddr)
return (-dev->hard_header_len);
@@ -2400,7 +2400,7 @@ static int set_mac_address(struct strip *strip_info,
static int strip_set_mac_address(struct net_device *dev, void *addr)
{
- struct strip *strip_info = (struct strip *) (dev->priv);
+ struct strip *strip_info = netdev_priv(dev);
struct sockaddr *sa = addr;
printk(KERN_INFO "%s: strip_set_dev_mac_address called\n", dev->name);
set_mac_address(strip_info, (MetricomAddress *) sa->sa_data);
@@ -2409,8 +2409,8 @@ static int strip_set_mac_address(struct net_device *dev, void *addr)
static struct net_device_stats *strip_get_stats(struct net_device *dev)
{
+ struct strip *strip_info = netdev_priv(dev);
static struct net_device_stats stats;
- struct strip *strip_info = (struct strip *) (dev->priv);
memset(&stats, 0, sizeof(struct net_device_stats));
@@ -2454,7 +2454,7 @@ static struct net_device_stats *strip_get_stats(struct net_device *dev)
static int strip_open_low(struct net_device *dev)
{
- struct strip *strip_info = (struct strip *) (dev->priv);
+ struct strip *strip_info = netdev_priv(dev);
if (strip_info->tty == NULL)
return (-ENODEV);
@@ -2487,7 +2487,7 @@ static int strip_open_low(struct net_device *dev)
static int strip_close_low(struct net_device *dev)
{
- struct strip *strip_info = (struct strip *) (dev->priv);
+ struct strip *strip_info = netdev_priv(dev);
if (strip_info->tty == NULL)
return -EBUSY;
diff --git a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c
index 9ac2dab4d7055..55720dc6ec43f 100644
--- a/drivers/oprofile/buffer_sync.c
+++ b/drivers/oprofile/buffer_sync.c
@@ -34,9 +34,9 @@
static LIST_HEAD(dying_tasks);
static LIST_HEAD(dead_tasks);
-cpumask_t marked_cpus = CPU_MASK_NONE;
+static cpumask_t marked_cpus = CPU_MASK_NONE;
static DEFINE_SPINLOCK(task_mortuary);
-void process_task_mortuary(void);
+static void process_task_mortuary(void);
/* Take ownership of the task struct and place it on the
@@ -422,7 +422,7 @@ static void increment_tail(struct oprofile_cpu_buffer * b)
* and to have reached the list, it must have gone through
* one full sync already.
*/
-void process_task_mortuary(void)
+static void process_task_mortuary(void)
{
struct list_head * pos;
struct list_head * pos2;
diff --git a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c
index 0865e48954a22..e9b1772a3a28c 100644
--- a/drivers/oprofile/cpu_buffer.c
+++ b/drivers/oprofile/cpu_buffer.c
@@ -32,7 +32,7 @@ struct oprofile_cpu_buffer cpu_buffer[NR_CPUS] __cacheline_aligned;
static void wq_sync_buffer(void *);
#define DEFAULT_TIMER_EXPIRE (HZ / 10)
-int work_enabled;
+static int work_enabled;
void free_cpu_buffers(void)
{
diff --git a/drivers/oprofile/event_buffer.c b/drivers/oprofile/event_buffer.c
index d8b1869241408..166bca7901334 100644
--- a/drivers/oprofile/event_buffer.c
+++ b/drivers/oprofile/event_buffer.c
@@ -94,7 +94,7 @@ void free_event_buffer(void)
}
-int event_buffer_open(struct inode * inode, struct file * file)
+static int event_buffer_open(struct inode * inode, struct file * file)
{
int err = -EPERM;
@@ -130,7 +130,7 @@ out:
}
-int event_buffer_release(struct inode * inode, struct file * file)
+static int event_buffer_release(struct inode * inode, struct file * file)
{
oprofile_stop();
oprofile_shutdown();
@@ -142,7 +142,8 @@ int event_buffer_release(struct inode * inode, struct file * file)
}
-ssize_t event_buffer_read(struct file * file, char __user * buf, size_t count, loff_t * offset)
+static ssize_t event_buffer_read(struct file * file, char __user * buf,
+ size_t count, loff_t * offset)
{
int retval = -EINVAL;
size_t const max = buffer_size * sizeof(unsigned long);
diff --git a/drivers/parisc/Kconfig b/drivers/parisc/Kconfig
index aa88c41004dff..3f5de867acd7c 100644
--- a/drivers/parisc/Kconfig
+++ b/drivers/parisc/Kconfig
@@ -110,6 +110,14 @@ config IOMMU_SBA
# help
# Say Y here for V-class PCI, DMA/IOMMU, IRQ subsystem support.
+source "drivers/pcmcia/Kconfig"
+
+source "drivers/pci/hotplug/Kconfig"
+
+endmenu
+
+menu "PA-RISC specific drivers"
+
config SUPERIO
bool "SuperIO (SuckyIO) support"
depends on PCI_LBA
@@ -144,9 +152,18 @@ config PDC_CHASSIS
If unsure, say Y.
-source "drivers/pcmcia/Kconfig"
-
-source "drivers/pci/hotplug/Kconfig"
-
+config PDC_STABLE
+ tristate "PDC Stable Storage support"
+ depends on SYSFS
+ default y
+ help
+ Say Y here if you want to enable support for accessing Stable Storage
+ variables (PDC non volatile variables such as Primary Boot Path,
+ Console Path, Autoboot, Autosearch, etc) through SysFS.
+
+ If unsure, say Y.
+
+ To compile this driver as a module, choose M here.
+ The module will be called pdc_stable.
endmenu
diff --git a/drivers/parisc/Makefile b/drivers/parisc/Makefile
index c7fce943ffd27..f95cab57133af 100644
--- a/drivers/parisc/Makefile
+++ b/drivers/parisc/Makefile
@@ -22,5 +22,6 @@ obj-$(CONFIG_EISA) += eisa.o eisa_enumerator.o eisa_eeprom.o
obj-$(CONFIG_SUPERIO) += superio.o
obj-$(CONFIG_CHASSIS_LCD_LED) += led.o
+obj-$(CONFIG_PDC_STABLE) += pdc_stable.o
obj-y += power.o
diff --git a/drivers/parisc/asp.c b/drivers/parisc/asp.c
index effc8779a900a..388609967133f 100644
--- a/drivers/parisc/asp.c
+++ b/drivers/parisc/asp.c
@@ -30,6 +30,8 @@
#define VIPER_INT_WORD 0xFFFBF088 /* addr of viper interrupt word */
+static struct gsc_asic asp;
+
static void asp_choose_irq(struct parisc_device *dev, void *ctrl)
{
int irq;
@@ -51,6 +53,14 @@ static void asp_choose_irq(struct parisc_device *dev, void *ctrl)
}
gsc_asic_assign_irq(ctrl, irq, &dev->irq);
+
+ switch (dev->id.sversion) {
+ case 0x73: irq = 2; break; /* i8042 High-priority */
+ case 0x76: irq = 0; break; /* EISA BA */
+ default: return; /* Other */
+ }
+
+ gsc_asic_assign_irq(ctrl, irq, &dev->aux_irq);
}
/* There are two register ranges we're interested in. Interrupt /
@@ -64,20 +74,15 @@ static void asp_choose_irq(struct parisc_device *dev, void *ctrl)
int __init
asp_init_chip(struct parisc_device *dev)
{
- struct gsc_asic *asp;
struct gsc_irq gsc_irq;
int ret;
- asp = kmalloc(sizeof(*asp), GFP_KERNEL);
- if(!asp)
- return -ENOMEM;
-
- asp->version = gsc_readb(dev->hpa + ASP_VER_OFFSET) & 0xf;
- asp->name = (asp->version == 1) ? "Asp" : "Cutoff";
- asp->hpa = ASP_INTERRUPT_ADDR;
+ asp.version = gsc_readb(dev->hpa + ASP_VER_OFFSET) & 0xf;
+ asp.name = (asp.version == 1) ? "Asp" : "Cutoff";
+ asp.hpa = ASP_INTERRUPT_ADDR;
printk(KERN_INFO "%s version %d at 0x%lx found.\n",
- asp->name, asp->version, dev->hpa);
+ asp.name, asp.version, dev->hpa);
/* the IRQ ASP should use */
ret = -EBUSY;
@@ -87,9 +92,9 @@ asp_init_chip(struct parisc_device *dev)
goto out;
}
- asp->eim = ((u32) gsc_irq.txn_addr) | gsc_irq.txn_data;
+ asp.eim = ((u32) gsc_irq.txn_addr) | gsc_irq.txn_data;
- ret = request_irq(gsc_irq.irq, gsc_asic_intr, 0, "asp", asp);
+ ret = request_irq(gsc_irq.irq, gsc_asic_intr, 0, "asp", &asp);
if (ret < 0)
goto out;
@@ -97,13 +102,13 @@ asp_init_chip(struct parisc_device *dev)
gsc_writel((1 << (31 - ASP_GSC_IRQ)),VIPER_INT_WORD);
/* Done init'ing, register this driver */
- ret = gsc_common_setup(dev, asp);
+ ret = gsc_common_setup(dev, &asp);
if (ret)
goto out;
- gsc_fixup_irqs(dev, asp, asp_choose_irq);
+ gsc_fixup_irqs(dev, &asp, asp_choose_irq);
/* Mongoose is a sibling of Asp, not a child... */
- gsc_fixup_irqs(parisc_parent(dev), asp, asp_choose_irq);
+ gsc_fixup_irqs(parisc_parent(dev), &asp, asp_choose_irq);
/* initialize the chassis LEDs */
#ifdef CONFIG_CHASSIS_LCD_LED
@@ -111,10 +116,7 @@ asp_init_chip(struct parisc_device *dev)
ASP_LED_ADDR);
#endif
- return 0;
-
-out:
- kfree(asp);
+ out:
return ret;
}
diff --git a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c
index 589ed1ee5ea5f..0e98a9d9834cb 100644
--- a/drivers/parisc/ccio-dma.c
+++ b/drivers/parisc/ccio-dma.c
@@ -262,8 +262,6 @@ struct ioc {
struct resource mmio_region[2]; /* The "routed" MMIO regions */
};
-/* Ratio of Host MEM to IOV Space size */
-static unsigned long ccio_mem_ratio = 4;
static struct ioc *ioc_list;
static int ioc_count;
@@ -559,7 +557,7 @@ void CCIO_INLINE
ccio_io_pdir_entry(u64 *pdir_ptr, space_t sid, unsigned long vba,
unsigned long hints)
{
- register unsigned long pa = (volatile unsigned long) vba;
+ register unsigned long pa;
register unsigned long ci; /* coherent index */
/* We currently only support kernel addresses */
@@ -1243,6 +1241,21 @@ ccio_get_iotlb_size(struct parisc_device *dev)
#define CCIO_CHAINID_MASK 0xff
#endif /* 0 */
+/* We *can't* support JAVA (T600). Venture there at your own risk. */
+static struct parisc_device_id ccio_tbl[] = {
+ { HPHW_IOA, HVERSION_REV_ANY_ID, U2_IOA_RUNWAY, 0xb }, /* U2 */
+ { HPHW_IOA, HVERSION_REV_ANY_ID, UTURN_IOA_RUNWAY, 0xb }, /* UTurn */
+ { 0, }
+};
+
+static int ccio_probe(struct parisc_device *dev);
+
+static struct parisc_driver ccio_driver = {
+ .name = "U2:Uturn",
+ .id_table = ccio_tbl,
+ .probe = ccio_probe,
+};
+
/**
* ccio_ioc_init - Initalize the I/O Controller
* @ioc: The I/O Controller.
@@ -1254,9 +1267,9 @@ ccio_get_iotlb_size(struct parisc_device *dev)
static void
ccio_ioc_init(struct ioc *ioc)
{
- int i, iov_order;
+ int i;
+ unsigned int iov_order;
u32 iova_space_size;
- unsigned long physmem;
/*
** Determine IOVA Space size from memory size.
@@ -1269,17 +1282,16 @@ ccio_ioc_init(struct ioc *ioc)
** Hot-Plug/Removal of PCI cards. (aka PCI OLARD).
*/
+ iova_space_size = (u32) (num_physpages / count_parisc_driver(&ccio_driver));
+
/* limit IOVA space size to 1MB-1GB */
- physmem = num_physpages << PAGE_SHIFT;
- if(physmem < (ccio_mem_ratio * 1024 * 1024)) {
- iova_space_size = 1024 * 1024;
+ if (iova_space_size < (1 << (20 - PAGE_SHIFT))) {
+ iova_space_size = 1 << (20 - PAGE_SHIFT);
#ifdef __LP64__
- } else if(physmem > (ccio_mem_ratio * 512 * 1024 * 1024)) {
- iova_space_size = 512 * 1024 * 1024;
+ } else if (iova_space_size > (1 << (30 - PAGE_SHIFT))) {
+ iova_space_size = 1 << (30 - PAGE_SHIFT);
#endif
- } else {
- iova_space_size = (u32)(physmem / ccio_mem_ratio);
}
/*
@@ -1295,10 +1307,10 @@ ccio_ioc_init(struct ioc *ioc)
** this is the case under linux."
*/
- iov_order = get_order(iova_space_size) >> (IOVP_SHIFT - PAGE_SHIFT);
- BUG_ON(iov_order > (30 - IOVP_SHIFT)); /* iova_space_size <= 1GB */
- BUG_ON(iov_order < (20 - IOVP_SHIFT)); /* iova_space_size >= 1MB */
- iova_space_size = 1 << (iov_order + IOVP_SHIFT);
+ iov_order = get_order(iova_space_size << PAGE_SHIFT);
+
+ /* iova_space_size is now bytes, not pages */
+ iova_space_size = 1 << (iov_order + PAGE_SHIFT);
ioc->pdir_size = (iova_space_size / IOVP_SIZE) * sizeof(u64);
@@ -1307,9 +1319,12 @@ ccio_ioc_init(struct ioc *ioc)
/* Verify it's a power of two */
BUG_ON((1 << get_order(ioc->pdir_size)) != (ioc->pdir_size >> PAGE_SHIFT));
- DBG_INIT("%s() hpa 0x%p mem %luMB IOV %dMB (%d bits) PDIR size 0x%0x",
- __FUNCTION__, ioc->ioc_hpa, physmem>>20, iova_space_size>>20,
- iov_order + PAGE_SHIFT, ioc->pdir_size);
+ DBG_INIT("%s() hpa 0x%lx mem %luMB IOV %dMB (%d bits)\n",
+ __FUNCTION__,
+ ioc->ioc_hpa,
+ (unsigned long) num_physpages >> (20 - PAGE_SHIFT),
+ iova_space_size>>20,
+ iov_order + PAGE_SHIFT);
ioc->pdir_base = (u64 *)__get_free_pages(GFP_KERNEL,
get_order(ioc->pdir_size));
@@ -1566,19 +1581,6 @@ static int ccio_probe(struct parisc_device *dev)
return 0;
}
-/* We *can't* support JAVA (T600). Venture there at your own risk. */
-static struct parisc_device_id ccio_tbl[] = {
- { HPHW_IOA, HVERSION_REV_ANY_ID, U2_IOA_RUNWAY, 0xb }, /* U2 */
- { HPHW_IOA, HVERSION_REV_ANY_ID, UTURN_IOA_RUNWAY, 0xb }, /* UTurn */
- { 0, }
-};
-
-static struct parisc_driver ccio_driver = {
- .name = "U2:Uturn",
- .id_table = ccio_tbl,
- .probe = ccio_probe,
-};
-
/**
* ccio_init - ccio initalization procedure.
*
diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c
index b2f07bb69ccab..b0d2a73d1d473 100644
--- a/drivers/parisc/dino.c
+++ b/drivers/parisc/dino.c
@@ -653,14 +653,13 @@ dino_fixup_bus(struct pci_bus *bus)
PCI_INTERRUPT_PIN, 1, &irq_pin);
irq_pin = (irq_pin + PCI_SLOT(dev->devfn) - 1) % 4 ;
printk(KERN_WARNING "Device %s has undefined IRQ, "
- "setting to %d\n", dev->slot_name,
- irq_pin);
+ "setting to %d\n", pci_name(dev), irq_pin);
dino_cfg_write(dev->bus, dev->devfn,
PCI_INTERRUPT_LINE, 1, irq_pin);
dino_assign_irq(dino_dev, irq_pin, &dev->irq);
#else
dev->irq = 65535;
- printk(KERN_WARNING "Device %s has unassigned IRQ\n", dev->slot_name);
+ printk(KERN_WARNING "Device %s has unassigned IRQ\n", pci_name(dev));
#endif
} else {
diff --git a/drivers/parisc/eisa.c b/drivers/parisc/eisa.c
index 1bd487dd51dab..043d47aea75b6 100644
--- a/drivers/parisc/eisa.c
+++ b/drivers/parisc/eisa.c
@@ -44,6 +44,7 @@
#include <asm/parisc-device.h>
#include <asm/delay.h>
#include <asm/eisa_bus.h>
+#include <asm/eisa_eeprom.h>
#if 0
#define EISA_DBG(msg, arg... ) printk(KERN_DEBUG "eisa: " msg , ## arg )
@@ -56,6 +57,8 @@
static DEFINE_SPINLOCK(eisa_irq_lock);
+void __iomem *eisa_eeprom_addr;
+
/* We can only have one EISA adapter in the system because neither
* implementation can be flexed.
*/
@@ -351,6 +354,7 @@ static int __devinit eisa_probe(struct parisc_device *dev)
}
EISA_bus = 1;
+
if (dev->num_addrs) {
/* newer firmware hand out the eeprom address */
eisa_dev.eeprom_addr = dev->addr[0];
@@ -362,8 +366,9 @@ static int __devinit eisa_probe(struct parisc_device *dev)
eisa_dev.eeprom_addr = MIRAGE_EEPROM_BASE_ADDR;
}
}
- eisa_eeprom_init(eisa_dev.eeprom_addr);
- result = eisa_enumerator(eisa_dev.eeprom_addr, &eisa_dev.hba.io_space, &eisa_dev.hba.lmmio_space);
+ eisa_eeprom_addr = ioremap(eisa_dev.eeprom_addr, HPEE_MAX_LENGTH);
+ result = eisa_enumerator(eisa_dev.eeprom_addr, &eisa_dev.hba.io_space,
+ &eisa_dev.hba.lmmio_space);
init_eisa_pic();
if (result >= 0) {
diff --git a/drivers/parisc/eisa_eeprom.c b/drivers/parisc/eisa_eeprom.c
index d16724dbe890c..3a1b4826e5c16 100644
--- a/drivers/parisc/eisa_eeprom.c
+++ b/drivers/parisc/eisa_eeprom.c
@@ -19,7 +19,6 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
@@ -32,8 +31,6 @@
#define EISA_EEPROM_MINOR 241
-static unsigned long eeprom_addr;
-
static loff_t eisa_eeprom_llseek(struct file *file, loff_t offset, int origin )
{
switch (origin) {
@@ -64,7 +61,7 @@ static ssize_t eisa_eeprom_read(struct file * file,
tmp = kmalloc(count, GFP_KERNEL);
if (tmp) {
for (i = 0; i < count; i++)
- tmp[i] = gsc_readb(eeprom_addr+(*ppos)++);
+ tmp[i] = readb(eisa_eeprom_addr+(*ppos)++);
if (copy_to_user (buf, tmp, count))
ret = -EFAULT;
@@ -86,7 +83,7 @@ static int eisa_eeprom_ioctl(struct inode *inode, struct file *file,
static int eisa_eeprom_open(struct inode *inode, struct file *file)
{
- if (file->f_mode & 2 || eeprom_addr == 0)
+ if (file->f_mode & 2)
return -EINVAL;
return 0;
@@ -109,22 +106,18 @@ static struct file_operations eisa_eeprom_fops = {
.release = eisa_eeprom_release,
};
-static struct miscdevice eisa_eeprom_dev=
-{
+static struct miscdevice eisa_eeprom_dev = {
EISA_EEPROM_MINOR,
- "eisa eeprom",
+ "eisa_eeprom",
&eisa_eeprom_fops
};
-int __init eisa_eeprom_init(unsigned long addr)
+static int __init eisa_eeprom_init(void)
{
int retval;
- /* XXX why return success when we haven't done anything? */
- if (!addr)
- return 0;
-
- eeprom_addr = addr;
+ if (!eisa_eeprom_addr)
+ return -ENODEV;
retval = misc_register(&eisa_eeprom_dev);
if (retval < 0) {
@@ -132,8 +125,10 @@ int __init eisa_eeprom_init(unsigned long addr)
return retval;
}
- printk(KERN_INFO "EISA EEPROM at 0x%lx\n", eeprom_addr);
+ printk(KERN_INFO "EISA EEPROM at 0x%p\n", eisa_eeprom_addr);
return 0;
}
MODULE_LICENSE("GPL");
+
+module_init(eisa_eeprom_init);
diff --git a/drivers/parisc/gsc.c b/drivers/parisc/gsc.c
index 17960846935ed..af5e02526a18d 100644
--- a/drivers/parisc/gsc.c
+++ b/drivers/parisc/gsc.c
@@ -38,14 +38,14 @@
int gsc_alloc_irq(struct gsc_irq *i)
{
- int irq = txn_alloc_irq();
+ int irq = txn_alloc_irq(GSC_EIM_WIDTH);
if (irq < 0) {
printk("cannot get irq\n");
return irq;
}
i->txn_addr = txn_alloc_addr(irq);
- i->txn_data = txn_alloc_data(irq, GSC_EIM_WIDTH);
+ i->txn_data = txn_alloc_data(irq);
i->irq = irq;
return irq;
@@ -64,7 +64,7 @@ int gsc_claim_irq(struct gsc_irq *i, int irq)
}
i->txn_addr = txn_alloc_addr(irq);
- i->txn_data = txn_alloc_data(irq, GSC_EIM_WIDTH);
+ i->txn_data = txn_alloc_data(irq);
i->irq = irq;
return irq;
@@ -171,12 +171,16 @@ int gsc_assign_irq(struct hw_interrupt_type *type, void *data)
void gsc_asic_assign_irq(struct gsc_asic *asic, int local_irq, int *irqp)
{
- int irq = gsc_assign_irq(&gsc_asic_interrupt_type, asic);
- if (irq == NO_IRQ)
- return;
-
+ int irq = asic->global_irq[local_irq];
+
+ if (irq <= 0) {
+ irq = gsc_assign_irq(&gsc_asic_interrupt_type, asic);
+ if (irq == NO_IRQ)
+ return;
+
+ asic->global_irq[local_irq] = irq;
+ }
*irqp = irq;
- asic->global_irq[local_irq] = irq;
}
void gsc_fixup_irqs(struct parisc_device *parent, void *ctrl,
@@ -198,9 +202,15 @@ void gsc_fixup_irqs(struct parisc_device *parent, void *ctrl,
int gsc_common_setup(struct parisc_device *parent, struct gsc_asic *gsc_asic)
{
struct resource *res;
+ int i;
gsc_asic->gsc = parent;
+ /* Initialise local irq -> global irq mapping */
+ for (i = 0; i < 32; i++) {
+ gsc_asic->global_irq[i] = NO_IRQ;
+ }
+
/* allocate resource region */
res = request_mem_region(gsc_asic->hpa, 0x100000, gsc_asic->name);
if (res) {
diff --git a/drivers/parisc/hppb.c b/drivers/parisc/hppb.c
index 8bda8bb50815d..e869c6020370a 100644
--- a/drivers/parisc/hppb.c
+++ b/drivers/parisc/hppb.c
@@ -16,7 +16,6 @@
**
*/
-#include <linux/config.h>
#include <linux/types.h>
#include <linux/init.h>
#include <linux/mm.h>
diff --git a/drivers/parisc/iosapic.c b/drivers/parisc/iosapic.c
index 7252d5c9ad818..91df0bf181ddf 100644
--- a/drivers/parisc/iosapic.c
+++ b/drivers/parisc/iosapic.c
@@ -158,31 +158,9 @@
#ifdef DEBUG_IOSAPIC
-static char assert_buf[128];
-
-static int
-assert_failed (char *a, char *f, int l)
-{
- sprintf(assert_buf,
- "ASSERT(%s) failed!\nline %d in %s\n",
- a, /* assertion text */
- l, /* line number */
- f); /* file name */
- panic(assert_buf);
- return 0;
-}
-
-#undef ASSERT
-#define ASSERT(EX) { if (!(EX)) assert_failed(# EX, __FILE__, __LINE__); }
-
#define DBG(x...) printk(x)
-
#else /* DEBUG_IOSAPIC */
-
#define DBG(x...)
-#undef ASSERT
-#define ASSERT(EX)
-
#endif /* DEBUG_IOSAPIC */
#ifdef DEBUG_IOSAPIC_IRT
@@ -191,6 +169,12 @@ assert_failed (char *a, char *f, int l)
#define DBG_IRT(x...)
#endif
+#ifdef CONFIG_64BIT
+#define COMPARE_IRTE_ADDR(irte, hpa) ((irte)->dest_iosapic_addr == (hpa))
+#else
+#define COMPARE_IRTE_ADDR(irte, hpa) \
+ ((irte)->dest_iosapic_addr == ((hpa) | 0xffffffff00000000ULL))
+#endif
#define IOSAPIC_REG_SELECT 0x00
#define IOSAPIC_REG_WINDOW 0x10
@@ -201,33 +185,18 @@ assert_failed (char *a, char *f, int l)
#define IOSAPIC_IRDT_ENTRY(idx) (0x10+(idx)*2)
#define IOSAPIC_IRDT_ENTRY_HI(idx) (0x11+(idx)*2)
-static inline unsigned int iosapic_read(unsigned long iosapic, unsigned int reg)
+static inline unsigned int iosapic_read(void __iomem *iosapic, unsigned int reg)
{
writel(reg, iosapic + IOSAPIC_REG_SELECT);
return readl(iosapic + IOSAPIC_REG_WINDOW);
}
-static inline void iosapic_write(unsigned long iosapic, unsigned int reg, u32 val)
+static inline void iosapic_write(void __iomem *iosapic, unsigned int reg, u32 val)
{
writel(reg, iosapic + IOSAPIC_REG_SELECT);
writel(val, iosapic + IOSAPIC_REG_WINDOW);
}
-/*
-** GFP_KERNEL includes __GFP_WAIT flag and that may not
-** be acceptable. Since this is boot time, we shouldn't have
-** to wait ever and this code should (will?) never get called
-** from the interrrupt context.
-*/
-#define IOSAPIC_KALLOC(a_type, cnt) \
- (a_type *) kmalloc(sizeof(a_type)*(cnt), GFP_KERNEL)
-#define IOSAPIC_FREE(addr, f_type, cnt) kfree((void *)addr)
-
-
-#define IOSAPIC_LOCK(lck) spin_lock_irqsave(lck, irqflags)
-#define IOSAPIC_UNLOCK(lck) spin_unlock_irqrestore(lck, irqflags)
-
-
#define IOSAPIC_VERSION_MASK 0x000000ff
#define IOSAPIC_VERSION(ver) ((int) (ver & IOSAPIC_VERSION_MASK))
@@ -265,52 +234,64 @@ static inline void iosapic_eoi(void __iomem *addr, unsigned int data)
static struct irt_entry *irt_cell;
static size_t irt_num_entry;
+static struct irt_entry *iosapic_alloc_irt(int num_entries)
+{
+ unsigned long a;
+ /* The IRT needs to be 8-byte aligned for the PDC call.
+ * Normally kmalloc would guarantee larger alignment, but
+ * if CONFIG_DEBUG_SLAB is enabled, then we can get only
+ * 4-byte alignment on 32-bit kernels
+ */
+ a = (unsigned long)kmalloc(sizeof(struct irt_entry) * num_entries + 8, GFP_KERNEL);
+ a = (a + 7) & ~7;
+ return (struct irt_entry *)a;
+}
-/*
-** iosapic_load_irt
-**
-** The "Get PCI INT Routing Table Size" option returns the number of
-** entries in the PCI interrupt routing table for the cell specified
-** in the cell_number argument. The cell number must be for a cell
-** within the caller's protection domain.
-**
-** The "Get PCI INT Routing Table" option returns, for the cell
-** specified in the cell_number argument, the PCI interrupt routing
-** table in the caller allocated memory pointed to by mem_addr.
-** We assume the IRT only contains entries for I/O SAPIC and
-** calculate the size based on the size of I/O sapic entries.
-**
-** The PCI interrupt routing table entry format is derived from the
-** IA64 SAL Specification 2.4. The PCI interrupt routing table defines
-** the routing of PCI interrupt signals between the PCI device output
-** "pins" and the IO SAPICs' input "lines" (including core I/O PCI
-** devices). This table does NOT include information for devices/slots
-** behind PCI to PCI bridges. See PCI to PCI Bridge Architecture Spec.
-** for the architected method of routing of IRQ's behind PPB's.
-*/
+/**
+ * iosapic_load_irt - Fill in the interrupt routing table
+ * @cell_num: The cell number of the CPU we're currently executing on
+ * @irt: The address to place the new IRT at
+ * @return The number of entries found
+ *
+ * The "Get PCI INT Routing Table Size" option returns the number of
+ * entries in the PCI interrupt routing table for the cell specified
+ * in the cell_number argument. The cell number must be for a cell
+ * within the caller's protection domain.
+ *
+ * The "Get PCI INT Routing Table" option returns, for the cell
+ * specified in the cell_number argument, the PCI interrupt routing
+ * table in the caller allocated memory pointed to by mem_addr.
+ * We assume the IRT only contains entries for I/O SAPIC and
+ * calculate the size based on the size of I/O sapic entries.
+ *
+ * The PCI interrupt routing table entry format is derived from the
+ * IA64 SAL Specification 2.4. The PCI interrupt routing table defines
+ * the routing of PCI interrupt signals between the PCI device output
+ * "pins" and the IO SAPICs' input "lines" (including core I/O PCI
+ * devices). This table does NOT include information for devices/slots
+ * behind PCI to PCI bridges. See PCI to PCI Bridge Architecture Spec.
+ * for the architected method of routing of IRQ's behind PPB's.
+ */
-static int __init /* return number of entries as success/fail flag */
+static int __init
iosapic_load_irt(unsigned long cell_num, struct irt_entry **irt)
{
long status; /* PDC return value status */
struct irt_entry *table; /* start of interrupt routing tbl */
unsigned long num_entries = 0UL;
- ASSERT(NULL != irt);
+ BUG_ON(!irt);
if (is_pdc_pat()) {
-
/* Use pat pdc routine to get interrupt routing table size */
DBG("calling get_irt_size (cell %ld)\n", cell_num);
status = pdc_pat_get_irt_size(&num_entries, cell_num);
DBG("get_irt_size: %ld\n", status);
- ASSERT(status == PDC_OK);
-
- /* save the number of entries in the table */
- ASSERT(0UL != num_entries);
+ BUG_ON(status != PDC_OK);
+ BUG_ON(num_entries == 0);
/*
** allocate memory for interrupt routing table
@@ -318,45 +299,47 @@ iosapic_load_irt(unsigned long cell_num, struct irt_entry **irt)
** the contents of the table are exclusively
** for I/O sapic devices.
*/
- table = IOSAPIC_KALLOC(struct irt_entry, num_entries);
+ table = iosapic_alloc_irt(num_entries);
if (table == NULL) {
- printk(KERN_WARNING MODULE_NAME ": read_irt : can not alloc mem for IRT\n");
+ printk(KERN_WARNING MODULE_NAME ": read_irt : can "
+ "not alloc mem for IRT\n");
return 0;
}
/* get PCI INT routing table */
status = pdc_pat_get_irt(table, cell_num);
DBG("pdc_pat_get_irt: %ld\n", status);
- ASSERT(status == PDC_OK);
+ WARN_ON(status != PDC_OK);
} else {
/*
** C3000/J5000 (and similar) platforms with Sprockets PDC
** will return exactly one IRT for all iosapics.
** So if we have one, don't need to get it again.
*/
- if (NULL != irt_cell)
+ if (irt_cell)
return 0;
/* Should be using the Elroy's HPA, but it's ignored anyway */
status = pdc_pci_irt_size(&num_entries, 0);
DBG("pdc_pci_irt_size: %ld\n", status);
- if (PDC_OK != status) {
+ if (status != PDC_OK) {
/* Not a "legacy" system with I/O SAPIC either */
return 0;
}
- ASSERT(0UL != num_entries);
+ BUG_ON(num_entries == 0);
- table = IOSAPIC_KALLOC(struct irt_entry, num_entries);
- if (table == NULL) {
- printk(KERN_WARNING MODULE_NAME ": read_irt : can not alloc mem for IRT\n");
+ table = iosapic_alloc_irt(num_entries);
+ if (!table) {
+ printk(KERN_WARNING MODULE_NAME ": read_irt : can "
+ "not alloc mem for IRT\n");
return 0;
}
/* HPA ignored by this call too. */
status = pdc_pci_irt(num_entries, 0, table);
- ASSERT(PDC_OK == status);
+ BUG_ON(status != PDC_OK);
}
/* return interrupt table address */
@@ -390,16 +373,10 @@ iosapic_load_irt(unsigned long cell_num, struct irt_entry **irt)
-void __init
-iosapic_init(void)
+void __init iosapic_init(void)
{
unsigned long cell = 0;
- /* init global data */
- spin_lock_init(&iosapic_lock);
- iosapic_list = (struct iosapic_info *) NULL;
- iosapic_count = 0;
-
DBG("iosapic_init()\n");
#ifdef __LP64__
@@ -414,11 +391,9 @@ iosapic_init(void)
}
#endif
- /*
- ** get IRT for this cell.
- */
- irt_num_entry = iosapic_load_irt(cell, &irt_cell);
- if (0 == irt_num_entry)
+ /* get interrupt routing table for this cell */
+ irt_num_entry = iosapic_load_irt(cell, &irt_cell);
+ if (irt_num_entry == 0)
irt_cell = NULL; /* old PDC w/o iosapic */
}
@@ -459,10 +434,7 @@ irt_find_irqline(struct iosapic_info *isi, u8 slot, u8 intr_pin)
continue;
}
- /*
- ** Compare: dest_iosapic_addr, src_bus_irq_devno
- */
- if (i->dest_iosapic_addr != (u64) ((long) isi->isi_hpa))
+ if (!COMPARE_IRTE_ADDR(i, isi->isi_hpa))
continue;
if ((i->src_bus_irq_devno & IRT_IRQ_DEVNO_MASK) != irq_devno)
@@ -506,10 +478,10 @@ iosapic_xlate_pin(struct iosapic_info *isi, struct pci_dev *pcidev)
pci_read_config_byte(pcidev, PCI_INTERRUPT_PIN, &intr_pin);
- DBG_IRT("iosapic_xlate_pin() SLOT %d pin %d\n",
- PCI_SLOT(pcidev->devfn), intr_pin);
+ DBG_IRT("iosapic_xlate_pin(%s) SLOT %d pin %d\n",
+ pcidev->slot_name, PCI_SLOT(pcidev->devfn), intr_pin);
- if (0 == intr_pin) {
+ if (intr_pin == 0) {
/* The device does NOT support/use IRQ lines. */
return NULL;
}
@@ -606,7 +578,6 @@ iosapic_set_irt_data( struct vector_info *vi, u32 *dp0, u32 *dp1)
{
u32 mode = 0;
struct irt_entry *p = vi->irte;
- ASSERT(NULL != vi->irte);
if ((p->polarity_trigger & IRT_PO_MASK) == IRT_ACTIVE_LO)
mode |= IOSAPIC_IRDT_PO_LOW;
@@ -619,7 +590,6 @@ iosapic_set_irt_data( struct vector_info *vi, u32 *dp0, u32 *dp1)
** PA doesn't support EXTINT or LPRIO bits.
*/
- ASSERT(vi->txn_data);
*dp0 = mode | (u32) vi->txn_data;
/*
@@ -802,22 +772,23 @@ int iosapic_fixup_irq(void *isi_obj, struct pci_dev *pcidev)
vi->irte = irte;
- /* Allocate processor IRQ */
- vi->txn_irq = txn_alloc_irq();
-
/*
+ * Allocate processor IRQ
+ *
* XXX/FIXME The txn_alloc_irq() code and related code should be
* moved to enable_irq(). That way we only allocate processor IRQ
* bits for devices that actually have drivers claiming them.
* Right now we assign an IRQ to every PCI device present,
* regardless of whether it's used or not.
*/
+ vi->txn_irq = txn_alloc_irq(8);
+
if (vi->txn_irq < 0)
panic("I/O sapic: couldn't get TXN IRQ\n");
/* enable_irq() will use txn_* to program IRdT */
vi->txn_addr = txn_alloc_addr(vi->txn_irq);
- vi->txn_data = txn_alloc_data(vi->txn_irq, 8);
+ vi->txn_data = txn_alloc_data(vi->txn_irq);
vi->eoi_addr = isi->addr + IOSAPIC_REG_EOI;
vi->eoi_data = cpu_to_le32(vi->txn_data);
@@ -841,10 +812,7 @@ int iosapic_fixup_irq(void *isi_obj, struct pci_dev *pcidev)
static unsigned int
iosapic_rd_version(struct iosapic_info *isi)
{
- ASSERT(isi);
- ASSERT(isi->isi_hpa);
-
- return iosapic_read(isi->isi_hpa, IOSAPIC_REG_VERSION);
+ return iosapic_read(isi->addr, IOSAPIC_REG_VERSION);
}
@@ -866,44 +834,38 @@ void *iosapic_register(unsigned long hpa)
int cnt; /* track how many entries we've looked at */
/*
- ** Astro based platforms can't support PCI OLARD if they
- ** implement the legacy PDC (not PAT). Though Legacy PDC
- ** supports an IRT, LBA's with no device under them
- ** are *not* listed in the IRT.
- ** Search the IRT and ignore iosapic's which aren't
- ** in the IRT.
- */
- ASSERT(NULL != irte); /* always have built-in devices */
+ * Astro based platforms can only support PCI OLARD if they implement
+ * PAT PDC. Legacy PDC omits LBAs with no PCI devices from the IRT.
+ * Search the IRT and ignore iosapic's which aren't in the IRT.
+ */
for (cnt=0; cnt < irt_num_entry; cnt++, irte++) {
- ASSERT(IRT_IOSAPIC_TYPE == irte->entry_type);
- /*
- ** We need sign extension of the hpa on 32-bit kernels.
- ** The address in the IRT is *always* 64 bit and really
- ** is an unsigned quantity (like all physical addresses).
- */
- if (irte->dest_iosapic_addr == (s64) ((long) hpa))
+ WARN_ON(IRT_IOSAPIC_TYPE != irte->entry_type);
+ if (COMPARE_IRTE_ADDR(irte, hpa))
break;
}
- if (cnt >= irt_num_entry)
- return (NULL);
+ if (cnt >= irt_num_entry) {
+ DBG("iosapic_register() ignoring 0x%lx (NOT FOUND)\n", hpa);
+ return NULL;
+ }
- if ((isi = IOSAPIC_KALLOC(struct iosapic_info, 1)) == NULL) {
+ isi = (struct iosapic_info *)kmalloc(sizeof(struct iosapic_info), GFP_KERNEL);
+ if (!isi) {
BUG();
- return (NULL);
+ return NULL;
}
memset(isi, 0, sizeof(struct iosapic_info));
- isi->isi_hpa = hpa;
- isi->isi_version = iosapic_rd_version(isi);
+ isi->addr = ioremap(hpa, 4096);
+ isi->isi_hpa = hpa;
+ isi->isi_version = iosapic_rd_version(isi);
isi->isi_num_vectors = IOSAPIC_IRDT_MAX_ENTRY(isi->isi_version) + 1;
- vip = isi->isi_vector =
- IOSAPIC_KALLOC(struct vector_info, isi->isi_num_vectors);
-
+ vip = isi->isi_vector = (struct vector_info *)
+ kmalloc(sizeof(struct vector_info) * isi->isi_num_vectors, GFP_KERNEL);
if (vip == NULL) {
- IOSAPIC_FREE(isi, struct iosapic_info, 1);
+ kfree(isi);
return NULL;
}
@@ -924,7 +886,6 @@ iosapic_prt_irt(void *irt, long num_entry)
{
unsigned int i, *irp = (unsigned int *) irt;
- ASSERT(NULL != irt);
printk(KERN_DEBUG MODULE_NAME ": Interrupt Routing Table (%lx entries)\n", num_entry);
@@ -938,8 +899,6 @@ iosapic_prt_irt(void *irt, long num_entry)
static void
iosapic_prt_vi(struct vector_info *vi)
{
- ASSERT(NULL != vi);
-
printk(KERN_DEBUG MODULE_NAME ": vector_info[%d] is at %p\n", vi->irqline, vi);
printk(KERN_DEBUG "\t\tstatus: %.4x\n", vi->status);
printk(KERN_DEBUG "\t\ttxn_irq: %d\n", vi->txn_irq);
@@ -953,10 +912,9 @@ iosapic_prt_vi(struct vector_info *vi)
static void
iosapic_prt_isi(struct iosapic_info *isi)
{
- ASSERT(NULL != isi);
printk(KERN_DEBUG MODULE_NAME ": io_sapic_info at %p\n", isi);
printk(KERN_DEBUG "\t\tisi_hpa: %lx\n", isi->isi_hpa);
- printk(KERN_DEBUG "\t\tisi_status: %x\n", isi->isi_status);
+ printk(KERN_DEBUG "\t\tisi_status: %x\n", isi->isi_status);
printk(KERN_DEBUG "\t\tisi_version: %x\n", isi->isi_version);
printk(KERN_DEBUG "\t\tisi_vector: %p\n", isi->isi_vector);
}
diff --git a/drivers/parisc/lasi.c b/drivers/parisc/lasi.c
index 61969d2c3c498..7318550533929 100644
--- a/drivers/parisc/lasi.c
+++ b/drivers/parisc/lasi.c
@@ -139,7 +139,7 @@ void __init lasi_led_init(unsigned long lasi_hpa)
break;
}
- register_led_driver(DISPLAY_MODEL_LASI, LED_CMD_REG_NONE, (char *)datareg);
+ register_led_driver(DISPLAY_MODEL_LASI, LED_CMD_REG_NONE, datareg);
}
#endif
diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c
index 8d1aa30f188d9..dc838804c0dda 100644
--- a/drivers/parisc/lba_pci.c
+++ b/drivers/parisc/lba_pci.c
@@ -51,11 +51,6 @@
#include <asm/iosapic.h> /* for iosapic_register() */
#include <asm/io.h> /* read/write stuff */
-#ifndef TRUE
-#define TRUE (1 == 1)
-#define FALSE (1 == 0)
-#endif
-
#undef DEBUG_LBA /* general stuff */
#undef DEBUG_LBA_PORT /* debug I/O Port access */
#undef DEBUG_LBA_CFG /* debug Config Space Access (ie PCI Bus walk) */
@@ -88,18 +83,6 @@
#define DBG_PAT(x...)
#endif
-#ifdef DEBUG_LBA
-#undef ASSERT
-#define ASSERT(expr) \
- if(!(expr)) { \
- printk("\n%s:%d: Assertion " #expr " failed!\n", \
- __FILE__, __LINE__); \
- panic(#expr); \
- }
-#else
-#define ASSERT(expr)
-#endif
-
/*
** Config accessor functions only pass in the 8-bit bus number and not
@@ -184,6 +167,7 @@
/* non-postable I/O port space, densely packed */
#define LBA_PORT_BASE (PCI_F_EXTEND | 0xfee00000UL)
+static void __iomem *astro_iop_base;
#define ELROY_HVERS 0x782
#define MERCURY_HVERS 0x783
@@ -214,8 +198,8 @@ struct lba_device {
spinlock_t lba_lock;
void *iosapic_obj;
-#ifdef CONFIG_PARISC64
- unsigned long iop_base; /* PA_VIEW - for IO port accessor funcs */
+#ifdef CONFIG_64BIT
+ void __iomem * iop_base; /* PA_VIEW - for IO port accessor funcs */
#endif
int flags; /* state/functionality enabled */
@@ -225,15 +209,9 @@ struct lba_device {
static u32 lba_t32;
-/*
-** lba "flags"
-*/
-#define LBA_FLAG_NO_DMA_DURING_CFG 0x01
+/* lba flags */
#define LBA_FLAG_SKIP_PROBE 0x10
-/* Tape Release 4 == hw_rev 5 */
-#define LBA_TR4PLUS(d) ((d)->hw_rev > 0x4)
-#define LBA_DMA_DURING_CFG_DISABLED(d) ((d)->flags & LBA_FLAG_NO_DMA_DURING_CFG)
#define LBA_SKIP_PROBE(d) ((d)->flags & LBA_FLAG_SKIP_PROBE)
@@ -293,7 +271,7 @@ lba_dump_res(struct resource *r, int d)
printk(KERN_DEBUG "(%p)", r->parent);
for (i = d; i ; --i) printk(" ");
- printk(KERN_DEBUG "%p [%lx,%lx]/%x\n", r, r->start, r->end, (int) r->flags);
+ printk(KERN_DEBUG "%p [%lx,%lx]/%lx\n", r, r->start, r->end, r->flags);
lba_dump_res(r->child, d+2);
lba_dump_res(r->sibling, d);
}
@@ -303,7 +281,7 @@ lba_dump_res(struct resource *r, int d)
** LBA rev 2.0, 2.1, 2.2, and 3.0 bus walks require a complex
** workaround for cfg cycles:
** -- preserve LBA state
-** -- LBA_FLAG_NO_DMA_DURING_CFG workaround
+** -- prevent any DMA from occurring
** -- turn on smart mode
** -- probe with config writes before doing config reads
** -- check ERROR_STATUS
@@ -313,25 +291,18 @@ lba_dump_res(struct resource *r, int d)
** The workaround is only used for device discovery.
*/
-static int
-lba_device_present( u8 bus, u8 dfn, struct lba_device *d)
+static int lba_device_present(u8 bus, u8 dfn, struct lba_device *d)
{
u8 first_bus = d->hba.hba_bus->secondary;
u8 last_sub_bus = d->hba.hba_bus->subordinate;
- ASSERT(bus >= first_bus);
- ASSERT(bus <= last_sub_bus);
- ASSERT((bus - first_bus) < LBA_MAX_NUM_BUSES);
-
if ((bus < first_bus) ||
(bus > last_sub_bus) ||
- ((bus - first_bus) >= LBA_MAX_NUM_BUSES))
- {
- /* devices that fall into any of these cases won't get claimed */
- return(FALSE);
+ ((bus - first_bus) >= LBA_MAX_NUM_BUSES)) {
+ return 0;
}
- return TRUE;
+ return 1;
}
@@ -346,7 +317,6 @@ lba_device_present( u8 bus, u8 dfn, struct lba_device *d)
/* For LBA rev 2.0, 2.1, 2.2, and 3.0, we must disable DMA \
** arbitration for full bus walks. \
*/ \
- if (LBA_DMA_DURING_CFG_DISABLED(d)) { \
/* Save contents of arb mask register. */ \
arb_mask = READ_REG32(d->hba.base_addr + LBA_ARB_MASK); \
\
@@ -354,8 +324,7 @@ lba_device_present( u8 bus, u8 dfn, struct lba_device *d)
* Turn off all device arbitration bits (i.e. everything \
* except arbitration enable bit). \
*/ \
- WRITE_REG32(0x1, d->hba.base_addr + LBA_ARB_MASK); \
- } \
+ WRITE_REG32(0x1, d->hba.base_addr + LBA_ARB_MASK); \
\
/* \
* Set the smart mode bit so that master aborts don't cause \
@@ -375,7 +344,7 @@ lba_device_present( u8 bus, u8 dfn, struct lba_device *d)
* Read address register to ensure that LBA is the bus master, \
* which implies that DMA traffic has stopped when DMA arb is off. \
*/ \
- lba_t32 = READ_REG32((d)->hba.base_addr + LBA_PCI_CFG_ADDR); \
+ lba_t32 = READ_REG32((d)->hba.base_addr + LBA_PCI_CFG_ADDR); \
/* \
* Generate a cfg write cycle (will have no affect on \
* Vendor ID register since read-only). \
@@ -385,7 +354,7 @@ lba_device_present( u8 bus, u8 dfn, struct lba_device *d)
* Make sure write has completed before proceeding further, \
* i.e. before setting clear enable. \
*/ \
- lba_t32 = READ_REG32((d)->hba.base_addr + LBA_PCI_CFG_ADDR); \
+ lba_t32 = READ_REG32((d)->hba.base_addr + LBA_PCI_CFG_ADDR); \
}
@@ -439,20 +408,16 @@ lba_device_present( u8 bus, u8 dfn, struct lba_device *d)
} \
}
-#define LBA_CFG_TR4_ADDR_SETUP(d, addr) \
- WRITE_REG32(((addr) & ~3), (d)->hba.base_addr + LBA_PCI_CFG_ADDR); \
- lba_t32 = READ_REG32((d)->hba.base_addr + LBA_PCI_CFG_ADDR)
+#define LBA_CFG_TR4_ADDR_SETUP(d, addr) \
+ WRITE_REG32(((addr) & ~3), (d)->hba.base_addr + LBA_PCI_CFG_ADDR);
-#define LBA_CFG_ADDR_SETUP(d, addr) { \
+#define LBA_CFG_ADDR_SETUP(d, addr) { \
WRITE_REG32(((addr) & ~3), (d)->hba.base_addr + LBA_PCI_CFG_ADDR); \
/* \
- * HPREVISIT: \
- * -- Potentially could skip this once DMA bug fixed. \
- * \
* Read address register to ensure that LBA is the bus master, \
* which implies that DMA traffic has stopped when DMA arb is off. \
*/ \
- lba_t32 = READ_REG32((d)->hba.base_addr + LBA_PCI_CFG_ADDR); \
+ lba_t32 = READ_REG32((d)->hba.base_addr + LBA_PCI_CFG_ADDR); \
}
@@ -465,12 +430,10 @@ lba_device_present( u8 bus, u8 dfn, struct lba_device *d)
* Restore error config register (turn off smart mode). \
*/ \
WRITE_REG32(error_config, base + LBA_ERROR_CONFIG); \
- if (LBA_DMA_DURING_CFG_DISABLED(d)) { \
/* \
* Restore arb mask register (reenables DMA arbitration). \
*/ \
WRITE_REG32(arb_mask, base + LBA_ARB_MASK); \
- } \
}
@@ -478,39 +441,23 @@ lba_device_present( u8 bus, u8 dfn, struct lba_device *d)
static unsigned int
lba_rd_cfg(struct lba_device *d, u32 tok, u8 reg, u32 size)
{
- u32 data = ~0;
+ u32 data = ~0U;
int error = 0;
u32 arb_mask = 0; /* used by LBA_CFG_SETUP/RESTORE */
u32 error_config = 0; /* used by LBA_CFG_SETUP/RESTORE */
u32 status_control = 0; /* used by LBA_CFG_SETUP/RESTORE */
- ASSERT((size == sizeof(u8)) ||
- (size == sizeof(u16)) ||
- (size == sizeof(u32)));
-
- if ((size != sizeof(u8)) &&
- (size != sizeof(u16)) &&
- (size != sizeof(u32))) {
- return(data);
- }
-
LBA_CFG_SETUP(d, tok);
LBA_CFG_PROBE(d, tok);
LBA_CFG_MASTER_ABORT_CHECK(d, d->hba.base_addr, tok, error);
if (!error) {
+ void __iomem *data_reg = d->hba.base_addr + LBA_PCI_CFG_DATA;
+
LBA_CFG_ADDR_SETUP(d, tok | reg);
switch (size) {
- case sizeof(u8):
- data = (u32) READ_REG8(d->hba.base_addr + LBA_PCI_CFG_DATA + (reg & 3));
- break;
- case sizeof(u16):
- data = (u32) READ_REG16(d->hba.base_addr + LBA_PCI_CFG_DATA + (reg & 2));
- break;
- case sizeof(u32):
- data = READ_REG32(d->hba.base_addr + LBA_PCI_CFG_DATA);
- break;
- default:
- break; /* leave data as -1 */
+ case 1: data = (u32) READ_REG8(data_reg + (reg & 3)); break;
+ case 2: data = (u32) READ_REG16(data_reg+ (reg & 2)); break;
+ case 4: data = READ_REG32(data_reg); break;
}
}
LBA_CFG_RESTORE(d, d->hba.base_addr);
@@ -518,142 +465,26 @@ lba_rd_cfg(struct lba_device *d, u32 tok, u8 reg, u32 size)
}
-#if USE_PAT_PDC_CFG
-
-/* PAT PDC needs to be relocated in order to perform properly.
- * tg3 driver does about 1600 PCI Cfg writes to initialize the card.
- * On 440Mhz A500, PDC takes ~20ms/write, or ~30 seconds per card.
- * On PA8800, that takes about 5ms/write (8 seconds).
- * But relocating PDC will burn at least 4MB of RAM.
- * Easier/Cheaper to just maintain our own mercury cfg ops.
- */
-#define pat_cfg_addr(bus, devfn, addr) (((bus) << 16) | ((devfn) << 8) | (addr))
-
-static int pat_cfg_read(struct pci_bus *bus, unsigned int devfn, int pos, int size, u32 *data)
-{
- int tok = pat_cfg_addr(bus->number, devfn, pos);
- u32 tmp;
- int ret = pdc_pat_io_pci_cfg_read(tok, size, &tmp);
-
- DBG_CFG("%s(%d:%d.%d+0x%02x) -> 0x%x %d\n", __FUNCTION__, bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn), pos, tmp, ret);
-
- switch (size) {
- case 1: *data = (u8) tmp; return (tmp == (u8) ~0);
- case 2: *data = (u16) tmp; return (tmp == (u16) ~0);
- case 4: *data = (u32) tmp; return (tmp == (u32) ~0);
- }
- *data = ~0;
- return (ret);
-}
-
-static int pat_cfg_write(struct pci_bus *bus, unsigned int devfn, int pos, int size, u32 data)
-{
- int tok = pat_cfg_addr(bus->number, devfn, pos);
- int ret = pdc_pat_io_pci_cfg_write(tok, size, data);
-
- DBG_CFG("%s(%d:%d.%d+0x%02x, 0x%lx/%d)\n", __FUNCTION__, bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn), pos, data, size);
- return (ret);
-}
-
-static struct pci_ops pat_cfg_ops = {
- .read = pat_cfg_read,
- .write = pat_cfg_write,
-};
-#endif
-
-
-#ifdef CONFIG_PARISC64
-static int mercury_cfg_read(struct pci_bus *bus, unsigned int devfn, int pos, int size, u32 *data)
+static int elroy_cfg_read(struct pci_bus *bus, unsigned int devfn, int pos, int size, u32 *data)
{
struct lba_device *d = LBA_DEV(parisc_walk_tree(bus->bridge));
u32 local_bus = (bus->parent == NULL) ? 0 : bus->secondary;
u32 tok = LBA_CFG_TOK(local_bus, devfn);
+ void __iomem *data_reg = d->hba.base_addr + LBA_PCI_CFG_DATA;
- /* Basic Algorithm
- ** Should only get here on fully working LBA rev.
- ** This is how simple the original LBA code should have been.
- */
- LBA_CFG_TR4_ADDR_SETUP(d, tok | pos);
- switch(size) {
- case 1: *(u8 *) data = READ_REG8(d->hba.base_addr + LBA_PCI_CFG_DATA
- + (pos & 3));
- DBG_CFG("%s(%x+%2x) -> 0x%x (c)\n", __FUNCTION__, tok, pos,
- *(u8 *)data);
- return(*(u8 *)data == (u8) ~0U);
- case 2: *(u16 *) data = READ_REG16(d->hba.base_addr + LBA_PCI_CFG_DATA
- + (pos & 2));
- DBG_CFG("%s(%x+%2x) -> 0x%x (c)\n", __FUNCTION__, tok, pos,
- *(u16 *)data);
- return(*(u16 *)data == (u16) ~0U);
- case 4: *(u32 *) data = READ_REG32(d->hba.base_addr + LBA_PCI_CFG_DATA);
- DBG_CFG("%s(%x+%2x) -> 0x%x (c)\n", __FUNCTION__, tok, pos, *data);
- return(*data == ~0U);
- }
- DBG_CFG("%s(%x+%2x) -> bad size (%d)\n", __FUNCTION__, tok, pos, size);
- *data = ~0U;
- return(!PCIBIOS_SUCCESSFUL); /* failed */
-}
-
-/*
- * LBA 4.0 config write code implements non-postable semantics
- * by doing a read of CONFIG ADDR after the write.
- */
-
-static int mercury_cfg_write(struct pci_bus *bus, unsigned int devfn, int pos, int size, u32 data)
-{
- struct lba_device *d = LBA_DEV(parisc_walk_tree(bus->bridge));
- unsigned long data_reg = d->hba.base_addr + LBA_PCI_CFG_DATA;
- u32 local_bus = (bus->parent == NULL) ? 0 : bus->secondary;
- u32 tok = LBA_CFG_TOK(local_bus,devfn);
-
- ASSERT((tok & 0xff) == 0);
- ASSERT(pos < 0x100);
-
- DBG_CFG("%s(%x+%2x) <- 0x%x (c)\n", __FUNCTION__, tok, pos, data);
-
- /* Basic Algorithm */
- LBA_CFG_TR4_ADDR_SETUP(d, tok | pos);
- switch(size) {
- case 1: WRITE_REG8 (data, data_reg + (pos & 3)); break;
- case 2: WRITE_REG16(data, data_reg + (pos & 2)); break;
- case 4: WRITE_REG32(data, data_reg); break;
- default:
- DBG_CFG("%s(%x+%2x) WTF! size %d\n", __FUNCTION__, tok, pos,
- size);
- }
-
- /* flush posted write */
- lba_t32 = READ_U32(d->hba.base_addr + LBA_PCI_CFG_ADDR);
- return PCIBIOS_SUCCESSFUL;
-}
-
-
-static struct pci_ops mercury_cfg_ops = {
- .read = mercury_cfg_read,
- .write = mercury_cfg_write,
-};
-#else
-#define mercury_cfg_ops lba_cfg_ops
-#endif /* CONFIG_PARISC64 */
-
-
-static int lba_cfg_read(struct pci_bus *bus, unsigned int devfn, int pos, int size, u32 *data)
-{
- struct lba_device *d = LBA_DEV(parisc_walk_tree(bus->bridge));
- u32 local_bus = (bus->parent == NULL) ? 0 : bus->secondary;
- u32 tok = LBA_CFG_TOK(local_bus, devfn);
+ if ((pos > 255) || (devfn > 255))
+ return -EINVAL;
/* FIXME: B2K/C3600 workaround is always use old method... */
- /* if (!LBA_TR4PLUS(d) && !LBA_SKIP_PROBE(d)) */ {
+ /* if (!LBA_SKIP_PROBE(d)) */ {
/* original - Generate config cycle on broken elroy
with risk we will miss PCI bus errors. */
*data = lba_rd_cfg(d, tok, pos, size);
DBG_CFG("%s(%x+%2x) -> 0x%x (a)\n", __FUNCTION__, tok, pos, *data);
- return(*data == ~0U);
+ return 0;
}
- if (LBA_SKIP_PROBE(d) && (!lba_device_present(bus->secondary, devfn, d)))
- {
+ if (LBA_SKIP_PROBE(d) && !lba_device_present(bus->secondary, devfn, d)) {
DBG_CFG("%s(%x+%2x) -> -1 (b)\n", __FUNCTION__, tok, pos);
/* either don't want to look or know device isn't present. */
*data = ~0U;
@@ -664,52 +495,32 @@ static int lba_cfg_read(struct pci_bus *bus, unsigned int devfn, int pos, int si
** Should only get here on fully working LBA rev.
** This is how simple the code should have been.
*/
- LBA_CFG_TR4_ADDR_SETUP(d, tok | pos);
+ LBA_CFG_ADDR_SETUP(d, tok | pos);
switch(size) {
- case 1: *(u8 *) data = READ_REG8(d->hba.base_addr + LBA_PCI_CFG_DATA + (pos & 3));
- break;
- case 2: *(u16 *) data = READ_REG16(d->hba.base_addr + LBA_PCI_CFG_DATA + (pos & 2));
- break;
- case 4: *(u32 *) data = READ_REG32(d->hba.base_addr + LBA_PCI_CFG_DATA);
- break;
+ case 1: *data = READ_REG8 (data_reg + (pos & 3)); break;
+ case 2: *data = READ_REG16(data_reg + (pos & 2)); break;
+ case 4: *data = READ_REG32(data_reg); break;
}
DBG_CFG("%s(%x+%2x) -> 0x%x (c)\n", __FUNCTION__, tok, pos, *data);
- return(*data == ~0U);
+ return 0;
}
static void
-lba_wr_cfg( struct lba_device *d, u32 tok, u8 reg, u32 data, u32 size)
+lba_wr_cfg(struct lba_device *d, u32 tok, u8 reg, u32 data, u32 size)
{
int error = 0;
u32 arb_mask = 0;
u32 error_config = 0;
u32 status_control = 0;
-
- ASSERT((size == sizeof(u8)) ||
- (size == sizeof(u16)) ||
- (size == sizeof(u32)));
-
- if ((size != sizeof(u8)) &&
- (size != sizeof(u16)) &&
- (size != sizeof(u32))) {
- return;
- }
+ void __iomem *data_reg = d->hba.base_addr + LBA_PCI_CFG_DATA;
LBA_CFG_SETUP(d, tok);
LBA_CFG_ADDR_SETUP(d, tok | reg);
switch (size) {
- case sizeof(u8):
- WRITE_REG8((u8) data, d->hba.base_addr + LBA_PCI_CFG_DATA + (reg&3));
- break;
- case sizeof(u16):
- WRITE_REG16((u8) data, d->hba.base_addr + LBA_PCI_CFG_DATA +(reg&2));
- break;
- case sizeof(u32):
- WRITE_REG32(data, d->hba.base_addr + LBA_PCI_CFG_DATA);
- break;
- default:
- break;
+ case 1: WRITE_REG8 (data, data_reg + (reg & 3)); break;
+ case 2: WRITE_REG16(data, data_reg + (reg & 2)); break;
+ case 4: WRITE_REG32(data, data_reg); break;
}
LBA_CFG_MASTER_ABORT_CHECK(d, d->hba.base_addr, tok, error);
LBA_CFG_RESTORE(d, d->hba.base_addr);
@@ -721,16 +532,16 @@ lba_wr_cfg( struct lba_device *d, u32 tok, u8 reg, u32 data, u32 size)
* by doing a read of CONFIG ADDR after the write.
*/
-static int lba_cfg_write(struct pci_bus *bus, unsigned int devfn, int pos, int size, u32 data)
+static int elroy_cfg_write(struct pci_bus *bus, unsigned int devfn, int pos, int size, u32 data)
{
struct lba_device *d = LBA_DEV(parisc_walk_tree(bus->bridge));
u32 local_bus = (bus->parent == NULL) ? 0 : bus->secondary;
u32 tok = LBA_CFG_TOK(local_bus,devfn);
- ASSERT((tok & 0xff) == 0);
- ASSERT(pos < 0x100);
+ if ((pos > 255) || (devfn > 255))
+ return -EINVAL;
- if (!LBA_TR4PLUS(d) && !LBA_SKIP_PROBE(d)) {
+ if (!LBA_SKIP_PROBE(d)) {
/* Original Workaround */
lba_wr_cfg(d, tok, pos, (u32) data, size);
DBG_CFG("%s(%x+%2x) = 0x%x (a)\n", __FUNCTION__, tok, pos,data);
@@ -745,7 +556,7 @@ static int lba_cfg_write(struct pci_bus *bus, unsigned int devfn, int pos, int s
DBG_CFG("%s(%x+%2x) = 0x%x (c)\n", __FUNCTION__, tok, pos, data);
/* Basic Algorithm */
- LBA_CFG_TR4_ADDR_SETUP(d, tok | pos);
+ LBA_CFG_ADDR_SETUP(d, tok | pos);
switch(size) {
case 1: WRITE_REG8 (data, d->hba.base_addr + LBA_PCI_CFG_DATA + (pos & 3));
break;
@@ -760,9 +571,82 @@ static int lba_cfg_write(struct pci_bus *bus, unsigned int devfn, int pos, int s
}
-static struct pci_ops lba_cfg_ops = {
- .read = lba_cfg_read,
- .write = lba_cfg_write,
+static struct pci_ops elroy_cfg_ops = {
+ .read = elroy_cfg_read,
+ .write = elroy_cfg_write,
+};
+
+/*
+ * The mercury_cfg_ops are slightly misnamed; they're also used for Elroy
+ * TR4.0 as no additional bugs were found in this areea between Elroy and
+ * Mercury
+ */
+
+static int mercury_cfg_read(struct pci_bus *bus, unsigned int devfn, int pos, int size, u32 *data)
+{
+ struct lba_device *d = LBA_DEV(parisc_walk_tree(bus->bridge));
+ u32 local_bus = (bus->parent == NULL) ? 0 : bus->secondary;
+ u32 tok = LBA_CFG_TOK(local_bus, devfn);
+ void __iomem *data_reg = d->hba.base_addr + LBA_PCI_CFG_DATA;
+
+ if ((pos > 255) || (devfn > 255))
+ return -EINVAL;
+
+ LBA_CFG_TR4_ADDR_SETUP(d, tok | pos);
+ switch(size) {
+ case 1:
+ *data = READ_REG8(data_reg + (pos & 3));
+ break;
+ case 2:
+ *data = READ_REG16(data_reg + (pos & 2));
+ break;
+ case 4:
+ *data = READ_REG32(data_reg); break;
+ break;
+ }
+
+ DBG_CFG("mercury_cfg_read(%x+%2x) -> 0x%x\n", tok, pos, *data);
+ return 0;
+}
+
+/*
+ * LBA 4.0 config write code implements non-postable semantics
+ * by doing a read of CONFIG ADDR after the write.
+ */
+
+static int mercury_cfg_write(struct pci_bus *bus, unsigned int devfn, int pos, int size, u32 data)
+{
+ struct lba_device *d = LBA_DEV(parisc_walk_tree(bus->bridge));
+ void __iomem *data_reg = d->hba.base_addr + LBA_PCI_CFG_DATA;
+ u32 local_bus = (bus->parent == NULL) ? 0 : bus->secondary;
+ u32 tok = LBA_CFG_TOK(local_bus,devfn);
+
+ if ((pos > 255) || (devfn > 255))
+ return -EINVAL;
+
+ DBG_CFG("%s(%x+%2x) <- 0x%x (c)\n", __FUNCTION__, tok, pos, data);
+
+ LBA_CFG_TR4_ADDR_SETUP(d, tok | pos);
+ switch(size) {
+ case 1:
+ WRITE_REG8 (data, data_reg + (pos & 3));
+ break;
+ case 2:
+ WRITE_REG16(data, data_reg + (pos & 2));
+ break;
+ case 4:
+ WRITE_REG32(data, data_reg);
+ break;
+ }
+
+ /* flush posted write */
+ lba_t32 = READ_U32(d->hba.base_addr + LBA_PCI_CFG_ADDR);
+ return 0;
+}
+
+static struct pci_ops mercury_cfg_ops = {
+ .read = mercury_cfg_read,
+ .write = mercury_cfg_write,
};
@@ -773,7 +657,7 @@ lba_bios_init(void)
}
-#ifdef CONFIG_PARISC64
+#ifdef CONFIG_64BIT
/*
** Determine if a device is already configured.
@@ -802,11 +686,11 @@ lba_claim_dev_resources(struct pci_dev *dev)
for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
if (dev->resource[i].flags & srch_flags) {
pci_claim_resource(dev, i);
- DBG(" claimed %s %d [%lx,%lx]/%x\n",
+ DBG(" claimed %s %d [%lx,%lx]/%lx\n",
pci_name(dev), i,
dev->resource[i].start,
dev->resource[i].end,
- (int) dev->resource[i].flags
+ dev->resource[i].flags
);
}
}
@@ -835,7 +719,7 @@ lba_fixup_bus(struct pci_bus *bus)
struct lba_device *ldev = LBA_DEV(parisc_walk_tree(bus->bridge));
int lba_portbase = HBA_PORT_BASE(ldev->hba.hba_num);
- DBG("lba_fixup_bus(0x%p) bus %d sysdata 0x%p\n",
+ DBG("lba_fixup_bus(0x%p) bus %d platform_data 0x%p\n",
bus, bus->secondary, bus->bridge->platform_data);
/*
@@ -849,14 +733,14 @@ lba_fixup_bus(struct pci_bus *bus)
/* Host-PCI Bridge */
int err, i;
- DBG("lba_fixup_bus() %s [%lx/%lx]/%x\n",
+ DBG("lba_fixup_bus() %s [%lx/%lx]/%lx\n",
ldev->hba.io_space.name,
ldev->hba.io_space.start, ldev->hba.io_space.end,
- (int) ldev->hba.io_space.flags);
- DBG("lba_fixup_bus() %s [%lx/%lx]/%x\n",
+ ldev->hba.io_space.flags);
+ DBG("lba_fixup_bus() %s [%lx/%lx]/%lx\n",
ldev->hba.lmmio_space.name,
ldev->hba.lmmio_space.start, ldev->hba.lmmio_space.end,
- (int) ldev->hba.lmmio_space.flags);
+ ldev->hba.lmmio_space.flags);
err = request_resource(&ioport_resource, &(ldev->hba.io_space));
if (err < 0) {
@@ -895,7 +779,7 @@ lba_fixup_bus(struct pci_bus *bus)
/* lba_dump_res(&iomem_resource, 2); */
}
-#ifdef CONFIG_PARISC64
+#ifdef CONFIG_64BIT
/* GMMIO is distributed range. Every LBA/Rope gets part it. */
if (ldev->hba.gmmio_space.flags) {
err = request_resource(&iomem_resource, &(ldev->hba.gmmio_space));
@@ -1035,7 +919,7 @@ struct pci_bios_ops lba_bios_ops = {
static u##size lba_astro_in##size (struct pci_hba_data *d, u16 addr) \
{ \
u##size t; \
- t = READ_REG##size(LBA_PORT_BASE + addr); \
+ t = READ_REG##size(astro_iop_base + addr); \
DBG_PORT(" 0x%x\n", t); \
return (t); \
}
@@ -1075,9 +959,8 @@ LBA_PORT_IN(32, 0)
#define LBA_PORT_OUT(size, mask) \
static void lba_astro_out##size (struct pci_hba_data *d, u16 addr, u##size val) \
{ \
- ASSERT(d != NULL); \
DBG_PORT("%s(0x%p, 0x%x, 0x%x)\n", __FUNCTION__, d, addr, val); \
- WRITE_REG##size(val, LBA_PORT_BASE + addr); \
+ WRITE_REG##size(val, astro_iop_base + addr); \
if (LBA_DEV(d)->hw_rev < 3) \
lba_t32 = READ_U32(d->base_addr + LBA_FUNC_ID); \
}
@@ -1097,7 +980,7 @@ static struct pci_port_ops lba_astro_port_ops = {
};
-#ifdef CONFIG_PARISC64
+#ifdef CONFIG_64BIT
#define PIOP_TO_GMMIO(lba, addr) \
((lba)->iop_base + (((addr)&0xFFFC)<<10) + ((addr)&3))
@@ -1215,16 +1098,19 @@ lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev)
case PAT_LMMIO:
/* used to fix up pre-initialized MEM BARs */
if (!lba_dev->hba.lmmio_space.start) {
- sprintf(lba_dev->hba.lmmio_name, "PCI%02x LMMIO",
- (int) lba_dev->hba.bus_num.start);
- lba_dev->hba.lmmio_space_offset = p->start - io->start;
- r = &(lba_dev->hba.lmmio_space);
- r->name = lba_dev->hba.lmmio_name;
+ sprintf(lba_dev->hba.lmmio_name,
+ "PCI%02lx LMMIO",
+ lba_dev->hba.bus_num.start);
+ lba_dev->hba.lmmio_space_offset = p->start -
+ io->start;
+ r = &lba_dev->hba.lmmio_space;
+ r->name = lba_dev->hba.lmmio_name;
} else if (!lba_dev->hba.elmmio_space.start) {
- sprintf(lba_dev->hba.elmmio_name, "PCI%02x ELMMIO",
- (int) lba_dev->hba.bus_num.start);
- r = &(lba_dev->hba.elmmio_space);
- r->name = lba_dev->hba.elmmio_name;
+ sprintf(lba_dev->hba.elmmio_name,
+ "PCI%02lx ELMMIO",
+ lba_dev->hba.bus_num.start);
+ r = &lba_dev->hba.elmmio_space;
+ r->name = lba_dev->hba.elmmio_name;
} else {
printk(KERN_WARNING MODULE_NAME
" only supports 2 LMMIO resources!\n");
@@ -1239,9 +1125,9 @@ lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev)
case PAT_GMMIO:
/* MMIO space > 4GB phys addr; for 64-bit BAR */
- sprintf(lba_dev->hba.gmmio_name, "PCI%02x GMMIO",
- (int) lba_dev->hba.bus_num.start);
- r = &(lba_dev->hba.gmmio_space);
+ sprintf(lba_dev->hba.gmmio_name, "PCI%02lx GMMIO",
+ lba_dev->hba.bus_num.start);
+ r = &lba_dev->hba.gmmio_space;
r->name = lba_dev->hba.gmmio_name;
r->start = p->start;
r->end = p->end;
@@ -1260,11 +1146,11 @@ lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev)
** Postable I/O port space is per PCI host adapter.
** base of 64MB PIOP region
*/
- lba_dev->iop_base = p->start;
+ lba_dev->iop_base = ioremap(p->start, 64 * 1024 * 1024);
- sprintf(lba_dev->hba.io_name, "PCI%02x Ports",
- (int) lba_dev->hba.bus_num.start);
- r = &(lba_dev->hba.io_space);
+ sprintf(lba_dev->hba.io_name, "PCI%02lx Ports",
+ lba_dev->hba.bus_num.start);
+ r = &lba_dev->hba.io_space;
r->name = lba_dev->hba.io_name;
r->start = HBA_PORT_BASE(lba_dev->hba.hba_num);
r->end = r->start + HBA_PORT_SPACE_SIZE - 1;
@@ -1284,7 +1170,7 @@ lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev)
/* keep compiler from complaining about missing declarations */
#define lba_pat_port_ops lba_astro_port_ops
#define lba_pat_resources(pa_dev, lba_dev)
-#endif /* CONFIG_PARISC64 */
+#endif /* CONFIG_64BIT */
extern void sba_distributed_lmmio(struct parisc_device *, struct resource *);
@@ -1306,7 +1192,7 @@ lba_legacy_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev)
** PCI bus walk *should* end up with the same result.
** FIXME: But we don't have sanity checks in PCI or LBA.
*/
- lba_num = READ_REG32(pa_dev->hpa + LBA_FW_SCRATCH);
+ lba_num = READ_REG32(lba_dev->hba.base_addr + LBA_FW_SCRATCH);
r = &(lba_dev->hba.bus_num);
r->name = "LBA PCI Busses";
r->start = lba_num & 0xff;
@@ -1316,8 +1202,8 @@ lba_legacy_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev)
** Legacy boxes but it's nice to see in /proc/iomem.
*/
r = &(lba_dev->hba.lmmio_space);
- sprintf(lba_dev->hba.lmmio_name, "PCI%02x LMMIO",
- (int) lba_dev->hba.bus_num.start);
+ sprintf(lba_dev->hba.lmmio_name, "PCI%02lx LMMIO",
+ lba_dev->hba.bus_num.start);
r->name = lba_dev->hba.lmmio_name;
#if 1
@@ -1387,7 +1273,7 @@ lba_legacy_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev)
*
* All is well now.
*/
- r->start = (long) READ_REG32(pa_dev->hpa + LBA_LMMIO_BASE);
+ r->start = READ_REG32(lba_dev->hba.base_addr + LBA_LMMIO_BASE);
if (r->start & 1) {
unsigned long rsize;
@@ -1395,7 +1281,7 @@ lba_legacy_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev)
/* mmio_mask also clears Enable bit */
r->start &= mmio_mask;
r->start = PCI_HOST_ADDR(HBA_DATA(lba_dev), r->start);
- rsize = ~ READ_REG32(pa_dev->hpa + LBA_LMMIO_MASK);
+ rsize = ~ READ_REG32(lba_dev->hba.base_addr + LBA_LMMIO_MASK);
/*
** Each rope only gets part of the distributed range.
@@ -1425,15 +1311,15 @@ lba_legacy_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev)
** an existing (but unused portion of) distributed range.
*/
r = &(lba_dev->hba.elmmio_space);
- sprintf(lba_dev->hba.elmmio_name, "PCI%02x ELMMIO",
- (int) lba_dev->hba.bus_num.start);
+ sprintf(lba_dev->hba.elmmio_name, "PCI%02lx ELMMIO",
+ lba_dev->hba.bus_num.start);
r->name = lba_dev->hba.elmmio_name;
#if 1
/* See comment which precedes call to sba_directed_lmmio() */
sba_directed_lmmio(pa_dev, r);
#else
- r->start = READ_REG32(pa_dev->hpa + LBA_ELMMIO_BASE);
+ r->start = READ_REG32(lba_dev->hba.base_addr + LBA_ELMMIO_BASE);
if (r->start & 1) {
unsigned long rsize;
@@ -1441,18 +1327,18 @@ lba_legacy_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev)
/* mmio_mask also clears Enable bit */
r->start &= mmio_mask;
r->start = PCI_HOST_ADDR(HBA_DATA(lba_dev), r->start);
- rsize = READ_REG32(pa_dev->hpa + LBA_ELMMIO_MASK);
+ rsize = READ_REG32(lba_dev->hba.base_addr + LBA_ELMMIO_MASK);
r->end = r->start + ~rsize;
}
#endif
r = &(lba_dev->hba.io_space);
- sprintf(lba_dev->hba.io_name, "PCI%02x Ports",
- (int) lba_dev->hba.bus_num.start);
+ sprintf(lba_dev->hba.io_name, "PCI%02lx Ports",
+ lba_dev->hba.bus_num.start);
r->name = lba_dev->hba.io_name;
r->flags = IORESOURCE_IO;
- r->start = READ_REG32(pa_dev->hpa + LBA_IOS_BASE) & ~1L;
- r->end = r->start + (READ_REG32(pa_dev->hpa + LBA_IOS_MASK) ^ (HBA_PORT_SPACE_SIZE - 1));
+ r->start = READ_REG32(lba_dev->hba.base_addr + LBA_IOS_BASE) & ~1L;
+ r->end = r->start + (READ_REG32(lba_dev->hba.base_addr + LBA_IOS_MASK) ^ (HBA_PORT_SPACE_SIZE - 1));
/* Virtualize the I/O Port space ranges */
lba_num = HBA_PORT_BASE(lba_dev->hba.hba_num);
@@ -1501,7 +1387,7 @@ lba_hw_init(struct lba_device *d)
printk("\n");
#endif /* DEBUG_LBA_PAT */
-#ifdef CONFIG_PARISC64
+#ifdef CONFIG_64BIT
/*
* FIXME add support for PDC_PAT_IO "Get slot status" - OLAR support
* Only N-Class and up can really make use of Get slot status.
@@ -1558,23 +1444,6 @@ lba_hw_init(struct lba_device *d)
-static void __init
-lba_common_init(struct lba_device *lba_dev)
-{
- pci_bios = &lba_bios_ops;
- pcibios_register_hba(HBA_DATA(lba_dev));
- spin_lock_init(&lba_dev->lba_lock);
-
- /*
- ** Set flags which depend on hw_rev
- */
- if (!LBA_TR4PLUS(lba_dev)) {
- lba_dev->flags |= LBA_FLAG_NO_DMA_DURING_CFG;
- }
-}
-
-
-
/*
** Determine if lba should claim this chip (return 0) or not (return 1).
** If so, initialize the chip and tell other partners in crime they
@@ -1585,12 +1454,14 @@ lba_driver_probe(struct parisc_device *dev)
{
struct lba_device *lba_dev;
struct pci_bus *lba_bus;
+ struct pci_ops *cfg_ops;
u32 func_class;
void *tmp_obj;
char *version;
+ void __iomem *addr = ioremap(dev->hpa, 4096);
/* Read HW Rev First */
- func_class = READ_REG32(dev->hpa + LBA_FCLASS);
+ func_class = READ_REG32(addr + LBA_FCLASS);
if (IS_ELROY(dev)) {
func_class &= 0xf;
@@ -1603,24 +1474,40 @@ lba_driver_probe(struct parisc_device *dev)
case 5: version = "TR4.0"; break;
default: version = "TR4+";
}
+
printk(KERN_INFO "%s version %s (0x%x) found at 0x%lx\n",
MODULE_NAME, version, func_class & 0xf, dev->hpa);
- /* Just in case we find some prototypes... */
+ if (func_class < 2) {
+ printk(KERN_WARNING "Can't support LBA older than "
+ "TR2.1 - continuing under adversity.\n");
+ }
+
+#if 0
+/* Elroy TR4.0 should work with simple algorithm.
+ But it doesn't. Still missing something. *sigh*
+*/
+ if (func_class > 4) {
+ cfg_ops = &mercury_cfg_ops;
+ } else
+#endif
+ {
+ cfg_ops = &elroy_cfg_ops;
+ }
+
} else if (IS_MERCURY(dev) || IS_QUICKSILVER(dev)) {
func_class &= 0xff;
version = kmalloc(6, GFP_KERNEL);
sprintf(version,"TR%d.%d",(func_class >> 4),(func_class & 0xf));
- /* We could use one printk for both and have it outside,
+ /* We could use one printk for both Elroy and Mercury,
* but for the mask for func_class.
*/
printk(KERN_INFO "%s version %s (0x%x) found at 0x%lx\n",
MODULE_NAME, version, func_class & 0xff, dev->hpa);
- }
-
- if (func_class < 2) {
- printk(KERN_WARNING "Can't support LBA older than TR2.1"
- " - continuing under adversity.\n");
+ cfg_ops = &mercury_cfg_ops;
+ } else {
+ printk(KERN_ERR "Unknown LBA found at 0x%lx\n", dev->hpa);
+ return -ENODEV;
}
/*
@@ -1633,8 +1520,7 @@ lba_driver_probe(struct parisc_device *dev)
*/
lba_dev = kmalloc(sizeof(struct lba_device), GFP_KERNEL);
- if (NULL == lba_dev)
- {
+ if (!lba_dev) {
printk(KERN_ERR "lba_init_chip - couldn't alloc lba_device\n");
return(1);
}
@@ -1644,19 +1530,16 @@ lba_driver_probe(struct parisc_device *dev)
/* ---------- First : initialize data we already have --------- */
- /*
- ** Need hw_rev to adjust configuration space behavior.
- ** LBA_TR4PLUS macro uses hw_rev field.
- */
lba_dev->hw_rev = func_class;
-
- lba_dev->hba.base_addr = dev->hpa; /* faster access */
+ lba_dev->hba.base_addr = addr;
lba_dev->hba.dev = dev;
lba_dev->iosapic_obj = tmp_obj; /* save interrupt handle */
lba_dev->hba.iommu = sba_get_iommu(dev); /* get iommu data */
/* ------------ Second : initialize common stuff ---------- */
- lba_common_init(lba_dev);
+ pci_bios = &lba_bios_ops;
+ pcibios_register_hba(HBA_DATA(lba_dev));
+ spin_lock_init(&lba_dev->lba_lock);
if (lba_hw_init(lba_dev))
return(1);
@@ -1669,8 +1552,11 @@ lba_driver_probe(struct parisc_device *dev)
/* Go ask PDC PAT what resources this LBA has */
lba_pat_resources(dev, lba_dev);
} else {
- /* Sprockets PDC uses NPIOP region */
- pci_port = &lba_astro_port_ops;
+ if (!astro_iop_base) {
+ /* Sprockets PDC uses NPIOP region */
+ astro_iop_base = ioremap(LBA_PORT_BASE, 64 * 1024);
+ pci_port = &lba_astro_port_ops;
+ }
/* Poke the chip a bit for /proc output */
lba_legacy_resources(dev, lba_dev);
@@ -1683,8 +1569,7 @@ lba_driver_probe(struct parisc_device *dev)
dev->dev.platform_data = lba_dev;
lba_bus = lba_dev->hba.hba_bus =
pci_scan_bus_parented(&dev->dev, lba_dev->hba.bus_num.start,
- IS_ELROY(dev) ? &lba_cfg_ops : &mercury_cfg_ops,
- NULL);
+ cfg_ops, NULL);
/* This is in lieu of calling pci_assign_unassigned_resources() */
if (is_pdc_pat()) {
@@ -1711,7 +1596,7 @@ lba_driver_probe(struct parisc_device *dev)
** space is restricted. Avoids master aborts on config cycles.
** Early LBA revs go fatal on *any* master abort.
*/
- if (!LBA_TR4PLUS(lba_dev)) {
+ if (cfg_ops == &elroy_cfg_ops) {
lba_dev->flags |= LBA_FLAG_SKIP_PROBE;
}
@@ -1746,18 +1631,19 @@ void __init lba_init(void)
** Only called from sba_iommu.c in order to route ranges (MMIO vs DMA).
** sba_iommu is responsible for locking (none needed at init time).
*/
-void
-lba_set_iregs(struct parisc_device *lba, u32 ibase, u32 imask)
+void lba_set_iregs(struct parisc_device *lba, u32 ibase, u32 imask)
{
- unsigned long base_addr = lba->hpa;
+ void __iomem * base_addr = ioremap(lba->hpa, 4096);
imask <<= 2; /* adjust for hints - 2 more bits */
- ASSERT((ibase & 0x003fffff) == 0);
- ASSERT((imask & 0x003fffff) == 0);
+ /* Make sure we aren't trying to set bits that aren't writeable. */
+ WARN_ON((ibase & 0x001fffff) != 0);
+ WARN_ON((imask & 0x001fffff) != 0);
DBG("%s() ibase 0x%x imask 0x%x\n", __FUNCTION__, ibase, imask);
WRITE_REG32( imask, base_addr + LBA_IMASK);
WRITE_REG32( ibase, base_addr + LBA_IBASE);
+ iounmap(base_addr);
}
diff --git a/drivers/parisc/led.c b/drivers/parisc/led.c
index 58e5c3e8153fd..e90fb72a69629 100644
--- a/drivers/parisc/led.c
+++ b/drivers/parisc/led.c
@@ -77,8 +77,8 @@ struct lcd_block {
struct pdc_chassis_lcd_info_ret_block {
unsigned long model:16; /* DISPLAY_MODEL_XXXX */
unsigned long lcd_width:16; /* width of the LCD in chars (DISPLAY_MODEL_LCD only) */
- char *lcd_cmd_reg_addr; /* ptr to LCD cmd-register & data ptr for LED */
- char *lcd_data_reg_addr; /* ptr to LCD data-register (LCD only) */
+ unsigned long lcd_cmd_reg_addr; /* ptr to LCD cmd-register & data ptr for LED */
+ unsigned long lcd_data_reg_addr; /* ptr to LCD data-register (LCD only) */
unsigned int min_cmd_delay; /* delay in uS after cmd-write (LCD only) */
unsigned char reset_cmd1; /* command #1 for writing LCD string (LCD only) */
unsigned char reset_cmd2; /* command #2 for writing LCD string (LCD only) */
@@ -102,8 +102,8 @@ lcd_info __attribute__((aligned(8))) =
{
.model = DISPLAY_MODEL_LCD,
.lcd_width = 16,
- .lcd_cmd_reg_addr = (char *) KITTYHAWK_LCD_CMD,
- .lcd_data_reg_addr = (char *) KITTYHAWK_LCD_DATA,
+ .lcd_cmd_reg_addr = KITTYHAWK_LCD_CMD,
+ .lcd_data_reg_addr = KITTYHAWK_LCD_DATA,
.min_cmd_delay = 40,
.reset_cmd1 = 0x80,
.reset_cmd2 = 0xc0,
@@ -540,20 +540,20 @@ static int led_halt(struct notifier_block *nb, unsigned long event, void *buf)
**
*/
-int __init register_led_driver(int model, char *cmd_reg, char *data_reg)
+int __init register_led_driver(int model, unsigned long cmd_reg, unsigned long data_reg)
{
static int initialized;
if (initialized || !data_reg)
- return 1;
+ return 1;
lcd_info.model = model; /* store the values */
- LCD_CMD_REG = (cmd_reg == LED_CMD_REG_NONE) ? NULL : cmd_reg;
+ LCD_CMD_REG = (cmd_reg == LED_CMD_REG_NONE) ? 0 : cmd_reg;
switch (lcd_info.model) {
case DISPLAY_MODEL_LCD:
LCD_DATA_REG = data_reg;
- printk(KERN_INFO "LCD display at %p,%p registered\n",
+ printk(KERN_INFO "LCD display at %lx,%lx registered\n",
LCD_CMD_REG , LCD_DATA_REG);
led_func_ptr = led_LCD_driver;
lcd_print( lcd_text_default );
@@ -563,14 +563,14 @@ int __init register_led_driver(int model, char *cmd_reg, char *data_reg)
case DISPLAY_MODEL_LASI:
LED_DATA_REG = data_reg;
led_func_ptr = led_LASI_driver;
- printk(KERN_INFO "LED display at %p registered\n", LED_DATA_REG);
+ printk(KERN_INFO "LED display at %lx registered\n", LED_DATA_REG);
led_type = LED_NOLCD;
break;
case DISPLAY_MODEL_OLD_ASP:
LED_DATA_REG = data_reg;
led_func_ptr = led_ASP_driver;
- printk(KERN_INFO "LED (ASP-style) display at %p registered\n",
+ printk(KERN_INFO "LED (ASP-style) display at %lx registered\n",
LED_DATA_REG);
led_type = LED_NOLCD;
break;
@@ -695,7 +695,8 @@ int __init led_init(void)
lcd_info.model = DISPLAY_MODEL_NONE;
chassis_info.actcnt = chassis_info.maxcnt = 0;
- if ((ret = pdc_chassis_info(&chassis_info, &lcd_info, sizeof(lcd_info))) == PDC_OK) {
+ ret = pdc_chassis_info(&chassis_info, &lcd_info, sizeof(lcd_info));
+ if (ret == PDC_OK) {
DPRINTK((KERN_INFO "%s: chassis info: model=%d (%s), "
"lcd_width=%d, cmd_delay=%u,\n"
"%s: sizecnt=%d, actcnt=%ld, maxcnt=%ld\n",
diff --git a/drivers/parisc/pdc_stable.c b/drivers/parisc/pdc_stable.c
new file mode 100644
index 0000000000000..67c8f3b44848d
--- /dev/null
+++ b/drivers/parisc/pdc_stable.c
@@ -0,0 +1,735 @@
+/*
+ * Interfaces to retrieve and set PDC Stable options (firmware)
+ *
+ * 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
+ *
+ *
+ * DEV NOTE: the PDC Procedures reference states that:
+ * "A minimum of 96 bytes of Stable Storage is required. Providing more than
+ * 96 bytes of Stable Storage is optional [...]. Failure to provide the
+ * optional locations from 96 to 192 results in the loss of certain
+ * functionality during boot."
+ *
+ * Since locations between 96 and 192 are the various paths, most (if not
+ * all) PA-RISC machines should have them. Anyway, for safety reasons, the
+ * following code can deal with only 96 bytes of Stable Storage, and all
+ * sizes between 96 and 192 bytes (provided they are multiple of struct
+ * device_path size, eg: 128, 160 and 192) to provide full information.
+ * The code makes no use of data above 192 bytes. One last word: there's one
+ * path we can always count on: the primary path.
+ */
+
+#undef PDCS_DEBUG
+#ifdef PDCS_DEBUG
+#define DPRINTK(fmt, args...) printk(KERN_DEBUG fmt, ## args)
+#else
+#define DPRINTK(fmt, args...)
+#endif
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/sched.h> /* for capable() */
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#include <linux/sysfs.h>
+#include <linux/kobject.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+
+#include <asm/pdc.h>
+#include <asm/page.h>
+#include <asm/uaccess.h>
+#include <asm/hardware.h>
+
+#define PDCS_VERSION "0.09"
+
+#define PDCS_ADDR_PPRI 0x00
+#define PDCS_ADDR_OSID 0x40
+#define PDCS_ADDR_FSIZ 0x5C
+#define PDCS_ADDR_PCON 0x60
+#define PDCS_ADDR_PALT 0x80
+#define PDCS_ADDR_PKBD 0xA0
+
+MODULE_AUTHOR("Thibaut VARENE <varenet@parisc-linux.org>");
+MODULE_DESCRIPTION("sysfs interface to HP PDC Stable Storage data");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(PDCS_VERSION);
+
+static unsigned long pdcs_size = 0;
+
+/* This struct defines what we need to deal with a parisc pdc path entry */
+struct pdcspath_entry {
+ short ready; /* entry record is valid if != 0 */
+ unsigned long addr; /* entry address in stable storage */
+ char *name; /* entry name */
+ struct device_path devpath; /* device path in parisc representation */
+ struct device *dev; /* corresponding device */
+ struct kobject kobj;
+};
+
+struct pdcspath_attribute {
+ struct attribute attr;
+ ssize_t (*show)(struct pdcspath_entry *entry, char *buf);
+ ssize_t (*store)(struct pdcspath_entry *entry, const char *buf, size_t count);
+};
+
+#define PDCSPATH_ENTRY(_addr, _name) \
+struct pdcspath_entry pdcspath_entry_##_name = { \
+ .ready = 0, \
+ .addr = _addr, \
+ .name = __stringify(_name), \
+};
+
+#define PDCS_ATTR(_name, _mode, _show, _store) \
+struct subsys_attribute pdcs_attr_##_name = { \
+ .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE}, \
+ .show = _show, \
+ .store = _store, \
+};
+
+#define PATHS_ATTR(_name, _mode, _show, _store) \
+struct pdcspath_attribute paths_attr_##_name = { \
+ .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE}, \
+ .show = _show, \
+ .store = _store, \
+};
+
+#define to_pdcspath_attribute(_attr) container_of(_attr, struct pdcspath_attribute, attr)
+#define to_pdcspath_entry(obj) container_of(obj, struct pdcspath_entry, kobj)
+
+/**
+ * pdcspath_fetch - This function populates the path entry structs.
+ * @entry: A pointer to an allocated pdcspath_entry.
+ *
+ * The general idea is that you don't read from the Stable Storage every time
+ * you access the files provided by the facilites. We store a copy of the
+ * content of the stable storage WRT various paths in these structs. We read
+ * these structs when reading the files, and we will write to these structs when
+ * writing to the files, and only then write them back to the Stable Storage.
+ */
+static int
+pdcspath_fetch(struct pdcspath_entry *entry)
+{
+ struct device_path *devpath;
+
+ if (!entry)
+ return -EINVAL;
+
+ devpath = &entry->devpath;
+
+ DPRINTK("%s: fetch: 0x%p, 0x%p, addr: 0x%lx\n", __func__,
+ entry, devpath, entry->addr);
+
+ /* addr, devpath and count must be word aligned */
+ if (pdc_stable_read(entry->addr, devpath, sizeof(*devpath)) != PDC_OK)
+ return -EIO;
+
+ /* Find the matching device.
+ NOTE: hardware_path overlays with device_path, so the nice cast can
+ be used */
+ entry->dev = hwpath_to_device((struct hardware_path *)devpath);
+
+ entry->ready = 1;
+
+ DPRINTK("%s: device: 0x%p\n", __func__, entry->dev);
+
+ return 0;
+}
+
+/**
+ * pdcspath_store - This function writes a path to stable storage.
+ * @entry: A pointer to an allocated pdcspath_entry.
+ *
+ * It can be used in two ways: either by passing it a preset devpath struct
+ * containing an already computed hardware path, or by passing it a device
+ * pointer, from which it'll find out the corresponding hardware path.
+ * For now we do not handle the case where there's an error in writing to the
+ * Stable Storage area, so you'd better not mess up the data :P
+ */
+static int
+pdcspath_store(struct pdcspath_entry *entry)
+{
+ struct device_path *devpath;
+
+ if (!entry)
+ return -EINVAL;
+
+ devpath = &entry->devpath;
+
+ /* We expect the caller to set the ready flag to 0 if the hardware
+ path struct provided is invalid, so that we know we have to fill it.
+ First case, we don't have a preset hwpath... */
+ if (!entry->ready) {
+ /* ...but we have a device, map it */
+ if (entry->dev)
+ device_to_hwpath(entry->dev, (struct hardware_path *)devpath);
+ else
+ return -EINVAL;
+ }
+ /* else, we expect the provided hwpath to be valid. */
+
+ DPRINTK("%s: store: 0x%p, 0x%p, addr: 0x%lx\n", __func__,
+ entry, devpath, entry->addr);
+
+ /* addr, devpath and count must be word aligned */
+ if (pdc_stable_write(entry->addr, devpath, sizeof(*devpath)) != PDC_OK) {
+ printk(KERN_ERR "%s: an error occured when writing to PDC.\n"
+ "It is likely that the Stable Storage data has been corrupted.\n"
+ "Please check it carefully upon next reboot.\n", __func__);
+ return -EIO;
+ }
+
+ entry->ready = 1;
+
+ DPRINTK("%s: device: 0x%p\n", __func__, entry->dev);
+
+ return 0;
+}
+
+/**
+ * pdcspath_hwpath_read - This function handles hardware path pretty printing.
+ * @entry: An allocated and populated pdscpath_entry struct.
+ * @buf: The output buffer to write to.
+ *
+ * We will call this function to format the output of the hwpath attribute file.
+ */
+static ssize_t
+pdcspath_hwpath_read(struct pdcspath_entry *entry, char *buf)
+{
+ char *out = buf;
+ struct device_path *devpath;
+ unsigned short i;
+
+ if (!entry || !buf)
+ return -EINVAL;
+
+ devpath = &entry->devpath;
+
+ if (!entry->ready)
+ return -ENODATA;
+
+ for (i = 0; i < 6; i++) {
+ if (devpath->bc[i] >= 128)
+ continue;
+ out += sprintf(out, "%u/", (unsigned char)devpath->bc[i]);
+ }
+ out += sprintf(out, "%u\n", (unsigned char)devpath->mod);
+
+ return out - buf;
+}
+
+/**
+ * pdcspath_hwpath_write - This function handles hardware path modifying.
+ * @entry: An allocated and populated pdscpath_entry struct.
+ * @buf: The input buffer to read from.
+ * @count: The number of bytes to be read.
+ *
+ * We will call this function to change the current hardware path.
+ * Hardware paths are to be given '/'-delimited, without brackets.
+ * We take care to make sure that the provided path actually maps to an existing
+ * device, BUT nothing would prevent some foolish user to set the path to some
+ * PCI bridge or even a CPU...
+ * A better work around would be to make sure we are at the end of a device tree
+ * for instance, but it would be IMHO beyond the simple scope of that driver.
+ * The aim is to provide a facility. Data correctness is left to userland.
+ */
+static ssize_t
+pdcspath_hwpath_write(struct pdcspath_entry *entry, const char *buf, size_t count)
+{
+ struct hardware_path hwpath;
+ unsigned short i;
+ char in[count+1], *temp;
+ struct device *dev;
+
+ if (!entry || !buf || !count)
+ return -EINVAL;
+
+ /* We'll use a local copy of buf */
+ memset(in, 0, count+1);
+ strncpy(in, buf, count);
+
+ /* Let's clean up the target. 0xff is a blank pattern */
+ memset(&hwpath, 0xff, sizeof(hwpath));
+
+ /* First, pick the mod field (the last one of the input string) */
+ if (!(temp = strrchr(in, '/')))
+ return -EINVAL;
+
+ hwpath.mod = simple_strtoul(temp+1, NULL, 10);
+ in[temp-in] = '\0'; /* truncate the remaining string. just precaution */
+ DPRINTK("%s: mod: %d\n", __func__, hwpath.mod);
+
+ /* Then, loop for each delimiter, making sure we don't have too many.
+ we write the bc fields in a down-top way. No matter what, we stop
+ before writing the last field. If there are too many fields anyway,
+ then the user is a moron and it'll be caught up later when we'll
+ check the consistency of the given hwpath. */
+ for (i=5; ((temp = strrchr(in, '/'))) && (temp-in > 0) && (likely(i)); i--) {
+ hwpath.bc[i] = simple_strtoul(temp+1, NULL, 10);
+ in[temp-in] = '\0';
+ DPRINTK("%s: bc[%d]: %d\n", __func__, i, hwpath.bc[i]);
+ }
+
+ /* Store the final field */
+ hwpath.bc[i] = simple_strtoul(in, NULL, 10);
+ DPRINTK("%s: bc[%d]: %d\n", __func__, i, hwpath.bc[i]);
+
+ /* Now we check that the user isn't trying to lure us */
+ if (!(dev = hwpath_to_device((struct hardware_path *)&hwpath))) {
+ printk(KERN_WARNING "%s: attempt to set invalid \"%s\" "
+ "hardware path: %s\n", __func__, entry->name, buf);
+ return -EINVAL;
+ }
+
+ /* So far so good, let's get in deep */
+ entry->ready = 0;
+ entry->dev = dev;
+
+ /* Now, dive in. Write back to the hardware */
+ WARN_ON(pdcspath_store(entry)); /* this warn should *NEVER* happen */
+
+ /* Update the symlink to the real device */
+ sysfs_remove_link(&entry->kobj, "device");
+ sysfs_create_link(&entry->kobj, &entry->dev->kobj, "device");
+
+ printk(KERN_INFO "PDC Stable Storage: changed \"%s\" path to \"%s\"\n",
+ entry->name, buf);
+
+ return count;
+}
+
+/**
+ * pdcspath_layer_read - Extended layer (eg. SCSI ids) pretty printing.
+ * @entry: An allocated and populated pdscpath_entry struct.
+ * @buf: The output buffer to write to.
+ *
+ * We will call this function to format the output of the layer attribute file.
+ */
+static ssize_t
+pdcspath_layer_read(struct pdcspath_entry *entry, char *buf)
+{
+ char *out = buf;
+ struct device_path *devpath;
+ unsigned short i;
+
+ if (!entry || !buf)
+ return -EINVAL;
+
+ devpath = &entry->devpath;
+
+ if (!entry->ready)
+ return -ENODATA;
+
+ for (i = 0; devpath->layers[i] && (likely(i < 6)); i++)
+ out += sprintf(out, "%u ", devpath->layers[i]);
+
+ out += sprintf(out, "\n");
+
+ return out - buf;
+}
+
+/**
+ * pdcspath_layer_write - This function handles extended layer modifying.
+ * @entry: An allocated and populated pdscpath_entry struct.
+ * @buf: The input buffer to read from.
+ * @count: The number of bytes to be read.
+ *
+ * We will call this function to change the current layer value.
+ * Layers are to be given '.'-delimited, without brackets.
+ * XXX beware we are far less checky WRT input data provided than for hwpath.
+ * Potential harm can be done, since there's no way to check the validity of
+ * the layer fields.
+ */
+static ssize_t
+pdcspath_layer_write(struct pdcspath_entry *entry, const char *buf, size_t count)
+{
+ unsigned int layers[6]; /* device-specific info (ctlr#, unit#, ...) */
+ unsigned short i;
+ char in[count+1], *temp;
+
+ if (!entry || !buf || !count)
+ return -EINVAL;
+
+ /* We'll use a local copy of buf */
+ memset(in, 0, count+1);
+ strncpy(in, buf, count);
+
+ /* Let's clean up the target. 0 is a blank pattern */
+ memset(&layers, 0, sizeof(layers));
+
+ /* First, pick the first layer */
+ if (unlikely(!isdigit(*in)))
+ return -EINVAL;
+ layers[0] = simple_strtoul(in, NULL, 10);
+ DPRINTK("%s: layer[0]: %d\n", __func__, layers[0]);
+
+ temp = in;
+ for (i=1; ((temp = strchr(temp, '.'))) && (likely(i<6)); i++) {
+ if (unlikely(!isdigit(*(++temp))))
+ return -EINVAL;
+ layers[i] = simple_strtoul(temp, NULL, 10);
+ DPRINTK("%s: layer[%d]: %d\n", __func__, i, layers[i]);
+ }
+
+ /* So far so good, let's get in deep */
+
+ /* First, overwrite the current layers with the new ones, not touching
+ the hardware path. */
+ memcpy(&entry->devpath.layers, &layers, sizeof(layers));
+
+ /* Now, dive in. Write back to the hardware */
+ WARN_ON(pdcspath_store(entry)); /* this warn should *NEVER* happen */
+
+ printk(KERN_INFO "PDC Stable Storage: changed \"%s\" layers to \"%s\"\n",
+ entry->name, buf);
+
+ return count;
+}
+
+/**
+ * pdcspath_attr_show - Generic read function call wrapper.
+ * @kobj: The kobject to get info from.
+ * @attr: The attribute looked upon.
+ * @buf: The output buffer.
+ */
+static ssize_t
+pdcspath_attr_show(struct kobject *kobj, struct attribute *attr, char *buf)
+{
+ struct pdcspath_entry *entry = to_pdcspath_entry(kobj);
+ struct pdcspath_attribute *pdcs_attr = to_pdcspath_attribute(attr);
+ ssize_t ret = 0;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EACCES;
+
+ if (pdcs_attr->show)
+ ret = pdcs_attr->show(entry, buf);
+
+ return ret;
+}
+
+/**
+ * pdcspath_attr_store - Generic write function call wrapper.
+ * @kobj: The kobject to write info to.
+ * @attr: The attribute to be modified.
+ * @buf: The input buffer.
+ * @count: The size of the buffer.
+ */
+static ssize_t
+pdcspath_attr_store(struct kobject *kobj, struct attribute *attr,
+ const char *buf, size_t count)
+{
+ struct pdcspath_entry *entry = to_pdcspath_entry(kobj);
+ struct pdcspath_attribute *pdcs_attr = to_pdcspath_attribute(attr);
+ ssize_t ret = 0;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EACCES;
+
+ if (pdcs_attr->store)
+ ret = pdcs_attr->store(entry, buf, count);
+
+ return ret;
+}
+
+static struct sysfs_ops pdcspath_attr_ops = {
+ .show = pdcspath_attr_show,
+ .store = pdcspath_attr_store,
+};
+
+/* These are the two attributes of any PDC path. */
+static PATHS_ATTR(hwpath, 0600, pdcspath_hwpath_read, pdcspath_hwpath_write);
+static PATHS_ATTR(layer, 0600, pdcspath_layer_read, pdcspath_layer_write);
+
+static struct attribute *paths_subsys_attrs[] = {
+ &paths_attr_hwpath.attr,
+ &paths_attr_layer.attr,
+ NULL,
+};
+
+/* Specific kobject type for our PDC paths */
+static struct kobj_type ktype_pdcspath = {
+ .sysfs_ops = &pdcspath_attr_ops,
+ .default_attrs = paths_subsys_attrs,
+};
+
+/* We hard define the 4 types of path we expect to find */
+static PDCSPATH_ENTRY(PDCS_ADDR_PPRI, primary);
+static PDCSPATH_ENTRY(PDCS_ADDR_PCON, console);
+static PDCSPATH_ENTRY(PDCS_ADDR_PALT, alternative);
+static PDCSPATH_ENTRY(PDCS_ADDR_PKBD, keyboard);
+
+/* An array containing all PDC paths we will deal with */
+static struct pdcspath_entry *pdcspath_entries[] = {
+ &pdcspath_entry_primary,
+ &pdcspath_entry_alternative,
+ &pdcspath_entry_console,
+ &pdcspath_entry_keyboard,
+ NULL,
+};
+
+/**
+ * pdcs_info_read - Pretty printing of the remaining useful data.
+ * @entry: An allocated and populated subsytem struct. We don't use it tho.
+ * @buf: The output buffer to write to.
+ *
+ * We will call this function to format the output of the 'info' attribute file.
+ * Please refer to PDC Procedures documentation, section PDC_STABLE to get a
+ * better insight of what we're doing here.
+ */
+static ssize_t
+pdcs_info_read(struct subsystem *entry, char *buf)
+{
+ char *out = buf;
+ __u32 result;
+ struct device_path devpath;
+ char *tmpstr = NULL;
+
+ if (!entry || !buf)
+ return -EINVAL;
+
+ /* show the size of the stable storage */
+ out += sprintf(out, "Stable Storage size: %ld bytes\n", pdcs_size);
+
+ /* deal with flags */
+ if (pdc_stable_read(PDCS_ADDR_PPRI, &devpath, sizeof(devpath)) != PDC_OK)
+ return -EIO;
+
+ out += sprintf(out, "Autoboot: %s\n", (devpath.flags & PF_AUTOBOOT) ? "On" : "Off");
+ out += sprintf(out, "Autosearch: %s\n", (devpath.flags & PF_AUTOSEARCH) ? "On" : "Off");
+ out += sprintf(out, "Timer: %u s\n", (devpath.flags & PF_TIMER) ? (1 << (devpath.flags & PF_TIMER)) : 0);
+
+ /* get OSID */
+ if (pdc_stable_read(PDCS_ADDR_OSID, &result, sizeof(result)) != PDC_OK)
+ return -EIO;
+
+ /* the actual result is 16 bits away */
+ switch (result >> 16) {
+ case 0x0000: tmpstr = "No OS-dependent data"; break;
+ case 0x0001: tmpstr = "HP-UX dependent data"; break;
+ case 0x0002: tmpstr = "MPE-iX dependent data"; break;
+ case 0x0003: tmpstr = "OSF dependent data"; break;
+ case 0x0004: tmpstr = "HP-RT dependent data"; break;
+ case 0x0005: tmpstr = "Novell Netware dependent data"; break;
+ default: tmpstr = "Unknown"; break;
+ }
+ out += sprintf(out, "OS ID: %s (0x%.4x)\n", tmpstr, (result >> 16));
+
+ /* get fast-size */
+ if (pdc_stable_read(PDCS_ADDR_FSIZ, &result, sizeof(result)) != PDC_OK)
+ return -EIO;
+
+ out += sprintf(out, "Memory tested: ");
+ if ((result & 0x0F) < 0x0E)
+ out += sprintf(out, "%.3f MB", 0.256*(1<<(result & 0x0F)));
+ else
+ out += sprintf(out, "All");
+ out += sprintf(out, "\n");
+
+ return out - buf;
+}
+
+/**
+ * pdcs_info_write - This function handles boot flag modifying.
+ * @entry: An allocated and populated subsytem struct. We don't use it tho.
+ * @buf: The input buffer to read from.
+ * @count: The number of bytes to be read.
+ *
+ * We will call this function to change the current boot flags.
+ * We expect a precise syntax:
+ * \"n n\" (n == 0 or 1) to toggle respectively AutoBoot and AutoSearch
+ *
+ * As of now there is no incentive on my side to provide more "knobs" to that
+ * interface, since modifying the rest of the data is pretty meaningless when
+ * the machine is running and for the expected use of that facility, such as
+ * PALO setting up the boot disk when installing a Linux distribution...
+ */
+static ssize_t
+pdcs_info_write(struct subsystem *entry, const char *buf, size_t count)
+{
+ struct pdcspath_entry *pathentry;
+ unsigned char flags;
+ char in[count+1], *temp;
+ char c;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EACCES;
+
+ if (!entry || !buf || !count)
+ return -EINVAL;
+
+ /* We'll use a local copy of buf */
+ memset(in, 0, count+1);
+ strncpy(in, buf, count);
+
+ /* Current flags are stored in primary boot path entry */
+ pathentry = &pdcspath_entry_primary;
+
+ /* Be nice to the existing flag record */
+ flags = pathentry->devpath.flags;
+
+ DPRINTK("%s: flags before: 0x%X\n", __func__, flags);
+
+ temp = in;
+
+ while (*temp && isspace(*temp))
+ temp++;
+
+ c = *temp++ - '0';
+ if ((c != 0) && (c != 1))
+ goto parse_error;
+ if (c == 0)
+ flags &= ~PF_AUTOBOOT;
+ else
+ flags |= PF_AUTOBOOT;
+
+ if (*temp++ != ' ')
+ goto parse_error;
+
+ c = *temp++ - '0';
+ if ((c != 0) && (c != 1))
+ goto parse_error;
+ if (c == 0)
+ flags &= ~PF_AUTOSEARCH;
+ else
+ flags |= PF_AUTOSEARCH;
+
+ DPRINTK("%s: flags after: 0x%X\n", __func__, flags);
+
+ /* So far so good, let's get in deep */
+
+ /* Change the path entry flags first */
+ pathentry->devpath.flags = flags;
+
+ /* Now, dive in. Write back to the hardware */
+ WARN_ON(pdcspath_store(pathentry)); /* this warn should *NEVER* happen */
+
+ printk(KERN_INFO "PDC Stable Storage: changed flags to \"%s\"\n", buf);
+
+ return count;
+
+parse_error:
+ printk(KERN_WARNING "%s: Parse error: expect \"n n\" (n == 0 or 1) for AB and AS\n", __func__);
+ return -EINVAL;
+}
+
+/* The last attribute (the 'root' one actually) with all remaining data. */
+static PDCS_ATTR(info, 0600, pdcs_info_read, pdcs_info_write);
+
+static struct subsys_attribute *pdcs_subsys_attrs[] = {
+ &pdcs_attr_info,
+ NULL, /* maybe more in the future? */
+};
+
+static decl_subsys(paths, &ktype_pdcspath, NULL);
+static decl_subsys(pdc, NULL, NULL);
+
+/**
+ * pdcs_register_pathentries - Prepares path entries kobjects for sysfs usage.
+ *
+ * It creates kobjects corresponding to each path entry with nice sysfs
+ * links to the real device. This is where the magic takes place: when
+ * registering the subsystem attributes during module init, each kobject hereby
+ * created will show in the sysfs tree as a folder containing files as defined
+ * by path_subsys_attr[].
+ */
+static inline int __init
+pdcs_register_pathentries(void)
+{
+ unsigned short i;
+ struct pdcspath_entry *entry;
+
+ for (i = 0; (entry = pdcspath_entries[i]); i++) {
+ if (pdcspath_fetch(entry) < 0)
+ continue;
+
+ kobject_set_name(&entry->kobj, "%s", entry->name);
+ kobj_set_kset_s(entry, paths_subsys);
+ kobject_register(&entry->kobj);
+
+ if (!entry->dev)
+ continue;
+
+ /* Add a nice symlink to the real device */
+ sysfs_create_link(&entry->kobj, &entry->dev->kobj, "device");
+ }
+
+ return 0;
+}
+
+/**
+ * pdcs_unregister_pathentries - Routine called when unregistering the module.
+ */
+static inline void __exit
+pdcs_unregister_pathentries(void)
+{
+ unsigned short i;
+ struct pdcspath_entry *entry;
+
+ for (i = 0; (entry = pdcspath_entries[i]); i++)
+ if (entry->ready)
+ kobject_unregister(&entry->kobj);
+}
+
+/*
+ * For now we register the pdc subsystem with the firmware subsystem
+ * and the paths subsystem with the pdc subsystem
+ */
+static int __init
+pdc_stable_init(void)
+{
+ struct subsys_attribute *attr;
+ int i, rc = 0, error = 0;
+
+ /* find the size of the stable storage */
+ if (pdc_stable_get_size(&pdcs_size) != PDC_OK)
+ return -ENODEV;
+
+ printk(KERN_INFO "PDC Stable Storage facility v%s\n", PDCS_VERSION);
+
+ /* For now we'll register the pdc subsys within this driver */
+ if ((rc = firmware_register(&pdc_subsys)))
+ return rc;
+
+ /* Don't forget the info entry */
+ for (i = 0; (attr = pdcs_subsys_attrs[i]) && !error; i++)
+ if (attr->show)
+ error = subsys_create_file(&pdc_subsys, attr);
+
+ /* register the paths subsys as a subsystem of pdc subsys */
+ kset_set_kset_s(&paths_subsys, pdc_subsys);
+ subsystem_register(&paths_subsys);
+
+ /* now we create all "files" for the paths subsys */
+ pdcs_register_pathentries();
+
+ return 0;
+}
+
+static void __exit
+pdc_stable_exit(void)
+{
+ pdcs_unregister_pathentries();
+ subsystem_unregister(&paths_subsys);
+
+ firmware_unregister(&pdc_subsys);
+}
+
+
+module_init(pdc_stable_init);
+module_exit(pdc_stable_exit);
diff --git a/drivers/parisc/power.c b/drivers/parisc/power.c
index d097e7ecdf8ea..ff75e9296df98 100644
--- a/drivers/parisc/power.c
+++ b/drivers/parisc/power.c
@@ -47,7 +47,6 @@
#include <linux/workqueue.h>
#include <asm/pdc.h>
-#include <asm/irq.h>
#include <asm/io.h>
#include <asm/led.h>
#include <asm/uaccess.h>
@@ -126,11 +125,11 @@ static void process_shutdown(void)
/* wait until the button was pressed for 1 second */
if (shutdown_timer == HZ) {
+#if defined (DEBUG) || defined(CONFIG_CHASSIS_LCD_LED)
static char msg[] = "Shutting down...";
+#endif
DPRINTK(KERN_INFO "%s\n", msg);
-#ifdef CONFIG_CHASSIS_LCD_LED
lcd_print(msg);
-#endif
poweroff();
}
}
diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c
index 166d5fe79bc55..82ea68b55df4f 100644
--- a/drivers/parisc/sba_iommu.c
+++ b/drivers/parisc/sba_iommu.c
@@ -58,7 +58,6 @@ extern struct proc_dir_entry * proc_mckinley_root;
** Don't even think about messing with it unless you have
** plenty of 710's to sacrifice to the computer gods. :^)
*/
-#undef DEBUG_SBA_ASSERT
#undef DEBUG_SBA_INIT
#undef DEBUG_SBA_RUN
#undef DEBUG_SBA_RUN_SG
@@ -92,19 +91,6 @@ extern struct proc_dir_entry * proc_mckinley_root;
#define DBG_RES(x...)
#endif
-#ifdef DEBUG_SBA_ASSERT
-#undef ASSERT
-#define ASSERT(expr) \
- if(!(expr)) { \
- printk("\n%s:%d: Assertion " #expr " failed!\n", \
- __FILE__, __LINE__); \
- panic(#expr); \
- }
-#else
-#define ASSERT(expr)
-#endif
-
-
#if defined(__LP64__) && !defined(CONFIG_PDC_NARROW)
/* "low end" PA8800 machines use ZX1 chipset */
#define ZX1_SUPPORT
@@ -125,39 +111,24 @@ extern struct proc_dir_entry * proc_mckinley_root;
#define DEFAULT_DMA_HINT_REG 0
#define ASTRO_RUNWAY_PORT 0x582
-#define ASTRO_ROPES_PORT 0x780
-
#define IKE_MERCED_PORT 0x803
-#define IKE_ROPES_PORT 0x781
-
#define REO_MERCED_PORT 0x804
-#define REO_ROPES_PORT 0x782
-
#define REOG_MERCED_PORT 0x805
-#define REOG_ROPES_PORT 0x783
-
#define PLUTO_MCKINLEY_PORT 0x880
-#define PLUTO_ROPES_PORT 0x784
#define SBA_FUNC_ID 0x0000 /* function id */
#define SBA_FCLASS 0x0008 /* function class, bist, header, rev... */
-#define IS_ASTRO(id) \
-(((id)->hversion == ASTRO_RUNWAY_PORT) || ((id)->hversion == ASTRO_ROPES_PORT))
-
-#define IS_IKE(id) \
-(((id)->hversion == IKE_MERCED_PORT) || ((id)->hversion == IKE_ROPES_PORT))
-
-#define IS_PLUTO(id) \
-(((id)->hversion == PLUTO_MCKINLEY_PORT) || ((id)->hversion == PLUTO_ROPES_PORT))
+#define IS_ASTRO(id) ((id)->hversion == ASTRO_RUNWAY_PORT)
+#define IS_IKE(id) ((id)->hversion == IKE_MERCED_PORT)
+#define IS_PLUTO(id) ((id)->hversion == PLUTO_MCKINLEY_PORT)
#define SBA_FUNC_SIZE 4096 /* SBA configuration function reg set */
-#define ASTRO_IOC_OFFSET 0x20000
-/* Ike's IOC's occupy functions 2 and 3 (not 0 and 1) */
-#define IKE_IOC_OFFSET(p) ((p+2)*SBA_FUNC_SIZE)
-
-#define PLUTO_IOC_OFFSET 0x1000
+#define ASTRO_IOC_OFFSET (32 * SBA_FUNC_SIZE)
+#define PLUTO_IOC_OFFSET (1 * SBA_FUNC_SIZE)
+/* Ike's IOC's occupy functions 2 and 3 */
+#define IKE_IOC_OFFSET(p) ((p+2) * SBA_FUNC_SIZE)
#define IOC_CTRL 0x8 /* IOC_CTRL offset */
#define IOC_CTRL_TC (1 << 0) /* TOC Enable */
@@ -165,6 +136,8 @@ extern struct proc_dir_entry * proc_mckinley_root;
#define IOC_CTRL_DE (1 << 2) /* Dillon Enable */
#define IOC_CTRL_RM (1 << 8) /* Real Mode */
#define IOC_CTRL_NC (1 << 9) /* Non Coherent Mode */
+#define IOC_CTRL_D4 (1 << 11) /* Disable 4-byte coalescing */
+#define IOC_CTRL_DD (1 << 13) /* Disable distr. LMMIO range coalescing */
#define MAX_IOC 2 /* per Ike. Pluto/Astro only have 1. */
@@ -246,9 +219,9 @@ extern struct proc_dir_entry * proc_mckinley_root;
struct ioc {
- unsigned long ioc_hpa; /* I/O MMU base address */
- char *res_map; /* resource map, bit == pdir entry */
- u64 *pdir_base; /* physical base address */
+ void __iomem *ioc_hpa; /* I/O MMU base address */
+ char *res_map; /* resource map, bit == pdir entry */
+ u64 *pdir_base; /* physical base address */
unsigned long ibase; /* pdir IOV Space base - shared w/lba_pci */
unsigned long imask; /* pdir IOV Space mask - shared w/lba_pci */
#ifdef ZX1_SUPPORT
@@ -295,7 +268,7 @@ struct sba_device {
struct parisc_device *dev; /* dev found in bus walk */
struct parisc_device_id *iodc; /* data about dev from firmware */
const char *name;
- unsigned long sba_hpa; /* base address */
+ void __iomem *sba_hpa; /* base address */
spinlock_t sba_lock;
unsigned int flags; /* state/functionality enabled */
unsigned int hw_rev; /* HW revision of chip */
@@ -312,9 +285,6 @@ static struct sba_device *sba_list;
static unsigned long ioc_needs_fdc = 0;
-/* Ratio of Host MEM to IOV Space size */
-static unsigned long sba_mem_ratio = 8;
-
/* global count of IOMMUs in the system */
static unsigned int global_ioc_cnt = 0;
@@ -364,9 +334,9 @@ static int reserve_sba_gart = 1;
* IO Adapter (aka Bus Converter).
*/
static void
-sba_dump_ranges(unsigned long hpa)
+sba_dump_ranges(void __iomem *hpa)
{
- DBG_INIT("SBA at 0x%lx\n", hpa);
+ DBG_INIT("SBA at 0x%p\n", hpa);
DBG_INIT("IOS_DIST_BASE : %Lx\n", READ_REG64(hpa+IOS_DIST_BASE));
DBG_INIT("IOS_DIST_MASK : %Lx\n", READ_REG64(hpa+IOS_DIST_MASK));
DBG_INIT("IOS_DIST_ROUTE : %Lx\n", READ_REG64(hpa+IOS_DIST_ROUTE));
@@ -382,10 +352,9 @@ sba_dump_ranges(unsigned long hpa)
*
* Print the size/location of the IO MMU PDIR.
*/
-static void
-sba_dump_tlb(unsigned long hpa)
+static void sba_dump_tlb(void __iomem *hpa)
{
- DBG_INIT("IO TLB at 0x%lx\n", hpa);
+ DBG_INIT("IO TLB at 0x%p\n", hpa);
DBG_INIT("IOC_IBASE : 0x%Lx\n", READ_REG64(hpa+IOC_IBASE));
DBG_INIT("IOC_IMASK : 0x%Lx\n", READ_REG64(hpa+IOC_IMASK));
DBG_INIT("IOC_TCNFG : 0x%Lx\n", READ_REG64(hpa+IOC_TCNFG));
@@ -547,8 +516,6 @@ sba_search_bitmap(struct ioc *ioc, unsigned long bits_wanted)
unsigned long *res_end = (unsigned long *) &(ioc->res_map[ioc->res_size]);
unsigned long pide = ~0UL;
- ASSERT(((unsigned long) ioc->res_hint & (sizeof(unsigned long) - 1UL)) == 0);
- ASSERT(res_ptr < res_end);
if (bits_wanted > (BITS_PER_LONG/2)) {
/* Search word at a time - no mask needed */
for(; res_ptr < res_end; ++res_ptr) {
@@ -583,8 +550,8 @@ sba_search_bitmap(struct ioc *ioc, unsigned long bits_wanted)
while(res_ptr < res_end)
{
DBG_RES(" %p %lx %lx\n", res_ptr, mask, *res_ptr);
- BUG_ON(0 == mask);
- if(0 == ((*res_ptr) & mask)) {
+ WARN_ON(mask == 0);
+ if(((*res_ptr) & mask) == 0) {
*res_ptr |= mask; /* mark resources busy! */
pide = ((unsigned long)res_ptr - (unsigned long)ioc->res_map);
pide <<= 3; /* convert to bit address */
@@ -593,7 +560,7 @@ sba_search_bitmap(struct ioc *ioc, unsigned long bits_wanted)
}
mask >>= o;
bitshiftcnt += o;
- if (0 == mask) {
+ if (mask == 0) {
mask = RESMAP_MASK(bits_wanted);
bitshiftcnt=0;
res_ptr++;
@@ -631,21 +598,11 @@ sba_alloc_range(struct ioc *ioc, size_t size)
#endif
unsigned long pide;
- ASSERT(pages_needed);
- ASSERT((pages_needed * IOVP_SIZE) <= DMA_CHUNK_SIZE);
- ASSERT(pages_needed <= BITS_PER_LONG);
- ASSERT(0 == (size & ~IOVP_MASK));
-
- /*
- ** "seek and ye shall find"...praying never hurts either...
- ** ggg sacrifices another 710 to the computer gods.
- */
-
pide = sba_search_bitmap(ioc, pages_needed);
if (pide >= (ioc->res_size << 3)) {
pide = sba_search_bitmap(ioc, pages_needed);
if (pide >= (ioc->res_size << 3))
- panic("%s: I/O MMU @ %lx is out of mapping resources\n",
+ panic("%s: I/O MMU @ %p is out of mapping resources\n",
__FILE__, ioc->ioc_hpa);
}
@@ -707,11 +664,6 @@ sba_free_range(struct ioc *ioc, dma_addr_t iova, size_t size)
ioc->used_pages -= bits_not_wanted;
#endif
- ASSERT(m != 0);
- ASSERT(bits_not_wanted);
- ASSERT((bits_not_wanted * IOVP_SIZE) <= DMA_CHUNK_SIZE);
- ASSERT(bits_not_wanted <= BITS_PER_LONG);
- ASSERT((*res_ptr & m) == m); /* verify same bits are set */
*res_ptr &= ~m;
}
@@ -732,8 +684,9 @@ typedef unsigned long space_t;
/**
* sba_io_pdir_entry - fill in one IO PDIR entry
* @pdir_ptr: pointer to IO PDIR entry
- * @sid: process Space ID
+ * @sid: process Space ID - currently only support KERNEL_SPACE
* @vba: Virtual CPU address of buffer to map
+ * @hint: DMA hint set to use for this mapping
*
* SBA Mapping Routine
*
@@ -768,7 +721,6 @@ typedef unsigned long space_t;
* IOMMU uses little endian for the pdir.
*/
-
void SBA_INLINE
sba_io_pdir_entry(u64 *pdir_ptr, space_t sid, unsigned long vba,
unsigned long hint)
@@ -776,12 +728,6 @@ sba_io_pdir_entry(u64 *pdir_ptr, space_t sid, unsigned long vba,
u64 pa; /* physical address */
register unsigned ci; /* coherent index */
- /* We currently only support kernel addresses.
- * fdc instr below will need to reload sr1 with KERNEL_SPACE
- * once we try to support direct DMA to user space.
- */
- ASSERT(sid == KERNEL_SPACE);
-
pa = virt_to_phys(vba);
pa &= IOVP_MASK;
@@ -830,10 +776,6 @@ sba_mark_invalid(struct ioc *ioc, dma_addr_t iova, size_t byte_cnt)
*/
int off = PDIR_INDEX(iovp)*sizeof(u64)+7;
- /* Must be non-zero and rounded up */
- ASSERT(byte_cnt > 0);
- ASSERT(0 == (byte_cnt & ~IOVP_MASK));
-
#ifdef ASSERT_PDIR_SANITY
/* Assert first pdir entry is set */
if (0x80 != (((u8 *) ioc->pdir_base)[off])) {
@@ -843,8 +785,6 @@ sba_mark_invalid(struct ioc *ioc, dma_addr_t iova, size_t byte_cnt)
if (byte_cnt <= IOVP_SIZE)
{
- ASSERT( off < ioc->pdir_size);
-
iovp |= IOVP_SHIFT; /* set "size" field for PCOM */
/*
@@ -858,11 +798,7 @@ sba_mark_invalid(struct ioc *ioc, dma_addr_t iova, size_t byte_cnt)
u32 t = get_order(byte_cnt) + PAGE_SHIFT;
iovp |= t;
- ASSERT(t <= 31); /* 2GB! Max value of "size" field */
-
do {
- /* verify this pdir entry is enabled */
- ASSERT(0x80 == (((u8 *) ioc->pdir_base)[off] & 0x80));
/* clear I/O Pdir entry "valid" bit first */
((u8 *)(ioc->pdir_base))[off] = 0;
off += sizeof(u64);
@@ -880,17 +816,21 @@ sba_mark_invalid(struct ioc *ioc, dma_addr_t iova, size_t byte_cnt)
*
* See Documentation/DMA-mapping.txt
*/
-static int
-sba_dma_supported( struct device *dev, u64 mask)
+static int sba_dma_supported( struct device *dev, u64 mask)
{
+ struct ioc *ioc;
if (dev == NULL) {
printk(KERN_ERR MODULE_NAME ": EISA/ISA/et al not supported\n");
BUG();
return(0);
}
- /* only support 32-bit PCI devices - no DAC support (yet) */
- return((int) (mask == 0xffffffffUL));
+ ioc = GET_IOC(dev);
+
+ /* check if mask is > than the largest IO Virt Address */
+
+ return((int) (mask >= (ioc->ibase +
+ (ioc->pdir_size / sizeof(u64) * IOVP_SIZE) )));
}
@@ -914,11 +854,7 @@ sba_map_single(struct device *dev, void *addr, size_t size,
u64 *pdir_start;
int pide;
- ASSERT(size > 0);
- ASSERT(size <= DMA_CHUNK_SIZE);
-
ioc = GET_IOC(dev);
- ASSERT(ioc);
/* save offset bits */
offset = ((dma_addr_t) (long) addr) & ~IOVP_MASK;
@@ -944,7 +880,6 @@ sba_map_single(struct device *dev, void *addr, size_t size,
pdir_start = &(ioc->pdir_base[pide]);
while (size > 0) {
- ASSERT(((u8 *)pdir_start)[7] == 0); /* verify availability */
sba_io_pdir_entry(pdir_start, KERNEL_SPACE, (unsigned long) addr, 0);
DBG_RUN(" pdir 0x%p %02x%02x%02x%02x%02x%02x%02x%02x\n",
@@ -992,14 +927,10 @@ sba_unmap_single(struct device *dev, dma_addr_t iova, size_t size,
unsigned long flags;
dma_addr_t offset;
- ioc = GET_IOC(dev);
- ASSERT(ioc);
+ DBG_RUN("%s() iovp 0x%lx/%x\n", __FUNCTION__, (long) iova, size);
+ ioc = GET_IOC(dev);
offset = iova & ~IOVP_MASK;
-
- DBG_RUN("%s() iovp 0x%lx/%x\n",
- __FUNCTION__, (long) iova, size);
-
iova ^= offset; /* clear offset bits */
size += offset;
size = ROUNDUP(size, IOVP_SIZE);
@@ -1131,7 +1062,6 @@ sba_map_sg(struct device *dev, struct scatterlist *sglist, int nents,
DBG_RUN_SG("%s() START %d entries\n", __FUNCTION__, nents);
ioc = GET_IOC(dev);
- ASSERT(ioc);
/* Fast path single entry scatterlists. */
if (nents == 1) {
@@ -1186,7 +1116,6 @@ sba_map_sg(struct device *dev, struct scatterlist *sglist, int nents,
spin_unlock_irqrestore(&ioc->res_lock, flags);
- ASSERT(coalesced == filled);
DBG_RUN_SG("%s() DONE %d mappings\n", __FUNCTION__, filled);
return filled;
@@ -1215,7 +1144,6 @@ sba_unmap_sg(struct device *dev, struct scatterlist *sglist, int nents,
__FUNCTION__, nents, sg_virt_addr(sglist), sglist->length);
ioc = GET_IOC(dev);
- ASSERT(ioc);
#ifdef SBA_COLLECT_STATS
ioc->usg_calls++;
@@ -1394,16 +1322,27 @@ sba_alloc_pdir(unsigned int pdir_size)
return (void *) pdir_base;
}
-static void
-sba_ioc_init_pluto(struct parisc_device *sba, struct ioc *ioc, int ioc_num)
+/* setup Mercury or Elroy IBASE/IMASK registers. */
+static void setup_ibase_imask(struct parisc_device *sba, struct ioc *ioc, int ioc_num)
{
- /* lba_set_iregs() is in arch/parisc/kernel/lba_pci.c */
+ /* lba_set_iregs() is in drivers/parisc/lba_pci.c */
extern void lba_set_iregs(struct parisc_device *, u32, u32);
+ struct device *dev;
+
+ list_for_each_entry(dev, &sba->dev.children, node) {
+ struct parisc_device *lba = to_parisc_device(dev);
+ int rope_num = (lba->hpa >> 13) & 0xf;
+ if (rope_num >> 3 == ioc_num)
+ lba_set_iregs(lba, ioc->ibase, ioc->imask);
+ }
+}
+static void
+sba_ioc_init_pluto(struct parisc_device *sba, struct ioc *ioc, int ioc_num)
+{
u32 iova_space_mask;
u32 iova_space_size;
int iov_order, tcnfg;
- struct parisc_device *lba;
#if SBA_AGP_SUPPORT
int agp_found = 0;
#endif
@@ -1449,7 +1388,7 @@ sba_ioc_init_pluto(struct parisc_device *sba, struct ioc *ioc, int ioc_num)
ioc->hint_shift_pdir, ioc->hint_mask_pdir);
#endif
- ASSERT((((unsigned long) ioc->pdir_base) & PAGE_MASK) == (unsigned long) ioc->pdir_base);
+ WARN_ON((((unsigned long) ioc->pdir_base) & PAGE_MASK) != (unsigned long) ioc->pdir_base);
WRITE_REG(virt_to_phys(ioc->pdir_base), ioc->ioc_hpa + IOC_PDIR_BASE);
/* build IMASK for IOC and Elroy */
@@ -1461,14 +1400,7 @@ sba_ioc_init_pluto(struct parisc_device *sba, struct ioc *ioc, int ioc_num)
#endif
sba_dump_tlb(ioc->ioc_hpa);
- /*
- ** setup Mercury IBASE/IMASK registers as well.
- */
- for (lba = sba->child; lba; lba = lba->sibling) {
- int rope_num = (lba->hpa >> 13) & 0xf;
- if (rope_num >> 3 == ioc_num)
- lba_set_iregs(lba, ioc->ibase, ioc->imask);
- }
+ setup_ibase_imask(sba, ioc, ioc_num);
WRITE_REG(ioc->imask, ioc->ioc_hpa + IOC_IMASK);
@@ -1534,13 +1466,8 @@ sba_ioc_init_pluto(struct parisc_device *sba, struct ioc *ioc, int ioc_num)
static void
sba_ioc_init(struct parisc_device *sba, struct ioc *ioc, int ioc_num)
{
- /* lba_set_iregs() is in arch/parisc/kernel/lba_pci.c */
- extern void lba_set_iregs(struct parisc_device *, u32, u32);
-
u32 iova_space_size, iova_space_mask;
- int pdir_size, iov_order;
- unsigned long physmem;
- struct parisc_device *lba;
+ unsigned int pdir_size, iov_order;
/*
** Determine IOVA Space size from memory size.
@@ -1556,16 +1483,15 @@ sba_ioc_init(struct parisc_device *sba, struct ioc *ioc, int ioc_num)
** for DMA hints - ergo only 30 bits max.
*/
- physmem = num_physpages << PAGE_SHIFT;
- iova_space_size = (u32) (physmem/(sba_mem_ratio*global_ioc_cnt));
+ iova_space_size = (u32) (num_physpages/global_ioc_cnt);
/* limit IOVA space size to 1MB-1GB */
- if (iova_space_size < 1024*1024) {
- iova_space_size = 1024*1024;
+ if (iova_space_size < (1 << (20 - PAGE_SHIFT))) {
+ iova_space_size = 1 << (20 - PAGE_SHIFT);
}
#ifdef __LP64__
- else if (iova_space_size > 512*1024*1024) {
- iova_space_size = 512*1024*1024;
+ else if (iova_space_size > (1 << (30 - PAGE_SHIFT))) {
+ iova_space_size = 1 << (30 - PAGE_SHIFT);
}
#endif
@@ -1574,21 +1500,19 @@ sba_ioc_init(struct parisc_device *sba, struct ioc *ioc, int ioc_num)
** thus, pdir/res_map will also be log2().
** PIRANHA BUG: Exception is when IO Pdir is 2MB (gets reduced)
*/
- iov_order = get_order(iova_space_size >> (IOVP_SHIFT-PAGE_SHIFT));
- ASSERT(iov_order <= (30 - IOVP_SHIFT)); /* iova_space_size <= 1GB */
- ASSERT(iov_order >= (20 - IOVP_SHIFT)); /* iova_space_size >= 1MB */
- iova_space_size = 1 << (iov_order + IOVP_SHIFT);
-
- ioc->pdir_size = pdir_size = (iova_space_size/IOVP_SIZE) * sizeof(u64);
+ iov_order = get_order(iova_space_size << PAGE_SHIFT);
- ASSERT(pdir_size < 4*1024*1024); /* max pdir size == 2MB */
+ /* iova_space_size is now bytes, not pages */
+ iova_space_size = 1 << (iov_order + PAGE_SHIFT);
- /* Verify it's a power of two */
- ASSERT((1 << get_order(pdir_size)) == (pdir_size >> PAGE_SHIFT));
+ ioc->pdir_size = pdir_size = (iova_space_size/IOVP_SIZE) * sizeof(u64);
- DBG_INIT("%s() hpa 0x%lx mem %dMB IOV %dMB (%d bits) PDIR size 0x%0x\n",
- __FUNCTION__, ioc->ioc_hpa, (int) (physmem>>20),
- iova_space_size>>20, iov_order + PAGE_SHIFT, pdir_size);
+ DBG_INIT("%s() hpa 0x%lx mem %ldMB IOV %dMB (%d bits)\n",
+ __FUNCTION__,
+ ioc->ioc_hpa,
+ (unsigned long) num_physpages >> (20 - PAGE_SHIFT),
+ iova_space_size>>20,
+ iov_order + PAGE_SHIFT);
ioc->pdir_base = sba_alloc_pdir(pdir_size);
@@ -1604,7 +1528,6 @@ sba_ioc_init(struct parisc_device *sba, struct ioc *ioc, int ioc_num)
ioc->hint_shift_pdir, ioc->hint_mask_pdir);
#endif
- ASSERT((((unsigned long) ioc->pdir_base) & PAGE_MASK) == (unsigned long) ioc->pdir_base);
WRITE_REG64(virt_to_phys(ioc->pdir_base), ioc->ioc_hpa + IOC_PDIR_BASE);
/* build IMASK for IOC and Elroy */
@@ -1630,14 +1553,7 @@ sba_ioc_init(struct parisc_device *sba, struct ioc *ioc, int ioc_num)
** can't reprogram them the way drivers want.
*/
- /*
- ** setup Elroy IBASE/IMASK registers as well.
- */
- for (lba = sba->child; lba; lba = lba->sibling) {
- int rope_num = (lba->hpa >> 13) & 0xf;
- if (rope_num >> 3 == ioc_num)
- lba_set_iregs(lba, ioc->ibase, ioc->imask);
- }
+ setup_ibase_imask(sba, ioc, ioc_num);
/*
** Program the IOC's ibase and enable IOVA translation
@@ -1672,8 +1588,12 @@ sba_ioc_init(struct parisc_device *sba, struct ioc *ioc, int ioc_num)
**
**************************************************************************/
-static void
-sba_hw_init(struct sba_device *sba_dev)
+static void __iomem *ioc_remap(struct sba_device *sba_dev, int offset)
+{
+ return ioremap(sba_dev->dev->hpa + offset, SBA_FUNC_SIZE);
+}
+
+static void sba_hw_init(struct sba_device *sba_dev)
{
int i;
int num_ioc;
@@ -1682,24 +1602,55 @@ sba_hw_init(struct sba_device *sba_dev)
if (!is_pdc_pat()) {
/* Shutdown the USB controller on Astro-based workstations.
** Once we reprogram the IOMMU, the next DMA performed by
- ** USB will HPMC the box.
+ ** USB will HPMC the box. USB is only enabled if a
+ ** keyboard is present and found.
+ **
+ ** With serial console, j6k v5.0 firmware says:
+ ** mem_kbd hpa 0xfee003f8 sba 0x0 pad 0x0 cl_class 0x7
+ **
+ ** FIXME: Using GFX+USB console at power up but direct
+ ** linux to serial console is still broken.
+ ** USB could generate DMA so we must reset USB.
+ ** The proper sequence would be:
+ ** o block console output
+ ** o reset USB device
+ ** o reprogram serial port
+ ** o unblock console output
*/
- pdc_io_reset_devices();
+ if (PAGE0->mem_kbd.cl_class == CL_KEYBD) {
+ pdc_io_reset_devices();
+ }
- /*
- ** XXX May need something more sophisticated to deal
- ** with DMA from LAN. Maybe use page zero boot device
- ** as a handle to talk to PDC about which device to
- ** shutdown. This also needs to work for is_pdc_pat().
- */
}
+
+#if 0
+printk("sba_hw_init(): mem_boot 0x%x 0x%x 0x%x 0x%x\n", PAGE0->mem_boot.hpa,
+ PAGE0->mem_boot.spa, PAGE0->mem_boot.pad, PAGE0->mem_boot.cl_class);
+
+ /*
+ ** Need to deal with DMA from LAN.
+ ** Maybe use page zero boot device as a handle to talk
+ ** to PDC about which device to shutdown.
+ **
+ ** Netbooting, j6k v5.0 firmware says:
+ ** mem_boot hpa 0xf4008000 sba 0x0 pad 0x0 cl_class 0x1002
+ ** ARGH! invalid class.
+ */
+ if ((PAGE0->mem_boot.cl_class != CL_RANDOM)
+ && (PAGE0->mem_boot.cl_class != CL_SEQU)) {
+ pdc_io_reset();
+ }
+#endif
+
if (!IS_PLUTO(sba_dev->iodc)) {
ioc_ctl = READ_REG(sba_dev->sba_hpa+IOC_CTRL);
DBG_INIT("%s() hpa 0x%lx ioc_ctl 0x%Lx ->",
__FUNCTION__, sba_dev->sba_hpa, ioc_ctl);
ioc_ctl &= ~(IOC_CTRL_RM | IOC_CTRL_NC | IOC_CTRL_CE);
- ioc_ctl |= IOC_CTRL_TC; /* Astro: firmware enables this */
+ ioc_ctl |= IOC_CTRL_DD | IOC_CTRL_D4 | IOC_CTRL_TC;
+ /* j6700 v1.6 firmware sets 0x294f */
+ /* A500 firmware sets 0x4d */
WRITE_REG(ioc_ctl, sba_dev->sba_hpa+IOC_CTRL);
@@ -1712,7 +1663,7 @@ sba_hw_init(struct sba_device *sba_dev)
if (IS_ASTRO(sba_dev->iodc)) {
int err;
/* PAT_PDC (L-class) also reports the same goofy base */
- sba_dev->ioc[0].ioc_hpa = ASTRO_IOC_OFFSET;
+ sba_dev->ioc[0].ioc_hpa = ioc_remap(sba_dev, ASTRO_IOC_OFFSET);
num_ioc = 1;
sba_dev->chip_resv.name = "Astro Intr Ack";
@@ -1730,32 +1681,32 @@ sba_hw_init(struct sba_device *sba_dev)
* corrected when we add it with IKE's IOC offset.
* Doesnt look clean, but fewer code.
*/
- sba_dev->ioc[0].ioc_hpa = -PLUTO_IOC_OFFSET;
+ sba_dev->ioc[0].ioc_hpa = ioc_remap(sba_dev, PLUTO_IOC_OFFSET);
num_ioc = 1;
sba_dev->chip_resv.name = "Pluto Intr/PIOP/VGA";
sba_dev->chip_resv.start = PCI_F_EXTEND | 0xfee00000UL;
sba_dev->chip_resv.end = PCI_F_EXTEND | (0xff200000UL - 1);
err = request_resource(&iomem_resource, &(sba_dev->chip_resv));
- BUG_ON(err < 0);
+ WARN_ON(err < 0);
sba_dev->iommu_resv.name = "IOVA Space";
sba_dev->iommu_resv.start = 0x40000000UL;
sba_dev->iommu_resv.end = 0x50000000UL - 1;
err = request_resource(&iomem_resource, &(sba_dev->iommu_resv));
- BUG_ON(err < 0);
+ WARN_ON(err < 0);
} else {
/* IS_IKE (ie N-class, L3000, L1500) */
- sba_dev->ioc[0].ioc_hpa = sba_dev->ioc[1].ioc_hpa = 0;
+ sba_dev->ioc[0].ioc_hpa = ioc_remap(sba_dev, IKE_IOC_OFFSET(0));
+ sba_dev->ioc[1].ioc_hpa = ioc_remap(sba_dev, IKE_IOC_OFFSET(1));
num_ioc = 2;
/* TODO - LOOKUP Ike/Stretch chipset mem map */
}
+ /* XXX: What about Reo? */
sba_dev->num_ioc = num_ioc;
for (i = 0; i < num_ioc; i++) {
- sba_dev->ioc[i].ioc_hpa += sba_dev->sba_hpa + IKE_IOC_OFFSET(i);
-
/*
** Make sure the box crashes if we get any errors on a rope.
*/
@@ -1771,6 +1722,16 @@ sba_hw_init(struct sba_device *sba_dev)
/* flush out the writes */
READ_REG(sba_dev->ioc[i].ioc_hpa + ROPE7_CTL);
+ DBG_INIT(" ioc[%d] ROPE_CFG 0x%Lx ROPE_DBG 0x%Lx\n",
+ i,
+ READ_REG(sba_dev->ioc[i].ioc_hpa + 0x40),
+ READ_REG(sba_dev->ioc[i].ioc_hpa + 0x50)
+ );
+ DBG_INIT(" STATUS_CONTROL 0x%Lx FLUSH_CTRL 0x%Lx\n",
+ READ_REG(sba_dev->ioc[i].ioc_hpa + 0x108),
+ READ_REG(sba_dev->ioc[i].ioc_hpa + 0x400)
+ );
+
if (IS_PLUTO(sba_dev->iodc)) {
sba_ioc_init_pluto(sba_dev->dev, &(sba_dev->ioc[i]), i);
} else {
@@ -1984,16 +1945,6 @@ static struct parisc_device_id sba_tbl[] = {
{ HPHW_BCPORT, HVERSION_REV_ANY_ID, REO_MERCED_PORT, 0xc },
{ HPHW_BCPORT, HVERSION_REV_ANY_ID, REOG_MERCED_PORT, 0xc },
{ HPHW_IOA, HVERSION_REV_ANY_ID, PLUTO_MCKINLEY_PORT, 0xc },
-/* These two entries commented out because we don't find them in a
- * buswalk yet. If/when we do, they would cause us to think we had
- * many more SBAs then we really do.
- * { HPHW_BCPORT, HVERSION_REV_ANY_ID, ASTRO_ROPES_PORT, 0xc },
- * { HPHW_BCPORT, HVERSION_REV_ANY_ID, IKE_ROPES_PORT, 0xc },
- */
-/* We shall also comment out Pluto Ropes Port since bus walk doesnt
- * report it yet.
- * { HPHW_BCPORT, HVERSION_REV_ANY_ID, PLUTO_ROPES_PORT, 0xc },
- */
{ 0, }
};
@@ -2017,18 +1968,19 @@ sba_driver_callback(struct parisc_device *dev)
u32 func_class;
int i;
char *version;
+ void __iomem *sba_addr = ioremap(dev->hpa, SBA_FUNC_SIZE);
- sba_dump_ranges(dev->hpa);
+ sba_dump_ranges(sba_addr);
/* Read HW Rev First */
- func_class = READ_REG(dev->hpa + SBA_FCLASS);
+ func_class = READ_REG(sba_addr + SBA_FCLASS);
if (IS_ASTRO(&dev->id)) {
unsigned long fclass;
static char astro_rev[]="Astro ?.?";
/* Astro is broken...Read HW Rev First */
- fclass = READ_REG(dev->hpa);
+ fclass = READ_REG(sba_addr);
astro_rev[6] = '1' + (char) (fclass & 0x7);
astro_rev[8] = '0' + (char) ((fclass & 0x18) >> 3);
@@ -2061,12 +2013,12 @@ sba_driver_callback(struct parisc_device *dev)
MODULE_NAME, version, dev->hpa);
sba_dev = kmalloc(sizeof(struct sba_device), GFP_KERNEL);
- if (NULL == sba_dev) {
+ if (!sba_dev) {
printk(KERN_ERR MODULE_NAME " - couldn't alloc sba_device\n");
- return(1);
+ return -ENOMEM;
}
- dev->sysdata = (void *) sba_dev;
+ parisc_set_drvdata(dev, sba_dev);
memset(sba_dev, 0, sizeof(struct sba_device));
for(i=0; i<MAX_IOC; i++)
@@ -2076,7 +2028,7 @@ sba_driver_callback(struct parisc_device *dev)
sba_dev->hw_rev = func_class;
sba_dev->iodc = &dev->id;
sba_dev->name = dev->name;
- sba_dev->sba_hpa = dev->hpa; /* faster access */
+ sba_dev->sba_hpa = sba_addr;
sba_get_pat_resources(sba_dev);
sba_hw_init(sba_dev);
@@ -2100,7 +2052,7 @@ sba_driver_callback(struct parisc_device *dev)
#endif
parisc_vmerge_boundary = IOVP_SIZE;
parisc_vmerge_max_size = IOVP_SIZE * BITS_PER_LONG;
-
+ parisc_has_iommu();
return 0;
}
@@ -2129,7 +2081,7 @@ void * sba_get_iommu(struct parisc_device *pci_hba)
char t = sba_dev->id.hw_type;
int iocnum = (pci_hba->hw_path >> 3); /* rope # */
- BUG_ON((t != HPHW_IOA) && (t != HPHW_BCPORT));
+ WARN_ON((t != HPHW_IOA) && (t != HPHW_BCPORT));
return &(sba->ioc[iocnum]);
}
@@ -2159,7 +2111,7 @@ void sba_directed_lmmio(struct parisc_device *pci_hba, struct resource *r)
/* Astro has 4 directed ranges. Not sure about Ike/Pluto/et al */
for (i=0; i<4; i++) {
int base, size;
- unsigned long reg = sba->sba_hpa + i*0x18;
+ void __iomem *reg = sba->sba_hpa + i*0x18;
base = READ_REG32(reg + LMMIO_DIRECT0_BASE);
if ((base & 1) == 0)
diff --git a/drivers/parisc/superio.c b/drivers/parisc/superio.c
index 18779674d5762..e0efed796b923 100644
--- a/drivers/parisc/superio.c
+++ b/drivers/parisc/superio.c
@@ -495,7 +495,7 @@ static struct pci_driver superio_driver = {
static int __init superio_modinit(void)
{
- return pci_module_init(&superio_driver);
+ return pci_register_driver(&superio_driver);
}
static void __exit superio_exit(void)
diff --git a/drivers/parisc/wax.c b/drivers/parisc/wax.c
index c384d5e802796..e547d7d024d8b 100644
--- a/drivers/parisc/wax.c
+++ b/drivers/parisc/wax.c
@@ -25,20 +25,27 @@
#include "gsc.h"
#define WAX_GSC_IRQ 7 /* Hardcoded Interrupt for GSC */
-#define WAX_GSC_NMI_IRQ 29
static void wax_choose_irq(struct parisc_device *dev, void *ctrl)
{
int irq;
switch (dev->id.sversion) {
- case 0x73: irq = 1; break; /* HIL */
- case 0x8c: irq = 6; break; /* RS232 */
- case 0x90: irq = 10; break; /* WAX EISA BA */
+ case 0x73: irq = 1; break; /* i8042 General */
+ case 0x8c: irq = 6; break; /* Serial */
+ case 0x90: irq = 10; break; /* EISA */
default: return; /* Unknown */
}
gsc_asic_assign_irq(ctrl, irq, &dev->irq);
+
+ switch (dev->id.sversion) {
+ case 0x73: irq = 2; break; /* i8042 High-priority */
+ case 0x90: irq = 0; break; /* EISA NMI */
+ default: return; /* No secondary IRQ */
+ }
+
+ gsc_asic_assign_irq(ctrl, irq, &dev->aux_irq);
}
static void __init
@@ -46,7 +53,7 @@ wax_init_irq(struct gsc_asic *wax)
{
unsigned long base = wax->hpa;
- /* Stop WAX barking for a bit */
+ /* Wax-off */
gsc_writel(0x00000000, base+OFFSET_IMR);
/* clear pending interrupts */
@@ -59,11 +66,6 @@ wax_init_irq(struct gsc_asic *wax)
/* Resets */
// gsc_writel(0xFFFFFFFF, base+0x1000); /* HIL */
// gsc_writel(0xFFFFFFFF, base+0x2000); /* RS232-B on Wax */
-
- /* Ok we hit it on the head with a hammer, our Dog is now
- ** comatose and muzzled. Devices will now unmask WAX
- ** interrupts as they are registered as irq's in the WAX range.
- */
}
int __init
@@ -78,7 +80,7 @@ wax_init_chip(struct parisc_device *dev)
if (!wax)
return -ENOMEM;
- wax->name = "Wax";
+ wax->name = "wax";
wax->hpa = dev->hpa;
wax->version = 0; /* gsc_readb(wax->hpa+WAX_VER); */
@@ -132,7 +134,7 @@ static struct parisc_device_id wax_tbl[] = {
MODULE_DEVICE_TABLE(parisc, wax_tbl);
struct parisc_driver wax_driver = {
- .name = "Wax",
+ .name = "wax",
.id_table = wax_tbl,
.probe = wax_init_chip,
};
diff --git a/drivers/parport/Kconfig b/drivers/parport/Kconfig
index 31dc05d081754..731010e0e6f6a 100644
--- a/drivers/parport/Kconfig
+++ b/drivers/parport/Kconfig
@@ -46,15 +46,9 @@ config PARPORT_PC
If unsure, say Y.
-config PARPORT_PC_CML1
- tristate
- depends on PARPORT!=n && PARPORT_PC!=n
- default PARPORT_PC if SERIAL_8250=y
- default m if SERIAL_8250=m
-
config PARPORT_SERIAL
tristate "Multi-IO cards (parallel and serial)"
- depends on SERIAL_8250!=n && PARPORT_PC_CML1 && PCI
+ depends on SERIAL_8250 && PARPORT_PC && PCI
help
This adds support for multi-IO PCI cards that have parallel and
serial ports. You should say Y or M here. If you say M, the module
@@ -88,13 +82,18 @@ config PARPORT_PC_PCMCIA
Say Y here if you need PCMCIA support for your PC-style parallel
ports. If unsure, say N.
+config PARPORT_NOT_PC
+ bool
+
config PARPORT_ARC
tristate "Archimedes hardware"
depends on ARM && PARPORT
+ select PARPORT_NOT_PC
config PARPORT_AMIGA
tristate "Amiga builtin port"
depends on AMIGA && PARPORT
+ select PARPORT_NOT_PC
help
Say Y here if you need support for the parallel port hardware on
Amiga machines. This code is also available as a module (say M),
@@ -103,6 +102,7 @@ config PARPORT_AMIGA
config PARPORT_MFC3
tristate "Multiface III parallel port"
depends on ZORRO && PARPORT
+ select PARPORT_NOT_PC
help
Say Y here if you need parallel port support for the MFC3 card.
This code is also available as a module (say M), called
@@ -111,6 +111,7 @@ config PARPORT_MFC3
config PARPORT_ATARI
tristate "Atari hardware"
depends on ATARI && PARPORT
+ select PARPORT_NOT_PC
help
Say Y here if you need support for the parallel port hardware on
Atari machines. This code is also available as a module (say M),
@@ -118,27 +119,18 @@ config PARPORT_ATARI
config PARPORT_GSC
tristate
- depends on GSC
- default PARPORT
+ default GSC
+ depends on PARPORT
config PARPORT_SUNBPP
tristate "Sparc hardware (EXPERIMENTAL)"
- depends on SBUS && EXPERIMENTAL && PARPORT
+ depends on SBUS && PARPORT && EXPERIMENTAL
+ select PARPORT_NOT_PC
help
This driver provides support for the bidirectional parallel port
found on many Sun machines. Note that many of the newer Ultras
actually have pc style hardware instead.
-# If exactly one hardware type is selected then parport will optimise away
-# support for loading any others. Defeat this if the user is keen.
-config PARPORT_OTHER
- bool "Support foreign hardware"
- depends on PARPORT
- help
- Say Y here if you want to be able to load driver modules to support
- other non-standard types of parallel ports. This causes a
- performance loss, so most people say N.
-
config PARPORT_1284
bool "IEEE 1284 transfer modes"
depends on PARPORT
diff --git a/drivers/parport/ieee1284.c b/drivers/parport/ieee1284.c
index a1bd5416d4b68..694bae162fed9 100644
--- a/drivers/parport/ieee1284.c
+++ b/drivers/parport/ieee1284.c
@@ -1,7 +1,7 @@
/* $Id: parport_ieee1284.c,v 1.4 1997/10/19 21:37:21 philip Exp $
* IEEE-1284 implementation for parport.
*
- * Authors: Phil Blundell <Philip.Blundell@pobox.com>
+ * Authors: Phil Blundell <philb@gnu.org>
* Carsten Gross <carsten@sol.wohnheim.uni-ulm.de>
* Jose Renau <renau@acm.org>
* Tim Waugh <tim@cyberelk.demon.co.uk> (largely rewritten)
diff --git a/drivers/parport/parport_arc.c b/drivers/parport/parport_arc.c
index c6d9c754527a4..b35bb4f48d628 100644
--- a/drivers/parport/parport_arc.c
+++ b/drivers/parport/parport_arc.c
@@ -1,6 +1,6 @@
/* Low-level parallel port routines for Archimedes onboard hardware
*
- * Author: Phil Blundell <Philip.Blundell@pobox.com>
+ * Author: Phil Blundell <philb@gnu.org>
*/
/* This driver is for the parallel port hardware found on Acorn's old
diff --git a/drivers/parport/parport_gsc.c b/drivers/parport/parport_gsc.c
index b0611e60abb91..02d72acd1c896 100644
--- a/drivers/parport/parport_gsc.c
+++ b/drivers/parport/parport_gsc.c
@@ -12,7 +12,7 @@
*
* based on parport_pc.c by
* Grant Guenther <grant@torque.net>
- * Phil Blundell <Philip.Blundell@pobox.com>
+ * Phil Blundell <philb@gnu.org>
* Tim Waugh <tim@cyberelk.demon.co.uk>
* Jose Renau <renau@acm.org>
* David Campbell <campbell@torque.net>
@@ -42,7 +42,7 @@
#include <asm/pdc.h>
#include <asm/parisc-device.h>
#include <asm/hardware.h>
-#include <asm/parport_gsc.h>
+#include "parport_gsc.h"
MODULE_AUTHOR("Helge Deller <deller@gmx.de>");
@@ -87,95 +87,6 @@ static irqreturn_t parport_gsc_interrupt(int irq, void *dev_id, struct pt_regs *
return IRQ_HANDLED;
}
-void parport_gsc_write_data(struct parport *p, unsigned char d)
-{
- parport_writeb (d, DATA (p));
-}
-
-unsigned char parport_gsc_read_data(struct parport *p)
-{
- unsigned char c = parport_readb (DATA (p));
- return c;
-}
-
-void parport_gsc_write_control(struct parport *p, unsigned char d)
-{
- const unsigned char wm = (PARPORT_CONTROL_STROBE |
- PARPORT_CONTROL_AUTOFD |
- PARPORT_CONTROL_INIT |
- PARPORT_CONTROL_SELECT);
-
- /* Take this out when drivers have adapted to the newer interface. */
- if (d & 0x20) {
- pr_debug("%s (%s): use data_reverse for this!\n",
- p->name, p->cad->name);
- parport_gsc_data_reverse (p);
- }
-
- __parport_gsc_frob_control (p, wm, d & wm);
-}
-
-unsigned char parport_gsc_read_control(struct parport *p)
-{
- const unsigned char wm = (PARPORT_CONTROL_STROBE |
- PARPORT_CONTROL_AUTOFD |
- PARPORT_CONTROL_INIT |
- PARPORT_CONTROL_SELECT);
- const struct parport_gsc_private *priv = p->physport->private_data;
- return priv->ctr & wm; /* Use soft copy */
-}
-
-unsigned char parport_gsc_frob_control (struct parport *p, unsigned char mask,
- unsigned char val)
-{
- const unsigned char wm = (PARPORT_CONTROL_STROBE |
- PARPORT_CONTROL_AUTOFD |
- PARPORT_CONTROL_INIT |
- PARPORT_CONTROL_SELECT);
-
- /* Take this out when drivers have adapted to the newer interface. */
- if (mask & 0x20) {
- pr_debug("%s (%s): use data_%s for this!\n",
- p->name, p->cad->name,
- (val & 0x20) ? "reverse" : "forward");
- if (val & 0x20)
- parport_gsc_data_reverse (p);
- else
- parport_gsc_data_forward (p);
- }
-
- /* Restrict mask and val to control lines. */
- mask &= wm;
- val &= wm;
-
- return __parport_gsc_frob_control (p, mask, val);
-}
-
-unsigned char parport_gsc_read_status(struct parport *p)
-{
- return parport_readb (STATUS (p));
-}
-
-void parport_gsc_disable_irq(struct parport *p)
-{
- __parport_gsc_frob_control (p, 0x10, 0);
-}
-
-void parport_gsc_enable_irq(struct parport *p)
-{
- __parport_gsc_frob_control (p, 0x10, 0x10);
-}
-
-void parport_gsc_data_forward (struct parport *p)
-{
- __parport_gsc_frob_control (p, 0x20, 0);
-}
-
-void parport_gsc_data_reverse (struct parport *p)
-{
- __parport_gsc_frob_control (p, 0x20, 0x20);
-}
-
void parport_gsc_init_state(struct pardevice *dev, struct parport_state *s)
{
s->u.pc.ctr = 0xc | (dev->irq_func ? 0x10 : 0x0);
diff --git a/include/asm-parisc/parport_gsc.h b/drivers/parport/parport_gsc.h
index 686d4f12777b5..662f6c1fee5df 100644
--- a/include/asm-parisc/parport_gsc.h
+++ b/drivers/parport/parport_gsc.h
@@ -1,5 +1,35 @@
-#ifndef __LINUX_PARPORT_GSC_H
-#define __LINUX_PARPORT_GSC_H
+/*
+ * Low-level parallel-support for PC-style hardware integrated in the
+ * LASI-Controller (on GSC-Bus) for HP-PARISC Workstations
+ *
+ * (C) 1999-2001 by Helge Deller <deller@gmx.de>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the 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
+ *
+ * based on parport_pc.c by
+ * Grant Guenther <grant@torque.net>
+ * Phil Blundell <Philip.Blundell@pobox.com>
+ * Tim Waugh <tim@cyberelk.demon.co.uk>
+ * Jose Renau <renau@acm.org>
+ * David Campbell <campbell@torque.net>
+ * Andrea Arcangeli
+ */
+
+#ifndef __DRIVERS_PARPORT_PARPORT_GSC_H
+#define __DRIVERS_PARPORT_PARPORT_GSC_H
#include <asm/io.h>
#include <linux/delay.h>
@@ -52,7 +82,7 @@ struct parport_gsc_private {
struct pci_dev *dev;
};
-extern __inline__ void parport_gsc_write_data(struct parport *p, unsigned char d)
+static inline void parport_gsc_write_data(struct parport *p, unsigned char d)
{
#ifdef DEBUG_PARPORT
printk (KERN_DEBUG "parport_gsc_write_data(%p,0x%02x)\n", p, d);
@@ -60,7 +90,7 @@ extern __inline__ void parport_gsc_write_data(struct parport *p, unsigned char d
parport_writeb(d, DATA(p));
}
-extern __inline__ unsigned char parport_gsc_read_data(struct parport *p)
+static inline unsigned char parport_gsc_read_data(struct parport *p)
{
unsigned char val = parport_readb (DATA (p));
#ifdef DEBUG_PARPORT
@@ -72,9 +102,9 @@ extern __inline__ unsigned char parport_gsc_read_data(struct parport *p)
/* __parport_gsc_frob_control differs from parport_gsc_frob_control in that
* it doesn't do any extra masking. */
-static __inline__ unsigned char __parport_gsc_frob_control (struct parport *p,
- unsigned char mask,
- unsigned char val)
+static inline unsigned char __parport_gsc_frob_control(struct parport *p,
+ unsigned char mask,
+ unsigned char val)
{
struct parport_gsc_private *priv = p->physport->private_data;
unsigned char ctr = priv->ctr;
@@ -90,17 +120,17 @@ static __inline__ unsigned char __parport_gsc_frob_control (struct parport *p,
return ctr;
}
-extern __inline__ void parport_gsc_data_reverse (struct parport *p)
+static inline void parport_gsc_data_reverse(struct parport *p)
{
__parport_gsc_frob_control (p, 0x20, 0x20);
}
-extern __inline__ void parport_gsc_data_forward (struct parport *p)
+static inline void parport_gsc_data_forward(struct parport *p)
{
__parport_gsc_frob_control (p, 0x20, 0x00);
}
-extern __inline__ void parport_gsc_write_control (struct parport *p,
+static inline void parport_gsc_write_control(struct parport *p,
unsigned char d)
{
const unsigned char wm = (PARPORT_CONTROL_STROBE |
@@ -118,7 +148,7 @@ extern __inline__ void parport_gsc_write_control (struct parport *p,
__parport_gsc_frob_control (p, wm, d & wm);
}
-extern __inline__ unsigned char parport_gsc_read_control(struct parport *p)
+static inline unsigned char parport_gsc_read_control(struct parport *p)
{
const unsigned char rm = (PARPORT_CONTROL_STROBE |
PARPORT_CONTROL_AUTOFD |
@@ -128,9 +158,9 @@ extern __inline__ unsigned char parport_gsc_read_control(struct parport *p)
return priv->ctr & rm; /* Use soft copy */
}
-extern __inline__ unsigned char parport_gsc_frob_control (struct parport *p,
- unsigned char mask,
- unsigned char val)
+static inline unsigned char parport_gsc_frob_control(struct parport *p,
+ unsigned char mask,
+ unsigned char val)
{
const unsigned char wm = (PARPORT_CONTROL_STROBE |
PARPORT_CONTROL_AUTOFD |
@@ -155,18 +185,17 @@ extern __inline__ unsigned char parport_gsc_frob_control (struct parport *p,
return __parport_gsc_frob_control (p, mask, val);
}
-extern __inline__ unsigned char parport_gsc_read_status(struct parport *p)
+static inline unsigned char parport_gsc_read_status(struct parport *p)
{
return parport_readb (STATUS(p));
}
-
-extern __inline__ void parport_gsc_disable_irq(struct parport *p)
+static inline void parport_gsc_disable_irq(struct parport *p)
{
__parport_gsc_frob_control (p, 0x10, 0x00);
}
-extern __inline__ void parport_gsc_enable_irq(struct parport *p)
+static inline void parport_gsc_enable_irq(struct parport *p)
{
__parport_gsc_frob_control (p, 0x10, 0x10);
}
@@ -185,9 +214,9 @@ extern void parport_gsc_inc_use_count(void);
extern void parport_gsc_dec_use_count(void);
-extern struct parport *parport_gsc_probe_port (unsigned long base,
- unsigned long base_hi,
- int irq, int dma,
- struct pci_dev *dev);
+extern struct parport *parport_gsc_probe_port(unsigned long base,
+ unsigned long base_hi,
+ int irq, int dma,
+ struct pci_dev *dev);
-#endif
+#endif /* __DRIVERS_PARPORT_PARPORT_GSC_H */
diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c
index 5af551df9367f..c5774e7855d03 100644
--- a/drivers/parport/parport_pc.c
+++ b/drivers/parport/parport_pc.c
@@ -1,6 +1,6 @@
/* Low-level parallel-port routines for 8255-based PC-style hardware.
*
- * Authors: Phil Blundell <Philip.Blundell@pobox.com>
+ * Authors: Phil Blundell <philb@gnu.org>
* Tim Waugh <tim@cyberelk.demon.co.uk>
* Jose Renau <renau@acm.org>
* David Campbell <campbell@torque.net>
@@ -2488,7 +2488,7 @@ static int __devinit sio_ite_8872_probe (struct pci_dev *pdev, int autoirq,
/* VIA 8231 support by Pavel Fedin <sonic_amiga@rambler.ru>
based on VIA 686a support code by Jeff Garzik <jgarzik@pobox.com> */
-static int __initdata parport_init_mode = 0;
+static int __devinitdata parport_init_mode = 0;
/* Data for two known VIA chips */
static struct parport_pc_via_data via_686a_data __devinitdata = {
@@ -2733,13 +2733,11 @@ enum parport_pc_pci_cards {
aks_0100,
mobility_pp,
netmos_9705,
+ netmos_9715,
+ netmos_9755,
netmos_9805,
netmos_9815,
netmos_9855,
- netmos_9735,
- netmos_9835,
- netmos_9755,
- netmos_9715
};
@@ -2810,13 +2808,11 @@ static struct parport_pc_pci {
/* aks_0100 */ { 1, { { 0, -1 }, } },
/* mobility_pp */ { 1, { { 0, 1 }, } },
/* netmos_9705 */ { 1, { { 0, -1 }, } }, /* untested */
+ /* netmos_9715 */ { 2, { { 0, 1 }, { 2, 3 },} }, /* untested */
+ /* netmos_9755 */ { 2, { { 0, 1 }, { 2, 3 },} }, /* untested */
/* netmos_9805 */ { 1, { { 0, -1 }, } }, /* untested */
/* netmos_9815 */ { 2, { { 0, -1 }, { 2, -1 }, } }, /* untested */
/* netmos_9855 */ { 2, { { 0, -1 }, { 2, -1 }, } }, /* untested */
- /* netmos_9735 */ { 1, { { 2, 3 }, } }, /* untested */
- /* netmos_9835 */ { 1, { { 2, 3 }, } }, /* untested */
- /* netmos_9755 */ { 2, { { 0, 1 }, { 2, 3 },} }, /* untested */
- /* netmos_9715 */ { 2, { { 0, 1 }, { 2, 3 },} }, /* untested */
};
static struct pci_device_id parport_pc_pci_tbl[] = {
@@ -2889,28 +2885,30 @@ static struct pci_device_id parport_pc_pci_tbl[] = {
/* NetMos communication controllers */
{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9705,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9705 },
+ { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9715,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9715 },
+ { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9755,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9755 },
{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9805,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9805 },
{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9815,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9815 },
{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9855,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9855 },
- { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9735,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9735 },
- { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9835,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9835 },
- { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9755,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9755 },
- { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9715,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9715 },
{ 0, } /* terminate list */
};
MODULE_DEVICE_TABLE(pci,parport_pc_pci_tbl);
+struct pci_parport_data {
+ int num;
+ struct parport *ports[2];
+};
+
static int parport_pc_pci_probe (struct pci_dev *dev,
const struct pci_device_id *id)
{
int err, count, n, i = id->driver_data;
+ struct pci_parport_data *data;
if (i < last_sio)
/* This is an onboard Super-IO and has already been probed */
@@ -2922,9 +2920,15 @@ static int parport_pc_pci_probe (struct pci_dev *dev,
if ((err = pci_enable_device (dev)) != 0)
return err;
+ data = kmalloc(sizeof(struct pci_parport_data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
if (cards[i].preinit_hook &&
- cards[i].preinit_hook (dev, PARPORT_IRQ_NONE, PARPORT_DMA_NONE))
+ cards[i].preinit_hook (dev, PARPORT_IRQ_NONE, PARPORT_DMA_NONE)) {
+ kfree(data);
return -ENODEV;
+ }
for (n = 0; n < cards[i].numports; n++) {
int lo = cards[i].addr[n].lo;
@@ -2943,21 +2947,48 @@ static int parport_pc_pci_probe (struct pci_dev *dev,
"I/O at %#lx(%#lx)\n",
parport_pc_pci_tbl[i + last_sio].vendor,
parport_pc_pci_tbl[i + last_sio].device, io_lo, io_hi);
- if (parport_pc_probe_port (io_lo, io_hi, PARPORT_IRQ_NONE,
- PARPORT_DMA_NONE, dev))
+ data->ports[count] =
+ parport_pc_probe_port (io_lo, io_hi, PARPORT_IRQ_NONE,
+ PARPORT_DMA_NONE, dev);
+ if (data->ports[count])
count++;
}
+ data->num = count;
+
if (cards[i].postinit_hook)
cards[i].postinit_hook (dev, count == 0);
- return count == 0 ? -ENODEV : 0;
+ if (count) {
+ pci_set_drvdata(dev, data);
+ return 0;
+ }
+
+ kfree(data);
+
+ return -ENODEV;
+}
+
+static void __devexit parport_pc_pci_remove(struct pci_dev *dev)
+{
+ struct pci_parport_data *data = pci_get_drvdata(dev);
+ int i;
+
+ pci_set_drvdata(dev, NULL);
+
+ if (data) {
+ for (i = data->num - 1; i >= 0; i--)
+ parport_pc_unregister_port(data->ports[i]);
+
+ kfree(data);
+ }
}
static struct pci_driver parport_pc_pci_driver = {
.name = "parport_pc",
.id_table = parport_pc_pci_tbl,
.probe = parport_pc_pci_probe,
+ .remove = __devexit_p(parport_pc_pci_remove),
};
static int __init parport_pc_init_superio (int autoirq, int autodma)
diff --git a/drivers/parport/parport_serial.c b/drivers/parport/parport_serial.c
index 1f17d0124cc7a..6715a17b5d0fe 100644
--- a/drivers/parport/parport_serial.c
+++ b/drivers/parport/parport_serial.c
@@ -33,8 +33,7 @@
enum parport_pc_pci_cards {
titan_110l = 0,
titan_210l,
- netmos_9735,
- netmos_9835,
+ netmos_9xx5_combo,
avlab_1s1p,
avlab_1s1p_650,
avlab_1s1p_850,
@@ -51,9 +50,8 @@ enum parport_pc_pci_cards {
siig_2s1p_20x,
};
-
/* each element directly indexed from enum list, above */
-static struct parport_pc_pci {
+struct parport_pc_pci {
int numports;
struct { /* BAR (base address registers) numbers in the config
space header */
@@ -65,16 +63,30 @@ static struct parport_pc_pci {
/* If set, this is called immediately after pci_enable_device.
* If it returns non-zero, no probing will take place and the
* ports will not be used. */
- int (*preinit_hook) (struct pci_dev *pdev, int autoirq, int autodma);
+ int (*preinit_hook) (struct pci_dev *pdev, struct parport_pc_pci *card,
+ int autoirq, int autodma);
/* If set, this is called after probing for ports. If 'failed'
* is non-zero we couldn't use any of the ports. */
- void (*postinit_hook) (struct pci_dev *pdev, int failed);
-} cards[] __devinitdata = {
+ void (*postinit_hook) (struct pci_dev *pdev,
+ struct parport_pc_pci *card, int failed);
+};
+
+static int __devinit netmos_parallel_init(struct pci_dev *dev, struct parport_pc_pci *card, int autoirq, int autodma)
+{
+ /*
+ * Netmos uses the subdevice ID to indicate the number of parallel
+ * and serial ports. The form is 0x00PS, where <P> is the number of
+ * parallel ports and <S> is the number of serial ports.
+ */
+ card->numports = (dev->subsystem_device & 0xf0) >> 4;
+ return 0;
+}
+
+static struct parport_pc_pci cards[] __devinitdata = {
/* titan_110l */ { 1, { { 3, -1 }, } },
/* titan_210l */ { 1, { { 3, -1 }, } },
- /* netmos_9735 (not tested) */ { 1, { { 2, -1 }, } },
- /* netmos_9835 */ { 1, { { 2, -1 }, } },
+ /* netmos_9xx5_combo */ { 1, { { 2, -1 }, }, netmos_parallel_init },
/* avlab_1s1p */ { 1, { { 1, 2}, } },
/* avlab_1s1p_650 */ { 1, { { 1, 2}, } },
/* avlab_1s1p_850 */ { 1, { { 1, 2}, } },
@@ -98,9 +110,17 @@ static struct pci_device_id parport_serial_pci_tbl[] = {
{ PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_210L,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, titan_210l },
{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9735,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9735 },
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9xx5_combo },
+ { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9745,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9xx5_combo },
{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9835,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9835 },
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9xx5_combo },
+ { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9835,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9xx5_combo },
+ { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9845,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9xx5_combo },
+ { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9855,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9xx5_combo },
/* PCI_VENDOR_ID_AVLAB/Intek21 has another bunch of cards ...*/
{ 0x14db, 0x2110, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s1p},
{ 0x14db, 0x2111, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s1p_650},
@@ -167,6 +187,12 @@ static int __devinit siig20x_init_fn(struct pci_dev *dev, struct pci_board_no_id
return pci_siig20x_fn(dev, enable);
}
+static int __devinit netmos_serial_init(struct pci_dev *dev, struct pci_board_no_ids *board, int enable)
+{
+ board->num_ports = dev->subsystem_device & 0xf;
+ return 0;
+}
+
static struct pci_board_no_ids pci_boards[] __devinitdata = {
/*
* PCI Flags, Number of Ports, Base (Maximum) Baud Rate,
@@ -180,8 +206,7 @@ static struct pci_board_no_ids pci_boards[] __devinitdata = {
/* titan_110l */ { SPCI_FL_BASE1 | SPCI_FL_BASE_TABLE, 1, 921600 },
/* titan_210l */ { SPCI_FL_BASE1 | SPCI_FL_BASE_TABLE, 2, 921600 },
-/* netmos_9735 (n/t)*/ { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 115200 },
-/* netmos_9835 */ { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 115200 },
+/* netmos_9xx5_combo */ { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200, 0, 0, netmos_serial_init },
/* avlab_1s1p (n/t) */ { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 },
/* avlab_1s1p_650 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 },
/* avlab_1s1p_850 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 },
@@ -204,6 +229,7 @@ struct parport_serial_private {
struct pci_board_no_ids ser;
int num_par;
struct parport *port[PARPORT_MAX];
+ struct parport_pc_pci par;
};
static int __devinit get_pci_port (struct pci_dev *dev,
@@ -271,14 +297,15 @@ static int __devinit get_pci_port (struct pci_dev *dev,
static int __devinit serial_register (struct pci_dev *dev,
const struct pci_device_id *id)
{
- struct pci_board_no_ids *board = &pci_boards[id->driver_data];
+ struct pci_board_no_ids *board;
struct parport_serial_private *priv = pci_get_drvdata (dev);
struct serial_struct serial_req;
int base_baud;
int k;
int success = 0;
- priv->ser = *board;
+ priv->ser = pci_boards[id->driver_data];
+ board = &priv->ser;
if (board->init_fn && ((board->init_fn) (dev, board, 1) != 0))
return 1;
@@ -289,6 +316,15 @@ static int __devinit serial_register (struct pci_dev *dev,
for (k = 0; k < board->num_ports; k++) {
int line;
+
+ if (priv->num_ser == ARRAY_SIZE (priv->line)) {
+ printk (KERN_WARNING
+ "parport_serial: %s: only %u serial lines "
+ "supported (%d reported)\n", pci_name (dev),
+ ARRAY_SIZE (priv->line), board->num_ports);
+ break;
+ }
+
serial_req.irq = dev->irq;
if (get_pci_port (dev, board, &serial_req, k))
break;
@@ -311,19 +347,31 @@ static int __devinit serial_register (struct pci_dev *dev,
static int __devinit parport_register (struct pci_dev *dev,
const struct pci_device_id *id)
{
+ struct parport_pc_pci *card;
struct parport_serial_private *priv = pci_get_drvdata (dev);
int i = id->driver_data, n;
int success = 0;
- if (cards[i].preinit_hook &&
- cards[i].preinit_hook (dev, PARPORT_IRQ_NONE, PARPORT_DMA_NONE))
+ priv->par = cards[id->driver_data];
+ card = &priv->par;
+ if (card->preinit_hook &&
+ card->preinit_hook (dev, card, PARPORT_IRQ_NONE, PARPORT_DMA_NONE))
return -ENODEV;
- for (n = 0; n < cards[i].numports; n++) {
+ for (n = 0; n < card->numports; n++) {
struct parport *port;
- int lo = cards[i].addr[n].lo;
- int hi = cards[i].addr[n].hi;
+ int lo = card->addr[n].lo;
+ int hi = card->addr[n].hi;
unsigned long io_lo, io_hi;
+
+ if (priv->num_par == ARRAY_SIZE (priv->port)) {
+ printk (KERN_WARNING
+ "parport_serial: %s: only %u parallel ports "
+ "supported (%d reported)\n", pci_name (dev),
+ ARRAY_SIZE (priv->port), card->numports);
+ break;
+ }
+
io_lo = pci_resource_start (dev, lo);
io_hi = 0;
if ((hi >= 0) && (hi <= 6))
@@ -345,8 +393,8 @@ static int __devinit parport_register (struct pci_dev *dev,
}
}
- if (cards[i].postinit_hook)
- cards[i].postinit_hook (dev, !success);
+ if (card->postinit_hook)
+ card->postinit_hook (dev, card, !success);
return success ? 0 : 1;
}
diff --git a/drivers/parport/parport_sunbpp.c b/drivers/parport/parport_sunbpp.c
index 13b9b60680a8c..36a1556e64c7d 100644
--- a/drivers/parport/parport_sunbpp.c
+++ b/drivers/parport/parport_sunbpp.c
@@ -4,7 +4,7 @@
* Author: Derrick J. Brashear <shadow@dementia.org>
*
* based on work by:
- * Phil Blundell <Philip.Blundell@pobox.com>
+ * Phil Blundell <philb@gnu.org>
* Tim Waugh <tim@cyberelk.demon.co.uk>
* Jose Renau <renau@acm.org>
* David Campbell <campbell@tirian.che.curtin.edu.au>
diff --git a/drivers/parport/probe.c b/drivers/parport/probe.c
index eef454e99bad2..c94963145e179 100644
--- a/drivers/parport/probe.c
+++ b/drivers/parport/probe.c
@@ -2,7 +2,7 @@
* Parallel port device probing code
*
* Authors: Carsten Gross, carsten@sol.wohnheim.uni-ulm.de
- * Philip Blundell <Philip.Blundell@pobox.com>
+ * Philip Blundell <philb@gnu.org>
*/
#include <linux/module.h>
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index 421c93f1f8990..812c4274d7cdd 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -3,8 +3,8 @@
#
config PCI_MSI
bool "Message Signaled Interrupts (MSI and MSI-X)"
+ depends on PCI
depends on (X86_LOCAL_APIC && X86_IO_APIC) || IA64
- default n
help
This allows device drivers to enable MSI (Message Signaled
Interrupts). Message Signaled Interrupts enable a device to
diff --git a/drivers/pci/hotplug/ibmphp_pci.c b/drivers/pci/hotplug/ibmphp_pci.c
index ee0a3845ccd7a..90ef5c086844f 100644
--- a/drivers/pci/hotplug/ibmphp_pci.c
+++ b/drivers/pci/hotplug/ibmphp_pci.c
@@ -1384,9 +1384,6 @@ static int unconfigure_boot_bridge (u8 busno, u8 device, u8 function)
return -EINVAL;
}
- pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_SECONDARY_BUS, &sec_number);
- sec_no = (int) sec_no;
-
pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_SUBORDINATE_BUS, &sub_number);
sub_no = (int) sub_number;
debug ("sub_no is %d, sec_no is %d\n", sub_no, sec_no);
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c
index 279f53d78608d..0dbcf04aa35e4 100644
--- a/drivers/pci/hotplug/pciehp_ctrl.c
+++ b/drivers/pci/hotplug/pciehp_ctrl.c
@@ -1354,10 +1354,11 @@ static u32 remove_board(struct pci_func *func, struct controller *ctrl)
dbg("PCI Bridge Hot-Remove s:b:d:f(%02x:%02x:%02x:%02x)\n",
ctrl->seg, func->bus, func->device, func->function);
bridge_slot_remove(func);
- } else
+ } else {
dbg("PCI Function Hot-Remove s:b:d:f(%02x:%02x:%02x:%02x)\n",
ctrl->seg, func->bus, func->device, func->function);
slot_remove(func);
+ }
func = pciehp_slot_find(ctrl->slot_bus, device, 0);
}
diff --git a/drivers/pci/hotplug/pciehprm_acpi.c b/drivers/pci/hotplug/pciehprm_acpi.c
index 424e7ac617466..57f4e6d1b27cb 100644
--- a/drivers/pci/hotplug/pciehprm_acpi.c
+++ b/drivers/pci/hotplug/pciehprm_acpi.c
@@ -254,10 +254,9 @@ static int acpi_run_oshp ( struct acpi_bridge *ab)
{
acpi_status status;
u8 *path_name = acpi_path_name(ab->handle);
- struct acpi_buffer ret_buf = { 0, NULL};
/* run OSHP */
- status = acpi_evaluate_object(ab->handle, METHOD_NAME_OSHP, NULL, &ret_buf);
+ status = acpi_evaluate_object(ab->handle, METHOD_NAME_OSHP, NULL, NULL);
if (ACPI_FAILURE(status)) {
err("acpi_pciehprm:%s OSHP fails=0x%x\n", path_name, status);
oshp_run_status = (status == AE_NOT_FOUND) ? OSHP_NOT_EXIST : OSHP_RUN_FAILED;
diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c
index 705e5b3e6e0d0..86b384e427178 100644
--- a/drivers/pci/hotplug/rpadlpar_core.c
+++ b/drivers/pci/hotplug/rpadlpar_core.c
@@ -142,7 +142,7 @@ static int pci_add_secondary_bus(struct device_node *dn,
child = pci_add_new_bus(bridge_dev->bus, bridge_dev, sec_busno);
if (!child) {
printk(KERN_ERR "%s: could not add secondary bus\n", __FUNCTION__);
- return 1;
+ return -ENOMEM;
}
sprintf(child->name, "PCI Bus #%02x", child->number);
@@ -204,7 +204,7 @@ static int dlpar_pci_remove_bus(struct pci_dev *bridge_dev)
if (!bridge_dev) {
printk(KERN_ERR "%s: unexpected null device\n",
__FUNCTION__);
- return 1;
+ return -EINVAL;
}
secondary_bus = bridge_dev->subordinate;
@@ -212,7 +212,7 @@ static int dlpar_pci_remove_bus(struct pci_dev *bridge_dev)
if (unmap_bus_range(secondary_bus)) {
printk(KERN_ERR "%s: failed to unmap bus range\n",
__FUNCTION__);
- return 1;
+ return -ERANGE;
}
pci_remove_bus_device(bridge_dev);
@@ -282,7 +282,7 @@ static int dlpar_remove_phb(struct slot *slot)
}
rc = dlpar_remove_root_bus(phb);
- if (rc)
+ if (rc < 0)
return rc;
return 0;
@@ -294,7 +294,7 @@ static int dlpar_add_phb(struct device_node *dn)
phb = init_phb_dynamic(dn);
if (!phb)
- return 1;
+ return -EINVAL;
return 0;
}
diff --git a/drivers/pci/hotplug/rpaphp.h b/drivers/pci/hotplug/rpaphp.h
index b07b0212f56de..df9575ef5aa55 100644
--- a/drivers/pci/hotplug/rpaphp.h
+++ b/drivers/pci/hotplug/rpaphp.h
@@ -45,11 +45,6 @@
#define LED_ID 2 /* slow blinking */
#define LED_ACTION 3 /* fast blinking */
-/* Error status from rtas_get-sensor */
-#define NEED_POWER -9000 /* slot must be power up and unisolated to get state */
-#define PWR_ONLY -9001 /* slot must be powerd up to get state, leave isolated */
-#define ERR_SENSE_USE -9002 /* No DR operation will succeed, slot is unusable */
-
/* Sensor values from rtas_get-sensor */
#define EMPTY 0 /* No card in slot */
#define PRESENT 1 /* Card in slot */
diff --git a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c
index e709bad434f4c..29117a3a32874 100644
--- a/drivers/pci/hotplug/rpaphp_core.c
+++ b/drivers/pci/hotplug/rpaphp_core.c
@@ -256,12 +256,12 @@ int rpaphp_get_drc_props(struct device_node *dn, int *drc_index,
my_index = (int *) get_property(dn, "ibm,my-drc-index", NULL);
if (!my_index) {
/* Node isn't DLPAR/hotplug capable */
- return 1;
+ return -EINVAL;
}
rc = get_children_props(dn->parent, &indexes, &names, &types, &domains);
if (rc < 0) {
- return 1;
+ return -EINVAL;
}
name_tmp = (char *) &names[1];
@@ -284,7 +284,7 @@ int rpaphp_get_drc_props(struct device_node *dn, int *drc_index,
type_tmp += (strlen(type_tmp) + 1);
}
- return 1;
+ return -EINVAL;
}
static int is_php_type(char *drc_type)
diff --git a/drivers/pci/hotplug/rpaphp_pci.c b/drivers/pci/hotplug/rpaphp_pci.c
index 9e81bdedca5a2..a96b4af16f245 100644
--- a/drivers/pci/hotplug/rpaphp_pci.c
+++ b/drivers/pci/hotplug/rpaphp_pci.c
@@ -81,8 +81,8 @@ static int rpaphp_get_sensor_state(struct slot *slot, int *state)
rc = rtas_get_sensor(DR_ENTITY_SENSE, slot->index, state);
- if (rc) {
- if (rc == NEED_POWER || rc == PWR_ONLY) {
+ if (rc < 0) {
+ if (rc == -EFAULT || rc == -EEXIST) {
dbg("%s: slot must be power up to get sensor-state\n",
__FUNCTION__);
@@ -91,14 +91,14 @@ static int rpaphp_get_sensor_state(struct slot *slot, int *state)
*/
rc = rtas_set_power_level(slot->power_domain, POWER_ON,
&setlevel);
- if (rc) {
+ if (rc < 0) {
dbg("%s: power on slot[%s] failed rc=%d.\n",
__FUNCTION__, slot->name, rc);
} else {
rc = rtas_get_sensor(DR_ENTITY_SENSE,
slot->index, state);
}
- } else if (rc == ERR_SENSE_USE)
+ } else if (rc == -ENODEV)
info("%s: slot is unusable\n", __FUNCTION__);
else
err("%s failed to get sensor state\n", __FUNCTION__);
@@ -413,7 +413,7 @@ static int setup_pci_hotplug_slot_info(struct slot *slot)
if (slot->hotplug_slot->info->adapter_status == NOT_VALID) {
err("%s: NOT_VALID: skip dn->full_name=%s\n",
__FUNCTION__, slot->dn->full_name);
- return -1;
+ return -EINVAL;
}
return 0;
}
@@ -426,15 +426,15 @@ static int set_phb_slot_name(struct slot *slot)
dn = slot->dn;
if (!dn) {
- return 1;
+ return -EINVAL;
}
phb = dn->phb;
if (!phb) {
- return 1;
+ return -EINVAL;
}
bus = phb->bus;
if (!bus) {
- return 1;
+ return -EINVAL;
}
sprintf(slot->name, "%04x:%02x:%02x.%x", pci_domain_nr(bus),
@@ -448,7 +448,7 @@ static int setup_pci_slot(struct slot *slot)
if (slot->type == PHB) {
rc = set_phb_slot_name(slot);
- if (rc) {
+ if (rc < 0) {
err("%s: failed to set phb slot name\n", __FUNCTION__);
goto exit_rc;
}
@@ -509,12 +509,12 @@ static int setup_pci_slot(struct slot *slot)
return 0;
exit_rc:
dealloc_slot_struct(slot);
- return 1;
+ return -EINVAL;
}
int register_pci_slot(struct slot *slot)
{
- int rc = 1;
+ int rc = -EINVAL;
slot->dev_type = PCI_DEV;
if ((slot->type == EMBEDDED) || (slot->type == PHB))
diff --git a/drivers/pci/hotplug/rpaphp_slot.c b/drivers/pci/hotplug/rpaphp_slot.c
index 2bbd87ef4cd21..5c58fd099bcf0 100644
--- a/drivers/pci/hotplug/rpaphp_slot.c
+++ b/drivers/pci/hotplug/rpaphp_slot.c
@@ -211,7 +211,7 @@ int register_slot(struct slot *slot)
if (is_registered(slot)) { /* should't be here */
err("register_slot: slot[%s] is already registered\n", slot->name);
rpaphp_release_slot(slot->hotplug_slot);
- return 1;
+ return -EAGAIN;
}
retval = pci_hp_register(slot->hotplug_slot);
if (retval) {
@@ -270,7 +270,7 @@ int rpaphp_set_attention_status(struct slot *slot, u8 status)
/* status: LED_OFF or LED_ON */
rc = rtas_set_indicator(DR_INDICATOR, slot->index, status);
- if (rc)
+ if (rc < 0)
err("slot(name=%s location=%s index=0x%x) set attention-status(%d) failed! rc=0x%x\n",
slot->name, slot->location, slot->index, status, rc);
diff --git a/drivers/pci/hotplug/rpaphp_vio.c b/drivers/pci/hotplug/rpaphp_vio.c
index 561c87cf24d01..74df6a305e64e 100644
--- a/drivers/pci/hotplug/rpaphp_vio.c
+++ b/drivers/pci/hotplug/rpaphp_vio.c
@@ -71,11 +71,11 @@ int register_vio_slot(struct device_node *dn)
{
u32 *index;
char *name;
- int rc = 1;
+ int rc = -EINVAL;
struct slot *slot = NULL;
rc = rpaphp_get_drc_props(dn, NULL, &name, NULL, NULL);
- if (rc)
+ if (rc < 0)
goto exit_rc;
index = (u32 *) get_property(dn, "ibm,my-drc-index", NULL);
if (!index)
diff --git a/drivers/pci/hotplug/shpchprm_acpi.c b/drivers/pci/hotplug/shpchprm_acpi.c
index f1c51f09283f1..243a51d88b868 100644
--- a/drivers/pci/hotplug/shpchprm_acpi.c
+++ b/drivers/pci/hotplug/shpchprm_acpi.c
@@ -242,10 +242,9 @@ static void acpi_run_oshp ( struct acpi_bridge *ab)
{
acpi_status status;
u8 *path_name = acpi_path_name(ab->handle);
- struct acpi_buffer ret_buf = { 0, NULL};
/* run OSHP */
- status = acpi_evaluate_object(ab->handle, METHOD_NAME_OSHP, NULL, &ret_buf);
+ status = acpi_evaluate_object(ab->handle, METHOD_NAME_OSHP, NULL, NULL);
if (ACPI_FAILURE(status)) {
err("acpi_pciehprm:%s OSHP fails=0x%x\n", path_name, status);
} else
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 6331a00676318..5425e0f77d860 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -20,6 +20,7 @@
#include <asm/io.h>
#include <asm/smp.h>
+#include "pci.h"
#include "msi.h"
static DEFINE_SPINLOCK(msi_lock);
@@ -66,7 +67,7 @@ static void msi_set_mask_bit(unsigned int vector, int flag)
int pos;
u32 mask_bits;
- pos = (int)entry->mask_base;
+ pos = (long)entry->mask_base;
pci_read_config_dword(entry->dev, pos, &mask_bits);
mask_bits &= ~(1);
mask_bits |= flag;
@@ -372,6 +373,13 @@ static int msi_init(void)
if (!status)
return status;
+ if (pci_msi_quirk) {
+ pci_msi_enable = 0;
+ printk(KERN_WARNING "PCI: MSI quirk detected. MSI disabled.\n");
+ status = -EINVAL;
+ return status;
+ }
+
if ((status = msi_cache_init()) < 0) {
pci_msi_enable = 0;
printk(KERN_WARNING "PCI: MSI cache init failed\n");
@@ -547,7 +555,7 @@ static int msi_capability_init(struct pci_dev *dev)
dev->irq = vector;
entry->dev = dev;
if (is_mask_bit_support(control)) {
- entry->mask_base = (void __iomem *)msi_mask_bits_reg(pos,
+ entry->mask_base = (void __iomem *)(long)msi_mask_bits_reg(pos,
is_64bit_address(control));
}
/* Replace with MSI handler */
@@ -616,15 +624,10 @@ static int msix_capability_init(struct pci_dev *dev,
bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK);
phys_addr = pci_resource_start (dev, bir);
phys_addr += (u32)(table_offset & ~PCI_MSIX_FLAGS_BIRMASK);
- if (!request_mem_region(phys_addr,
- nr_entries * PCI_MSIX_ENTRY_SIZE,
- "MSI-X vector table"))
- return -ENOMEM;
base = ioremap_nocache(phys_addr, nr_entries * PCI_MSIX_ENTRY_SIZE);
- if (base == NULL) {
- release_mem_region(phys_addr, nr_entries * PCI_MSIX_ENTRY_SIZE);
+ if (base == NULL)
return -ENOMEM;
- }
+
/* MSI-X Table Initialization */
for (i = 0; i < nvec; i++) {
entry = alloc_msi_entry();
@@ -859,8 +862,6 @@ static int msi_free_vector(struct pci_dev* dev, int vector, int reassign)
phys_addr += (u32)(table_offset &
~PCI_MSIX_FLAGS_BIRMASK);
iounmap(base);
- release_mem_region(phys_addr,
- nr_entries * PCI_MSIX_ENTRY_SIZE);
}
}
@@ -1133,8 +1134,6 @@ void msi_remove_pci_irq_vectors(struct pci_dev* dev)
phys_addr += (u32)(table_offset &
~PCI_MSIX_FLAGS_BIRMASK);
iounmap(base);
- release_mem_region(phys_addr, PCI_MSIX_ENTRY_SIZE *
- multi_msix_capable(control));
printk(KERN_WARNING "PCI: %s: msi_remove_pci_irq_vectors() "
"called without free_irq() on all MSI-X vectors\n",
pci_name(dev));
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index 8a09a953b358c..76fe2db404dff 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -115,7 +115,6 @@ static DRIVER_ATTR(new_id, S_IWUSR, NULL, store_new_id);
static inline void
pci_init_dynids(struct pci_dynids *dynids)
{
- memset(dynids, 0, sizeof(*dynids));
spin_lock_init(&dynids->lock);
INIT_LIST_HEAD(&dynids->list);
}
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 1ef9026b91d25..eb8cf2b12f3e6 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -481,7 +481,7 @@ static int __init pci_sysfs_init(void)
struct pci_dev *pdev = NULL;
sysfs_initialized = 1;
- while ((pdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev)) != NULL)
+ while ((pdev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pdev)) != NULL)
pci_create_sysfs_dev_files(pdev);
return 0;
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index b17ba2d0e511d..fb2b64b1f827c 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -271,7 +271,7 @@ pci_set_power_state(struct pci_dev *dev, pci_power_t state)
if ((pmc & PCI_PM_CAP_VER_MASK) > 2) {
printk(KERN_DEBUG
"PCI: %s has unsupported PM cap regs version (%u)\n",
- dev->slot_name, pmc & PCI_PM_CAP_VER_MASK);
+ pci_name(dev), pmc & PCI_PM_CAP_VER_MASK);
return -EIO;
}
@@ -312,22 +312,24 @@ pci_set_power_state(struct pci_dev *dev, pci_power_t state)
/**
* pci_choose_state - Choose the power state of a PCI device
* @dev: PCI device to be suspended
- * @state: target sleep state for the whole system
+ * @state: target sleep state for the whole system. This is the value
+ * that is passed to suspend() function.
*
* Returns PCI power state suitable for given device and given system
* message.
*/
-pci_power_t pci_choose_state(struct pci_dev *dev, u32 state)
+pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state)
{
if (!pci_find_capability(dev, PCI_CAP_ID_PM))
return PCI_D0;
switch (state) {
- case 0: return PCI_D0;
- case 2: return PCI_D2;
+ case 0: return PCI_D0;
case 3: return PCI_D3hot;
- default: BUG();
+ default:
+ printk("They asked me for state %d\n", state);
+ BUG();
}
return PCI_D0;
}
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 63dcb08ab939c..79cdc16c52c82 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -64,6 +64,12 @@ extern void pci_remove_legacy_files(struct pci_bus *bus);
/* Lock for read/write access to pci device and bus lists */
extern spinlock_t pci_bus_lock;
+#ifdef CONFIG_X86_IO_APIC
+extern int pci_msi_quirk;
+#else
+#define pci_msi_quirk 0
+#endif
+
extern int pcie_mch_quirk;
extern struct device_attribute pci_dev_attrs[];
extern struct class_device_attribute class_device_attr_cpuaffinity;
diff --git a/drivers/pci/pci.ids b/drivers/pci/pci.ids
index 7a1ae53388e89..6007a75900541 100644
--- a/drivers/pci/pci.ids
+++ b/drivers/pci/pci.ids
@@ -7,7 +7,7 @@
# so if you have anything to contribute, please visit the home page or
# send a diff -u against the most recent pci.ids to pci-ids@ucw.cz.
#
-# Daily snapshot on Mon 2004-07-12 10:00:27
+# Partial sync-up to daily snapshot on Tue 2005-02-08 11:00:09
#
# Vendors, devices and subsystems. Please keep sorted.
@@ -28,6 +28,9 @@
4001 WinTV PVR-250 (v1)
4009 WinTV PVR-250
4801 WinTV PVR-250 MCE
+0071 Nebula Electronics Ltd.
+0095 Silicon Image, Inc. (Wrong ID)
+ 0680 Ultra ATA/133 IDE RAID CONTROLLER CARD
0100 Ncipher Corp Ltd
# 018a is not LevelOne but there is a board misprogrammed
018a LevelOne
@@ -41,6 +44,11 @@
# SpeedStream is Efficient Networks, Inc, a Siemens Company
02ac SpeedStream
1012 1012 PCMCIA 10/100 Ethernet Card [RTL81xx]
+0357 TTTech AG
+ 000a TTP-Monitoring Card V2.0
+0432 SCM Microsystems, Inc.
+05e3 CyberDoor
+ 0701 CBD516
0675 Dynalink
1700 IS64PH ISDN Adapter
1702 IS64PH ISDN Adapter
@@ -49,6 +57,9 @@
09c1 Arris
0704 CM 200E Cable Modem
0a89 BREA Technologies Inc
+0b49 ASCII Corporation
+# see http://homepage1.nifty.com/mcn/lab/machines/trance_vibrator/usbview.vib.txt
+ 064f Trance Vibrator
0e11 Compaq Computer Corporation
0001 PCI to EISA Bridge
0002 PCI to ISA Bridge
@@ -150,6 +161,8 @@
0e11 4082 Smart Array 532
0e11 4083 Smart Array 5312
b1a4 NC7131 Gigabit Server Adapter
+# HP Memory Hot-Plug Controller
+ b200 Memory Hot-Plug Controller
b203 Integrated Lights Out Controller
b204 Integrated Lights Out Processor
f130 NetFlex-3/P ThunderLAN 1.0
@@ -169,6 +182,7 @@
000a 53c1510
1000 1000 LSI53C1510 PCI to Dual Channel Wide Ultra2 SCSI Controller (Nonintelligent mode)
000b 53C896/897
+ 0e11 6004 EOB003 Series SCSI host adapter
1000 1000 LSI53C896/7 PCI to Dual Channel Ultra2 SCSI Multifunction Controller
1000 1010 LSI22910 PCI to Dual Channel Ultra2 SCSI host adapter
1000 1020 LSI21002 PCI to Dual Channel Ultra2 SCSI host adapter
@@ -191,7 +205,7 @@
4c53 1050 CT7 mainboard
0010 53C1510
0e11 4040 Integrated Array Controller
- 0e11 4048 Integrated Array Controller
+ 0e11 4048 RAID LC2 Controller
1000 1000 53C1510 PCI to Dual Channel Wide Ultra2 SCSI Controller (Intelligent mode)
0012 53c895a
1000 1000 LSI53C895A PCI to Ultra2 SCSI Controller
@@ -202,6 +216,7 @@
1de1 1020 DC-390U3W
0021 53c1010 66MHz Ultra3 SCSI Adapter
1000 1000 LSI53C1000/1000R/1010R/1010-66 PCI to Ultra160 SCSI Controller
+ 1000 1010 Asus TR-DLS onboard 53C1010-66
124b 1070 PMC-USCSI3
4c53 1080 CT8 mainboard
4c53 1300 P017 mezzanine (32-bit PMC)
@@ -209,6 +224,7 @@
0030 53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI
1028 0123 PowerEdge 2600
1028 014a PowerEdge 1750
+ 1028 016c PowerEdge 1850 MPT Fusion SCSI/RAID (Perc 4)
1028 1010 LSI U320 SCSI Controller
0031 53c1030ZC PCI-X Fusion-MPT Dual Ultra320 SCSI
0032 53c1035 PCI-X Fusion-MPT Dual Ultra320 SCSI
@@ -226,21 +242,23 @@
1000 0531 MegaRAID 531 SCSI 320-4X RAID Controller
1000 0532 MegaRAID 532 SCSI 320-2X RAID Controller
1028 0531 PowerEdge Expandable RAID Controller 4/QC
+ 1028 0533 PowerEdge Expandable RAID Controller 4/QC
8086 0530 MegaRAID Intel RAID Controller SRCZCRX
8086 0532 MegaRAID Intel RAID Controller SRCU42X
0408 MegaRAID
1000 0001 MegaRAID SCSI 320-1E RAID Controller
1000 0002 MegaRAID SCSI 320-2E RAID Controller
- 1028 0001 Dell PowerEdge RAID Controller PERC4e/SC
- 1028 0002 Dell PowerEdge RAID Controller PERC4e/DC
+ 1025 004d MegaRAID ACER ROMB-2E RAID Controller
+ 1028 0001 PowerEdge RAID Controller PERC4e/SC
+ 1028 0002 PowerEdge RAID Controller PERC4e/DC
1734 1065 FSC MegaRAID PCI Express ROMB
8086 0002 MegaRAID Intel RAID Controller SRCU42E
0409 MegaRAID
1000 3004 MegaRAID SATA 300-4X RAID Controller
1000 3008 MegaRAID SATA 300-8X RAID Controller
- 8086 3008 MegaRAID Intel RAID Controller SRCS28X
- 8086 3431 MegaRAID Intel RAID Controller Alief SROMBU42E
- 8086 3499 MegaRAID Intel RAID Controller Harwich SROMBU42E
+ 8086 3008 MegaRAID RAID Controller SRCS28X
+ 8086 3431 MegaRAID RAID Controller Alief SROMBU42E
+ 8086 3499 MegaRAID RAID Controller Harwich SROMBU42E
0621 FC909 Fibre Channel Adapter
0622 FC929 Fibre Channel Adapter
1000 1020 44929 O Dual Fibre Channel card
@@ -272,8 +290,8 @@
1028 0520 MegaRAID 520 DELL PERC 4/SC RAID Controller
1028 0531 PowerEdge Expandable RAID Controller 4/QC
1028 0533 PowerEdge Expandable RAID Controller 4/QC
- 8086 0520 MegaRAID Intel RAID Controller SRCU41L
- 8086 0523 MegaRAID Intel RAID Controller SRCS16
+ 8086 0520 MegaRAIDRAID Controller SRCU41L
+ 8086 0523 MegaRAID RAID Controller SRCS16
1001 Kolter Electronic
0010 PCI 1616 Measurement card with 32 digital I/O lines
0011 OPTO-PCI Opto-Isolated digital I/O board
@@ -285,7 +303,13 @@
0017 PROTO-3 PCI Prototyping board
9100 INI-9100/9100W SCSI Host
1002 ATI Technologies Inc
+ 3150 M24 1P [Radeon Mobility X600]
+ 3154 M24 1T [FireGL M24 GL]
+ 3e50 RV380 0x3e50 [Radeon X600]
+ 3e54 RV380 0x3e54 [FireGL V3200]
+ 3e70 RV380 [Radeon X600] Secondary
4136 Radeon IGP 320 M
+ 4137 Radeon IGP330/340/350
4144 R300 AD [Radeon 9500 Pro]
# New PCI ID provided by ATI developer relations (correction to above)
4145 R300 AE [Radeon 9700 Pro]
@@ -294,19 +318,27 @@
4147 R300 AG [FireGL Z1/X1]
4148 R350 AH [Radeon 9800]
4149 R350 AI [Radeon 9800]
- 414b R350 AK [Fire GL ??]
+ 414a R350 AJ [Radeon 9800]
+ 414b R350 AK [Fire GL X2]
# New PCI ID provided by ATI developer relations
4150 RV350 AP [Radeon 9600]
+ 1002 0002 R9600 Pro primary (Asus OEM for HP)
+ 1002 0003 R9600 Pro secondary (Asus OEM for HP)
1458 4024 Giga-Byte GV-R96128D Primary
148c 2064 PowerColor R96A-C3N
148c 2066 PowerColor R96A-C3N
174b 7c19 Sapphire Atlantis Radeon 9600 Pro
174b 7c29 GC-R9600PRO Primary [Sapphire]
+ 17ee 2002 Radeon 9600 256Mb Primary
18bc 0101 GC-R9600PRO Primary
# New PCI ID provided by ATI developer relations
4151 RV350 AQ [Radeon 9600]
+ 1043 c004 A9600SE
# New PCI ID provided by ATI developer relations
4152 RV350 AR [Radeon 9600]
+ 1002 0002 Radeon 9600XT
+ 1043 c002 Radeon 9600 XT TVD
+ 4153 RV350 AS [Radeon 9600 AS]
4154 RV350 AT [Fire GL T2]
4155 RV350 AU [Fire GL T2]
4156 RV350 AV [Fire GL T2]
@@ -325,20 +357,35 @@
1458 4025 Giga-Byte GV-R96128D Secondary
148c 2067 PowerColor R96A-C3N (Secondary)
174b 7c28 GC-R9600PRO Secondary [Sapphire]
+ 17ee 2003 Radeon 9600 256Mb Secondary
18bc 0100 GC-R9600PRO Secondary
# New PCI ID provided by ATI developer relations (correction to above)
4171 RV350 AQ [Radeon 9600] (Secondary)
+ 1043 c005 A9600SE (Secondary)
# New PCI ID provided by ATI developer relations (correction to above)
4172 RV350 AR [Radeon 9600] (Secondary)
+ 1002 0003 Radeon 9600XT (Secondary)
+ 1043 c003 A9600XT (Secondary)
+ 4173 RV350 ?? [Radeon 9550] (Secondary)
+ 4237 Radeon 7000 IGP
4242 R200 BB [Radeon All in Wonder 8500DV]
1002 02aa Radeon 8500 AIW DV Edition
+ 4243 R200 BC [Radeon All in Wonder 8500]
4336 Radeon Mobility U1
- 4337 Radeon IGP 340M
+ 103c 0024 Pavilion ze4400 builtin Video
+ 4337 Radeon IGP 330M/340M/350M
+ 1014 053a ThinkPad R40e (2684-HVG) builtin VGA controller
+ 103c 0850 Radeon IGP 345M
4341 IXP150 AC'97 Audio Controller
+ 4345 EHCI USB Controller
+ 4347 OHCI USB Controller #1
+ 4348 OHCI USB Controller #2
+ 434d IXP AC'97 Modem
# Radeon 9100 IGP integrated
4353 ATI SMBus
4354 215CT [Mach64 CT]
4358 210888CX [Mach64 CX]
+ 4437 Radeon Mobility 7000 IGP
4554 210888ET [Mach64 ET]
4654 Mach64 VT
4742 3D Rage Pro AGP 1X/2X
@@ -389,6 +436,7 @@
1002 8008 Rage XL
1028 00ce PowerEdge 1400
1028 00d1 PowerEdge 2550
+ 1028 00d9 PowerEdge 2500
8086 3411 SDS2 Mainboard
8086 3427 S875WP1-E mainboard
4753 Rage XC
@@ -406,6 +454,7 @@
4758 210888GX [Mach64 GX]
4759 3D Rage IIC
475a 3D Rage IIC AGP
+ 1002 0084 Rage 3D Pro AGP 2x XPERT 98
1002 0087 Rage 3D IIC
1002 475a Rage IIC AGP
4964 Radeon RV250 Id [Radeon 9000]
@@ -422,6 +471,15 @@
17af 2006 RV250 If [Excalibur Radeon 9000]
4967 Radeon RV250 Ig [Radeon 9000]
496e Radeon RV250 [Radeon 9000] (Secondary)
+ 4a48 R420 JH [Radeon X800]
+ 4a49 R420 JI [Radeon X800PRO]
+ 4a4a R420 JJ [Radeon X800SE]
+ 4a4b R420 JK [Radeon X800]
+ 4a4c R420 JL [Radeon X800]
+ 4a4d R420 JM [FireGL X3]
+ 4a4e M18 JN [Radeon Mobility 9800]
+ 4a50 R420 JP [Radeon X800XT]
+ 4a70 R420 [X800XT-PE] (Secondary)
4c42 3D Rage LT Pro AGP-133
0e11 b0e7 Rage LT Pro (Compaq Presario 5240)
0e11 b0e8 Rage 3D LT Pro
@@ -452,6 +510,7 @@
1002 4c50 Rage LT Pro
4c51 3D Rage LT Pro
4c52 Rage Mobility P/M
+ 1033 8112 Versa Note VXi
4c53 Rage Mobility L
4c54 264LT [Mach64 LT]
4c57 Radeon Mobility M7 LW [Radeon Mobility 7500]
@@ -488,9 +547,14 @@
4e4b R350 NK [Fire GL X2]
# New PCI ID provided by ATI developer relations
4e50 RV350 [Mobility Radeon 9600 M10]
-# New PCI ID provided by ATI developer relations
+ 1025 005a TravelMate 290
+ 103c 0890 NC6000 laptop
+ 1734 1055 Amilo M1420W
+ 4e51 M10 NQ [Radeon Mobility 9600]
4e52 RV350 [Mobility Radeon 9600 M10]
+ 4e53 M10 NS [Radeon Mobility 9600]
4e54 M10 NT [FireGL Mobility T2]
+ 4e56 M11 NV [FireGL Mobility T2e]
4e64 Radeon R300 [Radeon 9700 Pro] (Secondary)
4e65 Radeon R300 [Radeon 9500 Pro] (Secondary)
1002 0003 Radeon R300 NE [Radeon 9500 Pro]
@@ -568,6 +632,7 @@
1002 003a Radeon R200 QL [Radeon 8500 LE]
1002 013a Radeon 8500
148c 2026 R200 QL [Radeon 8500 Evil Master II Multi Display Edition]
+ 1681 0010 Radeon 8500 [3D Prophet 8500 128Mb]
174b 7149 Radeon R200 QL [Sapphire Radeon 8500 LE]
514d Radeon R200 QM [Radeon 9100]
514e Radeon R200 QN [Radeon 8500LE]
@@ -576,6 +641,7 @@
5155 R200 QU [Radeon 9100]
5157 Radeon RV200 QW [Radeon 7500]
1002 013a Radeon 7500
+ 1002 103a Dell Optiplex GX260
1458 4000 RV200 QW [RADEON 7500 PRO MAYA AR]
148c 2024 RV200 QW [Radeon 7500LE Dual Display]
148c 2025 RV200 QW [Radeon 7500 Evil Master Multi Display Edition]
@@ -596,6 +662,7 @@
148c 2003 RV100 QY [Radeon 7000 Multi-Display Edition]
148c 2023 RV100 QY [Radeon 7000 Evil Master Multi-Display]
174b 7112 RV100 QY [Sapphire Radeon VE 7000]
+ 174b 7c28 Sapphire Radeon VE 7000 DDR
1787 0202 RV100 QY [Excalibur Radeon 7000]
515a Radeon RV100 QZ [Radeon 7000/VE]
5168 Radeon R200 Qh
@@ -650,29 +717,78 @@
5453 Rage 128 Pro Ultra TS
5454 Rage 128 Pro Ultra TT
5455 Rage 128 Pro Ultra TU
+ 5460 M22 [Radeon Mobility M300]
+ 5464 M22 [FireGL GL]
+ 5548 R423 UH [Radeon X800 (PCIE)]
+ 5549 R423 UI [Radeon X800PRO (PCIE)]
+ 554a R423 UJ [Radeon X800LE (PCIE)]
+ 554b R423 UK [Radeon X800SE (PCIE)]
+ 5551 R423 UQ [FireGL V7200 (PCIE)]
+ 5552 R423 UR [FireGL V5100 (PCIE)]
+ 5554 R423 UT [FireGL V7100 (PCIE)]
+ 556b Radeon R423 UK (PCIE) [X800 SE] (Secondary)
5654 264VT [Mach64 VT]
1002 5654 Mach64VT Reference
5655 264VT3 [Mach64 VT3]
5656 264VT4 [Mach64 VT4]
+ 5830 RS300 Host Bridge
+ 5831 RS300 Host Bridge
+ 5832 RS300 Host Bridge
+ 5833 Radeon 9100 IGP Host Bridge
+ 5834 Radeon 9100 IGP
+ 5835 RS300M AGP [Radeon Mobility 9100IGP]
+ 5838 Radeon 9100 IGP AGP Bridge
5941 RV280 [Radeon 9200] (Secondary)
+ 174b 7c12 Sapphire Radeon 9200
# http://www.hightech.com.hk/html/9200.htm
17af 200d Excalibur Radeon 9200
18bc 0050 GeXcube GC-R9200-C3 (Secondary)
+ 5944 RV280 [Radeon 9200 SE (PCI)]
5960 RV280 [Radeon 9200 PRO]
5961 RV280 [Radeon 9200]
+ 1002 2f72 All-in-Wonder 9200 Series
+ 12ab 5961 YUAN SMARTVGA Radeon 9200
+ 1458 4018 Gigabyte Radeon 9200
+ 174b 7c13 Sapphire Radeon 9200
# http://www.hightech.com.hk/html/9200.htm
17af 200c Excalibur Radeon 9200
+ 18bc 0050 Radeon 9200 Game Buster
18bc 0051 GeXcube GC-R9200-C3
+ 18bc 0053 Radeon 9200 Game Buster VIVO
+ 5962 RV280 [Radeon 9200]
5964 RV280 [Radeon 9200 SE]
+ 1043 c006 ASUS Radeon 9200 SE / TD / 128M
+ 1458 4018 Radeon 9200 SE
148c 2073 CN-AG92E
+ 174b 7c13 Sapphire Radeon 9200 SE
+ 1787 5964 Excalibur 9200SE VIVO 128M
+ 17af 2012 Radeon 9200 SE Excalibur
+ 18bc 0170 Sapphire Radeon 9200 SE 128MB Game Buster
+# 128MB DDR, DVI/VGA/TV out
+ 18bc 0173 GC-R9200L(SE)-C3H [Radeon 9200 Game Buster]
+ 5b60 RV370 5B60 [Radeon X300 (PCIE)]
+ 1043 002a EAX300SE
+ 5b62 RV370 5B62 [Radeon X600 (PCIE)]
+ 5b64 RV370 5B64 [FireGL V3100 (PCIE)]
+ 5b65 RV370 5B65 [FireGL D1100 (PCIE)]
5c61 RV250 5c61 [Radeon Mobility 9200 M9+]
5c63 RV250 5c63 [Radeon Mobility 9200 M9+]
5d44 RV280 [Radeon 9200 SE] (Secondary)
+ 1458 4019 Radeon 9200 SE (Secondary)
+ 174b 7c12 Sapphire Radeon 9200 SE (Secondary)
+ 1787 5965 Excalibur 9200SE VIVO 128M (Secondary)
+ 17af 2013 Radeon 9200 SE Excalibur (Secondary)
+ 18bc 0171 Radeon 9200 SE 128MB Game Buster (Secondary)
+ 18bc 0172 GC-R9200L(SE)-C3H [Radeon 9200 Game Buster]
+ 5d57 R423 5F57 [Radeon X800XT (PCIE)]
700f PCI Bridge [IGP 320M]
7010 PCI Bridge [IGP 340M]
+ 7834 Radeon 9100 PRO IGP
+ 7835 Radeon Mobility 9200 IGP
7c37 RV350 AQ [Radeon 9600 SE]
cab0 AGP Bridge [IGP 320M]
cab2 RS200/RS200M AGP Bridge [IGP 340M]
+ cbb2 RS200/RS200M AGP Bridge [IGP 340M]
1003 ULSI Systems
0201 US201
1004 VLSI Technology Inc
@@ -726,6 +842,7 @@
0011 NS87560 National PCI System I/O
0012 USB Controller
0020 DP83815 (MacPhyter) Ethernet Controller
+ 103c 0024 Pavilion ze4400 builtin Network
1385 f311 FA311 / FA312 (FA311 with WoL HW)
0022 DP83820 10/100/1000 Ethernet Controller
0028 CS5535 Host bridge
@@ -734,12 +851,16 @@
002e CS5535 Audio
002f CS5535 USB
0030 CS5535 Video
+ 0035 DP83065 [Saturn] 10/100/1000 Ethernet Controller
0500 SCx200 Bridge
0501 SCx200 SMI
0502 SCx200 IDE
0503 SCx200 Audio
0504 SCx200 Video
0505 SCx200 XBus
+ 0510 SC1100 Bridge
+ 0511 SC1100 SMI
+ 0515 SC1100 XBus
d001 87410 IDE
100c Tseng Labs Inc
3202 ET4000/W32p rev A
@@ -820,6 +941,7 @@
1385 2100 FA510
1395 0001 10/100 Ethernet CardBus PC Card
13d1 ab01 EtherFast 10/100 Cardbus (PCMPC200)
+ 14cb 0100 LNDL-100N 100Base-TX Ethernet PC Card
8086 0001 EtherExpress PRO/100 Mobile CardBus 32
001a Farallon PN9000SX Gigabit Ethernet
0021 DECchip 21052
@@ -915,6 +1037,7 @@
# AS400 iSeries PCI sync serial card
1014 0031 2721 WAN IOA - 2 Port Sync Serial Adapter
0036 Miami
+ 0037 82660 CPU to PCI Bridge
003a CPU to PCI Bridge
003c GXT250P/GXT255P Graphics Adapter
003e 16/4 Token ring UTP/STP controller
@@ -940,6 +1063,7 @@
005e GXT800P Graphics Adapter
007c ATM Controller (14107c00)
007d 3780IDSP [MWave]
+ 008b EADS PCI to PCI Bridge
008e GXT3000P Graphics Adapter
0090 GXT 3000P
1014 008e GXT-3000P
@@ -953,6 +1077,7 @@
00a5 ATM Controller (1410a500)
00a6 ATM 155MBPS MM Controller (1410a600)
00b7 256-bit Graphics Rasterizer [Fire GL1]
+ 1092 00b8 FireGL1 AGP 32Mb
00b8 GXT2000P Graphics Adapter
00be ATM 622MBPS Controller (1410be00)
00dc Advanced Systems Management Adapter (ASMA)
@@ -973,7 +1098,7 @@
0180 Snipe chipset SCSI controller
1014 0241 iSeries 2757 DASD IOA
1014 0264 Quad Channel PCI-X U320 SCSI RAID Adapter (2780)
- 1014 02BD Quad Channel PCI-X U320 DDR SCSI RAID Adapter (570F)
+ 0188 EADS-X PCI-X to PCI-X Bridge
01a7 PCI-X to PCI-X Bridge
01bd ServeRAID Controller
1014 01be ServeRAID-4M
@@ -997,8 +1122,11 @@
0268 Gigabit Ethernet-SX Adapter (PCI-X)
0269 10/100/1000 Base-TX Ethernet Adapter (PCI-X)
028C Citrine chipset SCSI controller
- 1014 02BE Dual Channel PCI-X U320 DDR SCSI RAID Adapter (571B)
+ 1014 028D Dual Channel PCI-X DDR SAS RAID Adapter (572E)
+ 1014 02BE Dual Channel PCI-X DDR U320 SCSI RAID Adapter (571B)
+ 1014 02C0 Dual Channel PCI-X DDR U320 SCSI Adapter (571A)
0302 X-Architecture Bridge [Summit]
+ 0314 ZISC 036 Neural accelerator card
ffff MPIC-2 interrupt controller
1015 LSI Logic Corp of Canada
1016 ICL Personal Systems
@@ -1048,10 +1176,10 @@
1020 Hitachi Computer Products
1021 OKI Electric Industry Co. Ltd.
1022 Advanced Micro Devices [AMD]
- 1100 K8 NorthBridge
- 1101 K8 NorthBridge
- 1102 K8 NorthBridge
- 1103 K8 NorthBridge
+ 1100 K8 [Athlon64/Opteron] HyperTransport Technology Configuration
+ 1101 K8 [Athlon64/Opteron] Address Map
+ 1102 K8 [Athlon64/Opteron] DRAM Controller
+ 1103 K8 [Athlon64/Opteron] Miscellaneous Control
2000 79c970 [PCnet32 LANCE]
1014 2000 NetFinity 10/100 Fast Ethernet
1022 2000 PCnet - Fast 79C971
@@ -1081,6 +1209,8 @@
3000 ELanSC520 Microcontroller
7006 AMD-751 [Irongate] System Controller
7007 AMD-751 [Irongate] AGP Bridge
+ 700a AMD-IGR4 AGP Host to PCI Bridge
+ 700b AMD-IGR4 PCI to PCI Bridge
700c AMD-760 MP [IGD4-2P] System Controller
700d AMD-760 MP [IGD4-2P] AGP Bridge
700e AMD-760 [IGD4-1P] System Controller
@@ -1209,6 +1339,8 @@
1631 M1631 Northbridge+3D Graphics [Aladdin TNT2]
1641 M1641 Northbridge [Aladdin-Pro IV]
1647 M1647 [MaGiK1] PCI North Bridge
+ 1671 M1671 Northbridge [ALADDiN-P4]
+ 1672 Northbridge [CyberALADDiN-P4]
3141 M3141
3143 M3143
3145 M3145
@@ -1353,6 +1485,7 @@
102b 07c1 Millennium G450 SDR Dual Head LE
102b 0d41 Millennium G450 Dual Head PCI
102b 0d42 Millennium G450 Dual Head LX PCI
+ 102b 0d43 Millennium G450 32Mb Dual Head PCI
102b 0e00 Marvel G450 eTV
102b 0e01 Marvel G450 eTV
102b 0e02 Marvel G450 eTV
@@ -1436,13 +1569,18 @@
102e Olivetti Advanced Technology
102f Toshiba America
0009 r4x00
+ 000a TX3927 MIPS RISC PCI Controller
0020 ATM Meteor 155
102f 00f8 ATM Meteor 155
+ 0030 TC35815CF PCI 10/100 Mbit Ethernet Controller
+ 0031 TC35815CF PCI 10/100 Mbit Ethernet Controller with WOL
0105 TC86C001 [goku-s] IDE
0106 TC86C001 [goku-s] USB 1.1 Host
0107 TC86C001 [goku-s] USB Device Controller
0108 TC86C001 [goku-s] I2C/SIO/GPIO Controller
- 0180 TX4927
+ 0180 TX4927/38 MIPS RISC PCI Controller
+ 0181 TX4925 MIPS RISC PCI Controller
+ 0182 TX4937 MIPS RISC PCI Controller
1030 TMC Research
1031 Miro Computer Products AG
5601 DC20 ASIC
@@ -1517,7 +1655,12 @@
0006 85C501/2/3
0008 SiS85C503/5513 (LPC Bridge)
0009 ACPI
+# source: http://members.datafast.net.au/dft0802/downloads/pcidevs.txt
+ 0016 SiS961/2 SMBus Controller
0018 SiS85C503/5513 (LPC Bridge)
+# Controller for 2 PATA and 2 SATA channels
+ 0180 RAID bus controller 180 SATA/PATA [SiS]
+ 0181 SiS SATA
0200 5597/5598/6326 VGA
1039 0000 SiS5597 SVGA (Shared RAM)
0204 82C204
@@ -1557,6 +1700,7 @@
0755 755 Host
0760 760/M760 Host
0900 SiS900 PCI Fast Ethernet
+ 1019 0a14 K7S5A motherboard
1039 0900 SiS900 10/100 Ethernet Adapter
1043 8035 CUSI-FX motherboard
0961 SiS961 [MuTIOL Media IO]
@@ -1599,9 +1743,10 @@
1092 4910 SpeedStar A70
1092 4920 SpeedStar A70
1569 6326 SiS6326 GUI Accelerator
- 6330 661FX/M661FX/M661MX/741/M741/760/M760 PCI/AGP
- 1039 6330 [M]661FX/M661MX/[M]741/[M]760 PCI/AGP VGA Display Adapter
+ 6330 661/741/760 PCI/AGP VGA Display Adapter
+ 1039 6330 [M]661xX/[M]741[GX]/[M]760 PCI/AGP VGA Adapter
7001 USB 1.0 Controller
+ 1019 0a14 K7S5A motherboard
1039 7000 Onboard USB Controller
7002 USB 2.0 Controller
1509 7002 Onboard USB Controller
@@ -1667,6 +1812,7 @@
103c 1226 Keystone SP2
103c 1227 Powerbar SP2
103c 1282 Everest SP2
+ 103c 1301 Diva RMP3
1054 PCI Local Bus Adapter
1064 79C970 PCnet Ethernet Controller
108b Visualize FXe
@@ -1694,13 +1840,14 @@
3000 Samurai_0
3010 Samurai_1
3020 Samurai_IDE
-1043 Asustek Computer, Inc.
+1043 ASUSTeK Computer Inc.
0675 ISDNLink P-IN100-ST-D
4015 v7100 SDRAM [GeForce2 MX]
4021 v7100 Combo Deluxe [GeForce2 MX + TV tuner]
4057 v8200 GeForce 3
8043 v8240 PAL 128M [P4T] Motherboard
807b v9280/TD [Geforce4 TI4200 8X With TV-Out and DVI]
+ 80bb v9180 Magic/T [GeForce4 MX440 AGP 8x 64MB TV-out]
1044 Adaptec (formerly DPT)
1012 Domino RAID Engine
a400 SmartCache/Raid I-IV Controller
@@ -1769,9 +1916,11 @@
1046 IPC Corporation, Ltd.
1047 Genoa Systems Corp
1048 Elsa AG
+ 0c60 Gladiac MX
0d22 Quadro4 900XGL [ELSA GLoria4 900XGL]
1000 QuickStep 1000
3000 QuickStep 3000
+ 8901 Gloria XL
1049 Fountain Technologies, Inc.
# # nee SGS Thomson Microelectronics
104a STMicroelectronics
@@ -1841,15 +1990,19 @@
8023 TSB43AB22/A IEEE-1394a-2000 Controller (PHY/Link)
8024 TSB43AB23 IEEE-1394a-2000 Controller (PHY/Link)
8025 TSB82AA2 IEEE-1394b Link Layer Controller
+ 55aa 55aa FireWire 800 PCI Card
8026 TSB43AB21 IEEE-1394a-2000 Controller (PHY/Link)
8027 PCI4451 IEEE-1394 Controller
1028 00e6 PCI4451 IEEE-1394 Controller (Dell Inspiron 8100)
8029 PCI4510 IEEE-1394 Controller
+ 1028 0163 Latitude D505
1071 8160 MIM2900
802e PCI7x20 1394a-2000 OHCI Two-Port PHY/Link-Layer Controller
+ 8201 PCI1620 Firmware Loading Function
8400 ACX 100 22Mbps Wireless Interface
00fc 16ec U.S. Robotics 22 Mbps Wireless PC Card (model 2210)
00fd 16ec U.S. Robotics 22Mbps Wireless PCI Adapter (model 2216)
+ 1186 3b00 DWL-650+ PC Card cardbus 22Mbs Wireless Adapter [AirPlus]
1186 3b01 DWL-520+ 22Mbps PCI Wireless Adapter
8401 ACX 100 22Mbps Wireless Interface
# OK, this info is almost useless as is, but at least it's known that it's a wireless card. More info requested from reporter (whi
@@ -1891,6 +2044,7 @@
ac42 PCI4451 PC card Cardbus Controller
1028 00e6 PCI4451 PC card CardBus Controller (Dell Inspiron 8100)
ac44 PCI4510 PC card Cardbus Controller
+ 1028 0163 Latitude D505
1071 8160 MIM2000
ac46 PCI4520 PC card Cardbus Controller
ac50 PCI1410 PC card Cardbus Controller
@@ -1898,20 +2052,23 @@
1014 023b ThinkPad T23 (2647-4MG)
1028 00b1 Latitude C600
1028 012a Latitude C640
+ 1033 80cd Versa Note VXi
10cf 1095 Lifebook C6155
e4bf 1000 CP2-2-HIPHOP
ac52 PCI1451 PC card Cardbus Controller
ac53 PCI1421 PC card Cardbus Controller
+ ac54 PCI1620 PC Card Controller
ac55 PCI1520 PC card Cardbus Controller
1014 0512 ThinkPad T30/T40
ac56 PCI1510 PC card Cardbus Controller
+ 1014 0528 ThinkPad R40e (2684-HVG) Cardbus Controller
ac60 PCI2040 PCI to DSP Bridge Controller
175c 5100 ASI51xx Audio Adapter
175c 6100 ASI61xx Audio Adapter
175c 6200 ASI62xx Audio Adapter
ac8d PCI 7620
ac8e PCI7420 CardBus Controller
- ac8f PCI7420 Flash Media Controller
+ ac8f PCI7420/PCI7620 Dual Socket CardBus and Smart Card Cont.
fe00 FireWire Host Controller
fe03 12C01A FireWire Host Controller
104d Sony Corporation
@@ -1937,6 +2094,8 @@
0940 W89C940
5a5a W89C940F
6692 W6692
+ 9921 W99200F MPEG-1 Video Encoder
+ 9922 W99200F/W9922PF MPEG-1/2 Video Encoder
9970 W9970CF
1051 Anigma, Inc.
1052 ?Young Micro Systems
@@ -1975,6 +2134,7 @@
175c 4400 ASI4401 Audio Adapter
ecc0 0030 Layla
18c0 MPC8265A/MPC8266
+ 18c1 MPC8271/MPC8272
4801 Raven
4802 Falcon
4803 Hawk
@@ -1998,7 +2158,9 @@
14c8 0302 SM56 PCI Fax Modem
1668 0300 SM56 PCI Speakerphone Modem
1668 0302 SM56 PCI Fax Modem
+ 5803 MPC5200
6400 MPC190 Security Processor (S1 family, encryption)
+ 6405 MPC184 Security Processor (S1 family)
1058 Electronics & Telecommunications RSH
1059 Teknor Industrial Computers Inc
105a Promise Technology, Inc.
@@ -2018,6 +2180,8 @@
3375 PDC20375 (SATA150 TX2plus)
3376 PDC20376 (FastTrak 376)
1043 809e A7V8X motherboard
+ 3574 PDC20579 SATAII 150 IDE Controller
+ 3d18 PDC20518 SATAII 150 IDE Controller
4d30 PDC20267 (FastTrak100/Ultra100)
105a 4d33 Ultra100
105a 4d39 FastTrak100
@@ -2189,8 +2353,16 @@
0049 K2 HT-PCI Bridge
004b U3 AGP
004c K2 GMAC (Sun GEM)
+ 004f Shasta Mac I/O
+ 0050 Shasta IDE
+ 0051 Shasta (Sun GEM)
+ 0052 Shasta Firewire
+ 0053 Shasta PCI Bridge
+ 0054 Shasta PCI Bridge
+ 0055 Shasta PCI Bridge
+ 0058 U3L AGP Bridge
1645 Tigon3 Gigabit Ethernet NIC (BCM5701)
-106c Hyundai Electronics America
+106c Hynix Semiconductor
8801 Dual Pentium ISA/PCI Motherboard
8802 PowerPC ISA/PCI Motherboard
8803 Dual Window Graphics Accelerator
@@ -2270,6 +2442,7 @@
107d LeadTek Research Inc.
0000 P86C850
2134 WinFast 3D S320 II
+ 2971 [GeForce FX 5900] WinFast A350 TDH MyViVo
107e Interphase Corporation
0001 5515 ATM Adapter [Flipper]
0002 100 VG AnyLan Controller
@@ -2347,6 +2520,7 @@
a000 Ultra IIi
a001 Ultra IIe
a801 Tomatillo PCI Bus Module
+ abba Cassini 10/100/1000
108f Systemsoft
1090 Encore Computer Corporation
1091 Intergraph Corporation
@@ -2357,6 +2531,8 @@
0060 Proprietary bus bridge
00e4 Powerstorm 4D50T
0720 Motion JPEG codec
+ 07a0 Sun Expert3D-Lite Graphics Accelerator
+ 1091 Sun Expert3D Graphics Accelerator
1092 Diamond Multimedia Systems
00a0 Speedstar Pro SE
00a8 Speedstar 64
@@ -2386,9 +2562,19 @@
1190 PCI-MIO-16E-4
1330 PCI-6031E
1350 PCI-6071E
+ 14e0 PCI-6110
+ 14f0 PCI-6111
17d0 PCI-6503
+ 1870 PCI-6713
+ 1880 PCI-6711
+ 18b0 PCI-6052E
2410 PCI-6733
+ 2890 PCI-6036E
2a60 PCI-6023E
+ 2a70 PCI-6024E
+ 2a80 PCI-6025E
+ 2c80 PCI-6035E
+ 2ca0 PCI-6034E
b001 IMAQ-PCI-1408
b011 IMAQ-PXI-1408
b021 IMAQ-PCI-1424
@@ -2403,13 +2589,13 @@
c831 PCI-GPIB bridge
1094 First International Computers [FIC]
1095 Silicon Image, Inc. (formerly CMD Technology Inc)
- 0240 Adaptec AAR-1210SA SATA HostRAID
+ 0240 Adaptec AAR-1210SA SATA HostRAID Contr.
0640 PCI0640
0643 PCI0643
0646 PCI0646
0647 PCI0647
0648 PCI0648
- 0649 PCI0649
+ 0649 SiI 0649 Ultra ATA-100 Host Controller
0e11 005d Integrated Ultra ATA-100 Dual Channel Controller
0e11 007e Integrated Ultra ATA-100 IDE RAID Controller
101e 0649 AMI MegaRAID IDE 100 Controller
@@ -2420,9 +2606,16 @@
0680 PCI0680 Ultra ATA-133 Host Controller
1095 3680 Winic W-680 (Silicon Image 680 based)
3112 SiI 3112 [SATALink/SATARaid] Serial ATA Controller
- 1095 6112 Asus A7N8X
+ 1095 3112 SiI 3112 SATALink Controller
+ 1095 6112 SiI 3112 SATARaid Controller
3114 SiI 3114 [SATALink/SATARaid] Serial ATA Controller
+ 1095 3114 SiI 3114 SATALink Controller
+ 1095 6114 SiI 3114 SATARaid Controller
+ 3124 SiI 3124 PCI-X Serial ATA Controller
+ 1095 3124 SiI 3124 PCI-X Serial ATA Controller
3512 SiI 3512 [SATALink/SATARaid] Serial ATA Controller
+ 1095 3512 SiI 3512 SATALink Controller
+ 1095 6512 SiI 3512 SATARaid Controller
1096 Alacron
1097 Appian Technology
1098 Quantum Designs (H.K.) Ltd
@@ -2444,6 +2637,7 @@
036e Bt878 Video Capture
0070 13eb WinTV Series
0070 ff01 Viewcast Osprey 200
+ 0071 0101 DigiTV PCI
107d 6606 WinFast TV 2000
11bd 0012 PCTV pro (TV + FM stereo receiver)
11bd 001c PCTV Sat (DBC receiver)
@@ -2454,6 +2648,7 @@
144f 3000 MagicTView CPH060 - Video
1461 0002 TV98 Series (TV/No FM/Remote)
1461 0004 AVerTV WDM Video Capture
+ 1461 0761 AverTV DVB-T
14f1 0001 Bt878 Mediastream Controller NTSC
14f1 0002 Bt878 Mediastream Controller PAL BG
14f1 0003 Bt878a Mediastream Controller PAL BG
@@ -2462,6 +2657,7 @@
1851 1850 FlyVideo'98 - Video
1851 1851 FlyVideo II
1852 1852 FlyVideo'98 - Video (with FM Tuner)
+ 270f fc00 Digitop DTT-1000
bd11 1200 PCTV pro (TV + FM stereo receiver)
036f Bt879 Video Capture
127a 0044 Bt879 Video Capture NTSC
@@ -2500,6 +2696,7 @@
0878 Bt878 Audio Capture
0070 13eb WinTV Series
0070 ff01 Viewcast Osprey 200
+ 0071 0101 DigiTV PCI
1002 0001 TV-Wonder
1002 0003 TV-Wonder/VE
11bd 0012 PCTV pro (TV + FM stereo receiver, audio section)
@@ -2511,11 +2708,13 @@
13e9 0070 Win/TV (Audio Section)
144f 3000 MagicTView CPH060 - Audio
1461 0004 AVerTV WDM Audio Capture
+ 1461 0761 AVerTV DVB-T
14f1 0001 Bt878 Video Capture (Audio Section)
14f1 0002 Bt878 Video Capture (Audio Section)
14f1 0003 Bt878 Video Capture (Audio Section)
14f1 0048 Bt878 Video Capture (Audio Section)
1822 0001 VisionPlus DVB Card
+ 270f fc00 Digitop DTT-1000
bd11 1200 PCTV pro (TV + FM stereo receiver, audio section)
0879 Bt879 Audio Capture
127a 0044 Bt879 Video Capture (Audio Section)
@@ -2631,12 +2830,15 @@
15ed 1003 MCCS 16-port Serial Hot Swap
9036 9036
9050 PCI <-> IOBus Bridge
+ 10b5 1067 IXXAT CAN i165
+ 10b5 1172 IK220 (Heidenhain)
10b5 2036 SatPak GPS
10b5 2221 Alpermann+Velte PCL PCI LV: Timecode Reader Board
10b5 2273 SH-ARC SoHard ARCnet card
10b5 2431 Alpermann+Velte PCL PCI D: Timecode Reader Board
10b5 2905 Alpermann+Velte PCI TS: Time Synchronisation Board
10b5 9050 MP9050
+ 1498 0362 TPMC866 8 Channel Serial Card
1522 0001 RockForce 4 Port V.90 Data/Fax/Voice Modem
1522 0002 RockForce 2 Port V.90 Data/Fax/Voice Modem
1522 0003 RockForce 6 Port V.90 Data/Fax/Voice Modem
@@ -2689,6 +2891,8 @@
125c 0640 Aries 16000P
906e 9060ES
9080 9080
+ 103c 10eb (Agilent) E2777B 83K Series PCI based Optical Communication Interface
+ 103c 10ec (Agilent) E6978-66442 PCI CIC
10b5 9080 9080 [real subsystem ID not set]
129d 0002 Aculab PCI Prosidy card
12d9 0002 PCI Prosody Card
@@ -2721,6 +2925,8 @@
1001 Collage 155 ATM Server Adapter
10b7 3Com Corporation
0001 3c985 1000BaseSX (SX/TX)
+ 0013 AR5212 802.11abg NIC (3CRDAG675)
+ 10b7 2031 3CRDAG675 11a/b/g Wireless PCI Adapter
0910 3C910-A01
1006 MINI PCI type 3B Data Fax Modem
1007 Mini PCI 56k Winmodem
@@ -2731,6 +2937,7 @@
1043 80eb P4P800 Mainboard
10b7 0010 3C940 Gigabit LOM Ethernet Adapter
10b7 0020 3C941 Gigabit LOM Ethernet Adapter
+ 147b 1407 KV8-MAX3 motherboard
3390 3c339 TokenLink Velocity
3590 3c359 TokenLink Velocity XL
10b7 3590 TokenLink Velocity XL Adapter (3C359/359B)
@@ -2769,6 +2976,7 @@
7940 3c803 FDDILink UTP Controller
7980 3c804 FDDILink SAS Controller
7990 3c805 FDDILink DAS Controller
+ 80eb 3c940B 10/100/1000Base-T
8811 Token ring
9000 3c900 10BaseT [Boomerang]
9001 3c900 10Mbps Combo [Boomerang]
@@ -2808,6 +3016,7 @@
9200 3c905C-TX/TX-M [Tornado]
1028 0095 3C920 Integrated Fast Ethernet Controller
1028 0097 3C920 Integrated Fast Ethernet Controller
+ 1028 00fe Optiplex GX240
1028 012a 3C920 Integrated Fast Ethernet Controller [Latitude C640]
10b7 1000 3C905C-TX Fast Etherlink for PC Management NIC
10b7 7000 10/100 Mini PCI Ethernet Adapter
@@ -2820,6 +3029,8 @@
9800 3c980-TX Fast Etherlink XL Server Adapter [Cyclone]
10b7 9800 3c980-TX Fast Etherlink XL Server Adapter
9805 3c980-C 10/100baseTX NIC [Python-T]
+ 10b7 1201 EtherLink Server 10/100 Dual Port A
+ 10b7 1202 EtherLink Server 10/100 Dual Port B
10b7 9805 3c980 10/100baseTX NIC [Python-T]
10f1 2462 Thunder K7 S2462
9900 3C990-TX [Typhoon]
@@ -2861,8 +3072,11 @@
a011 83C170QF
b106 SMC34C90
10b9 ALi Corporation
+ 0101 CMI8338/C3DX PCI Audio Device
0111 C-Media CMI8738/C3DX Audio Device (OEM)
10b9 0111 C-Media CMI8738/C3DX Audio Device (OEM)
+ 0780 Multi-IO Card
+ 0782 Multi-IO Card
1435 M1435
1445 M1445
1449 M1449
@@ -2878,6 +3092,7 @@
10b9 1523 ALI M1523 ISA Bridge
1531 M1531 [Aladdin IV]
1533 M1533 PCI to ISA Bridge [Aladdin IV]
+ 1014 053b ThinkPad R40e (2684-HVG) PCI to ISA Bridge
10b9 1533 ALI M1533 Aladdin IV ISA Bridge
1541 M1541
10b9 1541 ALI M1541 Aladdin V/V+ AGP System Controller
@@ -2892,8 +3107,10 @@
1647 M1647 Northbridge [MAGiK 1 / MobileMAGiK 1]
1651 M1651/M1651T Northbridge [Aladdin-Pro 5/5M,Aladdin-Pro 5T/5TM]
1671 M1671 Super P4 Northbridge [AGP4X,PCI and SDR/DDR]
+ 1672 M1672 Northbridge [CyberALADDiN-P4]
1681 M1681 P4 Northbridge [AGP8X,HyperTransport and SDR/DDR]
1687 M1687 K8 Northbridge [AGP8X and HyperTransport]
+ 1689 M1689 K8 Northbridge [Super K8 Single Chip]
3141 M3141
3143 M3143
3145 M3145
@@ -2910,22 +3127,34 @@
5225 M5225
5229 M5229 IDE
1014 050f ThinkPad R30
+ 1014 053d ThinkPad R40e (2684-HVG) builtin IDE
+ 103c 0024 Pavilion ze4400 builtin IDE
1043 8053 A7A266 Motherboard IDE
5235 M5225
5237 USB 1.1 Controller
+ 1014 0540 ThinkPad R40e (2684-HVG) builtin USB
+ 103c 0024 Pavilion ze4400 builtin USB
5239 USB 2.0 Controller
5243 M1541 PCI to AGP Controller
+ 5246 AGP8X Controller
5247 PCI to AGP Controller
5249 M5249 HTT to PCI Bridge
5251 M5251 P1394 OHCI 1.0 Controller
5253 M5253 P1394 OHCI 1.1 Controller
5261 M5261 Ethernet Controller
+ 5263 M5263 Ethernet Controller
+ 5281 ALi M5281 Serial ATA / RAID Host Controller
5450 Lucent Technologies Soft Modem AMR
5451 M5451 PCI AC-Link Controller Audio Device
1014 0506 ThinkPad R30
+ 1014 053e ThinkPad R40e (2684-HVG) builtin Audio
+ 103c 0024 Pavilion ze4400 builtin Audio
+ 10b9 5451 HP Compaq nc4010 (DY885AA#ABN)
5453 M5453 PCI AC-Link Controller Modem Device
5455 M5455 PCI AC-Link Controller Audio Device
5457 M5457 AC'97 Modem Controller
+ 1014 0535 ThinkPad R40e (2684-HVG) builtin modem
+ 103c 0024 Pavilion ze4400 builtin Modem Device
# Same but more usefull for driver's lookup
5459 SmartLink SmartPCI561 56K Modem
# SmartLink PCI SoftModem
@@ -2934,6 +3163,8 @@
5473 M5473 SD-MMC Controller
7101 M7101 Power Management Controller [PMU]
1014 0510 ThinkPad R30
+ 1014 053c ThinkPad R40e (2684-HVG) Power Management Controller
+ 103c 0024 Pavilion ze4400
10ba Mitsubishi Electric Corp.
0301 AccelGraphics AccelECLIPSE
0304 AccelGALAXY A2100 [OEM Evans & Sutherland]
@@ -2990,6 +3221,7 @@
0e11 b126 MagicMedia 256AV Audio Device on Durango
1014 00dd MagicMedia 256AV Audio Device on BlackTip Thinkpad
1025 1003 MagicMedia 256AV Audio Device on TravelMate 720
+ 1028 0088 Latitude CPi A
1028 008f MagicMedia 256AV Audio Device on Colorado Inspiron
103c 0007 MagicMedia 256AV Audio Device on Voyager II
103c 0008 MagicMedia 256AV Audio Device on Voyager III
@@ -3074,6 +3306,7 @@
1043 0205 PCI-V3800
1043 4000 AGP-V3800PRO
1048 0c21 Synergy II
+ 1048 0c31 Erazor III
107d 2134 WinFast 3D S320 II + TV-Out
1092 4804 Viper V770
1092 4a00 Viper V770
@@ -3115,7 +3348,35 @@
1554 1041 Pixelview RIVA TNT2 M64
002e NV6 [Vanta]
002f NV6 [Vanta]
- 0041 NV40 OS1RT00B30
+ 0034 MCP04 SMBus
+ 0035 MCP04 IDE
+ 0036 MCP04 Serial ATA Controller
+ 0037 MCP04 Ethernet Controller
+ 0038 MCP04 Ethernet Controller
+ 003a MCP04 AC'97 Audio Controller
+ 003b MCP04 USB Controller
+ 003c MCP04 USB Controller
+ 003d MCP04 PCI Bridge
+ 003e MCP04 Serial ATA Controller
+ 0040 NV40 [GeForce 6800 Ultra]
+ 0041 NV40 [GeForce 6800]
+ 0042 NV40.2
+ 0043 NV40.3
+ 0045 NV40 [GeForce 6800 GT]
+ 0049 NV40GL
+ 004e NV40GL [Quadro FX 4000]
+ 0052 CK804 SMBus
+ 0053 CK804 IDE
+ 0054 CK804 Serial ATA Controller
+ 0055 CK804 Serial ATA Controller
+ 0056 CK804 Ethernet Controller
+ 0057 CK804 Ethernet Controller
+ 0059 CK804 AC'97 Audio Controller
+ 005a CK804 USB Controller
+ 005b CK804 USB Controller
+ 005c CK804 PCI Bridge
+ 005d CK804 PCIE Bridge
+ 005e CK804 Memory Controller
0060 nForce2 ISA Bridge
1043 80ad A7N8X Mainboard
0064 nForce2 SMBus (MCP)
@@ -3128,14 +3389,30 @@
1043 0c11 A7N8X Mainboard
006a nForce2 AC97 Audio Controler (MCP)
006b nForce MultiMedia audio [Via VT82C686B]
+ 10de 006b nForce2 MCP Audio Processing Unit
006c nForce2 External PCI Bridge
006d nForce2 PCI Bridge
006e nForce2 FireWire (IEEE 1394) Controller
+ 0084 MCP2A SMBus
+ 0085 MCP2A IDE
+ 0086 MCP2A Ethernet Controller
+ 0087 MCP2A USB Controller
+ 0088 MCP2A USB Controller
+ 008a MCP2S AC'97 Audio Controller
+ 008b MCP2A PCI Bridge
+ 008c MCP2A Ethernet Controller
+ 008e nForce2 Serial ATA Controller
00a0 NV5 [Aladdin TNT2]
14af 5810 Maxi Gamer Xentor
+ 00c0 NV41.0
+ 00c1 NV41.1
+ 00c2 NV41.2
+ 00c8 NV41.8
+ 00ce NV41GL
00d0 nForce3 LPC Bridge
00d1 nForce3 Host Bridge
00d2 nForce3 AGP Bridge
+ 00d3 CK804 Memory Controller
00d4 nForce3 SMBus
00d5 nForce3 IDE
00d6 nForce3 Ethernet
@@ -3143,6 +3420,29 @@
00d8 nForce3 USB 2.0
00da nForce3 Audio
00dd nForce3 PCI Bridge
+ 00df CK8S Ethernet Controller
+ 00e1 nForce3 250Gb Host Bridge
+ 00e2 nForce3 250Gb AGP Host to PCI Bridge
+ 00e3 CK8S Serial ATA Controller (v2.5)
+ 00e4 nForce 250Gb PCI System Management
+ 00e5 CK8S Parallel ATA Controller (v2.5)
+ 00e6 CK8S Ethernet Controller
+ 00e7 CK8S USB Controller
+ 00e8 CK8S USB Controller
+ 00ea nForce3 250Gb AC'97 Audio Controller
+ 00ed nForce3 250Gb PCI-to-PCI Bridge
+ 00ee CK8S Serial ATA Controller (v2.5)
+ 00f0 NV40 [GeForce 6800/GeForce 6800 Ultra]
+ 00f1 NV43 [GeForce 6600/GeForce 6600 GT]
+ 00f2 NV43 [GeForce 6600 GT]
+ 00f8 NV45GL [Quadro FX 3400]
+ 00f9 NV40 [GeForce 6800 Ultra]
+ 00fa NV36 [GeForce PCX 5750]
+ 00fb NV35 [GeForce PCX 5900]
+ 00fc NV37GL [Quadro FX 330/GeForce PCX 5300]
+ 00fd NV37GL [Quadro FX 330]
+ 00fe NV38GL [Quadro FX 1300]
+ 00ff NV18 [GeForce PCX 4300]
0100 NV10 [GeForce 256 SDR]
1043 0200 AGP-V6600 SGRAM
1043 0201 AGP-V6600 SDRAM
@@ -3161,6 +3461,7 @@
0110 NV11 [GeForce2 MX/MX 400]
1043 4015 AGP-V7100 Pro
1043 4031 V7100 Pro with TV output
+ 10de 0091 Dell OEM GeForce 2 MX 400
1462 8817 MSI GeForce2 MX400 Pro32S [MS-8817]
14af 7102 3D Prophet II MX
14af 7103 3D Prophet II MX Dual-Display
@@ -3197,6 +3498,7 @@
017a NV17GL [Quadro4 200/400 NVS]
017b NV17GL [Quadro4 550 XGL]
017c NV17GL [Quadro4 550 GoGL]
+ 017d NV17 [GeForce4 410 Go 16M]
0181 NV18 [GeForce4 MX 440 AGP 8x]
1043 806f V9180 Magic
1462 8880 MS-StarForce GeForce4 MX 440 with AGP8X
@@ -3206,14 +3508,18 @@
0182 NV18 [GeForce4 MX 440SE AGP 8x]
0183 NV18 [GeForce4 MX 420 AGP 8x]
0185 NV18 [GeForce4 MX 4000 AGP 8x]
+ 0186 NV18M [GeForce4 448 Go]
+ 0187 NV18M [GeForce4 488 Go]
0188 NV18GL [Quadro4 580 XGL]
018a NV18GL [Quadro4 NVS AGP 8x]
018b NV18GL [Quadro4 380 XGL]
+ 018d NV18M [GeForce4 448 Go]
01a0 NVCrush11 [GeForce2 MX Integrated Graphics]
01a4 nForce CPU bridge
01ab nForce 420 Memory Controller (DDR)
01ac nForce 220/420 Memory Controller
01ad nForce 220/420 Memory Controller
+ 01b0 nForce Audio
01b1 nForce Audio
01b2 nForce ISA Bridge
01b4 nForce PCI System Management
@@ -3241,6 +3547,7 @@
0203 NV20DCC [Quadro DCC]
0250 NV25 [GeForce4 Ti 4600]
0251 NV25 [GeForce4 Ti 4400]
+ 1043 8023 v8440 GeForce 4 Ti4400
0252 NV25 [GeForce4 Ti]
0253 NV25 [GeForce4 Ti 4200]
107d 2896 WinFast A250 LE TD (Dual VGA/TV-out/DVI)
@@ -3254,6 +3561,7 @@
0286 NV28 [GeForce4 Ti 4200 Go AGP 8x]
0288 NV28GL [Quadro4 980 XGL]
0289 NV28GL [Quadro4 780 XGL]
+ 028c NV28GLM [Quadro4 700 GoGL]
0300 NV30 [GeForce FX]
0301 NV30 [GeForce FX 5800 Ultra]
0302 NV30 [GeForce FX 5800]
@@ -3261,32 +3569,66 @@
0309 NV30GL [Quadro FX 1000]
0311 NV31 [GeForce FX 5600 Ultra]
0312 NV31 [GeForce FX 5600]
+ 0313 NV31
0314 NV31 [GeForce FX 5600XT]
+ 1043 814a V9560XT/TD
+ 0316 NV31
+ 0317 NV31
031a NV31M [GeForce FX Go 5600]
+ 031b NV31M [GeForce FX Go5650]
031c NVIDIA Quadro FX 700 Go
+ 031d NV31
+ 031e NV31
+ 031f NV31
+ 0320 NV34 [GeForce FX 5200]
0321 NV34 [GeForce FX 5200 Ultra]
0322 NV34 [GeForce FX 5200]
1462 9171 MS-8917 (FX5200-T128)
+ 0323 NV34 [GeForce FX 5200LE]
0324 NV34M [GeForce FX Go 5200]
1071 8160 MIM2000
+ 0325 NV34M [GeForce FX Go5250]
+ 0326 NV34 [GeForce FX 5500]
+ 0327 NV34 [GeForce FX 5100]
0328 NV34M [GeForce FX Go 5200]
0329 NV34M [GeForce FX Go5200]
- 032b NV34GL [Quadro FX 500]
+ 032a NV34GL [Quadro NVS 280 PCI]
+ 032b NV34GL [Quadro FX 500/600 PCI]
032c NV34GLM [GeForce FX Go 5300]
+ 032d NV34 [GeForce FX Go5100]
+ 032f NV34
0330 NV35 [GeForce FX 5900 Ultra]
0331 NV35 [GeForce FX 5900]
+ 1043 8145 V9950GE
0332 NV35 [GeForce FX 5900XT]
0333 NV38 [GeForce FX 5950 Ultra]
+ 0334 NV35 [GeForce FX 5900ZT]
0338 NV35GL [Quadro FX 3000]
- 0341 NV 36 [GeForce 5700 Ultra]
- 0342 NV 36 [GeForce 5700]
+ 033f NV35GL [Quadro FX 700]
+ 0341 NV36.1 [GeForce FX 5700 Ultra]
+ 0342 NV36.2 [GeForce FX 5700]
+ 0343 NV36 [GeForce FX 5700LE]
+ 0344 NV36.4 [GeForce FX 5700VE]
+ 0345 NV36.5
+ 0347 NV36 [GeForce FX Go5700]
+ 0348 NV36 [GeForce FX Go5700]
+ 0349 NV36
+ 034b NV36
+ 034c NV36 [Quadro FX Go1000]
+ 034e NV36GL [Quadro FX 1100]
+ 034f NV36GL
10df Emulex Corporation
1ae5 LP6000 Fibre Channel Host Adapter
1ae6 LP 8000 Fibre Channel Host Adapter Alternate ID (JX1:2-3, JX2:1-2)
1ae7 LP 8000 Fibre Channel Host Adapter Alternate ID (JX1:2-3, JX2:2-3)
+ f015 LP1150e
f085 LP850 Fibre Channel Adapter
f095 LP952 Fibre Channel Adapter
f098 LP982 Fibre Channel Adapter
+ f0a1 LightPulse Fibre Channel Adapter
+ f0a5 LP1050
+ f0d5 LP1150
+ f100 LP11000e
f700 LP7000 Fibre Channel Host Adapter
f701 LP 7000EFibre Channel Host Adapter Alternate ID (JX1:2-3, JX2:1-2)
f800 LP8000 Fibre Channel Host Adapter
@@ -3297,6 +3639,9 @@
f981 LP 9802 Fibre Channel Host Adapter Alternate ID
f982 LP 9802 Fibre Channel Host Adapter Alternate ID
fa00 LP10000 Fibre Channel Host Adapter
+ fa01 LP101
+ fb00 LightPulse Fibre Channel Adapter
+ fd00 LP11000
10e0 Integrated Micro Solutions Inc.
5026 IMS5026/27/28
5027 IMS5027
@@ -3314,6 +3659,8 @@
0000 CA91C042 [Universe]
0860 CA91C860 [QSpan]
0862 CA91C862A [QSpan-II]
+ 8260 CA91L8200B [Dual PCI PowerSpan II]
+ 8261 CA91L8260B [Single PCI PowerSpan II]
10e4 Tandem Computers
10e5 Micro Industries Corporation
10e6 Gainbery Computer Products Inc.
@@ -3333,8 +3680,18 @@
80d9 PCI-9118
80da PCI-9812
811a PCI-IEEE1355-DS-DE Interface
+ 814c Fastcom ESCC-PCI (Commtech, Inc.)
8170 S5933 [Matchmaker] (Chipset Development Tool)
+# sold with Roper Scientifc(Photometrics) CoolSnap HQ camera
+ 81e6 Multimedia video controller
+ 8291 Fastcom 232/8-PCI (Commtech, Inc.)
+ 82c4 Fastcom 422/4-PCI (Commtech, Inc.)
+ 82c5 Fastcom 422/2-PCI (Commtech, Inc.)
+ 82c6 Fastcom IG422/1-PCI (Commtech, Inc.)
+ 82c7 Fastcom IG232/2-PCI (Commtech, Inc.)
+ 82ca Fastcom 232/4-PCI (Commtech, Inc.)
82db AJA HDNTV HD SDI Framestore
+ 82e2 Fastcom DIO24H-PCI (Commtech, Inc.)
8851 S5933 on Innes Corp FM Radio Capture card
10e9 Alps Electric Co., Ltd.
10ea Intergraphics Systems
@@ -3363,6 +3720,8 @@
8138 RT8139 (B/C) Cardbus Fast Ethernet Adapter
10ec 8138 RT8139 (B/C) Fast Ethernet Adapter
8139 RTL-8139/8139C/8139C+
+ 0357 000a TTP-Monitoring Card V2.0
+ 1025 005a TravelMate 290
1025 8920 ALN-325
1025 8921 ALN-325
1071 8160 MIM2000
@@ -3378,19 +3737,23 @@
1429 d010 ND010
1432 9130 EN-9130TX
1436 8139 RT8139
- 1458 e000 GA-7VM400M Motherboard
+ 1458 e000 GA-7VM400M/7VT600 Motherboard
146c 1439 FE-1439TX
1489 6001 GF100TXRII
1489 6002 GF100TXRA
149c 139a LFE-8139ATX
149c 8139 LFE-8139TX
+ 14cb 0200 LNR-100 Family 10/100 Base-TX Ethernet
1799 5000 F5D5000 PCI Card/Desktop Network PCI Card
2646 0001 EtheRx
8e2e 7000 KF-230TX
8e2e 7100 KF-230TX/2
a0a0 0007 ALN-325C
8169 RTL-8169 Gigabit Ethernet
+ 1259 c107 CG-LAPCIGT
1371 434e ProG-2000L
+ 1458 e000 GA-K8VT800 Pro Motherboard
+ 1462 702c K8T NEO 2 motherboard
8180 RTL8180L 802.11b MAC
8197 SmartLAN56 56K Modem
10ed Ascii Corporation
@@ -3455,6 +3818,7 @@
1102 8061 SBLive! Player 5.1
1102 8064 SB Live! 5.1 Model SB0100
1102 8065 SBLive! 5.1 Digital Model SB0220
+ 1102 8067 SBLive! 5.1 eMicro 28028
0004 SB Audigy
1102 0051 SB0090 Audigy Player
1102 0053 SB0090 Audigy Player/OEM
@@ -3462,6 +3826,9 @@
1102 2002 SB Audigy 2 ZS (SB0350)
0006 [SB Live! Value] EMU10k1X
0007 SB Audigy LS
+ 1102 1001 SB0310 Audigy LS
+ 1102 1002 SB0312 Audigy LS
+ 0008 SB0400 Audigy2 Value
4001 SB Audigy FireWire Port
1102 0010 SB Audigy FireWire Port
7002 SB Live! MIDI/Game Port
@@ -3470,6 +3837,8 @@
1102 0040 SB Audigy MIDI/Game Port
7004 [SB Live! Value] Input device controller
7005 SB Audigy LS MIDI/Game port
+ 1102 1001 SB0310 Audigy LS MIDI/Game port
+ 1102 1002 SB0312 Audigy LS MIDI/Game port
8064 SB0100 [SBLive! 5.1 OEM]
8938 Ectiva EV1938
1103 Triones Technologies, Inc.
@@ -3477,7 +3846,12 @@
# Revisions: 01=HPT366, 03=HPT370, 04=HPT370A, 05=HPT372
0004 HPT366/368/370/370A/372
1103 0001 HPT370A
+ 1103 0003 HPT343 / HPT345 / HPT363 UDMA33
+ 1103 0004 HPT366 UDMA66 (r1) / HPT368 UDMA66 (r2) / HPT370 UDMA100 (r3) / HPT370 UDMA100 RAID (r4)
1103 0005 HPT370 UDMA100
+ 1103 0006 HPT302
+ 1103 0007 HPT371 UDMA133
+ 1103 0008 HPT374 UDMA/ATA133 RAID Controller
0005 HPT372A
0006 HPT302
0007 HPT371
@@ -3519,6 +3893,9 @@
1179 0001 Magnia Z310
1297 f641 FX41 motherboard
1458 5002 GA-7VAX Mainboard
+ 1462 7020 K8T NEO 2 motherboard
+ 147b 1407 KV8-MAX3 motherboard
+ 1849 0571 K7VT2 motherboard
0576 VT82C576 3V [Apollo Master]
0585 VT82C585VP [Apollo VP1/VPX]
0586 VT82C586/A/B PCI-to-ISA [Apollo VP]
@@ -3555,6 +3932,7 @@
1106 VT82C570MV
1571 VT82C576M/VT82C586
1595 VT82C595/97 [Apollo VP2/97]
+ 3022 CLE266
# This is *not* USB 2.0 as the existing entry suggests
3038 VT82xxxxx UHCI USB 1.1 Controller
0925 1234 USB Controller
@@ -3565,12 +3943,17 @@
1043 80ed A7V600 motherboard
1179 0001 Magnia Z310
1458 5004 GA-7VAX Mainboard
+ 1462 7020 K8T NEO 2 motherboard
+ 147b 1407 KV8-MAX3 motherboard
3040 VT82C586B ACPI
3043 VT86C100A [Rhine]
10bd 0000 VT86C100A Fast Ethernet Adapter
1106 0100 VT86C100A Fast Ethernet Adapter
1186 1400 DFE-530TX rev A
3044 IEEE 1394 Host Controller
+ 1025 005a TravelMate 290
+ 1458 1000 GA-7VT600-1394 Motherboard
+ 1462 702d K8T NEO 2 motherboard
3050 VT82C596 Power Management
3051 VT82C596 Power Management
3053 VT6105M [Rhine-III]
@@ -3597,16 +3980,20 @@
1043 80a1 A7V8X-X Motherboard
1043 80b0 A7V600 motherboard (ADI AD1980 codec [SoundMAX])
1106 3059 L7VMM2 Motherboard
+ 1106 4161 K7VT2 motherboard
1297 c160 FX41 motherboard (Realtek ALC650 codec)
1458 a002 GA-7VAX Onboard Audio (Realtek ALC650)
+ 1462 0080 K8T NEO 2 motherboard
1462 3800 KT266 onboard audio
+ 147b 1407 KV8-MAX3 motherboard
3065 VT6102 [Rhine-II]
1043 80a1 A7V8X-X Motherboard
1106 0102 VT6102 [Rhine II] Embeded Ethernet Controller on VT8235
1186 1400 DFE-530TX rev A
1186 1401 DFE-530TX rev B
13b9 1421 LD-10/100AL PCI Fast Ethernet Adapter (rev.B)
- 3068 Intel 537 [AC97 Modem]
+# This hosts more than just the Intel 537 codec, it also hosts PCtel (SIL33) and SmartLink (SIL34) codecs
+ 3068 AC'97 Modem Controller
1462 309e MS-6309 Saturn Motherboard
3074 VT8233 PCI to ISA Bridge
1043 8052 VT8233A
@@ -3614,6 +4001,7 @@
3099 VT8366/A/7 [Apollo KT266/A/333]
1043 8064 A7V266-E Mainboard
1043 807f A7V333 Mainboard
+ 1849 3099 K7VT2 motherboard
3101 VT8653 Host Bridge
3102 VT8662 Host Bridge
3103 VT8615 Host Bridge
@@ -3624,12 +4012,17 @@
1043 80ed A7V600 motherboard
1297 f641 FX41 motherboard
1458 5004 GA-7VAX Mainboard
+ 1462 7020 K8T NEO 2 motherboard
+ 147b 1407 KV8-MAX3 motherboard
3106 VT6105 [Rhine-III]
1186 1403 DFE-530TX rev C
+ 3108 S3 Unichrome Pro VGA Adapter
3109 VT8233C PCI to ISA Bridge
3112 VT8361 [KLE133] Host Bridge
3116 VT8375 [KM266/KL266] Host Bridge
1297 f641 FX41 motherboard
+ 3118 S3 Unichrome Pro VGA Adapter
+ 3119 VT6120/VT6121/VT6122 Gigabit Ethernet Adapter
# found on EPIA M6000/9000 mainboard
3122 VT8623 [Apollo CLE266] integrated CastleRock graphics
# found on EPIA M6000/9000 mainboard
@@ -3640,6 +4033,7 @@
3148 P4M266 Host Bridge
3149 VIA VT6420 SATA RAID Controller
1043 80ed A7V600 motherboard
+ 1458 b003 GA-7VM400AM(F) Motherboard
1462 7020 MSI Neo K8T FIS2R mainboard
3156 P/KN266 Host Bridge
# on ASUS P4P800
@@ -3651,20 +4045,27 @@
1043 80a1 A7V8X-X motherboard
1297 f641 FX41 motherboard
1458 5001 GA-7VAX Mainboard
+ 1849 3177 K7VT2 motherboard
3188 VT8385 [K8T800 AGP] Host Bridge
+ 147b 1407 KV8-MAX3 motherboard
3189 VT8377 [KT400/KT600 AGP] Host Bridge
1043 807f A7V8X motherboard
1458 5000 GA-7VAX Mainboard
-# Updated the entry to the proper "chip [name] desc" format
- 3205 VT8378 [KM400] Chipset Host Bridge
+ 3204 K8M800
+ 3205 VT8378 [KM400/A] Chipset Host Bridge
1458 5000 GA-7VM400M Motherboard
- 3227 VT8237 ISA bridge [K8T800 South]
+ 3227 VT8237 ISA bridge [KT600/K8T800 South]
1043 80ed A7V600 motherboard
+ 1106 3227 DFI KT600-AL Motherboard
+ 1458 5001 GA-7VT600 Motherboard
+ 147b 1407 KV8-MAX3 motherboard
+ 4149 VIA VT6420 (ATA133) Controller
5030 VT82C596 ACPI [Apollo PRO]
6100 VT85C100A [Rhine II]
+ 7204 K8M800
# S3 Graphics UniChromeâ„¢ 2D/3D Graphics with motion compensation
7205 VT8378 [S3 UniChrome] Integrated Video
- 1458 d000 GA-7VM400M Motherboard
+ 1458 d000 Gigabyte GA-7VM400(A)M(F) Motherboard
8231 VT8231 [PCI-to-ISA Bridge]
8235 VT8235 ACPI
8305 VT8363/8365 [KT133/KM133 AGP]
@@ -3686,6 +4087,7 @@
b112 VT8361 [KLE133] AGP Bridge
b168 VT8235 PCI Bridge
b188 VT8237 PCI bridge [K8T800 South]
+ 147b 1407 KV8-MAX3 motherboard
b198 VT8237 PCI Bridge
# 32-Bit PCI bus master Ethernet MAC with standard MII interface
d104 VT8237 Integrated Fast Ethernet Controller
@@ -3711,9 +4113,12 @@
007b FSC Remote Service Controller, mailbox device
007c FSC Remote Service Controller, shared memory device
007d FSC Remote Service Controller, SMIC device
- 2102 DSCC4 WAN adapter
+# Superfastcom-PCI (Commtech, Inc.) or DSCC4 WAN Adapter
+ 2102 DSCC4 PEB/PEF 20534 DMA Supported Serial Communication Contr.
2104 Eicon Diva 2.02 compatible passive ISDN card
+ 3142 SIMATIC NET CP 5613A1 (Profibus Adapter)
4021 SIMATIC NET CP 5512 (Profibus and MPI Cardbus Adapter)
+ 4029 SIMATIC NET CP 5613A2 (Profibus Adapter)
4942 FPGA I-Bus Tracer for MBD
6120 SZB6120
110b Chromatic Research Inc.
@@ -3745,6 +4150,8 @@
9211 EN-1207D Fast Ethernet Adapter
1113 9211 EN-1207D Fast Ethernet Adapter
9511 21x4x DEC-Tulip compatible Fast Ethernet
+ d301 CPWNA100 (Philips wireless PCMCIA)
+ ec02 SMC 1244TX v3
1114 Atmel Corporation
0506 802.11b Wireless Network Adaptor (at76c506)
1115 3D Labs
@@ -3854,9 +4261,11 @@
111b Teledyne Electronic Systems
111c Tricord Systems Inc.
0001 Powerbis Bridge
-111d Integrated Device Tech
- 0001 IDT77211 ATM Adapter
- 0003 IDT77252 ATM network controller
+111d Integrated Device Technology, Inc.
+ 0001 IDT77201/77211 155Mbps ATM SAR Controller [NICStAR]
+ 0003 IDT77222/77252 155Mbps ATM MICRO ABR SAR Controller
+ 0004 IDT77V252 155Mbps ATM MICRO ABR SAR Controller
+ 0005 IDT77V222 155Mbps ATM MICRO ABR SAR Controller
111e Eldec
111f Precision Digital Images
4a47 Precision MX Video engine interface
@@ -3890,10 +4299,13 @@
1561 USB 1.1 Host Controller
1562 USB 2.0 Host Controller
3400 SmartPCI56(UCB1500) 56K Modem
+ 5400 TriMedia TM1000/1100
+ 5402 TriMedia TM-1300
7130 SAA7130 Video Broadcast Decoder
5168 0138 LiveView FlyVideo 2000
- 7133 SAA7133 Audio+video broadcast decoder
+ 7133 SAA713X Audio+video broadcast decoder
5168 0138 LifeView FlyVideo 3000
+ 5168 0212 LifeView FlyTV Platinum mini
# PCI audio and video broadcast decoder (http://www.semiconductors.philips.com/pip/saa7134hl)
7134 SAA7134
7135 SAA7135 Audio+video broadcast decoder
@@ -3906,7 +4318,7 @@
114b 2003 DVRaptor Video Edit/Capture Card
11bd 0006 DV500 Overlay
11bd 000a DV500 Overlay
- 13c2 0000 Siemens/Technotrend/Hauppauge DVB card rev1.3
+ 13c2 0000 Siemens/Technotrend/Hauppauge DVB card rev1.3 or rev1.5
13c2 0001 Technotrend/Hauppauge DVB card rev1.3 or rev1.6
13c2 0002 Technotrend/Hauppauge DVB card rev2.1
13c2 0003 Technotrend/Hauppauge DVB card rev2.1
@@ -3998,9 +4410,14 @@
1133 2002 Diva Server 4PRI/E1-120
1133 2003 Diva Server 4PRI/T1-96
e024 Diva Server Analog-4P
+ 1133 2400 Diva Server V-Analog-4P
+ 1133 e024 Diva Server Analog-4P
e028 Diva Server Analog-8P
+ 1133 2800 Diva Server V-Analog-8P
+ 1133 e028 Diva Server Analog-8P
1134 Mercury Computer Systems
0001 Raceway Bridge
+ 0002 Dual PCI to RapidIO Bridge
1135 Fuji Xerox Co Ltd
0001 Printer controller
1136 Momentum Data Systems
@@ -4048,7 +4465,8 @@
f015 NinjaSCSI-32 Melco
1146 Force Computers
1147 Interface Corp
-1148 Syskonnect (Schneider & Koch)
+# Formerly (Schneider & Koch)
+1148 SysKonnect
4000 FDDI Adapter
0e11 b03b Netelligent 100 FDDI DAS Fibre SC
0e11 b03c Netelligent 100 FDDI SAS Fibre SC
@@ -4106,6 +4524,14 @@
1148 9521 SK-9521 10/100/1000Base-T Adapter
4400 SK-9Dxx Gigabit Ethernet Adapter
4500 SK-9Mxx Gigabit Ethernet Adapter
+ 9e00 SK-9Exx 10/100/1000Base-T Adapter
+ 1148 2100 SK-9E21 Server Adapter
+ 1148 21d0 SK-9E21D 10/100/1000Base-T Adapter
+ 1148 2200 SK-9E22 Server Adapter
+ 1148 8100 SK-9E81 Server Adapter
+ 1148 8200 SK-9E82 Server Adapter
+ 1148 9100 SK-9E91 Server Adapter
+ 1148 9200 SK-9E92 Server Adapter
1149 Win System Corporation
114a VMIC
5579 VMIPCI-5579 (Reflective Memory Card)
@@ -4259,6 +4685,7 @@
0212 CSB5 IDE Controller
4c53 1080 CT8 mainboard
0213 CSB6 RAID/IDE Controller
+ 0217 CSB6 IDE Controller
0220 OSB4/CSB5 OHCI USB Controller
4c53 1080 CT8 mainboard
0221 CSB6 OHCI USB Controller
@@ -4268,6 +4695,7 @@
0227 GCLE-2 Host Bridge
0230 CSB5 LPC bridge
4c53 1080 CT8 mainboard
+ 0240 K2 SATA
1167 Mutoh Industries Inc
1168 Thine Electronics Inc
1169 Centre for Development of Advanced Computing
@@ -4300,7 +4728,7 @@
0603 ToPIC95 PCI to CardBus Bridge for Notebooks
060a ToPIC95
060f ToPIC97
- 0617 ToPIC95 PCI to Cardbus Bridge with ZV Support
+ 0617 ToPIC100 PCI to Cardbus Bridge with ZV Support
0618 CPU to PCI and PCI to ISA bridge
# Claimed to be Lucent DSP1645 [Mars], but that's apparently incorrect. Does anyone know the correct ID?
0701 FIR Port
@@ -4342,16 +4770,33 @@
1002 DL10050 Sundance Ethernet
1186 1002 DFE-550TX
1186 1012 DFE-580TX
+ 1025 AirPlus Xtreme G DWL-G650 Adapter
+ 1026 AirXpert DWL-AG650 Wireless Cardbus Adapter
+ 1043 AirXpert DWL-AG650 Wireless Cardbus Adapter
1300 RTL8139 Ethernet
1186 1300 DFE-538TX 10/100 Ethernet Adapter
1186 1301 DFE-530TX+ 10/100 Ethernet Adapter
1340 DFE-690TXD CardBus PC Card
1541 DFE-680TXD CardBus PC Card
1561 DRP-32TXD Cardbus PC Card
+ 2027 AirPlus Xtreme G DWL-G520 Adapter
+ 3203 AirPlus Xtreme G DWL-G520 Adapter
3300 DWL-510 2.4GHz Wireless PCI Adapter
+ 3a03 AirPro DWL-A650 Wireless Cardbus Adapter(rev.B)
+ 3a04 AirPro DWL-AB650 Multimode Wireless Cardbus Adapter
+ 3a05 AirPro DWL-AB520 Multimode Wireless PCI Adapter
+ 3a07 AirXpert DWL-AG650 Wireless Cardbus Adapter
+ 3a08 AirXpert DWL-AG520 Wireless PCI Adapter
+ 3a10 AirXpert DWL-AG650 Wireless Cardbus Adapter(rev.B)
+ 3a11 AirXpert DWL-AG520 Wireless PCI Adapter(rev.B)
+ 3a12 AirPlus DWL-G650 Wireless Cardbus Adapter(rev.C)
+ 3a13 AirPlus DWL-G520 Wireless PCI Adapter(rev.B)
+ 3a14 AirPremier DWL-AG530 Wireless PCI Adapter
+ 3a63 AirXpert DWL-AG660 Wireless Cardbus Adapter
3b05 DWL-G650+ CardBus PC Card
4000 DL2000-based Gigabit Ethernet
4c00 Gigabit Ethernet Adapter
+ 1186 4c00 DGE-530T Gigabit Ethernet Adapter
8400 D-Link DWL-650+ CardBus PC Card
1187 Advanced Technology Laboratories, Inc.
1188 Shima Seiki Manufacturing Ltd.
@@ -4432,9 +4877,118 @@
# Formerly Galileo Technology, Inc.
11ab Marvell Technology Group Ltd.
0146 GT-64010/64010A System Controller
+ 138f W8300 802.11 Adapter (rev 07)
1fa6 Marvell W8300 802.11 Adapter
4146 GT-64011/GT-64111 System Controller
- 4320 Yukon Gigabit Ethernet 10/100/1000Base-T Adapter
+ 4320 Gigabit Ethernet Controller
+ 1019 0f38 Marvell 88E8001 Gigabit Ethernet Controller (ECS)
+ 1019 8001 Marvell 88E8001 Gigabit Ethernet Controller (ECS)
+ 1043 173c Marvell 88E8001 Gigabit Ethernet Controller (Asus)
+ 1043 811a Marvell 88E8001 Gigabit Ethernet Controller (Asus)
+ 105b 0c19 Marvell 88E8001 Gigabit Ethernet Controller (Foxconn)
+ 10b8 b452 SMC EZ Card 1000 (SMC9452TXV.2)
+ 11ab 0121 Marvell RDK-8001
+ 11ab 0321 Marvell RDK-8003
+ 11ab 1021 Marvell RDK-8010
+ 11ab 5021 Marvell Yukon Gigabit Ethernet 10/100/1000Base-T Controller (64 bit)
+ 11ab 9521 Marvell Yukon Gigabit Ethernet 10/100/1000Base-T Controller (32 bit)
+ 1458 e000 Marvell 88E8001 Gigabit Ethernet Controller (Gigabyte)
+ 147b 1406 Marvell 88E8001 Gigabit Ethernet Controller (Abit)
+ 15d4 0047 Marvell 88E8001 Gigabit Ethernet Controller (Iwill)
+ 1695 9025 Marvell 88E8001 Gigabit Ethernet Controller (Epox)
+ 17f2 1c03 Marvell 88E8001 Gigabit Ethernet Controller (Albatron)
+ 270f 2803 Marvell 88E8001 Gigabit Ethernet Controller (Chaintech)
+ 4350 Fast Ethernet Controller
+ 1179 0001 Marvell 88E8035 Fast Ethernet Controller (Toshiba)
+ 11ab 3521 Marvell RDK-8035
+ 1854 000d Marvell 88E8035 Fast Ethernet Controller (LGE)
+ 1854 000e Marvell 88E8035 Fast Ethernet Controller (LGE)
+ 1854 000f Marvell 88E8035 Fast Ethernet Controller (LGE)
+ 1854 0011 Marvell 88E8035 Fast Ethernet Controller (LGE)
+ 1854 0012 Marvell 88E8035 Fast Ethernet Controller (LGE)
+ 1854 0016 Marvell 88E8035 Fast Ethernet Controller (LGE)
+ 1854 0017 Marvell 88E8035 Fast Ethernet Controller (LGE)
+ 1854 0018 Marvell 88E8035 Fast Ethernet Controller (LGE)
+ 1854 0019 Marvell 88E8035 Fast Ethernet Controller (LGE)
+ 1854 001c Marvell 88E8035 Fast Ethernet Controller (LGE)
+ 1854 001e Marvell 88E8035 Fast Ethernet Controller (LGE)
+ 1854 0020 Marvell 88E8035 Fast Ethernet Controller (LGE)
+ 4351 Fast Ethernet Controller
+ 107b 4009 Marvell 88E8036 Fast Ethernet Controller (Wistron)
+ 10f7 8338 Marvell 88E8036 Fast Ethernet Controller (Panasonic)
+ 1179 0001 Marvell 88E8036 Fast Ethernet Controller (Toshiba)
+ 1179 ff00 Marvell 88E8036 Fast Ethernet Controller (Compal)
+ 1179 ff10 Marvell 88E8036 Fast Ethernet Controller (Inventec)
+ 11ab 3621 Marvell RDK-8036
+ 13d1 ac12 Abocom EFE3K - 10/100 Ethernet Expresscard
+ 161f 203d Marvell 88E8036 Fast Ethernet Controller (Arima)
+ 1854 000d Marvell 88E8036 Fast Ethernet Controller (LGE)
+ 1854 000e Marvell 88E8036 Fast Ethernet Controller (LGE)
+ 1854 000f Marvell 88E8036 Fast Ethernet Controller (LGE)
+ 1854 0011 Marvell 88E8036 Fast Ethernet Controller (LGE)
+ 1854 0012 Marvell 88E8036 Fast Ethernet Controller (LGE)
+ 1854 0016 Marvell 88E8036 Fast Ethernet Controller (LGE)
+ 1854 0017 Marvell 88E8036 Fast Ethernet Controller (LGE)
+ 1854 0018 Marvell 88E8036 Fast Ethernet Controller (LGE)
+ 1854 0019 Marvell 88E8036 Fast Ethernet Controller (LGE)
+ 1854 001c Marvell 88E8036 Fast Ethernet Controller (LGE)
+ 1854 001e Marvell 88E8036 Fast Ethernet Controller (LGE)
+ 1854 0020 Marvell 88E8036 Fast Ethernet Controller (LGE)
+ 4360 Gigabit Ethernet Controller
+ 1043 8134 Marvell 88E8052 Gigabit Ethernet Controller (Asus)
+ 107b 4009 Marvell 88E8052 Gigabit Ethernet Controller (Wistron)
+ 11ab 5221 Marvell RDK-8052
+ 1458 e000 Marvell 88E8052 Gigabit Ethernet Controller (Gigabyte)
+ 1462 052c Marvell 88E8052 Gigabit Ethernet Controller (MSI)
+ 1849 8052 Marvell 88E8052 Gigabit Ethernet Controller (ASRock)
+ 1940 e000 Marvell 88E8052 Gigabit Ethernet Controller (Gigabyte)
+ a0a0 0509 Marvell 88E8052 Gigabit Ethernet Controller (Aopen)
+ 4361 Gigabit Ethernet Controller
+ 107b 3015 Marvell 88E8050 Gigabit Ethernet Controller (Gateway)
+ 11ab 5021 Marvell 88E8050 Gigabit Ethernet Controller (Intel)
+ 8086 3063 D925XCVLK mainboard
+ 4362 Gigabit Ethernet Controller
+ 103c 2a0d Marvell 88E8053 Gigabit Ethernet Controller (Asus)
+ 1043 8142 Marvell 88E8053 Gigabit Ethernet Controller (Asus)
+ 109f 3197 Marvell 88E8053 Gigabit Ethernet Controller (Trigem)
+ 10f7 8338 Marvell 88E8053 Gigabit Ethernet Controller (Panasonic)
+ 10fd a430 Marvell 88E8053 Gigabit Ethernet Controller (SOYO)
+ 1179 0001 Marvell 88E8053 Gigabit Ethernet Controller (Toshiba)
+ 1179 ff00 Marvell 88E8053 Gigabit Ethernet Controller (Compal)
+ 1179 ff10 Marvell 88E8053 Gigabit Ethernet Controller (Inventec)
+ 11ab 5321 Marvell RDK-8053
+ 1297 c240 Marvell 88E8053 Gigabit Ethernet Controller (Shuttle)
+ 1297 c241 Marvell 88E8053 Gigabit Ethernet Controller (Shuttle)
+ 1297 c242 Marvell 88E8053 Gigabit Ethernet Controller (Shuttle)
+ 1297 c243 Marvell 88E8053 Gigabit Ethernet Controller (Shuttle)
+ 1297 c244 Marvell 88E8053 Gigabit Ethernet Controller (Shuttle)
+ 13d1 ac11 Abocom EGE5K - Giga Ethernet Expresscard
+ 1458 e000 Marvell 88E8053 Gigabit Ethernet Controller (Gigabyte)
+ 1462 058c Marvell 88E8053 Gigabit Ethernet Controller (MSI)
+ 14c0 0012 Marvell 88E8053 Gigabit Ethernet Controller (Compal)
+ 1558 04a0 Marvell 88E8053 Gigabit Ethernet Controller (Clevo)
+ 15bd 1003 Marvell 88E8053 Gigabit Ethernet Controller (DFI)
+ 161f 203c Marvell 88E8053 Gigabit Ethernet Controller (Arima)
+ 161f 203d Marvell 88E8053 Gigabit Ethernet Controller (Arima)
+ 1695 9029 Marvell 88E8053 Gigabit Ethernet Controller (Epox)
+ 17f2 2c08 Marvell 88E8053 Gigabit Ethernet Controller (Albatron)
+ 17ff 0585 Marvell 88E8053 Gigabit Ethernet Controller (Quanta)
+ 1849 8053 Marvell 88E8053 Gigabit Ethernet Controller (ASRock)
+ 1854 000b Marvell 88E8053 Gigabit Ethernet Controller (LGE)
+ 1854 000c Marvell 88E8053 Gigabit Ethernet Controller (LGE)
+ 1854 0010 Marvell 88E8053 Gigabit Ethernet Controller (LGE)
+ 1854 0013 Marvell 88E8053 Gigabit Ethernet Controller (LGE)
+ 1854 0014 Marvell 88E8053 Gigabit Ethernet Controller (LGE)
+ 1854 0015 Marvell 88E8053 Gigabit Ethernet Controller (LGE)
+ 1854 001a Marvell 88E8053 Gigabit Ethernet Controller (LGE)
+ 1854 001b Marvell 88E8053 Gigabit Ethernet Controller (LGE)
+ 1854 001d Marvell 88E8053 Gigabit Ethernet Controller (LGE)
+ 1854 001f Marvell 88E8053 Gigabit Ethernet Controller (LGE)
+ 1854 0021 Marvell 88E8053 Gigabit Ethernet Controller (LGE)
+ 1854 0022 Marvell 88E8053 Gigabit Ethernet Controller (LGE)
+ 1940 e000 Marvell 88E8053 Gigabit Ethernet Controller (Gigabyte)
+ 270f 2801 Marvell 88E8053 Gigabit Ethernet Controller (Chaintech)
+ a0a0 0506 Marvell 88E8053 Gigabit Ethernet Controller (Aopen)
4611 GT-64115 System Controller
4620 GT-64120/64120A/64121A System Controller
4801 GT-48001
@@ -4483,7 +5037,7 @@
11be International Microcircuits Inc
11bf Astrodesign, Inc.
11c0 Hewlett Packard
-11c1 Lucent Microelectronics
+11c1 Agere Systems (former Lucent Microelectronics)
0440 56k WinModem
1033 8015 LT WinModem 56k Data+Fax+Voice+Dsvd
1033 8047 LT WinModem 56k Data+Fax+Voice+Dsvd
@@ -4586,12 +5140,25 @@
0462 V90 WildWire Modem
0480 Venus Modem (V90, 56KFlex)
048c V.92 56K WinModem
+# InPorte Home Internal 56k Modem/fax/answering machine/SMS Features
+ 048f V.92 56k WinModem
5801 USB
5802 USS-312 USB Controller
# 4 port PCI USB Controller made by Agere (formely Lucent)
5803 USS-344S USB Controller
5811 FW323
+ 8086 524c D865PERL mainboard
dead 0800 FireWire Host Bus Adapter
+ ab10 WL60010 Wireless LAN MAC
+ ab11 WL60040 Multimode Wireles LAN MAC
+ 11c1 ab12 WaveLAN 11abg Cardbus card (Model 1102)
+ 11c1 ab13 WaveLAN 11abg MiniPCI card (Model 0512)
+ 11c1 ab15 WaveLAN 11abg Cardbus card (Model 1106)
+ 11c1 ab16 WaveLAN 11abg MiniPCI card (Model 0516)
+ ab20 ORiNOCO PCI Adapter
+ ab21 Agere Wireless PCI Adapter
+ ab30 Hermes2 Mini-PCI WaveLAN a/b/g
+ 14cd 2012 Hermes2 Mini-PCI WaveLAN a/b/g
11c2 Sand Microelectronics
11c3 NEC Corporation
11c4 Document Technologies, Inc
@@ -4717,6 +5284,7 @@
0903 RocketPort Compact PCI 16 port w/external I/F
8015 RocketPort 4-port UART 16954
11ff Scion Corporation
+ 0003 AG-5
1200 CSS Corporation
1201 Vista Controls Corp
1202 Network General Corp.
@@ -4774,6 +5342,7 @@
1014 020c ThinkPad R30
1179 0001 Magnia Z310
7110 OZ711Mx MultiMediaBay Accelerator
+ 103c 0890 NC6000 laptop
7112 OZ711EC1/M1 SmartCardBus MultiMediaBay Controller
7113 OZ711EC1 SmartCardBus Controller
7114 OZ711M1 SmartCardBus MultiMediaBay Controller
@@ -4781,6 +5350,7 @@
7212 OZ711M2 SmartCardBus MultiMediaBay Controller
7213 OZ6933E CardBus Controller
7223 OZ711M3 SmartCardBus MultiMediaBay Controller
+ 103c 0890 NC6000 laptop
1218 Hybricon Corp.
1219 First Virtual Corporation
121a 3Dfx Interactive, Inc.
@@ -4808,7 +5378,7 @@
121a 0030 Voodoo3 AGP
121a 0031 Voodoo3 AGP
121a 0034 Voodoo3 AGP
- 121a 0036 Voodoo3
+ 121a 0036 Voodoo3 2000 PCI
121a 0037 Voodoo3 AGP
121a 0038 Voodoo3 AGP
121a 003a Voodoo3 AGP
@@ -4913,6 +5483,7 @@
1100 C2 ISDN
1200 T1 ISDN
2700 Fritz!Card DSL SL
+ 2900 Fritz!Card DSL v2.0
1245 A.P.D., S.A.
1246 Dipix Technologies, Inc.
1247 Xylon Research, Inc.
@@ -4929,7 +5500,7 @@
0003 EasyIO
0004 EasyConnection/RA
124e Cylink
-124f Infotrend Technology, Inc.
+124f Infortrend Technology, Inc.
0041 IFT-2000 Series RAID Controller
1250 Hitachi Microcomputer System Ltd
1251 VLSI Solutions Oy
@@ -4998,6 +5569,8 @@
125e Specialvideo Engineering SRL
125f Concurrent Technologies, Inc.
1260 Intersil Corporation
+ 3872 Prism 2.5 Wavelan chipset
+ 1468 0202 LAN-Express IEEE 802.11b Wireless LAN
3873 Prism 2.5 Wavelan chipset
1186 3501 DWL-520 Wireless PCI Adapter
1186 3700 DWL-520 Wireless PCI Adapter, Rev E1
@@ -5007,10 +5580,18 @@
1737 3874 WMP11 Wireless 802.11b PCI Adapter
8086 2513 Wireless 802.11b MiniPCI Adapter
3886 ISL3886 [Prism Javelin/Prism Xbow]
+ 17cf 0037 Z-Com XG-901 and clones Wireless Adapter
3890 Intersil ISL3890 [Prism GT/Prism Duette]
+ 10b8 2802 SMC2802W Wireless PCI Adapter
+ 10b8 2835 SMC2835W Wireless Cardbus Adapter
10b8 a835 SMC2835W V2 Wireless Cardbus Adapter
+ 1113 ee03 SMC2802W V2 Wireless PCI Adapter
+ 1186 3202 DWL-G650 A1 Wireless Adapter
+ 1259 c104 CG-WLCB54GT Wireless Adapter
+ 1385 4800 WG511 Wireless Adapter
16a5 1605 ALLNET ALL0271 Wireless PCI Adapter
- 17cf 0014 Ovislink WL-5400PCM, Prism GT
+ 17cf 0014 Z-Com XG-600 and clones Wireless Adapter
+ 17cf 0020 Z-Com XG-900 and clones Wireless Adapter
8130 HMP8130 NTSC/PAL Video Decoder
8131 HMP8131 NTSC/PAL Video Decoder
1261 Matsushita-Kotobuki Electronics Industries, Ltd.
@@ -5256,6 +5837,7 @@
1283 Integrated Technology Express, Inc.
673a IT8330G
8212 IT/ITE8212 Dual channel ATA RAID controller
+ 1283 0001 IT/ITE8212 Dual channel ATA RAID controller
8330 IT8330G
8872 IT8874F PCI Dual Serial Port Controller
8888 IT8888F PCI to ISA Bridge with SMB
@@ -5312,11 +5894,13 @@
12a9 Xiotech Corporation
12aa SDL Communications, Inc.
12ab Yuan Yuan Enterprise Co., Ltd.
+ 0002 AU8830 [Vortex2] Based Sound Card With A3D Support
3000 MPG-200C PCI DVD Decoder Card
12ac Measurex Corporation
12ad Multidata GmbH
12ae Alteon Networks Inc.
0001 AceNIC Gigabit Ethernet
+ 1014 0104 Gigabit Ethernet-SX PCI Adapter
12ae 0001 Gigabit Ethernet-SX (Universal)
1410 0104 Gigabit Ethernet-SX PCI Adapter
0002 AceNIC Gigabit Ethernet (Copper)
@@ -5333,7 +5917,7 @@
12b6 Natural Microsystems
12b7 Cognex Modular Vision Systems Div. - Acumen Inc.
12b8 Korg
-12b9 5610 56K FaxModem
+12b9 3Com Corp, Modem Division (formerly US Robotics)
1006 WinModem
12b9 005c USR 56k Internal Voice WinModem (Model 3472)
12b9 005e USR 56k Internal WinModem (Models 662975)
@@ -5417,7 +6001,7 @@
12d3 Vingmed Sound A/S
12d4 Ulticom (Formerly DGM&S)
0200 T1 Card
-12d5 Equator Technologies
+12d5 Equator Technologies Inc
12d6 Analogic Corp
12d7 Biotronic SRL
12d8 Pericom Semiconductor
@@ -5546,6 +6130,7 @@
004c PCI-DAS1000
004d PCI-QUAD04
0052 PCI-DAS4020/12
+ 005e PCI-DAS6025
1308 Jato Technologies Inc.
0001 NetCelerator Adapter
1308 0001 NetCelerator Adapter
@@ -5569,6 +6154,7 @@
8201 ADMtek ADM8211 802.11b Wireless Interface
10b8 2635 SMC2635W 802.11b (11Mbps) wireless lan pcmcia (cardbus) card
1317 8201 SMC2635W 802.11b (11mbps) wireless lan pcmcia (cardbus) card
+ 8211 ADMtek ADM8211 802.11b Wireless Interface
9511 21x4x DEC-Tulip compatible 10/100 Ethernet
1318 Packet Engines Inc.
0911 GNIC-II PCI Gigabit Ethernet [Hamachi]
@@ -5620,6 +6206,7 @@
2060 Trio 2S(16550)+1P
2061 Trio 2S(16650)+1P
2062 Trio 2S(16850)+1P
+ 2081 CyberSerial (8-port) ST16654
1320 Crypto AG
1321 Arcobel Graphics BV
1322 MTT Co., Ltd
@@ -5636,6 +6223,7 @@
132d Integrated Silicon Solution, Inc.
1330 MMC Networks
1331 Radisys Corp.
+ 0030 ENP-2611
8200 82600 Host Bridge
8201 82600 IDE
8202 82600 USB
@@ -5667,6 +6255,8 @@
134b ARK Research Corp.
134c Chori Joho System Co. Ltd
134d PCTel Inc
+ 2189 HSP56 MicroModem
+ 2486 2304WT V.92 MDC Modem
7890 HSP MicroModem 56
134d 0001 PCT789 adapter
7891 HSP MicroModem 56
@@ -5715,9 +6305,17 @@
7401 Four Port RS-232 Interface
7402 Four Port RS-422/485 Interface
7801 Eight Port RS-232 Interface
+ 7804 Eight Port RS-232/422/485 Interface
8001 8001 Digital I/O Adapter
135f I-Data International A-S
1360 Meinberg Funkuhren
+ 0101 PCI32 DCF77 Radio Clock
+ 0102 PCI509 DCF77 Radio Clock
+ 0103 PCI510 DCF77 Radio Clock
+ 0201 GPS167PCI GPS Receiver
+ 0202 GPS168PCI GPS Receiver
+ 0203 GPS169PCI GPS Receiver
+ 0301 TCR510PCI IRIG Receiver
1361 Soliton Systems K.K.
1362 Fujifacom Corporation
1363 Phoenix Technology Ltd
@@ -5736,6 +6334,7 @@
1370 ATL Products
1371 CNet Technology Inc
434e GigaCard Network Adapter
+ 1371 434e N-Way PCI-Bus Giga-Card 1000/100/10Mbps(L)
1373 Silicon Vision Inc
1374 Silicom Ltd
1375 Argosystems Inc
@@ -5753,13 +6352,21 @@
1380 Sanritz Automation Co Ltd
1381 Brains Co. Ltd
1382 Marian - Electronic & Software
+ 0001 ARC88 audio recording card
2088 Marc-8 MIDI 8 channel audio card
1383 Controlnet Inc
1384 Reality Simulation Systems Inc
1385 Netgear
+# Note: This lists as Atheros Communications, Inc. AR5212 802.11abg NIC because of Madwifi
+ 0013 WG311T
4100 802.11b Wireless Adapter (MA301)
4105 MA311 802.11b wireless adapter
- 4a00 WAG311 802.11abg Wireless Adapter
+ 4400 WAG511 802.11a/b/g Dual Band Wireless PC Card
+ 4600 WAG511 802.11a/b/g Dual Band Wireless PC Card
+ 4601 WAG511 802.11a/b/g Dual Band Wireless PC Card
+ 4610 WAG511 802.11a/b/g Dual Band Wireless PC Card
+ 4a00 WAG311 802.11a/g Wireless PCI Adapter
+ 4c00 WG311v2 54 Mbps Wireless PCI Adapter
620a GA620 Gigabit Ethernet
622a GA622
630a GA630 Gigabit Ethernet
@@ -5853,10 +6460,10 @@
0030 SyncLink Multiport Adapter
0210 SyncLink Adapter v2
13c1 3ware Inc
- 1000 3ware ATA-RAID
- 1001 3ware 7000-series ATA-RAID
+ 1000 3ware Inc 3ware 5xxx/6xxx-series PATA-RAID
+ 1001 3ware Inc 3ware 7xxx/8xxx-series PATA/SATA-RAID
13c1 1001 3ware Inc 3ware 7xxx/8xxx-series PATA/SATA-RAID
- 1002 3ware ATA-RAID
+ 1002 3ware Inc 3ware 9xxx-series SATA-RAID
13c2 Technotrend Systemtechnik GmbH
13c3 Janz Computer AG
13c4 Phase Metrics
@@ -5944,6 +6551,7 @@
13fc Computer Peripherals International
13fd Micro Science Inc
13fe Advantech Co. Ltd
+ 1240 PCI-1240 4-channel stepper motor controller card
1600 PCI-1612 4-port RS-232/422/485 PCI Communication Card
1752 PCI-1752
1754 PCI-1754
@@ -5998,6 +6606,7 @@
1415 Oxford Semiconductor Ltd
8403 VScom 011H-EP1 1 port parallel adaptor
9501 OX16PCI954 (Quad 16950 UART) function 0
+ 131f 2050 CyberPro (4-port)
15ed 2000 MCCR Serial p0-3 of 8
15ed 2001 MCCR Serial p0-3 of 16
950a EXSYS EX-41092 Dual 16950 Serial adapter
@@ -6022,7 +6631,7 @@
1422 Ygrec Systems Co Ltd
1423 Custom Technology Corp.
1424 Videoserver Connections
-1425 ASIC Designers Inc
+1425 Chelsio Communications Inc
1426 Storage Technology Corp.
1427 Better On-Line Solutions
1428 Edec Co Ltd
@@ -6067,6 +6676,7 @@
7434 PCI-7434
7841 PCI-7841
8133 PCI-8133
+ 8164 PCI-8164
8554 PCI-8554
9111 PCI-9111
9113 PCI-9113
@@ -6156,6 +6766,7 @@
1496 JOYTECH Computer Co., Ltd.
1497 SMA Regelsysteme GmBH
1498 TEWS Datentechnik GmBH
+ 30c8 TPCI200
1499 EMTEC CO., Ltd
149a ANDOR Technology Ltd
149b SEIKO Instruments Inc
@@ -6208,6 +6819,7 @@
4800 Cisco Aironet 340 802.11b WLAN Adapter/Aironet PC4800
a504 Cisco Aironet Wireless 802.11b
a505 Cisco Aironet CB20a 802.11a Wireless LAN Adapter
+ a506 Cisco Aironet Mini PCI b/g
14ba INTERNIX Inc.
14bb SEMTECH Corporation
14bc Globespan Semiconductor Inc.
@@ -6259,6 +6871,7 @@
# Formerly SiPackets, Inc., formerly API NetWorks, Inc., formerly Alpha Processor, Inc.
14d9 Alliance Semiconductor Corporation
0010 AP1011/SP1011 HyperTransport-PCI Bridge [Sturgeon]
+ 9000 AS90L10204/10208 HyperTransport to PCI-X Bridge
14da National Aerospace Laboratories
14db AFAVLAB Technology Inc
2120 TK9902
@@ -6353,17 +6966,27 @@
10b7 2000 3C998-T Dual Port 10/100/1000 PCI-X
10b7 3000 3C999-T Quad Port 10/100/1000 PCI-X
1166 1648 NetXtreme CIOB-E 1000Base-T
+ 164a NetXtreme II BCM5706 Gigabit Ethernet
164d NetXtreme BCM5702FE Gigabit Ethernet
1653 NetXtreme BCM5705 Gigabit Ethernet
+ 0e11 00e3 NC7761 Gigabit Server Adapter
1654 NetXtreme BCM5705_2 Gigabit Ethernet
+ 0e11 00e3 NC7761 Gigabit Server Adapter
+ 103c 3100 NC1020 HP ProLiant Gigabit Server Adapter 32 PCI
1659 NetXtreme BCM5721 Gigabit Ethernet PCI Express
165d NetXtreme BCM5705M Gigabit Ethernet
165e NetXtreme BCM5705M_2 Gigabit Ethernet
+ 103c 0890 NC6000 laptop
+ 166e 570x 10/100 Integrated Controller
1677 NetXtreme BCM5751 Gigabit Ethernet PCI Express
+ 1028 0179 Optiplex GX280
+ 167d NetXtreme BCM5751M Gigabit Ethernet PCI Express
+ 167e NetXtreme BCM5751F Fast Ethernet PCI Express
1696 NetXtreme BCM5782 Gigabit Ethernet
103c 12bc HP d530 CMT (DG746A)
14e4 000d NetXtreme BCM5782 1000Base-T
169c NetXtreme BCM5788 Gigabit Ethernet
+ 169d NetLink BCM5789 Gigabit Ethernet PCI Express
16a6 NetXtreme BCM5702X Gigabit Ethernet
0e11 00bb NC7760 Gigabit Server Adapter (PCI-X, 10/100/1000-T)
1028 0126 BCM5702 1000Base-T
@@ -6378,30 +7001,58 @@
14e4 800a NetXtreme BCM5703 1000Base-T
16a8 NetXtreme BCM5704S Gigabit Ethernet
10b7 2001 3C998-SX Dual Port 1000-SX PCI-X
+ 16aa NetXtreme II BCM5706S Gigabit Ethernet
16c6 NetXtreme BCM5702A3 Gigabit Ethernet
10b7 1100 3C1000B-T 10/100/1000 PCI
14e4 000c BCM5702 1000Base-T
14e4 8009 BCM5702 1000Base-T
16c7 NetXtreme BCM5703 Gigabit Ethernet
+ 0e11 00ca NC7771 Gigabit Server Adapter (PCI-X, 10,100,1000-T)
+ 0e11 00cb NC7781 Gigabit Server Adapter (PCI-X, 10,100,1000-T)
103c 12c3 HP Combo FC/GigE-SX [A9782A]
103c 12ca HP Combo FC/GigE-T [A9784A]
14e4 0009 NetXtreme BCM5703 1000Base-T
14e4 000a NetXtreme BCM5703 1000Base-SX
+ 16dd NetLink BCM5781 Gigabit Ethernet PCI Express
+ 16f7 NetXtreme BCM5753 Gigabit Ethernet PCI Express
+ 16fd NetXtreme BCM5753M Gigabit Ethernet PCI Express
+ 16fe NetXtreme BCM5753F Fast Ethernet PCI Express
170c BCM4401-B0 100Base-TX
170d NetXtreme BCM5901 100Base-TX
+ 1014 0545 ThinkPad R40e (2684-HVG) builtin ethernet controller
170e NetXtreme BCM5901 100Base-TX
3352 BCM3352
3360 BCM3360
4210 BCM4210 iLine10 HomePNA 2.0
4211 BCM4211 iLine10 HomePNA 2.0 + V.90 56k modem
4212 BCM4212 v.90 56k modem
- 4301 BCM4301 802.11b
+ 4301 BCM4303 802.11b Wireless LAN Controller
+ 1028 0407 TrueMobile 1180 Onboard WLAN
+ 1043 0120 WL-103b Wireless LAN PC Card
+ 4305 BCM4307 V.90 56k Modem
+ 4306 BCM4307 Ethernet Controller
4307 BCM4307 802.11b Wireless LAN Controller
+ 4310 BCM4310 Chipcommon I/OController
+ 4312 BCM4310 UART
+ 4313 BCM4310 Ethernet Controller
+ 4315 BCM4310 USB Controller
4320 BCM4306 802.11b/g Wireless LAN Controller
1028 0001 TrueMobile 1300 WLAN Mini-PCI Card
+ 1028 0003 Wireless 1350 WLAN Mini-PCI Card
+ 1043 100f WL-100G
+ 14e4 4320 Linksys WMP54G PCI
1737 4320 WPC54G
+ 1799 7010 Belkin F5D7010 54g Wireless Network card
+ 4321 BCM4306 802.11a Wireless LAN Controller
+ 4322 BCM4306 UART
4324 BCM4309 802.11a/b/g
1028 0001 Truemobile 1400
+ 1028 0003 Truemobile 1450 MiniPCI
+ 4325 BCM43xG 802.11b/g
+ 1414 0003 Wireless Notebook Adapter MN-720
+ 1414 0004 Wireless PCI Adapter MN-730
+# probably this is a correct ID...
+ 4326 BCM4307 Chipcommon I/O Controller?
4401 BCM4401 100Base-T
1043 80a8 A7V8X motherboard
4402 BCM4402 Integrated 10/100BaseT
@@ -6418,16 +7069,20 @@
4614 BCM4610 Sentry5 External Interface
4615 BCM4610 Sentry5 USB Controller
4704 BCM4704 PCI to SB Bridge
- 4708 BCM4708 Sentry5 PCI to SB Bridge
+ 4705 BCM4704 Sentry5 802.11b Wireless LAN Controller
+ 4706 BCM4704 Sentry5 Ethernet Controller
+ 4707 BCM4704 Sentry5 USB Controller
+ 4708 BCM4704 Crypto Accelerator
4710 BCM4710 Sentry5 PCI to SB Bridge
4711 BCM47xx Sentry5 iLine32 HomePNA 2.0
- 4712 Sentry5 UART
+ 4712 BCM47xx V.92 56k modem
4713 Sentry5 Ethernet Controller
4714 BCM47xx Sentry5 External Interface
4715 Sentry5 USB Controller
4716 BCM47xx Sentry5 USB Host Controller
4717 BCM47xx Sentry5 USB Device Controller
4718 Sentry5 Crypto Accelerator
+ 4720 BCM4712 MIPS CPU
5365 BCM5365P Sentry5 Host Bridge
5600 BCM5600 StrataSwitch 24+2 Ethernet Switch Controller
5605 BCM5605 StrataSwitch 24+2 Ethernet Switch Controller
@@ -6595,6 +7250,8 @@
13e0 8d84 IBM HSFi V.90
13e0 8d85 Compaq Stinger
14f1 2004 Dynalink 56PMi
+ 2f02 HSF 56k HSFi Data/Fax
+ 2f11 HSF 56k HSFi Modem
8234 RS8234 ATM SAR Controller [ServiceSAR Plus]
8800 Winfast TV2000 XP
14f2 MOBILITY Electronics
@@ -6603,12 +7260,16 @@
0122 EV1000 Serial port
0123 EV1000 Keyboard controller
0124 EV1000 Mouse controller
-14f3 BROADLOGIC
+14f3 BroadLogic
+ 2030 2030 DVB-S Satellite Reciever
+ 2050 2050 DVB-T Terrestrial (Cable) Reciever
+ 2060 2060 ATSC Terrestrial (Cable) Reciever
14f4 TOKYO Electronic Industry CO Ltd
14f5 SOPAC Ltd
14f6 COYOTE Technologies LLC
14f7 WOLF Technology Inc
14f8 AUDIOCODES Inc
+ 2077 TP-240 dual span E1 VoIP PCI card
14f9 AG COMMUNICATIONS
14fa WANDEL & GOCHERMANN
14fb TRANSAS MARINE (UK) Ltd
@@ -6687,12 +7348,16 @@
1523 MUSIC Semiconductors
1524 ENE Technology Inc
0510 CB710 Memory Card Reader Controller
+ 0610 PCI Smart Card Reader Controller
1211 CB1211 Cardbus Controller
1225 CB1225 Cardbus Controller
1410 CB1410 Cardbus Controller
- 1411 CB710 Cardbus Controller
+ 1025 005a TravelMate 290
+ 1411 CB-710/2/4 Cardbus Controller
+ 1412 CB-712/4 Cardbus Controller
1420 CB1420 Cardbus Controller
- 1421 CB720 Cardbus Controller
+ 1421 CB-720/2/4 Cardbus Controller
+ 1422 CB-722/4 Cardbus Controller
1525 IMPACT Technologies
1526 ISS, Inc
1527 SOLECTRON
@@ -6717,6 +7382,9 @@
153a ONO SOKKI
153b TERRATEC Electronic GmbH
1144 Aureon 5.1
+# Terratec seems to use several IDs for the same card.
+ 1147 Aureon 5.1 Sky
+ 1158 Philips Semiconductors SAA7134 (rev 01) [Terratec Cinergy 600 TV]
153c ANTAL Electronic
153d FILANET Corp
153e TECHWELL Inc
@@ -6859,18 +7527,24 @@
15aa Moreton Bay
15ab Bluesteel Networks Inc
15ac North Atlantic Instruments
-15ad VMWare Inc
- 0405 [VMWare SVGA II] PCI Display Adapter
+15ad VMware Inc
+ 0405 [VMware SVGA II] PCI Display Adapter
0710 Virtual SVGA
+ 0720 VMware High-Speed Virtual NIC [vmxnet]
15ae Amersham Pharmacia Biotech
15b0 Zoltrix International Ltd
15b1 Source Technology Inc
15b2 Mosaid Technologies Inc
-15b3 Mellanox Technology
+15b3 Mellanox Technologies
5274 MT21108 InfiniBridge
5a44 MT23108 InfiniHost
- 5a45 MT23108 InfiniHost (Tavor)
+ 5a45 MT23108 [Infinihost HCA Flash Recovery]
5a46 MT23108 PCI Bridge
+ 5e8c MT24204 [InfiniHost III Lx HCA]
+ 5e8d MT24204 [InfiniHost III Lx HCA Flash Recovery]
+ 6278 MT25208 InfiniHost III Ex (Tavor compatibility mode)
+ 6279 MT25208 [InfiniHost III Ex HCA Flash Recovery]
+ 6282 MT25208 InfiniHost III Ex
15b4 CCI/TRIAD
15b5 Cimetrics Inc
15b6 Texas Memory Systems Inc
@@ -6981,7 +7655,7 @@
1637 Linksys
3874 Linksys 802.11b WMP11 PCI Wireless card
1638 Standard Microsystems Corp [SMC]
- 1100 SMC2602W EZConnect/Addtron AWA-100/Eumitcom WL11000
+ 1100 SMC2602W EZConnect/Addtron AWA-100/Eumitcom PCI WL11000
163c Smart Link Ltd.
3052 SmartLink SmartPCI562 56K Modem
5449 SmartPCI561 Modem
@@ -6998,6 +7672,10 @@
166d Broadcom Corporation
0001 SiByte BCM1125/1125H/1250 System-on-a-Chip PCI
0002 SiByte BCM1125H/1250 System-on-a-Chip HyperTransport
+1677 Bernecker + Rainer
+ 104e 5LS172.6 B&R Dual CAN Interface Card
+ 12d7 5LS172.61 B&R Dual CAN Interface Card
+167b ZyDAS Technology Corp.
1681 Hercules
# More specs, more accurate desc.
0010 Hercules 3d Prophet II Ultra 64MB [ 350 MHz NV15BR core, 128-bit DDR @ 460 MHz, 1.5v AGP4x ]
@@ -7010,9 +7688,13 @@
0013 AR5212 802.11abg NIC
1186 3202 D-link DWL-G650 B3 Wireless cardbus adapter
1186 3203 DWL-G520 Wireless PCI Adapter
+ 1186 3a13 DWL-G520 Wireless PCI Adapter rev. B
1186 3a94 C54C Wireless 801.11g cardbus
+ 1385 4d00 Netgear WG311T Wireless PCI Adapter
+ 14b7 0a60 8482-WD ORiNOCO 11a/b/g Wireless PCI Adapter
168c 0013 WG511T Wireless CardBus Adapter
168c 1025 DWL-G650B2 Wireless CardBus Adapter
+ 168c 2026 Netgate 5354MP ARIES a(108Mb turbo)/b/g MiniPCI Adapter
1014 AR5212 802.11abg NIC
16a5 Tekram Technology Co.,Ltd.
16ab Global Sun Technology Inc
@@ -7021,10 +7703,12 @@
1102 PCMCIA-to-PCI Wireless Network Bridge
16ae Safenet Inc
1141 SafeXcel-1141
+16b4 Aspex Semiconductor Ltd
16be Creatix Polymedia GmbH
16ca CENATEK Inc
0001 Rocket Drive DL
16cd Densitron Technologies
+16ce Roland Corp.
# www.pikatechnologies.com
16df PIKA Technologies Inc.
16e3 European Space Agency
@@ -7032,6 +7716,9 @@
16ec U.S. Robotics
00ff USR997900 10/100 Mbps PCI Network Card
3685 Wireless Access PCI Adapter Model 022415
+16ed Sycron N. V.
+ 1001 UMIO communication card
+16f3 Jetway Information Co., Ltd.
16f4 Vweb Corp
8000 VW2010
16f6 VideoTele.com, Inc.
@@ -7045,8 +7732,10 @@
1725 Vitesse Semiconductor
7174 VSC7174 PCI/PCI-X Serial ATA Host Bus Controller
172a Accelerated Encryption
+1734 Fujitsu Siemens Computer GmbH
1737 Linksys
0013 WMP54G Wireless Pci Card
+ 0015 WMP54GS Wireless Pci Card
1032 Gigabit Network Adapter
1737 0015 EG1032 v2 Instant Gigabit Network Adapter
1064 Gigabit Network Adapter
@@ -7081,6 +7770,9 @@
6020 Wireless PCMCIA Card - F5D6020
6060 Wireless PDA Card - F5D6060
7000 Wireless PCI Card - F5D7000
+17a0 Genesys Logic, Inc
+ 8033 GL880S USB 1.1 controller
+ 8034 GL880S USB 2.0 controller
17af Hightech Information System Ltd.
17b3 Hawking Technologies
ab08 PN672TX 10/100 Ethernet
@@ -7090,9 +7782,12 @@
17c2 Newisys, Inc.
17cc NetChip Technology, Inc
2280 USB 2.0
+17d3 Areca Technology Corp.
# S2io ships 10Gb PCI-X Ethernet adapters www.s2io.com
17d5 S2io Inc.
-# Supplying full name for a currently green entry
+17de KWorld Computer Co. Ltd.
+# http://www.connect3d.com
+17ee Connect Components Ltd
17fe Linksys, A Division of Cisco Systems
2220 [AirConn] INPROCOMM IPN 2220 WLAN Adapter (rev 01)
1813 Ambient Technologies Inc
@@ -7103,15 +7798,30 @@
1814 RaLink
0101 Wireless PCI Adpator RT2400 / RT2460
0201 Ralink RT2500 802.11 Cardbus Reference Card
+ 1371 001e CWC-854 Wireless-G CardBus Adapter
+ 1371 001f CWM-854 Wireless-G Mini PCI Adapter
+ 1371 0020 CWP-854 Wireless-G PCI Adapter
1820 InfiniCon Systems Inc.
1822 Twinhan Technology Co. Ltd
+182d SiteCom Europe BV
+# HFC-based ISDN card
+ 3069 ISDN PCI DC-105V2
1830 Credence Systems Corporation
+183b MikroM GmbH
+ 08a7 MVC100 DVI
+ 08a8 MVC101 SDI
+ 08a9 MVC102 DVI+Audio
+1849 ASRock Incorporation
1851 Microtune, Inc.
1852 Anritsu Corp.
+185f Wistron NeWeb Corp.
1867 Topspin Communications
5a44 MT23108 PCI-X HCA
5a45 MT23108 PCI-X HCA flash recovery
5a46 MT23108 PCI-X HCA bridge
+ 6278 MT25208 InfiniHost III Ex (Tavor compatibility mode)
+ 6282 MT25208 InfiniHost III Ex
+187e ZyXEL Communication Corporation
1888 Varisys Ltd
0301 VMFX1 FPGA PMC module
0601 VSM2 dual PMC carrier
@@ -7119,14 +7829,30 @@
0720 VS24x series PowerPC PCI board
# found e.g. on KNC DVB-S card
1894 KNC One
+1896 B&B Electronics Manufacturing Company, Inc.
18a1 Astute Networks Inc.
+18ac DViCO Corporation
+ d810 FusionHDTV 3 Gold
+18b8 Ammasso
18bc Info-Tek Corp.
+# assigned to Octigabay System, which has been acquired by Cray
+18c8 Cray Inc
18c9 ARVOO Engineering BV
18ca XGI - Xabre Graphics Inc
0040 Volari V8
18e6 MPL AG
0001 OSCI [Octal Serial Communication Interface]
+18f7 Commtech, Inc.
+ 0001 Fastcom ESCC-PCI-335
+ 0002 Fastcom 422/4-PCI-335
+ 0004 Fastcom 422/2-PCI-335
+ 0005 Fastcom IGESCC-PCI-ISO/1
+ 000a Fastcom 232/4-PCI-335
18fb Resilience Corporation
+1924 Level 5 Networks Inc.
+1966 Orad Hi-Tec Systems
+1975 Pudlis Co. Ltd.
+1993 Innominate Security Technologies AG
1a08 Sierra semiconductor
0000 SC15064
1b13 Jaton Corp
@@ -7165,6 +7891,7 @@
4c53 10a0 CA3/CR3 mainboard
4c53 3010 PPCI mezzanine (32-bit PMC)
4c53 3011 PPCI mezzanine (64-bit PMC)
+ 0022 HiNT HB4 PCI-PCI Bridge (PCI6150)
0026 HB2 PCI-PCI Bridge
101a E.Band [AudioTrak Inca88]
101b E.Band [AudioTrak Inca88]
@@ -7176,6 +7903,7 @@
3388 8013 VXPro II Chipset EIDE Controller
3411 Quantum Designs (H.K.) Inc
3513 ARCOM Control Systems Ltd
+3842 eVga.com. Corp.
38ef 4Links
3d3d 3DLabs
0001 GLINT 300SX
@@ -7211,6 +7939,7 @@
0024 VP9 visual processor
0100 Permedia II 2D+3D
07a1 Wildcat III 6210
+ 07a2 Sun XVR-500 Graphics Accelerator
07a3 Wildcat IV 7210
1004 Permedia
3d04 Permedia
@@ -7252,6 +7981,8 @@
4916 RedCreek Communications Inc
1960 RedCreek PCI adapter
4943 Growth Networks
+494f ACCES I/O Products, Inc.
+ 10e8 LPCI-COM-8SM
4978 Axil Computer Inc
4a14 NetVin
5000 NV5000SC
@@ -7366,6 +8097,7 @@
8a22 Savage 4
1033 8068 Savage 4
1033 8069 Savage 4
+ 1033 8110 Savage4 LT
105d 0018 SR9 8Mb SDRAM
105d 002a SR9 Pro 16Mb SDRAM
105d 003a SR9 Pro 32Mb SDRAM
@@ -7458,7 +8190,7 @@
0011 PWDOG2 [PCI-Watchdog 2]
# Wrong ID used in subsystem ID of AsusTek PCI-USB2 PCI card.
807d Asustek Computer, Inc.
-8086 Intel Corp.
+8086 Intel Corporation
0007 82379AB
0008 Extended Express System Support Controller
0008 1000 WorldMark 4300 INCA ASIC
@@ -7466,11 +8198,11 @@
0122 82437FX
0309 80303 I/O Processor PCI-to-PCI Bridge
030d 80312 I/O Companion Chip PCI-to-PCI Bridge
- 0326 PCI Bridge Hub I/OxAPIC Interrupt Controller A
- 0327 PCI Bridge Hub I/OxAPIC Interrupt Controller B
- 0329 PCI Bridge Hub A
- 032a PCI Bridge Hub B
- 032c PCI Bridge Hub
+ 0326 6700/6702PXH I/OxAPIC Interrupt Controller A
+ 0327 6700PXH I/OxAPIC Interrupt Controller B
+ 0329 6700PXH PCI Express-to-PCI Bridge A
+ 032a 6700PXH PCI Express-to-PCI Bridge B
+ 032c 6702PXH PCI Express-to-PCI Bridge A
# A-segment bridge
0330 80332 [Dobson] I/O processor
# A-segment IOAPIC
@@ -7521,6 +8253,8 @@
0600 RAID Controller
8086 01c1 ICP Vortex GDT8546RZ
8086 01f7 SCRU32
+# uninitialized SRCU32 RAID Controller
+ 061f 80303 I/O Processor
0960 80960RP [i960 RP Microprocessor/Bridge]
0962 80960RM [i960RM Bridge]
0964 80960RP [i960 RP Microprocessor/Bridge]
@@ -7533,6 +8267,7 @@
1001 82543GC Gigabit Ethernet Controller (Fiber)
0e11 004a NC6136 Gigabit Server Adapter
1014 01ea Netfinity Gigabit Ethernet SX Adapter
+ 8086 1002 PRO/1000 F Server Adapter
8086 1003 PRO/1000 F Server Adapter
1002 Pro 100 LAN+Modem 56 Cardbus II
8086 200e Pro 100 LAN+Modem 56 Cardbus II
@@ -7567,6 +8302,8 @@
1014 0265 PRO/1000 MT Network Connection
1014 0267 PRO/1000 MT Network Connection
1014 026a PRO/1000 MT Network Connection
+ 1028 002e Optiplex GX260
+ 1028 0151 PRO/1000 MT Network Connection
107b 8920 PRO/1000 MT Desktop Adapter
8086 001e PRO/1000 MT Desktop Adapter
8086 002e PRO/1000 MT Desktop Adapter
@@ -7582,6 +8319,7 @@
4c53 10a0 CA3/CR3 mainboard
8086 1011 PRO/1000 MT Dual Port Server Adapter
8086 101a PRO/1000 MT Dual Port Network Adapter
+ 8086 3424 SE7501HG2 Mainboard
1011 82545EM Gigabit Ethernet Controller (Fiber)
1014 0268 iSeries Gigabit Ethernet Adapter
8086 1002 PRO/1000 MF Server Adapter
@@ -7590,6 +8328,7 @@
8086 1012 PRO/1000 MF Dual Port Server Adapter
1013 82541EI Gigabit Ethernet Controller (Copper)
8086 0013 PRO/1000 MT Network Connection
+ 8086 1013 IBM ThinkCentre Network Card
8086 1113 PRO/1000 MT Desktop Adapter
1014 82541ER Gigabit Ethernet Controller
1015 82540EM Gigabit Ethernet Controller (LOM)
@@ -7605,6 +8344,7 @@
1019 82547EI Gigabit Ethernet Controller (LOM)
1458 1019 GA-8IPE1000 Pro2 motherboard (865PE)
8086 1019 PRO/1000 CT Desktop Connection
+ 8086 301f D865PERL mainboard
8086 3427 S875WP1-E mainboard
101d 82546EB Gigabit Ethernet Controller
8086 1000 PRO/1000 MT Quad Port Server Adapter
@@ -7642,13 +8382,13 @@
1036 82801CAM (ICH3) 82562EH Ethernet Controller
1037 82801CAM (ICH3) Chipset Ethernet Controller
1038 82801CAM (ICH3) PRO/100 VM (KM) Ethernet Controller
- 1039 82801BD PRO/100 VE (LOM) Ethernet Controller
+ 1039 82801DB PRO/100 VE (LOM) Ethernet Controller
1014 0267 NetVista A30p
- 103a 82801BD PRO/100 VE (CNR) Ethernet Controller
- 103b 82801BD PRO/100 VM (LOM) Ethernet Controller
- 103c 82801BD PRO/100 VM (CNR) Ethernet Controller
- 103d 82801BD PRO/100 VE (MOB) Ethernet Controller
- 103e 82801BD PRO/100 VM (MOB) Ethernet Controller
+ 103a 82801DB PRO/100 VE (CNR) Ethernet Controller
+ 103b 82801DB PRO/100 VM (LOM) Ethernet Controller
+ 103c 82801DB PRO/100 VM (CNR) Ethernet Controller
+ 103d 82801DB PRO/100 VE (MOB) Ethernet Controller
+ 103e 82801DB PRO/100 VM (MOB) Ethernet Controller
1040 536EP Data Fax Modem
16be 1040 V.9X DSP Data Fax Modem
1043 PRO/Wireless LAN 2100 3B Mini PCI Adapter
@@ -7662,42 +8402,55 @@
8086 3427 S875WP1-E mainboard
1051 82801EB/ER (ICH5/ICH5R) integrated LAN Controller
1059 82551QM Ethernet Controller
- 1065 82801FB/FBM/FR/FW/FRW (ICH6 Family) LAN Controller
-# Updated controller name from 82547EI to 82547GI
+# ICH-6 Component
+ 1064 82562ET/EZ/GT/GZ - PRO/100 VE (LOM) Ethernet Controller
+# ICH-6 Component
+ 1065 82562ET/EZ/GT/GZ - PRO/100 VE Ethernet Controller
+# ICH-6 Component
+ 1066 82562 EM/EX/GX - PRO/100 VM (LOM) Ethernet Controller
+# ICH-6 Component
+ 1067 82562 EM/EX/GX - PRO/100 VM Ethernet Controller
+# ICH-6 Component
+ 1068 82562ET/EZ/GT/GZ - PRO/100 VE (LOM) Ethernet Controller Mobile
+# ICH-6 Component
+ 1069 82562 EM/EX/GX - PRO/100 VM (LOM) Ethernet Controller Mobile
+# ICH-6 Component
+ 106a 82562G \t- PRO/100 VE (LOM) Ethernet Controller
+# ICH-6 Component
+ 106b 82562G \t- PRO/100 VE Ethernet Controller Mobile
1075 82547GI Gigabit Ethernet Controller
+ 1028 0165 PowerEdge 750
8086 0075 PRO/1000 CT Network Connection
8086 1075 PRO/1000 CT Network Connection
-# Added PI to part name. Previous part name was 82541GI
1076 82541GI/PI Gigabit Ethernet Controller
+ 1028 0165 PowerEdge 750
8086 0076 PRO/1000 MT Network Connection
8086 1076 PRO/1000 MT Network Connection
8086 1176 PRO/1000 MT Desktop Adapter
8086 1276 PRO/1000 MT Desktop Adapter
-# Update controller name from 82541EI to 82541GI
1077 82541GI Gigabit Ethernet Controller
1179 0001 PRO/1000 MT Mobile Connection
8086 0077 PRO/1000 MT Mobile Connection
8086 1077 PRO/1000 MT Mobile Connection
1078 82541EI Gigabit Ethernet Controller
8086 1078 PRO/1000 MT Network Connection
-# Update from mistaken ID of 82546EB
1079 82546GB Gigabit Ethernet Controller
103c 12a6 HP Dual Port 1000Base-T [A9900A]
103c 12cf HP Core Dual Port 1000Base-T [AB352A]
4c53 1090 Cx9 / Vx9 mainboard
+ 4c53 10b0 CL9 mainboard
8086 0079 PRO/1000 MT Dual Port Network Connection
8086 1079 PRO/1000 MT Dual Port Network Connection
8086 1179 PRO/1000 MT Dual Port Network Connection
8086 117a PRO/1000 MT Dual Port Server Adapter
-# Update from mistaken ID of 82546EB
107a 82546GB Gigabit Ethernet Controller
103c 12a8 HP Dual Port 1000base-SX [A9899A]
8086 107a PRO/1000 MF Dual Port Server Adapter
8086 127a PRO/1000 MF Dual Port Server Adapter
-# Update from mistaken ID of 82546EB
107b 82546GB Gigabit Ethernet Controller
8086 007b PRO/1000 MB Dual Port Server Connection
8086 107b PRO/1000 MB Dual Port Server Connection
+ 1107 PRO/1000 MF Server Adapter (LX)
1130 82815 815 Chipset Host Bridge and Memory Controller Hub
1025 1016 Travelmate 612 TX
1043 8027 TUSL2-C Mainboard
@@ -7715,7 +8468,7 @@
1162 Xscale 80200 Big Endian Companion Chip
1200 Intel IXP1200 Network Processor
172a 0000 AEP SSL Accelerator
- 1209 82559ER
+ 1209 8255xER/82551IT Fast Ethernet Controller
4c53 1050 CT7 mainboard
4c53 1051 CE7 mainboard
4c53 1070 PC6 mainboard
@@ -7766,7 +8519,7 @@
1014 605c 10/100 EtherJet Secure Management Adapter
1014 705c 10/100 Netfinity 10/100 Ethernet Security Adapter
1014 805c 10/100 Netfinity 10/100 Ethernet Security Adapter
- 1028 009b PowerEdge 2550
+ 1028 009b PowerEdge 2500/2550
1028 00ce PowerEdge 1400
1033 8000 PC-9821X-B06
1033 8016 PK-UG-X006
@@ -7937,6 +8690,7 @@
1a23 82840 840 (Carmel) Chipset AGP Bridge
1a24 82840 840 (Carmel) Chipset PCI Bridge (Hub B)
1a30 82845 845 (Brookdale) Chipset Host Bridge
+ 1028 010e Optiplex GX240
1a31 82845 845 (Brookdale) Chipset AGP Bridge
2410 82801AA ISA Bridge (LPC)
2411 82801AA IDE
@@ -7962,6 +8716,8 @@
2442 82801BA/BAM USB (Hub #1)
1014 01c6 Netvista A40/A40p
1025 1016 Travelmate 612 TX
+ 1028 010e Optiplex GX240
+ 1043 8027 TUSL2-C Mainboard
104d 80df Vaio PCG-FX403
147b 0507 TH7II-RAID
8086 4532 D815EEA2 mainboard
@@ -7969,6 +8725,7 @@
2443 82801BA/BAM SMBus
1014 01c6 Netvista A40/A40p
1025 1016 Travelmate 612 TX
+ 1028 010e Optiplex GX240
1043 8027 TUSL2-C Mainboard
104d 80df Vaio PCG-FX403
147b 0507 TH7II-RAID
@@ -7976,6 +8733,8 @@
8086 4557 D815EGEW Mainboard
2444 82801BA/BAM USB (Hub #2)
1025 1016 Travelmate 612 TX
+ 1028 010e Optiplex GX240
+ 1043 8027 TUSL2-C Mainboard
104d 80df Vaio PCG-FX403
147b 0507 TH7II-RAID
8086 4532 D815EEA2 mainboard
@@ -8026,6 +8785,7 @@
104d 80df Vaio PCG-FX403
244b 82801BA IDE U100
1014 01c6 Netvista A40/A40p
+ 1028 010e Optiplex GX240
1043 8027 TUSL2-C Mainboard
147b 0507 TH7II-RAID
8086 4532 D815EEA2 mainboard
@@ -8046,6 +8806,7 @@
104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP
15d9 3480 P4DP6
8086 1958 vpr Matrix 170B4
+ 8086 3424 SE7501HG2 Mainboard
8086 4541 Latitude C640
2483 82801CA/CAM SMBus Controller
1014 0220 ThinkPad A/T/X Series
@@ -8058,6 +8819,7 @@
15d9 3480 P4DP6
8086 1958 vpr Matrix 170B4
2485 82801CA/CAM AC'97 Audio Controller
+ 1013 5959 Crystal WMD Audio Codec
1014 0222 ThinkPad T23 (2647-4MG) or A30/A30p (2652/2653)
1014 0508 ThinkPad T30
1014 051c ThinkPad A/T/X Series
@@ -8086,76 +8848,117 @@
248b 82801CA Ultra ATA Storage Controller
15d9 3480 P4DP6
248c 82801CAM ISA Bridge (LPC)
- 24c0 82801DB/DBL (ICH4/ICH4-L) LPC Bridge
+ 24c0 82801DB/DBL (ICH4/ICH4-L) LPC Interface Bridge
1014 0267 NetVista A30p
1462 5800 845PE Max (MS-6580)
24c1 82801DBL (ICH4-L) IDE Controller
24c2 82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #1
1014 0267 NetVista A30p
+ 1025 005a TravelMate 290
+ 1028 0126 Optiplex GX260
+ 1028 0163 Latitude D505
+ 103c 0890 NC6000 laptop
1071 8160 MIM2000
1462 5800 845PE Max (MS-6580)
+ 1509 2990 Averatec 5110H laptop
+ 4c53 1090 Cx9 / Vx9 mainboard
24c3 82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) SMBus Controller
1014 0267 NetVista A30p
+ 1025 005a TravelMate 290
+ 1028 0126 Optiplex GX260
+ 103c 0890 NC6000 laptop
1071 8160 MIM2000
1458 24c2 GA-8PE667 Ultra
1462 5800 845PE Max (MS-6580)
4c53 1090 Cx9 / Vx9 mainboard
24c4 82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #2
1014 0267 NetVista A30p
+ 1025 005a TravelMate 290
+ 1028 0126 Optiplex GX260
+ 1028 0163 Latitude D505
+ 103c 0890 NC6000 laptop
1071 8160 MIM2000
1462 5800 845PE Max (MS-6580)
+ 1509 2990 Averatec 5110H
4c53 1090 Cx9 / Vx9 mainboard
24c5 82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller
0e11 00b8 Analog Devices Inc. codec [SoundMAX]
1014 0267 NetVista A30p
+ 1025 005a TravelMate 290
+ 1028 0163 Latitude D505
+ 103c 0890 NC6000 laptop
1071 8160 MIM2000
1458 a002 GA-8PE667 Ultra
1462 5800 845PE Max (MS-6580)
24c6 82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Modem Controller
+ 1025 005a TravelMate 290
+ 103c 0890 NC6000 laptop
1071 8160 MIM2000
24c7 82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #3
1014 0267 NetVista A30p
+ 1025 005a TravelMate 290
+ 1028 0126 Optiplex GX260
+ 1028 0163 Latitude D505
+ 103c 0890 NC6000 laptop
1071 8160 MIM2000
1462 5800 845PE Max (MS-6580)
+ 1509 2990 Averatec 5110H
+ 4c53 1090 Cx9 / Vx9 mainboard
24ca 82801DBM (ICH4) Ultra ATA Storage Controller
+ 1025 005a TravelMate 290
+ 1028 0163 Latitude D505
+ 103c 0890 NC6000 laptop
1071 8160 MIM2000
24cb 82801DB/DBL (ICH4/ICH4-L) UltraATA-100 IDE Controller
1014 0267 NetVista A30p
+ 1028 0126 Optiplex GX260
1458 24c2 GA-8PE667 Ultra
1462 5800 845PE Max (MS-6580)
4c53 1090 Cx9 / Vx9 mainboard
24cc 82801DBM LPC Interface Controller
24cd 82801DB/DBM (ICH4/ICH4-M) USB 2.0 EHCI Controller
1014 0267 NetVista A30p
+ 1025 005a TravelMate 290
+ 1028 0126 Optiplex GX260
+ 1028 0163 Latitude D505
+ 103c 0890 NC6000 laptop
1071 8160 MIM2000
1462 3981 845PE Max (MS-6580)
+ 1509 1968 Averatec 5110H
4c53 1090 Cx9 / Vx9 mainboard
- 24d0 82801EB/ER (ICH5/ICH5R) LPC Bridge
+ 24d0 82801EB/ER (ICH5/ICH5R) LPC Interface Bridge
24d1 82801EB (ICH5) Serial ATA 150 Storage Controller
103c 12bc d530 CMT (DG746A)
1458 24d1 GA-8IPE1000 Pro2 motherboard (865PE)
1462 7280 865PE Neo2 (MS-6728)
8086 3427 S875WP1-E mainboard
- 24d2 82801EB/ER (ICH5/ICH5R) USB UHCI #1
+ 8086 524c D865PERL mainboard
+ 24d2 82801EB/ER (ICH5/ICH5R) USB UHCI Controller #1
103c 12bc d530 CMT (DG746A)
1043 80a6 P4P800 Mainboard
+ 1458 24d2 GA-8KNXP motherboard (875P)
1462 7280 865PE Neo2 (MS-6728)
8086 3427 S875WP1-E mainboard
+ 8086 524c D865PERL mainboard
24d3 82801EB/ER (ICH5/ICH5R) SMBus Controller
1043 80a6 P4P800 Mainboard
1458 24d2 GA-8IPE1000 Pro2 motherboard (865PE)
1462 7280 865PE Neo2 (MS-6728)
8086 3427 S875WP1-E mainboard
- 24d4 82801EB/ER (ICH5/ICH5R) USB UHCI #2
+ 8086 524c D865PERL mainboard
+ 24d4 82801EB/ER (ICH5/ICH5R) USB UHCI Controller #2
103c 12bc d530 CMT (DG746A)
1043 80a6 P4P800 Mainboard
1458 24d2 GA-8IPE1000 Pro2 motherboard (865PE)
1462 7280 865PE Neo2 (MS-6728)
8086 3427 S875WP1-E mainboard
+ 8086 524c D865PERL mainboard
24d5 82801EB/ER (ICH5/ICH5R) AC'97 Audio Controller
103c 12bc Analog Devices codec [SoundMAX Integrated Digital Audio]
1043 80f3 P4P800 Mainboard
+ 1458 a002 GA-8KNXP motherboard (875P)
1462 7280 865PE Neo2 (MS-6728)
+ 8086 a000 D865PERL mainboard
24d6 82801EB/ER (ICH5/ICH5R) AC'97 Modem Controller
24d7 82801EB/ER (ICH5/ICH5R) USB UHCI #3
103c 12bc d530 CMT (DG746A)
@@ -8163,6 +8966,7 @@
1458 24d2 GA-8IPE1000 Pro2 motherboard (865PE)
1462 7280 865PE Neo2 (MS-6728)
8086 3427 S875WP1-E mainboard
+ 8086 524c D865PERL mainboard
24db 82801EB/ER (ICH5/ICH5R) Ultra ATA 100 Storage Controller
103c 12bc d530 CMT (DG746A)
1043 80a6 P4P800 Mainboard
@@ -8170,18 +8974,21 @@
1462 7280 865PE Neo2 (MS-6728)
1462 7580 MSI 875P
8086 3427 S875WP1-E mainboard
- 24dc 82801EB LPC Interface Controller
+ 8086 524c D865PERL mainboard
+ 24dc 82801EB (ICH5) LPC Interface Bridge
24dd 82801EB/ER (ICH5/ICH5R) USB2 EHCI Controller
103c 12bc d530 CMT (DG746A)
1043 80a6 P4P800 Mainboard
1458 5006 GA-8IPE1000 Pro2 motherboard (865PE)
1462 7280 865PE Neo2 (MS-6728)
8086 3427 S875WP1-E mainboard
- 24de 82801EB/ER (ICH5/ICH5R) USB UHCI #4
+ 8086 524c D865PERL mainboard
+ 24de 82801EB/ER (ICH5/ICH5R) USB UHCI Controller #4
1043 80a6 P4P800 Mainboard
1458 24d2 GA-8IPE1000 Pro2 motherboard (865PE)
1462 7280 865PE Neo2 (MS-6728)
8086 3427 S875WP1-E mainboard
+ 8086 524c D865PERL mainboard
24df 82801EB (ICH5R) SATA (cc=RAID)
2500 82820 820 (Camino) Chipset Host Bridge (MCH)
1028 0095 Precision Workstation 220 Chipset
@@ -8203,6 +9010,7 @@
2541 E7500/E7501 Host RASUM Controller
15d9 3480 P4DP6
4c53 1090 Cx9 / Vx9 mainboard
+ 8086 3424 SE7501HG2 Mainboard
2543 E7500/E7501 Hub Interface B PCI-to-PCI Bridge
2544 E7500/E7501 Hub Interface B RASUM Controller
4c53 1090 Cx9 / Vx9 mainboard
@@ -8212,6 +9020,7 @@
2548 E7500/E7501 Hub Interface D RASUM Controller
254c E7501 Memory Controller Hub
4c53 1090 Cx9 / Vx9 mainboard
+ 8086 3424 SE7501HG2 Mainboard
2550 E7505 Memory Controller Hub
2551 E7505/E7205 Series RAS Controller
2552 E7505/E7205 PCI-to-AGP Bridge
@@ -8219,6 +9028,7 @@
2554 E7505 Hub Interface B PCI-to-PCI Bridge RAS Controller
255d E7205 Memory Controller Hub
2560 82845G/GL[Brookdale-G]/GE/PE DRAM Controller/Host-Hub Interface
+ 1028 0126 Optiplex GX260
1458 2560 GA-8PE667 Ultra
1462 5800 845PE Max (MS-6580)
2561 82845G/GL[Brookdale-G]/GE/PE Host-to-AGP Bridge
@@ -8228,37 +9038,47 @@
1043 80f2 P4P800 Mainboard
1458 2570 GA-8IPE1000 Pro2 motherboard (865PE)
2571 82865G/PE/P PCI to AGP Controller
- 2572 82865G Integrated Graphics Device
+ 2572 82865G Integrated Graphics Controller
2573 82865G/PE/P PCI to CSA Bridge
2576 82865G/PE/P Processor to I/O Memory Interface
- 2578 82875P Memory Controller Hub
+ 2578 82875P/E7210 Memory Controller Hub
+ 1458 2578 GA-8KNXP motherboard (875P)
1462 7580 MS-6758 (875P Neo)
# Motherboard P4SCE
15d9 4580 Super Micro Computer Inc. P4SCE
2579 82875P Processor to AGP Controller
- 257b 82875P Processor to PCI to CSA Bridge
- 257e 82875P Processor to I/O Memory Interface
+ 257b 82875P/E7210 Processor to PCI to CSA Bridge
+ 257e 82875P/E7210 Processor to I/O Memory Interface
2580 915G/P/GV Processor to I/O Controller
2581 915G/P/GV PCI Express Root Port
- 2582 82915G Express Chipset Family Graphics Controller
- 2584 925X Memory Controller Hub
- 2585 925X PCI Express Root Port
- 2588 Server Memory Controller Hub
- 2589 Server Memory Controller Hub PCI Express Port
- 258a Graphics Controller
- 2590 Mobile Memory Controller Hub
- 2591 Mobile Memory Controller Hub PCI Express Port
- 2592 Mobile Graphics Controller
+ 2582 82915G/GV/910GL Express Chipset Family Graphics Controller
+ 1028 1079 Optiplex GX280
+ 2584 925X/XE Memory Controller Hub
+ 2585 925X/XE PCI Express Root Port
+ 2588 E7220/E7221 Memory Controller Hub
+ 2589 E7220/E7221 PCI Express Root Port
+ 258a E7221 Integrated Graphics Controller
+ 2590 Mobile 915GM/PM/GMS/910GML Express Processor to DRAM Controller
+ 2591 Mobile 915GM/PM Express PCI Express Root Port
+ 2592 Mobile 915GM/GMS/910GML Express Graphics Controller
25a1 6300ESB LPC Interface Controller
25a2 6300ESB PATA Storage Controller
+ 4c53 10b0 CL9 mainboard
25a3 6300ESB SATA Storage Controller
+ 4c53 10b0 CL9 mainboard
25a4 6300ESB SMBus Controller
+ 4c53 10b0 CL9 mainboard
25a6 6300ESB AC'97 Audio Controller
+ 4c53 10b0 CL9 mainboard
25a7 6300ESB AC'97 Modem Controller
25a9 6300ESB USB Universal Host Controller
+ 4c53 10b0 CL9 mainboard
25aa 6300ESB USB Universal Host Controller
+ 4c53 10b0 CL9 mainboard
25ab 6300ESB Watchdog Timer
+ 4c53 10b0 CL9 mainboard
25ac 6300ESB I/O Advanced Programmable Interrupt Controller
+ 4c53 10b0 CL9 mainboard
25ad 6300ESB USB2 Enhanced Host Controller
25ae 6300ESB 64-bit PCI-X Bridge
25b0 6300ESB SATA RAID Controller
@@ -8300,28 +9120,71 @@
2641 82801FBM (ICH6M) LPC Interface Bridge
2642 82801FW/FRW (ICH6W/ICH6RW) LPC Interface Bridge
2651 82801FB/FW (ICH6/ICH6W) SATA Controller
+ 1028 0179 Optiplex GX280
2652 82801FR/FRW (ICH6R/ICH6RW) SATA Controller
2653 82801FBM (ICH6M) SATA Controller
2658 82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #1
+ 1028 0179 Optiplex GX280
2659 82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #2
+ 1028 0179 Optiplex GX280
265a 82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #3
+ 1028 0179 Optiplex GX280
265b 82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #4
+ 1028 0179 Optiplex GX280
265c 82801FB/FBM/FR/FW/FRW (ICH6 Family) USB2 EHCI Controller
+ 1028 0179 Optiplex GX280
2660 82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 1
2662 82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 2
2664 82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 3
2666 82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 4
2668 82801FB/FBM/FR/FW/FRW (ICH6 Family) High Definition Audio Controller
266a 82801FB/FBM/FR/FW/FRW (ICH6 Family) SMBus Controller
+ 1028 0179 Optiplex GX280
266c 82801FB/FBM/FR/FW/FRW (ICH6 Family) LAN Controller
266d 82801FB/FBM/FR/FW/FRW (ICH6 Family) AC'97 Modem Controller
266e 82801FB/FBM/FR/FW/FRW (ICH6 Family) AC'97 Audio Controller
+ 1028 0179 Optiplex GX280
266f 82801FB/FBM/FR/FW/FRW (ICH6 Family) IDE Controller
+ 2770 Memory Controller Hub
+ 2771 PCI Express Graphics Port
+ 2772 Integrated Graphics Controller
+ 2774 Workstation Memory Controller Hub
+ 2775 PCI Express Graphics Port
+ 2776 Integrated Graphics Controller
+ 2778 Server Memory Controller Hub
+ 2779 PCI Express Root Port
2782 82915G Express Chipset Family Graphics Controller
- 2792 Mobile Graphics Controller
+ 2792 Mobile 915GM/GMS/910GML Express Graphics Controller
+ 27b1 Mobile I/O Controller Hub LPC
+ 27b8 I/O Controller Hub LPC
+ 27c0 I/O Controller Hub SATA cc=IDE
+ 27c1 I/O Controller Hub SATA cc=AHCI
+ 27c2 I/O Controller Hub SATA cc=RAID
+ 27c3 I/O Controller Hub SATA cc=RAID
+ 27c4 Mobile I/O Controller Hub SATA cc=IDE
+ 27c5 Mobile I/O Controller Hub SATA cc=AHCI
+ 27c8 I/O Controller Hub UHCI USB #1
+ 27c9 I/O Controller Hub UHCI USB #2
+ 27ca I/O Controller Hub UHCI USB #3
+ 27cb I/O Controller Hub UHCI USB #4
+ 27cc I/O Controller Hub EHCI USB
+ 27d0 I/O Controller Hub PCI Express Port 1
+ 27d2 I/O Controller Hub PCI Express Port 2
+ 27d4 I/O Controller Hub PCI Express Port 3
+ 27d6 I/O Controller Hub PCI Express Port 4
+ 27d8 I/O Controller Hub High Definition Audio
+ 27da I/O Controller Hub SMBus
+ 27dc I/O Controller Hub LAN
+ 27dd I/O Controller Hub AC'97 Modem
+ 27de I/O Controller Hub AC'97 Audio
+ 27df I/O Controller Hub PATA
+ 27e0 I/O Controller Hub PCI Express Port 5
+ 27e2 I/O Controller Hub PCI Express Port 6
3092 Integrated RAID
3200 GD31244 PCI-X SATA HBA
3340 82855PM Processor to I/O Controller
+ 1025 005a TravelMate 290
+ 103c 0890 NC6000 laptop
3341 82855PM Processor to AGP Controller
3575 82830 830 Chipset Host Bridge
1014 021d ThinkPad A/T/X Series
@@ -8330,25 +9193,34 @@
3577 82830 CGC [Chipset Graphics Controller]
1014 0513 ThinkPad A/T/X Series
3578 82830 830 Chipset Host Bridge
- 3580 82852/855GM Host Bridge
- 3581 855GME GMCH Host-to-AGP Bridge (Virtual PCI-to-PCI)
+ 3580 82852/82855 GM/GME/PM/GMV Processor to I/O Controller
+ 1028 0163 Latitude D505
+ 4c53 10b0 CL9 mainboard
+ 3581 82852/82855 GM/GME/PM/GMV Processor to AGP Controller
3582 82852/855GM Integrated Graphics Device
- 3584 855GM/GME GMCH Memory I/O Control Registers
- 3585 855GM/GME GMCH Configuration Process Registers
- 3590 Server Memory Controller Hub
- 3591 Memory Controller Hub Error Reporting Register
- 3592 Server Memory Controller Hub
- 3593 Memory Controller Hub Error Reporting Register
- 3594 Memory Controller Hub DMA Controller
- 3595 Memory Controller Hub PCI Express Port A0
- 3596 Memory Controller Hub PCI Express Port A1
- 3597 Memory Controller Hub PCI Express Port B0
- 3598 Memory Controller Hub PCI Express Port B1
- 3599 Memory Controller Hub PCI Express Port C0
- 359a Memory Controller Hub PCI Express Port C1
- 359b Memory Controller Hub Extended Configuration Registers
- 359e Workstation Memory Controller Hub
+ 1028 0163 Latitude D505
+ 4c53 10b0 CL9 mainboard
+ 3584 82852/82855 GM/GME/PM/GMV Processor to I/O Controller
+ 1028 0163 Latitude D505
+ 4c53 10b0 CL9 mainboard
+ 3585 82852/82855 GM/GME/PM/GMV Processor to I/O Controller
+ 1028 0163 Latitude D505
+ 4c53 10b0 CL9 mainboard
+ 3590 E7520 Memory Controller Hub
+ 3591 E7525/E7520 Error Reporting Registers
+ 3592 E7320 Memory Controller Hub
+ 3593 E7320 Error Reporting Registers
+ 3594 E7520 DMA Controller
+ 3595 E7525/E7520/E7320 PCI Express Port A
+ 3596 E7525/E7520/E7320 PCI Express Port A1
+ 3597 E7525/E7520 PCI Express Port B
+ 3598 E7520 PCI Express Port B1
+ 3599 E7520 PCI Express Port C
+ 359a E7520 PCI Express Port C1
+ 359b E7525/E7520/E7320 Extended Configuration Registers
+ 359e E7525 Memory Controller Hub
4220 PRO/Wireless 2200BG
+ 4223 PRO/Wireless 2915ABG MiniPCI Adapter
5200 EtherExpress PRO/100 Intelligent Server
5201 EtherExpress PRO/100 Intelligent Server
8086 0001 EtherExpress PRO/100 Server Ethernet Adapter
@@ -8360,9 +9232,13 @@
7050 Intel Intercast Video Capture Card
7100 430TX - 82439TX MTXC
7110 82371AB/EB/MB PIIX4 ISA
+ 15ad 1976 virtualHW v3
7111 82371AB/EB/MB PIIX4 IDE
+ 15ad 1976 virtualHW v3
7112 82371AB/EB/MB PIIX4 USB
+ 15ad 1976 virtualHW v3
7113 82371AB/EB/MB PIIX4 ACPI
+ 15ad 1976 virtualHW v3
7120 82810 GMCH [Graphics Memory Controller Hub]
4c53 1040 CL7 mainboard
4c53 1060 PC7 mainboard
@@ -8383,6 +9259,7 @@
0e11 0500 Armada 1750 Laptop System Chipset
0e11 b110 Armada M700/E500
1179 0001 Toshiba Tecra 8100 Laptop System Chipset
+ 15ad 1976 virtualHW v3
4c53 1050 CT7 mainboard
4c53 1051 CE7 mainboard
7191 440BX/ZX/DX - 82443BX/ZX/DX AGP bridge
@@ -8393,6 +9270,7 @@
1033 0000 Versa Note Vxi
4c53 10a0 CA3/CR3 mainboard
7195 82440MX AC'97 Audio Controller
+ 1033 80cc Versa Note VXi
10cf 1099 QSound_SigmaTel Stac97 PCI Audio
11d4 0040 SoundMAX Integrated Digital Audio
11d4 0048 SoundMAX Integrated Digital Audio
@@ -8430,7 +9308,7 @@
84e4 460GX - 84460GX Memory Data Controller (MDC)
84e6 460GX - 82466GX Wide and fast PCI eXpander Bridge (WXB)
84ea 460GX - 84460GX AGP Bridge (GXB function 1)
- 8500 IXP4xx Family Network Processor (IXP420, 421, 422, 425 and IXC1100)
+ 8500 IXP4XX Network Processor family. IXP420/IXP421/IXP422/IXP425/IXC1100
9000 IXP2000 Family Network Processor
9001 IXP2400 Network Processor
9004 IXP2800 Network Processor
@@ -8438,10 +9316,15 @@
9622 Integrated RAID
9641 Integrated RAID
96a1 Integrated RAID
+# retail verson
+ a01f PRO/10GbE LR Server Adapter
+# OEM version
+ a11f PRO/10GbE LR Server Adapter
b152 21152 PCI-to-PCI Bridge
# observed, and documented in Intel revision note; new mask of 1011:0026
b154 21154 PCI-to-PCI Bridge
b555 21555 Non transparent PCI-to-PCI Bridge
+ 12d9 000a PCI VoIP Gateway
1331 0030 ENP-2611
4c53 1050 CT7 mainboard
4c53 1051 CE7 mainboard
@@ -8616,6 +9499,7 @@
00cf AIC-7899P U160/m
1028 00ce PowerEdge 1400
1028 00d1 PowerEdge 2550
+ 1028 00d9 PowerEdge 2500
10f1 2462 Thunder K7 S2462
15d9 9005 Onboard SCSI Host Adapter
8086 3411 SDS2 Mainboard
@@ -8647,6 +9531,8 @@
9005 0294 ESD SO-DIMM PCI-X SATA ZCR (Prowler)
0286 AAC-RAID (Rocket)
9005 028c ASR-2230S + ASR-2230SLP PCI-X (Lancer)
+ 0503 Scamp chipset SCSI controller
+ 1014 02BF Quad Channel PCI-X DDR U320 SCSI RAID Adapter (571E)
8000 ASC-29320A U320
800f AIC-7901 U320
8010 ASC-39320 U320
@@ -8685,13 +9571,26 @@
9699 Omni Media Technology Inc
6565 6565
9710 NetMos Technology
- 9815 PCI 9815 Multi-I/O Controller
+ 7780 USB IRDA-port
+ 9705 PCI 9705 Parallel Port
+ 9715 PCI 9715 Dual Parallel Port
+ 9735 PCI 9735 Multi-I/O Controller
+ 1000 0002 0P2S (2 serial)
+ 1000 0012 1P2S (1 parallel + 2 serial)
+ 9745 PCI 9745 Multi-I/O Controller
+ 1000 0002 0P2S (2 serial)
+ 1000 0012 1P2S (1 parallel + 2 serial)
+ 9755 PCI 9755 Parallel Port and ISA Bridge
+ 9805 PCI 9805 Parallel Port
+ 9815 PCI 9815 Dual Parallel Port
1000 0020 2P0S (2 port parallel adaptor)
9835 PCI 9835 Multi-I/O Controller
- 1000 0002 2S (16C550 UART)
+ 1000 0002 0P2S (16C550 UART)
1000 0012 1P2S
9845 PCI 9845 Multi-I/O Controller
- 1000 0006 0P6S (6 port 16550a serial card)
+ 1000 0004 0P4S (4 port 16550A serial card)
+ 1000 0006 0P6S (6 port 16550A serial card)
+ 1000 0014 1P4S (4 port 16550A serial card + parallel)
9855 PCI 9855 Multi-I/O Controller
1000 0014 1P4S
9902 Stargen Inc.
@@ -8705,8 +9604,10 @@ a259 Hewlett Packard
a25b Hewlett Packard GmbH PL24-MKT
a304 Sony
a727 3Com Corporation
+ 0013 3CRPAG175 Wireless PC Card
aa42 Scitex Digital Video
ac1e Digital Receiver Technology Inc
+ac3d Actuality Systems
aecb Adrienne Electronics Corporation
b1b3 Shiva Europe Limited
# Pinnacle should be 11bd, but they got it wrong several times --mj
diff --git a/drivers/pci/pcie/Kconfig b/drivers/pci/pcie/Kconfig
index 6258a9c346a85..1012db8b8b2c4 100644
--- a/drivers/pci/pcie/Kconfig
+++ b/drivers/pci/pcie/Kconfig
@@ -3,14 +3,12 @@
#
config PCIEPORTBUS
bool "PCI Express support"
- depends on PCI_GOMMCONFIG || PCI_GOANY
- default n
-
- ---help---
- This automatically enables PCI Express Port Bus support. Users can
- choose Native Hot-Plug support, Advanced Error Reporting support,
- Power Management Event support and Virtual Channel support to run
- on PCI Express Ports (Root or Switch).
+ depends on PCI
+ help
+ This automatically enables PCI Express Port Bus support. Users can
+ choose Native Hot-Plug support, Advanced Error Reporting support,
+ Power Management Event support and Virtual Channel support to run
+ on PCI Express Ports (Root or Switch).
#
# Include service Kconfig here
diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c
index daccaf531d935..3184843c36490 100644
--- a/drivers/pci/pcie/portdrv_pci.c
+++ b/drivers/pci/pcie/portdrv_pci.c
@@ -106,7 +106,7 @@ static int __init pcie_portdrv_init(void)
int retval = 0;
pcie_port_bus_register();
- retval = pci_module_init(&pcie_portdrv);
+ retval = pci_register_driver(&pcie_portdrv);
if (retval)
pcie_port_bus_unregister();
return retval;
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 663ce3aa73bfe..379fb2a6f72ac 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -64,9 +64,11 @@ static void pci_create_legacy_files(struct pci_bus *b)
void pci_remove_legacy_files(struct pci_bus *b)
{
- class_device_remove_bin_file(&b->class_dev, b->legacy_io);
- class_device_remove_bin_file(&b->class_dev, b->legacy_mem);
- kfree(b->legacy_io); /* both are allocated here */
+ if (b->legacy_io) {
+ class_device_remove_bin_file(&b->class_dev, b->legacy_io);
+ class_device_remove_bin_file(&b->class_dev, b->legacy_mem);
+ kfree(b->legacy_io); /* both are allocated here */
+ }
}
#else /* !HAVE_PCI_LEGACY */
static inline void pci_create_legacy_files(struct pci_bus *bus) { return; }
@@ -549,7 +551,6 @@ static int pci_setup_device(struct pci_dev * dev)
{
u32 class;
- dev->slot_name = dev->dev.bus_id;
sprintf(pci_name(dev), "%04x:%02x:%02x.%d", pci_domain_nr(dev->bus),
dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c
index da51bf96a15c6..b53bb859ce91c 100644
--- a/drivers/pci/proc.c
+++ b/drivers/pci/proc.c
@@ -384,26 +384,32 @@ static struct proc_dir_entry *proc_bus_pci_dir;
int pci_proc_attach_device(struct pci_dev *dev)
{
struct pci_bus *bus = dev->bus;
- struct proc_dir_entry *de, *e;
+ struct proc_dir_entry *e;
char name[16];
if (!proc_initialized)
return -EACCES;
- if (!(de = bus->procdir)) {
- if (pci_name_bus(name, bus))
- return -EEXIST;
- de = bus->procdir = proc_mkdir(name, proc_bus_pci_dir);
- if (!de)
+ if (!bus->procdir) {
+ if (pci_proc_domain(bus)) {
+ sprintf(name, "%04x:%02x", pci_domain_nr(bus),
+ bus->number);
+ } else {
+ sprintf(name, "%02x", bus->number);
+ }
+ bus->procdir = proc_mkdir(name, proc_bus_pci_dir);
+ if (!bus->procdir)
return -ENOMEM;
}
+
sprintf(name, "%02x.%x", PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
- e = dev->procent = create_proc_entry(name, S_IFREG | S_IRUGO | S_IWUSR, de);
+ e = create_proc_entry(name, S_IFREG | S_IRUGO | S_IWUSR, bus->procdir);
if (!e)
return -ENOMEM;
e->proc_fops = &proc_bus_pci_operations;
e->data = dev;
e->size = dev->cfg_size;
+ dev->procent = e;
return 0;
}
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 7fffd4d070905..eef35c8a71e59 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -429,6 +429,8 @@ static void __init quirk_ioapic_rmw(struct pci_dev *dev)
}
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI, PCI_ANY_ID, quirk_ioapic_rmw );
+int pci_msi_quirk;
+
#define AMD8131_revA0 0x01
#define AMD8131_revB0 0x11
#define AMD8131_MISC 0x40
@@ -437,6 +439,9 @@ static void __init quirk_amd_8131_ioapic(struct pci_dev *dev)
{
unsigned char revid, tmp;
+ pci_msi_quirk = 1;
+ printk(KERN_WARNING "PCI: MSI quirk detected. pci_msi_quirk set.\n");
+
if (nr_ioapics == 0)
return;
@@ -786,6 +791,7 @@ static void __init asus_hides_smbus_hostbridge(struct pci_dev *dev)
}
if (dev->device == PCI_DEVICE_ID_INTEL_82855PM_HB)
switch (dev->subsystem_device) {
+ case 0x184b: /* W1N notebook */
case 0x186a: /* M6Ne notebook */
asus_hides_smbus = 1;
}
@@ -801,6 +807,18 @@ static void __init asus_hides_smbus_hostbridge(struct pci_dev *dev)
case 0x12bc: /* HP D330L */
asus_hides_smbus = 1;
}
+ } else if (unlikely(dev->subsystem_vendor == PCI_VENDOR_ID_TOSHIBA)) {
+ if (dev->device == PCI_DEVICE_ID_INTEL_82855GM_HB)
+ switch(dev->subsystem_device) {
+ case 0x0001: /* Toshiba Satellite A40 */
+ asus_hides_smbus = 1;
+ }
+ } else if (unlikely(dev->subsystem_vendor == PCI_VENDOR_ID_SAMSUNG)) {
+ if (dev->device == PCI_DEVICE_ID_INTEL_82855PM_HB)
+ switch(dev->subsystem_device) {
+ case 0xC00C: /* Samsung P35 notebook */
+ asus_hides_smbus = 1;
+ }
}
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82845_HB, asus_hides_smbus_hostbridge );
@@ -1241,6 +1259,40 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7520_MCH, quir
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7320_MCH, quirk_pcie_mch );
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7525_MCH, quirk_pcie_mch );
+static void __devinit quirk_netmos(struct pci_dev *dev)
+{
+ unsigned int num_parallel = (dev->subsystem_device & 0xf0) >> 4;
+ unsigned int num_serial = dev->subsystem_device & 0xf;
+
+ /*
+ * These Netmos parts are multiport serial devices with optional
+ * parallel ports. Even when parallel ports are present, they
+ * are identified as class SERIAL, which means the serial driver
+ * will claim them. To prevent this, mark them as class OTHER.
+ * These combo devices should be claimed by parport_serial.
+ *
+ * The subdevice ID is of the form 0x00PS, where <P> is the number
+ * of parallel ports and <S> is the number of serial ports.
+ */
+ switch (dev->device) {
+ case PCI_DEVICE_ID_NETMOS_9735:
+ case PCI_DEVICE_ID_NETMOS_9745:
+ case PCI_DEVICE_ID_NETMOS_9835:
+ case PCI_DEVICE_ID_NETMOS_9845:
+ case PCI_DEVICE_ID_NETMOS_9855:
+ if ((dev->class >> 8) == PCI_CLASS_COMMUNICATION_SERIAL &&
+ num_parallel) {
+ printk(KERN_INFO "PCI: Netmos %04x (%u parallel, "
+ "%u serial); changing class SERIAL to OTHER "
+ "(use parport_serial)\n",
+ dev->device, num_parallel, num_serial);
+ dev->class = (PCI_CLASS_COMMUNICATION_OTHER << 8) |
+ (dev->class & 0xff);
+ }
+ }
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NETMOS, PCI_ANY_ID, quirk_netmos);
+
static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, struct pci_fixup *end)
{
while (f < end) {
diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c
index 9fbf0d2d5a2d2..26a1d767c449c 100644
--- a/drivers/pci/setup-res.c
+++ b/drivers/pci/setup-res.c
@@ -86,11 +86,11 @@ pci_update_resource(struct pci_dev *dev, struct resource *res, int resno)
}
res->flags &= ~IORESOURCE_UNSET;
DBGC((KERN_INFO "PCI: moved device %s resource %d (%lx) to %x\n",
- dev->slot_name, resno, res->flags,
+ pci_name(dev), resno, res->flags,
new & ~PCI_REGION_FLAG_MASK));
}
-int __init
+int __devinit
pci_claim_resource(struct pci_dev *dev, int resource)
{
struct resource *res = &dev->resource[resource];
diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig
index 5e0ea6ff877ce..6375ebc850205 100644
--- a/drivers/pcmcia/Kconfig
+++ b/drivers/pcmcia/Kconfig
@@ -20,9 +20,10 @@ config PCCARD
To compile this driver as modules, choose M here: the
module will be called pcmcia_core.
+if PCCARD
+
config PCMCIA_DEBUG
bool "Enable PCCARD debugging"
- depends on PCCARD != n
help
Say Y here to enable PCMCIA subsystem debugging. You
will need to choose the debugging level either via the
@@ -41,7 +42,6 @@ config PCMCIA_DEBUG
config PCMCIA
tristate "16-bit PCMCIA support"
- depends on PCCARD
default y
---help---
This option enables support for 16-bit PCMCIA cards. Most older
@@ -60,7 +60,7 @@ config PCMCIA
config CARDBUS
bool "32-bit CardBus support"
- depends on PCCARD && PCI
+ depends on PCI
default y
---help---
CardBus is a bus mastering architecture for PC-cards, which allows
@@ -77,7 +77,7 @@ comment "PC-card bridges"
config YENTA
tristate "CardBus yenta-compatible bridge support"
- depends on PCCARD && PCI
+ depends on PCI
#fixme: remove dependendcy on CARDBUS
depends on CARDBUS
select PCCARD_NONSTATIC
@@ -197,6 +197,7 @@ config PCMCIA_VRC4173
config PCCARD_NONSTATIC
tristate
- depends on PCCARD
+
+endif # PCCARD
endmenu
diff --git a/drivers/pcmcia/au1000_generic.c b/drivers/pcmcia/au1000_generic.c
index 769a8cc12f9dc..9fa7f15d89e59 100644
--- a/drivers/pcmcia/au1000_generic.c
+++ b/drivers/pcmcia/au1000_generic.c
@@ -156,15 +156,12 @@ static int au1x00_pcmcia_sock_init(struct pcmcia_socket *sock)
static int au1x00_pcmcia_suspend(struct pcmcia_socket *sock)
{
struct au1000_pcmcia_socket *skt = to_au1000_socket(sock);
- int ret;
debug("suspending socket %u\n", skt->nr);
- ret = au1x00_pcmcia_config_skt(skt, &dead_socket);
- if (ret == 0)
- skt->ops->socket_suspend(skt);
+ skt->ops->socket_suspend(skt);
- return ret;
+ return 0;
}
static DEFINE_SPINLOCK(status_lock);
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
index be4db637e7a26..03fc885db1c57 100644
--- a/drivers/pcmcia/cs.c
+++ b/drivers/pcmcia/cs.c
@@ -140,7 +140,7 @@ static u8 pcmcia_used_irq[NR_IRQS];
static int socket_resume(struct pcmcia_socket *skt);
static int socket_suspend(struct pcmcia_socket *skt);
-int pcmcia_socket_dev_suspend(struct device *dev, u32 state)
+int pcmcia_socket_dev_suspend(struct device *dev, pm_message_t state)
{
struct pcmcia_socket *socket;
@@ -221,6 +221,8 @@ int pcmcia_register_socket(struct pcmcia_socket *socket)
cs_dbg(socket, 0, "pcmcia_register_socket(0x%p)\n", socket->ops);
+ spin_lock_init(&socket->lock);
+
if (socket->resource_ops->init) {
ret = socket->resource_ops->init(socket);
if (ret)
@@ -261,7 +263,6 @@ int pcmcia_register_socket(struct pcmcia_socket *socket)
socket->cis_mem.speed = cis_speed;
INIT_LIST_HEAD(&socket->cis_cache);
- spin_lock_init(&socket->lock);
init_completion(&socket->socket_released);
init_completion(&socket->thread_done);
@@ -564,7 +565,9 @@ static int socket_suspend(struct pcmcia_socket *skt)
send_event(skt, CS_EVENT_PM_SUSPEND, CS_EVENT_PRI_LOW);
skt->socket = dead_socket;
- skt->ops->suspend(skt);
+ skt->ops->set_socket(skt, &skt->socket);
+ if (skt->ops->suspend)
+ skt->ops->suspend(skt);
skt->state |= SOCKET_SUSPEND;
return CS_SUCCESS;
@@ -586,6 +589,11 @@ static int socket_resume(struct pcmcia_socket *skt)
skt->ops->init(skt);
skt->ops->set_socket(skt, &skt->socket);
+ if (!(skt->state & SOCKET_PRESENT)) {
+ skt->state &= ~SOCKET_SUSPEND;
+ return socket_insert(skt);
+ }
+
ret = socket_setup(skt, resume_delay);
if (ret == CS_SUCCESS) {
/*
diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h
index b517e039d3fe6..7933a7db49d32 100644
--- a/drivers/pcmcia/cs_internal.h
+++ b/drivers/pcmcia/cs_internal.h
@@ -159,6 +159,7 @@ int pccard_access_configuration_register(struct pcmcia_socket *s, unsigned int f
struct pcmcia_callback{
struct module *owner;
int (*event) (struct pcmcia_socket *s, event_t event, int priority);
+ int (*resources_done) (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 26c0f63a9a0b4..66150d08b5c7c 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -91,8 +91,7 @@ struct pcmcia_bus_socket {
struct pcmcia_callback callback;
int state;
user_info_t *user;
- int req_pending, req_result;
- wait_queue_head_t queue, request;
+ wait_queue_head_t queue;
struct pcmcia_socket *parent;
/* the PCMCIA devices connected to this socket (normally one, more
@@ -285,13 +284,19 @@ static struct pcmcia_bus_socket *pcmcia_get_bus_socket(struct pcmcia_bus_socket
*
* Registers a PCMCIA driver with the PCMCIA bus core.
*/
+static int pcmcia_device_probe(struct device *dev);
+static int pcmcia_device_remove(struct device * dev);
+
int pcmcia_register_driver(struct pcmcia_driver *driver)
{
if (!driver)
return -EINVAL;
+ /* 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);
}
@@ -352,7 +357,8 @@ static struct pcmcia_device * pcmcia_get_dev(struct pcmcia_device *p_dev)
static void pcmcia_put_dev(struct pcmcia_device *p_dev)
{
- put_device(&p_dev->dev);
+ if (p_dev)
+ put_device(&p_dev->dev);
}
static void pcmcia_release_dev(struct device *dev)
@@ -364,6 +370,275 @@ static void pcmcia_release_dev(struct device *dev)
}
+static int pcmcia_device_probe(struct device * dev)
+{
+ struct pcmcia_device *p_dev;
+ struct pcmcia_driver *p_drv;
+ int ret = 0;
+
+ dev = get_device(dev);
+ if (!dev)
+ return -ENODEV;
+
+ p_dev = to_pcmcia_dev(dev);
+ p_drv = to_pcmcia_drv(dev->driver);
+
+ if (!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->client.state & CLIENT_UNBOUND)) {
+ printk(KERN_NOTICE "ds: unable to create instance "
+ "of '%s'!\n", p_drv->drv.name);
+ ret = -EINVAL;
+ }
+ }
+
+ if (ret)
+ module_put(p_drv->owner);
+ put_dev:
+ if ((ret) || !(p_drv->attach))
+ put_device(dev);
+ return (ret);
+}
+
+
+static int pcmcia_device_remove(struct device * dev)
+{
+ struct pcmcia_device *p_dev;
+ struct pcmcia_driver *p_drv;
+
+ /* detach the "instance" */
+ p_dev = to_pcmcia_dev(dev);
+ p_drv = to_pcmcia_drv(dev->driver);
+
+ 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);
+ }
+
+ return 0;
+}
+
+
+
+/*
+ * pcmcia_device_query -- determine information about a pcmcia device
+ */
+static int pcmcia_device_query(struct pcmcia_device *p_dev)
+{
+ cistpl_manfid_t manf_id;
+ cistpl_funcid_t func_id;
+ cistpl_vers_1_t vers1;
+ unsigned int i;
+
+ if (!pccard_read_tuple(p_dev->socket, p_dev->func,
+ CISTPL_MANFID, &manf_id)) {
+ p_dev->manf_id = manf_id.manf;
+ p_dev->card_id = manf_id.card;
+ p_dev->has_manf_id = 1;
+ p_dev->has_card_id = 1;
+ }
+
+ if (!pccard_read_tuple(p_dev->socket, p_dev->func,
+ CISTPL_FUNCID, &func_id)) {
+ p_dev->func_id = func_id.func;
+ p_dev->has_func_id = 1;
+ } else {
+ /* rule of thumb: cards with no FUNCID, but with
+ * common memory device geometry information, are
+ * probably memory cards (from pcmcia-cs) */
+ cistpl_device_geo_t devgeo;
+ if (!pccard_read_tuple(p_dev->socket, p_dev->func,
+ CISTPL_DEVICE_GEO, &devgeo)) {
+ ds_dbg(0, "mem device geometry probably means "
+ "FUNCID_MEMORY\n");
+ p_dev->func_id = CISTPL_FUNCID_MEMORY;
+ p_dev->has_func_id = 1;
+ }
+ }
+
+ if (!pccard_read_tuple(p_dev->socket, p_dev->func, CISTPL_VERS_1,
+ &vers1)) {
+ for (i=0; i < vers1.ns; i++) {
+ char *tmp;
+ unsigned int length;
+
+ tmp = vers1.str + vers1.ofs[i];
+
+ length = strlen(tmp) + 1;
+ if ((length < 3) || (length > 255))
+ continue;
+
+ p_dev->prod_id[i] = kmalloc(sizeof(char) * length,
+ GFP_KERNEL);
+ if (!p_dev->prod_id[i])
+ continue;
+
+ p_dev->prod_id[i] = strncpy(p_dev->prod_id[i],
+ tmp, length);
+ }
+ }
+
+ return 0;
+}
+
+
+/* device_add_lock is needed to avoid double registration by cardmgr and kernel.
+ * Serializes pcmcia_device_add; will most likely be removed in future.
+ *
+ * While it has the caveat that adding new PCMCIA devices inside(!) device_register()
+ * won't work, this doesn't matter much at the moment: the driver core doesn't
+ * support it either.
+ */
+static DECLARE_MUTEX(device_add_lock);
+
+static struct pcmcia_device * pcmcia_device_add(struct pcmcia_bus_socket *s, unsigned int function)
+{
+ struct pcmcia_device *p_dev;
+ unsigned long flags;
+
+ s = pcmcia_get_bus_socket(s);
+ if (!s)
+ return NULL;
+
+ down(&device_add_lock);
+
+ p_dev = kmalloc(sizeof(struct pcmcia_device), GFP_KERNEL);
+ if (!p_dev)
+ goto err_put;
+ memset(p_dev, 0, sizeof(struct pcmcia_device));
+
+ p_dev->socket = s->parent;
+ p_dev->device_no = (s->device_count++);
+ p_dev->func = function;
+
+ p_dev->dev.bus = &pcmcia_bus_type;
+ p_dev->dev.parent = s->parent->dev.dev;
+ p_dev->dev.release = pcmcia_release_dev;
+ sprintf (p_dev->dev.bus_id, "%d.%d", p_dev->socket->sock, p_dev->device_no);
+
+ /* compat */
+ p_dev->client.client_magic = CLIENT_MAGIC;
+ p_dev->client.Socket = s->parent;
+ p_dev->client.Function = function;
+ p_dev->client.state = CLIENT_UNBOUND;
+
+ /* Add to the list in pcmcia_bus_socket */
+ spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
+ list_add_tail(&p_dev->socket_device_list, &s->devices_list);
+ spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
+
+ if (device_register(&p_dev->dev)) {
+ spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
+ list_del(&p_dev->socket_device_list);
+ spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
+
+ goto err_free;
+ }
+
+ up(&device_add_lock);
+
+ return p_dev;
+
+ err_free:
+ kfree(p_dev);
+ s->device_count--;
+ err_put:
+ up(&device_add_lock);
+ pcmcia_put_bus_socket(s);
+
+ return NULL;
+}
+
+
+static int pcmcia_card_add(struct pcmcia_socket *s)
+{
+ cisinfo_t cisinfo;
+ cistpl_longlink_mfc_t mfc;
+ unsigned int no_funcs, i;
+ int ret = 0;
+
+ if (!(s->resource_setup_done))
+ return -EAGAIN; /* try again, but later... */
+
+ pcmcia_validate_mem(s);
+ ret = pccard_validate_cis(s, BIND_FN_ALL, &cisinfo);
+ if (ret || !cisinfo.Chains) {
+ ds_dbg(0, "invalid CIS or invalid resources\n");
+ return -ENODEV;
+ }
+
+ if (!pccard_read_tuple(s, BIND_FN_ALL, CISTPL_LONGLINK_MFC, &mfc))
+ no_funcs = mfc.nfn;
+ else
+ no_funcs = 1;
+
+ /* this doesn't handle multifunction devices on one pcmcia function
+ * yet. */
+ for (i=0; i < no_funcs; i++)
+ pcmcia_device_add(s->pcmcia, i);
+
+ return (ret);
+}
+
+
+static int pcmcia_bus_match(struct device * dev, struct device_driver * drv) {
+ struct pcmcia_device * p_dev = to_pcmcia_dev(dev);
+ struct pcmcia_driver * p_drv = to_pcmcia_drv(drv);
+
+ /* matching by cardmgr */
+ if (p_dev->cardmgr == p_drv)
+ return 1;
+
+ return 0;
+}
+
+/************************ per-device sysfs output ***************************/
+
+#define pcmcia_device_attr(field, test, format) \
+static ssize_t field##_show (struct device *dev, char *buf) \
+{ \
+ struct pcmcia_device *p_dev = to_pcmcia_dev(dev); \
+ return p_dev->test ? sprintf (buf, format, p_dev->field) : -ENODEV; \
+}
+
+#define pcmcia_device_stringattr(name, field) \
+static ssize_t name##_show (struct device *dev, char *buf) \
+{ \
+ struct pcmcia_device *p_dev = to_pcmcia_dev(dev); \
+ return p_dev->field ? sprintf (buf, "%s\n", p_dev->field) : -ENODEV; \
+}
+
+pcmcia_device_attr(func, socket, "0x%02x\n");
+pcmcia_device_attr(func_id, has_func_id, "0x%02x\n");
+pcmcia_device_attr(manf_id, has_manf_id, "0x%04x\n");
+pcmcia_device_attr(card_id, has_card_id, "0x%04x\n");
+pcmcia_device_stringattr(prod_id1, prod_id[0]);
+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 struct device_attribute pcmcia_dev_attrs[] = {
+ __ATTR(function, 0444, func_show, NULL),
+ __ATTR_RO(func_id),
+ __ATTR_RO(manf_id),
+ __ATTR_RO(card_id),
+ __ATTR_RO(prod_id1),
+ __ATTR_RO(prod_id2),
+ __ATTR_RO(prod_id3),
+ __ATTR_RO(prod_id4),
+ __ATTR_NULL,
+};
+
+
/*======================================================================
These manage a ring buffer of events pending for one user process
@@ -397,19 +672,6 @@ static void handle_event(struct pcmcia_bus_socket *s, event_t event)
wake_up_interruptible(&s->queue);
}
-static int handle_request(struct pcmcia_bus_socket *s, event_t event)
-{
- if (s->req_pending != 0)
- return CS_IN_USE;
- if (s->state & DS_SOCKET_BUSY)
- s->req_pending = 1;
- handle_event(s, event);
- if (wait_event_interruptible(s->request, s->req_pending <= 0))
- return CS_IN_USE;
- if (s->state & DS_SOCKET_BUSY)
- return s->req_result;
- return CS_SUCCESS;
-}
/*======================================================================
@@ -486,14 +748,11 @@ static int ds_event(struct pcmcia_socket *skt, event_t event, int priority)
case CS_EVENT_CARD_INSERTION:
s->state |= DS_SOCKET_PRESENT;
+ pcmcia_card_add(skt);
handle_event(s, event);
- send_event(skt, event, priority);
break;
case CS_EVENT_EJECTION_REQUEST:
- ret = handle_request(s, event);
- if (ret)
- break;
ret = send_event(skt, event, priority);
break;
@@ -533,9 +792,9 @@ static int ds_event(struct pcmcia_socket *skt, event_t event, int priority)
static int bind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info)
{
struct pcmcia_driver *p_drv;
- struct pcmcia_device *p_dev, *tmp_dev;
- unsigned long flags;
+ struct pcmcia_device *p_dev;
int ret = 0;
+ unsigned long flags;
s = pcmcia_get_bus_socket(s);
if (!s)
@@ -555,74 +814,63 @@ static int bind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info)
goto err_put_driver;
}
- /* Currently, the userspace pcmcia cardmgr detects pcmcia devices.
- * Here this information is translated into a kernel
- * struct pcmcia_device.
- */
-
- p_dev = kmalloc(sizeof(struct pcmcia_device), GFP_KERNEL);
- if (!p_dev) {
- ret = -ENOMEM;
- goto err_put_module;
- }
- memset(p_dev, 0, sizeof(struct pcmcia_device));
-
- p_dev->socket = s->parent;
- p_dev->device_no = (s->device_count++);
- p_dev->func = bind_info->function;
-
- p_dev->dev.bus = &pcmcia_bus_type;
- p_dev->dev.parent = s->parent->dev.dev;
- p_dev->dev.release = pcmcia_release_dev;
- sprintf (p_dev->dev.bus_id, "%d.%d", p_dev->socket->sock, p_dev->device_no);
- p_dev->dev.driver = &p_drv->drv;
-
- /* compat */
- p_dev->client.client_magic = CLIENT_MAGIC;
- p_dev->client.Socket = s->parent;
- p_dev->client.Function = bind_info->function;
- p_dev->client.state = CLIENT_UNBOUND;
-
- ret = device_register(&p_dev->dev);
- if (ret) {
- kfree(p_dev);
- goto err_put_module;
- }
-
- /* Add to the list in pcmcia_bus_socket, but only if no device
- * with the same func _and_ driver exists */
spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
- list_for_each_entry(tmp_dev, &s->devices_list, socket_device_list) {
- if ((tmp_dev->func == bind_info->function) &&
- (tmp_dev->dev.driver == p_dev->dev.driver)){
- spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
- bind_info->instance = tmp_dev->instance;
- ret = -EBUSY;
- goto err_unregister;
+ list_for_each_entry(p_dev, &s->devices_list, socket_device_list) {
+ if (p_dev->func == bind_info->function) {
+ if ((p_dev->dev.driver == &p_drv->drv)) {
+ if (p_dev->cardmgr) {
+ /* if there's already a device
+ * registered, and it was registered
+ * by userspace before, we need to
+ * return the "instance". */
+ spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
+ bind_info->instance = p_dev->instance;
+ ret = -EBUSY;
+ goto err_put_module;
+ } else {
+ /* the correct driver managed to bind
+ * itself magically to the correct
+ * device. */
+ spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
+ p_dev->cardmgr = p_drv;
+ ret = 0;
+ goto err_put_module;
+ }
+ } else if (!p_dev->dev.driver) {
+ /* there's already a device available where
+ * no device has been bound to yet. So we don't
+ * need to register a device! */
+ spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
+ goto rescan;
+ }
}
}
- list_add_tail(&p_dev->socket_device_list, &s->devices_list);
spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
- if (p_drv->attach) {
- p_dev->instance = p_drv->attach();
- if ((!p_dev->instance) || (p_dev->client.state & CLIENT_UNBOUND)) {
- printk(KERN_NOTICE "ds: unable to create instance "
- "of '%s'!\n", (char *)bind_info->dev_info);
- ret = -ENODEV;
- goto err_unregister;
- }
+ p_dev = pcmcia_device_add(s, bind_info->function);
+ if (!p_dev) {
+ ret = -EIO;
+ goto err_put_module;
}
- put_driver(&p_drv->drv);
+rescan:
+ p_dev->cardmgr = p_drv;
- return 0;
+ pcmcia_device_query(p_dev);
- err_unregister:
- device_unregister(&p_dev->dev);
- module_put(p_drv->owner);
- put_driver(&p_drv->drv);
- return (ret);
+ /*
+ * Prevent this racing with a card insertion.
+ */
+ down(&s->parent->skt_sem);
+ bus_rescan_devices(&pcmcia_bus_type);
+ up(&s->parent->skt_sem);
+
+ /* check whether the driver indeed matched. I don't care if this
+ * is racy or not, because it can only happen on cardmgr access
+ * paths...
+ */
+ if (!(p_dev->dev.driver == &p_drv->drv))
+ p_dev->cardmgr = NULL;
err_put_module:
module_put(p_drv->owner);
@@ -630,9 +878,11 @@ static int bind_request(struct pcmcia_bus_socket *s, bind_info_t *bind_info)
put_driver(&p_drv->drv);
err_put:
pcmcia_put_bus_socket(s);
+
return (ret);
} /* bind_request */
+
int pcmcia_register_client(client_handle_t *handle, client_reg_t *req)
{
client_t *client = NULL;
@@ -683,10 +933,6 @@ int pcmcia_register_client(client_handle_t *handle, client_reg_t *req)
pcmcia_put_bus_socket(skt); /* safe, as we already hold a reference from bind_device */
- /*
- * Prevent this racing with a card insertion.
- */
- down(&s->skt_sem);
*handle = client;
client->state &= ~CLIENT_UNBOUND;
client->Socket = s;
@@ -723,11 +969,9 @@ int pcmcia_register_client(client_handle_t *handle, client_reg_t *req)
EVENT(client, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW);
}
- up(&s->skt_sem);
return CS_SUCCESS;
out_no_resource:
- up(&s->skt_sem);
pcmcia_put_dev(p_dev);
return CS_OUT_OF_RESOURCE;
} /* register_client */
@@ -831,7 +1075,6 @@ static int get_device_info(struct pcmcia_bus_socket *s, bind_info_t *bind_info,
static int unbind_request(struct pcmcia_bus_socket *s)
{
struct pcmcia_device *p_dev;
- struct pcmcia_driver *p_drv;
unsigned long flags;
ds_dbg(2, "unbind_request(%d)\n", s->parent->sock);
@@ -850,14 +1093,6 @@ static int unbind_request(struct pcmcia_bus_socket *s)
p_dev->client.state |= CLIENT_STALE;
spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
- /* detach the "instance" */
- p_drv = to_pcmcia_drv(p_dev->dev.driver);
- if (p_drv) {
- if ((p_drv->detach) && (p_dev->instance))
- p_drv->detach(p_dev->instance);
- module_put(p_drv->owner);
- }
-
device_unregister(&p_dev->dev);
}
@@ -964,8 +1199,6 @@ static int ds_release(struct inode *inode, struct file *file)
/* Unlink user data structure */
if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
s->state &= ~DS_SOCKET_BUSY;
- s->req_pending = 0;
- wake_up_interruptible(&s->request);
}
file->private_data = NULL;
for (link = &s->user; *link; link = &(*link)->next)
@@ -1014,33 +1247,14 @@ static ssize_t ds_read(struct file *file, char __user *buf,
static ssize_t ds_write(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
- struct pcmcia_bus_socket *s;
- user_info_t *user;
-
ds_dbg(2, "ds_write(socket %d)\n", iminor(file->f_dentry->d_inode));
-
+
if (count != 4)
return -EINVAL;
if ((file->f_flags & O_ACCMODE) == O_RDONLY)
return -EBADF;
- user = file->private_data;
- if (CHECK_USER(user))
- return -EIO;
-
- s = user->socket;
- if (s->state & DS_SOCKET_DEAD)
- return -EIO;
-
- if (s->req_pending) {
- s->req_pending--;
- get_user(s->req_result, (int __user *)buf);
- if ((s->req_result != 0) || (s->req_pending == 0))
- wake_up_interruptible(&s->request);
- } else
- return -EIO;
-
- return 4;
+ return -EIO;
} /* ds_write */
/*====================================================================*/
@@ -1099,17 +1313,15 @@ static int ds_ioctl(struct inode * inode, struct file * file,
return -EPERM;
if (cmd & IOC_IN) {
- err = verify_area(VERIFY_READ, uarg, size);
- if (err) {
- ds_dbg(3, "ds_ioctl(): verify_read = %d\n", err);
- return err;
+ if (!access_ok(VERIFY_READ, uarg, size)) {
+ ds_dbg(3, "ds_ioctl(): verify_read = %d\n", -EFAULT);
+ return -EFAULT;
}
}
if (cmd & IOC_OUT) {
- err = verify_area(VERIFY_WRITE, uarg, size);
- if (err) {
- ds_dbg(3, "ds_ioctl(): verify_write = %d\n", err);
- return err;
+ if (!access_ok(VERIFY_WRITE, uarg, size)) {
+ ds_dbg(3, "ds_ioctl(): verify_write = %d\n", -EFAULT);
+ return -EFAULT;
}
}
buf = kmalloc(sizeof(ds_ioctl_arg_t), GFP_KERNEL);
@@ -1136,7 +1348,9 @@ static int ds_ioctl(struct inode * inode, struct file * file,
buf->config.Function, &buf->config);
break;
case DS_GET_FIRST_TUPLE:
+ down(&s->parent->skt_sem);
pcmcia_validate_mem(s->parent);
+ up(&s->parent->skt_sem);
ret = pccard_get_first_tuple(s->parent, BIND_FN_ALL, &buf->tuple);
break;
case DS_GET_NEXT_TUPLE:
@@ -1162,7 +1376,9 @@ static int ds_ioctl(struct inode * inode, struct file * file,
ret = pccard_get_status(s->parent, buf->status.Function, &buf->status);
break;
case DS_VALIDATE_CIS:
+ down(&s->parent->skt_sem);
pcmcia_validate_mem(s->parent);
+ up(&s->parent->skt_sem);
ret = pccard_validate_cis(s->parent, BIND_FN_ALL, &buf->cisinfo);
break;
case DS_SUSPEND_CARD:
@@ -1203,7 +1419,7 @@ static int ds_ioctl(struct inode * inode, struct file * file,
printed++;
}
}
- ret = -EINVAL;
+ err = -EINVAL;
goto free_out;
break;
case DS_GET_FIRST_WINDOW:
@@ -1312,12 +1528,12 @@ static int __devinit pcmcia_bus_add_socket(struct class_device *class_dev)
msleep(250);
init_waitqueue_head(&s->queue);
- init_waitqueue_head(&s->request);
INIT_LIST_HEAD(&s->devices_list);
/* Set up hotline to Card Services */
s->callback.owner = THIS_MODULE;
s->callback.event = &ds_event;
+ s->callback.resources_done = &pcmcia_card_add;
socket->pcmcia = s;
ret = pccard_register_pcmcia(socket, &s->callback);
@@ -1359,6 +1575,8 @@ static struct class_interface pcmcia_bus_interface = {
struct bus_type pcmcia_bus_type = {
.name = "pcmcia",
+ .match = pcmcia_bus_match,
+ .dev_attrs = pcmcia_dev_attrs,
};
EXPORT_SYMBOL(pcmcia_bus_type);
diff --git a/drivers/pcmcia/hd64465_ss.c b/drivers/pcmcia/hd64465_ss.c
index 48584bb264410..5e6c4ba7d9955 100644
--- a/drivers/pcmcia/hd64465_ss.c
+++ b/drivers/pcmcia/hd64465_ss.c
@@ -353,20 +353,6 @@ static int hs_init(struct pcmcia_socket *s)
/*============================================================*/
-static int hs_suspend(struct pcmcia_socket *s)
-{
-#ifdef HD64465_DEBUG
- hs_socket_t *sp = container_of(s, struct hs_socket_t, socket);
- DPRINTK("hs_suspend(%d)\n", sp->number);
-#endif
-
- /* TODO */
-
- return 0;
-}
-
-/*============================================================*/
-
static int hs_get_status(struct pcmcia_socket *s, u_int *value)
{
@@ -763,7 +749,6 @@ static irqreturn_t hs_interrupt(int irq, void *dev, struct pt_regs *regs)
static struct pccard_operations hs_operations = {
.init = hs_init,
- .suspend = hs_suspend,
.get_status = hs_get_status,
.get_socket = hs_get_socket,
.set_socket = hs_set_socket,
diff --git a/drivers/pcmcia/i82092.c b/drivers/pcmcia/i82092.c
index a34632d759920..f3fdc748659d0 100644
--- a/drivers/pcmcia/i82092.c
+++ b/drivers/pcmcia/i82092.c
@@ -42,7 +42,7 @@ static struct pci_device_id i82092aa_pci_ids[] = {
};
MODULE_DEVICE_TABLE(pci, i82092aa_pci_ids);
-static int i82092aa_socket_suspend (struct pci_dev *dev, u32 state)
+static int i82092aa_socket_suspend (struct pci_dev *dev, pm_message_t state)
{
return pcmcia_socket_dev_suspend(&dev->dev, state);
}
@@ -65,7 +65,6 @@ static struct pci_driver i82092aa_pci_drv = {
/* the pccard structure and its functions */
static struct pccard_operations i82092aa_operations = {
.init = i82092aa_init,
- .suspend = i82092aa_suspend,
.get_status = i82092aa_get_status,
.get_socket = i82092aa_get_socket,
.set_socket = i82092aa_set_socket,
@@ -440,15 +439,6 @@ static int i82092aa_init(struct pcmcia_socket *sock)
return 0;
}
-static int i82092aa_suspend(struct pcmcia_socket *sock)
-{
- int retval;
- enter("i82092aa_suspend");
- retval = i82092aa_set_socket(sock, &dead_socket);
- leave("i82092aa_suspend");
- return retval;
-}
-
static int i82092aa_get_status(struct pcmcia_socket *socket, u_int *value)
{
unsigned int sock = container_of(socket, struct socket_info, socket)->number;
diff --git a/drivers/pcmcia/i82092aa.h b/drivers/pcmcia/i82092aa.h
index 0cdd80a1e17e2..b98cac7bda9f5 100644
--- a/drivers/pcmcia/i82092aa.h
+++ b/drivers/pcmcia/i82092aa.h
@@ -34,7 +34,6 @@ static int i82092aa_set_socket(struct pcmcia_socket *socket, socket_state_t *sta
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);
static int i82092aa_init(struct pcmcia_socket *socket);
-static int i82092aa_suspend(struct pcmcia_socket *socket);
#endif
diff --git a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c
index e9b5eb3ad2e54..90a335a5d9faf 100644
--- a/drivers/pcmcia/i82365.c
+++ b/drivers/pcmcia/i82365.c
@@ -1322,14 +1322,8 @@ static int pcic_init(struct pcmcia_socket *s)
return 0;
}
-static int pcic_suspend(struct pcmcia_socket *sock)
-{
- return pcic_set_socket(sock, &dead_socket);
-}
-
static struct pccard_operations pcic_operations = {
.init = pcic_init,
- .suspend = pcic_suspend,
.get_status = pcic_get_status,
.get_socket = pcic_get_socket,
.set_socket = pcic_set_socket,
@@ -1339,7 +1333,7 @@ static struct pccard_operations pcic_operations = {
/*====================================================================*/
-static int i82365_suspend(struct device *dev, u32 state, u32 level)
+static int i82365_suspend(struct device *dev, pm_message_t state, u32 level)
{
int ret = 0;
if (level == SUSPEND_SAVE_STATE)
diff --git a/drivers/pcmcia/m32r_cfc.c b/drivers/pcmcia/m32r_cfc.c
index eab36ffb462d0..b0b7a7a411200 100644
--- a/drivers/pcmcia/m32r_cfc.c
+++ b/drivers/pcmcia/m32r_cfc.c
@@ -732,15 +732,8 @@ static int pcc_init(struct pcmcia_socket *s)
return 0;
}
-static int pcc_suspend(struct pcmcia_socket *sock)
-{
- debug(3, "m32r_cfc: pcc_suspend()\n");
- return pcc_set_socket(sock, &dead_socket);
-}
-
static struct pccard_operations pcc_operations = {
.init = pcc_init,
- .suspend = pcc_suspend,
.get_status = pcc_get_status,
.get_socket = pcc_get_socket,
.set_socket = pcc_set_socket,
diff --git a/drivers/pcmcia/m32r_pcc.c b/drivers/pcmcia/m32r_pcc.c
index cbd187d41d809..cafba6f45dfa4 100644
--- a/drivers/pcmcia/m32r_pcc.c
+++ b/drivers/pcmcia/m32r_pcc.c
@@ -685,14 +685,8 @@ static int pcc_init(struct pcmcia_socket *s)
return 0;
}
-static int pcc_suspend(struct pcmcia_socket *sock)
-{
- return pcc_set_socket(sock, &dead_socket);
-}
-
static struct pccard_operations pcc_operations = {
.init = pcc_init,
- .suspend = pcc_suspend,
.get_status = pcc_get_status,
.get_socket = pcc_get_socket,
.set_socket = pcc_set_socket,
diff --git a/drivers/pcmcia/pd6729.c b/drivers/pcmcia/pd6729.c
index 05da3bf154ede..3f4364341d8d0 100644
--- a/drivers/pcmcia/pd6729.c
+++ b/drivers/pcmcia/pd6729.c
@@ -615,11 +615,6 @@ static int pd6729_set_mem_map(struct pcmcia_socket *sock,
return 0;
}
-static int pd6729_suspend(struct pcmcia_socket *sock)
-{
- return pd6729_set_socket(sock, &dead_socket);
-}
-
static int pd6729_init(struct pcmcia_socket *sock)
{
int i;
@@ -644,7 +639,6 @@ static int pd6729_init(struct pcmcia_socket *sock)
/* the pccard structure and its functions */
static struct pccard_operations pd6729_operations = {
.init = pd6729_init,
- .suspend = pd6729_suspend,
.get_status = pd6729_get_status,
.get_socket = pd6729_get_socket,
.set_socket = pd6729_set_socket,
@@ -833,7 +827,7 @@ static void __devexit pd6729_pci_remove(struct pci_dev *dev)
kfree(socket);
}
-static int pd6729_socket_suspend(struct pci_dev *dev, u32 state)
+static int pd6729_socket_suspend(struct pci_dev *dev, pm_message_t state)
{
return pcmcia_socket_dev_suspend(&dev->dev, state);
}
@@ -865,7 +859,7 @@ static struct pci_driver pd6729_pci_drv = {
static int pd6729_module_init(void)
{
- return pci_module_init(&pd6729_pci_drv);
+ return pci_register_driver(&pd6729_pci_drv);
}
static void pd6729_module_exit(void)
diff --git a/drivers/pcmcia/pxa2xx_sharpsl.c b/drivers/pcmcia/pxa2xx_sharpsl.c
index cabb91fff0d91..42efe218867a1 100644
--- a/drivers/pcmcia/pxa2xx_sharpsl.c
+++ b/drivers/pcmcia/pxa2xx_sharpsl.c
@@ -38,7 +38,7 @@ static struct pcmcia_irqs irqs[] = {
static void sharpsl_pcmcia_init_reset(void)
{
- reset_scoop();
+ reset_scoop(&corgiscoop_device.dev);
keep_vs = NO_KEEP_VS;
keep_rd = 0;
}
@@ -79,8 +79,8 @@ static int sharpsl_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
}
/* Enable interrupt */
- write_scoop_reg(SCOOP_IMR, 0x00C0);
- write_scoop_reg(SCOOP_MCR, 0x0101);
+ write_scoop_reg(&corgiscoop_device.dev, SCOOP_IMR, 0x00C0);
+ write_scoop_reg(&corgiscoop_device.dev, SCOOP_MCR, 0x0101);
keep_vs = NO_KEEP_VS;
skt->irq = CORGI_IRQ_GPIO_CF_IRQ;
@@ -102,30 +102,30 @@ static void sharpsl_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
{
unsigned short cpr, csr;
- cpr = read_scoop_reg(SCOOP_CPR);
+ cpr = read_scoop_reg(&corgiscoop_device.dev, SCOOP_CPR);
- write_scoop_reg(SCOOP_IRM, 0x00FF);
- write_scoop_reg(SCOOP_ISR, 0x0000);
- write_scoop_reg(SCOOP_IRM, 0x0000);
- csr = read_scoop_reg(SCOOP_CSR);
+ write_scoop_reg(&corgiscoop_device.dev, SCOOP_IRM, 0x00FF);
+ write_scoop_reg(&corgiscoop_device.dev, SCOOP_ISR, 0x0000);
+ write_scoop_reg(&corgiscoop_device.dev, SCOOP_IRM, 0x0000);
+ csr = read_scoop_reg(&corgiscoop_device.dev, SCOOP_CSR);
if (csr & 0x0004) {
/* card eject */
- write_scoop_reg(SCOOP_CDR, 0x0000);
+ write_scoop_reg(&corgiscoop_device.dev, SCOOP_CDR, 0x0000);
keep_vs = NO_KEEP_VS;
}
else if (!(keep_vs & NO_KEEP_VS)) {
/* keep vs1,vs2 */
- write_scoop_reg(SCOOP_CDR, 0x0000);
+ write_scoop_reg(&corgiscoop_device.dev, SCOOP_CDR, 0x0000);
csr |= keep_vs;
}
else if (cpr & 0x0003) {
/* power on */
- write_scoop_reg(SCOOP_CDR, 0x0000);
+ write_scoop_reg(&corgiscoop_device.dev, SCOOP_CDR, 0x0000);
keep_vs = (csr & 0x00C0);
}
else {
/* card detect */
- write_scoop_reg(SCOOP_CDR, 0x0002);
+ write_scoop_reg(&corgiscoop_device.dev, SCOOP_CDR, 0x0002);
}
state->detect = (csr & 0x0004) ? 0 : 1;
@@ -166,10 +166,10 @@ static int sharpsl_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
local_irq_save(flags);
- nmcr = (mcr = read_scoop_reg(SCOOP_MCR)) & ~0x0010;
- ncpr = (cpr = read_scoop_reg(SCOOP_CPR)) & ~0x0083;
- nccr = (ccr = read_scoop_reg(SCOOP_CCR)) & ~0x0080;
- nimr = (imr = read_scoop_reg(SCOOP_IMR)) & ~0x003E;
+ nmcr = (mcr = read_scoop_reg(&corgiscoop_device.dev, SCOOP_MCR)) & ~0x0010;
+ ncpr = (cpr = read_scoop_reg(&corgiscoop_device.dev, SCOOP_CPR)) & ~0x0083;
+ nccr = (ccr = read_scoop_reg(&corgiscoop_device.dev, SCOOP_CCR)) & ~0x0080;
+ nimr = (imr = read_scoop_reg(&corgiscoop_device.dev, SCOOP_IMR)) & ~0x003E;
ncpr |= (state->Vcc == 33) ? 0x0001 :
(state->Vcc == 50) ? 0x0002 : 0;
@@ -193,13 +193,13 @@ static int sharpsl_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
}
if (mcr != nmcr)
- write_scoop_reg(SCOOP_MCR, nmcr);
+ write_scoop_reg(&corgiscoop_device.dev, SCOOP_MCR, nmcr);
if (cpr != ncpr)
- write_scoop_reg(SCOOP_CPR, ncpr);
+ write_scoop_reg(&corgiscoop_device.dev, SCOOP_CPR, ncpr);
if (ccr != nccr)
- write_scoop_reg(SCOOP_CCR, nccr);
+ write_scoop_reg(&corgiscoop_device.dev, SCOOP_CCR, nccr);
if (imr != nimr)
- write_scoop_reg(SCOOP_IMR, nimr);
+ write_scoop_reg(&corgiscoop_device.dev, SCOOP_IMR, nimr);
local_irq_restore(flags);
diff --git a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c
index 73d72d08e8905..b6843f8d300d2 100644
--- a/drivers/pcmcia/rsrc_mgr.c
+++ b/drivers/pcmcia/rsrc_mgr.c
@@ -59,6 +59,7 @@ int pcmcia_adjust_resource_info(adjust_t *adj)
{
struct pcmcia_socket *s;
int ret = CS_UNSUPPORTED_FUNCTION;
+ unsigned long flags;
down_read(&pcmcia_socket_list_rwsem);
list_for_each_entry(s, &pcmcia_socket_list, socket_list) {
@@ -66,8 +67,30 @@ int pcmcia_adjust_resource_info(adjust_t *adj)
if (adj->Resource == RES_IRQ)
ret = adjust_irq(s, adj);
- else if (s->resource_ops->adjust_resource)
+ else if (s->resource_ops->adjust_resource) {
+
+ /* you can't use the old interface if the new
+ * one was used before */
+ spin_lock_irqsave(&s->lock, flags);
+ if ((s->resource_setup_done) &&
+ !(s->resource_setup_old)) {
+ spin_unlock_irqrestore(&s->lock, flags);
+ continue;
+ } else if (!(s->resource_setup_old))
+ s->resource_setup_old = 1;
+ spin_unlock_irqrestore(&s->lock, flags);
+
ret = s->resource_ops->adjust_resource(s, adj);
+ if (!ret) {
+ /* as there's no way we know this is the
+ * last call to adjust_resource_info, we
+ * always need to assume this is the latest
+ * one... */
+ spin_lock_irqsave(&s->lock, flags);
+ s->resource_setup_done = 1;
+ spin_unlock_irqrestore(&s->lock, flags);
+ }
+ }
}
up_read(&pcmcia_socket_list_rwsem);
@@ -113,12 +136,28 @@ void release_resource_db(struct pcmcia_socket *s)
}
+static int static_init(struct pcmcia_socket *s)
+{
+ unsigned long flags;
+
+ /* the good thing about SS_CAP_STATIC_MAP sockets is
+ * that they don't need a resource database */
+
+ spin_lock_irqsave(&s->lock, flags);
+ s->resource_setup_done = 1;
+ spin_unlock_irqrestore(&s->lock, flags);
+
+ return 0;
+}
+
+
struct pccard_resource_ops pccard_static_ops = {
.validate_mem = NULL,
.adjust_io_region = NULL,
.find_io = NULL,
.find_mem = NULL,
.adjust_resource = NULL,
+ .init = static_init,
.exit = NULL,
};
EXPORT_SYMBOL(pccard_static_ops);
diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c
index 41c246c6f4f50..5876bab7c14c8 100644
--- a/drivers/pcmcia/rsrc_nonstatic.c
+++ b/drivers/pcmcia/rsrc_nonstatic.c
@@ -24,6 +24,8 @@
#include <linux/ioport.h>
#include <linux/timer.h>
#include <linux/pci.h>
+#include <linux/device.h>
+
#include <asm/irq.h>
#include <asm/io.h>
@@ -472,8 +474,7 @@ static void validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
/*
- * Locking note: this is the only place where we take
- * both rsrc_sem and skt_sem.
+ * Locking note: Must be called with skt_sem held!
*/
static void pcmcia_nonstatic_validate_mem(struct pcmcia_socket *s)
{
@@ -490,12 +491,8 @@ static void pcmcia_nonstatic_validate_mem(struct pcmcia_socket *s)
if (probe_mask & ~s_data->rsrc_mem_probe) {
s_data->rsrc_mem_probe |= probe_mask;
- down(&s->skt_sem);
-
if (s->state & SOCKET_PRESENT)
validate_mem(s, probe_mask);
-
- up(&s->skt_sem);
}
up(&rsrc_sem);
@@ -779,6 +776,7 @@ static int nonstatic_init(struct pcmcia_socket *s)
data = kmalloc(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;
@@ -816,3 +814,172 @@ struct pccard_resource_ops pccard_nonstatic_ops = {
.exit = nonstatic_release_resource_db,
};
EXPORT_SYMBOL(pccard_nonstatic_ops);
+
+
+/* sysfs interface to the resource database */
+
+static ssize_t show_io_db(struct class_device *class_dev, char *buf)
+{
+ struct pcmcia_socket *s = class_get_devdata(class_dev);
+ struct socket_data *data;
+ struct resource_map *p;
+ ssize_t ret = 0;
+
+ down(&rsrc_sem);
+ data = s->resource_data;
+
+ for (p = data->io_db.next; p != &data->io_db; p = p->next) {
+ if (ret > (PAGE_SIZE - 10))
+ continue;
+ ret += snprintf (&buf[ret], (PAGE_SIZE - ret - 1),
+ "0x%08lx - 0x%08lx\n",
+ ((unsigned long) p->base),
+ ((unsigned long) p->base + p->num - 1));
+ }
+
+ up(&rsrc_sem);
+ return (ret);
+}
+
+static ssize_t store_io_db(struct class_device *class_dev, const char *buf, size_t count)
+{
+ struct pcmcia_socket *s = class_get_devdata(class_dev);
+ unsigned long start_addr, end_addr;
+ unsigned int add = 1;
+ adjust_t adj;
+ ssize_t ret = 0;
+
+ ret = sscanf (buf, "+ 0x%lx - 0x%lx", &start_addr, &end_addr);
+ if (ret != 2) {
+ ret = sscanf (buf, "- 0x%lx - 0x%lx", &start_addr, &end_addr);
+ add = 0;
+ if (ret != 2) {
+ ret = sscanf (buf, "0x%lx - 0x%lx", &start_addr, &end_addr);
+ add = 1;
+ if (ret != 2)
+ return -EINVAL;
+ }
+ }
+ if (end_addr <= start_addr)
+ return -EINVAL;
+
+ adj.Action = add ? ADD_MANAGED_RESOURCE : REMOVE_MANAGED_RESOURCE;
+ adj.Resource = RES_IO_RANGE;
+ adj.resource.io.BasePort = start_addr;
+ adj.resource.io.NumPorts = end_addr - start_addr + 1;
+
+ ret = adjust_io(s, &adj);
+
+ return ret ? ret : count;
+}
+static CLASS_DEVICE_ATTR(available_resources_io, 0600, show_io_db, store_io_db);
+
+static ssize_t show_mem_db(struct class_device *class_dev, char *buf)
+{
+ struct pcmcia_socket *s = class_get_devdata(class_dev);
+ struct socket_data *data;
+ struct resource_map *p;
+ ssize_t ret = 0;
+
+ down(&rsrc_sem);
+ data = s->resource_data;
+
+ for (p = data->mem_db.next; p != &data->mem_db; p = p->next) {
+ if (ret > (PAGE_SIZE - 10))
+ continue;
+ ret += snprintf (&buf[ret], (PAGE_SIZE - ret - 1),
+ "0x%08lx - 0x%08lx\n",
+ ((unsigned long) p->base),
+ ((unsigned long) p->base + p->num - 1));
+ }
+
+ up(&rsrc_sem);
+ return (ret);
+}
+
+static ssize_t store_mem_db(struct class_device *class_dev, const char *buf, size_t count)
+{
+ struct pcmcia_socket *s = class_get_devdata(class_dev);
+ unsigned long start_addr, end_addr;
+ unsigned int add = 1;
+ adjust_t adj;
+ ssize_t ret = 0;
+
+ ret = sscanf (buf, "+ 0x%lx - 0x%lx", &start_addr, &end_addr);
+ if (ret != 2) {
+ ret = sscanf (buf, "- 0x%lx - 0x%lx", &start_addr, &end_addr);
+ add = 0;
+ if (ret != 2) {
+ ret = sscanf (buf, "0x%lx - 0x%lx", &start_addr, &end_addr);
+ add = 1;
+ if (ret != 2)
+ return -EINVAL;
+ }
+ }
+ if (end_addr <= start_addr)
+ return -EINVAL;
+
+ adj.Action = add ? ADD_MANAGED_RESOURCE : REMOVE_MANAGED_RESOURCE;
+ adj.Resource = RES_MEMORY_RANGE;
+ adj.resource.memory.Base = start_addr;
+ adj.resource.memory.Size = end_addr - start_addr + 1;
+
+ ret = adjust_memory(s, &adj);
+
+ return ret ? ret : count;
+}
+static CLASS_DEVICE_ATTR(available_resources_mem, 0600, show_mem_db, store_mem_db);
+
+static struct class_device_attribute *pccard_rsrc_attributes[] = {
+ &class_device_attr_available_resources_io,
+ &class_device_attr_available_resources_mem,
+ NULL,
+};
+
+static int __devinit pccard_sysfs_add_rsrc(struct class_device *class_dev)
+{
+ struct pcmcia_socket *s = class_get_devdata(class_dev);
+ struct class_device_attribute **attr;
+ int ret = 0;
+ if (s->resource_ops != &pccard_nonstatic_ops)
+ return 0;
+
+ for (attr = pccard_rsrc_attributes; *attr; attr++) {
+ ret = class_device_create_file(class_dev, *attr);
+ if (ret)
+ break;
+ }
+
+ return ret;
+}
+
+static void __devexit pccard_sysfs_remove_rsrc(struct class_device *class_dev)
+{
+ struct pcmcia_socket *s = class_get_devdata(class_dev);
+ struct class_device_attribute **attr;
+
+ if (s->resource_ops != &pccard_nonstatic_ops)
+ return;
+
+ for (attr = pccard_rsrc_attributes; *attr; attr++)
+ class_device_remove_file(class_dev, *attr);
+}
+
+static struct class_interface pccard_rsrc_interface = {
+ .class = &pcmcia_socket_class,
+ .add = &pccard_sysfs_add_rsrc,
+ .remove = __devexit_p(&pccard_sysfs_remove_rsrc),
+};
+
+static int __init nonstatic_sysfs_init(void)
+{
+ return class_interface_register(&pccard_rsrc_interface);
+}
+
+static void __exit nonstatic_sysfs_exit(void)
+{
+ class_interface_unregister(&pccard_rsrc_interface);
+}
+
+module_init(nonstatic_sysfs_init);
+module_exit(nonstatic_sysfs_exit);
diff --git a/drivers/pcmcia/soc_common.c b/drivers/pcmcia/soc_common.c
index e8c3f1fb62580..888b70e6a484f 100644
--- a/drivers/pcmcia/soc_common.c
+++ b/drivers/pcmcia/soc_common.c
@@ -197,15 +197,12 @@ static int soc_common_pcmcia_sock_init(struct pcmcia_socket *sock)
static int soc_common_pcmcia_suspend(struct pcmcia_socket *sock)
{
struct soc_pcmcia_socket *skt = to_soc_pcmcia_socket(sock);
- int ret;
debug(skt, 2, "suspending socket\n");
- ret = soc_common_pcmcia_config_skt(skt, &dead_socket);
- if (ret == 0)
- skt->ops->socket_suspend(skt);
+ skt->ops->socket_suspend(skt);
- return ret;
+ return 0;
}
static DEFINE_SPINLOCK(status_lock);
diff --git a/drivers/pcmcia/socket_sysfs.c b/drivers/pcmcia/socket_sysfs.c
index a68d7e5777e4f..8eed039382147 100644
--- a/drivers/pcmcia/socket_sysfs.c
+++ b/drivers/pcmcia/socket_sysfs.c
@@ -148,6 +148,45 @@ static ssize_t pccard_store_irq_mask(struct class_device *dev, const char *buf,
static CLASS_DEVICE_ATTR(card_irq_mask, 0600, pccard_show_irq_mask, pccard_store_irq_mask);
+static ssize_t pccard_show_resource(struct class_device *dev, char *buf)
+{
+ struct pcmcia_socket *s = to_socket(dev);
+ return sprintf(buf, "%s\n", s->resource_setup_done ? "yes" : "no");
+}
+
+static ssize_t pccard_store_resource(struct class_device *dev, const char *buf, size_t count)
+{
+ unsigned long flags;
+ struct pcmcia_socket *s = to_socket(dev);
+
+ if (!count)
+ return -EINVAL;
+
+ spin_lock_irqsave(&s->lock, flags);
+ if (!s->resource_setup_done) {
+ s->resource_setup_done = 1;
+ spin_unlock_irqrestore(&s->lock, flags);
+
+ down(&s->skt_sem);
+ if ((s->callback) &&
+ (s->state & SOCKET_PRESENT) &&
+ !(s->state & SOCKET_CARDBUS)) {
+ if (try_module_get(s->callback->owner)) {
+ s->callback->resources_done(s);
+ module_put(s->callback->owner);
+ }
+ }
+ up(&s->skt_sem);
+
+ return count;
+ }
+ spin_unlock_irqrestore(&s->lock, flags);
+
+ return count;
+}
+static CLASS_DEVICE_ATTR(available_resources_setup_done, 0600, pccard_show_resource, pccard_store_resource);
+
+
static struct class_device_attribute *pccard_socket_attributes[] = {
&class_device_attr_card_type,
&class_device_attr_card_voltage,
@@ -156,6 +195,7 @@ static struct class_device_attribute *pccard_socket_attributes[] = {
&class_device_attr_card_insert,
&class_device_attr_card_eject,
&class_device_attr_card_irq_mask,
+ &class_device_attr_available_resources_setup_done,
NULL,
};
diff --git a/drivers/pcmcia/tcic.c b/drivers/pcmcia/tcic.c
index 52d2a383e72b2..aacbbb5f055d8 100644
--- a/drivers/pcmcia/tcic.c
+++ b/drivers/pcmcia/tcic.c
@@ -373,7 +373,7 @@ static int __init get_tcic_id(void)
/*====================================================================*/
-static int tcic_drv_suspend(struct device *dev, u32 state, u32 level)
+static int tcic_drv_suspend(struct device *dev, pm_message_t state, u32 level)
{
int ret = 0;
if (level == SUSPEND_SAVE_STATE)
@@ -888,14 +888,8 @@ static int tcic_init(struct pcmcia_socket *s)
return 0;
}
-static int tcic_suspend(struct pcmcia_socket *sock)
-{
- return tcic_set_socket(sock, &dead_socket);
-}
-
static struct pccard_operations tcic_operations = {
.init = tcic_init,
- .suspend = tcic_suspend,
.get_status = tcic_get_status,
.get_socket = tcic_get_socket,
.set_socket = tcic_set_socket,
diff --git a/drivers/pcmcia/ti113x.h b/drivers/pcmcia/ti113x.h
index b9f3e3f21ad6c..52c073a9d7e44 100644
--- a/drivers/pcmcia/ti113x.h
+++ b/drivers/pcmcia/ti113x.h
@@ -262,6 +262,7 @@ static void ti_set_zv(struct yenta_socket *socket)
case PCI_DEVICE_ID_TI_1220:
case PCI_DEVICE_ID_TI_1221:
case PCI_DEVICE_ID_TI_1225:
+ case PCI_DEVICE_ID_TI_4510:
socket->socket.zoom_video = ti_zoom_video;
break;
case PCI_DEVICE_ID_TI_1250:
diff --git a/drivers/pcmcia/vrc4171_card.c b/drivers/pcmcia/vrc4171_card.c
index 24a544c88b4bf..987bc21ced42b 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 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * Copyright (C) 2003-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -26,7 +26,6 @@
#include <linux/types.h>
#include <asm/io.h>
-#include <asm/vr41xx/vrc4171.h>
#include <pcmcia/ss.h>
@@ -48,7 +47,6 @@ MODULE_LICENSE("GPL");
#define CARD_CONTROLLER_INDEX 0x03e0
#define CARD_CONTROLLER_DATA 0x03e1
-#define CARD_CONTROLLER_SIZE 2
/* Power register */
#define VPP_GET_VCC 0x01
#define POWER_ENABLE 0x10
@@ -69,18 +67,40 @@ MODULE_LICENSE("GPL");
#define IRQPM_EN 0x08
#define CLRPMIRQ 0x10
+#define INTERRUPT_STATUS 0x05fa
+ #define IRQ_A 0x02
+ #define IRQ_B 0x04
+
+#define CONFIGURATION1 0x05fe
+ #define SLOTB_CONFIG 0xc000
+ #define SLOTB_NONE 0x0000
+ #define SLOTB_PCCARD 0x4000
+ #define SLOTB_CF 0x8000
+ #define SLOTB_FLASHROM 0xc000
+
+#define CARD_CONTROLLER_START CARD_CONTROLLER_INDEX
+#define CARD_CONTROLLER_END CARD_CONTROLLER_DATA
+
#define IO_MAX_MAPS 2
#define MEM_MAX_MAPS 5
-enum {
+typedef enum {
SLOT_PROBE = 0,
SLOT_NOPROBE_IO,
SLOT_NOPROBE_MEM,
- SLOT_NOPROBE_ALL
-};
+ SLOT_NOPROBE_ALL,
+ SLOT_INITIALIZED,
+} vrc4171_slot_t;
+
+typedef enum {
+ SLOTB_IS_NONE,
+ SLOTB_IS_PCCARD,
+ SLOTB_IS_CF,
+ SLOTB_IS_FLASHROM,
+} vrc4171_slotb_t;
typedef struct vrc4171_socket {
- int noprobe;
+ vrc4171_slot_t slot;
struct pcmcia_socket pcmcia_socket;
char name[24];
int csc_irq;
@@ -88,10 +108,65 @@ typedef struct vrc4171_socket {
} vrc4171_socket_t;
static vrc4171_socket_t vrc4171_sockets[CARD_MAX_SLOTS];
-static int vrc4171_slotb = SLOTB_IS_NONE;
+static vrc4171_slotb_t vrc4171_slotb = SLOTB_IS_NONE;
+static char vrc4171_card_name[] = "NEC VRC4171 Card Controller";
static unsigned int vrc4171_irq;
static uint16_t vrc4171_irq_mask = 0xdeb8;
+static struct resource vrc4171_card_resource[3] = {
+ { .name = vrc4171_card_name,
+ .start = CARD_CONTROLLER_START,
+ .end = CARD_CONTROLLER_END,
+ .flags = IORESOURCE_IO, },
+ { .name = vrc4171_card_name,
+ .start = INTERRUPT_STATUS,
+ .end = INTERRUPT_STATUS,
+ .flags = IORESOURCE_IO, },
+ { .name = vrc4171_card_name,
+ .start = CONFIGURATION1,
+ .end = CONFIGURATION1,
+ .flags = IORESOURCE_IO, },
+};
+
+static struct platform_device vrc4171_card_device = {
+ .name = vrc4171_card_name,
+ .id = 0,
+ .num_resources = 3,
+ .resource = vrc4171_card_resource,
+};
+
+static inline uint16_t vrc4171_get_irq_status(void)
+{
+ return inw(INTERRUPT_STATUS);
+}
+
+static inline void vrc4171_set_multifunction_pin(vrc4171_slotb_t config)
+{
+ uint16_t config1;
+
+ config1 = inw(CONFIGURATION1);
+ config1 &= ~SLOTB_CONFIG;
+
+ switch (config) {
+ case SLOTB_IS_NONE:
+ config1 |= SLOTB_NONE;
+ break;
+ case SLOTB_IS_PCCARD:
+ config1 |= SLOTB_PCCARD;
+ break;
+ case SLOTB_IS_CF:
+ config1 |= SLOTB_CF;
+ break;
+ case SLOTB_IS_FLASHROM:
+ config1 |= SLOTB_FLASHROM;
+ break;
+ default:
+ break;
+ }
+
+ outw(config1, CONFIGURATION1);
+}
+
static inline uint8_t exca_read_byte(int slot, uint8_t index)
{
if (slot == CARD_SLOTB)
@@ -174,11 +249,6 @@ static int pccard_init(struct pcmcia_socket *sock)
return 0;
}
-static int pccard_suspend(struct pcmcia_socket *sock)
-{
- return -EINVAL;
-}
-
static int pccard_get_status(struct pcmcia_socket *sock, u_int *value)
{
unsigned int slot;
@@ -425,9 +495,9 @@ static int pccard_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map
if (sock == NULL || sock->sock >= CARD_MAX_SLOTS ||
mem == NULL || mem->map >= MEM_MAX_MAPS ||
- mem->sys_start < CARD_MEM_START || mem->sys_start > CARD_MEM_END ||
- mem->sys_stop < CARD_MEM_START || mem->sys_stop > CARD_MEM_END ||
- mem->sys_start > mem->sys_stop ||
+ mem->res->start < CARD_MEM_START || mem->res->start > CARD_MEM_END ||
+ mem->res->end < CARD_MEM_START || mem->res->end > CARD_MEM_END ||
+ mem->res->start > mem->res->end ||
mem->card_start > CARD_MAX_MEM_OFFSET ||
mem->speed > CARD_MAX_MEM_SPEED)
return -EINVAL;
@@ -441,12 +511,12 @@ static int pccard_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map
exca_write_byte(slot, I365_ADDRWIN, addrwin);
}
- start = (mem->sys_start >> 12) & 0x3fff;
+ start = (mem->res->start >> 12) & 0x3fff;
if (mem->flags & MAP_16BIT)
start |= I365_MEM_16BIT;
exca_write_word(slot, I365_MEM(map)+I365_W_START, start);
- stop = (mem->sys_stop >> 12) & 0x3fff;
+ stop = (mem->res->end >> 12) & 0x3fff;
switch (mem->speed) {
case 0:
break;
@@ -479,7 +549,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,
- .suspend = pccard_suspend,
.get_status = pccard_get_status,
.get_socket = pccard_get_socket,
.set_socket = pccard_set_socket,
@@ -524,7 +593,7 @@ static irqreturn_t pccard_interrupt(int irq, void *dev_id, struct pt_regs *regs)
status = vrc4171_get_irq_status();
if (status & IRQ_A) {
socket = &vrc4171_sockets[CARD_SLOTA];
- if (socket->noprobe == SLOT_PROBE) {
+ if (socket->slot == SLOT_INITIALIZED) {
if (status & (1 << socket->csc_irq)) {
events = get_events(CARD_SLOTA);
if (events != 0) {
@@ -537,7 +606,7 @@ static irqreturn_t pccard_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (status & IRQ_B) {
socket = &vrc4171_sockets[CARD_SLOTB];
- if (socket->noprobe == SLOT_PROBE) {
+ if (socket->slot == SLOT_INITIALIZED) {
if (status & (1 << socket->csc_irq)) {
events = get_events(CARD_SLOTB);
if (events != 0) {
@@ -564,63 +633,71 @@ static inline void reserve_using_irq(int slot)
vrc4171_irq_mask &= ~(1 << irq);
}
-static int __devinit vrc4171_add_socket(int slot)
+static int __devinit vrc4171_add_sockets(void)
{
vrc4171_socket_t *socket;
- int retval;
+ int slot, retval;
- if (slot >= CARD_MAX_SLOTS)
- return -EINVAL;
+ for (slot = 0; slot < CARD_MAX_SLOTS; slot++) {
+ if (slot == CARD_SLOTB && vrc4171_slotb == SLOTB_IS_NONE)
+ continue;
+
+ socket = &vrc4171_sockets[slot];
+ if (socket->slot != SLOT_PROBE) {
+ uint8_t addrwin;
+
+ switch (socket->slot) {
+ case SLOT_NOPROBE_MEM:
+ addrwin = exca_read_byte(slot, I365_ADDRWIN);
+ addrwin &= 0x1f;
+ exca_write_byte(slot, I365_ADDRWIN, addrwin);
+ break;
+ case SLOT_NOPROBE_IO:
+ addrwin = exca_read_byte(slot, I365_ADDRWIN);
+ addrwin &= 0xc0;
+ exca_write_byte(slot, I365_ADDRWIN, addrwin);
+ break;
+ default:
+ break;
+ }
- socket = &vrc4171_sockets[slot];
- if (socket->noprobe != SLOT_PROBE) {
- uint8_t addrwin;
-
- switch (socket->noprobe) {
- case SLOT_NOPROBE_MEM:
- addrwin = exca_read_byte(slot, I365_ADDRWIN);
- addrwin &= 0x1f;
- exca_write_byte(slot, I365_ADDRWIN, addrwin);
- break;
- case SLOT_NOPROBE_IO:
- addrwin = exca_read_byte(slot, I365_ADDRWIN);
- addrwin &= 0xc0;
- exca_write_byte(slot, I365_ADDRWIN, addrwin);
- break;
- default:
- break;
+ reserve_using_irq(slot);
+ continue;
}
- reserve_using_irq(slot);
-
- return 0;
- }
-
- sprintf(socket->name, "NEC VRC4171 Card Slot %1c", 'A' + slot);
+ sprintf(socket->name, "NEC VRC4171 Card Slot %1c", 'A' + slot);
+ socket->pcmcia_socket.dev.dev = &vrc4171_card_device.dev;
+ socket->pcmcia_socket.ops = &vrc4171_pccard_operations;
+ socket->pcmcia_socket.owner = THIS_MODULE;
- socket->pcmcia_socket.ops = &vrc4171_pccard_operations;
-
- retval = pcmcia_register_socket(&socket->pcmcia_socket);
- if (retval != 0)
- return retval;
+ retval = pcmcia_register_socket(&socket->pcmcia_socket);
+ if (retval < 0)
+ return retval;
- exca_write_byte(slot, I365_ADDRWIN, 0);
+ exca_write_byte(slot, I365_ADDRWIN, 0);
+ exca_write_byte(slot, GLOBAL_CONTROL, 0);
- exca_write_byte(slot, GLOBAL_CONTROL, 0);
+ socket->slot = SLOT_INITIALIZED;
+ }
return 0;
}
-static void vrc4171_remove_socket(int slot)
+static void vrc4171_remove_sockets(void)
{
vrc4171_socket_t *socket;
+ int slot;
- if (slot >= CARD_MAX_SLOTS)
- return;
+ for (slot = 0; slot < CARD_MAX_SLOTS; slot++) {
+ if (slot == CARD_SLOTB && vrc4171_slotb == SLOTB_IS_NONE)
+ continue;
- socket = &vrc4171_sockets[slot];
+ socket = &vrc4171_sockets[slot];
+ if (socket->slot == SLOT_INITIALIZED)
+ pcmcia_unregister_socket(&socket->pcmcia_socket);
- pcmcia_unregister_socket(&socket->pcmcia_socket);
+ socket->slot = SLOT_PROBE;
+ }
}
static int __devinit vrc4171_card_setup(char *options)
@@ -644,13 +721,13 @@ static int __devinit vrc4171_card_setup(char *options)
options += 6;
if (*options != '\0') {
if (strncmp(options, "memnoprobe", 10) == 0) {
- vrc4171_sockets[CARD_SLOTA].noprobe = SLOT_NOPROBE_MEM;
+ vrc4171_sockets[CARD_SLOTA].slot = SLOT_NOPROBE_MEM;
options += 10;
} else if (strncmp(options, "ionoprobe", 9) == 0) {
- vrc4171_sockets[CARD_SLOTA].noprobe = SLOT_NOPROBE_IO;
+ vrc4171_sockets[CARD_SLOTA].slot = SLOT_NOPROBE_IO;
options += 9;
} else if ( strncmp(options, "noprobe", 7) == 0) {
- vrc4171_sockets[CARD_SLOTA].noprobe = SLOT_NOPROBE_ALL;
+ vrc4171_sockets[CARD_SLOTA].slot = SLOT_NOPROBE_ALL;
options += 7;
}
@@ -684,11 +761,11 @@ static int __devinit vrc4171_card_setup(char *options)
options++;
if (strncmp(options, "memnoprobe", 10) == 0)
- vrc4171_sockets[CARD_SLOTB].noprobe = SLOT_NOPROBE_MEM;
+ vrc4171_sockets[CARD_SLOTB].slot = SLOT_NOPROBE_MEM;
if (strncmp(options, "ionoprobe", 9) == 0)
- vrc4171_sockets[CARD_SLOTB].noprobe = SLOT_NOPROBE_IO;
+ vrc4171_sockets[CARD_SLOTB].slot = SLOT_NOPROBE_IO;
if (strncmp(options, "noprobe", 7) == 0)
- vrc4171_sockets[CARD_SLOTB].noprobe = SLOT_NOPROBE_ALL;
+ vrc4171_sockets[CARD_SLOTB].slot = SLOT_NOPROBE_ALL;
}
}
@@ -697,47 +774,72 @@ static int __devinit vrc4171_card_setup(char *options)
__setup("vrc4171_card=", vrc4171_card_setup);
-static int __devinit vrc4171_card_init(void)
+static int vrc4171_card_suspend(struct device *dev, u32 state, u32 level)
{
- int retval, slot;
+ int retval = 0;
- vrc4171_set_multifunction_pin(vrc4171_slotb);
+ if (level == SUSPEND_SAVE_STATE)
+ retval = pcmcia_socket_dev_suspend(dev, state);
- if (request_region(CARD_CONTROLLER_INDEX, CARD_CONTROLLER_SIZE,
- "NEC VRC4171 Card Controller") == NULL)
- return -EBUSY;
+ return retval;
+}
- for (slot = 0; slot < CARD_MAX_SLOTS; slot++) {
- if (slot == CARD_SLOTB && vrc4171_slotb == SLOTB_IS_NONE)
- break;
+static int vrc4171_card_resume(struct device *dev, u32 level)
+{
+ int retval = 0;
- retval = vrc4171_add_socket(slot);
- if (retval != 0)
- return retval;
- }
+ if (level == RESUME_RESTORE_STATE)
+ retval = pcmcia_socket_dev_resume(dev);
+
+ return retval;
+}
+
+static struct device_driver vrc4171_card_driver = {
+ .name = vrc4171_card_name,
+ .bus = &platform_bus_type,
+ .suspend = vrc4171_card_suspend,
+ .resume = vrc4171_card_resume,
+};
+
+static int __devinit vrc4171_card_init(void)
+{
+ int retval;
+
+ retval = driver_register(&vrc4171_card_driver);
+ if (retval < 0)
+ return retval;
- retval = request_irq(vrc4171_irq, pccard_interrupt, SA_SHIRQ,
- "NEC VRC4171 Card Controller", vrc4171_sockets);
+ retval = platform_device_register(&vrc4171_card_device);
if (retval < 0) {
- for (slot = 0; slot < CARD_MAX_SLOTS; slot++)
- vrc4171_remove_socket(slot);
+ driver_unregister(&vrc4171_card_driver);
+ return retval;
+ }
+
+ vrc4171_set_multifunction_pin(vrc4171_slotb);
+
+ retval = vrc4171_add_sockets();
+ if (retval == 0)
+ retval = request_irq(vrc4171_irq, pccard_interrupt, SA_SHIRQ,
+ vrc4171_card_name, vrc4171_sockets);
+ if (retval < 0) {
+ vrc4171_remove_sockets();
+ platform_device_unregister(&vrc4171_card_device);
+ driver_unregister(&vrc4171_card_driver);
return retval;
}
- printk(KERN_INFO "NEC VRC4171 Card Controller, connected to IRQ %d\n", vrc4171_irq);
+ printk(KERN_INFO "%s, connected to IRQ %d\n", vrc4171_card_driver.name, vrc4171_irq);
return 0;
}
static void __devexit vrc4171_card_exit(void)
{
- int slot;
-
- for (slot = 0; slot < CARD_MAX_SLOTS; slot++)
- vrc4171_remove_socket(slot);
-
- release_region(CARD_CONTROLLER_INDEX, CARD_CONTROLLER_SIZE);
+ free_irq(vrc4171_irq, vrc4171_sockets);
+ vrc4171_remove_sockets();
+ platform_device_unregister(&vrc4171_card_device);
+ driver_unregister(&vrc4171_card_driver);
}
module_init(vrc4171_card_init);
diff --git a/drivers/pcmcia/vrc4173_cardu.c b/drivers/pcmcia/vrc4173_cardu.c
index 49de11e785312..db91259dc50eb 100644
--- a/drivers/pcmcia/vrc4173_cardu.c
+++ b/drivers/pcmcia/vrc4173_cardu.c
@@ -141,11 +141,6 @@ static int cardu_init(unsigned int slot)
return 0;
}
-static int cardu_suspend(unsigned int slot)
-{
- return -EINVAL;
-}
-
static int cardu_register_callback(unsigned int sock,
void (*handler)(void *, unsigned int),
void * info)
@@ -433,7 +428,6 @@ static void cardu_proc_setup(unsigned int sock, struct proc_dir_entry *base)
static struct pccard_operations cardu_operations = {
.init = cardu_init,
- .suspend = cardu_suspend,
.register_callback = cardu_register_callback,
.inquire_socket = cardu_inquire_socket,
.get_status = cardu_get_status,
@@ -620,3 +614,4 @@ static void __devexit vrc4173_cardu_exit(void)
module_init(vrc4173_cardu_init);
module_exit(vrc4173_cardu_exit);
+MODULE_DEVICE_TABLE(pci, vrc4173_cardu_id_table);
diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c
index 9fae06ac2761c..6404d97a12ebc 100644
--- a/drivers/pcmcia/yenta_socket.c
+++ b/drivers/pcmcia/yenta_socket.c
@@ -506,8 +506,6 @@ static int yenta_sock_suspend(struct pcmcia_socket *sock)
{
struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
- yenta_set_socket(sock, &dead_socket);
-
/* Disable CSC interrupts */
cb_writel(socket, CB_SOCKET_MASK, 0x0);
@@ -963,7 +961,7 @@ static int __devinit yenta_probe (struct pci_dev *dev, const struct pci_device_i
* the irq stuff...
*/
printk(KERN_INFO "Yenta: CardBus bridge found at %s [%04x:%04x]\n",
- dev->slot_name, dev->subsystem_vendor, dev->subsystem_device);
+ pci_name(dev), dev->subsystem_vendor, dev->subsystem_device);
yenta_config_init(socket);
@@ -1019,7 +1017,7 @@ static int __devinit yenta_probe (struct pci_dev *dev, const struct pci_device_i
}
-static int yenta_dev_suspend (struct pci_dev *dev, u32 state)
+static int yenta_dev_suspend (struct pci_dev *dev, pm_message_t state)
{
struct yenta_socket *socket = pci_get_drvdata(dev);
int ret;
@@ -1105,6 +1103,7 @@ static struct pci_device_id yenta_table [] = {
CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_4410, TI12XX),
CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_4450, TI12XX),
CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_4451, TI12XX),
+ CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_4510, TI12XX),
CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_4520, TI12XX),
CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1250, TI1250),
diff --git a/drivers/pnp/core.c b/drivers/pnp/core.c
index 34029a39ef46c..deed92459bc5e 100644
--- a/drivers/pnp/core.c
+++ b/drivers/pnp/core.c
@@ -18,7 +18,7 @@
#include "base.h"
-LIST_HEAD(pnp_protocols);
+static LIST_HEAD(pnp_protocols);
LIST_HEAD(pnp_global);
DEFINE_SPINLOCK(pnp_lock);
diff --git a/drivers/pnp/interface.c b/drivers/pnp/interface.c
index 8527ae626fe12..53fac8ba5d5cb 100644
--- a/drivers/pnp/interface.c
+++ b/drivers/pnp/interface.c
@@ -29,7 +29,7 @@ struct pnp_info_buffer {
typedef struct pnp_info_buffer pnp_info_buffer_t;
-int pnp_printf(pnp_info_buffer_t * buffer, char *fmt,...)
+static int pnp_printf(pnp_info_buffer_t * buffer, char *fmt,...)
{
va_list args;
int res;
diff --git a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c
index 6ec4862425951..82c5edd5b9ee0 100644
--- a/drivers/pnp/isapnp/core.c
+++ b/drivers/pnp/isapnp/core.c
@@ -52,9 +52,9 @@
#endif
int isapnp_disable; /* Disable ISA PnP */
-int isapnp_rdp; /* Read Data Port */
-int isapnp_reset = 1; /* reset all PnP cards (deactivate) */
-int isapnp_verbose = 1; /* verbose mode */
+static int isapnp_rdp; /* Read Data Port */
+static int isapnp_reset = 1; /* reset all PnP cards (deactivate) */
+static int isapnp_verbose = 1; /* verbose mode */
MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
MODULE_DESCRIPTION("Generic ISA Plug & Play support");
@@ -121,7 +121,7 @@ unsigned char isapnp_read_byte(unsigned char idx)
return read_data();
}
-unsigned short isapnp_read_word(unsigned char idx)
+static unsigned short isapnp_read_word(unsigned char idx)
{
unsigned short val;
@@ -130,38 +130,19 @@ unsigned short isapnp_read_word(unsigned char idx)
return val;
}
-unsigned int isapnp_read_dword(unsigned char idx)
-{
- unsigned int val;
-
- val = isapnp_read_byte(idx);
- val = (val << 8) + isapnp_read_byte(idx+1);
- val = (val << 8) + isapnp_read_byte(idx+2);
- val = (val << 8) + isapnp_read_byte(idx+3);
- return val;
-}
-
void isapnp_write_byte(unsigned char idx, unsigned char val)
{
write_address(idx);
write_data(val);
}
-void isapnp_write_word(unsigned char idx, unsigned short val)
+static void isapnp_write_word(unsigned char idx, unsigned short val)
{
isapnp_write_byte(idx, val >> 8);
isapnp_write_byte(idx+1, val);
}
-void isapnp_write_dword(unsigned char idx, unsigned int val)
-{
- isapnp_write_byte(idx, val >> 24);
- isapnp_write_byte(idx+1, val >> 16);
- isapnp_write_byte(idx+2, val >> 8);
- isapnp_write_byte(idx+3, val);
-}
-
-void *isapnp_alloc(long size)
+static void *isapnp_alloc(long size)
{
void *result;
@@ -196,24 +177,24 @@ static void isapnp_wait(void)
isapnp_write_byte(0x02, 0x02);
}
-void isapnp_wake(unsigned char csn)
+static void isapnp_wake(unsigned char csn)
{
isapnp_write_byte(0x03, csn);
}
-void isapnp_device(unsigned char logdev)
+static void isapnp_device(unsigned char logdev)
{
isapnp_write_byte(0x07, logdev);
}
-void isapnp_activate(unsigned char logdev)
+static void isapnp_activate(unsigned char logdev)
{
isapnp_device(logdev);
isapnp_write_byte(ISAPNP_CFG_ACTIVATE, 1);
udelay(250);
}
-void isapnp_deactivate(unsigned char logdev)
+static void isapnp_deactivate(unsigned char logdev)
{
isapnp_device(logdev);
isapnp_write_byte(ISAPNP_CFG_ACTIVATE, 0);
@@ -972,13 +953,7 @@ EXPORT_SYMBOL(isapnp_present);
EXPORT_SYMBOL(isapnp_cfg_begin);
EXPORT_SYMBOL(isapnp_cfg_end);
EXPORT_SYMBOL(isapnp_read_byte);
-EXPORT_SYMBOL(isapnp_read_word);
-EXPORT_SYMBOL(isapnp_read_dword);
EXPORT_SYMBOL(isapnp_write_byte);
-EXPORT_SYMBOL(isapnp_write_word);
-EXPORT_SYMBOL(isapnp_write_dword);
-EXPORT_SYMBOL(isapnp_wake);
-EXPORT_SYMBOL(isapnp_device);
static int isapnp_read_resources(struct pnp_dev *dev, struct pnp_resource_table *res)
{
@@ -1070,7 +1045,7 @@ struct pnp_protocol isapnp_protocol = {
.disable = isapnp_disable_resources,
};
-int __init isapnp_init(void)
+static int __init isapnp_init(void)
{
int cards;
struct pnp_card *card;
diff --git a/drivers/pnp/manager.c b/drivers/pnp/manager.c
index 0cbdf9d414c49..639e04253482c 100644
--- a/drivers/pnp/manager.c
+++ b/drivers/pnp/manager.c
@@ -296,7 +296,7 @@ static void pnp_clean_resource_table(struct pnp_resource_table * res)
*
* Only set depnum to 0 if the device does not have dependent options.
*/
-int pnp_assign_resources(struct pnp_dev *dev, int depnum)
+static int pnp_assign_resources(struct pnp_dev *dev, int depnum)
{
struct pnp_port *port;
struct pnp_mem *mem;
@@ -558,7 +558,6 @@ void pnp_resource_change(struct resource *resource, unsigned long start, unsigne
}
-EXPORT_SYMBOL(pnp_assign_resources);
EXPORT_SYMBOL(pnp_manual_config_dev);
EXPORT_SYMBOL(pnp_auto_config_dev);
EXPORT_SYMBOL(pnp_activate_dev);
diff --git a/drivers/pnp/pnpbios/core.c b/drivers/pnp/pnpbios/core.c
index 0d1736c03b968..0f6330b3af12b 100644
--- a/drivers/pnp/pnpbios/core.c
+++ b/drivers/pnp/pnpbios/core.c
@@ -12,7 +12,7 @@
* Minor reorganizations by David Hinds <dahinds@users.sourceforge.net>
* Further modifications (C) 2001, 2002 by:
* Alan Cox <alan@redhat.com>
- * Thomas Hood <jdthood@mail.com>
+ * Thomas Hood
* Brian Gerst <bgerst@didntduck.org>
*
* Ported to the PnP Layer and several additional improvements (C) 2002
@@ -180,8 +180,12 @@ static int pnp_dock_thread(void * unused)
* Poll every 2 seconds
*/
msleep_interruptible(2000);
- if(signal_pending(current))
+
+ if(signal_pending(current)) {
+ if (try_to_freeze(PF_FREEZE))
+ continue;
break;
+ }
status = pnp_bios_dock_station_info(&now);
@@ -454,7 +458,7 @@ __setup("pnpbios=", pnpbios_setup);
/* PnP BIOS signature: "$PnP" */
#define PNP_SIGNATURE (('$' << 0) + ('P' << 8) + ('n' << 16) + ('P' << 24))
-int __init pnpbios_probe_system(void)
+static int __init pnpbios_probe_system(void)
{
union pnp_bios_install_struct *check;
u8 sum;
@@ -530,7 +534,7 @@ static struct dmi_system_id pnpbios_dmi_table[] = {
{ }
};
-int __init pnpbios_init(void)
+static int __init pnpbios_init(void)
{
int ret;
diff --git a/drivers/pnp/pnpbios/proc.c b/drivers/pnp/pnpbios/proc.c
index 2fa4d21c7eee7..6bb8e1973fd49 100644
--- a/drivers/pnp/pnpbios/proc.c
+++ b/drivers/pnp/pnpbios/proc.c
@@ -2,7 +2,7 @@
* /proc/bus/pnp interface for Plug and Play devices
*
* Written by David Hinds, dahinds@users.sourceforge.net
- * Modified by Thomas Hood, jdthood@mail.com
+ * Modified by Thomas Hood
*
* The .../devices and .../<node> and .../boot/<node> files are
* utilized by the lspnp and setpnp utilities, supplied with the
diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c
index 80a6979ef5186..2d1322dd7e196 100644
--- a/drivers/pnp/resource.c
+++ b/drivers/pnp/resource.c
@@ -21,11 +21,10 @@
#include <linux/pnp.h>
#include "base.h"
-int pnp_skip_pci_scan; /* skip PCI resource scanning */
-int pnp_reserve_irq[16] = { [0 ... 15] = -1 }; /* reserve (don't use) some IRQ */
-int pnp_reserve_dma[8] = { [0 ... 7] = -1 }; /* reserve (don't use) some DMA */
-int pnp_reserve_io[16] = { [0 ... 15] = -1 }; /* reserve (don't use) some I/O region */
-int pnp_reserve_mem[16] = { [0 ... 15] = -1 }; /* reserve (don't use) some memory region */
+static int pnp_reserve_irq[16] = { [0 ... 15] = -1 }; /* reserve (don't use) some IRQ */
+static int pnp_reserve_dma[8] = { [0 ... 7] = -1 }; /* reserve (don't use) some DMA */
+static int pnp_reserve_io[16] = { [0 ... 15] = -1 }; /* reserve (don't use) some I/O region */
+static int pnp_reserve_mem[16] = { [0 ... 15] = -1 }; /* reserve (don't use) some memory region */
/*
@@ -385,9 +384,9 @@ int pnp_check_irq(struct pnp_dev * dev, int idx)
#ifdef CONFIG_PCI
/* check if the resource is being used by a pci device */
- if (!pnp_skip_pci_scan) {
- struct pci_dev * pci = NULL;
- while ((pci = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pci)) != NULL) {
+ {
+ struct pci_dev *pci = NULL;
+ for_each_pci_dev(pci) {
if (pci->irq == *irq)
return 0;
}
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index 30837596ccaf9..b755bac6ccbca 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.156 $
+ * $Revision: 1.158 $
*/
#include <linux/config.h>
@@ -757,6 +757,17 @@ dasd_start_IO(struct dasd_ccw_req * cqr)
DBF_DEV_EVENT(DBF_ERR, device, "%s",
"start_IO: request timeout, retry later");
break;
+ case -EACCES:
+ /* -EACCES indicates that the request used only a
+ * subset of the available pathes and all these
+ * pathes are gone.
+ * Do a retry with all available pathes.
+ */
+ cqr->lpm = LPM_ANYPATH;
+ DBF_DEV_EVENT(DBF_ERR, device, "%s",
+ "start_IO: selected pathes gone,"
+ " retry on all pathes");
+ break;
case -ENODEV:
case -EIO:
DBF_DEV_EVENT(DBF_ERR, device, "%s",
@@ -1222,7 +1233,9 @@ __dasd_start_head(struct dasd_device * device)
rc = device->discipline->start_IO(cqr);
if (rc == 0)
dasd_set_timer(device, cqr->expires);
- else
+ else if (rc == -EACCES) {
+ dasd_schedule_bh(device);
+ } else
/* Hmpf, try again in 1/2 sec */
dasd_set_timer(device, 50);
}
@@ -1813,8 +1826,8 @@ dasd_generic_set_online (struct ccw_device *cdev,
if (rc) {
printk (KERN_WARNING
"dasd_generic couldn't online device %s "
- "with discipline %s\n",
- cdev->dev.bus_id, discipline->name);
+ "with discipline %s rc=%i\n",
+ cdev->dev.bus_id, discipline->name, rc);
dasd_delete_device(device);
return rc;
}
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index df8902364762d..838aedf78a561 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.68 $
+ * $Revision: 1.69 $
*/
#include <linux/config.h>
@@ -56,6 +56,7 @@ static struct dasd_discipline dasd_eckd_discipline;
struct dasd_eckd_private {
struct dasd_eckd_characteristics rdc_data;
struct dasd_eckd_confdata conf_data;
+ struct dasd_eckd_path path_data;
struct eckd_count count_area[5];
int init_cqr_status;
int uses_cdl;
@@ -447,12 +448,72 @@ dasd_eckd_cdl_reclen(int recid)
}
static int
+dasd_eckd_read_conf(struct dasd_device *device)
+{
+ void *conf_data;
+ int conf_len, conf_data_saved;
+ int rc;
+ __u8 lpm;
+ struct dasd_eckd_private *private;
+ struct dasd_eckd_path *path_data;
+
+ private = (struct dasd_eckd_private *) device->private;
+ path_data = (struct dasd_eckd_path *) &private->path_data;
+ path_data->opm = ccw_device_get_path_mask(device->cdev);
+ lpm = 0x80;
+ conf_data_saved = 0;
+
+ /* get configuration data per operational path */
+ for (lpm = 0x80; lpm; lpm>>= 1) {
+ if (lpm & path_data->opm){
+ rc = read_conf_data_lpm(device->cdev, &conf_data,
+ &conf_len, lpm);
+ if (rc && rc != -EOPNOTSUPP) { /* -EOPNOTSUPP is ok */
+ MESSAGE(KERN_WARNING,
+ "Read configuration data returned "
+ "error %d", rc);
+ return rc;
+ }
+ if (conf_data == NULL) {
+ MESSAGE(KERN_WARNING, "%s", "No configuration "
+ "data retrieved");
+ continue; /* no errror */
+ }
+ if (conf_len != sizeof (struct dasd_eckd_confdata)) {
+ MESSAGE(KERN_WARNING,
+ "sizes of configuration data mismatch"
+ "%d (read) vs %ld (expected)",
+ conf_len,
+ sizeof (struct dasd_eckd_confdata));
+ kfree(conf_data);
+ continue; /* no errror */
+ }
+ /* save first valid configuration data */
+ if (!conf_data_saved){
+ memcpy(&private->conf_data, conf_data,
+ sizeof (struct dasd_eckd_confdata));
+ conf_data_saved++;
+ }
+ switch (((char *)conf_data)[242] & 0x07){
+ case 0x02:
+ path_data->npm |= lpm;
+ break;
+ case 0x03:
+ path_data->ppm |= lpm;
+ break;
+ }
+ kfree(conf_data);
+ }
+ }
+ return 0;
+}
+
+
+static int
dasd_eckd_check_characteristics(struct dasd_device *device)
{
struct dasd_eckd_private *private;
void *rdc_data;
- void *conf_data;
- int conf_len;
int rc;
private = (struct dasd_eckd_private *) device->private;
@@ -465,6 +526,7 @@ dasd_eckd_check_characteristics(struct dasd_device *device)
"data");
return -ENOMEM;
}
+ memset(private, 0, sizeof(struct dasd_eckd_private));
device->private = (void *) private;
}
/* Invalidate status of initial analysis. */
@@ -494,30 +556,9 @@ dasd_eckd_check_characteristics(struct dasd_device *device)
private->rdc_data.sec_per_trk);
/* Read Configuration Data */
- rc = read_conf_data(device->cdev, &conf_data, &conf_len);
- if (rc && rc != -EOPNOTSUPP) { /* -EOPNOTSUPP is ok */
- DEV_MESSAGE(KERN_WARNING, device,
- "Read configuration data returned error %d", rc);
- return rc;
- }
- if (conf_data == NULL) {
- DEV_MESSAGE(KERN_WARNING, device, "%s",
- "No configuration data retrieved");
- return 0; /* no errror */
- }
- if (conf_len != sizeof (struct dasd_eckd_confdata)) {
- DEV_MESSAGE(KERN_WARNING, device,
- "sizes of configuration data mismatch"
- "%d (read) vs %ld (expected)",
- conf_len, sizeof (struct dasd_eckd_confdata));
+ rc = dasd_eckd_read_conf (device);
+ return rc;
- kfree(conf_data); /* allocated by read_conf_data() */
- return 0; /* no errror */
- }
- memcpy(&private->conf_data, conf_data,
- sizeof (struct dasd_eckd_confdata));
- kfree(conf_data); /* allocated by read_conf_data() */
- return 0;
}
static struct dasd_ccw_req *
@@ -1096,7 +1137,7 @@ dasd_eckd_build_cp(struct dasd_device * device, struct request *req)
}
cqr->device = device;
cqr->expires = 5 * 60 * HZ; /* 5 minutes */
- cqr->lpm = LPM_ANYPATH;
+ cqr->lpm = private->path_data.ppm;
cqr->retries = 256;
cqr->buildclk = get_clock();
cqr->status = DASD_CQR_FILLED;
diff --git a/drivers/s390/block/dasd_eckd.h b/drivers/s390/block/dasd_eckd.h
index 3e1a051d4ab83..b6888c68b2244 100644
--- a/drivers/s390/block/dasd_eckd.h
+++ b/drivers/s390/block/dasd_eckd.h
@@ -5,7 +5,7 @@
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
*
- * $Revision: 1.9 $
+ * $Revision: 1.10 $
*/
#ifndef DASD_ECKD_H
@@ -326,6 +326,12 @@ struct dasd_eckd_confdata {
} __attribute__ ((packed)) neq;
} __attribute__ ((packed));
+struct dasd_eckd_path {
+ __u8 opm;
+ __u8 ppm;
+ __u8 npm;
+};
+
/*
* Perform Subsystem Function - Prepare for Read Subsystem Data
*/
diff --git a/drivers/s390/block/dasd_erp.c b/drivers/s390/block/dasd_erp.c
index 82a864719e2e3..7cb98d25f3416 100644
--- a/drivers/s390/block/dasd_erp.c
+++ b/drivers/s390/block/dasd_erp.c
@@ -7,7 +7,7 @@
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001
*
- * $Revision: 1.13 $
+ * $Revision: 1.14 $
*/
#include <linux/config.h>
@@ -95,6 +95,7 @@ dasd_default_erp_action(struct dasd_ccw_req * cqr)
DEV_MESSAGE (KERN_DEBUG, device,
"default ERP called (%i retries left)",
cqr->retries);
+ cqr->lpm = LPM_ANYPATH;
cqr->status = DASD_CQR_QUEUED;
} else {
DEV_MESSAGE (KERN_WARNING, device, "%s",
diff --git a/drivers/s390/char/keyboard.c b/drivers/s390/char/keyboard.c
index 5e35728db92e8..fd43d99b45a33 100644
--- a/drivers/s390/char/keyboard.c
+++ b/drivers/s390/char/keyboard.c
@@ -32,11 +32,11 @@ static k_handler_fn K_HANDLERS;
static k_handler_fn *k_handler[16] = { K_HANDLERS };
/* maximum values each key_handler can handle */
-static const int max_vals[] = {
+static const int kbd_max_vals[] = {
255, ARRAY_SIZE(func_table) - 1, NR_FN_HANDLER - 1, 0,
NR_DEAD - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
-static const int NR_TYPES = ARRAY_SIZE(max_vals);
+static const int KBD_NR_TYPES = ARRAY_SIZE(kbd_max_vals);
static unsigned char ret_diacr[NR_DEAD] = {
'`', '\'', '^', '~', '"', ','
@@ -360,7 +360,7 @@ do_kdsk_ioctl(struct kbd_data *kbd, struct kbentry __user *user_kbe,
key_map = kbd->key_maps[tmp.kb_table];
if (key_map) {
val = U(key_map[tmp.kb_index]);
- if (KTYP(val) >= NR_TYPES)
+ if (KTYP(val) >= KBD_NR_TYPES)
val = K_HOLE;
} else
val = (tmp.kb_index ? K_HOLE : K_NOSUCHMAP);
@@ -378,9 +378,9 @@ do_kdsk_ioctl(struct kbd_data *kbd, struct kbentry __user *user_kbe,
break;
}
- if (KTYP(tmp.kb_value) >= NR_TYPES)
+ if (KTYP(tmp.kb_value) >= KBD_NR_TYPES)
return -EINVAL;
- if (KVAL(tmp.kb_value) > max_vals[KTYP(tmp.kb_value)])
+ if (KVAL(tmp.kb_value) > kbd_max_vals[KTYP(tmp.kb_value)])
return -EINVAL;
if (!(key_map = kbd->key_maps[tmp.kb_table])) {
diff --git a/drivers/s390/char/sclp_quiesce.c b/drivers/s390/char/sclp_quiesce.c
index 924c5dc9f7f47..83f75774df602 100644
--- a/drivers/s390/char/sclp_quiesce.c
+++ b/drivers/s390/char/sclp_quiesce.c
@@ -30,31 +30,16 @@ do_load_quiesce_psw(void * __unused)
{
static atomic_t cpuid = ATOMIC_INIT(-1);
psw_t quiesce_psw;
- __u32 status;
- int i;
+ int cpu;
if (atomic_compare_and_swap(-1, smp_processor_id(), &cpuid))
signal_processor(smp_processor_id(), sigp_stop);
/* Wait for all other cpus to enter stopped state */
- i = 1;
- while (i < NR_CPUS) {
- if (!cpu_online(i)) {
- i++;
+ for_each_online_cpu(cpu) {
+ if (cpu == smp_processor_id())
continue;
- }
- switch (signal_processor_ps(&status, 0, i, sigp_sense)) {
- case sigp_order_code_accepted:
- case sigp_status_stored:
- /* Check for stopped and check stop state */
- if (status & 0x50)
- i++;
- break;
- case sigp_busy:
- break;
- case sigp_not_operational:
- i++;
- break;
- }
+ while(!smp_cpu_not_running(cpu))
+ cpu_relax();
}
/* Quiesce the last cpu with the special psw */
quiesce_psw.mask = PSW_BASE_BITS | PSW_MASK_WAIT;
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c
index de60cfd4550a4..b35fe12e6bfc5 100644
--- a/drivers/s390/cio/chsc.c
+++ b/drivers/s390/cio/chsc.c
@@ -1,7 +1,7 @@
/*
* drivers/s390/cio/chsc.c
* S/390 common I/O routines -- channel subsystem call
- * $Revision: 1.115 $
+ * $Revision: 1.119 $
*
* Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
@@ -423,12 +423,12 @@ s390_process_res_acc (u8 chpid, __u16 fla, u32 fla_mask)
sch->schib.pmcw.pam &
sch->schib.pmcw.pom)
| chp_mask) & sch->opm;
- spin_unlock_irq(&sch->lock);
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 != 0)
break;
@@ -703,6 +703,9 @@ __check_for_io_and_kill(struct subchannel *sch, int index)
{
int cc;
+ if (!device_is_online(sch))
+ /* cio could be doing I/O. */
+ return 0;
cc = stsch(sch->irq, &sch->schib);
if (cc)
return 0;
@@ -717,10 +720,12 @@ static inline void
__s390_subchannel_vary_chpid(struct subchannel *sch, __u8 chpid, int on)
{
int chp, old_lpm;
+ unsigned long flags;
if (!sch->ssd_info.valid)
return;
+ spin_lock_irqsave(&sch->lock, flags);
old_lpm = sch->lpm;
for (chp = 0; chp < 8; chp++) {
if (sch->ssd_info.chpid[chp] != chpid)
@@ -751,6 +756,7 @@ __s390_subchannel_vary_chpid(struct subchannel *sch, __u8 chpid, int on)
}
break;
}
+ spin_unlock_irqrestore(&sch->lock, flags);
}
static int
@@ -881,6 +887,27 @@ chp_status_write(struct device *dev, const char *buf, size_t count)
static DEVICE_ATTR(status, 0644, chp_status_show, chp_status_write);
+static ssize_t
+chp_type_show(struct device *dev, char *buf)
+{
+ struct channel_path *chp = container_of(dev, struct channel_path, dev);
+
+ if (!chp)
+ return 0;
+ return sprintf(buf, "%x\n", chp->desc.desc);
+}
+
+static DEVICE_ATTR(type, 0444, chp_type_show, NULL);
+
+static struct attribute * chp_attrs[] = {
+ &dev_attr_status.attr,
+ &dev_attr_type.attr,
+ NULL,
+};
+
+static struct attribute_group chp_attr_group = {
+ .attrs = chp_attrs,
+};
static void
chp_release(struct device *dev)
@@ -891,6 +918,68 @@ chp_release(struct device *dev)
kfree(cp);
}
+static int
+chsc_determine_channel_path_description(int chpid,
+ struct channel_path_desc *desc)
+{
+ int ccode, ret;
+
+ struct {
+ struct chsc_header request;
+ u32 : 24;
+ u32 first_chpid : 8;
+ u32 : 24;
+ u32 last_chpid : 8;
+ u32 zeroes1;
+ struct chsc_header response;
+ u32 zeroes2;
+ struct channel_path_desc desc;
+ } *scpd_area;
+
+ scpd_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
+ if (!scpd_area)
+ return -ENOMEM;
+
+ scpd_area->request = (struct chsc_header) {
+ .length = 0x0010,
+ .code = 0x0002,
+ };
+
+ scpd_area->first_chpid = chpid;
+ scpd_area->last_chpid = chpid;
+
+ ccode = chsc(scpd_area);
+ if (ccode > 0) {
+ ret = (ccode == 3) ? -ENODEV : -EBUSY;
+ goto out;
+ }
+
+ switch (scpd_area->response.code) {
+ case 0x0001: /* Success. */
+ memcpy(desc, &scpd_area->desc,
+ sizeof(struct channel_path_desc));
+ ret = 0;
+ break;
+ case 0x0003: /* Invalid block. */
+ case 0x0007: /* Invalid format. */
+ case 0x0008: /* Other invalid block. */
+ CIO_CRW_EVENT(2, "Error in chsc request block!\n");
+ ret = -EINVAL;
+ break;
+ case 0x0004: /* Command not provided in model. */
+ CIO_CRW_EVENT(2, "Model does not provide scpd\n");
+ ret = -EOPNOTSUPP;
+ break;
+ default:
+ CIO_CRW_EVENT(2, "Unknown CHSC response %d\n",
+ scpd_area->response.code);
+ ret = -EIO;
+ }
+out:
+ free_page((unsigned long)scpd_area);
+ return ret;
+}
+
/*
* Entries for chpids on the system bus.
* This replaces /proc/chpids.
@@ -915,6 +1004,11 @@ new_channel_path(int chpid)
};
snprintf(chp->dev.bus_id, BUS_ID_SIZE, "chp0.%x", chpid);
+ /* Obtain channel path description and fill it in. */
+ ret = chsc_determine_channel_path_description(chpid, &chp->desc);
+ if (ret)
+ goto out_free;
+
/* make it known to the system */
ret = device_register(&chp->dev);
if (ret) {
@@ -922,7 +1016,7 @@ new_channel_path(int chpid)
__func__, chpid);
goto out_free;
}
- ret = device_create_file(&chp->dev, &dev_attr_status);
+ ret = sysfs_create_group(&chp->dev.kobj, &chp_attr_group);
if (ret) {
device_unregister(&chp->dev);
goto out_free;
@@ -934,6 +1028,23 @@ out_free:
return ret;
}
+void *
+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]];
+ if (!chp)
+ return NULL;
+ desc = kmalloc(sizeof(struct channel_path_desc), GFP_KERNEL);
+ if (!desc)
+ return NULL;
+ memcpy(desc, &chp->desc, sizeof(struct channel_path_desc));
+ return desc;
+}
+
+
static int __init
chsc_alloc_sei_area(void)
{
diff --git a/drivers/s390/cio/chsc.h b/drivers/s390/cio/chsc.h
index a3390f99ab4cf..be20da49d147b 100644
--- a/drivers/s390/cio/chsc.h
+++ b/drivers/s390/cio/chsc.h
@@ -12,14 +12,24 @@ struct chsc_header {
u16 code;
};
+struct channel_path_desc {
+ u8 flags;
+ u8 lsn;
+ u8 desc;
+ u8 chpid;
+ u8 swla;
+ u8 zeroes;
+ u8 chla;
+ u8 chpp;
+};
+
struct channel_path {
int id;
int state;
+ struct channel_path_desc desc;
struct device dev;
};
-extern struct channel_path *chps[];
-
extern void s390_process_css( void );
extern void chsc_validate_chpids(struct subchannel *);
extern void chpid_is_actually_online(int);
@@ -51,4 +61,6 @@ extern struct css_chsc_char css_chsc_characteristics;
extern int chsc_determine_css_characteristics(void);
extern int css_characteristics_avail;
+
+extern void *chsc_get_chp_desc(struct subchannel*, int);
#endif
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index b6e4d3402b363..99ce5a567982a 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -1,7 +1,7 @@
/*
* drivers/s390/cio/cio.c
* S/390 common I/O routines -- low level i/o calls
- * $Revision: 1.130 $
+ * $Revision: 1.131 $
*
* Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
@@ -608,6 +608,10 @@ do_IRQ (struct pt_regs *regs)
irq_enter ();
asm volatile ("mc 0,0");
if (S390_lowcore.int_clock >= S390_lowcore.jiffy_timer)
+ /**
+ * Make sure that the i/o interrupt did not "overtake"
+ * the last HZ timer interrupt.
+ */
account_ticks(regs);
/*
* Get interrupt information from lowcore
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
index 948b3b158dd85..87bd70eeabed7 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -1,7 +1,7 @@
/*
* drivers/s390/cio/css.c
* driver for channel subsystem
- * $Revision: 1.84 $
+ * $Revision: 1.85 $
*
* Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
@@ -180,6 +180,7 @@ css_evaluate_subchannel(int irq, int slow)
{
int event, ret, disc;
struct subchannel *sch;
+ unsigned long flags;
sch = get_subchannel_by_schid(irq);
disc = sch ? device_is_disconnected(sch) : 0;
@@ -221,7 +222,9 @@ css_evaluate_subchannel(int irq, int slow)
* coming operational again. It won't do harm in real
* no path situations.
*/
+ spin_lock_irqsave(&sch->lock, flags);
device_trigger_reprobe(sch);
+ spin_unlock_irqrestore(&sch->lock, flags);
ret = 0;
break;
}
@@ -262,14 +265,19 @@ css_evaluate_subchannel(int irq, int slow)
* We can't immediately deregister the disconnected
* device since it might block.
*/
+ spin_lock_irqsave(&sch->lock, flags);
device_trigger_reprobe(sch);
+ spin_unlock_irqrestore(&sch->lock, flags);
ret = 0;
}
break;
case CIO_OPER:
- if (disc)
+ if (disc) {
+ spin_lock_irqsave(&sch->lock, flags);
/* Get device operational again. */
device_trigger_reprobe(sch);
+ spin_unlock_irqrestore(&sch->lock, flags);
+ }
ret = sch ? 0 : css_probe_device(irq);
break;
default:
diff --git a/drivers/s390/cio/css.h b/drivers/s390/cio/css.h
index 8ab01af597b1f..2004a6c49388e 100644
--- a/drivers/s390/cio/css.h
+++ b/drivers/s390/cio/css.h
@@ -84,6 +84,7 @@ struct ccw_device_private {
unsigned int doverify:1; /* delayed path verification */
unsigned int donotify:1; /* call notify function */
unsigned int recog_done:1; /* dev. recog. complete */
+ unsigned int fake_irb:1; /* deliver faked irb */
} __attribute__((packed)) flags;
unsigned long intparm; /* user interruption parameter */
struct qdio_irq *qdio_data;
@@ -136,6 +137,7 @@ void device_set_disconnected(struct subchannel *);
void device_trigger_reprobe(struct subchannel *);
/* Helper functions for vary on/off. */
+int device_is_online(struct subchannel *);
void device_set_waiting(struct subchannel *);
/* Machine check helper function. */
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index 7b6f85b3e42cb..df0325505e4e3 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -1,7 +1,7 @@
/*
* drivers/s390/cio/device.c
* bus driver for ccw devices
- * $Revision: 1.129 $
+ * $Revision: 1.131 $
*
* Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
@@ -293,6 +293,14 @@ ccw_device_set_offline(struct ccw_device *cdev)
cdev->online = 0;
spin_lock_irq(cdev->ccwlock);
ret = ccw_device_offline(cdev);
+ if (ret == -ENODEV) {
+ if (cdev->private->state != DEV_STATE_NOT_OPER) {
+ cdev->private->state = DEV_STATE_OFFLINE;
+ dev_fsm_event(cdev, DEV_EVENT_NOTOPER);
+ }
+ spin_unlock_irq(cdev->ccwlock);
+ return ret;
+ }
spin_unlock_irq(cdev->ccwlock);
if (ret == 0)
wait_event(cdev->private->wait_q, dev_fsm_final_state(cdev));
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
index cacebad072a8b..9b7f6f548b1df 100644
--- a/drivers/s390/cio/device_fsm.c
+++ b/drivers/s390/cio/device_fsm.c
@@ -24,6 +24,17 @@
#include "qdio.h"
int
+device_is_online(struct subchannel *sch)
+{
+ struct ccw_device *cdev;
+
+ if (!sch->dev.driver_data)
+ return 0;
+ cdev = sch->dev.driver_data;
+ return (cdev->private->state == DEV_STATE_ONLINE);
+}
+
+int
device_is_disconnected(struct subchannel *sch)
{
struct ccw_device *cdev;
@@ -44,6 +55,7 @@ device_set_disconnected(struct subchannel *sch)
return;
cdev = sch->dev.driver_data;
ccw_device_set_timeout(cdev, 0);
+ cdev->private->flags.fake_irb = 0;
cdev->private->state = DEV_STATE_DISCONNECTED;
}
@@ -474,6 +486,7 @@ ccw_device_nopath_notify(void *data)
} else {
cio_disable_subchannel(sch);
ccw_device_set_timeout(cdev, 0);
+ cdev->private->flags.fake_irb = 0;
cdev->private->state = DEV_STATE_DISCONNECTED;
wake_up(&cdev->private->wait_q);
}
@@ -488,6 +501,21 @@ ccw_device_verify_done(struct ccw_device *cdev, int err)
cdev->private->options.pgroup = 0;
case 0:
ccw_device_done(cdev, DEV_STATE_ONLINE);
+ /* Deliver fake irb to device driver, if needed. */
+ if (cdev->private->flags.fake_irb) {
+ memset(&cdev->private->irb, 0, sizeof(struct irb));
+ cdev->private->irb.scsw = (struct scsw) {
+ .cc = 1,
+ .fctl = SCSW_FCTL_START_FUNC,
+ .actl = SCSW_ACTL_START_PEND,
+ .stctl = SCSW_STCTL_STATUS_PEND,
+ };
+ cdev->private->flags.fake_irb = 0;
+ if (cdev->handler)
+ cdev->handler(cdev, cdev->private->intparm,
+ &cdev->private->irb);
+ memset(&cdev->private->irb, 0, sizeof(struct irb));
+ }
break;
case -ETIME:
ccw_device_done(cdev, DEV_STATE_BOXED);
@@ -560,6 +588,8 @@ 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)
+ return -ENODEV;
if (cdev->private->state != DEV_STATE_ONLINE) {
if (sch->schib.scsw.actl != 0)
return -EBUSY;
@@ -619,9 +649,11 @@ ccw_device_offline_notoper(struct ccw_device *cdev, enum dev_event dev_event)
cdev->private->state = DEV_STATE_NOT_OPER;
sch = to_subchannel(cdev->dev.parent);
- device_unregister(&sch->dev);
- sch->schib.pmcw.intparm = 0;
- cio_modify(sch);
+ if (get_device(&cdev->dev)) {
+ PREPARE_WORK(&cdev->private->kick_work,
+ ccw_device_call_sch_unregister, (void *)cdev);
+ queue_work(ccw_device_work, &cdev->private->kick_work);
+ }
wake_up(&cdev->private->wait_q);
}
@@ -637,6 +669,7 @@ ccw_device_online_notoper(struct ccw_device *cdev, enum dev_event dev_event)
if (sch->driver->notify &&
sch->driver->notify(&sch->dev, sch->lpm ? CIO_GONE : CIO_NO_PATH)) {
ccw_device_set_timeout(cdev, 0);
+ cdev->private->flags.fake_irb = 0;
cdev->private->state = DEV_STATE_DISCONNECTED;
wake_up(&cdev->private->wait_q);
return;
@@ -647,9 +680,11 @@ ccw_device_online_notoper(struct ccw_device *cdev, enum dev_event dev_event)
// FIXME: not-oper indication to device driver ?
ccw_device_call_handler(cdev);
}
- device_unregister(&sch->dev);
- sch->schib.pmcw.intparm = 0;
- cio_modify(sch);
+ if (get_device(&cdev->dev)) {
+ PREPARE_WORK(&cdev->private->kick_work,
+ ccw_device_call_sch_unregister, (void *)cdev);
+ queue_work(ccw_device_work, &cdev->private->kick_work);
+ }
wake_up(&cdev->private->wait_q);
}
@@ -668,6 +703,12 @@ ccw_device_online_verify(struct ccw_device *cdev, enum dev_event dev_event)
return;
}
sch = to_subchannel(cdev->dev.parent);
+ /*
+ * Since we might not just be coming from an interrupt from the
+ * subchannel we have to update the schib.
+ */
+ stsch(sch->irq, &sch->schib);
+
if (sch->schib.scsw.actl != 0 ||
(cdev->private->irb.scsw.stctl & SCSW_STCTL_STATUS_PEND)) {
/*
@@ -982,21 +1023,17 @@ void
device_trigger_reprobe(struct subchannel *sch)
{
struct ccw_device *cdev;
- unsigned long flags;
if (!sch->dev.driver_data)
return;
cdev = sch->dev.driver_data;
- spin_lock_irqsave(&sch->lock, flags);
- if (cdev->private->state != DEV_STATE_DISCONNECTED) {
- spin_unlock_irqrestore(&sch->lock, flags);
+ if (cdev->private->state != DEV_STATE_DISCONNECTED)
return;
- }
+
/* Update some values. */
- if (stsch(sch->irq, &sch->schib)) {
- spin_unlock_irqrestore(&sch->lock, flags);
+ if (stsch(sch->irq, &sch->schib))
return;
- }
+
/*
* The pim, pam, pom values may not be accurate, but they are the best
* we have before performing device selection :/
@@ -1014,7 +1051,6 @@ device_trigger_reprobe(struct subchannel *sch)
sch->schib.pmcw.intparm = (__u32)(unsigned long)sch;
/* We should also udate ssd info, but this has to wait. */
ccw_device_start_id(cdev, 0);
- spin_unlock_irqrestore(&sch->lock, flags);
}
static void
diff --git a/drivers/s390/cio/device_id.c b/drivers/s390/cio/device_id.c
index 9e5840fc6b21b..0e68fb511dc93 100644
--- a/drivers/s390/cio/device_id.c
+++ b/drivers/s390/cio/device_id.c
@@ -316,6 +316,7 @@ ccw_device_sense_id_irq(struct ccw_device *cdev, enum dev_event dev_event)
if (ccw_device_accumulate_and_sense(cdev, irb) != 0)
return;
ret = ccw_device_check_sense_id(cdev);
+ memset(&cdev->private->irb, 0, sizeof(struct irb));
switch (ret) {
/* 0, -ETIME, -EOPNOTSUPP, -EAGAIN or -EACCES */
case 0: /* Sense id succeeded. */
diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c
index ef1d4df8f9754..11e260e0b9c92 100644
--- a/drivers/s390/cio/device_ops.c
+++ b/drivers/s390/cio/device_ops.c
@@ -1,7 +1,7 @@
/*
* drivers/s390/cio/device_ops.c
*
- * $Revision: 1.53 $
+ * $Revision: 1.55 $
*
* Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
@@ -24,6 +24,7 @@
#include "cio.h"
#include "cio_debug.h"
#include "css.h"
+#include "chsc.h"
#include "device.h"
#include "qdio.h"
@@ -81,6 +82,16 @@ ccw_device_start_key(struct ccw_device *cdev, struct ccw1 *cpa,
return -ENODEV;
if (cdev->private->state == DEV_STATE_NOT_OPER)
return -ENODEV;
+ if (cdev->private->state == DEV_STATE_VERIFY) {
+ /* Remember to fake irb when finished. */
+ if (!cdev->private->flags.fake_irb) {
+ cdev->private->flags.fake_irb = 1;
+ cdev->private->intparm = intparm;
+ return 0;
+ } else
+ /* There's already a fake I/O around. */
+ return -EBUSY;
+ }
if (cdev->private->state != DEV_STATE_ONLINE ||
((sch->schib.scsw.stctl & SCSW_STCTL_PRIM_STATUS) &&
!(sch->schib.scsw.stctl & SCSW_STCTL_SEC_STATUS)) ||
@@ -281,14 +292,14 @@ ccw_device_wake_up(struct ccw_device *cdev, unsigned long ip, struct irb *irb)
}
static inline int
-__ccw_device_retry_loop(struct ccw_device *cdev, struct ccw1 *ccw, long magic)
+__ccw_device_retry_loop(struct ccw_device *cdev, struct ccw1 *ccw, long magic, __u8 lpm)
{
int ret;
struct subchannel *sch;
sch = to_subchannel(cdev->dev.parent);
do {
- ret = cio_start (sch, ccw, 0);
+ ret = cio_start (sch, ccw, lpm);
if ((ret == -EBUSY) || (ret == -EACCES)) {
/* Try again later. */
spin_unlock_irq(&sch->lock);
@@ -378,7 +389,7 @@ read_dev_chars (struct ccw_device *cdev, void **buffer, int length)
ret = -EBUSY;
else
/* 0x00D9C4C3 == ebcdic "RDC" */
- ret = __ccw_device_retry_loop(cdev, rdc_ccw, 0x00D9C4C3);
+ ret = __ccw_device_retry_loop(cdev, rdc_ccw, 0x00D9C4C3, 0);
/* Restore interrupt handler. */
cdev->handler = handler;
@@ -391,10 +402,10 @@ read_dev_chars (struct ccw_device *cdev, void **buffer, int length)
}
/*
- * Read Configuration data
+ * Read Configuration data using path mask
*/
int
-read_conf_data (struct ccw_device *cdev, void **buffer, int *length)
+read_conf_data_lpm (struct ccw_device *cdev, void **buffer, int *length, __u8 lpm)
{
void (*handler)(struct ccw_device *, unsigned long, struct irb *);
struct subchannel *sch;
@@ -447,7 +458,7 @@ read_conf_data (struct ccw_device *cdev, void **buffer, int *length)
ret = -EBUSY;
else
/* 0x00D9C3C4 == ebcdic "RCD" */
- ret = __ccw_device_retry_loop(cdev, rcd_ccw, 0x00D9C3C4);
+ ret = __ccw_device_retry_loop(cdev, rcd_ccw, 0x00D9C3C4, lpm);
/* Restore interrupt handler. */
cdev->handler = handler;
@@ -470,6 +481,15 @@ read_conf_data (struct ccw_device *cdev, void **buffer, int *length)
}
/*
+ * Read Configuration data
+ */
+int
+read_conf_data (struct ccw_device *cdev, void **buffer, int *length)
+{
+ return read_conf_data_lpm (cdev, buffer, length, 0);
+}
+
+/*
* Try to break the lock on a boxed device.
*/
int
@@ -540,6 +560,15 @@ out_unlock:
return ret;
}
+void *
+ccw_device_get_chp_desc(struct ccw_device *cdev, int chp_no)
+{
+ struct subchannel *sch;
+
+ sch = to_subchannel(cdev->dev.parent);
+ return chsc_get_chp_desc(sch, chp_no);
+}
+
// FIXME: these have to go:
int
@@ -570,3 +599,5 @@ EXPORT_SYMBOL(read_conf_data);
EXPORT_SYMBOL(read_dev_chars);
EXPORT_SYMBOL(_ccw_device_get_subchannel_number);
EXPORT_SYMBOL(_ccw_device_get_device_number);
+EXPORT_SYMBOL_GPL(ccw_device_get_chp_desc);
+EXPORT_SYMBOL_GPL(read_conf_data_lpm);
diff --git a/drivers/s390/cio/device_pgid.c b/drivers/s390/cio/device_pgid.c
index 7a808019956ea..0adac8a67331e 100644
--- a/drivers/s390/cio/device_pgid.c
+++ b/drivers/s390/cio/device_pgid.c
@@ -156,7 +156,9 @@ ccw_device_sense_pgid_irq(struct ccw_device *cdev, enum dev_event dev_event)
if (ccw_device_accumulate_and_sense(cdev, irb) != 0)
return;
sch = to_subchannel(cdev->dev.parent);
- switch (__ccw_device_check_sense_pgid(cdev)) {
+ ret = __ccw_device_check_sense_pgid(cdev);
+ memset(&cdev->private->irb, 0, sizeof(struct irb));
+ switch (ret) {
/* 0, -ETIME, -EOPNOTSUPP, -EAGAIN, -EACCES or -EUSERS */
case 0: /* Sense Path Group ID successful. */
if (cdev->private->pgid.inf.ps.state1 == SNID_STATE1_RESET)
@@ -307,6 +309,7 @@ ccw_device_verify_irq(struct ccw_device *cdev, enum dev_event dev_event)
{
struct subchannel *sch;
struct irb *irb;
+ int ret;
irb = (struct irb *) __LC_IRB;
/* Retry set pgid for cc=1. */
@@ -319,7 +322,9 @@ ccw_device_verify_irq(struct ccw_device *cdev, enum dev_event dev_event)
if (ccw_device_accumulate_and_sense(cdev, irb) != 0)
return;
sch = to_subchannel(cdev->dev.parent);
- switch (__ccw_device_check_pgid(cdev)) {
+ ret = __ccw_device_check_pgid(cdev);
+ memset(&cdev->private->irb, 0, sizeof(struct irb));
+ switch (ret) {
/* 0, -ETIME, -EAGAIN, -EOPNOTSUPP or -EACCES */
case 0:
/* Establish or Resign Path Group done. Update vpm. */
@@ -405,6 +410,7 @@ ccw_device_disband_irq(struct ccw_device *cdev, enum dev_event dev_event)
return;
sch = to_subchannel(cdev->dev.parent);
ret = __ccw_device_check_pgid(cdev);
+ memset(&cdev->private->irb, 0, sizeof(struct irb));
switch (ret) {
/* 0, -ETIME, -EAGAIN, -EOPNOTSUPP or -EACCES */
case 0: /* disband successful. */
diff --git a/drivers/s390/crypto/z90main.c b/drivers/s390/crypto/z90main.c
index ab92dea8cd08e..a98c00c025592 100644
--- a/drivers/s390/crypto/z90main.c
+++ b/drivers/s390/crypto/z90main.c
@@ -2657,8 +2657,8 @@ z90crypt_reader_task(unsigned long ptr)
/**
* we use workavail = 2 to ensure 2 passes with nothing dequeued before
- * exiting the loop. If pendingq_count == 0 after the loop, there is no
- * work remaining on the queues.
+ * exiting the loop. If (pendingq_count+requestq_count) == 0 after the
+ * loop, there is no work remaining on the queues.
*/
resp_addr = 0;
workavail = 2;
@@ -2697,7 +2697,7 @@ z90crypt_reader_task(unsigned long ptr)
spin_unlock_irq(&queuespinlock);
}
- if (pendingq_count)
+ if (pendingq_count + requestq_count)
z90crypt_schedule_reader_timer();
}
diff --git a/drivers/s390/net/Kconfig b/drivers/s390/net/Kconfig
index 7899560dbfa44..a7efc394515e1 100644
--- a/drivers/s390/net/Kconfig
+++ b/drivers/s390/net/Kconfig
@@ -50,6 +50,15 @@ config SMSGIUCV
Select this option if you want to be able to receive SMSG messages
from other VM guest systems.
+config CLAW
+ tristate "CLAW device support"
+ depends on NETDEVICES
+ help
+ This driver supports channel attached CLAW devices.
+ CLAW is Common Link Access for Workstation. Common devices
+ that use CLAW are RS/6000s, Cisco Routers (CIP) and 3172 devices.
+ To compile as a module choose M here: The module will be called
+ claw.ko to compile into the kernel choose Y
config QETH
tristate "Gigabit Ethernet device support"
diff --git a/drivers/s390/net/Makefile b/drivers/s390/net/Makefile
index 2cfd22b2f914d..7cabb80a2e414 100644
--- a/drivers/s390/net/Makefile
+++ b/drivers/s390/net/Makefile
@@ -9,6 +9,6 @@ obj-$(CONFIG_NETIUCV) += netiucv.o fsm.o
obj-$(CONFIG_SMSGIUCV) += smsgiucv.o
obj-$(CONFIG_CTC) += ctc.o fsm.o cu3088.o
obj-$(CONFIG_LCS) += lcs.o cu3088.o
-qeth-y := qeth_main.o qeth_mpc.o qeth_sys.o
+qeth-y := qeth_main.o qeth_mpc.o qeth_sys.o qeth_eddp.o qeth_tso.o
qeth-$(CONFIG_PROC_FS) += qeth_proc.o
obj-$(CONFIG_QETH) += qeth.o
diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c
new file mode 100644
index 0000000000000..06804d39a9c6d
--- /dev/null
+++ b/drivers/s390/net/claw.c
@@ -0,0 +1,4447 @@
+/*
+ * drivers/s390/net/claw.c
+ * ESCON CLAW network driver
+ *
+ * $Revision: 1.35 $ $Date: 2005/03/24 12:25:38 $
+ *
+ * Linux fo zSeries version
+ * Copyright (C) 2002,2005 IBM Corporation
+ * Author(s) Original code written by:
+ * Kazuo Iimura (iimura@jp.ibm.com)
+ * Rewritten by
+ * Andy Richter (richtera@us.ibm.com)
+ * Marc Price (mwprice@us.ibm.com)
+ *
+ * sysfs parms:
+ * group x.x.rrrr,x.x.wwww
+ * read_buffer nnnnnnn
+ * write_buffer nnnnnn
+ * host_name aaaaaaaa
+ * adapter_name aaaaaaaa
+ * api_type aaaaaaaa
+ *
+ * eg.
+ * group 0.0.0200 0.0.0201
+ * read_buffer 25
+ * write_buffer 20
+ * host_name LINUX390
+ * adapter_name RS6K
+ * api_type TCPIP
+ *
+ * where
+ *
+ * The device id is decided by the order entries
+ * are added to the group the first is claw0 the second claw1
+ * up to CLAW_MAX_DEV
+ *
+ * rrrr - the first of 2 consecutive device addresses used for the
+ * CLAW protocol.
+ * The specified address is always used as the input (Read)
+ * channel and the next address is used as the output channel.
+ *
+ * wwww - the second of 2 consecutive device addresses used for
+ * the CLAW protocol.
+ * The specified address is always used as the output
+ * channel and the previous address is used as the input channel.
+ *
+ * read_buffer - specifies number of input buffers to allocate.
+ * write_buffer - specifies number of output buffers to allocate.
+ * host_name - host name
+ * adaptor_name - adaptor name
+ * api_type - API type TCPIP or API will be sent and expected
+ * as ws_name
+ *
+ * Note the following requirements:
+ * 1) host_name must match the configured adapter_name on the remote side
+ * 2) adaptor_name must match the configured host name on the remote side
+ *
+ * Change History
+ * 1.00 Initial release shipped
+ * 1.10 Changes for Buffer allocation
+ * 1.15 Changed for 2.6 Kernel No longer compiles on 2.4 or lower
+ * 1.25 Added Packing support
+ */
+#include <asm/bitops.h>
+#include <asm/ccwdev.h>
+#include <asm/ccwgroup.h>
+#include <asm/debug.h>
+#include <asm/idals.h>
+#include <asm/io.h>
+
+#include <linux/ctype.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/if_arp.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/ip.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/proc_fs.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/skbuff.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/tcp.h>
+#include <linux/timer.h>
+#include <linux/types.h>
+#include <linux/version.h>
+
+#include "cu3088.h"
+#include "claw.h"
+
+MODULE_AUTHOR("Andy Richter <richtera@us.ibm.com>");
+MODULE_DESCRIPTION("Linux for zSeries CLAW Driver\n" \
+ "Copyright 2000,2005 IBM Corporation\n");
+MODULE_LICENSE("GPL");
+
+/* Debugging is based on DEBUGMSG, IOTRACE, or FUNCTRACE options:
+ DEBUGMSG - Enables output of various debug messages in the code
+ IOTRACE - Enables output of CCW and other IO related traces
+ FUNCTRACE - Enables output of function entry/exit trace
+ Define any combination of above options to enable tracing
+
+ CLAW also uses the s390dbf file system see claw_trace and claw_setup
+*/
+
+/* following enables tracing */
+//#define DEBUGMSG
+//#define IOTRACE
+//#define FUNCTRACE
+
+#ifdef DEBUGMSG
+#define DEBUG
+#endif
+
+#ifdef IOTRACE
+#define DEBUG
+#endif
+
+#ifdef FUNCTRACE
+#define DEBUG
+#endif
+
+ char debug_buffer[255];
+/**
+ * Debug Facility Stuff
+ */
+static debug_info_t *claw_dbf_setup;
+static debug_info_t *claw_dbf_trace;
+
+/**
+ * CLAW Debug Facility functions
+ */
+static void
+claw_unregister_debug_facility(void)
+{
+ if (claw_dbf_setup)
+ debug_unregister(claw_dbf_setup);
+ if (claw_dbf_trace)
+ debug_unregister(claw_dbf_trace);
+}
+
+static int
+claw_register_debug_facility(void)
+{
+ claw_dbf_setup = debug_register("claw_setup", 1, 1, 8);
+ claw_dbf_trace = debug_register("claw_trace", 1, 2, 8);
+ if (claw_dbf_setup == NULL || claw_dbf_trace == NULL) {
+ printk(KERN_WARNING "Not enough memory for debug facility.\n");
+ claw_unregister_debug_facility();
+ return -ENOMEM;
+ }
+ debug_register_view(claw_dbf_setup, &debug_hex_ascii_view);
+ debug_set_level(claw_dbf_setup, 2);
+ debug_register_view(claw_dbf_trace, &debug_hex_ascii_view);
+ debug_set_level(claw_dbf_trace, 2);
+ return 0;
+}
+
+static inline void
+claw_set_busy(struct net_device *dev)
+{
+ ((struct claw_privbk *) dev->priv)->tbusy=1;
+ eieio();
+}
+
+static inline void
+claw_clear_busy(struct net_device *dev)
+{
+ clear_bit(0, &(((struct claw_privbk *) dev->priv)->tbusy));
+ netif_wake_queue(dev);
+ eieio();
+}
+
+static inline int
+claw_check_busy(struct net_device *dev)
+{
+ eieio();
+ return ((struct claw_privbk *) dev->priv)->tbusy;
+}
+
+static inline void
+claw_setbit_busy(int nr,struct net_device *dev)
+{
+ netif_stop_queue(dev);
+ set_bit(nr, (void *)&(((struct claw_privbk *)dev->priv)->tbusy));
+}
+
+static inline void
+claw_clearbit_busy(int nr,struct net_device *dev)
+{
+ clear_bit(nr,(void *)&(((struct claw_privbk *)dev->priv)->tbusy));
+ netif_wake_queue(dev);
+}
+
+static inline int
+claw_test_and_setbit_busy(int nr,struct net_device *dev)
+{
+ netif_stop_queue(dev);
+ return test_and_set_bit(nr,
+ (void *)&(((struct claw_privbk *) dev->priv)->tbusy));
+}
+
+
+/* Functions for the DEV methods */
+
+static int claw_probe(struct ccwgroup_device *cgdev);
+static void claw_remove_device(struct ccwgroup_device *cgdev);
+static void claw_purge_skb_queue(struct sk_buff_head *q);
+static int claw_new_device(struct ccwgroup_device *cgdev);
+static int claw_shutdown_device(struct ccwgroup_device *cgdev);
+static int claw_tx(struct sk_buff *skb, struct net_device *dev);
+static int claw_change_mtu( struct net_device *dev, int new_mtu);
+static int claw_open(struct net_device *dev);
+static void claw_irq_handler(struct ccw_device *cdev,
+ unsigned long intparm, struct irb *irb);
+static void claw_irq_tasklet ( unsigned long data );
+static int claw_release(struct net_device *dev);
+static void claw_write_retry ( struct chbk * p_ch );
+static void claw_write_next ( struct chbk * p_ch );
+static void claw_timer ( struct chbk * p_ch );
+
+/* Functions */
+static int add_claw_reads(struct net_device *dev,
+ struct ccwbk* p_first, struct ccwbk* p_last);
+static void inline ccw_check_return_code (struct ccw_device *cdev,
+ int return_code);
+static void inline ccw_check_unit_check (struct chbk * p_ch,
+ unsigned char sense );
+static int find_link(struct net_device *dev, char *host_name, char *ws_name );
+static int claw_hw_tx(struct sk_buff *skb, struct net_device *dev, long linkid);
+static int init_ccw_bk(struct net_device *dev);
+static void probe_error( struct ccwgroup_device *cgdev);
+static struct net_device_stats *claw_stats(struct net_device *dev);
+static int inline pages_to_order_of_mag(int num_of_pages);
+static struct sk_buff *claw_pack_skb(struct claw_privbk *privptr);
+#ifdef DEBUG
+static void dumpit (char *buf, int len);
+#endif
+/* sysfs Functions */
+static ssize_t claw_hname_show(struct device *dev, char *buf);
+static ssize_t claw_hname_write(struct device *dev,
+ const char *buf, size_t count);
+static ssize_t claw_adname_show(struct device *dev, char *buf);
+static ssize_t claw_adname_write(struct device *dev,
+ const char *buf, size_t count);
+static ssize_t claw_apname_show(struct device *dev, char *buf);
+static ssize_t claw_apname_write(struct device *dev,
+ const char *buf, size_t count);
+static ssize_t claw_wbuff_show(struct device *dev, char *buf);
+static ssize_t claw_wbuff_write(struct device *dev,
+ const char *buf, size_t count);
+static ssize_t claw_rbuff_show(struct device *dev, char *buf);
+static ssize_t claw_rbuff_write(struct device *dev,
+ const char *buf, size_t count);
+static int claw_add_files(struct device *dev);
+static void claw_remove_files(struct device *dev);
+
+/* Functions for System Validate */
+static int claw_process_control( struct net_device *dev, struct ccwbk * p_ccw);
+static int claw_send_control(struct net_device *dev, __u8 type, __u8 link,
+ __u8 correlator, __u8 rc , char *local_name, char *remote_name);
+static int claw_snd_conn_req(struct net_device *dev, __u8 link);
+static int claw_snd_disc(struct net_device *dev, struct clawctl * p_ctl);
+static int claw_snd_sys_validate_rsp(struct net_device *dev,
+ struct clawctl * p_ctl, __u32 return_code);
+static int claw_strt_conn_req(struct net_device *dev );
+static void claw_strt_read ( struct net_device *dev, int lock );
+static void claw_strt_out_IO( struct net_device *dev );
+static void claw_free_wrt_buf( struct net_device *dev );
+
+/* Functions for unpack reads */
+static void unpack_read (struct net_device *dev );
+
+/* ccwgroup table */
+
+static struct ccwgroup_driver claw_group_driver = {
+ .owner = THIS_MODULE,
+ .name = "claw",
+ .max_slaves = 2,
+ .driver_id = 0xC3D3C1E6,
+ .probe = claw_probe,
+ .remove = claw_remove_device,
+ .set_online = claw_new_device,
+ .set_offline = claw_shutdown_device,
+};
+
+/*
+*
+* Key functions
+*/
+
+/*----------------------------------------------------------------*
+ * claw_probe *
+ * this function is called for each CLAW device. *
+ *----------------------------------------------------------------*/
+static int
+claw_probe(struct ccwgroup_device *cgdev)
+{
+ int rc;
+ struct claw_privbk *privptr=NULL;
+
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s Enter\n",__FUNCTION__);
+#endif
+ CLAW_DBF_TEXT(2,setup,"probe");
+ if (!get_device(&cgdev->dev))
+ return -ENODEV;
+#ifdef DEBUGMSG
+ printk(KERN_INFO "claw: variable cgdev =\n");
+ dumpit((char *)cgdev, sizeof(struct ccwgroup_device));
+#endif
+ privptr = kmalloc(sizeof(struct claw_privbk), GFP_KERNEL);
+ if (privptr == NULL) {
+ probe_error(cgdev);
+ put_device(&cgdev->dev);
+ printk(KERN_WARNING "Out of memory %s %s Exit Line %d \n",
+ cgdev->cdev[0]->dev.bus_id,__FUNCTION__,__LINE__);
+ CLAW_DBF_TEXT_(2,setup,"probex%d",-ENOMEM);
+ return -ENOMEM;
+ }
+ memset(privptr,0x00,sizeof(struct claw_privbk));
+ privptr->p_mtc_envelope= kmalloc( MAX_ENVELOPE_SIZE, GFP_KERNEL);
+ privptr->p_env = kmalloc(sizeof(struct claw_env), GFP_KERNEL);
+ if ((privptr->p_mtc_envelope==NULL) || (privptr->p_env==NULL)) {
+ probe_error(cgdev);
+ put_device(&cgdev->dev);
+ printk(KERN_WARNING "Out of memory %s %s Exit Line %d \n",
+ cgdev->cdev[0]->dev.bus_id,__FUNCTION__,__LINE__);
+ CLAW_DBF_TEXT_(2,setup,"probex%d",-ENOMEM);
+ return -ENOMEM;
+ }
+ memset(privptr->p_mtc_envelope, 0x00, MAX_ENVELOPE_SIZE);
+ memset(privptr->p_env, 0x00, sizeof(struct claw_env));
+ memcpy(privptr->p_env->adapter_name,WS_NAME_NOT_DEF,8);
+ memcpy(privptr->p_env->host_name,WS_NAME_NOT_DEF,8);
+ memcpy(privptr->p_env->api_type,WS_NAME_NOT_DEF,8);
+ privptr->p_env->packing = 0;
+ privptr->p_env->write_buffers = 5;
+ privptr->p_env->read_buffers = 5;
+ privptr->p_env->read_size = CLAW_FRAME_SIZE;
+ privptr->p_env->write_size = CLAW_FRAME_SIZE;
+ rc = claw_add_files(&cgdev->dev);
+ if (rc) {
+ probe_error(cgdev);
+ put_device(&cgdev->dev);
+ printk(KERN_WARNING "add_files failed %s %s Exit Line %d \n",
+ cgdev->cdev[0]->dev.bus_id,__FUNCTION__,__LINE__);
+ CLAW_DBF_TEXT_(2,setup,"probex%d",rc);
+ return rc;
+ }
+ printk(KERN_INFO "claw: sysfs files added for %s\n",cgdev->cdev[0]->dev.bus_id);
+ privptr->p_env->p_priv = privptr;
+ cgdev->cdev[0]->handler = claw_irq_handler;
+ cgdev->cdev[1]->handler = claw_irq_handler;
+ cgdev->dev.driver_data = privptr;
+#ifdef FUNCTRACE
+ printk(KERN_INFO "claw:%s exit on line %d, "
+ "rc = 0\n",__FUNCTION__,__LINE__);
+#endif
+ CLAW_DBF_TEXT(2,setup,"prbext 0");
+
+ return 0;
+} /* end of claw_probe */
+
+/*-------------------------------------------------------------------*
+ * claw_tx *
+ *-------------------------------------------------------------------*/
+
+static int
+claw_tx(struct sk_buff *skb, struct net_device *dev)
+{
+ int rc;
+ struct claw_privbk *privptr=dev->priv;
+ unsigned long saveflags;
+ struct chbk *p_ch;
+
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s enter\n",dev->name,__FUNCTION__);
+#endif
+ CLAW_DBF_TEXT(4,trace,"claw_tx");
+ p_ch=&privptr->channel[WRITE];
+ if (skb == NULL) {
+ printk(KERN_WARNING "%s: null pointer passed as sk_buffer\n",
+ dev->name);
+ privptr->stats.tx_dropped++;
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s: %s() exit on line %d, rc = EIO\n",
+ dev->name,__FUNCTION__, __LINE__);
+#endif
+ CLAW_DBF_TEXT_(2,trace,"clawtx%d",-EIO);
+ return -EIO;
+ }
+
+#ifdef IOTRACE
+ printk(KERN_INFO "%s: variable sk_buff=\n",dev->name);
+ dumpit((char *) skb, sizeof(struct sk_buff));
+ printk(KERN_INFO "%s: variable dev=\n",dev->name);
+ dumpit((char *) dev, sizeof(struct net_device));
+#endif
+ spin_lock_irqsave(get_ccwdev_lock(p_ch->cdev), saveflags);
+ rc=claw_hw_tx( skb, dev, 1 );
+ spin_unlock_irqrestore(get_ccwdev_lock(p_ch->cdev), saveflags);
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s exit on line %d, rc = %d\n",
+ dev->name, __FUNCTION__, __LINE__, rc);
+#endif
+ CLAW_DBF_TEXT_(4,trace,"clawtx%d",rc);
+ return rc;
+} /* end of claw_tx */
+
+/*------------------------------------------------------------------*
+ * pack the collect queue into an skb and return it *
+ * If not packing just return the top skb from the queue *
+ *------------------------------------------------------------------*/
+
+static struct sk_buff *
+claw_pack_skb(struct claw_privbk *privptr)
+{
+ struct sk_buff *new_skb,*held_skb;
+ struct chbk *p_ch = &privptr->channel[WRITE];
+ struct claw_env *p_env = privptr->p_env;
+ int pkt_cnt,pk_ind,so_far;
+
+ new_skb = NULL; /* assume no dice */
+ pkt_cnt = 0;
+ CLAW_DBF_TEXT(4,trace,"PackSKBe");
+ if (skb_queue_len(&p_ch->collect_queue) > 0) {
+ /* some data */
+ held_skb = skb_dequeue(&p_ch->collect_queue);
+ if (p_env->packing != DO_PACKED)
+ return held_skb;
+ if (held_skb)
+ atomic_dec(&held_skb->users);
+ else
+ return NULL;
+ /* get a new SKB we will pack at least one */
+ new_skb = dev_alloc_skb(p_env->write_size);
+ if (new_skb == NULL) {
+ atomic_inc(&held_skb->users);
+ skb_queue_head(&p_ch->collect_queue,held_skb);
+ return NULL;
+ }
+ /* we have packed packet and a place to put it */
+ pk_ind = 1;
+ so_far = 0;
+ new_skb->cb[1] = 'P'; /* every skb on queue has pack header */
+ while ((pk_ind) && (held_skb != NULL)) {
+ if (held_skb->len+so_far <= p_env->write_size-8) {
+ memcpy(skb_put(new_skb,held_skb->len),
+ held_skb->data,held_skb->len);
+ privptr->stats.tx_packets++;
+ so_far += held_skb->len;
+ pkt_cnt++;
+ dev_kfree_skb_irq(held_skb);
+ held_skb = skb_dequeue(&p_ch->collect_queue);
+ if (held_skb)
+ atomic_dec(&held_skb->users);
+ } else {
+ pk_ind = 0;
+ atomic_inc(&held_skb->users);
+ skb_queue_head(&p_ch->collect_queue,held_skb);
+ }
+ }
+#ifdef IOTRACE
+ printk(KERN_INFO "%s: %s() Packed %d len %d\n",
+ p_env->ndev->name,
+ __FUNCTION__,pkt_cnt,new_skb->len);
+#endif
+ }
+ CLAW_DBF_TEXT(4,trace,"PackSKBx");
+ return new_skb;
+}
+
+/*-------------------------------------------------------------------*
+ * claw_change_mtu *
+ * *
+ *-------------------------------------------------------------------*/
+
+static int
+claw_change_mtu(struct net_device *dev, int new_mtu)
+{
+ struct claw_privbk *privptr=dev->priv;
+ int buff_size;
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Enter \n",dev->name,__FUNCTION__);
+#endif
+#ifdef DEBUGMSG
+ printk(KERN_INFO "variable dev =\n");
+ dumpit((char *) dev, sizeof(struct net_device));
+ printk(KERN_INFO "variable new_mtu = %d\n", new_mtu);
+#endif
+ CLAW_DBF_TEXT(4,trace,"setmtu");
+ buff_size = privptr->p_env->write_size;
+ if ((new_mtu < 60) || (new_mtu > buff_size)) {
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d, rc=EINVAL\n",
+ dev->name,
+ __FUNCTION__, __LINE__);
+#endif
+ return -EINVAL;
+ }
+ dev->mtu = new_mtu;
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d\n",dev->name,
+ __FUNCTION__, __LINE__);
+#endif
+ return 0;
+} /* end of claw_change_mtu */
+
+
+/*-------------------------------------------------------------------*
+ * claw_open *
+ * *
+ *-------------------------------------------------------------------*/
+static int
+claw_open(struct net_device *dev)
+{
+
+ int rc;
+ int i;
+ unsigned long saveflags=0;
+ unsigned long parm;
+ struct claw_privbk *privptr;
+ DECLARE_WAITQUEUE(wait, current);
+ struct timer_list timer;
+ struct ccwbk *p_buf;
+
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Enter \n",dev->name,__FUNCTION__);
+#endif
+ CLAW_DBF_TEXT(4,trace,"open");
+ if (!dev | (dev->name[0] == 0x00)) {
+ CLAW_DBF_TEXT(2,trace,"BadDev");
+ printk(KERN_WARNING "claw: Bad device at open failing \n");
+ return -ENODEV;
+ }
+ privptr = (struct claw_privbk *)dev->priv;
+ /* allocate and initialize CCW blocks */
+ if (privptr->buffs_alloc == 0) {
+ rc=init_ccw_bk(dev);
+ if (rc) {
+ printk(KERN_INFO "%s:%s Exit on line %d, rc=ENOMEM\n",
+ dev->name,
+ __FUNCTION__, __LINE__);
+ CLAW_DBF_TEXT(2,trace,"openmem");
+ return -ENOMEM;
+ }
+ }
+ privptr->system_validate_comp=0;
+ privptr->release_pend=0;
+ if(strncmp(privptr->p_env->api_type,WS_APPL_NAME_PACKED,6) == 0) {
+ privptr->p_env->read_size=DEF_PACK_BUFSIZE;
+ privptr->p_env->write_size=DEF_PACK_BUFSIZE;
+ privptr->p_env->packing=PACKING_ASK;
+ } else {
+ privptr->p_env->packing=0;
+ privptr->p_env->read_size=CLAW_FRAME_SIZE;
+ privptr->p_env->write_size=CLAW_FRAME_SIZE;
+ }
+ claw_set_busy(dev);
+ tasklet_init(&privptr->channel[READ].tasklet, claw_irq_tasklet,
+ (unsigned long) &privptr->channel[READ]);
+ for ( i = 0; i < 2; i++) {
+ CLAW_DBF_TEXT_(2,trace,"opn_ch%d",i);
+ init_waitqueue_head(&privptr->channel[i].wait);
+ /* skb_queue_head_init(&p_ch->io_queue); */
+ if (i == WRITE)
+ skb_queue_head_init(
+ &privptr->channel[WRITE].collect_queue);
+ privptr->channel[i].flag_a = 0;
+ privptr->channel[i].IO_active = 0;
+ privptr->channel[i].flag &= ~CLAW_TIMER;
+ init_timer(&timer);
+ timer.function = (void *)claw_timer;
+ timer.data = (unsigned long)(&privptr->channel[i]);
+ timer.expires = jiffies + 15*HZ;
+ add_timer(&timer);
+ spin_lock_irqsave(get_ccwdev_lock(
+ privptr->channel[i].cdev), saveflags);
+ parm = (unsigned long) &privptr->channel[i];
+ privptr->channel[i].claw_state = CLAW_START_HALT_IO;
+ rc = 0;
+ add_wait_queue(&privptr->channel[i].wait, &wait);
+ rc = ccw_device_halt(
+ (struct ccw_device *)privptr->channel[i].cdev,parm);
+ set_current_state(TASK_INTERRUPTIBLE);
+ spin_unlock_irqrestore(
+ get_ccwdev_lock(privptr->channel[i].cdev), saveflags);
+ schedule();
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&privptr->channel[i].wait, &wait);
+ if(rc != 0)
+ ccw_check_return_code(privptr->channel[i].cdev, rc);
+ if((privptr->channel[i].flag & CLAW_TIMER) == 0x00)
+ del_timer(&timer);
+ }
+ if ((((privptr->channel[READ].last_dstat |
+ privptr->channel[WRITE].last_dstat) &
+ ~(DEV_STAT_CHN_END | DEV_STAT_DEV_END)) != 0x00) ||
+ (((privptr->channel[READ].flag |
+ privptr->channel[WRITE].flag) & CLAW_TIMER) != 0x00)) {
+#ifdef DEBUGMSG
+ printk(KERN_INFO "%s: channel problems during open - read:"
+ " %02x - write: %02x\n",
+ dev->name,
+ privptr->channel[READ].last_dstat,
+ privptr->channel[WRITE].last_dstat);
+#endif
+ printk(KERN_INFO "%s: remote side is not ready\n", dev->name);
+ CLAW_DBF_TEXT(2,trace,"notrdy");
+
+ for ( i = 0; i < 2; i++) {
+ spin_lock_irqsave(
+ get_ccwdev_lock(privptr->channel[i].cdev),
+ saveflags);
+ parm = (unsigned long) &privptr->channel[i];
+ privptr->channel[i].claw_state = CLAW_STOP;
+ rc = ccw_device_halt(
+ (struct ccw_device *)&privptr->channel[i].cdev,
+ parm);
+ spin_unlock_irqrestore(
+ get_ccwdev_lock(privptr->channel[i].cdev),
+ saveflags);
+ if (rc != 0) {
+ ccw_check_return_code(
+ privptr->channel[i].cdev, rc);
+ }
+ }
+ free_pages((unsigned long)privptr->p_buff_ccw,
+ (int)pages_to_order_of_mag(privptr->p_buff_ccw_num));
+ if (privptr->p_env->read_size < PAGE_SIZE) {
+ free_pages((unsigned long)privptr->p_buff_read,
+ (int)pages_to_order_of_mag(
+ privptr->p_buff_read_num));
+ }
+ else {
+ p_buf=privptr->p_read_active_first;
+ while (p_buf!=NULL) {
+ free_pages((unsigned long)p_buf->p_buffer,
+ (int)pages_to_order_of_mag(
+ privptr->p_buff_pages_perread ));
+ p_buf=p_buf->next;
+ }
+ }
+ if (privptr->p_env->write_size < PAGE_SIZE ) {
+ free_pages((unsigned long)privptr->p_buff_write,
+ (int)pages_to_order_of_mag(
+ privptr->p_buff_write_num));
+ }
+ else {
+ p_buf=privptr->p_write_active_first;
+ while (p_buf!=NULL) {
+ free_pages((unsigned long)p_buf->p_buffer,
+ (int)pages_to_order_of_mag(
+ privptr->p_buff_pages_perwrite ));
+ p_buf=p_buf->next;
+ }
+ }
+ privptr->buffs_alloc = 0;
+ privptr->channel[READ].flag= 0x00;
+ privptr->channel[WRITE].flag = 0x00;
+ privptr->p_buff_ccw=NULL;
+ privptr->p_buff_read=NULL;
+ privptr->p_buff_write=NULL;
+ claw_clear_busy(dev);
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d, rc=EIO\n",
+ dev->name,__FUNCTION__,__LINE__);
+#endif
+ CLAW_DBF_TEXT(2,trace,"open EIO");
+ return -EIO;
+ }
+
+ /* Send SystemValidate command */
+
+ claw_clear_busy(dev);
+
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d, rc=0\n",
+ dev->name,__FUNCTION__,__LINE__);
+#endif
+ CLAW_DBF_TEXT(4,trace,"openok");
+ return 0;
+} /* end of claw_open */
+
+/*-------------------------------------------------------------------*
+* *
+* claw_irq_handler *
+* *
+*--------------------------------------------------------------------*/
+static void
+claw_irq_handler(struct ccw_device *cdev,
+ unsigned long intparm, struct irb *irb)
+{
+ struct chbk *p_ch = NULL;
+ struct claw_privbk *privptr = NULL;
+ struct net_device *dev = NULL;
+ struct claw_env *p_env;
+ struct chbk *p_ch_r=NULL;
+
+
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s enter \n",__FUNCTION__);
+#endif
+ CLAW_DBF_TEXT(4,trace,"clawirq");
+ /* Bypass all 'unsolicited interrupts' */
+ if (!cdev->dev.driver_data) {
+ printk(KERN_WARNING "claw: unsolicited interrupt for device:"
+ "%s received c-%02x d-%02x\n",
+ cdev->dev.bus_id,irb->scsw.cstat, irb->scsw.dstat);
+#ifdef FUNCTRACE
+ printk(KERN_INFO "claw: %s() "
+ "exit on line %d\n",__FUNCTION__,__LINE__);
+#endif
+ CLAW_DBF_TEXT(2,trace,"badirq");
+ return;
+ }
+ privptr = (struct claw_privbk *)cdev->dev.driver_data;
+
+ /* Try to extract channel from driver data. */
+ if (privptr->channel[READ].cdev == cdev)
+ p_ch = &privptr->channel[READ];
+ else if (privptr->channel[WRITE].cdev == cdev)
+ p_ch = &privptr->channel[WRITE];
+ else {
+ printk(KERN_WARNING "claw: Can't determine channel for "
+ "interrupt, device %s\n", cdev->dev.bus_id);
+ CLAW_DBF_TEXT(2,trace,"badchan");
+ return;
+ }
+ CLAW_DBF_TEXT_(4,trace,"IRQCH=%d",p_ch->flag);
+
+ dev = (struct net_device *) (p_ch->ndev);
+ p_env=privptr->p_env;
+
+#ifdef IOTRACE
+ printk(KERN_INFO "%s: interrupt for device: %04x "
+ "received c-%02x d-%02x state-%02x\n",
+ dev->name, p_ch->devno, irb->scsw.cstat,
+ irb->scsw.dstat, p_ch->claw_state);
+#endif
+
+ /* Copy interruption response block. */
+ memcpy(p_ch->irb, irb, sizeof(struct irb));
+
+ /* Check for good subchannel return code, otherwise error message */
+ if (irb->scsw.cstat && !(irb->scsw.cstat & SCHN_STAT_PCI)) {
+ printk(KERN_INFO "%s: subchannel check for device: %04x -"
+ " Sch Stat %02x Dev Stat %02x CPA - %04x\n",
+ dev->name, p_ch->devno,
+ irb->scsw.cstat, irb->scsw.dstat,irb->scsw.cpa);
+#ifdef IOTRACE
+ dumpit((char *)irb,sizeof(struct irb));
+ dumpit((char *)(unsigned long)irb->scsw.cpa,
+ sizeof(struct ccw1));
+#endif
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d\n",
+ dev->name,__FUNCTION__,__LINE__);
+#endif
+ CLAW_DBF_TEXT(2,trace,"chanchk");
+ /* return; */
+ }
+
+ /* Check the reason-code of a unit check */
+ if (irb->scsw.dstat & DEV_STAT_UNIT_CHECK) {
+ ccw_check_unit_check(p_ch, irb->ecw[0]);
+ }
+
+ /* State machine to bring the connection up, down and to restart */
+ p_ch->last_dstat = irb->scsw.dstat;
+
+ switch (p_ch->claw_state) {
+ case CLAW_STOP:/* HALT_IO by claw_release (halt sequence) */
+#ifdef DEBUGMSG
+ printk(KERN_INFO "%s: CLAW_STOP enter\n", dev->name);
+#endif
+ if (!((p_ch->irb->scsw.stctl & SCSW_STCTL_SEC_STATUS) ||
+ (p_ch->irb->scsw.stctl == SCSW_STCTL_STATUS_PEND) ||
+ (p_ch->irb->scsw.stctl ==
+ (SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND)))) {
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d\n",
+ dev->name,__FUNCTION__,__LINE__);
+#endif
+ return;
+ }
+ wake_up(&p_ch->wait); /* wake up claw_release */
+
+#ifdef DEBUGMSG
+ printk(KERN_INFO "%s: CLAW_STOP exit\n", dev->name);
+#endif
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d\n",
+ dev->name,__FUNCTION__,__LINE__);
+#endif
+ CLAW_DBF_TEXT(4,trace,"stop");
+ return;
+
+ case CLAW_START_HALT_IO: /* HALT_IO issued by claw_open */
+#ifdef DEBUGMSG
+ printk(KERN_INFO "%s: process CLAW_STAT_HALT_IO\n",
+ dev->name);
+#endif
+ if (!((p_ch->irb->scsw.stctl & SCSW_STCTL_SEC_STATUS) ||
+ (p_ch->irb->scsw.stctl == SCSW_STCTL_STATUS_PEND) ||
+ (p_ch->irb->scsw.stctl ==
+ (SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND)))) {
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d\n",
+ dev->name,__FUNCTION__,__LINE__);
+#endif
+ CLAW_DBF_TEXT(4,trace,"haltio");
+ return;
+ }
+ if (p_ch->flag == CLAW_READ) {
+ p_ch->claw_state = CLAW_START_READ;
+ wake_up(&p_ch->wait); /* wake claw_open (READ)*/
+ }
+ else
+ if (p_ch->flag == CLAW_WRITE) {
+ p_ch->claw_state = CLAW_START_WRITE;
+ /* send SYSTEM_VALIDATE */
+ claw_strt_read(dev, LOCK_NO);
+ claw_send_control(dev,
+ SYSTEM_VALIDATE_REQUEST,
+ 0, 0, 0,
+ p_env->host_name,
+ p_env->adapter_name );
+ } else {
+ printk(KERN_WARNING "claw: unsolicited "
+ "interrupt for device:"
+ "%s received c-%02x d-%02x\n",
+ cdev->dev.bus_id,
+ irb->scsw.cstat,
+ irb->scsw.dstat);
+ return;
+ }
+#ifdef DEBUGMSG
+ printk(KERN_INFO "%s: process CLAW_STAT_HALT_IO exit\n",
+ dev->name);
+#endif
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d\n",
+ dev->name,__FUNCTION__,__LINE__);
+#endif
+ CLAW_DBF_TEXT(4,trace,"haltio");
+ return;
+ case CLAW_START_READ:
+ CLAW_DBF_TEXT(4,trace,"ReadIRQ");
+ if (p_ch->irb->scsw.dstat & DEV_STAT_UNIT_CHECK) {
+ clear_bit(0, (void *)&p_ch->IO_active);
+ if ((p_ch->irb->ecw[0] & 0x41) == 0x41 ||
+ (p_ch->irb->ecw[0] & 0x40) == 0x40 ||
+ (p_ch->irb->ecw[0]) == 0)
+ {
+ privptr->stats.rx_errors++;
+ printk(KERN_INFO "%s: Restart is "
+ "required after remote "
+ "side recovers \n",
+ dev->name);
+ }
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d\n",
+ dev->name,__FUNCTION__,__LINE__);
+#endif
+ CLAW_DBF_TEXT(4,trace,"notrdy");
+ return;
+ }
+ if ((p_ch->irb->scsw.cstat & SCHN_STAT_PCI) &&
+ (p_ch->irb->scsw.dstat==0)) {
+ if (test_and_set_bit(CLAW_BH_ACTIVE,
+ (void *)&p_ch->flag_a) == 0) {
+ tasklet_schedule(&p_ch->tasklet);
+ }
+ else {
+ CLAW_DBF_TEXT(4,trace,"PCINoBH");
+ }
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d\n",
+ dev->name,__FUNCTION__,__LINE__);
+#endif
+ CLAW_DBF_TEXT(4,trace,"PCI_read");
+ return;
+ }
+ if(!((p_ch->irb->scsw.stctl & SCSW_STCTL_SEC_STATUS) ||
+ (p_ch->irb->scsw.stctl == SCSW_STCTL_STATUS_PEND) ||
+ (p_ch->irb->scsw.stctl ==
+ (SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND)))) {
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d\n",
+ dev->name,__FUNCTION__,__LINE__);
+#endif
+ CLAW_DBF_TEXT(4,trace,"SPend_rd");
+ return;
+ }
+ clear_bit(0, (void *)&p_ch->IO_active);
+ claw_clearbit_busy(TB_RETRY,dev);
+ if (test_and_set_bit(CLAW_BH_ACTIVE,
+ (void *)&p_ch->flag_a) == 0) {
+ tasklet_schedule(&p_ch->tasklet);
+ }
+ else {
+ CLAW_DBF_TEXT(4,trace,"RdBHAct");
+ }
+
+#ifdef DEBUGMSG
+ printk(KERN_INFO "%s: process CLAW_START_READ exit\n",
+ dev->name);
+#endif
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d\n",
+ dev->name,__FUNCTION__,__LINE__);
+#endif
+ CLAW_DBF_TEXT(4,trace,"RdIRQXit");
+ return;
+ case CLAW_START_WRITE:
+ if (p_ch->irb->scsw.dstat & DEV_STAT_UNIT_CHECK) {
+ printk(KERN_INFO "%s: Unit Check Occured in "
+ "write channel\n",dev->name);
+ clear_bit(0, (void *)&p_ch->IO_active);
+ if (p_ch->irb->ecw[0] & 0x80 ) {
+ printk(KERN_INFO "%s: Resetting Event "
+ "occurred:\n",dev->name);
+ init_timer(&p_ch->timer);
+ p_ch->timer.function =
+ (void *)claw_write_retry;
+ p_ch->timer.data = (unsigned long)p_ch;
+ p_ch->timer.expires = jiffies + 10*HZ;
+ add_timer(&p_ch->timer);
+ printk(KERN_INFO "%s: write connection "
+ "restarting\n",dev->name);
+ }
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d\n",
+ dev->name,__FUNCTION__,__LINE__);
+#endif
+ CLAW_DBF_TEXT(4,trace,"rstrtwrt");
+ return;
+ }
+ if (p_ch->irb->scsw.dstat & DEV_STAT_UNIT_EXCEP) {
+ clear_bit(0, (void *)&p_ch->IO_active);
+ printk(KERN_INFO "%s: Unit Exception "
+ "Occured in write channel\n",
+ dev->name);
+ }
+ if(!((p_ch->irb->scsw.stctl & SCSW_STCTL_SEC_STATUS) ||
+ (p_ch->irb->scsw.stctl == SCSW_STCTL_STATUS_PEND) ||
+ (p_ch->irb->scsw.stctl ==
+ (SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND)))) {
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d\n",
+ dev->name,__FUNCTION__,__LINE__);
+#endif
+ CLAW_DBF_TEXT(4,trace,"writeUE");
+ return;
+ }
+ clear_bit(0, (void *)&p_ch->IO_active);
+ if (claw_test_and_setbit_busy(TB_TX,dev)==0) {
+ claw_write_next(p_ch);
+ claw_clearbit_busy(TB_TX,dev);
+ claw_clear_busy(dev);
+ }
+ p_ch_r=(struct chbk *)&privptr->channel[READ];
+ if (test_and_set_bit(CLAW_BH_ACTIVE,
+ (void *)&p_ch_r->flag_a) == 0) {
+ tasklet_schedule(&p_ch_r->tasklet);
+ }
+
+#ifdef DEBUGMSG
+ printk(KERN_INFO "%s: process CLAW_START_WRITE exit\n",
+ dev->name);
+#endif
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d\n",
+ dev->name,__FUNCTION__,__LINE__);
+#endif
+ CLAW_DBF_TEXT(4,trace,"StWtExit");
+ return;
+ default:
+ printk(KERN_WARNING "%s: wrong selection code - irq "
+ "state=%d\n",dev->name,p_ch->claw_state);
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d\n",
+ dev->name,__FUNCTION__,__LINE__);
+#endif
+ CLAW_DBF_TEXT(2,trace,"badIRQ");
+ return;
+ }
+
+} /* end of claw_irq_handler */
+
+
+/*-------------------------------------------------------------------*
+* claw_irq_tasklet *
+* *
+*--------------------------------------------------------------------*/
+static void
+claw_irq_tasklet ( unsigned long data )
+{
+ struct chbk * p_ch;
+ struct net_device *dev;
+ struct claw_privbk * privptr;
+
+ p_ch = (struct chbk *) data;
+ dev = (struct net_device *)p_ch->ndev;
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Enter \n",dev->name,__FUNCTION__);
+#endif
+#ifdef DEBUGMSG
+ printk(KERN_INFO "%s: variable p_ch =\n",dev->name);
+ dumpit((char *) p_ch, sizeof(struct chbk));
+#endif
+ CLAW_DBF_TEXT(4,trace,"IRQtask");
+
+ privptr = (struct claw_privbk *) dev->priv;
+
+#ifdef DEBUGMSG
+ printk(KERN_INFO "%s: bh routine - state-%02x\n" ,
+ dev->name, p_ch->claw_state);
+#endif
+
+ unpack_read(dev);
+ clear_bit(CLAW_BH_ACTIVE, (void *)&p_ch->flag_a);
+ CLAW_DBF_TEXT(4,trace,"TskletXt");
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d\n",
+ dev->name,__FUNCTION__,__LINE__);
+#endif
+ return;
+} /* end of claw_irq_bh */
+
+/*-------------------------------------------------------------------*
+* claw_release *
+* *
+*--------------------------------------------------------------------*/
+static int
+claw_release(struct net_device *dev)
+{
+ int rc;
+ int i;
+ unsigned long saveflags;
+ unsigned long parm;
+ struct claw_privbk *privptr;
+ DECLARE_WAITQUEUE(wait, current);
+ struct ccwbk* p_this_ccw;
+ struct ccwbk* p_buf;
+
+ if (!dev)
+ return 0;
+ privptr = (struct claw_privbk *) dev->priv;
+ if (!privptr)
+ return 0;
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Enter \n",dev->name,__FUNCTION__);
+#endif
+ CLAW_DBF_TEXT(4,trace,"release");
+#ifdef DEBUGMSG
+ printk(KERN_INFO "%s: variable dev =\n",dev->name);
+ dumpit((char *) dev, sizeof(struct net_device));
+ printk(KERN_INFO "Priv Buffalloc %d\n",privptr->buffs_alloc);
+ printk(KERN_INFO "Priv p_buff_ccw = %p\n",&privptr->p_buff_ccw);
+#endif
+ privptr->release_pend=1;
+ claw_setbit_busy(TB_STOP,dev);
+ for ( i = 1; i >=0 ; i--) {
+ spin_lock_irqsave(
+ get_ccwdev_lock(privptr->channel[i].cdev), saveflags);
+ /* del_timer(&privptr->channel[READ].timer); */
+ privptr->channel[i].claw_state = CLAW_STOP;
+ privptr->channel[i].IO_active = 0;
+ parm = (unsigned long) &privptr->channel[i];
+ if (i == WRITE)
+ claw_purge_skb_queue(
+ &privptr->channel[WRITE].collect_queue);
+ rc = ccw_device_halt (privptr->channel[i].cdev, parm);
+ if (privptr->system_validate_comp==0x00) /* never opened? */
+ init_waitqueue_head(&privptr->channel[i].wait);
+ add_wait_queue(&privptr->channel[i].wait, &wait);
+ set_current_state(TASK_INTERRUPTIBLE);
+ spin_unlock_irqrestore(
+ get_ccwdev_lock(privptr->channel[i].cdev), saveflags);
+ schedule();
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&privptr->channel[i].wait, &wait);
+ if (rc != 0) {
+ ccw_check_return_code(privptr->channel[i].cdev, rc);
+ }
+ }
+ if (privptr->pk_skb != NULL) {
+ dev_kfree_skb(privptr->pk_skb);
+ privptr->pk_skb = NULL;
+ }
+ if(privptr->buffs_alloc != 1) {
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d\n",
+ dev->name,__FUNCTION__,__LINE__);
+#endif
+ CLAW_DBF_TEXT(4,trace,"none2fre");
+ return 0;
+ }
+ CLAW_DBF_TEXT(4,trace,"freebufs");
+ if (privptr->p_buff_ccw != NULL) {
+ free_pages((unsigned long)privptr->p_buff_ccw,
+ (int)pages_to_order_of_mag(privptr->p_buff_ccw_num));
+ }
+ CLAW_DBF_TEXT(4,trace,"freeread");
+ if (privptr->p_env->read_size < PAGE_SIZE) {
+ if (privptr->p_buff_read != NULL) {
+ free_pages((unsigned long)privptr->p_buff_read,
+ (int)pages_to_order_of_mag(privptr->p_buff_read_num));
+ }
+ }
+ else {
+ p_buf=privptr->p_read_active_first;
+ while (p_buf!=NULL) {
+ free_pages((unsigned long)p_buf->p_buffer,
+ (int)pages_to_order_of_mag(
+ privptr->p_buff_pages_perread ));
+ p_buf=p_buf->next;
+ }
+ }
+ CLAW_DBF_TEXT(4,trace,"freewrit");
+ if (privptr->p_env->write_size < PAGE_SIZE ) {
+ free_pages((unsigned long)privptr->p_buff_write,
+ (int)pages_to_order_of_mag(privptr->p_buff_write_num));
+ }
+ else {
+ p_buf=privptr->p_write_active_first;
+ while (p_buf!=NULL) {
+ free_pages((unsigned long)p_buf->p_buffer,
+ (int)pages_to_order_of_mag(
+ privptr->p_buff_pages_perwrite ));
+ p_buf=p_buf->next;
+ }
+ }
+ CLAW_DBF_TEXT(4,trace,"clearptr");
+ privptr->buffs_alloc = 0;
+ privptr->p_buff_ccw=NULL;
+ privptr->p_buff_read=NULL;
+ privptr->p_buff_write=NULL;
+ privptr->system_validate_comp=0;
+ privptr->release_pend=0;
+ /* Remove any writes that were pending and reset all reads */
+ p_this_ccw=privptr->p_read_active_first;
+ while (p_this_ccw!=NULL) {
+ p_this_ccw->header.length=0xffff;
+ p_this_ccw->header.opcode=0xff;
+ p_this_ccw->header.flag=0x00;
+ p_this_ccw=p_this_ccw->next;
+ }
+
+ while (privptr->p_write_active_first!=NULL) {
+ p_this_ccw=privptr->p_write_active_first;
+ p_this_ccw->header.flag=CLAW_PENDING;
+ privptr->p_write_active_first=p_this_ccw->next;
+ p_this_ccw->next=privptr->p_write_free_chain;
+ privptr->p_write_free_chain=p_this_ccw;
+ ++privptr->write_free_count;
+ }
+ privptr->p_write_active_last=NULL;
+ privptr->mtc_logical_link = -1;
+ privptr->mtc_skipping = 1;
+ privptr->mtc_offset=0;
+
+ if (((privptr->channel[READ].last_dstat |
+ privptr->channel[WRITE].last_dstat) &
+ ~(DEV_STAT_CHN_END | DEV_STAT_DEV_END)) != 0x00) {
+ printk(KERN_WARNING "%s: channel problems during close - "
+ "read: %02x - write: %02x\n",
+ dev->name,
+ privptr->channel[READ].last_dstat,
+ privptr->channel[WRITE].last_dstat);
+ CLAW_DBF_TEXT(2,trace,"badclose");
+ }
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d\n",
+ dev->name,__FUNCTION__,__LINE__);
+#endif
+ CLAW_DBF_TEXT(4,trace,"rlsexit");
+ return 0;
+} /* end of claw_release */
+
+
+
+/*-------------------------------------------------------------------*
+* claw_write_retry *
+* *
+*--------------------------------------------------------------------*/
+
+static void
+claw_write_retry ( struct chbk *p_ch )
+{
+
+ struct net_device *dev=p_ch->ndev;
+
+
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Enter\n",dev->name,__FUNCTION__);
+ printk(KERN_INFO "claw: variable p_ch =\n");
+ dumpit((char *) p_ch, sizeof(struct chbk));
+#endif
+ CLAW_DBF_TEXT(4,trace,"w_retry");
+ if (p_ch->claw_state == CLAW_STOP) {
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d\n",
+ dev->name,__FUNCTION__,__LINE__);
+#endif
+ return;
+ }
+#ifdef DEBUGMSG
+ printk( KERN_INFO "%s:%s state-%02x\n" ,
+ dev->name,
+ __FUNCTION__,
+ p_ch->claw_state);
+#endif
+ claw_strt_out_IO( dev );
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d\n",
+ dev->name,__FUNCTION__,__LINE__);
+#endif
+ CLAW_DBF_TEXT(4,trace,"rtry_xit");
+ return;
+} /* end of claw_write_retry */
+
+
+/*-------------------------------------------------------------------*
+* claw_write_next *
+* *
+*--------------------------------------------------------------------*/
+
+static void
+claw_write_next ( struct chbk * p_ch )
+{
+
+ struct net_device *dev;
+ struct claw_privbk *privptr=NULL;
+ struct sk_buff *pk_skb;
+ int rc;
+
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Enter \n",p_ch->ndev->name,__FUNCTION__);
+ printk(KERN_INFO "%s: variable p_ch =\n",p_ch->ndev->name);
+ dumpit((char *) p_ch, sizeof(struct chbk));
+#endif
+ CLAW_DBF_TEXT(4,trace,"claw_wrt");
+ if (p_ch->claw_state == CLAW_STOP)
+ return;
+ dev = (struct net_device *) p_ch->ndev;
+ privptr = (struct claw_privbk *) dev->priv;
+ claw_free_wrt_buf( dev );
+ if ((privptr->write_free_count > 0) &&
+ (skb_queue_len(&p_ch->collect_queue) > 0)) {
+ pk_skb = claw_pack_skb(privptr);
+ while (pk_skb != NULL) {
+ rc = claw_hw_tx( pk_skb, dev,1);
+ if (privptr->write_free_count > 0) {
+ pk_skb = claw_pack_skb(privptr);
+ } else
+ pk_skb = NULL;
+ }
+ }
+ if (privptr->p_write_active_first!=NULL) {
+ claw_strt_out_IO(dev);
+ }
+
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d\n",
+ dev->name,__FUNCTION__,__LINE__);
+#endif
+ return;
+} /* end of claw_write_next */
+
+/*-------------------------------------------------------------------*
+* *
+* claw_timer *
+*--------------------------------------------------------------------*/
+
+static void
+claw_timer ( struct chbk * p_ch )
+{
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Entry\n",p_ch->ndev->name,__FUNCTION__);
+ printk(KERN_INFO "%s: variable p_ch =\n",p_ch->ndev->name);
+ dumpit((char *) p_ch, sizeof(struct chbk));
+#endif
+ CLAW_DBF_TEXT(4,trace,"timer");
+ p_ch->flag |= CLAW_TIMER;
+ wake_up(&p_ch->wait);
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d\n",
+ p_ch->ndev->name,__FUNCTION__,__LINE__);
+#endif
+ return;
+} /* end of claw_timer */
+
+
+/*
+*
+* functions
+*/
+
+
+/*-------------------------------------------------------------------*
+* *
+* pages_to_order_of_mag *
+* *
+* takes a number of pages from 1 to 512 and returns the *
+* log(num_pages)/log(2) get_free_pages() needs a base 2 order *
+* of magnitude get_free_pages() has an upper order of 9 *
+*--------------------------------------------------------------------*/
+
+static int inline
+pages_to_order_of_mag(int num_of_pages)
+{
+ int order_of_mag=1; /* assume 2 pages */
+ int nump=2;
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s Enter pages = %d \n",__FUNCTION__,num_of_pages);
+#endif
+ CLAW_DBF_TEXT_(5,trace,"pages%d",num_of_pages);
+ if (num_of_pages == 1) {return 0; } /* magnitude of 0 = 1 page */
+ /* 512 pages = 2Meg on 4k page systems */
+ if (num_of_pages >= 512) {return 9; }
+ /* we have two or more pages order is at least 1 */
+ for (nump=2 ;nump <= 512;nump*=2) {
+ if (num_of_pages <= nump)
+ break;
+ order_of_mag +=1;
+ }
+ if (order_of_mag > 9) { order_of_mag = 9; } /* I know it's paranoid */
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s Exit on line %d, order = %d\n",
+ __FUNCTION__,__LINE__, order_of_mag);
+#endif
+ CLAW_DBF_TEXT_(5,trace,"mag%d",order_of_mag);
+ return order_of_mag;
+}
+
+/*-------------------------------------------------------------------*
+* *
+* add_claw_reads *
+* *
+*--------------------------------------------------------------------*/
+static int
+add_claw_reads(struct net_device *dev, struct ccwbk* p_first,
+ struct ccwbk* p_last)
+{
+ struct claw_privbk *privptr;
+ struct ccw1 temp_ccw;
+ struct endccw * p_end;
+#ifdef IOTRACE
+ struct ccwbk* p_buf;
+#endif
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Enter \n",dev->name,__FUNCTION__);
+#endif
+#ifdef DEBUGMSG
+ printk(KERN_INFO "dev\n");
+ dumpit((char *) dev, sizeof(struct net_device));
+ printk(KERN_INFO "p_first\n");
+ dumpit((char *) p_first, sizeof(struct ccwbk));
+ printk(KERN_INFO "p_last\n");
+ dumpit((char *) p_last, sizeof(struct ccwbk));
+#endif
+ CLAW_DBF_TEXT(4,trace,"addreads");
+ privptr = dev->priv;
+ p_end = privptr->p_end_ccw;
+
+ /* first CCW and last CCW contains a new set of read channel programs
+ * to apend the running channel programs
+ */
+ if ( p_first==NULL) {
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d\n",
+ dev->name,__FUNCTION__,__LINE__);
+#endif
+ CLAW_DBF_TEXT(4,trace,"addexit");
+ return 0;
+ }
+
+ /* set up ending CCW sequence for this segment */
+ if (p_end->read1) {
+ p_end->read1=0x00; /* second ending CCW is now active */
+ /* reset ending CCWs and setup TIC CCWs */
+ p_end->read2_nop2.cmd_code = CCW_CLAW_CMD_READFF;
+ p_end->read2_nop2.flags = CCW_FLAG_SLI | CCW_FLAG_SKIP;
+ p_last->r_TIC_1.cda =(__u32)__pa(&p_end->read2_nop1);
+ p_last->r_TIC_2.cda =(__u32)__pa(&p_end->read2_nop1);
+ p_end->read2_nop2.cda=0;
+ p_end->read2_nop2.count=1;
+ }
+ else {
+ p_end->read1=0x01; /* first ending CCW is now active */
+ /* reset ending CCWs and setup TIC CCWs */
+ p_end->read1_nop2.cmd_code = CCW_CLAW_CMD_READFF;
+ p_end->read1_nop2.flags = CCW_FLAG_SLI | CCW_FLAG_SKIP;
+ p_last->r_TIC_1.cda = (__u32)__pa(&p_end->read1_nop1);
+ p_last->r_TIC_2.cda = (__u32)__pa(&p_end->read1_nop1);
+ p_end->read1_nop2.cda=0;
+ p_end->read1_nop2.count=1;
+ }
+
+ if ( privptr-> p_read_active_first ==NULL ) {
+#ifdef DEBUGMSG
+ printk(KERN_INFO "%s:%s p_read_active_frist == NULL \n",
+ dev->name,__FUNCTION__);
+ printk(KERN_INFO "%s:%s Read active first/last changed \n",
+ dev->name,__FUNCTION__);
+#endif
+ privptr-> p_read_active_first= p_first; /* set new first */
+ privptr-> p_read_active_last = p_last; /* set new last */
+ }
+ else {
+
+#ifdef DEBUGMSG
+ printk(KERN_INFO "%s:%s Read in progress \n",
+ dev->name,__FUNCTION__);
+#endif
+ /* set up TIC ccw */
+ temp_ccw.cda= (__u32)__pa(&p_first->read);
+ temp_ccw.count=0;
+ temp_ccw.flags=0;
+ temp_ccw.cmd_code = CCW_CLAW_CMD_TIC;
+
+
+ if (p_end->read1) {
+
+ /* first set of CCW's is chained to the new read */
+ /* chain, so the second set is chained to the active chain. */
+ /* Therefore modify the second set to point to the new */
+ /* read chain set up TIC CCWs */
+ /* make sure we update the CCW so channel doesn't fetch it */
+ /* when it's only half done */
+ memcpy( &p_end->read2_nop2, &temp_ccw ,
+ sizeof(struct ccw1));
+ privptr->p_read_active_last->r_TIC_1.cda=
+ (__u32)__pa(&p_first->read);
+ privptr->p_read_active_last->r_TIC_2.cda=
+ (__u32)__pa(&p_first->read);
+ }
+ else {
+ /* make sure we update the CCW so channel doesn't */
+ /* fetch it when it is only half done */
+ memcpy( &p_end->read1_nop2, &temp_ccw ,
+ sizeof(struct ccw1));
+ privptr->p_read_active_last->r_TIC_1.cda=
+ (__u32)__pa(&p_first->read);
+ privptr->p_read_active_last->r_TIC_2.cda=
+ (__u32)__pa(&p_first->read);
+ }
+ /* chain in new set of blocks */
+ privptr->p_read_active_last->next = p_first;
+ privptr->p_read_active_last=p_last;
+ } /* end of if ( privptr-> p_read_active_first ==NULL) */
+#ifdef IOTRACE
+ printk(KERN_INFO "%s:%s dump p_last CCW BK \n",dev->name,__FUNCTION__);
+ dumpit((char *)p_last, sizeof(struct ccwbk));
+ printk(KERN_INFO "%s:%s dump p_end CCW BK \n",dev->name,__FUNCTION__);
+ dumpit((char *)p_end, sizeof(struct endccw));
+
+ printk(KERN_INFO "%s:%s dump p_first CCW BK \n",dev->name,__FUNCTION__);
+ dumpit((char *)p_first, sizeof(struct ccwbk));
+ printk(KERN_INFO "%s:%s Dump Active CCW chain \n",
+ dev->name,__FUNCTION__);
+ p_buf=privptr->p_read_active_first;
+ while (p_buf!=NULL) {
+ dumpit((char *)p_buf, sizeof(struct ccwbk));
+ p_buf=p_buf->next;
+ }
+#endif
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d\n",
+ dev->name,__FUNCTION__,__LINE__);
+#endif
+ CLAW_DBF_TEXT(4,trace,"addexit");
+ return 0;
+} /* end of add_claw_reads */
+
+/*-------------------------------------------------------------------*
+ * ccw_check_return_code *
+ * *
+ *-------------------------------------------------------------------*/
+
+static void inline
+ccw_check_return_code(struct ccw_device *cdev, int return_code)
+{
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s: %s() > enter \n",
+ cdev->dev.bus_id,__FUNCTION__);
+#endif
+ CLAW_DBF_TEXT(4,trace,"ccwret");
+#ifdef DEBUGMSG
+ printk(KERN_INFO "variable cdev =\n");
+ dumpit((char *) cdev, sizeof(struct ccw_device));
+ printk(KERN_INFO "variable return_code = %d\n",return_code);
+#endif
+ if (return_code != 0) {
+ switch (return_code) {
+ case -EBUSY:
+ printk(KERN_INFO "%s: Busy !\n",
+ cdev->dev.bus_id);
+ break;
+ case -ENODEV:
+ printk(KERN_EMERG "%s: Missing device called "
+ "for IO ENODEV\n", cdev->dev.bus_id);
+ break;
+ case -EIO:
+ printk(KERN_EMERG "%s: Status pending... EIO \n",
+ cdev->dev.bus_id);
+ break;
+ case -EINVAL:
+ printk(KERN_EMERG "%s: Invalid Dev State EINVAL \n",
+ cdev->dev.bus_id);
+ break;
+ default:
+ printk(KERN_EMERG "%s: Unknown error in "
+ "Do_IO %d\n",cdev->dev.bus_id, return_code);
+ }
+ }
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s: %s() > exit on line %d\n",
+ cdev->dev.bus_id,__FUNCTION__,__LINE__);
+#endif
+ CLAW_DBF_TEXT(4,trace,"ccwret");
+} /* end of ccw_check_return_code */
+
+/*-------------------------------------------------------------------*
+* ccw_check_unit_check *
+*--------------------------------------------------------------------*/
+
+static void inline
+ccw_check_unit_check(struct chbk * p_ch, unsigned char sense )
+{
+ struct net_device *dev = p_ch->ndev;
+
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s: %s() > enter\n",dev->name,__FUNCTION__);
+#endif
+#ifdef DEBUGMSG
+ printk(KERN_INFO "%s: variable dev =\n",dev->name);
+ dumpit((char *)dev, sizeof(struct net_device));
+ printk(KERN_INFO "%s: variable sense =\n",dev->name);
+ dumpit((char *)&sense, 2);
+#endif
+ CLAW_DBF_TEXT(4,trace,"unitchek");
+
+ printk(KERN_INFO "%s: Unit Check with sense byte:0x%04x\n",
+ dev->name, sense);
+
+ if (sense & 0x40) {
+ if (sense & 0x01) {
+ printk(KERN_WARNING "%s: Interface disconnect or "
+ "Selective reset "
+ "occurred (remote side)\n", dev->name);
+ }
+ else {
+ printk(KERN_WARNING "%s: System reset occured"
+ " (remote side)\n", dev->name);
+ }
+ }
+ else if (sense & 0x20) {
+ if (sense & 0x04) {
+ printk(KERN_WARNING "%s: Data-streaming "
+ "timeout)\n", dev->name);
+ }
+ else {
+ printk(KERN_WARNING "%s: Data-transfer parity"
+ " error\n", dev->name);
+ }
+ }
+ else if (sense & 0x10) {
+ if (sense & 0x20) {
+ printk(KERN_WARNING "%s: Hardware malfunction "
+ "(remote side)\n", dev->name);
+ }
+ else {
+ printk(KERN_WARNING "%s: read-data parity error "
+ "(remote side)\n", dev->name);
+ }
+ }
+
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s: %s() exit on line %d\n",
+ dev->name,__FUNCTION__,__LINE__);
+#endif
+} /* end of ccw_check_unit_check */
+
+
+
+/*-------------------------------------------------------------------*
+* Dump buffer format *
+* *
+*--------------------------------------------------------------------*/
+#ifdef DEBUG
+static void
+dumpit(char* buf, int len)
+{
+
+ __u32 ct, sw, rm, dup;
+ char *ptr, *rptr;
+ char tbuf[82], tdup[82];
+#if (CONFIG_ARCH_S390X)
+ char addr[22];
+#else
+ char addr[12];
+#endif
+ char boff[12];
+ char bhex[82], duphex[82];
+ char basc[40];
+
+ sw = 0;
+ rptr =ptr=buf;
+ rm = 16;
+ duphex[0] = 0x00;
+ dup = 0;
+ for ( ct=0; ct < len; ct++, ptr++, rptr++ ) {
+ if (sw == 0) {
+#if (CONFIG_ARCH_S390X)
+ sprintf(addr, "%16.16lX",(unsigned long)rptr);
+#else
+ sprintf(addr, "%8.8X",(__u32)rptr);
+#endif
+ sprintf(boff, "%4.4X", (__u32)ct);
+ bhex[0] = '\0';
+ basc[0] = '\0';
+ }
+ if ((sw == 4) || (sw == 12)) {
+ strcat(bhex, " ");
+ }
+ if (sw == 8) {
+ strcat(bhex, " ");
+ }
+#if (CONFIG_ARCH_S390X)
+ sprintf(tbuf,"%2.2lX", (unsigned long)*ptr);
+#else
+ sprintf(tbuf,"%2.2X", (__u32)*ptr);
+#endif
+ tbuf[2] = '\0';
+ strcat(bhex, tbuf);
+ if ((0!=isprint(*ptr)) && (*ptr >= 0x20)) {
+ basc[sw] = *ptr;
+ }
+ else {
+ basc[sw] = '.';
+ }
+ basc[sw+1] = '\0';
+ sw++;
+ rm--;
+ if (sw==16) {
+ if ((strcmp(duphex, bhex)) !=0) {
+ if (dup !=0) {
+ sprintf(tdup,"Duplicate as above to"
+ " %s", addr);
+ printk( KERN_INFO " "
+ " --- %s ---\n",tdup);
+ }
+ printk( KERN_INFO " %s (+%s) : %s [%s]\n",
+ addr, boff, bhex, basc);
+ dup = 0;
+ strcpy(duphex, bhex);
+ }
+ else {
+ dup++;
+ }
+ sw = 0;
+ rm = 16;
+ }
+ } /* endfor */
+
+ if (sw != 0) {
+ for ( ; rm > 0; rm--, sw++ ) {
+ if ((sw==4) || (sw==12)) strcat(bhex, " ");
+ if (sw==8) strcat(bhex, " ");
+ strcat(bhex, " ");
+ strcat(basc, " ");
+ }
+ if (dup !=0) {
+ sprintf(tdup,"Duplicate as above to %s", addr);
+ printk( KERN_INFO " --- %s ---\n",
+ tdup);
+ }
+ printk( KERN_INFO " %s (+%s) : %s [%s]\n",
+ addr, boff, bhex, basc);
+ }
+ else {
+ if (dup >=1) {
+ sprintf(tdup,"Duplicate as above to %s", addr);
+ printk( KERN_INFO " --- %s ---\n",
+ tdup);
+ }
+ if (dup !=0) {
+ printk( KERN_INFO " %s (+%s) : %s [%s]\n",
+ addr, boff, bhex, basc);
+ }
+ }
+ return;
+
+} /* end of dumpit */
+#endif
+
+/*-------------------------------------------------------------------*
+* find_link *
+*--------------------------------------------------------------------*/
+static int
+find_link(struct net_device *dev, char *host_name, char *ws_name )
+{
+ struct claw_privbk *privptr;
+ struct claw_env *p_env;
+ int rc=0;
+
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s > enter \n",dev->name,__FUNCTION__);
+#endif
+ CLAW_DBF_TEXT(2,setup,"findlink");
+#ifdef DEBUGMSG
+ printk(KERN_INFO "%s: variable dev = \n",dev->name);
+ dumpit((char *) dev, sizeof(struct net_device));
+ printk(KERN_INFO "%s: variable host_name = %s\n",dev->name, host_name);
+ printk(KERN_INFO "%s: variable ws_name = %s\n",dev->name, ws_name);
+#endif
+ privptr=dev->priv;
+ p_env=privptr->p_env;
+ switch (p_env->packing)
+ {
+ case PACKING_ASK:
+ if ((memcmp(WS_APPL_NAME_PACKED, host_name, 8)!=0) ||
+ (memcmp(WS_APPL_NAME_PACKED, ws_name, 8)!=0 ))
+ rc = EINVAL;
+ break;
+ case DO_PACKED:
+ case PACK_SEND:
+ if ((memcmp(WS_APPL_NAME_IP_NAME, host_name, 8)!=0) ||
+ (memcmp(WS_APPL_NAME_IP_NAME, ws_name, 8)!=0 ))
+ rc = EINVAL;
+ break;
+ default:
+ if ((memcmp(HOST_APPL_NAME, host_name, 8)!=0) ||
+ (memcmp(p_env->api_type , ws_name, 8)!=0))
+ rc = EINVAL;
+ break;
+ }
+
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d\n",
+ dev->name,__FUNCTION__,__LINE__);
+#endif
+ return 0;
+} /* end of find_link */
+
+/*-------------------------------------------------------------------*
+ * claw_hw_tx *
+ * *
+ * *
+ *-------------------------------------------------------------------*/
+
+static int
+claw_hw_tx(struct sk_buff *skb, struct net_device *dev, long linkid)
+{
+ int rc=0;
+ struct claw_privbk *privptr;
+ struct ccwbk *p_this_ccw;
+ struct ccwbk *p_first_ccw;
+ struct ccwbk *p_last_ccw;
+ __u32 numBuffers;
+ signed long len_of_data;
+ unsigned long bytesInThisBuffer;
+ unsigned char *pDataAddress;
+ struct endccw *pEnd;
+ struct ccw1 tempCCW;
+ struct chbk *p_ch;
+ struct claw_env *p_env;
+ int lock;
+ struct clawph *pk_head;
+ struct chbk *ch;
+#ifdef IOTRACE
+ struct ccwbk *p_buf;
+#endif
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s: %s() > enter\n",dev->name,__FUNCTION__);
+#endif
+ CLAW_DBF_TEXT(4,trace,"hw_tx");
+#ifdef DEBUGMSG
+ printk(KERN_INFO "%s: variable dev skb =\n",dev->name);
+ dumpit((char *) skb, sizeof(struct sk_buff));
+ printk(KERN_INFO "%s: variable dev =\n",dev->name);
+ dumpit((char *) dev, sizeof(struct net_device));
+ printk(KERN_INFO "%s: variable linkid = %ld\n",dev->name,linkid);
+#endif
+ privptr = (struct claw_privbk *) (dev->priv);
+ p_ch=(struct chbk *)&privptr->channel[WRITE];
+ p_env =privptr->p_env;
+#ifdef IOTRACE
+ printk(KERN_INFO "%s: %s() dump sk_buff \n",dev->name,__FUNCTION__);
+ dumpit((char *)skb ,sizeof(struct sk_buff));
+#endif
+ claw_free_wrt_buf(dev); /* Clean up free chain if posible */
+ /* scan the write queue to free any completed write packets */
+ p_first_ccw=NULL;
+ p_last_ccw=NULL;
+ if ((p_env->packing >= PACK_SEND) &&
+ (skb->cb[1] != 'P')) {
+ skb_push(skb,sizeof(struct clawph));
+ pk_head=(struct clawph *)skb->data;
+ pk_head->len=skb->len-sizeof(struct clawph);
+ if (pk_head->len%4) {
+ pk_head->len+= 4-(pk_head->len%4);
+ skb_pad(skb,4-(pk_head->len%4));
+ skb_put(skb,4-(pk_head->len%4));
+ }
+ if (p_env->packing == DO_PACKED)
+ pk_head->link_num = linkid;
+ else
+ pk_head->link_num = 0;
+ pk_head->flag = 0x00;
+ skb_pad(skb,4);
+ skb->cb[1] = 'P';
+ }
+ if (linkid == 0) {
+ if (claw_check_busy(dev)) {
+ if (privptr->write_free_count!=0) {
+ claw_clear_busy(dev);
+ }
+ else {
+ claw_strt_out_IO(dev );
+ claw_free_wrt_buf( dev );
+ if (privptr->write_free_count==0) {
+#ifdef IOTRACE
+ printk(KERN_INFO "%s: "
+ "(claw_check_busy) no free write "
+ "buffers\n", dev->name);
+#endif
+ ch = &privptr->channel[WRITE];
+ atomic_inc(&skb->users);
+ skb_queue_tail(&ch->collect_queue, skb);
+ goto Done;
+ }
+ else {
+ claw_clear_busy(dev);
+ }
+ }
+ }
+ /* tx lock */
+ if (claw_test_and_setbit_busy(TB_TX,dev)) { /* set to busy */
+#ifdef DEBUGMSG
+ printk(KERN_INFO "%s: busy (claw_test_and_setbit_"
+ "busy)\n", dev->name);
+#endif
+ ch = &privptr->channel[WRITE];
+ atomic_inc(&skb->users);
+ skb_queue_tail(&ch->collect_queue, skb);
+ claw_strt_out_IO(dev );
+ rc=-EBUSY;
+ goto Done2;
+ }
+ }
+ /* See how many write buffers are required to hold this data */
+ numBuffers= ( skb->len + privptr->p_env->write_size - 1) /
+ ( privptr->p_env->write_size);
+
+ /* If that number of buffers isn't available, give up for now */
+ if (privptr->write_free_count < numBuffers ||
+ privptr->p_write_free_chain == NULL ) {
+
+ claw_setbit_busy(TB_NOBUFFER,dev);
+
+#ifdef DEBUGMSG
+ printk(KERN_INFO "%s: busy (claw_setbit_busy"
+ "(TB_NOBUFFER))\n", dev->name);
+ printk(KERN_INFO " free_count: %d, numBuffers : %d\n",
+ (int)privptr->write_free_count,(int) numBuffers );
+#endif
+ ch = &privptr->channel[WRITE];
+ atomic_inc(&skb->users);
+ skb_queue_tail(&ch->collect_queue, skb);
+ CLAW_DBF_TEXT(2,trace,"clawbusy");
+ goto Done2;
+ }
+ pDataAddress=skb->data;
+ len_of_data=skb->len;
+
+ while (len_of_data > 0) {
+#ifdef DEBUGMSG
+ printk(KERN_INFO "%s: %s() length-of-data is %ld \n",
+ dev->name ,__FUNCTION__,len_of_data);
+ dumpit((char *)pDataAddress ,64);
+#endif
+ p_this_ccw=privptr->p_write_free_chain; /* get a block */
+ if (p_this_ccw == NULL) { /* lost the race */
+ ch = &privptr->channel[WRITE];
+ atomic_inc(&skb->users);
+ skb_queue_tail(&ch->collect_queue, skb);
+ goto Done2;
+ }
+ privptr->p_write_free_chain=p_this_ccw->next;
+ p_this_ccw->next=NULL;
+ --privptr->write_free_count; /* -1 */
+ bytesInThisBuffer=len_of_data;
+ memcpy( p_this_ccw->p_buffer,pDataAddress, bytesInThisBuffer);
+ len_of_data-=bytesInThisBuffer;
+ pDataAddress+=(unsigned long)bytesInThisBuffer;
+ /* setup write CCW */
+ p_this_ccw->write.cmd_code = (linkid * 8) +1;
+ if (len_of_data>0) {
+ p_this_ccw->write.cmd_code+=MORE_to_COME_FLAG;
+ }
+ p_this_ccw->write.count=bytesInThisBuffer;
+ /* now add to end of this chain */
+ if (p_first_ccw==NULL) {
+ p_first_ccw=p_this_ccw;
+ }
+ if (p_last_ccw!=NULL) {
+ p_last_ccw->next=p_this_ccw;
+ /* set up TIC ccws */
+ p_last_ccw->w_TIC_1.cda=
+ (__u32)__pa(&p_this_ccw->write);
+ }
+ p_last_ccw=p_this_ccw; /* save new last block */
+#ifdef IOTRACE
+ printk(KERN_INFO "%s: %s() > CCW and Buffer %ld bytes long \n",
+ dev->name,__FUNCTION__,bytesInThisBuffer);
+ dumpit((char *)p_this_ccw, sizeof(struct ccwbk));
+ dumpit((char *)p_this_ccw->p_buffer, 64);
+#endif
+ }
+
+ /* FirstCCW and LastCCW now contain a new set of write channel
+ * programs to append to the running channel program
+ */
+
+ if (p_first_ccw!=NULL) {
+ /* setup ending ccw sequence for this segment */
+ pEnd=privptr->p_end_ccw;
+ if (pEnd->write1) {
+ pEnd->write1=0x00; /* second end ccw is now active */
+ /* set up Tic CCWs */
+ p_last_ccw->w_TIC_1.cda=
+ (__u32)__pa(&pEnd->write2_nop1);
+ pEnd->write2_nop2.cmd_code = CCW_CLAW_CMD_READFF;
+ pEnd->write2_nop2.flags =
+ CCW_FLAG_SLI | CCW_FLAG_SKIP;
+ pEnd->write2_nop2.cda=0;
+ pEnd->write2_nop2.count=1;
+ }
+ else { /* end of if (pEnd->write1)*/
+ pEnd->write1=0x01; /* first end ccw is now active */
+ /* set up Tic CCWs */
+ p_last_ccw->w_TIC_1.cda=
+ (__u32)__pa(&pEnd->write1_nop1);
+ pEnd->write1_nop2.cmd_code = CCW_CLAW_CMD_READFF;
+ pEnd->write1_nop2.flags =
+ CCW_FLAG_SLI | CCW_FLAG_SKIP;
+ pEnd->write1_nop2.cda=0;
+ pEnd->write1_nop2.count=1;
+ } /* end if if (pEnd->write1) */
+
+
+ if (privptr->p_write_active_first==NULL ) {
+ privptr->p_write_active_first=p_first_ccw;
+ privptr->p_write_active_last=p_last_ccw;
+ }
+ else {
+
+ /* set up Tic CCWs */
+
+ tempCCW.cda=(__u32)__pa(&p_first_ccw->write);
+ tempCCW.count=0;
+ tempCCW.flags=0;
+ tempCCW.cmd_code=CCW_CLAW_CMD_TIC;
+
+ if (pEnd->write1) {
+
+ /*
+ * first set of ending CCW's is chained to the new write
+ * chain, so the second set is chained to the active chain
+ * Therefore modify the second set to point the new write chain.
+ * make sure we update the CCW atomically
+ * so channel does not fetch it when it's only half done
+ */
+ memcpy( &pEnd->write2_nop2, &tempCCW ,
+ sizeof(struct ccw1));
+ privptr->p_write_active_last->w_TIC_1.cda=
+ (__u32)__pa(&p_first_ccw->write);
+ }
+ else {
+
+ /*make sure we update the CCW atomically
+ *so channel does not fetch it when it's only half done
+ */
+ memcpy(&pEnd->write1_nop2, &tempCCW ,
+ sizeof(struct ccw1));
+ privptr->p_write_active_last->w_TIC_1.cda=
+ (__u32)__pa(&p_first_ccw->write);
+
+ } /* end if if (pEnd->write1) */
+
+ privptr->p_write_active_last->next=p_first_ccw;
+ privptr->p_write_active_last=p_last_ccw;
+ }
+
+ } /* endif (p_first_ccw!=NULL) */
+
+
+#ifdef IOTRACE
+ printk(KERN_INFO "%s: %s() > Dump Active CCW chain \n",
+ dev->name,__FUNCTION__);
+ p_buf=privptr->p_write_active_first;
+ while (p_buf!=NULL) {
+ dumpit((char *)p_buf, sizeof(struct ccwbk));
+ p_buf=p_buf->next;
+ }
+ p_buf=(struct ccwbk*)privptr->p_end_ccw;
+ dumpit((char *)p_buf, sizeof(struct endccw));
+#endif
+ dev_kfree_skb(skb);
+ if (linkid==0) {
+ lock=LOCK_NO;
+ }
+ else {
+ lock=LOCK_YES;
+ }
+ claw_strt_out_IO(dev );
+ /* if write free count is zero , set NOBUFFER */
+#ifdef DEBUGMSG
+ printk(KERN_INFO "%s: %s() > free_count is %d\n",
+ dev->name,__FUNCTION__,
+ (int) privptr->write_free_count );
+#endif
+ if (privptr->write_free_count==0) {
+ claw_setbit_busy(TB_NOBUFFER,dev);
+ }
+Done2:
+ claw_clearbit_busy(TB_TX,dev);
+Done:
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s: %s() > exit on line %d, rc = %d \n",
+ dev->name,__FUNCTION__,__LINE__, rc);
+#endif
+ return(rc);
+} /* end of claw_hw_tx */
+
+/*-------------------------------------------------------------------*
+* *
+* init_ccw_bk *
+* *
+*--------------------------------------------------------------------*/
+
+static int
+init_ccw_bk(struct net_device *dev)
+{
+
+ __u32 ccw_blocks_required;
+ __u32 ccw_blocks_perpage;
+ __u32 ccw_pages_required;
+ __u32 claw_reads_perpage=1;
+ __u32 claw_read_pages;
+ __u32 claw_writes_perpage=1;
+ __u32 claw_write_pages;
+ void *p_buff=NULL;
+ struct ccwbk*p_free_chain;
+ struct ccwbk*p_buf;
+ struct ccwbk*p_last_CCWB;
+ struct ccwbk*p_first_CCWB;
+ struct endccw *p_endccw=NULL;
+ addr_t real_address;
+ struct claw_privbk *privptr=dev->priv;
+ struct clawh *pClawH=NULL;
+ addr_t real_TIC_address;
+ int i,j;
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s: %s() enter \n",dev->name,__FUNCTION__);
+#endif
+ CLAW_DBF_TEXT(4,trace,"init_ccw");
+#ifdef DEBUGMSG
+ printk(KERN_INFO "%s: variable dev =\n",dev->name);
+ dumpit((char *) dev, sizeof(struct net_device));
+#endif
+
+ /* initialize statistics field */
+ privptr->active_link_ID=0;
+ /* initialize ccwbk pointers */
+ privptr->p_write_free_chain=NULL; /* pointer to free ccw chain*/
+ privptr->p_write_active_first=NULL; /* pointer to the first write ccw*/
+ privptr->p_write_active_last=NULL; /* pointer to the last write ccw*/
+ privptr->p_read_active_first=NULL; /* pointer to the first read ccw*/
+ privptr->p_read_active_last=NULL; /* pointer to the last read ccw */
+ privptr->p_end_ccw=NULL; /* pointer to ending ccw */
+ privptr->p_claw_signal_blk=NULL; /* pointer to signal block */
+ privptr->buffs_alloc = 0;
+ memset(&privptr->end_ccw, 0x00, sizeof(struct endccw));
+ memset(&privptr->ctl_bk, 0x00, sizeof(struct clawctl));
+ /* initialize free write ccwbk counter */
+ privptr->write_free_count=0; /* number of free bufs on write chain */
+ p_last_CCWB = NULL;
+ p_first_CCWB= NULL;
+ /*
+ * We need 1 CCW block for each read buffer, 1 for each
+ * write buffer, plus 1 for ClawSignalBlock
+ */
+ ccw_blocks_required =
+ privptr->p_env->read_buffers+privptr->p_env->write_buffers+1;
+#ifdef DEBUGMSG
+ printk(KERN_INFO "%s: %s() "
+ "ccw_blocks_required=%d\n",
+ dev->name,__FUNCTION__,
+ ccw_blocks_required);
+ printk(KERN_INFO "%s: %s() "
+ "PAGE_SIZE=0x%x\n",
+ dev->name,__FUNCTION__,
+ (unsigned int)PAGE_SIZE);
+ printk(KERN_INFO "%s: %s() > "
+ "PAGE_MASK=0x%x\n",
+ dev->name,__FUNCTION__,
+ (unsigned int)PAGE_MASK);
+#endif
+ /*
+ * compute number of CCW blocks that will fit in a page
+ */
+ ccw_blocks_perpage= PAGE_SIZE / CCWBK_SIZE;
+ ccw_pages_required=
+ (ccw_blocks_required+ccw_blocks_perpage -1) /
+ ccw_blocks_perpage;
+
+#ifdef DEBUGMSG
+ printk(KERN_INFO "%s: %s() > ccw_blocks_perpage=%d\n",
+ dev->name,__FUNCTION__,
+ ccw_blocks_perpage);
+ printk(KERN_INFO "%s: %s() > ccw_pages_required=%d\n",
+ dev->name,__FUNCTION__,
+ ccw_pages_required);
+#endif
+ /*
+ * read and write sizes are set by 2 constants in claw.h
+ * 4k and 32k. Unpacked values other than 4k are not going to
+ * provide good performance. With packing buffers support 32k
+ * buffers are used.
+ */
+ if (privptr->p_env->read_size < PAGE_SIZE) {
+ claw_reads_perpage= PAGE_SIZE / privptr->p_env->read_size;
+ claw_read_pages= (privptr->p_env->read_buffers +
+ claw_reads_perpage -1) / claw_reads_perpage;
+ }
+ else { /* > or equal */
+ privptr->p_buff_pages_perread=
+ (privptr->p_env->read_size + PAGE_SIZE - 1) / PAGE_SIZE;
+ claw_read_pages=
+ privptr->p_env->read_buffers * privptr->p_buff_pages_perread;
+ }
+ if (privptr->p_env->write_size < PAGE_SIZE) {
+ claw_writes_perpage=
+ PAGE_SIZE / privptr->p_env->write_size;
+ claw_write_pages=
+ (privptr->p_env->write_buffers + claw_writes_perpage -1) /
+ claw_writes_perpage;
+
+ }
+ else { /* > or equal */
+ privptr->p_buff_pages_perwrite=
+ (privptr->p_env->read_size + PAGE_SIZE - 1) / PAGE_SIZE;
+ claw_write_pages=
+ privptr->p_env->write_buffers * privptr->p_buff_pages_perwrite;
+ }
+#ifdef DEBUGMSG
+ if (privptr->p_env->read_size < PAGE_SIZE) {
+ printk(KERN_INFO "%s: %s() reads_perpage=%d\n",
+ dev->name,__FUNCTION__,
+ claw_reads_perpage);
+ }
+ else {
+ printk(KERN_INFO "%s: %s() pages_perread=%d\n",
+ dev->name,__FUNCTION__,
+ privptr->p_buff_pages_perread);
+ }
+ printk(KERN_INFO "%s: %s() read_pages=%d\n",
+ dev->name,__FUNCTION__,
+ claw_read_pages);
+ if (privptr->p_env->write_size < PAGE_SIZE) {
+ printk(KERN_INFO "%s: %s() writes_perpage=%d\n",
+ dev->name,__FUNCTION__,
+ claw_writes_perpage);
+ }
+ else {
+ printk(KERN_INFO "%s: %s() pages_perwrite=%d\n",
+ dev->name,__FUNCTION__,
+ privptr->p_buff_pages_perwrite);
+ }
+ printk(KERN_INFO "%s: %s() write_pages=%d\n",
+ dev->name,__FUNCTION__,
+ claw_write_pages);
+#endif
+
+
+ /*
+ * allocate ccw_pages_required
+ */
+ if (privptr->p_buff_ccw==NULL) {
+ privptr->p_buff_ccw=
+ (void *)__get_free_pages(__GFP_DMA,
+ (int)pages_to_order_of_mag(ccw_pages_required ));
+ if (privptr->p_buff_ccw==NULL) {
+ printk(KERN_INFO "%s: %s() "
+ "__get_free_pages for CCWs failed : "
+ "pages is %d\n",
+ dev->name,__FUNCTION__,
+ ccw_pages_required );
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s: %s() > "
+ "exit on line %d, rc = ENOMEM\n",
+ dev->name,__FUNCTION__,
+ __LINE__);
+#endif
+ return -ENOMEM;
+ }
+ privptr->p_buff_ccw_num=ccw_pages_required;
+ }
+ memset(privptr->p_buff_ccw, 0x00,
+ privptr->p_buff_ccw_num * PAGE_SIZE);
+
+ /*
+ * obtain ending ccw block address
+ *
+ */
+ privptr->p_end_ccw = (struct endccw *)&privptr->end_ccw;
+ real_address = (__u32)__pa(privptr->p_end_ccw);
+ /* Initialize ending CCW block */
+#ifdef DEBUGMSG
+ printk(KERN_INFO "%s: %s() begin initialize ending CCW blocks\n",
+ dev->name,__FUNCTION__);
+#endif
+
+ p_endccw=privptr->p_end_ccw;
+ p_endccw->real=real_address;
+ p_endccw->write1=0x00;
+ p_endccw->read1=0x00;
+
+ /* write1_nop1 */
+ p_endccw->write1_nop1.cmd_code = CCW_CLAW_CMD_NOP;
+ p_endccw->write1_nop1.flags = CCW_FLAG_SLI | CCW_FLAG_CC;
+ p_endccw->write1_nop1.count = 1;
+ p_endccw->write1_nop1.cda = 0;
+
+ /* write1_nop2 */
+ p_endccw->write1_nop2.cmd_code = CCW_CLAW_CMD_READFF;
+ p_endccw->write1_nop2.flags = CCW_FLAG_SLI | CCW_FLAG_SKIP;
+ p_endccw->write1_nop2.count = 1;
+ p_endccw->write1_nop2.cda = 0;
+
+ /* write2_nop1 */
+ p_endccw->write2_nop1.cmd_code = CCW_CLAW_CMD_NOP;
+ p_endccw->write2_nop1.flags = CCW_FLAG_SLI | CCW_FLAG_CC;
+ p_endccw->write2_nop1.count = 1;
+ p_endccw->write2_nop1.cda = 0;
+
+ /* write2_nop2 */
+ p_endccw->write2_nop2.cmd_code = CCW_CLAW_CMD_READFF;
+ p_endccw->write2_nop2.flags = CCW_FLAG_SLI | CCW_FLAG_SKIP;
+ p_endccw->write2_nop2.count = 1;
+ p_endccw->write2_nop2.cda = 0;
+
+ /* read1_nop1 */
+ p_endccw->read1_nop1.cmd_code = CCW_CLAW_CMD_NOP;
+ p_endccw->read1_nop1.flags = CCW_FLAG_SLI | CCW_FLAG_CC;
+ p_endccw->read1_nop1.count = 1;
+ p_endccw->read1_nop1.cda = 0;
+
+ /* read1_nop2 */
+ p_endccw->read1_nop2.cmd_code = CCW_CLAW_CMD_READFF;
+ p_endccw->read1_nop2.flags = CCW_FLAG_SLI | CCW_FLAG_SKIP;
+ p_endccw->read1_nop2.count = 1;
+ p_endccw->read1_nop2.cda = 0;
+
+ /* read2_nop1 */
+ p_endccw->read2_nop1.cmd_code = CCW_CLAW_CMD_NOP;
+ p_endccw->read2_nop1.flags = CCW_FLAG_SLI | CCW_FLAG_CC;
+ p_endccw->read2_nop1.count = 1;
+ p_endccw->read2_nop1.cda = 0;
+
+ /* read2_nop2 */
+ p_endccw->read2_nop2.cmd_code = CCW_CLAW_CMD_READFF;
+ p_endccw->read2_nop2.flags = CCW_FLAG_SLI | CCW_FLAG_SKIP;
+ p_endccw->read2_nop2.count = 1;
+ p_endccw->read2_nop2.cda = 0;
+
+#ifdef IOTRACE
+ printk(KERN_INFO "%s: %s() dump claw ending CCW BK \n",
+ dev->name,__FUNCTION__);
+ dumpit((char *)p_endccw, sizeof(struct endccw));
+#endif
+
+ /*
+ * Build a chain of CCWs
+ *
+ */
+
+#ifdef DEBUGMSG
+ printk(KERN_INFO "%s: %s() Begin build a chain of CCW buffer \n",
+ dev->name,__FUNCTION__);
+#endif
+ p_buff=privptr->p_buff_ccw;
+
+ p_free_chain=NULL;
+ for (i=0 ; i < ccw_pages_required; i++ ) {
+ real_address = (__u32)__pa(p_buff);
+ p_buf=p_buff;
+ for (j=0 ; j < ccw_blocks_perpage ; j++) {
+ p_buf->next = p_free_chain;
+ p_free_chain = p_buf;
+ p_buf->real=(__u32)__pa(p_buf);
+ ++p_buf;
+ }
+ p_buff+=PAGE_SIZE;
+ }
+#ifdef DEBUGMSG
+ printk(KERN_INFO "%s: %s() "
+ "End build a chain of CCW buffer \n",
+ dev->name,__FUNCTION__);
+ p_buf=p_free_chain;
+ while (p_buf!=NULL) {
+ dumpit((char *)p_buf, sizeof(struct ccwbk));
+ p_buf=p_buf->next;
+ }
+#endif
+
+ /*
+ * Initialize ClawSignalBlock
+ *
+ */
+#ifdef DEBUGMSG
+ printk(KERN_INFO "%s: %s() "
+ "Begin initialize ClawSignalBlock \n",
+ dev->name,__FUNCTION__);
+#endif
+ if (privptr->p_claw_signal_blk==NULL) {
+ privptr->p_claw_signal_blk=p_free_chain;
+ p_free_chain=p_free_chain->next;
+ pClawH=(struct clawh *)privptr->p_claw_signal_blk;
+ pClawH->length=0xffff;
+ pClawH->opcode=0xff;
+ pClawH->flag=CLAW_BUSY;
+ }
+#ifdef DEBUGMSG
+ printk(KERN_INFO "%s: %s() > End initialize "
+ "ClawSignalBlock\n",
+ dev->name,__FUNCTION__);
+ dumpit((char *)privptr->p_claw_signal_blk, sizeof(struct ccwbk));
+#endif
+
+ /*
+ * allocate write_pages_required and add to free chain
+ */
+ if (privptr->p_buff_write==NULL) {
+ if (privptr->p_env->write_size < PAGE_SIZE) {
+ privptr->p_buff_write=
+ (void *)__get_free_pages(__GFP_DMA,
+ (int)pages_to_order_of_mag(claw_write_pages ));
+ if (privptr->p_buff_write==NULL) {
+ printk(KERN_INFO "%s: %s() __get_free_pages for write"
+ " bufs failed : get is for %d pages\n",
+ dev->name,__FUNCTION__,claw_write_pages );
+ free_pages((unsigned long)privptr->p_buff_ccw,
+ (int)pages_to_order_of_mag(privptr->p_buff_ccw_num));
+ privptr->p_buff_ccw=NULL;
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s: %s() > exit on line %d,"
+ "rc = ENOMEM\n",
+ dev->name,__FUNCTION__,__LINE__);
+#endif
+ return -ENOMEM;
+ }
+ /*
+ * Build CLAW write free chain
+ *
+ */
+
+ memset(privptr->p_buff_write, 0x00,
+ ccw_pages_required * PAGE_SIZE);
+#ifdef DEBUGMSG
+ printk(KERN_INFO "%s: %s() Begin build claw write free "
+ "chain \n",dev->name,__FUNCTION__);
+#endif
+ privptr->p_write_free_chain=NULL;
+
+ p_buff=privptr->p_buff_write;
+
+ for (i=0 ; i< privptr->p_env->write_buffers ; i++) {
+ p_buf = p_free_chain; /* get a CCW */
+ p_free_chain = p_buf->next;
+ p_buf->next =privptr->p_write_free_chain;
+ privptr->p_write_free_chain = p_buf;
+ p_buf-> p_buffer = (struct clawbuf *)p_buff;
+ p_buf-> write.cda = (__u32)__pa(p_buff);
+ p_buf-> write.flags = CCW_FLAG_SLI | CCW_FLAG_CC;
+ p_buf-> w_read_FF.cmd_code = CCW_CLAW_CMD_READFF;
+ p_buf-> w_read_FF.flags = CCW_FLAG_SLI | CCW_FLAG_CC;
+ p_buf-> w_read_FF.count = 1;
+ p_buf-> w_read_FF.cda =
+ (__u32)__pa(&p_buf-> header.flag);
+ p_buf-> w_TIC_1.cmd_code = CCW_CLAW_CMD_TIC;
+ p_buf-> w_TIC_1.flags = 0;
+ p_buf-> w_TIC_1.count = 0;
+
+ if (((unsigned long)p_buff+privptr->p_env->write_size) >=
+ ((unsigned long)(p_buff+2*
+ (privptr->p_env->write_size) -1) & PAGE_MASK)) {
+ p_buff= p_buff+privptr->p_env->write_size;
+ }
+ }
+ }
+ else /* Buffers are => PAGE_SIZE. 1 buff per get_free_pages */
+ {
+ privptr->p_write_free_chain=NULL;
+ for (i = 0; i< privptr->p_env->write_buffers ; i++) {
+ p_buff=(void *)__get_free_pages(__GFP_DMA,
+ (int)pages_to_order_of_mag(
+ privptr->p_buff_pages_perwrite) );
+#ifdef IOTRACE
+ printk(KERN_INFO "%s:%s __get_free_pages "
+ "for writes buf: get for %d pages\n",
+ dev->name,__FUNCTION__,
+ privptr->p_buff_pages_perwrite);
+#endif
+ if (p_buff==NULL) {
+ printk(KERN_INFO "%s:%s __get_free_pages"
+ "for writes buf failed : get is for %d pages\n",
+ dev->name,
+ __FUNCTION__,
+ privptr->p_buff_pages_perwrite );
+ free_pages((unsigned long)privptr->p_buff_ccw,
+ (int)pages_to_order_of_mag(
+ privptr->p_buff_ccw_num));
+ privptr->p_buff_ccw=NULL;
+ p_buf=privptr->p_buff_write;
+ while (p_buf!=NULL) {
+ free_pages((unsigned long)
+ p_buf->p_buffer,
+ (int)pages_to_order_of_mag(
+ privptr->p_buff_pages_perwrite));
+ p_buf=p_buf->next;
+ }
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s: %s exit on line %d, rc = ENOMEM\n",
+ dev->name,
+ __FUNCTION__,
+ __LINE__);
+#endif
+ return -ENOMEM;
+ } /* Error on get_pages */
+ memset(p_buff, 0x00, privptr->p_env->write_size );
+ p_buf = p_free_chain;
+ p_free_chain = p_buf->next;
+ p_buf->next = privptr->p_write_free_chain;
+ privptr->p_write_free_chain = p_buf;
+ privptr->p_buff_write = p_buf;
+ p_buf->p_buffer=(struct clawbuf *)p_buff;
+ p_buf-> write.cda = (__u32)__pa(p_buff);
+ p_buf-> write.flags = CCW_FLAG_SLI | CCW_FLAG_CC;
+ p_buf-> w_read_FF.cmd_code = CCW_CLAW_CMD_READFF;
+ p_buf-> w_read_FF.flags = CCW_FLAG_SLI | CCW_FLAG_CC;
+ p_buf-> w_read_FF.count = 1;
+ p_buf-> w_read_FF.cda =
+ (__u32)__pa(&p_buf-> header.flag);
+ p_buf-> w_TIC_1.cmd_code = CCW_CLAW_CMD_TIC;
+ p_buf-> w_TIC_1.flags = 0;
+ p_buf-> w_TIC_1.count = 0;
+ } /* for all write_buffers */
+
+ } /* else buffers are PAGE_SIZE or bigger */
+
+ }
+ privptr->p_buff_write_num=claw_write_pages;
+ privptr->write_free_count=privptr->p_env->write_buffers;
+
+
+#ifdef DEBUGMSG
+ printk(KERN_INFO "%s:%s End build claw write free chain \n",
+ dev->name,__FUNCTION__);
+ p_buf=privptr->p_write_free_chain;
+ while (p_buf!=NULL) {
+ dumpit((char *)p_buf, sizeof(struct ccwbk));
+ p_buf=p_buf->next;
+ }
+#endif
+ /*
+ * allocate read_pages_required and chain to free chain
+ */
+ if (privptr->p_buff_read==NULL) {
+ if (privptr->p_env->read_size < PAGE_SIZE) {
+ privptr->p_buff_read=
+ (void *)__get_free_pages(__GFP_DMA,
+ (int)pages_to_order_of_mag(claw_read_pages) );
+ if (privptr->p_buff_read==NULL) {
+ printk(KERN_INFO "%s: %s() "
+ "__get_free_pages for read buf failed : "
+ "get is for %d pages\n",
+ dev->name,__FUNCTION__,claw_read_pages );
+ free_pages((unsigned long)privptr->p_buff_ccw,
+ (int)pages_to_order_of_mag(
+ privptr->p_buff_ccw_num));
+ /* free the write pages size is < page size */
+ free_pages((unsigned long)privptr->p_buff_write,
+ (int)pages_to_order_of_mag(
+ privptr->p_buff_write_num));
+ privptr->p_buff_ccw=NULL;
+ privptr->p_buff_write=NULL;
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s: %s() > exit on line %d, rc ="
+ " ENOMEM\n",dev->name,__FUNCTION__,__LINE__);
+#endif
+ return -ENOMEM;
+ }
+ memset(privptr->p_buff_read, 0x00, claw_read_pages * PAGE_SIZE);
+ privptr->p_buff_read_num=claw_read_pages;
+ /*
+ * Build CLAW read free chain
+ *
+ */
+#ifdef DEBUGMSG
+ printk(KERN_INFO "%s: %s() Begin build claw read free chain \n",
+ dev->name,__FUNCTION__);
+#endif
+ p_buff=privptr->p_buff_read;
+ for (i=0 ; i< privptr->p_env->read_buffers ; i++) {
+ p_buf = p_free_chain;
+ p_free_chain = p_buf->next;
+
+ if (p_last_CCWB==NULL) {
+ p_buf->next=NULL;
+ real_TIC_address=0;
+ p_last_CCWB=p_buf;
+ }
+ else {
+ p_buf->next=p_first_CCWB;
+ real_TIC_address=
+ (__u32)__pa(&p_first_CCWB -> read );
+ }
+
+ p_first_CCWB=p_buf;
+
+ p_buf->p_buffer=(struct clawbuf *)p_buff;
+ /* initialize read command */
+ p_buf-> read.cmd_code = CCW_CLAW_CMD_READ;
+ p_buf-> read.cda = (__u32)__pa(p_buff);
+ p_buf-> read.flags = CCW_FLAG_SLI | CCW_FLAG_CC;
+ p_buf-> read.count = privptr->p_env->read_size;
+
+ /* initialize read_h command */
+ p_buf-> read_h.cmd_code = CCW_CLAW_CMD_READHEADER;
+ p_buf-> read_h.cda =
+ (__u32)__pa(&(p_buf->header));
+ p_buf-> read_h.flags = CCW_FLAG_SLI | CCW_FLAG_CC;
+ p_buf-> read_h.count = sizeof(struct clawh);
+
+ /* initialize Signal command */
+ p_buf-> signal.cmd_code = CCW_CLAW_CMD_SIGNAL_SMOD;
+ p_buf-> signal.cda =
+ (__u32)__pa(&(pClawH->flag));
+ p_buf-> signal.flags = CCW_FLAG_SLI | CCW_FLAG_CC;
+ p_buf-> signal.count = 1;
+
+ /* initialize r_TIC_1 command */
+ p_buf-> r_TIC_1.cmd_code = CCW_CLAW_CMD_TIC;
+ p_buf-> r_TIC_1.cda = (__u32)real_TIC_address;
+ p_buf-> r_TIC_1.flags = 0;
+ p_buf-> r_TIC_1.count = 0;
+
+ /* initialize r_read_FF command */
+ p_buf-> r_read_FF.cmd_code = CCW_CLAW_CMD_READFF;
+ p_buf-> r_read_FF.cda =
+ (__u32)__pa(&(pClawH->flag));
+ p_buf-> r_read_FF.flags =
+ CCW_FLAG_SLI | CCW_FLAG_CC | CCW_FLAG_PCI;
+ p_buf-> r_read_FF.count = 1;
+
+ /* initialize r_TIC_2 */
+ memcpy(&p_buf->r_TIC_2,
+ &p_buf->r_TIC_1, sizeof(struct ccw1));
+
+ /* initialize Header */
+ p_buf->header.length=0xffff;
+ p_buf->header.opcode=0xff;
+ p_buf->header.flag=CLAW_PENDING;
+
+ if (((unsigned long)p_buff+privptr->p_env->read_size) >=
+ ((unsigned long)(p_buff+2*(privptr->p_env->read_size) -1)
+ & PAGE_MASK) ) {
+ p_buff= p_buff+privptr->p_env->read_size;
+ }
+ else {
+ p_buff=
+ (void *)((unsigned long)
+ (p_buff+2*(privptr->p_env->read_size) -1)
+ & PAGE_MASK) ;
+ }
+ } /* for read_buffers */
+ } /* read_size < PAGE_SIZE */
+ else { /* read Size >= PAGE_SIZE */
+
+#ifdef DEBUGMSG
+ printk(KERN_INFO "%s: %s() Begin build claw read free chain \n",
+ dev->name,__FUNCTION__);
+#endif
+ for (i=0 ; i< privptr->p_env->read_buffers ; i++) {
+ p_buff = (void *)__get_free_pages(__GFP_DMA,
+ (int)pages_to_order_of_mag(privptr->p_buff_pages_perread) );
+ if (p_buff==NULL) {
+ printk(KERN_INFO "%s: %s() __get_free_pages for read "
+ "buf failed : get is for %d pages\n",
+ dev->name,__FUNCTION__,
+ privptr->p_buff_pages_perread );
+ free_pages((unsigned long)privptr->p_buff_ccw,
+ (int)pages_to_order_of_mag(privptr->p_buff_ccw_num));
+ /* free the write pages */
+ p_buf=privptr->p_buff_write;
+ while (p_buf!=NULL) {
+ free_pages((unsigned long)p_buf->p_buffer,
+ (int)pages_to_order_of_mag(
+ privptr->p_buff_pages_perwrite ));
+ p_buf=p_buf->next;
+ }
+ /* free any read pages already alloc */
+ p_buf=privptr->p_buff_read;
+ while (p_buf!=NULL) {
+ free_pages((unsigned long)p_buf->p_buffer,
+ (int)pages_to_order_of_mag(
+ privptr->p_buff_pages_perread ));
+ p_buf=p_buf->next;
+ }
+ privptr->p_buff_ccw=NULL;
+ privptr->p_buff_write=NULL;
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s: %s() exit on line %d, rc = ENOMEM\n",
+ dev->name,__FUNCTION__,
+ __LINE__);
+#endif
+ return -ENOMEM;
+ }
+ memset(p_buff, 0x00, privptr->p_env->read_size);
+ p_buf = p_free_chain;
+ privptr->p_buff_read = p_buf;
+ p_free_chain = p_buf->next;
+
+ if (p_last_CCWB==NULL) {
+ p_buf->next=NULL;
+ real_TIC_address=0;
+ p_last_CCWB=p_buf;
+ }
+ else {
+ p_buf->next=p_first_CCWB;
+ real_TIC_address=
+ (addr_t)__pa(
+ &p_first_CCWB -> read );
+ }
+
+ p_first_CCWB=p_buf;
+ /* save buff address */
+ p_buf->p_buffer=(struct clawbuf *)p_buff;
+ /* initialize read command */
+ p_buf-> read.cmd_code = CCW_CLAW_CMD_READ;
+ p_buf-> read.cda = (__u32)__pa(p_buff);
+ p_buf-> read.flags = CCW_FLAG_SLI | CCW_FLAG_CC;
+ p_buf-> read.count = privptr->p_env->read_size;
+
+ /* initialize read_h command */
+ p_buf-> read_h.cmd_code = CCW_CLAW_CMD_READHEADER;
+ p_buf-> read_h.cda =
+ (__u32)__pa(&(p_buf->header));
+ p_buf-> read_h.flags = CCW_FLAG_SLI | CCW_FLAG_CC;
+ p_buf-> read_h.count = sizeof(struct clawh);
+
+ /* initialize Signal command */
+ p_buf-> signal.cmd_code = CCW_CLAW_CMD_SIGNAL_SMOD;
+ p_buf-> signal.cda =
+ (__u32)__pa(&(pClawH->flag));
+ p_buf-> signal.flags = CCW_FLAG_SLI | CCW_FLAG_CC;
+ p_buf-> signal.count = 1;
+
+ /* initialize r_TIC_1 command */
+ p_buf-> r_TIC_1.cmd_code = CCW_CLAW_CMD_TIC;
+ p_buf-> r_TIC_1.cda = (__u32)real_TIC_address;
+ p_buf-> r_TIC_1.flags = 0;
+ p_buf-> r_TIC_1.count = 0;
+
+ /* initialize r_read_FF command */
+ p_buf-> r_read_FF.cmd_code = CCW_CLAW_CMD_READFF;
+ p_buf-> r_read_FF.cda =
+ (__u32)__pa(&(pClawH->flag));
+ p_buf-> r_read_FF.flags =
+ CCW_FLAG_SLI | CCW_FLAG_CC | CCW_FLAG_PCI;
+ p_buf-> r_read_FF.count = 1;
+
+ /* initialize r_TIC_2 */
+ memcpy(&p_buf->r_TIC_2, &p_buf->r_TIC_1,
+ sizeof(struct ccw1));
+
+ /* initialize Header */
+ p_buf->header.length=0xffff;
+ p_buf->header.opcode=0xff;
+ p_buf->header.flag=CLAW_PENDING;
+
+ } /* For read_buffers */
+ } /* read_size >= PAGE_SIZE */
+ } /* pBuffread = NULL */
+#ifdef DEBUGMSG
+ printk(KERN_INFO "%s: %s() > End build claw read free chain \n",
+ dev->name,__FUNCTION__);
+ p_buf=p_first_CCWB;
+ while (p_buf!=NULL) {
+ dumpit((char *)p_buf, sizeof(struct ccwbk));
+ p_buf=p_buf->next;
+ }
+
+#endif
+ add_claw_reads( dev ,p_first_CCWB , p_last_CCWB);
+ privptr->buffs_alloc = 1;
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s: %s() exit on line %d\n",
+ dev->name,__FUNCTION__,__LINE__);
+#endif
+ return 0;
+} /* end of init_ccw_bk */
+
+/*-------------------------------------------------------------------*
+* *
+* probe_error *
+* *
+*--------------------------------------------------------------------*/
+
+static void
+probe_error( struct ccwgroup_device *cgdev)
+{
+ struct claw_privbk *privptr;
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s enter \n",__FUNCTION__);
+#endif
+ CLAW_DBF_TEXT(4,trace,"proberr");
+#ifdef DEBUGMSG
+ printk(KERN_INFO "%s variable cgdev =\n",__FUNCTION__);
+ dumpit((char *) cgdev, sizeof(struct ccwgroup_device));
+#endif
+ privptr=(struct claw_privbk *)cgdev->dev.driver_data;
+ if (privptr!=NULL) {
+ if (privptr->p_env != NULL) {
+ kfree(privptr->p_env);
+ privptr->p_env=NULL;
+ }
+ if (privptr->p_mtc_envelope!=NULL) {
+ kfree(privptr->p_mtc_envelope);
+ privptr->p_mtc_envelope=NULL;
+ }
+ kfree(privptr);
+ privptr=NULL;
+ }
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s > exit on line %d\n",
+ __FUNCTION__,__LINE__);
+#endif
+
+ return;
+} /* probe_error */
+
+
+
+/*-------------------------------------------------------------------*
+* claw_process_control *
+* *
+* *
+*--------------------------------------------------------------------*/
+
+static int
+claw_process_control( struct net_device *dev, struct ccwbk * p_ccw)
+{
+
+ struct clawbuf *p_buf;
+ struct clawctl ctlbk;
+ struct clawctl *p_ctlbk;
+ char temp_host_name[8];
+ char temp_ws_name[8];
+ struct claw_privbk *privptr;
+ struct claw_env *p_env;
+ struct sysval *p_sysval;
+ struct conncmd *p_connect=NULL;
+ int rc;
+ struct chbk *p_ch = NULL;
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s: %s() > enter \n",
+ dev->name,__FUNCTION__);
+#endif
+ CLAW_DBF_TEXT(2,setup,"clw_cntl");
+#ifdef DEBUGMSG
+ printk(KERN_INFO "%s: variable dev =\n",dev->name);
+ dumpit((char *) dev, sizeof(struct net_device));
+ printk(KERN_INFO "%s: variable p_ccw =\n",dev->name);
+ dumpit((char *) p_ccw, sizeof(struct ccwbk *));
+#endif
+ udelay(1000); /* Wait a ms for the control packets to
+ *catch up to each other */
+ privptr=dev->priv;
+ p_env=privptr->p_env;
+ memcpy( &temp_host_name, p_env->host_name, 8);
+ memcpy( &temp_ws_name, p_env->adapter_name , 8);
+ printk(KERN_INFO "%s: CLAW device %.8s: "
+ "Received Control Packet\n",
+ dev->name, temp_ws_name);
+ if (privptr->release_pend==1) {
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s: %s() > "
+ "exit on line %d, rc=0\n",
+ dev->name,__FUNCTION__,__LINE__);
+#endif
+ return 0;
+ }
+ p_buf=p_ccw->p_buffer;
+ p_ctlbk=&ctlbk;
+ if (p_env->packing == DO_PACKED) { /* packing in progress?*/
+ memcpy(p_ctlbk, &p_buf->buffer[4], sizeof(struct clawctl));
+ } else {
+ memcpy(p_ctlbk, p_buf, sizeof(struct clawctl));
+ }
+#ifdef IOTRACE
+ printk(KERN_INFO "%s: dump claw control data inbound\n",dev->name);
+ dumpit((char *)p_ctlbk, sizeof(struct clawctl));
+#endif
+ switch (p_ctlbk->command)
+ {
+ case SYSTEM_VALIDATE_REQUEST:
+ if (p_ctlbk->version!=CLAW_VERSION_ID) {
+ claw_snd_sys_validate_rsp(dev, p_ctlbk,
+ CLAW_RC_WRONG_VERSION );
+ printk("%s: %d is wrong version id. "
+ "Expected %d\n",
+ dev->name, p_ctlbk->version,
+ CLAW_VERSION_ID);
+ }
+ p_sysval=(struct sysval *)&(p_ctlbk->data);
+ printk( "%s: Recv Sys Validate Request: "
+ "Vers=%d,link_id=%d,Corr=%d,WS name=%."
+ "8s,Host name=%.8s\n",
+ dev->name, p_ctlbk->version,
+ p_ctlbk->linkid,
+ p_ctlbk->correlator,
+ p_sysval->WS_name,
+ p_sysval->host_name);
+ if (0!=memcmp(temp_host_name,p_sysval->host_name,8)) {
+ claw_snd_sys_validate_rsp(dev, p_ctlbk,
+ CLAW_RC_NAME_MISMATCH );
+ CLAW_DBF_TEXT(2,setup,"HSTBAD");
+ CLAW_DBF_TEXT_(2,setup,"%s",p_sysval->host_name);
+ CLAW_DBF_TEXT_(2,setup,"%s",temp_host_name);
+ printk(KERN_INFO "%s: Host name mismatch\n",
+ dev->name);
+ printk(KERN_INFO "%s: Received :%s: "
+ "expected :%s: \n",
+ dev->name,
+ p_sysval->host_name,
+ temp_host_name);
+ }
+ if (0!=memcmp(temp_ws_name,p_sysval->WS_name,8)) {
+ claw_snd_sys_validate_rsp(dev, p_ctlbk,
+ CLAW_RC_NAME_MISMATCH );
+ CLAW_DBF_TEXT(2,setup,"WSNBAD");
+ CLAW_DBF_TEXT_(2,setup,"%s",p_sysval->WS_name);
+ CLAW_DBF_TEXT_(2,setup,"%s",temp_ws_name);
+ printk(KERN_INFO "%s: WS name mismatch\n",
+ dev->name);
+ printk(KERN_INFO "%s: Received :%s: "
+ "expected :%s: \n",
+ dev->name,
+ p_sysval->WS_name,
+ temp_ws_name);
+ }
+ if (( p_sysval->write_frame_size < p_env->write_size) &&
+ ( p_env->packing == 0)) {
+ claw_snd_sys_validate_rsp(dev, p_ctlbk,
+ CLAW_RC_HOST_RCV_TOO_SMALL );
+ printk(KERN_INFO "%s: host write size is too "
+ "small\n", dev->name);
+ CLAW_DBF_TEXT(2,setup,"wrtszbad");
+ }
+ if (( p_sysval->read_frame_size < p_env->read_size) &&
+ ( p_env->packing == 0)) {
+ claw_snd_sys_validate_rsp(dev, p_ctlbk,
+ CLAW_RC_HOST_RCV_TOO_SMALL );
+ printk(KERN_INFO "%s: host read size is too "
+ "small\n", dev->name);
+ CLAW_DBF_TEXT(2,setup,"rdsizbad");
+ }
+ claw_snd_sys_validate_rsp(dev, p_ctlbk, 0 );
+ printk("%s: CLAW device %.8s: System validate"
+ " completed.\n",dev->name, temp_ws_name);
+ printk("%s: sys Validate Rsize:%d Wsize:%d\n",dev->name,
+ p_sysval->read_frame_size,p_sysval->write_frame_size);
+ privptr->system_validate_comp=1;
+ if(strncmp(p_env->api_type,WS_APPL_NAME_PACKED,6) == 0) {
+ p_env->packing = PACKING_ASK;
+ }
+ claw_strt_conn_req(dev);
+ break;
+
+ case SYSTEM_VALIDATE_RESPONSE:
+ p_sysval=(struct sysval *)&(p_ctlbk->data);
+ printk("%s: Recv Sys Validate Resp: Vers=%d,Corr=%d,RC=%d,"
+ "WS name=%.8s,Host name=%.8s\n",
+ dev->name,
+ p_ctlbk->version,
+ p_ctlbk->correlator,
+ p_ctlbk->rc,
+ p_sysval->WS_name,
+ p_sysval->host_name);
+ switch (p_ctlbk->rc)
+ {
+ case 0:
+ printk(KERN_INFO "%s: CLAW device "
+ "%.8s: System validate "
+ "completed.\n",
+ dev->name, temp_ws_name);
+ if (privptr->system_validate_comp == 0)
+ claw_strt_conn_req(dev);
+ privptr->system_validate_comp=1;
+ break;
+ case CLAW_RC_NAME_MISMATCH:
+ printk(KERN_INFO "%s: Sys Validate "
+ "Resp : Host, WS name is "
+ "mismatch\n",
+ dev->name);
+ break;
+ case CLAW_RC_WRONG_VERSION:
+ printk(KERN_INFO "%s: Sys Validate "
+ "Resp : Wrong version\n",
+ dev->name);
+ break;
+ case CLAW_RC_HOST_RCV_TOO_SMALL:
+ printk(KERN_INFO "%s: Sys Validate "
+ "Resp : bad frame size\n",
+ dev->name);
+ break;
+ default:
+ printk(KERN_INFO "%s: Sys Validate "
+ "error code=%d \n",
+ dev->name, p_ctlbk->rc );
+ break;
+ }
+ break;
+
+ case CONNECTION_REQUEST:
+ p_connect=(struct conncmd *)&(p_ctlbk->data);
+ printk(KERN_INFO "%s: Recv Conn Req: Vers=%d,link_id=%d,"
+ "Corr=%d,HOST appl=%.8s,WS appl=%.8s\n",
+ dev->name,
+ p_ctlbk->version,
+ p_ctlbk->linkid,
+ p_ctlbk->correlator,
+ p_connect->host_name,
+ p_connect->WS_name);
+ if (privptr->active_link_ID!=0 ) {
+ claw_snd_disc(dev, p_ctlbk);
+ printk(KERN_INFO "%s: Conn Req error : "
+ "already logical link is active \n",
+ dev->name);
+ }
+ if (p_ctlbk->linkid!=1 ) {
+ claw_snd_disc(dev, p_ctlbk);
+ printk(KERN_INFO "%s: Conn Req error : "
+ "req logical link id is not 1\n",
+ dev->name);
+ }
+ rc=find_link(dev,
+ p_connect->host_name, p_connect->WS_name);
+ if (rc!=0) {
+ claw_snd_disc(dev, p_ctlbk);
+ printk(KERN_INFO "%s: Conn Req error : "
+ "req appl name does not match\n",
+ dev->name);
+ }
+ claw_send_control(dev,
+ CONNECTION_CONFIRM, p_ctlbk->linkid,
+ p_ctlbk->correlator,
+ 0, p_connect->host_name,
+ p_connect->WS_name);
+ if (p_env->packing == PACKING_ASK) {
+ printk("%s: Now Pack ask\n",dev->name);
+ p_env->packing = PACK_SEND;
+ claw_snd_conn_req(dev,0);
+ }
+ printk(KERN_INFO "%s: CLAW device %.8s: Connection "
+ "completed link_id=%d.\n",
+ dev->name, temp_ws_name,
+ p_ctlbk->linkid);
+ privptr->active_link_ID=p_ctlbk->linkid;
+ p_ch=&privptr->channel[WRITE];
+ wake_up(&p_ch->wait); /* wake up claw_open ( WRITE) */
+ break;
+ case CONNECTION_RESPONSE:
+ p_connect=(struct conncmd *)&(p_ctlbk->data);
+ printk(KERN_INFO "%s: Revc Conn Resp: Vers=%d,link_id=%d,"
+ "Corr=%d,RC=%d,Host appl=%.8s, WS appl=%.8s\n",
+ dev->name,
+ p_ctlbk->version,
+ p_ctlbk->linkid,
+ p_ctlbk->correlator,
+ p_ctlbk->rc,
+ p_connect->host_name,
+ p_connect->WS_name);
+
+ if (p_ctlbk->rc !=0 ) {
+ printk(KERN_INFO "%s: Conn Resp error: rc=%d \n",
+ dev->name, p_ctlbk->rc);
+ return 1;
+ }
+ rc=find_link(dev,
+ p_connect->host_name, p_connect->WS_name);
+ if (rc!=0) {
+ claw_snd_disc(dev, p_ctlbk);
+ printk(KERN_INFO "%s: Conn Resp error: "
+ "req appl name does not match\n",
+ dev->name);
+ }
+ /* should be until CONNECTION_CONFIRM */
+ privptr->active_link_ID = - (p_ctlbk->linkid);
+ break;
+ case CONNECTION_CONFIRM:
+ p_connect=(struct conncmd *)&(p_ctlbk->data);
+ printk(KERN_INFO "%s: Recv Conn Confirm:Vers=%d,link_id=%d,"
+ "Corr=%d,Host appl=%.8s,WS appl=%.8s\n",
+ dev->name,
+ p_ctlbk->version,
+ p_ctlbk->linkid,
+ p_ctlbk->correlator,
+ p_connect->host_name,
+ p_connect->WS_name);
+ if (p_ctlbk->linkid== -(privptr->active_link_ID)) {
+ privptr->active_link_ID=p_ctlbk->linkid;
+ if (p_env->packing > PACKING_ASK) {
+ printk(KERN_INFO "%s: Confirmed Now packing\n",dev->name);
+ p_env->packing = DO_PACKED;
+ }
+ p_ch=&privptr->channel[WRITE];
+ wake_up(&p_ch->wait);
+ }
+ else {
+ printk(KERN_INFO "%s: Conn confirm: "
+ "unexpected linkid=%d \n",
+ dev->name, p_ctlbk->linkid);
+ claw_snd_disc(dev, p_ctlbk);
+ }
+ break;
+ case DISCONNECT:
+ printk(KERN_INFO "%s: Disconnect: "
+ "Vers=%d,link_id=%d,Corr=%d\n",
+ dev->name, p_ctlbk->version,
+ p_ctlbk->linkid, p_ctlbk->correlator);
+ if ((p_ctlbk->linkid == 2) &&
+ (p_env->packing == PACK_SEND)) {
+ privptr->active_link_ID = 1;
+ p_env->packing = DO_PACKED;
+ }
+ else
+ privptr->active_link_ID=0;
+ break;
+ case CLAW_ERROR:
+ printk(KERN_INFO "%s: CLAW ERROR detected\n",
+ dev->name);
+ break;
+ default:
+ printk(KERN_INFO "%s: Unexpected command code=%d \n",
+ dev->name, p_ctlbk->command);
+ break;
+ }
+
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s: %s() exit on line %d, rc = 0\n",
+ dev->name,__FUNCTION__,__LINE__);
+#endif
+
+ return 0;
+} /* end of claw_process_control */
+
+
+/*-------------------------------------------------------------------*
+* claw_send_control *
+* *
+*--------------------------------------------------------------------*/
+
+static int
+claw_send_control(struct net_device *dev, __u8 type, __u8 link,
+ __u8 correlator, __u8 rc, char *local_name, char *remote_name)
+{
+ struct claw_privbk *privptr;
+ struct clawctl *p_ctl;
+ struct sysval *p_sysval;
+ struct conncmd *p_connect;
+ struct sk_buff *skb;
+
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s > enter \n",dev->name,__FUNCTION__);
+#endif
+ CLAW_DBF_TEXT(2,setup,"sndcntl");
+#ifdef DEBUGMSG
+ printk(KERN_INFO "%s: Sending Control Packet \n",dev->name);
+ printk(KERN_INFO "%s: variable type = 0x%X, link = "
+ "%d, correlator = %d, rc = %d\n",
+ dev->name,type, link, correlator, rc);
+ printk(KERN_INFO "%s: variable local_name = %s, "
+ "remote_name = %s\n",dev->name, local_name, remote_name);
+#endif
+ privptr=dev->priv;
+ p_ctl=(struct clawctl *)&privptr->ctl_bk;
+
+ p_ctl->command=type;
+ p_ctl->version=CLAW_VERSION_ID;
+ p_ctl->linkid=link;
+ p_ctl->correlator=correlator;
+ p_ctl->rc=rc;
+
+ p_sysval=(struct sysval *)&p_ctl->data;
+ p_connect=(struct conncmd *)&p_ctl->data;
+
+ switch (p_ctl->command) {
+ case SYSTEM_VALIDATE_REQUEST:
+ case SYSTEM_VALIDATE_RESPONSE:
+ memcpy(&p_sysval->host_name, local_name, 8);
+ memcpy(&p_sysval->WS_name, remote_name, 8);
+ if (privptr->p_env->packing > 0) {
+ p_sysval->read_frame_size=DEF_PACK_BUFSIZE;
+ p_sysval->write_frame_size=DEF_PACK_BUFSIZE;
+ } else {
+ /* how big is the piggest group of packets */
+ p_sysval->read_frame_size=privptr->p_env->read_size;
+ p_sysval->write_frame_size=privptr->p_env->write_size;
+ }
+ memset(&p_sysval->reserved, 0x00, 4);
+ break;
+ case CONNECTION_REQUEST:
+ case CONNECTION_RESPONSE:
+ case CONNECTION_CONFIRM:
+ case DISCONNECT:
+ memcpy(&p_sysval->host_name, local_name, 8);
+ memcpy(&p_sysval->WS_name, remote_name, 8);
+ if (privptr->p_env->packing > 0) {
+ /* How big is the biggest packet */
+ p_connect->reserved1[0]=CLAW_FRAME_SIZE;
+ p_connect->reserved1[1]=CLAW_FRAME_SIZE;
+ } else {
+ memset(&p_connect->reserved1, 0x00, 4);
+ memset(&p_connect->reserved2, 0x00, 4);
+ }
+ break;
+ default:
+ break;
+ }
+
+ /* write Control Record to the device */
+
+
+ skb = dev_alloc_skb(sizeof(struct clawctl));
+ if (!skb) {
+ printk( "%s:%s low on mem, returning...\n",
+ dev->name,__FUNCTION__);
+#ifdef DEBUG
+ printk(KERN_INFO "%s:%s Exit, rc = ENOMEM\n",
+ dev->name,__FUNCTION__);
+#endif
+ return -ENOMEM;
+ }
+ memcpy(skb_put(skb, sizeof(struct clawctl)),
+ p_ctl, sizeof(struct clawctl));
+#ifdef IOTRACE
+ printk(KERN_INFO "%s: outbnd claw cntl data \n",dev->name);
+ dumpit((char *)p_ctl,sizeof(struct clawctl));
+#endif
+ if (privptr->p_env->packing >= PACK_SEND)
+ claw_hw_tx(skb, dev, 1);
+ else
+ claw_hw_tx(skb, dev, 0);
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d\n",
+ dev->name,__FUNCTION__,__LINE__);
+#endif
+
+ return 0;
+} /* end of claw_send_control */
+
+/*-------------------------------------------------------------------*
+* claw_snd_conn_req *
+* *
+*--------------------------------------------------------------------*/
+static int
+claw_snd_conn_req(struct net_device *dev, __u8 link)
+{
+ int rc;
+ struct claw_privbk *privptr=dev->priv;
+ struct clawctl *p_ctl;
+
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Enter \n",dev->name,__FUNCTION__);
+#endif
+ CLAW_DBF_TEXT(2,setup,"snd_conn");
+#ifdef DEBUGMSG
+ printk(KERN_INFO "%s: variable link = %X, dev =\n",dev->name, link);
+ dumpit((char *) dev, sizeof(struct net_device));
+#endif
+ rc = 1;
+ p_ctl=(struct clawctl *)&privptr->ctl_bk;
+ p_ctl->linkid = link;
+ if ( privptr->system_validate_comp==0x00 ) {
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d, rc = 1\n",
+ dev->name,__FUNCTION__,__LINE__);
+#endif
+ return rc;
+ }
+ if (privptr->p_env->packing == PACKING_ASK )
+ rc=claw_send_control(dev, CONNECTION_REQUEST,0,0,0,
+ WS_APPL_NAME_PACKED, WS_APPL_NAME_PACKED);
+ if (privptr->p_env->packing == PACK_SEND) {
+ rc=claw_send_control(dev, CONNECTION_REQUEST,0,0,0,
+ WS_APPL_NAME_IP_NAME, WS_APPL_NAME_IP_NAME);
+ }
+ if (privptr->p_env->packing == 0)
+ rc=claw_send_control(dev, CONNECTION_REQUEST,0,0,0,
+ HOST_APPL_NAME, privptr->p_env->api_type);
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d, rc = %d\n",
+ dev->name,__FUNCTION__,__LINE__, rc);
+#endif
+ return rc;
+
+} /* end of claw_snd_conn_req */
+
+
+/*-------------------------------------------------------------------*
+* claw_snd_disc *
+* *
+*--------------------------------------------------------------------*/
+
+static int
+claw_snd_disc(struct net_device *dev, struct clawctl * p_ctl)
+{
+ int rc;
+ struct conncmd * p_connect;
+
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Enter\n",dev->name,__FUNCTION__);
+#endif
+ CLAW_DBF_TEXT(2,setup,"snd_dsc");
+#ifdef DEBUGMSG
+ printk(KERN_INFO "%s: variable dev =\n",dev->name);
+ dumpit((char *) dev, sizeof(struct net_device));
+ printk(KERN_INFO "%s: variable p_ctl",dev->name);
+ dumpit((char *) p_ctl, sizeof(struct clawctl));
+#endif
+ p_connect=(struct conncmd *)&p_ctl->data;
+
+ rc=claw_send_control(dev, DISCONNECT, p_ctl->linkid,
+ p_ctl->correlator, 0,
+ p_connect->host_name, p_connect->WS_name);
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d, rc = %d\n",
+ dev->name,__FUNCTION__, __LINE__, rc);
+#endif
+ return rc;
+} /* end of claw_snd_disc */
+
+
+/*-------------------------------------------------------------------*
+* claw_snd_sys_validate_rsp *
+* *
+*--------------------------------------------------------------------*/
+
+static int
+claw_snd_sys_validate_rsp(struct net_device *dev,
+ struct clawctl *p_ctl, __u32 return_code)
+{
+ struct claw_env * p_env;
+ struct claw_privbk *privptr;
+ int rc;
+
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Enter\n",
+ dev->name,__FUNCTION__);
+#endif
+ CLAW_DBF_TEXT(2,setup,"chkresp");
+#ifdef DEBUGMSG
+ printk(KERN_INFO "%s: variable return_code = %d, dev =\n",
+ dev->name, return_code);
+ dumpit((char *) dev, sizeof(struct net_device));
+ printk(KERN_INFO "%s: variable p_ctl =\n",dev->name);
+ dumpit((char *) p_ctl, sizeof(struct clawctl));
+#endif
+ privptr = dev->priv;
+ p_env=privptr->p_env;
+ rc=claw_send_control(dev, SYSTEM_VALIDATE_RESPONSE,
+ p_ctl->linkid,
+ p_ctl->correlator,
+ return_code,
+ p_env->host_name,
+ p_env->adapter_name );
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d, rc = %d\n",
+ dev->name,__FUNCTION__,__LINE__, rc);
+#endif
+ return rc;
+} /* end of claw_snd_sys_validate_rsp */
+
+/*-------------------------------------------------------------------*
+* claw_strt_conn_req *
+* *
+*--------------------------------------------------------------------*/
+
+static int
+claw_strt_conn_req(struct net_device *dev )
+{
+ int rc;
+
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Enter\n",dev->name,__FUNCTION__);
+#endif
+ CLAW_DBF_TEXT(2,setup,"conn_req");
+#ifdef DEBUGMSG
+ printk(KERN_INFO "%s: variable dev =\n",dev->name);
+ dumpit((char *) dev, sizeof(struct net_device));
+#endif
+ rc=claw_snd_conn_req(dev, 1);
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d, rc = %d\n",
+ dev->name,__FUNCTION__,__LINE__, rc);
+#endif
+ return rc;
+} /* end of claw_strt_conn_req */
+
+
+
+/*-------------------------------------------------------------------*
+ * claw_stats *
+ *-------------------------------------------------------------------*/
+
+static struct
+net_device_stats *claw_stats(struct net_device *dev)
+{
+ struct claw_privbk *privptr;
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Enter\n",dev->name,__FUNCTION__);
+#endif
+ CLAW_DBF_TEXT(4,trace,"stats");
+ privptr = dev->priv;
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d\n",
+ dev->name,__FUNCTION__,__LINE__);
+#endif
+ return &privptr->stats;
+} /* end of claw_stats */
+
+
+/*-------------------------------------------------------------------*
+* unpack_read *
+* *
+*--------------------------------------------------------------------*/
+static void
+unpack_read(struct net_device *dev )
+{
+ struct sk_buff *skb;
+ struct claw_privbk *privptr;
+ struct claw_env *p_env;
+ struct ccwbk *p_this_ccw;
+ struct ccwbk *p_first_ccw;
+ struct ccwbk *p_last_ccw;
+ struct clawph *p_packh;
+ void *p_packd;
+ struct clawctl *p_ctlrec=NULL;
+
+ __u32 len_of_data;
+ __u32 pack_off;
+ __u8 link_num;
+ __u8 mtc_this_frm=0;
+ __u32 bytes_to_mov;
+ struct chbk *p_ch = NULL;
+ int i=0;
+ int p=0;
+
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s enter \n",dev->name,__FUNCTION__);
+#endif
+ CLAW_DBF_TEXT(4,trace,"unpkread");
+ p_first_ccw=NULL;
+ p_last_ccw=NULL;
+ p_packh=NULL;
+ p_packd=NULL;
+ privptr=dev->priv;
+ p_env = privptr->p_env;
+ p_this_ccw=privptr->p_read_active_first;
+ i=0;
+ while (p_this_ccw!=NULL && p_this_ccw->header.flag!=CLAW_PENDING) {
+#ifdef IOTRACE
+ printk(KERN_INFO "%s p_this_ccw \n",dev->name);
+ dumpit((char*)p_this_ccw, sizeof(struct ccwbk));
+ printk(KERN_INFO "%s Inbound p_this_ccw->p_buffer(64)"
+ " pk=%d \n",dev->name,p_env->packing);
+ dumpit((char *)p_this_ccw->p_buffer, 64 );
+#endif
+ pack_off = 0;
+ p = 0;
+ p_this_ccw->header.flag=CLAW_PENDING;
+ privptr->p_read_active_first=p_this_ccw->next;
+ p_this_ccw->next=NULL;
+ p_packh = (struct clawph *)p_this_ccw->p_buffer;
+ if ((p_env->packing == PACK_SEND) &&
+ (p_packh->len == 32) &&
+ (p_packh->link_num == 0)) { /* is it a packed ctl rec? */
+ p_packh++; /* peek past pack header */
+ p_ctlrec = (struct clawctl *)p_packh;
+ p_packh--; /* un peek */
+ if ((p_ctlrec->command == CONNECTION_RESPONSE) ||
+ (p_ctlrec->command == CONNECTION_CONFIRM))
+ p_env->packing = DO_PACKED;
+ }
+ if (p_env->packing == DO_PACKED)
+ link_num=p_packh->link_num;
+ else
+ link_num=p_this_ccw->header.opcode / 8;
+ if ((p_this_ccw->header.opcode & MORE_to_COME_FLAG)!=0) {
+#ifdef DEBUGMSG
+ printk(KERN_INFO "%s: %s > More_to_come is ON\n",
+ dev->name,__FUNCTION__);
+#endif
+ mtc_this_frm=1;
+ if (p_this_ccw->header.length!=
+ privptr->p_env->read_size ) {
+ printk(KERN_INFO " %s: Invalid frame detected "
+ "length is %02x\n" ,
+ dev->name, p_this_ccw->header.length);
+ }
+ }
+
+ if (privptr->mtc_skipping) {
+ /*
+ * We're in the mode of skipping past a
+ * multi-frame message
+ * that we can't process for some reason or other.
+ * The first frame without the More-To-Come flag is
+ * the last frame of the skipped message.
+ */
+ /* in case of More-To-Come not set in this frame */
+ if (mtc_this_frm==0) {
+ privptr->mtc_skipping=0; /* Ok, the end */
+ privptr->mtc_logical_link=-1;
+ }
+#ifdef DEBUGMSG
+ printk(KERN_INFO "%s:%s goto next "
+ "frame from MoretoComeSkip \n",
+ dev->name,__FUNCTION__);
+#endif
+ goto NextFrame;
+ }
+
+ if (link_num==0) {
+ claw_process_control(dev, p_this_ccw);
+#ifdef DEBUGMSG
+ printk(KERN_INFO "%s:%s goto next "
+ "frame from claw_process_control \n",
+ dev->name,__FUNCTION__);
+#endif
+ CLAW_DBF_TEXT(4,trace,"UnpkCntl");
+ goto NextFrame;
+ }
+unpack_next:
+ if (p_env->packing == DO_PACKED) {
+ if (pack_off > p_env->read_size)
+ goto NextFrame;
+ p_packd = p_this_ccw->p_buffer+pack_off;
+ p_packh = (struct clawph *) p_packd;
+ if ((p_packh->len == 0) || /* all done with this frame? */
+ (p_packh->flag != 0))
+ goto NextFrame;
+ bytes_to_mov = p_packh->len;
+ pack_off += bytes_to_mov+sizeof(struct clawph);
+ p++;
+ } else {
+ bytes_to_mov=p_this_ccw->header.length;
+ }
+ if (privptr->mtc_logical_link<0) {
+#ifdef DEBUGMSG
+ printk(KERN_INFO "%s: %s mtc_logical_link < 0 \n",
+ dev->name,__FUNCTION__);
+#endif
+
+ /*
+ * if More-To-Come is set in this frame then we don't know
+ * length of entire message, and hence have to allocate
+ * large buffer */
+
+ /* We are starting a new envelope */
+ privptr->mtc_offset=0;
+ privptr->mtc_logical_link=link_num;
+ }
+
+ if (bytes_to_mov > (MAX_ENVELOPE_SIZE- privptr->mtc_offset) ) {
+ /* error */
+#ifdef DEBUGMSG
+ printk(KERN_INFO "%s: %s > goto next "
+ "frame from MoretoComeSkip \n",
+ dev->name,
+ __FUNCTION__);
+ printk(KERN_INFO " bytes_to_mov %d > (MAX_ENVELOPE_"
+ "SIZE-privptr->mtc_offset %d)\n",
+ bytes_to_mov,(MAX_ENVELOPE_SIZE- privptr->mtc_offset));
+#endif
+ privptr->stats.rx_frame_errors++;
+ goto NextFrame;
+ }
+ if (p_env->packing == DO_PACKED) {
+ memcpy( privptr->p_mtc_envelope+ privptr->mtc_offset,
+ p_packd+sizeof(struct clawph), bytes_to_mov);
+
+ } else {
+ memcpy( privptr->p_mtc_envelope+ privptr->mtc_offset,
+ p_this_ccw->p_buffer, bytes_to_mov);
+ }
+#ifdef DEBUGMSG
+ printk(KERN_INFO "%s: %s() received data \n",
+ dev->name,__FUNCTION__);
+ if (p_env->packing == DO_PACKED)
+ dumpit((char *)p_packd+sizeof(struct clawph),32);
+ else
+ dumpit((char *)p_this_ccw->p_buffer, 32);
+ printk(KERN_INFO "%s: %s() bytelength %d \n",
+ dev->name,__FUNCTION__,bytes_to_mov);
+#endif
+ if (mtc_this_frm==0) {
+ len_of_data=privptr->mtc_offset+bytes_to_mov;
+ skb=dev_alloc_skb(len_of_data);
+ if (skb) {
+ memcpy(skb_put(skb,len_of_data),
+ privptr->p_mtc_envelope,
+ len_of_data);
+ skb->mac.raw=skb->data;
+ skb->dev=dev;
+ skb->protocol=htons(ETH_P_IP);
+ skb->ip_summed=CHECKSUM_UNNECESSARY;
+ privptr->stats.rx_packets++;
+ privptr->stats.rx_bytes+=len_of_data;
+ netif_rx(skb);
+#ifdef DEBUGMSG
+ printk(KERN_INFO "%s: %s() netif_"
+ "rx(skb) completed \n",
+ dev->name,__FUNCTION__);
+#endif
+ }
+ else {
+ privptr->stats.rx_dropped++;
+ printk(KERN_WARNING "%s: %s() low on memory\n",
+ dev->name,__FUNCTION__);
+ }
+ privptr->mtc_offset=0;
+ privptr->mtc_logical_link=-1;
+ }
+ else {
+ privptr->mtc_offset+=bytes_to_mov;
+ }
+ if (p_env->packing == DO_PACKED)
+ goto unpack_next;
+NextFrame:
+ /*
+ * Remove ThisCCWblock from active read queue, and add it
+ * to queue of free blocks to be reused.
+ */
+ i++;
+ p_this_ccw->header.length=0xffff;
+ p_this_ccw->header.opcode=0xff;
+ /*
+ * add this one to the free queue for later reuse
+ */
+ if (p_first_ccw==NULL) {
+ p_first_ccw = p_this_ccw;
+ }
+ else {
+ p_last_ccw->next = p_this_ccw;
+ }
+ p_last_ccw = p_this_ccw;
+ /*
+ * chain to next block on active read queue
+ */
+ p_this_ccw = privptr->p_read_active_first;
+ CLAW_DBF_TEXT_(4,trace,"rxpkt %d",p);
+ } /* end of while */
+
+ /* check validity */
+
+#ifdef IOTRACE
+ printk(KERN_INFO "%s:%s processed frame is %d \n",
+ dev->name,__FUNCTION__,i);
+ printk(KERN_INFO "%s:%s F:%lx L:%lx\n",
+ dev->name,
+ __FUNCTION__,
+ (unsigned long)p_first_ccw,
+ (unsigned long)p_last_ccw);
+#endif
+ CLAW_DBF_TEXT_(4,trace,"rxfrm %d",i);
+ add_claw_reads(dev, p_first_ccw, p_last_ccw);
+ p_ch=&privptr->channel[READ];
+ claw_strt_read(dev, LOCK_YES);
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s: %s exit on line %d\n",
+ dev->name, __FUNCTION__, __LINE__);
+#endif
+ return;
+} /* end of unpack_read */
+
+/*-------------------------------------------------------------------*
+* claw_strt_read *
+* *
+*--------------------------------------------------------------------*/
+static void
+claw_strt_read (struct net_device *dev, int lock )
+{
+ int rc = 0;
+ __u32 parm;
+ unsigned long saveflags = 0;
+ struct claw_privbk *privptr=dev->priv;
+ struct ccwbk*p_ccwbk;
+ struct chbk *p_ch;
+ struct clawh *p_clawh;
+ p_ch=&privptr->channel[READ];
+
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Enter \n",dev->name,__FUNCTION__);
+ printk(KERN_INFO "%s: variable lock = %d, dev =\n",dev->name, lock);
+ dumpit((char *) dev, sizeof(struct net_device));
+#endif
+ CLAW_DBF_TEXT(4,trace,"StRdNter");
+ p_clawh=(struct clawh *)privptr->p_claw_signal_blk;
+ p_clawh->flag=CLAW_IDLE; /* 0x00 */
+
+ if ((privptr->p_write_active_first!=NULL &&
+ privptr->p_write_active_first->header.flag!=CLAW_PENDING) ||
+ (privptr->p_read_active_first!=NULL &&
+ privptr->p_read_active_first->header.flag!=CLAW_PENDING )) {
+ p_clawh->flag=CLAW_BUSY; /* 0xff */
+ }
+#ifdef DEBUGMSG
+ printk(KERN_INFO "%s:%s state-%02x\n" ,
+ dev->name,__FUNCTION__, p_ch->claw_state);
+#endif
+ if (lock==LOCK_YES) {
+ spin_lock_irqsave(get_ccwdev_lock(p_ch->cdev), saveflags);
+ }
+ if (test_and_set_bit(0, (void *)&p_ch->IO_active) == 0) {
+#ifdef DEBUGMSG
+ printk(KERN_INFO "%s: HOT READ started in %s\n" ,
+ dev->name,__FUNCTION__);
+ p_clawh=(struct clawh *)privptr->p_claw_signal_blk;
+ dumpit((char *)&p_clawh->flag , 1);
+#endif
+ CLAW_DBF_TEXT(4,trace,"HotRead");
+ p_ccwbk=privptr->p_read_active_first;
+ parm = (unsigned long) p_ch;
+ rc = ccw_device_start (p_ch->cdev, &p_ccwbk->read, parm,
+ 0xff, 0);
+ if (rc != 0) {
+ ccw_check_return_code(p_ch->cdev, rc);
+ }
+ }
+ else {
+#ifdef DEBUGMSG
+ printk(KERN_INFO "%s: No READ started by %s() In progress\n" ,
+ dev->name,__FUNCTION__);
+#endif
+ CLAW_DBF_TEXT(2,trace,"ReadAct");
+ }
+
+ if (lock==LOCK_YES) {
+ spin_unlock_irqrestore(get_ccwdev_lock(p_ch->cdev), saveflags);
+ }
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d\n",
+ dev->name,__FUNCTION__,__LINE__);
+#endif
+ CLAW_DBF_TEXT(4,trace,"StRdExit");
+ return;
+} /* end of claw_strt_read */
+
+/*-------------------------------------------------------------------*
+* claw_strt_out_IO *
+* *
+*--------------------------------------------------------------------*/
+
+static void
+claw_strt_out_IO( struct net_device *dev )
+{
+ int rc = 0;
+ unsigned long parm;
+ struct claw_privbk *privptr;
+ struct chbk *p_ch;
+ struct ccwbk *p_first_ccw;
+
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Enter\n",dev->name,__FUNCTION__);
+#endif
+ if (!dev) {
+ return;
+ }
+ privptr=(struct claw_privbk *)dev->priv;
+ p_ch=&privptr->channel[WRITE];
+
+#ifdef DEBUGMSG
+ printk(KERN_INFO "%s:%s state-%02x\n" ,
+ dev->name,__FUNCTION__,p_ch->claw_state);
+#endif
+ CLAW_DBF_TEXT(4,trace,"strt_io");
+ p_first_ccw=privptr->p_write_active_first;
+
+ if (p_ch->claw_state == CLAW_STOP)
+ return;
+ if (p_first_ccw == NULL) {
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d\n",
+ dev->name,__FUNCTION__,__LINE__);
+#endif
+ return;
+ }
+ if (test_and_set_bit(0, (void *)&p_ch->IO_active) == 0) {
+ parm = (unsigned long) p_ch;
+#ifdef DEBUGMSG
+ printk(KERN_INFO "%s:%s do_io \n" ,dev->name,__FUNCTION__);
+ dumpit((char *)p_first_ccw, sizeof(struct ccwbk));
+#endif
+ CLAW_DBF_TEXT(2,trace,"StWrtIO");
+ rc = ccw_device_start (p_ch->cdev,&p_first_ccw->write, parm,
+ 0xff, 0);
+ if (rc != 0) {
+ ccw_check_return_code(p_ch->cdev, rc);
+ }
+ }
+ dev->trans_start = jiffies;
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d\n",
+ dev->name,__FUNCTION__,__LINE__);
+#endif
+
+ return;
+} /* end of claw_strt_out_IO */
+
+/*-------------------------------------------------------------------*
+* Free write buffers *
+* *
+*--------------------------------------------------------------------*/
+
+static void
+claw_free_wrt_buf( struct net_device *dev )
+{
+
+ struct claw_privbk *privptr=(struct claw_privbk *)dev->priv;
+ struct ccwbk*p_first_ccw;
+ struct ccwbk*p_last_ccw;
+ struct ccwbk*p_this_ccw;
+ struct ccwbk*p_next_ccw;
+#ifdef IOTRACE
+ struct ccwbk*p_buf;
+#endif
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Enter\n",dev->name,__FUNCTION__);
+ printk(KERN_INFO "%s: free count = %d variable dev =\n",
+ dev->name,privptr->write_free_count);
+#endif
+ CLAW_DBF_TEXT(4,trace,"freewrtb");
+ /* scan the write queue to free any completed write packets */
+ p_first_ccw=NULL;
+ p_last_ccw=NULL;
+#ifdef IOTRACE
+ printk(KERN_INFO "%s: Dump current CCW chain \n",dev->name );
+ p_buf=privptr->p_write_active_first;
+ while (p_buf!=NULL) {
+ dumpit((char *)p_buf, sizeof(struct ccwbk));
+ p_buf=p_buf->next;
+ }
+ if (p_buf==NULL) {
+ printk(KERN_INFO "%s: privptr->p_write_"
+ "active_first==NULL\n",dev->name );
+ }
+ p_buf=(struct ccwbk*)privptr->p_end_ccw;
+ dumpit((char *)p_buf, sizeof(struct endccw));
+#endif
+ p_this_ccw=privptr->p_write_active_first;
+ while ( (p_this_ccw!=NULL) && (p_this_ccw->header.flag!=CLAW_PENDING))
+ {
+ p_next_ccw = p_this_ccw->next;
+ if (((p_next_ccw!=NULL) &&
+ (p_next_ccw->header.flag!=CLAW_PENDING)) ||
+ ((p_this_ccw == privptr->p_write_active_last) &&
+ (p_this_ccw->header.flag!=CLAW_PENDING))) {
+ /* The next CCW is OK or this is */
+ /* the last CCW...free it @A1A */
+ privptr->p_write_active_first=p_this_ccw->next;
+ p_this_ccw->header.flag=CLAW_PENDING;
+ p_this_ccw->next=privptr->p_write_free_chain;
+ privptr->p_write_free_chain=p_this_ccw;
+ ++privptr->write_free_count;
+ privptr->stats.tx_bytes+= p_this_ccw->write.count;
+ p_this_ccw=privptr->p_write_active_first;
+ privptr->stats.tx_packets++;
+ }
+ else {
+ break;
+ }
+ }
+ if (privptr->write_free_count!=0) {
+ claw_clearbit_busy(TB_NOBUFFER,dev);
+ }
+ /* whole chain removed? */
+ if (privptr->p_write_active_first==NULL) {
+ privptr->p_write_active_last=NULL;
+#ifdef DEBUGMSG
+ printk(KERN_INFO "%s:%s p_write_"
+ "active_first==NULL\n",dev->name,__FUNCTION__);
+#endif
+ }
+#ifdef IOTRACE
+ printk(KERN_INFO "%s: Dump arranged CCW chain \n",dev->name );
+ p_buf=privptr->p_write_active_first;
+ while (p_buf!=NULL) {
+ dumpit((char *)p_buf, sizeof(struct ccwbk));
+ p_buf=p_buf->next;
+ }
+ if (p_buf==NULL) {
+ printk(KERN_INFO "%s: privptr->p_write_active_"
+ "first==NULL\n",dev->name );
+ }
+ p_buf=(struct ccwbk*)privptr->p_end_ccw;
+ dumpit((char *)p_buf, sizeof(struct endccw));
+#endif
+
+ CLAW_DBF_TEXT_(4,trace,"FWC=%d",privptr->write_free_count);
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d free_count =%d\n",
+ dev->name,__FUNCTION__, __LINE__,privptr->write_free_count);
+#endif
+ return;
+}
+
+/*-------------------------------------------------------------------*
+* claw free netdevice *
+* *
+*--------------------------------------------------------------------*/
+static void
+claw_free_netdevice(struct net_device * dev, int free_dev)
+{
+ struct claw_privbk *privptr;
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Enter\n",dev->name,__FUNCTION__);
+#endif
+ CLAW_DBF_TEXT(2,setup,"free_dev");
+
+ if (!dev)
+ return;
+ CLAW_DBF_TEXT_(2,setup,"%s",dev->name);
+ privptr = dev->priv;
+ if (dev->flags & IFF_RUNNING)
+ claw_release(dev);
+ if (privptr) {
+ privptr->channel[READ].ndev = NULL; /* say it's free */
+ }
+ dev->priv=NULL;
+#ifdef MODULE
+ if (free_dev) {
+ free_netdev(dev);
+ }
+#endif
+ CLAW_DBF_TEXT(2,setup,"feee_ok");
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit\n",dev->name,__FUNCTION__);
+#endif
+}
+
+/**
+ * Claw init netdevice
+ * Initialize everything of the net device except the name and the
+ * channel structs.
+ */
+static void
+claw_init_netdevice(struct net_device * dev)
+{
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Enter\n",dev->name,__FUNCTION__);
+#endif
+ CLAW_DBF_TEXT(2,setup,"init_dev");
+ CLAW_DBF_TEXT_(2,setup,"%s",dev->name);
+ if (!dev) {
+ printk(KERN_WARNING "claw:%s BAD Device exit line %d\n",
+ __FUNCTION__,__LINE__);
+ CLAW_DBF_TEXT(2,setup,"baddev");
+ return;
+ }
+ dev->mtu = CLAW_DEFAULT_MTU_SIZE;
+ dev->hard_start_xmit = claw_tx;
+ dev->open = claw_open;
+ dev->stop = claw_release;
+ dev->get_stats = claw_stats;
+ dev->change_mtu = claw_change_mtu;
+ dev->hard_header_len = 0;
+ dev->addr_len = 0;
+ dev->type = ARPHRD_SLIP;
+ dev->tx_queue_len = 1300;
+ dev->flags = IFF_POINTOPOINT | IFF_NOARP;
+ SET_MODULE_OWNER(dev);
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit\n",dev->name,__FUNCTION__);
+#endif
+ CLAW_DBF_TEXT(2,setup,"initok");
+ return;
+}
+
+/**
+ * Init a new channel in the privptr->channel[i].
+ *
+ * @param cdev The ccw_device to be added.
+ *
+ * @return 0 on success, !0 on error.
+ */
+static int
+add_channel(struct ccw_device *cdev,int i,struct claw_privbk *privptr)
+{
+ struct chbk *p_ch;
+
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Enter\n",cdev->dev.bus_id,__FUNCTION__);
+#endif
+ CLAW_DBF_TEXT_(2,setup,"%s",cdev->dev.bus_id);
+ privptr->channel[i].flag = i+1; /* Read is 1 Write is 2 */
+ p_ch = &privptr->channel[i];
+ p_ch->cdev = cdev;
+ snprintf(p_ch->id, CLAW_ID_SIZE, "cl-%s", cdev->dev.bus_id);
+ sscanf(cdev->dev.bus_id+4,"%x",&p_ch->devno);
+ if ((p_ch->irb = kmalloc(sizeof (struct irb),GFP_KERNEL)) == NULL) {
+ printk(KERN_WARNING "%s Out of memory in %s for irb\n",
+ p_ch->id,__FUNCTION__);
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d\n",
+ p_ch->id,__FUNCTION__,__LINE__);
+#endif
+ return -ENOMEM;
+ }
+ memset(p_ch->irb, 0, sizeof (struct irb));
+#ifdef FUNCTRACE
+ printk(KERN_INFO "%s:%s Exit on line %d\n",
+ cdev->dev.bus_id,__FUNCTION__,__LINE__);
+#endif
+ return 0;
+}
+
+
+/**
+ *
+ * Setup an interface.
+ *
+ * @param cgdev Device to be setup.
+ *
+ * @returns 0 on success, !0 on failure.
+ */
+static int
+claw_new_device(struct ccwgroup_device *cgdev)
+{
+ struct claw_privbk *privptr;
+ struct claw_env *p_env;
+ struct net_device *dev;
+ int ret;
+
+ pr_debug("%s() called\n", __FUNCTION__);
+ printk(KERN_INFO "claw: add for %s\n",cgdev->cdev[READ]->dev.bus_id);
+ CLAW_DBF_TEXT(2,setup,"new_dev");
+ privptr = cgdev->dev.driver_data;
+ cgdev->cdev[READ]->dev.driver_data = privptr;
+ cgdev->cdev[WRITE]->dev.driver_data = privptr;
+ if (!privptr)
+ return -ENODEV;
+ p_env = privptr->p_env;
+ sscanf(cgdev->cdev[READ]->dev.bus_id+4,"%x",
+ &p_env->devno[READ]);
+ sscanf(cgdev->cdev[WRITE]->dev.bus_id+4,"%x",
+ &p_env->devno[WRITE]);
+ ret = add_channel(cgdev->cdev[0],0,privptr);
+ if (ret == 0)
+ ret = add_channel(cgdev->cdev[1],1,privptr);
+ if (ret != 0) {
+ printk(KERN_WARNING
+ "add channel failed "
+ "with ret = %d\n", ret);
+ goto out;
+ }
+ ret = ccw_device_set_online(cgdev->cdev[READ]);
+ if (ret != 0) {
+ printk(KERN_WARNING
+ "claw: ccw_device_set_online %s READ failed "
+ "with ret = %d\n",cgdev->cdev[READ]->dev.bus_id,ret);
+ goto out;
+ }
+ ret = ccw_device_set_online(cgdev->cdev[WRITE]);
+ if (ret != 0) {
+ printk(KERN_WARNING
+ "claw: ccw_device_set_online %s WRITE failed "
+ "with ret = %d\n",cgdev->cdev[WRITE]->dev.bus_id, ret);
+ goto out;
+ }
+ dev = alloc_netdev(0,"claw%d",claw_init_netdevice);
+ if (!dev) {
+ printk(KERN_WARNING "%s:alloc_netdev failed\n",__FUNCTION__);
+ goto out;
+ }
+ dev->priv = privptr;
+ cgdev->dev.driver_data = privptr;
+ cgdev->cdev[READ]->dev.driver_data = privptr;
+ cgdev->cdev[WRITE]->dev.driver_data = privptr;
+ /* sysfs magic */
+ SET_NETDEV_DEV(dev, &cgdev->dev);
+ if (register_netdev(dev) != 0) {
+ claw_free_netdevice(dev, 1);
+ CLAW_DBF_TEXT(2,trace,"regfail");
+ goto out;
+ }
+ dev->flags &=~IFF_RUNNING;
+ if (privptr->buffs_alloc == 0) {
+ ret=init_ccw_bk(dev);
+ if (ret !=0) {
+ printk(KERN_WARNING
+ "claw: init_ccw_bk failed with ret=%d\n", ret);
+ unregister_netdev(dev);
+ claw_free_netdevice(dev,1);
+ CLAW_DBF_TEXT(2,trace,"ccwmem");
+ goto out;
+ }
+ }
+ privptr->channel[READ].ndev = dev;
+ privptr->channel[WRITE].ndev = dev;
+ privptr->p_env->ndev = dev;
+
+ printk(KERN_INFO "%s:readsize=%d writesize=%d "
+ "readbuffer=%d writebuffer=%d read=0x%04x write=0x%04x\n",
+ dev->name, p_env->read_size,
+ p_env->write_size, p_env->read_buffers,
+ p_env->write_buffers, p_env->devno[READ],
+ p_env->devno[WRITE]);
+ printk(KERN_INFO "%s:host_name:%.8s, adapter_name "
+ ":%.8s api_type: %.8s\n",
+ dev->name, p_env->host_name,
+ p_env->adapter_name , p_env->api_type);
+ return 0;
+out:
+ ccw_device_set_offline(cgdev->cdev[1]);
+ ccw_device_set_offline(cgdev->cdev[0]);
+
+ return -ENODEV;
+}
+
+static void
+claw_purge_skb_queue(struct sk_buff_head *q)
+{
+ struct sk_buff *skb;
+
+ CLAW_DBF_TEXT(4,trace,"purgque");
+
+ while ((skb = skb_dequeue(q))) {
+ atomic_dec(&skb->users);
+ dev_kfree_skb_irq(skb);
+ }
+}
+
+/**
+ * Shutdown an interface.
+ *
+ * @param cgdev Device to be shut down.
+ *
+ * @returns 0 on success, !0 on failure.
+ */
+static int
+claw_shutdown_device(struct ccwgroup_device *cgdev)
+{
+ struct claw_privbk *priv;
+ struct net_device *ndev;
+ int ret;
+
+ pr_debug("%s() called\n", __FUNCTION__);
+ CLAW_DBF_TEXT_(2,setup,"%s",cgdev->dev.bus_id);
+ priv = cgdev->dev.driver_data;
+ if (!priv)
+ return -ENODEV;
+ ndev = priv->channel[READ].ndev;
+ if (ndev) {
+ /* Close the device */
+ printk(KERN_INFO
+ "%s: shuting down \n",ndev->name);
+ if (ndev->flags & IFF_RUNNING)
+ ret = claw_release(ndev);
+ ndev->flags &=~IFF_RUNNING;
+ unregister_netdev(ndev);
+ ndev->priv = NULL; /* cgdev data, not ndev's to free */
+ claw_free_netdevice(ndev, 1);
+ priv->channel[READ].ndev = NULL;
+ priv->channel[WRITE].ndev = NULL;
+ priv->p_env->ndev = NULL;
+ }
+ ccw_device_set_offline(cgdev->cdev[1]);
+ ccw_device_set_offline(cgdev->cdev[0]);
+ return 0;
+}
+
+static void
+claw_remove_device(struct ccwgroup_device *cgdev)
+{
+ struct claw_privbk *priv;
+
+ pr_debug("%s() called\n", __FUNCTION__);
+ CLAW_DBF_TEXT_(2,setup,"%s",cgdev->dev.bus_id);
+ priv = cgdev->dev.driver_data;
+ if (!priv) {
+ printk(KERN_WARNING "claw: %s() no Priv exiting\n",__FUNCTION__);
+ return;
+ }
+ printk(KERN_INFO "claw: %s() called %s will be removed.\n",
+ __FUNCTION__,cgdev->cdev[0]->dev.bus_id);
+ if (cgdev->state == CCWGROUP_ONLINE)
+ claw_shutdown_device(cgdev);
+ claw_remove_files(&cgdev->dev);
+ if (priv->p_mtc_envelope!=NULL) {
+ kfree(priv->p_mtc_envelope);
+ priv->p_mtc_envelope=NULL;
+ }
+ if (priv->p_env != NULL) {
+ kfree(priv->p_env);
+ priv->p_env=NULL;
+ }
+ if (priv->channel[0].irb != NULL) {
+ kfree(priv->channel[0].irb);
+ priv->channel[0].irb=NULL;
+ }
+ if (priv->channel[1].irb != NULL) {
+ kfree(priv->channel[1].irb);
+ priv->channel[1].irb=NULL;
+ }
+ kfree(priv);
+ cgdev->dev.driver_data=NULL;
+ cgdev->cdev[READ]->dev.driver_data = NULL;
+ cgdev->cdev[WRITE]->dev.driver_data = NULL;
+ put_device(&cgdev->dev);
+}
+
+
+/*
+ * sysfs attributes
+ */
+static ssize_t
+claw_hname_show(struct device *dev, char *buf)
+{
+ struct claw_privbk *priv;
+ struct claw_env * p_env;
+
+ priv = dev->driver_data;
+ if (!priv)
+ return -ENODEV;
+ p_env = priv->p_env;
+ return sprintf(buf, "%s\n",p_env->host_name);
+}
+
+static ssize_t
+claw_hname_write(struct device *dev, const char *buf, size_t count)
+{
+ struct claw_privbk *priv;
+ struct claw_env * p_env;
+
+ priv = dev->driver_data;
+ if (!priv)
+ return -ENODEV;
+ p_env = priv->p_env;
+ if (count > MAX_NAME_LEN+1)
+ return -EINVAL;
+ memset(p_env->host_name, 0x20, MAX_NAME_LEN);
+ strncpy(p_env->host_name,buf, count);
+ p_env->host_name[count-1] = 0x20; /* clear extra 0x0a */
+ p_env->host_name[MAX_NAME_LEN] = 0x00;
+ CLAW_DBF_TEXT(2,setup,"HstnSet");
+ CLAW_DBF_TEXT_(2,setup,"%s",p_env->host_name);
+
+ return count;
+}
+
+static DEVICE_ATTR(host_name, 0644, claw_hname_show, claw_hname_write);
+
+static ssize_t
+claw_adname_show(struct device *dev, char *buf)
+{
+ struct claw_privbk *priv;
+ struct claw_env * p_env;
+
+ priv = dev->driver_data;
+ if (!priv)
+ return -ENODEV;
+ p_env = priv->p_env;
+ return sprintf(buf, "%s\n",p_env->adapter_name);
+}
+
+static ssize_t
+claw_adname_write(struct device *dev, const char *buf, size_t count)
+{
+ struct claw_privbk *priv;
+ struct claw_env * p_env;
+
+ priv = dev->driver_data;
+ if (!priv)
+ return -ENODEV;
+ p_env = priv->p_env;
+ if (count > MAX_NAME_LEN+1)
+ return -EINVAL;
+ memset(p_env->adapter_name, 0x20, MAX_NAME_LEN);
+ strncpy(p_env->adapter_name,buf, count);
+ p_env->adapter_name[count-1] = 0x20; /* clear extra 0x0a */
+ p_env->adapter_name[MAX_NAME_LEN] = 0x00;
+ CLAW_DBF_TEXT(2,setup,"AdnSet");
+ CLAW_DBF_TEXT_(2,setup,"%s",p_env->adapter_name);
+
+ return count;
+}
+
+static DEVICE_ATTR(adapter_name, 0644, claw_adname_show, claw_adname_write);
+
+static ssize_t
+claw_apname_show(struct device *dev, char *buf)
+{
+ struct claw_privbk *priv;
+ struct claw_env * p_env;
+
+ priv = dev->driver_data;
+ if (!priv)
+ return -ENODEV;
+ p_env = priv->p_env;
+ return sprintf(buf, "%s\n",
+ p_env->api_type);
+}
+
+static ssize_t
+claw_apname_write(struct device *dev, const char *buf, size_t count)
+{
+ struct claw_privbk *priv;
+ struct claw_env * p_env;
+
+ priv = dev->driver_data;
+ if (!priv)
+ return -ENODEV;
+ p_env = priv->p_env;
+ if (count > MAX_NAME_LEN+1)
+ return -EINVAL;
+ memset(p_env->api_type, 0x20, MAX_NAME_LEN);
+ strncpy(p_env->api_type,buf, count);
+ p_env->api_type[count-1] = 0x20; /* we get a loose 0x0a */
+ p_env->api_type[MAX_NAME_LEN] = 0x00;
+ if(strncmp(p_env->api_type,WS_APPL_NAME_PACKED,6) == 0) {
+ p_env->read_size=DEF_PACK_BUFSIZE;
+ p_env->write_size=DEF_PACK_BUFSIZE;
+ p_env->packing=PACKING_ASK;
+ CLAW_DBF_TEXT(2,setup,"PACKING");
+ }
+ else {
+ p_env->packing=0;
+ p_env->read_size=CLAW_FRAME_SIZE;
+ p_env->write_size=CLAW_FRAME_SIZE;
+ CLAW_DBF_TEXT(2,setup,"ApiSet");
+ }
+ CLAW_DBF_TEXT_(2,setup,"%s",p_env->api_type);
+ return count;
+}
+
+static DEVICE_ATTR(api_type, 0644, claw_apname_show, claw_apname_write);
+
+static ssize_t
+claw_wbuff_show(struct device *dev, char *buf)
+{
+ struct claw_privbk *priv;
+ struct claw_env * p_env;
+
+ priv = dev->driver_data;
+ if (!priv)
+ return -ENODEV;
+ p_env = priv->p_env;
+ return sprintf(buf, "%d\n", p_env->write_buffers);
+}
+
+static ssize_t
+claw_wbuff_write(struct device *dev, const char *buf, size_t count)
+{
+ struct claw_privbk *priv;
+ struct claw_env * p_env;
+ int nnn,max;
+
+ priv = dev->driver_data;
+ if (!priv)
+ return -ENODEV;
+ p_env = priv->p_env;
+ sscanf(buf, "%i", &nnn);
+ if (p_env->packing) {
+ max = 64;
+ }
+ else {
+ max = 512;
+ }
+ if ((nnn > max ) || (nnn < 2))
+ return -EINVAL;
+ p_env->write_buffers = nnn;
+ CLAW_DBF_TEXT(2,setup,"Wbufset");
+ CLAW_DBF_TEXT_(2,setup,"WB=%d",p_env->write_buffers);
+ return count;
+}
+
+static DEVICE_ATTR(write_buffer, 0644, claw_wbuff_show, claw_wbuff_write);
+
+static ssize_t
+claw_rbuff_show(struct device *dev, char *buf)
+{
+ struct claw_privbk *priv;
+ struct claw_env * p_env;
+
+ priv = dev->driver_data;
+ if (!priv)
+ return -ENODEV;
+ p_env = priv->p_env;
+ return sprintf(buf, "%d\n", p_env->read_buffers);
+}
+
+static ssize_t
+claw_rbuff_write(struct device *dev, const char *buf, size_t count)
+{
+ struct claw_privbk *priv;
+ struct claw_env *p_env;
+ int nnn,max;
+
+ priv = dev->driver_data;
+ if (!priv)
+ return -ENODEV;
+ p_env = priv->p_env;
+ sscanf(buf, "%i", &nnn);
+ if (p_env->packing) {
+ max = 64;
+ }
+ else {
+ max = 512;
+ }
+ if ((nnn > max ) || (nnn < 2))
+ return -EINVAL;
+ p_env->read_buffers = nnn;
+ CLAW_DBF_TEXT(2,setup,"Rbufset");
+ CLAW_DBF_TEXT_(2,setup,"RB=%d",p_env->read_buffers);
+ return count;
+}
+
+static DEVICE_ATTR(read_buffer, 0644, claw_rbuff_show, claw_rbuff_write);
+
+static struct attribute *claw_attr[] = {
+ &dev_attr_read_buffer.attr,
+ &dev_attr_write_buffer.attr,
+ &dev_attr_adapter_name.attr,
+ &dev_attr_api_type.attr,
+ &dev_attr_host_name.attr,
+ NULL,
+};
+
+static struct attribute_group claw_attr_group = {
+ .attrs = claw_attr,
+};
+
+static int
+claw_add_files(struct device *dev)
+{
+ pr_debug("%s() called\n", __FUNCTION__);
+ CLAW_DBF_TEXT(2,setup,"add_file");
+ return sysfs_create_group(&dev->kobj, &claw_attr_group);
+}
+
+static void
+claw_remove_files(struct device *dev)
+{
+ pr_debug("%s() called\n", __FUNCTION__);
+ CLAW_DBF_TEXT(2,setup,"rem_file");
+ sysfs_remove_group(&dev->kobj, &claw_attr_group);
+}
+
+/*--------------------------------------------------------------------*
+* claw_init and cleanup *
+*---------------------------------------------------------------------*/
+
+static void __exit
+claw_cleanup(void)
+{
+ unregister_cu3088_discipline(&claw_group_driver);
+ claw_unregister_debug_facility();
+ printk(KERN_INFO "claw: Driver unloaded\n");
+
+}
+
+/**
+ * Initialize module.
+ * This is called just after the module is loaded.
+ *
+ * @return 0 on success, !0 on error.
+ */
+static int __init
+claw_init(void)
+{
+ int ret = 0;
+ printk(KERN_INFO "claw: starting driver "
+#ifdef MODULE
+ "module "
+#else
+ "compiled into kernel "
+#endif
+ " $Revision: 1.35 $ $Date: 2005/03/24 12:25:38 $ \n");
+
+
+#ifdef FUNCTRACE
+ printk(KERN_INFO "claw: %s() enter \n",__FUNCTION__);
+#endif
+ ret = claw_register_debug_facility();
+ if (ret) {
+ printk(KERN_WARNING "claw: %s() debug_register failed %d\n",
+ __FUNCTION__,ret);
+ return ret;
+ }
+ CLAW_DBF_TEXT(2,setup,"init_mod");
+ ret = register_cu3088_discipline(&claw_group_driver);
+ if (ret) {
+ claw_unregister_debug_facility();
+ printk(KERN_WARNING "claw; %s() cu3088 register failed %d\n",
+ __FUNCTION__,ret);
+ }
+#ifdef FUNCTRACE
+ printk(KERN_INFO "claw: %s() exit \n",__FUNCTION__);
+#endif
+ return ret;
+}
+
+module_init(claw_init);
+module_exit(claw_cleanup);
+
+
+
+/*--------------------------------------------------------------------*
+* End of File *
+*---------------------------------------------------------------------*/
+
+
diff --git a/drivers/s390/net/claw.h b/drivers/s390/net/claw.h
new file mode 100644
index 0000000000000..3df71970f6010
--- /dev/null
+++ b/drivers/s390/net/claw.h
@@ -0,0 +1,335 @@
+/*******************************************************
+* Define constants *
+* *
+********************************************************/
+#define VERSION_CLAW_H "$Revision: 1.6 $"
+/*-----------------------------------------------------*
+* CCW command codes for CLAW protocol *
+*------------------------------------------------------*/
+
+#define CCW_CLAW_CMD_WRITE 0x01 /* write - not including link */
+#define CCW_CLAW_CMD_READ 0x02 /* read */
+#define CCW_CLAW_CMD_NOP 0x03 /* NOP */
+#define CCW_CLAW_CMD_SENSE 0x04 /* Sense */
+#define CCW_CLAW_CMD_SIGNAL_SMOD 0x05 /* Signal Status Modifier */
+#define CCW_CLAW_CMD_TIC 0x08 /* TIC */
+#define CCW_CLAW_CMD_READHEADER 0x12 /* read header data */
+#define CCW_CLAW_CMD_READFF 0x22 /* read an FF */
+#define CCW_CLAW_CMD_SENSEID 0xe4 /* Sense ID */
+
+
+/*-----------------------------------------------------*
+* CLAW Unique constants *
+*------------------------------------------------------*/
+
+#define MORE_to_COME_FLAG 0x04 /* OR with write CCW in case of m-t-c */
+#define CLAW_IDLE 0x00 /* flag to indicate CLAW is idle */
+#define CLAW_BUSY 0xff /* flag to indicate CLAW is busy */
+#define CLAW_PENDING 0x00 /* flag to indicate i/o is pending */
+#define CLAW_COMPLETE 0xff /* flag to indicate i/o completed */
+
+/*-----------------------------------------------------*
+* CLAW control comand code *
+*------------------------------------------------------*/
+
+#define SYSTEM_VALIDATE_REQUEST 0x01 /* System Validate request */
+#define SYSTEM_VALIDATE_RESPONSE 0x02 /* System Validate response */
+#define CONNECTION_REQUEST 0x21 /* Connection request */
+#define CONNECTION_RESPONSE 0x22 /* Connection response */
+#define CONNECTION_CONFIRM 0x23 /* Connection confirm */
+#define DISCONNECT 0x24 /* Disconnect */
+#define CLAW_ERROR 0x41 /* CLAW error message */
+#define CLAW_VERSION_ID 2 /* CLAW version ID */
+
+/*-----------------------------------------------------*
+* CLAW adater sense bytes *
+*------------------------------------------------------*/
+
+#define CLAW_ADAPTER_SENSE_BYTE 0x41 /* Stop command issued to adapter */
+
+/*-----------------------------------------------------*
+* CLAW control command return codes *
+*------------------------------------------------------*/
+
+#define CLAW_RC_NAME_MISMATCH 166 /* names do not match */
+#define CLAW_RC_WRONG_VERSION 167 /* wrong CLAW version number */
+#define CLAW_RC_HOST_RCV_TOO_SMALL 180 /* Host maximum receive is */
+ /* less than Linux on zSeries*/
+ /* transmit size */
+
+/*-----------------------------------------------------*
+* CLAW Constants application name *
+*------------------------------------------------------*/
+
+#define HOST_APPL_NAME "TCPIP "
+#define WS_APPL_NAME_IP_LINK "TCPIP "
+#define WS_APPL_NAME_IP_NAME "IP "
+#define WS_APPL_NAME_API_LINK "API "
+#define WS_APPL_NAME_PACKED "PACKED "
+#define WS_NAME_NOT_DEF "NOT_DEF "
+#define PACKING_ASK 1
+#define PACK_SEND 2
+#define DO_PACKED 3
+
+#define MAX_ENVELOPE_SIZE 65536
+#define CLAW_DEFAULT_MTU_SIZE 4096
+#define DEF_PACK_BUFSIZE 32768
+#define READ 0
+#define WRITE 1
+
+#define TB_TX 0 /* sk buffer handling in process */
+#define TB_STOP 1 /* network device stop in process */
+#define TB_RETRY 2 /* retry in process */
+#define TB_NOBUFFER 3 /* no buffer on free queue */
+#define CLAW_MAX_LINK_ID 1
+#define CLAW_MAX_DEV 256 /* max claw devices */
+#define MAX_NAME_LEN 8 /* host name, adapter name length */
+#define CLAW_FRAME_SIZE 4096
+#define CLAW_ID_SIZE BUS_ID_SIZE+3
+
+/* state machine codes used in claw_irq_handler */
+
+#define CLAW_STOP 0
+#define CLAW_START_HALT_IO 1
+#define CLAW_START_SENSEID 2
+#define CLAW_START_READ 3
+#define CLAW_START_WRITE 4
+
+/*-----------------------------------------------------*
+* Lock flag *
+*------------------------------------------------------*/
+#define LOCK_YES 0
+#define LOCK_NO 1
+
+/*-----------------------------------------------------*
+* DBF Debug macros *
+*------------------------------------------------------*/
+#define CLAW_DBF_TEXT(level, name, text) \
+ do { \
+ debug_text_event(claw_dbf_##name, level, text); \
+ } while (0)
+
+#define CLAW_DBF_HEX(level,name,addr,len) \
+do { \
+ debug_event(claw_dbf_##name,level,(void*)(addr),len); \
+} while (0)
+
+#define CLAW_DBF_TEXT_(level,name,text...) \
+do { \
+ sprintf(debug_buffer, text); \
+ debug_text_event(claw_dbf_##name,level, debug_buffer);\
+} while (0)
+
+/*******************************************************
+* Define Control Blocks *
+* *
+********************************************************/
+
+/*------------------------------------------------------*/
+/* CLAW header */
+/*------------------------------------------------------*/
+
+struct clawh {
+ __u16 length; /* length of data read by preceding read CCW */
+ __u8 opcode; /* equivalent read CCW */
+ __u8 flag; /* flag of FF to indicate read was completed */
+};
+
+/*------------------------------------------------------*/
+/* CLAW Packing header 4 bytes */
+/*------------------------------------------------------*/
+struct clawph {
+ __u16 len; /* Length of Packed Data Area */
+ __u8 flag; /* Reserved not used */
+ __u8 link_num; /* Link ID */
+};
+
+/*------------------------------------------------------*/
+/* CLAW Ending struct ccwbk */
+/*------------------------------------------------------*/
+struct endccw {
+ __u32 real; /* real address of this block */
+ __u8 write1; /* write 1 is active */
+ __u8 read1; /* read 1 is active */
+ __u16 reserved; /* reserved for future use */
+ struct ccw1 write1_nop1;
+ struct ccw1 write1_nop2;
+ struct ccw1 write2_nop1;
+ struct ccw1 write2_nop2;
+ struct ccw1 read1_nop1;
+ struct ccw1 read1_nop2;
+ struct ccw1 read2_nop1;
+ struct ccw1 read2_nop2;
+};
+
+/*------------------------------------------------------*/
+/* CLAW struct ccwbk */
+/*------------------------------------------------------*/
+struct ccwbk {
+ void *next; /* pointer to next ccw block */
+ __u32 real; /* real address of this ccw */
+ void *p_buffer; /* virtual address of data */
+ struct clawh header; /* claw header */
+ struct ccw1 write; /* write CCW */
+ struct ccw1 w_read_FF; /* read FF */
+ struct ccw1 w_TIC_1; /* TIC */
+ struct ccw1 read; /* read CCW */
+ struct ccw1 read_h; /* read header */
+ struct ccw1 signal; /* signal SMOD */
+ struct ccw1 r_TIC_1; /* TIC1 */
+ struct ccw1 r_read_FF; /* read FF */
+ struct ccw1 r_TIC_2; /* TIC2 */
+};
+
+/*------------------------------------------------------*/
+/* CLAW control block */
+/*------------------------------------------------------*/
+struct clawctl {
+ __u8 command; /* control command */
+ __u8 version; /* CLAW protocol version */
+ __u8 linkid; /* link ID */
+ __u8 correlator; /* correlator */
+ __u8 rc; /* return code */
+ __u8 reserved1; /* reserved */
+ __u8 reserved2; /* reserved */
+ __u8 reserved3; /* reserved */
+ __u8 data[24]; /* command specific fields */
+};
+
+/*------------------------------------------------------*/
+/* Data for SYSTEMVALIDATE command */
+/*------------------------------------------------------*/
+struct sysval {
+ char WS_name[8]; /* Workstation System name */
+ char host_name[8]; /* Host system name */
+ __u16 read_frame_size; /* read frame size */
+ __u16 write_frame_size; /* write frame size */
+ __u8 reserved[4]; /* reserved */
+};
+
+/*------------------------------------------------------*/
+/* Data for Connect command */
+/*------------------------------------------------------*/
+struct conncmd {
+ char WS_name[8]; /* Workstation application name */
+ char host_name[8]; /* Host application name */
+ __u16 reserved1[2]; /* read frame size */
+ __u8 reserved2[4]; /* reserved */
+};
+
+/*------------------------------------------------------*/
+/* Data for CLAW error */
+/*------------------------------------------------------*/
+struct clawwerror {
+ char reserved1[8]; /* reserved */
+ char reserved2[8]; /* reserved */
+ char reserved3[8]; /* reserved */
+};
+
+/*------------------------------------------------------*/
+/* Data buffer for CLAW */
+/*------------------------------------------------------*/
+struct clawbuf {
+ char buffer[MAX_ENVELOPE_SIZE]; /* data buffer */
+};
+
+/*------------------------------------------------------*/
+/* Channel control block for read and write channel */
+/*------------------------------------------------------*/
+
+struct chbk {
+ unsigned int devno;
+ int irq;
+ char id[CLAW_ID_SIZE];
+ __u32 IO_active;
+ __u8 claw_state;
+ struct irb *irb;
+ struct ccw_device *cdev; /* pointer to the channel device */
+ struct net_device *ndev;
+ wait_queue_head_t wait;
+ struct tasklet_struct tasklet;
+ struct timer_list timer;
+ unsigned long flag_a; /* atomic flags */
+#define CLAW_BH_ACTIVE 0
+ unsigned long flag_b; /* atomic flags */
+#define CLAW_WRITE_ACTIVE 0
+ __u8 last_dstat;
+ __u8 flag;
+ struct sk_buff_head collect_queue;
+ spinlock_t collect_lock;
+#define CLAW_WRITE 0x02 /* - Set if this is a write channel */
+#define CLAW_READ 0x01 /* - Set if this is a read channel */
+#define CLAW_TIMER 0x80 /* - Set if timer made the wake_up */
+};
+
+/*--------------------------------------------------------------*
+* CLAW environment block *
+*---------------------------------------------------------------*/
+
+struct claw_env {
+ unsigned int devno[2]; /* device number */
+ char host_name[9]; /* Host name */
+ char adapter_name [9]; /* adapter name */
+ char api_type[9]; /* TCPIP, API or PACKED */
+ void *p_priv; /* privptr */
+ __u16 read_buffers; /* read buffer number */
+ __u16 write_buffers; /* write buffer number */
+ __u16 read_size; /* read buffer size */
+ __u16 write_size; /* write buffer size */
+ __u16 dev_id; /* device ident */
+ __u8 packing; /* are we packing? */
+ volatile __u8 queme_switch; /* gate for imed packing */
+ volatile unsigned long pk_delay; /* Delay for adaptive packing */
+ __u8 in_use; /* device active flag */
+ struct net_device *ndev; /* backward ptr to the net dev*/
+};
+
+/*--------------------------------------------------------------*
+* CLAW main control block *
+*---------------------------------------------------------------*/
+
+struct claw_privbk {
+ void *p_buff_ccw;
+ __u32 p_buff_ccw_num;
+ void *p_buff_read;
+ __u32 p_buff_read_num;
+ __u32 p_buff_pages_perread;
+ void *p_buff_write;
+ __u32 p_buff_write_num;
+ __u32 p_buff_pages_perwrite;
+ long active_link_ID; /* Active logical link ID */
+ struct ccwbk *p_write_free_chain; /* pointer to free ccw chain */
+ struct ccwbk *p_write_active_first; /* ptr to the first write ccw */
+ struct ccwbk *p_write_active_last; /* ptr to the last write ccw */
+ struct ccwbk *p_read_active_first; /* ptr to the first read ccw */
+ struct ccwbk *p_read_active_last; /* ptr to the last read ccw */
+ struct endccw *p_end_ccw; /*ptr to ending ccw */
+ struct ccwbk *p_claw_signal_blk; /* ptr to signal block */
+ __u32 write_free_count; /* number of free bufs for write */
+ struct net_device_stats stats; /* device status */
+ struct chbk channel[2]; /* Channel control blocks */
+ __u8 mtc_skipping;
+ int mtc_offset;
+ int mtc_logical_link;
+ void *p_mtc_envelope;
+ struct sk_buff *pk_skb; /* packing buffer */
+ int pk_cnt;
+ struct clawctl ctl_bk;
+ struct claw_env *p_env;
+ __u8 system_validate_comp;
+ __u8 release_pend;
+ __u8 checksum_received_ip_pkts;
+ __u8 buffs_alloc;
+ struct endccw end_ccw;
+ unsigned long tbusy;
+
+};
+
+
+/************************************************************/
+/* define global constants */
+/************************************************************/
+
+#define CCWBK_SIZE sizeof(struct ccwbk)
+
+
diff --git a/drivers/s390/net/ctcmain.c b/drivers/s390/net/ctcmain.c
index 44ed75b5eaf42..7266bf5ea6599 100644
--- a/drivers/s390/net/ctcmain.c
+++ b/drivers/s390/net/ctcmain.c
@@ -1,5 +1,5 @@
/*
- * $Id: ctcmain.c,v 1.68 2004/12/27 09:25:27 heicarst Exp $
+ * $Id: ctcmain.c,v 1.72 2005/03/17 10:51:52 ptiedem Exp $
*
* CTC / ESCON network driver
*
@@ -7,6 +7,7 @@
* Author(s): Fritz Elfert (elfert@de.ibm.com, felfert@millenux.com)
* 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>
*
* Documentation used:
@@ -36,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.68 $
+ * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.72 $
*
*/
@@ -280,6 +281,8 @@ struct ctc_priv {
*/
fsm_timer restart_timer;
+ int buffer_size;
+
struct channel *channel[2];
};
@@ -320,7 +323,7 @@ static void
print_banner(void)
{
static int printed = 0;
- char vbuf[] = "$Revision: 1.68 $";
+ char vbuf[] = "$Revision: 1.72 $";
char *version = vbuf;
if (printed)
@@ -1894,13 +1897,15 @@ add_channel(struct ccw_device *cdev, enum channel_types type)
return -1;
}
memset(ch, 0, sizeof (struct channel));
- if ((ch->ccw = (struct ccw1 *) kmalloc(sizeof (struct ccw1) * 8,
+ if ((ch->ccw = (struct ccw1 *) kmalloc(8*sizeof(struct ccw1),
GFP_KERNEL | GFP_DMA)) == NULL) {
kfree(ch);
ctc_pr_warn("ctc: Out of memory in add_channel\n");
return -1;
}
+ memset(ch->ccw, 0, 8*sizeof(struct ccw1)); // assure all flags and counters are reset
+
/**
* "static" ccws are used in the following way:
*
@@ -1914,21 +1919,17 @@ add_channel(struct ccw_device *cdev, enum channel_types type)
* 4: write (idal allocated on every write).
* 5: nop
* ccw[6..7] (Channel program for initial channel setup):
- * 3: set extended mode
- * 4: nop
+ * 6: set extended mode
+ * 7: nop
*
* ch->ccw[0..5] are initialized in ch_action_start because
* the channel's direction is yet unknown here.
*/
ch->ccw[6].cmd_code = CCW_CMD_SET_EXTENDED;
ch->ccw[6].flags = CCW_FLAG_SLI;
- ch->ccw[6].count = 0;
- ch->ccw[6].cda = 0;
ch->ccw[7].cmd_code = CCW_CMD_NOOP;
ch->ccw[7].flags = CCW_FLAG_SLI;
- ch->ccw[7].count = 0;
- ch->ccw[7].cda = 0;
ch->cdev = cdev;
snprintf(ch->id, CTC_ID_SIZE, "ch-%s", cdev->dev.bus_id);
@@ -1955,7 +1956,7 @@ add_channel(struct ccw_device *cdev, enum channel_types type)
memset(ch->irb, 0, sizeof (struct irb));
while (*c && less_than((*c)->id, ch->id))
c = &(*c)->next;
- if (!strncmp((*c)->id, ch->id, CTC_ID_SIZE)) {
+ if (*c && (!strncmp((*c)->id, ch->id, CTC_ID_SIZE))) {
ctc_pr_debug(
"ctc: add_channel: device %s already in list, "
"using old entry\n", (*c)->id);
@@ -2011,6 +2012,8 @@ channel_remove(struct channel *ch)
dev_kfree_skb(ch->trans_skb);
}
kfree(ch->ccw);
+ kfree(ch->irb);
+ kfree(ch);
return;
}
c = &((*c)->next);
@@ -2703,7 +2706,7 @@ buffer_show(struct device *dev, char *buf)
if (!priv)
return -ENODEV;
return sprintf(buf, "%d\n",
- priv->channel[READ]->max_bufsize);
+ priv->buffer_size);
}
static ssize_t
@@ -2730,6 +2733,7 @@ buffer_write(struct device *dev, const char *buf, size_t count)
if (bs1 < (576 + LL_HEADER_LENGTH + 2))
return -EINVAL;
+ priv->buffer_size = bs1;
priv->channel[READ]->max_bufsize =
priv->channel[WRITE]->max_bufsize = bs1;
if (!(ndev->flags & IFF_RUNNING))
@@ -2925,7 +2929,8 @@ ctc_init_netdevice(struct net_device * dev, int alloc_device,
}
fsm_newstate(privptr->fsm, DEV_STATE_STOPPED);
fsm_settimer(privptr->fsm, &privptr->restart_timer);
- dev->mtu = CTC_BUFSIZE_DEFAULT - LL_HEADER_LENGTH - 2;
+ if (dev->mtu == 0)
+ dev->mtu = CTC_BUFSIZE_DEFAULT - LL_HEADER_LENGTH - 2;
dev->hard_start_xmit = ctc_tx;
dev->open = ctc_open;
dev->stop = ctc_close;
@@ -3050,7 +3055,7 @@ ctc_probe_device(struct ccwgroup_device *cgdev)
put_device(&cgdev->dev);
return rc;
}
-
+ priv->buffer_size = CTC_BUFSIZE_DEFAULT;
cgdev->cdev[0]->handler = ctc_irq_handler;
cgdev->cdev[1]->handler = ctc_irq_handler;
cgdev->dev.driver_data = priv;
@@ -3131,7 +3136,7 @@ ctc_new_device(struct ccwgroup_device *cgdev)
}
privptr->channel[direction]->netdev = dev;
privptr->channel[direction]->protocol = privptr->protocol;
- privptr->channel[direction]->max_bufsize = CTC_BUFSIZE_DEFAULT;
+ privptr->channel[direction]->max_bufsize = privptr->buffer_size;
}
/* sysfs magic */
SET_NETDEV_DEV(dev, &cgdev->dev);
diff --git a/drivers/s390/net/ctctty.c b/drivers/s390/net/ctctty.c
index a4fda34df7498..9257d60c78330 100644
--- a/drivers/s390/net/ctctty.c
+++ b/drivers/s390/net/ctctty.c
@@ -778,11 +778,10 @@ ctc_tty_ioctl(struct tty_struct *tty, struct file *file,
printk(KERN_DEBUG "%s%d ioctl TIOCSERGETLSR\n", CTC_TTY_NAME,
info->line);
#endif
- error = verify_area(VERIFY_WRITE, (void __user *) arg, sizeof(uint));
- if (error)
- return error;
- else
+ if (access_ok(VERIFY_WRITE, (void __user *) arg, sizeof(uint)))
return ctc_tty_get_lsr_info(info, (uint __user *) arg);
+ else
+ return -EFAULT;
default:
#ifdef CTC_DEBUG_MODEM_IOCTL
printk(KERN_DEBUG "UNKNOWN ioctl 0x%08x on %s%d\n", cmd,
diff --git a/drivers/s390/net/iucv.c b/drivers/s390/net/iucv.c
index 999991d0b670d..1ac6563ee3e0f 100644
--- a/drivers/s390/net/iucv.c
+++ b/drivers/s390/net/iucv.c
@@ -1,5 +1,5 @@
/*
- * $Id: iucv.c,v 1.42 2005/01/07 10:49:54 braunu Exp $
+ * $Id: iucv.c,v 1.43 2005/02/09 14:47:43 braunu 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.42 $
+ * RELEASE-TAG: IUCV lowlevel driver $Revision: 1.43 $
*
*/
@@ -355,7 +355,7 @@ do { \
static void
iucv_banner(void)
{
- char vbuf[] = "$Revision: 1.42 $";
+ char vbuf[] = "$Revision: 1.43 $";
char *version = vbuf;
if ((version = strchr(version, ':'))) {
@@ -2525,7 +2525,7 @@ iucv_tasklet_handler(unsigned long ignored)
return;
}
-module_init(iucv_init);
+subsys_initcall(iucv_init);
module_exit(iucv_exit);
/**
diff --git a/drivers/s390/net/qeth.h b/drivers/s390/net/qeth.h
index 2ec865e8c07a6..a341041a6cf77 100644
--- a/drivers/s390/net/qeth.h
+++ b/drivers/s390/net/qeth.h
@@ -24,7 +24,7 @@
#include "qeth_mpc.h"
-#define VERSION_QETH_H "$Revision: 1.132 $"
+#define VERSION_QETH_H "$Revision: 1.135 $"
#ifdef CONFIG_QETH_IPV6
#define QETH_VERSION_IPV6 ":IPv6"
@@ -68,7 +68,8 @@
#define QETH_DBF_TRACE_LEN 8
#define QETH_DBF_TRACE_INDEX 2
#define QETH_DBF_TRACE_NR_AREAS 2
-#define QETH_DBF_TRACE_LEVEL 5
+#define QETH_DBF_TRACE_LEVEL 3
+extern debug_info_t *qeth_dbf_trace;
#define QETH_DBF_SENSE_NAME "qeth_sense"
#define QETH_DBF_SENSE_LEN 64
@@ -206,6 +207,11 @@ struct qeth_perf_stats {
__u64 outbound_do_qdio_start_time;
unsigned int outbound_do_qdio_cnt;
unsigned int outbound_do_qdio_time;
+ /* eddp data */
+ unsigned int large_send_bytes;
+ unsigned int large_send_cnt;
+ unsigned int sg_skbs_sent;
+ unsigned int sg_frags_sent;
};
#endif /* CONFIG_QETH_PERF_STATS */
@@ -334,8 +340,8 @@ qeth_is_ipa_enabled(struct qeth_ipa_info *ipa, enum qeth_ipa_funcs func)
struct qeth_hdr_layer3 {
__u8 id;
__u8 flags;
- __u16 inbound_checksum;
- __u32 token;
+ __u16 inbound_checksum; /*TSO:__u16 seqno */
+ __u32 token; /*TSO: __u32 reserved */
__u16 length;
__u8 vlan_prio;
__u8 ext_flags;
@@ -386,6 +392,7 @@ enum qeth_layer2_frame_flags {
enum qeth_header_ids {
QETH_HEADER_TYPE_LAYER3 = 0x01,
QETH_HEADER_TYPE_LAYER2 = 0x02,
+ QETH_HEADER_TYPE_TSO = 0x03,
};
/* flags for qeth_hdr.ext_flags */
#define QETH_HDR_EXT_VLAN_FRAME 0x01
@@ -394,6 +401,7 @@ enum qeth_header_ids {
#define QETH_HDR_EXT_SRC_MAC_ADDR 0x08
#define QETH_HDR_EXT_CSUM_HDR_REQ 0x10
#define QETH_HDR_EXT_CSUM_TRANSP_REQ 0x20
+#define QETH_HDR_EXT_UDP_TSO 0x40 /*bit off for TCP*/
static inline int
qeth_is_last_sbale(struct qdio_buffer_element *sbale)
@@ -448,11 +456,19 @@ struct qeth_qdio_q {
volatile int next_buf_to_init;
} __attribute__ ((aligned(256)));
+/* possible types of qeth large_send support */
+enum qeth_large_send_types {
+ QETH_LARGE_SEND_NO,
+ QETH_LARGE_SEND_EDDP,
+ QETH_LARGE_SEND_TSO,
+};
+
struct qeth_qdio_out_buffer {
struct qdio_buffer *buffer;
atomic_t state;
volatile int next_element_to_fill;
struct sk_buff_head skb_list;
+ struct list_head ctx_list;
};
struct qeth_card;
@@ -668,6 +684,14 @@ struct qeth_reply {
#define QETH_BROADCAST_WITH_ECHO 1
#define QETH_BROADCAST_WITHOUT_ECHO 2
+struct qeth_card_blkt {
+ int time_total;
+ int inter_packet;
+ int inter_packet_jumbo;
+};
+
+
+
struct qeth_card_info {
unsigned short unit_addr2;
unsigned short cula;
@@ -686,6 +710,7 @@ struct qeth_card_info {
int max_mtu;
int broadcast_capable;
int unique_id;
+ struct qeth_card_blkt blkt;
__u32 csum_mask;
};
@@ -704,6 +729,7 @@ struct qeth_card_options {
int add_hhlen;
int fake_ll;
int layer2;
+ enum qeth_large_send_types large_send;
};
/*
@@ -790,6 +816,57 @@ qeth_get_ipa_adp_type(enum qeth_link_types link_type)
}
inline static int
+qeth_realloc_headroom(struct qeth_card *card, struct sk_buff **skb, int size)
+{
+ struct sk_buff *new_skb = NULL;
+
+ if (skb_headroom(*skb) < size){
+ new_skb = skb_realloc_headroom(*skb, size);
+ if (!new_skb) {
+ PRINT_ERR("qeth_prepare_skb: could "
+ "not realloc headroom for qeth_hdr "
+ "on interface %s", QETH_CARD_IFNAME(card));
+ return -ENOMEM;
+ }
+ *skb = new_skb;
+ }
+ return 0;
+}
+static inline struct sk_buff *
+qeth_pskb_unshare(struct sk_buff *skb, int pri)
+{
+ struct sk_buff *nskb;
+ if (!skb_cloned(skb))
+ return skb;
+ nskb = skb_copy(skb, pri);
+ kfree_skb(skb); /* free our shared copy */
+ return nskb;
+}
+
+
+inline static void *
+qeth_push_skb(struct qeth_card *card, struct sk_buff **skb, int size)
+{
+ void *hdr;
+
+ hdr = (void *) skb_push(*skb, size);
+ /*
+ * sanity check, the Linux memory allocation scheme should
+ * never present us cases like this one (the qdio header size plus
+ * the first 40 bytes of the paket cross a 4k boundary)
+ */
+ if ((((unsigned long) hdr) & (~(PAGE_SIZE - 1))) !=
+ (((unsigned long) hdr + size +
+ QETH_IP_HEADER_SIZE) & (~(PAGE_SIZE - 1)))) {
+ PRINT_ERR("qeth_prepare_skb: misaligned "
+ "packet on interface %s. Discarded.",
+ QETH_CARD_IFNAME(card));
+ return NULL;
+ }
+ return hdr;
+}
+
+inline static int
qeth_get_hlen(__u8 link_type)
{
#ifdef CONFIG_QETH_IPV6
@@ -830,17 +907,6 @@ qeth_get_netdev_flags(struct qeth_card *card)
#endif
}
}
-static inline struct sk_buff *
-qeth_pskb_unshare(struct sk_buff *skb, int pri)
-{
- struct sk_buff *nskb;
- if (!skb_cloned(skb))
- return skb;
- nskb = skb_copy(skb, pri);
- kfree_skb(skb); /* free our shared copy */
- return nskb;
-}
-
inline static int
qeth_get_initial_mtu_for_card(struct qeth_card * card)
@@ -1084,4 +1150,13 @@ qeth_schedule_recovery(struct qeth_card *);
extern int
qeth_realloc_buffer_pool(struct qeth_card *, int);
+extern int
+qeth_set_large_send(struct qeth_card *);
+
+extern void
+qeth_fill_header(struct qeth_card *, struct qeth_hdr *,
+ struct sk_buff *, int, int);
+extern void
+qeth_flush_buffers(struct qeth_qdio_out_q *, int, int, int);
+
#endif /* __QETH_H__ */
diff --git a/drivers/s390/net/qeth_eddp.c b/drivers/s390/net/qeth_eddp.c
new file mode 100644
index 0000000000000..7ee1c06ed68a8
--- /dev/null
+++ b/drivers/s390/net/qeth_eddp.c
@@ -0,0 +1,643 @@
+/*
+ *
+ * linux/drivers/s390/net/qeth_eddp.c ($Revision: 1.11 $)
+ *
+ * Enhanced Device Driver Packing (EDDP) support for the qeth driver.
+ *
+ * Copyright 2004 IBM Corporation
+ *
+ * Author(s): Thomas Spatzier <tspat@de.ibm.com>
+ *
+ * $Revision: 1.11 $ $Date: 2005/03/24 09:04:18 $
+ *
+ */
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/ip.h>
+#include <linux/inetdevice.h>
+#include <linux/netdevice.h>
+#include <linux/kernel.h>
+#include <linux/tcp.h>
+#include <net/tcp.h>
+#include <linux/skbuff.h>
+
+#include <net/ip.h>
+
+#include "qeth.h"
+#include "qeth_mpc.h"
+#include "qeth_eddp.h"
+
+int
+qeth_eddp_check_buffers_for_context(struct qeth_qdio_out_q *queue,
+ struct qeth_eddp_context *ctx)
+{
+ int index = queue->next_buf_to_fill;
+ int elements_needed = ctx->num_elements;
+ int elements_in_buffer;
+ int skbs_in_buffer;
+ int buffers_needed = 0;
+
+ QETH_DBF_TEXT(trace, 5, "eddpcbfc");
+ while(elements_needed > 0) {
+ buffers_needed++;
+ if (atomic_read(&queue->bufs[index].state) !=
+ QETH_QDIO_BUF_EMPTY)
+ return -EBUSY;
+
+ elements_in_buffer = QETH_MAX_BUFFER_ELEMENTS(queue->card) -
+ queue->bufs[index].next_element_to_fill;
+ skbs_in_buffer = elements_in_buffer / ctx->elements_per_skb;
+ elements_needed -= skbs_in_buffer * ctx->elements_per_skb;
+ index = (index + 1) % QDIO_MAX_BUFFERS_PER_Q;
+ }
+ return buffers_needed;
+}
+
+static inline void
+qeth_eddp_free_context(struct qeth_eddp_context *ctx)
+{
+ int i;
+
+ QETH_DBF_TEXT(trace, 5, "eddpfctx");
+ for (i = 0; i < ctx->num_pages; ++i)
+ free_page((unsigned long)ctx->pages[i]);
+ kfree(ctx->pages);
+ if (ctx->elements != NULL)
+ kfree(ctx->elements);
+ kfree(ctx);
+}
+
+
+static inline void
+qeth_eddp_get_context(struct qeth_eddp_context *ctx)
+{
+ atomic_inc(&ctx->refcnt);
+}
+
+void
+qeth_eddp_put_context(struct qeth_eddp_context *ctx)
+{
+ if (atomic_dec_return(&ctx->refcnt) == 0)
+ qeth_eddp_free_context(ctx);
+}
+
+void
+qeth_eddp_buf_release_contexts(struct qeth_qdio_out_buffer *buf)
+{
+ struct qeth_eddp_context_reference *ref;
+
+ QETH_DBF_TEXT(trace, 6, "eddprctx");
+ while (!list_empty(&buf->ctx_list)){
+ ref = list_entry(buf->ctx_list.next,
+ struct qeth_eddp_context_reference, list);
+ qeth_eddp_put_context(ref->ctx);
+ list_del(&ref->list);
+ kfree(ref);
+ }
+}
+
+static inline int
+qeth_eddp_buf_ref_context(struct qeth_qdio_out_buffer *buf,
+ struct qeth_eddp_context *ctx)
+{
+ struct qeth_eddp_context_reference *ref;
+
+ QETH_DBF_TEXT(trace, 6, "eddprfcx");
+ ref = kmalloc(sizeof(struct qeth_eddp_context_reference), GFP_ATOMIC);
+ if (ref == NULL)
+ return -ENOMEM;
+ qeth_eddp_get_context(ctx);
+ ref->ctx = ctx;
+ list_add_tail(&ref->list, &buf->ctx_list);
+ return 0;
+}
+
+int
+qeth_eddp_fill_buffer(struct qeth_qdio_out_q *queue,
+ struct qeth_eddp_context *ctx,
+ int index)
+{
+ struct qeth_qdio_out_buffer *buf = NULL;
+ struct qdio_buffer *buffer;
+ int elements = ctx->num_elements;
+ int element = 0;
+ int flush_cnt = 0;
+ int must_refcnt = 1;
+ int i;
+
+ QETH_DBF_TEXT(trace, 5, "eddpfibu");
+ while (elements > 0) {
+ buf = &queue->bufs[index];
+ if (atomic_read(&buf->state) != QETH_QDIO_BUF_EMPTY){
+ /* normally this should not happen since we checked for
+ * available elements in qeth_check_elements_for_context
+ */
+ if (element == 0)
+ return -EBUSY;
+ else {
+ PRINT_WARN("could only partially fill eddp "
+ "buffer!\n");
+ goto out;
+ }
+ }
+ /* check if the whole next skb fits into current buffer */
+ if ((QETH_MAX_BUFFER_ELEMENTS(queue->card) -
+ buf->next_element_to_fill)
+ < ctx->elements_per_skb){
+ /* no -> go to next buffer */
+ atomic_set(&buf->state, QETH_QDIO_BUF_PRIMED);
+ index = (index + 1) % QDIO_MAX_BUFFERS_PER_Q;
+ flush_cnt++;
+ /* new buffer, so we have to add ctx to buffer'ctx_list
+ * and increment ctx's refcnt */
+ must_refcnt = 1;
+ continue;
+ }
+ if (must_refcnt){
+ must_refcnt = 0;
+ if (qeth_eddp_buf_ref_context(buf, ctx)){
+ PRINT_WARN("no memory to create eddp context "
+ "reference\n");
+ goto out_check;
+ }
+ }
+ buffer = buf->buffer;
+ /* fill one skb into buffer */
+ for (i = 0; i < ctx->elements_per_skb; ++i){
+ buffer->element[buf->next_element_to_fill].addr =
+ ctx->elements[element].addr;
+ buffer->element[buf->next_element_to_fill].length =
+ ctx->elements[element].length;
+ buffer->element[buf->next_element_to_fill].flags =
+ ctx->elements[element].flags;
+ buf->next_element_to_fill++;
+ element++;
+ elements--;
+ }
+ }
+out_check:
+ if (!queue->do_pack) {
+ QETH_DBF_TEXT(trace, 6, "fillbfnp");
+ /* set state to PRIMED -> will be flushed */
+ if (buf->next_element_to_fill > 0){
+ atomic_set(&buf->state, QETH_QDIO_BUF_PRIMED);
+ flush_cnt++;
+ }
+ } else {
+#ifdef CONFIG_QETH_PERF_STATS
+ queue->card->perf_stats.skbs_sent_pack++;
+#endif
+ QETH_DBF_TEXT(trace, 6, "fillbfpa");
+ if (buf->next_element_to_fill >=
+ QETH_MAX_BUFFER_ELEMENTS(queue->card)) {
+ /*
+ * packed buffer if full -> set state PRIMED
+ * -> will be flushed
+ */
+ atomic_set(&buf->state, QETH_QDIO_BUF_PRIMED);
+ flush_cnt++;
+ }
+ }
+out:
+ return flush_cnt;
+}
+
+static inline int
+qeth_get_skb_data_len(struct sk_buff *skb)
+{
+ int len = skb->len;
+ int i;
+
+ for (i = 0; i < skb_shinfo(skb)->nr_frags; ++i)
+ len -= skb_shinfo(skb)->frags[i].size;
+ return len;
+}
+
+static inline void
+qeth_eddp_create_segment_hdrs(struct qeth_eddp_context *ctx,
+ struct qeth_eddp_data *eddp)
+{
+ u8 *page;
+ int page_remainder;
+ int page_offset;
+ int hdr_len;
+ struct qeth_eddp_element *element;
+
+ QETH_DBF_TEXT(trace, 5, "eddpcrsh");
+ page = ctx->pages[ctx->offset >> PAGE_SHIFT];
+ page_offset = ctx->offset % PAGE_SIZE;
+ element = &ctx->elements[ctx->num_elements];
+ hdr_len = eddp->nhl + eddp->thl;
+ /* FIXME: layer2 and VLAN !!! */
+ if (eddp->qh.hdr.l2.id == QETH_HEADER_TYPE_LAYER2)
+ hdr_len += ETH_HLEN;
+ if (eddp->mac.h_proto == __constant_htons(ETH_P_8021Q))
+ hdr_len += VLAN_HLEN;
+ /* does complete header fit in current page ? */
+ page_remainder = PAGE_SIZE - page_offset;
+ if (page_remainder < (sizeof(struct qeth_hdr) + hdr_len)){
+ /* no -> go to start of next page */
+ ctx->offset += page_remainder;
+ page = ctx->pages[ctx->offset >> PAGE_SHIFT];
+ page_offset = 0;
+ }
+ memcpy(page + page_offset, &eddp->qh, sizeof(struct qeth_hdr));
+ element->addr = page + page_offset;
+ element->length = sizeof(struct qeth_hdr);
+ ctx->offset += sizeof(struct qeth_hdr);
+ page_offset += sizeof(struct qeth_hdr);
+ /* add mac header (?) */
+ if (eddp->qh.hdr.l2.id == QETH_HEADER_TYPE_LAYER2){
+ memcpy(page + page_offset, &eddp->mac, ETH_HLEN);
+ element->length += ETH_HLEN;
+ ctx->offset += ETH_HLEN;
+ page_offset += ETH_HLEN;
+ }
+ /* add VLAN tag */
+ if (eddp->mac.h_proto == __constant_htons(ETH_P_8021Q)){
+ memcpy(page + page_offset, &eddp->vlan, VLAN_HLEN);
+ element->length += VLAN_HLEN;
+ ctx->offset += VLAN_HLEN;
+ page_offset += VLAN_HLEN;
+ }
+ /* add network header */
+ memcpy(page + page_offset, (u8 *)&eddp->nh, eddp->nhl);
+ element->length += eddp->nhl;
+ eddp->nh_in_ctx = page + page_offset;
+ ctx->offset += eddp->nhl;
+ page_offset += eddp->nhl;
+ /* add transport header */
+ memcpy(page + page_offset, (u8 *)&eddp->th, eddp->thl);
+ element->length += eddp->thl;
+ eddp->th_in_ctx = page + page_offset;
+ ctx->offset += eddp->thl;
+}
+
+static inline void
+qeth_eddp_copy_data_tcp(char *dst, struct qeth_eddp_data *eddp, int len,
+ u32 *hcsum)
+{
+ struct skb_frag_struct *frag;
+ int left_in_frag;
+ int copy_len;
+ u8 *src;
+
+ QETH_DBF_TEXT(trace, 5, "eddpcdtc");
+ if (skb_shinfo(eddp->skb)->nr_frags == 0) {
+ memcpy(dst, eddp->skb->data + eddp->skb_offset, len);
+ *hcsum = csum_partial(eddp->skb->data + eddp->skb_offset, len,
+ *hcsum);
+ eddp->skb_offset += len;
+ } else {
+ while (len > 0) {
+ if (eddp->frag < 0) {
+ /* we're in skb->data */
+ left_in_frag = qeth_get_skb_data_len(eddp->skb)
+ - eddp->skb_offset;
+ src = eddp->skb->data + eddp->skb_offset;
+ } else {
+ frag = &skb_shinfo(eddp->skb)->
+ frags[eddp->frag];
+ left_in_frag = frag->size - eddp->frag_offset;
+ src = (u8 *)(
+ (page_to_pfn(frag->page) << PAGE_SHIFT)+
+ frag->page_offset + eddp->frag_offset);
+ }
+ if (left_in_frag <= 0) {
+ eddp->frag++;
+ eddp->frag_offset = 0;
+ continue;
+ }
+ copy_len = min(left_in_frag, len);
+ memcpy(dst, src, copy_len);
+ *hcsum = csum_partial(src, copy_len, *hcsum);
+ dst += copy_len;
+ eddp->frag_offset += copy_len;
+ eddp->skb_offset += copy_len;
+ len -= copy_len;
+ }
+ }
+}
+
+static inline void
+qeth_eddp_create_segment_data_tcp(struct qeth_eddp_context *ctx,
+ struct qeth_eddp_data *eddp, int data_len,
+ u32 hcsum)
+{
+ u8 *page;
+ int page_remainder;
+ int page_offset;
+ struct qeth_eddp_element *element;
+ int first_lap = 1;
+
+ QETH_DBF_TEXT(trace, 5, "eddpcsdt");
+ page = ctx->pages[ctx->offset >> PAGE_SHIFT];
+ page_offset = ctx->offset % PAGE_SIZE;
+ element = &ctx->elements[ctx->num_elements];
+ while (data_len){
+ page_remainder = PAGE_SIZE - page_offset;
+ if (page_remainder < data_len){
+ qeth_eddp_copy_data_tcp(page + page_offset, eddp,
+ page_remainder, &hcsum);
+ element->length += page_remainder;
+ if (first_lap)
+ element->flags = SBAL_FLAGS_FIRST_FRAG;
+ else
+ element->flags = SBAL_FLAGS_MIDDLE_FRAG;
+ ctx->num_elements++;
+ element++;
+ data_len -= page_remainder;
+ ctx->offset += page_remainder;
+ page = ctx->pages[ctx->offset >> PAGE_SHIFT];
+ page_offset = 0;
+ element->addr = page + page_offset;
+ } else {
+ qeth_eddp_copy_data_tcp(page + page_offset, eddp,
+ data_len, &hcsum);
+ element->length += data_len;
+ if (!first_lap)
+ element->flags = SBAL_FLAGS_LAST_FRAG;
+ ctx->num_elements++;
+ ctx->offset += data_len;
+ data_len = 0;
+ }
+ first_lap = 0;
+ }
+ ((struct tcphdr *)eddp->th_in_ctx)->check = csum_fold(hcsum);
+}
+
+static inline u32
+qeth_eddp_check_tcp4_hdr(struct qeth_eddp_data *eddp, int data_len)
+{
+ u32 phcsum; /* pseudo header checksum */
+
+ QETH_DBF_TEXT(trace, 5, "eddpckt4");
+ eddp->th.tcp.h.check = 0;
+ /* compute pseudo header checksum */
+ phcsum = csum_tcpudp_nofold(eddp->nh.ip4.h.saddr, eddp->nh.ip4.h.daddr,
+ eddp->thl + data_len, IPPROTO_TCP, 0);
+ /* compute checksum of tcp header */
+ return csum_partial((u8 *)&eddp->th, eddp->thl, phcsum);
+}
+
+static inline u32
+qeth_eddp_check_tcp6_hdr(struct qeth_eddp_data *eddp, int data_len)
+{
+ u32 proto;
+ u32 phcsum; /* pseudo header checksum */
+
+ QETH_DBF_TEXT(trace, 5, "eddpckt6");
+ eddp->th.tcp.h.check = 0;
+ /* compute pseudo header checksum */
+ phcsum = csum_partial((u8 *)&eddp->nh.ip6.h.saddr,
+ sizeof(struct in6_addr), 0);
+ phcsum = csum_partial((u8 *)&eddp->nh.ip6.h.daddr,
+ sizeof(struct in6_addr), phcsum);
+ proto = htonl(IPPROTO_TCP);
+ phcsum = csum_partial((u8 *)&proto, sizeof(u32), phcsum);
+ return phcsum;
+}
+
+static inline struct qeth_eddp_data *
+qeth_eddp_create_eddp_data(struct qeth_hdr *qh, u8 *nh, u8 nhl, u8 *th, u8 thl)
+{
+ struct qeth_eddp_data *eddp;
+
+ QETH_DBF_TEXT(trace, 5, "eddpcrda");
+ eddp = kmalloc(sizeof(struct qeth_eddp_data), GFP_ATOMIC);
+ if (eddp){
+ memset(eddp, 0, sizeof(struct qeth_eddp_data));
+ eddp->nhl = nhl;
+ eddp->thl = thl;
+ memcpy(&eddp->qh, qh, sizeof(struct qeth_hdr));
+ memcpy(&eddp->nh, nh, nhl);
+ memcpy(&eddp->th, th, thl);
+ eddp->frag = -1; /* initially we're in skb->data */
+ }
+ return eddp;
+}
+
+static inline void
+__qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx,
+ struct qeth_eddp_data *eddp)
+{
+ struct tcphdr *tcph;
+ int data_len;
+ u32 hcsum;
+
+ QETH_DBF_TEXT(trace, 5, "eddpftcp");
+ eddp->skb_offset = sizeof(struct qeth_hdr) + eddp->nhl + eddp->thl;
+ tcph = eddp->skb->h.th;
+ while (eddp->skb_offset < eddp->skb->len) {
+ data_len = min((int)skb_shinfo(eddp->skb)->tso_size,
+ (int)(eddp->skb->len - eddp->skb_offset));
+ /* prepare qdio hdr */
+ if (eddp->qh.hdr.l2.id == QETH_HEADER_TYPE_LAYER2){
+ eddp->qh.hdr.l2.pkt_length = data_len + ETH_HLEN +
+ eddp->nhl + eddp->thl -
+ sizeof(struct qeth_hdr);
+#ifdef CONFIG_QETH_VLAN
+ if (eddp->mac.h_proto == __constant_htons(ETH_P_8021Q))
+ eddp->qh.hdr.l2.pkt_length += VLAN_HLEN;
+#endif /* CONFIG_QETH_VLAN */
+ } else
+ eddp->qh.hdr.l3.length = data_len + eddp->nhl +
+ eddp->thl;
+ /* prepare ip hdr */
+ if (eddp->skb->protocol == ETH_P_IP){
+ eddp->nh.ip4.h.tot_len = data_len + eddp->nhl +
+ eddp->thl;
+ eddp->nh.ip4.h.check = 0;
+ eddp->nh.ip4.h.check =
+ ip_fast_csum((u8 *)&eddp->nh.ip4.h,
+ eddp->nh.ip4.h.ihl);
+ } else
+ eddp->nh.ip6.h.payload_len = data_len + eddp->thl;
+ /* prepare tcp hdr */
+ if (data_len == (eddp->skb->len - eddp->skb_offset)){
+ /* last segment -> set FIN and PSH flags */
+ eddp->th.tcp.h.fin = tcph->fin;
+ eddp->th.tcp.h.psh = tcph->psh;
+ }
+ if (eddp->skb->protocol == ETH_P_IP)
+ hcsum = qeth_eddp_check_tcp4_hdr(eddp, data_len);
+ else
+ hcsum = qeth_eddp_check_tcp6_hdr(eddp, data_len);
+ /* fill the next segment into the context */
+ qeth_eddp_create_segment_hdrs(ctx, eddp);
+ qeth_eddp_create_segment_data_tcp(ctx, eddp, data_len, hcsum);
+ if (eddp->skb_offset >= eddp->skb->len)
+ break;
+ /* prepare headers for next round */
+ if (eddp->skb->protocol == ETH_P_IP)
+ eddp->nh.ip4.h.id++;
+ eddp->th.tcp.h.seq += data_len;
+ }
+}
+
+static inline int
+qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx,
+ struct sk_buff *skb, struct qeth_hdr *qhdr)
+{
+ struct qeth_eddp_data *eddp = NULL;
+
+ QETH_DBF_TEXT(trace, 5, "eddpficx");
+ /* create our segmentation headers and copy original headers */
+ if (skb->protocol == ETH_P_IP)
+ eddp = qeth_eddp_create_eddp_data(qhdr, (u8 *)skb->nh.iph,
+ skb->nh.iph->ihl*4,
+ (u8 *)skb->h.th, skb->h.th->doff*4);
+ else
+ eddp = qeth_eddp_create_eddp_data(qhdr, (u8 *)skb->nh.ipv6h,
+ sizeof(struct ipv6hdr),
+ (u8 *)skb->h.th, skb->h.th->doff*4);
+
+ if (eddp == NULL) {
+ QETH_DBF_TEXT(trace, 2, "eddpfcnm");
+ return -ENOMEM;
+ }
+ if (qhdr->hdr.l2.id == QETH_HEADER_TYPE_LAYER2) {
+ memcpy(&eddp->mac, eth_hdr(skb), ETH_HLEN);
+#ifdef CONFIG_QETH_VLAN
+ if (eddp->mac.h_proto == __constant_htons(ETH_P_8021Q)) {
+ eddp->vlan[0] = __constant_htons(skb->protocol);
+ eddp->vlan[1] = htons(vlan_tx_tag_get(skb));
+ }
+#endif /* CONFIG_QETH_VLAN */
+ }
+ /* the next flags will only be set on the last segment */
+ eddp->th.tcp.h.fin = 0;
+ eddp->th.tcp.h.psh = 0;
+ eddp->skb = skb;
+ /* begin segmentation and fill context */
+ __qeth_eddp_fill_context_tcp(ctx, eddp);
+ kfree(eddp);
+ return 0;
+}
+
+static inline void
+qeth_eddp_calc_num_pages(struct qeth_eddp_context *ctx, struct sk_buff *skb,
+ int hdr_len)
+{
+ int skbs_per_page;
+
+ QETH_DBF_TEXT(trace, 5, "eddpcanp");
+ /* can we put multiple skbs in one page? */
+ skbs_per_page = PAGE_SIZE / (skb_shinfo(skb)->tso_size + hdr_len);
+ if (skbs_per_page > 1){
+ ctx->num_pages = (skb_shinfo(skb)->tso_segs + 1) /
+ skbs_per_page + 1;
+ ctx->elements_per_skb = 1;
+ } else {
+ /* no -> how many elements per skb? */
+ ctx->elements_per_skb = (skb_shinfo(skb)->tso_size + hdr_len +
+ PAGE_SIZE) >> PAGE_SHIFT;
+ ctx->num_pages = ctx->elements_per_skb *
+ (skb_shinfo(skb)->tso_segs + 1);
+ }
+ ctx->num_elements = ctx->elements_per_skb *
+ (skb_shinfo(skb)->tso_segs + 1);
+}
+
+static inline struct qeth_eddp_context *
+qeth_eddp_create_context_generic(struct qeth_card *card, struct sk_buff *skb,
+ int hdr_len)
+{
+ struct qeth_eddp_context *ctx = NULL;
+ u8 *addr;
+ int i;
+
+ QETH_DBF_TEXT(trace, 5, "creddpcg");
+ /* create the context and allocate pages */
+ ctx = kmalloc(sizeof(struct qeth_eddp_context), GFP_ATOMIC);
+ if (ctx == NULL){
+ QETH_DBF_TEXT(trace, 2, "ceddpcn1");
+ return NULL;
+ }
+ memset(ctx, 0, sizeof(struct qeth_eddp_context));
+ ctx->type = QETH_LARGE_SEND_EDDP;
+ qeth_eddp_calc_num_pages(ctx, skb, hdr_len);
+ if (ctx->elements_per_skb > QETH_MAX_BUFFER_ELEMENTS(card)){
+ QETH_DBF_TEXT(trace, 2, "ceddpcis");
+ kfree(ctx);
+ return NULL;
+ }
+ ctx->pages = kmalloc(ctx->num_pages * sizeof(u8 *), GFP_ATOMIC);
+ if (ctx->pages == NULL){
+ QETH_DBF_TEXT(trace, 2, "ceddpcn2");
+ kfree(ctx);
+ return NULL;
+ }
+ memset(ctx->pages, 0, ctx->num_pages * sizeof(u8 *));
+ for (i = 0; i < ctx->num_pages; ++i){
+ addr = (u8 *)__get_free_page(GFP_ATOMIC);
+ if (addr == NULL){
+ QETH_DBF_TEXT(trace, 2, "ceddpcn3");
+ ctx->num_pages = i;
+ qeth_eddp_free_context(ctx);
+ return NULL;
+ }
+ memset(addr, 0, PAGE_SIZE);
+ ctx->pages[i] = addr;
+ }
+ ctx->elements = kmalloc(ctx->num_elements *
+ sizeof(struct qeth_eddp_element), GFP_ATOMIC);
+ if (ctx->elements == NULL){
+ QETH_DBF_TEXT(trace, 2, "ceddpcn4");
+ qeth_eddp_free_context(ctx);
+ return NULL;
+ }
+ memset(ctx->elements, 0,
+ ctx->num_elements * sizeof(struct qeth_eddp_element));
+ /* reset num_elements; will be incremented again in fill_buffer to
+ * reflect number of actually used elements */
+ ctx->num_elements = 0;
+ return ctx;
+}
+
+static inline struct qeth_eddp_context *
+qeth_eddp_create_context_tcp(struct qeth_card *card, struct sk_buff *skb,
+ struct qeth_hdr *qhdr)
+{
+ struct qeth_eddp_context *ctx = NULL;
+
+ QETH_DBF_TEXT(trace, 5, "creddpct");
+ if (skb->protocol == ETH_P_IP)
+ ctx = qeth_eddp_create_context_generic(card, skb,
+ sizeof(struct qeth_hdr) + skb->nh.iph->ihl*4 +
+ skb->h.th->doff*4);
+ else if (skb->protocol == ETH_P_IPV6)
+ ctx = qeth_eddp_create_context_generic(card, skb,
+ sizeof(struct qeth_hdr) + sizeof(struct ipv6hdr) +
+ skb->h.th->doff*4);
+ else
+ QETH_DBF_TEXT(trace, 2, "cetcpinv");
+
+ if (ctx == NULL) {
+ QETH_DBF_TEXT(trace, 2, "creddpnl");
+ return NULL;
+ }
+ if (qeth_eddp_fill_context_tcp(ctx, skb, qhdr)){
+ QETH_DBF_TEXT(trace, 2, "ceddptfe");
+ qeth_eddp_free_context(ctx);
+ return NULL;
+ }
+ atomic_set(&ctx->refcnt, 1);
+ return ctx;
+}
+
+struct qeth_eddp_context *
+qeth_eddp_create_context(struct qeth_card *card, struct sk_buff *skb,
+ struct qeth_hdr *qhdr)
+{
+ QETH_DBF_TEXT(trace, 5, "creddpc");
+ switch (skb->sk->sk_protocol){
+ case IPPROTO_TCP:
+ return qeth_eddp_create_context_tcp(card, skb, qhdr);
+ default:
+ QETH_DBF_TEXT(trace, 2, "eddpinvp");
+ }
+ return NULL;
+}
+
+
diff --git a/drivers/s390/net/qeth_eddp.h b/drivers/s390/net/qeth_eddp.h
new file mode 100644
index 0000000000000..e1b51860bc57b
--- /dev/null
+++ b/drivers/s390/net/qeth_eddp.h
@@ -0,0 +1,85 @@
+/*
+ * linux/drivers/s390/net/qeth_eddp.c ($Revision: 1.5 $)
+ *
+ * Header file for qeth enhanced device driver pakcing.
+ *
+ * Copyright 2004 IBM Corporation
+ *
+ * Author(s): Thomas Spatzier <tspat@de.ibm.com>
+ *
+ * $Revision: 1.5 $ $Date: 2005/03/24 09:04:18 $
+ *
+ */
+#ifndef __QETH_EDDP_H__
+#define __QETH_EDDP_H__
+
+struct qeth_eddp_element {
+ u32 flags;
+ u32 length;
+ void *addr;
+};
+
+struct qeth_eddp_context {
+ atomic_t refcnt;
+ enum qeth_large_send_types type;
+ int num_pages; /* # of allocated pages */
+ u8 **pages; /* pointers to pages */
+ int offset; /* offset in ctx during creation */
+ int num_elements; /* # of required 'SBALEs' */
+ struct qeth_eddp_element *elements; /* array of 'SBALEs' */
+ int elements_per_skb; /* # of 'SBALEs' per skb **/
+};
+
+struct qeth_eddp_context_reference {
+ struct list_head list;
+ struct qeth_eddp_context *ctx;
+};
+
+extern struct qeth_eddp_context *
+qeth_eddp_create_context(struct qeth_card *,struct sk_buff *,struct qeth_hdr *);
+
+extern void
+qeth_eddp_put_context(struct qeth_eddp_context *);
+
+extern int
+qeth_eddp_fill_buffer(struct qeth_qdio_out_q *,struct qeth_eddp_context *,int);
+
+extern void
+qeth_eddp_buf_release_contexts(struct qeth_qdio_out_buffer *);
+
+extern int
+qeth_eddp_check_buffers_for_context(struct qeth_qdio_out_q *,
+ struct qeth_eddp_context *);
+/*
+ * Data used for fragmenting a IP packet.
+ */
+struct qeth_eddp_data {
+ struct qeth_hdr qh;
+ struct ethhdr mac;
+ u16 vlan[2];
+ union {
+ struct {
+ struct iphdr h;
+ u8 options[40];
+ } ip4;
+ struct {
+ struct ipv6hdr h;
+ } ip6;
+ } nh;
+ u8 nhl;
+ void *nh_in_ctx; /* address of nh within the ctx */
+ union {
+ struct {
+ struct tcphdr h;
+ u8 options[40];
+ } tcp;
+ } th;
+ u8 thl;
+ void *th_in_ctx; /* address of th within the ctx */
+ struct sk_buff *skb;
+ int skb_offset;
+ int frag;
+ int frag_offset;
+} __attribute__ ((packed));
+
+#endif /* __QETH_EDDP_H__ */
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c
index 535f46b92d72f..607b92542df6c 100644
--- a/drivers/s390/net/qeth_main.c
+++ b/drivers/s390/net/qeth_main.c
@@ -1,6 +1,6 @@
/*
*
- * linux/drivers/s390/net/qeth_main.c ($Revision: 1.191 $)
+ * linux/drivers/s390/net/qeth_main.c ($Revision: 1.206 $)
*
* Linux on zSeries OSA Express and HiperSockets support
*
@@ -12,7 +12,7 @@
* Frank Pavlic (pavlic@de.ibm.com) and
* Thomas Spatzier <tspat@de.ibm.com>
*
- * $Revision: 1.191 $ $Date: 2005/01/31 13:13:57 $
+ * $Revision: 1.206 $ $Date: 2005/03/24 09:04:18 $
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -61,6 +61,7 @@ qeth_eyecatcher(void)
#include <linux/reboot.h>
#include <linux/mii.h>
#include <linux/rcupdate.h>
+#include <linux/ethtool.h>
#include <net/arp.h>
#include <net/ip.h>
@@ -76,8 +77,10 @@ qeth_eyecatcher(void)
#include "qeth.h"
#include "qeth_mpc.h"
#include "qeth_fs.h"
+#include "qeth_eddp.h"
+#include "qeth_tso.h"
-#define VERSION_QETH_C "$Revision: 1.191 $"
+#define VERSION_QETH_C "$Revision: 1.206 $"
static const char *version = "qeth S/390 OSA-Express driver";
/**
@@ -87,7 +90,7 @@ static debug_info_t *qeth_dbf_setup = NULL;
static debug_info_t *qeth_dbf_data = NULL;
static debug_info_t *qeth_dbf_misc = NULL;
static debug_info_t *qeth_dbf_control = NULL;
-static debug_info_t *qeth_dbf_trace = NULL;
+debug_info_t *qeth_dbf_trace = NULL;
static debug_info_t *qeth_dbf_sense = NULL;
static debug_info_t *qeth_dbf_qerr = NULL;
@@ -1071,6 +1074,35 @@ qeth_setup_card(struct qeth_card *card)
}
static int
+is_1920_device (struct qeth_card *card)
+{
+ int single_queue = 0;
+ struct ccw_device *ccwdev;
+ struct channelPath_dsc {
+ u8 flags;
+ u8 lsn;
+ u8 desc;
+ u8 chpid;
+ u8 swla;
+ u8 zeroes;
+ u8 chla;
+ u8 chpp;
+ } *chp_dsc;
+
+ QETH_DBF_TEXT(setup, 2, "chk_1920");
+
+ ccwdev = card->data.ccwdev;
+ chp_dsc = (struct channelPath_dsc *)ccw_device_get_chp_desc(ccwdev, 0);
+ if (chp_dsc != NULL) {
+ /* CHPP field bit 6 == 1 -> single queue */
+ single_queue = ((chp_dsc->chpp & 0x02) == 0x02);
+ kfree(chp_dsc);
+ }
+ QETH_DBF_TEXT_(setup, 2, "rc:%x", single_queue);
+ return single_queue;
+}
+
+static int
qeth_determine_card_type(struct qeth_card *card)
{
int i = 0;
@@ -1081,7 +1113,14 @@ qeth_determine_card_type(struct qeth_card *card)
if ((CARD_RDEV(card)->id.dev_type == known_devices[i][2]) &&
(CARD_RDEV(card)->id.dev_model == known_devices[i][3])) {
card->info.type = known_devices[i][4];
- card->qdio.no_out_queues = known_devices[i][8];
+ if (is_1920_device(card)) {
+ PRINT_INFO("Priority Queueing not able "
+ "due to hardware limitations!\n");
+ card->qdio.no_out_queues = 1;
+ card->qdio.default_out_queue = 0;
+ } else {
+ card->qdio.no_out_queues = known_devices[i][8];
+ }
card->info.is_multicast_different = known_devices[i][9];
return 0;
}
@@ -1112,6 +1151,10 @@ qeth_probe_device(struct ccwgroup_device *gdev)
QETH_DBF_TEXT_(setup, 2, "1err%d", -ENOMEM);
return -ENOMEM;
}
+ card->read.ccwdev = gdev->cdev[0];
+ card->write.ccwdev = gdev->cdev[1];
+ card->data.ccwdev = gdev->cdev[2];
+
if ((rc = qeth_setup_card(card))){
QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
put_device(dev);
@@ -1130,9 +1173,6 @@ qeth_probe_device(struct ccwgroup_device *gdev)
qeth_free_card(card);
return rc;
}
- card->read.ccwdev = gdev->cdev[0];
- card->write.ccwdev = gdev->cdev[1];
- card->data.ccwdev = gdev->cdev[2];
if ((rc = qeth_determine_card_type(card))){
PRINT_WARN("%s: not a valid card type\n", __func__);
QETH_DBF_TEXT_(setup, 2, "3err%d", rc);
@@ -1631,10 +1671,7 @@ qeth_check_ipa_data(struct qeth_card *card, struct qeth_cmd_buffer *iob)
QETH_DBF_TEXT(trace,3, "irla");
break;
case IPA_CMD_UNREGISTER_LOCAL_ADDR:
- PRINT_WARN("probably problem on %s: "
- "received IPA command 0x%X\n",
- QETH_CARD_IFNAME(card),
- cmd->hdr.command);
+ QETH_DBF_TEXT(trace,3, "urla");
break;
default:
PRINT_WARN("Received data is IPA "
@@ -1714,7 +1751,7 @@ qeth_send_control_data_cb(struct qeth_channel *channel,
(unsigned long)iob);
}
if (cmd)
- reply->rc = (s16) cmd->hdr.return_code;
+ reply->rc = (u16) cmd->hdr.return_code;
else if (iob->rc)
reply->rc = iob->rc;
if (keep_reply) {
@@ -2263,19 +2300,25 @@ qeth_layer2_rebuild_skb(struct qeth_card *card, struct sk_buff *skb,
struct qeth_hdr *hdr)
{
unsigned short vlan_id = 0;
+#ifdef CONFIG_QETH_VLAN
+ struct vlan_hdr *vhdr;
+#endif
skb->pkt_type = PACKET_HOST;
+ skb->protocol = qeth_type_trans(skb, skb->dev);
if (card->options.checksum_type == NO_CHECKSUMMING)
skb->ip_summed = CHECKSUM_UNNECESSARY;
else
skb->ip_summed = CHECKSUM_NONE;
#ifdef CONFIG_QETH_VLAN
if (hdr->hdr.l2.flags[2] & (QETH_LAYER2_FLAG_VLAN)) {
+ vhdr = (struct vlan_hdr *) skb->data;
+ skb->protocol =
+ __constant_htons(vhdr->h_vlan_encapsulated_proto);
vlan_id = hdr->hdr.l2.vlan_id;
skb_pull(skb, VLAN_HLEN);
}
#endif
- skb->protocol = qeth_type_trans(skb, skb->dev);
return vlan_id;
}
@@ -2421,14 +2464,15 @@ qeth_clear_output_buffer(struct qeth_qdio_out_q *queue,
if (buf->buffer->element[0].flags & 0x40)
atomic_dec(&queue->set_pci_flags_count);
+ while ((skb = skb_dequeue(&buf->skb_list))){
+ atomic_dec(&skb->users);
+ dev_kfree_skb_any(skb);
+ }
+ qeth_eddp_buf_release_contexts(buf);
for(i = 0; i < QETH_MAX_BUFFER_ELEMENTS(queue->card); ++i){
buf->buffer->element[i].length = 0;
buf->buffer->element[i].addr = NULL;
buf->buffer->element[i].flags = 0;
- while ((skb = skb_dequeue(&buf->skb_list))){
- atomic_dec(&skb->users);
- dev_kfree_skb_any(skb);
- }
}
buf->next_element_to_fill = 0;
atomic_set(&buf->state, QETH_QDIO_BUF_EMPTY);
@@ -2578,7 +2622,7 @@ qeth_handle_send_error(struct qeth_card *card,
return QETH_SEND_ERROR_LINK_FAILURE;
}
-static inline void
+void
qeth_flush_buffers(struct qeth_qdio_out_q *queue, int under_int,
int index, int count)
{
@@ -2619,9 +2663,6 @@ qeth_flush_buffers(struct qeth_qdio_out_q *queue, int under_int,
atomic_inc(&queue->set_pci_flags_count);
buf->buffer->element[0].flags |= 0x40;
}
-#ifdef CONFIG_QETH_PERF_STATS
- queue->card->perf_stats.bufs_sent_pack++;
-#endif
}
}
@@ -2743,6 +2784,7 @@ qeth_check_outbound_queue(struct qeth_qdio_out_q *queue)
{
int index;
int flush_cnt = 0;
+ int q_was_packing = 0;
/*
* check if weed have to switch to non-packing mode or if
@@ -2757,20 +2799,22 @@ qeth_check_outbound_queue(struct qeth_qdio_out_q *queue)
* do_send_packet. So, we check if there is a
* packing buffer to be flushed here.
*/
- /* TODO: try if we get a performance improvement
- * by calling netif_stop_queue here */
- /* save start index for flushing */
+ netif_stop_queue(queue->card->dev);
index = queue->next_buf_to_fill;
+ q_was_packing = queue->do_pack;
flush_cnt += qeth_switch_to_nonpacking_if_needed(queue);
if (!flush_cnt &&
!atomic_read(&queue->set_pci_flags_count))
flush_cnt +=
qeth_flush_buffers_on_no_pci(queue);
- /* were done with updating critical queue members */
- atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED);
- /* flushing can be done outside the lock */
+#ifdef CONFIG_QETH_PERF_STATS
+ if (q_was_packing)
+ queue->card->perf_stats.bufs_sent_pack +=
+ flush_cnt;
+#endif
if (flush_cnt)
qeth_flush_buffers(queue, 1, index, flush_cnt);
+ atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED);
}
}
}
@@ -2800,7 +2844,6 @@ qeth_qdio_output_handler(struct ccw_device * ccwdev, unsigned int status,
return;
}
}
-
#ifdef CONFIG_QETH_PERF_STATS
card->perf_stats.outbound_handler_cnt++;
card->perf_stats.outbound_handler_start_time = qeth_get_micros();
@@ -2821,24 +2864,16 @@ qeth_qdio_output_handler(struct ccw_device * ccwdev, unsigned int status,
if (card->info.type != QETH_CARD_TYPE_IQD)
qeth_check_outbound_queue(queue);
- netif_wake_queue(card->dev);
+ netif_wake_queue(queue->card->dev);
#ifdef CONFIG_QETH_PERF_STATS
card->perf_stats.outbound_handler_time += qeth_get_micros() -
card->perf_stats.outbound_handler_start_time;
#endif
}
-static char*
-qeth_create_qib_param_field(struct qeth_card *card)
+static void
+qeth_create_qib_param_field(struct qeth_card *card, char *param_field)
{
- char *param_field;
-
- param_field = kmalloc(QDIO_MAX_BUFFERS_PER_Q * sizeof(char),
- GFP_KERNEL);
- if (!param_field)
- return NULL;
-
- memset(param_field, 0, QDIO_MAX_BUFFERS_PER_Q * sizeof(char));
param_field[0] = _ascebc['P'];
param_field[1] = _ascebc['C'];
@@ -2847,8 +2882,18 @@ qeth_create_qib_param_field(struct qeth_card *card)
*((unsigned int *) (&param_field[4])) = QETH_PCI_THRESHOLD_A(card);
*((unsigned int *) (&param_field[8])) = QETH_PCI_THRESHOLD_B(card);
*((unsigned int *) (&param_field[12])) = QETH_PCI_TIMER_VALUE(card);
+}
- return param_field;
+static void
+qeth_create_qib_param_field_blkt(struct qeth_card *card, char *param_field)
+{
+ param_field[16] = _ascebc['B'];
+ param_field[17] = _ascebc['L'];
+ param_field[18] = _ascebc['K'];
+ param_field[19] = _ascebc['T'];
+ *((unsigned int *) (&param_field[20])) = card->info.blkt.time_total;
+ *((unsigned int *) (&param_field[24])) = card->info.blkt.inter_packet;
+ *((unsigned int *) (&param_field[28])) = card->info.blkt.inter_packet_jumbo;
}
static void
@@ -2898,7 +2943,7 @@ qeth_alloc_buffer_pool(struct qeth_card *card)
void *ptr;
int i, j;
- QETH_DBF_TEXT(trace,5,"clwkpool");
+ QETH_DBF_TEXT(trace,5,"alocpool");
for (i = 0; i < card->qdio.init_pool.buf_count; ++i){
pool_entry = kmalloc(sizeof(*pool_entry), GFP_KERNEL);
if (!pool_entry){
@@ -2986,12 +3031,13 @@ qeth_alloc_qdio_buffers(struct qeth_card *card)
QETH_DBF_HEX(setup, 2, &card->qdio.out_qs[i], sizeof(void *));
memset(card->qdio.out_qs[i], 0, sizeof(struct qeth_qdio_out_q));
card->qdio.out_qs[i]->queue_no = i;
- /* give inbound qeth_qdio_buffers their qdio_buffers */
+ /* give outbound qeth_qdio_buffers their qdio_buffers */
for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j){
card->qdio.out_qs[i]->bufs[j].buffer =
&card->qdio.out_qs[i]->qdio_bufs[j];
skb_queue_head_init(&card->qdio.out_qs[i]->bufs[j].
skb_list);
+ INIT_LIST_HEAD(&card->qdio.out_qs[i]->bufs[j].ctx_list);
}
}
card->qdio.state = QETH_QDIO_ALLOCATED;
@@ -3108,10 +3154,17 @@ qeth_qdio_establish(struct qeth_card *card)
int rc;
QETH_DBF_TEXT(setup, 2, "qdioest");
- qib_param_field = qeth_create_qib_param_field(card);
- if (!qib_param_field)
+
+ qib_param_field = kmalloc(QDIO_MAX_BUFFERS_PER_Q * sizeof(char),
+ GFP_KERNEL);
+ if (!qib_param_field)
return -ENOMEM;
+ memset(qib_param_field, 0, QDIO_MAX_BUFFERS_PER_Q * sizeof(char));
+
+ qeth_create_qib_param_field(card, qib_param_field);
+ qeth_create_qib_param_field_blkt(card, qib_param_field);
+
in_sbal_ptrs = kmalloc(QDIO_MAX_BUFFERS_PER_Q * sizeof(void *),
GFP_KERNEL);
if (!in_sbal_ptrs) {
@@ -3388,11 +3441,9 @@ qeth_fake_header(struct sk_buff *skb, struct net_device *dev,
unsigned len)
{
struct ethhdr *hdr;
- struct qeth_card *card;
- card = (struct qeth_card *)dev->priv;
hdr = (struct ethhdr *)skb_push(skb, QETH_FAKE_LL_LEN);
- memcpy(hdr->h_source, card->dev->dev_addr, ETH_ALEN);
+ memcpy(hdr->h_source, dev->dev_addr, ETH_ALEN);
memcpy(hdr->h_dest, "FAKELL", ETH_ALEN);
if (type != ETH_P_802_3)
hdr->h_proto = htons(type);
@@ -3430,32 +3481,19 @@ qeth_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
card->perf_stats.outbound_cnt++;
card->perf_stats.outbound_start_time = qeth_get_micros();
#endif
- if (dev->hard_header == qeth_fake_header) {
- if ((skb = qeth_pskb_unshare(skb, GFP_ATOMIC)) == NULL) {
- card->stats.tx_dropped++;
- dev_kfree_skb_irq(skb);
- return 0;
- }
- skb_pull(skb, QETH_FAKE_LL_LEN);
- }
- /*
- * We only call netif_stop_queue in case of errors. Since we've
- * got our own synchronization on queues we can keep the stack's
- * queue running.
- */
- if ((rc = qeth_send_packet(card, skb))){
+ netif_stop_queue(dev);
+ if ((rc = qeth_send_packet(card, skb))) {
if (rc == -EBUSY) {
- netif_stop_queue(dev);
- rc = NETDEV_TX_BUSY;
+ return NETDEV_TX_BUSY;
} else {
card->stats.tx_errors++;
card->stats.tx_dropped++;
dev_kfree_skb_any(skb);
- /* set to OK; otherwise ksoftirqd goes to 100% */
+ /*set to OK; otherwise ksoftirqd goes to 100% */
rc = NETDEV_TX_OK;
}
}
-
+ netif_wake_queue(dev);
#ifdef CONFIG_QETH_PERF_STATS
card->perf_stats.outbound_time += qeth_get_micros() -
card->perf_stats.outbound_start_time;
@@ -3649,8 +3687,9 @@ qeth_get_priority_queue(struct qeth_card *card, struct sk_buff *skb,
/* TODO: IPv6!!! */
}
return card->qdio.default_out_queue;
+ case 1: /* fallthrough for single-out-queue 1920-device */
default:
- return 0;
+ return card->qdio.default_out_queue;
}
}
@@ -3671,22 +3710,16 @@ static inline int
qeth_prepare_skb(struct qeth_card *card, struct sk_buff **skb,
struct qeth_hdr **hdr, int ipv)
{
- struct sk_buff *new_skb;
+ int rc = 0;
#ifdef CONFIG_QETH_VLAN
u16 *tag;
#endif
QETH_DBF_TEXT(trace, 6, "prepskb");
- if (skb_headroom(*skb) < sizeof(struct qeth_hdr)){
- new_skb = skb_realloc_headroom(*skb, sizeof(struct qeth_hdr));
- if (!new_skb) {
- PRINT_ERR("qeth_prepare_skb: could "
- "not realloc headroom for qeth_hdr "
- "on interface %s", QETH_CARD_IFNAME(card));
- return -ENOMEM;
- }
- *skb = new_skb;
- }
+
+ rc = qeth_realloc_headroom(card, skb, sizeof(struct qeth_hdr));
+ if (rc)
+ return rc;
#ifdef CONFIG_QETH_VLAN
if (card->vlangrp && vlan_tx_tag_present(*skb) &&
((ipv == 6) || card->options.layer2) ) {
@@ -3708,20 +3741,10 @@ qeth_prepare_skb(struct qeth_card *card, struct sk_buff **skb,
*(tag + 1) = htons(vlan_tx_tag_get(*skb));
}
#endif
- *hdr = (struct qeth_hdr *) skb_push(*skb, sizeof(struct qeth_hdr));
- /*
- * sanity check, the Linux memory allocation scheme should
- * never present us cases like this one (the 32bytes header plus
- * the first 40 bytes of the paket cross a 4k boundary)
- */
- if ((((unsigned long) *hdr) & (~(PAGE_SIZE - 1))) !=
- (((unsigned long) *hdr + sizeof(struct qeth_hdr) +
- QETH_IP_HEADER_SIZE) & (~(PAGE_SIZE - 1)))) {
- PRINT_ERR("qeth_prepare_skb: misaligned "
- "packet on interface %s. Discarded.",
- QETH_CARD_IFNAME(card));
+ *hdr = (struct qeth_hdr *)
+ qeth_push_skb(card, skb, sizeof(struct qeth_hdr));
+ if (hdr == NULL)
return -EINVAL;
- }
return 0;
}
@@ -3813,12 +3836,13 @@ qeth_layer2_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
#endif
}
-static inline void
+void
qeth_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
struct sk_buff *skb, int ipv, int cast_type)
{
QETH_DBF_TEXT(trace, 6, "fillhdr");
+ memset(hdr, 0, sizeof(struct qeth_hdr));
if (card->options.layer2) {
qeth_layer2_fill_header(card, hdr, skb, cast_type);
return;
@@ -3869,21 +3893,59 @@ qeth_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
}
}
-static inline int
-qeth_fill_buffer(struct qeth_qdio_out_q *queue, struct qeth_qdio_out_buffer *buf,
- char *data, struct sk_buff *skb)
+static inline void
+__qeth_fill_buffer_frag(struct sk_buff *skb, struct qdio_buffer *buffer,
+ int *next_element_to_fill)
+{
+ int length = skb->len;
+ struct skb_frag_struct *frag;
+ int fragno;
+ unsigned long addr;
+ int element;
+ int first_lap = 1;
+
+ fragno = skb_shinfo(skb)->nr_frags; /* start with last frag */
+ element = *next_element_to_fill + fragno;
+ while (length > 0) {
+ if (fragno > 0) {
+ frag = &skb_shinfo(skb)->frags[fragno - 1];
+ addr = (page_to_pfn(frag->page) << PAGE_SHIFT) +
+ frag->page_offset;
+ buffer->element[element].addr = (char *)addr;
+ buffer->element[element].length = frag->size;
+ length -= frag->size;
+ if (first_lap)
+ buffer->element[element].flags =
+ SBAL_FLAGS_LAST_FRAG;
+ else
+ buffer->element[element].flags =
+ SBAL_FLAGS_MIDDLE_FRAG;
+ } else {
+ buffer->element[element].addr = skb->data;
+ buffer->element[element].length = length;
+ length = 0;
+ buffer->element[element].flags =
+ SBAL_FLAGS_FIRST_FRAG;
+ }
+ element--;
+ fragno--;
+ first_lap = 0;
+ }
+ *next_element_to_fill += skb_shinfo(skb)->nr_frags + 1;
+}
+
+static inline void
+__qeth_fill_buffer(struct sk_buff *skb, struct qdio_buffer *buffer,
+ int *next_element_to_fill)
{
- struct qdio_buffer *buffer;
int length = skb->len;
int length_here;
int element;
+ char *data;
int first_lap = 1;
- QETH_DBF_TEXT(trace, 6, "qdfillbf");
- buffer = buf->buffer;
- atomic_inc(&skb->users);
- skb_queue_tail(&buf->skb_list, skb);
- element = buf->next_element_to_fill;
+ element = *next_element_to_fill;
+ data = skb->data;
while (length > 0) {
/* length_here is the remaining amount of data in this page */
length_here = PAGE_SIZE - ((unsigned long) data % PAGE_SIZE);
@@ -3910,11 +3972,33 @@ qeth_fill_buffer(struct qeth_qdio_out_q *queue, struct qeth_qdio_out_buffer *buf
element++;
first_lap = 0;
}
- buf->next_element_to_fill = element;
+ *next_element_to_fill = element;
+}
+
+static inline int
+qeth_fill_buffer(struct qeth_qdio_out_q *queue,
+ struct qeth_qdio_out_buffer *buf,
+ struct sk_buff *skb)
+{
+ struct qdio_buffer *buffer;
+ int flush_cnt = 0;
+
+ QETH_DBF_TEXT(trace, 6, "qdfillbf");
+ buffer = buf->buffer;
+ atomic_inc(&skb->users);
+ skb_queue_tail(&buf->skb_list, skb);
+ if (skb_shinfo(skb)->nr_frags == 0)
+ __qeth_fill_buffer(skb, buffer,
+ (int *)&buf->next_element_to_fill);
+ else
+ __qeth_fill_buffer_frag(skb, buffer,
+ (int *)&buf->next_element_to_fill);
+
if (!queue->do_pack) {
QETH_DBF_TEXT(trace, 6, "fillbfnp");
/* set state to PRIMED -> will be flushed */
atomic_set(&buf->state, QETH_QDIO_BUF_PRIMED);
+ flush_cnt = 1;
} else {
QETH_DBF_TEXT(trace, 6, "fillbfpa");
#ifdef CONFIG_QETH_PERF_STATS
@@ -3927,17 +4011,21 @@ qeth_fill_buffer(struct qeth_qdio_out_q *queue, struct qeth_qdio_out_buffer *buf
* -> will be flushed
*/
atomic_set(&buf->state, QETH_QDIO_BUF_PRIMED);
+ flush_cnt = 1;
}
}
- return 0;
+ return flush_cnt;
}
static inline int
qeth_do_send_packet_fast(struct qeth_card *card, struct qeth_qdio_out_q *queue,
struct sk_buff *skb, struct qeth_hdr *hdr,
- int elements_needed)
+ int elements_needed,
+ struct qeth_eddp_context *ctx)
{
struct qeth_qdio_out_buffer *buffer;
+ int buffers_needed = 0;
+ int flush_cnt = 0;
int index;
QETH_DBF_TEXT(trace, 6, "dosndpfa");
@@ -3958,22 +4046,42 @@ qeth_do_send_packet_fast(struct qeth_card *card, struct qeth_qdio_out_q *queue,
atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED);
return -EBUSY;
}
- queue->next_buf_to_fill = (queue->next_buf_to_fill + 1) %
- QDIO_MAX_BUFFERS_PER_Q;
+ if (ctx == NULL)
+ queue->next_buf_to_fill = (queue->next_buf_to_fill + 1) %
+ QDIO_MAX_BUFFERS_PER_Q;
+ else {
+ buffers_needed = qeth_eddp_check_buffers_for_context(queue,ctx);
+ if (buffers_needed < 0) {
+ card->stats.tx_dropped++;
+ atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED);
+ return -EBUSY;
+ }
+ queue->next_buf_to_fill =
+ (queue->next_buf_to_fill + buffers_needed) %
+ QDIO_MAX_BUFFERS_PER_Q;
+ }
atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED);
- qeth_fill_buffer(queue, buffer, (char *)hdr, skb);
- qeth_flush_buffers(queue, 0, index, 1);
+ if (ctx == NULL) {
+ qeth_fill_buffer(queue, buffer, skb);
+ qeth_flush_buffers(queue, 0, index, 1);
+ } else {
+ flush_cnt = qeth_eddp_fill_buffer(queue, ctx, index);
+ WARN_ON(buffers_needed != flush_cnt);
+ qeth_flush_buffers(queue, 0, index, flush_cnt);
+ }
return 0;
}
static inline int
qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue,
struct sk_buff *skb, struct qeth_hdr *hdr,
- int elements_needed)
+ int elements_needed, struct qeth_eddp_context *ctx)
{
struct qeth_qdio_out_buffer *buffer;
int start_index;
int flush_count = 0;
+ int do_pack = 0;
+ int tmp;
int rc = 0;
QETH_DBF_TEXT(trace, 6, "dosndpkt");
@@ -3996,34 +4104,56 @@ qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue,
/* check if we need to switch packing state of this queue */
qeth_switch_to_packing_if_needed(queue);
if (queue->do_pack){
- /* does packet fit in current buffer? */
- if((QETH_MAX_BUFFER_ELEMENTS(card) -
- buffer->next_element_to_fill) < elements_needed){
- /* ... no -> set state PRIMED */
- atomic_set(&buffer->state, QETH_QDIO_BUF_PRIMED);
- flush_count++;
- queue->next_buf_to_fill =
- (queue->next_buf_to_fill + 1) %
- QDIO_MAX_BUFFERS_PER_Q;
- buffer = &queue->bufs[queue->next_buf_to_fill];
- /* we did a step forward, so check buffer state again */
- if (atomic_read(&buffer->state) != QETH_QDIO_BUF_EMPTY){
+ do_pack = 1;
+ if (ctx == NULL) {
+ /* does packet fit in current buffer? */
+ if((QETH_MAX_BUFFER_ELEMENTS(card) -
+ buffer->next_element_to_fill) < elements_needed){
+ /* ... no -> set state PRIMED */
+ atomic_set(&buffer->state,QETH_QDIO_BUF_PRIMED);
+ flush_count++;
+ queue->next_buf_to_fill =
+ (queue->next_buf_to_fill + 1) %
+ QDIO_MAX_BUFFERS_PER_Q;
+ buffer = &queue->bufs[queue->next_buf_to_fill];
+ /* we did a step forward, so check buffer state
+ * again */
+ if (atomic_read(&buffer->state) !=
+ QETH_QDIO_BUF_EMPTY){
+ card->stats.tx_dropped++;
+ qeth_flush_buffers(queue, 0, start_index, flush_count);
+ atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED);
+ return -EBUSY;
+ }
+ }
+ } else {
+ /* check if we have enough elements (including following
+ * free buffers) to handle eddp context */
+ if (qeth_eddp_check_buffers_for_context(queue,ctx) < 0){
+ printk("eddp tx_dropped 1\n");
card->stats.tx_dropped++;
- /* return EBUSY because we sent old packet, not
- * the current one */
rc = -EBUSY;
- atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED);
goto out;
}
}
}
- qeth_fill_buffer(queue, buffer, (char *)hdr, skb);
- if (atomic_read(&buffer->state) == QETH_QDIO_BUF_PRIMED){
- /* next time fill the next buffer */
- flush_count++;
- queue->next_buf_to_fill = (queue->next_buf_to_fill + 1) %
- QDIO_MAX_BUFFERS_PER_Q;
+ if (ctx == NULL)
+ tmp = qeth_fill_buffer(queue, buffer, skb);
+ else {
+ tmp = qeth_eddp_fill_buffer(queue,ctx,queue->next_buf_to_fill);
+ if (tmp < 0) {
+ printk("eddp tx_dropped 2\n");
+ card->stats.tx_dropped++;
+ rc = - EBUSY;
+ goto out;
+ }
}
+ queue->next_buf_to_fill = (queue->next_buf_to_fill + tmp) %
+ QDIO_MAX_BUFFERS_PER_Q;
+ flush_count += tmp;
+out:
+ if (flush_count)
+ qeth_flush_buffers(queue, 0, start_index, flush_count);
/*
* queue->state will go from LOCKED -> UNLOCKED or from
* LOCKED_FLUSH -> LOCKED if output_handler wanted to 'notify' us
@@ -4031,6 +4161,8 @@ qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue,
* In that case we will enter this loop
*/
while (atomic_dec_return(&queue->state)){
+ flush_count = 0;
+ start_index = queue->next_buf_to_fill;
/* check if we can go back to non-packing state */
flush_count += qeth_switch_to_nonpacking_if_needed(queue);
/*
@@ -4039,11 +4171,14 @@ qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue,
*/
if (!flush_count && !atomic_read(&queue->set_pci_flags_count))
flush_count += qeth_flush_buffers_on_no_pci(queue);
+ if (flush_count)
+ qeth_flush_buffers(queue, 0, start_index, flush_count);
}
/* at this point the queue is UNLOCKED again */
-out:
- if (flush_count)
- qeth_flush_buffers(queue, 0, start_index, flush_count);
+#ifdef CONFIG_QETH_PERF_STATS
+ if (do_pack)
+ queue->card->perf_stats.bufs_sent_pack += flush_count;
+#endif /* CONFIG_QETH_PERF_STATS */
return rc;
}
@@ -4055,40 +4190,92 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb)
int cast_type;
struct qeth_qdio_out_q *queue;
struct qeth_hdr *hdr;
- int elements_needed;
+ int elements_needed = 0;
+ enum qeth_large_send_types large_send = QETH_LARGE_SEND_NO;
+ struct qeth_eddp_context *ctx = NULL;
int rc;
QETH_DBF_TEXT(trace, 6, "sendpkt");
- if (!card->options.layer2)
+ if (!card->options.layer2) {
ipv = qeth_get_ip_version(skb);
+ if ((card->dev->hard_header == qeth_fake_header) && ipv) {
+ if ((skb = qeth_pskb_unshare(skb,GFP_ATOMIC)) == NULL) {
+ card->stats.tx_dropped++;
+ dev_kfree_skb_irq(skb);
+ return 0;
+ }
+ skb_pull(skb, QETH_FAKE_LL_LEN);
+ }
+ }
cast_type = qeth_get_cast_type(card, skb);
+ if ((cast_type == RTN_BROADCAST) && (card->info.broadcast_capable == 0)){
+ card->stats.tx_dropped++;
+ card->stats.tx_errors++;
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
+ }
queue = card->qdio.out_qs
[qeth_get_priority_queue(card, skb, ipv, cast_type)];
+ if (skb_shinfo(skb)->tso_size)
+ large_send = card->options.large_send;
+
if ((rc = qeth_prepare_skb(card, &skb, &hdr, ipv))){
- QETH_DBF_TEXT_(trace, 4, "1err%d", rc);
+ QETH_DBF_TEXT_(trace, 4, "pskbe%d", rc);
return rc;
}
+ /*are we able to do TSO ? If so ,prepare and send it from here */
+ if ((large_send == QETH_LARGE_SEND_TSO) &&
+ (cast_type == RTN_UNSPEC)) {
+ rc = qeth_tso_send_packet(card, skb, queue,
+ ipv, cast_type);
+ goto do_statistics;
+ }
+
qeth_fill_header(card, hdr, skb, ipv, cast_type);
- elements_needed = 1 + (((((unsigned long) hdr) % PAGE_SIZE) + skb->len)
- >> PAGE_SHIFT);
- if (elements_needed > QETH_MAX_BUFFER_ELEMENTS(card)){
- PRINT_ERR("qeth_do_send_packet: invalid size of "
- "IP packet. Discarded.");
- return -EINVAL;
+ if (large_send == QETH_LARGE_SEND_EDDP) {
+ ctx = qeth_eddp_create_context(card, skb, hdr);
+ if (ctx == NULL) {
+ PRINT_WARN("could not create eddp context\n");
+ return -EINVAL;
+ }
+ } else {
+ elements_needed = qeth_get_elements_no(card,(void*) hdr, skb);
+ if (!elements_needed)
+ return -EINVAL;
}
if (card->info.type != QETH_CARD_TYPE_IQD)
rc = qeth_do_send_packet(card, queue, skb, hdr,
- elements_needed);
+ elements_needed, ctx);
else
rc = qeth_do_send_packet_fast(card, queue, skb, hdr,
- elements_needed);
-
+ elements_needed, ctx);
+do_statistics:
if (!rc){
card->stats.tx_packets++;
card->stats.tx_bytes += skb->len;
+#ifdef CONFIG_QETH_PERF_STATS
+ if (skb_shinfo(skb)->tso_size) {
+ card->perf_stats.large_send_bytes += skb->len;
+ card->perf_stats.large_send_cnt++;
+ }
+ if (skb_shinfo(skb)->nr_frags > 0){
+ card->perf_stats.sg_skbs_sent++;
+ /* nr_frags + skb->data */
+ card->perf_stats.sg_frags_sent +=
+ skb_shinfo(skb)->nr_frags + 1;
+ }
+#endif /* CONFIG_QETH_PERF_STATS */
+ }
+ if (ctx != NULL) {
+ /* drop creator's reference */
+ qeth_eddp_put_context(ctx);
+ /* free skb; it's not referenced by a buffer */
+ if (rc == 0)
+ dev_kfree_skb_any(skb);
+
}
return rc;
}
@@ -4943,6 +5130,7 @@ out:
static void
qeth_free_vlan_addresses6(struct qeth_card *card, unsigned short vid)
{
+#ifdef CONFIG_QETH_IPV6
struct inet6_dev *in6_dev;
struct inet6_ifaddr *ifa;
struct qeth_ipaddr *addr;
@@ -4965,6 +5153,7 @@ qeth_free_vlan_addresses6(struct qeth_card *card, unsigned short vid)
}
}
in6_dev_put(in6_dev);
+#endif /* CONFIG_QETH_IPV6 */
}
static void
@@ -5242,7 +5431,8 @@ qeth_add_multicast_ipv6(struct qeth_card *card)
struct inet6_dev *in6_dev;
QETH_DBF_TEXT(trace,4,"chkmcv6");
- if (!qeth_is_supported(card, IPA_IPV6))
+ if ((card->options.layer2 == 0) &&
+ (!qeth_is_supported(card, IPA_IPV6)) )
return ;
in6_dev = in6_dev_get(card->dev);
@@ -5563,7 +5753,7 @@ static int
qeth_layer3_register_addr_entry(struct qeth_card *card,
struct qeth_ipaddr *addr)
{
- //char buf[50];
+ char buf[50];
int rc;
int cnt = 3;
@@ -5589,12 +5779,9 @@ qeth_layer3_register_addr_entry(struct qeth_card *card,
} while ((--cnt > 0) && rc);
if (rc){
QETH_DBF_TEXT(trace, 2, "FAILED");
- /* TODO: re-activate this warning as soon as we have a
- * clean mirco code
qeth_ipaddr_to_string(addr->proto, (u8 *)&addr->u, buf);
- PRINT_WARN("Could not register IP address %s (rc=%x)\n",
- buf, rc);
- */
+ PRINT_WARN("Could not register IP address %s (rc=0x%x/%d)\n",
+ buf, rc, rc);
}
return rc;
}
@@ -5652,6 +5839,111 @@ qeth_deregister_addr_entry(struct qeth_card *card, struct qeth_ipaddr *addr)
return qeth_layer3_deregister_addr_entry(card, addr);
}
+static u32
+qeth_ethtool_get_tx_csum(struct net_device *dev)
+{
+ /* We may need to say that we support tx csum offload if
+ * we do EDDP or TSO. There are discussions going on to
+ * enforce rules in the stack and in ethtool that make
+ * SG and TSO depend on HW_CSUM. At the moment there are
+ * no such rules....
+ * If we say yes here, we have to checksum outbound packets
+ * any time. */
+ return 0;
+}
+
+static int
+qeth_ethtool_set_tx_csum(struct net_device *dev, u32 data)
+{
+ return -EINVAL;
+}
+
+static u32
+qeth_ethtool_get_rx_csum(struct net_device *dev)
+{
+ struct qeth_card *card = (struct qeth_card *)dev->priv;
+
+ return (card->options.checksum_type == HW_CHECKSUMMING);
+}
+
+static int
+qeth_ethtool_set_rx_csum(struct net_device *dev, u32 data)
+{
+ struct qeth_card *card = (struct qeth_card *)dev->priv;
+
+ if ((card->state != CARD_STATE_DOWN) &&
+ (card->state != CARD_STATE_RECOVER))
+ return -EPERM;
+ if (data)
+ card->options.checksum_type = HW_CHECKSUMMING;
+ else
+ card->options.checksum_type = SW_CHECKSUMMING;
+ return 0;
+}
+
+static u32
+qeth_ethtool_get_sg(struct net_device *dev)
+{
+ struct qeth_card *card = (struct qeth_card *)dev->priv;
+
+ return ((card->options.large_send != QETH_LARGE_SEND_NO) &&
+ (dev->features & NETIF_F_SG));
+}
+
+static int
+qeth_ethtool_set_sg(struct net_device *dev, u32 data)
+{
+ struct qeth_card *card = (struct qeth_card *)dev->priv;
+
+ if (data) {
+ if (card->options.large_send != QETH_LARGE_SEND_NO)
+ dev->features |= NETIF_F_SG;
+ else {
+ dev->features &= ~NETIF_F_SG;
+ return -EINVAL;
+ }
+ } else
+ dev->features &= ~NETIF_F_SG;
+ return 0;
+}
+
+static u32
+qeth_ethtool_get_tso(struct net_device *dev)
+{
+ struct qeth_card *card = (struct qeth_card *)dev->priv;
+
+ return ((card->options.large_send != QETH_LARGE_SEND_NO) &&
+ (dev->features & NETIF_F_TSO));
+}
+
+static int
+qeth_ethtool_set_tso(struct net_device *dev, u32 data)
+{
+ struct qeth_card *card = (struct qeth_card *)dev->priv;
+
+ if (data) {
+ if (card->options.large_send != QETH_LARGE_SEND_NO)
+ dev->features |= NETIF_F_TSO;
+ else {
+ dev->features &= ~NETIF_F_TSO;
+ return -EINVAL;
+ }
+ } else
+ dev->features &= ~NETIF_F_TSO;
+ return 0;
+}
+
+static struct ethtool_ops qeth_ethtool_ops = {
+ .get_tx_csum = qeth_ethtool_get_tx_csum,
+ .set_tx_csum = qeth_ethtool_set_tx_csum,
+ .get_rx_csum = qeth_ethtool_get_rx_csum,
+ .set_rx_csum = qeth_ethtool_set_rx_csum,
+ .get_sg = qeth_ethtool_get_sg,
+ .set_sg = qeth_ethtool_set_sg,
+ .get_tso = qeth_ethtool_get_tso,
+ .set_tso = qeth_ethtool_set_tso,
+};
+
static int
qeth_netdev_init(struct net_device *dev)
{
@@ -5701,6 +5993,8 @@ qeth_netdev_init(struct net_device *dev)
dev->addr_len = OSA_ADDR_LEN;
dev->mtu = card->info.initial_mtu;
+ SET_ETHTOOL_OPS(dev, &qeth_ethtool_ops);
+
SET_MODULE_OWNER(dev);
return 0;
}
@@ -6092,6 +6386,9 @@ qeth_query_ipassists_cb(struct qeth_card *card, struct qeth_reply *reply,
card->options.ipa6.enabled_funcs = cmd->hdr.ipa_enabled;
#endif
}
+ QETH_DBF_TEXT(setup, 2, "suppenbl");
+ QETH_DBF_TEXT_(setup, 2, "%x",cmd->hdr.ipa_supported);
+ QETH_DBF_TEXT_(setup, 2, "%x",cmd->hdr.ipa_enabled);
return 0;
}
@@ -6492,26 +6789,33 @@ qeth_start_ipa_checksum(struct qeth_card *card)
return rc;
}
-/*
-static inline void
-qeth_print_ipassist_status(struct qeth_card *card)
+static int
+qeth_start_ipa_tso(struct qeth_card *card)
{
- char buf[255];
- int offset = 0;
+ int rc;
- offset += sprintf(buf, "IPAssist options of %s: ", card->info.if_name);
- if (qeth_is_enabled(card, IPA_ARP_PROCESSING))
- offset += sprintf(buf+offset, "ARP ");
- if (qeth_is_enabled(card, IPA_IP_FRAGMENTATION))
- offset += sprintf(buf+offset, "IP_FRAG");
- if (qeth_is_enabled(card, IPA_SOURCE_MAC))
- offset += sprintf(buf+offset, "SRC_MAC");
- if (qeth_is_enabled(card, IPA_FULL_VLAN))
- offset += sprintf(buf+offset, "VLAN");
- if (qeth_is_enabled(card, IPA_VLAN_PRIO))
- offset += sprintf(buf+offset, "VLAN_PRIO");
+ QETH_DBF_TEXT(trace,3,"sttso");
+
+ if (!qeth_is_supported(card, IPA_OUTBOUND_TSO)) {
+ PRINT_WARN("Outbound TSO not supported on %s\n",
+ QETH_CARD_IFNAME(card));
+ rc = -EOPNOTSUPP;
+ } else {
+ rc = qeth_send_simple_setassparms(card, IPA_OUTBOUND_TSO,
+ IPA_CMD_ASS_START,0);
+ if (rc)
+ PRINT_WARN("Could not start outbound TSO "
+ "assist on %s: rc=%i\n",
+ QETH_CARD_IFNAME(card), rc);
+ else
+ PRINT_INFO("Outbound TSO enabled\n");
+ }
+ if (rc && (card->options.large_send == QETH_LARGE_SEND_TSO)){
+ card->options.large_send = QETH_LARGE_SEND_NO;
+ card->dev->features &= ~ (NETIF_F_TSO | NETIF_F_SG);
+ }
+ return rc;
}
-*/
static int
qeth_start_ipassists(struct qeth_card *card)
@@ -6525,6 +6829,7 @@ qeth_start_ipassists(struct qeth_card *card)
qeth_start_ipa_ipv6(card); /* go on*/
qeth_start_ipa_broadcast(card); /* go on*/
qeth_start_ipa_checksum(card); /* go on*/
+ qeth_start_ipa_tso(card); /* go on*/
return 0;
}
@@ -6636,6 +6941,40 @@ qeth_setrouting_v6(struct qeth_card *card)
return rc;
}
+int
+qeth_set_large_send(struct qeth_card *card)
+{
+ int rc = 0;
+
+ if (card->dev == NULL)
+ return 0;
+
+ netif_stop_queue(card->dev);
+ switch (card->options.large_send) {
+ case QETH_LARGE_SEND_EDDP:
+ card->dev->features |= NETIF_F_TSO | NETIF_F_SG;
+ break;
+ case QETH_LARGE_SEND_TSO:
+ if (qeth_is_supported(card, IPA_OUTBOUND_TSO)){
+ card->dev->features |= NETIF_F_TSO | NETIF_F_SG;
+ } else {
+ PRINT_WARN("TSO not supported on %s. "
+ "large_send set to 'no'.\n",
+ card->dev->name);
+ card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG);
+ card->options.large_send = QETH_LARGE_SEND_NO;
+ rc = -EOPNOTSUPP;
+ }
+ break;
+ default: /* includes QETH_LARGE_SEND_NO */
+ card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG);
+ break;
+ }
+
+ netif_wake_queue(card->dev);
+ return rc;
+}
+
/*
* softsetup card: init IPA stuff
*/
@@ -6673,6 +7012,12 @@ qeth_softsetup_card(struct qeth_card *card)
#endif
goto out;
}
+ if ((card->options.large_send == QETH_LARGE_SEND_EDDP) ||
+ (card->options.large_send == QETH_LARGE_SEND_TSO))
+ card->dev->features |= NETIF_F_TSO | NETIF_F_SG;
+ else
+ card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG);
+
if ((rc = qeth_setadapter_parms(card)))
QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
if ((rc = qeth_start_ipassists(card)))
@@ -7117,10 +7462,7 @@ qeth_set_online(struct ccwgroup_device *gdev)
}
/*maybe it was set offline without ifconfig down
* we can also use this state for recovery purposes*/
- if (card->options.layer2)
- qeth_set_allowed_threads(card, QETH_RECOVER_THREAD, 0);
- else
- qeth_set_allowed_threads(card, 0xffffffff, 0);
+ qeth_set_allowed_threads(card, 0xffffffff, 0);
if (recover_flag == CARD_STATE_RECOVER)
qeth_start_again(card);
qeth_notify_processes();
diff --git a/drivers/s390/net/qeth_mpc.h b/drivers/s390/net/qeth_mpc.h
index 052c8406a3fb0..3d916b5c5d09c 100644
--- a/drivers/s390/net/qeth_mpc.h
+++ b/drivers/s390/net/qeth_mpc.h
@@ -14,7 +14,7 @@
#include <asm/qeth.h>
-#define VERSION_QETH_MPC_H "$Revision: 1.38 $"
+#define VERSION_QETH_MPC_H "$Revision: 1.43 $"
extern const char *VERSION_QETH_MPC_C;
@@ -182,6 +182,9 @@ enum qeth_ipa_funcs {
IPA_FULL_VLAN = 0x00004000L,
IPA_SOURCE_MAC = 0x00010000L,
IPA_OSA_MC_ROUTER = 0x00020000L,
+ IPA_QUERY_ARP_ASSIST = 0x00040000L,
+ IPA_INBOUND_TSO = 0x00080000L,
+ IPA_OUTBOUND_TSO = 0x00100000L,
};
/* SETIP/DELIP IPA Command: ***************************************************/
diff --git a/drivers/s390/net/qeth_proc.c b/drivers/s390/net/qeth_proc.c
index 0cd33887bedc7..04719196fd201 100644
--- a/drivers/s390/net/qeth_proc.c
+++ b/drivers/s390/net/qeth_proc.c
@@ -236,6 +236,14 @@ qeth_perf_procfile_seq_show(struct seq_file *s, void *it)
card->perf_stats.skbs_sent_pack,
card->perf_stats.bufs_sent_pack
);
+ seq_printf(s, " Skbs sent in SG mode : %i\n"
+ " Skb fragments sent in SG mode : %i\n\n",
+ card->perf_stats.sg_skbs_sent,
+ card->perf_stats.sg_frags_sent);
+ seq_printf(s, " large_send tx (in Kbytes) : %i\n"
+ " large_send count : %i\n\n",
+ card->perf_stats.large_send_bytes >> 10,
+ card->perf_stats.large_send_cnt);
seq_printf(s, " Packing state changes no pkg.->packing : %i/%i\n"
" Watermarks L/H : %i/%i\n"
" Current buffer usage (outbound q's) : "
@@ -262,7 +270,7 @@ qeth_perf_procfile_seq_show(struct seq_file *s, void *it)
" Outbound time (in us, incl QDIO) : %i\n"
" Outbound count : %i\n"
" Outbound do_QDIO time (in us) : %i\n"
- " Outbound do_QDIO count : %i\n",
+ " Outbound do_QDIO count : %i\n\n",
card->perf_stats.inbound_time,
card->perf_stats.inbound_cnt,
card->perf_stats.inbound_do_qdio_time,
@@ -274,7 +282,6 @@ qeth_perf_procfile_seq_show(struct seq_file *s, void *it)
card->perf_stats.outbound_do_qdio_time,
card->perf_stats.outbound_do_qdio_cnt
);
-
return 0;
}
diff --git a/drivers/s390/net/qeth_sys.c b/drivers/s390/net/qeth_sys.c
index fe8b0e24e4465..2403483982111 100644
--- a/drivers/s390/net/qeth_sys.c
+++ b/drivers/s390/net/qeth_sys.c
@@ -1,6 +1,6 @@
/*
*
- * linux/drivers/s390/net/qeth_sys.c ($Revision: 1.49 $)
+ * linux/drivers/s390/net/qeth_sys.c ($Revision: 1.51 $)
*
* Linux on zSeries OSA Express and HiperSockets support
* This file contains code related to sysfs.
@@ -20,7 +20,7 @@
#include "qeth_mpc.h"
#include "qeth_fs.h"
-const char *VERSION_QETH_SYS_C = "$Revision: 1.49 $";
+const char *VERSION_QETH_SYS_C = "$Revision: 1.51 $";
/*****************************************************************************/
/* */
@@ -249,6 +249,16 @@ qeth_dev_prioqing_store(struct device *dev, const char *buf, size_t count)
(card->state != CARD_STATE_RECOVER))
return -EPERM;
+ /* check if 1920 devices are supported ,
+ * if though we have to permit priority queueing
+ */
+ if (card->qdio.no_out_queues == 1) {
+ PRINT_WARN("Priority queueing disabled due "
+ "to hardware limitations!\n");
+ card->qdio.do_prio_queueing = QETH_PRIOQ_DEFAULT;
+ return -EPERM;
+ }
+
tmp = strsep((char **) &buf, "\n");
if (!strcmp(tmp, "prio_queueing_prec"))
card->qdio.do_prio_queueing = QETH_PRIO_Q_ING_PREC;
@@ -731,6 +741,174 @@ qeth_dev_layer2_store(struct device *dev, const char *buf, size_t count)
static DEVICE_ATTR(layer2, 0644, qeth_dev_layer2_show,
qeth_dev_layer2_store);
+static ssize_t
+qeth_dev_large_send_show(struct device *dev, char *buf)
+{
+ struct qeth_card *card = dev->driver_data;
+
+ if (!card)
+ return -EINVAL;
+
+ switch (card->options.large_send) {
+ case QETH_LARGE_SEND_NO:
+ return sprintf(buf, "%s\n", "no");
+ case QETH_LARGE_SEND_EDDP:
+ return sprintf(buf, "%s\n", "EDDP");
+ case QETH_LARGE_SEND_TSO:
+ return sprintf(buf, "%s\n", "TSO");
+ default:
+ return sprintf(buf, "%s\n", "N/A");
+ }
+}
+
+static ssize_t
+qeth_dev_large_send_store(struct device *dev, const char *buf, size_t count)
+{
+ struct qeth_card *card = dev->driver_data;
+ enum qeth_large_send_types type;
+ int rc = 0;
+ char *tmp;
+
+ if (!card)
+ return -EINVAL;
+
+ tmp = strsep((char **) &buf, "\n");
+
+ if (!strcmp(tmp, "no")){
+ type = QETH_LARGE_SEND_NO;
+ } else if (!strcmp(tmp, "EDDP")) {
+ type = QETH_LARGE_SEND_EDDP;
+ } else if (!strcmp(tmp, "TSO")) {
+ type = QETH_LARGE_SEND_TSO;
+ } else {
+ PRINT_WARN("large_send: invalid mode %s!\n", tmp);
+ return -EINVAL;
+ }
+ if (card->options.large_send == type)
+ return count;
+ card->options.large_send = type;
+ if ((rc = qeth_set_large_send(card)))
+ return rc;
+
+ return count;
+}
+
+static DEVICE_ATTR(large_send, 0644, qeth_dev_large_send_show,
+ qeth_dev_large_send_store);
+
+static ssize_t
+qeth_dev_blkt_show(char *buf, struct qeth_card *card, int value )
+{
+
+ if (!card)
+ return -EINVAL;
+
+ return sprintf(buf, "%i\n", value);
+}
+
+static ssize_t
+qeth_dev_blkt_store(struct qeth_card *card, const char *buf, size_t count,
+ int *value, int max_value)
+{
+ char *tmp;
+ int i;
+
+ if (!card)
+ return -EINVAL;
+
+ if ((card->state != CARD_STATE_DOWN) &&
+ (card->state != CARD_STATE_RECOVER))
+ return -EPERM;
+
+ i = simple_strtoul(buf, &tmp, 10);
+ if (i <= max_value) {
+ *value = i;
+ } else {
+ PRINT_WARN("blkt total time: write values between"
+ " 0 and %d to this file!\n", max_value);
+ return -EINVAL;
+ }
+ return count;
+}
+
+static ssize_t
+qeth_dev_blkt_total_show(struct device *dev, char *buf)
+{
+ struct qeth_card *card = dev->driver_data;
+
+ return qeth_dev_blkt_show(buf, card, card->info.blkt.time_total);
+}
+
+
+static ssize_t
+qeth_dev_blkt_total_store(struct device *dev, const char *buf, size_t count)
+{
+ struct qeth_card *card = dev->driver_data;
+
+ return qeth_dev_blkt_store(card, buf, count,
+ &card->info.blkt.time_total,1000);
+}
+
+
+
+static DEVICE_ATTR(total, 0644, qeth_dev_blkt_total_show,
+ qeth_dev_blkt_total_store);
+
+static ssize_t
+qeth_dev_blkt_inter_show(struct device *dev, char *buf)
+{
+ struct qeth_card *card = dev->driver_data;
+
+ return qeth_dev_blkt_show(buf, card, card->info.blkt.inter_packet);
+}
+
+
+static ssize_t
+qeth_dev_blkt_inter_store(struct device *dev, const char *buf, size_t count)
+{
+ struct qeth_card *card = dev->driver_data;
+
+ return qeth_dev_blkt_store(card, buf, count,
+ &card->info.blkt.inter_packet,100);
+}
+
+static DEVICE_ATTR(inter, 0644, qeth_dev_blkt_inter_show,
+ qeth_dev_blkt_inter_store);
+
+static ssize_t
+qeth_dev_blkt_inter_jumbo_show(struct device *dev, char *buf)
+{
+ struct qeth_card *card = dev->driver_data;
+
+ return qeth_dev_blkt_show(buf, card,
+ card->info.blkt.inter_packet_jumbo);
+}
+
+
+static ssize_t
+qeth_dev_blkt_inter_jumbo_store(struct device *dev, const char *buf, size_t count)
+{
+ struct qeth_card *card = dev->driver_data;
+
+ return qeth_dev_blkt_store(card, buf, count,
+ &card->info.blkt.inter_packet_jumbo,100);
+}
+
+static DEVICE_ATTR(inter_jumbo, 0644, qeth_dev_blkt_inter_jumbo_show,
+ qeth_dev_blkt_inter_jumbo_store);
+
+static struct device_attribute * qeth_blkt_device_attrs[] = {
+ &dev_attr_total,
+ &dev_attr_inter,
+ &dev_attr_inter_jumbo,
+ NULL,
+};
+
+static struct attribute_group qeth_device_blkt_group = {
+ .name = "blkt",
+ .attrs = (struct attribute **)qeth_blkt_device_attrs,
+};
+
static struct device_attribute * qeth_device_attrs[] = {
&dev_attr_state,
&dev_attr_chpid,
@@ -752,6 +930,7 @@ static struct device_attribute * qeth_device_attrs[] = {
&dev_attr_broadcast_mode,
&dev_attr_canonical_macaddr,
&dev_attr_layer2,
+ &dev_attr_large_send,
NULL,
};
@@ -1506,6 +1685,8 @@ qeth_create_device_attributes(struct device *dev)
sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group);
sysfs_remove_group(&dev->kobj, &qeth_device_vipa_group);
}
+ if ((ret = sysfs_create_group(&dev->kobj, &qeth_device_blkt_group)))
+ return ret;
return ret;
}
@@ -1517,6 +1698,7 @@ qeth_remove_device_attributes(struct device *dev)
sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group);
sysfs_remove_group(&dev->kobj, &qeth_device_vipa_group);
sysfs_remove_group(&dev->kobj, &qeth_device_rxip_group);
+ sysfs_remove_group(&dev->kobj, &qeth_device_blkt_group);
}
/**********************/
diff --git a/drivers/s390/net/qeth_tso.c b/drivers/s390/net/qeth_tso.c
new file mode 100644
index 0000000000000..c91976274e7b0
--- /dev/null
+++ b/drivers/s390/net/qeth_tso.c
@@ -0,0 +1,285 @@
+/*
+ * linux/drivers/s390/net/qeth_tso.c ($Revision: 1.6 $)
+ *
+ * Header file for qeth TCP Segmentation Offload support.
+ *
+ * Copyright 2004 IBM Corporation
+ *
+ * Author(s): Frank Pavlic <pavlic@de.ibm.com>
+ *
+ * $Revision: 1.6 $ $Date: 2005/03/24 09:04:18 $
+ *
+ */
+
+#include <linux/skbuff.h>
+#include <linux/tcp.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+#include <net/ip6_checksum.h>
+#include "qeth.h"
+#include "qeth_mpc.h"
+#include "qeth_tso.h"
+
+/**
+ * skb already partially prepared
+ * classic qdio header in skb->data
+ * */
+static inline struct qeth_hdr_tso *
+qeth_tso_prepare_skb(struct qeth_card *card, struct sk_buff **skb)
+{
+ int rc = 0;
+
+ QETH_DBF_TEXT(trace, 5, "tsoprsk");
+ rc = qeth_realloc_headroom(card, skb,sizeof(struct qeth_hdr_ext_tso));
+ if (rc)
+ return NULL;
+
+ return qeth_push_skb(card, skb, sizeof(struct qeth_hdr_ext_tso));
+}
+
+/**
+ * fill header for a TSO packet
+ */
+static inline void
+qeth_tso_fill_header(struct qeth_card *card, struct sk_buff *skb)
+{
+ struct qeth_hdr_tso *hdr;
+ struct tcphdr *tcph;
+ struct iphdr *iph;
+
+ QETH_DBF_TEXT(trace, 5, "tsofhdr");
+
+ hdr = (struct qeth_hdr_tso *) skb->data;
+ iph = skb->nh.iph;
+ tcph = skb->h.th;
+ /*fix header to TSO values ...*/
+ hdr->hdr.hdr.l3.id = QETH_HEADER_TYPE_TSO;
+ /*set values which are fix for the first approach ...*/
+ hdr->ext.hdr_tot_len = (__u16) sizeof(struct qeth_hdr_ext_tso);
+ hdr->ext.imb_hdr_no = 1;
+ hdr->ext.hdr_type = 1;
+ hdr->ext.hdr_version = 1;
+ hdr->ext.hdr_len = 28;
+ /*insert non-fix values */
+ hdr->ext.mss = skb_shinfo(skb)->tso_size;
+ hdr->ext.dg_hdr_len = (__u16)(iph->ihl*4 + tcph->doff*4);
+ hdr->ext.payload_len = (__u16)(skb->len - hdr->ext.dg_hdr_len -
+ sizeof(struct qeth_hdr_tso));
+}
+
+/**
+ * change some header values as requested by hardware
+ */
+static inline void
+qeth_tso_set_tcpip_header(struct qeth_card *card, struct sk_buff *skb)
+{
+ struct iphdr *iph;
+ struct ipv6hdr *ip6h;
+ struct tcphdr *tcph;
+
+ iph = skb->nh.iph;
+ ip6h = skb->nh.ipv6h;
+ tcph = skb->h.th;
+
+ tcph->check = 0;
+ if (skb->protocol == ETH_P_IPV6) {
+ ip6h->payload_len = 0;
+ tcph->check = ~csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr,
+ 0, IPPROTO_TCP, 0);
+ return;
+ }
+ /*OSA want us to set these values ...*/
+ tcph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr,
+ 0, IPPROTO_TCP, 0);
+ iph->tot_len = 0;
+ iph->check = 0;
+}
+
+static inline struct qeth_hdr_tso *
+qeth_tso_prepare_packet(struct qeth_card *card, struct sk_buff *skb,
+ int ipv, int cast_type)
+{
+ struct qeth_hdr_tso *hdr;
+ int rc = 0;
+
+ QETH_DBF_TEXT(trace, 5, "tsoprep");
+
+ /*get headroom for tso qdio header */
+ hdr = (struct qeth_hdr_tso *) qeth_tso_prepare_skb(card, &skb);
+ if (hdr == NULL) {
+ QETH_DBF_TEXT_(trace, 4, "2err%d", rc);
+ return NULL;
+ }
+ memset(hdr, 0, sizeof(struct qeth_hdr_tso));
+ /*fill first 32 bytes of qdio header as used
+ *FIXME: TSO has two struct members
+ * with different names but same size
+ * */
+ qeth_fill_header(card, &hdr->hdr, skb, ipv, cast_type);
+ qeth_tso_fill_header(card, skb);
+ qeth_tso_set_tcpip_header(card, skb);
+ return hdr;
+}
+
+static inline int
+qeth_tso_get_queue_buffer(struct qeth_qdio_out_q *queue)
+{
+ struct qeth_qdio_out_buffer *buffer;
+ int flush_cnt = 0;
+
+ QETH_DBF_TEXT(trace, 5, "tsobuf");
+
+ /* force to non-packing*/
+ if (queue->do_pack)
+ queue->do_pack = 0;
+ buffer = &queue->bufs[queue->next_buf_to_fill];
+ /* get a new buffer if current is already in use*/
+ if ((atomic_read(&buffer->state) == QETH_QDIO_BUF_EMPTY) &&
+ (buffer->next_element_to_fill > 0)) {
+ atomic_set(&buffer->state, QETH_QDIO_BUF_PRIMED);
+ queue->next_buf_to_fill = (queue->next_buf_to_fill + 1) %
+ QDIO_MAX_BUFFERS_PER_Q;
+ flush_cnt++;
+ }
+ return flush_cnt;
+}
+
+static inline void
+__qeth_tso_fill_buffer_frag(struct qeth_qdio_out_buffer *buf,
+ struct sk_buff *skb)
+{
+ struct skb_frag_struct *frag;
+ struct qdio_buffer *buffer;
+ int fragno, cnt, element;
+ unsigned long addr;
+
+ QETH_DBF_TEXT(trace, 6, "tsfilfrg");
+
+ /*initialize variables ...*/
+ fragno = skb_shinfo(skb)->nr_frags;
+ buffer = buf->buffer;
+ element = buf->next_element_to_fill;
+ /*fill buffer elements .....*/
+ for (cnt = 0; cnt < fragno; cnt++) {
+ frag = &skb_shinfo(skb)->frags[cnt];
+ addr = (page_to_pfn(frag->page) << PAGE_SHIFT) +
+ frag->page_offset;
+ buffer->element[element].addr = (char *)addr;
+ buffer->element[element].length = frag->size;
+ if (cnt < (fragno - 1))
+ buffer->element[element].flags =
+ SBAL_FLAGS_MIDDLE_FRAG;
+ else
+ buffer->element[element].flags =
+ SBAL_FLAGS_LAST_FRAG;
+ element++;
+ }
+ buf->next_element_to_fill = element;
+}
+
+static inline int
+qeth_tso_fill_buffer(struct qeth_qdio_out_buffer *buf,
+ struct sk_buff *skb)
+{
+ int length, length_here, element;
+ int hdr_len;
+ struct qdio_buffer *buffer;
+ struct qeth_hdr_tso *hdr;
+ char *data;
+
+ QETH_DBF_TEXT(trace, 3, "tsfilbuf");
+
+ /*increment user count and queue skb ...*/
+ atomic_inc(&skb->users);
+ skb_queue_tail(&buf->skb_list, skb);
+
+ /*initialize all variables...*/
+ buffer = buf->buffer;
+ hdr = (struct qeth_hdr_tso *)skb->data;
+ hdr_len = sizeof(struct qeth_hdr_tso) + hdr->ext.dg_hdr_len;
+ data = skb->data + hdr_len;
+ length = skb->len - hdr_len;
+ element = buf->next_element_to_fill;
+ /*fill first buffer entry only with header information */
+ buffer->element[element].addr = skb->data;
+ buffer->element[element].length = hdr_len;
+ buffer->element[element].flags = SBAL_FLAGS_FIRST_FRAG;
+ buf->next_element_to_fill++;
+
+ if (skb_shinfo(skb)->nr_frags > 0) {
+ __qeth_tso_fill_buffer_frag(buf, skb);
+ goto out;
+ }
+
+ /*start filling buffer entries ...*/
+ element++;
+ while (length > 0) {
+ /* length_here is the remaining amount of data in this page */
+ length_here = PAGE_SIZE - ((unsigned long) data % PAGE_SIZE);
+ if (length < length_here)
+ length_here = length;
+ buffer->element[element].addr = data;
+ buffer->element[element].length = length_here;
+ length -= length_here;
+ if (!length)
+ buffer->element[element].flags =
+ SBAL_FLAGS_LAST_FRAG;
+ else
+ buffer->element[element].flags =
+ SBAL_FLAGS_MIDDLE_FRAG;
+ data += length_here;
+ element++;
+ }
+ /*set the buffer to primed ...*/
+ buf->next_element_to_fill = element;
+out:
+ atomic_set(&buf->state, QETH_QDIO_BUF_PRIMED);
+ return 1;
+}
+
+int
+qeth_tso_send_packet(struct qeth_card *card, struct sk_buff *skb,
+ struct qeth_qdio_out_q *queue, int ipv, int cast_type)
+{
+ int flush_cnt = 0;
+ struct qeth_hdr_tso *hdr;
+ struct qeth_qdio_out_buffer *buffer;
+ int start_index;
+
+ QETH_DBF_TEXT(trace, 3, "tsosend");
+
+ if (!(hdr = qeth_tso_prepare_packet(card, skb, ipv, cast_type)))
+ return -ENOMEM;
+ /*check if skb fits in one SBAL ...*/
+ if (!(qeth_get_elements_no(card, (void*)hdr, skb)))
+ return -EINVAL;
+ /*lock queue, force switching to non-packing and send it ...*/
+ while (atomic_compare_and_swap(QETH_OUT_Q_UNLOCKED,
+ QETH_OUT_Q_LOCKED,
+ &queue->state));
+ start_index = queue->next_buf_to_fill;
+ buffer = &queue->bufs[queue->next_buf_to_fill];
+ /*check if card is too busy ...*/
+ if (atomic_read(&buffer->state) != QETH_QDIO_BUF_EMPTY){
+ card->stats.tx_dropped++;
+ goto out;
+ }
+ /*let's force to non-packing and get a new SBAL*/
+ flush_cnt += qeth_tso_get_queue_buffer(queue);
+ buffer = &queue->bufs[queue->next_buf_to_fill];
+ if (atomic_read(&buffer->state) != QETH_QDIO_BUF_EMPTY) {
+ card->stats.tx_dropped++;
+ goto out;
+ }
+ flush_cnt += qeth_tso_fill_buffer(buffer, skb);
+ queue->next_buf_to_fill = (queue->next_buf_to_fill + 1) %
+ QDIO_MAX_BUFFERS_PER_Q;
+out:
+ atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED);
+ if (flush_cnt)
+ qeth_flush_buffers(queue, 0, start_index, flush_cnt);
+ /*do some statistics */
+ card->stats.tx_packets++;
+ card->stats.tx_bytes += skb->len;
+ return 0;
+}
diff --git a/drivers/s390/net/qeth_tso.h b/drivers/s390/net/qeth_tso.h
new file mode 100644
index 0000000000000..83504dee3f57d
--- /dev/null
+++ b/drivers/s390/net/qeth_tso.h
@@ -0,0 +1,58 @@
+/*
+ * linux/drivers/s390/net/qeth_tso.h ($Revision: 1.4 $)
+ *
+ * Header file for qeth TCP Segmentation Offload support.
+ *
+ * Copyright 2004 IBM Corporation
+ *
+ * Author(s): Frank Pavlic <pavlic@de.ibm.com>
+ *
+ * $Revision: 1.4 $ $Date: 2005/03/24 09:04:18 $
+ *
+ */
+#ifndef __QETH_TSO_H__
+#define __QETH_TSO_H__
+
+
+extern int
+qeth_tso_send_packet(struct qeth_card *, struct sk_buff *,
+ struct qeth_qdio_out_q *, int , int);
+
+struct qeth_hdr_ext_tso {
+ __u16 hdr_tot_len;
+ __u8 imb_hdr_no;
+ __u8 reserved;
+ __u8 hdr_type;
+ __u8 hdr_version;
+ __u16 hdr_len;
+ __u32 payload_len;
+ __u16 mss;
+ __u16 dg_hdr_len;
+ __u8 padding[16];
+} __attribute__ ((packed));
+
+struct qeth_hdr_tso {
+ struct qeth_hdr hdr; /*hdr->hdr.l3.xxx*/
+ struct qeth_hdr_ext_tso ext;
+} __attribute__ ((packed));
+
+/*some helper functions*/
+
+static inline int
+qeth_get_elements_no(struct qeth_card *card, void *hdr, struct sk_buff *skb)
+{
+ int elements_needed = 0;
+
+ if (skb_shinfo(skb)->nr_frags > 0)
+ elements_needed = (skb_shinfo(skb)->nr_frags + 1);
+ if (elements_needed == 0 )
+ elements_needed = 1 + (((((unsigned long) hdr) % PAGE_SIZE)
+ + skb->len) >> PAGE_SHIFT);
+ if (elements_needed > QETH_MAX_BUFFER_ELEMENTS(card)){
+ PRINT_ERR("qeth_do_send_packet: invalid size of "
+ "IP packet. Discarded.");
+ return 0;
+ }
+ return elements_needed;
+}
+#endif /* __QETH_TSO_H__ */
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
index 007f915973b71..6a43322ccb0a5 100644
--- a/drivers/s390/scsi/zfcp_aux.c
+++ b/drivers/s390/scsi/zfcp_aux.c
@@ -583,7 +583,7 @@ zfcp_sg_list_alloc(struct zfcp_sg_list *sg_list, size_t size)
retval = -ENOMEM;
goto out;
}
- memset(sg_list->sg, sg_list->count * sizeof(struct scatterlist), 0);
+ memset(sg_list->sg, 0, sg_list->count * sizeof(struct scatterlist));
for (i = 0, sg = sg_list->sg; i < sg_list->count; i++, sg++) {
sg->length = min(size, PAGE_SIZE);
@@ -928,7 +928,7 @@ zfcp_unit_dequeue(struct zfcp_unit *unit)
}
static void *
-zfcp_mempool_alloc(int gfp_mask, void *size)
+zfcp_mempool_alloc(unsigned int __nocast gfp_mask, void *size)
{
return kmalloc((size_t) size, gfp_mask);
}
diff --git a/drivers/sbus/char/aurora.c b/drivers/sbus/char/aurora.c
index a433252a5ff28..e5fa1703856bf 100644
--- a/drivers/sbus/char/aurora.c
+++ b/drivers/sbus/char/aurora.c
@@ -1887,14 +1887,12 @@ extern int aurora_get_serial_info(struct Aurora_port * port,
{
struct serial_struct tmp;
struct Aurora_board *bp = port_Board(port);
- int error;
#ifdef AURORA_DEBUG
printk("aurora_get_serial_info: start\n");
#endif
- error = verify_area(VERIFY_WRITE, (void *) retinfo, sizeof(tmp));
- if (error)
- return error;
+ if (!access_ok(VERIFY_WRITE, (void *) retinfo, sizeof(tmp)))
+ return -EFAULT;
memset(&tmp, 0, sizeof(tmp));
tmp.type = PORT_CIRRUS;
diff --git a/drivers/sbus/char/flash.c b/drivers/sbus/char/flash.c
index cf2457b667a40..6bdd768b731db 100644
--- a/drivers/sbus/char/flash.c
+++ b/drivers/sbus/char/flash.c
@@ -75,7 +75,7 @@ flash_mmap(struct file *file, struct vm_area_struct *vma)
pgprot_val(vma->vm_page_prot) |= _PAGE_E;
vma->vm_flags |= (VM_SHM | VM_LOCKED);
- if (remap_pfn_range(vma, vma->vm_start, addr, size, vma->vm_page_prot))
+ if (io_remap_pfn_range(vma, vma->vm_start, addr, size, vma->vm_page_prot))
return -EAGAIN;
return 0;
diff --git a/drivers/sbus/char/openprom.c b/drivers/sbus/char/openprom.c
index 7c23de377354c..58ed33749571d 100644
--- a/drivers/sbus/char/openprom.c
+++ b/drivers/sbus/char/openprom.c
@@ -427,16 +427,14 @@ static int openprom_bsd_ioctl(struct inode * inode, struct file * file,
len = op.op_buflen = 0;
}
- error = verify_area(VERIFY_WRITE, argp, sizeof(op));
- if (error) {
+ if (!access_ok(VERIFY_WRITE, argp, sizeof(op))) {
kfree(str);
- return error;
+ return -EFAULT;
}
- error = verify_area(VERIFY_WRITE, op.op_buf, len);
- if (error) {
+ if (!access_ok(VERIFY_WRITE, op.op_buf, len)) {
kfree(str);
- return error;
+ return -EFAULT;
}
error = __copy_to_user(argp, &op, sizeof(op));
diff --git a/drivers/sbus/char/vfc_dev.c b/drivers/sbus/char/vfc_dev.c
index 057a24bba81a7..86ce541309549 100644
--- a/drivers/sbus/char/vfc_dev.c
+++ b/drivers/sbus/char/vfc_dev.c
@@ -626,8 +626,10 @@ static int vfc_mmap(struct file *file, struct vm_area_struct *vma)
vma->vm_flags |=
(VM_SHM | VM_LOCKED | VM_IO | VM_MAYREAD | VM_MAYWRITE | VM_MAYSHARE);
map_offset = (unsigned int) (long)dev->phys_regs;
- ret = io_remap_page_range(vma, vma->vm_start, map_offset, map_size,
- vma->vm_page_prot, dev->which_io);
+ ret = io_remap_pfn_range(vma, vma->vm_start,
+ MK_IOSPACE_PFN(dev->which_io,
+ map_offset >> PAGE_SHIFT),
+ map_size, vma->vm_page_prot);
if(ret)
return -EAGAIN;
diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c
index 199698597ba8e..a2b18f5a4f930 100644
--- a/drivers/scsi/3w-9xxx.c
+++ b/drivers/scsi/3w-9xxx.c
@@ -3,7 +3,7 @@
Written By: Adam Radford <linuxraid@amcc.com>
- Copyright (C) 2004 Applied Micro Circuits Corporation.
+ Copyright (C) 2004-2005 Applied Micro Circuits 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
@@ -51,6 +51,14 @@
-------
2.26.02.000 - Driver cleanup for kernel submission.
2.26.02.001 - Replace schedule_timeout() calls with msleep().
+ 2.26.02.002 - Add support for PAE mode.
+ Add lun support.
+ Fix twa_remove() to free irq handler/unregister_chrdev()
+ before shutting down card.
+ Change to new 'change_queue_depth' api.
+ Fix 'handled=1' ISR usage, remove bogus IRQ check.
+ Remove un-needed eh_abort handler.
+ Add support for embedded firmware error strings.
*/
#include <linux/module.h>
@@ -73,7 +81,7 @@
#include "3w-9xxx.h"
/* Globals */
-static const char *twa_driver_version="2.26.02.001";
+#define TW_DRIVER_VERSION "2.26.02.002"
static TW_Device_Extension *twa_device_extension_list[TW_MAX_SLOT];
static unsigned int twa_device_extension_count;
static int twa_major = -1;
@@ -83,6 +91,7 @@ extern struct timezone sys_tz;
MODULE_AUTHOR ("AMCC");
MODULE_DESCRIPTION ("3ware 9000 Storage Controller Linux Driver");
MODULE_LICENSE("GPL");
+MODULE_VERSION(TW_DRIVER_VERSION);
/* Function prototypes */
static void twa_aen_queue_event(TW_Device_Extension *tw_dev, TW_Command_Apache_Header *header);
@@ -108,9 +117,9 @@ static void twa_load_sgl(TW_Command_Full *full_command_packet, int request_id, d
static int twa_poll_response(TW_Device_Extension *tw_dev, int request_id, int seconds);
static int twa_poll_status_gone(TW_Device_Extension *tw_dev, u32 flag, int seconds);
static int twa_post_command_packet(TW_Device_Extension *tw_dev, int request_id, char internal);
-static int twa_reset_device_extension(TW_Device_Extension *tw_dev);
+static int twa_reset_device_extension(TW_Device_Extension *tw_dev, int ioctl_reset);
static int twa_reset_sequence(TW_Device_Extension *tw_dev, int soft_reset);
-static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, char *cdb, int use_sg, TW_SG_Apache *sglistarg);
+static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, char *cdb, int use_sg, TW_SG_Entry *sglistarg);
static void twa_scsiop_execute_scsi_complete(TW_Device_Extension *tw_dev, int request_id);
static char *twa_string_lookup(twa_message_type *table, unsigned int aen_code);
static void twa_unmap_scsi_data(TW_Device_Extension *tw_dev, int request_id);
@@ -126,7 +135,7 @@ static ssize_t twa_show_stats(struct class_device *class_dev, char *buf)
ssize_t len;
spin_lock_irqsave(tw_dev->host->host_lock, flags);
- len = snprintf(buf, PAGE_SIZE, "Driver version: %s\n"
+ len = snprintf(buf, PAGE_SIZE, "3w-9xxx Driver version: %s\n"
"Current commands posted: %4d\n"
"Max commands posted: %4d\n"
"Current pending commands: %4d\n"
@@ -136,9 +145,8 @@ static ssize_t twa_show_stats(struct class_device *class_dev, char *buf)
"Last sector count: %4d\n"
"Max sector count: %4d\n"
"SCSI Host Resets: %4d\n"
- "SCSI Aborts/Timeouts: %4d\n"
"AEN's: %4d\n",
- twa_driver_version,
+ TW_DRIVER_VERSION,
tw_dev->posted_request_count,
tw_dev->max_posted_request_count,
tw_dev->pending_request_count,
@@ -148,40 +156,19 @@ static ssize_t twa_show_stats(struct class_device *class_dev, char *buf)
tw_dev->sector_count,
tw_dev->max_sector_count,
tw_dev->num_resets,
- tw_dev->num_aborts,
tw_dev->aen_count);
spin_unlock_irqrestore(tw_dev->host->host_lock, flags);
return len;
} /* End twa_show_stats() */
/* This function will set a devices queue depth */
-static ssize_t twa_store_queue_depth(struct device *dev, const char *buf, size_t count)
+static int twa_change_queue_depth(struct scsi_device *sdev, int queue_depth)
{
- int queue_depth;
- struct scsi_device *sdev = to_scsi_device(dev);
-
- queue_depth = simple_strtoul(buf, NULL, 0);
if (queue_depth > TW_Q_LENGTH-2)
- return -EINVAL;
+ queue_depth = TW_Q_LENGTH-2;
scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, queue_depth);
-
- return count;
-} /* End twa_store_queue_depth() */
-
-/* Create sysfs 'queue_depth' entry */
-static struct device_attribute twa_queue_depth_attr = {
- .attr = {
- .name = "queue_depth",
- .mode = S_IRUSR | S_IWUSR,
- },
- .store = twa_store_queue_depth
-};
-
-/* Device attributes initializer */
-static struct device_attribute *twa_dev_attrs[] = {
- &twa_queue_depth_attr,
- NULL,
-};
+ return queue_depth;
+} /* End twa_change_queue_depth() */
/* Create sysfs 'stats' entry */
static struct class_device_attribute twa_host_stats_attr = {
@@ -265,7 +252,7 @@ static int twa_aen_drain_queue(TW_Device_Extension *tw_dev, int no_check_reset)
{
int request_id = 0;
char cdb[TW_MAX_CDB_LEN];
- TW_SG_Apache sglist[1];
+ TW_SG_Entry sglist[1];
int finished = 0, count = 0;
TW_Command_Full *full_command_packet;
TW_Command_Apache_Header *header;
@@ -286,7 +273,7 @@ static int twa_aen_drain_queue(TW_Device_Extension *tw_dev, int no_check_reset)
cdb[4] = TW_ALLOCATION_LENGTH; /* allocation length */
/* Initialize sglist */
- memset(&sglist, 0, sizeof(TW_SG_Apache));
+ memset(&sglist, 0, sizeof(TW_SG_Entry));
sglist[0].length = TW_SECTOR_SIZE;
sglist[0].address = tw_dev->generic_buffer_phys[request_id];
@@ -359,6 +346,7 @@ static void twa_aen_queue_event(TW_Device_Extension *tw_dev, TW_Command_Apache_H
TW_Event *event;
unsigned short aen;
char host[16];
+ char *error_str;
tw_dev->aen_count++;
@@ -385,6 +373,9 @@ static void twa_aen_queue_event(TW_Device_Extension *tw_dev, TW_Command_Apache_H
event->sequence_id = tw_dev->error_sequence_id;
tw_dev->error_sequence_id++;
+ /* Check for embedded error string */
+ error_str = &(header->err_specific_desc[strlen(header->err_specific_desc)+1]);
+
header->err_specific_desc[sizeof(header->err_specific_desc) - 1] = '\0';
event->parameter_len = strlen(header->err_specific_desc);
memcpy(event->parameter_data, header->err_specific_desc, event->parameter_len);
@@ -393,7 +384,7 @@ static void twa_aen_queue_event(TW_Device_Extension *tw_dev, TW_Command_Apache_H
host,
twa_aen_severity_lookup(TW_SEV_OUT(header->status_block.severity__reserved)),
TW_MESSAGE_SOURCE_CONTROLLER_EVENT, aen,
- twa_string_lookup(twa_aen_table, aen),
+ error_str[0] == '\0' ? twa_string_lookup(twa_aen_table, aen) : error_str,
header->err_specific_desc);
else
tw_dev->aen_count--;
@@ -407,7 +398,7 @@ static void twa_aen_queue_event(TW_Device_Extension *tw_dev, TW_Command_Apache_H
static int twa_aen_read_queue(TW_Device_Extension *tw_dev, int request_id)
{
char cdb[TW_MAX_CDB_LEN];
- TW_SG_Apache sglist[1];
+ TW_SG_Entry sglist[1];
TW_Command_Full *full_command_packet;
int retval = 1;
@@ -420,7 +411,7 @@ static int twa_aen_read_queue(TW_Device_Extension *tw_dev, int request_id)
cdb[4] = TW_ALLOCATION_LENGTH; /* allocation length */
/* Initialize sglist */
- memset(&sglist, 0, sizeof(TW_SG_Apache));
+ memset(&sglist, 0, sizeof(TW_SG_Entry));
sglist[0].length = TW_SECTOR_SIZE;
sglist[0].address = tw_dev->generic_buffer_phys[request_id];
@@ -558,18 +549,18 @@ static int twa_check_srl(TW_Device_Extension *tw_dev, int *flashed)
u32 init_connect_result = 0;
if (twa_initconnection(tw_dev, TW_INIT_MESSAGE_CREDITS,
- TW_EXTENDED_INIT_CONNECT, TW_CURRENT_FW_SRL,
- TW_9000_ARCH_ID, TW_CURRENT_FW_BRANCH,
- TW_CURRENT_FW_BUILD, &fw_on_ctlr_srl,
+ TW_EXTENDED_INIT_CONNECT, TW_CURRENT_DRIVER_SRL,
+ TW_9000_ARCH_ID, TW_CURRENT_DRIVER_BRANCH,
+ TW_CURRENT_DRIVER_BUILD, &fw_on_ctlr_srl,
&fw_on_ctlr_arch_id, &fw_on_ctlr_branch,
&fw_on_ctlr_build, &init_connect_result)) {
TW_PRINTK(tw_dev->host, TW_DRIVER, 0x7, "Initconnection failed while checking SRL");
goto out;
}
- tw_dev->working_srl = TW_CURRENT_FW_SRL;
- tw_dev->working_branch = TW_CURRENT_FW_BRANCH;
- tw_dev->working_build = TW_CURRENT_FW_BUILD;
+ tw_dev->working_srl = fw_on_ctlr_srl;
+ tw_dev->working_branch = fw_on_ctlr_branch;
+ tw_dev->working_build = fw_on_ctlr_build;
/* Try base mode compatibility */
if (!(init_connect_result & TW_CTLR_FW_COMPATIBLE)) {
@@ -584,7 +575,7 @@ static int twa_check_srl(TW_Device_Extension *tw_dev, int *flashed)
goto out;
}
if (!(init_connect_result & TW_CTLR_FW_COMPATIBLE)) {
- if (TW_CURRENT_FW_SRL > fw_on_ctlr_srl) {
+ if (TW_CURRENT_DRIVER_SRL > fw_on_ctlr_srl) {
TW_PRINTK(tw_dev->host, TW_DRIVER, 0x32, "Firmware and driver incompatibility: please upgrade firmware");
} else {
TW_PRINTK(tw_dev->host, TW_DRIVER, 0x33, "Firmware and driver incompatibility: please upgrade driver");
@@ -641,7 +632,7 @@ static int twa_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int
data_buffer_length_adjusted = (driver_command.buffer_length + 511) & ~511;
/* Now allocate ioctl buf memory */
- cpu_addr = pci_alloc_consistent(tw_dev->tw_pci_dev, data_buffer_length_adjusted+sizeof(TW_Ioctl_Buf_Apache) - 1, &dma_handle);
+ cpu_addr = dma_alloc_coherent(&tw_dev->tw_pci_dev->dev, data_buffer_length_adjusted+sizeof(TW_Ioctl_Buf_Apache) - 1, &dma_handle, GFP_KERNEL);
if (!cpu_addr) {
retval = TW_IOCTL_ERROR_OS_ENOMEM;
goto out2;
@@ -679,26 +670,28 @@ static int twa_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int
timeout = TW_IOCTL_CHRDEV_TIMEOUT*HZ;
/* Now wait for command to complete */
- timeout = wait_event_interruptible_timeout(tw_dev->ioctl_wqueue, tw_dev->chrdev_request_id == TW_IOCTL_CHRDEV_FREE, timeout);
+ timeout = wait_event_timeout(tw_dev->ioctl_wqueue, tw_dev->chrdev_request_id == TW_IOCTL_CHRDEV_FREE, timeout);
+
+ /* See if we reset while waiting for the ioctl to complete */
+ if (test_bit(TW_IN_RESET, &tw_dev->flags)) {
+ clear_bit(TW_IN_RESET, &tw_dev->flags);
+ retval = TW_IOCTL_ERROR_OS_ERESTARTSYS;
+ goto out3;
+ }
- /* Check if we timed out, got a signal, or didn't get
- an interrupt */
- if ((timeout <= 0) && (tw_dev->chrdev_request_id != TW_IOCTL_CHRDEV_FREE)) {
+ /* We timed out, and didn't get an interrupt */
+ if (tw_dev->chrdev_request_id != TW_IOCTL_CHRDEV_FREE) {
/* Now we need to reset the board */
- if (timeout == TW_IOCTL_ERROR_OS_ERESTARTSYS) {
- retval = timeout;
- } else {
- printk(KERN_WARNING "3w-9xxx: scsi%d: WARNING: (0x%02X:0x%04X): Character ioctl (0x%x) timed out, resetting card.\n",
- tw_dev->host->host_no, TW_DRIVER, 0xc,
- cmd);
- retval = TW_IOCTL_ERROR_OS_EIO;
- }
+ printk(KERN_WARNING "3w-9xxx: scsi%d: WARNING: (0x%02X:0x%04X): Character ioctl (0x%x) timed out, resetting card.\n",
+ tw_dev->host->host_no, TW_DRIVER, 0xc,
+ cmd);
+ retval = TW_IOCTL_ERROR_OS_EIO;
spin_lock_irqsave(tw_dev->host->host_lock, flags);
tw_dev->state[request_id] = TW_S_COMPLETED;
twa_free_request_id(tw_dev, request_id);
tw_dev->posted_request_count--;
- twa_reset_device_extension(tw_dev);
spin_unlock_irqrestore(tw_dev->host->host_lock, flags);
+ twa_reset_device_extension(tw_dev, 1);
goto out3;
}
@@ -716,10 +709,16 @@ static int twa_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int
tw_ioctl->driver_command.status = 0;
/* Copy compatiblity struct into ioctl data buffer */
tw_compat_info = (TW_Compatibility_Info *)tw_ioctl->data_buffer;
- strncpy(tw_compat_info->driver_version, twa_driver_version, strlen(twa_driver_version));
+ strncpy(tw_compat_info->driver_version, TW_DRIVER_VERSION, strlen(TW_DRIVER_VERSION));
tw_compat_info->working_srl = tw_dev->working_srl;
tw_compat_info->working_branch = tw_dev->working_branch;
tw_compat_info->working_build = tw_dev->working_build;
+ tw_compat_info->driver_srl_high = TW_CURRENT_DRIVER_SRL;
+ tw_compat_info->driver_branch_high = TW_CURRENT_DRIVER_BRANCH;
+ tw_compat_info->driver_build_high = TW_CURRENT_DRIVER_BUILD;
+ tw_compat_info->driver_srl_low = TW_BASE_FW_SRL;
+ tw_compat_info->driver_branch_low = TW_BASE_FW_BRANCH;
+ tw_compat_info->driver_build_low = TW_BASE_FW_BUILD;
break;
case TW_IOCTL_GET_LAST_EVENT:
if (tw_dev->event_queue_wrapped) {
@@ -849,7 +848,7 @@ static int twa_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int
retval = 0;
out3:
/* Now free ioctl buf memory */
- pci_free_consistent(tw_dev->tw_pci_dev, data_buffer_length_adjusted+sizeof(TW_Ioctl_Buf_Apache) - 1, cpu_addr, dma_handle);
+ 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);
out:
@@ -936,8 +935,13 @@ static int twa_fill_sense(TW_Device_Extension *tw_dev, int request_id, int copy_
TW_Command_Full *full_command_packet;
unsigned short error;
int retval = 1;
+ char *error_str;
full_command_packet = tw_dev->command_packet_virt[request_id];
+
+ /* Check for embedded error string */
+ error_str = &(full_command_packet->header.err_specific_desc[strlen(full_command_packet->header.err_specific_desc) + 1]);
+
/* Don't print error for Logical unit not supported during rollcall */
error = full_command_packet->header.status_block.error;
if ((error != TW_ERROR_LOGICAL_UNIT_NOT_SUPPORTED) && (error != TW_ERROR_UNIT_OFFLINE)) {
@@ -946,15 +950,17 @@ static int twa_fill_sense(TW_Device_Extension *tw_dev, int request_id, int copy_
tw_dev->host->host_no,
TW_MESSAGE_SOURCE_CONTROLLER_ERROR,
full_command_packet->header.status_block.error,
+ error_str[0] == '\0' ?
twa_string_lookup(twa_error_table,
- full_command_packet->header.status_block.error),
+ full_command_packet->header.status_block.error) : error_str,
full_command_packet->header.err_specific_desc);
else
printk(KERN_WARNING "3w-9xxx: ERROR: (0x%02X:0x%04X): %s:%s.\n",
TW_MESSAGE_SOURCE_CONTROLLER_ERROR,
full_command_packet->header.status_block.error,
+ error_str[0] == '\0' ?
twa_string_lookup(twa_error_table,
- full_command_packet->header.status_block.error),
+ full_command_packet->header.status_block.error) : error_str,
full_command_packet->header.err_specific_desc);
}
@@ -1075,10 +1081,9 @@ static int twa_initconnection(TW_Device_Extension *tw_dev, int message_credits,
tw_initconnect->request_id = request_id;
tw_initconnect->message_credits = message_credits;
tw_initconnect->features = set_features;
-#if BITS_PER_LONG > 32
- /* Turn on 64-bit sgl support */
- tw_initconnect->features |= 1;
-#endif
+
+ /* Turn on 64-bit sgl support if we need to */
+ tw_initconnect->features |= sizeof(dma_addr_t) > 4 ? 1 : 0;
if (set_features & TW_EXTENDED_INIT_CONNECT) {
tw_initconnect->size = TW_INIT_COMMAND_PACKET_SIZE_EXTENDED;
@@ -1173,139 +1178,142 @@ static irqreturn_t twa_interrupt(int irq, void *dev_instance, struct pt_regs *re
/* Get the per adapter lock */
spin_lock(tw_dev->host->host_lock);
- /* See if the interrupt matches this instance */
- if (tw_dev->tw_pci_dev->irq == (unsigned int)irq) {
+ /* Read the registers */
+ status_reg_value = readl(TW_STATUS_REG_ADDR(tw_dev));
- handled = 1;
+ /* Check if this is our interrupt, otherwise bail */
+ if (!(status_reg_value & TW_STATUS_VALID_INTERRUPT))
+ goto twa_interrupt_bail;
- /* Read the registers */
- status_reg_value = readl(TW_STATUS_REG_ADDR(tw_dev));
+ handled = 1;
- /* Check if this is our interrupt, otherwise bail */
- if (!(status_reg_value & TW_STATUS_VALID_INTERRUPT))
+ /* Check controller for errors */
+ if (twa_check_bits(status_reg_value)) {
+ if (twa_decode_bits(tw_dev, status_reg_value)) {
+ TW_CLEAR_ALL_INTERRUPTS(tw_dev);
goto twa_interrupt_bail;
+ }
+ }
+
+ /* Handle host interrupt */
+ if (status_reg_value & TW_STATUS_HOST_INTERRUPT)
+ TW_CLEAR_HOST_INTERRUPT(tw_dev);
+
+ /* Handle attention interrupt */
+ if (status_reg_value & TW_STATUS_ATTENTION_INTERRUPT) {
+ TW_CLEAR_ATTENTION_INTERRUPT(tw_dev);
+ if (!(test_and_set_bit(TW_IN_ATTENTION_LOOP, &tw_dev->flags))) {
+ twa_get_request_id(tw_dev, &request_id);
+
+ error = twa_aen_read_queue(tw_dev, request_id);
+ if (error) {
+ tw_dev->state[request_id] = TW_S_COMPLETED;
+ twa_free_request_id(tw_dev, request_id);
+ clear_bit(TW_IN_ATTENTION_LOOP, &tw_dev->flags);
+ }
+ }
+ }
- /* Check controller for errors */
- if (twa_check_bits(status_reg_value)) {
- if (twa_decode_bits(tw_dev, status_reg_value)) {
+ /* Handle command interrupt */
+ if (status_reg_value & TW_STATUS_COMMAND_INTERRUPT) {
+ TW_MASK_COMMAND_INTERRUPT(tw_dev);
+ /* Drain as many pending commands as we can */
+ while (tw_dev->pending_request_count > 0) {
+ request_id = tw_dev->pending_queue[tw_dev->pending_head];
+ if (tw_dev->state[request_id] != TW_S_PENDING) {
+ TW_PRINTK(tw_dev->host, TW_DRIVER, 0x19, "Found request id that wasn't pending");
TW_CLEAR_ALL_INTERRUPTS(tw_dev);
goto twa_interrupt_bail;
}
+ if (twa_post_command_packet(tw_dev, request_id, 1)==0) {
+ tw_dev->pending_head = (tw_dev->pending_head + 1) % TW_Q_LENGTH;
+ tw_dev->pending_request_count--;
+ } else {
+ /* If we get here, we will continue re-posting on the next command interrupt */
+ break;
+ }
}
+ }
- /* Handle host interrupt */
- if (status_reg_value & TW_STATUS_HOST_INTERRUPT)
- TW_CLEAR_HOST_INTERRUPT(tw_dev);
-
- /* Handle attention interrupt */
- if (status_reg_value & TW_STATUS_ATTENTION_INTERRUPT) {
- TW_CLEAR_ATTENTION_INTERRUPT(tw_dev);
- if (!(test_and_set_bit(TW_IN_ATTENTION_LOOP, &tw_dev->flags))) {
- twa_get_request_id(tw_dev, &request_id);
-
- error = twa_aen_read_queue(tw_dev, request_id);
- if (error) {
- tw_dev->state[request_id] = TW_S_COMPLETED;
- twa_free_request_id(tw_dev, request_id);
- clear_bit(TW_IN_ATTENTION_LOOP, &tw_dev->flags);
+ /* Handle response interrupt */
+ if (status_reg_value & TW_STATUS_RESPONSE_INTERRUPT) {
+
+ /* Drain the response queue from the board */
+ while ((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) {
+ /* Complete the response */
+ response_que.value = readl(TW_RESPONSE_QUEUE_REG_ADDR(tw_dev));
+ request_id = TW_RESID_OUT(response_que.response_id);
+ full_command_packet = tw_dev->command_packet_virt[request_id];
+ error = 0;
+ command_packet = &full_command_packet->command.oldcommand;
+ /* Check for command packet errors */
+ if (full_command_packet->command.newcommand.status != 0) {
+ if (tw_dev->srb[request_id] != 0) {
+ error = twa_fill_sense(tw_dev, request_id, 1, 1);
+ } else {
+ /* Skip ioctl error prints */
+ if (request_id != tw_dev->chrdev_request_id) {
+ error = twa_fill_sense(tw_dev, request_id, 0, 1);
+ }
}
}
- }
- /* Handle command interrupt */
- if (status_reg_value & TW_STATUS_COMMAND_INTERRUPT) {
- TW_MASK_COMMAND_INTERRUPT(tw_dev);
- /* Drain as many pending commands as we can */
- while (tw_dev->pending_request_count > 0) {
- request_id = tw_dev->pending_queue[tw_dev->pending_head];
- if (tw_dev->state[request_id] != TW_S_PENDING) {
- TW_PRINTK(tw_dev->host, TW_DRIVER, 0x19, "Found request id that wasn't pending");
+ /* Check for correct state */
+ if (tw_dev->state[request_id] != TW_S_POSTED) {
+ if (tw_dev->srb[request_id] != 0) {
+ TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1a, "Received a request id that wasn't posted");
TW_CLEAR_ALL_INTERRUPTS(tw_dev);
goto twa_interrupt_bail;
}
- if (twa_post_command_packet(tw_dev, request_id, 1)==0) {
- tw_dev->pending_head = (tw_dev->pending_head + 1) % TW_Q_LENGTH;
- tw_dev->pending_request_count--;
- } else {
- /* If we get here, we will continue re-posting on the next command interrupt */
- break;
- }
}
- }
- /* Handle response interrupt */
- if (status_reg_value & TW_STATUS_RESPONSE_INTERRUPT) {
-
- /* Drain the response queue from the board */
- while ((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) {
- /* Complete the response */
- response_que.value = readl(TW_RESPONSE_QUEUE_REG_ADDR(tw_dev));
- request_id = TW_RESID_OUT(response_que.response_id);
- full_command_packet = tw_dev->command_packet_virt[request_id];
- error = 0;
- command_packet = &full_command_packet->command.oldcommand;
- /* Check for command packet errors */
- if (full_command_packet->command.newcommand.status != 0) {
- if (tw_dev->srb[request_id] != 0) {
- error = twa_fill_sense(tw_dev, request_id, 1, 1);
- } else {
- /* Skip ioctl error prints */
- if (request_id != tw_dev->chrdev_request_id) {
- error = twa_fill_sense(tw_dev, request_id, 0, 1);
- }
- }
+ /* Check for internal command completion */
+ if (tw_dev->srb[request_id] == 0) {
+ if (request_id != tw_dev->chrdev_request_id) {
+ if (twa_aen_complete(tw_dev, request_id))
+ TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1b, "Error completing AEN during attention interrupt");
+ } else {
+ tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE;
+ wake_up(&tw_dev->ioctl_wqueue);
}
-
- /* Check for correct state */
- if (tw_dev->state[request_id] != TW_S_POSTED) {
- if (tw_dev->srb[request_id] != 0) {
- TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1a, "Received a request id that wasn't posted");
- TW_CLEAR_ALL_INTERRUPTS(tw_dev);
- goto twa_interrupt_bail;
- }
+ } else {
+ twa_scsiop_execute_scsi_complete(tw_dev, request_id);
+ /* If no error command was a success */
+ if (error == 0) {
+ tw_dev->srb[request_id]->result = (DID_OK << 16);
}
- /* Check for internal command completion */
- if (tw_dev->srb[request_id] == 0) {
- if (request_id != tw_dev->chrdev_request_id) {
- if (twa_aen_complete(tw_dev, request_id))
- TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1b, "Error completing AEN during attention interrupt");
- } else {
- tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE;
- wake_up(&tw_dev->ioctl_wqueue);
- }
- } else {
- twa_scsiop_execute_scsi_complete(tw_dev, request_id);
- /* If no error command was a success */
- if (error == 0) {
- tw_dev->srb[request_id]->result = (DID_OK << 16);
- }
-
- /* If error, command failed */
- if (error == 1) {
- /* Ask for a host reset */
- tw_dev->srb[request_id]->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
- }
+ /* If error, command failed */
+ if (error == 1) {
+ /* Ask for a host reset */
+ tw_dev->srb[request_id]->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
+ }
- /* Now complete the io */
- tw_dev->state[request_id] = TW_S_COMPLETED;
- twa_free_request_id(tw_dev, request_id);
- tw_dev->posted_request_count--;
- tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
- twa_unmap_scsi_data(tw_dev, request_id);
+ /* Report residual bytes for single sgl */
+ if ((tw_dev->srb[request_id]->use_sg <= 1) && (full_command_packet->command.newcommand.status == 0)) {
+ if (full_command_packet->command.newcommand.sg_list[0].length < tw_dev->srb[request_id]->request_bufflen)
+ tw_dev->srb[request_id]->resid = tw_dev->srb[request_id]->request_bufflen - full_command_packet->command.newcommand.sg_list[0].length;
}
- /* Check for valid status after each drain */
- status_reg_value = readl(TW_STATUS_REG_ADDR(tw_dev));
- if (twa_check_bits(status_reg_value)) {
- if (twa_decode_bits(tw_dev, status_reg_value)) {
- TW_CLEAR_ALL_INTERRUPTS(tw_dev);
- goto twa_interrupt_bail;
- }
+ /* Now complete the io */
+ tw_dev->state[request_id] = TW_S_COMPLETED;
+ twa_free_request_id(tw_dev, request_id);
+ tw_dev->posted_request_count--;
+ tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
+ twa_unmap_scsi_data(tw_dev, request_id);
+ }
+
+ /* Check for valid status after each drain */
+ status_reg_value = readl(TW_STATUS_REG_ADDR(tw_dev));
+ if (twa_check_bits(status_reg_value)) {
+ if (twa_decode_bits(tw_dev, status_reg_value)) {
+ TW_CLEAR_ALL_INTERRUPTS(tw_dev);
+ goto twa_interrupt_bail;
}
}
}
}
+
twa_interrupt_bail:
spin_unlock(tw_dev->host->host_lock);
return IRQ_RETVAL(handled);
@@ -1320,9 +1328,12 @@ static void twa_load_sgl(TW_Command_Full *full_command_packet, int request_id, d
if (TW_OP_OUT(full_command_packet->command.newcommand.opcode__reserved) == TW_OP_EXECUTE_SCSI) {
newcommand = &full_command_packet->command.newcommand;
- newcommand->request_id = request_id;
+ newcommand->request_id__lunl =
+ TW_REQ_LUN_IN(TW_LUN_OUT(newcommand->request_id__lunl), request_id);
newcommand->sg_list[0].address = dma_handle + sizeof(TW_Ioctl_Buf_Apache) - 1;
newcommand->sg_list[0].length = length;
+ newcommand->sgl_entries__lunh =
+ TW_REQ_LUN_IN(TW_LUN_OUT(newcommand->sgl_entries__lunh), 1);
} else {
oldcommand = &full_command_packet->command.oldcommand;
oldcommand->request_id = request_id;
@@ -1332,6 +1343,9 @@ static void twa_load_sgl(TW_Command_Full *full_command_packet, int request_id, d
sgl = (TW_SG_Entry *)((u32 *)oldcommand+TW_SGL_OUT(oldcommand->opcode__sgloffset));
sgl->address = dma_handle + sizeof(TW_Ioctl_Buf_Apache) - 1;
sgl->length = length;
+
+ if ((sizeof(long) < 8) && (sizeof(dma_addr_t) > 4))
+ oldcommand->size += 1;
}
}
} /* End twa_load_sgl() */
@@ -1486,7 +1500,7 @@ out:
static int twa_post_command_packet(TW_Device_Extension *tw_dev, int request_id, char internal)
{
u32 status_reg_value;
- unsigned long command_que_value;
+ dma_addr_t command_que_value;
int retval = 1;
command_que_value = tw_dev->command_packet_phys[request_id];
@@ -1517,11 +1531,13 @@ static int twa_post_command_packet(TW_Device_Extension *tw_dev, int request_id,
goto out;
} else {
/* We successfully posted the command packet */
-#if BITS_PER_LONG > 32
- writeq(TW_COMMAND_OFFSET + command_que_value, TW_COMMAND_QUEUE_REG_ADDR(tw_dev));
-#else
- writel(TW_COMMAND_OFFSET + command_que_value, TW_COMMAND_QUEUE_REG_ADDR(tw_dev));
-#endif
+ if (sizeof(dma_addr_t) > 4) {
+ command_que_value += TW_COMMAND_OFFSET;
+ writel((u32)command_que_value, TW_COMMAND_QUEUE_REG_ADDR(tw_dev));
+ writel((u32)((u64)command_que_value >> 32), TW_COMMAND_QUEUE_REG_ADDR(tw_dev) + 0x4);
+ } else {
+ writel(TW_COMMAND_OFFSET + command_que_value, TW_COMMAND_QUEUE_REG_ADDR(tw_dev));
+ }
tw_dev->state[request_id] = TW_S_POSTED;
tw_dev->posted_request_count++;
if (tw_dev->posted_request_count > tw_dev->max_posted_request_count) {
@@ -1534,10 +1550,16 @@ out:
} /* End twa_post_command_packet() */
/* This function will reset a device extension */
-static int twa_reset_device_extension(TW_Device_Extension *tw_dev)
+static int twa_reset_device_extension(TW_Device_Extension *tw_dev, int ioctl_reset)
{
int i = 0;
int retval = 1;
+ unsigned long flags = 0;
+
+ set_bit(TW_IN_RESET, &tw_dev->flags);
+ TW_DISABLE_INTERRUPTS(tw_dev);
+ TW_MASK_COMMAND_INTERRUPT(tw_dev);
+ spin_lock_irqsave(tw_dev->host->host_lock, flags);
/* Abort all requests that are in progress */
for (i = 0; i < TW_Q_LENGTH; i++) {
@@ -1564,16 +1586,21 @@ static int twa_reset_device_extension(TW_Device_Extension *tw_dev)
tw_dev->pending_head = TW_Q_START;
tw_dev->pending_tail = TW_Q_START;
tw_dev->reset_print = 0;
- tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE;
- tw_dev->flags = 0;
- TW_DISABLE_INTERRUPTS(tw_dev);
+ spin_unlock_irqrestore(tw_dev->host->host_lock, flags);
if (twa_reset_sequence(tw_dev, 1))
goto out;
- TW_ENABLE_AND_CLEAR_INTERRUPTS(tw_dev);
+ TW_ENABLE_AND_CLEAR_INTERRUPTS(tw_dev);
+ /* Wake up any ioctl that was pending before the reset */
+ if ((tw_dev->chrdev_request_id == TW_IOCTL_CHRDEV_FREE) || (ioctl_reset)) {
+ clear_bit(TW_IN_RESET, &tw_dev->flags);
+ } else {
+ tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE;
+ wake_up(&tw_dev->ioctl_wqueue);
+ }
retval = 0;
out:
return retval;
@@ -1589,7 +1616,7 @@ static int twa_reset_sequence(TW_Device_Extension *tw_dev, int soft_reset)
TW_SOFT_RESET(tw_dev);
/* Make sure controller is in a good state */
- if (twa_poll_status(tw_dev, TW_STATUS_MICROCONTROLLER_READY | (do_soft_reset == 1 ? TW_STATUS_ATTENTION_INTERRUPT : 0), 30)) {
+ if (twa_poll_status(tw_dev, TW_STATUS_MICROCONTROLLER_READY | (do_soft_reset == 1 ? TW_STATUS_ATTENTION_INTERRUPT : 0), 60)) {
TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1f, "Microcontroller not ready during reset sequence");
do_soft_reset = 1;
tries++;
@@ -1660,38 +1687,6 @@ static int twa_scsi_biosparam(struct scsi_device *sdev, struct block_device *bde
return 0;
} /* End twa_scsi_biosparam() */
-/* This is the new scsi eh abort function */
-static int twa_scsi_eh_abort(struct scsi_cmnd *SCpnt)
-{
- int i;
- TW_Device_Extension *tw_dev = NULL;
- int retval = FAILED;
-
- tw_dev = (TW_Device_Extension *)SCpnt->device->host->hostdata;
-
- spin_unlock_irq(tw_dev->host->host_lock);
-
- tw_dev->num_aborts++;
-
- /* If we find any IO's in process, we have to reset the card */
- for (i = 0; i < TW_Q_LENGTH; i++) {
- if ((tw_dev->state[i] != TW_S_FINISHED) && (tw_dev->state[i] != TW_S_INITIAL)) {
- printk(KERN_WARNING "3w-9xxx: scsi%d: WARNING: (0x%02X:0x%04X): Unit #%d: Command (0x%x) timed out, resetting card.\n",
- tw_dev->host->host_no, TW_DRIVER, 0x2c,
- SCpnt->device->id, SCpnt->cmnd[0]);
- if (twa_reset_device_extension(tw_dev)) {
- TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2a, "Controller reset failed during scsi abort");
- goto out;
- }
- break;
- }
- }
- retval = SUCCESS;
-out:
- spin_lock_irq(tw_dev->host->host_lock);
- return retval;
-} /* End twa_scsi_eh_abort() */
-
/* This is the new scsi eh reset function */
static int twa_scsi_eh_reset(struct scsi_cmnd *SCpnt)
{
@@ -1704,14 +1699,14 @@ static int twa_scsi_eh_reset(struct scsi_cmnd *SCpnt)
tw_dev->num_resets++;
- printk(KERN_WARNING "3w-9xxx: scsi%d: SCSI host reset started.\n", tw_dev->host->host_no);
+ printk(KERN_WARNING "3w-9xxx: scsi%d: WARNING: (0x%02X:0x%04X): Unit #%d: Command (0x%x) timed out, resetting card.\n", tw_dev->host->host_no, TW_DRIVER, 0x2c, SCpnt->device->id, SCpnt->cmnd[0]);
/* Now reset the card and some of the device extension data */
- if (twa_reset_device_extension(tw_dev)) {
+ if (twa_reset_device_extension(tw_dev, 0)) {
TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2b, "Controller reset failed during scsi host reset");
goto out;
}
- printk(KERN_WARNING "3w-9xxx: scsi%d: SCSI host reset succeeded.\n", tw_dev->host->host_no);
+
retval = SUCCESS;
out:
spin_lock_irq(tw_dev->host->host_lock);
@@ -1724,6 +1719,14 @@ static int twa_scsi_queue(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd
int request_id, retval;
TW_Device_Extension *tw_dev = (TW_Device_Extension *)SCpnt->device->host->hostdata;
+ /* Check if this FW supports luns */
+ if ((SCpnt->device->lun != 0) && (tw_dev->working_srl < TW_FW_SRL_LUNS_SUPPORTED)) {
+ SCpnt->result = (DID_BAD_TARGET << 16);
+ done(SCpnt);
+ retval = 0;
+ goto out;
+ }
+
/* Save done function into scsi_cmnd struct */
SCpnt->scsi_done = done;
@@ -1748,12 +1751,12 @@ static int twa_scsi_queue(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd
done(SCpnt);
retval = 0;
}
-
+out:
return retval;
} /* End twa_scsi_queue() */
/* This function hands scsi cdb's to the firmware */
-static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, char *cdb, int use_sg, TW_SG_Apache *sglistarg)
+static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, char *cdb, int use_sg, TW_SG_Entry *sglistarg)
{
TW_Command_Full *full_command_packet;
TW_Command_Apache *command_packet;
@@ -1787,12 +1790,16 @@ static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id,
else
memcpy(command_packet->cdb, cdb, TW_MAX_CDB_LEN);
- if (srb)
+ if (srb) {
command_packet->unit = srb->device->id;
- else
+ command_packet->request_id__lunl =
+ TW_REQ_LUN_IN(srb->device->lun, request_id);
+ } else {
+ command_packet->request_id__lunl =
+ TW_REQ_LUN_IN(0, request_id);
command_packet->unit = 0;
+ }
- command_packet->request_id = request_id;
command_packet->sgl_offset = 16;
if (!sglistarg) {
@@ -1809,7 +1816,7 @@ static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id,
command_packet->sg_list[0].address = buffaddr;
command_packet->sg_list[0].length = tw_dev->srb[request_id]->request_bufflen;
}
- command_packet->sgl_entries = 1;
+ command_packet->sgl_entries__lunh = TW_REQ_LUN_IN((srb->device->lun >> 4), 1);
if (command_packet->sg_list[0].address & TW_ALIGNMENT_9000_SGL) {
TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2d, "Found unaligned address during execute scsi");
@@ -1818,19 +1825,24 @@ static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id,
}
if (tw_dev->srb[request_id]->use_sg > 0) {
- sg_count = twa_map_scsi_sg_data(tw_dev, request_id);
- if (sg_count == 0)
- goto out;
-
- for (i = 0; i < sg_count; i++) {
- command_packet->sg_list[i].address = sg_dma_address(&sglist[i]);
- command_packet->sg_list[i].length = sg_dma_len(&sglist[i]);
- if (command_packet->sg_list[i].address & TW_ALIGNMENT_9000_SGL) {
- TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2e, "Found unaligned sgl address during execute scsi");
+ if ((tw_dev->srb[request_id]->use_sg == 1) && (tw_dev->srb[request_id]->request_bufflen < TW_MIN_SGL_LENGTH)) {
+ command_packet->sg_list[0].address = tw_dev->generic_buffer_phys[request_id];
+ command_packet->sg_list[0].length = TW_MIN_SGL_LENGTH;
+ } else {
+ sg_count = twa_map_scsi_sg_data(tw_dev, request_id);
+ if (sg_count == 0)
goto out;
+
+ for (i = 0; i < sg_count; i++) {
+ command_packet->sg_list[i].address = sg_dma_address(&sglist[i]);
+ command_packet->sg_list[i].length = sg_dma_len(&sglist[i]);
+ if (command_packet->sg_list[i].address & TW_ALIGNMENT_9000_SGL) {
+ TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2e, "Found unaligned sgl address during execute scsi");
+ goto out;
+ }
}
}
- command_packet->sgl_entries = tw_dev->srb[request_id]->use_sg;
+ command_packet->sgl_entries__lunh = TW_REQ_LUN_IN((srb->device->lun >> 4), tw_dev->srb[request_id]->use_sg);
}
} else {
/* Internal cdb post */
@@ -1842,7 +1854,7 @@ static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id,
goto out;
}
}
- command_packet->sgl_entries = use_sg;
+ command_packet->sgl_entries__lunh = TW_REQ_LUN_IN(0, use_sg);
}
if (srb) {
@@ -1903,7 +1915,7 @@ static void __twa_shutdown(TW_Device_Extension *tw_dev)
}
/* Clear all interrupts just before exit */
- TW_ENABLE_AND_CLEAR_INTERRUPTS(tw_dev);
+ TW_CLEAR_ALL_INTERRUPTS(tw_dev);
} /* End __twa_shutdown() */
/* Wrapper for __twa_shutdown */
@@ -1946,9 +1958,9 @@ static struct scsi_host_template driver_template = {
.module = THIS_MODULE,
.name = "3ware 9000 Storage Controller",
.queuecommand = twa_scsi_queue,
- .eh_abort_handler = twa_scsi_eh_abort,
.eh_host_reset_handler = twa_scsi_eh_reset,
.bios_param = twa_scsi_biosparam,
+ .change_queue_depth = twa_change_queue_depth,
.can_queue = TW_Q_LENGTH-2,
.this_id = -1,
.sg_tablesize = TW_APACHE_MAX_SGL_LENGTH,
@@ -1956,7 +1968,6 @@ static struct scsi_host_template driver_template = {
.cmd_per_lun = TW_MAX_CMDS_PER_LUN,
.use_clustering = ENABLE_CLUSTERING,
.shost_attrs = twa_host_attrs,
- .sdev_attrs = twa_dev_attrs,
.emulated = 1
};
@@ -1976,7 +1987,7 @@ static int __devinit twa_probe(struct pci_dev *pdev, const struct pci_device_id
pci_set_master(pdev);
- retval = pci_set_dma_mask(pdev, TW_DMA_MASK);
+ retval = pci_set_dma_mask(pdev, sizeof(dma_addr_t) > 4 ? DMA_64BIT_MASK : DMA_32BIT_MASK);
if (retval) {
TW_PRINTK(host, TW_DRIVER, 0x23, "Failed to set dma mask");
goto out_disable_device;
@@ -2028,8 +2039,8 @@ static int __devinit twa_probe(struct pci_dev *pdev, const struct pci_device_id
host->max_id = TW_MAX_UNITS;
host->max_cmd_len = TW_MAX_CDB_LEN;
- /* Luns and channels aren't supported by adapter */
- host->max_lun = 0;
+ /* Channels aren't supported by adapter */
+ host->max_lun = TW_MAX_LUNS(tw_dev->working_srl);
host->max_channel = 0;
/* Register the card with the kernel SCSI layer */
@@ -2095,23 +2106,24 @@ static void twa_remove(struct pci_dev *pdev)
scsi_remove_host(tw_dev->host);
- __twa_shutdown(tw_dev);
+ /* Unregister character device */
+ if (twa_major >= 0) {
+ unregister_chrdev(twa_major, "twa");
+ twa_major = -1;
+ }
/* Free up the IRQ */
free_irq(tw_dev->tw_pci_dev->irq, tw_dev);
+ /* Shutdown the card */
+ __twa_shutdown(tw_dev);
+
/* Free up the mem region */
pci_release_regions(pdev);
/* Free up device extension resources */
twa_free_device_extension(tw_dev);
- /* Unregister character device */
- if (twa_major >= 0) {
- unregister_chrdev(twa_major, "twa");
- twa_major = -1;
- }
-
scsi_host_put(tw_dev->host);
pci_disable_device(pdev);
twa_device_extension_count--;
@@ -2139,7 +2151,7 @@ static struct pci_driver twa_driver = {
/* This function is called on driver initialization */
static int __init twa_init(void)
{
- printk(KERN_WARNING "3ware 9000 Storage Controller device driver for Linux v%s.\n", twa_driver_version);
+ printk(KERN_WARNING "3ware 9000 Storage Controller device driver for Linux v%s.\n", TW_DRIVER_VERSION);
return pci_module_init(&twa_driver);
} /* End twa_init() */
diff --git a/drivers/scsi/3w-9xxx.h b/drivers/scsi/3w-9xxx.h
index 29f70d531744c..8c8ecbed3b587 100644
--- a/drivers/scsi/3w-9xxx.h
+++ b/drivers/scsi/3w-9xxx.h
@@ -3,7 +3,7 @@
Written By: Adam Radford <linuxraid@amcc.com>
- Copyright (C) 2004 Applied Micro Circuits Corporation.
+ Copyright (C) 2004-2005 Applied Micro Circuits 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
@@ -293,7 +293,6 @@ static twa_message_type twa_error_table[] = {
#define TW_RESPONSE_ID_MASK 0x00000FF0
/* PCI related defines */
-#define TW_DEVICE_NAME "3w-9xxx"
#define TW_NUMDEVICES 1
#define TW_PCI_CLEAR_PARITY_ERRORS 0xc100
#define TW_PCI_CLEAR_PCI_ABORT 0x2000
@@ -325,9 +324,9 @@ static twa_message_type twa_error_table[] = {
/* Compatibility defines */
#define TW_9000_ARCH_ID 0x5
-#define TW_CURRENT_FW_SRL 24
-#define TW_CURRENT_FW_BUILD 5
-#define TW_CURRENT_FW_BRANCH 1
+#define TW_CURRENT_DRIVER_SRL 28
+#define TW_CURRENT_DRIVER_BUILD 9
+#define TW_CURRENT_DRIVER_BRANCH 4
/* Phase defines */
#define TW_PHASE_INITIAL 0
@@ -346,19 +345,10 @@ static twa_message_type twa_error_table[] = {
#define TW_BUNDLED_FW_SAFE_TO_FLASH 0x4
#define TW_CTLR_FW_RECOMMENDS_FLASH 0x8
#define TW_CTLR_FW_COMPATIBLE 0x2
-#define TW_BASE_FW_SRL 0x17
+#define TW_BASE_FW_SRL 24
#define TW_BASE_FW_BRANCH 0
#define TW_BASE_FW_BUILD 1
-#if BITS_PER_LONG > 32
-#define TW_APACHE_MAX_SGL_LENGTH 72
-#define TW_ESCALADE_MAX_SGL_LENGTH 41
-#define TW_APACHE_CMD_PKT_SIZE 5
-#else
-#define TW_APACHE_MAX_SGL_LENGTH 109
-#define TW_ESCALADE_MAX_SGL_LENGTH 62
-#define TW_APACHE_CMD_PKT_SIZE 4
-#endif
-#define TW_ATA_PASS_SGL_MAX 60
+#define TW_FW_SRL_LUNS_SUPPORTED 28
#define TW_Q_LENGTH 256
#define TW_Q_START 0
#define TW_MAX_SLOT 32
@@ -366,7 +356,7 @@ static twa_message_type twa_error_table[] = {
#define TW_MAX_CMDS_PER_LUN 254
#define TW_MAX_RESPONSE_DRAIN 256
#define TW_MAX_AEN_DRAIN 40
-#define TW_IN_IOCTL 2
+#define TW_IN_RESET 2
#define TW_IN_CHRDEV_IOCTL 3
#define TW_IN_ATTENTION_LOOP 4
#define TW_MAX_SECTORS 256
@@ -424,13 +414,6 @@ static twa_message_type twa_error_table[] = {
#define TW_DRIVER TW_MESSAGE_SOURCE_LINUX_DRIVER
#define TW_MESSAGE_SOURCE_LINUX_OS 9
#define TW_OS TW_MESSAGE_SOURCE_LINUX_OS
-#if BITS_PER_LONG > 32
-#define TW_COMMAND_SIZE 5
-#define TW_DMA_MASK DMA_64BIT_MASK
-#else
-#define TW_COMMAND_SIZE 4
-#define TW_DMA_MASK DMA_32BIT_MASK
-#endif
#ifndef PCI_DEVICE_ID_3WARE_9000
#define PCI_DEVICE_ID_3WARE_9000 0x1002
#endif
@@ -451,14 +434,14 @@ static twa_message_type twa_error_table[] = {
/* reserved_1: 4, response_id: 8, reserved_2: 20 */
#define TW_RESID_OUT(x) ((x >> 4) & 0xff)
+/* request_id: 12, lun: 4 */
+#define TW_REQ_LUN_IN(lun, request_id) (((lun << 12) & 0xf000) | (request_id & 0xfff))
+#define TW_LUN_OUT(lun) ((lun >> 12) & 0xf)
+
/* Macros */
#define TW_CONTROL_REG_ADDR(x) (x->base_addr)
#define TW_STATUS_REG_ADDR(x) ((unsigned char __iomem *)x->base_addr + 0x4)
-#if BITS_PER_LONG > 32
-#define TW_COMMAND_QUEUE_REG_ADDR(x) ((unsigned char __iomem *)x->base_addr + 0x20)
-#else
-#define TW_COMMAND_QUEUE_REG_ADDR(x) ((unsigned char __iomem *)x->base_addr + 0x8)
-#endif
+#define TW_COMMAND_QUEUE_REG_ADDR(x) (sizeof(dma_addr_t) > 4 ? ((unsigned char __iomem *)x->base_addr + 0x20) : ((unsigned char __iomem *)x->base_addr + 0x8))
#define TW_RESPONSE_QUEUE_REG_ADDR(x) ((unsigned char __iomem *)x->base_addr + 0xC)
#define TW_CLEAR_ALL_INTERRUPTS(x) (writel(TW_STATUS_VALID_INTERRUPT, TW_CONTROL_REG_ADDR(x)))
#define TW_CLEAR_ATTENTION_INTERRUPT(x) (writel(TW_CONTROL_CLEAR_ATTENTION_INTERRUPT, TW_CONTROL_REG_ADDR(x)))
@@ -480,12 +463,17 @@ printk(KERN_WARNING "3w-9xxx: scsi%d: ERROR: (0x%02X:0x%04X): %s.\n",h->host_no,
else \
printk(KERN_WARNING "3w-9xxx: ERROR: (0x%02X:0x%04X): %s.\n",a,b,c); \
}
+#define TW_MAX_LUNS(srl) (srl < TW_FW_SRL_LUNS_SUPPORTED ? 1 : 16)
+#define TW_COMMAND_SIZE (sizeof(dma_addr_t) > 4 ? 5 : 4)
+#define TW_APACHE_MAX_SGL_LENGTH (sizeof(dma_addr_t) > 4 ? 72 : 109)
+#define TW_ESCALADE_MAX_SGL_LENGTH (sizeof(dma_addr_t) > 4 ? 41 : 62)
+#define TW_PADDING_LENGTH (sizeof(dma_addr_t) > 4 ? 8 : 0)
#pragma pack(1)
/* Scatter Gather List Entry */
typedef struct TAG_TW_SG_Entry {
- unsigned long address;
+ dma_addr_t address;
u32 length;
} TW_SG_Entry;
@@ -506,42 +494,27 @@ typedef struct TW_Command {
struct {
u32 lba;
TW_SG_Entry sgl[TW_ESCALADE_MAX_SGL_LENGTH];
-#if BITS_PER_LONG > 32
- u32 padding[2]; /* pad to 512 bytes */
-#else
- u32 padding;
-#endif
+ dma_addr_t padding;
} io;
struct {
TW_SG_Entry sgl[TW_ESCALADE_MAX_SGL_LENGTH];
-#if BITS_PER_LONG > 32
- u32 padding[3];
-#else
- u32 padding[2];
-#endif
+ u32 padding;
+ dma_addr_t padding2;
} param;
} byte8_offset;
} TW_Command;
-/* Scatter gather element for 9000+ controllers */
-typedef struct TAG_TW_SG_Apache {
- unsigned long address;
- u32 length;
-} TW_SG_Apache;
-
/* Command Packet for 9000+ controllers */
typedef struct TAG_TW_Command_Apache {
unsigned char opcode__reserved;
unsigned char unit;
- unsigned short request_id;
+ unsigned short request_id__lunl;
unsigned char status;
unsigned char sgl_offset;
- unsigned short sgl_entries;
+ unsigned short sgl_entries__lunh;
unsigned char cdb[16];
- TW_SG_Apache sg_list[TW_APACHE_MAX_SGL_LENGTH];
-#if BITS_PER_LONG > 32
- unsigned char padding[8];
-#endif
+ TW_SG_Entry sg_list[TW_APACHE_MAX_SGL_LENGTH];
+ unsigned char padding[TW_PADDING_LENGTH];
} TW_Command_Apache;
/* New command packet header */
@@ -652,14 +625,20 @@ typedef struct TAG_TW_Compatibility_Info
unsigned short working_srl;
unsigned short working_branch;
unsigned short working_build;
+ unsigned short driver_srl_high;
+ unsigned short driver_branch_high;
+ unsigned short driver_build_high;
+ unsigned short driver_srl_low;
+ unsigned short driver_branch_low;
+ unsigned short driver_build_low;
} TW_Compatibility_Info;
typedef struct TAG_TW_Device_Extension {
u32 __iomem *base_addr;
unsigned long *generic_buffer_virt[TW_Q_LENGTH];
- unsigned long generic_buffer_phys[TW_Q_LENGTH];
+ dma_addr_t generic_buffer_phys[TW_Q_LENGTH];
TW_Command_Full *command_packet_virt[TW_Q_LENGTH];
- unsigned long command_packet_phys[TW_Q_LENGTH];
+ dma_addr_t command_packet_phys[TW_Q_LENGTH];
struct pci_dev *tw_pci_dev;
struct scsi_cmnd *srb[TW_Q_LENGTH];
unsigned char free_queue[TW_Q_LENGTH];
@@ -675,7 +654,6 @@ typedef struct TAG_TW_Device_Extension {
unsigned int max_pending_request_count;
unsigned int max_sgl_entries;
unsigned int sgl_entries;
- unsigned int num_aborts;
unsigned int num_resets;
unsigned int sector_count;
unsigned int max_sector_count;
diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c
index 9073638c836aa..48f9ece1cbd09 100644
--- a/drivers/scsi/3w-xxxx.c
+++ b/drivers/scsi/3w-xxxx.c
@@ -6,7 +6,7 @@
Arnaldo Carvalho de Melo <acme@conectiva.com.br>
Brad Strand <linux@3ware.com>
- Copyright (C) 1999-2004 3ware Inc.
+ Copyright (C) 1999-2005 3ware Inc.
Kernel compatiblity By: Andre Hedrick <andre@suse.com>
Non-Copyright (C) 2000 Andre Hedrick <andre@suse.com>
@@ -185,6 +185,12 @@
Fix data_buffer_length usage in tw_chrdev_ioctl().
Update contact information.
1.26.02.000 - Convert driver to pci_driver format.
+ 1.26.02.001 - Increase max ioctl buffer size to 512 sectors.
+ Make tw_scsi_queue() return 0 for 'Unknown scsi opcode'.
+ Fix tw_remove() to free irq handler/unregister_chrdev()
+ before shutting down card.
+ Change to new 'change_queue_depth' api.
+ Fix 'handled=1' ISR usage, remove bogus IRQ check.
*/
#include <linux/module.h>
@@ -207,7 +213,7 @@
#include "3w-xxxx.h"
/* Globals */
-#define TW_DRIVER_VERSION "1.26.02.000"
+#define TW_DRIVER_VERSION "1.26.02.001"
static TW_Device_Extension *tw_device_extension_list[TW_MAX_SLOT];
static int tw_device_extension_count = 0;
static int twe_major = -1;
@@ -509,33 +515,13 @@ static ssize_t tw_show_stats(struct class_device *class_dev, char *buf)
} /* End tw_show_stats() */
/* This function will set a devices queue depth */
-static ssize_t tw_store_queue_depth(struct device *dev, const char *buf, size_t count)
+static int tw_change_queue_depth(struct scsi_device *sdev, int queue_depth)
{
- int queue_depth;
- struct scsi_device *sdev = to_scsi_device(dev);
-
- queue_depth = simple_strtoul(buf, NULL, 0);
if (queue_depth > TW_Q_LENGTH-2)
- return -EINVAL;
+ queue_depth = TW_Q_LENGTH-2;
scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, queue_depth);
-
- return count;
-} /* End tw_store_queue_depth() */
-
-/* Create sysfs 'queue_depth' entry */
-static struct device_attribute tw_queue_depth_attr = {
- .attr = {
- .name = "queue_depth",
- .mode = S_IRUSR | S_IWUSR,
- },
- .store = tw_store_queue_depth
-};
-
-/* Device attributes initializer */
-static struct device_attribute *tw_dev_attrs[] = {
- &tw_queue_depth_attr,
- NULL,
-};
+ return queue_depth;
+} /* End tw_change_queue_depth() */
/* Create sysfs 'stats' entry */
static struct class_device_attribute tw_host_stats_attr = {
@@ -910,7 +896,7 @@ static int tw_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int
goto out;
/* Check size */
- if (data_buffer_length > TW_MAX_SECTORS * 512) {
+ if (data_buffer_length > TW_MAX_IOCTL_SECTORS * 512) {
retval = -EINVAL;
goto out;
}
@@ -995,7 +981,7 @@ static int tw_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int
timeout = TW_IOCTL_CHRDEV_TIMEOUT*HZ;
/* Now wait for the command to complete */
- timeout = wait_event_interruptible_timeout(tw_dev->ioctl_wqueue, tw_dev->chrdev_request_id == TW_IOCTL_CHRDEV_FREE, timeout);
+ timeout = wait_event_timeout(tw_dev->ioctl_wqueue, tw_dev->chrdev_request_id == TW_IOCTL_CHRDEV_FREE, timeout);
/* See if we reset while waiting for the ioctl to complete */
if (test_bit(TW_IN_RESET, &tw_dev->flags)) {
@@ -1004,16 +990,11 @@ static int tw_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int
goto out2;
}
- /* Check if we timed out, got a signal, or didn't get
- an interrupt */
- if ((timeout <= 0) && (tw_dev->chrdev_request_id != TW_IOCTL_CHRDEV_FREE)) {
+ /* We timed out, and didn't get an interrupt */
+ if (tw_dev->chrdev_request_id != TW_IOCTL_CHRDEV_FREE) {
/* Now we need to reset the board */
- if (timeout == -ERESTARTSYS) {
- retval = timeout;
- } else {
- printk(KERN_WARNING "3w-xxxx: scsi%d: Character ioctl (0x%x) timed out, resetting card.\n", tw_dev->host->host_no, cmd);
- retval = -EIO;
- }
+ printk(KERN_WARNING "3w-xxxx: scsi%d: Character ioctl (0x%x) timed out, resetting card.\n", tw_dev->host->host_no, cmd);
+ retval = -EIO;
spin_lock_irqsave(tw_dev->host->host_lock, flags);
tw_dev->state[request_id] = TW_S_COMPLETED;
tw_state_request_finish(tw_dev, request_id);
@@ -2060,7 +2041,7 @@ static int tw_scsi_queue(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd
tw_state_request_finish(tw_dev, request_id);
SCpnt->result = (DID_BAD_TARGET << 16);
done(SCpnt);
- goto out;
+ retval = 0;
}
if (retval) {
tw_dev->state[request_id] = TW_S_COMPLETED;
@@ -2069,7 +2050,6 @@ static int tw_scsi_queue(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd
done(SCpnt);
retval = 0;
}
-out:
return retval;
} /* End tw_scsi_queue() */
@@ -2088,183 +2068,180 @@ static irqreturn_t tw_interrupt(int irq, void *dev_instance,
/* Get the host lock for io completions */
spin_lock(tw_dev->host->host_lock);
- /* See if the interrupt matches this instance */
- if (tw_dev->tw_pci_dev->irq == (unsigned int)irq) {
+ /* Read the registers */
+ status_reg_value = inl(TW_STATUS_REG_ADDR(tw_dev));
- handled = 1;
+ /* Check if this is our interrupt, otherwise bail */
+ if (!(status_reg_value & TW_STATUS_VALID_INTERRUPT))
+ goto tw_interrupt_bail;
- /* Read the registers */
- status_reg_value = inl(TW_STATUS_REG_ADDR(tw_dev));
+ handled = 1;
- /* Check if this is our interrupt, otherwise bail */
- if (!(status_reg_value & TW_STATUS_VALID_INTERRUPT))
+ /* Check controller for errors */
+ if (tw_check_bits(status_reg_value)) {
+ dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Unexpected bits.\n");
+ if (tw_decode_bits(tw_dev, status_reg_value, 1)) {
+ TW_CLEAR_ALL_INTERRUPTS(tw_dev);
goto tw_interrupt_bail;
-
- /* Check controller for errors */
- if (tw_check_bits(status_reg_value)) {
- dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Unexpected bits.\n");
- if (tw_decode_bits(tw_dev, status_reg_value, 1)) {
- TW_CLEAR_ALL_INTERRUPTS(tw_dev);
- goto tw_interrupt_bail;
- }
}
+ }
- /* Handle host interrupt */
- if (status_reg_value & TW_STATUS_HOST_INTERRUPT) {
- dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): Received host interrupt.\n");
- TW_CLEAR_HOST_INTERRUPT(tw_dev);
- }
+ /* Handle host interrupt */
+ if (status_reg_value & TW_STATUS_HOST_INTERRUPT) {
+ dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): Received host interrupt.\n");
+ TW_CLEAR_HOST_INTERRUPT(tw_dev);
+ }
- /* Handle attention interrupt */
- if (status_reg_value & TW_STATUS_ATTENTION_INTERRUPT) {
- dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): Received attention interrupt.\n");
- TW_CLEAR_ATTENTION_INTERRUPT(tw_dev);
- tw_state_request_start(tw_dev, &request_id);
- error = tw_aen_read_queue(tw_dev, request_id);
- if (error) {
- printk(KERN_WARNING "3w-xxxx: scsi%d: Error reading aen queue.\n", tw_dev->host->host_no);
- tw_dev->state[request_id] = TW_S_COMPLETED;
- tw_state_request_finish(tw_dev, request_id);
- }
+ /* Handle attention interrupt */
+ if (status_reg_value & TW_STATUS_ATTENTION_INTERRUPT) {
+ dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): Received attention interrupt.\n");
+ TW_CLEAR_ATTENTION_INTERRUPT(tw_dev);
+ tw_state_request_start(tw_dev, &request_id);
+ error = tw_aen_read_queue(tw_dev, request_id);
+ if (error) {
+ printk(KERN_WARNING "3w-xxxx: scsi%d: Error reading aen queue.\n", tw_dev->host->host_no);
+ tw_dev->state[request_id] = TW_S_COMPLETED;
+ tw_state_request_finish(tw_dev, request_id);
}
+ }
- /* Handle command interrupt */
- if (status_reg_value & TW_STATUS_COMMAND_INTERRUPT) {
- /* Drain as many pending commands as we can */
- while (tw_dev->pending_request_count > 0) {
- request_id = tw_dev->pending_queue[tw_dev->pending_head];
- if (tw_dev->state[request_id] != TW_S_PENDING) {
- printk(KERN_WARNING "3w-xxxx: scsi%d: Found request id that wasn't pending.\n", tw_dev->host->host_no);
- break;
- }
- if (tw_post_command_packet(tw_dev, request_id)==0) {
- if (tw_dev->pending_head == TW_Q_LENGTH-1) {
- tw_dev->pending_head = TW_Q_START;
- } else {
- tw_dev->pending_head = tw_dev->pending_head + 1;
- }
- tw_dev->pending_request_count--;
+ /* Handle command interrupt */
+ if (status_reg_value & TW_STATUS_COMMAND_INTERRUPT) {
+ /* Drain as many pending commands as we can */
+ while (tw_dev->pending_request_count > 0) {
+ request_id = tw_dev->pending_queue[tw_dev->pending_head];
+ if (tw_dev->state[request_id] != TW_S_PENDING) {
+ printk(KERN_WARNING "3w-xxxx: scsi%d: Found request id that wasn't pending.\n", tw_dev->host->host_no);
+ break;
+ }
+ if (tw_post_command_packet(tw_dev, request_id)==0) {
+ if (tw_dev->pending_head == TW_Q_LENGTH-1) {
+ tw_dev->pending_head = TW_Q_START;
} else {
- /* If we get here, we will continue re-posting on the next command interrupt */
- break;
+ tw_dev->pending_head = tw_dev->pending_head + 1;
}
+ tw_dev->pending_request_count--;
+ } else {
+ /* If we get here, we will continue re-posting on the next command interrupt */
+ break;
}
- /* If there are no more pending requests, we mask command interrupt */
- if (tw_dev->pending_request_count == 0)
- TW_MASK_COMMAND_INTERRUPT(tw_dev);
}
-
- /* Handle response interrupt */
- if (status_reg_value & TW_STATUS_RESPONSE_INTERRUPT) {
- /* Drain the response queue from the board */
- while ((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) {
- /* Read response queue register */
- response_que.value = inl(TW_RESPONSE_QUEUE_REG_ADDR(tw_dev));
- request_id = TW_RESID_OUT(response_que.response_id);
- command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
- error = 0;
-
- /* Check for bad response */
- if (command_packet->status != 0) {
- /* If internal command, don't error, don't fill sense */
- if (tw_dev->srb[request_id] == NULL) {
- tw_decode_sense(tw_dev, request_id, 0);
- } else {
- error = tw_decode_sense(tw_dev, request_id, 1);
- }
+ /* If there are no more pending requests, we mask command interrupt */
+ if (tw_dev->pending_request_count == 0)
+ TW_MASK_COMMAND_INTERRUPT(tw_dev);
+ }
+
+ /* Handle response interrupt */
+ if (status_reg_value & TW_STATUS_RESPONSE_INTERRUPT) {
+ /* Drain the response queue from the board */
+ while ((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) {
+ /* Read response queue register */
+ response_que.value = inl(TW_RESPONSE_QUEUE_REG_ADDR(tw_dev));
+ request_id = TW_RESID_OUT(response_que.response_id);
+ command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
+ error = 0;
+
+ /* Check for bad response */
+ if (command_packet->status != 0) {
+ /* If internal command, don't error, don't fill sense */
+ if (tw_dev->srb[request_id] == NULL) {
+ tw_decode_sense(tw_dev, request_id, 0);
+ } else {
+ error = tw_decode_sense(tw_dev, request_id, 1);
}
+ }
- /* Check for correct state */
- if (tw_dev->state[request_id] != TW_S_POSTED) {
- if (tw_dev->srb[request_id] != NULL) {
- printk(KERN_WARNING "3w-xxxx: scsi%d: Received a request id that wasn't posted.\n", tw_dev->host->host_no);
- error = 1;
- }
+ /* Check for correct state */
+ if (tw_dev->state[request_id] != TW_S_POSTED) {
+ if (tw_dev->srb[request_id] != NULL) {
+ printk(KERN_WARNING "3w-xxxx: scsi%d: Received a request id that wasn't posted.\n", tw_dev->host->host_no);
+ error = 1;
}
+ }
- dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): Response queue request id: %d.\n", request_id);
+ dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): Response queue request id: %d.\n", request_id);
- /* Check for internal command completion */
- if (tw_dev->srb[request_id] == NULL) {
- dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Found internally posted command.\n");
- /* Check for chrdev ioctl completion */
- if (request_id != tw_dev->chrdev_request_id) {
- retval = tw_aen_complete(tw_dev, request_id);
- if (retval) {
- printk(KERN_WARNING "3w-xxxx: scsi%d: Error completing aen.\n", tw_dev->host->host_no);
- }
- } else {
- tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE;
- wake_up(&tw_dev->ioctl_wqueue);
+ /* Check for internal command completion */
+ if (tw_dev->srb[request_id] == NULL) {
+ dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Found internally posted command.\n");
+ /* Check for chrdev ioctl completion */
+ if (request_id != tw_dev->chrdev_request_id) {
+ retval = tw_aen_complete(tw_dev, request_id);
+ if (retval) {
+ printk(KERN_WARNING "3w-xxxx: scsi%d: Error completing aen.\n", tw_dev->host->host_no);
}
} else {
+ tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE;
+ wake_up(&tw_dev->ioctl_wqueue);
+ }
+ } else {
switch (tw_dev->srb[request_id]->cmnd[0]) {
- case READ_10:
- case READ_6:
- dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught READ_10/READ_6\n");
- break;
- case WRITE_10:
- case WRITE_6:
- dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught WRITE_10/WRITE_6\n");
- break;
- case TEST_UNIT_READY:
- dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught TEST_UNIT_READY\n");
- error = tw_scsiop_test_unit_ready_complete(tw_dev, request_id);
- break;
- case INQUIRY:
- dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught INQUIRY\n");
- error = tw_scsiop_inquiry_complete(tw_dev, request_id);
- break;
- case READ_CAPACITY:
- dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught READ_CAPACITY\n");
- error = tw_scsiop_read_capacity_complete(tw_dev, request_id);
- break;
- case MODE_SENSE:
- dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught MODE_SENSE\n");
- error = tw_scsiop_mode_sense_complete(tw_dev, request_id);
- break;
- case SYNCHRONIZE_CACHE:
- dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught SYNCHRONIZE_CACHE\n");
- break;
- default:
- printk(KERN_WARNING "3w-xxxx: case slip in tw_interrupt()\n");
- error = 1;
- }
-
- /* If no error command was a success */
- if (error == 0) {
- tw_dev->srb[request_id]->result = (DID_OK << 16);
- }
+ case READ_10:
+ case READ_6:
+ dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught READ_10/READ_6\n");
+ break;
+ case WRITE_10:
+ case WRITE_6:
+ dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught WRITE_10/WRITE_6\n");
+ break;
+ case TEST_UNIT_READY:
+ dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught TEST_UNIT_READY\n");
+ error = tw_scsiop_test_unit_ready_complete(tw_dev, request_id);
+ break;
+ case INQUIRY:
+ dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught INQUIRY\n");
+ error = tw_scsiop_inquiry_complete(tw_dev, request_id);
+ break;
+ case READ_CAPACITY:
+ dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught READ_CAPACITY\n");
+ error = tw_scsiop_read_capacity_complete(tw_dev, request_id);
+ break;
+ case MODE_SENSE:
+ dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught MODE_SENSE\n");
+ error = tw_scsiop_mode_sense_complete(tw_dev, request_id);
+ break;
+ case SYNCHRONIZE_CACHE:
+ dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught SYNCHRONIZE_CACHE\n");
+ break;
+ default:
+ printk(KERN_WARNING "3w-xxxx: case slip in tw_interrupt()\n");
+ error = 1;
+ }
- /* If error, command failed */
- if (error == 1) {
- /* Ask for a host reset */
- tw_dev->srb[request_id]->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
- }
+ /* If no error command was a success */
+ if (error == 0) {
+ tw_dev->srb[request_id]->result = (DID_OK << 16);
+ }
- /* Now complete the io */
- if ((error != TW_ISR_DONT_COMPLETE)) {
- tw_dev->state[request_id] = TW_S_COMPLETED;
- tw_state_request_finish(tw_dev, request_id);
- tw_dev->posted_request_count--;
- tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
+ /* If error, command failed */
+ if (error == 1) {
+ /* Ask for a host reset */
+ tw_dev->srb[request_id]->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
+ }
- tw_unmap_scsi_data(tw_dev->tw_pci_dev, tw_dev->srb[request_id]);
- }
+ /* Now complete the io */
+ if ((error != TW_ISR_DONT_COMPLETE)) {
+ tw_dev->state[request_id] = TW_S_COMPLETED;
+ tw_state_request_finish(tw_dev, request_id);
+ tw_dev->posted_request_count--;
+ tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
+
+ tw_unmap_scsi_data(tw_dev->tw_pci_dev, tw_dev->srb[request_id]);
}
+ }
- /* Check for valid status after each drain */
- status_reg_value = inl(TW_STATUS_REG_ADDR(tw_dev));
- if (tw_check_bits(status_reg_value)) {
- dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Unexpected bits.\n");
- if (tw_decode_bits(tw_dev, status_reg_value, 1)) {
- TW_CLEAR_ALL_INTERRUPTS(tw_dev);
- goto tw_interrupt_bail;
- }
+ /* Check for valid status after each drain */
+ status_reg_value = inl(TW_STATUS_REG_ADDR(tw_dev));
+ if (tw_check_bits(status_reg_value)) {
+ dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Unexpected bits.\n");
+ if (tw_decode_bits(tw_dev, status_reg_value, 1)) {
+ TW_CLEAR_ALL_INTERRUPTS(tw_dev);
+ goto tw_interrupt_bail;
}
}
}
}
+
tw_interrupt_bail:
spin_unlock(tw_dev->host->host_lock);
return IRQ_RETVAL(handled);
@@ -2304,6 +2281,7 @@ static struct scsi_host_template driver_template = {
.queuecommand = tw_scsi_queue,
.eh_host_reset_handler = tw_scsi_eh_reset,
.bios_param = tw_scsi_biosparam,
+ .change_queue_depth = tw_change_queue_depth,
.can_queue = TW_Q_LENGTH-2,
.this_id = -1,
.sg_tablesize = TW_MAX_SGL_LENGTH,
@@ -2311,7 +2289,6 @@ static struct scsi_host_template driver_template = {
.cmd_per_lun = TW_MAX_CMDS_PER_LUN,
.use_clustering = ENABLE_CLUSTERING,
.shost_attrs = tw_host_attrs,
- .sdev_attrs = tw_dev_attrs,
.emulated = 1
};
@@ -2438,23 +2415,24 @@ static void tw_remove(struct pci_dev *pdev)
scsi_remove_host(tw_dev->host);
- __tw_shutdown(tw_dev);
+ /* Unregister character device */
+ if (twe_major >= 0) {
+ unregister_chrdev(twe_major, "twe");
+ twe_major = -1;
+ }
/* Free up the IRQ */
free_irq(tw_dev->tw_pci_dev->irq, tw_dev);
+ /* Shutdown the card */
+ __tw_shutdown(tw_dev);
+
/* Free up the mem region */
pci_release_regions(pdev);
/* Free up device extension resources */
tw_free_device_extension(tw_dev);
- /* Unregister character device */
- if (twe_major >= 0) {
- unregister_chrdev(twe_major, "twe");
- twe_major = -1;
- }
-
scsi_host_put(tw_dev->host);
pci_disable_device(pdev);
tw_device_extension_count--;
diff --git a/drivers/scsi/3w-xxxx.h b/drivers/scsi/3w-xxxx.h
index df070a8f8d4fb..98bad773f2408 100644
--- a/drivers/scsi/3w-xxxx.h
+++ b/drivers/scsi/3w-xxxx.h
@@ -6,7 +6,7 @@
Arnaldo Carvalho de Melo <acme@conectiva.com.br>
Brad Strand <linux@3ware.com>
- Copyright (C) 1999-2004 3ware Inc.
+ Copyright (C) 1999-2005 3ware Inc.
Kernel compatiblity By: Andre Hedrick <andre@suse.com>
Non-Copyright (C) 2000 Andre Hedrick <andre@suse.com>
@@ -227,6 +227,7 @@ static unsigned char tw_sense_table[][4] =
#define TW_IN_RESET 2
#define TW_IN_CHRDEV_IOCTL 3
#define TW_MAX_SECTORS 256
+#define TW_MAX_IOCTL_SECTORS 512
#define TW_AEN_WAIT_TIME 1000
#define TW_IOCTL_WAIT_TIME (1 * HZ) /* 1 second */
#define TW_ISR_DONT_COMPLETE 2
@@ -397,7 +398,6 @@ typedef struct TAG_TW_Device_Extension {
unsigned long *alignment_virtual_address[TW_Q_LENGTH];
unsigned long alignment_physical_address[TW_Q_LENGTH];
int is_unit_present[TW_MAX_UNITS];
- int num_units;
unsigned long *command_packet_virtual_address[TW_Q_LENGTH];
unsigned long command_packet_physical_address[TW_Q_LENGTH];
struct pci_dev *tw_pci_dev;
diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c
index 8adef650d300a..a591fcb8aab13 100644
--- a/drivers/scsi/53c700.c
+++ b/drivers/scsi/53c700.c
@@ -296,8 +296,7 @@ NCR_700_get_SXFER(struct scsi_device *SDp)
struct Scsi_Host *
NCR_700_detect(struct scsi_host_template *tpnt,
- struct NCR_700_Host_Parameters *hostdata, struct device *dev,
- unsigned long irq, u8 scsi_id)
+ struct NCR_700_Host_Parameters *hostdata, struct device *dev)
{
dma_addr_t pScript, pSlots;
__u8 *memory;
@@ -393,8 +392,6 @@ NCR_700_detect(struct scsi_host_template *tpnt,
host->unique_id = hostdata->base;
host->base = hostdata->base;
hostdata->eh_complete = NULL;
- host->irq = irq;
- host->this_id = scsi_id;
host->hostdata[0] = (unsigned long)hostdata;
/* kick the chip */
NCR_700_writeb(0xff, host, CTEST9_REG);
@@ -415,28 +412,16 @@ NCR_700_detect(struct scsi_host_template *tpnt,
/* reset the chip */
NCR_700_chip_reset(host);
- if (request_irq(irq, NCR_700_intr, SA_SHIRQ, dev->bus_id, host)) {
- dev_printk(KERN_ERR, dev, "53c700: irq %lu request failed\n ",
- irq);
- goto out_put_host;
- }
-
if (scsi_add_host(host, dev)) {
dev_printk(KERN_ERR, dev, "53c700: scsi_add_host failed\n");
- goto out_release_irq;
+ scsi_host_put(host);
+ return NULL;
}
spi_signalling(host) = hostdata->differential ? SPI_SIGNAL_HVD :
SPI_SIGNAL_SE;
return host;
-
- out_release_irq:
- free_irq(irq, host);
- out_put_host:
- scsi_host_put(host);
-
- return NULL;
}
int
@@ -824,6 +809,7 @@ process_extended_message(struct Scsi_Host *host,
switch(hostdata->msgin[2]) {
case A_SDTR_MSG:
if(SCp != NULL && NCR_700_is_flag_set(SCp->device, NCR_700_DEV_BEGIN_SYNC_NEGOTIATION)) {
+ struct scsi_target *starget = SCp->device->sdev_target;
__u8 period = hostdata->msgin[3];
__u8 offset = hostdata->msgin[4];
@@ -831,22 +817,15 @@ process_extended_message(struct Scsi_Host *host,
offset = 0;
period = 0;
}
+
+ spi_offset(starget) = offset;
+ spi_period(starget) = period;
if(NCR_700_is_flag_set(SCp->device, NCR_700_DEV_PRINT_SYNC_NEGOTIATION)) {
- if(spi_offset(SCp->device->sdev_target) != 0)
- printk(KERN_INFO "scsi%d: (%d:%d) Synchronous at offset %d, period %dns\n",
- host->host_no, pun, lun,
- offset, period*4);
- else
- printk(KERN_INFO "scsi%d: (%d:%d) Asynchronous\n",
- host->host_no, pun, lun);
+ spi_display_xfer_agreement(starget);
NCR_700_clear_flag(SCp->device, NCR_700_DEV_PRINT_SYNC_NEGOTIATION);
}
-
- spi_offset(SCp->device->sdev_target) = offset;
- spi_period(SCp->device->sdev_target) = period;
-
NCR_700_set_flag(SCp->device, NCR_700_DEV_NEGOTIATED_SYNC);
NCR_700_clear_flag(SCp->device, NCR_700_DEV_BEGIN_SYNC_NEGOTIATION);
diff --git a/drivers/scsi/53c700.h b/drivers/scsi/53c700.h
index f7693d7c8eec5..df4aa30ae0aa1 100644
--- a/drivers/scsi/53c700.h
+++ b/drivers/scsi/53c700.h
@@ -60,8 +60,7 @@ struct NCR_700_Host_Parameters;
/* These are the externally used routines */
struct Scsi_Host *NCR_700_detect(struct scsi_host_template *,
- struct NCR_700_Host_Parameters *, struct device *,
- unsigned long, u8);
+ struct NCR_700_Host_Parameters *, struct device *);
int NCR_700_release(struct Scsi_Host *host);
irqreturn_t NCR_700_intr(int, void *, struct pt_regs *);
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 2d492fe4de15d..d22b32f4662d2 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -273,8 +273,8 @@ config SCSI_ACARD
tristate "ACARD SCSI support"
depends on PCI && SCSI
help
- This driver supports the ACARD 870U/W SCSI host adapter.
-
+ This driver supports the ACARD SCSI host adapter.
+ Support Chip <ATP870 ATP876 ATP880 ATP885>
To compile this driver as a module, choose M here: the
module will be called atp870u.
@@ -457,6 +457,14 @@ config SCSI_SATA_PROMISE
If unsure, say N.
+config SCSI_SATA_QSTOR
+ tristate "Pacific Digital SATA QStor support"
+ depends on SCSI_SATA && PCI
+ help
+ This option enables support for Pacific Digital Serial ATA QStor.
+
+ If unsure, say N.
+
config SCSI_SATA_SX4
tristate "Promise SATA SX4 support"
depends on SCSI_SATA && PCI && EXPERIMENTAL
@@ -611,7 +619,7 @@ config SCSI_EATA_MAX_TAGS
config SCSI_EATA_PIO
tristate "EATA-PIO (old DPT PM2001, PM2012A) support"
- depends on (ISA || EISA || PCI) && SCSI
+ depends on (ISA || EISA || PCI) && SCSI && BROKEN
---help---
This driver supports all EATA-PIO protocol compliant SCSI Host
Adapters like the DPT PM2001 and the PM2012A. EATA-DMA compliant
@@ -1249,7 +1257,7 @@ config SCSI_QLOGIC_FAS
config SCSI_QLOGIC_ISP
tristate "Qlogic ISP SCSI support (old driver)"
- depends on PCI && SCSI
+ depends on PCI && SCSI && BROKEN
---help---
This driver works for all QLogic PCI SCSI host adapters (IQ-PCI,
IQ-PCI-10, IQ_PCI-D) except for the PCI-basic card. (This latter
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 42fa1a91ce064..29fcee35ec01f 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -125,6 +125,7 @@ obj-$(CONFIG_SCSI_SATA_AHCI) += libata.o ahci.o
obj-$(CONFIG_SCSI_SATA_SVW) += libata.o sata_svw.o
obj-$(CONFIG_SCSI_ATA_PIIX) += libata.o ata_piix.o
obj-$(CONFIG_SCSI_SATA_PROMISE) += libata.o sata_promise.o
+obj-$(CONFIG_SCSI_SATA_QSTOR) += libata.o sata_qstor.o
obj-$(CONFIG_SCSI_SATA_SIL) += libata.o sata_sil.o
obj-$(CONFIG_SCSI_SATA_VIA) += libata.o sata_via.o
obj-$(CONFIG_SCSI_SATA_VITESSE) += libata.o sata_vsc.o
diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c
index 6b3d2b2ad8d1a..5e71a0beafca9 100644
--- a/drivers/scsi/NCR5380.c
+++ b/drivers/scsi/NCR5380.c
@@ -533,7 +533,7 @@ static int should_disconnect(unsigned char cmd)
static void NCR5380_set_timer(struct NCR5380_hostdata *hostdata, unsigned long timeout)
{
hostdata->time_expires = jiffies + timeout;
- schedule_delayed_work(&hostdata->coroutine, hostdata->time_expires);
+ schedule_delayed_work(&hostdata->coroutine, timeout);
}
@@ -671,16 +671,8 @@ static void __init NCR5380_print_options(struct Scsi_Host *instance)
static void NCR5380_print_status(struct Scsi_Host *instance)
{
- static char pr_bfr[512];
- char *start;
- int len;
-
NCR5380_dprint(NDEBUG_ANY, instance);
NCR5380_dprint_phase(NDEBUG_ANY, instance);
-
- len = NCR5380_proc_info(instance, pr_bfr, &start, 0, sizeof(pr_bfr), 0);
- pr_bfr[len] = 0;
- printk("\n%s\n", pr_bfr);
}
/******************************************/
@@ -2689,11 +2681,6 @@ static int NCR5380_abort(Scsi_Cmnd * cmd) {
NCR5380_print_status(instance);
- printk(KERN_WARNING "scsi%d : aborting command\n", instance->host_no);
- print_Scsi_Cmnd(cmd);
-
- NCR5380_print_status(instance);
-
NCR5380_setup(instance);
dprintk(NDEBUG_ABORT, ("scsi%d : abort called\n", instance->host_no));
diff --git a/drivers/scsi/NCR_D700.c b/drivers/scsi/NCR_D700.c
index 9161af9c4d14d..507751941f1e6 100644
--- a/drivers/scsi/NCR_D700.c
+++ b/drivers/scsi/NCR_D700.c
@@ -97,6 +97,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mca.h>
+#include <linux/interrupt.h>
#include <asm/io.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_device.h>
@@ -106,7 +107,7 @@
#include "53c700.h"
#include "NCR_D700.h"
-char *NCR_D700; /* command line from insmod */
+static char *NCR_D700; /* command line from insmod */
MODULE_AUTHOR("James Bottomley");
MODULE_DESCRIPTION("NCR Dual700 SCSI Driver");
@@ -168,11 +169,13 @@ static struct scsi_host_template NCR_D700_driver_template = {
struct NCR_D700_private {
struct device *dev;
struct Scsi_Host *hosts[2];
+ char name[30];
+ char pad;
};
static int
-NCR_D700_probe_one(struct NCR_D700_private *p, int siop,
- int irq, int slot, u32 region, int differential)
+NCR_D700_probe_one(struct NCR_D700_private *p, int siop, int irq,
+ int slot, u32 region, int differential)
{
struct NCR_700_Host_Parameters *hostdata;
struct Scsi_Host *host;
@@ -201,18 +204,18 @@ NCR_D700_probe_one(struct NCR_D700_private *p, int siop,
NCR_700_set_io_mapped(hostdata);
/* and register the siop */
- host = NCR_700_detect(&NCR_D700_driver_template, hostdata,
- p->dev, irq,
- /* FIXME: read this from SUS */
- id_array[slot * 2 + siop]);
+ host = NCR_700_detect(&NCR_D700_driver_template, hostdata, p->dev);
if (!host) {
ret = -ENOMEM;
goto detect_failed;
}
+ p->hosts[siop] = host;
+ /* FIXME: read this from SUS */
+ host->this_id = id_array[slot * 2 + siop];
+ host->irq = irq;
scsi_scan_host(host);
- p->hosts[siop] = host;
return 0;
detect_failed:
@@ -223,6 +226,20 @@ NCR_D700_probe_one(struct NCR_D700_private *p, int siop,
return ret;
}
+static int
+NCR_D700_intr(int irq, void *data, struct pt_regs *regs)
+{
+ struct NCR_D700_private *p = (struct NCR_D700_private *)data;
+ int i, found = 0;
+
+ for (i = 0; i < 2; i++)
+ if (p->hosts[i] &&
+ NCR_700_intr(irq, p->hosts[i], regs) == IRQ_HANDLED)
+ found++;
+
+ return found ? IRQ_HANDLED : IRQ_NONE;
+}
+
/* Detect a D700 card. Note, because of the setup --- the chips are
* essentially connectecd to the MCA bus independently, it is easier
* to set them up as two separate host adapters, rather than one
@@ -301,13 +318,19 @@ NCR_D700_probe(struct device *dev)
p = kmalloc(sizeof(*p), GFP_KERNEL);
if (!p)
return -ENOMEM;
+ memset(p, '\0', sizeof(*p));
p->dev = dev;
-
+ snprintf(p->name, sizeof(p->name), "D700(%s)", dev->bus_id);
+ if (request_irq(irq, NCR_D700_intr, SA_SHIRQ, p->name, p)) {
+ printk(KERN_ERR "D700: request_irq failed\n");
+ kfree(p);
+ return -EBUSY;
+ }
/* plumb in both 700 chips */
for (i = 0; i < 2; i++) {
int err;
- if ((err = NCR_D700_probe_one(p, i, irq, slot,
+ if ((err = NCR_D700_probe_one(p, i, slot, irq,
offset_addr + (0x80 * i),
differential)) != 0)
printk("D700: SIOP%d: probe failed, error = %d\n",
@@ -352,7 +375,7 @@ NCR_D700_remove(struct device *dev)
static short NCR_D700_id_table[] = { NCR_D700_MCA_ID, 0 };
-struct mca_driver NCR_D700_driver = {
+static struct mca_driver NCR_D700_driver = {
.id_table = NCR_D700_id_table,
.driver = {
.name = "NCR_D700",
diff --git a/drivers/scsi/NCR_Q720.c b/drivers/scsi/NCR_Q720.c
index 6237de419ba9c..9d18ec90510f6 100644
--- a/drivers/scsi/NCR_Q720.c
+++ b/drivers/scsi/NCR_Q720.c
@@ -225,7 +225,7 @@ NCR_Q720_probe(struct device *dev)
/* The first 1k of the memory buffer is a memory map of the registers
*/
- mem_base = (__u32)dma_mark_declared_memory_occupied(dev, base_addr,
+ mem_base = dma_mark_declared_memory_occupied(dev, base_addr,
1024);
if (IS_ERR(mem_base)) {
printk("NCR_Q720 failed to reserve memory mapped region\n");
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c
index aaf3d1983d64b..f3fc35386060c 100644
--- a/drivers/scsi/aacraid/aachba.c
+++ b/drivers/scsi/aacraid/aachba.c
@@ -195,10 +195,12 @@ int aac_get_config_status(struct aac_dev *dev)
= (struct aac_get_config_status_resp *) fib_data(fibptr);
dprintk((KERN_WARNING
"aac_get_config_status: response=%d status=%d action=%d\n",
- reply->response, reply->status, reply->data.action));
- if ((reply->response != ST_OK)
- || (reply->status != CT_OK)
- || (reply->data.action > CFACT_PAUSE)) {
+ le32_to_cpu(reply->response),
+ le32_to_cpu(reply->status),
+ le32_to_cpu(reply->data.action)));
+ if ((le32_to_cpu(reply->response) != ST_OK) ||
+ (le32_to_cpu(reply->status) != CT_OK) ||
+ (le32_to_cpu(reply->data.action) > CFACT_PAUSE)) {
printk(KERN_WARNING "aac_get_config_status: Will not issue the Commit Configuration\n");
status = -EINVAL;
}
@@ -265,7 +267,7 @@ int aac_get_containers(struct aac_dev *dev)
NULL, NULL);
if (status >= 0) {
dresp = (struct aac_get_container_count_resp *)fib_data(fibptr);
- maximum_num_containers = dresp->ContainerSwitchEntries;
+ maximum_num_containers = le32_to_cpu(dresp->ContainerSwitchEntries);
fib_complete(fibptr);
}
@@ -624,25 +626,28 @@ int aac_get_adapter_info(struct aac_dev* dev)
memcpy(&dev->adapter_info, info, sizeof(struct aac_adapter_info));
- tmp = dev->adapter_info.kernelrev;
- printk(KERN_INFO"%s%d: kernel %d.%d.%d build %d\n",
+ tmp = le32_to_cpu(dev->adapter_info.kernelrev);
+ printk(KERN_INFO "%s%d: kernel %d.%d-%d[%d]\n",
+ dev->name,
+ dev->id,
+ tmp>>24,
+ (tmp>>16)&0xff,
+ tmp&0xff,
+ le32_to_cpu(dev->adapter_info.kernelbuild));
+ tmp = le32_to_cpu(dev->adapter_info.monitorrev);
+ printk(KERN_INFO "%s%d: monitor %d.%d-%d[%d]\n",
dev->name, dev->id,
- tmp>>24,(tmp>>16)&0xff,(tmp>>8)&0xff,
- dev->adapter_info.kernelbuild);
- tmp = dev->adapter_info.monitorrev;
- printk(KERN_INFO"%s%d: monitor %d.%d.%d build %d\n",
+ tmp>>24,(tmp>>16)&0xff,tmp&0xff,
+ le32_to_cpu(dev->adapter_info.monitorbuild));
+ tmp = le32_to_cpu(dev->adapter_info.biosrev);
+ printk(KERN_INFO "%s%d: bios %d.%d-%d[%d]\n",
dev->name, dev->id,
- tmp>>24,(tmp>>16)&0xff,(tmp>>8)&0xff,
- dev->adapter_info.monitorbuild);
- tmp = dev->adapter_info.biosrev;
- printk(KERN_INFO"%s%d: bios %d.%d.%d build %d\n",
+ tmp>>24,(tmp>>16)&0xff,tmp&0xff,
+ le32_to_cpu(dev->adapter_info.biosbuild));
+ if (le32_to_cpu(dev->adapter_info.serial[0]) != 0xBAD0)
+ printk(KERN_INFO "%s%d: serial %x\n",
dev->name, dev->id,
- tmp>>24,(tmp>>16)&0xff,(tmp>>8)&0xff,
- dev->adapter_info.biosbuild);
- printk(KERN_INFO"%s%d: serial %x%x\n",
- dev->name, dev->id,
- dev->adapter_info.serial[0],
- dev->adapter_info.serial[1]);
+ le32_to_cpu(dev->adapter_info.serial[0]));
dev->nondasd_support = 0;
dev->raid_scsi_mode = 0;
@@ -742,7 +747,8 @@ static void read_callback(void *context, struct fib * fibptr)
if (le32_to_cpu(readreply->status) == ST_OK)
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
else {
- printk(KERN_WARNING "read_callback: read failed, status = %d\n", readreply->status);
+ printk(KERN_WARNING "read_callback: read failed, status = %d\n",
+ le32_to_cpu(readreply->status));
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION;
set_sense((u8 *) &dev->fsa_dev[cid].sense_data,
HARDWARE_ERROR,
@@ -853,13 +859,15 @@ int aac_read(struct scsi_cmnd * scsicmd, int cid)
readcmd->cid = cpu_to_le16(cid);
readcmd->sector_count = cpu_to_le16(count);
readcmd->block = cpu_to_le32(lba);
- readcmd->pad = cpu_to_le16(0);
- readcmd->flags = cpu_to_le16(0);
+ readcmd->pad = 0;
+ readcmd->flags = 0;
aac_build_sg64(scsicmd, &readcmd->sg);
- if(readcmd->sg.count > MAX_DRIVER_SG_SEGMENT_COUNT)
- BUG();
- fibsize = sizeof(struct aac_read64) + ((readcmd->sg.count - 1) * sizeof (struct sgentry64));
+ fibsize = sizeof(struct aac_read64) +
+ ((le32_to_cpu(readcmd->sg.count) - 1) *
+ sizeof (struct sgentry64));
+ BUG_ON (fibsize > (sizeof(struct hw_fib) -
+ sizeof(struct aac_fibhdr)));
/*
* Now send the Fib to the adapter
*/
@@ -882,9 +890,11 @@ int aac_read(struct scsi_cmnd * scsicmd, int cid)
BUG();
aac_build_sg(scsicmd, &readcmd->sg);
- if(readcmd->sg.count > MAX_DRIVER_SG_SEGMENT_COUNT)
- BUG();
- fibsize = sizeof(struct aac_read) + ((readcmd->sg.count - 1) * sizeof (struct sgentry));
+ fibsize = sizeof(struct aac_read) +
+ ((le32_to_cpu(readcmd->sg.count) - 1) *
+ sizeof (struct sgentry));
+ BUG_ON (fibsize > (sizeof(struct hw_fib) -
+ sizeof(struct aac_fibhdr)));
/*
* Now send the Fib to the adapter
*/
@@ -903,10 +913,7 @@ int aac_read(struct scsi_cmnd * scsicmd, int cid)
* Check that the command queued to the controller
*/
if (status == -EINPROGRESS)
- {
- dprintk("read queued.\n");
return 0;
- }
printk(KERN_WARNING "aac_read: fib_send failed with status: %d.\n", status);
/*
@@ -943,7 +950,8 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
lba = (scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16) | (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5];
count = (scsicmd->cmnd[7] << 8) | scsicmd->cmnd[8];
}
- dprintk((KERN_DEBUG "aac_write[cpu %d]: lba = %u, t = %ld.\n", smp_processor_id(), lba, jiffies));
+ dprintk((KERN_DEBUG "aac_write[cpu %d]: lba = %u, t = %ld.\n",
+ smp_processor_id(), (unsigned long long)lba, jiffies));
/*
* Allocate and initialize a Fib then setup a BlockWrite command
*/
@@ -961,13 +969,15 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
writecmd->cid = cpu_to_le16(cid);
writecmd->sector_count = cpu_to_le16(count);
writecmd->block = cpu_to_le32(lba);
- writecmd->pad = cpu_to_le16(0);
- writecmd->flags = cpu_to_le16(0);
+ writecmd->pad = 0;
+ writecmd->flags = 0;
aac_build_sg64(scsicmd, &writecmd->sg);
- if(writecmd->sg.count > MAX_DRIVER_SG_SEGMENT_COUNT)
- BUG();
- fibsize = sizeof(struct aac_write64) + ((writecmd->sg.count - 1) * sizeof (struct sgentry64));
+ fibsize = sizeof(struct aac_write64) +
+ ((le32_to_cpu(writecmd->sg.count) - 1) *
+ sizeof (struct sgentry64));
+ BUG_ON (fibsize > (sizeof(struct hw_fib) -
+ sizeof(struct aac_fibhdr)));
/*
* Now send the Fib to the adapter
*/
@@ -993,9 +1003,11 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
}
aac_build_sg(scsicmd, &writecmd->sg);
- if(writecmd->sg.count > MAX_DRIVER_SG_SEGMENT_COUNT)
- BUG();
- fibsize = sizeof(struct aac_write) + ((writecmd->sg.count - 1) * sizeof (struct sgentry));
+ fibsize = sizeof(struct aac_write) +
+ ((le32_to_cpu(writecmd->sg.count) - 1) *
+ sizeof (struct sgentry));
+ BUG_ON (fibsize > (sizeof(struct hw_fib) -
+ sizeof(struct aac_fibhdr)));
/*
* Now send the Fib to the adapter
*/
@@ -1051,7 +1063,7 @@ static void synchronize_callback(void *context, struct fib *fibptr)
u32 cid = ID_LUN_TO_CONTAINER(sdev->id, sdev->lun);
printk(KERN_WARNING
"synchronize_callback: synchronize failed, status = %d\n",
- synchronizereply->status);
+ le32_to_cpu(synchronizereply->status));
cmd->result = DID_OK << 16 |
COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION;
set_sense((u8 *)&dev->fsa_dev[cid].sense_data,
@@ -1538,7 +1550,8 @@ static void aac_srb_callback(void *context, struct fib * fibptr)
* Calculate resid for sg
*/
- scsicmd->resid = scsicmd->request_bufflen - srbreply->data_xfer_length;
+ scsicmd->resid = scsicmd->request_bufflen -
+ le32_to_cpu(srbreply->data_xfer_length);
if(scsicmd->use_sg)
pci_unmap_sg(dev->pdev,
@@ -1556,8 +1569,10 @@ static void aac_srb_callback(void *context, struct fib * fibptr)
if (le32_to_cpu(srbreply->status) != ST_OK){
int len;
printk(KERN_WARNING "aac_srb_callback: srb failed, status = %d\n", le32_to_cpu(srbreply->status));
- len = (srbreply->sense_data_size > sizeof(scsicmd->sense_buffer))?
- sizeof(scsicmd->sense_buffer):srbreply->sense_data_size;
+ len = (le32_to_cpu(srbreply->sense_data_size) >
+ sizeof(scsicmd->sense_buffer)) ?
+ sizeof(scsicmd->sense_buffer) :
+ le32_to_cpu(srbreply->sense_data_size);
scsicmd->result = DID_ERROR << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION;
memcpy(scsicmd->sense_buffer, srbreply->sense_data, len);
}
@@ -1693,7 +1708,7 @@ static void aac_srb_callback(void *context, struct fib * fibptr)
default:
#ifdef AAC_DETAILED_STATUS_INFO
printk("aacraid: SRB ERROR(%u) %s scsi cmd 0x%x - scsi status 0x%x\n",
- le32_to_cpu(srbreply->srb_status & 0x3F),
+ le32_to_cpu(srbreply->srb_status) & 0x3F,
aac_get_status_string(
le32_to_cpu(srbreply->srb_status) & 0x3F),
scsicmd->cmnd[0],
@@ -1705,8 +1720,10 @@ static void aac_srb_callback(void *context, struct fib * fibptr)
if (le32_to_cpu(srbreply->scsi_status) == 0x02 ){ // Check Condition
int len;
scsicmd->result |= SAM_STAT_CHECK_CONDITION;
- len = (srbreply->sense_data_size > sizeof(scsicmd->sense_buffer))?
- sizeof(scsicmd->sense_buffer):srbreply->sense_data_size;
+ len = (le32_to_cpu(srbreply->sense_data_size) >
+ sizeof(scsicmd->sense_buffer)) ?
+ sizeof(scsicmd->sense_buffer) :
+ le32_to_cpu(srbreply->sense_data_size);
#ifdef AAC_DETAILED_STATUS_INFO
dprintk((KERN_WARNING "aac_srb_callback: check condition, status = %d len=%d\n",
le32_to_cpu(srbreply->status), len));
@@ -1786,7 +1803,7 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd)
timeout = 1;
}
srbcmd->timeout = cpu_to_le32(timeout); // timeout in seconds
- srbcmd->retry_limit =cpu_to_le32(0); // Obsolete parameter
+ srbcmd->retry_limit = 0; /* Obsolete parameter */
srbcmd->cdb_size = cpu_to_le32(scsicmd->cmd_len);
if( dev->dac_support == 1 ) {
@@ -1798,13 +1815,19 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd)
/*
* Build Scatter/Gather list
*/
- fibsize = sizeof (struct aac_srb) + (((srbcmd->sg.count & 0xff) - 1) * sizeof (struct sgentry64));
+ fibsize = sizeof (struct aac_srb) - sizeof (struct sgentry) +
+ ((le32_to_cpu(srbcmd->sg.count) & 0xff) *
+ sizeof (struct sgentry64));
+ BUG_ON (fibsize > (sizeof(struct hw_fib) -
+ sizeof(struct aac_fibhdr)));
/*
* Now send the Fib to the adapter
*/
- status = fib_send(ScsiPortCommand64, cmd_fibcontext, fibsize, FsaNormal, 0, 1,
- (fib_callback) aac_srb_callback, (void *) scsicmd);
+ status = fib_send(ScsiPortCommand64, cmd_fibcontext,
+ fibsize, FsaNormal, 0, 1,
+ (fib_callback) aac_srb_callback,
+ (void *) scsicmd);
} else {
aac_build_sg(scsicmd, (struct sgmap*)&srbcmd->sg);
srbcmd->count = cpu_to_le32(scsicmd->request_bufflen);
@@ -1814,7 +1837,11 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd)
/*
* Build Scatter/Gather list
*/
- fibsize = sizeof (struct aac_srb) + (((srbcmd->sg.count & 0xff) - 1) * sizeof (struct sgentry));
+ fibsize = sizeof (struct aac_srb) +
+ (((le32_to_cpu(srbcmd->sg.count) & 0xff) - 1) *
+ sizeof (struct sgentry));
+ BUG_ON (fibsize > (sizeof(struct hw_fib) -
+ sizeof(struct aac_fibhdr)));
/*
* Now send the Fib to the adapter
@@ -1843,9 +1870,9 @@ static unsigned long aac_build_sg(struct scsi_cmnd* scsicmd, struct sgmap* psg)
dev = (struct aac_dev *)scsicmd->device->host->hostdata;
// Get rid of old data
- psg->count = cpu_to_le32(0);
- psg->sg[0].addr = cpu_to_le32(0);
- psg->sg[0].count = cpu_to_le32(0);
+ psg->count = 0;
+ psg->sg[0].addr = 0;
+ psg->sg[0].count = 0;
if (scsicmd->use_sg) {
struct scatterlist *sg;
int i;
@@ -1899,10 +1926,10 @@ static unsigned long aac_build_sg64(struct scsi_cmnd* scsicmd, struct sgmap64* p
dev = (struct aac_dev *)scsicmd->device->host->hostdata;
// Get rid of old data
- psg->count = cpu_to_le32(0);
- psg->sg[0].addr[0] = cpu_to_le32(0);
- psg->sg[0].addr[1] = cpu_to_le32(0);
- psg->sg[0].count = cpu_to_le32(0);
+ psg->count = 0;
+ psg->sg[0].addr[0] = 0;
+ psg->sg[0].addr[1] = 0;
+ psg->sg[0].count = 0;
if (scsicmd->use_sg) {
struct scatterlist *sg;
int i;
diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h
index 7309129568b68..700d90331c1cd 100644
--- a/drivers/scsi/aacraid/aacraid.h
+++ b/drivers/scsi/aacraid/aacraid.h
@@ -507,40 +507,32 @@ struct aac_queue_block
*/
struct sa_drawbridge_CSR {
- // Offset | Name
- u32 reserved[10]; // 00h-27h | Reserved
- u8 LUT_Offset; // 28h | Looup Table Offset
- u8 reserved1[3]; // 29h-2bh | Reserved
- u32 LUT_Data; // 2ch | Looup Table Data
- u32 reserved2[26]; // 30h-97h | Reserved
- u16 PRICLEARIRQ; // 98h | Primary Clear Irq
- u16 SECCLEARIRQ; // 9ah | Secondary Clear Irq
- u16 PRISETIRQ; // 9ch | Primary Set Irq
- u16 SECSETIRQ; // 9eh | Secondary Set Irq
- u16 PRICLEARIRQMASK; // a0h | Primary Clear Irq Mask
- u16 SECCLEARIRQMASK; // a2h | Secondary Clear Irq Mask
- u16 PRISETIRQMASK; // a4h | Primary Set Irq Mask
- u16 SECSETIRQMASK; // a6h | Secondary Set Irq Mask
- u32 MAILBOX0; // a8h | Scratchpad 0
- u32 MAILBOX1; // ach | Scratchpad 1
- u32 MAILBOX2; // b0h | Scratchpad 2
- u32 MAILBOX3; // b4h | Scratchpad 3
- u32 MAILBOX4; // b8h | Scratchpad 4
- u32 MAILBOX5; // bch | Scratchpad 5
- u32 MAILBOX6; // c0h | Scratchpad 6
- u32 MAILBOX7; // c4h | Scratchpad 7
-
- u32 ROM_Setup_Data; // c8h | Rom Setup and Data
- u32 ROM_Control_Addr; // cch | Rom Control and Address
-
- u32 reserved3[12]; // d0h-ffh | reserved
- u32 LUT[64]; // 100h-1ffh| Lookup Table Entries
-
- //
- // TO DO
- // need to add DMA, I2O, UART, etc registers form 80h to 364h
- //
-
+ /* Offset | Name */
+ __le32 reserved[10]; /* 00h-27h | Reserved */
+ u8 LUT_Offset; /* 28h | Lookup Table Offset */
+ u8 reserved1[3]; /* 29h-2bh | Reserved */
+ __le32 LUT_Data; /* 2ch | Looup Table Data */
+ __le32 reserved2[26]; /* 30h-97h | Reserved */
+ __le16 PRICLEARIRQ; /* 98h | Primary Clear Irq */
+ __le16 SECCLEARIRQ; /* 9ah | Secondary Clear Irq */
+ __le16 PRISETIRQ; /* 9ch | Primary Set Irq */
+ __le16 SECSETIRQ; /* 9eh | Secondary Set Irq */
+ __le16 PRICLEARIRQMASK;/* a0h | Primary Clear Irq Mask */
+ __le16 SECCLEARIRQMASK;/* a2h | Secondary Clear Irq Mask */
+ __le16 PRISETIRQMASK; /* a4h | Primary Set Irq Mask */
+ __le16 SECSETIRQMASK; /* a6h | Secondary Set Irq Mask */
+ __le32 MAILBOX0; /* a8h | Scratchpad 0 */
+ __le32 MAILBOX1; /* ach | Scratchpad 1 */
+ __le32 MAILBOX2; /* b0h | Scratchpad 2 */
+ __le32 MAILBOX3; /* b4h | Scratchpad 3 */
+ __le32 MAILBOX4; /* b8h | Scratchpad 4 */
+ __le32 MAILBOX5; /* bch | Scratchpad 5 */
+ __le32 MAILBOX6; /* c0h | Scratchpad 6 */
+ __le32 MAILBOX7; /* c4h | Scratchpad 7 */
+ __le32 ROM_Setup_Data; /* c8h | Rom Setup and Data */
+ __le32 ROM_Control_Addr;/* cch | Rom Control and Address */
+ __le32 reserved3[12]; /* d0h-ffh | reserved */
+ __le32 LUT[64]; /* 100h-1ffh | Lookup Table Entries */
};
#define Mailbox0 SaDbCSR.MAILBOX0
@@ -556,13 +548,13 @@ struct sa_drawbridge_CSR {
#define DoorbellClrReg_p SaDbCSR.PRICLEARIRQ
-#define DOORBELL_0 cpu_to_le16(0x0001)
-#define DOORBELL_1 cpu_to_le16(0x0002)
-#define DOORBELL_2 cpu_to_le16(0x0004)
-#define DOORBELL_3 cpu_to_le16(0x0008)
-#define DOORBELL_4 cpu_to_le16(0x0010)
-#define DOORBELL_5 cpu_to_le16(0x0020)
-#define DOORBELL_6 cpu_to_le16(0x0040)
+#define DOORBELL_0 0x0001
+#define DOORBELL_1 0x0002
+#define DOORBELL_2 0x0004
+#define DOORBELL_3 0x0008
+#define DOORBELL_4 0x0010
+#define DOORBELL_5 0x0020
+#define DOORBELL_6 0x0040
#define PrintfReady DOORBELL_5
@@ -585,25 +577,29 @@ struct sa_registers {
*/
struct rx_mu_registers {
- // Local | PCI* | Name
- // | |
- u32 ARSR; // 1300h | 00h | APIC Register Select Register
- u32 reserved0; // 1304h | 04h | Reserved
- u32 AWR; // 1308h | 08h | APIC Window Register
- u32 reserved1; // 130Ch | 0Ch | Reserved
- u32 IMRx[2]; // 1310h | 10h | Inbound Message Registers
- u32 OMRx[2]; // 1318h | 18h | Outbound Message Registers
- u32 IDR; // 1320h | 20h | Inbound Doorbell Register
- u32 IISR; // 1324h | 24h | Inbound Interrupt Status Register
- u32 IIMR; // 1328h | 28h | Inbound Interrupt Mask Register
- u32 ODR; // 132Ch | 2Ch | Outbound Doorbell Register
- u32 OISR; // 1330h | 30h | Outbound Interrupt Status Register
- u32 OIMR; // 1334h | 34h | Outbound Interrupt Mask Register
- // * Must access through ATU Inbound Translation Window
+ /* Local | PCI*| Name */
+ __le32 ARSR; /* 1300h | 00h | APIC Register Select Register */
+ __le32 reserved0; /* 1304h | 04h | Reserved */
+ __le32 AWR; /* 1308h | 08h | APIC Window Register */
+ __le32 reserved1; /* 130Ch | 0Ch | Reserved */
+ __le32 IMRx[2]; /* 1310h | 10h | Inbound Message Registers */
+ __le32 OMRx[2]; /* 1318h | 18h | Outbound Message Registers */
+ __le32 IDR; /* 1320h | 20h | Inbound Doorbell Register */
+ __le32 IISR; /* 1324h | 24h | Inbound Interrupt
+ Status Register */
+ __le32 IIMR; /* 1328h | 28h | Inbound Interrupt
+ Mask Register */
+ __le32 ODR; /* 132Ch | 2Ch | Outbound Doorbell Register */
+ __le32 OISR; /* 1330h | 30h | Outbound Interrupt
+ Status Register */
+ __le32 OIMR; /* 1334h | 34h | Outbound Interrupt
+ Mask Register */
+ /* * Must access through ATU Inbound
+ Translation Window */
};
struct rx_inbound {
- u32 Mailbox[8];
+ __le32 Mailbox[8];
};
#define InboundMailbox0 IndexRegs.Mailbox[0]
@@ -613,28 +609,27 @@ struct rx_inbound {
#define InboundMailbox4 IndexRegs.Mailbox[4]
#define InboundMailbox5 IndexRegs.Mailbox[5]
#define InboundMailbox6 IndexRegs.Mailbox[6]
-#define InboundMailbox7 IndexRegs.Mailbox[7]
-
-#define INBOUNDDOORBELL_0 cpu_to_le32(0x00000001)
-#define INBOUNDDOORBELL_1 cpu_to_le32(0x00000002)
-#define INBOUNDDOORBELL_2 cpu_to_le32(0x00000004)
-#define INBOUNDDOORBELL_3 cpu_to_le32(0x00000008)
-#define INBOUNDDOORBELL_4 cpu_to_le32(0x00000010)
-#define INBOUNDDOORBELL_5 cpu_to_le32(0x00000020)
-#define INBOUNDDOORBELL_6 cpu_to_le32(0x00000040)
-
-#define OUTBOUNDDOORBELL_0 cpu_to_le32(0x00000001)
-#define OUTBOUNDDOORBELL_1 cpu_to_le32(0x00000002)
-#define OUTBOUNDDOORBELL_2 cpu_to_le32(0x00000004)
-#define OUTBOUNDDOORBELL_3 cpu_to_le32(0x00000008)
-#define OUTBOUNDDOORBELL_4 cpu_to_le32(0x00000010)
+
+#define INBOUNDDOORBELL_0 0x00000001
+#define INBOUNDDOORBELL_1 0x00000002
+#define INBOUNDDOORBELL_2 0x00000004
+#define INBOUNDDOORBELL_3 0x00000008
+#define INBOUNDDOORBELL_4 0x00000010
+#define INBOUNDDOORBELL_5 0x00000020
+#define INBOUNDDOORBELL_6 0x00000040
+
+#define OUTBOUNDDOORBELL_0 0x00000001
+#define OUTBOUNDDOORBELL_1 0x00000002
+#define OUTBOUNDDOORBELL_2 0x00000004
+#define OUTBOUNDDOORBELL_3 0x00000008
+#define OUTBOUNDDOORBELL_4 0x00000010
#define InboundDoorbellReg MUnit.IDR
#define OutboundDoorbellReg MUnit.ODR
struct rx_registers {
- struct rx_mu_registers MUnit; // 1300h - 1334h
- u32 reserved1[6]; // 1338h - 134ch
+ struct rx_mu_registers MUnit; /* 1300h - 1334h */
+ __le32 reserved1[6]; /* 1338h - 134ch */
struct rx_inbound IndexRegs;
};
@@ -652,7 +647,7 @@ struct rx_registers {
struct rkt_registers {
struct rkt_mu_registers MUnit; /* 1300h - 1334h */
- u32 reserved1[1010]; /* 1338h - 22fch */
+ __le32 reserved1[1010]; /* 1338h - 22fch */
struct rkt_inbound IndexRegs; /* 2300h - */
};
@@ -824,6 +819,9 @@ struct aac_adapter_info
#define AAC_OPT_NONDASD cpu_to_le32(1<<12)
#define AAC_OPT_SCSI_MANAGED cpu_to_le32(1<<13)
#define AAC_OPT_RAID_SCSI_MODE cpu_to_le32(1<<14)
+#define AAC_OPT_SUPPLEMENT_ADAPTER_INFO cpu_to_le32(1<<16)
+#define AAC_OPT_NEW_COMM cpu_to_le32(1<<17)
+#define AAC_OPT_NEW_COMM_64 cpu_to_le32(1<<18)
struct aac_dev
{
@@ -1482,15 +1480,19 @@ extern struct aac_common aac_config;
* Monitor/Kernel API
*/
-#define BREAKPOINT_REQUEST cpu_to_le32(0x00000004)
-#define INIT_STRUCT_BASE_ADDRESS cpu_to_le32(0x00000005)
-#define READ_PERMANENT_PARAMETERS cpu_to_le32(0x0000000a)
-#define WRITE_PERMANENT_PARAMETERS cpu_to_le32(0x0000000b)
-#define HOST_CRASHING cpu_to_le32(0x0000000d)
-#define SEND_SYNCHRONOUS_FIB cpu_to_le32(0x0000000c)
-#define COMMAND_POST_RESULTS cpu_to_le32(0x00000014)
-#define GET_ADAPTER_PROPERTIES cpu_to_le32(0x00000019)
-#define RE_INIT_ADAPTER cpu_to_le32(0x000000ee)
+#define BREAKPOINT_REQUEST 0x00000004
+#define INIT_STRUCT_BASE_ADDRESS 0x00000005
+#define READ_PERMANENT_PARAMETERS 0x0000000a
+#define WRITE_PERMANENT_PARAMETERS 0x0000000b
+#define HOST_CRASHING 0x0000000d
+#define SEND_SYNCHRONOUS_FIB 0x0000000c
+#define COMMAND_POST_RESULTS 0x00000014
+#define GET_ADAPTER_PROPERTIES 0x00000019
+#define GET_DRIVER_BUFFER_PROPERTIES 0x00000023
+#define RCV_TEMP_READINGS 0x00000025
+#define GET_COMM_PREFERRED_SETTINGS 0x00000026
+#define IOP_RESET 0x00001000
+#define RE_INIT_ADAPTER 0x000000ee
/*
* Adapter Status Register
@@ -1513,22 +1515,22 @@ extern struct aac_common aac_config;
* Phases are bit oriented. It is NOT valid to have multiple bits set
*/
-#define SELF_TEST_FAILED (cpu_to_le32(0x00000004))
-#define MONITOR_PANIC (cpu_to_le32(0x00000020))
-#define KERNEL_UP_AND_RUNNING (cpu_to_le32(0x00000080))
-#define KERNEL_PANIC (cpu_to_le32(0x00000100))
+#define SELF_TEST_FAILED 0x00000004
+#define MONITOR_PANIC 0x00000020
+#define KERNEL_UP_AND_RUNNING 0x00000080
+#define KERNEL_PANIC 0x00000100
/*
* Doorbell bit defines
*/
-#define DoorBellSyncCmdAvailable cpu_to_le32(1<<0) // Host -> Adapter
-#define DoorBellPrintfDone cpu_to_le32(1<<5) // Host -> Adapter
-#define DoorBellAdapterNormCmdReady cpu_to_le32(1<<1) // Adapter -> Host
-#define DoorBellAdapterNormRespReady cpu_to_le32(1<<2) // Adapter -> Host
-#define DoorBellAdapterNormCmdNotFull cpu_to_le32(1<<3) // Adapter -> Host
-#define DoorBellAdapterNormRespNotFull cpu_to_le32(1<<4) // Adapter -> Host
-#define DoorBellPrintfReady cpu_to_le32(1<<5) // Adapter -> Host
+#define DoorBellSyncCmdAvailable (1<<0) /* Host -> Adapter */
+#define DoorBellPrintfDone (1<<5) /* Host -> Adapter */
+#define DoorBellAdapterNormCmdReady (1<<1) /* Adapter -> Host */
+#define DoorBellAdapterNormRespReady (1<<2) /* Adapter -> Host */
+#define DoorBellAdapterNormCmdNotFull (1<<3) /* Adapter -> Host */
+#define DoorBellAdapterNormRespNotFull (1<<4) /* Adapter -> Host */
+#define DoorBellPrintfReady (1<<5) /* Adapter -> Host */
/*
* For FIB communication, we need all of the following things
@@ -1599,7 +1601,6 @@ void fib_dealloc(struct fib * context);
void aac_printf(struct aac_dev *dev, u32 val);
int fib_send(u16 command, struct fib * context, unsigned long size, int priority, int wait, int reply, fib_callback callback, void *ctxt);
int aac_consumer_get(struct aac_dev * dev, struct aac_queue * q, struct aac_entry **entry);
-int aac_consumer_avail(struct aac_dev * dev, struct aac_queue * q);
void aac_consumer_free(struct aac_dev * dev, struct aac_queue * q, u32 qnum);
int fib_complete(struct fib * context);
#define fib_data(fibctx) ((void *)(fibctx)->hw_fib->data)
diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c
index 7f3a22200af4d..30dd1f7120f4b 100644
--- a/drivers/scsi/aacraid/commctrl.c
+++ b/drivers/scsi/aacraid/commctrl.c
@@ -74,12 +74,14 @@ static int ioctl_send_fib(struct aac_dev * dev, void __user *arg)
* will not overrun the buffer when we copy the memory. Return
* an error if we would.
*/
- if(le32_to_cpu(kfib->header.Size) > sizeof(struct hw_fib) - sizeof(struct aac_fibhdr)) {
+ if (le16_to_cpu(kfib->header.Size) >
+ sizeof(struct hw_fib) - sizeof(struct aac_fibhdr)) {
fib_free(fibptr);
return -EINVAL;
}
- if (copy_from_user((void *) kfib, arg, le32_to_cpu(kfib->header.Size) + sizeof(struct aac_fibhdr))) {
+ if (copy_from_user(kfib, arg, le16_to_cpu(kfib->header.Size) +
+ sizeof(struct aac_fibhdr))) {
fib_free(fibptr);
return -EFAULT;
}
@@ -93,7 +95,7 @@ static int ioctl_send_fib(struct aac_dev * dev, void __user *arg)
kfib->header.XferState = 0;
} else {
int retval = fib_send(kfib->header.Command, fibptr,
- le32_to_cpu(kfib->header.Size) , FsaNormal,
+ le16_to_cpu(kfib->header.Size) , FsaNormal,
1, 1, NULL, NULL);
if (retval) {
fib_free(fibptr);
@@ -538,7 +540,9 @@ int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
struct sgmap* psg = &srbcmd->sg;
byte_count = 0;
- actual_fibsize = sizeof (struct aac_srb) + (((srbcmd->sg.count & 0xff) - 1) * sizeof (struct sgentry));
+ actual_fibsize = sizeof (struct aac_srb) +
+ (((le32_to_cpu(srbcmd->sg.count) & 0xff) - 1) *
+ sizeof (struct sgentry));
if(actual_fibsize != fibsize){ // User made a mistake - should not continue
printk(KERN_DEBUG"aacraid: Bad Size specified in Raw SRB command\n");
rcode = -EINVAL;
diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c
index d3ca7a37e489d..6832a55ca907b 100644
--- a/drivers/scsi/aacraid/comminit.c
+++ b/drivers/scsi/aacraid/comminit.c
@@ -83,7 +83,7 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co
*/
dev->aif_base_va = (struct hw_fib *)base;
- init->AdapterFibsVirtualAddress = cpu_to_le32(0);
+ init->AdapterFibsVirtualAddress = 0;
init->AdapterFibsPhysicalAddress = cpu_to_le32((u32)phys);
init->AdapterFibsSize = cpu_to_le32(fibsize);
init->AdapterFibAlign = cpu_to_le32(sizeof(struct hw_fib));
diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c
index a379bc9a1276b..3f36dbaa2bb32 100644
--- a/drivers/scsi/aacraid/commsup.c
+++ b/drivers/scsi/aacraid/commsup.c
@@ -102,7 +102,7 @@ int fib_setup(struct aac_dev * dev)
fibptr->next = fibptr+1; /* Forward chain the fibs */
init_MUTEX_LOCKED(&fibptr->event_wait);
spin_lock_init(&fibptr->event_lock);
- hw_fib_va->header.XferState = cpu_to_le32(0xffffffff);
+ hw_fib_va->header.XferState = 0xffffffff;
hw_fib_va->header.SenderSize = cpu_to_le16(sizeof(struct hw_fib));
fibptr->hw_fib_pa = hw_fib_pa;
hw_fib_va = (struct hw_fib *)((unsigned char *)hw_fib_va + sizeof(struct hw_fib));
@@ -148,7 +148,7 @@ struct fib * fib_alloc(struct aac_dev *dev)
* Null out fields that depend on being zero at the start of
* each I/O
*/
- fibptr->hw_fib->header.XferState = cpu_to_le32(0);
+ fibptr->hw_fib->header.XferState = 0;
fibptr->callback = NULL;
fibptr->callback_data = NULL;
@@ -175,7 +175,8 @@ void fib_free(struct fib * fibptr)
} else {
if (fibptr->hw_fib->header.XferState != 0) {
printk(KERN_WARNING "fib_free, XferState != 0, fibptr = 0x%p, XferState = 0x%x\n",
- (void*)fibptr, fibptr->hw_fib->header.XferState);
+ (void*)fibptr,
+ le32_to_cpu(fibptr->hw_fib->header.XferState));
}
fibptr->next = fibptr->dev->free_fib;
fibptr->dev->free_fib = fibptr;
@@ -215,7 +216,7 @@ void fib_dealloc(struct fib * fibptr)
struct hw_fib *hw_fib = fibptr->hw_fib;
if(hw_fib->header.StructType != FIB_MAGIC)
BUG();
- hw_fib->header.XferState = cpu_to_le32(0);
+ hw_fib->header.XferState = 0;
}
/*
@@ -344,7 +345,7 @@ static int aac_queue_get(struct aac_dev * dev, u32 * index, u32 qid, struct hw_f
* in the queue entry.
*/
if (map)
- entry->addr = fibptr->hw_fib_pa;
+ entry->addr = cpu_to_le32(fibptr->hw_fib_pa);
return 0;
}
@@ -418,13 +419,13 @@ int fib_send(u16 command, struct fib * fibptr, unsigned long size, int priority
struct hw_fib * hw_fib = fibptr->hw_fib;
struct aac_queue * q;
unsigned long flags = 0;
- if (!(le32_to_cpu(hw_fib->header.XferState) & HostOwned))
+ if (!(hw_fib->header.XferState & cpu_to_le32(HostOwned)))
return -EBUSY;
/*
* There are 5 cases with the wait and reponse requested flags.
* The only invalid cases are if the caller requests to wait and
* does not request a response and if the caller does not want a
- * response and the Fibis not allocated from pool. If a response
+ * response and the Fib is not allocated from pool. If a response
* is not requesed the Fib will just be deallocaed by the DPC
* routine when the response comes back from the adapter. No
* further processing will be done besides deleting the Fib. We
@@ -566,12 +567,6 @@ int aac_consumer_get(struct aac_dev * dev, struct aac_queue * q, struct aac_entr
return(status);
}
-int aac_consumer_avail(struct aac_dev *dev, struct aac_queue * q)
-{
- return (le32_to_cpu(*q->headers.producer) != le32_to_cpu(*q->headers.consumer));
-}
-
-
/**
* aac_consumer_free - free consumer entry
* @dev: Adapter
@@ -632,7 +627,7 @@ int fib_adapter_complete(struct fib * fibptr, unsigned short size)
struct hw_fib * hw_fib = fibptr->hw_fib;
struct aac_dev * dev = fibptr->dev;
unsigned long nointr = 0;
- if (le32_to_cpu(hw_fib->header.XferState) == 0)
+ if (hw_fib->header.XferState == 0)
return 0;
/*
* If we plan to do anything check the structure type first.
@@ -704,7 +699,7 @@ int fib_complete(struct fib * fibptr)
* Check for a fib which has already been completed
*/
- if (hw_fib->header.XferState == cpu_to_le32(0))
+ if (hw_fib->header.XferState == 0)
return 0;
/*
* If we plan to do anything check the structure type first.
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index 1a0803887702d..c9b82687ba1aa 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -45,6 +45,7 @@
#include <linux/syscalls.h>
#include <linux/ioctl32.h>
#include <linux/delay.h>
+#include <linux/smp_lock.h>
#include <asm/semaphore.h>
#include <scsi/scsi.h>
@@ -191,28 +192,6 @@ static struct aac_driver_ident aac_drivers[] = {
{ aac_rkt_init, "aacraid", "ADAPTEC ", "RAID ", 2 } /* Adaptec Rocket Catch All */
};
-#ifdef CONFIG_COMPAT
-/*
- * Promote 32 bit apps that call get_next_adapter_fib_ioctl to 64 bit version
- */
-static int aac_get_next_adapter_fib_ioctl(unsigned int fd, unsigned int cmd,
- unsigned long arg, struct file *file)
-{
- struct fib_ioctl __user *f;
-
- f = compat_alloc_user_space(sizeof(*f));
- if (!access_ok(VERIFY_WRITE, f, sizeof(*f)))
- return -EFAULT;
-
- clear_user(f, sizeof(*f));
- if (copy_in_user(f, (void __user *)arg, sizeof(struct fib_ioctl) - sizeof(u32)))
- return -EFAULT;
-
- return sys_ioctl(fd, cmd, (unsigned long)f);
-}
-#endif
-
-
/**
* aac_queuecommand - queue a SCSI command
* @cmd: SCSI command to queue
@@ -494,9 +473,65 @@ static int aac_cfg_ioctl(struct inode *inode, struct file *file,
return aac_do_ioctl(file->private_data, cmd, (void __user *)arg);
}
+#ifdef CONFIG_COMPAT
+static long aac_compat_do_ioctl(struct aac_dev *dev, unsigned cmd, unsigned long arg)
+{
+ long ret;
+ lock_kernel();
+ switch (cmd) {
+ case FSACTL_MINIPORT_REV_CHECK:
+ case FSACTL_SENDFIB:
+ case FSACTL_OPEN_GET_ADAPTER_FIB:
+ case FSACTL_CLOSE_GET_ADAPTER_FIB:
+ case FSACTL_SEND_RAW_SRB:
+ case FSACTL_GET_PCI_INFO:
+ case FSACTL_QUERY_DISK:
+ case FSACTL_DELETE_DISK:
+ case FSACTL_FORCE_DELETE_DISK:
+ case FSACTL_GET_CONTAINERS:
+ ret = aac_do_ioctl(dev, cmd, (void __user *)arg);
+ break;
+
+ case FSACTL_GET_NEXT_ADAPTER_FIB: {
+ struct fib_ioctl __user *f;
+
+ f = compat_alloc_user_space(sizeof(*f));
+ ret = 0;
+ if (clear_user(f, sizeof(*f) != sizeof(*f)))
+ ret = -EFAULT;
+ if (copy_in_user(f, (void __user *)arg, sizeof(struct fib_ioctl) - sizeof(u32)))
+ ret = -EFAULT;
+ if (!ret)
+ ret = aac_do_ioctl(dev, cmd, (void __user *)arg);
+ break;
+ }
+
+ default:
+ ret = -ENOIOCTLCMD;
+ break;
+ }
+ unlock_kernel();
+ return ret;
+}
+
+static int aac_compat_ioctl(struct scsi_device *sdev, int cmd, void __user *arg)
+{
+ struct aac_dev *dev = (struct aac_dev *)sdev->host->hostdata;
+ return aac_compat_do_ioctl(dev, cmd, (unsigned long)arg);
+}
+
+static long aac_compat_cfg_ioctl(struct file *file, unsigned cmd, unsigned long arg)
+{
+ return aac_compat_do_ioctl((struct aac_dev *)file->private_data, cmd, arg);
+}
+#endif
+
static struct file_operations aac_cfg_fops = {
.owner = THIS_MODULE,
.ioctl = aac_cfg_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = aac_compat_cfg_ioctl,
+#endif
.open = aac_cfg_open,
};
@@ -506,6 +541,9 @@ static struct scsi_host_template aac_driver_template = {
.proc_name = "aacraid",
.info = aac_info,
.ioctl = aac_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = aac_compat_ioctl,
+#endif
.queuecommand = aac_queuecommand,
.bios_param = aac_biosparm,
.slave_configure = aac_slave_configure,
@@ -535,10 +573,9 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,
int unique_id = 0;
list_for_each_entry(aac, &aac_devices, entry) {
- if (aac->id > unique_id) {
- insert = &aac->entry;
+ if (aac->id > unique_id)
break;
- }
+ insert = &aac->entry;
unique_id++;
}
@@ -699,39 +736,11 @@ static int __init aac_init(void)
printk(KERN_WARNING
"aacraid: unable to register \"aac\" device.\n");
}
-#ifdef CONFIG_COMPAT
- register_ioctl32_conversion(FSACTL_MINIPORT_REV_CHECK, NULL);
- register_ioctl32_conversion(FSACTL_SENDFIB, NULL);
- register_ioctl32_conversion(FSACTL_OPEN_GET_ADAPTER_FIB, NULL);
- register_ioctl32_conversion(FSACTL_GET_NEXT_ADAPTER_FIB,
- aac_get_next_adapter_fib_ioctl);
- register_ioctl32_conversion(FSACTL_CLOSE_GET_ADAPTER_FIB, NULL);
- register_ioctl32_conversion(FSACTL_SEND_RAW_SRB, NULL);
- register_ioctl32_conversion(FSACTL_GET_PCI_INFO, NULL);
- register_ioctl32_conversion(FSACTL_QUERY_DISK, NULL);
- register_ioctl32_conversion(FSACTL_DELETE_DISK, NULL);
- register_ioctl32_conversion(FSACTL_FORCE_DELETE_DISK, NULL);
- register_ioctl32_conversion(FSACTL_GET_CONTAINERS, NULL);
-#endif
-
return 0;
}
static void __exit aac_exit(void)
{
-#ifdef CONFIG_COMPAT
- unregister_ioctl32_conversion(FSACTL_MINIPORT_REV_CHECK);
- unregister_ioctl32_conversion(FSACTL_SENDFIB);
- unregister_ioctl32_conversion(FSACTL_OPEN_GET_ADAPTER_FIB);
- unregister_ioctl32_conversion(FSACTL_GET_NEXT_ADAPTER_FIB);
- unregister_ioctl32_conversion(FSACTL_CLOSE_GET_ADAPTER_FIB);
- unregister_ioctl32_conversion(FSACTL_SEND_RAW_SRB);
- unregister_ioctl32_conversion(FSACTL_GET_PCI_INFO);
- unregister_ioctl32_conversion(FSACTL_QUERY_DISK);
- unregister_ioctl32_conversion(FSACTL_DELETE_DISK);
- unregister_ioctl32_conversion(FSACTL_FORCE_DELETE_DISK);
- unregister_ioctl32_conversion(FSACTL_GET_CONTAINERS);
-#endif
unregister_chrdev(aac_cfg_major, "aac");
pci_unregister_driver(&aac_pci_driver);
}
diff --git a/drivers/scsi/aacraid/rkt.c b/drivers/scsi/aacraid/rkt.c
index df8ccb93fd4e9..1b8ed47cfe30b 100644
--- a/drivers/scsi/aacraid/rkt.c
+++ b/drivers/scsi/aacraid/rkt.c
@@ -63,7 +63,7 @@ static irqreturn_t aac_rkt_intr(int irq, void *dev_id, struct pt_regs *regs)
{
bellbits = rkt_readl(dev, OutboundDoorbellReg);
if (bellbits & DoorBellPrintfReady) {
- aac_printf(dev, le32_to_cpu(rkt_readl (dev, IndexRegs.Mailbox[5])));
+ aac_printf(dev, rkt_readl(dev, IndexRegs.Mailbox[5]));
rkt_writel(dev, MUnit.ODR,DoorBellPrintfReady);
rkt_writel(dev, InboundDoorbellReg,DoorBellPrintfDone);
}
@@ -94,7 +94,7 @@ static irqreturn_t aac_rkt_intr(int irq, void *dev_id, struct pt_regs *regs)
* @p1: first parameter
* @ret: adapter status
*
- * This routine will send a synchronous comamnd to the adapter and wait
+ * This routine will send a synchronous command to the adapter and wait
* for its completion.
*/
@@ -105,11 +105,11 @@ static int rkt_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *status)
/*
* Write the command into Mailbox 0
*/
- rkt_writel(dev, InboundMailbox0, cpu_to_le32(command));
+ rkt_writel(dev, InboundMailbox0, command);
/*
* Write the parameters into Mailboxes 1 - 4
*/
- rkt_writel(dev, InboundMailbox1, cpu_to_le32(p1));
+ rkt_writel(dev, InboundMailbox1, p1);
rkt_writel(dev, InboundMailbox2, 0);
rkt_writel(dev, InboundMailbox3, 0);
rkt_writel(dev, InboundMailbox4, 0);
@@ -168,7 +168,7 @@ static int rkt_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *status)
* Pull the synch status from Mailbox 0.
*/
if (status)
- *status = le32_to_cpu(rkt_readl(dev, IndexRegs.Mailbox[0]));
+ *status = rkt_readl(dev, IndexRegs.Mailbox[0]);
/*
* Clear the synch command doorbell.
*/
@@ -275,7 +275,7 @@ static void aac_rkt_start_adapter(struct aac_dev *dev)
*/
static int aac_rkt_check_health(struct aac_dev *dev)
{
- u32 status = le32_to_cpu(rkt_readl(dev, MUnit.OMRx[0]));
+ u32 status = rkt_readl(dev, MUnit.OMRx[0]);
/*
* Check to see if the board failed any self tests.
@@ -307,9 +307,9 @@ static int aac_rkt_check_health(struct aac_dev *dev)
return ret;
}
memset(buffer, 0, 512);
- post->Post_Command = cpu_to_le32(COMMAND_POST_RESULTS);
+ post->Post_Command = cpu_to_le32(COMMAND_POST_RESULTS);
post->Post_Address = cpu_to_le32(baddr);
- rkt_writel(dev, MUnit.IMRx[0], cpu_to_le32(paddr));
+ rkt_writel(dev, MUnit.IMRx[0], paddr);
rkt_sync_cmd(dev, COMMAND_POST_RESULTS, baddr, &status);
pci_free_consistent(dev->pdev, sizeof(struct POSTSTATUS),
post, paddr);
@@ -388,8 +388,9 @@ int aac_rkt_init(struct aac_dev *dev)
{
if(time_after(jiffies, start+180*HZ))
{
- status = rkt_readl(dev, IndexRegs.Mailbox[7]) >> 16;
- printk(KERN_ERR "%s%d: adapter kernel failed to start, init status = %ld.\n", dev->name, instance, status);
+ status = rkt_readl(dev, MUnit.OMRx[0]);
+ printk(KERN_ERR "%s%d: adapter kernel failed to start, init status = %lx.\n",
+ dev->name, instance, status);
goto error_iounmap;
}
set_current_state(TASK_UNINTERRUPTIBLE);
diff --git a/drivers/scsi/aacraid/rx.c b/drivers/scsi/aacraid/rx.c
index df12f5301b6a1..630b99e1fe83c 100644
--- a/drivers/scsi/aacraid/rx.c
+++ b/drivers/scsi/aacraid/rx.c
@@ -94,7 +94,7 @@ static irqreturn_t aac_rx_intr(int irq, void *dev_id, struct pt_regs *regs)
* @p1: first parameter
* @ret: adapter status
*
- * This routine will send a synchronous comamnd to the adapter and wait
+ * This routine will send a synchronous command to the adapter and wait
* for its completion.
*/
@@ -105,11 +105,11 @@ static int rx_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *status)
/*
* Write the command into Mailbox 0
*/
- rx_writel(dev, InboundMailbox0, cpu_to_le32(command));
+ rx_writel(dev, InboundMailbox0, command);
/*
* Write the parameters into Mailboxes 1 - 4
*/
- rx_writel(dev, InboundMailbox1, cpu_to_le32(p1));
+ rx_writel(dev, InboundMailbox1, p1);
rx_writel(dev, InboundMailbox2, 0);
rx_writel(dev, InboundMailbox3, 0);
rx_writel(dev, InboundMailbox4, 0);
@@ -167,7 +167,8 @@ static int rx_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *status)
/*
* Pull the synch status from Mailbox 0.
*/
- *status = le32_to_cpu(rx_readl(dev, IndexRegs.Mailbox[0]));
+ if (status)
+ *status = rx_readl(dev, IndexRegs.Mailbox[0]);
/*
* Clear the synch command doorbell.
*/
@@ -274,7 +275,7 @@ static void aac_rx_start_adapter(struct aac_dev *dev)
*/
static int aac_rx_check_health(struct aac_dev *dev)
{
- u32 status = le32_to_cpu(rx_readl(dev, MUnit.OMRx[0]));
+ u32 status = rx_readl(dev, MUnit.OMRx[0]);
/*
* Check to see if the board failed any self tests.
@@ -308,7 +309,7 @@ static int aac_rx_check_health(struct aac_dev *dev)
memset(buffer, 0, 512);
post->Post_Command = cpu_to_le32(COMMAND_POST_RESULTS);
post->Post_Address = cpu_to_le32(baddr);
- rx_writel(dev, MUnit.IMRx[0], cpu_to_le32(paddr));
+ rx_writel(dev, MUnit.IMRx[0], paddr);
rx_sync_cmd(dev, COMMAND_POST_RESULTS, baddr, &status);
pci_free_consistent(dev->pdev, sizeof(struct POSTSTATUS),
post, paddr);
@@ -388,8 +389,9 @@ int aac_rx_init(struct aac_dev *dev)
{
if(time_after(jiffies, start+180*HZ))
{
- status = rx_readl(dev, IndexRegs.Mailbox[7]) >> 16;
- printk(KERN_ERR "%s%d: adapter kernel failed to start, init status = %ld.\n", dev->name, instance, status);
+ status = rx_readl(dev, IndexRegs.Mailbox[7]);
+ printk(KERN_ERR "%s%d: adapter kernel failed to start, init status = %lx.\n",
+ dev->name, instance, status);
goto error_iounmap;
}
set_current_state(TASK_UNINTERRUPTIBLE);
diff --git a/drivers/scsi/aacraid/sa.c b/drivers/scsi/aacraid/sa.c
index 13e88188485a3..bd6c30723fbaa 100644
--- a/drivers/scsi/aacraid/sa.c
+++ b/drivers/scsi/aacraid/sa.c
@@ -62,7 +62,7 @@ static irqreturn_t aac_sa_intr(int irq, void *dev_id, struct pt_regs *regs)
if (intstat & mask) {
if (intstat & PrintfReady) {
- aac_printf(dev, le32_to_cpu(sa_readl(dev, Mailbox5)));
+ aac_printf(dev, sa_readl(dev, Mailbox5));
sa_writew(dev, DoorbellClrReg_p, PrintfReady); /* clear PrintfReady */
sa_writew(dev, DoorbellReg_s, PrintfDone);
} else if (intstat & DOORBELL_1) { // dev -> Host Normal Command Ready
@@ -128,7 +128,7 @@ void aac_sa_notify_adapter(struct aac_dev *dev, u32 event)
* @p1: first parameter
* @ret: adapter status
*
- * This routine will send a synchronous comamnd to the adapter and wait
+ * This routine will send a synchronous command to the adapter and wait
* for its completion.
*/
@@ -139,11 +139,11 @@ static int sa_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *ret)
/*
* Write the Command into Mailbox 0
*/
- sa_writel(dev, Mailbox0, cpu_to_le32(command));
+ sa_writel(dev, Mailbox0, command);
/*
* Write the parameters into Mailboxes 1 - 4
*/
- sa_writel(dev, Mailbox1, cpu_to_le32(p1));
+ sa_writel(dev, Mailbox1, p1);
sa_writel(dev, Mailbox2, 0);
sa_writel(dev, Mailbox3, 0);
sa_writel(dev, Mailbox4, 0);
@@ -186,7 +186,8 @@ static int sa_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *ret)
/*
* Pull the synch status from Mailbox 0.
*/
- *ret = le32_to_cpu(sa_readl(dev, Mailbox0));
+ if (ret)
+ *ret = sa_readl(dev, Mailbox0);
return 0;
}
@@ -218,9 +219,8 @@ static void aac_sa_start_adapter(struct aac_dev *dev)
* Fill in the remaining pieces of the init.
*/
init = dev->init;
- init->HostElapsedSeconds = cpu_to_le32(jiffies/HZ);
+ init->HostElapsedSeconds = cpu_to_le32(get_seconds());
- dprintk(("INIT\n"));
/*
* Tell the adapter we are back and up and running so it will scan its command
* queues and enable our interrupts
@@ -230,10 +230,8 @@ static void aac_sa_start_adapter(struct aac_dev *dev)
* First clear out all interrupts. Then enable the one's that
* we can handle.
*/
- dprintk(("MASK\n"));
sa_writew(dev, SaDbCSR.PRISETIRQMASK, cpu_to_le16(0xffff));
sa_writew(dev, SaDbCSR.PRICLEARIRQMASK, (PrintfReady | DOORBELL_1 | DOORBELL_2 | DOORBELL_3 | DOORBELL_4));
- dprintk(("SYNCCMD\n"));
/* We can only use a 32 bit address here */
sa_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, (u32)(ulong)dev->init_pa, &ret);
}
@@ -286,14 +284,12 @@ int aac_sa_init(struct aac_dev *dev)
int instance;
const char *name;
- dprintk(("PREINST\n"));
instance = dev->id;
name = dev->name;
/*
* Map in the registers from the adapter.
*/
- dprintk(("PREMAP\n"));
if((dev->regs.sa = ioremap((unsigned long)dev->scsi_host_ptr->base, 8192))==NULL)
{
@@ -320,15 +316,15 @@ int aac_sa_init(struct aac_dev *dev)
*/
while (!(sa_readl(dev, Mailbox7) & KERNEL_UP_AND_RUNNING)) {
if (time_after(jiffies, start+180*HZ)) {
- status = sa_readl(dev, Mailbox7) >> 16;
- printk(KERN_WARNING "%s%d: adapter kernel failed to start, init status = %d.\n", name, instance, le32_to_cpu(status));
+ status = sa_readl(dev, Mailbox7);
+ printk(KERN_WARNING "%s%d: adapter kernel failed to start, init status = %lx.\n",
+ name, instance, status);
goto error_iounmap;
}
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(1);
}
- dprintk(("ATIRQ\n"));
if (request_irq(dev->scsi_host_ptr->irq, aac_sa_intr, SA_SHIRQ|SA_INTERRUPT, "aacraid", (void *)dev ) < 0) {
printk(KERN_WARNING "%s%d: Interrupt unavailable.\n", name, instance);
goto error_iounmap;
@@ -343,12 +339,10 @@ int aac_sa_init(struct aac_dev *dev)
dev->a_ops.adapter_sync_cmd = sa_sync_cmd;
dev->a_ops.adapter_check_health = aac_sa_check_health;
- dprintk(("FUNCDONE\n"));
if(aac_init_adapter(dev) == NULL)
goto error_irq;
- dprintk(("NEWADAPTDONE\n"));
/*
* Start any kernel threads needed
*/
@@ -362,9 +356,7 @@ int aac_sa_init(struct aac_dev *dev)
* Tell the adapter that all is configure, and it can start
* accepting requests
*/
- dprintk(("STARTING\n"));
aac_sa_start_adapter(dev);
- dprintk(("STARTED\n"));
return 0;
diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c
index d9dd0f796d67f..9962c51dc2a7d 100644
--- a/drivers/scsi/advansys.c
+++ b/drivers/scsi/advansys.c
@@ -714,7 +714,7 @@
Tom Rini <trini@kernel.crashing.org> provided the CONFIG_ISA
patch and helped with PowerPC wide and narrow board support.
- Philip Blundell <philip.blundell@pobox.com> provided an
+ Philip Blundell <philb@gnu.org> provided an
advansys_interrupts_enabled patch.
Dave Jones <dave@denial.force9.co.uk> reported the compiler
diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
index 48e9e1a0c2e0d..3a15b13e747aa 100644
--- a/drivers/scsi/ahci.c
+++ b/drivers/scsi/ahci.c
@@ -177,8 +177,10 @@ static void ahci_eng_timeout(struct ata_port *ap);
static int ahci_port_start(struct ata_port *ap);
static void ahci_port_stop(struct ata_port *ap);
static void ahci_host_stop(struct ata_host_set *host_set);
+static void ahci_tf_read(struct ata_port *ap, struct ata_taskfile *tf);
static void ahci_qc_prep(struct ata_queued_cmd *qc);
static u8 ahci_check_status(struct ata_port *ap);
+static u8 ahci_check_err(struct ata_port *ap);
static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc);
static Scsi_Host_Template ahci_sht = {
@@ -198,14 +200,19 @@ static 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 struct ata_port_operations ahci_ops = {
.port_disable = ata_port_disable,
.check_status = ahci_check_status,
+ .check_altstatus = ahci_check_status,
+ .check_err = ahci_check_err,
.dev_select = ata_noop_dev_select,
+ .tf_read = ahci_tf_read,
+
.phy_reset = ahci_phy_reset,
.qc_prep = ahci_qc_prep,
@@ -246,8 +253,6 @@ static struct pci_device_id ahci_pci_tbl[] = {
board_ahci }, /* ICH7 */
{ PCI_VENDOR_ID_INTEL, 0x27c5, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
board_ahci }, /* ICH7M */
- { PCI_VENDOR_ID_INTEL, 0x27c2, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- board_ahci }, /* ICH7R */
{ PCI_VENDOR_ID_INTEL, 0x27c3, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
board_ahci }, /* ICH7R */
{ PCI_VENDOR_ID_AL, 0x5288, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
@@ -452,6 +457,21 @@ static u8 ahci_check_status(struct ata_port *ap)
return readl(mmio + PORT_TFDATA) & 0xFF;
}
+static u8 ahci_check_err(struct ata_port *ap)
+{
+ void *mmio = (void *) ap->ioaddr.cmd_addr;
+
+ return (readl(mmio + PORT_TFDATA) >> 8) & 0xFF;
+}
+
+static void ahci_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
+{
+ struct ahci_port_priv *pp = ap->private_data;
+ u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
+
+ ata_tf_from_fis(d2h_fis, tf);
+}
+
static void ahci_fill_sg(struct ata_queued_cmd *qc)
{
struct ahci_port_priv *pp = qc->ap->private_data;
@@ -528,7 +548,7 @@ static void ahci_intr_error(struct ata_port *ap, u32 irq_stat)
/* stop DMA */
tmp = readl(port_mmio + PORT_CMD);
- tmp &= PORT_CMD_START | PORT_CMD_FIS_RX;
+ tmp &= ~PORT_CMD_START;
writel(tmp, port_mmio + PORT_CMD);
/* wait for engine to stop. TODO: this could be
@@ -560,11 +580,11 @@ static void ahci_intr_error(struct ata_port *ap, u32 irq_stat)
/* re-start DMA */
tmp = readl(port_mmio + PORT_CMD);
- tmp |= PORT_CMD_START | PORT_CMD_FIS_RX;
+ tmp |= PORT_CMD_START;
writel(tmp, port_mmio + PORT_CMD);
readl(port_mmio + PORT_CMD); /* flush */
- printk(KERN_WARNING "ata%u: error occurred, port reset\n", ap->port_no);
+ printk(KERN_WARNING "ata%u: error occurred, port reset\n", ap->id);
}
static void ahci_eng_timeout(struct ata_port *ap)
@@ -756,10 +776,10 @@ static int ahci_host_init(struct ata_probe_ent *probe_ent)
using_dac = hpriv->cap & HOST_CAP_64;
if (using_dac &&
- !pci_set_dma_mask(pdev, 0xffffffffffffffffULL)) {
- rc = pci_set_consistent_dma_mask(pdev, 0xffffffffffffffffULL);
+ !pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
+ rc = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
if (rc) {
- rc = pci_set_consistent_dma_mask(pdev, 0xffffffffULL);
+ rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
if (rc) {
printk(KERN_ERR DRV_NAME "(%s): 64-bit DMA enable failed\n",
pci_name(pdev));
@@ -769,13 +789,13 @@ static int ahci_host_init(struct ata_probe_ent *probe_ent)
hpriv->flags |= HOST_CAP_64;
} else {
- rc = pci_set_dma_mask(pdev, 0xffffffffULL);
+ rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
if (rc) {
printk(KERN_ERR DRV_NAME "(%s): 32-bit DMA enable failed\n",
pci_name(pdev));
return rc;
}
- rc = pci_set_consistent_dma_mask(pdev, 0xffffffffULL);
+ rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
if (rc) {
printk(KERN_ERR DRV_NAME "(%s): 32-bit consistent DMA enable failed\n",
pci_name(pdev));
@@ -940,6 +960,7 @@ static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
unsigned long base;
void *mmio_base;
unsigned int board_idx = (unsigned int) ent->driver_data;
+ int pci_dev_busy = 0;
int rc;
VPRINTK("ENTER\n");
@@ -952,8 +973,10 @@ static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
return rc;
rc = pci_request_regions(pdev, DRV_NAME);
- if (rc)
+ if (rc) {
+ pci_dev_busy = 1;
goto err_out;
+ }
pci_enable_intx(pdev);
@@ -1015,7 +1038,8 @@ err_out_free_ent:
err_out_regions:
pci_release_regions(pdev);
err_out:
- pci_disable_device(pdev);
+ if (!pci_dev_busy)
+ pci_disable_device(pdev);
return rc;
}
diff --git a/drivers/scsi/arm/arxescsi.c b/drivers/scsi/arm/arxescsi.c
index 8397c6321382a..29811f5891ee4 100644
--- a/drivers/scsi/arm/arxescsi.c
+++ b/drivers/scsi/arm/arxescsi.c
@@ -43,6 +43,7 @@
struct arxescsi_info {
FAS216_Info info;
struct expansion_card *ec;
+ void __iomem *base;
};
#define DMADATA_OFFSET (0x200)
@@ -73,7 +74,7 @@ arxescsi_dma_setup(struct Scsi_Host *host, Scsi_Pointer *SCp,
return fasdma_pseudo;
}
-static void arxescsi_pseudo_dma_write(unsigned char *addr, unsigned char *base)
+static void arxescsi_pseudo_dma_write(unsigned char *addr, void __iomem *base)
{
__asm__ __volatile__(
" stmdb sp!, {r0-r12}\n"
@@ -115,7 +116,7 @@ arxescsi_dma_pseudo(struct Scsi_Host *host, Scsi_Pointer *SCp,
{
struct arxescsi_info *info = (struct arxescsi_info *)host->hostdata;
unsigned int length, error = 0;
- unsigned char *base = info->info.scsi.io_base;
+ void __iomem *base = info->info.scsi.io_base;
unsigned char *addr;
length = SCp->this_residual;
@@ -283,7 +284,7 @@ arxescsi_probe(struct expansion_card *ec, const struct ecard_id *id)
struct Scsi_Host *host;
struct arxescsi_info *info;
unsigned long resbase, reslen;
- unsigned char *base;
+ void __iomem *base;
int ret;
ret = ecard_request_resources(ec);
@@ -304,15 +305,13 @@ arxescsi_probe(struct expansion_card *ec, const struct ecard_id *id)
goto out_unmap;
}
- host->base = (unsigned long)base;
- host->irq = NO_IRQ;
- host->dma_channel = NO_DMA;
-
info = (struct arxescsi_info *)host->hostdata;
info->ec = ec;
+ info->base = base;
info->info.scsi.io_base = base + 0x2000;
- info->info.scsi.irq = host->irq;
+ info->info.scsi.irq = NO_IRQ;
+ info->info.scsi.dma = NO_DMA;
info->info.scsi.io_shift = 5;
info->info.ifcfg.clockrate = 24; /* MHz */
info->info.ifcfg.select_timeout = 255;
@@ -351,11 +350,12 @@ arxescsi_probe(struct expansion_card *ec, const struct ecard_id *id)
static void __devexit arxescsi_remove(struct expansion_card *ec)
{
struct Scsi_Host *host = ecard_get_drvdata(ec);
+ struct arxescsi_info *info = (struct arxescsi_info *)host->hostdata;
ecard_set_drvdata(ec, NULL);
fas216_remove(host);
- iounmap((void *)host->base);
+ iounmap(info->base);
fas216_release(host);
scsi_host_put(host);
diff --git a/drivers/scsi/arm/cumana_2.c b/drivers/scsi/arm/cumana_2.c
index e54885fd8561a..0ef0644eeb291 100644
--- a/drivers/scsi/arm/cumana_2.c
+++ b/drivers/scsi/arm/cumana_2.c
@@ -1,7 +1,7 @@
/*
* linux/drivers/acorn/scsi/cumana_2.c
*
- * Copyright (C) 1997-2002 Russell King
+ * Copyright (C) 1997-2005 Russell King
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -78,11 +78,8 @@ static int term[MAX_ECARDS] = { 1, 1, 1, 1, 1, 1, 1, 1 };
struct cumanascsi2_info {
FAS216_Info info;
struct expansion_card *ec;
-
- void *status; /* card status register */
- void *alatch; /* Control register */
+ void __iomem *base;
unsigned int terms; /* Terminator state */
- void *dmaarea; /* Pseudo DMA area */
struct scatterlist sg[NR_SG]; /* Scatter DMA list */
};
@@ -97,7 +94,8 @@ struct cumanascsi2_info {
static void
cumanascsi_2_irqenable(struct expansion_card *ec, int irqnr)
{
- writeb(ALATCH_ENA_INT, ec->irq_data);
+ struct cumanascsi2_info *info = ec->irq_data;
+ writeb(ALATCH_ENA_INT, info->base + CUMANASCSI2_ALATCH);
}
/* Prototype: void cumanascsi_2_irqdisable(ec, irqnr)
@@ -108,7 +106,8 @@ cumanascsi_2_irqenable(struct expansion_card *ec, int irqnr)
static void
cumanascsi_2_irqdisable(struct expansion_card *ec, int irqnr)
{
- writeb(ALATCH_DIS_INT, ec->irq_data);
+ struct cumanascsi2_info *info = ec->irq_data;
+ writeb(ALATCH_DIS_INT, info->base + CUMANASCSI2_ALATCH);
}
static const expansioncard_ops_t cumanascsi_2_ops = {
@@ -128,10 +127,10 @@ cumanascsi_2_terminator_ctl(struct Scsi_Host *host, int on_off)
if (on_off) {
info->terms = 1;
- writeb(ALATCH_ENA_TERM, info->alatch);
+ writeb(ALATCH_ENA_TERM, info->base + CUMANASCSI2_ALATCH);
} else {
info->terms = 0;
- writeb(ALATCH_DIS_TERM, info->alatch);
+ writeb(ALATCH_DIS_TERM, info->base + CUMANASCSI2_ALATCH);
}
}
@@ -163,9 +162,9 @@ cumanascsi_2_dma_setup(struct Scsi_Host *host, Scsi_Pointer *SCp,
{
struct cumanascsi2_info *info = (struct cumanascsi2_info *)host->hostdata;
struct device *dev = scsi_get_device(host);
- int dmach = host->dma_channel;
+ int dmach = info->info.scsi.dma;
- writeb(ALATCH_DIS_DMA, info->alatch);
+ writeb(ALATCH_DIS_DMA, info->base + CUMANASCSI2_ALATCH);
if (dmach != NO_DMA &&
(min_type == fasdma_real_all || SCp->this_residual >= 512)) {
@@ -186,11 +185,11 @@ cumanascsi_2_dma_setup(struct Scsi_Host *host, Scsi_Pointer *SCp,
disable_dma(dmach);
set_dma_sg(dmach, info->sg, bufs + 1);
- writeb(alatch_dir, info->alatch);
+ writeb(alatch_dir, info->base + CUMANASCSI2_ALATCH);
set_dma_mode(dmach, dma_dir);
enable_dma(dmach);
- writeb(ALATCH_ENA_DMA, info->alatch);
- writeb(ALATCH_DIS_BIT32, info->alatch);
+ writeb(ALATCH_ENA_DMA, info->base + CUMANASCSI2_ALATCH);
+ writeb(ALATCH_DIS_BIT32, info->base + CUMANASCSI2_ALATCH);
return fasdma_real_all;
}
@@ -224,7 +223,7 @@ cumanascsi_2_dma_pseudo(struct Scsi_Host *host, Scsi_Pointer *SCp,
#if 0
while (length > 1) {
unsigned long word;
- unsigned int status = readb(info->status);
+ unsigned int status = readb(info->base + CUMANASCSI2_STATUS);
if (status & STATUS_INT)
goto end;
@@ -233,7 +232,7 @@ cumanascsi_2_dma_pseudo(struct Scsi_Host *host, Scsi_Pointer *SCp,
continue;
word = *addr | *(addr + 1) << 8;
- writew(word, info->dmaarea);
+ writew(word, info->base + CUMANASCSI2_PSEUDODMA);
addr += 2;
length -= 2;
}
@@ -243,7 +242,7 @@ cumanascsi_2_dma_pseudo(struct Scsi_Host *host, Scsi_Pointer *SCp,
else {
if (transfer && (transfer & 255)) {
while (length >= 256) {
- unsigned int status = readb(info->status);
+ unsigned int status = readb(info->base + CUMANASCSI2_STATUS);
if (status & STATUS_INT)
return;
@@ -251,7 +250,8 @@ cumanascsi_2_dma_pseudo(struct Scsi_Host *host, Scsi_Pointer *SCp,
if (!(status & STATUS_DRQ))
continue;
- readsw(info->dmaarea, addr, 256 >> 1);
+ readsw(info->base + CUMANASCSI2_PSEUDODMA,
+ addr, 256 >> 1);
addr += 256;
length -= 256;
}
@@ -259,7 +259,7 @@ cumanascsi_2_dma_pseudo(struct Scsi_Host *host, Scsi_Pointer *SCp,
while (length > 0) {
unsigned long word;
- unsigned int status = readb(info->status);
+ unsigned int status = readb(info->base + CUMANASCSI2_STATUS);
if (status & STATUS_INT)
return;
@@ -267,7 +267,7 @@ cumanascsi_2_dma_pseudo(struct Scsi_Host *host, Scsi_Pointer *SCp,
if (!(status & STATUS_DRQ))
continue;
- word = readw(info->dmaarea);
+ word = readw(info->base + CUMANASCSI2_PSEUDODMA);
*addr++ = word;
if (--length > 0) {
*addr++ = word >> 8;
@@ -286,9 +286,9 @@ static void
cumanascsi_2_dma_stop(struct Scsi_Host *host, Scsi_Pointer *SCp)
{
struct cumanascsi2_info *info = (struct cumanascsi2_info *)host->hostdata;
- if (host->dma_channel != NO_DMA) {
- writeb(ALATCH_DIS_DMA, info->alatch);
- disable_dma(host->dma_channel);
+ if (info->info.scsi.dma != NO_DMA) {
+ writeb(ALATCH_DIS_DMA, info->base + CUMANASCSI2_ALATCH);
+ disable_dma(info->info.scsi.dma);
}
}
@@ -405,7 +405,7 @@ cumanascsi2_probe(struct expansion_card *ec, const struct ecard_id *id)
struct Scsi_Host *host;
struct cumanascsi2_info *info;
unsigned long resbase, reslen;
- unsigned char *base;
+ void __iomem *base;
int ret;
ret = ecard_request_resources(ec);
@@ -427,28 +427,18 @@ cumanascsi2_probe(struct expansion_card *ec, const struct ecard_id *id)
goto out_unmap;
}
- host->base = (unsigned long)base;
- host->irq = ec->irq;
- host->dma_channel = ec->dma;
-
ecard_set_drvdata(ec, host);
info = (struct cumanascsi2_info *)host->hostdata;
info->ec = ec;
- info->dmaarea = base + CUMANASCSI2_PSEUDODMA;
- info->status = base + CUMANASCSI2_STATUS;
- info->alatch = base + CUMANASCSI2_ALATCH;
-
- ec->irqaddr = info->status;
- ec->irqmask = STATUS_INT;
- ec->irq_data = base + CUMANASCSI2_ALATCH;
- ec->ops = &cumanascsi_2_ops;
+ info->base = base;
cumanascsi_2_terminator_ctl(host, term[ec->slot_no]);
info->info.scsi.io_base = base + CUMANASCSI2_FAS216_OFFSET;
info->info.scsi.io_shift = CUMANASCSI2_FAS216_SHIFT;
- info->info.scsi.irq = host->irq;
+ info->info.scsi.irq = ec->irq;
+ info->info.scsi.dma = ec->dma;
info->info.ifcfg.clockrate = 40; /* MHz */
info->info.ifcfg.select_timeout = 255;
info->info.ifcfg.asyncperiod = 200; /* ns */
@@ -461,25 +451,30 @@ cumanascsi2_probe(struct expansion_card *ec, const struct ecard_id *id)
info->info.dma.pseudo = cumanascsi_2_dma_pseudo;
info->info.dma.stop = cumanascsi_2_dma_stop;
+ ec->irqaddr = info->base + CUMANASCSI2_STATUS;
+ ec->irqmask = STATUS_INT;
+ ec->irq_data = info;
+ ec->ops = &cumanascsi_2_ops;
+
ret = fas216_init(host);
if (ret)
goto out_free;
- ret = request_irq(host->irq, cumanascsi_2_intr,
+ ret = request_irq(ec->irq, cumanascsi_2_intr,
SA_INTERRUPT, "cumanascsi2", info);
if (ret) {
printk("scsi%d: IRQ%d not free: %d\n",
- host->host_no, host->irq, ret);
+ host->host_no, ec->irq, ret);
goto out_release;
}
- if (host->dma_channel != NO_DMA) {
- if (request_dma(host->dma_channel, "cumanascsi2")) {
+ if (info->info.scsi.dma != NO_DMA) {
+ if (request_dma(info->info.scsi.dma, "cumanascsi2")) {
printk("scsi%d: DMA%d not free, using PIO\n",
- host->host_no, host->dma_channel);
- host->dma_channel = NO_DMA;
+ host->host_no, info->info.scsi.dma);
+ info->info.scsi.dma = NO_DMA;
} else {
- set_dma_speed(host->dma_channel, 180);
+ set_dma_speed(info->info.scsi.dma, 180);
info->info.ifcfg.capabilities |= FASCAP_DMA;
}
}
@@ -488,9 +483,9 @@ cumanascsi2_probe(struct expansion_card *ec, const struct ecard_id *id)
if (ret == 0)
goto out;
- if (host->dma_channel != NO_DMA)
- free_dma(host->dma_channel);
- free_irq(host->irq, host);
+ if (info->info.scsi.dma != NO_DMA)
+ free_dma(info->info.scsi.dma);
+ free_irq(ec->irq, host);
out_release:
fas216_release(host);
@@ -516,11 +511,11 @@ static void __devexit cumanascsi2_remove(struct expansion_card *ec)
ecard_set_drvdata(ec, NULL);
fas216_remove(host);
- if (host->dma_channel != NO_DMA)
- free_dma(host->dma_channel);
- free_irq(host->irq, info);
+ if (info->info.scsi.dma != NO_DMA)
+ free_dma(info->info.scsi.dma);
+ free_irq(ec->irq, info);
- iounmap((void *)host->base);
+ iounmap(info->base);
fas216_release(host);
scsi_host_put(host);
diff --git a/drivers/scsi/arm/eesox.c b/drivers/scsi/arm/eesox.c
index 70ba49f29cf95..78b7e543471bd 100644
--- a/drivers/scsi/arm/eesox.c
+++ b/drivers/scsi/arm/eesox.c
@@ -1,7 +1,7 @@
/*
* linux/drivers/acorn/scsi/eesox.c
*
- * Copyright (C) 1997-2003 Russell King
+ * Copyright (C) 1997-2005 Russell King
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -73,8 +73,8 @@ static int term[MAX_ECARDS] = { 1, 1, 1, 1, 1, 1, 1, 1 };
struct eesoxscsi_info {
FAS216_Info info;
struct expansion_card *ec;
-
- void *ctl_port;
+ void __iomem *base;
+ void __iomem *ctl_port;
unsigned int control;
struct scatterlist sg[NR_SG]; /* Scatter DMA list */
};
@@ -163,7 +163,7 @@ eesoxscsi_dma_setup(struct Scsi_Host *host, Scsi_Pointer *SCp,
{
struct eesoxscsi_info *info = (struct eesoxscsi_info *)host->hostdata;
struct device *dev = scsi_get_device(host);
- int dmach = host->dma_channel;
+ int dmach = info->info.scsi.dma;
if (dmach != NO_DMA &&
(min_type == fasdma_real_all || SCp->this_residual >= 512)) {
@@ -194,11 +194,11 @@ eesoxscsi_dma_setup(struct Scsi_Host *host, Scsi_Pointer *SCp,
return fasdma_pseudo;
}
-static void eesoxscsi_buffer_in(void *buf, int length, void *base)
+static void eesoxscsi_buffer_in(void *buf, int length, void __iomem *base)
{
- const void *reg_fas = base + EESOX_FAS216_OFFSET;
- const void *reg_dmastat = base + EESOX_DMASTAT;
- const void *reg_dmadata = base + EESOX_DMADATA;
+ const void __iomem *reg_fas = base + EESOX_FAS216_OFFSET;
+ const void __iomem *reg_dmastat = base + EESOX_DMASTAT;
+ const void __iomem *reg_dmadata = base + EESOX_DMADATA;
const register unsigned long mask = 0xffff;
do {
@@ -272,11 +272,11 @@ static void eesoxscsi_buffer_in(void *buf, int length, void *base)
} while (length);
}
-static void eesoxscsi_buffer_out(void *buf, int length, void *base)
+static void eesoxscsi_buffer_out(void *buf, int length, void __iomem *base)
{
- const void *reg_fas = base + EESOX_FAS216_OFFSET;
- const void *reg_dmastat = base + EESOX_DMASTAT;
- const void *reg_dmadata = base + EESOX_DMADATA;
+ const void __iomem *reg_fas = base + EESOX_FAS216_OFFSET;
+ const void __iomem *reg_dmastat = base + EESOX_DMASTAT;
+ const void __iomem *reg_dmadata = base + EESOX_DMADATA;
do {
unsigned int status;
@@ -356,11 +356,11 @@ static void
eesoxscsi_dma_pseudo(struct Scsi_Host *host, Scsi_Pointer *SCp,
fasdmadir_t dir, int transfer_size)
{
- void *base = (void *)host->base;
+ struct eesoxscsi_info *info = (struct eesoxscsi_info *)host->hostdata;
if (dir == DMA_IN) {
- eesoxscsi_buffer_in(SCp->ptr, SCp->this_residual, base);
+ eesoxscsi_buffer_in(SCp->ptr, SCp->this_residual, info->base);
} else {
- eesoxscsi_buffer_out(SCp->ptr, SCp->this_residual, base);
+ eesoxscsi_buffer_out(SCp->ptr, SCp->this_residual, info->base);
}
}
@@ -372,8 +372,9 @@ eesoxscsi_dma_pseudo(struct Scsi_Host *host, Scsi_Pointer *SCp,
static void
eesoxscsi_dma_stop(struct Scsi_Host *host, Scsi_Pointer *SCp)
{
- if (host->dma_channel != NO_DMA)
- disable_dma(host->dma_channel);
+ struct eesoxscsi_info *info = (struct eesoxscsi_info *)host->hostdata;
+ if (info->info.scsi.dma != NO_DMA)
+ disable_dma(info->info.scsi.dma);
}
/* Prototype: const char *eesoxscsi_info(struct Scsi_Host * host)
@@ -522,7 +523,7 @@ eesoxscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
struct Scsi_Host *host;
struct eesoxscsi_info *info;
unsigned long resbase, reslen;
- unsigned char *base;
+ void __iomem *base;
int ret;
ret = ecard_request_resources(ec);
@@ -544,26 +545,19 @@ eesoxscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
goto out_unmap;
}
- host->base = (unsigned long)base;
- host->irq = ec->irq;
- host->dma_channel = ec->dma;
-
ecard_set_drvdata(ec, host);
info = (struct eesoxscsi_info *)host->hostdata;
info->ec = ec;
+ info->base = base;
info->ctl_port = base + EESOX_CONTROL;
info->control = term[ec->slot_no] ? EESOX_TERM_ENABLE : 0;
writeb(info->control, info->ctl_port);
- ec->irqaddr = base + EESOX_DMASTAT;
- ec->irqmask = EESOX_STAT_INTR;
- ec->irq_data = info;
- ec->ops = &eesoxscsi_ops;
-
info->info.scsi.io_base = base + EESOX_FAS216_OFFSET;
info->info.scsi.io_shift = EESOX_FAS216_SHIFT;
- info->info.scsi.irq = host->irq;
+ info->info.scsi.irq = ec->irq;
+ info->info.scsi.dma = ec->dma;
info->info.ifcfg.clockrate = 40; /* MHz */
info->info.ifcfg.select_timeout = 255;
info->info.ifcfg.asyncperiod = 200; /* ns */
@@ -576,26 +570,31 @@ eesoxscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
info->info.dma.pseudo = eesoxscsi_dma_pseudo;
info->info.dma.stop = eesoxscsi_dma_stop;
+ ec->irqaddr = base + EESOX_DMASTAT;
+ ec->irqmask = EESOX_STAT_INTR;
+ ec->irq_data = info;
+ ec->ops = &eesoxscsi_ops;
+
device_create_file(&ec->dev, &dev_attr_bus_term);
ret = fas216_init(host);
if (ret)
goto out_free;
- ret = request_irq(host->irq, eesoxscsi_intr, 0, "eesoxscsi", info);
+ ret = request_irq(ec->irq, eesoxscsi_intr, 0, "eesoxscsi", info);
if (ret) {
printk("scsi%d: IRQ%d not free: %d\n",
- host->host_no, host->irq, ret);
+ host->host_no, ec->irq, ret);
goto out_remove;
}
- if (host->dma_channel != NO_DMA) {
- if (request_dma(host->dma_channel, "eesox")) {
+ if (info->info.scsi.dma != NO_DMA) {
+ if (request_dma(info->info.scsi.dma, "eesox")) {
printk("scsi%d: DMA%d not free, DMA disabled\n",
- host->host_no, host->dma_channel);
- host->dma_channel = NO_DMA;
+ host->host_no, info->info.scsi.dma);
+ info->info.scsi.dma = NO_DMA;
} else {
- set_dma_speed(host->dma_channel, 180);
+ set_dma_speed(info->info.scsi.dma, 180);
info->info.ifcfg.capabilities |= FASCAP_DMA;
info->info.ifcfg.cntl3 |= CNTL3_BS8;
}
@@ -605,9 +604,9 @@ eesoxscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
if (ret == 0)
goto out;
- if (host->dma_channel != NO_DMA)
- free_dma(host->dma_channel);
- free_irq(host->irq, host);
+ if (info->info.scsi.dma != NO_DMA)
+ free_dma(info->info.scsi.dma);
+ free_irq(ec->irq, host);
out_remove:
fas216_remove(host);
@@ -634,13 +633,13 @@ static void __devexit eesoxscsi_remove(struct expansion_card *ec)
ecard_set_drvdata(ec, NULL);
fas216_remove(host);
- if (host->dma_channel != NO_DMA)
- free_dma(host->dma_channel);
- free_irq(host->irq, info);
+ if (info->info.scsi.dma != NO_DMA)
+ free_dma(info->info.scsi.dma);
+ free_irq(ec->irq, info);
device_remove_file(&ec->dev, &dev_attr_bus_term);
- iounmap((void *)host->base);
+ iounmap(info->base);
fas216_release(host);
scsi_host_put(host);
@@ -679,4 +678,3 @@ MODULE_DESCRIPTION("EESOX 'Fast' SCSI driver for Acorn machines");
MODULE_PARM(term, "1-8i");
MODULE_PARM_DESC(term, "SCSI bus termination");
MODULE_LICENSE("GPL");
-
diff --git a/drivers/scsi/arm/fas216.c b/drivers/scsi/arm/fas216.c
index b10257eef6e90..5411e850c8336 100644
--- a/drivers/scsi/arm/fas216.c
+++ b/drivers/scsi/arm/fas216.c
@@ -142,19 +142,13 @@ __setup("fas216_logging=", fas216_log_setup);
static inline unsigned char fas216_readb(FAS216_Info *info, unsigned int reg)
{
unsigned int off = reg << info->scsi.io_shift;
- if (info->scsi.io_base)
- return readb(info->scsi.io_base + off);
- else
- return inb(info->scsi.io_port + off);
+ return readb(info->scsi.io_base + off);
}
static inline void fas216_writeb(FAS216_Info *info, unsigned int reg, unsigned int val)
{
unsigned int off = reg << info->scsi.io_shift;
- if (info->scsi.io_base)
- writeb(val, info->scsi.io_base + off);
- else
- outb(val, info->scsi.io_port + off);
+ writeb(val, info->scsi.io_base + off);
}
static void fas216_dumpstate(FAS216_Info *info)
@@ -197,8 +191,8 @@ static void fas216_dumpinfo(FAS216_Info *info)
printk(" { magic_start=%lX host=%p SCpnt=%p origSCpnt=%p\n",
info->magic_start, info->host, info->SCpnt,
info->origSCpnt);
- printk(" scsi={ io_port=%X io_shift=%X irq=%X cfg={ %X %X %X %X }\n",
- info->scsi.io_port, info->scsi.io_shift, info->scsi.irq,
+ printk(" scsi={ io_shift=%X irq=%X cfg={ %X %X %X %X }\n",
+ info->scsi.io_shift, info->scsi.irq,
info->scsi.cfg[0], info->scsi.cfg[1], info->scsi.cfg[2],
info->scsi.cfg[3]);
printk(" type=%p phase=%X\n",
@@ -2967,11 +2961,11 @@ int fas216_print_host(FAS216_Info *info, char *buffer)
return sprintf(buffer,
"\n"
"Chip : %s\n"
- " Address: 0x%08lx\n"
+ " Address: 0x%p\n"
" IRQ : %d\n"
" DMA : %d\n",
- info->scsi.type, info->host->io_port,
- info->host->irq, info->host->dma_channel);
+ info->scsi.type, info->scsi.io_base,
+ info->scsi.irq, info->scsi.dma);
}
int fas216_print_stats(FAS216_Info *info, char *buffer)
diff --git a/drivers/scsi/arm/fas216.h b/drivers/scsi/arm/fas216.h
index 8c80f0f8f5b4d..60a2a120205b9 100644
--- a/drivers/scsi/arm/fas216.h
+++ b/drivers/scsi/arm/fas216.h
@@ -236,12 +236,12 @@ typedef struct {
/* driver information */
struct {
phase_t phase; /* current phase */
- void *io_base; /* iomem base of FAS216 */
- unsigned int io_port; /* base address of FAS216 */
+ void __iomem *io_base; /* iomem base of FAS216 */
unsigned int io_shift; /* shift to adjust reg offsets by */
unsigned char cfg[4]; /* configuration registers */
const char *type; /* chip type */
unsigned int irq; /* interrupt */
+ int dma; /* dma channel */
Scsi_Pointer SCp; /* current commands data pointer */
diff --git a/drivers/scsi/arm/powertec.c b/drivers/scsi/arm/powertec.c
index 87c5cc10871a9..54f23be6460fd 100644
--- a/drivers/scsi/arm/powertec.c
+++ b/drivers/scsi/arm/powertec.c
@@ -1,7 +1,7 @@
/*
* linux/drivers/acorn/scsi/powertec.c
*
- * Copyright (C) 1997-2003 Russell King
+ * Copyright (C) 1997-2005 Russell King
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -61,7 +61,7 @@ static int term[MAX_ECARDS] = { 1, 1, 1, 1, 1, 1, 1, 1 };
struct powertec_info {
FAS216_Info info;
struct expansion_card *ec;
- void *term_port;
+ void __iomem *base;
unsigned int term_ctl;
struct scatterlist sg[NR_SG];
};
@@ -74,7 +74,8 @@ struct powertec_info {
static void
powertecscsi_irqenable(struct expansion_card *ec, int irqnr)
{
- writeb(POWERTEC_INTR_ENABLE, ec->irq_data);
+ struct powertec_info *info = ec->irq_data;
+ writeb(POWERTEC_INTR_ENABLE, info->base + POWERTEC_INTR_CONTROL);
}
/* Prototype: void powertecscsi_irqdisable(ec, irqnr)
@@ -85,7 +86,8 @@ powertecscsi_irqenable(struct expansion_card *ec, int irqnr)
static void
powertecscsi_irqdisable(struct expansion_card *ec, int irqnr)
{
- writeb(POWERTEC_INTR_DISABLE, ec->irq_data);
+ struct powertec_info *info = ec->irq_data;
+ writeb(POWERTEC_INTR_DISABLE, info->base + POWERTEC_INTR_CONTROL);
}
static const expansioncard_ops_t powertecscsi_ops = {
@@ -104,7 +106,7 @@ powertecscsi_terminator_ctl(struct Scsi_Host *host, int on_off)
struct powertec_info *info = (struct powertec_info *)host->hostdata;
info->term_ctl = on_off ? POWERTEC_TERM_ENABLE : 0;
- writeb(info->term_ctl, info->term_port);
+ writeb(info->term_ctl, info->base + POWERTEC_TERM_CONTROL);
}
/* Prototype: void powertecscsi_intr(irq, *dev_id, *regs)
@@ -135,7 +137,7 @@ powertecscsi_dma_setup(struct Scsi_Host *host, Scsi_Pointer *SCp,
{
struct powertec_info *info = (struct powertec_info *)host->hostdata;
struct device *dev = scsi_get_device(host);
- int dmach = host->dma_channel;
+ int dmach = info->info.scsi.dma;
if (info->info.ifcfg.capabilities & FASCAP_DMA &&
min_type == fasdma_real_all) {
@@ -174,8 +176,9 @@ powertecscsi_dma_setup(struct Scsi_Host *host, Scsi_Pointer *SCp,
static void
powertecscsi_dma_stop(struct Scsi_Host *host, Scsi_Pointer *SCp)
{
- if (host->dma_channel != NO_DMA)
- disable_dma(host->dma_channel);
+ struct powertec_info *info = (struct powertec_info *)host->hostdata;
+ if (info->info.scsi.dma != NO_DMA)
+ disable_dma(info->info.scsi.dma);
}
/* Prototype: const char *powertecscsi_info(struct Scsi_Host * host)
@@ -315,7 +318,7 @@ powertecscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
struct Scsi_Host *host;
struct powertec_info *info;
unsigned long resbase, reslen;
- unsigned char *base;
+ void __iomem *base;
int ret;
ret = ecard_request_resources(ec);
@@ -337,26 +340,16 @@ powertecscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
goto out_unmap;
}
- host->base = (unsigned long)base;
- host->irq = ec->irq;
- host->dma_channel = ec->dma;
-
- ec->irqaddr = base + POWERTEC_INTR_STATUS;
- ec->irqmask = POWERTEC_INTR_BIT;
- ec->irq_data = base + POWERTEC_INTR_CONTROL;
- ec->ops = &powertecscsi_ops;
-
ecard_set_drvdata(ec, host);
info = (struct powertec_info *)host->hostdata;
- info->term_port = base + POWERTEC_TERM_CONTROL;
+ info->base = base;
powertecscsi_terminator_ctl(host, term[ec->slot_no]);
- device_create_file(&ec->dev, &dev_attr_bus_term);
-
info->info.scsi.io_base = base + POWERTEC_FAS216_OFFSET;
info->info.scsi.io_shift = POWERTEC_FAS216_SHIFT;
- info->info.scsi.irq = host->irq;
+ info->info.scsi.irq = ec->irq;
+ info->info.scsi.dma = ec->dma;
info->info.ifcfg.clockrate = 40; /* MHz */
info->info.ifcfg.select_timeout = 255;
info->info.ifcfg.asyncperiod = 200; /* ns */
@@ -369,25 +362,32 @@ powertecscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
info->info.dma.pseudo = NULL;
info->info.dma.stop = powertecscsi_dma_stop;
+ ec->irqaddr = base + POWERTEC_INTR_STATUS;
+ ec->irqmask = POWERTEC_INTR_BIT;
+ ec->irq_data = info;
+ ec->ops = &powertecscsi_ops;
+
+ device_create_file(&ec->dev, &dev_attr_bus_term);
+
ret = fas216_init(host);
if (ret)
goto out_free;
- ret = request_irq(host->irq, powertecscsi_intr,
+ ret = request_irq(ec->irq, powertecscsi_intr,
SA_INTERRUPT, "powertec", info);
if (ret) {
printk("scsi%d: IRQ%d not free: %d\n",
- host->host_no, host->irq, ret);
+ host->host_no, ec->irq, ret);
goto out_release;
}
- if (host->dma_channel != NO_DMA) {
- if (request_dma(host->dma_channel, "powertec")) {
+ if (info->info.scsi.dma != NO_DMA) {
+ if (request_dma(info->info.scsi.dma, "powertec")) {
printk("scsi%d: DMA%d not free, using PIO\n",
- host->host_no, host->dma_channel);
- host->dma_channel = NO_DMA;
+ host->host_no, info->info.scsi.dma);
+ info->info.scsi.dma = NO_DMA;
} else {
- set_dma_speed(host->dma_channel, 180);
+ set_dma_speed(info->info.scsi.dma, 180);
info->info.ifcfg.capabilities |= FASCAP_DMA;
}
}
@@ -396,9 +396,9 @@ powertecscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
if (ret == 0)
goto out;
- if (host->dma_channel != NO_DMA)
- free_dma(host->dma_channel);
- free_irq(host->irq, host);
+ if (info->info.scsi.dma != NO_DMA)
+ free_dma(info->info.scsi.dma);
+ free_irq(ec->irq, host);
out_release:
fas216_release(host);
@@ -420,18 +420,18 @@ powertecscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
static void __devexit powertecscsi_remove(struct expansion_card *ec)
{
struct Scsi_Host *host = ecard_get_drvdata(ec);
- struct powertecscsi_info *info = (struct powertecscsi_info *)host->hostdata;
+ struct powertec_info *info = (struct powertec_info *)host->hostdata;
ecard_set_drvdata(ec, NULL);
fas216_remove(host);
device_remove_file(&ec->dev, &dev_attr_bus_term);
- if (host->dma_channel != NO_DMA)
- free_dma(host->dma_channel);
- free_irq(host->irq, info);
+ if (info->info.scsi.dma != NO_DMA)
+ free_dma(info->info.scsi.dma);
+ free_irq(ec->irq, info);
- iounmap((void *)host->base);
+ iounmap(info->base);
fas216_release(host);
scsi_host_put(host);
diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c
index ad5b07c05efff..ce19728aa8a48 100644
--- a/drivers/scsi/ata_piix.c
+++ b/drivers/scsi/ata_piix.c
@@ -121,6 +121,7 @@ static 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,
};
static struct ata_port_operations piix_pata_ops = {
@@ -138,6 +139,8 @@ static struct ata_port_operations piix_pata_ops = {
.bmdma_setup = ata_bmdma_setup,
.bmdma_start = ata_bmdma_start,
+ .bmdma_stop = ata_bmdma_stop,
+ .bmdma_status = ata_bmdma_status,
.qc_prep = ata_qc_prep,
.qc_issue = ata_qc_issue_prot,
@@ -163,6 +166,8 @@ static struct ata_port_operations piix_sata_ops = {
.bmdma_setup = ata_bmdma_setup,
.bmdma_start = ata_bmdma_start,
+ .bmdma_stop = ata_bmdma_stop,
+ .bmdma_status = ata_bmdma_status,
.qc_prep = ata_qc_prep,
.qc_issue = ata_qc_issue_prot,
diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index 27136a20add95..45b75ddacaaba 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright (C) 1997 Wu Ching Chen
* 2.1.x update (C) 1998 Krzysztof G. Baranowski
* 2.5.x update (C) 2002 Red Hat <alan@redhat.com>
@@ -13,8 +13,9 @@
* fix disconnect bug 2000/12/21
* support atp880 chip lvd u160 2001/05/15
* fix prd table bug 2001/09/12 (7.1)
+ *
+ * atp885 support add by ACARD Hao Ping Lian 2005/01/05
*/
-
#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>
@@ -38,39 +39,54 @@
#include "atp870u.h"
static struct scsi_host_template atp870u_template;
-static void send_s870(struct Scsi_Host *host);
+static void send_s870(struct atp_unit *dev,unsigned char c);
+static void is885(struct atp_unit *dev, unsigned int wkport,unsigned char c);
+static void tscam_885(void);
-
-static irqreturn_t atp870u_intr_handle(int irq, void *dev_id,
- struct pt_regs *regs)
+static irqreturn_t atp870u_intr_handle(int irq, void *dev_id, struct pt_regs *regs)
{
unsigned long flags;
unsigned short int tmpcip, id;
- unsigned char i, j, target_id, lun;
+ unsigned char i, j, c, target_id, lun,cmdp;
unsigned char *prd;
- struct scsi_cmnd *workrequ;
- unsigned int workportu, tmport;
- unsigned long adrcntu, k;
+ struct scsi_cmnd *workreq;
+ unsigned int workport, tmport, tmport1;
+ unsigned long adrcnt, k;
+#ifdef ED_DBGP
+ unsigned long l;
+#endif
int errstus;
struct Scsi_Host *host = dev_id;
struct atp_unit *dev = (struct atp_unit *)&host->hostdata;
- dev->in_int = 1;
- workportu = dev->ioport;
- tmport = workportu;
-
- if (dev->working != 0) {
- tmport += 0x1f;
+ for (c = 0; c < 2; c++) {
+ tmport = dev->ioport[c] + 0x1f;
j = inb(tmport);
- if ((j & 0x80) == 0) {
- dev->in_int = 0;
- return IRQ_NONE;
- }
-
- tmpcip = dev->pciport;
- if ((inb(tmpcip) & 0x08) != 0) {
+ if ((j & 0x80) != 0)
+ {
+ goto ch_sel;
+ }
+ dev->in_int[c] = 0;
+ }
+ return IRQ_NONE;
+ch_sel:
+#ifdef ED_DBGP
+ printk("atp870u_intr_handle enter\n");
+#endif
+ dev->in_int[c] = 1;
+ cmdp = inb(dev->ioport[c] + 0x10);
+ workport = dev->ioport[c];
+ if (dev->working[c] != 0) {
+ if (dev->dev_id == ATP885_DEVID) {
+ tmport1 = workport + 0x16;
+ if ((inb(tmport1) & 0x80) == 0)
+ outb((inb(tmport1) | 0x80), tmport1);
+ }
+ tmpcip = dev->pciport[c];
+ if ((inb(tmpcip) & 0x08) != 0)
+ {
tmpcip += 0x2;
- for (k = 0; k < 1000; k++) {
+ for (k=0; k < 1000; k++) {
if ((inb(tmpcip) & 0x08) == 0) {
goto stop_dma;
}
@@ -80,18 +96,24 @@ static irqreturn_t atp870u_intr_handle(int irq, void *dev_id,
}
}
stop_dma:
- tmpcip = dev->pciport;
+ tmpcip = dev->pciport[c];
outb(0x00, tmpcip);
tmport -= 0x08;
-
+
i = inb(tmport);
+
+ if (dev->dev_id == ATP885_DEVID) {
+ tmpcip += 2;
+ outb(0x06, tmpcip);
+ tmpcip -= 2;
+ }
tmport -= 0x02;
target_id = inb(tmport);
tmport += 0x02;
/*
- * Remap wide devices onto id numbers
+ * Remap wide devices onto id numbers
*/
if ((target_id & 0x40) != 0) {
@@ -101,332 +123,460 @@ stop_dma:
}
if ((j & 0x40) != 0) {
- if (dev->last_cmd == 0xff) {
- dev->last_cmd = target_id;
- }
- dev->last_cmd |= 0x40;
- }
-
+ if (dev->last_cmd[c] == 0xff) {
+ dev->last_cmd[c] = target_id;
+ }
+ dev->last_cmd[c] |= 0x40;
+ }
+ if (dev->dev_id == ATP885_DEVID)
+ dev->r1f[c][target_id] |= j;
+#ifdef ED_DBGP
+ printk("atp870u_intr_handle status = %x\n",i);
+#endif
if (i == 0x85) {
- if ((dev->last_cmd & 0xf0) != 0x40) {
- dev->last_cmd = 0xff;
+ if ((dev->last_cmd[c] & 0xf0) != 0x40) {
+ dev->last_cmd[c] = 0xff;
+ }
+ if (dev->dev_id == ATP885_DEVID) {
+ tmport -= 0x05;
+ adrcnt = 0;
+ ((unsigned char *) &adrcnt)[2] = inb(tmport++);
+ ((unsigned char *) &adrcnt)[1] = inb(tmport++);
+ ((unsigned char *) &adrcnt)[0] = inb(tmport);
+ if (dev->id[c][target_id].last_len != adrcnt)
+ {
+ k = dev->id[c][target_id].last_len;
+ k -= adrcnt;
+ dev->id[c][target_id].tran_len = k;
+ dev->id[c][target_id].last_len = adrcnt;
+ }
+#ifdef ED_DBGP
+ printk("tmport = %x dev->id[c][target_id].last_len = %d dev->id[c][target_id].tran_len = %d\n",tmport,dev->id[c][target_id].last_len,dev->id[c][target_id].tran_len);
+#endif
}
+
/*
* Flip wide
- */
- if (dev->wide_idu != 0) {
- tmport = workportu + 0x1b;
+ */
+ if (dev->wide_id[c] != 0) {
+ tmport = workport + 0x1b;
outb(0x01, tmport);
while ((inb(tmport) & 0x01) != 0x01) {
outb(0x01, tmport);
}
- }
+ }
/*
- * Issue more commands
+ * Issue more commands
*/
- spin_lock_irqsave(dev->host->host_lock, flags);
- if (((dev->quhdu != dev->quendu) || (dev->last_cmd != 0xff)) && (dev->in_snd == 0)) {
- send_s870(host);
+ spin_lock_irqsave(dev->host->host_lock, flags);
+ if (((dev->quhd[c] != dev->quend[c]) || (dev->last_cmd[c] != 0xff)) &&
+ (dev->in_snd[c] == 0)) {
+#ifdef ED_DBGP
+ printk("Call sent_s870\n");
+#endif
+ send_s870(dev,c);
}
spin_unlock_irqrestore(dev->host->host_lock, flags);
/*
- * Done
+ * Done
*/
- dev->in_int = 0;
- goto out;
+ dev->in_int[c] = 0;
+#ifdef ED_DBGP
+ printk("Status 0x85 return\n");
+#endif
+ goto handled;
}
if (i == 0x40) {
- dev->last_cmd |= 0x40;
- dev->in_int = 0;
- goto out;
+ dev->last_cmd[c] |= 0x40;
+ dev->in_int[c] = 0;
+ goto handled;
}
if (i == 0x21) {
- if ((dev->last_cmd & 0xf0) != 0x40) {
- dev->last_cmd = 0xff;
+ if ((dev->last_cmd[c] & 0xf0) != 0x40) {
+ dev->last_cmd[c] = 0xff;
}
tmport -= 0x05;
- adrcntu = 0;
- ((unsigned char *) &adrcntu)[2] = inb(tmport++);
- ((unsigned char *) &adrcntu)[1] = inb(tmport++);
- ((unsigned char *) &adrcntu)[0] = inb(tmport);
- k = dev->id[target_id].last_lenu;
- k -= adrcntu;
- dev->id[target_id].tran_lenu = k;
- dev->id[target_id].last_lenu = adrcntu;
+ adrcnt = 0;
+ ((unsigned char *) &adrcnt)[2] = inb(tmport++);
+ ((unsigned char *) &adrcnt)[1] = inb(tmport++);
+ ((unsigned char *) &adrcnt)[0] = inb(tmport);
+ k = dev->id[c][target_id].last_len;
+ k -= adrcnt;
+ dev->id[c][target_id].tran_len = k;
+ dev->id[c][target_id].last_len = adrcnt;
tmport -= 0x04;
outb(0x41, tmport);
tmport += 0x08;
outb(0x08, tmport);
- dev->in_int = 0;
- goto out;
+ dev->in_int[c] = 0;
+ goto handled;
+ }
+
+ if (dev->dev_id == ATP885_DEVID) {
+ if ((i == 0x4c) || (i == 0x4d) || (i == 0x8c) || (i == 0x8d)) {
+ if ((i == 0x4c) || (i == 0x8c))
+ i=0x48;
+ else
+ i=0x49;
+ }
+
}
if ((i == 0x80) || (i == 0x8f)) {
+#ifdef ED_DBGP
+ printk(KERN_DEBUG "Device reselect\n");
+#endif
lun = 0;
tmport -= 0x07;
- j = inb(tmport);
- if (j == 0x44 || i == 0x80) {
+ if (cmdp == 0x44 || i==0x80) {
tmport += 0x0d;
lun = inb(tmport) & 0x07;
} else {
- if ((dev->last_cmd & 0xf0) != 0x40) {
- dev->last_cmd = 0xff;
+ if ((dev->last_cmd[c] & 0xf0) != 0x40) {
+ dev->last_cmd[c] = 0xff;
}
- if (j == 0x41) {
+ if (cmdp == 0x41) {
+#ifdef ED_DBGP
+ printk("cmdp = 0x41\n");
+#endif
tmport += 0x02;
- adrcntu = 0;
- ((unsigned char *) &adrcntu)[2] = inb(tmport++);
- ((unsigned char *) &adrcntu)[1] = inb(tmport++);
- ((unsigned char *) &adrcntu)[0] = inb(tmport);
- k = dev->id[target_id].last_lenu;
- k -= adrcntu;
- dev->id[target_id].tran_lenu = k;
- dev->id[target_id].last_lenu = adrcntu;
+ adrcnt = 0;
+ ((unsigned char *) &adrcnt)[2] = inb(tmport++);
+ ((unsigned char *) &adrcnt)[1] = inb(tmport++);
+ ((unsigned char *) &adrcnt)[0] = inb(tmport);
+ k = dev->id[c][target_id].last_len;
+ k -= adrcnt;
+ dev->id[c][target_id].tran_len = k;
+ dev->id[c][target_id].last_len = adrcnt;
tmport += 0x04;
outb(0x08, tmport);
- dev->in_int = 0;
- goto out;
+ dev->in_int[c] = 0;
+ goto handled;
} else {
+#ifdef ED_DBGP
+ printk("cmdp != 0x41\n");
+#endif
outb(0x46, tmport);
- dev->id[target_id].dirctu = 0x00;
+ dev->id[c][target_id].dirct = 0x00;
tmport += 0x02;
outb(0x00, tmport++);
outb(0x00, tmport++);
outb(0x00, tmport++);
tmport += 0x03;
outb(0x08, tmport);
- dev->in_int = 0;
- goto out;
+ dev->in_int[c] = 0;
+ goto handled;
}
}
- if (dev->last_cmd != 0xff) {
- dev->last_cmd |= 0x40;
+ if (dev->last_cmd[c] != 0xff) {
+ dev->last_cmd[c] |= 0x40;
}
- tmport = workportu + 0x10;
- outb(0x45, tmport);
- tmport += 0x06;
+ if (dev->dev_id == ATP885_DEVID) {
+ j = inb(dev->baseport + 0x29) & 0xfe;
+ outb(j, dev->baseport + 0x29);
+ tmport = workport + 0x16;
+ } else {
+ tmport = workport + 0x10;
+ outb(0x45, tmport);
+ tmport += 0x06;
+ }
+
target_id = inb(tmport);
/*
- * Remap wide identifiers
+ * Remap wide identifiers
*/
if ((target_id & 0x10) != 0) {
target_id = (target_id & 0x07) | 0x08;
} else {
target_id &= 0x07;
}
- workrequ = dev->id[target_id].curr_req;
- tmport = workportu + 0x0f;
+ if (dev->dev_id == ATP885_DEVID) {
+ tmport = workport + 0x10;
+ outb(0x45, tmport);
+ }
+ workreq = dev->id[c][target_id].curr_req;
+#ifdef ED_DBGP
+ printk(KERN_DEBUG "Channel = %d ID = %d LUN = %d CDB",c,workreq->device->id,workreq->device->lun);
+ for(l=0;l<workreq->cmd_len;l++)
+ {
+ printk(KERN_DEBUG " %x",workreq->cmnd[l]);
+ }
+#endif
+
+ tmport = workport + 0x0f;
outb(lun, tmport);
tmport += 0x02;
- outb(dev->id[target_id].devspu, tmport++);
- adrcntu = dev->id[target_id].tran_lenu;
- k = dev->id[target_id].last_lenu;
+ outb(dev->id[c][target_id].devsp, tmport++);
+ adrcnt = dev->id[c][target_id].tran_len;
+ k = dev->id[c][target_id].last_len;
+
outb(((unsigned char *) &k)[2], tmport++);
outb(((unsigned char *) &k)[1], tmport++);
outb(((unsigned char *) &k)[0], tmport++);
+#ifdef ED_DBGP
+ printk("k %x, k[0] 0x%x k[1] 0x%x k[2] 0x%x\n", k, inb(tmport-1), inb(tmport-2), inb(tmport-3));
+#endif
/* Remap wide */
j = target_id;
if (target_id > 7) {
j = (j & 0x07) | 0x40;
}
/* Add direction */
- j |= dev->id[target_id].dirctu;
+ j |= dev->id[c][target_id].dirct;
outb(j, tmport++);
- outb(0x80, tmport);
-
- /* enable 32 bit fifo transfer */
- if (dev->deviceid != 0x8081) {
- tmport = workportu + 0x3a;
- if ((dev->ata_cdbu[0] == 0x08) || (dev->ata_cdbu[0] == 0x28) || (dev->ata_cdbu[0] == 0x0a) || (dev->ata_cdbu[0] == 0x2a)) {
- outb((unsigned char) ((inb(tmport) & 0xf3) | 0x08), tmport);
- } else {
- outb((unsigned char) (inb(tmport) & 0xf3), tmport);
+ outb(0x80,tmport);
+
+ /* enable 32 bit fifo transfer */
+ if (dev->dev_id == ATP885_DEVID) {
+ tmpcip = dev->pciport[c] + 1;
+ i=inb(tmpcip) & 0xf3;
+ //j=workreq->cmnd[0];
+ if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) || (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a)) {
+ i |= 0x0c;
}
- } else {
- tmport = workportu - 0x05;
- if ((dev->ata_cdbu[0] == 0x08) || (dev->ata_cdbu[0] == 0x28) || (dev->ata_cdbu[0] == 0x0a) || (dev->ata_cdbu[0] == 0x2a)) {
+ outb(i,tmpcip);
+ } else if ((dev->dev_id == ATP880_DEVID1) ||
+ (dev->dev_id == ATP880_DEVID2) ) {
+ tmport = workport - 0x05;
+ if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) || (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a)) {
outb((unsigned char) ((inb(tmport) & 0x3f) | 0xc0), tmport);
} else {
outb((unsigned char) (inb(tmport) & 0x3f), tmport);
}
- }
-
- tmport = workportu + 0x1b;
+ } else {
+ tmport = workport + 0x3a;
+ if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) || (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a)) {
+ outb((unsigned char) ((inb(tmport) & 0xf3) | 0x08), tmport);
+ } else {
+ outb((unsigned char) (inb(tmport) & 0xf3), tmport);
+ }
+ }
+ tmport = workport + 0x1b;
j = 0;
id = 1;
id = id << target_id;
/*
- * Is this a wide device
+ * Is this a wide device
*/
- if ((id & dev->wide_idu) != 0) {
+ if ((id & dev->wide_id[c]) != 0) {
j |= 0x01;
}
outb(j, tmport);
while ((inb(tmport) & 0x01) != j) {
- outb(j, tmport);
+ outb(j,tmport);
}
-
- if (dev->id[target_id].last_lenu == 0) {
- tmport = workportu + 0x18;
+ if (dev->id[c][target_id].last_len == 0) {
+ tmport = workport + 0x18;
outb(0x08, tmport);
- dev->in_int = 0;
- goto out;
+ dev->in_int[c] = 0;
+#ifdef ED_DBGP
+ printk("dev->id[c][target_id].last_len = 0\n");
+#endif
+ goto handled;
}
- prd = dev->id[target_id].prd_posu;
- while (adrcntu != 0) {
- id = ((unsigned short int *) (prd))[2];
+#ifdef ED_DBGP
+ printk("target_id = %d adrcnt = %d\n",target_id,adrcnt);
+#endif
+ prd = dev->id[c][target_id].prd_pos;
+ while (adrcnt != 0) {
+ id = ((unsigned short int *)prd)[2];
if (id == 0) {
k = 0x10000;
} else {
k = id;
}
- if (k > adrcntu) {
- ((unsigned short int *) (prd))[2] = (unsigned short int)
- (k - adrcntu);
- ((unsigned long *) (prd))[0] += adrcntu;
- adrcntu = 0;
- dev->id[target_id].prd_posu = prd;
+ if (k > adrcnt) {
+ ((unsigned short int *)prd)[2] = (unsigned short int)
+ (k - adrcnt);
+ ((unsigned long *)prd)[0] += adrcnt;
+ adrcnt = 0;
+ dev->id[c][target_id].prd_pos = prd;
} else {
- adrcntu -= k;
- dev->id[target_id].prdaddru += 0x08;
+ adrcnt -= k;
+ dev->id[c][target_id].prdaddr += 0x08;
prd += 0x08;
- if (adrcntu == 0) {
- dev->id[target_id].prd_posu = prd;
+ if (adrcnt == 0) {
+ dev->id[c][target_id].prd_pos = prd;
}
- }
+ }
}
- tmpcip = dev->pciport + 0x04;
- outl(dev->id[target_id].prdaddru, tmpcip);
- tmpcip -= 0x02;
- outb(0x06, tmpcip);
- outb(0x00, tmpcip);
- tmpcip -= 0x02;
- tmport = workportu + 0x18;
+ tmpcip = dev->pciport[c] + 0x04;
+ outl(dev->id[c][target_id].prdaddr, tmpcip);
+#ifdef ED_DBGP
+ printk("dev->id[%d][%d].prdaddr 0x%8x\n", c, target_id, dev->id[c][target_id].prdaddr);
+#endif
+ if (dev->dev_id == ATP885_DEVID) {
+ tmpcip -= 0x04;
+ } else {
+ tmpcip -= 0x02;
+ outb(0x06, tmpcip);
+ outb(0x00, tmpcip);
+ tmpcip -= 0x02;
+ }
+ tmport = workport + 0x18;
/*
- * Check transfer direction
+ * Check transfer direction
*/
- if (dev->id[target_id].dirctu != 0) {
+ if (dev->id[c][target_id].dirct != 0) {
outb(0x08, tmport);
outb(0x01, tmpcip);
- dev->in_int = 0;
- goto out;
+ dev->in_int[c] = 0;
+#ifdef ED_DBGP
+ printk("status 0x80 return dirct != 0\n");
+#endif
+ goto handled;
}
outb(0x08, tmport);
outb(0x09, tmpcip);
- dev->in_int = 0;
- goto out;
+ dev->in_int[c] = 0;
+#ifdef ED_DBGP
+ printk("status 0x80 return dirct = 0\n");
+#endif
+ goto handled;
}
/*
- * Current scsi request on this target
+ * Current scsi request on this target
*/
- workrequ = dev->id[target_id].curr_req;
+ workreq = dev->id[c][target_id].curr_req;
if (i == 0x42) {
- if ((dev->last_cmd & 0xf0) != 0x40) {
- dev->last_cmd = 0xff;
+ if ((dev->last_cmd[c] & 0xf0) != 0x40)
+ {
+ dev->last_cmd[c] = 0xff;
}
errstus = 0x02;
- workrequ->result = errstus;
+ workreq->result = errstus;
goto go_42;
}
if (i == 0x16) {
- if ((dev->last_cmd & 0xf0) != 0x40) {
- dev->last_cmd = 0xff;
+ if ((dev->last_cmd[c] & 0xf0) != 0x40) {
+ dev->last_cmd[c] = 0xff;
}
errstus = 0;
tmport -= 0x08;
errstus = inb(tmport);
- workrequ->result = errstus;
+ if (((dev->r1f[c][target_id] & 0x10) != 0)&&(dev->dev_id==ATP885_DEVID)) {
+ printk(KERN_WARNING "AEC67162 CRC ERROR !\n");
+ errstus = 0x02;
+ }
+ workreq->result = errstus;
go_42:
+ if (dev->dev_id == ATP885_DEVID) {
+ j = inb(dev->baseport + 0x29) | 0x01;
+ outb(j, dev->baseport + 0x29);
+ }
/*
- * Complete the command
+ * Complete the command
*/
-
- if (workrequ->use_sg) {
+ if (workreq->use_sg) {
pci_unmap_sg(dev->pdev,
- (struct scatterlist *)workrequ->buffer,
- workrequ->use_sg,
- workrequ->sc_data_direction);
- } else if (workrequ->request_bufflen &&
- workrequ->sc_data_direction != DMA_NONE) {
+ (struct scatterlist *)workreq->buffer,
+ workreq->use_sg,
+ workreq->sc_data_direction);
+ } else if (workreq->request_bufflen &&
+ workreq->sc_data_direction != DMA_NONE) {
pci_unmap_single(dev->pdev,
- workrequ->SCp.dma_handle,
- workrequ->request_bufflen,
- workrequ->sc_data_direction);
- }
+ workreq->SCp.dma_handle,
+ workreq->request_bufflen,
+ workreq->sc_data_direction);
+ }
spin_lock_irqsave(dev->host->host_lock, flags);
- (*workrequ->scsi_done) (workrequ);
-
+ (*workreq->scsi_done) (workreq);
+#ifdef ED_DBGP
+ printk("workreq->scsi_done\n");
+#endif
/*
- * Clear it off the queue
+ * Clear it off the queue
*/
- dev->id[target_id].curr_req = NULL;
- dev->working--;
+ dev->id[c][target_id].curr_req = NULL;
+ dev->working[c]--;
spin_unlock_irqrestore(dev->host->host_lock, flags);
/*
* Take it back wide
*/
- if (dev->wide_idu != 0) {
- tmport = workportu + 0x1b;
+ if (dev->wide_id[c] != 0) {
+ tmport = workport + 0x1b;
outb(0x01, tmport);
while ((inb(tmport) & 0x01) != 0x01) {
outb(0x01, tmport);
- }
- }
+ }
+ }
/*
- * If there is stuff to send and nothing going then send it
+ * If there is stuff to send and nothing going then send it
*/
spin_lock_irqsave(dev->host->host_lock, flags);
- if (((dev->last_cmd != 0xff) || (dev->quhdu != dev->quendu)) && (dev->in_snd == 0)) {
- send_s870(host);
+ if (((dev->last_cmd[c] != 0xff) || (dev->quhd[c] != dev->quend[c])) &&
+ (dev->in_snd[c] == 0)) {
+#ifdef ED_DBGP
+ printk("Call sent_s870(scsi_done)\n");
+#endif
+ send_s870(dev,c);
}
spin_unlock_irqrestore(dev->host->host_lock, flags);
- dev->in_int = 0;
- goto out;
+ dev->in_int[c] = 0;
+ goto handled;
}
- if ((dev->last_cmd & 0xf0) != 0x40) {
- dev->last_cmd = 0xff;
+ if ((dev->last_cmd[c] & 0xf0) != 0x40) {
+ dev->last_cmd[c] = 0xff;
}
if (i == 0x4f) {
i = 0x89;
}
i &= 0x0f;
if (i == 0x09) {
- tmpcip = tmpcip + 4;
- outl(dev->id[target_id].prdaddru, tmpcip);
+ tmpcip += 4;
+ outl(dev->id[c][target_id].prdaddr, tmpcip);
tmpcip = tmpcip - 2;
outb(0x06, tmpcip);
outb(0x00, tmpcip);
tmpcip = tmpcip - 2;
- tmport = workportu + 0x10;
+ tmport = workport + 0x10;
outb(0x41, tmport);
- dev->id[target_id].dirctu = 0x00;
- tmport += 0x08;
+ if (dev->dev_id == ATP885_DEVID) {
+ tmport += 2;
+ k = dev->id[c][target_id].last_len;
+ outb((unsigned char) (((unsigned char *) (&k))[2]), tmport++);
+ outb((unsigned char) (((unsigned char *) (&k))[1]), tmport++);
+ outb((unsigned char) (((unsigned char *) (&k))[0]), tmport);
+ dev->id[c][target_id].dirct = 0x00;
+ tmport += 0x04;
+ } else {
+ dev->id[c][target_id].dirct = 0x00;
+ tmport += 0x08;
+ }
outb(0x08, tmport);
outb(0x09, tmpcip);
- dev->in_int = 0;
- goto out;
+ dev->in_int[c] = 0;
+ goto handled;
}
if (i == 0x08) {
- tmpcip = tmpcip + 4;
- outl(dev->id[target_id].prdaddru, tmpcip);
+ tmpcip += 4;
+ outl(dev->id[c][target_id].prdaddr, tmpcip);
tmpcip = tmpcip - 2;
outb(0x06, tmpcip);
outb(0x00, tmpcip);
tmpcip = tmpcip - 2;
- tmport = workportu + 0x10;
+ tmport = workport + 0x10;
outb(0x41, tmport);
- tmport += 0x05;
+ if (dev->dev_id == ATP885_DEVID) {
+ tmport += 2;
+ k = dev->id[c][target_id].last_len;
+ outb((unsigned char) (((unsigned char *) (&k))[2]), tmport++);
+ outb((unsigned char) (((unsigned char *) (&k))[1]), tmport++);
+ outb((unsigned char) (((unsigned char *) (&k))[0]), tmport++);
+ } else {
+ tmport += 5;
+ }
outb((unsigned char) (inb(tmport) | 0x20), tmport);
- dev->id[target_id].dirctu = 0x20;
+ dev->id[c][target_id].dirct = 0x20;
tmport += 0x03;
outb(0x08, tmport);
outb(0x01, tmpcip);
- dev->in_int = 0;
- goto out;
+ dev->in_int[c] = 0;
+ goto handled;
}
tmport -= 0x07;
if (i == 0x0a) {
@@ -434,25 +584,29 @@ go_42:
} else {
outb(0x46, tmport);
}
- dev->id[target_id].dirctu = 0x00;
+ dev->id[c][target_id].dirct = 0x00;
tmport += 0x02;
outb(0x00, tmport++);
outb(0x00, tmport++);
outb(0x00, tmport++);
tmport += 0x03;
outb(0x08, tmport);
- dev->in_int = 0;
- goto out;
+ dev->in_int[c] = 0;
+ goto handled;
} else {
-// tmport = workportu + 0x17;
-// inb(tmport);
-// dev->working = 0;
- dev->in_int = 0;
+// tmport = workport + 0x17;
+// inb(tmport);
+// dev->working[c] = 0;
+ dev->in_int[c] = 0;
+ goto handled;
}
-out:
+
+handled:
+#ifdef ED_DBGP
+ printk("atp870u_intr_handle exit\n");
+#endif
return IRQ_HANDLED;
}
-
/**
* atp870u_queuecommand - Queue SCSI command
* @req_p: request block
@@ -460,24 +614,31 @@ out:
*
* Queue a command to the ATP queue. Called with the host lock held.
*/
-
-static int atp870u_queuecommand(struct scsi_cmnd *req_p,
- void (*done) (struct scsi_cmnd *))
+static int atp870u_queuecommand(struct scsi_cmnd * req_p,
+ void (*done) (struct scsi_cmnd *))
{
- unsigned short int m;
- unsigned int tmport;
- struct Scsi_Host *host;
+ unsigned char c;
+ unsigned int tmport,m;
struct atp_unit *dev;
+ struct Scsi_Host *host;
- if (req_p->device->channel != 0) {
+ c = req_p->device->channel;
+ req_p->sense_buffer[0]=0;
+ req_p->resid = 0;
+ if (req_p->device->channel > 1) {
req_p->result = 0x00040000;
done(req_p);
+#ifdef ED_DBGP
+ printk("atp870u_queuecommand : req_p->device->channel > 1\n");
+#endif
return 0;
- };
+ }
host = req_p->device->host;
dev = (struct atp_unit *)&host->hostdata;
-
+
+
+
m = 1;
m = m << req_p->device->id;
@@ -485,44 +646,60 @@ static int atp870u_queuecommand(struct scsi_cmnd *req_p,
* Fake a timeout for missing targets
*/
- if ((m & dev->active_idu) == 0) {
+ if ((m & dev->active_id[c]) == 0) {
req_p->result = 0x00040000;
done(req_p);
return 0;
}
+
if (done) {
req_p->scsi_done = done;
} else {
- printk(KERN_WARNING "atp870u_queuecommand: done can't be NULL\n");
+#ifdef ED_DBGP
+ printk( "atp870u_queuecommand: done can't be NULL\n");
+#endif
req_p->result = 0;
done(req_p);
return 0;
}
+
/*
- * Count new command
+ * Count new command
*/
-
- dev->quendu++;
- if (dev->quendu >= qcnt) {
- dev->quendu = 0;
+ dev->quend[c]++;
+ if (dev->quend[c] >= qcnt) {
+ dev->quend[c] = 0;
}
+
/*
- * Check queue state
+ * Check queue state
*/
- if (dev->quhdu == dev->quendu) {
- if (dev->quendu == 0) {
- dev->quendu = qcnt;
- }
- dev->quendu--;
+ if (dev->quhd[c] == dev->quend[c]) {
+ if (dev->quend[c] == 0) {
+ dev->quend[c] = qcnt;
+ }
+#ifdef ED_DBGP
+ printk("atp870u_queuecommand : dev->quhd[c] == dev->quend[c]\n");
+#endif
+ dev->quend[c]--;
req_p->result = 0x00020000;
- done(req_p);
+ done(req_p);
return 0;
}
- dev->querequ[dev->quendu] = req_p;
- tmport = dev->ioport + 0x1c;
- if ((inb(tmport) == 0) && (dev->in_int == 0) && (dev->in_snd == 0)) {
- send_s870(host);
- }
+ dev->quereq[c][dev->quend[c]] = req_p;
+ tmport = dev->ioport[c] + 0x1c;
+#ifdef ED_DBGP
+ printk("dev->ioport[c] = %x inb(tmport) = %x dev->in_int[%d] = %d dev->in_snd[%d] = %d\n",dev->ioport[c],inb(tmport),c,dev->in_int[c],c,dev->in_snd[c]);
+#endif
+ if ((inb(tmport) == 0) && (dev->in_int[c] == 0) && (dev->in_snd[c] == 0)) {
+#ifdef ED_DBGP
+ printk("Call sent_s870(atp870u_queuecommand)\n");
+#endif
+ send_s870(dev,c);
+ }
+#ifdef ED_DBGP
+ printk("atp870u_queuecommand : exit\n");
+#endif
return 0;
}
@@ -535,194 +712,242 @@ static int atp870u_queuecommand(struct scsi_cmnd *req_p,
*
* Caller holds the host lock.
*/
-
-static void send_s870(struct Scsi_Host *host)
+static void send_s870(struct atp_unit *dev,unsigned char c)
{
unsigned int tmport;
- struct scsi_cmnd *workrequ;
- unsigned int i;
- unsigned char j, target_id;
+ struct scsi_cmnd *workreq;
+ unsigned int i;//,k;
+ unsigned char j, target_id;
unsigned char *prd;
unsigned short int tmpcip, w;
- unsigned long l;
- dma_addr_t bttl;
- unsigned int workportu;
+ unsigned long l, bttl = 0;
+ unsigned int workport;
struct scatterlist *sgpnt;
- struct atp_unit *dev = (struct atp_unit *)&host->hostdata;
- int sg_count;
+ unsigned long sg_count;
- if (dev->in_snd != 0) {
- return;
- }
- dev->in_snd = 1;
- if ((dev->last_cmd != 0xff) && ((dev->last_cmd & 0x40) != 0)) {
- dev->last_cmd &= 0x0f;
- workrequ = dev->id[dev->last_cmd].curr_req;
- if (workrequ != NULL) { /* check NULL pointer */
- goto cmd_subp;
- }
- dev->last_cmd = 0xff;
- if (dev->quhdu == dev->quendu) {
- dev->in_snd = 0;
- return;
- }
- }
- if ((dev->last_cmd != 0xff) && (dev->working != 0)) {
- dev->in_snd = 0;
+ if (dev->in_snd[c] != 0) {
+#ifdef ED_DBGP
+ printk("cmnd in_snd\n");
+#endif
return;
}
- dev->working++;
- j = dev->quhdu;
- dev->quhdu++;
- if (dev->quhdu >= qcnt) {
- dev->quhdu = 0;
- }
- workrequ = dev->querequ[dev->quhdu];
- if (dev->id[workrequ->device->id].curr_req == 0) {
- dev->id[workrequ->device->id].curr_req = workrequ;
- dev->last_cmd = workrequ->device->id;
+#ifdef ED_DBGP
+ printk("Sent_s870 enter\n");
+#endif
+ dev->in_snd[c] = 1;
+ if ((dev->last_cmd[c] != 0xff) && ((dev->last_cmd[c] & 0x40) != 0)) {
+ dev->last_cmd[c] &= 0x0f;
+ workreq = dev->id[c][dev->last_cmd[c]].curr_req;
+ if (workreq != NULL) { /* check NULL pointer */
+ goto cmd_subp;
+ }
+ dev->last_cmd[c] = 0xff;
+ if (dev->quhd[c] == dev->quend[c]) {
+ dev->in_snd[c] = 0;
+ return ;
+ }
+ }
+ if ((dev->last_cmd[c] != 0xff) && (dev->working[c] != 0)) {
+ dev->in_snd[c] = 0;
+ return ;
+ }
+ dev->working[c]++;
+ j = dev->quhd[c];
+ dev->quhd[c]++;
+ if (dev->quhd[c] >= qcnt) {
+ dev->quhd[c] = 0;
+ }
+ workreq = dev->quereq[c][dev->quhd[c]];
+ if (dev->id[c][workreq->device->id].curr_req == 0) {
+ dev->id[c][workreq->device->id].curr_req = workreq;
+ dev->last_cmd[c] = workreq->device->id;
goto cmd_subp;
- }
- dev->quhdu = j;
- dev->working--;
- dev->in_snd = 0;
+ }
+ dev->quhd[c] = j;
+ dev->working[c]--;
+ dev->in_snd[c] = 0;
return;
cmd_subp:
- workportu = dev->ioport;
- tmport = workportu + 0x1f;
+ workport = dev->ioport[c];
+ tmport = workport + 0x1f;
if ((inb(tmport) & 0xb0) != 0) {
goto abortsnd;
}
- tmport = workportu + 0x1c;
+ tmport = workport + 0x1c;
if (inb(tmport) == 0) {
goto oktosend;
}
abortsnd:
- dev->last_cmd |= 0x40;
- dev->in_snd = 0;
+#ifdef ED_DBGP
+ printk("Abort to Send\n");
+#endif
+ dev->last_cmd[c] |= 0x40;
+ dev->in_snd[c] = 0;
return;
oktosend:
- memcpy(&dev->ata_cdbu[0], &workrequ->cmnd[0], workrequ->cmd_len);
- if (dev->ata_cdbu[0] == READ_CAPACITY) {
- if (workrequ->request_bufflen > 8) {
- workrequ->request_bufflen = 0x08;
+#ifdef ED_DBGP
+ printk("OK to Send\n");
+ printk("CDB");
+ for(i=0;i<workreq->cmd_len;i++) {
+ printk(" %x",workreq->cmnd[i]);
+ }
+ printk("\nChannel = %d ID = %d LUN = %d\n",c,workreq->device->id,workreq->device->lun);
+#endif
+ if (dev->dev_id == ATP885_DEVID) {
+ j = inb(dev->baseport + 0x29) & 0xfe;
+ outb(j, dev->baseport + 0x29);
+ dev->r1f[c][workreq->device->id] = 0;
+ }
+
+ if (workreq->cmnd[0] == READ_CAPACITY) {
+ if (workreq->request_bufflen > 8) {
+ workreq->request_bufflen = 0x08;
}
}
- if (dev->ata_cdbu[0] == 0x00) {
- workrequ->request_bufflen = 0;
+ if (workreq->cmnd[0] == 0x00) {
+ workreq->request_bufflen = 0;
}
- tmport = workportu + 0x1b;
+ tmport = workport + 0x1b;
j = 0;
- target_id = workrequ->device->id;
+ target_id = workreq->device->id;
/*
- * Wide ?
+ * Wide ?
*/
w = 1;
w = w << target_id;
- if ((w & dev->wide_idu) != 0) {
+ if ((w & dev->wide_id[c]) != 0) {
j |= 0x01;
}
outb(j, tmport);
while ((inb(tmport) & 0x01) != j) {
- outb(j, tmport);
+ outb(j,tmport);
+#ifdef ED_DBGP
+ printk("send_s870 while loop 1\n");
+#endif
}
-
/*
- * Write the command
+ * Write the command
*/
- tmport = workportu;
- outb(workrequ->cmd_len, tmport++);
+ tmport = workport;
+ outb(workreq->cmd_len, tmport++);
outb(0x2c, tmport++);
- outb(0xcf, tmport++);
- for (i = 0; i < workrequ->cmd_len; i++) {
- outb(dev->ata_cdbu[i], tmport++);
+ if (dev->dev_id == ATP885_DEVID) {
+ outb(0x7f, tmport++);
+ } else {
+ outb(0xcf, tmport++);
+ }
+ for (i = 0; i < workreq->cmd_len; i++) {
+ outb(workreq->cmnd[i], tmport++);
}
- tmport = workportu + 0x0f;
- outb(workrequ->device->lun, tmport);
+ tmport = workport + 0x0f;
+ outb(workreq->device->lun, tmport);
tmport += 0x02;
/*
- * Write the target
+ * Write the target
*/
- outb(dev->id[target_id].devspu, tmport++);
-
+ outb(dev->id[c][target_id].devsp, tmport++);
+#ifdef ED_DBGP
+ printk("dev->id[%d][%d].devsp = %2x\n",c,target_id,dev->id[c][target_id].devsp);
+#endif
/*
- * Figure out the transfer size
+ * Figure out the transfer size
*/
- if (workrequ->use_sg) {
+ if (workreq->use_sg) {
+#ifdef ED_DBGP
+ printk("Using SGL\n");
+#endif
l = 0;
- sgpnt = (struct scatterlist *) workrequ->request_buffer;
- sg_count = pci_map_sg(dev->pdev, sgpnt, workrequ->use_sg,
- workrequ->sc_data_direction);
- for (i = 0; i < workrequ->use_sg; i++) {
- if (sgpnt[i].length == 0 || workrequ->use_sg > ATP870U_SCATTER) {
+
+ sgpnt = (struct scatterlist *) workreq->request_buffer;
+ sg_count = pci_map_sg(dev->pdev, sgpnt, workreq->use_sg,
+ workreq->sc_data_direction);
+
+ for (i = 0; i < workreq->use_sg; i++) {
+ if (sgpnt[i].length == 0 || workreq->use_sg > ATP870U_SCATTER) {
panic("Foooooooood fight!");
}
l += sgpnt[i].length;
}
- } else if(workrequ->request_bufflen && workrequ->sc_data_direction != PCI_DMA_NONE) {
- workrequ->SCp.dma_handle = pci_map_single(dev->pdev,
- workrequ->request_buffer,
- workrequ->request_bufflen,
- workrequ->sc_data_direction);
- l = workrequ->request_bufflen;
- }
- else l = 0;
+#ifdef ED_DBGP
+ printk( "send_s870: workreq->use_sg %d, sg_count %d l %8ld\n", workreq->use_sg, sg_count, l);
+#endif
+ } else if(workreq->request_bufflen && workreq->sc_data_direction != PCI_DMA_NONE) {
+#ifdef ED_DBGP
+ printk("Not using SGL\n");
+#endif
+ workreq->SCp.dma_handle = pci_map_single(dev->pdev, workreq->request_buffer,
+ workreq->request_bufflen,
+ workreq->sc_data_direction);
+ l = workreq->request_bufflen;
+#ifdef ED_DBGP
+ printk( "send_s870: workreq->use_sg %d, l %8ld\n", workreq->use_sg, l);
+#endif
+ } else l = 0;
/*
- * Write transfer size
+ * Write transfer size
*/
outb((unsigned char) (((unsigned char *) (&l))[2]), tmport++);
outb((unsigned char) (((unsigned char *) (&l))[1]), tmport++);
outb((unsigned char) (((unsigned char *) (&l))[0]), tmport++);
- j = target_id;
- dev->id[j].last_lenu = l;
- dev->id[j].tran_lenu = 0;
+ j = target_id;
+ dev->id[c][j].last_len = l;
+ dev->id[c][j].tran_len = 0;
+#ifdef ED_DBGP
+ printk("dev->id[%2d][%2d].last_len = %d\n",c,j,dev->id[c][j].last_len);
+#endif
/*
- * Flip the wide bits
+ * Flip the wide bits
*/
if ((j & 0x08) != 0) {
j = (j & 0x07) | 0x40;
}
/*
- * Check transfer direction
+ * Check transfer direction
*/
- if (workrequ->sc_data_direction == DMA_TO_DEVICE) {
+ if (workreq->sc_data_direction == DMA_TO_DEVICE) {
outb((unsigned char) (j | 0x20), tmport++);
} else {
outb(j, tmport++);
}
outb((unsigned char) (inb(tmport) | 0x80), tmport);
outb(0x80, tmport);
- tmport = workportu + 0x1c;
- dev->id[target_id].dirctu = 0;
+ tmport = workport + 0x1c;
+ dev->id[c][target_id].dirct = 0;
if (l == 0) {
if (inb(tmport) == 0) {
- tmport = workportu + 0x18;
+ tmport = workport + 0x18;
+#ifdef ED_DBGP
+ printk("change SCSI_CMD_REG 0x08\n");
+#endif
outb(0x08, tmport);
} else {
- dev->last_cmd |= 0x40;
+ dev->last_cmd[c] |= 0x40;
}
- dev->in_snd = 0;
+ dev->in_snd[c] = 0;
return;
}
- tmpcip = dev->pciport;
- prd = dev->id[target_id].prd_tableu;
- dev->id[target_id].prd_posu = prd;
+ tmpcip = dev->pciport[c];
+ prd = dev->id[c][target_id].prd_table;
+ dev->id[c][target_id].prd_pos = prd;
/*
- * Now write the request list. Either as scatter/gather or as
- * a linear chain.
+ * Now write the request list. Either as scatter/gather or as
+ * a linear chain.
*/
- if (workrequ->use_sg) {
- sgpnt = (struct scatterlist *) workrequ->request_buffer;
+ if (workreq->use_sg) {
+ sgpnt = (struct scatterlist *) workreq->request_buffer;
i = 0;
- for (j = 0; j < workrequ->use_sg; j++) {
+ for (j = 0; j < workreq->use_sg; j++) {
bttl = sg_dma_address(&sgpnt[j]);
- l = sg_dma_len(&sgpnt[j]);
- while (l > 0x10000) {
+ l=sg_dma_len(&sgpnt[j]);
+#ifdef ED_DBGP
+ printk("1. bttl %x, l %x\n",bttl, l);
+#endif
+ while (l > 0x10000) {
(((u16 *) (prd))[i + 3]) = 0x0000;
(((u16 *) (prd))[i + 2]) = 0x0000;
(((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl);
@@ -733,73 +958,105 @@ oktosend:
(((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl);
(((u16 *) (prd))[i + 2]) = cpu_to_le16(l);
(((u16 *) (prd))[i + 3]) = 0;
- i += 0x04;
+ i += 0x04;
}
- (((u16 *) (prd))[i - 1]) = cpu_to_le16(0x8000);
+ (((u16 *) (prd))[i - 1]) = cpu_to_le16(0x8000);
+#ifdef ED_DBGP
+ printk("prd %4x %4x %4x %4x\n",(((unsigned short int *)prd)[0]),(((unsigned short int *)prd)[1]),(((unsigned short int *)prd)[2]),(((unsigned short int *)prd)[3]));
+ printk("2. bttl %x, l %x\n",bttl, l);
+#endif
} else {
/*
- * For a linear request write a chain of blocks
- */
- bttl = workrequ->SCp.dma_handle;
- l = workrequ->request_bufflen;
+ * For a linear request write a chain of blocks
+ */
+ bttl = workreq->SCp.dma_handle;
+ l = workreq->request_bufflen;
i = 0;
+#ifdef ED_DBGP
+ printk("3. bttl %x, l %x\n",bttl, l);
+#endif
while (l > 0x10000) {
- (((u16 *) (prd))[i + 3]) = 0x0000;
- (((u16 *) (prd))[i + 2]) = 0x0000;
- (((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl);
- l -= 0x10000;
- bttl += 0x10000;
- i += 0x04;
- }
- (((u16 *) (prd))[i + 3]) = cpu_to_le16(0x8000);
- (((u16 *) (prd))[i + 2]) = cpu_to_le16(l);
- (((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl);
+ (((u16 *) (prd))[i + 3]) = 0x0000;
+ (((u16 *) (prd))[i + 2]) = 0x0000;
+ (((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl);
+ l -= 0x10000;
+ bttl += 0x10000;
+ i += 0x04;
+ }
+ (((u16 *) (prd))[i + 3]) = cpu_to_le16(0x8000);
+ (((u16 *) (prd))[i + 2]) = cpu_to_le16(l);
+ (((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl);
+#ifdef ED_DBGP
+ printk("prd %4x %4x %4x %4x\n",(((unsigned short int *)prd)[0]),(((unsigned short int *)prd)[1]),(((unsigned short int *)prd)[2]),(((unsigned short int *)prd)[3]));
+ printk("4. bttl %x, l %x\n",bttl, l);
+#endif
+
}
- tmpcip = tmpcip + 4;
- dev->id[target_id].prdaddru = dev->id[target_id].prd_phys;
- outl(dev->id[target_id].prd_phys, tmpcip);
+ tmpcip += 4;
+#ifdef ED_DBGP
+ printk("send_s870: prdaddr_2 0x%8x tmpcip %x target_id %d\n", dev->id[c][target_id].prdaddr,tmpcip,target_id);
+#endif
+ outl(dev->id[c][target_id].prdaddr, tmpcip);
tmpcip = tmpcip - 2;
outb(0x06, tmpcip);
outb(0x00, tmpcip);
- tmpcip = tmpcip - 2;
-
- if (dev->deviceid != 0x8081) {
- tmport = workportu + 0x3a;
- if ((dev->ata_cdbu[0] == 0x08) || (dev->ata_cdbu[0] == 0x28) || (dev->ata_cdbu[0] == 0x0a) || (dev->ata_cdbu[0] == 0x2a)) {
- outb((inb(tmport) & 0xf3) | 0x08, tmport);
- } else {
- outb(inb(tmport) & 0xf3, tmport);
- }
- } else {
- tmport = workportu - 0x05;
- if ((dev->ata_cdbu[0] == 0x08) || (dev->ata_cdbu[0] == 0x28) || (dev->ata_cdbu[0] == 0x0a) || (dev->ata_cdbu[0] == 0x2a)) {
+ if (dev->dev_id == ATP885_DEVID) {
+ tmpcip--;
+ j=inb(tmpcip) & 0xf3;
+ if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) ||
+ (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a)) {
+ j |= 0x0c;
+ }
+ outb(j,tmpcip);
+ tmpcip--;
+ } else if ((dev->dev_id == ATP880_DEVID1) ||
+ (dev->dev_id == ATP880_DEVID2)) {
+ tmpcip =tmpcip -2;
+ tmport = workport - 0x05;
+ if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) || (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a)) {
outb((unsigned char) ((inb(tmport) & 0x3f) | 0xc0), tmport);
} else {
outb((unsigned char) (inb(tmport) & 0x3f), tmport);
- }
- }
- tmport = workportu + 0x1c;
+ }
+ } else {
+ tmpcip =tmpcip -2;
+ tmport = workport + 0x3a;
+ if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) || (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a)) {
+ outb((inb(tmport) & 0xf3) | 0x08, tmport);
+ } else {
+ outb(inb(tmport) & 0xf3, tmport);
+ }
+ }
+ tmport = workport + 0x1c;
- if (workrequ->sc_data_direction == DMA_TO_DEVICE) {
- dev->id[target_id].dirctu = 0x20;
+ if(workreq->sc_data_direction == DMA_TO_DEVICE) {
+ dev->id[c][target_id].dirct = 0x20;
if (inb(tmport) == 0) {
- tmport = workportu + 0x18;
+ tmport = workport + 0x18;
outb(0x08, tmport);
outb(0x01, tmpcip);
+#ifdef ED_DBGP
+ printk( "start DMA(to target)\n");
+#endif
} else {
- dev->last_cmd |= 0x40;
+ dev->last_cmd[c] |= 0x40;
}
- dev->in_snd = 0;
+ dev->in_snd[c] = 0;
return;
}
- if (inb(tmport) == 0) {
- tmport = workportu + 0x18;
+ if (inb(tmport) == 0) {
+ tmport = workport + 0x18;
outb(0x08, tmport);
outb(0x09, tmpcip);
+#ifdef ED_DBGP
+ printk( "start DMA(to host)\n");
+#endif
} else {
- dev->last_cmd |= 0x40;
+ dev->last_cmd[c] |= 0x40;
}
- dev->in_snd = 0;
+ dev->in_snd[c] = 0;
+ return;
+
}
static unsigned char fun_scam(struct atp_unit *dev, unsigned short int *val)
@@ -808,7 +1065,7 @@ static unsigned char fun_scam(struct atp_unit *dev, unsigned short int *val)
unsigned short int i, k;
unsigned char j;
- tmport = dev->ioport + 0x1c;
+ tmport = dev->ioport[0] + 0x1c;
outw(*val, tmport);
FUN_D7:
for (i = 0; i < 10; i++) { /* stable >= bus settle delay(400 ns) */
@@ -863,24 +1120,24 @@ static void tscam(struct Scsi_Host *host)
}
*/
- tmport = dev->ioport + 1;
+ tmport = dev->ioport[0] + 1;
outb(0x08, tmport++);
outb(0x7f, tmport);
- tmport = dev->ioport + 0x11;
+ tmport = dev->ioport[0] + 0x11;
outb(0x20, tmport);
if ((dev->scam_on & 0x40) == 0) {
return;
}
m = 1;
- m <<= dev->host_idu;
+ m <<= dev->host_id[0];
j = 16;
- if (dev->chip_veru < 4) {
+ if (dev->chip_ver < 4) {
m |= 0xff00;
j = 8;
}
assignid_map = m;
- tmport = dev->ioport + 0x02;
+ tmport = dev->ioport[0] + 0x02;
outb(0x02, tmport++); /* 2*2=4ms,3EH 2/32*3E=3.9ms */
outb(0, tmport++);
outb(0, tmport++);
@@ -895,7 +1152,7 @@ static void tscam(struct Scsi_Host *host)
if ((m & assignid_map) != 0) {
continue;
}
- tmport = dev->ioport + 0x0f;
+ tmport = dev->ioport[0] + 0x0f;
outb(0, tmport++);
tmport += 0x02;
outb(0, tmport++);
@@ -907,40 +1164,41 @@ static void tscam(struct Scsi_Host *host)
k = i;
}
outb(k, tmport++);
- tmport = dev->ioport + 0x1b;
- if (dev->chip_veru == 4) {
+ tmport = dev->ioport[0] + 0x1b;
+ if (dev->chip_ver == 4) {
outb(0x01, tmport);
} else {
outb(0x00, tmport);
}
wait_rdyok:
- tmport = dev->ioport + 0x18;
+ tmport = dev->ioport[0] + 0x18;
outb(0x09, tmport);
tmport += 0x07;
- while ((inb(tmport) & 0x80) == 0x00);
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
tmport -= 0x08;
k = inb(tmport);
if (k != 0x16) {
if ((k == 0x85) || (k == 0x42)) {
continue;
}
- tmport = dev->ioport + 0x10;
+ tmport = dev->ioport[0] + 0x10;
outb(0x41, tmport);
goto wait_rdyok;
}
assignid_map |= m;
}
- tmport = dev->ioport + 0x02;
+ tmport = dev->ioport[0] + 0x02;
outb(0x7f, tmport);
- tmport = dev->ioport + 0x1b;
+ tmport = dev->ioport[0] + 0x1b;
outb(0x02, tmport);
outb(0, 0x80);
val = 0x0080; /* bsy */
- tmport = dev->ioport + 0x1c;
+ tmport = dev->ioport[0] + 0x1c;
outw(val, tmport);
val |= 0x0040; /* sel */
outw(val, tmport);
@@ -984,12 +1242,13 @@ TCM_SYNC:
if ((inb(tmport) & 0x80) == 0x00) { /* bsy ? */
outw(0, tmport--);
outb(0, tmport);
- tmport = dev->ioport + 0x15;
+ tmport = dev->ioport[0] + 0x15;
outb(0, tmport);
tmport += 0x03;
outb(0x09, tmport);
tmport += 0x07;
- while ((inb(tmport) & 0x80) == 0);
+ while ((inb(tmport) & 0x80) == 0)
+ cpu_relax();
tmport -= 0x08;
inb(tmport);
return;
@@ -1085,7 +1344,7 @@ G2Q_QUIN: /* k=binID#, */
}
-static void is870(struct Scsi_Host *host, unsigned int wkport)
+static void is870(struct atp_unit *dev, unsigned int wkport)
{
unsigned int tmport;
unsigned char i, j, k, rmb, n;
@@ -1097,26 +1356,25 @@ static void is870(struct Scsi_Host *host, unsigned int wkport)
static unsigned char synu[6] = { 0x80, 1, 3, 1, 0x0c, 0x0e };
static unsigned char synw[6] = { 0x80, 1, 3, 1, 0x0c, 0x07 };
static unsigned char wide[6] = { 0x80, 1, 2, 3, 1, 0 };
- struct atp_unit *dev = (struct atp_unit *)&host->hostdata;
-
+
tmport = wkport + 0x3a;
outb((unsigned char) (inb(tmport) | 0x10), tmport);
for (i = 0; i < 16; i++) {
- if ((dev->chip_veru != 4) && (i > 7)) {
+ if ((dev->chip_ver != 4) && (i > 7)) {
break;
}
m = 1;
m = m << i;
- if ((m & dev->active_idu) != 0) {
+ if ((m & dev->active_id[0]) != 0) {
continue;
}
- if (i == dev->host_idu) {
- printk(KERN_INFO " ID: %2d Host Adapter\n", dev->host_idu);
+ if (i == dev->host_id[0]) {
+ printk(KERN_INFO " ID: %2d Host Adapter\n", dev->host_id[0]);
continue;
}
tmport = wkport + 0x1b;
- if (dev->chip_veru == 4) {
+ if (dev->chip_ver == 4) {
outb(0x01, tmport);
} else {
outb(0x00, tmport);
@@ -1133,7 +1391,7 @@ static void is870(struct Scsi_Host *host, unsigned int wkport)
tmport += 0x06;
outb(0, tmport);
tmport += 0x02;
- outb(dev->id[i].devspu, tmport++);
+ outb(dev->id[0][i].devsp, tmport++);
outb(0, tmport++);
outb(satn[6], tmport++);
outb(satn[7], tmport++);
@@ -1146,13 +1404,17 @@ static void is870(struct Scsi_Host *host, unsigned int wkport)
outb(satn[8], tmport);
tmport += 0x07;
- while ((inb(tmport) & 0x80) == 0x00);
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
+
tmport -= 0x08;
- if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
+ if (inb(tmport) != 0x11 && inb(tmport) != 0x8e)
continue;
- }
- while (inb(tmport) != 0x8e);
- dev->active_idu |= m;
+
+ while (inb(tmport) != 0x8e)
+ cpu_relax();
+
+ dev->active_id[0] |= m;
tmport = wkport + 0x10;
outb(0x30, tmport);
@@ -1163,7 +1425,8 @@ phase_cmd:
tmport = wkport + 0x18;
outb(0x08, tmport);
tmport += 0x07;
- while ((inb(tmport) & 0x80) == 0x00);
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
tmport -= 0x08;
j = inb(tmport);
if (j != 0x16) {
@@ -1182,23 +1445,28 @@ sel_ok:
tmport += 0x07;
outb(0, tmport);
tmport += 0x02;
- outb(dev->id[i].devspu, tmport++);
+ outb(dev->id[0][i].devsp, tmport++);
outb(0, tmport++);
outb(inqd[6], tmport++);
outb(inqd[7], tmport++);
tmport += 0x03;
outb(inqd[8], tmport);
tmport += 0x07;
- while ((inb(tmport) & 0x80) == 0x00);
+
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
+
tmport -= 0x08;
- if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
+ if (inb(tmport) != 0x11 && inb(tmport) != 0x8e)
continue;
- }
- while (inb(tmport) != 0x8e);
+
+ while (inb(tmport) != 0x8e)
+ cpu_relax();
+
tmport = wkport + 0x1b;
- if (dev->chip_veru == 4) {
+ if (dev->chip_ver == 4)
outb(0x00, tmport);
- }
+
tmport = wkport + 0x18;
outb(0x08, tmport);
tmport += 0x07;
@@ -1228,7 +1496,10 @@ rd_inq_data:
tmport += 0x03;
outb(0x08, tmport);
tmport += 0x07;
- while ((inb(tmport) & 0x80) == 0x00);
+
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
+
tmport -= 0x08;
if (inb(tmport) != 0x16) {
goto sel_ok;
@@ -1236,16 +1507,16 @@ rd_inq_data:
inq_ok:
mbuf[36] = 0;
printk(KERN_INFO " ID: %2d %s\n", i, &mbuf[8]);
- dev->id[i].devtypeu = mbuf[0];
+ dev->id[0][i].devtype = mbuf[0];
rmb = mbuf[1];
n = mbuf[7];
- if (dev->chip_veru != 4) {
+ if (dev->chip_ver != 4) {
goto not_wide;
}
if ((mbuf[7] & 0x60) == 0) {
goto not_wide;
}
- if ((dev->global_map & 0x20) == 0) {
+ if ((dev->global_map[0] & 0x20) == 0) {
goto not_wide;
}
tmport = wkport + 0x1b;
@@ -1260,7 +1531,7 @@ inq_ok:
tmport += 0x06;
outb(0, tmport);
tmport += 0x02;
- outb(dev->id[i].devspu, tmport++);
+ outb(dev->id[0][i].devsp, tmport++);
outb(0, tmport++);
outb(satn[6], tmport++);
outb(satn[7], tmport++);
@@ -1268,12 +1539,16 @@ inq_ok:
outb(satn[8], tmport);
tmport += 0x07;
- while ((inb(tmport) & 0x80) == 0x00);
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
+
tmport -= 0x08;
- if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
+ if (inb(tmport) != 0x11 && inb(tmport) != 0x8e)
continue;
- }
- while (inb(tmport) != 0x8e);
+
+ while (inb(tmport) != 0x8e)
+ cpu_relax();
+
try_wide:
j = 0;
tmport = wkport + 0x14;
@@ -1290,7 +1565,10 @@ try_wide:
}
}
tmport -= 0x08;
- while ((inb(tmport) & 0x80) == 0x00);
+
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
+
j = inb(tmport) & 0x0f;
if (j == 0x0f) {
goto widep_in;
@@ -1363,7 +1641,10 @@ widep_cmd:
tmport += 0x04;
outb(0x08, tmport);
tmport += 0x07;
- while ((inb(tmport) & 0x80) == 0x00);
+
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
+
tmport -= 0x08;
j = inb(tmport);
if (j != 0x16) {
@@ -1386,16 +1667,16 @@ widep_cmd:
}
m = 1;
m = m << i;
- dev->wide_idu |= m;
+ dev->wide_id[0] |= m;
not_wide:
- if ((dev->id[i].devtypeu == 0x00) || (dev->id[i].devtypeu == 0x07) || ((dev->id[i].devtypeu == 0x05) && ((n & 0x10) != 0))) {
+ if ((dev->id[0][i].devtype == 0x00) || (dev->id[0][i].devtype == 0x07) || ((dev->id[0][i].devtype == 0x05) && ((n & 0x10) != 0))) {
goto set_sync;
}
continue;
set_sync:
tmport = wkport + 0x1b;
j = 0;
- if ((m & dev->wide_idu) != 0) {
+ if ((m & dev->wide_id[0]) != 0) {
j |= 0x01;
}
outb(j, tmport);
@@ -1409,7 +1690,7 @@ set_sync:
tmport += 0x06;
outb(0, tmport);
tmport += 0x02;
- outb(dev->id[i].devspu, tmport++);
+ outb(dev->id[0][i].devsp, tmport++);
outb(0, tmport++);
outb(satn[6], tmport++);
outb(satn[7], tmport++);
@@ -1417,12 +1698,16 @@ set_sync:
outb(satn[8], tmport);
tmport += 0x07;
- while ((inb(tmport) & 0x80) == 0x00);
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
+
tmport -= 0x08;
- if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
+ if (inb(tmport) != 0x11 && inb(tmport) != 0x8e)
continue;
- }
- while (inb(tmport) != 0x8e);
+
+ while (inb(tmport) != 0x8e)
+ cpu_relax();
+
try_sync:
j = 0;
tmport = wkport + 0x14;
@@ -1434,10 +1719,10 @@ try_sync:
while ((inb(tmport) & 0x80) == 0) {
if ((inb(tmport) & 0x01) != 0) {
tmport -= 0x06;
- if ((m & dev->wide_idu) != 0) {
+ if ((m & dev->wide_id[0]) != 0) {
outb(synw[j++], tmport);
} else {
- if ((m & dev->ultra_map) != 0) {
+ if ((m & dev->ultra_map[0]) != 0) {
outb(synu[j++], tmport);
} else {
outb(synn[j++], tmport);
@@ -1447,7 +1732,10 @@ try_sync:
}
}
tmport -= 0x08;
- while ((inb(tmport) & 0x80) == 0x00);
+
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
+
j = inb(tmport) & 0x0f;
if (j == 0x0f) {
goto phase_ins;
@@ -1505,7 +1793,10 @@ phase_ins1:
goto phase_ins1;
}
tmport -= 0x08;
- while ((inb(tmport) & 0x80) == 0x00);
+
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
+
j = inb(tmport);
if (j == 0x85) {
goto tar_dcons;
@@ -1530,7 +1821,10 @@ tar_dcons:
tmport += 0x04;
outb(0x08, tmport);
tmport += 0x07;
- while ((inb(tmport) & 0x80) == 0x00);
+
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
+
tmport -= 0x08;
j = inb(tmport);
if (j != 0x16) {
@@ -1551,7 +1845,7 @@ tar_dcons:
if (mbuf[4] > 0x0c) {
mbuf[4] = 0x0c;
}
- dev->id[i].devspu = mbuf[4];
+ dev->id[0][i].devsp = mbuf[4];
if ((mbuf[3] < 0x0d) && (rmb == 0)) {
j = 0xa0;
goto set_syn_ok;
@@ -1570,13 +1864,13 @@ tar_dcons:
}
j = 0x60;
set_syn_ok:
- dev->id[i].devspu = (dev->id[i].devspu & 0x0f) | j;
+ dev->id[0][i].devsp = (dev->id[0][i].devsp & 0x0f) | j;
}
tmport = wkport + 0x3a;
outb((unsigned char) (inb(tmport) & 0xef), tmport);
}
-static void is880(struct Scsi_Host *host, unsigned int wkport)
+static void is880(struct atp_unit *dev, unsigned int wkport)
{
unsigned int tmport;
unsigned char i, j, k, rmb, n, lvdmode;
@@ -1590,18 +1884,17 @@ static void is880(struct Scsi_Host *host, unsigned int wkport)
unsigned char synuw[6] = { 0x80, 1, 3, 1, 0x0a, 0x0e };
static unsigned char wide[6] = { 0x80, 1, 2, 3, 1, 0 };
static unsigned char u3[9] = { 0x80, 1, 6, 4, 0x09, 00, 0x0e, 0x01, 0x02 };
- struct atp_unit *dev = (struct atp_unit *)&host->hostdata;
lvdmode = inb(wkport + 0x3f) & 0x40;
for (i = 0; i < 16; i++) {
m = 1;
m = m << i;
- if ((m & dev->active_idu) != 0) {
+ if ((m & dev->active_id[0]) != 0) {
continue;
}
- if (i == dev->host_idu) {
- printk(KERN_INFO " ID: %2d Host Adapter\n", dev->host_idu);
+ if (i == dev->host_id[0]) {
+ printk(KERN_INFO " ID: %2d Host Adapter\n", dev->host_id[0]);
continue;
}
tmport = wkport + 0x5b;
@@ -1618,7 +1911,7 @@ static void is880(struct Scsi_Host *host, unsigned int wkport)
tmport += 0x06;
outb(0, tmport);
tmport += 0x02;
- outb(dev->id[i].devspu, tmport++);
+ outb(dev->id[0][i].devsp, tmport++);
outb(0, tmport++);
outb(satn[6], tmport++);
outb(satn[7], tmport++);
@@ -1631,13 +1924,17 @@ static void is880(struct Scsi_Host *host, unsigned int wkport)
outb(satn[8], tmport);
tmport += 0x07;
- while ((inb(tmport) & 0x80) == 0x00);
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
+
tmport -= 0x08;
- if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
+ if (inb(tmport) != 0x11 && inb(tmport) != 0x8e)
continue;
- }
- while (inb(tmport) != 0x8e);
- dev->active_idu |= m;
+
+ while (inb(tmport) != 0x8e)
+ cpu_relax();
+
+ dev->active_id[0] |= m;
tmport = wkport + 0x50;
outb(0x30, tmport);
@@ -1648,7 +1945,10 @@ phase_cmd:
tmport = wkport + 0x58;
outb(0x08, tmport);
tmport += 0x07;
- while ((inb(tmport) & 0x80) == 0x00);
+
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
+
tmport -= 0x08;
j = inb(tmport);
if (j != 0x16) {
@@ -1667,19 +1967,24 @@ sel_ok:
tmport += 0x07;
outb(0, tmport);
tmport += 0x02;
- outb(dev->id[i].devspu, tmport++);
+ outb(dev->id[0][i].devsp, tmport++);
outb(0, tmport++);
outb(inqd[6], tmport++);
outb(inqd[7], tmport++);
tmport += 0x03;
outb(inqd[8], tmport);
tmport += 0x07;
- while ((inb(tmport) & 0x80) == 0x00);
+
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
+
tmport -= 0x08;
- if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
+ if (inb(tmport) != 0x11 && inb(tmport) != 0x8e)
continue;
- }
- while (inb(tmport) != 0x8e);
+
+ while (inb(tmport) != 0x8e)
+ cpu_relax();
+
tmport = wkport + 0x5b;
outb(0x00, tmport);
tmport = wkport + 0x58;
@@ -1711,27 +2016,29 @@ rd_inq_data:
tmport += 0x03;
outb(0x08, tmport);
tmport += 0x07;
- while ((inb(tmport) & 0x80) == 0x00);
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
+
tmport -= 0x08;
- if (inb(tmport) != 0x16) {
+ if (inb(tmport) != 0x16)
goto sel_ok;
- }
+
inq_ok:
mbuf[36] = 0;
printk(KERN_INFO " ID: %2d %s\n", i, &mbuf[8]);
- dev->id[i].devtypeu = mbuf[0];
+ dev->id[0][i].devtype = mbuf[0];
rmb = mbuf[1];
n = mbuf[7];
if ((mbuf[7] & 0x60) == 0) {
goto not_wide;
}
- if ((i < 8) && ((dev->global_map & 0x20) == 0)) {
+ if ((i < 8) && ((dev->global_map[0] & 0x20) == 0)) {
goto not_wide;
}
if (lvdmode == 0) {
goto chg_wide;
}
- if (dev->sp[i] != 0x04) // force u2
+ if (dev->sp[0][i] != 0x04) // force u2
{
goto chg_wide;
}
@@ -1748,7 +2055,7 @@ inq_ok:
tmport += 0x06;
outb(0, tmport);
tmport += 0x02;
- outb(dev->id[i].devspu, tmport++);
+ outb(dev->id[0][i].devsp, tmport++);
outb(0, tmport++);
outb(satn[6], tmport++);
outb(satn[7], tmport++);
@@ -1756,12 +2063,17 @@ inq_ok:
outb(satn[8], tmport);
tmport += 0x07;
- while ((inb(tmport) & 0x80) == 0x00);
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
+
tmport -= 0x08;
- if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
+
+ if (inb(tmport) != 0x11 && inb(tmport) != 0x8e)
continue;
- }
- while (inb(tmport) != 0x8e);
+
+ while (inb(tmport) != 0x8e)
+ cpu_relax();
+
try_u3:
j = 0;
tmport = wkport + 0x54;
@@ -1778,7 +2090,10 @@ try_u3:
}
}
tmport -= 0x08;
- while ((inb(tmport) & 0x80) == 0x00);
+
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
+
j = inb(tmport) & 0x0f;
if (j == 0x0f) {
goto u3p_in;
@@ -1851,7 +2166,10 @@ u3p_cmd:
tmport += 0x04;
outb(0x08, tmport);
tmport += 0x07;
- while ((inb(tmport) & 0x80) == 0x00);
+
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
+
tmport -= 0x08;
j = inb(tmport);
if (j != 0x16) {
@@ -1872,8 +2190,8 @@ u3p_cmd:
if (mbuf[3] == 0x09) {
m = 1;
m = m << i;
- dev->wide_idu |= m;
- dev->id[i].devspu = 0xce;
+ dev->wide_id[0] |= m;
+ dev->id[0][i].devsp = 0xce;
continue;
}
chg_wide:
@@ -1889,7 +2207,7 @@ chg_wide:
tmport += 0x06;
outb(0, tmport);
tmport += 0x02;
- outb(dev->id[i].devspu, tmport++);
+ outb(dev->id[0][i].devsp, tmport++);
outb(0, tmport++);
outb(satn[6], tmport++);
outb(satn[7], tmport++);
@@ -1897,12 +2215,16 @@ chg_wide:
outb(satn[8], tmport);
tmport += 0x07;
- while ((inb(tmport) & 0x80) == 0x00);
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
+
tmport -= 0x08;
- if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
+ if (inb(tmport) != 0x11 && inb(tmport) != 0x8e)
continue;
- }
- while (inb(tmport) != 0x8e);
+
+ while (inb(tmport) != 0x8e)
+ cpu_relax();
+
try_wide:
j = 0;
tmport = wkport + 0x54;
@@ -1919,7 +2241,9 @@ try_wide:
}
}
tmport -= 0x08;
- while ((inb(tmport) & 0x80) == 0x00);
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
+
j = inb(tmport) & 0x0f;
if (j == 0x0f) {
goto widep_in;
@@ -1992,7 +2316,10 @@ widep_cmd:
tmport += 0x04;
outb(0x08, tmport);
tmport += 0x07;
- while ((inb(tmport) & 0x80) == 0x00);
+
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
+
tmport -= 0x08;
j = inb(tmport);
if (j != 0x16) {
@@ -2015,29 +2342,29 @@ widep_cmd:
}
m = 1;
m = m << i;
- dev->wide_idu |= m;
+ dev->wide_id[0] |= m;
not_wide:
- if ((dev->id[i].devtypeu == 0x00) || (dev->id[i].devtypeu == 0x07) || ((dev->id[i].devtypeu == 0x05) && ((n & 0x10) != 0))) {
+ if ((dev->id[0][i].devtype == 0x00) || (dev->id[0][i].devtype == 0x07) || ((dev->id[0][i].devtype == 0x05) && ((n & 0x10) != 0))) {
m = 1;
m = m << i;
- if ((dev->async & m) != 0) {
+ if ((dev->async[0] & m) != 0) {
goto set_sync;
}
}
continue;
set_sync:
- if (dev->sp[i] == 0x02) {
+ if (dev->sp[0][i] == 0x02) {
synu[4] = 0x0c;
synuw[4] = 0x0c;
} else {
- if (dev->sp[i] >= 0x03) {
+ if (dev->sp[0][i] >= 0x03) {
synu[4] = 0x0a;
synuw[4] = 0x0a;
}
}
tmport = wkport + 0x5b;
j = 0;
- if ((m & dev->wide_idu) != 0) {
+ if ((m & dev->wide_id[0]) != 0) {
j |= 0x01;
}
outb(j, tmport);
@@ -2051,7 +2378,7 @@ set_sync:
tmport += 0x06;
outb(0, tmport);
tmport += 0x02;
- outb(dev->id[i].devspu, tmport++);
+ outb(dev->id[0][i].devsp, tmport++);
outb(0, tmport++);
outb(satn[6], tmport++);
outb(satn[7], tmport++);
@@ -2059,12 +2386,16 @@ set_sync:
outb(satn[8], tmport);
tmport += 0x07;
- while ((inb(tmport) & 0x80) == 0x00);
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
+
tmport -= 0x08;
if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
continue;
}
- while (inb(tmport) != 0x8e);
+ while (inb(tmport) != 0x8e)
+ cpu_relax();
+
try_sync:
j = 0;
tmport = wkport + 0x54;
@@ -2076,14 +2407,14 @@ try_sync:
while ((inb(tmport) & 0x80) == 0) {
if ((inb(tmport) & 0x01) != 0) {
tmport -= 0x06;
- if ((m & dev->wide_idu) != 0) {
- if ((m & dev->ultra_map) != 0) {
+ if ((m & dev->wide_id[0]) != 0) {
+ if ((m & dev->ultra_map[0]) != 0) {
outb(synuw[j++], tmport);
} else {
outb(synw[j++], tmport);
}
} else {
- if ((m & dev->ultra_map) != 0) {
+ if ((m & dev->ultra_map[0]) != 0) {
outb(synu[j++], tmport);
} else {
outb(synn[j++], tmport);
@@ -2093,7 +2424,10 @@ try_sync:
}
}
tmport -= 0x08;
- while ((inb(tmport) & 0x80) == 0x00);
+
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
+
j = inb(tmport) & 0x0f;
if (j == 0x0f) {
goto phase_ins;
@@ -2151,7 +2485,10 @@ phase_ins1:
goto phase_ins1;
}
tmport -= 0x08;
- while ((inb(tmport) & 0x80) == 0x00);
+
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
+
j = inb(tmport);
if (j == 0x85) {
goto tar_dcons;
@@ -2176,7 +2513,10 @@ tar_dcons:
tmport += 0x04;
outb(0x08, tmport);
tmport += 0x07;
- while ((inb(tmport) & 0x80) == 0x00);
+
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
+
tmport -= 0x08;
j = inb(tmport);
if (j != 0x16) {
@@ -2197,7 +2537,7 @@ tar_dcons:
if (mbuf[4] > 0x0e) {
mbuf[4] = 0x0e;
}
- dev->id[i].devspu = mbuf[4];
+ dev->id[0][i].devsp = mbuf[4];
if (mbuf[3] < 0x0c) {
j = 0xb0;
goto set_syn_ok;
@@ -2220,249 +2560,179 @@ tar_dcons:
}
j = 0x60;
set_syn_ok:
- dev->id[i].devspu = (dev->id[i].devspu & 0x0f) | j;
+ dev->id[0][i].devsp = (dev->id[0][i].devsp & 0x0f) | j;
}
}
static void atp870u_free_tables(struct Scsi_Host *host)
{
struct atp_unit *atp_dev = (struct atp_unit *)&host->hostdata;
- int k;
-
- for (k = 0; k < 16; k++) {
- if (!atp_dev->id[k].prd_tableu)
- continue;
- pci_free_consistent(atp_dev->pdev, 1024, atp_dev->id[k].prd_tableu,
- atp_dev->id[k].prd_phys);
- atp_dev->id[k].prd_tableu = NULL;
+ int j, k;
+ for (j=0; j < 2; j++) {
+ for (k = 0; k < 16; k++) {
+ if (!atp_dev->id[j][k].prd_table)
+ continue;
+ pci_free_consistent(atp_dev->pdev, 1024, atp_dev->id[j][k].prd_table, atp_dev->id[j][k].prdaddr);
+ atp_dev->id[j][k].prd_table = NULL;
+ }
}
}
static int atp870u_init_tables(struct Scsi_Host *host)
{
- struct atp_unit *dev = (struct atp_unit *)&host->hostdata;
- int k, i;
-
- for (i = k = 0; k < 16; k++) {
- dev->id[k].prd_tableu = pci_alloc_consistent(dev->pdev, 1024, &dev->id[k].prd_phys);
- if (!dev->id[k].prd_tableu) {
- atp870u_free_tables(host);
- return -ENOMEM;
- }
- dev->id[k].devspu = 0x20;
- dev->id[k].devtypeu = 0;
- dev->id[k].curr_req = NULL;
- }
- dev->active_idu = 0;
- dev->wide_idu = 0;
- dev->host_idu = 0x07;
- dev->quhdu = 0;
- dev->quendu = 0;
- dev->chip_veru = 0;
- dev->last_cmd = 0xff;
- dev->in_snd = 0;
- dev->in_int = 0;
- for (k = 0; k < qcnt; k++) {
- dev->querequ[k] = NULL;
- }
- for (k = 0; k < 16; k++) {
- dev->id[k].curr_req = NULL;
- dev->sp[k] = 0x04;
+ struct atp_unit *atp_dev = (struct atp_unit *)&host->hostdata;
+ int c,k;
+ for(c=0;c < 2;c++) {
+ for(k=0;k<16;k++) {
+ atp_dev->id[c][k].prd_table = pci_alloc_consistent(atp_dev->pdev, 1024, &(atp_dev->id[c][k].prdaddr));
+ if (!atp_dev->id[c][k].prd_table) {
+ printk("atp870u_init_tables fail\n");
+ atp870u_free_tables(host);
+ return -ENOMEM;
+ }
+ atp_dev->id[c][k].devsp=0x20;
+ atp_dev->id[c][k].devtype = 0x7f;
+ atp_dev->id[c][k].curr_req = NULL;
+ }
+
+ atp_dev->active_id[c] = 0;
+ atp_dev->wide_id[c] = 0;
+ atp_dev->host_id[c] = 0x07;
+ atp_dev->quhd[c] = 0;
+ atp_dev->quend[c] = 0;
+ atp_dev->last_cmd[c] = 0xff;
+ atp_dev->in_snd[c] = 0;
+ atp_dev->in_int[c] = 0;
+
+ for (k = 0; k < qcnt; k++) {
+ atp_dev->quereq[c][k] = NULL;
+ }
+ for (k = 0; k < 16; k++) {
+ atp_dev->id[c][k].curr_req = NULL;
+ atp_dev->sp[c][k] = 0x04;
+ }
}
return 0;
}
/* return non-zero on detection */
-static int atp870u_probe(struct pci_dev *dev, const struct pci_device_id *ent)
+static int atp870u_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
- unsigned char k, m;
+ unsigned char k, m, c;
unsigned long flags;
- unsigned int base_io, error, tmport;
+ unsigned int base_io, tmport, error,n;
unsigned char host_id;
- unsigned short n;
- struct Scsi_Host *shpnt;
+ struct Scsi_Host *shpnt = NULL;
struct atp_unit atp_dev, *p;
- static int count;
-
- if (pci_enable_device(dev))
+ unsigned char setupdata[2][16];
+ int count = 0;
+
+ if (pci_enable_device(pdev))
return -EIO;
- if (pci_set_dma_mask(dev, 0xFFFFFFFFUL)) {
- printk(KERN_ERR "atp870u: 32bit DMA mask required but not available.\n");
- return -EIO;
- }
-
+ if (!pci_set_dma_mask(pdev, 0xFFFFFFFFUL)) {
+ printk(KERN_INFO "atp870u: use 32bit DMA mask.\n");
+ } else {
+ printk(KERN_ERR "atp870u: DMA mask required but not available.\n");
+ return -EIO;
+ }
+
memset(&atp_dev, 0, sizeof atp_dev);
-
/*
* It's probably easier to weed out some revisions like
* this than via the PCI device table
*/
if (ent->device == PCI_DEVICE_ID_ARTOP_AEC7610) {
- error = pci_read_config_byte(dev, PCI_CLASS_REVISION, &atp_dev.chip_veru);
- if (atp_dev.chip_veru < 2)
+ error = pci_read_config_byte(pdev, PCI_CLASS_REVISION, &atp_dev.chip_ver);
+ if (atp_dev.chip_ver < 2)
return -EIO;
}
switch (ent->device) {
- case 0x8081:
case PCI_DEVICE_ID_ARTOP_AEC7612UW:
case PCI_DEVICE_ID_ARTOP_AEC7612SUW:
- atp_dev.chip_veru = 0x04;
+ case ATP880_DEVID1:
+ case ATP880_DEVID2:
+ case ATP885_DEVID:
+ atp_dev.chip_ver = 0x04;
default:
break;
}
+ base_io = pci_resource_start(pdev, 0);
+ base_io &= 0xfffffff8;
+
+ if ((ent->device == ATP880_DEVID1)||(ent->device == ATP880_DEVID2)) {
+ error = pci_read_config_byte(pdev, PCI_CLASS_REVISION, &atp_dev.chip_ver);
+ pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x80);//JCC082803
- base_io = pci_resource_start(dev, 0);
-
- if (ent->device != 0x8081) {
- error = pci_read_config_byte(dev, 0x49, &host_id);
- base_io &= 0xfffffff8;
-
- printk(KERN_INFO " ACARD AEC-671X PCI Ultra/W SCSI-3 Host Adapter: %d "
- "IO:%x, IRQ:%d.\n", count, base_io, dev->irq);
-
- atp_dev.unit = count;
- atp_dev.ioport = base_io;
- atp_dev.pciport = base_io + 0x20;
- atp_dev.deviceid = ent->device;
- host_id &= 0x07;
- atp_dev.host_idu = host_id;
- tmport = base_io + 0x22;
- atp_dev.scam_on = inb(tmport);
- tmport += 0x0b;
- atp_dev.global_map = inb(tmport++);
- atp_dev.ultra_map = inw(tmport);
-
- if (atp_dev.ultra_map == 0) {
- atp_dev.scam_on = 0x00;
- atp_dev.global_map = 0x20;
- atp_dev.ultra_map = 0xffff;
- }
-
- shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit));
- if (!shpnt)
- return -ENOMEM;
-
- p = (struct atp_unit *)&shpnt->hostdata;
-
- atp_dev.host = shpnt;
- atp_dev.pdev = dev;
- pci_set_drvdata(dev, p);
- memcpy(p, &atp_dev, sizeof atp_dev);
- if (atp870u_init_tables(shpnt) < 0)
- goto unregister;
-
- if (request_irq(dev->irq, atp870u_intr_handle, SA_SHIRQ, "atp870u", shpnt)) {
- printk(KERN_ERR "Unable to allocate IRQ%d for Acard controller.\n", dev->irq);
- goto free_tables;
- }
-
- spin_lock_irqsave(shpnt->host_lock, flags);
- if (atp_dev.chip_veru > 0x07) { /* check if atp876 chip then enable terminator */
- tmport = base_io + 0x3e;
- outb(0x00, tmport);
- }
-
- tmport = base_io + 0x3a;
- k = (inb(tmport) & 0xf3) | 0x10;
- outb(k, tmport);
- outb((k & 0xdf), tmport);
- mdelay(32);
- outb(k, tmport);
- mdelay(32);
- tmport = base_io;
- outb((host_id | 0x08), tmport);
- tmport += 0x18;
- outb(0, tmport);
- tmport += 0x07;
- while ((inb(tmport) & 0x80) == 0)
- mdelay(1);
-
- tmport -= 0x08;
- inb(tmport);
- tmport = base_io + 1;
- outb(8, tmport++);
- outb(0x7f, tmport);
- tmport = base_io + 0x11;
- outb(0x20, tmport);
-
- tscam(shpnt);
- is870(shpnt, base_io);
- tmport = base_io + 0x3a;
- outb((inb(tmport) & 0xef), tmport);
- tmport++;
- outb((inb(tmport) | 0x20), tmport);
- } else {
- base_io &= 0xfffffff8;
host_id = inb(base_io + 0x39);
host_id >>= 0x04;
printk(KERN_INFO " ACARD AEC-67160 PCI Ultra3 LVD Host Adapter: %d"
- " IO:%x, IRQ:%d.\n", count, base_io, dev->irq);
- atp_dev.ioport = base_io + 0x40;
- atp_dev.pciport = base_io + 0x28;
- atp_dev.deviceid = ent->device;
- atp_dev.host_idu = host_id;
+ " IO:%x, IRQ:%d.\n", count, base_io, pdev->irq);
+ atp_dev.ioport[0] = base_io + 0x40;
+ atp_dev.pciport[0] = base_io + 0x28;
+ atp_dev.dev_id = ent->device;
+ atp_dev.host_id[0] = host_id;
tmport = base_io + 0x22;
atp_dev.scam_on = inb(tmport);
tmport += 0x13;
- atp_dev.global_map = inb(tmport);
+ atp_dev.global_map[0] = inb(tmport);
tmport += 0x07;
- atp_dev.ultra_map = inw(tmport);
+ atp_dev.ultra_map[0] = inw(tmport);
n = 0x3f09;
-next_fblk:
+next_fblk_880:
if (n >= 0x4000)
- goto flash_ok;
+ goto flash_ok_880;
m = 0;
outw(n, base_io + 0x34);
n += 0x0002;
if (inb(base_io + 0x30) == 0xff)
- goto flash_ok;
+ goto flash_ok_880;
- atp_dev.sp[m++] = inb(base_io + 0x30);
- atp_dev.sp[m++] = inb(base_io + 0x31);
- atp_dev.sp[m++] = inb(base_io + 0x32);
- atp_dev.sp[m++] = inb(base_io + 0x33);
+ atp_dev.sp[0][m++] = inb(base_io + 0x30);
+ atp_dev.sp[0][m++] = inb(base_io + 0x31);
+ atp_dev.sp[0][m++] = inb(base_io + 0x32);
+ atp_dev.sp[0][m++] = inb(base_io + 0x33);
outw(n, base_io + 0x34);
n += 0x0002;
- atp_dev.sp[m++] = inb(base_io + 0x30);
- atp_dev.sp[m++] = inb(base_io + 0x31);
- atp_dev.sp[m++] = inb(base_io + 0x32);
- atp_dev.sp[m++] = inb(base_io + 0x33);
+ atp_dev.sp[0][m++] = inb(base_io + 0x30);
+ atp_dev.sp[0][m++] = inb(base_io + 0x31);
+ atp_dev.sp[0][m++] = inb(base_io + 0x32);
+ atp_dev.sp[0][m++] = inb(base_io + 0x33);
outw(n, base_io + 0x34);
n += 0x0002;
- atp_dev.sp[m++] = inb(base_io + 0x30);
- atp_dev.sp[m++] = inb(base_io + 0x31);
- atp_dev.sp[m++] = inb(base_io + 0x32);
- atp_dev.sp[m++] = inb(base_io + 0x33);
+ atp_dev.sp[0][m++] = inb(base_io + 0x30);
+ atp_dev.sp[0][m++] = inb(base_io + 0x31);
+ atp_dev.sp[0][m++] = inb(base_io + 0x32);
+ atp_dev.sp[0][m++] = inb(base_io + 0x33);
outw(n, base_io + 0x34);
n += 0x0002;
- atp_dev.sp[m++] = inb(base_io + 0x30);
- atp_dev.sp[m++] = inb(base_io + 0x31);
- atp_dev.sp[m++] = inb(base_io + 0x32);
- atp_dev.sp[m++] = inb(base_io + 0x33);
+ atp_dev.sp[0][m++] = inb(base_io + 0x30);
+ atp_dev.sp[0][m++] = inb(base_io + 0x31);
+ atp_dev.sp[0][m++] = inb(base_io + 0x32);
+ atp_dev.sp[0][m++] = inb(base_io + 0x33);
n += 0x0018;
- goto next_fblk;
-flash_ok:
+ goto next_fblk_880;
+flash_ok_880:
outw(0, base_io + 0x34);
- atp_dev.ultra_map = 0;
- atp_dev.async = 0;
+ atp_dev.ultra_map[0] = 0;
+ atp_dev.async[0] = 0;
for (k = 0; k < 16; k++) {
n = 1;
n = n << k;
- if (atp_dev.sp[k] > 1) {
- atp_dev.ultra_map |= n;
+ if (atp_dev.sp[0][k] > 1) {
+ atp_dev.ultra_map[0] |= n;
} else {
- if (atp_dev.sp[k] == 0)
- atp_dev.async |= n;
+ if (atp_dev.sp[0][k] == 0)
+ atp_dev.async[0] |= n;
}
}
- atp_dev.async = ~(atp_dev.async);
- outb(atp_dev.global_map, base_io + 0x35);
+ atp_dev.async[0] = ~(atp_dev.async[0]);
+ outb(atp_dev.global_map[0], base_io + 0x35);
shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit));
if (!shpnt)
@@ -2471,16 +2741,16 @@ flash_ok:
p = (struct atp_unit *)&shpnt->hostdata;
atp_dev.host = shpnt;
- atp_dev.pdev = dev;
- pci_set_drvdata(dev, p);
+ atp_dev.pdev = pdev;
+ pci_set_drvdata(pdev, p);
memcpy(p, &atp_dev, sizeof atp_dev);
if (atp870u_init_tables(shpnt) < 0) {
printk(KERN_ERR "Unable to allocate tables for Acard controller\n");
goto unregister;
}
- if (request_irq(dev->irq, atp870u_intr_handle, SA_SHIRQ, "atp870u", shpnt)) {
- printk(KERN_ERR "Unable to allocate IRQ%d for Acard controller.\n", dev->irq);
+ if (request_irq(pdev->irq, atp870u_intr_handle, SA_SHIRQ, "atp880i", shpnt)) {
+ printk(KERN_ERR "Unable to allocate IRQ%d for Acard controller.\n", pdev->irq);
goto free_tables;
}
@@ -2513,50 +2783,314 @@ flash_ok:
outb(0x20, tmport);
tscam(shpnt);
- is880(shpnt, base_io);
+ is880(p, base_io);
tmport = base_io + 0x38;
outb(0xb0, tmport);
- }
-
- if (p->chip_veru == 4)
shpnt->max_id = 16;
-
- shpnt->this_id = host_id;
- shpnt->unique_id = base_io;
- shpnt->io_port = base_io;
- if (ent->device == 0x8081) {
+ shpnt->this_id = host_id;
+ shpnt->unique_id = base_io;
+ shpnt->io_port = base_io;
shpnt->n_io_port = 0x60; /* Number of bytes of I/O space used */
+ shpnt->irq = pdev->irq;
+ } else if (ent->device == ATP885_DEVID) {
+ printk(KERN_INFO " ACARD AEC-67162 PCI Ultra3 LVD Host Adapter: IO:%x, IRQ:%d.\n"
+ , base_io, pdev->irq);
+
+ atp_dev.pdev = pdev;
+ atp_dev.dev_id = ent->device;
+ atp_dev.baseport = base_io;
+ atp_dev.ioport[0] = base_io + 0x80;
+ atp_dev.ioport[1] = base_io + 0xc0;
+ atp_dev.pciport[0] = base_io + 0x40;
+ atp_dev.pciport[1] = base_io + 0x50;
+
+ shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit));
+ if (!shpnt)
+ return -ENOMEM;
+
+ p = (struct atp_unit *)&shpnt->hostdata;
+
+ atp_dev.host = shpnt;
+ atp_dev.pdev = pdev;
+ pci_set_drvdata(pdev, p);
+ memcpy(p, &atp_dev, sizeof(struct atp_unit));
+ if (atp870u_init_tables(shpnt) < 0)
+ goto unregister;
+
+#ifdef ED_DBGP
+ printk("request_irq() shpnt %p hostdata %p\n", shpnt, p);
+#endif
+ if (request_irq(pdev->irq, atp870u_intr_handle, SA_SHIRQ, "atp870u", shpnt)) {
+ printk(KERN_ERR "Unable to allocate IRQ for Acard controller.\n");
+ goto free_tables;
+ }
+
+ spin_lock_irqsave(shpnt->host_lock, flags);
+
+ c=inb(base_io + 0x29);
+ outb((c | 0x04),base_io + 0x29);
+
+ n=0x1f80;
+next_fblk_885:
+ if (n >= 0x2000) {
+ goto flash_ok_885;
+ }
+ outw(n,base_io + 0x3c);
+ if (inl(base_io + 0x38) == 0xffffffff) {
+ goto flash_ok_885;
+ }
+ for (m=0; m < 2; m++) {
+ p->global_map[m]= 0;
+ for (k=0; k < 4; k++) {
+ outw(n++,base_io + 0x3c);
+ ((unsigned long *)&setupdata[m][0])[k]=inl(base_io + 0x38);
+ }
+ for (k=0; k < 4; k++) {
+ outw(n++,base_io + 0x3c);
+ ((unsigned long *)&p->sp[m][0])[k]=inl(base_io + 0x38);
+ }
+ n += 8;
+ }
+ goto next_fblk_885;
+flash_ok_885:
+#ifdef ED_DBGP
+ printk( "Flash Read OK\n");
+#endif
+ c=inb(base_io + 0x29);
+ outb((c & 0xfb),base_io + 0x29);
+ for (c=0;c < 2;c++) {
+ p->ultra_map[c]=0;
+ p->async[c] = 0;
+ for (k=0; k < 16; k++) {
+ n=1;
+ n = n << k;
+ if (p->sp[c][k] > 1) {
+ p->ultra_map[c] |= n;
+ } else {
+ if (p->sp[c][k] == 0) {
+ p->async[c] |= n;
+ }
+ }
+ }
+ p->async[c] = ~(p->async[c]);
+
+ if (p->global_map[c] == 0) {
+ k=setupdata[c][1];
+ if ((k & 0x40) != 0)
+ p->global_map[c] |= 0x20;
+ k &= 0x07;
+ p->global_map[c] |= k;
+ if ((setupdata[c][2] & 0x04) != 0)
+ p->global_map[c] |= 0x08;
+ p->host_id[c] = setupdata[c][0] & 0x07;
+ }
+ }
+
+ k = inb(base_io + 0x28) & 0x8f;
+ k |= 0x10;
+ outb(k, base_io + 0x28);
+ outb(0x80, base_io + 0x41);
+ outb(0x80, base_io + 0x51);
+ mdelay(100);
+ outb(0, base_io + 0x41);
+ outb(0, base_io + 0x51);
+ mdelay(1000);
+ inb(base_io + 0x9b);
+ inb(base_io + 0x97);
+ inb(base_io + 0xdb);
+ inb(base_io + 0xd7);
+ tmport = base_io + 0x80;
+ k=p->host_id[0];
+ if (k > 7)
+ k = (k & 0x07) | 0x40;
+ k |= 0x08;
+ outb(k, tmport);
+ tmport += 0x18;
+ outb(0, tmport);
+ tmport += 0x07;
+
+ while ((inb(tmport) & 0x80) == 0)
+ cpu_relax();
+
+ tmport -= 0x08;
+ inb(tmport);
+ tmport = base_io + 0x81;
+ outb(8, tmport++);
+ outb(0x7f, tmport);
+ tmport = base_io + 0x91;
+ outb(0x20, tmport);
+
+ tmport = base_io + 0xc0;
+ k=p->host_id[1];
+ if (k > 7)
+ k = (k & 0x07) | 0x40;
+ k |= 0x08;
+ outb(k, tmport);
+ tmport += 0x18;
+ outb(0, tmport);
+ tmport += 0x07;
+
+ while ((inb(tmport) & 0x80) == 0)
+ cpu_relax();
+
+ tmport -= 0x08;
+ inb(tmport);
+ tmport = base_io + 0xc1;
+ outb(8, tmport++);
+ outb(0x7f, tmport);
+ tmport = base_io + 0xd1;
+ outb(0x20, tmport);
+
+ tscam_885();
+ printk(KERN_INFO " Scanning Channel A SCSI Device ...\n");
+ is885(p, base_io + 0x80, 0);
+ printk(KERN_INFO " Scanning Channel B SCSI Device ...\n");
+ is885(p, base_io + 0xc0, 1);
+
+ k = inb(base_io + 0x28) & 0xcf;
+ k |= 0xc0;
+ outb(k, base_io + 0x28);
+ k = inb(base_io + 0x1f) | 0x80;
+ outb(k, base_io + 0x1f);
+ k = inb(base_io + 0x29) | 0x01;
+ outb(k, base_io + 0x29);
+#ifdef ED_DBGP
+ //printk("atp885: atp_host[0] 0x%p\n", atp_host[0]);
+#endif
+ shpnt->max_id = 16;
+ shpnt->max_lun = (p->global_map[0] & 0x07) + 1;
+ shpnt->max_channel = 1;
+ shpnt->this_id = p->host_id[0];
+ shpnt->unique_id = base_io;
+ shpnt->io_port = base_io;
+ shpnt->n_io_port = 0xff; /* Number of bytes of I/O space used */
+ shpnt->irq = pdev->irq;
+
} else {
+ error = pci_read_config_byte(pdev, 0x49, &host_id);
+
+ printk(KERN_INFO " ACARD AEC-671X PCI Ultra/W SCSI-2/3 Host Adapter: %d "
+ "IO:%x, IRQ:%d.\n", count, base_io, pdev->irq);
+
+ atp_dev.ioport[0] = base_io;
+ atp_dev.pciport[0] = base_io + 0x20;
+ atp_dev.dev_id = ent->device;
+ host_id &= 0x07;
+ atp_dev.host_id[0] = host_id;
+ tmport = base_io + 0x22;
+ atp_dev.scam_on = inb(tmport);
+ tmport += 0x0b;
+ atp_dev.global_map[0] = inb(tmport++);
+ atp_dev.ultra_map[0] = inw(tmport);
+
+ if (atp_dev.ultra_map[0] == 0) {
+ atp_dev.scam_on = 0x00;
+ atp_dev.global_map[0] = 0x20;
+ atp_dev.ultra_map[0] = 0xffff;
+ }
+
+ shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit));
+ if (!shpnt)
+ return -ENOMEM;
+
+ p = (struct atp_unit *)&shpnt->hostdata;
+
+ atp_dev.host = shpnt;
+ atp_dev.pdev = pdev;
+ pci_set_drvdata(pdev, p);
+ memcpy(p, &atp_dev, sizeof atp_dev);
+ if (atp870u_init_tables(shpnt) < 0)
+ goto unregister;
+
+ if (request_irq(pdev->irq, atp870u_intr_handle, SA_SHIRQ, "atp870i", shpnt)) {
+ printk(KERN_ERR "Unable to allocate IRQ%d for Acard controller.\n", pdev->irq);
+ goto free_tables;
+ }
+
+ spin_lock_irqsave(shpnt->host_lock, flags);
+ if (atp_dev.chip_ver > 0x07) { /* check if atp876 chip then enable terminator */
+ tmport = base_io + 0x3e;
+ outb(0x00, tmport);
+ }
+
+ tmport = base_io + 0x3a;
+ k = (inb(tmport) & 0xf3) | 0x10;
+ outb(k, tmport);
+ outb((k & 0xdf), tmport);
+ mdelay(32);
+ outb(k, tmport);
+ mdelay(32);
+ tmport = base_io;
+ outb((host_id | 0x08), tmport);
+ tmport += 0x18;
+ outb(0, tmport);
+ tmport += 0x07;
+ while ((inb(tmport) & 0x80) == 0)
+ mdelay(1);
+
+ tmport -= 0x08;
+ inb(tmport);
+ tmport = base_io + 1;
+ outb(8, tmport++);
+ outb(0x7f, tmport);
+ tmport = base_io + 0x11;
+ outb(0x20, tmport);
+
+ tscam(shpnt);
+ is870(p, base_io);
+ tmport = base_io + 0x3a;
+ outb((inb(tmport) & 0xef), tmport);
+ tmport++;
+ outb((inb(tmport) | 0x20), tmport);
+ if (atp_dev.chip_ver == 4)
+ shpnt->max_id = 16;
+ else
+ shpnt->max_id = 7;
+ shpnt->this_id = host_id;
+ shpnt->unique_id = base_io;
+ shpnt->io_port = base_io;
shpnt->n_io_port = 0x40; /* Number of bytes of I/O space used */
- }
- shpnt->irq = dev->irq;
- spin_unlock_irqrestore(shpnt->host_lock, flags);
- if (ent->device == 0x8081) {
- if (!request_region(base_io, 0x60, "atp870u"))
- goto request_io_fail;
- } else {
- if (!request_region(base_io, 0x40, "atp870u"))
- goto request_io_fail;
- }
+ shpnt->irq = pdev->irq;
+ }
+ spin_unlock_irqrestore(shpnt->host_lock, flags);
+ if(ent->device==ATP885_DEVID) {
+ if(!request_region(base_io, 0xff, "atp870u")) /* Register the IO ports that we use */
+ goto request_io_fail;
+ } else if((ent->device==ATP880_DEVID1)||(ent->device==ATP880_DEVID2)) {
+ if(!request_region(base_io, 0x60, "atp870u")) /* Register the IO ports that we use */
+ goto request_io_fail;
+ } else {
+ if(!request_region(base_io, 0x40, "atp870u")) /* Register the IO ports that we use */
+ goto request_io_fail;
+ }
+ count++;
+ if (scsi_add_host(shpnt, &pdev->dev))
+ goto scsi_add_fail;
+ scsi_scan_host(shpnt);
+#ifdef ED_DBGP
+ printk("atp870u_prob : exit\n");
+#endif
+ return 0;
- count++;
- if (scsi_add_host(shpnt, &dev->dev))
- goto scsi_add_fail;
- scsi_scan_host(shpnt);
- return 0;
-
scsi_add_fail:
- if (ent->device == 0x8081)
+ printk("atp870u_prob:scsi_add_fail\n");
+ if(ent->device==ATP885_DEVID) {
+ release_region(base_io, 0xff);
+ } else if((ent->device==ATP880_DEVID1)||(ent->device==ATP880_DEVID2)) {
release_region(base_io, 0x60);
- else
+ } else {
release_region(base_io, 0x40);
+ }
request_io_fail:
- free_irq(dev->irq, shpnt);
+ printk("atp870u_prob:request_io_fail\n");
+ free_irq(pdev->irq, shpnt);
free_tables:
+ printk("atp870u_prob:free_table\n");
atp870u_free_tables(shpnt);
unregister:
+ printk("atp870u_prob:unregister\n");
scsi_host_put(shpnt);
- return -1;
+ return -1;
}
/* The abort command does not leave the device in a clean state where
@@ -2565,40 +3099,40 @@ unregister:
static int atp870u_abort(struct scsi_cmnd * SCpnt)
{
- unsigned char j, k;
+ unsigned char j, k, c;
struct scsi_cmnd *workrequ;
unsigned int tmport;
- struct atp_unit *dev = (struct atp_unit *)&SCpnt->device->host->hostdata;
+ struct atp_unit *dev;
+ struct Scsi_Host *host;
+ host = SCpnt->device->host;
- printk(KERN_DEBUG "working=%x last_cmd=%x ", dev->working, dev->last_cmd);
- printk(" quhdu=%x quendu=%x ", dev->quhdu, dev->quendu);
- tmport = dev->ioport;
- for (j = 0; j < 0x17; j++) {
+ dev = (struct atp_unit *)&host->hostdata;
+ c=SCpnt->device->channel;
+ printk(" atp870u: abort Channel = %x \n", c);
+ printk("working=%x last_cmd=%x ", dev->working[c], dev->last_cmd[c]);
+ printk(" quhdu=%x quendu=%x ", dev->quhd[c], dev->quend[c]);
+ tmport = dev->ioport[c];
+ for (j = 0; j < 0x18; j++) {
printk(" r%2x=%2x", j, inb(tmport++));
}
- tmport += 0x05;
+ tmport += 0x04;
printk(" r1c=%2x", inb(tmport));
tmport += 0x03;
- printk(" r1f=%2x in_snd=%2x ", inb(tmport), dev->in_snd);
- tmport = dev->pciport;
- printk(" r20=%2x", inb(tmport));
+ printk(" r1f=%2x in_snd=%2x ", inb(tmport), dev->in_snd[c]);
+ tmport= dev->pciport[c];
+ printk(" d00=%2x", inb(tmport));
tmport += 0x02;
- printk(" r22=%2x", inb(tmport));
- tmport = dev->ioport + 0x3a;
- printk(" r3a=%2x \n", inb(tmport));
- tmport = dev->ioport + 0x3b;
- printk(" r3b=%2x \n", inb(tmport));
- for (j = 0; j < 16; j++) {
- if (dev->id[j].curr_req != NULL) {
- workrequ = dev->id[j].curr_req;
- printk("\n que cdb= ");
- for (k = 0; k < workrequ->cmd_len; k++) {
- printk(" %2x ", workrequ->cmnd[k]);
- }
- printk(" last_lenu= %lx ", dev->id[j].last_lenu);
+ printk(" d02=%2x", inb(tmport));
+ for(j=0;j<16;j++) {
+ if (dev->id[c][j].curr_req != NULL) {
+ workrequ = dev->id[c][j].curr_req;
+ printk("\n que cdb= ");
+ for (k=0; k < workrequ->cmd_len; k++) {
+ printk(" %2x ",workrequ->cmnd[k]);
}
+ printk(" last_lenu= %x ",(unsigned int)dev->id[c][j].last_len);
+ }
}
- /* Sort of - the thing handles itself */
return SUCCESS;
}
@@ -2612,20 +3146,19 @@ static const char *atp870u_info(struct Scsi_Host *notused)
}
#define BLS buffer + len + size
-static int atp870u_proc_info(struct Scsi_Host *HBAptr, char *buffer,
- char **start, off_t offset, int length, int inout)
+int atp870u_proc_info(struct Scsi_Host *HBAptr, char *buffer,
+ char **start, off_t offset, int length, int inout)
{
static u8 buff[512];
int size = 0;
int len = 0;
off_t begin = 0;
off_t pos = 0;
-
- if (inout)
- return -ENOSYS;
- if (offset == 0) {
+
+ if (inout)
+ return -EINVAL;
+ if (offset == 0)
memset(buff, 0, sizeof(buff));
- }
size += sprintf(BLS, "ACARD AEC-671X Driver Version: 2.6+ac\n");
len += size;
pos = begin + len;
@@ -2637,7 +3170,7 @@ static int atp870u_proc_info(struct Scsi_Host *HBAptr, char *buffer,
size += sprintf(BLS, " IRQ: %d\n", HBAptr->irq);
len += size;
pos = begin + len;
-
+
*start = buffer + (offset - begin); /* Start of wanted data */
len -= (offset - begin); /* Start slop */
if (len > length) {
@@ -2646,15 +3179,15 @@ static int atp870u_proc_info(struct Scsi_Host *HBAptr, char *buffer,
return (len);
}
-static int atp870u_biosparam(struct scsi_device *sdev,
- struct block_device *dev, sector_t capacity, int *ip)
+
+static int atp870u_biosparam(struct scsi_device *disk, struct block_device *dev,
+ sector_t capacity, int *ip)
{
int heads, sectors, cylinders;
heads = 64;
sectors = 32;
cylinders = (unsigned long)capacity / (heads * sectors);
-
if (cylinders > 1024) {
heads = 255;
sectors = 63;
@@ -2667,39 +3200,46 @@ static int atp870u_biosparam(struct scsi_device *sdev,
return 0;
}
-static void atp870u_remove(struct pci_dev *pdev)
-{
- struct atp_unit *atp_dev = pci_get_drvdata(pdev);
- struct Scsi_Host *pshost = atp_dev->host;
-
+static void atp870u_remove (struct pci_dev *pdev)
+{
+ struct atp_unit *devext = pci_get_drvdata(pdev);
+ struct Scsi_Host *pshost = devext->host;
+
+
scsi_remove_host(pshost);
+ printk(KERN_INFO "free_irq : %d\n",pshost->irq);
free_irq(pshost->irq, pshost);
release_region(pshost->io_port, pshost->n_io_port);
+ printk(KERN_INFO "atp870u_free_tables : %p\n",pshost);
atp870u_free_tables(pshost);
+ printk(KERN_INFO "scsi_host_put : %p\n",pshost);
scsi_host_put(pshost);
- pci_set_drvdata(pdev, NULL);
+ printk(KERN_INFO "pci_set_drvdata : %p\n",pdev);
+ pci_set_drvdata(pdev, NULL);
}
-
MODULE_LICENSE("GPL");
static struct scsi_host_template atp870u_template = {
- .module = THIS_MODULE,
- .name = "atp870u",
- .proc_name = "atp870u",
- .proc_info = atp870u_proc_info,
- .info = atp870u_info,
- .queuecommand = atp870u_queuecommand,
- .eh_abort_handler = atp870u_abort,
- .bios_param = atp870u_biosparam,
- .can_queue = qcnt,
- .this_id = 7,
- .sg_tablesize = ATP870U_SCATTER,
- .cmd_per_lun = ATP870U_CMDLUN,
- .use_clustering = ENABLE_CLUSTERING,
+ .module = THIS_MODULE,
+ .name = "atp870u" /* name */,
+ .proc_name = "atp870u",
+ .proc_info = atp870u_proc_info,
+ .info = atp870u_info /* info */,
+ .queuecommand = atp870u_queuecommand /* queuecommand */,
+ .eh_abort_handler = atp870u_abort /* abort */,
+ .bios_param = atp870u_biosparam /* biosparm */,
+ .can_queue = qcnt /* can_queue */,
+ .this_id = 7 /* SCSI ID */,
+ .sg_tablesize = ATP870U_SCATTER /*SG_ALL*/ /*SG_NONE*/,
+ .cmd_per_lun = ATP870U_CMDLUN /* commands per lun */,
+ .use_clustering = ENABLE_CLUSTERING,
+ .max_sectors = ATP870U_MAX_SECTORS,
};
static struct pci_device_id atp870u_id_table[] = {
- { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, 0x8081) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, ATP885_DEVID) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, ATP880_DEVID1) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, ATP880_DEVID2) },
{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7610) },
{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612UW) },
{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612U) },
@@ -2712,7 +3252,7 @@ static struct pci_device_id atp870u_id_table[] = {
MODULE_DEVICE_TABLE(pci, atp870u_id_table);
-static struct pci_driver atp870u_driver = {
+static struct pci_driver atp870u_driver = {
.id_table = atp870u_id_table,
.name = "atp870u",
.probe = atp870u_probe,
@@ -2721,14 +3261,710 @@ static struct pci_driver atp870u_driver = {
static int __init atp870u_init(void)
{
- return pci_module_init(&atp870u_driver);
+#ifdef ED_DBGP
+ printk("atp870u_init: Entry\n");
+#endif
+ return pci_register_driver(&atp870u_driver);
}
static void __exit atp870u_exit(void)
{
+#ifdef ED_DBGP
+ printk("atp870u_exit: Entry\n");
+#endif
pci_unregister_driver(&atp870u_driver);
}
+static void tscam_885(void)
+{
+ unsigned char i;
+
+ for (i = 0; i < 0x2; i++) {
+ mdelay(300);
+ }
+ return;
+}
+
+
+
+static void is885(struct atp_unit *dev, unsigned int wkport,unsigned char c)
+{
+ unsigned int tmport;
+ unsigned char i, j, k, rmb, n, lvdmode;
+ unsigned short int m;
+ static unsigned char mbuf[512];
+ static unsigned char satn[9] = {0, 0, 0, 0, 0, 0, 0, 6, 6};
+ static unsigned char inqd[9] = {0x12, 0, 0, 0, 0x24, 0, 0, 0x24, 6};
+ static unsigned char synn[6] = {0x80, 1, 3, 1, 0x19, 0x0e};
+ unsigned char synu[6] = {0x80, 1, 3, 1, 0x0a, 0x0e};
+ static unsigned char synw[6] = {0x80, 1, 3, 1, 0x19, 0x0e};
+ unsigned char synuw[6] = {0x80, 1, 3, 1, 0x0a, 0x0e};
+ static unsigned char wide[6] = {0x80, 1, 2, 3, 1, 0};
+ static unsigned char u3[9] = { 0x80,1,6,4,0x09,00,0x0e,0x01,0x02 };
+
+ lvdmode=inb(wkport + 0x1b) >> 7;
+
+ for (i = 0; i < 16; i++) {
+ m = 1;
+ m = m << i;
+ if ((m & dev->active_id[c]) != 0) {
+ continue;
+ }
+ if (i == dev->host_id[c]) {
+ printk(KERN_INFO " ID: %2d Host Adapter\n", dev->host_id[c]);
+ continue;
+ }
+ tmport = wkport + 0x1b;
+ outb(0x01, tmport);
+ tmport = wkport + 0x01;
+ outb(0x08, tmport++);
+ outb(0x7f, tmport++);
+ outb(satn[0], tmport++);
+ outb(satn[1], tmport++);
+ outb(satn[2], tmport++);
+ outb(satn[3], tmport++);
+ outb(satn[4], tmport++);
+ outb(satn[5], tmport++);
+ tmport += 0x06;
+ outb(0, tmport);
+ tmport += 0x02;
+ outb(dev->id[c][i].devsp, tmport++);
+
+ outb(0, tmport++);
+ outb(satn[6], tmport++);
+ outb(satn[7], tmport++);
+ j = i;
+ if ((j & 0x08) != 0) {
+ j = (j & 0x07) | 0x40;
+ }
+ outb(j, tmport);
+ tmport += 0x03;
+ outb(satn[8], tmport);
+ tmport += 0x07;
+
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
+ tmport -= 0x08;
+ if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
+ continue;
+ }
+ while (inb(tmport) != 0x8e)
+ cpu_relax();
+ dev->active_id[c] |= m;
+
+ tmport = wkport + 0x10;
+ outb(0x30, tmport);
+ tmport = wkport + 0x14;
+ outb(0x00, tmport);
+
+phase_cmd:
+ tmport = wkport + 0x18;
+ outb(0x08, tmport);
+ tmport += 0x07;
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
+ tmport -= 0x08;
+ j = inb(tmport);
+ if (j != 0x16) {
+ tmport = wkport + 0x10;
+ outb(0x41, tmport);
+ goto phase_cmd;
+ }
+sel_ok:
+ tmport = wkport + 0x03;
+ outb(inqd[0], tmport++);
+ outb(inqd[1], tmport++);
+ outb(inqd[2], tmport++);
+ outb(inqd[3], tmport++);
+ outb(inqd[4], tmport++);
+ outb(inqd[5], tmport);
+ tmport += 0x07;
+ outb(0, tmport);
+ tmport += 0x02;
+ outb(dev->id[c][i].devsp, tmport++);
+ outb(0, tmport++);
+ outb(inqd[6], tmport++);
+ outb(inqd[7], tmport++);
+ tmport += 0x03;
+ outb(inqd[8], tmport);
+ tmport += 0x07;
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
+ tmport -= 0x08;
+ if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
+ continue;
+ }
+ while (inb(tmport) != 0x8e)
+ cpu_relax();
+ tmport = wkport + 0x1b;
+ outb(0x00, tmport);
+ tmport = wkport + 0x18;
+ outb(0x08, tmport);
+ tmport += 0x07;
+ j = 0;
+rd_inq_data:
+ k = inb(tmport);
+ if ((k & 0x01) != 0) {
+ tmport -= 0x06;
+ mbuf[j++] = inb(tmport);
+ tmport += 0x06;
+ goto rd_inq_data;
+ }
+ if ((k & 0x80) == 0) {
+ goto rd_inq_data;
+ }
+ tmport -= 0x08;
+ j = inb(tmport);
+ if (j == 0x16) {
+ goto inq_ok;
+ }
+ tmport = wkport + 0x10;
+ outb(0x46, tmport);
+ tmport += 0x02;
+ outb(0, tmport++);
+ outb(0, tmport++);
+ outb(0, tmport++);
+ tmport += 0x03;
+ outb(0x08, tmport);
+ tmport += 0x07;
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
+ tmport -= 0x08;
+ if (inb(tmport) != 0x16) {
+ goto sel_ok;
+ }
+inq_ok:
+ mbuf[36] = 0;
+ printk( KERN_INFO" ID: %2d %s\n", i, &mbuf[8]);
+ dev->id[c][i].devtype = mbuf[0];
+ rmb = mbuf[1];
+ n = mbuf[7];
+ if ((mbuf[7] & 0x60) == 0) {
+ goto not_wide;
+ }
+ if ((i < 8) && ((dev->global_map[c] & 0x20) == 0)) {
+ goto not_wide;
+ }
+ if (lvdmode == 0) {
+ goto chg_wide;
+ }
+ if (dev->sp[c][i] != 0x04) { // force u2
+ goto chg_wide;
+ }
+
+ tmport = wkport + 0x1b;
+ outb(0x01, tmport);
+ tmport = wkport + 0x03;
+ outb(satn[0], tmport++);
+ outb(satn[1], tmport++);
+ outb(satn[2], tmport++);
+ outb(satn[3], tmport++);
+ outb(satn[4], tmport++);
+ outb(satn[5], tmport++);
+ tmport += 0x06;
+ outb(0, tmport);
+ tmport += 0x02;
+ outb(dev->id[c][i].devsp, tmport++);
+ outb(0, tmport++);
+ outb(satn[6], tmport++);
+ outb(satn[7], tmport++);
+ tmport += 0x03;
+ outb(satn[8], tmport);
+ tmport += 0x07;
+
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
+ tmport -= 0x08;
+ if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
+ continue;
+ }
+ while (inb(tmport) != 0x8e)
+ cpu_relax();
+try_u3:
+ j = 0;
+ tmport = wkport + 0x14;
+ outb(0x09, tmport);
+ tmport += 0x04;
+ outb(0x20, tmport);
+ tmport += 0x07;
+
+ while ((inb(tmport) & 0x80) == 0) {
+ if ((inb(tmport) & 0x01) != 0) {
+ tmport -= 0x06;
+ outb(u3[j++], tmport);
+ tmport += 0x06;
+ }
+ cpu_relax();
+ }
+ tmport -= 0x08;
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
+ j = inb(tmport) & 0x0f;
+ if (j == 0x0f) {
+ goto u3p_in;
+ }
+ if (j == 0x0a) {
+ goto u3p_cmd;
+ }
+ if (j == 0x0e) {
+ goto try_u3;
+ }
+ continue;
+u3p_out:
+ tmport = wkport + 0x18;
+ outb(0x20, tmport);
+ tmport += 0x07;
+ while ((inb(tmport) & 0x80) == 0) {
+ if ((inb(tmport) & 0x01) != 0) {
+ tmport -= 0x06;
+ outb(0, tmport);
+ tmport += 0x06;
+ }
+ cpu_relax();
+ }
+ tmport -= 0x08;
+ j = inb(tmport) & 0x0f;
+ if (j == 0x0f) {
+ goto u3p_in;
+ }
+ if (j == 0x0a) {
+ goto u3p_cmd;
+ }
+ if (j == 0x0e) {
+ goto u3p_out;
+ }
+ continue;
+u3p_in:
+ tmport = wkport + 0x14;
+ outb(0x09, tmport);
+ tmport += 0x04;
+ outb(0x20, tmport);
+ tmport += 0x07;
+ k = 0;
+u3p_in1:
+ j = inb(tmport);
+ if ((j & 0x01) != 0) {
+ tmport -= 0x06;
+ mbuf[k++] = inb(tmport);
+ tmport += 0x06;
+ goto u3p_in1;
+ }
+ if ((j & 0x80) == 0x00) {
+ goto u3p_in1;
+ }
+ tmport -= 0x08;
+ j = inb(tmport) & 0x0f;
+ if (j == 0x0f) {
+ goto u3p_in;
+ }
+ if (j == 0x0a) {
+ goto u3p_cmd;
+ }
+ if (j == 0x0e) {
+ goto u3p_out;
+ }
+ continue;
+u3p_cmd:
+ tmport = wkport + 0x10;
+ outb(0x30, tmport);
+ tmport = wkport + 0x14;
+ outb(0x00, tmport);
+ tmport += 0x04;
+ outb(0x08, tmport);
+ tmport += 0x07;
+ while ((inb(tmport) & 0x80) == 0x00);
+ tmport -= 0x08;
+ j = inb(tmport);
+ if (j != 0x16) {
+ if (j == 0x4e) {
+ goto u3p_out;
+ }
+ continue;
+ }
+ if (mbuf[0] != 0x01) {
+ goto chg_wide;
+ }
+ if (mbuf[1] != 0x06) {
+ goto chg_wide;
+ }
+ if (mbuf[2] != 0x04) {
+ goto chg_wide;
+ }
+ if (mbuf[3] == 0x09) {
+ m = 1;
+ m = m << i;
+ dev->wide_id[c] |= m;
+ dev->id[c][i].devsp = 0xce;
+#ifdef ED_DBGP
+ printk("dev->id[%2d][%2d].devsp = %2x\n",c,i,dev->id[c][i].devsp);
+#endif
+ continue;
+ }
+chg_wide:
+ tmport = wkport + 0x1b;
+ outb(0x01, tmport);
+ tmport = wkport + 0x03;
+ outb(satn[0], tmport++);
+ outb(satn[1], tmport++);
+ outb(satn[2], tmport++);
+ outb(satn[3], tmport++);
+ outb(satn[4], tmport++);
+ outb(satn[5], tmport++);
+ tmport += 0x06;
+ outb(0, tmport);
+ tmport += 0x02;
+ outb(dev->id[c][i].devsp, tmport++);
+ outb(0, tmport++);
+ outb(satn[6], tmport++);
+ outb(satn[7], tmport++);
+ tmport += 0x03;
+ outb(satn[8], tmport);
+ tmport += 0x07;
+
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
+ tmport -= 0x08;
+ if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
+ continue;
+ }
+ while (inb(tmport) != 0x8e)
+ cpu_relax();
+try_wide:
+ j = 0;
+ tmport = wkport + 0x14;
+ outb(0x05, tmport);
+ tmport += 0x04;
+ outb(0x20, tmport);
+ tmport += 0x07;
+
+ while ((inb(tmport) & 0x80) == 0) {
+ if ((inb(tmport) & 0x01) != 0) {
+ tmport -= 0x06;
+ outb(wide[j++], tmport);
+ tmport += 0x06;
+ }
+ cpu_relax();
+ }
+ tmport -= 0x08;
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
+ j = inb(tmport) & 0x0f;
+ if (j == 0x0f) {
+ goto widep_in;
+ }
+ if (j == 0x0a) {
+ goto widep_cmd;
+ }
+ if (j == 0x0e) {
+ goto try_wide;
+ }
+ continue;
+widep_out:
+ tmport = wkport + 0x18;
+ outb(0x20, tmport);
+ tmport += 0x07;
+ while ((inb(tmport) & 0x80) == 0) {
+ if ((inb(tmport) & 0x01) != 0) {
+ tmport -= 0x06;
+ outb(0, tmport);
+ tmport += 0x06;
+ }
+ cpu_relax();
+ }
+ tmport -= 0x08;
+ j = inb(tmport) & 0x0f;
+ if (j == 0x0f) {
+ goto widep_in;
+ }
+ if (j == 0x0a) {
+ goto widep_cmd;
+ }
+ if (j == 0x0e) {
+ goto widep_out;
+ }
+ continue;
+widep_in:
+ tmport = wkport + 0x14;
+ outb(0xff, tmport);
+ tmport += 0x04;
+ outb(0x20, tmport);
+ tmport += 0x07;
+ k = 0;
+widep_in1:
+ j = inb(tmport);
+ if ((j & 0x01) != 0) {
+ tmport -= 0x06;
+ mbuf[k++] = inb(tmport);
+ tmport += 0x06;
+ goto widep_in1;
+ }
+ if ((j & 0x80) == 0x00) {
+ goto widep_in1;
+ }
+ tmport -= 0x08;
+ j = inb(tmport) & 0x0f;
+ if (j == 0x0f) {
+ goto widep_in;
+ }
+ if (j == 0x0a) {
+ goto widep_cmd;
+ }
+ if (j == 0x0e) {
+ goto widep_out;
+ }
+ continue;
+widep_cmd:
+ tmport = wkport + 0x10;
+ outb(0x30, tmport);
+ tmport = wkport + 0x14;
+ outb(0x00, tmport);
+ tmport += 0x04;
+ outb(0x08, tmport);
+ tmport += 0x07;
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
+ tmport -= 0x08;
+ j = inb(tmport);
+ if (j != 0x16) {
+ if (j == 0x4e) {
+ goto widep_out;
+ }
+ continue;
+ }
+ if (mbuf[0] != 0x01) {
+ goto not_wide;
+ }
+ if (mbuf[1] != 0x02) {
+ goto not_wide;
+ }
+ if (mbuf[2] != 0x03) {
+ goto not_wide;
+ }
+ if (mbuf[3] != 0x01) {
+ goto not_wide;
+ }
+ m = 1;
+ m = m << i;
+ dev->wide_id[c] |= m;
+not_wide:
+ if ((dev->id[c][i].devtype == 0x00) || (dev->id[c][i].devtype == 0x07) ||
+ ((dev->id[c][i].devtype == 0x05) && ((n & 0x10) != 0))) {
+ m = 1;
+ m = m << i;
+ if ((dev->async[c] & m) != 0) {
+ goto set_sync;
+ }
+ }
+ continue;
+set_sync:
+ if (dev->sp[c][i] == 0x02) {
+ synu[4]=0x0c;
+ synuw[4]=0x0c;
+ } else {
+ if (dev->sp[c][i] >= 0x03) {
+ synu[4]=0x0a;
+ synuw[4]=0x0a;
+ }
+ }
+ tmport = wkport + 0x1b;
+ j = 0;
+ if ((m & dev->wide_id[c]) != 0) {
+ j |= 0x01;
+ }
+ outb(j, tmport);
+ tmport = wkport + 0x03;
+ outb(satn[0], tmport++);
+ outb(satn[1], tmport++);
+ outb(satn[2], tmport++);
+ outb(satn[3], tmport++);
+ outb(satn[4], tmport++);
+ outb(satn[5], tmport++);
+ tmport += 0x06;
+ outb(0, tmport);
+ tmport += 0x02;
+ outb(dev->id[c][i].devsp, tmport++);
+ outb(0, tmport++);
+ outb(satn[6], tmport++);
+ outb(satn[7], tmport++);
+ tmport += 0x03;
+ outb(satn[8], tmport);
+ tmport += 0x07;
+
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
+ tmport -= 0x08;
+ if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
+ continue;
+ }
+ while (inb(tmport) != 0x8e)
+ cpu_relax();
+try_sync:
+ j = 0;
+ tmport = wkport + 0x14;
+ outb(0x06, tmport);
+ tmport += 0x04;
+ outb(0x20, tmport);
+ tmport += 0x07;
+
+ while ((inb(tmport) & 0x80) == 0) {
+ if ((inb(tmport) & 0x01) != 0) {
+ tmport -= 0x06;
+ if ((m & dev->wide_id[c]) != 0) {
+ if ((m & dev->ultra_map[c]) != 0) {
+ outb(synuw[j++], tmport);
+ } else {
+ outb(synw[j++], tmport);
+ }
+ } else {
+ if ((m & dev->ultra_map[c]) != 0) {
+ outb(synu[j++], tmport);
+ } else {
+ outb(synn[j++], tmport);
+ }
+ }
+ tmport += 0x06;
+ }
+ }
+ tmport -= 0x08;
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
+ j = inb(tmport) & 0x0f;
+ if (j == 0x0f) {
+ goto phase_ins;
+ }
+ if (j == 0x0a) {
+ goto phase_cmds;
+ }
+ if (j == 0x0e) {
+ goto try_sync;
+ }
+ continue;
+phase_outs:
+ tmport = wkport + 0x18;
+ outb(0x20, tmport);
+ tmport += 0x07;
+ while ((inb(tmport) & 0x80) == 0x00) {
+ if ((inb(tmport) & 0x01) != 0x00) {
+ tmport -= 0x06;
+ outb(0x00, tmport);
+ tmport += 0x06;
+ }
+ cpu_relax();
+ }
+ tmport -= 0x08;
+ j = inb(tmport);
+ if (j == 0x85) {
+ goto tar_dcons;
+ }
+ j &= 0x0f;
+ if (j == 0x0f) {
+ goto phase_ins;
+ }
+ if (j == 0x0a) {
+ goto phase_cmds;
+ }
+ if (j == 0x0e) {
+ goto phase_outs;
+ }
+ continue;
+phase_ins:
+ tmport = wkport + 0x14;
+ outb(0x06, tmport);
+ tmport += 0x04;
+ outb(0x20, tmport);
+ tmport += 0x07;
+ k = 0;
+phase_ins1:
+ j = inb(tmport);
+ if ((j & 0x01) != 0x00) {
+ tmport -= 0x06;
+ mbuf[k++] = inb(tmport);
+ tmport += 0x06;
+ goto phase_ins1;
+ }
+ if ((j & 0x80) == 0x00) {
+ goto phase_ins1;
+ }
+ tmport -= 0x08;
+ while ((inb(tmport) & 0x80) == 0x00);
+ j = inb(tmport);
+ if (j == 0x85) {
+ goto tar_dcons;
+ }
+ j &= 0x0f;
+ if (j == 0x0f) {
+ goto phase_ins;
+ }
+ if (j == 0x0a) {
+ goto phase_cmds;
+ }
+ if (j == 0x0e) {
+ goto phase_outs;
+ }
+ continue;
+phase_cmds:
+ tmport = wkport + 0x10;
+ outb(0x30, tmport);
+tar_dcons:
+ tmport = wkport + 0x14;
+ outb(0x00, tmport);
+ tmport += 0x04;
+ outb(0x08, tmport);
+ tmport += 0x07;
+ while ((inb(tmport) & 0x80) == 0x00)
+ cpu_relax();
+ tmport -= 0x08;
+ j = inb(tmport);
+ if (j != 0x16) {
+ continue;
+ }
+ if (mbuf[0] != 0x01) {
+ continue;
+ }
+ if (mbuf[1] != 0x03) {
+ continue;
+ }
+ if (mbuf[4] == 0x00) {
+ continue;
+ }
+ if (mbuf[3] > 0x64) {
+ continue;
+ }
+ if (mbuf[4] > 0x0e) {
+ mbuf[4] = 0x0e;
+ }
+ dev->id[c][i].devsp = mbuf[4];
+ if (mbuf[3] < 0x0c){
+ j = 0xb0;
+ goto set_syn_ok;
+ }
+ if ((mbuf[3] < 0x0d) && (rmb == 0)) {
+ j = 0xa0;
+ goto set_syn_ok;
+ }
+ if (mbuf[3] < 0x1a) {
+ j = 0x20;
+ goto set_syn_ok;
+ }
+ if (mbuf[3] < 0x33) {
+ j = 0x40;
+ goto set_syn_ok;
+ }
+ if (mbuf[3] < 0x4c) {
+ j = 0x50;
+ goto set_syn_ok;
+ }
+ j = 0x60;
+ set_syn_ok:
+ dev->id[c][i].devsp = (dev->id[c][i].devsp & 0x0f) | j;
+#ifdef ED_DBGP
+ printk("dev->id[%2d][%2d].devsp = %2x\n",c,i,dev->id[c][i].devsp);
+#endif
+ }
+ tmport = wkport + 0x16;
+ outb(0x80, tmport);
+}
+
module_init(atp870u_init);
module_exit(atp870u_exit);
diff --git a/drivers/scsi/atp870u.h b/drivers/scsi/atp870u.h
index ce42a819dc612..89f43af39cf2e 100644
--- a/drivers/scsi/atp870u.h
+++ b/drivers/scsi/atp870u.h
@@ -2,50 +2,64 @@
#define _ATP870U_H
#include <linux/types.h>
+#include <linux/kdev_t.h>
/* I/O Port */
-#define MAX_CDB 12
-#define MAX_SENSE 14
-#define qcnt 32
-#define ATP870U_SCATTER 128
-#define ATP870U_CMDLUN 1
-
-struct atp_unit {
- unsigned long ioport;
- unsigned long pciport;
- unsigned char last_cmd;
- unsigned char in_snd;
- unsigned char in_int;
- unsigned char quhdu;
- unsigned char quendu;
+#define MAX_CDB 12
+#define MAX_SENSE 14
+#define qcnt 32
+#define ATP870U_SCATTER 128
+#define ATP870U_CMDLUN 1
+
+#define MAX_ADAPTER 8
+#define MAX_SCSI_ID 16
+#define ATP870U_MAX_SECTORS 128
+
+#define ATP885_DEVID 0x808A
+#define ATP880_DEVID1 0x8080
+#define ATP880_DEVID2 0x8081
+
+//#define ED_DBGP
+
+struct atp_unit
+{
+ unsigned long baseport;
+ unsigned long ioport[2];
+ unsigned long pciport[2];
+ unsigned long irq;
+ unsigned char last_cmd[2];
+ unsigned char in_snd[2];
+ unsigned char in_int[2];
+ unsigned char quhd[2];
+ unsigned char quend[2];
+ unsigned char global_map[2];
+ unsigned char chip_ver;
unsigned char scam_on;
- unsigned char global_map;
- unsigned char chip_veru;
- unsigned char host_idu;
- volatile int working;
- unsigned short wide_idu;
- unsigned short active_idu;
- unsigned short ultra_map;
- unsigned short async;
- unsigned short deviceid;
- unsigned char ata_cdbu[16];
- unsigned char sp[16];
- struct scsi_cmnd *querequ[qcnt];
- struct atp_id {
- unsigned char dirctu;
- unsigned char devspu;
- unsigned char devtypeu;
- unsigned long prdaddru;
- unsigned long tran_lenu;
- unsigned long last_lenu;
- unsigned char *prd_posu;
- unsigned char *prd_tableu;
- dma_addr_t prd_phys;
+ unsigned char host_id[2];
+ unsigned int working[2];
+ unsigned short wide_id[2];
+ unsigned short active_id[2];
+ unsigned short ultra_map[2];
+ unsigned short async[2];
+ unsigned short dev_id;
+ unsigned char sp[2][16];
+ unsigned char r1f[2][16];
+ struct scsi_cmnd *quereq[2][qcnt];
+ struct atp_id
+ {
+ unsigned char dirct;
+ unsigned char devsp;
+ unsigned char devtype;
+ unsigned long tran_len;
+ unsigned long last_len;
+ unsigned char *prd_pos;
+ unsigned char *prd_table;
+ dma_addr_t prdaddr;
struct scsi_cmnd *curr_req;
- } id[16];
- struct Scsi_Host *host;
- struct pci_dev *pdev;
+ } id[2][16];
+ struct Scsi_Host *host;
+ struct pci_dev *pdev;
unsigned int unit;
};
diff --git a/drivers/scsi/cpqfcTSinit.c b/drivers/scsi/cpqfcTSinit.c
index 80af7b5a5a360..2eeb493f5a2bf 100644
--- a/drivers/scsi/cpqfcTSinit.c
+++ b/drivers/scsi/cpqfcTSinit.c
@@ -752,7 +752,7 @@ int cpqfcTS_ioctl( struct scsi_device *ScsiDev, int Cmnd, void *arg)
result = -ENXIO;
break;
}
- result = verify_area(VERIFY_WRITE, arg, sizeof(Scsi_FCTargAddress));
+ result = access_ok(VERIFY_WRITE, arg, sizeof(Scsi_FCTargAddress)) ? 0 : -EFAULT;
if (result) break;
put_user(pLoggedInPort->port_id,
diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c
index 5f27f835d305a..cca41cf8d3e7c 100644
--- a/drivers/scsi/dc395x.c
+++ b/drivers/scsi/dc395x.c
@@ -56,6 +56,7 @@
#include <linux/spinlock.h>
#include <linux/pci.h>
#include <linux/list.h>
+#include <linux/vmalloc.h>
#include <asm/io.h>
#include <scsi/scsi.h>
@@ -182,7 +183,7 @@
* cross a page boundy.
*/
#define SEGMENTX_LEN (sizeof(struct SGentry)*DC395x_MAX_SG_LISTENTRY)
-
+#define VIRTX_LEN (sizeof(void *) * DC395x_MAX_SG_LISTENTRY)
struct SGentry {
u32 address; /* bus! address */
@@ -234,6 +235,7 @@ struct ScsiReqBlk {
u8 sg_count; /* No of HW sg entries for this request */
u8 sg_index; /* Index of HW sg entry for this request */
u32 total_xfer_length; /* Total number of bytes remaining to be transfered */
+ void **virt_map;
unsigned char *virt_addr; /* Virtual address of current transfer position */
/*
@@ -488,7 +490,7 @@ struct ParameterData {
int def; /* default value */
int safe; /* safe value */
};
-static struct ParameterData __initdata cfg_data[] = {
+static struct ParameterData __devinitdata cfg_data[] = {
{ /* adapter id */
CFG_PARAM_UNSET,
0,
@@ -573,7 +575,7 @@ MODULE_PARM_DESC(reset_delay, "Reset delay in seconds. Default 1 (0-180)");
* set_safe_settings - if the use_safe_settings option is set then
* set all values to the safe and slow values.
**/
-static void __init set_safe_settings(void)
+static void __devinit set_safe_settings(void)
{
if (use_safe_settings)
{
@@ -592,7 +594,7 @@ static void __init set_safe_settings(void)
* fix_settings - reset any boot parameters which are out of range
* back to the default values.
**/
-static void __init fix_settings(void)
+static void __devinit fix_settings(void)
{
int i;
@@ -619,7 +621,7 @@ static void __init fix_settings(void)
* Mapping from the eeprom delay index value (index into this array)
* to the the number of actual seconds that the delay should be for.
*/
-static char __initdata eeprom_index_to_delay_map[] =
+static char __devinitdata eeprom_index_to_delay_map[] =
{ 1, 3, 5, 10, 16, 30, 60, 120 };
@@ -629,7 +631,7 @@ static char __initdata eeprom_index_to_delay_map[] =
*
* @eeprom: The eeprom structure in which we find the delay index to map.
**/
-static void __init eeprom_index_to_delay(struct NvRamType *eeprom)
+static void __devinit eeprom_index_to_delay(struct NvRamType *eeprom)
{
eeprom->delay_time = eeprom_index_to_delay_map[eeprom->delay_time];
}
@@ -642,7 +644,7 @@ static void __init eeprom_index_to_delay(struct NvRamType *eeprom)
*
* @delay: The delay, in seconds, to find the eeprom index for.
**/
-static int __init delay_to_eeprom_index(int delay)
+static int __devinit delay_to_eeprom_index(int delay)
{
u8 idx = 0;
while (idx < 7 && eeprom_index_to_delay_map[idx] < delay)
@@ -658,7 +660,7 @@ static int __init delay_to_eeprom_index(int delay)
*
* @eeprom: The eeprom data to override with command line options.
**/
-static void __init eeprom_override(struct NvRamType *eeprom)
+static void __devinit eeprom_override(struct NvRamType *eeprom)
{
u8 id;
@@ -1020,14 +1022,14 @@ static void build_srb(struct scsi_cmnd *cmd, struct DeviceCtlBlk *dcb,
reqlen, cmd->request_buffer, cmd->use_sg,
srb->sg_count);
- srb->virt_addr = page_address(sl->page);
for (i = 0; i < srb->sg_count; i++) {
- u32 busaddr = (u32)sg_dma_address(&sl[i]);
- u32 seglen = (u32)sl[i].length;
- sgp[i].address = busaddr;
+ u32 seglen = (u32)sg_dma_len(sl + i);
+ sgp[i].address = (u32)sg_dma_address(sl + i);
sgp[i].length = seglen;
srb->total_xfer_length += seglen;
+ srb->virt_map[i] = kmap(sl[i].page);
}
+ srb->virt_addr = srb->virt_map[0];
sgp += srb->sg_count - 1;
/*
@@ -1964,6 +1966,7 @@ static void sg_update_list(struct ScsiReqBlk *srb, u32 left)
int segment = cmd->use_sg;
u32 xferred = srb->total_xfer_length - left; /* bytes transfered */
struct SGentry *psge = srb->segment_x + srb->sg_index;
+ void **virt = srb->virt_map;
dprintkdbg(DBG_0,
"sg_update_list: Transfered %i of %i bytes, %i remain\n",
@@ -2003,16 +2006,16 @@ static void sg_update_list(struct ScsiReqBlk *srb, u32 left)
/* We have to walk the scatterlist to find it */
sg = (struct scatterlist *)cmd->request_buffer;
+ idx = 0;
while (segment--) {
unsigned long mask =
~((unsigned long)sg->length - 1) & PAGE_MASK;
if ((sg_dma_address(sg) & mask) == (psge->address & mask)) {
- srb->virt_addr = (page_address(sg->page)
- + psge->address -
- (psge->address & PAGE_MASK));
+ srb->virt_addr = virt[idx] + (psge->address & ~PAGE_MASK);
return;
}
++sg;
+ ++idx;
}
dprintkl(KERN_ERR, "sg_update_list: sg_to_virt failed\n");
@@ -2138,7 +2141,7 @@ static void data_out_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
DC395x_read32(acb, TRM_S1040_DMA_CXCNT));
}
/*
- * calculate all the residue data that not yet tranfered
+ * calculate all the residue data that not yet transfered
* SCSI transfer counter + left in SCSI FIFO data
*
* .....TRM_S1040_SCSI_COUNTER (24bits)
@@ -3256,6 +3259,7 @@ static void pci_unmap_srb(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb)
struct scsi_cmnd *cmd = srb->cmd;
enum dma_data_direction dir = cmd->sc_data_direction;
if (cmd->use_sg && dir != PCI_DMA_NONE) {
+ int i;
/* unmap DC395x SG list */
dprintkdbg(DBG_SG, "pci_unmap_srb: list=%08x(%05x)\n",
srb->sg_bus_addr, SEGMENTX_LEN);
@@ -3265,6 +3269,8 @@ static void pci_unmap_srb(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb)
dprintkdbg(DBG_SG, "pci_unmap_srb: segs=%i buffer=%p\n",
cmd->use_sg, cmd->request_buffer);
/* unmap the sg segments */
+ for (i = 0; i < srb->sg_count; i++)
+ kunmap(virt_to_page(srb->virt_map[i]));
pci_unmap_sg(acb->dev,
(struct scatterlist *)cmd->request_buffer,
cmd->use_sg, dir);
@@ -3311,7 +3317,7 @@ static void srb_done(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb,
if (cmd->use_sg) {
struct scatterlist* sg = (struct scatterlist *)cmd->request_buffer;
- ptr = (struct ScsiInqData *)(page_address(sg->page) + sg->offset);
+ ptr = (struct ScsiInqData *)(srb->virt_map[0] + sg->offset);
} else {
ptr = (struct ScsiInqData *)(cmd->request_buffer);
}
@@ -3931,7 +3937,7 @@ static void dc395x_slave_destroy(struct scsi_device *scsi_device)
*
* @io_port: base I/O address
**/
-static void __init trms1040_wait_30us(unsigned long io_port)
+static void __devinit trms1040_wait_30us(unsigned long io_port)
{
/* ScsiPortStallExecution(30); wait 30 us */
outb(5, io_port + TRM_S1040_GEN_TIMER);
@@ -3948,7 +3954,7 @@ static void __init trms1040_wait_30us(unsigned long io_port)
* @cmd: SB + op code (command) to send
* @addr: address to send
**/
-static void __init trms1040_write_cmd(unsigned long io_port, u8 cmd, u8 addr)
+static void __devinit trms1040_write_cmd(unsigned long io_port, u8 cmd, u8 addr)
{
int i;
u8 send_data;
@@ -3993,7 +3999,7 @@ static void __init trms1040_write_cmd(unsigned long io_port, u8 cmd, u8 addr)
* @addr: offset into EEPROM
* @byte: bytes to write
**/
-static void __init trms1040_set_data(unsigned long io_port, u8 addr, u8 byte)
+static void __devinit trms1040_set_data(unsigned long io_port, u8 addr, u8 byte)
{
int i;
u8 send_data;
@@ -4047,7 +4053,7 @@ static void __init trms1040_set_data(unsigned long io_port, u8 addr, u8 byte)
* @eeprom: the data to write
* @io_port: the base io port
**/
-static void __init trms1040_write_all(struct NvRamType *eeprom, unsigned long io_port)
+static void __devinit trms1040_write_all(struct NvRamType *eeprom, unsigned long io_port)
{
u8 *b_eeprom = (u8 *)eeprom;
u8 addr;
@@ -4087,7 +4093,7 @@ static void __init trms1040_write_all(struct NvRamType *eeprom, unsigned long io
*
* Returns the the byte read.
**/
-static u8 __init trms1040_get_data(unsigned long io_port, u8 addr)
+static u8 __devinit trms1040_get_data(unsigned long io_port, u8 addr)
{
int i;
u8 read_byte;
@@ -4125,7 +4131,7 @@ static u8 __init trms1040_get_data(unsigned long io_port, u8 addr)
* @eeprom: where to store the data
* @io_port: the base io port
**/
-static void __init trms1040_read_all(struct NvRamType *eeprom, unsigned long io_port)
+static void __devinit trms1040_read_all(struct NvRamType *eeprom, unsigned long io_port)
{
u8 *b_eeprom = (u8 *)eeprom;
u8 addr;
@@ -4155,7 +4161,7 @@ static void __init trms1040_read_all(struct NvRamType *eeprom, unsigned long io_
* @eeprom: caller allocated strcuture to read the eeprom data into
* @io_port: io port to read from
**/
-static void __init check_eeprom(struct NvRamType *eeprom, unsigned long io_port)
+static void __devinit check_eeprom(struct NvRamType *eeprom, unsigned long io_port)
{
u16 *w_eeprom = (u16 *)eeprom;
u16 w_addr;
@@ -4225,7 +4231,7 @@ static void __init check_eeprom(struct NvRamType *eeprom, unsigned long io_port)
*
* @eeprom: The eeprom data strucutre to show details for.
**/
-static void __init print_eeprom_settings(struct NvRamType *eeprom)
+static void __devinit print_eeprom_settings(struct NvRamType *eeprom)
{
dprintkl(KERN_INFO, "Used settings: AdapterID=%02i, Speed=%i(%02i.%01iMHz), dev_mode=0x%02x\n",
eeprom->scsi_id,
@@ -4246,15 +4252,16 @@ static void adapter_sg_tables_free(struct AdapterCtlBlk *acb)
const unsigned srbs_per_page = PAGE_SIZE/SEGMENTX_LEN;
for (i = 0; i < DC395x_MAX_SRB_CNT; i += srbs_per_page)
- if (acb->srb_array[i].segment_x)
- kfree(acb->srb_array[i].segment_x);
+ kfree(acb->srb_array[i].segment_x);
+
+ vfree(acb->srb_array[0].virt_map);
}
/*
* Allocate SG tables; as we have to pci_map them, an SG list (struct SGentry*)
* should never cross a page boundary */
-static int __init adapter_sg_tables_alloc(struct AdapterCtlBlk *acb)
+static int __devinit adapter_sg_tables_alloc(struct AdapterCtlBlk *acb)
{
const unsigned mem_needed = (DC395x_MAX_SRB_CNT+1)
*SEGMENTX_LEN;
@@ -4263,9 +4270,12 @@ static int __init adapter_sg_tables_alloc(struct AdapterCtlBlk *acb)
int srb_idx = 0;
unsigned i = 0;
struct SGentry *ptr;
+ void **virt_array;
- for (i = 0; i < DC395x_MAX_SRB_CNT; i++)
+ for (i = 0; i < DC395x_MAX_SRB_CNT; i++) {
acb->srb_array[i].segment_x = NULL;
+ acb->srb_array[i].virt_map = NULL;
+ }
dprintkdbg(DBG_1, "Allocate %i pages for SG tables\n", pages);
while (pages--) {
@@ -4286,6 +4296,19 @@ static int __init adapter_sg_tables_alloc(struct AdapterCtlBlk *acb)
ptr + (i * DC395x_MAX_SG_LISTENTRY);
else
dprintkl(KERN_DEBUG, "No space for tmsrb SG table reserved?!\n");
+
+ virt_array = vmalloc((DC395x_MAX_SRB_CNT + 1) * DC395x_MAX_SG_LISTENTRY * sizeof(void*));
+
+ if (!virt_array) {
+ adapter_sg_tables_free(acb);
+ return 1;
+ }
+
+ for (i = 0; i < DC395x_MAX_SRB_CNT + 1; i++) {
+ acb->srb_array[i].virt_map = virt_array;
+ virt_array += DC395x_MAX_SG_LISTENTRY;
+ }
+
return 0;
}
@@ -4300,7 +4323,7 @@ static int __init adapter_sg_tables_alloc(struct AdapterCtlBlk *acb)
*
* @acb: The adapter to print the information for.
**/
-static void __init adapter_print_config(struct AdapterCtlBlk *acb)
+static void __devinit adapter_print_config(struct AdapterCtlBlk *acb)
{
u8 bval;
@@ -4344,7 +4367,7 @@ static void __init adapter_print_config(struct AdapterCtlBlk *acb)
*
* @acb: The adapter to initialize.
**/
-static void __init adapter_init_params(struct AdapterCtlBlk *acb)
+static void __devinit adapter_init_params(struct AdapterCtlBlk *acb)
{
struct NvRamType *eeprom = &acb->eeprom;
int i;
@@ -4406,7 +4429,7 @@ static void __init adapter_init_params(struct AdapterCtlBlk *acb)
*
* @host: The scsi host instance to fill in the values for.
**/
-static void __init adapter_init_scsi_host(struct Scsi_Host *host)
+static void __devinit adapter_init_scsi_host(struct Scsi_Host *host)
{
struct AdapterCtlBlk *acb = (struct AdapterCtlBlk *)host->hostdata;
struct NvRamType *eeprom = &acb->eeprom;
@@ -4447,7 +4470,7 @@ static void __init adapter_init_scsi_host(struct Scsi_Host *host)
*
* @acb: The adapter which we are to init.
**/
-static void __init adapter_init_chip(struct AdapterCtlBlk *acb)
+static void __devinit adapter_init_chip(struct AdapterCtlBlk *acb)
{
struct NvRamType *eeprom = &acb->eeprom;
@@ -4500,7 +4523,7 @@ static void __init adapter_init_chip(struct AdapterCtlBlk *acb)
* Returns 0 if the initialization succeeds, any other value on
* failure.
**/
-static int __init adapter_init(struct AdapterCtlBlk *acb,
+static int __devinit adapter_init(struct AdapterCtlBlk *acb,
unsigned long io_port, u32 io_port_len, unsigned int irq)
{
if (!request_region(io_port, io_port_len, DC395X_NAME)) {
diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c
index abb55c1e2dddc..53c9b93013f1c 100644
--- a/drivers/scsi/dpt_i2o.c
+++ b/drivers/scsi/dpt_i2o.c
@@ -107,7 +107,7 @@ static dpt_sig_S DPTI_sig = {
*============================================================================
*/
-DECLARE_MUTEX(adpt_configuration_lock);
+static DECLARE_MUTEX(adpt_configuration_lock);
static struct i2o_sys_tbl *sys_tbl = NULL;
static int sys_tbl_ind = 0;
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
index 96eb23515e8b2..ba347576d99b0 100644
--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -129,6 +129,15 @@ int scsi_add_host(struct Scsi_Host *shost, struct device *dev)
GFP_KERNEL)) == NULL)
goto out_del_classdev;
+ if (shost->transportt->create_work_queue) {
+ snprintf(shost->work_q_name, KOBJ_NAME_LEN, "scsi_wq_%d",
+ shost->host_no);
+ shost->work_q = create_singlethread_workqueue(
+ shost->work_q_name);
+ if (!shost->work_q)
+ goto out_free_shost_data;
+ }
+
error = scsi_sysfs_add_host(shost);
if (error)
goto out_destroy_host;
@@ -137,6 +146,10 @@ int scsi_add_host(struct Scsi_Host *shost, struct device *dev)
return error;
out_destroy_host:
+ if (shost->work_q)
+ destroy_workqueue(shost->work_q);
+ out_free_shost_data:
+ kfree(shost->shost_data);
out_del_classdev:
class_device_del(&shost->shost_classdev);
out_del_gendev:
@@ -160,6 +173,9 @@ static void scsi_host_dev_release(struct device *dev)
shost->eh_notify = NULL;
}
+ if (shost->work_q)
+ destroy_workqueue(shost->work_q);
+
scsi_proc_hostdir_rm(shost->hostt);
scsi_destroy_command_freelist(shost);
kfree(shost->shost_data);
@@ -216,6 +232,7 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
spin_lock_init(&shost->default_lock);
scsi_assign_lock(shost, &shost->default_lock);
INIT_LIST_HEAD(&shost->__devices);
+ INIT_LIST_HEAD(&shost->__targets);
INIT_LIST_HEAD(&shost->eh_cmd_q);
INIT_LIST_HEAD(&shost->starved_list);
init_waitqueue_head(&shost->host_wait);
@@ -247,6 +264,16 @@ 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;
@@ -392,3 +419,44 @@ int scsi_is_host_device(const struct device *dev)
return dev->release == scsi_host_dev_release;
}
EXPORT_SYMBOL(scsi_is_host_device);
+
+/**
+ * scsi_queue_work - Queue work to the Scsi_Host workqueue.
+ * @shost: Pointer to Scsi_Host.
+ * @work: Work to queue for execution.
+ *
+ * Return value:
+ * 0 on success / != 0 for error
+ **/
+int scsi_queue_work(struct Scsi_Host *shost, struct work_struct *work)
+{
+ if (unlikely(!shost->work_q)) {
+ printk(KERN_ERR
+ "ERROR: Scsi host '%s' attempted to queue scsi-work, "
+ "when no workqueue created.\n", shost->hostt->name);
+ dump_stack();
+
+ return -EINVAL;
+ }
+
+ return queue_work(shost->work_q, work);
+}
+EXPORT_SYMBOL_GPL(scsi_queue_work);
+
+/**
+ * scsi_flush_work - Flush a Scsi_Host's workqueue.
+ * @shost: Pointer to Scsi_Host.
+ **/
+void scsi_flush_work(struct Scsi_Host *shost)
+{
+ if (!shost->work_q) {
+ printk(KERN_ERR
+ "ERROR: Scsi host '%s' attempted to flush scsi-work, "
+ "when no workqueue created.\n", shost->hostt->name);
+ dump_stack();
+ return;
+ }
+
+ flush_workqueue(shost->work_q);
+}
+EXPORT_SYMBOL_GPL(scsi_flush_work);
diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c
index 599e7137c4100..805cccd042b67 100644
--- a/drivers/scsi/ide-scsi.c
+++ b/drivers/scsi/ide-scsi.c
@@ -96,14 +96,39 @@ typedef struct idescsi_pc_s {
*/
#define IDESCSI_LOG_CMD 0 /* Log SCSI commands */
-typedef struct {
- ide_drive_t *drive;
+typedef struct ide_scsi_obj {
+ ide_drive_t *drive;
+ struct Scsi_Host *host;
+
idescsi_pc_t *pc; /* Current packet command */
unsigned long flags; /* Status/Action flags */
unsigned long transform; /* SCSI cmd translation layer */
unsigned long log; /* log flags */
} idescsi_scsi_t;
+static DECLARE_MUTEX(idescsi_ref_sem);
+
+#define ide_scsi_g(disk) ((disk)->private_data)
+
+static struct ide_scsi_obj *ide_scsi_get(struct gendisk *disk)
+{
+ struct ide_scsi_obj *scsi = NULL;
+
+ down(&idescsi_ref_sem);
+ scsi = ide_scsi_g(disk);
+ if (scsi)
+ scsi_host_get(scsi->host);
+ up(&idescsi_ref_sem);
+ return scsi;
+}
+
+static void ide_scsi_put(struct ide_scsi_obj *scsi)
+{
+ down(&idescsi_ref_sem);
+ scsi_host_put(scsi->host);
+ up(&idescsi_ref_sem);
+}
+
static inline idescsi_scsi_t *scsihost_to_idescsi(struct Scsi_Host *host)
{
return (idescsi_scsi_t*) (&host[1]);
@@ -679,7 +704,6 @@ static void idescsi_add_settings(ide_drive_t *drive)
static void idescsi_setup (ide_drive_t *drive, idescsi_scsi_t *scsi)
{
DRIVER(drive)->busy++;
- drive->ready_stat = 0;
if (drive->id && (drive->id->config & 0x0060) == 0x20)
set_bit (IDESCSI_DRQ_INTERRUPT, &scsi->flags);
set_bit(IDESCSI_TRANSFORM, &scsi->transform);
@@ -694,21 +718,32 @@ static void idescsi_setup (ide_drive_t *drive, idescsi_scsi_t *scsi)
static int idescsi_cleanup (ide_drive_t *drive)
{
struct Scsi_Host *scsihost = drive->driver_data;
+ struct gendisk *g = drive->disk;
if (ide_unregister_subdriver(drive))
return 1;
-
- /* FIXME?: Are these two statements necessary? */
+
drive->driver_data = NULL;
- drive->disk->fops = ide_fops;
+ g->private_data = NULL;
+ g->fops = ide_fops;
scsi_remove_host(scsihost);
- scsi_host_put(scsihost);
+ ide_scsi_put(scsihost_to_idescsi(scsihost));
+
return 0;
}
static int idescsi_attach(ide_drive_t *drive);
+#ifdef CONFIG_PROC_FS
+static ide_proc_entry_t idescsi_proc[] = {
+ { "capacity", S_IFREG|S_IRUGO, proc_ide_read_capacity, NULL },
+ { NULL, 0, NULL, NULL }
+};
+#else
+# define idescsi_proc NULL
+#endif
+
/*
* IDE subdriver functions, registered with ide.c
*/
@@ -719,6 +754,7 @@ static ide_driver_t idescsi_driver = {
.media = ide_scsi,
.busy = 0,
.supports_dsc_overlap = 0,
+ .proc = idescsi_proc,
.attach = idescsi_attach,
.cleanup = idescsi_cleanup,
.do_request = idescsi_do_request,
@@ -730,15 +766,30 @@ static ide_driver_t idescsi_driver = {
static int idescsi_ide_open(struct inode *inode, struct file *filp)
{
- ide_drive_t *drive = inode->i_bdev->bd_disk->private_data;
+ struct gendisk *disk = inode->i_bdev->bd_disk;
+ struct ide_scsi_obj *scsi;
+ ide_drive_t *drive;
+
+ if (!(scsi = ide_scsi_get(disk)))
+ return -ENXIO;
+
+ drive = scsi->drive;
+
drive->usage++;
+
return 0;
}
static int idescsi_ide_release(struct inode *inode, struct file *filp)
{
- ide_drive_t *drive = inode->i_bdev->bd_disk->private_data;
+ struct gendisk *disk = inode->i_bdev->bd_disk;
+ struct ide_scsi_obj *scsi = ide_scsi_g(disk);
+ ide_drive_t *drive = scsi->drive;
+
drive->usage--;
+
+ ide_scsi_put(scsi);
+
return 0;
}
@@ -746,7 +797,8 @@ static int idescsi_ide_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
struct block_device *bdev = inode->i_bdev;
- return generic_ide_ioctl(file, bdev, cmd, arg);
+ struct ide_scsi_obj *scsi = ide_scsi_g(bdev->bd_disk);
+ return generic_ide_ioctl(scsi->drive, file, bdev, cmd, arg);
}
static struct block_device_operations idescsi_ops = {
@@ -1033,6 +1085,7 @@ static int idescsi_attach(ide_drive_t *drive)
{
idescsi_scsi_t *idescsi;
struct Scsi_Host *host;
+ struct gendisk *g = drive->disk;
static int warned;
int err;
@@ -1061,10 +1114,12 @@ static int idescsi_attach(ide_drive_t *drive)
drive->driver_data = host;
idescsi = scsihost_to_idescsi(host);
idescsi->drive = drive;
+ idescsi->host = host;
err = ide_register_subdriver(drive, &idescsi_driver);
if (!err) {
idescsi_setup (drive, idescsi);
- drive->disk->fops = &idescsi_ops;
+ g->fops = &idescsi_ops;
+ g->private_data = idescsi;
err = scsi_add_host(host, &drive->gendev);
if (!err) {
scsi_scan_host(host);
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index 9b684f9870fdd..5441531c0d8e5 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -89,6 +89,8 @@ static struct list_head ipr_ioa_head = LIST_HEAD_INIT(ipr_ioa_head);
static unsigned int ipr_log_level = IPR_DEFAULT_LOG_LEVEL;
static unsigned int ipr_max_speed = 1;
static int ipr_testmode = 0;
+static unsigned int ipr_fastfail = 0;
+static unsigned int ipr_transop_timeout = IPR_OPERATIONAL_TIMEOUT;
static DEFINE_SPINLOCK(ipr_driver_lock);
/* This table describes the differences between DMA controller chips */
@@ -108,7 +110,7 @@ static const struct ipr_chip_cfg_t ipr_chip_cfg[] = {
.clr_uproc_interrupt_reg = 0x00218
}
},
- { /* Snipe */
+ { /* Snipe and Scamp */
.mailbox = 0x0052C,
.cache_line_size = 0x20,
{
@@ -125,6 +127,13 @@ static const struct ipr_chip_cfg_t ipr_chip_cfg[] = {
},
};
+static const struct ipr_chip_t ipr_chip[] = {
+ { PCI_VENDOR_ID_MYLEX, PCI_DEVICE_ID_IBM_GEMSTONE, &ipr_chip_cfg[0] },
+ { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CITRINE, &ipr_chip_cfg[0] },
+ { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_SNIPE, &ipr_chip_cfg[1] },
+ { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_SCAMP, &ipr_chip_cfg[1] }
+};
+
static int ipr_max_bus_speeds [] = {
IPR_80MBs_SCSI_RATE, IPR_U160_SCSI_RATE, IPR_U320_SCSI_RATE
};
@@ -137,6 +146,10 @@ module_param_named(log_level, ipr_log_level, uint, 0);
MODULE_PARM_DESC(log_level, "Set to 0 - 4 for increasing verbosity of device driver");
module_param_named(testmode, ipr_testmode, int, 0);
MODULE_PARM_DESC(testmode, "DANGEROUS!!! Allows unsupported configurations");
+module_param_named(fastfail, ipr_fastfail, int, 0);
+MODULE_PARM_DESC(fastfail, "Reduce timeouts and retries");
+module_param_named(transop_timeout, ipr_transop_timeout, int, 0);
+MODULE_PARM_DESC(transop_timeout, "Time in seconds to wait for adapter to come operational (default: 300)");
MODULE_LICENSE("GPL");
MODULE_VERSION(IPR_DRIVER_VERSION);
@@ -310,10 +323,12 @@ struct ipr_error_table_t ipr_error_table[] = {
"3150: SCSI bus configuration error"},
{0x06690200, 0, 1,
"9041: Array protection temporarily suspended"},
+ {0x06698200, 0, 1,
+ "9042: Corrupt array parity detected on specified device"},
{0x066B0200, 0, 1,
"9030: Array no longer protected due to missing or failed disk unit"},
{0x066B8200, 0, 1,
- "9042: Corrupt array parity detected on specified device"},
+ "9032: Array exposed but still protected"},
{0x07270000, 0, 0,
"Failure due to other device"},
{0x07278000, 0, 1,
@@ -779,8 +794,6 @@ static void ipr_init_res_entry(struct ipr_resource_entry *res)
res->add_to_ml = 0;
res->del_from_ml = 0;
res->resetting_device = 0;
- res->tcq_active = 0;
- res->qdepth = IPR_MAX_CMD_PER_LUN;
res->sdev = NULL;
}
@@ -1001,9 +1014,7 @@ static void ipr_log_array_error(struct ipr_ioa_cfg *ioa_cfg,
int i;
struct ipr_hostrcb_type_04_error *error;
struct ipr_hostrcb_array_data_entry *array_entry;
- u8 zero_sn[IPR_SERIAL_NUM_LEN];
-
- memset(zero_sn, '0', IPR_SERIAL_NUM_LEN);
+ const u8 zero_sn[IPR_SERIAL_NUM_LEN] = { [0 ... IPR_SERIAL_NUM_LEN-1] = '0' };
error = &hostrcb->hcam.u.error.u.type_04_error;
@@ -1024,7 +1035,7 @@ static void ipr_log_array_error(struct ipr_ioa_cfg *ioa_cfg,
if (!memcmp(array_entry->serial_num, zero_sn, IPR_SERIAL_NUM_LEN))
continue;
- if (error->exposed_mode_adn == i) {
+ if (be32_to_cpu(error->exposed_mode_adn) == i) {
ipr_err("Exposed Array Member %d:\n", i);
} else {
ipr_err("Array Member %d:\n", i);
@@ -1250,6 +1261,41 @@ static void ipr_timeout(struct ipr_cmnd *ipr_cmd)
}
/**
+ * ipr_oper_timeout - Adapter timed out transitioning to operational
+ * @ipr_cmd: ipr command struct
+ *
+ * This function blocks host requests and initiates an
+ * adapter reset.
+ *
+ * Return value:
+ * none
+ **/
+static void ipr_oper_timeout(struct ipr_cmnd *ipr_cmd)
+{
+ unsigned long lock_flags = 0;
+ struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
+
+ ENTER;
+ spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
+
+ ioa_cfg->errors_logged++;
+ dev_err(&ioa_cfg->pdev->dev,
+ "Adapter timed out transitioning to operational.\n");
+
+ if (WAIT_FOR_DUMP == ioa_cfg->sdt_state)
+ ioa_cfg->sdt_state = GET_DUMP;
+
+ if (!ioa_cfg->in_reset_reload || ioa_cfg->reset_cmd == ipr_cmd) {
+ if (ipr_fastfail)
+ ioa_cfg->reset_retries += IPR_NUM_RESET_RELOAD_RETRIES;
+ ipr_initiate_ioa_reset(ioa_cfg, IPR_SHUTDOWN_NONE);
+ }
+
+ spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
+ LEAVE;
+}
+
+/**
* ipr_reset_reload - Reset/Reload the IOA
* @ioa_cfg: ioa config struct
* @shutdown_type: shutdown type
@@ -1390,7 +1436,7 @@ static int ipr_wait_iodbg_ack(struct ipr_ioa_cfg *ioa_cfg, int max_delay)
**/
static int ipr_get_ldump_data_section(struct ipr_ioa_cfg *ioa_cfg,
u32 start_addr,
- u32 *dest, u32 length_in_words)
+ __be32 *dest, u32 length_in_words)
{
volatile u32 temp_pcii_reg;
int i, delay = 0;
@@ -1482,7 +1528,7 @@ static int ipr_sdt_copy(struct ipr_ioa_cfg *ioa_cfg,
{
int bytes_copied = 0;
int cur_len, rc, rem_len, rem_page_len;
- u32 *page;
+ __be32 *page;
unsigned long lock_flags = 0;
struct ipr_ioa_dump *ioa_dump = &ioa_cfg->dump->ioa_dump;
@@ -1490,7 +1536,7 @@ static int ipr_sdt_copy(struct ipr_ioa_cfg *ioa_cfg,
(ioa_dump->hdr.len + bytes_copied) < IPR_MAX_IOA_DUMP_SIZE) {
if (ioa_dump->page_offset >= PAGE_SIZE ||
ioa_dump->page_offset == 0) {
- page = (u32 *)__get_free_page(GFP_ATOMIC);
+ page = (__be32 *)__get_free_page(GFP_ATOMIC);
if (!page) {
ipr_trace;
@@ -1705,8 +1751,8 @@ static void ipr_get_ioa_dump(struct ipr_ioa_cfg *ioa_cfg, struct ipr_dump *dump)
on entries in this table */
sdt = &ioa_dump->sdt;
- rc = ipr_get_ldump_data_section(ioa_cfg, start_addr, (u32 *)sdt,
- sizeof(struct ipr_sdt) / sizeof(u32));
+ rc = ipr_get_ldump_data_section(ioa_cfg, start_addr, (__be32 *)sdt,
+ sizeof(struct ipr_sdt) / sizeof(__be32));
/* Smart Dump table is ready to use and the first entry is valid */
if (rc || (be32_to_cpu(sdt->hdr.state) != IPR_FMT2_SDT_READY_TO_USE)) {
@@ -1878,6 +1924,7 @@ restart:
}
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
+ kobject_uevent(&ioa_cfg->host->shost_classdev.kobj, KOBJ_CHANGE, NULL);
LEAVE;
}
@@ -2619,100 +2666,48 @@ static int ipr_free_dump(struct ipr_ioa_cfg *ioa_cfg) { return 0; };
**/
static int ipr_change_queue_depth(struct scsi_device *sdev, int qdepth)
{
- struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)sdev->host->hostdata;
- struct ipr_resource_entry *res;
- int tagged = 0;
- unsigned long lock_flags = 0;
-
- spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
- res = (struct ipr_resource_entry *)sdev->hostdata;
- if (res) {
- res->qdepth = qdepth;
-
- if (ipr_is_gscsi(res) && res->tcq_active)
- tagged = MSG_ORDERED_TAG;
- }
-
- spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
- scsi_adjust_queue_depth(sdev, tagged, qdepth);
- return qdepth;
+ scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), qdepth);
+ return sdev->queue_depth;
}
/**
- * ipr_show_tcq_enable - Show if the device is enabled for tcqing
- * @dev: device struct
- * @buf: buffer
+ * ipr_change_queue_type - Change the device's queue type
+ * @dsev: scsi device struct
+ * @tag_type: type of tags to use
*
* Return value:
- * number of bytes printed to buffer
+ * actual queue type set
**/
-static ssize_t ipr_show_tcq_enable(struct device *dev, char *buf)
+static int ipr_change_queue_type(struct scsi_device *sdev, int tag_type)
{
- struct scsi_device *sdev = to_scsi_device(dev);
struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)sdev->host->hostdata;
struct ipr_resource_entry *res;
unsigned long lock_flags = 0;
- ssize_t len = -ENXIO;
spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
res = (struct ipr_resource_entry *)sdev->hostdata;
- if (res)
- len = snprintf(buf, PAGE_SIZE, "%d\n", res->tcq_active);
- spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
- return len;
-}
-
-/**
- * ipr_store_tcq_enable - Change the device's TCQing state
- * @dev: device struct
- * @buf: buffer
- *
- * Return value:
- * number of bytes printed to buffer
- **/
-static ssize_t ipr_store_tcq_enable(struct device *dev,
- const char *buf, size_t count)
-{
- struct scsi_device *sdev = to_scsi_device(dev);
- struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)sdev->host->hostdata;
- struct ipr_resource_entry *res;
- unsigned long lock_flags = 0;
- int tcq_active = simple_strtoul(buf, NULL, 10);
- ssize_t len = -ENXIO;
-
- spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
-
- res = (struct ipr_resource_entry *)sdev->hostdata;
if (res) {
if (ipr_is_gscsi(res) && sdev->tagged_supported) {
- if (tcq_active) {
- res->tcq_active = 1;
- scsi_activate_tcq(sdev, res->qdepth);
- } else {
- res->tcq_active = 0;
- scsi_deactivate_tcq(sdev, res->qdepth);
- }
+ /*
+ * We don't bother quiescing the device here since the
+ * adapter firmware does it for us.
+ */
+ scsi_set_tag_type(sdev, tag_type);
- len = strlen(buf);
- } else if (tcq_active) {
- len = -EINVAL;
- }
- }
+ if (tag_type)
+ scsi_activate_tcq(sdev, sdev->queue_depth);
+ else
+ scsi_deactivate_tcq(sdev, sdev->queue_depth);
+ } else
+ tag_type = 0;
+ } else
+ tag_type = 0;
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
- return len;
+ return tag_type;
}
-static struct device_attribute ipr_tcqing_attr = {
- .attr = {
- .name = "tcq_enable",
- .mode = S_IRUSR | S_IWUSR,
- },
- .store = ipr_store_tcq_enable,
- .show = ipr_show_tcq_enable
-};
-
/**
* ipr_show_adapter_handle - Show the adapter's resource handle for this device
* @dev: device struct
@@ -2746,7 +2741,6 @@ static struct device_attribute ipr_adapter_handle_attr = {
};
static struct device_attribute *ipr_dev_attrs[] = {
- &ipr_tcqing_attr,
&ipr_adapter_handle_attr,
NULL,
};
@@ -2832,11 +2826,13 @@ static int ipr_slave_configure(struct scsi_device *sdev)
sdev->type = TYPE_RAID;
if (ipr_is_af_dasd_device(res) || ipr_is_ioa_resource(res))
sdev->scsi_level = 4;
- if (ipr_is_vset_device(res))
+ if (ipr_is_vset_device(res)) {
sdev->timeout = IPR_VSET_RW_TIMEOUT;
+ blk_queue_max_sectors(sdev->request_queue, IPR_VSET_MAX_SECTORS);
+ }
if (IPR_IS_DASD_DEVICE(res->cfgte.std_inq_data))
sdev->allow_restart = 1;
- scsi_adjust_queue_depth(sdev, 0, res->qdepth);
+ scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun);
}
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
return 0;
@@ -3514,7 +3510,7 @@ static void ipr_erp_cancel_all(struct ipr_cmnd *ipr_cmd)
ipr_reinit_ipr_cmnd_for_erp(ipr_cmd);
- if (!res->tcq_active) {
+ if (!scsi_get_tag_type(scsi_cmd->device)) {
ipr_erp_request_sense(ipr_cmd);
return;
}
@@ -3546,7 +3542,7 @@ static void ipr_dump_ioasa(struct ipr_ioa_cfg *ioa_cfg,
u16 data_len;
u32 ioasc;
struct ipr_ioasa *ioasa = &ipr_cmd->ioasa;
- u32 *ioasa_data = (u32 *)ioasa;
+ __be32 *ioasa_data = (__be32 *)ioasa;
int error_index;
ioasc = be32_to_cpu(ioasa->ioasc) & IPR_IOASC_IOASC_MASK;
@@ -3947,11 +3943,12 @@ static struct scsi_host_template driver_template = {
.slave_configure = ipr_slave_configure,
.slave_destroy = ipr_slave_destroy,
.change_queue_depth = ipr_change_queue_depth,
+ .change_queue_type = ipr_change_queue_type,
.bios_param = ipr_biosparam,
.can_queue = IPR_MAX_COMMANDS,
.this_id = -1,
.sg_tablesize = IPR_MAX_SGLIST,
- .max_sectors = IPR_MAX_SECTORS,
+ .max_sectors = IPR_IOA_MAX_SECTORS,
.cmd_per_lun = IPR_MAX_CMD_PER_LUN,
.use_clustering = ENABLE_CLUSTERING,
.shost_attrs = ipr_ioa_attrs,
@@ -4058,10 +4055,10 @@ static int ipr_ioa_reset_done(struct ipr_cmnd *ipr_cmd)
list_for_each_entry(res, &ioa_cfg->used_res_q, queue) {
if (ioa_cfg->allow_ml_add_del && (res->add_to_ml || res->del_from_ml)) {
ipr_trace;
- schedule_work(&ioa_cfg->work_q);
break;
}
}
+ schedule_work(&ioa_cfg->work_q);
list_for_each_entry_safe(hostrcb, temp, &ioa_cfg->hostrcb_free_q, queue) {
list_del(&hostrcb->queue);
@@ -4317,7 +4314,7 @@ static void ipr_modify_ioafp_mode_page_28(struct ipr_ioa_cfg *ioa_cfg,
* none
**/
static void ipr_build_mode_select(struct ipr_cmnd *ipr_cmd,
- u32 res_handle, u8 parm, u32 dma_addr,
+ __be32 res_handle, u8 parm, u32 dma_addr,
u8 xfer_len)
{
struct ipr_ioadl_desc *ioadl = ipr_cmd->ioadl;
@@ -4392,7 +4389,7 @@ static int ipr_ioafp_mode_select_page28(struct ipr_cmnd *ipr_cmd)
* none
**/
static void ipr_build_mode_sense(struct ipr_cmnd *ipr_cmd,
- u32 res_handle,
+ __be32 res_handle,
u8 parm, u32 dma_addr, u8 xfer_len)
{
struct ipr_ioadl_desc *ioadl = ipr_cmd->ioadl;
@@ -4500,6 +4497,7 @@ static int ipr_init_res_table(struct ipr_cmnd *ipr_cmd)
list_for_each_entry_safe(res, temp, &old_res, queue) {
if (res->sdev) {
res->del_from_ml = 1;
+ res->sdev->hostdata = NULL;
list_move_tail(&res->queue, &ioa_cfg->used_res_q);
} else {
list_move_tail(&res->queue, &ioa_cfg->free_res_q);
@@ -4803,8 +4801,8 @@ static int ipr_reset_enable_ioa(struct ipr_cmnd *ipr_cmd)
dev_info(&ioa_cfg->pdev->dev, "Initializing IOA.\n");
ipr_cmd->timer.data = (unsigned long) ipr_cmd;
- ipr_cmd->timer.expires = jiffies + IPR_OPERATIONAL_TIMEOUT;
- ipr_cmd->timer.function = (void (*)(unsigned long))ipr_timeout;
+ ipr_cmd->timer.expires = jiffies + (ipr_transop_timeout * HZ);
+ ipr_cmd->timer.function = (void (*)(unsigned long))ipr_oper_timeout;
ipr_cmd->done = ipr_reset_ioa_job;
add_timer(&ipr_cmd->timer);
list_add_tail(&ipr_cmd->queue, &ioa_cfg->pending_q);
@@ -4876,8 +4874,8 @@ static void ipr_get_unit_check_buffer(struct ipr_ioa_cfg *ioa_cfg)
}
memset(&sdt, 0, sizeof(struct ipr_uc_sdt));
- rc = ipr_get_ldump_data_section(ioa_cfg, mailbox, (u32 *) &sdt,
- (sizeof(struct ipr_uc_sdt)) / sizeof(u32));
+ rc = ipr_get_ldump_data_section(ioa_cfg, mailbox, (__be32 *) &sdt,
+ (sizeof(struct ipr_uc_sdt)) / sizeof(__be32));
if (rc || (be32_to_cpu(sdt.hdr.state) != IPR_FMT2_SDT_READY_TO_USE) ||
!(sdt.entry[0].flags & IPR_SDT_VALID_ENTRY)) {
@@ -4896,8 +4894,8 @@ static void ipr_get_unit_check_buffer(struct ipr_ioa_cfg *ioa_cfg)
rc = ipr_get_ldump_data_section(ioa_cfg,
be32_to_cpu(sdt.entry[0].bar_str_offset),
- (u32 *)&hostrcb->hcam,
- min(length, (int)sizeof(hostrcb->hcam)) / sizeof(u32));
+ (__be32 *)&hostrcb->hcam,
+ min(length, (int)sizeof(hostrcb->hcam)) / sizeof(__be32));
if (!rc)
ipr_handle_log_data(ioa_cfg, hostrcb);
@@ -5279,7 +5277,7 @@ static void ipr_initiate_ioa_reset(struct ipr_ioa_cfg *ioa_cfg,
if (ioa_cfg->in_reset_reload && ioa_cfg->sdt_state == GET_DUMP)
ioa_cfg->sdt_state = ABORT_DUMP;
- if (ioa_cfg->reset_retries++ > IPR_NUM_RESET_RELOAD_RETRIES) {
+ if (ioa_cfg->reset_retries++ >= IPR_NUM_RESET_RELOAD_RETRIES) {
dev_err(&ioa_cfg->pdev->dev,
"IOA taken offline - error recovery failed\n");
@@ -5664,6 +5662,28 @@ static void __devinit ipr_init_ioa_cfg(struct ipr_ioa_cfg *ioa_cfg,
}
/**
+ * ipr_get_chip_cfg - Find adapter chip configuration
+ * @dev_id: PCI device id struct
+ *
+ * Return value:
+ * ptr to chip config on success / NULL on failure
+ **/
+static const struct ipr_chip_cfg_t * __devinit
+ipr_get_chip_cfg(const struct pci_device_id *dev_id)
+{
+ int i;
+
+ if (dev_id->driver_data)
+ return (const struct ipr_chip_cfg_t *)dev_id->driver_data;
+
+ for (i = 0; i < ARRAY_SIZE(ipr_chip); i++)
+ if (ipr_chip[i].vendor == dev_id->vendor &&
+ ipr_chip[i].device == dev_id->device)
+ return ipr_chip[i].cfg;
+ return NULL;
+}
+
+/**
* ipr_probe_ioa - Allocates memory and does first stage of initialization
* @pdev: PCI device struct
* @dev_id: PCI device id struct
@@ -5700,7 +5720,13 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev,
ioa_cfg = (struct ipr_ioa_cfg *)host->hostdata;
memset(ioa_cfg, 0, sizeof(struct ipr_ioa_cfg));
- ioa_cfg->chip_cfg = (const struct ipr_chip_cfg_t *)dev_id->driver_data;
+ ioa_cfg->chip_cfg = ipr_get_chip_cfg(dev_id);
+
+ if (!ioa_cfg->chip_cfg) {
+ dev_err(&pdev->dev, "Unknown adapter chipset 0x%04X 0x%04X\n",
+ dev_id->vendor, dev_id->device);
+ goto out_scsi_host_put;
+ }
ipr_regs_pci = pci_resource_start(pdev, 0);
@@ -5989,22 +6015,28 @@ static struct pci_device_id ipr_pci_table[] __devinitdata = {
PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_5702,
0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] },
{ PCI_VENDOR_ID_MYLEX, PCI_DEVICE_ID_IBM_GEMSTONE,
- PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572E,
- 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] },
- { PCI_VENDOR_ID_MYLEX, PCI_DEVICE_ID_IBM_GEMSTONE,
PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_5703,
0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] },
{ PCI_VENDOR_ID_MYLEX, PCI_DEVICE_ID_IBM_GEMSTONE,
PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_573D,
0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] },
+ { PCI_VENDOR_ID_MYLEX, PCI_DEVICE_ID_IBM_GEMSTONE,
+ PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_573E,
+ 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] },
{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CITRINE,
PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_571B,
0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] },
+ { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CITRINE,
+ PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572E,
+ 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] },
+ { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CITRINE,
+ PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_571A,
+ 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] },
{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_SNIPE,
PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_2780,
0, 0, (kernel_ulong_t)&ipr_chip_cfg[1] },
- { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_SNIPE,
- PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_570F,
+ { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_SCAMP,
+ PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_571E,
0, 0, (kernel_ulong_t)&ipr_chip_cfg[1] },
{ }
};
diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h
index 2f723a75356e0..446f4259285b8 100644
--- a/drivers/scsi/ipr.h
+++ b/drivers/scsi/ipr.h
@@ -36,8 +36,8 @@
/*
* Literals
*/
-#define IPR_DRIVER_VERSION "2.0.12"
-#define IPR_DRIVER_DATE "(December 14, 2004)"
+#define IPR_DRIVER_VERSION "2.0.13"
+#define IPR_DRIVER_DATE "(February 21, 2005)"
/*
* IPR_DBG_TRACE: Setting this to 1 will turn on some general function tracing
@@ -70,10 +70,12 @@
#define IPR_SUBS_DEV_ID_2780 0x0264
#define IPR_SUBS_DEV_ID_5702 0x0266
#define IPR_SUBS_DEV_ID_5703 0x0278
-#define IPR_SUBS_DEV_ID_572E 0x02D3
+#define IPR_SUBS_DEV_ID_572E 0x028D
+#define IPR_SUBS_DEV_ID_573E 0x02D3
#define IPR_SUBS_DEV_ID_573D 0x02D4
-#define IPR_SUBS_DEV_ID_570F 0x02BD
+#define IPR_SUBS_DEV_ID_571A 0x02C0
#define IPR_SUBS_DEV_ID_571B 0x02BE
+#define IPR_SUBS_DEV_ID_571E 0x02BF
#define IPR_NAME "ipr"
@@ -128,7 +130,8 @@
#define IPR_MAX_PHYSICAL_DEVS 192
#define IPR_MAX_SGLIST 64
-#define IPR_MAX_SECTORS 512
+#define IPR_IOA_MAX_SECTORS 32767
+#define IPR_VSET_MAX_SECTORS 512
#define IPR_MAX_CDB_LEN 16
#define IPR_DEFAULT_BUS_WIDTH 16
@@ -162,17 +165,17 @@
/*
* Timeouts
*/
-#define IPR_SHUTDOWN_TIMEOUT (10 * 60 * HZ)
-#define IPR_VSET_RW_TIMEOUT (2 * 60 * HZ)
+#define IPR_SHUTDOWN_TIMEOUT (ipr_fastfail ? 60 * HZ : 10 * 60 * HZ)
+#define IPR_VSET_RW_TIMEOUT (ipr_fastfail ? 30 * HZ : 2 * 60 * HZ)
#define IPR_ABBREV_SHUTDOWN_TIMEOUT (10 * HZ)
-#define IPR_DEVICE_RESET_TIMEOUT (30 * HZ)
-#define IPR_CANCEL_ALL_TIMEOUT (30 * HZ)
-#define IPR_ABORT_TASK_TIMEOUT (30 * HZ)
-#define IPR_INTERNAL_TIMEOUT (30 * HZ)
+#define IPR_DEVICE_RESET_TIMEOUT (ipr_fastfail ? 10 * HZ : 30 * HZ)
+#define IPR_CANCEL_ALL_TIMEOUT (ipr_fastfail ? 10 * HZ : 30 * HZ)
+#define IPR_ABORT_TASK_TIMEOUT (ipr_fastfail ? 10 * HZ : 30 * HZ)
+#define IPR_INTERNAL_TIMEOUT (ipr_fastfail ? 10 * HZ : 30 * HZ)
#define IPR_WRITE_BUFFER_TIMEOUT (10 * 60 * HZ)
#define IPR_SET_SUP_DEVICE_TIMEOUT (2 * 60 * HZ)
#define IPR_REQUEST_SENSE_TIMEOUT (10 * HZ)
-#define IPR_OPERATIONAL_TIMEOUT (5 * 60 * HZ)
+#define IPR_OPERATIONAL_TIMEOUT (5 * 60)
#define IPR_WAIT_FOR_RESET_TIMEOUT (2 * HZ)
#define IPR_CHECK_FOR_RESET_TIMEOUT (HZ / 10)
#define IPR_WAIT_FOR_BIST_TIMEOUT (2 * HZ)
@@ -302,8 +305,8 @@ struct ipr_config_table_entry {
#define IPR_SUBTYPE_VOLUME_SET 2
struct ipr_res_addr res_addr;
- u32 res_handle;
- u32 reserved4[2];
+ __be32 res_handle;
+ __be32 reserved4[2];
struct ipr_std_inq_data std_inq_data;
}__attribute__ ((packed, aligned (4)));
@@ -311,7 +314,7 @@ struct ipr_config_table_hdr {
u8 num_entries;
u8 flags;
#define IPR_UCODE_DOWNLOAD_REQ 0x10
- u16 reserved;
+ __be16 reserved;
}__attribute__((packed, aligned (4)));
struct ipr_config_table {
@@ -325,7 +328,7 @@ struct ipr_hostrcb_cfg_ch_not {
}__attribute__((packed, aligned (4)));
struct ipr_supported_device {
- u16 data_length;
+ __be16 data_length;
u8 reserved;
u8 num_records;
struct ipr_std_inq_vpids vpids;
@@ -334,7 +337,7 @@ struct ipr_supported_device {
/* Command packet structure */
struct ipr_cmd_pkt {
- u16 reserved; /* Reserved by IOA */
+ __be16 reserved; /* Reserved by IOA */
u8 request_type;
#define IPR_RQTYPE_SCSICDB 0x00
#define IPR_RQTYPE_IOACMD 0x01
@@ -359,38 +362,38 @@ struct ipr_cmd_pkt {
#define IPR_FLAGS_LO_ACA_TASK 0x08
u8 cdb[16];
- u16 timeout;
+ __be16 timeout;
}__attribute__ ((packed, aligned(4)));
/* IOA Request Control Block 128 bytes */
struct ipr_ioarcb {
- u32 ioarcb_host_pci_addr;
- u32 reserved;
- u32 res_handle;
- u32 host_response_handle;
- u32 reserved1;
- u32 reserved2;
- u32 reserved3;
-
- u32 write_data_transfer_length;
- u32 read_data_transfer_length;
- u32 write_ioadl_addr;
- u32 write_ioadl_len;
- u32 read_ioadl_addr;
- u32 read_ioadl_len;
-
- u32 ioasa_host_pci_addr;
- u16 ioasa_len;
- u16 reserved4;
+ __be32 ioarcb_host_pci_addr;
+ __be32 reserved;
+ __be32 res_handle;
+ __be32 host_response_handle;
+ __be32 reserved1;
+ __be32 reserved2;
+ __be32 reserved3;
+
+ __be32 write_data_transfer_length;
+ __be32 read_data_transfer_length;
+ __be32 write_ioadl_addr;
+ __be32 write_ioadl_len;
+ __be32 read_ioadl_addr;
+ __be32 read_ioadl_len;
+
+ __be32 ioasa_host_pci_addr;
+ __be16 ioasa_len;
+ __be16 reserved4;
struct ipr_cmd_pkt cmd_pkt;
- u32 add_cmd_parms_len;
- u32 add_cmd_parms[10];
+ __be32 add_cmd_parms_len;
+ __be32 add_cmd_parms[10];
}__attribute__((packed, aligned (4)));
struct ipr_ioadl_desc {
- u32 flags_and_data_len;
+ __be32 flags_and_data_len;
#define IPR_IOADL_FLAGS_MASK 0xff000000
#define IPR_IOADL_GET_FLAGS(x) (be32_to_cpu(x) & IPR_IOADL_FLAGS_MASK)
#define IPR_IOADL_DATA_LEN_MASK 0x00ffffff
@@ -401,55 +404,55 @@ struct ipr_ioadl_desc {
#define IPR_IOADL_FLAGS_WRITE_LAST 0x69000000
#define IPR_IOADL_FLAGS_LAST 0x01000000
- u32 address;
+ __be32 address;
}__attribute__((packed, aligned (8)));
struct ipr_ioasa_vset {
- u32 failing_lba_hi;
- u32 failing_lba_lo;
- u32 ioa_data[22];
+ __be32 failing_lba_hi;
+ __be32 failing_lba_lo;
+ __be32 ioa_data[22];
}__attribute__((packed, aligned (4)));
struct ipr_ioasa_af_dasd {
- u32 failing_lba;
+ __be32 failing_lba;
}__attribute__((packed, aligned (4)));
struct ipr_ioasa_gpdd {
u8 end_state;
u8 bus_phase;
- u16 reserved;
- u32 ioa_data[23];
+ __be16 reserved;
+ __be32 ioa_data[23];
}__attribute__((packed, aligned (4)));
struct ipr_ioasa_raw {
- u32 ioa_data[24];
+ __be32 ioa_data[24];
}__attribute__((packed, aligned (4)));
struct ipr_ioasa {
- u32 ioasc;
+ __be32 ioasc;
#define IPR_IOASC_SENSE_KEY(ioasc) ((ioasc) >> 24)
#define IPR_IOASC_SENSE_CODE(ioasc) (((ioasc) & 0x00ff0000) >> 16)
#define IPR_IOASC_SENSE_QUAL(ioasc) (((ioasc) & 0x0000ff00) >> 8)
#define IPR_IOASC_SENSE_STATUS(ioasc) ((ioasc) & 0x000000ff)
- u16 ret_stat_len; /* Length of the returned IOASA */
+ __be16 ret_stat_len; /* Length of the returned IOASA */
- u16 avail_stat_len; /* Total Length of status available. */
+ __be16 avail_stat_len; /* Total Length of status available. */
- u32 residual_data_len; /* number of bytes in the host data */
+ __be32 residual_data_len; /* number of bytes in the host data */
/* buffers that were not used by the IOARCB command. */
- u32 ilid;
+ __be32 ilid;
#define IPR_NO_ILID 0
#define IPR_DRIVER_ILID 0xffffffff
- u32 fd_ioasc;
+ __be32 fd_ioasc;
- u32 fd_phys_locator;
+ __be32 fd_phys_locator;
- u32 fd_res_handle;
+ __be32 fd_res_handle;
- u32 ioasc_specific; /* status code specific field */
+ __be32 ioasc_specific; /* status code specific field */
#define IPR_IOASC_SPECIFIC_MASK 0x00ffffff
#define IPR_FIELD_POINTER_VALID (0x80000000 >> 8)
#define IPR_FIELD_POINTER_MASK 0x0000ffff
@@ -497,11 +500,11 @@ struct ipr_dev_bus_entry {
u8 extended_reset_delay;
#define IPR_EXTENDED_RESET_DELAY 7
- u32 max_xfer_rate;
+ __be32 max_xfer_rate;
u8 spinup_delay;
u8 reserved3;
- u16 reserved4;
+ __be16 reserved4;
}__attribute__((packed, aligned (4)));
struct ipr_mode_page28 {
@@ -543,7 +546,7 @@ struct ipr_hostrcb_device_data_entry {
u8 ioa_last_with_dev_sn[IPR_SERIAL_NUM_LEN];
struct ipr_std_inq_vpids cfc_last_with_dev_vpids;
u8 cfc_last_with_dev_sn[IPR_SERIAL_NUM_LEN];
- u32 ioa_data[5];
+ __be32 ioa_data[5];
}__attribute__((packed, aligned (4)));
struct ipr_hostrcb_array_data_entry {
@@ -554,14 +557,14 @@ struct ipr_hostrcb_array_data_entry {
}__attribute__((packed, aligned (4)));
struct ipr_hostrcb_type_ff_error {
- u32 ioa_data[246];
+ __be32 ioa_data[246];
}__attribute__((packed, aligned (4)));
struct ipr_hostrcb_type_01_error {
- u32 seek_counter;
- u32 read_counter;
+ __be32 seek_counter;
+ __be32 read_counter;
u8 sense_data[32];
- u32 ioa_data[236];
+ __be32 ioa_data[236];
}__attribute__((packed, aligned (4)));
struct ipr_hostrcb_type_02_error {
@@ -573,7 +576,7 @@ struct ipr_hostrcb_type_02_error {
u8 ioa_last_attached_to_cfc_sn[IPR_SERIAL_NUM_LEN];
struct ipr_std_inq_vpids cfc_last_attached_to_ioa_vpids;
u8 cfc_last_attached_to_ioa_sn[IPR_SERIAL_NUM_LEN];
- u32 ioa_data[3];
+ __be32 ioa_data[3];
u8 reserved[844];
}__attribute__((packed, aligned (4)));
@@ -582,8 +585,8 @@ struct ipr_hostrcb_type_03_error {
u8 ioa_sn[IPR_SERIAL_NUM_LEN];
struct ipr_std_inq_vpids cfc_vpids;
u8 cfc_sn[IPR_SERIAL_NUM_LEN];
- u32 errors_detected;
- u32 errors_logged;
+ __be32 errors_detected;
+ __be32 errors_logged;
u8 ioa_data[12];
struct ipr_hostrcb_device_data_entry dev_entry[3];
u8 reserved[444];
@@ -596,11 +599,11 @@ struct ipr_hostrcb_type_04_error {
u8 cfc_sn[IPR_SERIAL_NUM_LEN];
u8 ioa_data[12];
struct ipr_hostrcb_array_data_entry array_member[10];
- u32 exposed_mode_adn;
- u32 array_id;
+ __be32 exposed_mode_adn;
+ __be32 array_id;
struct ipr_std_inq_vpids incomp_dev_vpids;
u8 incomp_dev_sn[IPR_SERIAL_NUM_LEN];
- u32 ioa_data2;
+ __be32 ioa_data2;
struct ipr_hostrcb_array_data_entry array_member2[8];
struct ipr_res_addr last_func_vset_res_addr;
u8 vset_serial_num[IPR_SERIAL_NUM_LEN];
@@ -609,10 +612,10 @@ struct ipr_hostrcb_type_04_error {
}__attribute__((packed, aligned (4)));
struct ipr_hostrcb_error {
- u32 failing_dev_ioasc;
+ __be32 failing_dev_ioasc;
struct ipr_res_addr failing_dev_res_addr;
- u32 failing_dev_res_handle;
- u32 prc;
+ __be32 failing_dev_res_handle;
+ __be32 prc;
union {
struct ipr_hostrcb_type_ff_error type_ff_error;
struct ipr_hostrcb_type_01_error type_01_error;
@@ -623,7 +626,7 @@ struct ipr_hostrcb_error {
}__attribute__((packed, aligned (4)));
struct ipr_hostrcb_raw {
- u32 data[sizeof(struct ipr_hostrcb_error)/sizeof(u32)];
+ __be32 data[sizeof(struct ipr_hostrcb_error)/sizeof(__be32)];
}__attribute__((packed, aligned (4)));
struct ipr_hcam {
@@ -655,10 +658,10 @@ struct ipr_hcam {
#define IPR_HOST_RCB_OVERLAY_ID_DEFAULT 0xFF
u8 reserved1[3];
- u32 ilid;
- u32 time_since_last_ioa_reset;
- u32 reserved2;
- u32 length;
+ __be32 ilid;
+ __be32 time_since_last_ioa_reset;
+ __be32 reserved2;
+ __be32 length;
union {
struct ipr_hostrcb_error error;
@@ -675,8 +678,8 @@ struct ipr_hostrcb {
/* IPR smart dump table structures */
struct ipr_sdt_entry {
- u32 bar_str_offset;
- u32 end_offset;
+ __be32 bar_str_offset;
+ __be32 end_offset;
u8 entry_byte;
u8 reserved[3];
@@ -685,14 +688,14 @@ struct ipr_sdt_entry {
#define IPR_SDT_VALID_ENTRY 0x20
u8 resv;
- u16 priority;
+ __be16 priority;
}__attribute__((packed, aligned (4)));
struct ipr_sdt_header {
- u32 state;
- u32 num_entries;
- u32 num_entries_used;
- u32 dump_size;
+ __be32 state;
+ __be32 num_entries;
+ __be32 num_entries_used;
+ __be32 dump_size;
}__attribute__((packed, aligned (4)));
struct ipr_sdt {
@@ -723,9 +726,7 @@ struct ipr_resource_entry {
u8 add_to_ml:1;
u8 del_from_ml:1;
u8 resetting_device:1;
- u8 tcq_active:1;
- int qdepth;
struct scsi_device *sdev;
struct list_head queue;
};
@@ -779,6 +780,12 @@ struct ipr_chip_cfg_t {
struct ipr_interrupt_offsets regs;
};
+struct ipr_chip_t {
+ u16 vendor;
+ u16 device;
+ const struct ipr_chip_cfg_t *cfg;
+};
+
enum ipr_shutdown_type {
IPR_SHUTDOWN_NORMAL = 0x00,
IPR_SHUTDOWN_PREPARE_FOR_NORMAL = 0x40,
@@ -795,7 +802,7 @@ struct ipr_trace_entry {
#define IPR_TRACE_FINISH 0xff
u16 cmd_index;
- u32 res_handle;
+ __be32 res_handle;
union {
u32 ioasc;
u32 add_data;
@@ -880,15 +887,15 @@ struct ipr_ioa_cfg {
struct list_head hostrcb_free_q;
struct list_head hostrcb_pending_q;
- u32 *host_rrq;
+ __be32 *host_rrq;
dma_addr_t host_rrq_dma;
#define IPR_HRRQ_REQ_RESP_HANDLE_MASK 0xfffffffc
#define IPR_HRRQ_RESP_BIT_SET 0x00000002
#define IPR_HRRQ_TOGGLE_BIT 0x00000001
#define IPR_HRRQ_REQ_RESP_HANDLE_SHIFT 2
- volatile u32 *hrrq_start;
- volatile u32 *hrrq_end;
- volatile u32 *hrrq_curr;
+ volatile __be32 *hrrq_start;
+ volatile __be32 *hrrq_end;
+ volatile __be32 *hrrq_curr;
volatile u32 toggle_bit;
struct ipr_bus_attributes bus_attr[IPR_MAX_NUM_BUSES];
@@ -1033,7 +1040,7 @@ struct ipr_driver_dump {
struct ipr_ioa_dump {
struct ipr_dump_entry_header hdr;
struct ipr_sdt sdt;
- u32 *ioa_data[IPR_MAX_NUM_DUMP_PAGES];
+ __be32 *ioa_data[IPR_MAX_NUM_DUMP_PAGES];
u32 reserved;
u32 next_page_index;
u32 page_offset;
@@ -1057,19 +1064,19 @@ struct ipr_error_table_t {
};
struct ipr_software_inq_lid_info {
- u32 load_id;
- u32 timestamp[3];
+ __be32 load_id;
+ __be32 timestamp[3];
}__attribute__((packed, aligned (4)));
struct ipr_ucode_image_header {
- u32 header_length;
- u32 lid_table_offset;
+ __be32 header_length;
+ __be32 lid_table_offset;
u8 major_release;
u8 card_type;
u8 minor_release[2];
u8 reserved[20];
char eyecatcher[16];
- u32 num_lids;
+ __be32 num_lids;
struct ipr_software_inq_lid_info lid[1];
}__attribute__((packed, aligned (4)));
diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c
index f96c4906693b5..e46096da8db2d 100644
--- a/drivers/scsi/ips.c
+++ b/drivers/scsi/ips.c
@@ -246,6 +246,117 @@ module_param(ips, charp, 0);
#endif
/*
+ * Function prototypes
+ */
+static int ips_detect(Scsi_Host_Template *);
+static int ips_release(struct Scsi_Host *);
+static int ips_eh_abort(Scsi_Cmnd *);
+static int ips_eh_reset(Scsi_Cmnd *);
+static int ips_queue(Scsi_Cmnd *, void (*)(Scsi_Cmnd *));
+static const char *ips_info(struct Scsi_Host *);
+static irqreturn_t do_ipsintr(int, void *, struct pt_regs *);
+static int ips_hainit(ips_ha_t *);
+static int ips_map_status(ips_ha_t *, ips_scb_t *, ips_stat_t *);
+static int ips_send_wait(ips_ha_t *, ips_scb_t *, int, int);
+static int ips_send_cmd(ips_ha_t *, ips_scb_t *);
+static int ips_online(ips_ha_t *, ips_scb_t *);
+static int ips_inquiry(ips_ha_t *, ips_scb_t *);
+static int ips_rdcap(ips_ha_t *, ips_scb_t *);
+static int ips_msense(ips_ha_t *, ips_scb_t *);
+static int ips_reqsen(ips_ha_t *, ips_scb_t *);
+static int ips_deallocatescbs(ips_ha_t *, int);
+static int ips_allocatescbs(ips_ha_t *);
+static int ips_reset_copperhead(ips_ha_t *);
+static int ips_reset_copperhead_memio(ips_ha_t *);
+static int ips_reset_morpheus(ips_ha_t *);
+static int ips_issue_copperhead(ips_ha_t *, ips_scb_t *);
+static int ips_issue_copperhead_memio(ips_ha_t *, ips_scb_t *);
+static int ips_issue_i2o(ips_ha_t *, ips_scb_t *);
+static int ips_issue_i2o_memio(ips_ha_t *, ips_scb_t *);
+static int ips_isintr_copperhead(ips_ha_t *);
+static int ips_isintr_copperhead_memio(ips_ha_t *);
+static int ips_isintr_morpheus(ips_ha_t *);
+static int ips_wait(ips_ha_t *, int, int);
+static int ips_write_driver_status(ips_ha_t *, int);
+static int ips_read_adapter_status(ips_ha_t *, int);
+static int ips_read_subsystem_parameters(ips_ha_t *, int);
+static int ips_read_config(ips_ha_t *, int);
+static int ips_clear_adapter(ips_ha_t *, int);
+static int ips_readwrite_page5(ips_ha_t *, int, int);
+static int ips_init_copperhead(ips_ha_t *);
+static int ips_init_copperhead_memio(ips_ha_t *);
+static int ips_init_morpheus(ips_ha_t *);
+static int ips_isinit_copperhead(ips_ha_t *);
+static int ips_isinit_copperhead_memio(ips_ha_t *);
+static int ips_isinit_morpheus(ips_ha_t *);
+static int ips_erase_bios(ips_ha_t *);
+static int ips_program_bios(ips_ha_t *, char *, uint32_t, uint32_t);
+static int ips_verify_bios(ips_ha_t *, char *, uint32_t, uint32_t);
+static int ips_erase_bios_memio(ips_ha_t *);
+static int ips_program_bios_memio(ips_ha_t *, char *, uint32_t, uint32_t);
+static int ips_verify_bios_memio(ips_ha_t *, char *, uint32_t, uint32_t);
+static int ips_flash_copperhead(ips_ha_t *, ips_passthru_t *, ips_scb_t *);
+static int ips_flash_bios(ips_ha_t *, ips_passthru_t *, ips_scb_t *);
+static int ips_flash_firmware(ips_ha_t *, ips_passthru_t *, ips_scb_t *);
+static void ips_free_flash_copperhead(ips_ha_t * ha);
+static void ips_get_bios_version(ips_ha_t *, int);
+static void ips_identify_controller(ips_ha_t *);
+static void ips_chkstatus(ips_ha_t *, IPS_STATUS *);
+static void ips_enable_int_copperhead(ips_ha_t *);
+static void ips_enable_int_copperhead_memio(ips_ha_t *);
+static void ips_enable_int_morpheus(ips_ha_t *);
+static int ips_intr_copperhead(ips_ha_t *);
+static int ips_intr_morpheus(ips_ha_t *);
+static void ips_next(ips_ha_t *, int);
+static void ipsintr_blocking(ips_ha_t *, struct ips_scb *);
+static void ipsintr_done(ips_ha_t *, struct ips_scb *);
+static void ips_done(ips_ha_t *, ips_scb_t *);
+static void ips_free(ips_ha_t *);
+static void ips_init_scb(ips_ha_t *, ips_scb_t *);
+static void ips_freescb(ips_ha_t *, ips_scb_t *);
+static void ips_setup_funclist(ips_ha_t *);
+static void ips_statinit(ips_ha_t *);
+static void ips_statinit_memio(ips_ha_t *);
+static void ips_fix_ffdc_time(ips_ha_t *, ips_scb_t *, time_t);
+static void ips_ffdc_reset(ips_ha_t *, int);
+static void ips_ffdc_time(ips_ha_t *);
+static uint32_t ips_statupd_copperhead(ips_ha_t *);
+static uint32_t ips_statupd_copperhead_memio(ips_ha_t *);
+static uint32_t ips_statupd_morpheus(ips_ha_t *);
+static ips_scb_t *ips_getscb(ips_ha_t *);
+static void ips_putq_scb_head(ips_scb_queue_t *, ips_scb_t *);
+static void ips_putq_wait_tail(ips_wait_queue_t *, Scsi_Cmnd *);
+static void ips_putq_copp_tail(ips_copp_queue_t *,
+ ips_copp_wait_item_t *);
+static ips_scb_t *ips_removeq_scb_head(ips_scb_queue_t *);
+static ips_scb_t *ips_removeq_scb(ips_scb_queue_t *, ips_scb_t *);
+static Scsi_Cmnd *ips_removeq_wait_head(ips_wait_queue_t *);
+static Scsi_Cmnd *ips_removeq_wait(ips_wait_queue_t *, Scsi_Cmnd *);
+static ips_copp_wait_item_t *ips_removeq_copp(ips_copp_queue_t *,
+ ips_copp_wait_item_t *);
+static ips_copp_wait_item_t *ips_removeq_copp_head(ips_copp_queue_t *);
+
+static int ips_is_passthru(Scsi_Cmnd *);
+static int ips_make_passthru(ips_ha_t *, Scsi_Cmnd *, ips_scb_t *, int);
+static int ips_usrcmd(ips_ha_t *, ips_passthru_t *, ips_scb_t *);
+static void ips_cleanup_passthru(ips_ha_t *, ips_scb_t *);
+static void ips_scmd_buf_write(Scsi_Cmnd * scmd, void *data,
+ unsigned int count);
+static void ips_scmd_buf_read(Scsi_Cmnd * scmd, void *data, unsigned int count);
+
+static int ips_proc_info(struct Scsi_Host *, char *, char **, off_t, int, int);
+static int ips_host_info(ips_ha_t *, char *, off_t, int);
+static void copy_mem_info(IPS_INFOSTR *, char *, int);
+static int copy_info(IPS_INFOSTR *, char *, ...);
+static int ips_get_version_info(ips_ha_t * ha, dma_addr_t, int intr);
+static void ips_version_check(ips_ha_t * ha, int intr);
+static int ips_abort_init(ips_ha_t * ha, int index);
+static int ips_init_phase2(int index);
+
+static int ips_init_phase1(struct pci_dev *pci_dev, int *indexPtr);
+static int ips_register_scsi(int index);
+
+/*
* global variables
*/
static const char ips_name[] = "ips";
@@ -293,7 +404,7 @@ static Scsi_Host_Template ips_driver_template = {
#endif
};
-IPS_DEFINE_COMPAT_TABLE( Compatable ); /* Version Compatability Table */
+static IPS_DEFINE_COMPAT_TABLE( Compatable ); /* Version Compatability Table */
/* This table describes all ServeRAID Adapters */
@@ -311,7 +422,7 @@ static char ips_hot_plug_name[] = "ips";
static int __devinit ips_insert_device(struct pci_dev *pci_dev, const struct pci_device_id *ent);
static void __devexit ips_remove_device(struct pci_dev *pci_dev);
-struct pci_driver ips_pci_driver = {
+static struct pci_driver ips_pci_driver = {
.name = ips_hot_plug_name,
.id_table = ips_pci_table,
.probe = ips_insert_device,
@@ -408,119 +519,6 @@ static char ips_command_direction[] = {
IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK, IPS_DATA_UNK
};
-/*
- * Function prototypes
- */
-int ips_detect(Scsi_Host_Template *);
-int ips_release(struct Scsi_Host *);
-int ips_eh_abort(Scsi_Cmnd *);
-int ips_eh_reset(Scsi_Cmnd *);
-int ips_queue(Scsi_Cmnd *, void (*)(Scsi_Cmnd *));
-const char *ips_info(struct Scsi_Host *);
-irqreturn_t do_ipsintr(int, void *, struct pt_regs *);
-static int ips_hainit(ips_ha_t *);
-static int ips_map_status(ips_ha_t *, ips_scb_t *, ips_stat_t *);
-static int ips_send_wait(ips_ha_t *, ips_scb_t *, int, int);
-static int ips_send_cmd(ips_ha_t *, ips_scb_t *);
-static int ips_online(ips_ha_t *, ips_scb_t *);
-static int ips_inquiry(ips_ha_t *, ips_scb_t *);
-static int ips_rdcap(ips_ha_t *, ips_scb_t *);
-static int ips_msense(ips_ha_t *, ips_scb_t *);
-static int ips_reqsen(ips_ha_t *, ips_scb_t *);
-static int ips_deallocatescbs(ips_ha_t *, int);
-static int ips_allocatescbs(ips_ha_t *);
-static int ips_reset_copperhead(ips_ha_t *);
-static int ips_reset_copperhead_memio(ips_ha_t *);
-static int ips_reset_morpheus(ips_ha_t *);
-static int ips_issue_copperhead(ips_ha_t *, ips_scb_t *);
-static int ips_issue_copperhead_memio(ips_ha_t *, ips_scb_t *);
-static int ips_issue_i2o(ips_ha_t *, ips_scb_t *);
-static int ips_issue_i2o_memio(ips_ha_t *, ips_scb_t *);
-static int ips_isintr_copperhead(ips_ha_t *);
-static int ips_isintr_copperhead_memio(ips_ha_t *);
-static int ips_isintr_morpheus(ips_ha_t *);
-static int ips_wait(ips_ha_t *, int, int);
-static int ips_write_driver_status(ips_ha_t *, int);
-static int ips_read_adapter_status(ips_ha_t *, int);
-static int ips_read_subsystem_parameters(ips_ha_t *, int);
-static int ips_read_config(ips_ha_t *, int);
-static int ips_clear_adapter(ips_ha_t *, int);
-static int ips_readwrite_page5(ips_ha_t *, int, int);
-static int ips_init_copperhead(ips_ha_t *);
-static int ips_init_copperhead_memio(ips_ha_t *);
-static int ips_init_morpheus(ips_ha_t *);
-static int ips_isinit_copperhead(ips_ha_t *);
-static int ips_isinit_copperhead_memio(ips_ha_t *);
-static int ips_isinit_morpheus(ips_ha_t *);
-static int ips_erase_bios(ips_ha_t *);
-static int ips_program_bios(ips_ha_t *, char *, uint32_t, uint32_t);
-static int ips_verify_bios(ips_ha_t *, char *, uint32_t, uint32_t);
-static int ips_erase_bios_memio(ips_ha_t *);
-static int ips_program_bios_memio(ips_ha_t *, char *, uint32_t, uint32_t);
-static int ips_verify_bios_memio(ips_ha_t *, char *, uint32_t, uint32_t);
-static int ips_flash_copperhead(ips_ha_t *, ips_passthru_t *, ips_scb_t *);
-static int ips_flash_bios(ips_ha_t *, ips_passthru_t *, ips_scb_t *);
-static int ips_flash_firmware(ips_ha_t *, ips_passthru_t *, ips_scb_t *);
-static void ips_free_flash_copperhead(ips_ha_t * ha);
-static void ips_get_bios_version(ips_ha_t *, int);
-static void ips_identify_controller(ips_ha_t *);
-static void ips_chkstatus(ips_ha_t *, IPS_STATUS *);
-static void ips_enable_int_copperhead(ips_ha_t *);
-static void ips_enable_int_copperhead_memio(ips_ha_t *);
-static void ips_enable_int_morpheus(ips_ha_t *);
-static int ips_intr_copperhead(ips_ha_t *);
-static int ips_intr_morpheus(ips_ha_t *);
-static void ips_next(ips_ha_t *, int);
-static void ipsintr_blocking(ips_ha_t *, struct ips_scb *);
-static void ipsintr_done(ips_ha_t *, struct ips_scb *);
-static void ips_done(ips_ha_t *, ips_scb_t *);
-static void ips_free(ips_ha_t *);
-static void ips_init_scb(ips_ha_t *, ips_scb_t *);
-static void ips_freescb(ips_ha_t *, ips_scb_t *);
-static void ips_setup_funclist(ips_ha_t *);
-static void ips_statinit(ips_ha_t *);
-static void ips_statinit_memio(ips_ha_t *);
-static void ips_fix_ffdc_time(ips_ha_t *, ips_scb_t *, time_t);
-static void ips_ffdc_reset(ips_ha_t *, int);
-static void ips_ffdc_time(ips_ha_t *);
-static uint32_t ips_statupd_copperhead(ips_ha_t *);
-static uint32_t ips_statupd_copperhead_memio(ips_ha_t *);
-static uint32_t ips_statupd_morpheus(ips_ha_t *);
-static ips_scb_t *ips_getscb(ips_ha_t *);
-static void ips_putq_scb_head(ips_scb_queue_t *, ips_scb_t *);
-static void ips_putq_wait_tail(ips_wait_queue_t *, Scsi_Cmnd *);
-static void ips_putq_copp_tail(ips_copp_queue_t *,
- ips_copp_wait_item_t *);
-static ips_scb_t *ips_removeq_scb_head(ips_scb_queue_t *);
-static ips_scb_t *ips_removeq_scb(ips_scb_queue_t *, ips_scb_t *);
-static Scsi_Cmnd *ips_removeq_wait_head(ips_wait_queue_t *);
-static Scsi_Cmnd *ips_removeq_wait(ips_wait_queue_t *, Scsi_Cmnd *);
-static ips_copp_wait_item_t *ips_removeq_copp(ips_copp_queue_t *,
- ips_copp_wait_item_t *);
-static ips_copp_wait_item_t *ips_removeq_copp_head(ips_copp_queue_t *);
-
-static int ips_is_passthru(Scsi_Cmnd *);
-static int ips_make_passthru(ips_ha_t *, Scsi_Cmnd *, ips_scb_t *, int);
-static int ips_usrcmd(ips_ha_t *, ips_passthru_t *, ips_scb_t *);
-static void ips_cleanup_passthru(ips_ha_t *, ips_scb_t *);
-static void ips_scmd_buf_write(Scsi_Cmnd * scmd, void *data,
- unsigned int count);
-static void ips_scmd_buf_read(Scsi_Cmnd * scmd, void *data, unsigned int count);
-
-int ips_proc_info(struct Scsi_Host *, char *, char **, off_t, int, int);
-static int ips_host_info(ips_ha_t *, char *, off_t, int);
-static void copy_mem_info(IPS_INFOSTR *, char *, int);
-static int copy_info(IPS_INFOSTR *, char *, ...);
-static int ips_get_version_info(ips_ha_t * ha, dma_addr_t, int intr);
-static void ips_version_check(ips_ha_t * ha, int intr);
-static int ips_abort_init(ips_ha_t * ha, int index);
-static int ips_init_phase2(int index);
-
-static int ips_init_phase1(struct pci_dev *pci_dev, int *indexPtr);
-static int ips_register_scsi(int index);
-/*--------------------------------------------------------------------------*/
-/* Exported Functions */
-/*--------------------------------------------------------------------------*/
/****************************************************************************/
/* */
@@ -589,7 +587,7 @@ __setup("ips=", ips_setup);
/* NOTE: this routine is called under the io_request_lock spinlock */
/* */
/****************************************************************************/
-int
+static int
ips_detect(Scsi_Host_Template * SHT)
{
int i;
@@ -678,7 +676,7 @@ ips_setup_funclist(ips_ha_t * ha)
/* Remove a driver */
/* */
/****************************************************************************/
-int
+static int
ips_release(struct Scsi_Host *sh)
{
ips_scb_t *scb;
@@ -874,7 +872,7 @@ ips_eh_abort(Scsi_Cmnd * SC)
/* NOTE: this routine is called under the io_request_lock spinlock */
/* */
/****************************************************************************/
-int
+static int
ips_eh_reset(Scsi_Cmnd * SC)
{
int ret;
@@ -1074,7 +1072,7 @@ ips_eh_reset(Scsi_Cmnd * SC)
/* Linux obtains io_request_lock before calling this function */
/* */
/****************************************************************************/
-int
+static int
ips_queue(Scsi_Cmnd * SC, void (*done) (Scsi_Cmnd *))
{
ips_ha_t *ha;
@@ -1297,7 +1295,7 @@ ips_select_queue_depth(struct Scsi_Host *host, Scsi_Device * scsi_devs)
/* Set queue depths on devices once scan is complete */
/* */
/****************************************************************************/
-int
+static int
ips_slave_configure(Scsi_Device * SDptr)
{
ips_ha_t *ha;
@@ -1323,7 +1321,7 @@ ips_slave_configure(Scsi_Device * SDptr)
/* Wrapper for the interrupt handler */
/* */
/****************************************************************************/
-irqreturn_t
+static irqreturn_t
do_ipsintr(int irq, void *dev_id, struct pt_regs * regs)
{
ips_ha_t *ha;
@@ -1502,7 +1500,7 @@ ips_intr_morpheus(ips_ha_t * ha)
/* Return info about the driver */
/* */
/****************************************************************************/
-const char *
+static const char *
ips_info(struct Scsi_Host *SH)
{
static char buffer[256];
@@ -1540,7 +1538,7 @@ ips_info(struct Scsi_Host *SH)
/* The passthru interface for the driver */
/* */
/****************************************************************************/
-int
+static int
ips_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
int length, int func)
{
diff --git a/drivers/scsi/ips.h b/drivers/scsi/ips.h
index d1553a0a30967..906a76158fa95 100644
--- a/drivers/scsi/ips.h
+++ b/drivers/scsi/ips.h
@@ -53,14 +53,6 @@
#include <asm/uaccess.h>
#include <asm/io.h>
- /* Prototypes */
- extern int ips_detect(Scsi_Host_Template *);
- extern int ips_release(struct Scsi_Host *);
- extern int ips_eh_abort(Scsi_Cmnd *);
- extern int ips_eh_reset(Scsi_Cmnd *);
- extern int ips_queue(Scsi_Cmnd *, void (*) (Scsi_Cmnd *));
- extern const char * ips_info(struct Scsi_Host *);
-
/*
* Some handy macros
*/
@@ -457,10 +449,10 @@
static void ips_select_queue_depth(struct Scsi_Host *, Scsi_Device *);
static int ips_biosparam(Disk *disk, kdev_t dev, int geom[]);
#else
- int ips_proc_info(struct Scsi_Host *, char *, char **, off_t, int, int);
+ static int ips_proc_info(struct Scsi_Host *, char *, char **, off_t, int, int);
static int ips_biosparam(struct scsi_device *sdev, struct block_device *bdev,
sector_t capacity, int geom[]);
- int ips_slave_configure(Scsi_Device *SDptr);
+ static int ips_slave_configure(Scsi_Device *SDptr);
#endif
/*
diff --git a/drivers/scsi/lasi700.c b/drivers/scsi/lasi700.c
index 25729f3f81648..29f250c80b98f 100644
--- a/drivers/scsi/lasi700.c
+++ b/drivers/scsi/lasi700.c
@@ -111,8 +111,8 @@ lasi700_probe(struct parisc_device *dev)
memset(hostdata, 0, sizeof(struct NCR_700_Host_Parameters));
hostdata->dev = &dev->dev;
- dma_set_mask(&dev->dev, 0xffffffffUL);
- hostdata->base = base;
+ dma_set_mask(&dev->dev, DMA_32BIT_MASK);
+ hostdata->base = ioremap(base, 0x100);
hostdata->differential = 0;
if (dev->id.sversion == LASI_700_SVERSION) {
@@ -127,17 +127,25 @@ lasi700_probe(struct parisc_device *dev)
NCR_700_set_mem_mapped(hostdata);
- host = NCR_700_detect(&lasi700_template, hostdata, &dev->dev,
- dev->irq, 7);
+ host = NCR_700_detect(&lasi700_template, hostdata, &dev->dev);
if (!host)
goto out_kfree;
+ host->this_id = 7;
+ host->irq = dev->irq;
+ if(request_irq(dev->irq, NCR_700_intr, SA_SHIRQ, "lasi700", host)) {
+ printk(KERN_ERR "lasi700: request_irq failed!\n");
+ goto out_put_host;
+ }
dev_set_drvdata(&dev->dev, host);
scsi_scan_host(host);
return 0;
+ out_put_host:
+ scsi_host_put(host);
out_kfree:
+ iounmap(hostdata->base);
kfree(hostdata);
return -ENODEV;
}
@@ -152,6 +160,7 @@ lasi700_driver_remove(struct parisc_device *dev)
scsi_remove_host(host);
NCR_700_release(host);
free_irq(host->irq, host);
+ iounmap(hostdata->base);
kfree(hostdata);
return 0;
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index b1c06ab1df949..0b5d3a5b7edab 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -377,7 +377,7 @@ void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
}
/**
- * ata_check_status - Read device status reg & clear interrupt
+ * ata_check_status_pio - Read device status reg & clear interrupt
* @ap: port where the device is
*
* Reads ATA taskfile status register for currently-selected device
@@ -415,6 +415,27 @@ u8 ata_check_status(struct ata_port *ap)
return ata_check_status_pio(ap);
}
+u8 ata_altstatus(struct ata_port *ap)
+{
+ if (ap->ops->check_altstatus)
+ return ap->ops->check_altstatus(ap);
+
+ if (ap->flags & ATA_FLAG_MMIO)
+ return readb((void __iomem *)ap->ioaddr.altstatus_addr);
+ return inb(ap->ioaddr.altstatus_addr);
+}
+
+u8 ata_chk_err(struct ata_port *ap)
+{
+ if (ap->ops->check_err)
+ return ap->ops->check_err(ap);
+
+ if (ap->flags & ATA_FLAG_MMIO) {
+ return readb((void __iomem *) ap->ioaddr.error_addr);
+ }
+ return inb(ap->ioaddr.error_addr);
+}
+
/**
* ata_tf_to_fis - Convert ATA taskfile to SATA FIS structure
* @tf: Taskfile to convert
@@ -1161,7 +1182,6 @@ err_out_nosup:
printk(KERN_WARNING "ata%u: dev %u not supported, ignoring\n",
ap->id, device);
err_out:
- ata_irq_on(ap); /* re-enable interrupts */
dev->class++; /* converts ATA_DEV_xxx into ATA_DEV_xxx_UNSUP */
DPRINTK("EXIT, err\n");
}
@@ -1669,7 +1689,8 @@ void ata_bus_reset(struct ata_port *ap)
ata_dev_try_classify(ap, 1);
/* re-enable interrupts */
- ata_irq_on(ap);
+ if (ap->ioaddr.ctl_addr) /* FIXME: hack. create a hook instead */
+ ata_irq_on(ap);
/* is double-select really necessary? */
if (ap->device[1].class != ATA_DEV_NONE)
@@ -2601,10 +2622,10 @@ static void ata_qc_timeout(struct ata_queued_cmd *qc)
case ATA_PROT_DMA:
case ATA_PROT_ATAPI_DMA:
- host_stat = ata_bmdma_status(ap);
+ host_stat = ap->ops->bmdma_status(ap);
/* before we do anything else, clear DMA-Start bit */
- ata_bmdma_stop(ap);
+ ap->ops->bmdma_stop(ap);
/* fall through */
@@ -2613,7 +2634,7 @@ static void ata_qc_timeout(struct ata_queued_cmd *qc)
drv_stat = ata_chk_status(ap);
/* ack bmdma irq events */
- ata_bmdma_ack_irq(ap);
+ ap->ops->irq_clear(ap);
printk(KERN_ERR "ata%u: command 0x%x timeout, stat 0x%x host_stat 0x%x\n",
ap->id, qc->tf.command, drv_stat, host_stat);
@@ -2752,6 +2773,24 @@ static void __ata_qc_complete(struct ata_queued_cmd *qc)
}
/**
+ * ata_qc_free - free unused ata_queued_cmd
+ * @qc: Command to complete
+ *
+ * Designed to free unused ata_queued_cmd object
+ * in case something prevents using it.
+ *
+ * LOCKING:
+ *
+ */
+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);
+}
+
+/**
* ata_qc_complete - Complete an active ATA command
* @qc: Command to complete
* @drv_stat: ATA status register contents
@@ -3042,7 +3081,43 @@ void ata_bmdma_setup(struct ata_queued_cmd *qc)
void ata_bmdma_irq_clear(struct ata_port *ap)
{
- ata_bmdma_ack_irq(ap);
+ if (ap->flags & ATA_FLAG_MMIO) {
+ void __iomem *mmio = ((void __iomem *) ap->ioaddr.bmdma_addr) + ATA_DMA_STATUS;
+ writeb(readb(mmio), mmio);
+ } else {
+ unsigned long addr = ap->ioaddr.bmdma_addr + ATA_DMA_STATUS;
+ outb(inb(addr), addr);
+ }
+
+}
+
+u8 ata_bmdma_status(struct ata_port *ap)
+{
+ u8 host_stat;
+ if (ap->flags & ATA_FLAG_MMIO) {
+ void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
+ host_stat = readb(mmio + ATA_DMA_STATUS);
+ } else
+ host_stat = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
+ return host_stat;
+}
+
+void ata_bmdma_stop(struct ata_port *ap)
+{
+ if (ap->flags & ATA_FLAG_MMIO) {
+ void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
+
+ /* clear start/stop bit */
+ writeb(readb(mmio + ATA_DMA_CMD) & ~ATA_DMA_START,
+ mmio + ATA_DMA_CMD);
+ } else {
+ /* clear start/stop bit */
+ outb(inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD) & ~ATA_DMA_START,
+ ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
+ }
+
+ /* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */
+ ata_altstatus(ap); /* dummy read */
}
/**
@@ -3072,7 +3147,7 @@ inline unsigned int ata_host_intr (struct ata_port *ap,
case ATA_PROT_ATAPI_DMA:
case ATA_PROT_ATAPI:
/* check status of DMA engine */
- host_stat = ata_bmdma_status(ap);
+ host_stat = ap->ops->bmdma_status(ap);
VPRINTK("ata%u: host_stat 0x%X\n", ap->id, host_stat);
/* if it's not our irq... */
@@ -3080,7 +3155,7 @@ inline unsigned int ata_host_intr (struct ata_port *ap,
goto idle_irq;
/* before we do anything else, clear DMA-Start bit */
- ata_bmdma_stop(ap);
+ ap->ops->bmdma_stop(ap);
/* fall through */
@@ -3099,7 +3174,7 @@ inline unsigned int ata_host_intr (struct ata_port *ap,
ap->id, qc->tf.protocol, status);
/* ack bmdma irq events */
- ata_bmdma_ack_irq(ap);
+ ap->ops->irq_clear(ap);
/* complete taskfile transaction */
ata_qc_complete(qc, status);
@@ -3656,6 +3731,7 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
struct ata_port_info *port[2];
u8 tmp8, mask;
unsigned int legacy_mode = 0;
+ int disable_dev_on_err = 1;
int rc;
DPRINTK("ENTER\n");
@@ -3686,8 +3762,10 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
return rc;
rc = pci_request_regions(pdev, DRV_NAME);
- if (rc)
+ if (rc) {
+ disable_dev_on_err = 0;
goto err_out;
+ }
if (legacy_mode) {
if (!request_region(0x1f0, 8, "libata")) {
@@ -3697,8 +3775,10 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
conflict = ____request_resource(&ioport_resource, &res);
if (!strcmp(conflict->name, "libata"))
legacy_mode |= (1 << 0);
- else
+ else {
+ disable_dev_on_err = 0;
printk(KERN_WARNING "ata: 0x1f0 IDE port busy\n");
+ }
} else
legacy_mode |= (1 << 0);
@@ -3709,8 +3789,10 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
conflict = ____request_resource(&ioport_resource, &res);
if (!strcmp(conflict->name, "libata"))
legacy_mode |= (1 << 1);
- else
+ else {
+ disable_dev_on_err = 0;
printk(KERN_WARNING "ata: 0x170 IDE port busy\n");
+ }
} else
legacy_mode |= (1 << 1);
}
@@ -3760,7 +3842,8 @@ err_out_regions:
release_region(0x170, 8);
pci_release_regions(pdev);
err_out:
- pci_disable_device(pdev);
+ if (disable_dev_on_err)
+ pci_disable_device(pdev);
return rc;
}
@@ -3801,26 +3884,22 @@ void ata_pci_remove_one (struct pci_dev *pdev)
ap = host_set->ports[i];
ata_scsi_release(ap->host);
- scsi_host_put(ap->host);
- }
-
- pci_release_regions(pdev);
-
- for (i = 0; i < host_set->n_ports; i++) {
- struct ata_ioports *ioaddr;
-
- ap = host_set->ports[i];
- ioaddr = &ap->ioaddr;
if ((ap->flags & ATA_FLAG_NO_LEGACY) == 0) {
+ struct ata_ioports *ioaddr = &ap->ioaddr;
+
if (ioaddr->cmd_addr == 0x1f0)
release_region(0x1f0, 8);
else if (ioaddr->cmd_addr == 0x170)
release_region(0x170, 8);
}
+
+ scsi_host_put(ap->host);
}
kfree(host_set);
+
+ pci_release_regions(pdev);
pci_disable_device(pdev);
dev_set_drvdata(dev, NULL);
}
@@ -3910,6 +3989,8 @@ EXPORT_SYMBOL_GPL(ata_std_dev_select);
EXPORT_SYMBOL_GPL(ata_tf_to_fis);
EXPORT_SYMBOL_GPL(ata_tf_from_fis);
EXPORT_SYMBOL_GPL(ata_check_status);
+EXPORT_SYMBOL_GPL(ata_altstatus);
+EXPORT_SYMBOL_GPL(ata_chk_err);
EXPORT_SYMBOL_GPL(ata_exec_command);
EXPORT_SYMBOL_GPL(ata_port_start);
EXPORT_SYMBOL_GPL(ata_port_stop);
@@ -3918,6 +3999,8 @@ EXPORT_SYMBOL_GPL(ata_qc_prep);
EXPORT_SYMBOL_GPL(ata_bmdma_setup);
EXPORT_SYMBOL_GPL(ata_bmdma_start);
EXPORT_SYMBOL_GPL(ata_bmdma_irq_clear);
+EXPORT_SYMBOL_GPL(ata_bmdma_status);
+EXPORT_SYMBOL_GPL(ata_bmdma_stop);
EXPORT_SYMBOL_GPL(ata_port_probe);
EXPORT_SYMBOL_GPL(sata_phy_reset);
EXPORT_SYMBOL_GPL(__sata_phy_reset);
diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c
index 76acb587391fa..4e5e54a1564b5 100644
--- a/drivers/scsi/libata-scsi.c
+++ b/drivers/scsi/libata-scsi.c
@@ -701,6 +701,7 @@ static void ata_scsi_translate(struct ata_port *ap, struct ata_device *dev,
return;
err_out:
+ ata_qc_free(qc);
ata_bad_cdb(cmd, done);
DPRINTK("EXIT - badcmd\n");
}
@@ -1037,7 +1038,12 @@ static unsigned int ata_msense_caching(u16 *id, u8 **ptr_io,
static unsigned int ata_msense_ctl_mode(u8 **ptr_io, const u8 *last)
{
- const u8 page[] = {0xa, 0xa, 2, 0, 0, 0, 0, 0, 0xff, 0xff, 0, 30};
+ const u8 page[] = {0xa, 0xa, 6, 0, 0, 0, 0, 0, 0xff, 0xff, 0, 30};
+
+ /* byte 2: set the descriptor format sense data bit (bit 2)
+ * since we need to support returning this format for SAT
+ * commands and any SCSI commands against a 48b LBA device.
+ */
ata_msense_push(ptr_io, last, page, sizeof(page));
return sizeof(page);
diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h
index bd67a21becf55..6518226b8f87f 100644
--- a/drivers/scsi/libata.h
+++ b/drivers/scsi/libata.h
@@ -37,6 +37,7 @@ struct ata_scsi_args {
/* libata-core.c */
extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
struct ata_device *dev);
+extern void ata_qc_free(struct ata_queued_cmd *qc);
extern int ata_qc_issue(struct ata_queued_cmd *qc);
extern int ata_check_atapi_dma(struct ata_queued_cmd *qc);
extern void ata_dev_select(struct ata_port *ap, unsigned int device,
diff --git a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c
index ef6a0c8077404..d5fd17ef74dbb 100644
--- a/drivers/scsi/mac_scsi.c
+++ b/drivers/scsi/mac_scsi.c
@@ -302,7 +302,7 @@ int macscsi_detect(Scsi_Host_Template * tpnt)
if (instance->irq != SCSI_IRQ_NONE)
if (request_irq(instance->irq, NCR5380_intr, IRQ_FLG_SLOW,
- "ncr5380", NCR5380_intr)) {
+ "ncr5380", instance)) {
printk(KERN_WARNING "scsi%d: IRQ%d not free, interrupts disabled\n",
instance->host_no, instance->irq);
instance->irq = SCSI_IRQ_NONE;
diff --git a/drivers/scsi/megaraid/megaraid_mm.c b/drivers/scsi/megaraid/megaraid_mm.c
index e12024dda32ee..9f1b550713ecd 100644
--- a/drivers/scsi/megaraid/megaraid_mm.c
+++ b/drivers/scsi/megaraid/megaraid_mm.c
@@ -16,6 +16,7 @@
*/
#include "megaraid_mm.h"
+#include <linux/smp_lock.h>
// Entry points for char node driver
@@ -43,8 +44,7 @@ static void mraid_mm_free_adp_resources(mraid_mmadp_t *);
static void mraid_mm_teardown_dma_pools(mraid_mmadp_t *);
#ifdef CONFIG_COMPAT
-static int mraid_mm_compat_ioctl(unsigned int, unsigned int, unsigned long,
- struct file *);
+static long mraid_mm_compat_ioctl(struct file *, unsigned int, unsigned long);
#endif
MODULE_AUTHOR("LSI Logic Corporation");
@@ -71,6 +71,9 @@ static wait_queue_head_t wait_q;
static struct file_operations lsi_fops = {
.open = mraid_mm_open,
.ioctl = mraid_mm_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = mraid_mm_compat_ioctl,
+#endif
.owner = THIS_MODULE,
};
@@ -1215,8 +1218,6 @@ mraid_mm_init(void)
INIT_LIST_HEAD(&adapters_list_g);
- register_ioctl32_conversion(MEGAIOCCMD, mraid_mm_compat_ioctl);
-
return 0;
}
@@ -1225,13 +1226,15 @@ mraid_mm_init(void)
* mraid_mm_compat_ioctl : 32bit to 64bit ioctl conversion routine
*/
#ifdef CONFIG_COMPAT
-static int
-mraid_mm_compat_ioctl(unsigned int fd, unsigned int cmd,
- unsigned long arg, struct file *filep)
+static long
+mraid_mm_compat_ioctl(struct file *filep, unsigned int cmd,
+ unsigned long arg)
{
- struct inode *inode = filep->f_dentry->d_inode;
-
- return mraid_mm_ioctl(inode, filep, cmd, arg);
+ int err;
+ lock_kernel();
+ err = mraid_mm_ioctl(NULL, filep, cmd, arg);
+ unlock_kernel();
+ return err;
}
#endif
@@ -1244,7 +1247,6 @@ mraid_mm_exit(void)
con_log(CL_DLEVEL1 , ("exiting common mod\n"));
unregister_chrdev(majorno, "megadev");
- unregister_ioctl32_conversion(MEGAIOCCMD);
}
module_init(mraid_mm_init);
diff --git a/drivers/scsi/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c
index 9b91b2efe4d2b..7ae13236788ec 100644
--- a/drivers/scsi/ncr53c8xx.c
+++ b/drivers/scsi/ncr53c8xx.c
@@ -86,7 +86,7 @@
*/
/* Name and version of the driver */
-#define SCSI_NCR_DRIVER_NAME "ncr53c8xx-3.4.3f"
+#define SCSI_NCR_DRIVER_NAME "ncr53c8xx-3.4.3g"
#define SCSI_NCR_DEBUG_FLAGS (0)
@@ -1219,7 +1219,7 @@ static struct lcb * ncr_alloc_lcb (struct ncb *np, u_char tn, u_char ln);
static struct lcb * ncr_setup_lcb (struct ncb *np, struct scsi_device *sdev);
static void ncr_getclock (struct ncb *np, int mult);
static void ncr_selectclock (struct ncb *np, u_char scntl3);
-static struct ccb *ncr_get_ccb (struct ncb *np, u_char tn, u_char ln);
+static struct ccb *ncr_get_ccb (struct ncb *np, struct scsi_cmnd *cmd);
static void ncr_chip_reset (struct ncb *np, int delay);
static void ncr_init (struct ncb *np, int reset, char * msg, u_long code);
static int ncr_int_sbmc (struct ncb *np);
@@ -1238,8 +1238,6 @@ static void ncr_getsync (struct ncb *np, u_char sfac, u_char *fakp, u_char *scnt
static void ncr_setsync (struct ncb *np, struct ccb *cp, u_char scntl3, u_char sxfer);
static void ncr_setup_tags (struct ncb *np, struct scsi_device *sdev);
static void ncr_setwide (struct ncb *np, struct ccb *cp, u_char wide, u_char ack);
-static int ncr_show_msg (u_char * msg);
-static void ncr_print_msg (struct ccb *cp, char *label, u_char *msg);
static int ncr_snooptest (struct ncb *np);
static void ncr_timeout (struct ncb *np);
static void ncr_wakeup (struct ncb *np, u_long code);
@@ -2746,7 +2744,7 @@ void __init ncr_script_fill (struct script * scr, struct scripth * scrh)
for (i=0; i<MAX_START; i++) {
*p++ =SCR_CALL;
*p++ =PADDR (idle);
- };
+ }
BUG_ON((u_long)p != (u_long)&scrh->tryloop + sizeof (scrh->tryloop));
@@ -2771,7 +2769,7 @@ void __init ncr_script_fill (struct script * scr, struct scripth * scrh)
*p++ =PADDR (dispatch);
*p++ =SCR_MOVE_TBL ^ SCR_DATA_IN;
*p++ =offsetof (struct dsb, data[i]);
- };
+ }
BUG_ON((u_long)p != (u_long)&scrh->hdata_in + sizeof (scrh->hdata_in));
@@ -2781,7 +2779,7 @@ void __init ncr_script_fill (struct script * scr, struct scripth * scrh)
*p++ =PADDR (dispatch);
*p++ =SCR_MOVE_TBL ^ SCR_DATA_IN;
*p++ =offsetof (struct dsb, data[i]);
- };
+ }
BUG_ON((u_long)p != (u_long)&scr->data_in + sizeof (scr->data_in));
@@ -2791,7 +2789,7 @@ void __init ncr_script_fill (struct script * scr, struct scripth * scrh)
*p++ =PADDR (dispatch);
*p++ =SCR_MOVE_TBL ^ SCR_DATA_OUT;
*p++ =offsetof (struct dsb, data[i]);
- };
+ }
BUG_ON((u_long)p != (u_long)&scrh->hdata_out + sizeof (scrh->hdata_out));
@@ -2801,7 +2799,7 @@ void __init ncr_script_fill (struct script * scr, struct scripth * scrh)
*p++ =PADDR (dispatch);
*p++ =SCR_MOVE_TBL ^ SCR_DATA_OUT;
*p++ =offsetof (struct dsb, data[i]);
- };
+ }
BUG_ON((u_long) p != (u_long)&scr->data_out + sizeof (scr->data_out));
}
@@ -2842,7 +2840,7 @@ ncr_script_copy_and_bind (struct ncb *np, ncrcmd *src, ncrcmd *dst, int len)
printk (KERN_ERR "%s: ERROR0 IN SCRIPT at %d.\n",
ncr_name(np), (int) (src-start-1));
mdelay(1000);
- };
+ }
if (DEBUG_FLAGS & DEBUG_SCRIPT)
printk (KERN_DEBUG "%p: <%x>\n",
@@ -2911,7 +2909,7 @@ ncr_script_copy_and_bind (struct ncb *np, ncrcmd *src, ncrcmd *dst, int len)
default:
relocs = 0;
break;
- };
+ }
if (relocs) {
while (relocs--) {
@@ -2958,7 +2956,7 @@ ncr_script_copy_and_bind (struct ncb *np, ncrcmd *src, ncrcmd *dst, int len)
} else
*dst++ = cpu_to_scr(*src++);
- };
+ }
}
/*
@@ -2969,25 +2967,25 @@ struct host_data {
struct ncb *ncb;
};
-/*
-** Print something which allows to retrieve the controller type, unit,
-** target, lun concerned by a kernel message.
-*/
+#define PRINT_ADDR(cmd, arg...) dev_info(&cmd->device->sdev_gendev , ## arg)
-static void PRINT_TARGET(struct ncb *np, int target)
+static void ncr_print_msg(struct ccb *cp, char *label, u_char *msg)
{
- printk(KERN_INFO "%s-<%d,*>: ", ncr_name(np), target);
-}
+ int i;
+ PRINT_ADDR(cp->cmd, "%s: ", label);
-static void PRINT_LUN(struct ncb *np, int target, int lun)
-{
- printk(KERN_INFO "%s-<%d,%d>: ", ncr_name(np), target, lun);
-}
+ 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]);
+ }
-static void PRINT_ADDR(struct scsi_cmnd *cmd)
-{
- struct host_data *host_data = (struct host_data *) cmd->device->host->hostdata;
- PRINT_LUN(host_data->ncb, cmd->device->id, cmd->device->lun);
+ printk(".\n");
}
/*==========================================================
@@ -3280,6 +3278,7 @@ static void __init ncr_prepare_setting(struct ncb *np)
tp->usrsync = driver_setup.default_sync;
tp->usrwide = driver_setup.max_wide;
tp->usrtags = MAX_TAGS;
+ tp->period = 0xffff;
if (!driver_setup.disconnection)
np->target[i].usrflag = UF_NODISC;
}
@@ -3369,34 +3368,23 @@ static int ncr_prepare_nego(struct ncb *np, struct ccb *cp, u_char *msgptr)
int nego = 0;
struct scsi_target *starget = tp->starget;
- if (likely(starget)) {
-
- /*
- ** negotiate wide transfers ?
- */
-
- if (!tp->widedone) {
- if (spi_support_wide(starget)) {
- nego = NS_WIDE;
- } else
- tp->widedone=1;
-
- };
-
- /*
- ** negotiate synchronous transfers?
- */
+ /* negotiate wide transfers ? */
+ if (!tp->widedone) {
+ if (spi_support_wide(starget)) {
+ nego = NS_WIDE;
+ } else
+ tp->widedone=1;
+ }
- if (!nego && !tp->period) {
- if (spi_support_sync(starget)) {
- nego = NS_SYNC;
- } else {
- tp->period =0xffff;
- PRINT_TARGET(np, cp->target);
- printk ("target did not report SYNC.\n");
- };
- };
- };
+ /* negotiate synchronous transfers? */
+ if (!nego && !tp->period) {
+ if (spi_support_sync(starget)) {
+ nego = NS_SYNC;
+ } else {
+ tp->period =0xffff;
+ dev_info(&starget->dev, "target did not report SYNC.\n");
+ }
+ }
switch (nego) {
case NS_SYNC:
@@ -3412,7 +3400,7 @@ static int ncr_prepare_nego(struct ncb *np, struct ccb *cp, u_char *msgptr)
msgptr[msglen++] = M_X_WIDE_REQ;
msgptr[msglen++] = tp->usrwide;
break;
- };
+ }
cp->nego_status = nego;
@@ -3421,8 +3409,8 @@ static int ncr_prepare_nego(struct ncb *np, struct ccb *cp, u_char *msgptr)
if (DEBUG_FLAGS & DEBUG_NEGO) {
ncr_print_msg(cp, nego == NS_WIDE ?
"wide msgout":"sync_msgout", msgptr);
- };
- };
+ }
+ }
return msglen;
}
@@ -3440,9 +3428,9 @@ static int ncr_prepare_nego(struct ncb *np, struct ccb *cp, u_char *msgptr)
*/
static int ncr_queue_command (struct ncb *np, struct scsi_cmnd *cmd)
{
-/* struct scsi_device *device = cmd->device; */
- struct tcb *tp = &np->target[cmd->device->id];
- struct lcb *lp = tp->lp[cmd->device->lun];
+ struct scsi_device *sdev = cmd->device;
+ struct tcb *tp = &np->target[sdev->id];
+ struct lcb *lp = tp->lp[sdev->lun];
struct ccb *cp;
int segments;
@@ -3457,9 +3445,9 @@ static int ncr_queue_command (struct ncb *np, struct scsi_cmnd *cmd)
**
**---------------------------------------------
*/
- if ((cmd->device->id == np->myaddr ) ||
- (cmd->device->id >= MAX_TARGET) ||
- (cmd->device->lun >= MAX_LUN )) {
+ if ((sdev->id == np->myaddr ) ||
+ (sdev->id >= MAX_TARGET) ||
+ (sdev->lun >= MAX_LUN )) {
return(DID_BAD_TARGET);
}
@@ -3479,8 +3467,7 @@ static int ncr_queue_command (struct ncb *np, struct scsi_cmnd *cmd)
}
if (DEBUG_FLAGS & DEBUG_TINY) {
- PRINT_ADDR(cmd);
- printk ("CMD=%x ", cmd->cmnd[0]);
+ PRINT_ADDR(cmd, "CMD=%x ", cmd->cmnd[0]);
}
/*---------------------------------------------------
@@ -3499,7 +3486,7 @@ static int ncr_queue_command (struct ncb *np, struct scsi_cmnd *cmd)
np->settle_time = tlimit;
}
- if (np->settle_time || !(cp=ncr_get_ccb (np, cmd->device->id, cmd->device->lun))) {
+ if (np->settle_time || !(cp=ncr_get_ccb (np, cmd))) {
insert_into_waiting_list(np, cmd);
return(DID_OK);
}
@@ -3512,7 +3499,7 @@ static int ncr_queue_command (struct ncb *np, struct scsi_cmnd *cmd)
**----------------------------------------------------
*/
- idmsg = M_IDENTIFY | cmd->device->lun;
+ idmsg = M_IDENTIFY | sdev->lun;
if (cp ->tag != NO_TAG ||
(cp != np->ccb && np->disc && !(tp->usrflag & UF_NODISC)))
@@ -3533,8 +3520,8 @@ static int ncr_queue_command (struct ncb *np, struct scsi_cmnd *cmd)
if (lp->tags_smap) {
order = M_ORDERED_TAG;
if ((DEBUG_FLAGS & DEBUG_TAGS)||bootverbose>2){
- PRINT_ADDR(cmd);
- printk("ordered tag forced.\n");
+ PRINT_ADDR(cmd,
+ "ordered tag forced.\n");
}
}
lp->tags_stime = ktime_get(3*HZ);
@@ -3682,7 +3669,7 @@ static int ncr_queue_command (struct ncb *np, struct scsi_cmnd *cmd)
/*
** select
*/
- cp->phys.select.sel_id = cmd->device->id;
+ cp->phys.select.sel_id = sdev->id;
cp->phys.select.sel_scntl3 = tp->wval;
cp->phys.select.sel_sxfer = tp->sval;
/*
@@ -3719,9 +3706,7 @@ static int ncr_queue_command (struct ncb *np, struct scsi_cmnd *cmd)
**----------------------------------------------------
*/
- /*
- ** activate this job.
- */
+ /* activate this job. */
cp->magic = CCB_MAGIC;
/*
@@ -3734,11 +3719,9 @@ static int ncr_queue_command (struct ncb *np, struct scsi_cmnd *cmd)
else
ncr_put_start_queue(np, cp);
- /*
- ** Command is successfully queued.
- */
+ /* Command is successfully queued. */
- return(DID_OK);
+ return DID_OK;
}
@@ -4203,8 +4186,7 @@ void ncr_complete (struct ncb *np, struct ccb *cp)
*/
if (cp->parity_status > 1) {
- PRINT_ADDR(cmd);
- printk ("%d parity error(s).\n",cp->parity_status);
+ PRINT_ADDR(cmd, "%d parity error(s).\n",cp->parity_status);
}
/*
@@ -4212,16 +4194,16 @@ void ncr_complete (struct ncb *np, struct ccb *cp)
*/
if (cp->xerr_status != XE_OK) {
- PRINT_ADDR(cmd);
switch (cp->xerr_status) {
case XE_EXTRA_DATA:
- printk ("extraneous data discarded.\n");
+ PRINT_ADDR(cmd, "extraneous data discarded.\n");
break;
case XE_BAD_PHASE:
- printk ("invalid scsi phase (4/5).\n");
+ PRINT_ADDR(cmd, "invalid scsi phase (4/5).\n");
break;
default:
- printk ("extended error %d.\n", cp->xerr_status);
+ PRINT_ADDR(cmd, "extended error %d.\n",
+ cp->xerr_status);
break;
}
if (cp->host_status==HS_COMPLETE)
@@ -4233,9 +4215,9 @@ void ncr_complete (struct ncb *np, struct ccb *cp)
*/
if (DEBUG_FLAGS & (DEBUG_RESULT|DEBUG_TINY)) {
if (cp->host_status!=HS_COMPLETE || cp->scsi_status!=S_GOOD) {
- PRINT_ADDR(cmd);
- printk ("ERROR: cmd=%x host_status=%x scsi_status=%x\n",
- cmd->cmnd[0], cp->host_status, cp->scsi_status);
+ PRINT_ADDR(cmd, "ERROR: cmd=%x host_status=%x "
+ "scsi_status=%x\n", cmd->cmnd[0],
+ cp->host_status, cp->scsi_status);
}
}
@@ -4296,8 +4278,7 @@ void ncr_complete (struct ncb *np, struct ccb *cp)
if (DEBUG_FLAGS & (DEBUG_RESULT|DEBUG_TINY)) {
u_char * p = (u_char*) & cmd->sense_buffer;
int i;
- PRINT_ADDR(cmd);
- printk ("sense data:");
+ PRINT_ADDR(cmd, "sense data:");
for (i=0; i<14; i++) printk (" %x", *p++);
printk (".\n");
}
@@ -4344,8 +4325,7 @@ void ncr_complete (struct ncb *np, struct ccb *cp)
/*
** Other protocol messes
*/
- PRINT_ADDR(cmd);
- printk ("COMMAND FAILED (%x %x) @%p.\n",
+ PRINT_ADDR(cmd, "COMMAND FAILED (%x %x) @%p.\n",
cp->host_status, cp->scsi_status, cp);
cmd->result = ScsiResult(DID_ERROR, cp->scsi_status);
@@ -4358,8 +4338,7 @@ void ncr_complete (struct ncb *np, struct ccb *cp)
if (tp->usrflag & UF_TRACE) {
u_char * p;
int i;
- PRINT_ADDR(cmd);
- printk (" CMD:");
+ PRINT_ADDR(cmd, " CMD:");
p = (u_char*) &cmd->cmnd[0];
for (i=0; i<cmd->cmd_len; i++) printk (" %x", *p++);
@@ -4667,12 +4646,11 @@ void ncr_init (struct ncb *np, int reset, char * msg, u_long code)
}
else
tp->usrsync = 255;
- };
+ }
if (tp->usrwide > np->maxwide)
tp->usrwide = np->maxwide;
- ncr_negotiate (np, tp);
}
/*
@@ -4849,7 +4827,7 @@ static void ncr_set_sync_wide_status (struct ncb *np, u_char target)
#endif
cp->phys.select.sel_scntl3 = tp->wval;
cp->phys.select.sel_sxfer = tp->sval;
- };
+ }
}
/*==========================================================
@@ -4885,40 +4863,19 @@ static void ncr_setsync (struct ncb *np, struct ccb *cp, u_char scntl3, u_char s
else
tp->period = 0xffff;
- /*
- ** Stop there if sync parameters are unchanged
- */
- if (tp->sval == sxfer && tp->wval == scntl3) return;
+ /* Stop there if sync parameters are unchanged */
+ if (tp->sval == sxfer && tp->wval == scntl3)
+ return;
tp->sval = sxfer;
tp->wval = scntl3;
- /*
- ** Bells and whistles ;-)
- */
- PRINT_TARGET(np, target);
if (sxfer & 0x01f) {
- unsigned f10 = 100000 << (tp->widedone ? tp->widedone -1 : 0);
- unsigned mb10 = (f10 + tp->period/2) / tp->period;
- char *scsi;
-
- /*
- ** Disable extended Sreq/Sack filtering
- */
- if (tp->period <= 2000) OUTOFFB (nc_stest2, EXT);
-
- /*
- ** Bells and whistles ;-)
- */
- if (tp->period < 500) scsi = "FAST-40";
- else if (tp->period < 1000) scsi = "FAST-20";
- else if (tp->period < 2000) scsi = "FAST-10";
- else scsi = "FAST-5";
-
- printk ("%s %sSCSI %d.%d MB/s (%d ns, offset %d)\n", scsi,
- tp->widedone > 1 ? "WIDE " : "",
- mb10 / 10, mb10 % 10, tp->period / 10, sxfer & 0x1f);
- } else
- printk ("%sasynchronous.\n", tp->widedone > 1 ? "wide " : "");
+ /* Disable extended Sreq/Sack filtering */
+ if (tp->period <= 2000)
+ OUTOFFB(nc_stest2, EXT);
+ }
+
+ spi_display_xfer_agreement(tp->starget);
/*
** set actual value and sync_status
@@ -4964,11 +4921,8 @@ static void ncr_setwide (struct ncb *np, struct ccb *cp, u_char wide, u_char ack
** Bells and whistles ;-)
*/
if (bootverbose >= 2) {
- PRINT_TARGET(np, target);
- if (scntl3 & EWS)
- printk ("WIDE SCSI (16 bit) enabled.\n");
- else
- printk ("WIDE SCSI disabled.\n");
+ dev_info(&cmd->device->sdev_target->dev, "WIDE SCSI %sabled.\n",
+ (scntl3 & EWS) ? "en" : "dis");
}
/*
@@ -5023,7 +4977,7 @@ static void ncr_setup_tags (struct ncb *np, struct scsi_device *sdev)
reqtags = lp->numtags;
} else {
reqtags = 1;
- };
+ }
/*
** Update max number of tags
@@ -5063,12 +5017,13 @@ static void ncr_setup_tags (struct ncb *np, struct scsi_device *sdev)
** Announce change to user.
*/
if (bootverbose) {
- PRINT_LUN(np, tn, ln);
if (lp->usetags) {
- printk("tagged command queue depth set to %d\n", reqtags);
- }
- else {
- printk("tagged command queueing disabled\n");
+ dev_info(&sdev->sdev_gendev,
+ "tagged command queue depth set to %d\n",
+ reqtags);
+ } else {
+ dev_info(&sdev->sdev_gendev,
+ "tagged command queueing disabled\n");
}
}
}
@@ -5274,7 +5229,7 @@ void ncr_exception (struct ncb *np)
istat = INB (nc_istat);
if (DEBUG_FLAGS & DEBUG_TINY) printk ("F ");
ncr_wakeup_done (np);
- };
+ }
if (!(istat & (SIP|DIP)))
return;
@@ -5335,7 +5290,7 @@ void ncr_exception (struct ncb *np)
}
OUTONB_STD ();
return;
- };
+ }
/*========================================================
** Now, interrupts that need some fixing up.
@@ -5355,7 +5310,7 @@ void ncr_exception (struct ncb *np)
if (sist & RST) {
ncr_init (np, 1, bootverbose ? "scsi reset" : NULL, HS_RESET);
return;
- };
+ }
if ((sist & STO) &&
!(dstat & (MDPE|BF|ABRT))) {
@@ -5366,7 +5321,7 @@ void ncr_exception (struct ncb *np)
ncr_int_sto (np);
return;
- };
+ }
/*=========================================================
** Now, interrupts we are not able to recover cleanly.
@@ -5387,7 +5342,7 @@ void ncr_exception (struct ncb *np)
((char*)&np->regdump)[i] = INB_OFF(i);
np->regdump.nc_dstat = dstat;
np->regdump.nc_sist = sist;
- };
+ }
ncr_log_hard_error(np, sist, dstat);
@@ -5399,20 +5354,20 @@ void ncr_exception (struct ncb *np)
(dstat & (MDPE|BF|ABRT|IID))) {
ncr_start_reset(np);
return;
- };
+ }
if (sist & HTH) {
printk ("%s: handshake timeout\n", ncr_name(np));
ncr_start_reset(np);
return;
- };
+ }
if (sist & UDC) {
printk ("%s: unexpected disconnect\n", ncr_name(np));
OUTB (HS_PRT, HS_UNEXPECTED);
OUTL_DSP (NCB_SCRIPT_PHYS (np, cleanup));
return;
- };
+ }
/*=========================================================
** We just miss the cause of the interrupt. :(
@@ -5456,7 +5411,7 @@ void ncr_int_sto (struct ncb *np)
if (cp) {
cp-> host_status = HS_SEL_TIMEOUT;
ncr_complete (np, cp);
- };
+ }
/*
** repair start queue and jump to start point.
@@ -5647,7 +5602,7 @@ static void ncr_int_ma (struct ncb *np)
ss2 = INB (nc_sstat2);
if (ss2 & OLF1) rest++;
if (ss2 & ORF1) rest++;
- };
+ }
if (DEBUG_FLAGS & (DEBUG_TINY|DEBUG_PHASE))
printk ("P%x%x RL=%d D=%d SS0=%x ", cmd&7, sbcl&7,
@@ -5716,7 +5671,7 @@ static void ncr_int_ma (struct ncb *np)
cp, np->header.cp,
(unsigned)dsp,
(unsigned)nxtdsp, vdsp, cmd);
- };
+ }
/*
** cp=0 means that the DSA does not point to a valid control
@@ -5744,7 +5699,7 @@ static void ncr_int_ma (struct ncb *np)
} else {
tblp = (u32 *) 0;
olen = scr_to_cpu(vdsp[0]) & 0xffffff;
- };
+ }
if (DEBUG_FLAGS & DEBUG_PHASE) {
printk ("OCMD=%x\nTBLP=%p OLEN=%x OADR=%x\n",
@@ -5752,16 +5707,15 @@ static void ncr_int_ma (struct ncb *np)
tblp,
(unsigned) olen,
(unsigned) oadr);
- };
+ }
/*
** check cmd against assumed interrupted script command.
*/
if (cmd != (scr_to_cpu(vdsp[0]) >> 24)) {
- PRINT_ADDR(cp->cmd);
- printk ("internal error: cmd=%02x != %02x=(vdsp[0] >> 24)\n",
- (unsigned)cmd, (unsigned)scr_to_cpu(vdsp[0]) >> 24);
+ PRINT_ADDR(cp->cmd, "internal error: cmd=%02x != %02x=(vdsp[0] "
+ ">> 24)\n", cmd, scr_to_cpu(vdsp[0]) >> 24);
goto reset_all;
}
@@ -5783,12 +5737,11 @@ static void ncr_int_ma (struct ncb *np)
*/
if (cmd & 0x06) {
- PRINT_ADDR(cp->cmd);
- printk ("phase change %x-%x %d@%08x resid=%d.\n",
+ PRINT_ADDR(cp->cmd, "phase change %x-%x %d@%08x resid=%d.\n",
cmd&7, sbcl&7, (unsigned)olen,
(unsigned)oadr, (unsigned)rest);
goto unexpected_phase;
- };
+ }
/*
** choose the correct patch area.
@@ -5812,8 +5765,7 @@ static void ncr_int_ma (struct ncb *np)
newcmd[3] = cpu_to_scr(nxtdsp);
if (DEBUG_FLAGS & DEBUG_PHASE) {
- PRINT_ADDR(cp->cmd);
- printk ("newcmd[%d] %x %x %x %x.\n",
+ PRINT_ADDR(cp->cmd, "newcmd[%d] %x %x %x %x.\n",
(int) (newcmd - cp->patch),
(unsigned)scr_to_cpu(newcmd[0]),
(unsigned)scr_to_cpu(newcmd[1]),
@@ -5939,9 +5891,8 @@ static void ncr_sir_to_redo(struct ncb *np, int num, struct ccb *cp)
if (!lp)
goto out;
if (bootverbose >= 1) {
- PRINT_ADDR(cmd);
- printk ("QUEUE FULL! %d busy, %d disconnected CCBs\n",
- busy_cnt, disc_cnt);
+ PRINT_ADDR(cmd, "QUEUE FULL! %d busy, %d disconnected "
+ "CCBs\n", busy_cnt, disc_cnt);
}
if (disc_cnt < lp->numtags) {
lp->numtags = disc_cnt > 2 ? disc_cnt : 2;
@@ -5978,7 +5929,7 @@ static void ncr_sir_to_redo(struct ncb *np, int num, struct ccb *cp)
**
** identify message
*/
- cp->scsi_smsg2[0] = M_IDENTIFY | cmd->device->lun;
+ cp->scsi_smsg2[0] = IDENTIFY(0, cmd->device->lun);
cp->phys.smsg.addr = cpu_to_scr(CCB_PHYS (cp, scsi_smsg2));
cp->phys.smsg.size = cpu_to_scr(1);
@@ -6048,34 +5999,6 @@ out:
**==========================================================
*/
-static int ncr_show_msg (u_char * msg)
-{
- u_char i;
- printk ("%x",*msg);
- if (*msg==M_EXTENDED) {
- for (i=1;i<8;i++) {
- if (i-1>msg[1]) break;
- printk ("-%x",msg[i]);
- };
- return (i+1);
- } else if ((*msg & 0xf0) == 0x20) {
- printk ("-%x",msg[1]);
- return (2);
- };
- return (1);
-}
-
-static void ncr_print_msg ( struct ccb *cp, char *label, u_char *msg)
-{
- if (cp)
- PRINT_ADDR(cp->cmd);
- if (label)
- printk("%s: ", label);
-
- (void) ncr_show_msg (msg);
- printk(".\n");
-}
-
void ncr_int_sir (struct ncb *np)
{
u_char scntl3;
@@ -6230,10 +6153,9 @@ void ncr_int_sir (struct ncb *np)
*/
if (DEBUG_FLAGS & DEBUG_NEGO) {
- PRINT_ADDR(cp->cmd);
- printk ("negotiation failed sir=%x status=%x.\n",
- num, cp->nego_status);
- };
+ PRINT_ADDR(cp->cmd, "negotiation failed sir=%x "
+ "status=%x.\n", num, cp->nego_status);
+ }
/*
** any error in negotiation:
@@ -6242,37 +6164,26 @@ void ncr_int_sir (struct ncb *np)
switch (cp->nego_status) {
case NS_SYNC:
- ncr_setsync (np, cp, 0, 0xe0);
spi_period(starget) = 0;
spi_offset(starget) = 0;
+ ncr_setsync (np, cp, 0, 0xe0);
break;
case NS_WIDE:
- ncr_setwide (np, cp, 0, 0);
spi_width(starget) = 0;
+ ncr_setwide (np, cp, 0, 0);
break;
- };
+ }
np->msgin [0] = M_NOOP;
np->msgout[0] = M_NOOP;
cp->nego_status = 0;
break;
case SIR_NEGO_SYNC:
- /*
- ** Synchronous request message received.
- */
-
if (DEBUG_FLAGS & DEBUG_NEGO) {
- PRINT_ADDR(cp->cmd);
- printk ("sync msgin: ");
- (void) ncr_show_msg (np->msgin);
- printk (".\n");
- };
-
- /*
- ** get requested values.
- */
+ ncr_print_msg(cp, "sync msgin", np->msgin);
+ }
chg = 0;
per = np->msgin[3];
@@ -6284,8 +6195,8 @@ void ncr_int_sir (struct ncb *np)
** it CAN transfer synch.
*/
- if (ofs && tp->starget)
- spi_support_sync(tp->starget) = 1;
+ if (ofs && starget)
+ spi_support_sync(starget) = 1;
/*
** check values against driver limits.
@@ -6318,9 +6229,8 @@ void ncr_int_sir (struct ncb *np)
}
if (DEBUG_FLAGS & DEBUG_NEGO) {
- PRINT_ADDR(cp->cmd);
- printk ("sync: per=%d scntl3=0x%x ofs=%d fak=%d chg=%d.\n",
- per, scntl3, ofs, fak, chg);
+ PRINT_ADDR(cp->cmd, "sync: per=%d scntl3=0x%x ofs=%d "
+ "fak=%d chg=%d.\n", per, scntl3, ofs, fak, chg);
}
if (INB (HS_PRT) == HS_NEGOTIATE) {
@@ -6328,43 +6238,37 @@ void ncr_int_sir (struct ncb *np)
switch (cp->nego_status) {
case NS_SYNC:
- /*
- ** This was an answer message
- */
+ /* This was an answer message */
if (chg) {
- /*
- ** Answer wasn't acceptable.
- */
- ncr_setsync (np, cp, 0, 0xe0);
+ /* Answer wasn't acceptable. */
spi_period(starget) = 0;
spi_offset(starget) = 0;
- OUTL_DSP (NCB_SCRIPT_PHYS (np, msg_bad));
+ ncr_setsync(np, cp, 0, 0xe0);
+ OUTL_DSP(NCB_SCRIPT_PHYS (np, msg_bad));
} else {
- /*
- ** Answer is ok.
- */
- ncr_setsync (np, cp, scntl3, (fak<<5)|ofs);
+ /* Answer is ok. */
spi_period(starget) = per;
spi_offset(starget) = ofs;
- OUTL_DSP (NCB_SCRIPT_PHYS (np, clrack));
- };
+ ncr_setsync(np, cp, scntl3, (fak<<5)|ofs);
+ OUTL_DSP(NCB_SCRIPT_PHYS (np, clrack));
+ }
return;
case NS_WIDE:
- ncr_setwide (np, cp, 0, 0);
spi_width(starget) = 0;
+ ncr_setwide(np, cp, 0, 0);
break;
- };
- };
+ }
+ }
/*
** It was a request. Set value and
** prepare an answer message
*/
- ncr_setsync (np, cp, scntl3, (fak<<5)|ofs);
spi_period(starget) = per;
spi_offset(starget) = ofs;
+ ncr_setsync(np, cp, scntl3, (fak<<5)|ofs);
np->msgout[0] = M_EXTENDED;
np->msgout[1] = 3;
@@ -6375,10 +6279,7 @@ void ncr_int_sir (struct ncb *np)
cp->nego_status = NS_SYNC;
if (DEBUG_FLAGS & DEBUG_NEGO) {
- PRINT_ADDR(cp->cmd);
- printk ("sync msgout: ");
- (void) ncr_show_msg (np->msgout);
- printk (".\n");
+ ncr_print_msg(cp, "sync msgout", np->msgout);
}
if (!ofs) {
@@ -6394,11 +6295,8 @@ void ncr_int_sir (struct ncb *np)
** Wide request message received.
*/
if (DEBUG_FLAGS & DEBUG_NEGO) {
- PRINT_ADDR(cp->cmd);
- printk ("wide msgin: ");
- (void) ncr_show_msg (np->msgin);
- printk (".\n");
- };
+ ncr_print_msg(cp, "wide msgin", np->msgin);
+ }
/*
** get requested values.
@@ -6412,8 +6310,8 @@ void ncr_int_sir (struct ncb *np)
** it CAN transfer wide.
*/
- if (wide && tp->starget)
- spi_support_wide(tp->starget) = 1;
+ if (wide && starget)
+ spi_support_wide(starget) = 1;
/*
** check values against driver limits.
@@ -6423,8 +6321,8 @@ void ncr_int_sir (struct ncb *np)
{chg = 1; wide = tp->usrwide;}
if (DEBUG_FLAGS & DEBUG_NEGO) {
- PRINT_ADDR(cp->cmd);
- printk ("wide: wide=%d chg=%d.\n", wide, chg);
+ PRINT_ADDR(cp->cmd, "wide: wide=%d chg=%d.\n", wide,
+ chg);
}
if (INB (HS_PRT) == HS_NEGOTIATE) {
@@ -6436,37 +6334,33 @@ void ncr_int_sir (struct ncb *np)
** This was an answer message
*/
if (chg) {
- /*
- ** Answer wasn't acceptable.
- */
- ncr_setwide (np, cp, 0, 1);
+ /* Answer wasn't acceptable. */
spi_width(starget) = 0;
+ ncr_setwide(np, cp, 0, 1);
OUTL_DSP (NCB_SCRIPT_PHYS (np, msg_bad));
} else {
- /*
- ** Answer is ok.
- */
- ncr_setwide (np, cp, wide, 1);
+ /* Answer is ok. */
spi_width(starget) = wide;
+ ncr_setwide(np, cp, wide, 1);
OUTL_DSP (NCB_SCRIPT_PHYS (np, clrack));
- };
+ }
return;
case NS_SYNC:
- ncr_setsync (np, cp, 0, 0xe0);
spi_period(starget) = 0;
spi_offset(starget) = 0;
+ ncr_setsync(np, cp, 0, 0xe0);
break;
- };
- };
+ }
+ }
/*
** It was a request, set value and
** prepare an answer message
*/
- ncr_setwide (np, cp, wide, 1);
spi_width(starget) = wide;
+ ncr_setwide(np, cp, wide, 1);
np->msgout[0] = M_EXTENDED;
np->msgout[1] = 2;
@@ -6478,10 +6372,7 @@ void ncr_int_sir (struct ncb *np)
cp->nego_status = NS_WIDE;
if (DEBUG_FLAGS & DEBUG_NEGO) {
- PRINT_ADDR(cp->cmd);
- printk ("wide msgout: ");
- (void) ncr_show_msg (np->msgin);
- printk (".\n");
+ ncr_print_msg(cp, "wide msgout", np->msgin);
}
break;
@@ -6500,8 +6391,7 @@ void ncr_int_sir (struct ncb *np)
**-----------------------------------------------
*/
- PRINT_ADDR(cp->cmd);
- printk ("M_REJECT received (%x:%x).\n",
+ PRINT_ADDR(cp->cmd, "M_REJECT received (%x:%x).\n",
(unsigned)scr_to_cpu(np->lastmsg), np->msgout[0]);
break;
@@ -6513,10 +6403,7 @@ void ncr_int_sir (struct ncb *np)
**-----------------------------------------------
*/
- PRINT_ADDR(cp->cmd);
- printk ("M_REJECT sent for ");
- (void) ncr_show_msg (np->msgin);
- printk (".\n");
+ ncr_print_msg(cp, "M_REJECT sent for", np->msgin);
break;
/*--------------------------------------------------------------------
@@ -6535,8 +6422,8 @@ void ncr_int_sir (struct ncb *np)
**-----------------------------------------------
*/
- PRINT_ADDR(cp->cmd);
- printk ("M_IGN_RESIDUE received, but not yet implemented.\n");
+ PRINT_ADDR(cp->cmd, "M_IGN_RESIDUE received, but not yet "
+ "implemented.\n");
break;
#if 0
case SIR_MISSING_SAVE:
@@ -6548,15 +6435,14 @@ void ncr_int_sir (struct ncb *np)
**-----------------------------------------------
*/
- PRINT_ADDR(cp->cmd);
- printk ("M_DISCONNECT received, but datapointer not saved: "
- "data=%x save=%x goal=%x.\n",
+ PRINT_ADDR(cp->cmd, "M_DISCONNECT received, but datapointer "
+ "not saved: data=%x save=%x goal=%x.\n",
(unsigned) INL (nc_temp),
(unsigned) scr_to_cpu(np->header.savep),
(unsigned) scr_to_cpu(np->header.goalp));
break;
#endif
- };
+ }
out:
OUTONB_STD ();
@@ -6571,8 +6457,10 @@ out:
**==========================================================
*/
-static struct ccb *ncr_get_ccb (struct ncb *np, u_char tn, u_char ln)
+static struct ccb *ncr_get_ccb(struct ncb *np, struct scsi_cmnd *cmd)
{
+ u_char tn = cmd->device->id;
+ u_char ln = cmd->device->lun;
struct tcb *tp = &np->target[tn];
struct lcb *lp = tp->lp[ln];
u_char tag = NO_TAG;
@@ -6602,8 +6490,8 @@ static struct ccb *ncr_get_ccb (struct ncb *np, u_char tn, u_char ln)
if (qp) {
cp = list_entry(qp, struct ccb, link_ccbq);
if (cp->magic) {
- PRINT_LUN(np, tn, ln);
- printk ("ccb free list corrupted (@%p)\n", cp);
+ PRINT_ADDR(cmd, "ccb free list corrupted "
+ "(@%p)\n", cp);
cp = NULL;
} else {
list_add_tail(qp, &lp->wait_ccbq);
@@ -6637,7 +6525,7 @@ static struct ccb *ncr_get_ccb (struct ncb *np, u_char tn, u_char ln)
if (flags & SCSI_NOSLEEP) break;
if (tsleep ((caddr_t)cp, PRIBIO|PCATCH, "ncr", 0))
break;
- };
+ }
#endif
if (cp->magic)
@@ -6665,8 +6553,7 @@ static struct ccb *ncr_get_ccb (struct ncb *np, u_char tn, u_char ln)
cp->lun = ln;
if (DEBUG_FLAGS & DEBUG_TAGS) {
- PRINT_LUN(np, tn, ln);
- printk ("ccb @%p using tag %d.\n", cp, tag);
+ PRINT_ADDR(cmd, "ccb @%p using tag %d.\n", cp, tag);
}
return cp;
@@ -6687,8 +6574,7 @@ static void ncr_free_ccb (struct ncb *np, struct ccb *cp)
struct lcb *lp = tp->lp[cp->lun];
if (DEBUG_FLAGS & DEBUG_TAGS) {
- PRINT_LUN(np, cp->target, cp->lun);
- printk ("ccb @%p freeing tag %d.\n", cp, cp->tag);
+ PRINT_ADDR(cp->cmd, "ccb @%p freeing tag %d.\n", cp, cp->tag);
}
/*
@@ -7014,21 +6900,12 @@ static struct lcb *ncr_setup_lcb (struct ncb *np, struct scsi_device *sdev)
unsigned char tn = sdev->id, ln = sdev->lun;
struct tcb *tp = &np->target[tn];
struct lcb *lp = tp->lp[ln];
- struct scsi_target *starget = tp->starget;
- /*
- ** If no lcb, try to allocate it.
- */
+ /* If no lcb, try to allocate it. */
if (!lp && !(lp = ncr_alloc_lcb(np, tn, ln)))
goto fail;
/*
- ** Prepare negotiation
- */
- if (spi_support_wide(starget) || spi_support_sync(starget))
- ncr_negotiate(np, tp);
-
- /*
** If unit supports tagged commands, allocate the
** CCB JUMP table if not yet.
*/
@@ -7170,7 +7047,7 @@ static int __init ncr_regtest (struct ncb* np)
printk ("CACHE TEST FAILED: reg dstat-sstat2 readback %x.\n",
(unsigned) data);
return (0x10);
- };
+ }
return (0);
}
@@ -7223,7 +7100,7 @@ static int __init ncr_snooptest (struct ncb* np)
if (i>=NCR_SNOOP_TIMEOUT) {
printk ("CACHE TEST FAILED: timeout.\n");
return (0x20);
- };
+ }
/*
** Check termination position.
*/
@@ -7233,7 +7110,7 @@ static int __init ncr_snooptest (struct ncb* np)
(u_long) NCB_SCRIPTH_PHYS (np, snooptest), (u_long) pc,
(u_long) NCB_SCRIPTH_PHYS (np, snoopend) +8);
return (0x40);
- };
+ }
/*
** Show results.
*/
@@ -7241,17 +7118,17 @@ static int __init ncr_snooptest (struct ncb* np)
printk ("CACHE TEST FAILED: host wrote %d, ncr read %d.\n",
(int) host_wr, (int) ncr_rd);
err |= 1;
- };
+ }
if (host_rd != ncr_wr) {
printk ("CACHE TEST FAILED: ncr wrote %d, host read %d.\n",
(int) ncr_wr, (int) host_rd);
err |= 2;
- };
+ }
if (ncr_bk != ncr_wr) {
printk ("CACHE TEST FAILED: ncr wrote %d, read back %d.\n",
(int) ncr_wr, (int) ncr_bk);
err |= 4;
- };
+ }
return (err);
}
@@ -7424,6 +7301,16 @@ static void __init ncr_getclock (struct ncb *np, int mult)
/*===================== LINUX ENTRY POINTS SECTION ==========================*/
+static int ncr53c8xx_slave_alloc(struct scsi_device *device)
+{
+ struct Scsi_Host *host = device->host;
+ struct ncb *np = ((struct host_data *) host->hostdata)->ncb;
+ struct tcb *tp = &np->target[device->id];
+ tp->starget = device->sdev_target;
+
+ return 0;
+}
+
static int ncr53c8xx_slave_configure(struct scsi_device *device)
{
struct Scsi_Host *host = device->host;
@@ -7432,8 +7319,6 @@ static int ncr53c8xx_slave_configure(struct scsi_device *device)
struct lcb *lp = tp->lp[device->lun];
int numtags, depth_to_use;
- tp->starget = device->sdev_target;
-
ncr_setup_lcb(np, device);
/*
@@ -7778,6 +7663,7 @@ struct Scsi_Host * __init ncr_attach(struct scsi_host_template *tpnt,
tpnt->queuecommand = ncr53c8xx_queue_command;
tpnt->slave_configure = ncr53c8xx_slave_configure;
+ tpnt->slave_alloc = ncr53c8xx_slave_alloc;
tpnt->eh_bus_reset_handler = ncr53c8xx_bus_reset;
tpnt->can_queue = SCSI_NCR_CAN_QUEUE;
tpnt->this_id = 7;
@@ -7925,7 +7811,7 @@ struct Scsi_Host * __init ncr_attach(struct scsi_host_template *tpnt,
if (ncr_snooptest(np)) {
printk(KERN_ERR "CACHE INCORRECTLY CONFIGURED.\n");
goto attach_error;
- };
+ }
/* Install the interrupt handler. */
np->irq = device->slot.irq;
@@ -8057,6 +7943,25 @@ static void ncr53c8xx_set_width(struct scsi_target *starget, int width)
ncr_negotiate(np, tp);
}
+static void ncr53c8xx_get_signalling(struct Scsi_Host *shost)
+{
+ struct ncb *np = ((struct host_data *)shost->hostdata)->ncb;
+ enum spi_signal_type type;
+
+ switch (np->scsi_mode) {
+ case SMODE_SE:
+ type = SPI_SIGNAL_SE;
+ break;
+ case SMODE_HVD:
+ type = SPI_SIGNAL_HVD;
+ break;
+ default:
+ type = SPI_SIGNAL_UNKNOWN;
+ break;
+ }
+ spi_signalling(shost) = type;
+}
+
static struct spi_function_template ncr53c8xx_transport_functions = {
.set_period = ncr53c8xx_set_period,
.show_period = 1,
@@ -8064,6 +7969,7 @@ static struct spi_function_template ncr53c8xx_transport_functions = {
.show_offset = 1,
.set_width = ncr53c8xx_set_width,
.show_width = 1,
+ .get_signalling = ncr53c8xx_get_signalling,
};
int __init ncr53c8xx_init(void)
diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c
index fb3494ab281e0..c585c7bef247c 100644
--- a/drivers/scsi/osst.c
+++ b/drivers/scsi/osst.c
@@ -24,7 +24,7 @@
*/
static const char * cvsid = "$Id: osst.c,v 1.73 2005/01/01 21:13:34 wriede Exp $";
-const char * osst_version = "0.99.3";
+static const char * osst_version = "0.99.3";
/* The "failure to reconnect" firmware bug */
#define OSST_FW_NEED_POLL_MIN 10601 /*(107A)*/
@@ -170,7 +170,7 @@ static int osst_copy_from_buffer(struct osst_buffer *, unsigned char *);
static int osst_probe(struct device *);
static int osst_remove(struct device *);
-struct scsi_driver osst_template = {
+static struct scsi_driver osst_template = {
.owner = THIS_MODULE,
.gendrv = {
.name = "osst",
@@ -4318,7 +4318,13 @@ static int os_scsi_tape_open(struct inode * inode, struct file * filp)
int dev = TAPE_NR(inode);
int mode = TAPE_MODE(inode);
- nonseekable_open(inode, filp);
+ /*
+ * We really want to do nonseekable_open(inode, filp); here, but some
+ * versions of tar incorrectly call lseek on tapes and bail out if that
+ * fails. So we disallow pread() and pwrite(), but permit lseeks.
+ */
+ filp->f_mode &= ~(FMODE_PREAD | FMODE_PWRITE);
+
write_lock(&os_scsi_tapes_lock);
if (dev >= osst_max_dev || os_scsi_tapes == NULL ||
(STp = os_scsi_tapes[dev]) == NULL || !STp->device) {
@@ -4764,9 +4770,6 @@ static int os_scsi_tape_close(struct inode * inode, struct file * filp)
{
int result = 0;
struct osst_tape * STp = filp->private_data;
- struct scsi_request * SRpnt = NULL;
-
- if (SRpnt) scsi_release_request(SRpnt);
if (STp->door_locked == ST_LOCKED_AUTO)
do_door_lock(STp, 0);
@@ -5121,6 +5124,22 @@ out:
return retval;
}
+#ifdef CONFIG_COMPAT
+static long osst_compat_ioctl(struct file * file, unsigned int cmd_in, unsigned long arg)
+{
+ struct osst_tape *STp = file->private_data;
+ struct scsi_device *sdev = STp->device;
+ int ret = -ENOIOCTLCMD;
+ if (sdev->host->hostt->compat_ioctl) {
+
+ ret = sdev->host->hostt->compat_ioctl(sdev, cmd_in, (void __user *)arg);
+
+ }
+ return ret;
+}
+#endif
+
+
/* Memory handling routines */
@@ -5456,6 +5475,9 @@ static struct file_operations osst_fops = {
.read = osst_read,
.write = osst_write,
.ioctl = osst_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = osst_compat_ioctl,
+#endif
.open = os_scsi_tape_open,
.flush = os_scsi_tape_flush,
.release = os_scsi_tape_close,
diff --git a/drivers/scsi/psi240i.c b/drivers/scsi/psi240i.c
index 03df5b630cd9a..0f576d4ad0dd9 100644
--- a/drivers/scsi/psi240i.c
+++ b/drivers/scsi/psi240i.c
@@ -390,7 +390,7 @@ static irqreturn_t do_Irq_Handler (int irq, void *dev_id, struct pt_regs *regs)
* Returns: Status code.
*
****************************************************************/
-int Psi240i_QueueCommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
+static int Psi240i_QueueCommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
{
UCHAR *cdb = (UCHAR *)SCpnt->cmnd; // Pointer to SCSI CDB
PADAPTER240I padapter = HOSTDATA (SCpnt->device->host); // Pointer to adapter control structure
@@ -509,7 +509,7 @@ int Psi240i_QueueCommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
* Returns: Nothing.
*
**************************************************************************/
-void ReadChipMemory (void *pdata, USHORT base, USHORT length, USHORT port)
+static void ReadChipMemory (void *pdata, USHORT base, USHORT length, USHORT port)
{
USHORT z, zz;
UCHAR *pd = (UCHAR *)pdata;
@@ -538,7 +538,7 @@ void ReadChipMemory (void *pdata, USHORT base, USHORT length, USHORT port)
* Returns: Number of adapters found.
*
****************************************************************/
-int Psi240i_Detect (Scsi_Host_Template *tpnt)
+static int Psi240i_Detect (Scsi_Host_Template *tpnt)
{
int board;
int count = 0;
@@ -654,7 +654,7 @@ static int Psi240i_Release(struct Scsi_Host *shost)
* Returns: zero.
*
****************************************************************/
-int Psi240i_BiosParam (struct scsi_device *sdev, struct block_device *dev,
+static int Psi240i_BiosParam (struct scsi_device *sdev, struct block_device *dev,
sector_t capacity, int geom[])
{
POUR_DEVICE pdev;
diff --git a/drivers/scsi/psi240i.h b/drivers/scsi/psi240i.h
index 536059b0fc06d..6a598766df516 100644
--- a/drivers/scsi/psi240i.h
+++ b/drivers/scsi/psi240i.h
@@ -309,11 +309,7 @@ typedef struct _IDENTIFY_DATA2 {
#endif // PSI_EIDE_SCSIOP
// function prototypes
-int Psi240i_Detect (Scsi_Host_Template *tpnt);
int Psi240i_Command (Scsi_Cmnd *SCpnt);
-int Psi240i_QueueCommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *));
int Psi240i_Abort (Scsi_Cmnd *SCpnt);
int Psi240i_Reset (Scsi_Cmnd *SCpnt, unsigned int flags);
-int Psi240i_BiosParam (struct scsi_device *sdev, struct block_device *bdev,
- sector_t capacity, int geom[]);
#endif
diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c
index df89d2b7c30fe..4ad2808149908 100644
--- a/drivers/scsi/qla1280.c
+++ b/drivers/scsi/qla1280.c
@@ -20,6 +20,9 @@
#define QLA1280_VERSION "3.25"
/*****************************************************************************
Revision History:
+ Rev 3.25.1, February 10, 2005 Christoph Hellwig
+ - use pci_map_single to map non-S/G requests
+ - remove qla1280_proc_info
Rev 3.25, September 28, 2004, Christoph Hellwig
- add support for ISP1020/1040
- don't include "scsi.h" anymore for 2.6.x
@@ -670,8 +673,6 @@ static struct qla_boards ql1280_board_tbl[] = {
};
static int qla1280_verbose = 1;
-static int qla1280_buffer_size;
-static char *qla1280_buffer;
#if DEBUG_QLA1280
static int ql_debug_level = 1;
@@ -694,97 +695,6 @@ static int ql_debug_level = 1;
#define LEAVE_INTR(x) dprintk(4, "qla1280 : Leaving %s()\n", x);
-/*************************************************************************
- * qla1280_proc_info
- *
- * Description:
- * Return information to handle /proc support for the driver.
- *
- * buffer - ptrs to a page buffer
- *
- * Returns:
- *************************************************************************/
-#define PROC_BUF &qla1280_buffer[len]
-
-static int qla1280_proc_info(struct Scsi_Host *host, char *buffer,
- char **start, off_t offset, int length, int inout)
-{
- struct scsi_qla_host *ha = (struct scsi_qla_host *)host->hostdata;
- struct qla_boards *bdp = &ql1280_board_tbl[ha->devnum];
- int size = 0;
- int len = 0;
-
- if (inout)
- return -ENOSYS;
-
- /*
- * if our old buffer is the right size use it otherwise
- * allocate a new one.
- */
- if (qla1280_buffer_size != PAGE_SIZE) {
- /* deallocate this buffer and get a new one */
- if (qla1280_buffer != NULL) {
- free_page((unsigned long)qla1280_buffer);
- qla1280_buffer_size = 0;
- }
- qla1280_buffer = (char *)get_zeroed_page(GFP_KERNEL);
- }
- if (qla1280_buffer == NULL) {
- size = sprintf(buffer, "qla1280 - kmalloc error at line %d\n",
- __LINE__);
- return size;
- }
- /* save the size of our buffer */
- qla1280_buffer_size = PAGE_SIZE;
-
- /* 3.20 clear the buffer we use for proc display */
- memset(qla1280_buffer, 0, PAGE_SIZE);
-
- /* start building the print buffer */
- size = sprintf(PROC_BUF,
- "QLogic PCI to SCSI Adapter for ISP 1280/12160:\n"
- " Firmware version: %2d.%02d.%02d, Driver version %s\n",
- bdp->fwver[0], bdp->fwver[1], bdp->fwver[2],
- QLA1280_VERSION);
-
- len += size;
-
- size = sprintf(PROC_BUF, "SCSI Host Adapter Information: %s\n",
- bdp->name);
- len += size;
- size = sprintf(PROC_BUF, "Request Queue count= 0x%x, Response "
- "Queue count= 0x%x\n",
- REQUEST_ENTRY_CNT, RESPONSE_ENTRY_CNT);
- len += size;
- size = sprintf(PROC_BUF, "Number of pending commands = 0x%lx\n",
- ha->actthreads);
- len += size;
- size = sprintf(PROC_BUF, "Number of free request entries = %d\n",
- ha->req_q_cnt);
- len += size;
- size = sprintf(PROC_BUF, "\n"); /* 1 */
- len += size;
-
- if (len >= qla1280_buffer_size) {
- printk(KERN_WARNING
- "qla1280: Overflow buffer in qla1280_proc.c\n");
- }
-
- if (offset > len - 1) {
- free_page((unsigned long) qla1280_buffer);
- qla1280_buffer = NULL;
- qla1280_buffer_size = length = 0;
- *start = NULL;
- } else {
- *start = &qla1280_buffer[offset]; /* Start of wanted data */
- if (len - offset < length) {
- length = len - offset;
- }
- }
- return length;
-}
-
-
static int qla1280_read_nvram(struct scsi_qla_host *ha)
{
uint16_t *wptr;
@@ -1334,22 +1244,6 @@ qla1280_biosparam_old(Disk * disk, kdev_t dev, int geom[])
{
return qla1280_biosparam(disk->device, NULL, disk->capacity, geom);
}
-
-static int
-qla1280_proc_info_old(char *buffer, char **start, off_t offset, int length,
- int hostno, int inout)
-{
- struct Scsi_Host *host;
-
- for (host = scsi_hostlist; host; host = host->next) {
- if (host->host_no == hostno) {
- return qla1280_proc_info(host, buffer, start,
- offset, length, inout);
- }
- }
-
- return -ESRCH;
-}
#endif
/**************************************************************************
@@ -1571,16 +1465,12 @@ qla1280_done(struct scsi_qla_host *ha)
/* Release memory used for this I/O */
if (cmd->use_sg) {
- dprintk(3, "S/G unmap_sg cmd=%p\n", cmd);
-
pci_unmap_sg(ha->pdev, cmd->request_buffer,
- cmd->use_sg, cmd->sc_data_direction);
+ cmd->use_sg, cmd->sc_data_direction);
} else if (cmd->request_bufflen) {
- /*dprintk(1, "No S/G unmap_single cmd=%x saved_dma_handle=%lx\n",
- cmd, sp->saved_dma_handle); */
-
- pci_unmap_page(ha->pdev, sp->saved_dma_handle,
- cmd->request_bufflen, cmd->sc_data_direction);
+ pci_unmap_single(ha->pdev, sp->saved_dma_handle,
+ cmd->request_bufflen,
+ cmd->sc_data_direction);
}
/* Call the mid-level driver interrupt handler */
@@ -3354,14 +3244,11 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
REQUEST_ENTRY_SIZE);
}
} else { /* No scatter gather data transfer */
- struct page *page = virt_to_page(cmd->request_buffer);
- unsigned long off = (unsigned long)cmd->request_buffer & ~PAGE_MASK;
-
- dma_handle = pci_map_page(ha->pdev, page, off,
- cmd->request_bufflen,
- cmd->sc_data_direction);
+ dma_handle = pci_map_single(ha->pdev,
+ cmd->request_buffer,
+ cmd->request_bufflen,
+ cmd->sc_data_direction);
- /* save dma_handle for pci_unmap_page */
sp->saved_dma_handle = dma_handle;
#if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2)
if (ha->flags.use_pci_vchannel)
@@ -3636,11 +3523,10 @@ qla1280_32bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
REQUEST_ENTRY_SIZE);
}
} else { /* No S/G data transfer */
- struct page *page = virt_to_page(cmd->request_buffer);
- unsigned long off = (unsigned long)cmd->request_buffer & ~PAGE_MASK;
- dma_handle = pci_map_page(ha->pdev, page, off,
- cmd->request_bufflen,
- cmd->sc_data_direction);
+ dma_handle = pci_map_single(ha->pdev,
+ cmd->request_buffer,
+ cmd->request_bufflen,
+ cmd->sc_data_direction);
sp->saved_dma_handle = dma_handle;
*dword_ptr++ = cpu_to_le32(pci_dma_lo32(dma_handle));
@@ -4668,7 +4554,6 @@ static struct scsi_host_template qla1280_driver_template = {
.eh_bus_reset_handler = qla1280_eh_bus_reset,
.eh_host_reset_handler = qla1280_eh_adapter_reset,
.bios_param = qla1280_biosparam,
- .proc_info = qla1280_proc_info,
.can_queue = 0xfffff,
.this_id = -1,
.sg_tablesize = SG_ALL,
@@ -4688,7 +4573,6 @@ static Scsi_Host_Template qla1280_driver_template = {
.eh_bus_reset_handler = qla1280_eh_bus_reset,
.eh_host_reset_handler = qla1280_eh_adapter_reset,
.bios_param = qla1280_biosparam_old,
- .proc_info = qla1280_proc_info_old,
.can_queue = 0xfffff,
.this_id = -1,
.sg_tablesize = SG_ALL,
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 22bdb841c8e47..b5863d8769e03 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -1847,13 +1847,13 @@ qla2x00_iospace_config(scsi_qla_host_t *ha)
if (pio_len < MIN_IOBASE_LEN) {
qla_printk(KERN_WARNING, ha,
"Invalid PCI I/O region size (%s)...\n",
- ha->pdev->slot_name);
+ pci_name(ha->pdev));
pio = 0;
}
} else {
qla_printk(KERN_WARNING, ha,
"region #0 not a PIO resource (%s)...\n",
- ha->pdev->slot_name);
+ pci_name(ha->pdev));
pio = 0;
}
@@ -1865,20 +1865,20 @@ qla2x00_iospace_config(scsi_qla_host_t *ha)
if (!(mmio_flags & IORESOURCE_MEM)) {
qla_printk(KERN_ERR, ha,
"region #0 not an MMIO resource (%s), aborting\n",
- ha->pdev->slot_name);
+ pci_name(ha->pdev));
goto iospace_error_exit;
}
if (mmio_len < MIN_IOBASE_LEN) {
qla_printk(KERN_ERR, ha,
"Invalid PCI mem region size (%s), aborting\n",
- ha->pdev->slot_name);
+ pci_name(ha->pdev));
goto iospace_error_exit;
}
if (pci_request_regions(ha->pdev, ha->brd_info->drv_name)) {
qla_printk(KERN_WARNING, ha,
- "Failed to reserve PIO/MMIO regions (%s)\n",
- ha->pdev->slot_name);
+ "Failed to reserve PIO/MMIO regions (%s)\n",
+ pci_name(ha->pdev));
goto iospace_error_exit;
}
@@ -1888,7 +1888,7 @@ qla2x00_iospace_config(scsi_qla_host_t *ha)
ha->iobase = ioremap(mmio, MIN_IOBASE_LEN);
if (!ha->iobase) {
qla_printk(KERN_ERR, ha,
- "cannot remap MMIO (%s), aborting\n", ha->pdev->slot_name);
+ "cannot remap MMIO (%s), aborting\n", pci_name(ha->pdev));
goto iospace_error_exit;
}
diff --git a/drivers/scsi/qlogicfc.c b/drivers/scsi/qlogicfc.c
index 3a192e3c911b4..24c1174b0c2f3 100644
--- a/drivers/scsi/qlogicfc.c
+++ b/drivers/scsi/qlogicfc.c
@@ -71,7 +71,25 @@
#define pci64_dma_build(hi,lo) \
((dma_addr_t)(((u64)(lo))|(((u64)(hi))<<32)))
-#include "qlogicfc.h"
+/*
+ * With the qlogic interface, every queue slot can hold a SCSI
+ * command with up to 2 scatter/gather entries. If we need more
+ * than 2 entries, continuation entries can be used that hold
+ * another 5 entries each. Unlike for other drivers, this means
+ * that the maximum number of scatter/gather entries we can
+ * support at any given time is a function of the number of queue
+ * slots available. That is, host->can_queue and host->sg_tablesize
+ * are dynamic and _not_ independent. This all works fine because
+ * requests are queued serially and the scatter/gather limit is
+ * determined for each queue request anew.
+ */
+
+#define DATASEGS_PER_COMMAND 2
+#define DATASEGS_PER_CONT 5
+
+#define QLOGICFC_REQ_QUEUE_LEN 255 /* must be power of two - 1 */
+#define QLOGICFC_MAX_SG(ql) (DATASEGS_PER_COMMAND + (((ql) > 0) ? DATASEGS_PER_CONT*((ql) - 1) : 0))
+#define QLOGICFC_CMD_PER_LUN 8
/* Configuration section **************************************************** */
@@ -693,7 +711,7 @@ static inline void isp2x00_disable_irqs(struct Scsi_Host *host)
}
-int isp2x00_detect(Scsi_Host_Template * tmpt)
+static int isp2x00_detect(Scsi_Host_Template * tmpt)
{
int hosts = 0;
unsigned long wait_time;
@@ -1083,7 +1101,7 @@ int isp2x00_init_fabric(struct Scsi_Host *host, struct id_name_map *port_db, int
#endif /* ISP2x00_FABRIC */
-int isp2x00_release(struct Scsi_Host *host)
+static int isp2x00_release(struct Scsi_Host *host)
{
struct isp2x00_hostdata *hostdata;
dma_addr_t busaddr;
@@ -1107,7 +1125,7 @@ int isp2x00_release(struct Scsi_Host *host)
}
-const char *isp2x00_info(struct Scsi_Host *host)
+static const char *isp2x00_info(struct Scsi_Host *host)
{
static char buf[80];
struct isp2x00_hostdata *hostdata;
@@ -1132,7 +1150,7 @@ const char *isp2x00_info(struct Scsi_Host *host)
* interrupt handler may call this routine as part of
* request-completion handling).
*/
-int isp2x00_queuecommand(Scsi_Cmnd * Cmnd, void (*done) (Scsi_Cmnd *))
+static int isp2x00_queuecommand(Scsi_Cmnd * Cmnd, void (*done) (Scsi_Cmnd *))
{
int i, sg_count, n, num_free;
u_int in_ptr, out_ptr;
@@ -1697,7 +1715,7 @@ static int isp2x00_return_status(Scsi_Cmnd *Cmnd, struct Status_Entry *sts)
}
-int isp2x00_abort(Scsi_Cmnd * Cmnd)
+static int isp2x00_abort(Scsi_Cmnd * Cmnd)
{
u_short param[8];
int i;
@@ -1755,37 +1773,7 @@ int isp2x00_abort(Scsi_Cmnd * Cmnd)
}
-int isp2x00_reset(Scsi_Cmnd * Cmnd, unsigned int reset_flags)
-{
- u_short param[8];
- struct Scsi_Host *host;
- struct isp2x00_hostdata *hostdata;
- int return_status = SCSI_RESET_SUCCESS;
-
- ENTER("isp2x00_reset");
-
- host = Cmnd->device->host;
- hostdata = (struct isp2x00_hostdata *) host->hostdata;
- param[0] = MBOX_BUS_RESET;
- param[1] = 3;
-
- isp2x00_disable_irqs(host);
-
- isp2x00_mbox_command(host, param);
-
- if (param[0] != MBOX_COMMAND_COMPLETE) {
- printk("qlogicfc%d : scsi bus reset failure: %x\n", hostdata->host_id, param[0]);
- return_status = SCSI_RESET_ERROR;
- }
- isp2x00_enable_irqs(host);
-
- LEAVE("isp2x00_reset");
-
- return return_status;
-}
-
-
-int isp2x00_biosparam(struct scsi_device *sdev, struct block_device *n,
+static int isp2x00_biosparam(struct scsi_device *sdev, struct block_device *n,
sector_t capacity, int ip[])
{
int size = capacity;
diff --git a/drivers/scsi/qlogicfc.h b/drivers/scsi/qlogicfc.h
deleted file mode 100644
index b7f470896e45a..0000000000000
--- a/drivers/scsi/qlogicfc.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * QLogic ISP2x00 SCSI-FCP
- *
- * Written by Erik H. Moe, ehm@cris.com
- * Copyright 1995, Erik H. Moe
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-/* Renamed and updated to 1.3.x by Michael Griffith <grif@cs.ucr.edu> */
-
-/* This is a version of the isp1020 driver which was modified by
- * Chris Loveland <cwl@iol.unh.edu> to support the isp2x00
- */
-
-
-/*
- * $Date: 1995/09/22 02:32:56 $
- * $Revision: 0.5 $
- *
- * $Log: isp1020.h,v $
- * Revision 0.5 1995/09/22 02:32:56 root
- * do auto request sense
- *
- * Revision 0.4 1995/08/07 04:48:28 root
- * supply firmware with driver.
- * numerous bug fixes/general cleanup of code.
- *
- * Revision 0.3 1995/07/16 16:17:16 root
- * added reset/abort code.
- *
- * Revision 0.2 1995/06/29 03:19:43 root
- * fixed biosparam.
- * added queue protocol.
- *
- * Revision 0.1 1995/06/25 01:56:13 root
- * Initial release.
- *
- */
-
-#ifndef _QLOGICFC_H
-#define _QLOGICFC_H
-
-/*
- * With the qlogic interface, every queue slot can hold a SCSI
- * command with up to 2 scatter/gather entries. If we need more
- * than 2 entries, continuation entries can be used that hold
- * another 5 entries each. Unlike for other drivers, this means
- * that the maximum number of scatter/gather entries we can
- * support at any given time is a function of the number of queue
- * slots available. That is, host->can_queue and host->sg_tablesize
- * are dynamic and _not_ independent. This all works fine because
- * requests are queued serially and the scatter/gather limit is
- * determined for each queue request anew.
- */
-
-#define DATASEGS_PER_COMMAND 2
-#define DATASEGS_PER_CONT 5
-
-#define QLOGICFC_REQ_QUEUE_LEN 255 /* must be power of two - 1 */
-#define QLOGICFC_MAX_SG(ql) (DATASEGS_PER_COMMAND + (((ql) > 0) ? DATASEGS_PER_CONT*((ql) - 1) : 0))
-#define QLOGICFC_CMD_PER_LUN 8
-
-int isp2x00_detect(Scsi_Host_Template *);
-int isp2x00_release(struct Scsi_Host *);
-const char * isp2x00_info(struct Scsi_Host *);
-int isp2x00_queuecommand(Scsi_Cmnd *, void (* done)(Scsi_Cmnd *));
-int isp2x00_abort(Scsi_Cmnd *);
-int isp2x00_reset(Scsi_Cmnd *, unsigned int);
-int isp2x00_biosparam(struct scsi_device *, struct block_device *,
- sector_t, int[]);
-#endif /* _QLOGICFC_H */
diff --git a/drivers/scsi/qlogicisp.c b/drivers/scsi/qlogicisp.c
index aa80193ce2cac..71d597a9b0b00 100644
--- a/drivers/scsi/qlogicisp.c
+++ b/drivers/scsi/qlogicisp.c
@@ -37,7 +37,21 @@
#include <asm/byteorder.h>
#include "scsi.h"
#include <scsi/scsi_host.h>
-#include "qlogicisp.h"
+
+/*
+ * With the qlogic interface, every queue slot can hold a SCSI
+ * command with up to 4 scatter/gather entries. If we need more
+ * than 4 entries, continuation entries can be used that hold
+ * another 7 entries each. Unlike for other drivers, this means
+ * that the maximum number of scatter/gather entries we can
+ * support at any given time is a function of the number of queue
+ * slots available. That is, host->can_queue and host->sg_tablesize
+ * are dynamic and _not_ independent. This all works fine because
+ * requests are queued serially and the scatter/gather limit is
+ * determined for each queue request anew.
+ */
+#define QLOGICISP_REQ_QUEUE_LEN 63 /* must be power of two - 1 */
+#define QLOGICISP_MAX_SG(ql) (4 + ((ql) > 0) ? 7*((ql) - 1) : 0)
/* Configuration section *****************************************************/
@@ -655,7 +669,7 @@ static inline void isp1020_disable_irqs(struct Scsi_Host *host)
}
-int isp1020_detect(Scsi_Host_Template *tmpt)
+static int isp1020_detect(Scsi_Host_Template *tmpt)
{
int hosts = 0;
struct Scsi_Host *host;
@@ -736,7 +750,7 @@ int isp1020_detect(Scsi_Host_Template *tmpt)
}
-int isp1020_release(struct Scsi_Host *host)
+static int isp1020_release(struct Scsi_Host *host)
{
struct isp1020_hostdata *hostdata;
@@ -757,7 +771,7 @@ int isp1020_release(struct Scsi_Host *host)
}
-const char *isp1020_info(struct Scsi_Host *host)
+static const char *isp1020_info(struct Scsi_Host *host)
{
static char buf[80];
struct isp1020_hostdata *hostdata;
@@ -783,7 +797,7 @@ const char *isp1020_info(struct Scsi_Host *host)
* interrupt handler may call this routine as part of
* request-completion handling).
*/
-int isp1020_queuecommand(Scsi_Cmnd *Cmnd, void (*done)(Scsi_Cmnd *))
+static int isp1020_queuecommand(Scsi_Cmnd *Cmnd, void (*done)(Scsi_Cmnd *))
{
int i, n, num_free;
u_int in_ptr, out_ptr;
@@ -1161,80 +1175,7 @@ static int isp1020_return_status(struct Status_Entry *sts)
}
-int isp1020_abort(Scsi_Cmnd *Cmnd)
-{
- u_short param[6];
- struct Scsi_Host *host;
- struct isp1020_hostdata *hostdata;
- int return_status = SCSI_ABORT_SUCCESS;
- u_int cmd_cookie;
- int i;
-
- ENTER("isp1020_abort");
-
- host = Cmnd->device->host;
- hostdata = (struct isp1020_hostdata *) host->hostdata;
-
- for (i = 0; i < QLOGICISP_REQ_QUEUE_LEN + 1; i++)
- if (hostdata->cmd_slots[i] == Cmnd)
- break;
- cmd_cookie = i;
-
- isp1020_disable_irqs(host);
-
- param[0] = MBOX_ABORT;
- param[1] = (((u_short) Cmnd->device->id) << 8) | Cmnd->device->lun;
- param[2] = cmd_cookie >> 16;
- param[3] = cmd_cookie & 0xffff;
-
- isp1020_mbox_command(host, param);
-
- if (param[0] != MBOX_COMMAND_COMPLETE) {
- printk("qlogicisp : scsi abort failure: %x\n", param[0]);
- return_status = SCSI_ABORT_ERROR;
- }
-
- isp1020_enable_irqs(host);
-
- LEAVE("isp1020_abort");
-
- return return_status;
-}
-
-
-int isp1020_reset(Scsi_Cmnd *Cmnd, unsigned int reset_flags)
-{
- u_short param[6];
- struct Scsi_Host *host;
- struct isp1020_hostdata *hostdata;
- int return_status = SCSI_RESET_SUCCESS;
-
- ENTER("isp1020_reset");
-
- host = Cmnd->device->host;
- hostdata = (struct isp1020_hostdata *) host->hostdata;
-
- param[0] = MBOX_BUS_RESET;
- param[1] = hostdata->host_param.bus_reset_delay;
-
- isp1020_disable_irqs(host);
-
- isp1020_mbox_command(host, param);
-
- if (param[0] != MBOX_COMMAND_COMPLETE) {
- printk("qlogicisp : scsi bus reset failure: %x\n", param[0]);
- return_status = SCSI_RESET_ERROR;
- }
-
- isp1020_enable_irqs(host);
-
- LEAVE("isp1020_reset");
-
- return return_status;
-}
-
-
-int isp1020_biosparam(struct scsi_device *sdev, struct block_device *n,
+static int isp1020_biosparam(struct scsi_device *sdev, struct block_device *n,
sector_t capacity, int ip[])
{
int size = capacity;
diff --git a/drivers/scsi/qlogicisp.h b/drivers/scsi/qlogicisp.h
deleted file mode 100644
index d3b263b75863e..0000000000000
--- a/drivers/scsi/qlogicisp.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * QLogic ISP1020 Intelligent SCSI Processor Driver (PCI)
- * Written by Erik H. Moe, ehm@cris.com
- * Copyright 1995, Erik H. Moe
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-
-/* Renamed and updated to 1.3.x by Michael Griffith <grif@cs.ucr.edu> */
-
-/*
- * $Date: 1995/09/22 02:32:56 $
- * $Revision: 0.5 $
- *
- * $Log: isp1020.h,v $
- * Revision 0.5 1995/09/22 02:32:56 root
- * do auto request sense
- *
- * Revision 0.4 1995/08/07 04:48:28 root
- * supply firmware with driver.
- * numerous bug fixes/general cleanup of code.
- *
- * Revision 0.3 1995/07/16 16:17:16 root
- * added reset/abort code.
- *
- * Revision 0.2 1995/06/29 03:19:43 root
- * fixed biosparam.
- * added queue protocol.
- *
- * Revision 0.1 1995/06/25 01:56:13 root
- * Initial release.
- *
- */
-
-#ifndef _QLOGICISP_H
-#define _QLOGICISP_H
-
-/*
- * With the qlogic interface, every queue slot can hold a SCSI
- * command with up to 4 scatter/gather entries. If we need more
- * than 4 entries, continuation entries can be used that hold
- * another 7 entries each. Unlike for other drivers, this means
- * that the maximum number of scatter/gather entries we can
- * support at any given time is a function of the number of queue
- * slots available. That is, host->can_queue and host->sg_tablesize
- * are dynamic and _not_ independent. This all works fine because
- * requests are queued serially and the scatter/gather limit is
- * determined for each queue request anew.
- */
-#define QLOGICISP_REQ_QUEUE_LEN 63 /* must be power of two - 1 */
-#define QLOGICISP_MAX_SG(ql) (4 + ((ql) > 0) ? 7*((ql) - 1) : 0)
-
-int isp1020_detect(Scsi_Host_Template *);
-int isp1020_release(struct Scsi_Host *);
-const char * isp1020_info(struct Scsi_Host *);
-int isp1020_queuecommand(Scsi_Cmnd *, void (* done)(Scsi_Cmnd *));
-int isp1020_abort(Scsi_Cmnd *);
-int isp1020_reset(Scsi_Cmnd *, unsigned int);
-int isp1020_biosparam(struct scsi_device *, struct block_device *,
- sector_t, int[]);
-#endif /* _QLOGICISP_H */
diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c
index 51c6988f41290..69009f853a491 100644
--- a/drivers/scsi/sata_nv.c
+++ b/drivers/scsi/sata_nv.c
@@ -99,7 +99,8 @@
#define NV_MCP_SATA_CFG_20_SATA_SPACE_EN 0x04
static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
-irqreturn_t nv_interrupt (int irq, void *dev_instance, struct pt_regs *regs);
+static irqreturn_t nv_interrupt (int irq, void *dev_instance,
+ struct pt_regs *regs);
static u32 nv_scr_read (struct ata_port *ap, unsigned int sc_reg);
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);
@@ -205,6 +206,7 @@ static 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 struct ata_port_operations nv_ops = {
@@ -217,6 +219,8 @@ static struct ata_port_operations nv_ops = {
.phy_reset = sata_phy_reset,
.bmdma_setup = ata_bmdma_setup,
.bmdma_start = ata_bmdma_start,
+ .bmdma_stop = ata_bmdma_stop,
+ .bmdma_status = ata_bmdma_status,
.qc_prep = ata_qc_prep,
.qc_issue = ata_qc_issue_prot,
.eng_timeout = ata_eng_timeout,
@@ -255,7 +259,8 @@ MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE(pci, nv_pci_tbl);
MODULE_VERSION(DRV_VERSION);
-irqreturn_t nv_interrupt (int irq, void *dev_instance, struct pt_regs *regs)
+static irqreturn_t nv_interrupt (int irq, void *dev_instance,
+ struct pt_regs *regs)
{
struct ata_host_set *host_set = dev_instance;
struct nv_host *host = host_set->private_data;
@@ -332,6 +337,7 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
struct nv_host *host;
struct ata_port_info *ppi;
struct ata_probe_ent *probe_ent;
+ int pci_dev_busy = 0;
int rc;
u32 bar;
@@ -350,8 +356,10 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
goto err_out;
rc = pci_request_regions(pdev, DRV_NAME);
- if (rc)
+ if (rc) {
+ pci_dev_busy = 1;
goto err_out_disable;
+ }
rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
if (rc)
@@ -427,7 +435,8 @@ err_out_free_ent:
err_out_regions:
pci_release_regions(pdev);
err_out_disable:
- pci_disable_device(pdev);
+ if (!pci_dev_busy)
+ pci_disable_device(pdev);
err_out:
return rc;
}
diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c
index 57e7df23d672c..19a13e3590f4e 100644
--- a/drivers/scsi/sata_promise.c
+++ b/drivers/scsi/sata_promise.c
@@ -102,6 +102,7 @@ static 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 struct ata_port_operations pdc_ata_ops = {
@@ -556,6 +557,7 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
unsigned long base;
void *mmio_base;
unsigned int board_idx = (unsigned int) ent->driver_data;
+ int pci_dev_busy = 0;
int rc;
if (!printed_version++)
@@ -570,8 +572,10 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
return rc;
rc = pci_request_regions(pdev, DRV_NAME);
- if (rc)
+ if (rc) {
+ pci_dev_busy = 1;
goto err_out;
+ }
rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
if (rc)
@@ -650,7 +654,8 @@ err_out_free_ent:
err_out_regions:
pci_release_regions(pdev);
err_out:
- pci_disable_device(pdev);
+ if (!pci_dev_busy)
+ pci_disable_device(pdev);
return rc;
}
diff --git a/drivers/scsi/sata_qstor.c b/drivers/scsi/sata_qstor.c
new file mode 100644
index 0000000000000..dfd3621047171
--- /dev/null
+++ b/drivers/scsi/sata_qstor.c
@@ -0,0 +1,718 @@
+/*
+ * sata_qstor.c - Pacific Digital Corporation QStor SATA
+ *
+ * Maintained by: Mark Lord <mlord@pobox.com>
+ *
+ * Copyright 2005 Pacific Digital Corporation.
+ * (OSL/GPL code release authorized by Jalil Fadavi).
+ *
+ * The contents of this file are subject to the Open
+ * Software License version 1.1 that can be found at
+ * http://www.opensource.org/licenses/osl-1.1.txt and is included herein
+ * by reference.
+ *
+ * Alternatively, the contents of this file may be used under the terms
+ * of the GNU General Public License version 2 (the "GPL") as distributed
+ * in the kernel source COPYING file, in which case the provisions of
+ * the GPL are applicable instead of the above. If you wish to allow
+ * the use of your version of this file only under the terms of the
+ * GPL and not to allow others to use your version of this file under
+ * the OSL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the GPL.
+ * If you do not delete the provisions above, a recipient may use your
+ * version of this file under either the OSL or the GPL.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include "scsi.h"
+#include <scsi/scsi_host.h>
+#include <asm/io.h>
+#include <linux/libata.h>
+
+#define DRV_NAME "sata_qstor"
+#define DRV_VERSION "0.04"
+
+enum {
+ QS_PORTS = 4,
+ QS_MAX_PRD = LIBATA_MAX_PRD,
+ QS_CPB_ORDER = 6,
+ QS_CPB_BYTES = (1 << QS_CPB_ORDER),
+ QS_PRD_BYTES = QS_MAX_PRD * 16,
+ QS_PKT_BYTES = QS_CPB_BYTES + QS_PRD_BYTES,
+
+ QS_DMA_BOUNDARY = ~0UL,
+
+ /* global register offsets */
+ QS_HCF_CNFG3 = 0x0003, /* host configuration offset */
+ QS_HID_HPHY = 0x0004, /* host physical interface info */
+ QS_HCT_CTRL = 0x00e4, /* global interrupt mask offset */
+ QS_HST_SFF = 0x0100, /* host status fifo offset */
+ QS_HVS_SERD3 = 0x0393, /* PHY enable offset */
+
+ /* global control bits */
+ QS_HPHY_64BIT = (1 << 1), /* 64-bit bus detected */
+ QS_CNFG3_GSRST = 0x01, /* global chip reset */
+ QS_SERD3_PHY_ENA = 0xf0, /* PHY detection ENAble*/
+
+ /* per-channel register offsets */
+ QS_CCF_CPBA = 0x0710, /* chan CPB base address */
+ QS_CCF_CSEP = 0x0718, /* chan CPB separation factor */
+ QS_CFC_HUFT = 0x0800, /* host upstream fifo threshold */
+ QS_CFC_HDFT = 0x0804, /* host downstream fifo threshold */
+ QS_CFC_DUFT = 0x0808, /* dev upstream fifo threshold */
+ QS_CFC_DDFT = 0x080c, /* dev downstream fifo threshold */
+ QS_CCT_CTR0 = 0x0900, /* chan control-0 offset */
+ QS_CCT_CTR1 = 0x0901, /* chan control-1 offset */
+ QS_CCT_CFF = 0x0a00, /* chan command fifo offset */
+
+ /* channel control bits */
+ QS_CTR0_REG = (1 << 1), /* register mode (vs. pkt mode) */
+ QS_CTR0_CLER = (1 << 2), /* clear channel errors */
+ QS_CTR1_RDEV = (1 << 1), /* sata phy/comms reset */
+ QS_CTR1_RCHN = (1 << 4), /* reset channel logic */
+ QS_CCF_RUN_PKT = 0x107, /* RUN a new dma PKT */
+
+ /* pkt sub-field headers */
+ QS_HCB_HDR = 0x01, /* Host Control Block header */
+ QS_DCB_HDR = 0x02, /* Device Control Block header */
+
+ /* pkt HCB flag bits */
+ QS_HF_DIRO = (1 << 0), /* data DIRection Out */
+ QS_HF_DAT = (1 << 3), /* DATa pkt */
+ QS_HF_IEN = (1 << 4), /* Interrupt ENable */
+ QS_HF_VLD = (1 << 5), /* VaLiD pkt */
+
+ /* pkt DCB flag bits */
+ QS_DF_PORD = (1 << 2), /* Pio OR Dma */
+ QS_DF_ELBA = (1 << 3), /* Extended LBA (lba48) */
+
+ /* PCI device IDs */
+ board_2068_idx = 0, /* QStor 4-port SATA/RAID */
+};
+
+typedef enum { qs_state_idle, qs_state_pkt, qs_state_mmio } qs_state_t;
+
+struct qs_port_priv {
+ u8 *pkt;
+ dma_addr_t pkt_dma;
+ qs_state_t state;
+};
+
+static u32 qs_scr_read (struct ata_port *ap, unsigned int sc_reg);
+static void qs_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
+static int qs_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
+static irqreturn_t qs_intr (int irq, void *dev_instance, struct pt_regs *regs);
+static int qs_port_start(struct ata_port *ap);
+static void qs_host_stop(struct ata_host_set *host_set);
+static void qs_port_stop(struct ata_port *ap);
+static void qs_phy_reset(struct ata_port *ap);
+static void qs_qc_prep(struct ata_queued_cmd *qc);
+static int qs_qc_issue(struct ata_queued_cmd *qc);
+static int qs_check_atapi_dma(struct ata_queued_cmd *qc);
+static void qs_bmdma_stop(struct ata_port *ap);
+static u8 qs_bmdma_status(struct ata_port *ap);
+static void qs_irq_clear(struct ata_port *ap);
+static void qs_eng_timeout(struct ata_port *ap);
+
+static Scsi_Host_Template qs_ata_sht = {
+ .module = THIS_MODULE,
+ .name = DRV_NAME,
+ .ioctl = ata_scsi_ioctl,
+ .queuecommand = ata_scsi_queuecmd,
+ .eh_strategy_handler = ata_scsi_error,
+ .can_queue = ATA_DEF_QUEUE,
+ .this_id = ATA_SHT_THIS_ID,
+ .sg_tablesize = QS_MAX_PRD,
+ .max_sectors = ATA_MAX_SECTORS,
+ .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+ .emulated = ATA_SHT_EMULATED,
+ //FIXME .use_clustering = ATA_SHT_USE_CLUSTERING,
+ .use_clustering = ENABLE_CLUSTERING,
+ .proc_name = DRV_NAME,
+ .dma_boundary = QS_DMA_BOUNDARY,
+ .slave_configure = ata_scsi_slave_config,
+ .bios_param = ata_std_bios_param,
+};
+
+static struct ata_port_operations qs_ata_ops = {
+ .port_disable = ata_port_disable,
+ .tf_load = ata_tf_load,
+ .tf_read = ata_tf_read,
+ .check_status = ata_check_status,
+ .check_atapi_dma = qs_check_atapi_dma,
+ .exec_command = ata_exec_command,
+ .dev_select = ata_std_dev_select,
+ .phy_reset = qs_phy_reset,
+ .qc_prep = qs_qc_prep,
+ .qc_issue = qs_qc_issue,
+ .eng_timeout = qs_eng_timeout,
+ .irq_handler = qs_intr,
+ .irq_clear = qs_irq_clear,
+ .scr_read = qs_scr_read,
+ .scr_write = qs_scr_write,
+ .port_start = qs_port_start,
+ .port_stop = qs_port_stop,
+ .host_stop = qs_host_stop,
+ .bmdma_stop = qs_bmdma_stop,
+ .bmdma_status = qs_bmdma_status,
+};
+
+static struct ata_port_info qs_port_info[] = {
+ /* board_2068_idx */
+ {
+ .sht = &qs_ata_sht,
+ .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+ ATA_FLAG_SATA_RESET |
+ //FIXME ATA_FLAG_SRST |
+ ATA_FLAG_MMIO,
+ .pio_mask = 0x10, /* pio4 */
+ .udma_mask = 0x7f, /* udma0-6 */
+ .port_ops = &qs_ata_ops,
+ },
+};
+
+static struct pci_device_id qs_ata_pci_tbl[] = {
+ { PCI_VENDOR_ID_PDC, 0x2068, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ board_2068_idx },
+
+ { } /* terminate list */
+};
+
+static struct pci_driver qs_ata_pci_driver = {
+ .name = DRV_NAME,
+ .id_table = qs_ata_pci_tbl,
+ .probe = qs_ata_init_one,
+ .remove = ata_pci_remove_one,
+};
+
+static int qs_check_atapi_dma(struct ata_queued_cmd *qc)
+{
+ return 1; /* ATAPI DMA not supported */
+}
+
+static void qs_bmdma_stop(struct ata_port *ap)
+{
+ /* nothing */
+}
+
+static u8 qs_bmdma_status(struct ata_port *ap)
+{
+ return 0;
+}
+
+static void qs_irq_clear(struct ata_port *ap)
+{
+ /* nothing */
+}
+
+static inline void qs_enter_reg_mode(struct ata_port *ap)
+{
+ u8 __iomem *chan = ap->host_set->mmio_base + (ap->port_no * 0x4000);
+
+ writeb(QS_CTR0_REG, chan + QS_CCT_CTR0);
+ readb(chan + QS_CCT_CTR0); /* flush */
+}
+
+static inline void qs_reset_channel_logic(struct ata_port *ap)
+{
+ u8 __iomem *chan = ap->host_set->mmio_base + (ap->port_no * 0x4000);
+
+ writeb(QS_CTR1_RCHN, chan + QS_CCT_CTR1);
+ readb(chan + QS_CCT_CTR0); /* flush */
+ qs_enter_reg_mode(ap);
+}
+
+static void qs_phy_reset(struct ata_port *ap)
+{
+ struct qs_port_priv *pp = ap->private_data;
+
+ pp->state = qs_state_idle;
+ qs_reset_channel_logic(ap);
+ sata_phy_reset(ap);
+}
+
+static void qs_eng_timeout(struct ata_port *ap)
+{
+ struct qs_port_priv *pp = ap->private_data;
+
+ if (pp->state != qs_state_idle) /* healthy paranoia */
+ pp->state = qs_state_mmio;
+ qs_reset_channel_logic(ap);
+ ata_eng_timeout(ap);
+}
+
+static u32 qs_scr_read (struct ata_port *ap, unsigned int sc_reg)
+{
+ if (sc_reg > SCR_CONTROL)
+ return ~0U;
+ return readl((void __iomem *)(ap->ioaddr.scr_addr + (sc_reg * 8)));
+}
+
+static void qs_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
+{
+ if (sc_reg > SCR_CONTROL)
+ return;
+ writel(val, (void __iomem *)(ap->ioaddr.scr_addr + (sc_reg * 8)));
+}
+
+static void qs_fill_sg(struct ata_queued_cmd *qc)
+{
+ struct scatterlist *sg = qc->sg;
+ struct ata_port *ap = qc->ap;
+ struct qs_port_priv *pp = ap->private_data;
+ unsigned int nelem;
+ u8 *prd = pp->pkt + QS_CPB_BYTES;
+
+ assert(sg != NULL);
+ assert(qc->n_elem > 0);
+
+ for (nelem = 0; nelem < qc->n_elem; nelem++,sg++) {
+ u64 addr;
+ u32 len;
+
+ addr = sg_dma_address(sg);
+ *(__le64 *)prd = cpu_to_le64(addr);
+ prd += sizeof(u64);
+
+ len = sg_dma_len(sg);
+ *(__le32 *)prd = cpu_to_le32(len);
+ prd += sizeof(u64);
+
+ VPRINTK("PRD[%u] = (0x%llX, 0x%X)\n", nelem,
+ (unsigned long long)addr, len);
+ }
+}
+
+static void qs_qc_prep(struct ata_queued_cmd *qc)
+{
+ struct qs_port_priv *pp = qc->ap->private_data;
+ u8 dflags = QS_DF_PORD, *buf = pp->pkt;
+ u8 hflags = QS_HF_DAT | QS_HF_IEN | QS_HF_VLD;
+ u64 addr;
+
+ VPRINTK("ENTER\n");
+
+ qs_enter_reg_mode(qc->ap);
+ if (qc->tf.protocol != ATA_PROT_DMA) {
+ ata_qc_prep(qc);
+ return;
+ }
+
+ qs_fill_sg(qc);
+
+ if ((qc->tf.flags & ATA_TFLAG_WRITE))
+ hflags |= QS_HF_DIRO;
+ if ((qc->tf.flags & ATA_TFLAG_LBA48))
+ dflags |= QS_DF_ELBA;
+
+ /* host control block (HCB) */
+ buf[ 0] = QS_HCB_HDR;
+ buf[ 1] = hflags;
+ *(__le32 *)(&buf[ 4]) = cpu_to_le32(qc->nsect * ATA_SECT_SIZE);
+ *(__le32 *)(&buf[ 8]) = cpu_to_le32(qc->n_elem);
+ addr = ((u64)pp->pkt_dma) + QS_CPB_BYTES;
+ *(__le64 *)(&buf[16]) = cpu_to_le64(addr);
+
+ /* device control block (DCB) */
+ buf[24] = QS_DCB_HDR;
+ buf[28] = dflags;
+
+ /* frame information structure (FIS) */
+ ata_tf_to_fis(&qc->tf, &buf[32], 0);
+}
+
+static inline void qs_packet_start(struct ata_queued_cmd *qc)
+{
+ struct ata_port *ap = qc->ap;
+ u8 __iomem *chan = ap->host_set->mmio_base + (ap->port_no * 0x4000);
+
+ VPRINTK("ENTER, ap %p\n", ap);
+
+ writeb(QS_CTR0_CLER, chan + QS_CCT_CTR0);
+ wmb(); /* flush PRDs and pkt to memory */
+ writel(QS_CCF_RUN_PKT, chan + QS_CCT_CFF);
+ readl(chan + QS_CCT_CFF); /* flush */
+}
+
+static int qs_qc_issue(struct ata_queued_cmd *qc)
+{
+ struct qs_port_priv *pp = qc->ap->private_data;
+
+ switch (qc->tf.protocol) {
+ case ATA_PROT_DMA:
+
+ pp->state = qs_state_pkt;
+ qs_packet_start(qc);
+ return 0;
+
+ case ATA_PROT_ATAPI_DMA:
+ BUG();
+ break;
+
+ default:
+ break;
+ }
+
+ pp->state = qs_state_mmio;
+ return ata_qc_issue_prot(qc);
+}
+
+static inline unsigned int qs_intr_pkt(struct ata_host_set *host_set)
+{
+ unsigned int handled = 0;
+ u8 sFFE;
+ u8 __iomem *mmio_base = host_set->mmio_base;
+
+ do {
+ u32 sff0 = readl(mmio_base + QS_HST_SFF);
+ u32 sff1 = readl(mmio_base + QS_HST_SFF + 4);
+ u8 sEVLD = (sff1 >> 30) & 0x01; /* valid flag */
+ sFFE = sff1 >> 31; /* empty flag */
+
+ if (sEVLD) {
+ u8 sDST = sff0 >> 16; /* dev status */
+ u8 sHST = sff1 & 0x3f; /* host status */
+ unsigned int port_no = (sff1 >> 8) & 0x03;
+ struct ata_port *ap = host_set->ports[port_no];
+
+ DPRINTK("SFF=%08x%08x: sCHAN=%u sHST=%d sDST=%02x\n",
+ sff1, sff0, port_no, sHST, sDST);
+ handled = 1;
+ if (ap && (!(ap->flags & ATA_FLAG_PORT_DISABLED))) {
+ struct ata_queued_cmd *qc;
+ struct qs_port_priv *pp = ap->private_data;
+ if (!pp || pp->state != qs_state_pkt)
+ continue;
+ qc = ata_qc_from_tag(ap, ap->active_tag);
+ if (qc && (!(qc->tf.ctl & ATA_NIEN))) {
+ switch (sHST) {
+ case 0: /* sucessful CPB */
+ case 3: /* device error */
+ pp->state = qs_state_idle;
+ qs_enter_reg_mode(qc->ap);
+ ata_qc_complete(qc, sDST);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+ } while (!sFFE);
+ return handled;
+}
+
+static inline unsigned int qs_intr_mmio(struct ata_host_set *host_set)
+{
+ unsigned int handled = 0, port_no;
+
+ for (port_no = 0; port_no < host_set->n_ports; ++port_no) {
+ struct ata_port *ap;
+ ap = host_set->ports[port_no];
+ if (ap && (!(ap->flags & ATA_FLAG_PORT_DISABLED))) {
+ struct ata_queued_cmd *qc;
+ struct qs_port_priv *pp = ap->private_data;
+ if (!pp || pp->state != qs_state_mmio)
+ continue;
+ qc = ata_qc_from_tag(ap, ap->active_tag);
+ if (qc && (!(qc->tf.ctl & ATA_NIEN))) {
+
+ /* check main status, clearing INTRQ */
+ u8 status = ata_chk_status(ap);
+ if ((status & ATA_BUSY))
+ continue;
+ DPRINTK("ata%u: protocol %d (dev_stat 0x%X)\n",
+ ap->id, qc->tf.protocol, status);
+
+ /* complete taskfile transaction */
+ pp->state = qs_state_idle;
+ ata_qc_complete(qc, status);
+ handled = 1;
+ }
+ }
+ }
+ return handled;
+}
+
+static irqreturn_t qs_intr(int irq, void *dev_instance, struct pt_regs *regs)
+{
+ struct ata_host_set *host_set = dev_instance;
+ unsigned int handled = 0;
+
+ VPRINTK("ENTER\n");
+
+ spin_lock(&host_set->lock);
+ handled = qs_intr_pkt(host_set) | qs_intr_mmio(host_set);
+ spin_unlock(&host_set->lock);
+
+ VPRINTK("EXIT\n");
+
+ return IRQ_RETVAL(handled);
+}
+
+static void qs_ata_setup_port(struct ata_ioports *port, unsigned long base)
+{
+ port->cmd_addr =
+ port->data_addr = base + 0x400;
+ port->error_addr =
+ port->feature_addr = base + 0x408; /* hob_feature = 0x409 */
+ port->nsect_addr = base + 0x410; /* hob_nsect = 0x411 */
+ port->lbal_addr = base + 0x418; /* hob_lbal = 0x419 */
+ port->lbam_addr = base + 0x420; /* hob_lbam = 0x421 */
+ port->lbah_addr = base + 0x428; /* hob_lbah = 0x429 */
+ port->device_addr = base + 0x430;
+ port->status_addr =
+ port->command_addr = base + 0x438;
+ port->altstatus_addr =
+ port->ctl_addr = base + 0x440;
+ port->scr_addr = base + 0xc00;
+}
+
+static int qs_port_start(struct ata_port *ap)
+{
+ struct device *dev = ap->host_set->dev;
+ struct qs_port_priv *pp;
+ void __iomem *mmio_base = ap->host_set->mmio_base;
+ void __iomem *chan = mmio_base + (ap->port_no * 0x4000);
+ u64 addr;
+ int rc;
+
+ rc = ata_port_start(ap);
+ if (rc)
+ return rc;
+ qs_enter_reg_mode(ap);
+ pp = kcalloc(1, sizeof(*pp), GFP_KERNEL);
+ if (!pp) {
+ rc = -ENOMEM;
+ goto err_out;
+ }
+ pp->pkt = dma_alloc_coherent(dev, QS_PKT_BYTES, &pp->pkt_dma,
+ GFP_KERNEL);
+ if (!pp->pkt) {
+ rc = -ENOMEM;
+ goto err_out_kfree;
+ }
+ memset(pp->pkt, 0, QS_PKT_BYTES);
+ ap->private_data = pp;
+
+ addr = (u64)pp->pkt_dma;
+ writel((u32) addr, chan + QS_CCF_CPBA);
+ writel((u32)(addr >> 32), chan + QS_CCF_CPBA + 4);
+ return 0;
+
+err_out_kfree:
+ kfree(pp);
+err_out:
+ ata_port_stop(ap);
+ return rc;
+}
+
+static void qs_port_stop(struct ata_port *ap)
+{
+ struct device *dev = ap->host_set->dev;
+ struct qs_port_priv *pp = ap->private_data;
+
+ if (pp != NULL) {
+ ap->private_data = NULL;
+ if (pp->pkt != NULL)
+ dma_free_coherent(dev, QS_PKT_BYTES, pp->pkt,
+ pp->pkt_dma);
+ kfree(pp);
+ }
+ ata_port_stop(ap);
+}
+
+static void qs_host_stop(struct ata_host_set *host_set)
+{
+ void __iomem *mmio_base = host_set->mmio_base;
+
+ writeb(0, mmio_base + QS_HCT_CTRL); /* disable host interrupts */
+ writeb(QS_CNFG3_GSRST, mmio_base + QS_HCF_CNFG3); /* global reset */
+}
+
+static void qs_host_init(unsigned int chip_id, struct ata_probe_ent *pe)
+{
+ void __iomem *mmio_base = pe->mmio_base;
+ unsigned int port_no;
+
+ writeb(0, mmio_base + QS_HCT_CTRL); /* disable host interrupts */
+ writeb(QS_CNFG3_GSRST, mmio_base + QS_HCF_CNFG3); /* global reset */
+
+ /* reset each channel in turn */
+ for (port_no = 0; port_no < pe->n_ports; ++port_no) {
+ u8 __iomem *chan = mmio_base + (port_no * 0x4000);
+ writeb(QS_CTR1_RDEV|QS_CTR1_RCHN, chan + QS_CCT_CTR1);
+ writeb(QS_CTR0_REG, chan + QS_CCT_CTR0);
+ readb(chan + QS_CCT_CTR0); /* flush */
+ }
+ writeb(QS_SERD3_PHY_ENA, mmio_base + QS_HVS_SERD3); /* enable phy */
+
+ for (port_no = 0; port_no < pe->n_ports; ++port_no) {
+ u8 __iomem *chan = mmio_base + (port_no * 0x4000);
+ /* set FIFO depths to same settings as Windows driver */
+ writew(32, chan + QS_CFC_HUFT);
+ writew(32, chan + QS_CFC_HDFT);
+ writew(10, chan + QS_CFC_DUFT);
+ writew( 8, chan + QS_CFC_DDFT);
+ /* set CPB size in bytes, as a power of two */
+ writeb(QS_CPB_ORDER, chan + QS_CCF_CSEP);
+ }
+ writeb(1, mmio_base + QS_HCT_CTRL); /* enable host interrupts */
+}
+
+/*
+ * The QStor understands 64-bit buses, and uses 64-bit fields
+ * for DMA pointers regardless of bus width. We just have to
+ * make sure our DMA masks are set appropriately for whatever
+ * bridge lies between us and the QStor, and then the DMA mapping
+ * code will ensure we only ever "see" appropriate buffer addresses.
+ * If we're 32-bit limited somewhere, then our 64-bit fields will
+ * just end up with zeros in the upper 32-bits, without any special
+ * logic required outside of this routine (below).
+ */
+static int qs_set_dma_masks(struct pci_dev *pdev, void __iomem *mmio_base)
+{
+ u32 bus_info = readl(mmio_base + QS_HID_HPHY);
+ int rc, have_64bit_bus = (bus_info & QS_HPHY_64BIT);
+
+ if (have_64bit_bus &&
+ !pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
+ rc = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
+ if (rc) {
+ rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
+ if (rc) {
+ printk(KERN_ERR DRV_NAME
+ "(%s): 64-bit DMA enable failed\n",
+ pci_name(pdev));
+ return rc;
+ }
+ }
+ } else {
+ rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+ if (rc) {
+ printk(KERN_ERR DRV_NAME
+ "(%s): 32-bit DMA enable failed\n",
+ pci_name(pdev));
+ return rc;
+ }
+ rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
+ if (rc) {
+ printk(KERN_ERR DRV_NAME
+ "(%s): 32-bit consistent DMA enable failed\n",
+ pci_name(pdev));
+ return rc;
+ }
+ }
+ return 0;
+}
+
+static int qs_ata_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ static int printed_version;
+ struct ata_probe_ent *probe_ent = NULL;
+ void __iomem *mmio_base;
+ unsigned int board_idx = (unsigned int) ent->driver_data;
+ int rc, port_no;
+
+ if (!printed_version++)
+ printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n");
+
+ rc = pci_enable_device(pdev);
+ if (rc)
+ return rc;
+
+ rc = pci_request_regions(pdev, DRV_NAME);
+ if (rc)
+ goto err_out;
+
+ if ((pci_resource_flags(pdev, 4) & IORESOURCE_MEM) == 0) {
+ rc = -ENODEV;
+ goto err_out_regions;
+ }
+
+ mmio_base = ioremap(pci_resource_start(pdev, 4),
+ pci_resource_len(pdev, 4));
+ if (mmio_base == NULL) {
+ rc = -ENOMEM;
+ goto err_out_regions;
+ }
+
+ rc = qs_set_dma_masks(pdev, mmio_base);
+ if (rc)
+ goto err_out_iounmap;
+
+ probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
+ if (probe_ent == NULL) {
+ rc = -ENOMEM;
+ goto err_out_iounmap;
+ }
+
+ memset(probe_ent, 0, sizeof(*probe_ent));
+ probe_ent->dev = pci_dev_to_dev(pdev);
+ INIT_LIST_HEAD(&probe_ent->node);
+
+ probe_ent->sht = qs_port_info[board_idx].sht;
+ probe_ent->host_flags = qs_port_info[board_idx].host_flags;
+ probe_ent->pio_mask = qs_port_info[board_idx].pio_mask;
+ probe_ent->mwdma_mask = qs_port_info[board_idx].mwdma_mask;
+ probe_ent->udma_mask = qs_port_info[board_idx].udma_mask;
+ probe_ent->port_ops = qs_port_info[board_idx].port_ops;
+
+ probe_ent->irq = pdev->irq;
+ probe_ent->irq_flags = SA_SHIRQ;
+ probe_ent->mmio_base = mmio_base;
+ probe_ent->n_ports = QS_PORTS;
+
+ for (port_no = 0; port_no < probe_ent->n_ports; ++port_no) {
+ unsigned long chan = (unsigned long)mmio_base +
+ (port_no * 0x4000);
+ qs_ata_setup_port(&probe_ent->port[port_no], chan);
+ }
+
+ pci_set_master(pdev);
+
+ /* initialize adapter */
+ qs_host_init(board_idx, probe_ent);
+
+ rc = ata_device_add(probe_ent);
+ kfree(probe_ent);
+ if (rc != QS_PORTS)
+ goto err_out_iounmap;
+ return 0;
+
+err_out_iounmap:
+ iounmap(mmio_base);
+err_out_regions:
+ pci_release_regions(pdev);
+err_out:
+ pci_disable_device(pdev);
+ return rc;
+}
+
+static int __init qs_ata_init(void)
+{
+ return pci_module_init(&qs_ata_pci_driver);
+}
+
+static void __exit qs_ata_exit(void)
+{
+ pci_unregister_driver(&qs_ata_pci_driver);
+}
+
+MODULE_AUTHOR("Mark Lord");
+MODULE_DESCRIPTION("Pacific Digital Corporation QStor SATA low-level driver");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, qs_ata_pci_tbl);
+MODULE_VERSION(DRV_VERSION);
+
+module_init(qs_ata_init);
+module_exit(qs_ata_exit);
diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c
index 28b7e2cdeafff..f0489dc302a03 100644
--- a/drivers/scsi/sata_sil.c
+++ b/drivers/scsi/sata_sil.c
@@ -38,12 +38,21 @@
#include <linux/libata.h>
#define DRV_NAME "sata_sil"
-#define DRV_VERSION "0.8"
+#define DRV_VERSION "0.9"
enum {
sil_3112 = 0,
sil_3114 = 1,
+ SIL_FIFO_R0 = 0x40,
+ SIL_FIFO_W0 = 0x41,
+ SIL_FIFO_R1 = 0x44,
+ SIL_FIFO_W1 = 0x45,
+ SIL_FIFO_R2 = 0x240,
+ SIL_FIFO_W2 = 0x241,
+ SIL_FIFO_R3 = 0x244,
+ SIL_FIFO_W3 = 0x245,
+
SIL_SYSCFG = 0x48,
SIL_MASK_IDE0_INT = (1 << 22),
SIL_MASK_IDE1_INT = (1 << 23),
@@ -78,7 +87,7 @@ static struct pci_device_id sil_pci_tbl[] = {
/* TODO firmware versions should be added - eric */
-struct sil_drivelist {
+static const struct sil_drivelist {
const char * product;
unsigned int quirk;
} sil_blacklist [] = {
@@ -125,6 +134,7 @@ static 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 struct ata_port_operations sil_ops = {
@@ -139,6 +149,8 @@ static struct ata_port_operations sil_ops = {
.post_set_mode = sil_post_set_mode,
.bmdma_setup = ata_bmdma_setup,
.bmdma_start = ata_bmdma_start,
+ .bmdma_stop = ata_bmdma_stop,
+ .bmdma_status = ata_bmdma_status,
.qc_prep = ata_qc_prep,
.qc_issue = ata_qc_issue_prot,
.eng_timeout = ata_eng_timeout,
@@ -196,6 +208,13 @@ MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE(pci, sil_pci_tbl);
MODULE_VERSION(DRV_VERSION);
+static unsigned char sil_get_device_cache_line(struct pci_dev *pdev)
+{
+ u8 cache_line = 0;
+ pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &cache_line);
+ return cache_line;
+}
+
static void sil_post_set_mode (struct ata_port *ap)
{
struct ata_host_set *host_set = ap->host_set;
@@ -336,7 +355,9 @@ static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
void *mmio_base;
int rc;
unsigned int i;
+ int pci_dev_busy = 0;
u32 tmp, irq_mask;
+ u8 cls;
if (!printed_version++)
printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n");
@@ -350,8 +371,10 @@ static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
return rc;
rc = pci_request_regions(pdev, DRV_NAME);
- if (rc)
+ if (rc) {
+ pci_dev_busy = 1;
goto err_out;
+ }
rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
if (rc)
@@ -399,6 +422,19 @@ static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
ata_std_ports(&probe_ent->port[i]);
}
+ /* Initialize FIFO PCI bus arbitration */
+ cls = sil_get_device_cache_line(pdev);
+ if (cls) {
+ cls >>= 3;
+ cls++; /* cls = (line_size/8)+1 */
+ writeb(cls, mmio_base + SIL_FIFO_R0);
+ writeb(cls, mmio_base + SIL_FIFO_W0);
+ writeb(cls, mmio_base + SIL_FIFO_R1);
+ writeb(cls, mmio_base + SIL_FIFO_W2);
+ } else
+ printk(KERN_WARNING DRV_NAME "(%s): cache line size not set. Driver may not function\n",
+ pci_name(pdev));
+
if (ent->driver_data == sil_3114) {
irq_mask = SIL_MASK_4PORT;
@@ -438,7 +474,8 @@ err_out_free_ent:
err_out_regions:
pci_release_regions(pdev);
err_out:
- pci_disable_device(pdev);
+ if (!pci_dev_busy)
+ pci_disable_device(pdev);
return rc;
}
diff --git a/drivers/scsi/sata_sis.c b/drivers/scsi/sata_sis.c
index d48e437c91db4..5105ddd084478 100644
--- a/drivers/scsi/sata_sis.c
+++ b/drivers/scsi/sata_sis.c
@@ -90,6 +90,7 @@ static 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 struct ata_port_operations sis_ops = {
@@ -102,6 +103,8 @@ static struct ata_port_operations sis_ops = {
.phy_reset = sata_phy_reset,
.bmdma_setup = ata_bmdma_setup,
.bmdma_start = ata_bmdma_start,
+ .bmdma_stop = ata_bmdma_stop,
+ .bmdma_status = ata_bmdma_status,
.qc_prep = ata_qc_prep,
.qc_issue = ata_qc_issue_prot,
.eng_timeout = ata_eng_timeout,
@@ -200,14 +203,17 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
int rc;
u32 genctl;
struct ata_port_info *ppi;
+ int pci_dev_busy = 0;
rc = pci_enable_device(pdev);
if (rc)
return rc;
rc = pci_request_regions(pdev, DRV_NAME);
- if (rc)
+ if (rc) {
+ pci_dev_busy = 1;
goto err_out;
+ }
rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
if (rc)
@@ -259,7 +265,8 @@ err_out_regions:
pci_release_regions(pdev);
err_out:
- pci_disable_device(pdev);
+ if (!pci_dev_busy)
+ pci_disable_device(pdev);
return rc;
}
diff --git a/drivers/scsi/sata_svw.c b/drivers/scsi/sata_svw.c
index eca3eeb9efa68..8d1a5d25c0536 100644
--- a/drivers/scsi/sata_svw.c
+++ b/drivers/scsi/sata_svw.c
@@ -156,7 +156,7 @@ static void k2_sata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
* spin_lock_irqsave(host_set lock)
*/
-void k2_bmdma_setup_mmio (struct ata_queued_cmd *qc)
+static void k2_bmdma_setup_mmio (struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
@@ -186,7 +186,7 @@ void k2_bmdma_setup_mmio (struct ata_queued_cmd *qc)
* spin_lock_irqsave(host_set lock)
*/
-void k2_bmdma_start_mmio (struct ata_queued_cmd *qc)
+static void k2_bmdma_start_mmio (struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
void *mmio = (void *) ap->ioaddr.bmdma_addr;
@@ -288,6 +288,7 @@ static Scsi_Host_Template k2_sata_sht = {
.proc_info = k2_sata_proc_info,
#endif
.bios_param = ata_std_bios_param,
+ .ordered_flush = 1,
};
@@ -301,6 +302,8 @@ static struct ata_port_operations k2_sata_ops = {
.phy_reset = sata_phy_reset,
.bmdma_setup = k2_bmdma_setup_mmio,
.bmdma_start = k2_bmdma_start_mmio,
+ .bmdma_stop = ata_bmdma_stop,
+ .bmdma_status = ata_bmdma_status,
.qc_prep = ata_qc_prep,
.qc_issue = ata_qc_issue_prot,
.eng_timeout = ata_eng_timeout,
@@ -338,6 +341,7 @@ static int k2_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
struct ata_probe_ent *probe_ent = NULL;
unsigned long base;
void *mmio_base;
+ int pci_dev_busy = 0;
int rc;
if (!printed_version++)
@@ -359,8 +363,10 @@ static int k2_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
/* Request PCI regions */
rc = pci_request_regions(pdev, DRV_NAME);
- if (rc)
+ if (rc) {
+ pci_dev_busy = 1;
goto err_out;
+ }
rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
if (rc)
@@ -433,7 +439,8 @@ err_out_free_ent:
err_out_regions:
pci_release_regions(pdev);
err_out:
- pci_disable_device(pdev);
+ if (!pci_dev_busy)
+ pci_disable_device(pdev);
return rc;
}
diff --git a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c
index 20a01253b036d..70118650c461e 100644
--- a/drivers/scsi/sata_sx4.c
+++ b/drivers/scsi/sata_sx4.c
@@ -188,6 +188,7 @@ static 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 struct ata_port_operations pdc_20621_ops = {
@@ -1366,6 +1367,7 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *
void *mmio_base, *dimm_mmio = NULL;
struct pdc_host_priv *hpriv = NULL;
unsigned int board_idx = (unsigned int) ent->driver_data;
+ int pci_dev_busy = 0;
int rc;
if (!printed_version++)
@@ -1380,8 +1382,10 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *
return rc;
rc = pci_request_regions(pdev, DRV_NAME);
- if (rc)
+ if (rc) {
+ pci_dev_busy = 1;
goto err_out;
+ }
rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
if (rc)
@@ -1471,7 +1475,8 @@ err_out_free_ent:
err_out_regions:
pci_release_regions(pdev);
err_out:
- pci_disable_device(pdev);
+ if (!pci_dev_busy)
+ pci_disable_device(pdev);
return rc;
}
diff --git a/drivers/scsi/sata_uli.c b/drivers/scsi/sata_uli.c
index f1ae63a414a15..0bff4f475f262 100644
--- a/drivers/scsi/sata_uli.c
+++ b/drivers/scsi/sata_uli.c
@@ -82,6 +82,7 @@ static 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 struct ata_port_operations uli_ops = {
@@ -97,6 +98,8 @@ static struct ata_port_operations uli_ops = {
.bmdma_setup = ata_bmdma_setup,
.bmdma_start = ata_bmdma_start,
+ .bmdma_stop = ata_bmdma_stop,
+ .bmdma_status = ata_bmdma_status,
.qc_prep = ata_qc_prep,
.qc_issue = ata_qc_issue_prot,
@@ -185,14 +188,17 @@ static int uli_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
struct ata_port_info *ppi;
int rc;
unsigned int board_idx = (unsigned int) ent->driver_data;
+ int pci_dev_busy = 0;
rc = pci_enable_device(pdev);
if (rc)
return rc;
rc = pci_request_regions(pdev, DRV_NAME);
- if (rc)
+ if (rc) {
+ pci_dev_busy = 1;
goto err_out;
+ }
rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
if (rc)
@@ -260,7 +266,8 @@ err_out_regions:
pci_release_regions(pdev);
err_out:
- pci_disable_device(pdev);
+ if (!pci_dev_busy)
+ pci_disable_device(pdev);
return rc;
}
diff --git a/drivers/scsi/sata_via.c b/drivers/scsi/sata_via.c
index 5e3d5a60035c7..3a7830667277f 100644
--- a/drivers/scsi/sata_via.c
+++ b/drivers/scsi/sata_via.c
@@ -24,6 +24,11 @@
If you do not delete the provisions above, a recipient may use your
version of this file under either the OSL or the GPL.
+ ----------------------------------------------------------------------
+
+ To-do list:
+ * VT6421 PATA support
+
*/
#include <linux/kernel.h>
@@ -38,11 +43,14 @@
#include <asm/io.h>
#define DRV_NAME "sata_via"
-#define DRV_VERSION "1.0"
+#define DRV_VERSION "1.1"
-enum {
- via_sata = 0,
+enum board_ids_enum {
+ vt6420,
+ vt6421,
+};
+enum {
SATA_CHAN_ENAB = 0x40, /* SATA channel enable */
SATA_INT_GATE = 0x41, /* SATA interrupt gating */
SATA_NATIVE_MODE = 0x42, /* Native mode enable */
@@ -50,10 +58,8 @@ enum {
PORT0 = (1 << 1),
PORT1 = (1 << 0),
-
- ENAB_ALL = PORT0 | PORT1,
-
- INT_GATE_ALL = PORT0 | PORT1,
+ ALL_PORTS = PORT0 | PORT1,
+ N_PORTS = 2,
NATIVE_MODE_ALL = (1 << 7) | (1 << 6) | (1 << 5) | (1 << 4),
@@ -66,7 +72,8 @@ static u32 svia_scr_read (struct ata_port *ap, unsigned int sc_reg);
static void svia_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
static struct pci_device_id svia_pci_tbl[] = {
- { 0x1106, 0x3149, PCI_ANY_ID, PCI_ANY_ID, 0, 0, via_sata },
+ { 0x1106, 0x3149, PCI_ANY_ID, PCI_ANY_ID, 0, 0, vt6420 },
+ { 0x1106, 0x3249, PCI_ANY_ID, PCI_ANY_ID, 0, 0, vt6421 },
{ } /* terminate list */
};
@@ -95,6 +102,7 @@ static 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 struct ata_port_operations svia_sata_ops = {
@@ -110,6 +118,9 @@ static struct ata_port_operations svia_sata_ops = {
.bmdma_setup = ata_bmdma_setup,
.bmdma_start = ata_bmdma_start,
+ .bmdma_stop = ata_bmdma_stop,
+ .bmdma_status = ata_bmdma_status,
+
.qc_prep = ata_qc_prep,
.qc_issue = ata_qc_issue_prot,
@@ -158,18 +169,132 @@ static const unsigned int svia_bar_sizes[] = {
8, 4, 8, 4, 16, 256
};
+static const unsigned int vt6421_bar_sizes[] = {
+ 16, 16, 16, 16, 32, 128
+};
+
static unsigned long svia_scr_addr(unsigned long addr, unsigned int port)
{
return addr + (port * 128);
}
+static unsigned long vt6421_scr_addr(unsigned long addr, unsigned int port)
+{
+ return addr + (port * 64);
+}
+
+static void vt6421_init_addrs(struct ata_probe_ent *probe_ent,
+ struct pci_dev *pdev,
+ unsigned int port)
+{
+ unsigned long reg_addr = pci_resource_start(pdev, port);
+ unsigned long bmdma_addr = pci_resource_start(pdev, 4) + (port * 8);
+ unsigned long scr_addr;
+
+ probe_ent->port[port].cmd_addr = reg_addr;
+ probe_ent->port[port].altstatus_addr =
+ probe_ent->port[port].ctl_addr = (reg_addr + 8) | ATA_PCI_CTL_OFS;
+ probe_ent->port[port].bmdma_addr = bmdma_addr;
+
+ scr_addr = vt6421_scr_addr(pci_resource_start(pdev, 5), port);
+ probe_ent->port[port].scr_addr = scr_addr;
+
+ ata_std_ports(&probe_ent->port[port]);
+}
+
+static struct ata_probe_ent *vt6420_init_probe_ent(struct pci_dev *pdev)
+{
+ struct ata_probe_ent *probe_ent;
+ struct ata_port_info *ppi = &svia_port_info;
+
+ probe_ent = ata_pci_init_native_mode(pdev, &ppi);
+ if (!probe_ent)
+ return NULL;
+
+ probe_ent->port[0].scr_addr =
+ svia_scr_addr(pci_resource_start(pdev, 5), 0);
+ probe_ent->port[1].scr_addr =
+ svia_scr_addr(pci_resource_start(pdev, 5), 1);
+
+ return probe_ent;
+}
+
+static struct ata_probe_ent *vt6421_init_probe_ent(struct pci_dev *pdev)
+{
+ struct ata_probe_ent *probe_ent;
+ unsigned int i;
+
+ probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
+ if (!probe_ent)
+ return NULL;
+
+ memset(probe_ent, 0, sizeof(*probe_ent));
+ probe_ent->dev = pci_dev_to_dev(pdev);
+ INIT_LIST_HEAD(&probe_ent->node);
+
+ probe_ent->sht = &svia_sht;
+ probe_ent->host_flags = ATA_FLAG_SATA | ATA_FLAG_SATA_RESET |
+ ATA_FLAG_NO_LEGACY;
+ probe_ent->port_ops = &svia_sata_ops;
+ probe_ent->n_ports = N_PORTS;
+ probe_ent->irq = pdev->irq;
+ probe_ent->irq_flags = SA_SHIRQ;
+ probe_ent->pio_mask = 0x1f;
+ probe_ent->mwdma_mask = 0x07;
+ probe_ent->udma_mask = 0x7f;
+
+ for (i = 0; i < N_PORTS; i++)
+ vt6421_init_addrs(probe_ent, pdev, i);
+
+ return probe_ent;
+}
+
+static void svia_configure(struct pci_dev *pdev)
+{
+ u8 tmp8;
+
+ pci_read_config_byte(pdev, PCI_INTERRUPT_LINE, &tmp8);
+ printk(KERN_INFO DRV_NAME "(%s): routed to hard irq line %d\n",
+ pci_name(pdev),
+ (int) (tmp8 & 0xf0) == 0xf0 ? 0 : tmp8 & 0x0f);
+
+ /* make sure SATA channels are enabled */
+ pci_read_config_byte(pdev, SATA_CHAN_ENAB, &tmp8);
+ if ((tmp8 & ALL_PORTS) != ALL_PORTS) {
+ printk(KERN_DEBUG DRV_NAME "(%s): enabling SATA channels (0x%x)\n",
+ pci_name(pdev), (int) tmp8);
+ tmp8 |= ALL_PORTS;
+ pci_write_config_byte(pdev, SATA_CHAN_ENAB, tmp8);
+ }
+
+ /* make sure interrupts for each channel sent to us */
+ pci_read_config_byte(pdev, SATA_INT_GATE, &tmp8);
+ if ((tmp8 & ALL_PORTS) != ALL_PORTS) {
+ printk(KERN_DEBUG DRV_NAME "(%s): enabling SATA channel interrupts (0x%x)\n",
+ pci_name(pdev), (int) tmp8);
+ tmp8 |= ALL_PORTS;
+ pci_write_config_byte(pdev, SATA_INT_GATE, tmp8);
+ }
+
+ /* make sure native mode is enabled */
+ pci_read_config_byte(pdev, SATA_NATIVE_MODE, &tmp8);
+ if ((tmp8 & NATIVE_MODE_ALL) != NATIVE_MODE_ALL) {
+ printk(KERN_DEBUG DRV_NAME "(%s): enabling SATA channel native mode (0x%x)\n",
+ pci_name(pdev), (int) tmp8);
+ tmp8 |= NATIVE_MODE_ALL;
+ pci_write_config_byte(pdev, SATA_NATIVE_MODE, tmp8);
+ }
+}
+
static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
{
static int printed_version;
unsigned int i;
int rc;
- struct ata_port_info *ppi;
struct ata_probe_ent *probe_ent;
+ int board_id = (int) ent->driver_data;
+ const int *bar_sizes;
+ int pci_dev_busy = 0;
u8 tmp8;
if (!printed_version++)
@@ -180,20 +305,28 @@ static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
return rc;
rc = pci_request_regions(pdev, DRV_NAME);
- if (rc)
+ if (rc) {
+ pci_dev_busy = 1;
goto err_out;
+ }
- pci_read_config_byte(pdev, SATA_PATA_SHARING, &tmp8);
- if (tmp8 & SATA_2DEV) {
- printk(KERN_ERR DRV_NAME "(%s): SATA master/slave not supported (0x%x)\n",
- pci_name(pdev), (int) tmp8);
- rc = -EIO;
- goto err_out_regions;
+ if (board_id == vt6420) {
+ pci_read_config_byte(pdev, SATA_PATA_SHARING, &tmp8);
+ if (tmp8 & SATA_2DEV) {
+ printk(KERN_ERR DRV_NAME "(%s): SATA master/slave not supported (0x%x)\n",
+ pci_name(pdev), (int) tmp8);
+ rc = -EIO;
+ goto err_out_regions;
+ }
+
+ bar_sizes = &svia_bar_sizes[0];
+ } else {
+ bar_sizes = &vt6421_bar_sizes[0];
}
for (i = 0; i < ARRAY_SIZE(svia_bar_sizes); i++)
if ((pci_resource_start(pdev, i) == 0) ||
- (pci_resource_len(pdev, i) < svia_bar_sizes[i])) {
+ (pci_resource_len(pdev, i) < bar_sizes[i])) {
printk(KERN_ERR DRV_NAME "(%s): invalid PCI BAR %u (sz 0x%lx, val 0x%lx)\n",
pci_name(pdev), i,
pci_resource_start(pdev, i),
@@ -209,8 +342,11 @@ static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
if (rc)
goto err_out_regions;
- ppi = &svia_port_info;
- probe_ent = ata_pci_init_native_mode(pdev, &ppi);
+ if (board_id == vt6420)
+ probe_ent = vt6420_init_probe_ent(pdev);
+ else
+ probe_ent = vt6421_init_probe_ent(pdev);
+
if (!probe_ent) {
printk(KERN_ERR DRV_NAME "(%s): out of memory\n",
pci_name(pdev));
@@ -218,42 +354,7 @@ static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
goto err_out_regions;
}
- probe_ent->port[0].scr_addr =
- svia_scr_addr(pci_resource_start(pdev, 5), 0);
- probe_ent->port[1].scr_addr =
- svia_scr_addr(pci_resource_start(pdev, 5), 1);
-
- pci_read_config_byte(pdev, PCI_INTERRUPT_LINE, &tmp8);
- printk(KERN_INFO DRV_NAME "(%s): routed to hard irq line %d\n",
- pci_name(pdev),
- (int) (tmp8 & 0xf0) == 0xf0 ? 0 : tmp8 & 0x0f);
-
- /* make sure SATA channels are enabled */
- pci_read_config_byte(pdev, SATA_CHAN_ENAB, &tmp8);
- if ((tmp8 & ENAB_ALL) != ENAB_ALL) {
- printk(KERN_DEBUG DRV_NAME "(%s): enabling SATA channels (0x%x)\n",
- pci_name(pdev), (int) tmp8);
- tmp8 |= ENAB_ALL;
- pci_write_config_byte(pdev, SATA_CHAN_ENAB, tmp8);
- }
-
- /* make sure interrupts for each channel sent to us */
- pci_read_config_byte(pdev, SATA_INT_GATE, &tmp8);
- if ((tmp8 & INT_GATE_ALL) != INT_GATE_ALL) {
- printk(KERN_DEBUG DRV_NAME "(%s): enabling SATA channel interrupts (0x%x)\n",
- pci_name(pdev), (int) tmp8);
- tmp8 |= INT_GATE_ALL;
- pci_write_config_byte(pdev, SATA_INT_GATE, tmp8);
- }
-
- /* make sure native mode is enabled */
- pci_read_config_byte(pdev, SATA_NATIVE_MODE, &tmp8);
- if ((tmp8 & NATIVE_MODE_ALL) != NATIVE_MODE_ALL) {
- printk(KERN_DEBUG DRV_NAME "(%s): enabling SATA channel native mode (0x%x)\n",
- pci_name(pdev), (int) tmp8);
- tmp8 |= NATIVE_MODE_ALL;
- pci_write_config_byte(pdev, SATA_NATIVE_MODE, tmp8);
- }
+ svia_configure(pdev);
pci_set_master(pdev);
@@ -266,7 +367,8 @@ static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
err_out_regions:
pci_release_regions(pdev);
err_out:
- pci_disable_device(pdev);
+ if (!pci_dev_busy)
+ pci_disable_device(pdev);
return rc;
}
diff --git a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c
index 26c822f1e8e67..2c28f0ad73c20 100644
--- a/drivers/scsi/sata_vsc.c
+++ b/drivers/scsi/sata_vsc.c
@@ -155,7 +155,8 @@ static void vsc_sata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
*
* Read the interrupt register and process for the devices that have them pending.
*/
-irqreturn_t vsc_sata_interrupt (int irq, void *dev_instance, struct pt_regs *regs)
+static irqreturn_t vsc_sata_interrupt (int irq, void *dev_instance,
+ struct pt_regs *regs)
{
struct ata_host_set *host_set = dev_instance;
unsigned int i;
@@ -204,6 +205,7 @@ static 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,
};
@@ -217,6 +219,8 @@ static struct ata_port_operations vsc_sata_ops = {
.phy_reset = sata_phy_reset,
.bmdma_setup = ata_bmdma_setup,
.bmdma_start = ata_bmdma_start,
+ .bmdma_stop = ata_bmdma_stop,
+ .bmdma_status = ata_bmdma_status,
.qc_prep = ata_qc_prep,
.qc_issue = ata_qc_issue_prot,
.eng_timeout = ata_eng_timeout,
@@ -255,6 +259,7 @@ static int __devinit vsc_sata_init_one (struct pci_dev *pdev, const struct pci_d
static int printed_version;
struct ata_probe_ent *probe_ent = NULL;
unsigned long base;
+ int pci_dev_busy = 0;
void *mmio_base;
int rc;
@@ -274,16 +279,18 @@ static int __devinit vsc_sata_init_one (struct pci_dev *pdev, const struct pci_d
}
rc = pci_request_regions(pdev, DRV_NAME);
- if (rc)
+ if (rc) {
+ pci_dev_busy = 1;
goto err_out;
+ }
/*
* Use 32 bit DMA mask, because 64 bit address support is poor.
*/
- rc = pci_set_dma_mask(pdev, 0xFFFFFFFFULL);
+ rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
if (rc)
goto err_out_regions;
- rc = pci_set_consistent_dma_mask(pdev, 0xFFFFFFFFULL);
+ rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
if (rc)
goto err_out_regions;
@@ -352,7 +359,8 @@ err_out_free_ent:
err_out_regions:
pci_release_regions(pdev);
err_out:
- pci_disable_device(pdev);
+ if (!pci_dev_busy)
+ pci_disable_device(pdev);
return rc;
}
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index ab4c237306e44..2e7ab3ab09932 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -88,12 +88,6 @@
COMMAND_SIZE((cmd)->cmnd[0]) : (cmd)->cmd_len)
/*
- * Data declarations.
- */
-unsigned long scsi_pid;
-static unsigned long serial_number;
-
-/*
* Note - the initial logging level can be set here to log events at boot time.
* After the system is up, you may enable logging via the /proc interface.
*/
@@ -510,6 +504,21 @@ void scsi_log_completion(struct scsi_cmnd *cmd, int disposition)
}
#endif
+/*
+ * Assign a serial number and pid to the request for error recovery
+ * and debugging purposes. Protected by the Host_Lock of host.
+ */
+static inline void scsi_cmd_get_serial(struct Scsi_Host *host, struct scsi_cmnd *cmd)
+{
+ cmd->serial_number = host->cmd_serial_number++;
+ if (cmd->serial_number == 0)
+ cmd->serial_number = host->cmd_serial_number++;
+
+ cmd->pid = host->cmd_pid++;
+ if (cmd->pid == 0)
+ cmd->pid = host->cmd_pid++;
+}
+
/*
* Function: scsi_dispatch_command
*
@@ -532,6 +541,7 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
* returns an immediate error upwards, and signals
* that the device is no longer present */
cmd->result = DID_NO_CONNECT << 16;
+ atomic_inc(&cmd->device->iorequest_cnt);
scsi_done(cmd);
/* return 0 (because the command has been processed) */
goto out;
@@ -556,13 +566,6 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
goto out;
}
- /* Assign a unique nonzero serial_number. */
- /* XXX(hch): this is racy */
- if (++serial_number == 0)
- serial_number = 1;
- cmd->serial_number = serial_number;
- cmd->pid = scsi_pid++;
-
/*
* If SCSI-2 or lower, store the LUN value in cmnd.
*/
@@ -593,6 +596,10 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
host->resetting = 0;
}
+ /*
+ * AK: unlikely race here: for some reason the timer could
+ * expire before the serial number is set up below.
+ */
scsi_add_timer(cmd, cmd->timeout_per_command, scsi_times_out);
scsi_log_send(cmd);
@@ -605,6 +612,8 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
cmd->state = SCSI_STATE_QUEUED;
cmd->owner = SCSI_OWNER_LOWLEVEL;
+ atomic_inc(&cmd->device->iorequest_cnt);
+
/*
* Before we queue this command, check if the command
* length exceeds what the host adapter can handle.
@@ -619,6 +628,8 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
}
spin_lock_irqsave(host->host_lock, flags);
+ scsi_cmd_get_serial(host, cmd);
+
if (unlikely(test_bit(SHOST_CANCEL, &host->shost_state))) {
cmd->result = (DID_NO_CONNECT << 16);
scsi_done(cmd);
@@ -627,6 +638,7 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
}
spin_unlock_irqrestore(host->host_lock, flags);
if (rtn) {
+ atomic_inc(&cmd->device->iodone_cnt);
scsi_queue_insert(cmd,
(rtn == SCSI_MLQUEUE_DEVICE_BUSY) ?
rtn : SCSI_MLQUEUE_HOST_BUSY);
@@ -758,6 +770,10 @@ void __scsi_done(struct scsi_cmnd *cmd)
cmd->state = SCSI_STATE_BHQUEUE;
cmd->owner = SCSI_OWNER_BH_HANDLER;
+ atomic_inc(&cmd->device->iodone_cnt);
+ if (cmd->result)
+ atomic_inc(&cmd->device->ioerr_cnt);
+
/*
* Next, enqueue the command into the done queue.
* It is a per-CPU queue, so we just disable local interrupts
@@ -920,12 +936,9 @@ EXPORT_SYMBOL(scsi_finish_command);
* the right thing depending on whether or not the device is
* currently active and whether or not it even has the
* command blocks built yet.
- *
- * XXX(hch): What exactly is device_request_lock trying to protect?
*/
void scsi_adjust_queue_depth(struct scsi_device *sdev, int tagged, int tags)
{
- static DEFINE_SPINLOCK(device_request_lock);
unsigned long flags;
/*
@@ -934,8 +947,7 @@ void scsi_adjust_queue_depth(struct scsi_device *sdev, int tagged, int tags)
if (tags <= 0)
return;
- spin_lock_irqsave(&device_request_lock, flags);
- spin_lock(sdev->request_queue->queue_lock);
+ spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
/* Check to see if the queue is managed by the block layer
* if it is, and we fail to adjust the depth, exit */
@@ -964,8 +976,7 @@ void scsi_adjust_queue_depth(struct scsi_device *sdev, int tagged, int tags)
break;
}
out:
- spin_unlock(sdev->request_queue->queue_lock);
- spin_unlock_irqrestore(&device_request_lock, flags);
+ spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
}
EXPORT_SYMBOL(scsi_adjust_queue_depth);
@@ -1105,6 +1116,60 @@ void starget_for_each_device(struct scsi_target *starget, void * data,
EXPORT_SYMBOL(starget_for_each_device);
/**
+ * __scsi_device_lookup_by_target - find a device given the target (UNLOCKED)
+ * @starget: SCSI target pointer
+ * @lun: SCSI Logical Unit Number
+ *
+ * Looks up the scsi_device with the specified @lun for a give
+ * @starget. The returned scsi_device does not have an additional
+ * reference. You must hold the host's host_lock over this call and
+ * any access to the returned scsi_device.
+ *
+ * Note: The only reason why drivers would want to use this is because
+ * they're need to access the device list in irq context. Otherwise you
+ * really want to use scsi_device_lookup_by_target instead.
+ **/
+struct scsi_device *__scsi_device_lookup_by_target(struct scsi_target *starget,
+ uint lun)
+{
+ struct scsi_device *sdev;
+
+ list_for_each_entry(sdev, &starget->devices, same_target_siblings) {
+ if (sdev->lun ==lun)
+ return sdev;
+ }
+
+ return NULL;
+}
+EXPORT_SYMBOL(__scsi_device_lookup_by_target);
+
+/**
+ * scsi_device_lookup_by_target - find a device given the target
+ * @starget: SCSI target pointer
+ * @lun: SCSI Logical Unit Number
+ *
+ * Looks up the scsi_device with the specified @channel, @id, @lun for a
+ * give host. The returned scsi_device has an additional reference that
+ * needs to be release with scsi_host_put once you're done with it.
+ **/
+struct scsi_device *scsi_device_lookup_by_target(struct scsi_target *starget,
+ uint lun)
+{
+ struct scsi_device *sdev;
+ struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+ unsigned long flags;
+
+ spin_lock_irqsave(shost->host_lock, flags);
+ sdev = __scsi_device_lookup_by_target(starget, lun);
+ if (sdev && scsi_device_get(sdev))
+ sdev = NULL;
+ spin_unlock_irqrestore(shost->host_lock, flags);
+
+ return sdev;
+}
+EXPORT_SYMBOL(scsi_device_lookup_by_target);
+
+/**
* scsi_device_lookup - find a device given the host (UNLOCKED)
* @shost: SCSI host pointer
* @channel: SCSI channel (zero if only one channel)
diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c
index 4347594a6bc09..6121dc1bfada4 100644
--- a/drivers/scsi/scsi_devinfo.c
+++ b/drivers/scsi/scsi_devinfo.c
@@ -28,7 +28,7 @@ struct scsi_dev_info_list {
static const char spaces[] = " "; /* 16 of them */
static unsigned scsi_default_dev_flags;
static LIST_HEAD(scsi_dev_info_list);
-static __initdata char scsi_dev_flags[256];
+static char scsi_dev_flags[256];
/*
* scsi_static_device_list: deprecated list of devices that require
@@ -63,6 +63,7 @@ static struct {
{"MAXTOR", "XT-4170S", "B5A", BLIST_NOLUN}, /* locks up */
{"MAXTOR", "XT-8760S", "B7B", BLIST_NOLUN}, /* locks up */
{"MEDIAVIS", "RENO CD-ROMX2A", "2.03", BLIST_NOLUN}, /* responds to all lun */
+ {"MICROTEK", "ScanMakerIII", "2.30", BLIST_NOLUN}, /* responds to all lun */
{"NEC", "CD-ROM DRIVE:841", "1.0", BLIST_NOLUN},/* locks up */
{"PHILIPS", "PCA80SC", "V4-2", BLIST_NOLUN}, /* responds to all lun */
{"RODIME", "RO3000S", "2.33", BLIST_NOLUN}, /* locks up */
@@ -159,6 +160,7 @@ static struct {
{"HP", "C3323-300", "4269", BLIST_NOTQ},
{"IBM", "AuSaV1S2", NULL, BLIST_FORCELUN},
{"IBM", "ProFibre 4000R", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
+ {"IBM", "2105", NULL, BLIST_RETRY_HWERROR},
{"iomega", "jaz 1GB", "J.86", BLIST_NOTQ | BLIST_NOLUN},
{"IOMEGA", "Io20S *F", NULL, BLIST_KEY},
{"INSITE", "Floptical F*8I", NULL, BLIST_KEY},
@@ -192,6 +194,7 @@ static struct {
{"SMSC", "USB 2 HS-CF", NULL, BLIST_SPARSELUN | BLIST_INQUIRY_36},
{"SONY", "CD-ROM CDU-8001", NULL, BLIST_BORKEN},
{"SONY", "TSL", NULL, BLIST_FORCELUN}, /* DDS3 & DDS4 autoloaders */
+ {"ST650211", "CF", NULL, BLIST_RETRY_HWERROR},
{"SUN", "T300", "*", BLIST_SPARSELUN},
{"SUN", "T4", "*", BLIST_SPARSELUN},
{"TEXEL", "CD-ROM", "1.06", BLIST_BORKEN},
@@ -201,6 +204,7 @@ static struct {
{"WangDAT", "Model 2600", "01.7", BLIST_SELECT_NO_ATN},
{"WangDAT", "Model 3200", "02.2", BLIST_SELECT_NO_ATN},
{"WangDAT", "Model 1300", "02.4", BLIST_SELECT_NO_ATN},
+ {"WDC WD25", "00JB-00FUA0", NULL, BLIST_NOREPORTLUN},
{"XYRATEX", "RS", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
{"Zzyzx", "RocketStor 500S", NULL, BLIST_SPARSELUN},
{"Zzyzx", "RocketStor 2000", NULL, BLIST_SPARSELUN},
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index eb337e474583d..9bc597bd13bad 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -350,10 +350,15 @@ static int scsi_check_sense(struct scsi_cmnd *scmd)
case MEDIUM_ERROR:
return NEEDS_RETRY;
+ case HARDWARE_ERROR:
+ if (scmd->device->retry_hwerror)
+ return NEEDS_RETRY;
+ else
+ return SUCCESS;
+
case ILLEGAL_REQUEST:
case BLANK_CHECK:
case DATA_PROTECT:
- case HARDWARE_ERROR:
default:
return SUCCESS;
}
@@ -1364,6 +1369,7 @@ int scsi_decide_disposition(struct scsi_cmnd *scmd)
return ADD_TO_MLQUEUE;
case GOOD:
case COMMAND_TERMINATED:
+ case TASK_ABORTED:
return SUCCESS;
case CHECK_CONDITION:
rtn = scsi_check_sense(scmd);
@@ -1377,6 +1383,7 @@ int scsi_decide_disposition(struct scsi_cmnd *scmd)
case CONDITION_GOOD:
case INTERMEDIATE_GOOD:
case INTERMEDIATE_C_GOOD:
+ case ACA_ACTIVE:
/*
* who knows? FIXME(eric)
*/
diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c
index 0929d1ef615aa..68c9728dfbbb3 100644
--- a/drivers/scsi/scsi_ioctl.c
+++ b/drivers/scsi/scsi_ioctl.c
@@ -230,7 +230,7 @@ int scsi_ioctl_send_command(struct scsi_device *sdev,
/*
* Verify that we can read at least this much.
*/
- if (verify_area(VERIFY_READ, sic, sizeof(Scsi_Ioctl_Command)))
+ if (!access_ok(VERIFY_READ, sic, sizeof(Scsi_Ioctl_Command)))
return -EFAULT;
if(__get_user(inlen, &sic->inlen))
@@ -285,7 +285,7 @@ int scsi_ioctl_send_command(struct scsi_device *sdev,
result = -EFAULT;
- if (verify_area(VERIFY_READ, cmd_in, cmdlen + inlen))
+ if (!access_ok(VERIFY_READ, cmd_in, cmdlen + inlen))
goto error;
if(__copy_from_user(cmd, cmd_in, cmdlen))
@@ -417,7 +417,7 @@ int scsi_ioctl(struct scsi_device *sdev, int cmd, void __user *arg)
switch (cmd) {
case SCSI_IOCTL_GET_IDLUN:
- if (verify_area(VERIFY_WRITE, arg, sizeof(struct scsi_idlun)))
+ if (!access_ok(VERIFY_WRITE, arg, sizeof(struct scsi_idlun)))
return -EFAULT;
__put_user((sdev->id & 0xff)
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 20131251693ed..7cbc4127fb5a6 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -252,6 +252,16 @@ static void scsi_wait_done(struct scsi_cmnd *cmd)
complete(req->waiting);
}
+/* This is the end routine we get to if a command was never attached
+ * to the request. Simply complete the request without changing
+ * rq_status; this will cause a DRIVER_ERROR. */
+static void scsi_wait_req_end_io(struct request *req)
+{
+ BUG_ON(!req->waiting);
+
+ complete(req->waiting);
+}
+
void scsi_wait_req(struct scsi_request *sreq, const void *cmnd, void *buffer,
unsigned bufflen, int timeout, int retries)
{
@@ -259,6 +269,7 @@ void scsi_wait_req(struct scsi_request *sreq, const void *cmnd, void *buffer,
sreq->sr_request->waiting = &wait;
sreq->sr_request->rq_status = RQ_SCSI_BUSY;
+ sreq->sr_request->end_io = scsi_wait_req_end_io;
scsi_do_req(sreq, cmnd, buffer, bufflen, scsi_wait_done,
timeout, retries);
wait_for_completion(&wait);
@@ -365,10 +376,11 @@ static void scsi_single_lun_run(struct scsi_device *current_sdev)
{
struct Scsi_Host *shost = current_sdev->host;
struct scsi_device *sdev, *tmp;
+ struct scsi_target *starget = scsi_target(current_sdev);
unsigned long flags;
spin_lock_irqsave(shost->host_lock, flags);
- scsi_target(current_sdev)->starget_sdev_user = NULL;
+ starget->starget_sdev_user = NULL;
spin_unlock_irqrestore(shost->host_lock, flags);
/*
@@ -380,10 +392,12 @@ static void scsi_single_lun_run(struct scsi_device *current_sdev)
blk_run_queue(current_sdev->request_queue);
spin_lock_irqsave(shost->host_lock, flags);
- if (scsi_target(current_sdev)->starget_sdev_user)
+ if (starget->starget_sdev_user)
goto out;
- list_for_each_entry_safe(sdev, tmp, &current_sdev->same_target_siblings,
+ list_for_each_entry_safe(sdev, tmp, &starget->devices,
same_target_siblings) {
+ if (sdev == current_sdev)
+ continue;
if (scsi_device_get(sdev))
continue;
@@ -697,6 +711,9 @@ 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
@@ -723,7 +740,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes,
req->errors = result;
if (result) {
clear_errors = 0;
- if (sense_valid) {
+ if (sense_valid && req->sense) {
/*
* SG_IO wants current and deferred errors
*/
@@ -962,6 +979,38 @@ 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)
{
@@ -1195,6 +1244,22 @@ static inline int scsi_host_queue_ready(struct request_queue *q,
}
/*
+ * Kill requests for a dead device
+ */
+static void scsi_kill_requests(request_queue_t *q)
+{
+ struct request *req;
+
+ while ((req = elv_next_request(q)) != NULL) {
+ blkdev_dequeue_request(req);
+ req->flags |= REQ_QUIET;
+ while (end_that_request_first(req, 0, req->nr_sectors))
+ ;
+ end_that_request_last(req);
+ }
+}
+
+/*
* Function: scsi_request_fn()
*
* Purpose: Main strategy routine for SCSI.
@@ -1208,10 +1273,16 @@ static inline int scsi_host_queue_ready(struct request_queue *q,
static void scsi_request_fn(struct request_queue *q)
{
struct scsi_device *sdev = q->queuedata;
- struct Scsi_Host *shost = sdev->host;
+ struct Scsi_Host *shost;
struct scsi_cmnd *cmd;
struct request *req;
+ if (!sdev) {
+ printk("scsi: killing requests for dead queue\n");
+ scsi_kill_requests(q);
+ return;
+ }
+
if(!get_device(&sdev->sdev_gendev))
/* We must be tearing the block queue down already */
return;
@@ -1220,6 +1291,7 @@ static void scsi_request_fn(struct request_queue *q)
* To start with, we keep looping until the queue is empty, or until
* the host is no longer able to accept any more requests.
*/
+ shost = sdev->host;
while (!blk_queue_plugged(q)) {
int rtn;
/*
@@ -1366,6 +1438,17 @@ struct request_queue *scsi_alloc_queue(struct scsi_device *sdev)
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;
+ }
+
if (!shost->use_clustering)
clear_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags);
return q;
@@ -1886,3 +1969,55 @@ scsi_internal_device_unblock(struct scsi_device *sdev)
return 0;
}
EXPORT_SYMBOL_GPL(scsi_internal_device_unblock);
+
+static void
+device_block(struct scsi_device *sdev, void *data)
+{
+ scsi_internal_device_block(sdev);
+}
+
+static int
+target_block(struct device *dev, void *data)
+{
+ if (scsi_is_target_device(dev))
+ starget_for_each_device(to_scsi_target(dev), NULL,
+ device_block);
+ return 0;
+}
+
+void
+scsi_target_block(struct device *dev)
+{
+ if (scsi_is_target_device(dev))
+ starget_for_each_device(to_scsi_target(dev), NULL,
+ device_block);
+ else
+ device_for_each_child(dev, NULL, target_block);
+}
+EXPORT_SYMBOL_GPL(scsi_target_block);
+
+static void
+device_unblock(struct scsi_device *sdev, void *data)
+{
+ scsi_internal_device_unblock(sdev);
+}
+
+static int
+target_unblock(struct device *dev, void *data)
+{
+ if (scsi_is_target_device(dev))
+ starget_for_each_device(to_scsi_target(dev), NULL,
+ device_unblock);
+ return 0;
+}
+
+void
+scsi_target_unblock(struct device *dev)
+{
+ if (scsi_is_target_device(dev))
+ starget_for_each_device(to_scsi_target(dev), NULL,
+ device_unblock);
+ else
+ device_for_each_child(dev, NULL, target_unblock);
+}
+EXPORT_SYMBOL_GPL(scsi_target_unblock);
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 98e92ed900ccf..a8a37a338c02f 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -200,12 +200,12 @@ static void print_inquiry(unsigned char *inq_result)
* Return value:
* scsi_Device pointer, or NULL on failure.
**/
-static struct scsi_device *scsi_alloc_sdev(struct Scsi_Host *shost,
- uint channel, uint id, uint lun, void *hostdata)
+static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget,
+ unsigned int lun, void *hostdata)
{
struct scsi_device *sdev;
- unsigned long flags;
int display_failure_msg = 1, ret;
+ struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
sdev = kmalloc(sizeof(*sdev) + shost->transportt->device_size,
GFP_ATOMIC);
@@ -217,9 +217,9 @@ static struct scsi_device *scsi_alloc_sdev(struct Scsi_Host *shost,
sdev->model = scsi_null_device_strs;
sdev->rev = scsi_null_device_strs;
sdev->host = shost;
- sdev->id = id;
+ sdev->id = starget->id;
sdev->lun = lun;
- sdev->channel = channel;
+ sdev->channel = starget->channel;
sdev->sdev_state = SDEV_CREATED;
INIT_LIST_HEAD(&sdev->siblings);
INIT_LIST_HEAD(&sdev->same_target_siblings);
@@ -227,6 +227,9 @@ static struct scsi_device *scsi_alloc_sdev(struct Scsi_Host *shost,
INIT_LIST_HEAD(&sdev->starved_entry);
spin_lock_init(&sdev->list_lock);
+ sdev->sdev_gendev.parent = get_device(&starget->dev);
+ sdev->sdev_target = starget;
+
/* usually NULL and set by ->slave_alloc instead */
sdev->hostdata = hostdata;
@@ -248,8 +251,12 @@ static struct scsi_device *scsi_alloc_sdev(struct Scsi_Host *shost,
spin_lock_init(&sdev->sdev_lock);
sdev->request_queue = scsi_alloc_queue(sdev);
- if (!sdev->request_queue)
- goto out_free_dev;
+ if (!sdev->request_queue) {
+ /* release fn is set up in scsi_sysfs_device_initialise, so
+ * have to free and put manually here */
+ put_device(&starget->dev);
+ goto out;
+ }
sdev->request_queue->queuedata = sdev;
scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun);
@@ -262,6 +269,8 @@ static struct scsi_device *scsi_alloc_sdev(struct Scsi_Host *shost,
/*
* if LLDD reports slave not present, don't clutter
* console with alloc failure messages
+
+
*/
if (ret == -ENXIO)
display_failure_msg = 0;
@@ -269,32 +278,128 @@ static struct scsi_device *scsi_alloc_sdev(struct Scsi_Host *shost,
}
}
- /* NOTE: this target initialisation code depends critically on
- * lun scanning being sequential. */
- if (scsi_sysfs_target_initialize(sdev))
- goto out_remove_siblings;
-
return sdev;
-out_remove_siblings:
- spin_lock_irqsave(shost->host_lock, flags);
- list_del(&sdev->siblings);
- list_del(&sdev->same_target_siblings);
- spin_unlock_irqrestore(shost->host_lock, flags);
-
- if (shost->hostt->slave_destroy)
- shost->hostt->slave_destroy(sdev);
out_device_destroy:
transport_destroy_device(&sdev->sdev_gendev);
scsi_free_queue(sdev->request_queue);
-out_free_dev:
- kfree(sdev);
+ put_device(&sdev->sdev_gendev);
out:
if (display_failure_msg)
printk(ALLOC_FAILURE_MSG, __FUNCTION__);
return NULL;
}
+static void scsi_target_dev_release(struct device *dev)
+{
+ struct device *parent = dev->parent;
+ struct scsi_target *starget = to_scsi_target(dev);
+ kfree(starget);
+ put_device(parent);
+}
+
+int scsi_is_target_device(const struct device *dev)
+{
+ return dev->release == scsi_target_dev_release;
+}
+EXPORT_SYMBOL(scsi_is_target_device);
+
+static struct scsi_target *__scsi_find_target(struct device *parent,
+ int channel, uint id)
+{
+ struct scsi_target *starget, *found_starget = NULL;
+ struct Scsi_Host *shost = dev_to_shost(parent);
+ /*
+ * Search for an existing target for this sdev.
+ */
+ list_for_each_entry(starget, &shost->__targets, siblings) {
+ if (starget->id == id &&
+ starget->channel == channel) {
+ found_starget = starget;
+ break;
+ }
+ }
+ if (found_starget)
+ get_device(&found_starget->dev);
+
+ return found_starget;
+}
+
+static struct scsi_target *scsi_alloc_target(struct device *parent,
+ int channel, uint id)
+{
+ struct Scsi_Host *shost = dev_to_shost(parent);
+ struct device *dev = NULL;
+ unsigned long flags;
+ const int size = sizeof(struct scsi_target)
+ + shost->transportt->target_size;
+ struct scsi_target *starget = kmalloc(size, GFP_ATOMIC);
+ struct scsi_target *found_target;
+
+ if (!starget) {
+ printk(KERN_ERR "%s: allocation failure\n", __FUNCTION__);
+ return NULL;
+ }
+ memset(starget, 0, size);
+ dev = &starget->dev;
+ device_initialize(dev);
+ starget->reap_ref = 1;
+ dev->parent = get_device(parent);
+ dev->release = scsi_target_dev_release;
+ sprintf(dev->bus_id, "target%d:%d:%d",
+ shost->host_no, channel, id);
+ starget->id = id;
+ starget->channel = channel;
+ INIT_LIST_HEAD(&starget->siblings);
+ INIT_LIST_HEAD(&starget->devices);
+ spin_lock_irqsave(shost->host_lock, flags);
+
+ found_target = __scsi_find_target(parent, channel, id);
+ if (found_target)
+ goto found;
+
+ list_add_tail(&starget->siblings, &shost->__targets);
+ spin_unlock_irqrestore(shost->host_lock, flags);
+ /* allocate and add */
+ transport_setup_device(&starget->dev);
+ device_add(&starget->dev);
+ transport_add_device(&starget->dev);
+ return starget;
+
+ found:
+ found_target->reap_ref++;
+ spin_unlock_irqrestore(shost->host_lock, flags);
+ put_device(parent);
+ kfree(starget);
+ return found_target;
+}
+
+/**
+ * scsi_target_reap - check to see if target is in use and destroy if not
+ *
+ * @starget: target to be checked
+ *
+ * This is used after removing a LUN or doing a last put of the target
+ * it checks atomically that nothing is using the target and removes
+ * it if so.
+ */
+void scsi_target_reap(struct scsi_target *starget)
+{
+ struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+ unsigned long flags;
+ spin_lock_irqsave(shost->host_lock, flags);
+
+ if (--starget->reap_ref == 0 && list_empty(&starget->devices)) {
+ list_del_init(&starget->siblings);
+ spin_unlock_irqrestore(shost->host_lock, flags);
+ device_del(&starget->dev);
+ transport_unregister_device(&starget->dev);
+ put_device(&starget->dev);
+ return;
+ }
+ spin_unlock_irqrestore(shost->host_lock, flags);
+}
+
/**
* scsi_probe_lun - probe a single LUN using a SCSI INQUIRY
* @sreq: used to send the INQUIRY
@@ -620,6 +725,9 @@ static int scsi_add_lun(struct scsi_device *sdev, char *inq_result, int *bflags)
if (*bflags & BLIST_NOT_LOCKABLE)
sdev->lockable = 0;
+ if (*bflags & BLIST_RETRY_HWERROR)
+ sdev->retry_hwerror = 1;
+
transport_configure_device(&sdev->sdev_gendev);
if (sdev->host->hostt->slave_configure)
@@ -637,6 +745,8 @@ static int scsi_add_lun(struct scsi_device *sdev, char *inq_result, int *bflags)
/**
* scsi_probe_and_add_lun - probe a LUN, if a LUN is found add it
+ * @starget: pointer to target device structure
+ * @lun: LUN of target device
* @sdevscan: probe the LUN corresponding to this Scsi_Device
* @sdevnew: store the value of any new Scsi_Device allocated
* @bflagsp: store bflags here if not NULL
@@ -651,45 +761,48 @@ static int scsi_add_lun(struct scsi_device *sdev, char *inq_result, int *bflags)
* attached at the LUN
* SCSI_SCAN_LUN_PRESENT: a new Scsi_Device was allocated and initialized
**/
-static int scsi_probe_and_add_lun(struct Scsi_Host *host,
- uint channel, uint id, uint lun, int *bflagsp,
- struct scsi_device **sdevp, int rescan, void *hostdata)
+static int scsi_probe_and_add_lun(struct scsi_target *starget,
+ uint lun, int *bflagsp,
+ struct scsi_device **sdevp, int rescan,
+ void *hostdata)
{
struct scsi_device *sdev;
struct scsi_request *sreq;
unsigned char *result;
int bflags, res = SCSI_SCAN_NO_RESPONSE;
+ struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
/*
* The rescan flag is used as an optimization, the first scan of a
* host adapter calls into here with rescan == 0.
*/
if (rescan) {
- sdev = scsi_device_lookup(host, channel, id, lun);
+ sdev = scsi_device_lookup_by_target(starget, lun);
if (sdev) {
SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO
- "scsi scan: device exists on <%d:%d:%d:%d>\n",
- host->host_no, channel, id, lun));
+ "scsi scan: device exists on %s\n",
+ sdev->sdev_gendev.bus_id));
if (sdevp)
*sdevp = sdev;
+ else
+ scsi_device_put(sdev);
+
if (bflagsp)
*bflagsp = scsi_get_device_flags(sdev,
sdev->vendor,
sdev->model);
- /* XXX: bandaid until callers do refcounting */
- scsi_device_put(sdev);
return SCSI_SCAN_LUN_PRESENT;
}
}
- sdev = scsi_alloc_sdev(host, channel, id, lun, hostdata);
+ sdev = scsi_alloc_sdev(starget, lun, hostdata);
if (!sdev)
goto out;
sreq = scsi_allocate_request(sdev, GFP_ATOMIC);
if (!sreq)
goto out_free_sdev;
result = kmalloc(256, GFP_ATOMIC |
- (host->unchecked_isa_dma) ? __GFP_DMA : 0);
+ (shost->unchecked_isa_dma) ? __GFP_DMA : 0);
if (!result)
goto out_free_sreq;
@@ -734,8 +847,10 @@ static int scsi_probe_and_add_lun(struct Scsi_Host *host,
scsi_release_request(sreq);
out_free_sdev:
if (res == SCSI_SCAN_LUN_PRESENT) {
- if (sdevp)
+ if (sdevp) {
+ scsi_device_get(sdev);
*sdevp = sdev;
+ }
} else {
if (sdev->host->hostt->slave_destroy)
sdev->host->hostt->slave_destroy(sdev);
@@ -748,7 +863,7 @@ static int scsi_probe_and_add_lun(struct Scsi_Host *host,
/**
* scsi_sequential_lun_scan - sequentially scan a SCSI target
- * @sdevscan: scan the host, channel, and id of this Scsi_Device
+ * @starget: pointer to target structure to scan
* @bflags: black/white list flag for LUN 0
* @lun0_res: result of scanning LUN 0
*
@@ -759,14 +874,15 @@ static int scsi_probe_and_add_lun(struct Scsi_Host *host,
*
* Modifies sdevscan->lun.
**/
-static void scsi_sequential_lun_scan(struct Scsi_Host *shost, uint channel,
- uint id, int bflags, int lun0_res, int scsi_level, int rescan)
+static void scsi_sequential_lun_scan(struct scsi_target *starget,
+ int bflags, int lun0_res, int scsi_level,
+ int rescan)
{
unsigned int sparse_lun, lun, max_dev_lun;
+ struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO "scsi scan: Sequential scan of"
- " host %d channel %d id %d\n", shost->host_no,
- channel, id));
+ "%s\n", starget->dev.bus_id));
max_dev_lun = min(max_scsi_luns, shost->max_lun);
/*
@@ -828,8 +944,8 @@ static void scsi_sequential_lun_scan(struct Scsi_Host *shost, uint channel,
* sparse_lun.
*/
for (lun = 1; lun < max_dev_lun; ++lun)
- if ((scsi_probe_and_add_lun(shost, channel, id, lun,
- NULL, NULL, rescan, NULL) != SCSI_SCAN_LUN_PRESENT) &&
+ if ((scsi_probe_and_add_lun(starget, lun, NULL, NULL, rescan,
+ NULL) != SCSI_SCAN_LUN_PRESENT) &&
!sparse_lun)
return;
}
@@ -893,6 +1009,7 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags,
struct scsi_request *sreq;
u8 *data;
struct scsi_sense_hdr sshdr;
+ struct scsi_target *starget = scsi_target(sdev);
/*
* Only support SCSI-3 and up devices if BLIST_NOREPORTLUN is not set.
@@ -1043,8 +1160,8 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags,
} else {
int res;
- res = scsi_probe_and_add_lun(sdev->host, sdev->channel,
- sdev->id, lun, NULL, NULL, rescan, NULL);
+ res = scsi_probe_and_add_lun(starget,
+ lun, NULL, NULL, rescan, NULL);
if (res == SCSI_SCAN_NO_RESPONSE) {
/*
* Got some results, but now none, abort.
@@ -1071,17 +1188,23 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags,
}
struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel,
- uint id, uint lun, void *hostdata)
+ uint id, uint lun, void *hostdata)
{
struct scsi_device *sdev;
+ struct device *parent = &shost->shost_gendev;
int res;
+ struct scsi_target *starget = scsi_alloc_target(parent, channel, id);
+
+ if (!starget)
+ return ERR_PTR(-ENOMEM);
down(&shost->scan_mutex);
- res = scsi_probe_and_add_lun(shost, channel, id, lun, NULL,
- &sdev, 1, hostdata);
+ res = scsi_probe_and_add_lun(starget, lun, NULL, &sdev, 1, hostdata);
if (res != SCSI_SCAN_LUN_PRESENT)
sdev = ERR_PTR(-ENODEV);
up(&shost->scan_mutex);
+ scsi_target_reap(starget);
+ put_device(&starget->dev);
return sdev;
}
@@ -1122,12 +1245,14 @@ EXPORT_SYMBOL(scsi_rescan_device);
* First try a REPORT LUN scan, if that does not scan the target, do a
* sequential scan of LUNs on the target id.
**/
-static void scsi_scan_target(struct Scsi_Host *shost, unsigned int channel,
- unsigned int id, unsigned int lun, int rescan)
+void scsi_scan_target(struct device *parent, unsigned int channel,
+ unsigned int id, unsigned int lun, int rescan)
{
+ struct Scsi_Host *shost = dev_to_shost(parent);
int bflags = 0;
int res;
- struct scsi_device *sdev;
+ struct scsi_device *sdev = NULL;
+ struct scsi_target *starget;
if (shost->this_id == id)
/*
@@ -1135,28 +1260,33 @@ static void scsi_scan_target(struct Scsi_Host *shost, unsigned int channel,
*/
return;
+
+ starget = scsi_alloc_target(parent, channel, id);
+
+ if (!starget)
+ return;
+
+ get_device(&starget->dev);
if (lun != SCAN_WILD_CARD) {
/*
* Scan for a specific host/chan/id/lun.
*/
- scsi_probe_and_add_lun(shost, channel, id, lun, NULL, NULL,
- rescan, NULL);
- return;
+ scsi_probe_and_add_lun(starget, lun, NULL, NULL, rescan, NULL);
+ goto out_reap;
}
/*
* Scan LUN 0, if there is some response, scan further. Ideally, we
* would not configure LUN 0 until all LUNs are scanned.
*/
- res = scsi_probe_and_add_lun(shost, channel, id, 0, &bflags, &sdev,
- rescan, NULL);
+ res = scsi_probe_and_add_lun(starget, 0, &bflags, &sdev, rescan, NULL);
if (res == SCSI_SCAN_LUN_PRESENT) {
if (scsi_report_lun_scan(sdev, bflags, rescan) != 0)
/*
* The REPORT LUN did not scan the target,
* do a sequential scan.
*/
- scsi_sequential_lun_scan(shost, channel, id, bflags,
+ scsi_sequential_lun_scan(starget, bflags,
res, sdev->scsi_level, rescan);
} else if (res == SCSI_SCAN_TARGET_PRESENT) {
/*
@@ -1165,10 +1295,20 @@ static void scsi_scan_target(struct Scsi_Host *shost, unsigned int channel,
* sequential lun scan with a bflags of SPARSELUN and
* a default scsi level of SCSI_2
*/
- scsi_sequential_lun_scan(shost, channel, id, BLIST_SPARSELUN,
+ scsi_sequential_lun_scan(starget, BLIST_SPARSELUN,
SCSI_SCAN_TARGET_PRESENT, SCSI_2, rescan);
}
+ if (sdev)
+ scsi_device_put(sdev);
+
+ out_reap:
+ /* now determine if the target has any children at all
+ * and if not, nuke it */
+ scsi_target_reap(starget);
+
+ put_device(&starget->dev);
}
+EXPORT_SYMBOL(scsi_scan_target);
static void scsi_scan_channel(struct Scsi_Host *shost, unsigned int channel,
unsigned int id, unsigned int lun, int rescan)
@@ -1193,10 +1333,10 @@ static void scsi_scan_channel(struct Scsi_Host *shost, unsigned int channel,
order_id = shost->max_id - id - 1;
else
order_id = id;
- scsi_scan_target(shost, channel, order_id, lun, rescan);
+ scsi_scan_target(&shost->shost_gendev, channel, order_id, lun, rescan);
}
else
- scsi_scan_target(shost, channel, id, lun, rescan);
+ scsi_scan_target(&shost->shost_gendev, channel, id, lun, rescan);
}
int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel,
@@ -1247,7 +1387,7 @@ EXPORT_SYMBOL(scsi_scan_single_target);
void scsi_forget_host(struct Scsi_Host *shost)
{
- struct scsi_device *sdev, *tmp;
+ struct scsi_target *starget, *tmp;
unsigned long flags;
/*
@@ -1260,9 +1400,9 @@ void scsi_forget_host(struct Scsi_Host *shost)
* after that we don't look at sdev anymore.
*/
spin_lock_irqsave(shost->host_lock, flags);
- list_for_each_entry_safe(sdev, tmp, &shost->__devices, siblings) {
+ list_for_each_entry_safe(starget, tmp, &shost->__targets, siblings) {
spin_unlock_irqrestore(shost->host_lock, flags);
- scsi_remove_device(sdev);
+ scsi_remove_target(&starget->dev);
spin_lock_irqsave(shost->host_lock, flags);
}
spin_unlock_irqrestore(shost->host_lock, flags);
@@ -1291,11 +1431,18 @@ void scsi_forget_host(struct Scsi_Host *shost)
struct scsi_device *scsi_get_host_dev(struct Scsi_Host *shost)
{
struct scsi_device *sdev;
+ struct scsi_target *starget;
+
+ starget = scsi_alloc_target(&shost->shost_gendev, 0, shost->this_id);
+ if (!starget)
+ return NULL;
- sdev = scsi_alloc_sdev(shost, 0, shost->this_id, 0, NULL);
+ sdev = scsi_alloc_sdev(starget, 0, NULL);
if (sdev) {
+ sdev->sdev_gendev.parent = get_device(&starget->dev);
sdev->borken = 0;
}
+ put_device(&starget->dev);
return sdev;
}
EXPORT_SYMBOL(scsi_get_host_dev);
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index 11a46f83070d0..134d3a3e4222a 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -154,32 +154,26 @@ void scsi_device_dev_release(struct device *dev)
{
struct scsi_device *sdev;
struct device *parent;
+ struct scsi_target *starget;
unsigned long flags;
- int delete;
parent = dev->parent;
sdev = to_scsi_device(dev);
+ starget = to_scsi_target(parent);
spin_lock_irqsave(sdev->host->host_lock, flags);
- /* If we're the last LUN on the target, destroy the target */
- delete = list_empty(&sdev->same_target_siblings);
+ starget->reap_ref++;
list_del(&sdev->siblings);
list_del(&sdev->same_target_siblings);
list_del(&sdev->starved_entry);
spin_unlock_irqrestore(sdev->host->host_lock, flags);
- if (delete) {
- struct scsi_target *starget = to_scsi_target(parent);
- if (!starget->create) {
- transport_remove_device(&starget->dev);
- device_del(parent);
- }
- transport_destroy_device(&starget->dev);
-
- put_device(parent);
- }
- if (sdev->request_queue)
+ if (sdev->request_queue) {
+ sdev->request_queue->queuedata = NULL;
scsi_free_queue(sdev->request_queue);
+ }
+
+ scsi_target_reap(scsi_target(sdev));
kfree(sdev->inquiry);
kfree(sdev);
@@ -408,6 +402,28 @@ show_queue_type_field(struct device *dev, char *buf)
static DEVICE_ATTR(queue_type, S_IRUGO, show_queue_type_field, NULL);
+static ssize_t
+show_iostat_counterbits(struct device *dev, char *buf)
+{
+ return snprintf(buf, 20, "%d\n", (int)sizeof(atomic_t) * 8);
+}
+
+static DEVICE_ATTR(iocounterbits, S_IRUGO, show_iostat_counterbits, NULL);
+
+#define show_sdev_iostat(field) \
+static ssize_t \
+show_iostat_##field(struct device *dev, char *buf) \
+{ \
+ struct scsi_device *sdev = to_scsi_device(dev); \
+ unsigned long long count = atomic_read(&sdev->field); \
+ return snprintf(buf, 20, "0x%llx\n", count); \
+} \
+static DEVICE_ATTR(field, S_IRUGO, show_iostat_##field, NULL)
+
+show_sdev_iostat(iorequest_cnt);
+show_sdev_iostat(iodone_cnt);
+show_sdev_iostat(ioerr_cnt);
+
/* Default template for device attributes. May NOT be modified */
static struct device_attribute *scsi_sysfs_sdev_attrs[] = {
@@ -423,6 +439,10 @@ static struct device_attribute *scsi_sysfs_sdev_attrs[] = {
&dev_attr_delete,
&dev_attr_state,
&dev_attr_timeout,
+ &dev_attr_iocounterbits,
+ &dev_attr_iorequest_cnt,
+ &dev_attr_iodone_cnt,
+ &dev_attr_ioerr_cnt,
NULL
};
@@ -534,14 +554,6 @@ static int attr_add(struct device *dev, struct device_attribute *attr)
return device_create_file(dev, attr);
}
-static void scsi_target_dev_release(struct device *dev)
-{
- struct scsi_target *starget = to_scsi_target(dev);
- struct device *parent = dev->parent;
- kfree(starget);
- put_device(parent);
-}
-
/**
* scsi_sysfs_add_sdev - add scsi device to sysfs
* @sdev: scsi_device to add
@@ -551,24 +563,7 @@ static void scsi_target_dev_release(struct device *dev)
**/
int scsi_sysfs_add_sdev(struct scsi_device *sdev)
{
- struct scsi_target *starget = sdev->sdev_target;
- struct Scsi_Host *shost = sdev->host;
- int error, i, create;
- unsigned long flags;
-
- spin_lock_irqsave(shost->host_lock, flags);
- create = starget->create;
- starget->create = 0;
- spin_unlock_irqrestore(shost->host_lock, flags);
-
- if (create) {
- error = device_add(&starget->dev);
- if (error) {
- printk(KERN_ERR "Target device_add failed\n");
- return error;
- }
- transport_add_device(&starget->dev);
- }
+ int error, i;
if ((error = scsi_device_set_state(sdev, SDEV_RUNNING)) != 0)
return error;
@@ -617,7 +612,6 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev)
out:
return error;
- class_device_del(&sdev->sdev_classdev);
clean_device:
scsi_device_set_state(sdev, SDEV_CANCEL);
@@ -647,12 +641,57 @@ void scsi_remove_device(struct scsi_device *sdev)
sdev->host->hostt->slave_destroy(sdev);
transport_unregister_device(&sdev->sdev_gendev);
put_device(&sdev->sdev_gendev);
-
out:
up(&shost->scan_mutex);
}
EXPORT_SYMBOL(scsi_remove_device);
+void __scsi_remove_target(struct scsi_target *starget)
+{
+ struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+ unsigned long flags;
+ struct scsi_device *sdev, *tmp;
+
+ spin_lock_irqsave(shost->host_lock, flags);
+ starget->reap_ref++;
+ list_for_each_entry_safe(sdev, tmp, &shost->__devices, siblings) {
+ if (sdev->channel != starget->channel ||
+ sdev->id != starget->id)
+ continue;
+ spin_unlock_irqrestore(shost->host_lock, flags);
+ scsi_remove_device(sdev);
+ spin_lock_irqsave(shost->host_lock, flags);
+ }
+ spin_unlock_irqrestore(shost->host_lock, flags);
+ scsi_target_reap(starget);
+}
+
+/**
+ * scsi_remove_target - try to remove a target and all its devices
+ * @dev: generic starget or parent of generic stargets to be removed
+ *
+ * Note: This is slightly racy. It is possible that if the user
+ * requests the addition of another device then the target won't be
+ * removed.
+ */
+void scsi_remove_target(struct device *dev)
+{
+ struct device *rdev, *idev, *next;
+
+ if (scsi_is_target_device(dev)) {
+ __scsi_remove_target(to_scsi_target(dev));
+ return;
+ }
+
+ rdev = get_device(dev);
+ list_for_each_entry_safe(idev, next, &dev->children, node) {
+ if (scsi_is_target_device(idev))
+ __scsi_remove_target(to_scsi_target(idev));
+ }
+ put_device(rdev);
+}
+EXPORT_SYMBOL(scsi_remove_target);
+
int scsi_register_driver(struct device_driver *drv)
{
drv->bus = &scsi_bus_type;
@@ -741,6 +780,10 @@ int scsi_sysfs_add_host(struct Scsi_Host *shost)
void scsi_sysfs_device_initialize(struct scsi_device *sdev)
{
+ unsigned long flags;
+ struct Scsi_Host *shost = sdev->host;
+ struct scsi_target *starget = sdev->sdev_target;
+
device_initialize(&sdev->sdev_gendev);
sdev->sdev_gendev.bus = &scsi_bus_type;
sdev->sdev_gendev.release = scsi_device_dev_release;
@@ -754,83 +797,20 @@ void scsi_sysfs_device_initialize(struct scsi_device *sdev)
snprintf(sdev->sdev_classdev.class_id, BUS_ID_SIZE,
"%d:%d:%d:%d", sdev->host->host_no,
sdev->channel, sdev->id, sdev->lun);
-
+ sdev->scsi_level = SCSI_2;
transport_setup_device(&sdev->sdev_gendev);
-}
-
-int scsi_is_sdev_device(const struct device *dev)
-{
- return dev->release == scsi_device_dev_release;
-}
-EXPORT_SYMBOL(scsi_is_sdev_device);
-
-int scsi_sysfs_target_initialize(struct scsi_device *sdev)
-{
- struct scsi_target *starget = NULL;
- struct Scsi_Host *shost = sdev->host;
- struct scsi_device *device;
- struct device *dev = NULL;
- unsigned long flags;
- int create = 0;
-
spin_lock_irqsave(shost->host_lock, flags);
- /*
- * Search for an existing target for this sdev.
- */
- list_for_each_entry(device, &shost->__devices, siblings) {
- if (device->id == sdev->id &&
- device->channel == sdev->channel) {
- list_add_tail(&sdev->same_target_siblings,
- &device->same_target_siblings);
- sdev->scsi_level = device->scsi_level;
- starget = device->sdev_target;
- break;
- }
- }
-
- if (!starget) {
- const int size = sizeof(*starget) +
- shost->transportt->target_size;
- starget = kmalloc(size, GFP_ATOMIC);
- if (!starget) {
- printk(KERN_ERR "%s: allocation failure\n", __FUNCTION__);
- spin_unlock_irqrestore(shost->host_lock,
- flags);
- return -ENOMEM;
- }
- memset(starget, 0, size);
- dev = &starget->dev;
- device_initialize(dev);
- dev->parent = get_device(&shost->shost_gendev);
- dev->release = scsi_target_dev_release;
- sprintf(dev->bus_id, "target%d:%d:%d",
- shost->host_no, sdev->channel, sdev->id);
- starget->id = sdev->id;
- starget->channel = sdev->channel;
- create = starget->create = 1;
- /*
- * If there wasn't another lun already configured at
- * this target, then default this device to SCSI_2
- * until we know better
- */
- sdev->scsi_level = SCSI_2;
- }
- get_device(&starget->dev);
- sdev->sdev_gendev.parent = &starget->dev;
- sdev->sdev_target = starget;
+ list_add_tail(&sdev->same_target_siblings, &starget->devices);
list_add_tail(&sdev->siblings, &shost->__devices);
spin_unlock_irqrestore(shost->host_lock, flags);
- if (create)
- transport_setup_device(&starget->dev);
- return 0;
}
-int scsi_is_target_device(const struct device *dev)
+int scsi_is_sdev_device(const struct device *dev)
{
- return dev->release == scsi_target_dev_release;
+ return dev->release == scsi_device_dev_release;
}
-EXPORT_SYMBOL(scsi_is_target_device);
+EXPORT_SYMBOL(scsi_is_sdev_device);
/* A blank transport template that is used in drivers that don't
* yet implement Transport Attributes */
-struct scsi_transport_template blank_transport_template = { NULL, };
+struct scsi_transport_template blank_transport_template = { { { {NULL, }, }, }, };
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index 8e90174d5ce48..35d1c1e8e345d 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -16,6 +16,13 @@
* You should have received a copy of the 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) 2004-2005 James Smart, Emulex Corporation
+ * Rewrite for host, target, device, and remote port attributes,
+ * statistics, and service functions...
+ *
*/
#include <linux/module.h>
#include <linux/init.h>
@@ -90,8 +97,10 @@ static struct {
char *name;
} fc_port_state_names[] = {
{ FC_PORTSTATE_UNKNOWN, "Unknown" },
+ { FC_PORTSTATE_NOTPRESENT, "Not Present" },
{ FC_PORTSTATE_ONLINE, "Online" },
{ FC_PORTSTATE_OFFLINE, "Offline" },
+ { FC_PORTSTATE_BLOCKED, "Blocked" },
{ FC_PORTSTATE_BYPASSED, "Bypassed" },
{ FC_PORTSTATE_DIAGNOSTICS, "Diagnostics" },
{ FC_PORTSTATE_LINKDOWN, "Linkdown" },
@@ -108,9 +117,10 @@ static struct {
char *name;
int matchlen;
} fc_tgtid_binding_type_names[] = {
+ { FC_TGTID_BIND_NONE, "none", 4 },
{ FC_TGTID_BIND_BY_WWPN, "wwpn (World Wide Port Name)", 4 },
{ FC_TGTID_BIND_BY_WWNN, "wwnn (World Wide Node Name)", 4 },
- { FC_TGTID_BIND_BY_ID, "fcportid (FC Address)", 8 },
+ { FC_TGTID_BIND_BY_ID, "port_id (FC Address)", 7 },
};
fc_enum_name_search(tgtid_bind_type, fc_tgtid_binding_type,
fc_tgtid_binding_type_names)
@@ -139,7 +149,7 @@ get_fc_##title##_names(u32 table_key, char *buf) \
}
-/* Convert fc_cos bit values to ascii string name */
+/* Convert FC_COS bit values to ascii string name */
static struct {
u32 value;
char *name;
@@ -153,7 +163,7 @@ static struct {
fc_bitfield_name_search(cos, fc_cos_names)
-/* Convert fc_port_speed bit values to ascii string name */
+/* Convert FC_PORTSPEED bit values to ascii string name */
static struct {
u32 value;
char *name;
@@ -179,67 +189,102 @@ show_fc_fc4s (char *buf, u8 *fc4_list)
}
+/* Convert FC_RPORT_ROLE bit values to ascii string name */
+static struct {
+ u32 value;
+ char *name;
+} fc_remote_port_role_names[] = {
+ { FC_RPORT_ROLE_FCP_TARGET, "FCP Target" },
+ { FC_RPORT_ROLE_FCP_INITIATOR, "FCP Initiator" },
+ { FC_RPORT_ROLE_IP_PORT, "IP Port" },
+};
+fc_bitfield_name_search(remote_port_roles, fc_remote_port_role_names)
-static void fc_timeout_blocked_host(void *data);
-static void fc_timeout_blocked_tgt(void *data);
+/*
+ * Define roles that are specific to port_id. Values are relative to ROLE_MASK.
+ */
+#define FC_WELLKNOWN_PORTID_MASK 0xfffff0
+#define FC_WELLKNOWN_ROLE_MASK 0x00000f
+#define FC_FPORT_PORTID 0x00000e
+#define FC_FABCTLR_PORTID 0x00000d
+#define FC_DIRSRVR_PORTID 0x00000c
+#define FC_TIMESRVR_PORTID 0x00000b
+#define FC_MGMTSRVR_PORTID 0x00000a
-#define FC_STARGET_NUM_ATTRS 4 /* increase this if you add attributes */
-#define FC_STARGET_OTHER_ATTRS 0 /* increase this if you add "always on"
- * attributes */
+
+static void fc_timeout_blocked_rport(void *data);
+static void fc_scsi_scan_rport(void *data);
+static void fc_rport_terminate(struct fc_rport *rport);
+
+/*
+ * Attribute counts pre object type...
+ * Increase these values if you add attributes
+ */
+#define FC_STARGET_NUM_ATTRS 3
+#define FC_RPORT_NUM_ATTRS 9
#define FC_HOST_NUM_ATTRS 15
struct fc_internal {
struct scsi_transport_template t;
struct fc_function_template *f;
- /* The actual attributes */
+
+ /*
+ * For attributes : each object has :
+ * An array of the actual attributes structures
+ * An array of null-terminated pointers to the attribute
+ * structures - used for mid-layer interaction.
+ *
+ * The attribute containers for the starget and host are are
+ * part of the midlayer. As the remote port is specific to the
+ * fc transport, we must provide the attribute container.
+ */
struct class_device_attribute private_starget_attrs[
- FC_STARGET_NUM_ATTRS];
- /* The array of null terminated pointers to attributes
- * needed by scsi_sysfs.c */
- struct class_device_attribute *starget_attrs[
- FC_STARGET_NUM_ATTRS + FC_STARGET_OTHER_ATTRS + 1];
+ FC_STARGET_NUM_ATTRS];
+ struct class_device_attribute *starget_attrs[FC_STARGET_NUM_ATTRS + 1];
struct class_device_attribute private_host_attrs[FC_HOST_NUM_ATTRS];
struct class_device_attribute *host_attrs[FC_HOST_NUM_ATTRS + 1];
+
+ struct transport_container rport_attr_cont;
+ struct class_device_attribute private_rport_attrs[FC_RPORT_NUM_ATTRS];
+ struct class_device_attribute *rport_attrs[FC_RPORT_NUM_ATTRS + 1];
};
#define to_fc_internal(tmpl) container_of(tmpl, struct fc_internal, t)
-static int fc_add_target(struct device *dev)
+static int fc_target_setup(struct device *dev)
{
struct scsi_target *starget = to_scsi_target(dev);
- /*
- * Set default values easily detected by the midlayer as
- * failure cases. The scsi lldd is responsible for initializing
- * all transport attributes to valid values per target.
+ struct fc_rport *rport = starget_to_rport(starget);
+
+ /*
+ * if parent is remote port, use values from remote port.
+ * Otherwise, this host uses the fc_transport, but not the
+ * remote port interface. As such, initialize to known non-values.
*/
- fc_starget_node_name(starget) = -1;
- fc_starget_port_name(starget) = -1;
- fc_starget_port_id(starget) = -1;
- fc_starget_dev_loss_tmo(starget) = -1;
- INIT_WORK(&fc_starget_dev_loss_work(starget),
- fc_timeout_blocked_tgt, starget);
- return 0;
-}
+ if (rport) {
+ fc_starget_node_name(starget) = rport->node_name;
+ fc_starget_port_name(starget) = rport->port_name;
+ fc_starget_port_id(starget) = rport->port_id;
+ } else {
+ fc_starget_node_name(starget) = -1;
+ fc_starget_port_name(starget) = -1;
+ fc_starget_port_id(starget) = -1;
+ }
-static int fc_remove_target(struct device *dev)
-{
- struct scsi_target *starget = to_scsi_target(dev);
- /* Stop the target timer */
- if (cancel_delayed_work(&fc_starget_dev_loss_work(starget)))
- flush_scheduled_work();
return 0;
}
static DECLARE_TRANSPORT_CLASS(fc_transport_class,
"fc_transport",
- fc_add_target,
- fc_remove_target,
+ fc_target_setup,
+ NULL,
NULL);
-static int fc_add_host(struct device *dev)
+static int fc_host_setup(struct device *dev)
{
struct Scsi_Host *shost = dev_to_shost(dev);
+
/*
* Set default values easily detected by the midlayer as
* failure cases. The scsi lldd is responsible for initializing
@@ -254,16 +299,8 @@ static int fc_add_host(struct device *dev)
sizeof(fc_host_symbolic_name(shost)));
fc_host_supported_speeds(shost) = FC_PORTSPEED_UNKNOWN;
fc_host_maxframe_size(shost) = -1;
- memset(fc_host_hardware_version(shost), 0,
- sizeof(fc_host_hardware_version(shost)));
- memset(fc_host_firmware_version(shost), 0,
- sizeof(fc_host_firmware_version(shost)));
memset(fc_host_serial_number(shost), 0,
sizeof(fc_host_serial_number(shost)));
- memset(fc_host_opt_rom_version(shost), 0,
- sizeof(fc_host_opt_rom_version(shost)));
- memset(fc_host_driver_version(shost), 0,
- sizeof(fc_host_driver_version(shost)));
fc_host_port_id(shost) = -1;
fc_host_port_type(shost) = FC_PORTTYPE_UNKNOWN;
@@ -272,93 +309,279 @@ static int fc_add_host(struct device *dev)
sizeof(fc_host_active_fc4s(shost)));
fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
fc_host_fabric_name(shost) = -1;
- fc_host_link_down_tmo(shost) = -1;
fc_host_tgtid_bind_type(shost) = FC_TGTID_BIND_BY_WWPN;
- INIT_WORK(&fc_host_link_down_work(shost),
- fc_timeout_blocked_host, shost);
- return 0;
-}
+ INIT_LIST_HEAD(&fc_host_rports(shost));
+ INIT_LIST_HEAD(&fc_host_rport_bindings(shost));
+ fc_host_next_rport_number(shost) = 0;
+ fc_host_next_target_id(shost) = 0;
-static int fc_remove_host(struct device *dev)
-{
- struct Scsi_Host *shost = dev_to_shost(dev);
- /* Stop the host timer */
- if (cancel_delayed_work(&fc_host_link_down_work(shost)))
- flush_scheduled_work();
return 0;
}
static DECLARE_TRANSPORT_CLASS(fc_host_class,
"fc_host",
- fc_add_host,
- fc_remove_host,
+ fc_host_setup,
+ NULL,
+ NULL);
+
+/*
+ * Setup and Remove actions for remote ports are handled
+ * in the service functions below.
+ */
+static DECLARE_TRANSPORT_CLASS(fc_rport_class,
+ "fc_remote_ports",
+ NULL,
+ NULL,
NULL);
+/*
+ * Module Parameters
+ */
+
+/*
+ * dev_loss_tmo: the default number of seconds that the FC transport
+ * should insulate the loss of a remote port.
+ * The maximum will be capped by the value of SCSI_DEVICE_BLOCK_MAX_TIMEOUT.
+ */
+static unsigned int fc_dev_loss_tmo = SCSI_DEVICE_BLOCK_MAX_TIMEOUT;
+
+module_param_named(dev_loss_tmo, fc_dev_loss_tmo, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(dev_loss_tmo,
+ "Maximum number of seconds that the FC transport should"
+ " insulate the loss of a remote port. Once this value is"
+ " exceeded, the scsi target is removed. Value should be"
+ " between 1 and SCSI_DEVICE_BLOCK_MAX_TIMEOUT.");
+
+
static __init int fc_transport_init(void)
{
int error = transport_class_register(&fc_host_class);
if (error)
return error;
+ error = transport_class_register(&fc_rport_class);
+ if (error)
+ return error;
return transport_class_register(&fc_transport_class);
}
static void __exit fc_transport_exit(void)
{
transport_class_unregister(&fc_transport_class);
+ transport_class_unregister(&fc_rport_class);
transport_class_unregister(&fc_host_class);
}
/*
- * Remote Port (Target) Attribute Management
+ * FC Remote Port Attribute Management
*/
-#define fc_starget_show_function(field, format_string, cast) \
+#define fc_rport_show_function(field, format_string, sz, cast) \
static ssize_t \
-show_fc_starget_##field (struct class_device *cdev, char *buf) \
+show_fc_rport_##field (struct class_device *cdev, char *buf) \
{ \
- struct scsi_target *starget = transport_class_to_starget(cdev); \
- struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); \
+ struct fc_rport *rport = transport_class_to_rport(cdev); \
+ struct Scsi_Host *shost = rport_to_shost(rport); \
struct fc_internal *i = to_fc_internal(shost->transportt); \
- if (i->f->get_starget_##field) \
- i->f->get_starget_##field(starget); \
- return snprintf(buf, 20, format_string, \
- cast fc_starget_##field(starget)); \
+ if (i->f->get_rport_##field) \
+ i->f->get_rport_##field(rport); \
+ return snprintf(buf, sz, format_string, cast rport->field); \
}
-#define fc_starget_store_function(field, format_string) \
+#define fc_rport_store_function(field) \
static ssize_t \
-store_fc_starget_##field(struct class_device *cdev, const char *buf, \
+store_fc_rport_##field(struct class_device *cdev, const char *buf, \
size_t count) \
{ \
int val; \
- struct scsi_target *starget = transport_class_to_starget(cdev); \
- struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); \
+ struct fc_rport *rport = transport_class_to_rport(cdev); \
+ struct Scsi_Host *shost = rport_to_shost(rport); \
struct fc_internal *i = to_fc_internal(shost->transportt); \
- \
val = simple_strtoul(buf, NULL, 0); \
- i->f->set_starget_##field(starget, val); \
+ i->f->set_rport_##field(rport, val); \
return count; \
}
-#define fc_starget_rd_attr(field, format_string) \
- fc_starget_show_function(field, format_string, ) \
+#define fc_rport_rd_attr(field, format_string, sz) \
+ fc_rport_show_function(field, format_string, sz, ) \
+static FC_CLASS_DEVICE_ATTR(rport, field, S_IRUGO, \
+ show_fc_rport_##field, NULL)
+
+#define fc_rport_rd_attr_cast(field, format_string, sz, cast) \
+ fc_rport_show_function(field, format_string, sz, (cast)) \
+static FC_CLASS_DEVICE_ATTR(rport, field, S_IRUGO, \
+ show_fc_rport_##field, NULL)
+
+#define fc_rport_rw_attr(field, format_string, sz) \
+ fc_rport_show_function(field, format_string, sz, ) \
+ fc_rport_store_function(field) \
+static FC_CLASS_DEVICE_ATTR(rport, field, S_IRUGO | S_IWUSR, \
+ show_fc_rport_##field, \
+ store_fc_rport_##field)
+
+
+#define fc_private_rport_show_function(field, format_string, sz, cast) \
+static ssize_t \
+show_fc_rport_##field (struct class_device *cdev, char *buf) \
+{ \
+ struct fc_rport *rport = transport_class_to_rport(cdev); \
+ return snprintf(buf, sz, format_string, cast rport->field); \
+}
+
+#define fc_private_rport_rd_attr(field, format_string, sz) \
+ fc_private_rport_show_function(field, format_string, sz, ) \
+static FC_CLASS_DEVICE_ATTR(rport, field, S_IRUGO, \
+ show_fc_rport_##field, NULL)
+
+#define fc_private_rport_rd_attr_cast(field, format_string, sz, cast) \
+ fc_private_rport_show_function(field, format_string, sz, (cast)) \
+static FC_CLASS_DEVICE_ATTR(rport, field, S_IRUGO, \
+ show_fc_rport_##field, NULL)
+
+
+#define fc_private_rport_rd_enum_attr(title, maxlen) \
+static ssize_t \
+show_fc_rport_##title (struct class_device *cdev, char *buf) \
+{ \
+ struct fc_rport *rport = transport_class_to_rport(cdev); \
+ const char *name; \
+ name = get_fc_##title##_name(rport->title); \
+ if (!name) \
+ return -EINVAL; \
+ return snprintf(buf, maxlen, "%s\n", name); \
+} \
+static FC_CLASS_DEVICE_ATTR(rport, title, S_IRUGO, \
+ show_fc_rport_##title, NULL)
+
+
+#define SETUP_RPORT_ATTRIBUTE_RD(field) \
+ i->private_rport_attrs[count] = class_device_attr_rport_##field; \
+ i->private_rport_attrs[count].attr.mode = S_IRUGO; \
+ i->private_rport_attrs[count].store = NULL; \
+ i->rport_attrs[count] = &i->private_rport_attrs[count]; \
+ if (i->f->show_rport_##field) \
+ count++
+
+#define SETUP_PRIVATE_RPORT_ATTRIBUTE_RD(field) \
+ i->private_rport_attrs[count] = class_device_attr_rport_##field; \
+ i->private_rport_attrs[count].attr.mode = S_IRUGO; \
+ i->private_rport_attrs[count].store = NULL; \
+ i->rport_attrs[count] = &i->private_rport_attrs[count]; \
+ count++
+
+#define SETUP_RPORT_ATTRIBUTE_RW(field) \
+ i->private_rport_attrs[count] = class_device_attr_rport_##field; \
+ if (!i->f->set_rport_##field) { \
+ i->private_rport_attrs[count].attr.mode = S_IRUGO; \
+ i->private_rport_attrs[count].store = NULL; \
+ } \
+ i->rport_attrs[count] = &i->private_rport_attrs[count]; \
+ if (i->f->show_rport_##field) \
+ count++
+
+
+/* The FC Transport Remote Port Attributes: */
+
+/* Fixed Remote Port Attributes */
+
+fc_private_rport_rd_attr(maxframe_size, "%u bytes\n", 20);
+
+static ssize_t
+show_fc_rport_supported_classes (struct class_device *cdev, char *buf)
+{
+ struct fc_rport *rport = transport_class_to_rport(cdev);
+ if (rport->supported_classes == FC_COS_UNSPECIFIED)
+ return snprintf(buf, 20, "unspecified\n");
+ return get_fc_cos_names(rport->supported_classes, buf);
+}
+static FC_CLASS_DEVICE_ATTR(rport, supported_classes, S_IRUGO,
+ show_fc_rport_supported_classes, NULL);
+
+/* Dynamic Remote Port Attributes */
+
+fc_rport_rw_attr(dev_loss_tmo, "%d\n", 20);
+
+
+/* Private Remote Port Attributes */
+
+fc_private_rport_rd_attr_cast(node_name, "0x%llx\n", 20, unsigned long long);
+fc_private_rport_rd_attr_cast(port_name, "0x%llx\n", 20, unsigned long long);
+fc_private_rport_rd_attr(port_id, "0x%06x\n", 20);
+
+static ssize_t
+show_fc_rport_roles (struct class_device *cdev, char *buf)
+{
+ struct fc_rport *rport = transport_class_to_rport(cdev);
+
+ /* identify any roles that are port_id specific */
+ if ((rport->port_id != -1) &&
+ (rport->port_id & FC_WELLKNOWN_PORTID_MASK) ==
+ FC_WELLKNOWN_PORTID_MASK) {
+ switch (rport->port_id & FC_WELLKNOWN_ROLE_MASK) {
+ case FC_FPORT_PORTID:
+ return snprintf(buf, 30, "Fabric Port\n");
+ case FC_FABCTLR_PORTID:
+ return snprintf(buf, 30, "Fabric Controller\n");
+ case FC_DIRSRVR_PORTID:
+ return snprintf(buf, 30, "Directory Server\n");
+ case FC_TIMESRVR_PORTID:
+ return snprintf(buf, 30, "Time Server\n");
+ case FC_MGMTSRVR_PORTID:
+ return snprintf(buf, 30, "Management Server\n");
+ default:
+ return snprintf(buf, 30, "Unknown Fabric Entity\n");
+ }
+ } else {
+ if (rport->roles == FC_RPORT_ROLE_UNKNOWN)
+ return snprintf(buf, 20, "unknown\n");
+ return get_fc_remote_port_roles_names(rport->roles, buf);
+ }
+}
+static FC_CLASS_DEVICE_ATTR(rport, roles, S_IRUGO,
+ show_fc_rport_roles, NULL);
+
+fc_private_rport_rd_enum_attr(port_state, FC_PORTSTATE_MAX_NAMELEN);
+fc_private_rport_rd_attr(scsi_target_id, "%d\n", 20);
+
+
+
+/*
+ * FC SCSI Target Attribute Management
+ */
+
+/*
+ * Note: in the target show function we recognize when the remote
+ * port is in the heirarchy and do not allow the driver to get
+ * involved in sysfs functions. The driver only gets involved if
+ * it's the "old" style that doesn't use rports.
+ */
+#define fc_starget_show_function(field, format_string, sz, cast) \
+static ssize_t \
+show_fc_starget_##field (struct class_device *cdev, char *buf) \
+{ \
+ struct scsi_target *starget = transport_class_to_starget(cdev); \
+ struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); \
+ struct fc_internal *i = to_fc_internal(shost->transportt); \
+ struct fc_rport *rport = starget_to_rport(starget); \
+ if (rport) \
+ fc_starget_##field(starget) = rport->field; \
+ else if (i->f->get_starget_##field) \
+ i->f->get_starget_##field(starget); \
+ return snprintf(buf, sz, format_string, \
+ cast fc_starget_##field(starget)); \
+}
+
+#define fc_starget_rd_attr(field, format_string, sz) \
+ fc_starget_show_function(field, format_string, sz, ) \
static FC_CLASS_DEVICE_ATTR(starget, field, S_IRUGO, \
show_fc_starget_##field, NULL)
-#define fc_starget_rd_attr_cast(field, format_string, cast) \
- fc_starget_show_function(field, format_string, (cast)) \
+#define fc_starget_rd_attr_cast(field, format_string, sz, cast) \
+ fc_starget_show_function(field, format_string, sz, (cast)) \
static FC_CLASS_DEVICE_ATTR(starget, field, S_IRUGO, \
show_fc_starget_##field, NULL)
-#define fc_starget_rw_attr(field, format_string) \
- fc_starget_show_function(field, format_string, ) \
- fc_starget_store_function(field, format_string) \
-static FC_CLASS_DEVICE_ATTR(starget, field, S_IRUGO | S_IWUSR, \
- show_fc_starget_##field, \
- store_fc_starget_##field)
-
#define SETUP_STARGET_ATTRIBUTE_RD(field) \
i->private_starget_attrs[count] = class_device_attr_starget_##field; \
i->private_starget_attrs[count].attr.mode = S_IRUGO; \
@@ -377,12 +600,10 @@ static FC_CLASS_DEVICE_ATTR(starget, field, S_IRUGO | S_IWUSR, \
if (i->f->show_starget_##field) \
count++
-/* The FC Tranport Remote Port (Target) Attributes: */
-fc_starget_rd_attr_cast(node_name, "0x%llx\n", unsigned long long);
-fc_starget_rd_attr_cast(port_name, "0x%llx\n", unsigned long long);
-fc_starget_rd_attr(port_id, "0x%06x\n");
-fc_starget_rw_attr(dev_loss_tmo, "%d\n");
-
+/* The FC Transport SCSI Target Attributes: */
+fc_starget_rd_attr_cast(node_name, "0x%llx\n", 20, unsigned long long);
+fc_starget_rd_attr_cast(port_name, "0x%llx\n", 20, unsigned long long);
+fc_starget_rd_attr(port_id, "0x%06x\n", 20);
/*
@@ -400,7 +621,7 @@ show_fc_host_##field (struct class_device *cdev, char *buf) \
return snprintf(buf, sz, format_string, cast fc_host_##field(shost)); \
}
-#define fc_host_store_function(field, format_string) \
+#define fc_host_store_function(field) \
static ssize_t \
store_fc_host_##field(struct class_device *cdev, const char *buf, \
size_t count) \
@@ -426,7 +647,7 @@ static FC_CLASS_DEVICE_ATTR(host, field, S_IRUGO, \
#define fc_host_rw_attr(field, format_string, sz) \
fc_host_show_function(field, format_string, sz, ) \
- fc_host_store_function(field, format_string) \
+ fc_host_store_function(field) \
static FC_CLASS_DEVICE_ATTR(host, field, S_IRUGO | S_IWUSR, \
show_fc_host_##field, \
store_fc_host_##field)
@@ -539,11 +760,7 @@ 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(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(hardware_version, "%s\n", (FC_VERSION_STRING_SIZE +1));
-fc_private_host_rd_attr(firmware_version, "%s\n", (FC_VERSION_STRING_SIZE +1));
fc_private_host_rd_attr(serial_number, "%s\n", (FC_SERIAL_NUMBER_SIZE +1));
-fc_private_host_rd_attr(opt_rom_version, "%s\n", (FC_VERSION_STRING_SIZE +1));
-fc_private_host_rd_attr(driver_version, "%s\n", (FC_VERSION_STRING_SIZE +1));
/* Dynamic Host Attributes */
@@ -584,7 +801,6 @@ fc_host_rd_attr(port_id, "0x%06x\n", 20);
fc_host_rd_enum_attr(port_type, FC_PORTTYPE_MAX_NAMELEN);
fc_host_rd_enum_attr(port_state, FC_PORTSTATE_MAX_NAMELEN);
fc_host_rd_attr_cast(fabric_name, "0x%llx\n", 20, unsigned long long);
-fc_host_rw_attr(link_down_tmo, "%d\n", 20);
/* Private Host Attributes */
@@ -606,10 +822,22 @@ store_fc_private_host_tgtid_bind_type(struct class_device *cdev,
const char *buf, size_t count)
{
struct Scsi_Host *shost = transport_class_to_shost(cdev);
- enum fc_tgtid_binding_type val;
+ struct fc_rport *rport, *next_rport;
+ enum fc_tgtid_binding_type val;
+ unsigned long flags;
if (get_fc_tgtid_bind_type_match(buf, &val))
return -EINVAL;
+
+ /* if changing bind type, purge all unused consistent bindings */
+ if (val != fc_host_tgtid_bind_type(shost)) {
+ spin_lock_irqsave(shost->host_lock, flags);
+ list_for_each_entry_safe(rport, next_rport,
+ &fc_host_rport_bindings(shost), peers)
+ fc_rport_terminate(rport);
+ spin_unlock_irqrestore(shost->host_lock, flags);
+ }
+
fc_host_tgtid_bind_type(shost) = val;
return count;
}
@@ -734,13 +962,13 @@ static int fc_host_match(struct attribute_container *cont,
return 0;
shost = dev_to_shost(dev);
- if (!shost->transportt || shost->transportt->host_attrs.class
+ if (!shost->transportt || shost->transportt->host_attrs.ac.class
!= &fc_host_class.class)
return 0;
i = to_fc_internal(shost->transportt);
-
- return &i->t.host_attrs == cont;
+
+ return &i->t.host_attrs.ac == cont;
}
static int fc_target_match(struct attribute_container *cont,
@@ -753,62 +981,99 @@ static int fc_target_match(struct attribute_container *cont,
return 0;
shost = dev_to_shost(dev->parent);
- if (!shost->transportt || shost->transportt->host_attrs.class
+ if (!shost->transportt || shost->transportt->host_attrs.ac.class
!= &fc_host_class.class)
return 0;
i = to_fc_internal(shost->transportt);
-
- return &i->t.target_attrs == cont;
+
+ return &i->t.target_attrs.ac == cont;
}
+static void fc_rport_dev_release(struct device *dev)
+{
+ struct fc_rport *rport = dev_to_rport(dev);
+ put_device(dev->parent);
+ kfree(rport);
+}
+
+int scsi_is_fc_rport(const struct device *dev)
+{
+ return dev->release == fc_rport_dev_release;
+}
+EXPORT_SYMBOL(scsi_is_fc_rport);
+
+static int fc_rport_match(struct attribute_container *cont,
+ struct device *dev)
+{
+ struct Scsi_Host *shost;
+ struct fc_internal *i;
+
+ if (!scsi_is_fc_rport(dev))
+ return 0;
+
+ shost = dev_to_shost(dev->parent);
+ if (!shost->transportt || shost->transportt->host_attrs.ac.class
+ != &fc_host_class.class)
+ return 0;
+
+ i = to_fc_internal(shost->transportt);
+
+ return &i->rport_attr_cont.ac == cont;
+}
struct scsi_transport_template *
fc_attach_transport(struct fc_function_template *ft)
{
struct fc_internal *i = kmalloc(sizeof(struct fc_internal),
GFP_KERNEL);
- int count = 0;
+ int count;
if (unlikely(!i))
return NULL;
memset(i, 0, sizeof(struct fc_internal));
- i->t.target_attrs.attrs = &i->starget_attrs[0];
- i->t.target_attrs.class = &fc_transport_class.class;
- i->t.target_attrs.match = fc_target_match;
- attribute_container_register(&i->t.target_attrs);
+ i->t.target_attrs.ac.attrs = &i->starget_attrs[0];
+ i->t.target_attrs.ac.class = &fc_transport_class.class;
+ i->t.target_attrs.ac.match = fc_target_match;
i->t.target_size = sizeof(struct fc_starget_attrs);
+ transport_container_register(&i->t.target_attrs);
- i->t.host_attrs.attrs = &i->host_attrs[0];
- i->t.host_attrs.class = &fc_host_class.class;
- i->t.host_attrs.match = fc_host_match;
- attribute_container_register(&i->t.host_attrs);
+ i->t.host_attrs.ac.attrs = &i->host_attrs[0];
+ i->t.host_attrs.ac.class = &fc_host_class.class;
+ i->t.host_attrs.ac.match = fc_host_match;
i->t.host_size = sizeof(struct fc_host_attrs);
-
if (ft->get_fc_host_stats)
- i->t.host_statistics = &fc_statistics_group;
+ i->t.host_attrs.statistics = &fc_statistics_group;
+ transport_container_register(&i->t.host_attrs);
+
+ i->rport_attr_cont.ac.attrs = &i->rport_attrs[0];
+ i->rport_attr_cont.ac.class = &fc_rport_class.class;
+ i->rport_attr_cont.ac.match = fc_rport_match;
+ transport_container_register(&i->rport_attr_cont);
i->f = ft;
+ /* Transport uses the shost workq for scsi scanning */
+ i->t.create_work_queue = 1;
/*
- * setup remote port (target) attributes
+ * Setup SCSI Target Attributes.
*/
- SETUP_STARGET_ATTRIBUTE_RD(port_id);
- SETUP_STARGET_ATTRIBUTE_RD(port_name);
+ count = 0;
SETUP_STARGET_ATTRIBUTE_RD(node_name);
- SETUP_STARGET_ATTRIBUTE_RW(dev_loss_tmo);
+ SETUP_STARGET_ATTRIBUTE_RD(port_name);
+ SETUP_STARGET_ATTRIBUTE_RD(port_id);
BUG_ON(count > FC_STARGET_NUM_ATTRS);
- /* Setup the always-on attributes here */
-
i->starget_attrs[count] = NULL;
- /* setup host attributes */
+ /*
+ * Setup SCSI Host Attributes.
+ */
count=0;
SETUP_HOST_ATTRIBUTE_RD(node_name);
SETUP_HOST_ATTRIBUTE_RD(port_name);
@@ -817,11 +1082,7 @@ fc_attach_transport(struct fc_function_template *ft)
SETUP_HOST_ATTRIBUTE_RD(symbolic_name);
SETUP_HOST_ATTRIBUTE_RD(supported_speeds);
SETUP_HOST_ATTRIBUTE_RD(maxframe_size);
- SETUP_HOST_ATTRIBUTE_RD(hardware_version);
- SETUP_HOST_ATTRIBUTE_RD(firmware_version);
SETUP_HOST_ATTRIBUTE_RD(serial_number);
- SETUP_HOST_ATTRIBUTE_RD(opt_rom_version);
- SETUP_HOST_ATTRIBUTE_RD(driver_version);
SETUP_HOST_ATTRIBUTE_RD(port_id);
SETUP_HOST_ATTRIBUTE_RD(port_type);
@@ -829,7 +1090,6 @@ fc_attach_transport(struct fc_function_template *ft)
SETUP_HOST_ATTRIBUTE_RD(active_fc4s);
SETUP_HOST_ATTRIBUTE_RD(speed);
SETUP_HOST_ATTRIBUTE_RD(fabric_name);
- SETUP_HOST_ATTRIBUTE_RW(link_down_tmo);
/* Transport-managed attributes */
SETUP_PRIVATE_HOST_ATTRIBUTE_RW(tgtid_bind_type);
@@ -838,6 +1098,23 @@ fc_attach_transport(struct fc_function_template *ft)
i->host_attrs[count] = NULL;
+ /*
+ * Setup Remote Port Attributes.
+ */
+ count=0;
+ SETUP_RPORT_ATTRIBUTE_RD(maxframe_size);
+ SETUP_RPORT_ATTRIBUTE_RD(supported_classes);
+ SETUP_RPORT_ATTRIBUTE_RW(dev_loss_tmo);
+ SETUP_PRIVATE_RPORT_ATTRIBUTE_RD(node_name);
+ SETUP_PRIVATE_RPORT_ATTRIBUTE_RD(port_name);
+ SETUP_PRIVATE_RPORT_ATTRIBUTE_RD(port_id);
+ SETUP_PRIVATE_RPORT_ATTRIBUTE_RD(roles);
+ SETUP_PRIVATE_RPORT_ATTRIBUTE_RD(port_state);
+ SETUP_PRIVATE_RPORT_ATTRIBUTE_RD(scsi_target_id);
+
+ BUG_ON(count > FC_RPORT_NUM_ATTRS);
+
+ i->rport_attrs[count] = NULL;
return &i->t;
}
@@ -847,205 +1124,538 @@ void fc_release_transport(struct scsi_transport_template *t)
{
struct fc_internal *i = to_fc_internal(t);
- attribute_container_unregister(&i->t.target_attrs);
- attribute_container_unregister(&i->t.host_attrs);
+ transport_container_unregister(&i->t.target_attrs);
+ transport_container_unregister(&i->t.host_attrs);
+ transport_container_unregister(&i->rport_attr_cont);
kfree(i);
}
EXPORT_SYMBOL(fc_release_transport);
-
/**
- * fc_device_block - called by target functions to block a scsi device
- * @dev: scsi device
- * @data: unused
+ * fc_remove_host - called to terminate any fc_transport-related elements
+ * for a scsi host.
+ * @rport: remote port to be unblocked.
+ *
+ * This routine is expected to be called immediately preceeding the
+ * a driver's call to scsi_remove_host().
+ *
+ * WARNING: A driver utilizing the fc_transport, which fails to call
+ * this routine prior to scsi_remote_host(), will leave dangling
+ * objects in /sys/class/fc_remote_ports. Access to any of these
+ * objects can result in a system crash !!!
+ *
+ * Notes:
+ * This routine assumes no locks are held on entry.
**/
-static void fc_device_block(struct scsi_device *sdev, void *data)
+void
+fc_remove_host(struct Scsi_Host *shost)
{
- scsi_internal_device_block(sdev);
+ struct fc_rport *rport, *next_rport;
+
+ /* Remove any remote ports */
+ list_for_each_entry_safe(rport, next_rport,
+ &fc_host_rports(shost), peers)
+ fc_rport_terminate(rport);
+ list_for_each_entry_safe(rport, next_rport,
+ &fc_host_rport_bindings(shost), peers)
+ fc_rport_terminate(rport);
}
+EXPORT_SYMBOL(fc_remove_host);
/**
- * fc_device_unblock - called by target functions to unblock a scsi device
- * @dev: scsi device
- * @data: unused
+ * fc_rport_create - allocates and creates a remote FC port.
+ * @shost: scsi host the remote port is connected to.
+ * @channel: Channel on shost port connected to.
+ * @ids: The world wide names, fc address, and FC4 port
+ * roles for the remote port.
+ *
+ * Allocates and creates the remoter port structure, including the
+ * class and sysfs creation.
+ *
+ * Notes:
+ * This routine assumes no locks are held on entry.
**/
-static void fc_device_unblock(struct scsi_device *sdev, void *data)
+struct fc_rport *
+fc_rport_create(struct Scsi_Host *shost, int channel,
+ struct fc_rport_identifiers *ids)
{
- scsi_internal_device_unblock(sdev);
+ struct fc_host_attrs *fc_host =
+ (struct fc_host_attrs *)shost->shost_data;
+ struct fc_internal *fci = to_fc_internal(shost->transportt);
+ struct fc_rport *rport;
+ struct device *dev;
+ unsigned long flags;
+ int error;
+ size_t size;
+
+ size = (sizeof(struct fc_rport) + fci->f->dd_fcrport_size);
+ rport = kmalloc(size, GFP_KERNEL);
+ if (unlikely(!rport)) {
+ printk(KERN_ERR "%s: allocation failure\n", __FUNCTION__);
+ return NULL;
+ }
+ memset(rport, 0, size);
+
+ rport->maxframe_size = -1;
+ rport->supported_classes = FC_COS_UNSPECIFIED;
+ rport->dev_loss_tmo = fc_dev_loss_tmo;
+ memcpy(&rport->node_name, &ids->node_name, sizeof(rport->node_name));
+ memcpy(&rport->port_name, &ids->port_name, sizeof(rport->port_name));
+ rport->port_id = ids->port_id;
+ rport->roles = ids->roles;
+ rport->port_state = FC_PORTSTATE_ONLINE;
+ if (fci->f->dd_fcrport_size)
+ rport->dd_data = &rport[1];
+ rport->channel = channel;
+
+ INIT_WORK(&rport->dev_loss_work, fc_timeout_blocked_rport, rport);
+ INIT_WORK(&rport->scan_work, fc_scsi_scan_rport, rport);
+
+ spin_lock_irqsave(shost->host_lock, flags);
+
+ rport->number = fc_host->next_rport_number++;
+ if (rport->roles & FC_RPORT_ROLE_FCP_TARGET)
+ rport->scsi_target_id = fc_host->next_target_id++;
+ else
+ rport->scsi_target_id = -1;
+ list_add_tail(&rport->peers, &fc_host_rports(shost));
+ get_device(&shost->shost_gendev);
+
+ spin_unlock_irqrestore(shost->host_lock, flags);
+
+ dev = &rport->dev;
+ device_initialize(dev);
+ dev->parent = get_device(&shost->shost_gendev);
+ dev->release = fc_rport_dev_release;
+ sprintf(dev->bus_id, "rport-%d:%d-%d",
+ shost->host_no, channel, rport->number);
+ transport_setup_device(dev);
+
+ error = device_add(dev);
+ if (error) {
+ printk(KERN_ERR "FC Remote Port device_add failed\n");
+ goto delete_rport;
+ }
+ transport_add_device(dev);
+ transport_configure_device(dev);
+
+ if (rport->roles & FC_RPORT_ROLE_FCP_TARGET)
+ /* initiate a scan of the target */
+ scsi_queue_work(shost, &rport->scan_work);
+
+ return rport;
+
+delete_rport:
+ transport_destroy_device(dev);
+ put_device(dev->parent);
+ spin_lock_irqsave(shost->host_lock, flags);
+ list_del(&rport->peers);
+ put_device(&shost->shost_gendev);
+ spin_unlock_irqrestore(shost->host_lock, flags);
+ put_device(dev->parent);
+ kfree(rport);
+ return NULL;
}
/**
- * fc_timeout_blocked_tgt - Timeout handler for blocked scsi targets
- * that fail to recover in the alloted time.
- * @data: scsi target that failed to reappear in the alloted time.
+ * fc_remote_port_add - notifies the fc transport of the existence
+ * of a remote FC port.
+ * @shost: scsi host the remote port is connected to.
+ * @channel: Channel on shost port connected to.
+ * @ids: The world wide names, fc address, and FC4 port
+ * roles for the remote port.
+ *
+ * The LLDD calls this routine to notify the transport of the existence
+ * of a remote port. The LLDD provides the unique identifiers (wwpn,wwn)
+ * of the port, it's FC address (port_id), and the FC4 roles that are
+ * active for the port.
+ *
+ * For ports that are FCP targets (aka scsi targets), the FC transport
+ * maintains consistent target id bindings on behalf of the LLDD.
+ * A consistent target id binding is an assignment of a target id to
+ * a remote port identifier, which persists while the scsi host is
+ * attached. The remote port can disappear, then later reappear, and
+ * it's target id assignment remains the same. This allows for shifts
+ * in FC addressing (if binding by wwpn or wwnn) with no apparent
+ * changes to the scsi subsystem which is based on scsi host number and
+ * target id values. Bindings are only valid during the attachment of
+ * the scsi host. If the host detaches, then later re-attaches, target
+ * id bindings may change.
+ *
+ * This routine is responsible for returning a remote port structure.
+ * The routine will search the list of remote ports it maintains
+ * internally on behalf of consistent target id mappings. If found, the
+ * remote port structure will be reused. Otherwise, a new remote port
+ * structure will be allocated.
+ *
+ * Whenever a remote port is allocated, a new fc_remote_port class
+ * device is created.
+ *
+ * Should not be called from interrupt context.
+ *
+ * Notes:
+ * This routine assumes no locks are held on entry.
**/
-static void fc_timeout_blocked_tgt(void *data)
+struct fc_rport *
+fc_remote_port_add(struct Scsi_Host *shost, int channel,
+ struct fc_rport_identifiers *ids)
{
- struct scsi_target *starget = (struct scsi_target *)data;
+ struct fc_rport *rport;
+ unsigned long flags;
+ int match = 0;
+
+ if (likely((ids->roles & FC_RPORT_ROLE_FCP_TARGET) &&
+ (fc_host_tgtid_bind_type(shost) != FC_TGTID_BIND_NONE))) {
+
+ /* search for a matching consistent binding */
+
+ spin_lock_irqsave(shost->host_lock, flags);
+
+ list_for_each_entry(rport, &fc_host_rport_bindings(shost),
+ peers) {
+ if (rport->channel != channel)
+ continue;
+
+ switch (fc_host_tgtid_bind_type(shost)) {
+ case FC_TGTID_BIND_BY_WWPN:
+ if (rport->port_name == ids->port_name)
+ match = 1;
+ break;
+ case FC_TGTID_BIND_BY_WWNN:
+ if (rport->node_name == ids->node_name)
+ match = 1;
+ break;
+ case FC_TGTID_BIND_BY_ID:
+ if (rport->port_id == ids->port_id)
+ match = 1;
+ break;
+ case FC_TGTID_BIND_NONE: /* to keep compiler happy */
+ break;
+ }
+
+ if (match) {
+ list_move_tail(&rport->peers,
+ &fc_host_rports(shost));
+ break;
+ }
+ }
+
+ spin_unlock_irqrestore(shost->host_lock, flags);
+
+ if (match) {
+ memcpy(&rport->node_name, &ids->node_name,
+ sizeof(rport->node_name));
+ memcpy(&rport->port_name, &ids->port_name,
+ sizeof(rport->port_name));
+ rport->port_id = ids->port_id;
+ rport->roles = ids->roles;
+ rport->port_state = FC_PORTSTATE_ONLINE;
+
+ if (rport->roles & FC_RPORT_ROLE_FCP_TARGET)
+ /* initiate a scan of the target */
+ scsi_queue_work(shost, &rport->scan_work);
+
+ return rport;
+ }
+ }
- dev_printk(KERN_ERR, &starget->dev,
- "blocked target time out: target resuming\n");
+ /* No consistent binding found - create new remote port entry */
+ rport = fc_rport_create(shost, channel, ids);
- /*
- * set the device going again ... if the scsi lld didn't
- * unblock this device, then IO errors will probably
- * result if the host still isn't ready.
- */
- starget_for_each_device(starget, NULL, fc_device_unblock);
+ return rport;
+}
+EXPORT_SYMBOL(fc_remote_port_add);
+
+/*
+ * fc_rport_tgt_remove - Removes the scsi target on the remote port
+ * @rport: The remote port to be operated on
+ */
+static void
+fc_rport_tgt_remove(struct fc_rport *rport)
+{
+ struct Scsi_Host *shost = rport_to_shost(rport);
+
+ scsi_target_unblock(&rport->dev);
+
+ /* Stop anything on the workq */
+ if (!cancel_delayed_work(&rport->dev_loss_work))
+ flush_scheduled_work();
+ scsi_flush_work(shost);
+
+ scsi_remove_target(&rport->dev);
+}
+
+/*
+ * fc_rport_terminate - this routine tears down and deallocates a remote port.
+ * @rport: The remote port to be terminated
+ *
+ * Notes:
+ * This routine assumes no locks are held on entry.
+ */
+static void
+fc_rport_terminate(struct fc_rport *rport)
+{
+ struct Scsi_Host *shost = rport_to_shost(rport);
+ struct device *dev = &rport->dev;
+ unsigned long flags;
+
+ fc_rport_tgt_remove(rport);
+
+ transport_remove_device(dev);
+ device_del(dev);
+ transport_destroy_device(dev);
+ spin_lock_irqsave(shost->host_lock, flags);
+ list_del(&rport->peers);
+ spin_unlock_irqrestore(shost->host_lock, flags);
+ put_device(&shost->shost_gendev);
}
/**
- * fc_target_block - block a target by temporarily putting all its scsi devices
- * into the SDEV_BLOCK state.
- * @starget: scsi target managed by this fc scsi lldd.
+ * fc_remote_port_delete - notifies the fc transport that a remote
+ * port is no longer in existence.
+ * @rport: The remote port that no longer exists
*
- * scsi lldd's with a FC transport call this routine to temporarily stop all
- * scsi commands to all devices managed by this scsi target. Called
- * from interrupt or normal process context.
+ * The LLDD calls this routine to notify the transport that a remote
+ * port is no longer part of the topology. Note: Although a port
+ * may no longer be part of the topology, it may persist in the remote
+ * ports displayed by the fc_host. This is done so that target id
+ * mappings (managed via the remote port structures), are always visible
+ * as long as the mapping is valid, regardless of port state,
*
- * Returns zero if successful or error if not
+ * If the remote port is not an FCP Target, it will be fully torn down
+ * and deallocated, including the fc_remote_port class device.
*
- * Notes:
- * The timeout and timer types are extracted from the fc transport
- * attributes from the caller's target pointer. This routine assumes no
- * locks are held on entry.
+ * If the remote port is an FCP Target, the port structure will be
+ * marked as Not Present, but will remain as long as there is a valid
+ * SCSI target id mapping associated with the port structure. Validity
+ * is determined by the binding type. If binding by wwpn, then the port
+ * structure is always valid and will not be deallocated until the host
+ * is removed. If binding by wwnn, then the port structure is valid
+ * until another port with the same node name is found in the topology.
+ * If binding by port id (fc address), then the port structure is valid
+ * valid until another port with the same address is identified.
+ *
+ * Called from interrupt or normal process context.
+ *
+ * Notes:
+ * This routine assumes no locks are held on entry.
**/
-int
-fc_target_block(struct scsi_target *starget)
+void
+fc_remote_port_delete(struct fc_rport *rport)
{
- int timeout = fc_starget_dev_loss_tmo(starget);
- struct work_struct *work = &fc_starget_dev_loss_work(starget);
+ struct Scsi_Host *shost = rport_to_shost(rport);
+ unsigned long flags;
+
+ /* If no scsi target id mapping or consistent binding type, delete it */
+ if ((rport->scsi_target_id == -1) ||
+ (fc_host_tgtid_bind_type(shost) == FC_TGTID_BIND_NONE)) {
+ fc_rport_terminate(rport);
+ return;
+ }
- if (timeout < 0 || timeout > SCSI_DEVICE_BLOCK_MAX_TIMEOUT)
- return -EINVAL;
+ fc_rport_tgt_remove(rport);
- starget_for_each_device(starget, NULL, fc_device_block);
+ spin_lock_irqsave(shost->host_lock, flags);
+ list_move_tail(&rport->peers, &fc_host_rport_bindings(shost));
+ spin_unlock_irqrestore(shost->host_lock, flags);
- /* The scsi lld blocks this target for the timeout period only. */
- schedule_delayed_work(work, timeout * HZ);
+ /*
+ * Note: We do not remove or clear the hostdata area. This allows
+ * host-specific target data to persist along with the
+ * scsi_target_id. It's up to the host to manage it's hostdata area.
+ */
- return 0;
+ /*
+ * Reinitialize port attributes that may change if the port comes back.
+ */
+ rport->maxframe_size = -1;
+ rport->supported_classes = FC_COS_UNSPECIFIED;
+ rport->roles = FC_RPORT_ROLE_UNKNOWN;
+ rport->port_state = FC_PORTSTATE_NOTPRESENT;
+
+ /* remove the identifiers that aren't used in the consisting binding */
+ switch (fc_host_tgtid_bind_type(shost)) {
+ case FC_TGTID_BIND_BY_WWPN:
+ rport->node_name = -1;
+ rport->port_id = -1;
+ break;
+ case FC_TGTID_BIND_BY_WWNN:
+ rport->port_name = -1;
+ rport->port_id = -1;
+ break;
+ case FC_TGTID_BIND_BY_ID:
+ rport->node_name = -1;
+ rport->port_name = -1;
+ break;
+ case FC_TGTID_BIND_NONE: /* to keep compiler happy */
+ break;
+ }
}
-EXPORT_SYMBOL(fc_target_block);
+EXPORT_SYMBOL(fc_remote_port_delete);
/**
- * fc_target_unblock - unblock a target following a fc_target_block request.
- * @starget: scsi target managed by this fc scsi lldd.
+ * fc_remote_port_rolechg - notifies the fc transport that the roles
+ * on a remote may have changed.
+ * @rport: The remote port that changed.
*
- * scsi lld's with a FC transport call this routine to restart IO to all
- * devices associated with the caller's scsi target following a fc_target_block
- * request. Called from interrupt or normal process context.
+ * The LLDD calls this routine to notify the transport that the roles
+ * on a remote port may have changed. The largest effect of this is
+ * if a port now becomes a FCP Target, it must be allocated a
+ * scsi target id. If the port is no longer a FCP target, any
+ * scsi target id value assigned to it will persist in case the
+ * role changes back to include FCP Target. No changes in the scsi
+ * midlayer will be invoked if the role changes (in the expectation
+ * that the role will be resumed. If it doesn't normal error processing
+ * will take place).
+ *
+ * Should not be called from interrupt context.
*
- * Notes:
+ * Notes:
* This routine assumes no locks are held on entry.
**/
void
-fc_target_unblock(struct scsi_target *starget)
+fc_remote_port_rolechg(struct fc_rport *rport, u32 roles)
{
- /*
- * Stop the target timer first. Take no action on the del_timer
- * failure as the state machine state change will validate the
- * transaction.
- */
- if (cancel_delayed_work(&fc_starget_dev_loss_work(starget)))
- flush_scheduled_work();
+ struct Scsi_Host *shost = rport_to_shost(rport);
+ struct fc_host_attrs *fc_host =
+ (struct fc_host_attrs *)shost->shost_data;
+ unsigned long flags;
+ int create = 0;
+
+ rport->roles = roles;
+
+ spin_lock_irqsave(shost->host_lock, flags);
+ if ((rport->scsi_target_id == -1) &&
+ (rport->roles & FC_RPORT_ROLE_FCP_TARGET)) {
+ rport->scsi_target_id = fc_host->next_target_id++;
+ create = 1;
+ }
+ spin_unlock_irqrestore(shost->host_lock, flags);
- starget_for_each_device(starget, NULL, fc_device_unblock);
+ if (create)
+ /* initiate a scan of the target */
+ scsi_queue_work(shost, &rport->scan_work);
}
-EXPORT_SYMBOL(fc_target_unblock);
+EXPORT_SYMBOL(fc_remote_port_rolechg);
/**
- * fc_timeout_blocked_host - Timeout handler for blocked scsi hosts
- * that fail to recover in the alloted time.
- * @data: scsi host that failed to recover its devices in the alloted
- * time.
+ * fc_timeout_blocked_rport - Timeout handler for blocked remote port
+ * that fails to return in the alloted time.
+ * @data: scsi target that failed to reappear in the alloted time.
**/
-static void fc_timeout_blocked_host(void *data)
+static void
+fc_timeout_blocked_rport(void *data)
{
- struct Scsi_Host *shost = (struct Scsi_Host *)data;
- struct scsi_device *sdev;
+ struct fc_rport *rport = (struct fc_rport *)data;
- dev_printk(KERN_ERR, &shost->shost_gendev,
- "blocked host time out: host resuming\n");
+ rport->port_state = FC_PORTSTATE_OFFLINE;
- shost_for_each_device(sdev, shost) {
- /*
- * set the device going again ... if the scsi lld didn't
- * unblock this device, then IO errors will probably
- * result if the host still isn't ready.
- */
- scsi_internal_device_unblock(sdev);
- }
+ dev_printk(KERN_ERR, &rport->dev,
+ "blocked FC remote port time out: removing target\n");
+
+ /*
+ * As this only occurs if the remote port (scsi target)
+ * went away and didn't come back - we'll remove
+ * all attached scsi devices.
+ */
+ scsi_target_unblock(&rport->dev);
+ scsi_remove_target(&rport->dev);
}
/**
- * fc_host_block - block all scsi devices managed by the calling host temporarily
- * by putting each device in the SDEV_BLOCK state.
- * @shost: scsi host pointer that contains all scsi device siblings.
+ * fc_remote_port_block - temporarily block any scsi traffic to a remote port.
+ * @rport: remote port to be blocked.
+ *
+ * scsi lldd's with a FC transport call this routine to temporarily stop
+ * all scsi traffic to a remote port. If the port is not a SCSI target,
+ * no action is taken. If the port is a SCSI target, all attached devices
+ * are placed into a SDEV_BLOCK state and a timer is started. The timer is
+ * represents the maximum amount of time the port may be blocked. If the
+ * timer expires, the port is considered non-existent and the attached
+ * scsi devices will be removed.
*
- * scsi lld's with a FC transport call this routine to temporarily stop all
- * scsi commands to all devices managed by this host. Called
- * from interrupt or normal process context.
+ * Called from interrupt or normal process context.
*
* Returns zero if successful or error if not
*
* Notes:
+ * This routine assumes no locks are held on entry.
+ *
* The timeout and timer types are extracted from the fc transport
- * attributes from the caller's host pointer. This routine assumes no
- * locks are held on entry.
+ * attributes from the caller's rport pointer.
**/
int
-fc_host_block(struct Scsi_Host *shost)
+fc_remote_port_block(struct fc_rport *rport)
{
- struct scsi_device *sdev;
- int timeout = fc_host_link_down_tmo(shost);
- struct work_struct *work = &fc_host_link_down_work(shost);
+ int timeout = rport->dev_loss_tmo;
+ struct work_struct *work = &rport->dev_loss_work;
if (timeout < 0 || timeout > SCSI_DEVICE_BLOCK_MAX_TIMEOUT)
return -EINVAL;
- shost_for_each_device(sdev, shost) {
- scsi_internal_device_block(sdev);
- }
+ scsi_target_block(&rport->dev);
+ /* cap the length the devices can be blocked */
schedule_delayed_work(work, timeout * HZ);
+ rport->port_state = FC_PORTSTATE_BLOCKED;
return 0;
}
-EXPORT_SYMBOL(fc_host_block);
+EXPORT_SYMBOL(fc_remote_port_block);
/**
- * fc_host_unblock - unblock all devices managed by this host following a
- * fc_host_block request.
- * @shost: scsi host containing all scsi device siblings to unblock.
+ * fc_remote_port_unblock - restart any blocked scsi traffic to a remote port.
+ * @rport: remote port to be unblocked.
*
- * scsi lld's with a FC transport call this routine to restart IO to all scsi
- * devices managed by the specified scsi host following an fc_host_block
+ * scsi lld's with a FC transport call this routine to restart IO to all
+ * devices associated with the caller's scsi target following a fc_target_block
* request. Called from interrupt or normal process context.
*
- * Notes:
+ * Notes:
* This routine assumes no locks are held on entry.
**/
-void
-fc_host_unblock(struct Scsi_Host *shost)
+ void
+fc_remote_port_unblock(struct fc_rport *rport)
{
- struct scsi_device *sdev;
+ struct work_struct *work = &rport->dev_loss_work;
+ struct Scsi_Host *shost = rport_to_shost(rport);
- /*
- * Stop the host timer first. Take no action on the del_timer
+ /*
+ * Stop the target timer first. Take no action on the del_timer
* failure as the state machine state change will validate the
* transaction.
*/
- if (cancel_delayed_work(&fc_host_link_down_work(shost)))
+ if (!cancel_delayed_work(work))
flush_scheduled_work();
- shost_for_each_device(sdev, shost) {
- scsi_internal_device_unblock(sdev);
- }
+ if (rport->port_state == FC_PORTSTATE_OFFLINE)
+ /*
+ * initiate a scan of the target as the target has
+ * been torn down.
+ */
+ scsi_queue_work(shost, &rport->scan_work);
+ else
+ scsi_target_unblock(&rport->dev);
+
+ rport->port_state = FC_PORTSTATE_ONLINE;
+}
+EXPORT_SYMBOL(fc_remote_port_unblock);
+
+/**
+ * fc_scsi_scan_rport - called to perform a scsi scan on a remote port.
+ * @data: remote port to be scanned.
+ **/
+static void
+fc_scsi_scan_rport(void *data)
+{
+ struct fc_rport *rport = (struct fc_rport *)data;
+
+ scsi_scan_target(&rport->dev, rport->channel, rport->scsi_target_id,
+ SCAN_WILD_CARD, 1);
}
-EXPORT_SYMBOL(fc_host_unblock);
+
MODULE_AUTHOR("Martin Hicks");
MODULE_DESCRIPTION("FC Transport Attributes");
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index b0aff94a27847..8bb8222ea5896 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -264,13 +264,13 @@ static int iscsi_host_match(struct attribute_container *cont,
return 0;
shost = dev_to_shost(dev);
- if (!shost->transportt || shost->transportt->host_attrs.class
+ if (!shost->transportt || shost->transportt->host_attrs.ac.class
!= &iscsi_host_class.class)
return 0;
i = to_iscsi_internal(shost->transportt);
- return &i->t.host_attrs == cont;
+ return &i->t.host_attrs.ac == cont;
}
static int iscsi_target_match(struct attribute_container *cont,
@@ -283,13 +283,13 @@ static int iscsi_target_match(struct attribute_container *cont,
return 0;
shost = dev_to_shost(dev->parent);
- if (!shost->transportt || shost->transportt->host_attrs.class
+ if (!shost->transportt || shost->transportt->host_attrs.ac.class
!= &iscsi_host_class.class)
return 0;
i = to_iscsi_internal(shost->transportt);
- return &i->t.target_attrs == cont;
+ return &i->t.target_attrs.ac == cont;
}
struct scsi_transport_template *
@@ -305,10 +305,10 @@ iscsi_attach_transport(struct iscsi_function_template *fnt)
memset(i, 0, sizeof(struct iscsi_internal));
i->fnt = fnt;
- i->t.target_attrs.attrs = &i->session_attrs[0];
- i->t.target_attrs.class = &iscsi_transport_class.class;
- i->t.target_attrs.match = iscsi_target_match;
- attribute_container_register(&i->t.target_attrs);
+ i->t.target_attrs.ac.attrs = &i->session_attrs[0];
+ i->t.target_attrs.ac.class = &iscsi_transport_class.class;
+ i->t.target_attrs.ac.match = iscsi_target_match;
+ transport_container_register(&i->t.target_attrs);
i->t.target_size = sizeof(struct iscsi_class_session);
SETUP_SESSION_RD_ATTR(tsih);
@@ -335,10 +335,10 @@ iscsi_attach_transport(struct iscsi_function_template *fnt)
BUG_ON(count > ISCSI_SESSION_ATTRS);
i->session_attrs[count] = NULL;
- i->t.host_attrs.attrs = &i->host_attrs[0];
- i->t.host_attrs.class = &iscsi_host_class.class;
- i->t.host_attrs.match = iscsi_host_match;
- attribute_container_register(&i->t.host_attrs);
+ i->t.host_attrs.ac.attrs = &i->host_attrs[0];
+ i->t.host_attrs.ac.class = &iscsi_host_class.class;
+ i->t.host_attrs.ac.match = iscsi_host_match;
+ transport_container_register(&i->t.host_attrs);
i->t.host_size = 0;
count = 0;
@@ -357,9 +357,9 @@ void iscsi_release_transport(struct scsi_transport_template *t)
{
struct iscsi_internal *i = to_iscsi_internal(t);
- attribute_container_unregister(&i->t.target_attrs);
- attribute_container_unregister(&i->t.host_attrs);
-
+ transport_container_unregister(&i->t.target_attrs);
+ transport_container_unregister(&i->t.host_attrs);
+
kfree(i);
}
diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c
index 83c038ea47aee..303d7656f7102 100644
--- a/drivers/scsi/scsi_transport_spi.c
+++ b/drivers/scsi/scsi_transport_spi.c
@@ -18,15 +18,11 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include <linux/module.h>
+#include <linux/ctype.h>
#include <linux/init.h>
-#include <linux/smp_lock.h>
-#include <linux/list.h>
-#include <linux/spinlock.h>
-#include <linux/mm.h>
+#include <linux/module.h>
#include <linux/workqueue.h>
-#include <asm/scatterlist.h>
-#include <asm/io.h>
+#include <asm/semaphore.h>
#include <scsi/scsi.h>
#include "scsi_priv.h"
#include <scsi/scsi_device.h>
@@ -63,27 +59,47 @@ struct spi_internal {
#define to_spi_internal(tmpl) container_of(tmpl, struct spi_internal, t)
-static const char *const ppr_to_ns[] = {
+static const int ppr_to_ps[] = {
/* The PPR values 0-6 are reserved, fill them in when
* the committee defines them */
- NULL, /* 0x00 */
- NULL, /* 0x01 */
- NULL, /* 0x02 */
- NULL, /* 0x03 */
- NULL, /* 0x04 */
- NULL, /* 0x05 */
- NULL, /* 0x06 */
- "3.125", /* 0x07 */
- "6.25", /* 0x08 */
- "12.5", /* 0x09 */
- "25", /* 0x0a */
- "30.3", /* 0x0b */
- "50", /* 0x0c */
+ -1, /* 0x00 */
+ -1, /* 0x01 */
+ -1, /* 0x02 */
+ -1, /* 0x03 */
+ -1, /* 0x04 */
+ -1, /* 0x05 */
+ -1, /* 0x06 */
+ 3125, /* 0x07 */
+ 6250, /* 0x08 */
+ 12500, /* 0x09 */
+ 25000, /* 0x0a */
+ 30300, /* 0x0b */
+ 50000, /* 0x0c */
};
/* The PPR values at which you calculate the period in ns by multiplying
* by 4 */
#define SPI_STATIC_PPR 0x0c
+static int sprint_frac(char *dest, int value, int denom)
+{
+ int frac = value % denom;
+ int result = sprintf(dest, "%d", value / denom);
+
+ if (frac == 0)
+ return result;
+ dest[result++] = '.';
+
+ do {
+ denom /= 10;
+ sprintf(dest + result, "%d", frac / denom);
+ result++;
+ frac %= denom;
+ } while (frac);
+
+ dest[result++] = '\0';
+ return result;
+}
+
static struct {
enum spi_signal_type value;
char *name;
@@ -142,13 +158,13 @@ static int spi_host_match(struct attribute_container *cont,
return 0;
shost = dev_to_shost(dev);
- if (!shost->transportt || shost->transportt->host_attrs.class
+ if (!shost->transportt || shost->transportt->host_attrs.ac.class
!= &spi_host_class.class)
return 0;
i = to_spi_internal(shost->transportt);
- return &i->t.host_attrs == cont;
+ return &i->t.host_attrs.ac == cont;
}
static int spi_device_configure(struct device *dev)
@@ -261,7 +277,7 @@ static ssize_t show_spi_transport_period(struct class_device *cdev, char *buf)
struct scsi_target *starget = transport_class_to_starget(cdev);
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
struct spi_transport_attrs *tp;
- const char *str;
+ int len, picosec;
struct spi_internal *i = to_spi_internal(shost->transportt);
tp = (struct spi_transport_attrs *)&starget->starget_data;
@@ -269,22 +285,23 @@ static ssize_t show_spi_transport_period(struct class_device *cdev, char *buf)
if (i->f->get_period)
i->f->get_period(starget);
- switch(tp->period) {
-
- case 0x07 ... SPI_STATIC_PPR:
- str = ppr_to_ns[tp->period];
- if(!str)
- str = "reserved";
- break;
-
-
- case (SPI_STATIC_PPR+1) ... 0xff:
- return sprintf(buf, "%d\n", tp->period * 4);
+ if (tp->period < 0 || tp->period > 0xff) {
+ picosec = -1;
+ } else if (tp->period <= SPI_STATIC_PPR) {
+ picosec = ppr_to_ps[tp->period];
+ } else {
+ picosec = tp->period * 4000;
+ }
- default:
- str = "unknown";
+ if (picosec == -1) {
+ len = sprintf(buf, "reserved");
+ } else {
+ len = sprint_frac(buf, picosec, 1000);
}
- return sprintf(buf, "%s\n", str);
+
+ buf[len++] = '\n';
+ buf[len] = '\0';
+ return len;
}
static ssize_t
@@ -294,34 +311,30 @@ store_spi_transport_period(struct class_device *cdev, const char *buf,
struct scsi_target *starget = transport_class_to_starget(cdev);
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
struct spi_internal *i = to_spi_internal(shost->transportt);
- int j, period = -1;
-
- for (j = 0; j < SPI_STATIC_PPR; j++) {
- int len;
-
- if(ppr_to_ns[j] == NULL)
- continue;
-
- len = strlen(ppr_to_ns[j]);
-
- if(strncmp(ppr_to_ns[j], buf, len) != 0)
- continue;
+ int j, picosec, period = -1;
+ char *endp;
+
+ picosec = simple_strtoul(buf, &endp, 10) * 1000;
+ if (*endp == '.') {
+ int mult = 100;
+ do {
+ endp++;
+ if (!isdigit(*endp))
+ break;
+ picosec += (*endp - '0') * mult;
+ mult /= 10;
+ } while (mult > 0);
+ }
- if(buf[len] != '\n')
+ for (j = 0; j <= SPI_STATIC_PPR; j++) {
+ if (ppr_to_ps[j] < picosec)
continue;
-
period = j;
break;
}
- if (period == -1) {
- int val = simple_strtoul(buf, NULL, 0);
-
-
- /* Should probably check limits here, but this
- * gets reasonably close to OK for most things */
- period = val/4;
- }
+ if (period == -1)
+ period = picosec / 4000;
if (period > 0xff)
period = 0xff;
@@ -330,7 +343,7 @@ store_spi_transport_period(struct class_device *cdev, const char *buf,
return count;
}
-
+
static CLASS_DEVICE_ATTR(period, S_IRUGO | S_IWUSR,
show_spi_transport_period,
store_spi_transport_period);
@@ -795,6 +808,61 @@ spi_schedule_dv_device(struct scsi_device *sdev)
}
EXPORT_SYMBOL(spi_schedule_dv_device);
+/**
+ * spi_display_xfer_agreement - Print the current target transfer agreement
+ * @starget: The target for which to display the agreement
+ *
+ * Each SPI port is required to maintain a transfer agreement for each
+ * other port on the bus. This function prints a one-line summary of
+ * the current agreement; more detailed information is available in sysfs.
+ */
+void spi_display_xfer_agreement(struct scsi_target *starget)
+{
+ struct spi_transport_attrs *tp;
+ tp = (struct spi_transport_attrs *)&starget->starget_data;
+
+ if (tp->offset > 0 && tp->period > 0) {
+ unsigned int picosec, kb100;
+ char *scsi = "FAST-?";
+ char tmp[8];
+
+ if (tp->period <= SPI_STATIC_PPR) {
+ picosec = ppr_to_ps[tp->period];
+ switch (tp->period) {
+ case 7: scsi = "FAST-320"; break;
+ case 8: scsi = "FAST-160"; break;
+ case 9: scsi = "FAST-80"; break;
+ case 10:
+ case 11: scsi = "FAST-40"; break;
+ case 12: scsi = "FAST-20"; break;
+ }
+ } else {
+ picosec = tp->period * 4000;
+ if (tp->period < 25)
+ scsi = "FAST-20";
+ else if (tp->period < 50)
+ scsi = "FAST-10";
+ else
+ scsi = "FAST-5";
+ }
+
+ kb100 = (10000000 + picosec / 2) / picosec;
+ if (tp->width)
+ kb100 *= 2;
+ sprint_frac(tmp, picosec, 1000);
+
+ dev_info(&starget->dev,
+ "%s %sSCSI %d.%d MB/s %s%s%s (%s ns, offset %d)\n",
+ scsi, tp->width ? "WIDE " : "", kb100/10, kb100 % 10,
+ tp->dt ? "DT" : "ST", tp->iu ? " IU" : "",
+ tp->qas ? " QAS" : "", tmp, tp->offset);
+ } else {
+ dev_info(&starget->dev, "%sasynchronous.\n",
+ tp->width ? "wide " : "");
+ }
+}
+EXPORT_SYMBOL(spi_display_xfer_agreement);
+
#define SETUP_ATTRIBUTE(field) \
i->private_attrs[count] = class_device_attr_##field; \
if (!i->f->set_##field) { \
@@ -825,7 +893,7 @@ static int spi_device_match(struct attribute_container *cont,
sdev = to_scsi_device(dev);
shost = sdev->host;
- if (!shost->transportt || shost->transportt->host_attrs.class
+ if (!shost->transportt || shost->transportt->host_attrs.ac.class
!= &spi_host_class.class)
return 0;
/* Note: this class has no device attributes, so it has
@@ -844,13 +912,13 @@ static int spi_target_match(struct attribute_container *cont,
return 0;
shost = dev_to_shost(dev->parent);
- if (!shost->transportt || shost->transportt->host_attrs.class
+ if (!shost->transportt || shost->transportt->host_attrs.ac.class
!= &spi_host_class.class)
return 0;
i = to_spi_internal(shost->transportt);
- return &i->t.target_attrs == cont;
+ return &i->t.target_attrs.ac == cont;
}
static DECLARE_TRANSPORT_CLASS(spi_transport_class,
@@ -875,15 +943,15 @@ spi_attach_transport(struct spi_function_template *ft)
memset(i, 0, sizeof(struct spi_internal));
- i->t.target_attrs.class = &spi_transport_class.class;
- i->t.target_attrs.attrs = &i->attrs[0];
- i->t.target_attrs.match = spi_target_match;
- attribute_container_register(&i->t.target_attrs);
+ i->t.target_attrs.ac.class = &spi_transport_class.class;
+ i->t.target_attrs.ac.attrs = &i->attrs[0];
+ i->t.target_attrs.ac.match = spi_target_match;
+ transport_container_register(&i->t.target_attrs);
i->t.target_size = sizeof(struct spi_transport_attrs);
- i->t.host_attrs.class = &spi_host_class.class;
- i->t.host_attrs.attrs = &i->host_attrs[0];
- i->t.host_attrs.match = spi_host_match;
- attribute_container_register(&i->t.host_attrs);
+ i->t.host_attrs.ac.class = &spi_host_class.class;
+ i->t.host_attrs.ac.attrs = &i->host_attrs[0];
+ i->t.host_attrs.ac.match = spi_host_match;
+ transport_container_register(&i->t.host_attrs);
i->t.host_size = sizeof(struct spi_host_attrs);
i->f = ft;
@@ -921,8 +989,8 @@ void spi_release_transport(struct scsi_transport_template *t)
{
struct spi_internal *i = to_spi_internal(t);
- attribute_container_unregister(&i->t.target_attrs);
- attribute_container_unregister(&i->t.host_attrs);
+ transport_container_unregister(&i->t.target_attrs);
+ transport_container_unregister(&i->t.host_attrs);
kfree(i);
}
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 523d68ad047ba..19afb25e44d35 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -122,6 +122,8 @@ 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_read_capacity(struct scsi_disk *sdkp, char *diskname,
struct scsi_request *SRpnt, unsigned char *buffer);
@@ -136,6 +138,8 @@ 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,
};
/*
@@ -735,17 +739,95 @@ static int sd_issue_flush(struct device *dev, sector_t *error_sector)
return sd_sync_cache(sdp);
}
+static void sd_end_flush(request_queue_t *q, struct request *flush_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->WCE) {
+ memset(rq->cmd, 0, sizeof(rq->cmd));
+ rq->flags |= REQ_BLOCK_PC | REQ_SOFTBARRIER;
+ rq->timeout = SD_TIMEOUT;
+ rq->cmd[0] = SYNCHRONIZE_CACHE;
+ return 1;
+ }
+
+ return 0;
+}
+
static void sd_rescan(struct device *dev)
{
struct scsi_disk *sdkp = dev_get_drvdata(dev);
sd_revalidate_disk(sdkp->disk);
}
+
+#ifdef CONFIG_COMPAT
+/*
+ * This gets directly called from VFS. When the ioctl
+ * is not recognized we go back to the other translation paths.
+ */
+static long sd_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ struct block_device *bdev = file->f_dentry->d_inode->i_bdev;
+ struct gendisk *disk = bdev->bd_disk;
+ struct scsi_device *sdev = scsi_disk(disk)->device;
+
+ /*
+ * If we are in the middle of error recovery, don't let anyone
+ * else try and use this device. Also, if error recovery fails, it
+ * may try and take the device offline, in which case all further
+ * access to the device is prohibited.
+ */
+ if (!scsi_block_when_processing_errors(sdev))
+ return -ENODEV;
+
+ if (sdev->host->hostt->compat_ioctl) {
+ int ret;
+
+ ret = sdev->host->hostt->compat_ioctl(sdev, cmd, (void __user *)arg);
+
+ return ret;
+ }
+
+ /*
+ * Let the static ioctl translation table take care of it.
+ */
+ return -ENOIOCTLCMD;
+}
+#endif
+
static struct block_device_operations sd_fops = {
.owner = THIS_MODULE,
.open = sd_open,
.release = sd_release,
.ioctl = sd_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = sd_compat_ioctl,
+#endif
.media_changed = sd_media_changed,
.revalidate_disk = sd_revalidate_disk,
};
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index f5feebf866bb1..fd72d73bb2440 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -330,7 +330,7 @@ sg_release(struct inode *inode, struct file *filp)
static ssize_t
sg_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos)
{
- int k, res;
+ int res;
Sg_device *sdp;
Sg_fd *sfp;
Sg_request *srp;
@@ -343,8 +343,8 @@ 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 ((k = verify_area(VERIFY_WRITE, buf, count)))
- return k;
+ if (!access_ok(VERIFY_WRITE, buf, count))
+ return -EFAULT;
if (sfp->force_packid && (count >= SZ_SG_HEADER)) {
if (__copy_from_user(&old_hdr, buf, SZ_SG_HEADER))
return -EFAULT;
@@ -501,8 +501,8 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
scsi_block_when_processing_errors(sdp->device)))
return -ENXIO;
- if ((k = verify_area(VERIFY_READ, buf, count)))
- return k; /* protects following copy_from_user()s + get_user()s */
+ if (!access_ok(VERIFY_READ, buf, count))
+ return -EFAULT; /* protects following copy_from_user()s + get_user()s */
if (count < SZ_SG_HEADER)
return -EIO;
if (__copy_from_user(&old_hdr, buf, SZ_SG_HEADER))
@@ -594,8 +594,8 @@ sg_new_write(Sg_fd * sfp, const char __user *buf, size_t count,
if (count < SZ_SG_IO_HDR)
return -EINVAL;
- if ((k = verify_area(VERIFY_READ, buf, count)))
- return k; /* protects following copy_from_user()s + get_user()s */
+ if (!access_ok(VERIFY_READ, buf, count))
+ return -EFAULT; /* protects following copy_from_user()s + get_user()s */
sfp->cmd_q = 1; /* when sg_io_hdr seen, set command queuing on */
if (!(srp = sg_add_request(sfp))) {
@@ -631,9 +631,9 @@ sg_new_write(Sg_fd * sfp, const char __user *buf, size_t count,
sg_remove_request(sfp, srp);
return -EMSGSIZE;
}
- if ((k = verify_area(VERIFY_READ, hp->cmdp, hp->cmd_len))) {
+ if (!access_ok(VERIFY_READ, hp->cmdp, hp->cmd_len)) {
sg_remove_request(sfp, srp);
- return k; /* protects following copy_from_user()s + get_user()s */
+ return -EFAULT; /* protects following copy_from_user()s + get_user()s */
}
if (__copy_from_user(cmnd, hp->cmdp, hp->cmd_len)) {
sg_remove_request(sfp, srp);
@@ -773,9 +773,8 @@ sg_ioctl(struct inode *inode, struct file *filp,
return -ENODEV;
if (!scsi_block_when_processing_errors(sdp->device))
return -ENXIO;
- result = verify_area(VERIFY_WRITE, p, SZ_SG_IO_HDR);
- if (result)
- return result;
+ if (!access_ok(VERIFY_WRITE, p, SZ_SG_IO_HDR))
+ return -EFAULT;
result =
sg_new_write(sfp, p, SZ_SG_IO_HDR,
blocking, read_only, &srp);
@@ -837,10 +836,8 @@ sg_ioctl(struct inode *inode, struct file *filp,
case SG_GET_LOW_DMA:
return put_user((int) sfp->low_dma, ip);
case SG_GET_SCSI_ID:
- result =
- verify_area(VERIFY_WRITE, p, sizeof (sg_scsi_id_t));
- if (result)
- return result;
+ if (!access_ok(VERIFY_WRITE, p, sizeof (sg_scsi_id_t)))
+ return -EFAULT;
else {
sg_scsi_id_t __user *sg_idp = p;
@@ -868,9 +865,8 @@ sg_ioctl(struct inode *inode, struct file *filp,
sfp->force_packid = val ? 1 : 0;
return 0;
case SG_GET_PACK_ID:
- result = verify_area(VERIFY_WRITE, ip, sizeof (int));
- if (result)
- return result;
+ if (!access_ok(VERIFY_WRITE, ip, sizeof (int)))
+ return -EFAULT;
read_lock_irqsave(&sfp->rq_list_lock, iflags);
for (srp = sfp->headrp; srp; srp = srp->nextrp) {
if ((1 == srp->done) && (!srp->sg_io_owned)) {
@@ -938,10 +934,8 @@ sg_ioctl(struct inode *inode, struct file *filp,
val = (sdp->device ? 1 : 0);
return put_user(val, ip);
case SG_GET_REQUEST_TABLE:
- result = verify_area(VERIFY_WRITE, p,
- SZ_SG_REQ_INFO * SG_MAX_QUEUE);
- if (result)
- return result;
+ if (!access_ok(VERIFY_WRITE, p, SZ_SG_REQ_INFO * SG_MAX_QUEUE))
+ return -EFAULT;
else {
sg_req_info_t rinfo[SG_MAX_QUEUE];
Sg_request *srp;
@@ -1037,6 +1031,29 @@ sg_ioctl(struct inode *inode, struct file *filp,
}
}
+#ifdef CONFIG_COMPAT
+static long sg_compat_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
+{
+ Sg_device *sdp;
+ Sg_fd *sfp;
+ struct scsi_device *sdev;
+
+ if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp)))
+ return -ENXIO;
+
+ sdev = sdp->device;
+ if (sdev->host->hostt->compat_ioctl) {
+ int ret;
+
+ ret = sdev->host->hostt->compat_ioctl(sdev, cmd_in, (void __user *)arg);
+
+ return ret;
+ }
+
+ return -ENOIOCTLCMD;
+}
+#endif
+
static unsigned int
sg_poll(struct file *filp, poll_table * wait)
{
@@ -1346,6 +1363,9 @@ static struct file_operations sg_fops = {
.write = sg_write,
.poll = sg_poll,
.ioctl = sg_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = sg_compat_ioctl,
+#endif
.open = sg_open,
.mmap = sg_mmap,
.release = sg_release,
@@ -1959,9 +1979,8 @@ sg_write_xfer(Sg_request * srp)
num_xfer, iovec_count, schp->k_use_sg));
if (iovec_count) {
onum = iovec_count;
- if ((k = verify_area(VERIFY_READ, hp->dxferp,
- SZ_SG_IOVEC * onum)))
- return k;
+ if (!access_ok(VERIFY_READ, hp->dxferp, SZ_SG_IOVEC * onum))
+ return -EFAULT;
} else
onum = 1;
@@ -2031,7 +2050,7 @@ sg_u_iovec(sg_io_hdr_t * hp, int sg_num, int ind,
{
int num_xfer = (int) hp->dxfer_len;
unsigned char __user *p = hp->dxferp;
- int count, k;
+ int count;
if (0 == sg_num) {
if (wr_xf && ('\0' == hp->interface_id))
@@ -2045,8 +2064,8 @@ sg_u_iovec(sg_io_hdr_t * hp, int sg_num, int ind,
p = iovec.iov_base;
count = (int) iovec.iov_len;
}
- if ((k = verify_area(wr_xf ? VERIFY_READ : VERIFY_WRITE, p, count)))
- return k;
+ if (!access_ok(wr_xf ? VERIFY_READ : VERIFY_WRITE, p, count))
+ return -EFAULT;
if (up)
*up = p;
if (countp)
@@ -2113,9 +2132,8 @@ sg_read_xfer(Sg_request * srp)
num_xfer, iovec_count, schp->k_use_sg));
if (iovec_count) {
onum = iovec_count;
- if ((k = verify_area(VERIFY_READ, hp->dxferp,
- SZ_SG_IOVEC * onum)))
- return k;
+ if (!access_ok(VERIFY_READ, hp->dxferp, SZ_SG_IOVEC * onum))
+ return -EFAULT;
} else
onum = 1;
diff --git a/drivers/scsi/sim710.c b/drivers/scsi/sim710.c
index add007a81e0e6..63bf2aecbc57c 100644
--- a/drivers/scsi/sim710.c
+++ b/drivers/scsi/sim710.c
@@ -47,7 +47,7 @@
#define MAX_SLOTS 8
static __u8 __initdata id_array[MAX_SLOTS] = { [0 ... MAX_SLOTS-1] = 7 };
-char *sim710; /* command line passed by insmod */
+static char *sim710; /* command line passed by insmod */
MODULE_AUTHOR("Richard Hirst");
MODULE_DESCRIPTION("Simple NCR53C710 driver");
@@ -61,7 +61,7 @@ module_param(sim710, charp, 0);
#define ARG_SEP ','
#endif
-__init int
+static __init int
param_setup(char *str)
{
char *pos = str, *next;
@@ -127,16 +127,24 @@ sim710_probe_common(struct device *dev, unsigned long base_addr,
NCR_700_set_io_mapped(hostdata);
/* and register the chip */
- if((host = NCR_700_detect(&sim710_driver_template, hostdata, dev, irq,
- scsi_id)) == NULL) {
+ if((host = NCR_700_detect(&sim710_driver_template, hostdata, dev))
+ == NULL) {
printk(KERN_ERR "sim710: No host detected; card configuration problem?\n");
goto out_release;
}
+ host->this_id = scsi_id;
+ host->irq = irq;
+ if (request_irq(irq, NCR_700_intr, SA_SHIRQ, "sim710", host)) {
+ printk(KERN_ERR "sim710: request_irq failed\n");
+ goto out_put_host;
+ }
scsi_scan_host(host);
return 0;
+ out_put_host:
+ scsi_host_put(host);
out_release:
release_region(host->base, 64);
out_free:
@@ -314,7 +322,7 @@ sim710_eisa_probe(struct device *dev)
differential, scsi_id);
}
-struct eisa_driver sim710_eisa_driver = {
+static struct eisa_driver sim710_eisa_driver = {
.id_table = sim710_eisa_ids,
.driver = {
.name = "sim710",
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index 47c3d08e01f2a..2f259f2495229 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -511,13 +511,17 @@ static int sr_block_media_changed(struct gendisk *disk)
return cdrom_media_changed(&cd->cdi);
}
-struct block_device_operations sr_bdops =
+static struct block_device_operations sr_bdops =
{
.owner = THIS_MODULE,
.open = sr_block_open,
.release = sr_block_release,
.ioctl = sr_block_ioctl,
.media_changed = sr_block_media_changed,
+ /*
+ * No compat_ioctl for now because sr_block_ioctl never
+ * seems to pass arbitary ioctls down to host drivers.
+ */
};
static int sr_open(struct cdrom_device_info *cdi, int purpose)
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index 4388fc8c396c5..265d1eed64fa9 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -9,7 +9,7 @@
Steve Hirsch, Andreas Koppenh"ofer, Michael Leodolter, Eyal Lebedinsky,
Michael Schaefer, J"org Weule, and Eric Youngdale.
- Copyright 1992 - 2004 Kai Makisara
+ Copyright 1992 - 2005 Kai Makisara
email Kai.Makisara@kolumbus.fi
Some small formal changes - aeb, 950809
@@ -17,7 +17,7 @@
Last modified: 18-JAN-1998 Richard Gooch <rgooch@atnf.csiro.au> Devfs support
*/
-static char *verstr = "20041025";
+static char *verstr = "20050312";
#include <linux/module.h>
@@ -36,6 +36,8 @@ static char *verstr = "20041025";
#include <linux/moduleparam.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/cdev.h>
+#include <linux/delay.h>
+
#include <asm/uaccess.h>
#include <asm/dma.h>
#include <asm/system.h>
@@ -144,7 +146,7 @@ static char *st_formats[] = {
#error "Buffer size should not exceed (2 << 24 - 1) bytes!"
#endif
-DEB( static int debugging = DEBUG; )
+static int debugging = DEBUG;
#define MAX_RETRIES 0
#define MAX_WRITE_RETRIES 0
@@ -262,25 +264,57 @@ static inline char *tape_name(struct scsi_tape *tape)
return tape->disk->disk_name;
}
+
+static void st_analyze_sense(struct scsi_request *SRpnt, struct st_cmdstatus *s)
+{
+ const u8 *ucp;
+ const u8 *sense = SRpnt->sr_sense_buffer;
+
+ s->have_sense = scsi_request_normalize_sense(SRpnt, &s->sense_hdr);
+ s->flags = 0;
+
+ if (s->have_sense) {
+ s->deferred = 0;
+ s->remainder_valid =
+ scsi_get_sense_info_fld(sense, SCSI_SENSE_BUFFERSIZE, &s->uremainder64);
+ switch (sense[0] & 0x7f) {
+ case 0x71:
+ s->deferred = 1;
+ case 0x70:
+ s->fixed_format = 1;
+ s->flags = sense[2] & 0xe0;
+ break;
+ case 0x73:
+ s->deferred = 1;
+ case 0x72:
+ s->fixed_format = 0;
+ ucp = scsi_sense_desc_find(sense, SCSI_SENSE_BUFFERSIZE, 4);
+ s->flags = ucp ? (ucp[3] & 0xe0) : 0;
+ break;
+ }
+ }
+}
+
+
/* Convert the result to success code */
static int st_chk_result(struct scsi_tape *STp, struct scsi_request * SRpnt)
{
int result = SRpnt->sr_result;
- unsigned char *sense = SRpnt->sr_sense_buffer, scode;
+ u8 scode;
DEB(const char *stp;)
char *name = tape_name(STp);
+ struct st_cmdstatus *cmdstatp;
- if (!result) {
- sense[0] = 0; /* We don't have sense data if this byte is zero */
+ if (!result)
return 0;
- }
- if ((driver_byte(result) & DRIVER_MASK) == DRIVER_SENSE)
- scode = sense[2] & 0x0f;
- else {
- sense[0] = 0;
+ cmdstatp = &STp->buffer->cmdstat;
+ st_analyze_sense(STp->buffer->last_SRpnt, cmdstatp);
+
+ if (cmdstatp->have_sense)
+ scode = STp->buffer->cmdstat.sense_hdr.sense_key;
+ else
scode = 0;
- }
DEB(
if (debugging) {
@@ -289,29 +323,30 @@ static int st_chk_result(struct scsi_tape *STp, struct scsi_request * SRpnt)
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);
- if (driver_byte(result) & DRIVER_SENSE)
+ if (cmdstatp->have_sense)
scsi_print_req_sense("st", SRpnt);
- } else ) /* end DEB */
- if (!(driver_byte(result) & DRIVER_SENSE) ||
- ((sense[0] & 0x70) == 0x70 &&
- scode != NO_SENSE &&
- scode != RECOVERED_ERROR &&
- /* scode != UNIT_ATTENTION && */
- scode != BLANK_CHECK &&
- scode != VOLUME_OVERFLOW &&
- SRpnt->sr_cmnd[0] != MODE_SENSE &&
- SRpnt->sr_cmnd[0] != TEST_UNIT_READY)) { /* Abnormal conditions for tape */
- if (driver_byte(result) & DRIVER_SENSE) {
- printk(KERN_WARNING "%s: Error with sense data: ", name);
- scsi_print_req_sense("st", SRpnt);
- } else
+ } ) /* end DEB */
+ if (!debugging) { /* Abnormal conditions for tape */
+ if (!cmdstatp->have_sense)
printk(KERN_WARNING
"%s: Error %x (sugg. bt 0x%x, driver bt 0x%x, host bt 0x%x).\n",
name, result, suggestion(result),
- driver_byte(result) & DRIVER_MASK, host_byte(result));
+ driver_byte(result) & DRIVER_MASK, host_byte(result));
+ else if (cmdstatp->have_sense &&
+ scode != NO_SENSE &&
+ scode != RECOVERED_ERROR &&
+ /* scode != UNIT_ATTENTION && */
+ scode != BLANK_CHECK &&
+ scode != VOLUME_OVERFLOW &&
+ SRpnt->sr_cmnd[0] != MODE_SENSE &&
+ SRpnt->sr_cmnd[0] != TEST_UNIT_READY) {
+ printk(KERN_WARNING "%s: Error with sense data: ", name);
+ scsi_print_req_sense("st", SRpnt);
+ }
}
- if (STp->cln_mode >= EXTENDED_SENSE_START) {
+ 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->cln_sense_mask) == STp->cln_sense_value);
@@ -319,12 +354,13 @@ static int st_chk_result(struct scsi_tape *STp, struct scsi_request * SRpnt)
STp->cleaning_req |= ((SRpnt->sr_sense_buffer[STp->cln_mode] &
STp->cln_sense_mask) != 0);
}
- if (sense[12] == 0 && sense[13] == 0x17) /* ASC and ASCQ => cleaning requested */
- STp->cleaning_req = 1;
+ if (cmdstatp->have_sense &&
+ cmdstatp->sense_hdr.asc == 0 && cmdstatp->sense_hdr.ascq == 0x17)
+ STp->cleaning_req = 1; /* ASC and ASCQ => cleaning requested */
STp->pos_unknown |= STp->device->was_reset;
- if ((sense[0] & 0x70) == 0x70 &&
+ if (cmdstatp->have_sense &&
scode == RECOVERED_ERROR
#if ST_RECOVERED_WRITE_FATAL
&& SRpnt->sr_cmnd[0] != WRITE_6
@@ -346,7 +382,7 @@ static int st_chk_result(struct scsi_tape *STp, struct scsi_request * SRpnt)
STp->recover_count);
} ) /* end DEB */
- if ((sense[2] & 0xe0) == 0)
+ if (cmdstatp->flags == 0)
return 0;
}
return (-EIO);
@@ -356,28 +392,10 @@ 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)
{
- int remainder;
struct scsi_tape *STp = container_of(SCpnt->request->rq_disk->private_data,
struct scsi_tape, driver);
- if ((STp->buffer)->writing &&
- (SCpnt->sense_buffer[0] & 0x70) == 0x70 &&
- (SCpnt->sense_buffer[2] & 0x40)) {
- /* EOM at write-behind, has all been written? */
- if ((SCpnt->sense_buffer[0] & 0x80) != 0)
- remainder = (SCpnt->sense_buffer[3] << 24) |
- (SCpnt->sense_buffer[4] << 16) |
- (SCpnt->sense_buffer[5] << 8) |
- SCpnt->sense_buffer[6];
- else
- remainder = 0;
- if ((SCpnt->sense_buffer[2] & 0x0f) == VOLUME_OVERFLOW ||
- remainder > 0)
- (STp->buffer)->midlevel_result = SCpnt->result; /* Error */
- else
- (STp->buffer)->midlevel_result = INT_MAX; /* OK */
- } else
- (STp->buffer)->midlevel_result = SCpnt->result;
+ (STp->buffer)->cmdstat.midlevel_result = SCpnt->result;
SCpnt->request->rq_status = RQ_SCSI_DONE;
(STp->buffer)->last_SRpnt = SCpnt->sc_request;
DEB( STp->write_pending = 0; )
@@ -421,6 +439,7 @@ st_do_scsi(struct scsi_request * SRpnt, struct scsi_tape * STp, unsigned char *c
SRpnt->sr_request->waiting = &(STp->wait);
SRpnt->sr_request->rq_status = RQ_SCSI_BUSY;
SRpnt->sr_request->rq_disk = STp->disk;
+ STp->buffer->cmdstat.have_sense = 0;
scsi_do_req(SRpnt, (void *) cmd, bp, bytes,
st_sleep_done, timeout, retries);
@@ -434,13 +453,20 @@ st_do_scsi(struct scsi_request * SRpnt, struct scsi_tape * STp, unsigned char *c
}
-/* Handle the write-behind checking (downs the semaphore) */
-static void write_behind_check(struct scsi_tape * STp)
+/* Handle the write-behind checking (waits for completion). Returns -ENOSPC if
+ write has been correct but EOM early warning reached, -EIO if write ended in
+ error or zero if write successful. Asynchronous writes are used only in
+ variable block mode. */
+static int write_behind_check(struct scsi_tape * STp)
{
+ int retval = 0;
struct st_buffer *STbuffer;
struct st_partstat *STps;
+ struct st_cmdstatus *cmdstatp;
STbuffer = STp->buffer;
+ if (!STbuffer->writing)
+ return 0;
DEB(
if (STp->write_pending)
@@ -463,9 +489,29 @@ static void write_behind_check(struct scsi_tape * STp)
else
STps->drv_block += STbuffer->writing / STp->block_size;
}
+
+ cmdstatp = &STbuffer->cmdstat;
+ if (STbuffer->syscall_result) {
+ retval = -EIO;
+ if (cmdstatp->have_sense && !cmdstatp->deferred &&
+ (cmdstatp->flags & SENSE_EOM) &&
+ (cmdstatp->sense_hdr.sense_key == NO_SENSE ||
+ cmdstatp->sense_hdr.sense_key == RECOVERED_ERROR)) {
+ /* EOM at write-behind, has all data been written? */
+ if (!cmdstatp->remainder_valid ||
+ cmdstatp->uremainder64 == 0)
+ retval = -ENOSPC;
+ }
+ if (retval == -EIO)
+ STps->drv_block = -1;
+ }
STbuffer->writing = 0;
- return;
+ DEB(if (debugging && retval)
+ printk(ST_DEB_MSG "%s: Async write error %x, return value %d.\n",
+ tape_name(STp), STbuffer->cmdstat.midlevel_result, retval);) /* end DEB */
+
+ return retval;
}
@@ -496,7 +542,7 @@ static int cross_eof(struct scsi_tape * STp, int forward)
scsi_release_request(SRpnt);
SRpnt = NULL;
- if ((STp->buffer)->midlevel_result != 0)
+ if ((STp->buffer)->cmdstat.midlevel_result != 0)
printk(KERN_ERR "%s: Stepping over filemark %s failed.\n",
tape_name(STp), forward ? "forward" : "backward");
@@ -513,19 +559,9 @@ static int flush_write_buffer(struct scsi_tape * STp)
struct scsi_request *SRpnt;
struct st_partstat *STps;
- if ((STp->buffer)->writing) {
- write_behind_check(STp);
- if ((STp->buffer)->syscall_result) {
- DEBC(printk(ST_DEB_MSG
- "%s: Async write error (flush) %x.\n",
- tape_name(STp), (STp->buffer)->midlevel_result))
- if ((STp->buffer)->midlevel_result == INT_MAX)
- return (-ENOSPC);
- return (-EIO);
- }
- }
- if (STp->block_size == 0)
- return 0;
+ result = write_behind_check(STp);
+ if (result)
+ return result;
result = 0;
if (STp->dirty == 1) {
@@ -553,18 +589,25 @@ static int flush_write_buffer(struct scsi_tape * STp)
STps = &(STp->ps[STp->partition]);
if ((STp->buffer)->syscall_result != 0) {
- if ((SRpnt->sr_sense_buffer[0] & 0x70) == 0x70 &&
- (SRpnt->sr_sense_buffer[2] & 0x40) &&
- (SRpnt->sr_sense_buffer[2] & 0x0f) == NO_SENSE) {
+ struct st_cmdstatus *cmdstatp = &STp->buffer->cmdstat;
+
+ if (cmdstatp->have_sense && !cmdstatp->deferred &&
+ (cmdstatp->flags & SENSE_EOM) &&
+ (cmdstatp->sense_hdr.sense_key == NO_SENSE ||
+ cmdstatp->sense_hdr.sense_key == RECOVERED_ERROR) &&
+ (!cmdstatp->remainder_valid ||
+ cmdstatp->uremainder64 == 0)) { /* All written at EOM early warning */
STp->dirty = 0;
(STp->buffer)->buffer_bytes = 0;
+ if (STps->drv_block >= 0)
+ STps->drv_block += blks;
result = (-ENOSPC);
} else {
printk(KERN_ERR "%s: Error on flush.\n",
tape_name(STp));
+ STps->drv_block = (-1);
result = (-EIO);
}
- STps->drv_block = (-1);
} else {
if (STps->drv_block >= 0)
STps->drv_block += blks;
@@ -728,6 +771,7 @@ static int test_ready(struct scsi_tape *STp, int do_wait)
int retval = CHKRES_READY, new_session = 0;
unsigned char cmd[MAX_COMMAND_SIZE];
struct scsi_request *SRpnt = NULL;
+ struct st_cmdstatus *cmdstatp = &STp->buffer->cmdstat;
max_wait = do_wait ? ST_BLOCK_SECONDS : 0;
@@ -742,9 +786,9 @@ static int test_ready(struct scsi_tape *STp, int do_wait)
break;
}
- if ((SRpnt->sr_sense_buffer[0] & 0x70) == 0x70) {
+ if (cmdstatp->have_sense) {
- scode = (SRpnt->sr_sense_buffer[2] & 0x0f);
+ scode = cmdstatp->sense_hdr.sense_key;
if (scode == UNIT_ATTENTION) { /* New media? */
new_session = 1;
@@ -760,9 +804,7 @@ static int test_ready(struct scsi_tape *STp, int do_wait)
if (scode == NOT_READY) {
if (waits < max_wait) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(HZ);
- if (signal_pending(current)) {
+ if (msleep_interruptible(1000)) {
retval = (-EINTR);
break;
}
@@ -771,7 +813,7 @@ static int test_ready(struct scsi_tape *STp, int do_wait)
}
else {
if ((STp->device)->scsi_level >= SCSI_2 &&
- SRpnt->sr_sense_buffer[12] == 0x3a) /* Check ASC */
+ cmdstatp->sense_hdr.asc == 0x3a) /* Check ASC */
retval = CHKRES_NO_TAPE;
else
retval = CHKRES_NOT_READY;
@@ -877,7 +919,7 @@ static int check_tape(struct scsi_tape *STp, struct file *filp)
goto err_out;
}
- if (!SRpnt->sr_result && !SRpnt->sr_sense_buffer[0]) {
+ if (!SRpnt->sr_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) |
@@ -1004,7 +1046,13 @@ static int st_open(struct inode *inode, struct file *filp)
int dev = TAPE_NR(inode);
char *name;
- nonseekable_open(inode, filp);
+ /*
+ * We really want to do nonseekable_open(inode, filp); here, but some
+ * versions of tar incorrectly call lseek on tapes and bail out if that
+ * fails. So we disallow pread() and pwrite(), but permit lseeks.
+ */
+ filp->f_mode &= ~(FMODE_PREAD | FMODE_PWRITE);
+
write_lock(&st_dev_arr_lock);
if (dev >= st_dev_max || scsi_tapes == NULL ||
((STp = scsi_tapes[dev]) == NULL)) {
@@ -1108,10 +1156,9 @@ static int st_flush(struct file *filp)
name, STp->nbr_requests, STp->nbr_dio, STp->nbr_pages, STp->nbr_combinable));
if (STps->rw == ST_WRITING && !STp->pos_unknown) {
+ struct st_cmdstatus *cmdstatp = &STp->buffer->cmdstat;
- DEBC(printk(ST_DEB_MSG "%s: File length %lld bytes.\n",
- name, (long long)filp->f_pos);
- printk(ST_DEB_MSG "%s: Async write waits %d, finished %d.\n",
+ DEBC(printk(ST_DEB_MSG "%s: Async write waits %d, finished %d.\n",
name, STp->nbr_waits, STp->nbr_finished);
)
@@ -1126,20 +1173,13 @@ static int st_flush(struct file *filp)
goto out;
}
- if ((STp->buffer)->syscall_result != 0 &&
- ((SRpnt->sr_sense_buffer[0] & 0x70) != 0x70 ||
- (SRpnt->sr_sense_buffer[2] & 0x4f) != 0x40 ||
- ((SRpnt->sr_sense_buffer[0] & 0x80) != 0 &&
- (SRpnt->sr_sense_buffer[3] | SRpnt->sr_sense_buffer[4] |
- SRpnt->sr_sense_buffer[5] |
- SRpnt->sr_sense_buffer[6]) != 0))) {
- /* Filter out successful write at EOM */
- scsi_release_request(SRpnt);
- SRpnt = NULL;
- printk(KERN_ERR "%s: Error on write filemark.\n", name);
- if (result == 0)
- result = (-EIO);
- } else {
+ if (STp->buffer->syscall_result == 0 ||
+ (cmdstatp->have_sense && !cmdstatp->deferred &&
+ (cmdstatp->flags & SENSE_EOM) &&
+ (cmdstatp->sense_hdr.sense_key == NO_SENSE ||
+ cmdstatp->sense_hdr.sense_key == RECOVERED_ERROR) &&
+ (!cmdstatp->remainder_valid || cmdstatp->uremainder64 == 0))) {
+ /* Write successful at EOM */
scsi_release_request(SRpnt);
SRpnt = NULL;
if (STps->drv_file >= 0)
@@ -1149,6 +1189,13 @@ static int st_flush(struct file *filp)
cross_eof(STp, 0);
STps->eof = ST_FM;
}
+ else { /* Write error */
+ scsi_release_request(SRpnt);
+ SRpnt = NULL;
+ printk(KERN_ERR "%s: Error on write filemark.\n", name);
+ if (result == 0)
+ result = (-EIO);
+ }
DEBC(printk(ST_DEB_MSG "%s: Buffer flushed, %d EOF(s) written\n",
name, cmd[4]));
@@ -1410,16 +1457,12 @@ st_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
}
STbp = STp->buffer;
- if (STbp->writing) {
- write_behind_check(STp);
- if (STbp->syscall_result) {
- DEBC(printk(ST_DEB_MSG "%s: Async write error (write) %x.\n",
- name, STbp->midlevel_result));
- if (STbp->midlevel_result == INT_MAX)
- STps->eof = ST_EOM_OK;
- else
- STps->eof = ST_EOM_ERROR;
- }
+ i = write_behind_check(STp);
+ if (i) {
+ if (i == -ENOSPC)
+ STps->eof = ST_EOM_OK;
+ else
+ STps->eof = ST_EOM_ERROR;
}
if (STps->eof == ST_EOM_OK) {
@@ -1477,7 +1520,6 @@ st_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
}
}
count -= do_count;
- filp->f_pos += do_count;
b_point += do_count;
async_write = STp->block_size == 0 && !STbp->do_dio &&
@@ -1523,15 +1565,13 @@ st_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
}
if (STbp->syscall_result != 0) {
+ struct st_cmdstatus *cmdstatp = &STp->buffer->cmdstat;
+
DEBC(printk(ST_DEB_MSG "%s: Error on write:\n", name));
- if ((SRpnt->sr_sense_buffer[0] & 0x70) == 0x70 &&
- (SRpnt->sr_sense_buffer[2] & 0x40)) {
- scode = SRpnt->sr_sense_buffer[2] & 0x0f;
- if ((SRpnt->sr_sense_buffer[0] & 0x80) != 0)
- undone = (SRpnt->sr_sense_buffer[3] << 24) |
- (SRpnt->sr_sense_buffer[4] << 16) |
- (SRpnt->sr_sense_buffer[5] << 8) |
- SRpnt->sr_sense_buffer[6];
+ if (cmdstatp->have_sense && (cmdstatp->flags & SENSE_EOM)) {
+ scode = cmdstatp->sense_hdr.sense_key;
+ if (cmdstatp->remainder_valid)
+ undone = (int)cmdstatp->uremainder64;
else if (STp->block_size == 0 &&
scode == VOLUME_OVERFLOW)
undone = transfer;
@@ -1539,7 +1579,6 @@ st_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
undone = 0;
if (STp->block_size != 0)
undone *= STp->block_size;
- filp->f_pos -= undone;
if (undone <= do_count) {
/* Only data from this write is not written */
count += undone;
@@ -1556,11 +1595,11 @@ st_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
retval = (-ENOSPC); /* EOM within current request */
DEBC(printk(ST_DEB_MSG
"%s: EOM with %d bytes unwritten.\n",
- name, count));
+ name, (int)count));
} else {
/* EOT within data buffered earlier (possible only
in fixed block mode without direct i/o) */
- if (!retry_eot && (SRpnt->sr_sense_buffer[0] & 1) == 0 &&
+ if (!retry_eot && !cmdstatp->deferred &&
(scode == NO_SENSE || scode == RECOVERED_ERROR)) {
move_buffer_data(STp->buffer, transfer - undone);
retry_eot = 1;
@@ -1588,7 +1627,6 @@ st_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
}
}
} else {
- filp->f_pos -= do_count;
count += do_count;
STps->drv_block = (-1); /* Too cautious? */
retval = (-EIO);
@@ -1690,6 +1728,8 @@ static long read_tape(struct scsi_tape *STp, long count,
/* Something to check */
if (STbp->syscall_result) {
+ struct st_cmdstatus *cmdstatp = &STp->buffer->cmdstat;
+
retval = 1;
DEBC(printk(ST_DEB_MSG "%s: Sense: %2x %2x %2x %2x %2x %2x %2x %2x\n",
name,
@@ -1697,25 +1737,22 @@ static long read_tape(struct scsi_tape *STp, long count,
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]));
- if ((SRpnt->sr_sense_buffer[0] & 0x70) == 0x70) { /* extended sense */
+ if (cmdstatp->have_sense) {
- if ((SRpnt->sr_sense_buffer[2] & 0x0f) == BLANK_CHECK)
- SRpnt->sr_sense_buffer[2] &= 0xcf; /* No need for EOM in this case */
+ if (cmdstatp->sense_hdr.sense_key == BLANK_CHECK)
+ cmdstatp->flags &= 0xcf; /* No need for EOM in this case */
- if ((SRpnt->sr_sense_buffer[2] & 0xe0) != 0) { /* EOF, EOM, or ILI */
+ if (cmdstatp->flags != 0) { /* EOF, EOM, or ILI */
/* Compute the residual count */
- if ((SRpnt->sr_sense_buffer[0] & 0x80) != 0)
- transfer = (SRpnt->sr_sense_buffer[3] << 24) |
- (SRpnt->sr_sense_buffer[4] << 16) |
- (SRpnt->sr_sense_buffer[5] << 8) |
- SRpnt->sr_sense_buffer[6];
+ if (cmdstatp->remainder_valid)
+ transfer = (int)cmdstatp->uremainder64;
else
transfer = 0;
if (STp->block_size == 0 &&
- (SRpnt->sr_sense_buffer[2] & 0x0f) == MEDIUM_ERROR)
+ cmdstatp->sense_hdr.sense_key == MEDIUM_ERROR)
transfer = bytes;
- if (SRpnt->sr_sense_buffer[2] & 0x20) { /* ILI */
+ if (cmdstatp->flags & SENSE_ILI) { /* ILI */
if (STp->block_size == 0) {
if (transfer <= 0) {
if (transfer < 0)
@@ -1749,7 +1786,7 @@ static long read_tape(struct scsi_tape *STp, long count,
if (st_int_ioctl(STp, MTBSR, 1))
return (-EIO);
}
- } else if (SRpnt->sr_sense_buffer[2] & 0x80) { /* FM overrides EOM */
+ } else if (cmdstatp->flags & SENSE_FMK) { /* FM overrides EOM */
if (STps->eof != ST_FM_HIT)
STps->eof = ST_FM_HIT;
else
@@ -1762,7 +1799,7 @@ static long read_tape(struct scsi_tape *STp, long count,
DEBC(printk(ST_DEB_MSG
"%s: EOF detected (%d bytes read).\n",
name, STbp->buffer_bytes));
- } else if (SRpnt->sr_sense_buffer[2] & 0x40) {
+ } else if (cmdstatp->flags & SENSE_EOM) {
if (STps->eof == ST_FM)
STps->eof = ST_EOD_1;
else
@@ -1783,7 +1820,7 @@ static long read_tape(struct scsi_tape *STp, long count,
"%s: Tape error while reading.\n", name));
STps->drv_block = (-1);
if (STps->eof == ST_FM &&
- (SRpnt->sr_sense_buffer[2] & 0x0f) == BLANK_CHECK) {
+ cmdstatp->sense_hdr.sense_key == BLANK_CHECK) {
DEBC(printk(ST_DEB_MSG
"%s: Zero returned for first BLANK CHECK after EOF.\n",
name));
@@ -1907,7 +1944,7 @@ st_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos)
printk(ST_DEB_MSG
"%s: EOF up (%d). Left %d, needed %d.\n", name,
STps->eof, STbp->buffer_bytes,
- count - total);
+ (int)(count - total));
) /* end DEB */
transfer = STbp->buffer_bytes < count - total ?
STbp->buffer_bytes : count - total;
@@ -1918,7 +1955,6 @@ st_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos)
goto out;
}
}
- filp->f_pos += transfer;
buf += transfer;
total += transfer;
}
@@ -2373,6 +2409,22 @@ static int do_load_unload(struct scsi_tape *STp, struct file *filp, int load_cod
return retval;
}
+#if DEBUG
+#define ST_DEB_FORWARD 0
+#define ST_DEB_BACKWARD 1
+static void deb_space_print(char *name, int direction, char *units, unsigned char *cmd)
+{
+ s32 sc;
+
+ sc = cmd[2] & 0x80 ? 0xff000000 : 0;
+ sc |= (cmd[2] << 16) | (cmd[3] << 8) | cmd[4];
+ if (direction)
+ sc = -sc;
+ printk(ST_DEB_MSG "%s: Spacing tape %s over %d %s.\n", name,
+ direction ? "backward" : "forward", sc, units);
+}
+#endif
+
/* Internal ioctl function */
static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned long arg)
@@ -2411,8 +2463,7 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon
cmd[2] = (arg >> 16);
cmd[3] = (arg >> 8);
cmd[4] = arg;
- DEBC(printk(ST_DEB_MSG "%s: Spacing tape forward over %d filemarks.\n",
- name, cmd[2] * 65536 + cmd[3] * 256 + cmd[4]));
+ DEBC(deb_space_print(name, ST_DEB_FORWARD, "filemarks", cmd);)
if (fileno >= 0)
fileno += arg;
blkno = 0;
@@ -2427,14 +2478,7 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon
cmd[2] = (ltmp >> 16);
cmd[3] = (ltmp >> 8);
cmd[4] = ltmp;
- DEBC(
- if (cmd[2] & 0x80)
- ltmp = 0xff000000;
- ltmp = ltmp | (cmd[2] << 16) | (cmd[3] << 8) | cmd[4];
- printk(ST_DEB_MSG
- "%s: Spacing tape backward over %ld filemarks.\n",
- name, (-ltmp));
- )
+ DEBC(deb_space_print(name, ST_DEB_BACKWARD, "filemarks", cmd);)
if (fileno >= 0)
fileno -= arg;
blkno = (-1); /* We can't know the block number */
@@ -2446,8 +2490,7 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon
cmd[2] = (arg >> 16);
cmd[3] = (arg >> 8);
cmd[4] = arg;
- DEBC(printk(ST_DEB_MSG "%s: Spacing tape forward %d blocks.\n", name,
- cmd[2] * 65536 + cmd[3] * 256 + cmd[4]));
+ DEBC(deb_space_print(name, ST_DEB_FORWARD, "blocks", cmd);)
if (blkno >= 0)
blkno += arg;
at_sm &= (arg == 0);
@@ -2459,13 +2502,7 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon
cmd[2] = (ltmp >> 16);
cmd[3] = (ltmp >> 8);
cmd[4] = ltmp;
- DEBC(
- if (cmd[2] & 0x80)
- ltmp = 0xff000000;
- ltmp = ltmp | (cmd[2] << 16) | (cmd[3] << 8) | cmd[4];
- printk(ST_DEB_MSG
- "%s: Spacing tape backward %ld blocks.\n", name, (-ltmp));
- )
+ DEBC(deb_space_print(name, ST_DEB_BACKWARD, "blocks", cmd);)
if (blkno >= 0)
blkno -= arg;
at_sm &= (arg == 0);
@@ -2476,8 +2513,7 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon
cmd[2] = (arg >> 16);
cmd[3] = (arg >> 8);
cmd[4] = arg;
- DEBC(printk(ST_DEB_MSG "%s: Spacing tape forward %d setmarks.\n", name,
- cmd[2] * 65536 + cmd[3] * 256 + cmd[4]));
+ DEBC(deb_space_print(name, ST_DEB_FORWARD, "setmarks", cmd);)
if (arg != 0) {
blkno = fileno = (-1);
at_sm = 1;
@@ -2490,13 +2526,7 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon
cmd[2] = (ltmp >> 16);
cmd[3] = (ltmp >> 8);
cmd[4] = ltmp;
- DEBC(
- if (cmd[2] & 0x80)
- ltmp = 0xff000000;
- ltmp = ltmp | (cmd[2] << 16) | (cmd[3] << 8) | cmd[4];
- printk(ST_DEB_MSG "%s: Spacing tape backward %ld setmarks.\n",
- name, (-ltmp));
- )
+ DEBC(deb_space_print(name, ST_DEB_BACKWARD, "setmarks", cmd);)
if (arg != 0) {
blkno = fileno = (-1);
at_sm = 1;
@@ -2566,7 +2596,7 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon
cmd[1] = 3;
DEBC(printk(ST_DEB_MSG "%s: Spacing to end of recorded medium.\n",
name));
- blkno = 0;
+ blkno = -1;
at_sm = 0;
break;
case MTERASE:
@@ -2693,25 +2723,30 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon
else if (chg_eof)
STps->eof = ST_NOEOF;
+ if (cmd_in == MTWEOF)
+ STps->rw = ST_IDLE;
} else { /* SCSI command was not completely successful. Don't return
from this block without releasing the SCSI command block! */
+ struct st_cmdstatus *cmdstatp = &STp->buffer->cmdstat;
- if (SRpnt->sr_sense_buffer[2] & 0x40) {
+ if (cmdstatp->flags & SENSE_EOM) {
if (cmd_in != MTBSF && cmd_in != MTBSFM &&
cmd_in != MTBSR && cmd_in != MTBSS)
STps->eof = ST_EOM_OK;
STps->drv_block = 0;
}
- undone = ((SRpnt->sr_sense_buffer[3] << 24) +
- (SRpnt->sr_sense_buffer[4] << 16) +
- (SRpnt->sr_sense_buffer[5] << 8) +
- SRpnt->sr_sense_buffer[6]);
+ if (cmdstatp->remainder_valid)
+ undone = (int)cmdstatp->uremainder64;
+ else
+ undone = 0;
if (cmd_in == MTWEOF &&
- (SRpnt->sr_sense_buffer[0] & 0x70) == 0x70 &&
- (SRpnt->sr_sense_buffer[2] & 0x4f) == 0x40 &&
- ((SRpnt->sr_sense_buffer[0] & 0x80) == 0 || undone == 0)) {
+ cmdstatp->have_sense &&
+ (cmdstatp->flags & SENSE_EOM) &&
+ (cmdstatp->sense_hdr.sense_key == NO_SENSE ||
+ cmdstatp->sense_hdr.sense_key == RECOVERED_ERROR) &&
+ undone == 0) {
ioctl_result = 0; /* EOF written succesfully at EOM */
if (fileno >= 0)
fileno++;
@@ -2722,7 +2757,7 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon
STps->drv_file = fileno - undone;
else
STps->drv_file = fileno;
- STps->drv_block = 0;
+ STps->drv_block = -1;
STps->eof = ST_NOEOF;
} else if ((cmd_in == MTBSF) || (cmd_in == MTBSFM)) {
if (arg > 0 && undone < 0) /* Some drives get this wrong */
@@ -2732,7 +2767,7 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon
STps->drv_block = 0;
STps->eof = ST_NOEOF;
} else if (cmd_in == MTFSR) {
- if (SRpnt->sr_sense_buffer[2] & 0x80) { /* Hit filemark */
+ if (cmdstatp->flags & SENSE_FMK) { /* Hit filemark */
if (STps->drv_file >= 0)
STps->drv_file++;
STps->drv_block = 0;
@@ -2745,7 +2780,7 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon
STps->eof = ST_NOEOF;
}
} else if (cmd_in == MTBSR) {
- if (SRpnt->sr_sense_buffer[2] & 0x80) { /* Hit filemark */
+ if (cmdstatp->flags & SENSE_FMK) { /* Hit filemark */
STps->drv_file--;
STps->drv_block = (-1);
} else {
@@ -2763,7 +2798,7 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon
cmd_in == MTSETDENSITY ||
cmd_in == MTSETDRVBUFFER ||
cmd_in == SET_DENS_AND_BLK) {
- if ((SRpnt->sr_sense_buffer[2] & 0x0f) == ILLEGAL_REQUEST &&
+ if (cmdstatp->sense_hdr.sense_key == ILLEGAL_REQUEST &&
!(STp->use_pf & PF_TESTED)) {
/* Try the other possible state of Page Format if not
already tried */
@@ -2775,7 +2810,7 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon
} else if (chg_eof)
STps->eof = ST_NOEOF;
- if ((SRpnt->sr_sense_buffer[2] & 0x0f) == BLANK_CHECK)
+ if (cmdstatp->sense_hdr.sense_key == BLANK_CHECK)
STps->eof = ST_EOD;
scsi_release_request(SRpnt);
@@ -3198,6 +3233,20 @@ static int st_ioctl(struct inode *inode, struct file *file,
retval = i;
goto out;
}
+ if (STps->rw == ST_WRITING &&
+ (mtc.mt_op == MTREW || mtc.mt_op == MTOFFL ||
+ mtc.mt_op == MTSEEK ||
+ mtc.mt_op == MTBSF || mtc.mt_op == MTBSFM)) {
+ i = st_int_ioctl(STp, MTWEOF, 1);
+ if (i < 0) {
+ retval = i;
+ goto out;
+ }
+ if (mtc.mt_op == MTBSF || mtc.mt_op == MTBSFM)
+ mtc.mt_count++;
+ STps->rw = ST_IDLE;
+ }
+
} else {
/*
* If there was a bus reset, block further access
@@ -3414,17 +3463,39 @@ static int st_ioctl(struct inode *inode, struct file *file,
case SCSI_IOCTL_GET_BUS_NUMBER:
break;
default:
- i = scsi_cmd_ioctl(file, STp->disk, cmd_in, p);
+ if (!capable(CAP_SYS_ADMIN))
+ i = -EPERM;
+ else
+ i = scsi_cmd_ioctl(file, STp->disk, cmd_in, p);
if (i != -ENOTTY)
return i;
break;
}
+ if (!capable(CAP_SYS_ADMIN) &&
+ (cmd_in == SCSI_IOCTL_START_UNIT || cmd_in == SCSI_IOCTL_STOP_UNIT))
+ return -EPERM;
return scsi_ioctl(STp->device, cmd_in, p);
out:
up(&STp->lock);
return retval;
}
+
+#ifdef CONFIG_COMPAT
+static long st_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ struct scsi_tape *STp = file->private_data;
+ struct scsi_device *sdev = STp->device;
+ int ret = -ENOIOCTLCMD;
+ if (sdev->host->hostt->compat_ioctl) {
+
+ ret = sdev->host->hostt->compat_ioctl(sdev, cmd, (void __user *)arg);
+
+ }
+ return ret;
+}
+#endif
+
/* Try to allocate a new tape buffer. Calling function must not hold
@@ -3716,6 +3787,9 @@ static struct file_operations st_fops =
.read = st_read,
.write = st_write,
.ioctl = st_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = st_compat_ioctl,
+#endif
.open = st_open,
.flush = st_flush,
.release = st_release,
diff --git a/drivers/scsi/st.h b/drivers/scsi/st.h
index 0e6dd5d68a387..061da111398e9 100644
--- a/drivers/scsi/st.h
+++ b/drivers/scsi/st.h
@@ -5,6 +5,18 @@
#include <linux/completion.h>
+/* Descriptor for analyzed sense data */
+struct st_cmdstatus {
+ int midlevel_result;
+ struct scsi_sense_hdr sense_hdr;
+ int have_sense;
+ u64 uremainder64;
+ u8 flags;
+ u8 remainder_valid;
+ u8 fixed_format;
+ u8 deferred;
+};
+
/* The tape buffer descriptor. */
struct st_buffer {
unsigned char in_use;
@@ -15,9 +27,9 @@ struct st_buffer {
int buffer_bytes;
int read_pointer;
int writing;
- int midlevel_result;
int syscall_result;
struct scsi_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 */
unsigned short sg_segs; /* number of segments in s/g list */
@@ -192,4 +204,9 @@ struct scsi_tape {
#define EXTENDED_SENSE_START 18
+/* Masks for some conditions in the sense data */
+#define SENSE_FMK 0x80
+#define SENSE_EOM 0x40
+#define SENSE_ILI 0x20
+
#endif
diff --git a/drivers/scsi/sym53c416.c b/drivers/scsi/sym53c416.c
index fbfc0c06d4096..f26c3a29e631e 100644
--- a/drivers/scsi/sym53c416.c
+++ b/drivers/scsi/sym53c416.c
@@ -616,7 +616,7 @@ static struct isapnp_device_id id_table[] __devinitdata = {
MODULE_DEVICE_TABLE(isapnp, id_table);
-void sym53c416_probe(void)
+static void sym53c416_probe(void)
{
int *base = probeaddrs;
int ints[2];
diff --git a/drivers/scsi/sym53c8xx_2/Makefile b/drivers/scsi/sym53c8xx_2/Makefile
index 672ca5af42154..873e8ced82523 100644
--- a/drivers/scsi/sym53c8xx_2/Makefile
+++ b/drivers/scsi/sym53c8xx_2/Makefile
@@ -1,4 +1,4 @@
# Makefile for the NCR/SYMBIOS/LSI 53C8XX PCI SCSI controllers driver.
-sym53c8xx-objs := sym_fw.o sym_glue.o sym_hipd.o sym_malloc.o sym_misc.o sym_nvram.o
+sym53c8xx-objs := sym_fw.o sym_glue.o sym_hipd.o sym_malloc.o sym_nvram.o
obj-$(CONFIG_SCSI_SYM53C8XX_2) := sym53c8xx.o
diff --git a/drivers/scsi/sym53c8xx_2/sym53c8xx.h b/drivers/scsi/sym53c8xx_2/sym53c8xx.h
index 6bc75a391bd18..481103769729f 100644
--- a/drivers/scsi/sym53c8xx_2/sym53c8xx.h
+++ b/drivers/scsi/sym53c8xx_2/sym53c8xx.h
@@ -42,10 +42,6 @@
#include <linux/config.h>
-#ifdef CONFIG_SCSI_SYM53C8XX_IOMAPPED
-#define SYM_CONF_IOMAPPED
-#endif
-
/*
* DMA addressing mode.
*
@@ -144,10 +140,6 @@ struct sym_driver_setup {
#define SYM_SETUP_HOST_ID sym_driver_setup.host_id
#define boot_verbose sym_driver_setup.verbose
-/* Always enable parity. */
-#define SYM_SETUP_PCI_PARITY 1
-#define SYM_SETUP_SCSI_PARITY 1
-
/*
* Initial setup.
*
@@ -170,4 +162,56 @@ extern struct sym_driver_setup sym_driver_setup;
extern unsigned int sym_debug_flags;
#define DEBUG_FLAGS sym_debug_flags
+/*
+ * Max number of targets.
+ * Maximum is 16 and you are advised not to change this value.
+ */
+#ifndef SYM_CONF_MAX_TARGET
+#define SYM_CONF_MAX_TARGET (16)
+#endif
+
+/*
+ * Max number of logical units.
+ * SPI-2 allows up to 64 logical units, but in real life, target
+ * that implements more that 7 logical units are pretty rare.
+ * Anyway, the cost of accepting up to 64 logical unit is low in
+ * this driver, thus going with the maximum is acceptable.
+ */
+#ifndef SYM_CONF_MAX_LUN
+#define SYM_CONF_MAX_LUN (64)
+#endif
+
+/*
+ * Max number of IO control blocks queued to the controller.
+ * Each entry needs 8 bytes and the queues are allocated contiguously.
+ * Since we donnot want to allocate more than a page, the theorical
+ * maximum is PAGE_SIZE/8. For safety, we announce a bit less to the
+ * access method. :)
+ * When not supplied, as it is suggested, the driver compute some
+ * good value for this parameter.
+ */
+/* #define SYM_CONF_MAX_START (PAGE_SIZE/8 - 16) */
+
+/*
+ * Support for Immediate Arbitration.
+ * Not advised.
+ */
+/* #define SYM_CONF_IARB_SUPPORT */
+
+/*
+ * Only relevant if IARB support configured.
+ * - Max number of successive settings of IARB hints.
+ * - Set IARB on arbitration lost.
+ */
+#define SYM_CONF_IARB_MAX 3
+#define SYM_CONF_SET_IARB_ON_ARB_LOST 1
+
+/*
+ * Returning wrong residuals may make problems.
+ * When zero, this define tells the driver to
+ * always return 0 as transfer residual.
+ * Btw, all my testings of residuals have succeeded.
+ */
+#define SYM_SETUP_RESIDUAL_SUPPORT 1
+
#endif /* SYM53C8XX_H */
diff --git a/drivers/scsi/sym53c8xx_2/sym_conf.h b/drivers/scsi/sym53c8xx_2/sym_conf.h
deleted file mode 100644
index 30bb92c90fc61..0000000000000
--- a/drivers/scsi/sym53c8xx_2/sym_conf.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Device driver for the SYMBIOS/LSILOGIC 53C8XX and 53C1010 family
- * of PCI-SCSI IO processors.
- *
- * Copyright (C) 1999-2001 Gerard Roudier <groudier@free.fr>
- *
- * This driver is derived from the Linux sym53c8xx driver.
- * Copyright (C) 1998-2000 Gerard Roudier
- *
- * The sym53c8xx driver is derived from the ncr53c8xx driver that had been
- * a port of the FreeBSD ncr driver to Linux-1.2.13.
- *
- * The original ncr driver has been written for 386bsd and FreeBSD by
- * Wolfgang Stanglmeier <wolf@cologne.de>
- * Stefan Esser <se@mi.Uni-Koeln.de>
- * Copyright (C) 1994 Wolfgang Stanglmeier
- *
- * Other major contributions:
- *
- * NVRAM detection and reading.
- * Copyright (C) 1997 Richard Waltham <dormouse@farsrobt.demon.co.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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef SYM_CONF_H
-#define SYM_CONF_H
-
-#include "sym53c8xx.h"
-
-/*
- * Max number of targets.
- * Maximum is 16 and you are advised not to change this value.
- */
-#ifndef SYM_CONF_MAX_TARGET
-#define SYM_CONF_MAX_TARGET (16)
-#endif
-
-/*
- * Max number of logical units.
- * SPI-2 allows up to 64 logical units, but in real life, target
- * that implements more that 7 logical units are pretty rare.
- * Anyway, the cost of accepting up to 64 logical unit is low in
- * this driver, thus going with the maximum is acceptable.
- */
-#ifndef SYM_CONF_MAX_LUN
-#define SYM_CONF_MAX_LUN (64)
-#endif
-
-/*
- * Max number of IO control blocks queued to the controller.
- * Each entry needs 8 bytes and the queues are allocated contiguously.
- * Since we donnot want to allocate more than a page, the theorical
- * maximum is PAGE_SIZE/8. For safety, we announce a bit less to the
- * access method. :)
- * When not supplied, as it is suggested, the driver compute some
- * good value for this parameter.
- */
-/* #define SYM_CONF_MAX_START (PAGE_SIZE/8 - 16) */
-
-/*
- * Support for Immediate Arbitration.
- * Not advised.
- */
-/* #define SYM_CONF_IARB_SUPPORT */
-
-/*
- * Only relevant if IARB support configured.
- * - Max number of successive settings of IARB hints.
- * - Set IARB on arbitration lost.
- */
-#define SYM_CONF_IARB_MAX 3
-#define SYM_CONF_SET_IARB_ON_ARB_LOST 1
-
-/*
- * Returning wrong residuals may make problems.
- * When zero, this define tells the driver to
- * always return 0 as transfer residual.
- * Btw, all my testings of residuals have succeeded.
- */
-#define SYM_SETUP_RESIDUAL_SUPPORT 1
-
-/*
- * Supported maximum number of LUNs to announce to
- * the access method.
- * The driver supports up to 64 LUNs per target as
- * required by SPI-2/SPI-3. However some SCSI devices
- * designed prior to these specifications or not being
- * conformant may be highly confused when they are
- * asked about a LUN > 7.
- */
-#ifndef SYM_SETUP_MAX_LUN
-#define SYM_SETUP_MAX_LUN (8)
-#endif
-
-#endif /* SYM_CONF_H */
diff --git a/drivers/scsi/sym53c8xx_2/sym_defs.h b/drivers/scsi/sym53c8xx_2/sym_defs.h
index d27071dcb28bb..15bb89195c094 100644
--- a/drivers/scsi/sym53c8xx_2/sym_defs.h
+++ b/drivers/scsi/sym53c8xx_2/sym_defs.h
@@ -40,13 +40,13 @@
#ifndef SYM_DEFS_H
#define SYM_DEFS_H
-#define SYM_VERSION "2.1.18n"
+#define SYM_VERSION "2.2.0"
#define SYM_DRIVER_NAME "sym-" SYM_VERSION
/*
* SYM53C8XX device features descriptor.
*/
-struct sym_pci_chip {
+struct sym_chip {
u_short device_id;
u_short revision_id;
char *name;
diff --git a/drivers/scsi/sym53c8xx_2/sym_fw.c b/drivers/scsi/sym53c8xx_2/sym_fw.c
index 1c6d0d182d2c0..fd36cf9858cbb 100644
--- a/drivers/scsi/sym53c8xx_2/sym_fw.c
+++ b/drivers/scsi/sym53c8xx_2/sym_fw.c
@@ -361,7 +361,7 @@ static struct sym_fw sym_fw2 = SYM_FW_ENTRY(sym_fw2, "LOAD/STORE-based");
* Find the most appropriate firmware for a chip.
*/
struct sym_fw *
-sym_find_firmware(struct sym_pci_chip *chip)
+sym_find_firmware(struct sym_chip *chip)
{
if (chip->features & FE_LDSTR)
return &sym_fw2;
diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c
index 3ed36af0c893d..a1dff6d437bc2 100644
--- a/drivers/scsi/sym53c8xx_2/sym_glue.c
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.c
@@ -3,7 +3,7 @@
* of PCI-SCSI IO processors.
*
* Copyright (C) 1999-2001 Gerard Roudier <groudier@free.fr>
- * Copyright (c) 2003-2004 Matthew Wilcox <matthew@wil.cx>
+ * Copyright (c) 2003-2005 Matthew Wilcox <matthew@wil.cx>
*
* This driver is derived from the Linux sym53c8xx driver.
* Copyright (C) 1998-2000 Gerard Roudier
@@ -47,7 +47,6 @@
#include <scsi/scsi_tcq.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_transport.h>
-#include <scsi/scsi_transport_spi.h>
#include "sym_glue.h"
#include "sym_nvram.h"
@@ -135,81 +134,47 @@ static void sym2_setup_params(void)
}
}
+/*
+ * We used to try to deal with 64-bit BARs here, but don't any more.
+ * There are many parts of this driver which would need to be modified
+ * to handle a 64-bit base address, including scripts. I'm uncomfortable
+ * with making those changes when I have no way of testing it, so I'm
+ * just going to disable it.
+ *
+ * Note that some machines (eg HP rx8620 and Superdome) have bus addresses
+ * below 4GB and physical addresses above 4GB. These will continue to work.
+ */
static int __devinit
-pci_get_base_address(struct pci_dev *pdev, int index, u_long *base)
+pci_get_base_address(struct pci_dev *pdev, int index, unsigned long *basep)
{
u32 tmp;
+ unsigned long base;
#define PCI_BAR_OFFSET(index) (PCI_BASE_ADDRESS_0 + (index<<2))
- pci_read_config_dword(pdev, PCI_BAR_OFFSET(index), &tmp);
- *base = tmp;
- ++index;
+ pci_read_config_dword(pdev, PCI_BAR_OFFSET(index++), &tmp);
+ base = tmp;
if ((tmp & 0x7) == PCI_BASE_ADDRESS_MEM_TYPE_64) {
-#if BITS_PER_LONG > 32
- pci_read_config_dword(pdev, PCI_BAR_OFFSET(index), &tmp);
- *base |= (((u_long)tmp) << 32);
-#endif
- ++index;
+ pci_read_config_dword(pdev, PCI_BAR_OFFSET(index++), &tmp);
+ if (tmp > 0)
+ dev_err(&pdev->dev,
+ "BAR %d is 64-bit, disabling\n", index - 1);
+ base = 0;
}
+
+ if ((base & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO) {
+ base &= PCI_BASE_ADDRESS_IO_MASK;
+ } else {
+ base &= PCI_BASE_ADDRESS_MEM_MASK;
+ }
+
+ *basep = base;
return index;
#undef PCI_BAR_OFFSET
}
-/* This lock protects only the memory allocation/free. */
-static DEFINE_SPINLOCK(sym53c8xx_lock);
-
static struct scsi_transport_template *sym2_transport_template = NULL;
/*
- * Wrappers to the generic memory allocator.
- */
-void *sym_calloc(int size, char *name)
-{
- unsigned long flags;
- void *m;
- spin_lock_irqsave(&sym53c8xx_lock, flags);
- m = sym_calloc_unlocked(size, name);
- spin_unlock_irqrestore(&sym53c8xx_lock, flags);
- return m;
-}
-
-void sym_mfree(void *m, int size, char *name)
-{
- unsigned long flags;
- spin_lock_irqsave(&sym53c8xx_lock, flags);
- sym_mfree_unlocked(m, size, name);
- spin_unlock_irqrestore(&sym53c8xx_lock, flags);
-}
-
-void *__sym_calloc_dma(m_pool_ident_t dev_dmat, int size, char *name)
-{
- unsigned long flags;
- void *m;
- spin_lock_irqsave(&sym53c8xx_lock, flags);
- m = __sym_calloc_dma_unlocked(dev_dmat, size, name);
- spin_unlock_irqrestore(&sym53c8xx_lock, flags);
- return m;
-}
-
-void __sym_mfree_dma(m_pool_ident_t dev_dmat, void *m, int size, char *name)
-{
- unsigned long flags;
- spin_lock_irqsave(&sym53c8xx_lock, flags);
- __sym_mfree_dma_unlocked(dev_dmat, m, size, name);
- spin_unlock_irqrestore(&sym53c8xx_lock, flags);
-}
-
-m_addr_t __vtobus(m_pool_ident_t dev_dmat, void *m)
-{
- unsigned long flags;
- m_addr_t b;
- spin_lock_irqsave(&sym53c8xx_lock, flags);
- b = __vtobus_unlocked(dev_dmat, m);
- spin_unlock_irqrestore(&sym53c8xx_lock, flags);
- return b;
-}
-
-/*
* Used by the eh thread to wait for command completion.
* It is allocated on the eh thread stack.
*/
@@ -231,8 +196,7 @@ struct sym_ucmd { /* Override the SCSI pointer structure */
};
#define SYM_UCMD_PTR(cmd) ((struct sym_ucmd *)(&(cmd)->SCp))
-#define SYM_SCMD_PTR(ucmd) sym_que_entry(ucmd, struct scsi_cmnd, SCp)
-#define SYM_SOFTC_PTR(cmd) (((struct host_data *)cmd->device->host->hostdata)->ncb)
+#define SYM_SOFTC_PTR(cmd) sym_get_hcb(cmd->device->host)
static void __unmap_scsi_data(struct pci_dev *pdev, struct scsi_cmnd *cmd)
{
@@ -288,31 +252,20 @@ static int __map_scsi_sg_data(struct pci_dev *pdev, struct scsi_cmnd *cmd)
/*
* Complete a pending CAM CCB.
*/
-void sym_xpt_done(struct sym_hcb *np, struct scsi_cmnd *ccb)
+void sym_xpt_done(struct sym_hcb *np, struct scsi_cmnd *cmd)
{
- unmap_scsi_data(np, ccb);
- ccb->scsi_done(ccb);
+ unmap_scsi_data(np, cmd);
+ cmd->scsi_done(cmd);
}
-static void sym_xpt_done2(struct sym_hcb *np, struct scsi_cmnd *ccb, int cam_status)
+static void sym_xpt_done2(struct sym_hcb *np, struct scsi_cmnd *cmd, int cam_status)
{
- sym_set_cam_status(ccb, cam_status);
- sym_xpt_done(np, ccb);
+ sym_set_cam_status(cmd, cam_status);
+ sym_xpt_done(np, cmd);
}
/*
- * Print something that identifies the IO.
- */
-void sym_print_addr(struct sym_ccb *cp)
-{
- struct scsi_cmnd *cmd = cp->cam_ccb;
- if (cmd)
- printf("%s:%d:%d:", sym_name(SYM_SOFTC_PTR(cmd)),
- cmd->device->id, cmd->device->lun);
-}
-
-/*
* Tell the SCSI layer about a BUS RESET.
*/
void sym_xpt_async_bus_reset(struct sym_hcb *np)
@@ -334,16 +287,6 @@ void sym_xpt_async_sent_bdr(struct sym_hcb *np, int target)
}
/*
- * Tell the SCSI layer about the new transfer parameters.
- */
-void sym_xpt_async_nego_wide(struct sym_hcb *np, int target)
-{
- if (sym_verbose < 3)
- return;
- sym_announce_transfer_rate(np, target);
-}
-
-/*
* Choose the more appropriate CAM status if
* the IO encountered an extended error.
*/
@@ -367,7 +310,7 @@ static int sym_xerr_cam_status(int cam_status, int x_status)
*/
void sym_set_cam_result_error(struct sym_hcb *np, struct sym_ccb *cp, int resid)
{
- struct scsi_cmnd *csio = cp->cam_ccb;
+ struct scsi_cmnd *cmd = cp->cmd;
u_int cam_status, scsi_status, drv_status;
drv_status = 0;
@@ -378,7 +321,7 @@ void sym_set_cam_result_error(struct sym_hcb *np, struct sym_ccb *cp, int resid)
scsi_status = cp->sv_scsi_status;
resid = cp->sv_resid;
if (sym_verbose && cp->sv_xerr_status)
- sym_print_xerr(cp, cp->sv_xerr_status);
+ sym_print_xerr(cmd, cp->sv_xerr_status);
if (cp->host_status == HS_COMPLETE &&
cp->ssss_status == S_GOOD &&
cp->xerr_status == 0) {
@@ -388,9 +331,9 @@ void sym_set_cam_result_error(struct sym_hcb *np, struct sym_ccb *cp, int resid)
/*
* Bounce back the sense data to user.
*/
- memset(&csio->sense_buffer, 0, sizeof(csio->sense_buffer));
- memcpy(csio->sense_buffer, cp->sns_bbuf,
- min(sizeof(csio->sense_buffer),
+ memset(&cmd->sense_buffer, 0, sizeof(cmd->sense_buffer));
+ memcpy(cmd->sense_buffer, cp->sns_bbuf,
+ min(sizeof(cmd->sense_buffer),
(size_t)SYM_SNS_BBUF_LEN));
#if 0
/*
@@ -400,7 +343,7 @@ void sym_set_cam_result_error(struct sym_hcb *np, struct sym_ccb *cp, int resid)
*/
if (1) {
u_char *p;
- p = (u_char *) csio->sense_data;
+ p = (u_char *) cmd->sense_data;
if (p[0]==0x70 && p[2]==0x6 && p[12]==0x29)
sym_clear_tasks(np, DID_ABORT,
cp->target,cp->lun, -1);
@@ -413,7 +356,7 @@ void sym_set_cam_result_error(struct sym_hcb *np, struct sym_ccb *cp, int resid)
* condition otherwise the device will always return
* BUSY. Use a big stick.
*/
- sym_reset_scsi_target(np, csio->device->id);
+ sym_reset_scsi_target(np, cmd->device->id);
cam_status = DID_ERROR;
}
} else if (cp->host_status == HS_COMPLETE) /* Bad SCSI status */
@@ -424,8 +367,7 @@ void sym_set_cam_result_error(struct sym_hcb *np, struct sym_ccb *cp, int resid)
cam_status = DID_ERROR;
else { /* Extended error */
if (sym_verbose) {
- PRINT_ADDR(cp);
- printf ("COMMAND FAILED (%x %x %x).\n",
+ sym_print_addr(cmd, "COMMAND FAILED (%x %x %x).\n",
cp->host_status, cp->ssss_status,
cp->xerr_status);
}
@@ -434,8 +376,8 @@ void sym_set_cam_result_error(struct sym_hcb *np, struct sym_ccb *cp, int resid)
*/
cam_status = sym_xerr_cam_status(DID_ERROR, cp->xerr_status);
}
- csio->resid = resid;
- csio->result = (drv_status << 24) + (cam_status << 16) + scsi_status;
+ cmd->resid = resid;
+ cmd->result = (drv_status << 24) + (cam_status << 16) + scsi_status;
}
@@ -502,9 +444,9 @@ static int sym_scatter(struct sym_hcb *np, struct sym_ccb *cp, struct scsi_cmnd
/*
* Queue a SCSI command.
*/
-static int sym_queue_command(struct sym_hcb *np, struct scsi_cmnd *ccb)
+static int sym_queue_command(struct sym_hcb *np, struct scsi_cmnd *cmd)
{
-/* struct scsi_device *device = ccb->device; */
+ struct scsi_device *sdev = cmd->device;
struct sym_tcb *tp;
struct sym_lcb *lp;
struct sym_ccb *cp;
@@ -514,17 +456,17 @@ static int sym_queue_command(struct sym_hcb *np, struct scsi_cmnd *ccb)
* Minimal checkings, so that we will not
* go outside our tables.
*/
- if (ccb->device->id == np->myaddr ||
- ccb->device->id >= SYM_CONF_MAX_TARGET ||
- ccb->device->lun >= SYM_CONF_MAX_LUN) {
- sym_xpt_done2(np, ccb, CAM_DEV_NOT_THERE);
+ if (sdev->id == np->myaddr ||
+ sdev->id >= SYM_CONF_MAX_TARGET ||
+ sdev->lun >= SYM_CONF_MAX_LUN) {
+ sym_xpt_done2(np, cmd, CAM_DEV_NOT_THERE);
return 0;
}
/*
* Retrieve the target descriptor.
*/
- tp = &np->target[ccb->device->id];
+ tp = &np->target[sdev->id];
/*
* Complete the 1st INQUIRY command with error
@@ -538,12 +480,12 @@ static int sym_queue_command(struct sym_hcb *np, struct scsi_cmnd *ccb)
* devices behave badly when asked for some non
* zero LUN. Btw, this is an absolute hack.:-)
*/
- if (ccb->cmnd[0] == 0x12 || ccb->cmnd[0] == 0x0) {
+ if (cmd->cmnd[0] == 0x12 || cmd->cmnd[0] == 0x0) {
if ((tp->usrflags & SYM_SCAN_BOOT_DISABLED) ||
((tp->usrflags & SYM_SCAN_LUNS_DISABLED) &&
- ccb->device->lun != 0)) {
+ sdev->lun != 0)) {
tp->usrflags &= ~SYM_SCAN_BOOT_DISABLED;
- sym_xpt_done2(np, ccb, CAM_DEV_NOT_THERE);
+ sym_xpt_done2(np, cmd, CAM_DEV_NOT_THERE);
return 0;
}
}
@@ -551,23 +493,23 @@ static int sym_queue_command(struct sym_hcb *np, struct scsi_cmnd *ccb)
/*
* Select tagged/untagged.
*/
- lp = sym_lp(np, tp, ccb->device->lun);
+ lp = sym_lp(tp, sdev->lun);
order = (lp && lp->s.reqtags) ? M_SIMPLE_TAG : 0;
/*
* Queue the SCSI IO.
*/
- cp = sym_get_ccb(np, ccb->device->id, ccb->device->lun, order);
+ cp = sym_get_ccb(np, cmd, order);
if (!cp)
return 1; /* Means resource shortage */
- sym_queue_scsiio(np, ccb, cp);
+ sym_queue_scsiio(np, cmd, cp);
return 0;
}
/*
* Setup buffers and pointers that address the CDB.
*/
-static inline int sym_setup_cdb(struct sym_hcb *np, struct scsi_cmnd *ccb, struct sym_ccb *cp)
+static inline int sym_setup_cdb(struct sym_hcb *np, struct scsi_cmnd *cmd, struct sym_ccb *cp)
{
u32 cmd_ba;
int cmd_len;
@@ -575,14 +517,14 @@ static inline int sym_setup_cdb(struct sym_hcb *np, struct scsi_cmnd *ccb, struc
/*
* CDB is 16 bytes max.
*/
- if (ccb->cmd_len > sizeof(cp->cdb_buf)) {
- sym_set_cam_status(cp->cam_ccb, CAM_REQ_INVALID);
+ if (cmd->cmd_len > sizeof(cp->cdb_buf)) {
+ sym_set_cam_status(cp->cmd, CAM_REQ_INVALID);
return -1;
}
- memcpy(cp->cdb_buf, ccb->cmnd, ccb->cmd_len);
+ memcpy(cp->cdb_buf, cmd->cmnd, cmd->cmd_len);
cmd_ba = CCB_BA (cp, cdb_buf[0]);
- cmd_len = ccb->cmd_len;
+ cmd_len = cmd->cmd_len;
cp->phys.cmd.addr = cpu_to_scr(cmd_ba);
cp->phys.cmd.size = cpu_to_scr(cmd_len);
@@ -593,29 +535,29 @@ static inline int sym_setup_cdb(struct sym_hcb *np, struct scsi_cmnd *ccb, struc
/*
* Setup pointers that address the data and start the I/O.
*/
-int sym_setup_data_and_start(struct sym_hcb *np, struct scsi_cmnd *csio, struct sym_ccb *cp)
+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(np, tp, cp->lun);
+ struct sym_lcb *lp = sym_lp(tp, cp->lun);
/*
* Build the CDB.
*/
- if (sym_setup_cdb(np, csio, cp))
+ if (sym_setup_cdb(np, cmd, cp))
goto out_abort;
/*
* No direction means no data.
*/
- dir = csio->sc_data_direction;
+ dir = cmd->sc_data_direction;
if (dir != DMA_NONE) {
- cp->segments = sym_scatter(np, cp, csio);
+ cp->segments = sym_scatter(np, cp, cmd);
if (cp->segments < 0) {
if (cp->segments == -2)
- sym_set_cam_status(csio, CAM_RESRC_UNAVAIL);
+ sym_set_cam_status(cmd, CAM_RESRC_UNAVAIL);
else
- sym_set_cam_status(csio, CAM_REQ_TOO_BIG);
+ sym_set_cam_status(cmd, CAM_REQ_TOO_BIG);
goto out_abort;
}
} else {
@@ -655,7 +597,7 @@ int sym_setup_data_and_start(struct sym_hcb *np, struct scsi_cmnd *csio, struct
out_abort:
sym_free_ccb(np, cp);
- sym_xpt_done(np, csio);
+ sym_xpt_done(np, cmd);
return 0;
}
@@ -737,7 +679,6 @@ static int sym53c8xx_queue_command(struct scsi_cmnd *cmd,
int sts = 0;
cmd->scsi_done = done;
- cmd->host_scribble = NULL;
memset(ucp, 0, sizeof(*ucp));
/*
@@ -855,11 +796,8 @@ static int sym_eh_handler(int op, char *opname, struct scsi_cmnd *cmd)
int to_do = SYM_EH_DO_IGNORE;
int sts = -1;
struct sym_eh_wait eh, *ep = &eh;
- char devname[20];
-
- sprintf(devname, "%s:%d:%d", sym_name(np), cmd->device->id, cmd->device->lun);
- printf_warning("%s: %s operation started.\n", devname, opname);
+ dev_warn(&cmd->device->sdev_gendev, "%s operation started.\n", opname);
#if 0
/* This one should be the result of some race, thus to ignore */
@@ -870,7 +808,7 @@ static int sym_eh_handler(int op, char *opname, struct scsi_cmnd *cmd)
/* This one is queued in some place -> to wait for completion */
FOR_EACH_QUEUED_ELEMENT(&np->busy_ccbq, qp) {
struct sym_ccb *cp = sym_que_entry(qp, struct sym_ccb, link_ccbq);
- if (cp->cam_ccb == cmd) {
+ if (cp->cmd == cmd) {
to_do = SYM_EH_DO_WAIT;
goto prepare;
}
@@ -939,9 +877,9 @@ prepare:
if (ep->timed_out)
sts = -2;
}
- printf_warning("%s: %s operation %s.\n", devname, opname,
- sts==0?"complete":sts==-2?"timed-out":"failed");
- return sts? SCSI_FAILED : SCSI_SUCCESS;
+ dev_warn(&cmd->device->sdev_gendev, "%s operation %s.\n", opname,
+ sts==0 ? "complete" :sts==-2 ? "timed-out" : "failed");
+ return sts ? SCSI_FAILED : SCSI_SUCCESS;
}
@@ -971,10 +909,9 @@ static int sym53c8xx_eh_host_reset_handler(struct scsi_cmnd *cmd)
/*
* Tune device queuing depth, according to various limits.
*/
-static void sym_tune_dev_queuing(struct sym_hcb *np, int target, int lun, u_short reqtags)
+static void sym_tune_dev_queuing(struct sym_tcb *tp, int lun, u_short reqtags)
{
- struct sym_tcb *tp = &np->target[target];
- struct sym_lcb *lp = sym_lp(np, tp, lun);
+ struct sym_lcb *lp = sym_lp(tp, lun);
u_short oldtags;
if (!lp)
@@ -990,9 +927,8 @@ static void sym_tune_dev_queuing(struct sym_hcb *np, int target, int lun, u_shor
lp->s.reqtags = reqtags;
if (reqtags != oldtags) {
- printf_info("%s:%d:%d: "
+ dev_info(&tp->sdev->sdev_target->dev,
"tagged command queuing %s, command queue depth %d.\n",
- sym_name(np), target, lun,
lp->s.reqtags ? "enabled" : "disabled",
lp->started_limit);
}
@@ -1051,21 +987,34 @@ static int device_queue_depth(struct sym_hcb *np, int target, int lun)
return DEF_DEPTH;
}
+static int sym53c8xx_slave_alloc(struct scsi_device *device)
+{
+ struct sym_hcb *np = sym_get_hcb(device->host);
+ struct sym_tcb *tp = &np->target[device->id];
+ if (!tp->sdev)
+ tp->sdev = device;
+
+ return 0;
+}
+
+static void sym53c8xx_slave_destroy(struct scsi_device *device)
+{
+ struct sym_hcb *np = sym_get_hcb(device->host);
+ struct sym_tcb *tp = &np->target[device->id];
+ if (tp->sdev == device)
+ tp->sdev = NULL;
+}
+
/*
* Linux entry point for device queue sizing.
*/
static int sym53c8xx_slave_configure(struct scsi_device *device)
{
- struct Scsi_Host *host = device->host;
- struct sym_hcb *np;
- struct sym_tcb *tp;
+ struct sym_hcb *np = sym_get_hcb(device->host);
+ struct sym_tcb *tp = &np->target[device->id];
struct sym_lcb *lp;
int reqtags, depth_to_use;
- np = ((struct host_data *) host->hostdata)->ncb;
- tp = &np->target[device->id];
- tp->sdev = device;
-
/*
* Allocate the LCB if not yet.
* If it fail, we may well be in the sh*t. :)
@@ -1102,7 +1051,7 @@ static int sym53c8xx_slave_configure(struct scsi_device *device)
MSG_SIMPLE_TAG : 0),
depth_to_use);
lp->s.scdev_depth = depth_to_use;
- sym_tune_dev_queuing(np, device->id, device->lun, reqtags);
+ sym_tune_dev_queuing(tp, device->lun, reqtags);
if (!spi_initial_dv(device->sdev_target))
spi_dv_device(device);
@@ -1115,7 +1064,7 @@ static int sym53c8xx_slave_configure(struct scsi_device *device)
*/
static const char *sym53c8xx_info (struct Scsi_Host *host)
{
- return sym_driver_name();
+ return SYM_DRIVER_NAME;
}
@@ -1178,44 +1127,47 @@ static void sym_exec_user_command (struct sym_hcb *np, struct sym_usrcmd *uc)
case UC_SETSYNC:
if (!uc->data || uc->data >= 255) {
- tp->tinfo.goal.options = 0;
- tp->tinfo.goal.offset = 0;
- break;
- }
- if (uc->data <= 9 && np->minsync_dt) {
+ tp->tgoal.iu = tp->tgoal.dt =
+ tp->tgoal.qas = 0;
+ tp->tgoal.offset = 0;
+ } else if (uc->data <= 9 && np->minsync_dt) {
if (uc->data < np->minsync_dt)
uc->data = np->minsync_dt;
- tp->tinfo.goal.options = PPR_OPT_MASK;
- tp->tinfo.goal.width = 1;
- tp->tinfo.goal.period = uc->data;
- tp->tinfo.goal.offset = np->maxoffs_dt;
+ tp->tgoal.iu = tp->tgoal.dt =
+ tp->tgoal.qas = 1;
+ tp->tgoal.width = 1;
+ tp->tgoal.period = uc->data;
+ tp->tgoal.offset = np->maxoffs_dt;
} else {
if (uc->data < np->minsync)
uc->data = np->minsync;
- tp->tinfo.goal.options = 0;
- tp->tinfo.goal.period = uc->data;
- tp->tinfo.goal.offset = np->maxoffs;
+ tp->tgoal.iu = tp->tgoal.dt =
+ tp->tgoal.qas = 0;
+ tp->tgoal.period = uc->data;
+ tp->tgoal.offset = np->maxoffs;
}
+ tp->tgoal.check_nego = 1;
break;
case UC_SETWIDE:
- tp->tinfo.goal.width = uc->data ? 1 : 0;
+ tp->tgoal.width = uc->data ? 1 : 0;
+ tp->tgoal.check_nego = 1;
break;
case UC_SETTAGS:
for (l = 0; l < SYM_CONF_MAX_LUN; l++)
- sym_tune_dev_queuing(np, t,l, uc->data);
+ sym_tune_dev_queuing(tp, l, uc->data);
break;
case UC_RESETDEV:
tp->to_reset = 1;
np->istat_sem = SEM;
- OUTB (nc_istat, SIGP|SEM);
+ OUTB(np, nc_istat, SIGP|SEM);
break;
case UC_CLEARDEV:
for (l = 0; l < SYM_CONF_MAX_LUN; l++) {
- struct sym_lcb *lp = sym_lp(np, tp, l);
+ struct sym_lcb *lp = sym_lp(tp, l);
if (lp) lp->to_clear = 1;
}
np->istat_sem = SEM;
- OUTB (nc_istat, SIGP|SEM);
+ OUTB(np, nc_istat, SIGP|SEM);
break;
case UC_SETFLAG:
tp->usrflags = uc->data;
@@ -1226,8 +1178,6 @@ static void sym_exec_user_command (struct sym_hcb *np, struct sym_usrcmd *uc)
}
}
-#define digit_to_bin(c) ((c) - '0')
-
static int skip_spaces(char *ptr, int len)
{
int cnt, c;
@@ -1239,17 +1189,10 @@ static int skip_spaces(char *ptr, int len)
static int get_int_arg(char *ptr, int len, u_long *pv)
{
- int cnt, c;
- u_long v;
+ char *end;
- for (v = 0, cnt = len; cnt > 0 && (c = *ptr++) && isdigit(c); cnt--) {
- v = (v * 10) + digit_to_bin(c);
- }
-
- if (pv)
- *pv = v;
-
- return (len - cnt);
+ *pv = simple_strtoul(ptr, &end, 10);
+ return (end - ptr);
}
static int is_keyword(char *ptr, int len, char *verb)
@@ -1260,15 +1203,14 @@ static int is_keyword(char *ptr, int len, char *verb)
return verb_len;
else
return 0;
-
}
-#define SKIP_SPACES(min_spaces) \
- if ((arg_len = skip_spaces(ptr, len)) < (min_spaces)) \
+#define SKIP_SPACES(ptr, len) \
+ if ((arg_len = skip_spaces(ptr, len)) < 1) \
return -EINVAL; \
ptr += arg_len; len -= arg_len;
-#define GET_INT_ARG(v) \
+#define GET_INT_ARG(ptr, len, v) \
if (!(arg_len = get_int_arg(ptr, len, &(v)))) \
return -EINVAL; \
ptr += arg_len; len -= arg_len;
@@ -1327,12 +1269,12 @@ printk("sym_user_command: arg_len=%d, cmd=%ld\n", arg_len, uc->cmd);
case UC_SETFLAG:
case UC_RESETDEV:
case UC_CLEARDEV:
- SKIP_SPACES(1);
+ SKIP_SPACES(ptr, len);
if ((arg_len = is_keyword(ptr, len, "all")) != 0) {
ptr += arg_len; len -= arg_len;
uc->target = ~0;
} else {
- GET_INT_ARG(target);
+ GET_INT_ARG(ptr, len, target);
uc->target = (1<<target);
#ifdef DEBUG_PROC_INFO
printk("sym_user_command: target=%ld\n", target);
@@ -1346,8 +1288,8 @@ printk("sym_user_command: target=%ld\n", target);
case UC_SETSYNC:
case UC_SETTAGS:
case UC_SETWIDE:
- SKIP_SPACES(1);
- GET_INT_ARG(uc->data);
+ SKIP_SPACES(ptr, len);
+ GET_INT_ARG(ptr, len, uc->data);
#ifdef DEBUG_PROC_INFO
printk("sym_user_command: data=%ld\n", uc->data);
#endif
@@ -1355,7 +1297,7 @@ printk("sym_user_command: data=%ld\n", uc->data);
#ifdef SYM_LINUX_DEBUG_CONTROL_SUPPORT
case UC_SETDEBUG:
while (len > 0) {
- SKIP_SPACES(1);
+ SKIP_SPACES(ptr, len);
if ((arg_len = is_keyword(ptr, len, "alloc")))
uc->data |= DEBUG_ALLOC;
else if ((arg_len = is_keyword(ptr, len, "phase")))
@@ -1389,7 +1331,7 @@ printk("sym_user_command: data=%ld\n", uc->data);
#endif /* SYM_LINUX_DEBUG_CONTROL_SUPPORT */
case UC_SETFLAG:
while (len > 0) {
- SKIP_SPACES(1);
+ SKIP_SPACES(ptr, len);
if ((arg_len = is_keyword(ptr, len, "no_disc")))
uc->data &= ~SYM_DISC_ENABLED;
else
@@ -1499,15 +1441,9 @@ static int sym_host_info(struct sym_hcb *np, char *ptr, off_t offset, int len)
static int sym53c8xx_proc_info(struct Scsi_Host *host, char *buffer,
char **start, off_t offset, int length, int func)
{
- struct host_data *host_data;
- struct sym_hcb *np = NULL;
+ struct sym_hcb *np = sym_get_hcb(host);
int retv;
- host_data = (struct host_data *) host->hostdata;
- np = host_data->ncb;
- if (!np)
- return -EINVAL;
-
if (func) {
#ifdef SYM_LINUX_USER_COMMAND_SUPPORT
retv = sym_user_command(np, buffer, length);
@@ -1531,19 +1467,17 @@ static int sym53c8xx_proc_info(struct Scsi_Host *host, char *buffer,
/*
* Free controller resources.
*/
-static void sym_free_resources(struct sym_hcb *np)
+static void sym_free_resources(struct sym_hcb *np, struct pci_dev *pdev)
{
/*
* Free O/S specific resources.
*/
if (np->s.irq)
free_irq(np->s.irq, np);
-#ifndef SYM_CONF_IOMAPPED
- if (np->s.mmio_va)
- iounmap(np->s.mmio_va);
-#endif
- if (np->s.ram_va)
- iounmap(np->s.ram_va);
+ if (np->s.ioaddr)
+ pci_iounmap(pdev, np->s.ioaddr);
+ if (np->s.ramaddr)
+ pci_iounmap(pdev, np->s.ramaddr);
/*
* Free O/S independent resources.
*/
@@ -1592,13 +1526,14 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt,
struct host_data *host_data;
struct sym_hcb *np = NULL;
struct Scsi_Host *instance = NULL;
+ struct pci_dev *pdev = dev->pdev;
unsigned long flags;
struct sym_fw *fw;
printk(KERN_INFO
"sym%d: <%s> rev 0x%x at pci %s irq " IRQ_FMT "\n",
unit, dev->chip.name, dev->chip.revision_id,
- pci_name(dev->pdev), IRQ_PRM(dev->s.irq));
+ pci_name(pdev), IRQ_PRM(pdev->irq));
/*
* Get the firmware for this chip.
@@ -1621,22 +1556,22 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt,
* We keep track in the HCB of all the resources that
* are to be released on error.
*/
- np = __sym_calloc_dma(dev->pdev, sizeof(*np), "HCB");
+ np = __sym_calloc_dma(&pdev->dev, sizeof(*np), "HCB");
if (!np)
goto attach_failed;
- np->s.device = dev->pdev;
- np->bus_dmat = dev->pdev; /* Result in 1 DMA pool per HBA */
+ np->s.device = pdev;
+ np->bus_dmat = &pdev->dev; /* Result in 1 DMA pool per HBA */
host_data->ncb = np;
np->s.host = instance;
- pci_set_drvdata(dev->pdev, np);
+ pci_set_drvdata(pdev, np);
/*
* Copy some useful infos to the HCB.
*/
np->hcb_ba = vtobus(np);
np->verbose = sym_driver_setup.verbose;
- np->s.device = dev->pdev;
+ np->s.device = pdev;
np->s.unit = unit;
np->device_id = dev->chip.device_id;
np->revision_id = dev->chip.revision_id;
@@ -1659,58 +1594,35 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt,
* Try to map the controller chip to
* virtual and physical memory.
*/
- np->mmio_ba = (u32)dev->s.base;
- np->s.io_ws = (np->features & FE_IO256)? 256 : 128;
-
-#ifndef SYM_CONF_IOMAPPED
- np->s.mmio_va = ioremap(dev->s.base_c, np->s.io_ws);
- if (!np->s.mmio_va) {
- printf_err("%s: can't map PCI MMIO region\n", sym_name(np));
- goto attach_failed;
- } else if (sym_verbose > 1)
- printf_info("%s: using memory mapped IO\n", sym_name(np));
-#endif /* !defined SYM_CONF_IOMAPPED */
-
- np->s.io_port = dev->s.io_port;
+ np->mmio_ba = (u32)dev->mmio_base;
+ np->s.ioaddr = dev->s.ioaddr;
+ np->s.ramaddr = dev->s.ramaddr;
+ np->s.io_ws = (np->features & FE_IO256) ? 256 : 128;
/*
* Map on-chip RAM if present and supported.
*/
if (!(np->features & FE_RAM))
- dev->s.base_2 = 0;
- if (dev->s.base_2) {
- np->ram_ba = (u32)dev->s.base_2;
- if (np->features & FE_RAM8K)
- np->ram_ws = 8192;
- else
- np->ram_ws = 4096;
- np->s.ram_va = ioremap(dev->s.base_2_c, np->ram_ws);
- if (!np->s.ram_va) {
- printf_err("%s: can't map PCI MEMORY region\n",
- sym_name(np));
- goto attach_failed;
- }
+ dev->ram_base = 0;
+ if (dev->ram_base) {
+ np->ram_ba = (u32)dev->ram_base;
+ np->ram_ws = (np->features & FE_RAM8K) ? 8192 : 4096;
}
- /*
- * Perform O/S independent stuff.
- */
- if (sym_hcb_attach(np, fw, dev->nvram))
+ if (sym_hcb_attach(instance, fw, dev->nvram))
goto attach_failed;
-
/*
* Install the interrupt handler.
* If we synchonize the C code with SCRIPTS on interrupt,
- * we donnot want to share the INTR line at all.
+ * we do not want to share the INTR line at all.
*/
- if (request_irq(dev->s.irq, sym53c8xx_intr, SA_SHIRQ,
- NAME53C8XX, np)) {
+ if (request_irq(pdev->irq, sym53c8xx_intr, SA_SHIRQ, NAME53C8XX, np)) {
printf_err("%s: request irq %d failure\n",
- sym_name(np), dev->s.irq);
+ sym_name(np), pdev->irq);
goto attach_failed;
}
- np->s.irq = dev->s.irq;
+ np->s.irq = pdev->irq;
/*
* After SCSI devices have been opened, we cannot
@@ -1742,14 +1654,7 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt,
instance->this_id = np->myaddr;
instance->max_id = np->maxwide ? 16 : 8;
instance->max_lun = SYM_CONF_MAX_LUN;
-#ifndef SYM_CONF_IOMAPPED
- instance->base = (unsigned long) np->s.mmio_va;
-#endif
- instance->irq = np->s.irq;
- instance->unique_id = np->s.io_port;
- instance->io_port = np->s.io_port;
- instance->n_io_port = np->s.io_ws;
- instance->dma_channel = 0;
+ instance->unique_id = pci_resource_start(pdev, 0);
instance->cmd_per_lun = SYM_CONF_MAX_TAG;
instance->can_queue = (SYM_CONF_MAX_START-2);
instance->sg_tablesize = SYM_CONF_MAX_SG;
@@ -1770,7 +1675,7 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt,
return NULL;
printf_info("%s: giving up ...\n", sym_name(np));
if (np)
- sym_free_resources(np);
+ sym_free_resources(np, pdev);
scsi_host_put(instance);
return NULL;
@@ -1787,23 +1692,7 @@ static void __devinit sym_get_nvram(struct sym_device *devp, struct sym_nvram *n
devp->device_id = devp->chip.device_id;
nvp->type = 0;
- /*
- * Get access to chip IO registers
- */
-#ifndef SYM_CONF_IOMAPPED
- devp->s.mmio_va = ioremap(devp->s.base_c, 128);
- if (!devp->s.mmio_va)
- return;
-#endif
-
sym_read_nvram(devp, nvp);
-
- /*
- * Release access to chip IO registers
- */
-#ifndef SYM_CONF_IOMAPPED
- iounmap(devp->s.mmio_va);
-#endif
}
#else
static inline void sym_get_nvram(struct sym_device *devp, struct sym_nvram *nvp)
@@ -1813,15 +1702,15 @@ static inline void sym_get_nvram(struct sym_device *devp, struct sym_nvram *nvp)
static int __devinit sym_check_supported(struct sym_device *device)
{
- struct sym_pci_chip *chip;
+ struct sym_chip *chip;
struct pci_dev *pdev = device->pdev;
u_char revision;
- unsigned long io_port = device->s.io_port;
- unsigned long base = device->s.base;
+ unsigned long io_port = pci_resource_start(pdev, 0);
int i;
/*
* If user excluded this chip, do not initialize it.
+ * I hate this code so much. Must kill it.
*/
if (io_port) {
for (i = 0 ; i < 8 ; i++) {
@@ -1831,32 +1720,14 @@ static int __devinit sym_check_supported(struct sym_device *device)
}
/*
- * Check if the chip has been assigned resources we need.
- * XXX: can this still happen with Linux 2.6's PCI layer?
- */
-#ifdef SYM_CONF_IOMAPPED
- if (!io_port) {
- printf_info("%s: IO base address disabled.\n",
- sym_name(device));
- return -ENODEV;
- }
-#else
- if (!base) {
- printf_info("%s: MMIO base address disabled.\n",
- sym_name(device));
- return -ENODEV;
- }
-#endif
-
- /*
* Check if the chip is supported. Then copy the chip description
* to our device structure so we can make it match the actual device
* and options.
*/
pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
- chip = sym_lookup_pci_chip_table(pdev->device, revision);
+ chip = sym_lookup_chip_table(pdev->device, revision);
if (!chip) {
- printf_info("%s: device not supported\n", sym_name(device));
+ dev_info(&pdev->dev, "device not supported\n");
return -ENODEV;
}
memcpy(&device->chip, chip, sizeof(device->chip));
@@ -1871,11 +1742,9 @@ static int __devinit sym_check_supported(struct sym_device *device)
*/
static int __devinit sym_check_raid(struct sym_device *device)
{
- unsigned long base_2_c = device->s.base_2_c;
unsigned int ram_size, ram_val;
- void __iomem *ram_ptr;
- if (!base_2_c)
+ if (!device->s.ramaddr)
return 0;
if (device->chip.features & FE_RAM8K)
@@ -1883,23 +1752,18 @@ static int __devinit sym_check_raid(struct sym_device *device)
else
ram_size = 4096;
- ram_ptr = ioremap(base_2_c, ram_size);
- if (!ram_ptr)
- return 0;
-
- ram_val = readl(ram_ptr + ram_size - 16);
- iounmap(ram_ptr);
+ ram_val = readl(device->s.ramaddr + ram_size - 16);
if (ram_val != 0x52414944)
return 0;
- printf_info("%s: not initializing, driven by RAID controller.\n",
- sym_name(device));
+ dev_info(&device->pdev->dev,
+ "not initializing, driven by RAID controller.\n");
return -ENODEV;
}
static int __devinit sym_set_workarounds(struct sym_device *device)
{
- struct sym_pci_chip *chip = &device->chip;
+ struct sym_chip *chip = &device->chip;
struct pci_dev *pdev = device->pdev;
u_short status_reg;
@@ -1952,26 +1816,25 @@ static int __devinit sym_set_workarounds(struct sym_device *device)
static void __devinit
sym_init_device(struct pci_dev *pdev, struct sym_device *device)
{
- unsigned long base, base_2;
int i;
device->host_id = SYM_SETUP_HOST_ID;
device->pdev = pdev;
- device->s.irq = pdev->irq;
-
- /* Choose some short name for this device */
- sprintf(device->s.inst_name, "sym.%d.%d.%d", pdev->bus->number,
- PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
- device->s.io_port = pdev->resource[0].start;
+ i = pci_get_base_address(pdev, 1, &device->mmio_base);
+ pci_get_base_address(pdev, i, &device->ram_base);
- device->s.base_c = pdev->resource[1].start;
- i = pci_get_base_address(pdev, 1, &base);
- device->s.base = base & PCI_BASE_ADDRESS_MEM_MASK;
-
- device->s.base_2_c = pdev->resource[i].start;
- pci_get_base_address(pdev, i, &base_2);
- device->s.base_2 = base_2 & PCI_BASE_ADDRESS_MEM_MASK;
+#ifndef CONFIG_SCSI_SYM53C8XX_IOMAPPED
+ if (device->mmio_base)
+ device->s.ioaddr = pci_iomap(pdev, 1,
+ pci_resource_len(pdev, 1));
+#endif
+ if (!device->s.ioaddr)
+ device->s.ioaddr = pci_iomap(pdev, 0,
+ pci_resource_len(pdev, 0));
+ if (device->ram_base)
+ device->s.ramaddr = pci_iomap(pdev, i,
+ pci_resource_len(pdev, i));
}
/*
@@ -2027,7 +1890,7 @@ static void sym_config_pqs(struct pci_dev *pdev, struct sym_device *sym_dev)
* Detach the host.
* We have to free resources and halt the NCR chip.
*/
-static int sym_detach(struct sym_hcb *np)
+static int sym_detach(struct sym_hcb *np, struct pci_dev *pdev)
{
printk("%s: detaching ...\n", sym_name(np));
@@ -2039,11 +1902,11 @@ static int sym_detach(struct sym_hcb *np)
* so, since we may not be safe if interrupts occur.
*/
printk("%s: resetting chip\n", sym_name(np));
- OUTB (nc_istat, SRST);
- UDELAY (10);
- OUTB (nc_istat, 0);
+ OUTB(np, nc_istat, SRST);
+ udelay(10);
+ OUTB(np, nc_istat, 0);
- sym_free_resources(np);
+ sym_free_resources(np, pdev);
return 1;
}
@@ -2056,7 +1919,9 @@ static struct scsi_host_template sym2_template = {
.name = "sym53c8xx",
.info = sym53c8xx_info,
.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,
@@ -2116,7 +1981,7 @@ static int __devinit sym2_probe(struct pci_dev *pdev,
return 0;
detach:
- sym_detach(pci_get_drvdata(pdev));
+ sym_detach(pci_get_drvdata(pdev), pdev);
free:
pci_release_regions(pdev);
disable:
@@ -2133,7 +1998,7 @@ static void __devexit sym2_remove(struct pci_dev *pdev)
scsi_remove_host(host);
scsi_host_put(host);
- sym_detach(np);
+ sym_detach(np, pdev);
pci_release_regions(pdev);
pci_disable_device(pdev);
@@ -2143,12 +2008,12 @@ static void __devexit sym2_remove(struct pci_dev *pdev)
static void sym2_get_signalling(struct Scsi_Host *shost)
{
- struct sym_hcb *np = ((struct host_data *)shost->hostdata)->ncb;
+ struct sym_hcb *np = sym_get_hcb(shost);
enum spi_signal_type type;
switch (np->scsi_mode) {
case SMODE_SE:
- type = SPI_SIGNAL_SE;
+ type = SPI_SIGNAL_SE;
break;
case SMODE_LVD:
type = SPI_SIGNAL_LVD;
@@ -2163,152 +2028,97 @@ static void sym2_get_signalling(struct Scsi_Host *shost)
spi_signalling(shost) = type;
}
-static void sym2_get_offset(struct scsi_target *starget)
-{
- struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
- struct sym_hcb *np = ((struct host_data *)shost->hostdata)->ncb;
- struct sym_tcb *tp = &np->target[starget->id];
-
- spi_offset(starget) = tp->tinfo.curr.offset;
-}
-
static void sym2_set_offset(struct scsi_target *starget, int offset)
{
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
- struct sym_hcb *np = ((struct host_data *)shost->hostdata)->ncb;
- struct sym_tcb *tp = &np->target[starget->id];
-
- tp->tinfo.goal.offset = offset;
-}
-
-
-static void sym2_get_period(struct scsi_target *starget)
-{
- struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
- struct sym_hcb *np = ((struct host_data *)shost->hostdata)->ncb;
+ struct sym_hcb *np = sym_get_hcb(shost);
struct sym_tcb *tp = &np->target[starget->id];
- spi_period(starget) = tp->tinfo.curr.period;
+ tp->tgoal.offset = offset;
+ tp->tgoal.check_nego = 1;
}
static void sym2_set_period(struct scsi_target *starget, int period)
{
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
- struct sym_hcb *np = ((struct host_data *)shost->hostdata)->ncb;
+ struct sym_hcb *np = sym_get_hcb(shost);
struct sym_tcb *tp = &np->target[starget->id];
/* have to have DT for these transfers */
if (period <= np->minsync)
- tp->tinfo.goal.options |= PPR_OPT_DT;
+ tp->tgoal.dt = 1;
- tp->tinfo.goal.period = period;
-}
-
-static void sym2_get_width(struct scsi_target *starget)
-{
- struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
- struct sym_hcb *np = ((struct host_data *)shost->hostdata)->ncb;
- struct sym_tcb *tp = &np->target[starget->id];
-
- spi_width(starget) = tp->tinfo.curr.width ? 1 : 0;
+ tp->tgoal.period = period;
+ tp->tgoal.check_nego = 1;
}
static void sym2_set_width(struct scsi_target *starget, int width)
{
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
- struct sym_hcb *np = ((struct host_data *)shost->hostdata)->ncb;
+ struct sym_hcb *np = sym_get_hcb(shost);
struct sym_tcb *tp = &np->target[starget->id];
/* It is illegal to have DT set on narrow transfers. If DT is
* clear, we must also clear IU and QAS. */
if (width == 0)
- tp->tinfo.goal.options &= ~PPR_OPT_MASK;
+ tp->tgoal.iu = tp->tgoal.dt = tp->tgoal.qas = 0;
- tp->tinfo.goal.width = width;
-}
-
-static void sym2_get_dt(struct scsi_target *starget)
-{
- struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
- struct sym_hcb *np = ((struct host_data *)shost->hostdata)->ncb;
- struct sym_tcb *tp = &np->target[starget->id];
-
- spi_dt(starget) = (tp->tinfo.curr.options & PPR_OPT_DT) ? 1 : 0;
+ tp->tgoal.width = width;
+ tp->tgoal.check_nego = 1;
}
static void sym2_set_dt(struct scsi_target *starget, int dt)
{
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
- struct sym_hcb *np = ((struct host_data *)shost->hostdata)->ncb;
+ struct sym_hcb *np = sym_get_hcb(shost);
struct sym_tcb *tp = &np->target[starget->id];
/* We must clear QAS and IU if DT is clear */
if (dt)
- tp->tinfo.goal.options |= PPR_OPT_DT;
+ tp->tgoal.dt = 1;
else
- tp->tinfo.goal.options &= ~PPR_OPT_MASK;
-}
-
-static void sym2_get_iu(struct scsi_target *starget)
-{
- struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
- struct sym_hcb *np = ((struct host_data *)shost->hostdata)->ncb;
- struct sym_tcb *tp = &np->target[starget->id];
-
- spi_iu(starget) = (tp->tinfo.curr.options & PPR_OPT_IU) ? 1 : 0;
+ tp->tgoal.iu = tp->tgoal.dt = tp->tgoal.qas = 0;
+ tp->tgoal.check_nego = 1;
}
static void sym2_set_iu(struct scsi_target *starget, int iu)
{
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
- struct sym_hcb *np = ((struct host_data *)shost->hostdata)->ncb;
+ struct sym_hcb *np = sym_get_hcb(shost);
struct sym_tcb *tp = &np->target[starget->id];
if (iu)
- tp->tinfo.goal.options |= PPR_OPT_IU | PPR_OPT_DT;
+ tp->tgoal.iu = tp->tgoal.dt = 1;
else
- tp->tinfo.goal.options &= ~PPR_OPT_IU;
-}
-
-static void sym2_get_qas(struct scsi_target *starget)
-{
- struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
- struct sym_hcb *np = ((struct host_data *)shost->hostdata)->ncb;
- struct sym_tcb *tp = &np->target[starget->id];
-
- spi_qas(starget) = (tp->tinfo.curr.options & PPR_OPT_QAS) ? 1 : 0;
+ tp->tgoal.iu = 0;
+ tp->tgoal.check_nego = 1;
}
static void sym2_set_qas(struct scsi_target *starget, int qas)
{
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
- struct sym_hcb *np = ((struct host_data *)shost->hostdata)->ncb;
+ struct sym_hcb *np = sym_get_hcb(shost);
struct sym_tcb *tp = &np->target[starget->id];
if (qas)
- tp->tinfo.goal.options |= PPR_OPT_QAS | PPR_OPT_DT;
+ tp->tgoal.dt = tp->tgoal.qas = 1;
else
- tp->tinfo.goal.options &= ~PPR_OPT_QAS;
+ tp->tgoal.qas = 0;
+ tp->tgoal.check_nego = 1;
}
static struct spi_function_template sym2_transport_functions = {
.set_offset = sym2_set_offset,
- .get_offset = sym2_get_offset,
.show_offset = 1,
.set_period = sym2_set_period,
- .get_period = sym2_get_period,
.show_period = 1,
.set_width = sym2_set_width,
- .get_width = sym2_get_width,
.show_width = 1,
- .get_dt = sym2_get_dt,
.set_dt = sym2_set_dt,
.show_dt = 1,
- .get_iu = sym2_get_iu,
.set_iu = sym2_set_iu,
.show_iu = 1,
- .get_qas = sym2_get_qas,
.set_qas = sym2_set_qas,
.show_qas = 1,
.get_signalling = sym2_get_signalling,
@@ -2370,7 +2180,7 @@ static int __init sym2_init(void)
if (!sym2_transport_template)
return -ENODEV;
- error = pci_module_init(&sym2_driver);
+ error = pci_register_driver(&sym2_driver);
if (error)
spi_release_transport(sym2_transport_template);
return error;
diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.h b/drivers/scsi/sym53c8xx_2/sym_glue.h
index 7cfb1b21b69ae..e943f167fb510 100644
--- a/drivers/scsi/sym53c8xx_2/sym_glue.h
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.h
@@ -56,9 +56,10 @@
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_device.h>
+#include <scsi/scsi_transport_spi.h>
#include <scsi/scsi_host.h>
-#include "sym_conf.h"
+#include "sym53c8xx.h"
#include "sym_defs.h"
#include "sym_misc.h"
@@ -70,7 +71,6 @@
#define SYM_OPT_HANDLE_DIR_UNKNOWN
#define SYM_OPT_HANDLE_DEVICE_QUEUEING
#define SYM_OPT_LIMIT_COMMAND_REORDERING
-#define SYM_OPT_ANNOUNCE_TRANSFER_RATE
/*
* Print a message with severity.
@@ -86,11 +86,6 @@
#define printf(args...) printk(args)
/*
- * Insert a delay in micro-seconds
- */
-#define sym_udelay(us) udelay(us)
-
-/*
* A 'read barrier' flushes any data that have been prefetched
* by the processor due to out of order execution. Such a barrier
* must notably be inserted prior to looking at data that have
@@ -111,23 +106,12 @@
#define MEMORY_WRITE_BARRIER() wmb()
/*
- * Let the compiler know about driver data structure names.
- */
-typedef struct sym_tcb *tcb_p;
-typedef struct sym_lcb *lcb_p;
-typedef struct sym_ccb *ccb_p;
-
-/*
* IO functions definition for big/little endian CPU support.
* For now, PCI chips are 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 readw_l2b readw
#define readl_l2b readl
#define writew_b2l writew
@@ -135,11 +119,6 @@ typedef struct sym_ccb *ccb_p;
#else /* little endian */
-#define inw_raw inw
-#define inl_raw inl
-#define outw_raw outw
-#define outl_raw outl
-
#define readw_raw readw
#define readl_raw readl
#define writew_raw writew
@@ -151,27 +130,6 @@ typedef struct sym_ccb *ccb_p;
#error "Chips in BIG ENDIAN addressing mode are not (yet) supported"
#endif
-
-/*
- * If the chip 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, sym_offb() and sym_offw() macros only apply to
- * constants and so donnot generate bloated code.
- */
-
-#if defined(SYM_CONF_CHIP_BIG_ENDIAN)
-
-#define sym_offb(o) (((o)&~3)+((~((o)&3))&3))
-#define sym_offw(o) (((o)&~3)+((~((o)&3))&2))
-
-#else
-
-#define sym_offb(o) (o)
-#define sym_offw(o) (o)
-
-#endif
-
/*
* If the CPU and the chip use same endian-ness addressing,
* no byte reordering is needed for script patching.
@@ -180,117 +138,9 @@ typedef struct sym_ccb *ccb_p;
* from the script.
*/
-#if defined(__BIG_ENDIAN) && !defined(SYM_CONF_CHIP_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(SYM_CONF_CHIP_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 SYM_CONF_IOMAPPED is defined, the driver will use
- * normal IOs instead of the MEMORY MAPPED IO method
- * recommended by PCI specifications.
- * If all PCI bridges, host brigdes and architectures
- * would have been correctly designed for PCI, this
- * option would be useless.
- *
- * If the CPU and the chip 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, ...
- */
-
-#if defined(SYM_CONF_IOMAPPED)
-
-/*
- * IO mapped only input / ouput
- */
-
-#define INB_OFF(o) inb (np->s.io_port + sym_offb(o))
-#define OUTB_OFF(o, val) outb ((val), np->s.io_port + sym_offb(o))
-
-#if defined(__BIG_ENDIAN) && !defined(SYM_CONF_CHIP_BIG_ENDIAN)
-
-#define INW_OFF(o) inw_l2b (np->s.io_port + sym_offw(o))
-#define INL_OFF(o) inl_l2b (np->s.io_port + (o))
-
-#define OUTW_OFF(o, val) outw_b2l ((val), np->s.io_port + sym_offw(o))
-#define OUTL_OFF(o, val) outl_b2l ((val), np->s.io_port + (o))
-
-#elif defined(__LITTLE_ENDIAN) && defined(SYM_CONF_CHIP_BIG_ENDIAN)
-
-#define INW_OFF(o) inw_b2l (np->s.io_port + sym_offw(o))
-#define INL_OFF(o) inl_b2l (np->s.io_port + (o))
-
-#define OUTW_OFF(o, val) outw_l2b ((val), np->s.io_port + sym_offw(o))
-#define OUTL_OFF(o, val) outl_l2b ((val), np->s.io_port + (o))
-
-#else
-
-#define INW_OFF(o) inw_raw (np->s.io_port + sym_offw(o))
-#define INL_OFF(o) inl_raw (np->s.io_port + (o))
-
-#define OUTW_OFF(o, val) outw_raw ((val), np->s.io_port + sym_offw(o))
-#define OUTL_OFF(o, val) outl_raw ((val), np->s.io_port + (o))
-
-#endif /* ENDIANs */
-
-#else /* defined SYM_CONF_IOMAPPED */
-
-/*
- * MEMORY mapped IO input / output
- */
-
-#define INB_OFF(o) readb(np->s.mmio_va + sym_offb(o))
-#define OUTB_OFF(o, val) writeb((val), np->s.mmio_va + sym_offb(o))
-
-#if defined(__BIG_ENDIAN) && !defined(SYM_CONF_CHIP_BIG_ENDIAN)
-
-#define INW_OFF(o) readw_l2b(np->s.mmio_va + sym_offw(o))
-#define INL_OFF(o) readl_l2b(np->s.mmio_va + (o))
-
-#define OUTW_OFF(o, val) writew_b2l((val), np->s.mmio_va + sym_offw(o))
-#define OUTL_OFF(o, val) writel_b2l((val), np->s.mmio_va + (o))
-
-#elif defined(__LITTLE_ENDIAN) && defined(SYM_CONF_CHIP_BIG_ENDIAN)
-
-#define INW_OFF(o) readw_b2l(np->s.mmio_va + sym_offw(o))
-#define INL_OFF(o) readl_b2l(np->s.mmio_va + (o))
-
-#define OUTW_OFF(o, val) writew_l2b((val), np->s.mmio_va + sym_offw(o))
-#define OUTL_OFF(o, val) writel_l2b((val), np->s.mmio_va + (o))
-
-#else
-
-#define INW_OFF(o) readw_raw(np->s.mmio_va + sym_offw(o))
-#define INL_OFF(o) readl_raw(np->s.mmio_va + (o))
-
-#define OUTW_OFF(o, val) writew_raw((val), np->s.mmio_va + sym_offw(o))
-#define OUTL_OFF(o, val) writel_raw((val), np->s.mmio_va + (o))
-
-#endif
-
-#endif /* defined SYM_CONF_IOMAPPED */
-
-#define OUTRAM_OFF(o, a, l) memcpy_toio(np->s.ram_va + (o), (a), (l))
-
/*
* Remap some status field values.
*/
@@ -360,9 +210,8 @@ struct sym_shcb {
struct Scsi_Host *host;
- void __iomem * mmio_va; /* MMIO kernel virtual address */
- void __iomem * ram_va; /* RAM kernel virtual address */
- u_long io_port; /* IO port address cookie */
+ void __iomem * ioaddr; /* MMIO kernel io address */
+ void __iomem * ramaddr; /* RAM kernel io address */
u_short io_ws; /* IO window size */
int irq; /* IRQ number */
@@ -377,29 +226,20 @@ struct sym_shcb {
*/
#define sym_name(np) (np)->s.inst_name
-/*
- * Data structure used as input for the NVRAM reading.
- * Must resolve the IO macros and sym_name(), when
- * used as sub-field 's' of another structure.
- */
-struct sym_slot {
- u_long base;
- u_long base_2;
- u_long base_c;
- u_long base_2_c;
- int irq;
-/* port and address fields to fit INB, OUTB macros */
- u_long io_port;
- void __iomem * mmio_va;
- char inst_name[16];
-};
-
struct sym_nvram;
+/*
+ * The IO macros require a struct called 's' and are abused in sym_nvram.c
+ */
struct sym_device {
struct pci_dev *pdev;
- struct sym_slot s;
- struct sym_pci_chip chip;
+ unsigned long mmio_base;
+ unsigned long ram_base;
+ struct {
+ void __iomem *ioaddr;
+ void __iomem *ramaddr;
+ } s;
+ struct sym_chip chip;
struct sym_nvram *nvram;
u_short device_id;
u_char host_id;
@@ -412,133 +252,48 @@ struct host_data {
struct sym_hcb *ncb;
};
-/*
- * The driver definitions (sym_hipd.h) must know about a
- * couple of things related to the memory allocator.
- */
-typedef u_long m_addr_t; /* Enough bits to represent any address */
-#define SYM_MEM_PAGE_ORDER 0 /* 1 PAGE maximum */
-#define SYM_MEM_CLUSTER_SHIFT (PAGE_SHIFT+SYM_MEM_PAGE_ORDER)
-#ifdef MODULE
-#define SYM_MEM_FREE_UNUSED /* Free unused pages immediately */
-#endif
-typedef struct pci_dev *m_pool_ident_t;
-
-/*
- * Include driver soft definitions.
- */
-#include "sym_fw.h"
-#include "sym_hipd.h"
-
-/*
- * Memory allocator related stuff.
- */
-
-#define SYM_MEM_GFP_FLAGS GFP_ATOMIC
-#define SYM_MEM_WARN 1 /* Warn on failed operations */
-
-#define sym_get_mem_cluster() \
- __get_free_pages(SYM_MEM_GFP_FLAGS, SYM_MEM_PAGE_ORDER)
-#define sym_free_mem_cluster(p) \
- free_pages(p, SYM_MEM_PAGE_ORDER)
-
-void *sym_calloc(int size, char *name);
-void sym_mfree(void *m, int size, char *name);
-
-/*
- * We have to provide the driver memory allocator with methods for
- * it to maintain virtual to bus physical address translations.
- */
-
-#define sym_m_pool_match(mp_id1, mp_id2) (mp_id1 == mp_id2)
-
-static __inline m_addr_t sym_m_get_dma_mem_cluster(m_pool_p mp, m_vtob_p vbp)
-{
- void *vaddr = NULL;
- dma_addr_t baddr = 0;
-
- vaddr = pci_alloc_consistent(mp->dev_dmat,SYM_MEM_CLUSTER_SIZE, &baddr);
- if (vaddr) {
- vbp->vaddr = (m_addr_t) vaddr;
- vbp->baddr = (m_addr_t) baddr;
- }
- return (m_addr_t) vaddr;
-}
-
-static __inline void sym_m_free_dma_mem_cluster(m_pool_p mp, m_vtob_p vbp)
+static inline struct sym_hcb * sym_get_hcb(struct Scsi_Host *host)
{
- pci_free_consistent(mp->dev_dmat, SYM_MEM_CLUSTER_SIZE,
- (void *)vbp->vaddr, (dma_addr_t)vbp->baddr);
+ return ((struct host_data *)host->hostdata)->ncb;
}
-#define sym_m_create_dma_mem_tag(mp) (0)
-#define sym_m_delete_dma_mem_tag(mp) do { ; } while (0)
-
-void *__sym_calloc_dma(m_pool_ident_t dev_dmat, int size, char *name);
-void __sym_mfree_dma(m_pool_ident_t dev_dmat, void *m, int size, char *name);
-m_addr_t __vtobus(m_pool_ident_t dev_dmat, void *m);
+#include "sym_fw.h"
+#include "sym_hipd.h"
/*
* Set the status field of a CAM CCB.
*/
static __inline void
-sym_set_cam_status(struct scsi_cmnd *ccb, int status)
+sym_set_cam_status(struct scsi_cmnd *cmd, int status)
{
- ccb->result &= ~(0xff << 16);
- ccb->result |= (status << 16);
+ cmd->result &= ~(0xff << 16);
+ cmd->result |= (status << 16);
}
/*
* Get the status field of a CAM CCB.
*/
static __inline int
-sym_get_cam_status(struct scsi_cmnd *ccb)
+sym_get_cam_status(struct scsi_cmnd *cmd)
{
- return ((ccb->result >> 16) & 0xff);
+ return host_byte(cmd->result);
}
/*
- * The dma mapping is mostly handled by the
- * SCSI layer and the driver glue under Linux.
- */
-#define sym_data_dmamap_create(np, cp) (0)
-#define sym_data_dmamap_destroy(np, cp) do { ; } while (0)
-#define sym_data_dmamap_unload(np, cp) do { ; } while (0)
-#define sym_data_dmamap_presync(np, cp) do { ; } while (0)
-#define sym_data_dmamap_postsync(np, cp) do { ; } while (0)
-
-/*
- * Async handler for negotiations.
- */
-void sym_xpt_async_nego_wide(struct sym_hcb *np, int target);
-#define sym_xpt_async_nego_sync(np, target) \
- sym_announce_transfer_rate(np, target)
-#define sym_xpt_async_nego_ppr(np, target) \
- sym_announce_transfer_rate(np, target)
-
-/*
* Build CAM result for a successful IO and for a failed IO.
*/
-static __inline void sym_set_cam_result_ok(struct sym_hcb *np, ccb_p cp, int resid)
+static __inline void sym_set_cam_result_ok(struct sym_ccb *cp, struct scsi_cmnd *cmd, int resid)
{
- struct scsi_cmnd *cmd = cp->cam_ccb;
-
cmd->resid = resid;
cmd->result = (((DID_OK) << 16) + ((cp->ssss_status) & 0x7f));
}
-void sym_set_cam_result_error(struct sym_hcb *np, ccb_p cp, int resid);
+void sym_set_cam_result_error(struct sym_hcb *np, struct sym_ccb *cp, int resid);
-/*
- * Other O/S specific methods.
- */
-#define sym_cam_target_id(ccb) (ccb)->target
-#define sym_cam_target_lun(ccb) (ccb)->lun
-#define sym_freeze_cam_ccb(ccb) do { ; } while (0)
void sym_xpt_done(struct sym_hcb *np, struct scsi_cmnd *ccb);
-void sym_print_addr (ccb_p cp);
+#define sym_print_addr(cmd, arg...) dev_info(&cmd->device->sdev_gendev , ## arg)
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, ccb_p cp);
+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);
diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c
index 8b7aa921e487a..50a176b3888d4 100644
--- a/drivers/scsi/sym53c8xx_2/sym_hipd.c
+++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c
@@ -3,7 +3,7 @@
* of PCI-SCSI IO processors.
*
* Copyright (C) 1999-2001 Gerard Roudier <groudier@free.fr>
- * Copyright (c) 2003-2004 Matthew Wilcox <matthew@wil.cx>
+ * Copyright (c) 2003-2005 Matthew Wilcox <matthew@wil.cx>
*
* This driver is derived from the Linux sym53c8xx driver.
* Copyright (C) 1998-2000 Gerard Roudier
@@ -49,54 +49,24 @@
*/
static void sym_int_ma (struct sym_hcb *np);
static void sym_int_sir (struct sym_hcb *np);
-static ccb_p sym_alloc_ccb(struct sym_hcb *np);
-static ccb_p sym_ccb_from_dsa(struct sym_hcb *np, u32 dsa);
+static struct sym_ccb *sym_alloc_ccb(struct sym_hcb *np);
+static struct sym_ccb *sym_ccb_from_dsa(struct sym_hcb *np, u32 dsa);
static void sym_alloc_lcb_tags (struct sym_hcb *np, u_char tn, u_char ln);
-static void sym_complete_error (struct sym_hcb *np, ccb_p cp);
-static void sym_complete_ok (struct sym_hcb *np, ccb_p cp);
-static int sym_compute_residual(struct sym_hcb *np, ccb_p cp);
+static void sym_complete_error (struct sym_hcb *np, struct sym_ccb *cp);
+static void sym_complete_ok (struct sym_hcb *np, struct sym_ccb *cp);
+static int sym_compute_residual(struct sym_hcb *np, struct sym_ccb *cp);
/*
- * Returns the name of this driver.
+ * Print a buffer in hexadecimal format with a ".\n" at end.
*/
-char *sym_driver_name(void)
-{
- return SYM_DRIVER_NAME;
-}
-/*
- * Print a buffer in hexadecimal format.
- */
-static void sym_printb_hex (u_char *p, int n)
+static void sym_printl_hex(u_char *p, int n)
{
while (n-- > 0)
printf (" %x", *p++);
-}
-
-/*
- * Same with a label at beginning and .\n at end.
- */
-static void sym_printl_hex (char *label, u_char *p, int n)
-{
- printf ("%s", label);
- sym_printb_hex (p, n);
printf (".\n");
}
/*
- * Print something which allows to retrieve the controler type,
- * unit, target, lun concerned by a kernel message.
- */
-static void sym_print_target (struct sym_hcb *np, int target)
-{
- printf ("%s:%d:", sym_name(np), target);
-}
-
-static void sym_print_lun(struct sym_hcb *np, int target, int lun)
-{
- printf ("%s:%d:%d:", sym_name(np), target, lun);
-}
-
-/*
* Print out the content of a SCSI message.
*/
static int sym_show_msg (u_char * msg)
@@ -107,59 +77,51 @@ static int sym_show_msg (u_char * msg)
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 (ccb_p cp, char *label, u_char *msg)
+static void sym_print_msg(struct sym_ccb *cp, char *label, u_char *msg)
{
- PRINT_ADDR(cp);
- if (label)
- printf ("%s: ", label);
+ sym_print_addr(cp->cmd, "%s: ", label);
- (void) sym_show_msg (msg);
- printf (".\n");
+ sym_show_msg(msg);
+ printf(".\n");
}
-static void sym_print_nego_msg (struct sym_hcb *np, int target, char *label, u_char *msg)
+static void sym_print_nego_msg(struct sym_hcb *np, int target, char *label, u_char *msg)
{
- PRINT_TARGET(np, target);
- if (label)
- printf ("%s: ", label);
+ struct sym_tcb *tp = &np->target[target];
+ dev_info(&tp->sdev->sdev_target->dev, "%s: ", label);
- (void) sym_show_msg (msg);
- printf (".\n");
+ sym_show_msg(msg);
+ printf(".\n");
}
/*
* Print something that tells about extended errors.
*/
-void sym_print_xerr(ccb_p cp, int x_status)
+void sym_print_xerr(struct scsi_cmnd *cmd, int x_status)
{
if (x_status & XE_PARITY_ERR) {
- PRINT_ADDR(cp);
- printf ("unrecovered SCSI parity error.\n");
+ sym_print_addr(cmd, "unrecovered SCSI parity error.\n");
}
if (x_status & XE_EXTRA_DATA) {
- PRINT_ADDR(cp);
- printf ("extraneous data discarded.\n");
+ sym_print_addr(cmd, "extraneous data discarded.\n");
}
if (x_status & XE_BAD_PHASE) {
- PRINT_ADDR(cp);
- printf ("illegal scsi phase (4/5).\n");
+ sym_print_addr(cmd, "illegal scsi phase (4/5).\n");
}
if (x_status & XE_SODL_UNRUN) {
- PRINT_ADDR(cp);
- printf ("ODD transfer in DATA OUT phase.\n");
+ sym_print_addr(cmd, "ODD transfer in DATA OUT phase.\n");
}
if (x_status & XE_SWIDE_OVRUN) {
- PRINT_ADDR(cp);
- printf ("ODD transfer in DATA IN phase.\n");
+ sym_print_addr(cmd, "ODD transfer in DATA IN phase.\n");
}
}
@@ -186,10 +148,10 @@ static char *sym_scsi_bus_mode(int mode)
*/
static void sym_chip_reset (struct sym_hcb *np)
{
- OUTB (nc_istat, SRST);
- UDELAY (10);
- OUTB (nc_istat, 0);
- UDELAY(2000); /* For BUS MODE to settle */
+ OUTB(np, nc_istat, SRST);
+ udelay(10);
+ OUTB(np, nc_istat, 0);
+ udelay(2000); /* For BUS MODE to settle */
}
/*
@@ -206,27 +168,27 @@ static void sym_soft_reset (struct sym_hcb *np)
u_char istat = 0;
int i;
- if (!(np->features & FE_ISTAT1) || !(INB (nc_istat1) & SCRUN))
+ if (!(np->features & FE_ISTAT1) || !(INB(np, nc_istat1) & SCRUN))
goto do_chip_reset;
- OUTB (nc_istat, CABRT);
+ OUTB(np, nc_istat, CABRT);
for (i = 100000 ; i ; --i) {
- istat = INB (nc_istat);
+ istat = INB(np, nc_istat);
if (istat & SIP) {
- INW (nc_sist);
+ INW(np, nc_sist);
}
else if (istat & DIP) {
- if (INB (nc_dstat) & ABRT)
+ if (INB(np, nc_dstat) & ABRT)
break;
}
- UDELAY(5);
+ udelay(5);
}
- OUTB (nc_istat, 0);
+ OUTB(np, nc_istat, 0);
if (!i)
printf("%s: unable to abort current chip operation, "
"ISTAT=0x%02x.\n", sym_name(np), istat);
do_chip_reset:
- sym_chip_reset (np);
+ sym_chip_reset(np);
}
/*
@@ -236,7 +198,7 @@ do_chip_reset:
*/
static void sym_start_reset(struct sym_hcb *np)
{
- (void) sym_reset_scsi_bus(np, 1);
+ sym_reset_scsi_bus(np, 1);
}
int sym_reset_scsi_bus(struct sym_hcb *np, int enab_int)
@@ -246,15 +208,15 @@ int sym_reset_scsi_bus(struct sym_hcb *np, int enab_int)
sym_soft_reset(np); /* Soft reset the chip */
if (enab_int)
- OUTW (nc_sien, RST);
+ OUTW(np, nc_sien, RST);
/*
* Enable Tolerant, reset IRQD if present and
* properly set IRQ mode, prior to resetting the bus.
*/
- OUTB (nc_stest3, TE);
- OUTB (nc_dcntl, (np->rv_dcntl & IRQM));
- OUTB (nc_scntl1, CRST);
- UDELAY (200);
+ OUTB(np, nc_stest3, TE);
+ OUTB(np, nc_dcntl, (np->rv_dcntl & IRQM));
+ OUTB(np, nc_scntl1, CRST);
+ udelay(200);
if (!SYM_SETUP_SCSI_BUS_CHECK)
goto out;
@@ -264,12 +226,12 @@ int sym_reset_scsi_bus(struct sym_hcb *np, int enab_int)
* We are expecting RESET to be TRUE and other signals to be
* FALSE.
*/
- term = INB(nc_sstat0);
+ term = INB(np, nc_sstat0);
term = ((term & 2) << 7) + ((term & 1) << 17); /* rst sdp0 */
- term |= ((INB(nc_sstat2) & 0x01) << 26) | /* sdp1 */
- ((INW(nc_sbdl) & 0xff) << 9) | /* d7-0 */
- ((INW(nc_sbdl) & 0xff00) << 10) | /* d15-8 */
- INB(nc_sbcl); /* req ack bsy sel atn msg cd io */
+ term |= ((INB(np, nc_sstat2) & 0x01) << 26) | /* sdp1 */
+ ((INW(np, nc_sbdl) & 0xff) << 9) | /* d7-0 */
+ ((INW(np, nc_sbdl) & 0xff00) << 10) | /* d15-8 */
+ INB(np, nc_sbcl); /* req ack bsy sel atn msg cd io */
if (!np->maxwide)
term &= 0x3ffff;
@@ -286,7 +248,7 @@ int sym_reset_scsi_bus(struct sym_hcb *np, int enab_int)
retv = 1;
}
out:
- OUTB (nc_scntl1, 0);
+ OUTB(np, nc_scntl1, 0);
return retv;
}
@@ -299,31 +261,31 @@ static void sym_selectclock(struct sym_hcb *np, u_char scntl3)
* If multiplier not present or not selected, leave here.
*/
if (np->multiplier <= 1) {
- OUTB(nc_scntl3, scntl3);
+ OUTB(np, nc_scntl3, scntl3);
return;
}
if (sym_verbose >= 2)
printf ("%s: enabling clock multiplier\n", sym_name(np));
- OUTB(nc_stest1, DBLEN); /* Enable clock multiplier */
+ OUTB(np, nc_stest1, DBLEN); /* Enable clock multiplier */
/*
* Wait for the LCKFRQ bit to be set if supported by the chip.
* Otherwise wait 50 micro-seconds (at least).
*/
if (np->features & FE_LCKFRQ) {
int i = 20;
- while (!(INB(nc_stest4) & LCKFRQ) && --i > 0)
- UDELAY (20);
+ while (!(INB(np, nc_stest4) & LCKFRQ) && --i > 0)
+ udelay(20);
if (!i)
printf("%s: the chip cannot lock the frequency\n",
sym_name(np));
} else
- UDELAY ((50+10));
- OUTB(nc_stest3, HSC); /* Halt the scsi clock */
- OUTB(nc_scntl3, scntl3);
- OUTB(nc_stest1, (DBLEN|DBLSEL));/* Select clock multiplier */
- OUTB(nc_stest3, 0x00); /* Restart scsi clock */
+ udelay((50+10));
+ OUTB(np, nc_stest3, HSC); /* Halt the scsi clock */
+ OUTB(np, nc_scntl3, scntl3);
+ OUTB(np, nc_stest1, (DBLEN|DBLSEL));/* Select clock multiplier */
+ OUTB(np, nc_stest3, 0x00); /* Restart scsi clock */
}
@@ -368,38 +330,38 @@ static unsigned getfreq (struct sym_hcb *np, int gen)
* performed trust the higher delay
* (lower frequency returned).
*/
- OUTW (nc_sien , 0); /* mask all scsi interrupts */
- (void) INW (nc_sist); /* clear pending scsi interrupt */
- OUTB (nc_dien , 0); /* mask all dma interrupts */
- (void) INW (nc_sist); /* another one, just to be sure :) */
+ OUTW(np, nc_sien, 0); /* mask all scsi interrupts */
+ INW(np, nc_sist); /* clear pending scsi interrupt */
+ OUTB(np, nc_dien, 0); /* mask all dma interrupts */
+ INW(np, nc_sist); /* another one, just to be sure :) */
/*
* The C1010-33 core does not report GEN in SIST,
* if this interrupt is masked in SIEN.
* I don't know yet if the C1010-66 behaves the same way.
*/
if (np->features & FE_C10) {
- OUTW (nc_sien, GEN);
- OUTB (nc_istat1, SIRQD);
+ OUTW(np, nc_sien, GEN);
+ OUTB(np, nc_istat1, SIRQD);
}
- OUTB (nc_scntl3, 4); /* set pre-scaler to divide by 3 */
- OUTB (nc_stime1, 0); /* disable general purpose timer */
- OUTB (nc_stime1, gen); /* set to nominal delay of 1<<gen * 125us */
- while (!(INW(nc_sist) & GEN) && ms++ < 100000)
- UDELAY (1000/4);/* count in 1/4 of ms */
- OUTB (nc_stime1, 0); /* disable general purpose timer */
+ OUTB(np, nc_scntl3, 4); /* set pre-scaler to divide by 3 */
+ OUTB(np, nc_stime1, 0); /* disable general purpose timer */
+ OUTB(np, nc_stime1, gen); /* set to nominal delay of 1<<gen * 125us */
+ while (!(INW(np, nc_sist) & GEN) && ms++ < 100000)
+ udelay(1000/4); /* count in 1/4 of ms */
+ OUTB(np, nc_stime1, 0); /* disable general purpose timer */
/*
* Undo C1010-33 specific settings.
*/
if (np->features & FE_C10) {
- OUTW (nc_sien, 0);
- OUTB (nc_istat1, 0);
+ OUTW(np, nc_sien, 0);
+ OUTB(np, nc_istat1, 0);
}
/*
* set prescaler to divide by whatever 0 means
* 0 ought to choose divide by 2, but appears
* to set divide by 3.5 mode in my 53c810 ...
*/
- OUTB (nc_scntl3, 0);
+ OUTB(np, nc_scntl3, 0);
/*
* adjust for prescaler, and convert into KHz
@@ -425,7 +387,7 @@ static unsigned sym_getfreq (struct sym_hcb *np)
u_int f1, f2;
int gen = 8;
- (void) getfreq (np, gen); /* throw away first result */
+ getfreq (np, gen); /* throw away first result */
f1 = getfreq (np, gen);
f2 = getfreq (np, gen);
if (f1 > f2) f1 = f2; /* trust lower result */
@@ -458,7 +420,7 @@ static void sym_getclock (struct sym_hcb *np, int mult)
* Otherwise trust scntl3 BIOS setting.
*/
if (np->multiplier != mult || (scntl3 & 7) < 3 || !(scntl3 & 1)) {
- OUTB (nc_stest1, 0); /* make sure doubler is OFF */
+ OUTB(np, nc_stest1, 0); /* make sure doubler is OFF */
f1 = sym_getfreq (np);
if (sym_verbose)
@@ -505,9 +467,9 @@ static int sym_getpciclock (struct sym_hcb *np)
#else
if (1) {
#endif
- OUTB (nc_stest1, SCLK); /* Use the PCI clock as SCSI clock */
- f = (int) sym_getfreq (np);
- OUTB (nc_stest1, 0);
+ OUTB(np, nc_stest1, SCLK); /* Use the PCI clock as SCSI clock */
+ f = sym_getfreq(np);
+ OUTB(np, nc_stest1, 0);
}
np->pciclk_khz = f;
@@ -698,29 +660,29 @@ static void sym_print_targets_flag(struct sym_hcb *np, int mask, char *msg)
*/
static void sym_save_initial_setting (struct sym_hcb *np)
{
- np->sv_scntl0 = INB(nc_scntl0) & 0x0a;
- np->sv_scntl3 = INB(nc_scntl3) & 0x07;
- np->sv_dmode = INB(nc_dmode) & 0xce;
- np->sv_dcntl = INB(nc_dcntl) & 0xa8;
- np->sv_ctest3 = INB(nc_ctest3) & 0x01;
- np->sv_ctest4 = INB(nc_ctest4) & 0x80;
- np->sv_gpcntl = INB(nc_gpcntl);
- np->sv_stest1 = INB(nc_stest1);
- np->sv_stest2 = INB(nc_stest2) & 0x20;
- np->sv_stest4 = INB(nc_stest4);
+ np->sv_scntl0 = INB(np, nc_scntl0) & 0x0a;
+ np->sv_scntl3 = INB(np, nc_scntl3) & 0x07;
+ np->sv_dmode = INB(np, nc_dmode) & 0xce;
+ np->sv_dcntl = INB(np, nc_dcntl) & 0xa8;
+ np->sv_ctest3 = INB(np, nc_ctest3) & 0x01;
+ np->sv_ctest4 = INB(np, nc_ctest4) & 0x80;
+ np->sv_gpcntl = INB(np, nc_gpcntl);
+ np->sv_stest1 = INB(np, nc_stest1);
+ np->sv_stest2 = INB(np, nc_stest2) & 0x20;
+ np->sv_stest4 = INB(np, nc_stest4);
if (np->features & FE_C10) { /* Always large DMA fifo + ultra3 */
- np->sv_scntl4 = INB(nc_scntl4);
- np->sv_ctest5 = INB(nc_ctest5) & 0x04;
+ np->sv_scntl4 = INB(np, nc_scntl4);
+ np->sv_ctest5 = INB(np, nc_ctest5) & 0x04;
}
else
- np->sv_ctest5 = INB(nc_ctest5) & 0x24;
+ np->sv_ctest5 = INB(np, nc_ctest5) & 0x24;
}
/*
* Prepare io register values used by sym_start_up()
* according to selected and supported features.
*/
-static int sym_prepare_setting(struct sym_hcb *np, struct sym_nvram *nvram)
+static int sym_prepare_setting(struct Scsi_Host *shost, struct sym_hcb *np, struct sym_nvram *nvram)
{
u_char burst_max;
u32 period;
@@ -903,22 +865,20 @@ static int sym_prepare_setting(struct sym_hcb *np, struct sym_nvram *nvram)
/*
* Select some other
*/
- if (SYM_SETUP_PCI_PARITY)
- np->rv_ctest4 |= MPEE; /* Master parity checking */
- if (SYM_SETUP_SCSI_PARITY)
- np->rv_scntl0 |= 0x0a; /* full arb., ena parity, par->ATN */
+ np->rv_ctest4 |= MPEE; /* Master parity checking */
+ np->rv_scntl0 |= 0x0a; /* full arb., ena parity, par->ATN */
/*
* Get parity checking, host ID and verbose mode from NVRAM
*/
np->myaddr = 255;
- sym_nvram_setup_host (np, nvram);
+ sym_nvram_setup_host(shost, np, nvram);
/*
* Get SCSI addr of host adapter (set by bios?).
*/
if (np->myaddr == 255) {
- np->myaddr = INB(nc_scid) & 0x07;
+ np->myaddr = INB(np, nc_scid) & 0x07;
if (!np->myaddr)
np->myaddr = SYM_SETUP_HOST_ID;
}
@@ -946,7 +906,7 @@ static int sym_prepare_setting(struct sym_hcb *np, struct sym_nvram *nvram)
np->scsi_mode = SMODE_HVD;
}
else if (nvram->type == SYM_SYMBIOS_NVRAM) {
- if (!(INB(nc_gpreg) & 0x08))
+ if (!(INB(np, nc_gpreg) & 0x08))
np->scsi_mode = SMODE_HVD;
}
}
@@ -988,12 +948,12 @@ static int sym_prepare_setting(struct sym_hcb *np, struct sym_nvram *nvram)
* If NVRAM present get targets setup from NVRAM.
*/
for (i = 0 ; i < SYM_CONF_MAX_TARGET ; i++) {
- tcb_p tp = &np->target[i];
+ struct sym_tcb *tp = &np->target[i];
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(np, i, nvram);
if (!tp->usrtags)
tp->usrflags &= ~SYM_TAGS_ENABLED;
@@ -1002,11 +962,8 @@ static int sym_prepare_setting(struct sym_hcb *np, struct sym_nvram *nvram)
/*
* Let user know about the settings.
*/
- i = nvram->type;
- printf("%s: %s NVRAM, ID %d, Fast-%d, %s, %s\n", sym_name(np),
- i == SYM_SYMBIOS_NVRAM ? "Symbios" :
- (i == SYM_TEKRAM_NVRAM ? "Tekram" : "No"),
- np->myaddr,
+ printf("%s: %s, ID %d, Fast-%d, %s, %s\n", sym_name(np),
+ sym_nvram_type(nvram), np->myaddr,
(np->features & FE_ULTRA3) ? 80 :
(np->features & FE_ULTRA2) ? 40 :
(np->features & FE_ULTRA) ? 20 : 10,
@@ -1055,7 +1012,7 @@ static int sym_prepare_setting(struct sym_hcb *np, struct sym_nvram *nvram)
*
* Has to be called with interrupts disabled.
*/
-#ifndef SYM_CONF_IOMAPPED
+#ifndef CONFIG_SCSI_SYM53C8XX_IOMAPPED
static int sym_regtest (struct sym_hcb *np)
{
register volatile u32 data;
@@ -1065,8 +1022,8 @@ static int sym_regtest (struct sym_hcb *np)
* and try to read it back.
*/
data = 0xffffffff;
- OUTL_OFF(offsetof(struct sym_reg, nc_dstat), data);
- data = INL_OFF(offsetof(struct sym_reg, nc_dstat));
+ OUTL(np, nc_dstat, data);
+ data = INL(np, nc_dstat);
#if 1
if (data == 0xffffffff) {
#else
@@ -1075,7 +1032,7 @@ static int sym_regtest (struct sym_hcb *np)
printf ("CACHE TEST FAILED: reg dstat-sstat2 readback %x.\n",
(unsigned) data);
return (0x10);
- };
+ }
return (0);
}
#endif
@@ -1084,7 +1041,7 @@ static int sym_snooptest (struct sym_hcb *np)
{
u32 sym_rd, sym_wr, sym_bk, host_rd, host_wr, pc, dstat;
int i, err=0;
-#ifndef SYM_CONF_IOMAPPED
+#ifndef CONFIG_SCSI_SYM53C8XX_IOMAPPED
err |= sym_regtest (np);
if (err) return (err);
#endif
@@ -1093,37 +1050,37 @@ restart_test:
* Enable Master Parity Checking as we intend
* to enable it for normal operations.
*/
- OUTB (nc_ctest4, (np->rv_ctest4 & MPEE));
+ OUTB(np, nc_ctest4, (np->rv_ctest4 & MPEE));
/*
* init
*/
- pc = SCRIPTZ_BA (np, snooptest);
+ pc = SCRIPTZ_BA(np, snooptest);
host_wr = 1;
sym_wr = 2;
/*
* Set memory and register.
*/
np->scratch = cpu_to_scr(host_wr);
- OUTL (nc_temp, sym_wr);
+ OUTL(np, nc_temp, sym_wr);
/*
* Start script (exchange values)
*/
- OUTL (nc_dsa, np->hcb_ba);
- OUTL_DSP (pc);
+ OUTL(np, nc_dsa, np->hcb_ba);
+ OUTL_DSP(np, pc);
/*
* Wait 'til done (with timeout)
*/
for (i=0; i<SYM_SNOOP_TIMEOUT; i++)
- if (INB(nc_istat) & (INTF|SIP|DIP))
+ if (INB(np, nc_istat) & (INTF|SIP|DIP))
break;
if (i>=SYM_SNOOP_TIMEOUT) {
printf ("CACHE TEST FAILED: timeout.\n");
return (0x20);
- };
+ }
/*
* Check for fatal DMA errors.
*/
- dstat = INB (nc_dstat);
+ dstat = INB(np, nc_dstat);
#if 1 /* Band aiding for broken hardwares that fail PCI parity */
if ((dstat & MDPE) && (np->rv_ctest4 & MPEE)) {
printf ("%s: PCI DATA PARITY ERROR DETECTED - "
@@ -1140,23 +1097,23 @@ restart_test:
/*
* Save termination position.
*/
- pc = INL (nc_dsp);
+ pc = INL(np, nc_dsp);
/*
* Read memory and register.
*/
host_rd = scr_to_cpu(np->scratch);
- sym_rd = INL (nc_scratcha);
- sym_bk = INL (nc_temp);
+ sym_rd = INL(np, nc_scratcha);
+ sym_bk = INL(np, nc_temp);
/*
* Check termination position.
*/
- if (pc != SCRIPTZ_BA (np, snoopend)+8) {
+ if (pc != SCRIPTZ_BA(np, snoopend)+8) {
printf ("CACHE TEST FAILED: script execution failed.\n");
printf ("start=%08lx, pc=%08lx, end=%08lx\n",
- (u_long) SCRIPTZ_BA (np, snooptest), (u_long) pc,
- (u_long) SCRIPTZ_BA (np, snoopend) +8);
+ (u_long) SCRIPTZ_BA(np, snooptest), (u_long) pc,
+ (u_long) SCRIPTZ_BA(np, snoopend) +8);
return (0x40);
- };
+ }
/*
* Show results.
*/
@@ -1164,17 +1121,17 @@ restart_test:
printf ("CACHE TEST FAILED: host wrote %d, chip read %d.\n",
(int) host_wr, (int) sym_rd);
err |= 1;
- };
+ }
if (host_rd != sym_wr) {
printf ("CACHE TEST FAILED: chip wrote %d, host read %d.\n",
(int) sym_wr, (int) host_rd);
err |= 2;
- };
+ }
if (sym_bk != sym_wr) {
printf ("CACHE TEST FAILED: chip wrote %d, read back %d.\n",
(int) sym_wr, (int) sym_bk);
err |= 4;
- };
+ }
return (err);
}
@@ -1215,7 +1172,7 @@ static void sym_log_hard_error(struct sym_hcb *np, u_short sist, u_char dstat)
u_char *script_base;
int i;
- dsp = INL (nc_dsp);
+ dsp = INL(np, nc_dsp);
if (dsp > np->scripta_ba &&
dsp <= np->scripta_ba + np->scripta_sz) {
@@ -1238,12 +1195,12 @@ static void sym_log_hard_error(struct sym_hcb *np, u_short sist, u_char dstat)
}
printf ("%s:%d: ERROR (%x:%x) (%x-%x-%x) (%x/%x/%x) @ (%s %x:%08x).\n",
- sym_name (np), (unsigned)INB (nc_sdid)&0x0f, dstat, sist,
- (unsigned)INB (nc_socl), (unsigned)INB (nc_sbcl),
- (unsigned)INB (nc_sbdl), (unsigned)INB (nc_sxfer),
- (unsigned)INB (nc_scntl3),
- (np->features & FE_C10) ? (unsigned)INB (nc_scntl4) : 0,
- script_name, script_ofs, (unsigned)INL (nc_dbc));
+ sym_name(np), (unsigned)INB(np, nc_sdid)&0x0f, dstat, sist,
+ (unsigned)INB(np, nc_socl), (unsigned)INB(np, nc_sbcl),
+ (unsigned)INB(np, nc_sbdl), (unsigned)INB(np, nc_sxfer),
+ (unsigned)INB(np, nc_scntl3),
+ (np->features & FE_C10) ? (unsigned)INB(np, nc_scntl4) : 0,
+ script_name, script_ofs, (unsigned)INL(np, nc_dbc));
if (((script_ofs & 3) == 0) &&
(unsigned)script_ofs < script_size) {
@@ -1253,7 +1210,7 @@ static void sym_log_hard_error(struct sym_hcb *np, u_short sist, u_char dstat)
printf ("%s: regdump:", sym_name(np));
for (i=0; i<24;i++)
- printf (" %02x", (unsigned)INB_OFF(i));
+ printf (" %02x", (unsigned)INB_OFF(np, i));
printf (".\n");
/*
@@ -1263,7 +1220,7 @@ static void sym_log_hard_error(struct sym_hcb *np, u_short sist, u_char dstat)
sym_log_bus_error(np);
}
-static struct sym_pci_chip sym_pci_dev_table[] = {
+static struct sym_chip sym_dev_table[] = {
{PCI_DEVICE_ID_NCR_53C810, 0x0f, "810", 4, 8, 4, 64,
FE_ERL}
,
@@ -1347,8 +1304,8 @@ static struct sym_pci_chip sym_pci_dev_table[] = {
FE_RAM|FE_IO256|FE_LEDC}
};
-#define sym_pci_num_devs \
- (sizeof(sym_pci_dev_table) / sizeof(sym_pci_dev_table[0]))
+#define sym_num_devs \
+ (sizeof(sym_dev_table) / sizeof(sym_dev_table[0]))
/*
* Look up the chip table.
@@ -1356,14 +1313,14 @@ static struct sym_pci_chip sym_pci_dev_table[] = {
* Return a pointer to the chip entry if found,
* zero otherwise.
*/
-struct sym_pci_chip *
-sym_lookup_pci_chip_table (u_short device_id, u_char revision)
+struct sym_chip *
+sym_lookup_chip_table (u_short device_id, u_char revision)
{
- struct sym_pci_chip *chip;
+ struct sym_chip *chip;
int i;
- for (i = 0; i < sym_pci_num_devs; i++) {
- chip = &sym_pci_dev_table[i];
+ for (i = 0; i < sym_num_devs; i++) {
+ chip = &sym_dev_table[i];
if (device_id != chip->device_id)
continue;
if (revision > chip->revision_id)
@@ -1421,7 +1378,7 @@ static void sym_update_dmap_regs(struct sym_hcb *np)
return;
o = offsetof(struct sym_reg, nc_scrx[0]);
for (i = 0; i < SYM_DMAP_SIZE; i++) {
- OUTL_OFF(o, np->dmap_bah[i]);
+ OUTL_OFF(np, o, np->dmap_bah[i]);
o += 4;
}
np->dmap_dirty = 0;
@@ -1429,52 +1386,52 @@ static void sym_update_dmap_regs(struct sym_hcb *np)
#endif
/* Enforce all the fiddly SPI rules and the chip limitations */
-static void sym_check_goals(struct scsi_device *sdev)
+static void sym_check_goals(struct sym_hcb *np, struct scsi_target *starget,
+ struct sym_trans *goal)
{
- struct sym_hcb *np = ((struct host_data *)sdev->host->hostdata)->ncb;
- struct sym_trans *st = &np->target[sdev->id].tinfo.goal;
-
- if (!scsi_device_wide(sdev))
- st->width = 0;
-
- if (!scsi_device_sync(sdev)) {
- st->options = 0;
- st->period = 0;
- st->offset = 0;
+ if (!spi_support_wide(starget))
+ goal->width = 0;
+
+ if (!spi_support_sync(starget)) {
+ goal->iu = 0;
+ goal->dt = 0;
+ goal->qas = 0;
+ goal->period = 0;
+ goal->offset = 0;
return;
}
- if (scsi_device_dt(sdev)) {
- if (scsi_device_dt_only(sdev))
- st->options |= PPR_OPT_DT;
+ if (spi_support_dt(starget)) {
+ if (spi_support_dt_only(starget))
+ goal->dt = 1;
- if (st->offset == 0)
- st->options &= ~PPR_OPT_DT;
+ if (goal->offset == 0)
+ goal->dt = 0;
} else {
- st->options &= ~PPR_OPT_DT;
+ goal->dt = 0;
}
/* Some targets fail to properly negotiate DT in SE mode */
if ((np->scsi_mode != SMODE_LVD) || !(np->features & FE_U3EN))
- st->options &= ~PPR_OPT_DT;
+ goal->dt = 0;
- if (st->options & PPR_OPT_DT) {
+ if (goal->dt) {
/* all DT transfers must be wide */
- st->width = 1;
- if (st->offset > np->maxoffs_dt)
- st->offset = np->maxoffs_dt;
- if (st->period < np->minsync_dt)
- st->period = np->minsync_dt;
- if (st->period > np->maxsync_dt)
- st->period = np->maxsync_dt;
+ goal->width = 1;
+ if (goal->offset > np->maxoffs_dt)
+ goal->offset = np->maxoffs_dt;
+ if (goal->period < np->minsync_dt)
+ goal->period = np->minsync_dt;
+ if (goal->period > np->maxsync_dt)
+ goal->period = np->maxsync_dt;
} else {
- st->options &= ~PPR_OPT_MASK;
- if (st->offset > np->maxoffs)
- st->offset = np->maxoffs;
- if (st->period < np->minsync)
- st->period = np->minsync;
- if (st->period > np->maxsync)
- st->period = np->maxsync;
+ goal->iu = goal->qas = 0;
+ if (goal->offset > np->maxoffs)
+ goal->offset = np->maxoffs;
+ if (goal->period < np->minsync)
+ goal->period = np->minsync;
+ if (goal->period > np->maxsync)
+ goal->period = np->maxsync;
}
}
@@ -1485,30 +1442,29 @@ static void sym_check_goals(struct scsi_device *sdev)
* negotiation and the nego_status field of the CCB.
* Returns the size of the message in bytes.
*/
-static int sym_prepare_nego(struct sym_hcb *np, ccb_p cp, u_char *msgptr)
+static int sym_prepare_nego(struct sym_hcb *np, struct sym_ccb *cp, u_char *msgptr)
{
- tcb_p tp = &np->target[cp->target];
- struct scsi_device *sdev = tp->sdev;
- struct sym_trans *goal = &tp->tinfo.goal;
- struct sym_trans *curr = &tp->tinfo.curr;
+ struct sym_tcb *tp = &np->target[cp->target];
+ struct scsi_target *starget = tp->sdev->sdev_target;
+ struct sym_trans *goal = &tp->tgoal;
int msglen = 0;
int nego;
- if (likely(sdev))
- sym_check_goals(sdev);
+ sym_check_goals(np, starget, goal);
/*
* Many devices implement PPR in a buggy way, so only use it if we
* really want to.
*/
- if ((goal->options & PPR_OPT_MASK) || (goal->period < 0xa)) {
+ if (goal->iu || goal->dt || goal->qas || (goal->period < 0xa)) {
nego = NS_PPR;
- } else if (curr->width != goal->width) {
+ } else if (spi_width(starget) != goal->width) {
nego = NS_WIDE;
- } else if (curr->period != goal->period ||
- curr->offset != goal->offset) {
+ } else if (spi_period(starget) != goal->period ||
+ spi_offset(starget) != goal->offset) {
nego = NS_SYNC;
} else {
+ goal->check_nego = 0;
nego = 0;
}
@@ -1534,9 +1490,11 @@ static int sym_prepare_nego(struct sym_hcb *np, ccb_p cp, u_char *msgptr)
msgptr[msglen++] = 0;
msgptr[msglen++] = goal->offset;
msgptr[msglen++] = goal->width;
- msgptr[msglen++] = goal->options & PPR_OPT_MASK;
+ msgptr[msglen++] = (goal->iu ? PPR_OPT_IU : 0) |
+ (goal->dt ? PPR_OPT_DT : 0) |
+ (goal->qas ? PPR_OPT_QAS : 0);
break;
- };
+ }
cp->nego_status = nego;
@@ -1547,8 +1505,8 @@ static int sym_prepare_nego(struct sym_hcb *np, ccb_p cp, u_char *msgptr)
nego == NS_SYNC ? "sync msgout" :
nego == NS_WIDE ? "wide msgout" :
"ppr msgout", msgptr);
- };
- };
+ }
+ }
return msglen;
}
@@ -1556,7 +1514,7 @@ static int sym_prepare_nego(struct sym_hcb *np, ccb_p cp, u_char *msgptr)
/*
* Insert a job into the start queue.
*/
-void sym_put_start_queue(struct sym_hcb *np, ccb_p cp)
+void sym_put_start_queue(struct sym_hcb *np, struct sym_ccb *cp)
{
u_short qidx;
@@ -1608,17 +1566,17 @@ void sym_put_start_queue(struct sym_hcb *np, ccb_p cp)
* Wake it up.
*/
MEMORY_WRITE_BARRIER();
- OUTB (nc_istat, SIGP|np->istat_sem);
+ OUTB(np, nc_istat, SIGP|np->istat_sem);
}
#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
/*
* Start next ready-to-start CCBs.
*/
-void sym_start_next_ccbs(struct sym_hcb *np, lcb_p lp, int maxn)
+void sym_start_next_ccbs(struct sym_hcb *np, struct sym_lcb *lp, int maxn)
{
SYM_QUEHEAD *qp;
- ccb_p cp;
+ struct sym_ccb *cp;
/*
* Paranoia, as usual. :-)
@@ -1643,7 +1601,7 @@ void sym_start_next_ccbs(struct sym_hcb *np, lcb_p lp, int maxn)
}
lp->itlq_tbl[cp->tag] = cpu_to_scr(cp->ccb_ba);
lp->head.resel_sa =
- cpu_to_scr(SCRIPTA_BA (np, resel_tag));
+ cpu_to_scr(SCRIPTA_BA(np, resel_tag));
++lp->started_tags;
} else {
if (lp->started_no_tag || lp->started_tags) {
@@ -1652,7 +1610,7 @@ void sym_start_next_ccbs(struct sym_hcb *np, lcb_p lp, int maxn)
}
lp->head.itl_task_sa = cpu_to_scr(cp->ccb_ba);
lp->head.resel_sa =
- cpu_to_scr(SCRIPTA_BA (np, resel_no_tag));
+ cpu_to_scr(SCRIPTA_BA(np, resel_no_tag));
++lp->started_no_tag;
}
cp->started = 1;
@@ -1671,7 +1629,7 @@ void sym_start_next_ccbs(struct sym_hcb *np, lcb_p lp, int maxn)
*/
static int sym_wakeup_done (struct sym_hcb *np)
{
- ccb_p cp;
+ struct sym_ccb *cp;
int i, n;
u32 dsa;
@@ -1719,22 +1677,22 @@ static int sym_wakeup_done (struct sym_hcb *np)
static void sym_flush_comp_queue(struct sym_hcb *np, int cam_status)
{
SYM_QUEHEAD *qp;
- ccb_p cp;
+ struct sym_ccb *cp;
while ((qp = sym_remque_head(&np->comp_ccbq)) != 0) {
- struct scsi_cmnd *ccb;
+ struct scsi_cmnd *cmd;
cp = sym_que_entry(qp, struct sym_ccb, link_ccbq);
sym_insque_tail(&cp->link_ccbq, &np->busy_ccbq);
/* Leave quiet CCBs waiting for resources */
if (cp->host_status == HS_WAIT)
continue;
- ccb = cp->cam_ccb;
+ cmd = cp->cmd;
if (cam_status)
- sym_set_cam_status(ccb, cam_status);
+ sym_set_cam_status(cmd, cam_status);
#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
- if (sym_get_cam_status(ccb) == CAM_REQUEUE_REQ) {
- tcb_p tp = &np->target[cp->target];
- lcb_p lp = sym_lp(np, tp, cp->lun);
+ if (sym_get_cam_status(cmd) == CAM_REQUEUE_REQ) {
+ struct sym_tcb *tp = &np->target[cp->target];
+ struct sym_lcb *lp = sym_lp(tp, cp->lun);
if (lp) {
sym_remque(&cp->link2_ccbq);
sym_insque_tail(&cp->link2_ccbq,
@@ -1751,8 +1709,7 @@ static void sym_flush_comp_queue(struct sym_hcb *np, int cam_status)
}
#endif
sym_free_ccb(np, cp);
- sym_freeze_cam_ccb(ccb);
- sym_xpt_done(np, ccb);
+ sym_xpt_done(np, cmd);
}
}
@@ -1790,8 +1747,8 @@ void sym_start_up (struct sym_hcb *np, int reason)
if (reason == 1)
sym_soft_reset(np);
else {
- OUTB (nc_stest3, TE|CSF);
- OUTONB (nc_ctest3, CLF);
+ OUTB(np, nc_stest3, TE|CSF);
+ OUTONB(np, nc_ctest3, CLF);
}
/*
@@ -1839,39 +1796,39 @@ void sym_start_up (struct sym_hcb *np, int reason)
/*
* Init chip.
*/
- OUTB (nc_istat, 0x00 ); /* Remove Reset, abort */
- UDELAY (2000); /* The 895 needs time for the bus mode to settle */
+ OUTB(np, nc_istat, 0x00); /* Remove Reset, abort */
+ udelay(2000); /* The 895 needs time for the bus mode to settle */
- OUTB (nc_scntl0, np->rv_scntl0 | 0xc0);
+ OUTB(np, nc_scntl0, np->rv_scntl0 | 0xc0);
/* full arb., ena parity, par->ATN */
- OUTB (nc_scntl1, 0x00); /* odd parity, and remove CRST!! */
+ OUTB(np, nc_scntl1, 0x00); /* odd parity, and remove CRST!! */
sym_selectclock(np, np->rv_scntl3); /* Select SCSI clock */
- OUTB (nc_scid , RRE|np->myaddr); /* Adapter SCSI address */
- OUTW (nc_respid, 1ul<<np->myaddr); /* Id to respond to */
- OUTB (nc_istat , SIGP ); /* Signal Process */
- OUTB (nc_dmode , np->rv_dmode); /* Burst length, dma mode */
- OUTB (nc_ctest5, np->rv_ctest5); /* Large fifo + large burst */
+ OUTB(np, nc_scid , RRE|np->myaddr); /* Adapter SCSI address */
+ OUTW(np, nc_respid, 1ul<<np->myaddr); /* Id to respond to */
+ OUTB(np, nc_istat , SIGP ); /* Signal Process */
+ OUTB(np, nc_dmode , np->rv_dmode); /* Burst length, dma mode */
+ OUTB(np, nc_ctest5, np->rv_ctest5); /* Large fifo + large burst */
- OUTB (nc_dcntl , NOCOM|np->rv_dcntl); /* Protect SFBR */
- OUTB (nc_ctest3, np->rv_ctest3); /* Write and invalidate */
- OUTB (nc_ctest4, np->rv_ctest4); /* Master parity checking */
+ OUTB(np, nc_dcntl , NOCOM|np->rv_dcntl); /* Protect SFBR */
+ OUTB(np, nc_ctest3, np->rv_ctest3); /* Write and invalidate */
+ OUTB(np, nc_ctest4, np->rv_ctest4); /* Master parity checking */
/* Extended Sreq/Sack filtering not supported on the C10 */
if (np->features & FE_C10)
- OUTB (nc_stest2, np->rv_stest2);
+ OUTB(np, nc_stest2, np->rv_stest2);
else
- OUTB (nc_stest2, EXT|np->rv_stest2);
+ OUTB(np, nc_stest2, EXT|np->rv_stest2);
- OUTB (nc_stest3, TE); /* TolerANT enable */
- OUTB (nc_stime0, 0x0c); /* HTH disabled STO 0.25 sec */
+ OUTB(np, nc_stest3, TE); /* TolerANT enable */
+ OUTB(np, nc_stime0, 0x0c); /* HTH disabled STO 0.25 sec */
/*
* For now, disable AIP generation on C1010-66.
*/
if (np->device_id == PCI_DEVICE_ID_LSI_53C1010_66)
- OUTB (nc_aipcntl1, DISAIP);
+ OUTB(np, nc_aipcntl1, DISAIP);
/*
* C10101 rev. 0 errata.
@@ -1882,7 +1839,7 @@ void sym_start_up (struct sym_hcb *np, int reason)
*/
if (np->device_id == PCI_DEVICE_ID_LSI_53C1010_33 &&
np->revision_id < 1)
- OUTB (nc_stest1, INB(nc_stest1) | 0x30);
+ OUTB(np, nc_stest1, INB(np, nc_stest1) | 0x30);
/*
* DEL 441 - 53C876 Rev 5 - Part Number 609-0392787/2788 - ITEM 2.
@@ -1890,7 +1847,7 @@ void sym_start_up (struct sym_hcb *np, int reason)
* regardless revision id (kind of post-chip-design feature. ;-))
*/
if (np->device_id == PCI_DEVICE_ID_NCR_53C875)
- OUTB (nc_ctest0, (1<<5));
+ OUTB(np, nc_ctest0, (1<<5));
else if (np->device_id == PCI_DEVICE_ID_NCR_53C896)
np->rv_ccntl0 |= DPR;
@@ -1900,8 +1857,8 @@ void sym_start_up (struct sym_hcb *np, int reason)
* seem to support those IO registers.
*/
if (np->features & (FE_DAC|FE_NOPM)) {
- OUTB (nc_ccntl0, np->rv_ccntl0);
- OUTB (nc_ccntl1, np->rv_ccntl1);
+ OUTB(np, nc_ccntl0, np->rv_ccntl0);
+ OUTB(np, nc_ccntl1, np->rv_ccntl1);
}
#if SYM_CONF_DMA_ADDRESSING_MODE == 2
@@ -1911,8 +1868,8 @@ void sym_start_up (struct sym_hcb *np, int reason)
*/
if (np->use_dac) {
np->dmap_bah[0] = 0; /* ??? */
- OUTL (nc_scrx[0], np->dmap_bah[0]);
- OUTL (nc_drs, np->dmap_bah[0]);
+ OUTL(np, nc_scrx[0], np->dmap_bah[0]);
+ OUTL(np, nc_drs, np->dmap_bah[0]);
}
#endif
@@ -1921,8 +1878,8 @@ void sym_start_up (struct sym_hcb *np, int reason)
* set PM jump addresses.
*/
if (np->features & FE_NOPM) {
- OUTL (nc_pmjad1, SCRIPTB_BA (np, pm_handle));
- OUTL (nc_pmjad2, SCRIPTB_BA (np, pm_handle));
+ OUTL(np, nc_pmjad1, SCRIPTB_BA(np, pm_handle));
+ OUTL(np, nc_pmjad2, SCRIPTB_BA(np, pm_handle));
}
/*
@@ -1930,15 +1887,15 @@ void sym_start_up (struct sym_hcb *np, int reason)
* Also set GPIO5 and clear GPIO6 if hardware LED control.
*/
if (np->features & FE_LED0)
- OUTB(nc_gpcntl, INB(nc_gpcntl) & ~0x01);
+ OUTB(np, nc_gpcntl, INB(np, nc_gpcntl) & ~0x01);
else if (np->features & FE_LEDC)
- OUTB(nc_gpcntl, (INB(nc_gpcntl) & ~0x41) | 0x20);
+ OUTB(np, nc_gpcntl, (INB(np, nc_gpcntl) & ~0x41) | 0x20);
/*
* enable ints
*/
- OUTW (nc_sien , STO|HTH|MA|SGE|UDC|RST|PAR);
- OUTB (nc_dien , MDPE|BF|SSI|SIR|IID);
+ OUTW(np, nc_sien , STO|HTH|MA|SGE|UDC|RST|PAR);
+ OUTB(np, nc_dien , MDPE|BF|SSI|SIR|IID);
/*
* For 895/6 enable SBMC interrupt and save current SCSI bus mode.
@@ -1946,12 +1903,12 @@ void sym_start_up (struct sym_hcb *np, int reason)
* we reset the chip but not the SCSI BUS (at initialization).
*/
if (np->features & (FE_ULTRA2|FE_ULTRA3)) {
- OUTONW (nc_sien, SBMC);
+ OUTONW(np, nc_sien, SBMC);
if (reason == 0) {
mdelay(100);
- INW (nc_sist);
+ INW(np, nc_sist);
}
- np->scsi_mode = INB (nc_stest4) & SMODE;
+ np->scsi_mode = INB(np, nc_stest4) & SMODE;
}
/*
@@ -1961,17 +1918,12 @@ void sym_start_up (struct sym_hcb *np, int reason)
* Prepare sync negotiation according to actual SCSI bus mode.
*/
for (i=0;i<SYM_CONF_MAX_TARGET;i++) {
- tcb_p tp = &np->target[i];
+ struct sym_tcb *tp = &np->target[i];
tp->to_reset = 0;
tp->head.sval = 0;
tp->head.wval = np->rv_scntl3;
tp->head.uval = 0;
-
- tp->tinfo.curr.period = 0;
- tp->tinfo.curr.offset = 0;
- tp->tinfo.curr.width = BUS_8_BIT;
- tp->tinfo.curr.options = 0;
}
/*
@@ -1981,29 +1933,25 @@ void sym_start_up (struct sym_hcb *np, int reason)
* For platforms that may not support PCI memory mapping,
* we use simple SCRIPTS that performs MEMORY MOVEs.
*/
+ phys = SCRIPTA_BA(np, init);
if (np->ram_ba) {
if (sym_verbose >= 2)
- printf ("%s: Downloading SCSI SCRIPTS.\n",
- sym_name(np));
+ printf("%s: Downloading SCSI SCRIPTS.\n", sym_name(np));
+ memcpy_toio(np->s.ramaddr, np->scripta0, np->scripta_sz);
if (np->ram_ws == 8192) {
- OUTRAM_OFF(4096, np->scriptb0, np->scriptb_sz);
- phys = scr_to_cpu(np->scr_ram_seg);
- OUTL (nc_mmws, phys);
- OUTL (nc_mmrs, phys);
- OUTL (nc_sfs, phys);
- phys = SCRIPTB_BA (np, start64);
+ memcpy_toio(np->s.ramaddr + 4096, np->scriptb0, np->scriptb_sz);
+ phys = scr_to_cpu(np->scr_ram_seg);
+ OUTL(np, nc_mmws, phys);
+ OUTL(np, nc_mmrs, phys);
+ OUTL(np, nc_sfs, phys);
+ phys = SCRIPTB_BA(np, start64);
}
- else
- phys = SCRIPTA_BA (np, init);
- OUTRAM_OFF(0, np->scripta0, np->scripta_sz);
}
- else
- phys = SCRIPTA_BA (np, init);
np->istat_sem = 0;
- OUTL (nc_dsa, np->hcb_ba);
- OUTL_DSP (phys);
+ OUTL(np, nc_dsa, np->hcb_ba);
+ OUTL_DSP(np, phys);
/*
* Notify the XPT about the RESET condition.
@@ -2013,16 +1961,16 @@ void sym_start_up (struct sym_hcb *np, int reason)
}
/*
- * Switch trans mode for current job and it's target.
+ * Switch trans mode for current job and its target.
*/
static void sym_settrans(struct sym_hcb *np, int target, u_char opts, u_char ofs,
u_char per, u_char wide, u_char div, u_char fak)
{
SYM_QUEHEAD *qp;
u_char sval, wval, uval;
- tcb_p tp = &np->target[target];
+ struct sym_tcb *tp = &np->target[target];
- assert(target == (INB (nc_sdid) & 0x0f));
+ assert(target == (INB(np, nc_sdid) & 0x0f));
sval = tp->head.sval;
wval = tp->head.wval;
@@ -2070,8 +2018,7 @@ static void sym_settrans(struct sym_hcb *np, int target, u_char opts, u_char ofs
assert(np->features & FE_U3EN);
uval |= U3EN;
}
- }
- else {
+ } else {
wval = wval & ~ULTRA;
if (per <= 12) wval |= ULTRA;
}
@@ -2092,23 +2039,23 @@ static void sym_settrans(struct sym_hcb *np, int target, u_char opts, u_char ofs
* Not supported on the C1010.
*/
if (per < 50 && !(np->features & FE_C10))
- OUTOFFB (nc_stest2, EXT);
+ OUTOFFB(np, nc_stest2, EXT);
/*
* set actual value and sync_status
*/
- OUTB (nc_sxfer, tp->head.sval);
- OUTB (nc_scntl3, tp->head.wval);
+ OUTB(np, nc_sxfer, tp->head.sval);
+ OUTB(np, nc_scntl3, tp->head.wval);
if (np->features & FE_C10) {
- OUTB (nc_scntl4, tp->head.uval);
+ OUTB(np, nc_scntl4, tp->head.uval);
}
/*
* patch ALL busy ccbs of this target.
*/
FOR_EACH_QUEUED_ELEMENT(&np->busy_ccbq, qp) {
- ccb_p cp;
+ struct sym_ccb *cp;
cp = sym_que_entry(qp, struct sym_ccb, link_ccbq);
if (cp->target != target)
continue;
@@ -2126,16 +2073,24 @@ static void sym_settrans(struct sym_hcb *np, int target, u_char opts, u_char ofs
*/
static void sym_setwide(struct sym_hcb *np, int target, u_char wide)
{
- tcb_p tp = &np->target[target];
+ struct sym_tcb *tp = &np->target[target];
+ struct scsi_target *starget = tp->sdev->sdev_target;
+
+ if (spi_width(starget) == wide)
+ return;
sym_settrans(np, target, 0, 0, 0, wide, 0, 0);
- tp->tinfo.goal.width = tp->tinfo.curr.width = wide;
- tp->tinfo.curr.offset = 0;
- tp->tinfo.curr.period = 0;
- tp->tinfo.curr.options = 0;
+ tp->tgoal.width = wide;
+ spi_offset(starget) = 0;
+ spi_period(starget) = 0;
+ spi_width(starget) = wide;
+ spi_iu(starget) = 0;
+ spi_dt(starget) = 0;
+ spi_qas(starget) = 0;
- sym_xpt_async_nego_wide(np, target);
+ if (sym_verbose >= 3)
+ spi_display_xfer_agreement(starget);
}
/*
@@ -2146,22 +2101,23 @@ static void
sym_setsync(struct sym_hcb *np, int target,
u_char ofs, u_char per, u_char div, u_char fak)
{
- tcb_p tp = &np->target[target];
+ struct sym_tcb *tp = &np->target[target];
+ struct scsi_target *starget = tp->sdev->sdev_target;
u_char wide = (tp->head.wval & EWS) ? BUS_16_BIT : BUS_8_BIT;
sym_settrans(np, target, 0, ofs, per, wide, div, fak);
- tp->tinfo.curr.period = per;
- tp->tinfo.curr.offset = ofs;
- tp->tinfo.curr.options = 0;
+ spi_period(starget) = per;
+ spi_offset(starget) = ofs;
+ spi_iu(starget) = spi_dt(starget) = spi_qas(starget) = 0;
- if (!(tp->tinfo.goal.options & PPR_OPT_MASK)) {
- tp->tinfo.goal.period = per;
- tp->tinfo.goal.offset = ofs;
- tp->tinfo.goal.options = 0;
+ if (!tp->tgoal.dt && !tp->tgoal.iu && !tp->tgoal.qas) {
+ tp->tgoal.period = per;
+ tp->tgoal.offset = ofs;
+ tp->tgoal.check_nego = 0;
}
- sym_xpt_async_nego_sync(np, target);
+ spi_display_xfer_agreement(starget);
}
/*
@@ -2172,16 +2128,20 @@ static void
sym_setpprot(struct sym_hcb *np, int target, u_char opts, u_char ofs,
u_char per, u_char wide, u_char div, u_char fak)
{
- tcb_p tp = &np->target[target];
+ struct sym_tcb *tp = &np->target[target];
+ struct scsi_target *starget = tp->sdev->sdev_target;
sym_settrans(np, target, opts, ofs, per, wide, div, fak);
- tp->tinfo.goal.width = tp->tinfo.curr.width = wide;
- tp->tinfo.goal.period = tp->tinfo.curr.period = per;
- tp->tinfo.goal.offset = tp->tinfo.curr.offset = ofs;
- tp->tinfo.goal.options = tp->tinfo.curr.options = opts;
+ spi_width(starget) = tp->tgoal.width = wide;
+ spi_period(starget) = tp->tgoal.period = per;
+ spi_offset(starget) = tp->tgoal.offset = ofs;
+ spi_iu(starget) = tp->tgoal.iu = !!(opts & PPR_OPT_IU);
+ spi_dt(starget) = tp->tgoal.dt = !!(opts & PPR_OPT_DT);
+ spi_qas(starget) = tp->tgoal.qas = !!(opts & PPR_OPT_QAS);
+ tp->tgoal.check_nego = 0;
- sym_xpt_async_nego_ppr(np, target);
+ spi_display_xfer_agreement(starget);
}
/*
@@ -2212,25 +2172,25 @@ sym_setpprot(struct sym_hcb *np, int target, u_char opts, u_char ofs,
*/
static void sym_recover_scsi_int (struct sym_hcb *np, u_char hsts)
{
- u32 dsp = INL (nc_dsp);
- u32 dsa = INL (nc_dsa);
- ccb_p cp = sym_ccb_from_dsa(np, dsa);
+ u32 dsp = INL(np, nc_dsp);
+ u32 dsa = INL(np, nc_dsa);
+ struct sym_ccb *cp = sym_ccb_from_dsa(np, dsa);
/*
* If we haven't been interrupted inside the SCRIPTS
* critical pathes, we can safely restart the SCRIPTS
* and trust the DSA value if it matches a CCB.
*/
- if ((!(dsp > SCRIPTA_BA (np, getjob_begin) &&
- dsp < SCRIPTA_BA (np, getjob_end) + 1)) &&
- (!(dsp > SCRIPTA_BA (np, ungetjob) &&
- dsp < SCRIPTA_BA (np, reselect) + 1)) &&
- (!(dsp > SCRIPTB_BA (np, sel_for_abort) &&
- dsp < SCRIPTB_BA (np, sel_for_abort_1) + 1)) &&
- (!(dsp > SCRIPTA_BA (np, done) &&
- dsp < SCRIPTA_BA (np, done_end) + 1))) {
- OUTB (nc_ctest3, np->rv_ctest3 | CLF); /* clear dma fifo */
- OUTB (nc_stest3, TE|CSF); /* clear scsi fifo */
+ if ((!(dsp > SCRIPTA_BA(np, getjob_begin) &&
+ dsp < SCRIPTA_BA(np, getjob_end) + 1)) &&
+ (!(dsp > SCRIPTA_BA(np, ungetjob) &&
+ dsp < SCRIPTA_BA(np, reselect) + 1)) &&
+ (!(dsp > SCRIPTB_BA(np, sel_for_abort) &&
+ dsp < SCRIPTB_BA(np, sel_for_abort_1) + 1)) &&
+ (!(dsp > SCRIPTA_BA(np, done) &&
+ dsp < SCRIPTA_BA(np, done_end) + 1))) {
+ OUTB(np, nc_ctest3, np->rv_ctest3 | CLF); /* clear dma fifo */
+ OUTB(np, nc_stest3, TE|CSF); /* clear scsi fifo */
/*
* If we have a CCB, let the SCRIPTS call us back for
* the handling of the error with SCRATCHA filled with
@@ -2239,14 +2199,14 @@ static void sym_recover_scsi_int (struct sym_hcb *np, u_char hsts)
*/
if (cp) {
cp->host_status = hsts;
- OUTL_DSP (SCRIPTA_BA (np, complete_error));
+ OUTL_DSP(np, SCRIPTA_BA(np, complete_error));
}
/*
* Otherwise just restart the SCRIPTS.
*/
else {
- OUTL (nc_dsa, 0xffffff);
- OUTL_DSP (SCRIPTA_BA (np, start));
+ OUTL(np, nc_dsa, 0xffffff);
+ OUTL_DSP(np, SCRIPTA_BA(np, start));
}
}
else
@@ -2263,11 +2223,11 @@ reset_all:
*/
static void sym_int_sto (struct sym_hcb *np)
{
- u32 dsp = INL (nc_dsp);
+ u32 dsp = INL(np, nc_dsp);
if (DEBUG_FLAGS & DEBUG_TINY) printf ("T");
- if (dsp == SCRIPTA_BA (np, wf_sel_done) + 8)
+ if (dsp == SCRIPTA_BA(np, wf_sel_done) + 8)
sym_recover_scsi_int(np, HS_SEL_TIMEOUT);
else
sym_start_reset(np);
@@ -2294,7 +2254,7 @@ static void sym_int_udc (struct sym_hcb *np)
*/
static void sym_int_sbmc (struct sym_hcb *np)
{
- u_char scsi_mode = INB (nc_stest4) & SMODE;
+ u_char scsi_mode = INB(np, nc_stest4) & SMODE;
/*
* Notify user.
@@ -2335,14 +2295,14 @@ static void sym_int_sbmc (struct sym_hcb *np)
*/
static void sym_int_par (struct sym_hcb *np, u_short sist)
{
- u_char hsts = INB (HS_PRT);
- u32 dsp = INL (nc_dsp);
- u32 dbc = INL (nc_dbc);
- u32 dsa = INL (nc_dsa);
- u_char sbcl = INB (nc_sbcl);
+ u_char hsts = INB(np, HS_PRT);
+ u32 dsp = INL(np, nc_dsp);
+ u32 dbc = INL(np, nc_dbc);
+ u32 dsa = INL(np, nc_dsa);
+ u_char sbcl = INB(np, nc_sbcl);
u_char cmd = dbc >> 24;
int phase = cmd & 7;
- ccb_p cp = sym_ccb_from_dsa(np, dsa);
+ struct sym_ccb *cp = sym_ccb_from_dsa(np, dsa);
printf("%s: SCSI parity error detected: SCR1=%d DBC=%x SBCL=%x\n",
sym_name(np), hsts, dbc, sbcl);
@@ -2350,7 +2310,7 @@ static void sym_int_par (struct sym_hcb *np, u_short sist)
/*
* Check that the chip is connected to the SCSI BUS.
*/
- if (!(INB (nc_scntl1) & ISCON)) {
+ if (!(INB(np, nc_scntl1) & ISCON)) {
sym_recover_scsi_int(np, HS_UNEXPECTED);
return;
}
@@ -2372,7 +2332,7 @@ static void sym_int_par (struct sym_hcb *np, u_short sist)
/*
* Keep track of the parity error.
*/
- OUTONB (HF_PRT, HF_EXT_ERR);
+ OUTONB(np, HF_PRT, HF_EXT_ERR);
cp->xerr_status |= XE_PARITY_ERR;
/*
@@ -2389,25 +2349,25 @@ static void sym_int_par (struct sym_hcb *np, u_short sist)
*/
if (phase == 1 || phase == 5) {
/* Phase mismatch handled by SCRIPTS */
- if (dsp == SCRIPTB_BA (np, pm_handle))
- OUTL_DSP (dsp);
+ if (dsp == SCRIPTB_BA(np, pm_handle))
+ OUTL_DSP(np, dsp);
/* Phase mismatch handled by the C code */
else if (sist & MA)
sym_int_ma (np);
/* No phase mismatch occurred */
else {
sym_set_script_dp (np, cp, dsp);
- OUTL_DSP (SCRIPTA_BA (np, dispatch));
+ OUTL_DSP(np, SCRIPTA_BA(np, dispatch));
}
}
else if (phase == 7) /* We definitely cannot handle parity errors */
#if 1 /* in message-in phase due to the relection */
goto reset_all; /* path and various message anticipations. */
#else
- OUTL_DSP (SCRIPTA_BA (np, clrack));
+ OUTL_DSP(np, SCRIPTA_BA(np, clrack));
#endif
else
- OUTL_DSP (SCRIPTA_BA (np, dispatch));
+ OUTL_DSP(np, SCRIPTA_BA(np, dispatch));
return;
reset_all:
@@ -2436,11 +2396,11 @@ static void sym_int_ma (struct sym_hcb *np)
u_char cmd;
u_char hflags, hflags0;
struct sym_pmc *pm;
- ccb_p cp;
+ struct sym_ccb *cp;
- dsp = INL (nc_dsp);
- dbc = INL (nc_dbc);
- dsa = INL (nc_dsa);
+ dsp = INL(np, nc_dsp);
+ dbc = INL(np, nc_dbc);
+ dsa = INL(np, nc_dsa);
cmd = dbc >> 24;
rest = dbc & 0xffffff;
@@ -2461,14 +2421,14 @@ static void sym_int_ma (struct sym_hcb *np)
u_char ss0, ss2;
if (np->features & FE_DFBC)
- delta = INW (nc_dfbc);
+ delta = INW(np, nc_dfbc);
else {
u32 dfifo;
/*
* Read DFIFO, CTEST[4-6] using 1 PCI bus ownership.
*/
- dfifo = INL(nc_dfifo);
+ dfifo = INL(np, nc_dfifo);
/*
* Calculate remaining bytes in DMA fifo.
@@ -2488,29 +2448,29 @@ static void sym_int_ma (struct sym_hcb *np)
* Check the sstat2 register in case of wide transfer.
*/
rest += delta;
- ss0 = INB (nc_sstat0);
+ ss0 = INB(np, nc_sstat0);
if (ss0 & OLF) rest++;
if (!(np->features & FE_C10))
if (ss0 & ORF) rest++;
if (cp && (cp->phys.select.sel_scntl3 & EWS)) {
- ss2 = INB (nc_sstat2);
+ ss2 = INB(np, nc_sstat2);
if (ss2 & OLF1) rest++;
if (!(np->features & FE_C10))
if (ss2 & ORF1) rest++;
- };
+ }
/*
* Clear fifos.
*/
- OUTB (nc_ctest3, np->rv_ctest3 | CLF); /* dma fifo */
- OUTB (nc_stest3, TE|CSF); /* scsi fifo */
+ OUTB(np, nc_ctest3, np->rv_ctest3 | CLF); /* dma fifo */
+ OUTB(np, nc_stest3, TE|CSF); /* scsi fifo */
}
/*
* log the information
*/
if (DEBUG_FLAGS & (DEBUG_TINY|DEBUG_PHASE))
- printf ("P%x%x RL=%d D=%d ", cmd&7, INB(nc_sbcl)&7,
+ printf ("P%x%x RL=%d D=%d ", cmd&7, INB(np, nc_sbcl)&7,
(unsigned) rest, (unsigned) delta);
/*
@@ -2536,7 +2496,7 @@ static void sym_int_ma (struct sym_hcb *np)
if (DEBUG_FLAGS & DEBUG_PHASE) {
printf ("\nCP=%p DSP=%x NXT=%x VDSP=%p CMD=%x ",
cp, (unsigned)dsp, (unsigned)nxtdsp, vdsp, cmd);
- };
+ }
if (!vdsp) {
printf ("%s: interrupted SCRIPT address not found.\n",
@@ -2562,7 +2522,7 @@ static void sym_int_ma (struct sym_hcb *np)
} else {
tblp = (u32 *) 0;
olen = scr_to_cpu(vdsp[0]) & 0xffffff;
- };
+ }
if (DEBUG_FLAGS & DEBUG_PHASE) {
printf ("OCMD=%x\nTBLP=%p OLEN=%x OADR=%x\n",
@@ -2570,7 +2530,7 @@ static void sym_int_ma (struct sym_hcb *np)
tblp,
(unsigned) olen,
(unsigned) oadr);
- };
+ }
/*
* check cmd against assumed interrupted script command.
@@ -2578,23 +2538,23 @@ static void sym_int_ma (struct sym_hcb *np)
* the phase.
*/
if (((cmd & 2) ? cmd : (cmd & ~4)) != (scr_to_cpu(vdsp[0]) >> 24)) {
- PRINT_ADDR(cp);
- printf ("internal error: cmd=%02x != %02x=(vdsp[0] >> 24)\n",
- (unsigned)cmd, (unsigned)scr_to_cpu(vdsp[0]) >> 24);
+ sym_print_addr(cp->cmd,
+ "internal error: cmd=%02x != %02x=(vdsp[0] >> 24)\n",
+ cmd, scr_to_cpu(vdsp[0]) >> 24);
goto reset_all;
- };
+ }
/*
* if old phase not dataphase, leave here.
*/
if (cmd & 2) {
- PRINT_ADDR(cp);
- printf ("phase change %x-%x %d@%08x resid=%d.\n",
- cmd&7, INB(nc_sbcl)&7, (unsigned)olen,
+ sym_print_addr(cp->cmd,
+ "phase change %x-%x %d@%08x resid=%d.\n",
+ cmd&7, INB(np, nc_sbcl)&7, (unsigned)olen,
(unsigned)oadr, (unsigned)rest);
goto unexpected_phase;
- };
+ }
/*
* Choose the correct PM save area.
@@ -2604,7 +2564,7 @@ static void sym_int_ma (struct sym_hcb *np)
* SCRIPTS for the 895A, 896 and 1010 that are able to
* handle PM from the SCRIPTS processor.
*/
- hflags0 = INB (HF_PRT);
+ hflags0 = INB(np, HF_PRT);
hflags = hflags0;
if (hflags & (HF_IN_PM0 | HF_IN_PM1 | HF_DP_SAVED)) {
@@ -2619,16 +2579,16 @@ static void sym_int_ma (struct sym_hcb *np)
if (!(hflags & HF_ACT_PM)) {
pm = &cp->phys.pm0;
- newcmd = SCRIPTA_BA (np, pm0_data);
+ newcmd = SCRIPTA_BA(np, pm0_data);
}
else {
pm = &cp->phys.pm1;
- newcmd = SCRIPTA_BA (np, pm1_data);
+ newcmd = SCRIPTA_BA(np, pm1_data);
}
hflags &= ~(HF_IN_PM0 | HF_IN_PM1 | HF_DP_SAVED);
if (hflags != hflags0)
- OUTB (HF_PRT, hflags);
+ OUTB(np, HF_PRT, hflags);
/*
* fillin the phase mismatch context
@@ -2643,9 +2603,9 @@ static void sym_int_ma (struct sym_hcb *np)
* - compute the SCRIPTS address to restart from,
* - move current data pointer context by one byte.
*/
- nxtdsp = SCRIPTA_BA (np, dispatch);
+ nxtdsp = SCRIPTA_BA(np, dispatch);
if ((cmd & 7) == 1 && cp && (cp->phys.select.sel_scntl3 & EWS) &&
- (INB (nc_scntl2) & WSR)) {
+ (INB(np, nc_scntl2) & WSR)) {
u32 tmp;
/*
@@ -2671,12 +2631,11 @@ static void sym_int_ma (struct sym_hcb *np)
* Prepare the address of SCRIPTS that will
* move the residual byte to memory.
*/
- nxtdsp = SCRIPTB_BA (np, wsr_ma_helper);
+ nxtdsp = SCRIPTB_BA(np, wsr_ma_helper);
}
if (DEBUG_FLAGS & DEBUG_PHASE) {
- PRINT_ADDR(cp);
- printf ("PM %x %x %x / %x %x %x.\n",
+ sym_print_addr(cp->cmd, "PM %x %x %x / %x %x %x.\n",
hflags0, hflags, newcmd,
(unsigned)scr_to_cpu(pm->sg.addr),
(unsigned)scr_to_cpu(pm->sg.size),
@@ -2687,7 +2646,7 @@ static void sym_int_ma (struct sym_hcb *np)
* Restart the SCRIPTS processor.
*/
sym_set_script_dp (np, cp, newcmd);
- OUTL_DSP (nxtdsp);
+ OUTL_DSP(np, nxtdsp);
return;
/*
@@ -2723,11 +2682,11 @@ unexpected_phase:
switch (cmd & 7) {
case 2: /* COMMAND phase */
- nxtdsp = SCRIPTA_BA (np, dispatch);
+ nxtdsp = SCRIPTA_BA(np, dispatch);
break;
#if 0
case 3: /* STATUS phase */
- nxtdsp = SCRIPTA_BA (np, dispatch);
+ nxtdsp = SCRIPTA_BA(np, dispatch);
break;
#endif
case 6: /* MSG OUT phase */
@@ -2737,30 +2696,34 @@ unexpected_phase:
* since we will not be able to handle reselect.
* Otherwise, we just don't care.
*/
- if (dsp == SCRIPTA_BA (np, send_ident)) {
+ if (dsp == SCRIPTA_BA(np, send_ident)) {
if (cp->tag != NO_TAG && olen - rest <= 3) {
cp->host_status = HS_BUSY;
np->msgout[0] = IDENTIFY(0, cp->lun);
- nxtdsp = SCRIPTB_BA (np, ident_break_atn);
+ nxtdsp = SCRIPTB_BA(np, ident_break_atn);
}
else
- nxtdsp = SCRIPTB_BA (np, ident_break);
+ nxtdsp = SCRIPTB_BA(np, ident_break);
}
- else if (dsp == SCRIPTB_BA (np, send_wdtr) ||
- dsp == SCRIPTB_BA (np, send_sdtr) ||
- dsp == SCRIPTB_BA (np, send_ppr)) {
- nxtdsp = SCRIPTB_BA (np, nego_bad_phase);
+ else if (dsp == SCRIPTB_BA(np, send_wdtr) ||
+ dsp == SCRIPTB_BA(np, send_sdtr) ||
+ dsp == SCRIPTB_BA(np, send_ppr)) {
+ nxtdsp = SCRIPTB_BA(np, nego_bad_phase);
+ if (dsp == SCRIPTB_BA(np, send_ppr)) {
+ struct scsi_device *dev = cp->cmd->device;
+ dev->ppr = 0;
+ }
}
break;
#if 0
case 7: /* MSG IN phase */
- nxtdsp = SCRIPTA_BA (np, clrack);
+ nxtdsp = SCRIPTA_BA(np, clrack);
break;
#endif
}
if (nxtdsp) {
- OUTL_DSP (nxtdsp);
+ OUTL_DSP(np, nxtdsp);
return;
}
@@ -2848,20 +2811,20 @@ void sym_interrupt (struct sym_hcb *np)
* Note that SCRIPTS also (dummy) read to memory
* prior to deliver the INTF interrupt condition.
*/
- istat = INB (nc_istat);
+ istat = INB(np, nc_istat);
if (istat & INTF) {
- OUTB (nc_istat, (istat & SIGP) | INTF | np->istat_sem);
- istat = INB (nc_istat); /* DUMMY READ */
+ OUTB(np, nc_istat, (istat & SIGP) | INTF | np->istat_sem);
+ istat = INB(np, nc_istat); /* DUMMY READ */
if (DEBUG_FLAGS & DEBUG_TINY) printf ("F ");
- (void)sym_wakeup_done (np);
- };
+ sym_wakeup_done(np);
+ }
if (!(istat & (SIP|DIP)))
return;
#if 0 /* We should never get this one */
if (istat & CABRT)
- OUTB (nc_istat, CABRT);
+ OUTB(np, nc_istat, CABRT);
#endif
/*
@@ -2879,19 +2842,19 @@ void sym_interrupt (struct sym_hcb *np)
istatc = istat;
do {
if (istatc & SIP)
- sist |= INW (nc_sist);
+ sist |= INW(np, nc_sist);
if (istatc & DIP)
- dstat |= INB (nc_dstat);
- istatc = INB (nc_istat);
+ dstat |= INB(np, nc_dstat);
+ istatc = INB(np, nc_istat);
istat |= istatc;
} while (istatc & (SIP|DIP));
if (DEBUG_FLAGS & DEBUG_TINY)
printf ("<%d|%x:%x|%x:%x>",
- (int)INB(nc_scr0),
+ (int)INB(np, nc_scr0),
dstat,sist,
- (unsigned)INL(nc_dsp),
- (unsigned)INL(nc_dbc));
+ (unsigned)INL(np, nc_dsp),
+ (unsigned)INL(np, nc_dbc));
/*
* On paper, a memory read barrier may be needed here to
* prevent out of order LOADs by the CPU from having
@@ -2918,10 +2881,10 @@ void sym_interrupt (struct sym_hcb *np)
if (sist & PAR) sym_int_par (np, sist);
else if (sist & MA) sym_int_ma (np);
else if (dstat & SIR) sym_int_sir (np);
- else if (dstat & SSI) OUTONB_STD ();
+ else if (dstat & SSI) OUTONB_STD();
else goto unknown_int;
return;
- };
+ }
/*
* Now, interrupts that donnot happen in normal
@@ -2938,10 +2901,10 @@ void sym_interrupt (struct sym_hcb *np)
printf("%s: SCSI BUS reset detected.\n", sym_name(np));
sym_start_up (np, 1);
return;
- };
+ }
- OUTB (nc_ctest3, np->rv_ctest3 | CLF); /* clear dma fifo */
- OUTB (nc_stest3, TE|CSF); /* clear scsi fifo */
+ OUTB(np, nc_ctest3, np->rv_ctest3 | CLF); /* clear dma fifo */
+ OUTB(np, nc_stest3, TE|CSF); /* clear scsi fifo */
if (!(sist & (GEN|HTH|SGE)) &&
!(dstat & (MDPE|BF|ABRT|IID))) {
@@ -2950,7 +2913,7 @@ void sym_interrupt (struct sym_hcb *np)
else if (sist & UDC) sym_int_udc (np);
else goto unknown_int;
return;
- };
+ }
/*
* Now, interrupts we are not able to recover cleanly.
@@ -2965,7 +2928,7 @@ void sym_interrupt (struct sym_hcb *np)
(dstat & (MDPE|BF|ABRT|IID))) {
sym_start_reset(np);
return;
- };
+ }
unknown_int:
/*
@@ -2989,7 +2952,7 @@ static int
sym_dequeue_from_squeue(struct sym_hcb *np, int i, int target, int lun, int task)
{
int j;
- ccb_p cp;
+ struct sym_ccb *cp;
/*
* Make sure the starting index is within range.
@@ -3011,7 +2974,7 @@ sym_dequeue_from_squeue(struct sym_hcb *np, int i, int target, int lun, int task
if ((target == -1 || cp->target == target) &&
(lun == -1 || cp->lun == lun) &&
(task == -1 || cp->tag == task)) {
- sym_set_cam_status(cp->cam_ccb, CAM_REQUEUE_REQ);
+ sym_set_cam_status(cp->cmd, CAM_REQUEUE_REQ);
sym_remque(&cp->link_ccbq);
sym_insque_tail(&cp->link_ccbq, &np->comp_ccbq);
}
@@ -3047,9 +3010,8 @@ sym_dequeue_from_squeue(struct sym_hcb *np, int i, int target, int lun, int task
* SCRATCHA is assumed to have been loaded with STARTPOS
* before the SCRIPTS called the C code.
*/
-static void sym_sir_bad_scsi_status(struct sym_hcb *np, int num, ccb_p cp)
+static void sym_sir_bad_scsi_status(struct sym_hcb *np, int num, struct sym_ccb *cp)
{
- tcb_p tp = &np->target[cp->target];
u32 startp;
u_char s_status = cp->ssss_status;
u_char h_flags = cp->host_flags;
@@ -3059,7 +3021,7 @@ static void sym_sir_bad_scsi_status(struct sym_hcb *np, int num, ccb_p cp)
/*
* Compute the index of the next job to start from SCRIPTS.
*/
- i = (INL (nc_scratcha) - np->squeue_ba) / 4;
+ i = (INL(np, nc_scratcha) - np->squeue_ba) / 4;
/*
* The last CCB queued used for IARB hint may be
@@ -3077,8 +3039,7 @@ static void sym_sir_bad_scsi_status(struct sym_hcb *np, int num, ccb_p cp)
case S_BUSY:
case S_QUEUE_FULL:
if (sym_verbose >= 2) {
- PRINT_ADDR(cp);
- printf ("%s\n",
+ sym_print_addr(cp->cmd, "%s\n",
s_status == S_BUSY ? "BUSY" : "QUEUE FULL\n");
}
default: /* S_INT, S_INT_COND_MET, S_CONFLICT */
@@ -3098,8 +3059,8 @@ static void sym_sir_bad_scsi_status(struct sym_hcb *np, int num, ccb_p cp)
* Dequeue all queued CCBs for that device not yet started,
* and restart the SCRIPTS processor immediately.
*/
- (void) sym_dequeue_from_squeue(np, i, cp->target, cp->lun, -1);
- OUTL_DSP (SCRIPTA_BA (np, start));
+ sym_dequeue_from_squeue(np, i, cp->target, cp->lun, -1);
+ OUTL_DSP(np, SCRIPTA_BA(np, start));
/*
* Save some info of the actual IO.
@@ -3132,13 +3093,13 @@ static void sym_sir_bad_scsi_status(struct sym_hcb *np, int num, ccb_p cp)
/*
* Message table indirect structure.
*/
- cp->phys.smsg.addr = cpu_to_scr(CCB_BA (cp, scsi_smsg2));
+ cp->phys.smsg.addr = cpu_to_scr(CCB_BA(cp, scsi_smsg2));
cp->phys.smsg.size = cpu_to_scr(msglen);
/*
* sense command
*/
- cp->phys.cmd.addr = cpu_to_scr(CCB_BA (cp, sensecmd));
+ cp->phys.cmd.addr = cpu_to_scr(CCB_BA(cp, sensecmd));
cp->phys.cmd.size = cpu_to_scr(6);
/*
@@ -3146,7 +3107,7 @@ static void sym_sir_bad_scsi_status(struct sym_hcb *np, int num, ccb_p cp)
*/
cp->sensecmd[0] = REQUEST_SENSE;
cp->sensecmd[1] = 0;
- if (tp->tinfo.curr.scsi_version <= 2 && cp->lun <= 7)
+ if (cp->cmd->device->scsi_level <= SCSI_2 && cp->lun <= 7)
cp->sensecmd[1] = cp->lun << 5;
cp->sensecmd[4] = SYM_SNS_BBUF_LEN;
cp->data_len = SYM_SNS_BBUF_LEN;
@@ -3155,13 +3116,13 @@ static void sym_sir_bad_scsi_status(struct sym_hcb *np, int num, ccb_p cp)
* sense data
*/
memset(cp->sns_bbuf, 0, SYM_SNS_BBUF_LEN);
- cp->phys.sense.addr = cpu_to_scr(vtobus(cp->sns_bbuf));
+ cp->phys.sense.addr = cpu_to_scr(CCB_BA(cp, sns_bbuf));
cp->phys.sense.size = cpu_to_scr(SYM_SNS_BBUF_LEN);
/*
* requeue the command.
*/
- startp = SCRIPTB_BA (np, sdata_in);
+ startp = SCRIPTB_BA(np, sdata_in);
cp->phys.head.savep = cpu_to_scr(startp);
cp->phys.head.lastp = cpu_to_scr(startp);
@@ -3175,7 +3136,7 @@ static void sym_sir_bad_scsi_status(struct sym_hcb *np, int num, ccb_p cp)
cp->xerr_status = 0;
cp->extra_bytes = 0;
- cp->phys.head.go.start = cpu_to_scr(SCRIPTA_BA (np, select));
+ cp->phys.head.go.start = cpu_to_scr(SCRIPTA_BA(np, select));
/*
* Requeue the command.
@@ -3208,7 +3169,7 @@ int sym_clear_tasks(struct sym_hcb *np, int cam_status, int target, int lun, int
{
SYM_QUEHEAD qtmp, *qp;
int i = 0;
- ccb_p cp;
+ struct sym_ccb *cp;
/*
* Move the entire BUSY queue to our temporary queue.
@@ -3223,9 +3184,9 @@ int sym_clear_tasks(struct sym_hcb *np, int cam_status, int target, int lun, int
* the BUSY queue.
*/
while ((qp = sym_remque_head(&qtmp)) != 0) {
- struct scsi_cmnd *ccb;
+ struct scsi_cmnd *cmd;
cp = sym_que_entry(qp, struct sym_ccb, link_ccbq);
- ccb = cp->cam_ccb;
+ cmd = cp->cmd;
if (cp->host_status != HS_DISCONNECT ||
cp->target != target ||
(lun != -1 && cp->lun != lun) ||
@@ -3237,8 +3198,8 @@ int sym_clear_tasks(struct sym_hcb *np, int cam_status, int target, int lun, int
sym_insque_tail(&cp->link_ccbq, &np->comp_ccbq);
/* Preserve the software timeout condition */
- if (sym_get_cam_status(ccb) != CAM_CMD_TIMEOUT)
- sym_set_cam_status(ccb, cam_status);
+ if (sym_get_cam_status(cmd) != CAM_CMD_TIMEOUT)
+ sym_set_cam_status(cmd, cam_status);
++i;
#if 0
printf("XXXX TASK @%p CLEARED\n", cp);
@@ -3290,8 +3251,9 @@ printf("XXXX TASK @%p CLEARED\n", cp);
static void sym_sir_task_recovery(struct sym_hcb *np, int num)
{
SYM_QUEHEAD *qp;
- ccb_p cp;
- tcb_p tp;
+ struct sym_ccb *cp;
+ struct sym_tcb *tp = NULL; /* gcc isn't quite smart enough yet */
+ struct scsi_target *starget;
int target=-1, lun=-1, task;
int i, k;
@@ -3349,8 +3311,8 @@ static void sym_sir_task_recovery(struct sym_hcb *np, int num)
np->abrt_sel.sel_id = target;
np->abrt_sel.sel_scntl3 = tp->head.wval;
np->abrt_sel.sel_sxfer = tp->head.sval;
- OUTL(nc_dsa, np->hcb_ba);
- OUTL_DSP (SCRIPTB_BA (np, sel_for_abort));
+ OUTL(np, nc_dsa, np->hcb_ba);
+ OUTL_DSP(np, SCRIPTB_BA(np, sel_for_abort));
return;
}
@@ -3389,7 +3351,7 @@ static void sym_sir_task_recovery(struct sym_hcb *np, int num)
* Remove the SEM flag from the ISTAT.
*/
np->istat_sem = 0;
- OUTB (nc_istat, SIGP);
+ OUTB(np, nc_istat, SIGP);
break;
}
/*
@@ -3397,14 +3359,14 @@ static void sym_sir_task_recovery(struct sym_hcb *np, int num)
* queue the SCRIPTS intends to start and dequeue
* all CCBs for that device that haven't been started.
*/
- i = (INL (nc_scratcha) - np->squeue_ba) / 4;
+ i = (INL(np, nc_scratcha) - np->squeue_ba) / 4;
i = sym_dequeue_from_squeue(np, i, cp->target, cp->lun, -1);
/*
* Make sure at least our IO to abort has been dequeued.
*/
#ifndef SYM_OPT_HANDLE_DEVICE_QUEUEING
- assert(i && sym_get_cam_status(cp->cam_ccb) == CAM_REQUEUE_REQ);
+ assert(i && sym_get_cam_status(cp->cmd) == CAM_REQUEUE_REQ);
#else
sym_remque(&cp->link_ccbq);
sym_insque_tail(&cp->link_ccbq, &np->comp_ccbq);
@@ -3413,9 +3375,9 @@ static void sym_sir_task_recovery(struct sym_hcb *np, int num)
* Keep track in cam status of the reason of the abort.
*/
if (cp->to_abort == 2)
- sym_set_cam_status(cp->cam_ccb, CAM_CMD_TIMEOUT);
+ sym_set_cam_status(cp->cmd, CAM_CMD_TIMEOUT);
else
- sym_set_cam_status(cp->cam_ccb, CAM_REQ_ABORTED);
+ sym_set_cam_status(cp->cmd, CAM_REQ_ABORTED);
/*
* Complete with error everything that we have dequeued.
@@ -3427,7 +3389,7 @@ static void sym_sir_task_recovery(struct sym_hcb *np, int num)
* we may have some manual recovery to perform for.
*/
case SIR_TARGET_SELECTED:
- target = (INB (nc_sdid) & 0xf);
+ target = INB(np, nc_sdid) & 0xf;
tp = &np->target[target];
np->abrt_tbl.addr = cpu_to_scr(vtobus(np->abrt_msg));
@@ -3463,7 +3425,7 @@ static void sym_sir_task_recovery(struct sym_hcb *np, int num)
* an IDENTIFY(lun) + ABORT MESSAGE.
*/
if (lun != -1) {
- lcb_p lp = sym_lp(np, tp, lun);
+ struct sym_lcb *lp = sym_lp(tp, lun);
lp->to_clear = 0; /* We don't expect to fail here */
np->abrt_msg[0] = IDENTIFY(0, lun);
np->abrt_msg[1] = M_ABORT;
@@ -3529,7 +3491,7 @@ static void sym_sir_task_recovery(struct sym_hcb *np, int num)
* conditions not due to timeout.
*/
if (cp->to_abort == 2)
- sym_set_cam_status(cp->cam_ccb, CAM_CMD_TIMEOUT);
+ sym_set_cam_status(cp->cmd, CAM_CMD_TIMEOUT);
cp->to_abort = 0; /* We donnot expect to fail here */
break;
@@ -3538,8 +3500,9 @@ static void sym_sir_task_recovery(struct sym_hcb *np, int num)
* to BUS FREE phase as we expected.
*/
case SIR_ABORT_SENT:
- target = (INB (nc_sdid) & 0xf);
+ target = INB(np, nc_sdid) & 0xf;
tp = &np->target[target];
+ starget = tp->sdev->sdev_target;
/*
** If we didn't abort anything, leave here.
@@ -3561,10 +3524,13 @@ static void sym_sir_task_recovery(struct sym_hcb *np, int num)
tp->head.sval = 0;
tp->head.wval = np->rv_scntl3;
tp->head.uval = 0;
- tp->tinfo.curr.period = 0;
- tp->tinfo.curr.offset = 0;
- tp->tinfo.curr.width = BUS_8_BIT;
- tp->tinfo.curr.options = 0;
+ spi_period(starget) = 0;
+ spi_offset(starget) = 0;
+ spi_width(starget) = 0;
+ spi_iu(starget) = 0;
+ spi_dt(starget) = 0;
+ spi_qas(starget) = 0;
+ tp->tgoal.check_nego = 1;
}
/*
@@ -3583,9 +3549,9 @@ static void sym_sir_task_recovery(struct sym_hcb *np, int num)
* Complete all the CCBs the device should have
* aborted due to our 'kiss of death' message.
*/
- i = (INL (nc_scratcha) - np->squeue_ba) / 4;
- (void) sym_dequeue_from_squeue(np, i, target, lun, -1);
- (void) sym_clear_tasks(np, CAM_REQ_ABORTED, target, lun, task);
+ i = (INL(np, nc_scratcha) - np->squeue_ba) / 4;
+ sym_dequeue_from_squeue(np, i, target, lun, -1);
+ sym_clear_tasks(np, CAM_REQ_ABORTED, target, lun, task);
sym_flush_comp_queue(np, 0);
/*
@@ -3600,16 +3566,15 @@ static void sym_sir_task_recovery(struct sym_hcb *np, int num)
* Print to the log the message we intend to send.
*/
if (num == SIR_TARGET_SELECTED) {
- PRINT_TARGET(np, target);
- sym_printl_hex("control msgout:", np->abrt_msg,
- np->abrt_tbl.size);
+ dev_info(&tp->sdev->sdev_target->dev, "control msgout:");
+ sym_printl_hex(np->abrt_msg, np->abrt_tbl.size);
np->abrt_tbl.size = cpu_to_scr(np->abrt_tbl.size);
}
/*
* Let the SCRIPTS processor continue.
*/
- OUTONB_STD ();
+ OUTONB_STD();
}
/*
@@ -3617,7 +3582,7 @@ static void sym_sir_task_recovery(struct sym_hcb *np, int num)
* pointer for both MDP and the residual calculation.
*
* I didn't want to bloat the code by more than 200
- * lignes for the handling of both MDP and the residual.
+ * lines for the handling of both MDP and the residual.
* This has been achieved by using a data pointer
* representation consisting in an index in the data
* array (dp_sg) and a negative offset (dp_ofs) that
@@ -3639,7 +3604,7 @@ static void sym_sir_task_recovery(struct sym_hcb *np, int num)
* the corresponding values of dp_sg and dp_ofs.
*/
-static int sym_evaluate_dp(struct sym_hcb *np, ccb_p cp, u32 scr, int *ofs)
+static int sym_evaluate_dp(struct sym_hcb *np, struct sym_ccb *cp, u32 scr, int *ofs)
{
u32 dp_scr;
int dp_ofs, dp_sg, dp_sgmin;
@@ -3652,9 +3617,9 @@ static int sym_evaluate_dp(struct sym_hcb *np, ccb_p cp, u32 scr, int *ofs)
*/
dp_scr = scr;
dp_ofs = *ofs;
- if (dp_scr == SCRIPTA_BA (np, pm0_data))
+ if (dp_scr == SCRIPTA_BA(np, pm0_data))
pm = &cp->phys.pm0;
- else if (dp_scr == SCRIPTA_BA (np, pm1_data))
+ else if (dp_scr == SCRIPTA_BA(np, pm1_data))
pm = &cp->phys.pm1;
else
pm = NULL;
@@ -3757,7 +3722,7 @@ out_err:
* is equivalent to a MODIFY DATA POINTER (offset=-1).
*/
-static void sym_modify_dp(struct sym_hcb *np, tcb_p tp, ccb_p cp, int ofs)
+static void sym_modify_dp(struct sym_hcb *np, struct sym_tcb *tp, struct sym_ccb *cp, int ofs)
{
int dp_ofs = ofs;
u32 dp_scr = sym_get_script_dp (np, cp);
@@ -3800,23 +3765,23 @@ static void sym_modify_dp(struct sym_hcb *np, tcb_p tp, ccb_p cp, int ofs)
/*
* Get a context for the new current data pointer.
*/
- hflags = INB (HF_PRT);
+ hflags = INB(np, HF_PRT);
if (hflags & HF_DP_SAVED)
hflags ^= HF_ACT_PM;
if (!(hflags & HF_ACT_PM)) {
pm = &cp->phys.pm0;
- dp_scr = SCRIPTA_BA (np, pm0_data);
+ dp_scr = SCRIPTA_BA(np, pm0_data);
}
else {
pm = &cp->phys.pm1;
- dp_scr = SCRIPTA_BA (np, pm1_data);
+ dp_scr = SCRIPTA_BA(np, pm1_data);
}
hflags &= ~(HF_DP_SAVED);
- OUTB (HF_PRT, hflags);
+ OUTB(np, HF_PRT, hflags);
/*
* Set up the new current data pointer.
@@ -3833,11 +3798,11 @@ static void sym_modify_dp(struct sym_hcb *np, tcb_p tp, ccb_p cp, int ofs)
out_ok:
sym_set_script_dp (np, cp, dp_scr);
- OUTL_DSP (SCRIPTA_BA (np, clrack));
+ OUTL_DSP(np, SCRIPTA_BA(np, clrack));
return;
out_reject:
- OUTL_DSP (SCRIPTB_BA (np, msg_bad));
+ OUTL_DSP(np, SCRIPTB_BA(np, msg_bad));
}
@@ -3856,7 +3821,7 @@ out_reject:
* a relevant information. :)
*/
-int sym_compute_residual(struct sym_hcb *np, ccb_p cp)
+int sym_compute_residual(struct sym_hcb *np, struct sym_ccb *cp)
{
int dp_sg, dp_sgmin, resid = 0;
int dp_ofs = 0;
@@ -3956,13 +3921,14 @@ int sym_compute_residual(struct sym_hcb *np, ccb_p cp)
* chip handler for SYNCHRONOUS DATA TRANSFER REQUEST (SDTR) message.
*/
static int
-sym_sync_nego_check(struct sym_hcb *np, int req, int target)
+sym_sync_nego_check(struct sym_hcb *np, int req, struct sym_ccb *cp)
{
+ int target = cp->target;
u_char chg, ofs, per, fak, div;
if (DEBUG_FLAGS & DEBUG_NEGO) {
sym_print_nego_msg(np, target, "sync msgin", np->msgin);
- };
+ }
/*
* Get requested values.
@@ -3992,9 +3958,9 @@ sym_sync_nego_check(struct sym_hcb *np, int req, int target)
goto reject_it;
if (DEBUG_FLAGS & DEBUG_NEGO) {
- PRINT_TARGET(np, target);
- printf ("sdtr: ofs=%d per=%d div=%d fak=%d chg=%d.\n",
- ofs, per, div, fak, chg);
+ sym_print_addr(cp->cmd,
+ "sdtr: ofs=%d per=%d div=%d fak=%d chg=%d.\n",
+ ofs, per, div, fak, chg);
}
/*
@@ -4037,7 +4003,7 @@ reject_it:
return -1;
}
-static void sym_sync_nego(struct sym_hcb *np, tcb_p tp, ccb_p cp)
+static void sym_sync_nego(struct sym_hcb *np, struct sym_tcb *tp, struct sym_ccb *cp)
{
int req = 1;
int result;
@@ -4045,8 +4011,8 @@ static void sym_sync_nego(struct sym_hcb *np, tcb_p tp, ccb_p cp)
/*
* Request or answer ?
*/
- if (INB (HS_PRT) == HS_NEGOTIATE) {
- OUTB (HS_PRT, HS_BUSY);
+ if (INB(np, HS_PRT) == HS_NEGOTIATE) {
+ OUTB(np, HS_PRT, HS_BUSY);
if (cp->nego_status && cp->nego_status != NS_SYNC)
goto reject_it;
req = 0;
@@ -4055,19 +4021,19 @@ static void sym_sync_nego(struct sym_hcb *np, tcb_p tp, ccb_p cp)
/*
* Check and apply new values.
*/
- result = sym_sync_nego_check(np, req, cp->target);
+ result = sym_sync_nego_check(np, req, cp);
if (result) /* Not acceptable, reject it */
goto reject_it;
if (req) { /* Was a request, send response. */
cp->nego_status = NS_SYNC;
- OUTL_DSP (SCRIPTB_BA (np, sdtr_resp));
+ OUTL_DSP(np, SCRIPTB_BA(np, sdtr_resp));
}
else /* Was a response, we are done. */
- OUTL_DSP (SCRIPTA_BA (np, clrack));
+ OUTL_DSP(np, SCRIPTA_BA(np, clrack));
return;
reject_it:
- OUTL_DSP (SCRIPTB_BA (np, msg_bad));
+ OUTL_DSP(np, SCRIPTB_BA(np, msg_bad));
}
/*
@@ -4076,7 +4042,7 @@ reject_it:
static int
sym_ppr_nego_check(struct sym_hcb *np, int req, int target)
{
- tcb_p tp = &np->target[target];
+ struct sym_tcb *tp = &np->target[target];
unsigned char fak, div;
int dt, chg = 0;
@@ -4096,10 +4062,7 @@ sym_ppr_nego_check(struct sym_hcb *np, int req, int target)
chg = 1;
wide = np->maxwide;
}
- if (!wide || !(np->features & FE_ULTRA3))
- opts = 0;
-
- if (!(np->features & FE_U3EN)) /* Broken U3EN bit not supported */
+ if (!wide || !(np->features & FE_U3EN))
opts = 0;
if (opts != (np->msgin[7] & PPR_OPT_MASK))
@@ -4175,15 +4138,16 @@ reject_it:
* ST, we may want to try a legacy negotiation later.
*/
if (!req && !opts) {
- tp->tinfo.goal.options = 0;
- tp->tinfo.goal.width = wide;
- tp->tinfo.goal.period = per;
- tp->tinfo.goal.offset = ofs;
+ tp->tgoal.period = per;
+ tp->tgoal.offset = ofs;
+ tp->tgoal.width = wide;
+ tp->tgoal.iu = tp->tgoal.dt = tp->tgoal.qas = 0;
+ tp->tgoal.check_nego = 1;
}
return -1;
}
-static void sym_ppr_nego(struct sym_hcb *np, tcb_p tp, ccb_p cp)
+static void sym_ppr_nego(struct sym_hcb *np, struct sym_tcb *tp, struct sym_ccb *cp)
{
int req = 1;
int result;
@@ -4191,8 +4155,8 @@ static void sym_ppr_nego(struct sym_hcb *np, tcb_p tp, ccb_p cp)
/*
* Request or answer ?
*/
- if (INB (HS_PRT) == HS_NEGOTIATE) {
- OUTB (HS_PRT, HS_BUSY);
+ if (INB(np, HS_PRT) == HS_NEGOTIATE) {
+ OUTB(np, HS_PRT, HS_BUSY);
if (cp->nego_status && cp->nego_status != NS_PPR)
goto reject_it;
req = 0;
@@ -4206,27 +4170,28 @@ static void sym_ppr_nego(struct sym_hcb *np, tcb_p tp, ccb_p cp)
goto reject_it;
if (req) { /* Was a request, send response. */
cp->nego_status = NS_PPR;
- OUTL_DSP (SCRIPTB_BA (np, ppr_resp));
+ OUTL_DSP(np, SCRIPTB_BA(np, ppr_resp));
}
else /* Was a response, we are done. */
- OUTL_DSP (SCRIPTA_BA (np, clrack));
+ OUTL_DSP(np, SCRIPTA_BA(np, clrack));
return;
reject_it:
- OUTL_DSP (SCRIPTB_BA (np, msg_bad));
+ OUTL_DSP(np, SCRIPTB_BA(np, msg_bad));
}
/*
* chip handler for WIDE DATA TRANSFER REQUEST (WDTR) message.
*/
static int
-sym_wide_nego_check(struct sym_hcb *np, int req, int target)
+sym_wide_nego_check(struct sym_hcb *np, int req, struct sym_ccb *cp)
{
+ int target = cp->target;
u_char chg, wide;
if (DEBUG_FLAGS & DEBUG_NEGO) {
sym_print_nego_msg(np, target, "wide msgin", np->msgin);
- };
+ }
/*
* Get requested values.
@@ -4243,8 +4208,8 @@ sym_wide_nego_check(struct sym_hcb *np, int req, int target)
}
if (DEBUG_FLAGS & DEBUG_NEGO) {
- PRINT_TARGET(np, target);
- printf ("wdtr: wide=%d chg=%d.\n", wide, chg);
+ sym_print_addr(cp->cmd, "wdtr: wide=%d chg=%d.\n",
+ wide, chg);
}
/*
@@ -4285,7 +4250,7 @@ reject_it:
return -1;
}
-static void sym_wide_nego(struct sym_hcb *np, tcb_p tp, ccb_p cp)
+static void sym_wide_nego(struct sym_hcb *np, struct sym_tcb *tp, struct sym_ccb *cp)
{
int req = 1;
int result;
@@ -4293,8 +4258,8 @@ static void sym_wide_nego(struct sym_hcb *np, tcb_p tp, ccb_p cp)
/*
* Request or answer ?
*/
- if (INB (HS_PRT) == HS_NEGOTIATE) {
- OUTB (HS_PRT, HS_BUSY);
+ if (INB(np, HS_PRT) == HS_NEGOTIATE) {
+ OUTB(np, HS_PRT, HS_BUSY);
if (cp->nego_status && cp->nego_status != NS_WIDE)
goto reject_it;
req = 0;
@@ -4303,25 +4268,24 @@ static void sym_wide_nego(struct sym_hcb *np, tcb_p tp, ccb_p cp)
/*
* Check and apply new values.
*/
- result = sym_wide_nego_check(np, req, cp->target);
+ result = sym_wide_nego_check(np, req, cp);
if (result) /* Not acceptable, reject it */
goto reject_it;
if (req) { /* Was a request, send response. */
cp->nego_status = NS_WIDE;
- OUTL_DSP (SCRIPTB_BA (np, wdtr_resp));
- }
- else { /* Was a response. */
+ OUTL_DSP(np, SCRIPTB_BA(np, wdtr_resp));
+ } else { /* Was a response. */
/*
* Negotiate for SYNC immediately after WIDE response.
* This allows to negotiate for both WIDE and SYNC on
* a single SCSI command (Suggested by Justin Gibbs).
*/
- if (tp->tinfo.goal.offset) {
+ if (tp->tgoal.offset) {
np->msgout[0] = M_EXTENDED;
np->msgout[1] = 3;
np->msgout[2] = M_X_SYNC_REQ;
- np->msgout[3] = tp->tinfo.goal.period;
- np->msgout[4] = tp->tinfo.goal.offset;
+ np->msgout[3] = tp->tgoal.period;
+ np->msgout[4] = tp->tgoal.offset;
if (DEBUG_FLAGS & DEBUG_NEGO) {
sym_print_nego_msg(np, cp->target,
@@ -4329,18 +4293,17 @@ static void sym_wide_nego(struct sym_hcb *np, tcb_p tp, ccb_p cp)
}
cp->nego_status = NS_SYNC;
- OUTB (HS_PRT, HS_NEGOTIATE);
- OUTL_DSP (SCRIPTB_BA (np, sdtr_resp));
+ OUTB(np, HS_PRT, HS_NEGOTIATE);
+ OUTL_DSP(np, SCRIPTB_BA(np, sdtr_resp));
return;
- }
- else
- OUTL_DSP (SCRIPTA_BA (np, clrack));
- };
+ } else
+ OUTL_DSP(np, SCRIPTA_BA(np, clrack));
+ }
return;
reject_it:
- OUTL_DSP (SCRIPTB_BA (np, msg_bad));
+ OUTL_DSP(np, SCRIPTB_BA(np, msg_bad));
}
/*
@@ -4354,18 +4317,19 @@ reject_it:
* So, if a PPR makes problems, we may just want to
* try a legacy negotiation later.
*/
-static void sym_nego_default(struct sym_hcb *np, tcb_p tp, ccb_p cp)
+static void sym_nego_default(struct sym_hcb *np, struct sym_tcb *tp, struct sym_ccb *cp)
{
switch (cp->nego_status) {
case NS_PPR:
#if 0
sym_setpprot (np, cp->target, 0, 0, 0, 0, 0, 0);
#else
- tp->tinfo.goal.options = 0;
- if (tp->tinfo.goal.period < np->minsync)
- tp->tinfo.goal.period = np->minsync;
- if (tp->tinfo.goal.offset > np->maxoffs)
- tp->tinfo.goal.offset = np->maxoffs;
+ if (tp->tgoal.period < np->minsync)
+ tp->tgoal.period = np->minsync;
+ if (tp->tgoal.offset > np->maxoffs)
+ tp->tgoal.offset = np->maxoffs;
+ tp->tgoal.iu = tp->tgoal.dt = tp->tgoal.qas = 0;
+ tp->tgoal.check_nego = 1;
#endif
break;
case NS_SYNC:
@@ -4374,7 +4338,7 @@ static void sym_nego_default(struct sym_hcb *np, tcb_p tp, ccb_p cp)
case NS_WIDE:
sym_setwide (np, cp->target, 0);
break;
- };
+ }
np->msgin [0] = M_NOOP;
np->msgout[0] = M_NOOP;
cp->nego_status = 0;
@@ -4384,10 +4348,10 @@ static void sym_nego_default(struct sym_hcb *np, tcb_p tp, ccb_p cp)
* chip handler for MESSAGE REJECT received in response to
* PPR, WIDE or SYNCHRONOUS negotiation.
*/
-static void sym_nego_rejected(struct sym_hcb *np, tcb_p tp, ccb_p cp)
+static void sym_nego_rejected(struct sym_hcb *np, struct sym_tcb *tp, struct sym_ccb *cp)
{
sym_nego_default(np, tp, cp);
- OUTB (HS_PRT, HS_BUSY);
+ OUTB(np, HS_PRT, HS_BUSY);
}
/*
@@ -4395,11 +4359,11 @@ static void sym_nego_rejected(struct sym_hcb *np, tcb_p tp, ccb_p cp)
*/
static void sym_int_sir (struct sym_hcb *np)
{
- u_char num = INB (nc_dsps);
- u32 dsa = INL (nc_dsa);
- ccb_p cp = sym_ccb_from_dsa(np, dsa);
- u_char target = INB (nc_sdid) & 0x0f;
- tcb_p tp = &np->target[target];
+ u_char num = INB(np, nc_dsps);
+ u32 dsa = INL(np, nc_dsa);
+ struct sym_ccb *cp = sym_ccb_from_dsa(np, dsa);
+ u_char target = INB(np, nc_sdid) & 0x0f;
+ struct sym_tcb *tp = &np->target[target];
int tmp;
if (DEBUG_FLAGS & DEBUG_TINY) printf ("I#%d", num);
@@ -4497,7 +4461,7 @@ static void sym_int_sir (struct sym_hcb *np)
if (cp) {
cp->xerr_status &= ~XE_PARITY_ERR;
if (!cp->xerr_status)
- OUTOFFB (HF_PRT, HF_EXT_ERR);
+ OUTOFFB(np, HF_PRT, HF_EXT_ERR);
}
}
goto out;
@@ -4527,7 +4491,7 @@ static void sym_int_sir (struct sym_hcb *np)
*/
case SIR_SWIDE_OVERRUN:
if (cp) {
- OUTONB (HF_PRT, HF_EXT_ERR);
+ OUTONB(np, HF_PRT, HF_EXT_ERR);
cp->xerr_status |= XE_SWIDE_OVRUN;
}
goto out;
@@ -4538,7 +4502,7 @@ static void sym_int_sir (struct sym_hcb *np)
*/
case SIR_SODL_UNDERRUN:
if (cp) {
- OUTONB (HF_PRT, HF_EXT_ERR);
+ OUTONB(np, HF_PRT, HF_EXT_ERR);
cp->xerr_status |= XE_SODL_UNRUN;
}
goto out;
@@ -4550,9 +4514,9 @@ static void sym_int_sir (struct sym_hcb *np)
*/
case SIR_DATA_OVERRUN:
if (cp) {
- OUTONB (HF_PRT, HF_EXT_ERR);
+ OUTONB(np, HF_PRT, HF_EXT_ERR);
cp->xerr_status |= XE_EXTRA_DATA;
- cp->extra_bytes += INL (nc_scratcha);
+ cp->extra_bytes += INL(np, nc_scratcha);
}
goto out;
/*
@@ -4560,7 +4524,7 @@ static void sym_int_sir (struct sym_hcb *np)
*/
case SIR_BAD_PHASE:
if (cp) {
- OUTONB (HF_PRT, HF_EXT_ERR);
+ OUTONB(np, HF_PRT, HF_EXT_ERR);
cp->xerr_status |= XE_BAD_PHASE;
}
goto out;
@@ -4609,16 +4573,16 @@ static void sym_int_sir (struct sym_hcb *np)
if (DEBUG_FLAGS & DEBUG_POINTER)
sym_print_msg(cp,"ign wide residue", np->msgin);
if (cp->host_flags & HF_SENSE)
- OUTL_DSP (SCRIPTA_BA (np, clrack));
+ OUTL_DSP(np, SCRIPTA_BA(np, clrack));
else
sym_modify_dp(np, tp, cp, -1);
return;
case M_REJECT:
- if (INB (HS_PRT) == HS_NEGOTIATE)
+ if (INB(np, HS_PRT) == HS_NEGOTIATE)
sym_nego_rejected(np, tp, cp);
else {
- PRINT_ADDR(cp);
- printf ("M_REJECT received (%x:%x).\n",
+ sym_print_addr(cp->cmd,
+ "M_REJECT received (%x:%x).\n",
scr_to_cpu(np->lastmsg), np->msgout[0]);
}
goto out_clrack;
@@ -4633,7 +4597,7 @@ static void sym_int_sir (struct sym_hcb *np)
*/
case SIR_MSG_WEIRD:
sym_print_msg(cp, "WEIRD message received", np->msgin);
- OUTL_DSP (SCRIPTB_BA (np, msg_weird));
+ OUTL_DSP(np, SCRIPTB_BA(np, msg_weird));
return;
/*
* Negotiation failed.
@@ -4641,7 +4605,7 @@ static void sym_int_sir (struct sym_hcb *np)
* Remove the HS_NEGOTIATE status.
*/
case SIR_NEGO_FAILED:
- OUTB (HS_PRT, HS_BUSY);
+ OUTB(np, HS_PRT, HS_BUSY);
/*
* Negotiation failed.
* Target does not want answer message.
@@ -4649,16 +4613,16 @@ static void sym_int_sir (struct sym_hcb *np)
case SIR_NEGO_PROTO:
sym_nego_default(np, tp, cp);
goto out;
- };
+ }
out:
- OUTONB_STD ();
+ OUTONB_STD();
return;
out_reject:
- OUTL_DSP (SCRIPTB_BA (np, msg_bad));
+ OUTL_DSP(np, SCRIPTB_BA(np, msg_bad));
return;
out_clrack:
- OUTL_DSP (SCRIPTA_BA (np, clrack));
+ OUTL_DSP(np, SCRIPTA_BA(np, clrack));
return;
out_stuck:
return;
@@ -4667,19 +4631,21 @@ out_stuck:
/*
* Acquire a control block
*/
-ccb_p sym_get_ccb (struct sym_hcb *np, u_char tn, u_char ln, u_char tag_order)
+struct sym_ccb *sym_get_ccb (struct sym_hcb *np, struct scsi_cmnd *cmd, u_char tag_order)
{
- tcb_p tp = &np->target[tn];
- lcb_p lp = sym_lp(np, tp, ln);
+ u_char tn = cmd->device->id;
+ u_char ln = cmd->device->lun;
+ struct sym_tcb *tp = &np->target[tn];
+ struct sym_lcb *lp = sym_lp(tp, ln);
u_short tag = NO_TAG;
SYM_QUEHEAD *qp;
- ccb_p cp = (ccb_p) 0;
+ struct sym_ccb *cp = NULL;
/*
* Look for a free CCB
*/
if (sym_que_empty(&np->free_ccbq))
- (void) sym_alloc_ccb(np);
+ sym_alloc_ccb(np);
qp = sym_remque_head(&np->free_ccbq);
if (!qp)
goto out;
@@ -4741,7 +4707,7 @@ ccb_p sym_get_ccb (struct sym_hcb *np, u_char tn, u_char ln, u_char tag_order)
#ifndef SYM_OPT_HANDLE_DEVICE_QUEUEING
lp->itlq_tbl[tag] = cpu_to_scr(cp->ccb_ba);
lp->head.resel_sa =
- cpu_to_scr(SCRIPTA_BA (np, resel_tag));
+ cpu_to_scr(SCRIPTA_BA(np, resel_tag));
#endif
#ifdef SYM_OPT_LIMIT_COMMAND_REORDERING
cp->tags_si = lp->tags_si;
@@ -4774,7 +4740,7 @@ ccb_p sym_get_ccb (struct sym_hcb *np, u_char tn, u_char ln, u_char tag_order)
if (lp->busy_itl == 1) {
lp->head.itl_task_sa = cpu_to_scr(cp->ccb_ba);
lp->head.resel_sa =
- cpu_to_scr(SCRIPTA_BA (np, resel_no_tag));
+ cpu_to_scr(SCRIPTA_BA(np, resel_no_tag));
}
else
goto out_free;
@@ -4802,28 +4768,27 @@ ccb_p sym_get_ccb (struct sym_hcb *np, u_char tn, u_char ln, u_char tag_order)
cp->lun = ln;
if (DEBUG_FLAGS & DEBUG_TAGS) {
- PRINT_LUN(np, tn, ln);
- printf ("ccb @%p using tag %d.\n", cp, tag);
+ sym_print_addr(cmd, "ccb @%p using tag %d.\n", cp, tag);
}
out:
return cp;
out_free:
sym_insque_head(&cp->link_ccbq, &np->free_ccbq);
- return (ccb_p) 0;
+ return NULL;
}
/*
* Release one control block
*/
-void sym_free_ccb (struct sym_hcb *np, ccb_p cp)
+void sym_free_ccb (struct sym_hcb *np, struct sym_ccb *cp)
{
- tcb_p tp = &np->target[cp->target];
- lcb_p lp = sym_lp(np, tp, cp->lun);
+ struct sym_tcb *tp = &np->target[cp->target];
+ struct sym_lcb *lp = sym_lp(tp, cp->lun);
if (DEBUG_FLAGS & DEBUG_TAGS) {
- PRINT_LUN(np, cp->target, cp->lun);
- printf ("ccb @%p freeing tag %d.\n", cp, cp->tag);
+ sym_print_addr(cp->cmd, "ccb @%p freeing tag %d.\n",
+ cp, cp->tag);
}
/*
@@ -4862,7 +4827,7 @@ void sym_free_ccb (struct sym_hcb *np, ccb_p cp)
*/
if (lp->busy_itlq == 0 && lp->busy_itl == 0)
lp->head.resel_sa =
- cpu_to_scr(SCRIPTB_BA (np, resel_bad_lun));
+ cpu_to_scr(SCRIPTB_BA(np, resel_bad_lun));
}
/*
* Otherwise, we only accept 1 IO per LUN.
@@ -4889,14 +4854,9 @@ void sym_free_ccb (struct sym_hcb *np, ccb_p cp)
#endif
/*
- * Unmap user data from DMA map if needed.
- */
- sym_data_dmamap_unload(np, cp);
-
- /*
* Make this CCB available.
*/
- cp->cam_ccb = NULL;
+ cp->cmd = NULL;
cp->host_status = HS_IDLE;
sym_remque(&cp->link_ccbq);
sym_insque_head(&cp->link_ccbq, &np->free_ccbq);
@@ -4919,9 +4879,9 @@ void sym_free_ccb (struct sym_hcb *np, ccb_p cp)
/*
* Allocate a CCB from memory and initialize its fixed part.
*/
-static ccb_p sym_alloc_ccb(struct sym_hcb *np)
+static struct sym_ccb *sym_alloc_ccb(struct sym_hcb *np)
{
- ccb_p cp = NULL;
+ struct sym_ccb *cp = NULL;
int hcode;
/*
@@ -4939,19 +4899,6 @@ static ccb_p sym_alloc_ccb(struct sym_hcb *np)
goto out_free;
/*
- * Allocate a bounce buffer for sense data.
- */
- cp->sns_bbuf = sym_calloc_dma(SYM_SNS_BBUF_LEN, "SNS_BBUF");
- if (!cp->sns_bbuf)
- goto out_free;
-
- /*
- * Allocate a map for the DMA of user data.
- */
- if (sym_data_dmamap_create(np, cp))
- goto out_free;
-
- /*
* Count it.
*/
np->actccbs++;
@@ -4971,8 +4918,8 @@ static ccb_p sym_alloc_ccb(struct sym_hcb *np)
/*
* Initialyze the start and restart actions.
*/
- cp->phys.head.go.start = cpu_to_scr(SCRIPTA_BA (np, idle));
- cp->phys.head.go.restart = cpu_to_scr(SCRIPTB_BA (np, bad_i_t_l));
+ cp->phys.head.go.start = cpu_to_scr(SCRIPTA_BA(np, idle));
+ cp->phys.head.go.restart = cpu_to_scr(SCRIPTB_BA(np, bad_i_t_l));
/*
* Initilialyze some other fields.
@@ -4992,21 +4939,18 @@ static ccb_p sym_alloc_ccb(struct sym_hcb *np)
#endif
return cp;
out_free:
- if (cp) {
- if (cp->sns_bbuf)
- sym_mfree_dma(cp->sns_bbuf,SYM_SNS_BBUF_LEN,"SNS_BBUF");
+ if (cp)
sym_mfree_dma(cp, sizeof(*cp), "CCB");
- }
return NULL;
}
/*
* Look up a CCB from a DSA value.
*/
-static ccb_p sym_ccb_from_dsa(struct sym_hcb *np, u32 dsa)
+static struct sym_ccb *sym_ccb_from_dsa(struct sym_hcb *np, u32 dsa)
{
int hcode;
- ccb_p cp;
+ struct sym_ccb *cp;
hcode = CCB_HASH_CODE(dsa);
cp = np->ccbh[hcode];
@@ -5039,10 +4983,10 @@ static void sym_init_tcb (struct sym_hcb *np, u_char tn)
/*
* Lun control block allocation and initialization.
*/
-lcb_p sym_alloc_lcb (struct sym_hcb *np, u_char tn, u_char ln)
+struct sym_lcb *sym_alloc_lcb (struct sym_hcb *np, u_char tn, u_char ln)
{
- tcb_p tp = &np->target[tn];
- lcb_p lp = sym_lp(np, tp, ln);
+ struct sym_tcb *tp = &np->target[tn];
+ struct sym_lcb *lp = sym_lp(tp, ln);
/*
* Already done, just return.
@@ -5081,8 +5025,8 @@ lcb_p sym_alloc_lcb (struct sym_hcb *np, u_char tn, u_char ln)
* Allocate the table of pointers for LUN(s) > 0, if needed.
*/
if (ln && !tp->lunmp) {
- tp->lunmp = sym_calloc(SYM_CONF_MAX_LUN * sizeof(lcb_p),
- "LUNMP");
+ tp->lunmp = kcalloc(SYM_CONF_MAX_LUN, sizeof(struct sym_lcb *),
+ GFP_KERNEL);
if (!tp->lunmp)
goto fail;
}
@@ -5111,7 +5055,7 @@ lcb_p sym_alloc_lcb (struct sym_hcb *np, u_char tn, u_char ln)
/*
* Set the reselect pattern to our default. :)
*/
- lp->head.resel_sa = cpu_to_scr(SCRIPTB_BA (np, resel_bad_lun));
+ lp->head.resel_sa = cpu_to_scr(SCRIPTB_BA(np, resel_bad_lun));
/*
* Set user capabilities.
@@ -5143,8 +5087,8 @@ fail:
*/
static void sym_alloc_lcb_tags (struct sym_hcb *np, u_char tn, u_char ln)
{
- tcb_p tp = &np->target[tn];
- lcb_p lp = sym_lp(np, tp, ln);
+ struct sym_tcb *tp = &np->target[tn];
+ struct sym_lcb *lp = sym_lp(tp, ln);
int i;
/*
@@ -5160,7 +5104,7 @@ static void sym_alloc_lcb_tags (struct sym_hcb *np, u_char tn, u_char ln)
lp->itlq_tbl = sym_calloc_dma(SYM_CONF_MAX_TASK*4, "ITLQ_TBL");
if (!lp->itlq_tbl)
goto fail;
- lp->cb_tags = sym_calloc(SYM_CONF_MAX_TASK, "CB_TAGS");
+ lp->cb_tags = kcalloc(SYM_CONF_MAX_TASK, 1, GFP_KERNEL);
if (!lp->cb_tags) {
sym_mfree_dma(lp->itlq_tbl, SYM_CONF_MAX_TASK*4, "ITLQ_TBL");
lp->itlq_tbl = NULL;
@@ -5193,10 +5137,11 @@ fail:
/*
* Queue a SCSI IO to the controller.
*/
-int sym_queue_scsiio(struct sym_hcb *np, struct scsi_cmnd *csio, ccb_p cp)
+int sym_queue_scsiio(struct sym_hcb *np, struct scsi_cmnd *cmd, struct sym_ccb *cp)
{
- tcb_p tp;
- lcb_p lp;
+ struct scsi_device *sdev = cmd->device;
+ struct sym_tcb *tp;
+ struct sym_lcb *lp;
u_char *msgptr;
u_int msglen;
int can_disconnect;
@@ -5204,7 +5149,7 @@ int sym_queue_scsiio(struct sym_hcb *np, struct scsi_cmnd *csio, ccb_p cp)
/*
* Keep track of the IO in our CCB.
*/
- cp->cam_ccb = csio;
+ cp->cmd = cmd;
/*
* Retrieve the target descriptor.
@@ -5214,14 +5159,14 @@ int sym_queue_scsiio(struct sym_hcb *np, struct scsi_cmnd *csio, ccb_p cp)
/*
* Retrieve the lun descriptor.
*/
- lp = sym_lp(np, tp, cp->lun);
+ lp = sym_lp(tp, sdev->lun);
can_disconnect = (cp->tag != NO_TAG) ||
(lp && (lp->curr_flags & SYM_DISC_ENABLED));
msgptr = cp->scsi_smsg;
msglen = 0;
- msgptr[msglen++] = IDENTIFY(can_disconnect, cp->lun);
+ msgptr[msglen++] = IDENTIFY(can_disconnect, sdev->lun);
/*
* Build the tag message if present.
@@ -5249,8 +5194,8 @@ int sym_queue_scsiio(struct sym_hcb *np, struct scsi_cmnd *csio, ccb_p cp)
if (lp->tags_sum[lp->tags_si]) {
order = M_ORDERED_TAG;
if ((DEBUG_FLAGS & DEBUG_TAGS)||sym_verbose>1) {
- PRINT_ADDR(cp);
- printf("ordered tag forced.\n");
+ sym_print_addr(cmd,
+ "ordered tag forced.\n");
}
}
lp->tags_since = 0;
@@ -5277,19 +5222,15 @@ int sym_queue_scsiio(struct sym_hcb *np, struct scsi_cmnd *csio, ccb_p cp)
* (nego_status is filled by sym_prepare_nego())
*/
cp->nego_status = 0;
- if (tp->tinfo.curr.width != tp->tinfo.goal.width ||
- tp->tinfo.curr.period != tp->tinfo.goal.period ||
- tp->tinfo.curr.offset != tp->tinfo.goal.offset ||
- tp->tinfo.curr.options != tp->tinfo.goal.options) {
- if (!tp->nego_cp && lp)
- msglen += sym_prepare_nego(np, cp, msgptr + msglen);
+ if (tp->tgoal.check_nego && !tp->nego_cp && lp) {
+ msglen += sym_prepare_nego(np, cp, msgptr + msglen);
}
/*
* Startqueue
*/
- cp->phys.head.go.start = cpu_to_scr(SCRIPTA_BA (np, select));
- cp->phys.head.go.restart = cpu_to_scr(SCRIPTA_BA (np, resel_dsa));
+ cp->phys.head.go.start = cpu_to_scr(SCRIPTA_BA(np, select));
+ cp->phys.head.go.restart = cpu_to_scr(SCRIPTA_BA(np, resel_dsa));
/*
* select
@@ -5302,7 +5243,7 @@ int sym_queue_scsiio(struct sym_hcb *np, struct scsi_cmnd *csio, ccb_p cp)
/*
* message
*/
- cp->phys.smsg.addr = cpu_to_scr(CCB_BA (cp, scsi_smsg));
+ cp->phys.smsg.addr = cpu_to_scr(CCB_BA(cp, scsi_smsg));
cp->phys.smsg.size = cpu_to_scr(msglen);
/*
@@ -5326,7 +5267,7 @@ int sym_queue_scsiio(struct sym_hcb *np, struct scsi_cmnd *csio, ccb_p cp)
* Build the CDB and DATA descriptor block
* and start the IO.
*/
- return sym_setup_data_and_start(np, csio, cp);
+ return sym_setup_data_and_start(np, cmd, cp);
}
/*
@@ -5334,7 +5275,7 @@ int sym_queue_scsiio(struct sym_hcb *np, struct scsi_cmnd *csio, ccb_p cp)
*/
int sym_reset_scsi_target(struct sym_hcb *np, int target)
{
- tcb_p tp;
+ struct sym_tcb *tp;
if (target == np->myaddr || (u_int)target >= SYM_CONF_MAX_TARGET)
return -1;
@@ -5343,7 +5284,7 @@ int sym_reset_scsi_target(struct sym_hcb *np, int target)
tp->to_reset = 1;
np->istat_sem = SEM;
- OUTB (nc_istat, SIGP|SEM);
+ OUTB(np, nc_istat, SIGP|SEM);
return 0;
}
@@ -5351,7 +5292,7 @@ int sym_reset_scsi_target(struct sym_hcb *np, int target)
/*
* Abort a SCSI IO.
*/
-int sym_abort_ccb(struct sym_hcb *np, ccb_p cp, int timed_out)
+static int sym_abort_ccb(struct sym_hcb *np, struct sym_ccb *cp, int timed_out)
{
/*
* Check that the IO is active.
@@ -5377,13 +5318,13 @@ int sym_abort_ccb(struct sym_hcb *np, ccb_p cp, int timed_out)
* Tell the SCRIPTS processor to stop and synchronize with us.
*/
np->istat_sem = SEM;
- OUTB (nc_istat, SIGP|SEM);
+ OUTB(np, nc_istat, SIGP|SEM);
return 0;
}
-int sym_abort_scsiio(struct sym_hcb *np, struct scsi_cmnd *ccb, int timed_out)
+int sym_abort_scsiio(struct sym_hcb *np, struct scsi_cmnd *cmd, int timed_out)
{
- ccb_p cp;
+ struct sym_ccb *cp;
SYM_QUEHEAD *qp;
/*
@@ -5391,8 +5332,8 @@ int sym_abort_scsiio(struct sym_hcb *np, struct scsi_cmnd *ccb, int timed_out)
*/
cp = NULL;
FOR_EACH_QUEUED_ELEMENT(&np->busy_ccbq, qp) {
- ccb_p cp2 = sym_que_entry(qp, struct sym_ccb, link_ccbq);
- if (cp2->cam_ccb == ccb) {
+ struct sym_ccb *cp2 = sym_que_entry(qp, struct sym_ccb, link_ccbq);
+ if (cp2->cmd == cmd) {
cp = cp2;
break;
}
@@ -5411,37 +5352,40 @@ int sym_abort_scsiio(struct sym_hcb *np, struct scsi_cmnd *ccb, int timed_out)
* SCRATCHA is assumed to have been loaded with STARTPOS
* before the SCRIPTS called the C code.
*/
-void sym_complete_error (struct sym_hcb *np, ccb_p cp)
+void sym_complete_error(struct sym_hcb *np, struct sym_ccb *cp)
{
- tcb_p tp;
- lcb_p lp;
+ struct scsi_device *sdev;
+ struct scsi_cmnd *cmd;
+ struct sym_tcb *tp;
+ struct sym_lcb *lp;
int resid;
int i;
/*
* Paranoid check. :)
*/
- if (!cp || !cp->cam_ccb)
+ if (!cp || !cp->cmd)
return;
+ cmd = cp->cmd;
+ sdev = cmd->device;
if (DEBUG_FLAGS & (DEBUG_TINY|DEBUG_RESULT)) {
- printf ("CCB=%lx STAT=%x/%x/%x DEV=%d/%d\n", (unsigned long)cp,
- cp->host_status, cp->ssss_status, cp->host_flags,
- cp->target, cp->lun);
+ dev_info(&sdev->sdev_gendev, "CCB=%p STAT=%x/%x/%x\n", cp,
+ cp->host_status, cp->ssss_status, cp->host_flags);
}
/*
* Get target and lun pointers.
*/
tp = &np->target[cp->target];
- lp = sym_lp(np, tp, cp->lun);
+ lp = sym_lp(tp, sdev->lun);
/*
* Check for extended errors.
*/
if (cp->xerr_status) {
if (sym_verbose)
- sym_print_xerr(cp, cp->xerr_status);
+ sym_print_xerr(cmd, cp->xerr_status);
if (cp->host_status == HS_COMPLETE)
cp->host_status = HS_COMP_ERR;
}
@@ -5464,13 +5408,13 @@ if (resid)
* Dequeue all queued CCBs for that device
* not yet started by SCRIPTS.
*/
- i = (INL (nc_scratcha) - np->squeue_ba) / 4;
- i = sym_dequeue_from_squeue(np, i, cp->target, cp->lun, -1);
+ i = (INL(np, nc_scratcha) - np->squeue_ba) / 4;
+ i = sym_dequeue_from_squeue(np, i, cp->target, sdev->lun, -1);
/*
* Restart the SCRIPTS processor.
*/
- OUTL_DSP (SCRIPTA_BA (np, start));
+ OUTL_DSP(np, SCRIPTA_BA(np, start));
#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
if (cp->host_status == HS_COMPLETE &&
@@ -5484,8 +5428,8 @@ if (resid)
lp->num_sgood = 0;
if (sym_verbose >= 2) {
- PRINT_LUN(np, cp->target, cp->lun);
- printf(" queue depth is now %d\n", lp->started_max);
+ sym_print_addr(cmd, " queue depth is now %d\n",
+ lp->started_max);
}
/*
@@ -5497,17 +5441,12 @@ if (resid)
/*
* Let's requeue it to device.
*/
- sym_set_cam_status(cp->cam_ccb, CAM_REQUEUE_REQ);
+ sym_set_cam_status(cmd, CAM_REQUEUE_REQ);
goto finish;
}
weirdness:
#endif
/*
- * Synchronize DMA map if needed.
- */
- sym_data_dmamap_postsync(np, cp);
-
- /*
* Build result in CAM ccb.
*/
sym_set_cam_result_error(np, cp, resid);
@@ -5545,30 +5484,30 @@ finish:
* The SCRIPTS processor is running while we are
* completing successful commands.
*/
-void sym_complete_ok (struct sym_hcb *np, ccb_p cp)
+void sym_complete_ok (struct sym_hcb *np, struct sym_ccb *cp)
{
- tcb_p tp;
- lcb_p lp;
- struct scsi_cmnd *ccb;
+ struct sym_tcb *tp;
+ struct sym_lcb *lp;
+ struct scsi_cmnd *cmd;
int resid;
/*
* Paranoid check. :)
*/
- if (!cp || !cp->cam_ccb)
+ if (!cp || !cp->cmd)
return;
assert (cp->host_status == HS_COMPLETE);
/*
* Get user command.
*/
- ccb = cp->cam_ccb;
+ cmd = cp->cmd;
/*
* Get target and lun pointers.
*/
tp = &np->target[cp->target];
- lp = sym_lp(np, tp, cp->lun);
+ lp = sym_lp(tp, cp->lun);
/*
* Assume device discovered on first success.
@@ -5586,8 +5525,8 @@ void sym_complete_ok (struct sym_hcb *np, ccb_p cp)
/*
* Wrong transfer residuals may be worse than just always
- * returning zero. User can disable this feature from
- * sym_conf.h. Residual support is enabled by default.
+ * returning zero. User can disable this feature in
+ * sym53c8xx.h. Residual support is enabled by default.
*/
if (!SYM_SETUP_RESIDUAL_SUPPORT)
resid = 0;
@@ -5597,14 +5536,9 @@ if (resid)
#endif
/*
- * Synchronize DMA map if needed.
- */
- sym_data_dmamap_postsync(np, cp);
-
- /*
* Build result in CAM ccb.
*/
- sym_set_cam_result_ok(np, cp, resid);
+ sym_set_cam_result_ok(cp, cmd, resid);
#ifdef SYM_OPT_SNIFF_INQUIRY
/*
@@ -5612,7 +5546,7 @@ if (resid)
* not set), sniff out device capabilities.
*/
if (cp->cdb_buf[0] == INQUIRY && !(cp->cdb_buf[1] & 0x3))
- sym_sniff_inquiry(np, cp->cam_ccb, resid);
+ sym_sniff_inquiry(np, cmd, resid);
#endif
#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
@@ -5626,8 +5560,7 @@ if (resid)
lp->num_sgood = 0;
++lp->started_max;
if (sym_verbose >= 2) {
- PRINT_LUN(np, cp->target, cp->lun);
- printf(" queue depth is now %d\n",
+ sym_print_addr(cmd, " queue depth is now %d\n",
lp->started_max);
}
}
@@ -5649,14 +5582,15 @@ if (resid)
/*
* Complete the command.
*/
- sym_xpt_done(np, ccb);
+ sym_xpt_done(np, cmd);
}
/*
* Soft-attach the controller.
*/
-int sym_hcb_attach(struct sym_hcb *np, struct sym_fw *fw, struct sym_nvram *nvram)
+int sym_hcb_attach(struct Scsi_Host *shost, struct sym_fw *fw, struct sym_nvram *nvram)
{
+ struct sym_hcb *np = sym_get_hcb(shost);
int i;
/*
@@ -5680,13 +5614,13 @@ int sym_hcb_attach(struct sym_hcb *np, struct sym_fw *fw, struct sym_nvram *nvra
* that SCSI clock calibration may not work properly
* if the chip is currently active.
*/
- sym_chip_reset (np);
+ sym_chip_reset(np);
/*
* Prepare controller and devices settings, according
* to chip features, user set-up and driver set-up.
*/
- (void) sym_prepare_setting(np, nvram);
+ sym_prepare_setting(shost, np, nvram);
/*
* Check the PCI clock frequency.
@@ -5701,7 +5635,7 @@ int sym_hcb_attach(struct sym_hcb *np, struct sym_fw *fw, struct sym_nvram *nvra
/*
* Allocate the start queue.
*/
- np->squeue = (u32 *) sym_calloc_dma(sizeof(u32)*(MAX_QUEUE*2),"SQUEUE");
+ np->squeue = sym_calloc_dma(sizeof(u32)*(MAX_QUEUE*2),"SQUEUE");
if (!np->squeue)
goto attach_failed;
np->squeue_ba = vtobus(np->squeue);
@@ -5709,7 +5643,7 @@ int sym_hcb_attach(struct sym_hcb *np, struct sym_fw *fw, struct sym_nvram *nvra
/*
* Allocate the done queue.
*/
- np->dqueue = (u32 *) sym_calloc_dma(sizeof(u32)*(MAX_QUEUE*2),"DQUEUE");
+ np->dqueue = sym_calloc_dma(sizeof(u32)*(MAX_QUEUE*2),"DQUEUE");
if (!np->dqueue)
goto attach_failed;
np->dqueue_ba = vtobus(np->dqueue);
@@ -5717,7 +5651,7 @@ int sym_hcb_attach(struct sym_hcb *np, struct sym_fw *fw, struct sym_nvram *nvra
/*
* Allocate the target bus address array.
*/
- np->targtbl = (u32 *) sym_calloc_dma(256, "TARGTBL");
+ np->targtbl = sym_calloc_dma(256, "TARGTBL");
if (!np->targtbl)
goto attach_failed;
np->targtbl_ba = vtobus(np->targtbl);
@@ -5734,7 +5668,7 @@ int sym_hcb_attach(struct sym_hcb *np, struct sym_fw *fw, struct sym_nvram *nvra
/*
* Allocate the array of lists of CCBs hashed by DSA.
*/
- np->ccbh = sym_calloc(sizeof(ccb_p *)*CCB_HASH_SIZE, "CCBH");
+ np->ccbh = kcalloc(sizeof(struct sym_ccb **), CCB_HASH_SIZE, GFP_KERNEL);
if (!np->ccbh)
goto attach_failed;
@@ -5817,20 +5751,20 @@ int sym_hcb_attach(struct sym_hcb *np, struct sym_fw *fw, struct sym_nvram *nvra
/*
* Prepare the idle and invalid task actions.
*/
- np->idletask.start = cpu_to_scr(SCRIPTA_BA (np, idle));
- np->idletask.restart = cpu_to_scr(SCRIPTB_BA (np, bad_i_t_l));
+ np->idletask.start = cpu_to_scr(SCRIPTA_BA(np, idle));
+ np->idletask.restart = cpu_to_scr(SCRIPTB_BA(np, bad_i_t_l));
np->idletask_ba = vtobus(&np->idletask);
- np->notask.start = cpu_to_scr(SCRIPTA_BA (np, idle));
- np->notask.restart = cpu_to_scr(SCRIPTB_BA (np, bad_i_t_l));
+ np->notask.start = cpu_to_scr(SCRIPTA_BA(np, idle));
+ np->notask.restart = cpu_to_scr(SCRIPTB_BA(np, bad_i_t_l));
np->notask_ba = vtobus(&np->notask);
- np->bad_itl.start = cpu_to_scr(SCRIPTA_BA (np, idle));
- np->bad_itl.restart = cpu_to_scr(SCRIPTB_BA (np, bad_i_t_l));
+ np->bad_itl.start = cpu_to_scr(SCRIPTA_BA(np, idle));
+ np->bad_itl.restart = cpu_to_scr(SCRIPTB_BA(np, bad_i_t_l));
np->bad_itl_ba = vtobus(&np->bad_itl);
- np->bad_itlq.start = cpu_to_scr(SCRIPTA_BA (np, idle));
- np->bad_itlq.restart = cpu_to_scr(SCRIPTB_BA (np,bad_i_t_l_q));
+ np->bad_itlq.start = cpu_to_scr(SCRIPTA_BA(np, idle));
+ np->bad_itlq.restart = cpu_to_scr(SCRIPTB_BA(np,bad_i_t_l_q));
np->bad_itlq_ba = vtobus(&np->bad_itlq);
/*
@@ -5843,7 +5777,7 @@ int sym_hcb_attach(struct sym_hcb *np, struct sym_fw *fw, struct sym_nvram *nvra
if (!np->badluntbl)
goto attach_failed;
- np->badlun_sa = cpu_to_scr(SCRIPTB_BA (np, resel_bad_lun));
+ np->badlun_sa = cpu_to_scr(SCRIPTB_BA(np, resel_bad_lun));
for (i = 0 ; i < 64 ; i++) /* 64 luns/target, no less */
np->badluntbl[i] = cpu_to_scr(vtobus(&np->badlun_sa));
@@ -5866,7 +5800,7 @@ int sym_hcb_attach(struct sym_hcb *np, struct sym_fw *fw, struct sym_nvram *nvra
if (sym_snooptest (np)) {
printf("%s: CACHE INCORRECTLY CONFIGURED.\n", sym_name(np));
goto attach_failed;
- };
+ }
/*
* Sigh! we are done.
@@ -5883,9 +5817,9 @@ attach_failed:
void sym_hcb_free(struct sym_hcb *np)
{
SYM_QUEHEAD *qp;
- ccb_p cp;
- tcb_p tp;
- lcb_p lp;
+ struct sym_ccb *cp;
+ struct sym_tcb *tp;
+ struct sym_lcb *lp;
int target, lun;
if (np->scriptz0)
@@ -5902,14 +5836,10 @@ void sym_hcb_free(struct sym_hcb *np)
if (np->actccbs) {
while ((qp = sym_remque_head(&np->free_ccbq)) != 0) {
cp = sym_que_entry(qp, struct sym_ccb, link_ccbq);
- sym_data_dmamap_destroy(np, cp);
- sym_mfree_dma(cp->sns_bbuf, SYM_SNS_BBUF_LEN,
- "SNS_BBUF");
sym_mfree_dma(cp, sizeof(*cp), "CCB");
}
}
- if (np->ccbh)
- sym_mfree(np->ccbh, sizeof(ccb_p *)*CCB_HASH_SIZE, "CCBH");
+ kfree(np->ccbh);
if (np->badluntbl)
sym_mfree_dma(np->badluntbl, 256,"BADLUNTBL");
@@ -5917,21 +5847,17 @@ 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(np, tp, 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");
- if (lp->cb_tags)
- sym_mfree(lp->cb_tags, SYM_CONF_MAX_TASK,
- "CB_TAGS");
+ kfree(lp->cb_tags);
sym_mfree_dma(lp, sizeof(*lp), "LCB");
}
#if SYM_CONF_MAX_LUN > 1
- if (tp->lunmp)
- sym_mfree(tp->lunmp, SYM_CONF_MAX_LUN*sizeof(lcb_p),
- "LUNMP");
+ kfree(tp->lunmp);
#endif
}
if (np->targtbl)
diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.h b/drivers/scsi/sym53c8xx_2/sym_hipd.h
index e3509d4c879cb..a95cbe4b8e39f 100644
--- a/drivers/scsi/sym53c8xx_2/sym_hipd.h
+++ b/drivers/scsi/sym53c8xx_2/sym_hipd.h
@@ -188,36 +188,45 @@
/*
* Common definitions for both bus space based and legacy IO methods.
*/
-#define INB(r) INB_OFF(offsetof(struct sym_reg,r))
-#define INW(r) INW_OFF(offsetof(struct sym_reg,r))
-#define INL(r) INL_OFF(offsetof(struct sym_reg,r))
-#define OUTB(r, v) OUTB_OFF(offsetof(struct sym_reg,r), (v))
-#define OUTW(r, v) OUTW_OFF(offsetof(struct sym_reg,r), (v))
-#define OUTL(r, v) OUTL_OFF(offsetof(struct sym_reg,r), (v))
+#define INB_OFF(np, o) ioread8(np->s.ioaddr + (o))
+#define INW_OFF(np, o) ioread16(np->s.ioaddr + (o))
+#define INL_OFF(np, o) ioread32(np->s.ioaddr + (o))
-#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))
+#define OUTB_OFF(np, o, val) iowrite8((val), np->s.ioaddr + (o))
+#define OUTW_OFF(np, o, val) iowrite16((val), np->s.ioaddr + (o))
+#define OUTL_OFF(np, o, val) iowrite32((val), np->s.ioaddr + (o))
+
+#define INB(np, r) INB_OFF(np, offsetof(struct sym_reg, r))
+#define INW(np, r) INW_OFF(np, offsetof(struct sym_reg, r))
+#define INL(np, r) INL_OFF(np, offsetof(struct sym_reg, r))
+
+#define OUTB(np, r, v) OUTB_OFF(np, offsetof(struct sym_reg, r), (v))
+#define OUTW(np, r, v) OUTW_OFF(np, offsetof(struct sym_reg, r), (v))
+#define OUTL(np, r, v) OUTL_OFF(np, offsetof(struct sym_reg, r), (v))
+
+#define OUTONB(np, r, m) OUTB(np, r, INB(np, r) | (m))
+#define OUTOFFB(np, r, m) OUTB(np, r, INB(np, r) & ~(m))
+#define OUTONW(np, r, m) OUTW(np, r, INW(np, r) | (m))
+#define OUTOFFW(np, r, m) OUTW(np, r, INW(np, r) & ~(m))
+#define OUTONL(np, r, m) OUTL(np, r, INL(np, r) | (m))
+#define OUTOFFL(np, r, m) OUTL(np, r, INL(np, 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) \
+#define OUTL_DSP(np, v) \
do { \
MEMORY_WRITE_BARRIER(); \
- OUTL (nc_dsp, (v)); \
+ OUTL(np, nc_dsp, (v)); \
} while (0)
#define OUTONB_STD() \
do { \
MEMORY_WRITE_BARRIER(); \
- OUTONB (nc_dcntl, (STD|NOCOM)); \
+ OUTONB(np, nc_dcntl, (STD|NOCOM)); \
} while (0)
/*
@@ -321,7 +330,6 @@
* Host adapter miscellaneous flags.
*/
#define SYM_AVOID_BUS_RESET (1)
-#define SYM_SCAN_TARGETS_HILO (1<<1)
/*
* Misc.
@@ -334,20 +342,13 @@
* Gather negotiable parameters value
*/
struct sym_trans {
- u8 scsi_version;
- u8 spi_version;
u8 period;
u8 offset;
- u8 width;
- u8 options; /* PPR options */
-};
-
-struct sym_tinfo {
- struct sym_trans curr;
- struct sym_trans goal;
-#ifdef SYM_OPT_ANNOUNCE_TRANSFER_RATE
- struct sym_trans prev;
-#endif
+ unsigned int width:1;
+ unsigned int iu:1;
+ unsigned int dt:1;
+ unsigned int qas:1;
+ unsigned int check_nego:1;
};
/*
@@ -398,9 +399,9 @@ struct sym_tcb {
/*
* LUN table used by the C code.
*/
- lcb_p lun0p; /* LCB of LUN #0 (usual case) */
+ struct sym_lcb *lun0p; /* LCB of LUN #0 (usual case) */
#if SYM_CONF_MAX_LUN > 1
- lcb_p *lunmp; /* Other LCBs [1..MAX_LUN] */
+ struct sym_lcb **lunmp; /* Other LCBs [1..MAX_LUN] */
#endif
/*
@@ -423,16 +424,14 @@ struct sym_tcb {
struct sym_stcb s;
#endif
- /*
- * Transfer capabilities (SIP)
- */
- struct sym_tinfo tinfo;
+ /* Transfer goal */
+ struct sym_trans tgoal;
/*
* Keep track of the CCB used for the negotiation in order
* to ensure that only 1 negotiation is queued at a time.
*/
- ccb_p nego_cp; /* CCB used for the nego */
+ struct sym_ccb * nego_cp; /* CCB used for the nego */
/*
* Set when we want to reset the device.
@@ -520,10 +519,8 @@ struct sym_lcb {
* Optionnaly the driver can handle device queueing,
* and requeues internally command to redo.
*/
- SYM_QUEHEAD
- waiting_ccbq;
- SYM_QUEHEAD
- started_ccbq;
+ SYM_QUEHEAD waiting_ccbq;
+ SYM_QUEHEAD started_ccbq;
int num_sgood;
u_short started_tags;
u_short started_no_tag;
@@ -533,8 +530,8 @@ struct sym_lcb {
#ifdef SYM_OPT_LIMIT_COMMAND_REORDERING
/*
- * Optionnaly the driver can try to prevent SCSI
- * IOs from being too much reordering.
+ * Optionally the driver can try to prevent SCSI
+ * IOs from being reordered too much.
*/
u_char tags_si; /* Current index to tags sum */
u_short tags_sum[2]; /* Tags sum counters */
@@ -582,9 +579,9 @@ struct sym_pmc {
* LUN(s) > 0.
*/
#if SYM_CONF_MAX_LUN <= 1
-#define sym_lp(np, tp, lun) (!lun) ? (tp)->lun0p : NULL
+#define sym_lp(tp, lun) (!lun) ? (tp)->lun0p : NULL
#else
-#define sym_lp(np, tp, lun) \
+#define sym_lp(tp, lun) \
(!lun) ? (tp)->lun0p : (tp)->lunmp ? (tp)->lunmp[(lun)] : NULL
#endif
@@ -749,12 +746,10 @@ struct sym_ccb {
/*
* Pointer to CAM ccb and related stuff.
*/
- struct scsi_cmnd *cam_ccb; /* CAM scsiio ccb */
+ struct scsi_cmnd *cmd; /* CAM scsiio ccb */
u8 cdb_buf[16]; /* Copy of CDB */
- u8 *sns_bbuf; /* Bounce buffer for sense data */
-#ifndef SYM_SNS_BBUF_LEN
-#define SYM_SNS_BBUF_LEN (32)
-#endif
+#define SYM_SNS_BBUF_LEN 32
+ u8 sns_bbuf[SYM_SNS_BBUF_LEN]; /* Bounce buffer for sense data */
int data_len; /* Total data length */
int segments; /* Number of SG segments */
@@ -788,12 +783,6 @@ struct sym_ccb {
int sv_resid; /* Saved residual */
/*
- * O/S specific data structure.
- */
-#ifdef SYM_HAVE_SCCB
- struct sym_sccb s;
-#endif
- /*
* Other fields.
*/
u32 ccb_ba; /* BUS address of this CCB */
@@ -801,9 +790,8 @@ struct sym_ccb {
/* NO_TAG means no tag */
u_char target;
u_char lun;
- ccb_p link_ccbh; /* Host adapter CCB hash chain */
- SYM_QUEHEAD
- link_ccbq; /* Link to free/busy CCB queue */
+ struct sym_ccb *link_ccbh; /* Host adapter CCB hash chain */
+ 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
@@ -812,8 +800,7 @@ struct sym_ccb {
int ext_sg; /* Extreme data pointer, used */
int ext_ofs; /* to calculate the residual. */
#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
- SYM_QUEHEAD
- link2_ccbq; /* Link for device queueing */
+ SYM_QUEHEAD link2_ccbq; /* Link for device queueing */
u_char started; /* CCB queued to the squeue */
#endif
u_char to_abort; /* Want this IO to be aborted */
@@ -830,6 +817,8 @@ struct sym_ccb {
#define sym_goalp(cp) (cp->goalp)
#endif
+typedef struct device *m_pool_ident_t;
+
/*
* Host Control Block
*/
@@ -1005,7 +994,7 @@ struct sym_hcb {
/*
* CCB lists and queue.
*/
- ccb_p *ccbh; /* CCBs hashed by DSA value */
+ struct sym_ccb **ccbh; /* CCBs hashed by DSA value */
/* CCB_HASH_SIZE lists of CCBs */
SYM_QUEHEAD free_ccbq; /* Queue of available CCBs */
SYM_QUEHEAD busy_ccbq; /* Queue of busy CCBs */
@@ -1037,7 +1026,7 @@ struct sym_hcb {
#ifdef SYM_CONF_IARB_SUPPORT
u_short iarb_max; /* Max. # consecutive IARB hints*/
u_short iarb_count; /* Actual # of these hints */
- ccb_p last_cp;
+ struct sym_ccb * last_cp;
#endif
/*
@@ -1068,41 +1057,31 @@ struct sym_hcb {
/*
* FIRMWARES (sym_fw.c)
*/
-struct sym_fw * sym_find_firmware(struct sym_pci_chip *chip);
-void sym_fw_bind_script (struct sym_hcb *np, u32 *start, int len);
+struct sym_fw * sym_find_firmware(struct sym_chip *chip);
+void sym_fw_bind_script(struct sym_hcb *np, u32 *start, int len);
/*
* Driver methods called from O/S specific code.
*/
char *sym_driver_name(void);
-void sym_print_xerr(ccb_p cp, int x_status);
+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_pci_chip *
-sym_lookup_pci_chip_table (u_short device_id, u_char revision);
-void sym_put_start_queue(struct sym_hcb *np, ccb_p cp);
+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, lcb_p lp, int maxn);
+void sym_start_next_ccbs(struct sym_hcb *np, struct sym_lcb *lp, int maxn);
#endif
-void sym_start_up (struct sym_hcb *np, int reason);
-void sym_interrupt (struct sym_hcb *np);
+void sym_start_up(struct sym_hcb *np, int reason);
+void sym_interrupt(struct sym_hcb *np);
int sym_clear_tasks(struct sym_hcb *np, int cam_status, int target, int lun, int task);
-ccb_p sym_get_ccb (struct sym_hcb *np, u_char tn, u_char ln, u_char tag_order);
-void sym_free_ccb (struct sym_hcb *np, ccb_p cp);
-lcb_p sym_alloc_lcb (struct sym_hcb *np, u_char tn, u_char ln);
-int sym_queue_scsiio(struct sym_hcb *np, struct scsi_cmnd *csio, ccb_p cp);
+struct sym_ccb *sym_get_ccb(struct sym_hcb *np, struct scsi_cmnd *cmd, u_char tag_order);
+void sym_free_ccb(struct sym_hcb *np, struct sym_ccb *cp);
+struct sym_lcb *sym_alloc_lcb(struct sym_hcb *np, u_char tn, u_char ln);
+int sym_queue_scsiio(struct sym_hcb *np, struct scsi_cmnd *csio, struct sym_ccb *cp);
int sym_abort_scsiio(struct sym_hcb *np, struct scsi_cmnd *ccb, int timed_out);
-int sym_abort_ccb(struct sym_hcb *np, ccb_p cp, int timed_out);
int sym_reset_scsi_target(struct sym_hcb *np, int target);
void sym_hcb_free(struct sym_hcb *np);
-int sym_hcb_attach(struct sym_hcb *np, struct sym_fw *fw, struct sym_nvram *nvram);
-
-/*
- * Optionnaly, the driver may provide a function
- * to announce transfer rate changes.
- */
-#ifdef SYM_OPT_ANNOUNCE_TRANSFER_RATE
-void sym_announce_transfer_rate(struct sym_hcb *np, int target);
-#endif
+int sym_hcb_attach(struct Scsi_Host *shost, struct sym_fw *fw, struct sym_nvram *nvram);
/*
* Build a scatter/gather entry.
@@ -1169,7 +1148,7 @@ static inline void sym_setup_data_pointers(struct sym_hcb *np,
case CAM_DIR_UNKNOWN:
#endif
case CAM_DIR_OUT:
- goalp = SCRIPTA_BA (np, data_out2) + 8;
+ 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);
@@ -1182,7 +1161,7 @@ static inline void sym_setup_data_pointers(struct sym_hcb *np,
#endif
case CAM_DIR_IN:
cp->host_flags |= HF_DATA_IN;
- goalp = SCRIPTA_BA (np, data_in2) + 8;
+ goalp = SCRIPTA_BA(np, data_in2) + 8;
lastp = goalp - 8 - (cp->segments * (2*4));
break;
case CAM_DIR_NONE:
@@ -1190,7 +1169,7 @@ static inline void sym_setup_data_pointers(struct sym_hcb *np,
#ifdef SYM_OPT_HANDLE_DIR_UNKNOWN
cp->host_flags |= HF_DATA_IN;
#endif
- lastp = goalp = SCRIPTB_BA (np, no_data);
+ lastp = goalp = SCRIPTB_BA(np, no_data);
break;
}
@@ -1207,7 +1186,7 @@ static inline void sym_setup_data_pointers(struct sym_hcb *np,
* If direction is unknown, start at data_io.
*/
if (dir == CAM_DIR_UNKNOWN)
- cp->phys.head.savep = cpu_to_scr(SCRIPTB_BA (np, data_io));
+ cp->phys.head.savep = cpu_to_scr(SCRIPTB_BA(np, data_io));
#endif
}
@@ -1215,6 +1194,17 @@ static inline void sym_setup_data_pointers(struct sym_hcb *np,
* MEMORY ALLOCATOR.
*/
+#define SYM_MEM_PAGE_ORDER 0 /* 1 PAGE maximum */
+#define SYM_MEM_CLUSTER_SHIFT (PAGE_SHIFT+SYM_MEM_PAGE_ORDER)
+#define SYM_MEM_FREE_UNUSED /* Free unused pages immediately */
+
+#define SYM_MEM_WARN 1 /* Warn on failed operations */
+
+#define sym_get_mem_cluster() \
+ (void *) __get_free_pages(GFP_ATOMIC, SYM_MEM_PAGE_ORDER)
+#define sym_free_mem_cluster(p) \
+ free_pages((unsigned long)p, SYM_MEM_PAGE_ORDER)
+
/*
* Link between free memory chunks of a given size.
*/
@@ -1228,11 +1218,8 @@ typedef struct sym_m_link {
*/
typedef struct sym_m_vtob { /* Virtual to Bus address translation */
struct sym_m_vtob *next;
-#ifdef SYM_HAVE_M_SVTOB
- struct sym_m_svtob s; /* OS specific data structure */
-#endif
- m_addr_t vaddr; /* Virtual address */
- m_addr_t baddr; /* Bus physical address */
+ void *vaddr; /* Virtual address */
+ dma_addr_t baddr; /* Bus physical address */
} *m_vtob_p;
/* Hash this stuff a bit to speed up translations */
@@ -1240,7 +1227,7 @@ typedef struct sym_m_vtob { /* Virtual to Bus address translation */
#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)) >> SYM_MEM_CLUSTER_SHIFT) & VTOB_HASH_MASK)
+ ((((unsigned long)(m)) >> SYM_MEM_CLUSTER_SHIFT) & VTOB_HASH_MASK)
/*
* Memory pool of a given kind.
@@ -1253,15 +1240,12 @@ typedef struct sym_m_vtob { /* Virtual to Bus address translation */
*/
typedef struct sym_m_pool {
m_pool_ident_t dev_dmat; /* Identifies the pool (see above) */
- m_addr_t (*get_mem_cluster)(struct sym_m_pool *);
+ void * (*get_mem_cluster)(struct sym_m_pool *);
#ifdef SYM_MEM_FREE_UNUSED
- void (*free_mem_cluster)(struct sym_m_pool *, m_addr_t);
+ void (*free_mem_cluster)(struct sym_m_pool *, void *);
#endif
#define M_GET_MEM_CLUSTER() mp->get_mem_cluster(mp)
#define M_FREE_MEM_CLUSTER(p) mp->free_mem_cluster(mp, p)
-#ifdef SYM_HAVE_M_SPOOL
- struct sym_m_spool s; /* OS specific data structure */
-#endif
int nump;
m_vtob_p vtob[VTOB_HASH_SIZE];
struct sym_m_pool *next;
@@ -1269,19 +1253,12 @@ typedef struct sym_m_pool {
} *m_pool_p;
/*
- * Alloc and free non DMAable memory.
- */
-void sym_mfree_unlocked(void *ptr, int size, char *name);
-void *sym_calloc_unlocked(int size, char *name);
-
-/*
* Alloc, free and translate addresses to bus physical
* for DMAable memory.
*/
-void *__sym_calloc_dma_unlocked(m_pool_ident_t dev_dmat, int size, char *name);
-void
-__sym_mfree_dma_unlocked(m_pool_ident_t dev_dmat, void *m,int size, char *name);
-u32 __vtobus_unlocked(m_pool_ident_t dev_dmat, void *m);
+void *__sym_calloc_dma(m_pool_ident_t dev_dmat, int size, char *name);
+void __sym_mfree_dma(m_pool_ident_t dev_dmat, void *m, int size, char *name);
+dma_addr_t __vtobus(m_pool_ident_t dev_dmat, void *m);
/*
* Verbs used by the driver code for DMAable memory handling.
@@ -1295,15 +1272,33 @@ u32 __vtobus_unlocked(m_pool_ident_t dev_dmat, void *m);
__sym_mfree_dma(np->bus_dmat, _uvptv_(p), l, n)
#define sym_calloc_dma(l, n) _sym_calloc_dma(np, l, n)
#define sym_mfree_dma(p, l, n) _sym_mfree_dma(np, p, l, n)
-#define _vtobus(np, p) __vtobus(np->bus_dmat, _uvptv_(p))
-#define vtobus(p) _vtobus(np, p)
+#define vtobus(p) __vtobus(np->bus_dmat, _uvptv_(p))
/*
- * Override some function names.
+ * We have to provide the driver memory allocator with methods for
+ * it to maintain virtual to bus physical address translations.
*/
-#define PRINT_ADDR sym_print_addr
-#define PRINT_TARGET sym_print_target
-#define PRINT_LUN sym_print_lun
-#define UDELAY sym_udelay
+
+#define sym_m_pool_match(mp_id1, mp_id2) (mp_id1 == mp_id2)
+
+static __inline void *sym_m_get_dma_mem_cluster(m_pool_p mp, m_vtob_p vbp)
+{
+ void *vaddr = NULL;
+ dma_addr_t baddr = 0;
+
+ vaddr = dma_alloc_coherent(mp->dev_dmat, SYM_MEM_CLUSTER_SIZE, &baddr,
+ GFP_ATOMIC);
+ if (vaddr) {
+ vbp->vaddr = vaddr;
+ vbp->baddr = baddr;
+ }
+ return vaddr;
+}
+
+static __inline void sym_m_free_dma_mem_cluster(m_pool_p mp, m_vtob_p vbp)
+{
+ dma_free_coherent(mp->dev_dmat, SYM_MEM_CLUSTER_SIZE, vbp->vaddr,
+ vbp->baddr);
+}
#endif /* SYM_HIPD_H */
diff --git a/drivers/scsi/sym53c8xx_2/sym_malloc.c b/drivers/scsi/sym53c8xx_2/sym_malloc.c
index 01f380a2d28f8..a34d403ccc6c4 100644
--- a/drivers/scsi/sym53c8xx_2/sym_malloc.c
+++ b/drivers/scsi/sym53c8xx_2/sym_malloc.c
@@ -66,7 +66,7 @@ static void *___sym_malloc(m_pool_p mp, int size)
int i = 0;
int s = (1 << SYM_MEM_SHIFT);
int j;
- m_addr_t a;
+ void *a;
m_link_p h = mp->h;
if (size > SYM_MEM_CLUSTER_SIZE)
@@ -88,7 +88,7 @@ static void *___sym_malloc(m_pool_p mp, int size)
++j;
s <<= 1;
}
- a = (m_addr_t) h[j].next;
+ a = h[j].next;
if (a) {
h[j].next = h[j].next->next;
while (j > i) {
@@ -101,7 +101,7 @@ static void *___sym_malloc(m_pool_p mp, int size)
#ifdef DEBUG
printf("___sym_malloc(%d) = %p\n", size, (void *) a);
#endif
- return (void *) a;
+ return a;
}
/*
@@ -112,7 +112,7 @@ static void ___sym_mfree(m_pool_p mp, void *ptr, int size)
int i = 0;
int s = (1 << SYM_MEM_SHIFT);
m_link_p q;
- m_addr_t a, b;
+ unsigned long a, b;
m_link_p h = mp->h;
#ifdef DEBUG
@@ -127,12 +127,12 @@ static void ___sym_mfree(m_pool_p mp, void *ptr, int size)
++i;
}
- a = (m_addr_t) ptr;
+ a = (unsigned long)ptr;
while (1) {
if (s == SYM_MEM_CLUSTER_SIZE) {
#ifdef SYM_MEM_FREE_UNUSED
- M_FREE_MEM_CLUSTER(a);
+ M_FREE_MEM_CLUSTER((void *)a);
#else
((m_link_p) a)->next = h[i].next;
h[i].next = (m_link_p) a;
@@ -194,58 +194,40 @@ static void __sym_mfree(m_pool_p mp, void *ptr, int size, char *name)
* With DMA abstraction, we use functions (methods), to
* distinguish between non DMAable memory and DMAable memory.
*/
-static m_addr_t ___mp0_get_mem_cluster(m_pool_p mp)
+static void *___mp0_get_mem_cluster(m_pool_p mp)
{
- m_addr_t m = (m_addr_t) sym_get_mem_cluster();
+ void *m = sym_get_mem_cluster();
if (m)
++mp->nump;
return m;
}
#ifdef SYM_MEM_FREE_UNUSED
-static void ___mp0_free_mem_cluster(m_pool_p mp, m_addr_t m)
+static void ___mp0_free_mem_cluster(m_pool_p mp, void *m)
{
sym_free_mem_cluster(m);
--mp->nump;
}
-#endif
-
-#ifdef SYM_MEM_FREE_UNUSED
-static struct sym_m_pool mp0 =
- {NULL, ___mp0_get_mem_cluster, ___mp0_free_mem_cluster};
#else
-static struct sym_m_pool mp0 =
- {NULL, ___mp0_get_mem_cluster};
+#define ___mp0_free_mem_cluster NULL
#endif
-/*
- * Actual memory allocation routine for non-DMAed memory.
- */
-void *sym_calloc_unlocked(int size, char *name)
-{
- void *m;
- m = __sym_calloc(&mp0, size, name);
- return m;
-}
-
-/*
- * Its counter-part.
- */
-void sym_mfree_unlocked(void *ptr, int size, char *name)
-{
- __sym_mfree(&mp0, ptr, size, name);
-}
+static struct sym_m_pool mp0 = {
+ NULL,
+ ___mp0_get_mem_cluster,
+ ___mp0_free_mem_cluster
+};
/*
* Methods that maintains DMAable pools according to user allocations.
* New pools are created on the fly when a new pool id is provided.
* They are deleted on the fly when they get emptied.
*/
-/* Get a memory cluster that matches the DMA contraints of a given pool */
-static m_addr_t ___get_dma_mem_cluster(m_pool_p mp)
+/* Get a memory cluster that matches the DMA constraints of a given pool */
+static void * ___get_dma_mem_cluster(m_pool_p mp)
{
m_vtob_p vbp;
- m_addr_t vaddr;
+ void *vaddr;
vbp = __sym_calloc(&mp0, sizeof(*vbp), "VTOB");
if (!vbp)
@@ -257,16 +239,15 @@ static m_addr_t ___get_dma_mem_cluster(m_pool_p mp)
vbp->next = mp->vtob[hc];
mp->vtob[hc] = vbp;
++mp->nump;
- return (m_addr_t) vaddr;
}
return vaddr;
out_err:
- return 0;
+ return NULL;
}
#ifdef SYM_MEM_FREE_UNUSED
/* Free a memory cluster and associated resources for DMA */
-static void ___free_dma_mem_cluster(m_pool_p mp, m_addr_t m)
+static void ___free_dma_mem_cluster(m_pool_p mp, void *m)
{
m_vtob_p *vbpp, vbp;
int hc = VTOB_HASH_CODE(m);
@@ -297,23 +278,17 @@ static __inline m_pool_p ___get_dma_pool(m_pool_ident_t dev_dmat)
/* Create a new memory DMAable pool (when fetch failed) */
static m_pool_p ___cre_dma_pool(m_pool_ident_t dev_dmat)
{
- m_pool_p mp = NULL;
-
- mp = __sym_calloc(&mp0, sizeof(*mp), "MPOOL");
+ m_pool_p mp = __sym_calloc(&mp0, sizeof(*mp), "MPOOL");
if (mp) {
mp->dev_dmat = dev_dmat;
- if (!sym_m_create_dma_mem_tag(mp)) {
- mp->get_mem_cluster = ___get_dma_mem_cluster;
+ mp->get_mem_cluster = ___get_dma_mem_cluster;
#ifdef SYM_MEM_FREE_UNUSED
- mp->free_mem_cluster = ___free_dma_mem_cluster;
+ mp->free_mem_cluster = ___free_dma_mem_cluster;
#endif
- mp->next = mp0.next;
- mp0.next = mp;
- return mp;
- }
+ mp->next = mp0.next;
+ mp0.next = mp;
+ return mp;
}
- if (mp)
- __sym_mfree(&mp0, mp, sizeof(*mp), "MPOOL");
return NULL;
}
@@ -327,68 +302,81 @@ static void ___del_dma_pool(m_pool_p p)
pp = &(*pp)->next;
if (*pp) {
*pp = (*pp)->next;
- sym_m_delete_dma_mem_tag(p);
__sym_mfree(&mp0, p, sizeof(*p), "MPOOL");
}
}
#endif
+/* This lock protects only the memory allocation/free. */
+static DEFINE_SPINLOCK(sym53c8xx_lock);
+
/*
* Actual allocator for DMAable memory.
*/
-void *__sym_calloc_dma_unlocked(m_pool_ident_t dev_dmat, int size, char *name)
+void *__sym_calloc_dma(m_pool_ident_t dev_dmat, int size, char *name)
{
+ unsigned long flags;
m_pool_p mp;
void *m = NULL;
+ spin_lock_irqsave(&sym53c8xx_lock, flags);
mp = ___get_dma_pool(dev_dmat);
if (!mp)
mp = ___cre_dma_pool(dev_dmat);
- if (mp)
- m = __sym_calloc(mp, size, name);
+ if (!mp)
+ goto out;
+ m = __sym_calloc(mp, size, name);
#ifdef SYM_MEM_FREE_UNUSED
- if (mp && !mp->nump)
+ if (!mp->nump)
___del_dma_pool(mp);
#endif
+ out:
+ spin_unlock_irqrestore(&sym53c8xx_lock, flags);
return m;
}
-/*
- * Its counter-part.
- */
-void
-__sym_mfree_dma_unlocked(m_pool_ident_t dev_dmat, void *m, int size, char *name)
+void __sym_mfree_dma(m_pool_ident_t dev_dmat, void *m, int size, char *name)
{
+ unsigned long flags;
m_pool_p mp;
+ spin_lock_irqsave(&sym53c8xx_lock, flags);
mp = ___get_dma_pool(dev_dmat);
- if (mp)
- __sym_mfree(mp, m, size, name);
+ if (!mp)
+ goto out;
+ __sym_mfree(mp, m, size, name);
#ifdef SYM_MEM_FREE_UNUSED
- if (mp && !mp->nump)
+ if (!mp->nump)
___del_dma_pool(mp);
#endif
+ out:
+ spin_unlock_irqrestore(&sym53c8xx_lock, flags);
}
/*
* Actual virtual to bus physical address translator
* for 32 bit addressable DMAable memory.
*/
-u32 __vtobus_unlocked(m_pool_ident_t dev_dmat, void *m)
+dma_addr_t __vtobus(m_pool_ident_t dev_dmat, void *m)
{
+ unsigned long flags;
m_pool_p mp;
int hc = VTOB_HASH_CODE(m);
m_vtob_p vp = NULL;
- m_addr_t a = ((m_addr_t) m) & ~SYM_MEM_CLUSTER_MASK;
+ void *a = (void *)((unsigned long)m & ~SYM_MEM_CLUSTER_MASK);
+ dma_addr_t b;
+ spin_lock_irqsave(&sym53c8xx_lock, flags);
mp = ___get_dma_pool(dev_dmat);
if (mp) {
vp = mp->vtob[hc];
- while (vp && (m_addr_t) vp->vaddr != a)
+ while (vp && vp->vaddr != a)
vp = vp->next;
}
if (!vp)
panic("sym: VTOBUS FAILED!\n");
- return (u32)(vp ? vp->baddr + (((m_addr_t) m) - a) : 0);
+ b = vp->baddr + (m - a);
+ spin_unlock_irqrestore(&sym53c8xx_lock, flags);
+ return b;
}
diff --git a/drivers/scsi/sym53c8xx_2/sym_misc.c b/drivers/scsi/sym53c8xx_2/sym_misc.c
deleted file mode 100644
index 0b678ae73acca..0000000000000
--- a/drivers/scsi/sym53c8xx_2/sym_misc.c
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Device driver for the SYMBIOS/LSILOGIC 53C8XX and 53C1010 family
- * of PCI-SCSI IO processors.
- *
- * Copyright (C) 1999-2001 Gerard Roudier <groudier@free.fr>
- *
- * This driver is derived from the Linux sym53c8xx driver.
- * Copyright (C) 1998-2000 Gerard Roudier
- *
- * The sym53c8xx driver is derived from the ncr53c8xx driver that had been
- * a port of the FreeBSD ncr driver to Linux-1.2.13.
- *
- * The original ncr driver has been written for 386bsd and FreeBSD by
- * Wolfgang Stanglmeier <wolf@cologne.de>
- * Stefan Esser <se@mi.Uni-Koeln.de>
- * Copyright (C) 1994 Wolfgang Stanglmeier
- *
- * Other major contributions:
- *
- * NVRAM detection and reading.
- * Copyright (C) 1997 Richard Waltham <dormouse@farsrobt.demon.co.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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include "sym_glue.h"
-
-#ifdef SYM_OPT_ANNOUNCE_TRANSFER_RATE
-/*
- * Announce transfer rate if anything changed since last announcement.
- */
-void sym_announce_transfer_rate(struct sym_hcb *np, int target)
-{
- tcb_p tp = &np->target[target];
-
-#define __tprev tp->tinfo.prev
-#define __tcurr tp->tinfo.curr
-
- if (__tprev.options == __tcurr.options &&
- __tprev.width == __tcurr.width &&
- __tprev.offset == __tcurr.offset &&
- !(__tprev.offset && __tprev.period != __tcurr.period))
- return;
-
- __tprev.options = __tcurr.options;
- __tprev.width = __tcurr.width;
- __tprev.offset = __tcurr.offset;
- __tprev.period = __tcurr.period;
-
- if (__tcurr.offset && __tcurr.period) {
- u_int period, f10, mb10;
- char *scsi;
-
- period = f10 = mb10 = 0;
- scsi = "FAST-5";
-
- if (__tcurr.period <= 9) {
- scsi = "FAST-80";
- period = 125;
- mb10 = 1600;
- }
- else {
- if (__tcurr.period <= 11) {
- scsi = "FAST-40";
- period = 250;
- if (__tcurr.period == 11)
- period = 303;
- }
- else if (__tcurr.period < 25) {
- scsi = "FAST-20";
- if (__tcurr.period == 12)
- period = 500;
- }
- else if (__tcurr.period <= 50) {
- scsi = "FAST-10";
- }
- if (!period)
- period = 40 * __tcurr.period;
- f10 = 100000 << (__tcurr.width ? 1 : 0);
- mb10 = (f10 + period/2) / period;
- }
- printf_info (
- "%s:%d: %s %sSCSI %d.%d MB/s %s%s%s (%d.%d ns, offset %d)\n",
- sym_name(np), target, scsi, __tcurr.width? "WIDE " : "",
- mb10/10, mb10%10,
- (__tcurr.options & PPR_OPT_DT) ? "DT" : "ST",
- (__tcurr.options & PPR_OPT_IU) ? " IU" : "",
- (__tcurr.options & PPR_OPT_QAS) ? " QAS" : "",
- period/10, period%10, __tcurr.offset);
- }
- else
- printf_info ("%s:%d: %sasynchronous.\n",
- sym_name(np), target, __tcurr.width? "wide " : "");
-}
-#undef __tprev
-#undef __tcurr
-#endif /* SYM_OPT_ANNOUNCE_TRANSFER_RATE */
diff --git a/drivers/scsi/sym53c8xx_2/sym_nvram.c b/drivers/scsi/sym53c8xx_2/sym_nvram.c
index 0809437706e83..1b721e3ec5202 100644
--- a/drivers/scsi/sym53c8xx_2/sym_nvram.c
+++ b/drivers/scsi/sym53c8xx_2/sym_nvram.c
@@ -47,7 +47,7 @@ static u_char Tekram_boot_delay[7] = {3, 5, 10, 20, 30, 60, 120};
/*
* Get host setup from NVRAM.
*/
-void sym_nvram_setup_host(struct sym_hcb *np, struct sym_nvram *nvram)
+void sym_nvram_setup_host(struct Scsi_Host *shost, struct sym_hcb *np, struct sym_nvram *nvram)
{
/*
* Get parity checking, host ID, verbose mode
@@ -61,7 +61,7 @@ void sym_nvram_setup_host(struct sym_hcb *np, struct sym_nvram *nvram)
if (nvram->data.Symbios.flags & SYMBIOS_VERBOSE_MSGS)
np->verbose += 1;
if (nvram->data.Symbios.flags1 & SYMBIOS_SCAN_HI_LO)
- np->usrflags |= SYM_SCAN_TARGETS_HILO;
+ shost->reverse_ordering = 1;
if (nvram->data.Symbios.flags2 & SYMBIOS_AVOID_BUS_RESET)
np->usrflags |= SYM_AVOID_BUS_RESET;
break;
@@ -253,7 +253,7 @@ static void sym_display_Tekram_nvram(struct sym_device *np, Tekram_nvram *nvram)
static void S24C16_set_bit(struct sym_device *np, u_char write_bit, u_char *gpreg,
int bit_mode)
{
- UDELAY (5);
+ udelay(5);
switch (bit_mode) {
case SET_BIT:
*gpreg |= write_bit;
@@ -269,8 +269,8 @@ static void S24C16_set_bit(struct sym_device *np, u_char write_bit, u_char *gpre
break;
}
- OUTB (nc_gpreg, *gpreg);
- UDELAY (5);
+ OUTB(np, nc_gpreg, *gpreg);
+ udelay(5);
}
/*
@@ -303,7 +303,7 @@ static void S24C16_do_bit(struct sym_device *np, u_char *read_bit, u_char write_
S24C16_set_bit(np, write_bit, gpreg, SET_BIT);
S24C16_set_bit(np, 0, gpreg, SET_CLK);
if (read_bit)
- *read_bit = INB (nc_gpreg);
+ *read_bit = INB(np, nc_gpreg);
S24C16_set_bit(np, 0, gpreg, CLR_CLK);
S24C16_set_bit(np, 0, gpreg, CLR_BIT);
}
@@ -315,9 +315,9 @@ static void S24C16_do_bit(struct sym_device *np, u_char *read_bit, u_char write_
static void S24C16_write_ack(struct sym_device *np, u_char write_bit, u_char *gpreg,
u_char *gpcntl)
{
- OUTB (nc_gpcntl, *gpcntl & 0xfe);
+ OUTB(np, nc_gpcntl, *gpcntl & 0xfe);
S24C16_do_bit(np, NULL, write_bit, gpreg);
- OUTB (nc_gpcntl, *gpcntl);
+ OUTB(np, nc_gpcntl, *gpcntl);
}
/*
@@ -327,9 +327,9 @@ static void S24C16_write_ack(struct sym_device *np, u_char write_bit, u_char *gp
static void S24C16_read_ack(struct sym_device *np, u_char *read_bit, u_char *gpreg,
u_char *gpcntl)
{
- OUTB (nc_gpcntl, *gpcntl | 0x01);
+ OUTB(np, nc_gpcntl, *gpcntl | 0x01);
S24C16_do_bit(np, read_bit, 1, gpreg);
- OUTB (nc_gpcntl, *gpcntl);
+ OUTB(np, nc_gpcntl, *gpcntl);
}
/*
@@ -379,13 +379,13 @@ static int sym_write_S24C16_nvram(struct sym_device *np, int offset,
int x;
/* save current state of GPCNTL and GPREG */
- old_gpreg = INB (nc_gpreg);
- old_gpcntl = INB (nc_gpcntl);
+ old_gpreg = INB(np, nc_gpreg);
+ old_gpcntl = INB(np, nc_gpcntl);
gpcntl = old_gpcntl & 0x1c;
/* set up GPREG & GPCNTL to set GPIO0 and GPIO1 in to known state */
- OUTB (nc_gpreg, old_gpreg);
- OUTB (nc_gpcntl, gpcntl);
+ OUTB(np, nc_gpreg, old_gpreg);
+ OUTB(np, nc_gpcntl, gpcntl);
/* this is to set NVRAM into a known state with GPIO0/1 both low */
gpreg = old_gpreg;
@@ -414,8 +414,8 @@ static int sym_write_S24C16_nvram(struct sym_device *np, int offset,
}
/* return GPIO0/1 to original states after having accessed NVRAM */
- OUTB (nc_gpcntl, old_gpcntl);
- OUTB (nc_gpreg, old_gpreg);
+ OUTB(np, nc_gpcntl, old_gpcntl);
+ OUTB(np, nc_gpreg, old_gpreg);
return 0;
}
@@ -433,13 +433,13 @@ static int sym_read_S24C16_nvram(struct sym_device *np, int offset, u_char *data
int x;
/* save current state of GPCNTL and GPREG */
- old_gpreg = INB (nc_gpreg);
- old_gpcntl = INB (nc_gpcntl);
+ old_gpreg = INB(np, nc_gpreg);
+ old_gpcntl = INB(np, nc_gpcntl);
gpcntl = old_gpcntl & 0x1c;
/* set up GPREG & GPCNTL to set GPIO0 and GPIO1 in to known state */
- OUTB (nc_gpreg, old_gpreg);
- OUTB (nc_gpcntl, gpcntl);
+ OUTB(np, nc_gpreg, old_gpreg);
+ OUTB(np, nc_gpcntl, gpcntl);
/* this is to set NVRAM into a known state with GPIO0/1 both low */
gpreg = old_gpreg;
@@ -475,7 +475,7 @@ static int sym_read_S24C16_nvram(struct sym_device *np, int offset, u_char *data
/* now set up GPIO0 for inputting data */
gpcntl |= 0x01;
- OUTB (nc_gpcntl, gpcntl);
+ OUTB(np, nc_gpcntl, gpcntl);
/* input all requested data - only part of total NVRAM */
for (x = 0; x < len; x++)
@@ -483,13 +483,13 @@ static int sym_read_S24C16_nvram(struct sym_device *np, int offset, u_char *data
/* finally put NVRAM back in inactive mode */
gpcntl &= 0xfe;
- OUTB (nc_gpcntl, gpcntl);
+ OUTB(np, nc_gpcntl, gpcntl);
S24C16_stop(np, &gpreg);
retv = 0;
out:
/* return GPIO0/1 to original states after having accessed NVRAM */
- OUTB (nc_gpcntl, old_gpcntl);
- OUTB (nc_gpreg, old_gpreg);
+ OUTB(np, nc_gpcntl, old_gpcntl);
+ OUTB(np, nc_gpreg, old_gpreg);
return retv;
}
@@ -546,9 +546,9 @@ static int sym_read_Symbios_nvram(struct sym_device *np, Symbios_nvram *nvram)
*/
static void T93C46_Clk(struct sym_device *np, u_char *gpreg)
{
- OUTB (nc_gpreg, *gpreg | 0x04);
- UDELAY (2);
- OUTB (nc_gpreg, *gpreg);
+ OUTB(np, nc_gpreg, *gpreg | 0x04);
+ udelay(2);
+ OUTB(np, nc_gpreg, *gpreg);
}
/*
@@ -556,9 +556,9 @@ static void T93C46_Clk(struct sym_device *np, u_char *gpreg)
*/
static void T93C46_Read_Bit(struct sym_device *np, u_char *read_bit, u_char *gpreg)
{
- UDELAY (2);
+ udelay(2);
T93C46_Clk(np, gpreg);
- *read_bit = INB (nc_gpreg);
+ *read_bit = INB(np, nc_gpreg);
}
/*
@@ -573,8 +573,8 @@ static void T93C46_Write_Bit(struct sym_device *np, u_char write_bit, u_char *gp
*gpreg |= 0x10;
- OUTB (nc_gpreg, *gpreg);
- UDELAY (2);
+ OUTB(np, nc_gpreg, *gpreg);
+ udelay(2);
T93C46_Clk(np, gpreg);
}
@@ -585,8 +585,8 @@ static void T93C46_Write_Bit(struct sym_device *np, u_char write_bit, u_char *gp
static void T93C46_Stop(struct sym_device *np, u_char *gpreg)
{
*gpreg &= 0xef;
- OUTB (nc_gpreg, *gpreg);
- UDELAY (2);
+ OUTB(np, nc_gpreg, *gpreg);
+ udelay(2);
T93C46_Clk(np, gpreg);
}
@@ -603,7 +603,7 @@ static void T93C46_Send_Command(struct sym_device *np, u_short write_data,
for (x = 0; x < 9; x++)
T93C46_Write_Bit(np, (u_char) (write_data >> (8 - x)), gpreg);
- *read_bit = INB (nc_gpreg);
+ *read_bit = INB(np, nc_gpreg);
}
/*
@@ -657,23 +657,23 @@ static int sym_read_T93C46_nvram(struct sym_device *np, Tekram_nvram *nvram)
int retv = 1;
/* save current state of GPCNTL and GPREG */
- old_gpreg = INB (nc_gpreg);
- old_gpcntl = INB (nc_gpcntl);
+ old_gpreg = INB(np, nc_gpreg);
+ old_gpcntl = INB(np, nc_gpcntl);
/* set up GPREG & GPCNTL to set GPIO0/1/2/4 in to known state, 0 in,
1/2/4 out */
gpreg = old_gpreg & 0xe9;
- OUTB (nc_gpreg, gpreg);
+ OUTB(np, nc_gpreg, gpreg);
gpcntl = (old_gpcntl & 0xe9) | 0x09;
- OUTB (nc_gpcntl, gpcntl);
+ OUTB(np, nc_gpcntl, gpcntl);
/* input all of NVRAM, 64 words */
retv = T93C46_Read_Data(np, (u_short *) nvram,
sizeof(*nvram) / sizeof(short), &gpreg);
/* return GPIO0/1/2/4 to original states after having accessed NVRAM */
- OUTB (nc_gpcntl, old_gpcntl);
- OUTB (nc_gpreg, old_gpreg);
+ OUTB(np, nc_gpcntl, old_gpcntl);
+ OUTB(np, nc_gpreg, old_gpreg);
return retv;
}
@@ -755,3 +755,17 @@ int sym_read_nvram(struct sym_device *np, struct sym_nvram *nvp)
}
return nvp->type;
}
+
+char *sym_nvram_type(struct sym_nvram *nvp)
+{
+ switch (nvp->type) {
+ case SYM_SYMBIOS_NVRAM:
+ return "Symbios NVRAM";
+ case SYM_TEKRAM_NVRAM:
+ return "Tekram NVRAM";
+ case SYM_PARISC_PDC:
+ return "PA-RISC Firmware";
+ default:
+ return "No NVRAM";
+ }
+}
diff --git a/drivers/scsi/sym53c8xx_2/sym_nvram.h b/drivers/scsi/sym53c8xx_2/sym_nvram.h
index 9572f87b599af..1538bede52773 100644
--- a/drivers/scsi/sym53c8xx_2/sym_nvram.h
+++ b/drivers/scsi/sym53c8xx_2/sym_nvram.h
@@ -40,7 +40,7 @@
#ifndef SYM_NVRAM_H
#define SYM_NVRAM_H
-#include "sym_conf.h"
+#include "sym53c8xx.h"
/*
* Symbios NVRAM data format
@@ -193,17 +193,22 @@ struct sym_nvram {
};
#if SYM_CONF_NVRAM_SUPPORT
-void sym_nvram_setup_host (struct sym_hcb *np, struct sym_nvram *nvram);
+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);
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 sym_hcb *np, struct sym_nvram *nvram) { }
+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 int sym_read_nvram(struct sym_device *np, struct sym_nvram *nvp)
{
nvp->type = 0;
return 0;
}
+static inline char *sym_nvram_type(struct sym_nvram *nvp)
+{
+ return "No NVRAM";
+}
#endif
#endif /* SYM_NVRAM_H */
diff --git a/drivers/scsi/sym53c8xx_defs.h b/drivers/scsi/sym53c8xx_defs.h
index c1d1e959f30cf..4c4ae7d4713fd 100644
--- a/drivers/scsi/sym53c8xx_defs.h
+++ b/drivers/scsi/sym53c8xx_defs.h
@@ -314,9 +314,9 @@
#define writew_b2l __raw_writew
#define writel_b2l __raw_writel
#define readw_raw __raw_readw
-#define readl_raw(a) __raw_readl((unsigned long)(a))
+#define readl_raw __raw_readl
#define writew_raw __raw_writew
-#define writel_raw(v,a) __raw_writel(v,(unsigned long)(a))
+#define writel_raw __raw_writel
#else /* Other big-endian */
#define readw_l2b readw
#define readl_l2b readl
@@ -1281,34 +1281,34 @@ struct scr_tblsel {
** Messages
*/
-#define M_COMPLETE (0x00)
-#define M_EXTENDED (0x01)
-#define M_SAVE_DP (0x02)
-#define M_RESTORE_DP (0x03)
-#define M_DISCONNECT (0x04)
-#define M_ID_ERROR (0x05)
-#define M_ABORT (0x06)
-#define M_REJECT (0x07)
-#define M_NOOP (0x08)
-#define M_PARITY (0x09)
-#define M_LCOMPLETE (0x0a)
-#define M_FCOMPLETE (0x0b)
-#define M_RESET (0x0c)
-#define M_ABORT_TAG (0x0d)
-#define M_CLEAR_QUEUE (0x0e)
-#define M_INIT_REC (0x0f)
-#define M_REL_REC (0x10)
+#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 (0x20)
-#define M_HEAD_TAG (0x21)
-#define M_ORDERED_TAG (0x22)
-#define M_IGN_RESIDUE (0x23)
+#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 (0x00)
-#define M_X_SYNC_REQ (0x01)
-#define M_X_WIDE_REQ (0x03)
-#define M_X_PPR_REQ (0x04)
+#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
diff --git a/drivers/scsi/ultrastor.c b/drivers/scsi/ultrastor.c
index 3d0a0f2f7f89d..7484916fe2aac 100644
--- a/drivers/scsi/ultrastor.c
+++ b/drivers/scsi/ultrastor.c
@@ -259,7 +259,7 @@ static struct ultrastor_config
} config = {0};
/* Set this to 1 to reset the SCSI bus on error. */
-int ultrastor_bus_reset;
+static int ultrastor_bus_reset;
/* Allowed BIOS base addresses (NULL indicates reserved) */
diff --git a/drivers/scsi/zalon.c b/drivers/scsi/zalon.c
index 31ba6a9168c77..5a51051e31f0e 100644
--- a/drivers/scsi/zalon.c
+++ b/drivers/scsi/zalon.c
@@ -88,31 +88,30 @@ zalon_probe(struct parisc_device *dev)
struct gsc_irq gsc_irq;
u32 zalon_vers;
int error = -ENODEV;
- unsigned long zalon = dev->hpa;
- unsigned long io_port = zalon + GSC_SCSI_ZALON_OFFSET;
+ void __iomem *zalon = ioremap(dev->hpa, 4096);
+ void __iomem *io_port = zalon + GSC_SCSI_ZALON_OFFSET;
static int unit = 0;
struct Scsi_Host *host;
struct ncr_device device;
__raw_writel(CMD_RESET, zalon + IO_MODULE_IO_COMMAND);
while (!(__raw_readl(zalon + IO_MODULE_IO_STATUS) & IOSTATUS_RY))
- ;
+ cpu_relax();
__raw_writel(IOIIDATA_MINT5EN | IOIIDATA_PACKEN | IOIIDATA_PREFETCHEN,
zalon + IO_MODULE_II_CDATA);
/* XXX: Save the Zalon version for bug workarounds? */
- zalon_vers = __raw_readl(dev->hpa + IO_MODULE_II_CDATA) & 0x07000000;
- zalon_vers >>= 24;
+ zalon_vers = (__raw_readl(zalon + IO_MODULE_II_CDATA) >> 24) & 0x07;
/* Setup the interrupts first.
** Later on request_irq() will register the handler.
*/
dev->irq = gsc_alloc_irq(&gsc_irq);
- printk("%s: Zalon vers field is 0x%x, IRQ %d\n", __FUNCTION__,
+ printk(KERN_INFO "%s: Zalon version %d, IRQ %d\n", __FUNCTION__,
zalon_vers, dev->irq);
- __raw_writel(gsc_irq.txn_addr | gsc_irq.txn_data, dev->hpa + IO_MODULE_EIM);
+ __raw_writel(gsc_irq.txn_addr | gsc_irq.txn_data, zalon + IO_MODULE_EIM);
if (zalon_vers == 0)
printk(KERN_WARNING "%s: Zalon 1.1 or earlier\n", __FUNCTION__);
@@ -120,16 +119,16 @@ zalon_probe(struct parisc_device *dev)
memset(&device, 0, sizeof(struct ncr_device));
/* The following three are needed before any other access. */
- writeb(0x20, io_port + 0x38); /* DCNTL_REG, EA */
- writeb(0x04, io_port + 0x1b); /* CTEST0_REG, EHP */
- writeb(0x80, io_port + 0x22); /* CTEST4_REG, MUX */
+ __raw_writeb(0x20, io_port + 0x38); /* DCNTL_REG, EA */
+ __raw_writeb(0x04, io_port + 0x1b); /* CTEST0_REG, EHP */
+ __raw_writeb(0x80, io_port + 0x22); /* CTEST4_REG, MUX */
/* Initialise ncr_device structure with items required by ncr_attach. */
device.chip = zalon720_chip;
device.host_id = 7;
device.dev = &dev->dev;
- device.slot.base = (u_long)io_port;
- device.slot.base_c = (u_long)io_port;
+ device.slot.base = dev->hpa + GSC_SCSI_ZALON_OFFSET;
+ device.slot.base_v = io_port;
device.slot.irq = dev->irq;
device.differential = 2;
diff --git a/drivers/serial/21285.c b/drivers/serial/21285.c
index 759addd518547..f8504b0adebcd 100644
--- a/drivers/serial/21285.c
+++ b/drivers/serial/21285.c
@@ -142,7 +142,6 @@ static irqreturn_t serial21285_rx_chars(int irq, void *dev_id, struct pt_regs *r
}
tty_flip_buffer_push(tty);
- out:
return IRQ_HANDLED;
}
@@ -383,11 +382,9 @@ static struct uart_ops serial21285_ops = {
};
static struct uart_port serial21285_port = {
- .membase = 0,
.mapbase = 0x42000160,
.iotype = SERIAL_IO_MEM,
.irq = NO_IRQ,
- .uartclk = 0,
.fifosize = 16,
.ops = &serial21285_ops,
.flags = ASYNC_BOOT_AUTOCONF,
diff --git a/drivers/serial/68328serial.c b/drivers/serial/68328serial.c
index 36f2fb04c052d..db92a0ceda79f 100644
--- a/drivers/serial/68328serial.c
+++ b/drivers/serial/68328serial.c
@@ -1055,28 +1055,23 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
(arg ? CLOCAL : 0));
return 0;
case TIOCGSERIAL:
- error = verify_area(VERIFY_WRITE, (void *) arg,
- sizeof(struct serial_struct));
- if (error)
- return error;
- return get_serial_info(info,
+ if (access_ok(VERIFY_WRITE, (void *) arg,
+ sizeof(struct serial_struct)))
+ return get_serial_info(info,
(struct serial_struct *) arg);
+ return -EFAULT;
case TIOCSSERIAL:
return set_serial_info(info,
(struct serial_struct *) arg);
case TIOCSERGETLSR: /* Get line status register */
- error = verify_area(VERIFY_WRITE, (void *) arg,
- sizeof(unsigned int));
- if (error)
- return error;
- else
- return get_lsr_info(info, (unsigned int *) arg);
-
+ if (access_ok(VERIFY_WRITE, (void *) arg,
+ sizeof(unsigned int));
+ return get_lsr_info(info, (unsigned int *) arg);
+ return -EFAULT;
case TIOCSERGSTRUCT:
- error = verify_area(VERIFY_WRITE, (void *) arg,
- sizeof(struct m68k_serial));
- if (error)
- return error;
+ if (!access_ok(VERIFY_WRITE, (void *) arg,
+ sizeof(struct m68k_serial)))
+ return -EFAULT;
copy_to_user((struct m68k_serial *) arg,
info, sizeof(struct m68k_serial));
return 0;
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index ec620e33fcf6f..49071f2394527 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -261,7 +261,7 @@ static const struct serial8250_config uart_config[] = {
.fifo_size = 32,
.tx_loadsz = 32,
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
- .flags = UART_CAP_FIFO,
+ .flags = UART_CAP_FIFO | UART_CAP_UUE,
},
};
@@ -450,9 +450,11 @@ static void disable_rsa(struct uart_8250_port *up)
*/
static int size_fifo(struct uart_8250_port *up)
{
- unsigned char old_fcr, old_mcr, old_dll, old_dlm;
+ unsigned char old_fcr, old_mcr, old_dll, old_dlm, old_lcr;
int count;
+ old_lcr = serial_inp(up, UART_LCR);
+ serial_outp(up, UART_LCR, 0);
old_fcr = serial_inp(up, UART_FCR);
old_mcr = serial_inp(up, UART_MCR);
serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO |
@@ -475,11 +477,40 @@ static int size_fifo(struct uart_8250_port *up)
serial_outp(up, UART_LCR, UART_LCR_DLAB);
serial_outp(up, UART_DLL, old_dll);
serial_outp(up, UART_DLM, old_dlm);
+ serial_outp(up, UART_LCR, old_lcr);
return count;
}
/*
+ * Read UART ID using the divisor method - set DLL and DLM to zero
+ * and the revision will be in DLL and device type in DLM. We
+ * preserve the device state across this.
+ */
+static unsigned int autoconfig_read_divisor_id(struct uart_8250_port *p)
+{
+ unsigned char old_dll, old_dlm, old_lcr;
+ unsigned int id;
+
+ old_lcr = serial_inp(p, UART_LCR);
+ serial_outp(p, UART_LCR, UART_LCR_DLAB);
+
+ old_dll = serial_inp(p, UART_DLL);
+ old_dlm = serial_inp(p, UART_DLM);
+
+ serial_outp(p, UART_DLL, 0);
+ serial_outp(p, UART_DLM, 0);
+
+ id = serial_inp(p, UART_DLL) | serial_inp(p, UART_DLM) << 8;
+
+ serial_outp(p, UART_DLL, old_dll);
+ serial_outp(p, UART_DLM, old_dlm);
+ serial_outp(p, UART_LCR, old_lcr);
+
+ return id;
+}
+
+/*
* This is a helper routine to autodetect StarTech/Exar/Oxsemi UART's.
* When this function is called we know it is at least a StarTech
* 16650 V2, but it might be one of several StarTech UARTs, or one of
@@ -491,7 +522,7 @@ static int size_fifo(struct uart_8250_port *up)
*/
static void autoconfig_has_efr(struct uart_8250_port *up)
{
- unsigned char id1, id2, id3, rev, saved_dll, saved_dlm;
+ unsigned int id1, id2, id3, rev;
/*
* Everything with an EFR has SLEEP
@@ -541,21 +572,13 @@ static void autoconfig_has_efr(struct uart_8250_port *up)
* 0x12 - XR16C2850.
* 0x14 - XR16C854.
*/
- serial_outp(up, UART_LCR, UART_LCR_DLAB);
- saved_dll = serial_inp(up, UART_DLL);
- saved_dlm = serial_inp(up, UART_DLM);
- serial_outp(up, UART_DLL, 0);
- serial_outp(up, UART_DLM, 0);
- id2 = serial_inp(up, UART_DLL);
- id1 = serial_inp(up, UART_DLM);
- serial_outp(up, UART_DLL, saved_dll);
- serial_outp(up, UART_DLM, saved_dlm);
-
- DEBUG_AUTOCONF("850id=%02x:%02x ", id1, id2);
-
- if (id1 == 0x10 || id1 == 0x12 || id1 == 0x14) {
- if (id1 == 0x10)
- up->rev = id2;
+ id1 = autoconfig_read_divisor_id(up);
+ DEBUG_AUTOCONF("850id=%04x ", id1);
+
+ id2 = id1 >> 8;
+ if (id2 == 0x10 || id2 == 0x12 || id2 == 0x14) {
+ if (id2 == 0x10)
+ up->rev = id1 & 255;
up->port.type = PORT_16850;
return;
}
@@ -597,6 +620,19 @@ static void autoconfig_8250(struct uart_8250_port *up)
up->port.type = PORT_16450;
}
+static int broken_efr(struct uart_8250_port *up)
+{
+ /*
+ * Exar ST16C2550 "A2" devices incorrectly detect as
+ * having an EFR, and report an ID of 0x0201. See
+ * http://www.exar.com/info.php?pdf=dan180_oct2004.pdf
+ */
+ if (autoconfig_read_divisor_id(up) == 0x0201 && size_fifo(up) == 16)
+ return 1;
+
+ return 0;
+}
+
/*
* We know that the chip has FIFOs. Does it have an EFR? The
* EFR is located in the same register position as the IIR and
@@ -606,6 +642,7 @@ static void autoconfig_8250(struct uart_8250_port *up)
static void autoconfig_16550a(struct uart_8250_port *up)
{
unsigned char status1, status2;
+ unsigned int iersave;
up->port.type = PORT_16550A;
up->capabilities |= UART_CAP_FIFO;
@@ -633,7 +670,7 @@ static void autoconfig_16550a(struct uart_8250_port *up)
* (other ST16C650V2 UARTs, TI16C752A, etc)
*/
serial_outp(up, UART_LCR, 0xBF);
- if (serial_in(up, UART_EFR) == 0) {
+ if (serial_in(up, UART_EFR) == 0 && !broken_efr(up)) {
DEBUG_AUTOCONF("EFRv2 ");
autoconfig_has_efr(up);
return;
@@ -692,6 +729,7 @@ static void autoconfig_16550a(struct uart_8250_port *up)
serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE);
status2 = serial_in(up, UART_IIR) >> 5;
serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
+ serial_outp(up, UART_LCR, 0);
DEBUG_AUTOCONF("iir1=%d iir2=%d ", status1, status2);
@@ -700,6 +738,41 @@ static void autoconfig_16550a(struct uart_8250_port *up)
up->capabilities |= UART_CAP_AFE | UART_CAP_SLEEP;
return;
}
+
+ /*
+ * Try writing and reading the UART_IER_UUE bit (b6).
+ * If it works, this is probably one of the Xscale platform's
+ * internal UARTs.
+ * We're going to explicitly set the UUE bit to 0 before
+ * trying to write and read a 1 just to make sure it's not
+ * already a 1 and maybe locked there before we even start start.
+ */
+ iersave = serial_in(up, UART_IER);
+ serial_outp(up, UART_IER, iersave & ~UART_IER_UUE);
+ if (!(serial_in(up, UART_IER) & UART_IER_UUE)) {
+ /*
+ * OK it's in a known zero state, try writing and reading
+ * without disturbing the current state of the other bits.
+ */
+ serial_outp(up, UART_IER, iersave | UART_IER_UUE);
+ if (serial_in(up, UART_IER) & UART_IER_UUE) {
+ /*
+ * It's an Xscale.
+ * We'll leave the UART_IER_UUE bit set to 1 (enabled).
+ */
+ DEBUG_AUTOCONF("Xscale ");
+ up->port.type = PORT_XSCALE;
+ up->capabilities |= UART_CAP_UUE;
+ return;
+ }
+ } else {
+ /*
+ * If we got here we couldn't force the IER_UUE bit to 0.
+ * Log it and continue.
+ */
+ DEBUG_AUTOCONF("Couldn't force IER_UUE to 0 ");
+ }
+ serial_outp(up, UART_IER, iersave);
}
/*
@@ -1678,7 +1751,7 @@ serial8250_set_termios(struct uart_port *port, struct termios *termios,
up->ier &= ~UART_IER_MSI;
if (UART_ENABLE_MS(&up->port, termios->c_cflag))
up->ier |= UART_IER_MSI;
- if (up->port.type == PORT_XSCALE)
+ if (up->capabilities & UART_CAP_UUE)
up->ier |= UART_IER_UUE | UART_IER_RTOIE;
serial_out(up, UART_IER, up->ier);
@@ -2047,7 +2120,7 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count)
*/
ier = serial_in(up, UART_IER);
- if (up->port.type == PORT_XSCALE)
+ if (up->capabilities & UART_CAP_UUE)
serial_out(up, UART_IER, UART_IER_UUE);
else
serial_out(up, UART_IER, 0);
@@ -2260,7 +2333,7 @@ static int __devexit serial8250_remove(struct device *dev)
return 0;
}
-static int serial8250_suspend(struct device *dev, u32 state, u32 level)
+static int serial8250_suspend(struct device *dev, pm_message_t state, u32 level)
{
int i;
@@ -2316,26 +2389,6 @@ static struct platform_device *serial8250_isa_devs;
*/
static DECLARE_MUTEX(serial_sem);
-/*
- * Are the two ports equivalent?
- */
-static int uart_match_port(struct uart_port *port1, struct uart_port *port2)
-{
- if (port1->iotype != port2->iotype)
- return 0;
-
- switch (port1->iotype) {
- case UPIO_PORT:
- return (port1->iobase == port2->iobase);
- case UPIO_HUB6:
- return (port1->iobase == port2->iobase) &&
- (port1->hub6 == port2->hub6);
- case UPIO_MEM:
- return (port1->membase == port2->membase);
- }
- return 0;
-}
-
static struct uart_8250_port *serial8250_find_match_or_unused(struct uart_port *port)
{
int i;
diff --git a/drivers/serial/8250.h b/drivers/serial/8250.h
index b4cb2fbaa58bb..4f3d62f222f47 100644
--- a/drivers/serial/8250.h
+++ b/drivers/serial/8250.h
@@ -49,14 +49,9 @@ struct serial8250_config {
#define UART_CAP_EFR (1 << 9) /* UART has EFR */
#define UART_CAP_SLEEP (1 << 10) /* UART has IER sleep */
#define UART_CAP_AFE (1 << 11) /* MCR-based hw flow control */
-
-#undef SERIAL_DEBUG_PCI
+#define UART_CAP_UUE (1 << 12) /* UART needs IER bit 6 set (Xscale) */
#if defined(__i386__) && (defined(CONFIG_M386) || defined(CONFIG_M486))
-#define SERIAL_INLINE
-#endif
-
-#ifdef SERIAL_INLINE
#define _INLINE_ inline
#else
#define _INLINE_
@@ -80,6 +75,13 @@ struct serial8250_config {
* is cleared, the machine locks up with endless interrupts.
*/
#define ALPHA_KLUDGE_MCR (UART_MCR_OUT2 | UART_MCR_OUT1)
+#elif defined(CONFIG_SBC8560)
+/*
+ * WindRiver did something similarly broken on their SBC8560 board. The
+ * UART tristates its IRQ output while OUT2 is clear, but they pulled
+ * the interrupt line _up_ instead of down, so if we register the IRQ
+ * while the UART is in that state, we die in an IRQ storm. */
+#define ALPHA_KLUDGE_MCR (UART_MCR_OUT2)
#else
#define ALPHA_KLUDGE_MCR 0
#endif
diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c
index 11ed840476d71..f8d90d0ecfeac 100644
--- a/drivers/serial/8250_pci.c
+++ b/drivers/serial/8250_pci.c
@@ -31,6 +31,8 @@
#include "8250.h"
+#undef SERIAL_DEBUG_PCI
+
/*
* Definitions for PCI support.
*/
@@ -577,6 +579,16 @@ static int __devinit pci_xircom_init(struct pci_dev *dev)
return 0;
}
+static int __devinit pci_netmos_init(struct pci_dev *dev)
+{
+ /* subdevice 0x00PS means <P> parallel, <S> serial */
+ unsigned int num_serial = dev->subsystem_device & 0xf;
+
+ if (num_serial == 0)
+ return -ENODEV;
+ return num_serial;
+}
+
static int
pci_default_setup(struct pci_dev *dev, struct pci_board *board,
struct uart_port *port, int idx)
@@ -934,6 +946,17 @@ static struct pci_serial_quirk pci_serial_quirks[] = {
.setup = pci_default_setup,
},
/*
+ * Netmos cards
+ */
+ {
+ .vendor = PCI_VENDOR_ID_NETMOS,
+ .device = PCI_ANY_ID,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .init = pci_netmos_init,
+ .setup = pci_default_setup,
+ },
+ /*
* Default "match everything" terminator entry
*/
{
@@ -1759,7 +1782,7 @@ static void __devexit pciserial_remove_one(struct pci_dev *dev)
}
}
-static int pciserial_suspend_one(struct pci_dev *dev, u32 state)
+static int pciserial_suspend_one(struct pci_dev *dev, pm_message_t state)
{
struct serial_private *priv = pci_get_drvdata(dev);
@@ -1769,6 +1792,8 @@ static int pciserial_suspend_one(struct pci_dev *dev, u32 state)
for (i = 0; i < priv->nr; i++)
serial8250_suspend_port(priv->line[i]);
}
+ pci_save_state(dev);
+ pci_set_power_state(dev, pci_choose_state(dev, state));
return 0;
}
@@ -1776,10 +1801,18 @@ static int pciserial_resume_one(struct pci_dev *dev)
{
struct serial_private *priv = pci_get_drvdata(dev);
+ pci_set_power_state(dev, PCI_D0);
+ pci_restore_state(dev);
+
if (priv) {
int i;
/*
+ * The device may have been disabled. Re-enable it.
+ */
+ pci_enable_device(dev);
+
+ /*
* Ensure that the board is correctly configured.
*/
if (priv->quirk->init)
@@ -1867,6 +1900,9 @@ static struct pci_device_id serial_pci_tbl[] = {
{ PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_COMM8,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_b2_8_115200 },
+ { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_UCOMM8,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b2_8_115200 },
{ PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_GTEK_SERIAL2,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
@@ -2175,6 +2211,9 @@ static struct pci_device_id serial_pci_tbl[] = {
* HP Diva card
*/
{ PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_DIVA,
+ PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_DIVA_RMP3, 0, 0,
+ pbn_b1_1_115200 },
+ { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_DIVA,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_b0_5_115200 },
{ PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_DIVA_AUX,
@@ -2212,6 +2251,13 @@ static struct pci_device_id serial_pci_tbl[] = {
0, pbn_exar_XR17C158 },
/*
+ * Topic TP560 Data/Fax/Voice 56k modem (reported by Evan Clarke)
+ */
+ { PCI_VENDOR_ID_TOPIC, PCI_DEVICE_ID_TOPIC_TP560,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_1_115200 },
+
+ /*
* These entries match devices with class COMMUNICATION_SERIAL,
* COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL
*/
@@ -2241,7 +2287,7 @@ static struct pci_driver serial_pci_driver = {
static int __init serial8250_pci_init(void)
{
- return pci_module_init(&serial_pci_driver);
+ return pci_register_driver(&serial_pci_driver);
}
static void __exit serial8250_pci_exit(void)
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index ab8035437a7a9..cdf110fd63518 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -615,7 +615,7 @@ config SERIAL_68360
config SERIAL_PMACZILOG
tristate "PowerMac z85c30 ESCC support"
- depends on PPC_OF
+ depends on PPC_OF && PPC_PMAC
select SERIAL_CORE
help
This driver supports the Zilog z85C30 serial ports found on
@@ -810,4 +810,36 @@ config SERIAL_TXX9_STDSERIAL
bool "TX39XX/49XX SIO act as standard serial"
depends on !SERIAL_8250 && SERIAL_TXX9
+config SERIAL_VR41XX
+ tristate "NEC VR4100 series Serial Interface Unit support"
+ depends on CPU_VR41XX
+ select SERIAL_CORE
+ help
+ If you have a NEC VR4100 series processor and you want to use
+ Serial Interface Unit(SIU) or Debug Serial Interface Unit(DSIU)
+ (not include VR4111/VR4121 DSIU), say Y. Otherwise, say N.
+
+config SERIAL_VR41XX_CONSOLE
+ bool "Enable NEC VR4100 series Serial Interface Unit console"
+ depends on SERIAL_VR41XX
+ select SERIAL_CORE_CONSOLE
+ help
+ If you have a NEC VR4100 series processor and you want to use
+ a console on a serial port, say Y. Otherwise, say N.
+
+config SERIAL_JSM
+ tristate "Digi International NEO PCI Support"
+ select SERIAL_CORE
+ help
+ This is a driver for Digi International's Neo series
+ of cards which provide multiple serial ports. You would need
+ something like this to connect more than two modems to your Linux
+ box, for instance in order to become a dial-in server. This driver
+ supports PCI boards only.
+ If you have a card like this, say Y here and read the file
+ <file:Documentation/jsm.txt>.
+
+ To compile this driver as a module, choose M here: the
+ module will be called jsm.
+
endmenu
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index 9ca204984bfb2..81b77d769b846 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -6,9 +6,9 @@
serial-8250-y :=
serial-8250-$(CONFIG_SERIAL_8250_ACPI) += 8250_acpi.o
+serial-8250-$(CONFIG_PNP) += 8250_pnp.o
serial-8250-$(CONFIG_GSC) += 8250_gsc.o
serial-8250-$(CONFIG_PCI) += 8250_pci.o
-serial-8250-$(CONFIG_PNP) += 8250_pnp.o
serial-8250-$(CONFIG_HP300) += 8250_hp300.o
obj-$(CONFIG_SERIAL_CORE) += serial_core.o
@@ -48,4 +48,7 @@ obj-$(CONFIG_SERIAL_ICOM) += icom.o
obj-$(CONFIG_SERIAL_M32R_SIO) += m32r_sio.o
obj-$(CONFIG_SERIAL_MPSC) += mpsc.o
obj-$(CONFIG_ETRAX_SERIAL) += crisv10.o
+obj-$(CONFIG_SERIAL_JSM) += jsm/
obj-$(CONFIG_SERIAL_TXX9) += serial_txx9.o
+obj-$(CONFIG_SERIAL_VR41XX) += vr41xx_siu.o
+obj-$(CONFIG_BLK_DEV_SGIIOC4) += ioc4_serial.o
diff --git a/drivers/serial/au1x00_uart.c b/drivers/serial/au1x00_uart.c
index 1db28380bbac2..b6d3d50349407 100644
--- a/drivers/serial/au1x00_uart.c
+++ b/drivers/serial/au1x00_uart.c
@@ -320,7 +320,9 @@ receive_chars(struct uart_8250_port *up, int *status, struct pt_regs *regs)
ignore_char:
*status = serial_inp(up, UART_LSR);
} while ((*status & UART_LSR_DR) && (max_count-- > 0));
+ spin_unlock(&up->port.lock);
tty_flip_buffer_push(tty);
+ spin_lock(&up->port.lock);
}
static _INLINE_ void transmit_chars(struct uart_8250_port *up)
@@ -1242,57 +1244,6 @@ static struct uart_driver serial8250_reg = {
.cons = SERIAL8250_CONSOLE,
};
-/*
- * register_serial and unregister_serial allows for 16x50 serial ports to be
- * configured at run-time, to support PCMCIA modems.
- */
-
-static int __register_serial(struct serial_struct *req, int line)
-{
- struct uart_port port;
-
- port.iobase = req->port;
- port.membase = req->iomem_base;
- port.irq = req->irq;
- port.uartclk = req->baud_base * 16;
- port.fifosize = req->xmit_fifo_size;
- port.regshift = req->iomem_reg_shift;
- port.iotype = req->io_type;
- port.flags = req->flags | UPF_BOOT_AUTOCONF;
- port.mapbase = req->iomap_base;
- port.line = line;
-
- if (HIGH_BITS_OFFSET)
- port.iobase |= (long) req->port_high << HIGH_BITS_OFFSET;
-
- /*
- * If a clock rate wasn't specified by the low level
- * driver, then default to the standard clock rate.
- */
- if (port.uartclk == 0)
- port.uartclk = BASE_BAUD * 16;
-
- return uart_register_port(&serial8250_reg, &port);
-}
-
-/**
- * register_serial - configure a 16x50 serial port at runtime
- * @req: request structure
- *
- * Configure the serial port specified by the request. If the
- * port exists and is in use an error is returned. If the port
- * is not currently in the table it is added.
- *
- * The port is then probed and if necessary the IRQ is autodetected
- * If this fails an error is returned.
- *
- * On success the port is ready to use and the line number is returned.
- */
-int register_serial(struct serial_struct *req)
-{
- return __register_serial(req, -1);
-}
-
int __init early_serial_setup(struct uart_port *port)
{
serial8250_isa_init_ports();
@@ -1302,18 +1253,6 @@ int __init early_serial_setup(struct uart_port *port)
}
/**
- * unregister_serial - remove a 16x50 serial port at runtime
- * @line: serial line number
- *
- * Remove one serial port. This may be called from interrupt
- * context.
- */
-void unregister_serial(int line)
-{
- uart_unregister_port(&serial8250_reg, line);
-}
-
-/**
* serial8250_suspend_port - suspend one serial port
* @line: serial line number
* @level: the level of port suspension, as per uart_suspend_port
@@ -1366,8 +1305,6 @@ static void __exit serial8250_exit(void)
module_init(serial8250_init);
module_exit(serial8250_exit);
-EXPORT_SYMBOL(register_serial);
-EXPORT_SYMBOL(unregister_serial);
EXPORT_SYMBOL(serial8250_suspend_port);
EXPORT_SYMBOL(serial8250_resume_port);
diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c
index 73306b9d9cc74..29db677d4284d 100644
--- a/drivers/serial/cpm_uart/cpm_uart_core.c
+++ b/drivers/serial/cpm_uart/cpm_uart_core.c
@@ -864,6 +864,7 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = {
.irq = SMC1_IRQ,
.ops = &cpm_uart_pops,
.iotype = SERIAL_IO_MEM,
+ .lock = SPIN_LOCK_UNLOCKED,
},
.flags = FLAG_SMC,
.tx_nrfifos = TX_NUM_FIFO,
@@ -877,6 +878,7 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = {
.irq = SMC2_IRQ,
.ops = &cpm_uart_pops,
.iotype = SERIAL_IO_MEM,
+ .lock = SPIN_LOCK_UNLOCKED,
},
.flags = FLAG_SMC,
.tx_nrfifos = TX_NUM_FIFO,
@@ -893,6 +895,7 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = {
.irq = SCC1_IRQ,
.ops = &cpm_uart_pops,
.iotype = SERIAL_IO_MEM,
+ .lock = SPIN_LOCK_UNLOCKED,
},
.tx_nrfifos = TX_NUM_FIFO,
.tx_fifosize = TX_BUF_SIZE,
@@ -905,6 +908,7 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = {
.irq = SCC2_IRQ,
.ops = &cpm_uart_pops,
.iotype = SERIAL_IO_MEM,
+ .lock = SPIN_LOCK_UNLOCKED,
},
.tx_nrfifos = TX_NUM_FIFO,
.tx_fifosize = TX_BUF_SIZE,
@@ -917,6 +921,7 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = {
.irq = SCC3_IRQ,
.ops = &cpm_uart_pops,
.iotype = SERIAL_IO_MEM,
+ .lock = SPIN_LOCK_UNLOCKED,
},
.tx_nrfifos = TX_NUM_FIFO,
.tx_fifosize = TX_BUF_SIZE,
@@ -929,6 +934,7 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = {
.irq = SCC4_IRQ,
.ops = &cpm_uart_pops,
.iotype = SERIAL_IO_MEM,
+ .lock = SPIN_LOCK_UNLOCKED,
},
.tx_nrfifos = TX_NUM_FIFO,
.tx_fifosize = TX_BUF_SIZE,
diff --git a/drivers/serial/crisv10.c b/drivers/serial/crisv10.c
index 676c423bd3414..3da5494953af2 100644
--- a/drivers/serial/crisv10.c
+++ b/drivers/serial/crisv10.c
@@ -3757,10 +3757,8 @@ rs_write(struct tty_struct * tty, int from_user,
e100_enable_rx_irq(info);
#endif
- if (info->rs485.delay_rts_before_send > 0) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout((info->rs485.delay_rts_before_send * HZ)/1000);
- }
+ if (info->rs485.delay_rts_before_send > 0)
+ msleep(info->rs485.delay_rts_before_send);
}
#endif /* CONFIG_ETRAX_RS485 */
diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c
index fc2a8f03218e9..d273134f9e6cc 100644
--- a/drivers/serial/imx.c
+++ b/drivers/serial/imx.c
@@ -22,6 +22,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
+ * [29-Mar-2005] Mike Lee
+ * Added hardware handshake
*/
#include <linux/config.h>
@@ -428,6 +430,11 @@ imx_set_termios(struct uart_port *port, struct termios *termios,
else
ucr2 = UCR2_SRST | UCR2_IRTS;
+ if (termios->c_cflag & CRTSCTS) {
+ ucr2 &= ~UCR2_IRTS;
+ ucr2 |= UCR2_CTSC;
+ }
+
if (termios->c_cflag & CSTOPB)
ucr2 |= UCR2_STPB;
if (termios->c_cflag & PARENB) {
diff --git a/drivers/serial/ioc4_serial.c b/drivers/serial/ioc4_serial.c
new file mode 100644
index 0000000000000..d054f1265701c
--- /dev/null
+++ b/drivers/serial/ioc4_serial.c
@@ -0,0 +1,2909 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2003-2005 Silicon Graphics, Inc. All Rights Reserved.
+ */
+
+
+/*
+ * This file contains a module version of the ioc4 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/serialP.h>
+#include <linux/circ_buf.h>
+#include <linux/serial_reg.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/ioc4_common.h>
+#include <linux/serial_core.h>
+
+/*
+ * interesting things about the ioc4
+ */
+
+#define IOC4_NUM_SERIAL_PORTS 4 /* max ports per card */
+#define IOC4_NUM_CARDS 8 /* max cards per partition */
+
+#define GET_SIO_IR(_n) (_n == 0) ? (IOC4_SIO_IR_S0) : \
+ (_n == 1) ? (IOC4_SIO_IR_S1) : \
+ (_n == 2) ? (IOC4_SIO_IR_S2) : \
+ (IOC4_SIO_IR_S3)
+
+#define GET_OTHER_IR(_n) (_n == 0) ? (IOC4_OTHER_IR_S0_MEMERR) : \
+ (_n == 1) ? (IOC4_OTHER_IR_S1_MEMERR) : \
+ (_n == 2) ? (IOC4_OTHER_IR_S2_MEMERR) : \
+ (IOC4_OTHER_IR_S3_MEMERR)
+
+
+/*
+ * All IOC4 registers are 32 bits wide.
+ */
+
+/*
+ * PCI Memory Space Map
+ */
+#define IOC4_PCI_ERR_ADDR_L 0x000 /* Low Error Address */
+#define IOC4_PCI_ERR_ADDR_VLD (0x1 << 0)
+#define IOC4_PCI_ERR_ADDR_MST_ID_MSK (0xf << 1)
+#define IOC4_PCI_ERR_ADDR_MST_NUM_MSK (0xe << 1)
+#define IOC4_PCI_ERR_ADDR_MST_TYP_MSK (0x1 << 1)
+#define IOC4_PCI_ERR_ADDR_MUL_ERR (0x1 << 5)
+#define IOC4_PCI_ERR_ADDR_ADDR_MSK (0x3ffffff << 6)
+
+/* Interrupt types */
+#define IOC4_SIO_INTR_TYPE 0
+#define IOC4_OTHER_INTR_TYPE 1
+#define IOC4_NUM_INTR_TYPES 2
+
+/* Bitmasks for IOC4_SIO_IR, IOC4_SIO_IEC, and IOC4_SIO_IES */
+#define IOC4_SIO_IR_S0_TX_MT 0x00000001 /* Serial port 0 TX empty */
+#define IOC4_SIO_IR_S0_RX_FULL 0x00000002 /* Port 0 RX buf full */
+#define IOC4_SIO_IR_S0_RX_HIGH 0x00000004 /* Port 0 RX hiwat */
+#define IOC4_SIO_IR_S0_RX_TIMER 0x00000008 /* Port 0 RX timeout */
+#define IOC4_SIO_IR_S0_DELTA_DCD 0x00000010 /* Port 0 delta DCD */
+#define IOC4_SIO_IR_S0_DELTA_CTS 0x00000020 /* Port 0 delta CTS */
+#define IOC4_SIO_IR_S0_INT 0x00000040 /* Port 0 pass-thru intr */
+#define IOC4_SIO_IR_S0_TX_EXPLICIT 0x00000080 /* Port 0 explicit TX thru */
+#define IOC4_SIO_IR_S1_TX_MT 0x00000100 /* Serial port 1 */
+#define IOC4_SIO_IR_S1_RX_FULL 0x00000200 /* */
+#define IOC4_SIO_IR_S1_RX_HIGH 0x00000400 /* */
+#define IOC4_SIO_IR_S1_RX_TIMER 0x00000800 /* */
+#define IOC4_SIO_IR_S1_DELTA_DCD 0x00001000 /* */
+#define IOC4_SIO_IR_S1_DELTA_CTS 0x00002000 /* */
+#define IOC4_SIO_IR_S1_INT 0x00004000 /* */
+#define IOC4_SIO_IR_S1_TX_EXPLICIT 0x00008000 /* */
+#define IOC4_SIO_IR_S2_TX_MT 0x00010000 /* Serial port 2 */
+#define IOC4_SIO_IR_S2_RX_FULL 0x00020000 /* */
+#define IOC4_SIO_IR_S2_RX_HIGH 0x00040000 /* */
+#define IOC4_SIO_IR_S2_RX_TIMER 0x00080000 /* */
+#define IOC4_SIO_IR_S2_DELTA_DCD 0x00100000 /* */
+#define IOC4_SIO_IR_S2_DELTA_CTS 0x00200000 /* */
+#define IOC4_SIO_IR_S2_INT 0x00400000 /* */
+#define IOC4_SIO_IR_S2_TX_EXPLICIT 0x00800000 /* */
+#define IOC4_SIO_IR_S3_TX_MT 0x01000000 /* Serial port 3 */
+#define IOC4_SIO_IR_S3_RX_FULL 0x02000000 /* */
+#define IOC4_SIO_IR_S3_RX_HIGH 0x04000000 /* */
+#define IOC4_SIO_IR_S3_RX_TIMER 0x08000000 /* */
+#define IOC4_SIO_IR_S3_DELTA_DCD 0x10000000 /* */
+#define IOC4_SIO_IR_S3_DELTA_CTS 0x20000000 /* */
+#define IOC4_SIO_IR_S3_INT 0x40000000 /* */
+#define IOC4_SIO_IR_S3_TX_EXPLICIT 0x80000000 /* */
+
+/* Per device interrupt masks */
+#define IOC4_SIO_IR_S0 (IOC4_SIO_IR_S0_TX_MT | \
+ IOC4_SIO_IR_S0_RX_FULL | \
+ IOC4_SIO_IR_S0_RX_HIGH | \
+ IOC4_SIO_IR_S0_RX_TIMER | \
+ IOC4_SIO_IR_S0_DELTA_DCD | \
+ IOC4_SIO_IR_S0_DELTA_CTS | \
+ IOC4_SIO_IR_S0_INT | \
+ IOC4_SIO_IR_S0_TX_EXPLICIT)
+#define IOC4_SIO_IR_S1 (IOC4_SIO_IR_S1_TX_MT | \
+ IOC4_SIO_IR_S1_RX_FULL | \
+ IOC4_SIO_IR_S1_RX_HIGH | \
+ IOC4_SIO_IR_S1_RX_TIMER | \
+ IOC4_SIO_IR_S1_DELTA_DCD | \
+ IOC4_SIO_IR_S1_DELTA_CTS | \
+ IOC4_SIO_IR_S1_INT | \
+ IOC4_SIO_IR_S1_TX_EXPLICIT)
+#define IOC4_SIO_IR_S2 (IOC4_SIO_IR_S2_TX_MT | \
+ IOC4_SIO_IR_S2_RX_FULL | \
+ IOC4_SIO_IR_S2_RX_HIGH | \
+ IOC4_SIO_IR_S2_RX_TIMER | \
+ IOC4_SIO_IR_S2_DELTA_DCD | \
+ IOC4_SIO_IR_S2_DELTA_CTS | \
+ IOC4_SIO_IR_S2_INT | \
+ IOC4_SIO_IR_S2_TX_EXPLICIT)
+#define IOC4_SIO_IR_S3 (IOC4_SIO_IR_S3_TX_MT | \
+ IOC4_SIO_IR_S3_RX_FULL | \
+ IOC4_SIO_IR_S3_RX_HIGH | \
+ IOC4_SIO_IR_S3_RX_TIMER | \
+ IOC4_SIO_IR_S3_DELTA_DCD | \
+ IOC4_SIO_IR_S3_DELTA_CTS | \
+ IOC4_SIO_IR_S3_INT | \
+ IOC4_SIO_IR_S3_TX_EXPLICIT)
+
+/* Bitmasks for IOC4_OTHER_IR, IOC4_OTHER_IEC, and IOC4_OTHER_IES */
+#define IOC4_OTHER_IR_ATA_INT 0x00000001 /* ATAPI intr pass-thru */
+#define IOC4_OTHER_IR_ATA_MEMERR 0x00000002 /* ATAPI DMA PCI error */
+#define IOC4_OTHER_IR_S0_MEMERR 0x00000004 /* Port 0 PCI error */
+#define IOC4_OTHER_IR_S1_MEMERR 0x00000008 /* Port 1 PCI error */
+#define IOC4_OTHER_IR_S2_MEMERR 0x00000010 /* Port 2 PCI error */
+#define IOC4_OTHER_IR_S3_MEMERR 0x00000020 /* Port 3 PCI error */
+
+/* Bitmasks for IOC4_SIO_CR */
+#define IOC4_SIO_CR_CMD_PULSE_SHIFT 0 /* byte bus strobe shift */
+#define IOC4_SIO_CR_ARB_DIAG_TX0 0x00000000
+#define IOC4_SIO_CR_ARB_DIAG_RX0 0x00000010
+#define IOC4_SIO_CR_ARB_DIAG_TX1 0x00000020
+#define IOC4_SIO_CR_ARB_DIAG_RX1 0x00000030
+#define IOC4_SIO_CR_ARB_DIAG_TX2 0x00000040
+#define IOC4_SIO_CR_ARB_DIAG_RX2 0x00000050
+#define IOC4_SIO_CR_ARB_DIAG_TX3 0x00000060
+#define IOC4_SIO_CR_ARB_DIAG_RX3 0x00000070
+#define IOC4_SIO_CR_SIO_DIAG_IDLE 0x00000080 /* 0 -> active request among
+ serial ports (ro) */
+/* Defs for some of the generic I/O pins */
+#define IOC4_GPCR_UART0_MODESEL 0x10 /* Pin is output to port 0
+ mode sel */
+#define IOC4_GPCR_UART1_MODESEL 0x20 /* Pin is output to port 1
+ mode sel */
+#define IOC4_GPCR_UART2_MODESEL 0x40 /* Pin is output to port 2
+ mode sel */
+#define IOC4_GPCR_UART3_MODESEL 0x80 /* Pin is output to port 3
+ mode sel */
+
+#define IOC4_GPPR_UART0_MODESEL_PIN 4 /* GIO pin controlling
+ uart 0 mode select */
+#define IOC4_GPPR_UART1_MODESEL_PIN 5 /* GIO pin controlling
+ uart 1 mode select */
+#define IOC4_GPPR_UART2_MODESEL_PIN 6 /* GIO pin controlling
+ uart 2 mode select */
+#define IOC4_GPPR_UART3_MODESEL_PIN 7 /* GIO pin controlling
+ uart 3 mode select */
+
+/* Bitmasks for serial RX status byte */
+#define IOC4_RXSB_OVERRUN 0x01 /* Char(s) lost */
+#define IOC4_RXSB_PAR_ERR 0x02 /* Parity error */
+#define IOC4_RXSB_FRAME_ERR 0x04 /* Framing error */
+#define IOC4_RXSB_BREAK 0x08 /* Break character */
+#define IOC4_RXSB_CTS 0x10 /* State of CTS */
+#define IOC4_RXSB_DCD 0x20 /* State of DCD */
+#define IOC4_RXSB_MODEM_VALID 0x40 /* DCD, CTS, and OVERRUN are valid */
+#define IOC4_RXSB_DATA_VALID 0x80 /* Data byte, FRAME_ERR PAR_ERR
+ * & BREAK valid */
+
+/* Bitmasks for serial TX control byte */
+#define IOC4_TXCB_INT_WHEN_DONE 0x20 /* Interrupt after this byte is sent */
+#define IOC4_TXCB_INVALID 0x00 /* Byte is invalid */
+#define IOC4_TXCB_VALID 0x40 /* Byte is valid */
+#define IOC4_TXCB_MCR 0x80 /* Data<7:0> to modem control reg */
+#define IOC4_TXCB_DELAY 0xc0 /* Delay data<7:0> mSec */
+
+/* Bitmasks for IOC4_SBBR_L */
+#define IOC4_SBBR_L_SIZE 0x00000001 /* 0 == 1KB rings, 1 == 4KB rings */
+
+/* Bitmasks for IOC4_SSCR_<3:0> */
+#define IOC4_SSCR_RX_THRESHOLD 0x000001ff /* Hiwater mark */
+#define IOC4_SSCR_TX_TIMER_BUSY 0x00010000 /* TX timer in progress */
+#define IOC4_SSCR_HFC_EN 0x00020000 /* Hardware flow control enabled */
+#define IOC4_SSCR_RX_RING_DCD 0x00040000 /* Post RX record on delta-DCD */
+#define IOC4_SSCR_RX_RING_CTS 0x00080000 /* Post RX record on delta-CTS */
+#define IOC4_SSCR_DIAG 0x00200000 /* Bypass clock divider for sim */
+#define IOC4_SSCR_RX_DRAIN 0x08000000 /* Drain RX buffer to memory */
+#define IOC4_SSCR_DMA_EN 0x10000000 /* Enable ring buffer DMA */
+#define IOC4_SSCR_DMA_PAUSE 0x20000000 /* Pause DMA */
+#define IOC4_SSCR_PAUSE_STATE 0x40000000 /* Sets when PAUSE takes effect */
+#define IOC4_SSCR_RESET 0x80000000 /* Reset DMA channels */
+
+/* All producer/comsumer pointers are the same bitfield */
+#define IOC4_PROD_CONS_PTR_4K 0x00000ff8 /* For 4K buffers */
+#define IOC4_PROD_CONS_PTR_1K 0x000003f8 /* For 1K buffers */
+#define IOC4_PROD_CONS_PTR_OFF 3
+
+/* Bitmasks for IOC4_SRCIR_<3:0> */
+#define IOC4_SRCIR_ARM 0x80000000 /* Arm RX timer */
+
+/* Bitmasks for IOC4_SHADOW_<3:0> */
+#define IOC4_SHADOW_DR 0x00000001 /* Data ready */
+#define IOC4_SHADOW_OE 0x00000002 /* Overrun error */
+#define IOC4_SHADOW_PE 0x00000004 /* Parity error */
+#define IOC4_SHADOW_FE 0x00000008 /* Framing error */
+#define IOC4_SHADOW_BI 0x00000010 /* Break interrupt */
+#define IOC4_SHADOW_THRE 0x00000020 /* Xmit holding register empty */
+#define IOC4_SHADOW_TEMT 0x00000040 /* Xmit shift register empty */
+#define IOC4_SHADOW_RFCE 0x00000080 /* Char in RX fifo has an error */
+#define IOC4_SHADOW_DCTS 0x00010000 /* Delta clear to send */
+#define IOC4_SHADOW_DDCD 0x00080000 /* Delta data carrier detect */
+#define IOC4_SHADOW_CTS 0x00100000 /* Clear to send */
+#define IOC4_SHADOW_DCD 0x00800000 /* Data carrier detect */
+#define IOC4_SHADOW_DTR 0x01000000 /* Data terminal ready */
+#define IOC4_SHADOW_RTS 0x02000000 /* Request to send */
+#define IOC4_SHADOW_OUT1 0x04000000 /* 16550 OUT1 bit */
+#define IOC4_SHADOW_OUT2 0x08000000 /* 16550 OUT2 bit */
+#define IOC4_SHADOW_LOOP 0x10000000 /* Loopback enabled */
+
+/* Bitmasks for IOC4_SRTR_<3:0> */
+#define IOC4_SRTR_CNT 0x00000fff /* Reload value for RX timer */
+#define IOC4_SRTR_CNT_VAL 0x0fff0000 /* Current value of RX timer */
+#define IOC4_SRTR_CNT_VAL_SHIFT 16
+#define IOC4_SRTR_HZ 16000 /* SRTR clock frequency */
+
+/* Serial port register map used for DMA and PIO serial I/O */
+struct ioc4_serialregs {
+ uint32_t sscr;
+ uint32_t stpir;
+ uint32_t stcir;
+ uint32_t srpir;
+ uint32_t srcir;
+ uint32_t srtr;
+ uint32_t shadow;
+};
+
+/* IOC4 UART register map */
+struct ioc4_uartregs {
+ char i4u_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 i4u_scr;
+ char i4u_msr;
+ char i4u_lsr;
+ char i4u_mcr;
+};
+
+/* short names */
+#define i4u_dll u1.dll
+#define i4u_ier u2.ier
+#define i4u_dlm u2.dlm
+#define i4u_fcr u3.fcr
+
+/* PCI memory space register map addressed using pci_bar0 */
+struct ioc4_memregs {
+ struct ioc4_mem {
+ /* Miscellaneous IOC4 registers */
+ uint32_t pci_err_addr_l;
+ uint32_t pci_err_addr_h;
+ uint32_t sio_ir;
+ uint32_t other_ir;
+
+ /* These registers are read-only for general kernel code. */
+ uint32_t sio_ies_ro;
+ uint32_t other_ies_ro;
+ uint32_t sio_iec_ro;
+ uint32_t other_iec_ro;
+ uint32_t sio_cr;
+ uint32_t misc_fill1;
+ uint32_t int_out;
+ uint32_t misc_fill2;
+ uint32_t gpcr_s;
+ uint32_t gpcr_c;
+ uint32_t gpdr;
+ uint32_t misc_fill3;
+ uint32_t gppr_0;
+ uint32_t gppr_1;
+ uint32_t gppr_2;
+ uint32_t gppr_3;
+ uint32_t gppr_4;
+ uint32_t gppr_5;
+ uint32_t gppr_6;
+ uint32_t gppr_7;
+ } ioc4_mem;
+
+ char misc_fill4[0x100 - 0x5C - 4];
+
+ /* ATA/ATAP registers */
+ uint32_t ata_notused[9];
+ char ata_fill1[0x140 - 0x120 - 4];
+ uint32_t ata_notused1[8];
+ char ata_fill2[0x200 - 0x15C - 4];
+
+ /* Keyboard and mouse registers */
+ uint32_t km_notused[5];;
+ char km_fill1[0x300 - 0x210 - 4];
+
+ /* Serial port registers used for DMA serial I/O */
+ struct ioc4_serial {
+ uint32_t sbbr01_l;
+ uint32_t sbbr01_h;
+ uint32_t sbbr23_l;
+ uint32_t sbbr23_h;
+
+ struct ioc4_serialregs port_0;
+ struct ioc4_serialregs port_1;
+ struct ioc4_serialregs port_2;
+ struct ioc4_serialregs port_3;
+ struct ioc4_uartregs uart_0;
+ struct ioc4_uartregs uart_1;
+ struct ioc4_uartregs uart_2;
+ struct ioc4_uartregs uart_3;
+ } ioc4_serial;
+};
+
+/* UART clock speed */
+#define IOC4_SER_XIN_CLK IOC4_SER_XIN_CLK_66
+#define IOC4_SER_XIN_CLK_66 66666667
+#define IOC4_SER_XIN_CLK_33 33333333
+
+#define IOC4_W_IES 0
+#define IOC4_W_IEC 1
+
+typedef void ioc4_intr_func_f(void *, uint32_t);
+typedef ioc4_intr_func_f *ioc4_intr_func_t;
+
+/* defining this will get you LOTS of great debug info */
+//#define DEBUG_INTERRUPTS
+#define DPRINT_CONFIG(_x...) ;
+//#define DPRINT_CONFIG(_x...) printk _x
+
+/* number of characters left in xmit buffer before we ask for more */
+#define WAKEUP_CHARS 256
+
+/* number of characters we want to transmit to the lower level at a time */
+#define IOC4_MAX_CHARS 128
+
+/* Device name we're using */
+#define DEVICE_NAME "ttyIOC"
+#define DEVICE_MAJOR 204
+#define DEVICE_MINOR 50
+
+/* register offsets */
+#define IOC4_SERIAL_OFFSET 0x300
+
+/* 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 */
+enum sio_proto {
+ PROTO_RS232,
+ PROTO_RS422
+};
+
+/* 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_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(_p) (readl(&(_p)->ip_mem->sio_ir) & _p->ip_ienb)
+#define READ_SIO_IR(_p) readl(&(_p)->ip_mem->sio_ir)
+
+/* Default to 4k buffers */
+#ifdef IOC4_1K_BUFFERS
+#define RING_BUF_SIZE 1024
+#define IOC4_BUF_SIZE_BIT 0
+#define PROD_CONS_MASK IOC4_PROD_CONS_PTR_1K
+#else
+#define RING_BUF_SIZE 4096
+#define IOC4_BUF_SIZE_BIT IOC4_SBBR_L_SIZE
+#define PROD_CONS_MASK IOC4_PROD_CONS_PTR_4K
+#endif
+
+#define TOTAL_RING_BUF_SIZE (RING_BUF_SIZE * 4)
+
+/*
+ * This is the entry saved by the driver - one per card
+ */
+struct ioc4_control {
+ int ic_irq;
+ struct {
+ /* uart ports are allocated here */
+ struct uart_port icp_uart_port;
+ /* Handy reference material */
+ struct ioc4_port *icp_port;
+ } ic_port[IOC4_NUM_SERIAL_PORTS];
+ struct ioc4_soft *ic_soft;
+};
+
+/*
+ * per-IOC4 data structure
+ */
+#define MAX_IOC4_INTR_ENTS (8 * sizeof(uint32_t))
+struct ioc4_soft {
+ struct ioc4_mem __iomem *is_ioc4_mem_addr;
+ struct ioc4_serial __iomem *is_ioc4_serial_addr;
+
+ /* Each interrupt type has an entry in the array */
+ struct ioc4_intr_type {
+
+ /*
+ * Each in-use entry in this array contains at least
+ * one nonzero bit in sd_bits; no two entries in this
+ * array have overlapping sd_bits values.
+ */
+ struct ioc4_intr_info {
+ uint32_t sd_bits;
+ ioc4_intr_func_f *sd_intr;
+ void *sd_info;
+ } is_intr_info[MAX_IOC4_INTR_ENTS];
+
+ /* Number of entries active in the above array */
+ atomic_t is_num_intrs;
+ } is_intr_type[IOC4_NUM_INTR_TYPES];
+
+ /* 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 is_ir_lock; /* SIO_IE[SC] mod lock */
+};
+
+/* Local port info for each IOC4 serial ports */
+struct ioc4_port {
+ struct uart_port *ip_port;
+ /* Back ptrs for this port */
+ struct ioc4_control *ip_control;
+ struct pci_dev *ip_pdev;
+ struct ioc4_soft *ip_ioc4_soft;
+
+ /* pci mem addresses */
+ struct ioc4_mem __iomem *ip_mem;
+ struct ioc4_serial __iomem *ip_serial;
+ struct ioc4_serialregs __iomem *ip_serial_regs;
+ struct ioc4_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 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_ienb; /* Enabled interrupts */
+ uint32_t ip_sscr;
+ uint32_t ip_tx_prod;
+ uint32_t ip_rx_cons;
+ int ip_pci_bus_speed;
+ 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
+#define DCD_ON 0x02
+#define LOWAT_WRITTEN 0x04
+#define READ_ABORTED 0x08
+
+/* 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 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_dma_error;
+ uint32_t intr_clear;
+ uint32_t intr_all;
+ char rs422_select_pin;
+};
+
+static struct hooks hooks_array[IOC4_NUM_SERIAL_PORTS] = {
+ /* Values for port 0 */
+ {
+ IOC4_SIO_IR_S0_DELTA_DCD, IOC4_SIO_IR_S0_DELTA_CTS,
+ IOC4_SIO_IR_S0_TX_MT, IOC4_SIO_IR_S0_RX_TIMER,
+ IOC4_SIO_IR_S0_RX_HIGH, IOC4_SIO_IR_S0_TX_EXPLICIT,
+ IOC4_OTHER_IR_S0_MEMERR,
+ (IOC4_SIO_IR_S0_TX_MT | IOC4_SIO_IR_S0_RX_FULL |
+ IOC4_SIO_IR_S0_RX_HIGH | IOC4_SIO_IR_S0_RX_TIMER |
+ IOC4_SIO_IR_S0_DELTA_DCD | IOC4_SIO_IR_S0_DELTA_CTS |
+ IOC4_SIO_IR_S0_INT | IOC4_SIO_IR_S0_TX_EXPLICIT),
+ IOC4_SIO_IR_S0, IOC4_GPPR_UART0_MODESEL_PIN,
+ },
+
+ /* Values for port 1 */
+ {
+ IOC4_SIO_IR_S1_DELTA_DCD, IOC4_SIO_IR_S1_DELTA_CTS,
+ IOC4_SIO_IR_S1_TX_MT, IOC4_SIO_IR_S1_RX_TIMER,
+ IOC4_SIO_IR_S1_RX_HIGH, IOC4_SIO_IR_S1_TX_EXPLICIT,
+ IOC4_OTHER_IR_S1_MEMERR,
+ (IOC4_SIO_IR_S1_TX_MT | IOC4_SIO_IR_S1_RX_FULL |
+ IOC4_SIO_IR_S1_RX_HIGH | IOC4_SIO_IR_S1_RX_TIMER |
+ IOC4_SIO_IR_S1_DELTA_DCD | IOC4_SIO_IR_S1_DELTA_CTS |
+ IOC4_SIO_IR_S1_INT | IOC4_SIO_IR_S1_TX_EXPLICIT),
+ IOC4_SIO_IR_S1, IOC4_GPPR_UART1_MODESEL_PIN,
+ },
+
+ /* Values for port 2 */
+ {
+ IOC4_SIO_IR_S2_DELTA_DCD, IOC4_SIO_IR_S2_DELTA_CTS,
+ IOC4_SIO_IR_S2_TX_MT, IOC4_SIO_IR_S2_RX_TIMER,
+ IOC4_SIO_IR_S2_RX_HIGH, IOC4_SIO_IR_S2_TX_EXPLICIT,
+ IOC4_OTHER_IR_S2_MEMERR,
+ (IOC4_SIO_IR_S2_TX_MT | IOC4_SIO_IR_S2_RX_FULL |
+ IOC4_SIO_IR_S2_RX_HIGH | IOC4_SIO_IR_S2_RX_TIMER |
+ IOC4_SIO_IR_S2_DELTA_DCD | IOC4_SIO_IR_S2_DELTA_CTS |
+ IOC4_SIO_IR_S2_INT | IOC4_SIO_IR_S2_TX_EXPLICIT),
+ IOC4_SIO_IR_S2, IOC4_GPPR_UART2_MODESEL_PIN,
+ },
+
+ /* Values for port 3 */
+ {
+ IOC4_SIO_IR_S3_DELTA_DCD, IOC4_SIO_IR_S3_DELTA_CTS,
+ IOC4_SIO_IR_S3_TX_MT, IOC4_SIO_IR_S3_RX_TIMER,
+ IOC4_SIO_IR_S3_RX_HIGH, IOC4_SIO_IR_S3_TX_EXPLICIT,
+ IOC4_OTHER_IR_S3_MEMERR,
+ (IOC4_SIO_IR_S3_TX_MT | IOC4_SIO_IR_S3_RX_FULL |
+ IOC4_SIO_IR_S3_RX_HIGH | IOC4_SIO_IR_S3_RX_TIMER |
+ IOC4_SIO_IR_S3_DELTA_DCD | IOC4_SIO_IR_S3_DELTA_CTS |
+ IOC4_SIO_IR_S3_INT | IOC4_SIO_IR_S3_TX_EXPLICIT),
+ IOC4_SIO_IR_S3, IOC4_GPPR_UART3_MODESEL_PIN,
+ }
+};
+
+/* A ring buffer entry */
+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)(IOC4_RXSB_MODEM_VALID | IOC4_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_0_OR_2;
+ struct ring RX_0_OR_2;
+ struct ring TX_1_OR_3;
+ struct ring RX_1_OR_3;
+};
+
+/* Get a ring from a port struct */
+#define RING(_p, _wh) &(((struct ring_buffer *)((_p)->ip_cpu_ringbuf))->_wh)
+
+/* Infinite loop detection.
+ */
+#define MAXITER 10000000
+
+/* Prototypes */
+static void receive_chars(struct uart_port *);
+static void handle_intr(void *arg, uint32_t sio_ir);
+
+/**
+ * write_ireg - write the interrupt regs
+ * @ioc4_soft: ptr to soft struct for this port
+ * @val: value to write
+ * @which: which register
+ * @type: which ireg set
+ */
+static inline void
+write_ireg(struct ioc4_soft *ioc4_soft, uint32_t val, int which, int type)
+{
+ struct ioc4_mem __iomem *mem = ioc4_soft->is_ioc4_mem_addr;
+ unsigned long flags;
+
+ spin_lock_irqsave(&ioc4_soft->is_ir_lock, flags);
+
+ switch (type) {
+ case IOC4_SIO_INTR_TYPE:
+ switch (which) {
+ case IOC4_W_IES:
+ writel(val, &mem->sio_ies_ro);
+ break;
+
+ case IOC4_W_IEC:
+ writel(val, &mem->sio_iec_ro);
+ break;
+ }
+ break;
+
+ case IOC4_OTHER_INTR_TYPE:
+ switch (which) {
+ case IOC4_W_IES:
+ writel(val, &mem->other_ies_ro);
+ break;
+
+ case IOC4_W_IEC:
+ writel(val, &mem->other_iec_ro);
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+ spin_unlock_irqrestore(&ioc4_soft->is_ir_lock, flags);
+}
+
+/**
+ * set_baud - Baud rate setting code
+ * @port: port to set
+ * @baud: baud rate to use
+ */
+static int set_baud(struct ioc4_port *port, int baud)
+{
+ int actual_baud;
+ int diff;
+ int lcr;
+ unsigned short divisor;
+ struct ioc4_uartregs __iomem *uart;
+
+ divisor = SER_DIVISOR(baud, port->ip_pci_bus_speed);
+ if (!divisor)
+ return 1;
+ actual_baud = DIVISOR_TO_BAUD(divisor, port->ip_pci_bus_speed);
+
+ diff = actual_baud - baud;
+ if (diff < 0)
+ diff = -diff;
+
+ /* If we're within 1%, we've found a match */
+ if (diff * 100 > actual_baud)
+ return 1;
+
+ uart = port->ip_uart_regs;
+ lcr = readb(&uart->i4u_lcr);
+ writeb(lcr | UART_LCR_DLAB, &uart->i4u_lcr);
+ writeb((unsigned char)divisor, &uart->i4u_dll);
+ writeb((unsigned char)(divisor >> 8), &uart->i4u_dlm);
+ writeb(lcr, &uart->i4u_lcr);
+ return 0;
+}
+
+
+/**
+ * get_ioc4_port - given a uart port, return the control structure
+ * @port: uart port
+ */
+static struct ioc4_port *get_ioc4_port(struct uart_port *the_port)
+{
+ struct ioc4_control *control = dev_get_drvdata(the_port->dev);
+ int ii;
+
+ if (control) {
+ for ( ii = 0; ii < IOC4_NUM_SERIAL_PORTS; ii++ ) {
+ if (!control->ic_port[ii].icp_port)
+ continue;
+ if (the_port == control->ic_port[ii].icp_port->ip_port)
+ return control->ic_port[ii].icp_port;
+ }
+ }
+ return NULL;
+}
+
+/* The IOC4 hardware provides no atomic way to determine if interrupts
+ * are pending since two reads are required to do so. The handler must
+ * read the SIO_IR and the SIO_IES, and take the logical and of the
+ * two. When this value is zero, all interrupts have been serviced and
+ * the handler may return.
+ *
+ * This has the unfortunate "hole" that, if some other CPU or
+ * some other thread or some higher level interrupt manages to
+ * modify SIO_IE between our reads of SIO_IR and SIO_IE, we may
+ * think we have observed SIO_IR&SIO_IE==0 when in fact this
+ * condition never really occurred.
+ *
+ * To solve this, we use a simple spinlock that must be held
+ * whenever modifying SIO_IE; holding this lock while observing
+ * both SIO_IR and SIO_IE guarantees that we do not falsely
+ * conclude that no enabled interrupts are pending.
+ */
+
+static inline uint32_t
+pending_intrs(struct ioc4_soft *soft, int type)
+{
+ struct ioc4_mem __iomem *mem = soft->is_ioc4_mem_addr;
+ unsigned long flag;
+ uint32_t intrs = 0;
+
+ BUG_ON(!((type == IOC4_SIO_INTR_TYPE)
+ || (type == IOC4_OTHER_INTR_TYPE)));
+
+ spin_lock_irqsave(&soft->is_ir_lock, flag);
+
+ switch (type) {
+ case IOC4_SIO_INTR_TYPE:
+ intrs = readl(&mem->sio_ir) & readl(&mem->sio_ies_ro);
+ break;
+
+ case IOC4_OTHER_INTR_TYPE:
+ intrs = readl(&mem->other_ir) & readl(&mem->other_ies_ro);
+
+ /* Don't process any ATA interrupte */
+ intrs &= ~(IOC4_OTHER_IR_ATA_INT | IOC4_OTHER_IR_ATA_MEMERR);
+ break;
+
+ default:
+ break;
+ }
+ spin_unlock_irqrestore(&soft->is_ir_lock, flag);
+ return intrs;
+}
+
+/**
+ * port_init - Initialize the sio and ioc4 hardware for a given port
+ * called per port from attach...
+ * @port: port to initialize
+ */
+static int inline port_init(struct ioc4_port *port)
+{
+ uint32_t sio_cr;
+ struct hooks *hooks = port->ip_hooks;
+ struct ioc4_uartregs __iomem *uart;
+
+ /* Idle the IOC4 serial interface */
+ writel(IOC4_SSCR_RESET, &port->ip_serial_regs->sscr);
+
+ /* Wait until any pending bus activity for this port has ceased */
+ do
+ sio_cr = readl(&port->ip_mem->sio_cr);
+ while (!(sio_cr & IOC4_SIO_CR_SIO_DIAG_IDLE));
+
+ /* 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, &port->ip_serial_regs->srcir);
+
+ /* Disable interrupts for this 16550 */
+ uart = port->ip_uart_regs;
+ writeb(0, &uart->i4u_lcr);
+ writeb(0, &uart->i4u_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->i4u_lcr);
+ /* UART_LCR_STOP == 1 stop */
+
+ /* Enable the FIFOs */
+ writeb(UART_FCR_ENABLE_FIFO, &uart->i4u_fcr);
+ /* then reset 16550 FIFOs */
+ writeb(UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT,
+ &uart->i4u_fcr);
+
+ /* Clear modem control register */
+ writeb(0, &uart->i4u_mcr);
+
+ /* Clear deltas in modem status register */
+ readb(&uart->i4u_msr);
+
+ /* Only do this once per port pair */
+ if (port->ip_hooks == &hooks_array[0]
+ || port->ip_hooks == &hooks_array[2]) {
+ unsigned long ring_pci_addr;
+ uint32_t __iomem *sbbr_l;
+ uint32_t __iomem *sbbr_h;
+
+ if (port->ip_hooks == &hooks_array[0]) {
+ sbbr_l = &port->ip_serial->sbbr01_l;
+ sbbr_h = &port->ip_serial->sbbr01_h;
+ } else {
+ sbbr_l = &port->ip_serial->sbbr23_l;
+ sbbr_h = &port->ip_serial->sbbr23_h;
+ }
+
+ ring_pci_addr = (unsigned long __iomem)port->ip_dma_ringbuf;
+ DPRINT_CONFIG(("%s: ring_pci_addr 0x%lx\n",
+ __FUNCTION__, ring_pci_addr));
+
+ writel((unsigned int)((uint64_t)ring_pci_addr >> 32), sbbr_h);
+ writel((unsigned int)ring_pci_addr | IOC4_BUF_SIZE_BIT, sbbr_l);
+ }
+
+ /* Set the receive timeout value to 10 msec */
+ writel(IOC4_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);
+ writel(port->ip_sscr, &port->ip_serial_regs->sscr);
+
+ /* Disable and clear all serial related interrupt bits */
+ write_ireg(port->ip_ioc4_soft, hooks->intr_clear,
+ IOC4_W_IEC, IOC4_SIO_INTR_TYPE);
+ port->ip_ienb &= ~hooks->intr_clear;
+ writel(hooks->intr_clear, &port->ip_mem->sio_ir);
+ return 0;
+}
+
+/**
+ * handle_dma_error_intr - service any pending DMA error interrupts for the
+ * given port - 2nd level called via sd_intr
+ * @arg: handler arg
+ * @other_ir: ioc4regs
+ */
+static void handle_dma_error_intr(void *arg, uint32_t other_ir)
+{
+ struct ioc4_port *port = (struct ioc4_port *)arg;
+ struct hooks *hooks = port->ip_hooks;
+ unsigned int flags;
+
+ spin_lock_irqsave(&port->ip_lock, flags);
+
+ /* ACK the interrupt */
+ writel(hooks->intr_dma_error, &port->ip_mem->other_ir);
+
+ if (readl(&port->ip_mem->pci_err_addr_l) & IOC4_PCI_ERR_ADDR_VLD) {
+ printk(KERN_ERR
+ "PCI error address is 0x%lx, "
+ "master is serial port %c %s\n",
+ (((uint64_t)readl(&port->ip_mem->pci_err_addr_h)
+ << 32)
+ | readl(&port->ip_mem->pci_err_addr_l))
+ & IOC4_PCI_ERR_ADDR_ADDR_MSK, '1' +
+ ((char)(readl(&port->ip_mem-> pci_err_addr_l) &
+ IOC4_PCI_ERR_ADDR_MST_NUM_MSK) >> 1),
+ (readl(&port->ip_mem->pci_err_addr_l)
+ & IOC4_PCI_ERR_ADDR_MST_TYP_MSK)
+ ? "RX" : "TX");
+
+ if (readl(&port->ip_mem->pci_err_addr_l)
+ & IOC4_PCI_ERR_ADDR_MUL_ERR) {
+ printk(KERN_ERR
+ "Multiple errors occurred\n");
+ }
+ }
+ spin_unlock_irqrestore(&port->ip_lock, flags);
+
+ /* Re-enable DMA error interrupts */
+ write_ireg(port->ip_ioc4_soft, hooks->intr_dma_error, IOC4_W_IES,
+ IOC4_OTHER_INTR_TYPE);
+}
+
+/**
+ * intr_connect - interrupt connect function
+ * @soft: soft struct for this card
+ * @type: interrupt type
+ * @intrbits: bit pattern to set
+ * @intr: handler function
+ * @info: handler arg
+ */
+static void
+intr_connect(struct ioc4_soft *soft, int type,
+ uint32_t intrbits, ioc4_intr_func_f * intr, void *info)
+{
+ int i;
+ struct ioc4_intr_info *intr_ptr;
+
+ BUG_ON(!((type == IOC4_SIO_INTR_TYPE)
+ || (type == IOC4_OTHER_INTR_TYPE)));
+
+ i = atomic_inc(&soft-> is_intr_type[type].is_num_intrs) - 1;
+ BUG_ON(!(i < MAX_IOC4_INTR_ENTS || (printk("i %d\n", i), 0)));
+
+ /* Save off the lower level interrupt handler */
+ intr_ptr = &soft->is_intr_type[type].is_intr_info[i];
+ intr_ptr->sd_bits = intrbits;
+ intr_ptr->sd_intr = intr;
+ intr_ptr->sd_info = info;
+}
+
+/**
+ * ioc4_intr - Top level IOC4 interrupt handler.
+ * @irq: irq value
+ * @arg: handler arg
+ * @regs: registers
+ */
+static irqreturn_t ioc4_intr(int irq, void *arg, struct pt_regs *regs)
+{
+ struct ioc4_soft *soft;
+ uint32_t this_ir, this_mir;
+ int xx, num_intrs = 0;
+ int intr_type;
+ int handled = 0;
+ struct ioc4_intr_info *ii;
+
+ soft = arg;
+ for (intr_type = 0; intr_type < IOC4_NUM_INTR_TYPES; intr_type++) {
+ num_intrs = (int)atomic_read(
+ &soft->is_intr_type[intr_type].is_num_intrs);
+
+ this_mir = this_ir = pending_intrs(soft, intr_type);
+
+ /* Farm out the interrupt to the various drivers depending on
+ * which interrupt bits are set.
+ */
+ for (xx = 0; xx < num_intrs; xx++) {
+ ii = &soft->is_intr_type[intr_type].is_intr_info[xx];
+ if ((this_mir = this_ir & ii->sd_bits)) {
+ /* Disable owned interrupts, call handler */
+ handled++;
+ write_ireg(soft, ii->sd_bits, IOC4_W_IEC,
+ intr_type);
+ ii->sd_intr(ii->sd_info, this_mir);
+ this_ir &= ~this_mir;
+ }
+ }
+ if (this_ir) {
+ printk(KERN_ERR
+ "unknown IOC4 %s interrupt 0x%x, sio_ir = 0x%x,"
+ " sio_ies = 0x%x, other_ir = 0x%x :"
+ "other_ies = 0x%x\n",
+ (intr_type == IOC4_SIO_INTR_TYPE) ? "sio" :
+ "other", this_ir,
+ readl(&soft->is_ioc4_mem_addr->sio_ir),
+ readl(&soft->is_ioc4_mem_addr->sio_ies_ro),
+ readl(&soft->is_ioc4_mem_addr->other_ir),
+ readl(&soft->is_ioc4_mem_addr->other_ies_ro));
+ }
+ }
+#ifdef DEBUG_INTERRUPTS
+ {
+ struct ioc4_mem __iomem *mem = soft->is_ioc4_mem_addr;
+ spinlock_t *lp = &soft->is_ir_lock;
+ unsigned long flag;
+
+ spin_lock_irqsave(&soft->is_ir_lock, flag);
+ printk ("%s : %d : mem 0x%p sio_ir 0x%x sio_ies_ro 0x%x "
+ "other_ir 0x%x other_ies_ro 0x%x mask 0x%x\n",
+ __FUNCTION__, __LINE__,
+ (void *)mem, readl(&mem->sio_ir),
+ readl(&mem->sio_ies_ro),
+ readl(&mem->other_ir),
+ readl(&mem->other_ies_ro),
+ IOC4_OTHER_IR_ATA_INT | IOC4_OTHER_IR_ATA_MEMERR);
+ spin_unlock_irqrestore(&soft->is_ir_lock, flag);
+ }
+#endif
+ return handled ? IRQ_HANDLED : IRQ_NONE;
+}
+
+/**
+ * ioc4_attach_local - Device initialization.
+ * Called at *_attach() time for each
+ * IOC4 with serial ports in the system.
+ * @control: ioc4_control ptr
+ * @pdev: PCI handle for this device
+ * @soft: soft struct for this device
+ * @ioc4: ioc4 mem space
+ */
+static int inline ioc4_attach_local(struct pci_dev *pdev,
+ struct ioc4_control *control,
+ struct ioc4_soft *soft, void __iomem *ioc4_mem,
+ void __iomem *ioc4_serial)
+{
+ struct ioc4_port *port;
+ struct ioc4_port *ports[IOC4_NUM_SERIAL_PORTS];
+ int port_number;
+ uint16_t ioc4_revid_min = 62;
+ uint16_t ioc4_revid;
+
+ /* IOC4 firmware must be at least rev 62 */
+ pci_read_config_word(pdev, PCI_COMMAND_SPECIAL, &ioc4_revid);
+
+ printk(KERN_INFO "IOC4 firmware revision %d\n", ioc4_revid);
+ if (ioc4_revid < ioc4_revid_min) {
+ printk(KERN_WARNING
+ "IOC4 serial not supported on firmware rev %d, "
+ "please upgrade to rev %d or higher\n",
+ ioc4_revid, ioc4_revid_min);
+ return -EPERM;
+ }
+ BUG_ON(ioc4_mem == NULL);
+ BUG_ON(ioc4_serial == NULL);
+
+ /* Create port structures for each port */
+ for (port_number = 0; port_number < IOC4_NUM_SERIAL_PORTS;
+ port_number++) {
+ port = kmalloc(sizeof(struct ioc4_port), GFP_KERNEL);
+ if (!port) {
+ printk(KERN_WARNING
+ "IOC4 serial memory not available for port\n");
+ return -ENOMEM;
+ }
+ memset(port, 0, sizeof(struct ioc4_port));
+
+ /* we need to remember the previous ones, to point back to
+ * them farther down - setting up the ring buffers.
+ */
+ ports[port_number] = port;
+
+ /* Allocate buffers and jumpstart the hardware. */
+ control->ic_port[port_number].icp_port = port;
+ port->ip_ioc4_soft = soft;
+ port->ip_pdev = pdev;
+ port->ip_ienb = 0;
+ port->ip_pci_bus_speed = IOC4_SER_XIN_CLK;
+ port->ip_baud = 9600;
+ port->ip_control = control;
+ port->ip_mem = ioc4_mem;
+ port->ip_serial = ioc4_serial;
+
+ /* point to the right hook */
+ port->ip_hooks = &hooks_array[port_number];
+
+ /* Get direct hooks to the serial regs and uart regs
+ * for this port
+ */
+ switch (port_number) {
+ case 0:
+ port->ip_serial_regs = &(port->ip_serial->port_0);
+ port->ip_uart_regs = &(port->ip_serial->uart_0);
+ break;
+ case 1:
+ port->ip_serial_regs = &(port->ip_serial->port_1);
+ port->ip_uart_regs = &(port->ip_serial->uart_1);
+ break;
+ case 2:
+ port->ip_serial_regs = &(port->ip_serial->port_2);
+ port->ip_uart_regs = &(port->ip_serial->uart_2);
+ break;
+ default:
+ case 3:
+ port->ip_serial_regs = &(port->ip_serial->port_3);
+ port->ip_uart_regs = &(port->ip_serial->uart_3);
+ break;
+ }
+
+ /* ring buffers are 1 to a pair of ports */
+ if (port_number && (port_number & 1)) {
+ /* odd use the evens buffer */
+ port->ip_dma_ringbuf =
+ ports[port_number - 1]->ip_dma_ringbuf;
+ port->ip_cpu_ringbuf =
+ ports[port_number - 1]->ip_cpu_ringbuf;
+ port->ip_inring = RING(port, RX_1_OR_3);
+ port->ip_outring = RING(port, TX_1_OR_3);
+
+ } else {
+ if (port->ip_dma_ringbuf == 0) {
+ 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));
+ DPRINT_CONFIG(("%s : ip_cpu_ringbuf 0x%p "
+ "ip_dma_ringbuf 0x%p\n",
+ __FUNCTION__,
+ (void *)port->ip_cpu_ringbuf,
+ (void *)port->ip_dma_ringbuf));
+ port->ip_inring = RING(port, RX_0_OR_2);
+ port->ip_outring = RING(port, TX_0_OR_2);
+ }
+ DPRINT_CONFIG(("%s : port %d [addr 0x%p] control 0x%p",
+ __FUNCTION__,
+ port_number, (void *)port, (void *)control));
+ 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 IOC4 */
+ port_init(port);
+
+ DPRINT_CONFIG(("%s: port_number %d port 0x%p inring 0x%p "
+ "outring 0x%p\n",
+ __FUNCTION__,
+ port_number, (void *)port,
+ (void *)port->ip_inring,
+ (void *)port->ip_outring));
+
+ /* Attach interrupt handlers */
+ intr_connect(soft, IOC4_SIO_INTR_TYPE,
+ GET_SIO_IR(port_number),
+ handle_intr, port);
+
+ intr_connect(soft, IOC4_OTHER_INTR_TYPE,
+ GET_OTHER_IR(port_number),
+ handle_dma_error_intr, port);
+ }
+ return 0;
+}
+
+/**
+ * enable_intrs - enable interrupts
+ * @port: port to enable
+ * @mask: mask to use
+ */
+static void enable_intrs(struct ioc4_port *port, uint32_t mask)
+{
+ struct hooks *hooks = port->ip_hooks;
+
+ if ((port->ip_ienb & mask) != mask) {
+ write_ireg(port->ip_ioc4_soft, mask, IOC4_W_IES,
+ IOC4_SIO_INTR_TYPE);
+ port->ip_ienb |= mask;
+ }
+
+ if (port->ip_ienb)
+ write_ireg(port->ip_ioc4_soft, hooks->intr_dma_error,
+ IOC4_W_IES, IOC4_OTHER_INTR_TYPE);
+}
+
+/**
+ * local_open - local open a port
+ * @port: port to open
+ */
+static inline int local_open(struct ioc4_port *port)
+{
+ int spiniter = 0;
+
+ port->ip_flags = 0;
+
+ /* Pause the DMA interface if necessary */
+ if (port->ip_sscr & IOC4_SSCR_DMA_EN) {
+ writel(port->ip_sscr | IOC4_SSCR_DMA_PAUSE,
+ &port->ip_serial_regs->sscr);
+ while((readl(&port->ip_serial_regs-> sscr)
+ & IOC4_SSCR_PAUSE_STATE) == 0) {
+ spiniter++;
+ if (spiniter > MAXITER) {
+ 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->i4u_fcr);
+
+ writeb(UART_LCR_WLEN8, &port->ip_uart_regs->i4u_lcr);
+ /* UART_LCR_STOP == 1 stop */
+
+ /* Re-enable DMA, set default threshold to intr whenever there is
+ * data available.
+ */
+ port->ip_sscr &= ~IOC4_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 ioc4_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.
+ */
+ threshold = timeout * port->ip_baud / 10 / HZ / 4;
+ if (threshold == 0)
+ threshold = 1; /* otherwise we'll intr all the time! */
+
+ if ((unsigned)threshold > (unsigned)IOC4_SSCR_RX_THRESHOLD)
+ return 1;
+
+ port->ip_sscr &= ~IOC4_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 */
+ timeout = timeout * IOC4_SRTR_HZ / HZ;
+ if (timeout > IOC4_SRTR_CNT)
+ timeout = IOC4_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 ioc4_port *port,
+ int baud, int byte_size, int stop_bits, int parenb, int parodd)
+{
+ char lcr, sizebits;
+ int spiniter = 0;
+
+ DPRINT_CONFIG(("%s: baud %d byte_size %d stop %d parenb %d parodd %d\n",
+ __FUNCTION__, 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 & IOC4_SSCR_DMA_EN) {
+ writel(port->ip_sscr | IOC4_SSCR_DMA_PAUSE,
+ &port->ip_serial_regs->sscr);
+ while((readl(&port->ip_serial_regs->sscr)
+ & IOC4_SSCR_PAUSE_STATE) == 0) {
+ spiniter++;
+ if (spiniter > MAXITER)
+ return -1;
+ }
+ }
+
+ /* Clear relevant fields in lcr */
+ lcr = readb(&port->ip_uart_regs->i4u_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->i4u_lcr);
+
+ /* Re-enable the DMA interface if necessary */
+ if (port->ip_sscr & IOC4_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, port->ip_rx_timeout);
+
+ 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 ioc4_port *port, char *buf, int len)
+{
+ int prod_ptr, cons_ptr, total = 0;
+ struct ring *outring;
+ struct ring_entry *entry;
+ struct 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] = IOC4_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] |= IOC4_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 & IOC4_SSCR_DMA_EN)) {
+ port->ip_sscr |= IOC4_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 void disable_intrs(struct ioc4_port *port, uint32_t mask)
+{
+ struct hooks *hooks = port->ip_hooks;
+
+ if (port->ip_ienb & mask) {
+ write_ireg(port->ip_ioc4_soft, mask, IOC4_W_IEC,
+ IOC4_SIO_INTR_TYPE);
+ port->ip_ienb &= ~mask;
+ }
+
+ if (!port->ip_ienb)
+ write_ireg(port->ip_ioc4_soft, hooks->intr_dma_error,
+ IOC4_W_IEC, IOC4_OTHER_INTR_TYPE);
+}
+
+/**
+ * set_notification - Modify event notification
+ * @port: port to use
+ * @mask: events mask
+ * @set_on: set ?
+ */
+static int set_notification(struct ioc4_port *port, int mask, int set_on)
+{
+ struct 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 |= IOC4_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 |= IOC4_SSCR_DMA_EN;
+ else if (!(port->ip_ienb & hooks->intr_tx_mt))
+ port->ip_sscr &= ~IOC4_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
+ * @set: set ?
+ * @mask1: mcr mask
+ * @mask2: shadow mask
+ */
+static inline int set_mcr(struct uart_port *the_port, int set,
+ int mask1, int mask2)
+{
+ struct ioc4_port *port = get_ioc4_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 & IOC4_SSCR_DMA_EN) {
+ writel(port->ip_sscr | IOC4_SSCR_DMA_PAUSE,
+ &port->ip_serial_regs->sscr);
+ while ((readl(&port->ip_serial_regs->sscr)
+ & IOC4_SSCR_PAUSE_STATE) == 0) {
+ spiniter++;
+ if (spiniter > MAXITER)
+ return -1;
+ }
+ }
+ shadow = readl(&port->ip_serial_regs->shadow);
+ mcr = (shadow & 0xff000000) >> 24;
+
+ /* Set new value */
+ if (set) {
+ mcr |= mask1;
+ shadow |= mask2;
+ } else {
+ mcr &= ~mask1;
+ shadow &= ~mask2;
+ }
+ writeb(mcr, &port->ip_uart_regs->i4u_mcr);
+ writel(shadow, &port->ip_serial_regs->shadow);
+
+ /* Re-enable the DMA interface if necessary */
+ if (port->ip_sscr & IOC4_SSCR_DMA_EN) {
+ writel(port->ip_sscr, &port->ip_serial_regs->sscr);
+ }
+ return 0;
+}
+
+/**
+ * ioc4_set_proto - set the protocol for the port
+ * @port: port to use
+ * @proto: protocol to use
+ */
+static int ioc4_set_proto(struct ioc4_port *port, enum sio_proto proto)
+{
+ struct hooks *hooks = port->ip_hooks;
+
+ switch (proto) {
+ case PROTO_RS232:
+ /* Clear the appropriate GIO pin */
+ writel(0, (&port->ip_mem->gppr_0 +
+ hooks->rs422_select_pin));
+ break;
+
+ case PROTO_RS422:
+ /* Set the appropriate GIO pin */
+ writel(1, (&port->ip_mem->gppr_0 +
+ hooks->rs422_select_pin));
+ break;
+
+ default:
+ return 1;
+ }
+ return 0;
+}
+
+/**
+ * transmit_chars - upper level write, called with ip_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 ioc4_port *port = get_ioc4_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);
+ }
+}
+
+/**
+ * ioc4_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
+ioc4_change_speed(struct uart_port *the_port,
+ struct termios *new_termios, struct termios *old_termios)
+{
+ struct ioc4_port *port = get_ioc4_port(the_port);
+ int baud, bits;
+ unsigned cflag, cval;
+ int new_parity = 0, new_parity_enable = 0, new_stop = 1, new_data = 8;
+ struct uart_info *info = the_port->info;
+
+ cflag = new_termios->c_cflag;
+
+ switch (cflag & CSIZE) {
+ case CS5:
+ new_data = 5;
+ cval = 0x00;
+ bits = 7;
+ break;
+ case CS6:
+ new_data = 6;
+ cval = 0x01;
+ bits = 8;
+ break;
+ case CS7:
+ new_data = 7;
+ cval = 0x02;
+ bits = 9;
+ break;
+ case CS8:
+ new_data = 8;
+ cval = 0x03;
+ bits = 10;
+ break;
+ default:
+ /* cuz we always need a default ... */
+ new_data = 5;
+ cval = 0x00;
+ bits = 7;
+ break;
+ }
+ if (cflag & CSTOPB) {
+ cval |= 0x04;
+ bits++;
+ new_stop = 1;
+ }
+ if (cflag & PARENB) {
+ cval |= UART_LCR_PARITY;
+ bits++;
+ new_parity_enable = 1;
+ }
+ if (cflag & PARODD) {
+ cval |= UART_LCR_EPAR;
+ new_parity = 1;
+ }
+ if (cflag & IGNPAR) {
+ cval &= ~UART_LCR_PARITY;
+ new_parity_enable = 0;
+ }
+ baud = uart_get_baud_rate(the_port, new_termios, old_termios,
+ MIN_BAUD_SUPPORTED, MAX_BAUD_SUPPORTED);
+ DPRINT_CONFIG(("%s: returned baud %d\n", __FUNCTION__, baud));
+
+ /* default is 9600 */
+ if (!baud)
+ baud = 9600;
+
+ if (!the_port->fifosize)
+ the_port->fifosize = IOC4_MAX_CHARS;
+ the_port->timeout = ((the_port->fifosize * HZ * bits) / (baud / 10));
+ the_port->timeout += HZ / 50; /* Add .02 seconds of slop */
+
+ the_port->ignore_status_mask = N_ALL_INPUT;
+
+ 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)
+ info->flags |= ASYNC_CTS_FLOW;
+ else
+ info->flags &= ~ASYNC_CTS_FLOW;
+
+ /* Set the configuration and proper notification call */
+ DPRINT_CONFIG(("%s : port 0x%p cflag 0%o "
+ "config_port(baud %d data %d stop %d p enable %d parity %d),"
+ " notification 0x%x\n",
+ __FUNCTION__, (void *)port, 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);
+ }
+}
+
+/**
+ * ic4_startup_local - Start up the serial port - returns >= 0 if no errors
+ * @the_port: Port to operate on
+ */
+static inline int ic4_startup_local(struct uart_port *the_port)
+{
+ int retval = 0;
+ struct ioc4_port *port;
+ struct uart_info *info;
+
+ if (!the_port)
+ return -1;
+
+ port = get_ioc4_port(the_port);
+ if (!port)
+ return -1;
+
+ info = the_port->info;
+ if (info->flags & UIF_INITIALIZED) {
+ return retval;
+ }
+
+ if (info->tty) {
+ set_bit(TTY_IO_ERROR, &info->tty->flags);
+ clear_bit(TTY_IO_ERROR, &info->tty->flags);
+ if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
+ info->tty->alt_speed = 57600;
+ if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
+ info->tty->alt_speed = 115200;
+ if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
+ info->tty->alt_speed = 230400;
+ if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
+ info->tty->alt_speed = 460800;
+ }
+ local_open(port);
+
+ /* set the speed of the serial port */
+ ioc4_change_speed(the_port, info->tty->termios, (struct termios *)0);
+
+ /* enable hardware flow control - after ioc4_change_speed because
+ * ASYNC_CTS_FLOW is set there */
+ if (info->flags & ASYNC_CTS_FLOW) {
+ port->ip_sscr |= IOC4_SSCR_HFC_EN;
+ writel(port->ip_sscr, &port->ip_serial_regs->sscr);
+ }
+ info->flags |= UIF_INITIALIZED;
+ return 0;
+}
+
+/*
+ * ioc4_cb_output_lowat - called when the output low water mark is hit
+ * @port: port to output
+ */
+static void ioc4_cb_output_lowat(struct ioc4_port *port)
+{
+ /* ip_lock is set on the call here */
+ if (port->ip_port) {
+ transmit_chars(port->ip_port);
+ }
+}
+
+
+/**
+ * handle_intr - service any interrupts for the given port - 2nd level
+ * called via sd_intr
+ * @arg: handler arg
+ * @sio_ir: ioc4regs
+ */
+static void handle_intr(void *arg, uint32_t sio_ir)
+{
+ struct ioc4_port *port = (struct ioc4_port *)arg;
+ struct hooks *hooks = port->ip_hooks;
+ unsigned int rx_high_rd_aborted = 0;
+ unsigned int flags;
+ struct uart_port *the_port;
+ int loop_counter;
+
+ /* 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 &= ~(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 "IOC4 serial: "
+ "possible hang condition/"
+ "port stuck on interrupt.\n");
+ break;
+ }
+
+ /* Handle a DCD change */
+ if (sio_ir & hooks->intr_delta_dcd) {
+ /* ACK the interrupt */
+ writel(hooks->intr_delta_dcd,
+ &port->ip_mem->sio_ir);
+
+ shadow = readl(&port->ip_serial_regs->shadow);
+
+ if ((port->ip_notify & N_DDCD)
+ && (shadow & IOC4_SHADOW_DCD)
+ && (port->ip_port)) {
+ the_port = port->ip_port;
+ the_port->icount.dcd = 1;
+ wake_up_interruptible
+ (&the_port-> info->delta_msr_wait);
+ } else if ((port->ip_notify & N_DDCD)
+ && !(shadow & IOC4_SHADOW_DCD)) {
+ /* Flag delta DCD/no DCD */
+ port->ip_flags |= DCD_ON;
+ }
+ }
+
+ /* Handle a CTS change */
+ if (sio_ir & hooks->intr_delta_cts) {
+ /* ACK the interrupt */
+ writel(hooks->intr_delta_cts,
+ &port->ip_mem->sio_ir);
+
+ shadow = readl(&port->ip_serial_regs->shadow);
+
+ if ((port->ip_notify & N_DCTS)
+ && (port->ip_port)) {
+ the_port = port->ip_port;
+ the_port->icount.cts =
+ (shadow & IOC4_SHADOW_CTS) ? 1 : 0;
+ 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) {
+ /* ACK the interrupt */
+ writel(hooks->intr_rx_timer,
+ &port->ip_mem->sio_ir);
+
+ if ((port->ip_notify & N_DATA_READY)
+ && (port->ip_port)) {
+ /* ip_lock is set on call here */
+ 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) {
+ /* ip_lock is set on call here */
+ 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(port)) & hooks->intr_rx_high) {
+ if ((port->ip_flags & READ_ABORTED) == 0) {
+ port->ip_ienb &= ~hooks->intr_rx_high;
+ port->ip_flags |= INPUT_HIGH;
+ } else {
+ rx_high_rd_aborted++;
+ }
+ }
+ }
+
+ /* 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;
+
+ /* ACK the interrupt */
+ writel(hooks->intr_tx_explicit,
+ &port->ip_mem->sio_ir);
+
+ if (port->ip_notify & N_OUTPUT_LOWAT)
+ ioc4_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) {
+ ioc4_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(port);
+ }
+
+ /* 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
+ & IOC4_SSCR_DMA_EN));
+ port->ip_sscr &= ~IOC4_SSCR_DMA_EN;
+ writel(port->ip_sscr,
+ &port->ip_serial_regs->sscr);
+ }
+
+ /* Prevent infinite tx_mt interrupt */
+ port->ip_ienb &= ~hooks->intr_tx_mt;
+ }
+ }
+ sio_ir = PENDING(port);
+
+ /* 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);
+
+ /* Re-enable interrupts before returning from interrupt handler.
+ * Getting interrupted here is okay. It'll just v() our semaphore, and
+ * we'll come through the loop again.
+ */
+
+ write_ireg(port->ip_ioc4_soft, port->ip_ienb, IOC4_W_IES,
+ IOC4_SIO_INTR_TYPE);
+}
+
+/*
+ * ioc4_cb_post_ncs - called for some basic errors
+ * @port: port to use
+ * @ncs: event
+ */
+static void ioc4_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, unsigned char *buf,
+ int len)
+{
+ int prod_ptr, cons_ptr, total;
+ struct ioc4_port *port = get_ioc4_port(the_port);
+ struct ring *inring;
+ struct ring_entry *entry;
+ struct 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 IOC4. 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 | IOC4_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 & IOC4_SSCR_DMA_EN)) {
+ port->ip_sscr |= IOC4_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 | IOC4_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) &
+ IOC4_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 &= ~IOC4_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 "IOC4 serial: "
+ "possible hang condition/"
+ "port stuck on read.\n");
+ 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 & IOC4_RXSB_MODEM_VALID)
+ && (port->ip_notify & N_DDCD)) {
+ /* Notify upper layer if DCD dropped */
+
+ if ((port->ip_flags & DCD_ON)
+ && !(*sc & IOC4_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 &= ~IOC4_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) {
+ the_port->icount.dcd = 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 & IOC4_RXSB_MODEM_VALID) {
+ /* Notify that an input overrun occurred */
+ if ((*sc & IOC4_RXSB_OVERRUN)
+ && (port->ip_notify & N_OVERRUN_ERROR)) {
+ ioc4_cb_post_ncs(the_port, NCS_OVERRUN);
+ }
+ /* Don't look at this byte again */
+ *sc &= ~IOC4_RXSB_MODEM_VALID;
+ }
+
+ /* Check for valid data or RX errors */
+ if ((*sc & IOC4_RXSB_DATA_VALID) &&
+ ((*sc & (IOC4_RXSB_PAR_ERR
+ | IOC4_RXSB_FRAME_ERR
+ | IOC4_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 & IOC4_RXSB_PAR_ERR) &&
+ (port->ip_notify & N_PARITY_ERROR)) {
+ ioc4_cb_post_ncs(the_port,
+ NCS_PARITY);
+ }
+ if ((*sc & IOC4_RXSB_FRAME_ERR) &&
+ (port->ip_notify & N_FRAMING_ERROR)){
+ ioc4_cb_post_ncs(the_port,
+ NCS_FRAMING);
+ }
+ if ((*sc & IOC4_RXSB_BREAK)
+ && (port->ip_notify & N_BREAK)) {
+ ioc4_cb_post_ncs
+ (the_port,
+ NCS_BREAK);
+ }
+ len = 1;
+ }
+ }
+ if (*sc & IOC4_RXSB_DATA_VALID) {
+ *sc &= ~IOC4_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 &
+ IOC4_SSCR_RX_THRESHOLD)
+ << IOC4_PROD_CONS_PTR_OFF))) {
+ port->ip_flags &= ~INPUT_HIGH;
+ enable_intrs(port, hooks->intr_rx_high);
+ }
+ return total;
+}
+/**
+ * receive_chars - upper level read. Called with ip_lock.
+ * @the_port: port to read from
+ */
+static void receive_chars(struct uart_port *the_port)
+{
+ struct tty_struct *tty;
+ unsigned char ch[IOC4_MAX_CHARS];
+ int read_count, request_count;
+ struct uart_icount *icount;
+ struct uart_info *info = the_port->info;
+
+ /* Make sure all the pointers are "good" ones */
+ if (!info)
+ return;
+ if (!info->tty)
+ return;
+
+ tty = info->tty;
+
+ request_count = TTY_FLIPBUF_SIZE - tty->flip.count - 1;
+
+ if (request_count > 0) {
+ if (request_count > IOC4_MAX_CHARS - 2)
+ request_count = IOC4_MAX_CHARS - 2;
+ icount = &the_port->icount;
+ read_count = do_read(the_port, ch, request_count);
+ if (read_count > 0) {
+ 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;
+ icount->rx += read_count;
+ }
+ }
+ tty_flip_buffer_push(tty);
+}
+
+/**
+ * ic4_type - What type of console are we?
+ * @port: Port to operate with (we ignore since we only have one port)
+ *
+ */
+static const char *ic4_type(struct uart_port *the_port)
+{
+ return "SGI IOC4 Serial";
+}
+
+/**
+ * ic4_tx_empty - Is the transmitter empty? We pretend we're always empty
+ * @port: Port to operate on (we ignore since we always return 1)
+ *
+ */
+static unsigned int ic4_tx_empty(struct uart_port *the_port)
+{
+ return 1;
+}
+
+/**
+ * ic4_stop_tx - stop the transmitter
+ * @port: Port to operate on
+ * @tty_stop: Set to 1 if called via uart_stop
+ *
+ */
+static void ic4_stop_tx(struct uart_port *the_port, unsigned int tty_stop)
+{
+}
+
+/**
+ * null_void_function -
+ * @port: Port to operate on
+ *
+ */
+static void null_void_function(struct uart_port *the_port)
+{
+}
+
+/**
+ * ic4_shutdown - shut down the port - free irq and disable
+ * @port: Port to shut down
+ *
+ */
+static void ic4_shutdown(struct uart_port *the_port)
+{
+ unsigned long port_flags;
+ struct ioc4_port *port;
+ struct uart_info *info;
+
+ port = get_ioc4_port(the_port);
+ if (!port)
+ return;
+
+ info = the_port->info;
+
+ if (!(info->flags & UIF_INITIALIZED))
+ return;
+
+ wake_up_interruptible(&info->delta_msr_wait);
+
+ if (info->tty)
+ set_bit(TTY_IO_ERROR, &info->tty->flags);
+
+ spin_lock_irqsave(&port->ip_lock, port_flags);
+ set_notification(port, N_ALL, 0);
+ info->flags &= ~UIF_INITIALIZED;
+ spin_unlock_irqrestore(&port->ip_lock, port_flags);
+}
+
+/**
+ * ic4_set_mctrl - set control lines (dtr, rts, etc)
+ * @port: Port to operate on
+ * @mctrl: Lines to set/unset
+ *
+ */
+static void ic4_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, 1, mcr, IOC4_SHADOW_DTR);
+}
+
+/**
+ * ic4_get_mctrl - get control line info
+ * @port: port to operate on
+ *
+ */
+static unsigned int ic4_get_mctrl(struct uart_port *the_port)
+{
+ struct ioc4_port *port = get_ioc4_port(the_port);
+ uint32_t shadow;
+ unsigned int ret = 0;
+
+ if (!port)
+ return 0;
+
+ shadow = readl(&port->ip_serial_regs->shadow);
+ if (shadow & IOC4_SHADOW_DCD)
+ ret |= TIOCM_CAR;
+ if (shadow & IOC4_SHADOW_DR)
+ ret |= TIOCM_DSR;
+ if (shadow & IOC4_SHADOW_CTS)
+ ret |= TIOCM_CTS;
+ return ret;
+}
+
+/**
+ * ic4_start_tx - Start transmitter, flush any output
+ * @port: Port to operate on
+ * @tty_stop: Set to 1 if called via uart_start
+ *
+ */
+static void ic4_start_tx(struct uart_port *the_port, unsigned int tty_stop)
+{
+ struct ioc4_port *port = get_ioc4_port(the_port);
+ unsigned long flags;
+
+ if (port) {
+ spin_lock_irqsave(&port->ip_lock, flags);
+ transmit_chars(the_port);
+ spin_unlock_irqrestore(&port->ip_lock, flags);
+ }
+}
+
+/**
+ * ic4_break_ctl - handle breaks
+ * @port: Port to operate on
+ * @break_state: Break state
+ *
+ */
+static void ic4_break_ctl(struct uart_port *the_port, int break_state)
+{
+}
+
+/**
+ * ic4_startup - Start up the serial port - always return 0 (We're always on)
+ * @port: Port to operate on
+ *
+ */
+static int ic4_startup(struct uart_port *the_port)
+{
+ int retval;
+ struct ioc4_port *port;
+ struct ioc4_control *control;
+ struct uart_info *info;
+ unsigned long port_flags;
+
+ if (!the_port) {
+ return -ENODEV;
+ }
+ port = get_ioc4_port(the_port);
+ if (!port) {
+ return -ENODEV;
+ }
+ info = the_port->info;
+
+ control = port->ip_control;
+ if (!control) {
+ return -ENODEV;
+ }
+
+ /* Start up the serial port */
+ spin_lock_irqsave(&port->ip_lock, port_flags);
+ retval = ic4_startup_local(the_port);
+ spin_unlock_irqrestore(&port->ip_lock, port_flags);
+ return retval;
+}
+
+/**
+ * ic4_set_termios - set termios stuff
+ * @port: port to operate on
+ * @termios: New settings
+ * @termios: Old
+ *
+ */
+static void
+ic4_set_termios(struct uart_port *the_port,
+ struct termios *termios, struct termios *old_termios)
+{
+ struct ioc4_port *port = get_ioc4_port(the_port);
+ unsigned long port_flags;
+
+ spin_lock_irqsave(&port->ip_lock, port_flags);
+ ioc4_change_speed(the_port, termios, old_termios);
+ spin_unlock_irqrestore(&port->ip_lock, port_flags);
+}
+
+/**
+ * ic4_request_port - allocate resources for port - no op....
+ * @port: port to operate on
+ *
+ */
+static int ic4_request_port(struct uart_port *port)
+{
+ return 0;
+}
+
+/* Associate the uart functions above - given to serial core */
+
+static struct uart_ops ioc4_ops = {
+ .tx_empty = ic4_tx_empty,
+ .set_mctrl = ic4_set_mctrl,
+ .get_mctrl = ic4_get_mctrl,
+ .stop_tx = ic4_stop_tx,
+ .start_tx = ic4_start_tx,
+ .stop_rx = null_void_function,
+ .enable_ms = null_void_function,
+ .break_ctl = ic4_break_ctl,
+ .startup = ic4_startup,
+ .shutdown = ic4_shutdown,
+ .set_termios = ic4_set_termios,
+ .type = ic4_type,
+ .release_port = null_void_function,
+ .request_port = ic4_request_port,
+};
+
+/*
+ * Boot-time initialization code
+ */
+
+static struct uart_driver ioc4_uart = {
+ .owner = THIS_MODULE,
+ .driver_name = "ioc4_serial",
+ .dev_name = DEVICE_NAME,
+ .major = DEVICE_MAJOR,
+ .minor = DEVICE_MINOR,
+ .nr = IOC4_NUM_CARDS * IOC4_NUM_SERIAL_PORTS,
+};
+
+/**
+ * ioc4_serial_core_attach - register with serial core
+ * This is done during pci probing
+ * @pdev: handle for this card
+ */
+static inline int
+ioc4_serial_core_attach(struct pci_dev *pdev)
+{
+ struct ioc4_port *port;
+ struct uart_port *the_port;
+ struct ioc4_control *control = pci_get_drvdata(pdev);
+ int ii;
+
+ DPRINT_CONFIG(("%s: attach pdev 0x%p - control 0x%p\n",
+ __FUNCTION__, pdev, (void *)control));
+
+ if (!control)
+ return -ENODEV;
+
+ /* once around for each port on this card */
+ for (ii = 0; ii < IOC4_NUM_SERIAL_PORTS; ii++) {
+ the_port = &control->ic_port[ii].icp_uart_port;
+ port = control->ic_port[ii].icp_port;
+ port->ip_port = the_port;
+
+ DPRINT_CONFIG(("%s: attach the_port 0x%p / port 0x%p\n",
+ __FUNCTION__, (void *)the_port,
+ (void *)port));
+
+ spin_lock_init(&the_port->lock);
+ /* membase, iobase and mapbase just need to be non-0 */
+ the_port->membase = (unsigned char __iomem *)1;
+ the_port->line = the_port->iobase = ii;
+ the_port->mapbase = 1;
+ the_port->type = PORT_16550A;
+ the_port->fifosize = IOC4_MAX_CHARS;
+ the_port->ops = &ioc4_ops;
+ the_port->irq = control->ic_irq;
+ the_port->dev = &pdev->dev;
+ if (uart_add_one_port(&ioc4_uart, the_port) < 0) {
+ printk(KERN_WARNING
+ "%s: unable to add port %d\n",
+ __FUNCTION__, the_port->line);
+ } else {
+ DPRINT_CONFIG(
+ ("IOC4 serial driver port %d irq = %d\n",
+ the_port->line, the_port->irq));
+ }
+ /* all ports are rs232 for now */
+ ioc4_set_proto(port, PROTO_RS232);
+ }
+ return 0;
+}
+
+/**
+ * ioc4_serial_attach_one - register attach function
+ * called per card found from ioc4_serial_detect as part
+ * of module_init().
+ * @pdev: handle for this card
+ * @pci_id: pci id for this card
+ */
+int
+ioc4_serial_attach_one(struct pci_dev *pdev, const struct pci_device_id *pci_id)
+{
+ struct ioc4_mem __iomem *mem;
+ unsigned long tmp_addr, tmp_addr1;
+ struct ioc4_serial __iomem *serial;
+ struct ioc4_soft *soft;
+ struct ioc4_control *control;
+ int tmp, ret = 0;
+
+
+ DPRINT_CONFIG(("%s (0x%p, 0x%p)\n", __FUNCTION__, pdev, pci_id));
+
+ /* Map in the ioc4 memory */
+ tmp_addr = pci_resource_start(pdev, 0);
+ if (!tmp_addr) {
+ printk(KERN_WARNING
+ "ioc4 (%p) : unable to get PIO mapping for "
+ "MEM space\n", (void *)pdev);
+ return -ENODEV;
+ }
+ if (!request_region(tmp_addr, sizeof(struct ioc4_mem), "sioc4_mem")) {
+ printk(KERN_ALERT
+ "ioc4 (%p): unable to get request region for "
+ "MEM space\n", (void *)pdev);
+ return -ENODEV;
+ }
+ mem = ioremap(tmp_addr, sizeof(struct ioc4_mem));
+ if (!mem) {
+ printk(KERN_WARNING
+ "ioc4 (%p) : unable to remap ioc4 memory\n",
+ (void *)pdev);
+ ret = -ENODEV;
+ goto out1;
+ }
+
+ /* request serial registers */
+ tmp_addr1 = pci_resource_start(pdev, 0) + IOC4_SERIAL_OFFSET;
+
+ if (!request_region(tmp_addr1, sizeof(struct ioc4_serial),
+ "sioc4_uart")) {
+ printk(KERN_WARNING
+ "ioc4 (%p): unable to get request region for "
+ "uart space\n", (void *)pdev);
+ ret = -ENODEV;
+ goto out1;
+ }
+ serial = ioremap(tmp_addr1, sizeof(struct ioc4_serial));
+ if (!serial) {
+ printk(KERN_WARNING
+ "ioc4 (%p) : unable to remap ioc4 serial register\n",
+ (void *)pdev);
+ ret = -ENODEV;
+ goto out2;
+ }
+ DPRINT_CONFIG(("%s : mem 0x%p, serial 0x%p\n",
+ __FUNCTION__, (void *)mem, (void *)serial));
+
+ /* Get memory for the new card */
+ control = kmalloc(sizeof(struct ioc4_control) * IOC4_NUM_SERIAL_PORTS,
+ GFP_KERNEL);
+
+ if (!control) {
+ printk(KERN_WARNING "ioc4_attach_one"
+ ": unable to get memory for the IOC4\n");
+ ret = -ENOMEM;
+ goto out2;
+ }
+ memset(control, 0, sizeof(struct ioc4_control));
+ pci_set_drvdata(pdev, control);
+
+ /* Allocate the soft structure */
+ soft = kmalloc(sizeof(struct ioc4_soft), GFP_KERNEL);
+ if (!soft) {
+ printk(KERN_WARNING
+ "ioc4 (%p): unable to get memory for the soft struct\n",
+ (void *)pdev);
+ ret = -ENOMEM;
+ goto out3;
+ }
+ memset(soft, 0, sizeof(struct ioc4_soft));
+
+ spin_lock_init(&soft->is_ir_lock);
+ soft->is_ioc4_mem_addr = mem;
+ soft->is_ioc4_serial_addr = serial;
+
+ /* Init the IOC4 */
+ pci_read_config_dword(pdev, PCI_COMMAND, &tmp);
+ pci_write_config_dword(pdev, PCI_COMMAND,
+ tmp | PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
+
+ writel(0xf << IOC4_SIO_CR_CMD_PULSE_SHIFT, &mem->sio_cr);
+
+ /* Enable serial port mode select generic PIO pins as outputs */
+ writel(IOC4_GPCR_UART0_MODESEL | IOC4_GPCR_UART1_MODESEL
+ | IOC4_GPCR_UART2_MODESEL | IOC4_GPCR_UART3_MODESEL,
+ &mem->gpcr_s);
+
+ /* Clear and disable all interrupts */
+ write_ireg(soft, ~0, IOC4_W_IEC, IOC4_SIO_INTR_TYPE);
+ writel(~0, &mem->sio_ir);
+ write_ireg(soft, ~(IOC4_OTHER_IR_ATA_INT | IOC4_OTHER_IR_ATA_MEMERR),
+ IOC4_W_IEC, IOC4_OTHER_INTR_TYPE);
+ writel(~(IOC4_OTHER_IR_ATA_MEMERR | IOC4_OTHER_IR_ATA_MEMERR),
+ &mem->other_ir);
+ control->ic_soft = soft;
+ if (!request_irq(pdev->irq, ioc4_intr, SA_SHIRQ,
+ "sgi-ioc4serial", (void *)soft)) {
+ control->ic_irq = pdev->irq;
+ } else {
+ printk(KERN_WARNING
+ "%s : request_irq fails for IRQ 0x%x\n ",
+ __FUNCTION__, pdev->irq);
+ }
+ if ((ret = ioc4_attach_local(pdev, control, soft,
+ soft->is_ioc4_mem_addr,
+ soft->is_ioc4_serial_addr)))
+ goto out4;
+
+ /* register port with the serial core */
+
+ if ((ret = ioc4_serial_core_attach(pdev)))
+ goto out4;
+
+ return ret;
+
+ /* error exits that give back resources */
+out4:
+ kfree(soft);
+out3:
+ kfree(control);
+out2:
+ release_region(tmp_addr1, sizeof(struct ioc4_serial));
+out1:
+ release_region(tmp_addr, sizeof(struct ioc4_mem));
+
+ return ret;
+}
+
+
+/**
+ * ioc4_serial_remove_one - detach function
+ *
+ * @pdev: handle for this card
+ */
+
+#if 0
+void ioc4_serial_remove_one(struct pci_dev *pdev)
+{
+ int ii;
+ struct ioc4_control *control;
+ struct uart_port *the_port;
+ struct ioc4_port *port;
+ struct ioc4_soft *soft;
+
+ control = pci_get_drvdata(pdev);
+
+ for (ii = 0; ii < IOC4_NUM_SERIAL_PORTS; ii++) {
+ the_port = &control->ic_port[ii].icp_uart_port;
+ if (the_port) {
+ uart_remove_one_port(&ioc4_uart, the_port);
+ }
+ port = control->ic_port[ii].icp_port;
+ if (!(ii & 1) && port) {
+ pci_free_consistent(port->ip_pdev,
+ TOTAL_RING_BUF_SIZE,
+ (void *)port->ip_cpu_ringbuf,
+ port->ip_dma_ringbuf);
+ kfree(port);
+ }
+ }
+ soft = control->ic_soft;
+ if (soft) {
+ free_irq(control->ic_irq, (void *)soft);
+ if (soft->is_ioc4_serial_addr) {
+ release_region((unsigned long)
+ soft->is_ioc4_serial_addr,
+ sizeof(struct ioc4_serial));
+ }
+ kfree(soft);
+ }
+ kfree(control);
+ pci_set_drvdata(pdev, NULL);
+ uart_unregister_driver(&ioc4_uart);
+}
+#endif
+
+/**
+ * ioc4_serial_init - module init
+ */
+int ioc4_serial_init(void)
+{
+ int ret;
+
+ /* register with serial core */
+ if ((ret = uart_register_driver(&ioc4_uart)) < 0) {
+ printk(KERN_WARNING
+ "%s: Couldn't register IOC4 serial driver\n",
+ __FUNCTION__);
+ return ret;
+ }
+ return 0;
+}
+
+MODULE_AUTHOR("Pat Gefre - Silicon Graphics Inc. (SGI) <pfg@sgi.com>");
+MODULE_DESCRIPTION("Serial PCI driver module for SGI IOC4 Base-IO Card");
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(ioc4_serial_init);
+EXPORT_SYMBOL(ioc4_serial_attach_one);
diff --git a/drivers/serial/jsm/Makefile b/drivers/serial/jsm/Makefile
new file mode 100644
index 0000000000000..e46b6e0f8b185
--- /dev/null
+++ b/drivers/serial/jsm/Makefile
@@ -0,0 +1,8 @@
+#
+# Makefile for Jasmine adapter
+#
+
+obj-$(CONFIG_SERIAL_JSM) += jsm.o
+
+jsm-objs := jsm_driver.o jsm_neo.o jsm_tty.o
+
diff --git a/drivers/serial/jsm/jsm.h b/drivers/serial/jsm/jsm.h
new file mode 100644
index 0000000000000..6926b100e2b04
--- /dev/null
+++ b/drivers/serial/jsm/jsm.h
@@ -0,0 +1,437 @@
+/************************************************************************
+ * Copyright 2003 Digi International (www.digi.com)
+ *
+ * Copyright (C) 2004 IBM 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the 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.
+ *
+ * Contact Information:
+ * Scott H Kilau <Scott_Kilau@digi.com>
+ * Wendy Xiong <wendyx@us.ltcfwd.linux.ibm.com>
+ *
+ ***********************************************************************/
+
+#ifndef __JSM_DRIVER_H
+#define __JSM_DRIVER_H
+
+#include <linux/kernel.h>
+#include <linux/version.h>
+#include <linux/types.h> /* To pick up the varions Linux types */
+#include <linux/tty.h>
+#include <linux/serial_core.h>
+#include <linux/device.h>
+
+/*
+ * Debugging levels can be set using debug insmod variable
+ * They can also be compiled out completely.
+ */
+enum {
+ DBG_INIT = 0x01,
+ DBG_BASIC = 0x02,
+ DBG_CORE = 0x04,
+ DBG_OPEN = 0x08,
+ DBG_CLOSE = 0x10,
+ DBG_READ = 0x20,
+ DBG_WRITE = 0x40,
+ DBG_IOCTL = 0x80,
+ DBG_PROC = 0x100,
+ DBG_PARAM = 0x200,
+ DBG_PSCAN = 0x400,
+ DBG_EVENT = 0x800,
+ DBG_DRAIN = 0x1000,
+ DBG_MSIGS = 0x2000,
+ DBG_MGMT = 0x4000,
+ DBG_INTR = 0x8000,
+ DBG_CARR = 0x10000,
+};
+
+#define jsm_printk(nlevel, klevel, pdev, fmt, args...) \
+ if ((DBG_##nlevel & jsm_debug)) \
+ dev_printk(KERN_##klevel, pdev->dev, fmt, ## args)
+
+#define MAXPORTS 8
+#define MAX_STOPS_SENT 5
+
+/* Board type definitions */
+
+#define T_NEO 0000
+#define T_CLASSIC 0001
+#define T_PCIBUS 0400
+
+/* Board State Definitions */
+
+#define BD_RUNNING 0x0
+#define BD_REASON 0x7f
+#define BD_NOTFOUND 0x1
+#define BD_NOIOPORT 0x2
+#define BD_NOMEM 0x3
+#define BD_NOBIOS 0x4
+#define BD_NOFEP 0x5
+#define BD_FAILED 0x6
+#define BD_ALLOCATED 0x7
+#define BD_TRIBOOT 0x8
+#define BD_BADKME 0x80
+
+
+/* 4 extra for alignment play space */
+#define WRITEBUFLEN ((4096) + 4)
+#define MYFLIPLEN N_TTY_BUF_SIZE
+
+#define JSM_VERSION "jsm: 1.1-1-INKERNEL"
+#define JSM_PARTNUM "40002438_A-INKERNEL"
+
+/*
+ * All the possible states the driver can be while being loaded.
+ */
+enum {
+ DRIVER_INITIALIZED = 0,
+ DRIVER_READY
+};
+
+/*
+ * All the possible states the board can be while booting up.
+ */
+enum {
+ BOARD_FAILED = 0,
+ BOARD_FOUND,
+ BOARD_READY
+};
+
+struct board_id {
+ u8 *name;
+ u32 maxports;
+};
+
+struct jsm_board;
+struct jsm_channel;
+
+/************************************************************************
+ * Per board operations structure *
+ ************************************************************************/
+struct board_ops {
+ irqreturn_t (*intr) (int irq, void *voidbrd, struct pt_regs *regs);
+ void (*uart_init) (struct jsm_channel *ch);
+ void (*uart_off) (struct jsm_channel *ch);
+ void (*param) (struct jsm_channel *ch);
+ void (*assert_modem_signals) (struct jsm_channel *ch);
+ void (*flush_uart_write) (struct jsm_channel *ch);
+ void (*flush_uart_read) (struct jsm_channel *ch);
+ void (*disable_receiver) (struct jsm_channel *ch);
+ void (*enable_receiver) (struct jsm_channel *ch);
+ void (*send_break) (struct jsm_channel *ch);
+ void (*clear_break) (struct jsm_channel *ch, int);
+ void (*send_start_character) (struct jsm_channel *ch);
+ void (*send_stop_character) (struct jsm_channel *ch);
+ void (*copy_data_from_queue_to_uart) (struct jsm_channel *ch);
+ u32 (*get_uart_bytes_left) (struct jsm_channel *ch);
+ void (*send_immediate_char) (struct jsm_channel *ch, unsigned char);
+};
+
+
+/*
+ * Per-board information
+ */
+struct jsm_board
+{
+ int boardnum; /* Board number: 0-32 */
+
+ int type; /* Type of board */
+ char *name; /* Product Name */
+ u8 rev; /* PCI revision ID */
+ struct pci_dev *pci_dev;
+ u32 maxports; /* MAX ports this board can handle */
+
+ spinlock_t bd_lock; /* Used to protect board */
+
+ spinlock_t bd_intr_lock; /* Used to protect the poller tasklet and
+ * the interrupt routine from each other.
+ */
+
+ u32 state; /* State of card. */
+ wait_queue_head_t state_wait; /* Place to sleep on for state change */
+
+ u32 nasync; /* Number of ports on card */
+
+ u32 irq; /* Interrupt request number */
+ u64 intr_count; /* Count of interrupts */
+
+ u64 membase; /* Start of base memory of the card */
+ u64 membase_end; /* End of base memory of the card */
+
+ u8 *re_map_membase;/* Remapped memory of the card */
+
+ u64 iobase; /* Start of io base of the card */
+ u64 iobase_end; /* End of io base of the card */
+
+ u32 bd_uart_offset; /* Space between each UART */
+
+ struct jsm_channel *channels[MAXPORTS]; /* array of pointers to our channels. */
+ char *flipbuf; /* Our flip buffer, alloced if board is found */
+
+ u16 dpatype; /* The board "type", as defined by DPA */
+ u16 dpastatus; /* The board "status", as defined by DPA */
+
+ u32 bd_dividend; /* Board/UARTs specific dividend */
+
+ struct board_ops *bd_ops;
+
+ struct list_head jsm_board_entry;
+};
+
+/************************************************************************
+ * Device flag definitions for ch_flags.
+ ************************************************************************/
+#define CH_PRON 0x0001 /* Printer on string */
+#define CH_STOP 0x0002 /* Output is stopped */
+#define CH_STOPI 0x0004 /* Input is stopped */
+#define CH_CD 0x0008 /* Carrier is present */
+#define CH_FCAR 0x0010 /* Carrier forced on */
+#define CH_HANGUP 0x0020 /* Hangup received */
+
+#define CH_RECEIVER_OFF 0x0040 /* Receiver is off */
+#define CH_OPENING 0x0080 /* Port in fragile open state */
+#define CH_CLOSING 0x0100 /* Port in fragile close state */
+#define CH_FIFO_ENABLED 0x0200 /* Port has FIFOs enabled */
+#define CH_TX_FIFO_EMPTY 0x0400 /* TX Fifo is completely empty */
+#define CH_TX_FIFO_LWM 0x0800 /* TX Fifo is below Low Water */
+#define CH_BREAK_SENDING 0x1000 /* Break is being sent */
+#define CH_LOOPBACK 0x2000 /* Channel is in lookback mode */
+#define CH_FLIPBUF_IN_USE 0x4000 /* Channel's flipbuf is in use */
+#define CH_BAUD0 0x08000 /* Used for checking B0 transitions */
+
+/* Our Read/Error/Write queue sizes */
+#define RQUEUEMASK 0x1FFF /* 8 K - 1 */
+#define EQUEUEMASK 0x1FFF /* 8 K - 1 */
+#define WQUEUEMASK 0x0FFF /* 4 K - 1 */
+#define RQUEUESIZE (RQUEUEMASK + 1)
+#define EQUEUESIZE RQUEUESIZE
+#define WQUEUESIZE (WQUEUEMASK + 1)
+
+
+/************************************************************************
+ * Channel information structure.
+ ************************************************************************/
+struct jsm_channel {
+ struct uart_port uart_port;
+ struct jsm_board *ch_bd; /* Board structure pointer */
+
+ spinlock_t ch_lock; /* provide for serialization */
+ wait_queue_head_t ch_flags_wait;
+
+ u32 ch_portnum; /* Port number, 0 offset. */
+ u32 ch_open_count; /* open count */
+ u32 ch_flags; /* Channel flags */
+
+ u64 ch_close_delay; /* How long we should drop RTS/DTR for */
+
+ u64 ch_cpstime; /* Time for CPS calculations */
+
+ tcflag_t ch_c_iflag; /* channel iflags */
+ tcflag_t ch_c_cflag; /* channel cflags */
+ tcflag_t ch_c_oflag; /* channel oflags */
+ tcflag_t ch_c_lflag; /* channel lflags */
+ u8 ch_stopc; /* Stop character */
+ u8 ch_startc; /* Start character */
+
+ u32 ch_old_baud; /* Cache of the current baud */
+ u32 ch_custom_speed;/* Custom baud, if set */
+
+ u32 ch_wopen; /* Waiting for open process cnt */
+
+ u8 ch_mostat; /* FEP output modem status */
+ u8 ch_mistat; /* FEP input modem status */
+
+ struct neo_uart_struct *ch_neo_uart; /* Pointer to the "mapped" UART struct */
+ u8 ch_cached_lsr; /* Cached value of the LSR register */
+
+ u8 *ch_rqueue; /* Our read queue buffer - malloc'ed */
+ u16 ch_r_head; /* Head location of the read queue */
+ u16 ch_r_tail; /* Tail location of the read queue */
+
+ u8 *ch_equeue; /* Our error queue buffer - malloc'ed */
+ u16 ch_e_head; /* Head location of the error queue */
+ u16 ch_e_tail; /* Tail location of the error queue */
+
+ u8 *ch_wqueue; /* Our write queue buffer - malloc'ed */
+ u16 ch_w_head; /* Head location of the write queue */
+ u16 ch_w_tail; /* Tail location of the write queue */
+
+ u64 ch_rxcount; /* total of data received so far */
+ u64 ch_txcount; /* total of data transmitted so far */
+
+ u8 ch_r_tlevel; /* Receive Trigger level */
+ u8 ch_t_tlevel; /* Transmit Trigger level */
+
+ u8 ch_r_watermark; /* Receive Watermark */
+
+
+ u32 ch_stops_sent; /* How many times I have sent a stop character
+ * to try to stop the other guy sending.
+ */
+ u64 ch_err_parity; /* Count of parity errors on channel */
+ u64 ch_err_frame; /* Count of framing errors on channel */
+ u64 ch_err_break; /* Count of breaks on channel */
+ u64 ch_err_overrun; /* Count of overruns on channel */
+
+ u64 ch_xon_sends; /* Count of xons transmitted */
+ u64 ch_xoff_sends; /* Count of xoffs transmitted */
+};
+
+
+/************************************************************************
+ * Per channel/port NEO UART structure *
+ ************************************************************************
+ * Base Structure Entries Usage Meanings to Host *
+ * *
+ * W = read write R = read only *
+ * U = Unused. *
+ ************************************************************************/
+
+struct neo_uart_struct {
+ u8 txrx; /* WR RHR/THR - Holding Reg */
+ u8 ier; /* WR IER - Interrupt Enable Reg */
+ u8 isr_fcr; /* WR ISR/FCR - Interrupt Status Reg/Fifo Control Reg */
+ u8 lcr; /* WR LCR - Line Control Reg */
+ u8 mcr; /* WR MCR - Modem Control Reg */
+ u8 lsr; /* WR LSR - Line Status Reg */
+ u8 msr; /* WR MSR - Modem Status Reg */
+ u8 spr; /* WR SPR - Scratch Pad Reg */
+ u8 fctr; /* WR FCTR - Feature Control Reg */
+ u8 efr; /* WR EFR - Enhanced Function Reg */
+ u8 tfifo; /* WR TXCNT/TXTRG - Transmit FIFO Reg */
+ u8 rfifo; /* WR RXCNT/RXTRG - Recieve FIFO Reg */
+ u8 xoffchar1; /* WR XOFF 1 - XOff Character 1 Reg */
+ u8 xoffchar2; /* WR XOFF 2 - XOff Character 2 Reg */
+ u8 xonchar1; /* WR XON 1 - Xon Character 1 Reg */
+ u8 xonchar2; /* WR XON 2 - XOn Character 2 Reg */
+
+ u8 reserved1[0x2ff - 0x200]; /* U Reserved by Exar */
+ u8 txrxburst[64]; /* RW 64 bytes of RX/TX FIFO Data */
+ u8 reserved2[0x37f - 0x340]; /* U Reserved by Exar */
+ u8 rxburst_with_errors[64]; /* R 64 bytes of RX FIFO Data + LSR */
+};
+
+/* Where to read the extended interrupt register (32bits instead of 8bits) */
+#define UART_17158_POLL_ADDR_OFFSET 0x80
+
+/*
+ * These are the redefinitions for the FCTR on the XR17C158, since
+ * Exar made them different than their earlier design. (XR16C854)
+ */
+
+/* These are only applicable when table D is selected */
+#define UART_17158_FCTR_RTS_NODELAY 0x00
+#define UART_17158_FCTR_RTS_4DELAY 0x01
+#define UART_17158_FCTR_RTS_6DELAY 0x02
+#define UART_17158_FCTR_RTS_8DELAY 0x03
+#define UART_17158_FCTR_RTS_12DELAY 0x12
+#define UART_17158_FCTR_RTS_16DELAY 0x05
+#define UART_17158_FCTR_RTS_20DELAY 0x13
+#define UART_17158_FCTR_RTS_24DELAY 0x06
+#define UART_17158_FCTR_RTS_28DELAY 0x14
+#define UART_17158_FCTR_RTS_32DELAY 0x07
+#define UART_17158_FCTR_RTS_36DELAY 0x16
+#define UART_17158_FCTR_RTS_40DELAY 0x08
+#define UART_17158_FCTR_RTS_44DELAY 0x09
+#define UART_17158_FCTR_RTS_48DELAY 0x10
+#define UART_17158_FCTR_RTS_52DELAY 0x11
+
+#define UART_17158_FCTR_RTS_IRDA 0x10
+#define UART_17158_FCTR_RS485 0x20
+#define UART_17158_FCTR_TRGA 0x00
+#define UART_17158_FCTR_TRGB 0x40
+#define UART_17158_FCTR_TRGC 0x80
+#define UART_17158_FCTR_TRGD 0xC0
+
+/* 17158 trigger table selects.. */
+#define UART_17158_FCTR_BIT6 0x40
+#define UART_17158_FCTR_BIT7 0x80
+
+/* 17158 TX/RX memmapped buffer offsets */
+#define UART_17158_RX_FIFOSIZE 64
+#define UART_17158_TX_FIFOSIZE 64
+
+/* 17158 Extended IIR's */
+#define UART_17158_IIR_RDI_TIMEOUT 0x0C /* Receiver data TIMEOUT */
+#define UART_17158_IIR_XONXOFF 0x10 /* Received an XON/XOFF char */
+#define UART_17158_IIR_HWFLOW_STATE_CHANGE 0x20 /* CTS/DSR or RTS/DTR state change */
+#define UART_17158_IIR_FIFO_ENABLED 0xC0 /* 16550 FIFOs are Enabled */
+
+/*
+ * These are the extended interrupts that get sent
+ * back to us from the UART's 32bit interrupt register
+ */
+#define UART_17158_RX_LINE_STATUS 0x1 /* RX Ready */
+#define UART_17158_RXRDY_TIMEOUT 0x2 /* RX Ready Timeout */
+#define UART_17158_TXRDY 0x3 /* TX Ready */
+#define UART_17158_MSR 0x4 /* Modem State Change */
+#define UART_17158_TX_AND_FIFO_CLR 0x40 /* Transmitter Holding Reg Empty */
+#define UART_17158_RX_FIFO_DATA_ERROR 0x80 /* UART detected an RX FIFO Data error */
+
+/*
+ * These are the EXTENDED definitions for the 17C158's Interrupt
+ * Enable Register.
+ */
+#define UART_17158_EFR_ECB 0x10 /* Enhanced control bit */
+#define UART_17158_EFR_IXON 0x2 /* Receiver compares Xon1/Xoff1 */
+#define UART_17158_EFR_IXOFF 0x8 /* Transmit Xon1/Xoff1 */
+#define UART_17158_EFR_RTSDTR 0x40 /* Auto RTS/DTR Flow Control Enable */
+#define UART_17158_EFR_CTSDSR 0x80 /* Auto CTS/DSR Flow COntrol Enable */
+
+#define UART_17158_XOFF_DETECT 0x1 /* Indicates whether chip saw an incoming XOFF char */
+#define UART_17158_XON_DETECT 0x2 /* Indicates whether chip saw an incoming XON char */
+
+#define UART_17158_IER_RSVD1 0x10 /* Reserved by Exar */
+#define UART_17158_IER_XOFF 0x20 /* Xoff Interrupt Enable */
+#define UART_17158_IER_RTSDTR 0x40 /* Output Interrupt Enable */
+#define UART_17158_IER_CTSDSR 0x80 /* Input Interrupt Enable */
+
+#define PCI_DEVICE_NEO_2DB9_PCI_NAME "Neo 2 - DB9 Universal PCI"
+#define PCI_DEVICE_NEO_2DB9PRI_PCI_NAME "Neo 2 - DB9 Universal PCI - Powered Ring Indicator"
+#define PCI_DEVICE_NEO_2RJ45_PCI_NAME "Neo 2 - RJ45 Universal PCI"
+#define PCI_DEVICE_NEO_2RJ45PRI_PCI_NAME "Neo 2 - RJ45 Universal PCI - Powered Ring Indicator"
+
+/*
+ * Our Global Variables.
+ */
+extern struct uart_driver jsm_uart_driver;
+extern struct board_ops jsm_neo_ops;
+extern int jsm_debug;
+extern int jsm_rawreadok;
+
+extern int jsm_driver_state; /* The state of the driver */
+extern char *jsm_driver_state_text[];/* Array of driver state text */
+
+extern spinlock_t jsm_board_head_lock;
+extern struct list_head jsm_board_head;
+
+/*************************************************************************
+ *
+ * Prototypes for non-static functions used in more than one module
+ *
+ *************************************************************************/
+int jsm_tty_write(struct uart_port *port);
+int jsm_tty_init(struct jsm_board *);
+int jsm_uart_port_init(struct jsm_board *);
+int jsm_remove_uart_port(struct jsm_board *);
+void jsm_input(struct jsm_channel *ch);
+void jsm_carrier(struct jsm_channel *ch);
+void jsm_check_queue_flow_control(struct jsm_channel *ch);
+
+void jsm_create_driver_sysfiles(struct device_driver *);
+void jsm_remove_driver_sysfiles(struct device_driver *);
+
+#endif
diff --git a/drivers/serial/jsm/jsm_driver.c b/drivers/serial/jsm/jsm_driver.c
new file mode 100644
index 0000000000000..d4847d4f1473d
--- /dev/null
+++ b/drivers/serial/jsm/jsm_driver.c
@@ -0,0 +1,404 @@
+/************************************************************************
+ * Copyright 2003 Digi International (www.digi.com)
+ *
+ * Copyright (C) 2004 IBM 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the 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.
+ *
+ * Contact Information:
+ * Scott H Kilau <Scott_Kilau@digi.com>
+ * Wendy Xiong <wendyx@us.ltcfwd.linux.ibm.com>
+ *
+ ***********************************************************************/
+#include <linux/moduleparam.h>
+#include <linux/pci.h>
+
+#include "jsm.h"
+
+MODULE_AUTHOR("Digi International, http://www.digi.com");
+MODULE_DESCRIPTION("Driver for the Digi International Neo PCI based product line");
+MODULE_SUPPORTED_DEVICE("jsm");
+
+#define JSM_DRIVER_NAME "jsm"
+#define NR_PORTS 32
+#define JSM_MINOR_START 0
+
+struct uart_driver jsm_uart_driver = {
+ .owner = THIS_MODULE,
+ .driver_name = JSM_DRIVER_NAME,
+ .dev_name = "ttyn",
+ .major = 253,
+ .minor = JSM_MINOR_START,
+ .nr = NR_PORTS,
+ .cons = NULL,
+};
+
+int jsm_debug;
+int jsm_rawreadok;
+module_param(jsm_debug, int, 0);
+module_param(jsm_rawreadok, int, 0);
+MODULE_PARM_DESC(jsm_debug, "Driver debugging level");
+MODULE_PARM_DESC(jsm_rawreadok, "Bypass flip buffers on input");
+
+/*
+ * Globals
+ */
+int jsm_driver_state = DRIVER_INITIALIZED;
+spinlock_t jsm_board_head_lock = SPIN_LOCK_UNLOCKED;
+LIST_HEAD(jsm_board_head);
+
+static struct pci_device_id jsm_pci_tbl[] = {
+ { PCI_DEVICE (PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_NEO_2DB9), 0, 0, 0 },
+ { PCI_DEVICE (PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_NEO_2DB9PRI), 0, 0, 1 },
+ { PCI_DEVICE (PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_NEO_2RJ45), 0, 0, 2 },
+ { PCI_DEVICE (PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_NEO_2RJ45PRI), 0, 0, 3 },
+ { 0,} /* 0 terminated list. */
+};
+MODULE_DEVICE_TABLE(pci, jsm_pci_tbl);
+
+static struct board_id jsm_Ids[] = {
+ { PCI_DEVICE_NEO_2DB9_PCI_NAME, 2 },
+ { PCI_DEVICE_NEO_2DB9PRI_PCI_NAME, 2 },
+ { PCI_DEVICE_NEO_2RJ45_PCI_NAME, 2 },
+ { PCI_DEVICE_NEO_2RJ45PRI_PCI_NAME, 2 },
+ { NULL, 0 }
+};
+
+char *jsm_driver_state_text[] = {
+ "Driver Initialized",
+ "Driver Ready."
+};
+
+static int jsm_finalize_board_init(struct jsm_board *brd)
+{
+ int rc = 0;
+
+ jsm_printk(INIT, INFO, &brd->pci_dev, "start\n");
+
+ if (brd->irq) {
+ rc = request_irq(brd->irq, brd->bd_ops->intr, SA_INTERRUPT|SA_SHIRQ, "JSM", brd);
+
+ if (rc) {
+ printk(KERN_WARNING "Failed to hook IRQ %d\n",brd->irq);
+ brd->state = BOARD_FAILED;
+ brd->dpastatus = BD_NOFEP;
+ rc = -ENODEV;
+ } else
+ jsm_printk(INIT, INFO, &brd->pci_dev,
+ "Requested and received usage of IRQ %d\n", brd->irq);
+ }
+ return rc;
+}
+
+/*
+ * jsm_found_board()
+ *
+ * A board has been found, init it.
+ */
+static int jsm_found_board(struct pci_dev *pdev, int id)
+{
+ struct jsm_board *brd;
+ int i = 0;
+ int rc = 0;
+ struct list_head *tmp;
+ struct jsm_board *cur_board_entry;
+ unsigned long lock_flags;
+ int adapter_count = 0;
+ int retval;
+
+ brd = kmalloc(sizeof(struct jsm_board), GFP_KERNEL);
+ if (!brd) {
+ dev_err(&pdev->dev, "memory allocation for board structure failed\n");
+ return -ENOMEM;
+ }
+ memset(brd, 0, sizeof(struct jsm_board));
+
+ spin_lock_irqsave(&jsm_board_head_lock, lock_flags);
+ list_for_each(tmp, &jsm_board_head) {
+ cur_board_entry =
+ list_entry(tmp, struct jsm_board,
+ jsm_board_entry);
+ if (cur_board_entry->boardnum != adapter_count) {
+ break;
+ }
+ adapter_count++;
+ }
+
+ list_add_tail(&brd->jsm_board_entry, &jsm_board_head);
+ spin_unlock_irqrestore(&jsm_board_head_lock, lock_flags);
+
+ /* store the info for the board we've found */
+ brd->boardnum = adapter_count;
+ brd->pci_dev = pdev;
+ brd->name = jsm_Ids[id].name;
+ brd->maxports = jsm_Ids[id].maxports;
+ brd->dpastatus = BD_NOFEP;
+ init_waitqueue_head(&brd->state_wait);
+
+ spin_lock_init(&brd->bd_lock);
+ spin_lock_init(&brd->bd_intr_lock);
+
+ brd->state = BOARD_FOUND;
+
+ for (i = 0; i < brd->maxports; i++)
+ brd->channels[i] = NULL;
+
+ /* store which revision we have */
+ pci_read_config_byte(pdev, PCI_REVISION_ID, &brd->rev);
+
+ brd->irq = pdev->irq;
+
+ switch(brd->pci_dev->device) {
+
+ case PCI_DEVICE_ID_NEO_2DB9:
+ case PCI_DEVICE_ID_NEO_2DB9PRI:
+ case PCI_DEVICE_ID_NEO_2RJ45:
+ case PCI_DEVICE_ID_NEO_2RJ45PRI:
+
+ /*
+ * This chip is set up 100% when we get to it.
+ * No need to enable global interrupts or anything.
+ */
+ brd->dpatype = T_NEO | T_PCIBUS;
+
+ jsm_printk(INIT, INFO, &brd->pci_dev,
+ "jsm_found_board - NEO adapter\n");
+
+ /* get the PCI Base Address Registers */
+ brd->membase = pci_resource_start(pdev, 0);
+ brd->membase_end = pci_resource_end(pdev, 0);
+
+ if (brd->membase & 1)
+ brd->membase &= ~3;
+ else
+ brd->membase &= ~15;
+
+ /* Assign the board_ops struct */
+ brd->bd_ops = &jsm_neo_ops;
+
+ brd->bd_uart_offset = 0x200;
+ brd->bd_dividend = 921600;
+
+ brd->re_map_membase = ioremap(brd->membase, 0x1000);
+ jsm_printk(INIT, INFO, &brd->pci_dev,
+ "remapped mem: 0x%p\n", brd->re_map_membase);
+ if (!brd->re_map_membase) {
+ kfree(brd);
+ dev_err(&pdev->dev, "card has no PCI Memory resources, failing board.\n");
+ return -ENOMEM;
+ }
+ break;
+
+ default:
+ dev_err(&pdev->dev, "Did not find any compatible Neo or Classic PCI boards in system.\n");
+ kfree(brd);
+ return -ENXIO;
+ }
+
+ /*
+ * Do tty device initialization.
+ */
+ rc = jsm_finalize_board_init(brd);
+ if (rc < 0) {
+ dev_err(&pdev->dev, "Can't finalize board init (%d)\n", rc);
+ brd->state = BOARD_FAILED;
+ retval = -ENXIO;
+ goto failed0;
+ }
+
+ rc = jsm_tty_init(brd);
+ if (rc < 0) {
+ dev_err(&pdev->dev, "Can't init tty devices (%d)\n", rc);
+ brd->state = BOARD_FAILED;
+ retval = -ENXIO;
+ goto failed1;
+ }
+
+ rc = jsm_uart_port_init(brd);
+ if (rc < 0) {
+ dev_err(&pdev->dev, "Can't init uart port (%d)\n", rc);
+ brd->state = BOARD_FAILED;
+ retval = -ENXIO;
+ goto failed1;
+ }
+
+ brd->state = BOARD_READY;
+ brd->dpastatus = BD_RUNNING;
+
+ /* Log the information about the board */
+ dev_info(&pdev->dev, "board %d: %s (rev %d), irq %d\n",adapter_count, brd->name, brd->rev, brd->irq);
+
+ /*
+ * allocate flip buffer for board.
+ *
+ * Okay to malloc with GFP_KERNEL, we are not at interrupt
+ * context, and there are no locks held.
+ */
+ brd->flipbuf = kmalloc(MYFLIPLEN, GFP_KERNEL);
+ if (!brd->flipbuf) {
+ dev_err(&pdev->dev, "memory allocation for flipbuf failed\n");
+ brd->state = BOARD_FAILED;
+ retval = -ENOMEM;
+ goto failed1;
+ }
+ memset(brd->flipbuf, 0, MYFLIPLEN);
+
+ jsm_create_driver_sysfiles(pdev->dev.driver);
+
+ wake_up_interruptible(&brd->state_wait);
+ return 0;
+failed1:
+ free_irq(brd->irq, brd);
+failed0:
+ kfree(brd);
+ iounmap(brd->re_map_membase);
+ return retval;
+}
+
+/* returns count (>= 0), or negative on error */
+static int jsm_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+ int rc;
+
+ rc = pci_enable_device(pdev);
+ if (rc) {
+ dev_err(&pdev->dev, "Device enable FAILED\n");
+ return rc;
+ }
+
+ if ((rc = pci_request_regions(pdev, "jsm"))) {
+ dev_err(&pdev->dev, "pci_request_region FAILED\n");
+ pci_disable_device(pdev);
+ return rc;
+ }
+
+ if ((rc = jsm_found_board(pdev, ent->driver_data))) {
+ dev_err(&pdev->dev, "jsm_found_board FAILED\n");
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+ return rc;
+ }
+ return rc;
+}
+
+
+/*
+ * jsm_cleanup_board()
+ *
+ * Free all the memory associated with a board
+ */
+static void jsm_cleanup_board(struct jsm_board *brd)
+{
+ int i = 0;
+
+ free_irq(brd->irq, brd);
+ iounmap(brd->re_map_membase);
+
+ /* Free all allocated channels structs */
+ for (i = 0; i < brd->maxports; i++) {
+ if (brd->channels[i]) {
+ if (brd->channels[i]->ch_rqueue)
+ kfree(brd->channels[i]->ch_rqueue);
+ if (brd->channels[i]->ch_equeue)
+ kfree(brd->channels[i]->ch_equeue);
+ if (brd->channels[i]->ch_wqueue)
+ kfree(brd->channels[i]->ch_wqueue);
+ kfree(brd->channels[i]);
+ }
+ }
+
+ pci_release_regions(brd->pci_dev);
+ pci_disable_device(brd->pci_dev);
+ kfree(brd->flipbuf);
+ kfree(brd);
+}
+
+static void jsm_remove_one(struct pci_dev *dev)
+{
+ unsigned long lock_flags;
+ struct list_head *tmp;
+ struct jsm_board *brd;
+
+ spin_lock_irqsave(&jsm_board_head_lock, lock_flags);
+ list_for_each(tmp, &jsm_board_head) {
+ brd = list_entry(tmp, struct jsm_board,
+ jsm_board_entry);
+ if ( brd != NULL && brd->pci_dev == dev) {
+ jsm_remove_uart_port(brd);
+ jsm_cleanup_board(brd);
+ list_del(&brd->jsm_board_entry);
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&jsm_board_head_lock, lock_flags);
+ return;
+}
+
+struct pci_driver jsm_driver = {
+ .name = "jsm",
+ .probe = jsm_init_one,
+ .id_table = jsm_pci_tbl,
+ .remove = __devexit_p(jsm_remove_one),
+};
+
+/*
+ * jsm_init_module()
+ *
+ * Module load. This is where it all starts.
+ */
+static int __init jsm_init_module(void)
+{
+ int rc = 0;
+
+ printk(KERN_INFO "%s, Digi International Part Number %s\n",
+ JSM_VERSION, JSM_VERSION);
+
+ /*
+ * Initialize global stuff
+ */
+
+ rc = uart_register_driver(&jsm_uart_driver);
+ if (rc < 0) {
+ return rc;
+ }
+
+ rc = pci_register_driver(&jsm_driver);
+ if (rc < 0) {
+ uart_unregister_driver(&jsm_uart_driver);
+ return rc;
+ }
+ jsm_driver_state = DRIVER_READY;
+
+ return rc;
+}
+
+module_init(jsm_init_module);
+
+/*
+ * jsm_exit_module()
+ *
+ * Module unload. This is where it all ends.
+ */
+static void __exit jsm_exit_module(void)
+{
+ jsm_remove_driver_sysfiles(&jsm_driver.driver);
+
+ pci_unregister_driver(&jsm_driver);
+
+ uart_unregister_driver(&jsm_uart_driver);
+}
+module_exit(jsm_exit_module);
+MODULE_LICENSE("GPL");
diff --git a/drivers/serial/jsm/jsm_neo.c b/drivers/serial/jsm/jsm_neo.c
new file mode 100644
index 0000000000000..0511d6be7d173
--- /dev/null
+++ b/drivers/serial/jsm/jsm_neo.c
@@ -0,0 +1,1427 @@
+/************************************************************************
+ * Copyright 2003 Digi International (www.digi.com)
+ *
+ * Copyright (C) 2004 IBM 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the 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.
+ *
+ * Contact Information:
+ * Scott H Kilau <Scott_Kilau@digi.com>
+ * Wendy Xiong <wendyx@us.ltcfwd.linux.ibm.com>
+ *
+ ***********************************************************************/
+#include <linux/delay.h> /* For udelay */
+#include <linux/serial_reg.h> /* For the various UART offsets */
+#include <linux/tty.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+
+#include "jsm.h" /* Driver main header file */
+
+static u32 jsm_offset_table[8] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
+
+/*
+ * This function allows calls to ensure that all outstanding
+ * PCI writes have been completed, by doing a PCI read against
+ * a non-destructive, read-only location on the Neo card.
+ *
+ * In this case, we are reading the DVID (Read-only Device Identification)
+ * value of the Neo card.
+ */
+static inline void neo_pci_posting_flush(struct jsm_board *bd)
+{
+ readb(bd->re_map_membase + 0x8D);
+}
+
+static void neo_set_cts_flow_control(struct jsm_channel *ch)
+{
+ u8 ier = readb(&ch->ch_neo_uart->ier);
+ u8 efr = readb(&ch->ch_neo_uart->efr);
+
+ jsm_printk(PARAM, INFO, &ch->ch_bd->pci_dev, "Setting CTSFLOW\n");
+
+ /* Turn on auto CTS flow control */
+ ier |= (UART_17158_IER_CTSDSR);
+ efr |= (UART_17158_EFR_ECB | UART_17158_EFR_CTSDSR);
+
+ /* Turn off auto Xon flow control */
+ efr &= ~(UART_17158_EFR_IXON);
+
+ /* Why? Becuz Exar's spec says we have to zero it out before setting it */
+ writeb(0, &ch->ch_neo_uart->efr);
+
+ /* Turn on UART enhanced bits */
+ writeb(efr, &ch->ch_neo_uart->efr);
+
+ /* Turn on table D, with 8 char hi/low watermarks */
+ writeb((UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_4DELAY), &ch->ch_neo_uart->fctr);
+
+ /* Feed the UART our trigger levels */
+ writeb(8, &ch->ch_neo_uart->tfifo);
+ ch->ch_t_tlevel = 8;
+
+ writeb(ier, &ch->ch_neo_uart->ier);
+}
+
+static void neo_set_rts_flow_control(struct jsm_channel *ch)
+{
+ u8 ier = readb(&ch->ch_neo_uart->ier);
+ u8 efr = readb(&ch->ch_neo_uart->efr);
+
+ jsm_printk(PARAM, INFO, &ch->ch_bd->pci_dev, "Setting RTSFLOW\n");
+
+ /* Turn on auto RTS flow control */
+ ier |= (UART_17158_IER_RTSDTR);
+ efr |= (UART_17158_EFR_ECB | UART_17158_EFR_RTSDTR);
+
+ /* Turn off auto Xoff flow control */
+ ier &= ~(UART_17158_IER_XOFF);
+ efr &= ~(UART_17158_EFR_IXOFF);
+
+ /* Why? Becuz Exar's spec says we have to zero it out before setting it */
+ writeb(0, &ch->ch_neo_uart->efr);
+
+ /* Turn on UART enhanced bits */
+ writeb(efr, &ch->ch_neo_uart->efr);
+
+ writeb((UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_4DELAY), &ch->ch_neo_uart->fctr);
+ ch->ch_r_watermark = 4;
+
+ writeb(56, &ch->ch_neo_uart->rfifo);
+ ch->ch_r_tlevel = 56;
+
+ writeb(ier, &ch->ch_neo_uart->ier);
+
+ /*
+ * From the Neo UART spec sheet:
+ * The auto RTS/DTR function must be started by asserting
+ * RTS/DTR# output pin (MCR bit-0 or 1 to logic 1 after
+ * it is enabled.
+ */
+ ch->ch_mostat |= (UART_MCR_RTS);
+}
+
+
+static void neo_set_ixon_flow_control(struct jsm_channel *ch)
+{
+ u8 ier = readb(&ch->ch_neo_uart->ier);
+ u8 efr = readb(&ch->ch_neo_uart->efr);
+
+ jsm_printk(PARAM, INFO, &ch->ch_bd->pci_dev, "Setting IXON FLOW\n");
+
+ /* Turn off auto CTS flow control */
+ ier &= ~(UART_17158_IER_CTSDSR);
+ efr &= ~(UART_17158_EFR_CTSDSR);
+
+ /* Turn on auto Xon flow control */
+ efr |= (UART_17158_EFR_ECB | UART_17158_EFR_IXON);
+
+ /* Why? Becuz Exar's spec says we have to zero it out before setting it */
+ writeb(0, &ch->ch_neo_uart->efr);
+
+ /* Turn on UART enhanced bits */
+ writeb(efr, &ch->ch_neo_uart->efr);
+
+ writeb((UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_8DELAY), &ch->ch_neo_uart->fctr);
+ ch->ch_r_watermark = 4;
+
+ writeb(32, &ch->ch_neo_uart->rfifo);
+ ch->ch_r_tlevel = 32;
+
+ /* Tell UART what start/stop chars it should be looking for */
+ writeb(ch->ch_startc, &ch->ch_neo_uart->xonchar1);
+ writeb(0, &ch->ch_neo_uart->xonchar2);
+
+ writeb(ch->ch_stopc, &ch->ch_neo_uart->xoffchar1);
+ writeb(0, &ch->ch_neo_uart->xoffchar2);
+
+ writeb(ier, &ch->ch_neo_uart->ier);
+}
+
+static void neo_set_ixoff_flow_control(struct jsm_channel *ch)
+{
+ u8 ier = readb(&ch->ch_neo_uart->ier);
+ u8 efr = readb(&ch->ch_neo_uart->efr);
+
+ jsm_printk(PARAM, INFO, &ch->ch_bd->pci_dev, "Setting IXOFF FLOW\n");
+
+ /* Turn off auto RTS flow control */
+ ier &= ~(UART_17158_IER_RTSDTR);
+ efr &= ~(UART_17158_EFR_RTSDTR);
+
+ /* Turn on auto Xoff flow control */
+ ier |= (UART_17158_IER_XOFF);
+ efr |= (UART_17158_EFR_ECB | UART_17158_EFR_IXOFF);
+
+ /* Why? Becuz Exar's spec says we have to zero it out before setting it */
+ writeb(0, &ch->ch_neo_uart->efr);
+
+ /* Turn on UART enhanced bits */
+ writeb(efr, &ch->ch_neo_uart->efr);
+
+ /* Turn on table D, with 8 char hi/low watermarks */
+ writeb((UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_8DELAY), &ch->ch_neo_uart->fctr);
+
+ writeb(8, &ch->ch_neo_uart->tfifo);
+ ch->ch_t_tlevel = 8;
+
+ /* Tell UART what start/stop chars it should be looking for */
+ writeb(ch->ch_startc, &ch->ch_neo_uart->xonchar1);
+ writeb(0, &ch->ch_neo_uart->xonchar2);
+
+ writeb(ch->ch_stopc, &ch->ch_neo_uart->xoffchar1);
+ writeb(0, &ch->ch_neo_uart->xoffchar2);
+
+ writeb(ier, &ch->ch_neo_uart->ier);
+}
+
+static void neo_set_no_input_flow_control(struct jsm_channel *ch)
+{
+ u8 ier = readb(&ch->ch_neo_uart->ier);
+ u8 efr = readb(&ch->ch_neo_uart->efr);
+
+ jsm_printk(PARAM, INFO, &ch->ch_bd->pci_dev, "Unsetting Input FLOW\n");
+
+ /* Turn off auto RTS flow control */
+ ier &= ~(UART_17158_IER_RTSDTR);
+ efr &= ~(UART_17158_EFR_RTSDTR);
+
+ /* Turn off auto Xoff flow control */
+ ier &= ~(UART_17158_IER_XOFF);
+ if (ch->ch_c_iflag & IXON)
+ efr &= ~(UART_17158_EFR_IXOFF);
+ else
+ efr &= ~(UART_17158_EFR_ECB | UART_17158_EFR_IXOFF);
+
+ /* Why? Becuz Exar's spec says we have to zero it out before setting it */
+ writeb(0, &ch->ch_neo_uart->efr);
+
+ /* Turn on UART enhanced bits */
+ writeb(efr, &ch->ch_neo_uart->efr);
+
+ /* Turn on table D, with 8 char hi/low watermarks */
+ writeb((UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_8DELAY), &ch->ch_neo_uart->fctr);
+
+ ch->ch_r_watermark = 0;
+
+ writeb(16, &ch->ch_neo_uart->tfifo);
+ ch->ch_t_tlevel = 16;
+
+ writeb(16, &ch->ch_neo_uart->rfifo);
+ ch->ch_r_tlevel = 16;
+
+ writeb(ier, &ch->ch_neo_uart->ier);
+}
+
+static void neo_set_no_output_flow_control(struct jsm_channel *ch)
+{
+ u8 ier = readb(&ch->ch_neo_uart->ier);
+ u8 efr = readb(&ch->ch_neo_uart->efr);
+
+ jsm_printk(PARAM, INFO, &ch->ch_bd->pci_dev, "Unsetting Output FLOW\n");
+
+ /* Turn off auto CTS flow control */
+ ier &= ~(UART_17158_IER_CTSDSR);
+ efr &= ~(UART_17158_EFR_CTSDSR);
+
+ /* Turn off auto Xon flow control */
+ if (ch->ch_c_iflag & IXOFF)
+ efr &= ~(UART_17158_EFR_IXON);
+ else
+ efr &= ~(UART_17158_EFR_ECB | UART_17158_EFR_IXON);
+
+ /* Why? Becuz Exar's spec says we have to zero it out before setting it */
+ writeb(0, &ch->ch_neo_uart->efr);
+
+ /* Turn on UART enhanced bits */
+ writeb(efr, &ch->ch_neo_uart->efr);
+
+ /* Turn on table D, with 8 char hi/low watermarks */
+ writeb((UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_8DELAY), &ch->ch_neo_uart->fctr);
+
+ ch->ch_r_watermark = 0;
+
+ writeb(16, &ch->ch_neo_uart->tfifo);
+ ch->ch_t_tlevel = 16;
+
+ writeb(16, &ch->ch_neo_uart->rfifo);
+ ch->ch_r_tlevel = 16;
+
+ writeb(ier, &ch->ch_neo_uart->ier);
+}
+
+static inline void neo_set_new_start_stop_chars(struct jsm_channel *ch)
+{
+
+ /* if hardware flow control is set, then skip this whole thing */
+ if (ch->ch_c_cflag & CRTSCTS)
+ return;
+
+ jsm_printk(PARAM, INFO, &ch->ch_bd->pci_dev, "start\n");
+
+ /* Tell UART what start/stop chars it should be looking for */
+ writeb(ch->ch_startc, &ch->ch_neo_uart->xonchar1);
+ writeb(0, &ch->ch_neo_uart->xonchar2);
+
+ writeb(ch->ch_stopc, &ch->ch_neo_uart->xoffchar1);
+ writeb(0, &ch->ch_neo_uart->xoffchar2);
+}
+
+static void neo_copy_data_from_uart_to_queue(struct jsm_channel *ch)
+{
+ int qleft = 0;
+ u8 linestatus = 0;
+ u8 error_mask = 0;
+ int n = 0;
+ int total = 0;
+ u16 head;
+ u16 tail;
+
+ if (!ch)
+ return;
+
+ /* cache head and tail of queue */
+ head = ch->ch_r_head & RQUEUEMASK;
+ tail = ch->ch_r_tail & RQUEUEMASK;
+
+ /* Get our cached LSR */
+ linestatus = ch->ch_cached_lsr;
+ ch->ch_cached_lsr = 0;
+
+ /* Store how much space we have left in the queue */
+ if ((qleft = tail - head - 1) < 0)
+ qleft += RQUEUEMASK + 1;
+
+ /*
+ * If the UART is not in FIFO mode, force the FIFO copy to
+ * NOT be run, by setting total to 0.
+ *
+ * On the other hand, if the UART IS in FIFO mode, then ask
+ * the UART to give us an approximation of data it has RX'ed.
+ */
+ if (!(ch->ch_flags & CH_FIFO_ENABLED))
+ total = 0;
+ else {
+ total = readb(&ch->ch_neo_uart->rfifo);
+
+ /*
+ * EXAR chip bug - RX FIFO COUNT - Fudge factor.
+ *
+ * This resolves a problem/bug with the Exar chip that sometimes
+ * returns a bogus value in the rfifo register.
+ * The count can be any where from 0-3 bytes "off".
+ * Bizarre, but true.
+ */
+ total -= 3;
+ }
+
+ /*
+ * Finally, bound the copy to make sure we don't overflow
+ * our own queue...
+ * The byte by byte copy loop below this loop this will
+ * deal with the queue overflow possibility.
+ */
+ total = min(total, qleft);
+
+ while (total > 0) {
+ /*
+ * Grab the linestatus register, we need to check
+ * to see if there are any errors in the FIFO.
+ */
+ linestatus = readb(&ch->ch_neo_uart->lsr);
+
+ /*
+ * Break out if there is a FIFO error somewhere.
+ * This will allow us to go byte by byte down below,
+ * finding the exact location of the error.
+ */
+ if (linestatus & UART_17158_RX_FIFO_DATA_ERROR)
+ break;
+
+ /* Make sure we don't go over the end of our queue */
+ n = min(((u32) total), (RQUEUESIZE - (u32) head));
+
+ /*
+ * Cut down n even further if needed, this is to fix
+ * a problem with memcpy_fromio() with the Neo on the
+ * IBM pSeries platform.
+ * 15 bytes max appears to be the magic number.
+ */
+ n = min((u32) n, (u32) 12);
+
+ /*
+ * Since we are grabbing the linestatus register, which
+ * will reset some bits after our read, we need to ensure
+ * we don't miss our TX FIFO emptys.
+ */
+ if (linestatus & (UART_LSR_THRE | UART_17158_TX_AND_FIFO_CLR))
+ ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
+
+ linestatus = 0;
+
+ /* Copy data from uart to the queue */
+ memcpy_fromio(ch->ch_rqueue + head, &ch->ch_neo_uart->txrxburst, n);
+ /*
+ * Since RX_FIFO_DATA_ERROR was 0, we are guarenteed
+ * that all the data currently in the FIFO is free of
+ * breaks and parity/frame/orun errors.
+ */
+ memset(ch->ch_equeue + head, 0, n);
+
+ /* Add to and flip head if needed */
+ head = (head + n) & RQUEUEMASK;
+ total -= n;
+ qleft -= n;
+ ch->ch_rxcount += n;
+ }
+
+ /*
+ * Create a mask to determine whether we should
+ * insert the character (if any) into our queue.
+ */
+ if (ch->ch_c_iflag & IGNBRK)
+ error_mask |= UART_LSR_BI;
+
+ /*
+ * Now cleanup any leftover bytes still in the UART.
+ * Also deal with any possible queue overflow here as well.
+ */
+ while (1) {
+
+ /*
+ * Its possible we have a linestatus from the loop above
+ * this, so we "OR" on any extra bits.
+ */
+ linestatus |= readb(&ch->ch_neo_uart->lsr);
+
+ /*
+ * If the chip tells us there is no more data pending to
+ * be read, we can then leave.
+ * But before we do, cache the linestatus, just in case.
+ */
+ if (!(linestatus & UART_LSR_DR)) {
+ ch->ch_cached_lsr = linestatus;
+ break;
+ }
+
+ /* No need to store this bit */
+ linestatus &= ~UART_LSR_DR;
+
+ /*
+ * Since we are grabbing the linestatus register, which
+ * will reset some bits after our read, we need to ensure
+ * we don't miss our TX FIFO emptys.
+ */
+ if (linestatus & (UART_LSR_THRE | UART_17158_TX_AND_FIFO_CLR)) {
+ linestatus &= ~(UART_LSR_THRE | UART_17158_TX_AND_FIFO_CLR);
+ ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
+ }
+
+ /*
+ * Discard character if we are ignoring the error mask.
+ */
+ if (linestatus & error_mask) {
+ u8 discard;
+ linestatus = 0;
+ memcpy_fromio(&discard, &ch->ch_neo_uart->txrxburst, 1);
+ continue;
+ }
+
+ /*
+ * If our queue is full, we have no choice but to drop some data.
+ * The assumption is that HWFLOW or SWFLOW should have stopped
+ * things way way before we got to this point.
+ *
+ * I decided that I wanted to ditch the oldest data first,
+ * I hope thats okay with everyone? Yes? Good.
+ */
+ while (qleft < 1) {
+ jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
+ "Queue full, dropping DATA:%x LSR:%x\n",
+ ch->ch_rqueue[tail], ch->ch_equeue[tail]);
+
+ ch->ch_r_tail = tail = (tail + 1) & RQUEUEMASK;
+ ch->ch_err_overrun++;
+ qleft++;
+ }
+
+ memcpy_fromio(ch->ch_rqueue + head, &ch->ch_neo_uart->txrxburst, 1);
+ ch->ch_equeue[head] = (u8) linestatus;
+
+ jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
+ "DATA/LSR pair: %x %x\n", ch->ch_rqueue[head], ch->ch_equeue[head]);
+
+ /* Ditch any remaining linestatus value. */
+ linestatus = 0;
+
+ /* Add to and flip head if needed */
+ head = (head + 1) & RQUEUEMASK;
+
+ qleft--;
+ ch->ch_rxcount++;
+ }
+
+ /*
+ * Write new final heads to channel structure.
+ */
+ ch->ch_r_head = head & RQUEUEMASK;
+ ch->ch_e_head = head & EQUEUEMASK;
+ jsm_input(ch);
+}
+
+static void neo_copy_data_from_queue_to_uart(struct jsm_channel *ch)
+{
+ u16 head;
+ u16 tail;
+ int n;
+ int s;
+ int qlen;
+ u32 len_written = 0;
+
+ if (!ch)
+ return;
+
+ /* No data to write to the UART */
+ if (ch->ch_w_tail == ch->ch_w_head)
+ return;
+
+ /* If port is "stopped", don't send any data to the UART */
+ if ((ch->ch_flags & CH_STOP) || (ch->ch_flags & CH_BREAK_SENDING))
+ return;
+ /*
+ * If FIFOs are disabled. Send data directly to txrx register
+ */
+ if (!(ch->ch_flags & CH_FIFO_ENABLED)) {
+ u8 lsrbits = readb(&ch->ch_neo_uart->lsr);
+
+ ch->ch_cached_lsr |= lsrbits;
+ if (ch->ch_cached_lsr & UART_LSR_THRE) {
+ ch->ch_cached_lsr &= ~(UART_LSR_THRE);
+
+ writeb(ch->ch_wqueue[ch->ch_w_tail], &ch->ch_neo_uart->txrx);
+ jsm_printk(WRITE, INFO, &ch->ch_bd->pci_dev,
+ "Tx data: %x\n", ch->ch_wqueue[ch->ch_w_head]);
+ ch->ch_w_tail++;
+ ch->ch_w_tail &= WQUEUEMASK;
+ ch->ch_txcount++;
+ }
+ return;
+ }
+
+ /*
+ * We have to do it this way, because of the EXAR TXFIFO count bug.
+ */
+ if (!(ch->ch_flags & (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM)))
+ return;
+
+ len_written = 0;
+ n = UART_17158_TX_FIFOSIZE - ch->ch_t_tlevel;
+
+ /* cache head and tail of queue */
+ head = ch->ch_w_head & WQUEUEMASK;
+ tail = ch->ch_w_tail & WQUEUEMASK;
+ qlen = (head - tail) & WQUEUEMASK;
+
+ /* Find minimum of the FIFO space, versus queue length */
+ n = min(n, qlen);
+
+ while (n > 0) {
+
+ s = ((head >= tail) ? head : WQUEUESIZE) - tail;
+ s = min(s, n);
+
+ if (s <= 0)
+ break;
+
+ memcpy_toio(&ch->ch_neo_uart->txrxburst, ch->ch_wqueue + tail, s);
+ /* Add and flip queue if needed */
+ tail = (tail + s) & WQUEUEMASK;
+ n -= s;
+ ch->ch_txcount += s;
+ len_written += s;
+ }
+
+ /* Update the final tail */
+ ch->ch_w_tail = tail & WQUEUEMASK;
+
+ if (len_written >= ch->ch_t_tlevel)
+ ch->ch_flags &= ~(CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
+
+ if (!jsm_tty_write(&ch->uart_port))
+ uart_write_wakeup(&ch->uart_port);
+}
+
+static void neo_parse_modem(struct jsm_channel *ch, u8 signals)
+{
+ u8 msignals = signals;
+
+ jsm_printk(MSIGS, INFO, &ch->ch_bd->pci_dev,
+ "neo_parse_modem: port: %d msignals: %x\n", ch->ch_portnum, msignals);
+
+ if (!ch)
+ return;
+
+ /* Scrub off lower bits. They signify delta's, which I don't care about */
+ msignals &= 0xf0;
+
+ if (msignals & UART_MSR_DCD)
+ ch->ch_mistat |= UART_MSR_DCD;
+ else
+ ch->ch_mistat &= ~UART_MSR_DCD;
+
+ if (msignals & UART_MSR_DSR)
+ ch->ch_mistat |= UART_MSR_DSR;
+ else
+ ch->ch_mistat &= ~UART_MSR_DSR;
+
+ if (msignals & UART_MSR_RI)
+ ch->ch_mistat |= UART_MSR_RI;
+ else
+ ch->ch_mistat &= ~UART_MSR_RI;
+
+ if (msignals & UART_MSR_CTS)
+ ch->ch_mistat |= UART_MSR_CTS;
+ else
+ ch->ch_mistat &= ~UART_MSR_CTS;
+
+ jsm_printk(MSIGS, INFO, &ch->ch_bd->pci_dev,
+ "Port: %d DTR: %d RTS: %d CTS: %d DSR: %d " "RI: %d CD: %d\n",
+ ch->ch_portnum,
+ !!((ch->ch_mistat | ch->ch_mostat) & UART_MCR_DTR),
+ !!((ch->ch_mistat | ch->ch_mostat) & UART_MCR_RTS),
+ !!((ch->ch_mistat | ch->ch_mostat) & UART_MSR_CTS),
+ !!((ch->ch_mistat | ch->ch_mostat) & UART_MSR_DSR),
+ !!((ch->ch_mistat | ch->ch_mostat) & UART_MSR_RI),
+ !!((ch->ch_mistat | ch->ch_mostat) & UART_MSR_DCD));
+}
+
+/* Make the UART raise any of the output signals we want up */
+static void neo_assert_modem_signals(struct jsm_channel *ch)
+{
+ u8 out;
+
+ if (!ch)
+ return;
+
+ out = ch->ch_mostat;
+
+ writeb(out, &ch->ch_neo_uart->mcr);
+
+ /* flush write operation */
+ neo_pci_posting_flush(ch->ch_bd);
+}
+
+/*
+ * Flush the WRITE FIFO on the Neo.
+ *
+ * NOTE: Channel lock MUST be held before calling this function!
+ */
+static void neo_flush_uart_write(struct jsm_channel *ch)
+{
+ u8 tmp = 0;
+ int i = 0;
+
+ if (!ch)
+ return;
+
+ writeb((UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_XMIT), &ch->ch_neo_uart->isr_fcr);
+
+ for (i = 0; i < 10; i++) {
+
+ /* Check to see if the UART feels it completely flushed the FIFO. */
+ tmp = readb(&ch->ch_neo_uart->isr_fcr);
+ if (tmp & 4) {
+ jsm_printk(IOCTL, INFO, &ch->ch_bd->pci_dev,
+ "Still flushing TX UART... i: %d\n", i);
+ udelay(10);
+ }
+ else
+ break;
+ }
+
+ ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
+}
+
+
+/*
+ * Flush the READ FIFO on the Neo.
+ *
+ * NOTE: Channel lock MUST be held before calling this function!
+ */
+static void neo_flush_uart_read(struct jsm_channel *ch)
+{
+ u8 tmp = 0;
+ int i = 0;
+
+ if (!ch)
+ return;
+
+ writeb((UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR), &ch->ch_neo_uart->isr_fcr);
+
+ for (i = 0; i < 10; i++) {
+
+ /* Check to see if the UART feels it completely flushed the FIFO. */
+ tmp = readb(&ch->ch_neo_uart->isr_fcr);
+ if (tmp & 2) {
+ jsm_printk(IOCTL, INFO, &ch->ch_bd->pci_dev,
+ "Still flushing RX UART... i: %d\n", i);
+ udelay(10);
+ }
+ else
+ break;
+ }
+}
+
+/*
+ * No locks are assumed to be held when calling this function.
+ */
+void neo_clear_break(struct jsm_channel *ch, int force)
+{
+ u64 lock_flags;
+
+ spin_lock_irqsave(&ch->ch_lock, lock_flags);
+
+ /* Turn break off, and unset some variables */
+ if (ch->ch_flags & CH_BREAK_SENDING) {
+ u8 temp = readb(&ch->ch_neo_uart->lcr);
+ writeb((temp & ~UART_LCR_SBC), &ch->ch_neo_uart->lcr);
+
+ ch->ch_flags &= ~(CH_BREAK_SENDING);
+ jsm_printk(IOCTL, INFO, &ch->ch_bd->pci_dev,
+ "clear break Finishing UART_LCR_SBC! finished: %lx\n", jiffies);
+
+ /* flush write operation */
+ neo_pci_posting_flush(ch->ch_bd);
+ }
+ spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
+}
+
+/*
+ * Parse the ISR register.
+ */
+static inline void neo_parse_isr(struct jsm_board *brd, u32 port)
+{
+ struct jsm_channel *ch;
+ u8 isr;
+ u8 cause;
+ u64 lock_flags;
+
+ if (!brd)
+ return;
+
+ if (port > brd->maxports)
+ return;
+
+ ch = brd->channels[port];
+ if (!ch)
+ return;
+
+ /* Here we try to figure out what caused the interrupt to happen */
+ while (1) {
+
+ isr = readb(&ch->ch_neo_uart->isr_fcr);
+
+ /* Bail if no pending interrupt */
+ if (isr & UART_IIR_NO_INT)
+ break;
+
+ /*
+ * Yank off the upper 2 bits, which just show that the FIFO's are enabled.
+ */
+ isr &= ~(UART_17158_IIR_FIFO_ENABLED);
+
+ jsm_printk(INTR, INFO, &ch->ch_bd->pci_dev,
+ "%s:%d isr: %x\n", __FILE__, __LINE__, isr);
+
+ if (isr & (UART_17158_IIR_RDI_TIMEOUT | UART_IIR_RDI)) {
+ /* Read data from uart -> queue */
+ neo_copy_data_from_uart_to_queue(ch);
+
+ /* Call our tty layer to enforce queue flow control if needed. */
+ spin_lock_irqsave(&ch->ch_lock, lock_flags);
+ jsm_check_queue_flow_control(ch);
+ spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
+ }
+
+ if (isr & UART_IIR_THRI) {
+ /* Transfer data (if any) from Write Queue -> UART. */
+ spin_lock_irqsave(&ch->ch_lock, lock_flags);
+ ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
+ spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
+ neo_copy_data_from_queue_to_uart(ch);
+ }
+
+ if (isr & UART_17158_IIR_XONXOFF) {
+ cause = readb(&ch->ch_neo_uart->xoffchar1);
+
+ jsm_printk(INTR, INFO, &ch->ch_bd->pci_dev,
+ "Port %d. Got ISR_XONXOFF: cause:%x\n", port, cause);
+
+ /*
+ * Since the UART detected either an XON or
+ * XOFF match, we need to figure out which
+ * one it was, so we can suspend or resume data flow.
+ */
+ spin_lock_irqsave(&ch->ch_lock, lock_flags);
+ if (cause == UART_17158_XON_DETECT) {
+ /* Is output stopped right now, if so, resume it */
+ if (brd->channels[port]->ch_flags & CH_STOP) {
+ ch->ch_flags &= ~(CH_STOP);
+ }
+ jsm_printk(INTR, INFO, &ch->ch_bd->pci_dev,
+ "Port %d. XON detected in incoming data\n", port);
+ }
+ else if (cause == UART_17158_XOFF_DETECT) {
+ if (!(brd->channels[port]->ch_flags & CH_STOP)) {
+ ch->ch_flags |= CH_STOP;
+ jsm_printk(INTR, INFO, &ch->ch_bd->pci_dev,
+ "Setting CH_STOP\n");
+ }
+ jsm_printk(INTR, INFO, &ch->ch_bd->pci_dev,
+ "Port: %d. XOFF detected in incoming data\n", port);
+ }
+ spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
+ }
+
+ if (isr & UART_17158_IIR_HWFLOW_STATE_CHANGE) {
+ /*
+ * If we get here, this means the hardware is doing auto flow control.
+ * Check to see whether RTS/DTR or CTS/DSR caused this interrupt.
+ */
+ cause = readb(&ch->ch_neo_uart->mcr);
+
+ /* Which pin is doing auto flow? RTS or DTR? */
+ spin_lock_irqsave(&ch->ch_lock, lock_flags);
+ if ((cause & 0x4) == 0) {
+ if (cause & UART_MCR_RTS)
+ ch->ch_mostat |= UART_MCR_RTS;
+ else
+ ch->ch_mostat &= ~(UART_MCR_RTS);
+ } else {
+ if (cause & UART_MCR_DTR)
+ ch->ch_mostat |= UART_MCR_DTR;
+ else
+ ch->ch_mostat &= ~(UART_MCR_DTR);
+ }
+ spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
+ }
+
+ /* Parse any modem signal changes */
+ jsm_printk(INTR, INFO, &ch->ch_bd->pci_dev,
+ "MOD_STAT: sending to parse_modem_sigs\n");
+ neo_parse_modem(ch, readb(&ch->ch_neo_uart->msr));
+ }
+}
+
+static inline void neo_parse_lsr(struct jsm_board *brd, u32 port)
+{
+ struct jsm_channel *ch;
+ int linestatus;
+ u64 lock_flags;
+
+ if (!brd)
+ return;
+
+ if (port > brd->maxports)
+ return;
+
+ ch = brd->channels[port];
+ if (!ch)
+ return;
+
+ linestatus = readb(&ch->ch_neo_uart->lsr);
+
+ jsm_printk(INTR, INFO, &ch->ch_bd->pci_dev,
+ "%s:%d port: %d linestatus: %x\n", __FILE__, __LINE__, port, linestatus);
+
+ ch->ch_cached_lsr |= linestatus;
+
+ if (ch->ch_cached_lsr & UART_LSR_DR) {
+ /* Read data from uart -> queue */
+ neo_copy_data_from_uart_to_queue(ch);
+ spin_lock_irqsave(&ch->ch_lock, lock_flags);
+ jsm_check_queue_flow_control(ch);
+ spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
+ }
+
+ /*
+ * This is a special flag. It indicates that at least 1
+ * RX error (parity, framing, or break) has happened.
+ * Mark this in our struct, which will tell me that I have
+ *to do the special RX+LSR read for this FIFO load.
+ */
+ if (linestatus & UART_17158_RX_FIFO_DATA_ERROR)
+ jsm_printk(INTR, DEBUG, &ch->ch_bd->pci_dev,
+ "%s:%d Port: %d Got an RX error, need to parse LSR\n",
+ __FILE__, __LINE__, port);
+
+ /*
+ * The next 3 tests should *NOT* happen, as the above test
+ * should encapsulate all 3... At least, thats what Exar says.
+ */
+
+ if (linestatus & UART_LSR_PE) {
+ ch->ch_err_parity++;
+ jsm_printk(INTR, DEBUG, &ch->ch_bd->pci_dev,
+ "%s:%d Port: %d. PAR ERR!\n", __FILE__, __LINE__, port);
+ }
+
+ if (linestatus & UART_LSR_FE) {
+ ch->ch_err_frame++;
+ jsm_printk(INTR, DEBUG, &ch->ch_bd->pci_dev,
+ "%s:%d Port: %d. FRM ERR!\n", __FILE__, __LINE__, port);
+ }
+
+ if (linestatus & UART_LSR_BI) {
+ ch->ch_err_break++;
+ jsm_printk(INTR, DEBUG, &ch->ch_bd->pci_dev,
+ "%s:%d Port: %d. BRK INTR!\n", __FILE__, __LINE__, port);
+ }
+
+ if (linestatus & UART_LSR_OE) {
+ /*
+ * Rx Oruns. Exar says that an orun will NOT corrupt
+ * the FIFO. It will just replace the holding register
+ * with this new data byte. So basically just ignore this.
+ * Probably we should eventually have an orun stat in our driver...
+ */
+ ch->ch_err_overrun++;
+ jsm_printk(INTR, DEBUG, &ch->ch_bd->pci_dev,
+ "%s:%d Port: %d. Rx Overrun!\n", __FILE__, __LINE__, port);
+ }
+
+ if (linestatus & UART_LSR_THRE) {
+ spin_lock_irqsave(&ch->ch_lock, lock_flags);
+ ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
+ spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
+
+ /* Transfer data (if any) from Write Queue -> UART. */
+ neo_copy_data_from_queue_to_uart(ch);
+ }
+ else if (linestatus & UART_17158_TX_AND_FIFO_CLR) {
+ spin_lock_irqsave(&ch->ch_lock, lock_flags);
+ ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
+ spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
+
+ /* Transfer data (if any) from Write Queue -> UART. */
+ neo_copy_data_from_queue_to_uart(ch);
+ }
+}
+
+/*
+ * neo_param()
+ * Send any/all changes to the line to the UART.
+ */
+static void neo_param(struct jsm_channel *ch)
+{
+ u8 lcr = 0;
+ u8 uart_lcr = 0;
+ u8 ier = 0;
+ u32 baud = 9600;
+ int quot = 0;
+ struct jsm_board *bd;
+
+ bd = ch->ch_bd;
+ if (!bd)
+ return;
+
+ /*
+ * If baud rate is zero, flush queues, and set mval to drop DTR.
+ */
+ if ((ch->ch_c_cflag & (CBAUD)) == 0) {
+ ch->ch_r_head = ch->ch_r_tail = 0;
+ ch->ch_e_head = ch->ch_e_tail = 0;
+ ch->ch_w_head = ch->ch_w_tail = 0;
+
+ neo_flush_uart_write(ch);
+ neo_flush_uart_read(ch);
+
+ ch->ch_flags |= (CH_BAUD0);
+ ch->ch_mostat &= ~(UART_MCR_RTS | UART_MCR_DTR);
+ neo_assert_modem_signals(ch);
+ ch->ch_old_baud = 0;
+ return;
+
+ } else if (ch->ch_custom_speed) {
+ baud = ch->ch_custom_speed;
+ if (ch->ch_flags & CH_BAUD0)
+ ch->ch_flags &= ~(CH_BAUD0);
+ } else {
+ int iindex = 0;
+ int jindex = 0;
+
+ const u64 bauds[4][16] = {
+ {
+ 0, 50, 75, 110,
+ 134, 150, 200, 300,
+ 600, 1200, 1800, 2400,
+ 4800, 9600, 19200, 38400 },
+ {
+ 0, 57600, 115200, 230400,
+ 460800, 150, 200, 921600,
+ 600, 1200, 1800, 2400,
+ 4800, 9600, 19200, 38400 },
+ {
+ 0, 57600, 76800, 115200,
+ 131657, 153600, 230400, 460800,
+ 921600, 1200, 1800, 2400,
+ 4800, 9600, 19200, 38400 },
+ {
+ 0, 57600, 115200, 230400,
+ 460800, 150, 200, 921600,
+ 600, 1200, 1800, 2400,
+ 4800, 9600, 19200, 38400 }
+ };
+
+ baud = C_BAUD(ch->uart_port.info->tty) & 0xff;
+
+ if (ch->ch_c_cflag & CBAUDEX)
+ iindex = 1;
+
+ jindex = baud;
+
+ if ((iindex >= 0) && (iindex < 4) && (jindex >= 0) && (jindex < 16))
+ baud = bauds[iindex][jindex];
+ else {
+ jsm_printk(IOCTL, DEBUG, &ch->ch_bd->pci_dev,
+ "baud indices were out of range (%d)(%d)",
+ iindex, jindex);
+ baud = 0;
+ }
+
+ if (baud == 0)
+ baud = 9600;
+
+ if (ch->ch_flags & CH_BAUD0)
+ ch->ch_flags &= ~(CH_BAUD0);
+ }
+
+ if (ch->ch_c_cflag & PARENB)
+ lcr |= UART_LCR_PARITY;
+
+ if (!(ch->ch_c_cflag & PARODD))
+ lcr |= UART_LCR_EPAR;
+
+ /*
+ * Not all platforms support mark/space parity,
+ * so this will hide behind an ifdef.
+ */
+#ifdef CMSPAR
+ if (ch->ch_c_cflag & CMSPAR)
+ lcr |= UART_LCR_SPAR;
+#endif
+
+ if (ch->ch_c_cflag & CSTOPB)
+ lcr |= UART_LCR_STOP;
+
+ switch (ch->ch_c_cflag & CSIZE) {
+ case CS5:
+ lcr |= UART_LCR_WLEN5;
+ break;
+ case CS6:
+ lcr |= UART_LCR_WLEN6;
+ break;
+ case CS7:
+ lcr |= UART_LCR_WLEN7;
+ break;
+ case CS8:
+ default:
+ lcr |= UART_LCR_WLEN8;
+ break;
+ }
+
+ ier = readb(&ch->ch_neo_uart->ier);
+ uart_lcr = readb(&ch->ch_neo_uart->lcr);
+
+ if (baud == 0)
+ baud = 9600;
+
+ quot = ch->ch_bd->bd_dividend / baud;
+
+ if (quot != 0) {
+ ch->ch_old_baud = baud;
+ writeb(UART_LCR_DLAB, &ch->ch_neo_uart->lcr);
+ writeb((quot & 0xff), &ch->ch_neo_uart->txrx);
+ writeb((quot >> 8), &ch->ch_neo_uart->ier);
+ writeb(lcr, &ch->ch_neo_uart->lcr);
+ }
+
+ if (uart_lcr != lcr)
+ writeb(lcr, &ch->ch_neo_uart->lcr);
+
+ if (ch->ch_c_cflag & CREAD)
+ ier |= (UART_IER_RDI | UART_IER_RLSI);
+
+ ier |= (UART_IER_THRI | UART_IER_MSI);
+
+ writeb(ier, &ch->ch_neo_uart->ier);
+
+ /* Set new start/stop chars */
+ neo_set_new_start_stop_chars(ch);
+
+ if (ch->ch_c_cflag & CRTSCTS)
+ neo_set_cts_flow_control(ch);
+ else if (ch->ch_c_iflag & IXON) {
+ /* If start/stop is set to disable, then we should disable flow control */
+ if ((ch->ch_startc == __DISABLED_CHAR) || (ch->ch_stopc == __DISABLED_CHAR))
+ neo_set_no_output_flow_control(ch);
+ else
+ neo_set_ixon_flow_control(ch);
+ }
+ else
+ neo_set_no_output_flow_control(ch);
+
+ if (ch->ch_c_cflag & CRTSCTS)
+ neo_set_rts_flow_control(ch);
+ else if (ch->ch_c_iflag & IXOFF) {
+ /* If start/stop is set to disable, then we should disable flow control */
+ if ((ch->ch_startc == __DISABLED_CHAR) || (ch->ch_stopc == __DISABLED_CHAR))
+ neo_set_no_input_flow_control(ch);
+ else
+ neo_set_ixoff_flow_control(ch);
+ }
+ else
+ neo_set_no_input_flow_control(ch);
+ /*
+ * Adjust the RX FIFO Trigger level if baud is less than 9600.
+ * Not exactly elegant, but this is needed because of the Exar chip's
+ * delay on firing off the RX FIFO interrupt on slower baud rates.
+ */
+ if (baud < 9600) {
+ writeb(1, &ch->ch_neo_uart->rfifo);
+ ch->ch_r_tlevel = 1;
+ }
+
+ neo_assert_modem_signals(ch);
+
+ /* Get current status of the modem signals now */
+ neo_parse_modem(ch, readb(&ch->ch_neo_uart->msr));
+ return;
+}
+
+/*
+ * jsm_neo_intr()
+ *
+ * Neo specific interrupt handler.
+ */
+static irqreturn_t neo_intr(int irq, void *voidbrd, struct pt_regs *regs)
+{
+ struct jsm_board *brd = (struct jsm_board *) voidbrd;
+ struct jsm_channel *ch;
+ int port = 0;
+ int type = 0;
+ int current_port;
+ u32 tmp;
+ u32 uart_poll;
+ unsigned long lock_flags;
+ unsigned long lock_flags2;
+ int outofloop_count = 0;
+
+ brd->intr_count++;
+
+ /* Lock out the slow poller from running on this board. */
+ spin_lock_irqsave(&brd->bd_intr_lock, lock_flags);
+
+ /*
+ * Read in "extended" IRQ information from the 32bit Neo register.
+ * Bits 0-7: What port triggered the interrupt.
+ * Bits 8-31: Each 3bits indicate what type of interrupt occurred.
+ */
+ uart_poll = readl(brd->re_map_membase + UART_17158_POLL_ADDR_OFFSET);
+
+ jsm_printk(INTR, INFO, &brd->pci_dev,
+ "%s:%d uart_poll: %x\n", __FILE__, __LINE__, uart_poll);
+
+ if (!uart_poll) {
+ jsm_printk(INTR, INFO, &brd->pci_dev,
+ "Kernel interrupted to me, but no pending interrupts...\n");
+ spin_unlock_irqrestore(&brd->bd_intr_lock, lock_flags);
+ return IRQ_NONE;
+ }
+
+ /* At this point, we have at least SOMETHING to service, dig further... */
+
+ current_port = 0;
+
+ /* Loop on each port */
+ while (((uart_poll & 0xff) != 0) && (outofloop_count < 0xff)){
+
+ tmp = uart_poll;
+ outofloop_count++;
+
+ /* Check current port to see if it has interrupt pending */
+ if ((tmp & jsm_offset_table[current_port]) != 0) {
+ port = current_port;
+ type = tmp >> (8 + (port * 3));
+ type &= 0x7;
+ } else {
+ current_port++;
+ continue;
+ }
+
+ jsm_printk(INTR, INFO, &brd->pci_dev,
+ "%s:%d port: %x type: %x\n", __FILE__, __LINE__, port, type);
+
+ /* Remove this port + type from uart_poll */
+ uart_poll &= ~(jsm_offset_table[port]);
+
+ if (!type) {
+ /* If no type, just ignore it, and move onto next port */
+ jsm_printk(INTR, ERR, &brd->pci_dev,
+ "Interrupt with no type! port: %d\n", port);
+ continue;
+ }
+
+ /* Switch on type of interrupt we have */
+ switch (type) {
+
+ case UART_17158_RXRDY_TIMEOUT:
+ /*
+ * RXRDY Time-out is cleared by reading data in the
+ * RX FIFO until it falls below the trigger level.
+ */
+
+ /* Verify the port is in range. */
+ if (port > brd->nasync)
+ continue;
+
+ ch = brd->channels[port];
+ neo_copy_data_from_uart_to_queue(ch);
+
+ /* Call our tty layer to enforce queue flow control if needed. */
+ spin_lock_irqsave(&ch->ch_lock, lock_flags2);
+ jsm_check_queue_flow_control(ch);
+ spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
+
+ continue;
+
+ case UART_17158_RX_LINE_STATUS:
+ /*
+ * RXRDY and RX LINE Status (logic OR of LSR[4:1])
+ */
+ neo_parse_lsr(brd, port);
+ continue;
+
+ case UART_17158_TXRDY:
+ /*
+ * TXRDY interrupt clears after reading ISR register for the UART channel.
+ */
+
+ /*
+ * Yes, this is odd...
+ * Why would I check EVERY possibility of type of
+ * interrupt, when we know its TXRDY???
+ * Becuz for some reason, even tho we got triggered for TXRDY,
+ * it seems to be occassionally wrong. Instead of TX, which
+ * it should be, I was getting things like RXDY too. Weird.
+ */
+ neo_parse_isr(brd, port);
+ continue;
+
+ case UART_17158_MSR:
+ /*
+ * MSR or flow control was seen.
+ */
+ neo_parse_isr(brd, port);
+ continue;
+
+ default:
+ /*
+ * The UART triggered us with a bogus interrupt type.
+ * It appears the Exar chip, when REALLY bogged down, will throw
+ * these once and awhile.
+ * Its harmless, just ignore it and move on.
+ */
+ jsm_printk(INTR, ERR, &brd->pci_dev,
+ "%s:%d Unknown Interrupt type: %x\n", __FILE__, __LINE__, type);
+ continue;
+ }
+ }
+
+ spin_unlock_irqrestore(&brd->bd_intr_lock, lock_flags);
+
+ jsm_printk(INTR, INFO, &brd->pci_dev, "finish.\n");
+ return IRQ_HANDLED;
+}
+
+/*
+ * Neo specific way of turning off the receiver.
+ * Used as a way to enforce queue flow control when in
+ * hardware flow control mode.
+ */
+static void neo_disable_receiver(struct jsm_channel *ch)
+{
+ u8 tmp = readb(&ch->ch_neo_uart->ier);
+ tmp &= ~(UART_IER_RDI);
+ writeb(tmp, &ch->ch_neo_uart->ier);
+
+ /* flush write operation */
+ neo_pci_posting_flush(ch->ch_bd);
+}
+
+
+/*
+ * Neo specific way of turning on the receiver.
+ * Used as a way to un-enforce queue flow control when in
+ * hardware flow control mode.
+ */
+static void neo_enable_receiver(struct jsm_channel *ch)
+{
+ u8 tmp = readb(&ch->ch_neo_uart->ier);
+ tmp |= (UART_IER_RDI);
+ writeb(tmp, &ch->ch_neo_uart->ier);
+
+ /* flush write operation */
+ neo_pci_posting_flush(ch->ch_bd);
+}
+
+static void neo_send_start_character(struct jsm_channel *ch)
+{
+ if (!ch)
+ return;
+
+ if (ch->ch_startc != __DISABLED_CHAR) {
+ ch->ch_xon_sends++;
+ writeb(ch->ch_startc, &ch->ch_neo_uart->txrx);
+
+ /* flush write operation */
+ neo_pci_posting_flush(ch->ch_bd);
+ }
+}
+
+static void neo_send_stop_character(struct jsm_channel *ch)
+{
+ if (!ch)
+ return;
+
+ if (ch->ch_stopc != __DISABLED_CHAR) {
+ ch->ch_xoff_sends++;
+ writeb(ch->ch_stopc, &ch->ch_neo_uart->txrx);
+
+ /* flush write operation */
+ neo_pci_posting_flush(ch->ch_bd);
+ }
+}
+
+/*
+ * neo_uart_init
+ */
+static void neo_uart_init(struct jsm_channel *ch)
+{
+ writeb(0, &ch->ch_neo_uart->ier);
+ writeb(0, &ch->ch_neo_uart->efr);
+ writeb(UART_EFR_ECB, &ch->ch_neo_uart->efr);
+
+ /* Clear out UART and FIFO */
+ readb(&ch->ch_neo_uart->txrx);
+ writeb((UART_FCR_ENABLE_FIFO|UART_FCR_CLEAR_RCVR|UART_FCR_CLEAR_XMIT), &ch->ch_neo_uart->isr_fcr);
+ readb(&ch->ch_neo_uart->lsr);
+ readb(&ch->ch_neo_uart->msr);
+
+ ch->ch_flags |= CH_FIFO_ENABLED;
+
+ /* Assert any signals we want up */
+ writeb(ch->ch_mostat, &ch->ch_neo_uart->mcr);
+}
+
+/*
+ * Make the UART completely turn off.
+ */
+static void neo_uart_off(struct jsm_channel *ch)
+{
+ /* Turn off UART enhanced bits */
+ writeb(0, &ch->ch_neo_uart->efr);
+
+ /* Stop all interrupts from occurring. */
+ writeb(0, &ch->ch_neo_uart->ier);
+}
+
+static u32 neo_get_uart_bytes_left(struct jsm_channel *ch)
+{
+ u8 left = 0;
+ u8 lsr = readb(&ch->ch_neo_uart->lsr);
+
+ /* We must cache the LSR as some of the bits get reset once read... */
+ ch->ch_cached_lsr |= lsr;
+
+ /* Determine whether the Transmitter is empty or not */
+ if (!(lsr & UART_LSR_TEMT))
+ left = 1;
+ else {
+ ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
+ left = 0;
+ }
+
+ return left;
+}
+
+/* Channel lock MUST be held by the calling function! */
+static void neo_send_break(struct jsm_channel *ch)
+{
+ /*
+ * Set the time we should stop sending the break.
+ * If we are already sending a break, toss away the existing
+ * time to stop, and use this new value instead.
+ */
+
+ /* Tell the UART to start sending the break */
+ if (!(ch->ch_flags & CH_BREAK_SENDING)) {
+ u8 temp = readb(&ch->ch_neo_uart->lcr);
+ writeb((temp | UART_LCR_SBC), &ch->ch_neo_uart->lcr);
+ ch->ch_flags |= (CH_BREAK_SENDING);
+
+ /* flush write operation */
+ neo_pci_posting_flush(ch->ch_bd);
+ }
+}
+
+/*
+ * neo_send_immediate_char.
+ *
+ * Sends a specific character as soon as possible to the UART,
+ * jumping over any bytes that might be in the write queue.
+ *
+ * The channel lock MUST be held by the calling function.
+ */
+static void neo_send_immediate_char(struct jsm_channel *ch, unsigned char c)
+{
+ if (!ch)
+ return;
+
+ writeb(c, &ch->ch_neo_uart->txrx);
+
+ /* flush write operation */
+ neo_pci_posting_flush(ch->ch_bd);
+}
+
+struct board_ops jsm_neo_ops = {
+ .intr = neo_intr,
+ .uart_init = neo_uart_init,
+ .uart_off = neo_uart_off,
+ .param = neo_param,
+ .assert_modem_signals = neo_assert_modem_signals,
+ .flush_uart_write = neo_flush_uart_write,
+ .flush_uart_read = neo_flush_uart_read,
+ .disable_receiver = neo_disable_receiver,
+ .enable_receiver = neo_enable_receiver,
+ .send_break = neo_send_break,
+ .clear_break = neo_clear_break,
+ .send_start_character = neo_send_start_character,
+ .send_stop_character = neo_send_stop_character,
+ .copy_data_from_queue_to_uart = neo_copy_data_from_queue_to_uart,
+ .get_uart_bytes_left = neo_get_uart_bytes_left,
+ .send_immediate_char = neo_send_immediate_char
+};
diff --git a/drivers/serial/jsm/jsm_tty.c b/drivers/serial/jsm/jsm_tty.c
new file mode 100644
index 0000000000000..b6bc881166c0d
--- /dev/null
+++ b/drivers/serial/jsm/jsm_tty.c
@@ -0,0 +1,1043 @@
+/************************************************************************
+ * Copyright 2003 Digi International (www.digi.com)
+ *
+ * Copyright (C) 2004 IBM 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the 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.
+ *
+ * Contact Information:
+ * Scott H Kilau <Scott_Kilau@digi.com>
+ * Wendy Xiong <wendyx@us.ltcfwd.linux.ibm.com>
+ *
+ ***********************************************************************/
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/serial_reg.h>
+#include <linux/delay.h> /* For udelay */
+#include <linux/pci.h>
+
+#include "jsm.h"
+
+static inline int jsm_get_mstat(struct jsm_channel *ch)
+{
+ unsigned char mstat;
+ unsigned char result;
+
+ jsm_printk(IOCTL, INFO, &ch->ch_bd->pci_dev, "start\n");
+
+ mstat = (ch->ch_mostat | ch->ch_mistat);
+
+ result = 0;
+
+ if (mstat & UART_MCR_DTR)
+ result |= TIOCM_DTR;
+ if (mstat & UART_MCR_RTS)
+ result |= TIOCM_RTS;
+ if (mstat & UART_MSR_CTS)
+ result |= TIOCM_CTS;
+ if (mstat & UART_MSR_DSR)
+ result |= TIOCM_DSR;
+ if (mstat & UART_MSR_RI)
+ result |= TIOCM_RI;
+ if (mstat & UART_MSR_DCD)
+ result |= TIOCM_CD;
+
+ jsm_printk(IOCTL, INFO, &ch->ch_bd->pci_dev, "finish\n");
+ return result;
+}
+
+static unsigned int jsm_tty_tx_empty(struct uart_port *port)
+{
+ return TIOCSER_TEMT;
+}
+
+/*
+ * Return modem signals to ld.
+ */
+static unsigned int jsm_tty_get_mctrl(struct uart_port *port)
+{
+ int result;
+ struct jsm_channel *channel = (struct jsm_channel *)port;
+
+ jsm_printk(IOCTL, INFO, &channel->ch_bd->pci_dev, "start\n");
+
+ result = jsm_get_mstat(channel);
+
+ if (result < 0)
+ return -ENXIO;
+
+ jsm_printk(IOCTL, INFO, &channel->ch_bd->pci_dev, "finish\n");
+
+ return result;
+}
+
+/*
+ * jsm_set_modem_info()
+ *
+ * Set modem signals, called by ld.
+ */
+static void jsm_tty_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+ struct jsm_channel *channel = (struct jsm_channel *)port;
+
+ jsm_printk(IOCTL, INFO, &channel->ch_bd->pci_dev, "start\n");
+
+ if (mctrl & TIOCM_RTS)
+ channel->ch_mostat |= UART_MCR_RTS;
+ else
+ channel->ch_mostat &= ~UART_MCR_RTS;
+
+ if (mctrl & TIOCM_DTR)
+ channel->ch_mostat |= UART_MCR_DTR;
+ else
+ channel->ch_mostat &= ~UART_MCR_DTR;
+
+ channel->ch_bd->bd_ops->assert_modem_signals(channel);
+
+ jsm_printk(IOCTL, INFO, &channel->ch_bd->pci_dev, "finish\n");
+ udelay(10);
+}
+
+static void jsm_tty_start_tx(struct uart_port *port, unsigned int tty_start)
+{
+ struct jsm_channel *channel = (struct jsm_channel *)port;
+
+ jsm_printk(IOCTL, INFO, &channel->ch_bd->pci_dev, "start\n");
+
+ channel->ch_flags &= ~(CH_STOP);
+ jsm_tty_write(port);
+
+ jsm_printk(IOCTL, INFO, &channel->ch_bd->pci_dev, "finish\n");
+}
+
+static void jsm_tty_stop_tx(struct uart_port *port, unsigned int tty_stop)
+{
+ struct jsm_channel *channel = (struct jsm_channel *)port;
+
+ jsm_printk(IOCTL, INFO, &channel->ch_bd->pci_dev, "start\n");
+
+ channel->ch_flags |= (CH_STOP);
+
+ jsm_printk(IOCTL, INFO, &channel->ch_bd->pci_dev, "finish\n");
+}
+
+static void jsm_tty_send_xchar(struct uart_port *port, char ch)
+{
+ unsigned long lock_flags;
+ struct jsm_channel *channel = (struct jsm_channel *)port;
+
+ spin_lock_irqsave(&port->lock, lock_flags);
+ if (ch == port->info->tty->termios->c_cc[VSTART])
+ channel->ch_bd->bd_ops->send_start_character(channel);
+
+ if (ch == port->info->tty->termios->c_cc[VSTOP])
+ channel->ch_bd->bd_ops->send_stop_character(channel);
+ spin_unlock_irqrestore(&port->lock, lock_flags);
+}
+
+static void jsm_tty_stop_rx(struct uart_port *port)
+{
+ struct jsm_channel *channel = (struct jsm_channel *)port;
+
+ channel->ch_bd->bd_ops->disable_receiver(channel);
+}
+
+static void jsm_tty_break(struct uart_port *port, int break_state)
+{
+ unsigned long lock_flags;
+ struct jsm_channel *channel = (struct jsm_channel *)port;
+
+ spin_lock_irqsave(&port->lock, lock_flags);
+ if (break_state == -1)
+ channel->ch_bd->bd_ops->send_break(channel);
+ else
+ channel->ch_bd->bd_ops->clear_break(channel, 0);
+
+ spin_unlock_irqrestore(&port->lock, lock_flags);
+}
+
+static int jsm_tty_open(struct uart_port *port)
+{
+ struct jsm_board *brd;
+ int rc = 0;
+ struct jsm_channel *channel = (struct jsm_channel *)port;
+
+ /* Get board pointer from our array of majors we have allocated */
+ brd = channel->ch_bd;
+
+ /*
+ * Allocate channel buffers for read/write/error.
+ * Set flag, so we don't get trounced on.
+ */
+ channel->ch_flags |= (CH_OPENING);
+
+ /* Drop locks, as malloc with GFP_KERNEL can sleep */
+
+ if (!channel->ch_rqueue) {
+ channel->ch_rqueue = (u8 *) kmalloc(RQUEUESIZE, GFP_KERNEL);
+ if (!channel->ch_rqueue) {
+ jsm_printk(INIT, ERR, &channel->ch_bd->pci_dev,
+ "unable to allocate read queue buf");
+ return -ENOMEM;
+ }
+ memset(channel->ch_rqueue, 0, RQUEUESIZE);
+ }
+ if (!channel->ch_equeue) {
+ channel->ch_equeue = (u8 *) kmalloc(EQUEUESIZE, GFP_KERNEL);
+ if (!channel->ch_equeue) {
+ jsm_printk(INIT, ERR, &channel->ch_bd->pci_dev,
+ "unable to allocate error queue buf");
+ return -ENOMEM;
+ }
+ memset(channel->ch_equeue, 0, EQUEUESIZE);
+ }
+ if (!channel->ch_wqueue) {
+ channel->ch_wqueue = (u8 *) kmalloc(WQUEUESIZE, GFP_KERNEL);
+ if (!channel->ch_wqueue) {
+ jsm_printk(INIT, ERR, &channel->ch_bd->pci_dev,
+ "unable to allocate write queue buf");
+ return -ENOMEM;
+ }
+ memset(channel->ch_wqueue, 0, WQUEUESIZE);
+ }
+
+ channel->ch_flags &= ~(CH_OPENING);
+ /*
+ * Initialize if neither terminal is open.
+ */
+ jsm_printk(OPEN, INFO, &channel->ch_bd->pci_dev,
+ "jsm_open: initializing channel in open...\n");
+
+ /*
+ * Flush input queues.
+ */
+ channel->ch_r_head = channel->ch_r_tail = 0;
+ channel->ch_e_head = channel->ch_e_tail = 0;
+ channel->ch_w_head = channel->ch_w_tail = 0;
+
+ brd->bd_ops->flush_uart_write(channel);
+ brd->bd_ops->flush_uart_read(channel);
+
+ channel->ch_flags = 0;
+ channel->ch_cached_lsr = 0;
+ channel->ch_stops_sent = 0;
+
+ channel->ch_c_cflag = port->info->tty->termios->c_cflag;
+ channel->ch_c_iflag = port->info->tty->termios->c_iflag;
+ channel->ch_c_oflag = port->info->tty->termios->c_oflag;
+ channel->ch_c_lflag = port->info->tty->termios->c_lflag;
+ channel->ch_startc = port->info->tty->termios->c_cc[VSTART];
+ channel->ch_stopc = port->info->tty->termios->c_cc[VSTOP];
+
+ /* Tell UART to init itself */
+ brd->bd_ops->uart_init(channel);
+
+ /*
+ * Run param in case we changed anything
+ */
+ brd->bd_ops->param(channel);
+
+ jsm_carrier(channel);
+
+ channel->ch_open_count++;
+
+ jsm_printk(OPEN, INFO, &channel->ch_bd->pci_dev, "finish\n");
+ return rc;
+}
+
+static void jsm_tty_close(struct uart_port *port)
+{
+ struct jsm_board *bd;
+ struct termios *ts;
+ struct jsm_channel *channel = (struct jsm_channel *)port;
+
+ jsm_printk(CLOSE, INFO, &channel->ch_bd->pci_dev, "start\n");
+
+ bd = channel->ch_bd;
+ ts = channel->uart_port.info->tty->termios;
+
+ channel->ch_flags &= ~(CH_STOPI);
+
+ channel->ch_open_count--;
+
+ /*
+ * If we have HUPCL set, lower DTR and RTS
+ */
+ if (channel->ch_c_cflag & HUPCL) {
+ jsm_printk(CLOSE, INFO, &channel->ch_bd->pci_dev,
+ "Close. HUPCL set, dropping DTR/RTS\n");
+
+ /* Drop RTS/DTR */
+ channel->ch_mostat &= ~(UART_MCR_DTR | UART_MCR_RTS);
+ bd->bd_ops->assert_modem_signals(channel);
+ }
+
+ channel->ch_old_baud = 0;
+
+ /* Turn off UART interrupts for this port */
+ channel->ch_bd->bd_ops->uart_off(channel);
+
+ jsm_printk(CLOSE, INFO, &channel->ch_bd->pci_dev, "finish\n");
+}
+
+static void jsm_tty_set_termios(struct uart_port *port,
+ struct termios *termios,
+ struct termios *old_termios)
+{
+ unsigned long lock_flags;
+ struct jsm_channel *channel = (struct jsm_channel *)port;
+
+ spin_lock_irqsave(&port->lock, lock_flags);
+ channel->ch_c_cflag = termios->c_cflag;
+ channel->ch_c_iflag = termios->c_iflag;
+ channel->ch_c_oflag = termios->c_oflag;
+ channel->ch_c_lflag = termios->c_lflag;
+ channel->ch_startc = termios->c_cc[VSTART];
+ channel->ch_stopc = termios->c_cc[VSTOP];
+
+ channel->ch_bd->bd_ops->param(channel);
+ jsm_carrier(channel);
+ spin_unlock_irqrestore(&port->lock, lock_flags);
+}
+
+static const char *jsm_tty_type(struct uart_port *port)
+{
+ return "jsm";
+}
+
+static void jsm_tty_release_port(struct uart_port *port)
+{
+}
+
+static int jsm_tty_request_port(struct uart_port *port)
+{
+ return 0;
+}
+
+static void jsm_config_port(struct uart_port *port, int flags)
+{
+ port->type = PORT_JSM;
+}
+
+static struct uart_ops jsm_ops = {
+ .tx_empty = jsm_tty_tx_empty,
+ .set_mctrl = jsm_tty_set_mctrl,
+ .get_mctrl = jsm_tty_get_mctrl,
+ .stop_tx = jsm_tty_stop_tx,
+ .start_tx = jsm_tty_start_tx,
+ .send_xchar = jsm_tty_send_xchar,
+ .stop_rx = jsm_tty_stop_rx,
+ .break_ctl = jsm_tty_break,
+ .startup = jsm_tty_open,
+ .shutdown = jsm_tty_close,
+ .set_termios = jsm_tty_set_termios,
+ .type = jsm_tty_type,
+ .release_port = jsm_tty_release_port,
+ .request_port = jsm_tty_request_port,
+ .config_port = jsm_config_port,
+};
+
+/*
+ * jsm_tty_init()
+ *
+ * Init the tty subsystem. Called once per board after board has been
+ * downloaded and init'ed.
+ */
+int jsm_tty_init(struct jsm_board *brd)
+{
+ int i;
+ u8 *vaddr;
+ struct jsm_channel *ch;
+
+ if (!brd)
+ return -ENXIO;
+
+ jsm_printk(INIT, INFO, &brd->pci_dev, "start\n");
+
+ /*
+ * Initialize board structure elements.
+ */
+
+ vaddr = brd->re_map_membase;
+
+ brd->nasync = brd->maxports;
+
+ /*
+ * Allocate channel memory that might not have been allocated
+ * when the driver was first loaded.
+ */
+ for (i = 0; i < brd->nasync; i++) {
+ if (!brd->channels[i]) {
+
+ /*
+ * Okay to malloc with GFP_KERNEL, we are not at
+ * interrupt context, and there are no locks held.
+ */
+ brd->channels[i] = kmalloc(sizeof(struct jsm_channel), GFP_KERNEL);
+ if (!brd->channels[i]) {
+ jsm_printk(CORE, ERR, &brd->pci_dev,
+ "%s:%d Unable to allocate memory for channel struct\n",
+ __FILE__, __LINE__);
+ }
+ memset(brd->channels[i], 0, sizeof(struct jsm_channel));
+ }
+ }
+
+ ch = brd->channels[0];
+ vaddr = brd->re_map_membase;
+
+ /* Set up channel variables */
+ for (i = 0; i < brd->nasync; i++, ch = brd->channels[i]) {
+
+ if (!brd->channels[i])
+ continue;
+
+ spin_lock_init(&ch->ch_lock);
+
+ if (brd->bd_uart_offset == 0x200)
+ ch->ch_neo_uart = (struct neo_uart_struct *) ((u64) vaddr
+ + (brd->bd_uart_offset * i));
+
+ ch->ch_bd = brd;
+ ch->ch_portnum = i;
+
+ /* .25 second delay */
+ ch->ch_close_delay = 250;
+
+ init_waitqueue_head(&ch->ch_flags_wait);
+ }
+
+ jsm_printk(INIT, INFO, &brd->pci_dev, "finish\n");
+ return 0;
+}
+
+int jsm_uart_port_init(struct jsm_board *brd)
+{
+ int i;
+ u8 *vaddr;
+ struct jsm_channel *ch;
+
+ if (!brd)
+ return -ENXIO;
+
+ jsm_printk(INIT, INFO, &brd->pci_dev, "start\n");
+
+ /*
+ * Initialize board structure elements.
+ */
+
+ vaddr = brd->re_map_membase;
+ brd->nasync = brd->maxports;
+
+ /* Set up channel variables */
+ for (i = 0; i < brd->nasync; i++, ch = brd->channels[i]) {
+
+ if (!brd->channels[i])
+ continue;
+
+ brd->channels[i]->uart_port.irq = brd->irq;
+ brd->channels[i]->uart_port.type = PORT_JSM;
+ brd->channels[i]->uart_port.iotype = UPIO_MEM;
+ brd->channels[i]->uart_port.membase = brd->re_map_membase;
+ brd->channels[i]->uart_port.fifosize = 16;
+ brd->channels[i]->uart_port.ops = &jsm_ops;
+ brd->channels[i]->uart_port.line = brd->channels[i]->ch_portnum + brd->boardnum * 2;
+ if (uart_add_one_port (&jsm_uart_driver, &brd->channels[i]->uart_port))
+ printk(KERN_INFO "Added device failed\n");
+ else
+ printk(KERN_INFO "Added device \n");
+ }
+
+ jsm_printk(INIT, INFO, &brd->pci_dev, "finish\n");
+ return 0;
+}
+
+int jsm_remove_uart_port(struct jsm_board *brd)
+{
+ int i;
+ struct jsm_channel *ch;
+
+ if (!brd)
+ return -ENXIO;
+
+ jsm_printk(INIT, INFO, &brd->pci_dev, "start\n");
+
+ /*
+ * Initialize board structure elements.
+ */
+
+ brd->nasync = brd->maxports;
+
+ /* Set up channel variables */
+ for (i = 0; i < brd->nasync; i++) {
+
+ if (!brd->channels[i])
+ continue;
+
+ ch = brd->channels[i];
+
+ uart_remove_one_port(&jsm_uart_driver, &brd->channels[i]->uart_port);
+ }
+
+ jsm_printk(INIT, INFO, &brd->pci_dev, "finish\n");
+ return 0;
+}
+
+void jsm_input(struct jsm_channel *ch)
+{
+ struct jsm_board *bd;
+ struct tty_struct *tp;
+ u32 rmask;
+ u16 head;
+ u16 tail;
+ int data_len;
+ u64 lock_flags;
+ int flip_len;
+ int len = 0;
+ int n = 0;
+ char *buf = NULL;
+ char *buf2 = NULL;
+ int s = 0;
+ int i = 0;
+
+ jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, "start\n");
+
+ if (!ch)
+ return;
+
+ tp = ch->uart_port.info->tty;
+
+ bd = ch->ch_bd;
+ if(!bd)
+ return;
+
+ spin_lock_irqsave(&ch->ch_lock, lock_flags);
+
+ /*
+ *Figure the number of characters in the buffer.
+ *Exit immediately if none.
+ */
+
+ rmask = RQUEUEMASK;
+
+ head = ch->ch_r_head & rmask;
+ tail = ch->ch_r_tail & rmask;
+
+ data_len = (head - tail) & rmask;
+ if (data_len == 0) {
+ spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
+ return;
+ }
+
+ jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, "start\n");
+
+ /*
+ *If the device is not open, or CREAD is off, flush
+ *input data and return immediately.
+ */
+ if (!tp ||
+ !(tp->termios->c_cflag & CREAD) ) {
+
+ jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
+ "input. dropping %d bytes on port %d...\n", data_len, ch->ch_portnum);
+ ch->ch_r_head = tail;
+
+ /* Force queue flow control to be released, if needed */
+ jsm_check_queue_flow_control(ch);
+
+ spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
+ return;
+ }
+
+ /*
+ * If we are throttled, simply don't read any data.
+ */
+ if (ch->ch_flags & CH_STOPI) {
+ spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
+ jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
+ "Port %d throttled, not reading any data. head: %x tail: %x\n",
+ ch->ch_portnum, head, tail);
+ return;
+ }
+
+ jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, "start 2\n");
+
+ /*
+ * If the rxbuf is empty and we are not throttled, put as much
+ * as we can directly into the linux TTY flip buffer.
+ * The jsm_rawreadok case takes advantage of carnal knowledge that
+ * the char_buf and the flag_buf are next to each other and
+ * are each of (2 * TTY_FLIPBUF_SIZE) size.
+ *
+ * NOTE: if(!tty->real_raw), the call to ldisc.receive_buf
+ *actually still uses the flag buffer, so you can't
+ *use it for input data
+ */
+ if (jsm_rawreadok) {
+ if (tp->real_raw)
+ flip_len = MYFLIPLEN;
+ else
+ flip_len = 2 * TTY_FLIPBUF_SIZE;
+ } else
+ flip_len = TTY_FLIPBUF_SIZE - tp->flip.count;
+
+ len = min(data_len, flip_len);
+ len = min(len, (N_TTY_BUF_SIZE - 1) - tp->read_cnt);
+
+ if (len <= 0) {
+ spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
+ jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, "jsm_input 1\n");
+ return;
+ }
+
+ /*
+ * If we're bypassing flip buffers on rx, we can blast it
+ * right into the beginning of the buffer.
+ */
+ if (jsm_rawreadok) {
+ if (tp->real_raw) {
+ if (ch->ch_flags & CH_FLIPBUF_IN_USE) {
+ jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
+ "JSM - FLIPBUF in use. delaying input\n");
+ spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
+ return;
+ }
+ ch->ch_flags |= CH_FLIPBUF_IN_USE;
+ buf = ch->ch_bd->flipbuf;
+ buf2 = NULL;
+ } else {
+ buf = tp->flip.char_buf;
+ buf2 = tp->flip.flag_buf;
+ }
+ } else {
+ buf = tp->flip.char_buf_ptr;
+ buf2 = tp->flip.flag_buf_ptr;
+ }
+
+ n = len;
+
+ /*
+ * n now contains the most amount of data we can copy,
+ * bounded either by the flip buffer size or the amount
+ * of data the card actually has pending...
+ */
+ while (n) {
+ s = ((head >= tail) ? head : RQUEUESIZE) - tail;
+ s = min(s, n);
+
+ if (s <= 0)
+ break;
+
+ memcpy(buf, ch->ch_rqueue + tail, s);
+
+ /* buf2 is only set when port isn't raw */
+ if (buf2)
+ memcpy(buf2, ch->ch_equeue + tail, s);
+
+ tail += s;
+ buf += s;
+ if (buf2)
+ buf2 += s;
+ n -= s;
+ /* Flip queue if needed */
+ tail &= rmask;
+ }
+
+ /*
+ * In high performance mode, we don't have to update
+ * flag_buf or any of the counts or pointers into flip buf.
+ */
+ if (!jsm_rawreadok) {
+ if (I_PARMRK(tp) || I_BRKINT(tp) || I_INPCK(tp)) {
+ for (i = 0; i < len; i++) {
+ /*
+ * Give the Linux ld the flags in the
+ * format it likes.
+ */
+ if (tp->flip.flag_buf_ptr[i] & UART_LSR_BI)
+ tp->flip.flag_buf_ptr[i] = TTY_BREAK;
+ else if (tp->flip.flag_buf_ptr[i] & UART_LSR_PE)
+ tp->flip.flag_buf_ptr[i] = TTY_PARITY;
+ else if (tp->flip.flag_buf_ptr[i] & UART_LSR_FE)
+ tp->flip.flag_buf_ptr[i] = TTY_FRAME;
+ else
+ tp->flip.flag_buf_ptr[i] = TTY_NORMAL;
+ }
+ } else {
+ memset(tp->flip.flag_buf_ptr, 0, len);
+ }
+
+ tp->flip.char_buf_ptr += len;
+ tp->flip.flag_buf_ptr += len;
+ tp->flip.count += len;
+ }
+ else if (!tp->real_raw) {
+ if (I_PARMRK(tp) || I_BRKINT(tp) || I_INPCK(tp)) {
+ for (i = 0; i < len; i++) {
+ /*
+ * Give the Linux ld the flags in the
+ * format it likes.
+ */
+ if (tp->flip.flag_buf_ptr[i] & UART_LSR_BI)
+ tp->flip.flag_buf_ptr[i] = TTY_BREAK;
+ else if (tp->flip.flag_buf_ptr[i] & UART_LSR_PE)
+ tp->flip.flag_buf_ptr[i] = TTY_PARITY;
+ else if (tp->flip.flag_buf_ptr[i] & UART_LSR_FE)
+ tp->flip.flag_buf_ptr[i] = TTY_FRAME;
+ else
+ tp->flip.flag_buf_ptr[i] = TTY_NORMAL;
+ }
+ } else
+ memset(tp->flip.flag_buf, 0, len);
+ }
+
+ /*
+ * If we're doing raw reads, jam it right into the
+ * line disc bypassing the flip buffers.
+ */
+ if (jsm_rawreadok) {
+ if (tp->real_raw) {
+ ch->ch_r_tail = tail & rmask;
+ ch->ch_e_tail = tail & rmask;
+
+ jsm_check_queue_flow_control(ch);
+
+ /* !!! WE *MUST* LET GO OF ALL LOCKS BEFORE CALLING RECEIVE BUF !!! */
+
+ spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
+
+ jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
+ "jsm_input. %d real_raw len:%d calling receive_buf for board %d\n",
+ __LINE__, len, ch->ch_bd->boardnum);
+ tp->ldisc.receive_buf(tp, ch->ch_bd->flipbuf, NULL, len);
+
+ /* Allow use of channel flip buffer again */
+ spin_lock_irqsave(&ch->ch_lock, lock_flags);
+ ch->ch_flags &= ~CH_FLIPBUF_IN_USE;
+ spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
+
+ } else {
+ ch->ch_r_tail = tail & rmask;
+ ch->ch_e_tail = tail & rmask;
+
+ jsm_check_queue_flow_control(ch);
+
+ /* !!! WE *MUST* LET GO OF ALL LOCKS BEFORE CALLING RECEIVE BUF !!! */
+ spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
+
+ jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
+ "jsm_input. %d not real_raw len:%d calling receive_buf for board %d\n",
+ __LINE__, len, ch->ch_bd->boardnum);
+
+ tp->ldisc.receive_buf(tp, tp->flip.char_buf, tp->flip.flag_buf, len);
+ }
+ } else {
+ ch->ch_r_tail = tail & rmask;
+ ch->ch_e_tail = tail & rmask;
+
+ jsm_check_queue_flow_control(ch);
+
+ spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
+
+ jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
+ "jsm_input. %d not jsm_read raw okay scheduling flip\n", __LINE__);
+ tty_schedule_flip(tp);
+ }
+
+ jsm_printk(IOCTL, INFO, &ch->ch_bd->pci_dev, "finish\n");
+}
+
+void jsm_carrier(struct jsm_channel *ch)
+{
+ struct jsm_board *bd;
+
+ int virt_carrier = 0;
+ int phys_carrier = 0;
+
+ jsm_printk(CARR, INFO, &ch->ch_bd->pci_dev, "start\n");
+ if (!ch)
+ return;
+
+ bd = ch->ch_bd;
+
+ if (!bd)
+ return;
+
+ if (ch->ch_mistat & UART_MSR_DCD) {
+ jsm_printk(CARR, INFO, &ch->ch_bd->pci_dev,
+ "mistat: %x D_CD: %x\n", ch->ch_mistat, ch->ch_mistat & UART_MSR_DCD);
+ phys_carrier = 1;
+ }
+
+ if (ch->ch_c_cflag & CLOCAL)
+ virt_carrier = 1;
+
+ jsm_printk(CARR, INFO, &ch->ch_bd->pci_dev,
+ "DCD: physical: %d virt: %d\n", phys_carrier, virt_carrier);
+
+ /*
+ * Test for a VIRTUAL carrier transition to HIGH.
+ */
+ if (((ch->ch_flags & CH_FCAR) == 0) && (virt_carrier == 1)) {
+
+ /*
+ * When carrier rises, wake any threads waiting
+ * for carrier in the open routine.
+ */
+
+ jsm_printk(CARR, INFO, &ch->ch_bd->pci_dev,
+ "carrier: virt DCD rose\n");
+
+ if (waitqueue_active(&(ch->ch_flags_wait)))
+ wake_up_interruptible(&ch->ch_flags_wait);
+ }
+
+ /*
+ * Test for a PHYSICAL carrier transition to HIGH.
+ */
+ if (((ch->ch_flags & CH_CD) == 0) && (phys_carrier == 1)) {
+
+ /*
+ * When carrier rises, wake any threads waiting
+ * for carrier in the open routine.
+ */
+
+ jsm_printk(CARR, INFO, &ch->ch_bd->pci_dev,
+ "carrier: physical DCD rose\n");
+
+ if (waitqueue_active(&(ch->ch_flags_wait)))
+ wake_up_interruptible(&ch->ch_flags_wait);
+ }
+
+ /*
+ * Test for a PHYSICAL transition to low, so long as we aren't
+ * currently ignoring physical transitions (which is what "virtual
+ * carrier" indicates).
+ *
+ * The transition of the virtual carrier to low really doesn't
+ * matter... it really only means "ignore carrier state", not
+ * "make pretend that carrier is there".
+ */
+ if ((virt_carrier == 0) && ((ch->ch_flags & CH_CD) != 0)
+ && (phys_carrier == 0)) {
+ /*
+ * When carrier drops:
+ *
+ * Drop carrier on all open units.
+ *
+ * Flush queues, waking up any task waiting in the
+ * line discipline.
+ *
+ * Send a hangup to the control terminal.
+ *
+ * Enable all select calls.
+ */
+ if (waitqueue_active(&(ch->ch_flags_wait)))
+ wake_up_interruptible(&ch->ch_flags_wait);
+ }
+
+ /*
+ * Make sure that our cached values reflect the current reality.
+ */
+ if (virt_carrier == 1)
+ ch->ch_flags |= CH_FCAR;
+ else
+ ch->ch_flags &= ~CH_FCAR;
+
+ if (phys_carrier == 1)
+ ch->ch_flags |= CH_CD;
+ else
+ ch->ch_flags &= ~CH_CD;
+}
+
+
+void jsm_check_queue_flow_control(struct jsm_channel *ch)
+{
+ int qleft = 0;
+
+ /* Store how much space we have left in the queue */
+ if ((qleft = ch->ch_r_tail - ch->ch_r_head - 1) < 0)
+ qleft += RQUEUEMASK + 1;
+
+ /*
+ * Check to see if we should enforce flow control on our queue because
+ * the ld (or user) isn't reading data out of our queue fast enuf.
+ *
+ * NOTE: This is done based on what the current flow control of the
+ * port is set for.
+ *
+ * 1) HWFLOW (RTS) - Turn off the UART's Receive interrupt.
+ * This will cause the UART's FIFO to back up, and force
+ * the RTS signal to be dropped.
+ * 2) SWFLOW (IXOFF) - Keep trying to send a stop character to
+ * the other side, in hopes it will stop sending data to us.
+ * 3) NONE - Nothing we can do. We will simply drop any extra data
+ * that gets sent into us when the queue fills up.
+ */
+ if (qleft < 256) {
+ /* HWFLOW */
+ if (ch->ch_c_cflag & CRTSCTS) {
+ if(!(ch->ch_flags & CH_RECEIVER_OFF)) {
+ ch->ch_bd->bd_ops->disable_receiver(ch);
+ ch->ch_flags |= (CH_RECEIVER_OFF);
+ jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
+ "Internal queue hit hilevel mark (%d)! Turning off interrupts.\n",
+ qleft);
+ }
+ }
+ /* SWFLOW */
+ else if (ch->ch_c_iflag & IXOFF) {
+ if (ch->ch_stops_sent <= MAX_STOPS_SENT) {
+ ch->ch_bd->bd_ops->send_stop_character(ch);
+ ch->ch_stops_sent++;
+ jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
+ "Sending stop char! Times sent: %x\n", ch->ch_stops_sent);
+ }
+ }
+ }
+
+ /*
+ * Check to see if we should unenforce flow control because
+ * ld (or user) finally read enuf data out of our queue.
+ *
+ * NOTE: This is done based on what the current flow control of the
+ * port is set for.
+ *
+ * 1) HWFLOW (RTS) - Turn back on the UART's Receive interrupt.
+ * This will cause the UART's FIFO to raise RTS back up,
+ * which will allow the other side to start sending data again.
+ * 2) SWFLOW (IXOFF) - Send a start character to
+ * the other side, so it will start sending data to us again.
+ * 3) NONE - Do nothing. Since we didn't do anything to turn off the
+ * other side, we don't need to do anything now.
+ */
+ if (qleft > (RQUEUESIZE / 2)) {
+ /* HWFLOW */
+ if (ch->ch_c_cflag & CRTSCTS) {
+ if (ch->ch_flags & CH_RECEIVER_OFF) {
+ ch->ch_bd->bd_ops->enable_receiver(ch);
+ ch->ch_flags &= ~(CH_RECEIVER_OFF);
+ jsm_printk(READ, INFO, &ch->ch_bd->pci_dev,
+ "Internal queue hit lowlevel mark (%d)! Turning on interrupts.\n",
+ qleft);
+ }
+ }
+ /* SWFLOW */
+ else if (ch->ch_c_iflag & IXOFF && ch->ch_stops_sent) {
+ ch->ch_stops_sent = 0;
+ ch->ch_bd->bd_ops->send_start_character(ch);
+ jsm_printk(READ, INFO, &ch->ch_bd->pci_dev, "Sending start char!\n");
+ }
+ }
+}
+
+/*
+ * jsm_tty_write()
+ *
+ * Take data from the user or kernel and send it out to the FEP.
+ * In here exists all the Transparent Print magic as well.
+ */
+int jsm_tty_write(struct uart_port *port)
+{
+ int bufcount = 0, n = 0;
+ int data_count = 0,data_count1 =0;
+ u16 head;
+ u16 tail;
+ u16 tmask;
+ u32 remain;
+ int temp_tail = port->info->xmit.tail;
+ struct jsm_channel *channel = (struct jsm_channel *)port;
+
+ tmask = WQUEUEMASK;
+ head = (channel->ch_w_head) & tmask;
+ tail = (channel->ch_w_tail) & tmask;
+
+ if ((bufcount = tail - head - 1) < 0)
+ bufcount += WQUEUESIZE;
+
+ n = bufcount;
+
+ n = min(n, 56);
+ remain = WQUEUESIZE - head;
+
+ data_count = 0;
+ if (n >= remain) {
+ n -= remain;
+ while ((port->info->xmit.head != temp_tail) &&
+ (data_count < remain)) {
+ channel->ch_wqueue[head++] =
+ port->info->xmit.buf[temp_tail];
+
+ temp_tail++;
+ temp_tail &= (UART_XMIT_SIZE - 1);
+ data_count++;
+ }
+ if (data_count == remain) head = 0;
+ }
+
+ data_count1 = 0;
+ if (n > 0) {
+ remain = n;
+ while ((port->info->xmit.head != temp_tail) &&
+ (data_count1 < remain)) {
+ channel->ch_wqueue[head++] =
+ port->info->xmit.buf[temp_tail];
+
+ temp_tail++;
+ temp_tail &= (UART_XMIT_SIZE - 1);
+ data_count1++;
+
+ }
+ }
+
+ port->info->xmit.tail = temp_tail;
+
+ data_count += data_count1;
+ if (data_count) {
+ head &= tmask;
+ channel->ch_w_head = head;
+ }
+
+ if (data_count) {
+ channel->ch_bd->bd_ops->copy_data_from_queue_to_uart(channel);
+ }
+
+ return data_count;
+}
+
+static ssize_t jsm_driver_version_show(struct device_driver *ddp, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%s\n", JSM_VERSION);
+}
+static DRIVER_ATTR(version, S_IRUSR, jsm_driver_version_show, NULL);
+
+static ssize_t jsm_driver_state_show(struct device_driver *ddp, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%s\n", jsm_driver_state_text[jsm_driver_state]);
+}
+static DRIVER_ATTR(state, S_IRUSR, jsm_driver_state_show, NULL);
+
+void jsm_create_driver_sysfiles(struct device_driver *driverfs)
+{
+ driver_create_file(driverfs, &driver_attr_version);
+ driver_create_file(driverfs, &driver_attr_state);
+}
+
+void jsm_remove_driver_sysfiles(struct device_driver *driverfs)
+{
+ driver_remove_file(driverfs, &driver_attr_version);
+ driver_remove_file(driverfs, &driver_attr_state);
+}
diff --git a/drivers/serial/m32r_sio.c b/drivers/serial/m32r_sio.c
index 380c29539952b..bb6509f5fe8bb 100644
--- a/drivers/serial/m32r_sio.c
+++ b/drivers/serial/m32r_sio.c
@@ -26,6 +26,11 @@
* serial.c driver, and is currently the preferred form.
*/
#include <linux/config.h>
+
+#if defined(CONFIG_SERIAL_M32R_SIO_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
+
#include <linux/module.h>
#include <linux/tty.h>
#include <linux/ioport.h>
@@ -40,12 +45,8 @@
#include <asm/io.h>
#include <asm/irq.h>
-#if defined(CONFIG_SERIAL_M32R_SIO_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#define PORT_SIO 1
-#define PORT_MAX_SIO 1
+#define PORT_M32R_BASE PORT_M32R_SIO
+#define PORT_INDEX(x) (x - PORT_M32R_BASE + 1)
#define BAUD_RATE 115200
#include <linux/serial_core.h>
@@ -83,44 +84,20 @@ unsigned int share_irqs_sio = M32R_SIO_SHARE_IRQS;
*/
#define is_real_interrupt(irq) ((irq) != 0)
-/*
- * This converts from our new CONFIG_ symbols to the symbols
- * that asm/serial.h expects. You _NEED_ to comment out the
- * linux/config.h include contained inside asm/serial.h for
- * this to work.
- */
-#undef CONFIG_SERIAL_MANY_PORTS
-#undef CONFIG_SERIAL_DETECT_IRQ
-#undef CONFIG_SERIAL_MULTIPORT
-#undef CONFIG_HUB6
-
-#ifdef CONFIG_SERIAL_M32R_SIO_DETECT_IRQ
-#define CONFIG_SERIAL_DETECT_IRQ 1
-#endif
-#ifdef CONFIG_SERIAL_M32R_SIO_MULTIPORT
-#define CONFIG_SERIAL_MULTIPORT 1
-#endif
-#ifdef CONFIG_SERIAL_M32R_SIO_MANY_PORTS
-#define CONFIG_SERIAL_MANY_PORTS 1
-#endif
+#include <asm/serial.h>
/*
- * HUB6 is always on. This will be removed once the header
- * files have been cleaned.
+ * SERIAL_PORT_DFNS tells us about built-in ports that have no
+ * standard enumeration mechanism. Platforms that can find all
+ * serial ports via mechanisms like ACPI or PCI need not supply it.
*/
-#define CONFIG_HUB6 1
-
-#include <asm/serial.h>
+#ifndef SERIAL_PORT_DFNS
+#define SERIAL_PORT_DFNS
+#endif
-#ifdef CONFIG_SERIAL_M32R_PLDSIO
static struct old_serial_port old_serial_port[] = {
- { 0, BASE_BAUD, ((unsigned long)PLD_ESIO0CR), PLD_IRQ_SIO0_RCV, STD_COM_FLAGS },
+ SERIAL_PORT_DFNS /* defined in asm/serial.h */
};
-#else
-static struct old_serial_port old_serial_port[] = {
- { 0, BASE_BAUD, M32R_SIO_OFFSET, M32R_IRQ_SIO0_R, STD_COM_FLAGS },
-};
-#endif
#define UART_NR ARRAY_SIZE(old_serial_port)
@@ -153,9 +130,17 @@ static struct irq_info irq_lists[NR_IRQS];
/*
* Here we define the default xmit fifo size used for each type of UART.
*/
-static const struct serial_uart_config uart_config[PORT_MAX_SIO+1] = {
- { "unknown", 1, 0 },
- { "M32RSIO", 1, 0 }
+static const struct serial_uart_config uart_config[] = {
+ [PORT_UNKNOWN] = {
+ .name = "unknown",
+ .dfl_xmit_fifo_size = 1,
+ .flags = 0,
+ },
+ [PORT_INDEX(PORT_M32R_SIO)] = {
+ .name = "M32RSIO",
+ .dfl_xmit_fifo_size = 1,
+ .flags = 0,
+ },
};
#ifdef CONFIG_SERIAL_M32R_PLDSIO
@@ -460,7 +445,6 @@ static inline void m32r_sio_handle_port(struct uart_sio_port *up,
if (status & 0x04)
receive_chars(up, &status, regs);
- // check_modem_status(up);
if (status & 0x01)
transmit_chars(up);
}
@@ -842,13 +826,12 @@ m32r_sio_request_std_resource(struct uart_sio_port *up, struct resource **res)
int ret = 0;
switch (up->port.iotype) {
- case SERIAL_IO_MEM:
+ case UPIO_MEM:
if (up->port.mapbase) {
#ifdef CONFIG_SERIAL_M32R_PLDSIO
*res = request_mem_region(up->port.mapbase, size, "serial");
#else
start = up->port.mapbase;
- start += UART_RSA_BASE << up->port.regshift;
*res = request_mem_region(start, size, "serial");
#endif
if (!*res)
@@ -856,8 +839,7 @@ m32r_sio_request_std_resource(struct uart_sio_port *up, struct resource **res)
}
break;
- case SERIAL_IO_HUB6:
- case SERIAL_IO_PORT:
+ case UPIO_PORT:
*res = request_region(up->port.iobase, size, "serial");
if (!*res)
ret = -EBUSY;
@@ -866,55 +848,15 @@ m32r_sio_request_std_resource(struct uart_sio_port *up, struct resource **res)
return ret;
}
-static int
-m32r_sio_request_rsa_resource(struct uart_sio_port *up, struct resource **res)
-{
- unsigned int size = 8 << up->port.regshift;
- unsigned long start;
- int ret = 0;
-
- switch (up->port.iotype) {
- case SERIAL_IO_MEM:
- if (up->port.mapbase) {
- start = up->port.mapbase;
- start += UART_RSA_BASE << up->port.regshift;
-#ifdef CONFIG_SERIAL_M32R_PLDSIO
- *res = request_mem_region(start, size, "serial-rsa");
-#else
- *res = request_mem_region(up->port.mapbase, size, "serial-rsa");
-#endif
- if (!*res)
- ret = -EBUSY;
- }
- break;
-
- case SERIAL_IO_HUB6:
- case SERIAL_IO_PORT:
- start = up->port.iobase;
- start += UART_RSA_BASE << up->port.regshift;
- *res = request_region(up->port.iobase, size, "serial-rsa");
- if (!*res)
- ret = -EBUSY;
- break;
- }
-
- return ret;
-}
-
static void m32r_sio_release_port(struct uart_port *port)
{
struct uart_sio_port *up = (struct uart_sio_port *)port;
unsigned long start, offset = 0, size = 0;
- if (up->port.type == PORT_RSA) {
- offset = UART_RSA_BASE << up->port.regshift;
- size = 8;
- }
-
size <<= up->port.regshift;
switch (up->port.iotype) {
- case SERIAL_IO_MEM:
+ case UPIO_MEM:
if (up->port.mapbase) {
/*
* Unmap the area.
@@ -930,8 +872,7 @@ static void m32r_sio_release_port(struct uart_port *port)
}
break;
- case SERIAL_IO_HUB6:
- case SERIAL_IO_PORT:
+ case UPIO_PORT:
start = up->port.iobase;
if (size)
@@ -947,14 +888,9 @@ static void m32r_sio_release_port(struct uart_port *port)
static int m32r_sio_request_port(struct uart_port *port)
{
struct uart_sio_port *up = (struct uart_sio_port *)port;
- struct resource *res = NULL, *res_rsa = NULL;
+ struct resource *res = NULL;
int ret = 0;
- if (up->port.type == PORT_RSA){
- ret = m32r_sio_request_rsa_resource(up, &res_rsa);
- if (ret < 0)
- return ret;
- }
ret = m32r_sio_request_std_resource(up, &res);
/*
@@ -969,11 +905,10 @@ static int m32r_sio_request_port(struct uart_port *port)
}
if (ret < 0) {
- if (res_rsa)
- release_resource(res_rsa);
if (res)
release_resource(res);
}
+
return ret;
}
@@ -983,7 +918,7 @@ static void m32r_sio_config_port(struct uart_port *port, int flags)
spin_lock_irqsave(&up->port.lock, flags);
- up->port.type = PORT_SIO;
+ up->port.type = (PORT_M32R_SIO - PORT_M32R_BASE + 1);
up->port.fifosize = uart_config[up->port.type].dfl_xmit_fifo_size;
spin_unlock_irqrestore(&up->port.lock, flags);
@@ -994,8 +929,7 @@ m32r_sio_verify_port(struct uart_port *port, struct serial_struct *ser)
{
if (ser->irq >= NR_IRQS || ser->irq < 0 ||
ser->baud_base < 9600 || ser->type < PORT_UNKNOWN ||
- ser->type > PORT_MAX_SIO || ser->type == PORT_CIRRUS ||
- ser->type == PORT_STARTECH)
+ ser->type >= ARRAY_SIZE(uart_config))
return -EINVAL;
return 0;
}
@@ -1048,7 +982,6 @@ static void __init m32r_sio_isa_init_ports(void)
up->port.irq = irq_canonicalize(old_serial_port[i].irq);
up->port.uartclk = old_serial_port[i].baud_base * 16;
up->port.flags = old_serial_port[i].flags;
- up->port.hub6 = old_serial_port[i].hub6;
up->port.membase = old_serial_port[i].iomem_base;
up->port.iotype = old_serial_port[i].io_type;
up->port.regshift = old_serial_port[i].iomem_reg_shift;
@@ -1255,7 +1188,7 @@ static int __register_m32r_sio(struct serial_struct *req, int line)
}
/**
- * register_serial - configure a 16x50 serial port at runtime
+ * register_m32r_sio - configure a 16x50 serial port at runtime
* @req: request structure
*
* Configure the serial port specified by the request. If the
@@ -1272,7 +1205,7 @@ int register_m32r_sio(struct serial_struct *req)
return __register_m32r_sio(req, -1);
}
-int __init early_m32r_sio_setup(struct uart_port *port)
+int __init early_serial_setup(struct uart_port *port)
{
m32r_sio_isa_init_ports();
m32r_sio_ports[port->line].port = *port;
@@ -1282,7 +1215,7 @@ int __init early_m32r_sio_setup(struct uart_port *port)
}
/**
- * unregister_serial - remove a 16x50 serial port at runtime
+ * unregister_m32r_sio - remove a 16x50 serial port at runtime
* @line: serial line number
*
* Remove one serial port. This may be called from interrupt
@@ -1293,20 +1226,6 @@ void unregister_m32r_sio(int line)
uart_unregister_port(&m32r_sio_reg, line);
}
-/*
- * This is for ISAPNP only.
- */
-void m32r_sio_get_irq_map(unsigned int *map)
-{
- int i;
-
- for (i = 0; i < UART_NR; i++) {
- if (m32r_sio_ports[i].port.type != PORT_UNKNOWN &&
- m32r_sio_ports[i].port.irq < 16)
- *map |= 1 << m32r_sio_ports[i].port.irq;
- }
-}
-
/**
* m32r_sio_suspend_port - suspend one serial port
* @line: serial line number
@@ -1361,7 +1280,6 @@ module_exit(m32r_sio_exit);
EXPORT_SYMBOL(register_m32r_sio);
EXPORT_SYMBOL(unregister_m32r_sio);
-EXPORT_SYMBOL(m32r_sio_get_irq_map);
EXPORT_SYMBOL(m32r_sio_suspend_port);
EXPORT_SYMBOL(m32r_sio_resume_port);
diff --git a/drivers/serial/m32r_sio.h b/drivers/serial/m32r_sio.h
index f957c76f42321..07d0dd80aa3dd 100644
--- a/drivers/serial/m32r_sio.h
+++ b/drivers/serial/m32r_sio.h
@@ -36,7 +36,6 @@ struct old_serial_port {
unsigned int port;
unsigned int irq;
unsigned int flags;
- unsigned char hub6;
unsigned char io_type;
unsigned char *iomem_base;
unsigned short iomem_reg_shift;
diff --git a/drivers/serial/m32r_sio_reg.h b/drivers/serial/m32r_sio_reg.h
index d94025568ebd5..9c864529451b1 100644
--- a/drivers/serial/m32r_sio_reg.h
+++ b/drivers/serial/m32r_sio_reg.h
@@ -104,31 +104,6 @@
#define UART_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
/*
- * These are the definitions for the FIFO Control Register
- * (16650 only)
- */
-#define UART_FCR_ENABLE_FIFO 0x01 /* Enable the FIFO */
-#define UART_FCR_CLEAR_RCVR 0x02 /* Clear the RCVR FIFO */
-#define UART_FCR_CLEAR_XMIT 0x04 /* Clear the XMIT FIFO */
-#define UART_FCR_DMA_SELECT 0x08 /* For DMA applications */
-#define UART_FCR_TRIGGER_MASK 0xC0 /* Mask for the FIFO trigger range */
-#define UART_FCR_TRIGGER_1 0x00 /* Mask for trigger set at 1 */
-#define UART_FCR_TRIGGER_4 0x40 /* Mask for trigger set at 4 */
-#define UART_FCR_TRIGGER_8 0x80 /* Mask for trigger set at 8 */
-#define UART_FCR_TRIGGER_14 0xC0 /* Mask for trigger set at 14 */
-/* 16650 redefinitions */
-#define UART_FCR6_R_TRIGGER_8 0x00 /* Mask for receive trigger set at 1 */
-#define UART_FCR6_R_TRIGGER_16 0x40 /* Mask for receive trigger set at 4 */
-#define UART_FCR6_R_TRIGGER_24 0x80 /* Mask for receive trigger set at 8 */
-#define UART_FCR6_R_TRIGGER_28 0xC0 /* Mask for receive trigger set at 14 */
-#define UART_FCR6_T_TRIGGER_16 0x00 /* Mask for transmit trigger set at 16 */
-#define UART_FCR6_T_TRIGGER_8 0x10 /* Mask for transmit trigger set at 8 */
-#define UART_FCR6_T_TRIGGER_24 0x20 /* Mask for transmit trigger set at 24 */
-#define UART_FCR6_T_TRIGGER_30 0x30 /* Mask for transmit trigger set at 30 */
-/* TI 16750 definitions */
-#define UART_FCR7_64BYTE 0x20 /* Go into 64 byte mode */
-
-/*
* These are the definitions for the Line Control Register
*
* Note: if the word length is 5 bits (UART_LCR_WLEN5), then setting
@@ -174,170 +149,5 @@
#define UART_IER_RLSI 0x08 /* Enable receiver line status interrupt */
#define UART_IER_THRI 0x03 /* Enable Transmitter holding register int. */
#define UART_IER_RDI 0x04 /* Enable receiver data interrupt */
-/*
- * Sleep mode for ST16650 and TI16750.
- * Note that for 16650, EFR-bit 4 must be selected as well.
- */
-#define UART_IERX_SLEEP 0x10 /* Enable sleep mode */
-
-/*
- * These are the definitions for the Modem Control Register
- */
-#define UART_MCR_LOOP 0x10 /* Enable loopback test mode */
-#define UART_MCR_OUT2 0x08 /* Out2 complement */
-#define UART_MCR_OUT1 0x04 /* Out1 complement */
-#define UART_MCR_RTS 0x02 /* RTS complement */
-#define UART_MCR_DTR 0x01 /* DTR complement */
-
-/*
- * These are the definitions for the Modem Status Register
- */
-#define UART_MSR_DCD 0x80 /* Data Carrier Detect */
-#define UART_MSR_RI 0x40 /* Ring Indicator */
-#define UART_MSR_DSR 0x20 /* Data Set Ready */
-#define UART_MSR_CTS 0x10 /* Clear to Send */
-#define UART_MSR_DDCD 0x08 /* Delta DCD */
-#define UART_MSR_TERI 0x04 /* Trailing edge ring indicator */
-#define UART_MSR_DDSR 0x02 /* Delta DSR */
-#define UART_MSR_DCTS 0x01 /* Delta CTS */
-#define UART_MSR_ANY_DELTA 0x0F /* Any of the delta bits! */
-
-/*
- * These are the definitions for the Extended Features Register
- * (StarTech 16C660 only, when DLAB=1)
- */
-#define UART_EFR_CTS 0x80 /* CTS flow control */
-#define UART_EFR_RTS 0x40 /* RTS flow control */
-#define UART_EFR_SCD 0x20 /* Special character detect */
-#define UART_EFR_ECB 0x10 /* Enhanced control bit */
-/*
- * the low four bits control software flow control
- */
-
-/*
- * These register definitions are for the 16C950
- */
-#define UART_ASR 0x01 /* Additional Status Register */
-#define UART_RFL 0x03 /* Receiver FIFO level */
-#define UART_TFL 0x04 /* Transmitter FIFO level */
-#define UART_ICR 0x05 /* Index Control Register */
-
-/* The 16950 ICR registers */
-#define UART_ACR 0x00 /* Additional Control Register */
-#define UART_CPR 0x01 /* Clock Prescalar Register */
-#define UART_TCR 0x02 /* Times Clock Register */
-#define UART_CKS 0x03 /* Clock Select Register */
-#define UART_TTL 0x04 /* Transmitter Interrupt Trigger Level */
-#define UART_RTL 0x05 /* Receiver Interrupt Trigger Level */
-#define UART_FCL 0x06 /* Flow Control Level Lower */
-#define UART_FCH 0x07 /* Flow Control Level Higher */
-#define UART_ID1 0x08 /* ID #1 */
-#define UART_ID2 0x09 /* ID #2 */
-#define UART_ID3 0x0A /* ID #3 */
-#define UART_REV 0x0B /* Revision */
-#define UART_CSR 0x0C /* Channel Software Reset */
-#define UART_NMR 0x0D /* Nine-bit Mode Register */
-#define UART_CTR 0xFF
-
-/*
- * The 16C950 Additional Control Reigster
- */
-#define UART_ACR_RXDIS 0x01 /* Receiver disable */
-#define UART_ACR_TXDIS 0x02 /* Receiver disable */
-#define UART_ACR_DSRFC 0x04 /* DSR Flow Control */
-#define UART_ACR_TLENB 0x20 /* 950 trigger levels enable */
-#define UART_ACR_ICRRD 0x40 /* ICR Read enable */
-#define UART_ACR_ASREN 0x80 /* Additional status enable */
-
-/*
- * These are the definitions for the Feature Control Register
- * (XR16C85x only, when LCR=bf; doubles with the Interrupt Enable
- * Register, UART register #1)
- */
-#define UART_FCTR_RTS_NODELAY 0x00 /* RTS flow control delay */
-#define UART_FCTR_RTS_4DELAY 0x01
-#define UART_FCTR_RTS_6DELAY 0x02
-#define UART_FCTR_RTS_8DELAY 0x03
-#define UART_FCTR_IRDA 0x04 /* IrDa data encode select */
-#define UART_FCTR_TX_INT 0x08 /* Tx interrupt type select */
-#define UART_FCTR_TRGA 0x00 /* Tx/Rx 550 trigger table select */
-#define UART_FCTR_TRGB 0x10 /* Tx/Rx 650 trigger table select */
-#define UART_FCTR_TRGC 0x20 /* Tx/Rx 654 trigger table select */
-#define UART_FCTR_TRGD 0x30 /* Tx/Rx 850 programmable trigger select */
-#define UART_FCTR_SCR_SWAP 0x40 /* Scratch pad register swap */
-#define UART_FCTR_RX 0x00 /* Programmable trigger mode select */
-#define UART_FCTR_TX 0x80 /* Programmable trigger mode select */
-
-/*
- * These are the definitions for the Enhanced Mode Select Register
- * (XR16C85x only, when LCR=bf and FCTR bit 6=1; doubles with the
- * Scratch register, UART register #7)
- */
-#define UART_EMSR_FIFO_COUNT 0x01 /* Rx/Tx select */
-#define UART_EMSR_ALT_COUNT 0x02 /* Alternating count select */
-
-/*
- * These are the definitions for the Programmable Trigger
- * Register (XR16C85x only, when LCR=bf; doubles with the UART RX/TX
- * register, UART register #0)
- */
-#define UART_TRG_1 0x01
-#define UART_TRG_4 0x04
-#define UART_TRG_8 0x08
-#define UART_TRG_16 0x10
-#define UART_TRG_32 0x20
-#define UART_TRG_64 0x40
-#define UART_TRG_96 0x60
-#define UART_TRG_120 0x78
-#define UART_TRG_128 0x80
-
-/*
- * These definitions are for the RSA-DV II/S card, from
- *
- * Kiyokazu SUTO <suto@ks-and-ks.ne.jp>
- */
-
-#define UART_RSA_BASE (-8)
-
-#define UART_RSA_MSR ((UART_RSA_BASE) + 0) /* I/O: Mode Select Register */
-
-#define UART_RSA_MSR_SWAP (1 << 0) /* Swap low/high 8 bytes in I/O port addr */
-#define UART_RSA_MSR_FIFO (1 << 2) /* Enable the external FIFO */
-#define UART_RSA_MSR_FLOW (1 << 3) /* Enable the auto RTS/CTS flow control */
-#define UART_RSA_MSR_ITYP (1 << 4) /* Level (1) / Edge triger (0) */
-
-#define UART_RSA_IER ((UART_RSA_BASE) + 1) /* I/O: Interrupt Enable Register */
-
-#define UART_RSA_IER_Rx_FIFO_H (1 << 0) /* Enable Rx FIFO half full int. */
-#define UART_RSA_IER_Tx_FIFO_H (1 << 1) /* Enable Tx FIFO half full int. */
-#define UART_RSA_IER_Tx_FIFO_E (1 << 2) /* Enable Tx FIFO empty int. */
-#define UART_RSA_IER_Rx_TOUT (1 << 3) /* Enable char receive timeout int */
-#define UART_RSA_IER_TIMER (1 << 4) /* Enable timer interrupt */
-
-#define UART_RSA_SRR ((UART_RSA_BASE) + 2) /* IN: Status Read Register */
-
-#define UART_RSA_SRR_Tx_FIFO_NEMP (1 << 0) /* Tx FIFO is not empty (1) */
-#define UART_RSA_SRR_Tx_FIFO_NHFL (1 << 1) /* Tx FIFO is not half full (1) */
-#define UART_RSA_SRR_Tx_FIFO_NFUL (1 << 2) /* Tx FIFO is not full (1) */
-#define UART_RSA_SRR_Rx_FIFO_NEMP (1 << 3) /* Rx FIFO is not empty (1) */
-#define UART_RSA_SRR_Rx_FIFO_NHFL (1 << 4) /* Rx FIFO is not half full (1) */
-#define UART_RSA_SRR_Rx_FIFO_NFUL (1 << 5) /* Rx FIFO is not full (1) */
-#define UART_RSA_SRR_Rx_TOUT (1 << 6) /* Character reception timeout occurred (1) */
-#define UART_RSA_SRR_TIMER (1 << 7) /* Timer interrupt occurred */
-
-#define UART_RSA_FRR ((UART_RSA_BASE) + 2) /* OUT: FIFO Reset Register */
-
-#define UART_RSA_TIVSR ((UART_RSA_BASE) + 3) /* I/O: Timer Interval Value Set Register */
-
-#define UART_RSA_TCR ((UART_RSA_BASE) + 4) /* OUT: Timer Control Register */
-
-#define UART_RSA_TCR_SWITCH (1 << 0) /* Timer on */
-
-/*
- * The RSA DSV/II board has two fixed clock frequencies. One is the
- * standard rate, and the other is 8 times faster.
- */
-#define SERIAL_RSA_BAUD_BASE (921600)
-#define SERIAL_RSA_BAUD_BASE_LO (SERIAL_RSA_BAUD_BASE / 8)
#endif /* _M32R_SIO_REG_H */
diff --git a/drivers/serial/mcfserial.c b/drivers/serial/mcfserial.c
index d40f69c117e3c..8c40167778dea 100644
--- a/drivers/serial/mcfserial.c
+++ b/drivers/serial/mcfserial.c
@@ -138,18 +138,6 @@ extern int magic_sysrq_key(int ch);
/*
- * tmp_buf is used as a temporary buffer by serial_write. We need to
- * lock it in case the copy_from_user blocks while swapping in a page,
- * and some other program tries to do a serial write at the same time.
- * Since the lock will only come under contention when the system is
- * swapping and available memory is low, it makes sense to share one
- * buffer across all the serial ports, since it significantly saves
- * memory if large numbers of serial ports are open.
- */
-static unsigned char mcfrs_tmp_buf[4096]; /* This is cheating */
-static DECLARE_MUTEX(mcfrs_tmp_buf_sem);
-
-/*
* Forware declarations...
*/
static void mcfrs_change_speed(struct mcf_serial *info);
@@ -1092,23 +1080,19 @@ static int mcfrs_ioctl(struct tty_struct *tty, struct file * file,
(arg ? CLOCAL : 0));
return 0;
case TIOCGSERIAL:
- error = verify_area(VERIFY_WRITE, (void *) arg,
- sizeof(struct serial_struct));
- if (error)
- return error;
- return get_serial_info(info,
+ if (access_ok(VERIFY_WRITE, (void *) arg,
+ sizeof(struct serial_struct)))
+ return get_serial_info(info,
(struct serial_struct *) arg);
+ return -EFAULT;
case TIOCSSERIAL:
return set_serial_info(info,
(struct serial_struct *) arg);
case TIOCSERGETLSR: /* Get line status register */
- error = verify_area(VERIFY_WRITE, (void *) arg,
- sizeof(unsigned int));
- if (error)
- return error;
- else
- return get_lsr_info(info, (unsigned int *) arg);
-
+ if (access_ok(VERIFY_WRITE, (void *) arg,
+ sizeof(unsigned int)))
+ return get_lsr_info(info, (unsigned int *) arg);
+ return -EFAULT;
case TIOCSERGSTRUCT:
error = copy_to_user((struct mcf_serial *) arg,
info, sizeof(struct mcf_serial));
diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c
index 900f7bb51de92..2a5cf174ca30d 100644
--- a/drivers/serial/mpc52xx_uart.c
+++ b/drivers/serial/mpc52xx_uart.c
@@ -18,7 +18,7 @@
* Some of the code has been inspired/copied from the 2.4 code written
* by Dale Farnsworth <dfarnsworth@mvista.com>.
*
- * Copyright (C) 2004 Sylvain Munaut <tnt@246tNt.com>
+ * Copyright (C) 2004-2005 Sylvain Munaut <tnt@246tNt.com>
* Copyright (C) 2003 MontaVista, Software, Inc.
*
* This file is licensed under the terms of the GNU General Public License
@@ -26,33 +26,26 @@
* kind, whether express or implied.
*/
-/* OCP Usage :
+/* Platform device Usage :
*
- * This drivers uses the OCP model. To load the serial driver for one of the
- * PSCs, just add this to the core_ocp table :
+ * Since PSCs can have multiple function, the correct driver for each one
+ * is selected by calling mpc52xx_match_psc_function(...). The function
+ * handled by this driver is "uart".
*
- * {
- * .vendor = OCP_VENDOR_FREESCALE,
- * .function = OCP_FUNC_PSC_UART,
- * .index = 0,
- * .paddr = MPC52xx_PSC1,
- * .irq = MPC52xx_PSC1_IRQ,
- * .pm = OCP_CPM_NA,
- * },
- *
- * This is for PSC1, replace the paddr and irq according to the PSC you want to
- * use. The driver all necessary registers to place the PSC in uart mode without
+ * The driver init all necessary registers to place the PSC in uart mode without
* DCD. However, the pin multiplexing aren't changed and should be set either
* by the bootloader or in the platform init code.
- * The index field must be equal to the PSC index ( e.g. 0 for PSC1, 1 for PSC2,
+ *
+ * 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 because OCP stuff is not yet initialized.
+ * mapped to.
*/
#include <linux/config.h>
+#include <linux/device.h>
#include <linux/module.h>
#include <linux/tty.h>
#include <linux/serial.h>
@@ -61,7 +54,6 @@
#include <asm/delay.h>
#include <asm/io.h>
-#include <asm/ocp.h>
#include <asm/mpc52xx.h>
#include <asm/mpc52xx_psc.h>
@@ -86,7 +78,7 @@ static struct uart_port mpc52xx_uart_ports[MPC52xx_PSC_MAXNUM];
* the console_init
*/
-#define PSC(port) ((struct mpc52xx_psc *)((port)->membase))
+#define PSC(port) ((struct mpc52xx_psc __iomem *)((port)->membase))
/* Forward declaration of the interruption handling routine */
@@ -190,7 +182,14 @@ mpc52xx_uart_break_ctl(struct uart_port *port, int ctl)
static int
mpc52xx_uart_startup(struct uart_port *port)
{
- struct mpc52xx_psc *psc = PSC(port);
+ struct mpc52xx_psc __iomem *psc = PSC(port);
+ int ret;
+
+ /* Request IRQ */
+ ret = request_irq(port->irq, mpc52xx_uart_int,
+ SA_INTERRUPT | SA_SAMPLE_RANDOM, "mpc52xx_psc_uart", port);
+ if (ret)
+ return ret;
/* Reset/activate the port, clear and enable interrupts */
out_8(&psc->command,MPC52xx_PSC_RST_RX);
@@ -217,7 +216,7 @@ mpc52xx_uart_startup(struct uart_port *port)
static void
mpc52xx_uart_shutdown(struct uart_port *port)
{
- struct mpc52xx_psc *psc = PSC(port);
+ struct mpc52xx_psc __iomem *psc = PSC(port);
/* Shut down the port, interrupt and all */
out_8(&psc->command,MPC52xx_PSC_RST_RX);
@@ -225,13 +224,16 @@ mpc52xx_uart_shutdown(struct uart_port *port)
port->read_status_mask = 0;
out_be16(&psc->mpc52xx_psc_imr,port->read_status_mask);
+
+ /* Release interrupt */
+ free_irq(port->irq, port);
}
static void
mpc52xx_uart_set_termios(struct uart_port *port, struct termios *new,
struct termios *old)
{
- struct mpc52xx_psc *psc = PSC(port);
+ struct mpc52xx_psc __iomem *psc = PSC(port);
unsigned long flags;
unsigned char mr1, mr2;
unsigned short ctr;
@@ -326,15 +328,21 @@ mpc52xx_uart_release_port(struct uart_port *port)
iounmap(port->membase);
port->membase = NULL;
}
+
+ release_mem_region(port->mapbase, MPC52xx_PSC_SIZE);
}
static int
mpc52xx_uart_request_port(struct uart_port *port)
{
if (port->flags & UPF_IOREMAP) /* Need to remap ? */
- port->membase = ioremap(port->mapbase, sizeof(struct mpc52xx_psc));
-
- return port->membase != NULL ? 0 : -EBUSY;
+ port->membase = ioremap(port->mapbase, MPC52xx_PSC_SIZE);
+
+ if (!port->membase)
+ return -EINVAL;
+
+ return request_mem_region(port->mapbase, MPC52xx_PSC_SIZE,
+ "mpc52xx_psc_uart") != NULL ? 0 : -EBUSY;
}
static void
@@ -354,7 +362,7 @@ mpc52xx_uart_verify_port(struct uart_port *port, struct serial_struct *ser)
if ( (ser->irq != port->irq) ||
(ser->io_type != SERIAL_IO_MEM) ||
(ser->baud_base != port->uartclk) ||
- // FIXME Should check addresses/irq as well ?
+ (ser->iomem_base != (void*)port->mapbase) ||
(ser->hub6 != 0 ) )
return -EINVAL;
@@ -562,7 +570,7 @@ static void __init
mpc52xx_console_get_options(struct uart_port *port,
int *baud, int *parity, int *bits, int *flow)
{
- struct mpc52xx_psc *psc = PSC(port);
+ struct mpc52xx_psc __iomem *psc = PSC(port);
unsigned char mr1;
/* Read the mode registers */
@@ -592,7 +600,7 @@ static void
mpc52xx_console_write(struct console *co, const char *s, unsigned int count)
{
struct uart_port *port = &mpc52xx_uart_ports[co->index];
- struct mpc52xx_psc *psc = PSC(port);
+ struct mpc52xx_psc __iomem *psc = PSC(port);
unsigned int i, j;
/* Disable interrupts */
@@ -630,7 +638,7 @@ mpc52xx_console_setup(struct console *co, char *options)
{
struct uart_port *port = &mpc52xx_uart_ports[co->index];
- int baud = 9600;
+ int baud = CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD;
int bits = 8;
int parity = 'n';
int flow = 'n';
@@ -643,14 +651,12 @@ mpc52xx_console_setup(struct console *co, char *options)
spin_lock_init(&port->lock);
port->uartclk = __res.bi_ipbfreq / 2; /* Look at CTLR doc */
port->ops = &mpc52xx_uart_ops;
- port->mapbase = MPC52xx_PSCx(co->index);
+ port->mapbase = MPC52xx_PA(MPC52xx_PSCx_OFFSET(co->index+1));
- /* We ioremap ourself */
- port->membase = ioremap(port->mapbase, sizeof(struct mpc52xx_psc));
- if (port->membase == NULL) {
- release_mem_region(port->mapbase, sizeof(struct mpc52xx_psc));
- return -EBUSY;
- }
+ /* We ioremap ourself */
+ port->membase = ioremap(port->mapbase, MPC52xx_PSC_SIZE);
+ if (port->membase == NULL)
+ return -EINVAL;
/* Setup the port parameters accoding to options */
if (options)
@@ -707,26 +713,32 @@ static struct uart_driver mpc52xx_uart_driver = {
/* ======================================================================== */
-/* OCP Driver */
+/* Platform Driver */
/* ======================================================================== */
static int __devinit
-mpc52xx_uart_probe(struct ocp_device *ocp)
+mpc52xx_uart_probe(struct device *dev)
{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct resource *res = pdev->resource;
+
struct uart_port *port = NULL;
- int idx, ret;
+ int i, idx, ret;
- /* Get the corresponding port struct */
- idx = ocp->def->index;
+ /* Check validity & presence */
+ idx = pdev->id;
if (idx < 0 || idx >= MPC52xx_PSC_MAXNUM)
return -EINVAL;
-
- port = &mpc52xx_uart_ports[idx];
+
+ if (!mpc52xx_match_psc_function(idx,"uart"))
+ return -ENODEV;
/* Init the port structure */
+ port = &mpc52xx_uart_ports[idx];
+
+ memset(port, 0x00, sizeof(struct uart_port));
+
spin_lock_init(&port->lock);
- port->mapbase = ocp->def->paddr;
- port->irq = ocp->def->irq;
port->uartclk = __res.bi_ipbfreq / 2; /* Look at CTLR doc */
port->fifosize = 255; /* Should be 512 ! But it can't be */
/* stored in a unsigned char */
@@ -735,95 +747,65 @@ mpc52xx_uart_probe(struct ocp_device *ocp)
( uart_console(port) ? 0 : UPF_IOREMAP );
port->line = idx;
port->ops = &mpc52xx_uart_ops;
- port->read_status_mask = 0;
-
- /* Requests the mem & irqs */
- /* Unlike other serial drivers, we reserve the resources here, so we
- * can detect early if multiple drivers uses the same PSC. Special
- * care must be taken with the console PSC
- */
- ret = request_irq(
- port->irq, mpc52xx_uart_int,
- SA_INTERRUPT | SA_SAMPLE_RANDOM, "mpc52xx_psc_uart", port);
- if (ret)
- goto error;
- ret = request_mem_region(port->mapbase, sizeof(struct mpc52xx_psc),
- "mpc52xx_psc_uart") != NULL ? 0 : -EBUSY;
- if (ret)
- goto free_irq;
+ /* Search for IRQ and mapbase */
+ for (i=0 ; i<pdev->num_resources ; i++, res++) {
+ if (res->flags & IORESOURCE_MEM)
+ port->mapbase = res->start;
+ else if (res->flags & IORESOURCE_IRQ)
+ port->irq = res->start;
+ }
+ if (!port->irq || !port->mapbase)
+ return -EINVAL;
/* Add the port to the uart sub-system */
ret = uart_add_one_port(&mpc52xx_uart_driver, port);
- if (ret)
- goto release_mem;
-
- ocp_set_drvdata(ocp, (void*)port);
-
- return 0;
-
-
-free_irq:
- free_irq(port->irq, mpc52xx_uart_int);
-
-release_mem:
- release_mem_region(port->mapbase, sizeof(struct mpc52xx_psc));
-
-error:
- if (uart_console(port))
- printk( "mpc52xx_uart.c: Error during resource alloction for "
- "the console port !!! Check that the console PSC is "
- "not used by another OCP driver !!!\n" );
+ if (!ret)
+ dev_set_drvdata(dev, (void*)port);
return ret;
}
-static void
-mpc52xx_uart_remove(struct ocp_device *ocp)
+static int
+mpc52xx_uart_remove(struct device *dev)
{
- struct uart_port *port = (struct uart_port *) ocp_get_drvdata(ocp);
+ struct uart_port *port = (struct uart_port *) dev_get_drvdata(dev);
- ocp_set_drvdata(ocp, NULL);
+ dev_set_drvdata(dev, NULL);
- if (port) {
+ if (port)
uart_remove_one_port(&mpc52xx_uart_driver, port);
- release_mem_region(port->mapbase, sizeof(struct mpc52xx_psc));
- free_irq(port->irq, mpc52xx_uart_int);
- }
+
+ return 0;
}
#ifdef CONFIG_PM
static int
-mpc52xx_uart_suspend(struct ocp_device *ocp, u32 state)
+mpc52xx_uart_suspend(struct device *dev, u32 state, u32 level)
{
- struct uart_port *port = (struct uart_port *) ocp_get_drvdata(ocp);
+ struct uart_port *port = (struct uart_port *) dev_get_drvdata(dev);
- uart_suspend_port(&mpc52xx_uart_driver, port);
+ if (sport && level == SUSPEND_DISABLE)
+ uart_suspend_port(&mpc52xx_uart_driver, port);
return 0;
}
static int
-mpc52xx_uart_resume(struct ocp_device *ocp)
+mpc52xx_uart_resume(struct device *dev, u32 level)
{
- struct uart_port *port = (struct uart_port *) ocp_get_drvdata(ocp);
+ struct uart_port *port = (struct uart_port *) dev_get_drvdata(dev);
- uart_resume_port(&mpc52xx_uart_driver, port);
+ if (port && level == RESUME_ENABLE)
+ uart_resume_port(&mpc52xx_uart_driver, port);
return 0;
}
#endif
-static struct ocp_device_id mpc52xx_uart_ids[] __devinitdata = {
- { .vendor = OCP_VENDOR_FREESCALE, .function = OCP_FUNC_PSC_UART },
- { .vendor = OCP_VENDOR_INVALID /* Terminating entry */ }
-};
-
-MODULE_DEVICE_TABLE(ocp, mpc52xx_uart_ids);
-
-static struct ocp_driver mpc52xx_uart_ocp_driver = {
- .name = "mpc52xx_psc_uart",
- .id_table = mpc52xx_uart_ids,
+static struct device_driver mpc52xx_uart_platform_driver = {
+ .name = "mpc52xx-psc",
+ .bus = &platform_bus_type,
.probe = mpc52xx_uart_probe,
.remove = mpc52xx_uart_remove,
#ifdef CONFIG_PM
@@ -845,10 +827,11 @@ mpc52xx_uart_init(void)
printk(KERN_INFO "Serial: MPC52xx PSC driver\n");
ret = uart_register_driver(&mpc52xx_uart_driver);
- if (ret)
- return ret;
-
- ret = ocp_register_driver(&mpc52xx_uart_ocp_driver);
+ if (ret == 0) {
+ ret = driver_register(&mpc52xx_uart_platform_driver);
+ if (ret)
+ uart_unregister_driver(&mpc52xx_uart_driver);
+ }
return ret;
}
@@ -856,7 +839,7 @@ mpc52xx_uart_init(void)
static void __exit
mpc52xx_uart_exit(void)
{
- ocp_unregister_driver(&mpc52xx_uart_ocp_driver);
+ driver_unregister(&mpc52xx_uart_platform_driver);
uart_unregister_driver(&mpc52xx_uart_driver);
}
diff --git a/drivers/serial/mux.c b/drivers/serial/mux.c
index 033f9b145b889..dadd7e19714e1 100644
--- a/drivers/serial/mux.c
+++ b/drivers/serial/mux.c
@@ -404,7 +404,7 @@ static struct console mux_console = {
.write = mux_console_write,
.device = mux_console_device,
.setup = mux_console_setup,
- .flags = CON_BOOT|CON_PRINTBUFFER|CON_ENABLED,
+ .flags = CON_ENABLED | CON_PRINTBUFFER,
.index = 0,
};
diff --git a/drivers/serial/s3c2410.c b/drivers/serial/s3c2410.c
index 6079c8cc7aa0c..ffc61389614b6 100644
--- a/drivers/serial/s3c2410.c
+++ b/drivers/serial/s3c2410.c
@@ -5,7 +5,8 @@
*
* Based on drivers/char/serial.c and drivers/char/21285.c
*
- * Ben Dooks, (c) 2003 Simtec Electronics
+ * Ben Dooks, (c) 2003-2005 Simtec Electronics
+ * http://www.simtec.co.uk/products/SWLINUX/
*
* Changelog:
*
@@ -24,6 +25,19 @@
* - spin-lock initialisation (Dimitry Andric)
* - added clock control
* - updated init code to use platform_device info
+ *
+ * 06-Mar-2005 BJD Add s3c2440 fclk clock source
+ *
+ * 09-Mar-2005 BJD Add s3c2400 support
+ *
+ * 10-Mar-2005 LCVR Changed S3C2410_VA_UART to S3C24XX_VA_UART
+*/
+
+/* Note on 2440 fclk clock source handling
+ *
+ * Whilst it is possible to use the fclk as clock source, the method
+ * of properly switching too/from this is currently un-implemented, so
+ * whichever way is configured at startup is the one that will be used.
*/
/* Hote on 2410 error handling
@@ -87,6 +101,9 @@ struct s3c24xx_uart_info {
int (*get_clksrc)(struct uart_port *, struct s3c24xx_uart_clksrc *clk);
int (*set_clksrc)(struct uart_port *, struct s3c24xx_uart_clksrc *clk);
+
+ /* uart controls */
+ int (*reset_port)(struct uart_port *, struct s3c2410_uartcfg *);
};
struct s3c24xx_uart_port {
@@ -606,11 +623,6 @@ static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level,
* baud clocks (and the resultant actual baud rates) and then tries to
* pick the closest one and select that.
*
- * NOTES:
- * 1) there is no current code to properly select/deselect FCLK on
- * the s3c2440, so only specify FCLK or non-FCLK in the clock
- * sources for the UART
- *
*/
@@ -658,6 +670,7 @@ static int s3c24xx_serial_calcbaud(struct baud_calc *calc,
return 0;
rate = clk_get_rate(calc->src);
+ rate /= clksrc->divisor;
calc->clksrc = clksrc;
calc->quot = (rate + (8 * baud)) / (16 * baud);
@@ -685,6 +698,27 @@ static unsigned int s3c24xx_serial_getclk(struct uart_port *port,
if (cfg->clocks_size == 0)
clkp = &tmp_clksrc;
+ /* check to see if we're sourcing fclk, and if so we're
+ * going to have to update the clock source
+ */
+
+ if (strcmp(clkp->name, "fclk") == 0) {
+ struct s3c24xx_uart_clksrc src;
+
+ s3c24xx_serial_getsource(port, &src);
+
+ /* check that the port already using fclk, and if
+ * not, then re-select fclk
+ */
+
+ if (strcmp(src.name, clkp->name) == 0) {
+ s3c24xx_serial_setsource(port, clkp);
+ s3c24xx_serial_getsource(port, &src);
+ }
+
+ clkp->divisor = src.divisor;
+ }
+
s3c24xx_serial_calcbaud(res, port, clkp, baud);
best = res;
resptr = best + 1;
@@ -955,8 +989,6 @@ static struct s3c24xx_uart_port s3c24xx_serial_ports[NR_PORTS] = {
[0] = {
.port = {
.lock = SPIN_LOCK_UNLOCKED,
- .membase = 0,
- .mapbase = 0,
.iotype = UPIO_MEM,
.irq = IRQ_S3CUART_RX0,
.uartclk = 0,
@@ -969,8 +1001,6 @@ static struct s3c24xx_uart_port s3c24xx_serial_ports[NR_PORTS] = {
[1] = {
.port = {
.lock = SPIN_LOCK_UNLOCKED,
- .membase = 0,
- .mapbase = 0,
.iotype = UPIO_MEM,
.irq = IRQ_S3CUART_RX1,
.uartclk = 0,
@@ -985,8 +1015,6 @@ static struct s3c24xx_uart_port s3c24xx_serial_ports[NR_PORTS] = {
[2] = {
.port = {
.lock = SPIN_LOCK_UNLOCKED,
- .membase = 0,
- .mapbase = 0,
.iotype = UPIO_MEM,
.irq = IRQ_S3CUART_RX2,
.uartclk = 0,
@@ -999,24 +1027,18 @@ static struct s3c24xx_uart_port s3c24xx_serial_ports[NR_PORTS] = {
#endif
};
+/* s3c24xx_serial_resetport
+ *
+ * wrapper to call the specific reset for this port (reset the fifos
+ * and the settings)
+*/
-static int s3c24xx_serial_resetport(struct uart_port *port,
- struct s3c2410_uartcfg *cfg)
+static inline int s3c24xx_serial_resetport(struct uart_port * port,
+ struct s3c2410_uartcfg *cfg)
{
- /* ensure registers are setup */
-
- dbg("s3c24xx_serial_resetport: port=%p (%08lx), cfg=%p\n",
- port, port->mapbase, cfg);
-
- wr_regl(port, S3C2410_UCON, cfg->ucon);
- wr_regl(port, S3C2410_ULCON, cfg->ulcon);
-
- /* reset both fifos */
-
- wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH);
- wr_regl(port, S3C2410_UFCON, cfg->ufcon);
+ struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
- return 0;
+ return (info->reset_port)(port, cfg);
}
/* s3c24xx_serial_init_port
@@ -1072,8 +1094,7 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
dbg("resource %p (%lx..%lx)\n", res, res->start, res->end);
port->mapbase = res->start;
- port->membase = (void __iomem *)(res->start - S3C2410_PA_UART);
- port->membase += S3C2410_VA_UART;
+ port->membase = S3C24XX_VA_UART + (res->start - S3C2410_PA_UART);
port->irq = platform_get_irq(platdev, 0);
ourport->clk = clk_get(&platdev->dev, "uart");
@@ -1180,6 +1201,97 @@ int s3c24xx_serial_init(struct device_driver *drv,
/* cpu specific variations on the serial port support */
+#ifdef CONFIG_CPU_S3C2400
+
+static int s3c2400_serial_getsource(struct uart_port *port,
+ struct s3c24xx_uart_clksrc *clk)
+{
+ clk->divisor = 1;
+ clk->name = "pclk";
+
+ return 0;
+}
+
+static int s3c2400_serial_setsource(struct uart_port *port,
+ struct s3c24xx_uart_clksrc *clk)
+{
+ return 0;
+}
+
+static int s3c2400_serial_resetport(struct uart_port *port,
+ struct s3c2410_uartcfg *cfg)
+{
+ dbg("s3c2400_serial_resetport: port=%p (%08lx), cfg=%p\n",
+ port, port->mapbase, cfg);
+
+ wr_regl(port, S3C2410_UCON, cfg->ucon);
+ wr_regl(port, S3C2410_ULCON, cfg->ulcon);
+
+ /* reset both fifos */
+
+ wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH);
+ wr_regl(port, S3C2410_UFCON, cfg->ufcon);
+
+ return 0;
+}
+
+static struct s3c24xx_uart_info s3c2400_uart_inf = {
+ .name = "Samsung S3C2400 UART",
+ .type = PORT_S3C2400,
+ .fifosize = 16,
+ .rx_fifomask = S3C2410_UFSTAT_RXMASK,
+ .rx_fifoshift = S3C2410_UFSTAT_RXSHIFT,
+ .rx_fifofull = S3C2410_UFSTAT_RXFULL,
+ .tx_fifofull = S3C2410_UFSTAT_TXFULL,
+ .tx_fifomask = S3C2410_UFSTAT_TXMASK,
+ .tx_fifoshift = S3C2410_UFSTAT_TXSHIFT,
+ .get_clksrc = s3c2400_serial_getsource,
+ .set_clksrc = s3c2400_serial_setsource,
+ .reset_port = s3c2400_serial_resetport,
+};
+
+static int s3c2400_serial_probe(struct device *dev)
+{
+ return s3c24xx_serial_probe(dev, &s3c2400_uart_inf);
+}
+
+static struct device_driver s3c2400_serial_drv = {
+ .name = "s3c2400-uart",
+ .bus = &platform_bus_type,
+ .probe = s3c2400_serial_probe,
+ .remove = s3c24xx_serial_remove,
+ .suspend = s3c24xx_serial_suspend,
+ .resume = s3c24xx_serial_resume,
+};
+
+static inline int s3c2400_serial_init(void)
+{
+ return s3c24xx_serial_init(&s3c2400_serial_drv, &s3c2400_uart_inf);
+}
+
+static inline void s3c2400_serial_exit(void)
+{
+ driver_unregister(&s3c2400_serial_drv);
+}
+
+#define s3c2400_uart_inf_at &s3c2400_uart_inf
+#else
+
+static inline int s3c2400_serial_init(void)
+{
+ return 0;
+}
+
+static inline void s3c2400_serial_exit(void)
+{
+}
+
+#define s3c2400_uart_inf_at NULL
+
+#endif /* CONFIG_CPU_S3C2400 */
+
+/* S3C2410 support */
+
#ifdef CONFIG_CPU_S3C2410
static int s3c2410_serial_setsource(struct uart_port *port,
@@ -1207,6 +1319,23 @@ static int s3c2410_serial_getsource(struct uart_port *port,
return 0;
}
+static int s3c2410_serial_resetport(struct uart_port *port,
+ struct s3c2410_uartcfg *cfg)
+{
+ dbg("s3c2410_serial_resetport: port=%p (%08lx), cfg=%p\n",
+ port, port->mapbase, cfg);
+
+ wr_regl(port, S3C2410_UCON, cfg->ucon);
+ wr_regl(port, S3C2410_ULCON, cfg->ulcon);
+
+ /* reset both fifos */
+
+ wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH);
+ wr_regl(port, S3C2410_UFCON, cfg->ufcon);
+
+ return 0;
+}
+
static struct s3c24xx_uart_info s3c2410_uart_inf = {
.name = "Samsung S3C2410 UART",
.type = PORT_S3C2410,
@@ -1219,6 +1348,7 @@ static struct s3c24xx_uart_info s3c2410_uart_inf = {
.tx_fifoshift = S3C2410_UFSTAT_TXSHIFT,
.get_clksrc = s3c2410_serial_getsource,
.set_clksrc = s3c2410_serial_setsource,
+ .reset_port = s3c2410_serial_resetport,
};
/* device management */
@@ -1294,6 +1424,7 @@ static int s3c2440_serial_getsource(struct uart_port *port,
struct s3c24xx_uart_clksrc *clk)
{
unsigned long ucon = rd_regl(port, S3C2410_UCON);
+ unsigned long ucon0, ucon1, ucon2;
switch (ucon & S3C2440_UCON_CLKMASK) {
case S3C2440_UCON_UCLK:
@@ -1308,7 +1439,33 @@ static int s3c2440_serial_getsource(struct uart_port *port,
break;
case S3C2440_UCON_FCLK:
- clk->divisor = 7; /* todo - work out divisor */
+ /* the fun of calculating the uart divisors on
+ * the s3c2440 */
+
+ ucon0 = __raw_readl(S3C24XX_VA_UART0 + S3C2410_UCON);
+ ucon1 = __raw_readl(S3C24XX_VA_UART1 + S3C2410_UCON);
+ ucon2 = __raw_readl(S3C24XX_VA_UART2 + S3C2410_UCON);
+
+ printk("ucons: %08lx, %08lx, %08lx\n", ucon0, ucon1, ucon2);
+
+ ucon0 &= S3C2440_UCON0_DIVMASK;
+ ucon1 &= S3C2440_UCON1_DIVMASK;
+ ucon2 &= S3C2440_UCON2_DIVMASK;
+
+ if (ucon0 != 0) {
+ clk->divisor = ucon0 >> S3C2440_UCON_DIVSHIFT;
+ clk->divisor += 6;
+ } else if (ucon1 != 0) {
+ clk->divisor = ucon1 >> S3C2440_UCON_DIVSHIFT;
+ clk->divisor += 21;
+ } else if (ucon2 != 0) {
+ clk->divisor = ucon2 >> S3C2440_UCON_DIVSHIFT;
+ clk->divisor += 36;
+ } else {
+ /* manual calims 44, seems to be 9 */
+ clk->divisor = 9;
+ }
+
clk->name = "fclk";
break;
}
@@ -1316,6 +1473,28 @@ static int s3c2440_serial_getsource(struct uart_port *port,
return 0;
}
+static int s3c2440_serial_resetport(struct uart_port *port,
+ struct s3c2410_uartcfg *cfg)
+{
+ unsigned long ucon = rd_regl(port, S3C2410_UCON);
+
+ dbg("s3c2440_serial_resetport: port=%p (%08lx), cfg=%p\n",
+ port, port->mapbase, cfg);
+
+ /* ensure we don't change the clock settings... */
+
+ ucon &= (S3C2440_UCON0_DIVMASK | (3<<10));
+
+ wr_regl(port, S3C2410_UCON, ucon | cfg->ucon);
+ wr_regl(port, S3C2410_ULCON, cfg->ulcon);
+
+ /* reset both fifos */
+
+ wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH);
+ wr_regl(port, S3C2410_UFCON, cfg->ufcon);
+
+ return 0;
+}
static struct s3c24xx_uart_info s3c2440_uart_inf = {
.name = "Samsung S3C2440 UART",
@@ -1328,7 +1507,8 @@ static struct s3c24xx_uart_info s3c2440_uart_inf = {
.tx_fifomask = S3C2440_UFSTAT_TXMASK,
.tx_fifoshift = S3C2440_UFSTAT_TXSHIFT,
.get_clksrc = s3c2440_serial_getsource,
- .set_clksrc = s3c2440_serial_setsource
+ .set_clksrc = s3c2440_serial_setsource,
+ .reset_port = s3c2440_serial_resetport,
};
/* device management */
@@ -1386,6 +1566,7 @@ static int __init s3c24xx_serial_modinit(void)
return -1;
}
+ s3c2400_serial_init();
s3c2410_serial_init();
s3c2440_serial_init();
@@ -1394,6 +1575,7 @@ static int __init s3c24xx_serial_modinit(void)
static void __exit s3c24xx_serial_modexit(void)
{
+ s3c2400_serial_exit();
s3c2410_serial_exit();
s3c2440_serial_exit();
@@ -1509,7 +1691,7 @@ s3c24xx_serial_get_options(struct uart_port *port, int *baud,
clk = clk_get(port->dev, clksrc.name);
if (!IS_ERR(clk) && clk != NULL)
- rate = clk_get_rate(clk);
+ rate = clk_get_rate(clk) / clksrc.divisor;
else
rate = 1;
@@ -1603,7 +1785,6 @@ static struct console s3c24xx_serial_console =
.setup = s3c24xx_serial_console_setup
};
-
static int s3c24xx_serial_initconsole(void)
{
struct s3c24xx_uart_info *info;
@@ -1618,7 +1799,9 @@ static int s3c24xx_serial_initconsole(void)
return 0;
}
- if (strcmp(dev->name, "s3c2410-uart") == 0) {
+ if (strcmp(dev->name, "s3c2400-uart") == 0) {
+ info = s3c2400_uart_inf_at;
+ } else if (strcmp(dev->name, "s3c2410-uart") == 0) {
info = s3c2410_uart_inf_at;
} else if (strcmp(dev->name, "s3c2440-uart") == 0) {
info = s3c2440_uart_inf_at;
diff --git a/drivers/serial/sa1100.c b/drivers/serial/sa1100.c
index 91d208755a6ad..85f0af452f95a 100644
--- a/drivers/serial/sa1100.c
+++ b/drivers/serial/sa1100.c
@@ -687,21 +687,21 @@ void __init sa1100_register_uart(int idx, int port)
switch (port) {
case 1:
- sa1100_ports[idx].port.membase = (void *)&Ser1UTCR0;
+ sa1100_ports[idx].port.membase = (void __iomem *)&Ser1UTCR0;
sa1100_ports[idx].port.mapbase = _Ser1UTCR0;
sa1100_ports[idx].port.irq = IRQ_Ser1UART;
sa1100_ports[idx].port.flags = ASYNC_BOOT_AUTOCONF;
break;
case 2:
- sa1100_ports[idx].port.membase = (void *)&Ser2UTCR0;
+ sa1100_ports[idx].port.membase = (void __iomem *)&Ser2UTCR0;
sa1100_ports[idx].port.mapbase = _Ser2UTCR0;
sa1100_ports[idx].port.irq = IRQ_Ser2ICP;
sa1100_ports[idx].port.flags = ASYNC_BOOT_AUTOCONF;
break;
case 3:
- sa1100_ports[idx].port.membase = (void *)&Ser3UTCR0;
+ sa1100_ports[idx].port.membase = (void __iomem *)&Ser3UTCR0;
sa1100_ports[idx].port.mapbase = _Ser3UTCR0;
sa1100_ports[idx].port.irq = IRQ_Ser3UART;
sa1100_ports[idx].port.flags = ASYNC_BOOT_AUTOCONF;
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c
index 16c227d30016b..36b1ae083fb7b 100644
--- a/drivers/serial/serial_core.c
+++ b/drivers/serial/serial_core.c
@@ -2233,7 +2233,7 @@ int uart_remove_one_port(struct uart_driver *drv, struct uart_port *port)
/*
* Are the two ports equivalent?
*/
-static int uart_match_port(struct uart_port *port1, struct uart_port *port2)
+int uart_match_port(struct uart_port *port1, struct uart_port *port2)
{
if (port1->iotype != port2->iotype)
return 0;
@@ -2249,6 +2249,7 @@ static int uart_match_port(struct uart_port *port1, struct uart_port *port2)
}
return 0;
}
+EXPORT_SYMBOL(uart_match_port);
/*
* Try to find an unused uart_state slot for a port.
diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c
index fe4c635baaa2e..9034f9ad37c7e 100644
--- a/drivers/serial/serial_cs.c
+++ b/drivers/serial/serial_cs.c
@@ -289,7 +289,8 @@ static void serial_detach(dev_link_t * link)
/*====================================================================*/
-static int setup_serial(struct serial_info * info, kio_addr_t iobase, int irq)
+static int setup_serial(client_handle_t handle, struct serial_info * info,
+ kio_addr_t iobase, int irq)
{
struct uart_port port;
int line;
@@ -299,6 +300,7 @@ static int setup_serial(struct serial_info * info, kio_addr_t iobase, int irq)
port.irq = irq;
port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ;
port.uartclk = 1843200;
+ port.dev = &handle_to_dev(handle);
if (buggy_uart)
port.flags |= UPF_BUGGY_UART;
line = serial8250_register_port(&port);
@@ -376,7 +378,7 @@ static int simple_config(dev_link_t *link)
info->slave = 1;
}
if (info->slave)
- return setup_serial(info, port, config.AssignedIRQ);
+ return setup_serial(handle, info, port, config.AssignedIRQ);
}
link->conf.Vcc = config.Vcc;
@@ -451,7 +453,7 @@ next_entry:
return -1;
}
- return setup_serial(info, link->io.BasePort1, link->irq.AssignedIRQ);
+ return setup_serial(handle, info, link->io.BasePort1, link->irq.AssignedIRQ);
}
static int multi_config(dev_link_t * link)
@@ -546,21 +548,21 @@ static int multi_config(dev_link_t * link)
8 registers are for the UART, the others are extra registers */
if (info->manfid == MANFID_OXSEMI) {
if (cf->index == 1 || cf->index == 3) {
- setup_serial(info, base2, link->irq.AssignedIRQ);
+ setup_serial(handle, info, base2, link->irq.AssignedIRQ);
outb(12, link->io.BasePort1 + 1);
} else {
- setup_serial(info, link->io.BasePort1, link->irq.AssignedIRQ);
+ setup_serial(handle, info, link->io.BasePort1, link->irq.AssignedIRQ);
outb(12, base2 + 1);
}
return 0;
}
- setup_serial(info, link->io.BasePort1, link->irq.AssignedIRQ);
+ setup_serial(handle, info, link->io.BasePort1, link->irq.AssignedIRQ);
/* The Nokia cards are not really multiport cards */
if (info->manfid == MANFID_NOKIA)
return 0;
for (i = 0; i < info->multi - 1; i++)
- setup_serial(info, base2 + (8 * i), link->irq.AssignedIRQ);
+ setup_serial(handle, info, base2 + (8 * i), link->irq.AssignedIRQ);
return 0;
}
diff --git a/drivers/serial/sn_console.c b/drivers/serial/sn_console.c
index 57aa612b5d357..ffaab9b90fd8f 100644
--- a/drivers/serial/sn_console.c
+++ b/drivers/serial/sn_console.c
@@ -6,7 +6,7 @@
* driver for that.
*
*
- * Copyright (c) 2004 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) 2004-2005 Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License
@@ -104,6 +104,7 @@ struct sn_cons_port {
};
static struct sn_cons_port sal_console_port;
+static int sn_process_input;
/* Only used if USE_DYNAMIC_MINOR is set to 1 */
static struct miscdevice misc; /* used with misc_register for dynamic */
@@ -681,7 +682,8 @@ static void sn_sal_timer_poll(unsigned long data)
if (!port->sc_port.irq) {
spin_lock_irqsave(&port->sc_port.lock, flags);
- sn_receive_chars(port, NULL, flags);
+ if (sn_process_input)
+ sn_receive_chars(port, NULL, flags);
sn_transmit_chars(port, TRANSMIT_RAW);
spin_unlock_irqrestore(&port->sc_port.lock, flags);
mod_timer(&port->sc_timer,
@@ -799,7 +801,7 @@ static struct console sal_console = {
#define SAL_CONSOLE &sal_console
-static struct uart_driver sal_console_uart = {
+struct uart_driver sal_console_uart = {
.owner = THIS_MODULE,
.driver_name = "sn_console",
.dev_name = DEVICE_NAME,
@@ -878,6 +880,7 @@ static int __init sn_sal_module_init(void)
if (!IS_RUNNING_ON_SIMULATOR()) {
sn_sal_switch_to_interrupts(&sal_console_port);
}
+ sn_process_input = 1;
return 0;
}
diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c
index c8fce59745861..23d19d3943208 100644
--- a/drivers/serial/sunsu.c
+++ b/drivers/serial/sunsu.c
@@ -1314,12 +1314,13 @@ static int __init sunsu_kbd_ms_init(struct uart_sunsu_port *up, int channel)
serio->port_data = up;
- serio->type = SERIO_RS232;
+ serio->id.type = SERIO_RS232;
if (up->su_type == SU_PORT_KBD) {
- serio->type |= SERIO_SUNKBD;
+ serio->id.proto = SERIO_SUNKBD;
strlcpy(serio->name, "sukbd", sizeof(serio->name));
} else {
- serio->type |= (SERIO_SUN | (1 << 16));
+ serio->id.proto = SERIO_SUN;
+ serio->id.extra = 1;
strlcpy(serio->name, "sums", sizeof(serio->name));
}
strlcpy(serio->phys, (channel == 0 ? "su/serio0" : "su/serio1"),
diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c
index abf20dc56183b..5c4231ae295b0 100644
--- a/drivers/serial/sunzilog.c
+++ b/drivers/serial/sunzilog.c
@@ -1562,12 +1562,13 @@ static void __init sunzilog_register_serio(struct uart_sunzilog_port *up, int ch
serio->port_data = up;
- serio->type = SERIO_RS232;
+ serio->id.type = SERIO_RS232;
if (channel == KEYBOARD_LINE) {
- serio->type |= SERIO_SUNKBD;
+ serio->id.proto = SERIO_SUNKBD;
strlcpy(serio->name, "zskbd", sizeof(serio->name));
} else {
- serio->type |= (SERIO_SUN | (1 << 16));
+ serio->id.proto = SERIO_SUN;
+ serio->id.extra = 1;
strlcpy(serio->name, "zsms", sizeof(serio->name));
}
strlcpy(serio->phys,
diff --git a/drivers/serial/vr41xx_siu.c b/drivers/serial/vr41xx_siu.c
new file mode 100644
index 0000000000000..ebc59c27a85cf
--- /dev/null
+++ b/drivers/serial/vr41xx_siu.c
@@ -0,0 +1,1100 @@
+/*
+ * Driver for NEC VR4100 series Serial Interface Unit.
+ *
+ * Copyright (C) 2004-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ *
+ * Based on drivers/serial/8250.c, by Russell King.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the 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>
+
+#if defined(CONFIG_SERIAL_VR41XX_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
+
+#include <linux/console.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+#include <linux/serial_reg.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+
+#include <asm/io.h>
+#include <asm/vr41xx/siu.h>
+#include <asm/vr41xx/vr41xx.h>
+
+#define SIU_PORTS_MAX 2
+#define SIU_BAUD_BASE 1152000
+#define SIU_MAJOR 204
+#define SIU_MINOR_BASE 82
+
+#define RX_MAX_COUNT 256
+#define TX_MAX_COUNT 15
+
+#define SIUIRSEL 0x08
+ #define TMICMODE 0x20
+ #define TMICTX 0x10
+ #define IRMSEL 0x0c
+ #define IRMSEL_HP 0x08
+ #define IRMSEL_TEMIC 0x04
+ #define IRMSEL_SHARP 0x00
+ #define IRUSESEL 0x02
+ #define SIRSEL 0x01
+
+struct siu_port {
+ unsigned int type;
+ unsigned int irq;
+ unsigned long start;
+};
+
+static const struct siu_port siu_type1_ports[] = {
+ { .type = PORT_VR41XX_SIU,
+ .irq = SIU_IRQ,
+ .start = 0x0c000000UL, },
+};
+
+#define SIU_TYPE1_NR_PORTS (sizeof(siu_type1_ports) / sizeof(struct siu_port))
+
+static const struct siu_port siu_type2_ports[] = {
+ { .type = PORT_VR41XX_SIU,
+ .irq = SIU_IRQ,
+ .start = 0x0f000800UL, },
+ { .type = PORT_VR41XX_DSIU,
+ .irq = DSIU_IRQ,
+ .start = 0x0f000820UL, },
+};
+
+#define SIU_TYPE2_NR_PORTS (sizeof(siu_type2_ports) / sizeof(struct siu_port))
+
+static struct uart_port siu_uart_ports[SIU_PORTS_MAX];
+static uint8_t lsr_break_flag[SIU_PORTS_MAX];
+
+#define siu_read(port, offset) readb((port)->membase + (offset))
+#define siu_write(port, offset, value) writeb((value), (port)->membase + (offset))
+
+void vr41xx_select_siu_interface(siu_interface_t interface)
+{
+ struct uart_port *port;
+ unsigned long flags;
+ uint8_t irsel;
+
+ port = &siu_uart_ports[0];
+
+ spin_lock_irqsave(&port->lock, flags);
+
+ irsel = siu_read(port, SIUIRSEL);
+ if (interface == SIU_INTERFACE_IRDA)
+ irsel |= SIRSEL;
+ else
+ irsel &= ~SIRSEL;
+ siu_write(port, SIUIRSEL, irsel);
+
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+
+EXPORT_SYMBOL_GPL(vr41xx_select_siu_interface);
+
+void vr41xx_use_irda(irda_use_t use)
+{
+ struct uart_port *port;
+ unsigned long flags;
+ uint8_t irsel;
+
+ port = &siu_uart_ports[0];
+
+ spin_lock_irqsave(&port->lock, flags);
+
+ irsel = siu_read(port, SIUIRSEL);
+ if (use == FIR_USE_IRDA)
+ irsel |= IRUSESEL;
+ else
+ irsel &= ~IRUSESEL;
+ siu_write(port, SIUIRSEL, irsel);
+
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+
+EXPORT_SYMBOL_GPL(vr41xx_use_irda);
+
+void vr41xx_select_irda_module(irda_module_t module, irda_speed_t speed)
+{
+ struct uart_port *port;
+ unsigned long flags;
+ uint8_t irsel;
+
+ port = &siu_uart_ports[0];
+
+ spin_lock_irqsave(&port->lock, flags);
+
+ irsel = siu_read(port, SIUIRSEL);
+ irsel &= ~(IRMSEL | TMICTX | TMICMODE);
+ switch (module) {
+ case SHARP_IRDA:
+ irsel |= IRMSEL_SHARP;
+ break;
+ case TEMIC_IRDA:
+ irsel |= IRMSEL_TEMIC | TMICMODE;
+ if (speed == IRDA_TX_4MBPS)
+ irsel |= TMICTX;
+ break;
+ case HP_IRDA:
+ irsel |= IRMSEL_HP;
+ break;
+ default:
+ break;
+ }
+ siu_write(port, SIUIRSEL, irsel);
+
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+
+EXPORT_SYMBOL_GPL(vr41xx_select_irda_module);
+
+static inline void siu_clear_fifo(struct uart_port *port)
+{
+ siu_write(port, UART_FCR, UART_FCR_ENABLE_FIFO);
+ siu_write(port, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR |
+ UART_FCR_CLEAR_XMIT);
+ siu_write(port, UART_FCR, 0);
+}
+
+static inline int siu_probe_ports(void)
+{
+ switch (current_cpu_data.cputype) {
+ case CPU_VR4111:
+ case CPU_VR4121:
+ return SIU_TYPE1_NR_PORTS;
+ case CPU_VR4122:
+ case CPU_VR4131:
+ case CPU_VR4133:
+ return SIU_TYPE2_NR_PORTS;
+ }
+
+ return 0;
+}
+
+static inline unsigned long siu_port_size(struct uart_port *port)
+{
+ switch (port->type) {
+ case PORT_VR41XX_SIU:
+ return 11UL;
+ case PORT_VR41XX_DSIU:
+ return 8UL;
+ }
+
+ return 0;
+}
+
+static inline unsigned int siu_check_type(struct uart_port *port)
+{
+ switch (current_cpu_data.cputype) {
+ case CPU_VR4111:
+ case CPU_VR4121:
+ if (port->line == 0)
+ return PORT_VR41XX_SIU;
+ break;
+ case CPU_VR4122:
+ case CPU_VR4131:
+ case CPU_VR4133:
+ if (port->line == 0)
+ return PORT_VR41XX_SIU;
+ else if (port->line == 1)
+ return PORT_VR41XX_DSIU;
+ break;
+ }
+
+ return PORT_UNKNOWN;
+}
+
+static inline const char *siu_type_name(struct uart_port *port)
+{
+ switch (port->type) {
+ case PORT_VR41XX_SIU:
+ return "SIU";
+ case PORT_VR41XX_DSIU:
+ return "DSIU";
+ }
+
+ return "unknown";
+}
+
+static unsigned int siu_tx_empty(struct uart_port *port)
+{
+ uint8_t lsr;
+
+ lsr = siu_read(port, UART_LSR);
+ if (lsr & UART_LSR_TEMT)
+ return TIOCSER_TEMT;
+
+ return 0;
+}
+
+static void siu_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+ uint8_t mcr = 0;
+
+ if (mctrl & TIOCM_DTR)
+ mcr |= UART_MCR_DTR;
+ if (mctrl & TIOCM_RTS)
+ mcr |= UART_MCR_RTS;
+ if (mctrl & TIOCM_OUT1)
+ mcr |= UART_MCR_OUT1;
+ if (mctrl & TIOCM_OUT2)
+ mcr |= UART_MCR_OUT2;
+ if (mctrl & TIOCM_LOOP)
+ mcr |= UART_MCR_LOOP;
+
+ siu_write(port, UART_MCR, mcr);
+}
+
+static unsigned int siu_get_mctrl(struct uart_port *port)
+{
+ uint8_t msr;
+ unsigned int mctrl = 0;
+
+ msr = siu_read(port, UART_MSR);
+ if (msr & UART_MSR_DCD)
+ mctrl |= TIOCM_CAR;
+ if (msr & UART_MSR_RI)
+ mctrl |= TIOCM_RNG;
+ if (msr & UART_MSR_DSR)
+ mctrl |= TIOCM_DSR;
+ if (msr & UART_MSR_CTS)
+ mctrl |= TIOCM_CTS;
+
+ return mctrl;
+}
+
+static void siu_stop_tx(struct uart_port *port, unsigned int tty_stop)
+{
+ unsigned long flags;
+ uint8_t ier;
+
+ spin_lock_irqsave(&port->lock, flags);
+
+ ier = siu_read(port, UART_IER);
+ ier &= ~UART_IER_THRI;
+ siu_write(port, UART_IER, ier);
+
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static void siu_start_tx(struct uart_port *port, unsigned int tty_start)
+{
+ unsigned long flags;
+ uint8_t ier;
+
+ spin_lock_irqsave(&port->lock, flags);
+
+ ier = siu_read(port, UART_IER);
+ ier |= UART_IER_THRI;
+ siu_write(port, UART_IER, ier);
+
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static void siu_stop_rx(struct uart_port *port)
+{
+ unsigned long flags;
+ uint8_t ier;
+
+ spin_lock_irqsave(&port->lock, flags);
+
+ ier = siu_read(port, UART_IER);
+ ier &= ~UART_IER_RLSI;
+ siu_write(port, UART_IER, ier);
+
+ port->read_status_mask &= ~UART_LSR_DR;
+
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static void siu_enable_ms(struct uart_port *port)
+{
+ unsigned long flags;
+ uint8_t ier;
+
+ spin_lock_irqsave(&port->lock, flags);
+
+ ier = siu_read(port, UART_IER);
+ ier |= UART_IER_MSI;
+ siu_write(port, UART_IER, ier);
+
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static void siu_break_ctl(struct uart_port *port, int ctl)
+{
+ unsigned long flags;
+ uint8_t lcr;
+
+ spin_lock_irqsave(&port->lock, flags);
+
+ lcr = siu_read(port, UART_LCR);
+ if (ctl == -1)
+ lcr |= UART_LCR_SBC;
+ else
+ lcr &= ~UART_LCR_SBC;
+ siu_write(port, UART_LCR, lcr);
+
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static inline void receive_chars(struct uart_port *port, uint8_t *status,
+ struct pt_regs *regs)
+{
+ struct tty_struct *tty;
+ uint8_t lsr, ch;
+ char flag;
+ int max_count = RX_MAX_COUNT;
+
+ tty = port->info->tty;
+ 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;
+
+#ifdef CONFIG_SERIAL_VR41XX_CONSOLE
+ lsr |= lsr_break_flag[port->line];
+ lsr_break_flag[port->line] = 0;
+#endif
+ if (unlikely(lsr & (UART_LSR_BI | UART_LSR_FE |
+ UART_LSR_PE | UART_LSR_OE))) {
+ if (lsr & UART_LSR_BI) {
+ lsr &= ~(UART_LSR_FE | UART_LSR_PE);
+ port->icount.brk++;
+
+ if (uart_handle_break(port))
+ goto ignore_char;
+ }
+
+ if (lsr & UART_LSR_FE)
+ port->icount.frame++;
+ if (lsr & UART_LSR_PE)
+ port->icount.parity++;
+ if (lsr & UART_LSR_OE)
+ port->icount.overrun++;
+
+ lsr &= port->read_status_mask;
+ if (lsr & UART_LSR_BI)
+ flag = TTY_BREAK;
+ if (lsr & UART_LSR_FE)
+ flag = TTY_FRAME;
+ if (lsr & UART_LSR_PE)
+ flag = TTY_PARITY;
+ }
+
+ if (uart_handle_sysrq_char(port, ch, regs))
+ goto ignore_char;
+ if ((lsr & port->ignore_status_mask) == 0)
+ tty_insert_flip_char(tty, ch, flag);
+ if ((lsr & UART_LSR_OE) && (tty->flip.count < TTY_FLIPBUF_SIZE))
+ tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+
+ ignore_char:
+ lsr = siu_read(port, UART_LSR);
+ } while ((lsr & UART_LSR_DR) && (max_count-- > 0));
+
+ tty_flip_buffer_push(tty);
+
+ *status = lsr;
+}
+
+static inline void check_modem_status(struct uart_port *port)
+{
+ uint8_t msr;
+
+ msr = siu_read(port, UART_MSR);
+ if ((msr & UART_MSR_ANY_DELTA) == 0)
+ return;
+ if (msr & UART_MSR_DDCD)
+ uart_handle_dcd_change(port, msr & UART_MSR_DCD);
+ if (msr & UART_MSR_TERI)
+ port->icount.rng++;
+ if (msr & UART_MSR_DDSR)
+ port->icount.dsr++;
+ if (msr & UART_MSR_DCTS)
+ uart_handle_cts_change(port, msr & UART_MSR_CTS);
+
+ wake_up_interruptible(&port->info->delta_msr_wait);
+}
+
+static inline void transmit_chars(struct uart_port *port)
+{
+ struct circ_buf *xmit;
+ int max_count = TX_MAX_COUNT;
+
+ xmit = &port->info->xmit;
+
+ if (port->x_char) {
+ siu_write(port, UART_TX, port->x_char);
+ port->icount.tx++;
+ port->x_char = 0;
+ return;
+ }
+
+ if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
+ siu_stop_tx(port, 0);
+ return;
+ }
+
+ do {
+ siu_write(port, UART_TX, xmit->buf[xmit->tail]);
+ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+ port->icount.tx++;
+ if (uart_circ_empty(xmit))
+ break;
+ } while (max_count-- > 0);
+
+ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+ uart_write_wakeup(port);
+
+ if (uart_circ_empty(xmit))
+ siu_stop_tx(port, 0);
+}
+
+static irqreturn_t siu_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct uart_port *port;
+ uint8_t iir, lsr;
+
+ if (dev_id == NULL)
+ return IRQ_NONE;
+
+ port = (struct uart_port *)dev_id;
+
+ iir = siu_read(port, UART_IIR);
+ if (iir & UART_IIR_NO_INT)
+ return IRQ_NONE;
+
+ lsr = siu_read(port, UART_LSR);
+ if (lsr & UART_LSR_DR)
+ receive_chars(port, &lsr, regs);
+
+ check_modem_status(port);
+
+ if (lsr & UART_LSR_THRE)
+ transmit_chars(port);
+
+ return IRQ_HANDLED;
+}
+
+static int siu_startup(struct uart_port *port)
+{
+ int retval;
+
+ siu_clear_fifo(port);
+
+ (void)siu_read(port, UART_LSR);
+ (void)siu_read(port, UART_RX);
+ (void)siu_read(port, UART_IIR);
+ (void)siu_read(port, UART_MSR);
+
+ if (siu_read(port, UART_LSR) == 0xff)
+ return -ENODEV;
+
+ retval = request_irq(port->irq, siu_interrupt, 0, siu_type_name(port), port);
+ if (retval)
+ return retval;
+
+ if (port->type == PORT_VR41XX_DSIU)
+ vr41xx_enable_dsiuint(DSIUINT_ALL);
+
+ siu_write(port, UART_LCR, UART_LCR_WLEN8);
+
+ spin_lock_irq(&port->lock);
+ siu_set_mctrl(port, port->mctrl);
+ spin_unlock_irq(&port->lock);
+
+ siu_write(port, UART_IER, UART_IER_RLSI | UART_IER_RDI);
+
+ (void)siu_read(port, UART_LSR);
+ (void)siu_read(port, UART_RX);
+ (void)siu_read(port, UART_IIR);
+ (void)siu_read(port, UART_MSR);
+
+ return 0;
+}
+
+static void siu_shutdown(struct uart_port *port)
+{
+ unsigned long flags;
+ uint8_t lcr;
+
+ if (port->membase == NULL)
+ return;
+
+ siu_write(port, UART_IER, 0);
+
+ spin_lock_irqsave(&port->lock, flags);
+
+ port->mctrl &= ~TIOCM_OUT2;
+ siu_set_mctrl(port, port->mctrl);
+
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ lcr = siu_read(port, UART_LCR);
+ lcr &= ~UART_LCR_SBC;
+ siu_write(port, UART_LCR, lcr);
+
+ siu_clear_fifo(port);
+
+ (void)siu_read(port, UART_RX);
+
+ if (port->type == PORT_VR41XX_DSIU)
+ vr41xx_disable_dsiuint(DSIUINT_ALL);
+
+ free_irq(port->irq, port);
+}
+
+static void siu_set_termios(struct uart_port *port, struct termios *new,
+ struct termios *old)
+{
+ tcflag_t c_cflag, c_iflag;
+ uint8_t lcr, fcr, ier;
+ unsigned int baud, quot;
+ unsigned long flags;
+
+ c_cflag = new->c_cflag;
+ switch (c_cflag & CSIZE) {
+ case CS5:
+ lcr = UART_LCR_WLEN5;
+ break;
+ case CS6:
+ lcr = UART_LCR_WLEN6;
+ break;
+ case CS7:
+ lcr = UART_LCR_WLEN7;
+ break;
+ default:
+ lcr = UART_LCR_WLEN8;
+ break;
+ }
+
+ if (c_cflag & CSTOPB)
+ lcr |= UART_LCR_STOP;
+ if (c_cflag & PARENB)
+ lcr |= UART_LCR_PARITY;
+ if ((c_cflag & PARODD) != PARODD)
+ lcr |= UART_LCR_EPAR;
+ if (c_cflag & CMSPAR)
+ lcr |= UART_LCR_SPAR;
+
+ baud = uart_get_baud_rate(port, new, old, 0, port->uartclk/16);
+ quot = uart_get_divisor(port, baud);
+
+ fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10;
+
+ spin_lock_irqsave(&port->lock, flags);
+
+ uart_update_timeout(port, c_cflag, baud);
+
+ c_iflag = new->c_iflag;
+
+ port->read_status_mask = UART_LSR_THRE | UART_LSR_OE | UART_LSR_DR;
+ if (c_iflag & INPCK)
+ port->read_status_mask |= UART_LSR_FE | UART_LSR_PE;
+ if (c_iflag & (BRKINT | PARMRK))
+ port->read_status_mask |= UART_LSR_BI;
+
+ port->ignore_status_mask = 0;
+ if (c_iflag & IGNPAR)
+ port->ignore_status_mask |= UART_LSR_FE | UART_LSR_PE;
+ if (c_iflag & IGNBRK) {
+ port->ignore_status_mask |= UART_LSR_BI;
+ if (c_iflag & IGNPAR)
+ port->ignore_status_mask |= UART_LSR_OE;
+ }
+
+ if ((c_cflag & CREAD) == 0)
+ port->ignore_status_mask |= UART_LSR_DR;
+
+ ier = siu_read(port, UART_IER);
+ ier &= ~UART_IER_MSI;
+ if (UART_ENABLE_MS(port, c_cflag))
+ ier |= UART_IER_MSI;
+ siu_write(port, UART_IER, ier);
+
+ siu_write(port, UART_LCR, lcr | UART_LCR_DLAB);
+
+ siu_write(port, UART_DLL, (uint8_t)quot);
+ siu_write(port, UART_DLM, (uint8_t)(quot >> 8));
+
+ siu_write(port, UART_LCR, lcr);
+
+ siu_write(port, UART_FCR, fcr);
+
+ siu_set_mctrl(port, port->mctrl);
+
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static void siu_pm(struct uart_port *port, unsigned int state, unsigned int oldstate)
+{
+ switch (state) {
+ case 0:
+ switch (port->type) {
+ case PORT_VR41XX_SIU:
+ vr41xx_supply_clock(SIU_CLOCK);
+ break;
+ case PORT_VR41XX_DSIU:
+ vr41xx_supply_clock(DSIU_CLOCK);
+ break;
+ }
+ break;
+ case 3:
+ switch (port->type) {
+ case PORT_VR41XX_SIU:
+ vr41xx_mask_clock(SIU_CLOCK);
+ break;
+ case PORT_VR41XX_DSIU:
+ vr41xx_mask_clock(DSIU_CLOCK);
+ break;
+ }
+ break;
+ }
+}
+
+static const char *siu_type(struct uart_port *port)
+{
+ return siu_type_name(port);
+}
+
+static void siu_release_port(struct uart_port *port)
+{
+ unsigned long size;
+
+ if (port->flags & UPF_IOREMAP) {
+ iounmap(port->membase);
+ port->membase = NULL;
+ }
+
+ size = siu_port_size(port);
+ release_mem_region(port->mapbase, size);
+}
+
+static int siu_request_port(struct uart_port *port)
+{
+ unsigned long size;
+ struct resource *res;
+
+ size = siu_port_size(port);
+ res = request_mem_region(port->mapbase, size, siu_type_name(port));
+ if (res == NULL)
+ return -EBUSY;
+
+ if (port->flags & UPF_IOREMAP) {
+ port->membase = ioremap(port->mapbase, size);
+ if (port->membase == NULL) {
+ release_resource(res);
+ return -ENOMEM;
+ }
+ }
+
+ return 0;
+}
+
+static void siu_config_port(struct uart_port *port, int flags)
+{
+ if (flags & UART_CONFIG_TYPE) {
+ port->type = siu_check_type(port);
+ (void)siu_request_port(port);
+ }
+}
+
+static int siu_verify_port(struct uart_port *port, struct serial_struct *serial)
+{
+ if (port->type != PORT_VR41XX_SIU && port->type != PORT_VR41XX_DSIU)
+ return -EINVAL;
+ if (port->irq != serial->irq)
+ return -EINVAL;
+ if (port->iotype != serial->io_type)
+ return -EINVAL;
+ if (port->mapbase != (unsigned long)serial->iomem_base)
+ return -EINVAL;
+
+ return 0;
+}
+
+static struct uart_ops siu_uart_ops = {
+ .tx_empty = siu_tx_empty,
+ .set_mctrl = siu_set_mctrl,
+ .get_mctrl = siu_get_mctrl,
+ .stop_tx = siu_stop_tx,
+ .start_tx = siu_start_tx,
+ .stop_rx = siu_stop_rx,
+ .enable_ms = siu_enable_ms,
+ .break_ctl = siu_break_ctl,
+ .startup = siu_startup,
+ .shutdown = siu_shutdown,
+ .set_termios = siu_set_termios,
+ .pm = siu_pm,
+ .type = siu_type,
+ .release_port = siu_release_port,
+ .request_port = siu_request_port,
+ .config_port = siu_config_port,
+ .verify_port = siu_verify_port,
+};
+
+static int siu_init_ports(void)
+{
+ const struct siu_port *siu;
+ struct uart_port *port;
+ int i, num;
+
+ switch (current_cpu_data.cputype) {
+ case CPU_VR4111:
+ case CPU_VR4121:
+ siu = siu_type1_ports;
+ break;
+ case CPU_VR4122:
+ case CPU_VR4131:
+ case CPU_VR4133:
+ siu = siu_type2_ports;
+ break;
+ default:
+ return 0;
+ }
+
+ port = siu_uart_ports;
+ num = siu_probe_ports();
+ for (i = 0; i < num; i++) {
+ spin_lock_init(&port->lock);
+ port->irq = siu->irq;
+ port->uartclk = SIU_BAUD_BASE * 16;
+ port->fifosize = 16;
+ port->regshift = 0;
+ port->iotype = UPIO_MEM;
+ port->flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF;
+ port->type = siu->type;
+ port->line = i;
+ port->mapbase = siu->start;
+ siu++;
+ port++;
+ }
+
+ return num;
+}
+
+#ifdef CONFIG_SERIAL_VR41XX_CONSOLE
+
+static void early_set_termios(struct uart_port *port, struct termios *new,
+ struct termios *old)
+{
+ tcflag_t c_cflag;
+ uint8_t lcr;
+ unsigned int baud, quot;
+
+ c_cflag = new->c_cflag;
+ switch (c_cflag & CSIZE) {
+ case CS5:
+ lcr = UART_LCR_WLEN5;
+ break;
+ case CS6:
+ lcr = UART_LCR_WLEN6;
+ break;
+ case CS7:
+ lcr = UART_LCR_WLEN7;
+ break;
+ default:
+ lcr = UART_LCR_WLEN8;
+ break;
+ }
+
+ if (c_cflag & CSTOPB)
+ lcr |= UART_LCR_STOP;
+ if (c_cflag & PARENB)
+ lcr |= UART_LCR_PARITY;
+ if ((c_cflag & PARODD) != PARODD)
+ lcr |= UART_LCR_EPAR;
+ if (c_cflag & CMSPAR)
+ lcr |= UART_LCR_SPAR;
+
+ baud = uart_get_baud_rate(port, new, old, 0, port->uartclk/16);
+ quot = uart_get_divisor(port, baud);
+
+ siu_write(port, UART_LCR, lcr | UART_LCR_DLAB);
+
+ siu_write(port, UART_DLL, (uint8_t)quot);
+ siu_write(port, UART_DLM, (uint8_t)(quot >> 8));
+
+ siu_write(port, UART_LCR, lcr);
+}
+
+static struct uart_ops early_uart_ops = {
+ .set_termios = early_set_termios,
+};
+
+#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
+
+static void wait_for_xmitr(struct uart_port *port)
+{
+ int timeout = 10000;
+ uint8_t lsr, msr;
+
+ do {
+ lsr = siu_read(port, UART_LSR);
+ if (lsr & UART_LSR_BI)
+ lsr_break_flag[port->line] = UART_LSR_BI;
+
+ if ((lsr & BOTH_EMPTY) == BOTH_EMPTY)
+ break;
+ } while (timeout-- > 0);
+
+ if (port->flags & UPF_CONS_FLOW) {
+ timeout = 1000000;
+
+ do {
+ msr = siu_read(port, UART_MSR);
+ if ((msr & UART_MSR_CTS) != 0)
+ break;
+ } while (timeout-- > 0);
+ }
+}
+
+static void siu_console_write(struct console *con, const char *s, unsigned count)
+{
+ struct uart_port *port;
+ uint8_t ier;
+ unsigned i;
+
+ port = &siu_uart_ports[con->index];
+
+ ier = siu_read(port, UART_IER);
+ siu_write(port, UART_IER, 0);
+
+ for (i = 0; i < count && *s != '\0'; i++, s++) {
+ wait_for_xmitr(port);
+ siu_write(port, UART_TX, *s);
+ if (*s == '\n') {
+ wait_for_xmitr(port);
+ siu_write(port, UART_TX, '\r');
+ }
+ }
+
+ wait_for_xmitr(port);
+ siu_write(port, UART_IER, ier);
+}
+
+static int siu_console_setup(struct console *con, char *options)
+{
+ struct uart_port *port;
+ int baud = 9600;
+ int parity = 'n';
+ int bits = 8;
+ int flow = 'n';
+
+ if (con->index >= SIU_PORTS_MAX)
+ con->index = 0;
+
+ port = &siu_uart_ports[con->index];
+ if (port->membase == NULL) {
+ if (port->mapbase == 0)
+ return -ENODEV;
+ port->membase = (unsigned char __iomem *)KSEG1ADDR(port->mapbase);
+ }
+
+ vr41xx_select_siu_interface(SIU_INTERFACE_RS232C);
+
+ if (options != NULL)
+ uart_parse_options(options, &baud, &parity, &bits, &flow);
+
+ return uart_set_options(port, con, baud, parity, bits, flow);
+}
+
+static struct uart_driver siu_uart_driver;
+
+static struct console siu_console = {
+ .name = "ttyVR",
+ .write = siu_console_write,
+ .device = uart_console_device,
+ .setup = siu_console_setup,
+ .flags = CON_PRINTBUFFER,
+ .index = -1,
+ .data = &siu_uart_driver,
+};
+
+static int __devinit siu_console_init(void)
+{
+ struct uart_port *port;
+ int num, i;
+
+ num = siu_init_ports();
+ if (num <= 0)
+ return -ENODEV;
+
+ for (i = 0; i < num; i++) {
+ port = &siu_uart_ports[i];
+ port->ops = &early_uart_ops;
+ }
+
+ register_console(&siu_console);
+
+ return 0;
+}
+
+console_initcall(siu_console_init);
+
+#define SERIAL_VR41XX_CONSOLE &siu_console
+#else
+#define SERIAL_VR41XX_CONSOLE NULL
+#endif
+
+static struct uart_driver siu_uart_driver = {
+ .owner = THIS_MODULE,
+ .driver_name = "SIU",
+ .dev_name = "ttyVR",
+ .devfs_name = "ttvr/",
+ .major = SIU_MAJOR,
+ .minor = SIU_MINOR_BASE,
+ .cons = SERIAL_VR41XX_CONSOLE,
+};
+
+static int siu_probe(struct device *dev)
+{
+ struct uart_port *port;
+ int num, i, retval;
+
+ num = siu_init_ports();
+ if (num <= 0)
+ return -ENODEV;
+
+ siu_uart_driver.nr = num;
+ retval = uart_register_driver(&siu_uart_driver);
+ if (retval)
+ return retval;
+
+ for (i = 0; i < num; i++) {
+ port = &siu_uart_ports[i];
+ port->ops = &siu_uart_ops;
+ port->dev = dev;
+
+ retval = uart_add_one_port(&siu_uart_driver, port);
+ if (retval)
+ break;
+ }
+
+ if (i == 0 && retval < 0) {
+ uart_unregister_driver(&siu_uart_driver);
+ return retval;
+ }
+
+ return 0;
+}
+
+static int siu_remove(struct device *dev)
+{
+ struct uart_port *port;
+ int i;
+
+ for (i = 0; i < siu_uart_driver.nr; i++) {
+ port = &siu_uart_ports[i];
+ if (port->dev == dev) {
+ uart_remove_one_port(&siu_uart_driver, port);
+ port->dev = NULL;
+ }
+ }
+
+ uart_unregister_driver(&siu_uart_driver);
+
+ return 0;
+}
+
+static int siu_suspend(struct device *dev, u32 state, u32 level)
+{
+ struct uart_port *port;
+ int i;
+
+ if (level != SUSPEND_DISABLE)
+ return 0;
+
+ for (i = 0; i < siu_uart_driver.nr; i++) {
+ port = &siu_uart_ports[i];
+ if ((port->type == PORT_VR41XX_SIU ||
+ port->type == PORT_VR41XX_DSIU) && port->dev == dev)
+ uart_suspend_port(&siu_uart_driver, port);
+
+ }
+
+ return 0;
+}
+
+static int siu_resume(struct device *dev, u32 level)
+{
+ struct uart_port *port;
+ int i;
+
+ if (level != RESUME_ENABLE)
+ return 0;
+
+ for (i = 0; i < siu_uart_driver.nr; i++) {
+ port = &siu_uart_ports[i];
+ if ((port->type == PORT_VR41XX_SIU ||
+ port->type == PORT_VR41XX_DSIU) && port->dev == dev)
+ uart_resume_port(&siu_uart_driver, port);
+ }
+
+ return 0;
+}
+
+static struct platform_device *siu_platform_device;
+
+static struct device_driver siu_device_driver = {
+ .name = "SIU",
+ .bus = &platform_bus_type,
+ .probe = siu_probe,
+ .remove = siu_remove,
+ .suspend = siu_suspend,
+ .resume = siu_resume,
+};
+
+static int __devinit vr41xx_siu_init(void)
+{
+ int retval;
+
+ siu_platform_device = platform_device_register_simple("SIU", -1, NULL, 0);
+ if (IS_ERR(siu_platform_device))
+ return PTR_ERR(siu_platform_device);
+
+ retval = driver_register(&siu_device_driver);
+ if (retval < 0)
+ platform_device_unregister(siu_platform_device);
+
+ return retval;
+}
+
+static void __devexit vr41xx_siu_exit(void)
+{
+ driver_unregister(&siu_device_driver);
+
+ platform_device_unregister(siu_platform_device);
+}
+
+module_init(vr41xx_siu_init);
+module_exit(vr41xx_siu_exit);
diff --git a/drivers/sh/Makefile b/drivers/sh/Makefile
new file mode 100644
index 0000000000000..8a143894e33f6
--- /dev/null
+++ b/drivers/sh/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the SuperH specific drivers.
+#
+
+obj-$(CONFIG_SUPERHYWAY) += superhyway/
+
diff --git a/drivers/sh/superhyway/Makefile b/drivers/sh/superhyway/Makefile
new file mode 100644
index 0000000000000..499dc47d8dcd1
--- /dev/null
+++ b/drivers/sh/superhyway/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for the SuperHyway bus drivers.
+#
+
+obj-$(CONFIG_SUPERHYWAY) += superhyway.o
+obj-$(CONFIG_SYSFS) += superhyway-sysfs.o
+
diff --git a/drivers/sh/superhyway/superhyway-sysfs.c b/drivers/sh/superhyway/superhyway-sysfs.c
new file mode 100644
index 0000000000000..39ab6a12da76f
--- /dev/null
+++ b/drivers/sh/superhyway/superhyway-sysfs.c
@@ -0,0 +1,45 @@
+/*
+ * drivers/sh/superhyway/superhyway-sysfs.c
+ *
+ * SuperHyway Bus sysfs interface
+ *
+ * Copyright (C) 2004, 2005 Paul Mundt <lethal@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/kernel.h>
+#include <linux/device.h>
+#include <linux/types.h>
+#include <linux/superhyway.h>
+
+#define superhyway_ro_attr(name, fmt, field) \
+static ssize_t name##_show(struct device *dev, char *buf) \
+{ \
+ struct superhyway_device *s = to_superhyway_device(dev); \
+ return sprintf(buf, fmt, s->field); \
+}
+
+/* VCR flags */
+superhyway_ro_attr(perr_flags, "0x%02x\n", vcr.perr_flags);
+superhyway_ro_attr(merr_flags, "0x%02x\n", vcr.merr_flags);
+superhyway_ro_attr(mod_vers, "0x%04x\n", vcr.mod_vers);
+superhyway_ro_attr(mod_id, "0x%04x\n", vcr.mod_id);
+superhyway_ro_attr(bot_mb, "0x%02x\n", vcr.bot_mb);
+superhyway_ro_attr(top_mb, "0x%02x\n", vcr.top_mb);
+
+/* Misc */
+superhyway_ro_attr(resource, "0x%08lx\n", resource.start);
+
+struct device_attribute superhyway_dev_attrs[] = {
+ __ATTR_RO(perr_flags),
+ __ATTR_RO(merr_flags),
+ __ATTR_RO(mod_vers),
+ __ATTR_RO(mod_id),
+ __ATTR_RO(bot_mb),
+ __ATTR_RO(top_mb),
+ __ATTR_RO(resource),
+ __ATTR_NULL,
+};
+
diff --git a/drivers/sh/superhyway/superhyway.c b/drivers/sh/superhyway/superhyway.c
new file mode 100644
index 0000000000000..f056276b08a1d
--- /dev/null
+++ b/drivers/sh/superhyway/superhyway.c
@@ -0,0 +1,201 @@
+/*
+ * drivers/sh/superhyway/superhyway.c
+ *
+ * SuperHyway Bus Driver
+ *
+ * Copyright (C) 2004, 2005 Paul Mundt <lethal@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/kernel.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/superhyway.h>
+
+static int superhyway_devices;
+
+static struct device superhyway_bus_device = {
+ .bus_id = "superhyway",
+};
+
+static void superhyway_device_release(struct device *dev)
+{
+ kfree(to_superhyway_device(dev));
+}
+
+/**
+ * superhyway_add_device - Add a SuperHyway module
+ * @mod_id: Module ID (taken from MODULE.VCR.MOD_ID).
+ * @base: Physical address where module is mapped.
+ * @vcr: VCR value.
+ *
+ * This is responsible for adding a new SuperHyway module. This sets up a new
+ * struct superhyway_device for the module being added. Each one of @mod_id,
+ * @base, and @vcr are registered with the new device for further use
+ * elsewhere.
+ *
+ * Devices are initially added in the order that they are scanned (from the
+ * top-down of the memory map), and are assigned an ID based on the order that
+ * they are added. Any manual addition of a module will thus get the ID after
+ * the devices already discovered regardless of where it resides in memory.
+ *
+ * Further work can and should be done in superhyway_scan_bus(), to be sure
+ * that any new modules are properly discovered and subsequently registered.
+ */
+int superhyway_add_device(unsigned int mod_id, unsigned long base,
+ unsigned long long vcr)
+{
+ struct superhyway_device *dev;
+
+ dev = kmalloc(sizeof(struct superhyway_device), GFP_KERNEL);
+ if (!dev)
+ return -ENOMEM;
+
+ memset(dev, 0, sizeof(struct superhyway_device));
+
+ dev->id.id = mod_id;
+ sprintf(dev->name, "SuperHyway device %04x", dev->id.id);
+
+ dev->vcr = *((struct vcr_info *)(&vcr));
+ dev->resource.name = dev->name;
+ dev->resource.start = base;
+ dev->resource.end = dev->resource.start + 0x01000000;
+ dev->dev.parent = &superhyway_bus_device;
+ dev->dev.bus = &superhyway_bus_type;
+ dev->dev.release = superhyway_device_release;
+
+ sprintf(dev->dev.bus_id, "%02x", superhyway_devices);
+
+ superhyway_devices++;
+
+ return device_register(&dev->dev);
+}
+
+static int __init superhyway_init(void)
+{
+ device_register(&superhyway_bus_device);
+ return superhyway_scan_bus();
+}
+
+postcore_initcall(superhyway_init);
+
+static const struct superhyway_device_id *
+superhyway_match_id(const struct superhyway_device_id *ids,
+ struct superhyway_device *dev)
+{
+ while (ids->id) {
+ if (ids->id == dev->id.id)
+ return ids;
+
+ ids++;
+ }
+
+ return NULL;
+}
+
+static int superhyway_device_probe(struct device *dev)
+{
+ struct superhyway_device *shyway_dev = to_superhyway_device(dev);
+ struct superhyway_driver *shyway_drv = to_superhyway_driver(dev->driver);
+
+ if (shyway_drv && shyway_drv->probe) {
+ const struct superhyway_device_id *id;
+
+ id = superhyway_match_id(shyway_drv->id_table, shyway_dev);
+ if (id)
+ return shyway_drv->probe(shyway_dev, id);
+ }
+
+ return -ENODEV;
+}
+
+static int superhyway_device_remove(struct device *dev)
+{
+ struct superhyway_device *shyway_dev = to_superhyway_device(dev);
+ struct superhyway_driver *shyway_drv = to_superhyway_driver(dev->driver);
+
+ if (shyway_drv && shyway_drv->remove) {
+ shyway_drv->remove(shyway_dev);
+ return 0;
+ }
+
+ return -ENODEV;
+}
+
+/**
+ * superhyway_register_driver - Register a new SuperHyway driver
+ * @drv: SuperHyway driver to register.
+ *
+ * This registers the passed in @drv. Any devices matching the id table will
+ * automatically be populated and handed off to the driver's specified probe
+ * routine.
+ */
+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);
+}
+
+/**
+ * superhyway_unregister_driver - Unregister a SuperHyway driver
+ * @drv: SuperHyway driver to unregister.
+ *
+ * This cleans up after superhyway_register_driver(), and should be invoked in
+ * the exit path of any module drivers.
+ */
+void superhyway_unregister_driver(struct superhyway_driver *drv)
+{
+ driver_unregister(&drv->drv);
+}
+
+static int superhyway_bus_match(struct device *dev, struct device_driver *drv)
+{
+ struct superhyway_device *shyway_dev = to_superhyway_device(dev);
+ struct superhyway_driver *shyway_drv = to_superhyway_driver(drv);
+ const struct superhyway_device_id *ids = shyway_drv->id_table;
+
+ if (!ids)
+ return -EINVAL;
+ if (superhyway_match_id(ids, shyway_dev))
+ return 1;
+
+ return -ENODEV;
+}
+
+struct bus_type superhyway_bus_type = {
+ .name = "superhyway",
+ .match = superhyway_bus_match,
+#ifdef CONFIG_SYSFS
+ .dev_attrs = superhyway_dev_attrs,
+#endif
+};
+
+static int __init superhyway_bus_init(void)
+{
+ return bus_register(&superhyway_bus_type);
+}
+
+static void __exit superhyway_bus_exit(void)
+{
+ device_unregister(&superhyway_bus_device);
+ bus_unregister(&superhyway_bus_type);
+}
+
+core_initcall(superhyway_bus_init);
+module_exit(superhyway_bus_exit);
+
+EXPORT_SYMBOL(superhyway_bus_type);
+EXPORT_SYMBOL(superhyway_add_device);
+EXPORT_SYMBOL(superhyway_register_driver);
+EXPORT_SYMBOL(superhyway_unregister_driver);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/sn/Makefile b/drivers/sn/Makefile
new file mode 100644
index 0000000000000..631e54958448f
--- /dev/null
+++ b/drivers/sn/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the Altix device drivers.
+#
+#
+
+obj-$(CONFIG_BLK_DEV_SGIIOC4) += ioc4.o
diff --git a/drivers/sn/ioc4.c b/drivers/sn/ioc4.c
new file mode 100644
index 0000000000000..d9e4ee280e5f7
--- /dev/null
+++ b/drivers/sn/ioc4.c
@@ -0,0 +1,65 @@
+/*
+ * 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 shim driver for the IOC4 IDE and serial drivers.
+ */
+
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/ioc4_common.h>
+#include <linux/ide.h>
+
+
+static int __devinit
+ioc4_probe_one(struct pci_dev *pdev, const struct pci_device_id *pci_id)
+{
+ int ret;
+
+ if ((ret = pci_enable_device(pdev))) {
+ printk(KERN_WARNING
+ "%s: Failed to enable device with "
+ "pci_dev 0x%p... returning\n",
+ __FUNCTION__, (void *)pdev);
+ return ret;
+ }
+ pci_set_master(pdev);
+
+ /* attach each sub-device */
+ ret = ioc4_ide_attach_one(pdev, pci_id);
+ if (ret)
+ return ret;
+ return ioc4_serial_attach_one(pdev, pci_id);
+}
+
+/* pci device struct */
+static struct pci_device_id ioc4_s_id_table[] = {
+ {PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC4, PCI_ANY_ID,
+ PCI_ANY_ID, 0x0b4000, 0xFFFFFF},
+ {0}
+};
+MODULE_DEVICE_TABLE(pci, ioc4_s_id_table);
+
+static struct pci_driver __devinitdata ioc4_s_driver = {
+ .name = "IOC4",
+ .id_table = ioc4_s_id_table,
+ .probe = ioc4_probe_one,
+};
+
+static int __devinit ioc4_detect(void)
+{
+ ioc4_serial_init();
+
+ return pci_register_driver(&ioc4_s_driver);
+}
+module_init(ioc4_detect);
+
+MODULE_AUTHOR("Pat Gefre - Silicon Graphics Inc. (SGI) <pfg@sgi.com>");
+MODULE_DESCRIPTION("PCI driver module for SGI IOC4 Base-IO Card");
+MODULE_LICENSE("GPL");
diff --git a/drivers/tc/zs.c b/drivers/tc/zs.c
index 0f0d879bd1bf0..4382ee60b6a85 100644
--- a/drivers/tc/zs.c
+++ b/drivers/tc/zs.c
@@ -1240,28 +1240,24 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
switch (cmd) {
case TIOCGSERIAL:
- error = verify_area(VERIFY_WRITE, (void *)arg,
- sizeof(struct serial_struct));
- if (error)
- return error;
+ if (!access_ok(VERIFY_WRITE, (void *)arg,
+ sizeof(struct serial_struct)))
+ return -EFAULT;
return get_serial_info(info, (struct serial_struct *)arg);
case TIOCSSERIAL:
return set_serial_info(info, (struct serial_struct *)arg);
case TIOCSERGETLSR: /* Get line status register */
- error = verify_area(VERIFY_WRITE, (void *)arg,
- sizeof(unsigned int));
- if (error)
- return error;
- else
- return get_lsr_info(info, (unsigned int *)arg);
+ if (!access_ok(VERIFY_WRITE, (void *)arg,
+ sizeof(unsigned int)))
+ return -EFAULT;
+ return get_lsr_info(info, (unsigned int *)arg);
case TIOCSERGSTRUCT:
- error = verify_area(VERIFY_WRITE, (void *)arg,
- sizeof(struct dec_serial));
- if (error)
- return error;
+ if (!access_ok(VERIFY_WRITE, (void *)arg,
+ sizeof(struct dec_serial)))
+ return -EFAULT;
copy_from_user((struct dec_serial *)arg, info,
sizeof(struct dec_serial));
return 0;
@@ -1368,8 +1364,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
info->tty = 0;
if (info->blocked_open) {
if (info->close_delay) {
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(info->close_delay);
+ msleep_interruptible(jiffies_to_msecs(info->close_delay));
}
wake_up_interruptible(&info->open_wait);
}
@@ -1403,8 +1398,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
if (timeout)
char_time = min(char_time, timeout);
while ((read_zsreg(info->zs_channel, 1) & Tx_BUF_EMP) == 0) {
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(char_time);
+ msleep_interruptible(jiffies_to_msecs(char_time));
if (signal_pending(current))
break;
if (timeout && time_after(jiffies, orig_jiffies + timeout))
diff --git a/drivers/telephony/ixj.c b/drivers/telephony/ixj.c
index 210b0b16345ef..5538756f13ba8 100644
--- a/drivers/telephony/ixj.c
+++ b/drivers/telephony/ixj.c
@@ -5949,10 +5949,10 @@ static int ixj_build_filter_cadence(IXJ *j, IXJ_FILTER_CADENCE __user * cp)
j->cadence_f[lcp->filter].off3 = lcp->off3;
j->cadence_f[lcp->filter].off3min = 0;
j->cadence_f[lcp->filter].off3max = 0;
- kfree(lcp);
if(ixjdebug & 0x0002) {
printk(KERN_INFO "Cadence %d loaded\n", lcp->filter);
}
+ kfree(lcp);
return 0;
}
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index e22a84223afb9..cd329dd7fb865 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -4,6 +4,31 @@
menu "USB support"
+# Host-side USB depends on having a host controller
+# NOTE: dummy_hcd is always an option, but it's ignored here ...
+# NOTE: SL-811 option should be board-specific ...
+config USB_ARCH_HAS_HCD
+ boolean
+ default y if USB_ARCH_HAS_OHCI
+ default y if ARM # SL-811
+ default PCI
+
+# many non-PCI SOC chips embed OHCI
+config USB_ARCH_HAS_OHCI
+ boolean
+ # ARM:
+ default y if SA1111
+ default y if ARCH_OMAP
+ default y if ARCH_LH7A404
+ default y if PXA27x
+ # PPC:
+ default y if STB03xxx
+ default y if PPC_MPC52xx
+ # MIPS:
+ default y if SOC_AU1X00
+ # more:
+ default PCI
+
# ARM SA1111 chips have a non-PCI based "OHCI-compatible" USB host interface.
config USB
tristate "Support for Host-side USB"
@@ -56,12 +81,15 @@ source "drivers/usb/media/Kconfig"
source "drivers/usb/net/Kconfig"
+source "drivers/usb/mon/Kconfig"
+
comment "USB port drivers"
depends on USB
config USB_USS720
tristate "USS720 parport driver"
depends on USB && PARPORT
+ select PARPORT_NOT_PC
---help---
This driver is for USB parallel port adapters that use the Lucent
Technologies USS-720 chip. These cables are plugged into your USB
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
index aa790f1a3ef12..a61d4433a989f 100644
--- a/drivers/usb/Makefile
+++ b/drivers/usb/Makefile
@@ -6,6 +6,8 @@
obj-$(CONFIG_USB) += core/
+obj-$(CONFIG_USB_MON) += mon/
+
obj-$(CONFIG_USB_EHCI_HCD) += host/
obj-$(CONFIG_USB_OHCI_HCD) += host/
obj-$(CONFIG_USB_UHCI_HCD) += host/
@@ -48,8 +50,8 @@ obj-$(CONFIG_USB_KAWETH) += net/
obj-$(CONFIG_USB_PEGASUS) += net/
obj-$(CONFIG_USB_RTL8150) += net/
obj-$(CONFIG_USB_USBNET) += net/
+obj-$(CONFIG_USB_ZD1201) += net/
-obj-$(CONFIG_USB_HPUSBSCSI) += image/
obj-$(CONFIG_USB_MDC800) += image/
obj-$(CONFIG_USB_MICROTEK) += image/
diff --git a/drivers/usb/atm/speedtch.c b/drivers/usb/atm/speedtch.c
index 76b45b1d66098..233f9229badb6 100644
--- a/drivers/usb/atm/speedtch.c
+++ b/drivers/usb/atm/speedtch.c
@@ -58,8 +58,8 @@ static const char speedtch_driver_name[] = "speedtch";
#define SPEEDTOUCH_PRODUCTID 0x4061
/* Timeout in jiffies */
-#define CTRL_TIMEOUT (2*HZ)
-#define DATA_TIMEOUT (2*HZ)
+#define CTRL_TIMEOUT 2000
+#define DATA_TIMEOUT 2000
#define OFFSET_7 0 /* size 1 */
#define OFFSET_b 1 /* size 8 */
@@ -474,7 +474,7 @@ static void speedtch_upload_firmware(struct speedtch_instance_data *instance,
/* URB 7 */
if (dl_512_first) { /* some modems need a read before writing the firmware */
ret = usb_bulk_msg(usb_dev, usb_rcvbulkpipe(usb_dev, SPEEDTCH_ENDPOINT_FIRMWARE),
- buffer, 0x200, &actual_length, 2 * HZ);
+ buffer, 0x200, &actual_length, 2000);
if (ret < 0 && ret != -ETIMEDOUT)
dbg("speedtch_upload_firmware: read BLOCK0 from modem failed (%d)!", ret);
@@ -766,7 +766,7 @@ static int speedtch_usb_probe(struct usb_interface *intf,
/* First check whether the modem already seems to be alive */
ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
- 0x12, 0xc0, 0x07, 0x00, buf7, SIZE_7, HZ / 2);
+ 0x12, 0xc0, 0x07, 0x00, buf7, SIZE_7, 500);
if (ret == SIZE_7) {
dbg("firmware appears to be already loaded");
diff --git a/drivers/usb/class/audio.c b/drivers/usb/class/audio.c
index e5b6194bbb4b2..f432b7d5b2357 100644
--- a/drivers/usb/class/audio.c
+++ b/drivers/usb/class/audio.c
@@ -1561,7 +1561,7 @@ static int set_format_in(struct usb_audiodev *as)
if (fmt->attributes & 0x02) {
data[0] = 1;
if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT,
- PITCH_CONTROL << 8, ep, data, 1, HZ)) < 0) {
+ PITCH_CONTROL << 8, ep, data, 1, 1000)) < 0) {
printk(KERN_ERR "usbaudio: failure (error %d) to set output pitch control device %d interface %u endpoint 0x%x to %u\n",
ret, dev->devnum, u->interface, ep, d->srate);
return -1;
@@ -1573,13 +1573,13 @@ static int set_format_in(struct usb_audiodev *as)
data[1] = d->srate >> 8;
data[2] = d->srate >> 16;
if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT,
- SAMPLING_FREQ_CONTROL << 8, ep, data, 3, HZ)) < 0) {
+ SAMPLING_FREQ_CONTROL << 8, ep, data, 3, 1000)) < 0) {
printk(KERN_ERR "usbaudio: failure (error %d) to set input sampling frequency device %d interface %u endpoint 0x%x to %u\n",
ret, dev->devnum, u->interface, ep, d->srate);
return -1;
}
if ((ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_IN,
- SAMPLING_FREQ_CONTROL << 8, ep, data, 3, HZ)) < 0) {
+ SAMPLING_FREQ_CONTROL << 8, ep, data, 3, 1000)) < 0) {
printk(KERN_ERR "usbaudio: failure (error %d) to get input sampling frequency device %d interface %u endpoint 0x%x\n",
ret, dev->devnum, u->interface, ep);
return -1;
@@ -1657,7 +1657,7 @@ static int set_format_out(struct usb_audiodev *as)
if (fmt->attributes & 0x02) {
data[0] = 1;
if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT,
- PITCH_CONTROL << 8, ep, data, 1, HZ)) < 0) {
+ PITCH_CONTROL << 8, ep, data, 1, 1000)) < 0) {
printk(KERN_ERR "usbaudio: failure (error %d) to set output pitch control device %d interface %u endpoint 0x%x to %u\n",
ret, dev->devnum, u->interface, ep, d->srate);
return -1;
@@ -1669,13 +1669,13 @@ static int set_format_out(struct usb_audiodev *as)
data[1] = d->srate >> 8;
data[2] = d->srate >> 16;
if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT,
- SAMPLING_FREQ_CONTROL << 8, ep, data, 3, HZ)) < 0) {
+ SAMPLING_FREQ_CONTROL << 8, ep, data, 3, 1000)) < 0) {
printk(KERN_ERR "usbaudio: failure (error %d) to set output sampling frequency device %d interface %u endpoint 0x%x to %u\n",
ret, dev->devnum, u->interface, ep, d->srate);
return -1;
}
if ((ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_IN,
- SAMPLING_FREQ_CONTROL << 8, ep, data, 3, HZ)) < 0) {
+ SAMPLING_FREQ_CONTROL << 8, ep, data, 3, 1000)) < 0) {
printk(KERN_ERR "usbaudio: failure (error %d) to get output sampling frequency device %d interface %u endpoint 0x%x\n",
ret, dev->devnum, u->interface, ep);
return -1;
@@ -1754,7 +1754,7 @@ static int wrmixer(struct usb_mixerdev *ms, unsigned mixch, unsigned value)
data[0] = v1;
data[1] = v1 >> 8;
if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
- (ch->chnum << 8) | 1, ms->iface | (ch->unitid << 8), data, 2, HZ) < 0)
+ (ch->chnum << 8) | 1, ms->iface | (ch->unitid << 8), data, 2, 1000) < 0)
goto err;
if (!(ch->flags & (MIXFLG_STEREOIN | MIXFLG_STEREOOUT)))
return 0;
@@ -1762,7 +1762,7 @@ static int wrmixer(struct usb_mixerdev *ms, unsigned mixch, unsigned value)
data[1] = v2 >> 8;
if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
((ch->chnum + !!(ch->flags & MIXFLG_STEREOIN)) << 8) | (1 + !!(ch->flags & MIXFLG_STEREOOUT)),
- ms->iface | (ch->unitid << 8), data, 2, HZ) < 0)
+ ms->iface | (ch->unitid << 8), data, 2, 1000) < 0)
goto err;
return 0;
@@ -1771,14 +1771,14 @@ static int wrmixer(struct usb_mixerdev *ms, unsigned mixch, unsigned value)
data[0] = v1;
data[1] = v1 >> 8;
if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
- (ch->selector << 8) | ch->chnum, ms->iface | (ch->unitid << 8), data, 2, HZ) < 0)
+ (ch->selector << 8) | ch->chnum, ms->iface | (ch->unitid << 8), data, 2, 1000) < 0)
goto err;
if (!(ch->flags & (MIXFLG_STEREOIN | MIXFLG_STEREOOUT)))
return 0;
data[0] = v2;
data[1] = v2 >> 8;
if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
- (ch->selector << 8) | (ch->chnum + 1), ms->iface | (ch->unitid << 8), data, 2, HZ) < 0)
+ (ch->selector << 8) | (ch->chnum + 1), ms->iface | (ch->unitid << 8), data, 2, 1000) < 0)
goto err;
return 0;
@@ -1787,13 +1787,13 @@ static int wrmixer(struct usb_mixerdev *ms, unsigned mixch, unsigned value)
case TREBLE_CONTROL:
data[0] = v1 >> 8;
if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
- (ch->selector << 8) | ch->chnum, ms->iface | (ch->unitid << 8), data, 1, HZ) < 0)
+ (ch->selector << 8) | ch->chnum, ms->iface | (ch->unitid << 8), data, 1, 1000) < 0)
goto err;
if (!(ch->flags & (MIXFLG_STEREOIN | MIXFLG_STEREOOUT)))
return 0;
data[0] = v2 >> 8;
if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
- (ch->selector << 8) | (ch->chnum + 1), ms->iface | (ch->unitid << 8), data, 1, HZ) < 0)
+ (ch->selector << 8) | (ch->chnum + 1), ms->iface | (ch->unitid << 8), data, 1, 1000) < 0)
goto err;
return 0;
@@ -1820,7 +1820,7 @@ static int get_rec_src(struct usb_mixerdev *ms)
if (!ms->ch[i].slctunitid || (mask & (1 << i)))
continue;
if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
- 0, ms->iface | (ms->ch[i].slctunitid << 8), &buf, 1, HZ) < 0) {
+ 0, ms->iface | (ms->ch[i].slctunitid << 8), &buf, 1, 1000) < 0) {
err = -EIO;
printk(KERN_ERR "usbaudio: selector read request device %u if %u unit %u failed\n",
dev->devnum, ms->iface, ms->ch[i].slctunitid & 0xff);
@@ -1851,7 +1851,7 @@ static int set_rec_src(struct usb_mixerdev *ms, int srcmask)
if (!ms->ch[i].slctunitid || (mask & (1 << i)))
continue;
if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
- 0, ms->iface | (ms->ch[i].slctunitid << 8), &buf, 1, HZ) < 0) {
+ 0, ms->iface | (ms->ch[i].slctunitid << 8), &buf, 1, 1000) < 0) {
err = -EIO;
printk(KERN_ERR "usbaudio: selector read request device %u if %u unit %u failed\n",
dev->devnum, ms->iface, ms->ch[i].slctunitid & 0xff);
@@ -1880,7 +1880,7 @@ static int set_rec_src(struct usb_mixerdev *ms, int srcmask)
continue;
buf = ms->ch[j].slctunitid >> 8;
if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
- 0, ms->iface | (ms->ch[j].slctunitid << 8), &buf, 1, HZ) < 0) {
+ 0, ms->iface | (ms->ch[j].slctunitid << 8), &buf, 1, 1000) < 0) {
err = -EIO;
printk(KERN_ERR "usbaudio: selector write request device %u if %u unit %u failed\n",
dev->devnum, ms->iface, ms->ch[j].slctunitid & 0xff);
@@ -3136,18 +3136,18 @@ static void prepmixch(struct consmixstate *state)
switch (ch->selector) {
case 0: /* mixer unit request */
if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_MIN, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
- (ch->chnum << 8) | 1, state->ctrlif | (ch->unitid << 8), buf, 2, HZ) < 0)
+ (ch->chnum << 8) | 1, state->ctrlif | (ch->unitid << 8), buf, 2, 1000) < 0)
goto err;
ch->minval = buf[0] | (buf[1] << 8);
if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_MAX, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
- (ch->chnum << 8) | 1, state->ctrlif | (ch->unitid << 8), buf, 2, HZ) < 0)
+ (ch->chnum << 8) | 1, state->ctrlif | (ch->unitid << 8), buf, 2, 1000) < 0)
goto err;
ch->maxval = buf[0] | (buf[1] << 8);
v2 = ch->maxval - ch->minval;
if (!v2)
v2 = 1;
if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
- (ch->chnum << 8) | 1, state->ctrlif | (ch->unitid << 8), buf, 2, HZ) < 0)
+ (ch->chnum << 8) | 1, state->ctrlif | (ch->unitid << 8), buf, 2, 1000) < 0)
goto err;
v1 = buf[0] | (buf[1] << 8);
v3 = v1 - ch->minval;
@@ -3158,7 +3158,7 @@ static void prepmixch(struct consmixstate *state)
if (ch->flags & (MIXFLG_STEREOIN | MIXFLG_STEREOOUT)) {
if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
((ch->chnum + !!(ch->flags & MIXFLG_STEREOIN)) << 8) | (1 + !!(ch->flags & MIXFLG_STEREOOUT)),
- state->ctrlif | (ch->unitid << 8), buf, 2, HZ) < 0)
+ state->ctrlif | (ch->unitid << 8), buf, 2, 1000) < 0)
goto err;
v1 = buf[0] | (buf[1] << 8);
v3 = v1 - ch->minval;
@@ -3172,15 +3172,15 @@ static void prepmixch(struct consmixstate *state)
/* various feature unit controls */
case VOLUME_CONTROL:
if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_MIN, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
- (ch->selector << 8) | ch->chnum, state->ctrlif | (ch->unitid << 8), buf, 2, HZ) < 0)
+ (ch->selector << 8) | ch->chnum, state->ctrlif | (ch->unitid << 8), buf, 2, 1000) < 0)
goto err;
ch->minval = buf[0] | (buf[1] << 8);
if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_MAX, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
- (ch->selector << 8) | ch->chnum, state->ctrlif | (ch->unitid << 8), buf, 2, HZ) < 0)
+ (ch->selector << 8) | ch->chnum, state->ctrlif | (ch->unitid << 8), buf, 2, 1000) < 0)
goto err;
ch->maxval = buf[0] | (buf[1] << 8);
if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
- (ch->selector << 8) | ch->chnum, state->ctrlif | (ch->unitid << 8), buf, 2, HZ) < 0)
+ (ch->selector << 8) | ch->chnum, state->ctrlif | (ch->unitid << 8), buf, 2, 1000) < 0)
goto err;
v1 = buf[0] | (buf[1] << 8);
v2 = ch->maxval - ch->minval;
@@ -3193,7 +3193,7 @@ static void prepmixch(struct consmixstate *state)
ch->value = v3;
if (ch->flags & (MIXFLG_STEREOIN | MIXFLG_STEREOOUT)) {
if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
- (ch->selector << 8) | (ch->chnum + 1), state->ctrlif | (ch->unitid << 8), buf, 2, HZ) < 0)
+ (ch->selector << 8) | (ch->chnum + 1), state->ctrlif | (ch->unitid << 8), buf, 2, 1000) < 0)
goto err;
v1 = buf[0] | (buf[1] << 8);
v3 = v1 - ch->minval;
@@ -3208,15 +3208,15 @@ static void prepmixch(struct consmixstate *state)
case MID_CONTROL:
case TREBLE_CONTROL:
if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_MIN, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
- (ch->selector << 8) | ch->chnum, state->ctrlif | (ch->unitid << 8), buf, 1, HZ) < 0)
+ (ch->selector << 8) | ch->chnum, state->ctrlif | (ch->unitid << 8), buf, 1, 1000) < 0)
goto err;
ch->minval = buf[0] << 8;
if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_MAX, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
- (ch->selector << 8) | ch->chnum, state->ctrlif | (ch->unitid << 8), buf, 1, HZ) < 0)
+ (ch->selector << 8) | ch->chnum, state->ctrlif | (ch->unitid << 8), buf, 1, 1000) < 0)
goto err;
ch->maxval = buf[0] << 8;
if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
- (ch->selector << 8) | ch->chnum, state->ctrlif | (ch->unitid << 8), buf, 1, HZ) < 0)
+ (ch->selector << 8) | ch->chnum, state->ctrlif | (ch->unitid << 8), buf, 1, 1000) < 0)
goto err;
v1 = buf[0] << 8;
v2 = ch->maxval - ch->minval;
@@ -3229,7 +3229,7 @@ static void prepmixch(struct consmixstate *state)
ch->value = v3;
if (ch->flags & (MIXFLG_STEREOIN | MIXFLG_STEREOOUT)) {
if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
- (ch->selector << 8) | (ch->chnum + 1), state->ctrlif | (ch->unitid << 8), buf, 1, HZ) < 0)
+ (ch->selector << 8) | (ch->chnum + 1), state->ctrlif | (ch->unitid << 8), buf, 1, 1000) < 0)
goto err;
v1 = buf[0] << 8;
v3 = v1 - ch->minval;
@@ -3522,7 +3522,7 @@ static void usb_audio_featureunit(struct consmixstate *state, unsigned char *ftr
printk(KERN_DEBUG "usbaudio: unmuting feature unit %u interface %u\n", ftr[3], state->ctrlif);
data[0] = 0;
if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
- (MUTE_CONTROL << 8) | 0xff, state->ctrlif | (ftr[3] << 8), data, 1, HZ) < 0)
+ (MUTE_CONTROL << 8) | 0xff, state->ctrlif | (ftr[3] << 8), data, 1, 1000) < 0)
printk(KERN_WARNING "usbaudio: failure to unmute feature unit %u interface %u\n", ftr[3], state->ctrlif);
}
#endif
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index f1d8ccf331b86..6d1f9b6aecff7 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -60,6 +60,7 @@
#include <linux/smp_lock.h>
#include <asm/uaccess.h>
#include <linux/usb.h>
+#include <linux/usb_cdc.h>
#include <asm/byteorder.h>
#include <asm/unaligned.h>
@@ -89,7 +90,7 @@ static int acm_ctrl_msg(struct acm *acm, int request, int value, void *buf, int
int retval = usb_control_msg(acm->dev, usb_sndctrlpipe(acm->dev, 0),
request, USB_RT_ACM, value,
acm->control->altsetting[0].desc.bInterfaceNumber,
- buf, len, HZ * 5);
+ buf, len, 5000);
dbg("acm_control_msg: rq: 0x%02x val: %#x len: %#x result: %d", request, value, len, retval);
return retval < 0 ? retval : 0;
}
@@ -97,9 +98,12 @@ static int acm_ctrl_msg(struct acm *acm, int request, int value, void *buf, int
/* devices aren't required to support these requests.
* the cdc acm descriptor tells whether they do...
*/
-#define acm_set_control(acm, control) acm_ctrl_msg(acm, ACM_REQ_SET_CONTROL, control, NULL, 0)
-#define acm_set_line(acm, line) acm_ctrl_msg(acm, ACM_REQ_SET_LINE, 0, line, sizeof(struct acm_line))
-#define acm_send_break(acm, ms) acm_ctrl_msg(acm, ACM_REQ_SEND_BREAK, ms, NULL, 0)
+#define acm_set_control(acm, control) \
+ acm_ctrl_msg(acm, USB_CDC_REQ_SET_CONTROL_LINE_STATE, control, NULL, 0)
+#define acm_set_line(acm, line) \
+ acm_ctrl_msg(acm, USB_CDC_REQ_SET_LINE_CODING, 0, line, sizeof *(line))
+#define acm_send_break(acm, ms) \
+ acm_ctrl_msg(acm, USB_CDC_REQ_SEND_BREAK, ms, NULL, 0)
/*
* Interrupt handlers for various ACM device responses
@@ -109,7 +113,7 @@ static int acm_ctrl_msg(struct acm *acm, int request, int value, void *buf, int
static void acm_ctrl_irq(struct urb *urb, struct pt_regs *regs)
{
struct acm *acm = urb->context;
- struct usb_ctrlrequest *dr = urb->transfer_buffer;
+ struct usb_cdc_notification *dr = urb->transfer_buffer;
unsigned char *data;
int newctrl;
int status;
@@ -133,14 +137,14 @@ static void acm_ctrl_irq(struct urb *urb, struct pt_regs *regs)
goto exit;
data = (unsigned char *)(dr + 1);
- switch (dr->bRequest) {
+ switch (dr->bNotificationType) {
- case ACM_IRQ_NETWORK:
+ case USB_CDC_NOTIFY_NETWORK_CONNECTION:
dbg("%s network", dr->wValue ? "connected to" : "disconnected from");
break;
- case ACM_IRQ_LINE_STATE:
+ case USB_CDC_NOTIFY_SERIAL_STATE:
newctrl = le16_to_cpu(get_unaligned((__le16 *) data));
@@ -160,8 +164,9 @@ static void acm_ctrl_irq(struct urb *urb, struct pt_regs *regs)
break;
default:
- dbg("unknown control event received: request %d index %d len %d data0 %d data1 %d",
- dr->bRequest, dr->wIndex, dr->wLength, data[0], data[1]);
+ dbg("unknown notification %d received: index %d len %d data0 %d data1 %d",
+ dr->bNotificationType, dr->wIndex,
+ dr->wLength, data[0], data[1]);
break;
}
exit:
@@ -278,15 +283,14 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp)
- if (acm->used) {
+ if (acm->used++) {
goto done;
}
acm->ctrlurb->dev = acm->dev;
if (usb_submit_urb(acm->ctrlurb, GFP_KERNEL)) {
dbg("usb_submit_urb(ctrl irq) failed");
- rv = -EIO;
- goto err_out;
+ goto bail_out;
}
acm->readurb->dev = acm->dev;
@@ -303,7 +307,6 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp)
tty->low_latency = 1;
done:
- acm->used++;
err_out:
up(&open_sem);
return rv;
@@ -312,6 +315,8 @@ full_bailout:
usb_kill_urb(acm->readurb);
bail_out_and_unlink:
usb_kill_urb(acm->ctrlurb);
+bail_out:
+ acm->used--;
up(&open_sem);
return -EIO;
}
@@ -485,32 +490,34 @@ static void acm_tty_set_termios(struct tty_struct *tty, struct termios *termios_
{
struct acm *acm = tty->driver_data;
struct termios *termios = tty->termios;
- struct acm_line newline;
+ struct usb_cdc_line_coding newline;
int newctrl = acm->ctrlout;
if (!ACM_READY(acm))
return;
- newline.speed = cpu_to_le32p(acm_tty_speed +
+ newline.dwDTERate = cpu_to_le32p(acm_tty_speed +
(termios->c_cflag & CBAUD & ~CBAUDEX) + (termios->c_cflag & CBAUDEX ? 15 : 0));
- newline.stopbits = termios->c_cflag & CSTOPB ? 2 : 0;
- newline.parity = termios->c_cflag & PARENB ?
+ newline.bCharFormat = termios->c_cflag & CSTOPB ? 2 : 0;
+ newline.bParityType = termios->c_cflag & PARENB ?
(termios->c_cflag & PARODD ? 1 : 2) + (termios->c_cflag & CMSPAR ? 2 : 0) : 0;
- newline.databits = acm_tty_size[(termios->c_cflag & CSIZE) >> 4];
+ newline.bDataBits = acm_tty_size[(termios->c_cflag & CSIZE) >> 4];
acm->clocal = ((termios->c_cflag & CLOCAL) != 0);
- if (!newline.speed) {
- newline.speed = acm->line.speed;
+ if (!newline.dwDTERate) {
+ newline.dwDTERate = acm->line.dwDTERate;
newctrl &= ~ACM_CTRL_DTR;
} else newctrl |= ACM_CTRL_DTR;
if (newctrl != acm->ctrlout)
acm_set_control(acm, acm->ctrlout = newctrl);
- if (memcmp(&acm->line, &newline, sizeof(struct acm_line))) {
- memcpy(&acm->line, &newline, sizeof(struct acm_line));
- dbg("set line: %d %d %d %d", newline.speed, newline.stopbits, newline.parity, newline.databits);
+ if (memcmp(&acm->line, &newline, sizeof newline)) {
+ memcpy(&acm->line, &newline, sizeof newline);
+ dbg("set line: %d %d %d %d", le32_to_cpu(newline.dwDTERate),
+ newline.bCharFormat, newline.bParityType,
+ newline.bDataBits);
acm_set_line(acm, &acm->line);
}
}
@@ -522,7 +529,7 @@ static void acm_tty_set_termios(struct tty_struct *tty, struct termios *termios_
static int acm_probe (struct usb_interface *intf,
const struct usb_device_id *id)
{
- struct union_desc *union_header = NULL;
+ struct usb_cdc_union_desc *union_header = NULL;
char *buffer = intf->altsetting->extra;
int buflen = intf->altsetting->extralen;
struct usb_interface *control_interface;
@@ -573,21 +580,22 @@ static int acm_probe (struct usb_interface *intf,
}
switch (buffer [2]) {
- case CDC_UNION_TYPE: /* we've found it */
+ case USB_CDC_UNION_TYPE: /* we've found it */
if (union_header) {
err("More than one union descriptor, skipping ...");
goto next_desc;
}
- union_header = (struct union_desc *)buffer;
+ union_header = (struct usb_cdc_union_desc *)
+ buffer;
break;
- case CDC_COUNTRY_TYPE: /* maybe somehow export */
+ case USB_CDC_COUNTRY_TYPE: /* maybe somehow export */
break; /* for now we ignore it */
- case CDC_HEADER_TYPE: /* maybe check version */
+ case USB_CDC_HEADER_TYPE: /* maybe check version */
break; /* for now we ignore it */
- case CDC_AC_MANAGEMENT_TYPE:
+ case USB_CDC_ACM_TYPE:
ac_management_function = buffer[3];
break;
- case CDC_CALL_MANAGEMENT_TYPE:
+ case USB_CDC_CALL_MANAGEMENT_TYPE:
call_management_function = buffer[3];
call_interface_num = buffer[4];
if ((call_management_function & 3) != 3)
@@ -750,8 +758,8 @@ skip_normal_probe:
acm_set_control(acm, acm->ctrlout);
- acm->line.speed = cpu_to_le32(9600);
- acm->line.databits = 8;
+ acm->line.dwDTERate = cpu_to_le32(9600);
+ acm->line.bDataBits = 8;
acm_set_line(acm, &acm->line);
usb_driver_claim_interface(&acm_driver, data_interface, acm);
@@ -831,14 +839,20 @@ static struct usb_device_id acm_ids[] = {
.driver_info = NO_UNION_NORMAL, /* has no union descriptor */
},
/* control interfaces with various AT-command sets */
- { USB_INTERFACE_INFO(USB_CLASS_COMM, 2, 1) },
- { USB_INTERFACE_INFO(USB_CLASS_COMM, 2, 2) },
- { USB_INTERFACE_INFO(USB_CLASS_COMM, 2, 3) },
- { USB_INTERFACE_INFO(USB_CLASS_COMM, 2, 4) },
- { USB_INTERFACE_INFO(USB_CLASS_COMM, 2, 5) },
- { USB_INTERFACE_INFO(USB_CLASS_COMM, 2, 6) },
-
- /* NOTE: COMM/2/0xff is likely MSFT RNDIS ... NOT a modem!! */
+ { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
+ USB_CDC_ACM_PROTO_AT_V25TER) },
+ { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
+ USB_CDC_ACM_PROTO_AT_PCCA101) },
+ { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
+ USB_CDC_ACM_PROTO_AT_PCCA101_WAKE) },
+ { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
+ USB_CDC_ACM_PROTO_AT_GSM) },
+ { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
+ USB_CDC_ACM_PROTO_AT_3G ) },
+ { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
+ USB_CDC_ACM_PROTO_AT_CDMA) },
+
+ /* NOTE: COMM/ACM/0xff is likely MSFT RNDIS ... NOT a modem!! */
{ }
};
diff --git a/drivers/usb/class/cdc-acm.h b/drivers/usb/class/cdc-acm.h
index c98a8c2b2a440..9009114e311be 100644
--- a/drivers/usb/class/cdc-acm.h
+++ b/drivers/usb/class/cdc-acm.h
@@ -27,24 +27,6 @@
#define USB_RT_ACM (USB_TYPE_CLASS | USB_RECIP_INTERFACE)
-#define ACM_REQ_COMMAND 0x00
-#define ACM_REQ_RESPONSE 0x01
-#define ACM_REQ_SET_FEATURE 0x02
-#define ACM_REQ_GET_FEATURE 0x03
-#define ACM_REQ_CLEAR_FEATURE 0x04
-
-#define ACM_REQ_SET_LINE 0x20
-#define ACM_REQ_GET_LINE 0x21
-#define ACM_REQ_SET_CONTROL 0x22
-#define ACM_REQ_SEND_BREAK 0x23
-
-/*
- * IRQs.
- */
-
-#define ACM_IRQ_NETWORK 0x00
-#define ACM_IRQ_LINE_STATE 0x20
-
/*
* Output control lines.
*/
@@ -66,17 +48,6 @@
#define ACM_CTRL_OVERRUN 0x40
/*
- * Line speed and caracter encoding.
- */
-
-struct acm_line {
- __le32 speed;
- __u8 stopbits;
- __u8 parity;
- __u8 databits;
-} __attribute__ ((packed));
-
-/*
* Internal driver structures.
*/
@@ -88,7 +59,7 @@ struct acm {
struct urb *ctrlurb, *readurb, *writeurb; /* urbs */
u8 *ctrl_buffer, *read_buffer, *write_buffer; /* buffers of urbs */
dma_addr_t ctrl_dma, read_dma, write_dma; /* dma handles of buffers */
- struct acm_line line; /* line coding (bits, stop, parity) */
+ 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 */
spinlock_t throttle_lock; /* synchronize throtteling and read callback */
@@ -105,24 +76,6 @@ struct acm {
unsigned int ctrl_caps; /* control capabilities from the class specific header */
};
-/* "Union Functional Descriptor" from CDC spec 5.2.3.X */
-struct union_desc {
- u8 bLength;
- u8 bDescriptorType;
- u8 bDescriptorSubType;
-
- u8 bMasterInterface0;
- u8 bSlaveInterface0;
- /* ... and there could be other slave interfaces */
-} __attribute__ ((packed));
-
-/* class specific descriptor types */
-#define CDC_HEADER_TYPE 0x00
-#define CDC_CALL_MANAGEMENT_TYPE 0x01
-#define CDC_AC_MANAGEMENT_TYPE 0x02
-#define CDC_UNION_TYPE 0x06
-#define CDC_COUNTRY_TYPE 0x07
-
#define CDC_DATA_INTERFACE_TYPE 0x0a
/* constants describing various quirks and errors */
diff --git a/drivers/usb/class/usb-midi.c b/drivers/usb/class/usb-midi.c
index b5f85504cf559..5f8af35e76330 100644
--- a/drivers/usb/class/usb-midi.c
+++ b/drivers/usb/class/usb-midi.c
@@ -992,7 +992,7 @@ static struct midi_in_endpoint *alloc_midi_in_endpoint( struct usb_device *d, in
endPoint &= 0x0f; /* Silently force endPoint to lie in range 0 to 15. */
pipe = usb_rcvbulkpipe( d, endPoint );
- bufSize = usb_maxpacket( d, pipe, usb_pipein(pipe) );
+ bufSize = usb_maxpacket( d, pipe, 0 );
/* usb_pipein() = ! usb_pipeout() = true for an in Endpoint */
ep = (struct midi_in_endpoint *)kmalloc(sizeof(struct midi_in_endpoint), GFP_KERNEL);
@@ -1063,7 +1063,7 @@ static struct midi_out_endpoint *alloc_midi_out_endpoint( struct usb_device *d,
endPoint &= 0x0f;
pipe = usb_sndbulkpipe( d, endPoint );
- bufSize = usb_maxpacket( d, pipe, usb_pipeout(pipe) );
+ bufSize = usb_maxpacket( d, pipe, 1 );
ep = (struct midi_out_endpoint *)kmalloc(sizeof(struct midi_out_endpoint), GFP_KERNEL);
if ( !ep ) {
@@ -1451,8 +1451,6 @@ static struct usb_midi_device *parse_descriptor( struct usb_device *d, unsigned
} else {
if ( oep < 15 ) {
pins = oep+1;
- if ( pins > 16 )
- pins = 16;
u->out[oep].endpoint = p1[2];
u->out[oep].cableId = ( 1 << pins ) - 1;
if ( u->out[oep].cableId )
diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c
index d6cfeb8ec6315..bba22e97ea0f0 100644
--- a/drivers/usb/class/usblp.c
+++ b/drivers/usb/class/usblp.c
@@ -114,7 +114,7 @@ MFG:HEWLETT-PACKARD;MDL:DESKJET 970C;CMD:MLC,PCL,PML;CLASS:PRINTER;DESCRIPTION:H
#define USBLP_MINORS 16
#define USBLP_MINOR_BASE 0
-#define USBLP_WRITE_TIMEOUT (5*HZ) /* 5 seconds */
+#define USBLP_WRITE_TIMEOUT (5000) /* 5 seconds */
#define USBLP_FIRST_PROTOCOL 1
#define USBLP_LAST_PROTOCOL 3
diff --git a/drivers/usb/core/buffer.c b/drivers/usb/core/buffer.c
index 1e2a42ad34a40..b7827df21f486 100644
--- a/drivers/usb/core/buffer.c
+++ b/drivers/usb/core/buffer.c
@@ -76,7 +76,6 @@ int hcd_buffer_create (struct usb_hcd *hcd)
}
return 0;
}
-EXPORT_SYMBOL (hcd_buffer_create);
/**
@@ -98,7 +97,6 @@ void hcd_buffer_destroy (struct usb_hcd *hcd)
}
}
}
-EXPORT_SYMBOL (hcd_buffer_destroy);
/* sometimes alloc/free could use kmalloc with SLAB_DMA, for
diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
index 42e9f84662720..0b092bdf98f39 100644
--- a/drivers/usb/core/config.c
+++ b/drivers/usb/core/config.c
@@ -221,7 +221,7 @@ skip_to_next_interface_descriptor:
return buffer - buffer0 + i;
}
-int usb_parse_configuration(struct device *ddev, int cfgidx,
+static int usb_parse_configuration(struct device *ddev, int cfgidx,
struct usb_host_config *config, unsigned char *buffer, int size)
{
unsigned char *buffer0 = buffer;
@@ -420,6 +420,9 @@ void usb_destroy_configuration(struct usb_device *dev)
for (c = 0; c < dev->descriptor.bNumConfigurations; c++) {
struct usb_host_config *cf = &dev->config[c];
+ kfree(cf->string);
+ cf->string = NULL;
+
for (i = 0; i < cf->desc.bNumInterfaces; i++) {
if (cf->intf_cache[i])
kref_put(&cf->intf_cache[i]->ref,
diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c
index a6961efc2cf0c..8b61bcd742cac 100644
--- a/drivers/usb/core/devices.c
+++ b/drivers/usb/core/devices.c
@@ -362,33 +362,21 @@ static char *usb_dump_device_descriptor(char *start, char *end, const struct usb
*/
static char *usb_dump_device_strings (char *start, char *end, struct usb_device *dev)
{
- char *buf;
-
if (start > end)
return start;
- buf = kmalloc(128, GFP_KERNEL);
- if (!buf)
- return start;
- if (dev->descriptor.iManufacturer) {
- if (usb_string(dev, dev->descriptor.iManufacturer, buf, 128) > 0)
- start += sprintf(start, format_string_manufacturer, buf);
- }
+ if (dev->manufacturer)
+ start += sprintf(start, format_string_manufacturer, dev->manufacturer);
if (start > end)
goto out;
- if (dev->descriptor.iProduct) {
- if (usb_string(dev, dev->descriptor.iProduct, buf, 128) > 0)
- start += sprintf(start, format_string_product, buf);
- }
+ if (dev->product)
+ start += sprintf(start, format_string_product, dev->product);
if (start > end)
goto out;
#ifdef ALLOW_SERIAL_NUMBER
- if (dev->descriptor.iSerialNumber) {
- if (usb_string(dev, dev->descriptor.iSerialNumber, buf, 128) > 0)
- start += sprintf(start, format_string_serialnumber, buf);
- }
+ if (dev->serial)
+ start += sprintf(start, format_string_serialnumber, dev->serial);
#endif
out:
- kfree(buf);
return start;
}
@@ -472,7 +460,7 @@ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes, loff_t *ski
return 0;
if (level > MAX_TOPO_LEVEL)
- return total_written;
+ return 0;
/* allocate 2^1 pages = 8K (on i386); should be more than enough for one device */
if (!(pages_start = (char*) __get_free_pages(GFP_KERNEL,1)))
return -ENOMEM;
@@ -539,10 +527,7 @@ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes, loff_t *ski
length = *nbytes;
if (copy_to_user(*buffer, pages_start + *skip_bytes, length)) {
free_pages((unsigned long)pages_start, 1);
-
- if (total_written == 0)
- return -EFAULT;
- return total_written;
+ return -EFAULT;
}
*nbytes -= length;
*file_offset += length;
@@ -620,6 +605,7 @@ static unsigned int usb_device_poll(struct file *file, struct poll_table_struct
/* we may have dropped BKL - need to check for having lost the race */
if (file->private_data) {
kfree(st);
+ st = file->private_data;
goto lost_race;
}
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index a694ce8c2be47..a047bc392983e 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -565,7 +565,7 @@ static int proc_control(struct dev_state *ps, void __user *arg)
return -EINVAL;
if (!(tbuf = (unsigned char *)__get_free_page(GFP_KERNEL)))
return -ENOMEM;
- tmo = (ctrl.timeout * HZ + 999) / 1000;
+ tmo = ctrl.timeout;
if (ctrl.bRequestType & 0x80) {
if (ctrl.wLength && !access_ok(VERIFY_WRITE, ctrl.data, ctrl.wLength)) {
free_page((unsigned long)tbuf);
@@ -646,7 +646,7 @@ static int proc_bulk(struct dev_state *ps, void __user *arg)
return -EINVAL;
if (!(tbuf = kmalloc(len1, GFP_KERNEL)))
return -ENOMEM;
- tmo = (bulk.timeout * HZ + 999) / 1000;
+ tmo = bulk.timeout;
if (bulk.ep & 0x80) {
if (len1 && !access_ok(VERIFY_WRITE, bulk.data, len1)) {
kfree(tbuf);
@@ -673,11 +673,8 @@ static int proc_bulk(struct dev_state *ps, void __user *arg)
usb_lock_device(dev);
}
kfree(tbuf);
- if (i < 0) {
- dev_warn(&dev->dev, "usbfs: USBDEVFS_BULK failed "
- "ep 0x%x len %u ret %d\n", bulk.ep, bulk.len, i);
+ if (i < 0)
return i;
- }
return len2;
}
@@ -816,9 +813,11 @@ static int proc_setconfig(struct dev_state *ps, void __user *arg)
return status;
}
-static int proc_submiturb(struct dev_state *ps, void __user *arg)
+
+static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
+ struct usbdevfs_iso_packet_desc __user *iso_frame_desc,
+ void __user *arg)
{
- struct usbdevfs_urb uurb;
struct usbdevfs_iso_packet_desc *isopkt = NULL;
struct usb_host_endpoint *ep;
struct async *as;
@@ -826,42 +825,40 @@ static int proc_submiturb(struct dev_state *ps, void __user *arg)
unsigned int u, totlen, isofrmlen;
int ret, interval = 0, ifnum = -1;
- if (copy_from_user(&uurb, arg, sizeof(uurb)))
- return -EFAULT;
- if (uurb.flags & ~(USBDEVFS_URB_ISO_ASAP|USBDEVFS_URB_SHORT_NOT_OK|
+ if (uurb->flags & ~(USBDEVFS_URB_ISO_ASAP|USBDEVFS_URB_SHORT_NOT_OK|
URB_NO_FSBR|URB_ZERO_PACKET))
return -EINVAL;
- if (!uurb.buffer)
+ if (!uurb->buffer)
return -EINVAL;
- if (uurb.signr != 0 && (uurb.signr < SIGRTMIN || uurb.signr > SIGRTMAX))
+ if (uurb->signr != 0 && (uurb->signr < SIGRTMIN || uurb->signr > SIGRTMAX))
return -EINVAL;
- if (!(uurb.type == USBDEVFS_URB_TYPE_CONTROL && (uurb.endpoint & ~USB_ENDPOINT_DIR_MASK) == 0)) {
- if ((ifnum = findintfep(ps->dev, uurb.endpoint)) < 0)
+ if (!(uurb->type == USBDEVFS_URB_TYPE_CONTROL && (uurb->endpoint & ~USB_ENDPOINT_DIR_MASK) == 0)) {
+ if ((ifnum = findintfep(ps->dev, uurb->endpoint)) < 0)
return ifnum;
if ((ret = checkintf(ps, ifnum)))
return ret;
}
- if ((uurb.endpoint & ~USB_ENDPOINT_DIR_MASK) != 0)
- ep = ps->dev->ep_in [uurb.endpoint & USB_ENDPOINT_NUMBER_MASK];
+ if ((uurb->endpoint & USB_ENDPOINT_DIR_MASK) != 0)
+ ep = ps->dev->ep_in [uurb->endpoint & USB_ENDPOINT_NUMBER_MASK];
else
- ep = ps->dev->ep_out [uurb.endpoint & USB_ENDPOINT_NUMBER_MASK];
+ ep = ps->dev->ep_out [uurb->endpoint & USB_ENDPOINT_NUMBER_MASK];
if (!ep)
return -ENOENT;
- switch(uurb.type) {
+ switch(uurb->type) {
case USBDEVFS_URB_TYPE_CONTROL:
if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
!= USB_ENDPOINT_XFER_CONTROL)
return -EINVAL;
/* min 8 byte setup packet, max arbitrary */
- if (uurb.buffer_length < 8 || uurb.buffer_length > PAGE_SIZE)
+ if (uurb->buffer_length < 8 || uurb->buffer_length > PAGE_SIZE)
return -EINVAL;
if (!(dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL)))
return -ENOMEM;
- if (copy_from_user(dr, uurb.buffer, 8)) {
+ if (copy_from_user(dr, uurb->buffer, 8)) {
kfree(dr);
return -EFAULT;
}
- if (uurb.buffer_length < (le16_to_cpup(&dr->wLength) + 8)) {
+ if (uurb->buffer_length < (le16_to_cpup(&dr->wLength) + 8)) {
kfree(dr);
return -EINVAL;
}
@@ -869,11 +866,11 @@ static int proc_submiturb(struct dev_state *ps, void __user *arg)
kfree(dr);
return ret;
}
- uurb.endpoint = (uurb.endpoint & ~USB_ENDPOINT_DIR_MASK) | (dr->bRequestType & USB_ENDPOINT_DIR_MASK);
- uurb.number_of_packets = 0;
- uurb.buffer_length = le16_to_cpup(&dr->wLength);
- uurb.buffer += 8;
- if (!access_ok((uurb.endpoint & USB_DIR_IN) ? VERIFY_WRITE : VERIFY_READ, uurb.buffer, uurb.buffer_length)) {
+ uurb->endpoint = (uurb->endpoint & ~USB_ENDPOINT_DIR_MASK) | (dr->bRequestType & USB_ENDPOINT_DIR_MASK);
+ uurb->number_of_packets = 0;
+ uurb->buffer_length = le16_to_cpup(&dr->wLength);
+ uurb->buffer += 8;
+ if (!access_ok((uurb->endpoint & USB_DIR_IN) ? VERIFY_WRITE : VERIFY_READ, uurb->buffer, uurb->buffer_length)) {
kfree(dr);
return -EFAULT;
}
@@ -886,29 +883,29 @@ static int proc_submiturb(struct dev_state *ps, void __user *arg)
return -EINVAL;
/* allow single-shot interrupt transfers, at bogus rates */
}
- uurb.number_of_packets = 0;
- if (uurb.buffer_length > MAX_USBFS_BUFFER_SIZE)
+ uurb->number_of_packets = 0;
+ if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE)
return -EINVAL;
- if (!access_ok((uurb.endpoint & USB_DIR_IN) ? VERIFY_WRITE : VERIFY_READ, uurb.buffer, uurb.buffer_length))
+ if (!access_ok((uurb->endpoint & USB_DIR_IN) ? VERIFY_WRITE : VERIFY_READ, uurb->buffer, uurb->buffer_length))
return -EFAULT;
break;
case USBDEVFS_URB_TYPE_ISO:
/* arbitrary limit */
- if (uurb.number_of_packets < 1 || uurb.number_of_packets > 128)
+ if (uurb->number_of_packets < 1 || uurb->number_of_packets > 128)
return -EINVAL;
if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
!= USB_ENDPOINT_XFER_ISOC)
return -EINVAL;
interval = 1 << min (15, ep->desc.bInterval - 1);
- isofrmlen = sizeof(struct usbdevfs_iso_packet_desc) * uurb.number_of_packets;
+ isofrmlen = sizeof(struct usbdevfs_iso_packet_desc) * uurb->number_of_packets;
if (!(isopkt = kmalloc(isofrmlen, GFP_KERNEL)))
return -ENOMEM;
- if (copy_from_user(isopkt, &((struct usbdevfs_urb __user *)arg)->iso_frame_desc, isofrmlen)) {
+ if (copy_from_user(isopkt, iso_frame_desc, isofrmlen)) {
kfree(isopkt);
return -EFAULT;
}
- for (totlen = u = 0; u < uurb.number_of_packets; u++) {
+ for (totlen = u = 0; u < uurb->number_of_packets; u++) {
if (isopkt[u].length > 1023) {
kfree(isopkt);
return -EINVAL;
@@ -919,11 +916,11 @@ static int proc_submiturb(struct dev_state *ps, void __user *arg)
kfree(isopkt);
return -EINVAL;
}
- uurb.buffer_length = totlen;
+ uurb->buffer_length = totlen;
break;
case USBDEVFS_URB_TYPE_INTERRUPT:
- uurb.number_of_packets = 0;
+ uurb->number_of_packets = 0;
if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
!= USB_ENDPOINT_XFER_INT)
return -EINVAL;
@@ -931,23 +928,23 @@ static int proc_submiturb(struct dev_state *ps, void __user *arg)
interval = 1 << min (15, ep->desc.bInterval - 1);
else
interval = ep->desc.bInterval;
- if (uurb.buffer_length > MAX_USBFS_BUFFER_SIZE)
+ if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE)
return -EINVAL;
- if (!access_ok((uurb.endpoint & USB_DIR_IN) ? VERIFY_WRITE : VERIFY_READ, uurb.buffer, uurb.buffer_length))
+ if (!access_ok((uurb->endpoint & USB_DIR_IN) ? VERIFY_WRITE : VERIFY_READ, uurb->buffer, uurb->buffer_length))
return -EFAULT;
break;
default:
return -EINVAL;
}
- if (!(as = alloc_async(uurb.number_of_packets))) {
+ if (!(as = alloc_async(uurb->number_of_packets))) {
if (isopkt)
kfree(isopkt);
if (dr)
kfree(dr);
return -ENOMEM;
}
- if (!(as->urb->transfer_buffer = kmalloc(uurb.buffer_length, GFP_KERNEL))) {
+ if (!(as->urb->transfer_buffer = kmalloc(uurb->buffer_length, GFP_KERNEL))) {
if (isopkt)
kfree(isopkt);
if (dr)
@@ -956,16 +953,16 @@ static int proc_submiturb(struct dev_state *ps, void __user *arg)
return -ENOMEM;
}
as->urb->dev = ps->dev;
- as->urb->pipe = (uurb.type << 30) | __create_pipe(ps->dev, uurb.endpoint & 0xf) | (uurb.endpoint & USB_DIR_IN);
- as->urb->transfer_flags = uurb.flags;
- as->urb->transfer_buffer_length = uurb.buffer_length;
+ as->urb->pipe = (uurb->type << 30) | __create_pipe(ps->dev, uurb->endpoint & 0xf) | (uurb->endpoint & USB_DIR_IN);
+ as->urb->transfer_flags = uurb->flags;
+ as->urb->transfer_buffer_length = uurb->buffer_length;
as->urb->setup_packet = (unsigned char*)dr;
- as->urb->start_frame = uurb.start_frame;
- as->urb->number_of_packets = uurb.number_of_packets;
+ as->urb->start_frame = uurb->start_frame;
+ as->urb->number_of_packets = uurb->number_of_packets;
as->urb->interval = interval;
as->urb->context = as;
as->urb->complete = async_completed;
- for (totlen = u = 0; u < uurb.number_of_packets; u++) {
+ for (totlen = u = 0; u < uurb->number_of_packets; u++) {
as->urb->iso_frame_desc[u].offset = totlen;
as->urb->iso_frame_desc[u].length = isopkt[u].length;
totlen += isopkt[u].length;
@@ -974,15 +971,15 @@ static int proc_submiturb(struct dev_state *ps, void __user *arg)
kfree(isopkt);
as->ps = ps;
as->userurb = arg;
- if (uurb.endpoint & USB_DIR_IN)
- as->userbuffer = uurb.buffer;
+ if (uurb->endpoint & USB_DIR_IN)
+ as->userbuffer = uurb->buffer;
else
as->userbuffer = NULL;
- as->signr = uurb.signr;
+ as->signr = uurb->signr;
as->ifnum = ifnum;
as->task = current;
- if (!(uurb.endpoint & USB_DIR_IN)) {
- if (copy_from_user(as->urb->transfer_buffer, uurb.buffer, as->urb->transfer_buffer_length)) {
+ if (!(uurb->endpoint & USB_DIR_IN)) {
+ if (copy_from_user(as->urb->transfer_buffer, uurb->buffer, as->urb->transfer_buffer_length)) {
free_async(as);
return -EFAULT;
}
@@ -997,6 +994,16 @@ static int proc_submiturb(struct dev_state *ps, void __user *arg)
return 0;
}
+static int proc_submiturb(struct dev_state *ps, void __user *arg)
+{
+ struct usbdevfs_urb uurb;
+
+ if (copy_from_user(&uurb, arg, sizeof(uurb)))
+ return -EFAULT;
+
+ return proc_do_submiturb(ps, &uurb, (((struct usbdevfs_urb __user *)arg)->iso_frame_desc), arg);
+}
+
static int proc_unlinkurb(struct dev_state *ps, void __user *arg)
{
struct async *as;
@@ -1008,10 +1015,11 @@ static int proc_unlinkurb(struct dev_state *ps, void __user *arg)
return 0;
}
-static int processcompl(struct async *as)
+static int processcompl(struct async *as, void __user * __user *arg)
{
struct urb *urb = as->urb;
struct usbdevfs_urb __user *userurb = as->userurb;
+ void __user *addr = as->userurb;
unsigned int i;
if (as->userbuffer)
@@ -1034,16 +1042,19 @@ static int processcompl(struct async *as)
&userurb->iso_frame_desc[i].status))
return -EFAULT;
}
+
+ free_async(as);
+
+ if (put_user(addr, (void __user * __user *)arg))
+ return -EFAULT;
return 0;
}
-static int proc_reapurb(struct dev_state *ps, void __user *arg)
+static struct async* reap_as(struct dev_state *ps)
{
DECLARE_WAITQUEUE(wait, current);
struct async *as = NULL;
- void __user *addr;
struct usb_device *dev = ps->dev;
- int ret;
add_wait_queue(&ps->wait, &wait);
for (;;) {
@@ -1058,16 +1069,14 @@ static int proc_reapurb(struct dev_state *ps, void __user *arg)
}
remove_wait_queue(&ps->wait, &wait);
set_current_state(TASK_RUNNING);
- if (as) {
- ret = processcompl(as);
- addr = as->userurb;
- free_async(as);
- if (ret)
- return ret;
- if (put_user(addr, (void __user * __user *)arg))
- return -EFAULT;
- return 0;
- }
+ return as;
+}
+
+static int proc_reapurb(struct dev_state *ps, void __user *arg)
+{
+ struct async *as = reap_as(ps);
+ if (as)
+ return processcompl(as, (void __user * __user *)arg);
if (signal_pending(current))
return -EINTR;
return -EIO;
@@ -1076,21 +1085,107 @@ static int proc_reapurb(struct dev_state *ps, void __user *arg)
static int proc_reapurbnonblock(struct dev_state *ps, void __user *arg)
{
struct async *as;
- void __user *addr;
- int ret;
if (!(as = async_getcompleted(ps)))
return -EAGAIN;
- ret = processcompl(as);
- addr = as->userurb;
+ return processcompl(as, (void __user * __user *)arg);
+}
+
+#ifdef CONFIG_COMPAT
+
+static int get_urb32(struct usbdevfs_urb *kurb,
+ struct usbdevfs_urb32 __user *uurb)
+{
+ __u32 uptr;
+ if (get_user(kurb->type, &uurb->type) ||
+ __get_user(kurb->endpoint, &uurb->endpoint) ||
+ __get_user(kurb->status, &uurb->status) ||
+ __get_user(kurb->flags, &uurb->flags) ||
+ __get_user(kurb->buffer_length, &uurb->buffer_length) ||
+ __get_user(kurb->actual_length, &uurb->actual_length) ||
+ __get_user(kurb->start_frame, &uurb->start_frame) ||
+ __get_user(kurb->number_of_packets, &uurb->number_of_packets) ||
+ __get_user(kurb->error_count, &uurb->error_count) ||
+ __get_user(kurb->signr, &uurb->signr))
+ return -EFAULT;
+
+ if (__get_user(uptr, &uurb->buffer))
+ return -EFAULT;
+ kurb->buffer = compat_ptr(uptr);
+ if (__get_user(uptr, &uurb->buffer))
+ return -EFAULT;
+ kurb->usercontext = compat_ptr(uptr);
+
+ return 0;
+}
+
+static int proc_submiturb_compat(struct dev_state *ps, void __user *arg)
+{
+ struct usbdevfs_urb uurb;
+
+ if (get_urb32(&uurb,(struct usbdevfs_urb32 *)arg))
+ return -EFAULT;
+
+ return proc_do_submiturb(ps, &uurb, ((struct usbdevfs_urb __user *)arg)->iso_frame_desc, arg);
+}
+
+static int processcompl_compat(struct async *as, void __user * __user *arg)
+{
+ struct urb *urb = as->urb;
+ struct usbdevfs_urb32 __user *userurb = as->userurb;
+ void __user *addr = as->userurb;
+ unsigned int i;
+
+ if (as->userbuffer)
+ if (copy_to_user(as->userbuffer, urb->transfer_buffer, urb->transfer_buffer_length))
+ return -EFAULT;
+ if (put_user(urb->status, &userurb->status))
+ return -EFAULT;
+ if (put_user(urb->actual_length, &userurb->actual_length))
+ return -EFAULT;
+ if (put_user(urb->error_count, &userurb->error_count))
+ return -EFAULT;
+
+ if (!(usb_pipeisoc(urb->pipe)))
+ return 0;
+ for (i = 0; i < urb->number_of_packets; i++) {
+ if (put_user(urb->iso_frame_desc[i].actual_length,
+ &userurb->iso_frame_desc[i].actual_length))
+ return -EFAULT;
+ if (put_user(urb->iso_frame_desc[i].status,
+ &userurb->iso_frame_desc[i].status))
+ return -EFAULT;
+ }
+
free_async(as);
- if (ret)
- return ret;
- if (put_user(addr, (void __user * __user *)arg))
+ if (put_user((u32)(u64)addr, (u32 __user *)arg))
return -EFAULT;
return 0;
}
+static int proc_reapurb_compat(struct dev_state *ps, void __user *arg)
+{
+ struct async *as = reap_as(ps);
+ if (as)
+ return processcompl_compat(as, (void __user * __user *)arg);
+ if (signal_pending(current))
+ return -EINTR;
+ return -EIO;
+}
+
+static int proc_reapurbnonblock_compat(struct dev_state *ps, void __user *arg)
+{
+ struct async *as;
+
+ printk("reapurbnblock\n");
+ if (!(as = async_getcompleted(ps)))
+ return -EAGAIN;
+ printk("reap got as %p\n", as);
+ return processcompl_compat(as, (void __user * __user *)arg);
+}
+
+#endif
+
static int proc_disconnectsignal(struct dev_state *ps, void __user *arg)
{
struct usbdevfs_disconnectsignal ds;
@@ -1302,6 +1397,27 @@ static int usbdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
inode->i_mtime = CURRENT_TIME;
break;
+#ifdef CONFIG_COMPAT
+
+ case USBDEVFS_SUBMITURB32:
+ snoop(&dev->dev, "%s: SUBMITURB32\n", __FUNCTION__);
+ ret = proc_submiturb_compat(ps, p);
+ if (ret >= 0)
+ inode->i_mtime = CURRENT_TIME;
+ break;
+
+ case USBDEVFS_REAPURB32:
+ snoop(&dev->dev, "%s: REAPURB32\n", __FUNCTION__);
+ ret = proc_reapurb_compat(ps, p);
+ break;
+
+ case USBDEVFS_REAPURBNDELAY32:
+ snoop(&dev->dev, "%s: REAPURBDELAY32\n", __FUNCTION__);
+ ret = proc_reapurbnonblock_compat(ps, p);
+ break;
+
+#endif
+
case USBDEVFS_DISCARDURB:
snoop(&dev->dev, "%s: DISCARDURB\n", __FUNCTION__);
ret = proc_unlinkurb(ps, p);
diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c
index db26eda94dbbb..80ce9644d0eea 100644
--- a/drivers/usb/core/file.c
+++ b/drivers/usb/core/file.c
@@ -66,16 +66,7 @@ static struct file_operations usb_fops = {
.open = usb_open,
};
-static void release_usb_class_dev(struct class_device *class_dev)
-{
- dbg("%s - %s", __FUNCTION__, class_dev->class_id);
- kfree(class_dev);
-}
-
-static struct class usb_class = {
- .name = "usb",
- .release = &release_usb_class_dev,
-};
+static struct class_simple *usb_class;
int usb_major_init(void)
{
@@ -87,9 +78,9 @@ int usb_major_init(void)
goto out;
}
- error = class_register(&usb_class);
- if (error) {
- err("class_register failed for usb devices");
+ usb_class = class_simple_create(THIS_MODULE, "usb");
+ if (IS_ERR(usb_class)) {
+ err("class_simple_create failed for usb devices");
unregister_chrdev(USB_MAJOR, "usb");
goto out;
}
@@ -102,18 +93,11 @@ out:
void usb_major_cleanup(void)
{
- class_unregister(&usb_class);
+ class_simple_destroy(usb_class);
devfs_remove("usb");
unregister_chrdev(USB_MAJOR, "usb");
}
-static ssize_t show_dev(struct class_device *class_dev, char *buf)
-{
- int minor = (int)(long)class_get_devdata(class_dev);
- return print_dev_t(buf, MKDEV(USB_MAJOR, minor));
-}
-static CLASS_DEVICE_ATTR(dev, S_IRUGO, show_dev, NULL);
-
/**
* usb_register_dev - register a USB device, and ask for a minor number
* @intf: pointer to the usb_interface that is being registered
@@ -141,7 +125,6 @@ int usb_register_dev(struct usb_interface *intf,
int minor_base = class_driver->minor_base;
int minor = 0;
char name[BUS_ID_SIZE];
- struct class_device *class_dev;
char *temp;
#ifdef CONFIG_USB_DYNAMIC_MINORS
@@ -181,22 +164,18 @@ int usb_register_dev(struct usb_interface *intf,
devfs_mk_cdev(MKDEV(USB_MAJOR, minor), class_driver->mode, name);
/* create a usb class device for this usb interface */
- class_dev = kmalloc(sizeof(*class_dev), GFP_KERNEL);
- if (class_dev) {
- memset(class_dev, 0x00, sizeof(struct class_device));
- class_dev->class = &usb_class;
- class_dev->dev = &intf->dev;
-
- temp = strrchr(name, '/');
- if (temp && (temp[1] != 0x00))
- ++temp;
- else
- temp = name;
- snprintf(class_dev->class_id, BUS_ID_SIZE, "%s", temp);
- class_set_devdata(class_dev, (void *)(long)intf->minor);
- class_device_register(class_dev);
- class_device_create_file(class_dev, &class_device_attr_dev);
- intf->class_dev = class_dev;
+ temp = strrchr(name, '/');
+ if (temp && (temp[1] != 0x00))
+ ++temp;
+ else
+ temp = name;
+ intf->class_dev = class_simple_device_add(usb_class, MKDEV(USB_MAJOR, minor), &intf->dev, "%s", temp);
+ if (IS_ERR(intf->class_dev)) {
+ spin_lock (&minor_lock);
+ usb_minors[intf->minor] = NULL;
+ spin_unlock (&minor_lock);
+ devfs_remove (name);
+ retval = PTR_ERR(intf->class_dev);
}
exit:
return retval;
@@ -239,11 +218,8 @@ void usb_deregister_dev(struct usb_interface *intf,
snprintf(name, BUS_ID_SIZE, class_driver->name, intf->minor - minor_base);
devfs_remove (name);
-
- if (intf->class_dev) {
- class_device_unregister(intf->class_dev);
- intf->class_dev = NULL;
- }
+ class_simple_device_remove(MKDEV(USB_MAJOR, intf->minor));
+ intf->class_dev = NULL;
intf->minor = -1;
}
EXPORT_SYMBOL(usb_deregister_dev);
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
index 7b836ae195308..b9a3dae070363 100644
--- a/drivers/usb/core/hcd-pci.c
+++ b/drivers/usb/core/hcd-pci.c
@@ -56,11 +56,8 @@
int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
{
struct hc_driver *driver;
- unsigned long resource, len;
- void __iomem *base;
struct usb_hcd *hcd;
- int retval, region;
- char buf [8], *bufp = buf;
+ int retval;
if (usb_disabled())
return -ENODEV;
@@ -78,122 +75,75 @@ int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
"Found HC with no IRQ. Check BIOS/PCI %s setup!\n",
pci_name(dev));
retval = -ENODEV;
- goto done;
+ goto err1;
}
-
+
+ hcd = usb_create_hcd (driver, &dev->dev, pci_name(dev));
+ if (!hcd) {
+ retval = -ENOMEM;
+ goto err1;
+ }
+
if (driver->flags & HCD_MEMORY) { // EHCI, OHCI
- region = 0;
- resource = pci_resource_start (dev, 0);
- len = pci_resource_len (dev, 0);
- if (!request_mem_region (resource, len, driver->description)) {
+ hcd->rsrc_start = pci_resource_start (dev, 0);
+ hcd->rsrc_len = pci_resource_len (dev, 0);
+ if (!request_mem_region (hcd->rsrc_start, hcd->rsrc_len,
+ driver->description)) {
dev_dbg (&dev->dev, "controller already in use\n");
retval = -EBUSY;
- goto done;
+ goto err2;
}
- base = ioremap_nocache (resource, len);
- if (base == NULL) {
+ hcd->regs = ioremap_nocache (hcd->rsrc_start, hcd->rsrc_len);
+ if (hcd->regs == NULL) {
dev_dbg (&dev->dev, "error mapping memory\n");
retval = -EFAULT;
-clean_1:
- release_mem_region (resource, len);
- dev_err (&dev->dev, "init %s fail, %d\n",
- pci_name(dev), retval);
- goto done;
+ goto err3;
}
} else { // UHCI
- resource = len = 0;
+ int region;
+
for (region = 0; region < PCI_ROM_RESOURCE; region++) {
- if (!(pci_resource_flags (dev, region) & IORESOURCE_IO))
+ if (!(pci_resource_flags (dev, region) &
+ IORESOURCE_IO))
continue;
- resource = pci_resource_start (dev, region);
- len = pci_resource_len (dev, region);
- if (request_region (resource, len,
+ hcd->rsrc_start = pci_resource_start (dev, region);
+ hcd->rsrc_len = pci_resource_len (dev, region);
+ if (request_region (hcd->rsrc_start, hcd->rsrc_len,
driver->description))
break;
}
if (region == PCI_ROM_RESOURCE) {
dev_dbg (&dev->dev, "no i/o regions available\n");
retval = -EBUSY;
- goto done;
- }
- base = (void __iomem *) resource;
- }
-
- // driver->reset(), later on, will transfer device from
- // control by SMM/BIOS to control by Linux (if needed)
-
- hcd = usb_create_hcd (driver);
- if (hcd == NULL){
- dev_dbg (&dev->dev, "hcd alloc fail\n");
- retval = -ENOMEM;
-clean_2:
- if (driver->flags & HCD_MEMORY) {
- iounmap (base);
- goto clean_1;
- } else {
- release_region (resource, len);
- dev_err (&dev->dev, "init %s fail, %d\n",
- pci_name(dev), retval);
- goto done;
+ goto err1;
}
}
- // hcd zeroed everything
- hcd->regs = base;
- hcd->region = region;
- pci_set_drvdata (dev, hcd);
- hcd->self.bus_name = pci_name(dev);
#ifdef CONFIG_PCI_NAMES
hcd->product_desc = dev->pretty_name;
#endif
- hcd->self.controller = &dev->dev;
-
- if ((retval = hcd_buffer_create (hcd)) != 0) {
-clean_3:
- pci_set_drvdata (dev, NULL);
- usb_put_hcd (hcd);
- goto clean_2;
- }
-
- dev_info (hcd->self.controller, "%s\n", hcd->product_desc);
-
- /* till now HC has been in an indeterminate state ... */
- if (driver->reset && (retval = driver->reset (hcd)) < 0) {
- dev_err (hcd->self.controller, "can't reset\n");
- goto clean_3;
- }
pci_set_master (dev);
-#ifndef __sparc__
- sprintf (buf, "%d", dev->irq);
-#else
- bufp = __irq_itoa(dev->irq);
-#endif
- retval = request_irq (dev->irq, usb_hcd_irq, SA_SHIRQ,
- hcd->driver->description, hcd);
- if (retval != 0) {
- dev_err (hcd->self.controller,
- "request interrupt %s failed\n", bufp);
- goto clean_3;
- }
- hcd->irq = dev->irq;
-
- dev_info (hcd->self.controller, "irq %s, %s 0x%lx\n", bufp,
- (driver->flags & HCD_MEMORY) ? "pci mem" : "io base",
- resource);
-
- usb_register_bus (&hcd->self);
-
- if ((retval = driver->start (hcd)) < 0) {
- dev_err (hcd->self.controller, "init error %d\n", retval);
- usb_hcd_pci_remove (dev);
- }
-done:
+ retval = usb_add_hcd (hcd, dev->irq, SA_SHIRQ);
if (retval != 0)
- pci_disable_device (dev);
+ goto err4;
+ return retval;
+
+ err4:
+ if (driver->flags & HCD_MEMORY) {
+ iounmap (hcd->regs);
+ err3:
+ release_mem_region (hcd->rsrc_start, hcd->rsrc_len);
+ } else
+ release_region (hcd->rsrc_start, hcd->rsrc_len);
+ err2:
+ usb_put_hcd (hcd);
+ err1:
+ pci_disable_device (dev);
+ dev_err (&dev->dev, "init %s fail, %d\n", pci_name(dev), retval);
return retval;
}
EXPORT_SYMBOL (usb_hcd_pci_probe);
@@ -220,34 +170,15 @@ void usb_hcd_pci_remove (struct pci_dev *dev)
hcd = pci_get_drvdata(dev);
if (!hcd)
return;
- dev_info (hcd->self.controller, "remove, state %x\n", hcd->state);
-
- if (in_interrupt ())
- BUG ();
-
- if (HCD_IS_RUNNING (hcd->state))
- hcd->state = USB_STATE_QUIESCING;
- dev_dbg (hcd->self.controller, "roothub graceful disconnect\n");
- usb_disconnect (&hcd->self.root_hub);
-
- hcd->driver->stop (hcd);
- hcd_buffer_destroy (hcd);
- hcd->state = USB_STATE_HALT;
- pci_set_drvdata(dev, NULL);
-
- free_irq (hcd->irq, hcd);
+ usb_remove_hcd (hcd);
if (hcd->driver->flags & HCD_MEMORY) {
iounmap (hcd->regs);
- release_mem_region (pci_resource_start (dev, 0),
- pci_resource_len (dev, 0));
+ release_mem_region (hcd->rsrc_start, hcd->rsrc_len);
} else {
- release_region (pci_resource_start (dev, hcd->region),
- pci_resource_len (dev, hcd->region));
+ release_region (hcd->rsrc_start, hcd->rsrc_len);
}
-
- usb_deregister_bus (&hcd->self);
-
+ usb_put_hcd (hcd);
pci_disable_device(dev);
}
EXPORT_SYMBOL (usb_hcd_pci_remove);
@@ -295,8 +226,8 @@ int usb_hcd_pci_suspend (struct pci_dev *dev, u32 state)
/* entry if root hub wasn't yet suspended ... from sysfs,
* without autosuspend, or if USB_SUSPEND isn't configured.
*/
- case USB_STATE_RUNNING:
- hcd->state = USB_STATE_QUIESCING;
+ case HC_STATE_RUNNING:
+ hcd->state = HC_STATE_QUIESCING;
retval = hcd->driver->suspend (hcd, state);
if (retval) {
dev_dbg (hcd->self.controller,
@@ -304,7 +235,7 @@ int usb_hcd_pci_suspend (struct pci_dev *dev, u32 state)
retval);
break;
}
- hcd->state = HCD_STATE_SUSPENDED;
+ hcd->state = HC_STATE_SUSPENDED;
/* FALLTHROUGH */
/* entry with CONFIG_USB_SUSPEND, or hcds that autosuspend: the
@@ -314,7 +245,7 @@ int usb_hcd_pci_suspend (struct pci_dev *dev, u32 state)
* FIXME only CONFIG_USB_SUSPEND guarantees hub_suspend() will
* have been called, otherwise root hub timers still run ...
*/
- case HCD_STATE_SUSPENDED:
+ case HC_STATE_SUSPENDED:
if (state <= dev->current_state)
break;
@@ -380,7 +311,7 @@ int usb_hcd_pci_resume (struct pci_dev *dev)
int has_pci_pm;
hcd = pci_get_drvdata(dev);
- if (hcd->state != HCD_STATE_SUSPENDED) {
+ if (hcd->state != HC_STATE_SUSPENDED) {
dev_dbg (hcd->self.controller,
"can't resume, not suspended!\n");
return 0;
@@ -392,7 +323,7 @@ int usb_hcd_pci_resume (struct pci_dev *dev)
pci_state(dev->current_state),
has_pci_pm ? "" : " (legacy)");
- hcd->state = USB_STATE_RESUMING;
+ hcd->state = HC_STATE_RESUMING;
if (has_pci_pm)
pci_set_power_state (dev, 0);
@@ -412,7 +343,7 @@ int usb_hcd_pci_resume (struct pci_dev *dev)
#endif
retval = hcd->driver->resume (hcd);
- if (!HCD_IS_RUNNING (hcd->state)) {
+ if (!HC_IS_RUNNING (hcd->state)) {
dev_dbg (hcd->self.controller,
"resume fail, retval %d\n", retval);
usb_hc_died (hcd);
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index b87aa7c06e0c6..266e9e06a9f50 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -46,6 +46,7 @@
#include "usb.h"
#include "hcd.h"
+#include "hub.h"
// #define USB_BANDWIDTH_MESSAGES
@@ -87,6 +88,7 @@
/* host controllers we manage */
LIST_HEAD (usb_bus_list);
+EXPORT_SYMBOL_GPL (usb_bus_list);
/* used when allocating bus numbers */
#define USB_MAXBUS 64
@@ -97,6 +99,10 @@ static struct usb_busmap busmap;
/* used when updating list of hcds */
DECLARE_MUTEX (usb_bus_list_lock); /* exported only for usbfs */
+EXPORT_SYMBOL_GPL (usb_bus_list_lock);
+
+/* used for controlling access to virtual root hubs */
+static DEFINE_SPINLOCK(hcd_root_hub_lock);
/* used when updating hcd data */
static DEFINE_SPINLOCK(hcd_data_lock);
@@ -272,6 +278,10 @@ static int ascii2utf (char *s, u8 *utf, int utfmax)
*utf++ = *s++;
*utf++ = 0;
}
+ if (utfmax > 0) {
+ *utf = *s;
+ ++retval;
+ }
return retval;
}
@@ -296,30 +306,40 @@ static int rh_string (
// language ids
if (id == 0) {
- *data++ = 4; *data++ = 3; /* 4 bytes string data */
- *data++ = 0x09; *data++ = 0x04; /* MSFT-speak for "en-us" */
- return 4;
+ buf[0] = 4; buf[1] = 3; /* 4 bytes string data */
+ buf[2] = 0x09; buf[3] = 0x04; /* MSFT-speak for "en-us" */
+ len = min (len, 4);
+ memcpy (data, buf, len);
+ return len;
// serial number
} else if (id == 1) {
- strcpy (buf, hcd->self.bus_name);
+ strlcpy (buf, hcd->self.bus_name, sizeof buf);
// product description
} else if (id == 2) {
- strcpy (buf, hcd->product_desc);
+ strlcpy (buf, hcd->product_desc, sizeof buf);
// id 3 == vendor description
} else if (id == 3) {
- sprintf (buf, "%s %s %s", system_utsname.sysname,
+ snprintf (buf, sizeof buf, "%s %s %s", system_utsname.sysname,
system_utsname.release, hcd->driver->description);
// unsupported IDs --> "protocol stall"
} else
- return 0;
+ return -EPIPE;
- data [0] = 2 * (strlen (buf) + 1);
- data [1] = 3; /* type == string */
- return 2 + ascii2utf (buf, data + 2, len - 2);
+ switch (len) { /* All cases fall through */
+ default:
+ len = 2 + ascii2utf (buf, data + 2, len - 2);
+ case 2:
+ data [1] = 3; /* type == string */
+ case 1:
+ data [0] = 2 * (strlen (buf) + 1);
+ case 0:
+ ; /* Compiler wants a statement here */
+ }
+ return len;
}
@@ -328,11 +348,14 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
{
struct usb_ctrlrequest *cmd;
u16 typeReq, wValue, wIndex, wLength;
- const u8 *bufp = NULL;
u8 *ubuf = urb->transfer_buffer;
+ u8 tbuf [sizeof (struct usb_hub_descriptor)];
+ const u8 *bufp = tbuf;
int len = 0;
int patch_wakeup = 0;
unsigned long flags;
+ int status = 0;
+ int n;
cmd = (struct usb_ctrlrequest *) urb->setup_packet;
typeReq = (cmd->bRequestType << 8) | cmd->bRequest;
@@ -343,17 +366,16 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
if (wLength > urb->transfer_buffer_length)
goto error;
- /* set up for success */
- urb->status = 0;
- urb->actual_length = wLength;
+ urb->actual_length = 0;
switch (typeReq) {
/* DEVICE REQUESTS */
case DeviceRequest | USB_REQ_GET_STATUS:
- ubuf [0] = (hcd->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP)
+ tbuf [0] = (hcd->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP)
| (1 << USB_DEVICE_SELF_POWERED);
- ubuf [1] = 0;
+ tbuf [1] = 0;
+ len = 2;
break;
case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
if (wValue == USB_DEVICE_REMOTE_WAKEUP)
@@ -368,7 +390,8 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
goto error;
break;
case DeviceRequest | USB_REQ_GET_CONFIGURATION:
- ubuf [0] = 1;
+ tbuf [0] = 1;
+ len = 1;
/* FALLTHROUGH */
case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
break;
@@ -395,16 +418,18 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
patch_wakeup = 1;
break;
case USB_DT_STRING << 8:
- urb->actual_length = rh_string (
- wValue & 0xff, hcd,
- ubuf, wLength);
+ n = rh_string (wValue & 0xff, hcd, ubuf, wLength);
+ if (n < 0)
+ goto error;
+ urb->actual_length = n;
break;
default:
goto error;
}
break;
case DeviceRequest | USB_REQ_GET_INTERFACE:
- ubuf [0] = 0;
+ tbuf [0] = 0;
+ len = 1;
/* FALLTHROUGH */
case DeviceOutRequest | USB_REQ_SET_INTERFACE:
break;
@@ -420,8 +445,9 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
case EndpointRequest | USB_REQ_GET_STATUS:
// ENDPOINT_HALT flag
- ubuf [0] = 0;
- ubuf [1] = 0;
+ tbuf [0] = 0;
+ tbuf [1] = 0;
+ len = 2;
/* FALLTHROUGH */
case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
case EndpointOutRequest | USB_REQ_SET_FEATURE:
@@ -432,20 +458,31 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
default:
/* non-generic request */
- if (HCD_IS_SUSPENDED (hcd->state))
- urb->status = -EAGAIN;
- else
- urb->status = hcd->driver->hub_control (hcd,
+ if (HC_IS_SUSPENDED (hcd->state))
+ status = -EAGAIN;
+ else {
+ switch (typeReq) {
+ case GetHubStatus:
+ case GetPortStatus:
+ len = 4;
+ break;
+ case GetHubDescriptor:
+ len = sizeof (struct usb_hub_descriptor);
+ break;
+ }
+ status = hcd->driver->hub_control (hcd,
typeReq, wValue, wIndex,
- ubuf, wLength);
+ tbuf, wLength);
+ }
break;
error:
/* "protocol stall" on error */
- urb->status = -EPIPE;
+ status = -EPIPE;
}
- if (urb->status) {
- urb->actual_length = 0;
- if (urb->status != -EPIPE) {
+
+ if (status) {
+ len = 0;
+ if (status != -EPIPE) {
dev_dbg (hcd->self.controller,
"CTRL: TypeReq=0x%x val=0x%x "
"idx=0x%x len=%d ==> %d\n",
@@ -453,7 +490,7 @@ error:
wLength, urb->status);
}
}
- if (bufp) {
+ if (len) {
if (urb->transfer_buffer_length < len)
len = urb->transfer_buffer_length;
urb->actual_length = len;
@@ -461,13 +498,19 @@ error:
memcpy (ubuf, bufp, len);
/* report whether RH hardware supports remote wakeup */
- if (patch_wakeup)
+ if (patch_wakeup &&
+ len > offsetof (struct usb_config_descriptor,
+ bmAttributes))
((struct usb_config_descriptor *)ubuf)->bmAttributes
|= USB_CONFIG_ATT_WAKEUP;
}
/* any errors get returned through the urb completion */
local_irq_save (flags);
+ spin_lock (&urb->lock);
+ if (urb->status == -EINPROGRESS)
+ urb->status = status;
+ spin_unlock (&urb->lock);
usb_hcd_giveback_urb (hcd, urb, NULL);
local_irq_restore (flags);
return 0;
@@ -661,7 +704,7 @@ void usb_host_cleanup(void)
* This code is used to initialize a usb_bus structure, memory for which is
* separately managed.
*/
-void usb_bus_init (struct usb_bus *bus)
+static void usb_bus_init (struct usb_bus *bus)
{
memset (&bus->devmap, 0, sizeof(struct usb_devmap));
@@ -679,7 +722,6 @@ void usb_bus_init (struct usb_bus *bus)
class_device_initialize(&bus->class_dev);
bus->class_dev.class = &usb_host_class;
}
-EXPORT_SYMBOL (usb_bus_init);
/**
* usb_alloc_bus - creates a new USB host controller structure
@@ -705,7 +747,6 @@ struct usb_bus *usb_alloc_bus (struct usb_operations *op)
bus->op = op;
return bus;
}
-EXPORT_SYMBOL (usb_alloc_bus);
/*-------------------------------------------------------------------------*/
@@ -717,7 +758,7 @@ EXPORT_SYMBOL (usb_alloc_bus);
* Assigns a bus number, and links the controller into usbcore data
* structures so that it can be seen by scanning the bus list.
*/
-int usb_register_bus(struct usb_bus *bus)
+static int usb_register_bus(struct usb_bus *bus)
{
int busnum;
int retval;
@@ -747,11 +788,11 @@ int usb_register_bus(struct usb_bus *bus)
up (&usb_bus_list_lock);
usbfs_add_bus (bus);
+ usbmon_notify_bus_add (bus);
dev_info (bus->controller, "new USB bus registered, assigned bus number %d\n", bus->busnum);
return 0;
}
-EXPORT_SYMBOL (usb_register_bus);
/**
* usb_deregister_bus - deregisters the USB host controller
@@ -761,7 +802,7 @@ EXPORT_SYMBOL (usb_register_bus);
* Recycles the bus number, and unlinks the controller from usbcore data
* structures so that it won't be seen by scanning the bus list.
*/
-void usb_deregister_bus (struct usb_bus *bus)
+static void usb_deregister_bus (struct usb_bus *bus)
{
dev_info (bus->controller, "USB bus %d deregistered\n", bus->busnum);
@@ -774,18 +815,18 @@ void usb_deregister_bus (struct usb_bus *bus)
list_del (&bus->bus_list);
up (&usb_bus_list_lock);
+ usbmon_notify_bus_remove (bus);
usbfs_remove_bus (bus);
clear_bit (bus->busnum, busmap.busmap);
- class_device_unregister(&bus->class_dev);
+ class_device_del(&bus->class_dev);
}
-EXPORT_SYMBOL (usb_deregister_bus);
/**
- * usb_register_root_hub - called by HCD to register its root hub
+ * usb_hcd_register_root_hub - called by HCD to register its root hub
* @usb_dev: the usb root hub device to be registered.
- * @parent_dev: the parent device of this root hub.
+ * @hcd: host controller for this root hub
*
* The USB host controller calls this function to register the root hub
* properly with the USB subsystem. It sets up the device properly in
@@ -793,11 +834,20 @@ EXPORT_SYMBOL (usb_deregister_bus);
* then calls usb_new_device() to register the usb device. It also
* assigns the root hub's USB address (always 1).
*/
-int usb_register_root_hub (struct usb_device *usb_dev, struct device *parent_dev)
+int usb_hcd_register_root_hub (struct usb_device *usb_dev, struct usb_hcd *hcd)
{
+ struct device *parent_dev = hcd->self.controller;
const int devnum = 1;
int retval;
+ /* hcd->driver->start() reported can_wakeup, probably with
+ * assistance from board's boot firmware.
+ * NOTE: normal devices won't enable wakeup by default.
+ */
+ if (hcd->can_wakeup)
+ dev_dbg (parent_dev, "supports USB remote wakeup\n");
+ hcd->remote_wakeup = hcd->can_wakeup;
+
usb_dev->devnum = devnum;
usb_dev->bus->devnum_next = devnum + 1;
memset (&usb_dev->bus->devmap.devicemap, 0,
@@ -827,9 +877,20 @@ int usb_register_root_hub (struct usb_device *usb_dev, struct device *parent_dev
usb_dev->dev.bus_id, retval);
}
up (&usb_bus_list_lock);
+
+ if (retval == 0) {
+ spin_lock_irq (&hcd_root_hub_lock);
+ hcd->rh_registered = 1;
+ spin_unlock_irq (&hcd_root_hub_lock);
+
+ /* Did the HC die before the root hub was registered? */
+ if (hcd->state == HC_STATE_HALT)
+ usb_hc_died (hcd); /* This time clean up */
+ }
+
return retval;
}
-EXPORT_SYMBOL (usb_register_root_hub);
+EXPORT_SYMBOL_GPL(usb_hcd_register_root_hub);
/*-------------------------------------------------------------------------*/
@@ -1049,19 +1110,10 @@ static int hcd_submit_urb (struct urb *urb, int mem_flags)
struct usb_host_endpoint *ep;
unsigned long flags;
- ep = (usb_pipein(urb->pipe) ? urb->dev->ep_in : urb->dev->ep_out)
- [usb_pipeendpoint(urb->pipe)];
- if (!hcd || !ep)
+ if (!hcd)
return -ENODEV;
- /*
- * FIXME: make urb timeouts be generic, keeping the HCD cores
- * as simple as possible.
- */
-
- // NOTE: a generic device/urb monitoring hook would go here.
- // hcd_monitor_hook(MONITOR_URB_SUBMIT, urb)
- // It would catch submission paths for all urbs.
+ usbmon_urb_submit(&hcd->self, urb);
/*
* Atomically queue the urb, first to our records, then to the HCD.
@@ -1072,11 +1124,15 @@ static int hcd_submit_urb (struct urb *urb, int mem_flags)
// FIXME: verify that quiescing hc works right (RH cleans up)
spin_lock_irqsave (&hcd_data_lock, flags);
- if (unlikely (urb->reject))
+ ep = (usb_pipein(urb->pipe) ? urb->dev->ep_in : urb->dev->ep_out)
+ [usb_pipeendpoint(urb->pipe)];
+ if (unlikely (!ep))
+ status = -ENOENT;
+ else if (unlikely (urb->reject))
status = -EPERM;
else switch (hcd->state) {
- case USB_STATE_RUNNING:
- case USB_STATE_RESUMING:
+ case HC_STATE_RUNNING:
+ case HC_STATE_RESUMING:
usb_get_dev (urb->dev);
list_add_tail (&urb->urb_list, &ep->urb_list);
status = 0;
@@ -1088,6 +1144,7 @@ static int hcd_submit_urb (struct urb *urb, int mem_flags)
spin_unlock_irqrestore (&hcd_data_lock, flags);
if (status) {
INIT_LIST_HEAD (&urb->urb_list);
+ usbmon_urb_submit_error(&hcd->self, urb, status);
return status;
}
@@ -1104,8 +1161,6 @@ static int hcd_submit_urb (struct urb *urb, int mem_flags)
* valid and usb_buffer_{sync,unmap}() not be needed, since
* they could clobber root hub response data.
*/
- urb->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP
- | URB_NO_SETUP_DMA_MAP);
status = rh_urb_enqueue (hcd, urb);
goto done;
}
@@ -1140,6 +1195,7 @@ done:
if (urb->reject)
wake_up (&usb_kill_urb_queue);
usb_put_urb (urb);
+ usbmon_urb_submit_error(&hcd->self, urb, status);
}
return status;
}
@@ -1150,7 +1206,7 @@ done:
static int hcd_get_frame_number (struct usb_device *udev)
{
struct usb_hcd *hcd = (struct usb_hcd *)udev->bus->hcpriv;
- if (!HCD_IS_RUNNING (hcd->state))
+ if (!HC_IS_RUNNING (hcd->state))
return -ESHUTDOWN;
return hcd->driver->get_frame_number (hcd);
}
@@ -1232,7 +1288,7 @@ static int hcd_unlink_urb (struct urb *urb, int status)
* halted ~= no unlink handshake is needed
* suspended, resuming == should never happen
*/
- WARN_ON (!HCD_IS_RUNNING (hcd->state) && hcd->state != USB_STATE_HALT);
+ WARN_ON (!HC_IS_RUNNING (hcd->state) && hcd->state != HC_STATE_HALT);
/* insist the urb is still queued */
list_for_each(tmp, &ep->urb_list) {
@@ -1299,7 +1355,7 @@ hcd_endpoint_disable (struct usb_device *udev, struct usb_host_endpoint *ep)
hcd = udev->bus->hcpriv;
- WARN_ON (!HCD_IS_RUNNING (hcd->state) && hcd->state != USB_STATE_HALT);
+ WARN_ON (!HC_IS_RUNNING (hcd->state) && hcd->state != HC_STATE_HALT);
local_irq_disable ();
@@ -1386,7 +1442,31 @@ static int hcd_hub_resume (struct usb_bus *bus)
return 0;
}
+/**
+ * usb_hcd_resume_root_hub - called by HCD to resume its root hub
+ * @hcd: host controller for this root hub
+ *
+ * The USB host controller calls this function when its root hub is
+ * suspended (with the remote wakeup feature enabled) and a remote
+ * wakeup request is received. It queues a request for khubd to
+ * resume the root hub.
+ */
+void usb_hcd_resume_root_hub (struct usb_hcd *hcd)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave (&hcd_root_hub_lock, flags);
+ if (hcd->rh_registered)
+ usb_resume_root_hub (hcd->self.root_hub);
+ spin_unlock_irqrestore (&hcd_root_hub_lock, flags);
+}
+
+#else
+void usb_hcd_resume_root_hub (struct usb_hcd *hcd)
+{
+}
#endif
+EXPORT_SYMBOL_GPL(usb_hcd_resume_root_hub);
/*-------------------------------------------------------------------------*/
@@ -1395,7 +1475,7 @@ static int hcd_hub_resume (struct usb_bus *bus)
/**
* usb_bus_start_enum - start immediate enumeration (for OTG)
* @bus: the bus (must use hcd framework)
- * @port: 1-based number of port; usually bus->otg_port
+ * @port_num: 1-based number of port; usually bus->otg_port
* Context: in_interrupt()
*
* Starts enumeration, with an immediate reset followed later by
@@ -1462,14 +1542,13 @@ static struct usb_operations usb_hcd_operations = {
*/
void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb, struct pt_regs *regs)
{
- urb_unlink (urb);
+ int at_root_hub;
- // NOTE: a generic device/urb monitoring hook would go here.
- // hcd_monitor_hook(MONITOR_URB_FINISH, urb, dev)
- // It would catch exit/unlink paths for all urbs.
+ at_root_hub = (urb->dev == hcd->self.root_hub);
+ urb_unlink (urb);
/* lower level hcd code should use *_dma exclusively */
- if (hcd->self.controller->dma_mask) {
+ if (hcd->self.controller->dma_mask && !at_root_hub) {
if (usb_pipecontrol (urb->pipe)
&& !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP))
dma_unmap_single (hcd->self.controller, urb->setup_dma,
@@ -1485,6 +1564,7 @@ void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb, struct pt_regs
: DMA_TO_DEVICE);
}
+ usbmon_urb_complete (&hcd->self, urb);
/* pass ownership to the completion handler */
urb->complete (urb, regs);
atomic_dec (&urb->use_count);
@@ -1499,29 +1579,27 @@ EXPORT_SYMBOL (usb_hcd_giveback_urb);
/**
* usb_hcd_irq - hook IRQs to HCD framework (bus glue)
* @irq: the IRQ being raised
- * @__hcd: pointer to the HCD whose IRQ is beinng signaled
+ * @__hcd: pointer to the HCD whose IRQ is being signaled
* @r: saved hardware registers
*
- * When registering a USB bus through the HCD framework code, use this
- * to handle interrupts. The PCI glue layer does so automatically; only
- * bus glue for non-PCI system busses will need to use this.
+ * If the controller isn't HALTed, calls the driver's irq handler.
+ * Checks whether the controller is now dead.
*/
irqreturn_t usb_hcd_irq (int irq, void *__hcd, struct pt_regs * r)
{
struct usb_hcd *hcd = __hcd;
int start = hcd->state;
- if (start == USB_STATE_HALT)
+ if (start == HC_STATE_HALT)
return IRQ_NONE;
if (hcd->driver->irq (hcd, r) == IRQ_NONE)
return IRQ_NONE;
hcd->saw_irq = 1;
- if (hcd->state != start && hcd->state == USB_STATE_HALT)
+ if (hcd->state != start && hcd->state == HC_STATE_HALT)
usb_hc_died (hcd);
return IRQ_HANDLED;
}
-EXPORT_SYMBOL (usb_hcd_irq);
/*-------------------------------------------------------------------------*/
@@ -1535,12 +1613,21 @@ EXPORT_SYMBOL (usb_hcd_irq);
*/
void usb_hc_died (struct usb_hcd *hcd)
{
+ unsigned long flags;
+
dev_err (hcd->self.controller, "HC died; cleaning up\n");
- /* make khubd clean up old urbs and devices */
- usb_set_device_state(hcd->self.root_hub, USB_STATE_NOTATTACHED);
- mod_timer(&hcd->rh_timer, jiffies);
+ spin_lock_irqsave (&hcd_root_hub_lock, flags);
+ if (hcd->rh_registered) {
+
+ /* make khubd clean up old urbs and devices */
+ usb_set_device_state (hcd->self.root_hub,
+ USB_STATE_NOTATTACHED);
+ usb_kick_khubd (hcd->self.root_hub);
+ }
+ spin_unlock_irqrestore (&hcd_root_hub_lock, flags);
}
+EXPORT_SYMBOL_GPL (usb_hc_died);
/*-------------------------------------------------------------------------*/
@@ -1555,6 +1642,8 @@ static void hcd_release (struct usb_bus *bus)
/**
* usb_create_hcd - create and initialize an HCD structure
* @driver: HC driver that will use this hcd
+ * @dev: device for this HC, stored in hcd->self.controller
+ * @bus_name: value to store in hcd->self.bus_name
* Context: !in_interrupt()
*
* Allocate a struct usb_hcd, with extra space at the end for the
@@ -1563,25 +1652,30 @@ static void hcd_release (struct usb_bus *bus)
*
* If memory is unavailable, returns NULL.
*/
-struct usb_hcd *usb_create_hcd (const struct hc_driver *driver)
+struct usb_hcd *usb_create_hcd (const struct hc_driver *driver,
+ struct device *dev, char *bus_name)
{
struct usb_hcd *hcd;
hcd = kcalloc(1, sizeof(*hcd) + driver->hcd_priv_size, GFP_KERNEL);
- if (!hcd)
+ if (!hcd) {
+ dev_dbg (dev, "hcd alloc failed\n");
return NULL;
+ }
+ dev_set_drvdata(dev, hcd);
usb_bus_init(&hcd->self);
hcd->self.op = &usb_hcd_operations;
hcd->self.hcpriv = hcd;
hcd->self.release = &hcd_release;
+ hcd->self.controller = dev;
+ hcd->self.bus_name = bus_name;
init_timer(&hcd->rh_timer);
hcd->driver = driver;
hcd->product_desc = (driver->product_desc) ? driver->product_desc :
"USB Host Controller";
- hcd->state = USB_STATE_HALT;
return hcd;
}
@@ -1589,6 +1683,158 @@ EXPORT_SYMBOL (usb_create_hcd);
void usb_put_hcd (struct usb_hcd *hcd)
{
+ dev_set_drvdata(hcd->self.controller, NULL);
usb_bus_put(&hcd->self);
}
EXPORT_SYMBOL (usb_put_hcd);
+
+/**
+ * usb_add_hcd - finish generic HCD structure initialization and register
+ * @hcd: the usb_hcd structure to initialize
+ * @irqnum: Interrupt line to allocate
+ * @irqflags: Interrupt type flags
+ *
+ * Finish the remaining parts of generic HCD initialization: allocate the
+ * buffers of consistent memory, register the bus, request the IRQ line,
+ * and call the driver's reset() and start() routines.
+ */
+int usb_add_hcd(struct usb_hcd *hcd,
+ unsigned int irqnum, unsigned long irqflags)
+{
+ int retval;
+
+ dev_info(hcd->self.controller, "%s\n", hcd->product_desc);
+
+ /* till now HC has been in an indeterminate state ... */
+ if (hcd->driver->reset && (retval = hcd->driver->reset(hcd)) < 0) {
+ dev_err(hcd->self.controller, "can't reset\n");
+ return retval;
+ }
+
+ if ((retval = hcd_buffer_create(hcd)) != 0) {
+ dev_dbg(hcd->self.controller, "pool alloc failed\n");
+ return retval;
+ }
+
+ if ((retval = usb_register_bus(&hcd->self)) < 0)
+ goto err1;
+
+ if (hcd->driver->irq) {
+ char buf[8], *bufp = buf;
+
+#ifdef __sparc__
+ bufp = __irq_itoa(irqnum);
+#else
+ sprintf(buf, "%d", irqnum);
+#endif
+
+ snprintf(hcd->irq_descr, sizeof(hcd->irq_descr), "%s:usb%d",
+ hcd->driver->description, hcd->self.busnum);
+ if ((retval = request_irq(irqnum, &usb_hcd_irq, irqflags,
+ hcd->irq_descr, hcd)) != 0) {
+ dev_err(hcd->self.controller,
+ "request interrupt %s failed\n", bufp);
+ goto err2;
+ }
+ hcd->irq = irqnum;
+ dev_info(hcd->self.controller, "irq %s, %s 0x%08llx\n", bufp,
+ (hcd->driver->flags & HCD_MEMORY) ?
+ "io mem" : "io base",
+ (unsigned long long)hcd->rsrc_start);
+ } else {
+ hcd->irq = -1;
+ if (hcd->rsrc_start)
+ dev_info(hcd->self.controller, "%s 0x%08llx\n",
+ (hcd->driver->flags & HCD_MEMORY) ?
+ "io mem" : "io base",
+ (unsigned long long)hcd->rsrc_start);
+ }
+
+ if ((retval = hcd->driver->start(hcd)) < 0) {
+ dev_err(hcd->self.controller, "startup error %d\n", retval);
+ goto err3;
+ }
+
+ return retval;
+
+ err3:
+ if (hcd->irq >= 0)
+ free_irq(irqnum, hcd);
+ err2:
+ usb_deregister_bus(&hcd->self);
+ err1:
+ hcd_buffer_destroy(hcd);
+ return retval;
+}
+EXPORT_SYMBOL (usb_add_hcd);
+
+/**
+ * usb_remove_hcd - shutdown processing for generic HCDs
+ * @hcd: the usb_hcd structure to remove
+ * Context: !in_interrupt()
+ *
+ * Disconnects the root hub, then reverses the effects of usb_add_hcd(),
+ * invoking the HCD's stop() method.
+ */
+void usb_remove_hcd(struct usb_hcd *hcd)
+{
+ dev_info(hcd->self.controller, "remove, state %x\n", hcd->state);
+
+ if (HC_IS_RUNNING (hcd->state))
+ hcd->state = HC_STATE_QUIESCING;
+
+ dev_dbg(hcd->self.controller, "roothub graceful disconnect\n");
+ spin_lock_irq (&hcd_root_hub_lock);
+ hcd->rh_registered = 0;
+ spin_unlock_irq (&hcd_root_hub_lock);
+ usb_disconnect(&hcd->self.root_hub);
+
+ hcd->driver->stop(hcd);
+ hcd->state = HC_STATE_HALT;
+
+ if (hcd->irq >= 0)
+ free_irq(hcd->irq, hcd);
+ usb_deregister_bus(&hcd->self);
+ hcd_buffer_destroy(hcd);
+}
+EXPORT_SYMBOL (usb_remove_hcd);
+
+/*-------------------------------------------------------------------------*/
+
+#if defined(CONFIG_USB_MON) || defined(CONFIG_USB_MON_MODULE)
+
+struct usb_mon_operations *mon_ops;
+
+/*
+ * The registration is unlocked.
+ * We do it this way because we do not want to lock in hot paths.
+ *
+ * Notice that the code is minimally error-proof. Because usbmon needs
+ * symbols from usbcore, usbcore gets referenced and cannot be unloaded first.
+ */
+
+int usb_mon_register (struct usb_mon_operations *ops)
+{
+
+ if (mon_ops)
+ return -EBUSY;
+
+ mon_ops = ops;
+ mb();
+ return 0;
+}
+EXPORT_SYMBOL_GPL (usb_mon_register);
+
+void usb_mon_deregister (void)
+{
+
+ if (mon_ops == NULL) {
+ printk(KERN_ERR "USB: monitor was not registered\n");
+ return;
+ }
+ mon_ops = NULL;
+ mb();
+}
+EXPORT_SYMBOL_GPL (usb_mon_deregister);
+
+#endif /* CONFIG_USB_MON */
diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
index 64884196cf21e..6c625b35fa0c9 100644
--- a/drivers/usb/core/hcd.h
+++ b/drivers/usb/core/hcd.h
@@ -63,6 +63,7 @@ struct usb_hcd { /* usb_bus.hcpriv points to this */
struct usb_bus self; /* hcd is-a bus */
const char *product_desc; /* product/vendor string */
+ char irq_descr[24]; /* driver + bus # */
struct timer_list rh_timer; /* drives root hub */
@@ -73,12 +74,12 @@ struct usb_hcd { /* usb_bus.hcpriv points to this */
unsigned saw_irq : 1;
unsigned can_wakeup:1; /* hw supports wakeup? */
unsigned remote_wakeup:1;/* sw should use wakeup? */
+ unsigned rh_registered:1;/* is root hub registered? */
+
int irq; /* irq allocated */
void __iomem *regs; /* device memory/io */
-
-#ifdef CONFIG_PCI
- int region; /* pci region for regs */
-#endif
+ u64 rsrc_start; /* memory/io resource start */
+ u64 rsrc_len; /* memory/io resource length */
#define HCD_BUFFER_POOLS 4
struct dma_pool *pool [HCD_BUFFER_POOLS];
@@ -88,14 +89,14 @@ struct usb_hcd { /* usb_bus.hcpriv points to this */
# define __SUSPEND 0x04
# define __TRANSIENT 0x80
-# define USB_STATE_HALT 0
-# define USB_STATE_RUNNING (__ACTIVE)
-# define USB_STATE_QUIESCING (__SUSPEND|__TRANSIENT|__ACTIVE)
-# define USB_STATE_RESUMING (__SUSPEND|__TRANSIENT)
-# define HCD_STATE_SUSPENDED (__SUSPEND)
+# define HC_STATE_HALT 0
+# define HC_STATE_RUNNING (__ACTIVE)
+# define HC_STATE_QUIESCING (__SUSPEND|__TRANSIENT|__ACTIVE)
+# define HC_STATE_RESUMING (__SUSPEND|__TRANSIENT)
+# define HC_STATE_SUSPENDED (__SUSPEND)
-#define HCD_IS_RUNNING(state) ((state) & __ACTIVE)
-#define HCD_IS_SUSPENDED(state) ((state) & __SUSPEND)
+#define HC_IS_RUNNING(state) ((state) & __ACTIVE)
+#define HC_IS_SUSPENDED(state) ((state) & __SUSPEND)
/* more shared queuing code would be good; it should support
* smarter scheduling, handle transaction translators, etc;
@@ -209,11 +210,13 @@ struct hc_driver {
};
extern void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb, struct pt_regs *regs);
-extern void usb_bus_init (struct usb_bus *bus);
-extern struct usb_hcd *usb_create_hcd (const struct hc_driver *driver);
+extern struct usb_hcd *usb_create_hcd (const struct hc_driver *driver,
+ struct device *dev, char *bus_name);
extern void usb_put_hcd (struct usb_hcd *hcd);
-
+extern int usb_add_hcd(struct usb_hcd *hcd,
+ unsigned int irqnum, unsigned long irqflags);
+extern void usb_remove_hcd(struct usb_hcd *hcd);
#ifdef CONFIG_PCI
struct pci_dev;
@@ -338,25 +341,10 @@ extern long usb_calc_bus_time (int speed, int is_input,
extern struct usb_bus *usb_alloc_bus (struct usb_operations *);
-extern int usb_register_bus (struct usb_bus *);
-extern void usb_deregister_bus (struct usb_bus *);
-
-extern int usb_register_root_hub (struct usb_device *usb_dev,
- struct device *parent_dev);
+extern int usb_hcd_register_root_hub (struct usb_device *usb_dev,
+ struct usb_hcd *hcd);
-static inline int hcd_register_root (struct usb_device *usb_dev,
- struct usb_hcd *hcd)
-{
- /* hcd->driver->start() reported can_wakeup, probably with
- * assistance from board's boot firmware.
- * NOTE: normal devices won't enable wakeup by default.
- */
- if (hcd->can_wakeup)
- dev_dbg (hcd->self.controller, "supports USB remote wakeup\n");
- hcd->remote_wakeup = hcd->can_wakeup;
-
- return usb_register_root_hub (usb_dev, hcd->self.controller);
-}
+extern void usb_hcd_resume_root_hub (struct usb_hcd *hcd);
extern void usb_set_device_state(struct usb_device *udev,
enum usb_device_state new_state);
@@ -411,6 +399,66 @@ static inline void usbfs_cleanup(void) { }
/*-------------------------------------------------------------------------*/
+#if defined(CONFIG_USB_MON) || defined(CONFIG_USB_MON_MODULE)
+
+struct usb_mon_operations {
+ void (*urb_submit)(struct usb_bus *bus, struct urb *urb);
+ void (*urb_submit_error)(struct usb_bus *bus, struct urb *urb, int err);
+ void (*urb_complete)(struct usb_bus *bus, struct urb *urb);
+ /* void (*urb_unlink)(struct usb_bus *bus, struct urb *urb); */
+ void (*bus_add)(struct usb_bus *bus);
+ void (*bus_remove)(struct usb_bus *bus);
+};
+
+extern struct usb_mon_operations *mon_ops;
+
+static inline void usbmon_urb_submit(struct usb_bus *bus, struct urb *urb)
+{
+ if (bus->monitored)
+ (*mon_ops->urb_submit)(bus, urb);
+}
+
+static inline void usbmon_urb_submit_error(struct usb_bus *bus, struct urb *urb,
+ int error)
+{
+ if (bus->monitored)
+ (*mon_ops->urb_submit_error)(bus, urb, error);
+}
+
+static inline void usbmon_urb_complete(struct usb_bus *bus, struct urb *urb)
+{
+ if (bus->monitored)
+ (*mon_ops->urb_complete)(bus, urb);
+}
+
+static inline void usbmon_notify_bus_add(struct usb_bus *bus)
+{
+ if (mon_ops)
+ (*mon_ops->bus_add)(bus);
+}
+
+static inline void usbmon_notify_bus_remove(struct usb_bus *bus)
+{
+ if (mon_ops)
+ (*mon_ops->bus_remove)(bus);
+}
+
+int usb_mon_register(struct usb_mon_operations *ops);
+void usb_mon_deregister(void);
+
+#else
+
+static inline void usbmon_urb_submit(struct usb_bus *bus, struct urb *urb) {}
+static inline void usbmon_urb_submit_error(struct usb_bus *bus, struct urb *urb,
+ int error) {}
+static inline void usbmon_urb_complete(struct usb_bus *bus, struct urb *urb) {}
+static inline void usbmon_notify_bus_add(struct usb_bus *bus) {}
+static inline void usbmon_notify_bus_remove(struct usb_bus *bus) {}
+
+#endif /* CONFIG_USB_MON */
+
+/*-------------------------------------------------------------------------*/
+
/* hub.h ... DeviceRemovable in 2.4.2-ac11, gone in 2.4.10 */
// bleech -- resurfaced in 2.4.11 or 2.4.12
#define bitmap DeviceRemovable
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index bab10573c3f3c..fa0dc4f6de473 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -74,7 +74,7 @@ module_param(old_scheme_first, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(old_scheme_first,
"start with the old device initialization scheme");
-static int use_both_schemes = 0;
+static int use_both_schemes = 1;
module_param(use_both_schemes, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(use_both_schemes,
"try the other device initialization scheme if the "
@@ -108,7 +108,7 @@ static int get_hub_descriptor(struct usb_device *hdev, void *data, int size)
ret = usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0),
USB_REQ_GET_DESCRIPTOR, USB_DIR_IN | USB_RT_HUB,
USB_DT_HUB << 8, 0, data, size,
- HZ * USB_CTRL_GET_TIMEOUT);
+ USB_CTRL_GET_TIMEOUT);
if (ret >= (USB_DT_HUB_NONVAR_SIZE + 2))
return ret;
}
@@ -121,7 +121,7 @@ static int get_hub_descriptor(struct usb_device *hdev, void *data, int size)
static int clear_hub_feature(struct usb_device *hdev, int feature)
{
return usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
- USB_REQ_CLEAR_FEATURE, USB_RT_HUB, feature, 0, NULL, 0, HZ);
+ USB_REQ_CLEAR_FEATURE, USB_RT_HUB, feature, 0, NULL, 0, 1000);
}
/*
@@ -131,7 +131,7 @@ static int clear_port_feature(struct usb_device *hdev, int port1, int feature)
{
return usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
USB_REQ_CLEAR_FEATURE, USB_RT_PORT, feature, port1,
- NULL, 0, HZ);
+ NULL, 0, 1000);
}
/*
@@ -141,7 +141,7 @@ static int set_port_feature(struct usb_device *hdev, int port1, int feature)
{
return usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
USB_REQ_SET_FEATURE, USB_RT_PORT, feature, port1,
- NULL, 0, HZ);
+ NULL, 0, 1000);
}
/*
@@ -242,7 +242,7 @@ static void led_work (void *__hub)
}
/* use a short timeout for hub/port status fetches */
-#define USB_STS_TIMEOUT 1
+#define USB_STS_TIMEOUT 1000
#define USB_STS_RETRIES 5
/*
@@ -256,7 +256,7 @@ static int get_hub_status(struct usb_device *hdev,
for (i = 0; i < USB_STS_RETRIES && status == -ETIMEDOUT; i++) {
status = usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0),
USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_HUB, 0, 0,
- data, sizeof(*data), HZ * USB_STS_TIMEOUT);
+ data, sizeof(*data), USB_STS_TIMEOUT);
}
return status;
}
@@ -272,7 +272,7 @@ static int get_port_status(struct usb_device *hdev, int port1,
for (i = 0; i < USB_STS_RETRIES && status == -ETIMEDOUT; i++) {
status = usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0),
USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_PORT, 0, port1,
- data, sizeof(*data), HZ * USB_STS_TIMEOUT);
+ data, sizeof(*data), USB_STS_TIMEOUT);
}
return status;
}
@@ -289,6 +289,11 @@ static void kick_khubd(struct usb_hub *hub)
spin_unlock_irqrestore(&hub_event_lock, flags);
}
+void usb_kick_khubd(struct usb_device *hdev)
+{
+ kick_khubd(hdev_to_hub(hdev));
+}
+
/* completion function, fires on port status changes and various faults */
static void hub_irq(struct urb *urb, struct pt_regs *regs)
@@ -342,7 +347,7 @@ hub_clear_tt_buffer (struct usb_device *hdev, u16 devinfo, u16 tt)
{
return usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0),
HUB_CLEAR_TT_BUFFER, USB_RT_PORT, devinfo,
- tt, NULL, 0, HZ);
+ tt, NULL, 0, 1000);
}
/*
@@ -383,7 +388,7 @@ static void hub_tt_kevent (void *arg)
/**
* usb_hub_tt_clear_buffer - clear control/bulk TT state in high speed hub
- * @dev: the device whose split transaction failed
+ * @udev: the device whose split transaction failed
* @pipe: identifies the endpoint of the failed transaction
*
* High speed HCDs use this to tell the hub driver that some split control or
@@ -459,6 +464,7 @@ static void hub_activate(struct usb_hub *hub)
int status;
hub->quiescing = 0;
+ hub->activating = 1;
status = usb_submit_urb(hub->urb, GFP_NOIO);
if (status < 0)
dev_err(hub->intfdev, "activate --> %d\n", status);
@@ -466,7 +472,6 @@ static void hub_activate(struct usb_hub *hub)
schedule_delayed_work(&hub->leds, LED_CYCLE_PERIOD);
/* scan all ports ASAP */
- hub->event_bits[0] = (1UL << (hub->descriptor->bNbrPorts + 1)) - 1;
kick_khubd(hub);
}
@@ -689,7 +694,6 @@ static int hub_configure(struct usb_hub *hub,
hub->indicator [0] = INDICATOR_CYCLE;
hub_power_on(hub);
- hub->change_bits[0] = (1UL << (hub->descriptor->bNbrPorts + 1)) - 2;
hub_activate(hub);
return 0;
@@ -1103,23 +1107,33 @@ static int choose_configuration(struct usb_device *udev)
}
#ifdef DEBUG
-static void show_string(struct usb_device *udev, char *id, int index)
+static void show_string(struct usb_device *udev, char *id, char *string)
+{
+ if (!string)
+ return;
+ dev_printk(KERN_INFO, &udev->dev, "%s: %s\n", id, string);
+}
+
+#else
+static inline void show_string(struct usb_device *udev, char *id, char *string)
+{}
+#endif
+
+static void get_string(struct usb_device *udev, char **string, int index)
{
char *buf;
if (!index)
return;
- if (!(buf = kmalloc(256, GFP_KERNEL)))
+ buf = kmalloc(256, GFP_KERNEL);
+ if (!buf)
return;
if (usb_string(udev, index, buf, 256) > 0)
- dev_printk(KERN_INFO, &udev->dev, "%s: %s\n", id, buf);
- kfree(buf);
+ *string = buf;
+ else
+ kfree(buf);
}
-#else
-static inline void show_string(struct usb_device *udev, char *id, int index)
-{}
-#endif
#ifdef CONFIG_USB_OTG
#include "otg_whitelist.h"
@@ -1157,22 +1171,20 @@ int usb_new_device(struct usb_device *udev)
goto fail;
}
+ /* read the standard strings and cache them if present */
+ get_string(udev, &udev->product, udev->descriptor.iProduct);
+ get_string(udev, &udev->manufacturer, udev->descriptor.iManufacturer);
+ get_string(udev, &udev->serial, udev->descriptor.iSerialNumber);
+
/* Tell the world! */
dev_dbg(&udev->dev, "new device strings: Mfr=%d, Product=%d, "
"SerialNumber=%d\n",
udev->descriptor.iManufacturer,
udev->descriptor.iProduct,
udev->descriptor.iSerialNumber);
-
- if (udev->descriptor.iProduct)
- show_string(udev, "Product",
- udev->descriptor.iProduct);
- if (udev->descriptor.iManufacturer)
- show_string(udev, "Manufacturer",
- udev->descriptor.iManufacturer);
- if (udev->descriptor.iSerialNumber)
- show_string(udev, "SerialNumber",
- udev->descriptor.iSerialNumber);
+ show_string(udev, "Product", udev->product);
+ show_string(udev, "Manufacturer", udev->manufacturer);
+ show_string(udev, "SerialNumber", udev->serial);
#ifdef CONFIG_USB_OTG
/*
@@ -1214,7 +1226,7 @@ int usb_new_device(struct usb_device *udev)
bus->b_hnp_enable
? USB_DEVICE_B_HNP_ENABLE
: USB_DEVICE_A_ALT_HNP_SUPPORT,
- 0, NULL, 0, HZ * USB_CTRL_SET_TIMEOUT);
+ 0, NULL, 0, USB_CTRL_SET_TIMEOUT);
if (err < 0) {
/* OTG MESSAGE: report errors here,
* customize to match your product.
@@ -1235,10 +1247,10 @@ int usb_new_device(struct usb_device *udev)
*/
if (udev->bus->b_hnp_enable || udev->bus->is_b_host) {
static int __usb_suspend_device (struct usb_device *,
- int port1, u32 state);
+ int port1, pm_message_t state);
err = __usb_suspend_device(udev,
udev->bus->otg_port,
- PM_SUSPEND_MEM);
+ PMSG_SUSPEND);
if (err < 0)
dev_dbg(&udev->dev, "HNP fail, %d\n", err);
}
@@ -1376,8 +1388,13 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
dev_err(hub->intfdev,
"cannot reset port %d (err = %d)\n",
port1, status);
- else
+ else {
status = hub_port_wait_reset(hub, port1, udev, delay);
+ if (status)
+ dev_dbg(hub->intfdev,
+ "port_wait_reset: err = %d\n",
+ status);
+ }
/* return on disconnect or reset */
switch (status) {
@@ -1526,7 +1543,8 @@ static int hub_port_suspend(struct usb_hub *hub, int port1,
* Linux (2.6) currently has NO mechanisms to initiate that: no khubd
* timer, no SRP, no requests through sysfs.
*/
-int __usb_suspend_device (struct usb_device *udev, int port1, u32 state)
+static int __usb_suspend_device (struct usb_device *udev, int port1,
+ pm_message_t state)
{
int status;
@@ -1607,9 +1625,11 @@ int __usb_suspend_device (struct usb_device *udev, int port1, u32 state)
struct usb_bus *bus = udev->bus;
if (bus && bus->op->hub_suspend) {
status = bus->op->hub_suspend (bus);
- if (status == 0)
+ if (status == 0) {
+ dev_dbg(&udev->dev, "usb suspend\n");
usb_set_device_state(udev,
USB_STATE_SUSPENDED);
+ }
} else
status = -EOPNOTSUPP;
} else
@@ -1624,7 +1644,7 @@ int __usb_suspend_device (struct usb_device *udev, int port1, u32 state)
/**
* usb_suspend_device - suspend a usb device
* @udev: device that's no longer in active use
- * @state: PM_SUSPEND_MEM to suspend
+ * @state: PMSG_SUSPEND to suspend
* Context: must be able to sleep; device not locked
*
* Suspends a USB device that isn't in active use, conserving power.
@@ -1639,7 +1659,7 @@ int __usb_suspend_device (struct usb_device *udev, int port1, u32 state)
*
* Returns 0 on success, else negative errno.
*/
-int usb_suspend_device(struct usb_device *udev, u32 state)
+int usb_suspend_device(struct usb_device *udev, pm_message_t state)
{
int port1, status;
@@ -1673,7 +1693,7 @@ static int finish_port_resume(struct usb_device *udev)
usb_set_device_state(udev, udev->actconfig
? USB_STATE_CONFIGURED
: USB_STATE_ADDRESS);
- udev->dev.power.power_state = PM_SUSPEND_ON;
+ 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,
@@ -1827,9 +1847,11 @@ int usb_resume_device(struct usb_device *udev)
} else
status = -EOPNOTSUPP;
if (status == 0) {
+ dev_dbg(&udev->dev, "usb resume\n");
/* TRSMRCY = 10 msec */
msleep(10);
usb_set_device_state (udev, USB_STATE_CONFIGURED);
+ udev->dev.power.power_state = PMSG_ON;
status = hub_resume (udev
->actconfig->interface[0]);
}
@@ -1874,7 +1896,7 @@ static int remote_wakeup(struct usb_device *udev)
return status;
}
-static int hub_suspend(struct usb_interface *intf, u32 state)
+static int hub_suspend(struct usb_interface *intf, pm_message_t state)
{
struct usb_hub *hub = usb_get_intfdata (intf);
struct usb_device *hdev = hub->hdev;
@@ -1946,15 +1968,24 @@ static int hub_resume(struct usb_interface *intf)
}
up(&udev->serialize);
}
- intf->dev.power.power_state = PM_SUSPEND_ON;
+ intf->dev.power.power_state = PMSG_ON;
+ hub->resume_root_hub = 0;
hub_activate(hub);
return 0;
}
+void usb_resume_root_hub(struct usb_device *hdev)
+{
+ struct usb_hub *hub = hdev_to_hub(hdev);
+
+ hub->resume_root_hub = 1;
+ kick_khubd(hub);
+}
+
#else /* !CONFIG_USB_SUSPEND */
-int usb_suspend_device(struct usb_device *udev, u32 state)
+int usb_suspend_device(struct usb_device *udev, pm_message_t state)
{
return 0;
}
@@ -2058,7 +2089,7 @@ static int hub_set_address(struct usb_device *udev)
return -EINVAL;
retval = usb_control_msg(udev, usb_sndaddr0pipe(),
USB_REQ_SET_ADDRESS, 0, udev->devnum, 0,
- NULL, 0, HZ * USB_CTRL_SET_TIMEOUT);
+ NULL, 0, USB_CTRL_SET_TIMEOUT);
if (retval == 0) {
usb_set_device_state(udev, USB_STATE_ADDRESS);
ep0_reinit(udev);
@@ -2181,24 +2212,35 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
retval = -ENOMEM;
continue;
}
- buf->bMaxPacketSize0 = 0;
/* Use a short timeout the first time through,
* so that recalcitrant full-speed devices with
* 8- or 16-byte ep0-maxpackets won't slow things
* down tremendously by NAKing the unexpectedly
- * early status stage. Also, retry on length 0
- * or stall; some devices are flakey.
+ * early status stage. Also, retry on all errors;
+ * some devices are flakey.
*/
for (j = 0; j < 3; ++j) {
+ buf->bMaxPacketSize0 = 0;
r = usb_control_msg(udev, usb_rcvaddr0pipe(),
USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
USB_DT_DEVICE << 8, 0,
buf, GET_DESCRIPTOR_BUFSIZE,
- (i ? HZ * USB_CTRL_GET_TIMEOUT : HZ));
- if (r == 0 || r == -EPIPE)
- continue;
- if (r < 0)
+ (i ? USB_CTRL_GET_TIMEOUT : 1000));
+ switch (buf->bMaxPacketSize0) {
+ case 8: case 16: case 32: case 64:
+ if (buf->bDescriptorType ==
+ USB_DT_DEVICE) {
+ r = 0;
+ break;
+ }
+ /* FALL THROUGH */
+ default:
+ if (r == 0)
+ r = -EPROTO;
+ break;
+ }
+ if (r == 0)
break;
}
udev->descriptor.bMaxPacketSize0 =
@@ -2214,10 +2256,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
retval = -ENODEV;
goto fail;
}
- switch (udev->descriptor.bMaxPacketSize0) {
- case 64: case 32: case 16: case 8:
- break;
- default:
+ if (r) {
dev_err(&udev->dev, "device descriptor "
"read/%s, error %d\n",
"64", r);
@@ -2600,15 +2639,30 @@ static void hub_events(void)
(u16) hub->event_bits[0]);
usb_get_intf(intf);
+ i = hub->resume_root_hub;
spin_unlock_irq(&hub_event_lock);
+ /* Is this is a root hub wanting to be resumed? */
+ if (i)
+ usb_resume_device(hdev);
+
/* Lock the device, then check to see if we were
* disconnected while waiting for the lock to succeed. */
if (locktree(hdev) < 0) {
usb_put_intf(intf);
continue;
}
- if (hub != usb_get_intfdata(intf) || hub->quiescing)
+ if (hub != usb_get_intfdata(intf))
+ goto loop;
+
+ /* If the hub has died, clean up after it */
+ if (hdev->state == USB_STATE_NOTATTACHED) {
+ hub_pre_reset(hub);
+ goto loop;
+ }
+
+ /* If this is an inactive or suspended hub, do nothing */
+ if (hub->quiescing)
goto loop;
if (hub->error) {
@@ -2628,9 +2682,11 @@ static void hub_events(void)
/* deal with port status changes */
for (i = 1; i <= hub->descriptor->bNbrPorts; i++) {
+ if (test_bit(i, hub->busy_bits))
+ continue;
connect_change = test_bit(i, hub->change_bits);
if (!test_and_clear_bit(i, hub->event_bits) &&
- !connect_change)
+ !connect_change && !hub->activating)
continue;
ret = hub_port_status(hub, i,
@@ -2638,6 +2694,11 @@ static void hub_events(void)
if (ret < 0)
continue;
+ if (hub->activating && !hdev->children[i-1] &&
+ (portstatus &
+ USB_PORT_STAT_CONNECTION))
+ connect_change = 1;
+
if (portchange & USB_PORT_STAT_C_CONNECTION) {
clear_port_feature(hdev, i,
USB_PORT_FEAT_C_CONNECTION);
@@ -2728,6 +2789,8 @@ static void hub_events(void)
}
}
+ hub->activating = 0;
+
loop:
usb_unlock_device(hdev);
usb_put_intf(intf);
@@ -2926,6 +2989,7 @@ int usb_reset_device(struct usb_device *udev)
hub_pre_reset(hub);
}
+ set_bit(port1, parent_hub->busy_bits);
for (i = 0; i < SET_CONFIG_TRIES; ++i) {
/* ep0 maxpacket size may change; let the HCD know about it.
@@ -2935,6 +2999,7 @@ int usb_reset_device(struct usb_device *udev)
if (ret >= 0)
break;
}
+ clear_bit(port1, parent_hub->busy_bits);
if (ret < 0)
goto re_enumerate;
@@ -2952,7 +3017,7 @@ int usb_reset_device(struct usb_device *udev)
ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
USB_REQ_SET_CONFIGURATION, 0,
udev->actconfig->desc.bConfigurationValue, 0,
- NULL, 0, HZ * USB_CTRL_SET_TIMEOUT);
+ NULL, 0, USB_CTRL_SET_TIMEOUT);
if (ret < 0) {
dev_err(&udev->dev,
"can't restore configuration #%d (error=%d)\n",
diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h
index b8f8a1159007d..d114b847d56f8 100644
--- a/drivers/usb/core/hub.h
+++ b/drivers/usb/core/hub.h
@@ -205,6 +205,7 @@ struct usb_hub {
unsigned long event_bits[1]; /* status change bitmask */
unsigned long change_bits[1]; /* ports with logical connect
status change */
+ unsigned long busy_bits[1]; /* ports being reset */
#if USB_MAXCHILDREN > 31 /* 8*sizeof(unsigned long) - 1 */
#error event_bits[] is too short!
#endif
@@ -215,6 +216,8 @@ struct usb_hub {
u8 power_budget; /* in 2mA units; or zero */
unsigned quiescing:1;
+ unsigned activating:1;
+ unsigned resume_root_hub:1;
unsigned has_indicators:1;
enum hub_led_mode indicator[USB_MAXCHILDREN];
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index e0165ae9cfc0f..40bdb38e7bcba 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -55,7 +55,7 @@ static int usb_start_wait_urb(struct urb *urb, int timeout, int* actual_length)
if (status == 0) {
if (timeout > 0) {
init_timer(&timer);
- timer.expires = jiffies + timeout;
+ timer.expires = jiffies + msecs_to_jiffies(timeout);
timer.data = (unsigned long)urb;
timer.function = timeout_kill;
/* grr. timeout _should_ include submit delays. */
@@ -65,12 +65,18 @@ static int usb_start_wait_urb(struct urb *urb, int timeout, int* actual_length)
status = urb->status;
/* note: HCDs return ETIMEDOUT for other reasons too */
if (status == -ECONNRESET) {
- dev_warn(&urb->dev->dev,
- "%s timed out on ep%d%s\n",
+ dev_dbg(&urb->dev->dev,
+ "%s timed out on ep%d%s len=%d/%d\n",
current->comm,
usb_pipeendpoint(urb->pipe),
- usb_pipein(urb->pipe) ? "in" : "out");
- status = -ETIMEDOUT;
+ usb_pipein(urb->pipe) ? "in" : "out",
+ urb->actual_length,
+ urb->transfer_buffer_length
+ );
+ if (urb->actual_length > 0)
+ status = 0;
+ else
+ status = -ETIMEDOUT;
}
if (timeout > 0)
del_timer_sync(&timer);
@@ -84,8 +90,10 @@ static int usb_start_wait_urb(struct urb *urb, int timeout, int* actual_length)
/*-------------------------------------------------------------------*/
// returns status (negative) or length (positive)
-int usb_internal_control_msg(struct usb_device *usb_dev, unsigned int pipe,
- struct usb_ctrlrequest *cmd, void *data, int len, int timeout)
+static int usb_internal_control_msg(struct usb_device *usb_dev,
+ unsigned int pipe,
+ struct usb_ctrlrequest *cmd,
+ void *data, int len, int timeout)
{
struct urb *urb;
int retv;
@@ -115,7 +123,7 @@ int usb_internal_control_msg(struct usb_device *usb_dev, unsigned int pipe,
* @index: USB message index value
* @data: pointer to the data to send
* @size: length in bytes of the data to send
- * @timeout: time in jiffies to wait for the message to complete before
+ * @timeout: time in msecs to wait for the message to complete before
* timing out (if 0 the wait is forever)
* Context: !in_interrupt ()
*
@@ -163,7 +171,7 @@ int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u
* @data: pointer to the data to send
* @len: length in bytes of the data to send
* @actual_length: pointer to a location to put the actual length transferred in bytes
- * @timeout: time in jiffies to wait for the message to complete before
+ * @timeout: time in msecs to wait for the message to complete before
* timing out (if 0 the wait is forever)
* Context: !in_interrupt ()
*
@@ -196,7 +204,7 @@ int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe,
usb_fill_bulk_urb(urb, usb_dev, pipe, data, len,
usb_api_blocking_completion, NULL);
- return usb_start_wait_urb(urb,timeout,actual_length);
+ return usb_start_wait_urb(urb, timeout, actual_length);
}
/*-------------------------------------------------------------------*/
@@ -579,7 +587,7 @@ int usb_get_descriptor(struct usb_device *dev, unsigned char type, unsigned char
result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
(type << 8) + index, 0, buf, size,
- HZ * USB_CTRL_GET_TIMEOUT);
+ USB_CTRL_GET_TIMEOUT);
if (result == 0 || result == -EPIPE)
continue;
if (result > 1 && ((u8 *)buf)[1] != type) {
@@ -624,7 +632,7 @@ int usb_get_string(struct usb_device *dev, unsigned short langid,
result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
(USB_DT_STRING << 8) + index, langid, buf, size,
- HZ * USB_CTRL_GET_TIMEOUT);
+ USB_CTRL_GET_TIMEOUT);
if (!(result == 0 || result == -EPIPE))
break;
}
@@ -834,7 +842,7 @@ int usb_get_status(struct usb_device *dev, int type, int target, void *data)
ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
USB_REQ_GET_STATUS, USB_DIR_IN | type, 0, target, status,
- sizeof(*status), HZ * USB_CTRL_GET_TIMEOUT);
+ sizeof(*status), USB_CTRL_GET_TIMEOUT);
*(u16 *)data = *status;
kfree(status);
@@ -879,7 +887,7 @@ int usb_clear_halt(struct usb_device *dev, int pipe)
result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT,
USB_ENDPOINT_HALT, endp, NULL, 0,
- HZ * USB_CTRL_SET_TIMEOUT);
+ USB_CTRL_SET_TIMEOUT);
/* don't un-halt or force to DATA0 except on success */
if (result < 0)
@@ -982,6 +990,8 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
dev_dbg (&dev->dev, "unregistering interface %s\n",
interface->dev.bus_id);
usb_remove_sysfs_intf_files(interface);
+ kfree(interface->cur_altsetting->string);
+ interface->cur_altsetting->string = NULL;
device_del (&interface->dev);
}
@@ -1033,8 +1043,8 @@ usb_enable_endpoint(struct usb_device *dev, struct usb_host_endpoint *ep)
*
* Enables all the endpoints for the interface's current altsetting.
*/
-void usb_enable_interface(struct usb_device *dev,
- struct usb_interface *intf)
+static void usb_enable_interface(struct usb_device *dev,
+ struct usb_interface *intf)
{
struct usb_host_interface *alt = intf->cur_altsetting;
int i;
@@ -1101,7 +1111,7 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
USB_REQ_SET_INTERFACE, USB_RECIP_INTERFACE,
- alternate, interface, NULL, 0, HZ * 5);
+ alternate, interface, NULL, 0, 5000);
/* 9.4.10 says devices don't need this and are free to STALL the
* request if the interface only has one alternate setting.
@@ -1123,10 +1133,29 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
/* prevent submissions using previous endpoint settings */
usb_disable_interface(dev, iface);
+ /* 9.1.1.5 says:
+ *
+ * Configuring a device or changing an alternate setting
+ * causes all of the status and configuration values
+ * associated with endpoints in the affected interfaces to
+ * be set to their default values. This includes setting
+ * the data toggle of any endpoint using data toggles to
+ * the value DATA0.
+ *
+ * Some devices take this too literally and don't reset the data
+ * toggles if the new altsetting is the same as the old one (the
+ * command isn't "changing" an alternate setting). We will manually
+ * reset the toggles when the new and old altsettings are the same.
+ * Most devices won't need this, but fortunately it doesn't happen
+ * often.
+ */
+ if (iface->cur_altsetting == alt)
+ manual = 1;
iface->cur_altsetting = alt;
/* If the interface only has one altsetting and the device didn't
- * accept the request, we attempt to carry out the equivalent action
+ * accept the request (or whenever the old altsetting is the same
+ * as the new one), we attempt to carry out the equivalent action
* by manually clearing the HALT feature for each endpoint in the
* new altsetting.
*/
@@ -1202,7 +1231,7 @@ int usb_reset_configuration(struct usb_device *dev)
retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
USB_REQ_SET_CONFIGURATION, 0,
config->desc.bConfigurationValue, 0,
- NULL, 0, HZ * USB_CTRL_SET_TIMEOUT);
+ NULL, 0, USB_CTRL_SET_TIMEOUT);
if (retval < 0) {
usb_set_device_state(dev, USB_STATE_ADDRESS);
return retval;
@@ -1337,7 +1366,7 @@ free_interfaces:
if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
USB_REQ_SET_CONFIGURATION, 0, configuration, 0,
- NULL, 0, HZ * USB_CTRL_SET_TIMEOUT)) < 0)
+ NULL, 0, USB_CTRL_SET_TIMEOUT)) < 0)
goto free_interfaces;
dev->actconfig = cp;
@@ -1386,6 +1415,13 @@ free_interfaces:
}
kfree(new_interfaces);
+ if ((cp->desc.iConfiguration) &&
+ (cp->string == NULL)) {
+ cp->string = kmalloc(256, GFP_KERNEL);
+ if (cp->string)
+ usb_string(dev, cp->desc.iConfiguration, cp->string, 256);
+ }
+
/* Now that all the interfaces are set up, register them
* to trigger binding of drivers to interfaces. probe()
* routines may install different altsettings and may
@@ -1409,6 +1445,13 @@ free_interfaces:
ret);
continue;
}
+ if ((intf->cur_altsetting->desc.iInterface) &&
+ (intf->cur_altsetting->string == NULL)) {
+ intf->cur_altsetting->string = kmalloc(256, GFP_KERNEL);
+ if (intf->cur_altsetting->string)
+ usb_string(dev, intf->cur_altsetting->desc.iInterface,
+ intf->cur_altsetting->string, 256);
+ }
usb_create_sysfs_intf_files (intf);
}
}
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
index ce71f7af74784..ec9b3bde8ae59 100644
--- a/drivers/usb/core/sysfs.c
+++ b/drivers/usb/core/sysfs.c
@@ -46,27 +46,24 @@ usb_actconfig_attr (bNumInterfaces, 1, "%2d\n")
usb_actconfig_attr (bmAttributes, 1, "%2x\n")
usb_actconfig_attr (bMaxPower, 2, "%3dmA\n")
-#define usb_actconfig_str(name, field) \
-static ssize_t show_##name(struct device *dev, char *buf) \
-{ \
- struct usb_device *udev; \
- struct usb_host_config *actconfig; \
- int len; \
- \
- udev = to_usb_device (dev); \
- actconfig = udev->actconfig; \
- if (!actconfig) \
- return 0; \
- len = usb_string(udev, actconfig->desc.field, buf, PAGE_SIZE); \
- if (len < 0) \
- return 0; \
- buf[len] = '\n'; \
- buf[len+1] = 0; \
- return len+1; \
-} \
-static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL);
+static ssize_t show_configuration_string(struct device *dev, char *buf)
+{
+ struct usb_device *udev;
+ struct usb_host_config *actconfig;
+ int len;
-usb_actconfig_str (configuration, iConfiguration)
+ udev = to_usb_device (dev);
+ actconfig = udev->actconfig;
+ if ((!actconfig) || (!actconfig->string))
+ return 0;
+ len = sprintf(buf, actconfig->string, PAGE_SIZE);
+ if (len < 0)
+ return 0;
+ buf[len] = '\n';
+ buf[len+1] = 0;
+ return len+1;
+}
+static DEVICE_ATTR(configuration, S_IRUGO, show_configuration_string, NULL);
/* configuration value is always present, and r/w */
usb_actconfig_show(bConfigurationValue, 1, "%u\n");
@@ -89,14 +86,14 @@ static DEVICE_ATTR(bConfigurationValue, S_IRUGO | S_IWUSR,
show_bConfigurationValue, set_bConfigurationValue);
/* String fields */
-#define usb_string_attr(name, field) \
+#define usb_string_attr(name) \
static ssize_t show_##name(struct device *dev, char *buf) \
{ \
struct usb_device *udev; \
int len; \
\
udev = to_usb_device (dev); \
- len = usb_string(udev, udev->descriptor.field, buf, PAGE_SIZE); \
+ len = snprintf(buf, 256, "%s", udev->name); \
if (len < 0) \
return 0; \
buf[len] = '\n'; \
@@ -105,9 +102,9 @@ static ssize_t show_##name(struct device *dev, char *buf) \
} \
static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL);
-usb_string_attr(product, iProduct);
-usb_string_attr(manufacturer, iManufacturer);
-usb_string_attr(serial, iSerialNumber);
+usb_string_attr(product);
+usb_string_attr(manufacturer);
+usb_string_attr(serial);
static ssize_t
show_speed (struct device *dev, char *buf)
@@ -230,11 +227,11 @@ void usb_create_sysfs_dev_files (struct usb_device *udev)
sysfs_create_group(&dev->kobj, &dev_attr_grp);
- if (udev->descriptor.iManufacturer)
+ if (udev->manufacturer)
device_create_file (dev, &dev_attr_manufacturer);
- if (udev->descriptor.iProduct)
+ if (udev->product)
device_create_file (dev, &dev_attr_product);
- if (udev->descriptor.iSerialNumber)
+ if (udev->serial)
device_create_file (dev, &dev_attr_serial);
device_create_file (dev, &dev_attr_configuration);
}
@@ -272,25 +269,22 @@ usb_intf_attr (bInterfaceClass, "%02x\n")
usb_intf_attr (bInterfaceSubClass, "%02x\n")
usb_intf_attr (bInterfaceProtocol, "%02x\n")
-#define usb_intf_str(name, field) \
-static ssize_t show_##name(struct device *dev, char *buf) \
-{ \
- struct usb_interface *intf; \
- struct usb_device *udev; \
- int len; \
- \
- intf = to_usb_interface (dev); \
- udev = interface_to_usbdev (intf); \
- len = usb_string(udev, intf->cur_altsetting->desc.field, buf, PAGE_SIZE);\
- if (len < 0) \
- return 0; \
- buf[len] = '\n'; \
- buf[len+1] = 0; \
- return len+1; \
-} \
-static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL);
-
-usb_intf_str (interface, iInterface);
+static ssize_t show_interface_string(struct device *dev, char *buf)
+{
+ struct usb_interface *intf;
+ struct usb_device *udev;
+ int len;
+
+ intf = to_usb_interface (dev);
+ udev = interface_to_usbdev (intf);
+ len = snprintf(buf, 256, "%s", intf->cur_altsetting->string);
+ if (len < 0)
+ return 0;
+ buf[len] = '\n';
+ buf[len+1] = 0;
+ return len+1;
+}
+static DEVICE_ATTR(interface, S_IRUGO, show_interface_string, NULL);
static struct attribute *intf_attrs[] = {
&dev_attr_bInterfaceNumber.attr,
@@ -309,7 +303,7 @@ void usb_create_sysfs_intf_files (struct usb_interface *intf)
{
sysfs_create_group(&intf->dev.kobj, &intf_attr_grp);
- if (intf->cur_altsetting->desc.iInterface)
+ if (intf->cur_altsetting->string)
device_create_file(&intf->dev, &dev_attr_interface);
}
@@ -318,7 +312,7 @@ void usb_remove_sysfs_intf_files (struct usb_interface *intf)
{
sysfs_remove_group(&intf->dev.kobj, &intf_attr_grp);
- if (intf->cur_altsetting->desc.iInterface)
+ if (intf->cur_altsetting->string)
device_remove_file(&intf->dev, &dev_attr_interface);
}
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index 99268c2e51647..f0534ee064901 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -60,7 +60,7 @@ extern void usb_host_cleanup(void);
const char *usbcore_name = "usbcore";
-int nousb; /* Disable USB when built into kernel image */
+static int nousb; /* Disable USB when built into kernel image */
/* Not honored on modular build */
static DECLARE_RWSEM(usb_all_devices_rwsem);
@@ -86,7 +86,7 @@ static struct device_driver usb_generic_driver = {
static int usb_generic_driver_data;
/* called from driver core with usb_bus_type.subsys writelock */
-int usb_probe_interface(struct device *dev)
+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);
@@ -114,7 +114,7 @@ int usb_probe_interface(struct device *dev)
}
/* called from driver core with usb_bus_type.subsys writelock */
-int usb_unbind_interface(struct device *dev)
+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);
@@ -615,6 +615,33 @@ static int usb_hotplug (struct device *dev, char **envp, int num_envp,
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%04Xdl%04Xdh%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),
+ 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;
+ } else {
+ if (add_hotplug_env_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "MODALIAS=usb:v%04Xp%04Xdl%04Xdh%04Xdc%02Xdsc%02Xdp%02Xic*isc*ip*",
+ le16_to_cpu(usb_dev->descriptor.idVendor),
+ le16_to_cpu(usb_dev->descriptor.idProduct),
+ le16_to_cpu(usb_dev->descriptor.bcdDevice),
+ le16_to_cpu(usb_dev->descriptor.bcdDevice),
+ usb_dev->descriptor.bDeviceClass,
+ usb_dev->descriptor.bDeviceSubClass,
+ usb_dev->descriptor.bDeviceProtocol))
+ return -ENOMEM;
}
envp[i] = NULL;
@@ -647,7 +674,10 @@ static void usb_release_dev(struct device *dev)
usb_destroy_configuration(udev);
usb_bus_put(udev->bus);
- kfree (udev);
+ kfree(udev->product);
+ kfree(udev->manufacturer);
+ kfree(udev->serial);
+ kfree(udev);
}
/**
@@ -1145,6 +1175,7 @@ void usb_buffer_free (
*
* Reverse the effect of this call with usb_buffer_unmap().
*/
+#if 0
struct urb *usb_buffer_map (struct urb *urb)
{
struct usb_bus *bus;
@@ -1174,6 +1205,7 @@ struct urb *usb_buffer_map (struct urb *urb)
| URB_NO_SETUP_DMA_MAP);
return urb;
}
+#endif /* 0 */
/* XXX DISABLED, no users currently. If you wish to re-enable this
* XXX please determine whether the sync is to transfer ownership of
@@ -1218,6 +1250,7 @@ void usb_buffer_dmasync (struct urb *urb)
*
* Reverses the effect of usb_buffer_map().
*/
+#if 0
void usb_buffer_unmap (struct urb *urb)
{
struct usb_bus *bus;
@@ -1244,6 +1277,7 @@ void usb_buffer_unmap (struct urb *urb)
urb->transfer_flags &= ~(URB_NO_TRANSFER_DMA_MAP
| URB_NO_SETUP_DMA_MAP);
}
+#endif /* 0 */
/**
* usb_buffer_map_sg - create scatterlist DMA mapping(s) for an endpoint
@@ -1524,11 +1558,11 @@ EXPORT_SYMBOL(usb_get_current_frame_number);
EXPORT_SYMBOL (usb_buffer_alloc);
EXPORT_SYMBOL (usb_buffer_free);
-EXPORT_SYMBOL (usb_buffer_map);
#if 0
+EXPORT_SYMBOL (usb_buffer_map);
EXPORT_SYMBOL (usb_buffer_dmasync);
-#endif
EXPORT_SYMBOL (usb_buffer_unmap);
+#endif
EXPORT_SYMBOL (usb_buffer_map_sg);
#if 0
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
index 5b95a53babdd4..4c33eee520011 100644
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -4,8 +4,6 @@ extern void usb_create_sysfs_dev_files (struct usb_device *dev);
extern void usb_remove_sysfs_dev_files (struct usb_device *dev);
extern void usb_create_sysfs_intf_files (struct usb_interface *intf);
extern void usb_remove_sysfs_intf_files (struct usb_interface *intf);
-extern int usb_probe_interface (struct device *dev);
-extern int usb_unbind_interface (struct device *dev);
extern void usb_disable_endpoint (struct usb_device *dev, unsigned int epaddr);
extern void usb_disable_interface (struct usb_device *dev,
@@ -13,9 +11,6 @@ extern void usb_disable_interface (struct usb_device *dev,
extern void usb_release_interface_cache(struct kref *ref);
extern void usb_disable_device (struct usb_device *dev, int skip_ep0);
-extern void usb_enable_interface (struct usb_device *dev,
- struct usb_interface *intf);
-
extern int usb_get_device_descriptor(struct usb_device *dev,
unsigned int size);
extern int usb_set_configuration(struct usb_device *dev, int configuration);
@@ -23,6 +18,9 @@ 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_resume_root_hub(struct usb_device *dev);
+
/* for labeling diagnostics */
extern const char *usbcore_name;
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index fa34e8a13b614..3b24f9f2c2341 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -87,10 +87,10 @@ config USB_NET2280
default USB_GADGET
config USB_GADGET_PXA2XX
- boolean "PXA 2xx or IXP 4xx"
- depends on ARCH_PXA || ARCH_IXP4XX
+ boolean "PXA 25x or IXP 4xx"
+ depends on (ARCH_PXA && PXA25x) || ARCH_IXP4XX
help
- Intel's PXA 2xx series XScale ARM-5TE processors include
+ Intel's PXA 25x series XScale ARM-5TE processors include
an integrated full speed USB 1.1 device controller. The
controller in the IXP 4xx series is register-compatible.
@@ -135,21 +135,6 @@ config USB_GOKU
depends on USB_GADGET_GOKU
default USB_GADGET
-# this could be built elsewhere (doesn't yet exist)
-config USB_GADGET_SA1100
- boolean "SA 1100"
- depends on ARCH_SA1100
- help
- Intel's SA-1100 is an ARM-4 processor with an integrated
- full speed USB 1.1 device controller.
-
- It has two fixed-function endpoints, as well as endpoint
- zero (for control transfers).
-
-config USB_SA1100
- tristate
- depends on USB_GADGET_SA1100
- default USB_GADGET
config USB_GADGET_LH7A40X
boolean "LH7A40X"
@@ -163,38 +148,10 @@ config USB_LH7A40X
default USB_GADGET
-config USB_GADGET_DUMMY_HCD
- boolean "Dummy HCD (DEVELOPMENT)"
- depends on USB && EXPERIMENTAL
- select USB_GADGET_DUALSPEED
- help
- This host controller driver emulates USB, looping all data transfer
- requests back to a USB "gadget driver" in the same host. The host
- side is the master; the gadget side is the slave. Gadget drivers
- can be high, full, or low speed; and they have access to endpoints
- like those from NET2280, PXA2xx, or SA1100 hardware.
-
- This may help in some stages of creating a driver to embed in a
- Linux device, since it lets you debug several parts of the gadget
- driver without its hardware or drivers being involved.
-
- Since such a gadget side driver needs to interoperate with a host
- side Linux-USB device driver, this may help to debug both sides
- of a USB protocol stack.
-
- Say "y" to link the driver statically, or "m" to build a
- dynamically linked module called "dummy_hcd" and force all
- gadget drivers to also be dynamically linked.
-
-config USB_DUMMY_HCD
- tristate
- depends on USB_GADGET_DUMMY_HCD
- default USB_GADGET
-
config USB_GADGET_OMAP
boolean "OMAP USB Device Controller"
depends on ARCH_OMAP
- select ISP1301_OMAP if MACH_OMAP_H2
+ select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3
help
Many Texas Instruments OMAP processors have flexible full
speed USB device controllers, with support for up to 30
@@ -222,6 +179,38 @@ config USB_OTG
Select this only if your OMAP board has a Mini-AB connector.
+
+config USB_GADGET_DUMMY_HCD
+ boolean "Dummy HCD (DEVELOPMENT)"
+ depends on USB && EXPERIMENTAL
+ select USB_GADGET_DUALSPEED
+ help
+ This host controller driver emulates USB, looping all data transfer
+ requests back to a USB "gadget driver" in the same host. The host
+ side is the master; the gadget side is the slave. Gadget drivers
+ can be high, full, or low speed; and they have access to endpoints
+ like those from NET2280, PXA2xx, or SA1100 hardware.
+
+ This may help in some stages of creating a driver to embed in a
+ Linux device, since it lets you debug several parts of the gadget
+ driver without its hardware or drivers being involved.
+
+ Since such a gadget side driver needs to interoperate with a host
+ side Linux-USB device driver, this may help to debug both sides
+ of a USB protocol stack.
+
+ Say "y" to link the driver statically, or "m" to build a
+ dynamically linked module called "dummy_hcd" and force all
+ gadget drivers to also be dynamically linked.
+
+config USB_DUMMY_HCD
+ tristate
+ depends on USB_GADGET_DUMMY_HCD
+ default USB_GADGET
+
+# NOTE: Please keep dummy_hcd LAST so that "real hardware" appears
+# first and will be selected by default.
+
endchoice
config USB_GADGET_DUALSPEED
@@ -355,8 +344,6 @@ config USB_GADGETFS
config USB_FILE_STORAGE
tristate "File-backed Storage Gadget"
- # we don't support the SA1100 because of its limitations
- depends on USB_GADGET_SA1100 = n
help
The File-backed Storage Gadget acts as a USB Mass Storage
disk drive. As its storage repository it can use a regular
diff --git a/drivers/usb/gadget/config.c b/drivers/usb/gadget/config.c
index 531909242b247..83b4866df9af0 100644
--- a/drivers/usb/gadget/config.c
+++ b/drivers/usb/gadget/config.c
@@ -25,6 +25,7 @@
#include <linux/device.h>
#include <linux/usb_ch9.h>
+#include <linux/usb_gadget.h>
/**
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index 702de0302795f..8ef8a9cd9ac4f 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/dummy_hcd.c
@@ -4,7 +4,7 @@
* Maintainer: Alan Stern <stern@rowland.harvard.edu>
*
* Copyright (C) 2003 David Brownell
- * Copyright (C) 2003, 2004 Alan Stern
+ * Copyright (C) 2003-2005 Alan Stern
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -167,7 +167,6 @@ struct dummy {
*/
struct timer_list timer;
u32 port_status;
- unsigned started:1;
unsigned resuming:1;
unsigned long re_timeout;
@@ -1637,7 +1636,6 @@ static int dummy_start (struct usb_hcd *hcd)
* just like more familiar pci-based HCDs.
*/
spin_lock_init (&dum->lock);
-
init_timer (&dum->timer);
dum->timer.function = dummy_timer;
dum->timer.data = (unsigned long) dum;
@@ -1649,30 +1647,30 @@ static int dummy_start (struct usb_hcd *hcd)
return -ENOMEM;
/* root hub enters addressed state... */
- hcd->state = USB_STATE_RUNNING;
+ hcd->state = HC_STATE_RUNNING;
root->speed = USB_SPEED_HIGH;
/* ...then configured, so khubd sees us. */
- if ((retval = hcd_register_root (root, hcd)) != 0) {
- usb_put_dev (root);
-clean:
- hcd->state = USB_STATE_QUIESCING;
- return retval;
+ if ((retval = usb_hcd_register_root_hub (root, hcd)) != 0) {
+ goto err1;
}
/* only show a low-power port: just 8mA */
hub_set_power_budget (root, 8);
- if ((retval = dummy_register_udc (dum)) != 0) {
- usb_disconnect (&hcd->self.root_hub);
- goto clean;
- }
+ if ((retval = dummy_register_udc (dum)) != 0)
+ goto err2;
/* FIXME 'urbs' should be a per-device thing, maybe in usbcore */
device_create_file (dummy_dev(dum), &dev_attr_urbs);
-
- dum->started = 1;
return 0;
+
+ err2:
+ usb_disconnect (&hcd->self.root_hub);
+ err1:
+ usb_put_dev (root);
+ hcd->state = HC_STATE_QUIESCING;
+ return retval;
}
static void dummy_stop (struct usb_hcd *hcd)
@@ -1680,9 +1678,6 @@ static void dummy_stop (struct usb_hcd *hcd)
struct dummy *dum;
dum = hcd_to_dummy (hcd);
- if (!dum->started)
- return;
- dum->started = 0;
device_remove_file (dummy_dev(dum), &dev_attr_urbs);
@@ -1718,71 +1713,33 @@ static const struct hc_driver dummy_hcd = {
.hub_control = dummy_hub_control,
};
-static void dummy_remove (struct device *dev);
-
static int dummy_probe (struct device *dev)
{
struct usb_hcd *hcd;
- struct dummy *dum;
int retval;
dev_info (dev, "%s, driver " DRIVER_VERSION "\n", driver_desc);
- hcd = usb_create_hcd (&dummy_hcd);
- if (hcd == NULL) {
- dev_dbg (dev, "hcd_alloc failed\n");
+ hcd = usb_create_hcd (&dummy_hcd, dev, dev->bus_id);
+ if (!hcd)
return -ENOMEM;
- }
+ the_controller = hcd_to_dummy (hcd);
- dev_set_drvdata (dev, hcd);
- dum = hcd_to_dummy (hcd);
- the_controller = dum;
-
- hcd->self.controller = dev;
-
- /* FIXME don't require the pci-based buffer/alloc impls;
- * the "generic dma" implementation still requires them,
- * it's not very generic yet.
- */
- retval = hcd_buffer_create (hcd);
+ retval = usb_add_hcd(hcd, 0, 0);
if (retval != 0) {
- dev_dbg (dev, "pool alloc failed\n");
- goto err1;
+ usb_put_hcd (hcd);
+ the_controller = NULL;
}
-
- hcd->self.bus_name = dev->bus_id;
- usb_register_bus (&hcd->self);
-
- if ((retval = dummy_start (hcd)) < 0)
- dummy_remove (dev);
- return retval;
-
-err1:
- usb_put_hcd (hcd);
- dev_set_drvdata (dev, NULL);
return retval;
}
static void dummy_remove (struct device *dev)
{
struct usb_hcd *hcd;
- struct dummy *dum;
hcd = dev_get_drvdata (dev);
- dum = hcd_to_dummy (hcd);
-
- hcd->state = USB_STATE_QUIESCING;
-
- dev_dbg (dev, "roothub graceful disconnect\n");
- usb_disconnect (&hcd->self.root_hub);
-
- hcd->driver->stop (hcd);
- hcd->state = USB_STATE_HALT;
-
- hcd_buffer_destroy (hcd);
-
- dev_set_drvdata (dev, NULL);
- usb_deregister_bus (&hcd->self);
+ usb_remove_hcd (hcd);
+ usb_put_hcd (hcd);
the_controller = NULL;
}
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index 48ec722d3091d..cff9fb0b73cc0 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -1,7 +1,7 @@
/*
* ether.c -- Ethernet gadget driver, with CDC and non-CDC options
*
- * Copyright (C) 2003-2004 David Brownell
+ * Copyright (C) 2003-2005 David Brownell
* Copyright (C) 2003-2004 Robert Schwebel, Benedikt Spranger
*
* This program is free software; you can redistribute it and/or modify
@@ -49,6 +49,7 @@
#include <asm/unaligned.h>
#include <linux/usb_ch9.h>
+#include <linux/usb_cdc.h>
#include <linux/usb_gadget.h>
#include <linux/random.h>
@@ -97,12 +98,18 @@ static const char driver_desc [] = DRIVER_DESC;
#define rndis_exit() do{}while(0)
#endif
+/* CDC and RNDIS support the same host-chosen outgoing packet filters. */
+#define DEFAULT_FILTER (USB_CDC_PACKET_TYPE_BROADCAST \
+ |USB_CDC_PACKET_TYPE_DIRECTED)
+
+
/*-------------------------------------------------------------------------*/
struct eth_dev {
spinlock_t lock;
struct usb_gadget *gadget;
struct usb_request *req; /* for control responses */
+ struct usb_request *stat_req; /* for cdc & rndis status */
u8 config;
struct usb_ep *in_ep, *out_ep, *status_ep;
@@ -198,7 +205,7 @@ MODULE_PARM_DESC(iProduct, "USB Product string");
/* initial value, changed by "ifconfig usb0 hw ether xx:xx:xx:xx:xx:xx" */
static char *__initdata dev_addr;
module_param(dev_addr, charp, S_IRUGO);
-MODULE_PARM_DESC(iProduct, "Device Ethernet Address");
+MODULE_PARM_DESC(dev_addr, "Device Ethernet Address");
/* this address is invisible to ifconfig */
static char *__initdata host_addr;
@@ -242,6 +249,10 @@ MODULE_PARM_DESC(host_addr, "Host Ethernet Address");
#define DEV_CONFIG_CDC
#endif
+#ifdef CONFIG_USB_GADGET_AT91
+#define DEV_CONFIG_CDC
+#endif
+
/* For CDC-incapable hardware, choose the simple cdc subset.
* Anything that talks bulk (without notable bugs) can do this.
@@ -259,11 +270,45 @@ MODULE_PARM_DESC(host_addr, "Host Ethernet Address");
#define DEV_CONFIG_SUBSET
#endif
+#ifdef CONFIG_USB_GADGET_S3C2410
+#define DEV_CONFIG_CDC
+#endif
/*-------------------------------------------------------------------------*/
+/* "main" config is either CDC, or its simple subset */
+static inline int is_cdc(struct eth_dev *dev)
+{
+#if !defined(DEV_CONFIG_SUBSET)
+ return 1; /* only cdc possible */
+#elif !defined (DEV_CONFIG_CDC)
+ return 0; /* only subset possible */
+#else
+ return dev->cdc; /* depends on what hardware we found */
+#endif
+}
+
+/* "secondary" RNDIS config may sometimes be activated */
+static inline int rndis_active(struct eth_dev *dev)
+{
+#ifdef CONFIG_USB_ETH_RNDIS
+ return dev->rndis;
+#else
+ return 0;
+#endif
+}
+
+#define subset_active(dev) (!is_cdc(dev) && !rndis_active(dev))
+#define cdc_active(dev) ( is_cdc(dev) && !rndis_active(dev))
+
+
+
#define DEFAULT_QLEN 2 /* double buffering by default */
+/* peak bulk transfer bits-per-second */
+#define HS_BPS (13 * 512 * 8 * 1000 * 8)
+#define FS_BPS (19 * 64 * 1 * 1000 * 8)
+
#ifdef CONFIG_USB_GADGET_DUALSPEED
static unsigned qmult = 5;
@@ -277,12 +322,12 @@ module_param (qmult, uint, S_IRUGO|S_IWUSR);
/* also defer IRQs on highspeed TX */
#define TX_DELAY qmult
-#define BITRATE(g) ((g->speed == USB_SPEED_HIGH) ? 4800000 : 120000)
+#define BITRATE(g) (((g)->speed == USB_SPEED_HIGH) ? HS_BPS : FS_BPS)
#else /* full speed (low speed doesn't do bulk) */
#define qlen(gadget) DEFAULT_QLEN
-#define BITRATE(g) (12000)
+#define BITRATE(g) FS_BPS
#endif
@@ -432,8 +477,8 @@ control_intf = {
/* status endpoint is optional; this may be patched later */
.bNumEndpoints = 1,
.bInterfaceClass = USB_CLASS_COMM,
- .bInterfaceSubClass = 6, /* ethernet control model */
- .bInterfaceProtocol = 0,
+ .bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET,
+ .bInterfaceProtocol = USB_CDC_PROTO_NONE,
.iInterface = STRING_CONTROL,
};
#endif
@@ -447,46 +492,26 @@ rndis_control_intf = {
.bInterfaceNumber = 0,
.bNumEndpoints = 1,
.bInterfaceClass = USB_CLASS_COMM,
- .bInterfaceSubClass = 2, /* abstract control model */
- .bInterfaceProtocol = 0xff, /* vendor specific */
+ .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM,
+ .bInterfaceProtocol = USB_CDC_ACM_PROTO_VENDOR,
.iInterface = STRING_RNDIS_CONTROL,
};
#endif
#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)
-/* "Header Functional Descriptor" from CDC spec 5.2.3.1 */
-struct header_desc {
- u8 bLength;
- u8 bDescriptorType;
- u8 bDescriptorSubType;
-
- u16 bcdCDC;
-} __attribute__ ((packed));
-
-static const struct header_desc header_desc = {
+static const struct usb_cdc_header_desc header_desc = {
.bLength = sizeof header_desc,
.bDescriptorType = USB_DT_CS_INTERFACE,
- .bDescriptorSubType = 0,
+ .bDescriptorSubType = USB_CDC_HEADER_TYPE,
.bcdCDC = __constant_cpu_to_le16 (0x0110),
};
-/* "Union Functional Descriptor" from CDC spec 5.2.3.8 */
-struct union_desc {
- u8 bLength;
- u8 bDescriptorType;
- u8 bDescriptorSubType;
-
- u8 bMasterInterface0;
- u8 bSlaveInterface0;
- /* ... and there could be other slave interfaces */
-} __attribute__ ((packed));
-
-static const struct union_desc union_desc = {
+static const struct usb_cdc_union_desc union_desc = {
.bLength = sizeof union_desc,
.bDescriptorType = USB_DT_CS_INTERFACE,
- .bDescriptorSubType = 6,
+ .bDescriptorSubType = USB_CDC_UNION_TYPE,
.bMasterInterface0 = 0, /* index of control interface */
.bSlaveInterface0 = 1, /* index of DATA interface */
@@ -496,64 +521,31 @@ static const struct union_desc union_desc = {
#ifdef CONFIG_USB_ETH_RNDIS
-/* "Call Management Descriptor" from CDC spec 5.2.3.3 */
-struct call_mgmt_descriptor {
- u8 bLength;
- u8 bDescriptorType;
- u8 bDescriptorSubType;
-
- u8 bmCapabilities;
- u8 bDataInterface;
-} __attribute__ ((packed));
-
-static const struct call_mgmt_descriptor call_mgmt_descriptor = {
+static const struct usb_cdc_call_mgmt_descriptor call_mgmt_descriptor = {
.bLength = sizeof call_mgmt_descriptor,
.bDescriptorType = USB_DT_CS_INTERFACE,
- .bDescriptorSubType = 0x01,
+ .bDescriptorSubType = USB_CDC_CALL_MANAGEMENT_TYPE,
.bmCapabilities = 0x00,
.bDataInterface = 0x01,
};
-
-/* "Abstract Control Management Descriptor" from CDC spec 5.2.3.4 */
-struct acm_descriptor {
- u8 bLength;
- u8 bDescriptorType;
- u8 bDescriptorSubType;
-
- u8 bmCapabilities;
-} __attribute__ ((packed));
-
-static struct acm_descriptor acm_descriptor = {
+static struct usb_cdc_acm_descriptor acm_descriptor = {
.bLength = sizeof acm_descriptor,
.bDescriptorType = USB_DT_CS_INTERFACE,
- .bDescriptorSubType = 0x02,
+ .bDescriptorSubType = USB_CDC_ACM_TYPE,
- .bmCapabilities = 0X00,
+ .bmCapabilities = 0x00,
};
#endif
#ifdef DEV_CONFIG_CDC
-/* "Ethernet Networking Functional Descriptor" from CDC spec 5.2.3.16 */
-struct ether_desc {
- u8 bLength;
- u8 bDescriptorType;
- u8 bDescriptorSubType;
-
- u8 iMACAddress;
- u32 bmEthernetStatistics;
- u16 wMaxSegmentSize;
- u16 wNumberMCFilters;
- u8 bNumberPowerFilters;
-} __attribute__ ((packed));
-
-static const struct ether_desc ether_desc = {
+static const struct usb_cdc_ether_desc ether_desc = {
.bLength = sizeof ether_desc,
.bDescriptorType = USB_DT_CS_INTERFACE,
- .bDescriptorSubType = 0x0f,
+ .bDescriptorSubType = USB_CDC_ETHERNET_TYPE,
/* this descriptor actually adds value, surprise! */
.iMACAddress = STRING_ETHADDR,
@@ -568,9 +560,8 @@ static const struct ether_desc ether_desc = {
#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)
/* include the status endpoint if we can, even where it's optional.
- * use small wMaxPacketSize, since many "interrupt" endpoints have
- * very small fifos and it's no big deal if CDC_NOTIFY_SPEED_CHANGE
- * takes two packets. also default to a big transfer interval, to
+ * use wMaxPacketSize big enough to fit CDC_NOTIFY_SPEED_CHANGE in one
+ * packet, to simplify cancelation; and a big transfer interval, to
* waste less bandwidth.
*
* some drivers (like Linux 2.4 cdc-ether!) "need" it to exist even
@@ -583,7 +574,7 @@ static const struct ether_desc ether_desc = {
*/
#define LOG2_STATUS_INTERVAL_MSEC 5 /* 1 << 5 == 32 msec */
-#define STATUS_BYTECOUNT 8 /* 8 byte header + data */
+#define STATUS_BYTECOUNT 16 /* 8 byte header + data */
static struct usb_endpoint_descriptor
fs_status_desc = {
@@ -965,14 +956,12 @@ static inline int ether_alt_ep_setup (struct eth_dev *dev, struct usb_ep *ep)
if (strcmp (ep->name, EP_IN_NAME) == 0) {
d = ep_desc (dev->gadget, &hs_source_desc, &fs_source_desc);
ep->driver_data = dev;
- dev->in_ep = ep;
dev->in = d;
/* one endpoint just reads OUT packets */
} else if (strcmp (ep->name, EP_OUT_NAME) == 0) {
d = ep_desc (dev->gadget, &hs_sink_desc, &fs_sink_desc);
ep->driver_data = dev;
- dev->out_ep = ep;
dev->out = d;
/* optional status/notification endpoint */
@@ -986,7 +975,6 @@ static inline int ether_alt_ep_setup (struct eth_dev *dev, struct usb_ep *ep)
return result;
ep->driver_data = dev;
- dev->status_ep = ep;
dev->status = d;
}
return 0;
@@ -1013,7 +1001,6 @@ static inline int ether_ep_setup (struct eth_dev *dev, struct usb_ep *ep)
return result;
ep->driver_data = dev;
- dev->in_ep = ep;
dev->in = d;
/* one endpoint just reads OUT packets */
@@ -1024,7 +1011,6 @@ static inline int ether_ep_setup (struct eth_dev *dev, struct usb_ep *ep)
return result;
ep->driver_data = dev;
- dev->out_ep = ep;
dev->out = d;
}
@@ -1055,7 +1041,6 @@ set_ether_config (struct eth_dev *dev, int gfp_flags)
result = usb_ep_enable (ep, d);
if (result == 0) {
ep->driver_data = dev;
- dev->status_ep = ep;
dev->status = d;
continue;
}
@@ -1083,22 +1068,19 @@ set_ether_config (struct eth_dev *dev, int gfp_flags)
/* on error, disable any endpoints */
if (result < 0) {
#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)
- if (dev->status_ep)
+ if (dev->status)
(void) usb_ep_disable (dev->status_ep);
#endif
- dev->status_ep = NULL;
dev->status = NULL;
#if defined(DEV_CONFIG_SUBSET) || defined(CONFIG_USB_ETH_RNDIS)
if (dev->rndis || !dev->cdc) {
- if (dev->in_ep)
+ if (dev->in)
(void) usb_ep_disable (dev->in_ep);
- if (dev->out_ep)
+ if (dev->out)
(void) usb_ep_disable (dev->out_ep);
}
#endif
- dev->in_ep = NULL;
dev->in = NULL;
- dev->out_ep = NULL;
dev->out = NULL;
} else
@@ -1138,7 +1120,7 @@ static void eth_reset_config (struct eth_dev *dev)
/* disable endpoints, forcing (synchronous) completion of
* pending i/o. then free the requests.
*/
- if (dev->in_ep) {
+ if (dev->in) {
usb_ep_disable (dev->in_ep);
while (likely (!list_empty (&dev->tx_reqs))) {
req = container_of (dev->tx_reqs.next,
@@ -1146,9 +1128,8 @@ static void eth_reset_config (struct eth_dev *dev)
list_del (&req->list);
usb_ep_free_request (dev->in_ep, req);
}
- dev->in_ep = NULL;
}
- if (dev->out_ep) {
+ if (dev->out) {
usb_ep_disable (dev->out_ep);
while (likely (!list_empty (&dev->rx_reqs))) {
req = container_of (dev->rx_reqs.next,
@@ -1156,12 +1137,10 @@ static void eth_reset_config (struct eth_dev *dev)
list_del (&req->list);
usb_ep_free_request (dev->out_ep, req);
}
- dev->out_ep = NULL;
}
- if (dev->status_ep) {
+ if (dev->status) {
usb_ep_disable (dev->status_ep);
- dev->status_ep = NULL;
}
dev->config = 0;
}
@@ -1242,67 +1221,44 @@ eth_set_config (struct eth_dev *dev, unsigned number, int gfp_flags)
/*-------------------------------------------------------------------------*/
-/* section 3.8.2 table 11 of the CDC spec lists Ethernet notifications
- * section 3.6.2.1 table 5 specifies ACM notifications, accepted by RNDIS
- * and RNDIS also defines its own bit-incompatible notifications
- */
-#define CDC_NOTIFY_NETWORK_CONNECTION 0x00 /* required; 6.3.1 */
-#define CDC_NOTIFY_RESPONSE_AVAILABLE 0x01 /* optional; 6.3.2 */
-#define CDC_NOTIFY_SPEED_CHANGE 0x2a /* required; 6.3.8 */
-
#ifdef DEV_CONFIG_CDC
-struct cdc_notification {
- u8 bmRequestType;
- u8 bNotificationType;
- u16 wValue;
- u16 wIndex;
- u16 wLength;
-
- /* SPEED_CHANGE data looks like this */
- u32 data [2];
-};
-
static void eth_status_complete (struct usb_ep *ep, struct usb_request *req)
{
- struct cdc_notification *event = req->buf;
- int value = req->status;
- struct eth_dev *dev = ep->driver_data;
+ struct usb_cdc_notification *event = req->buf;
+ int value = req->status;
+ struct eth_dev *dev = ep->driver_data;
/* issue the second notification if host reads the first */
- if (event->bNotificationType == CDC_NOTIFY_NETWORK_CONNECTION
+ if (event->bNotificationType == USB_CDC_NOTIFY_NETWORK_CONNECTION
&& value == 0) {
+ __le32 *data = req->buf + sizeof *event;
+
event->bmRequestType = 0xA1;
- event->bNotificationType = CDC_NOTIFY_SPEED_CHANGE;
+ event->bNotificationType = USB_CDC_NOTIFY_SPEED_CHANGE;
event->wValue = __constant_cpu_to_le16 (0);
event->wIndex = __constant_cpu_to_le16 (1);
event->wLength = __constant_cpu_to_le16 (8);
/* SPEED_CHANGE data is up/down speeds in bits/sec */
- event->data [0] = event->data [1] =
- (dev->gadget->speed == USB_SPEED_HIGH)
- ? (13 * 512 * 8 * 1000 * 8)
- : (19 * 64 * 1 * 1000 * 8);
+ data [0] = data [1] = cpu_to_le32 (BITRATE (dev->gadget));
- req->length = 16;
+ req->length = STATUS_BYTECOUNT;
value = usb_ep_queue (ep, req, GFP_ATOMIC);
DEBUG (dev, "send SPEED_CHANGE --> %d\n", value);
if (value == 0)
return;
- } else
+ } else if (value != -ECONNRESET)
DEBUG (dev, "event %02x --> %d\n",
event->bNotificationType, value);
-
- /* free when done */
- usb_ep_free_buffer (ep, req->buf, req->dma, 16);
- usb_ep_free_request (ep, req);
+ event->bmRequestType = 0xff;
}
static void issue_start_status (struct eth_dev *dev)
{
- struct usb_request *req;
- struct cdc_notification *event;
- int value;
+ struct usb_request *req = dev->stat_req;
+ struct usb_cdc_notification *event;
+ int value;
DEBUG (dev, "%s, flush old status first\n", __FUNCTION__);
@@ -1316,40 +1272,21 @@ static void issue_start_status (struct eth_dev *dev)
usb_ep_disable (dev->status_ep);
usb_ep_enable (dev->status_ep, dev->status);
- /* FIXME make these allocations static like dev->req */
- req = usb_ep_alloc_request (dev->status_ep, GFP_ATOMIC);
- if (req == 0) {
- DEBUG (dev, "status ENOMEM\n");
- return;
- }
- req->buf = usb_ep_alloc_buffer (dev->status_ep, 16,
- &dev->req->dma, GFP_ATOMIC);
- if (req->buf == 0) {
- DEBUG (dev, "status buf ENOMEM\n");
-free_req:
- usb_ep_free_request (dev->status_ep, req);
- return;
- }
-
/* 3.8.1 says to issue first NETWORK_CONNECTION, then
* a SPEED_CHANGE. could be useful in some configs.
*/
event = req->buf;
event->bmRequestType = 0xA1;
- event->bNotificationType = CDC_NOTIFY_NETWORK_CONNECTION;
+ event->bNotificationType = USB_CDC_NOTIFY_NETWORK_CONNECTION;
event->wValue = __constant_cpu_to_le16 (1); /* connected */
event->wIndex = __constant_cpu_to_le16 (1);
event->wLength = 0;
- req->length = 8;
+ req->length = sizeof *event;
req->complete = eth_status_complete;
value = usb_ep_queue (dev->status_ep, req, GFP_ATOMIC);
- if (value < 0) {
+ if (value < 0)
DEBUG (dev, "status buf queue --> %d\n", value);
- usb_ep_free_buffer (dev->status_ep,
- req->buf, dev->req->dma, 16);
- goto free_req;
- }
}
#endif
@@ -1364,26 +1301,6 @@ static void eth_setup_complete (struct usb_ep *ep, struct usb_request *req)
req->status, req->actual, req->length);
}
-/* see section 3.8.2 table 10 of the CDC spec for more ethernet
- * requests, mostly for filters (multicast, pm) and statistics
- * section 3.6.2.1 table 4 has ACM requests; RNDIS requires the
- * encapsulated command mechanism.
- */
-#define CDC_SEND_ENCAPSULATED_COMMAND 0x00 /* optional */
-#define CDC_GET_ENCAPSULATED_RESPONSE 0x01 /* optional */
-#define CDC_SET_ETHERNET_MULTICAST_FILTERS 0x40 /* optional */
-#define CDC_SET_ETHERNET_PM_PATTERN_FILTER 0x41 /* optional */
-#define CDC_GET_ETHERNET_PM_PATTERN_FILTER 0x42 /* optional */
-#define CDC_SET_ETHERNET_PACKET_FILTER 0x43 /* required */
-#define CDC_GET_ETHERNET_STATISTIC 0x44 /* optional */
-
-/* table 62; bits in cdc_filter */
-#define CDC_PACKET_TYPE_PROMISCUOUS (1 << 0)
-#define CDC_PACKET_TYPE_ALL_MULTICAST (1 << 1) /* no filter */
-#define CDC_PACKET_TYPE_DIRECTED (1 << 2)
-#define CDC_PACKET_TYPE_BROADCAST (1 << 3)
-#define CDC_PACKET_TYPE_MULTICAST (1 << 4) /* filtered */
-
#ifdef CONFIG_USB_ETH_RNDIS
static void rndis_response_complete (struct usb_ep *ep, struct usb_request *req)
@@ -1393,7 +1310,7 @@ static void rndis_response_complete (struct usb_ep *ep, struct usb_request *req)
"rndis response complete --> %d, %d/%d\n",
req->status, req->actual, req->length);
- /* done sending after CDC_GET_ENCAPSULATED_RESPONSE */
+ /* done sending after USB_CDC_GET_ENCAPSULATED_RESPONSE */
}
static void rndis_command_complete (struct usb_ep *ep, struct usb_request *req)
@@ -1401,7 +1318,7 @@ static void rndis_command_complete (struct usb_ep *ep, struct usb_request *req)
struct eth_dev *dev = ep->driver_data;
int status;
- /* received RNDIS command from CDC_SEND_ENCAPSULATED_COMMAND */
+ /* received RNDIS command from USB_CDC_SEND_ENCAPSULATED_COMMAND */
spin_lock(&dev->lock);
status = rndis_msg_parser (dev->rndis_config, (u8 *) req->buf);
if (status < 0)
@@ -1426,6 +1343,9 @@ eth_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
struct eth_dev *dev = get_gadget_data (gadget);
struct usb_request *req = dev->req;
int value = -EOPNOTSUPP;
+ u16 wIndex = ctrl->wIndex;
+ u16 wValue = ctrl->wValue;
+ u16 wLength = ctrl->wLength;
/* descriptors just go into the pre-allocated ep0 buffer,
* while config change events may enable network traffic.
@@ -1436,17 +1356,17 @@ eth_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
case USB_REQ_GET_DESCRIPTOR:
if (ctrl->bRequestType != USB_DIR_IN)
break;
- switch (ctrl->wValue >> 8) {
+ switch (wValue >> 8) {
case USB_DT_DEVICE:
- value = min (ctrl->wLength, (u16) sizeof device_desc);
+ value = min (wLength, (u16) sizeof device_desc);
memcpy (req->buf, &device_desc, value);
break;
#ifdef CONFIG_USB_GADGET_DUALSPEED
case USB_DT_DEVICE_QUALIFIER:
if (!gadget->is_dualspeed)
break;
- value = min (ctrl->wLength, (u16) sizeof dev_qualifier);
+ value = min (wLength, (u16) sizeof dev_qualifier);
memcpy (req->buf, &dev_qualifier, value);
break;
@@ -1457,18 +1377,18 @@ eth_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
#endif /* CONFIG_USB_GADGET_DUALSPEED */
case USB_DT_CONFIG:
value = config_buf (gadget->speed, req->buf,
- ctrl->wValue >> 8,
- ctrl->wValue & 0xff,
+ wValue >> 8,
+ wValue & 0xff,
gadget->is_otg);
if (value >= 0)
- value = min (ctrl->wLength, (u16) value);
+ value = min (wLength, (u16) value);
break;
case USB_DT_STRING:
value = usb_gadget_get_string (&stringtab,
- ctrl->wValue & 0xff, req->buf);
+ wValue & 0xff, req->buf);
if (value >= 0)
- value = min (ctrl->wLength, (u16) value);
+ value = min (wLength, (u16) value);
break;
}
break;
@@ -1481,22 +1401,22 @@ eth_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
else if (gadget->a_alt_hnp_support)
DEBUG (dev, "HNP needs a different root port\n");
spin_lock (&dev->lock);
- value = eth_set_config (dev, ctrl->wValue, GFP_ATOMIC);
+ value = eth_set_config (dev, wValue, GFP_ATOMIC);
spin_unlock (&dev->lock);
break;
case USB_REQ_GET_CONFIGURATION:
if (ctrl->bRequestType != USB_DIR_IN)
break;
*(u8 *)req->buf = dev->config;
- value = min (ctrl->wLength, (u16) 1);
+ value = min (wLength, (u16) 1);
break;
case USB_REQ_SET_INTERFACE:
if (ctrl->bRequestType != USB_RECIP_INTERFACE
|| !dev->config
- || ctrl->wIndex > 1)
+ || wIndex > 1)
break;
- if (!dev->cdc && ctrl->wIndex != 0)
+ if (!dev->cdc && wIndex != 0)
break;
spin_lock (&dev->lock);
@@ -1510,18 +1430,18 @@ eth_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
}
#ifdef DEV_CONFIG_CDC
- switch (ctrl->wIndex) {
+ switch (wIndex) {
case 0: /* control/master intf */
- if (ctrl->wValue != 0)
+ if (wValue != 0)
break;
- if (dev->status_ep) {
+ if (dev->status) {
usb_ep_disable (dev->status_ep);
usb_ep_enable (dev->status_ep, dev->status);
}
value = 0;
break;
case 1: /* data intf */
- if (ctrl->wValue > 1)
+ if (wValue > 1)
break;
usb_ep_disable (dev->in_ep);
usb_ep_disable (dev->out_ep);
@@ -1530,11 +1450,12 @@ eth_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
* the default interface setting ... also, setting
* the non-default interface clears filters etc.
*/
- if (ctrl->wValue == 1) {
+ if (wValue == 1) {
usb_ep_enable (dev->in_ep, dev->in);
usb_ep_enable (dev->out_ep, dev->out);
+ dev->cdc_filter = DEFAULT_FILTER;
netif_carrier_on (dev->net);
- if (dev->status_ep)
+ if (dev->status)
issue_start_status (dev);
if (netif_running (dev->net)) {
spin_unlock (&dev->lock);
@@ -1561,66 +1482,70 @@ done_set_intf:
case USB_REQ_GET_INTERFACE:
if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE)
|| !dev->config
- || ctrl->wIndex > 1)
+ || wIndex > 1)
break;
- if (!(dev->cdc || dev->rndis) && ctrl->wIndex != 0)
+ if (!(dev->cdc || dev->rndis) && wIndex != 0)
break;
/* for CDC, iff carrier is on, data interface is active. */
- if (dev->rndis || ctrl->wIndex != 1)
+ if (dev->rndis || wIndex != 1)
*(u8 *)req->buf = 0;
else
*(u8 *)req->buf = netif_carrier_ok (dev->net) ? 1 : 0;
- value = min (ctrl->wLength, (u16) 1);
+ value = min (wLength, (u16) 1);
break;
#ifdef DEV_CONFIG_CDC
- case CDC_SET_ETHERNET_PACKET_FILTER:
+ case USB_CDC_SET_ETHERNET_PACKET_FILTER:
/* see 6.2.30: no data, wIndex = interface,
* wValue = packet filter bitmap
*/
if (ctrl->bRequestType != (USB_TYPE_CLASS|USB_RECIP_INTERFACE)
|| !dev->cdc
|| dev->rndis
- || ctrl->wLength != 0
- || ctrl->wIndex > 1)
+ || wLength != 0
+ || wIndex > 1)
break;
- DEBUG (dev, "NOP packet filter %04x\n", ctrl->wValue);
- /* NOTE: table 62 has 5 filter bits to reduce traffic,
- * and we "must" support multicast and promiscuous.
- * this NOP implements a bad filter (always promisc)
- */
- dev->cdc_filter = ctrl->wValue;
+ DEBUG (dev, "packet filter %02x\n", wValue);
+ dev->cdc_filter = wValue;
value = 0;
break;
+
+ /* and potentially:
+ * case USB_CDC_SET_ETHERNET_MULTICAST_FILTERS:
+ * case USB_CDC_SET_ETHERNET_PM_PATTERN_FILTER:
+ * case USB_CDC_GET_ETHERNET_PM_PATTERN_FILTER:
+ * case USB_CDC_GET_ETHERNET_STATISTIC:
+ */
+
#endif /* DEV_CONFIG_CDC */
#ifdef CONFIG_USB_ETH_RNDIS
/* RNDIS uses the CDC command encapsulation mechanism to implement
* an RPC scheme, with much getting/setting of attributes by OID.
*/
- case CDC_SEND_ENCAPSULATED_COMMAND:
+ case USB_CDC_SEND_ENCAPSULATED_COMMAND:
if (ctrl->bRequestType != (USB_TYPE_CLASS|USB_RECIP_INTERFACE)
|| !dev->rndis
- || ctrl->wLength > USB_BUFSIZ
- || ctrl->wValue
+ || wLength > USB_BUFSIZ
+ || wValue
|| rndis_control_intf.bInterfaceNumber
- != ctrl->wIndex)
+ != wIndex)
break;
/* read the request, then process it */
- value = ctrl->wLength;
+ value = wLength;
req->complete = rndis_command_complete;
/* later, rndis_control_ack () sends a notification */
break;
- case CDC_GET_ENCAPSULATED_RESPONSE:
+ case USB_CDC_GET_ENCAPSULATED_RESPONSE:
if ((USB_DIR_IN|USB_TYPE_CLASS|USB_RECIP_INTERFACE)
== ctrl->bRequestType
&& dev->rndis
- // && ctrl->wLength >= 0x0400
- && !ctrl->wValue
+ // && wLength >= 0x0400
+ && !wValue
&& rndis_control_intf.bInterfaceNumber
- == ctrl->wIndex) {
+ == wIndex) {
u8 *buf;
/* return the result */
@@ -1640,13 +1565,13 @@ done_set_intf:
VDEBUG (dev,
"unknown control req%02x.%02x v%04x i%04x l%d\n",
ctrl->bRequestType, ctrl->bRequest,
- ctrl->wValue, ctrl->wIndex, ctrl->wLength);
+ wValue, wIndex, wLength);
}
/* respond with data transfer before status phase? */
if (value >= 0) {
req->length = value;
- req->zero = value < ctrl->wLength
+ req->zero = value < wLength
&& (value % gadget->ep0->maxpacket) == 0;
value = usb_ep_queue (gadget->ep0, req, GFP_ATOMIC);
if (value < 0) {
@@ -1761,10 +1686,16 @@ rx_submit (struct eth_dev *dev, struct usb_request *req, int gfp_flags)
#endif
size -= size % dev->out_ep->maxpacket;
- if ((skb = alloc_skb (size, gfp_flags)) == 0) {
+ if ((skb = alloc_skb (size + NET_IP_ALIGN, gfp_flags)) == 0) {
DEBUG (dev, "no rx skb\n");
goto enomem;
}
+
+ /* Some platforms perform better when IP packets are aligned,
+ * but on at least one, checksumming fails otherwise. Note:
+ * this doesn't account for variable-sized RNDIS headers.
+ */
+ skb_reserve(skb, NET_IP_ALIGN);
req->buf = skb->data;
req->length = size;
@@ -1981,6 +1912,14 @@ static void tx_complete (struct usb_ep *ep, struct usb_request *req)
netif_wake_queue (dev->net);
}
+static inline int eth_is_promisc (struct eth_dev *dev)
+{
+ /* no filters for the CDC subset; always promisc */
+ if (subset_active (dev))
+ return 1;
+ return dev->cdc_filter & USB_CDC_PACKET_TYPE_PROMISCUOUS;
+}
+
static int eth_start_xmit (struct sk_buff *skb, struct net_device *net)
{
struct eth_dev *dev = netdev_priv(net);
@@ -1989,10 +1928,27 @@ static int eth_start_xmit (struct sk_buff *skb, struct net_device *net)
struct usb_request *req = NULL;
unsigned long flags;
- /* FIXME check dev->cdc_filter to decide whether to send this,
- * instead of acting as if CDC_PACKET_TYPE_PROMISCUOUS were
- * always set. RNDIS has the same kind of outgoing filter.
- */
+ /* apply outgoing CDC or RNDIS filters */
+ if (!eth_is_promisc (dev)) {
+ u8 *dest = skb->data;
+
+ if (dest [0] & 0x01) {
+ u16 type;
+
+ /* ignores USB_CDC_PACKET_TYPE_MULTICAST and host
+ * SET_ETHERNET_MULTICAST_FILTERS requests
+ */
+ if (memcmp (dest, net->broadcast, ETH_ALEN) == 0)
+ type = USB_CDC_PACKET_TYPE_BROADCAST;
+ else
+ type = USB_CDC_PACKET_TYPE_ALL_MULTICAST;
+ if (!(dev->cdc_filter & type)) {
+ dev_kfree_skb_any (skb);
+ return 0;
+ }
+ }
+ /* ignores USB_CDC_PACKET_TYPE_DIRECTED */
+ }
spin_lock_irqsave (&dev->lock, flags);
req = container_of (dev->tx_reqs.next, struct usb_request, list);
@@ -2124,13 +2080,13 @@ static int rndis_control_ack (struct net_device *net)
}
/* Send RNDIS RESPONSE_AVAILABLE notification;
- * CDC_NOTIFY_RESPONSE_AVAILABLE should work too
+ * USB_CDC_NOTIFY_RESPONSE_AVAILABLE should work too
*/
resp->length = 8;
resp->complete = rndis_control_ack_complete;
- *((u32 *) resp->buf) = __constant_cpu_to_le32 (1);
- *((u32 *) resp->buf + 1) = __constant_cpu_to_le32 (0);
+ *((__le32 *) resp->buf) = __constant_cpu_to_le32 (1);
+ *((__le32 *) resp->buf + 1) = __constant_cpu_to_le32 (0);
length = usb_ep_queue (dev->status_ep, resp, GFP_ATOMIC);
if (length < 0) {
@@ -2214,6 +2170,30 @@ static int eth_stop (struct net_device *net)
/*-------------------------------------------------------------------------*/
+static struct usb_request *eth_req_alloc (struct usb_ep *ep, unsigned size)
+{
+ struct usb_request *req;
+
+ req = usb_ep_alloc_request (ep, GFP_KERNEL);
+ if (!req)
+ return NULL;
+
+ req->buf = kmalloc (size, GFP_KERNEL);
+ if (!req->buf) {
+ usb_ep_free_request (ep, req);
+ req = NULL;
+ }
+ return req;
+}
+
+static void
+eth_req_free (struct usb_ep *ep, struct usb_request *req)
+{
+ kfree (req->buf);
+ usb_ep_free_request (ep, req);
+}
+
+
static void
eth_unbind (struct usb_gadget *gadget)
{
@@ -2227,12 +2207,13 @@ eth_unbind (struct usb_gadget *gadget)
/* we've already been disconnected ... no i/o is active */
if (dev->req) {
- usb_ep_free_buffer (gadget->ep0,
- dev->req->buf, dev->req->dma,
- USB_BUFSIZ);
- usb_ep_free_request (gadget->ep0, dev->req);
+ eth_req_free (gadget->ep0, dev->req);
dev->req = NULL;
}
+ if (dev->stat_req) {
+ eth_req_free (dev->status_ep, dev->stat_req);
+ dev->stat_req = NULL;
+ }
unregister_netdev (dev->net);
free_netdev(dev->net);
@@ -2278,7 +2259,7 @@ eth_bind (struct usb_gadget *gadget)
struct eth_dev *dev;
struct net_device *net;
u8 cdc = 1, zlp = 1, rndis = 1;
- struct usb_ep *ep;
+ struct usb_ep *in_ep, *out_ep, *status_ep = NULL;
int status = -ENOMEM;
/* these flags are only ever cleared; compiler take note */
@@ -2326,6 +2307,10 @@ eth_bind (struct usb_gadget *gadget)
device_desc.bcdDevice = __constant_cpu_to_le16 (0x0210);
} else if (gadget_is_pxa27x(gadget)) {
device_desc.bcdDevice = __constant_cpu_to_le16 (0x0211);
+ } else if (gadget_is_s3c2410(gadget)) {
+ device_desc.bcdDevice = __constant_cpu_to_le16 (0x0212);
+ } else if (gadget_is_at91(gadget)) {
+ device_desc.bcdDevice = __constant_cpu_to_le16 (0x0213);
} else {
/* can't assume CDC works. don't want to default to
* anything less functional on CDC-capable hardware,
@@ -2383,40 +2368,43 @@ eth_bind (struct usb_gadget *gadget)
/* all we really need is bulk IN/OUT */
usb_ep_autoconfig_reset (gadget);
- ep = usb_ep_autoconfig (gadget, &fs_source_desc);
- if (!ep) {
+ in_ep = usb_ep_autoconfig (gadget, &fs_source_desc);
+ if (!in_ep) {
autoconf_fail:
dev_err (&gadget->dev,
"can't autoconfigure on %s\n",
gadget->name);
return -ENODEV;
}
- EP_IN_NAME = ep->name;
- ep->driver_data = ep; /* claim */
+ EP_IN_NAME = in_ep->name;
+ in_ep->driver_data = in_ep; /* claim */
- ep = usb_ep_autoconfig (gadget, &fs_sink_desc);
- if (!ep)
+ out_ep = usb_ep_autoconfig (gadget, &fs_sink_desc);
+ if (!out_ep)
goto autoconf_fail;
- EP_OUT_NAME = ep->name;
- ep->driver_data = ep; /* claim */
+ EP_OUT_NAME = out_ep->name;
+ out_ep->driver_data = out_ep; /* claim */
#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)
/* CDC Ethernet control interface doesn't require a status endpoint.
* Since some hosts expect one, try to allocate one anyway.
*/
if (cdc || rndis) {
- ep = usb_ep_autoconfig (gadget, &fs_status_desc);
- if (ep) {
- EP_STATUS_NAME = ep->name;
- ep->driver_data = ep; /* claim */
+ status_ep = usb_ep_autoconfig (gadget, &fs_status_desc);
+ if (status_ep) {
+ EP_STATUS_NAME = status_ep->name;
+ status_ep->driver_data = status_ep; /* claim */
} else if (rndis) {
dev_err (&gadget->dev,
"can't run RNDIS on %s\n",
gadget->name);
return -ENODEV;
+#ifdef DEV_CONFIG_CDC
+ /* pxa25x only does CDC subset; often used with RNDIS */
} else if (cdc) {
control_intf.bNumEndpoints = 0;
/* FIXME remove endpoint from descriptor list */
+#endif
}
}
#endif
@@ -2481,6 +2469,10 @@ autoconf_fail:
dev->cdc = cdc;
dev->zlp = zlp;
+ dev->in_ep = in_ep;
+ dev->out_ep = out_ep;
+ dev->status_ep = status_ep;
+
/* Module params for these addresses should come from ID proms.
* The host side address is used with CDC and RNDIS, and commonly
* ends up in a persistent config database.
@@ -2514,16 +2506,20 @@ autoconf_fail:
// set_multicast_list
SET_ETHTOOL_OPS(net, &ops);
- /* preallocate control response and buffer */
- dev->req = usb_ep_alloc_request (gadget->ep0, GFP_KERNEL);
+ /* preallocate control message data and buffer */
+ dev->req = eth_req_alloc (gadget->ep0, USB_BUFSIZ);
if (!dev->req)
goto fail;
dev->req->complete = eth_setup_complete;
- dev->req->buf = usb_ep_alloc_buffer (gadget->ep0, USB_BUFSIZ,
- &dev->req->dma, GFP_KERNEL);
- if (!dev->req->buf) {
- usb_ep_free_request (gadget->ep0, dev->req);
- goto fail;
+
+ /* ... and maybe likewise for status transfer */
+ if (dev->status_ep) {
+ dev->stat_req = eth_req_alloc (dev->status_ep,
+ STATUS_BYTECOUNT);
+ if (!dev->stat_req) {
+ eth_req_free (gadget->ep0, dev->req);
+ goto fail;
+ }
}
/* finish hookup to lower layer ... */
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
index ae82b80748aee..4857f0e4ef449 100644
--- a/drivers/usb/gadget/file_storage.c
+++ b/drivers/usb/gadget/file_storage.c
@@ -1,7 +1,7 @@
/*
* file_storage.c -- File-backed USB Storage Gadget, for USB development
*
- * Copyright (C) 2003, 2004 Alan Stern
+ * Copyright (C) 2003-2005 Alan Stern
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -832,6 +832,8 @@ static void inline put_be32(u8 *buf, u32 val)
#define STRING_MANUFACTURER 1
#define STRING_PRODUCT 2
#define STRING_SERIAL 3
+#define STRING_CONFIG 4
+#define STRING_INTERFACE 5
/* There is only one configuration. */
#define CONFIG_VALUE 1
@@ -863,6 +865,7 @@ config_desc = {
/* wTotalLength computed by usb_gadget_config_buf() */
.bNumInterfaces = 1,
.bConfigurationValue = CONFIG_VALUE,
+ .iConfiguration = STRING_CONFIG,
.bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
.bMaxPower = 1, // self-powered
};
@@ -886,6 +889,7 @@ intf_desc = {
.bInterfaceClass = USB_CLASS_MASS_STORAGE,
.bInterfaceSubClass = USB_SC_SCSI, // Adjusted during fsg_bind()
.bInterfaceProtocol = USB_PR_BULK, // Adjusted during fsg_bind()
+ .iInterface = STRING_INTERFACE,
};
/* Three full-speed endpoint descriptors: bulk-in, bulk-out,
@@ -1009,7 +1013,7 @@ static const struct usb_descriptor_header *hs_function[] = {
/* The CBI specification limits the serial string to 12 uppercase hexadecimal
* characters. */
-static char manufacturer[50];
+static char manufacturer[64];
static char serial[13];
/* Static strings, in UTF-8 (for simplicity we use only ASCII characters) */
@@ -1017,6 +1021,8 @@ static struct usb_string strings[] = {
{STRING_MANUFACTURER, manufacturer},
{STRING_PRODUCT, longname},
{STRING_SERIAL, serial},
+ {STRING_CONFIG, "Self-powered"},
+ {STRING_INTERFACE, "Mass Storage"},
{}
};
@@ -1270,6 +1276,8 @@ static int class_setup_req(struct fsg_dev *fsg,
{
struct usb_request *req = fsg->ep0req;
int value = -EOPNOTSUPP;
+ u16 w_index = ctrl->wIndex;
+ u16 w_length = ctrl->wLength;
if (!fsg->config)
return value;
@@ -1282,7 +1290,7 @@ static int class_setup_req(struct fsg_dev *fsg,
if (ctrl->bRequestType != (USB_DIR_OUT |
USB_TYPE_CLASS | USB_RECIP_INTERFACE))
break;
- if (ctrl->wIndex != 0) {
+ if (w_index != 0) {
value = -EDOM;
break;
}
@@ -1298,13 +1306,13 @@ static int class_setup_req(struct fsg_dev *fsg,
if (ctrl->bRequestType != (USB_DIR_IN |
USB_TYPE_CLASS | USB_RECIP_INTERFACE))
break;
- if (ctrl->wIndex != 0) {
+ if (w_index != 0) {
value = -EDOM;
break;
}
VDBG(fsg, "get max LUN\n");
*(u8 *) req->buf = fsg->nluns - 1;
- value = min(ctrl->wLength, (u16) 1);
+ value = min(w_length, (u16) 1);
break;
}
}
@@ -1317,15 +1325,15 @@ static int class_setup_req(struct fsg_dev *fsg,
if (ctrl->bRequestType != (USB_DIR_OUT |
USB_TYPE_CLASS | USB_RECIP_INTERFACE))
break;
- if (ctrl->wIndex != 0) {
+ if (w_index != 0) {
value = -EDOM;
break;
}
- if (ctrl->wLength > MAX_COMMAND_SIZE) {
+ if (w_length > MAX_COMMAND_SIZE) {
value = -EOVERFLOW;
break;
}
- value = ctrl->wLength;
+ value = w_length;
fsg->ep0req->context = received_cbi_adsc;
break;
}
@@ -1336,7 +1344,7 @@ static int class_setup_req(struct fsg_dev *fsg,
"unknown class-specific control req "
"%02x.%02x v%04x i%04x l%u\n",
ctrl->bRequestType, ctrl->bRequest,
- ctrl->wValue, ctrl->wIndex, ctrl->wLength);
+ ctrl->wValue, w_index, w_length);
return value;
}
@@ -1350,6 +1358,9 @@ static int standard_setup_req(struct fsg_dev *fsg,
{
struct usb_request *req = fsg->ep0req;
int value = -EOPNOTSUPP;
+ u16 w_index = ctrl->wIndex;
+ u16 w_value = ctrl->wValue;
+ u16 w_length = ctrl->wLength;
/* Usually this just stores reply data in the pre-allocated ep0 buffer,
* but config change events will also reconfigure hardware. */
@@ -1359,11 +1370,11 @@ static int standard_setup_req(struct fsg_dev *fsg,
if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_STANDARD |
USB_RECIP_DEVICE))
break;
- switch (ctrl->wValue >> 8) {
+ switch (w_value >> 8) {
case USB_DT_DEVICE:
VDBG(fsg, "get device descriptor\n");
- value = min(ctrl->wLength, (u16) sizeof device_desc);
+ value = min(w_length, (u16) sizeof device_desc);
memcpy(req->buf, &device_desc, value);
break;
#ifdef CONFIG_USB_GADGET_DUALSPEED
@@ -1371,7 +1382,7 @@ static int standard_setup_req(struct fsg_dev *fsg,
VDBG(fsg, "get device qualifier\n");
if (!fsg->gadget->is_dualspeed)
break;
- value = min(ctrl->wLength, (u16) sizeof dev_qualifier);
+ value = min(w_length, (u16) sizeof dev_qualifier);
memcpy(req->buf, &dev_qualifier, value);
break;
@@ -1388,10 +1399,10 @@ static int standard_setup_req(struct fsg_dev *fsg,
#endif
value = populate_config_buf(fsg->gadget,
req->buf,
- ctrl->wValue >> 8,
- ctrl->wValue & 0xff);
+ w_value >> 8,
+ w_value & 0xff);
if (value >= 0)
- value = min(ctrl->wLength, (u16) value);
+ value = min(w_length, (u16) value);
break;
case USB_DT_STRING:
@@ -1399,9 +1410,9 @@ static int standard_setup_req(struct fsg_dev *fsg,
/* wIndex == language code */
value = usb_gadget_get_string(&stringtab,
- ctrl->wValue & 0xff, req->buf);
+ w_value & 0xff, req->buf);
if (value >= 0)
- value = min(ctrl->wLength, (u16) value);
+ value = min(w_length, (u16) value);
break;
}
break;
@@ -1412,8 +1423,8 @@ static int standard_setup_req(struct fsg_dev *fsg,
USB_RECIP_DEVICE))
break;
VDBG(fsg, "set configuration\n");
- if (ctrl->wValue == CONFIG_VALUE || ctrl->wValue == 0) {
- fsg->new_config = ctrl->wValue;
+ if (w_value == CONFIG_VALUE || w_value == 0) {
+ fsg->new_config = w_value;
/* Raise an exception to wipe out previous transaction
* state (queued bufs, etc) and set the new config. */
@@ -1427,14 +1438,14 @@ static int standard_setup_req(struct fsg_dev *fsg,
break;
VDBG(fsg, "get configuration\n");
*(u8 *) req->buf = fsg->config;
- value = min(ctrl->wLength, (u16) 1);
+ value = min(w_length, (u16) 1);
break;
case USB_REQ_SET_INTERFACE:
if (ctrl->bRequestType != (USB_DIR_OUT| USB_TYPE_STANDARD |
USB_RECIP_INTERFACE))
break;
- if (fsg->config && ctrl->wIndex == 0) {
+ if (fsg->config && w_index == 0) {
/* Raise an exception to wipe out previous transaction
* state (queued bufs, etc) and install the new
@@ -1449,20 +1460,20 @@ static int standard_setup_req(struct fsg_dev *fsg,
break;
if (!fsg->config)
break;
- if (ctrl->wIndex != 0) {
+ if (w_index != 0) {
value = -EDOM;
break;
}
VDBG(fsg, "get interface\n");
*(u8 *) req->buf = 0;
- value = min(ctrl->wLength, (u16) 1);
+ value = min(w_length, (u16) 1);
break;
default:
VDBG(fsg,
"unknown control req %02x.%02x v%04x i%04x l%u\n",
ctrl->bRequestType, ctrl->bRequest,
- ctrl->wValue, ctrl->wIndex, ctrl->wLength);
+ w_value, w_index, w_length);
}
return value;
@@ -3740,6 +3751,10 @@ static int __init check_parameters(struct fsg_dev *fsg)
mod_data.release = 0x0310;
else if (gadget_is_pxa27x(fsg->gadget))
mod_data.release = 0x0311;
+ else if (gadget_is_s3c2410(gadget))
+ mod_data.release = 0x0312;
+ else if (gadget_is_at91(fsg->gadget))
+ mod_data.release = 0x0313;
else {
WARN(fsg, "controller '%s' not recognized\n",
fsg->gadget->name);
diff --git a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h
index e893de9fbe33b..ea2eb52c766d6 100644
--- a/drivers/usb/gadget/gadget_chips.h
+++ b/drivers/usb/gadget/gadget_chips.h
@@ -74,7 +74,18 @@
#define gadget_is_pxa27x(g) 0
#endif
-// CONFIG_USB_GADGET_AT91RM9200
+#ifdef CONFIG_USB_GADGET_S3C2410
+#define gadget_is_s3c2410(g) !strcmp("s3c2410_udc", (g)->name)
+#else
+#define gadget_is_s3c2410(g) 0
+#endif
+
+#ifdef CONFIG_USB_GADGET_AT91
+#define gadget_is_at91(g) !strcmp("at91_udc", (g)->name)
+#else
+#define gadget_is_at91(g) 0
+#endif
+
// CONFIG_USB_GADGET_SX2
// CONFIG_USB_GADGET_AU1X00
// ...
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c
index 790b4b0b2eb54..2cff67ccce452 100644
--- a/drivers/usb/gadget/inode.c
+++ b/drivers/usb/gadget/inode.c
@@ -1318,6 +1318,8 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
struct usb_request *req = dev->req;
int value = -EOPNOTSUPP;
struct usb_gadgetfs_event *event;
+ u16 w_value = ctrl->wValue;
+ u16 w_length = ctrl->wLength;
spin_lock (&dev->lock);
dev->setup_abort = 0;
@@ -1378,17 +1380,17 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
case USB_REQ_GET_DESCRIPTOR:
if (ctrl->bRequestType != USB_DIR_IN)
goto unrecognized;
- switch (ctrl->wValue >> 8) {
+ switch (w_value >> 8) {
case USB_DT_DEVICE:
- value = min (ctrl->wLength, (u16) sizeof *dev->dev);
+ value = min (w_length, (u16) sizeof *dev->dev);
req->buf = dev->dev;
break;
#ifdef HIGHSPEED
case USB_DT_DEVICE_QUALIFIER:
if (!dev->hs_config)
break;
- value = min (ctrl->wLength, (u16)
+ value = min (w_length, (u16)
sizeof (struct usb_qualifier_descriptor));
make_qualifier (dev);
break;
@@ -1397,10 +1399,10 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
#endif
case USB_DT_CONFIG:
value = config_buf (dev,
- ctrl->wValue >> 8,
- ctrl->wValue & 0xff);
+ w_value >> 8,
+ w_value & 0xff);
if (value >= 0)
- value = min (ctrl->wLength, (u16) value);
+ value = min (w_length, (u16) value);
break;
case USB_DT_STRING:
goto unrecognized;
@@ -1414,7 +1416,7 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
case USB_REQ_SET_CONFIGURATION:
if (ctrl->bRequestType != 0)
break;
- if (0 == (u8) ctrl->wValue) {
+ if (0 == (u8) w_value) {
value = 0;
dev->current_config = 0;
usb_gadget_vbus_draw(gadget, 8 /* mA */ );
@@ -1432,7 +1434,7 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
power = dev->config->bMaxPower;
}
- if (config == (u8) ctrl->wValue) {
+ if (config == (u8) w_value) {
value = 0;
dev->current_config = config;
usb_gadget_vbus_draw(gadget, 2 * power);
@@ -1463,7 +1465,7 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
if (ctrl->bRequestType != 0x80)
break;
*(u8 *)req->buf = dev->current_config;
- value = min (ctrl->wLength, (u16) 1);
+ value = min (w_length, (u16) 1);
break;
#endif
@@ -1472,7 +1474,7 @@ unrecognized:
VDEBUG (dev, "%s req%02x.%02x v%04x i%04x l%d\n",
dev->usermode_setup ? "delegate" : "fail",
ctrl->bRequestType, ctrl->bRequest,
- ctrl->wValue, ctrl->wIndex, ctrl->wLength);
+ w_value, le16_to_cpu(ctrl->wIndex), w_length);
/* if there's an ep0 reader, don't stall */
if (dev->usermode_setup) {
@@ -1485,9 +1487,9 @@ delegate:
value = 0;
/* read DATA stage for OUT right away */
- if (unlikely (!dev->setup_in && ctrl->wLength)) {
+ if (unlikely (!dev->setup_in && w_length)) {
value = setup_req (gadget->ep0, dev->req,
- ctrl->wLength);
+ w_length);
if (value < 0)
break;
value = usb_ep_queue (gadget->ep0, dev->req,
@@ -1513,8 +1515,7 @@ delegate:
/* proceed with data transfer and status phases? */
if (value >= 0 && dev->state != STATE_SETUP) {
req->length = value;
- req->zero = value < ctrl->wLength
- && (value % gadget->ep0->maxpacket) == 0;
+ req->zero = value < w_length;
value = usb_ep_queue (gadget->ep0, req, GFP_ATOMIC);
if (value < 0) {
DBG (dev, "ep_queue --> %d\n", value);
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
index d2997ef3cd6a6..e5457f2026ccd 100644
--- a/drivers/usb/gadget/net2280.c
+++ b/drivers/usb/gadget/net2280.c
@@ -1,8 +1,9 @@
/*
- * Driver for the NetChip 2280 USB device controller.
- * Specs and errata are available from <http://www.netchip.com>.
+ * Driver for the PLX NET2280 USB device controller.
+ * Specs and errata are available from <http://www.plxtech.com>.
*
- * NetChip Technology Inc. supported the development of this driver.
+ * PLX Technology Inc. (formerly NetChip Technology) supported the
+ * development of this driver.
*
*
* CODE STATUS HIGHLIGHTS
@@ -23,7 +24,7 @@
/*
* Copyright (C) 2003 David Brownell
- * Copyright (C) 2003 NetChip Technologies
+ * Copyright (C) 2003-2005 PLX Technology, 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
@@ -69,8 +70,8 @@
#include <asm/unaligned.h>
-#define DRIVER_DESC "NetChip 2280 USB Peripheral Controller"
-#define DRIVER_VERSION "2004 Jan 14"
+#define DRIVER_DESC "PLX NET2280 USB Peripheral Controller"
+#define DRIVER_VERSION "2005 Feb 03"
#define DMA_ADDR_INVALID (~(dma_addr_t)0)
#define EP_DONTUSE 13 /* nonzero */
@@ -113,6 +114,16 @@ static ushort fifo_mode = 0;
/* "modprobe net2280 fifo_mode=1" etc */
module_param (fifo_mode, ushort, 0644);
+/* enable_suspend -- When enabled, the driver will respond to
+ * USB suspend requests by powering down the NET2280. Otherwise,
+ * USB suspend requests will be ignored. This is acceptible for
+ * self-powered devices, and helps avoid some quirks.
+ */
+static int enable_suspend = 0;
+
+/* "modprobe net2280 enable_suspend=1" etc */
+module_param (enable_suspend, bool, S_IRUGO);
+
#define DIR_STRING(bAddress) (((bAddress) & USB_DIR_IN) ? "in" : "out")
@@ -1259,7 +1270,7 @@ static int net2280_dequeue (struct usb_ep *_ep, struct usb_request *_req)
}
spin_unlock_irqrestore (&ep->dev->lock, flags);
- return req ? 0 : -EOPNOTSUPP;
+ return 0;
}
/*-------------------------------------------------------------------------*/
@@ -2561,6 +2572,8 @@ static void handle_stat1_irqs (struct net2280 *dev, u32 stat)
if (stat & (1 << SUSPEND_REQUEST_INTERRUPT)) {
if (dev->driver->suspend)
dev->driver->suspend (&dev->gadget);
+ if (!enable_suspend)
+ stat &= ~(1 << SUSPEND_REQUEST_INTERRUPT);
} else {
if (dev->driver->resume)
dev->driver->resume (&dev->gadget);
diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c
index aeb821a5f2c38..b66ea5a6ed791 100644
--- a/drivers/usb/gadget/omap_udc.c
+++ b/drivers/usb/gadget/omap_udc.c
@@ -2,7 +2,7 @@
* omap_udc.c -- for OMAP full speed udc; most chips support OTG.
*
* Copyright (C) 2004 Texas Instruments, Inc.
- * Copyright (C) 2004 David Brownell
+ * Copyright (C) 2004-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
@@ -2046,7 +2046,10 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver)
pullup_disable (udc);
}
- if (machine_is_omap_innovator())
+ /* boards that don't have VBUS sensing can't autogate 48MHz;
+ * can't enter deep sleep while a gadget driver is active.
+ */
+ if (machine_is_omap_innovator() || machine_is_omap_osk())
omap_vbus_session(&udc->gadget, 1);
done:
@@ -2064,7 +2067,7 @@ int usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
if (!driver || driver != udc->driver)
return -EINVAL;
- if (machine_is_omap_innovator())
+ if (machine_is_omap_innovator() || machine_is_omap_osk())
omap_vbus_session(&udc->gadget, 0);
if (udc->transceiver)
@@ -2157,13 +2160,13 @@ static void proc_ep_show(struct seq_file *s, struct omap_ep *ep)
}
}
-static char *trx_mode(unsigned m)
+static char *trx_mode(unsigned m, int enabled)
{
switch (m) {
- case 3:
- case 0: return "6wire";
+ case 0: return enabled ? "*6wire" : "unused";
case 1: return "4wire";
case 2: return "3wire";
+ case 3: return "6wire";
default: return "unknown";
}
}
@@ -2171,17 +2174,20 @@ static char *trx_mode(unsigned m)
static int proc_otg_show(struct seq_file *s)
{
u32 tmp;
+ u32 trans;
tmp = OTG_REV_REG;
- seq_printf(s, "OTG rev %d.%d, transceiver_ctrl %08x\n",
- tmp >> 4, tmp & 0xf,
- USB_TRANSCEIVER_CTRL_REG);
+ trans = USB_TRANSCEIVER_CTRL_REG;
+ seq_printf(s, "OTG rev %d.%d, transceiver_ctrl %03x\n",
+ tmp >> 4, tmp & 0xf, trans);
tmp = OTG_SYSCON_1_REG;
seq_printf(s, "otg_syscon1 %08x usb2 %s, usb1 %s, usb0 %s,"
FOURBITS "\n", tmp,
- trx_mode(USB2_TRX_MODE(tmp)),
- trx_mode(USB1_TRX_MODE(tmp)),
- trx_mode(USB0_TRX_MODE(tmp)),
+ trx_mode(USB2_TRX_MODE(tmp), trans & CONF_USB2_UNI_R),
+ trx_mode(USB1_TRX_MODE(tmp), trans & CONF_USB1_UNI_R),
+ (USB0_TRX_MODE(tmp) == 0)
+ ? "internal"
+ : trx_mode(USB0_TRX_MODE(tmp), 1),
(tmp & OTG_IDLE_EN) ? " !otg" : "",
(tmp & HST_IDLE_EN) ? " !host" : "",
(tmp & DEV_IDLE_EN) ? " !dev" : "",
diff --git a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c
index 710f7a435f9ec..6390c5726d81c 100644
--- a/drivers/usb/gadget/pxa2xx_udc.c
+++ b/drivers/usb/gadget/pxa2xx_udc.c
@@ -310,7 +310,7 @@ static int pxa2xx_ep_disable (struct usb_ep *_ep)
/* flush fifo (mostly for IN buffers) */
pxa2xx_ep_fifo_flush (_ep);
- ep->desc = 0;
+ ep->desc = NULL;
ep->stopped = 1;
DBG(DBG_VERBOSE, "%s disabled\n", _ep->name);
@@ -334,7 +334,7 @@ pxa2xx_ep_alloc_request (struct usb_ep *_ep, int gfp_flags)
req = kmalloc (sizeof *req, gfp_flags);
if (!req)
- return 0;
+ return NULL;
memset (req, 0, sizeof *req);
INIT_LIST_HEAD (&req->queue);
@@ -369,7 +369,11 @@ pxa2xx_ep_alloc_buffer(struct usb_ep *_ep, unsigned bytes,
retval = kmalloc (bytes, gfp_flags & ~(__GFP_DMA|__GFP_HIGHMEM));
if (retval)
+#ifdef USE_DMA
*dma = virt_to_bus (retval);
+#else
+ *dma = (dma_addr_t)~0;
+#endif
return retval;
}
@@ -411,7 +415,6 @@ static void done(struct pxa2xx_ep *ep, struct pxa2xx_request *req, int status)
static inline void ep0_idle (struct pxa2xx_udc *dev)
{
dev->ep0state = EP0_IDLE;
- LED_EP0_OFF;
}
static int
@@ -930,7 +933,7 @@ pxa2xx_ep_queue(struct usb_ep *_ep, struct usb_request *_req, int gfp_flags)
case EP0_IN_DATA_PHASE:
dev->stats.write.ops++;
if (write_ep0_fifo(ep, req))
- req = 0;
+ req = NULL;
break;
case EP0_OUT_DATA_PHASE:
@@ -940,9 +943,11 @@ pxa2xx_ep_queue(struct usb_ep *_ep, struct usb_request *_req, int gfp_flags)
DBG(DBG_VERBOSE, "ep0 config ack%s\n",
dev->has_cfr ? "" : " raced");
if (dev->has_cfr)
- UDCCFR = UDCCFR_AREN|UDCCFR_ACM;
+ UDCCFR = UDCCFR_AREN|UDCCFR_ACM
+ |UDCCFR_MB1;
done(ep, req, 0);
dev->ep0state = EP0_END_XFER;
+ local_irq_restore (flags);
return 0;
}
if (dev->req_pending)
@@ -951,7 +956,7 @@ pxa2xx_ep_queue(struct usb_ep *_ep, struct usb_request *_req, int gfp_flags)
&& read_ep0_fifo(ep, req))) {
ep0_idle(dev);
done(ep, req, 0);
- req = 0;
+ req = NULL;
}
break;
@@ -969,10 +974,10 @@ pxa2xx_ep_queue(struct usb_ep *_ep, struct usb_request *_req, int gfp_flags)
} else if ((ep->bEndpointAddress & USB_DIR_IN) != 0
&& (*ep->reg_udccs & UDCCS_BI_TFS) != 0
&& write_fifo(ep, req)) {
- req = 0;
+ req = NULL;
} else if ((*ep->reg_udccs & UDCCS_BO_RFS) != 0
&& read_fifo(ep, req)) {
- req = 0;
+ req = NULL;
}
if (likely (req && ep->desc) && ep->dma < 0)
@@ -1093,7 +1098,6 @@ static int pxa2xx_ep_set_halt(struct usb_ep *_ep, int value)
start_watchdog(ep->dev);
ep->dev->req_pending = 0;
ep->dev->ep0state = EP0_STALL;
- LED_EP0_OFF;
/* and bulk/intr endpoints like dropping stalls too */
} else {
@@ -1193,13 +1197,71 @@ static int pxa2xx_udc_wakeup(struct usb_gadget *_gadget)
return 0;
}
+static void stop_activity(struct pxa2xx_udc *, struct usb_gadget_driver *);
+static void udc_enable (struct pxa2xx_udc *);
+static void udc_disable(struct pxa2xx_udc *);
+
+/* We disable the UDC -- and its 48 MHz clock -- whenever it's not
+ * in active use.
+ */
+static int pullup(struct pxa2xx_udc *udc, int is_active)
+{
+ is_active = is_active && udc->vbus && udc->pullup;
+ DMSG("%s\n", is_active ? "active" : "inactive");
+ if (is_active)
+ udc_enable(udc);
+ else {
+ if (udc->gadget.speed != USB_SPEED_UNKNOWN) {
+ DMSG("disconnect %s\n", udc->driver
+ ? udc->driver->driver.name
+ : "(no driver)");
+ stop_activity(udc, udc->driver);
+ }
+ udc_disable(udc);
+ }
+ return 0;
+}
+
+/* VBUS reporting logically comes from a transceiver */
+static int pxa2xx_udc_vbus_session(struct usb_gadget *_gadget, int is_active)
+{
+ struct pxa2xx_udc *udc;
+
+ udc = container_of(_gadget, struct pxa2xx_udc, gadget);
+ udc->vbus = is_active = (is_active != 0);
+ DMSG("vbus %s\n", is_active ? "supplied" : "inactive");
+ pullup(udc, is_active);
+ return 0;
+}
+
+/* drivers may have software control over D+ pullup */
+static int pxa2xx_udc_pullup(struct usb_gadget *_gadget, int is_active)
+{
+ struct pxa2xx_udc *udc;
+
+ udc = container_of(_gadget, struct pxa2xx_udc, gadget);
+
+ /* not all boards support pullup control */
+ if (!udc->mach->udc_command)
+ return -EOPNOTSUPP;
+
+ is_active = (is_active != 0);
+ udc->pullup = is_active;
+ pullup(udc, is_active);
+ return 0;
+}
+
static const struct usb_gadget_ops pxa2xx_udc_ops = {
- .get_frame = pxa2xx_udc_get_frame,
- .wakeup = pxa2xx_udc_wakeup,
- // current versions must always be self-powered
+ .get_frame = pxa2xx_udc_get_frame,
+ .wakeup = pxa2xx_udc_wakeup,
+ .vbus_session = pxa2xx_udc_vbus_session,
+ .pullup = pxa2xx_udc_pullup,
+
+ // .vbus_draw ... boards may consume current from VBUS, up to
+ // 100-500mA based on config. the 500uA suspend ceiling means
+ // that exclusively vbus-powered PXA designs violate USB specs.
};
-
/*-------------------------------------------------------------------------*/
#ifdef CONFIG_USB_GADGET_DEBUG_FILES
@@ -1426,7 +1488,7 @@ static void udc_reinit(struct pxa2xx_udc *dev)
if (i != 0)
list_add_tail (&ep->ep.ep_list, &dev->gadget.ep_list);
- ep->desc = 0;
+ ep->desc = NULL;
ep->stopped = 0;
INIT_LIST_HEAD (&ep->queue);
ep->pio_irqs = ep->dma_irqs = 0;
@@ -1445,6 +1507,7 @@ static void udc_enable (struct pxa2xx_udc *dev)
#ifdef CONFIG_ARCH_PXA
/* Enable clock for USB device */
pxa_set_cken(CKEN11_USB, 1);
+ udelay(5);
#endif
/* try to clear these bits before we enable the udc */
@@ -1468,7 +1531,7 @@ static void udc_enable (struct pxa2xx_udc *dev)
/* pxa255 (a0+) can avoid a set_config race that could
* prevent gadget drivers from configuring correctly
*/
- UDCCFR = UDCCFR_ACM;
+ UDCCFR = UDCCFR_ACM | UDCCFR_MB1;
} else {
/* "USB test mode" for pxa250 errata 40-42 (stepping a0, a1)
* which could result in missing packets and interrupts.
@@ -1497,18 +1560,13 @@ static void udc_enable (struct pxa2xx_udc *dev)
}
#endif
- /* caller must be able to sleep in order to cope
- * with startup transients.
- */
- msleep(100);
-
/* enable suspend/resume and reset irqs */
udc_clear_mask_UDCCR(UDCCR_SRM | UDCCR_REM);
/* enable ep0 irqs */
UICR0 &= ~UICR0_IM0;
- /* if hardware supports it, connect to usb and wait for host */
+ /* if hardware supports it, pullup D+ and wait for reset */
let_usb_appear();
}
@@ -1539,6 +1597,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
/* first hook up the driver ... */
dev->driver = driver;
dev->gadget.dev.driver = &driver->driver;
+ dev->pullup = 1;
device_add (&dev->gadget.dev);
retval = driver->bind(&dev->gadget);
@@ -1547,18 +1606,17 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
driver->driver.name, retval);
device_del (&dev->gadget.dev);
- dev->driver = 0;
- dev->gadget.dev.driver = 0;
+ dev->driver = NULL;
+ dev->gadget.dev.driver = NULL;
return retval;
}
device_create_file(dev->dev, &dev_attr_function);
/* ... then enable host detection and ep0; and we're ready
* for set_configuration as well as eventual disconnect.
- * NOTE: this shouldn't power up until later.
*/
DMSG("registered gadget driver '%s'\n", driver->driver.name);
- udc_enable(dev);
+ pullup(dev, 1);
dump_state(dev);
return 0;
}
@@ -1571,7 +1629,7 @@ stop_activity(struct pxa2xx_udc *dev, struct usb_gadget_driver *driver)
/* don't disconnect drivers more than once */
if (dev->gadget.speed == USB_SPEED_UNKNOWN)
- driver = 0;
+ driver = NULL;
dev->gadget.speed = USB_SPEED_UNKNOWN;
/* prevent new request submissions, kill any outstanding requests */
@@ -1602,12 +1660,12 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
return -EINVAL;
local_irq_disable();
- udc_disable(dev);
+ pullup(dev, 0);
stop_activity(dev, driver);
local_irq_enable();
driver->unbind(&dev->gadget);
- dev->driver = 0;
+ dev->driver = NULL;
device_del (&dev->gadget.dev);
device_remove_file(dev->dev, &dev_attr_function);
@@ -1623,61 +1681,41 @@ EXPORT_SYMBOL(usb_gadget_unregister_driver);
#ifdef CONFIG_ARCH_LUBBOCK
-/* Lubbock can report connect or disconnect irqs. Likely more hardware
- * could support it as a timer callback.
- *
- * FIXME for better power management, keep the hardware powered down
- * until a host is powering the link. means scheduling work later
- * in some task that can udc_enable().
+/* Lubbock has separate connect and disconnect irqs. More typical designs
+ * use one GPIO as the VBUS IRQ, and another to control the D+ pullup.
*/
-#define enable_disconnect_irq() \
- if (machine_is_lubbock()) { enable_irq(LUBBOCK_USB_DISC_IRQ); }
-#define disable_disconnect_irq() \
- if (machine_is_lubbock()) { disable_irq(LUBBOCK_USB_DISC_IRQ); }
-
static irqreturn_t
-usb_connection_irq(int irq, void *_dev, struct pt_regs *r)
+lubbock_vbus_irq(int irq, void *_dev, struct pt_regs *r)
{
struct pxa2xx_udc *dev = _dev;
+ int vbus;
dev->stats.irqs++;
HEX_DISPLAY(dev->stats.irqs);
-
- if (!is_usb_connected()) {
- LED_CONNECTED_OFF;
- disable_disconnect_irq();
- /* report disconnect just once */
- if (dev->gadget.speed != USB_SPEED_UNKNOWN) {
- DMSG("disconnect %s\n",
- dev->driver ? dev->driver->driver.name : 0);
- stop_activity(dev, dev->driver);
-
- // udc_disable (dev);
- // no more udc irqs
- // maybe "ACTION=disconnect /sbin/hotplug gadget".
- }
- } else if (dev->gadget.speed == USB_SPEED_UNKNOWN) {
+ switch (irq) {
+ case LUBBOCK_USB_IRQ:
LED_CONNECTED_ON;
-
- DMSG("?? connect irq ??\n");
-
- // if there's no driver bound, ignore; else
- // udc_enable (dev);
- // UDC irqs drive the rest.
- // maybe "ACTION=connect /sbin/hotplug gadget".
+ vbus = 1;
+ disable_irq(LUBBOCK_USB_IRQ);
+ enable_irq(LUBBOCK_USB_DISC_IRQ);
+ break;
+ case LUBBOCK_USB_DISC_IRQ:
+ LED_CONNECTED_OFF;
+ vbus = 0;
+ disable_irq(LUBBOCK_USB_DISC_IRQ);
+ enable_irq(LUBBOCK_USB_IRQ);
+ break;
+ default:
+ return IRQ_NONE;
}
+
+ pxa2xx_udc_vbus_session(&dev->gadget, vbus);
return IRQ_HANDLED;
}
#endif
-#ifndef enable_disconnect_irq
-#warning USB disconnect() is not yet reported.
-#define enable_disconnect_irq() do {} while (0)
-#define disable_disconnect_irq() do {} while (0)
-#endif
-
/*-------------------------------------------------------------------------*/
@@ -1719,7 +1757,7 @@ static void handle_ep0 (struct pxa2xx_udc *dev)
} u;
if (list_empty(&ep->queue))
- req = 0;
+ req = NULL;
else
req = list_entry(ep->queue.next, struct pxa2xx_request, queue);
@@ -1763,14 +1801,11 @@ bad_setup:
goto bad_setup;
got_setup:
- le16_to_cpus (&u.r.wValue);
- le16_to_cpus (&u.r.wIndex);
- le16_to_cpus (&u.r.wLength);
-
- LED_EP0_ON;
DBG(DBG_VERBOSE, "SETUP %02x.%02x v%04x i%04x l%04x\n",
u.r.bRequestType, u.r.bRequest,
- u.r.wValue, u.r.wIndex, u.r.wLength);
+ le16_to_cpu(u.r.wValue),
+ le16_to_cpu(u.r.wIndex),
+ le16_to_cpu(u.r.wLength));
/* cope with automagic for some standard requests. */
dev->req_std = (u.r.bRequestType & USB_TYPE_MASK)
@@ -1802,7 +1837,8 @@ config_change:
* - ep reset doesn't include halt(?).
*/
DMSG("broken set_interface (%d/%d)\n",
- u.r.wIndex, u.r.wValue);
+ le16_to_cpu(u.r.wIndex),
+ le16_to_cpu(u.r.wValue));
goto config_change;
}
break;
@@ -1846,7 +1882,6 @@ stall:
ep0start(dev, UDCCS0_FST|UDCCS0_FTF, "stall");
start_watchdog(dev);
dev->ep0state = EP0_STALL;
- LED_EP0_OFF;
/* deferred i/o == no response yet */
} else if (dev->req_pending) {
@@ -1947,7 +1982,7 @@ static void handle_ep(struct pxa2xx_ep *ep)
req = list_entry(ep->queue.next,
struct pxa2xx_request, queue);
else
- req = 0;
+ req = NULL;
// TODO check FST handling
@@ -2049,8 +2084,6 @@ pxa2xx_udc_irq(int irq, void *_dev, struct pt_regs *r)
if ((UDCCR & UDCCR_UDA) == 0) {
DBG(DBG_VERBOSE, "USB reset start\n");
- if (dev->gadget.speed != USB_SPEED_UNKNOWN)
- disable_disconnect_irq();
/* reset driver and endpoints,
* in case that's not yet done
@@ -2058,12 +2091,11 @@ pxa2xx_udc_irq(int irq, void *_dev, struct pt_regs *r)
stop_activity (dev, dev->driver);
} else {
- INFO("USB reset\n");
+ DBG(DBG_VERBOSE, "USB reset end\n");
dev->gadget.speed = USB_SPEED_FULL;
LED_CONNECTED_ON;
memset(&dev->stats, 0, sizeof dev->stats);
/* driver and endpoints are still reset */
- enable_disconnect_irq();
}
} else {
@@ -2477,6 +2509,8 @@ static int __init pxa2xx_udc_probe(struct device *_dev)
udc_disable(dev);
udc_reinit(dev);
+ dev->vbus = is_usb_connected();
+
/* irq setup after old hardware state is cleaned up */
retval = request_irq(IRQ_USB, pxa2xx_udc_irq,
SA_INTERRUPT, driver_name, dev);
@@ -2489,18 +2523,32 @@ static int __init pxa2xx_udc_probe(struct device *_dev)
#ifdef CONFIG_ARCH_LUBBOCK
if (machine_is_lubbock()) {
- disable_irq(LUBBOCK_USB_DISC_IRQ);
retval = request_irq(LUBBOCK_USB_DISC_IRQ,
- usb_connection_irq,
- SA_INTERRUPT /* OOPSING | SA_SAMPLE_RANDOM */,
+ lubbock_vbus_irq,
+ SA_INTERRUPT | SA_SAMPLE_RANDOM,
driver_name, dev);
if (retval != 0) {
- enable_irq(LUBBOCK_USB_DISC_IRQ);
printk(KERN_ERR "%s: can't get irq %i, err %d\n",
driver_name, LUBBOCK_USB_DISC_IRQ, retval);
+lubbock_fail0:
+ free_irq(IRQ_USB, dev);
return -EBUSY;
}
- dev->got_disc = 1;
+ retval = request_irq(LUBBOCK_USB_IRQ,
+ lubbock_vbus_irq,
+ SA_INTERRUPT | SA_SAMPLE_RANDOM,
+ driver_name, dev);
+ if (retval != 0) {
+ printk(KERN_ERR "%s: can't get irq %i, err %d\n",
+ driver_name, LUBBOCK_USB_IRQ, retval);
+ free_irq(LUBBOCK_USB_DISC_IRQ, dev);
+ goto lubbock_fail0;
+ }
+#ifdef DEBUG
+ /* with U-Boot (but not BLOB), hex is off by default */
+ HEX_DISPLAY(dev->stats.irqs);
+ LUB_DISC_BLNK_LED &= 0xff;
+#endif
}
#endif
create_proc_files();
@@ -2509,7 +2557,7 @@ static int __init pxa2xx_udc_probe(struct device *_dev)
}
static int __exit pxa2xx_udc_remove(struct device *_dev)
{
- struct pxa2xx_udc *dev = _dev->driver_data;
+ struct pxa2xx_udc *dev = dev_get_drvdata(_dev);
udc_disable(dev);
remove_proc_files();
@@ -2519,15 +2567,57 @@ static int __exit pxa2xx_udc_remove(struct device *_dev)
free_irq(IRQ_USB, dev);
dev->got_irq = 0;
}
- if (machine_is_lubbock() && dev->got_disc) {
+ if (machine_is_lubbock()) {
free_irq(LUBBOCK_USB_DISC_IRQ, dev);
- dev->got_disc = 0;
+ free_irq(LUBBOCK_USB_IRQ, dev);
+ }
+ dev_set_drvdata(_dev, NULL);
+ the_controller = NULL;
+ return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef CONFIG_PM
+
+/* USB suspend (controlled by the host) and system suspend (controlled
+ * by the PXA) don't necessarily work well together. If USB is active,
+ * the 48 MHz clock is required; so the system can't enter 33 MHz idle
+ * mode, or any deeper PM saving state.
+ *
+ * For now, we punt and forcibly disconnect from the USB host when PXA
+ * enters any suspend state. While we're disconnected, we always disable
+ * the 48MHz USB clock ... allowing PXA sleep and/or 33 MHz idle states.
+ * Boards without software pullup control shouldn't use those states.
+ * VBUS IRQs should probably be ignored so that the PXA device just acts
+ * "dead" to USB hosts until system resume.
+ */
+static int pxa2xx_udc_suspend(struct device *dev, u32 state, u32 level)
+{
+ struct pxa2xx_udc *udc = dev_get_drvdata(dev);
+
+ if (level == SUSPEND_POWER_DOWN) {
+ if (!udc->mach->udc_command)
+ WARN("USB host won't detect disconnect!\n");
+ pullup(udc, 0);
}
- dev_set_drvdata(_dev, 0);
- the_controller = 0;
return 0;
}
+static int pxa2xx_udc_resume(struct device *dev, u32 level)
+{
+ struct pxa2xx_udc *udc = dev_get_drvdata(dev);
+
+ if (level == RESUME_POWER_ON)
+ pullup(udc, 1);
+ return 0;
+}
+
+#else
+#define pxa2xx_udc_suspend NULL
+#define pxa2xx_udc_resume NULL
+#endif
+
/*-------------------------------------------------------------------------*/
static struct device_driver udc_driver = {
@@ -2535,10 +2625,8 @@ static struct device_driver udc_driver = {
.bus = &platform_bus_type,
.probe = pxa2xx_udc_probe,
.remove = __exit_p(pxa2xx_udc_remove),
-
- // FIXME power management support
- // .suspend = ... disable UDC
- // .resume = ... re-enable UDC
+ .suspend = pxa2xx_udc_suspend,
+ .resume = pxa2xx_udc_resume,
};
static int __init udc_init(void)
diff --git a/drivers/usb/gadget/pxa2xx_udc.h b/drivers/usb/gadget/pxa2xx_udc.h
index f3d6853852c3e..1f3a7d999da7e 100644
--- a/drivers/usb/gadget/pxa2xx_udc.h
+++ b/drivers/usb/gadget/pxa2xx_udc.h
@@ -40,6 +40,9 @@
#define UDCCFR_AREN (1 << 7) /* ACK response enable (now) */
#define UDCCFR_ACM (1 << 2) /* ACK control mode (wait for AREN) */
+/* latest pxa255 errata define new "must be one" bits in UDCCFR */
+#define UDCCFR_MB1 (0xff & ~(UDCCFR_AREN|UDCCFR_ACM))
+
/*-------------------------------------------------------------------------*/
struct pxa2xx_udc;
@@ -120,7 +123,8 @@ struct pxa2xx_udc {
enum ep0_state ep0state;
struct udc_stats stats;
unsigned got_irq : 1,
- got_disc : 1,
+ vbus : 1,
+ pullup : 1,
has_cfr : 1,
req_pending : 1,
req_std : 1,
@@ -143,14 +147,7 @@ struct pxa2xx_udc {
#ifdef DEBUG
#define HEX_DISPLAY(n) if (machine_is_lubbock()) { LUB_HEXLED = (n); }
-
-#define LED_CONNECTED_ON if (machine_is_lubbock()) { \
- DISCRETE_LED_ON(D26); }
-#define LED_CONNECTED_OFF if(machine_is_lubbock()) { \
- DISCRETE_LED_OFF(D26); LUB_HEXLED = 0; }
-#define LED_EP0_ON if (machine_is_lubbock()) { DISCRETE_LED_ON(D25); }
-#define LED_EP0_OFF if (machine_is_lubbock()) { DISCRETE_LED_OFF(D25); }
-#endif /* DEBUG */
+#endif
#endif
@@ -161,14 +158,20 @@ struct pxa2xx_udc {
#define HEX_DISPLAY(n) do {} while(0)
#endif
+#ifdef DEBUG
+#include <asm/leds.h>
+
+#define LED_CONNECTED_ON leds_event(led_green_on)
+#define LED_CONNECTED_OFF do { \
+ leds_event(led_green_off); \
+ HEX_DISPLAY(0); \
+ } while(0)
+#endif
+
#ifndef LED_CONNECTED_ON
#define LED_CONNECTED_ON do {} while(0)
#define LED_CONNECTED_OFF do {} while(0)
#endif
-#ifndef LED_EP0_ON
-#define LED_EP0_ON do {} while (0)
-#define LED_EP0_OFF do {} while (0)
-#endif
/*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c
index c3d064b09ef1a..6c5197850edc1 100644
--- a/drivers/usb/gadget/rndis.c
+++ b/drivers/usb/gadget/rndis.c
@@ -74,7 +74,7 @@ MODULE_PARM_DESC (rndis_debug, "enable debugging");
static rndis_params rndis_per_dev_params [RNDIS_MAX_CONFIGS];
/* Driver Version */
-static const u32 rndis_driver_version = __constant_cpu_to_le32 (1);
+static const __le32 rndis_driver_version = __constant_cpu_to_le32 (1);
/* Function Prototypes */
static int rndis_init_response (int configNr, rndis_init_msg_type *buf);
@@ -92,7 +92,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
{
int retval = -ENOTSUPP;
u32 length = 0;
- u32 *tmp;
+ __le32 *tmp;
int i, count;
rndis_query_cmplt_type *resp;
@@ -110,7 +110,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
DEBUG ("%s: OID_GEN_SUPPORTED_LIST\n", __FUNCTION__);
length = sizeof (oid_supported_list);
count = length / sizeof (u32);
- tmp = (u32 *) ((u8 *)resp + 24);
+ tmp = (__le32 *) ((u8 *)resp + 24);
for (i = 0; i < count; i++)
tmp[i] = cpu_to_le32 (oid_supported_list[i]);
retval = 0;
@@ -126,7 +126,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
* reddite ergo quae sunt Caesaris Caesari
* et quae sunt Dei Deo!
*/
- *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+ *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
retval = 0;
break;
@@ -134,7 +134,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
case OID_GEN_MEDIA_SUPPORTED:
DEBUG("%s: OID_GEN_MEDIA_SUPPORTED\n", __FUNCTION__);
length = 4;
- *((u32 *) resp + 6) = cpu_to_le32 (
+ *((__le32 *) resp + 6) = cpu_to_le32 (
rndis_per_dev_params [configNr].medium);
retval = 0;
break;
@@ -144,7 +144,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
DEBUG("%s: OID_GEN_MEDIA_IN_USE\n", __FUNCTION__);
length = 4;
/* one medium, one transport... (maybe you do it better) */
- *((u32 *) resp + 6) = cpu_to_le32 (
+ *((__le32 *) resp + 6) = cpu_to_le32 (
rndis_per_dev_params [configNr].medium);
retval = 0;
break;
@@ -154,11 +154,11 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
DEBUG("%s: OID_GEN_MAXIMUM_FRAME_SIZE\n", __FUNCTION__);
if (rndis_per_dev_params [configNr].dev) {
length = 4;
- *((u32 *) resp + 6) = cpu_to_le32 (
+ *((__le32 *) resp + 6) = cpu_to_le32 (
rndis_per_dev_params [configNr].dev->mtu);
retval = 0;
} else {
- *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+ *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
retval = 0;
}
break;
@@ -169,9 +169,9 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
length = 4;
if (rndis_per_dev_params [configNr].media_state
== NDIS_MEDIA_STATE_DISCONNECTED)
- *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+ *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
else
- *((u32 *) resp + 6) = cpu_to_le32 (
+ *((__le32 *) resp + 6) = cpu_to_le32 (
rndis_per_dev_params [configNr].speed);
retval = 0;
break;
@@ -181,7 +181,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
DEBUG("%s: OID_GEN_TRANSMIT_BLOCK_SIZE\n", __FUNCTION__);
if (rndis_per_dev_params [configNr].dev) {
length = 4;
- *((u32 *) resp + 6) = cpu_to_le32 (
+ *((__le32 *) resp + 6) = cpu_to_le32 (
rndis_per_dev_params [configNr].dev->mtu);
retval = 0;
}
@@ -192,7 +192,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
DEBUG("%s: OID_GEN_RECEIVE_BLOCK_SIZE\n", __FUNCTION__);
if (rndis_per_dev_params [configNr].dev) {
length = 4;
- *((u32 *) resp + 6) = cpu_to_le32 (
+ *((__le32 *) resp + 6) = cpu_to_le32 (
rndis_per_dev_params [configNr].dev->mtu);
retval = 0;
}
@@ -202,7 +202,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
case OID_GEN_VENDOR_ID:
DEBUG("%s: OID_GEN_VENDOR_ID\n", __FUNCTION__);
length = 4;
- *((u32 *) resp + 6) = cpu_to_le32 (
+ *((__le32 *) resp + 6) = cpu_to_le32 (
rndis_per_dev_params [configNr].vendorID);
retval = 0;
break;
@@ -220,7 +220,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
DEBUG("%s: OID_GEN_VENDOR_DRIVER_VERSION\n", __FUNCTION__);
length = 4;
/* Created as LE */
- *((u32 *) resp + 6) = rndis_driver_version;
+ *((__le32 *) resp + 6) = rndis_driver_version;
retval = 0;
break;
@@ -228,7 +228,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
case OID_GEN_CURRENT_PACKET_FILTER:
DEBUG("%s: OID_GEN_CURRENT_PACKET_FILTER\n", __FUNCTION__);
length = 4;
- *((u32 *) resp + 6) = cpu_to_le32 (
+ *((__le32 *) resp + 6) = cpu_to_le32 (
rndis_per_dev_params[configNr].filter);
retval = 0;
break;
@@ -237,7 +237,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
case OID_GEN_MAXIMUM_TOTAL_SIZE:
DEBUG("%s: OID_GEN_MAXIMUM_TOTAL_SIZE\n", __FUNCTION__);
length = 4;
- *((u32 *) resp + 6) = __constant_cpu_to_le32(
+ *((__le32 *) resp + 6) = __constant_cpu_to_le32(
RNDIS_MAX_TOTAL_SIZE);
retval = 0;
break;
@@ -246,7 +246,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
case OID_GEN_MEDIA_CONNECT_STATUS:
DEBUG("%s: OID_GEN_MEDIA_CONNECT_STATUS\n", __FUNCTION__);
length = 4;
- *((u32 *) resp + 6) = cpu_to_le32 (
+ *((__le32 *) resp + 6) = cpu_to_le32 (
rndis_per_dev_params [configNr]
.media_state);
retval = 0;
@@ -255,7 +255,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
case OID_GEN_PHYSICAL_MEDIUM:
DEBUG("%s: OID_GEN_PHYSICAL_MEDIUM\n", __FUNCTION__);
length = 4;
- *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+ *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
retval = 0;
break;
@@ -266,7 +266,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
case OID_GEN_MAC_OPTIONS: /* from WinME */
DEBUG("%s: OID_GEN_MAC_OPTIONS\n", __FUNCTION__);
length = 4;
- *((u32 *) resp + 6) = __constant_cpu_to_le32(
+ *((__le32 *) resp + 6) = __constant_cpu_to_le32(
NDIS_MAC_OPTION_RECEIVE_SERIALIZED
| NDIS_MAC_OPTION_FULL_DUPLEX);
retval = 0;
@@ -279,13 +279,13 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
DEBUG("%s: OID_GEN_XMIT_OK\n", __FUNCTION__);
if (rndis_per_dev_params [configNr].stats) {
length = 4;
- *((u32 *) resp + 6) = cpu_to_le32 (
+ *((__le32 *) resp + 6) = cpu_to_le32 (
rndis_per_dev_params [configNr].stats->tx_packets -
rndis_per_dev_params [configNr].stats->tx_errors -
rndis_per_dev_params [configNr].stats->tx_dropped);
retval = 0;
} else {
- *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+ *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
retval = 0;
}
break;
@@ -295,13 +295,13 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
DEBUG("%s: OID_GEN_RCV_OK\n", __FUNCTION__);
if (rndis_per_dev_params [configNr].stats) {
length = 4;
- *((u32 *) resp + 6) = cpu_to_le32 (
+ *((__le32 *) resp + 6) = cpu_to_le32 (
rndis_per_dev_params [configNr].stats->rx_packets -
rndis_per_dev_params [configNr].stats->rx_errors -
rndis_per_dev_params [configNr].stats->rx_dropped);
retval = 0;
} else {
- *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+ *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
retval = 0;
}
break;
@@ -311,12 +311,12 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
DEBUG("%s: OID_GEN_XMIT_ERROR\n", __FUNCTION__);
if (rndis_per_dev_params [configNr].stats) {
length = 4;
- *((u32 *) resp + 6) = cpu_to_le32 (
+ *((__le32 *) resp + 6) = cpu_to_le32 (
rndis_per_dev_params [configNr]
.stats->tx_errors);
retval = 0;
} else {
- *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+ *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
retval = 0;
}
break;
@@ -325,12 +325,12 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
case OID_GEN_RCV_ERROR:
DEBUG("%s: OID_GEN_RCV_ERROR\n", __FUNCTION__);
if (rndis_per_dev_params [configNr].stats) {
- *((u32 *) resp + 6) = cpu_to_le32 (
+ *((__le32 *) resp + 6) = cpu_to_le32 (
rndis_per_dev_params [configNr]
.stats->rx_errors);
retval = 0;
} else {
- *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+ *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
retval = 0;
}
break;
@@ -339,12 +339,12 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
case OID_GEN_RCV_NO_BUFFER:
DEBUG("%s: OID_GEN_RCV_NO_BUFFER\n", __FUNCTION__);
if (rndis_per_dev_params [configNr].stats) {
- *((u32 *) resp + 6) = cpu_to_le32 (
+ *((__le32 *) resp + 6) = cpu_to_le32 (
rndis_per_dev_params [configNr]
.stats->rx_dropped);
retval = 0;
} else {
- *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+ *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
retval = 0;
}
break;
@@ -359,7 +359,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
*/
if (rndis_per_dev_params [configNr].stats) {
length = 4;
- *((u32 *) resp + 6) = cpu_to_le32 (
+ *((__le32 *) resp + 6) = cpu_to_le32 (
(rndis_per_dev_params [configNr]
.stats->tx_packets -
rndis_per_dev_params [configNr]
@@ -369,7 +369,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
* 123);
retval = 0;
} else {
- *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+ *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
retval = 0;
}
break;
@@ -379,7 +379,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
/* dito */
if (rndis_per_dev_params [configNr].stats) {
length = 4;
- *((u32 *) resp + 6) = cpu_to_le32 (
+ *((__le32 *) resp + 6) = cpu_to_le32 (
(rndis_per_dev_params [configNr]
.stats->tx_packets -
rndis_per_dev_params [configNr]
@@ -389,7 +389,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
/ 123);
retval = 0;
} else {
- *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+ *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
retval = 0;
}
break;
@@ -397,12 +397,12 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
case OID_GEN_MULTICAST_BYTES_XMIT:
DEBUG("%s: OID_GEN_MULTICAST_BYTES_XMIT\n", __FUNCTION__);
if (rndis_per_dev_params [configNr].stats) {
- *((u32 *) resp + 6) = cpu_to_le32 (
+ *((__le32 *) resp + 6) = cpu_to_le32 (
rndis_per_dev_params [configNr]
.stats->multicast*1234);
retval = 0;
} else {
- *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+ *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
retval = 0;
}
break;
@@ -410,12 +410,12 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
case OID_GEN_MULTICAST_FRAMES_XMIT:
DEBUG("%s: OID_GEN_MULTICAST_FRAMES_XMIT\n", __FUNCTION__);
if (rndis_per_dev_params [configNr].stats) {
- *((u32 *) resp + 6) = cpu_to_le32 (
+ *((__le32 *) resp + 6) = cpu_to_le32 (
rndis_per_dev_params [configNr]
.stats->multicast);
retval = 0;
} else {
- *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+ *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
retval = 0;
}
break;
@@ -423,12 +423,12 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
case OID_GEN_BROADCAST_BYTES_XMIT:
DEBUG("%s: OID_GEN_BROADCAST_BYTES_XMIT\n", __FUNCTION__);
if (rndis_per_dev_params [configNr].stats) {
- *((u32 *) resp + 6) = cpu_to_le32 (
+ *((__le32 *) resp + 6) = cpu_to_le32 (
rndis_per_dev_params [configNr]
.stats->tx_packets/42*255);
retval = 0;
} else {
- *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+ *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
retval = 0;
}
break;
@@ -436,37 +436,37 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
case OID_GEN_BROADCAST_FRAMES_XMIT:
DEBUG("%s: OID_GEN_BROADCAST_FRAMES_XMIT\n", __FUNCTION__);
if (rndis_per_dev_params [configNr].stats) {
- *((u32 *) resp + 6) = cpu_to_le32 (
+ *((__le32 *) resp + 6) = cpu_to_le32 (
rndis_per_dev_params [configNr]
.stats->tx_packets/42);
retval = 0;
} else {
- *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+ *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
retval = 0;
}
break;
case OID_GEN_DIRECTED_BYTES_RCV:
DEBUG("%s: OID_GEN_DIRECTED_BYTES_RCV\n", __FUNCTION__);
- *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+ *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
retval = 0;
break;
case OID_GEN_DIRECTED_FRAMES_RCV:
DEBUG("%s: OID_GEN_DIRECTED_FRAMES_RCV\n", __FUNCTION__);
- *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+ *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
retval = 0;
break;
case OID_GEN_MULTICAST_BYTES_RCV:
DEBUG("%s: OID_GEN_MULTICAST_BYTES_RCV\n", __FUNCTION__);
if (rndis_per_dev_params [configNr].stats) {
- *((u32 *) resp + 6) = cpu_to_le32 (
+ *((__le32 *) resp + 6) = cpu_to_le32 (
rndis_per_dev_params [configNr]
.stats->multicast * 1111);
retval = 0;
} else {
- *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+ *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
retval = 0;
}
break;
@@ -474,12 +474,12 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
case OID_GEN_MULTICAST_FRAMES_RCV:
DEBUG("%s: OID_GEN_MULTICAST_FRAMES_RCV\n", __FUNCTION__);
if (rndis_per_dev_params [configNr].stats) {
- *((u32 *) resp + 6) = cpu_to_le32 (
+ *((__le32 *) resp + 6) = cpu_to_le32 (
rndis_per_dev_params [configNr]
.stats->multicast);
retval = 0;
} else {
- *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+ *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
retval = 0;
}
break;
@@ -487,12 +487,12 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
case OID_GEN_BROADCAST_BYTES_RCV:
DEBUG("%s: OID_GEN_BROADCAST_BYTES_RCV\n", __FUNCTION__);
if (rndis_per_dev_params [configNr].stats) {
- *((u32 *) resp + 6) = cpu_to_le32 (
+ *((__le32 *) resp + 6) = cpu_to_le32 (
rndis_per_dev_params [configNr]
.stats->rx_packets/42*255);
retval = 0;
} else {
- *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+ *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
retval = 0;
}
break;
@@ -500,12 +500,12 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
case OID_GEN_BROADCAST_FRAMES_RCV:
DEBUG("%s: OID_GEN_BROADCAST_FRAMES_RCV\n", __FUNCTION__);
if (rndis_per_dev_params [configNr].stats) {
- *((u32 *) resp + 6) = cpu_to_le32 (
+ *((__le32 *) resp + 6) = cpu_to_le32 (
rndis_per_dev_params [configNr]
.stats->rx_packets/42);
retval = 0;
} else {
- *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+ *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
retval = 0;
}
break;
@@ -513,19 +513,19 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
case OID_GEN_RCV_CRC_ERROR:
DEBUG("%s: OID_GEN_RCV_CRC_ERROR\n", __FUNCTION__);
if (rndis_per_dev_params [configNr].stats) {
- *((u32 *) resp + 6) = cpu_to_le32 (
+ *((__le32 *) resp + 6) = cpu_to_le32 (
rndis_per_dev_params [configNr]
.stats->rx_crc_errors);
retval = 0;
} else {
- *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+ *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
retval = 0;
}
break;
case OID_GEN_TRANSMIT_QUEUE_LENGTH:
DEBUG("%s: OID_GEN_TRANSMIT_QUEUE_LENGTH\n", __FUNCTION__);
- *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+ *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
retval = 0;
break;
#endif /* RNDIS_OPTIONAL_STATS */
@@ -542,7 +542,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
length);
retval = 0;
} else {
- *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+ *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
retval = 0;
}
break;
@@ -564,7 +564,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
DEBUG("%s: OID_802_3_MULTICAST_LIST\n", __FUNCTION__);
length = 4;
/* Multicast base address only */
- *((u32 *) resp + 6) = __constant_cpu_to_le32 (0xE0000000);
+ *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0xE0000000);
retval = 0;
break;
@@ -573,7 +573,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
DEBUG("%s: OID_802_3_MAXIMUM_LIST_SIZE\n", __FUNCTION__);
length = 4;
/* Multicast base address only */
- *((u32 *) resp + 6) = __constant_cpu_to_le32 (1);
+ *((__le32 *) resp + 6) = __constant_cpu_to_le32 (1);
retval = 0;
break;
@@ -589,7 +589,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
if (rndis_per_dev_params [configNr].stats)
{
length = 4;
- *((u32 *) resp + 6) = cpu_to_le32 (
+ *((__le32 *) resp + 6) = cpu_to_le32 (
rndis_per_dev_params [configNr]
.stats->rx_frame_errors);
retval = 0;
@@ -600,7 +600,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
case OID_802_3_XMIT_ONE_COLLISION:
DEBUG("%s: OID_802_3_XMIT_ONE_COLLISION\n", __FUNCTION__);
length = 4;
- *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+ *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
retval = 0;
break;
@@ -608,7 +608,7 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
case OID_802_3_XMIT_MORE_COLLISIONS:
DEBUG("%s: OID_802_3_XMIT_MORE_COLLISIONS\n", __FUNCTION__);
length = 4;
- *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+ *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
retval = 0;
break;
@@ -730,11 +730,11 @@ static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len,
/* FIXME use these NDIS_PACKET_TYPE_* bitflags to
* filter packets in hard_start_xmit()
- * NDIS_PACKET_TYPE_x == CDC_PACKET_TYPE_x for x in:
+ * NDIS_PACKET_TYPE_x == USB_CDC_PACKET_TYPE_x for x in:
* PROMISCUOUS, DIRECTED,
* MULTICAST, ALL_MULTICAST, BROADCAST
*/
- params->filter = cpu_to_le32p((u32 *)buf);
+ params->filter = le32_to_cpup((__le32 *)buf);
DEBUG("%s: OID_GEN_CURRENT_PACKET_FILTER %08x\n",
__FUNCTION__, params->filter);
@@ -866,7 +866,7 @@ static int rndis_query_response (int configNr, rndis_query_msg_type *buf)
resp->MessageLength = __constant_cpu_to_le32 (24);
resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
- if (gen_ndis_query_resp (configNr, cpu_to_le32 (buf->OID), r)) {
+ if (gen_ndis_query_resp (configNr, le32_to_cpu (buf->OID), r)) {
/* OID not supported */
resp->Status = __constant_cpu_to_le32 (
RNDIS_STATUS_NOT_SUPPORTED);
@@ -893,8 +893,8 @@ static int rndis_set_response (int configNr, rndis_set_msg_type *buf)
resp = (rndis_set_cmplt_type *) r->buf;
if (!resp) return -ENOMEM;
- BufLength = cpu_to_le32 (buf->InformationBufferLength);
- BufOffset = cpu_to_le32 (buf->InformationBufferOffset);
+ BufLength = le32_to_cpu (buf->InformationBufferLength);
+ BufOffset = le32_to_cpu (buf->InformationBufferOffset);
#ifdef VERBOSE
DEBUG("%s: Length: %d\n", __FUNCTION__, BufLength);
@@ -911,7 +911,7 @@ static int rndis_set_response (int configNr, rndis_set_msg_type *buf)
resp->MessageType = __constant_cpu_to_le32 (REMOTE_NDIS_SET_CMPLT);
resp->MessageLength = __constant_cpu_to_le32 (16);
resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
- if (gen_ndis_set_resp (configNr, cpu_to_le32 (buf->OID),
+ if (gen_ndis_set_resp (configNr, le32_to_cpu (buf->OID),
((u8 *) buf) + 8 + BufOffset, BufLength, r))
resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_NOT_SUPPORTED);
else resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS);
@@ -1030,15 +1030,16 @@ void rndis_set_host_mac (int configNr, const u8 *addr)
*/
int rndis_msg_parser (u8 configNr, u8 *buf)
{
- u32 MsgType, MsgLength, *tmp;
+ u32 MsgType, MsgLength;
+ __le32 *tmp;
struct rndis_params *params;
if (!buf)
return -ENOMEM;
- tmp = (u32 *) buf;
- MsgType = cpu_to_le32p(tmp++);
- MsgLength = cpu_to_le32p(tmp++);
+ tmp = (__le32 *) buf;
+ MsgType = le32_to_cpup(tmp++);
+ MsgLength = le32_to_cpup(tmp++);
if (configNr >= RNDIS_MAX_CONFIGS)
return -ENOTSUPP;
@@ -1187,15 +1188,16 @@ int rndis_set_param_medium (u8 configNr, u32 medium, u32 speed)
void rndis_add_hdr (struct sk_buff *skb)
{
- if (!skb) return;
- skb_push (skb, sizeof (struct rndis_packet_msg_type));
- memset (skb->data, 0, sizeof (struct rndis_packet_msg_type));
- *((u32 *) skb->data) = __constant_cpu_to_le32 (1);
- *((u32 *) skb->data + 1) = cpu_to_le32(skb->len);
- *((u32 *) skb->data + 2) = __constant_cpu_to_le32 (36);
- *((u32 *) skb->data + 3) = cpu_to_le32(skb->len - 44);
-
- return;
+ struct rndis_packet_msg_type *header;
+
+ if (!skb)
+ return;
+ header = (void *) skb_push (skb, sizeof *header);
+ memset (header, 0, sizeof *header);
+ header->MessageType = __constant_cpu_to_le32 (1);
+ header->MessageLength = cpu_to_le32(skb->len);
+ header->DataOffset = __constant_cpu_to_le32 (36);
+ header->OOBDataOffset = cpu_to_le32(skb->len - 44);
}
void rndis_free_response (int configNr, u8 *buf)
@@ -1253,15 +1255,16 @@ static rndis_resp_t *rndis_add_response (int configNr, u32 length)
int rndis_rm_hdr (u8 *buf, u32 *length)
{
- u32 i, messageLen, dataOffset, *tmp;
+ u32 i, messageLen, dataOffset;
+ __le32 *tmp;
- tmp = (u32 *) buf;
+ tmp = (__le32 *) buf;
if (!buf || !length) return -1;
- if (cpu_to_le32p(tmp++) != 1) return -1;
+ if (le32_to_cpup(tmp++) != 1) return -1;
- messageLen = cpu_to_le32p(tmp++);
- dataOffset = cpu_to_le32p(tmp++) + 8;
+ messageLen = le32_to_cpup(tmp++);
+ dataOffset = le32_to_cpup(tmp++) + 8;
if (messageLen < dataOffset || messageLen > *length) return -1;
diff --git a/drivers/usb/gadget/rndis.h b/drivers/usb/gadget/rndis.h
index fa7d90854d6fb..822501852c50b 100644
--- a/drivers/usb/gadget/rndis.h
+++ b/drivers/usb/gadget/rndis.h
@@ -154,139 +154,139 @@ static const u32 oid_supported_list [] =
typedef struct rndis_init_msg_type
{
- u32 MessageType;
- u32 MessageLength;
- u32 RequestID;
- u32 MajorVersion;
- u32 MinorVersion;
- u32 MaxTransferSize;
+ __le32 MessageType;
+ __le32 MessageLength;
+ __le32 RequestID;
+ __le32 MajorVersion;
+ __le32 MinorVersion;
+ __le32 MaxTransferSize;
} rndis_init_msg_type;
typedef struct rndis_init_cmplt_type
{
- u32 MessageType;
- u32 MessageLength;
- u32 RequestID;
- u32 Status;
- u32 MajorVersion;
- u32 MinorVersion;
- u32 DeviceFlags;
- u32 Medium;
- u32 MaxPacketsPerTransfer;
- u32 MaxTransferSize;
- u32 PacketAlignmentFactor;
- u32 AFListOffset;
- u32 AFListSize;
+ __le32 MessageType;
+ __le32 MessageLength;
+ __le32 RequestID;
+ __le32 Status;
+ __le32 MajorVersion;
+ __le32 MinorVersion;
+ __le32 DeviceFlags;
+ __le32 Medium;
+ __le32 MaxPacketsPerTransfer;
+ __le32 MaxTransferSize;
+ __le32 PacketAlignmentFactor;
+ __le32 AFListOffset;
+ __le32 AFListSize;
} rndis_init_cmplt_type;
typedef struct rndis_halt_msg_type
{
- u32 MessageType;
- u32 MessageLength;
- u32 RequestID;
+ __le32 MessageType;
+ __le32 MessageLength;
+ __le32 RequestID;
} rndis_halt_msg_type;
typedef struct rndis_query_msg_type
{
- u32 MessageType;
- u32 MessageLength;
- u32 RequestID;
- u32 OID;
- u32 InformationBufferLength;
- u32 InformationBufferOffset;
- u32 DeviceVcHandle;
+ __le32 MessageType;
+ __le32 MessageLength;
+ __le32 RequestID;
+ __le32 OID;
+ __le32 InformationBufferLength;
+ __le32 InformationBufferOffset;
+ __le32 DeviceVcHandle;
} rndis_query_msg_type;
typedef struct rndis_query_cmplt_type
{
- u32 MessageType;
- u32 MessageLength;
- u32 RequestID;
- u32 Status;
- u32 InformationBufferLength;
- u32 InformationBufferOffset;
+ __le32 MessageType;
+ __le32 MessageLength;
+ __le32 RequestID;
+ __le32 Status;
+ __le32 InformationBufferLength;
+ __le32 InformationBufferOffset;
} rndis_query_cmplt_type;
typedef struct rndis_set_msg_type
{
- u32 MessageType;
- u32 MessageLength;
- u32 RequestID;
- u32 OID;
- u32 InformationBufferLength;
- u32 InformationBufferOffset;
- u32 DeviceVcHandle;
+ __le32 MessageType;
+ __le32 MessageLength;
+ __le32 RequestID;
+ __le32 OID;
+ __le32 InformationBufferLength;
+ __le32 InformationBufferOffset;
+ __le32 DeviceVcHandle;
} rndis_set_msg_type;
typedef struct rndis_set_cmplt_type
{
- u32 MessageType;
- u32 MessageLength;
- u32 RequestID;
- u32 Status;
+ __le32 MessageType;
+ __le32 MessageLength;
+ __le32 RequestID;
+ __le32 Status;
} rndis_set_cmplt_type;
typedef struct rndis_reset_msg_type
{
- u32 MessageType;
- u32 MessageLength;
- u32 Reserved;
+ __le32 MessageType;
+ __le32 MessageLength;
+ __le32 Reserved;
} rndis_reset_msg_type;
typedef struct rndis_reset_cmplt_type
{
- u32 MessageType;
- u32 MessageLength;
- u32 Status;
- u32 AddressingReset;
+ __le32 MessageType;
+ __le32 MessageLength;
+ __le32 Status;
+ __le32 AddressingReset;
} rndis_reset_cmplt_type;
typedef struct rndis_indicate_status_msg_type
{
- u32 MessageType;
- u32 MessageLength;
- u32 Status;
- u32 StatusBufferLength;
- u32 StatusBufferOffset;
+ __le32 MessageType;
+ __le32 MessageLength;
+ __le32 Status;
+ __le32 StatusBufferLength;
+ __le32 StatusBufferOffset;
} rndis_indicate_status_msg_type;
typedef struct rndis_keepalive_msg_type
{
- u32 MessageType;
- u32 MessageLength;
- u32 RequestID;
+ __le32 MessageType;
+ __le32 MessageLength;
+ __le32 RequestID;
} rndis_keepalive_msg_type;
typedef struct rndis_keepalive_cmplt_type
{
- u32 MessageType;
- u32 MessageLength;
- u32 RequestID;
- u32 Status;
+ __le32 MessageType;
+ __le32 MessageLength;
+ __le32 RequestID;
+ __le32 Status;
} rndis_keepalive_cmplt_type;
struct rndis_packet_msg_type
{
- u32 MessageType;
- u32 MessageLength;
- u32 DataOffset;
- u32 DataLength;
- u32 OOBDataOffset;
- u32 OOBDataLength;
- u32 NumOOBDataElements;
- u32 PerPacketInfoOffset;
- u32 PerPacketInfoLength;
- u32 VcHandle;
- u32 Reserved;
+ __le32 MessageType;
+ __le32 MessageLength;
+ __le32 DataOffset;
+ __le32 DataLength;
+ __le32 OOBDataOffset;
+ __le32 OOBDataLength;
+ __le32 NumOOBDataElements;
+ __le32 PerPacketInfoOffset;
+ __le32 PerPacketInfoLength;
+ __le32 VcHandle;
+ __le32 Reserved;
};
struct rndis_config_parameter
{
- u32 ParameterNameOffset;
- u32 ParameterNameLength;
- u32 ParameterType;
- u32 ParameterValueOffset;
- u32 ParameterValueLength;
+ __le32 ParameterNameOffset;
+ __le32 ParameterNameLength;
+ __le32 ParameterType;
+ __le32 ParameterValueOffset;
+ __le32 ParameterValueLength;
};
/* implementation specific */
diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c
index 9432b85b8fe27..2af3f785d5a11 100644
--- a/drivers/usb/gadget/serial.c
+++ b/drivers/usb/gadget/serial.c
@@ -45,6 +45,7 @@
#include <asm/uaccess.h>
#include <linux/usb_ch9.h>
+#include <linux/usb_cdc.h>
#include <linux/usb_gadget.h>
#include "gadget_chips.h"
@@ -122,80 +123,6 @@ do { \
})
-/* CDC-ACM Defines and Structures */
-
-#define USB_CDC_SUBCLASS_ACM 2
-
-#define USB_CDC_CTRL_PROTO_NONE 0
-#define USB_CDC_CTRL_PROTO_AT 1
-#define USB_CDC_CTRL_PROTO_VENDOR 0xff
-
-#define USB_CDC_SUBTYPE_HEADER 0
-#define USB_CDC_SUBTYPE_CALL_MGMT 1
-#define USB_CDC_SUBTYPE_ACM 2
-#define USB_CDC_SUBTYPE_UNION 6
-
-#define USB_CDC_CALL_MGMT_CAP_CALL_MGMT 0x01
-#define USB_CDC_CALL_MGMT_CAP_DATA_INTF 0x02
-
-#define USB_CDC_REQ_SET_LINE_CODING 0x20
-#define USB_CDC_REQ_GET_LINE_CODING 0x21
-#define USB_CDC_REQ_SET_CONTROL_LINE_STATE 0x22
-
-#define USB_CDC_1_STOP_BITS 0
-#define USB_CDC_1_5_STOP_BITS 1
-#define USB_CDC_2_STOP_BITS 2
-
-#define USB_CDC_NO_PARITY 0
-#define USB_CDC_ODD_PARITY 1
-#define USB_CDC_EVEN_PARITY 2
-#define USB_CDC_MARK_PARITY 3
-#define USB_CDC_SPACE_PARITY 4
-
-/* Header Functional Descriptor from CDC spec 5.2.3.1 */
-struct usb_cdc_header_desc {
- u8 bLength;
- u8 bDescriptorType;
- u8 bDescriptorSubType;
- u16 bcdCDC;
-} __attribute__ ((packed));
-
-/* Call Management Descriptor from CDC spec 5.2.3.3 */
-struct usb_cdc_call_mgmt_desc {
- u8 bLength;
- u8 bDescriptorType;
- u8 bDescriptorSubType;
- u8 bmCapabilities;
- u8 bDataInterface;
-} __attribute__ ((packed));
-
-/* Abstract Control Management Descriptor from CDC spec 5.2.3.4 */
-struct usb_cdc_acm_desc {
- u8 bLength;
- u8 bDescriptorType;
- u8 bDescriptorSubType;
- u8 bmCapabilities;
-} __attribute__ ((packed));
-
-/* Union Functional Descriptor from CDC spec 5.2.3.8 */
-struct usb_cdc_union_desc {
- u8 bLength;
- u8 bDescriptorType;
- u8 bDescriptorSubType;
- u8 bMasterInterface0;
- u8 bSlaveInterface0;
- /* ... and there could be other slave interfaces */
-} __attribute__ ((packed));
-
-/* Line Coding Structure from CDC spec 6.2.13 */
-struct usb_cdc_line_coding {
- u32 dwDTERate;
- u8 bCharFormat;
- u8 bParityType;
- u8 bDataBits;
-} __attribute__ ((packed));
-
-
/* Defines */
#define GS_VERSION_STR "v2.0"
@@ -542,7 +469,7 @@ static const struct usb_interface_descriptor gs_control_interface_desc = {
.bNumEndpoints = 1,
.bInterfaceClass = USB_CLASS_COMM,
.bInterfaceSubClass = USB_CDC_SUBCLASS_ACM,
- .bInterfaceProtocol = USB_CDC_CTRL_PROTO_AT,
+ .bInterfaceProtocol = USB_CDC_ACM_PROTO_AT_V25TER,
.iInterface = GS_CONTROL_STR_ID,
};
@@ -560,29 +487,29 @@ static const struct usb_interface_descriptor gs_data_interface_desc = {
static const struct usb_cdc_header_desc gs_header_desc = {
.bLength = sizeof(gs_header_desc),
.bDescriptorType = USB_DT_CS_INTERFACE,
- .bDescriptorSubType = USB_CDC_SUBTYPE_HEADER,
+ .bDescriptorSubType = USB_CDC_HEADER_TYPE,
.bcdCDC = __constant_cpu_to_le16(0x0110),
};
-static const struct usb_cdc_call_mgmt_desc gs_call_mgmt_descriptor = {
+static const struct usb_cdc_call_mgmt_descriptor gs_call_mgmt_descriptor = {
.bLength = sizeof(gs_call_mgmt_descriptor),
.bDescriptorType = USB_DT_CS_INTERFACE,
- .bDescriptorSubType = USB_CDC_SUBTYPE_CALL_MGMT,
+ .bDescriptorSubType = USB_CDC_CALL_MANAGEMENT_TYPE,
.bmCapabilities = 0,
.bDataInterface = 1, /* index of data interface */
};
-static struct usb_cdc_acm_desc gs_acm_descriptor = {
+static struct usb_cdc_acm_descriptor gs_acm_descriptor = {
.bLength = sizeof(gs_acm_descriptor),
.bDescriptorType = USB_DT_CS_INTERFACE,
- .bDescriptorSubType = USB_CDC_SUBTYPE_ACM,
+ .bDescriptorSubType = USB_CDC_ACM_TYPE,
.bmCapabilities = 0,
};
static const struct usb_cdc_union_desc gs_union_desc = {
.bLength = sizeof(gs_union_desc),
.bDescriptorType = USB_DT_CS_INTERFACE,
- .bDescriptorSubType = USB_CDC_SUBTYPE_UNION,
+ .bDescriptorSubType = USB_CDC_UNION_TYPE,
.bMasterInterface0 = 0, /* index of control interface */
.bSlaveInterface0 = 1, /* index of data interface */
};
@@ -1531,6 +1458,12 @@ static int gs_bind(struct usb_gadget *gadget)
} else if (gadget_is_pxa27x(gadget)) {
gs_device_desc.bcdDevice =
__constant_cpu_to_le16(GS_VERSION_NUM|0x0011);
+ } else if (gadget_is_s3c2410(gadget)) {
+ gs_device_desc.bcdDevice =
+ __constant_cpu_to_le16(GS_VERSION_NUM|0x0012);
+ } else if (gadget_is_at91(gadget)) {
+ gs_device_desc.bcdDevice =
+ __constant_cpu_to_le16(GS_VERSION_NUM|0x0013);
} else {
printk(KERN_WARNING "gs_bind: controller '%s' not recognized\n",
gadget->name);
@@ -1674,6 +1607,9 @@ static int gs_setup(struct usb_gadget *gadget,
int ret = -EOPNOTSUPP;
struct gs_dev *dev = get_gadget_data(gadget);
struct usb_request *req = dev->dev_ctrl_req;
+ u16 wIndex = ctrl->wIndex;
+ u16 wValue = ctrl->wValue;
+ u16 wLength = ctrl->wLength;
switch (ctrl->bRequestType & USB_TYPE_MASK) {
case USB_TYPE_STANDARD:
@@ -1686,15 +1622,15 @@ static int gs_setup(struct usb_gadget *gadget,
default:
printk(KERN_ERR "gs_setup: unknown request, type=%02x, request=%02x, value=%04x, index=%04x, length=%d\n",
- ctrl->bRequestType, ctrl->bRequest, ctrl->wValue,
- ctrl->wIndex, ctrl->wLength);
+ ctrl->bRequestType, ctrl->bRequest,
+ wValue, wIndex, wLength);
break;
}
/* respond with data transfer before status phase? */
if (ret >= 0) {
req->length = ret;
- req->zero = ret < ctrl->wLength
+ req->zero = ret < wLength
&& (ret % gadget->ep0->maxpacket) == 0;
ret = usb_ep_queue(gadget->ep0, req, GFP_ATOMIC);
if (ret < 0) {
@@ -1715,15 +1651,18 @@ static int gs_setup_standard(struct usb_gadget *gadget,
int ret = -EOPNOTSUPP;
struct gs_dev *dev = get_gadget_data(gadget);
struct usb_request *req = dev->dev_ctrl_req;
+ u16 wIndex = ctrl->wIndex;
+ u16 wValue = ctrl->wValue;
+ u16 wLength = ctrl->wLength;
switch (ctrl->bRequest) {
case USB_REQ_GET_DESCRIPTOR:
if (ctrl->bRequestType != USB_DIR_IN)
break;
- switch (ctrl->wValue >> 8) {
+ switch (wValue >> 8) {
case USB_DT_DEVICE:
- ret = min(ctrl->wLength,
+ ret = min(wLength,
(u16)sizeof(struct usb_device_descriptor));
memcpy(req->buf, &gs_device_desc, ret);
break;
@@ -1732,7 +1671,7 @@ static int gs_setup_standard(struct usb_gadget *gadget,
case USB_DT_DEVICE_QUALIFIER:
if (!gadget->is_dualspeed)
break;
- ret = min(ctrl->wLength,
+ ret = min(wLength,
(u16)sizeof(struct usb_qualifier_descriptor));
memcpy(req->buf, &gs_qualifier_desc, ret);
break;
@@ -1744,18 +1683,18 @@ static int gs_setup_standard(struct usb_gadget *gadget,
#endif /* CONFIG_USB_GADGET_DUALSPEED */
case USB_DT_CONFIG:
ret = gs_build_config_buf(req->buf, gadget->speed,
- ctrl->wValue >> 8, ctrl->wValue & 0xff,
+ wValue >> 8, wValue & 0xff,
gadget->is_otg);
if (ret >= 0)
- ret = min(ctrl->wLength, (u16)ret);
+ ret = min(wLength, (u16)ret);
break;
case USB_DT_STRING:
/* wIndex == language code. */
ret = usb_gadget_get_string(&gs_string_table,
- ctrl->wValue & 0xff, req->buf);
+ wValue & 0xff, req->buf);
if (ret >= 0)
- ret = min(ctrl->wLength, (u16)ret);
+ ret = min(wLength, (u16)ret);
break;
}
break;
@@ -1764,7 +1703,7 @@ static int gs_setup_standard(struct usb_gadget *gadget,
if (ctrl->bRequestType != 0)
break;
spin_lock(&dev->dev_lock);
- ret = gs_set_config(dev, ctrl->wValue);
+ ret = gs_set_config(dev, wValue);
spin_unlock(&dev->dev_lock);
break;
@@ -1772,18 +1711,19 @@ static int gs_setup_standard(struct usb_gadget *gadget,
if (ctrl->bRequestType != USB_DIR_IN)
break;
*(u8 *)req->buf = dev->dev_config;
- ret = min(ctrl->wLength, (u16)1);
+ ret = min(wLength, (u16)1);
break;
case USB_REQ_SET_INTERFACE:
if (ctrl->bRequestType != USB_RECIP_INTERFACE
- || !dev->dev_config || ctrl->wIndex >= GS_MAX_NUM_INTERFACES)
+ || !dev->dev_config
+ || wIndex >= GS_MAX_NUM_INTERFACES)
break;
if (dev->dev_config == GS_BULK_CONFIG_ID
- && ctrl->wIndex != GS_BULK_INTERFACE_ID)
+ && wIndex != GS_BULK_INTERFACE_ID)
break;
/* no alternate interface settings */
- if (ctrl->wValue != 0)
+ if (wValue != 0)
break;
spin_lock(&dev->dev_lock);
/* PXA hardware partially handles SET_INTERFACE;
@@ -1794,7 +1734,7 @@ static int gs_setup_standard(struct usb_gadget *gadget,
goto set_interface_done;
}
if (dev->dev_config != GS_BULK_CONFIG_ID
- && ctrl->wIndex == GS_CONTROL_INTERFACE_ID) {
+ && wIndex == GS_CONTROL_INTERFACE_ID) {
if (dev->dev_notify_ep) {
usb_ep_disable(dev->dev_notify_ep);
usb_ep_enable(dev->dev_notify_ep, dev->dev_notify_ep_desc);
@@ -1814,21 +1754,21 @@ set_interface_done:
if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE)
|| dev->dev_config == GS_NO_CONFIG_ID)
break;
- if (ctrl->wIndex >= GS_MAX_NUM_INTERFACES
- || (dev->dev_config == GS_BULK_CONFIG_ID
- && ctrl->wIndex != GS_BULK_INTERFACE_ID)) {
+ if (wIndex >= GS_MAX_NUM_INTERFACES
+ || (dev->dev_config == GS_BULK_CONFIG_ID
+ && wIndex != GS_BULK_INTERFACE_ID)) {
ret = -EDOM;
break;
}
/* no alternate interface settings */
*(u8 *)req->buf = 0;
- ret = min(ctrl->wLength, (u16)1);
+ ret = min(wLength, (u16)1);
break;
default:
printk(KERN_ERR "gs_setup: unknown standard request, type=%02x, request=%02x, value=%04x, index=%04x, length=%d\n",
- ctrl->bRequestType, ctrl->bRequest, ctrl->wValue,
- ctrl->wIndex, ctrl->wLength);
+ ctrl->bRequestType, ctrl->bRequest,
+ wValue, wIndex, wLength);
break;
}
@@ -1842,10 +1782,13 @@ static int gs_setup_class(struct usb_gadget *gadget,
struct gs_dev *dev = get_gadget_data(gadget);
struct gs_port *port = dev->dev_port[0]; /* ACM only has one port */
struct usb_request *req = dev->dev_ctrl_req;
+ u16 wIndex = ctrl->wIndex;
+ u16 wValue = ctrl->wValue;
+ u16 wLength = ctrl->wLength;
switch (ctrl->bRequest) {
case USB_CDC_REQ_SET_LINE_CODING:
- ret = min(ctrl->wLength,
+ ret = min(wLength,
(u16)sizeof(struct usb_cdc_line_coding));
if (port) {
spin_lock(&port->port_lock);
@@ -1856,7 +1799,7 @@ static int gs_setup_class(struct usb_gadget *gadget,
case USB_CDC_REQ_GET_LINE_CODING:
port = dev->dev_port[0]; /* ACM only has one port */
- ret = min(ctrl->wLength,
+ ret = min(wLength,
(u16)sizeof(struct usb_cdc_line_coding));
if (port) {
spin_lock(&port->port_lock);
@@ -1871,8 +1814,8 @@ static int gs_setup_class(struct usb_gadget *gadget,
default:
printk(KERN_ERR "gs_setup: unknown class request, type=%02x, request=%02x, value=%04x, index=%04x, length=%d\n",
- ctrl->bRequestType, ctrl->bRequest, ctrl->wValue,
- ctrl->wIndex, ctrl->wLength);
+ ctrl->bRequestType, ctrl->bRequest,
+ wValue, wIndex, wLength);
break;
}
@@ -2272,7 +2215,7 @@ static int gs_alloc_ports(struct gs_dev *dev, int kmalloc_flags)
memset(port, 0, sizeof(struct gs_port));
port->port_dev = dev;
port->port_num = i;
- port->port_line_coding.dwDTERate = GS_DEFAULT_DTE_RATE;
+ port->port_line_coding.dwDTERate = cpu_to_le32(GS_DEFAULT_DTE_RATE);
port->port_line_coding.bCharFormat = GS_DEFAULT_CHAR_FORMAT;
port->port_line_coding.bParityType = GS_DEFAULT_PARITY;
port->port_line_coding.bDataBits = GS_DEFAULT_DATA_BITS;
@@ -2324,6 +2267,7 @@ static void gs_free_ports(struct gs_dev *dev)
}
spin_unlock_irqrestore(&port->port_lock, flags);
} else {
+ spin_unlock_irqrestore(&port->port_lock, flags);
kfree(port);
}
diff --git a/drivers/usb/gadget/usbstring.c b/drivers/usb/gadget/usbstring.c
index e1ca71bcc3966..b1735767660b6 100644
--- a/drivers/usb/gadget/usbstring.c
+++ b/drivers/usb/gadget/usbstring.c
@@ -20,7 +20,7 @@
#include <asm/unaligned.h>
-static int utf8_to_utf16le(const char *s, u16 *cp, unsigned len)
+static int utf8_to_utf16le(const char *s, __le16 *cp, unsigned len)
{
int count = 0;
u8 c;
@@ -126,7 +126,7 @@ usb_gadget_get_string (struct usb_gadget_strings *table, int id, u8 *buf)
/* string descriptors have length, tag, then UTF16-LE text */
len = min ((size_t) 126, strlen (s->s));
memset (buf + 2, 0, 2 * len); /* zero all the bytes */
- len = utf8_to_utf16le(s->s, (u16 *)&buf[2], len);
+ len = utf8_to_utf16le(s->s, (__le16 *)&buf[2], len);
if (len < 0)
return -EINVAL;
buf [0] = (len + 1) * 2;
diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c
index b128bc8ced6fa..6e49432071a1d 100644
--- a/drivers/usb/gadget/zero.c
+++ b/drivers/usb/gadget/zero.c
@@ -919,6 +919,9 @@ zero_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
struct zero_dev *dev = get_gadget_data (gadget);
struct usb_request *req = dev->req;
int value = -EOPNOTSUPP;
+ u16 w_index = ctrl->wIndex;
+ u16 w_value = ctrl->wValue;
+ u16 w_length = ctrl->wLength;
/* usually this stores reply data in the pre-allocated ep0 buffer,
* but config change events will reconfigure hardware.
@@ -929,17 +932,17 @@ zero_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
case USB_REQ_GET_DESCRIPTOR:
if (ctrl->bRequestType != USB_DIR_IN)
goto unknown;
- switch (ctrl->wValue >> 8) {
+ switch (w_value >> 8) {
case USB_DT_DEVICE:
- value = min (ctrl->wLength, (u16) sizeof device_desc);
+ value = min (w_length, (u16) sizeof device_desc);
memcpy (req->buf, &device_desc, value);
break;
#ifdef CONFIG_USB_GADGET_DUALSPEED
case USB_DT_DEVICE_QUALIFIER:
if (!gadget->is_dualspeed)
break;
- value = min (ctrl->wLength, (u16) sizeof dev_qualifier);
+ value = min (w_length, (u16) sizeof dev_qualifier);
memcpy (req->buf, &dev_qualifier, value);
break;
@@ -950,10 +953,10 @@ zero_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
#endif /* CONFIG_USB_GADGET_DUALSPEED */
case USB_DT_CONFIG:
value = config_buf (gadget, req->buf,
- ctrl->wValue >> 8,
- ctrl->wValue & 0xff);
+ w_value >> 8,
+ w_value & 0xff);
if (value >= 0)
- value = min (ctrl->wLength, (u16) value);
+ value = min (w_length, (u16) value);
break;
case USB_DT_STRING:
@@ -963,9 +966,9 @@ zero_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
* any UTF-8 characters
*/
value = usb_gadget_get_string (&stringtab,
- ctrl->wValue & 0xff, req->buf);
+ w_value & 0xff, req->buf);
if (value >= 0)
- value = min (ctrl->wLength, (u16) value);
+ value = min (w_length, (u16) value);
break;
}
break;
@@ -981,14 +984,14 @@ zero_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
else
VDBG (dev, "HNP inactive\n");
spin_lock (&dev->lock);
- value = zero_set_config (dev, ctrl->wValue, GFP_ATOMIC);
+ value = zero_set_config (dev, w_value, GFP_ATOMIC);
spin_unlock (&dev->lock);
break;
case USB_REQ_GET_CONFIGURATION:
if (ctrl->bRequestType != USB_DIR_IN)
goto unknown;
*(u8 *)req->buf = dev->config;
- value = min (ctrl->wLength, (u16) 1);
+ value = min (w_length, (u16) 1);
break;
/* until we add altsetting support, or other interfaces,
@@ -999,7 +1002,7 @@ zero_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
if (ctrl->bRequestType != USB_RECIP_INTERFACE)
goto unknown;
spin_lock (&dev->lock);
- if (dev->config && ctrl->wIndex == 0 && ctrl->wValue == 0) {
+ if (dev->config && w_index == 0 && w_value == 0) {
u8 config = dev->config;
/* resets interface configuration, forgets about
@@ -1020,12 +1023,12 @@ zero_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
goto unknown;
if (!dev->config)
break;
- if (ctrl->wIndex != 0) {
+ if (w_index != 0) {
value = -EDOM;
break;
}
*(u8 *)req->buf = 0;
- value = min (ctrl->wLength, (u16) 1);
+ value = min (w_length, (u16) 1);
break;
/*
@@ -1036,23 +1039,23 @@ zero_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
case 0x5b: /* control WRITE test -- fill the buffer */
if (ctrl->bRequestType != (USB_DIR_OUT|USB_TYPE_VENDOR))
goto unknown;
- if (ctrl->wValue || ctrl->wIndex)
+ if (w_value || w_index)
break;
/* just read that many bytes into the buffer */
- if (ctrl->wLength > USB_BUFSIZ)
+ if (w_length > USB_BUFSIZ)
break;
- value = ctrl->wLength;
+ value = w_length;
break;
case 0x5c: /* control READ test -- return the buffer */
if (ctrl->bRequestType != (USB_DIR_IN|USB_TYPE_VENDOR))
goto unknown;
- if (ctrl->wValue || ctrl->wIndex)
+ if (w_value || w_index)
break;
/* expect those bytes are still in the buffer; send back */
- if (ctrl->wLength > USB_BUFSIZ
- || ctrl->wLength != req->length)
+ if (w_length > USB_BUFSIZ
+ || w_length != req->length)
break;
- value = ctrl->wLength;
+ value = w_length;
break;
default:
@@ -1060,14 +1063,13 @@ unknown:
VDBG (dev,
"unknown control req%02x.%02x v%04x i%04x l%d\n",
ctrl->bRequestType, ctrl->bRequest,
- ctrl->wValue, ctrl->wIndex, ctrl->wLength);
+ w_value, w_index, w_length);
}
/* respond with data transfer before status phase? */
if (value >= 0) {
req->length = value;
- req->zero = value < ctrl->wLength
- && (value % gadget->ep0->maxpacket) == 0;
+ req->zero = value < w_length;
value = usb_ep_queue (gadget->ep0, req, GFP_ATOMIC);
if (value < 0) {
DBG (dev, "ep_queue --> %d\n", value);
@@ -1191,6 +1193,10 @@ autoconf_fail:
device_desc.bcdDevice = __constant_cpu_to_le16 (0x0210);
} else if (gadget_is_pxa27x(gadget)) {
device_desc.bcdDevice = __constant_cpu_to_le16 (0x0211);
+ } else if (gadget_is_s3c2410(gadget)) {
+ device_desc.bcdDevice = __constant_cpu_to_le16 (0x0212);
+ } else if (gadget_is_at91(gadget)) {
+ device_desc.bcdDevice = __constant_cpu_to_le16 (0x0213);
} else {
/* gadget zero is so simple (for now, no altsettings) that
* it SHOULD NOT have problems with bulk-capable hardware.
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 256787e33bdee..3196c3265ff53 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -1,21 +1,3 @@
-# Host-side USB depends on having a host controller
-# NOTE: dummy_hcd is always an option, but it's ignored here ...
-# NOTE: SL-811 option should be board-specific ...
-config USB_ARCH_HAS_HCD
- boolean
- default y if USB_ARCH_HAS_OHCI
- default y if ARM # SL-811
- default PCI
-
-# many non-PCI hcds implement OHCI
-config USB_ARCH_HAS_OHCI
- boolean
- default y if SA1111
- default y if ARCH_OMAP
- default y if ARCH_LH7A404
- default y if PXA27x
- default PCI
-
#
# USB Host Controller Drivers
#
@@ -65,7 +47,7 @@ config USB_EHCI_ROOT_HUB_TT
controller is needed. It's safe to say "y" even if your
controller doesn't support this feature.
- This supports the EHCI implementation from ARC International.
+ This supports the EHCI implementation from TransDimension Inc.
config USB_OHCI_HCD
tristate "OHCI HCD support"
@@ -84,6 +66,35 @@ config USB_OHCI_HCD
To compile this driver as a module, choose M here: the
module will be called ohci-hcd.
+config USB_OHCI_HCD_PPC_SOC
+ bool "OHCI support for on-chip PPC USB controller"
+ depends on USB_OHCI_HCD && (STB03xxx || PPC_MPC52xx)
+ default y
+ select USB_OHCI_BIG_ENDIAN
+ ---help---
+ Enables support for the USB controller on the MPC52xx or
+ STB03xxx processor chip. If unsure, say Y.
+
+config USB_OHCI_HCD_PCI
+ bool "OHCI support for PCI-bus USB controllers"
+ depends on USB_OHCI_HCD && PCI && (STB03xxx || PPC_MPC52xx)
+ default y
+ select USB_OHCI_LITTLE_ENDIAN
+ ---help---
+ Enables support for PCI-bus plug-in USB controller cards.
+ If unsure, say Y.
+
+config USB_OHCI_BIG_ENDIAN
+ bool
+ depends on USB_OHCI_HCD
+ default n
+
+config USB_OHCI_LITTLE_ENDIAN
+ bool
+ depends on USB_OHCI_HCD
+ default n if STB03xxx || PPC_MPC52xx
+ default y
+
config USB_UHCI_HCD
tristate "UHCI HCD (most Intel and VIA) support"
depends on USB && PCI
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 681b7e25b8eb5..a63bb792e2c7e 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -191,17 +191,38 @@ static int ehci_halt (struct ehci_hcd *ehci)
return handshake (&ehci->regs->status, STS_HALT, STS_HALT, 16 * 125);
}
+/* put TDI/ARC silicon into EHCI mode */
+static void tdi_reset (struct ehci_hcd *ehci)
+{
+ u32 __iomem *reg_ptr;
+ u32 tmp;
+
+ reg_ptr = (u32 __iomem *)(((u8 __iomem *)ehci->regs) + 0x68);
+ tmp = readl (reg_ptr);
+ tmp |= 0x3;
+ writel (tmp, reg_ptr);
+}
+
/* reset a non-running (STS_HALT == 1) controller */
static int ehci_reset (struct ehci_hcd *ehci)
{
+ int retval;
u32 command = readl (&ehci->regs->command);
command |= CMD_RESET;
dbg_cmd (ehci, "reset", command);
writel (command, &ehci->regs->command);
- ehci_to_hcd(ehci)->state = USB_STATE_HALT;
+ ehci_to_hcd(ehci)->state = HC_STATE_HALT;
ehci->next_statechange = jiffies;
- return handshake (&ehci->regs->command, CMD_RESET, 0, 250 * 1000);
+ retval = handshake (&ehci->regs->command, CMD_RESET, 0, 250 * 1000);
+
+ if (retval)
+ return retval;
+
+ if (ehci_is_TDI(ehci))
+ tdi_reset (ehci);
+
+ return retval;
}
/* idle the controller (from running) */
@@ -210,7 +231,7 @@ static void ehci_quiesce (struct ehci_hcd *ehci)
u32 temp;
#ifdef DEBUG
- if (!HCD_IS_RUNNING (ehci_to_hcd(ehci)->state))
+ if (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state))
BUG ();
#endif
@@ -219,7 +240,7 @@ static void ehci_quiesce (struct ehci_hcd *ehci)
temp &= STS_ASS | STS_PSS;
if (handshake (&ehci->regs->status, STS_ASS | STS_PSS,
temp, 16 * 125) != 0) {
- ehci_to_hcd(ehci)->state = USB_STATE_HALT;
+ ehci_to_hcd(ehci)->state = HC_STATE_HALT;
return;
}
@@ -231,7 +252,7 @@ static void ehci_quiesce (struct ehci_hcd *ehci)
/* hardware can take 16 microframes to turn off ... */
if (handshake (&ehci->regs->status, STS_ASS | STS_PSS,
0, 16 * 125) != 0) {
- ehci_to_hcd(ehci)->state = USB_STATE_HALT;
+ ehci_to_hcd(ehci)->state = HC_STATE_HALT;
return;
}
}
@@ -346,11 +367,20 @@ static int ehci_hc_reset (struct usb_hcd *hcd)
if (hcd->self.controller->bus == &pci_bus_type) {
struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
- /* AMD8111 EHCI doesn't work, according to AMD errata */
- if ((pdev->vendor == PCI_VENDOR_ID_AMD)
- && (pdev->device == 0x7463)) {
- ehci_info (ehci, "ignoring AMD8111 (errata)\n");
- return -EIO;
+ switch (pdev->vendor) {
+ case PCI_VENDOR_ID_TDI:
+ if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) {
+ ehci->is_tdi_rh_tt = 1;
+ tdi_reset (ehci);
+ }
+ break;
+ case PCI_VENDOR_ID_AMD:
+ /* AMD8111 EHCI doesn't work, according to AMD errata */
+ if (pdev->device == 0x7463) {
+ ehci_info (ehci, "ignoring AMD8111 (errata)\n");
+ return -EIO;
+ }
+ break;
}
temp = HCC_EXT_CAPS (readl (&ehci->caps->hcc_params));
@@ -380,6 +410,8 @@ static int ehci_hc_reset (struct usb_hcd *hcd)
ehci_err (ehci, "bogus capabilities ... PCI problems!\n");
return -EIO;
}
+ if (ehci_is_TDI(ehci))
+ ehci_reset (ehci);
#endif
/* cache this readonly data; minimize PCI reads */
@@ -481,15 +513,6 @@ static int ehci_start (struct usb_hcd *hcd)
/* help hc dma work well with cachelines */
pci_set_mwi (pdev);
-
- /* chip-specific init */
- switch (pdev->vendor) {
- case PCI_VENDOR_ID_ARC:
- if (pdev->device == PCI_DEVICE_ID_ARC_EHCI)
- ehci->is_arc_rh_tt = 1;
- break;
- }
-
}
#endif
@@ -592,7 +615,7 @@ done2:
register_reboot_notifier (&ehci->reboot_notifier);
}
- hcd->state = USB_STATE_RUNNING;
+ hcd->state = HC_STATE_RUNNING;
writel (FLAG_CF, &ehci->regs->configured_flag);
readl (&ehci->regs->command); /* unblock posted write */
@@ -612,8 +635,8 @@ done2:
* Before this point the HC was idle/ready. After, khubd
* and device drivers may start it running.
*/
- if (first && hcd_register_root (udev, hcd) != 0) {
- if (hcd->state == USB_STATE_RUNNING)
+ if (first && usb_hcd_register_root_hub (udev, hcd) != 0) {
+ if (hcd->state == HC_STATE_RUNNING)
ehci_quiesce (ehci);
ehci_reset (ehci);
usb_put_dev (udev);
@@ -649,7 +672,7 @@ static void ehci_stop (struct usb_hcd *hcd)
del_timer_sync (&ehci->watchdog);
spin_lock_irq(&ehci->lock);
- if (HCD_IS_RUNNING (hcd->state))
+ if (HC_IS_RUNNING (hcd->state))
ehci_quiesce (ehci);
ehci_reset (ehci);
@@ -816,7 +839,7 @@ static void ehci_work (struct ehci_hcd *ehci, struct pt_regs *regs)
* misplace IRQs, and should let us run completely without IRQs.
* such lossage has been observed on both VT6202 and VT8235.
*/
- if (HCD_IS_RUNNING (ehci_to_hcd(ehci)->state) &&
+ if (HC_IS_RUNNING (ehci_to_hcd(ehci)->state) &&
(ehci->async->qh_next.ptr != NULL ||
ehci->periodic_sched != 0))
timer_action (ehci, TIMER_IO_WATCHDOG);
@@ -977,7 +1000,7 @@ static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
/* if we need to use IAA and it's busy, defer */
if (qh->qh_state == QH_STATE_LINKED
&& ehci->reclaim
- && HCD_IS_RUNNING (ehci_to_hcd(ehci)->state)) {
+ && HC_IS_RUNNING (ehci_to_hcd(ehci)->state)) {
struct ehci_qh *last;
for (last = ehci->reclaim;
@@ -988,7 +1011,7 @@ static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
last->reclaim = qh;
/* bypass IAA if the hc can't care */
- } else if (!HCD_IS_RUNNING (ehci_to_hcd(ehci)->state) && ehci->reclaim)
+ } else if (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state) && ehci->reclaim)
end_unlink_async (ehci, NULL);
/* something else might have unlinked the qh by now */
@@ -1036,7 +1059,7 @@ static int ehci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
/* reschedule QH iff another request is queued */
if (!list_empty (&qh->qtd_list)
- && HCD_IS_RUNNING (hcd->state)) {
+ && HC_IS_RUNNING (hcd->state)) {
int status;
status = qh_schedule (ehci, qh);
@@ -1092,7 +1115,7 @@ rescan:
goto idle_timeout;
}
- if (!HCD_IS_RUNNING (hcd->state))
+ if (!HC_IS_RUNNING (hcd->state))
qh->qh_state = QH_STATE_IDLE;
switch (qh->qh_state) {
case QH_STATE_LINKED:
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 8a1c130f94482..2373537fabed3 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -42,9 +42,9 @@ static int ehci_hub_suspend (struct usb_hcd *hcd)
spin_lock_irq (&ehci->lock);
/* stop schedules, clean any completed work */
- if (HCD_IS_RUNNING(hcd->state)) {
+ if (HC_IS_RUNNING(hcd->state)) {
ehci_quiesce (ehci);
- hcd->state = USB_STATE_QUIESCING;
+ hcd->state = HC_STATE_QUIESCING;
}
ehci->command = readl (&ehci->regs->command);
if (ehci->reclaim)
@@ -73,7 +73,7 @@ static int ehci_hub_suspend (struct usb_hcd *hcd)
/* turn off now-idle HC */
ehci_halt (ehci);
- hcd->state = HCD_STATE_SUSPENDED;
+ hcd->state = HC_STATE_SUSPENDED;
ehci->next_statechange = jiffies + msecs_to_jiffies(10);
spin_unlock_irq (&ehci->lock);
@@ -145,7 +145,7 @@ static int ehci_hub_resume (struct usb_hcd *hcd)
}
ehci->next_statechange = jiffies + msecs_to_jiffies(5);
- hcd->state = USB_STATE_RUNNING;
+ hcd->state = HC_STATE_RUNNING;
/* Now we can safely re-enable irqs */
if (intr_enable)
@@ -178,7 +178,7 @@ static int check_reset_complete (
if (!(port_status & PORT_PE)) {
/* with integrated TT, there's nobody to hand it to! */
- if (ehci_is_ARC(ehci)) {
+ if (ehci_is_TDI(ehci)) {
ehci_dbg (ehci,
"Failed to enable port %d on root hub TT\n",
index+1);
@@ -212,7 +212,7 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
unsigned long flags;
/* if !USB_SUSPEND, root hub timers won't get shut down ... */
- if (!HCD_IS_RUNNING(hcd->state))
+ if (!HC_IS_RUNNING(hcd->state))
return 0;
/* init status to no-changes */
@@ -517,7 +517,7 @@ static int ehci_hub_control (
* transaction translator built in.
*/
if ((temp & (PORT_PE|PORT_CONNECT)) == PORT_CONNECT
- && !ehci_is_ARC(ehci)
+ && !ehci_is_TDI(ehci)
&& PORT_USB11 (temp)) {
ehci_dbg (ehci,
"port %d low speed --> companion\n",
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index b284c4c896af8..7df9b9af54f60 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -198,7 +198,7 @@ static void qtd_copy_status (
&& urb->dev->tt && !usb_pipeint (urb->pipe)
&& ((token & QTD_STS_MMF) != 0
|| QTD_CERR(token) == 0)
- && (!ehci_is_ARC(ehci)
+ && (!ehci_is_TDI(ehci)
|| urb->dev->tt->hub !=
ehci_to_hcd(ehci)->self.root_hub)) {
#ifdef DEBUG
@@ -338,23 +338,24 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh, struct pt_regs *regs)
if ((token & QTD_STS_HALT) != 0) {
stopped = 1;
- /* magic dummy for some short reads; qh won't advance */
+ /* magic dummy for some short reads; qh won't advance.
+ * that silicon quirk can kick in with this dummy too.
+ */
} else if (IS_SHORT_READ (token)
- && (qh->hw_alt_next & QTD_MASK)
- == ehci->async->hw_alt_next) {
+ && !(qtd->hw_alt_next & EHCI_LIST_END)) {
stopped = 1;
goto halt;
}
/* stop scanning when we reach qtds the hc is using */
} else if (likely (!stopped
- && HCD_IS_RUNNING (ehci_to_hcd(ehci)->state))) {
+ && HC_IS_RUNNING (ehci_to_hcd(ehci)->state))) {
break;
} else {
stopped = 1;
- if (unlikely (!HCD_IS_RUNNING (ehci_to_hcd(ehci)->state)))
+ if (unlikely (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state)))
urb->status = -ESHUTDOWN;
/* ignore active urbs unless some previous qtd
@@ -522,7 +523,7 @@ qh_urb_transaction (
else
buf = 0;
- // FIXME this 'buf' check break some zlps...
+ /* for zero length DATA stages, STATUS is always IN */
if (!buf || is_input)
token |= (1 /* "in" */ << 8);
/* else it's already initted to "out" pid (0 << 8) */
@@ -714,10 +715,10 @@ qh_make (
info2 |= (EHCI_TUNE_MULT_TT << 30);
info2 |= urb->dev->ttport << 23;
- /* set the address of the TT; for ARC's integrated
+ /* set the address of the TT; for TDI's integrated
* root hub tt, leave it zeroed.
*/
- if (!ehci_is_ARC(ehci)
+ if (!ehci_is_TDI(ehci)
|| urb->dev->tt->hub !=
ehci_to_hcd(ehci)->self.root_hub)
info2 |= urb->dev->tt->hub->devnum << 16;
@@ -780,7 +781,7 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
(void) handshake (&ehci->regs->status, STS_ASS, 0, 150);
cmd |= CMD_ASE | CMD_RUN;
writel (cmd, &ehci->regs->command);
- ehci_to_hcd(ehci)->state = USB_STATE_RUNNING;
+ ehci_to_hcd(ehci)->state = HC_STATE_RUNNING;
/* posted write need not be known to HC yet ... */
}
}
@@ -959,7 +960,7 @@ static void end_unlink_async (struct ehci_hcd *ehci, struct pt_regs *regs)
qh_completions (ehci, qh, regs);
if (!list_empty (&qh->qtd_list)
- && HCD_IS_RUNNING (ehci_to_hcd(ehci)->state))
+ && HC_IS_RUNNING (ehci_to_hcd(ehci)->state))
qh_link_async (ehci, qh);
else {
qh_put (qh); // refcount from async list
@@ -967,7 +968,7 @@ static void end_unlink_async (struct ehci_hcd *ehci, struct pt_regs *regs)
/* it's not free to turn the async schedule on/off; leave it
* active but idle for a while once it empties.
*/
- if (HCD_IS_RUNNING (ehci_to_hcd(ehci)->state)
+ if (HC_IS_RUNNING (ehci_to_hcd(ehci)->state)
&& ehci->async->qh_next.qh == NULL)
timer_action (ehci, TIMER_ASYNC_OFF);
}
@@ -998,7 +999,7 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
/* stop async schedule right now? */
if (unlikely (qh == ehci->async)) {
/* can't get here without STS_ASS set */
- if (ehci_to_hcd(ehci)->state != USB_STATE_HALT) {
+ if (ehci_to_hcd(ehci)->state != HC_STATE_HALT) {
writel (cmd & ~CMD_ASE, &ehci->regs->command);
wmb ();
// handshake later, if we need to
@@ -1018,7 +1019,7 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
prev->qh_next = qh->qh_next;
wmb ();
- if (unlikely (ehci_to_hcd(ehci)->state == USB_STATE_HALT)) {
+ if (unlikely (ehci_to_hcd(ehci)->state == HC_STATE_HALT)) {
/* if (unlikely (qh->reclaim != 0))
* this will recurse, probably not much
*/
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index 3cdfb95c38007..f6c86354e3049 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -208,7 +208,7 @@ static int tt_no_collision (
here = here.qh->qh_next;
continue;
case Q_TYPE_SITD:
- if (same_tt (dev, here.itd->urb->dev)) {
+ if (same_tt (dev, here.sitd->urb->dev)) {
u16 mask;
mask = le32_to_cpu (here.sitd
@@ -218,7 +218,7 @@ static int tt_no_collision (
if (mask & uf_mask)
break;
}
- type = Q_NEXT_TYPE (here.qh->hw_next);
+ type = Q_NEXT_TYPE (here.sitd->hw_next);
here = here.sitd->sitd_next;
continue;
// case Q_TYPE_FSTN:
@@ -249,14 +249,14 @@ static int enable_periodic (struct ehci_hcd *ehci)
*/
status = handshake (&ehci->regs->status, STS_PSS, 0, 9 * 125);
if (status != 0) {
- ehci_to_hcd(ehci)->state = USB_STATE_HALT;
+ ehci_to_hcd(ehci)->state = HC_STATE_HALT;
return status;
}
cmd = readl (&ehci->regs->command) | CMD_PSE;
writel (cmd, &ehci->regs->command);
/* posted write ... PSS happens later */
- ehci_to_hcd(ehci)->state = USB_STATE_RUNNING;
+ ehci_to_hcd(ehci)->state = HC_STATE_RUNNING;
/* make sure ehci_work scans these */
ehci->next_uframe = readl (&ehci->regs->frame_index)
@@ -274,7 +274,7 @@ static int disable_periodic (struct ehci_hcd *ehci)
*/
status = handshake (&ehci->regs->status, STS_PSS, STS_PSS, 9 * 125);
if (status != 0) {
- ehci_to_hcd(ehci)->state = USB_STATE_HALT;
+ ehci_to_hcd(ehci)->state = HC_STATE_HALT;
return status;
}
@@ -650,6 +650,7 @@ iso_stream_alloc (int mem_flags)
static void
iso_stream_init (
+ struct ehci_hcd *ehci,
struct ehci_iso_stream *stream,
struct usb_device *dev,
int pipe,
@@ -701,7 +702,10 @@ iso_stream_init (
u32 addr;
addr = dev->ttport << 24;
- addr |= dev->tt->hub->devnum << 16;
+ if (!ehci_is_TDI(ehci)
+ || (dev->tt->hub !=
+ ehci_to_hcd(ehci)->self.root_hub))
+ addr |= dev->tt->hub->devnum << 16;
addr |= epnum << 8;
addr |= dev->devnum;
stream->usecs = HS_USECS_ISO (maxp);
@@ -819,7 +823,7 @@ iso_stream_find (struct ehci_hcd *ehci, struct urb *urb)
/* dev->ep owns the initial refcount */
ep->hcpriv = stream;
stream->ep = ep;
- iso_stream_init(stream, urb->dev, urb->pipe,
+ iso_stream_init(ehci, stream, urb->dev, urb->pipe,
urb->interval);
}
@@ -1176,7 +1180,10 @@ fail:
return status;
ready:
+ /* report high speed start in uframes; full speed, in frames */
urb->start_frame = stream->next_uframe;
+ if (!stream->highspeed)
+ urb->start_frame >>= 3;
return 0;
}
@@ -1500,18 +1507,17 @@ sitd_sched_init (
/* might need to cross a buffer page within a td */
packet->bufp = buf;
- buf += length;
- packet->buf1 = buf & ~0x0fff;
+ packet->buf1 = (buf + length) & ~0x0fff;
if (packet->buf1 != (buf & ~(u64)0x0fff))
packet->cross = 1;
/* OUT uses multiple start-splits */
if (stream->bEndpointAddress & USB_DIR_IN)
continue;
- length = 1 + (length / 188);
- packet->buf1 |= length;
+ length = (length + 187) / 188;
if (length > 1) /* BEGIN vs ALL */
- packet->buf1 |= 1 << 3;
+ length |= 1 << 3;
+ packet->buf1 |= length;
}
}
@@ -1606,10 +1612,9 @@ sitd_patch (
sitd->hw_buf_hi [0] = cpu_to_le32 (bufp >> 32);
sitd->hw_buf [1] = cpu_to_le32 (uf->buf1);
- if (uf->cross) {
+ if (uf->cross)
bufp += 4096;
- sitd->hw_buf_hi [1] = cpu_to_le32 (bufp >> 32);
- }
+ sitd->hw_buf_hi [1] = cpu_to_le32 (bufp >> 32);
sitd->index = index;
}
@@ -1646,7 +1651,7 @@ sitd_link_urb (
ehci_to_hcd(ehci)->self.bandwidth_allocated
+= stream->bandwidth;
ehci_vdbg (ehci,
- "sched dev%s ep%d%s-iso [%d] %dms/%04x\n",
+ "sched devp %s ep%d%s-iso [%d] %dms/%04x\n",
urb->dev->devpath, stream->bEndpointAddress & 0x0f,
(stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out",
(next_uframe >> 3) % ehci->periodic_size,
@@ -1693,7 +1698,7 @@ sitd_link_urb (
/*-------------------------------------------------------------------------*/
#define SITD_ERRS (SITD_STS_ERR | SITD_STS_DBE | SITD_STS_BABBLE \
- | SITD_STS_XACT | SITD_STS_MMF | SITD_STS_STS)
+ | SITD_STS_XACT | SITD_STS_MMF)
static unsigned
sitd_complete (
@@ -1776,12 +1781,6 @@ static int sitd_submit (struct ehci_hcd *ehci, struct urb *urb, int mem_flags)
unsigned long flags;
struct ehci_iso_stream *stream;
- // FIXME remove when csplits behave
- if (usb_pipein(urb->pipe)) {
- ehci_dbg (ehci, "no iso-IN split transactions yet\n");
- return -ENOMEM;
- }
-
/* Get iso_stream head */
stream = iso_stream_find (ehci, urb);
if (stream == NULL) {
@@ -1860,7 +1859,7 @@ scan_periodic (struct ehci_hcd *ehci, struct pt_regs *regs)
* Touches as few pages as possible: cache-friendly.
*/
now_uframe = ehci->next_uframe;
- if (HCD_IS_RUNNING (ehci_to_hcd(ehci)->state))
+ if (HC_IS_RUNNING (ehci_to_hcd(ehci)->state))
clock = readl (&ehci->regs->frame_index);
else
clock = now_uframe + mod - 1;
@@ -1894,7 +1893,7 @@ restart:
union ehci_shadow temp;
int live;
- live = HCD_IS_RUNNING (ehci_to_hcd(ehci)->state);
+ live = HC_IS_RUNNING (ehci_to_hcd(ehci)->state);
switch (type) {
case Q_TYPE_QH:
/* handle any completions */
@@ -1983,7 +1982,7 @@ restart:
if (now_uframe == clock) {
unsigned now;
- if (!HCD_IS_RUNNING (ehci_to_hcd(ehci)->state))
+ if (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state))
break;
ehci->next_uframe = now_uframe;
now = readl (&ehci->regs->frame_index) % mod;
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index e28d19724f560..67988dba9eb73 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -82,7 +82,7 @@ struct ehci_hcd { /* one per controller */
unsigned long next_statechange;
u32 command;
- unsigned is_arc_rh_tt:1; /* ARC roothub with TT */
+ unsigned is_tdi_rh_tt:1; /* TDI roothub with TT */
/* glue to PCI and HCD framework */
struct ehci_caps __iomem *caps;
@@ -430,7 +430,7 @@ struct ehci_iso_packet {
__le32 transaction; /* itd->hw_transaction[i] |= */
u8 cross; /* buf crosses pages */
/* for full speed OUT splits */
- u16 buf1;
+ u32 buf1;
};
/* temporary schedule data for packets from iso urbs (both speeds)
@@ -599,13 +599,13 @@ struct ehci_fstn {
* needed (mostly in root hub code).
*/
-#define ehci_is_ARC(e) ((e)->is_arc_rh_tt)
+#define ehci_is_TDI(e) ((e)->is_tdi_rh_tt)
/* Returns the speed of a device attached to a port on the root hub. */
static inline unsigned int
ehci_port_speed(struct ehci_hcd *ehci, unsigned int portsc)
{
- if (ehci_is_ARC(ehci)) {
+ if (ehci_is_TDI(ehci)) {
switch ((portsc>>26)&3) {
case 0:
return 0;
@@ -621,7 +621,7 @@ ehci_port_speed(struct ehci_hcd *ehci, unsigned int portsc)
#else
-#define ehci_is_ARC(e) (0)
+#define ehci_is_TDI(e) (0)
#define ehci_port_speed(ehci, portsc) (1<<USB_PORT_FEAT_HIGHSPEED)
#endif
diff --git a/drivers/usb/host/ohci-au1xxx.c b/drivers/usb/host/ohci-au1xxx.c
index ee8503aa024bd..3981bf15c8c72 100644
--- a/drivers/usb/host/ohci-au1xxx.c
+++ b/drivers/usb/host/ohci-au1xxx.c
@@ -70,19 +70,6 @@ static void au1xxx_stop_hc(struct platform_device *dev)
/*-------------------------------------------------------------------------*/
-
-static irqreturn_t usb_hcd_au1xxx_hcim_irq (int irq, void *__hcd,
- struct pt_regs * r)
-{
- struct usb_hcd *hcd = __hcd;
-
- return usb_hcd_irq(irq, hcd, r);
-}
-
-/*-------------------------------------------------------------------------*/
-
-void usb_hcd_au1xxx_remove (struct usb_hcd *, struct platform_device *);
-
/* configure so an HC device and id are always provided */
/* always called with process context; sleeping is OK */
@@ -97,90 +84,48 @@ void usb_hcd_au1xxx_remove (struct usb_hcd *, struct platform_device *);
*
*/
int usb_hcd_au1xxx_probe (const struct hc_driver *driver,
- struct usb_hcd **hcd_out,
struct platform_device *dev)
{
int retval;
- struct usb_hcd *hcd = 0;
-
- unsigned int *addr = NULL;
-
- if (!request_mem_region(dev->resource[0].start,
- dev->resource[0].end
- - dev->resource[0].start + 1, hcd_name)) {
- pr_debug("request_mem_region failed");
- return -EBUSY;
- }
-
- au1xxx_start_hc(dev);
-
- addr = ioremap(dev->resource[0].start,
- dev->resource[0].end
- - dev->resource[0].start + 1);
- if (!addr) {
- pr_debug("ioremap failed");
- retval = -ENOMEM;
- goto err1;
- }
+ struct usb_hcd *hcd;
if(dev->resource[1].flags != IORESOURCE_IRQ) {
pr_debug ("resource[1] is not IORESOURCE_IRQ");
- retval = -ENOMEM;
- goto err1;
+ return -ENOMEM;
}
- hcd = usb_create_hcd(driver);
- if (hcd == NULL) {
- pr_debug ("usb_create_hcd failed");
- retval = -ENOMEM;
+ hcd = usb_create_hcd(driver, &dev->dev, "au1xxx");
+ if (!hcd)
+ return -ENOMEM;
+ hcd->rsrc_start = dev->resource[0].start;
+ hcd->rsrc_len = dev->resource[0].end - dev->resource[0].start + 1;
+
+ if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
+ pr_debug("request_mem_region failed");
+ retval = -EBUSY;
goto err1;
}
- ohci_hcd_init(hcd_to_ohci(hcd));
-
- hcd->irq = dev->resource[1].start;
- hcd->regs = addr;
- hcd->self.controller = &dev->dev;
- retval = hcd_buffer_create (hcd);
- if (retval != 0) {
- pr_debug ("pool alloc fail");
+ hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
+ if (!hcd->regs) {
+ pr_debug("ioremap failed");
+ retval = -ENOMEM;
goto err2;
}
- retval = request_irq (hcd->irq, usb_hcd_au1xxx_hcim_irq, SA_INTERRUPT,
- hcd->driver->description, hcd);
- if (retval != 0) {
- pr_debug("request_irq failed");
- retval = -EBUSY;
- goto err3;
- }
-
- pr_debug ("%s (Au1xxx) at 0x%p, irq %d",
- hcd->driver->description, hcd->regs, hcd->irq);
-
- hcd->self.bus_name = "au1xxx";
-
- usb_register_bus (&hcd->self);
+ au1xxx_start_hc(dev);
+ ohci_hcd_init(hcd_to_ohci(hcd));
- if ((retval = driver->start (hcd)) < 0)
- {
- usb_hcd_au1xxx_remove(hcd, dev);
- printk("bad driver->start\n");
+ retval = usb_add_hcd(hcd, dev->resource[1].start, SA_INTERRUPT);
+ if (retval == 0)
return retval;
- }
- *hcd_out = hcd;
- return 0;
-
- err3:
- hcd_buffer_destroy (hcd);
+ au1xxx_stop_hc(dev);
+ iounmap(hcd->regs);
err2:
- usb_put_hcd(hcd);
+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
err1:
- au1xxx_stop_hc(dev);
- release_mem_region(dev->resource[0].start,
- dev->resource[0].end
- - dev->resource[0].start + 1);
+ usb_put_hcd(hcd);
return retval;
}
@@ -200,28 +145,11 @@ int usb_hcd_au1xxx_probe (const struct hc_driver *driver,
*/
void usb_hcd_au1xxx_remove (struct usb_hcd *hcd, struct platform_device *dev)
{
- pr_debug ("remove: %s, state %x", hcd->self.bus_name, hcd->state);
-
- if (in_interrupt ())
- BUG ();
-
- hcd->state = USB_STATE_QUIESCING;
-
- pr_debug ("%s: roothub graceful disconnect", hcd->self.bus_name);
- usb_disconnect (&hcd->self.root_hub);
-
- hcd->driver->stop (hcd);
- hcd->state = USB_STATE_HALT;
-
- free_irq (hcd->irq, hcd);
- hcd_buffer_destroy (hcd);
-
- usb_deregister_bus (&hcd->self);
-
+ usb_remove_hcd(hcd);
au1xxx_stop_hc(dev);
- release_mem_region(dev->resource[0].start,
- dev->resource[0].end
- - dev->resource[0].start + 1);
+ iounmap(hcd->regs);
+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+ usb_put_hcd(hcd);
}
/*-------------------------------------------------------------------------*/
@@ -257,7 +185,7 @@ static const struct hc_driver ohci_au1xxx_hc_driver = {
* generic hardware linkage
*/
.irq = ohci_irq,
- .flags = HCD_USB11,
+ .flags = HCD_USB11 | HCD_MEMORY,
/*
* basic lifecycle operations
@@ -293,7 +221,6 @@ static const struct hc_driver ohci_au1xxx_hc_driver = {
static int ohci_hcd_au1xxx_drv_probe(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
- struct usb_hcd *hcd = NULL;
int ret;
pr_debug ("In ohci_hcd_au1xxx_drv_probe");
@@ -301,11 +228,7 @@ static int ohci_hcd_au1xxx_drv_probe(struct device *dev)
if (usb_disabled())
return -ENODEV;
- ret = usb_hcd_au1xxx_probe(&ohci_au1xxx_hc_driver, &hcd, pdev);
-
- if (ret == 0)
- dev_set_drvdata(dev, hcd);
-
+ ret = usb_hcd_au1xxx_probe(&ohci_au1xxx_hc_driver, pdev);
return ret;
}
@@ -315,7 +238,6 @@ static int ohci_hcd_au1xxx_drv_remove(struct device *dev)
struct usb_hcd *hcd = dev_get_drvdata(dev);
usb_hcd_au1xxx_remove(hcd, pdev);
- dev_set_drvdata(dev, NULL);
return 0;
}
/*TBD*/
diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c
index 45053ca193cd7..62f53a2138082 100644
--- a/drivers/usb/host/ohci-dbg.c
+++ b/drivers/usb/host/ohci-dbg.c
@@ -138,7 +138,7 @@ ohci_dump_status (struct ohci_hcd *controller, char **next, unsigned *size)
ohci_dbg_sw (controller, next, size,
"OHCI %d.%d, %s legacy support registers\n",
0x03 & (temp >> 4), (temp & 0x0f),
- (temp & 0x10) ? "with" : "NO");
+ (temp & 0x0100) ? "with" : "NO");
temp = ohci_readl (controller, &regs->control);
ohci_dbg_sw (controller, next, size,
@@ -193,6 +193,10 @@ ohci_dump_status (struct ohci_hcd *controller, char **next, unsigned *size)
maybe_print_eds (controller, "donehead",
ohci_readl (controller, &regs->donehead), next, size);
+
+ /* broken fminterval means traffic won't flow! */
+ ohci_dbg (controller, "fminterval %08x\n",
+ ohci_readl (controller, &regs->fminterval));
}
#define dbg_port_sw(hc,num,value,next,size) \
@@ -328,7 +332,7 @@ static void ohci_dump_td (const struct ohci_hcd *ohci, const char *label,
hc32_to_cpup (ohci, &td->hwCBP) & ~0x0fff,
hc32_to_cpup (ohci, &td->hwBE));
for (i = 0; i < MAXPSW; i++) {
- u16 psw = hc16_to_cpup (ohci, &td->hwPSW [i]);
+ u16 psw = ohci_hwPSW (ohci, td, i);
int cc = (psw >> 12) & 0x0f;
ohci_dbg (ohci, " psw [%d] = %2x, CC=%x %s=%d\n", i,
psw, cc,
@@ -620,9 +624,11 @@ show_registers (struct class_device *class_dev, char *buf)
ohci_dbg_sw (ohci, &next, &size,
"bus %s, device %s\n"
+ "%s\n"
"%s version " DRIVER_VERSION "\n",
hcd->self.controller->bus->name,
hcd->self.controller->bus_id,
+ hcd->product_desc,
hcd_name);
if (bus->controller->power.power_state) {
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index 9db8e18d3fed8..1e27f10c1592c 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -148,10 +148,22 @@ static void ohci_stop (struct usb_hcd *hcd);
#include "ohci-q.c"
-/* Some boards don't support per-port power switching */
-static int power_switching = 0;
-module_param (power_switching, bool, 0);
-MODULE_PARM_DESC (power_switching, "true (not default) to switch port power");
+/*
+ * On architectures with edge-triggered interrupts we must never return
+ * IRQ_NONE.
+ */
+#if defined(CONFIG_SA1111) /* ... or other edge-triggered systems */
+#define IRQ_NOTMINE IRQ_HANDLED
+#else
+#define IRQ_NOTMINE IRQ_NONE
+#endif
+
+
+/* Some boards misreport power switching/overcurrent */
+static int distrust_firmware = 1;
+module_param (distrust_firmware, bool, 0);
+MODULE_PARM_DESC (distrust_firmware,
+ "true to distrust firmware power/overcurrent setup");
/* Some boards leave IR set wrongly, since they fail BIOS/SMM handshakes */
static int no_handshake = 0;
@@ -240,7 +252,7 @@ static int ohci_urb_enqueue (
spin_lock_irqsave (&ohci->lock, flags);
/* don't submit to a dead HC */
- if (!HCD_IS_RUNNING(hcd->state)) {
+ if (!HC_IS_RUNNING(hcd->state)) {
retval = -ENODEV;
goto fail;
}
@@ -308,7 +320,7 @@ static int ohci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
#endif
spin_lock_irqsave (&ohci->lock, flags);
- if (HCD_IS_RUNNING(hcd->state)) {
+ if (HC_IS_RUNNING(hcd->state)) {
urb_priv_t *urb_priv;
/* Unless an IRQ completed the unlink while it was being
@@ -355,7 +367,7 @@ ohci_endpoint_disable (struct usb_hcd *hcd, struct usb_host_endpoint *ep)
rescan:
spin_lock_irqsave (&ohci->lock, flags);
- if (!HCD_IS_RUNNING (hcd->state)) {
+ if (!HC_IS_RUNNING (hcd->state)) {
sanitize:
ed->state = ED_IDLE;
finish_unlinks (ohci, 0, NULL);
@@ -532,8 +544,9 @@ static int ohci_run (struct ohci_hcd *ohci)
// flush the writes
(void) ohci_readl (ohci, &ohci->regs->control);
msleep(temp);
- if (power_switching) {
- unsigned ports = roothub_a (ohci) & RH_A_NDP;
+ temp = roothub_a (ohci);
+ if (!(temp & RH_A_NPS)) {
+ unsigned ports = temp & RH_A_NDP;
/* power down each port */
for (temp = 0; temp < ports; temp++)
@@ -574,7 +587,6 @@ retry:
// flush those writes
(void) ohci_readl (ohci, &ohci->regs->control);
}
- ohci_writel (ohci, ohci->fminterval, &ohci->regs->fminterval);
/* Tell the controller where the control and bulk lists are
* The lists are empty now. */
@@ -607,7 +619,7 @@ retry:
ohci->hc_control &= OHCI_CTRL_RWC;
ohci->hc_control |= OHCI_CONTROL_INIT | OHCI_USB_OPER;
ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
- ohci_to_hcd(ohci)->state = USB_STATE_RUNNING;
+ ohci_to_hcd(ohci)->state = HC_STATE_RUNNING;
/* wake on ConnectStatusChange, matching external hubs */
ohci_writel (ohci, RH_HS_DRWE, &ohci->regs->roothub.status);
@@ -624,21 +636,16 @@ retry:
/* NSC 87560 and maybe others */
temp |= RH_A_NOCP;
temp &= ~(RH_A_POTPGT | RH_A_NPS);
- } else if (power_switching) {
- /* act like most external hubs: use per-port power
- * switching and overcurrent reporting.
- */
- temp &= ~(RH_A_NPS | RH_A_NOCP);
- temp |= RH_A_PSM | RH_A_OCPM;
- } else {
+ ohci_writel (ohci, temp, &ohci->regs->roothub.a);
+ } else if ((ohci->flags & OHCI_QUIRK_AMD756) || distrust_firmware) {
/* hub power always on; required for AMD-756 and some
* Mac platforms. ganged overcurrent reporting, if any.
*/
temp |= RH_A_NPS;
+ ohci_writel (ohci, temp, &ohci->regs->roothub.a);
}
- ohci_writel (ohci, temp, &ohci->regs->roothub.a);
ohci_writel (ohci, RH_HS_LPSC, &ohci->regs->roothub.status);
- ohci_writel (ohci, power_switching ? RH_B_PPCM : 0,
+ ohci_writel (ohci, (temp & RH_A_NPS) ? 0 : RH_B_PPCM,
&ohci->regs->roothub.b);
// flush those writes
(void) ohci_readl (ohci, &ohci->regs->control);
@@ -646,9 +653,9 @@ retry:
spin_unlock_irq (&ohci->lock);
// POTPGT delay is bits 24-31, in 2 ms units.
- mdelay ((roothub_a (ohci) >> 23) & 0x1fe);
+ mdelay ((temp >> 23) & 0x1fe);
bus = &ohci_to_hcd(ohci)->self;
- ohci_to_hcd(ohci)->state = USB_STATE_RUNNING;
+ ohci_to_hcd(ohci)->state = HC_STATE_RUNNING;
ohci_dump (ohci, 1);
@@ -667,7 +674,7 @@ retry:
}
udev->speed = USB_SPEED_FULL;
- if (hcd_register_root (udev, ohci_to_hcd(ohci)) != 0) {
+ if (usb_hcd_register_root_hub (udev, ohci_to_hcd(ohci)) != 0) {
usb_put_dev (udev);
disable (ohci);
ohci->hc_control &= ~OHCI_CTRL_HCFS;
@@ -706,7 +713,7 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs)
/* interrupt for some other device? */
} else if ((ints &= ohci_readl (ohci, &regs->intrenable)) == 0) {
- return IRQ_NONE;
+ return IRQ_NOTMINE;
}
if (ints & OHCI_INTR_UE) {
@@ -720,16 +727,17 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs)
if (ints & OHCI_INTR_RD) {
ohci_vdbg (ohci, "resume detect\n");
- schedule_work(&ohci->rh_resume);
+ if (hcd->state != HC_STATE_QUIESCING)
+ schedule_work(&ohci->rh_resume);
}
if (ints & OHCI_INTR_WDH) {
- if (HCD_IS_RUNNING(hcd->state))
+ if (HC_IS_RUNNING(hcd->state))
ohci_writel (ohci, OHCI_INTR_WDH, &regs->intrdisable);
spin_lock (&ohci->lock);
dl_done_list (ohci, ptregs);
spin_unlock (&ohci->lock);
- if (HCD_IS_RUNNING(hcd->state))
+ if (HC_IS_RUNNING(hcd->state))
ohci_writel (ohci, OHCI_INTR_WDH, &regs->intrenable);
}
@@ -742,11 +750,11 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs)
if (ohci->ed_rm_list)
finish_unlinks (ohci, ohci_frame_no(ohci), ptregs);
if ((ints & OHCI_INTR_SF) != 0 && !ohci->ed_rm_list
- && HCD_IS_RUNNING(hcd->state))
+ && HC_IS_RUNNING(hcd->state))
ohci_writel (ohci, OHCI_INTR_SF, &regs->intrdisable);
spin_unlock (&ohci->lock);
- if (HCD_IS_RUNNING(hcd->state)) {
+ if (HC_IS_RUNNING(hcd->state)) {
ohci_writel (ohci, ints, &regs->intrstatus);
ohci_writel (ohci, OHCI_INTR_MIE, &regs->intrenable);
// flush those writes
@@ -901,12 +909,17 @@ MODULE_LICENSE ("GPL");
#include "ohci-au1xxx.c"
#endif
+#ifdef CONFIG_USB_OHCI_HCD_PPC_SOC
+#include "ohci-ppc-soc.c"
+#endif
+
#if !(defined(CONFIG_PCI) \
|| defined(CONFIG_SA1111) \
|| defined(CONFIG_ARCH_OMAP) \
|| defined (CONFIG_ARCH_LH7A404) \
|| defined (CONFIG_PXA27x) \
|| defined (CONFIG_SOC_AU1X00) \
+ || defined (CONFIG_USB_OHCI_HCD_PPC_SOC) \
)
#error "missing bus glue for ohci-hcd"
#endif
diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
index 1c296c3adcbae..e2fc4129dfc6e 100644
--- a/drivers/usb/host/ohci-hub.c
+++ b/drivers/usb/host/ohci-hub.c
@@ -73,7 +73,7 @@ static int ohci_hub_suspend (struct usb_hcd *hcd)
ohci_dbg (ohci, "suspend root hub\n");
/* First stop any processing */
- hcd->state = USB_STATE_QUIESCING;
+ hcd->state = HC_STATE_QUIESCING;
if (ohci->hc_control & OHCI_SCHED_ENABLES) {
int limit;
@@ -119,7 +119,7 @@ static int ohci_hub_suspend (struct usb_hcd *hcd)
done:
if (status == 0)
- hcd->state = HCD_STATE_SUSPENDED;
+ hcd->state = HC_STATE_SUSPENDED;
spin_unlock_irqrestore (&ohci->lock, flags);
return status;
}
@@ -147,7 +147,7 @@ static int ohci_hub_resume (struct usb_hcd *hcd)
if (ohci->hc_control & (OHCI_CTRL_IR | OHCI_SCHED_ENABLES)) {
/* this can happen after suspend-to-disk */
- if (hcd->state == USB_STATE_RESUMING) {
+ if (hcd->state == HC_STATE_RESUMING) {
ohci_dbg (ohci, "BIOS/SMM active, control %03x\n",
ohci->hc_control);
status = -EBUSY;
@@ -169,7 +169,7 @@ static int ohci_hub_resume (struct usb_hcd *hcd)
ohci_info (ohci, "wakeup\n");
break;
case OHCI_USB_OPER:
- ohci_dbg (ohci, "odd resume\n");
+ ohci_dbg (ohci, "already resumed\n");
status = 0;
break;
default: /* RESET, we lost power */
@@ -197,8 +197,8 @@ static int ohci_hub_resume (struct usb_hcd *hcd)
&ohci->regs->roothub.portstatus [temp]);
}
- /* Some controllers (lucent) need extra-long delays */
- hcd->state = USB_STATE_RESUMING;
+ /* Some controllers (lucent erratum) need extra-long delays */
+ hcd->state = HC_STATE_RESUMING;
mdelay (20 /* usb 11.5.1.10 */ + 15);
temp = ohci_readl (ohci, &ohci->regs->control);
@@ -216,6 +216,7 @@ static int ohci_hub_resume (struct usb_hcd *hcd)
ohci_writel (ohci, 0, &ohci->regs->ed_periodcurrent);
ohci_writel (ohci, (u32) ohci->hcca_dma, &ohci->regs->hcca);
+ /* Sometimes PCI D3 suspend trashes frame timings ... */
periodic_reinit (ohci);
/* interrupts might have been disabled */
@@ -272,7 +273,7 @@ static int ohci_hub_resume (struct usb_hcd *hcd)
(void) ohci_readl (ohci, &ohci->regs->control);
}
- hcd->state = USB_STATE_RUNNING;
+ hcd->state = HC_STATE_RUNNING;
return 0;
}
@@ -313,7 +314,7 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
* letting khubd or root hub timer see state changes.
*/
if ((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER
- || !HCD_IS_RUNNING(hcd->state)) {
+ || !HC_IS_RUNNING(hcd->state)) {
can_suspend = 0;
goto done;
}
@@ -378,7 +379,7 @@ done:
) {
ohci_vdbg (ohci, "autosuspend\n");
(void) ohci_hub_suspend (hcd);
- hcd->state = USB_STATE_RUNNING;
+ hcd->state = HC_STATE_RUNNING;
usb_unlock_device (hcd->self.root_hub);
}
#endif
diff --git a/drivers/usb/host/ohci-lh7a404.c b/drivers/usb/host/ohci-lh7a404.c
index c00324861050b..817620d738414 100644
--- a/drivers/usb/host/ohci-lh7a404.c
+++ b/drivers/usb/host/ohci-lh7a404.c
@@ -53,19 +53,6 @@ static void lh7a404_stop_hc(struct platform_device *dev)
/*-------------------------------------------------------------------------*/
-
-static irqreturn_t usb_hcd_lh7a404_hcim_irq (int irq, void *__hcd,
- struct pt_regs * r)
-{
- struct usb_hcd *hcd = __hcd;
-
- return usb_hcd_irq(irq, hcd, r);
-}
-
-/*-------------------------------------------------------------------------*/
-
-void usb_hcd_lh7a404_remove (struct usb_hcd *, struct platform_device *);
-
/* configure so an HC device and id are always provided */
/* always called with process context; sleeping is OK */
@@ -80,90 +67,48 @@ void usb_hcd_lh7a404_remove (struct usb_hcd *, struct platform_device *);
*
*/
int usb_hcd_lh7a404_probe (const struct hc_driver *driver,
- struct usb_hcd **hcd_out,
struct platform_device *dev)
{
int retval;
- struct usb_hcd *hcd = 0;
-
- unsigned int *addr = NULL;
+ struct usb_hcd *hcd;
- if (!request_mem_region(dev->resource[0].start,
- dev->resource[0].end
- - dev->resource[0].start + 1, hcd_name)) {
- pr_debug("request_mem_region failed");
- return -EBUSY;
- }
-
-
- lh7a404_start_hc(dev);
-
- addr = ioremap(dev->resource[0].start,
- dev->resource[0].end
- - dev->resource[0].start + 1);
- if (!addr) {
- pr_debug("ioremap failed");
- retval = -ENOMEM;
- goto err1;
+ if (dev->resource[1].flags != IORESOURCE_IRQ) {
+ pr_debug("resource[1] is not IORESOURCE_IRQ");
+ return -ENOMEM;
}
- if(dev->resource[1].flags != IORESOURCE_IRQ){
- pr_debug ("resource[1] is not IORESOURCE_IRQ");
- retval = -ENOMEM;
+ hcd = usb_create_hcd(driver, &dev->dev, "lh7a404");
+ if (!hcd)
+ return -ENOMEM;
+ hcd->rsrc_start = dev->resource[0].start;
+ hcd->rsrc_len = dev->resource[0].end - dev->resource[0].start + 1;
+
+ if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
+ pr_debug("request_mem_region failed");
+ retval = -EBUSY;
goto err1;
}
-
- hcd = usb_create_hcd (driver);
- if (hcd == NULL){
- pr_debug ("hcd_alloc failed");
+ hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
+ if (!hcd->regs) {
+ pr_debug("ioremap failed");
retval = -ENOMEM;
- goto err1;
- }
- ohci_hcd_init(hcd_to_ohci(hcd));
-
- hcd->irq = dev->resource[1].start;
- hcd->regs = addr;
- hcd->self.controller = &dev->dev;
-
- retval = hcd_buffer_create (hcd);
- if (retval != 0) {
- pr_debug ("pool alloc fail");
goto err2;
}
- retval = request_irq (hcd->irq, usb_hcd_lh7a404_hcim_irq, SA_INTERRUPT,
- hcd->driver->description, hcd);
- if (retval != 0) {
- pr_debug("request_irq failed");
- retval = -EBUSY;
- goto err3;
- }
-
- pr_debug ("%s (LH7A404) at 0x%p, irq %d",
- hcd->driver->description, hcd->regs, hcd->irq);
-
- hcd->self.bus_name = "lh7a404";
- usb_register_bus (&hcd->self);
+ lh7a404_start_hc(dev);
+ ohci_hcd_init(hcd_to_ohci(hcd));
- if ((retval = driver->start (hcd)) < 0)
- {
- usb_hcd_lh7a404_remove(hcd, dev);
+ retval = usb_add_hcd(hcd, dev->resource[1].start, SA_INTERRUPT);
+ if (retval == 0)
return retval;
- }
- *hcd_out = hcd;
- return 0;
-
- err3:
- hcd_buffer_destroy (hcd);
+ lh7a404_stop_hc(dev);
+ iounmap(hcd->regs);
err2:
- usb_put_hcd(hcd);
+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
err1:
- lh7a404_stop_hc(dev);
- release_mem_region(dev->resource[0].start,
- dev->resource[0].end
- - dev->resource[0].start + 1);
+ usb_put_hcd(hcd);
return retval;
}
@@ -183,28 +128,11 @@ int usb_hcd_lh7a404_probe (const struct hc_driver *driver,
*/
void usb_hcd_lh7a404_remove (struct usb_hcd *hcd, struct platform_device *dev)
{
- pr_debug ("remove: %s, state %x", hcd->self.bus_name, hcd->state);
-
- if (in_interrupt ())
- BUG ();
-
- hcd->state = USB_STATE_QUIESCING;
-
- pr_debug ("%s: roothub graceful disconnect", hcd->self.bus_name);
- usb_disconnect (&hcd->self.root_hub);
-
- hcd->driver->stop (hcd);
- hcd->state = USB_STATE_HALT;
-
- free_irq (hcd->irq, hcd);
- hcd_buffer_destroy (hcd);
-
- usb_deregister_bus (&hcd->self);
-
+ usb_remove_hcd(hcd);
lh7a404_stop_hc(dev);
- release_mem_region(dev->resource[0].start,
- dev->resource[0].end
- - dev->resource[0].start + 1);
+ iounmap(hcd->regs);
+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+ usb_put_hcd(hcd);
}
/*-------------------------------------------------------------------------*/
@@ -238,7 +166,7 @@ static const struct hc_driver ohci_lh7a404_hc_driver = {
* generic hardware linkage
*/
.irq = ohci_irq,
- .flags = HCD_USB11,
+ .flags = HCD_USB11 | HCD_MEMORY,
/*
* basic lifecycle operations
@@ -274,7 +202,6 @@ static const struct hc_driver ohci_lh7a404_hc_driver = {
static int ohci_hcd_lh7a404_drv_probe(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
- struct usb_hcd *hcd = NULL;
int ret;
pr_debug ("In ohci_hcd_lh7a404_drv_probe");
@@ -282,11 +209,7 @@ static int ohci_hcd_lh7a404_drv_probe(struct device *dev)
if (usb_disabled())
return -ENODEV;
- ret = usb_hcd_lh7a404_probe(&ohci_lh7a404_hc_driver, &hcd, pdev);
-
- if (ret == 0)
- dev_set_drvdata(dev, hcd);
-
+ ret = usb_hcd_lh7a404_probe(&ohci_lh7a404_hc_driver, pdev);
return ret;
}
@@ -296,7 +219,6 @@ static int ohci_hcd_lh7a404_drv_remove(struct device *dev)
struct usb_hcd *hcd = dev_get_drvdata(dev);
usb_hcd_lh7a404_remove(hcd, pdev);
- dev_set_drvdata(dev, NULL);
return 0;
}
/*TBD*/
diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c
index 2e9c5c07942dc..90285f180f87a 100644
--- a/drivers/usb/host/ohci-omap.c
+++ b/drivers/usb/host/ohci-omap.c
@@ -2,16 +2,14 @@
* OHCI HCD (Host Controller Driver) for USB.
*
* (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
- * (C) Copyright 2000-2004 David Brownell <dbrownell@users.sourceforge.net>
+ * (C) Copyright 2000-2005 David Brownell
* (C) Copyright 2002 Hewlett-Packard Company
*
* OMAP Bus Glue
*
- * Written by Christopher Hoover <ch@hpl.hp.com>
- * Based on fragments of previous driver by Russell King et al.
- *
- * Modified for OMAP from ohci-sa1111.c by Tony Lindgren <tony@atomide.com>
+ * Modified for OMAP by Tony Lindgren <tony@atomide.com>
* Based on the 2.4 OMAP OHCI driver originally done by MontaVista Software Inc.
+ * and on ohci-sa1111.c by Christopher Hoover <ch@hpl.hp.com>
*
* This file is licenced under the GPL.
*/
@@ -26,59 +24,60 @@
#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 */
+#define OMAP1510_LB_MEMSIZE 32 /* Should be same as SDRAM size */
+#define OMAP1510_LB_CLOCK_DIV 0xfffec10c
+#define OMAP1510_LB_MMU_CTL 0xfffec208
+#define OMAP1510_LB_MMU_LCK 0xfffec224
+#define OMAP1510_LB_MMU_LD_TLB 0xfffec228
+#define OMAP1510_LB_MMU_CAM_H 0xfffec22c
+#define OMAP1510_LB_MMU_CAM_L 0xfffec230
+#define OMAP1510_LB_MMU_RAM_H 0xfffec234
+#define OMAP1510_LB_MMU_RAM_L 0xfffec238
-#include "ohci-omap.h"
#ifndef CONFIG_ARCH_OMAP
#error "This file is OMAP bus glue. CONFIG_OMAP must be defined."
#endif
-extern int usb_disabled(void);
-extern int ocpi_enable(void);
+#ifdef CONFIG_TPS65010
+#include <asm/arch/tps65010.h>
+#else
-/*
- * OHCI clock initialization for OMAP-1510 and 1610
- */
-static int omap_ohci_clock_power(int on)
-{
- if (on) {
- /* for 1510, 48MHz DPLL is set up in usb init */
+#define LOW 0
+#define HIGH 1
- if (cpu_is_omap16xx()) {
- /* Enable OHCI */
- omap_writel(omap_readl(ULPD_SOFT_REQ) | SOFT_USB_OTG_REQ,
- ULPD_SOFT_REQ);
+#define GPIO1 1
- /* USB host clock request if not using OTG */
- omap_writel(omap_readl(ULPD_SOFT_REQ) | SOFT_USB_REQ,
- ULPD_SOFT_REQ);
+static inline int tps65010_set_gpio_out_value(unsigned gpio, unsigned value)
+{
+ return 0;
+}
- omap_writel(omap_readl(ULPD_STATUS_REQ) | USB_HOST_DPLL_REQ,
- ULPD_STATUS_REQ);
- }
+#endif
- /* Enable 48MHz clock to USB */
- omap_writel(omap_readl(ULPD_CLOCK_CTRL) | USB_MCLK_EN,
- ULPD_CLOCK_CTRL);
+extern int usb_disabled(void);
+extern int ocpi_enable(void);
- omap_writel(omap_readl(ARM_IDLECT2) | (1 << EN_LBFREECK) | (1 << EN_LBCK),
- ARM_IDLECT2);
+static struct clk *usb_host_ck;
- omap_writel(omap_readl(MOD_CONF_CTRL_0) | USB_HOST_HHC_UHOST_EN,
- MOD_CONF_CTRL_0);
+static void omap_ohci_clock_power(int on)
+{
+ if (on) {
+ clk_enable(usb_host_ck);
+ /* guesstimate for T5 == 1x 32K clock + APLL lock time */
+ udelay(100);
} else {
- /* Disable 48MHz clock to USB */
- omap_writel(omap_readl(ULPD_CLOCK_CTRL) & ~USB_MCLK_EN,
- ULPD_CLOCK_CTRL);
-
- /* FIXME: The DPLL stays on for now */
+ clk_disable(usb_host_ck);
}
-
- return 0;
}
/*
- * Hardware specific transceiver power on/off
+ * Board specific gang-switched transceiver power on/off.
+ * NOTE: OSK supplies power from DC, not battery.
*/
static int omap_ohci_transceiver_power(int on)
{
@@ -87,17 +86,15 @@ static int omap_ohci_transceiver_power(int on)
fpga_write(fpga_read(INNOVATOR_FPGA_CAM_USB_CONTROL)
| ((1 << 5/*usb1*/) | (1 << 3/*usb2*/)),
INNOVATOR_FPGA_CAM_USB_CONTROL);
- else if (machine_is_omap_osk()) {
- /* FIXME: GPIO1 -> 1 on the TPS65010 I2C chip */
- }
+ else if (machine_is_omap_osk())
+ tps65010_set_gpio_out_value(GPIO1, LOW);
} else {
if (machine_is_omap_innovator() && cpu_is_omap1510())
fpga_write(fpga_read(INNOVATOR_FPGA_CAM_USB_CONTROL)
& ~((1 << 5/*usb1*/) | (1 << 3/*usb2*/)),
INNOVATOR_FPGA_CAM_USB_CONTROL);
- else if (machine_is_omap_osk()) {
- /* FIXME: GPIO1 -> 0 on the TPS65010 I2C chip */
- }
+ else if (machine_is_omap_osk())
+ tps65010_set_gpio_out_value(GPIO1, HIGH);
}
return 0;
@@ -177,6 +174,7 @@ static int omap_start_hc(struct ohci_hcd *ohci, struct platform_device *pdev)
{
struct omap_usb_config *config = pdev->dev.platform_data;
int need_transceiver = (config->otg != 0);
+ int ret;
dev_dbg(&pdev->dev, "starting USB Controller\n");
@@ -188,7 +186,7 @@ static int omap_start_hc(struct ohci_hcd *ohci, struct platform_device *pdev)
/* boards can use OTG transceivers in non-OTG modes */
need_transceiver = need_transceiver
- || machine_is_omap_h2();
+ || machine_is_omap_h2() || machine_is_omap_h3();
if (cpu_is_omap16xx())
ocpi_enable();
@@ -213,21 +211,44 @@ static int omap_start_hc(struct ohci_hcd *ohci, struct platform_device *pdev)
}
#endif
- if (machine_is_omap_osk()) {
- omap_request_gpio(9);
- omap_set_gpio_direction(9, 1);
- omap_set_gpio_dataout(9, 1);
- }
-
omap_ohci_clock_power(1);
- omap_ohci_transceiver_power(1);
-
if (cpu_is_omap1510()) {
omap_1510_local_bus_power(1);
omap_1510_local_bus_init();
}
+ if ((ret = ohci_init(ohci)) < 0)
+ return ret;
+
+ /* board-specific power switching and overcurrent support */
+ if (machine_is_omap_osk() || machine_is_omap_innovator()) {
+ u32 rh = roothub_a (ohci);
+
+ /* power switching (ganged by default) */
+ rh &= ~RH_A_NPS;
+
+ /* TPS2045 switch for internal transceiver (port 1) */
+ if (machine_is_omap_osk()) {
+ ohci->power_budget = 250;
+
+ rh &= ~RH_A_NOCP;
+
+ /* gpio9 for overcurrent detction */
+ omap_cfg_reg(W8_1610_GPIO9);
+ omap_request_gpio(9);
+ omap_set_gpio_direction(9, 1 /* IN */);
+
+ /* for paranoia's sake: disable USB.PUEN */
+ omap_cfg_reg(W4_USB_HIGHZ);
+ }
+ ohci_writel(ohci, rh, &ohci->regs->roothub.a);
+ distrust_firmware = 0;
+ }
+
+ /* FIXME khubd hub requests should manage power switching */
+ omap_ohci_transceiver_power(1);
+
/* board init will have already handled HMC and mux setup.
* any external transceiver should already be initialized
* too, so all configured ports use the right signaling now.
@@ -239,16 +260,7 @@ static int omap_start_hc(struct ohci_hcd *ohci, struct platform_device *pdev)
static void omap_stop_hc(struct platform_device *pdev)
{
dev_dbg(&pdev->dev, "stopping USB Controller\n");
-
- /*
- * FIXME: Put the USB host controller into reset.
- */
-
- /*
- * FIXME: Stop the USB clock.
- */
- //omap_disable_device(dev);
-
+ omap_ohci_clock_power(0);
}
@@ -282,78 +294,53 @@ int usb_hcd_omap_probe (const struct hc_driver *driver,
}
if (pdev->resource[0].flags != IORESOURCE_MEM
- || pdev->resource[1].flags != IORESOURCE_IRQ) {
+ || pdev->resource[1].flags != IORESOURCE_IRQ) {
printk(KERN_ERR "hcd probe: invalid resource type\n");
return -ENODEV;
}
- if (!request_mem_region(pdev->resource[0].start,
- pdev->resource[0].end - pdev->resource[0].start + 1, hcd_name)) {
- dev_dbg(&pdev->dev, "request_mem_region failed\n");
- return -EBUSY;
- }
+ usb_host_ck = clk_get(0, "usb_hhc_ck");
+ if (IS_ERR(usb_host_ck))
+ return PTR_ERR(usb_host_ck);
- hcd = usb_create_hcd (driver);
- if (hcd == NULL){
- dev_dbg(&pdev->dev, "hcd_alloc failed\n");
+ hcd = usb_create_hcd (driver, &pdev->dev, pdev->dev.bus_id);
+ if (!hcd) {
retval = -ENOMEM;
+ goto err0;
+ }
+ 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)) {
+ dev_dbg(&pdev->dev, "request_mem_region failed\n");
+ retval = -EBUSY;
goto err1;
}
- dev_set_drvdata(&pdev->dev, hcd);
+
+ hcd->regs = (void __iomem *) (int) IO_ADDRESS(hcd->rsrc_start);
+
ohci = hcd_to_ohci(hcd);
ohci_hcd_init(ohci);
- hcd->irq = pdev->resource[1].start;
- hcd->regs = (void *)pdev->resource[0].start;
- hcd->self.controller = &pdev->dev;
-
retval = omap_start_hc(ohci, pdev);
if (retval < 0)
goto err2;
- retval = hcd_buffer_create (hcd);
- if (retval != 0) {
- dev_dbg(&pdev->dev, "pool alloc fail\n");
- goto err2;
- }
-
- retval = request_irq (hcd->irq, usb_hcd_irq,
- SA_INTERRUPT, hcd->driver->description, hcd);
- if (retval != 0) {
- dev_dbg(&pdev->dev, "request_irq failed\n");
- retval = -EBUSY;
- goto err3;
- }
-
- dev_info(&pdev->dev, "at 0x%p, irq %d\n", hcd->regs, hcd->irq);
-
- hcd->self.bus_name = pdev->dev.bus_id;
- usb_register_bus (&hcd->self);
-
- if ((retval = driver->start (hcd)) < 0)
- {
- usb_hcd_omap_remove(hcd, pdev);
+ retval = usb_add_hcd(hcd, platform_get_irq(pdev, 0), SA_INTERRUPT);
+ if (retval == 0)
return retval;
- }
- return 0;
-
- err3:
- hcd_buffer_destroy (hcd);
- err2:
- dev_set_drvdata(&pdev->dev, NULL);
- usb_put_hcd(hcd);
- err1:
omap_stop_hc(pdev);
-
- release_mem_region(pdev->resource[0].start,
- pdev->resource[0].end - pdev->resource[0].start + 1);
-
+err2:
+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+err1:
+ usb_put_hcd(hcd);
+err0:
+ clk_put(usb_host_ck);
return retval;
}
-/* may be called without controller electrically present */
/* may be called with controller, bus, and devices active */
/**
@@ -368,31 +355,13 @@ int usb_hcd_omap_probe (const struct hc_driver *driver,
*/
void usb_hcd_omap_remove (struct usb_hcd *hcd, struct platform_device *pdev)
{
- dev_info(&pdev->dev, "remove: state %x\n", hcd->state);
-
- if (in_interrupt ())
- BUG ();
-
- hcd->state = USB_STATE_QUIESCING;
-
- dev_dbg(&pdev->dev, "roothub graceful disconnect\n");
- usb_disconnect (&hcd->self.root_hub);
-
- hcd->driver->stop (hcd);
- hcd_buffer_destroy (hcd);
- hcd->state = USB_STATE_HALT;
-
+ usb_remove_hcd(hcd);
if (machine_is_omap_osk())
omap_free_gpio(9);
-
- free_irq (hcd->irq, hcd);
-
- usb_deregister_bus (&hcd->self);
-
omap_stop_hc(pdev);
-
- release_mem_region(pdev->resource[0].start,
- pdev->resource[0].end - pdev->resource[0].start + 1);
+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+ usb_put_hcd(hcd);
+ clk_put(usb_host_ck);
}
/*-------------------------------------------------------------------------*/
@@ -404,15 +373,12 @@ ohci_omap_start (struct usb_hcd *hcd)
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
int ret;
- if ((ret = ohci_init(ohci)) < 0)
- return ret;
-
config = hcd->self.controller->platform_data;
if (config->otg || config->rwc)
writel(OHCI_CTRL_RWC, &ohci->regs->control);
if ((ret = ohci_run (ohci)) < 0) {
- err ("can't start %s", hcd->self.bus_name);
+ dev_err(hcd->self.controller, "can't start\n");
ohci_stop (hcd);
return ret;
}
@@ -430,7 +396,7 @@ static const struct hc_driver ohci_omap_hc_driver = {
* generic hardware linkage
*/
.irq = ohci_irq,
- .flags = HCD_USB11,
+ .flags = HCD_USB11 | HCD_MEMORY,
/*
* basic lifecycle operations
@@ -488,7 +454,7 @@ static int ohci_hcd_omap_drv_remove(struct device *dev)
/*-------------------------------------------------------------------------*/
-#if defined(CONFIG_USB_SUSPEND) || defined(CONFIG_PM)
+#ifdef CONFIG_PM
/* states match PCI usage, always suspending the root hub except that
* 4 ~= D3cold (ACPI D3) with clock off (resume sees reset).
@@ -499,6 +465,8 @@ static int ohci_omap_suspend(struct device *dev, u32 state, u32 level)
struct ohci_hcd *ohci = hcd_to_ohci(dev_get_drvdata(dev));
int status = -EINVAL;
+ if (level != SUSPEND_POWER_DOWN)
+ return 0;
if (state <= dev->power.power_state)
return 0;
@@ -507,13 +475,12 @@ static int ohci_omap_suspend(struct device *dev, u32 state, u32 level)
status = ohci_hub_suspend(ohci_to_hcd(ohci));
if (status == 0) {
if (state >= 4) {
- /* power off + reset */
- OTG_SYSCON_2_REG &= ~UHOST_EN;
+ omap_ohci_clock_power(0);
ohci_to_hcd(ohci)->self.root_hub->state =
USB_STATE_SUSPENDED;
state = 4;
}
- ohci_to_hcd(ohci)->state = HCD_STATE_SUSPENDED;
+ ohci_to_hcd(ohci)->state = HC_STATE_SUSPENDED;
dev->power.power_state = state;
}
up(&ohci_to_hcd(ohci)->self.root_hub->serialize);
@@ -525,6 +492,9 @@ static int ohci_omap_resume(struct device *dev, u32 level)
struct ohci_hcd *ohci = hcd_to_ohci(dev_get_drvdata(dev));
int status = 0;
+ if (level != RESUME_POWER_ON)
+ return 0;
+
switch (dev->power.power_state) {
case 0:
break;
@@ -532,7 +502,7 @@ static int ohci_omap_resume(struct device *dev, u32 level)
if (time_before(jiffies, ohci->next_statechange))
msleep(5);
ohci->next_statechange = jiffies;
- OTG_SYSCON_2_REG |= UHOST_EN;
+ omap_ohci_clock_power(1);
/* FALLTHROUGH */
default:
dev_dbg(dev, "resume from %d\n", dev->power.power_state);
@@ -563,7 +533,7 @@ static struct device_driver ohci_hcd_omap_driver = {
.bus = &platform_bus_type,
.probe = ohci_hcd_omap_drv_probe,
.remove = ohci_hcd_omap_drv_remove,
-#if defined(CONFIG_USB_SUSPEND) || defined(CONFIG_PM)
+#ifdef CONFIG_PM
.suspend = ohci_omap_suspend,
.resume = ohci_omap_resume,
#endif
diff --git a/drivers/usb/host/ohci-ppc-soc.c b/drivers/usb/host/ohci-ppc-soc.c
new file mode 100644
index 0000000000000..17964c39d06a0
--- /dev/null
+++ b/drivers/usb/host/ohci-ppc-soc.c
@@ -0,0 +1,234 @@
+/*
+ * OHCI HCD (Host Controller Driver) for USB.
+ *
+ * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
+ * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
+ * (C) Copyright 2002 Hewlett-Packard Company
+ * (C) Copyright 2003-2005 MontaVista Software Inc.
+ *
+ * Bus Glue for PPC On-Chip OHCI driver
+ * Tested on Freescale MPC5200 and IBM STB04xxx
+ *
+ * Modified by Dale Farnsworth <dale@farnsworth.org> from ohci-sa1111.c
+ *
+ * This file is licenced under the GPL.
+ */
+
+#include <asm/usb.h>
+
+/* configure so an HC device and id are always provided */
+/* always called with process context; sleeping is OK */
+
+/**
+ * usb_hcd_ppc_soc_probe - initialize On-Chip HCDs
+ * Context: !in_interrupt()
+ *
+ * Allocates basic resources for this USB host controller, and
+ * then invokes the start() method for the HCD associated with it
+ * through the hotplug entry's driver_data.
+ *
+ * Store this function in the HCD's struct pci_driver as probe().
+ */
+static int usb_hcd_ppc_soc_probe(const struct hc_driver *driver,
+ struct platform_device *pdev)
+{
+ int retval;
+ struct usb_hcd *hcd;
+ struct ohci_hcd *ohci;
+ struct resource *res;
+ int irq;
+ struct usb_hcd_platform_data *pd = pdev->dev.platform_data;
+
+ pr_debug("initializing PPC-SOC USB Controller\n");
+
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (!res) {
+ pr_debug(__FILE__ ": no irq\n");
+ return -ENODEV;
+ }
+ irq = res->start;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ pr_debug(__FILE__ ": no reg addr\n");
+ return -ENODEV;
+ }
+
+ hcd = usb_create_hcd(driver, &pdev->dev, "PPC-SOC USB");
+ if (!hcd)
+ return -ENOMEM;
+ hcd->rsrc_start = res->start;
+ hcd->rsrc_len = res->end - res->start + 1;
+
+ if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
+ pr_debug(__FILE__ ": request_mem_region failed\n");
+ retval = -EBUSY;
+ goto err1;
+ }
+
+ hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
+ if (!hcd->regs) {
+ pr_debug(__FILE__ ": ioremap failed\n");
+ retval = -ENOMEM;
+ goto err2;
+ }
+
+ if (pd->start && (retval = pd->start(pdev)))
+ goto err3;
+
+ ohci = hcd_to_ohci(hcd);
+ ohci->flags |= OHCI_BIG_ENDIAN;
+ ohci_hcd_init(ohci);
+
+ retval = usb_add_hcd(hcd, irq, SA_INTERRUPT);
+ if (retval == 0)
+ return retval;
+
+ pr_debug("Removing PPC-SOC USB Controller\n");
+ if (pd && pd->stop)
+ pd->stop(pdev);
+ err3:
+ iounmap(hcd->regs);
+ err2:
+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+ err1:
+ usb_put_hcd(hcd);
+ return retval;
+}
+
+
+/* may be called without controller electrically present */
+/* may be called with controller, bus, and devices active */
+
+/**
+ * usb_hcd_ppc_soc_remove - shutdown processing for On-Chip HCDs
+ * @pdev: USB Host Controller being removed
+ * Context: !in_interrupt()
+ *
+ * Reverses the effect of usb_hcd_ppc_soc_probe(), first invoking
+ * the HCD's stop() method. It is always called from a thread
+ * context, normally "rmmod", "apmd", or something similar.
+ *
+ */
+static void usb_hcd_ppc_soc_remove(struct usb_hcd *hcd,
+ struct platform_device *pdev)
+{
+ struct usb_hcd_platform_data *pd = pdev->dev.platform_data;
+
+ usb_remove_hcd(hcd);
+
+ pr_debug("stopping PPC-SOC USB Controller\n");
+ if (pd && pd->stop)
+ pd->stop(pdev);
+
+ iounmap(hcd->regs);
+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+ usb_hcd_put(hcd);
+}
+
+static int __devinit
+ohci_ppc_soc_start(struct usb_hcd *hcd)
+{
+ struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+ int ret;
+
+ if ((ret = ohci_init(ohci)) < 0)
+ return ret;
+
+ if ((ret = ohci_run(ohci)) < 0) {
+ err("can't start %s", ohci_to_hcd(ohci)->self.bus_name);
+ ohci_stop(hcd);
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct hc_driver ohci_ppc_soc_hc_driver = {
+ .description = hcd_name,
+ .hcd_priv_size = sizeof(struct ohci_hcd),
+
+ /*
+ * generic hardware linkage
+ */
+ .irq = ohci_irq,
+ .flags = HCD_USB11 | HCD_MEMORY,
+
+ /*
+ * basic lifecycle operations
+ */
+ .start = ohci_ppc_soc_start,
+ .stop = ohci_stop,
+
+ /*
+ * managing i/o requests and associated device resources
+ */
+ .urb_enqueue = ohci_urb_enqueue,
+ .urb_dequeue = ohci_urb_dequeue,
+ .endpoint_disable = ohci_endpoint_disable,
+
+ /*
+ * scheduling support
+ */
+ .get_frame_number = ohci_get_frame,
+
+ /*
+ * root hub support
+ */
+ .hub_status_data = ohci_hub_status_data,
+ .hub_control = ohci_hub_control,
+#ifdef CONFIG_USB_SUSPEND
+ .hub_suspend = ohci_hub_suspend,
+ .hub_resume = ohci_hub_resume,
+#endif
+ .start_port_reset = ohci_start_port_reset,
+};
+
+static int ohci_hcd_ppc_soc_drv_probe(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ int ret;
+
+ if (usb_disabled())
+ return -ENODEV;
+
+ ret = usb_hcd_ppc_soc_probe(&ohci_ppc_soc_hc_driver, pdev);
+ return ret;
+}
+
+static int ohci_hcd_ppc_soc_drv_remove(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct usb_hcd *hcd = dev_get_drvdata(dev);
+
+ usb_hcd_ppc_soc_remove(hcd, pdev);
+ return 0;
+}
+
+static struct device_driver ohci_hcd_ppc_soc_driver = {
+ .name = "ppc-soc-ohci",
+ .bus = &platform_bus_type,
+ .probe = ohci_hcd_ppc_soc_drv_probe,
+ .remove = ohci_hcd_ppc_soc_drv_remove,
+#if defined(CONFIG_USB_SUSPEND) || defined(CONFIG_PM)
+ /*.suspend = ohci_hcd_ppc_soc_drv_suspend,*/
+ /*.resume = ohci_hcd_ppc_soc_drv_resume,*/
+#endif
+};
+
+static int __init ohci_hcd_ppc_soc_init(void)
+{
+ pr_debug(DRIVER_INFO " (PPC SOC)\n");
+ pr_debug("block sizes: ed %d td %d\n", sizeof(struct ed),
+ sizeof(struct td));
+
+ return driver_register(&ohci_hcd_ppc_soc_driver);
+}
+
+static void __exit ohci_hcd_ppc_soc_cleanup(void)
+{
+ driver_unregister(&ohci_hcd_ppc_soc_driver);
+}
+
+module_init(ohci_hcd_ppc_soc_init);
+module_exit(ohci_hcd_ppc_soc_cleanup);
diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c
index 8283c1aafcf9f..6f3464a957798 100644
--- a/drivers/usb/host/ohci-pxa27x.c
+++ b/drivers/usb/host/ohci-pxa27x.c
@@ -152,8 +152,6 @@ static void pxa27x_stop_hc(struct platform_device *dev)
/*-------------------------------------------------------------------------*/
-void usb_hcd_pxa27x_remove (struct usb_hcd *, struct platform_device *);
-
/* configure so an HC device and id are always provided */
/* always called with process context; sleeping is OK */
@@ -168,19 +166,33 @@ void usb_hcd_pxa27x_remove (struct usb_hcd *, struct platform_device *);
*
*/
int usb_hcd_pxa27x_probe (const struct hc_driver *driver,
- struct usb_hcd **hcd_out,
struct platform_device *dev)
{
int retval;
- struct usb_hcd *hcd = 0;
+ struct usb_hcd *hcd;
+
+ if (dev->resource[1].flags != IORESOURCE_IRQ) {
+ pr_debug ("resource[1] is not IORESOURCE_IRQ");
+ return -ENOMEM;
+ }
- unsigned int *addr = NULL;
+ hcd = usb_create_hcd (driver, &dev->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;
- if (!request_mem_region(dev->resource[0].start,
- dev->resource[0].end
- - dev->resource[0].start + 1, hcd_name)) {
+ if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
pr_debug("request_mem_region failed");
- return -EBUSY;
+ retval = -EBUSY;
+ goto err1;
+ }
+
+ hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
+ if (!hcd->regs) {
+ pr_debug("ioremap failed");
+ retval = -ENOMEM;
+ goto err2;
}
pxa27x_start_hc(dev);
@@ -198,69 +210,18 @@ int usb_hcd_pxa27x_probe (const struct hc_driver *driver,
if (pxa27x_ohci_clear_port_power(3) < 0)
printk(KERN_ERR "Setting port 3 power failed.\n");
- addr = ioremap(dev->resource[0].start,
- dev->resource[0].end - dev->resource[0].start + 1);
- if (!addr) {
- pr_debug("ioremap failed");
- retval = -ENOMEM;
- goto err1;
- }
-
- if(dev->resource[1].flags != IORESOURCE_IRQ){
- pr_debug ("resource[1] is not IORESOURCE_IRQ");
- retval = -ENOMEM;
- goto err1;
- }
-
- hcd = usb_create_hcd (driver);
- if (hcd == NULL){
- pr_debug ("hcd_alloc failed");
- retval = -ENOMEM;
- goto err1;
- }
ohci_hcd_init(hcd_to_ohci(hcd));
- hcd->irq = dev->resource[1].start;
- hcd->regs = addr;
- hcd->self.controller = &dev->dev;
-
- retval = hcd_buffer_create (hcd);
- if (retval != 0) {
- pr_debug ("pool alloc fail");
- goto err2;
- }
-
- retval = request_irq (hcd->irq, usb_hcd_irq, SA_INTERRUPT,
- hcd->driver->description, hcd);
- if (retval != 0) {
- pr_debug("request_irq(%d) failed with retval %d\n",hcd->irq,retval);
- retval = -EBUSY;
- goto err3;
- }
-
- pr_debug ("%s (pxa27x) at 0x%p, irq %d",
- hcd->driver->description, hcd->regs, hcd->irq);
-
- hcd->self.bus_name = "pxa27x";
- usb_register_bus (&hcd->self);
-
- if ((retval = driver->start (hcd)) < 0) {
- usb_hcd_pxa27x_remove(hcd, dev);
+ retval = usb_add_hcd(hcd, dev->resource[1].start, SA_INTERRUPT);
+ if (retval == 0)
return retval;
- }
-
- *hcd_out = hcd;
- return 0;
- err3:
- hcd_buffer_destroy (hcd);
+ pxa27x_stop_hc(dev);
+ iounmap(hcd->regs);
err2:
- usb_put_hcd(hcd);
+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
err1:
- pxa27x_stop_hc(dev);
- release_mem_region(dev->resource[0].start,
- dev->resource[0].end
- - dev->resource[0].start + 1);
+ usb_put_hcd(hcd);
return retval;
}
@@ -280,27 +241,11 @@ int usb_hcd_pxa27x_probe (const struct hc_driver *driver,
*/
void usb_hcd_pxa27x_remove (struct usb_hcd *hcd, struct platform_device *dev)
{
- pr_debug ("remove: %s, state %x", hcd->self.bus_name, hcd->state);
-
- if (in_interrupt ())
- BUG ();
-
- hcd->state = USB_STATE_QUIESCING;
-
- pr_debug ("%s: roothub graceful disconnect", hcd->self.bus_name);
- usb_disconnect (&hcd->self.root_hub);
-
- hcd->driver->stop (hcd);
- hcd->state = USB_STATE_HALT;
-
- free_irq (hcd->irq, hcd);
- hcd_buffer_destroy (hcd);
-
- usb_deregister_bus (&hcd->self);
-
+ usb_remove_hcd(hcd);
pxa27x_stop_hc(dev);
- release_mem_region(dev->resource[0].start,
- dev->resource[0].end - dev->resource[0].start + 1);
+ iounmap(hcd->regs);
+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+ usb_put_hcd(hcd);
}
/*-------------------------------------------------------------------------*/
@@ -336,7 +281,7 @@ static const struct hc_driver ohci_pxa27x_hc_driver = {
* generic hardware linkage
*/
.irq = ohci_irq,
- .flags = HCD_USB11,
+ .flags = HCD_USB11 | HCD_MEMORY,
/*
* basic lifecycle operations
@@ -372,7 +317,6 @@ static const struct hc_driver ohci_pxa27x_hc_driver = {
static int ohci_hcd_pxa27x_drv_probe(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
- struct usb_hcd *hcd = NULL;
int ret;
pr_debug ("In ohci_hcd_pxa27x_drv_probe");
@@ -380,11 +324,7 @@ static int ohci_hcd_pxa27x_drv_probe(struct device *dev)
if (usb_disabled())
return -ENODEV;
- ret = usb_hcd_pxa27x_probe(&ohci_pxa27x_hc_driver, &hcd, pdev);
-
- if (ret == 0)
- dev_set_drvdata(dev, hcd);
-
+ ret = usb_hcd_pxa27x_probe(&ohci_pxa27x_hc_driver, pdev);
return ret;
}
@@ -394,7 +334,6 @@ static int ohci_hcd_pxa27x_drv_remove(struct device *dev)
struct usb_hcd *hcd = dev_get_drvdata(dev);
usb_hcd_pxa27x_remove(hcd, pdev);
- dev_set_drvdata(dev, NULL);
return 0;
}
diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c
index c86815586886f..c90114a772776 100644
--- a/drivers/usb/host/ohci-q.c
+++ b/drivers/usb/host/ohci-q.c
@@ -172,7 +172,7 @@ static int ed_schedule (struct ohci_hcd *ohci, struct ed *ed)
{
int branch;
- if (ohci_to_hcd(ohci)->state == USB_STATE_QUIESCING)
+ if (ohci_to_hcd(ohci)->state == HC_STATE_QUIESCING)
return -EAGAIN;
ed->state = ED_OPER;
@@ -547,7 +547,8 @@ td_fill (struct ohci_hcd *ohci, u32 info,
td->hwINFO = cpu_to_hc32 (ohci, info);
if (is_iso) {
td->hwCBP = cpu_to_hc32 (ohci, data & 0xFFFFF000);
- td->hwPSW [0] = cpu_to_hc16 (ohci, (data & 0x0FFF) | 0xE000);
+ *ohci_hwPSWp(ohci, td, 0) = cpu_to_hc16 (ohci,
+ (data & 0x0FFF) | 0xE000);
td->ed->last_iso = info & 0xffff;
} else {
td->hwCBP = cpu_to_hc32 (ohci, data);
@@ -662,7 +663,7 @@ static void td_submit_urb (
/* NOTE: mishandles transfers >8K, some >4K */
td_fill (ohci, info, data, data_len, urb, cnt++);
}
- info = is_out
+ info = (is_out || data_len == 0)
? TD_CC | TD_DP_IN | TD_T_DATA1
: TD_CC | TD_DP_OUT | TD_T_DATA1;
td_fill (ohci, info, data, 0, urb, cnt++);
@@ -719,10 +720,12 @@ static void td_done (struct ohci_hcd *ohci, struct urb *urb, struct td *td)
/* ISO ... drivers see per-TD length/status */
if (tdINFO & TD_ISO) {
- u16 tdPSW = hc16_to_cpu (ohci, td->hwPSW [0]);
+ u16 tdPSW = ohci_hwPSW (ohci, td, 0);
int dlen = 0;
- /* NOTE: assumes FC in tdINFO == 0 (and MAXPSW == 1) */
+ /* NOTE: assumes FC in tdINFO == 0, and that
+ * only the first of 0..MAXPSW psws is used.
+ */
cc = (tdPSW >> 12) & 0xF;
if (tdINFO & TD_CC) /* hc didn't touch? */
@@ -920,7 +923,7 @@ rescan_all:
/* only take off EDs that the HC isn't using, accounting for
* frame counter wraps and EDs with partially retired TDs
*/
- if (likely (regs && HCD_IS_RUNNING(ohci_to_hcd(ohci)->state))) {
+ if (likely (regs && HC_IS_RUNNING(ohci_to_hcd(ohci)->state))) {
if (tick_before (tick, ed->tick)) {
skip_ed:
last = &ed->ed_next;
@@ -1002,7 +1005,7 @@ rescan_this:
/* but if there's work queued, reschedule */
if (!list_empty (&ed->td_list)) {
- if (HCD_IS_RUNNING(ohci_to_hcd(ohci)->state))
+ if (HC_IS_RUNNING(ohci_to_hcd(ohci)->state))
ed_schedule (ohci, ed);
}
@@ -1011,8 +1014,8 @@ rescan_this:
}
/* maybe reenable control and bulk lists */
- if (HCD_IS_RUNNING(ohci_to_hcd(ohci)->state)
- && ohci_to_hcd(ohci)->state != USB_STATE_QUIESCING
+ if (HC_IS_RUNNING(ohci_to_hcd(ohci)->state)
+ && ohci_to_hcd(ohci)->state != HC_STATE_QUIESCING
&& !ohci->ed_rm_list) {
u32 command = 0, control = 0;
diff --git a/drivers/usb/host/ohci-sa1111.c b/drivers/usb/host/ohci-sa1111.c
index eb656a73d2eca..814d2be4ee7b9 100644
--- a/drivers/usb/host/ohci-sa1111.c
+++ b/drivers/usb/host/ohci-sa1111.c
@@ -105,34 +105,8 @@ static void dump_hci_status(struct usb_hcd *hcd, const char *label)
}
#endif
-static irqreturn_t usb_hcd_sa1111_hcim_irq (int irq, void *__hcd, struct pt_regs * r)
-{
- struct usb_hcd *hcd = __hcd;
-// unsigned long status = sa1111_readl(hcd->regs + SA1111_USB_STATUS);
-
- //dump_hci_status(hcd, "irq");
-
-#if 0
- /* may work better this way -- need to investigate further */
- if (status & USB_STATUS_NIRQHCIM) {
- //dbg ("not normal HC interrupt; ignoring");
- return;
- }
-#endif
-
- usb_hcd_irq(irq, hcd, r);
-
- /*
- * SA1111 seems to re-assert its interrupt immediately
- * after processing an interrupt. Always return IRQ_HANDLED.
- */
- return IRQ_HANDLED;
-}
-
/*-------------------------------------------------------------------------*/
-void usb_hcd_sa1111_remove (struct usb_hcd *, struct sa1111_dev *);
-
/* configure so an HC device and id are always provided */
/* always called with process context; sleeping is OK */
@@ -148,68 +122,35 @@ void usb_hcd_sa1111_remove (struct usb_hcd *, struct sa1111_dev *);
* Store this function in the HCD's struct pci_driver as probe().
*/
int usb_hcd_sa1111_probe (const struct hc_driver *driver,
- struct usb_hcd **hcd_out,
struct sa1111_dev *dev)
{
+ struct usb_hcd *hcd;
int retval;
- struct usb_hcd *hcd = 0;
- if (!request_mem_region(dev->res.start,
- dev->res.end - dev->res.start + 1, hcd_name)) {
- dbg("request_mem_region failed");
- return -EBUSY;
- }
-
- sa1111_start_hc(dev);
+ hcd = usb_create_hcd (driver, &dev->dev, "sa1111");
+ if (!hcd)
+ return -ENOMEM;
+ hcd->rsrc_start = dev->res.start;
+ hcd->rsrc_len = dev->res.end - dev->res.start + 1;
- hcd = usb_create_hcd (driver);
- if (hcd == NULL){
- dbg ("hcd_alloc failed");
- retval = -ENOMEM;
+ if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
+ dbg("request_mem_region failed");
+ retval = -EBUSY;
goto err1;
}
- ohci_hcd_init(hcd_to_ohci(hcd));
-
- hcd->irq = dev->irq[1];
hcd->regs = dev->mapbase;
- hcd->self.controller = &dev->dev;
-
- retval = hcd_buffer_create (hcd);
- if (retval != 0) {
- dbg ("pool alloc fail");
- goto err2;
- }
-
- retval = request_irq (hcd->irq, usb_hcd_sa1111_hcim_irq, SA_INTERRUPT,
- hcd->driver->description, hcd);
- if (retval != 0) {
- dbg("request_irq failed");
- retval = -EBUSY;
- goto err3;
- }
- info ("%s (SA-1111) at 0x%p, irq %d\n",
- hcd->driver->description, hcd->regs, hcd->irq);
-
- hcd->self.bus_name = "sa1111";
- usb_register_bus (&hcd->self);
+ sa1111_start_hc(dev);
+ ohci_hcd_init(hcd_to_ohci(hcd));
- if ((retval = driver->start (hcd)) < 0)
- {
- usb_hcd_sa1111_remove(hcd, dev);
+ retval = usb_add_hcd(hcd, dev->irq[1], SA_INTERRUPT);
+ if (retval == 0)
return retval;
- }
- *hcd_out = hcd;
- return 0;
-
- err3:
- hcd_buffer_destroy (hcd);
- err2:
- usb_put_hcd(hcd);
- err1:
sa1111_stop_hc(dev);
- release_mem_region(dev->res.start, dev->res.end - dev->res.start + 1);
+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+ err1:
+ usb_put_hcd(hcd);
return retval;
}
@@ -229,26 +170,10 @@ int usb_hcd_sa1111_probe (const struct hc_driver *driver,
*/
void usb_hcd_sa1111_remove (struct usb_hcd *hcd, struct sa1111_dev *dev)
{
- info ("remove: %s, state %x", hcd->self.bus_name, hcd->state);
-
- if (in_interrupt ())
- BUG ();
-
- hcd->state = USB_STATE_QUIESCING;
-
- dbg ("%s: roothub graceful disconnect", hcd->self.bus_name);
- usb_disconnect (&hcd->self.root_hub);
-
- hcd->driver->stop (hcd);
- hcd->state = USB_STATE_HALT;
-
- free_irq (hcd->irq, hcd);
- hcd_buffer_destroy (hcd);
-
- usb_deregister_bus (&hcd->self);
-
+ usb_remove_hcd(hcd);
sa1111_stop_hc(dev);
- release_mem_region(dev->res.start, dev->res.end - dev->res.start + 1);
+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+ usb_put_hcd(hcd);
}
/*-------------------------------------------------------------------------*/
@@ -281,7 +206,7 @@ static const struct hc_driver ohci_sa1111_hc_driver = {
* generic hardware linkage
*/
.irq = ohci_irq,
- .flags = HCD_USB11,
+ .flags = HCD_USB11 | HCD_MEMORY,
/*
* basic lifecycle operations
@@ -294,11 +219,6 @@ static const struct hc_driver ohci_sa1111_hc_driver = {
.stop = ohci_stop,
/*
- * memory lifecycle (except per-request)
- */
- .hcd_alloc = ohci_hcd_alloc,
-
- /*
* managing i/o requests and associated device resources
*/
.urb_enqueue = ohci_urb_enqueue,
@@ -325,17 +245,12 @@ static const struct hc_driver ohci_sa1111_hc_driver = {
static int ohci_hcd_sa1111_drv_probe(struct sa1111_dev *dev)
{
- struct usb_hcd *hcd = NULL;
int ret;
if (usb_disabled())
return -ENODEV;
- ret = usb_hcd_sa1111_probe(&ohci_sa1111_hc_driver, &hcd, dev);
-
- if (ret == 0)
- sa1111_set_drvdata(dev, hcd);
-
+ ret = usb_hcd_sa1111_probe(&ohci_sa1111_hc_driver, dev);
return ret;
}
@@ -344,9 +259,6 @@ static int ohci_hcd_sa1111_drv_remove(struct sa1111_dev *dev)
struct usb_hcd *hcd = sa1111_get_drvdata(dev);
usb_hcd_sa1111_remove(hcd, dev);
-
- sa1111_set_drvdata(dev, NULL);
-
return 0;
}
diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h
index 437e8b03ed93c..2ba6e2b0210c9 100644
--- a/drivers/usb/host/ohci.h
+++ b/drivers/usb/host/ohci.h
@@ -111,8 +111,10 @@ struct td {
__hc32 hwNextTD; /* Next TD Pointer */
__hc32 hwBE; /* Memory Buffer End Pointer */
- /* PSW is only for ISO */
-#define MAXPSW 1 /* hardware allows 8 */
+ /* PSW is only for ISO. Only 1 PSW entry is used, but on
+ * big-endian PPC hardware that's the second entry.
+ */
+#define MAXPSW 2
__hc16 hwPSW [MAXPSW];
/* rest are purely for the driver's use */
@@ -183,7 +185,7 @@ struct ohci_hcca {
/*
* OHCI defines u16 frame_no, followed by u16 zero pad.
* Since some processors can't do 16 bit bus accesses,
- * portable access must be a 32 bit byteswapped access.
+ * portable access must be a 32 bits wide.
*/
__hc32 frame_no; /* current frame number */
__hc32 done_head; /* info returned for an interrupt */
@@ -191,8 +193,6 @@ struct ohci_hcca {
u8 what [4]; /* spec only identifies 252 bytes :) */
} __attribute__ ((aligned(256)));
-#define ohci_frame_no(ohci) ((u16)hc32_to_cpup(ohci,&(ohci)->hcca->frame_no))
-
/*
* This is the structure of the OHCI controller's memory mapped I/O region.
* You must use readl() and writel() (in <asm/io.h>) to access these fields!!
@@ -554,19 +554,61 @@ static inline u32 hc32_to_cpup (const struct ohci_hcd *ohci, const __hc32 *x)
/*-------------------------------------------------------------------------*/
+/* HCCA frame number is 16 bits, but is accessed as 32 bits since not all
+ * hardware handles 16 bit reads. That creates a different confusion on
+ * some big-endian SOC implementations. Same thing happens with PSW access.
+ */
+
+#ifdef CONFIG_STB03xxx
+#define OHCI_BE_FRAME_NO_SHIFT 16
+#else
+#define OHCI_BE_FRAME_NO_SHIFT 0
+#endif
+
+static inline u16 ohci_frame_no(const struct ohci_hcd *ohci)
+{
+ u32 tmp;
+ if (big_endian(ohci)) {
+ tmp = be32_to_cpup((__force __be32 *)&ohci->hcca->frame_no);
+ tmp >>= OHCI_BE_FRAME_NO_SHIFT;
+ } else
+ tmp = le32_to_cpup((__force __le32 *)&ohci->hcca->frame_no);
+
+ return (u16)tmp;
+}
+
+static inline __hc16 *ohci_hwPSWp(const struct ohci_hcd *ohci,
+ const struct td *td, int index)
+{
+ return (__hc16 *)(big_endian(ohci) ?
+ &td->hwPSW[index ^ 1] : &td->hwPSW[index]);
+}
+
+static inline u16 ohci_hwPSW(const struct ohci_hcd *ohci,
+ const struct td *td, int index)
+{
+ return hc16_to_cpup(ohci, ohci_hwPSWp(ohci, td, index));
+}
+
+/*-------------------------------------------------------------------------*/
+
static inline void disable (struct ohci_hcd *ohci)
{
- ohci_to_hcd(ohci)->state = USB_STATE_HALT;
+ ohci_to_hcd(ohci)->state = HC_STATE_HALT;
}
#define FI 0x2edf /* 12000 bits per frame (-1) */
#define FSMP(fi) (0x7fff & ((6 * ((fi) - 210)) / 7))
+#define FIT (1 << 31)
#define LSTHRESH 0x628 /* lowspeed bit threshold */
-static inline void periodic_reinit (struct ohci_hcd *ohci)
+static void periodic_reinit (struct ohci_hcd *ohci)
{
- u32 fi = ohci->fminterval & 0x0ffff;
+ u32 fi = ohci->fminterval & 0x03fff;
+ u32 fit = ohci_readl(ohci, &ohci->regs->fminterval) & FIT;
+ ohci_writel (ohci, (fit ^ FIT) | ohci->fminterval,
+ &ohci->regs->fminterval);
ohci_writel (ohci, ((9 * fi) / 10) & 0x3fff,
&ohci->regs->periodicstart);
}
diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
index c932c53ac01db..d309e292198ed 100644
--- a/drivers/usb/host/sl811-hcd.c
+++ b/drivers/usb/host/sl811-hcd.c
@@ -90,8 +90,6 @@ static const char hcd_name[] = "sl811-hcd";
/*-------------------------------------------------------------------------*/
-static irqreturn_t sl811h_irq(int irq, void *_hcd, struct pt_regs *regs);
-
static void port_power(struct sl811 *sl811, int is_on)
{
struct usb_hcd *hcd = sl811_to_hcd(sl811);
@@ -103,12 +101,12 @@ static void port_power(struct sl811 *sl811, int is_on)
sl811->port1 = (1 << USB_PORT_FEAT_POWER);
sl811->irq_enable = SL11H_INTMASK_INSRMV;
- hcd->self.controller->power.power_state = PM_SUSPEND_ON;
+ hcd->self.controller->power.power_state = PMSG_ON;
} else {
sl811->port1 = 0;
sl811->irq_enable = 0;
- hcd->state = USB_STATE_HALT;
- hcd->self.controller->power.power_state = PM_SUSPEND_DISK;
+ hcd->state = HC_STATE_HALT;
+ hcd->self.controller->power.power_state = PMSG_SUSPEND;
}
sl811->ctrl1 = 0;
sl811_write(sl811, SL11H_IRQ_ENABLE, 0);
@@ -645,9 +643,8 @@ static inline u8 checkdone(struct sl811 *sl811)
return irqstat;
}
-static irqreturn_t sl811h_irq(int irq, void *_hcd, struct pt_regs *regs)
+static irqreturn_t sl811h_irq(struct usb_hcd *hcd, struct pt_regs *regs)
{
- struct usb_hcd *hcd = _hcd;
struct sl811 *sl811 = hcd_to_sl811(hcd);
u8 irqstat;
irqreturn_t ret = IRQ_NONE;
@@ -666,7 +663,7 @@ retry:
/* this may no longer be necessary ... */
if (irqstat == 0 && ret == IRQ_NONE) {
irqstat = checkdone(sl811);
- if (irqstat && irq != ~0)
+ if (irqstat /* && irq != ~0 */ )
sl811->stat_lost++;
}
#endif
@@ -760,7 +757,6 @@ retry:
if (sl811->port1 & (1 << USB_PORT_FEAT_ENABLE))
start_transfer(sl811);
ret = IRQ_HANDLED;
- hcd->saw_irq = 1;
if (retries--)
goto retry;
}
@@ -838,7 +834,7 @@ static int sl811h_urb_enqueue(
/* don't submit to a dead or disabled port */
if (!(sl811->port1 & (1 << USB_PORT_FEAT_ENABLE))
- || !HCD_IS_RUNNING(hcd->state)) {
+ || !HC_IS_RUNNING(hcd->state)) {
retval = -ENODEV;
goto fail;
}
@@ -1073,7 +1069,7 @@ sl811h_hub_status_data(struct usb_hcd *hcd, char *buf)
*/
local_irq_save(flags);
if (!timer_pending(&sl811->timer)) {
- if (sl811h_irq(~0, sl811, NULL) != IRQ_NONE)
+ if (sl811h_irq( /* ~0, */ hcd, NULL) != IRQ_NONE)
sl811->stat_lost++;
}
local_irq_restore(flags);
@@ -1566,12 +1562,12 @@ sl811h_start(struct usb_hcd *hcd)
return -ENOMEM;
udev->speed = USB_SPEED_FULL;
- hcd->state = USB_STATE_RUNNING;
+ hcd->state = HC_STATE_RUNNING;
if (sl811->board)
hcd->can_wakeup = sl811->board->can_wakeup;
- if (hcd_register_root(udev, hcd) != 0) {
+ if (usb_hcd_register_root_hub(udev, hcd) != 0) {
usb_put_dev(udev);
sl811h_stop(hcd);
return -ENODEV;
@@ -1592,7 +1588,12 @@ static struct hc_driver sl811h_hc_driver = {
/*
* generic hardware linkage
*/
- .flags = HCD_USB11,
+ .irq = sl811h_irq,
+ .flags = HCD_USB11 | HCD_MEMORY,
+
+ /* Basic lifecycle operations */
+ .start = sl811h_start,
+ .stop = sl811h_stop,
/*
* managing i/o requests and associated device resources
@@ -1620,23 +1621,15 @@ static struct hc_driver sl811h_hc_driver = {
static int __init_or_module
sl811h_remove(struct device *dev)
{
- struct sl811 *sl811 = dev_get_drvdata(dev);
- struct usb_hcd *hcd = sl811_to_hcd(sl811);
+ struct usb_hcd *hcd = dev_get_drvdata(dev);
+ struct sl811 *sl811 = hcd_to_sl811(hcd);
struct platform_device *pdev;
struct resource *res;
pdev = container_of(dev, struct platform_device, dev);
- if (HCD_IS_RUNNING(hcd->state))
- hcd->state = USB_STATE_QUIESCING;
-
- usb_disconnect(&hcd->self.root_hub);
remove_debug_file(sl811);
- sl811h_stop(hcd);
-
- usb_deregister_bus(&hcd->self);
-
- free_irq(hcd->irq, hcd);
+ usb_remove_hcd(hcd);
iounmap(sl811->data_reg);
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
@@ -1707,18 +1700,13 @@ sl811h_probe(struct device *dev)
}
/* allocate and initialize hcd */
- hcd = usb_create_hcd(&sl811h_hc_driver);
+ hcd = usb_create_hcd(&sl811h_hc_driver, dev, dev->bus_id);
if (!hcd) {
- retval = 0;
+ retval = -ENOMEM;
goto err5;
}
+ hcd->rsrc_start = addr->start;
sl811 = hcd_to_sl811(hcd);
- dev_set_drvdata(dev, sl811);
-
- hcd->self.controller = dev;
- hcd->self.bus_name = dev->bus_id;
- hcd->irq = irq;
- hcd->regs = addr_reg;
spin_lock_init(&sl811->lock);
INIT_LIST_HEAD(&sl811->async);
@@ -1754,28 +1742,13 @@ sl811h_probe(struct device *dev)
/* Cypress docs say the IRQ is IRQT_HIGH ... */
set_irq_type(irq, IRQT_RISING);
#endif
- retval = request_irq(irq, sl811h_irq, SA_INTERRUPT,
- hcd->driver->description, hcd);
+ retval = usb_add_hcd(hcd, irq, SA_INTERRUPT);
if (retval != 0)
goto err6;
- INFO("%s, irq %d\n", hcd->product_desc, irq);
-
- retval = usb_register_bus(&hcd->self);
- if (retval < 0)
- goto err7;
-
- retval = sl811h_start(hcd);
- if (retval < 0)
- goto err8;
-
create_debug_file(sl811);
- return 0;
+ return retval;
- err8:
- usb_deregister_bus(&hcd->self);
- err7:
- free_irq(hcd->irq, hcd);
err6:
usb_put_hcd(hcd);
err5:
@@ -1799,16 +1772,17 @@ sl811h_probe(struct device *dev)
*/
static int
-sl811h_suspend(struct device *dev, u32 state, u32 phase)
+sl811h_suspend(struct device *dev, pm_message_t state, u32 phase)
{
- struct sl811 *sl811 = dev_get_drvdata(dev);
+ struct usb_hcd *hcd = dev_get_drvdata(dev);
+ struct sl811 *sl811 = hcd_to_sl811(hcd);
int retval = 0;
if (phase != SUSPEND_POWER_DOWN)
return retval;
if (state <= PM_SUSPEND_MEM)
- retval = sl811h_hub_suspend(sl811_to_hcd(sl811));
+ retval = sl811h_hub_suspend(hcd);
else
port_power(sl811, 0);
if (retval == 0)
@@ -1819,7 +1793,8 @@ sl811h_suspend(struct device *dev, u32 state, u32 phase)
static int
sl811h_resume(struct device *dev, u32 phase)
{
- struct sl811 *sl811 = dev_get_drvdata(dev);
+ struct usb_hcd *hcd = dev_get_drvdata(dev);
+ struct sl811 *sl811 = hcd_to_sl811(hcd);
if (phase != RESUME_POWER_ON)
return 0;
@@ -1828,14 +1803,14 @@ sl811h_resume(struct device *dev, u32 phase)
* let's assume it'd only be powered to enable remote wakeup.
*/
if (dev->power.power_state > PM_SUSPEND_MEM
- || !sl811_to_hcd(sl811)->can_wakeup) {
+ || !hcd->can_wakeup) {
sl811->port1 = 0;
port_power(sl811, 1);
return 0;
}
- dev->power.power_state = PM_SUSPEND_ON;
- return sl811h_hub_resume(sl811_to_hcd(sl811));
+ dev->power.power_state = PMSG_ON;
+ return sl811h_hub_resume(hcd);
}
#else
diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c
index 397ec79cc1e41..24c73c5a34354 100644
--- a/drivers/usb/host/uhci-debug.c
+++ b/drivers/usb/host/uhci-debug.c
@@ -17,6 +17,8 @@
#include "uhci-hcd.h"
+static struct dentry *uhci_debugfs_root = NULL;
+
/* Handle REALLY large printk's so we don't overflow buffers */
static inline void lprintk(char *buf)
{
@@ -404,7 +406,7 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
struct uhci_td *td;
struct list_head *tmp, *head;
- spin_lock_irqsave(&uhci->schedule_lock, flags);
+ spin_lock_irqsave(&uhci->lock, flags);
out += sprintf(out, "HC status\n");
out += uhci_show_status(uhci, out, len - (out - buf));
@@ -490,15 +492,13 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
if (debug > 2)
out += uhci_show_lists(uhci, out, len - (out - buf));
- spin_unlock_irqrestore(&uhci->schedule_lock, flags);
+ spin_unlock_irqrestore(&uhci->lock, flags);
return out - buf;
}
#define MAX_OUTPUT (64 * 1024)
-static struct dentry *uhci_debugfs_root = NULL;
-
struct uhci_debug {
int size;
char *data;
@@ -579,4 +579,9 @@ static struct file_operations uhci_debug_operations = {
.read = uhci_debug_read,
.release = uhci_debug_release,
};
+
+#else /* CONFIG_DEBUG_FS */
+
+#define uhci_debug_operations (* (struct file_operations *) NULL)
+
#endif
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index 1e82aa7dc01ed..324a1a9bbdb2d 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -87,19 +87,9 @@ MODULE_PARM_DESC(debug, "Debug level");
static char *errbuf;
#define ERRBUF_LEN (32 * 1024)
-#include "uhci-hub.c"
-#include "uhci-debug.c"
-
static kmem_cache_t *uhci_up_cachep; /* urb_priv */
-static unsigned int uhci_get_current_frame_number(struct uhci_hcd *uhci);
-static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb);
-static void uhci_unlink_generic(struct uhci_hcd *uhci, struct urb *urb);
-static void uhci_remove_pending_urbps(struct uhci_hcd *uhci);
-static void uhci_finish_completion(struct usb_hcd *hcd, struct pt_regs *regs);
-static void uhci_free_pending_qhs(struct uhci_hcd *uhci);
-static void uhci_free_pending_tds(struct uhci_hcd *uhci);
-
+static void uhci_get_current_frame_number(struct uhci_hcd *uhci);
static void hc_state_transitions(struct uhci_hcd *uhci);
/* If a transfer is still active after this much time, turn off FSBR */
@@ -111,1424 +101,9 @@ static void hc_state_transitions(struct uhci_hcd *uhci);
/* to make sure it doesn't hog all of the bandwidth */
#define DEPTH_INTERVAL 5
-/*
- * Technically, updating td->status here is a race, but it's not really a
- * problem. The worst that can happen is that we set the IOC bit again
- * generating a spurious interrupt. We could fix this by creating another
- * QH and leaving the IOC bit always set, but then we would have to play
- * games with the FSBR code to make sure we get the correct order in all
- * the cases. I don't think it's worth the effort
- */
-static inline void uhci_set_next_interrupt(struct uhci_hcd *uhci)
-{
- uhci->term_td->status |= cpu_to_le32(TD_CTRL_IOC);
-}
-
-static inline void uhci_clear_next_interrupt(struct uhci_hcd *uhci)
-{
- uhci->term_td->status &= ~cpu_to_le32(TD_CTRL_IOC);
-}
-
-static inline void uhci_moveto_complete(struct uhci_hcd *uhci,
- struct urb_priv *urbp)
-{
- list_move_tail(&urbp->urb_list, &uhci->complete_list);
-}
-
-static struct uhci_td *uhci_alloc_td(struct uhci_hcd *uhci, struct usb_device *dev)
-{
- dma_addr_t dma_handle;
- struct uhci_td *td;
-
- td = dma_pool_alloc(uhci->td_pool, GFP_ATOMIC, &dma_handle);
- if (!td)
- return NULL;
-
- td->dma_handle = dma_handle;
-
- td->link = UHCI_PTR_TERM;
- td->buffer = 0;
-
- td->frame = -1;
- td->dev = dev;
-
- INIT_LIST_HEAD(&td->list);
- INIT_LIST_HEAD(&td->remove_list);
- INIT_LIST_HEAD(&td->fl_list);
-
- usb_get_dev(dev);
-
- return td;
-}
-
-static inline void uhci_fill_td(struct uhci_td *td, u32 status,
- u32 token, u32 buffer)
-{
- td->status = cpu_to_le32(status);
- td->token = cpu_to_le32(token);
- td->buffer = cpu_to_le32(buffer);
-}
-
-/*
- * We insert Isochronous URB's 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)
-{
- framenum &= (UHCI_NUMFRAMES - 1);
-
- td->frame = framenum;
-
- /* Is there a TD already mapped there? */
- if (uhci->fl->frame_cpu[framenum]) {
- struct uhci_td *ftd, *ltd;
-
- ftd = uhci->fl->frame_cpu[framenum];
- ltd = list_entry(ftd->fl_list.prev, struct uhci_td, fl_list);
-
- list_add_tail(&td->fl_list, &ftd->fl_list);
-
- td->link = ltd->link;
- wmb();
- ltd->link = cpu_to_le32(td->dma_handle);
- } else {
- td->link = uhci->fl->frame[framenum];
- wmb();
- uhci->fl->frame[framenum] = cpu_to_le32(td->dma_handle);
- uhci->fl->frame_cpu[framenum] = td;
- }
-}
-
-static void uhci_remove_td(struct uhci_hcd *uhci, struct uhci_td *td)
-{
- /* If it's not inserted, don't remove it */
- if (td->frame == -1 && list_empty(&td->fl_list))
- return;
-
- if (td->frame != -1 && uhci->fl->frame_cpu[td->frame] == td) {
- if (list_empty(&td->fl_list)) {
- uhci->fl->frame[td->frame] = td->link;
- uhci->fl->frame_cpu[td->frame] = NULL;
- } else {
- struct uhci_td *ntd;
-
- ntd = list_entry(td->fl_list.next, struct uhci_td, fl_list);
- uhci->fl->frame[td->frame] = cpu_to_le32(ntd->dma_handle);
- uhci->fl->frame_cpu[td->frame] = ntd;
- }
- } else {
- struct uhci_td *ptd;
-
- ptd = list_entry(td->fl_list.prev, struct uhci_td, fl_list);
- ptd->link = td->link;
- }
-
- wmb();
- td->link = UHCI_PTR_TERM;
-
- list_del_init(&td->fl_list);
- td->frame = -1;
-}
-
-/*
- * Inserts a td list into qh.
- */
-static void uhci_insert_tds_in_qh(struct uhci_qh *qh, struct urb *urb, __le32 breadth)
-{
- struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
- struct uhci_td *td;
- __le32 *plink;
-
- /* Ordering isn't important here yet since the QH hasn't been */
- /* inserted into the schedule yet */
- plink = &qh->element;
- list_for_each_entry(td, &urbp->td_list, list) {
- *plink = cpu_to_le32(td->dma_handle) | breadth;
- plink = &td->link;
- }
- *plink = UHCI_PTR_TERM;
-}
-
-static void uhci_free_td(struct uhci_hcd *uhci, struct uhci_td *td)
-{
- if (!list_empty(&td->list))
- dev_warn(uhci_dev(uhci), "td %p still in list!\n", td);
- if (!list_empty(&td->remove_list))
- dev_warn(uhci_dev(uhci), "td %p still in remove_list!\n", td);
- if (!list_empty(&td->fl_list))
- dev_warn(uhci_dev(uhci), "td %p still in fl_list!\n", td);
-
- if (td->dev)
- usb_put_dev(td->dev);
-
- dma_pool_free(uhci->td_pool, td, td->dma_handle);
-}
-
-static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci, struct usb_device *dev)
-{
- dma_addr_t dma_handle;
- struct uhci_qh *qh;
-
- qh = dma_pool_alloc(uhci->qh_pool, GFP_ATOMIC, &dma_handle);
- if (!qh)
- return NULL;
-
- qh->dma_handle = dma_handle;
-
- qh->element = UHCI_PTR_TERM;
- qh->link = UHCI_PTR_TERM;
-
- qh->dev = dev;
- qh->urbp = NULL;
-
- INIT_LIST_HEAD(&qh->list);
- INIT_LIST_HEAD(&qh->remove_list);
-
- usb_get_dev(dev);
-
- return qh;
-}
-
-static void uhci_free_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
-{
- if (!list_empty(&qh->list))
- dev_warn(uhci_dev(uhci), "qh %p list not empty!\n", qh);
- if (!list_empty(&qh->remove_list))
- dev_warn(uhci_dev(uhci), "qh %p still in remove_list!\n", qh);
-
- if (qh->dev)
- usb_put_dev(qh->dev);
-
- dma_pool_free(uhci->qh_pool, qh, qh->dma_handle);
-}
-
-/*
- * Append this urb's qh after the last qh in skelqh->list
- *
- * Note that urb_priv.queue_list doesn't have a separate queue head;
- * it's a ring with every element "live".
- */
-static void uhci_insert_qh(struct uhci_hcd *uhci, struct uhci_qh *skelqh, struct urb *urb)
-{
- struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
- struct urb_priv *turbp;
- struct uhci_qh *lqh;
-
- /* Grab the last QH */
- lqh = list_entry(skelqh->list.prev, struct uhci_qh, list);
-
- /* Point to the next skelqh */
- urbp->qh->link = lqh->link;
- wmb(); /* Ordering is important */
-
- /*
- * Patch QHs for previous endpoint's queued URBs? HC goes
- * here next, not to the next skelqh it now points to.
- *
- * lqh --> td ... --> qh ... --> td --> qh ... --> td
- * | | |
- * v v v
- * +<----------------+-----------------+
- * v
- * newqh --> td ... --> td
- * |
- * v
- * ...
- *
- * The HC could see (and use!) any of these as we write them.
- */
- lqh->link = cpu_to_le32(urbp->qh->dma_handle) | UHCI_PTR_QH;
- if (lqh->urbp) {
- list_for_each_entry(turbp, &lqh->urbp->queue_list, queue_list)
- turbp->qh->link = lqh->link;
- }
-
- list_add_tail(&urbp->qh->list, &skelqh->list);
-}
-
-/*
- * Start removal of QH from schedule; it finishes next frame.
- * TDs should be unlinked before this is called.
- */
-static void uhci_remove_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
-{
- struct uhci_qh *pqh;
- __le32 newlink;
- unsigned int age;
-
- if (!qh)
- return;
-
- /*
- * Only go through the hoops if it's actually linked in
- */
- if (!list_empty(&qh->list)) {
-
- /* If our queue is nonempty, make the next URB the head */
- if (!list_empty(&qh->urbp->queue_list)) {
- struct urb_priv *nurbp;
-
- nurbp = list_entry(qh->urbp->queue_list.next,
- struct urb_priv, queue_list);
- nurbp->queued = 0;
- list_add(&nurbp->qh->list, &qh->list);
- newlink = cpu_to_le32(nurbp->qh->dma_handle) | UHCI_PTR_QH;
- } else
- newlink = qh->link;
-
- /* Fix up the previous QH's queue to link to either
- * the new head of this queue or the start of the
- * next endpoint's queue. */
- pqh = list_entry(qh->list.prev, struct uhci_qh, list);
- pqh->link = newlink;
- if (pqh->urbp) {
- struct urb_priv *turbp;
-
- list_for_each_entry(turbp, &pqh->urbp->queue_list,
- queue_list)
- turbp->qh->link = newlink;
- }
- wmb();
-
- /* Leave qh->link in case the HC is on the QH now, it will */
- /* continue the rest of the schedule */
- qh->element = UHCI_PTR_TERM;
-
- list_del_init(&qh->list);
- }
-
- list_del_init(&qh->urbp->queue_list);
- qh->urbp = NULL;
-
- age = uhci_get_current_frame_number(uhci);
- if (age != uhci->qh_remove_age) {
- uhci_free_pending_qhs(uhci);
- uhci->qh_remove_age = age;
- }
-
- /* Check to see if the remove list is empty. Set the IOC bit */
- /* to force an interrupt so we can remove the QH */
- if (list_empty(&uhci->qh_remove_list))
- uhci_set_next_interrupt(uhci);
-
- list_add(&qh->remove_list, &uhci->qh_remove_list);
-}
-
-static int uhci_fixup_toggle(struct urb *urb, unsigned int toggle)
-{
- struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
- struct uhci_td *td;
-
- list_for_each_entry(td, &urbp->td_list, list) {
- if (toggle)
- td->token |= cpu_to_le32(TD_TOKEN_TOGGLE);
- else
- td->token &= ~cpu_to_le32(TD_TOKEN_TOGGLE);
-
- toggle ^= 1;
- }
-
- return toggle;
-}
-
-/* This function will append one URB's QH to another URB's QH. This is for */
-/* queuing interrupt, control or bulk transfers */
-static void uhci_append_queued_urb(struct uhci_hcd *uhci, struct urb *eurb, struct urb *urb)
-{
- struct urb_priv *eurbp, *urbp, *furbp, *lurbp;
- struct uhci_td *lltd;
-
- eurbp = eurb->hcpriv;
- urbp = urb->hcpriv;
-
- /* Find the first URB in the queue */
- furbp = eurbp;
- if (eurbp->queued) {
- list_for_each_entry(furbp, &eurbp->queue_list, queue_list)
- if (!furbp->queued)
- break;
- }
-
- lurbp = list_entry(furbp->queue_list.prev, struct urb_priv, queue_list);
-
- lltd = list_entry(lurbp->td_list.prev, struct uhci_td, list);
-
- /* Control transfers always start with toggle 0 */
- if (!usb_pipecontrol(urb->pipe))
- usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
- usb_pipeout(urb->pipe),
- uhci_fixup_toggle(urb,
- uhci_toggle(td_token(lltd)) ^ 1));
-
- /* All qh's in the queue need to link to the next queue */
- urbp->qh->link = eurbp->qh->link;
-
- wmb(); /* Make sure we flush everything */
-
- lltd->link = cpu_to_le32(urbp->qh->dma_handle) | UHCI_PTR_QH;
-
- list_add_tail(&urbp->queue_list, &furbp->queue_list);
-
- urbp->queued = 1;
-}
-
-static void uhci_delete_queued_urb(struct uhci_hcd *uhci, struct urb *urb)
-{
- struct urb_priv *urbp, *nurbp, *purbp, *turbp;
- struct uhci_td *pltd;
- unsigned int toggle;
-
- urbp = urb->hcpriv;
-
- if (list_empty(&urbp->queue_list))
- return;
-
- nurbp = list_entry(urbp->queue_list.next, struct urb_priv, queue_list);
-
- /*
- * Fix up the toggle for the following URBs in the queue.
- * Only needed for bulk and interrupt: control and isochronous
- * endpoints don't propagate toggles between messages.
- */
- if (usb_pipebulk(urb->pipe) || usb_pipeint(urb->pipe)) {
- if (!urbp->queued)
- /* We just set the toggle in uhci_unlink_generic */
- toggle = usb_gettoggle(urb->dev,
- usb_pipeendpoint(urb->pipe),
- usb_pipeout(urb->pipe));
- else {
- /* If we're in the middle of the queue, grab the */
- /* toggle from the TD previous to us */
- purbp = list_entry(urbp->queue_list.prev,
- struct urb_priv, queue_list);
- pltd = list_entry(purbp->td_list.prev,
- struct uhci_td, list);
- toggle = uhci_toggle(td_token(pltd)) ^ 1;
- }
-
- list_for_each_entry(turbp, &urbp->queue_list, queue_list) {
- if (!turbp->queued)
- break;
- toggle = uhci_fixup_toggle(turbp->urb, toggle);
- }
-
- usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
- usb_pipeout(urb->pipe), toggle);
- }
-
- if (urbp->queued) {
- /* We're somewhere in the middle (or end). The case where
- * we're at the head is handled in uhci_remove_qh(). */
- purbp = list_entry(urbp->queue_list.prev, struct urb_priv,
- queue_list);
-
- pltd = list_entry(purbp->td_list.prev, struct uhci_td, list);
- if (nurbp->queued)
- pltd->link = cpu_to_le32(nurbp->qh->dma_handle) | UHCI_PTR_QH;
- else
- /* The next URB happens to be the beginning, so */
- /* we're the last, end the chain */
- pltd->link = UHCI_PTR_TERM;
- }
-
- /* urbp->queue_list is handled in uhci_remove_qh() */
-}
-
-static struct urb_priv *uhci_alloc_urb_priv(struct uhci_hcd *uhci, struct urb *urb)
-{
- struct urb_priv *urbp;
-
- urbp = kmem_cache_alloc(uhci_up_cachep, SLAB_ATOMIC);
- if (!urbp)
- return NULL;
-
- memset((void *)urbp, 0, sizeof(*urbp));
-
- urbp->inserttime = jiffies;
- urbp->fsbrtime = jiffies;
- urbp->urb = urb;
-
- INIT_LIST_HEAD(&urbp->td_list);
- INIT_LIST_HEAD(&urbp->queue_list);
- INIT_LIST_HEAD(&urbp->urb_list);
-
- list_add_tail(&urbp->urb_list, &uhci->urb_list);
-
- urb->hcpriv = urbp;
-
- return urbp;
-}
-
-static void uhci_add_td_to_urb(struct urb *urb, struct uhci_td *td)
-{
- struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
-
- td->urb = urb;
-
- list_add_tail(&td->list, &urbp->td_list);
-}
-
-static void uhci_remove_td_from_urb(struct uhci_td *td)
-{
- if (list_empty(&td->list))
- return;
-
- list_del_init(&td->list);
-
- td->urb = NULL;
-}
-
-static void uhci_destroy_urb_priv(struct uhci_hcd *uhci, struct urb *urb)
-{
- struct uhci_td *td, *tmp;
- struct urb_priv *urbp;
- unsigned int age;
-
- urbp = (struct urb_priv *)urb->hcpriv;
- if (!urbp)
- return;
-
- if (!list_empty(&urbp->urb_list))
- dev_warn(uhci_dev(uhci), "urb %p still on uhci->urb_list "
- "or uhci->remove_list!\n", urb);
-
- age = uhci_get_current_frame_number(uhci);
- if (age != uhci->td_remove_age) {
- uhci_free_pending_tds(uhci);
- uhci->td_remove_age = age;
- }
-
- /* Check to see if the remove list is empty. Set the IOC bit */
- /* to force an interrupt so we can remove the TD's*/
- if (list_empty(&uhci->td_remove_list))
- uhci_set_next_interrupt(uhci);
-
- list_for_each_entry_safe(td, tmp, &urbp->td_list, list) {
- uhci_remove_td_from_urb(td);
- uhci_remove_td(uhci, td);
- list_add(&td->remove_list, &uhci->td_remove_list);
- }
-
- urb->hcpriv = NULL;
- kmem_cache_free(uhci_up_cachep, urbp);
-}
-
-static void uhci_inc_fsbr(struct uhci_hcd *uhci, struct urb *urb)
-{
- struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
-
- if ((!(urb->transfer_flags & URB_NO_FSBR)) && !urbp->fsbr) {
- urbp->fsbr = 1;
- if (!uhci->fsbr++ && !uhci->fsbrtimeout)
- uhci->skel_term_qh->link = cpu_to_le32(uhci->skel_fs_control_qh->dma_handle) | UHCI_PTR_QH;
- }
-}
-
-static void uhci_dec_fsbr(struct uhci_hcd *uhci, struct urb *urb)
-{
- struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
-
- if ((!(urb->transfer_flags & URB_NO_FSBR)) && urbp->fsbr) {
- urbp->fsbr = 0;
- if (!--uhci->fsbr)
- uhci->fsbrtimeout = jiffies + FSBR_DELAY;
- }
-}
-
-/*
- * Map status to standard result codes
- *
- * <status> is (td_status(td) & 0xF60000), a.k.a.
- * uhci_status_bits(td_status(td)).
- * Note: <status> does not include the TD_CTRL_NAK bit.
- * <dir_out> is True for output TDs and False for input TDs.
- */
-static int uhci_map_status(int status, int dir_out)
-{
- if (!status)
- return 0;
- if (status & TD_CTRL_BITSTUFF) /* Bitstuff error */
- return -EPROTO;
- if (status & TD_CTRL_CRCTIMEO) { /* CRC/Timeout */
- if (dir_out)
- return -EPROTO;
- else
- return -EILSEQ;
- }
- if (status & TD_CTRL_BABBLE) /* Babble */
- return -EOVERFLOW;
- if (status & TD_CTRL_DBUFERR) /* Buffer error */
- return -ENOSR;
- if (status & TD_CTRL_STALLED) /* Stalled */
- return -EPIPE;
- WARN_ON(status & TD_CTRL_ACTIVE); /* Active */
- return 0;
-}
-
-/*
- * Control transfers
- */
-static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct urb *eurb)
-{
- struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
- struct uhci_td *td;
- struct uhci_qh *qh, *skelqh;
- unsigned long destination, status;
- int maxsze = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe));
- int len = urb->transfer_buffer_length;
- dma_addr_t data = urb->transfer_dma;
-
- /* The "pipe" thing contains the destination in bits 8--18 */
- destination = (urb->pipe & PIPE_DEVEP_MASK) | USB_PID_SETUP;
-
- /* 3 errors */
- status = TD_CTRL_ACTIVE | uhci_maxerr(3);
- if (urb->dev->speed == USB_SPEED_LOW)
- status |= TD_CTRL_LS;
-
- /*
- * Build the TD for the control request setup packet
- */
- td = uhci_alloc_td(uhci, urb->dev);
- if (!td)
- return -ENOMEM;
-
- uhci_add_td_to_urb(urb, td);
- uhci_fill_td(td, status, destination | uhci_explen(7),
- urb->setup_dma);
-
- /*
- * If direction is "send", change the packet ID from SETUP (0x2D)
- * to OUT (0xE1). Else change it from SETUP to IN (0x69) and
- * set Short Packet Detect (SPD) for all data packets.
- */
- if (usb_pipeout(urb->pipe))
- destination ^= (USB_PID_SETUP ^ USB_PID_OUT);
- else {
- destination ^= (USB_PID_SETUP ^ USB_PID_IN);
- status |= TD_CTRL_SPD;
- }
-
- /*
- * Build the DATA TD's
- */
- while (len > 0) {
- int pktsze = len;
-
- if (pktsze > maxsze)
- pktsze = maxsze;
-
- td = uhci_alloc_td(uhci, urb->dev);
- if (!td)
- return -ENOMEM;
-
- /* Alternate Data0/1 (start with Data1) */
- destination ^= TD_TOKEN_TOGGLE;
-
- uhci_add_td_to_urb(urb, td);
- uhci_fill_td(td, status, destination | uhci_explen(pktsze - 1),
- data);
-
- data += pktsze;
- len -= pktsze;
- }
-
- /*
- * Build the final TD for control status
- */
- td = uhci_alloc_td(uhci, urb->dev);
- if (!td)
- return -ENOMEM;
-
- /*
- * It's IN if the pipe is an output pipe or we're not expecting
- * data back.
- */
- destination &= ~TD_TOKEN_PID_MASK;
- if (usb_pipeout(urb->pipe) || !urb->transfer_buffer_length)
- destination |= USB_PID_IN;
- else
- destination |= USB_PID_OUT;
-
- destination |= TD_TOKEN_TOGGLE; /* End in Data1 */
-
- status &= ~TD_CTRL_SPD;
-
- uhci_add_td_to_urb(urb, td);
- uhci_fill_td(td, status | TD_CTRL_IOC,
- destination | uhci_explen(UHCI_NULL_DATA_SIZE), 0);
-
- qh = uhci_alloc_qh(uhci, urb->dev);
- if (!qh)
- return -ENOMEM;
-
- urbp->qh = qh;
- qh->urbp = urbp;
-
- uhci_insert_tds_in_qh(qh, urb, UHCI_PTR_BREADTH);
-
- /* Low-speed transfers get a different queue, and won't hog the bus.
- * Also, some devices enumerate better without FSBR; the easiest way
- * to do that is to put URBs on the low-speed queue while the device
- * is in the DEFAULT state. */
- if (urb->dev->speed == USB_SPEED_LOW ||
- urb->dev->state == USB_STATE_DEFAULT)
- skelqh = uhci->skel_ls_control_qh;
- else {
- skelqh = uhci->skel_fs_control_qh;
- uhci_inc_fsbr(uhci, urb);
- }
-
- if (eurb)
- uhci_append_queued_urb(uhci, eurb, urb);
- else
- uhci_insert_qh(uhci, skelqh, urb);
-
- return -EINPROGRESS;
-}
-
-/*
- * If control-IN transfer was short, the status packet wasn't sent.
- * This routine changes the element pointer in the QH to point at the
- * status TD. It's safe to do this even while the QH is live, because
- * the hardware only updates the element pointer following a successful
- * transfer. The inactive TD for the short packet won't cause an update,
- * so the pointer won't get overwritten. The next time the controller
- * sees this QH, it will send the status packet.
- */
-static int usb_control_retrigger_status(struct uhci_hcd *uhci, struct urb *urb)
-{
- struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
- struct uhci_td *td;
-
- urbp->short_control_packet = 1;
-
- td = list_entry(urbp->td_list.prev, struct uhci_td, list);
- urbp->qh->element = cpu_to_le32(td->dma_handle);
-
- return -EINPROGRESS;
-}
-
-
-static int uhci_result_control(struct uhci_hcd *uhci, struct urb *urb)
-{
- struct list_head *tmp, *head;
- struct urb_priv *urbp = urb->hcpriv;
- struct uhci_td *td;
- unsigned int status;
- int ret = 0;
-
- if (list_empty(&urbp->td_list))
- return -EINVAL;
-
- head = &urbp->td_list;
-
- if (urbp->short_control_packet) {
- tmp = head->prev;
- goto status_stage;
- }
-
- tmp = head->next;
- td = list_entry(tmp, struct uhci_td, list);
-
- /* The first TD is the SETUP stage, check the status, but skip */
- /* the count */
- status = uhci_status_bits(td_status(td));
- if (status & TD_CTRL_ACTIVE)
- return -EINPROGRESS;
-
- if (status)
- goto td_error;
-
- urb->actual_length = 0;
-
- /* The rest of the TD's (but the last) are data */
- tmp = tmp->next;
- while (tmp != head && tmp->next != head) {
- unsigned int ctrlstat;
-
- td = list_entry(tmp, struct uhci_td, list);
- tmp = tmp->next;
-
- ctrlstat = td_status(td);
- status = uhci_status_bits(ctrlstat);
- if (status & TD_CTRL_ACTIVE)
- return -EINPROGRESS;
-
- urb->actual_length += uhci_actual_length(ctrlstat);
-
- if (status)
- goto td_error;
-
- /* Check to see if we received a short packet */
- if (uhci_actual_length(ctrlstat) <
- uhci_expected_length(td_token(td))) {
- if (urb->transfer_flags & URB_SHORT_NOT_OK) {
- ret = -EREMOTEIO;
- goto err;
- }
-
- if (uhci_packetid(td_token(td)) == USB_PID_IN)
- return usb_control_retrigger_status(uhci, urb);
- else
- return 0;
- }
- }
-
-status_stage:
- td = list_entry(tmp, struct uhci_td, list);
-
- /* Control status stage */
- status = td_status(td);
-
-#ifdef I_HAVE_BUGGY_APC_BACKUPS
- /* APC BackUPS Pro kludge */
- /* It tries to send all of the descriptor instead of the amount */
- /* we requested */
- if (status & TD_CTRL_IOC && /* IOC is masked out by uhci_status_bits */
- status & TD_CTRL_ACTIVE &&
- status & TD_CTRL_NAK)
- return 0;
-#endif
-
- status = uhci_status_bits(status);
- if (status & TD_CTRL_ACTIVE)
- return -EINPROGRESS;
-
- if (status)
- goto td_error;
-
- return 0;
-
-td_error:
- ret = uhci_map_status(status, uhci_packetout(td_token(td)));
-
-err:
- if ((debug == 1 && ret != -EPIPE) || debug > 1) {
- /* Some debugging code */
- dev_dbg(uhci_dev(uhci), "%s: failed with status %x\n",
- __FUNCTION__, status);
-
- if (errbuf) {
- /* Print the chain for debugging purposes */
- uhci_show_qh(urbp->qh, errbuf, ERRBUF_LEN, 0);
-
- lprintk(errbuf);
- }
- }
-
- return ret;
-}
-
-/*
- * Common submit for bulk and interrupt
- */
-static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, struct urb *eurb, struct uhci_qh *skelqh)
-{
- struct uhci_td *td;
- struct uhci_qh *qh;
- unsigned long destination, status;
- int maxsze = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe));
- int len = urb->transfer_buffer_length;
- struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
- dma_addr_t data = urb->transfer_dma;
-
- if (len < 0)
- return -EINVAL;
-
- /* The "pipe" thing contains the destination in bits 8--18 */
- destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe);
-
- status = uhci_maxerr(3) | TD_CTRL_ACTIVE;
- if (urb->dev->speed == USB_SPEED_LOW)
- status |= TD_CTRL_LS;
- if (usb_pipein(urb->pipe))
- status |= TD_CTRL_SPD;
-
- /*
- * Build the DATA TD's
- */
- do { /* Allow zero length packets */
- int pktsze = maxsze;
-
- if (pktsze >= len) {
- pktsze = len;
- if (!(urb->transfer_flags & URB_SHORT_NOT_OK))
- status &= ~TD_CTRL_SPD;
- }
-
- td = uhci_alloc_td(uhci, urb->dev);
- if (!td)
- return -ENOMEM;
-
- uhci_add_td_to_urb(urb, td);
- uhci_fill_td(td, status, destination | uhci_explen(pktsze - 1) |
- (usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe),
- usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE_SHIFT),
- data);
-
- data += pktsze;
- len -= maxsze;
-
- usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe),
- usb_pipeout(urb->pipe));
- } while (len > 0);
-
- /*
- * URB_ZERO_PACKET means adding a 0-length packet, if direction
- * is OUT and the transfer_length was an exact multiple of maxsze,
- * hence (len = transfer_length - N * maxsze) == 0
- * however, if transfer_length == 0, the zero packet was already
- * prepared above.
- */
- if (usb_pipeout(urb->pipe) && (urb->transfer_flags & URB_ZERO_PACKET) &&
- !len && urb->transfer_buffer_length) {
- td = uhci_alloc_td(uhci, urb->dev);
- if (!td)
- return -ENOMEM;
-
- uhci_add_td_to_urb(urb, td);
- uhci_fill_td(td, status, destination | uhci_explen(UHCI_NULL_DATA_SIZE) |
- (usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe),
- usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE_SHIFT),
- data);
-
- usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe),
- usb_pipeout(urb->pipe));
- }
-
- /* Set the interrupt-on-completion flag on the last packet.
- * A more-or-less typical 4 KB URB (= size of one memory page)
- * will require about 3 ms to transfer; that's a little on the
- * fast side but not enough to justify delaying an interrupt
- * more than 2 or 3 URBs, so we will ignore the URB_NO_INTERRUPT
- * flag setting. */
- td->status |= cpu_to_le32(TD_CTRL_IOC);
-
- qh = uhci_alloc_qh(uhci, urb->dev);
- if (!qh)
- return -ENOMEM;
-
- urbp->qh = qh;
- qh->urbp = urbp;
-
- /* Always breadth first */
- uhci_insert_tds_in_qh(qh, urb, UHCI_PTR_BREADTH);
-
- if (eurb)
- uhci_append_queued_urb(uhci, eurb, urb);
- else
- uhci_insert_qh(uhci, skelqh, urb);
-
- return -EINPROGRESS;
-}
-
-/*
- * Common result for bulk and interrupt
- */
-static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb)
-{
- struct urb_priv *urbp = urb->hcpriv;
- struct uhci_td *td;
- unsigned int status = 0;
- int ret = 0;
-
- urb->actual_length = 0;
-
- list_for_each_entry(td, &urbp->td_list, list) {
- unsigned int ctrlstat = td_status(td);
-
- status = uhci_status_bits(ctrlstat);
- if (status & TD_CTRL_ACTIVE)
- return -EINPROGRESS;
-
- urb->actual_length += uhci_actual_length(ctrlstat);
-
- if (status)
- goto td_error;
-
- if (uhci_actual_length(ctrlstat) <
- uhci_expected_length(td_token(td))) {
- if (urb->transfer_flags & URB_SHORT_NOT_OK) {
- ret = -EREMOTEIO;
- goto err;
- } else
- return 0;
- }
- }
-
- return 0;
-
-td_error:
- ret = uhci_map_status(status, uhci_packetout(td_token(td)));
-
-err:
- /*
- * Enable this chunk of code if you want to see some more debugging.
- * But be careful, it has the tendancy to starve out khubd and prevent
- * disconnects from happening successfully if you have a slow debug
- * log interface (like a serial console.
- */
-#if 0
- if ((debug == 1 && ret != -EPIPE) || debug > 1) {
- /* Some debugging code */
- dev_dbg(uhci_dev(uhci), "%s: failed with status %x\n",
- __FUNCTION__, status);
-
- if (errbuf) {
- /* Print the chain for debugging purposes */
- uhci_show_qh(urbp->qh, errbuf, ERRBUF_LEN, 0);
-
- lprintk(errbuf);
- }
- }
-#endif
- return ret;
-}
-
-static inline int uhci_submit_bulk(struct uhci_hcd *uhci, struct urb *urb, struct urb *eurb)
-{
- int ret;
-
- /* Can't have low-speed bulk transfers */
- if (urb->dev->speed == USB_SPEED_LOW)
- return -EINVAL;
-
- ret = uhci_submit_common(uhci, urb, eurb, uhci->skel_bulk_qh);
- if (ret == -EINPROGRESS)
- uhci_inc_fsbr(uhci, urb);
-
- return ret;
-}
-
-static inline int uhci_submit_interrupt(struct uhci_hcd *uhci, struct urb *urb, struct urb *eurb)
-{
- /* USB 1.1 interrupt transfers only involve one packet per interval;
- * that's the uhci_submit_common() "breadth first" policy. Drivers
- * can submit urbs of any length, but longer ones might need many
- * intervals to complete.
- */
- return uhci_submit_common(uhci, urb, eurb, uhci->skelqh[__interval_to_skel(urb->interval)]);
-}
-
-/*
- * Isochronous transfers
- */
-static int isochronous_find_limits(struct uhci_hcd *uhci, struct urb *urb, unsigned int *start, unsigned int *end)
-{
- struct urb *last_urb = NULL;
- struct urb_priv *up;
- int ret = 0;
-
- list_for_each_entry(up, &uhci->urb_list, urb_list) {
- struct urb *u = up->urb;
-
- /* look for pending URB's with identical pipe handle */
- if ((urb->pipe == u->pipe) && (urb->dev == u->dev) &&
- (u->status == -EINPROGRESS) && (u != urb)) {
- if (!last_urb)
- *start = u->start_frame;
- last_urb = u;
- }
- }
-
- if (last_urb) {
- *end = (last_urb->start_frame + last_urb->number_of_packets *
- last_urb->interval) & (UHCI_NUMFRAMES-1);
- ret = 0;
- } else
- ret = -1; /* no previous urb found */
-
- return ret;
-}
-
-static int isochronous_find_start(struct uhci_hcd *uhci, struct urb *urb)
-{
- int limits;
- unsigned int start = 0, end = 0;
-
- if (urb->number_of_packets > 900) /* 900? Why? */
- return -EFBIG;
-
- limits = isochronous_find_limits(uhci, urb, &start, &end);
-
- if (urb->transfer_flags & URB_ISO_ASAP) {
- if (limits)
- urb->start_frame =
- (uhci_get_current_frame_number(uhci) +
- 10) & (UHCI_NUMFRAMES - 1);
- else
- urb->start_frame = end;
- } else {
- urb->start_frame &= (UHCI_NUMFRAMES - 1);
- /* FIXME: Sanity check */
- }
-
- return 0;
-}
-
-/*
- * Isochronous transfers
- */
-static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb)
-{
- struct uhci_td *td;
- int i, ret, frame;
- int status, destination;
-
- status = TD_CTRL_ACTIVE | TD_CTRL_IOS;
- destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe);
-
- ret = isochronous_find_start(uhci, urb);
- if (ret)
- return ret;
-
- frame = urb->start_frame;
- for (i = 0; i < urb->number_of_packets; i++, frame += urb->interval) {
- if (!urb->iso_frame_desc[i].length)
- continue;
-
- td = uhci_alloc_td(uhci, urb->dev);
- if (!td)
- return -ENOMEM;
-
- uhci_add_td_to_urb(urb, td);
- uhci_fill_td(td, status, destination | uhci_explen(urb->iso_frame_desc[i].length - 1),
- urb->transfer_dma + urb->iso_frame_desc[i].offset);
-
- if (i + 1 >= urb->number_of_packets)
- td->status |= cpu_to_le32(TD_CTRL_IOC);
-
- uhci_insert_td_frame_list(uhci, td, frame);
- }
-
- return -EINPROGRESS;
-}
-
-static int uhci_result_isochronous(struct uhci_hcd *uhci, struct urb *urb)
-{
- struct uhci_td *td;
- struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
- int status;
- int i, ret = 0;
-
- urb->actual_length = 0;
-
- i = 0;
- list_for_each_entry(td, &urbp->td_list, list) {
- int actlength;
- unsigned int ctrlstat = td_status(td);
-
- if (ctrlstat & TD_CTRL_ACTIVE)
- return -EINPROGRESS;
-
- actlength = uhci_actual_length(ctrlstat);
- urb->iso_frame_desc[i].actual_length = actlength;
- urb->actual_length += actlength;
-
- status = uhci_map_status(uhci_status_bits(ctrlstat),
- usb_pipeout(urb->pipe));
- urb->iso_frame_desc[i].status = status;
- if (status) {
- urb->error_count++;
- ret = status;
- }
-
- i++;
- }
-
- return ret;
-}
-
-static struct urb *uhci_find_urb_ep(struct uhci_hcd *uhci, struct urb *urb)
-{
- struct urb_priv *up;
-
- /* We don't match Isoc transfers since they are special */
- if (usb_pipeisoc(urb->pipe))
- return NULL;
-
- list_for_each_entry(up, &uhci->urb_list, urb_list) {
- struct urb *u = up->urb;
-
- if (u->dev == urb->dev && u->status == -EINPROGRESS) {
- /* For control, ignore the direction */
- if (usb_pipecontrol(urb->pipe) &&
- (u->pipe & ~USB_DIR_IN) == (urb->pipe & ~USB_DIR_IN))
- return u;
- else if (u->pipe == urb->pipe)
- return u;
- }
- }
-
- return NULL;
-}
-
-static int uhci_urb_enqueue(struct usb_hcd *hcd,
- struct usb_host_endpoint *ep,
- struct urb *urb, int mem_flags)
-{
- int ret;
- struct uhci_hcd *uhci = hcd_to_uhci(hcd);
- unsigned long flags;
- struct urb *eurb;
- int bustime;
-
- spin_lock_irqsave(&uhci->schedule_lock, flags);
-
- ret = urb->status;
- if (ret != -EINPROGRESS) /* URB already unlinked! */
- goto out;
-
- eurb = uhci_find_urb_ep(uhci, urb);
-
- if (!uhci_alloc_urb_priv(uhci, urb)) {
- ret = -ENOMEM;
- goto out;
- }
-
- switch (usb_pipetype(urb->pipe)) {
- case PIPE_CONTROL:
- ret = uhci_submit_control(uhci, urb, eurb);
- break;
- case PIPE_INTERRUPT:
- if (!eurb) {
- bustime = usb_check_bandwidth(urb->dev, urb);
- if (bustime < 0)
- ret = bustime;
- else {
- ret = uhci_submit_interrupt(uhci, urb, eurb);
- if (ret == -EINPROGRESS)
- usb_claim_bandwidth(urb->dev, urb, bustime, 0);
- }
- } else { /* inherit from parent */
- urb->bandwidth = eurb->bandwidth;
- ret = uhci_submit_interrupt(uhci, urb, eurb);
- }
- break;
- case PIPE_BULK:
- ret = uhci_submit_bulk(uhci, urb, eurb);
- break;
- case PIPE_ISOCHRONOUS:
- bustime = usb_check_bandwidth(urb->dev, urb);
- if (bustime < 0) {
- ret = bustime;
- break;
- }
-
- ret = uhci_submit_isochronous(uhci, urb);
- if (ret == -EINPROGRESS)
- usb_claim_bandwidth(urb->dev, urb, bustime, 1);
- break;
- }
-
- if (ret != -EINPROGRESS) {
- /* Submit failed, so delete it from the urb_list */
- struct urb_priv *urbp = urb->hcpriv;
-
- list_del_init(&urbp->urb_list);
- uhci_destroy_urb_priv(uhci, urb);
- } else
- ret = 0;
-
-out:
- spin_unlock_irqrestore(&uhci->schedule_lock, flags);
- return ret;
-}
-
-/*
- * Return the result of a transfer
- */
-static void uhci_transfer_result(struct uhci_hcd *uhci, struct urb *urb)
-{
- int ret = -EINPROGRESS;
- struct urb_priv *urbp;
-
- spin_lock(&urb->lock);
-
- urbp = (struct urb_priv *)urb->hcpriv;
-
- if (urb->status != -EINPROGRESS) /* URB already dequeued */
- goto out;
-
- switch (usb_pipetype(urb->pipe)) {
- case PIPE_CONTROL:
- ret = uhci_result_control(uhci, urb);
- break;
- case PIPE_BULK:
- case PIPE_INTERRUPT:
- ret = uhci_result_common(uhci, urb);
- break;
- case PIPE_ISOCHRONOUS:
- ret = uhci_result_isochronous(uhci, urb);
- break;
- }
-
- if (ret == -EINPROGRESS)
- goto out;
- urb->status = ret;
-
- switch (usb_pipetype(urb->pipe)) {
- case PIPE_CONTROL:
- case PIPE_BULK:
- case PIPE_ISOCHRONOUS:
- /* Release bandwidth for Interrupt or Isoc. transfers */
- if (urb->bandwidth)
- usb_release_bandwidth(urb->dev, urb, 1);
- uhci_unlink_generic(uhci, urb);
- break;
- case PIPE_INTERRUPT:
- /* Release bandwidth for Interrupt or Isoc. transfers */
- /* Make sure we don't release if we have a queued URB */
- if (list_empty(&urbp->queue_list) && urb->bandwidth)
- usb_release_bandwidth(urb->dev, urb, 0);
- else
- /* bandwidth was passed on to queued URB, */
- /* so don't let usb_unlink_urb() release it */
- urb->bandwidth = 0;
- uhci_unlink_generic(uhci, urb);
- break;
- default:
- dev_info(uhci_dev(uhci), "%s: unknown pipe type %d "
- "for urb %p\n",
- __FUNCTION__, usb_pipetype(urb->pipe), urb);
- }
-
- /* Move it from uhci->urb_list to uhci->complete_list */
- uhci_moveto_complete(uhci, urbp);
-
-out:
- spin_unlock(&urb->lock);
-}
-
-static void uhci_unlink_generic(struct uhci_hcd *uhci, struct urb *urb)
-{
- struct list_head *head;
- struct uhci_td *td;
- struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
- int prevactive = 0;
-
- uhci_dec_fsbr(uhci, urb); /* Safe since it checks */
-
- /*
- * Now we need to find out what the last successful toggle was
- * so we can update the local data toggle for the next transfer
- *
- * There are 2 ways the last successful completed TD is found:
- *
- * 1) The TD is NOT active and the actual length < expected length
- * 2) The TD is NOT active and it's the last TD in the chain
- *
- * and a third way the first uncompleted TD is found:
- *
- * 3) The TD is active and the previous TD is NOT active
- *
- * Control and Isochronous ignore the toggle, so this is safe
- * for all types
- *
- * FIXME: The toggle fixups won't be 100% reliable until we
- * change over to using a single queue for each endpoint and
- * stop the queue before unlinking.
- */
- head = &urbp->td_list;
- list_for_each_entry(td, head, list) {
- unsigned int ctrlstat = td_status(td);
-
- if (!(ctrlstat & TD_CTRL_ACTIVE) &&
- (uhci_actual_length(ctrlstat) <
- uhci_expected_length(td_token(td)) ||
- td->list.next == head))
- usb_settoggle(urb->dev, uhci_endpoint(td_token(td)),
- uhci_packetout(td_token(td)),
- uhci_toggle(td_token(td)) ^ 1);
- else if ((ctrlstat & TD_CTRL_ACTIVE) && !prevactive)
- usb_settoggle(urb->dev, uhci_endpoint(td_token(td)),
- uhci_packetout(td_token(td)),
- uhci_toggle(td_token(td)));
-
- prevactive = ctrlstat & TD_CTRL_ACTIVE;
- }
-
- uhci_delete_queued_urb(uhci, urb);
-
- /* The interrupt loop will reclaim the QH's */
- uhci_remove_qh(uhci, urbp->qh);
- urbp->qh = NULL;
-}
-
-static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
-{
- struct uhci_hcd *uhci = hcd_to_uhci(hcd);
- unsigned long flags;
- struct urb_priv *urbp;
- unsigned int age;
-
- spin_lock_irqsave(&uhci->schedule_lock, flags);
- urbp = urb->hcpriv;
- if (!urbp) /* URB was never linked! */
- goto done;
- list_del_init(&urbp->urb_list);
-
- uhci_unlink_generic(uhci, urb);
-
- age = uhci_get_current_frame_number(uhci);
- if (age != uhci->urb_remove_age) {
- uhci_remove_pending_urbps(uhci);
- uhci->urb_remove_age = age;
- }
-
- /* If we're the first, set the next interrupt bit */
- if (list_empty(&uhci->urb_remove_list))
- uhci_set_next_interrupt(uhci);
- list_add_tail(&urbp->urb_list, &uhci->urb_remove_list);
-
-done:
- spin_unlock_irqrestore(&uhci->schedule_lock, flags);
- return 0;
-}
-
-static int uhci_fsbr_timeout(struct uhci_hcd *uhci, struct urb *urb)
-{
- struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
- struct list_head *head;
- struct uhci_td *td;
- int count = 0;
-
- uhci_dec_fsbr(uhci, urb);
-
- urbp->fsbr_timeout = 1;
-
- /*
- * Ideally we would want to fix qh->element as well, but it's
- * read/write by the HC, so that can introduce a race. It's not
- * really worth the hassle
- */
-
- head = &urbp->td_list;
- 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
- * make sure it doesn't hog the bandwidth
- */
- if (td->list.next != head && (count % DEPTH_INTERVAL) ==
- (DEPTH_INTERVAL - 1))
- td->link |= UHCI_PTR_DEPTH;
-
- count++;
- }
-
- return 0;
-}
-
-/*
- * uhci_get_current_frame_number()
- *
- * returns the current frame number for a USB bus/controller.
- */
-static unsigned int uhci_get_current_frame_number(struct uhci_hcd *uhci)
-{
- return inw(uhci->io_addr + USBFRNUM);
-}
+#include "uhci-hub.c"
+#include "uhci-debug.c"
+#include "uhci-q.c"
static int init_stall_timer(struct usb_hcd *hcd);
@@ -1538,15 +113,9 @@ static void stall_callback(unsigned long ptr)
struct uhci_hcd *uhci = hcd_to_uhci(hcd);
struct urb_priv *up;
unsigned long flags;
- int called_uhci_finish_completion = 0;
-
- spin_lock_irqsave(&uhci->schedule_lock, flags);
- if (!list_empty(&uhci->urb_remove_list) &&
- uhci_get_current_frame_number(uhci) != uhci->urb_remove_age) {
- uhci_remove_pending_urbps(uhci);
- uhci_finish_completion(hcd, NULL);
- called_uhci_finish_completion = 1;
- }
+
+ spin_lock_irqsave(&uhci->lock, flags);
+ uhci_scan_schedule(uhci, NULL);
list_for_each_entry(up, &uhci->urb_list, urb_list) {
struct urb *u = up->urb;
@@ -1559,11 +128,6 @@ static void stall_callback(unsigned long ptr)
spin_unlock(&u->lock);
}
- spin_unlock_irqrestore(&uhci->schedule_lock, flags);
-
- /* Wake up anyone waiting for an URB to complete */
- if (called_uhci_finish_completion)
- wake_up_all(&uhci->waitqh);
/* Really disable FSBR */
if (!uhci->fsbr && uhci->fsbrtimeout && time_after_eq(jiffies, uhci->fsbrtimeout)) {
@@ -1574,9 +138,10 @@ static void stall_callback(unsigned long ptr)
/* Poll for and perform state transitions */
hc_state_transitions(uhci);
if (unlikely(uhci->suspended_ports && uhci->state != UHCI_SUSPENDED))
- uhci_check_resume(uhci);
+ uhci_check_ports(uhci);
init_stall_timer(hcd);
+ spin_unlock_irqrestore(&uhci->lock, flags);
}
static int init_stall_timer(struct usb_hcd *hcd)
@@ -1592,69 +157,11 @@ static int init_stall_timer(struct usb_hcd *hcd)
return 0;
}
-static void uhci_free_pending_qhs(struct uhci_hcd *uhci)
-{
- struct uhci_qh *qh, *tmp;
-
- list_for_each_entry_safe(qh, tmp, &uhci->qh_remove_list, remove_list) {
- list_del_init(&qh->remove_list);
-
- uhci_free_qh(uhci, qh);
- }
-}
-
-static void uhci_free_pending_tds(struct uhci_hcd *uhci)
-{
- struct uhci_td *td, *tmp;
-
- list_for_each_entry_safe(td, tmp, &uhci->td_remove_list, remove_list) {
- list_del_init(&td->remove_list);
-
- uhci_free_td(uhci, td);
- }
-}
-
-static void
-uhci_finish_urb(struct usb_hcd *hcd, struct urb *urb, struct pt_regs *regs)
-__releases(uhci->schedule_lock)
-__acquires(uhci->schedule_lock)
-{
- struct uhci_hcd *uhci = hcd_to_uhci(hcd);
-
- uhci_destroy_urb_priv(uhci, urb);
-
- spin_unlock(&uhci->schedule_lock);
- usb_hcd_giveback_urb(hcd, urb, regs);
- spin_lock(&uhci->schedule_lock);
-}
-
-static void uhci_finish_completion(struct usb_hcd *hcd, struct pt_regs *regs)
-{
- struct uhci_hcd *uhci = hcd_to_uhci(hcd);
- struct urb_priv *urbp, *tmp;
-
- list_for_each_entry_safe(urbp, tmp, &uhci->complete_list, urb_list) {
- struct urb *urb = urbp->urb;
-
- list_del_init(&urbp->urb_list);
- uhci_finish_urb(hcd, urb, regs);
- }
-}
-
-static void uhci_remove_pending_urbps(struct uhci_hcd *uhci)
-{
-
- /* Splice the urb_remove_list onto the end of the complete_list */
- list_splice_init(&uhci->urb_remove_list, uhci->complete_list.prev);
-}
-
static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
{
struct uhci_hcd *uhci = hcd_to_uhci(hcd);
unsigned long io_addr = uhci->io_addr;
unsigned short status;
- struct urb_priv *urbp, *tmp;
- unsigned int age;
/*
* Read the interrupt status, and write it back to clear the
@@ -1683,37 +190,9 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
if (status & USBSTS_RD)
uhci->resume_detect = 1;
- spin_lock(&uhci->schedule_lock);
-
- age = uhci_get_current_frame_number(uhci);
- if (age != uhci->qh_remove_age)
- uhci_free_pending_qhs(uhci);
- if (age != uhci->td_remove_age)
- uhci_free_pending_tds(uhci);
- if (age != uhci->urb_remove_age)
- uhci_remove_pending_urbps(uhci);
-
- if (list_empty(&uhci->urb_remove_list) &&
- list_empty(&uhci->td_remove_list) &&
- list_empty(&uhci->qh_remove_list))
- uhci_clear_next_interrupt(uhci);
- else
- uhci_set_next_interrupt(uhci);
-
- /* Walk the list of pending URBs to see which ones completed
- * (must be _safe because uhci_transfer_result() dequeues URBs) */
- list_for_each_entry_safe(urbp, tmp, &uhci->urb_list, urb_list) {
- struct urb *urb = urbp->urb;
-
- /* Checks the status and does all of the magic necessary */
- uhci_transfer_result(uhci, urb);
- }
- uhci_finish_completion(hcd, regs);
-
- spin_unlock(&uhci->schedule_lock);
-
- /* Wake up anyone waiting for an URB to complete */
- wake_up_all(&uhci->waitqh);
+ spin_lock(&uhci->lock);
+ uhci_scan_schedule(uhci, regs);
+ spin_unlock(&uhci->lock);
return IRQ_HANDLED;
}
@@ -1737,6 +216,7 @@ static void reset_hc(struct uhci_hcd *uhci)
/* Another 10ms delay */
msleep(10);
uhci->resume_detect = 0;
+ uhci->is_stopped = UHCI_IS_STOPPED;
}
static void suspend_hc(struct uhci_hcd *uhci)
@@ -1747,6 +227,12 @@ static void suspend_hc(struct uhci_hcd *uhci)
uhci->state = UHCI_SUSPENDED;
uhci->resume_detect = 0;
outw(USBCMD_EGSM, io_addr + USBCMD);
+
+ /* FIXME: Wait for the controller to actually stop */
+ uhci_get_current_frame_number(uhci);
+ uhci->is_stopped = UHCI_IS_STOPPED;
+
+ uhci_scan_schedule(uhci, NULL);
}
static void wakeup_hc(struct uhci_hcd *uhci)
@@ -1761,6 +247,7 @@ static void wakeup_hc(struct uhci_hcd *uhci)
outw(USBCMD_FGR | USBCMD_EGSM, io_addr + USBCMD);
uhci->state = UHCI_RESUMING_1;
uhci->state_end = jiffies + msecs_to_jiffies(20);
+ uhci->is_stopped = 0;
break;
case UHCI_RESUMING_1: /* End global resume */
@@ -1866,6 +353,16 @@ static void hc_state_transitions(struct uhci_hcd *uhci)
}
}
+/*
+ * Store the current frame number in uhci->frame_number if the controller
+ * is runnning
+ */
+static void uhci_get_current_frame_number(struct uhci_hcd *uhci)
+{
+ if (!uhci->is_stopped)
+ uhci->frame_number = inw(uhci->io_addr + USBFRNUM);
+}
+
static int start_hc(struct uhci_hcd *uhci)
{
unsigned long io_addr = uhci->io_addr;
@@ -1886,6 +383,9 @@ static int start_hc(struct uhci_hcd *uhci)
msleep(1);
}
+ /* Mark controller as running before we enable interrupts */
+ uhci_to_hcd(uhci)->state = HC_STATE_RUNNING;
+
/* Turn on PIRQ and all interrupts */
pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP,
USBLEGSUP_DEFAULT);
@@ -1900,13 +400,13 @@ static int start_hc(struct uhci_hcd *uhci)
uhci->state = UHCI_RUNNING_GRACE;
uhci->state_end = jiffies + HZ;
outw(USBCMD_RS | USBCMD_CF | USBCMD_MAXP, io_addr + USBCMD);
+ uhci->is_stopped = 0;
- uhci_to_hcd(uhci)->state = USB_STATE_RUNNING;
return 0;
}
/*
- * De-allocate all resources..
+ * De-allocate all resources
*/
static void release_uhci(struct uhci_hcd *uhci)
{
@@ -1949,7 +449,7 @@ static int uhci_reset(struct usb_hcd *hcd)
{
struct uhci_hcd *uhci = hcd_to_uhci(hcd);
- uhci->io_addr = (unsigned long) hcd->regs;
+ uhci->io_addr = (unsigned long) hcd->rsrc_start;
/* Kick BIOS off this hardware and reset, so we won't get
* interrupts from any previous setup.
@@ -1984,7 +484,7 @@ static int uhci_start(struct usb_hcd *hcd)
struct usb_device *udev;
struct dentry *dentry;
- io_size = pci_resource_len(to_pci_dev(uhci_dev(uhci)), hcd->region);
+ io_size = (unsigned) hcd->rsrc_len;
dentry = debugfs_create_file(hcd->self.bus_name, S_IFREG|S_IRUGO|S_IWUSR, uhci_debugfs_root, uhci, &uhci_debug_operations);
if (!dentry) {
@@ -1997,7 +497,7 @@ static int uhci_start(struct usb_hcd *hcd)
uhci->fsbr = 0;
uhci->fsbrtimeout = 0;
- spin_lock_init(&uhci->schedule_lock);
+ spin_lock_init(&uhci->lock);
INIT_LIST_HEAD(&uhci->qh_remove_list);
INIT_LIST_HEAD(&uhci->td_remove_list);
@@ -2151,7 +651,7 @@ static int uhci_start(struct usb_hcd *hcd)
udev->speed = USB_SPEED_FULL;
- if (hcd_register_root(udev, hcd) != 0) {
+ if (usb_hcd_register_root_hub(udev, hcd) != 0) {
dev_err(uhci_dev(uhci), "unable to start root hub\n");
retval = -ENOMEM;
goto err_start_root_hub;
@@ -2206,26 +706,11 @@ static void uhci_stop(struct usb_hcd *hcd)
struct uhci_hcd *uhci = hcd_to_uhci(hcd);
del_timer_sync(&uhci->stall_timer);
-
- /*
- * At this point, we're guaranteed that no new connects can be made
- * to this bus since there are no more parents
- */
-
reset_hc(uhci);
- spin_lock_irq(&uhci->schedule_lock);
- uhci_free_pending_qhs(uhci);
- uhci_free_pending_tds(uhci);
- uhci_remove_pending_urbps(uhci);
- uhci_finish_completion(hcd, NULL);
-
- uhci_free_pending_qhs(uhci);
- uhci_free_pending_tds(uhci);
- spin_unlock_irq(&uhci->schedule_lock);
-
- /* Wake up anyone waiting for an URB to complete */
- wake_up_all(&uhci->waitqh);
+ spin_lock_irq(&uhci->lock);
+ uhci_scan_schedule(uhci, NULL);
+ spin_unlock_irq(&uhci->lock);
release_uhci(uhci);
}
@@ -2235,13 +720,19 @@ static int uhci_suspend(struct usb_hcd *hcd, u32 state)
{
struct uhci_hcd *uhci = hcd_to_uhci(hcd);
+ spin_lock_irq(&uhci->lock);
+
/* Don't try to suspend broken motherboards, reset instead */
- if (suspend_allowed(uhci)) {
+ if (suspend_allowed(uhci))
suspend_hc(uhci);
- uhci->saved_framenumber =
- inw(uhci->io_addr + USBFRNUM) & 0x3ff;
- } else
+ else {
+ spin_unlock_irq(&uhci->lock);
reset_hc(uhci);
+ spin_lock_irq(&uhci->lock);
+ uhci_scan_schedule(uhci, NULL);
+ }
+
+ spin_unlock_irq(&uhci->lock);
return 0;
}
@@ -2252,6 +743,8 @@ static int uhci_resume(struct usb_hcd *hcd)
pci_set_master(to_pci_dev(uhci_dev(uhci)));
+ spin_lock_irq(&uhci->lock);
+
if (uhci->state == UHCI_SUSPENDED) {
/*
@@ -2262,7 +755,7 @@ static int uhci_resume(struct usb_hcd *hcd)
*/
pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP,
0);
- outw(uhci->saved_framenumber, uhci->io_addr + USBFRNUM);
+ outw(uhci->frame_number, uhci->io_addr + USBFRNUM);
outl(uhci->fl->dma_handle, uhci->io_addr + USBFLBASEADD);
outw(USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC |
USBINTR_SP, uhci->io_addr + USBINTR);
@@ -2270,11 +763,15 @@ static int uhci_resume(struct usb_hcd *hcd)
pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP,
USBLEGSUP_DEFAULT);
} else {
+ spin_unlock_irq(&uhci->lock);
reset_hc(uhci);
if ((rc = start_hc(uhci)) != 0)
return rc;
+ spin_lock_irq(&uhci->lock);
}
- hcd->state = USB_STATE_RUNNING;
+ hcd->state = HC_STATE_RUNNING;
+
+ spin_unlock_irq(&uhci->lock);
return 0;
}
#endif
@@ -2290,7 +787,17 @@ static void uhci_hcd_endpoint_disable(struct usb_hcd *hcd,
static int uhci_hcd_get_frame_number(struct usb_hcd *hcd)
{
- return uhci_get_current_frame_number(hcd_to_uhci(hcd));
+ struct uhci_hcd *uhci = hcd_to_uhci(hcd);
+ int frame_number;
+ unsigned long flags;
+
+ /* Minimize latency by avoiding the spinlock */
+ local_irq_save(flags);
+ rmb();
+ frame_number = (uhci->is_stopped ? uhci->frame_number :
+ inw(uhci->io_addr + USBFRNUM));
+ local_irq_restore(flags);
+ return frame_number;
}
static const char hcd_name[] = "uhci_hcd";
diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
index fee7c52dcc317..02255d69e1fef 100644
--- a/drivers/usb/host/uhci-hcd.h
+++ b/drivers/usb/host/uhci-hcd.h
@@ -358,39 +358,44 @@ struct uhci_hcd {
struct uhci_td *term_td; /* Terminating TD, see UHCI bug */
struct uhci_qh *skelqh[UHCI_NUM_SKELQH]; /* Skeleton QH's */
- spinlock_t schedule_lock;
- struct uhci_frame_list *fl; /* P: uhci->schedule_lock */
+ spinlock_t lock;
+ struct uhci_frame_list *fl; /* P: uhci->lock */
int fsbr; /* Full-speed bandwidth reclamation */
unsigned long fsbrtimeout; /* FSBR delay */
enum uhci_state state; /* FIXME: needs a spinlock */
unsigned long state_end; /* Time of next transition */
- int resume_detect; /* Need a Global Resume */
- unsigned int saved_framenumber; /* Save during PM suspend */
+ unsigned int frame_number; /* As of last check */
+ unsigned int is_stopped;
+#define UHCI_IS_STOPPED 9999 /* Larger than a frame # */
- /* Support for port suspend/resume */
+ unsigned int scan_in_progress:1; /* Schedule scan is running */
+ unsigned int need_rescan:1; /* Redo the schedule scan */
+ unsigned int resume_detect:1; /* Need a Global Resume */
+
+ /* Support for port suspend/resume/reset */
unsigned long port_c_suspend; /* Bit-arrays of ports */
unsigned long suspended_ports;
unsigned long resuming_ports;
- unsigned long resume_timeout; /* Time to stop signalling */
+ unsigned long ports_timeout; /* Time to stop signalling */
/* Main list of URB's currently controlled by this HC */
- struct list_head urb_list; /* P: uhci->schedule_lock */
+ struct list_head urb_list; /* P: uhci->lock */
/* List of QH's that are done, but waiting to be unlinked (race) */
- struct list_head qh_remove_list; /* P: uhci->schedule_lock */
+ struct list_head qh_remove_list; /* P: uhci->lock */
unsigned int qh_remove_age; /* Age in frames */
/* List of TD's that are done, but waiting to be freed (race) */
- struct list_head td_remove_list; /* P: uhci->schedule_lock */
+ struct list_head td_remove_list; /* P: uhci->lock */
unsigned int td_remove_age; /* Age in frames */
/* List of asynchronously unlinked URB's */
- struct list_head urb_remove_list; /* P: uhci->schedule_lock */
+ struct list_head urb_remove_list; /* P: uhci->lock */
unsigned int urb_remove_age; /* Age in frames */
/* List of URB's awaiting completion callback */
- struct list_head complete_list; /* P: uhci->schedule_lock */
+ struct list_head complete_list; /* P: uhci->lock */
int rh_numports;
@@ -436,13 +441,13 @@ struct urb_priv {
* Locking in uhci.c
*
* Almost everything relating to the hardware schedule and processing
- * of URBs is protected by uhci->schedule_lock. urb->status is protected
- * by urb->lock; that's the one exception.
+ * of URBs is protected by uhci->lock. urb->status is protected by
+ * urb->lock; that's the one exception.
*
- * To prevent deadlocks, never lock uhci->schedule_lock while holding
- * urb->lock. The safe order of locking is:
+ * To prevent deadlocks, never lock uhci->lock while holding urb->lock.
+ * The safe order of locking is:
*
- * #1 uhci->schedule_lock
+ * #1 uhci->lock
* #2 urb->lock
*/
diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c
index 1feccf2f03b53..4c45ba8390f8a 100644
--- a/drivers/usb/host/uhci-hub.c
+++ b/drivers/usb/host/uhci-hub.c
@@ -66,7 +66,6 @@ static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf)
/* UHCI controllers don't automatically stop resume signalling after 20 msec,
* so we have to poll and check timeouts in order to take care of it.
- * FIXME: Synchronize access to these fields by a spinlock.
*/
static void uhci_finish_suspend(struct uhci_hcd *uhci, int port,
unsigned long port_addr)
@@ -87,22 +86,37 @@ static void uhci_finish_suspend(struct uhci_hcd *uhci, int port,
}
}
-static void uhci_check_resume(struct uhci_hcd *uhci)
+static void uhci_check_ports(struct uhci_hcd *uhci)
{
unsigned int port;
unsigned long port_addr;
+ int status;
for (port = 0; port < uhci->rh_numports; ++port) {
port_addr = uhci->io_addr + USBPORTSC1 + 2 * port;
- if (unlikely(inw(port_addr) & USBPORTSC_RD)) {
+ status = inw(port_addr);
+ if (unlikely(status & USBPORTSC_PR)) {
+ if (time_after_eq(jiffies, uhci->ports_timeout)) {
+ CLR_RH_PORTSTAT(USBPORTSC_PR);
+ udelay(10);
+
+ /* If the port was enabled before, turning
+ * reset on caused a port enable change.
+ * Turning reset off causes a port connect
+ * status change. Clear these changes. */
+ CLR_RH_PORTSTAT(USBPORTSC_CSC | USBPORTSC_PEC);
+ SET_RH_PORTSTAT(USBPORTSC_PE);
+ }
+ }
+ if (unlikely(status & USBPORTSC_RD)) {
if (!test_bit(port, &uhci->resuming_ports)) {
/* Port received a wakeup request */
set_bit(port, &uhci->resuming_ports);
- uhci->resume_timeout = jiffies +
+ uhci->ports_timeout = jiffies +
msecs_to_jiffies(20);
} else if (time_after_eq(jiffies,
- uhci->resume_timeout)) {
+ uhci->ports_timeout)) {
uhci_finish_suspend(uhci, port, port_addr);
}
}
@@ -118,7 +132,9 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
unsigned int port = wIndex - 1;
unsigned long port_addr = uhci->io_addr + USBPORTSC1 + 2 * port;
u16 wPortChange, wPortStatus;
+ unsigned long flags;
+ spin_lock_irqsave(&uhci->lock, flags);
switch (typeReq) {
case GetHubStatus:
@@ -128,9 +144,7 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
if (port >= uhci->rh_numports)
goto err;
- if (uhci->resuming_ports)
- uhci_check_resume(uhci);
-
+ uhci_check_ports(uhci);
status = inw(port_addr);
/* Intel controllers report the OverCurrent bit active on.
@@ -203,15 +217,12 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
OK(0);
case USB_PORT_FEAT_RESET:
SET_RH_PORTSTAT(USBPORTSC_PR);
- mdelay(50); /* USB v1.1 7.1.7.3 */
- CLR_RH_PORTSTAT(USBPORTSC_PR);
- udelay(10);
/* Reset terminates Resume signalling */
uhci_finish_suspend(uhci, port, port_addr);
- SET_RH_PORTSTAT(USBPORTSC_PE);
- mdelay(10);
- CLR_RH_PORTSTAT(USBPORTSC_PEC|USBPORTSC_CSC);
+
+ /* USB v2.0 7.1.7.5 */
+ uhci->ports_timeout = jiffies + msecs_to_jiffies(50);
OK(0);
case USB_PORT_FEAT_POWER:
/* UHCI has no power switching */
@@ -238,8 +249,6 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
if (test_bit(port, &uhci->suspended_ports) &&
!test_and_set_bit(port,
&uhci->resuming_ports)) {
- uhci->resume_timeout = jiffies +
- msecs_to_jiffies(20);
SET_RH_PORTSTAT(USBPORTSC_RD);
/* The controller won't allow RD to be set
@@ -249,6 +258,10 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
if (!(inw(port_addr) & USBPORTSC_RD))
uhci_finish_suspend(uhci, port,
port_addr);
+ else
+ /* USB v2.0 7.1.7.7 */
+ uhci->ports_timeout = jiffies +
+ msecs_to_jiffies(20);
}
OK(0);
case USB_PORT_FEAT_C_SUSPEND:
@@ -280,6 +293,7 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
err:
retval = -EPIPE;
}
+ spin_unlock_irqrestore(&uhci->lock, flags);
return retval;
}
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
new file mode 100644
index 0000000000000..2a7c19501f248
--- /dev/null
+++ b/drivers/usb/host/uhci-q.c
@@ -0,0 +1,1539 @@
+/*
+ * Universal Host Controller Interface driver for USB.
+ *
+ * Maintainer: Alan Stern <stern@rowland.harvard.edu>
+ *
+ * (C) Copyright 1999 Linus Torvalds
+ * (C) Copyright 1999-2002 Johannes Erdfelt, johannes@erdfelt.com
+ * (C) Copyright 1999 Randy Dunlap
+ * (C) Copyright 1999 Georg Acher, acher@in.tum.de
+ * (C) Copyright 1999 Deti Fliegl, deti@fliegl.de
+ * (C) Copyright 1999 Thomas Sailer, sailer@ife.ee.ethz.ch
+ * (C) Copyright 1999 Roman Weissgaerber, weissg@vienna.at
+ * (C) Copyright 2000 Yggdrasil Computing, Inc. (port of new PCI interface
+ * support from usb-ohci.c by Adam Richter, adam@yggdrasil.com).
+ * (C) Copyright 1999 Gregory P. Smith (from usb-ohci.c)
+ * (C) Copyright 2004 Alan Stern, stern@rowland.harvard.edu
+ */
+
+static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb);
+static void uhci_unlink_generic(struct uhci_hcd *uhci, struct urb *urb);
+static void uhci_remove_pending_urbps(struct uhci_hcd *uhci);
+static void uhci_free_pending_qhs(struct uhci_hcd *uhci);
+static void uhci_free_pending_tds(struct uhci_hcd *uhci);
+
+/*
+ * Technically, updating td->status here is a race, but it's not really a
+ * problem. The worst that can happen is that we set the IOC bit again
+ * generating a spurious interrupt. We could fix this by creating another
+ * QH and leaving the IOC bit always set, but then we would have to play
+ * games with the FSBR code to make sure we get the correct order in all
+ * the cases. I don't think it's worth the effort
+ */
+static inline void uhci_set_next_interrupt(struct uhci_hcd *uhci)
+{
+ uhci->term_td->status |= cpu_to_le32(TD_CTRL_IOC);
+}
+
+static inline void uhci_clear_next_interrupt(struct uhci_hcd *uhci)
+{
+ uhci->term_td->status &= ~cpu_to_le32(TD_CTRL_IOC);
+}
+
+static inline void uhci_moveto_complete(struct uhci_hcd *uhci,
+ struct urb_priv *urbp)
+{
+ list_move_tail(&urbp->urb_list, &uhci->complete_list);
+}
+
+static struct uhci_td *uhci_alloc_td(struct uhci_hcd *uhci, struct usb_device *dev)
+{
+ dma_addr_t dma_handle;
+ struct uhci_td *td;
+
+ td = dma_pool_alloc(uhci->td_pool, GFP_ATOMIC, &dma_handle);
+ if (!td)
+ return NULL;
+
+ td->dma_handle = dma_handle;
+
+ td->link = UHCI_PTR_TERM;
+ td->buffer = 0;
+
+ td->frame = -1;
+ td->dev = dev;
+
+ INIT_LIST_HEAD(&td->list);
+ INIT_LIST_HEAD(&td->remove_list);
+ INIT_LIST_HEAD(&td->fl_list);
+
+ usb_get_dev(dev);
+
+ return td;
+}
+
+static inline void uhci_fill_td(struct uhci_td *td, u32 status,
+ u32 token, u32 buffer)
+{
+ td->status = cpu_to_le32(status);
+ td->token = cpu_to_le32(token);
+ td->buffer = cpu_to_le32(buffer);
+}
+
+/*
+ * We insert Isochronous URB's 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)
+{
+ framenum &= (UHCI_NUMFRAMES - 1);
+
+ td->frame = framenum;
+
+ /* Is there a TD already mapped there? */
+ if (uhci->fl->frame_cpu[framenum]) {
+ struct uhci_td *ftd, *ltd;
+
+ ftd = uhci->fl->frame_cpu[framenum];
+ ltd = list_entry(ftd->fl_list.prev, struct uhci_td, fl_list);
+
+ list_add_tail(&td->fl_list, &ftd->fl_list);
+
+ td->link = ltd->link;
+ wmb();
+ ltd->link = cpu_to_le32(td->dma_handle);
+ } else {
+ td->link = uhci->fl->frame[framenum];
+ wmb();
+ uhci->fl->frame[framenum] = cpu_to_le32(td->dma_handle);
+ uhci->fl->frame_cpu[framenum] = td;
+ }
+}
+
+static void uhci_remove_td(struct uhci_hcd *uhci, struct uhci_td *td)
+{
+ /* If it's not inserted, don't remove it */
+ if (td->frame == -1 && list_empty(&td->fl_list))
+ return;
+
+ if (td->frame != -1 && uhci->fl->frame_cpu[td->frame] == td) {
+ if (list_empty(&td->fl_list)) {
+ uhci->fl->frame[td->frame] = td->link;
+ uhci->fl->frame_cpu[td->frame] = NULL;
+ } else {
+ struct uhci_td *ntd;
+
+ ntd = list_entry(td->fl_list.next, struct uhci_td, fl_list);
+ uhci->fl->frame[td->frame] = cpu_to_le32(ntd->dma_handle);
+ uhci->fl->frame_cpu[td->frame] = ntd;
+ }
+ } else {
+ struct uhci_td *ptd;
+
+ ptd = list_entry(td->fl_list.prev, struct uhci_td, fl_list);
+ ptd->link = td->link;
+ }
+
+ wmb();
+ td->link = UHCI_PTR_TERM;
+
+ list_del_init(&td->fl_list);
+ td->frame = -1;
+}
+
+/*
+ * Inserts a td list into qh.
+ */
+static void uhci_insert_tds_in_qh(struct uhci_qh *qh, struct urb *urb, __le32 breadth)
+{
+ struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+ struct uhci_td *td;
+ __le32 *plink;
+
+ /* Ordering isn't important here yet since the QH hasn't been */
+ /* inserted into the schedule yet */
+ plink = &qh->element;
+ list_for_each_entry(td, &urbp->td_list, list) {
+ *plink = cpu_to_le32(td->dma_handle) | breadth;
+ plink = &td->link;
+ }
+ *plink = UHCI_PTR_TERM;
+}
+
+static void uhci_free_td(struct uhci_hcd *uhci, struct uhci_td *td)
+{
+ if (!list_empty(&td->list))
+ dev_warn(uhci_dev(uhci), "td %p still in list!\n", td);
+ if (!list_empty(&td->remove_list))
+ dev_warn(uhci_dev(uhci), "td %p still in remove_list!\n", td);
+ if (!list_empty(&td->fl_list))
+ dev_warn(uhci_dev(uhci), "td %p still in fl_list!\n", td);
+
+ if (td->dev)
+ usb_put_dev(td->dev);
+
+ dma_pool_free(uhci->td_pool, td, td->dma_handle);
+}
+
+static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci, struct usb_device *dev)
+{
+ dma_addr_t dma_handle;
+ struct uhci_qh *qh;
+
+ qh = dma_pool_alloc(uhci->qh_pool, GFP_ATOMIC, &dma_handle);
+ if (!qh)
+ return NULL;
+
+ qh->dma_handle = dma_handle;
+
+ qh->element = UHCI_PTR_TERM;
+ qh->link = UHCI_PTR_TERM;
+
+ qh->dev = dev;
+ qh->urbp = NULL;
+
+ INIT_LIST_HEAD(&qh->list);
+ INIT_LIST_HEAD(&qh->remove_list);
+
+ usb_get_dev(dev);
+
+ return qh;
+}
+
+static void uhci_free_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
+{
+ if (!list_empty(&qh->list))
+ dev_warn(uhci_dev(uhci), "qh %p list not empty!\n", qh);
+ if (!list_empty(&qh->remove_list))
+ dev_warn(uhci_dev(uhci), "qh %p still in remove_list!\n", qh);
+
+ if (qh->dev)
+ usb_put_dev(qh->dev);
+
+ dma_pool_free(uhci->qh_pool, qh, qh->dma_handle);
+}
+
+/*
+ * Append this urb's qh after the last qh in skelqh->list
+ *
+ * Note that urb_priv.queue_list doesn't have a separate queue head;
+ * it's a ring with every element "live".
+ */
+static void uhci_insert_qh(struct uhci_hcd *uhci, struct uhci_qh *skelqh, struct urb *urb)
+{
+ struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+ struct urb_priv *turbp;
+ struct uhci_qh *lqh;
+
+ /* Grab the last QH */
+ lqh = list_entry(skelqh->list.prev, struct uhci_qh, list);
+
+ /* Point to the next skelqh */
+ urbp->qh->link = lqh->link;
+ wmb(); /* Ordering is important */
+
+ /*
+ * Patch QHs for previous endpoint's queued URBs? HC goes
+ * here next, not to the next skelqh it now points to.
+ *
+ * lqh --> td ... --> qh ... --> td --> qh ... --> td
+ * | | |
+ * v v v
+ * +<----------------+-----------------+
+ * v
+ * newqh --> td ... --> td
+ * |
+ * v
+ * ...
+ *
+ * The HC could see (and use!) any of these as we write them.
+ */
+ lqh->link = cpu_to_le32(urbp->qh->dma_handle) | UHCI_PTR_QH;
+ if (lqh->urbp) {
+ list_for_each_entry(turbp, &lqh->urbp->queue_list, queue_list)
+ turbp->qh->link = lqh->link;
+ }
+
+ list_add_tail(&urbp->qh->list, &skelqh->list);
+}
+
+/*
+ * Start removal of QH from schedule; it finishes next frame.
+ * TDs should be unlinked before this is called.
+ */
+static void uhci_remove_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
+{
+ struct uhci_qh *pqh;
+ __le32 newlink;
+
+ if (!qh)
+ return;
+
+ /*
+ * Only go through the hoops if it's actually linked in
+ */
+ if (!list_empty(&qh->list)) {
+
+ /* If our queue is nonempty, make the next URB the head */
+ if (!list_empty(&qh->urbp->queue_list)) {
+ struct urb_priv *nurbp;
+
+ nurbp = list_entry(qh->urbp->queue_list.next,
+ struct urb_priv, queue_list);
+ nurbp->queued = 0;
+ list_add(&nurbp->qh->list, &qh->list);
+ newlink = cpu_to_le32(nurbp->qh->dma_handle) | UHCI_PTR_QH;
+ } else
+ newlink = qh->link;
+
+ /* Fix up the previous QH's queue to link to either
+ * the new head of this queue or the start of the
+ * next endpoint's queue. */
+ pqh = list_entry(qh->list.prev, struct uhci_qh, list);
+ pqh->link = newlink;
+ if (pqh->urbp) {
+ struct urb_priv *turbp;
+
+ list_for_each_entry(turbp, &pqh->urbp->queue_list,
+ queue_list)
+ turbp->qh->link = newlink;
+ }
+ wmb();
+
+ /* Leave qh->link in case the HC is on the QH now, it will */
+ /* continue the rest of the schedule */
+ qh->element = UHCI_PTR_TERM;
+
+ list_del_init(&qh->list);
+ }
+
+ list_del_init(&qh->urbp->queue_list);
+ qh->urbp = NULL;
+
+ uhci_get_current_frame_number(uhci);
+ if (uhci->frame_number + uhci->is_stopped != uhci->qh_remove_age) {
+ uhci_free_pending_qhs(uhci);
+ uhci->qh_remove_age = uhci->frame_number;
+ }
+
+ /* Check to see if the remove list is empty. Set the IOC bit */
+ /* to force an interrupt so we can remove the QH */
+ if (list_empty(&uhci->qh_remove_list))
+ uhci_set_next_interrupt(uhci);
+
+ list_add(&qh->remove_list, &uhci->qh_remove_list);
+}
+
+static int uhci_fixup_toggle(struct urb *urb, unsigned int toggle)
+{
+ struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+ struct uhci_td *td;
+
+ list_for_each_entry(td, &urbp->td_list, list) {
+ if (toggle)
+ td->token |= cpu_to_le32(TD_TOKEN_TOGGLE);
+ else
+ td->token &= ~cpu_to_le32(TD_TOKEN_TOGGLE);
+
+ toggle ^= 1;
+ }
+
+ return toggle;
+}
+
+/* This function will append one URB's QH to another URB's QH. This is for */
+/* queuing interrupt, control or bulk transfers */
+static void uhci_append_queued_urb(struct uhci_hcd *uhci, struct urb *eurb, struct urb *urb)
+{
+ struct urb_priv *eurbp, *urbp, *furbp, *lurbp;
+ struct uhci_td *lltd;
+
+ eurbp = eurb->hcpriv;
+ urbp = urb->hcpriv;
+
+ /* Find the first URB in the queue */
+ furbp = eurbp;
+ if (eurbp->queued) {
+ list_for_each_entry(furbp, &eurbp->queue_list, queue_list)
+ if (!furbp->queued)
+ break;
+ }
+
+ lurbp = list_entry(furbp->queue_list.prev, struct urb_priv, queue_list);
+
+ lltd = list_entry(lurbp->td_list.prev, struct uhci_td, list);
+
+ /* Control transfers always start with toggle 0 */
+ if (!usb_pipecontrol(urb->pipe))
+ usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
+ usb_pipeout(urb->pipe),
+ uhci_fixup_toggle(urb,
+ uhci_toggle(td_token(lltd)) ^ 1));
+
+ /* All qh's in the queue need to link to the next queue */
+ urbp->qh->link = eurbp->qh->link;
+
+ wmb(); /* Make sure we flush everything */
+
+ lltd->link = cpu_to_le32(urbp->qh->dma_handle) | UHCI_PTR_QH;
+
+ list_add_tail(&urbp->queue_list, &furbp->queue_list);
+
+ urbp->queued = 1;
+}
+
+static void uhci_delete_queued_urb(struct uhci_hcd *uhci, struct urb *urb)
+{
+ struct urb_priv *urbp, *nurbp, *purbp, *turbp;
+ struct uhci_td *pltd;
+ unsigned int toggle;
+
+ urbp = urb->hcpriv;
+
+ if (list_empty(&urbp->queue_list))
+ return;
+
+ nurbp = list_entry(urbp->queue_list.next, struct urb_priv, queue_list);
+
+ /*
+ * Fix up the toggle for the following URBs in the queue.
+ * Only needed for bulk and interrupt: control and isochronous
+ * endpoints don't propagate toggles between messages.
+ */
+ if (usb_pipebulk(urb->pipe) || usb_pipeint(urb->pipe)) {
+ if (!urbp->queued)
+ /* We just set the toggle in uhci_unlink_generic */
+ toggle = usb_gettoggle(urb->dev,
+ usb_pipeendpoint(urb->pipe),
+ usb_pipeout(urb->pipe));
+ else {
+ /* If we're in the middle of the queue, grab the */
+ /* toggle from the TD previous to us */
+ purbp = list_entry(urbp->queue_list.prev,
+ struct urb_priv, queue_list);
+ pltd = list_entry(purbp->td_list.prev,
+ struct uhci_td, list);
+ toggle = uhci_toggle(td_token(pltd)) ^ 1;
+ }
+
+ list_for_each_entry(turbp, &urbp->queue_list, queue_list) {
+ if (!turbp->queued)
+ break;
+ toggle = uhci_fixup_toggle(turbp->urb, toggle);
+ }
+
+ usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
+ usb_pipeout(urb->pipe), toggle);
+ }
+
+ if (urbp->queued) {
+ /* We're somewhere in the middle (or end). The case where
+ * we're at the head is handled in uhci_remove_qh(). */
+ purbp = list_entry(urbp->queue_list.prev, struct urb_priv,
+ queue_list);
+
+ pltd = list_entry(purbp->td_list.prev, struct uhci_td, list);
+ if (nurbp->queued)
+ pltd->link = cpu_to_le32(nurbp->qh->dma_handle) | UHCI_PTR_QH;
+ else
+ /* The next URB happens to be the beginning, so */
+ /* we're the last, end the chain */
+ pltd->link = UHCI_PTR_TERM;
+ }
+
+ /* urbp->queue_list is handled in uhci_remove_qh() */
+}
+
+static struct urb_priv *uhci_alloc_urb_priv(struct uhci_hcd *uhci, struct urb *urb)
+{
+ struct urb_priv *urbp;
+
+ urbp = kmem_cache_alloc(uhci_up_cachep, SLAB_ATOMIC);
+ if (!urbp)
+ return NULL;
+
+ memset((void *)urbp, 0, sizeof(*urbp));
+
+ urbp->inserttime = jiffies;
+ urbp->fsbrtime = jiffies;
+ urbp->urb = urb;
+
+ INIT_LIST_HEAD(&urbp->td_list);
+ INIT_LIST_HEAD(&urbp->queue_list);
+ INIT_LIST_HEAD(&urbp->urb_list);
+
+ list_add_tail(&urbp->urb_list, &uhci->urb_list);
+
+ urb->hcpriv = urbp;
+
+ return urbp;
+}
+
+static void uhci_add_td_to_urb(struct urb *urb, struct uhci_td *td)
+{
+ struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+
+ td->urb = urb;
+
+ list_add_tail(&td->list, &urbp->td_list);
+}
+
+static void uhci_remove_td_from_urb(struct uhci_td *td)
+{
+ if (list_empty(&td->list))
+ return;
+
+ list_del_init(&td->list);
+
+ td->urb = NULL;
+}
+
+static void uhci_destroy_urb_priv(struct uhci_hcd *uhci, struct urb *urb)
+{
+ struct uhci_td *td, *tmp;
+ struct urb_priv *urbp;
+
+ urbp = (struct urb_priv *)urb->hcpriv;
+ if (!urbp)
+ return;
+
+ if (!list_empty(&urbp->urb_list))
+ dev_warn(uhci_dev(uhci), "urb %p still on uhci->urb_list "
+ "or uhci->remove_list!\n", urb);
+
+ uhci_get_current_frame_number(uhci);
+ if (uhci->frame_number + uhci->is_stopped != uhci->td_remove_age) {
+ uhci_free_pending_tds(uhci);
+ uhci->td_remove_age = uhci->frame_number;
+ }
+
+ /* Check to see if the remove list is empty. Set the IOC bit */
+ /* to force an interrupt so we can remove the TD's*/
+ if (list_empty(&uhci->td_remove_list))
+ uhci_set_next_interrupt(uhci);
+
+ list_for_each_entry_safe(td, tmp, &urbp->td_list, list) {
+ uhci_remove_td_from_urb(td);
+ uhci_remove_td(uhci, td);
+ list_add(&td->remove_list, &uhci->td_remove_list);
+ }
+
+ urb->hcpriv = NULL;
+ kmem_cache_free(uhci_up_cachep, urbp);
+}
+
+static void uhci_inc_fsbr(struct uhci_hcd *uhci, struct urb *urb)
+{
+ struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+
+ if ((!(urb->transfer_flags & URB_NO_FSBR)) && !urbp->fsbr) {
+ urbp->fsbr = 1;
+ if (!uhci->fsbr++ && !uhci->fsbrtimeout)
+ uhci->skel_term_qh->link = cpu_to_le32(uhci->skel_fs_control_qh->dma_handle) | UHCI_PTR_QH;
+ }
+}
+
+static void uhci_dec_fsbr(struct uhci_hcd *uhci, struct urb *urb)
+{
+ struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+
+ if ((!(urb->transfer_flags & URB_NO_FSBR)) && urbp->fsbr) {
+ urbp->fsbr = 0;
+ if (!--uhci->fsbr)
+ uhci->fsbrtimeout = jiffies + FSBR_DELAY;
+ }
+}
+
+/*
+ * Map status to standard result codes
+ *
+ * <status> is (td_status(td) & 0xF60000), a.k.a.
+ * uhci_status_bits(td_status(td)).
+ * Note: <status> does not include the TD_CTRL_NAK bit.
+ * <dir_out> is True for output TDs and False for input TDs.
+ */
+static int uhci_map_status(int status, int dir_out)
+{
+ if (!status)
+ return 0;
+ if (status & TD_CTRL_BITSTUFF) /* Bitstuff error */
+ return -EPROTO;
+ if (status & TD_CTRL_CRCTIMEO) { /* CRC/Timeout */
+ if (dir_out)
+ return -EPROTO;
+ else
+ return -EILSEQ;
+ }
+ if (status & TD_CTRL_BABBLE) /* Babble */
+ return -EOVERFLOW;
+ if (status & TD_CTRL_DBUFERR) /* Buffer error */
+ return -ENOSR;
+ if (status & TD_CTRL_STALLED) /* Stalled */
+ return -EPIPE;
+ WARN_ON(status & TD_CTRL_ACTIVE); /* Active */
+ return 0;
+}
+
+/*
+ * Control transfers
+ */
+static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct urb *eurb)
+{
+ struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+ struct uhci_td *td;
+ struct uhci_qh *qh, *skelqh;
+ unsigned long destination, status;
+ int maxsze = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe));
+ int len = urb->transfer_buffer_length;
+ dma_addr_t data = urb->transfer_dma;
+
+ /* The "pipe" thing contains the destination in bits 8--18 */
+ destination = (urb->pipe & PIPE_DEVEP_MASK) | USB_PID_SETUP;
+
+ /* 3 errors */
+ status = TD_CTRL_ACTIVE | uhci_maxerr(3);
+ if (urb->dev->speed == USB_SPEED_LOW)
+ status |= TD_CTRL_LS;
+
+ /*
+ * Build the TD for the control request setup packet
+ */
+ td = uhci_alloc_td(uhci, urb->dev);
+ if (!td)
+ return -ENOMEM;
+
+ uhci_add_td_to_urb(urb, td);
+ uhci_fill_td(td, status, destination | uhci_explen(7),
+ urb->setup_dma);
+
+ /*
+ * If direction is "send", change the packet ID from SETUP (0x2D)
+ * to OUT (0xE1). Else change it from SETUP to IN (0x69) and
+ * set Short Packet Detect (SPD) for all data packets.
+ */
+ if (usb_pipeout(urb->pipe))
+ destination ^= (USB_PID_SETUP ^ USB_PID_OUT);
+ else {
+ destination ^= (USB_PID_SETUP ^ USB_PID_IN);
+ status |= TD_CTRL_SPD;
+ }
+
+ /*
+ * Build the DATA TD's
+ */
+ while (len > 0) {
+ int pktsze = len;
+
+ if (pktsze > maxsze)
+ pktsze = maxsze;
+
+ td = uhci_alloc_td(uhci, urb->dev);
+ if (!td)
+ return -ENOMEM;
+
+ /* Alternate Data0/1 (start with Data1) */
+ destination ^= TD_TOKEN_TOGGLE;
+
+ uhci_add_td_to_urb(urb, td);
+ uhci_fill_td(td, status, destination | uhci_explen(pktsze - 1),
+ data);
+
+ data += pktsze;
+ len -= pktsze;
+ }
+
+ /*
+ * Build the final TD for control status
+ */
+ td = uhci_alloc_td(uhci, urb->dev);
+ if (!td)
+ return -ENOMEM;
+
+ /*
+ * It's IN if the pipe is an output pipe or we're not expecting
+ * data back.
+ */
+ destination &= ~TD_TOKEN_PID_MASK;
+ if (usb_pipeout(urb->pipe) || !urb->transfer_buffer_length)
+ destination |= USB_PID_IN;
+ else
+ destination |= USB_PID_OUT;
+
+ destination |= TD_TOKEN_TOGGLE; /* End in Data1 */
+
+ status &= ~TD_CTRL_SPD;
+
+ uhci_add_td_to_urb(urb, td);
+ uhci_fill_td(td, status | TD_CTRL_IOC,
+ destination | uhci_explen(UHCI_NULL_DATA_SIZE), 0);
+
+ qh = uhci_alloc_qh(uhci, urb->dev);
+ if (!qh)
+ return -ENOMEM;
+
+ urbp->qh = qh;
+ qh->urbp = urbp;
+
+ uhci_insert_tds_in_qh(qh, urb, UHCI_PTR_BREADTH);
+
+ /* Low-speed transfers get a different queue, and won't hog the bus.
+ * Also, some devices enumerate better without FSBR; the easiest way
+ * to do that is to put URBs on the low-speed queue while the device
+ * is in the DEFAULT state. */
+ if (urb->dev->speed == USB_SPEED_LOW ||
+ urb->dev->state == USB_STATE_DEFAULT)
+ skelqh = uhci->skel_ls_control_qh;
+ else {
+ skelqh = uhci->skel_fs_control_qh;
+ uhci_inc_fsbr(uhci, urb);
+ }
+
+ if (eurb)
+ uhci_append_queued_urb(uhci, eurb, urb);
+ else
+ uhci_insert_qh(uhci, skelqh, urb);
+
+ return -EINPROGRESS;
+}
+
+/*
+ * If control-IN transfer was short, the status packet wasn't sent.
+ * This routine changes the element pointer in the QH to point at the
+ * status TD. It's safe to do this even while the QH is live, because
+ * the hardware only updates the element pointer following a successful
+ * transfer. The inactive TD for the short packet won't cause an update,
+ * so the pointer won't get overwritten. The next time the controller
+ * sees this QH, it will send the status packet.
+ */
+static int usb_control_retrigger_status(struct uhci_hcd *uhci, struct urb *urb)
+{
+ struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+ struct uhci_td *td;
+
+ urbp->short_control_packet = 1;
+
+ td = list_entry(urbp->td_list.prev, struct uhci_td, list);
+ urbp->qh->element = cpu_to_le32(td->dma_handle);
+
+ return -EINPROGRESS;
+}
+
+
+static int uhci_result_control(struct uhci_hcd *uhci, struct urb *urb)
+{
+ struct list_head *tmp, *head;
+ struct urb_priv *urbp = urb->hcpriv;
+ struct uhci_td *td;
+ unsigned int status;
+ int ret = 0;
+
+ if (list_empty(&urbp->td_list))
+ return -EINVAL;
+
+ head = &urbp->td_list;
+
+ if (urbp->short_control_packet) {
+ tmp = head->prev;
+ goto status_stage;
+ }
+
+ tmp = head->next;
+ td = list_entry(tmp, struct uhci_td, list);
+
+ /* The first TD is the SETUP stage, check the status, but skip */
+ /* the count */
+ status = uhci_status_bits(td_status(td));
+ if (status & TD_CTRL_ACTIVE)
+ return -EINPROGRESS;
+
+ if (status)
+ goto td_error;
+
+ urb->actual_length = 0;
+
+ /* The rest of the TD's (but the last) are data */
+ tmp = tmp->next;
+ while (tmp != head && tmp->next != head) {
+ unsigned int ctrlstat;
+
+ td = list_entry(tmp, struct uhci_td, list);
+ tmp = tmp->next;
+
+ ctrlstat = td_status(td);
+ status = uhci_status_bits(ctrlstat);
+ if (status & TD_CTRL_ACTIVE)
+ return -EINPROGRESS;
+
+ urb->actual_length += uhci_actual_length(ctrlstat);
+
+ if (status)
+ goto td_error;
+
+ /* Check to see if we received a short packet */
+ if (uhci_actual_length(ctrlstat) <
+ uhci_expected_length(td_token(td))) {
+ if (urb->transfer_flags & URB_SHORT_NOT_OK) {
+ ret = -EREMOTEIO;
+ goto err;
+ }
+
+ if (uhci_packetid(td_token(td)) == USB_PID_IN)
+ return usb_control_retrigger_status(uhci, urb);
+ else
+ return 0;
+ }
+ }
+
+status_stage:
+ td = list_entry(tmp, struct uhci_td, list);
+
+ /* Control status stage */
+ status = td_status(td);
+
+#ifdef I_HAVE_BUGGY_APC_BACKUPS
+ /* APC BackUPS Pro kludge */
+ /* It tries to send all of the descriptor instead of the amount */
+ /* we requested */
+ if (status & TD_CTRL_IOC && /* IOC is masked out by uhci_status_bits */
+ status & TD_CTRL_ACTIVE &&
+ status & TD_CTRL_NAK)
+ return 0;
+#endif
+
+ status = uhci_status_bits(status);
+ if (status & TD_CTRL_ACTIVE)
+ return -EINPROGRESS;
+
+ if (status)
+ goto td_error;
+
+ return 0;
+
+td_error:
+ ret = uhci_map_status(status, uhci_packetout(td_token(td)));
+
+err:
+ if ((debug == 1 && ret != -EPIPE) || debug > 1) {
+ /* Some debugging code */
+ dev_dbg(uhci_dev(uhci), "%s: failed with status %x\n",
+ __FUNCTION__, status);
+
+ if (errbuf) {
+ /* Print the chain for debugging purposes */
+ uhci_show_qh(urbp->qh, errbuf, ERRBUF_LEN, 0);
+
+ lprintk(errbuf);
+ }
+ }
+
+ return ret;
+}
+
+/*
+ * Common submit for bulk and interrupt
+ */
+static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, struct urb *eurb, struct uhci_qh *skelqh)
+{
+ struct uhci_td *td;
+ struct uhci_qh *qh;
+ unsigned long destination, status;
+ int maxsze = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe));
+ int len = urb->transfer_buffer_length;
+ struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+ dma_addr_t data = urb->transfer_dma;
+
+ if (len < 0)
+ return -EINVAL;
+
+ /* The "pipe" thing contains the destination in bits 8--18 */
+ destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe);
+
+ status = uhci_maxerr(3) | TD_CTRL_ACTIVE;
+ if (urb->dev->speed == USB_SPEED_LOW)
+ status |= TD_CTRL_LS;
+ if (usb_pipein(urb->pipe))
+ status |= TD_CTRL_SPD;
+
+ /*
+ * Build the DATA TD's
+ */
+ do { /* Allow zero length packets */
+ int pktsze = maxsze;
+
+ if (pktsze >= len) {
+ pktsze = len;
+ if (!(urb->transfer_flags & URB_SHORT_NOT_OK))
+ status &= ~TD_CTRL_SPD;
+ }
+
+ td = uhci_alloc_td(uhci, urb->dev);
+ if (!td)
+ return -ENOMEM;
+
+ uhci_add_td_to_urb(urb, td);
+ uhci_fill_td(td, status, destination | uhci_explen(pktsze - 1) |
+ (usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe),
+ usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE_SHIFT),
+ data);
+
+ data += pktsze;
+ len -= maxsze;
+
+ usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe),
+ usb_pipeout(urb->pipe));
+ } while (len > 0);
+
+ /*
+ * URB_ZERO_PACKET means adding a 0-length packet, if direction
+ * is OUT and the transfer_length was an exact multiple of maxsze,
+ * hence (len = transfer_length - N * maxsze) == 0
+ * however, if transfer_length == 0, the zero packet was already
+ * prepared above.
+ */
+ if (usb_pipeout(urb->pipe) && (urb->transfer_flags & URB_ZERO_PACKET) &&
+ !len && urb->transfer_buffer_length) {
+ td = uhci_alloc_td(uhci, urb->dev);
+ if (!td)
+ return -ENOMEM;
+
+ uhci_add_td_to_urb(urb, td);
+ uhci_fill_td(td, status, destination | uhci_explen(UHCI_NULL_DATA_SIZE) |
+ (usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe),
+ usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE_SHIFT),
+ data);
+
+ usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe),
+ usb_pipeout(urb->pipe));
+ }
+
+ /* Set the interrupt-on-completion flag on the last packet.
+ * A more-or-less typical 4 KB URB (= size of one memory page)
+ * will require about 3 ms to transfer; that's a little on the
+ * fast side but not enough to justify delaying an interrupt
+ * more than 2 or 3 URBs, so we will ignore the URB_NO_INTERRUPT
+ * flag setting. */
+ td->status |= cpu_to_le32(TD_CTRL_IOC);
+
+ qh = uhci_alloc_qh(uhci, urb->dev);
+ if (!qh)
+ return -ENOMEM;
+
+ urbp->qh = qh;
+ qh->urbp = urbp;
+
+ /* Always breadth first */
+ uhci_insert_tds_in_qh(qh, urb, UHCI_PTR_BREADTH);
+
+ if (eurb)
+ uhci_append_queued_urb(uhci, eurb, urb);
+ else
+ uhci_insert_qh(uhci, skelqh, urb);
+
+ return -EINPROGRESS;
+}
+
+/*
+ * Common result for bulk and interrupt
+ */
+static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb)
+{
+ struct urb_priv *urbp = urb->hcpriv;
+ struct uhci_td *td;
+ unsigned int status = 0;
+ int ret = 0;
+
+ urb->actual_length = 0;
+
+ list_for_each_entry(td, &urbp->td_list, list) {
+ unsigned int ctrlstat = td_status(td);
+
+ status = uhci_status_bits(ctrlstat);
+ if (status & TD_CTRL_ACTIVE)
+ return -EINPROGRESS;
+
+ urb->actual_length += uhci_actual_length(ctrlstat);
+
+ if (status)
+ goto td_error;
+
+ if (uhci_actual_length(ctrlstat) <
+ uhci_expected_length(td_token(td))) {
+ if (urb->transfer_flags & URB_SHORT_NOT_OK) {
+ ret = -EREMOTEIO;
+ goto err;
+ } else
+ return 0;
+ }
+ }
+
+ return 0;
+
+td_error:
+ ret = uhci_map_status(status, uhci_packetout(td_token(td)));
+
+err:
+ /*
+ * Enable this chunk of code if you want to see some more debugging.
+ * But be careful, it has the tendancy to starve out khubd and prevent
+ * disconnects from happening successfully if you have a slow debug
+ * log interface (like a serial console.
+ */
+#if 0
+ if ((debug == 1 && ret != -EPIPE) || debug > 1) {
+ /* Some debugging code */
+ dev_dbg(uhci_dev(uhci), "%s: failed with status %x\n",
+ __FUNCTION__, status);
+
+ if (errbuf) {
+ /* Print the chain for debugging purposes */
+ uhci_show_qh(urbp->qh, errbuf, ERRBUF_LEN, 0);
+
+ lprintk(errbuf);
+ }
+ }
+#endif
+ return ret;
+}
+
+static inline int uhci_submit_bulk(struct uhci_hcd *uhci, struct urb *urb, struct urb *eurb)
+{
+ int ret;
+
+ /* Can't have low-speed bulk transfers */
+ if (urb->dev->speed == USB_SPEED_LOW)
+ return -EINVAL;
+
+ ret = uhci_submit_common(uhci, urb, eurb, uhci->skel_bulk_qh);
+ if (ret == -EINPROGRESS)
+ uhci_inc_fsbr(uhci, urb);
+
+ return ret;
+}
+
+static inline int uhci_submit_interrupt(struct uhci_hcd *uhci, struct urb *urb, struct urb *eurb)
+{
+ /* USB 1.1 interrupt transfers only involve one packet per interval;
+ * that's the uhci_submit_common() "breadth first" policy. Drivers
+ * can submit urbs of any length, but longer ones might need many
+ * intervals to complete.
+ */
+ return uhci_submit_common(uhci, urb, eurb, uhci->skelqh[__interval_to_skel(urb->interval)]);
+}
+
+/*
+ * Isochronous transfers
+ */
+static int isochronous_find_limits(struct uhci_hcd *uhci, struct urb *urb, unsigned int *start, unsigned int *end)
+{
+ struct urb *last_urb = NULL;
+ struct urb_priv *up;
+ int ret = 0;
+
+ list_for_each_entry(up, &uhci->urb_list, urb_list) {
+ struct urb *u = up->urb;
+
+ /* look for pending URB's with identical pipe handle */
+ if ((urb->pipe == u->pipe) && (urb->dev == u->dev) &&
+ (u->status == -EINPROGRESS) && (u != urb)) {
+ if (!last_urb)
+ *start = u->start_frame;
+ last_urb = u;
+ }
+ }
+
+ if (last_urb) {
+ *end = (last_urb->start_frame + last_urb->number_of_packets *
+ last_urb->interval) & (UHCI_NUMFRAMES-1);
+ ret = 0;
+ } else
+ ret = -1; /* no previous urb found */
+
+ return ret;
+}
+
+static int isochronous_find_start(struct uhci_hcd *uhci, struct urb *urb)
+{
+ int limits;
+ unsigned int start = 0, end = 0;
+
+ if (urb->number_of_packets > 900) /* 900? Why? */
+ return -EFBIG;
+
+ limits = isochronous_find_limits(uhci, urb, &start, &end);
+
+ if (urb->transfer_flags & URB_ISO_ASAP) {
+ if (limits) {
+ uhci_get_current_frame_number(uhci);
+ urb->start_frame = (uhci->frame_number + 10)
+ & (UHCI_NUMFRAMES - 1);
+ } else
+ urb->start_frame = end;
+ } else {
+ urb->start_frame &= (UHCI_NUMFRAMES - 1);
+ /* FIXME: Sanity check */
+ }
+
+ return 0;
+}
+
+/*
+ * Isochronous transfers
+ */
+static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb)
+{
+ struct uhci_td *td;
+ int i, ret, frame;
+ int status, destination;
+
+ status = TD_CTRL_ACTIVE | TD_CTRL_IOS;
+ destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe);
+
+ ret = isochronous_find_start(uhci, urb);
+ if (ret)
+ return ret;
+
+ frame = urb->start_frame;
+ for (i = 0; i < urb->number_of_packets; i++, frame += urb->interval) {
+ if (!urb->iso_frame_desc[i].length)
+ continue;
+
+ td = uhci_alloc_td(uhci, urb->dev);
+ if (!td)
+ return -ENOMEM;
+
+ uhci_add_td_to_urb(urb, td);
+ uhci_fill_td(td, status, destination | uhci_explen(urb->iso_frame_desc[i].length - 1),
+ urb->transfer_dma + urb->iso_frame_desc[i].offset);
+
+ if (i + 1 >= urb->number_of_packets)
+ td->status |= cpu_to_le32(TD_CTRL_IOC);
+
+ uhci_insert_td_frame_list(uhci, td, frame);
+ }
+
+ return -EINPROGRESS;
+}
+
+static int uhci_result_isochronous(struct uhci_hcd *uhci, struct urb *urb)
+{
+ struct uhci_td *td;
+ struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+ int status;
+ int i, ret = 0;
+
+ urb->actual_length = 0;
+
+ i = 0;
+ list_for_each_entry(td, &urbp->td_list, list) {
+ int actlength;
+ unsigned int ctrlstat = td_status(td);
+
+ if (ctrlstat & TD_CTRL_ACTIVE)
+ return -EINPROGRESS;
+
+ actlength = uhci_actual_length(ctrlstat);
+ urb->iso_frame_desc[i].actual_length = actlength;
+ urb->actual_length += actlength;
+
+ status = uhci_map_status(uhci_status_bits(ctrlstat),
+ usb_pipeout(urb->pipe));
+ urb->iso_frame_desc[i].status = status;
+ if (status) {
+ urb->error_count++;
+ ret = status;
+ }
+
+ i++;
+ }
+
+ return ret;
+}
+
+static struct urb *uhci_find_urb_ep(struct uhci_hcd *uhci, struct urb *urb)
+{
+ struct urb_priv *up;
+
+ /* We don't match Isoc transfers since they are special */
+ if (usb_pipeisoc(urb->pipe))
+ return NULL;
+
+ list_for_each_entry(up, &uhci->urb_list, urb_list) {
+ struct urb *u = up->urb;
+
+ if (u->dev == urb->dev && u->status == -EINPROGRESS) {
+ /* For control, ignore the direction */
+ if (usb_pipecontrol(urb->pipe) &&
+ (u->pipe & ~USB_DIR_IN) == (urb->pipe & ~USB_DIR_IN))
+ return u;
+ else if (u->pipe == urb->pipe)
+ return u;
+ }
+ }
+
+ return NULL;
+}
+
+static int uhci_urb_enqueue(struct usb_hcd *hcd,
+ struct usb_host_endpoint *ep,
+ struct urb *urb, int mem_flags)
+{
+ int ret;
+ struct uhci_hcd *uhci = hcd_to_uhci(hcd);
+ unsigned long flags;
+ struct urb *eurb;
+ int bustime;
+
+ spin_lock_irqsave(&uhci->lock, flags);
+
+ ret = urb->status;
+ if (ret != -EINPROGRESS) /* URB already unlinked! */
+ goto out;
+
+ eurb = uhci_find_urb_ep(uhci, urb);
+
+ if (!uhci_alloc_urb_priv(uhci, urb)) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ switch (usb_pipetype(urb->pipe)) {
+ case PIPE_CONTROL:
+ ret = uhci_submit_control(uhci, urb, eurb);
+ break;
+ case PIPE_INTERRUPT:
+ if (!eurb) {
+ bustime = usb_check_bandwidth(urb->dev, urb);
+ if (bustime < 0)
+ ret = bustime;
+ else {
+ ret = uhci_submit_interrupt(uhci, urb, eurb);
+ if (ret == -EINPROGRESS)
+ usb_claim_bandwidth(urb->dev, urb, bustime, 0);
+ }
+ } else { /* inherit from parent */
+ urb->bandwidth = eurb->bandwidth;
+ ret = uhci_submit_interrupt(uhci, urb, eurb);
+ }
+ break;
+ case PIPE_BULK:
+ ret = uhci_submit_bulk(uhci, urb, eurb);
+ break;
+ case PIPE_ISOCHRONOUS:
+ bustime = usb_check_bandwidth(urb->dev, urb);
+ if (bustime < 0) {
+ ret = bustime;
+ break;
+ }
+
+ ret = uhci_submit_isochronous(uhci, urb);
+ if (ret == -EINPROGRESS)
+ usb_claim_bandwidth(urb->dev, urb, bustime, 1);
+ break;
+ }
+
+ if (ret != -EINPROGRESS) {
+ /* Submit failed, so delete it from the urb_list */
+ struct urb_priv *urbp = urb->hcpriv;
+
+ list_del_init(&urbp->urb_list);
+ uhci_destroy_urb_priv(uhci, urb);
+ } else
+ ret = 0;
+
+out:
+ spin_unlock_irqrestore(&uhci->lock, flags);
+ return ret;
+}
+
+/*
+ * Return the result of a transfer
+ */
+static void uhci_transfer_result(struct uhci_hcd *uhci, struct urb *urb)
+{
+ int ret = -EINPROGRESS;
+ struct urb_priv *urbp;
+
+ spin_lock(&urb->lock);
+
+ urbp = (struct urb_priv *)urb->hcpriv;
+
+ if (urb->status != -EINPROGRESS) /* URB already dequeued */
+ goto out;
+
+ switch (usb_pipetype(urb->pipe)) {
+ case PIPE_CONTROL:
+ ret = uhci_result_control(uhci, urb);
+ break;
+ case PIPE_BULK:
+ case PIPE_INTERRUPT:
+ ret = uhci_result_common(uhci, urb);
+ break;
+ case PIPE_ISOCHRONOUS:
+ ret = uhci_result_isochronous(uhci, urb);
+ break;
+ }
+
+ if (ret == -EINPROGRESS)
+ goto out;
+ urb->status = ret;
+
+ switch (usb_pipetype(urb->pipe)) {
+ case PIPE_CONTROL:
+ case PIPE_BULK:
+ case PIPE_ISOCHRONOUS:
+ /* Release bandwidth for Interrupt or Isoc. transfers */
+ if (urb->bandwidth)
+ usb_release_bandwidth(urb->dev, urb, 1);
+ uhci_unlink_generic(uhci, urb);
+ break;
+ case PIPE_INTERRUPT:
+ /* Release bandwidth for Interrupt or Isoc. transfers */
+ /* Make sure we don't release if we have a queued URB */
+ if (list_empty(&urbp->queue_list) && urb->bandwidth)
+ usb_release_bandwidth(urb->dev, urb, 0);
+ else
+ /* bandwidth was passed on to queued URB, */
+ /* so don't let usb_unlink_urb() release it */
+ urb->bandwidth = 0;
+ uhci_unlink_generic(uhci, urb);
+ break;
+ default:
+ dev_info(uhci_dev(uhci), "%s: unknown pipe type %d "
+ "for urb %p\n",
+ __FUNCTION__, usb_pipetype(urb->pipe), urb);
+ }
+
+ /* Move it from uhci->urb_list to uhci->complete_list */
+ uhci_moveto_complete(uhci, urbp);
+
+out:
+ spin_unlock(&urb->lock);
+}
+
+static void uhci_unlink_generic(struct uhci_hcd *uhci, struct urb *urb)
+{
+ struct list_head *head;
+ struct uhci_td *td;
+ struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+ int prevactive = 0;
+
+ uhci_dec_fsbr(uhci, urb); /* Safe since it checks */
+
+ /*
+ * Now we need to find out what the last successful toggle was
+ * so we can update the local data toggle for the next transfer
+ *
+ * There are 2 ways the last successful completed TD is found:
+ *
+ * 1) The TD is NOT active and the actual length < expected length
+ * 2) The TD is NOT active and it's the last TD in the chain
+ *
+ * and a third way the first uncompleted TD is found:
+ *
+ * 3) The TD is active and the previous TD is NOT active
+ *
+ * Control and Isochronous ignore the toggle, so this is safe
+ * for all types
+ *
+ * FIXME: The toggle fixups won't be 100% reliable until we
+ * change over to using a single queue for each endpoint and
+ * stop the queue before unlinking.
+ */
+ head = &urbp->td_list;
+ list_for_each_entry(td, head, list) {
+ unsigned int ctrlstat = td_status(td);
+
+ if (!(ctrlstat & TD_CTRL_ACTIVE) &&
+ (uhci_actual_length(ctrlstat) <
+ uhci_expected_length(td_token(td)) ||
+ td->list.next == head))
+ usb_settoggle(urb->dev, uhci_endpoint(td_token(td)),
+ uhci_packetout(td_token(td)),
+ uhci_toggle(td_token(td)) ^ 1);
+ else if ((ctrlstat & TD_CTRL_ACTIVE) && !prevactive)
+ usb_settoggle(urb->dev, uhci_endpoint(td_token(td)),
+ uhci_packetout(td_token(td)),
+ uhci_toggle(td_token(td)));
+
+ prevactive = ctrlstat & TD_CTRL_ACTIVE;
+ }
+
+ uhci_delete_queued_urb(uhci, urb);
+
+ /* The interrupt loop will reclaim the QH's */
+ uhci_remove_qh(uhci, urbp->qh);
+ urbp->qh = NULL;
+}
+
+static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
+{
+ struct uhci_hcd *uhci = hcd_to_uhci(hcd);
+ unsigned long flags;
+ struct urb_priv *urbp;
+
+ spin_lock_irqsave(&uhci->lock, flags);
+ urbp = urb->hcpriv;
+ if (!urbp) /* URB was never linked! */
+ goto done;
+ list_del_init(&urbp->urb_list);
+
+ uhci_unlink_generic(uhci, urb);
+
+ uhci_get_current_frame_number(uhci);
+ if (uhci->frame_number + uhci->is_stopped != uhci->urb_remove_age) {
+ uhci_remove_pending_urbps(uhci);
+ uhci->urb_remove_age = uhci->frame_number;
+ }
+
+ /* If we're the first, set the next interrupt bit */
+ if (list_empty(&uhci->urb_remove_list))
+ uhci_set_next_interrupt(uhci);
+ list_add_tail(&urbp->urb_list, &uhci->urb_remove_list);
+
+done:
+ spin_unlock_irqrestore(&uhci->lock, flags);
+ return 0;
+}
+
+static int uhci_fsbr_timeout(struct uhci_hcd *uhci, struct urb *urb)
+{
+ struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+ struct list_head *head;
+ struct uhci_td *td;
+ int count = 0;
+
+ uhci_dec_fsbr(uhci, urb);
+
+ urbp->fsbr_timeout = 1;
+
+ /*
+ * Ideally we would want to fix qh->element as well, but it's
+ * read/write by the HC, so that can introduce a race. It's not
+ * really worth the hassle
+ */
+
+ head = &urbp->td_list;
+ 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
+ * make sure it doesn't hog the bandwidth
+ */
+ if (td->list.next != head && (count % DEPTH_INTERVAL) ==
+ (DEPTH_INTERVAL - 1))
+ td->link |= UHCI_PTR_DEPTH;
+
+ count++;
+ }
+
+ return 0;
+}
+
+static void uhci_free_pending_qhs(struct uhci_hcd *uhci)
+{
+ struct uhci_qh *qh, *tmp;
+
+ list_for_each_entry_safe(qh, tmp, &uhci->qh_remove_list, remove_list) {
+ list_del_init(&qh->remove_list);
+
+ uhci_free_qh(uhci, qh);
+ }
+}
+
+static void uhci_free_pending_tds(struct uhci_hcd *uhci)
+{
+ struct uhci_td *td, *tmp;
+
+ list_for_each_entry_safe(td, tmp, &uhci->td_remove_list, remove_list) {
+ list_del_init(&td->remove_list);
+
+ uhci_free_td(uhci, td);
+ }
+}
+
+static void
+uhci_finish_urb(struct usb_hcd *hcd, struct urb *urb, struct pt_regs *regs)
+__releases(uhci->lock)
+__acquires(uhci->lock)
+{
+ struct uhci_hcd *uhci = hcd_to_uhci(hcd);
+
+ uhci_destroy_urb_priv(uhci, urb);
+
+ spin_unlock(&uhci->lock);
+ usb_hcd_giveback_urb(hcd, urb, regs);
+ spin_lock(&uhci->lock);
+}
+
+static void uhci_finish_completion(struct uhci_hcd *uhci, struct pt_regs *regs)
+{
+ struct urb_priv *urbp, *tmp;
+
+ list_for_each_entry_safe(urbp, tmp, &uhci->complete_list, urb_list) {
+ struct urb *urb = urbp->urb;
+
+ list_del_init(&urbp->urb_list);
+ uhci_finish_urb(uhci_to_hcd(uhci), urb, regs);
+ }
+}
+
+static void uhci_remove_pending_urbps(struct uhci_hcd *uhci)
+{
+
+ /* Splice the urb_remove_list onto the end of the complete_list */
+ list_splice_init(&uhci->urb_remove_list, uhci->complete_list.prev);
+}
+
+/* Process events in the schedule, but only in one thread at a time */
+static void uhci_scan_schedule(struct uhci_hcd *uhci, struct pt_regs *regs)
+{
+ struct urb_priv *urbp, *tmp;
+
+ /* Don't allow re-entrant calls */
+ if (uhci->scan_in_progress) {
+ uhci->need_rescan = 1;
+ return;
+ }
+ uhci->scan_in_progress = 1;
+ rescan:
+ uhci->need_rescan = 0;
+
+ uhci_get_current_frame_number(uhci);
+
+ if (uhci->frame_number + uhci->is_stopped != uhci->qh_remove_age)
+ uhci_free_pending_qhs(uhci);
+ if (uhci->frame_number + uhci->is_stopped != uhci->td_remove_age)
+ uhci_free_pending_tds(uhci);
+ if (uhci->frame_number + uhci->is_stopped != uhci->urb_remove_age)
+ uhci_remove_pending_urbps(uhci);
+
+ /* Walk the list of pending URBs to see which ones completed
+ * (must be _safe because uhci_transfer_result() dequeues URBs) */
+ list_for_each_entry_safe(urbp, tmp, &uhci->urb_list, urb_list) {
+ struct urb *urb = urbp->urb;
+
+ /* Checks the status and does all of the magic necessary */
+ uhci_transfer_result(uhci, urb);
+ }
+ uhci_finish_completion(uhci, regs);
+
+ /* If the controller is stopped, we can finish these off right now */
+ if (uhci->is_stopped) {
+ uhci_free_pending_qhs(uhci);
+ uhci_free_pending_tds(uhci);
+ uhci_remove_pending_urbps(uhci);
+ }
+
+ if (uhci->need_rescan)
+ goto rescan;
+ uhci->scan_in_progress = 0;
+
+ if (list_empty(&uhci->urb_remove_list) &&
+ list_empty(&uhci->td_remove_list) &&
+ list_empty(&uhci->qh_remove_list))
+ uhci_clear_next_interrupt(uhci);
+ else
+ uhci_set_next_interrupt(uhci);
+
+ /* Wake up anyone waiting for an URB to complete */
+ wake_up_all(&uhci->waitqh);
+}
diff --git a/drivers/usb/image/Kconfig b/drivers/usb/image/Kconfig
index df508cb14c89d..95ce703110d27 100644
--- a/drivers/usb/image/Kconfig
+++ b/drivers/usb/image/Kconfig
@@ -28,14 +28,3 @@ config USB_MICROTEK
The scanner will appear as a scsi generic device to the rest
of the system. Scsi support is required.
This driver can be compiled as a module, called microtek.
-
-config USB_HPUSBSCSI
- tristate "HP53xx USB scanner support"
- depends on USB && SCSI && BROKEN
- help
- Say Y here if you want support for the HP 53xx series of scanners
- and the Minolta Scan Dual.
- The scanner will be accessible as a SCSI device.
- Please note that recent versions of SANE use usbfs, not this driver.
- This can be compiled as a module, called hpusbscsi.
-
diff --git a/drivers/usb/image/Makefile b/drivers/usb/image/Makefile
index f01a73959c4e1..4148ae306352b 100644
--- a/drivers/usb/image/Makefile
+++ b/drivers/usb/image/Makefile
@@ -3,5 +3,4 @@
#
obj-$(CONFIG_USB_MDC800) += mdc800.o
-obj-$(CONFIG_USB_HPUSBSCSI) += hpusbscsi.o
obj-$(CONFIG_USB_MICROTEK) += microtek.o
diff --git a/drivers/usb/image/hpusbscsi.c b/drivers/usb/image/hpusbscsi.c
deleted file mode 100644
index 47a864b29f3d9..0000000000000
--- a/drivers/usb/image/hpusbscsi.c
+++ /dev/null
@@ -1,523 +0,0 @@
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/signal.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/smp_lock.h>
-#include <linux/usb.h>
-#include <asm/atomic.h>
-#include <linux/blkdev.h>
-#include "../../scsi/scsi.h"
-#include <scsi/scsi_host.h>
-
-#include "hpusbscsi.h"
-
-#define DEBUG(x...) \
- printk( KERN_DEBUG x )
-
-static char *states[]={"FREE", "BEGINNING", "WORKING", "ERROR", "WAIT", "PREMATURE"};
-
-#define TRACE_STATE printk(KERN_DEBUG"hpusbscsi->state = %s at line %d\n", states[hpusbscsi->state], __LINE__)
-
-static Scsi_Host_Template hpusbscsi_scsi_host_template = {
- .module = THIS_MODULE,
- .name = "hpusbscsi",
- .proc_name = "hpusbscsi",
- .queuecommand = hpusbscsi_scsi_queuecommand,
- .eh_abort_handler = hpusbscsi_scsi_abort,
- .eh_host_reset_handler = hpusbscsi_scsi_host_reset,
- .sg_tablesize = SG_ALL,
- .can_queue = 1,
- .this_id = -1,
- .cmd_per_lun = 1,
- .use_clustering = 1,
- .emulated = 1,
-};
-
-static int
-hpusbscsi_usb_probe(struct usb_interface *intf,
- const struct usb_device_id *id)
-{
- struct usb_device *dev = interface_to_usbdev(intf);
- struct usb_host_interface *altsetting = intf->cur_altsetting;
- struct hpusbscsi *new;
- int error = -ENOMEM;
- int i;
-
- if (altsetting->desc.bNumEndpoints != 3) {
- printk (KERN_ERR "Wrong number of endpoints\n");
- return -ENODEV;
- }
-
- new = kmalloc(sizeof(struct hpusbscsi), GFP_KERNEL);
- if (!new)
- return -ENOMEM;
- memset(new, 0, sizeof(struct hpusbscsi));
- new->dataurb = usb_alloc_urb(0, GFP_KERNEL);
- if (!new->dataurb)
- goto out_kfree;
- new->controlurb = usb_alloc_urb(0, GFP_KERNEL);
- if (!new->controlurb)
- goto out_free_dataurb;
-
- new->dev = dev;
- init_waitqueue_head(&new->pending);
- init_waitqueue_head(&new->deathrow);
-
- error = -ENODEV;
- for (i = 0; i < altsetting->desc.bNumEndpoints; i++) {
- if ((altsetting->endpoint[i].desc.
- bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
- USB_ENDPOINT_XFER_BULK) {
- if (altsetting->endpoint[i].desc.
- bEndpointAddress & USB_DIR_IN) {
- new->ep_in =
- altsetting->endpoint[i].desc.
- bEndpointAddress &
- USB_ENDPOINT_NUMBER_MASK;
- } else {
- new->ep_out =
- altsetting->endpoint[i].desc.
- bEndpointAddress &
- USB_ENDPOINT_NUMBER_MASK;
- }
- } else {
- new->ep_int =
- altsetting->endpoint[i].desc.
- bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
- new->interrupt_interval= altsetting->endpoint[i].desc.
- bInterval;
- }
- }
-
- /* build and submit an interrupt URB for status byte handling */
- usb_fill_int_urb(new->controlurb, new->dev,
- usb_rcvintpipe(new->dev, new->ep_int),
- &new->scsi_state_byte, 1,
- control_interrupt_callback,new,
- new->interrupt_interval);
-
- if (usb_submit_urb(new->controlurb, GFP_KERNEL) < 0)
- goto out_free_controlurb;
-
- /* In host->hostdata we store a pointer to desc */
- new->host = scsi_host_alloc(&hpusbscsi_scsi_host_template, sizeof(new));
- if (!new->host)
- goto out_kill_controlurb;
-
- new->host->hostdata[0] = (unsigned long)new;
- scsi_add_host(new->host, &intf->dev); /* XXX handle failure */
- scsi_scan_host(new->host);
-
- new->sense_command[0] = REQUEST_SENSE;
- new->sense_command[4] = HPUSBSCSI_SENSE_LENGTH;
-
- usb_set_intfdata(intf, new);
- return 0;
-
- out_kill_controlurb:
- usb_kill_urb(new->controlurb);
- out_free_controlurb:
- usb_free_urb(new->controlurb);
- out_free_dataurb:
- usb_free_urb(new->dataurb);
- out_kfree:
- kfree(new);
- return error;
-}
-
-static void
-hpusbscsi_usb_disconnect(struct usb_interface *intf)
-{
- struct hpusbscsi *desc = usb_get_intfdata(intf);
-
- usb_set_intfdata(intf, NULL);
-
- scsi_remove_host(desc->host);
- usb_kill_urb(desc->controlurb);
- scsi_host_put(desc->host);
-
- usb_free_urb(desc->controlurb);
- usb_free_urb(desc->dataurb);
- kfree(desc);
-}
-
-static struct usb_device_id hpusbscsi_usb_ids[] = {
- {USB_DEVICE (0x03f0, 0x0701)}, /* HP 53xx */
- {USB_DEVICE (0x03f0, 0x0801)}, /* HP 7400 */
- {USB_DEVICE (0x0638, 0x0268)}, /*iVina 1200U */
- {USB_DEVICE (0x0638, 0x026a)}, /*Scan Dual II */
- {USB_DEVICE (0x0638, 0x0A13)}, /*Avision AV600U */
- {USB_DEVICE (0x0638, 0x0A16)}, /*Avision DS610CU Scancopier */
- {USB_DEVICE (0x0638, 0x0A18)}, /*Avision AV600U Plus */
- {USB_DEVICE (0x0638, 0x0A23)}, /*Avision AV220 */
- {USB_DEVICE (0x0638, 0x0A24)}, /*Avision AV210 */
- {USB_DEVICE (0x0686, 0x4004)}, /*Minolta Elite II */
- {} /* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE (usb, hpusbscsi_usb_ids);
-MODULE_LICENSE("GPL");
-
-
-static struct usb_driver hpusbscsi_usb_driver = {
- .owner = THIS_MODULE,
- .name ="hpusbscsi",
- .probe =hpusbscsi_usb_probe,
- .disconnect =hpusbscsi_usb_disconnect,
- .id_table =hpusbscsi_usb_ids,
-};
-
-/* module initialisation */
-
-static int __init
-hpusbscsi_init (void)
-{
- return usb_register(&hpusbscsi_usb_driver);
-}
-
-static void __exit
-hpusbscsi_exit (void)
-{
- usb_deregister(&hpusbscsi_usb_driver);
-}
-
-module_init (hpusbscsi_init);
-module_exit (hpusbscsi_exit);
-
-static int hpusbscsi_scsi_queuecommand (Scsi_Cmnd *srb, scsi_callback callback)
-{
- struct hpusbscsi* hpusbscsi = (struct hpusbscsi*)(srb->device->host->hostdata[0]);
- usb_complete_t usb_callback;
- int res;
-
- /* we don't answer for anything but our single device on any faked host controller */
- if ( srb->device->lun || srb->device->id || srb->device->channel ) {
- if (callback) {
- srb->result = DID_BAD_TARGET;
- callback(srb);
- }
- goto out;
- }
-
- /* Now we need to decide which callback to give to the urb we send the command with */
-
- if (!srb->bufflen) {
- if (srb->cmnd[0] == REQUEST_SENSE){
- hpusbscsi->current_data_pipe = usb_rcvbulkpipe(hpusbscsi->dev, hpusbscsi->ep_in);
- usb_callback = request_sense_callback;
- } else {
- usb_callback = simple_command_callback;
- }
- } else {
- if (likely(srb->use_sg)) {
- usb_callback = scatter_gather_callback;
- hpusbscsi->fragment = 0;
- } else {
- usb_callback = simple_payload_callback;
- }
- /* Now we find out which direction data is to be transferred in */
- hpusbscsi->current_data_pipe = DIRECTION_IS_IN(srb->cmnd[0]) ?
- usb_rcvbulkpipe(hpusbscsi->dev, hpusbscsi->ep_in)
- :
- usb_sndbulkpipe(hpusbscsi->dev, hpusbscsi->ep_out)
- ;
- }
-
-
- TRACE_STATE;
-
- /* We zero the sense buffer to avoid confusing user space */
- memset(srb->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
-
- hpusbscsi->state = HP_STATE_BEGINNING;
- TRACE_STATE;
-
- /* We prepare the urb for writing out the scsi command */
- usb_fill_bulk_urb(
- hpusbscsi->dataurb,
- hpusbscsi->dev,
- usb_sndbulkpipe(hpusbscsi->dev,hpusbscsi->ep_out),
- srb->cmnd,
- srb->cmd_len,
- usb_callback,
- hpusbscsi
- );
- hpusbscsi->scallback = callback;
- hpusbscsi->srb = srb;
-
- res = usb_submit_urb(hpusbscsi->dataurb, GFP_ATOMIC);
- if (unlikely(res)) {
- hpusbscsi->state = HP_STATE_FREE;
- TRACE_STATE;
- if (likely(callback != NULL)) {
- srb->result = DID_ERROR;
- callback(srb);
- }
- }
-
-out:
- return 0;
-}
-
-static int hpusbscsi_scsi_host_reset (Scsi_Cmnd *srb)
-{
- struct hpusbscsi* hpusbscsi = (struct hpusbscsi*)(srb->device->host->hostdata[0]);
-
- printk(KERN_DEBUG"SCSI reset requested.\n");
- //usb_reset_device(hpusbscsi->dev);
- //printk(KERN_DEBUG"SCSI reset completed.\n");
- hpusbscsi->state = HP_STATE_FREE;
-
- return 0;
-}
-
-static int hpusbscsi_scsi_abort (Scsi_Cmnd *srb)
-{
- struct hpusbscsi* hpusbscsi = (struct hpusbscsi*)(srb->device->host->hostdata[0]);
- printk(KERN_DEBUG"Requested is canceled.\n");
-
- usb_kill_urb(hpusbscsi->dataurb);
- usb_kill_urb(hpusbscsi->controlurb);
- hpusbscsi->state = HP_STATE_FREE;
-
- return SCSI_ABORT_PENDING;
-}
-
-/* usb interrupt handlers - they are all running IN INTERRUPT ! */
-
-static void handle_usb_error (struct hpusbscsi *hpusbscsi)
-{
- if (likely(hpusbscsi->scallback != NULL)) {
- hpusbscsi->srb->result = DID_ERROR;
- hpusbscsi->scallback(hpusbscsi->srb);
- }
- hpusbscsi->state = HP_STATE_FREE;
-}
-
-static void control_interrupt_callback (struct urb *u, struct pt_regs *regs)
-{
- struct hpusbscsi * hpusbscsi = (struct hpusbscsi *)u->context;
- u8 scsi_state;
-
-DEBUG("Getting status byte %d \n",hpusbscsi->scsi_state_byte);
- if(unlikely(u->status < 0)) {
- if (likely(hpusbscsi->state != HP_STATE_FREE))
- handle_usb_error(hpusbscsi);
- if (u->status == -ECONNRESET || u->status == -ENOENT || u->status == -ESHUTDOWN)
- return;
- else
- goto resub;
- }
-
- scsi_state = hpusbscsi->scsi_state_byte;
- if (hpusbscsi->state != HP_STATE_ERROR) {
- hpusbscsi->srb->result &= SCSI_ERR_MASK;
- hpusbscsi->srb->result |= scsi_state;
- }
-
- if (scsi_state == CHECK_CONDITION << 1) {
- if (hpusbscsi->state == HP_STATE_WAIT) {
- issue_request_sense(hpusbscsi);
- } else {
- /* we request sense after an eventual data transfer */
- hpusbscsi->state = HP_STATE_ERROR;
- }
- }
-
- if (hpusbscsi->scallback != NULL && hpusbscsi->state == HP_STATE_WAIT && scsi_state != CHECK_CONDITION <<1 )
- /* we do a callback to the scsi layer if and only if all data has been transferred */
- hpusbscsi->scallback(hpusbscsi->srb);
-
- TRACE_STATE;
- switch (hpusbscsi->state) {
- case HP_STATE_WAIT:
- hpusbscsi->state = HP_STATE_FREE;
- TRACE_STATE;
- break;
- case HP_STATE_WORKING:
- case HP_STATE_BEGINNING:
- hpusbscsi->state = HP_STATE_PREMATURE;
- TRACE_STATE;
- break;
- case HP_STATE_ERROR:
- break;
- default:
- printk(KERN_ERR"hpusbscsi: Unexpected status report.\n");
- TRACE_STATE;
- hpusbscsi->state = HP_STATE_FREE;
- TRACE_STATE;
- break;
- }
-resub:
- usb_submit_urb(u, GFP_ATOMIC);
-}
-
-static void simple_command_callback(struct urb *u, struct pt_regs *regs)
-{
- struct hpusbscsi * hpusbscsi = (struct hpusbscsi *)u->context;
- if (unlikely(u->status<0)) {
- handle_usb_error(hpusbscsi);
- return;
- }
- TRACE_STATE;
- if (hpusbscsi->state != HP_STATE_PREMATURE) {
- TRACE_STATE;
- hpusbscsi->state = HP_STATE_WAIT;
- } else {
- if (likely(hpusbscsi->scallback != NULL))
- hpusbscsi->scallback(hpusbscsi->srb);
- hpusbscsi->state = HP_STATE_FREE;
- TRACE_STATE;
- }
-}
-
-static void scatter_gather_callback(struct urb *u, struct pt_regs *regs)
-{
- struct hpusbscsi * hpusbscsi = (struct hpusbscsi *)u->context;
- struct scatterlist *sg = hpusbscsi->srb->buffer;
- usb_complete_t callback;
- int res;
-
- DEBUG("Going through scatter/gather\n");
- if (unlikely(u->status < 0)) {
- handle_usb_error(hpusbscsi);
- return;
- }
-
- if (hpusbscsi->fragment + 1 != hpusbscsi->srb->use_sg)
- callback = scatter_gather_callback;
- else
- callback = simple_done;
-
- TRACE_STATE;
- if (hpusbscsi->state != HP_STATE_PREMATURE)
- hpusbscsi->state = HP_STATE_WORKING;
- TRACE_STATE;
-
- usb_fill_bulk_urb(
- u,
- hpusbscsi->dev,
- hpusbscsi->current_data_pipe,
- page_address(sg[hpusbscsi->fragment].page) +
- sg[hpusbscsi->fragment].offset,
- sg[hpusbscsi->fragment++].length,
- callback,
- hpusbscsi
- );
-
- res = usb_submit_urb(u, GFP_ATOMIC);
- if (unlikely(res))
- handle_usb_error(hpusbscsi);
- TRACE_STATE;
-}
-
-static void simple_done (struct urb *u, struct pt_regs *regs)
-{
- struct hpusbscsi * hpusbscsi = (struct hpusbscsi *)u->context;
-
- if (unlikely(u->status < 0)) {
- handle_usb_error(hpusbscsi);
- return;
- }
- DEBUG("Data transfer done\n");
- TRACE_STATE;
- if (hpusbscsi->state != HP_STATE_PREMATURE) {
- if (unlikely(u->status < 0)) {
- handle_usb_error(hpusbscsi);
- } else {
- if (hpusbscsi->state != HP_STATE_ERROR) {
- hpusbscsi->state = HP_STATE_WAIT;
- } else {
- issue_request_sense(hpusbscsi);
- }
- }
- } else {
- if (likely(hpusbscsi->scallback != NULL))
- hpusbscsi->scallback(hpusbscsi->srb);
- hpusbscsi->state = HP_STATE_FREE;
- }
-}
-
-static void simple_payload_callback (struct urb *u, struct pt_regs *regs)
-{
- struct hpusbscsi * hpusbscsi = (struct hpusbscsi *)u->context;
- int res;
-
- if (unlikely(u->status<0)) {
- handle_usb_error(hpusbscsi);
- return;
- }
-
- usb_fill_bulk_urb(
- u,
- hpusbscsi->dev,
- hpusbscsi->current_data_pipe,
- hpusbscsi->srb->buffer,
- hpusbscsi->srb->bufflen,
- simple_done,
- hpusbscsi
- );
-
- res = usb_submit_urb(u, GFP_ATOMIC);
- if (unlikely(res)) {
- handle_usb_error(hpusbscsi);
- return;
- }
- TRACE_STATE;
- if (hpusbscsi->state != HP_STATE_PREMATURE) {
- hpusbscsi->state = HP_STATE_WORKING;
- TRACE_STATE;
- }
-}
-
-static void request_sense_callback (struct urb *u, struct pt_regs *regs)
-{
- struct hpusbscsi * hpusbscsi = (struct hpusbscsi *)u->context;
-
- if (u->status<0) {
- handle_usb_error(hpusbscsi);
- return;
- }
-
- usb_fill_bulk_urb(
- u,
- hpusbscsi->dev,
- hpusbscsi->current_data_pipe,
- hpusbscsi->srb->sense_buffer,
- SCSI_SENSE_BUFFERSIZE,
- simple_done,
- hpusbscsi
- );
-
- if (0 > usb_submit_urb(u, GFP_ATOMIC)) {
- handle_usb_error(hpusbscsi);
- return;
- }
- if (hpusbscsi->state != HP_STATE_PREMATURE && hpusbscsi->state != HP_STATE_ERROR)
- hpusbscsi->state = HP_STATE_WORKING;
-}
-
-static void issue_request_sense (struct hpusbscsi *hpusbscsi)
-{
- usb_fill_bulk_urb(
- hpusbscsi->dataurb,
- hpusbscsi->dev,
- usb_sndbulkpipe(hpusbscsi->dev, hpusbscsi->ep_out),
- &hpusbscsi->sense_command,
- SENSE_COMMAND_SIZE,
- request_sense_callback,
- hpusbscsi
- );
-
- hpusbscsi->current_data_pipe = usb_rcvbulkpipe(hpusbscsi->dev, hpusbscsi->ep_in);
-
- if (0 > usb_submit_urb(hpusbscsi->dataurb, GFP_ATOMIC)) {
- handle_usb_error(hpusbscsi);
- }
-}
-
-
diff --git a/drivers/usb/image/hpusbscsi.h b/drivers/usb/image/hpusbscsi.h
deleted file mode 100644
index bdfae769adea7..0000000000000
--- a/drivers/usb/image/hpusbscsi.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/* Header file for the hpusbscsi driver */
-/* (C) Copyright 2001 Oliver Neukum */
-/* sponsored by the Linux Usb Project */
-/* large parts based on or taken from code by John Fremlin and Matt Dharm */
-/* this file is licensed under the GPL */
-
-/* A big thanks to Jose for untiring testing */
-
-typedef void (*scsi_callback)(Scsi_Cmnd *);
-
-#define SENSE_COMMAND_SIZE 6
-#define HPUSBSCSI_SENSE_LENGTH 0x16
-
-struct hpusbscsi
-{
- struct usb_device *dev; /* NULL indicates unplugged device */
- int ep_out;
- int ep_in;
- int ep_int;
- int interrupt_interval;
- int number;
- int fragment;
- struct Scsi_Host *host;
-
- scsi_callback scallback;
- Scsi_Cmnd *srb;
-
-
- wait_queue_head_t pending;
- wait_queue_head_t deathrow;
-
- struct urb *dataurb;
- struct urb *controlurb;
-
-
- int state;
- int current_data_pipe;
- u8 sense_command[SENSE_COMMAND_SIZE];
- u8 scsi_state_byte;
-};
-
-#define SCSI_ERR_MASK ~0x3fu
-
-static const unsigned char scsi_command_direction[256/8] = {
- 0x28, 0x81, 0x14, 0x14, 0x20, 0x01, 0x90, 0x77,
- 0x0C, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
-#define DIRECTION_IS_IN(x) ((scsi_command_direction[x>>3] >> (x & 7)) & 1)
-
-static void simple_command_callback(struct urb *u, struct pt_regs *regs);
-static void scatter_gather_callback(struct urb *u, struct pt_regs *regs);
-static void simple_payload_callback (struct urb *u, struct pt_regs *regs);
-static void request_sense_callback (struct urb *u, struct pt_regs *regs);
-static void control_interrupt_callback (struct urb *u, struct pt_regs *regs);
-static void simple_done (struct urb *u, struct pt_regs *regs);
-static int hpusbscsi_scsi_queuecommand (Scsi_Cmnd *srb, scsi_callback callback);
-static int hpusbscsi_scsi_host_reset (Scsi_Cmnd *srb);
-static int hpusbscsi_scsi_abort (Scsi_Cmnd *srb);
-static void issue_request_sense (struct hpusbscsi *hpusbscsi);
-
-/* defines for internal driver state */
-#define HP_STATE_FREE 0 /*ready for next request */
-#define HP_STATE_BEGINNING 1 /*command being transferred */
-#define HP_STATE_WORKING 2 /* data transfer stage */
-#define HP_STATE_ERROR 3 /* error has been reported */
-#define HP_STATE_WAIT 4 /* waiting for status transfer */
-#define HP_STATE_PREMATURE 5 /* status prematurely reported */
-
-
-
diff --git a/drivers/usb/image/mdc800.c b/drivers/usb/image/mdc800.c
index 83f3c9feae2b8..5791723e6083b 100644
--- a/drivers/usb/image/mdc800.c
+++ b/drivers/usb/image/mdc800.c
@@ -95,6 +95,7 @@
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/smp_lock.h>
+#include <linux/wait.h>
#include <linux/usb.h>
#include <linux/fs.h>
@@ -330,7 +331,7 @@ static void mdc800_usb_irq (struct urb *urb, struct pt_regs *res)
{
mdc800->camera_request_ready=0;
mdc800->irq_woken=1;
- wake_up_interruptible (&mdc800->irq_wait);
+ wake_up (&mdc800->irq_wait);
}
}
@@ -346,19 +347,9 @@ static void mdc800_usb_irq (struct urb *urb, struct pt_regs *res)
*/
static int mdc800_usb_waitForIRQ (int mode, int msec)
{
- DECLARE_WAITQUEUE(wait, current);
- long timeout;
-
mdc800->camera_request_ready=1+mode;
- add_wait_queue(&mdc800->irq_wait, &wait);
- timeout = msec*HZ/1000;
- while (!mdc800->irq_woken && timeout)
- {
- set_current_state(TASK_UNINTERRUPTIBLE);
- timeout = schedule_timeout (timeout);
- }
- remove_wait_queue(&mdc800->irq_wait, &wait);
+ wait_event_timeout(mdc800->irq_wait, mdc800->irq_woken, msec*HZ/1000);
mdc800->irq_woken = 0;
if (mdc800->camera_request_ready>0)
@@ -395,7 +386,7 @@ static void mdc800_usb_write_notify (struct urb *urb, struct pt_regs *res)
mdc800->state=READY;
}
mdc800->written = 1;
- wake_up_interruptible (&mdc800->write_wait);
+ wake_up (&mdc800->write_wait);
}
@@ -423,7 +414,7 @@ static void mdc800_usb_download_notify (struct urb *urb, struct pt_regs *res)
err ("request bytes fails (status:%i)", urb->status);
}
mdc800->downloaded = 1;
- wake_up_interruptible (&mdc800->download_wait);
+ wake_up (&mdc800->download_wait);
}
@@ -704,8 +695,6 @@ static ssize_t mdc800_device_read (struct file *file, char __user *buf, size_t l
{
size_t left=len, sts=len; /* single transfer size */
char __user *ptr = buf;
- long timeout;
- DECLARE_WAITQUEUE(wait, current);
down (&mdc800->io_lock);
if (mdc800->state == NOT_CONNECTED)
@@ -751,14 +740,8 @@ static ssize_t mdc800_device_read (struct file *file, char __user *buf, size_t l
up (&mdc800->io_lock);
return len-left;
}
- add_wait_queue(&mdc800->download_wait, &wait);
- timeout = TO_DOWNLOAD_GET_READY*HZ/1000;
- while (!mdc800->downloaded && timeout)
- {
- set_current_state(TASK_UNINTERRUPTIBLE);
- timeout = schedule_timeout (timeout);
- }
- remove_wait_queue(&mdc800->download_wait, &wait);
+ wait_event_timeout(mdc800->download_wait, mdc800->downloaded,
+ TO_DOWNLOAD_GET_READY*HZ/1000);
mdc800->downloaded = 0;
if (mdc800->download_urb->status != 0)
{
@@ -802,7 +785,6 @@ static ssize_t mdc800_device_read (struct file *file, char __user *buf, size_t l
static ssize_t mdc800_device_write (struct file *file, const char __user *buf, size_t len, loff_t *pos)
{
size_t i=0;
- DECLARE_WAITQUEUE(wait, current);
down (&mdc800->io_lock);
if (mdc800->state != READY)
@@ -856,7 +838,6 @@ static ssize_t mdc800_device_write (struct file *file, const char __user *buf, s
if (mdc800->in_count == 8)
{
int answersize;
- long timeout;
if (mdc800_usb_waitForIRQ (0,TO_GET_READY))
{
@@ -876,14 +857,7 @@ static ssize_t mdc800_device_write (struct file *file, const char __user *buf, s
up (&mdc800->io_lock);
return -EIO;
}
- add_wait_queue(&mdc800->write_wait, &wait);
- timeout = TO_WRITE_GET_READY*HZ/1000;
- while (!mdc800->written && timeout)
- {
- set_current_state(TASK_UNINTERRUPTIBLE);
- timeout = schedule_timeout (timeout);
- }
- remove_wait_queue(&mdc800->write_wait, &wait);
+ wait_event_timeout(mdc800->write_wait, mdc800->written, TO_WRITE_GET_READY*HZ/1000);
mdc800->written = 0;
if (mdc800->state == WORKING)
{
diff --git a/drivers/usb/image/microtek.c b/drivers/usb/image/microtek.c
index fe32608b43471..de0d32f6618de 100644
--- a/drivers/usb/image/microtek.c
+++ b/drivers/usb/image/microtek.c
@@ -703,6 +703,7 @@ static int mts_usb_probe(struct usb_interface *intf,
int ep_in_set[3]; /* this will break if we have more than three endpoints
which is why we check */
int *ep_in_current = ep_in_set;
+ int err_retval = -ENOMEM;
struct mts_desc * new_desc;
struct vendor_product const* p;
@@ -809,7 +810,10 @@ static int mts_usb_probe(struct usb_interface *intf,
goto out_free_urb;
new_desc->host->hostdata[0] = (unsigned long)new_desc;
- scsi_add_host(new_desc->host, NULL); /* XXX handle failure */
+ if (scsi_add_host(new_desc->host, NULL)) {
+ err_retval = -EIO;
+ goto out_free_urb;
+ }
scsi_scan_host(new_desc->host);
usb_set_intfdata(intf, new_desc);
@@ -820,7 +824,7 @@ static int mts_usb_probe(struct usb_interface *intf,
out_kfree:
kfree(new_desc);
out:
- return -ENOMEM;
+ return err_retval;
}
static void mts_usb_disconnect (struct usb_interface *intf)
diff --git a/drivers/usb/input/aiptek.c b/drivers/usb/input/aiptek.c
index a2a037fe791f7..d7fea9ea301b8 100644
--- a/drivers/usb/input/aiptek.c
+++ b/drivers/usb/input/aiptek.c
@@ -297,8 +297,6 @@ struct aiptek_features {
int firmwareCode; /* prom/eeprom version */
char usbPath[64 + 1]; /* device's physical usb path */
char inputPath[64 + 1]; /* input device path */
- char manuName[64 + 1]; /* manufacturer name */
- char prodName[64 + 1]; /* product name */
};
struct aiptek_settings {
@@ -796,7 +794,7 @@ exit:
* manufacturing revisions. In any event, we consider these
* IDs to not be model-specific nor unique.
*/
-struct usb_device_id aiptek_ids[] = {
+static const struct usb_device_id aiptek_ids[] = {
{USB_DEVICE(USB_VENDOR_ID_AIPTEK, 0x01)},
{USB_DEVICE(USB_VENDOR_ID_AIPTEK, 0x10)},
{USB_DEVICE(USB_VENDOR_ID_AIPTEK, 0x20)},
@@ -855,7 +853,7 @@ aiptek_set_report(struct aiptek *aiptek,
USB_REQ_SET_REPORT,
USB_TYPE_CLASS | USB_RECIP_INTERFACE |
USB_DIR_OUT, (report_type << 8) + report_id,
- aiptek->ifnum, buffer, size, 5 * HZ);
+ aiptek->ifnum, buffer, size, 5000);
}
static int
@@ -868,7 +866,7 @@ aiptek_get_report(struct aiptek *aiptek,
USB_REQ_GET_REPORT,
USB_TYPE_CLASS | USB_RECIP_INTERFACE |
USB_DIR_IN, (report_type << 8) + report_id,
- aiptek->ifnum, buffer, size, 5 * HZ);
+ aiptek->ifnum, buffer, size, 5000);
}
/***********************************************************************
@@ -1089,7 +1087,7 @@ static ssize_t show_tabletManufacturer(struct device *dev, char *buf)
if (aiptek == NULL)
return 0;
- retval = snprintf(buf, PAGE_SIZE, "%s\n", aiptek->features.manuName);
+ retval = snprintf(buf, PAGE_SIZE, "%s\n", aiptek->usbdev->manufacturer);
return retval;
}
@@ -1106,7 +1104,7 @@ static ssize_t show_tabletProduct(struct device *dev, char *buf)
if (aiptek == NULL)
return 0;
- retval = snprintf(buf, PAGE_SIZE, "%s\n", aiptek->features.prodName);
+ retval = snprintf(buf, PAGE_SIZE, "%s\n", aiptek->usbdev->product);
return retval;
}
@@ -2166,19 +2164,6 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
*/
input_register_device(&aiptek->inputdev);
- /* Go and decode the USB representation of the tablet's manufacturer
- * name and product name. They only change once every hotplug event,
- * which is why we put it here instead of in the sysfs interface.
- */
- usb_string(usbdev,
- usbdev->descriptor.iManufacturer,
- aiptek->features.manuName,
- sizeof(aiptek->features.manuName));
- usb_string(usbdev,
- usbdev->descriptor.iProduct,
- aiptek->features.prodName,
- sizeof(aiptek->features.prodName));
-
/* We now will look for the evdev device which is mapped to
* the tablet. The partial name is kept in the link list of
* input_handles associated with this input device.
diff --git a/drivers/usb/input/ati_remote.c b/drivers/usb/input/ati_remote.c
index 3f5414446485a..355add5c29f57 100644
--- a/drivers/usb/input/ati_remote.c
+++ b/drivers/usb/input/ati_remote.c
@@ -94,6 +94,7 @@
#include <linux/moduleparam.h>
#include <linux/input.h>
#include <linux/usb.h>
+#include <linux/wait.h>
/*
* Module and Version Information, Module Parameters
@@ -174,7 +175,6 @@ struct ati_remote {
dma_addr_t outbuf_dma;
int open; /* open counter */
- int present; /* device plugged in? */
unsigned char old_data[2]; /* Detect duplicate events */
unsigned long old_jiffies;
@@ -252,8 +252,8 @@ static struct
{KIND_FILTERED, 0xdd, 0x18, EV_KEY, KEY_KPENTER, 1}, /* "check" */
{KIND_FILTERED, 0xdb, 0x16, EV_KEY, KEY_MENU, 1}, /* "menu" */
{KIND_FILTERED, 0xc7, 0x02, EV_KEY, KEY_POWER, 1}, /* Power */
- {KIND_FILTERED, 0xc8, 0x03, EV_KEY, KEY_PROG1, 1}, /* TV */
- {KIND_FILTERED, 0xc9, 0x04, EV_KEY, KEY_PROG2, 1}, /* DVD */
+ {KIND_FILTERED, 0xc8, 0x03, EV_KEY, KEY_TV, 1}, /* TV */
+ {KIND_FILTERED, 0xc9, 0x04, EV_KEY, KEY_DVD, 1}, /* DVD */
{KIND_FILTERED, 0xca, 0x05, EV_KEY, KEY_WWW, 1}, /* WEB */
{KIND_FILTERED, 0xcb, 0x06, EV_KEY, KEY_BOOKMARKS, 1}, /* "book" */
{KIND_FILTERED, 0xcc, 0x07, EV_KEY, KEY_EDIT, 1}, /* "hand" */
@@ -263,14 +263,14 @@ static struct
{KIND_FILTERED, 0xe4, 0x1f, EV_KEY, KEY_RIGHT, 1}, /* right */
{KIND_FILTERED, 0xe7, 0x22, EV_KEY, KEY_DOWN, 1}, /* down */
{KIND_FILTERED, 0xdf, 0x1a, EV_KEY, KEY_UP, 1}, /* up */
- {KIND_FILTERED, 0xe3, 0x1e, EV_KEY, KEY_ENTER, 1}, /* "OK" */
+ {KIND_FILTERED, 0xe3, 0x1e, EV_KEY, KEY_OK, 1}, /* "OK" */
{KIND_FILTERED, 0xce, 0x09, EV_KEY, KEY_VOLUMEDOWN, 1}, /* VOL + */
{KIND_FILTERED, 0xcd, 0x08, EV_KEY, KEY_VOLUMEUP, 1}, /* VOL - */
{KIND_FILTERED, 0xcf, 0x0a, EV_KEY, KEY_MUTE, 1}, /* MUTE */
- {KIND_FILTERED, 0xd1, 0x0c, EV_KEY, KEY_CHANNELUP, 1}, /* CH + */
- {KIND_FILTERED, 0xd0, 0x0b, EV_KEY, KEY_CHANNELDOWN, 1},/* CH - */
+ {KIND_FILTERED, 0xd0, 0x0b, EV_KEY, KEY_CHANNELUP, 1}, /* CH + */
+ {KIND_FILTERED, 0xd1, 0x0c, EV_KEY, KEY_CHANNELDOWN, 1},/* CH - */
{KIND_FILTERED, 0xec, 0x27, EV_KEY, KEY_RECORD, 1}, /* ( o) red */
- {KIND_FILTERED, 0xea, 0x25, EV_KEY, KEY_PLAYCD, 1}, /* ( >) */
+ {KIND_FILTERED, 0xea, 0x25, EV_KEY, KEY_PLAY, 1}, /* ( >) */
{KIND_FILTERED, 0xe9, 0x24, EV_KEY, KEY_REWIND, 1}, /* (<<) */
{KIND_FILTERED, 0xeb, 0x26, EV_KEY, KEY_FORWARD, 1}, /* (>>) */
{KIND_FILTERED, 0xed, 0x28, EV_KEY, KEY_STOP, 1}, /* ([]) */
@@ -356,19 +356,8 @@ static void ati_remote_close(struct input_dev *inputdev)
{
struct ati_remote *ati_remote = inputdev->private;
- if (ati_remote == NULL) {
- err("ati_remote: %s: object is NULL!\n", __FUNCTION__);
- return;
- }
-
- if (ati_remote->open <= 0)
- dev_dbg(&ati_remote->interface->dev, "%s: Not open.\n", __FUNCTION__);
- else
- --ati_remote->open;
-
- /* If still present, disconnect will call delete. */
- if (!ati_remote->present && !ati_remote->open)
- ati_remote_delete(ati_remote);
+ if (!--ati_remote->open)
+ usb_kill_urb(ati_remote->irq_urb);
}
/*
@@ -396,8 +385,6 @@ static void ati_remote_irq_out(struct urb *urb, struct pt_regs *regs)
*/
static int ati_remote_sendpacket(struct ati_remote *ati_remote, u16 cmd, unsigned char *data)
{
- DECLARE_WAITQUEUE(wait, current);
- int timeout = HZ; /* 1 second */
int retval = 0;
/* Set up out_urb */
@@ -415,18 +402,10 @@ static int ati_remote_sendpacket(struct ati_remote *ati_remote, u16 cmd, unsigne
return retval;
}
- set_current_state(TASK_INTERRUPTIBLE);
- add_wait_queue(&ati_remote->wait, &wait);
-
- while (timeout && (ati_remote->out_urb->status == -EINPROGRESS)
- && !(ati_remote->send_flags & SEND_FLAG_COMPLETE)) {
- set_current_state(TASK_INTERRUPTIBLE);
- timeout = schedule_timeout(timeout);
- rmb();
- }
-
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&ati_remote->wait, &wait);
+ wait_event_timeout(ati_remote->wait,
+ ((ati_remote->out_urb->status != -EINPROGRESS) ||
+ (ati_remote->send_flags & SEND_FLAG_COMPLETE)),
+ HZ);
usb_kill_urb(ati_remote->out_urb);
return retval;
@@ -727,7 +706,6 @@ static int ati_remote_probe(struct usb_interface *interface, const struct usb_de
struct usb_host_interface *iface_host;
int retval = -ENOMEM;
char path[64];
- char *buf = NULL;
/* Allocate and clear an ati_remote struct */
if (!(ati_remote = kmalloc(sizeof (struct ati_remote), GFP_KERNEL)))
@@ -761,8 +739,6 @@ static int ati_remote_probe(struct usb_interface *interface, const struct usb_de
retval = -ENODEV;
goto error;
}
- if (!(buf = kmalloc(NAME_BUFSIZE, GFP_KERNEL)))
- goto error;
/* Allocate URB buffers, URBs */
ati_remote->inbuf = usb_buffer_alloc(udev, DATA_BUFSIZE, SLAB_ATOMIC,
@@ -785,14 +761,11 @@ static int ati_remote_probe(struct usb_interface *interface, const struct usb_de
usb_make_path(udev, path, NAME_BUFSIZE);
sprintf(ati_remote->phys, "%s/input%d", path, ATI_INPUTNUM);
- if (udev->descriptor.iManufacturer &&
- (usb_string(udev, udev->descriptor.iManufacturer, buf,
- NAME_BUFSIZE) > 0))
- strcat(ati_remote->name, buf);
+ if (udev->manufacturer)
+ strcat(ati_remote->name, udev->manufacturer);
- if (udev->descriptor.iProduct &&
- (usb_string(udev, udev->descriptor.iProduct, buf, NAME_BUFSIZE) > 0))
- sprintf(ati_remote->name, "%s %s", ati_remote->name, buf);
+ if (udev->product)
+ sprintf(ati_remote->name, "%s %s", ati_remote->name, udev->product);
if (!strlen(ati_remote->name))
sprintf(ati_remote->name, DRIVER_DESC "(%04x,%04x)",
@@ -812,12 +785,8 @@ static int ati_remote_probe(struct usb_interface *interface, const struct usb_de
ati_remote->name, path);
usb_set_intfdata(interface, ati_remote);
- ati_remote->present = 1;
error:
- if (buf)
- kfree(buf);
-
if (retval)
ati_remote_delete(ati_remote);
@@ -840,12 +809,7 @@ static void ati_remote_disconnect(struct usb_interface *interface)
return;
}
- /* Mark device as unplugged */
- ati_remote->present = 0;
-
- /* If device is still open, ati_remote_close will call delete. */
- if (!ati_remote->open)
- ati_remote_delete(ati_remote);
+ ati_remote_delete(ati_remote);
up(&disconnect_sem);
}
diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c
index 2280d13986e64..7662cf4e26215 100644
--- a/drivers/usb/input/hid-core.c
+++ b/drivers/usb/input/hid-core.c
@@ -24,6 +24,7 @@
#include <asm/unaligned.h>
#include <asm/byteorder.h>
#include <linux/input.h>
+#include <linux/wait.h>
#undef DEBUG
#undef DEBUG_DATA
@@ -37,13 +38,20 @@
* Version Information
*/
-#define DRIVER_VERSION "v2.0"
+#define DRIVER_VERSION "v2.01"
#define DRIVER_AUTHOR "Andreas Gal, Vojtech Pavlik"
#define DRIVER_DESC "USB HID core driver"
#define DRIVER_LICENSE "GPL"
static char *hid_types[] = {"Device", "Pointer", "Mouse", "Device", "Joystick",
"Gamepad", "Keyboard", "Keypad", "Multi-Axis Controller"};
+/*
+ * Module parameters.
+ */
+
+static unsigned int hid_mousepoll_interval;
+module_param_named(mousepoll, hid_mousepoll_interval, uint, 0644);
+MODULE_PARM_DESC(mousepoll, "Polling interval of mice");
/*
* Register a new report for a device.
@@ -121,18 +129,17 @@ static int open_collection(struct hid_parser *parser, unsigned type)
if (parser->device->maxcollection == parser->device->collection_size) {
collection = kmalloc(sizeof(struct hid_collection) *
- parser->device->collection_size * 2,
- GFP_KERNEL);
+ parser->device->collection_size * 2, GFP_KERNEL);
if (collection == NULL) {
dbg("failed to reallocate collection array");
return -1;
}
memcpy(collection, parser->device->collection,
- sizeof(struct hid_collection) *
- parser->device->collection_size);
+ sizeof(struct hid_collection) *
+ parser->device->collection_size);
memset(collection + parser->device->collection_size, 0,
- sizeof(struct hid_collection) *
- parser->device->collection_size);
+ sizeof(struct hid_collection) *
+ parser->device->collection_size);
kfree(parser->device->collection);
parser->device->collection = collection;
parser->device->collection_size *= 2;
@@ -141,12 +148,12 @@ static int open_collection(struct hid_parser *parser, unsigned type)
parser->collection_stack[parser->collection_stack_ptr++] =
parser->device->maxcollection;
- collection = parser->device->collection +
+ collection = parser->device->collection +
parser->device->maxcollection++;
collection->type = type;
collection->usage = usage;
collection->level = parser->collection_stack_ptr - 1;
-
+
if (type == HID_COLLECTION_APPLICATION)
parser->device->maxapplication++;
@@ -193,7 +200,7 @@ static int hid_add_usage(struct hid_parser *parser, unsigned usage)
}
parser->local.usage[parser->local.usage_index] = usage;
parser->local.collection_index[parser->local.usage_index] =
- parser->collection_stack_ptr ?
+ parser->collection_stack_ptr ?
parser->collection_stack[parser->collection_stack_ptr - 1] : 0;
parser->local.usage_index++;
return 0;
@@ -220,13 +227,15 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign
dbg("logical range invalid %d %d", parser->global.logical_minimum, parser->global.logical_maximum);
return -1;
}
-
- if (!(usages = max_t(int, parser->local.usage_index, parser->global.report_count)))
- return 0; /* Ignore padding fields */
offset = report->size;
report->size += parser->global.report_size * parser->global.report_count;
+ if (!parser->local.usage_index) /* Ignore padding fields */
+ return 0;
+
+ usages = max_t(int, parser->local.usage_index, parser->global.report_count);
+
if ((field = hid_register_field(report, usages, parser->global.report_count)) == NULL)
return 0;
@@ -581,13 +590,13 @@ static u8 *fetch_item(__u8 *start, __u8 *end, struct hid_item *item)
item->size = *start++;
item->tag = *start++;
- if ((end - start) < item->size)
+ if ((end - start) < item->size)
return NULL;
item->data.longdata = start;
start += item->size;
return start;
- }
+ }
item->format = HID_ITEM_FORMAT_SHORT;
item->size = b & 3;
@@ -604,7 +613,7 @@ static u8 *fetch_item(__u8 *start, __u8 *end, struct hid_item *item)
return start;
case 2:
- if ((end - start) < 2)
+ if ((end - start) < 2)
return NULL;
item->data.u16 = le16_to_cpu(get_unaligned((__le16*)start));
start = (__u8 *)((__le16 *)start + 1);
@@ -646,13 +655,13 @@ static struct hid_device *hid_parse_report(__u8 *start, unsigned size)
return NULL;
memset(device, 0, sizeof(struct hid_device));
- if (!(device->collection =kmalloc(sizeof(struct hid_collection) *
+ if (!(device->collection = kmalloc(sizeof(struct hid_collection) *
HID_DEFAULT_NUM_COLLECTIONS, GFP_KERNEL))) {
kfree(device);
return NULL;
}
memset(device->collection, 0, sizeof(struct hid_collection) *
- HID_DEFAULT_NUM_COLLECTIONS);
+ HID_DEFAULT_NUM_COLLECTIONS);
device->collection_size = HID_DEFAULT_NUM_COLLECTIONS;
for (i = 0; i < HID_REPORT_TYPES; i++)
@@ -806,8 +815,7 @@ static void hid_input_field(struct hid_device *hid, struct hid_field *field, __u
__s32 max = field->logical_maximum;
__s32 *value;
- value = kmalloc(sizeof(__s32)*count, GFP_ATOMIC);
- if (!value)
+ if (!(value = kmalloc(sizeof(__s32) * count, GFP_ATOMIC)))
return;
for (n = 0; n < count; n++) {
@@ -824,14 +832,6 @@ static void hid_input_field(struct hid_device *hid, struct hid_field *field, __u
for (n = 0; n < count; n++) {
if (HID_MAIN_ITEM_VARIABLE & field->flags) {
-
- if (field->flags & HID_MAIN_ITEM_RELATIVE) {
- if (!value[n])
- continue;
- } else {
- if (value[n] == field->value[n])
- continue;
- }
hid_process_event(hid, field, &field->usage[n], value[n], regs);
continue;
}
@@ -893,10 +893,8 @@ static int hid_input_report(int type, struct urb *urb, struct pt_regs *regs)
size = ((report->size - 1) >> 3) + 1;
- if (len < size) {
+ if (len < size)
dbg("report %d is too short, (%d < %d)", report->id, len, size);
- return -1;
- }
if (hid->claimed & HID_CLAIMED_HIDDEV)
hiddev_report_event(hid, report);
@@ -934,7 +932,7 @@ static void hid_irq_in(struct urb *urb, struct pt_regs *regs)
default: /* error */
warn("input irq status %d received", urb->status);
}
-
+
status = usb_submit_urb(urb, SLAB_ATOMIC);
if (status)
err("can't resubmit intr, %s-%s/input%d, status %d",
@@ -956,7 +954,7 @@ static void hid_output_field(struct hid_field *field, __u8 *data)
for (n = 0; n < count; n++) {
if (field->logical_minimum < 0) /* signed values */
implement(data, offset + n * size, size, s32ton(field->value[n], size));
- else /* unsigned values */
+ else /* unsigned values */
implement(data, offset + n * size, size, field->value[n]);
}
}
@@ -1003,63 +1001,21 @@ int hid_set_field(struct hid_field *field, unsigned offset, __s32 value)
return 0;
}
-int hid_find_field(struct hid_device *hid, unsigned int type, unsigned int code, struct hid_field **field)
-{
- struct hid_report_enum *report_enum = hid->report_enum + HID_OUTPUT_REPORT;
- struct list_head *list = report_enum->report_list.next;
- int i, j;
-
- while (list != &report_enum->report_list) {
- struct hid_report *report = (struct hid_report *) list;
- list = list->next;
- for (i = 0; i < report->maxfield; i++) {
- *field = report->field[i];
- for (j = 0; j < (*field)->maxusage; j++)
- if ((*field)->usage[j].type == type && (*field)->usage[j].code == code)
- return j;
- }
- }
- return -1;
-}
-
/*
- * Find a report with a specified HID usage.
+ * Find a report field with a specified HID usage.
*/
-int hid_find_report_by_usage(struct hid_device *hid, __u32 wanted_usage, struct hid_report **report, int type)
+struct hid_field *hid_find_field_by_usage(struct hid_device *hid, __u32 wanted_usage, int type)
{
- struct hid_report_enum *report_enum = hid->report_enum + type;
- struct list_head *list = report_enum->report_list.next;
- int i, j;
-
- while (list != &report_enum->report_list) {
- *report = (struct hid_report *) list;
- list = list->next;
- for (i = 0; i < (*report)->maxfield; i++) {
- struct hid_field *field = (*report)->field[i];
- for (j = 0; j < field->maxusage; j++)
- if (field->logical == wanted_usage)
- return j;
- }
- }
- return -1;
-}
-
-#if 0
-static int hid_find_field_in_report(struct hid_report *report, __u32 wanted_usage, struct hid_field **field)
-{
- int i, j;
-
- for (i = 0; i < report->maxfield; i++) {
- *field = report->field[i];
- for (j = 0; j < (*field)->maxusage; j++)
- if ((*field)->usage[j].hid == wanted_usage)
- return j;
- }
+ struct hid_report *report;
+ int i;
- return -1;
+ list_for_each_entry(report, &hid->report_enum[type].report_list, list)
+ for (i = 0; i < report->maxfield; i++)
+ if (report->field[i]->logical == wanted_usage)
+ return report->field[i];
+ return NULL;
}
-#endif
static int hid_submit_out(struct hid_device *hid)
{
@@ -1118,8 +1074,8 @@ static int hid_submit_ctrl(struct hid_device *hid)
hid->cr->wLength = cpu_to_le16(len);
dbg("submitting ctrl urb: %s wValue=0x%04x wIndex=0x%04x wLength=%u",
- hid->cr->bRequest == HID_REQ_SET_REPORT ? "Set_Report" : "Get_Report",
- hid->cr->wValue, hid->cr->wIndex, hid->cr->wLength);
+ hid->cr->bRequest == HID_REQ_SET_REPORT ? "Set_Report" : "Get_Report",
+ hid->cr->wValue, hid->cr->wIndex, hid->cr->wLength);
if (usb_submit_urb(hid->urbctrl, GFP_ATOMIC)) {
err("usb_submit_urb(ctrl) failed");
@@ -1186,7 +1142,7 @@ static void hid_ctrl(struct urb *urb, struct pt_regs *regs)
switch (urb->status) {
case 0: /* success */
- if (hid->ctrl[hid->ctrltail].dir == USB_DIR_IN)
+ if (hid->ctrl[hid->ctrltail].dir == USB_DIR_IN)
hid_input_report(hid->ctrl[hid->ctrltail].report->type, urb, regs);
case -ESHUTDOWN: /* unplug */
case -EILSEQ: /* unplug timectrl on uhci */
@@ -1268,22 +1224,9 @@ void hid_submit_report(struct hid_device *hid, struct hid_report *report, unsign
int hid_wait_io(struct hid_device *hid)
{
- DECLARE_WAITQUEUE(wait, current);
- int timeout = 10*HZ;
-
- set_current_state(TASK_UNINTERRUPTIBLE);
- add_wait_queue(&hid->wait, &wait);
-
- while (timeout && (test_bit(HID_CTRL_RUNNING, &hid->iofl) ||
- test_bit(HID_OUT_RUNNING, &hid->iofl))) {
- set_current_state(TASK_UNINTERRUPTIBLE);
- timeout = schedule_timeout(timeout);
- }
-
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&hid->wait, &wait);
-
- if (!timeout) {
+ if (!wait_event_timeout(hid->wait, (!test_bit(HID_CTRL_RUNNING, &hid->iofl) &&
+ !test_bit(HID_OUT_RUNNING, &hid->iofl)),
+ 10*HZ)) {
dbg("timeout waiting for ctrl or out queue to clear");
return -1;
}
@@ -1301,7 +1244,7 @@ static int hid_get_class_descriptor(struct usb_device *dev, int ifnum,
do {
result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
USB_REQ_GET_DESCRIPTOR, USB_RECIP_INTERFACE | USB_DIR_IN,
- (type << 8), ifnum, buf, size, HZ * USB_CTRL_GET_TIMEOUT);
+ (type << 8), ifnum, buf, size, USB_CTRL_GET_TIMEOUT);
retries--;
} while (result < size && retries);
return result;
@@ -1332,47 +1275,19 @@ void hid_close(struct hid_device *hid)
void hid_init_reports(struct hid_device *hid)
{
- struct hid_report_enum *report_enum;
struct hid_report *report;
- struct list_head *list;
- int err, ret, size;
-
- /*
- * The Set_Idle request is supposed to affect only the
- * "Interrupt In" pipe. Unfortunately, buggy devices such as
- * the BTC keyboard (ID 046e:5303) the request also affects
- * Get_Report requests on the control pipe. In the worst
- * case, if the device was put on idle for an indefinite
- * amount of time (as we do below) and there are no input
- * events to report, the Get_Report requests will just hang
- * until we get a USB timeout. To avoid this, we temporarily
- * establish a minimal idle time of 1ms. This shouldn't hurt
- * bugfree devices and will cause a worst-case extra delay of
- * 1ms for buggy ones.
- */
- usb_control_msg(hid->dev, usb_sndctrlpipe(hid->dev, 0),
- HID_REQ_SET_IDLE, USB_TYPE_CLASS | USB_RECIP_INTERFACE, (1 << 8),
- hid->ifnum, NULL, 0, HZ * USB_CTRL_SET_TIMEOUT);
-
- report_enum = hid->report_enum + HID_INPUT_REPORT;
- list = report_enum->report_list.next;
- while (list != &report_enum->report_list) {
- report = (struct hid_report *) list;
- size = ((report->size - 1) >> 3) + 1 + report_enum->numbered;
+ int err, ret;
+
+ list_for_each_entry(report, &hid->report_enum[HID_INPUT_REPORT].report_list, list) {
+ int size = ((report->size - 1) >> 3) + 1 + hid->report_enum[HID_INPUT_REPORT].numbered;
if (size > HID_BUFFER_SIZE) size = HID_BUFFER_SIZE;
if (size > hid->urbin->transfer_buffer_length)
hid->urbin->transfer_buffer_length = size;
hid_submit_report(hid, report, USB_DIR_IN);
- list = list->next;
}
- report_enum = hid->report_enum + HID_FEATURE_REPORT;
- list = report_enum->report_list.next;
- while (list != &report_enum->report_list) {
- report = (struct hid_report *) list;
+ list_for_each_entry(report, &hid->report_enum[HID_FEATURE_REPORT].report_list, list)
hid_submit_report(hid, report, USB_DIR_IN);
- list = list->next;
- }
err = 0;
ret = hid_wait_io(hid);
@@ -1388,15 +1303,9 @@ void hid_init_reports(struct hid_device *hid)
if (err)
warn("timeout initializing reports\n");
- report_enum = hid->report_enum + HID_INPUT_REPORT;
- list = report_enum->report_list.next;
- while (list != &report_enum->report_list) {
- report = (struct hid_report *) list;
- usb_control_msg(hid->dev, usb_sndctrlpipe(hid->dev, 0),
- HID_REQ_SET_IDLE, USB_TYPE_CLASS | USB_RECIP_INTERFACE, report->id,
- hid->ifnum, NULL, 0, HZ * USB_CTRL_SET_TIMEOUT);
- list = list->next;
- }
+ usb_control_msg(hid->dev, usb_sndctrlpipe(hid->dev, 0),
+ HID_REQ_SET_IDLE, USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0,
+ hid->ifnum, NULL, 0, USB_CTRL_SET_TIMEOUT);
}
#define USB_VENDOR_ID_WACOM 0x056a
@@ -1405,11 +1314,11 @@ void hid_init_reports(struct hid_device *hid)
#define USB_DEVICE_ID_WACOM_INTUOS 0x0020
#define USB_DEVICE_ID_WACOM_PL 0x0030
#define USB_DEVICE_ID_WACOM_INTUOS2 0x0040
-#define USB_DEVICE_ID_WACOM_VOLITO 0x0060
-#define USB_DEVICE_ID_WACOM_PTU 0x0003
+#define USB_DEVICE_ID_WACOM_VOLITO 0x0060
+#define USB_DEVICE_ID_WACOM_PTU 0x0003
-#define USB_VENDOR_ID_KBGEAR 0x084e
-#define USB_DEVICE_ID_KBGEAR_JAMSTUDIO 0x1001
+#define USB_VENDOR_ID_KBGEAR 0x084e
+#define USB_DEVICE_ID_KBGEAR_JAMSTUDIO 0x1001
#define USB_VENDOR_ID_AIPTEK 0x08ca
#define USB_DEVICE_ID_AIPTEK_01 0x0001
@@ -1424,35 +1333,35 @@ void hid_init_reports(struct hid_device *hid)
#define USB_DEVICE_ID_POWERMATE 0x0410
#define USB_DEVICE_ID_SOUNDKNOB 0x04AA
-#define USB_VENDOR_ID_ATEN 0x0557
-#define USB_DEVICE_ID_ATEN_UC100KM 0x2004
-#define USB_DEVICE_ID_ATEN_CS124U 0x2202
-#define USB_DEVICE_ID_ATEN_2PORTKVM 0x2204
-#define USB_DEVICE_ID_ATEN_4PORTKVM 0x2205
-#define USB_DEVICE_ID_ATEN_4PORTKVMC 0x2208
+#define USB_VENDOR_ID_ATEN 0x0557
+#define USB_DEVICE_ID_ATEN_UC100KM 0x2004
+#define USB_DEVICE_ID_ATEN_CS124U 0x2202
+#define USB_DEVICE_ID_ATEN_2PORTKVM 0x2204
+#define USB_DEVICE_ID_ATEN_4PORTKVM 0x2205
+#define USB_DEVICE_ID_ATEN_4PORTKVMC 0x2208
-#define USB_VENDOR_ID_TOPMAX 0x0663
-#define USB_DEVICE_ID_TOPMAX_COBRAPAD 0x0103
+#define USB_VENDOR_ID_TOPMAX 0x0663
+#define USB_DEVICE_ID_TOPMAX_COBRAPAD 0x0103
-#define USB_VENDOR_ID_HAPP 0x078b
-#define USB_DEVICE_ID_UGCI_DRIVING 0x0010
-#define USB_DEVICE_ID_UGCI_FLYING 0x0020
-#define USB_DEVICE_ID_UGCI_FIGHTING 0x0030
+#define USB_VENDOR_ID_HAPP 0x078b
+#define USB_DEVICE_ID_UGCI_DRIVING 0x0010
+#define USB_DEVICE_ID_UGCI_FLYING 0x0020
+#define USB_DEVICE_ID_UGCI_FIGHTING 0x0030
-#define USB_VENDOR_ID_MGE 0x0463
-#define USB_DEVICE_ID_MGE_UPS 0xffff
-#define USB_DEVICE_ID_MGE_UPS1 0x0001
+#define USB_VENDOR_ID_MGE 0x0463
+#define USB_DEVICE_ID_MGE_UPS 0xffff
+#define USB_DEVICE_ID_MGE_UPS1 0x0001
#define USB_VENDOR_ID_ONTRAK 0x0a07
#define USB_DEVICE_ID_ONTRAK_ADU100 0x0064
-#define USB_VENDOR_ID_TANGTOP 0x0d3d
-#define USB_DEVICE_ID_TANGTOP_USBPS2 0x0001
+#define USB_VENDOR_ID_TANGTOP 0x0d3d
+#define USB_DEVICE_ID_TANGTOP_USBPS2 0x0001
#define USB_VENDOR_ID_ESSENTIAL_REALITY 0x0d7f
-#define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100
+#define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100
-#define USB_VENDOR_ID_A4TECH 0x09DA
+#define USB_VENDOR_ID_A4TECH 0x09da
#define USB_DEVICE_ID_A4TECH_WCP32PU 0x0006
#define USB_VENDOR_ID_CYPRESS 0x04b4
@@ -1494,6 +1403,21 @@ void hid_init_reports(struct hid_device *hid)
#define USB_VENDOR_ID_DELORME 0x1163
#define USB_DEVICE_ID_DELORME_EARTHMATE 0x0100
+#define USB_VENDOR_ID_MCC 0x09db
+#define USB_DEVICE_ID_MCC_PMD1024LS 0x0076
+#define USB_DEVICE_ID_MCC_PMD1208LS 0x007a
+
+#define USB_VENDOR_ID_CHICONY 0x04f2
+#define USB_DEVICE_ID_CHICONY_USBHUB_KB 0x0100
+
+#define USB_VENDOR_ID_BTC 0x046e
+#define USB_DEVICE_ID_BTC_KEYBOARD 0x5303
+
+
+/*
+ * Alphabetically sorted blacklist by quirk type.
+ */
+
static struct hid_blacklist {
__u16 idVendor;
__u16 idProduct;
@@ -1512,9 +1436,9 @@ static struct hid_blacklist {
{ USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW24, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW48, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW28, HID_QUIRK_IGNORE },
-
+ { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_HIDCOM, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_GLAB, USB_DEVICE_ID_4_PHIDGETSERVO_30, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_GLAB, USB_DEVICE_ID_1_PHIDGETSERVO_30, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_GLAB, USB_DEVICE_ID_8_8_8_IF_KIT, HID_QUIRK_IGNORE },
@@ -1522,6 +1446,9 @@ static struct hid_blacklist {
{ USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_8_8_IF_KIT, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_POWERMATE, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_SOUNDKNOB, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1024LS, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1208LS, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS1, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100, HID_QUIRK_IGNORE },
@@ -1557,18 +1484,18 @@ static struct hid_blacklist {
{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PTU, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_4_PHIDGETSERVO_20, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_1_PHIDGETSERVO_20, HID_QUIRK_IGNORE },
-
{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_UC100KM, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS124U, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET },
+ { USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_KEYBOARD, HID_QUIRK_NOGET},
+ { USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_USBHUB_KB, HID_QUIRK_NOGET},
{ USB_VENDOR_ID_TANGTOP, USB_DEVICE_ID_TANGTOP_USBPS2, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU, HID_QUIRK_2WHEEL_MOUSE_HACK_7 },
{ USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE, HID_QUIRK_2WHEEL_MOUSE_HACK_5 },
- { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_HIDCOM, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD, HID_QUIRK_BADPAD },
{ USB_VENDOR_ID_CHIC, USB_DEVICE_ID_CHIC_GAMEPAD, HID_QUIRK_BADPAD },
@@ -1579,13 +1506,6 @@ 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_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW40, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW24, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW48, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW28, HID_QUIRK_IGNORE },
-
- { USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE, HID_QUIRK_IGNORE },
-
{ 0, 0 }
};
@@ -1695,6 +1615,10 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
if (dev->speed == USB_SPEED_HIGH)
interval = 1 << (interval - 1);
+ /* Change the polling interval of mice. */
+ if (hid->collection->usage == HID_GD_MOUSE && hid_mousepoll_interval > 0)
+ interval = hid_mousepoll_interval;
+
if (endpoint->bEndpointAddress & USB_DIR_IN) {
if (hid->urbin)
continue;
@@ -1724,7 +1648,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
}
init_waitqueue_head(&hid->wait);
-
+
spin_lock_init(&hid->outlock);
spin_lock_init(&hid->ctrllock);
@@ -1739,16 +1663,16 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
if (!(buf = kmalloc(64, GFP_KERNEL)))
goto fail;
- if (usb_string(dev, dev->descriptor.iManufacturer, buf, 64) > 0) {
- strcat(hid->name, buf);
- if (usb_string(dev, dev->descriptor.iProduct, buf, 64) > 0)
- snprintf(hid->name, 64, "%s %s", hid->name, buf);
- } else if (usb_string(dev, dev->descriptor.iProduct, buf, 64) > 0) {
- snprintf(hid->name, 128, "%s", buf);
+ if (dev->manufacturer) {
+ strcat(hid->name, dev->manufacturer);
+ if (dev->product)
+ snprintf(hid->name, 64, "%s %s", hid->name, dev->product);
+ } else if (dev->product) {
+ snprintf(hid->name, 128, "%s", dev->product);
} else
- snprintf(hid->name, 128, "%04x:%04x",
- le16_to_cpu(dev->descriptor.idVendor),
- le16_to_cpu(dev->descriptor.idProduct));
+ snprintf(hid->name, 128, "%04x:%04x",
+ le16_to_cpu(dev->descriptor.idVendor),
+ le16_to_cpu(dev->descriptor.idProduct));
usb_make_path(dev, buf, 64);
snprintf(hid->phys, 64, "%s/input%d", buf,
@@ -1810,7 +1734,7 @@ static void hid_disconnect(struct usb_interface *intf)
hid_free_device(hid);
}
-static int hid_probe (struct usb_interface *intf, const struct usb_device_id *id)
+static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
struct hid_device *hid;
char path[64];
@@ -1892,7 +1816,7 @@ static int hid_resume(struct usb_interface *intf)
static struct usb_device_id hid_usb_ids [] = {
{ .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS,
- .bInterfaceClass = USB_INTERFACE_CLASS_HID },
+ .bInterfaceClass = USB_INTERFACE_CLASS_HID },
{ } /* Terminating entry */
};
diff --git a/drivers/usb/input/hid-debug.h b/drivers/usb/input/hid-debug.h
index 5ea2307403b87..2b91705740a73 100644
--- a/drivers/usb/input/hid-debug.h
+++ b/drivers/usb/input/hid-debug.h
@@ -473,7 +473,6 @@ static void __attribute__((unused)) hid_dump_input(struct hid_usage *usage, __s3
static char *events[EV_MAX + 1] = {
- [0 ... EV_MAX] = NULL,
[EV_SYN] = "Sync", [EV_KEY] = "Key",
[EV_REL] = "Relative", [EV_ABS] = "Absolute",
[EV_MSC] = "Misc", [EV_LED] = "LED",
@@ -483,11 +482,9 @@ static char *events[EV_MAX + 1] = {
};
static char *syncs[2] = {
- [0 ... 1] = NULL,
[SYN_REPORT] = "Report", [SYN_CONFIG] = "Config",
};
static char *keys[KEY_MAX + 1] = {
- [0 ... KEY_MAX] = NULL,
[KEY_RESERVED] = "Reserved", [KEY_ESC] = "Esc",
[KEY_1] = "1", [KEY_2] = "2",
[KEY_3] = "3", [KEY_4] = "4",
@@ -665,7 +662,6 @@ static char *keys[KEY_MAX + 1] = {
};
static char *relatives[REL_MAX + 1] = {
- [0 ... REL_MAX] = NULL,
[REL_X] = "X", [REL_Y] = "Y",
[REL_Z] = "Z", [REL_HWHEEL] = "HWheel",
[REL_DIAL] = "Dial", [REL_WHEEL] = "Wheel",
@@ -673,7 +669,6 @@ static char *relatives[REL_MAX + 1] = {
};
static char *absolutes[ABS_MAX + 1] = {
- [0 ... ABS_MAX] = NULL,
[ABS_X] = "X", [ABS_Y] = "Y",
[ABS_Z] = "Z", [ABS_RX] = "Rx",
[ABS_RY] = "Ry", [ABS_RZ] = "Rz",
@@ -690,13 +685,11 @@ static char *absolutes[ABS_MAX + 1] = {
};
static char *misc[MSC_MAX + 1] = {
- [ 0 ... MSC_MAX] = NULL,
[MSC_SERIAL] = "Serial", [MSC_PULSELED] = "Pulseled",
[MSC_GESTURE] = "Gesture", [MSC_RAW] = "RawData"
};
static char *leds[LED_MAX + 1] = {
- [0 ... LED_MAX] = NULL,
[LED_NUML] = "NumLock", [LED_CAPSL] = "CapsLock",
[LED_SCROLLL] = "ScrollLock", [LED_COMPOSE] = "Compose",
[LED_KANA] = "Kana", [LED_SLEEP] = "Sleep",
@@ -705,25 +698,22 @@ static char *leds[LED_MAX + 1] = {
};
static char *repeats[REP_MAX + 1] = {
- [0 ... REP_MAX] = NULL,
[REP_DELAY] = "Delay", [REP_PERIOD] = "Period"
};
static char *sounds[SND_MAX + 1] = {
- [0 ... SND_MAX] = NULL,
[SND_CLICK] = "Click", [SND_BELL] = "Bell",
[SND_TONE] = "Tone"
};
static char **names[EV_MAX + 1] = {
- [0 ... EV_MAX] = NULL,
[EV_SYN] = syncs, [EV_KEY] = keys,
[EV_REL] = relatives, [EV_ABS] = absolutes,
[EV_MSC] = misc, [EV_LED] = leds,
[EV_SND] = sounds, [EV_REP] = repeats,
};
-static void resolv_event(__u8 type, __u16 code) {
+static void __attribute__((unused)) resolv_event(__u8 type, __u16 code) {
printk("%s.%s", events[type] ? events[type] : "?",
names[type] ? (names[type][code] ? names[type][code] : "?") : "?");
diff --git a/drivers/usb/input/hid-ff.c b/drivers/usb/input/hid-ff.c
index f978680b9c0a2..72e698658b532 100644
--- a/drivers/usb/input/hid-ff.c
+++ b/drivers/usb/input/hid-ff.c
@@ -55,6 +55,7 @@ static struct hid_ff_initializer inits[] = {
{0x46d, 0xc211, hid_lgff_init}, // Logitech Cordless rumble pad
{0x46d, 0xc283, hid_lgff_init}, // Logitech Wingman Force 3d
{0x46d, 0xc295, hid_lgff_init}, // Logitech MOMO force wheel
+ {0x46d, 0xc219, hid_lgff_init}, // Logitech Cordless rumble pad 2
#endif
#ifdef CONFIG_HID_PID
{0x45e, 0x001b, hid_pid_init},
diff --git a/drivers/usb/input/hid-input.c b/drivers/usb/input/hid-input.c
index c90ff0f0362f6..5553c3553e9d1 100644
--- a/drivers/usb/input/hid-input.c
+++ b/drivers/usb/input/hid-input.c
@@ -404,7 +404,6 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct
return;
input_regs(input, regs);
- input_event(input, EV_MSC, MSC_SCAN, usage->hid);
if (!usage->type)
return;
@@ -483,10 +482,26 @@ void hidinput_report_event(struct hid_device *hid, struct hid_report *report)
}
}
+static int hidinput_find_field(struct hid_device *hid, unsigned int type, unsigned int code, struct hid_field **field)
+{
+ struct hid_report *report;
+ int i, j;
+
+ list_for_each_entry(report, &hid->report_enum[HID_OUTPUT_REPORT].report_list, list) {
+ for (i = 0; i < report->maxfield; i++) {
+ *field = report->field[i];
+ for (j = 0; j < (*field)->maxusage; j++)
+ if ((*field)->usage[j].type == type && (*field)->usage[j].code == code)
+ return j;
+ }
+ }
+ return -1;
+}
+
static int hidinput_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
{
struct hid_device *hid = dev->private;
- struct hid_field *field = NULL;
+ struct hid_field *field;
int offset;
if (type == EV_FF)
@@ -495,7 +510,7 @@ static int hidinput_input_event(struct input_dev *dev, unsigned int type, unsign
if (type != EV_LED)
return -1;
- if ((offset = hid_find_field(hid, type, code, &field)) == -1) {
+ if ((offset = hidinput_find_field(hid, type, code, &field)) == -1) {
warn("event field not found");
return -1;
}
@@ -527,9 +542,7 @@ static void hidinput_close(struct input_dev *dev)
int hidinput_connect(struct hid_device *hid)
{
struct usb_device *dev = hid->dev;
- struct hid_report_enum *report_enum;
struct hid_report *report;
- struct list_head *list;
struct hid_input *hidinput = NULL;
int i, j, k;
@@ -544,16 +557,11 @@ int hidinput_connect(struct hid_device *hid)
if (i == hid->maxcollection)
return -1;
- for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) {
- report_enum = hid->report_enum + k;
- list = report_enum->report_list.next;
- while (list != &report_enum->report_list) {
- report = (struct hid_report *) list;
+ for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++)
+ list_for_each_entry(report, &hid->report_enum[k].report_list, list) {
- if (!report->maxfield) {
- list = list->next;
+ if (!report->maxfield)
continue;
- }
if (!hidinput) {
hidinput = kmalloc(sizeof(*hidinput), GFP_KERNEL);
@@ -578,9 +586,6 @@ int hidinput_connect(struct hid_device *hid)
hidinput->input.id.product = le16_to_cpu(dev->descriptor.idProduct);
hidinput->input.id.version = le16_to_cpu(dev->descriptor.bcdDevice);
hidinput->input.dev = &hid->intf->dev;
-
- set_bit(EV_MSC, hidinput->input.evbit);
- set_bit(MSC_SCAN, hidinput->input.mscbit);
}
for (i = 0; i < report->maxfield; i++)
@@ -598,10 +603,7 @@ int hidinput_connect(struct hid_device *hid)
input_register_device(&hidinput->input);
hidinput = NULL;
}
-
- list = list->next;
}
- }
/* This only gets called when we are a single-input (most of the
* time). IOW, not a HID_QUIRK_MULTI_INPUT. The hid_ff_init() is
@@ -619,7 +621,7 @@ void hidinput_disconnect(struct hid_device *hid)
struct list_head *lh, *next;
struct hid_input *hidinput;
- list_for_each_safe (lh, next, &hid->inputs) {
+ list_for_each_safe(lh, next, &hid->inputs) {
hidinput = list_entry(lh, struct hid_input, list);
input_unregister_device(&hidinput->input);
list_del(&hidinput->list);
diff --git a/drivers/usb/input/hid-lgff.c b/drivers/usb/input/hid-lgff.c
index b86f822e2968e..0d7404bab92f7 100644
--- a/drivers/usb/input/hid-lgff.c
+++ b/drivers/usb/input/hid-lgff.c
@@ -126,6 +126,7 @@ static signed short ff_joystick[] = {
static struct device_type devices[] = {
{0x046d, 0xc211, ff_rumble},
+ {0x046d, 0xc219, ff_rumble},
{0x046d, 0xc283, ff_joystick},
{0x0000, 0x0000, ff_joystick}
};
diff --git a/drivers/usb/input/hid.h b/drivers/usb/input/hid.h
index 93f39abc1c947..6d9329c698d90 100644
--- a/drivers/usb/input/hid.h
+++ b/drivers/usb/input/hid.h
@@ -484,11 +484,10 @@ static inline void hidinput_disconnect(struct hid_device *hid) { }
int hid_open(struct hid_device *);
void hid_close(struct hid_device *);
-int hid_find_field(struct hid_device *, unsigned int, unsigned int, struct hid_field **);
int hid_set_field(struct hid_field *, unsigned, __s32);
void hid_submit_report(struct hid_device *, struct hid_report *, unsigned char dir);
void hid_init_reports(struct hid_device *hid);
-int hid_find_report_by_usage(struct hid_device *hid, __u32 wanted_usage, struct hid_report **report, int type);
+struct hid_field *hid_find_field_by_usage(struct hid_device *hid, __u32 wanted_usage, int type);
int hid_wait_io(struct hid_device* hid);
diff --git a/drivers/usb/input/hiddev.c b/drivers/usb/input/hiddev.c
index bf9a693a6f5a8..96b7c9067951d 100644
--- a/drivers/usb/input/hiddev.c
+++ b/drivers/usb/input/hiddev.c
@@ -124,7 +124,6 @@ hiddev_lookup_usage(struct hid_device *hid, struct hiddev_usage_ref *uref)
int i, j;
struct hid_report *report;
struct hid_report_enum *report_enum;
- struct list_head *list;
struct hid_field *field;
if (uref->report_type < HID_REPORT_TYPE_MIN ||
@@ -132,9 +131,8 @@ hiddev_lookup_usage(struct hid_device *hid, struct hiddev_usage_ref *uref)
report_enum = hid->report_enum +
(uref->report_type - HID_REPORT_TYPE_MIN);
- list = report_enum->report_list.next;
- while (list != &report_enum->report_list) {
- report = (struct hid_report *) list;
+
+ list_for_each_entry(report, &report_enum->report_list, list)
for (i = 0; i < report->maxfield; i++) {
field = report->field[i];
for (j = 0; j < field->maxusage; j++) {
@@ -146,8 +144,6 @@ hiddev_lookup_usage(struct hid_device *hid, struct hiddev_usage_ref *uref)
}
}
}
- list = list->next;
- }
return NULL;
}
@@ -634,9 +630,8 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
goto inval;
else if ((cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) &&
- (uref_multi->num_values >= HID_MAX_MULTI_USAGES ||
- uref->usage_index + uref_multi->num_values >= field->report_count ||
- uref->usage_index + uref_multi->num_values < uref->usage_index))
+ (uref_multi->num_values > HID_MAX_MULTI_USAGES ||
+ uref->usage_index + uref_multi->num_values >= field->report_count))
goto inval;
}
diff --git a/drivers/usb/input/mtouchusb.c b/drivers/usb/input/mtouchusb.c
index f0e75c939a487..6b45a66d58c15 100644
--- a/drivers/usb/input/mtouchusb.c
+++ b/drivers/usb/input/mtouchusb.c
@@ -34,6 +34,9 @@
* Eliminated vendor/product module params
* Performed multiple successfull tests with an EXII-5010UC
*
+ * 1.5 02/27/2005 ddstreet@ieee.org
+ * Added module parameter to select raw or hw-calibrated coordinate reporting
+ *
*****************************************************************************/
#include <linux/config.h>
@@ -52,11 +55,13 @@
#include <linux/usb.h>
#define MTOUCHUSB_MIN_XC 0x0
-#define MTOUCHUSB_MAX_XC 0x4000
+#define MTOUCHUSB_MAX_RAW_XC 0x4000
+#define MTOUCHUSB_MAX_CALIB_XC 0xffff
#define MTOUCHUSB_XC_FUZZ 0x0
#define MTOUCHUSB_XC_FLAT 0x0
#define MTOUCHUSB_MIN_YC 0x0
-#define MTOUCHUSB_MAX_YC 0x4000
+#define MTOUCHUSB_MAX_RAW_YC 0x4000
+#define MTOUCHUSB_MAX_CALIB_YC 0xffff
#define MTOUCHUSB_YC_FUZZ 0x0
#define MTOUCHUSB_YC_FLAT 0x0
@@ -65,15 +70,28 @@
#define MTOUCHUSB_REPORT_DATA_SIZE 11
#define MTOUCHUSB_REQ_CTRLLR_ID 10
-#define MTOUCHUSB_GET_XC(data) (data[8]<<8 | data[7])
-#define MTOUCHUSB_GET_YC(data) (data[10]<<8 | data[9])
+#define MTOUCHUSB_GET_RAW_XC(data) (data[8]<<8 | data[7])
+#define MTOUCHUSB_GET_CALIB_XC(data) (data[4]<<8 | data[3])
+#define MTOUCHUSB_GET_RAW_YC(data) (data[10]<<8 | data[9])
+#define MTOUCHUSB_GET_CALIB_YC(data) (data[6]<<8 | data[5])
+#define MTOUCHUSB_GET_XC(data) (raw_coordinates ? \
+ MTOUCHUSB_GET_RAW_XC(data) : \
+ MTOUCHUSB_GET_CALIB_XC(data))
+#define MTOUCHUSB_GET_YC(data) (raw_coordinates ? \
+ MTOUCHUSB_GET_RAW_YC(data) : \
+ MTOUCHUSB_GET_CALIB_YC(data))
#define MTOUCHUSB_GET_TOUCHED(data) ((data[2] & 0x40) ? 1:0)
-#define DRIVER_VERSION "v1.4"
+#define DRIVER_VERSION "v1.5"
#define DRIVER_AUTHOR "Todd E. Johnson, tejohnson@yahoo.com"
#define DRIVER_DESC "3M USB Touchscreen Driver"
#define DRIVER_LICENSE "GPL"
+static int raw_coordinates = 1;
+
+module_param(raw_coordinates, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(raw_coordinates, "report raw coordinate values (y, default) or hardware-calibrated coordinate values (n)");
+
struct mtouch_usb {
unsigned char *data;
dma_addr_t data_dma;
@@ -123,7 +141,8 @@ static void mtouchusb_irq(struct urb *urb, struct pt_regs *regs)
input_report_abs(&mtouch->input, ABS_X,
MTOUCHUSB_GET_XC(mtouch->data));
input_report_abs(&mtouch->input, ABS_Y,
- MTOUCHUSB_GET_YC(mtouch->data));
+ (raw_coordinates ? MTOUCHUSB_MAX_RAW_YC : MTOUCHUSB_MAX_CALIB_YC)
+ - MTOUCHUSB_GET_YC(mtouch->data));
input_sync(&mtouch->input);
exit:
@@ -187,7 +206,6 @@ static int mtouchusb_probe(struct usb_interface *intf, const struct usb_device_i
struct usb_endpoint_descriptor *endpoint;
struct usb_device *udev = interface_to_usbdev (intf);
char path[64];
- char *buf;
int nRet;
dbg("%s - called", __FUNCTION__);
@@ -234,32 +252,25 @@ static int mtouchusb_probe(struct usb_interface *intf, const struct usb_device_i
/* Used to Scale Compensated Data and Flip Y */
mtouch->input.absmin[ABS_X] = MTOUCHUSB_MIN_XC;
- mtouch->input.absmax[ABS_X] = MTOUCHUSB_MAX_XC;
+ mtouch->input.absmax[ABS_X] = raw_coordinates ? \
+ MTOUCHUSB_MAX_RAW_XC : MTOUCHUSB_MAX_CALIB_XC;
mtouch->input.absfuzz[ABS_X] = MTOUCHUSB_XC_FUZZ;
mtouch->input.absflat[ABS_X] = MTOUCHUSB_XC_FLAT;
mtouch->input.absmin[ABS_Y] = MTOUCHUSB_MIN_YC;
- mtouch->input.absmax[ABS_Y] = MTOUCHUSB_MAX_YC;
+ mtouch->input.absmax[ABS_Y] = raw_coordinates ? \
+ MTOUCHUSB_MAX_RAW_YC : MTOUCHUSB_MAX_CALIB_YC;
mtouch->input.absfuzz[ABS_Y] = MTOUCHUSB_YC_FUZZ;
mtouch->input.absflat[ABS_Y] = MTOUCHUSB_YC_FLAT;
- if (!(buf = kmalloc(63, GFP_KERNEL))) {
- kfree(mtouch);
- return -ENOMEM;
- }
-
- if (udev->descriptor.iManufacturer &&
- usb_string(udev, udev->descriptor.iManufacturer, buf, 63) > 0)
- strcat(mtouch->name, buf);
- if (udev->descriptor.iProduct &&
- usb_string(udev, udev->descriptor.iProduct, buf, 63) > 0)
- sprintf(mtouch->name, "%s %s", mtouch->name, buf);
+ if (udev->manufacturer)
+ strcat(mtouch->name, udev->manufacturer);
+ if (udev->product)
+ sprintf(mtouch->name, "%s %s", mtouch->name, udev->product);
if (!strlen(mtouch->name))
sprintf(mtouch->name, "USB Touchscreen %04x:%04x",
mtouch->input.id.vendor, mtouch->input.id.product);
- kfree(buf);
-
nRet = usb_control_msg(mtouch->udev,
usb_rcvctrlpipe(udev, 0),
MTOUCHUSB_RESET,
@@ -268,7 +279,7 @@ static int mtouchusb_probe(struct usb_interface *intf, const struct usb_device_i
0,
NULL,
0,
- HZ * USB_CTRL_SET_TIMEOUT);
+ USB_CTRL_SET_TIMEOUT);
dbg("%s - usb_control_msg - MTOUCHUSB_RESET - bytes|err: %d",
__FUNCTION__, nRet);
@@ -302,7 +313,7 @@ static int mtouchusb_probe(struct usb_interface *intf, const struct usb_device_i
1,
NULL,
0,
- HZ * USB_CTRL_SET_TIMEOUT);
+ USB_CTRL_SET_TIMEOUT);
dbg("%s - usb_control_msg - MTOUCHUSB_ASYNC_REPORT - bytes|err: %d",
__FUNCTION__, nRet);
diff --git a/drivers/usb/input/pid.c b/drivers/usb/input/pid.c
index d1ea1f0565991..2569638634781 100644
--- a/drivers/usb/input/pid.c
+++ b/drivers/usb/input/pid.c
@@ -48,106 +48,96 @@
/* Called when a transfer is completed */
static void hid_pid_ctrl_out(struct urb *u, struct pt_regs *regs)
{
- dev_dbg(&u->dev->dev, "hid_pid_ctrl_out - Transfer Completed\n");
+ dev_dbg(&u->dev->dev, "hid_pid_ctrl_out - Transfer Completed\n");
}
-static void hid_pid_exit(struct hid_device* hid)
+static void hid_pid_exit(struct hid_device *hid)
{
- struct hid_ff_pid *private = hid->ff_private;
-
- if (private->urbffout) {
- usb_kill_urb(private->urbffout);
- usb_free_urb(private->urbffout);
- }
+ struct hid_ff_pid *private = hid->ff_private;
+
+ if (private->urbffout) {
+ usb_kill_urb(private->urbffout);
+ usb_free_urb(private->urbffout);
+ }
}
-static int pid_upload_periodic(struct hid_ff_pid *pid, struct ff_effect *effect, int is_update) {
- dev_info(&pid->hid->dev->dev, "requested periodic force upload\n");
- return 0;
+static int pid_upload_periodic(struct hid_ff_pid *pid, struct ff_effect *effect, int is_update)
+{
+ dev_info(&pid->hid->dev->dev, "requested periodic force upload\n");
+ return 0;
}
-static int pid_upload_constant(struct hid_ff_pid *pid, struct ff_effect *effect, int is_update) {
- dev_info(&pid->hid->dev->dev, "requested constant force upload\n");
- return 0;
+static int pid_upload_constant(struct hid_ff_pid *pid, struct ff_effect *effect, int is_update)
+{
+ dev_info(&pid->hid->dev->dev, "requested constant force upload\n");
+ return 0;
}
-static int pid_upload_condition(struct hid_ff_pid *pid, struct ff_effect *effect, int is_update) {
- dev_info(&pid->hid->dev->dev, "requested Condition force upload\n");
- return 0;
+static int pid_upload_condition(struct hid_ff_pid *pid, struct ff_effect *effect, int is_update)
+{
+ dev_info(&pid->hid->dev->dev, "requested Condition force upload\n");
+ return 0;
}
-static int pid_upload_ramp(struct hid_ff_pid *pid, struct ff_effect *effect, int is_update) {
- dev_info(&pid->hid->dev->dev, "request ramp force upload\n");
- return 0;
+static int pid_upload_ramp(struct hid_ff_pid *pid, struct ff_effect *effect, int is_update)
+{
+ dev_info(&pid->hid->dev->dev, "request ramp force upload\n");
+ return 0;
}
static int hid_pid_event(struct hid_device *hid, struct input_dev *input,
- unsigned int type, unsigned int code, int value)
+ unsigned int type, unsigned int code, int value)
{
- dev_dbg(&hid->dev->dev, "PID event received: type=%d,code=%d,value=%d.\n", type, code, value);
+ dev_dbg(&hid->dev->dev, "PID event received: type=%d,code=%d,value=%d.\n", type, code, value);
- if (type != EV_FF)
- return -1;
+ if (type != EV_FF)
+ return -1;
-
-
- return 0;
+ return 0;
}
/* Lock must be held by caller */
-static void hid_pid_ctrl_playback(struct hid_device *hid,
- struct hid_pid_effect *effect, int play)
+static void hid_pid_ctrl_playback(struct hid_device *hid, struct hid_pid_effect *effect, int play)
{
- if (play) {
+ if (play)
set_bit(FF_PID_FLAGS_PLAYING, &effect->flags);
-
- } else {
+ else
clear_bit(FF_PID_FLAGS_PLAYING, &effect->flags);
- }
}
-
static int hid_pid_erase(struct input_dev *dev, int id)
{
struct hid_device *hid = dev->private;
- struct hid_field* field;
- struct hid_report* report;
struct hid_ff_pid *pid = hid->ff_private;
+ struct hid_field *field;
unsigned long flags;
- unsigned wanted_report = HID_UP_PID | FF_PID_USAGE_BLOCK_FREE; /* PID Block Free Report */
int ret;
if (!CHECK_OWNERSHIP(id, pid))
return -EACCES;
/* Find report */
- ret = hid_find_report_by_usage(hid, wanted_report, &report, HID_OUTPUT_REPORT);
- if(!ret) {
+ field = hid_find_field_by_usage(hid, HID_UP_PID | FF_PID_USAGE_BLOCK_FREE,
+ HID_OUTPUT_REPORT);
+ if (!field) {
dev_err(&hid->dev->dev, "couldn't find report\n");
- return ret;
- }
-
- /* Find field */
- field = (struct hid_field *) kmalloc(sizeof(struct hid_field), GFP_KERNEL);
- if(!field) {
- dev_err(&hid->dev->dev, "couldn't allocate field\n");
- return -ENOMEM;
+ return -EIO;
}
- ret = hid_set_field(field, ret, pid->effects[id].device_id);
- if(!ret) {
+ ret = hid_set_field(field, 0, pid->effects[id].device_id);
+ if (ret) {
dev_err(&hid->dev->dev, "couldn't set field\n");
return ret;
}
- hid_submit_report(hid, report, USB_DIR_OUT);
+ hid_submit_report(hid, field->report, USB_DIR_OUT);
spin_lock_irqsave(&pid->lock, flags);
hid_pid_ctrl_playback(hid, pid->effects + id, 0);
pid->effects[id].flags = 0;
spin_unlock_irqrestore(&pid->lock, flags);
- return ret;
+ return 0;
}
/* Erase all effects this process owns */
@@ -158,31 +148,32 @@ static int hid_pid_flush(struct input_dev *dev, struct file *file)
int i;
/*NOTE: no need to lock here. The only times EFFECT_USED is
- modified is when effects are uploaded or when an effect is
- erased. But a process cannot close its dev/input/eventX fd
- and perform ioctls on the same fd all at the same time */
- for (i=0; i<dev->ff_effects_max; ++i)
- if ( current->pid == pid->effects[i].owner
- && test_bit(FF_PID_FLAGS_USED, &pid->effects[i].flags))
+ modified is when effects are uploaded or when an effect is
+ erased. But a process cannot close its dev/input/eventX fd
+ and perform ioctls on the same fd all at the same time */
+ /*FIXME: multiple threads, anyone? */
+ for (i = 0; i < dev->ff_effects_max; ++i)
+ if (current->pid == pid->effects[i].owner
+ && test_bit(FF_PID_FLAGS_USED, &pid->effects[i].flags))
if (hid_pid_erase(dev, i))
dev_warn(&hid->dev->dev, "erase effect %d failed", i);
return 0;
}
-
static int hid_pid_upload_effect(struct input_dev *dev,
- struct ff_effect *effect)
+ struct ff_effect *effect)
{
- struct hid_ff_pid* pid_private = (struct hid_ff_pid*)(dev->private);
+ struct hid_ff_pid *pid_private = (struct hid_ff_pid *)(dev->private);
int ret;
int is_update;
- unsigned long flags = 0;
+ unsigned long flags;
- dev_dbg(&pid_private->hid->dev->dev, "upload effect called: effect_type=%x\n",effect->type);
+ dev_dbg(&pid_private->hid->dev->dev, "upload effect called: effect_type=%x\n", effect->type);
/* Check this effect type is supported by this device */
if (!test_bit(effect->type, dev->ffbit)) {
- dev_dbg(&pid_private->hid->dev->dev, "invalid kind of effect requested.\n");
+ dev_dbg(&pid_private->hid->dev->dev,
+ "invalid kind of effect requested.\n");
return -EINVAL;
}
@@ -190,31 +181,30 @@ static int hid_pid_upload_effect(struct input_dev *dev,
* If we want to create a new effect, get a free id
*/
if (effect->id == -1) {
- int id=0;
+ int id = 0;
// Spinlock so we don`t get a race condition when choosing IDs
spin_lock_irqsave(&pid_private->lock, flags);
- while(id < FF_EFFECTS_MAX)
- if (!test_and_set_bit(FF_PID_FLAGS_USED, &pid_private->effects[id++].flags))
- break;
+ while (id < FF_EFFECTS_MAX)
+ if (!test_and_set_bit(FF_PID_FLAGS_USED, &pid_private->effects[id++].flags))
+ break;
- if ( id == FF_EFFECTS_MAX) {
- spin_unlock_irqrestore(&pid_private->lock,flags);
+ if (id == FF_EFFECTS_MAX) {
+ spin_unlock_irqrestore(&pid_private->lock, flags);
// TEMP - We need to get ff_effects_max correctly first: || id >= dev->ff_effects_max) {
dev_dbg(&pid_private->hid->dev->dev, "Not enough device memory\n");
return -ENOMEM;
}
effect->id = id;
- dev_dbg(&pid_private->hid->dev->dev, "effect ID is %d\n.",id);
+ dev_dbg(&pid_private->hid->dev->dev, "effect ID is %d\n.", id);
pid_private->effects[id].owner = current->pid;
- pid_private->effects[id].flags = (1<<FF_PID_FLAGS_USED);
- spin_unlock_irqrestore(&pid_private->lock,flags);
+ pid_private->effects[id].flags = (1 << FF_PID_FLAGS_USED);
+ spin_unlock_irqrestore(&pid_private->lock, flags);
is_update = FF_PID_FALSE;
- }
- else {
+ } else {
/* We want to update an effect */
if (!CHECK_OWNERSHIP(effect->id, pid_private))
return -EACCES;
@@ -224,9 +214,8 @@ static int hid_pid_upload_effect(struct input_dev *dev,
return -EINVAL;
/* Check the effect is not already being updated */
- if (test_bit(FF_PID_FLAGS_UPDATING, &pid_private->effects[effect->id].flags)) {
+ if (test_bit(FF_PID_FLAGS_UPDATING, &pid_private->effects[effect->id].flags))
return -EAGAIN;
- }
is_update = FF_PID_TRUE;
}
@@ -235,28 +224,30 @@ static int hid_pid_upload_effect(struct input_dev *dev,
* Upload the effect
*/
switch (effect->type) {
- case FF_PERIODIC:
- ret = pid_upload_periodic(pid_private, effect, is_update);
- break;
-
- case FF_CONSTANT:
- ret = pid_upload_constant(pid_private, effect, is_update);
- break;
-
- case FF_SPRING:
- case FF_FRICTION:
- case FF_DAMPER:
- case FF_INERTIA:
- ret = pid_upload_condition(pid_private, effect, is_update);
- break;
-
- case FF_RAMP:
- ret = pid_upload_ramp(pid_private, effect, is_update);
- break;
-
- default:
- dev_dbg(&pid_private->hid->dev->dev, "invalid type of effect requested - %x.\n", effect->type);
- return -EINVAL;
+ case FF_PERIODIC:
+ ret = pid_upload_periodic(pid_private, effect, is_update);
+ break;
+
+ case FF_CONSTANT:
+ ret = pid_upload_constant(pid_private, effect, is_update);
+ break;
+
+ case FF_SPRING:
+ case FF_FRICTION:
+ case FF_DAMPER:
+ case FF_INERTIA:
+ ret = pid_upload_condition(pid_private, effect, is_update);
+ break;
+
+ case FF_RAMP:
+ ret = pid_upload_ramp(pid_private, effect, is_update);
+ break;
+
+ default:
+ dev_dbg(&pid_private->hid->dev->dev,
+ "invalid type of effect requested - %x.\n",
+ effect->type);
+ return -EINVAL;
}
/* If a packet was sent, forbid new updates until we are notified
* that the packet was updated
@@ -269,37 +260,36 @@ 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);
-
- private = hid->ff_private = kmalloc(sizeof(struct hid_ff_pid), GFP_KERNEL);
- if (!private) return -1;
-
- memset(private,0,sizeof(struct hid_ff_pid));
-
- hid->ff_private = private; /* 'cause memset can move the block away */
-
- private->hid = hid;
-
- hid->ff_exit = hid_pid_exit;
- hid->ff_event = hid_pid_event;
-
- /* Open output URB */
- if (!(private->urbffout = usb_alloc_urb(0, GFP_KERNEL))) {
- kfree(private);
- return -1;
- }
-
- usb_fill_control_urb(private->urbffout, hid->dev,0,(void *) &private->ffcr,private->ctrl_buffer,8,hid_pid_ctrl_out,hid);
- hidinput->input.upload_effect = hid_pid_upload_effect;
- hidinput->input.flush = hid_pid_flush;
- hidinput->input.ff_effects_max = 8; // A random default
- set_bit(EV_FF, hidinput->input.evbit);
- set_bit(EV_FF_STATUS, hidinput->input.evbit);
-
- spin_lock_init(&private->lock);
-
- printk(KERN_INFO "Force feedback driver for PID devices by Rodrigo Damazio <rdamazio@lsi.usp.br>.\n");
-
- return 0;
+ struct hid_ff_pid *private;
+ struct hid_input *hidinput = list_entry(&hid->inputs, struct hid_input, list);
+
+ private = hid->ff_private = kcalloc(1, sizeof(struct hid_ff_pid), GFP_KERNEL);
+ if (!private)
+ return -ENOMEM;
+
+ private->hid = hid;
+
+ hid->ff_exit = hid_pid_exit;
+ hid->ff_event = hid_pid_event;
+
+ /* Open output URB */
+ if (!(private->urbffout = usb_alloc_urb(0, GFP_KERNEL))) {
+ kfree(private);
+ return -1;
+ }
+
+ usb_fill_control_urb(private->urbffout, hid->dev, 0,
+ (void *)&private->ffcr, private->ctrl_buffer, 8,
+ hid_pid_ctrl_out, hid);
+ hidinput->input.upload_effect = hid_pid_upload_effect;
+ hidinput->input.flush = hid_pid_flush;
+ hidinput->input.ff_effects_max = 8; // A random default
+ set_bit(EV_FF, hidinput->input.evbit);
+ set_bit(EV_FF_STATUS, hidinput->input.evbit);
+
+ spin_lock_init(&private->lock);
+
+ printk(KERN_INFO "Force feedback driver for PID devices by Rodrigo Damazio <rdamazio@lsi.usp.br>.\n");
+
+ return 0;
}
diff --git a/drivers/usb/input/pid.h b/drivers/usb/input/pid.h
index a27e48b8026dd..a2cb9627ed0e3 100644
--- a/drivers/usb/input/pid.h
+++ b/drivers/usb/input/pid.h
@@ -25,31 +25,31 @@
#define FF_EFFECTS_MAX 64
-#define FF_PID_FLAGS_USED 1 /* If the effect exists */
-#define FF_PID_FLAGS_UPDATING 2 /* If the effect is being updated */
-#define FF_PID_FLAGS_PLAYING 3 /* If the effect is currently being played */
+#define FF_PID_FLAGS_USED 1 /* If the effect exists */
+#define FF_PID_FLAGS_UPDATING 2 /* If the effect is being updated */
+#define FF_PID_FLAGS_PLAYING 3 /* If the effect is currently being played */
#define FF_PID_FALSE 0
#define FF_PID_TRUE 1
struct hid_pid_effect {
- unsigned long flags;
- pid_t owner;
- unsigned int device_id; // The device-assigned ID
- struct ff_effect effect;
+ unsigned long flags;
+ pid_t owner;
+ unsigned int device_id; /* The device-assigned ID */
+ struct ff_effect effect;
};
struct hid_ff_pid {
- struct hid_device *hid;
- unsigned long int gain;
+ struct hid_device *hid;
+ unsigned long gain;
- struct urb *urbffout;
- struct usb_ctrlrequest ffcr;
- spinlock_t lock;
+ struct urb *urbffout;
+ struct usb_ctrlrequest ffcr;
+ spinlock_t lock;
- char ctrl_buffer[8];
+ unsigned char ctrl_buffer[8];
- struct hid_pid_effect effects[FF_EFFECTS_MAX];
+ struct hid_pid_effect effects[FF_EFFECTS_MAX];
};
/*
diff --git a/drivers/usb/input/powermate.c b/drivers/usb/input/powermate.c
index 6e77750b44a45..7fa2f9b9fb69a 100644
--- a/drivers/usb/input/powermate.c
+++ b/drivers/usb/input/powermate.c
@@ -320,7 +320,7 @@ static int powermate_probe(struct usb_interface *intf, const struct usb_device_i
usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
0x0a, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
0, interface->desc.bInterfaceNumber, NULL, 0,
- HZ * USB_CTRL_SET_TIMEOUT);
+ USB_CTRL_SET_TIMEOUT);
if (!(pm = kmalloc(sizeof(struct powermate_device), GFP_KERNEL)))
return -ENOMEM;
@@ -395,6 +395,7 @@ static int powermate_probe(struct usb_interface *intf, const struct usb_device_i
pm->input.id.version = le16_to_cpu(udev->descriptor.bcdDevice);
pm->input.event = powermate_input_event;
pm->input.dev = &intf->dev;
+ pm->input.phys = pm->phys;
input_register_device(&pm->input);
diff --git a/drivers/usb/input/touchkitusb.c b/drivers/usb/input/touchkitusb.c
index 734e1114aafba..a71f1bbd0a174 100644
--- a/drivers/usb/input/touchkitusb.c
+++ b/drivers/usb/input/touchkitusb.c
@@ -184,7 +184,6 @@ static int touchkit_probe(struct usb_interface *intf,
struct usb_endpoint_descriptor *endpoint;
struct usb_device *udev = interface_to_usbdev(intf);
char path[64];
- char *buf;
interface = intf->cur_altsetting;
endpoint = &interface->endpoint[0].desc;
@@ -230,25 +229,15 @@ static int touchkit_probe(struct usb_interface *intf,
touchkit->input.absfuzz[ABS_Y] = TOUCHKIT_YC_FUZZ;
touchkit->input.absflat[ABS_Y] = TOUCHKIT_YC_FLAT;
- buf = kmalloc(63, GFP_KERNEL);
- if (!buf) {
- ret = -ENOMEM;
- goto out_free_buffers;
- }
-
- if (udev->descriptor.iManufacturer &&
- usb_string(udev, udev->descriptor.iManufacturer, buf, 63) > 0)
- strcat(touchkit->name, buf);
- if (udev->descriptor.iProduct &&
- usb_string(udev, udev->descriptor.iProduct, buf, 63) > 0)
- sprintf(touchkit->name, "%s %s", touchkit->name, buf);
+ if (udev->manufacturer)
+ strcat(touchkit->name, udev->manufacturer);
+ if (udev->product)
+ sprintf(touchkit->name, "%s %s", touchkit->name, udev->product);
if (!strlen(touchkit->name))
sprintf(touchkit->name, "USB Touchscreen %04x:%04x",
touchkit->input.id.vendor, touchkit->input.id.product);
- kfree(buf);
-
touchkit->irq = usb_alloc_urb(0, GFP_KERNEL);
if (!touchkit->irq) {
dbg("%s - usb_alloc_urb failed: touchkit->irq", __FUNCTION__);
diff --git a/drivers/usb/input/usbkbd.c b/drivers/usb/input/usbkbd.c
index 148d81e034803..01514b0551b86 100644
--- a/drivers/usb/input/usbkbd.c
+++ b/drivers/usb/input/usbkbd.c
@@ -238,7 +238,6 @@ static int usb_kbd_probe(struct usb_interface *iface,
struct usb_kbd *kbd;
int i, pipe, maxp;
char path[64];
- char *buf;
interface = iface->cur_altsetting;
@@ -301,26 +300,15 @@ static int usb_kbd_probe(struct usb_interface *iface,
kbd->dev.id.version = le16_to_cpu(dev->descriptor.bcdDevice);
kbd->dev.dev = &iface->dev;
- if (!(buf = kmalloc(63, GFP_KERNEL))) {
- usb_free_urb(kbd->irq);
- usb_kbd_free_mem(dev, kbd);
- kfree(kbd);
- return -ENOMEM;
- }
-
- if (dev->descriptor.iManufacturer &&
- usb_string(dev, dev->descriptor.iManufacturer, buf, 63) > 0)
- strcat(kbd->name, buf);
- if (dev->descriptor.iProduct &&
- usb_string(dev, dev->descriptor.iProduct, buf, 63) > 0)
- sprintf(kbd->name, "%s %s", kbd->name, buf);
+ if (dev->manufacturer)
+ strcat(kbd->name, dev->manufacturer);
+ if (dev->product)
+ sprintf(kbd->name, "%s %s", kbd->name, dev->product);
if (!strlen(kbd->name))
sprintf(kbd->name, "USB HIDBP Keyboard %04x:%04x",
kbd->dev.id.vendor, kbd->dev.id.product);
- kfree(buf);
-
usb_fill_control_urb(kbd->led, dev, usb_sndctrlpipe(dev, 0),
(void *) kbd->cr, kbd->leds, 1,
usb_kbd_led, kbd);
diff --git a/drivers/usb/input/usbmouse.c b/drivers/usb/input/usbmouse.c
index 54b247cfd3127..01155bbddd43b 100644
--- a/drivers/usb/input/usbmouse.c
+++ b/drivers/usb/input/usbmouse.c
@@ -129,7 +129,6 @@ static int usb_mouse_probe(struct usb_interface * intf, const struct usb_device_
struct usb_mouse *mouse;
int pipe, maxp;
char path[64];
- char *buf;
interface = intf->cur_altsetting;
@@ -185,25 +184,15 @@ static int usb_mouse_probe(struct usb_interface * intf, const struct usb_device_
mouse->dev.id.version = le16_to_cpu(dev->descriptor.bcdDevice);
mouse->dev.dev = &intf->dev;
- if (!(buf = kmalloc(63, GFP_KERNEL))) {
- usb_buffer_free(dev, 8, mouse->data, mouse->data_dma);
- kfree(mouse);
- return -ENOMEM;
- }
-
- if (dev->descriptor.iManufacturer &&
- usb_string(dev, dev->descriptor.iManufacturer, buf, 63) > 0)
- strcat(mouse->name, buf);
- if (dev->descriptor.iProduct &&
- usb_string(dev, dev->descriptor.iProduct, buf, 63) > 0)
- sprintf(mouse->name, "%s %s", mouse->name, buf);
+ if (dev->manufacturer)
+ strcat(mouse->name, dev->manufacturer);
+ if (dev->product)
+ sprintf(mouse->name, "%s %s", mouse->name, dev->product);
if (!strlen(mouse->name))
sprintf(mouse->name, "USB HIDBP Mouse %04x:%04x",
mouse->dev.id.vendor, mouse->dev.id.product);
- kfree(buf);
-
usb_fill_int_urb(mouse->irq, dev, pipe, mouse->data,
(maxp > 8 ? 8 : maxp),
usb_mouse_irq, mouse, endpoint->bInterval);
diff --git a/drivers/usb/input/wacom.c b/drivers/usb/input/wacom.c
index f2f34392f8556..fec04dda088ea 100644
--- a/drivers/usb/input/wacom.c
+++ b/drivers/usb/input/wacom.c
@@ -72,7 +72,7 @@
/*
* Version Information
*/
-#define DRIVER_VERSION "v1.30"
+#define DRIVER_VERSION "v1.40"
#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>"
#define DRIVER_DESC "USB Wacom Graphire and Wacom Intuos tablet driver"
#define DRIVER_LICENSE "GPL"
@@ -115,7 +115,7 @@ static int usb_set_report(struct usb_interface *intf, unsigned char type,
usb_sndctrlpipe(interface_to_usbdev(intf), 0),
USB_REQ_SET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
(type << 8) + id, intf->altsetting[0].desc.bInterfaceNumber,
- buf, size, HZ);
+ buf, size, 1000);
}
static void wacom_pl_irq(struct urb *urb, struct pt_regs *regs)
@@ -141,8 +141,10 @@ static void wacom_pl_irq(struct urb *urb, struct pt_regs *regs)
goto exit;
}
- if (data[0] != 2)
+ if (data[0] != 2) {
dbg("wacom_pl_irq: received unknown report #%d", data[0]);
+ goto exit;
+ }
prox = data[1] & 0x40;
@@ -233,6 +235,7 @@ static void wacom_ptu_irq(struct urb *urb, struct pt_regs *regs)
if (data[0] != 2)
{
printk(KERN_INFO "wacom_ptu_irq: received unknown report #%d\n", data[0]);
+ goto exit;
}
input_regs(dev, regs);
@@ -246,9 +249,9 @@ static void wacom_ptu_irq(struct urb *urb, struct pt_regs *regs)
input_report_key(dev, BTN_TOOL_PEN, data[1] & 0x20);
input_report_key(dev, BTN_TOUCH, data[1] & 0x01);
}
- input_report_abs(dev, ABS_X, data[3] << 8 | data[2]);
- input_report_abs(dev, ABS_Y, data[5] << 8 | data[4]);
- input_report_abs(dev, ABS_PRESSURE, (data[6]|data[7] << 8));
+ input_report_abs(dev, ABS_X, le16_to_cpu(*(__le16 *) &data[2]));
+ input_report_abs(dev, ABS_Y, le16_to_cpu(*(__le16 *) &data[4]));
+ input_report_abs(dev, ABS_PRESSURE, le16_to_cpu(*(__le16 *) &data[6]));
input_report_key(dev, BTN_STYLUS, data[1] & 0x02);
input_report_key(dev, BTN_STYLUS2, data[1] & 0x10);
@@ -283,10 +286,15 @@ static void wacom_penpartner_irq(struct urb *urb, struct pt_regs *regs)
goto exit;
}
+ if (data[0] != 2) {
+ printk(KERN_INFO "wacom_penpartner_irq: received unknown report #%d\n", data[0]);
+ goto exit;
+ }
+
input_regs(dev, regs);
input_report_key(dev, BTN_TOOL_PEN, 1);
- input_report_abs(dev, ABS_X, le16_to_cpu(get_unaligned((__le16 *) &data[1])));
- input_report_abs(dev, ABS_Y, le16_to_cpu(get_unaligned((__le16 *) &data[3])));
+ input_report_abs(dev, ABS_X, le16_to_cpu(*(__le16 *) &data[1]));
+ input_report_abs(dev, ABS_Y, le16_to_cpu(*(__le16 *) &data[3]));
input_report_abs(dev, ABS_PRESSURE, (signed char)data[6] + 127);
input_report_key(dev, BTN_TOUCH, ((signed char)data[6] > -80) && !(data[5] & 0x20));
input_report_key(dev, BTN_STYLUS, (data[5] & 0x40));
@@ -322,12 +330,10 @@ static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs)
goto exit;
}
- /* check if we can handle the data */
- if (data[0] == 99)
- goto exit;
-
- if (data[0] != 2)
+ if (data[0] != 2) {
dbg("wacom_graphire_irq: received unknown report #%d", data[0]);
+ goto exit;
+ }
x = le16_to_cpu(*(__le16 *) &data[2]);
y = le16_to_cpu(*(__le16 *) &data[4]);
@@ -381,107 +387,171 @@ exit:
__FUNCTION__, retval);
}
-static void wacom_intuos_irq(struct urb *urb, struct pt_regs *regs)
+static int wacom_intuos_inout(struct urb *urb)
{
struct wacom *wacom = urb->context;
unsigned char *data = wacom->data;
struct input_dev *dev = &wacom->dev;
- unsigned int t;
int idx;
- int retval;
-
- switch (urb->status) {
- case 0:
- /* success */
- break;
- case -ECONNRESET:
- case -ENOENT:
- case -ESHUTDOWN:
- /* this urb is terminated, clean up */
- dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
- return;
- default:
- dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
- goto exit;
- }
-
- if (data[0] != 2)
- dbg("wacom_intuos_irq: received unknown report #%d", data[0]);
-
- input_regs(dev, regs);
/* tool number */
idx = data[1] & 0x01;
- if ((data[1] & 0xfc) == 0xc0) { /* Enter report */
-
- wacom->serial[idx] = ((__u32)(data[3] & 0x0f) << 28) + /* serial number of the tool */
+ /* Enter report */
+ if ((data[1] & 0xfc) == 0xc0)
+ {
+ /* serial number of the tool */
+ wacom->serial[idx] = ((__u32)(data[3] & 0x0f) << 28) +
((__u32)data[4] << 20) + ((__u32)data[5] << 12) +
((__u32)data[6] << 4) + (data[7] >> 4);
switch (((__u32)data[2] << 4) | (data[3] >> 4)) {
- case 0x812:
- case 0x012: wacom->tool[idx] = BTN_TOOL_PENCIL; break; /* Inking pen */
- case 0x822:
+ case 0x812: /* Inking pen */
+ case 0x801: /* Intuos3 Inking pen */
+ case 0x012:
+ wacom->tool[idx] = BTN_TOOL_PENCIL;
+ break;
+ case 0x822: /* Pen */
case 0x842:
case 0x852:
- case 0x022: wacom->tool[idx] = BTN_TOOL_PEN; break; /* Pen */
- case 0x832:
- case 0x032: wacom->tool[idx] = BTN_TOOL_BRUSH; break; /* Stroke pen */
- case 0x007:
+ case 0x823: /* Intuos3 Grip Pen */
+ case 0x813: /* Intuos3 Classic Pen */
+ case 0x885: /* Intuos3 Marker Pen */
+ case 0x022:
+ wacom->tool[idx] = BTN_TOOL_PEN;
+ break;
+ case 0x832: /* Stroke pen */
+ case 0x032:
+ wacom->tool[idx] = BTN_TOOL_BRUSH;
+ break;
+ case 0x007: /* Mouse 4D and 2D */
case 0x09c:
- case 0x094: wacom->tool[idx] = BTN_TOOL_MOUSE; break; /* Mouse 4D and 2D */
- case 0x096: wacom->tool[idx] = BTN_TOOL_LENS; break; /* Lens cursor */
- case 0x82a:
+ case 0x094:
+ case 0x017: /* Intuos3 2D Mouse */
+ wacom->tool[idx] = BTN_TOOL_MOUSE;
+ break;
+ case 0x096: /* Lens cursor */
+ case 0x097: /* Intuos3 Lens cursor */
+ wacom->tool[idx] = BTN_TOOL_LENS;
+ break;
+ case 0x82a: /* Eraser */
case 0x85a:
case 0x91a:
case 0xd1a:
- case 0x0fa: wacom->tool[idx] = BTN_TOOL_RUBBER; break; /* Eraser */
+ case 0x0fa:
+ case 0x82b: /* Intuos3 Grip Pen Eraser */
+ case 0x81b: /* Intuos3 Classic Pen Eraser */
+ case 0x91b: /* Intuos3 Airbrush Eraser */
+ wacom->tool[idx] = BTN_TOOL_RUBBER;
+ break;
case 0xd12:
case 0x912:
- case 0x112: wacom->tool[idx] = BTN_TOOL_AIRBRUSH; break; /* Airbrush */
- default: wacom->tool[idx] = BTN_TOOL_PEN; break; /* Unknown tool */
+ case 0x112:
+ case 0x913: /* Intuos3 Airbrush */
+ wacom->tool[idx] = BTN_TOOL_AIRBRUSH;
+ break; /* Airbrush */
+ default: /* Unknown tool */
+ wacom->tool[idx] = BTN_TOOL_PEN;
}
-
input_report_key(dev, wacom->tool[idx], 1);
input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
input_sync(dev);
- goto exit;
+ return 1;
}
- if ((data[1] & 0xfe) == 0x80) { /* Exit report */
+ /* Exit report */
+ if ((data[1] & 0xfe) == 0x80) {
input_report_key(dev, wacom->tool[idx], 0);
input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
input_sync(dev);
- goto exit;
+ return 1;
}
- input_report_abs(dev, ABS_X, be16_to_cpu(*(__be16 *) &data[2]));
- input_report_abs(dev, ABS_Y, be16_to_cpu(*(__be16 *) &data[4]));
- input_report_abs(dev, ABS_DISTANCE, data[9]);
+ return 0;
+}
- if ((data[1] & 0xb8) == 0xa0) { /* general pen packet */
- input_report_abs(dev, ABS_PRESSURE, t = ((__u32)data[6] << 2) | ((data[7] >> 6) & 3));
- input_report_abs(dev, ABS_TILT_X, ((data[7] << 1) & 0x7e) | (data[8] >> 7));
+static void wacom_intuos_general(struct urb *urb)
+{
+ struct wacom *wacom = urb->context;
+ unsigned char *data = wacom->data;
+ struct input_dev *dev = &wacom->dev;
+ unsigned int t;
+
+ /* general pen packet */
+ if ((data[1] & 0xb8) == 0xa0)
+ {
+ t = ((__u32)data[6] << 2) | ((data[7] >> 6) & 3);
+ input_report_abs(dev, ABS_PRESSURE, t);
+ input_report_abs(dev, ABS_TILT_X,
+ ((data[7] << 1) & 0x7e) | (data[8] >> 7));
input_report_abs(dev, ABS_TILT_Y, data[8] & 0x7f);
input_report_key(dev, BTN_STYLUS, data[1] & 2);
input_report_key(dev, BTN_STYLUS2, data[1] & 4);
input_report_key(dev, BTN_TOUCH, t > 10);
}
- if ((data[1] & 0xbc) == 0xb4) { /* airbrush second packet */
- input_report_abs(dev, ABS_WHEEL, ((__u32)data[6] << 2) | ((data[7] >> 6) & 3));
- input_report_abs(dev, ABS_TILT_X, ((data[7] << 1) & 0x7e) | (data[8] >> 7));
+ /* airbrush second packet */
+ if ((data[1] & 0xbc) == 0xb4)
+ {
+ input_report_abs(dev, ABS_WHEEL,
+ ((__u32)data[6] << 2) | ((data[7] >> 6) & 3));
+ input_report_abs(dev, ABS_TILT_X,
+ ((data[7] << 1) & 0x7e) | (data[8] >> 7));
input_report_abs(dev, ABS_TILT_Y, data[8] & 0x7f);
}
+ return;
+}
+
+static void wacom_intuos_irq(struct urb *urb, struct pt_regs *regs)
+{
+ struct wacom *wacom = urb->context;
+ unsigned char *data = wacom->data;
+ struct input_dev *dev = &wacom->dev;
+ unsigned int t;
+ int idx;
+ int retval;
+
+ switch (urb->status) {
+ case 0:
+ /* success */
+ break;
+ case -ECONNRESET:
+ case -ENOENT:
+ case -ESHUTDOWN:
+ /* this urb is terminated, clean up */
+ dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
+ return;
+ default:
+ dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
+ goto exit;
+ }
+
+ if (data[0] != 2 && data[0] != 5 && data[0] != 6) {
+ dbg("wacom_intuos_irq: received unknown report #%d", data[0]);
+ goto exit;
+ }
+
+ input_regs(dev, regs);
+
+ /* tool number */
+ idx = data[1] & 0x01;
+
+ /* process in/out prox events */
+ if (wacom_intuos_inout(urb)) goto exit;
+
+ input_report_abs(dev, ABS_X, be16_to_cpu(*(__be16 *) &data[2]));
+ input_report_abs(dev, ABS_Y, be16_to_cpu(*(__be16 *) &data[4]));
+ input_report_abs(dev, ABS_DISTANCE, data[9]);
+
+ /* process general packets */
+ wacom_intuos_general(urb);
if ((data[1] & 0xbc) == 0xa8 || (data[1] & 0xbe) == 0xb0) { /* 4D mouse or Lens cursor packets */
if (data[1] & 0x02) { /* Rotation packet */
- input_report_abs(dev, ABS_RZ, (data[7] & 0x20) ?
- ((__u32)data[6] << 3) | ((data[7] >> 5) & 7):
- (-(((__u32)data[6] << 3) | ((data[7] >> 5) & 7))) - 1);
+ t = ((__u32)data[6] << 3) | ((data[7] >> 5) & 7);
+ input_report_abs(dev, ABS_RZ, (data[7] & 0x20) ? ((t - 1) / 2) : -t / 2);
} else {
@@ -493,9 +563,8 @@ static void wacom_intuos_irq(struct urb *urb, struct pt_regs *regs)
input_report_key(dev, BTN_SIDE, data[8] & 0x20);
input_report_key(dev, BTN_EXTRA, data[8] & 0x10);
- input_report_abs(dev, ABS_THROTTLE, -((data[8] & 0x08) ?
- ((__u32)data[6] << 2) | ((data[7] >> 6) & 3) :
- -((__u32)data[6] << 2) | ((data[7] >> 6) & 3)));
+ t = ((__u32)data[6] << 2) | ((data[7] >> 6) & 3);
+ input_report_abs(dev, ABS_THROTTLE, (data[8] & 0x08) ? -t : t);
} else {
if (wacom->tool[idx] == BTN_TOOL_MOUSE) { /* 2D mouse packets */
@@ -527,6 +596,111 @@ exit:
__FUNCTION__, retval);
}
+static void wacom_intuos3_irq(struct urb *urb, struct pt_regs *regs)
+{
+ struct wacom *wacom = urb->context;
+ unsigned char *data = wacom->data;
+ struct input_dev *dev = &wacom->dev;
+ unsigned int t;
+ int idx, retval;
+
+ switch (urb->status) {
+ case 0:
+ /* success */
+ break;
+ case -ECONNRESET:
+ case -ENOENT:
+ case -ESHUTDOWN:
+ /* this urb is terminated, clean up */
+ dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
+ return;
+ default:
+ dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
+ goto exit;
+ }
+
+ /* check for valid report */
+ if (data[0] != 2 && data[0] != 5 && data[0] != 12)
+ {
+ printk(KERN_INFO "wacom_intuos3_irq: received unknown report #%d\n", data[0]);
+ goto exit;
+ }
+
+ input_regs(dev, regs);
+
+ /* tool index is always 0 here since there is no dual input tool */
+ idx = data[1] & 0x01;
+
+ /* pad packets. Works as a second tool and is always in prox */
+ if (data[0] == 12)
+ {
+ /* initiate the pad as a device */
+ if (wacom->tool[1] != BTN_TOOL_FINGER)
+ {
+ wacom->tool[1] = BTN_TOOL_FINGER;
+ input_report_key(dev, wacom->tool[1], 1);
+ }
+ input_report_key(dev, BTN_0, (data[5] & 0x01));
+ input_report_key(dev, BTN_1, (data[5] & 0x02));
+ input_report_key(dev, BTN_2, (data[5] & 0x04));
+ input_report_key(dev, BTN_3, (data[5] & 0x08));
+ input_report_key(dev, BTN_4, (data[6] & 0x01));
+ input_report_key(dev, BTN_5, (data[6] & 0x02));
+ input_report_key(dev, BTN_6, (data[6] & 0x04));
+ input_report_key(dev, BTN_7, (data[6] & 0x08));
+ input_report_abs(dev, ABS_RX, ((data[1] & 0x1f) << 8) | data[2]);
+ input_report_abs(dev, ABS_RY, ((data[3] & 0x1f) << 8) | data[4]);
+ input_event(dev, EV_MSC, MSC_SERIAL, 0xffffffff);
+ input_sync(dev);
+ goto exit;
+ }
+
+ /* process in/out prox events */
+ if (wacom_intuos_inout(urb)) goto exit;
+
+ input_report_abs(dev, ABS_X, ((__u32)data[2] << 9) | ((__u32)data[3] << 1) | ((data[9] >> 1) & 1));
+ input_report_abs(dev, ABS_Y, ((__u32)data[4] << 9) | ((__u32)data[5] << 1) | (data[9] & 1));
+ input_report_abs(dev, ABS_DISTANCE, ((data[9] >> 2) & 0x3f));
+
+ /* process general packets */
+ wacom_intuos_general(urb);
+
+ if ((data[1] & 0xbc) == 0xa8 || (data[1] & 0xbe) == 0xb0)
+ {
+ /* Marker pen rotation packet. Reported as wheel due to valuator limitation */
+ if (data[1] & 0x02)
+ {
+ t = ((__u32)data[6] << 3) | ((data[7] >> 5) & 7);
+ t = (data[7] & 0x20) ? ((t > 900) ? ((t-1) / 2 - 1350) :
+ ((t-1) / 2 + 450)) : (450 - t / 2) ;
+ input_report_abs(dev, ABS_WHEEL, t);
+ }
+
+ /* 2D mouse packets */
+ if (wacom->tool[idx] == BTN_TOOL_MOUSE)
+ {
+ input_report_key(dev, BTN_LEFT, data[8] & 0x04);
+ input_report_key(dev, BTN_MIDDLE, data[8] & 0x08);
+ input_report_key(dev, BTN_RIGHT, data[8] & 0x10);
+ input_report_key(dev, BTN_SIDE, data[8] & 0x40);
+ input_report_key(dev, BTN_EXTRA, data[8] & 0x20);
+ /* mouse wheel is positive when rolled backwards */
+ input_report_rel(dev, REL_WHEEL, ((__u32)((data[8] & 0x02) >> 1)
+ - (__u32)(data[8] & 0x01)));
+ }
+ }
+
+ input_report_key(dev, wacom->tool[idx], 1);
+ input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
+ input_sync(dev);
+
+exit:
+ retval = usb_submit_urb (urb, GFP_ATOMIC);
+ if (retval)
+ err ("%s - usb_submit_urb failed with result %d",
+ __FUNCTION__, retval);
+}
+
static struct wacom_features wacom_features[] = {
{ "Wacom Penpartner", 7, 5040, 3780, 255, 32, 0, wacom_penpartner_irq },
{ "Wacom Graphire", 8, 10206, 7422, 511, 32, 1, wacom_graphire_irq },
@@ -552,6 +726,9 @@ static struct wacom_features wacom_features[] = {
{ "Wacom Intuos2 12x18", 10, 45720, 31680, 1023, 15, 2, wacom_intuos_irq },
{ "Wacom Volito", 8, 5104, 3712, 511, 32, 1, wacom_graphire_irq },
{ "Wacom Cintiq Partner",8, 20480, 15360, 511, 32, 3, wacom_ptu_irq },
+ { "Wacom Intuos3 4x5", 10, 25400, 20320, 1023, 15, 4, wacom_intuos3_irq },
+ { "Wacom Intuos3 6x8", 10, 40640, 30480, 1023, 15, 4, wacom_intuos3_irq },
+ { "Wacom Intuos3 9x12", 10, 60960, 45720, 1023, 15, 4, wacom_intuos3_irq },
{ "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 15, 2, wacom_intuos_irq },
{ }
};
@@ -581,6 +758,9 @@ static struct usb_device_id wacom_ids[] = {
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x45) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x60) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x03) },
+ { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB0) },
+ { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB1) },
+ { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB2) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x47) },
{ }
};
@@ -651,6 +831,12 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE) | BIT(BTN_STYLUS2);
break;
+ case 4: /* new functions for Intuos3 */
+ wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_FINGER);
+ wacom->dev.keybit[LONG(BTN_LEFT)] |= BIT(BTN_0) | BIT(BTN_1) | BIT(BTN_2) | BIT(BTN_3) | BIT(BTN_4) | BIT(BTN_5) | BIT(BTN_6) | BIT(BTN_7);
+ wacom->dev.absbit[0] |= BIT(ABS_RX) | BIT(ABS_RY);
+ /* fall through */
+
case 2:
wacom->dev.evbit[0] |= BIT(EV_MSC) | BIT(EV_REL);
wacom->dev.mscbit[0] |= BIT(MSC_SERIAL);
@@ -662,7 +848,7 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
break;
case 3:
- wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_STYLUS2);
+ wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_STYLUS2) | BIT(BTN_TOOL_RUBBER);
break;
}
@@ -674,6 +860,8 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
wacom->dev.absmax[ABS_TILT_Y] = 127;
wacom->dev.absmax[ABS_WHEEL] = 1023;
+ wacom->dev.absmax[ABS_RX] = 4097;
+ wacom->dev.absmax[ABS_RY] = 4097;
wacom->dev.absmin[ABS_RZ] = -900;
wacom->dev.absmax[ABS_RZ] = 899;
wacom->dev.absmin[ABS_THROTTLE] = -1023;
@@ -712,9 +900,10 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
input_register_device(&wacom->dev);
+ /* ask the tablet to report tablet data */
+ usb_set_report(intf, 3, 2, rep_data, 2);
+ /* repeat once (not sure why the first call often fails) */
usb_set_report(intf, 3, 2, rep_data, 2);
- usb_set_report(intf, 3, 5, rep_data, 0);
- usb_set_report(intf, 3, 6, rep_data, 0);
printk(KERN_INFO "input: %s on %s\n", wacom->features->name, path);
diff --git a/drivers/usb/media/Kconfig b/drivers/usb/media/Kconfig
index 678e5fcbe29a7..21232ee2974cb 100644
--- a/drivers/usb/media/Kconfig
+++ b/drivers/usb/media/Kconfig
@@ -175,3 +175,39 @@ config USB_W9968CF
To compile this driver as a module, choose M here: the
module will be called w9968cf.
+
+config USB_PWC
+ tristate "USB Philips Cameras"
+ depends on USB && VIDEO_DEV
+ ---help---
+ Say Y or M here if you want to use one of these Philips & OEM
+ webcams:
+ * Philips PCA645, PCA646
+ * Philips PCVC675, PCVC680, PCVC690
+ * Philips PCVC720/40, PCVC730, PCVC740, PCVC750
+ * Askey VC010
+ * Logitech QuickCam Pro 3000, 4000, 'Zoom', 'Notebook Pro'
+ and 'Orbit'/'Sphere'
+ * Samsung MPC-C10, MPC-C30
+ * Creative Webcam 5, Pro Ex
+ * SOTEC Afina Eye
+ * Visionite VCS-UC300, VCS-UM100
+
+ The PCA635, PCVC665 and PCVC720/20 are not supported by this driver
+ and never will be, but the 665 and 720/20 are supported by other
+ drivers.
+
+ See <file:Documentation/usb/philips.txt> for more information and
+ installation instructions.
+
+ The built-in microphone is enabled by selecting USB Audio support.
+
+ This driver uses the Video For Linux API. You must say Y or M to
+ "Video For Linux" (under Character Devices) to use this driver.
+ Information on this API and pointers to "v4l" programs may be found
+ at <file:Documentation/video4linux/API.html>.
+
+ To compile this driver as a module, choose M here: the
+ module will be called pwc.
+
+
diff --git a/drivers/usb/media/Makefile b/drivers/usb/media/Makefile
index 425d67f1b17a2..2b76df7005fec 100644
--- a/drivers/usb/media/Makefile
+++ b/drivers/usb/media/Makefile
@@ -14,3 +14,4 @@ obj-$(CONFIG_USB_SN9C102) += sn9c102.o
obj-$(CONFIG_USB_STV680) += stv680.o
obj-$(CONFIG_USB_VICAM) += vicam.o usbvideo.o
obj-$(CONFIG_USB_W9968CF) += w9968cf.o
+obj-$(CONFIG_USB_PWC) += pwc/
diff --git a/drivers/usb/media/ibmcam.c b/drivers/usb/media/ibmcam.c
index 64eb7ca72836c..ba41fc7b95c21 100644
--- a/drivers/usb/media/ibmcam.c
+++ b/drivers/usb/media/ibmcam.c
@@ -1036,7 +1036,8 @@ static enum ParseState ibmcam_model4_128x96_parse_lines(
* History:
* 1/21/00 Created.
*/
-void ibmcam_ProcessIsocData(struct uvd *uvd, struct usbvideo_frame *frame)
+static void ibmcam_ProcessIsocData(struct uvd *uvd,
+ struct usbvideo_frame *frame)
{
enum ParseState newstate;
long copylen = 0;
@@ -1137,7 +1138,7 @@ static int ibmcam_veio(
index,
cp,
sizeof(cp),
- HZ);
+ 1000);
#if 0
info("USB => %02x%02x%02x%02x%02x%02x%02x%02x "
"(req=$%02x val=$%04x ind=$%04x)",
@@ -1154,7 +1155,7 @@ static int ibmcam_veio(
index,
NULL,
0,
- HZ);
+ 1000);
}
if (i < 0) {
err("%s: ERROR=%d. Camera stopped; Reconnect or reload driver.",
diff --git a/drivers/usb/media/konicawc.c b/drivers/usb/media/konicawc.c
index 7ff1468f59770..08521a2b4f3dc 100644
--- a/drivers/usb/media/konicawc.c
+++ b/drivers/usb/media/konicawc.c
@@ -133,7 +133,7 @@ static int konicawc_ctrl_msg(struct uvd *uvd, u8 dir, u8 request, u16 value, u16
{
int retval = usb_control_msg(uvd->dev,
dir ? usb_rcvctrlpipe(uvd->dev, 0) : usb_sndctrlpipe(uvd->dev, 0),
- request, 0x40 | dir, value, index, buf, len, HZ);
+ request, 0x40 | dir, value, index, buf, len, 1000);
return retval < 0 ? retval : 0;
}
diff --git a/drivers/usb/media/ov511.c b/drivers/usb/media/ov511.c
index 88c3628dc2f51..0fd7ffed3a980 100644
--- a/drivers/usb/media/ov511.c
+++ b/drivers/usb/media/ov511.c
@@ -383,7 +383,7 @@ reg_w(struct usb_ov511 *ov, unsigned char reg, unsigned char value)
usb_sndctrlpipe(ov->dev, 0),
(ov->bclass == BCL_OV518)?1:2 /* REG_IO */,
USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- 0, (__u16)reg, &ov->cbuf[0], 1, HZ);
+ 0, (__u16)reg, &ov->cbuf[0], 1, 1000);
up(&ov->cbuf_lock);
if (rc < 0)
@@ -404,7 +404,7 @@ reg_r(struct usb_ov511 *ov, unsigned char reg)
usb_rcvctrlpipe(ov->dev, 0),
(ov->bclass == BCL_OV518)?1:3 /* REG_IO */,
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- 0, (__u16)reg, &ov->cbuf[0], 1, HZ);
+ 0, (__u16)reg, &ov->cbuf[0], 1, 1000);
if (rc < 0) {
err("reg read: error %d: %s", rc, symbolic(urb_errlist, rc));
@@ -464,7 +464,7 @@ ov518_reg_w32(struct usb_ov511 *ov, unsigned char reg, u32 val, int n)
usb_sndctrlpipe(ov->dev, 0),
1 /* REG_IO */,
USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- 0, (__u16)reg, ov->cbuf, n, HZ);
+ 0, (__u16)reg, ov->cbuf, n, 1000);
up(&ov->cbuf_lock);
if (rc < 0)
diff --git a/drivers/usb/media/pwc/ChangeLog b/drivers/usb/media/pwc/ChangeLog
new file mode 100644
index 0000000000000..b2eb71a9afb5a
--- /dev/null
+++ b/drivers/usb/media/pwc/ChangeLog
@@ -0,0 +1,143 @@
+9.0.2
+
+* Adding #ifdef to compile PWC before and after 2.6.5
+
+9.0.1
+
+9.0
+
+
+8.12
+
+* Implement motorized pan/tilt feature for Logitech QuickCam Orbit/Spere.
+
+8.11.1
+
+* Fix for PCVC720/40, would not be able to set videomode
+* Fix for Samsung MPC models, appearantly they are based on a newer chipset
+
+8.11
+
+* 20 dev_hints (per request)
+* Hot unplugging should be better, no more dangling pointers or memory leaks
+* Added reserved Logitech webcam IDs
+* Device now remembers size & fps between close()/open()
+* Removed palette stuff altogether
+
+8.10.1
+
+* Added IDs for PCVC720K/40 and Creative Labs Webcam Pro
+
+8.10
+
+* Fixed ID for QuickCam Notebook pro
+* Added GREALSIZE ioctl() call
+* Fixed bug in case PWCX was not loaded and invalid size was set
+
+8.9
+
+* Merging with kernel 2.5.49
+* Adding IDs for QuickCam Zoom & QuickCam Notebook
+
+8.8
+
+* Fixing 'leds' parameter
+* Adding IDs for Logitech QuickCam Pro 4000
+* Making URB init/cleanup a little nicer
+
+8.7
+
+* Incorporating changes in ioctl() parameter passing
+* Also changes to URB mechanism
+
+8.6
+
+* Added ID's for Visionite VCS UM100 and UC300
+* Removed YUV420-interlaced palette altogether (was confusing)
+* Removed MIRROR stuff as it didn't work anyway
+* Fixed a problem with the 'leds' parameter (wouldn't blink)
+* Added ioctl()s for advanced features: 'extended' whitebalance ioctl()s,
+ CONTOUR, BACKLIGHT, FLICKER, DYNNOISE.
+* VIDIOCGCAP.name now contains real camera model name instead of
+ 'Philips xxx webcam'
+* Added PROBE ioctl (see previous point & API doc)
+
+8.5
+
+* Adding IDs for Creative Labs Webcam 5
+* Adding IDs for SOTEC CMS-001 webcam
+* Solving possible hang in VIDIOCSYNC when unplugging the cam
+* Forgot to return structure in VIDIOCPWCGAWB, oops
+* Time interval for the LEDs are now in milliseconds
+
+8.4
+
+* Fixing power_save option for Vesta range
+* Handling new error codes in ISOC callback
+* Adding dev_hint module parameter, to specify /dev/videoX device nodes
+
+8.3
+
+* Adding Samsung C10 and C30 cameras
+* Removing palette module parameter
+* Fixed typo in ID of QuickCam 3000 Pro
+* Adding LED settings (blinking while in use) for ToUCam cameras.
+* Turns LED off when camera is not in use.
+
+8.2
+
+* Making module more silent when trace = 0
+* Adding QuickCam 3000 Pro IDs
+* Chrominance control for the Vesta cameras
+* Hopefully fixed problems on machines with BIGMEM and > 1GB of RAM
+* Included Oliver Neukem's lock_kernel() patch
+* Allocates less memory for image buffers
+* Adds ioctl()s for the whitebalancing
+
+8.1
+
+* Adding support for 750
+* Adding V4L GAUDIO/SAUDIO/UNIT ioctl() calls
+
+8.0
+* 'damage control' after inclusion in 2.4.5.
+* Changed wait-queue mechanism in read/mmap/poll according to the book.
+* Included YUV420P palette.
+* Changed interface to decompressor module.
+* Cleaned up pwc structure a bit.
+
+7.0
+
+* Fixed bug in vcvt_420i_yuyv; extra variables on stack were misaligned.
+* There is now a clear error message when an image size is selected that
+ is only supported using the decompressor, and the decompressor isn't
+ loaded.
+* When the decompressor wasn't loaded, selecting large image size
+ would create skewed or double images.
+
+6.3
+
+* Introduced spinlocks for the buffer pointer manipulation; a number of
+ reports seem to suggest the down()/up() semaphores were the cause of
+ lockups, since they are not suitable for interrupt/user locking.
+* Separated decompressor and core code into 2 modules.
+
+6.2
+
+* Non-integral image sizes are now padded with gray or black.
+* Added SHUTTERSPEED ioctl().
+* Fixed buglet in VIDIOCPWCSAGC; the function would always return an error,
+ even though the call succeeded.
+* Added hotplug support for 2.4.*.
+* Memory: the 645/646 uses less memory now.
+
+6.1
+
+* VIDIOCSPICT returns -EINVAL with invalid palettes.
+* Added saturation control.
+* Split decompressors from rest.
+* Fixed bug that would reset the framerate to the default framerate if
+ the rate field was set to 0 (which is not what I intended, nl. do not
+ change the framerate!).
+* VIDIOCPWCSCQUAL (setting compression quality) now takes effect immediately.
+* Workaround for a bug in the 730 sensor.
diff --git a/drivers/usb/media/pwc/Makefile b/drivers/usb/media/pwc/Makefile
new file mode 100644
index 0000000000000..e0b41ed4407f5
--- /dev/null
+++ b/drivers/usb/media/pwc/Makefile
@@ -0,0 +1,20 @@
+ifneq ($(KERNELRELEASE),)
+
+pwc-objs := pwc-if.o pwc-misc.o pwc-ctrl.o pwc-uncompress.o pwc-dec1.o pwc-dec23.o pwc-kiara.o pwc-timon.o
+
+obj-$(CONFIG_USB_PWC) += pwc.o
+
+else
+
+KDIR := /lib/modules/$(shell uname -r)/build
+PWD := $(shell pwd)
+
+default:
+ $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
+
+endif
+
+clean:
+ rm -f *.[oas] .*.flags *.ko .*.cmd .*.d .*.tmp *.mod.c
+ rm -rf .tmp_versions
+
diff --git a/drivers/usb/media/pwc/philips.txt b/drivers/usb/media/pwc/philips.txt
new file mode 100644
index 0000000000000..04a640d723ed4
--- /dev/null
+++ b/drivers/usb/media/pwc/philips.txt
@@ -0,0 +1,236 @@
+This file contains some additional information for the Philips and OEM webcams.
+E-mail: webcam@smcc.demon.nl Last updated: 2004-01-19
+Site: http://www.smcc.demon.nl/webcam/
+
+As of this moment, the following cameras are supported:
+ * Philips PCA645
+ * Philips PCA646
+ * Philips PCVC675
+ * Philips PCVC680
+ * Philips PCVC690
+ * Philips PCVC720/40
+ * Philips PCVC730
+ * Philips PCVC740
+ * Philips PCVC750
+ * Askey VC010
+ * Creative Labs Webcam 5
+ * Creative Labs Webcam Pro Ex
+ * Logitech QuickCam 3000 Pro
+ * Logitech QuickCam 4000 Pro
+ * Logitech QuickCam Notebook Pro
+ * Logitech QuickCam Zoom
+ * Logitech QuickCam Orbit
+ * Logitech QuickCam Sphere
+ * Samsung MPC-C10
+ * Samsung MPC-C30
+ * Sotec Afina Eye
+ * AME CU-001
+ * Visionite VCS-UM100
+ * Visionite VCS-UC300
+
+The main webpage for the Philips driver is at the address above. It contains
+a lot of extra information, a FAQ, and the binary plugin 'PWCX'. This plugin
+contains decompression routines that allow you to use higher image sizes and
+framerates; in addition the webcam uses less bandwidth on the USB bus (handy
+if you want to run more than 1 camera simultaneously). These routines fall
+under a NDA, and may therefor not be distributed as source; however, its use
+is completely optional.
+
+You can build this code either into your kernel, or as a module. I recommend
+the latter, since it makes troubleshooting a lot easier. The built-in
+microphone is supported through the USB Audio class.
+
+When you load the module you can set some default settings for the
+camera; some programs depend on a particular image-size or -format and
+don't know how to set it properly in the driver. The options are:
+
+size
+ Can be one of 'sqcif', 'qsif', 'qcif', 'sif', 'cif' or
+ 'vga', for an image size of resp. 128x96, 160x120, 176x144,
+ 320x240, 352x288 and 640x480 (of course, only for those cameras that
+ support these resolutions).
+
+fps
+ Specifies the desired framerate. Is an integer in the range of 4-30.
+
+fbufs
+ This paramter specifies the number of internal buffers to use for storing
+ frames from the cam. This will help if the process that reads images from
+ the cam is a bit slow or momentarely busy. However, on slow machines it
+ only introduces lag, so choose carefully. The default is 3, which is
+ reasonable. You can set it between 2 and 5.
+
+mbufs
+ This is an integer between 1 and 10. It will tell the module the number of
+ buffers to reserve for mmap(), VIDIOCCGMBUF, VIDIOCMCAPTURE and friends.
+ The default is 2, which is adequate for most applications (double
+ buffering).
+
+ Should you experience a lot of 'Dumping frame...' messages during
+ grabbing with a tool that uses mmap(), you might want to increase if.
+ However, it doesn't really buffer images, it just gives you a bit more
+ slack when your program is behind. But you need a multi-threaded or
+ forked program to really take advantage of these buffers.
+
+ The absolute maximum is 10, but don't set it too high! Every buffer takes
+ up 460 KB of RAM, so unless you have a lot of memory setting this to
+ something more than 4 is an absolute waste. This memory is only
+ allocated during open(), so nothing is wasted when the camera is not in
+ use.
+
+power_save
+ When power_save is enabled (set to 1), the module will try to shut down
+ the cam on close() and re-activate on open(). This will save power and
+ turn off the LED. Not all cameras support this though (the 645 and 646
+ don't have power saving at all), and some models don't work either (they
+ will shut down, but never wake up). Consider this experimental. By
+ default this option is disabled.
+
+compression (only useful with the plugin)
+ With this option you can control the compression factor that the camera
+ uses to squeeze the image through the USB bus. You can set the
+ parameter between 0 and 3:
+ 0 = prefer uncompressed images; if the requested mode is not available
+ in an uncompressed format, the driver will silently switch to low
+ compression.
+ 1 = low compression.
+ 2 = medium compression.
+ 3 = high compression.
+
+ High compression takes less bandwidth of course, but it could also
+ introduce some unwanted artefacts. The default is 2, medium compression.
+ See the FAQ on the website for an overview of which modes require
+ compression.
+
+ The compression parameter does not apply to the 645 and 646 cameras
+ and OEM models derived from those (only a few). Most cams honour this
+ parameter.
+
+leds
+ This settings takes 2 integers, that define the on/off time for the LED
+ (in milliseconds). One of the interesting things that you can do with
+ this is let the LED blink while the camera is in use. This:
+
+ leds=500,500
+
+ will blink the LED once every second. But with:
+
+ leds=0,0
+
+ the LED never goes on, making it suitable for silent surveillance.
+
+ By default the camera's LED is on solid while in use, and turned off
+ when the camera is not used anymore.
+
+ This parameter works only with the ToUCam range of cameras (720, 730, 740,
+ 750) and OEMs. For other cameras this command is silently ignored, and
+ the LED cannot be controlled.
+
+ Finally: this parameters does not take effect UNTIL the first time you
+ open the camera device. Until then, the LED remains on.
+
+dev_hint
+ A long standing problem with USB devices is their dynamic nature: you
+ never know what device a camera gets assigned; it depends on module load
+ order, the hub configuration, the order in which devices are plugged in,
+ and the phase of the moon (i.e. it can be random). With this option you
+ can give the driver a hint as to what video device node (/dev/videoX) it
+ should use with a specific camera. This is also handy if you have two
+ cameras of the same model.
+
+ A camera is specified by its type (the number from the camera model,
+ like PCA645, PCVC750VC, etc) and optionally the serial number (visible
+ in /proc/bus/usb/devices). A hint consists of a string with the following
+ format:
+
+ [type[.serialnumber]:]node
+
+ The square brackets mean that both the type and the serialnumber are
+ optional, but a serialnumber cannot be specified without a type (which
+ would be rather pointless). The serialnumber is separated from the type
+ by a '.'; the node number by a ':'.
+
+ This somewhat cryptic syntax is best explained by a few examples:
+
+ dev_hint=3,5 The first detected cam gets assigned
+ /dev/video3, the second /dev/video5. Any
+ other cameras will get the first free
+ available slot (see below).
+
+ dev_hint=645:1,680:2 The PCA645 camera will get /dev/video1,
+ and a PCVC680 /dev/video2.
+
+ dev_hint=645.0123:3,645.4567:0 The PCA645 camera with serialnumber
+ 0123 goes to /dev/video3, the same
+ camera model with the 4567 serial
+ gets /dev/video0.
+
+ dev_hint=750:1,4,5,6 The PCVC750 camera will get /dev/video1, the
+ next 3 Philips cams will use /dev/video4
+ through /dev/video6.
+
+ Some points worth knowing:
+ - Serialnumbers are case sensitive and must be written full, including
+ leading zeroes (it's treated as a string).
+ - If a device node is already occupied, registration will fail and
+ the webcam is not available.
+ - You can have up to 64 video devices; be sure to make enough device
+ nodes in /dev if you want to spread the numbers (this does not apply
+ to devfs). After /dev/video9 comes /dev/video10 (not /dev/videoA).
+ - If a camera does not match any dev_hint, it will simply get assigned
+ the first available device node, just as it used to be.
+
+trace
+ In order to better detect problems, it is now possible to turn on a
+ 'trace' of some of the calls the module makes; it logs all items in your
+ kernel log at debug level.
+
+ The trace variable is a bitmask; each bit represents a certain feature.
+ If you want to trace something, look up the bit value(s) in the table
+ below, add the values together and supply that to the trace variable.
+
+ Value Value Description Default
+ (dec) (hex)
+ 1 0x1 Module initialization; this will log messages On
+ while loading and unloading the module
+
+ 2 0x2 probe() and disconnect() traces On
+
+ 4 0x4 Trace open() and close() calls Off
+
+ 8 0x8 read(), mmap() and associated ioctl() calls Off
+
+ 16 0x10 Memory allocation of buffers, etc. Off
+
+ 32 0x20 Showing underflow, overflow and Dumping frame On
+ messages
+
+ 64 0x40 Show viewport and image sizes Off
+
+ 128 0x80 PWCX debugging Off
+
+ For example, to trace the open() & read() fuctions, sum 8 + 4 = 12,
+ so you would supply trace=12 during insmod or modprobe. If
+ you want to turn the initialization and probing tracing off, set trace=0.
+ The default value for trace is 35 (0x23).
+
+
+
+Example:
+
+ # modprobe pwc size=cif fps=15 power_save=1
+
+The fbufs, mbufs and trace parameters are global and apply to all connected
+cameras. Each camera has its own set of buffers.
+
+size and fps only specify defaults when you open() the device; this is to
+accommodate some tools that don't set the size. You can change these
+settings after open() with the Video4Linux ioctl() calls. The default of
+defaults is QCIF size at 10 fps.
+
+The compression parameter is semiglobal; it sets the initial compression
+preference for all camera's, but this parameter can be set per camera with
+the VIDIOCPWCSCQUAL ioctl() call.
+
+All parameters are optional.
+
diff --git a/drivers/usb/media/pwc/pwc-ctrl.c b/drivers/usb/media/pwc/pwc-ctrl.c
new file mode 100644
index 0000000000000..26aa914bc541a
--- /dev/null
+++ b/drivers/usb/media/pwc/pwc-ctrl.c
@@ -0,0 +1,1630 @@
+/* Driver for Philips webcam
+ Functions that send various control messages to the webcam, including
+ video modes.
+ (C) 1999-2003 Nemosoft Unv.
+ (C) 2004 Luc Saillard (luc@saillard.org)
+
+ NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+ driver and thus may have bugs that are not present in the original version.
+ Please send bug reports and support requests to <luc@saillard.org>.
+
+ NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+ driver and thus may have bugs that are not present in the original version.
+ Please send bug reports and support requests to <luc@saillard.org>.
+ The decompression routines have been implemented by reverse-engineering the
+ Nemosoft binary pwcx module. Caveat emptor.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the 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
+*/
+
+/*
+ Changes
+ 2001/08/03 Alvarado Added methods for changing white balance and
+ red/green gains
+ */
+
+/* Control functions for the cam; brightness, contrast, video mode, etc. */
+
+#ifdef __KERNEL__
+#include <asm/uaccess.h>
+#endif
+#include <asm/errno.h>
+#include <linux/version.h>
+
+#include "pwc.h"
+#include "pwc-ioctl.h"
+#include "pwc-uncompress.h"
+#include "pwc-kiara.h"
+#include "pwc-timon.h"
+#include "pwc-dec1.h"
+#include "pwc-dec23.h"
+
+/* Request types: video */
+#define SET_LUM_CTL 0x01
+#define GET_LUM_CTL 0x02
+#define SET_CHROM_CTL 0x03
+#define GET_CHROM_CTL 0x04
+#define SET_STATUS_CTL 0x05
+#define GET_STATUS_CTL 0x06
+#define SET_EP_STREAM_CTL 0x07
+#define GET_EP_STREAM_CTL 0x08
+#define SET_MPT_CTL 0x0D
+#define GET_MPT_CTL 0x0E
+
+/* Selectors for the Luminance controls [GS]ET_LUM_CTL */
+#define AGC_MODE_FORMATTER 0x2000
+#define PRESET_AGC_FORMATTER 0x2100
+#define SHUTTER_MODE_FORMATTER 0x2200
+#define PRESET_SHUTTER_FORMATTER 0x2300
+#define PRESET_CONTOUR_FORMATTER 0x2400
+#define AUTO_CONTOUR_FORMATTER 0x2500
+#define BACK_LIGHT_COMPENSATION_FORMATTER 0x2600
+#define CONTRAST_FORMATTER 0x2700
+#define DYNAMIC_NOISE_CONTROL_FORMATTER 0x2800
+#define FLICKERLESS_MODE_FORMATTER 0x2900
+#define AE_CONTROL_SPEED 0x2A00
+#define BRIGHTNESS_FORMATTER 0x2B00
+#define GAMMA_FORMATTER 0x2C00
+
+/* Selectors for the Chrominance controls [GS]ET_CHROM_CTL */
+#define WB_MODE_FORMATTER 0x1000
+#define AWB_CONTROL_SPEED_FORMATTER 0x1100
+#define AWB_CONTROL_DELAY_FORMATTER 0x1200
+#define PRESET_MANUAL_RED_GAIN_FORMATTER 0x1300
+#define PRESET_MANUAL_BLUE_GAIN_FORMATTER 0x1400
+#define COLOUR_MODE_FORMATTER 0x1500
+#define SATURATION_MODE_FORMATTER1 0x1600
+#define SATURATION_MODE_FORMATTER2 0x1700
+
+/* Selectors for the Status controls [GS]ET_STATUS_CTL */
+#define SAVE_USER_DEFAULTS_FORMATTER 0x0200
+#define RESTORE_USER_DEFAULTS_FORMATTER 0x0300
+#define RESTORE_FACTORY_DEFAULTS_FORMATTER 0x0400
+#define READ_AGC_FORMATTER 0x0500
+#define READ_SHUTTER_FORMATTER 0x0600
+#define READ_RED_GAIN_FORMATTER 0x0700
+#define READ_BLUE_GAIN_FORMATTER 0x0800
+#define SENSOR_TYPE_FORMATTER1 0x0C00
+#define READ_RAW_Y_MEAN_FORMATTER 0x3100
+#define SET_POWER_SAVE_MODE_FORMATTER 0x3200
+#define MIRROR_IMAGE_FORMATTER 0x3300
+#define LED_FORMATTER 0x3400
+#define SENSOR_TYPE_FORMATTER2 0x3700
+
+/* Formatters for the Video Endpoint controls [GS]ET_EP_STREAM_CTL */
+#define VIDEO_OUTPUT_CONTROL_FORMATTER 0x0100
+
+/* Formatters for the motorized pan & tilt [GS]ET_MPT_CTL */
+#define PT_RELATIVE_CONTROL_FORMATTER 0x01
+#define PT_RESET_CONTROL_FORMATTER 0x02
+#define PT_STATUS_FORMATTER 0x03
+
+static char *size2name[PSZ_MAX] =
+{
+ "subQCIF",
+ "QSIF",
+ "QCIF",
+ "SIF",
+ "CIF",
+ "VGA",
+};
+
+/********/
+
+/* Entries for the Nala (645/646) camera; the Nala doesn't have compression
+ preferences, so you either get compressed or non-compressed streams.
+
+ An alternate value of 0 means this mode is not available at all.
+ */
+
+struct Nala_table_entry {
+ char alternate; /* USB alternate setting */
+ int compressed; /* Compressed yes/no */
+
+ unsigned char mode[3]; /* precomputed mode table */
+};
+
+static struct Nala_table_entry Nala_table[PSZ_MAX][8] =
+{
+#include "pwc-nala.h"
+};
+
+
+/****************************************************************************/
+
+
+#define SendControlMsg(request, value, buflen) \
+ usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0), \
+ request, \
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, \
+ value, \
+ pdev->vcinterface, \
+ &buf, buflen, 500)
+
+#define RecvControlMsg(request, value, buflen) \
+ usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0), \
+ request, \
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, \
+ value, \
+ pdev->vcinterface, \
+ &buf, buflen, 500)
+
+
+#if PWC_DEBUG
+void pwc_hexdump(void *p, int len)
+{
+ int i;
+ unsigned char *s;
+ char buf[100], *d;
+
+ s = (unsigned char *)p;
+ d = buf;
+ *d = '\0';
+ Debug("Doing hexdump @ %p, %d bytes.\n", p, len);
+ for (i = 0; i < len; i++) {
+ d += sprintf(d, "%02X ", *s++);
+ if ((i & 0xF) == 0xF) {
+ Debug("%s\n", buf);
+ d = buf;
+ *d = '\0';
+ }
+ }
+ if ((i & 0xF) != 0)
+ Debug("%s\n", buf);
+}
+#endif
+
+static inline int send_video_command(struct usb_device *udev, int index, void *buf, int buflen)
+{
+ return usb_control_msg(udev,
+ usb_sndctrlpipe(udev, 0),
+ SET_EP_STREAM_CTL,
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ VIDEO_OUTPUT_CONTROL_FORMATTER,
+ index,
+ buf, buflen, 1000);
+}
+
+
+
+static inline int set_video_mode_Nala(struct pwc_device *pdev, int size, int frames)
+{
+ unsigned char buf[3];
+ int ret, fps;
+ struct Nala_table_entry *pEntry;
+ int frames2frames[31] =
+ { /* closest match of framerate */
+ 0, 0, 0, 0, 4, /* 0-4 */
+ 5, 5, 7, 7, 10, /* 5-9 */
+ 10, 10, 12, 12, 15, /* 10-14 */
+ 15, 15, 15, 20, 20, /* 15-19 */
+ 20, 20, 20, 24, 24, /* 20-24 */
+ 24, 24, 24, 24, 24, /* 25-29 */
+ 24 /* 30 */
+ };
+ int frames2table[31] =
+ { 0, 0, 0, 0, 0, /* 0-4 */
+ 1, 1, 1, 2, 2, /* 5-9 */
+ 3, 3, 4, 4, 4, /* 10-14 */
+ 5, 5, 5, 5, 5, /* 15-19 */
+ 6, 6, 6, 6, 7, /* 20-24 */
+ 7, 7, 7, 7, 7, /* 25-29 */
+ 7 /* 30 */
+ };
+
+ if (size < 0 || size > PSZ_CIF || frames < 4 || frames > 25)
+ return -EINVAL;
+ frames = frames2frames[frames];
+ fps = frames2table[frames];
+ pEntry = &Nala_table[size][fps];
+ if (pEntry->alternate == 0)
+ return -EINVAL;
+
+ if (pEntry->compressed)
+ return -ENOENT; /* Not supported. */
+
+ memcpy(buf, pEntry->mode, 3);
+ ret = send_video_command(pdev->udev, pdev->vendpoint, buf, 3);
+ if (ret < 0) {
+ Debug("Failed to send video command... %d\n", ret);
+ return ret;
+ }
+ if (pEntry->compressed && pdev->vpalette != VIDEO_PALETTE_RAW)
+ {
+ switch(pdev->type) {
+ case 645:
+ case 646:
+ pwc_dec1_init(pdev->type, pdev->release, buf, pdev->decompress_data);
+ break;
+
+ case 675:
+ case 680:
+ case 690:
+ case 720:
+ case 730:
+ case 740:
+ case 750:
+ pwc_dec23_init(pdev->type, pdev->release, buf, pdev->decompress_data);
+ break;
+ }
+ }
+
+ pdev->cmd_len = 3;
+ memcpy(pdev->cmd_buf, buf, 3);
+
+ /* Set various parameters */
+ pdev->vframes = frames;
+ pdev->vsize = size;
+ pdev->valternate = pEntry->alternate;
+ pdev->image = pwc_image_sizes[size];
+ pdev->frame_size = (pdev->image.x * pdev->image.y * 3) / 2;
+ if (pEntry->compressed) {
+ if (pdev->release < 5) { /* 4 fold compression */
+ pdev->vbandlength = 528;
+ pdev->frame_size /= 4;
+ }
+ else {
+ pdev->vbandlength = 704;
+ pdev->frame_size /= 3;
+ }
+ }
+ else
+ pdev->vbandlength = 0;
+ return 0;
+}
+
+
+static inline int set_video_mode_Timon(struct pwc_device *pdev, int size, int frames, int compression, int snapshot)
+{
+ unsigned char buf[13];
+ const struct Timon_table_entry *pChoose;
+ int ret, fps;
+
+ if (size >= PSZ_MAX || frames < 5 || frames > 30 || compression < 0 || compression > 3)
+ return -EINVAL;
+ if (size == PSZ_VGA && frames > 15)
+ return -EINVAL;
+ fps = (frames / 5) - 1;
+
+ /* Find a supported framerate with progressively higher compression ratios
+ if the preferred ratio is not available.
+ */
+ pChoose = NULL;
+ while (compression <= 3) {
+ pChoose = &Timon_table[size][fps][compression];
+ if (pChoose->alternate != 0)
+ break;
+ compression++;
+ }
+ if (pChoose == NULL || pChoose->alternate == 0)
+ return -ENOENT; /* Not supported. */
+
+ memcpy(buf, pChoose->mode, 13);
+ if (snapshot)
+ buf[0] |= 0x80;
+ ret = send_video_command(pdev->udev, pdev->vendpoint, buf, 13);
+ if (ret < 0)
+ return ret;
+
+ if (pChoose->bandlength > 0 && pdev->vpalette != VIDEO_PALETTE_RAW)
+ pwc_dec23_init(pdev->type, pdev->release, buf, pdev->decompress_data);
+
+ pdev->cmd_len = 13;
+ memcpy(pdev->cmd_buf, buf, 13);
+
+ /* Set various parameters */
+ pdev->vframes = frames;
+ pdev->vsize = size;
+ pdev->vsnapshot = snapshot;
+ pdev->valternate = pChoose->alternate;
+ pdev->image = pwc_image_sizes[size];
+ pdev->vbandlength = pChoose->bandlength;
+ if (pChoose->bandlength > 0)
+ pdev->frame_size = (pChoose->bandlength * pdev->image.y) / 4;
+ else
+ pdev->frame_size = (pdev->image.x * pdev->image.y * 12) / 8;
+ return 0;
+}
+
+
+static inline int set_video_mode_Kiara(struct pwc_device *pdev, int size, int frames, int compression, int snapshot)
+{
+ const struct Kiara_table_entry *pChoose = NULL;
+ int fps, ret;
+ unsigned char buf[12];
+ struct Kiara_table_entry RawEntry = {6, 773, 1272, {0xAD, 0xF4, 0x10, 0x27, 0xB6, 0x24, 0x96, 0x02, 0x30, 0x05, 0x03, 0x80}};
+
+ if (size >= PSZ_MAX || frames < 5 || frames > 30 || compression < 0 || compression > 3)
+ return -EINVAL;
+ if (size == PSZ_VGA && frames > 15)
+ return -EINVAL;
+ fps = (frames / 5) - 1;
+
+ /* special case: VGA @ 5 fps and snapshot is raw bayer mode */
+ if (size == PSZ_VGA && frames == 5 && snapshot)
+ {
+ /* Only available in case the raw palette is selected or
+ we have the decompressor available. This mode is
+ only available in compressed form
+ */
+ if (pdev->vpalette == VIDEO_PALETTE_RAW)
+ {
+ Info("Choosing VGA/5 BAYER mode (%d).\n", pdev->vpalette);
+ pChoose = &RawEntry;
+ }
+ else
+ {
+ Info("VGA/5 BAYER mode _must_ have a decompressor available, or use RAW palette.\n");
+ }
+ }
+ else
+ {
+ /* Find a supported framerate with progressively higher compression ratios
+ if the preferred ratio is not available.
+ Skip this step when using RAW modes.
+ */
+ while (compression <= 3) {
+ pChoose = &Kiara_table[size][fps][compression];
+ if (pChoose->alternate != 0)
+ break;
+ compression++;
+ }
+ }
+ if (pChoose == NULL || pChoose->alternate == 0)
+ return -ENOENT; /* Not supported. */
+
+ Debug("Using alternate setting %d.\n", pChoose->alternate);
+
+ /* usb_control_msg won't take staticly allocated arrays as argument?? */
+ memcpy(buf, pChoose->mode, 12);
+ if (snapshot)
+ buf[0] |= 0x80;
+
+ /* Firmware bug: video endpoint is 5, but commands are sent to endpoint 4 */
+ ret = send_video_command(pdev->udev, 4 /* pdev->vendpoint */, buf, 12);
+ if (ret < 0)
+ return ret;
+
+ if (pChoose->bandlength > 0 && pdev->vpalette != VIDEO_PALETTE_RAW)
+ pwc_dec23_init(pdev->type, pdev->release, buf, pdev->decompress_data);
+
+ pdev->cmd_len = 12;
+ memcpy(pdev->cmd_buf, buf, 12);
+ /* All set and go */
+ pdev->vframes = frames;
+ pdev->vsize = size;
+ pdev->vsnapshot = snapshot;
+ pdev->valternate = pChoose->alternate;
+ pdev->image = pwc_image_sizes[size];
+ pdev->vbandlength = pChoose->bandlength;
+ if (pdev->vbandlength > 0)
+ pdev->frame_size = (pdev->vbandlength * pdev->image.y) / 4;
+ else
+ pdev->frame_size = (pdev->image.x * pdev->image.y * 12) / 8;
+ return 0;
+}
+
+
+
+/**
+ @pdev: device structure
+ @width: viewport width
+ @height: viewport height
+ @frame: framerate, in fps
+ @compression: preferred compression ratio
+ @snapshot: snapshot mode or streaming
+ */
+int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, int frames, int compression, int snapshot)
+{
+ int ret, size;
+
+ Trace(TRACE_FLOW, "set_video_mode(%dx%d @ %d, palette %d).\n", width, height, frames, pdev->vpalette);
+ size = pwc_decode_size(pdev, width, height);
+ if (size < 0) {
+ Debug("Could not find suitable size.\n");
+ return -ERANGE;
+ }
+ Debug("decode_size = %d.\n", size);
+
+ ret = -EINVAL;
+ switch(pdev->type) {
+ case 645:
+ case 646:
+ ret = set_video_mode_Nala(pdev, size, frames);
+ break;
+
+ case 675:
+ case 680:
+ case 690:
+ ret = set_video_mode_Timon(pdev, size, frames, compression, snapshot);
+ break;
+
+ case 720:
+ case 730:
+ case 740:
+ case 750:
+ ret = set_video_mode_Kiara(pdev, size, frames, compression, snapshot);
+ break;
+ }
+ if (ret < 0) {
+ if (ret == -ENOENT)
+ Info("Video mode %s@%d fps is only supported with the decompressor module (pwcx).\n", size2name[size], frames);
+ else {
+ Err("Failed to set video mode %s@%d fps; return code = %d\n", size2name[size], frames, ret);
+ }
+ return ret;
+ }
+ pdev->view.x = width;
+ pdev->view.y = height;
+ pdev->frame_total_size = pdev->frame_size + pdev->frame_header_size + pdev->frame_trailer_size;
+ pwc_set_image_buffer_size(pdev);
+ Trace(TRACE_SIZE, "Set viewport to %dx%d, image size is %dx%d.\n", width, height, pwc_image_sizes[size].x, pwc_image_sizes[size].y);
+ return 0;
+}
+
+
+void pwc_set_image_buffer_size(struct pwc_device *pdev)
+{
+ int i, factor = 0, filler = 0;
+
+ /* for PALETTE_YUV420P */
+ switch(pdev->vpalette)
+ {
+ case VIDEO_PALETTE_YUV420P:
+ factor = 6;
+ filler = 128;
+ break;
+ case VIDEO_PALETTE_RAW:
+ factor = 6; /* can be uncompressed YUV420P */
+ filler = 0;
+ break;
+ }
+
+ /* Set sizes in bytes */
+ pdev->image.size = pdev->image.x * pdev->image.y * factor / 4;
+ pdev->view.size = pdev->view.x * pdev->view.y * factor / 4;
+
+ /* Align offset, or you'll get some very weird results in
+ YUV420 mode... x must be multiple of 4 (to get the Y's in
+ place), and y even (or you'll mixup U & V). This is less of a
+ problem for YUV420P.
+ */
+ pdev->offset.x = ((pdev->view.x - pdev->image.x) / 2) & 0xFFFC;
+ pdev->offset.y = ((pdev->view.y - pdev->image.y) / 2) & 0xFFFE;
+
+ /* Fill buffers with gray or black */
+ for (i = 0; i < MAX_IMAGES; i++) {
+ if (pdev->image_ptr[i] != NULL)
+ memset(pdev->image_ptr[i], filler, pdev->view.size);
+ }
+}
+
+
+
+/* BRIGHTNESS */
+
+int pwc_get_brightness(struct pwc_device *pdev)
+{
+ char buf;
+ int ret;
+
+ ret = RecvControlMsg(GET_LUM_CTL, BRIGHTNESS_FORMATTER, 1);
+ if (ret < 0)
+ return ret;
+ return buf << 9;
+}
+
+int pwc_set_brightness(struct pwc_device *pdev, int value)
+{
+ char buf;
+
+ if (value < 0)
+ value = 0;
+ if (value > 0xffff)
+ value = 0xffff;
+ buf = (value >> 9) & 0x7f;
+ return SendControlMsg(SET_LUM_CTL, BRIGHTNESS_FORMATTER, 1);
+}
+
+/* CONTRAST */
+
+int pwc_get_contrast(struct pwc_device *pdev)
+{
+ char buf;
+ int ret;
+
+ ret = RecvControlMsg(GET_LUM_CTL, CONTRAST_FORMATTER, 1);
+ if (ret < 0)
+ return ret;
+ return buf << 10;
+}
+
+int pwc_set_contrast(struct pwc_device *pdev, int value)
+{
+ char buf;
+
+ if (value < 0)
+ value = 0;
+ if (value > 0xffff)
+ value = 0xffff;
+ buf = (value >> 10) & 0x3f;
+ return SendControlMsg(SET_LUM_CTL, CONTRAST_FORMATTER, 1);
+}
+
+/* GAMMA */
+
+int pwc_get_gamma(struct pwc_device *pdev)
+{
+ char buf;
+ int ret;
+
+ ret = RecvControlMsg(GET_LUM_CTL, GAMMA_FORMATTER, 1);
+ if (ret < 0)
+ return ret;
+ return buf << 11;
+}
+
+int pwc_set_gamma(struct pwc_device *pdev, int value)
+{
+ char buf;
+
+ if (value < 0)
+ value = 0;
+ if (value > 0xffff)
+ value = 0xffff;
+ buf = (value >> 11) & 0x1f;
+ return SendControlMsg(SET_LUM_CTL, GAMMA_FORMATTER, 1);
+}
+
+
+/* SATURATION */
+
+int pwc_get_saturation(struct pwc_device *pdev)
+{
+ char buf;
+ int ret;
+
+ if (pdev->type < 675)
+ return -1;
+ ret = RecvControlMsg(GET_CHROM_CTL, pdev->type < 730 ? SATURATION_MODE_FORMATTER2 : SATURATION_MODE_FORMATTER1, 1);
+ if (ret < 0)
+ return ret;
+ return 32768 + buf * 327;
+}
+
+int pwc_set_saturation(struct pwc_device *pdev, int value)
+{
+ char buf;
+
+ if (pdev->type < 675)
+ return -EINVAL;
+ if (value < 0)
+ value = 0;
+ if (value > 0xffff)
+ value = 0xffff;
+ /* saturation ranges from -100 to +100 */
+ buf = (value - 32768) / 327;
+ return SendControlMsg(SET_CHROM_CTL, pdev->type < 730 ? SATURATION_MODE_FORMATTER2 : SATURATION_MODE_FORMATTER1, 1);
+}
+
+/* AGC */
+
+static inline int pwc_set_agc(struct pwc_device *pdev, int mode, int value)
+{
+ char buf;
+ int ret;
+
+ if (mode)
+ buf = 0x0; /* auto */
+ else
+ buf = 0xff; /* fixed */
+
+ ret = SendControlMsg(SET_LUM_CTL, AGC_MODE_FORMATTER, 1);
+
+ if (!mode && ret >= 0) {
+ if (value < 0)
+ value = 0;
+ if (value > 0xffff)
+ value = 0xffff;
+ buf = (value >> 10) & 0x3F;
+ ret = SendControlMsg(SET_LUM_CTL, PRESET_AGC_FORMATTER, 1);
+ }
+ if (ret < 0)
+ return ret;
+ return 0;
+}
+
+static inline int pwc_get_agc(struct pwc_device *pdev, int *value)
+{
+ unsigned char buf;
+ int ret;
+
+ ret = RecvControlMsg(GET_LUM_CTL, AGC_MODE_FORMATTER, 1);
+ if (ret < 0)
+ return ret;
+
+ if (buf != 0) { /* fixed */
+ ret = RecvControlMsg(GET_LUM_CTL, PRESET_AGC_FORMATTER, 1);
+ if (ret < 0)
+ return ret;
+ if (buf > 0x3F)
+ buf = 0x3F;
+ *value = (buf << 10);
+ }
+ else { /* auto */
+ ret = RecvControlMsg(GET_STATUS_CTL, READ_AGC_FORMATTER, 1);
+ if (ret < 0)
+ return ret;
+ /* Gah... this value ranges from 0x00 ... 0x9F */
+ if (buf > 0x9F)
+ buf = 0x9F;
+ *value = -(48 + buf * 409);
+ }
+
+ return 0;
+}
+
+static inline int pwc_set_shutter_speed(struct pwc_device *pdev, int mode, int value)
+{
+ char buf[2];
+ int speed, ret;
+
+
+ if (mode)
+ buf[0] = 0x0; /* auto */
+ else
+ buf[0] = 0xff; /* fixed */
+
+ ret = SendControlMsg(SET_LUM_CTL, SHUTTER_MODE_FORMATTER, 1);
+
+ if (!mode && ret >= 0) {
+ if (value < 0)
+ value = 0;
+ if (value > 0xffff)
+ value = 0xffff;
+ switch(pdev->type) {
+ case 675:
+ case 680:
+ case 690:
+ /* speed ranges from 0x0 to 0x290 (656) */
+ speed = (value / 100);
+ buf[1] = speed >> 8;
+ buf[0] = speed & 0xff;
+ break;
+ case 720:
+ case 730:
+ case 740:
+ case 750:
+ /* speed seems to range from 0x0 to 0xff */
+ buf[1] = 0;
+ buf[0] = value >> 8;
+ break;
+ }
+
+ ret = SendControlMsg(SET_LUM_CTL, PRESET_SHUTTER_FORMATTER, 2);
+ }
+ return ret;
+}
+
+
+/* POWER */
+
+int pwc_camera_power(struct pwc_device *pdev, int power)
+{
+ char buf;
+
+ if (pdev->type < 675 || (pdev->type < 730 && pdev->release < 6))
+ return 0; /* Not supported by Nala or Timon < release 6 */
+
+ if (power)
+ buf = 0x00; /* active */
+ else
+ buf = 0xFF; /* power save */
+ return SendControlMsg(SET_STATUS_CTL, SET_POWER_SAVE_MODE_FORMATTER, 1);
+}
+
+
+
+/* private calls */
+
+static inline int pwc_restore_user(struct pwc_device *pdev)
+{
+ char buf; /* dummy */
+ return SendControlMsg(SET_STATUS_CTL, RESTORE_USER_DEFAULTS_FORMATTER, 0);
+}
+
+static inline int pwc_save_user(struct pwc_device *pdev)
+{
+ char buf; /* dummy */
+ return SendControlMsg(SET_STATUS_CTL, SAVE_USER_DEFAULTS_FORMATTER, 0);
+}
+
+static inline int pwc_restore_factory(struct pwc_device *pdev)
+{
+ char buf; /* dummy */
+ return SendControlMsg(SET_STATUS_CTL, RESTORE_FACTORY_DEFAULTS_FORMATTER, 0);
+}
+
+ /* ************************************************* */
+ /* Patch by Alvarado: (not in the original version */
+
+ /*
+ * the camera recognizes modes from 0 to 4:
+ *
+ * 00: indoor (incandescant lighting)
+ * 01: outdoor (sunlight)
+ * 02: fluorescent lighting
+ * 03: manual
+ * 04: auto
+ */
+static inline int pwc_set_awb(struct pwc_device *pdev, int mode)
+{
+ char buf;
+ int ret;
+
+ if (mode < 0)
+ mode = 0;
+
+ if (mode > 4)
+ mode = 4;
+
+ buf = mode & 0x07; /* just the lowest three bits */
+
+ ret = SendControlMsg(SET_CHROM_CTL, WB_MODE_FORMATTER, 1);
+
+ if (ret < 0)
+ return ret;
+ return 0;
+}
+
+static inline int pwc_get_awb(struct pwc_device *pdev)
+{
+ unsigned char buf;
+ int ret;
+
+ ret = RecvControlMsg(GET_CHROM_CTL, WB_MODE_FORMATTER, 1);
+
+ if (ret < 0)
+ return ret;
+ return buf;
+}
+
+static inline int pwc_set_red_gain(struct pwc_device *pdev, int value)
+{
+ unsigned char buf;
+
+ if (value < 0)
+ value = 0;
+ if (value > 0xffff)
+ value = 0xffff;
+ /* only the msb is considered */
+ buf = value >> 8;
+ return SendControlMsg(SET_CHROM_CTL, PRESET_MANUAL_RED_GAIN_FORMATTER, 1);
+}
+
+static inline int pwc_get_red_gain(struct pwc_device *pdev, int *value)
+{
+ unsigned char buf;
+ int ret;
+
+ ret = RecvControlMsg(GET_CHROM_CTL, PRESET_MANUAL_RED_GAIN_FORMATTER, 1);
+ if (ret < 0)
+ return ret;
+ *value = buf << 8;
+ return 0;
+}
+
+
+static inline int pwc_set_blue_gain(struct pwc_device *pdev, int value)
+{
+ unsigned char buf;
+
+ if (value < 0)
+ value = 0;
+ if (value > 0xffff)
+ value = 0xffff;
+ /* only the msb is considered */
+ buf = value >> 8;
+ return SendControlMsg(SET_CHROM_CTL, PRESET_MANUAL_BLUE_GAIN_FORMATTER, 1);
+}
+
+static inline int pwc_get_blue_gain(struct pwc_device *pdev, int *value)
+{
+ unsigned char buf;
+ int ret;
+
+ ret = RecvControlMsg(GET_CHROM_CTL, PRESET_MANUAL_BLUE_GAIN_FORMATTER, 1);
+ if (ret < 0)
+ return ret;
+ *value = buf << 8;
+ return 0;
+}
+
+
+/* The following two functions are different, since they only read the
+ internal red/blue gains, which may be different from the manual
+ gains set or read above.
+ */
+static inline int pwc_read_red_gain(struct pwc_device *pdev, int *value)
+{
+ unsigned char buf;
+ int ret;
+
+ ret = RecvControlMsg(GET_STATUS_CTL, READ_RED_GAIN_FORMATTER, 1);
+ if (ret < 0)
+ return ret;
+ *value = buf << 8;
+ return 0;
+}
+
+static inline int pwc_read_blue_gain(struct pwc_device *pdev, int *value)
+{
+ unsigned char buf;
+ int ret;
+
+ ret = RecvControlMsg(GET_STATUS_CTL, READ_BLUE_GAIN_FORMATTER, 1);
+ if (ret < 0)
+ return ret;
+ *value = buf << 8;
+ return 0;
+}
+
+
+static inline int pwc_set_wb_speed(struct pwc_device *pdev, int speed)
+{
+ unsigned char buf;
+
+ /* useful range is 0x01..0x20 */
+ buf = speed / 0x7f0;
+ return SendControlMsg(SET_CHROM_CTL, AWB_CONTROL_SPEED_FORMATTER, 1);
+}
+
+static inline int pwc_get_wb_speed(struct pwc_device *pdev, int *value)
+{
+ unsigned char buf;
+ int ret;
+
+ ret = RecvControlMsg(GET_CHROM_CTL, AWB_CONTROL_SPEED_FORMATTER, 1);
+ if (ret < 0)
+ return ret;
+ *value = buf * 0x7f0;
+ return 0;
+}
+
+
+static inline int pwc_set_wb_delay(struct pwc_device *pdev, int delay)
+{
+ unsigned char buf;
+
+ /* useful range is 0x01..0x3F */
+ buf = (delay >> 10);
+ return SendControlMsg(SET_CHROM_CTL, AWB_CONTROL_DELAY_FORMATTER, 1);
+}
+
+static inline int pwc_get_wb_delay(struct pwc_device *pdev, int *value)
+{
+ unsigned char buf;
+ int ret;
+
+ ret = RecvControlMsg(GET_CHROM_CTL, AWB_CONTROL_DELAY_FORMATTER, 1);
+ if (ret < 0)
+ return ret;
+ *value = buf << 10;
+ return 0;
+}
+
+
+int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value)
+{
+ unsigned char buf[2];
+
+ if (pdev->type < 730)
+ return 0;
+ on_value /= 100;
+ off_value /= 100;
+ if (on_value < 0)
+ on_value = 0;
+ if (on_value > 0xff)
+ on_value = 0xff;
+ if (off_value < 0)
+ off_value = 0;
+ if (off_value > 0xff)
+ off_value = 0xff;
+
+ buf[0] = on_value;
+ buf[1] = off_value;
+
+ return SendControlMsg(SET_STATUS_CTL, LED_FORMATTER, 2);
+}
+
+int pwc_get_leds(struct pwc_device *pdev, int *on_value, int *off_value)
+{
+ unsigned char buf[2];
+ int ret;
+
+ if (pdev->type < 730) {
+ *on_value = -1;
+ *off_value = -1;
+ return 0;
+ }
+
+ ret = RecvControlMsg(GET_STATUS_CTL, LED_FORMATTER, 2);
+ if (ret < 0)
+ return ret;
+ *on_value = buf[0] * 100;
+ *off_value = buf[1] * 100;
+ return 0;
+}
+
+static inline int pwc_set_contour(struct pwc_device *pdev, int contour)
+{
+ unsigned char buf;
+ int ret;
+
+ if (contour < 0)
+ buf = 0xff; /* auto contour on */
+ else
+ buf = 0x0; /* auto contour off */
+ ret = SendControlMsg(SET_LUM_CTL, AUTO_CONTOUR_FORMATTER, 1);
+ if (ret < 0)
+ return ret;
+
+ if (contour < 0)
+ return 0;
+ if (contour > 0xffff)
+ contour = 0xffff;
+
+ buf = (contour >> 10); /* contour preset is [0..3f] */
+ ret = SendControlMsg(SET_LUM_CTL, PRESET_CONTOUR_FORMATTER, 1);
+ if (ret < 0)
+ return ret;
+ return 0;
+}
+
+static inline int pwc_get_contour(struct pwc_device *pdev, int *contour)
+{
+ unsigned char buf;
+ int ret;
+
+ ret = RecvControlMsg(GET_LUM_CTL, AUTO_CONTOUR_FORMATTER, 1);
+ if (ret < 0)
+ return ret;
+
+ if (buf == 0) {
+ /* auto mode off, query current preset value */
+ ret = RecvControlMsg(GET_LUM_CTL, PRESET_CONTOUR_FORMATTER, 1);
+ if (ret < 0)
+ return ret;
+ *contour = buf << 10;
+ }
+ else
+ *contour = -1;
+ return 0;
+}
+
+
+static inline int pwc_set_backlight(struct pwc_device *pdev, int backlight)
+{
+ unsigned char buf;
+
+ if (backlight)
+ buf = 0xff;
+ else
+ buf = 0x0;
+ return SendControlMsg(SET_LUM_CTL, BACK_LIGHT_COMPENSATION_FORMATTER, 1);
+}
+
+static inline int pwc_get_backlight(struct pwc_device *pdev, int *backlight)
+{
+ int ret;
+ unsigned char buf;
+
+ ret = RecvControlMsg(GET_LUM_CTL, BACK_LIGHT_COMPENSATION_FORMATTER, 1);
+ if (ret < 0)
+ return ret;
+ *backlight = buf;
+ return 0;
+}
+
+
+static inline int pwc_set_flicker(struct pwc_device *pdev, int flicker)
+{
+ unsigned char buf;
+
+ if (flicker)
+ buf = 0xff;
+ else
+ buf = 0x0;
+ return SendControlMsg(SET_LUM_CTL, FLICKERLESS_MODE_FORMATTER, 1);
+}
+
+static inline int pwc_get_flicker(struct pwc_device *pdev, int *flicker)
+{
+ int ret;
+ unsigned char buf;
+
+ ret = RecvControlMsg(GET_LUM_CTL, FLICKERLESS_MODE_FORMATTER, 1);
+ if (ret < 0)
+ return ret;
+ *flicker = buf;
+ return 0;
+}
+
+
+static inline int pwc_set_dynamic_noise(struct pwc_device *pdev, int noise)
+{
+ unsigned char buf;
+
+ if (noise < 0)
+ noise = 0;
+ if (noise > 3)
+ noise = 3;
+ buf = noise;
+ return SendControlMsg(SET_LUM_CTL, DYNAMIC_NOISE_CONTROL_FORMATTER, 1);
+}
+
+static inline int pwc_get_dynamic_noise(struct pwc_device *pdev, int *noise)
+{
+ int ret;
+ unsigned char buf;
+
+ ret = RecvControlMsg(GET_LUM_CTL, DYNAMIC_NOISE_CONTROL_FORMATTER, 1);
+ if (ret < 0)
+ return ret;
+ *noise = buf;
+ return 0;
+}
+
+static int pwc_mpt_reset(struct pwc_device *pdev, int flags)
+{
+ unsigned char buf;
+
+ buf = flags & 0x03; // only lower two bits are currently used
+ return SendControlMsg(SET_MPT_CTL, PT_RESET_CONTROL_FORMATTER, 1);
+}
+
+static inline int pwc_mpt_set_angle(struct pwc_device *pdev, int pan, int tilt)
+{
+ unsigned char buf[4];
+
+ /* set new relative angle; angles are expressed in degrees * 100,
+ but cam as .5 degree resolution, hence devide by 200. Also
+ the angle must be multiplied by 64 before it's send to
+ the cam (??)
+ */
+ pan = 64 * pan / 100;
+ tilt = -64 * tilt / 100; /* positive tilt is down, which is not what the user would expect */
+ buf[0] = pan & 0xFF;
+ buf[1] = (pan >> 8) & 0xFF;
+ buf[2] = tilt & 0xFF;
+ buf[3] = (tilt >> 8) & 0xFF;
+ return SendControlMsg(SET_MPT_CTL, PT_RELATIVE_CONTROL_FORMATTER, 4);
+}
+
+static inline int pwc_mpt_get_status(struct pwc_device *pdev, struct pwc_mpt_status *status)
+{
+ int ret;
+ unsigned char buf[5];
+
+ ret = RecvControlMsg(GET_MPT_CTL, PT_STATUS_FORMATTER, 5);
+ if (ret < 0)
+ return ret;
+ status->status = buf[0] & 0x7; // 3 bits are used for reporting
+ status->time_pan = (buf[1] << 8) + buf[2];
+ status->time_tilt = (buf[3] << 8) + buf[4];
+ return 0;
+}
+
+
+int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor)
+{
+ unsigned char buf;
+ int ret = -1, request;
+
+ if (pdev->type < 675)
+ request = SENSOR_TYPE_FORMATTER1;
+ else if (pdev->type < 730)
+ return -1; /* The Vesta series doesn't have this call */
+ else
+ request = SENSOR_TYPE_FORMATTER2;
+
+ ret = RecvControlMsg(GET_STATUS_CTL, request, 1);
+ if (ret < 0)
+ return ret;
+ if (pdev->type < 675)
+ *sensor = buf | 0x100;
+ else
+ *sensor = buf;
+ return 0;
+}
+
+
+ /* End of Add-Ons */
+ /* ************************************************* */
+
+/* Linux 2.5.something and 2.6 pass direct pointers to arguments of
+ ioctl() calls. With 2.4, you have to do tedious copy_from_user()
+ and copy_to_user() calls. With these macros we circumvent this,
+ and let me maintain only one source file. The functionality is
+ exactly the same otherwise.
+ */
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
+
+/* define local variable for arg */
+#define ARG_DEF(ARG_type, ARG_name)\
+ ARG_type *ARG_name = arg;
+/* copy arg to local variable */
+#define ARG_IN(ARG_name) /* nothing */
+/* argument itself (referenced) */
+#define ARGR(ARG_name) (*ARG_name)
+/* argument address */
+#define ARGA(ARG_name) ARG_name
+/* copy local variable to arg */
+#define ARG_OUT(ARG_name) /* nothing */
+
+#else
+
+#define ARG_DEF(ARG_type, ARG_name)\
+ ARG_type ARG_name;
+#define ARG_IN(ARG_name)\
+ if (copy_from_user(&ARG_name, arg, sizeof(ARG_name))) {\
+ ret = -EFAULT;\
+ break;\
+ }
+#define ARGR(ARG_name) ARG_name
+#define ARGA(ARG_name) &ARG_name
+#define ARG_OUT(ARG_name)\
+ if (copy_to_user(arg, &ARG_name, sizeof(ARG_name))) {\
+ ret = -EFAULT;\
+ break;\
+ }
+
+#endif
+
+int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
+{
+ int ret = 0;
+
+ switch(cmd) {
+ case VIDIOCPWCRUSER:
+ {
+ if (pwc_restore_user(pdev))
+ ret = -EINVAL;
+ break;
+ }
+
+ case VIDIOCPWCSUSER:
+ {
+ if (pwc_save_user(pdev))
+ ret = -EINVAL;
+ break;
+ }
+
+ case VIDIOCPWCFACTORY:
+ {
+ if (pwc_restore_factory(pdev))
+ ret = -EINVAL;
+ break;
+ }
+
+ case VIDIOCPWCSCQUAL:
+ {
+ ARG_DEF(int, qual)
+
+ ARG_IN(qual)
+ if (ARGR(qual) < 0 || ARGR(qual) > 3)
+ ret = -EINVAL;
+ else
+ ret = pwc_try_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, ARGR(qual), pdev->vsnapshot);
+ if (ret >= 0)
+ pdev->vcompression = ARGR(qual);
+ break;
+ }
+
+ case VIDIOCPWCGCQUAL:
+ {
+ ARG_DEF(int, qual)
+
+ ARGR(qual) = pdev->vcompression;
+ ARG_OUT(qual)
+ break;
+ }
+
+ case VIDIOCPWCPROBE:
+ {
+ ARG_DEF(struct pwc_probe, probe)
+
+ strcpy(ARGR(probe).name, pdev->vdev->name);
+ ARGR(probe).type = pdev->type;
+ ARG_OUT(probe)
+ break;
+ }
+
+ case VIDIOCPWCGSERIAL:
+ {
+ ARG_DEF(struct pwc_serial, serial)
+
+ strcpy(ARGR(serial).serial, pdev->serial);
+ ARG_OUT(serial)
+ break;
+ }
+
+ case VIDIOCPWCSAGC:
+ {
+ ARG_DEF(int, agc)
+
+ ARG_IN(agc)
+ if (pwc_set_agc(pdev, ARGR(agc) < 0 ? 1 : 0, ARGR(agc)))
+ ret = -EINVAL;
+ break;
+ }
+
+ case VIDIOCPWCGAGC:
+ {
+ ARG_DEF(int, agc)
+
+ if (pwc_get_agc(pdev, ARGA(agc)))
+ ret = -EINVAL;
+ ARG_OUT(agc)
+ break;
+ }
+
+ case VIDIOCPWCSSHUTTER:
+ {
+ ARG_DEF(int, shutter_speed)
+
+ ARG_IN(shutter_speed)
+ ret = pwc_set_shutter_speed(pdev, ARGR(shutter_speed) < 0 ? 1 : 0, ARGR(shutter_speed));
+ break;
+ }
+
+ case VIDIOCPWCSAWB:
+ {
+ ARG_DEF(struct pwc_whitebalance, wb)
+
+ ARG_IN(wb)
+ ret = pwc_set_awb(pdev, ARGR(wb).mode);
+ if (ret >= 0 && ARGR(wb).mode == PWC_WB_MANUAL) {
+ pwc_set_red_gain(pdev, ARGR(wb).manual_red);
+ pwc_set_blue_gain(pdev, ARGR(wb).manual_blue);
+ }
+ break;
+ }
+
+ case VIDIOCPWCGAWB:
+ {
+ ARG_DEF(struct pwc_whitebalance, wb)
+
+ memset(ARGA(wb), 0, sizeof(struct pwc_whitebalance));
+ ARGR(wb).mode = pwc_get_awb(pdev);
+ if (ARGR(wb).mode < 0)
+ ret = -EINVAL;
+ else {
+ if (ARGR(wb).mode == PWC_WB_MANUAL) {
+ ret = pwc_get_red_gain(pdev, &ARGR(wb).manual_red);
+ if (ret < 0)
+ break;
+ ret = pwc_get_blue_gain(pdev, &ARGR(wb).manual_blue);
+ if (ret < 0)
+ break;
+ }
+ if (ARGR(wb).mode == PWC_WB_AUTO) {
+ ret = pwc_read_red_gain(pdev, &ARGR(wb).read_red);
+ if (ret < 0)
+ break;
+ ret =pwc_read_blue_gain(pdev, &ARGR(wb).read_blue);
+ if (ret < 0)
+ break;
+ }
+ }
+ ARG_OUT(wb)
+ break;
+ }
+
+ case VIDIOCPWCSAWBSPEED:
+ {
+ ARG_DEF(struct pwc_wb_speed, wbs)
+
+ if (ARGR(wbs).control_speed > 0) {
+ ret = pwc_set_wb_speed(pdev, ARGR(wbs).control_speed);
+ }
+ if (ARGR(wbs).control_delay > 0) {
+ ret = pwc_set_wb_delay(pdev, ARGR(wbs).control_delay);
+ }
+ break;
+ }
+
+ case VIDIOCPWCGAWBSPEED:
+ {
+ ARG_DEF(struct pwc_wb_speed, wbs)
+
+ ret = pwc_get_wb_speed(pdev, &ARGR(wbs).control_speed);
+ if (ret < 0)
+ break;
+ ret = pwc_get_wb_delay(pdev, &ARGR(wbs).control_delay);
+ if (ret < 0)
+ break;
+ ARG_OUT(wbs)
+ break;
+ }
+
+ case VIDIOCPWCSLED:
+ {
+ ARG_DEF(struct pwc_leds, leds)
+
+ ARG_IN(leds)
+ ret = pwc_set_leds(pdev, ARGR(leds).led_on, ARGR(leds).led_off);
+ break;
+ }
+
+
+ case VIDIOCPWCGLED:
+ {
+ ARG_DEF(struct pwc_leds, leds)
+
+ ret = pwc_get_leds(pdev, &ARGR(leds).led_on, &ARGR(leds).led_off);
+ ARG_OUT(leds)
+ break;
+ }
+
+ case VIDIOCPWCSCONTOUR:
+ {
+ ARG_DEF(int, contour)
+
+ ARG_IN(contour)
+ ret = pwc_set_contour(pdev, ARGR(contour));
+ break;
+ }
+
+ case VIDIOCPWCGCONTOUR:
+ {
+ ARG_DEF(int, contour)
+
+ ret = pwc_get_contour(pdev, ARGA(contour));
+ ARG_OUT(contour)
+ break;
+ }
+
+ case VIDIOCPWCSBACKLIGHT:
+ {
+ ARG_DEF(int, backlight)
+
+ ARG_IN(backlight)
+ ret = pwc_set_backlight(pdev, ARGR(backlight));
+ break;
+ }
+
+ case VIDIOCPWCGBACKLIGHT:
+ {
+ ARG_DEF(int, backlight)
+
+ ret = pwc_get_backlight(pdev, ARGA(backlight));
+ ARG_OUT(backlight)
+ break;
+ }
+
+ case VIDIOCPWCSFLICKER:
+ {
+ ARG_DEF(int, flicker)
+
+ ARG_IN(flicker)
+ ret = pwc_set_flicker(pdev, ARGR(flicker));
+ break;
+ }
+
+ case VIDIOCPWCGFLICKER:
+ {
+ ARG_DEF(int, flicker)
+
+ ret = pwc_get_flicker(pdev, ARGA(flicker));
+ ARG_OUT(flicker)
+ break;
+ }
+
+ case VIDIOCPWCSDYNNOISE:
+ {
+ ARG_DEF(int, dynnoise)
+
+ ARG_IN(dynnoise)
+ ret = pwc_set_dynamic_noise(pdev, ARGR(dynnoise));
+ break;
+ }
+
+ case VIDIOCPWCGDYNNOISE:
+ {
+ ARG_DEF(int, dynnoise)
+
+ ret = pwc_get_dynamic_noise(pdev, ARGA(dynnoise));
+ ARG_OUT(dynnoise);
+ break;
+ }
+
+ case VIDIOCPWCGREALSIZE:
+ {
+ ARG_DEF(struct pwc_imagesize, size)
+
+ ARGR(size).width = pdev->image.x;
+ ARGR(size).height = pdev->image.y;
+ ARG_OUT(size)
+ break;
+ }
+
+ case VIDIOCPWCMPTRESET:
+ {
+ if (pdev->features & FEATURE_MOTOR_PANTILT)
+ {
+ ARG_DEF(int, flags)
+
+ ARG_IN(flags)
+ ret = pwc_mpt_reset(pdev, ARGR(flags));
+ if (ret >= 0)
+ {
+ pdev->pan_angle = 0;
+ pdev->tilt_angle = 0;
+ }
+ }
+ else
+ {
+ ret = -ENXIO;
+ }
+ break;
+ }
+
+ case VIDIOCPWCMPTGRANGE:
+ {
+ if (pdev->features & FEATURE_MOTOR_PANTILT)
+ {
+ ARG_DEF(struct pwc_mpt_range, range)
+
+ ARGR(range) = pdev->angle_range;
+ ARG_OUT(range)
+ }
+ else
+ {
+ ret = -ENXIO;
+ }
+ break;
+ }
+
+ case VIDIOCPWCMPTSANGLE:
+ {
+ int new_pan, new_tilt;
+
+ if (pdev->features & FEATURE_MOTOR_PANTILT)
+ {
+ ARG_DEF(struct pwc_mpt_angles, angles)
+
+ ARG_IN(angles)
+ /* The camera can only set relative angles, so
+ do some calculations when getting an absolute angle .
+ */
+ if (ARGR(angles).absolute)
+ {
+ new_pan = ARGR(angles).pan;
+ new_tilt = ARGR(angles).tilt;
+ }
+ else
+ {
+ new_pan = pdev->pan_angle + ARGR(angles).pan;
+ new_tilt = pdev->tilt_angle + ARGR(angles).tilt;
+ }
+ /* check absolute ranges */
+ if (new_pan < pdev->angle_range.pan_min ||
+ new_pan > pdev->angle_range.pan_max ||
+ new_tilt < pdev->angle_range.tilt_min ||
+ new_tilt > pdev->angle_range.tilt_max)
+ {
+ ret = -ERANGE;
+ }
+ else
+ {
+ /* go to relative range, check again */
+ new_pan -= pdev->pan_angle;
+ new_tilt -= pdev->tilt_angle;
+ /* angles are specified in degrees * 100, thus the limit = 36000 */
+ if (new_pan < -36000 || new_pan > 36000 || new_tilt < -36000 || new_tilt > 36000)
+ ret = -ERANGE;
+ }
+ if (ret == 0) /* no errors so far */
+ {
+ ret = pwc_mpt_set_angle(pdev, new_pan, new_tilt);
+ if (ret >= 0)
+ {
+ pdev->pan_angle += new_pan;
+ pdev->tilt_angle += new_tilt;
+ }
+ if (ret == -EPIPE) /* stall -> out of range */
+ ret = -ERANGE;
+ }
+ }
+ else
+ {
+ ret = -ENXIO;
+ }
+ break;
+ }
+
+ case VIDIOCPWCMPTGANGLE:
+ {
+
+ if (pdev->features & FEATURE_MOTOR_PANTILT)
+ {
+ ARG_DEF(struct pwc_mpt_angles, angles)
+
+ ARGR(angles).absolute = 1;
+ ARGR(angles).pan = pdev->pan_angle;
+ ARGR(angles).tilt = pdev->tilt_angle;
+ ARG_OUT(angles)
+ }
+ else
+ {
+ ret = -ENXIO;
+ }
+ break;
+ }
+
+ case VIDIOCPWCMPTSTATUS:
+ {
+ if (pdev->features & FEATURE_MOTOR_PANTILT)
+ {
+ ARG_DEF(struct pwc_mpt_status, status)
+
+ ret = pwc_mpt_get_status(pdev, ARGA(status));
+ ARG_OUT(status)
+ }
+ else
+ {
+ ret = -ENXIO;
+ }
+ break;
+ }
+
+ case VIDIOCPWCGVIDCMD:
+ {
+ ARG_DEF(struct pwc_video_command, cmd);
+
+ ARGR(cmd).type = pdev->type;
+ ARGR(cmd).release = pdev->release;
+ ARGR(cmd).command_len = pdev->cmd_len;
+ memcpy(&ARGR(cmd).command_buf, pdev->cmd_buf, pdev->cmd_len);
+ ARGR(cmd).bandlength = pdev->vbandlength;
+ ARGR(cmd).frame_size = pdev->frame_size;
+ ARG_OUT(cmd)
+ break;
+ }
+ /*
+ case VIDIOCPWCGVIDTABLE:
+ {
+ ARG_DEF(struct pwc_table_init_buffer, table);
+ ARGR(table).len = pdev->cmd_len;
+ memcpy(&ARGR(table).buffer, pdev->decompress_data, pdev->decompressor->table_size);
+ ARG_OUT(table)
+ break;
+ }
+ */
+
+ default:
+ ret = -ENOIOCTLCMD;
+ break;
+ }
+
+ if (ret > 0)
+ return 0;
+ return ret;
+}
+
+
+
diff --git a/drivers/usb/media/pwc/pwc-dec1.c b/drivers/usb/media/pwc/pwc-dec1.c
new file mode 100644
index 0000000000000..57d03d9178f61
--- /dev/null
+++ b/drivers/usb/media/pwc/pwc-dec1.c
@@ -0,0 +1,42 @@
+/* Linux driver for Philips webcam
+ Decompression for chipset version 1
+ (C) 2004 Luc Saillard (luc@saillard.org)
+
+ NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+ driver and thus may have bugs that are not present in the original version.
+ Please send bug reports and support requests to <luc@saillard.org>.
+ The decompression routines have been implemented by reverse-engineering the
+ Nemosoft binary pwcx module. Caveat emptor.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the 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 "pwc-dec1.h"
+
+
+void pwc_dec1_init(int type, int release, void *buffer, void *table)
+{
+
+}
+
+void pwc_dec1_exit(void)
+{
+
+
+
+}
+
diff --git a/drivers/usb/media/pwc/pwc-dec1.h b/drivers/usb/media/pwc/pwc-dec1.h
new file mode 100644
index 0000000000000..a7ffd9c45a2c2
--- /dev/null
+++ b/drivers/usb/media/pwc/pwc-dec1.h
@@ -0,0 +1,36 @@
+/* Linux driver for Philips webcam
+ (C) 2004 Luc Saillard (luc@saillard.org)
+
+ NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+ driver and thus may have bugs that are not present in the original version.
+ Please send bug reports and support requests to <luc@saillard.org>.
+ The decompression routines have been implemented by reverse-engineering the
+ Nemosoft binary pwcx module. Caveat emptor.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the 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 PWC_DEC1_H
+#define PWC_DEC1_H
+
+void pwc_dec1_init(int type, int release, void *buffer, void *private_data);
+void pwc_dec1_exit(void);
+
+#endif
+
+
+
diff --git a/drivers/usb/media/pwc/pwc-dec23.c b/drivers/usb/media/pwc/pwc-dec23.c
new file mode 100644
index 0000000000000..98fa3f7a9eff4
--- /dev/null
+++ b/drivers/usb/media/pwc/pwc-dec23.c
@@ -0,0 +1,623 @@
+/* Linux driver for Philips webcam
+ Decompression for chipset version 2 et 3
+ (C) 2004 Luc Saillard (luc@saillard.org)
+
+ NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+ driver and thus may have bugs that are not present in the original version.
+ Please send bug reports and support requests to <luc@saillard.org>.
+ The decompression routines have been implemented by reverse-engineering the
+ Nemosoft binary pwcx module. Caveat emptor.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the 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 "pwc-timon.h"
+#include "pwc-kiara.h"
+#include "pwc-dec23.h"
+#include "pwc-ioctl.h"
+
+#include <linux/string.h>
+
+/****
+ *
+ *
+ *
+ */
+
+
+static void fill_table_a000(unsigned int *p)
+{
+ static unsigned int initial_values[12] = {
+ 0xFFAD9B00, 0xFFDDEE00, 0x00221200, 0x00526500,
+ 0xFFC21E00, 0x003DE200, 0xFF924B80, 0xFFD2A300,
+ 0x002D5D00, 0x006DB480, 0xFFED3E00, 0x0012C200
+ };
+ static unsigned int values_derivated[12] = {
+ 0x0000A4CA, 0x00004424, 0xFFFFBBDC, 0xFFFF5B36,
+ 0x00007BC4, 0xFFFF843C, 0x0000DB69, 0x00005ABA,
+ 0xFFFFA546, 0xFFFF2497, 0x00002584, 0xFFFFDA7C
+ };
+ unsigned int temp_values[12];
+ int i,j;
+
+ memcpy(temp_values,initial_values,sizeof(initial_values));
+ for (i=0;i<256;i++)
+ {
+ for (j=0;j<12;j++)
+ {
+ *p++ = temp_values[j];
+ temp_values[j] += values_derivated[j];
+ }
+ }
+}
+
+static void fill_table_d000(unsigned char *p)
+{
+ int bit,byte;
+
+ for (bit=0; bit<8; bit++)
+ {
+ unsigned char bitpower = 1<<bit;
+ unsigned char mask = bitpower-1;
+ for (byte=0; byte<256; byte++)
+ {
+ if (byte & bitpower)
+ *p++ = -(byte & mask);
+ else
+ *p++ = (byte & mask);
+ }
+ }
+}
+
+/*
+ *
+ * Kiara: 0 <= ver <= 7
+ * Timon: 0 <= ver <= 15
+ *
+ */
+static void fill_table_color(unsigned int version, const unsigned int *romtable,
+ unsigned char *p0004,
+ unsigned char *p8004)
+{
+ const unsigned int *table;
+ unsigned char *p0, *p8;
+ int i,j,k;
+ int dl,bit,pw;
+
+ romtable += version*256;
+
+ for (i=0; i<2; i++)
+ {
+ table = romtable + i*128;
+
+ for (dl=0; dl<16; dl++)
+ {
+ p0 = p0004 + (i<<14) + (dl<<10);
+ p8 = p8004 + (i<<12) + (dl<<8);
+
+ for (j=0; j<8; j++ , table++, p0+=128)
+ {
+ for (k=0; k<16; k++)
+ {
+ if (k==0)
+ bit=1;
+ else if (k>=1 && k<3)
+ bit=(table[0]>>15)&7;
+ else if (k>=3 && k<6)
+ bit=(table[0]>>12)&7;
+ else if (k>=6 && k<10)
+ bit=(table[0]>>9)&7;
+ else if (k>=10 && k<13)
+ bit=(table[0]>>6)&7;
+ else if (k>=13 && k<15)
+ bit=(table[0]>>3)&7;
+ else
+ bit=(table[0])&7;
+ if (k == 0)
+ *(unsigned char *)p8++ = 8;
+ else
+ *(unsigned char *)p8++ = j - bit;
+ *(unsigned char *)p8++ = bit;
+
+ pw = 1<<bit;
+ p0[k+0x00] = (1*pw) + 0x80;
+ p0[k+0x10] = (2*pw) + 0x80;
+ p0[k+0x20] = (3*pw) + 0x80;
+ p0[k+0x30] = (4*pw) + 0x80;
+ p0[k+0x40] = (-pw) + 0x80;
+ p0[k+0x50] = (2*-pw) + 0x80;
+ p0[k+0x60] = (3*-pw) + 0x80;
+ p0[k+0x70] = (4*-pw) + 0x80;
+ } /* end of for (k=0; k<16; k++, p8++) */
+ } /* end of for (j=0; j<8; j++ , table++) */
+ } /* end of for (dl=0; dl<16; dl++) */
+ } /* end of for (i=0; i<2; i++) */
+}
+
+/*
+ * precision = (pdev->xx + pdev->yy)
+ *
+ */
+static void fill_table_dc00_d800(unsigned int precision, unsigned int *pdc00, unsigned int *pd800)
+{
+ int i;
+ unsigned int offset1, offset2;
+
+ for(i=0,offset1=0x4000, offset2=0; i<256 ; i++,offset1+=0x7BC4, offset2+=0x7BC4)
+ {
+ unsigned int msb = offset1 >> 15;
+
+ if ( msb > 255)
+ {
+ if (msb)
+ msb=0;
+ else
+ msb=255;
+ }
+
+ *pdc00++ = msb << precision;
+ *pd800++ = offset2;
+ }
+
+}
+
+/*
+ * struct {
+ * unsigned char op; // operation to execute
+ * unsigned char bits; // bits use to perform operation
+ * unsigned char offset1; // offset to add to access in the table_0004 % 16
+ * unsigned char offset2; // offset to add to access in the table_0004
+ * }
+ *
+ */
+static unsigned int table_ops[] = {
+0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x00, 0x00,0x04,0x01,0x10, 0x00,0x06,0x01,0x30,
+0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x40, 0x00,0x05,0x01,0x20, 0x01,0x00,0x00,0x00,
+0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x00, 0x00,0x04,0x01,0x50, 0x00,0x05,0x02,0x00,
+0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x40, 0x00,0x05,0x03,0x00, 0x01,0x00,0x00,0x00,
+0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x00, 0x00,0x04,0x01,0x10, 0x00,0x06,0x02,0x10,
+0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x40, 0x00,0x05,0x01,0x60, 0x01,0x00,0x00,0x00,
+0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x00, 0x00,0x04,0x01,0x50, 0x00,0x05,0x02,0x40,
+0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x40, 0x00,0x05,0x03,0x40, 0x01,0x00,0x00,0x00,
+0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x00, 0x00,0x04,0x01,0x10, 0x00,0x06,0x01,0x70,
+0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x40, 0x00,0x05,0x01,0x20, 0x01,0x00,0x00,0x00,
+0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x00, 0x00,0x04,0x01,0x50, 0x00,0x05,0x02,0x00,
+0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x40, 0x00,0x05,0x03,0x00, 0x01,0x00,0x00,0x00,
+0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x00, 0x00,0x04,0x01,0x10, 0x00,0x06,0x02,0x50,
+0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x40, 0x00,0x05,0x01,0x60, 0x01,0x00,0x00,0x00,
+0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x00, 0x00,0x04,0x01,0x50, 0x00,0x05,0x02,0x40,
+0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x40, 0x00,0x05,0x03,0x40, 0x01,0x00,0x00,0x00
+};
+
+/*
+ * TODO: multiply by 4 all values
+ *
+ */
+static unsigned int MulIdx[256] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+ 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
+ 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4,
+ 6, 7, 8, 9, 7,10,11, 8, 8,11,10, 7, 9, 8, 7, 6,
+ 4, 5, 5, 4, 4, 5, 5, 4, 4, 5, 5, 4, 4, 5, 5, 4,
+ 1, 3, 0, 2, 1, 3, 0, 2, 1, 3, 0, 2, 1, 3, 0, 2,
+ 0, 3, 3, 0, 1, 2, 2, 1, 2, 1, 1, 2, 3, 0, 0, 3,
+ 0, 1, 2, 3, 3, 2, 1, 0, 3, 2, 1, 0, 0, 1, 2, 3,
+ 1, 1, 1, 1, 3, 3, 3, 3, 0, 0, 0, 0, 2, 2, 2, 2,
+ 7,10,11, 8, 9, 8, 7, 6, 6, 7, 8, 9, 8,11,10, 7,
+ 4, 5, 5, 4, 5, 4, 4, 5, 5, 4, 4, 5, 4, 5, 5, 4,
+ 7, 9, 6, 8,10, 8, 7,11,11, 7, 8,10, 8, 6, 9, 7,
+ 1, 3, 0, 2, 2, 0, 3, 1, 2, 0, 3, 1, 1, 3, 0, 2,
+ 1, 2, 2, 1, 3, 0, 0, 3, 0, 3, 3, 0, 2, 1, 1, 2,
+10, 8, 7,11, 8, 6, 9, 7, 7, 9, 6, 8,11, 7, 8,10
+};
+
+
+
+void pwc_dec23_init(int type, int release, unsigned char *mode, void *data)
+{
+ int flags;
+ struct pwc_dec23_private *pdev = data;
+ release = release;
+
+ switch (type)
+ {
+ case 720:
+ case 730:
+ case 740:
+ case 750:
+ flags = mode[2]&0x18; /* our: flags = 8, mode[2]==e8 */
+ if (flags==8)
+ pdev->zz = 7;
+ else if (flags==0x10)
+ pdev->zz = 8;
+ else
+ pdev->zz = 6;
+ flags = mode[2]>>5; /* our: 7 */
+
+ fill_table_color(flags, (unsigned int *)KiaraRomTable, pdev->table_0004, pdev->table_8004);
+ break;
+
+
+ case 675:
+ case 680:
+ case 690:
+ flags = mode[2]&6;
+ if (flags==2)
+ pdev->zz = 7;
+ else if (flags==4)
+ pdev->zz = 8;
+ else
+ pdev->zz = 6;
+ flags = mode[2]>>3;
+
+ fill_table_color(flags, (unsigned int *)TimonRomTable, pdev->table_0004, pdev->table_8004);
+ break;
+
+ default:
+ /* Not supported */
+ return;
+ }
+
+ /* * * * ** */
+ pdev->xx = 8 - pdev->zz;
+ pdev->yy = 15 - pdev->xx;
+ pdev->zzmask = 0xFF>>pdev->xx;
+ //pdev->zzmask = (1U<<pdev->zz)-1;
+
+
+ fill_table_dc00_d800(pdev->xx + pdev->yy, pdev->table_dc00, pdev->table_d800);
+ fill_table_a000(pdev->table_a004);
+ fill_table_d000(pdev->table_d004);
+}
+
+
+/*
+ * To manage the stream, we keep in a 32 bits variables,
+ * the next bits in the stream. fill_reservoir() add to
+ * the reservoir at least wanted nbits.
+ *
+ *
+ */
+#define fill_nbits(reservoir,nbits_in_reservoir,stream,nbits_wanted) do { \
+ while (nbits_in_reservoir<nbits_wanted) \
+ { \
+ reservoir |= (*(stream)++) << nbits_in_reservoir; \
+ nbits_in_reservoir+=8; \
+ } \
+} while(0);
+
+#define get_nbits(reservoir,nbits_in_reservoir,stream,nbits_wanted,result) do { \
+ fill_nbits(reservoir,nbits_in_reservoir,stream,nbits_wanted); \
+ result = (reservoir) & ((1U<<nbits_wanted)-1); \
+ reservoir >>= nbits_wanted; \
+ nbits_in_reservoir -= nbits_wanted; \
+} while(0);
+
+
+
+static void DecompressBand23(const struct pwc_dec23_private *pdev,
+ const unsigned char *rawyuv,
+ unsigned char *planar_y,
+ unsigned char *planar_u,
+ unsigned char *planar_v,
+ unsigned int image_x, /* aka number of pixels wanted ??? */
+ unsigned int pixels_per_line, /* aka number of pixels per line */
+ int flags)
+{
+
+
+ unsigned int reservoir, nbits_in_reservoir;
+ int first_4_bits;
+ unsigned int bytes_per_channel;
+ int line_size; /* size of the line (4Y+U+V) */
+ int passes;
+ const unsigned char *ptable0004, *ptable8004;
+
+ int even_line;
+ unsigned int temp_colors[16];
+ int nblocks;
+
+ const unsigned char *stream;
+ unsigned char *dest_y, *dest_u=NULL, *dest_v=NULL;
+ unsigned int offset_to_plane_u, offset_to_plane_v;
+
+ int i;
+
+
+ reservoir = 0;
+ nbits_in_reservoir = 0;
+ stream = rawyuv+1; /* The first byte of the stream is skipped */
+ even_line = 1;
+
+ get_nbits(reservoir,nbits_in_reservoir,stream,4,first_4_bits);
+
+ line_size = pixels_per_line*3;
+
+ for (passes=0;passes<2;passes++)
+ {
+ if (passes==0)
+ {
+ bytes_per_channel = pixels_per_line;
+ dest_y = planar_y;
+ nblocks = image_x/4;
+ }
+ else
+ {
+ /* Format planar: All Y, then all U, then all V */
+ bytes_per_channel = pixels_per_line/2;
+ dest_u = planar_u;
+ dest_v = planar_v;
+ dest_y = dest_u;
+ nblocks = image_x/8;
+ }
+
+ offset_to_plane_u = bytes_per_channel*2;
+ offset_to_plane_v = bytes_per_channel*3;
+ /*
+ printf("bytes_per_channel = %d\n",bytes_per_channel);
+ printf("offset_to_plane_u = %d\n",offset_to_plane_u);
+ printf("offset_to_plane_v = %d\n",offset_to_plane_v);
+ */
+
+ while (nblocks-->0)
+ {
+ unsigned int gray_index;
+
+ fill_nbits(reservoir,nbits_in_reservoir,stream,16);
+ gray_index = reservoir & pdev->zzmask;
+ reservoir >>= pdev->zz;
+ nbits_in_reservoir -= pdev->zz;
+
+ fill_nbits(reservoir,nbits_in_reservoir,stream,2);
+
+ if ( (reservoir & 3) == 0)
+ {
+ reservoir>>=2;
+ nbits_in_reservoir-=2;
+ for (i=0;i<16;i++)
+ temp_colors[i] = pdev->table_dc00[gray_index];
+
+ }
+ else
+ {
+ unsigned int channel_v, offset1;
+
+ /* swap bit 0 and 2 of offset_OR */
+ channel_v = ((reservoir & 1) << 2) | (reservoir & 2) | ((reservoir & 4)>>2);
+ reservoir>>=3;
+ nbits_in_reservoir-=3;
+
+ for (i=0;i<16;i++)
+ temp_colors[i] = pdev->table_d800[gray_index];
+
+ ptable0004 = pdev->table_0004 + (passes*16384) + (first_4_bits*1024) + (channel_v*128);
+ ptable8004 = pdev->table_8004 + (passes*4096) + (first_4_bits*256) + (channel_v*32);
+
+ offset1 = 0;
+ while(1)
+ {
+ unsigned int index_in_table_ops, op, rows=0;
+ fill_nbits(reservoir,nbits_in_reservoir,stream,16);
+
+ /* mode is 0,1 or 2 */
+ index_in_table_ops = (reservoir&0x3F);
+ op = table_ops[ index_in_table_ops*4 ];
+ if (op == 2)
+ {
+ reservoir >>= 2;
+ nbits_in_reservoir -= 2;
+ break; /* exit the while(1) */
+ }
+ if (op == 0)
+ {
+ unsigned int shift;
+
+ offset1 = (offset1 + table_ops[index_in_table_ops*4+2]) & 0x0F;
+ shift = table_ops[ index_in_table_ops*4+1 ];
+ reservoir >>= shift;
+ nbits_in_reservoir -= shift;
+ rows = ptable0004[ offset1 + table_ops[index_in_table_ops*4+3] ];
+ }
+ if (op == 1)
+ {
+ /* 10bits [ xxxx xxxx yyyy 000 ]
+ * yyy => offset in the table8004
+ * xxx => offset in the tabled004
+ */
+ unsigned int mask, shift;
+ unsigned int col1, row1, total_bits;
+
+ offset1 = (offset1 + ((reservoir>>3)&0x0F)+1) & 0x0F;
+
+ col1 = (reservoir>>7) & 0xFF;
+ row1 = ptable8004 [ offset1*2 ];
+
+ /* Bit mask table */
+ mask = pdev->table_d004[ (row1<<8) + col1 ];
+ shift = ptable8004 [ offset1*2 + 1];
+ rows = ((mask << shift) + 0x80) & 0xFF;
+
+ total_bits = row1 + 8;
+ reservoir >>= total_bits;
+ nbits_in_reservoir -= total_bits;
+ }
+ {
+ const unsigned int *table_a004 = pdev->table_a004 + rows*12;
+ unsigned int *poffset = MulIdx + offset1*16; /* 64/4 (int) */
+ for (i=0;i<16;i++)
+ {
+ temp_colors[i] += table_a004[ *poffset ];
+ poffset++;
+ }
+ }
+ }
+ }
+#define USE_SIGNED_INT_FOR_COLOR
+#ifdef USE_SIGNED_INT_FOR_COLOR
+# define CLAMP(x) ((x)>255?255:((x)<0?0:x))
+#else
+# define CLAMP(x) ((x)>255?255:x)
+#endif
+
+ if (passes == 0)
+ {
+#ifdef USE_SIGNED_INT_FOR_COLOR
+ const int *c = temp_colors;
+#else
+ const unsigned int *c = temp_colors;
+#endif
+ unsigned char *d;
+
+ d = dest_y;
+ for (i=0;i<4;i++,c++)
+ *d++ = CLAMP((*c) >> pdev->yy);
+
+ d = dest_y + bytes_per_channel;
+ for (i=0;i<4;i++,c++)
+ *d++ = CLAMP((*c) >> pdev->yy);
+
+ d = dest_y + offset_to_plane_u;
+ for (i=0;i<4;i++,c++)
+ *d++ = CLAMP((*c) >> pdev->yy);
+
+ d = dest_y + offset_to_plane_v;
+ for (i=0;i<4;i++,c++)
+ *d++ = CLAMP((*c) >> pdev->yy);
+
+ dest_y += 4;
+ }
+ else if (passes == 1)
+ {
+#ifdef USE_SIGNED_INT_FOR_COLOR
+ int *c1 = temp_colors;
+ int *c2 = temp_colors+4;
+#else
+ unsigned int *c1 = temp_colors;
+ unsigned int *c2 = temp_colors+4;
+#endif
+ unsigned char *d;
+
+ d = dest_y;
+ for (i=0;i<4;i++,c1++,c2++)
+ {
+ *d++ = CLAMP((*c1) >> pdev->yy);
+ *d++ = CLAMP((*c2) >> pdev->yy);
+ }
+ c1 = temp_colors+12;
+ //c2 = temp_colors+8;
+ d = dest_y + bytes_per_channel;
+ for (i=0;i<4;i++,c1++,c2++)
+ {
+ *d++ = CLAMP((*c1) >> pdev->yy);
+ *d++ = CLAMP((*c2) >> pdev->yy);
+ }
+
+ if (even_line) /* Each line, swap u/v */
+ {
+ even_line=0;
+ dest_y = dest_v;
+ dest_u += 8;
+ }
+ else
+ {
+ even_line=1;
+ dest_y = dest_u;
+ dest_v += 8;
+ }
+ }
+
+ } /* end of while (nblocks-->0) */
+
+ } /* end of for (passes=0;passes<2;passes++) */
+
+}
+
+
+/**
+ *
+ * image: size of the image wanted
+ * view : size of the image returned by the camera
+ * offset: (x,y) to displayer image in the view
+ *
+ * src: raw data
+ * dst: image output
+ * flags: PWCX_FLAG_PLANAR
+ * pdev: private buffer
+ * bandlength:
+ *
+ */
+void pwc_dec23_decompress(const struct pwc_coord *image,
+ const struct pwc_coord *view,
+ const struct pwc_coord *offset,
+ const void *src,
+ void *dst,
+ int flags,
+ const void *data,
+ int bandlength)
+{
+ const struct pwc_dec23_private *pdev = data;
+ unsigned char *pout, *pout_planar_y=NULL, *pout_planar_u=NULL, *pout_planar_v=NULL;
+ int i,n,stride,pixel_size;
+
+
+ if (flags & PWCX_FLAG_BAYER)
+ {
+ pout = dst + (view->x * offset->y) + offset->x;
+ pixel_size = view->x * 4;
+ }
+ else
+ {
+ n = view->x * view->y;
+
+ /* offset in Y plane */
+ stride = view->x * offset->y;
+ pout_planar_y = dst + stride + offset->x;
+
+ /* offsets in U/V planes */
+ stride = (view->x * offset->y)/4 + offset->x/2;
+ pout_planar_u = dst + n + + stride;
+ pout_planar_v = dst + n + n/4 + stride;
+
+ pixel_size = view->x * 4;
+ }
+
+
+ for (i=0;i<image->y;i+=4)
+ {
+ if (flags & PWCX_FLAG_BAYER)
+ {
+ //TODO:
+ //DecompressBandBayer(pdev,src,pout,image.x,view->x,flags);
+ src += bandlength;
+ pout += pixel_size;
+ }
+ else
+ {
+ DecompressBand23(pdev,src,pout_planar_y,pout_planar_u,pout_planar_v,image->x,view->x,flags);
+ src += bandlength;
+ pout_planar_y += pixel_size;
+ pout_planar_u += view->x;
+ pout_planar_v += view->x;
+ }
+ }
+}
+
+void pwc_dec23_exit(void)
+{
+ /* Do nothing */
+
+}
+
diff --git a/drivers/usb/media/pwc/pwc-dec23.h b/drivers/usb/media/pwc/pwc-dec23.h
new file mode 100644
index 0000000000000..5b2aacdefa6cb
--- /dev/null
+++ b/drivers/usb/media/pwc/pwc-dec23.h
@@ -0,0 +1,58 @@
+/* Linux driver for Philips webcam
+ (C) 2004 Luc Saillard (luc@saillard.org)
+
+ NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+ driver and thus may have bugs that are not present in the original version.
+ Please send bug reports and support requests to <luc@saillard.org>.
+ The decompression routines have been implemented by reverse-engineering the
+ Nemosoft binary pwcx module. Caveat emptor.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the 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 PWC_DEC23_H
+#define PWC_DEC23_H
+
+struct pwc_dec23_private
+{
+ unsigned char xx,yy,zz,zzmask;
+
+ unsigned char table_0004[2*0x4000];
+ unsigned char table_8004[2*0x1000];
+ unsigned int table_a004[256*12];
+
+ unsigned char table_d004[8*256];
+ unsigned int table_d800[256];
+ unsigned int table_dc00[256];
+};
+
+
+void pwc_dec23_init(int type, int release, unsigned char *buffer, void *private_data);
+void pwc_dec23_exit(void);
+void pwc_dec23_decompress(const struct pwc_coord *image,
+ const struct pwc_coord *view,
+ const struct pwc_coord *offset,
+ const void *src,
+ void *dst,
+ int flags,
+ const void *data,
+ int bandlength);
+
+
+
+#endif
+
+
+
diff --git a/drivers/usb/media/pwc/pwc-if.c b/drivers/usb/media/pwc/pwc-if.c
new file mode 100644
index 0000000000000..100a5a4f03a32
--- /dev/null
+++ b/drivers/usb/media/pwc/pwc-if.c
@@ -0,0 +1,2212 @@
+/* Linux driver for Philips webcam
+ USB and Video4Linux interface part.
+ (C) 1999-2004 Nemosoft Unv.
+ (C) 2004 Luc Saillard (luc@saillard.org)
+
+ NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+ driver and thus may have bugs that are not present in the original version.
+ Please send bug reports and support requests to <luc@saillard.org>.
+ The decompression routines have been implemented by reverse-engineering the
+ Nemosoft binary pwcx module. Caveat emptor.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the 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 code forms the interface between the USB layers and the Philips
+ specific stuff. Some adanved stuff of the driver falls under an
+ NDA, signed between me and Philips B.V., Eindhoven, the Netherlands, and
+ is thus not distributed in source form. The binary pwcx.o module
+ contains the code that falls under the NDA.
+
+ In case you're wondering: 'pwc' stands for "Philips WebCam", but
+ I really didn't want to type 'philips_web_cam' every time (I'm lazy as
+ any Linux kernel hacker, but I don't like uncomprehensible abbreviations
+ without explanation).
+
+ Oh yes, convention: to disctinguish between all the various pointers to
+ device-structures, I use these names for the pointer variables:
+ udev: struct usb_device *
+ vdev: struct video_device *
+ pdev: struct pwc_devive *
+*/
+
+/* Contributors:
+ - Alvarado: adding whitebalance code
+ - Alistar Moire: QuickCam 3000 Pro device/product ID
+ - Tony Hoyle: Creative Labs Webcam 5 device/product ID
+ - Mark Burazin: solving hang in VIDIOCSYNC when camera gets unplugged
+ - Jk Fang: Sotec Afina Eye ID
+ - Xavier Roche: QuickCam Pro 4000 ID
+ - Jens Knudsen: QuickCam Zoom ID
+ - J. Debert: QuickCam for Notebooks ID
+*/
+
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/poll.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <asm/io.h>
+
+#include "pwc.h"
+#include "pwc-ioctl.h"
+#include "pwc-kiara.h"
+#include "pwc-timon.h"
+#include "pwc-dec23.h"
+#include "pwc-dec1.h"
+#include "pwc-uncompress.h"
+
+/* Function prototypes and driver templates */
+
+/* hotplug device table support */
+static struct usb_device_id pwc_device_table [] = {
+ { USB_DEVICE(0x0471, 0x0302) }, /* Philips models */
+ { USB_DEVICE(0x0471, 0x0303) },
+ { USB_DEVICE(0x0471, 0x0304) },
+ { USB_DEVICE(0x0471, 0x0307) },
+ { USB_DEVICE(0x0471, 0x0308) },
+ { USB_DEVICE(0x0471, 0x030C) },
+ { USB_DEVICE(0x0471, 0x0310) },
+ { USB_DEVICE(0x0471, 0x0311) },
+ { USB_DEVICE(0x0471, 0x0312) },
+ { USB_DEVICE(0x0471, 0x0313) }, /* the 'new' 720K */
+ { USB_DEVICE(0x069A, 0x0001) }, /* Askey */
+ { USB_DEVICE(0x046D, 0x08B0) }, /* Logitech QuickCam Pro 3000 */
+ { USB_DEVICE(0x046D, 0x08B1) }, /* Logitech QuickCam Notebook Pro */
+ { USB_DEVICE(0x046D, 0x08B2) }, /* Logitech QuickCam Pro 4000 */
+ { USB_DEVICE(0x046D, 0x08B3) }, /* Logitech QuickCam Zoom (old model) */
+ { USB_DEVICE(0x046D, 0x08B4) }, /* Logitech QuickCam Zoom (new model) */
+ { USB_DEVICE(0x046D, 0x08B5) }, /* Logitech QuickCam Orbit/Sphere */
+ { USB_DEVICE(0x046D, 0x08B6) }, /* Logitech (reserved) */
+ { USB_DEVICE(0x046D, 0x08B7) }, /* Logitech (reserved) */
+ { USB_DEVICE(0x046D, 0x08B8) }, /* Logitech (reserved) */
+ { USB_DEVICE(0x055D, 0x9000) }, /* Samsung */
+ { USB_DEVICE(0x055D, 0x9001) },
+ { USB_DEVICE(0x041E, 0x400C) }, /* Creative Webcam 5 */
+ { USB_DEVICE(0x041E, 0x4011) }, /* Creative Webcam Pro Ex */
+ { USB_DEVICE(0x04CC, 0x8116) }, /* Afina Eye */
+ { USB_DEVICE(0x06BE, 0x8116) }, /* new Afina Eye */
+ { USB_DEVICE(0x0d81, 0x1910) }, /* Visionite */
+ { USB_DEVICE(0x0d81, 0x1900) },
+ { }
+};
+MODULE_DEVICE_TABLE(usb, pwc_device_table);
+
+static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id *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() */
+ .disconnect = usb_pwc_disconnect, /* disconnect() */
+};
+
+#define MAX_DEV_HINTS 20
+#define MAX_ISOC_ERRORS 20
+
+static int default_size = PSZ_QCIF;
+static int default_fps = 10;
+static int default_fbufs = 3; /* Default number of frame buffers */
+static int default_mbufs = 2; /* Default number of mmap() buffers */
+ int pwc_trace = TRACE_MODULE | TRACE_FLOW | TRACE_PWCX;
+static int power_save = 0;
+static int led_on = 100, led_off = 0; /* defaults to LED that is on while in use */
+ int pwc_preferred_compression = 2; /* 0..3 = uncompressed..high */
+static struct {
+ int type;
+ char serial_number[30];
+ int device_node;
+ struct pwc_device *pdev;
+} device_hint[MAX_DEV_HINTS];
+
+/***/
+
+static int pwc_video_open(struct inode *inode, struct file *file);
+static int pwc_video_close(struct inode *inode, struct file *file);
+static ssize_t pwc_video_read(struct file *file, char __user * buf,
+ size_t count, loff_t *ppos);
+static unsigned int pwc_video_poll(struct file *file, poll_table *wait);
+static int pwc_video_ioctl(struct inode *inode, struct file *file,
+ unsigned int ioctlnr, unsigned long arg);
+static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma);
+
+static struct file_operations pwc_fops = {
+ .owner = THIS_MODULE,
+ .open = pwc_video_open,
+ .release = pwc_video_close,
+ .read = pwc_video_read,
+ .poll = pwc_video_poll,
+ .mmap = pwc_video_mmap,
+ .ioctl = pwc_video_ioctl,
+ .llseek = no_llseek,
+};
+static struct video_device pwc_template = {
+ .owner = THIS_MODULE,
+ .name = "Philips Webcam", /* Filled in later */
+ .type = VID_TYPE_CAPTURE,
+ .hardware = VID_HARDWARE_PWC,
+ .release = video_device_release,
+ .fops = &pwc_fops,
+ .minor = -1,
+};
+
+/***************************************************************************/
+
+/* Okay, this is some magic that I worked out and the reasoning behind it...
+
+ The biggest problem with any USB device is of course: "what to do
+ when the user unplugs the device while it is in use by an application?"
+ We have several options:
+ 1) Curse them with the 7 plagues when they do (requires divine intervention)
+ 2) Tell them not to (won't work: they'll do it anyway)
+ 3) Oops the kernel (this will have a negative effect on a user's uptime)
+ 4) Do something sensible.
+
+ Of course, we go for option 4.
+
+ It happens that this device will be linked to two times, once from
+ usb_device and once from the video_device in their respective 'private'
+ pointers. This is done when the device is probed() and all initialization
+ succeeded. The pwc_device struct links back to both structures.
+
+ When a device is unplugged while in use it will be removed from the
+ list of known USB devices; I also de-register it as a V4L device, but
+ unfortunately I can't free the memory since the struct is still in use
+ by the file descriptor. This free-ing is then deferend until the first
+ opportunity. Crude, but it works.
+
+ A small 'advantage' is that if a user unplugs the cam and plugs it back
+ in, it should get assigned the same video device minor, but unfortunately
+ it's non-trivial to re-link the cam back to the video device... (that
+ would surely be magic! :))
+*/
+
+/***************************************************************************/
+/* Private functions */
+
+/* Here we want the physical address of the memory.
+ * This is used when initializing the contents of the area.
+ */
+static inline unsigned long kvirt_to_pa(unsigned long adr)
+{
+ unsigned long kva, ret;
+
+ kva = (unsigned long) page_address(vmalloc_to_page((void *)adr));
+ kva |= adr & (PAGE_SIZE-1); /* restore the offset */
+ ret = __pa(kva);
+ return ret;
+}
+
+static void * rvmalloc(unsigned long size)
+{
+ void * mem;
+ unsigned long adr;
+
+ size=PAGE_ALIGN(size);
+ mem=vmalloc_32(size);
+ if (mem)
+ {
+ memset(mem, 0, size); /* Clear the ram out, no junk to the user */
+ adr=(unsigned long) mem;
+ while (size > 0)
+ {
+ SetPageReserved(vmalloc_to_page((void *)adr));
+ adr+=PAGE_SIZE;
+ size-=PAGE_SIZE;
+ }
+ }
+ return mem;
+}
+
+static void rvfree(void * mem, unsigned long size)
+{
+ unsigned long adr;
+
+ if (mem)
+ {
+ adr=(unsigned long) mem;
+ while ((long) size > 0)
+ {
+ ClearPageReserved(vmalloc_to_page((void *)adr));
+ adr+=PAGE_SIZE;
+ size-=PAGE_SIZE;
+ }
+ vfree(mem);
+ }
+}
+
+
+
+
+static int pwc_allocate_buffers(struct pwc_device *pdev)
+{
+ int i;
+ void *kbuf;
+
+ Trace(TRACE_MEMORY, ">> pwc_allocate_buffers(pdev = 0x%p)\n", pdev);
+
+ if (pdev == NULL)
+ return -ENXIO;
+
+#ifdef PWC_MAGIC
+ if (pdev->magic != PWC_MAGIC) {
+ Err("allocate_buffers(): magic failed.\n");
+ return -ENXIO;
+ }
+#endif
+ /* Allocate Isochronuous pipe buffers */
+ for (i = 0; i < MAX_ISO_BUFS; i++) {
+ if (pdev->sbuf[i].data == NULL) {
+ kbuf = kmalloc(ISO_BUFFER_SIZE, GFP_KERNEL);
+ if (kbuf == NULL) {
+ Err("Failed to allocate iso buffer %d.\n", i);
+ return -ENOMEM;
+ }
+ Trace(TRACE_MEMORY, "Allocated iso buffer at %p.\n", kbuf);
+ pdev->sbuf[i].data = kbuf;
+ memset(kbuf, 0, ISO_BUFFER_SIZE);
+ }
+ }
+
+ /* Allocate frame buffer structure */
+ if (pdev->fbuf == NULL) {
+ kbuf = kmalloc(default_fbufs * sizeof(struct pwc_frame_buf), GFP_KERNEL);
+ if (kbuf == NULL) {
+ Err("Failed to allocate frame buffer structure.\n");
+ return -ENOMEM;
+ }
+ Trace(TRACE_MEMORY, "Allocated frame buffer structure at %p.\n", kbuf);
+ pdev->fbuf = kbuf;
+ memset(kbuf, 0, default_fbufs * sizeof(struct pwc_frame_buf));
+ }
+ /* create frame buffers, and make circular ring */
+ for (i = 0; i < default_fbufs; i++) {
+ if (pdev->fbuf[i].data == NULL) {
+ kbuf = vmalloc(PWC_FRAME_SIZE); /* need vmalloc since frame buffer > 128K */
+ if (kbuf == NULL) {
+ Err("Failed to allocate frame buffer %d.\n", i);
+ return -ENOMEM;
+ }
+ Trace(TRACE_MEMORY, "Allocated frame buffer %d at %p.\n", i, kbuf);
+ pdev->fbuf[i].data = kbuf;
+ memset(kbuf, 128, PWC_FRAME_SIZE);
+ }
+ }
+
+ /* Allocate decompressor table space */
+ kbuf = NULL;
+ switch (pdev->type)
+ {
+ case 675:
+ case 680:
+ case 690:
+ case 720:
+ case 730:
+ case 740:
+ case 750:
+ Trace(TRACE_MEMORY,"private_data(%Zd)\n",sizeof(struct pwc_dec23_private));
+ kbuf = kmalloc(sizeof(struct pwc_dec23_private), GFP_KERNEL); /* Timon & Kiara */
+ break;
+ case 645:
+ case 646:
+ /* TODO & FIXME */
+ kbuf = kmalloc(sizeof(struct pwc_dec23_private), GFP_KERNEL);
+ break;
+ }
+ if (kbuf == NULL) {
+ Err("Failed to allocate decompress table.\n");
+ return -ENOMEM;
+ }
+ pdev->decompress_data = kbuf;
+
+ /* Allocate image buffer; double buffer for mmap() */
+ kbuf = rvmalloc(default_mbufs * pdev->len_per_image);
+ if (kbuf == NULL) {
+ Err("Failed to allocate image buffer(s). needed (%d)\n",default_mbufs * pdev->len_per_image);
+ return -ENOMEM;
+ }
+ Trace(TRACE_MEMORY, "Allocated image buffer at %p.\n", kbuf);
+ pdev->image_data = kbuf;
+ for (i = 0; i < default_mbufs; i++)
+ pdev->image_ptr[i] = kbuf + i * pdev->len_per_image;
+ for (; i < MAX_IMAGES; i++)
+ pdev->image_ptr[i] = NULL;
+
+ kbuf = NULL;
+
+ Trace(TRACE_MEMORY, "<< pwc_allocate_buffers()\n");
+ return 0;
+}
+
+static void pwc_free_buffers(struct pwc_device *pdev)
+{
+ int i;
+
+ Trace(TRACE_MEMORY, "Entering free_buffers(%p).\n", pdev);
+
+ if (pdev == NULL)
+ return;
+#ifdef PWC_MAGIC
+ if (pdev->magic != PWC_MAGIC) {
+ Err("free_buffers(): magic failed.\n");
+ return;
+ }
+#endif
+
+ /* Release Iso-pipe buffers */
+ for (i = 0; i < MAX_ISO_BUFS; i++)
+ if (pdev->sbuf[i].data != NULL) {
+ Trace(TRACE_MEMORY, "Freeing ISO buffer at %p.\n", pdev->sbuf[i].data);
+ kfree(pdev->sbuf[i].data);
+ pdev->sbuf[i].data = NULL;
+ }
+
+ /* The same for frame buffers */
+ if (pdev->fbuf != NULL) {
+ for (i = 0; i < default_fbufs; i++) {
+ if (pdev->fbuf[i].data != NULL) {
+ Trace(TRACE_MEMORY, "Freeing frame buffer %d at %p.\n", i, pdev->fbuf[i].data);
+ vfree(pdev->fbuf[i].data);
+ pdev->fbuf[i].data = NULL;
+ }
+ }
+ kfree(pdev->fbuf);
+ pdev->fbuf = NULL;
+ }
+
+ /* Intermediate decompression buffer & tables */
+ if (pdev->decompress_data != NULL) {
+ Trace(TRACE_MEMORY, "Freeing decompression buffer at %p.\n", pdev->decompress_data);
+ kfree(pdev->decompress_data);
+ pdev->decompress_data = NULL;
+ }
+ pdev->decompressor = NULL;
+
+ /* Release image buffers */
+ if (pdev->image_data != NULL) {
+ Trace(TRACE_MEMORY, "Freeing image buffer at %p.\n", pdev->image_data);
+ rvfree(pdev->image_data, default_mbufs * pdev->len_per_image);
+ }
+ pdev->image_data = NULL;
+
+ Trace(TRACE_MEMORY, "Leaving free_buffers().\n");
+}
+
+/* The frame & image buffer mess.
+
+ Yes, this is a mess. Well, it used to be simple, but alas... In this
+ module, 3 buffers schemes are used to get the data from the USB bus to
+ the user program. The first scheme involves the ISO buffers (called thus
+ since they transport ISO data from the USB controller), and not really
+ interesting. Suffices to say the data from this buffer is quickly
+ gathered in an interrupt handler (pwc_isoc_handler) and placed into the
+ frame buffer.
+
+ The frame buffer is the second scheme, and is the central element here.
+ It collects the data from a single frame from the camera (hence, the
+ name). Frames are delimited by the USB camera with a short USB packet,
+ so that's easy to detect. The frame buffers form a list that is filled
+ by the camera+USB controller and drained by the user process through
+ either read() or mmap().
+
+ The image buffer is the third scheme, in which frames are decompressed
+ and converted into planar format. For mmap() there is more than
+ one image buffer available.
+
+ The frame buffers provide the image buffering. In case the user process
+ is a bit slow, this introduces lag and some undesired side-effects.
+ The problem arises when the frame buffer is full. I used to drop the last
+ frame, which makes the data in the queue stale very quickly. But dropping
+ the frame at the head of the queue proved to be a litte bit more difficult.
+ I tried a circular linked scheme, but this introduced more problems than
+ it solved.
+
+ Because filling and draining are completely asynchronous processes, this
+ requires some fiddling with pointers and mutexes.
+
+ Eventually, I came up with a system with 2 lists: an 'empty' frame list
+ and a 'full' frame list:
+ * Initially, all frame buffers but one are on the 'empty' list; the one
+ remaining buffer is our initial fill frame.
+ * If a frame is needed for filling, we try to take it from the 'empty'
+ list, unless that list is empty, in which case we take the buffer at
+ the head of the 'full' list.
+ * When our fill buffer has been filled, it is appended to the 'full'
+ list.
+ * If a frame is needed by read() or mmap(), it is taken from the head of
+ the 'full' list, handled, and then appended to the 'empty' list. If no
+ buffer is present on the 'full' list, we wait.
+ The advantage is that the buffer that is currently being decompressed/
+ converted, is on neither list, and thus not in our way (any other scheme
+ I tried had the problem of old data lingering in the queue).
+
+ Whatever strategy you choose, it always remains a tradeoff: with more
+ frame buffers the chances of a missed frame are reduced. On the other
+ hand, on slower machines it introduces lag because the queue will
+ always be full.
+ */
+
+/**
+ \brief Find next frame buffer to fill. Take from empty or full list, whichever comes first.
+ */
+static inline int pwc_next_fill_frame(struct pwc_device *pdev)
+{
+ int ret;
+ unsigned long flags;
+
+ ret = 0;
+ spin_lock_irqsave(&pdev->ptrlock, flags);
+ if (pdev->fill_frame != NULL) {
+ /* append to 'full' list */
+ if (pdev->full_frames == NULL) {
+ pdev->full_frames = pdev->fill_frame;
+ pdev->full_frames_tail = pdev->full_frames;
+ }
+ else {
+ pdev->full_frames_tail->next = pdev->fill_frame;
+ pdev->full_frames_tail = pdev->fill_frame;
+ }
+ }
+ if (pdev->empty_frames != NULL) {
+ /* We have empty frames available. That's easy */
+ pdev->fill_frame = pdev->empty_frames;
+ pdev->empty_frames = pdev->empty_frames->next;
+ }
+ else {
+ /* Hmm. Take it from the full list */
+#if PWC_DEBUG
+ /* sanity check */
+ if (pdev->full_frames == NULL) {
+ Err("Neither empty or full frames available!\n");
+ spin_unlock_irqrestore(&pdev->ptrlock, flags);
+ return -EINVAL;
+ }
+#endif
+ pdev->fill_frame = pdev->full_frames;
+ pdev->full_frames = pdev->full_frames->next;
+ ret = 1;
+ }
+ pdev->fill_frame->next = NULL;
+#if PWC_DEBUG
+ Trace(TRACE_SEQUENCE, "Assigning sequence number %d.\n", pdev->sequence);
+ pdev->fill_frame->sequence = pdev->sequence++;
+#endif
+ spin_unlock_irqrestore(&pdev->ptrlock, flags);
+ return ret;
+}
+
+
+/**
+ \brief Reset all buffers, pointers and lists, except for the image_used[] buffer.
+
+ If the image_used[] buffer is cleared too, mmap()/VIDIOCSYNC will run into trouble.
+ */
+static void pwc_reset_buffers(struct pwc_device *pdev)
+{
+ int i;
+ unsigned long flags;
+
+ spin_lock_irqsave(&pdev->ptrlock, flags);
+ pdev->full_frames = NULL;
+ pdev->full_frames_tail = NULL;
+ for (i = 0; i < default_fbufs; i++) {
+ pdev->fbuf[i].filled = 0;
+ if (i > 0)
+ pdev->fbuf[i].next = &pdev->fbuf[i - 1];
+ else
+ pdev->fbuf->next = NULL;
+ }
+ pdev->empty_frames = &pdev->fbuf[default_fbufs - 1];
+ pdev->empty_frames_tail = pdev->fbuf;
+ pdev->read_frame = NULL;
+ pdev->fill_frame = pdev->empty_frames;
+ pdev->empty_frames = pdev->empty_frames->next;
+
+ pdev->image_read_pos = 0;
+ pdev->fill_image = 0;
+ spin_unlock_irqrestore(&pdev->ptrlock, flags);
+}
+
+
+/**
+ \brief Do all the handling for getting one frame: get pointer, decompress, advance pointers.
+ */
+static int pwc_handle_frame(struct pwc_device *pdev)
+{
+ int ret = 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&pdev->ptrlock, flags);
+ /* First grab our read_frame; this is removed from all lists, so
+ we can release the lock after this without problems */
+ if (pdev->read_frame != NULL) {
+ /* This can't theoretically happen */
+ Err("Huh? Read frame still in use?\n");
+ }
+ else {
+ if (pdev->full_frames == NULL) {
+ Err("Woops. No frames ready.\n");
+ }
+ else {
+ pdev->read_frame = pdev->full_frames;
+ pdev->full_frames = pdev->full_frames->next;
+ pdev->read_frame->next = NULL;
+ }
+
+ if (pdev->read_frame != NULL) {
+#if PWC_DEBUG
+ Trace(TRACE_SEQUENCE, "Decompressing frame %d\n", pdev->read_frame->sequence);
+#endif
+ /* Decompression is a lenghty process, so it's outside of the lock.
+ This gives the isoc_handler the opportunity to fill more frames
+ in the mean time.
+ */
+ spin_unlock_irqrestore(&pdev->ptrlock, flags);
+ ret = pwc_decompress(pdev);
+ spin_lock_irqsave(&pdev->ptrlock, flags);
+
+ /* We're done with read_buffer, tack it to the end of the empty buffer list */
+ if (pdev->empty_frames == NULL) {
+ pdev->empty_frames = pdev->read_frame;
+ pdev->empty_frames_tail = pdev->empty_frames;
+ }
+ else {
+ pdev->empty_frames_tail->next = pdev->read_frame;
+ pdev->empty_frames_tail = pdev->read_frame;
+ }
+ pdev->read_frame = NULL;
+ }
+ }
+ spin_unlock_irqrestore(&pdev->ptrlock, flags);
+ return ret;
+}
+
+/**
+ \brief Advance pointers of image buffer (after each user request)
+*/
+static inline void pwc_next_image(struct pwc_device *pdev)
+{
+ pdev->image_used[pdev->fill_image] = 0;
+ pdev->fill_image = (pdev->fill_image + 1) % default_mbufs;
+}
+
+
+/* This gets called for the Isochronous pipe (video). This is done in
+ * interrupt time, so it has to be fast, not crash, and not stall. Neat.
+ */
+static void pwc_isoc_handler(struct urb *urb, struct pt_regs *regs)
+{
+ struct pwc_device *pdev;
+ int i, fst, flen;
+ int awake;
+ struct pwc_frame_buf *fbuf;
+ unsigned char *fillptr = NULL, *iso_buf = NULL;
+
+ awake = 0;
+ pdev = (struct pwc_device *)urb->context;
+ if (pdev == NULL) {
+ Err("isoc_handler() called with NULL device?!\n");
+ return;
+ }
+#ifdef PWC_MAGIC
+ if (pdev->magic != PWC_MAGIC) {
+ Err("isoc_handler() called with bad magic!\n");
+ return;
+ }
+#endif
+ if (urb->status == -ENOENT || urb->status == -ECONNRESET) {
+ Trace(TRACE_OPEN, "pwc_isoc_handler(): URB (%p) unlinked %ssynchronuously.\n", urb, urb->status == -ENOENT ? "" : "a");
+ return;
+ }
+ if (urb->status != -EINPROGRESS && urb->status != 0) {
+ const char *errmsg;
+
+ errmsg = "Unknown";
+ switch(urb->status) {
+ case -ENOSR: errmsg = "Buffer error (overrun)"; break;
+ case -EPIPE: errmsg = "Stalled (device not responding)"; break;
+ case -EOVERFLOW: errmsg = "Babble (bad cable?)"; break;
+ case -EPROTO: errmsg = "Bit-stuff error (bad cable?)"; break;
+ case -EILSEQ: errmsg = "CRC/Timeout (could be anything)"; break;
+ case -ETIMEDOUT: errmsg = "NAK (device does not respond)"; break;
+ }
+ Trace(TRACE_FLOW, "pwc_isoc_handler() called with status %d [%s].\n", urb->status, errmsg);
+ /* Give up after a number of contiguous errors on the USB bus.
+ Appearantly something is wrong so we simulate an unplug event.
+ */
+ if (++pdev->visoc_errors > MAX_ISOC_ERRORS)
+ {
+ Info("Too many ISOC errors, bailing out.\n");
+ pdev->error_status = EIO;
+ awake = 1;
+ wake_up_interruptible(&pdev->frameq);
+ }
+ goto handler_end; // ugly, but practical
+ }
+
+ fbuf = pdev->fill_frame;
+ if (fbuf == NULL) {
+ Err("pwc_isoc_handler without valid fill frame.\n");
+ awake = 1;
+ goto handler_end;
+ }
+ else {
+ fillptr = fbuf->data + fbuf->filled;
+ }
+
+ /* Reset ISOC error counter. We did get here, after all. */
+ pdev->visoc_errors = 0;
+
+ /* vsync: 0 = don't copy data
+ 1 = sync-hunt
+ 2 = synched
+ */
+ /* Compact data */
+ for (i = 0; i < urb->number_of_packets; i++) {
+ fst = urb->iso_frame_desc[i].status;
+ flen = urb->iso_frame_desc[i].actual_length;
+ iso_buf = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
+ if (fst == 0) {
+ if (flen > 0) { /* if valid data... */
+ if (pdev->vsync > 0) { /* ...and we are not sync-hunting... */
+ pdev->vsync = 2;
+
+ /* ...copy data to frame buffer, if possible */
+ if (flen + fbuf->filled > pdev->frame_total_size) {
+ Trace(TRACE_FLOW, "Frame buffer overflow (flen = %d, frame_total_size = %d).\n", flen, pdev->frame_total_size);
+ pdev->vsync = 0; /* Hmm, let's wait for an EOF (end-of-frame) */
+ pdev->vframes_error++;
+ }
+ else {
+ memmove(fillptr, iso_buf, flen);
+ fillptr += flen;
+ }
+ }
+ fbuf->filled += flen;
+ } /* ..flen > 0 */
+
+ if (flen < pdev->vlast_packet_size) {
+ /* Shorter packet... We probably have the end of an image-frame;
+ wake up read() process and let select()/poll() do something.
+ Decompression is done in user time over there.
+ */
+ if (pdev->vsync == 2) {
+ /* The ToUCam Fun CMOS sensor causes the firmware to send 2 or 3 bogus
+ frames on the USB wire after an exposure change. This conditition is
+ however detected in the cam and a bit is set in the header.
+ */
+ if (pdev->type == 730) {
+ unsigned char *ptr = (unsigned char *)fbuf->data;
+
+ if (ptr[1] == 1 && ptr[0] & 0x10) {
+#if PWC_DEBUG
+ Debug("Hyundai CMOS sensor bug. Dropping frame %d.\n", fbuf->sequence);
+#endif
+ pdev->drop_frames += 2;
+ pdev->vframes_error++;
+ }
+ if ((ptr[0] ^ pdev->vmirror) & 0x01) {
+ if (ptr[0] & 0x01)
+ Info("Snapshot button pressed.\n");
+ else
+ Info("Snapshot button released.\n");
+ }
+ if ((ptr[0] ^ pdev->vmirror) & 0x02) {
+ if (ptr[0] & 0x02)
+ Info("Image is mirrored.\n");
+ else
+ Info("Image is normal.\n");
+ }
+ pdev->vmirror = ptr[0] & 0x03;
+ /* Sometimes the trailer of the 730 is still sent as a 4 byte packet
+ after a short frame; this condition is filtered out specifically. A 4 byte
+ frame doesn't make sense anyway.
+ So we get either this sequence:
+ drop_bit set -> 4 byte frame -> short frame -> good frame
+ Or this one:
+ drop_bit set -> short frame -> good frame
+ So we drop either 3 or 2 frames in all!
+ */
+ if (fbuf->filled == 4)
+ pdev->drop_frames++;
+ }
+
+ /* In case we were instructed to drop the frame, do so silently.
+ The buffer pointers are not updated either (but the counters are reset below).
+ */
+ if (pdev->drop_frames > 0)
+ pdev->drop_frames--;
+ else {
+ /* Check for underflow first */
+ if (fbuf->filled < pdev->frame_total_size) {
+ Trace(TRACE_FLOW, "Frame buffer underflow (%d bytes); discarded.\n", fbuf->filled);
+ pdev->vframes_error++;
+ }
+ else {
+ /* Send only once per EOF */
+ awake = 1; /* delay wake_ups */
+
+ /* Find our next frame to fill. This will always succeed, since we
+ * nick a frame from either empty or full list, but if we had to
+ * take it from the full list, it means a frame got dropped.
+ */
+ if (pwc_next_fill_frame(pdev)) {
+ pdev->vframes_dumped++;
+ if ((pdev->vframe_count > FRAME_LOWMARK) && (pwc_trace & TRACE_FLOW)) {
+ if (pdev->vframes_dumped < 20)
+ Trace(TRACE_FLOW, "Dumping frame %d.\n", pdev->vframe_count);
+ if (pdev->vframes_dumped == 20)
+ Trace(TRACE_FLOW, "Dumping frame %d (last message).\n", pdev->vframe_count);
+ }
+ }
+ fbuf = pdev->fill_frame;
+ }
+ } /* !drop_frames */
+ pdev->vframe_count++;
+ }
+ fbuf->filled = 0;
+ fillptr = fbuf->data;
+ pdev->vsync = 1;
+ } /* .. flen < last_packet_size */
+ pdev->vlast_packet_size = flen;
+ } /* ..status == 0 */
+#if PWC_DEBUG
+ /* This is normally not interesting to the user, unless you are really debugging something */
+ else {
+ static int iso_error = 0;
+ iso_error++;
+ if (iso_error < 20)
+ Trace(TRACE_FLOW, "Iso frame %d of USB has error %d\n", i, fst);
+ }
+#endif
+ }
+
+handler_end:
+ if (awake)
+ wake_up_interruptible(&pdev->frameq);
+
+ urb->dev = pdev->udev;
+ i = usb_submit_urb(urb, GFP_ATOMIC);
+ if (i != 0)
+ Err("Error (%d) re-submitting urb in pwc_isoc_handler.\n", i);
+}
+
+
+static int pwc_isoc_init(struct pwc_device *pdev)
+{
+ struct usb_device *udev;
+ struct urb *urb;
+ int i, j, ret;
+
+ struct usb_interface *intf;
+ struct usb_host_interface *idesc = NULL;
+
+ if (pdev == NULL)
+ return -EFAULT;
+ if (pdev->iso_init)
+ return 0;
+ pdev->vsync = 0;
+ udev = pdev->udev;
+
+ /* Get the current alternate interface, adjust packet size */
+ if (!udev->actconfig)
+ return -EFAULT;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,5)
+ idesc = &udev->actconfig->interface[0]->altsetting[pdev->valternate];
+#else
+ intf = usb_ifnum_to_if(udev, 0);
+ if (intf)
+ idesc = usb_altnum_to_altsetting(intf, pdev->valternate);
+#endif
+
+ if (!idesc)
+ return -EFAULT;
+
+ /* Search video endpoint */
+ pdev->vmax_packet_size = -1;
+ for (i = 0; i < idesc->desc.bNumEndpoints; i++)
+ if ((idesc->endpoint[i].desc.bEndpointAddress & 0xF) == pdev->vendpoint) {
+ pdev->vmax_packet_size = le16_to_cpu(idesc->endpoint[i].desc.wMaxPacketSize);
+ break;
+ }
+
+ if (pdev->vmax_packet_size < 0 || pdev->vmax_packet_size > ISO_MAX_FRAME_SIZE) {
+ Err("Failed to find packet size for video endpoint in current alternate setting.\n");
+ return -ENFILE; /* Odd error, that should be noticable */
+ }
+
+ /* Set alternate interface */
+ ret = 0;
+ Trace(TRACE_OPEN, "Setting alternate interface %d\n", pdev->valternate);
+ ret = usb_set_interface(pdev->udev, 0, pdev->valternate);
+ if (ret < 0)
+ return ret;
+
+ for (i = 0; i < MAX_ISO_BUFS; i++) {
+ urb = usb_alloc_urb(ISO_FRAMES_PER_DESC, GFP_KERNEL);
+ if (urb == NULL) {
+ Err("Failed to allocate urb %d\n", i);
+ ret = -ENOMEM;
+ break;
+ }
+ pdev->sbuf[i].urb = urb;
+ Trace(TRACE_MEMORY, "Allocated URB at 0x%p\n", urb);
+ }
+ if (ret) {
+ /* De-allocate in reverse order */
+ while (i >= 0) {
+ if (pdev->sbuf[i].urb != NULL)
+ usb_free_urb(pdev->sbuf[i].urb);
+ pdev->sbuf[i].urb = NULL;
+ i--;
+ }
+ return ret;
+ }
+
+ /* init URB structure */
+ for (i = 0; i < MAX_ISO_BUFS; i++) {
+ urb = pdev->sbuf[i].urb;
+
+ urb->interval = 1; // devik
+ urb->dev = udev;
+ urb->pipe = usb_rcvisocpipe(udev, pdev->vendpoint);
+ urb->transfer_flags = URB_ISO_ASAP;
+ urb->transfer_buffer = pdev->sbuf[i].data;
+ urb->transfer_buffer_length = ISO_BUFFER_SIZE;
+ urb->complete = pwc_isoc_handler;
+ urb->context = pdev;
+ urb->start_frame = 0;
+ urb->number_of_packets = ISO_FRAMES_PER_DESC;
+ for (j = 0; j < ISO_FRAMES_PER_DESC; j++) {
+ urb->iso_frame_desc[j].offset = j * ISO_MAX_FRAME_SIZE;
+ urb->iso_frame_desc[j].length = pdev->vmax_packet_size;
+ }
+ }
+
+ /* link */
+ for (i = 0; i < MAX_ISO_BUFS; i++) {
+ ret = usb_submit_urb(pdev->sbuf[i].urb, GFP_KERNEL);
+ if (ret)
+ Err("isoc_init() submit_urb %d failed with error %d\n", i, ret);
+ else
+ Trace(TRACE_MEMORY, "URB 0x%p submitted.\n", pdev->sbuf[i].urb);
+ }
+
+ /* All is done... */
+ pdev->iso_init = 1;
+ Trace(TRACE_OPEN, "<< pwc_isoc_init()\n");
+ return 0;
+}
+
+static void pwc_isoc_cleanup(struct pwc_device *pdev)
+{
+ int i;
+
+ Trace(TRACE_OPEN, ">> pwc_isoc_cleanup()\n");
+ if (pdev == NULL)
+ return;
+
+ /* Unlinking ISOC buffers one by one */
+ for (i = 0; i < MAX_ISO_BUFS; i++) {
+ struct urb *urb;
+
+ urb = pdev->sbuf[i].urb;
+ if (urb != 0) {
+ if (pdev->iso_init) {
+ Trace(TRACE_MEMORY, "Unlinking URB %p\n", urb);
+ usb_kill_urb(urb);
+ }
+ Trace(TRACE_MEMORY, "Freeing URB\n");
+ usb_free_urb(urb);
+ pdev->sbuf[i].urb = NULL;
+ }
+ }
+
+ /* Stop camera, but only if we are sure the camera is still there (unplug
+ is signalled by EPIPE)
+ */
+ if (pdev->error_status && pdev->error_status != EPIPE) {
+ Trace(TRACE_OPEN, "Setting alternate interface 0.\n");
+ usb_set_interface(pdev->udev, 0, 0);
+ }
+
+ pdev->iso_init = 0;
+ Trace(TRACE_OPEN, "<< pwc_isoc_cleanup()\n");
+}
+
+int pwc_try_video_mode(struct pwc_device *pdev, int width, int height, int new_fps, int new_compression, int new_snapshot)
+{
+ int ret, start;
+
+ /* Stop isoc stuff */
+ pwc_isoc_cleanup(pdev);
+ /* Reset parameters */
+ pwc_reset_buffers(pdev);
+ /* Try to set video mode... */
+ start = ret = pwc_set_video_mode(pdev, width, height, new_fps, new_compression, new_snapshot);
+ if (ret) {
+ Trace(TRACE_FLOW, "pwc_set_video_mode attempt 1 failed.\n");
+ /* That failed... restore old mode (we know that worked) */
+ start = pwc_set_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, pdev->vcompression, pdev->vsnapshot);
+ if (start) {
+ Trace(TRACE_FLOW, "pwc_set_video_mode attempt 2 failed.\n");
+ }
+ }
+ if (start == 0)
+ {
+ if (pwc_isoc_init(pdev) < 0)
+ {
+ Info("Failed to restart ISOC transfers in pwc_try_video_mode.\n");
+ ret = -EAGAIN; /* let's try again, who knows if it works a second time */
+ }
+ }
+ pdev->drop_frames++; /* try to avoid garbage during switch */
+ return ret; /* Return original error code */
+}
+
+
+/***************************************************************************/
+/* Video4Linux functions */
+
+static int pwc_video_open(struct inode *inode, struct file *file)
+{
+ int i;
+ struct video_device *vdev = video_devdata(file);
+ struct pwc_device *pdev;
+
+ Trace(TRACE_OPEN, ">> video_open called(vdev = 0x%p).\n", vdev);
+
+ pdev = (struct pwc_device *)vdev->priv;
+ if (pdev == NULL)
+ BUG();
+ if (pdev->vopen)
+ return -EBUSY;
+
+ down(&pdev->modlock);
+ if (!pdev->usb_init) {
+ Trace(TRACE_OPEN, "Doing first time initialization.\n");
+ pdev->usb_init = 1;
+
+ if (pwc_trace & TRACE_OPEN)
+ {
+ /* Query sensor type */
+ const char *sensor_type = NULL;
+ int ret;
+
+ ret = pwc_get_cmos_sensor(pdev, &i);
+ if (ret >= 0)
+ {
+ switch(i) {
+ case 0x00: sensor_type = "Hyundai CMOS sensor"; break;
+ case 0x20: sensor_type = "Sony CCD sensor + TDA8787"; break;
+ case 0x2E: sensor_type = "Sony CCD sensor + Exas 98L59"; break;
+ case 0x2F: sensor_type = "Sony CCD sensor + ADI 9804"; break;
+ case 0x30: sensor_type = "Sharp CCD sensor + TDA8787"; break;
+ case 0x3E: sensor_type = "Sharp CCD sensor + Exas 98L59"; break;
+ case 0x3F: sensor_type = "Sharp CCD sensor + ADI 9804"; break;
+ case 0x40: sensor_type = "UPA 1021 sensor"; break;
+ case 0x100: sensor_type = "VGA sensor"; break;
+ case 0x101: sensor_type = "PAL MR sensor"; break;
+ default: sensor_type = "unknown type of sensor"; break;
+ }
+ }
+ if (sensor_type != NULL)
+ Info("This %s camera is equipped with a %s (%d).\n", pdev->vdev->name, sensor_type, i);
+ }
+ }
+
+ /* Turn on camera */
+ if (power_save) {
+ i = pwc_camera_power(pdev, 1);
+ if (i < 0)
+ Info("Failed to restore power to the camera! (%d)\n", i);
+ }
+ /* Set LED on/off time */
+ if (pwc_set_leds(pdev, led_on, led_off) < 0)
+ Info("Failed to set LED on/off time.\n");
+
+ pwc_construct(pdev); /* set min/max sizes correct */
+
+ /* So far, so good. Allocate memory. */
+ i = pwc_allocate_buffers(pdev);
+ if (i < 0) {
+ Trace(TRACE_OPEN, "Failed to allocate buffer memory.\n");
+ up(&pdev->modlock);
+ return i;
+ }
+
+ /* Reset buffers & parameters */
+ pwc_reset_buffers(pdev);
+ for (i = 0; i < default_mbufs; i++)
+ pdev->image_used[i] = 0;
+ pdev->vframe_count = 0;
+ pdev->vframes_dumped = 0;
+ pdev->vframes_error = 0;
+ pdev->visoc_errors = 0;
+ pdev->error_status = 0;
+#if PWC_DEBUG
+ pdev->sequence = 0;
+#endif
+ pwc_construct(pdev); /* set min/max sizes correct */
+
+ /* Set some defaults */
+ pdev->vsnapshot = 0;
+
+ /* Start iso pipe for video; first try the last used video size
+ (or the default one); if that fails try QCIF/10 or QSIF/10;
+ it that fails too, give up.
+ */
+ i = pwc_set_video_mode(pdev, pwc_image_sizes[pdev->vsize].x, pwc_image_sizes[pdev->vsize].y, pdev->vframes, pdev->vcompression, 0);
+ if (i) {
+ Trace(TRACE_OPEN, "First attempt at set_video_mode failed.\n");
+ if (pdev->type == 730 || pdev->type == 740 || pdev->type == 750)
+ i = pwc_set_video_mode(pdev, pwc_image_sizes[PSZ_QSIF].x, pwc_image_sizes[PSZ_QSIF].y, 10, pdev->vcompression, 0);
+ else
+ i = pwc_set_video_mode(pdev, pwc_image_sizes[PSZ_QCIF].x, pwc_image_sizes[PSZ_QCIF].y, 10, pdev->vcompression, 0);
+ }
+ if (i) {
+ Trace(TRACE_OPEN, "Second attempt at set_video_mode failed.\n");
+ up(&pdev->modlock);
+ return i;
+ }
+
+ i = pwc_isoc_init(pdev);
+ if (i) {
+ Trace(TRACE_OPEN, "Failed to init ISOC stuff = %d.\n", i);
+ up(&pdev->modlock);
+ return i;
+ }
+
+ pdev->vopen++;
+ file->private_data = vdev;
+ up(&pdev->modlock);
+ Trace(TRACE_OPEN, "<< video_open() returns 0.\n");
+ return 0;
+}
+
+/* Note that all cleanup is done in the reverse order as in _open */
+static int pwc_video_close(struct inode *inode, struct file *file)
+{
+ struct video_device *vdev = file->private_data;
+ struct pwc_device *pdev;
+ int i;
+
+ Trace(TRACE_OPEN, ">> video_close called(vdev = 0x%p).\n", vdev);
+
+ pdev = (struct pwc_device *)vdev->priv;
+ if (pdev->vopen == 0)
+ Info("video_close() called on closed device?\n");
+
+ /* Dump statistics, but only if a reasonable amount of frames were
+ processed (to prevent endless log-entries in case of snap-shot
+ programs)
+ */
+ if (pdev->vframe_count > 20)
+ Info("Closing video device: %d frames received, dumped %d frames, %d frames with errors.\n", pdev->vframe_count, pdev->vframes_dumped, pdev->vframes_error);
+
+ switch (pdev->type)
+ {
+ case 675:
+ case 680:
+ case 690:
+ case 720:
+ case 730:
+ case 740:
+ case 750:
+ pwc_dec23_exit(); /* Timon & Kiara */
+ break;
+ case 645:
+ case 646:
+ pwc_dec1_exit();
+ break;
+ }
+
+ pwc_isoc_cleanup(pdev);
+ pwc_free_buffers(pdev);
+
+ /* Turn off LEDS and power down camera, but only when not unplugged */
+ if (pdev->error_status != EPIPE) {
+ /* Turn LEDs off */
+ if (pwc_set_leds(pdev, 0, 0) < 0)
+ Info("Failed to set LED on/off time.\n");
+ if (power_save) {
+ i = pwc_camera_power(pdev, 0);
+ if (i < 0)
+ Err("Failed to power down camera (%d)\n", i);
+ }
+ }
+ pdev->vopen = 0;
+ Trace(TRACE_OPEN, "<< video_close()\n");
+ return 0;
+}
+
+/*
+ * FIXME: what about two parallel reads ????
+ * ANSWER: Not supported. You can't open the device more than once,
+ despite what the V4L1 interface says. First, I don't see
+ the need, second there's no mechanism of alerting the
+ 2nd/3rd/... process of events like changing image size.
+ And I don't see the point of blocking that for the
+ 2nd/3rd/... process.
+ In multi-threaded environments reading parallel from any
+ device is tricky anyhow.
+ */
+
+static ssize_t pwc_video_read(struct file *file, char __user * buf,
+ size_t count, loff_t *ppos)
+{
+ struct video_device *vdev = file->private_data;
+ struct pwc_device *pdev;
+ int noblock = file->f_flags & O_NONBLOCK;
+ DECLARE_WAITQUEUE(wait, current);
+ int bytes_to_read;
+
+ Trace(TRACE_READ, "video_read(0x%p, %p, %Zd) called.\n", vdev, buf, count);
+ if (vdev == NULL)
+ return -EFAULT;
+ pdev = vdev->priv;
+ if (pdev == NULL)
+ return -EFAULT;
+ if (pdev->error_status)
+ return -pdev->error_status; /* Something happened, report what. */
+
+ /* In case we're doing partial reads, we don't have to wait for a frame */
+ if (pdev->image_read_pos == 0) {
+ /* Do wait queueing according to the (doc)book */
+ add_wait_queue(&pdev->frameq, &wait);
+ while (pdev->full_frames == NULL) {
+ /* Check for unplugged/etc. here */
+ if (pdev->error_status) {
+ remove_wait_queue(&pdev->frameq, &wait);
+ set_current_state(TASK_RUNNING);
+ return -pdev->error_status ;
+ }
+ if (noblock) {
+ remove_wait_queue(&pdev->frameq, &wait);
+ set_current_state(TASK_RUNNING);
+ return -EWOULDBLOCK;
+ }
+ if (signal_pending(current)) {
+ remove_wait_queue(&pdev->frameq, &wait);
+ set_current_state(TASK_RUNNING);
+ return -ERESTARTSYS;
+ }
+ schedule();
+ set_current_state(TASK_INTERRUPTIBLE);
+ }
+ remove_wait_queue(&pdev->frameq, &wait);
+ set_current_state(TASK_RUNNING);
+
+ /* Decompress and release frame */
+ if (pwc_handle_frame(pdev))
+ return -EFAULT;
+ }
+
+ Trace(TRACE_READ, "Copying data to user space.\n");
+ if (pdev->vpalette == VIDEO_PALETTE_RAW)
+ bytes_to_read = pdev->frame_size;
+ else
+ bytes_to_read = pdev->view.size;
+
+ /* copy bytes to user space; we allow for partial reads */
+ if (count + pdev->image_read_pos > bytes_to_read)
+ count = bytes_to_read - pdev->image_read_pos;
+ if (copy_to_user(buf, pdev->image_ptr[pdev->fill_image] + pdev->image_read_pos, count))
+ return -EFAULT;
+ pdev->image_read_pos += count;
+ if (pdev->image_read_pos >= bytes_to_read) { /* All data has been read */
+ pdev->image_read_pos = 0;
+ pwc_next_image(pdev);
+ }
+ return count;
+}
+
+static unsigned int pwc_video_poll(struct file *file, poll_table *wait)
+{
+ struct video_device *vdev = file->private_data;
+ struct pwc_device *pdev;
+
+ if (vdev == NULL)
+ return -EFAULT;
+ pdev = vdev->priv;
+ if (pdev == NULL)
+ return -EFAULT;
+
+ poll_wait(file, &pdev->frameq, wait);
+ if (pdev->error_status)
+ return POLLERR;
+ if (pdev->full_frames != NULL) /* we have frames waiting */
+ return (POLLIN | POLLRDNORM);
+
+ return 0;
+}
+
+static int pwc_video_do_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, void *arg)
+{
+ struct video_device *vdev = file->private_data;
+ struct pwc_device *pdev;
+ DECLARE_WAITQUEUE(wait, current);
+
+ if (vdev == NULL)
+ return -EFAULT;
+ pdev = vdev->priv;
+ if (pdev == NULL)
+ return -EFAULT;
+
+ switch (cmd) {
+ /* Query cabapilities */
+ case VIDIOCGCAP:
+ {
+ struct video_capability *caps = arg;
+
+ strcpy(caps->name, vdev->name);
+ caps->type = VID_TYPE_CAPTURE;
+ caps->channels = 1;
+ caps->audios = 1;
+ caps->minwidth = pdev->view_min.x;
+ caps->minheight = pdev->view_min.y;
+ caps->maxwidth = pdev->view_max.x;
+ caps->maxheight = pdev->view_max.y;
+ break;
+ }
+
+ /* Channel functions (simulate 1 channel) */
+ case VIDIOCGCHAN:
+ {
+ struct video_channel *v = arg;
+
+ if (v->channel != 0)
+ return -EINVAL;
+ v->flags = 0;
+ v->tuners = 0;
+ v->type = VIDEO_TYPE_CAMERA;
+ strcpy(v->name, "Webcam");
+ return 0;
+ }
+
+ case VIDIOCSCHAN:
+ {
+ /* The spec says the argument is an integer, but
+ the bttv driver uses a video_channel arg, which
+ makes sense becasue it also has the norm flag.
+ */
+ struct video_channel *v = arg;
+ if (v->channel != 0)
+ return -EINVAL;
+ return 0;
+ }
+
+
+ /* Picture functions; contrast etc. */
+ case VIDIOCGPICT:
+ {
+ struct video_picture *p = arg;
+ int val;
+
+ val = pwc_get_brightness(pdev);
+ if (val >= 0)
+ p->brightness = val;
+ else
+ p->brightness = 0xffff;
+ val = pwc_get_contrast(pdev);
+ if (val >= 0)
+ p->contrast = val;
+ else
+ p->contrast = 0xffff;
+ /* Gamma, Whiteness, what's the difference? :) */
+ val = pwc_get_gamma(pdev);
+ if (val >= 0)
+ p->whiteness = val;
+ else
+ p->whiteness = 0xffff;
+ val = pwc_get_saturation(pdev);
+ if (val >= 0)
+ p->colour = val;
+ else
+ p->colour = 0xffff;
+ p->depth = 24;
+ p->palette = pdev->vpalette;
+ p->hue = 0xFFFF; /* N/A */
+ break;
+ }
+
+ case VIDIOCSPICT:
+ {
+ struct video_picture *p = arg;
+ /*
+ * FIXME: Suppose we are mid read
+ ANSWER: No problem: the firmware of the camera
+ can handle brightness/contrast/etc
+ changes at _any_ time, and the palette
+ is used exactly once in the uncompress
+ routine.
+ */
+ pwc_set_brightness(pdev, p->brightness);
+ pwc_set_contrast(pdev, p->contrast);
+ pwc_set_gamma(pdev, p->whiteness);
+ pwc_set_saturation(pdev, p->colour);
+ if (p->palette && p->palette != pdev->vpalette) {
+ switch (p->palette) {
+ case VIDEO_PALETTE_YUV420P:
+ case VIDEO_PALETTE_RAW:
+ pdev->vpalette = p->palette;
+ return pwc_try_video_mode(pdev, pdev->image.x, pdev->image.y, pdev->vframes, pdev->vcompression, pdev->vsnapshot);
+ break;
+ default:
+ return -EINVAL;
+ break;
+ }
+ }
+ break;
+ }
+
+ /* Window/size parameters */
+ case VIDIOCGWIN:
+ {
+ struct video_window *vw = arg;
+
+ vw->x = 0;
+ vw->y = 0;
+ vw->width = pdev->view.x;
+ vw->height = pdev->view.y;
+ vw->chromakey = 0;
+ vw->flags = (pdev->vframes << PWC_FPS_SHIFT) |
+ (pdev->vsnapshot ? PWC_FPS_SNAPSHOT : 0);
+ break;
+ }
+
+ case VIDIOCSWIN:
+ {
+ struct video_window *vw = arg;
+ int fps, snapshot, ret;
+
+ fps = (vw->flags & PWC_FPS_FRMASK) >> PWC_FPS_SHIFT;
+ snapshot = vw->flags & PWC_FPS_SNAPSHOT;
+ if (fps == 0)
+ fps = pdev->vframes;
+ if (pdev->view.x == vw->width && pdev->view.y && fps == pdev->vframes && snapshot == pdev->vsnapshot)
+ return 0;
+ ret = pwc_try_video_mode(pdev, vw->width, vw->height, fps, pdev->vcompression, snapshot);
+ if (ret)
+ return ret;
+ break;
+ }
+
+ /* We don't have overlay support (yet) */
+ case VIDIOCGFBUF:
+ {
+ struct video_buffer *vb = arg;
+
+ memset(vb,0,sizeof(*vb));
+ break;
+ }
+
+ /* mmap() functions */
+ case VIDIOCGMBUF:
+ {
+ /* Tell the user program how much memory is needed for a mmap() */
+ struct video_mbuf *vm = arg;
+ int i;
+
+ memset(vm, 0, sizeof(*vm));
+ vm->size = default_mbufs * pdev->len_per_image;
+ vm->frames = default_mbufs; /* double buffering should be enough for most applications */
+ for (i = 0; i < default_mbufs; i++)
+ vm->offsets[i] = i * pdev->len_per_image;
+ break;
+ }
+
+ case VIDIOCMCAPTURE:
+ {
+ /* Start capture into a given image buffer (called 'frame' in video_mmap structure) */
+ struct video_mmap *vm = arg;
+
+ Trace(TRACE_READ, "VIDIOCMCAPTURE: %dx%d, frame %d, format %d\n", vm->width, vm->height, vm->frame, vm->format);
+ if (vm->frame < 0 || vm->frame >= default_mbufs)
+ return -EINVAL;
+
+ /* xawtv is nasty. It probes the available palettes
+ by setting a very small image size and trying
+ various palettes... The driver doesn't support
+ such small images, so I'm working around it.
+ */
+ if (vm->format)
+ {
+ switch (vm->format)
+ {
+ case VIDEO_PALETTE_YUV420P:
+ case VIDEO_PALETTE_RAW:
+ break;
+ default:
+ return -EINVAL;
+ break;
+ }
+ }
+
+ if ((vm->width != pdev->view.x || vm->height != pdev->view.y) &&
+ (vm->width >= pdev->view_min.x && vm->height >= pdev->view_min.y)) {
+ int ret;
+
+ Trace(TRACE_OPEN, "VIDIOCMCAPTURE: changing size to please xawtv :-(.\n");
+ ret = pwc_try_video_mode(pdev, vm->width, vm->height, pdev->vframes, pdev->vcompression, pdev->vsnapshot);
+ if (ret)
+ return ret;
+ } /* ... size mismatch */
+
+ /* FIXME: should we lock here? */
+ if (pdev->image_used[vm->frame])
+ return -EBUSY; /* buffer wasn't available. Bummer */
+ pdev->image_used[vm->frame] = 1;
+
+ /* Okay, we're done here. In the SYNC call we wait until a
+ frame comes available, then expand image into the given
+ buffer.
+ In contrast to the CPiA cam the Philips cams deliver a
+ constant stream, almost like a grabber card. Also,
+ we have separate buffers for the rawdata and the image,
+ meaning we can nearly always expand into the requested buffer.
+ */
+ Trace(TRACE_READ, "VIDIOCMCAPTURE done.\n");
+ break;
+ }
+
+ case VIDIOCSYNC:
+ {
+ /* The doc says: "Whenever a buffer is used it should
+ call VIDIOCSYNC to free this frame up and continue."
+
+ The only odd thing about this whole procedure is
+ that MCAPTURE flags the buffer as "in use", and
+ SYNC immediately unmarks it, while it isn't
+ after SYNC that you know that the buffer actually
+ got filled! So you better not start a CAPTURE in
+ the same frame immediately (use double buffering).
+ This is not a problem for this cam, since it has
+ extra intermediate buffers, but a hardware
+ grabber card will then overwrite the buffer
+ you're working on.
+ */
+ int *mbuf = arg;
+ int ret;
+
+ Trace(TRACE_READ, "VIDIOCSYNC called (%d).\n", *mbuf);
+
+ /* bounds check */
+ if (*mbuf < 0 || *mbuf >= default_mbufs)
+ return -EINVAL;
+ /* check if this buffer was requested anyway */
+ if (pdev->image_used[*mbuf] == 0)
+ return -EINVAL;
+
+ /* Add ourselves to the frame wait-queue.
+
+ FIXME: needs auditing for safety.
+ QUESTION: In what respect? I think that using the
+ frameq is safe now.
+ */
+ add_wait_queue(&pdev->frameq, &wait);
+ while (pdev->full_frames == NULL) {
+ if (pdev->error_status) {
+ remove_wait_queue(&pdev->frameq, &wait);
+ set_current_state(TASK_RUNNING);
+ return -pdev->error_status;
+ }
+
+ if (signal_pending(current)) {
+ remove_wait_queue(&pdev->frameq, &wait);
+ set_current_state(TASK_RUNNING);
+ return -ERESTARTSYS;
+ }
+ schedule();
+ set_current_state(TASK_INTERRUPTIBLE);
+ }
+ remove_wait_queue(&pdev->frameq, &wait);
+ set_current_state(TASK_RUNNING);
+
+ /* The frame is ready. Expand in the image buffer
+ requested by the user. I don't care if you
+ mmap() 5 buffers and request data in this order:
+ buffer 4 2 3 0 1 2 3 0 4 3 1 . . .
+ Grabber hardware may not be so forgiving.
+ */
+ Trace(TRACE_READ, "VIDIOCSYNC: frame ready.\n");
+ pdev->fill_image = *mbuf; /* tell in which buffer we want the image to be expanded */
+ /* Decompress, etc */
+ ret = pwc_handle_frame(pdev);
+ pdev->image_used[*mbuf] = 0;
+ if (ret)
+ return -EFAULT;
+ break;
+ }
+
+ case VIDIOCGAUDIO:
+ {
+ struct video_audio *v = arg;
+
+ strcpy(v->name, "Microphone");
+ v->audio = -1; /* unknown audio minor */
+ v->flags = 0;
+ v->mode = VIDEO_SOUND_MONO;
+ v->volume = 0;
+ v->bass = 0;
+ v->treble = 0;
+ v->balance = 0x8000;
+ v->step = 1;
+ break;
+ }
+
+ case VIDIOCSAUDIO:
+ {
+ /* Dummy: nothing can be set */
+ break;
+ }
+
+ case VIDIOCGUNIT:
+ {
+ struct video_unit *vu = arg;
+
+ vu->video = pdev->vdev->minor & 0x3F;
+ vu->audio = -1; /* not known yet */
+ vu->vbi = -1;
+ vu->radio = -1;
+ vu->teletext = -1;
+ break;
+ }
+ default:
+ return pwc_ioctl(pdev, cmd, arg);
+ } /* ..switch */
+ return 0;
+}
+
+static int pwc_video_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ return video_usercopy(inode, file, cmd, arg, pwc_video_do_ioctl);
+}
+
+
+static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ struct video_device *vdev = file->private_data;
+ struct pwc_device *pdev;
+ unsigned long start = vma->vm_start;
+ unsigned long size = vma->vm_end-vma->vm_start;
+ unsigned long page, pos;
+
+ Trace(TRACE_MEMORY, "mmap(0x%p, 0x%lx, %lu) called.\n", vdev, start, size);
+ pdev = vdev->priv;
+
+ vma->vm_flags |= VM_IO;
+
+ pos = (unsigned long)pdev->image_data;
+ while (size > 0) {
+ page = vmalloc_to_pfn((void *)pos);
+ if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED))
+ return -EAGAIN;
+
+ start += PAGE_SIZE;
+ pos += PAGE_SIZE;
+ if (size > PAGE_SIZE)
+ size -= PAGE_SIZE;
+ else
+ size = 0;
+ }
+
+ return 0;
+}
+
+/***************************************************************************/
+/* USB functions */
+
+/* This function gets called when a new device is plugged in or the usb core
+ * is loaded.
+ */
+
+static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id *id)
+{
+ struct usb_device *udev = interface_to_usbdev(intf);
+ struct pwc_device *pdev = NULL;
+ int vendor_id, product_id, type_id;
+ int i, hint;
+ int features = 0;
+ int video_nr = -1; /* default: use next available device */
+ char serial_number[30], *name;
+
+ /* Check if we can handle this device */
+ Trace(TRACE_PROBE, "probe() called [%04X %04X], if %d\n",
+ le16_to_cpu(udev->descriptor.idVendor),
+ le16_to_cpu(udev->descriptor.idProduct),
+ intf->altsetting->desc.bInterfaceNumber);
+
+ /* the interfaces are probed one by one. We are only interested in the
+ video interface (0) now.
+ Interface 1 is the Audio Control, and interface 2 Audio itself.
+ */
+ if (intf->altsetting->desc.bInterfaceNumber > 0)
+ return -ENODEV;
+
+ vendor_id = le16_to_cpu(udev->descriptor.idVendor);
+ product_id = le16_to_cpu(udev->descriptor.idProduct);
+
+ if (vendor_id == 0x0471) {
+ switch (product_id) {
+ case 0x0302:
+ Info("Philips PCA645VC USB webcam detected.\n");
+ name = "Philips 645 webcam";
+ type_id = 645;
+ break;
+ case 0x0303:
+ Info("Philips PCA646VC USB webcam detected.\n");
+ name = "Philips 646 webcam";
+ type_id = 646;
+ break;
+ case 0x0304:
+ Info("Askey VC010 type 2 USB webcam detected.\n");
+ name = "Askey VC010 webcam";
+ type_id = 646;
+ break;
+ case 0x0307:
+ Info("Philips PCVC675K (Vesta) USB webcam detected.\n");
+ name = "Philips 675 webcam";
+ type_id = 675;
+ break;
+ case 0x0308:
+ Info("Philips PCVC680K (Vesta Pro) USB webcam detected.\n");
+ name = "Philips 680 webcam";
+ type_id = 680;
+ break;
+ case 0x030C:
+ Info("Philips PCVC690K (Vesta Pro Scan) USB webcam detected.\n");
+ name = "Philips 690 webcam";
+ type_id = 690;
+ break;
+ case 0x0310:
+ Info("Philips PCVC730K (ToUCam Fun)/PCVC830 (ToUCam II) USB webcam detected.\n");
+ name = "Philips 730 webcam";
+ type_id = 730;
+ break;
+ case 0x0311:
+ Info("Philips PCVC740K (ToUCam Pro)/PCVC840 (ToUCam II) USB webcam detected.\n");
+ name = "Philips 740 webcam";
+ type_id = 740;
+ break;
+ case 0x0312:
+ Info("Philips PCVC750K (ToUCam Pro Scan) USB webcam detected.\n");
+ name = "Philips 750 webcam";
+ type_id = 750;
+ break;
+ case 0x0313:
+ Info("Philips PCVC720K/40 (ToUCam XS) USB webcam detected.\n");
+ name = "Philips 720K/40 webcam";
+ type_id = 720;
+ break;
+ default:
+ return -ENODEV;
+ break;
+ }
+ }
+ else if (vendor_id == 0x069A) {
+ switch(product_id) {
+ case 0x0001:
+ Info("Askey VC010 type 1 USB webcam detected.\n");
+ name = "Askey VC010 webcam";
+ type_id = 645;
+ break;
+ default:
+ return -ENODEV;
+ break;
+ }
+ }
+ else if (vendor_id == 0x046d) {
+ switch(product_id) {
+ case 0x08b0:
+ Info("Logitech QuickCam Pro 3000 USB webcam detected.\n");
+ name = "Logitech QuickCam Pro 3000";
+ type_id = 740; /* CCD sensor */
+ break;
+ case 0x08b1:
+ Info("Logitech QuickCam Notebook Pro USB webcam detected.\n");
+ name = "Logitech QuickCam Notebook Pro";
+ type_id = 740; /* CCD sensor */
+ break;
+ case 0x08b2:
+ Info("Logitech QuickCam 4000 Pro USB webcam detected.\n");
+ name = "Logitech QuickCam Pro 4000";
+ type_id = 740; /* CCD sensor */
+ break;
+ case 0x08b3:
+ Info("Logitech QuickCam Zoom USB webcam detected.\n");
+ name = "Logitech QuickCam Zoom";
+ type_id = 740; /* CCD sensor */
+ break;
+ case 0x08B4:
+ Info("Logitech QuickCam Zoom (new model) USB webcam detected.\n");
+ name = "Logitech QuickCam Zoom";
+ type_id = 740; /* CCD sensor */
+ break;
+ case 0x08b5:
+ Info("Logitech QuickCam Orbit/Sphere USB webcam detected.\n");
+ name = "Logitech QuickCam Orbit";
+ type_id = 740; /* CCD sensor */
+ features |= FEATURE_MOTOR_PANTILT;
+ break;
+ case 0x08b6:
+ case 0x08b7:
+ case 0x08b8:
+ Info("Logitech QuickCam detected (reserved ID).\n");
+ name = "Logitech QuickCam (res.)";
+ type_id = 730; /* Assuming CMOS */
+ break;
+ default:
+ return -ENODEV;
+ break;
+ }
+ }
+ else if (vendor_id == 0x055d) {
+ /* I don't know the difference between the C10 and the C30;
+ I suppose the difference is the sensor, but both cameras
+ work equally well with a type_id of 675
+ */
+ switch(product_id) {
+ case 0x9000:
+ Info("Samsung MPC-C10 USB webcam detected.\n");
+ name = "Samsung MPC-C10";
+ type_id = 675;
+ break;
+ case 0x9001:
+ Info("Samsung MPC-C30 USB webcam detected.\n");
+ name = "Samsung MPC-C30";
+ type_id = 675;
+ break;
+ default:
+ return -ENODEV;
+ break;
+ }
+ }
+ else if (vendor_id == 0x041e) {
+ switch(product_id) {
+ case 0x400c:
+ Info("Creative Labs Webcam 5 detected.\n");
+ name = "Creative Labs Webcam 5";
+ type_id = 730;
+ break;
+ case 0x4011:
+ Info("Creative Labs Webcam Pro Ex detected.\n");
+ name = "Creative Labs Webcam Pro Ex";
+ type_id = 740;
+ break;
+ default:
+ return -ENODEV;
+ break;
+ }
+ }
+ else if (vendor_id == 0x04cc) {
+ switch(product_id) {
+ case 0x8116:
+ Info("Sotec Afina Eye USB webcam detected.\n");
+ name = "Sotec Afina Eye";
+ type_id = 730;
+ break;
+ default:
+ return -ENODEV;
+ break;
+ }
+ }
+ else if (vendor_id == 0x06be) {
+ switch(product_id) {
+ case 0x8116:
+ /* This is essentially the same cam as the Sotec Afina Eye */
+ Info("AME Co. Afina Eye USB webcam detected.\n");
+ name = "AME Co. Afina Eye";
+ type_id = 750;
+ break;
+ default:
+ return -ENODEV;
+ break;
+ }
+
+ }
+ else if (vendor_id == 0x0d81) {
+ switch(product_id) {
+ case 0x1900:
+ Info("Visionite VCS-UC300 USB webcam detected.\n");
+ name = "Visionite VCS-UC300";
+ type_id = 740; /* CCD sensor */
+ break;
+ case 0x1910:
+ Info("Visionite VCS-UM100 USB webcam detected.\n");
+ name = "Visionite VCS-UM100";
+ type_id = 730; /* CMOS sensor */
+ break;
+ default:
+ return -ENODEV;
+ break;
+ }
+ }
+ else
+ return -ENODEV; /* Not any of the know types; but the list keeps growing. */
+
+ memset(serial_number, 0, 30);
+ usb_string(udev, udev->descriptor.iSerialNumber, serial_number, 29);
+ Trace(TRACE_PROBE, "Device serial number is %s\n", serial_number);
+
+ if (udev->descriptor.bNumConfigurations > 1)
+ Info("Warning: more than 1 configuration available.\n");
+
+ /* Allocate structure, initialize pointers, mutexes, etc. and link it to the usb_device */
+ pdev = kmalloc(sizeof(struct pwc_device), GFP_KERNEL);
+ if (pdev == NULL) {
+ Err("Oops, could not allocate memory for pwc_device.\n");
+ return -ENOMEM;
+ }
+ memset(pdev, 0, sizeof(struct pwc_device));
+ pdev->type = type_id;
+ pdev->vsize = default_size;
+ pdev->vframes = default_fps;
+ strcpy(pdev->serial, serial_number);
+ pdev->features = features;
+ if (vendor_id == 0x046D && product_id == 0x08B5)
+ {
+ /* Logitech QuickCam Orbit
+ The ranges have been determined experimentally; they may differ from cam to cam.
+ Also, the exact ranges left-right and up-down are different for my cam
+ */
+ pdev->angle_range.pan_min = -7000;
+ pdev->angle_range.pan_max = 7000;
+ pdev->angle_range.tilt_min = -3000;
+ pdev->angle_range.tilt_max = 2500;
+ }
+
+ init_MUTEX(&pdev->modlock);
+ spin_lock_init(&pdev->ptrlock);
+
+ pdev->udev = udev;
+ init_waitqueue_head(&pdev->frameq);
+ pdev->vcompression = pwc_preferred_compression;
+
+ /* Allocate video_device structure */
+ pdev->vdev = video_device_alloc();
+ if (pdev->vdev == 0)
+ {
+ Err("Err, cannot allocate video_device struture. Failing probe.");
+ kfree(pdev);
+ return -ENOMEM;
+ }
+ memcpy(pdev->vdev, &pwc_template, sizeof(pwc_template));
+ strcpy(pdev->vdev->name, name);
+ pdev->vdev->owner = THIS_MODULE;
+ video_set_drvdata(pdev->vdev, pdev);
+
+ pdev->release = le16_to_cpu(udev->descriptor.bcdDevice);
+ Trace(TRACE_PROBE, "Release: %04x\n", pdev->release);
+
+ /* Now search device_hint[] table for a match, so we can hint a node number. */
+ for (hint = 0; hint < MAX_DEV_HINTS; hint++) {
+ if (((device_hint[hint].type == -1) || (device_hint[hint].type == pdev->type)) &&
+ (device_hint[hint].pdev == NULL)) {
+ /* so far, so good... try serial number */
+ if ((device_hint[hint].serial_number[0] == '*') || !strcmp(device_hint[hint].serial_number, serial_number)) {
+ /* match! */
+ video_nr = device_hint[hint].device_node;
+ Trace(TRACE_PROBE, "Found hint, will try to register as /dev/video%d\n", video_nr);
+ break;
+ }
+ }
+ }
+
+ pdev->vdev->release = video_device_release;
+ i = video_register_device(pdev->vdev, VFL_TYPE_GRABBER, video_nr);
+ if (i < 0) {
+ Err("Failed to register as video device (%d).\n", i);
+ video_device_release(pdev->vdev); /* Drip... drip... drip... */
+ kfree(pdev); /* Oops, no memory leaks please */
+ return -EIO;
+ }
+ else {
+ Info("Registered as /dev/video%d.\n", pdev->vdev->minor & 0x3F);
+ }
+
+ /* occupy slot */
+ if (hint < MAX_DEV_HINTS)
+ device_hint[hint].pdev = pdev;
+
+ Trace(TRACE_PROBE, "probe() function returning struct at 0x%p.\n", pdev);
+ usb_set_intfdata (intf, pdev);
+ return 0;
+}
+
+/* The user janked out the cable... */
+static void usb_pwc_disconnect(struct usb_interface *intf)
+{
+ struct pwc_device *pdev;
+ int hint;
+
+ lock_kernel();
+ pdev = usb_get_intfdata (intf);
+ usb_set_intfdata (intf, NULL);
+ if (pdev == NULL) {
+ Err("pwc_disconnect() Called without private pointer.\n");
+ goto disconnect_out;
+ }
+ if (pdev->udev == NULL) {
+ Err("pwc_disconnect() already called for %p\n", pdev);
+ goto disconnect_out;
+ }
+ if (pdev->udev != interface_to_usbdev(intf)) {
+ Err("pwc_disconnect() Woops: pointer mismatch udev/pdev.\n");
+ goto disconnect_out;
+ }
+#ifdef PWC_MAGIC
+ if (pdev->magic != PWC_MAGIC) {
+ Err("pwc_disconnect() Magic number failed. Consult your scrolls and try again.\n");
+ goto disconnect_out;
+ }
+#endif
+
+ /* We got unplugged; this is signalled by an EPIPE error code */
+ if (pdev->vopen) {
+ Info("Disconnected while webcam is in use!\n");
+ pdev->error_status = EPIPE;
+ }
+
+ /* Alert waiting processes */
+ wake_up_interruptible(&pdev->frameq);
+ /* Wait until device is closed */
+ while (pdev->vopen)
+ schedule();
+ /* Device is now closed, so we can safely unregister it */
+ Trace(TRACE_PROBE, "Unregistering video device in disconnect().\n");
+ video_unregister_device(pdev->vdev);
+
+ /* Free memory (don't set pdev to 0 just yet) */
+ kfree(pdev);
+
+disconnect_out:
+ /* search device_hint[] table if we occupy a slot, by any chance */
+ for (hint = 0; hint < MAX_DEV_HINTS; hint++)
+ if (device_hint[hint].pdev == pdev)
+ device_hint[hint].pdev = NULL;
+
+ unlock_kernel();
+}
+
+
+/* *grunt* We have to do atoi ourselves :-( */
+static int pwc_atoi(const char *s)
+{
+ int k = 0;
+
+ k = 0;
+ while (*s != '\0' && *s >= '0' && *s <= '9') {
+ k = 10 * k + (*s - '0');
+ s++;
+ }
+ return k;
+}
+
+
+/*
+ * Initialization code & module stuff
+ */
+
+static char size[10];
+static int fps = 0;
+static int fbufs = 0;
+static int mbufs = 0;
+static int trace = -1;
+static int compression = -1;
+static int leds[2] = { -1, -1 };
+static char *dev_hint[MAX_DEV_HINTS] = { };
+
+module_param_string(size, size, sizeof(size), 0);
+MODULE_PARM_DESC(size, "Initial image size. One of sqcif, qsif, qcif, sif, cif, vga");
+module_param(fps, int, 0000);
+MODULE_PARM_DESC(fps, "Initial frames per second. Varies with model, useful range 5-30");
+module_param(fbufs, int, 0000);
+MODULE_PARM_DESC(fbufs, "Number of internal frame buffers to reserve");
+module_param(mbufs, int, 0000);
+MODULE_PARM_DESC(mbufs, "Number of external (mmap()ed) image buffers");
+module_param(trace, int, 0000);
+MODULE_PARM_DESC(trace, "For debugging purposes");
+module_param(power_save, bool, 0000);
+MODULE_PARM_DESC(power_save, "Turn power save feature in camera on or off");
+module_param(compression, int, 0000);
+MODULE_PARM_DESC(compression, "Preferred compression quality. Range 0 (uncompressed) to 3 (high compression)");
+module_param_array(leds, int, NULL, 0000);
+MODULE_PARM_DESC(leds, "LED on,off time in milliseconds");
+module_param_array(dev_hint, charp, NULL, 0000);
+MODULE_PARM_DESC(dev_hint, "Device node hints");
+
+MODULE_DESCRIPTION("Philips & OEM USB webcam driver");
+MODULE_AUTHOR("Luc Saillard <luc@saillard.org>");
+MODULE_LICENSE("GPL");
+
+static int __init usb_pwc_init(void)
+{
+ int i, sz;
+ char *sizenames[PSZ_MAX] = { "sqcif", "qsif", "qcif", "sif", "cif", "vga" };
+
+ Info("Philips webcam module version " PWC_VERSION " loaded.\n");
+ Info("Supports Philips PCA645/646, PCVC675/680/690, PCVC720[40]/730/740/750 & PCVC830/840.\n");
+ Info("Also supports the Askey VC010, various Logitech Quickcams, Samsung MPC-C10 and MPC-C30,\n");
+ Info("the Creative WebCam 5 & Pro Ex, SOTEC Afina Eye and Visionite VCS-UC300 and VCS-UM100.\n");
+
+ if (fps) {
+ if (fps < 4 || fps > 30) {
+ Err("Framerate out of bounds (4-30).\n");
+ return -EINVAL;
+ }
+ default_fps = fps;
+ Info("Default framerate set to %d.\n", default_fps);
+ }
+
+ if (size[0]) {
+ /* string; try matching with array */
+ for (sz = 0; sz < PSZ_MAX; sz++) {
+ if (!strcmp(sizenames[sz], size)) { /* Found! */
+ default_size = sz;
+ break;
+ }
+ }
+ if (sz == PSZ_MAX) {
+ Err("Size not recognized; try size=[sqcif | qsif | qcif | sif | cif | vga].\n");
+ return -EINVAL;
+ }
+ Info("Default image size set to %s [%dx%d].\n", sizenames[default_size], pwc_image_sizes[default_size].x, pwc_image_sizes[default_size].y);
+ }
+ if (mbufs) {
+ if (mbufs < 1 || mbufs > MAX_IMAGES) {
+ Err("Illegal number of mmap() buffers; use a number between 1 and %d.\n", MAX_IMAGES);
+ return -EINVAL;
+ }
+ default_mbufs = mbufs;
+ Info("Number of image buffers set to %d.\n", default_mbufs);
+ }
+ if (fbufs) {
+ if (fbufs < 2 || fbufs > MAX_FRAMES) {
+ Err("Illegal number of frame buffers; use a number between 2 and %d.\n", MAX_FRAMES);
+ return -EINVAL;
+ }
+ default_fbufs = fbufs;
+ Info("Number of frame buffers set to %d.\n", default_fbufs);
+ }
+ if (trace >= 0) {
+ Info("Trace options: 0x%04x\n", trace);
+ pwc_trace = trace;
+ }
+ if (compression >= 0) {
+ if (compression > 3) {
+ Err("Invalid compression setting; use a number between 0 (uncompressed) and 3 (high).\n");
+ return -EINVAL;
+ }
+ pwc_preferred_compression = compression;
+ Info("Preferred compression set to %d.\n", pwc_preferred_compression);
+ }
+ if (power_save)
+ Info("Enabling power save on open/close.\n");
+ if (leds[0] >= 0)
+ led_on = leds[0];
+ if (leds[1] >= 0)
+ led_off = leds[1];
+
+ /* Big device node whoopla. Basicly, it allows you to assign a
+ device node (/dev/videoX) to a camera, based on its type
+ & serial number. The format is [type[.serialnumber]:]node.
+
+ Any camera that isn't matched by these rules gets the next
+ available free device node.
+ */
+ for (i = 0; i < MAX_DEV_HINTS; i++) {
+ char *s, *colon, *dot;
+
+ /* This loop also initializes the array */
+ device_hint[i].pdev = NULL;
+ s = dev_hint[i];
+ if (s != NULL && *s != '\0') {
+ device_hint[i].type = -1; /* wildcard */
+ strcpy(device_hint[i].serial_number, "*");
+
+ /* parse string: chop at ':' & '/' */
+ colon = dot = s;
+ while (*colon != '\0' && *colon != ':')
+ colon++;
+ while (*dot != '\0' && *dot != '.')
+ dot++;
+ /* Few sanity checks */
+ if (*dot != '\0' && dot > colon) {
+ Err("Malformed camera hint: the colon must be after the dot.\n");
+ return -EINVAL;
+ }
+
+ if (*colon == '\0') {
+ /* No colon */
+ if (*dot != '\0') {
+ Err("Malformed camera hint: no colon + device node given.\n");
+ return -EINVAL;
+ }
+ else {
+ /* No type or serial number specified, just a number. */
+ device_hint[i].device_node = pwc_atoi(s);
+ }
+ }
+ else {
+ /* There's a colon, so we have at least a type and a device node */
+ device_hint[i].type = pwc_atoi(s);
+ device_hint[i].device_node = pwc_atoi(colon + 1);
+ if (*dot != '\0') {
+ /* There's a serial number as well */
+ int k;
+
+ dot++;
+ k = 0;
+ while (*dot != ':' && k < 29) {
+ device_hint[i].serial_number[k++] = *dot;
+ dot++;
+ }
+ device_hint[i].serial_number[k] = '\0';
+ }
+ }
+#if PWC_DEBUG
+ Debug("device_hint[%d]:\n", i);
+ Debug(" type : %d\n", device_hint[i].type);
+ Debug(" serial# : %s\n", device_hint[i].serial_number);
+ Debug(" node : %d\n", device_hint[i].device_node);
+#endif
+ }
+ else
+ device_hint[i].type = 0; /* not filled */
+ } /* ..for MAX_DEV_HINTS */
+
+ Trace(TRACE_PROBE, "Registering driver at address 0x%p.\n", &pwc_driver);
+ return usb_register(&pwc_driver);
+}
+
+static void __exit usb_pwc_exit(void)
+{
+ Trace(TRACE_MODULE, "Deregistering driver.\n");
+ usb_deregister(&pwc_driver);
+ Info("Philips webcam module removed.\n");
+}
+
+module_init(usb_pwc_init);
+module_exit(usb_pwc_exit);
+
diff --git a/drivers/usb/media/pwc/pwc-ioctl.h b/drivers/usb/media/pwc/pwc-ioctl.h
new file mode 100644
index 0000000000000..65805eaa9a1c8
--- /dev/null
+++ b/drivers/usb/media/pwc/pwc-ioctl.h
@@ -0,0 +1,292 @@
+#ifndef PWC_IOCTL_H
+#define PWC_IOCTL_H
+
+/* (C) 2001-2004 Nemosoft Unv.
+ (C) 2004 Luc Saillard (luc@saillard.org)
+
+ NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+ driver and thus may have bugs that are not present in the original version.
+ Please send bug reports and support requests to <luc@saillard.org>.
+ The decompression routines have been implemented by reverse-engineering the
+ Nemosoft binary pwcx module. Caveat emptor.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the 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 is pwc-ioctl.h belonging to PWC 8.12.1
+ It contains structures and defines to communicate from user space
+ directly to the driver.
+ */
+
+/*
+ Changes
+ 2001/08/03 Alvarado Added ioctl constants to access methods for
+ changing white balance and red/blue gains
+ 2002/12/15 G. H. Fernandez-Toribio VIDIOCGREALSIZE
+ 2003/12/13 Nemosft Unv. Some modifications to make interfacing to
+ PWCX easier
+ */
+
+/* These are private ioctl() commands, specific for the Philips webcams.
+ They contain functions not found in other webcams, and settings not
+ specified in the Video4Linux API.
+
+ The #define names are built up like follows:
+ VIDIOC VIDeo IOCtl prefix
+ PWC Philps WebCam
+ G optional: Get
+ S optional: Set
+ ... the function
+ */
+
+
+ /* Enumeration of image sizes */
+#define PSZ_SQCIF 0x00
+#define PSZ_QSIF 0x01
+#define PSZ_QCIF 0x02
+#define PSZ_SIF 0x03
+#define PSZ_CIF 0x04
+#define PSZ_VGA 0x05
+#define PSZ_MAX 6
+
+
+/* The frame rate is encoded in the video_window.flags parameter using
+ the upper 16 bits, since some flags are defined nowadays. The following
+ defines provide a mask and shift to filter out this value.
+
+ In 'Snapshot' mode the camera freezes its automatic exposure and colour
+ balance controls.
+ */
+#define PWC_FPS_SHIFT 16
+#define PWC_FPS_MASK 0x00FF0000
+#define PWC_FPS_FRMASK 0x003F0000
+#define PWC_FPS_SNAPSHOT 0x00400000
+
+
+/* structure for transfering x & y coordinates */
+struct pwc_coord
+{
+ int x, y; /* guess what */
+ int size; /* size, or offset */
+};
+
+
+/* Used with VIDIOCPWCPROBE */
+struct pwc_probe
+{
+ char name[32];
+ int type;
+};
+
+struct pwc_serial
+{
+ char serial[30]; /* String with serial number. Contains terminating 0 */
+};
+
+/* pwc_whitebalance.mode values */
+#define PWC_WB_INDOOR 0
+#define PWC_WB_OUTDOOR 1
+#define PWC_WB_FL 2
+#define PWC_WB_MANUAL 3
+#define PWC_WB_AUTO 4
+
+/* Used with VIDIOCPWC[SG]AWB (Auto White Balance).
+ Set mode to one of the PWC_WB_* values above.
+ *red and *blue are the respective gains of these colour components inside
+ the camera; range 0..65535
+ When 'mode' == PWC_WB_MANUAL, 'manual_red' and 'manual_blue' are set or read;
+ otherwise undefined.
+ 'read_red' and 'read_blue' are read-only.
+*/
+struct pwc_whitebalance
+{
+ int mode;
+ int manual_red, manual_blue; /* R/W */
+ int read_red, read_blue; /* R/O */
+};
+
+/*
+ 'control_speed' and 'control_delay' are used in automatic whitebalance mode,
+ and tell the camera how fast it should react to changes in lighting, and
+ with how much delay. Valid values are 0..65535.
+*/
+struct pwc_wb_speed
+{
+ int control_speed;
+ int control_delay;
+
+};
+
+/* Used with VIDIOCPWC[SG]LED */
+struct pwc_leds
+{
+ int led_on; /* Led on-time; range = 0..25000 */
+ int led_off; /* Led off-time; range = 0..25000 */
+};
+
+/* Image size (used with GREALSIZE) */
+struct pwc_imagesize
+{
+ int width;
+ int height;
+};
+
+/* Defines and structures for Motorized Pan & Tilt */
+#define PWC_MPT_PAN 0x01
+#define PWC_MPT_TILT 0x02
+#define PWC_MPT_TIMEOUT 0x04 /* for status */
+
+/* Set angles; when absolute != 0, the angle is absolute and the
+ driver calculates the relative offset for you. This can only
+ be used with VIDIOCPWCSANGLE; VIDIOCPWCGANGLE always returns
+ absolute angles.
+ */
+struct pwc_mpt_angles
+{
+ int absolute; /* write-only */
+ int pan; /* degrees * 100 */
+ int tilt; /* degress * 100 */
+};
+
+/* Range of angles of the camera, both horizontally and vertically.
+ */
+struct pwc_mpt_range
+{
+ int pan_min, pan_max; /* degrees * 100 */
+ int tilt_min, tilt_max;
+};
+
+struct pwc_mpt_status
+{
+ int status;
+ int time_pan;
+ int time_tilt;
+};
+
+
+/* This is used for out-of-kernel decompression. With it, you can get
+ all the necessary information to initialize and use the decompressor
+ routines in standalone applications.
+ */
+struct pwc_video_command
+{
+ int type; /* camera type (645, 675, 730, etc.) */
+ int release; /* release number */
+
+ int size; /* one of PSZ_* */
+ int alternate;
+ int command_len; /* length of USB video command */
+ unsigned char command_buf[13]; /* Actual USB video command */
+ int bandlength; /* >0 = compressed */
+ int frame_size; /* Size of one (un)compressed frame */
+};
+
+/* Flags for PWCX subroutines. Not all modules honour all flags. */
+#define PWCX_FLAG_PLANAR 0x0001
+#define PWCX_FLAG_BAYER 0x0008
+
+
+/* IOCTL definitions */
+
+ /* Restore user settings */
+#define VIDIOCPWCRUSER _IO('v', 192)
+ /* Save user settings */
+#define VIDIOCPWCSUSER _IO('v', 193)
+ /* Restore factory settings */
+#define VIDIOCPWCFACTORY _IO('v', 194)
+
+ /* You can manipulate the compression factor. A compression preference of 0
+ means use uncompressed modes when available; 1 is low compression, 2 is
+ medium and 3 is high compression preferred. Of course, the higher the
+ compression, the lower the bandwidth used but more chance of artefacts
+ in the image. The driver automatically chooses a higher compression when
+ the preferred mode is not available.
+ */
+ /* Set preferred compression quality (0 = uncompressed, 3 = highest compression) */
+#define VIDIOCPWCSCQUAL _IOW('v', 195, int)
+ /* Get preferred compression quality */
+#define VIDIOCPWCGCQUAL _IOR('v', 195, int)
+
+
+/* Retrieve serial number of camera */
+#define VIDIOCPWCGSERIAL _IOR('v', 198, struct pwc_serial)
+
+ /* This is a probe function; since so many devices are supported, it
+ becomes difficult to include all the names in programs that want to
+ check for the enhanced Philips stuff. So in stead, try this PROBE;
+ it returns a structure with the original name, and the corresponding
+ Philips type.
+ To use, fill the structure with zeroes, call PROBE and if that succeeds,
+ compare the name with that returned from VIDIOCGCAP; they should be the
+ same. If so, you can be assured it is a Philips (OEM) cam and the type
+ is valid.
+ */
+#define VIDIOCPWCPROBE _IOR('v', 199, struct pwc_probe)
+
+ /* Set AGC (Automatic Gain Control); int < 0 = auto, 0..65535 = fixed */
+#define VIDIOCPWCSAGC _IOW('v', 200, int)
+ /* Get AGC; int < 0 = auto; >= 0 = fixed, range 0..65535 */
+#define VIDIOCPWCGAGC _IOR('v', 200, int)
+ /* Set shutter speed; int < 0 = auto; >= 0 = fixed, range 0..65535 */
+#define VIDIOCPWCSSHUTTER _IOW('v', 201, int)
+
+ /* Color compensation (Auto White Balance) */
+#define VIDIOCPWCSAWB _IOW('v', 202, struct pwc_whitebalance)
+#define VIDIOCPWCGAWB _IOR('v', 202, struct pwc_whitebalance)
+
+ /* Auto WB speed */
+#define VIDIOCPWCSAWBSPEED _IOW('v', 203, struct pwc_wb_speed)
+#define VIDIOCPWCGAWBSPEED _IOR('v', 203, struct pwc_wb_speed)
+
+ /* LEDs on/off/blink; int range 0..65535 */
+#define VIDIOCPWCSLED _IOW('v', 205, struct pwc_leds)
+#define VIDIOCPWCGLED _IOR('v', 205, struct pwc_leds)
+
+ /* Contour (sharpness); int < 0 = auto, 0..65536 = fixed */
+#define VIDIOCPWCSCONTOUR _IOW('v', 206, int)
+#define VIDIOCPWCGCONTOUR _IOR('v', 206, int)
+
+ /* Backlight compensation; 0 = off, otherwise on */
+#define VIDIOCPWCSBACKLIGHT _IOW('v', 207, int)
+#define VIDIOCPWCGBACKLIGHT _IOR('v', 207, int)
+
+ /* Flickerless mode; = 0 off, otherwise on */
+#define VIDIOCPWCSFLICKER _IOW('v', 208, int)
+#define VIDIOCPWCGFLICKER _IOR('v', 208, int)
+
+ /* Dynamic noise reduction; 0 off, 3 = high noise reduction */
+#define VIDIOCPWCSDYNNOISE _IOW('v', 209, int)
+#define VIDIOCPWCGDYNNOISE _IOR('v', 209, int)
+
+ /* Real image size as used by the camera; tells you whether or not there's a gray border around the image */
+#define VIDIOCPWCGREALSIZE _IOR('v', 210, struct pwc_imagesize)
+
+ /* Motorized pan & tilt functions */
+#define VIDIOCPWCMPTRESET _IOW('v', 211, int)
+#define VIDIOCPWCMPTGRANGE _IOR('v', 211, struct pwc_mpt_range)
+#define VIDIOCPWCMPTSANGLE _IOW('v', 212, struct pwc_mpt_angles)
+#define VIDIOCPWCMPTGANGLE _IOR('v', 212, struct pwc_mpt_angles)
+#define VIDIOCPWCMPTSTATUS _IOR('v', 213, struct pwc_mpt_status)
+
+ /* Get the USB set-video command; needed for initializing libpwcx */
+#define VIDIOCPWCGVIDCMD _IOR('v', 215, struct pwc_video_command)
+struct pwc_table_init_buffer {
+ int len;
+ char *buffer;
+
+};
+#define VIDIOCPWCGVIDTABLE _IOR('v', 216, struct pwc_table_init_buffer)
+
+#endif
diff --git a/drivers/usb/media/pwc/pwc-kiara.c b/drivers/usb/media/pwc/pwc-kiara.c
new file mode 100644
index 0000000000000..5485800efd833
--- /dev/null
+++ b/drivers/usb/media/pwc/pwc-kiara.c
@@ -0,0 +1,891 @@
+/* Linux driver for Philips webcam
+ (C) 2004 Luc Saillard (luc@saillard.org)
+
+ NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+ driver and thus may have bugs that are not present in the original version.
+ Please send bug reports and support requests to <luc@saillard.org>.
+ The decompression routines have been implemented by reverse-engineering the
+ Nemosoft binary pwcx module. Caveat emptor.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the 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 tables contains entries for the 730/740/750 (Kiara) camera, with
+ 4 different qualities (no compression, low, medium, high).
+ It lists the bandwidth requirements for said mode by its alternate interface
+ number. An alternate of 0 means that the mode is unavailable.
+
+ There are 6 * 4 * 4 entries:
+ 6 different resolutions subqcif, qsif, qcif, sif, cif, vga
+ 6 framerates: 5, 10, 15, 20, 25, 30
+ 4 compression modi: none, low, medium, high
+
+ When an uncompressed mode is not available, the next available compressed mode
+ will be chosen (unless the decompressor is absent). Sometimes there are only
+ 1 or 2 compressed modes available; in that case entries are duplicated.
+*/
+
+
+#include "pwc-kiara.h"
+#include "pwc-uncompress.h"
+
+const struct Kiara_table_entry Kiara_table[PSZ_MAX][6][4] =
+{
+ /* SQCIF */
+ {
+ /* 5 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 10 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 15 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 20 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 25 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 30 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ },
+ /* QSIF */
+ {
+ /* 5 fps */
+ {
+ {1, 146, 0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}},
+ {1, 146, 0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}},
+ {1, 146, 0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}},
+ {1, 146, 0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}},
+ },
+ /* 10 fps */
+ {
+ {2, 291, 0, {0x1C, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x23, 0x01, 0x80}},
+ {1, 192, 630, {0x14, 0xF4, 0x30, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xC0, 0x00, 0x80}},
+ {1, 192, 630, {0x14, 0xF4, 0x30, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xC0, 0x00, 0x80}},
+ {1, 192, 630, {0x14, 0xF4, 0x30, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xC0, 0x00, 0x80}},
+ },
+ /* 15 fps */
+ {
+ {3, 437, 0, {0x1B, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xB5, 0x01, 0x80}},
+ {2, 292, 640, {0x13, 0xF4, 0x30, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x20, 0x24, 0x01, 0x80}},
+ {2, 292, 640, {0x13, 0xF4, 0x30, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x20, 0x24, 0x01, 0x80}},
+ {1, 192, 420, {0x13, 0xF4, 0x30, 0x0D, 0x1B, 0x0C, 0x53, 0x1E, 0x18, 0xC0, 0x00, 0x80}},
+ },
+ /* 20 fps */
+ {
+ {4, 589, 0, {0x1A, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x4D, 0x02, 0x80}},
+ {3, 448, 730, {0x12, 0xF4, 0x30, 0x16, 0xC9, 0x16, 0x01, 0x0E, 0x18, 0xC0, 0x01, 0x80}},
+ {2, 292, 476, {0x12, 0xF4, 0x30, 0x0E, 0xD8, 0x0E, 0x10, 0x19, 0x18, 0x24, 0x01, 0x80}},
+ {1, 192, 312, {0x12, 0xF4, 0x50, 0x09, 0xB3, 0x08, 0xEB, 0x1E, 0x18, 0xC0, 0x00, 0x80}},
+ },
+ /* 25 fps */
+ {
+ {5, 703, 0, {0x19, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xBF, 0x02, 0x80}},
+ {3, 447, 610, {0x11, 0xF4, 0x30, 0x13, 0x0B, 0x12, 0x43, 0x14, 0x28, 0xBF, 0x01, 0x80}},
+ {2, 292, 398, {0x11, 0xF4, 0x50, 0x0C, 0x6C, 0x0B, 0xA4, 0x1E, 0x28, 0x24, 0x01, 0x80}},
+ {1, 193, 262, {0x11, 0xF4, 0x50, 0x08, 0x23, 0x07, 0x5B, 0x1E, 0x28, 0xC1, 0x00, 0x80}},
+ },
+ /* 30 fps */
+ {
+ {8, 874, 0, {0x18, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x6A, 0x03, 0x80}},
+ {5, 704, 730, {0x10, 0xF4, 0x30, 0x16, 0xC9, 0x16, 0x01, 0x0E, 0x28, 0xC0, 0x02, 0x80}},
+ {3, 448, 492, {0x10, 0xF4, 0x30, 0x0F, 0x5D, 0x0E, 0x95, 0x15, 0x28, 0xC0, 0x01, 0x80}},
+ {2, 292, 320, {0x10, 0xF4, 0x50, 0x09, 0xFB, 0x09, 0x33, 0x1E, 0x28, 0x24, 0x01, 0x80}},
+ },
+ },
+ /* QCIF */
+ {
+ /* 5 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 10 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 15 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 20 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 25 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 30 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ },
+ /* SIF */
+ {
+ /* 5 fps */
+ {
+ {4, 582, 0, {0x0D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x46, 0x02, 0x80}},
+ {3, 387, 1276, {0x05, 0xF4, 0x30, 0x27, 0xD8, 0x26, 0x48, 0x03, 0x10, 0x83, 0x01, 0x80}},
+ {2, 291, 960, {0x05, 0xF4, 0x30, 0x1D, 0xF2, 0x1C, 0x62, 0x04, 0x10, 0x23, 0x01, 0x80}},
+ {1, 191, 630, {0x05, 0xF4, 0x50, 0x13, 0xA9, 0x12, 0x19, 0x05, 0x18, 0xBF, 0x00, 0x80}},
+ },
+ /* 10 fps */
+ {
+ {0, },
+ {6, 775, 1278, {0x04, 0xF4, 0x30, 0x27, 0xE8, 0x26, 0x58, 0x05, 0x30, 0x07, 0x03, 0x80}},
+ {3, 447, 736, {0x04, 0xF4, 0x30, 0x16, 0xFB, 0x15, 0x6B, 0x05, 0x28, 0xBF, 0x01, 0x80}},
+ {2, 292, 480, {0x04, 0xF4, 0x70, 0x0E, 0xF9, 0x0D, 0x69, 0x09, 0x28, 0x24, 0x01, 0x80}},
+ },
+ /* 15 fps */
+ {
+ {0, },
+ {9, 955, 1050, {0x03, 0xF4, 0x30, 0x20, 0xCF, 0x1F, 0x3F, 0x06, 0x48, 0xBB, 0x03, 0x80}},
+ {4, 592, 650, {0x03, 0xF4, 0x30, 0x14, 0x44, 0x12, 0xB4, 0x08, 0x30, 0x50, 0x02, 0x80}},
+ {3, 448, 492, {0x03, 0xF4, 0x50, 0x0F, 0x52, 0x0D, 0xC2, 0x09, 0x38, 0xC0, 0x01, 0x80}},
+ },
+ /* 20 fps */
+ {
+ {0, },
+ {9, 958, 782, {0x02, 0xF4, 0x30, 0x18, 0x6A, 0x16, 0xDA, 0x0B, 0x58, 0xBE, 0x03, 0x80}},
+ {5, 703, 574, {0x02, 0xF4, 0x50, 0x11, 0xE7, 0x10, 0x57, 0x0B, 0x40, 0xBF, 0x02, 0x80}},
+ {3, 446, 364, {0x02, 0xF4, 0x90, 0x0B, 0x5C, 0x09, 0xCC, 0x0E, 0x38, 0xBE, 0x01, 0x80}},
+ },
+ /* 25 fps */
+ {
+ {0, },
+ {9, 958, 654, {0x01, 0xF4, 0x30, 0x14, 0x66, 0x12, 0xD6, 0x0B, 0x50, 0xBE, 0x03, 0x80}},
+ {6, 776, 530, {0x01, 0xF4, 0x50, 0x10, 0x8C, 0x0E, 0xFC, 0x0C, 0x48, 0x08, 0x03, 0x80}},
+ {4, 592, 404, {0x01, 0xF4, 0x70, 0x0C, 0x96, 0x0B, 0x06, 0x0B, 0x48, 0x50, 0x02, 0x80}},
+ },
+ /* 30 fps */
+ {
+ {0, },
+ {9, 957, 526, {0x00, 0xF4, 0x50, 0x10, 0x68, 0x0E, 0xD8, 0x0D, 0x58, 0xBD, 0x03, 0x80}},
+ {6, 775, 426, {0x00, 0xF4, 0x70, 0x0D, 0x48, 0x0B, 0xB8, 0x0F, 0x50, 0x07, 0x03, 0x80}},
+ {4, 590, 324, {0x00, 0x7A, 0x88, 0x0A, 0x1C, 0x08, 0xB4, 0x0E, 0x50, 0x4E, 0x02, 0x80}},
+ },
+ },
+ /* CIF */
+ {
+ /* 5 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 10 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 15 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 20 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 25 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 30 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ },
+ /* VGA */
+ {
+ /* 5 fps */
+ {
+ {0, },
+ {6, 773, 1272, {0x25, 0xF4, 0x30, 0x27, 0xB6, 0x24, 0x96, 0x02, 0x30, 0x05, 0x03, 0x80}},
+ {4, 592, 976, {0x25, 0xF4, 0x50, 0x1E, 0x78, 0x1B, 0x58, 0x03, 0x30, 0x50, 0x02, 0x80}},
+ {3, 448, 738, {0x25, 0xF4, 0x90, 0x17, 0x0C, 0x13, 0xEC, 0x04, 0x30, 0xC0, 0x01, 0x80}},
+ },
+ /* 10 fps */
+ {
+ {0, },
+ {9, 956, 788, {0x24, 0xF4, 0x70, 0x18, 0x9C, 0x15, 0x7C, 0x03, 0x48, 0xBC, 0x03, 0x80}},
+ {6, 776, 640, {0x24, 0xF4, 0xB0, 0x13, 0xFC, 0x11, 0x2C, 0x04, 0x48, 0x08, 0x03, 0x80}},
+ {4, 592, 488, {0x24, 0x7A, 0xE8, 0x0F, 0x3C, 0x0C, 0x6C, 0x06, 0x48, 0x50, 0x02, 0x80}},
+ },
+ /* 15 fps */
+ {
+ {0, },
+ {9, 957, 526, {0x23, 0x7A, 0xE8, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x03, 0x80}},
+ {9, 957, 526, {0x23, 0x7A, 0xE8, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x03, 0x80}},
+ {8, 895, 492, {0x23, 0x7A, 0xE8, 0x0F, 0x5D, 0x0C, 0x8D, 0x06, 0x58, 0x7F, 0x03, 0x80}},
+ },
+ /* 20 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 25 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 30 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ },
+};
+
+
+/*
+ * Rom table for kiara chips
+ *
+ * 32 roms tables (one for each resolution ?)
+ * 2 tables per roms (one for each passes) (Y, and U&V)
+ * 128 bytes per passes
+ */
+
+const unsigned int KiaraRomTable [8][2][16][8] =
+{
+ { /* version 0 */
+ { /* version 0, passes 0 */
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000001,0x00000001},
+ {0x00000000,0x00000000,0x00000009,0x00000009,
+ 0x00000009,0x00000009,0x00000009,0x00000009},
+ {0x00000000,0x00000000,0x00000009,0x00000049,
+ 0x00000049,0x00000049,0x00000049,0x00000049},
+ {0x00000000,0x00000000,0x00000049,0x00000049,
+ 0x00000049,0x00000249,0x0000024a,0x00000049},
+ {0x00000000,0x00000000,0x00000049,0x00000049,
+ 0x00000249,0x00000249,0x0000024a,0x0000024a},
+ {0x00000000,0x00000000,0x00000049,0x00000249,
+ 0x00000249,0x0000124a,0x0000024a,0x0000024a},
+ {0x00000000,0x00000000,0x00000049,0x00000249,
+ 0x0000124a,0x00009252,0x00001252,0x00001252},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x00009252,0x00009292,0x00009292,0x00009292},
+ {0x00000000,0x00000000,0x00000249,0x00001249,
+ 0x00009292,0x00009292,0x00009493,0x000124db},
+ {0x00000000,0x00000000,0x00000249,0x0000924a,
+ 0x00009492,0x0000a49b,0x0000a49b,0x000124db},
+ {0x00000000,0x00000000,0x00001249,0x00009252,
+ 0x0000a493,0x000124db,0x000124db,0x000126dc},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x000124db,0x000126dc,0x000136e4,0x000126dc},
+ {0x00000000,0x00000000,0x00009292,0x0000a49b,
+ 0x000124db,0x000136e4,0x000136e4,0x000136e4},
+ {0x00000000,0x00000000,0x00009292,0x0000a49b,
+ 0x000126dc,0x0001b724,0x0001b92d,0x0001b925},
+ {0x00000000,0x00000000,0x00009492,0x000124db,
+ 0x000136e4,0x0001b925,0x0001c96e,0x0001c92d},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ },
+ { /* version 0, passes 1 */
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000},
+ {0x00000000,0x00000000,0x00000001,0x00000009,
+ 0x00000009,0x00000009,0x00000009,0x00000001},
+ {0x00000000,0x00000000,0x00000009,0x00000009,
+ 0x00000049,0x00000049,0x00000049,0x00000049},
+ {0x00000000,0x00000000,0x00000049,0x00000049,
+ 0x00000049,0x00000049,0x0000024a,0x0000024a},
+ {0x00000000,0x00000000,0x00000049,0x00000049,
+ 0x00000249,0x00000249,0x0000024a,0x0000024a},
+ {0x00000000,0x00000000,0x00000049,0x00000249,
+ 0x00000249,0x00000249,0x0000024a,0x00001252},
+ {0x00000000,0x00000000,0x00000049,0x00001249,
+ 0x0000124a,0x0000124a,0x00001252,0x00009292},
+ {0x00000000,0x00000000,0x00000249,0x00001249,
+ 0x00009252,0x00009252,0x00009292,0x00009493},
+ {0x00000000,0x00000000,0x00000249,0x0000924a,
+ 0x00009292,0x00009292,0x00009292,0x00009493},
+ {0x00000000,0x00000000,0x00000249,0x00009292,
+ 0x00009492,0x00009493,0x0000a49b,0x00009493},
+ {0x00000000,0x00000000,0x00001249,0x00009292,
+ 0x0000a493,0x000124db,0x000126dc,0x000126dc},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x000126dc,0x000136e4,0x000136e4},
+ {0x00000000,0x00000000,0x00009252,0x00009493,
+ 0x000126dc,0x000126dc,0x000136e4,0x000136e4},
+ {0x00000000,0x00000000,0x00009292,0x0000a49b,
+ 0x000136e4,0x000136e4,0x0001b725,0x0001b724},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ }
+ },
+ { /* version 1 */
+ { /* version 1, passes 0 */
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000001},
+ {0x00000000,0x00000000,0x00000009,0x00000009,
+ 0x00000009,0x00000009,0x00000009,0x00000009},
+ {0x00000000,0x00000000,0x00000049,0x00000049,
+ 0x00000049,0x00000049,0x00000049,0x00000049},
+ {0x00000000,0x00000000,0x00000049,0x00000049,
+ 0x00000049,0x00000249,0x0000024a,0x0000024a},
+ {0x00000000,0x00000000,0x00000049,0x00000249,
+ 0x00000249,0x00000249,0x0000024a,0x00001252},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x00000249,0x0000124a,0x00001252,0x00001252},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x0000124a,0x0000124a,0x00009292,0x00009292},
+ {0x00000000,0x00000000,0x00000249,0x00001249,
+ 0x0000124a,0x00009252,0x00009292,0x00009292},
+ {0x00000000,0x00000000,0x00000249,0x00001249,
+ 0x00009252,0x00009292,0x00009292,0x00009292},
+ {0x00000000,0x00000000,0x00000249,0x00001249,
+ 0x00009252,0x00009292,0x00009493,0x00009493},
+ {0x00000000,0x00000000,0x00000249,0x0000924a,
+ 0x00009252,0x00009493,0x00009493,0x00009493},
+ {0x00000000,0x00000000,0x00000249,0x0000924a,
+ 0x00009292,0x00009493,0x00009493,0x00009493},
+ {0x00000000,0x00000000,0x00000249,0x00009252,
+ 0x00009492,0x00009493,0x0000a49b,0x0000a49b},
+ {0x00000000,0x00000000,0x00001249,0x00009292,
+ 0x00009492,0x000124db,0x000124db,0x000124db},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x000126dc,0x000126dc,0x000126dc},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ },
+ { /* version 1, passes 1 */
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000},
+ {0x00000000,0x00000000,0x00000049,0x00000009,
+ 0x00000049,0x00000009,0x00000001,0x00000000},
+ {0x00000000,0x00000000,0x00000049,0x00000049,
+ 0x00000049,0x00000049,0x00000049,0x00000000},
+ {0x00000000,0x00000000,0x00000249,0x00000049,
+ 0x00000249,0x00000049,0x0000024a,0x00000001},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x00000249,0x00000249,0x0000024a,0x00000001},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x00000249,0x00000249,0x0000024a,0x00000001},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x00000249,0x00000249,0x0000024a,0x00000009},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x0000124a,0x0000124a,0x0000024a,0x00000009},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x0000124a,0x0000124a,0x0000024a,0x00000009},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x0000124a,0x00009252,0x00001252,0x00000049},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x0000124a,0x00009292,0x00001252,0x00000049},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x0000124a,0x00009292,0x00001252,0x00000049},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009252,0x00009292,0x00001252,0x0000024a},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009292,0x00009292,0x00001252,0x0000024a},
+ {0x00000000,0x00000000,0x0000924a,0x0000924a,
+ 0x00009492,0x00009493,0x00009292,0x00001252},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ }
+ },
+ { /* version 2 */
+ { /* version 2, passes 0 */
+ {0x00000000,0x00000000,0x00000049,0x00000049,
+ 0x00000049,0x00000049,0x0000024a,0x0000024a},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x00000249,0x0000124a,0x00001252,0x00009292},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x0000124a,0x00009252,0x00009292,0x00009292},
+ {0x00000000,0x00000000,0x00000249,0x00001249,
+ 0x0000124a,0x00009292,0x00009493,0x00009493},
+ {0x00000000,0x00000000,0x00000249,0x00001249,
+ 0x00009252,0x00009493,0x00009493,0x0000a49b},
+ {0x00000000,0x00000000,0x00000249,0x0000924a,
+ 0x00009292,0x00009493,0x0000a49b,0x0000a49b},
+ {0x00000000,0x00000000,0x00001249,0x0000924a,
+ 0x00009292,0x00009493,0x0000a49b,0x000124db},
+ {0x00000000,0x00000000,0x00001249,0x00009252,
+ 0x00009492,0x0000a49b,0x0000a49b,0x000124db},
+ {0x00000000,0x00000000,0x00001249,0x00009292,
+ 0x00009492,0x000124db,0x000124db,0x000126dc},
+ {0x00000000,0x00000000,0x00001249,0x00009292,
+ 0x0000a493,0x000124db,0x000126dc,0x000126dc},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x000124db,0x000126dc,0x000136e4},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x000126dc,0x000136e4,0x000136e4},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0001249b,0x000126dc,0x000136e4,0x000136e4},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000124db,0x000136e4,0x000136e4,0x0001b724},
+ {0x00000000,0x00000000,0x00009252,0x000124db,
+ 0x000126dc,0x0001b724,0x0001b725,0x0001b925},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ },
+ { /* version 2, passes 1 */
+ {0x00000000,0x00000000,0x00000049,0x00000049,
+ 0x00000049,0x00000049,0x00000049,0x00000049},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x00000249,0x00000249,0x0000024a,0x00000049},
+ {0x00000000,0x00000000,0x00001249,0x00000249,
+ 0x0000124a,0x0000124a,0x00001252,0x00000049},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x0000124a,0x0000124a,0x00009292,0x0000024a},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009252,0x00009292,0x00009292,0x0000024a},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009252,0x00009292,0x0000a49b,0x0000024a},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009292,0x00009493,0x0000a49b,0x00001252},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009292,0x00009493,0x0000a49b,0x00001252},
+ {0x00000000,0x00000000,0x00001249,0x0000924a,
+ 0x00009492,0x0000a49b,0x0000a49b,0x00001252},
+ {0x00000000,0x00000000,0x00001249,0x00009252,
+ 0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+ {0x00000000,0x00000000,0x00001249,0x00009292,
+ 0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x0000a49b,0x0000a49b,0x00009292},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x0000a49b,0x0000a49b,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x000124db,0x0000a49b,0x00009493},
+ {0x00000000,0x00000000,0x00009252,0x0000a49b,
+ 0x0001249b,0x000126dc,0x000124db,0x0000a49b},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ }
+ },
+ { /* version 3 */
+ { /* version 3, passes 0 */
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x0000124a,0x0000124a,0x00009292,0x00009292},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009292,0x00009493,0x0000a49b,0x0000a49b},
+ {0x00000000,0x00000000,0x00001249,0x0000924a,
+ 0x00009492,0x0000a49b,0x0000a49b,0x000124db},
+ {0x00000000,0x00000000,0x00001249,0x00009292,
+ 0x00009492,0x000124db,0x000126dc,0x000126dc},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x000124db,0x000126dc,0x000126dc},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x000126dc,0x000136e4,0x000136e4},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x000126dc,0x000136e4,0x0001b724},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0001249b,0x000126dc,0x000136e4,0x0001b724},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0001249b,0x000126dc,0x000136e4,0x0001b724},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0001249b,0x000136e4,0x0001b725,0x0001b724},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000124db,0x000136e4,0x0001b725,0x0001b925},
+ {0x00000000,0x00000000,0x00009292,0x0000a49b,
+ 0x000126dc,0x000136e4,0x0001b92d,0x0001b925},
+ {0x00000000,0x00000000,0x00009292,0x0000a49b,
+ 0x000126dc,0x0001b724,0x0001b92d,0x0001c92d},
+ {0x00000000,0x00000000,0x00009492,0x000124db,
+ 0x000126dc,0x0001b724,0x0001c96e,0x0001c92d},
+ {0x00000000,0x00000000,0x0000a492,0x000126db,
+ 0x000136e4,0x0001b925,0x00025bb6,0x00024b77},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ },
+ { /* version 3, passes 1 */
+ {0x00000000,0x00000000,0x00001249,0x00000249,
+ 0x0000124a,0x0000124a,0x00001252,0x00001252},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009252,0x00009292,0x00009292,0x00001252},
+ {0x00000000,0x00000000,0x00001249,0x0000924a,
+ 0x00009492,0x00009493,0x0000a49b,0x00001252},
+ {0x00000000,0x00000000,0x00001249,0x00009252,
+ 0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+ {0x00000000,0x00000000,0x00001249,0x00009292,
+ 0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x0000a49b,0x000126dc,0x00009292},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x0000a49b,0x000126dc,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x0000a49b,0x000126dc,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x000124db,0x000126dc,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0001249b,0x000126dc,0x000126dc,0x0000a49b},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000124db,0x000136e4,0x000126dc,0x000124db},
+ {0x00000000,0x00000000,0x00009492,0x0000a49b,
+ 0x000136e4,0x000136e4,0x000126dc,0x000124db},
+ {0x00000000,0x00000000,0x0000a492,0x000124db,
+ 0x0001b724,0x0001b724,0x000136e4,0x000126dc},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ }
+ },
+ { /* version 4 */
+ { /* version 4, passes 0 */
+ {0x00000000,0x00000000,0x00000049,0x00000049,
+ 0x00000049,0x00000049,0x00000049,0x00000049},
+ {0x00000000,0x00000000,0x00000249,0x00000049,
+ 0x00000249,0x00000249,0x0000024a,0x00000049},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x0000124a,0x00009252,0x00001252,0x0000024a},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009252,0x00009292,0x00009493,0x00001252},
+ {0x00000000,0x00000000,0x00001249,0x0000924a,
+ 0x00009292,0x00009493,0x00009493,0x00001252},
+ {0x00000000,0x00000000,0x00001249,0x00009292,
+ 0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x000124db,0x000124db,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0001249b,0x000126dc,0x000126dc,0x000124db},
+ {0x00000000,0x00000000,0x00009252,0x00009493,
+ 0x000124db,0x000136e4,0x000136e4,0x000126dc},
+ {0x00000000,0x00000000,0x00009252,0x0000a49b,
+ 0x000124db,0x000136e4,0x000136e4,0x000126dc},
+ {0x00000000,0x00000000,0x00009292,0x0000a49b,
+ 0x000126dc,0x000136e4,0x000136e4,0x000136e4},
+ {0x00000000,0x00000000,0x00009492,0x0000a49b,
+ 0x000126dc,0x0001b724,0x0001b725,0x0001b724},
+ {0x00000000,0x00000000,0x0000a492,0x000124db,
+ 0x000136e4,0x0001b925,0x0001b92d,0x0001b925},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ },
+ { /* version 4, passes 1 */
+ {0x00000000,0x00000000,0x00000249,0x00000049,
+ 0x00000009,0x00000009,0x00000009,0x00000009},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x00000049,0x00000049,0x00000009,0x00000009},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x0000124a,0x00000249,0x00000049,0x00000049},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x0000124a,0x0000124a,0x00000049,0x00000049},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009252,0x0000124a,0x0000024a,0x0000024a},
+ {0x00000000,0x00000000,0x00001249,0x0000924a,
+ 0x00009252,0x0000124a,0x0000024a,0x0000024a},
+ {0x00000000,0x00000000,0x00001249,0x00009292,
+ 0x00009492,0x00009252,0x00001252,0x00001252},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x00009292,0x00009292,0x00001252},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x00009292,0x00009292,0x00009292},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x00009493,0x00009493,0x00009292},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0000a493,0x0000a49b,0x00009493,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0000a493,0x0000a49b,0x0000a49b,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0001249b,0x000124db,0x0000a49b,0x0000a49b},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+ {0x00000000,0x00000000,0x00009252,0x000124db,
+ 0x0001b724,0x000136e4,0x000126dc,0x000124db},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ }
+ },
+ { /* version 5 */
+ { /* version 5, passes 0 */
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x00000249,0x00000249,0x00001252,0x00001252},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009252,0x00009292,0x00009292,0x00001252},
+ {0x00000000,0x00000000,0x00001249,0x0000924a,
+ 0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x0000a49b,0x000124db,0x00009493},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x000124db,0x000126dc,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x000126dc,0x000126dc,0x0000a49b},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0001249b,0x000126dc,0x000136e4,0x000124db},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000126dc,0x000136e4,0x000136e4,0x000126dc},
+ {0x00000000,0x00000000,0x00009292,0x0000a49b,
+ 0x000126dc,0x000136e4,0x000136e4,0x000126dc},
+ {0x00000000,0x00000000,0x00009292,0x0000a49b,
+ 0x000126dc,0x0001b724,0x0001b725,0x000136e4},
+ {0x00000000,0x00000000,0x00009292,0x0000a49b,
+ 0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
+ {0x00000000,0x00000000,0x00009492,0x0000a49b,
+ 0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
+ {0x00000000,0x00000000,0x00009492,0x000124db,
+ 0x000136e4,0x0001b925,0x0001c96e,0x0001b925},
+ {0x00000000,0x00000000,0x00009492,0x000124db,
+ 0x0001b724,0x0001b925,0x0001c96e,0x0001c92d},
+ {0x00000000,0x00000000,0x0000a492,0x000126db,
+ 0x0001c924,0x0002496d,0x00025bb6,0x00024b77},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ },
+ { /* version 5, passes 1 */
+ {0x00000000,0x00000000,0x00001249,0x00000249,
+ 0x00000249,0x00000249,0x0000024a,0x0000024a},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x0000124a,0x0000124a,0x0000024a,0x0000024a},
+ {0x00000000,0x00000000,0x00001249,0x0000924a,
+ 0x00009252,0x00009252,0x0000024a,0x0000024a},
+ {0x00000000,0x00000000,0x00001249,0x00009292,
+ 0x00009492,0x0000a49b,0x00001252,0x00001252},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x0000a49b,0x00001252,0x00001252},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x0000a49b,0x00009292,0x00001252},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0000a493,0x0000a49b,0x00009292,0x00009292},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0000a493,0x0000a49b,0x00009493,0x00009292},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0001249b,0x000124db,0x00009493,0x00009292},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0001249b,0x000124db,0x00009493,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000124db,0x000124db,0x0000a49b,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x000124db,
+ 0x000126dc,0x000126dc,0x0000a49b,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x000124db,
+ 0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+ {0x00000000,0x00000000,0x00009292,0x000124db,
+ 0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+ {0x00000000,0x00000000,0x00009492,0x000126db,
+ 0x0001b724,0x000136e4,0x000126dc,0x000124db},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ }
+ },
+ { /* version 6 */
+ { /* version 6, passes 0 */
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009252,0x00009292,0x00009493,0x00009493},
+ {0x00000000,0x00000000,0x00001249,0x00009292,
+ 0x0000a493,0x0000a49b,0x0000a49b,0x00009493},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x000124db,0x000124db,0x0000a49b},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x000126dc,0x000126dc,0x0000a49b},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0001249b,0x000126dc,0x000136e4,0x000124db},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000126dc,0x000136e4,0x000136e4,0x000126dc},
+ {0x00000000,0x00000000,0x00009292,0x0000a49b,
+ 0x000126dc,0x0001b724,0x0001b725,0x000126dc},
+ {0x00000000,0x00000000,0x00009292,0x0000a49b,
+ 0x000136e4,0x0001b724,0x0001b92d,0x000136e4},
+ {0x00000000,0x00000000,0x00009492,0x0000a49b,
+ 0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
+ {0x00000000,0x00000000,0x00009492,0x000124db,
+ 0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
+ {0x00000000,0x00000000,0x00009492,0x000124db,
+ 0x000136e4,0x0001b925,0x0001b92d,0x0001b925},
+ {0x00000000,0x00000000,0x00009492,0x000124db,
+ 0x0001b724,0x0001b925,0x0001c96e,0x0001c92d},
+ {0x00000000,0x00000000,0x0000a492,0x000124db,
+ 0x0001b724,0x0001c92d,0x0001c96e,0x0001c92d},
+ {0x00000000,0x00000000,0x0000a492,0x000124db,
+ 0x0001b724,0x0001c92d,0x00024b76,0x0002496e},
+ {0x00000000,0x00000000,0x00012492,0x000126db,
+ 0x0001c924,0x00024b6d,0x0002ddb6,0x00025bbf},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ },
+ { /* version 6, passes 1 */
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x0000124a,0x0000124a,0x00001252,0x00001252},
+ {0x00000000,0x00000000,0x00001249,0x00009292,
+ 0x00009492,0x00009252,0x00001252,0x00001252},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x00009292,0x00001252,0x00001252},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0000a493,0x0000a49b,0x00009292,0x00009292},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0000a493,0x0000a49b,0x00009292,0x00009292},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0001249b,0x0000a49b,0x00009493,0x00009292},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000124db,0x000124db,0x00009493,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000124db,0x000124db,0x0000a49b,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x000124db,
+ 0x000126dc,0x000124db,0x0000a49b,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x000124db,
+ 0x000126dc,0x000126dc,0x0000a49b,0x0000a49b},
+ {0x00000000,0x00000000,0x0000924a,0x000124db,
+ 0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+ {0x00000000,0x00000000,0x00009492,0x000126db,
+ 0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+ {0x00000000,0x00000000,0x00009492,0x000126db,
+ 0x0001b724,0x000136e4,0x000126dc,0x000124db},
+ {0x00000000,0x00000000,0x00009492,0x000126db,
+ 0x0001b724,0x000136e4,0x000126dc,0x000124db},
+ {0x00000000,0x00000000,0x0000a492,0x000136db,
+ 0x0001c924,0x0001b724,0x000136e4,0x000126dc},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ }
+ },
+ { /* version 7 */
+ { /* version 7, passes 0 */
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009252,0x00009292,0x00009493,0x00009493},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x000124db,0x000126dc,0x00009493},
+ {0x00000000,0x00000000,0x00001249,0x0000a49b,
+ 0x0001249b,0x000126dc,0x000126dc,0x0000a49b},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0001249b,0x000126dc,0x000136e4,0x0000a49b},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000126dc,0x000136e4,0x0001b725,0x000124db},
+ {0x00000000,0x00000000,0x00009292,0x0000a49b,
+ 0x000136e4,0x0001b724,0x0001b725,0x000126dc},
+ {0x00000000,0x00000000,0x00009292,0x000124db,
+ 0x000136e4,0x0001b724,0x0001b725,0x000126dc},
+ {0x00000000,0x00000000,0x00009492,0x000124db,
+ 0x000136e4,0x0001b724,0x0001c96e,0x000136e4},
+ {0x00000000,0x00000000,0x00009492,0x000124db,
+ 0x000136e4,0x0001c92d,0x0001c96e,0x0001b724},
+ {0x00000000,0x00000000,0x0000a492,0x000124db,
+ 0x000136e4,0x0001c92d,0x0001c96e,0x0001b724},
+ {0x00000000,0x00000000,0x0000a492,0x000124db,
+ 0x0001b724,0x0001c92d,0x0001c96e,0x0001b925},
+ {0x00000000,0x00000000,0x0000a492,0x000126db,
+ 0x0001b724,0x0001c92d,0x00024b76,0x0001c92d},
+ {0x00000000,0x00000000,0x0000a492,0x000126db,
+ 0x0001b924,0x0001c92d,0x00024b76,0x0001c92d},
+ {0x00000000,0x00000000,0x0000a492,0x000126db,
+ 0x0001b924,0x0001c92d,0x00024b76,0x0002496e},
+ {0x00000000,0x00000000,0x00012492,0x000136db,
+ 0x00024924,0x00024b6d,0x0002ddb6,0x00025bbf},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ },
+ { /* version 7, passes 1 */
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x0000124a,0x0000124a,0x00001252,0x00001252},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x00009492,0x00009292,0x00001252,0x00001252},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0000a493,0x0000a49b,0x00001252,0x00001252},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0000a493,0x0000a49b,0x00009292,0x00009292},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0000a493,0x0000a49b,0x00009292,0x00009292},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000126dc,0x0000a49b,0x00009493,0x00009292},
+ {0x00000000,0x00000000,0x0000924a,0x000124db,
+ 0x000126dc,0x000124db,0x00009493,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x000124db,
+ 0x000136e4,0x000124db,0x0000a49b,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x000136db,
+ 0x0001b724,0x000124db,0x0000a49b,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x000136db,
+ 0x0001b724,0x000126dc,0x0000a49b,0x0000a49b},
+ {0x00000000,0x00000000,0x00009292,0x000136db,
+ 0x0001b724,0x000126dc,0x000124db,0x0000a49b},
+ {0x00000000,0x00000000,0x00009492,0x000136db,
+ 0x0001b724,0x000126dc,0x000124db,0x0000a49b},
+ {0x00000000,0x00000000,0x0000a492,0x000136db,
+ 0x0001b724,0x000136e4,0x000126dc,0x000124db},
+ {0x00000000,0x00000000,0x0000a492,0x000136db,
+ 0x0001b724,0x000136e4,0x000126dc,0x000124db},
+ {0x00000000,0x00000000,0x00012492,0x0001b6db,
+ 0x0001c924,0x0001b724,0x000136e4,0x000126dc},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ }
+ }
+};
+
diff --git a/drivers/usb/media/pwc/pwc-kiara.h b/drivers/usb/media/pwc/pwc-kiara.h
new file mode 100644
index 0000000000000..12929abbb1f0c
--- /dev/null
+++ b/drivers/usb/media/pwc/pwc-kiara.h
@@ -0,0 +1,45 @@
+/* Linux driver for Philips webcam
+ (C) 2004 Luc Saillard (luc@saillard.org)
+
+ NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+ driver and thus may have bugs that are not present in the original version.
+ Please send bug reports and support requests to <luc@saillard.org>.
+ The decompression routines have been implemented by reverse-engineering the
+ Nemosoft binary pwcx module. Caveat emptor.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the 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
+*/
+
+/* Entries for the Kiara (730/740/750) camera */
+
+#ifndef PWC_KIARA_H
+#define PWC_KIARA_H
+
+#include "pwc-ioctl.h"
+
+struct Kiara_table_entry
+{
+ char alternate; /* USB alternate interface */
+ unsigned short packetsize; /* Normal packet size */
+ unsigned short bandlength; /* Bandlength when decompressing */
+ unsigned char mode[12]; /* precomputed mode settings for cam */
+};
+
+const extern struct Kiara_table_entry Kiara_table[PSZ_MAX][6][4];
+const extern unsigned int KiaraRomTable[8][2][16][8];
+
+#endif
+
+
diff --git a/drivers/usb/media/pwc/pwc-misc.c b/drivers/usb/media/pwc/pwc-misc.c
new file mode 100644
index 0000000000000..b7a4bd3524c7f
--- /dev/null
+++ b/drivers/usb/media/pwc/pwc-misc.c
@@ -0,0 +1,140 @@
+/* Linux driver for Philips webcam
+ Various miscellaneous functions and tables.
+ (C) 1999-2003 Nemosoft Unv.
+ (C) 2004 Luc Saillard (luc@saillard.org)
+
+ NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+ driver and thus may have bugs that are not present in the original version.
+ Please send bug reports and support requests to <luc@saillard.org>.
+ The decompression routines have been implemented by reverse-engineering the
+ Nemosoft binary pwcx module. Caveat emptor.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the 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 "pwc.h"
+
+struct pwc_coord pwc_image_sizes[PSZ_MAX] =
+{
+ { 128, 96, 0 },
+ { 160, 120, 0 },
+ { 176, 144, 0 },
+ { 320, 240, 0 },
+ { 352, 288, 0 },
+ { 640, 480, 0 },
+};
+
+/* x,y -> PSZ_ */
+int pwc_decode_size(struct pwc_device *pdev, int width, int height)
+{
+ int i, find;
+
+ /* Make sure we don't go beyond our max size.
+ NB: we have different limits for RAW and normal modes. In case
+ you don't have the decompressor loaded or use RAW mode,
+ the maximum viewable size is smaller.
+ */
+ if (pdev->vpalette == VIDEO_PALETTE_RAW)
+ {
+ if (width > pdev->abs_max.x || height > pdev->abs_max.y)
+ {
+ Debug("VIDEO_PALETTE_RAW: going beyond abs_max.\n");
+ return -1;
+ }
+ }
+ else
+ {
+ if (width > pdev->view_max.x || height > pdev->view_max.y)
+ {
+ Debug("VIDEO_PALETTE_ not RAW: going beyond view_max.\n");
+ return -1;
+ }
+ }
+
+ /* Find the largest size supported by the camera that fits into the
+ requested size.
+ */
+ find = -1;
+ for (i = 0; i < PSZ_MAX; i++) {
+ if (pdev->image_mask & (1 << i)) {
+ if (pwc_image_sizes[i].x <= width && pwc_image_sizes[i].y <= height)
+ find = i;
+ }
+ }
+ return find;
+}
+
+/* initialize variables depending on type and decompressor*/
+void pwc_construct(struct pwc_device *pdev)
+{
+ switch(pdev->type) {
+ case 645:
+ case 646:
+ pdev->view_min.x = 128;
+ pdev->view_min.y = 96;
+ pdev->view_max.x = 352;
+ pdev->view_max.y = 288;
+ pdev->abs_max.x = 352;
+ pdev->abs_max.y = 288;
+ pdev->image_mask = 1 << PSZ_SQCIF | 1 << PSZ_QCIF | 1 << PSZ_CIF;
+ pdev->vcinterface = 2;
+ pdev->vendpoint = 4;
+ pdev->frame_header_size = 0;
+ pdev->frame_trailer_size = 0;
+ break;
+ case 675:
+ case 680:
+ case 690:
+ pdev->view_min.x = 128;
+ pdev->view_min.y = 96;
+ /* Anthill bug #38: PWC always reports max size, even without PWCX */
+ pdev->view_max.x = 640;
+ pdev->view_max.y = 480;
+ pdev->image_mask = 1 << PSZ_SQCIF | 1 << PSZ_QSIF | 1 << PSZ_QCIF | 1 << PSZ_SIF | 1 << PSZ_CIF | 1 << PSZ_VGA;
+ pdev->abs_max.x = 640;
+ pdev->abs_max.y = 480;
+ pdev->vcinterface = 3;
+ pdev->vendpoint = 4;
+ pdev->frame_header_size = 0;
+ pdev->frame_trailer_size = 0;
+ break;
+ case 720:
+ case 730:
+ case 740:
+ case 750:
+ pdev->view_min.x = 160;
+ pdev->view_min.y = 120;
+ pdev->view_max.x = 640;
+ pdev->view_max.y = 480;
+ pdev->image_mask = 1 << PSZ_QSIF | 1 << PSZ_SIF | 1 << PSZ_VGA;
+ pdev->abs_max.x = 640;
+ pdev->abs_max.y = 480;
+ pdev->vcinterface = 3;
+ pdev->vendpoint = 5;
+ pdev->frame_header_size = TOUCAM_HEADER_SIZE;
+ pdev->frame_trailer_size = TOUCAM_TRAILER_SIZE;
+ break;
+ }
+ Debug("type = %d\n",pdev->type);
+ pdev->vpalette = VIDEO_PALETTE_YUV420P; /* default */
+ pdev->view_min.size = pdev->view_min.x * pdev->view_min.y;
+ pdev->view_max.size = pdev->view_max.x * pdev->view_max.y;
+ /* length of image, in YUV format; always allocate enough memory. */
+ pdev->len_per_image = (pdev->abs_max.x * pdev->abs_max.y * 3) / 2;
+}
+
+
diff --git a/drivers/usb/media/pwc/pwc-nala.h b/drivers/usb/media/pwc/pwc-nala.h
new file mode 100644
index 0000000000000..e6c5cb69d03be
--- /dev/null
+++ b/drivers/usb/media/pwc/pwc-nala.h
@@ -0,0 +1,66 @@
+ /* SQCIF */
+ {
+ {0, 0, {0x04, 0x01, 0x03}},
+ {8, 0, {0x05, 0x01, 0x03}},
+ {7, 0, {0x08, 0x01, 0x03}},
+ {7, 0, {0x0A, 0x01, 0x03}},
+ {6, 0, {0x0C, 0x01, 0x03}},
+ {5, 0, {0x0F, 0x01, 0x03}},
+ {4, 0, {0x14, 0x01, 0x03}},
+ {3, 0, {0x18, 0x01, 0x03}},
+ },
+ /* QSIF */
+ {
+ {0},
+ {0},
+ {0},
+ {0},
+ {0},
+ {0},
+ {0},
+ {0},
+ },
+ /* QCIF */
+ {
+ {0, 0, {0x04, 0x01, 0x02}},
+ {8, 0, {0x05, 0x01, 0x02}},
+ {7, 0, {0x08, 0x01, 0x02}},
+ {6, 0, {0x0A, 0x01, 0x02}},
+ {5, 0, {0x0C, 0x01, 0x02}},
+ {4, 0, {0x0F, 0x01, 0x02}},
+ {1, 0, {0x14, 0x01, 0x02}},
+ {1, 0, {0x18, 0x01, 0x02}},
+ },
+ /* SIF */
+ {
+ {0},
+ {0},
+ {0},
+ {0},
+ {0},
+ {0},
+ {0},
+ {0},
+ },
+ /* CIF */
+ {
+ {4, 0, {0x04, 0x01, 0x01}},
+ {7, 1, {0x05, 0x03, 0x01}},
+ {6, 1, {0x08, 0x03, 0x01}},
+ {4, 1, {0x0A, 0x03, 0x01}},
+ {3, 1, {0x0C, 0x03, 0x01}},
+ {2, 1, {0x0F, 0x03, 0x01}},
+ {0},
+ {0},
+ },
+ /* VGA */
+ {
+ {0},
+ {0},
+ {0},
+ {0},
+ {0},
+ {0},
+ {0},
+ {0},
+ },
diff --git a/drivers/usb/media/pwc/pwc-timon.c b/drivers/usb/media/pwc/pwc-timon.c
new file mode 100644
index 0000000000000..f950a4e5ed96d
--- /dev/null
+++ b/drivers/usb/media/pwc/pwc-timon.c
@@ -0,0 +1,1446 @@
+/* Linux driver for Philips webcam
+ (C) 2004 Luc Saillard (luc@saillard.org)
+
+ NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+ driver and thus may have bugs that are not present in the original version.
+ Please send bug reports and support requests to <luc@saillard.org>.
+ The decompression routines have been implemented by reverse-engineering the
+ Nemosoft binary pwcx module. Caveat emptor.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the 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 tables contains entries for the 675/680/690 (Timon) camera, with
+ 4 different qualities (no compression, low, medium, high).
+ It lists the bandwidth requirements for said mode by its alternate interface
+ number. An alternate of 0 means that the mode is unavailable.
+
+ There are 6 * 4 * 4 entries:
+ 6 different resolutions subqcif, qsif, qcif, sif, cif, vga
+ 6 framerates: 5, 10, 15, 20, 25, 30
+ 4 compression modi: none, low, medium, high
+
+ When an uncompressed mode is not available, the next available compressed mode
+ will be chosen (unless the decompressor is absent). Sometimes there are only
+ 1 or 2 compressed modes available; in that case entries are duplicated.
+*/
+
+#include "pwc-timon.h"
+
+const struct Timon_table_entry Timon_table[PSZ_MAX][6][4] =
+{
+ /* SQCIF */
+ {
+ /* 5 fps */
+ {
+ {1, 140, 0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}},
+ {1, 140, 0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}},
+ {1, 140, 0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}},
+ {1, 140, 0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}},
+ },
+ /* 10 fps */
+ {
+ {2, 280, 0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}},
+ {2, 280, 0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}},
+ {2, 280, 0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}},
+ {2, 280, 0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}},
+ },
+ /* 15 fps */
+ {
+ {3, 410, 0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}},
+ {3, 410, 0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}},
+ {3, 410, 0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}},
+ {3, 410, 0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}},
+ },
+ /* 20 fps */
+ {
+ {4, 559, 0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}},
+ {4, 559, 0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}},
+ {4, 559, 0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}},
+ {4, 559, 0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}},
+ },
+ /* 25 fps */
+ {
+ {5, 659, 0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}},
+ {5, 659, 0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}},
+ {5, 659, 0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}},
+ {5, 659, 0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}},
+ },
+ /* 30 fps */
+ {
+ {7, 838, 0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}},
+ {7, 838, 0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}},
+ {7, 838, 0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}},
+ {7, 838, 0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}},
+ },
+ },
+ /* QSIF */
+ {
+ /* 5 fps */
+ {
+ {1, 146, 0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}},
+ {1, 146, 0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}},
+ {1, 146, 0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}},
+ {1, 146, 0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}},
+ },
+ /* 10 fps */
+ {
+ {2, 291, 0, {0x2C, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x23, 0xA1, 0xC0, 0x02}},
+ {1, 191, 630, {0x2C, 0xF4, 0x05, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xBF, 0xF4, 0xC0, 0x02}},
+ {1, 191, 630, {0x2C, 0xF4, 0x05, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xBF, 0xF4, 0xC0, 0x02}},
+ {1, 191, 630, {0x2C, 0xF4, 0x05, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xBF, 0xF4, 0xC0, 0x02}},
+ },
+ /* 15 fps */
+ {
+ {3, 437, 0, {0x2B, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xB5, 0x6D, 0xC0, 0x02}},
+ {2, 291, 640, {0x2B, 0xF4, 0x05, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x08, 0x23, 0xA1, 0xC0, 0x02}},
+ {2, 291, 640, {0x2B, 0xF4, 0x05, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x08, 0x23, 0xA1, 0xC0, 0x02}},
+ {1, 191, 420, {0x2B, 0xF4, 0x0D, 0x0D, 0x1B, 0x0C, 0x53, 0x1E, 0x08, 0xBF, 0xF4, 0xC0, 0x02}},
+ },
+ /* 20 fps */
+ {
+ {4, 588, 0, {0x2A, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x4C, 0x52, 0xC0, 0x02}},
+ {3, 447, 730, {0x2A, 0xF4, 0x05, 0x16, 0xC9, 0x16, 0x01, 0x0E, 0x18, 0xBF, 0x69, 0xC0, 0x02}},
+ {2, 292, 476, {0x2A, 0xF4, 0x0D, 0x0E, 0xD8, 0x0E, 0x10, 0x19, 0x18, 0x24, 0xA1, 0xC0, 0x02}},
+ {1, 192, 312, {0x2A, 0xF4, 0x1D, 0x09, 0xB3, 0x08, 0xEB, 0x1E, 0x18, 0xC0, 0xF4, 0xC0, 0x02}},
+ },
+ /* 25 fps */
+ {
+ {5, 703, 0, {0x29, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xBF, 0x42, 0xC0, 0x02}},
+ {3, 447, 610, {0x29, 0xF4, 0x05, 0x13, 0x0B, 0x12, 0x43, 0x14, 0x18, 0xBF, 0x69, 0xC0, 0x02}},
+ {2, 292, 398, {0x29, 0xF4, 0x0D, 0x0C, 0x6C, 0x0B, 0xA4, 0x1E, 0x18, 0x24, 0xA1, 0xC0, 0x02}},
+ {1, 192, 262, {0x29, 0xF4, 0x25, 0x08, 0x23, 0x07, 0x5B, 0x1E, 0x18, 0xC0, 0xF4, 0xC0, 0x02}},
+ },
+ /* 30 fps */
+ {
+ {8, 873, 0, {0x28, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x69, 0x37, 0xC0, 0x02}},
+ {5, 704, 774, {0x28, 0xF4, 0x05, 0x18, 0x21, 0x17, 0x59, 0x0F, 0x18, 0xC0, 0x42, 0xC0, 0x02}},
+ {3, 448, 492, {0x28, 0xF4, 0x05, 0x0F, 0x5D, 0x0E, 0x95, 0x15, 0x18, 0xC0, 0x69, 0xC0, 0x02}},
+ {2, 291, 320, {0x28, 0xF4, 0x1D, 0x09, 0xFB, 0x09, 0x33, 0x1E, 0x18, 0x23, 0xA1, 0xC0, 0x02}},
+ },
+ },
+ /* QCIF */
+ {
+ /* 5 fps */
+ {
+ {1, 193, 0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}},
+ {1, 193, 0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}},
+ {1, 193, 0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}},
+ {1, 193, 0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}},
+ },
+ /* 10 fps */
+ {
+ {3, 385, 0, {0x0C, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x81, 0x79, 0xC0, 0x02}},
+ {2, 291, 800, {0x0C, 0xF4, 0x05, 0x18, 0xF4, 0x18, 0x18, 0x11, 0x08, 0x23, 0xA1, 0xC0, 0x02}},
+ {2, 291, 800, {0x0C, 0xF4, 0x05, 0x18, 0xF4, 0x18, 0x18, 0x11, 0x08, 0x23, 0xA1, 0xC0, 0x02}},
+ {1, 194, 532, {0x0C, 0xF4, 0x05, 0x10, 0x9A, 0x0F, 0xBE, 0x1B, 0x08, 0xC2, 0xF0, 0xC0, 0x02}},
+ },
+ /* 15 fps */
+ {
+ {4, 577, 0, {0x0B, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x41, 0x52, 0xC0, 0x02}},
+ {3, 447, 818, {0x0B, 0xF4, 0x05, 0x19, 0x89, 0x18, 0xAD, 0x0F, 0x10, 0xBF, 0x69, 0xC0, 0x02}},
+ {2, 292, 534, {0x0B, 0xF4, 0x05, 0x10, 0xA3, 0x0F, 0xC7, 0x19, 0x10, 0x24, 0xA1, 0xC0, 0x02}},
+ {1, 195, 356, {0x0B, 0xF4, 0x15, 0x0B, 0x11, 0x0A, 0x35, 0x1E, 0x10, 0xC3, 0xF0, 0xC0, 0x02}},
+ },
+ /* 20 fps */
+ {
+ {6, 776, 0, {0x0A, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x08, 0x3F, 0xC0, 0x02}},
+ {4, 591, 804, {0x0A, 0xF4, 0x05, 0x19, 0x1E, 0x18, 0x42, 0x0F, 0x18, 0x4F, 0x4E, 0xC0, 0x02}},
+ {3, 447, 608, {0x0A, 0xF4, 0x05, 0x12, 0xFD, 0x12, 0x21, 0x15, 0x18, 0xBF, 0x69, 0xC0, 0x02}},
+ {2, 291, 396, {0x0A, 0xF4, 0x15, 0x0C, 0x5E, 0x0B, 0x82, 0x1E, 0x18, 0x23, 0xA1, 0xC0, 0x02}},
+ },
+ /* 25 fps */
+ {
+ {9, 928, 0, {0x09, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xA0, 0x33, 0xC0, 0x02}},
+ {5, 703, 800, {0x09, 0xF4, 0x05, 0x18, 0xF4, 0x18, 0x18, 0x10, 0x18, 0xBF, 0x42, 0xC0, 0x02}},
+ {3, 447, 508, {0x09, 0xF4, 0x0D, 0x0F, 0xD2, 0x0E, 0xF6, 0x1B, 0x18, 0xBF, 0x69, 0xC0, 0x02}},
+ {2, 292, 332, {0x09, 0xF4, 0x1D, 0x0A, 0x5A, 0x09, 0x7E, 0x1E, 0x18, 0x24, 0xA1, 0xC0, 0x02}},
+ },
+ /* 30 fps */
+ {
+ {0, },
+ {9, 956, 876, {0x08, 0xF4, 0x05, 0x1B, 0x58, 0x1A, 0x7C, 0x0E, 0x20, 0xBC, 0x33, 0x10, 0x02}},
+ {4, 592, 542, {0x08, 0xF4, 0x05, 0x10, 0xE4, 0x10, 0x08, 0x17, 0x20, 0x50, 0x4E, 0x10, 0x02}},
+ {2, 291, 266, {0x08, 0xF4, 0x25, 0x08, 0x48, 0x07, 0x6C, 0x1E, 0x20, 0x23, 0xA1, 0x10, 0x02}},
+ },
+ },
+ /* SIF */
+ {
+ /* 5 fps */
+ {
+ {4, 582, 0, {0x35, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x46, 0x52, 0x60, 0x02}},
+ {3, 387, 1276, {0x35, 0xF4, 0x05, 0x27, 0xD8, 0x26, 0x48, 0x03, 0x10, 0x83, 0x79, 0x60, 0x02}},
+ {2, 291, 960, {0x35, 0xF4, 0x0D, 0x1D, 0xF2, 0x1C, 0x62, 0x04, 0x10, 0x23, 0xA1, 0x60, 0x02}},
+ {1, 191, 630, {0x35, 0xF4, 0x1D, 0x13, 0xA9, 0x12, 0x19, 0x05, 0x08, 0xBF, 0xF4, 0x60, 0x02}},
+ },
+ /* 10 fps */
+ {
+ {0, },
+ {6, 775, 1278, {0x34, 0xF4, 0x05, 0x27, 0xE8, 0x26, 0x58, 0x05, 0x30, 0x07, 0x3F, 0x10, 0x02}},
+ {3, 447, 736, {0x34, 0xF4, 0x15, 0x16, 0xFB, 0x15, 0x6B, 0x05, 0x18, 0xBF, 0x69, 0x10, 0x02}},
+ {2, 291, 480, {0x34, 0xF4, 0x2D, 0x0E, 0xF9, 0x0D, 0x69, 0x09, 0x18, 0x23, 0xA1, 0x10, 0x02}},
+ },
+ /* 15 fps */
+ {
+ {0, },
+ {9, 955, 1050, {0x33, 0xF4, 0x05, 0x20, 0xCF, 0x1F, 0x3F, 0x06, 0x48, 0xBB, 0x33, 0x10, 0x02}},
+ {4, 591, 650, {0x33, 0xF4, 0x15, 0x14, 0x44, 0x12, 0xB4, 0x08, 0x30, 0x4F, 0x4E, 0x10, 0x02}},
+ {3, 448, 492, {0x33, 0xF4, 0x25, 0x0F, 0x52, 0x0D, 0xC2, 0x09, 0x28, 0xC0, 0x69, 0x10, 0x02}},
+ },
+ /* 20 fps */
+ {
+ {0, },
+ {9, 958, 782, {0x32, 0xF4, 0x0D, 0x18, 0x6A, 0x16, 0xDA, 0x0B, 0x58, 0xBE, 0x33, 0xD0, 0x02}},
+ {5, 703, 574, {0x32, 0xF4, 0x1D, 0x11, 0xE7, 0x10, 0x57, 0x0B, 0x40, 0xBF, 0x42, 0xD0, 0x02}},
+ {3, 446, 364, {0x32, 0xF4, 0x3D, 0x0B, 0x5C, 0x09, 0xCC, 0x0E, 0x30, 0xBE, 0x69, 0xD0, 0x02}},
+ },
+ /* 25 fps */
+ {
+ {0, },
+ {9, 958, 654, {0x31, 0xF4, 0x15, 0x14, 0x66, 0x12, 0xD6, 0x0B, 0x50, 0xBE, 0x33, 0x90, 0x02}},
+ {6, 776, 530, {0x31, 0xF4, 0x25, 0x10, 0x8C, 0x0E, 0xFC, 0x0C, 0x48, 0x08, 0x3F, 0x90, 0x02}},
+ {4, 592, 404, {0x31, 0xF4, 0x35, 0x0C, 0x96, 0x0B, 0x06, 0x0B, 0x38, 0x50, 0x4E, 0x90, 0x02}},
+ },
+ /* 30 fps */
+ {
+ {0, },
+ {9, 957, 526, {0x30, 0xF4, 0x25, 0x10, 0x68, 0x0E, 0xD8, 0x0D, 0x58, 0xBD, 0x33, 0x60, 0x02}},
+ {6, 775, 426, {0x30, 0xF4, 0x35, 0x0D, 0x48, 0x0B, 0xB8, 0x0F, 0x50, 0x07, 0x3F, 0x60, 0x02}},
+ {4, 590, 324, {0x30, 0x7A, 0x4B, 0x0A, 0x1C, 0x08, 0xB4, 0x0E, 0x40, 0x4E, 0x52, 0x60, 0x02}},
+ },
+ },
+ /* CIF */
+ {
+ /* 5 fps */
+ {
+ {6, 771, 0, {0x15, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x3F, 0x80, 0x02}},
+ {4, 465, 1278, {0x15, 0xF4, 0x05, 0x27, 0xEE, 0x26, 0x36, 0x03, 0x18, 0xD1, 0x65, 0x80, 0x02}},
+ {2, 291, 800, {0x15, 0xF4, 0x15, 0x18, 0xF4, 0x17, 0x3C, 0x05, 0x18, 0x23, 0xA1, 0x80, 0x02}},
+ {1, 193, 528, {0x15, 0xF4, 0x2D, 0x10, 0x7E, 0x0E, 0xC6, 0x0A, 0x18, 0xC1, 0xF4, 0x80, 0x02}},
+ },
+ /* 10 fps */
+ {
+ {0, },
+ {9, 932, 1278, {0x14, 0xF4, 0x05, 0x27, 0xEE, 0x26, 0x36, 0x04, 0x30, 0xA4, 0x33, 0x10, 0x02}},
+ {4, 591, 812, {0x14, 0xF4, 0x15, 0x19, 0x56, 0x17, 0x9E, 0x06, 0x28, 0x4F, 0x4E, 0x10, 0x02}},
+ {2, 291, 400, {0x14, 0xF4, 0x3D, 0x0C, 0x7A, 0x0A, 0xC2, 0x0E, 0x28, 0x23, 0xA1, 0x10, 0x02}},
+ },
+ /* 15 fps */
+ {
+ {0, },
+ {9, 956, 876, {0x13, 0xF4, 0x0D, 0x1B, 0x58, 0x19, 0xA0, 0x05, 0x38, 0xBC, 0x33, 0x60, 0x02}},
+ {5, 703, 644, {0x13, 0xF4, 0x1D, 0x14, 0x1C, 0x12, 0x64, 0x08, 0x38, 0xBF, 0x42, 0x60, 0x02}},
+ {3, 448, 410, {0x13, 0xF4, 0x3D, 0x0C, 0xC4, 0x0B, 0x0C, 0x0E, 0x38, 0xC0, 0x69, 0x60, 0x02}},
+ },
+ /* 20 fps */
+ {
+ {0, },
+ {9, 956, 650, {0x12, 0xF4, 0x1D, 0x14, 0x4A, 0x12, 0x92, 0x09, 0x48, 0xBC, 0x33, 0x10, 0x03}},
+ {6, 776, 528, {0x12, 0xF4, 0x2D, 0x10, 0x7E, 0x0E, 0xC6, 0x0A, 0x40, 0x08, 0x3F, 0x10, 0x03}},
+ {4, 591, 402, {0x12, 0xF4, 0x3D, 0x0C, 0x8F, 0x0A, 0xD7, 0x0E, 0x40, 0x4F, 0x4E, 0x10, 0x03}},
+ },
+ /* 25 fps */
+ {
+ {0, },
+ {9, 956, 544, {0x11, 0xF4, 0x25, 0x10, 0xF4, 0x0F, 0x3C, 0x0A, 0x48, 0xBC, 0x33, 0xC0, 0x02}},
+ {7, 840, 478, {0x11, 0xF4, 0x2D, 0x0E, 0xEB, 0x0D, 0x33, 0x0B, 0x48, 0x48, 0x3B, 0xC0, 0x02}},
+ {5, 703, 400, {0x11, 0xF4, 0x3D, 0x0C, 0x7A, 0x0A, 0xC2, 0x0E, 0x48, 0xBF, 0x42, 0xC0, 0x02}},
+ },
+ /* 30 fps */
+ {
+ {0, },
+ {9, 956, 438, {0x10, 0xF4, 0x35, 0x0D, 0xAC, 0x0B, 0xF4, 0x0D, 0x50, 0xBC, 0x33, 0x10, 0x02}},
+ {7, 838, 384, {0x10, 0xF4, 0x45, 0x0B, 0xFD, 0x0A, 0x45, 0x0F, 0x50, 0x46, 0x3B, 0x10, 0x02}},
+ {6, 773, 354, {0x10, 0x7A, 0x4B, 0x0B, 0x0C, 0x09, 0x80, 0x10, 0x50, 0x05, 0x3F, 0x10, 0x02}},
+ },
+ },
+ /* VGA */
+ {
+ /* 5 fps */
+ {
+ {0, },
+ {6, 773, 1272, {0x1D, 0xF4, 0x15, 0x27, 0xB6, 0x24, 0x96, 0x02, 0x30, 0x05, 0x3F, 0x10, 0x02}},
+ {4, 592, 976, {0x1D, 0xF4, 0x25, 0x1E, 0x78, 0x1B, 0x58, 0x03, 0x30, 0x50, 0x4E, 0x10, 0x02}},
+ {3, 448, 738, {0x1D, 0xF4, 0x3D, 0x17, 0x0C, 0x13, 0xEC, 0x04, 0x30, 0xC0, 0x69, 0x10, 0x02}},
+ },
+ /* 10 fps */
+ {
+ {0, },
+ {9, 956, 788, {0x1C, 0xF4, 0x35, 0x18, 0x9C, 0x15, 0x7C, 0x03, 0x48, 0xBC, 0x33, 0x10, 0x02}},
+ {6, 776, 640, {0x1C, 0x7A, 0x53, 0x13, 0xFC, 0x11, 0x2C, 0x04, 0x48, 0x08, 0x3F, 0x10, 0x02}},
+ {4, 592, 488, {0x1C, 0x7A, 0x6B, 0x0F, 0x3C, 0x0C, 0x6C, 0x06, 0x48, 0x50, 0x4E, 0x10, 0x02}},
+ },
+ /* 15 fps */
+ {
+ {0, },
+ {9, 957, 526, {0x1B, 0x7A, 0x63, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x33, 0x80, 0x02}},
+ {9, 957, 526, {0x1B, 0x7A, 0x63, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x33, 0x80, 0x02}},
+ {8, 895, 492, {0x1B, 0x7A, 0x6B, 0x0F, 0x5D, 0x0C, 0x8D, 0x06, 0x58, 0x7F, 0x37, 0x80, 0x02}},
+ },
+ /* 20 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 25 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ /* 30 fps */
+ {
+ {0, },
+ {0, },
+ {0, },
+ {0, },
+ },
+ },
+};
+
+/*
+ * 16 versions:
+ * 2 tables (one for Y, and one for U&V)
+ * 16 levels of details per tables
+ * 8 blocs
+ */
+
+const unsigned int TimonRomTable [16][2][16][8] =
+{
+ { /* version 0 */
+ { /* version 0, passes 0 */
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000001},
+ {0x00000000,0x00000000,0x00000001,0x00000001,
+ 0x00000001,0x00000001,0x00000001,0x00000001},
+ {0x00000000,0x00000000,0x00000001,0x00000001,
+ 0x00000001,0x00000009,0x00000009,0x00000009},
+ {0x00000000,0x00000000,0x00000009,0x00000001,
+ 0x00000009,0x00000009,0x00000009,0x00000009},
+ {0x00000000,0x00000000,0x00000009,0x00000009,
+ 0x00000009,0x00000009,0x00000049,0x00000009},
+ {0x00000000,0x00000000,0x00000009,0x00000009,
+ 0x00000009,0x00000049,0x00000049,0x00000049},
+ {0x00000000,0x00000000,0x00000009,0x00000009,
+ 0x00000049,0x00000049,0x00000049,0x00000049},
+ {0x00000000,0x00000000,0x00000009,0x00000049,
+ 0x00000049,0x00000049,0x00000049,0x00000049},
+ {0x00000000,0x00000000,0x00000049,0x00000049,
+ 0x00000049,0x00000049,0x0000024a,0x0000024a},
+ {0x00000000,0x00000000,0x00000049,0x00000049,
+ 0x00000049,0x00000249,0x0000024a,0x0000024a},
+ {0x00000000,0x00000000,0x00000049,0x00000049,
+ 0x00000249,0x00000249,0x0000024a,0x0000024a},
+ {0x00000000,0x00000000,0x00000049,0x00000049,
+ 0x00000249,0x00000249,0x00001252,0x0000024a},
+ {0x00000000,0x00000000,0x00000049,0x00000049,
+ 0x00000249,0x0000124a,0x00001252,0x0000024a},
+ {0x00000000,0x00000000,0x00000049,0x00000249,
+ 0x00000249,0x0000124a,0x00001252,0x0000024a},
+ {0x00000000,0x00000000,0x00000249,0x00001249,
+ 0x0000124a,0x00009252,0x00009292,0x00001252},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ },
+ { /* version 0, passes 1 */
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000},
+ {0x00000000,0x00000000,0x00000001,0x00000001,
+ 0x00000001,0x00000001,0x00000000,0x00000000},
+ {0x00000000,0x00000000,0x00000009,0x00000001,
+ 0x00000001,0x00000009,0x00000000,0x00000000},
+ {0x00000000,0x00000000,0x00000009,0x00000009,
+ 0x00000009,0x00000009,0x00000000,0x00000000},
+ {0x00000000,0x00000000,0x00000009,0x00000009,
+ 0x00000009,0x00000009,0x00000001,0x00000000},
+ {0x00000000,0x00000000,0x00000049,0x00000009,
+ 0x00000009,0x00000049,0x00000001,0x00000001},
+ {0x00000000,0x00000000,0x00000049,0x00000009,
+ 0x00000009,0x00000049,0x00000001,0x00000001},
+ {0x00000000,0x00000000,0x00000049,0x00000049,
+ 0x00000049,0x00000049,0x00000009,0x00000001},
+ {0x00000000,0x00000000,0x00000049,0x00000049,
+ 0x00000049,0x00000049,0x00000009,0x00000001},
+ {0x00000000,0x00000000,0x00000049,0x00000049,
+ 0x00000049,0x00000049,0x00000009,0x00000001},
+ {0x00000000,0x00000000,0x00000049,0x00000049,
+ 0x00000049,0x00000049,0x00000009,0x00000009},
+ {0x00000000,0x00000000,0x00000049,0x00000049,
+ 0x00000049,0x00000249,0x00000049,0x00000009},
+ {0x00000000,0x00000000,0x00000049,0x00000049,
+ 0x00000049,0x00000249,0x00000049,0x00000009},
+ {0x00000000,0x00000000,0x00000249,0x00000049,
+ 0x00000249,0x00000249,0x00000049,0x00000009},
+ {0x00000000,0x00000000,0x00001249,0x00000249,
+ 0x0000124a,0x0000124a,0x0000024a,0x00000049},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ }
+ },
+ { /* version 1 */
+ { /* version 1, passes 0 */
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000001},
+ {0x00000000,0x00000000,0x00000001,0x00000001,
+ 0x00000001,0x00000009,0x00000009,0x00000009},
+ {0x00000000,0x00000000,0x00000009,0x00000009,
+ 0x00000009,0x00000009,0x00000009,0x00000009},
+ {0x00000000,0x00000000,0x00000009,0x00000009,
+ 0x00000009,0x00000049,0x00000049,0x00000049},
+ {0x00000000,0x00000000,0x00000009,0x00000049,
+ 0x00000049,0x00000049,0x00000049,0x00000049},
+ {0x00000000,0x00000000,0x00000049,0x00000049,
+ 0x00000049,0x00000249,0x0000024a,0x0000024a},
+ {0x00000000,0x00000000,0x00000049,0x00000049,
+ 0x00000249,0x00000249,0x0000024a,0x0000024a},
+ {0x00000000,0x00000000,0x00000049,0x00000249,
+ 0x00000249,0x00000249,0x0000024a,0x00001252},
+ {0x00000000,0x00000000,0x00000049,0x00000249,
+ 0x00000249,0x0000124a,0x00001252,0x00001252},
+ {0x00000000,0x00000000,0x00000049,0x00000249,
+ 0x0000124a,0x0000124a,0x00001252,0x00001252},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x0000124a,0x0000124a,0x00009292,0x00009292},
+ {0x00000000,0x00000000,0x00000249,0x00001249,
+ 0x0000124a,0x00009252,0x00009292,0x00009292},
+ {0x00000000,0x00000000,0x00000249,0x00001249,
+ 0x00009252,0x00009252,0x00009292,0x00009292},
+ {0x00000000,0x00000000,0x00000249,0x0000924a,
+ 0x00009292,0x00009493,0x00009493,0x00009493},
+ {0x00000000,0x00000000,0x00001249,0x00009252,
+ 0x00009492,0x0000a49b,0x0000a49b,0x0000a49b},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ },
+ { /* version 1, passes 1 */
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000},
+ {0x00000000,0x00000000,0x00000009,0x00000009,
+ 0x00000009,0x00000001,0x00000001,0x00000000},
+ {0x00000000,0x00000000,0x00000009,0x00000009,
+ 0x00000009,0x00000009,0x00000001,0x00000000},
+ {0x00000000,0x00000000,0x00000049,0x00000049,
+ 0x00000049,0x00000009,0x00000001,0x00000000},
+ {0x00000000,0x00000000,0x00000049,0x00000049,
+ 0x00000049,0x00000049,0x00000001,0x00000001},
+ {0x00000000,0x00000000,0x00000049,0x00000049,
+ 0x00000049,0x00000049,0x00000009,0x00000001},
+ {0x00000000,0x00000000,0x00000249,0x00000049,
+ 0x00000049,0x00000249,0x00000009,0x00000001},
+ {0x00000000,0x00000000,0x00000249,0x00000049,
+ 0x00000249,0x00000249,0x00000009,0x00000009},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x00000249,0x00000249,0x00000049,0x00000009},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x00000249,0x0000124a,0x00000049,0x00000009},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x00000249,0x0000124a,0x00000049,0x00000009},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x00000249,0x0000124a,0x0000024a,0x00000049},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x0000124a,0x0000124a,0x0000024a,0x00000049},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x0000124a,0x0000124a,0x0000024a,0x00000049},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009252,0x00009252,0x00001252,0x0000024a},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ }
+ },
+ { /* version 2 */
+ { /* version 2, passes 0 */
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000001},
+ {0x00000000,0x00000000,0x00000009,0x00000009,
+ 0x00000009,0x00000009,0x00000009,0x00000009},
+ {0x00000000,0x00000000,0x00000049,0x00000049,
+ 0x00000049,0x00000049,0x00000049,0x00000049},
+ {0x00000000,0x00000000,0x00000049,0x00000049,
+ 0x00000049,0x00000249,0x0000024a,0x0000024a},
+ {0x00000000,0x00000000,0x00000049,0x00000249,
+ 0x00000249,0x00000249,0x0000024a,0x00001252},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x00000249,0x0000124a,0x00001252,0x00001252},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x0000124a,0x0000124a,0x00009292,0x00009292},
+ {0x00000000,0x00000000,0x00000249,0x00001249,
+ 0x0000124a,0x00009252,0x00009292,0x00009292},
+ {0x00000000,0x00000000,0x00000249,0x00001249,
+ 0x00009252,0x00009292,0x00009292,0x00009292},
+ {0x00000000,0x00000000,0x00000249,0x00001249,
+ 0x00009252,0x00009292,0x00009493,0x00009493},
+ {0x00000000,0x00000000,0x00000249,0x0000924a,
+ 0x00009252,0x00009493,0x00009493,0x00009493},
+ {0x00000000,0x00000000,0x00000249,0x0000924a,
+ 0x00009292,0x00009493,0x00009493,0x00009493},
+ {0x00000000,0x00000000,0x00000249,0x00009252,
+ 0x00009492,0x00009493,0x0000a49b,0x0000a49b},
+ {0x00000000,0x00000000,0x00001249,0x00009292,
+ 0x00009492,0x000124db,0x000124db,0x000124db},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x000126dc,0x000126dc,0x000126dc},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ },
+ { /* version 2, passes 1 */
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000},
+ {0x00000000,0x00000000,0x00000049,0x00000009,
+ 0x00000049,0x00000009,0x00000001,0x00000000},
+ {0x00000000,0x00000000,0x00000049,0x00000049,
+ 0x00000049,0x00000049,0x00000049,0x00000000},
+ {0x00000000,0x00000000,0x00000249,0x00000049,
+ 0x00000249,0x00000049,0x0000024a,0x00000001},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x00000249,0x00000249,0x0000024a,0x00000001},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x00000249,0x00000249,0x0000024a,0x00000001},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x00000249,0x00000249,0x0000024a,0x00000009},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x0000124a,0x0000124a,0x0000024a,0x00000009},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x0000124a,0x0000124a,0x0000024a,0x00000009},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x0000124a,0x00009252,0x00001252,0x00000049},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x0000124a,0x00009292,0x00001252,0x00000049},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x0000124a,0x00009292,0x00001252,0x00000049},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009252,0x00009292,0x00001252,0x0000024a},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009292,0x00009292,0x00001252,0x0000024a},
+ {0x00000000,0x00000000,0x0000924a,0x0000924a,
+ 0x00009492,0x00009493,0x00009292,0x00001252},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ }
+ },
+ { /* version 3 */
+ { /* version 3, passes 0 */
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000001},
+ {0x00000000,0x00000000,0x00000049,0x00000049,
+ 0x00000049,0x00000049,0x00000049,0x00000049},
+ {0x00000000,0x00000000,0x00000049,0x00000249,
+ 0x00000249,0x00000249,0x00001252,0x0000024a},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x00000249,0x0000124a,0x00001252,0x00001252},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x0000124a,0x00009252,0x00009292,0x00009292},
+ {0x00000000,0x00000000,0x00000249,0x00001249,
+ 0x0000124a,0x00009292,0x00009292,0x00009493},
+ {0x00000000,0x00000000,0x00000249,0x00001249,
+ 0x00009252,0x00009292,0x00009493,0x00009493},
+ {0x00000000,0x00000000,0x00000249,0x00001249,
+ 0x00009292,0x00009493,0x00009493,0x00009493},
+ {0x00000000,0x00000000,0x00000249,0x00009252,
+ 0x00009292,0x00009493,0x0000a49b,0x0000a49b},
+ {0x00000000,0x00000000,0x00001249,0x00009252,
+ 0x00009292,0x0000a49b,0x0000a49b,0x0000a49b},
+ {0x00000000,0x00000000,0x00001249,0x00009252,
+ 0x00009492,0x0000a49b,0x0000a49b,0x0000a49b},
+ {0x00000000,0x00000000,0x00001249,0x00009292,
+ 0x00009492,0x0000a49b,0x000124db,0x000124db},
+ {0x00000000,0x00000000,0x00001249,0x00009292,
+ 0x0000a493,0x0000a49b,0x000124db,0x000124db},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0001249b,0x000126dc,0x000136e4,0x000126dc},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000124db,0x000136e4,0x0001b725,0x000136e4},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ },
+ { /* version 3, passes 1 */
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000},
+ {0x00000000,0x00000000,0x00000049,0x00000049,
+ 0x00000049,0x00000049,0x00000001,0x00000000},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x00000249,0x00000249,0x00000049,0x00000001},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x00000249,0x0000124a,0x00001252,0x00000001},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x0000124a,0x0000124a,0x00001252,0x00000009},
+ {0x00000000,0x00000000,0x00000249,0x00001249,
+ 0x0000124a,0x00009252,0x00009292,0x00000009},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x0000124a,0x00009252,0x00009292,0x00000049},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009252,0x00009252,0x00009292,0x00000049},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009252,0x00009493,0x00009292,0x0000024a},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009252,0x00009493,0x00009292,0x0000024a},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009252,0x00009493,0x00009493,0x00001252},
+ {0x00000000,0x00000000,0x00001249,0x0000924a,
+ 0x00009292,0x00009493,0x00009493,0x00001252},
+ {0x00000000,0x00000000,0x00001249,0x0000924a,
+ 0x00009492,0x00009493,0x00009493,0x00009292},
+ {0x00000000,0x00000000,0x00001249,0x00009252,
+ 0x00009492,0x0000a49b,0x00009493,0x00009292},
+ {0x00000000,0x00000000,0x0000924a,0x00009292,
+ 0x0000a493,0x000124db,0x0000a49b,0x00009493},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ }
+ },
+ { /* version 4 */
+ { /* version 4, passes 0 */
+ {0x00000000,0x00000000,0x00000049,0x00000049,
+ 0x00000049,0x00000049,0x0000024a,0x0000024a},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x00000249,0x0000124a,0x00001252,0x00009292},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x0000124a,0x00009252,0x00009292,0x00009292},
+ {0x00000000,0x00000000,0x00000249,0x00001249,
+ 0x0000124a,0x00009292,0x00009493,0x00009493},
+ {0x00000000,0x00000000,0x00000249,0x00001249,
+ 0x00009252,0x00009493,0x00009493,0x0000a49b},
+ {0x00000000,0x00000000,0x00000249,0x0000924a,
+ 0x00009292,0x00009493,0x0000a49b,0x0000a49b},
+ {0x00000000,0x00000000,0x00001249,0x0000924a,
+ 0x00009292,0x00009493,0x0000a49b,0x000124db},
+ {0x00000000,0x00000000,0x00001249,0x00009252,
+ 0x00009492,0x0000a49b,0x0000a49b,0x000124db},
+ {0x00000000,0x00000000,0x00001249,0x00009292,
+ 0x00009492,0x000124db,0x000124db,0x000126dc},
+ {0x00000000,0x00000000,0x00001249,0x00009292,
+ 0x0000a493,0x000124db,0x000126dc,0x000126dc},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x000124db,0x000126dc,0x000136e4},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x000126dc,0x000136e4,0x000136e4},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0001249b,0x000126dc,0x000136e4,0x000136e4},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000124db,0x000136e4,0x000136e4,0x0001b724},
+ {0x00000000,0x00000000,0x00009252,0x000124db,
+ 0x000126dc,0x0001b724,0x0001b725,0x0001b925},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ },
+ { /* version 4, passes 1 */
+ {0x00000000,0x00000000,0x00000049,0x00000049,
+ 0x00000049,0x00000049,0x00000049,0x00000049},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x00000249,0x00000249,0x0000024a,0x00000049},
+ {0x00000000,0x00000000,0x00001249,0x00000249,
+ 0x0000124a,0x0000124a,0x00001252,0x00000049},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x0000124a,0x0000124a,0x00009292,0x0000024a},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009252,0x00009292,0x00009292,0x0000024a},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009252,0x00009292,0x0000a49b,0x0000024a},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009292,0x00009493,0x0000a49b,0x00001252},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009292,0x00009493,0x0000a49b,0x00001252},
+ {0x00000000,0x00000000,0x00001249,0x0000924a,
+ 0x00009492,0x0000a49b,0x0000a49b,0x00001252},
+ {0x00000000,0x00000000,0x00001249,0x00009252,
+ 0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+ {0x00000000,0x00000000,0x00001249,0x00009292,
+ 0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x0000a49b,0x0000a49b,0x00009292},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x0000a49b,0x0000a49b,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x000124db,0x0000a49b,0x00009493},
+ {0x00000000,0x00000000,0x00009252,0x0000a49b,
+ 0x0001249b,0x000126dc,0x000124db,0x0000a49b},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ }
+ },
+ { /* version 5 */
+ { /* version 5, passes 0 */
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x00000249,0x0000124a,0x00001252,0x00009292},
+ {0x00000000,0x00000000,0x00000249,0x00001249,
+ 0x0000124a,0x00009292,0x00009292,0x00009493},
+ {0x00000000,0x00000000,0x00000249,0x0000924a,
+ 0x00009292,0x00009493,0x0000a49b,0x0000a49b},
+ {0x00000000,0x00000000,0x00001249,0x0000924a,
+ 0x00009292,0x00009493,0x0000a49b,0x0000a49b},
+ {0x00000000,0x00000000,0x00001249,0x0000924a,
+ 0x00009492,0x0000a49b,0x0000a49b,0x000124db},
+ {0x00000000,0x00000000,0x00001249,0x00009292,
+ 0x00009492,0x0000a49b,0x000124db,0x000124db},
+ {0x00000000,0x00000000,0x00001249,0x00009292,
+ 0x0000a493,0x000124db,0x000124db,0x000126dc},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x000124db,0x000126dc,0x000126dc},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x000126dc,0x000136e4,0x000136e4},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0001249b,0x000126dc,0x000136e4,0x000136e4},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0001249b,0x000126dc,0x000136e4,0x000136e4},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0001249b,0x000126dc,0x0001b725,0x0001b724},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000124db,0x000126dc,0x0001b725,0x0001b724},
+ {0x00000000,0x00000000,0x00009292,0x0000a49b,
+ 0x000126dc,0x000136e4,0x0001b92d,0x0001b925},
+ {0x00000000,0x00000000,0x00009492,0x000124db,
+ 0x000136e4,0x0001b724,0x0001c96e,0x0001c92d},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ },
+ { /* version 5, passes 1 */
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x0000124a,0x00000249,0x0000024a,0x0000024a},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x0000124a,0x0000124a,0x00001252,0x0000024a},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009292,0x00009493,0x00009493,0x0000024a},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009292,0x00009493,0x00009493,0x00001252},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009292,0x00009493,0x0000a49b,0x00001252},
+ {0x00000000,0x00000000,0x00001249,0x0000924a,
+ 0x00009492,0x00009493,0x000124db,0x00001252},
+ {0x00000000,0x00000000,0x00001249,0x00009292,
+ 0x00009492,0x00009493,0x000124db,0x00009292},
+ {0x00000000,0x00000000,0x00001249,0x00009292,
+ 0x00009492,0x0000a49b,0x000124db,0x00009292},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x0000a49b,0x000124db,0x00009292},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x000124db,0x000124db,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x000124db,0x000124db,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x000124db,0x000124db,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x000124db,0x000124db,0x0000a49b},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000124db,0x000126dc,0x000124db,0x0000a49b},
+ {0x00000000,0x00000000,0x00009252,0x000124db,
+ 0x000126dc,0x000136e4,0x000126dc,0x000124db},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ }
+ },
+ { /* version 6 */
+ { /* version 6, passes 0 */
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x0000124a,0x0000124a,0x00009292,0x00009292},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009292,0x00009493,0x0000a49b,0x0000a49b},
+ {0x00000000,0x00000000,0x00001249,0x0000924a,
+ 0x00009492,0x0000a49b,0x0000a49b,0x000124db},
+ {0x00000000,0x00000000,0x00001249,0x00009292,
+ 0x00009492,0x000124db,0x000126dc,0x000126dc},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x000124db,0x000126dc,0x000126dc},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x000126dc,0x000136e4,0x000136e4},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x000126dc,0x000136e4,0x0001b724},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0001249b,0x000126dc,0x000136e4,0x0001b724},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0001249b,0x000126dc,0x000136e4,0x0001b724},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0001249b,0x000136e4,0x0001b725,0x0001b724},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000124db,0x000136e4,0x0001b725,0x0001b925},
+ {0x00000000,0x00000000,0x00009292,0x0000a49b,
+ 0x000126dc,0x000136e4,0x0001b92d,0x0001b925},
+ {0x00000000,0x00000000,0x00009292,0x0000a49b,
+ 0x000126dc,0x0001b724,0x0001b92d,0x0001c92d},
+ {0x00000000,0x00000000,0x00009492,0x000124db,
+ 0x000126dc,0x0001b724,0x0001c96e,0x0001c92d},
+ {0x00000000,0x00000000,0x0000a492,0x000126db,
+ 0x000136e4,0x0001b925,0x00025bb6,0x00024b77},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ },
+ { /* version 6, passes 1 */
+ {0x00000000,0x00000000,0x00001249,0x00000249,
+ 0x0000124a,0x0000124a,0x00001252,0x00001252},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009252,0x00009292,0x00009292,0x00001252},
+ {0x00000000,0x00000000,0x00001249,0x0000924a,
+ 0x00009492,0x00009493,0x0000a49b,0x00001252},
+ {0x00000000,0x00000000,0x00001249,0x00009252,
+ 0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+ {0x00000000,0x00000000,0x00001249,0x00009292,
+ 0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x0000a49b,0x000126dc,0x00009292},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x0000a49b,0x000126dc,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x0000a49b,0x000126dc,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x000124db,0x000126dc,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0001249b,0x000126dc,0x000126dc,0x0000a49b},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000124db,0x000136e4,0x000126dc,0x000124db},
+ {0x00000000,0x00000000,0x00009492,0x0000a49b,
+ 0x000136e4,0x000136e4,0x000126dc,0x000124db},
+ {0x00000000,0x00000000,0x0000a492,0x000124db,
+ 0x0001b724,0x0001b724,0x000136e4,0x000126dc},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ }
+ },
+ { /* version 7 */
+ { /* version 7, passes 0 */
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009292,0x00009493,0x0000a49b,0x000124db},
+ {0x00000000,0x00000000,0x00001249,0x00009292,
+ 0x0000a493,0x0000a49b,0x000124db,0x000126dc},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x000124db,0x000126dc,0x000136e4},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x000124db,0x000136e4,0x000136e4},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0001249b,0x000126dc,0x000136e4,0x000136e4},
+ {0x00000000,0x00000000,0x00001249,0x0000a49b,
+ 0x0001249b,0x000126dc,0x000136e4,0x0001b724},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0001249b,0x000126dc,0x000136e4,0x0001b724},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000124db,0x000136e4,0x0001b725,0x0001b724},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000126dc,0x000136e4,0x0001b725,0x0001b925},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000126dc,0x0001b724,0x0001b92d,0x0001b925},
+ {0x00000000,0x00000000,0x00009292,0x0000a49b,
+ 0x000126dc,0x0001b724,0x0001c96e,0x0001c92d},
+ {0x00000000,0x00000000,0x00009292,0x000124db,
+ 0x000126dc,0x0001b724,0x0001c96e,0x0001c92d},
+ {0x00000000,0x00000000,0x00009492,0x000124db,
+ 0x000136e4,0x0001b724,0x0001c96e,0x0002496e},
+ {0x00000000,0x00000000,0x00009492,0x000126db,
+ 0x000136e4,0x0001b925,0x0001c96e,0x0002496e},
+ {0x00000000,0x00000000,0x0000a492,0x000136db,
+ 0x0001b724,0x0002496d,0x00025bb6,0x00025bbf},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ },
+ { /* version 7, passes 1 */
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009252,0x00009292,0x00009292,0x00009292},
+ {0x00000000,0x00000000,0x00001249,0x0000924a,
+ 0x00009492,0x00009493,0x00009493,0x00009292},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x0000a49b,0x0000a49b,0x00009292},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x0000a49b,0x000124db,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x000124db,0x000124db,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0000a493,0x000124db,0x000136e4,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0000a493,0x000124db,0x000136e4,0x0000a49b},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0001249b,0x000124db,0x000136e4,0x0000a49b},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0001249b,0x000126dc,0x000136e4,0x0000a49b},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0001249b,0x000126dc,0x000136e4,0x000124db},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000126dc,0x000136e4,0x000136e4,0x000124db},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000126dc,0x000136e4,0x000136e4,0x000124db},
+ {0x00000000,0x00000000,0x0000924a,0x000124db,
+ 0x000136e4,0x000136e4,0x000136e4,0x000126dc},
+ {0x00000000,0x00000000,0x0000a492,0x000124db,
+ 0x000136e4,0x0001b724,0x000136e4,0x000126dc},
+ {0x00000000,0x00000000,0x00012492,0x000126db,
+ 0x0001b724,0x0001b925,0x0001b725,0x000136e4},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ }
+ },
+ { /* version 8 */
+ { /* version 8, passes 0 */
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009292,0x00009493,0x0000a49b,0x000124db},
+ {0x00000000,0x00000000,0x00001249,0x00009292,
+ 0x0000a493,0x000124db,0x000126dc,0x000126dc},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x000124db,0x000126dc,0x000136e4},
+ {0x00000000,0x00000000,0x00001249,0x0000a49b,
+ 0x0001249b,0x000126dc,0x000136e4,0x0001b724},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0001249b,0x000126dc,0x000136e4,0x0001b724},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000124db,0x000136e4,0x0001b725,0x0001b724},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000126dc,0x000136e4,0x0001b725,0x0001b925},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000126dc,0x0001b724,0x0001b92d,0x0001c92d},
+ {0x00000000,0x00000000,0x00009252,0x000124db,
+ 0x000126dc,0x0001b724,0x0001b92d,0x0001c92d},
+ {0x00000000,0x00000000,0x00009292,0x000124db,
+ 0x000126dc,0x0001b925,0x0001c96e,0x0001c92d},
+ {0x00000000,0x00000000,0x00009492,0x000124db,
+ 0x000136e4,0x0001b925,0x0001c96e,0x0001c92d},
+ {0x00000000,0x00000000,0x00009492,0x000124db,
+ 0x000136e4,0x0001b925,0x00024b76,0x00024b77},
+ {0x00000000,0x00000000,0x00009492,0x000126db,
+ 0x000136e4,0x0001b925,0x00024b76,0x00025bbf},
+ {0x00000000,0x00000000,0x0000a492,0x000126db,
+ 0x000136e4,0x0001c92d,0x00024b76,0x00025bbf},
+ {0x00000000,0x00000000,0x00012492,0x000136db,
+ 0x0001b724,0x00024b6d,0x0002ddb6,0x0002efff},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ },
+ { /* version 8, passes 1 */
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009252,0x00009493,0x00009493,0x00009493},
+ {0x00000000,0x00000000,0x00001249,0x00009292,
+ 0x0000a493,0x0000a49b,0x0000a49b,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x0000a49b,0x000124db,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0000a493,0x000124db,0x000136e4,0x000124db},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0001249b,0x000126dc,0x000136e4,0x000124db},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000126dc,0x000126dc,0x000136e4,0x000126dc},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000126dc,0x000136e4,0x000136e4,0x000126dc},
+ {0x00000000,0x00000000,0x0000924a,0x000124db,
+ 0x000126dc,0x000136e4,0x000136e4,0x000126dc},
+ {0x00000000,0x00000000,0x0000924a,0x000124db,
+ 0x000126dc,0x000136e4,0x000136e4,0x000136e4},
+ {0x00000000,0x00000000,0x00009292,0x000124db,
+ 0x000136e4,0x0001b724,0x0001b725,0x000136e4},
+ {0x00000000,0x00000000,0x00009492,0x000126db,
+ 0x000136e4,0x0001b925,0x0001b725,0x0001b724},
+ {0x00000000,0x00000000,0x00009492,0x000126db,
+ 0x000136e4,0x0001b925,0x0001b725,0x0001b724},
+ {0x00000000,0x00000000,0x0000a492,0x000136db,
+ 0x0001b724,0x0002496d,0x0001b92d,0x0001b925},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ }
+ },
+ { /* version 9 */
+ { /* version 9, passes 0 */
+ {0x00000000,0x00000000,0x00000049,0x00000049,
+ 0x00000049,0x00000049,0x00000049,0x00000049},
+ {0x00000000,0x00000000,0x00000249,0x00000049,
+ 0x00000249,0x00000249,0x0000024a,0x00000049},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x0000124a,0x00009252,0x00001252,0x0000024a},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009252,0x00009292,0x00009493,0x00001252},
+ {0x00000000,0x00000000,0x00001249,0x0000924a,
+ 0x00009292,0x00009493,0x00009493,0x00001252},
+ {0x00000000,0x00000000,0x00001249,0x00009292,
+ 0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x000124db,0x000124db,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0001249b,0x000126dc,0x000126dc,0x000124db},
+ {0x00000000,0x00000000,0x00009252,0x00009493,
+ 0x000124db,0x000136e4,0x000136e4,0x000126dc},
+ {0x00000000,0x00000000,0x00009252,0x0000a49b,
+ 0x000124db,0x000136e4,0x000136e4,0x000126dc},
+ {0x00000000,0x00000000,0x00009292,0x0000a49b,
+ 0x000126dc,0x000136e4,0x000136e4,0x000136e4},
+ {0x00000000,0x00000000,0x00009492,0x0000a49b,
+ 0x000126dc,0x0001b724,0x0001b725,0x0001b724},
+ {0x00000000,0x00000000,0x0000a492,0x000124db,
+ 0x000136e4,0x0001b925,0x0001b92d,0x0001b925},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ },
+ { /* version 9, passes 1 */
+ {0x00000000,0x00000000,0x00000249,0x00000049,
+ 0x00000009,0x00000009,0x00000009,0x00000009},
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x00000049,0x00000049,0x00000009,0x00000009},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x0000124a,0x00000249,0x00000049,0x00000049},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x0000124a,0x0000124a,0x00000049,0x00000049},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009252,0x0000124a,0x0000024a,0x0000024a},
+ {0x00000000,0x00000000,0x00001249,0x0000924a,
+ 0x00009252,0x0000124a,0x0000024a,0x0000024a},
+ {0x00000000,0x00000000,0x00001249,0x00009292,
+ 0x00009492,0x00009252,0x00001252,0x00001252},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x00009292,0x00009292,0x00001252},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x00009292,0x00009292,0x00009292},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x00009493,0x00009493,0x00009292},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0000a493,0x0000a49b,0x00009493,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0000a493,0x0000a49b,0x0000a49b,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0001249b,0x000124db,0x0000a49b,0x0000a49b},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+ {0x00000000,0x00000000,0x00009252,0x000124db,
+ 0x0001b724,0x000136e4,0x000126dc,0x000124db},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ }
+ },
+ { /* version 10 */
+ { /* version 10, passes 0 */
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x00000249,0x00000249,0x0000024a,0x0000024a},
+ {0x00000000,0x00000000,0x00000249,0x00001249,
+ 0x00009252,0x00009292,0x00009292,0x0000024a},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009252,0x00009292,0x00009292,0x00001252},
+ {0x00000000,0x00000000,0x00001249,0x0000924a,
+ 0x00009492,0x00009493,0x0000a49b,0x00009292},
+ {0x00000000,0x00000000,0x00001249,0x00009292,
+ 0x00009492,0x000124db,0x000124db,0x00009292},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x000124db,0x000124db,0x00009493},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x000124db,0x000126dc,0x000124db},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0001249b,0x000126dc,0x000126dc,0x000124db},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000124db,0x000126dc,0x000136e4,0x000126dc},
+ {0x00000000,0x00000000,0x00009252,0x0000a49b,
+ 0x000124db,0x000136e4,0x000136e4,0x000136e4},
+ {0x00000000,0x00000000,0x00009292,0x0000a49b,
+ 0x000126dc,0x000136e4,0x000136e4,0x000136e4},
+ {0x00000000,0x00000000,0x00009492,0x0000a49b,
+ 0x000126dc,0x0001b724,0x0001b92d,0x0001b724},
+ {0x00000000,0x00000000,0x00009492,0x000124db,
+ 0x000126dc,0x0001b925,0x0001b92d,0x0001b925},
+ {0x00000000,0x00000000,0x0000a492,0x000126db,
+ 0x000136e4,0x0002496d,0x0001c96e,0x0001c92d},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ },
+ { /* version 10, passes 1 */
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x00000049,0x00000049,0x00000049,0x00000049},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x0000124a,0x00000249,0x00000049,0x00000049},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x0000124a,0x00009252,0x0000024a,0x00000049},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009252,0x00009493,0x0000024a,0x0000024a},
+ {0x00000000,0x00000000,0x00001249,0x00009252,
+ 0x00009492,0x00009493,0x00001252,0x0000024a},
+ {0x00000000,0x00000000,0x00001249,0x00009292,
+ 0x00009492,0x00009493,0x00001252,0x00001252},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x00009492,0x00009493,0x00009292,0x00001252},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x00009493,0x00009292,0x00009292},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x0000a49b,0x00009493,0x00009292},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x0000a49b,0x00009493,0x00009292},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0000a493,0x000124db,0x0000a49b,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0000a493,0x000124db,0x0000a49b,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x000124db,
+ 0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+ {0x00000000,0x00000000,0x0000924a,0x000124db,
+ 0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+ {0x00000000,0x00000000,0x00009252,0x000126db,
+ 0x0001b724,0x000136e4,0x000126dc,0x000124db},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ }
+ },
+ { /* version 11 */
+ { /* version 11, passes 0 */
+ {0x00000000,0x00000000,0x00000249,0x00000249,
+ 0x00000249,0x00000249,0x00001252,0x00001252},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009252,0x00009292,0x00009292,0x00001252},
+ {0x00000000,0x00000000,0x00001249,0x0000924a,
+ 0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x0000a49b,0x000124db,0x00009493},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x000124db,0x000126dc,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x000126dc,0x000126dc,0x0000a49b},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0001249b,0x000126dc,0x000136e4,0x000124db},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000126dc,0x000136e4,0x000136e4,0x000126dc},
+ {0x00000000,0x00000000,0x00009292,0x0000a49b,
+ 0x000126dc,0x000136e4,0x000136e4,0x000126dc},
+ {0x00000000,0x00000000,0x00009292,0x0000a49b,
+ 0x000126dc,0x0001b724,0x0001b725,0x000136e4},
+ {0x00000000,0x00000000,0x00009292,0x0000a49b,
+ 0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
+ {0x00000000,0x00000000,0x00009492,0x0000a49b,
+ 0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
+ {0x00000000,0x00000000,0x00009492,0x000124db,
+ 0x000136e4,0x0001b925,0x0001c96e,0x0001b925},
+ {0x00000000,0x00000000,0x00009492,0x000124db,
+ 0x0001b724,0x0001b925,0x0001c96e,0x0001c92d},
+ {0x00000000,0x00000000,0x0000a492,0x000126db,
+ 0x0001c924,0x0002496d,0x00025bb6,0x00024b77},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ },
+ { /* version 11, passes 1 */
+ {0x00000000,0x00000000,0x00001249,0x00000249,
+ 0x00000249,0x00000249,0x0000024a,0x0000024a},
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x0000124a,0x0000124a,0x0000024a,0x0000024a},
+ {0x00000000,0x00000000,0x00001249,0x0000924a,
+ 0x00009252,0x00009252,0x0000024a,0x0000024a},
+ {0x00000000,0x00000000,0x00001249,0x00009292,
+ 0x00009492,0x0000a49b,0x00001252,0x00001252},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x0000a49b,0x00001252,0x00001252},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x0000a49b,0x00009292,0x00001252},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0000a493,0x0000a49b,0x00009292,0x00009292},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0000a493,0x0000a49b,0x00009493,0x00009292},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0001249b,0x000124db,0x00009493,0x00009292},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0001249b,0x000124db,0x00009493,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000124db,0x000124db,0x0000a49b,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x000124db,
+ 0x000126dc,0x000126dc,0x0000a49b,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x000124db,
+ 0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+ {0x00000000,0x00000000,0x00009292,0x000124db,
+ 0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+ {0x00000000,0x00000000,0x00009492,0x000126db,
+ 0x0001b724,0x000136e4,0x000126dc,0x000124db},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ }
+ },
+ { /* version 12 */
+ { /* version 12, passes 0 */
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009252,0x00009292,0x00009493,0x00009493},
+ {0x00000000,0x00000000,0x00001249,0x00009292,
+ 0x0000a493,0x0000a49b,0x0000a49b,0x00009493},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x000124db,0x000124db,0x0000a49b},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x000126dc,0x000126dc,0x0000a49b},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0001249b,0x000126dc,0x000136e4,0x000124db},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000126dc,0x000136e4,0x000136e4,0x000126dc},
+ {0x00000000,0x00000000,0x00009292,0x0000a49b,
+ 0x000126dc,0x0001b724,0x0001b725,0x000126dc},
+ {0x00000000,0x00000000,0x00009292,0x0000a49b,
+ 0x000136e4,0x0001b724,0x0001b92d,0x000136e4},
+ {0x00000000,0x00000000,0x00009492,0x0000a49b,
+ 0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
+ {0x00000000,0x00000000,0x00009492,0x000124db,
+ 0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
+ {0x00000000,0x00000000,0x00009492,0x000124db,
+ 0x000136e4,0x0001b925,0x0001b92d,0x0001b925},
+ {0x00000000,0x00000000,0x00009492,0x000124db,
+ 0x0001b724,0x0001b925,0x0001c96e,0x0001c92d},
+ {0x00000000,0x00000000,0x0000a492,0x000124db,
+ 0x0001b724,0x0001c92d,0x0001c96e,0x0001c92d},
+ {0x00000000,0x00000000,0x0000a492,0x000124db,
+ 0x0001b724,0x0001c92d,0x00024b76,0x0002496e},
+ {0x00000000,0x00000000,0x00012492,0x000126db,
+ 0x0001c924,0x00024b6d,0x0002ddb6,0x00025bbf},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ },
+ { /* version 12, passes 1 */
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x0000124a,0x0000124a,0x00001252,0x00001252},
+ {0x00000000,0x00000000,0x00001249,0x00009292,
+ 0x00009492,0x00009252,0x00001252,0x00001252},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x00009292,0x00001252,0x00001252},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0000a493,0x0000a49b,0x00009292,0x00009292},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0000a493,0x0000a49b,0x00009292,0x00009292},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0001249b,0x0000a49b,0x00009493,0x00009292},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000124db,0x000124db,0x00009493,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000124db,0x000124db,0x0000a49b,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x000124db,
+ 0x000126dc,0x000124db,0x0000a49b,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x000124db,
+ 0x000126dc,0x000126dc,0x0000a49b,0x0000a49b},
+ {0x00000000,0x00000000,0x0000924a,0x000124db,
+ 0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+ {0x00000000,0x00000000,0x00009492,0x000126db,
+ 0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+ {0x00000000,0x00000000,0x00009492,0x000126db,
+ 0x0001b724,0x000136e4,0x000126dc,0x000124db},
+ {0x00000000,0x00000000,0x00009492,0x000126db,
+ 0x0001b724,0x000136e4,0x000126dc,0x000124db},
+ {0x00000000,0x00000000,0x0000a492,0x000136db,
+ 0x0001c924,0x0001b724,0x000136e4,0x000126dc},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ }
+ },
+ { /* version 13 */
+ { /* version 13, passes 0 */
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x00009252,0x00009292,0x00009493,0x00009493},
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x000124db,0x000126dc,0x00009493},
+ {0x00000000,0x00000000,0x00001249,0x0000a49b,
+ 0x0001249b,0x000126dc,0x000126dc,0x0000a49b},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0001249b,0x000126dc,0x000136e4,0x0000a49b},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000126dc,0x000136e4,0x0001b725,0x000124db},
+ {0x00000000,0x00000000,0x00009292,0x0000a49b,
+ 0x000136e4,0x0001b724,0x0001b725,0x000126dc},
+ {0x00000000,0x00000000,0x00009292,0x000124db,
+ 0x000136e4,0x0001b724,0x0001b725,0x000126dc},
+ {0x00000000,0x00000000,0x00009492,0x000124db,
+ 0x000136e4,0x0001b724,0x0001c96e,0x000136e4},
+ {0x00000000,0x00000000,0x00009492,0x000124db,
+ 0x000136e4,0x0001c92d,0x0001c96e,0x0001b724},
+ {0x00000000,0x00000000,0x0000a492,0x000124db,
+ 0x000136e4,0x0001c92d,0x0001c96e,0x0001b724},
+ {0x00000000,0x00000000,0x0000a492,0x000124db,
+ 0x0001b724,0x0001c92d,0x0001c96e,0x0001b925},
+ {0x00000000,0x00000000,0x0000a492,0x000126db,
+ 0x0001b724,0x0001c92d,0x00024b76,0x0001c92d},
+ {0x00000000,0x00000000,0x0000a492,0x000126db,
+ 0x0001b924,0x0001c92d,0x00024b76,0x0001c92d},
+ {0x00000000,0x00000000,0x0000a492,0x000126db,
+ 0x0001b924,0x0001c92d,0x00024b76,0x0002496e},
+ {0x00000000,0x00000000,0x00012492,0x000136db,
+ 0x00024924,0x00024b6d,0x0002ddb6,0x00025bbf},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ },
+ { /* version 13, passes 1 */
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x0000124a,0x0000124a,0x00001252,0x00001252},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x00009492,0x00009292,0x00001252,0x00001252},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0000a493,0x0000a49b,0x00001252,0x00001252},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0000a493,0x0000a49b,0x00009292,0x00009292},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0000a493,0x0000a49b,0x00009292,0x00009292},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000126dc,0x0000a49b,0x00009493,0x00009292},
+ {0x00000000,0x00000000,0x0000924a,0x000124db,
+ 0x000126dc,0x000124db,0x00009493,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x000124db,
+ 0x000136e4,0x000124db,0x0000a49b,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x000136db,
+ 0x0001b724,0x000124db,0x0000a49b,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x000136db,
+ 0x0001b724,0x000126dc,0x0000a49b,0x0000a49b},
+ {0x00000000,0x00000000,0x00009292,0x000136db,
+ 0x0001b724,0x000126dc,0x000124db,0x0000a49b},
+ {0x00000000,0x00000000,0x00009492,0x000136db,
+ 0x0001b724,0x000126dc,0x000124db,0x0000a49b},
+ {0x00000000,0x00000000,0x0000a492,0x000136db,
+ 0x0001b724,0x000136e4,0x000126dc,0x000124db},
+ {0x00000000,0x00000000,0x0000a492,0x000136db,
+ 0x0001b724,0x000136e4,0x000126dc,0x000124db},
+ {0x00000000,0x00000000,0x00012492,0x0001b6db,
+ 0x0001c924,0x0001b724,0x000136e4,0x000126dc},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ }
+ },
+ { /* version 14 */
+ { /* version 14, passes 0 */
+ {0x00000000,0x00000000,0x00001249,0x0000924a,
+ 0x00009292,0x00009493,0x00009493,0x00009493},
+ {0x00000000,0x00000000,0x00001249,0x0000a49b,
+ 0x0000a493,0x000124db,0x000126dc,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0001249b,0x000126dc,0x000136e4,0x0000a49b},
+ {0x00000000,0x00000000,0x0000924a,0x000124db,
+ 0x000126dc,0x000136e4,0x0001b725,0x000124db},
+ {0x00000000,0x00000000,0x00009292,0x000124db,
+ 0x000126dc,0x0001b724,0x0001b92d,0x000126dc},
+ {0x00000000,0x00000000,0x00009492,0x000124db,
+ 0x000136e4,0x0001b724,0x0001b92d,0x000126dc},
+ {0x00000000,0x00000000,0x00009492,0x000124db,
+ 0x000136e4,0x0001c92d,0x0001c96e,0x000136e4},
+ {0x00000000,0x00000000,0x00009492,0x000124db,
+ 0x0001b724,0x0001c92d,0x0001c96e,0x0001b724},
+ {0x00000000,0x00000000,0x0000a492,0x000124db,
+ 0x0001b724,0x0001c92d,0x00024b76,0x0001b925},
+ {0x00000000,0x00000000,0x0000a492,0x000126db,
+ 0x0001b724,0x0001c92d,0x00024b76,0x0001c92d},
+ {0x00000000,0x00000000,0x0000a492,0x000126db,
+ 0x0001b724,0x0001c92d,0x00024b76,0x0001c92d},
+ {0x00000000,0x00000000,0x0000a492,0x000136db,
+ 0x0001b724,0x0001c92d,0x00024b76,0x0002496e},
+ {0x00000000,0x00000000,0x0000a492,0x000136db,
+ 0x0001b924,0x0002496d,0x00024b76,0x00024b77},
+ {0x00000000,0x00000000,0x0000a492,0x000136db,
+ 0x0001b924,0x00024b6d,0x0002ddb6,0x00025bbf},
+ {0x00000000,0x00000000,0x00012492,0x0001b6db,
+ 0x00024924,0x0002db6d,0x00036db6,0x0002efff},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ },
+ { /* version 14, passes 1 */
+ {0x00000000,0x00000000,0x00001249,0x00001249,
+ 0x0000124a,0x0000124a,0x00001252,0x00001252},
+ {0x00000000,0x00000000,0x0000924a,0x00009493,
+ 0x0000a493,0x00009292,0x00001252,0x00001252},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0000a493,0x0000a49b,0x00001252,0x00001252},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0001249b,0x000136e4,0x00009292,0x00009292},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0001249b,0x000136e4,0x00009292,0x00009292},
+ {0x00000000,0x00000000,0x0000924a,0x000124db,
+ 0x000136e4,0x000136e4,0x00009493,0x00009292},
+ {0x00000000,0x00000000,0x00009492,0x000136db,
+ 0x0001b724,0x000136e4,0x00009493,0x00009493},
+ {0x00000000,0x00000000,0x00009492,0x000136db,
+ 0x0001b724,0x000136e4,0x0000a49b,0x00009493},
+ {0x00000000,0x00000000,0x00009492,0x000136db,
+ 0x0001b724,0x000136e4,0x0000a49b,0x00009493},
+ {0x00000000,0x00000000,0x00009492,0x000136db,
+ 0x0001b724,0x000136e4,0x0000a49b,0x0000a49b},
+ {0x00000000,0x00000000,0x0000a492,0x000136db,
+ 0x0001b724,0x000136e4,0x000124db,0x0000a49b},
+ {0x00000000,0x00000000,0x0000a492,0x000136db,
+ 0x0001b724,0x000136e4,0x000124db,0x0000a49b},
+ {0x00000000,0x00000000,0x0000a492,0x000136db,
+ 0x0001b724,0x000136e4,0x000126dc,0x000124db},
+ {0x00000000,0x00000000,0x0000a492,0x000136db,
+ 0x0001b724,0x000136e4,0x000126dc,0x000124db},
+ {0x00000000,0x00000000,0x00012492,0x0001b6db,
+ 0x0001c924,0x0001b724,0x000136e4,0x000126dc},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ }
+ },
+ { /* version 15 */
+ { /* version 15, passes 0 */
+ {0x00000000,0x00000000,0x00001249,0x00009493,
+ 0x0000a493,0x0000a49b,0x000124db,0x000124db},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0001249b,0x000126dc,0x000136e4,0x000124db},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x000126dc,0x0001b724,0x0001b725,0x000126dc},
+ {0x00000000,0x00000000,0x0000924a,0x000124db,
+ 0x000136e4,0x0001b724,0x0001b92d,0x000126dc},
+ {0x00000000,0x00000000,0x00009492,0x000124db,
+ 0x000136e4,0x0001b925,0x0001c96e,0x000136e4},
+ {0x00000000,0x00000000,0x00009492,0x000124db,
+ 0x0001b724,0x0001c92d,0x0001c96e,0x0001b724},
+ {0x00000000,0x00000000,0x0000a492,0x000124db,
+ 0x0001b724,0x0001c92d,0x0001c96e,0x0001b724},
+ {0x00000000,0x00000000,0x0000a492,0x000126db,
+ 0x0001b724,0x0001c92d,0x0001c96e,0x0001b925},
+ {0x00000000,0x00000000,0x0000a492,0x000126db,
+ 0x0001b924,0x0001c92d,0x00024b76,0x0001c92d},
+ {0x00000000,0x00000000,0x0000a492,0x000136db,
+ 0x0001b924,0x0001c92d,0x00024b76,0x0001c92d},
+ {0x00000000,0x00000000,0x0000a492,0x000136db,
+ 0x0001b924,0x0002496d,0x00024b76,0x0002496e},
+ {0x00000000,0x00000000,0x0000a492,0x000136db,
+ 0x0001c924,0x0002496d,0x00025bb6,0x00024b77},
+ {0x00000000,0x00000000,0x0000a492,0x000136db,
+ 0x0001c924,0x00024b6d,0x00025bb6,0x00024b77},
+ {0x00000000,0x00000000,0x00012492,0x000136db,
+ 0x0001c924,0x00024b6d,0x0002ddb6,0x00025bbf},
+ {0x00000000,0x00000000,0x00012492,0x0001b6db,
+ 0x00024924,0x0002db6d,0x00036db6,0x0002efff},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ },
+ { /* version 15, passes 1 */
+ {0x00000000,0x00000000,0x0000924a,0x0000924a,
+ 0x00009292,0x00009292,0x00009292,0x00009292},
+ {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+ 0x0000a493,0x000124db,0x00009292,0x00009292},
+ {0x00000000,0x00000000,0x0000924a,0x000124db,
+ 0x000124db,0x0001b724,0x00009493,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x000124db,
+ 0x000126dc,0x0001b724,0x00009493,0x00009493},
+ {0x00000000,0x00000000,0x0000924a,0x000124db,
+ 0x000136e4,0x0001b724,0x0000a49b,0x0000a49b},
+ {0x00000000,0x00000000,0x00009292,0x000136db,
+ 0x0001b724,0x0001b724,0x0000a49b,0x0000a49b},
+ {0x00000000,0x00000000,0x00009492,0x000136db,
+ 0x0001c924,0x0001b724,0x000124db,0x000124db},
+ {0x00000000,0x00000000,0x00009492,0x000136db,
+ 0x0001c924,0x0001b724,0x000124db,0x000124db},
+ {0x00000000,0x00000000,0x0000a492,0x000136db,
+ 0x0001c924,0x0001b724,0x000126dc,0x000126dc},
+ {0x00000000,0x00000000,0x0000a492,0x000136db,
+ 0x0001c924,0x0001b925,0x000126dc,0x000126dc},
+ {0x00000000,0x00000000,0x0000a492,0x000136db,
+ 0x0001c924,0x0001b925,0x000136e4,0x000136e4},
+ {0x00000000,0x00000000,0x0000a492,0x000136db,
+ 0x0001c924,0x0001b925,0x000136e4,0x000136e4},
+ {0x00000000,0x00000000,0x0000a492,0x000136db,
+ 0x0001c924,0x0001b925,0x0001b725,0x0001b724},
+ {0x00000000,0x00000000,0x00012492,0x000136db,
+ 0x0001c924,0x0001b925,0x0001b725,0x0001b724},
+ {0x00000000,0x00000000,0x00012492,0x0001b6db,
+ 0x00024924,0x0002496d,0x0001b92d,0x0001b925},
+ {0x00000000,0x00000000,0x00000000,0x00000000,
+ 0x00000000,0x00000000,0x00000000,0x00000000}
+ }
+ }
+};
diff --git a/drivers/usb/media/pwc/pwc-timon.h b/drivers/usb/media/pwc/pwc-timon.h
new file mode 100644
index 0000000000000..a86b3782a081f
--- /dev/null
+++ b/drivers/usb/media/pwc/pwc-timon.h
@@ -0,0 +1,61 @@
+/* Linux driver for Philips webcam
+ (C) 2004 Luc Saillard (luc@saillard.org)
+
+ NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+ driver and thus may have bugs that are not present in the original version.
+ Please send bug reports and support requests to <luc@saillard.org>.
+ The decompression routines have been implemented by reverse-engineering the
+ Nemosoft binary pwcx module. Caveat emptor.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the 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 tables contains entries for the 675/680/690 (Timon) camera, with
+ 4 different qualities (no compression, low, medium, high).
+ It lists the bandwidth requirements for said mode by its alternate interface
+ number. An alternate of 0 means that the mode is unavailable.
+
+ There are 6 * 4 * 4 entries:
+ 6 different resolutions subqcif, qsif, qcif, sif, cif, vga
+ 6 framerates: 5, 10, 15, 20, 25, 30
+ 4 compression modi: none, low, medium, high
+
+ When an uncompressed mode is not available, the next available compressed mode
+ will be chosen (unless the decompressor is absent). Sometimes there are only
+ 1 or 2 compressed modes available; in that case entries are duplicated.
+*/
+
+#ifndef PWC_TIMON_H
+#define PWC_TIMON_H
+
+#include "pwc-ioctl.h"
+
+struct Timon_table_entry
+{
+ char alternate; /* USB alternate interface */
+ unsigned short packetsize; /* Normal packet size */
+ unsigned short bandlength; /* Bandlength when decompressing */
+ unsigned char mode[13]; /* precomputed mode settings for cam */
+};
+
+const extern struct Timon_table_entry Timon_table[PSZ_MAX][6][4];
+const extern unsigned int TimonRomTable [16][2][16][8];
+
+
+#endif
+
+
diff --git a/drivers/usb/media/pwc/pwc-uncompress.c b/drivers/usb/media/pwc/pwc-uncompress.c
new file mode 100644
index 0000000000000..c062e43b3ac56
--- /dev/null
+++ b/drivers/usb/media/pwc/pwc-uncompress.c
@@ -0,0 +1,147 @@
+/* Linux driver for Philips webcam
+ Decompression frontend.
+ (C) 1999-2003 Nemosoft Unv.
+ (C) 2004 Luc Saillard (luc@saillard.org)
+
+ NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+ driver and thus may have bugs that are not present in the original version.
+ Please send bug reports and support requests to <luc@saillard.org>.
+ The decompression routines have been implemented by reverse-engineering the
+ Nemosoft binary pwcx module. Caveat emptor.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the 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/current.h>
+#include <asm/types.h>
+
+#include "pwc.h"
+#include "pwc-uncompress.h"
+#include "pwc-dec1.h"
+#include "pwc-dec23.h"
+
+int pwc_decompress(struct pwc_device *pdev)
+{
+ struct pwc_frame_buf *fbuf;
+ int n, line, col, stride;
+ void *yuv, *image;
+ u16 *src;
+ u16 *dsty, *dstu, *dstv;
+
+ if (pdev == NULL)
+ return -EFAULT;
+#if defined(__KERNEL__) && defined(PWC_MAGIC)
+ if (pdev->magic != PWC_MAGIC) {
+ Err("pwc_decompress(): magic failed.\n");
+ return -EFAULT;
+ }
+#endif
+
+ fbuf = pdev->read_frame;
+ if (fbuf == NULL)
+ return -EFAULT;
+ image = pdev->image_ptr[pdev->fill_image];
+ if (!image)
+ return -EFAULT;
+
+ yuv = fbuf->data + pdev->frame_header_size; /* Skip header */
+
+ /* Raw format; that's easy... */
+ if (pdev->vpalette == VIDEO_PALETTE_RAW)
+ {
+ memcpy(image, yuv, pdev->frame_size);
+ return 0;
+ }
+
+ if (pdev->vbandlength == 0) {
+ /* Uncompressed mode. We copy the data into the output buffer,
+ using the viewport size (which may be larger than the image
+ size). Unfortunately we have to do a bit of byte stuffing
+ to get the desired output format/size.
+ */
+ /*
+ * We do some byte shuffling here to go from the
+ * native format to YUV420P.
+ */
+ src = (u16 *)yuv;
+ n = pdev->view.x * pdev->view.y;
+
+ /* offset in Y plane */
+ stride = pdev->view.x * pdev->offset.y + pdev->offset.x;
+ dsty = (u16 *)(image + stride);
+
+ /* offsets in U/V planes */
+ stride = pdev->view.x * pdev->offset.y / 4 + pdev->offset.x / 2;
+ dstu = (u16 *)(image + n + stride);
+ dstv = (u16 *)(image + n + n / 4 + stride);
+
+ /* increment after each line */
+ stride = (pdev->view.x - pdev->image.x) / 2; /* u16 is 2 bytes */
+
+ for (line = 0; line < pdev->image.y; line++) {
+ for (col = 0; col < pdev->image.x; col += 4) {
+ *dsty++ = *src++;
+ *dsty++ = *src++;
+ if (line & 1)
+ *dstv++ = *src++;
+ else
+ *dstu++ = *src++;
+ }
+ dsty += stride;
+ if (line & 1)
+ dstv += (stride >> 1);
+ else
+ dstu += (stride >> 1);
+ }
+ }
+ else {
+ /* Compressed; the decompressor routines will write the data
+ in planar format immediately.
+ */
+ int flags;
+
+ flags = PWCX_FLAG_PLANAR;
+ if (pdev->vsize == PSZ_VGA && pdev->vframes == 5 && pdev->vsnapshot)
+ {
+ printk(KERN_ERR "pwc: Mode Bayer is not supported for now\n");
+ flags |= PWCX_FLAG_BAYER;
+ return -ENXIO; /* No such device or address: missing decompressor */
+ }
+
+ switch (pdev->type)
+ {
+ case 675:
+ case 680:
+ case 690:
+ case 720:
+ case 730:
+ case 740:
+ case 750:
+ pwc_dec23_decompress(&pdev->image, &pdev->view, &pdev->offset,
+ yuv, image,
+ flags,
+ pdev->decompress_data, pdev->vbandlength);
+ break;
+ case 645:
+ case 646:
+ /* TODO & FIXME */
+ return -ENXIO; /* No such device or address: missing decompressor */
+ break;
+ }
+ }
+ return 0;
+}
+
+
diff --git a/drivers/usb/media/pwc/pwc-uncompress.h b/drivers/usb/media/pwc/pwc-uncompress.h
new file mode 100644
index 0000000000000..d3b9250e4ed32
--- /dev/null
+++ b/drivers/usb/media/pwc/pwc-uncompress.h
@@ -0,0 +1,41 @@
+/* (C) 1999-2003 Nemosoft Unv.
+ (C) 2004 Luc Saillard (luc@saillard.org)
+
+ NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+ driver and thus may have bugs that are not present in the original version.
+ Please send bug reports and support requests to <luc@saillard.org>.
+ The decompression routines have been implemented by reverse-engineering the
+ Nemosoft binary pwcx module. Caveat emptor.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the 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 is the bridge between the kernel module and the plugin; it
+ describes the structures and datatypes used in both modules. Any
+ significant change should be reflected by increasing the
+ pwc_decompressor_version major number.
+ */
+#ifndef PWC_UNCOMPRESS_H
+#define PWC_UNCOMPRESS_H
+
+#include <linux/config.h>
+
+#include "pwc-ioctl.h"
+
+/* from pwc-dec.h */
+#define PWCX_FLAG_PLANAR 0x0001
+/* */
+
+#endif
diff --git a/drivers/usb/media/pwc/pwc.h b/drivers/usb/media/pwc/pwc.h
new file mode 100644
index 0000000000000..53b516d29cf56
--- /dev/null
+++ b/drivers/usb/media/pwc/pwc.h
@@ -0,0 +1,278 @@
+/* (C) 1999-2003 Nemosoft Unv.
+ (C) 2004 Luc Saillard (luc@saillard.org)
+
+ NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+ driver and thus may have bugs that are not present in the original version.
+ Please send bug reports and support requests to <luc@saillard.org>.
+ The decompression routines have been implemented by reverse-engineering the
+ Nemosoft binary pwcx module. Caveat emptor.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the 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 PWC_H
+#define PWC_H
+
+#include <linux/version.h>
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/spinlock.h>
+#include <linux/videodev.h>
+#include <linux/wait.h>
+#include <linux/smp_lock.h>
+#include <asm/semaphore.h>
+#include <asm/errno.h>
+
+#include "pwc-uncompress.h"
+#include "pwc-ioctl.h"
+
+/* Defines and structures for the Philips webcam */
+/* Used for checking memory corruption/pointer validation */
+#define PWC_MAGIC 0x89DC10ABUL
+#undef PWC_MAGIC
+
+/* Turn some debugging options on/off */
+#define PWC_DEBUG 0
+
+/* Trace certain actions in the driver */
+#define TRACE_MODULE 0x0001
+#define TRACE_PROBE 0x0002
+#define TRACE_OPEN 0x0004
+#define TRACE_READ 0x0008
+#define TRACE_MEMORY 0x0010
+#define TRACE_FLOW 0x0020
+#define TRACE_SIZE 0x0040
+#define TRACE_PWCX 0x0080
+#define TRACE_SEQUENCE 0x1000
+
+#define Trace(R, A...) if (pwc_trace & R) printk(KERN_DEBUG PWC_NAME " " A)
+#define Debug(A...) printk(KERN_DEBUG PWC_NAME " " A)
+#define Info(A...) printk(KERN_INFO PWC_NAME " " A)
+#define Err(A...) printk(KERN_ERR PWC_NAME " " A)
+
+
+/* Defines for ToUCam cameras */
+#define TOUCAM_HEADER_SIZE 8
+#define TOUCAM_TRAILER_SIZE 4
+
+#define FEATURE_MOTOR_PANTILT 0x0001
+
+/* Version block */
+#define PWC_MAJOR 9
+#define PWC_MINOR 0
+#define PWC_VERSION "9.0.2-unofficial"
+#define PWC_NAME "pwc"
+
+/* Turn certain features on/off */
+#define PWC_INT_PIPE 0
+
+/* Ignore errors in the first N frames, to allow for startup delays */
+#define FRAME_LOWMARK 5
+
+/* Size and number of buffers for the ISO pipe. */
+#define MAX_ISO_BUFS 2
+#define ISO_FRAMES_PER_DESC 10
+#define ISO_MAX_FRAME_SIZE 960
+#define ISO_BUFFER_SIZE (ISO_FRAMES_PER_DESC * ISO_MAX_FRAME_SIZE)
+
+/* Frame buffers: contains compressed or uncompressed video data. */
+#define MAX_FRAMES 5
+/* Maximum size after decompression is 640x480 YUV data, 1.5 * 640 * 480 */
+#define PWC_FRAME_SIZE (460800 + TOUCAM_HEADER_SIZE + TOUCAM_TRAILER_SIZE)
+
+/* Absolute maximum number of buffers available for mmap() */
+#define MAX_IMAGES 10
+
+/* The following structures were based on cpia.h. Why reinvent the wheel? :-) */
+struct pwc_iso_buf
+{
+ void *data;
+ int length;
+ int read;
+ struct urb *urb;
+};
+
+/* intermediate buffers with raw data from the USB cam */
+struct pwc_frame_buf
+{
+ void *data;
+ volatile int filled; /* number of bytes filled */
+ struct pwc_frame_buf *next; /* list */
+#if PWC_DEBUG
+ int sequence; /* Sequence number */
+#endif
+};
+
+struct pwc_device
+{
+ struct video_device *vdev;
+#ifdef PWC_MAGIC
+ int magic;
+#endif
+ /* Pointer to our usb_device */
+ struct usb_device *udev;
+
+ int type; /* type of cam (645, 646, 675, 680, 690, 720, 730, 740, 750) */
+ int release; /* release number */
+ int features; /* feature bits */
+ char serial[30]; /* serial number (string) */
+ int error_status; /* set when something goes wrong with the cam (unplugged, USB errors) */
+ int usb_init; /* set when the cam has been initialized over USB */
+
+ /*** Video data ***/
+ int vopen; /* flag */
+ int vendpoint; /* video isoc endpoint */
+ int vcinterface; /* video control interface */
+ int valternate; /* alternate interface needed */
+ int vframes, vsize; /* frames-per-second & size (see PSZ_*) */
+ int vpalette; /* palette: 420P, RAW or RGBBAYER */
+ int vframe_count; /* received frames */
+ int vframes_dumped; /* counter for dumped frames */
+ int vframes_error; /* frames received in error */
+ int vmax_packet_size; /* USB maxpacket size */
+ int vlast_packet_size; /* for frame synchronisation */
+ int visoc_errors; /* number of contiguous ISOC errors */
+ int vcompression; /* desired compression factor */
+ int vbandlength; /* compressed band length; 0 is uncompressed */
+ char vsnapshot; /* snapshot mode */
+ char vsync; /* used by isoc handler */
+ char vmirror; /* for ToUCaM series */
+
+ int cmd_len;
+ unsigned char cmd_buf[13];
+
+ /* The image acquisition requires 3 to 4 steps:
+ 1. data is gathered in short packets from the USB controller
+ 2. data is synchronized and packed into a frame buffer
+ 3a. in case data is compressed, decompress it directly into image buffer
+ 3b. in case data is uncompressed, copy into image buffer with viewport
+ 4. data is transferred to the user process
+
+ Note that MAX_ISO_BUFS != MAX_FRAMES != MAX_IMAGES....
+ We have in effect a back-to-back-double-buffer system.
+ */
+ /* 1: isoc */
+ struct pwc_iso_buf sbuf[MAX_ISO_BUFS];
+ char iso_init;
+
+ /* 2: frame */
+ struct pwc_frame_buf *fbuf; /* all frames */
+ struct pwc_frame_buf *empty_frames, *empty_frames_tail; /* all empty frames */
+ struct pwc_frame_buf *full_frames, *full_frames_tail; /* all filled frames */
+ struct pwc_frame_buf *fill_frame; /* frame currently being filled */
+ struct pwc_frame_buf *read_frame; /* frame currently read by user process */
+ int frame_header_size, frame_trailer_size;
+ int frame_size;
+ int frame_total_size; /* including header & trailer */
+ int drop_frames;
+#if PWC_DEBUG
+ int sequence; /* Debugging aid */
+#endif
+
+ /* 3: decompression */
+ struct pwc_decompressor *decompressor; /* function block with decompression routines */
+ void *decompress_data; /* private data for decompression engine */
+
+ /* 4: image */
+ /* We have an 'image' and a 'view', where 'image' is the fixed-size image
+ as delivered by the camera, and 'view' is the size requested by the
+ program. The camera image is centered in this viewport, laced with
+ a gray or black border. view_min <= image <= view <= view_max;
+ */
+ int image_mask; /* bitmask of supported sizes */
+ struct pwc_coord view_min, view_max; /* minimum and maximum viewable sizes */
+ struct pwc_coord abs_max; /* maximum supported size with compression */
+ struct pwc_coord image, view; /* image and viewport size */
+ struct pwc_coord offset; /* offset within the viewport */
+
+ void *image_data; /* total buffer, which is subdivided into ... */
+ void *image_ptr[MAX_IMAGES]; /* ...several images... */
+ int fill_image; /* ...which are rotated. */
+ int len_per_image; /* length per image */
+ int image_read_pos; /* In case we read data in pieces, keep track of were we are in the imagebuffer */
+ int image_used[MAX_IMAGES]; /* For MCAPTURE and SYNC */
+
+ struct semaphore modlock; /* to prevent races in video_open(), etc */
+ spinlock_t ptrlock; /* for manipulating the buffer pointers */
+
+ /*** motorized pan/tilt feature */
+ struct pwc_mpt_range angle_range;
+ int pan_angle; /* in degrees * 100 */
+ int tilt_angle; /* absolute angle; 0,0 is home position */
+
+ /*** Misc. data ***/
+ wait_queue_head_t frameq; /* When waiting for a frame to finish... */
+#if PWC_INT_PIPE
+ void *usb_int_handler; /* for the interrupt endpoint */
+#endif
+};
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Global variables */
+extern int pwc_trace;
+extern int pwc_preferred_compression;
+
+/** functions in pwc-if.c */
+int pwc_try_video_mode(struct pwc_device *pdev, int width, int height, int new_fps, int new_compression, int new_snapshot);
+
+/** Functions in pwc-misc.c */
+/* sizes in pixels */
+extern struct pwc_coord pwc_image_sizes[PSZ_MAX];
+
+int pwc_decode_size(struct pwc_device *pdev, int width, int height);
+void pwc_construct(struct pwc_device *pdev);
+
+/** Functions in pwc-ctrl.c */
+/* Request a certain video mode. Returns < 0 if not possible */
+extern int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, int frames, int compression, int snapshot);
+/* Calculate the number of bytes per image (not frame) */
+extern void pwc_set_image_buffer_size(struct pwc_device *pdev);
+
+/* Various controls; should be obvious. Value 0..65535, or < 0 on error */
+extern int pwc_get_brightness(struct pwc_device *pdev);
+extern int pwc_set_brightness(struct pwc_device *pdev, int value);
+extern int pwc_get_contrast(struct pwc_device *pdev);
+extern int pwc_set_contrast(struct pwc_device *pdev, int value);
+extern int pwc_get_gamma(struct pwc_device *pdev);
+extern int pwc_set_gamma(struct pwc_device *pdev, int value);
+extern int pwc_get_saturation(struct pwc_device *pdev);
+extern int pwc_set_saturation(struct pwc_device *pdev, int value);
+extern int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value);
+extern int pwc_get_leds(struct pwc_device *pdev, int *on_value, int *off_value);
+extern int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor);
+
+/* Power down or up the camera; not supported by all models */
+extern int pwc_camera_power(struct pwc_device *pdev, int power);
+
+/* Private ioctl()s; see pwc-ioctl.h */
+extern int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg);
+
+
+/** pwc-uncompress.c */
+/* Expand frame to image, possibly including decompression. Uses read_frame and fill_image */
+extern int pwc_decompress(struct pwc_device *pdev);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
diff --git a/drivers/usb/media/se401.c b/drivers/usb/media/se401.c
index 6761806bc86f2..685bdae5cb626 100644
--- a/drivers/usb/media/se401.c
+++ b/drivers/usb/media/se401.c
@@ -122,7 +122,7 @@ static int se401_sndctrl(int set, struct usb_se401 *se401, unsigned short req,
0,
cp,
size,
- HZ
+ 1000
);
}
@@ -142,7 +142,7 @@ static int se401_set_feature(struct usb_se401 *se401, unsigned short selector,
selector,
NULL,
0,
- HZ
+ 1000
);
}
@@ -162,7 +162,7 @@ static unsigned short se401_get_feature(struct usb_se401 *se401,
selector,
cp,
2,
- HZ
+ 1000
);
return cp[0]+cp[1]*256;
}
diff --git a/drivers/usb/media/sn9c102.h b/drivers/usb/media/sn9c102.h
index 795ebc6413779..8b8a4c8743f88 100644
--- a/drivers/usb/media/sn9c102.h
+++ b/drivers/usb/media/sn9c102.h
@@ -48,16 +48,16 @@
#define SN9C102_ISO_PACKETS 7
#define SN9C102_ALTERNATE_SETTING 8
#define SN9C102_URB_TIMEOUT msecs_to_jiffies(2 * SN9C102_ISO_PACKETS)
-#define SN9C102_CTRL_TIMEOUT msecs_to_jiffies(300)
+#define SN9C102_CTRL_TIMEOUT 300
/*****************************************************************************/
#define SN9C102_MODULE_NAME "V4L2 driver for SN9C10x PC Camera Controllers"
-#define SN9C102_MODULE_AUTHOR "(C) 2004 Luca Risolia"
+#define SN9C102_MODULE_AUTHOR "(C) 2004-2005 Luca Risolia"
#define SN9C102_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>"
#define SN9C102_MODULE_LICENSE "GPL"
-#define SN9C102_MODULE_VERSION "1:1.22"
-#define SN9C102_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 22)
+#define SN9C102_MODULE_VERSION "1:1.24"
+#define SN9C102_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 24)
enum sn9c102_bridge {
BRIDGE_SN9C101 = 0x01,
diff --git a/drivers/usb/media/sn9c102_core.c b/drivers/usb/media/sn9c102_core.c
index e509d2ffa0f63..898401cf7dcc5 100644
--- a/drivers/usb/media/sn9c102_core.c
+++ b/drivers/usb/media/sn9c102_core.c
@@ -164,8 +164,8 @@ sn9c102_request_buffers(struct sn9c102_device* cam, u32 count,
struct v4l2_rect* r = &(cam->sensor->cropcap.bounds);
const size_t imagesize = cam->module_param.force_munmap ||
io == IO_READ ?
- (p->width * p->height * p->priv)/8 :
- (r->width * r->height * p->priv)/8;
+ (p->width * p->height * p->priv) / 8 :
+ (r->width * r->height * p->priv) / 8;
void* buff = NULL;
u32 i;
@@ -499,6 +499,7 @@ static void sn9c102_urb_complete(struct urb *urb, struct pt_regs* regs)
{
struct sn9c102_device* cam = urb->context;
struct sn9c102_frame_t** f;
+ size_t imagesize;
unsigned long lock_flags;
u8 i;
int err = 0;
@@ -516,8 +517,13 @@ static void sn9c102_urb_complete(struct urb *urb, struct pt_regs* regs)
wake_up_interruptible(&cam->wait_stream);
}
- if ((cam->state & DEV_DISCONNECTED)||(cam->state & DEV_MISCONFIGURED))
+ if (cam->state & DEV_DISCONNECTED)
+ return;
+
+ if (cam->state & DEV_MISCONFIGURED) {
+ wake_up_interruptible(&cam->wait_frame);
return;
+ }
if (cam->stream == STREAM_OFF || list_empty(&cam->inqueue))
goto resubmit_urb;
@@ -526,6 +532,10 @@ static void sn9c102_urb_complete(struct urb *urb, struct pt_regs* regs)
(*f) = list_entry(cam->inqueue.next, struct sn9c102_frame_t,
frame);
+ imagesize = (cam->sensor->pix_format.width *
+ cam->sensor->pix_format.height *
+ cam->sensor->pix_format.priv) / 8;
+
for (i = 0; i < urb->number_of_packets; i++) {
unsigned int img, len, status;
void *pos, *sof, *eof;
@@ -560,11 +570,10 @@ end_of_frame:
if (eof)
img = (eof > pos) ? eof - pos - 1 : 0;
- if ((*f)->buf.bytesused+img>(*f)->buf.length) {
+ if ((*f)->buf.bytesused+img > imagesize) {
u32 b = (*f)->buf.bytesused + img -
- (*f)->buf.length;
- img = (*f)->buf.length -
- (*f)->buf.bytesused;
+ imagesize;
+ img = imagesize - (*f)->buf.bytesused;
DBG(3, "Expected EOF not found: "
"video frame cut")
if (eof)
@@ -580,7 +589,7 @@ end_of_frame:
(*f)->buf.bytesused += img;
- if ((*f)->buf.bytesused == (*f)->buf.length ||
+ if ((*f)->buf.bytesused == imagesize ||
(cam->sensor->pix_format.pixelformat ==
V4L2_PIX_FMT_SN9C10X && eof)) {
u32 b = (*f)->buf.bytesused;
@@ -1558,7 +1567,8 @@ sn9c102_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos)
err = wait_event_interruptible
( cam->wait_frame,
(!list_empty(&cam->outqueue)) ||
- (cam->state & DEV_DISCONNECTED) );
+ (cam->state & DEV_DISCONNECTED) ||
+ (cam->state & DEV_MISCONFIGURED) );
if (err) {
up(&cam->fileop_sem);
return err;
@@ -1567,6 +1577,10 @@ sn9c102_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos)
up(&cam->fileop_sem);
return -ENODEV;
}
+ if (cam->state & DEV_MISCONFIGURED) {
+ up(&cam->fileop_sem);
+ return -EIO;
+ }
}
f = list_entry(cam->outqueue.prev, struct sn9c102_frame_t, frame);
@@ -1615,7 +1629,8 @@ static unsigned int sn9c102_poll(struct file *filp, poll_table *wait)
}
if (cam->io == IO_NONE) {
- if (!sn9c102_request_buffers(cam, 2, IO_READ)) {
+ if (!sn9c102_request_buffers(cam, cam->nreadbuffers,
+ IO_READ)) {
DBG(1, "poll() failed, not enough memory")
goto error;
}
@@ -1729,7 +1744,7 @@ static int sn9c102_mmap(struct file* filp, struct vm_area_struct *vma)
}
-static int sn9c102_v4l2_ioctl(struct inode* inode, struct file* filp,
+static int sn9c102_ioctl_v4l2(struct inode* inode, struct file* filp,
unsigned int cmd, void __user * arg)
{
struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp));
@@ -1970,7 +1985,7 @@ static int sn9c102_v4l2_ioctl(struct inode* inode, struct file* filp,
return -EFAULT;
}
- if (cam->module_param.force_munmap)
+ if (cam->module_param.force_munmap || cam->io == IO_READ)
sn9c102_release_buffers(cam);
err = sn9c102_set_crop(cam, rect);
@@ -1990,7 +2005,7 @@ static int sn9c102_v4l2_ioctl(struct inode* inode, struct file* filp,
s->pix_format.height = rect->height/scale;
memcpy(&(s->_rect), rect, sizeof(*rect));
- if (cam->module_param.force_munmap &&
+ if ((cam->module_param.force_munmap || cam->io == IO_READ) &&
nbuffers != sn9c102_request_buffers(cam, nbuffers,
cam->io)) {
cam->state |= DEV_MISCONFIGURED;
@@ -2146,7 +2161,7 @@ static int sn9c102_v4l2_ioctl(struct inode* inode, struct file* filp,
return -EFAULT;
}
- if (cam->module_param.force_munmap)
+ if (cam->module_param.force_munmap || cam->io == IO_READ)
sn9c102_release_buffers(cam);
err += sn9c102_set_pix_format(cam, pix);
@@ -2168,7 +2183,7 @@ static int sn9c102_v4l2_ioctl(struct inode* inode, struct file* filp,
memcpy(pfmt, pix, sizeof(*pix));
memcpy(&(s->_rect), &rect, sizeof(rect));
- if (cam->module_param.force_munmap &&
+ if ((cam->module_param.force_munmap || cam->io == IO_READ) &&
nbuffers != sn9c102_request_buffers(cam, nbuffers,
cam->io)) {
cam->state |= DEV_MISCONFIGURED;
@@ -2346,11 +2361,14 @@ static int sn9c102_v4l2_ioctl(struct inode* inode, struct file* filp,
err = wait_event_interruptible
( cam->wait_frame,
(!list_empty(&cam->outqueue)) ||
- (cam->state & DEV_DISCONNECTED) );
+ (cam->state & DEV_DISCONNECTED) ||
+ (cam->state & DEV_MISCONFIGURED) );
if (err)
return err;
if (cam->state & DEV_DISCONNECTED)
return -ENODEV;
+ if (cam->state & DEV_MISCONFIGURED)
+ return -EIO;
}
spin_lock_irqsave(&cam->queue_lock, lock_flags);
@@ -2495,7 +2513,7 @@ static int sn9c102_ioctl(struct inode* inode, struct file* filp,
return -EIO;
}
- err = sn9c102_v4l2_ioctl(inode, filp, cmd, (void __user *)arg);
+ err = sn9c102_ioctl_v4l2(inode, filp, cmd, (void __user *)arg);
up(&cam->fileop_sem);
diff --git a/drivers/usb/media/ultracam.c b/drivers/usb/media/ultracam.c
index fec1f09615f4d..75ff755224df6 100644
--- a/drivers/usb/media/ultracam.c
+++ b/drivers/usb/media/ultracam.c
@@ -155,7 +155,7 @@ static int ultracam_veio(
index,
cp,
sizeof(cp),
- HZ);
+ 1000);
#if 1
info("USB => %02x%02x%02x%02x%02x%02x%02x%02x "
"(req=$%02x val=$%04x ind=$%04x)",
@@ -172,7 +172,7 @@ static int ultracam_veio(
index,
NULL,
0,
- HZ);
+ 1000);
}
if (i < 0) {
err("%s: ERROR=%d. Camera stopped; Reconnect or reload driver.",
diff --git a/drivers/usb/media/usbvideo.c b/drivers/usb/media/usbvideo.c
index 543d465e7dfa9..298484aa27d24 100644
--- a/drivers/usb/media/usbvideo.c
+++ b/drivers/usb/media/usbvideo.c
@@ -1814,12 +1814,12 @@ static void usbvideo_StopDataPump(struct uvd *uvd)
{
int i, j;
- if (uvd->debug > 1)
- info("%s($%p)", __FUNCTION__, uvd);
-
if ((uvd == NULL) || (!uvd->streaming) || (uvd->dev == NULL))
return;
+ if (uvd->debug > 1)
+ info("%s($%p)", __FUNCTION__, uvd);
+
/* Unschedule all of the iso td's */
for (i=0; i < USBVIDEO_NUMSBUF; i++) {
usb_kill_urb(uvd->sbuf[i].urb);
diff --git a/drivers/usb/media/vicam.c b/drivers/usb/media/vicam.c
index 908ff5b7a9d65..4a5857c53f112 100644
--- a/drivers/usb/media/vicam.c
+++ b/drivers/usb/media/vicam.c
@@ -441,7 +441,7 @@ static int __send_control_msg(struct vicam_camera *cam,
request,
USB_DIR_OUT | USB_TYPE_VENDOR |
USB_RECIP_DEVICE, value, index,
- cp, size, HZ);
+ cp, size, 1000);
status = min(status, 0);
@@ -977,7 +977,7 @@ read_frame(struct vicam_camera *cam, int framenum)
n = usb_bulk_msg(cam->udev,
usb_rcvbulkpipe(cam->udev, cam->bulkEndpoint),
cam->raw_image,
- 512 * 242 + 128, &actual_length, HZ*10);
+ 512 * 242 + 128, &actual_length, 10000);
if (n < 0) {
printk(KERN_ERR "Problem during bulk read of frame data: %d\n",
diff --git a/drivers/usb/media/w9968cf.h b/drivers/usb/media/w9968cf.h
index 988125ab30716..8acbfe205bc76 100644
--- a/drivers/usb/media/w9968cf.h
+++ b/drivers/usb/media/w9968cf.h
@@ -65,7 +65,7 @@ static const u16 wMaxPacketSize[] = {1023, 959, 895, 831, 767, 703, 639, 575,
#define W9968CF_PACKET_SIZE 1023 /* according to wMaxPacketSizes[] */
#define W9968CF_MIN_PACKET_SIZE 63 /* minimum value */
#define W9968CF_ISO_PACKETS 5 /* n.of packets for isochronous transfers */
-#define W9968CF_USB_CTRL_TIMEOUT HZ /* timeout for usb control commands */
+#define W9968CF_USB_CTRL_TIMEOUT 1000 /* timeout (ms) for usb control commands */
#define W9968CF_URBS 2 /* n. of scheduled URBs for ISO transfer */
#define W9968CF_I2C_BUS_DELAY 4 /* delay in us for I2C bit r/w operations */
diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig
index abd5ac02be485..3a896954b3a9a 100644
--- a/drivers/usb/misc/Kconfig
+++ b/drivers/usb/misc/Kconfig
@@ -137,6 +137,8 @@ config USB_IDMOUSE
See also <http://www.fs.tum.de/~echtler/idmouse/>.
+source "drivers/usb/misc/sisusbvga/Kconfig"
+
config USB_TEST
tristate "USB testing driver (DEVELOPMENT)"
depends on USB && USB_DEVICEFS && EXPERIMENTAL
diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile
index 566e26ae64803..4a3814cbd48d2 100644
--- a/drivers/usb/misc/Makefile
+++ b/drivers/usb/misc/Makefile
@@ -16,3 +16,5 @@ obj-$(CONFIG_USB_PHIDGETSERVO) += phidgetservo.o
obj-$(CONFIG_USB_RIO500) += rio500.o
obj-$(CONFIG_USB_TEST) += usbtest.o
obj-$(CONFIG_USB_USS720) += uss720.o
+
+obj-$(CONFIG_USB_SISUSBVGA) += sisusbvga/ \ No newline at end of file
diff --git a/drivers/usb/misc/auerswald.c b/drivers/usb/misc/auerswald.c
index d656592c25dd2..a530bb976e437 100644
--- a/drivers/usb/misc/auerswald.c
+++ b/drivers/usb/misc/auerswald.c
@@ -29,6 +29,7 @@
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/init.h>
+#include <linux/wait.h>
#undef DEBUG /* include debug macros until it's done */
#include <linux/usb.h>
@@ -605,7 +606,6 @@ static void auerchain_blocking_completion (struct urb *urb, struct pt_regs *regs
/* Starts chained urb and waits for completion or timeout */
static int auerchain_start_wait_urb (pauerchain_t acp, struct urb *urb, int timeout, int* actual_length)
{
- DECLARE_WAITQUEUE (wait, current);
auerchain_chs_t chs;
int status;
@@ -613,26 +613,13 @@ static int auerchain_start_wait_urb (pauerchain_t acp, struct urb *urb, int time
init_waitqueue_head (&chs.wqh);
chs.done = 0;
- set_current_state (TASK_UNINTERRUPTIBLE);
- add_wait_queue (&chs.wqh, &wait);
urb->context = &chs;
status = auerchain_submit_urb (acp, urb);
- if (status) {
+ if (status)
/* something went wrong */
- set_current_state (TASK_RUNNING);
- remove_wait_queue (&chs.wqh, &wait);
return status;
- }
-
- while (timeout && !chs.done)
- {
- timeout = schedule_timeout (timeout);
- set_current_state(TASK_UNINTERRUPTIBLE);
- rmb();
- }
- set_current_state (TASK_RUNNING);
- remove_wait_queue (&chs.wqh, &wait);
+ timeout = wait_event_timeout(chs.wqh, chs.done, timeout);
if (!timeout && !chs.done) {
if (urb->status != -EINPROGRESS) { /* No callback?!! */
@@ -2009,7 +1996,7 @@ static int auerswald_probe (struct usb_interface *intf,
AUDI_MBCTRANS, /* USB message index value */
pbuf, /* pointer to the receive buffer */
2, /* length of the buffer */
- HZ * 2); /* time to wait for the message to complete before timing out */
+ 2000); /* time to wait for the message to complete before timing out */
if (ret == 2) {
cp->maxControlLength = le16_to_cpup(pbuf);
kfree(pbuf);
diff --git a/drivers/usb/misc/cytherm.c b/drivers/usb/misc/cytherm.c
index 4d27eab244487..626e2b05f719e 100644
--- a/drivers/usb/misc/cytherm.c
+++ b/drivers/usb/misc/cytherm.c
@@ -77,7 +77,7 @@ static int vendor_command(struct usb_device *dev, unsigned char request,
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_OTHER,
value,
index, buf, size,
- HZ * USB_CTRL_GET_TIMEOUT);
+ USB_CTRL_GET_TIMEOUT);
}
diff --git a/drivers/usb/misc/emi26.c b/drivers/usb/misc/emi26.c
index 66920ab9faf65..c8155209bf4b4 100644
--- a/drivers/usb/misc/emi26.c
+++ b/drivers/usb/misc/emi26.c
@@ -30,6 +30,7 @@ typedef struct _INTEL_HEX_RECORD
#define EMI26_VENDOR_ID 0x086a /* Emagic Soft-und Hardware GmBH */
#define EMI26_PRODUCT_ID 0x0100 /* EMI 2|6 without firmware */
+#define EMI26B_PRODUCT_ID 0x0102 /* EMI 2|6 without firmware */
#define ANCHOR_LOAD_INTERNAL 0xA0 /* Vendor specific request code for Anchor Upload/Download (This one is implemented in the core) */
#define ANCHOR_LOAD_EXTERNAL 0xA3 /* This command is not implemented in the core. Requires firmware */
@@ -203,6 +204,7 @@ wraperr:
static struct usb_device_id id_table [] = {
{ USB_DEVICE(EMI26_VENDOR_ID, EMI26_PRODUCT_ID) },
+ { USB_DEVICE(EMI26_VENDOR_ID, EMI26B_PRODUCT_ID) },
{ } /* Terminating entry */
};
diff --git a/drivers/usb/misc/idmouse.c b/drivers/usb/misc/idmouse.c
index 04f091244e3a2..ce030d1f1c1f5 100644
--- a/drivers/usb/misc/idmouse.c
+++ b/drivers/usb/misc/idmouse.c
@@ -124,28 +124,28 @@ static int idmouse_create_image(struct usb_idmouse *dev)
means init..
*/
result = usb_control_msg (dev->udev, usb_sndctrlpipe (dev->udev, 0),
- 0x21, 0x42, 0x0001, 0x0002, NULL, 0, HZ);
+ 0x21, 0x42, 0x0001, 0x0002, NULL, 0, 1000);
if (result < 0)
return result;
result = usb_control_msg (dev->udev, usb_sndctrlpipe (dev->udev, 0),
- 0x20, 0x42, 0x0001, 0x0002, NULL, 0, HZ);
+ 0x20, 0x42, 0x0001, 0x0002, NULL, 0, 1000);
if (result < 0)
return result;
result = usb_control_msg (dev->udev, usb_sndctrlpipe (dev->udev, 0),
- 0x22, 0x42, 0x0000, 0x0002, NULL, 0, HZ);
+ 0x22, 0x42, 0x0000, 0x0002, NULL, 0, 1000);
if (result < 0)
return result;
result = usb_control_msg (dev->udev, usb_sndctrlpipe (dev->udev, 0),
- 0x21, 0x42, 0x0001, 0x0002, NULL, 0, HZ);
+ 0x21, 0x42, 0x0001, 0x0002, NULL, 0, 1000);
if (result < 0)
return result;
result = usb_control_msg (dev->udev, usb_sndctrlpipe (dev->udev, 0),
- 0x20, 0x42, 0x0001, 0x0002, NULL, 0, HZ);
+ 0x20, 0x42, 0x0001, 0x0002, NULL, 0, 1000);
if (result < 0)
return result;
result = usb_control_msg (dev->udev, usb_sndctrlpipe (dev->udev, 0),
- 0x20, 0x42, 0x0000, 0x0002, NULL, 0, HZ);
+ 0x20, 0x42, 0x0000, 0x0002, NULL, 0, 1000);
if (result < 0)
return result;
@@ -154,7 +154,7 @@ static int idmouse_create_image(struct usb_idmouse *dev)
result = usb_bulk_msg (dev->udev,
usb_rcvbulkpipe (dev->udev, dev->bulk_in_endpointAddr),
dev->bulk_in_buffer + bytes_read,
- dev->bulk_in_size, &bulk_read, HZ * 5);
+ dev->bulk_in_size, &bulk_read, 5000);
if (result < 0)
return result;
if (signal_pending(current))
@@ -164,7 +164,7 @@ static int idmouse_create_image(struct usb_idmouse *dev)
/* reset the device */
result = usb_control_msg (dev->udev, usb_sndctrlpipe (dev->udev, 0),
- 0x22, 0x42, 0x0000, 0x0002, NULL, 0, HZ);
+ 0x22, 0x42, 0x0000, 0x0002, NULL, 0, 1000);
if (result < 0)
return result;
diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c
index edf3df586a8c8..dd4580cb57e0d 100644
--- a/drivers/usb/misc/legousbtower.c
+++ b/drivers/usb/misc/legousbtower.c
@@ -391,7 +391,7 @@ static int tower_open (struct inode *inode, struct file *file)
0,
&reset_reply,
sizeof(reset_reply),
- HZ);
+ 1000);
if (result < 0) {
err("LEGO USB Tower reset control request failed");
retval = result;
@@ -972,7 +972,7 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device
0,
&get_version_reply,
sizeof(get_version_reply),
- HZ);
+ 1000);
if (result < 0) {
err("LEGO USB Tower get version control request failed");
retval = result;
diff --git a/drivers/usb/misc/phidgetkit.c b/drivers/usb/misc/phidgetkit.c
index ace44a7485730..ddbf8e992368e 100644
--- a/drivers/usb/misc/phidgetkit.c
+++ b/drivers/usb/misc/phidgetkit.c
@@ -103,14 +103,15 @@ static int change_outputs(struct phidget_interfacekit *kit, int output_num, int
}
}
- dev_dbg(&kit->udev->dev, "data: %02x %02x\n", buffer[0], buffer[1]);
+ dev_dbg(&kit->udev->dev, "sending data: %02x\n", buffer[0]);
retval = usb_control_msg(kit->udev,
usb_sndctrlpipe(kit->udev, 0),
- 0x09, 0x21, 0x0200, 0x0000, buffer, 4, 2 * HZ);
+ 0x09, 0x21, 0x0200, 0x0000, buffer, 4, 2000);
if (retval != 4)
- dev_err(&kit->udev->dev, "retval = %d\n", retval);
+ dev_err(&kit->udev->dev, "usb_control_msg returned %d\n",
+ retval);
kfree(buffer);
return retval < 0 ? retval : 0;
@@ -158,7 +159,7 @@ static int change_string(struct phidget_interfacekit *kit, const char *display,
retval = usb_control_msg(kit->udev,
usb_sndctrlpipe(kit->udev, 0),
- 0x09, 0x21, 0x0200, 0x0000, buffer, 8, 2 * HZ);
+ 0x09, 0x21, 0x0200, 0x0000, buffer, 8, 2000);
if (retval < 0)
goto exit;
}
@@ -210,7 +211,7 @@ static ssize_t set_backlight(struct device *dev, const char *buf, size_t count)
retval = usb_control_msg(kit->udev,
usb_sndctrlpipe(kit->udev, 0),
- 0x09, 0x21, 0x0200, 0x0000, buffer, 8, 2 * HZ);
+ 0x09, 0x21, 0x0200, 0x0000, buffer, 8, 2000);
if (retval < 0)
goto exit;
@@ -328,7 +329,7 @@ static ssize_t show_output##value(struct device *dev, char *buf) \
struct usb_interface *intf = to_usb_interface(dev); \
struct phidget_interfacekit *kit = usb_get_intfdata(intf); \
\
- return sprintf(buf, "%d\n", kit->outputs[value - 1 ]); \
+ return sprintf(buf, "%d\n", kit->outputs[value - 1]); \
} \
static DEVICE_ATTR(output##value, S_IWUGO | S_IRUGO, \
show_output##value, set_output##value);
@@ -440,11 +441,13 @@ static int interfacekit_probe(struct usb_interface *intf, const struct usb_devic
return -EIO;
}
- if (ifkit->outputs == 8) {
+ if (ifkit->outputs >= 4) {
device_create_file(&intf->dev, &dev_attr_output1);
device_create_file(&intf->dev, &dev_attr_output2);
device_create_file(&intf->dev, &dev_attr_output3);
device_create_file(&intf->dev, &dev_attr_output4);
+ }
+ if (ifkit->outputs == 8) {
device_create_file(&intf->dev, &dev_attr_output5);
device_create_file(&intf->dev, &dev_attr_output6);
device_create_file(&intf->dev, &dev_attr_output7);
@@ -483,7 +486,7 @@ static int interfacekit_probe(struct usb_interface *intf, const struct usb_devic
device_create_file(&intf->dev, &dev_attr_lcd);
dev_info(&intf->dev, "USB PhidgetInterfaceKit %d/%d/%d attached\n",
- ifkit->inputs, ifkit->outputs, ifkit->sensors);
+ ifkit->sensors, ifkit->inputs, ifkit->outputs);
return 0;
}
@@ -497,15 +500,17 @@ static void interfacekit_disconnect(struct usb_interface *interface)
if (!kit)
return;
- if (kit->ifkit->outputs == MAX_INTERFACES) {
+ if (kit->ifkit->outputs >= 4) {
device_remove_file(&interface->dev, &dev_attr_output1);
device_remove_file(&interface->dev, &dev_attr_output2);
device_remove_file(&interface->dev, &dev_attr_output3);
device_remove_file(&interface->dev, &dev_attr_output4);
+ }
+ if (kit->ifkit->outputs == 8) {
device_remove_file(&interface->dev, &dev_attr_output5);
device_remove_file(&interface->dev, &dev_attr_output6);
device_remove_file(&interface->dev, &dev_attr_output7);
- device_remove_file(&interface->dev, &dev_attr_output7);
+ device_remove_file(&interface->dev, &dev_attr_output8);
}
if (kit->ifkit->inputs >= 4) {
@@ -536,10 +541,10 @@ static void interfacekit_disconnect(struct usb_interface *interface)
device_remove_file(&interface->dev, &dev_attr_sensor8);
}
if (kit->ifkit->has_lcd)
- device_create_file(&interface->dev, &dev_attr_lcd);
+ device_remove_file(&interface->dev, &dev_attr_lcd);
dev_info(&interface->dev, "USB PhidgetInterfaceKit %d/%d/%d detached\n",
- kit->ifkit->inputs, kit->ifkit->outputs, kit->ifkit->sensors);
+ kit->ifkit->sensors, kit->ifkit->inputs, kit->ifkit->outputs);
usb_kill_urb(kit->irq);
usb_free_urb(kit->irq);
diff --git a/drivers/usb/misc/phidgetservo.c b/drivers/usb/misc/phidgetservo.c
index 8cca7e7474a9d..4bd291502a3c0 100644
--- a/drivers/usb/misc/phidgetservo.c
+++ b/drivers/usb/misc/phidgetservo.c
@@ -148,7 +148,7 @@ change_position_v30(struct phidget_servo *servo, int servo_no, int degrees,
retval = usb_control_msg(servo->udev,
usb_sndctrlpipe(servo->udev, 0),
- 0x09, 0x21, 0x0200, 0x0000, buffer, 6, 2 * HZ);
+ 0x09, 0x21, 0x0200, 0x0000, buffer, 6, 2000);
kfree(buffer);
@@ -199,7 +199,7 @@ change_position_v20(struct phidget_servo *servo, int servo_no, int degrees,
retval = usb_control_msg(servo->udev,
usb_sndctrlpipe(servo->udev, 0),
- 0x09, 0x21, 0x0200, 0x0000, buffer, 2, 2 * HZ);
+ 0x09, 0x21, 0x0200, 0x0000, buffer, 2, 2000);
kfree(buffer);
diff --git a/drivers/usb/misc/rio500.c b/drivers/usb/misc/rio500.c
index 6a6e3de91a0a5..26f77e29c7a61 100644
--- a/drivers/usb/misc/rio500.c
+++ b/drivers/usb/misc/rio500.c
@@ -40,6 +40,7 @@
#include <linux/spinlock.h>
#include <linux/usb.h>
#include <linux/smp_lock.h>
+#include <linux/wait.h>
#include "rio500_usb.h"
@@ -166,7 +167,7 @@ ioctl_rio(struct inode *inode, struct file *file, unsigned int cmd,
rio_cmd.value,
rio_cmd.index, buffer,
rio_cmd.length,
- rio_cmd.timeout);
+ jiffies_to_msecs(rio_cmd.timeout));
if (result == -ETIMEDOUT)
retries--;
else if (result < 0) {
@@ -233,7 +234,7 @@ ioctl_rio(struct inode *inode, struct file *file, unsigned int cmd,
rio_cmd.value,
rio_cmd.index, buffer,
rio_cmd.length,
- rio_cmd.timeout);
+ jiffies_to_msecs(rio_cmd.timeout));
if (result == -ETIMEDOUT)
retries--;
else if (result < 0) {
@@ -264,6 +265,7 @@ static ssize_t
write_rio(struct file *file, const char __user *buffer,
size_t count, loff_t * ppos)
{
+ DEFINE_WAIT(wait);
struct rio_usb_data *rio = &rio_instance;
unsigned long copy_size;
@@ -309,7 +311,7 @@ write_rio(struct file *file, const char __user *buffer,
result = usb_bulk_msg(rio->rio_dev,
usb_sndbulkpipe(rio->rio_dev, 2),
- obuf, thistime, &partial, 5 * HZ);
+ obuf, thistime, &partial, 5000);
dbg("write stats: result:%d thistime:%lu partial:%u",
result, thistime, partial);
@@ -319,7 +321,9 @@ write_rio(struct file *file, const char __user *buffer,
errn = -ETIME;
goto error;
}
- interruptible_sleep_on_timeout(&rio-> wait_q, NAK_TIMEOUT);
+ prepare_to_wait(&rio->wait_q, &wait, TASK_INTERRUPTIBLE);
+ schedule_timeout(NAK_TIMEOUT);
+ finish_wait(&rio->wait_q, &wait);
continue;
} else if (!result && partial) {
obuf += partial;
@@ -349,6 +353,7 @@ error:
static ssize_t
read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos)
{
+ DEFINE_WAIT(wait);
struct rio_usb_data *rio = &rio_instance;
ssize_t read_count;
unsigned int partial;
@@ -386,7 +391,7 @@ read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos)
result = usb_bulk_msg(rio->rio_dev,
usb_rcvbulkpipe(rio->rio_dev, 1),
ibuf, this_read, &partial,
- (int) (HZ * 8));
+ 8000);
dbg(KERN_DEBUG "read stats: result:%d this_read:%u partial:%u",
result, this_read, partial);
@@ -399,8 +404,9 @@ read_rio(struct file *file, char __user *buffer, size_t count, loff_t * ppos)
err("read_rio: maxretry timeout");
return -ETIME;
}
- interruptible_sleep_on_timeout(&rio->wait_q,
- NAK_TIMEOUT);
+ prepare_to_wait(&rio->wait_q, &wait, TASK_INTERRUPTIBLE);
+ schedule_timeout(NAK_TIMEOUT);
+ finish_wait(&rio->wait_q, &wait);
continue;
} else if (result != -EREMOTEIO) {
up(&(rio->lock));
diff --git a/drivers/usb/misc/sisusbvga/Kconfig b/drivers/usb/misc/sisusbvga/Kconfig
new file mode 100644
index 0000000000000..3957e144caf73
--- /dev/null
+++ b/drivers/usb/misc/sisusbvga/Kconfig
@@ -0,0 +1,14 @@
+
+config USB_SISUSBVGA
+ tristate "USB 2.0 SVGA dongle support (Net2280/SiS315)"
+ depends on USB && USB_EHCI_HCD
+ ---help---
+ Say Y here if you intend to attach a USB2VGA dongle based on a
+ Net2280 and a SiS315 chip.
+
+ Note that this device requires a USB 2.0 host controller. It will not
+ work with USB 1.x controllers.
+
+ To compile this driver as a module, choose M here: the module will be
+ called sisusb. If unsure, say N.
+
diff --git a/drivers/usb/misc/sisusbvga/Makefile b/drivers/usb/misc/sisusbvga/Makefile
new file mode 100644
index 0000000000000..76f1643ceaf8e
--- /dev/null
+++ b/drivers/usb/misc/sisusbvga/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the sisusb driver (if driver is inside kernel tree).
+#
+
+obj-$(CONFIG_USB_SISUSBVGA) += sisusb.o
+
diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c
new file mode 100644
index 0000000000000..be163b3301674
--- /dev/null
+++ b/drivers/usb/misc/sisusbvga/sisusb.c
@@ -0,0 +1,3145 @@
+/*
+ * sisusb - usb kernel driver for SiS315(E) based USB2VGA dongles
+ *
+ * Copyright (C) 2005 by Thomas Winischhofer, Vienna, Austria
+ *
+ * If distributed as part of the Linux kernel, this code is licensed under the
+ * terms of the GPL v2.
+ *
+ * Otherwise, the following license terms apply:
+ *
+ * * Redistribution and use in source and binary forms, with or without
+ * * modification, are permitted provided that the following conditions
+ * * are met:
+ * * 1) Redistributions of source code must retain the above copyright
+ * * notice, this list of conditions and the following disclaimer.
+ * * 2) Redistributions in binary form must reproduce the above copyright
+ * * notice, this list of conditions and the following disclaimer in the
+ * * documentation and/or other materials provided with the distribution.
+ * * 3) The name of the author may not be used to endorse or promote products
+ * * derived from this software without specific psisusbr written permission.
+ * *
+ * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR
+ * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Author: Thomas Winischhofer <thomas@winischhofer.net>
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/poll.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/kref.h>
+#include <linux/usb.h>
+#include <linux/smp_lock.h>
+
+#include "sisusb.h"
+
+#define SISUSB_DONTSYNC
+
+/* Forward declarations / clean-up routines */
+
+static struct usb_driver sisusb_driver;
+
+static DECLARE_MUTEX(disconnect_sem);
+
+static void
+sisusb_free_buffers(struct sisusb_usb_data *sisusb)
+{
+ int i;
+
+ for (i = 0; i < NUMOBUFS; i++) {
+ if (sisusb->obuf[i]) {
+ usb_buffer_free(sisusb->sisusb_dev, sisusb->obufsize,
+ sisusb->obuf[i], sisusb->transfer_dma_out[i]);
+ sisusb->obuf[i] = NULL;
+ }
+ }
+ if (sisusb->ibuf) {
+ usb_buffer_free(sisusb->sisusb_dev, sisusb->ibufsize,
+ sisusb->ibuf, sisusb->transfer_dma_in);
+ sisusb->ibuf = NULL;
+ }
+}
+
+static void
+sisusb_free_urbs(struct sisusb_usb_data *sisusb)
+{
+ int i;
+
+ for (i = 0; i < NUMOBUFS; i++) {
+ usb_free_urb(sisusb->sisurbout[i]);
+ sisusb->sisurbout[i] = NULL;
+ }
+ usb_free_urb(sisusb->sisurbin);
+ sisusb->sisurbin = NULL;
+}
+
+/* Level 0: USB transport layer */
+
+/* 1. out-bulks */
+
+/* out-urb management */
+
+/* Return 1 if all free, 0 otherwise */
+static int
+sisusb_all_free(struct sisusb_usb_data *sisusb)
+{
+ int i;
+
+ for (i = 0; i < sisusb->numobufs; i++) {
+
+ if (sisusb->urbstatus[i] & SU_URB_BUSY)
+ return 0;
+
+ }
+
+ return 1;
+}
+
+/* Kill all busy URBs */
+static void
+sisusb_kill_all_busy(struct sisusb_usb_data *sisusb)
+{
+ int i;
+
+ if (sisusb_all_free(sisusb))
+ return;
+
+ for (i = 0; i < sisusb->numobufs; i++) {
+
+ if (sisusb->urbstatus[i] & SU_URB_BUSY)
+ usb_kill_urb(sisusb->sisurbout[i]);
+
+ }
+}
+
+/* Return 1 if ok, 0 if error (not all complete within timeout) */
+static int
+sisusb_wait_all_out_complete(struct sisusb_usb_data *sisusb)
+{
+ int timeout = 5 * HZ, i = 1;
+
+ wait_event_timeout(sisusb->wait_q,
+ (i = sisusb_all_free(sisusb)),
+ timeout);
+
+ return i;
+}
+
+static int
+sisusb_outurb_available(struct sisusb_usb_data *sisusb)
+{
+ int i;
+
+ for (i = 0; i < sisusb->numobufs; i++) {
+
+ if ((sisusb->urbstatus[i] & (SU_URB_BUSY|SU_URB_ALLOC)) == 0)
+ return i;
+
+ }
+
+ return -1;
+}
+
+static int
+sisusb_get_free_outbuf(struct sisusb_usb_data *sisusb)
+{
+ int i, timeout = 5 * HZ;
+
+ wait_event_timeout(sisusb->wait_q,
+ ((i = sisusb_outurb_available(sisusb)) >= 0),
+ timeout);
+
+ return i;
+}
+
+static int
+sisusb_alloc_outbuf(struct sisusb_usb_data *sisusb)
+{
+ int i;
+
+ i = sisusb_outurb_available(sisusb);
+
+ if (i >= 0)
+ sisusb->urbstatus[i] |= SU_URB_ALLOC;
+
+ return i;
+}
+
+static void
+sisusb_free_outbuf(struct sisusb_usb_data *sisusb, int index)
+{
+ if ((index >= 0) && (index < sisusb->numobufs))
+ sisusb->urbstatus[index] &= ~SU_URB_ALLOC;
+}
+
+/* completion callback */
+
+static void
+sisusb_bulk_completeout(struct urb *urb, struct pt_regs *regs)
+{
+ struct sisusb_urb_context *context = urb->context;
+ struct sisusb_usb_data *sisusb;
+
+ if (!context)
+ return;
+
+ sisusb = context->sisusb;
+
+ if (!sisusb || !sisusb->sisusb_dev || !sisusb->present)
+ return;
+
+#ifndef SISUSB_DONTSYNC
+ if (context->actual_length)
+ *(context->actual_length) += urb->actual_length;
+#endif
+
+ sisusb->urbstatus[context->urbindex] &= ~SU_URB_BUSY;
+ wake_up(&sisusb->wait_q);
+}
+
+static int
+sisusb_bulkout_msg(struct sisusb_usb_data *sisusb, int index, unsigned int pipe, void *data,
+ int len, int *actual_length, int timeout, unsigned int tflags,
+ dma_addr_t transfer_dma)
+{
+ struct urb *urb = sisusb->sisurbout[index];
+ int retval, byteswritten = 0;
+
+ /* Set up URB */
+ urb->transfer_flags = 0;
+
+ usb_fill_bulk_urb(urb, sisusb->sisusb_dev, pipe, data, len,
+ sisusb_bulk_completeout, &sisusb->urbout_context[index]);
+
+ urb->transfer_flags |= (tflags | URB_ASYNC_UNLINK);
+ urb->actual_length = 0;
+
+ if ((urb->transfer_dma = transfer_dma))
+ urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+ /* Set up context */
+ sisusb->urbout_context[index].actual_length = (timeout) ?
+ NULL : actual_length;
+
+ /* Declare this urb/buffer in use */
+ sisusb->urbstatus[index] |= SU_URB_BUSY;
+
+ /* Submit URB */
+ retval = usb_submit_urb(urb, GFP_ATOMIC);
+
+ /* If OK, and if timeout > 0, wait for completion */
+ if ((retval == 0) && timeout) {
+ wait_event_timeout(sisusb->wait_q,
+ (!(sisusb->urbstatus[index] & SU_URB_BUSY)),
+ timeout);
+ if (sisusb->urbstatus[index] & SU_URB_BUSY) {
+ /* URB timed out... kill it and report error */
+ usb_kill_urb(urb);
+ retval = -ETIMEDOUT;
+ } else {
+ /* Otherwise, report urb status */
+ retval = urb->status;
+ byteswritten = urb->actual_length;
+ }
+ }
+
+ if (actual_length)
+ *actual_length = byteswritten;
+
+ return retval;
+}
+
+/* 2. in-bulks */
+
+/* completion callback */
+
+static void
+sisusb_bulk_completein(struct urb *urb, struct pt_regs *regs)
+{
+ struct sisusb_usb_data *sisusb = urb->context;
+
+ if (!sisusb || !sisusb->sisusb_dev || !sisusb->present)
+ return;
+
+ sisusb->completein = 1;
+ wake_up(&sisusb->wait_q);
+}
+
+static int
+sisusb_bulkin_msg(struct sisusb_usb_data *sisusb, unsigned int pipe, void *data, int len,
+ int *actual_length, int timeout, unsigned int tflags, dma_addr_t transfer_dma)
+{
+ struct urb *urb = sisusb->sisurbin;
+ int retval, readbytes = 0;
+
+ urb->transfer_flags = 0;
+
+ usb_fill_bulk_urb(urb, sisusb->sisusb_dev, pipe, data, len,
+ sisusb_bulk_completein, sisusb);
+
+ urb->transfer_flags |= (tflags | URB_ASYNC_UNLINK);
+ urb->actual_length = 0;
+
+ if ((urb->transfer_dma = transfer_dma))
+ urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+ sisusb->completein = 0;
+ retval = usb_submit_urb(urb, GFP_ATOMIC);
+ if (retval == 0) {
+ wait_event_timeout(sisusb->wait_q, sisusb->completein, timeout);
+ if (!sisusb->completein) {
+ /* URB timed out... kill it and report error */
+ usb_kill_urb(urb);
+ retval = -ETIMEDOUT;
+ } else {
+ /* URB completed within timout */
+ retval = urb->status;
+ readbytes = urb->actual_length;
+ }
+ }
+
+ if (actual_length)
+ *actual_length = readbytes;
+
+ return retval;
+}
+
+
+/* Level 1: */
+
+/* Send a bulk message of variable size
+ *
+ * To copy the data from userspace, give pointer to "userbuffer",
+ * to copy from (non-DMA) kernel memory, give "kernbuffer". If
+ * both of these are NULL, it is assumed, that the transfer
+ * buffer "sisusb->obuf[index]" is set up with the data to send.
+ * Index is ignored if either kernbuffer or userbuffer is set.
+ * If async is nonzero, URBs will be sent without waiting for
+ * completion of the previous URB.
+ *
+ * (return 0 on success)
+ */
+
+static int sisusb_send_bulk_msg(struct sisusb_usb_data *sisusb, int ep, int len,
+ char *kernbuffer, const char __user *userbuffer, int index,
+ ssize_t *bytes_written, unsigned int tflags, int async)
+{
+ int result = 0, retry, count = len;
+ int passsize, thispass, transferred_len = 0;
+ int fromuser = (userbuffer != NULL) ? 1 : 0;
+ int fromkern = (kernbuffer != NULL) ? 1 : 0;
+ unsigned int pipe;
+ char *buffer;
+
+ (*bytes_written) = 0;
+
+ /* Sanity check */
+ if (!sisusb || !sisusb->present || !sisusb->sisusb_dev)
+ return -ENODEV;
+
+ /* If we copy data from kernel or userspace, force the
+ * allocation of a buffer/urb. If we have the data in
+ * the transfer buffer[index] already, reuse the buffer/URB
+ * if the length is > buffer size. (So, transmitting
+ * large data amounts directly from the transfer buffer
+ * treats the buffer as a ring buffer. However, we need
+ * to sync in this case.)
+ */
+ if (fromuser || fromkern)
+ index = -1;
+ else if (len > sisusb->obufsize)
+ async = 0;
+
+ pipe = usb_sndbulkpipe(sisusb->sisusb_dev, ep);
+
+ do {
+ passsize = thispass = (sisusb->obufsize < count) ?
+ sisusb->obufsize : count;
+
+ if (index < 0)
+ index = sisusb_get_free_outbuf(sisusb);
+
+ if (index < 0)
+ return -EIO;
+
+ buffer = sisusb->obuf[index];
+
+ if (fromuser) {
+
+ if (copy_from_user(buffer, userbuffer, passsize))
+ return -EFAULT;
+
+ userbuffer += passsize;
+
+ } else if (fromkern) {
+
+ memcpy(buffer, kernbuffer, passsize);
+ kernbuffer += passsize;
+
+ }
+
+ retry = 5;
+ while (thispass) {
+
+ if (!sisusb->sisusb_dev)
+ return -ENODEV;
+
+ result = sisusb_bulkout_msg(sisusb,
+ index,
+ pipe,
+ buffer,
+ thispass,
+ &transferred_len,
+ async ? 0 : 5 * HZ,
+ tflags,
+ sisusb->transfer_dma_out[index]);
+
+ if (result == -ETIMEDOUT) {
+
+ /* Will not happen if async */
+ if (!retry--)
+ return -ETIME;
+
+ continue;
+
+ } else if ((result == 0) && !async && transferred_len) {
+
+ thispass -= transferred_len;
+ if (thispass) {
+ if (sisusb->transfer_dma_out) {
+ /* If DMA, copy remaining
+ * to beginning of buffer
+ */
+ memcpy(buffer,
+ buffer + transferred_len,
+ thispass);
+ } else {
+ /* If not DMA, simply increase
+ * the pointer
+ */
+ buffer += transferred_len;
+ }
+ }
+
+ } else
+ break;
+ };
+
+ if (result)
+ return result;
+
+ (*bytes_written) += passsize;
+ count -= passsize;
+
+ /* Force new allocation in next iteration */
+ if (fromuser || fromkern)
+ index = -1;
+
+ } while (count > 0);
+
+ if (async) {
+#ifdef SISUSB_DONTSYNC
+ (*bytes_written) = len;
+ /* Some URBs/buffers might be busy */
+#else
+ sisusb_wait_all_out_complete(sisusb);
+ (*bytes_written) = transferred_len;
+ /* All URBs and all buffers are available */
+#endif
+ }
+
+ return ((*bytes_written) == len) ? 0 : -EIO;
+}
+
+/* Receive a bulk message of variable size
+ *
+ * To copy the data to userspace, give pointer to "userbuffer",
+ * to copy to kernel memory, give "kernbuffer". One of them
+ * MUST be set. (There is no technique for letting the caller
+ * read directly from the ibuf.)
+ *
+ */
+
+static int sisusb_recv_bulk_msg(struct sisusb_usb_data *sisusb, int ep, int len,
+ void *kernbuffer, char __user *userbuffer, ssize_t *bytes_read,
+ unsigned int tflags)
+{
+ int result = 0, retry, count = len;
+ int bufsize, thispass, transferred_len;
+ unsigned int pipe;
+ char *buffer;
+
+ (*bytes_read) = 0;
+
+ /* Sanity check */
+ if (!sisusb || !sisusb->present || !sisusb->sisusb_dev)
+ return -ENODEV;
+
+ pipe = usb_rcvbulkpipe(sisusb->sisusb_dev, ep);
+ buffer = sisusb->ibuf;
+ bufsize = sisusb->ibufsize;
+
+ retry = 5;
+
+#ifdef SISUSB_DONTSYNC
+ if (!(sisusb_wait_all_out_complete(sisusb)))
+ return -EIO;
+#endif
+
+ while (count > 0) {
+
+ if (!sisusb->sisusb_dev)
+ return -ENODEV;
+
+ thispass = (bufsize < count) ? bufsize : count;
+
+ result = sisusb_bulkin_msg(sisusb,
+ pipe,
+ buffer,
+ thispass,
+ &transferred_len,
+ 5 * HZ,
+ tflags,
+ sisusb->transfer_dma_in);
+
+ if (transferred_len)
+ thispass = transferred_len;
+
+ else if (result == -ETIMEDOUT) {
+
+ if (!retry--)
+ return -ETIME;
+
+ continue;
+
+ } else
+ return -EIO;
+
+
+ if (thispass) {
+
+ (*bytes_read) += thispass;
+ count -= thispass;
+
+ if (userbuffer) {
+
+ if (copy_to_user(userbuffer, buffer, thispass))
+ return -EFAULT;
+
+ userbuffer += thispass;
+
+ } else {
+
+ memcpy(kernbuffer, buffer, thispass);
+ kernbuffer += thispass;
+
+ }
+
+ }
+
+ }
+
+ return ((*bytes_read) == len) ? 0 : -EIO;
+}
+
+static int sisusb_send_packet(struct sisusb_usb_data *sisusb, int len,
+ struct sisusb_packet *packet)
+{
+ int ret;
+ ssize_t bytes_transferred = 0;
+ __le32 tmp;
+
+ if (len == 6)
+ packet->data = 0;
+
+#ifdef SISUSB_DONTSYNC
+ if (!(sisusb_wait_all_out_complete(sisusb)))
+ return 1;
+#endif
+
+ /* Eventually correct endianness */
+ SISUSB_CORRECT_ENDIANNESS_PACKET(packet);
+
+ /* 1. send the packet */
+ ret = sisusb_send_bulk_msg(sisusb, SISUSB_EP_GFX_OUT, len,
+ (char *)packet, NULL, 0, &bytes_transferred, 0, 0);
+
+ if ((ret == 0) && (len == 6)) {
+
+ /* 2. if packet len == 6, it means we read, so wait for 32bit
+ * return value and write it to packet->data
+ */
+ ret = sisusb_recv_bulk_msg(sisusb, SISUSB_EP_GFX_IN, 4,
+ (char *)&tmp, NULL, &bytes_transferred, 0);
+
+ packet->data = le32_to_cpu(tmp);
+ }
+
+ return ret;
+}
+
+static int sisusb_send_bridge_packet(struct sisusb_usb_data *sisusb, int len,
+ struct sisusb_packet *packet,
+ unsigned int tflags)
+{
+ int ret;
+ ssize_t bytes_transferred = 0;
+ __le32 tmp;
+
+ if (len == 6)
+ packet->data = 0;
+
+#ifdef SISUSB_DONTSYNC
+ if (!(sisusb_wait_all_out_complete(sisusb)))
+ return 1;
+#endif
+
+ /* Eventually correct endianness */
+ SISUSB_CORRECT_ENDIANNESS_PACKET(packet);
+
+ /* 1. send the packet */
+ ret = sisusb_send_bulk_msg(sisusb, SISUSB_EP_BRIDGE_OUT, len,
+ (char *)packet, NULL, 0, &bytes_transferred, tflags, 0);
+
+ if ((ret == 0) && (len == 6)) {
+
+ /* 2. if packet len == 6, it means we read, so wait for 32bit
+ * return value and write it to packet->data
+ */
+ ret = sisusb_recv_bulk_msg(sisusb, SISUSB_EP_BRIDGE_IN, 4,
+ (char *)&tmp, NULL, &bytes_transferred, 0);
+
+ packet->data = le32_to_cpu(tmp);
+ }
+
+ return ret;
+}
+
+/* access video memory and mmio (return 0 on success) */
+
+/* Low level */
+
+/* The following routines assume being used to transfer byte, word,
+ * long etc.
+ * This means that they assume "data" in machine endianness format.
+ */
+
+static int sisusb_write_memio_byte(struct sisusb_usb_data *sisusb, int type,
+ u32 addr, u8 data)
+{
+ struct sisusb_packet packet;
+ int ret;
+
+ packet.header = (1 << (addr & 3)) | (type << 6);
+ packet.address = addr & ~3;
+ packet.data = data << ((addr & 3) << 3);
+ ret = sisusb_send_packet(sisusb, 10, &packet);
+ return ret;
+}
+
+static int sisusb_write_memio_word(struct sisusb_usb_data *sisusb, int type,
+ u32 addr, u16 data)
+{
+ struct sisusb_packet packet;
+ int ret = 0;
+
+ packet.address = addr & ~3;
+
+ switch (addr & 3) {
+ case 0:
+ packet.header = (type << 6) | 0x0003;
+ packet.data = (u32)data;
+ ret = sisusb_send_packet(sisusb, 10, &packet);
+ break;
+ case 1:
+ packet.header = (type << 6) | 0x0006;
+ packet.data = (u32)data << 8;
+ ret = sisusb_send_packet(sisusb, 10, &packet);
+ break;
+ case 2:
+ packet.header = (type << 6) | 0x000c;
+ packet.data = (u32)data << 16;
+ ret = sisusb_send_packet(sisusb, 10, &packet);
+ break;
+ case 3:
+ packet.header = (type << 6) | 0x0008;
+ packet.data = (u32)data << 24;
+ ret = sisusb_send_packet(sisusb, 10, &packet);
+ packet.header = (type << 6) | 0x0001;
+ packet.address = (addr & ~3) + 4;
+ packet.data = (u32)data >> 8;
+ ret |= sisusb_send_packet(sisusb, 10, &packet);
+ }
+
+ return ret;
+}
+
+static int sisusb_write_memio_24bit(struct sisusb_usb_data *sisusb, int type,
+ u32 addr, u32 data)
+{
+ struct sisusb_packet packet;
+ int ret = 0;
+
+ packet.address = addr & ~3;
+
+ switch (addr & 3) {
+ case 0:
+ packet.header = (type << 6) | 0x0007;
+ packet.data = data & 0x00ffffff;
+ ret = sisusb_send_packet(sisusb, 10, &packet);
+ break;
+ case 1:
+ packet.header = (type << 6) | 0x000e;
+ packet.data = data << 8;
+ ret = sisusb_send_packet(sisusb, 10, &packet);
+ break;
+ case 2:
+ packet.header = (type << 6) | 0x000c;
+ packet.data = data << 16;
+ ret = sisusb_send_packet(sisusb, 10, &packet);
+ packet.header = (type << 6) | 0x0001;
+ packet.address = (addr & ~3) + 4;
+ packet.data = (data >> 16) & 0x00ff;
+ ret |= sisusb_send_packet(sisusb, 10, &packet);
+ break;
+ case 3:
+ packet.header = (type << 6) | 0x0008;
+ packet.data = data << 24;
+ ret = sisusb_send_packet(sisusb, 10, &packet);
+ packet.header = (type << 6) | 0x0003;
+ packet.address = (addr & ~3) + 4;
+ packet.data = (data >> 8) & 0xffff;
+ ret |= sisusb_send_packet(sisusb, 10, &packet);
+ }
+
+ return ret;
+}
+
+static int sisusb_write_memio_long(struct sisusb_usb_data *sisusb, int type,
+ u32 addr, u32 data)
+{
+ struct sisusb_packet packet;
+ int ret = 0;
+
+ packet.address = addr & ~3;
+
+ switch (addr & 3) {
+ case 0:
+ packet.header = (type << 6) | 0x000f;
+ packet.data = data;
+ ret = sisusb_send_packet(sisusb, 10, &packet);
+ break;
+ case 1:
+ packet.header = (type << 6) | 0x000e;
+ packet.data = data << 8;
+ ret = sisusb_send_packet(sisusb, 10, &packet);
+ packet.header = (type << 6) | 0x0001;
+ packet.address = (addr & ~3) + 4;
+ packet.data = data >> 24;
+ ret |= sisusb_send_packet(sisusb, 10, &packet);
+ break;
+ case 2:
+ packet.header = (type << 6) | 0x000c;
+ packet.data = data << 16;
+ ret = sisusb_send_packet(sisusb, 10, &packet);
+ packet.header = (type << 6) | 0x0003;
+ packet.address = (addr & ~3) + 4;
+ packet.data = data >> 16;
+ ret |= sisusb_send_packet(sisusb, 10, &packet);
+ break;
+ case 3:
+ packet.header = (type << 6) | 0x0008;
+ packet.data = data << 24;
+ ret = sisusb_send_packet(sisusb, 10, &packet);
+ packet.header = (type << 6) | 0x0007;
+ packet.address = (addr & ~3) + 4;
+ packet.data = data >> 8;
+ ret |= sisusb_send_packet(sisusb, 10, &packet);
+ }
+
+ return ret;
+}
+
+/* The xxx_bulk routines copy a buffer of variable size. They treat the
+ * buffer as chars, therefore lsb/msb has to be corrected if using the
+ * byte/word/long/etc routines for speed-up
+ *
+ * If data is from userland, set "userbuffer" (and clear "kernbuffer"),
+ * if data is in kernel space, set "kernbuffer" (and clear "userbuffer");
+ * if neither "kernbuffer" nor "userbuffer" are given, it is assumed
+ * that the data already is in the transfer buffer "sisusb->obuf[index]".
+ */
+
+static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
+ char *kernbuffer, int length,
+ const char __user *userbuffer, int index,
+ ssize_t *bytes_written)
+{
+ struct sisusb_packet packet;
+ int ret = 0;
+ static int msgcount = 0;
+ u8 swap8, fromkern = kernbuffer ? 1 : 0;
+ u16 swap16;
+ u32 swap32, flag = (length >> 28) & 1;
+ char buf[4];
+
+ /* if neither kernbuffer not userbuffer are given, assume
+ * data in obuf
+ */
+ if (!fromkern && !userbuffer)
+ kernbuffer = sisusb->obuf[index];
+
+ (*bytes_written = 0);
+
+ length &= 0x00ffffff;
+
+ while (length) {
+
+ switch (length) {
+
+ case 0:
+ return ret;
+
+ case 1:
+ if (userbuffer) {
+ if (get_user(swap8, (u8 __user *)userbuffer))
+ return -EFAULT;
+ } else
+ swap8 = kernbuffer[0];
+
+ ret = sisusb_write_memio_byte(sisusb,
+ SISUSB_TYPE_MEM,
+ addr, swap8);
+
+ if (!ret)
+ (*bytes_written)++;
+
+ return ret;
+
+ case 2:
+ if (userbuffer) {
+ if (get_user(swap16, (u16 __user *)userbuffer))
+ return -EFAULT;
+ } else
+ swap16 = (kernbuffer[0] << 8) | kernbuffer[1];
+
+ ret = sisusb_write_memio_word(sisusb,
+ SISUSB_TYPE_MEM,
+ addr,
+ swap16);
+
+ if (!ret)
+ (*bytes_written) += 2;
+
+ return ret;
+
+ case 3:
+ if (userbuffer) {
+ if (copy_from_user(&buf, userbuffer, 3))
+ return -EFAULT;
+
+ swap32 = (buf[0] << 16) |
+ (buf[1] << 8) |
+ buf[2];
+ } else
+ swap32 = (kernbuffer[0] << 16) |
+ (kernbuffer[1] << 8) |
+ kernbuffer[2];
+
+ ret = sisusb_write_memio_24bit(sisusb,
+ SISUSB_TYPE_MEM,
+ addr,
+ swap32);
+
+ if (!ret)
+ (*bytes_written) += 3;
+
+ return ret;
+
+ case 4:
+ if (userbuffer) {
+ if (get_user(swap32, (u32 __user *)userbuffer))
+ return -EFAULT;
+ } else
+ swap32 = (kernbuffer[0] << 24) |
+ (kernbuffer[1] << 16) |
+ (kernbuffer[2] << 8) |
+ kernbuffer[3];
+
+ ret = sisusb_write_memio_long(sisusb,
+ SISUSB_TYPE_MEM,
+ addr,
+ swap32);
+ if (!ret)
+ (*bytes_written) += 4;
+
+ return ret;
+
+ default:
+ if ((length & ~3) > 0x10000) {
+
+ packet.header = 0x001f;
+ packet.address = 0x000001d4;
+ packet.data = addr;
+ ret = sisusb_send_bridge_packet(sisusb, 10,
+ &packet, 0);
+ packet.header = 0x001f;
+ packet.address = 0x000001d0;
+ packet.data = (length & ~3);
+ ret |= sisusb_send_bridge_packet(sisusb, 10,
+ &packet, 0);
+ packet.header = 0x001f;
+ packet.address = 0x000001c0;
+ packet.data = flag | 0x16;
+ ret |= sisusb_send_bridge_packet(sisusb, 10,
+ &packet, 0);
+ if (userbuffer) {
+ ret |= sisusb_send_bulk_msg(sisusb,
+ SISUSB_EP_GFX_LBULK_OUT,
+ (length & ~3),
+ NULL, userbuffer, 0,
+ bytes_written, 0, 1);
+ userbuffer += (*bytes_written);
+ } else if (fromkern) {
+ ret |= sisusb_send_bulk_msg(sisusb,
+ SISUSB_EP_GFX_LBULK_OUT,
+ (length & ~3),
+ kernbuffer, NULL, 0,
+ bytes_written, 0, 1);
+ kernbuffer += (*bytes_written);
+ } else {
+ ret |= sisusb_send_bulk_msg(sisusb,
+ SISUSB_EP_GFX_LBULK_OUT,
+ (length & ~3),
+ NULL, NULL, index,
+ bytes_written, 0, 1);
+ kernbuffer += ((*bytes_written) &
+ (sisusb->obufsize-1));
+ }
+
+ } else {
+
+ packet.header = 0x001f;
+ packet.address = 0x00000194;
+ packet.data = addr;
+ ret = sisusb_send_bridge_packet(sisusb, 10,
+ &packet, 0);
+ packet.header = 0x001f;
+ packet.address = 0x00000190;
+ packet.data = (length & ~3);
+ ret |= sisusb_send_bridge_packet(sisusb, 10,
+ &packet, 0);
+ if (sisusb->flagb0 != 0x16) {
+ packet.header = 0x001f;
+ packet.address = 0x00000180;
+ packet.data = flag | 0x16;
+ ret |= sisusb_send_bridge_packet(sisusb, 10,
+ &packet, 0);
+ sisusb->flagb0 = 0x16;
+ }
+ if (userbuffer) {
+ ret |= sisusb_send_bulk_msg(sisusb,
+ SISUSB_EP_GFX_BULK_OUT,
+ (length & ~3),
+ NULL, userbuffer, 0,
+ bytes_written, 0, 1);
+ userbuffer += (*bytes_written);
+ } else if (fromkern) {
+ ret |= sisusb_send_bulk_msg(sisusb,
+ SISUSB_EP_GFX_BULK_OUT,
+ (length & ~3),
+ kernbuffer, NULL, 0,
+ bytes_written, 0, 1);
+ kernbuffer += (*bytes_written);
+ } else {
+ ret |= sisusb_send_bulk_msg(sisusb,
+ SISUSB_EP_GFX_BULK_OUT,
+ (length & ~3),
+ NULL, NULL, index,
+ bytes_written, 0, 1);
+ kernbuffer += ((*bytes_written) &
+ (sisusb->obufsize-1));
+ }
+ }
+ if (ret) {
+ msgcount++;
+ if (msgcount < 500)
+ printk(KERN_ERR
+ "sisusbvga[%d]: Wrote %Zd of "
+ "%d bytes, error %d\n",
+ sisusb->minor, *bytes_written,
+ length, ret);
+ else if (msgcount == 500)
+ printk(KERN_ERR
+ "sisusbvga[%d]: Too many errors"
+ ", logging stopped\n",
+ sisusb->minor);
+ }
+ addr += (*bytes_written);
+ length -= (*bytes_written);
+ }
+
+ if (ret)
+ break;
+
+ }
+
+ return ret ? -EIO : 0;
+}
+
+static int sisusb_read_memio_byte(struct sisusb_usb_data *sisusb, int type,
+ u32 addr, u8 *data)
+{
+ struct sisusb_packet packet;
+ int ret;
+
+ CLEARPACKET(&packet);
+ packet.header = (1 << (addr & 3)) | (type << 6);
+ packet.address = addr & ~3;
+ ret = sisusb_send_packet(sisusb, 6, &packet);
+ *data = (u8)(packet.data >> ((addr & 3) << 3));
+ return ret;
+}
+
+static int sisusb_read_memio_word(struct sisusb_usb_data *sisusb, int type,
+ u32 addr, u16 *data)
+{
+ struct sisusb_packet packet;
+ int ret = 0;
+
+ CLEARPACKET(&packet);
+
+ packet.address = addr & ~3;
+
+ switch (addr & 3) {
+ case 0:
+ packet.header = (type << 6) | 0x0003;
+ ret = sisusb_send_packet(sisusb, 6, &packet);
+ *data = (u16)(packet.data);
+ break;
+ case 1:
+ packet.header = (type << 6) | 0x0006;
+ ret = sisusb_send_packet(sisusb, 6, &packet);
+ *data = (u16)(packet.data >> 8);
+ break;
+ case 2:
+ packet.header = (type << 6) | 0x000c;
+ ret = sisusb_send_packet(sisusb, 6, &packet);
+ *data = (u16)(packet.data >> 16);
+ break;
+ case 3:
+ packet.header = (type << 6) | 0x0008;
+ ret = sisusb_send_packet(sisusb, 6, &packet);
+ *data = (u16)(packet.data >> 24);
+ packet.header = (type << 6) | 0x0001;
+ packet.address = (addr & ~3) + 4;
+ ret |= sisusb_send_packet(sisusb, 6, &packet);
+ *data |= (u16)(packet.data << 8);
+ }
+
+ return ret;
+}
+
+static int sisusb_read_memio_24bit(struct sisusb_usb_data *sisusb, int type,
+ u32 addr, u32 *data)
+{
+ struct sisusb_packet packet;
+ int ret = 0;
+
+ packet.address = addr & ~3;
+
+ switch (addr & 3) {
+ case 0:
+ packet.header = (type << 6) | 0x0007;
+ ret = sisusb_send_packet(sisusb, 6, &packet);
+ *data = packet.data & 0x00ffffff;
+ break;
+ case 1:
+ packet.header = (type << 6) | 0x000e;
+ ret = sisusb_send_packet(sisusb, 6, &packet);
+ *data = packet.data >> 8;
+ break;
+ case 2:
+ packet.header = (type << 6) | 0x000c;
+ ret = sisusb_send_packet(sisusb, 6, &packet);
+ *data = packet.data >> 16;
+ packet.header = (type << 6) | 0x0001;
+ packet.address = (addr & ~3) + 4;
+ ret |= sisusb_send_packet(sisusb, 6, &packet);
+ *data |= ((packet.data & 0xff) << 16);
+ break;
+ case 3:
+ packet.header = (type << 6) | 0x0008;
+ ret = sisusb_send_packet(sisusb, 6, &packet);
+ *data = packet.data >> 24;
+ packet.header = (type << 6) | 0x0003;
+ packet.address = (addr & ~3) + 4;
+ ret |= sisusb_send_packet(sisusb, 6, &packet);
+ *data |= ((packet.data & 0xffff) << 8);
+ }
+
+ return ret;
+}
+
+static int sisusb_read_memio_long(struct sisusb_usb_data *sisusb, int type,
+ u32 addr, u32 *data)
+{
+ struct sisusb_packet packet;
+ int ret = 0;
+
+ packet.address = addr & ~3;
+
+ switch (addr & 3) {
+ case 0:
+ packet.header = (type << 6) | 0x000f;
+ ret = sisusb_send_packet(sisusb, 6, &packet);
+ *data = packet.data;
+ break;
+ case 1:
+ packet.header = (type << 6) | 0x000e;
+ ret = sisusb_send_packet(sisusb, 6, &packet);
+ *data = packet.data >> 8;
+ packet.header = (type << 6) | 0x0001;
+ packet.address = (addr & ~3) + 4;
+ ret |= sisusb_send_packet(sisusb, 6, &packet);
+ *data |= (packet.data << 24);
+ break;
+ case 2:
+ packet.header = (type << 6) | 0x000c;
+ ret = sisusb_send_packet(sisusb, 6, &packet);
+ *data = packet.data >> 16;
+ packet.header = (type << 6) | 0x0003;
+ packet.address = (addr & ~3) + 4;
+ ret |= sisusb_send_packet(sisusb, 6, &packet);
+ *data |= (packet.data << 16);
+ break;
+ case 3:
+ packet.header = (type << 6) | 0x0008;
+ ret = sisusb_send_packet(sisusb, 6, &packet);
+ *data = packet.data >> 24;
+ packet.header = (type << 6) | 0x0007;
+ packet.address = (addr & ~3) + 4;
+ ret |= sisusb_send_packet(sisusb, 6, &packet);
+ *data |= (packet.data << 8);
+ }
+
+ return ret;
+}
+
+static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
+ char *kernbuffer, int length,
+ char __user *userbuffer, ssize_t *bytes_read)
+{
+ int ret = 0;
+ char buf[4];
+ u16 swap16;
+ u32 swap32;
+
+ (*bytes_read = 0);
+
+ length &= 0x00ffffff;
+
+ while (length) {
+
+ switch (length) {
+
+ case 0:
+ return ret;
+
+ case 1:
+
+ ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM,
+ addr, &buf[0]);
+ if (!ret) {
+ (*bytes_read)++;
+ if (userbuffer) {
+ if (put_user(buf[0],
+ (u8 __user *)userbuffer)) {
+ return -EFAULT;
+ }
+ } else {
+ kernbuffer[0] = buf[0];
+ }
+ }
+ return ret;
+
+ case 2:
+ ret |= sisusb_read_memio_word(sisusb, SISUSB_TYPE_MEM,
+ addr, &swap16);
+ if (!ret) {
+ (*bytes_read) += 2;
+ if (userbuffer) {
+ if (put_user(swap16,
+ (u16 __user *)userbuffer))
+ return -EFAULT;
+ } else {
+ kernbuffer[0] = swap16 >> 8;
+ kernbuffer[1] = swap16 & 0xff;
+ }
+ }
+ return ret;
+
+ case 3:
+ ret |= sisusb_read_memio_24bit(sisusb, SISUSB_TYPE_MEM,
+ addr, &swap32);
+ if (!ret) {
+ (*bytes_read) += 3;
+ buf[0] = (swap32 >> 16) & 0xff;
+ buf[1] = (swap32 >> 8) & 0xff;
+ buf[2] = swap32 & 0xff;
+ if (userbuffer) {
+ if (copy_to_user(userbuffer, &buf[0], 3))
+ return -EFAULT;
+ } else {
+ kernbuffer[0] = buf[0];
+ kernbuffer[1] = buf[1];
+ kernbuffer[2] = buf[2];
+ }
+ }
+ return ret;
+
+ default:
+ ret |= sisusb_read_memio_long(sisusb, SISUSB_TYPE_MEM,
+ addr, &swap32);
+ if (!ret) {
+ (*bytes_read) += 4;
+ if (userbuffer) {
+ if (put_user(swap32,
+ (u32 __user *)userbuffer))
+ return -EFAULT;
+
+ userbuffer += 4;
+ } else {
+ kernbuffer[0] = (swap32 >> 24) & 0xff;
+ kernbuffer[1] = (swap32 >> 16) & 0xff;
+ kernbuffer[2] = (swap32 >> 8) & 0xff;
+ kernbuffer[3] = swap32 & 0xff;
+ kernbuffer += 4;
+ }
+ addr += 4;
+ length -= 4;
+ }
+#if 0 /* That does not work, as EP 2 is an OUT EP! */
+ default:
+ CLEARPACKET(&packet);
+ packet.header = 0x001f;
+ packet.address = 0x000001a0;
+ packet.data = 0x00000006;
+ ret |= sisusb_send_bridge_packet(sisusb, 10,
+ &packet, 0);
+ packet.header = 0x001f;
+ packet.address = 0x000001b0;
+ packet.data = (length & ~3) | 0x40000000;
+ ret |= sisusb_send_bridge_packet(sisusb, 10,
+ &packet, 0);
+ packet.header = 0x001f;
+ packet.address = 0x000001b4;
+ packet.data = addr;
+ ret |= sisusb_send_bridge_packet(sisusb, 10,
+ &packet, 0);
+ packet.header = 0x001f;
+ packet.address = 0x000001a4;
+ packet.data = 0x00000001;
+ ret |= sisusb_send_bridge_packet(sisusb, 10,
+ &packet, 0);
+ if (userbuffer) {
+ ret |= sisusb_recv_bulk_msg(sisusb,
+ SISUSB_EP_GFX_BULK_IN,
+ (length & ~3),
+ NULL, userbuffer,
+ bytes_read, 0);
+ if (!ret) userbuffer += (*bytes_read);
+ } else {
+ ret |= sisusb_recv_bulk_msg(sisusb,
+ SISUSB_EP_GFX_BULK_IN,
+ (length & ~3),
+ kernbuffer, NULL,
+ bytes_read, 0);
+ if (!ret) kernbuffer += (*bytes_read);
+ }
+ addr += (*bytes_read);
+ length -= (*bytes_read);
+#endif
+ }
+
+ if (ret)
+ break;
+ }
+
+ return ret;
+}
+
+/* High level: Gfx (indexed) register access */
+
+static int
+sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 data)
+{
+ int ret;
+ ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, index);
+ ret |= sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, data);
+ return ret;
+}
+
+static int
+sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 *data)
+{
+ int ret;
+ ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, index);
+ ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, data);
+ return ret;
+}
+
+static int
+sisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port, u8 idx,
+ u8 myand, u8 myor)
+{
+ int ret;
+ u8 tmp;
+
+ ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, idx);
+ ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, &tmp);
+ tmp &= myand;
+ tmp |= myor;
+ ret |= sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, tmp);
+ return ret;
+}
+
+static int
+sisusb_setidxregmask(struct sisusb_usb_data *sisusb, int port, u8 idx,
+ u8 data, u8 mask)
+{
+ int ret;
+ u8 tmp;
+ ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, idx);
+ ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, &tmp);
+ tmp &= ~(mask);
+ tmp |= (data & mask);
+ ret |= sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, tmp);
+ return ret;
+}
+
+static int
+sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port, u8 index, u8 myor)
+{
+ return(sisusb_setidxregandor(sisusb, port, index, 0xff, myor));
+}
+
+static int
+sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand)
+{
+ return(sisusb_setidxregandor(sisusb, port, idx, myand, 0x00));
+}
+
+/* access pci config registers (reg numbers 0, 4, 8, etc) */
+
+static int
+sisusb_write_pci_config(struct sisusb_usb_data *sisusb, int regnum, u32 data)
+{
+ struct sisusb_packet packet;
+ int ret;
+
+ packet.header = 0x008f;
+ packet.address = regnum | 0x10000;
+ packet.data = data;
+ ret = sisusb_send_packet(sisusb, 10, &packet);
+ return ret;
+}
+
+static int
+sisusb_read_pci_config(struct sisusb_usb_data *sisusb, int regnum, u32 *data)
+{
+ struct sisusb_packet packet;
+ int ret;
+
+ packet.header = 0x008f;
+ packet.address = (u32)regnum | 0x10000;
+ ret = sisusb_send_packet(sisusb, 6, &packet);
+ *data = packet.data;
+ return ret;
+}
+
+/* Clear video RAM */
+
+static int
+sisusb_clear_vram(struct sisusb_usb_data *sisusb, u32 address, int length)
+{
+ int ret, i;
+ ssize_t j;
+
+ if (address < sisusb->vrambase)
+ return 1;
+
+ if (address >= sisusb->vrambase + sisusb->vramsize)
+ return 1;
+
+ if (address + length > sisusb->vrambase + sisusb->vramsize)
+ length = sisusb->vrambase + sisusb->vramsize - address;
+
+ if (length <= 0)
+ return 0;
+
+ /* allocate free buffer/urb and clear the buffer */
+ if ((i = sisusb_alloc_outbuf(sisusb)) < 0)
+ return -EBUSY;
+
+ memset(sisusb->obuf[i], 0, sisusb->obufsize);
+
+ /* We can write a length > buffer size here. The buffer
+ * data will simply be re-used (like a ring-buffer).
+ */
+ ret = sisusb_write_mem_bulk(sisusb, address, NULL, length, NULL, i, &j);
+
+ /* Free the buffer/urb */
+ sisusb_free_outbuf(sisusb, i);
+
+ return ret;
+}
+
+/* Initialize the graphics core (return 0 on success)
+ * This resets the graphics hardware and puts it into
+ * a defined mode (640x480@60Hz)
+ */
+
+#define GETREG(r,d) sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, r, d)
+#define SETREG(r,d) sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, r, d)
+#define SETIREG(r,i,d) sisusb_setidxreg(sisusb, r, i, d)
+#define GETIREG(r,i,d) sisusb_getidxreg(sisusb, r, i, d)
+#define SETIREGOR(r,i,o) sisusb_setidxregor(sisusb, r, i, o)
+#define SETIREGAND(r,i,a) sisusb_setidxregand(sisusb, r, i, a)
+#define SETIREGANDOR(r,i,a,o) sisusb_setidxregandor(sisusb, r, i, a, o)
+#define READL(a,d) sisusb_read_memio_long(sisusb, SISUSB_TYPE_MEM, a, d)
+#define WRITEL(a,d) sisusb_write_memio_long(sisusb, SISUSB_TYPE_MEM, a, d)
+#define READB(a,d) sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d)
+#define WRITEB(a,d) sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d)
+
+static int
+sisusb_triggersr16(struct sisusb_usb_data *sisusb, u8 ramtype)
+{
+ int ret;
+ u8 tmp8;
+
+ ret = GETIREG(SISSR, 0x16, &tmp8);
+ if (ramtype <= 1) {
+ tmp8 &= 0x3f;
+ ret |= SETIREG(SISSR, 0x16, tmp8);
+ tmp8 |= 0x80;
+ ret |= SETIREG(SISSR, 0x16, tmp8);
+ } else {
+ tmp8 |= 0xc0;
+ ret |= SETIREG(SISSR, 0x16, tmp8);
+ tmp8 &= 0x0f;
+ ret |= SETIREG(SISSR, 0x16, tmp8);
+ tmp8 |= 0x80;
+ ret |= SETIREG(SISSR, 0x16, tmp8);
+ tmp8 &= 0x0f;
+ ret |= SETIREG(SISSR, 0x16, tmp8);
+ tmp8 |= 0xd0;
+ ret |= SETIREG(SISSR, 0x16, tmp8);
+ tmp8 &= 0x0f;
+ ret |= SETIREG(SISSR, 0x16, tmp8);
+ tmp8 |= 0xa0;
+ ret |= SETIREG(SISSR, 0x16, tmp8);
+ }
+ return ret;
+}
+
+static int
+sisusb_getbuswidth(struct sisusb_usb_data *sisusb, int *bw, int *chab)
+{
+ int ret;
+ u8 ramtype, done = 0;
+ u32 t0, t1, t2, t3;
+ u32 ramptr = SISUSB_PCI_MEMBASE;
+
+ ret = GETIREG(SISSR, 0x3a, &ramtype);
+ ramtype &= 3;
+
+ ret |= SETIREG(SISSR, 0x13, 0x00);
+
+ if (ramtype <= 1) {
+ ret |= SETIREG(SISSR, 0x14, 0x12);
+ ret |= SETIREGAND(SISSR, 0x15, 0xef);
+ } else {
+ ret |= SETIREG(SISSR, 0x14, 0x02);
+ }
+
+ ret |= sisusb_triggersr16(sisusb, ramtype);
+ ret |= WRITEL(ramptr + 0, 0x01234567);
+ ret |= WRITEL(ramptr + 4, 0x456789ab);
+ ret |= WRITEL(ramptr + 8, 0x89abcdef);
+ ret |= WRITEL(ramptr + 12, 0xcdef0123);
+ ret |= WRITEL(ramptr + 16, 0x55555555);
+ ret |= WRITEL(ramptr + 20, 0x55555555);
+ ret |= WRITEL(ramptr + 24, 0xffffffff);
+ ret |= WRITEL(ramptr + 28, 0xffffffff);
+ ret |= READL(ramptr + 0, &t0);
+ ret |= READL(ramptr + 4, &t1);
+ ret |= READL(ramptr + 8, &t2);
+ ret |= READL(ramptr + 12, &t3);
+
+ if (ramtype <= 1) {
+
+ *chab = 0; *bw = 64;
+
+ if ((t3 != 0xcdef0123) || (t2 != 0x89abcdef)) {
+ if ((t1 == 0x456789ab) && (t0 == 0x01234567)) {
+ *chab = 0; *bw = 64;
+ ret |= SETIREGAND(SISSR, 0x14, 0xfd);
+ }
+ }
+ if ((t1 != 0x456789ab) || (t0 != 0x01234567)) {
+ *chab = 1; *bw = 64;
+ ret |= SETIREGANDOR(SISSR, 0x14, 0xfc,0x01);
+
+ ret |= sisusb_triggersr16(sisusb, ramtype);
+ ret |= WRITEL(ramptr + 0, 0x89abcdef);
+ ret |= WRITEL(ramptr + 4, 0xcdef0123);
+ ret |= WRITEL(ramptr + 8, 0x55555555);
+ ret |= WRITEL(ramptr + 12, 0x55555555);
+ ret |= WRITEL(ramptr + 16, 0xaaaaaaaa);
+ ret |= WRITEL(ramptr + 20, 0xaaaaaaaa);
+ ret |= READL(ramptr + 4, &t1);
+
+ if (t1 != 0xcdef0123) {
+ *bw = 32;
+ ret |= SETIREGOR(SISSR, 0x15, 0x10);
+ }
+ }
+
+ } else {
+
+ *chab = 0; *bw = 64; /* default: cha, bw = 64 */
+
+ done = 0;
+
+ if (t1 == 0x456789ab) {
+ if (t0 == 0x01234567) {
+ *chab = 0; *bw = 64;
+ done = 1;
+ }
+ } else {
+ if (t0 == 0x01234567) {
+ *chab = 0; *bw = 32;
+ ret |= SETIREG(SISSR, 0x14, 0x00);
+ done = 1;
+ }
+ }
+
+ if (!done) {
+ ret |= SETIREG(SISSR, 0x14, 0x03);
+ ret |= sisusb_triggersr16(sisusb, ramtype);
+
+ ret |= WRITEL(ramptr + 0, 0x01234567);
+ ret |= WRITEL(ramptr + 4, 0x456789ab);
+ ret |= WRITEL(ramptr + 8, 0x89abcdef);
+ ret |= WRITEL(ramptr + 12, 0xcdef0123);
+ ret |= WRITEL(ramptr + 16, 0x55555555);
+ ret |= WRITEL(ramptr + 20, 0x55555555);
+ ret |= WRITEL(ramptr + 24, 0xffffffff);
+ ret |= WRITEL(ramptr + 28, 0xffffffff);
+ ret |= READL(ramptr + 0, &t0);
+ ret |= READL(ramptr + 4, &t1);
+
+ if (t1 == 0x456789ab) {
+ if (t0 == 0x01234567) {
+ *chab = 1; *bw = 64;
+ return ret;
+ } /* else error */
+ } else {
+ if (t0 == 0x01234567) {
+ *chab = 1; *bw = 32;
+ ret |= SETIREG(SISSR, 0x14, 0x01);
+ } /* else error */
+ }
+ }
+ }
+ return ret;
+}
+
+static int
+sisusb_verify_mclk(struct sisusb_usb_data *sisusb)
+{
+ int ret = 0;
+ u32 ramptr = SISUSB_PCI_MEMBASE;
+ u8 tmp1, tmp2, i, j;
+
+ ret |= WRITEB(ramptr, 0xaa);
+ ret |= WRITEB(ramptr + 16, 0x55);
+ ret |= READB(ramptr, &tmp1);
+ ret |= READB(ramptr + 16, &tmp2);
+ if ((tmp1 != 0xaa) || (tmp2 != 0x55)) {
+ for (i = 0, j = 16; i < 2; i++, j += 16) {
+ ret |= GETIREG(SISSR, 0x21, &tmp1);
+ ret |= SETIREGAND(SISSR, 0x21, (tmp1 & 0xfb));
+ ret |= SETIREGOR(SISSR, 0x3c, 0x01); /* not on 330 */
+ ret |= SETIREGAND(SISSR, 0x3c, 0xfe); /* not on 330 */
+ ret |= SETIREG(SISSR, 0x21, tmp1);
+ ret |= WRITEB(ramptr + 16 + j, j);
+ ret |= READB(ramptr + 16 + j, &tmp1);
+ if (tmp1 == j) {
+ ret |= WRITEB(ramptr + j, j);
+ break;
+ }
+ }
+ }
+ return ret;
+}
+
+static int
+sisusb_set_rank(struct sisusb_usb_data *sisusb, int *iret, int index,
+ u8 rankno, u8 chab, const u8 dramtype[][5],
+ int bw)
+{
+ int ret = 0, ranksize;
+ u8 tmp;
+
+ *iret = 0;
+
+ if ((rankno == 2) && (dramtype[index][0] == 2))
+ return ret;
+
+ ranksize = dramtype[index][3] / 2 * bw / 32;
+
+ if ((ranksize * rankno) > 128)
+ return ret;
+
+ tmp = 0;
+ while ((ranksize >>= 1) > 0) tmp += 0x10;
+ tmp |= ((rankno - 1) << 2);
+ tmp |= ((bw / 64) & 0x02);
+ tmp |= (chab & 0x01);
+
+ ret = SETIREG(SISSR, 0x14, tmp);
+ ret |= sisusb_triggersr16(sisusb, 0); /* sic! */
+
+ *iret = 1;
+
+ return ret;
+}
+
+static int
+sisusb_check_rbc(struct sisusb_usb_data *sisusb, int *iret, u32 inc, int testn)
+{
+ int ret = 0, i;
+ u32 j, tmp;
+
+ *iret = 0;
+
+ for (i = 0, j = 0; i < testn; i++) {
+ ret |= WRITEL(sisusb->vrambase + j, j);
+ j += inc;
+ }
+
+ for (i = 0, j = 0; i < testn; i++) {
+ ret |= READL(sisusb->vrambase + j, &tmp);
+ if (tmp != j) return ret;
+ j += inc;
+ }
+
+ *iret = 1;
+ return ret;
+}
+
+static int
+sisusb_check_ranks(struct sisusb_usb_data *sisusb, int *iret, int rankno,
+ int idx, int bw, const u8 rtype[][5])
+{
+ int ret = 0, i, i2ret;
+ u32 inc;
+
+ *iret = 0;
+
+ for (i = rankno; i >= 1; i--) {
+ inc = 1 << (rtype[idx][2] +
+ rtype[idx][1] +
+ rtype[idx][0] +
+ bw / 64 + i);
+ ret |= sisusb_check_rbc(sisusb, &i2ret, inc, 2);
+ if (!i2ret)
+ return ret;
+ }
+
+ inc = 1 << (rtype[idx][2] + bw / 64 + 2);
+ ret |= sisusb_check_rbc(sisusb, &i2ret, inc, 4);
+ if (!i2ret)
+ return ret;
+
+ inc = 1 << (10 + bw / 64);
+ ret |= sisusb_check_rbc(sisusb, &i2ret, inc, 2);
+ if (!i2ret)
+ return ret;
+
+ *iret = 1;
+ return ret;
+}
+
+static int
+sisusb_get_sdram_size(struct sisusb_usb_data *sisusb, int *iret, int bw,
+ int chab)
+{
+ int ret = 0, i2ret = 0, i, j;
+ static const u8 sdramtype[13][5] = {
+ { 2, 12, 9, 64, 0x35 },
+ { 1, 13, 9, 64, 0x44 },
+ { 2, 12, 8, 32, 0x31 },
+ { 2, 11, 9, 32, 0x25 },
+ { 1, 12, 9, 32, 0x34 },
+ { 1, 13, 8, 32, 0x40 },
+ { 2, 11, 8, 16, 0x21 },
+ { 1, 12, 8, 16, 0x30 },
+ { 1, 11, 9, 16, 0x24 },
+ { 1, 11, 8, 8, 0x20 },
+ { 2, 9, 8, 4, 0x01 },
+ { 1, 10, 8, 4, 0x10 },
+ { 1, 9, 8, 2, 0x00 }
+ };
+
+ *iret = 1; /* error */
+
+ for (i = 0; i < 13; i++) {
+ ret |= SETIREGANDOR(SISSR, 0x13, 0x80, sdramtype[i][4]);
+ for (j = 2; j > 0; j--) {
+ ret |= sisusb_set_rank(sisusb, &i2ret, i, j,
+ chab, sdramtype, bw);
+ if (!i2ret)
+ continue;
+
+ ret |= sisusb_check_ranks(sisusb, &i2ret, j, i,
+ bw, sdramtype);
+ if (i2ret) {
+ *iret = 0; /* ram size found */
+ return ret;
+ }
+ }
+ }
+
+ return ret;
+}
+
+static int
+sisusb_setup_screen(struct sisusb_usb_data *sisusb, int clrall, int drwfr)
+{
+ int ret = 0;
+ u32 address;
+ int i, length, modex, modey, bpp;
+
+ modex = 640; modey = 480; bpp = 2;
+
+ address = sisusb->vrambase; /* Clear video ram */
+
+ if (clrall)
+ length = sisusb->vramsize;
+ else
+ length = modex * bpp * modey;
+
+ ret = sisusb_clear_vram(sisusb, address, length);
+
+ if (!ret && drwfr) {
+ for (i = 0; i < modex; i++) {
+ address = sisusb->vrambase + (i * bpp);
+ ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
+ address, 0xf100);
+ address += (modex * (modey-1) * bpp);
+ ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
+ address, 0xf100);
+ }
+ for (i = 0; i < modey; i++) {
+ address = sisusb->vrambase + ((i * modex) * bpp);
+ ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
+ address, 0xf100);
+ address += ((modex - 1) * bpp);
+ ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
+ address, 0xf100);
+ }
+ }
+
+ return ret;
+}
+
+static int
+sisusb_set_default_mode(struct sisusb_usb_data *sisusb, int touchengines)
+{
+ int ret = 0, i, j, modex, modey, bpp, du;
+ u8 sr31, cr63, tmp8;
+ static const char attrdata[] = {
+ 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+ 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
+ 0x01,0x00,0x00,0x00
+ };
+ static const char crtcrdata[] = {
+ 0x5f,0x4f,0x50,0x82,0x54,0x80,0x0b,0x3e,
+ 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xea,0x8c,0xdf,0x28,0x40,0xe7,0x04,0xa3,
+ 0xff
+ };
+ static const char grcdata[] = {
+ 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0f,
+ 0xff
+ };
+ static const char crtcdata[] = {
+ 0x5f,0x4f,0x4f,0x83,0x55,0x81,0x0b,0x3e,
+ 0xe9,0x8b,0xdf,0xe8,0x0c,0x00,0x00,0x05,
+ 0x00
+ };
+
+ modex = 640; modey = 480; bpp = 2;
+
+ GETIREG(SISSR, 0x31, &sr31);
+ GETIREG(SISCR, 0x63, &cr63);
+ SETIREGOR(SISSR, 0x01, 0x20);
+ SETIREG(SISCR, 0x63, cr63 & 0xbf);
+ SETIREGOR(SISCR, 0x17, 0x80);
+ SETIREGOR(SISSR, 0x1f, 0x04);
+ SETIREGAND(SISSR, 0x07, 0xfb);
+ SETIREG(SISSR, 0x00, 0x03); /* seq */
+ SETIREG(SISSR, 0x01, 0x21);
+ SETIREG(SISSR, 0x02, 0x0f);
+ SETIREG(SISSR, 0x03, 0x00);
+ SETIREG(SISSR, 0x04, 0x0e);
+ SETREG(SISMISCW, 0x23); /* misc */
+ for (i = 0; i <= 0x18; i++) { /* crtc */
+ SETIREG(SISCR, i, crtcrdata[i]);
+ }
+ for (i = 0; i <= 0x13; i++) { /* att */
+ GETREG(SISINPSTAT, &tmp8);
+ SETREG(SISAR, i);
+ SETREG(SISAR, attrdata[i]);
+ }
+ GETREG(SISINPSTAT, &tmp8);
+ SETREG(SISAR, 0x14);
+ SETREG(SISAR, 0x00);
+ GETREG(SISINPSTAT, &tmp8);
+ SETREG(SISAR, 0x20);
+ GETREG(SISINPSTAT, &tmp8);
+ for (i = 0; i <= 0x08; i++) { /* grc */
+ SETIREG(SISGR, i, grcdata[i]);
+ }
+ SETIREGAND(SISGR, 0x05, 0xbf);
+ for (i = 0x0A; i <= 0x0E; i++) { /* clr ext */
+ SETIREG(SISSR, i, 0x00);
+ }
+ SETIREGAND(SISSR, 0x37, 0xfe);
+ SETREG(SISMISCW, 0xef); /* sync */
+ SETIREG(SISCR, 0x11, 0x00); /* crtc */
+ for (j = 0x00, i = 0; i <= 7; i++, j++) {
+ SETIREG(SISCR, j, crtcdata[i]);
+ }
+ for (j = 0x10; i <= 10; i++, j++) {
+ SETIREG(SISCR, j, crtcdata[i]);
+ }
+ for (j = 0x15; i <= 12; i++, j++) {
+ SETIREG(SISCR, j, crtcdata[i]);
+ }
+ for (j = 0x0A; i <= 15; i++, j++) {
+ SETIREG(SISSR, j, crtcdata[i]);
+ }
+ SETIREG(SISSR, 0x0E, (crtcdata[16] & 0xE0));
+ SETIREGANDOR(SISCR, 0x09, 0x5f, ((crtcdata[16] & 0x01) << 5));
+ SETIREG(SISCR, 0x14, 0x4f);
+ du = (modex / 16) * (bpp * 2); /* offset/pitch */
+ if (modex % 16) du += bpp;
+ SETIREGANDOR(SISSR, 0x0e, 0xf0, ((du >> 8) & 0x0f));
+ SETIREG(SISCR, 0x13, (du & 0xff));
+ du <<= 5;
+ tmp8 = du >> 8;
+ if (du & 0xff) tmp8++;
+ SETIREG(SISSR, 0x10, tmp8);
+ SETIREG(SISSR, 0x31, 0x00); /* VCLK */
+ SETIREG(SISSR, 0x2b, 0x1b);
+ SETIREG(SISSR, 0x2c, 0xe1);
+ SETIREG(SISSR, 0x2d, 0x01);
+ SETIREGAND(SISSR, 0x3d, 0xfe); /* FIFO */
+ SETIREG(SISSR, 0x08, 0xae);
+ SETIREGAND(SISSR, 0x09, 0xf0);
+ SETIREG(SISSR, 0x08, 0x34);
+ SETIREGOR(SISSR, 0x3d, 0x01);
+ SETIREGAND(SISSR, 0x1f, 0x3f); /* mode regs */
+ SETIREGANDOR(SISSR, 0x06, 0xc0, 0x0a);
+ SETIREG(SISCR, 0x19, 0x00);
+ SETIREGAND(SISCR, 0x1a, 0xfc);
+ SETIREGAND(SISSR, 0x0f, 0xb7);
+ SETIREGAND(SISSR, 0x31, 0xfb);
+ SETIREGANDOR(SISSR, 0x21, 0x1f, 0xa0);
+ SETIREGAND(SISSR, 0x32, 0xf3);
+ SETIREGANDOR(SISSR, 0x07, 0xf8, 0x03);
+ SETIREG(SISCR, 0x52, 0x6c);
+
+ SETIREG(SISCR, 0x0d, 0x00); /* adjust frame */
+ SETIREG(SISCR, 0x0c, 0x00);
+ SETIREG(SISSR, 0x0d, 0x00);
+ SETIREGAND(SISSR, 0x37, 0xfe);
+
+ SETIREG(SISCR, 0x32, 0x20);
+ SETIREGAND(SISSR, 0x01, 0xdf); /* enable display */
+ SETIREG(SISCR, 0x63, (cr63 & 0xbf));
+ SETIREG(SISSR, 0x31, (sr31 & 0xfb));
+
+ if (touchengines) {
+ SETIREG(SISSR, 0x20, 0xa1); /* enable engines */
+ SETIREGOR(SISSR, 0x1e, 0x5a);
+
+ SETIREG(SISSR, 0x26, 0x01); /* disable cmdqueue */
+ SETIREG(SISSR, 0x27, 0x1f);
+ SETIREG(SISSR, 0x26, 0x00);
+ }
+
+ SETIREG(SISCR, 0x34, 0x44); /* we just set std mode #44 */
+
+ return ret;
+}
+
+static int
+sisusb_init_gfxcore(struct sisusb_usb_data *sisusb)
+{
+ int ret = 0, i, j, bw, chab, iret, retry = 3;
+ u8 tmp8, ramtype;
+ u32 tmp32;
+ static const char mclktable[] = {
+ 0x3b, 0x22, 0x01, 143,
+ 0x3b, 0x22, 0x01, 143,
+ 0x3b, 0x22, 0x01, 143,
+ 0x3b, 0x22, 0x01, 143
+ };
+ static const char eclktable[] = {
+ 0x3b, 0x22, 0x01, 143,
+ 0x3b, 0x22, 0x01, 143,
+ 0x3b, 0x22, 0x01, 143,
+ 0x3b, 0x22, 0x01, 143
+ };
+ static const char ramtypetable1[] = {
+ 0x00, 0x04, 0x60, 0x60,
+ 0x0f, 0x0f, 0x1f, 0x1f,
+ 0xba, 0xba, 0xba, 0xba,
+ 0xa9, 0xa9, 0xac, 0xac,
+ 0xa0, 0xa0, 0xa0, 0xa8,
+ 0x00, 0x00, 0x02, 0x02,
+ 0x30, 0x30, 0x40, 0x40
+ };
+ static const char ramtypetable2[] = {
+ 0x77, 0x77, 0x44, 0x44,
+ 0x77, 0x77, 0x44, 0x44,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x5b, 0x5b, 0xab, 0xab,
+ 0x00, 0x00, 0xf0, 0xf8
+ };
+
+ while (retry--) {
+
+ /* Enable VGA */
+ ret = GETREG(SISVGAEN, &tmp8);
+ ret |= SETREG(SISVGAEN, (tmp8 | 0x01));
+
+ /* Enable GPU access to VRAM */
+ ret |= GETREG(SISMISCR, &tmp8);
+ ret |= SETREG(SISMISCW, (tmp8 | 0x01));
+
+ if (ret) continue;
+
+ /* Reset registers */
+ ret |= SETIREGAND(SISCR, 0x5b, 0xdf);
+ ret |= SETIREG(SISSR, 0x05, 0x86);
+ ret |= SETIREGOR(SISSR, 0x20, 0x01);
+
+ ret |= SETREG(SISMISCW, 0x67);
+
+ for (i = 0x06; i <= 0x1f; i++) {
+ ret |= SETIREG(SISSR, i, 0x00);
+ }
+ for (i = 0x21; i <= 0x27; i++) {
+ ret |= SETIREG(SISSR, i, 0x00);
+ }
+ for (i = 0x31; i <= 0x3d; i++) {
+ ret |= SETIREG(SISSR, i, 0x00);
+ }
+ for (i = 0x12; i <= 0x1b; i++) {
+ ret |= SETIREG(SISSR, i, 0x00);
+ }
+ for (i = 0x79; i <= 0x7c; i++) {
+ ret |= SETIREG(SISCR, i, 0x00);
+ }
+
+ if (ret) continue;
+
+ ret |= SETIREG(SISCR, 0x63, 0x80);
+
+ ret |= GETIREG(SISSR, 0x3a, &ramtype);
+ ramtype &= 0x03;
+
+ ret |= SETIREG(SISSR, 0x28, mclktable[ramtype * 4]);
+ ret |= SETIREG(SISSR, 0x29, mclktable[(ramtype * 4) + 1]);
+ ret |= SETIREG(SISSR, 0x2a, mclktable[(ramtype * 4) + 2]);
+
+ ret |= SETIREG(SISSR, 0x2e, eclktable[ramtype * 4]);
+ ret |= SETIREG(SISSR, 0x2f, eclktable[(ramtype * 4) + 1]);
+ ret |= SETIREG(SISSR, 0x30, eclktable[(ramtype * 4) + 2]);
+
+ ret |= SETIREG(SISSR, 0x07, 0x18);
+ ret |= SETIREG(SISSR, 0x11, 0x0f);
+
+ if (ret) continue;
+
+ for (i = 0x15, j = 0; i <= 0x1b; i++, j++) {
+ ret |= SETIREG(SISSR, i, ramtypetable1[(j*4) + ramtype]);
+ }
+ for (i = 0x40, j = 0; i <= 0x44; i++, j++) {
+ ret |= SETIREG(SISCR, i, ramtypetable2[(j*4) + ramtype]);
+ }
+
+ ret |= SETIREG(SISCR, 0x49, 0xaa);
+
+ ret |= SETIREG(SISSR, 0x1f, 0x00);
+ ret |= SETIREG(SISSR, 0x20, 0xa0);
+ ret |= SETIREG(SISSR, 0x23, 0xf6);
+ ret |= SETIREG(SISSR, 0x24, 0x0d);
+ ret |= SETIREG(SISSR, 0x25, 0x33);
+
+ ret |= SETIREG(SISSR, 0x11, 0x0f);
+
+ ret |= SETIREGOR(SISPART1, 0x2f, 0x01);
+
+ ret |= SETIREGAND(SISCAP, 0x3f, 0xef);
+
+ if (ret) continue;
+
+ ret |= SETIREG(SISPART1, 0x00, 0x00);
+
+ ret |= GETIREG(SISSR, 0x13, &tmp8);
+ tmp8 >>= 4;
+
+ ret |= SETIREG(SISPART1, 0x02, 0x00);
+ ret |= SETIREG(SISPART1, 0x2e, 0x08);
+
+ ret |= sisusb_read_pci_config(sisusb, 0x50, &tmp32);
+ tmp32 &= 0x00f00000;
+ tmp8 = (tmp32 == 0x100000) ? 0x33 : 0x03;
+ ret |= SETIREG(SISSR, 0x25, tmp8);
+ tmp8 = (tmp32 == 0x100000) ? 0xaa : 0x88;
+ ret |= SETIREG(SISCR, 0x49, tmp8);
+
+ ret |= SETIREG(SISSR, 0x27, 0x1f);
+ ret |= SETIREG(SISSR, 0x31, 0x00);
+ ret |= SETIREG(SISSR, 0x32, 0x11);
+ ret |= SETIREG(SISSR, 0x33, 0x00);
+
+ if (ret) continue;
+
+ ret |= SETIREG(SISCR, 0x83, 0x00);
+
+ ret |= sisusb_set_default_mode(sisusb, 0);
+
+ ret |= SETIREGAND(SISSR, 0x21, 0xdf);
+ ret |= SETIREGOR(SISSR, 0x01, 0x20);
+ ret |= SETIREGOR(SISSR, 0x16, 0x0f);
+
+ ret |= sisusb_triggersr16(sisusb, ramtype);
+
+ /* Disable refresh */
+ ret |= SETIREGAND(SISSR, 0x17, 0xf8);
+ ret |= SETIREGOR(SISSR, 0x19, 0x03);
+
+ ret |= sisusb_getbuswidth(sisusb, &bw, &chab);
+ ret |= sisusb_verify_mclk(sisusb);
+
+ if (ramtype <= 1) {
+ ret |= sisusb_get_sdram_size(sisusb, &iret, bw, chab);
+ if (iret) {
+ printk(KERN_ERR "sisusbvga[%d]: RAM size "
+ "detection failed, "
+ "assuming 8MB video RAM\n",
+ sisusb->minor);
+ ret |= SETIREG(SISSR,0x14,0x31);
+ /* TODO */
+ }
+ } else {
+ printk(KERN_ERR "sisusbvga[%d]: DDR RAM device found, "
+ "assuming 8MB video RAM\n",
+ sisusb->minor);
+ ret |= SETIREG(SISSR,0x14,0x31);
+ /* *** TODO *** */
+ }
+
+ /* Enable refresh */
+ ret |= SETIREG(SISSR, 0x16, ramtypetable1[4 + ramtype]);
+ ret |= SETIREG(SISSR, 0x17, ramtypetable1[8 + ramtype]);
+ ret |= SETIREG(SISSR, 0x19, ramtypetable1[16 + ramtype]);
+
+ ret |= SETIREGOR(SISSR, 0x21, 0x20);
+
+ ret |= SETIREG(SISSR, 0x22, 0xfb);
+ ret |= SETIREG(SISSR, 0x21, 0xa5);
+
+ if (ret == 0)
+ break;
+ }
+
+ return ret;
+}
+
+#undef SETREG
+#undef GETREG
+#undef SETIREG
+#undef GETIREG
+#undef SETIREGOR
+#undef SETIREGAND
+#undef SETIREGANDOR
+#undef READL
+#undef WRITEL
+
+static void
+sisusb_get_ramconfig(struct sisusb_usb_data *sisusb)
+{
+ u8 tmp8, tmp82, ramtype;
+ int bw = 0;
+ char *ramtypetext1 = NULL;
+ const char *ramtypetext2[] = { "SDR SDRAM", "SDR SGRAM",
+ "DDR SDRAM", "DDR SGRAM" };
+ static const int busSDR[4] = {64, 64, 128, 128};
+ static const int busDDR[4] = {32, 32, 64, 64};
+ static const int busDDRA[4] = {64+32, 64+32 , (64+32)*2, (64+32)*2};
+
+ sisusb_getidxreg(sisusb, SISSR, 0x14, &tmp8);
+ sisusb_getidxreg(sisusb, SISSR, 0x15, &tmp82);
+ sisusb_getidxreg(sisusb, SISSR, 0x3a, &ramtype);
+ sisusb->vramsize = (1 << ((tmp8 & 0xf0) >> 4)) * 1024 * 1024;
+ ramtype &= 0x03;
+ switch ((tmp8 >> 2) & 0x03) {
+ case 0: ramtypetext1 = "1 ch/1 r";
+ if (tmp82 & 0x10) {
+ bw = 32;
+ } else {
+ bw = busSDR[(tmp8 & 0x03)];
+ }
+ break;
+ case 1: ramtypetext1 = "1 ch/2 r";
+ sisusb->vramsize <<= 1;
+ bw = busSDR[(tmp8 & 0x03)];
+ break;
+ case 2: ramtypetext1 = "asymmeric";
+ sisusb->vramsize += sisusb->vramsize/2;
+ bw = busDDRA[(tmp8 & 0x03)];
+ break;
+ case 3: ramtypetext1 = "2 channel";
+ sisusb->vramsize <<= 1;
+ bw = busDDR[(tmp8 & 0x03)];
+ break;
+ }
+
+ printk(KERN_INFO "sisusbvga[%d]: %dMB %s %s, bus width %d\n",
+ sisusb->minor, (sisusb->vramsize >> 20), ramtypetext1,
+ ramtypetext2[ramtype], bw);
+}
+
+static int
+sisusb_do_init_gfxdevice(struct sisusb_usb_data *sisusb)
+{
+ struct sisusb_packet packet;
+ int ret;
+ u32 tmp32;
+
+ /* Do some magic */
+ packet.header = 0x001f;
+ packet.address = 0x00000324;
+ packet.data = 0x00000004;
+ ret = sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
+
+ packet.header = 0x001f;
+ packet.address = 0x00000364;
+ packet.data = 0x00000004;
+ ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
+
+ packet.header = 0x001f;
+ packet.address = 0x00000384;
+ packet.data = 0x00000004;
+ ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
+
+ packet.header = 0x001f;
+ packet.address = 0x00000100;
+ packet.data = 0x00000700;
+ ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
+
+ packet.header = 0x000f;
+ packet.address = 0x00000004;
+ ret |= sisusb_send_bridge_packet(sisusb, 6, &packet, 0);
+ packet.data |= 0x17;
+ ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
+
+ /* Init BAR 0 (VRAM) */
+ ret |= sisusb_read_pci_config(sisusb, 0x10, &tmp32);
+ ret |= sisusb_write_pci_config(sisusb, 0x10, 0xfffffff0);
+ ret |= sisusb_read_pci_config(sisusb, 0x10, &tmp32);
+ tmp32 &= 0x0f;
+ tmp32 |= SISUSB_PCI_MEMBASE;
+ ret |= sisusb_write_pci_config(sisusb, 0x10, tmp32);
+
+ /* Init BAR 1 (MMIO) */
+ ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32);
+ ret |= sisusb_write_pci_config(sisusb, 0x14, 0xfffffff0);
+ ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32);
+ tmp32 &= 0x0f;
+ tmp32 |= SISUSB_PCI_MMIOBASE;
+ ret |= sisusb_write_pci_config(sisusb, 0x14, tmp32);
+
+ /* Init BAR 2 (i/o ports) */
+ ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32);
+ ret |= sisusb_write_pci_config(sisusb, 0x18, 0xfffffff0);
+ ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32);
+ tmp32 &= 0x0f;
+ tmp32 |= SISUSB_PCI_IOPORTBASE;
+ ret |= sisusb_write_pci_config(sisusb, 0x18, tmp32);
+
+ /* Enable memory and i/o access */
+ ret |= sisusb_read_pci_config(sisusb, 0x04, &tmp32);
+ tmp32 |= 0x3;
+ ret |= sisusb_write_pci_config(sisusb, 0x04, tmp32);
+
+ if (ret == 0) {
+ /* Some further magic */
+ packet.header = 0x001f;
+ packet.address = 0x00000050;
+ packet.data = 0x000000ff;
+ ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
+ }
+
+ return ret;
+}
+
+/* Initialize the graphics device (return 0 on success)
+ * This initializes the net2280 as well as the PCI registers
+ * of the graphics board.
+ */
+
+static int
+sisusb_init_gfxdevice(struct sisusb_usb_data *sisusb, int initscreen)
+{
+ int ret = 0, test = 0;
+ u32 tmp32;
+
+ if (sisusb->devinit == 1) {
+ /* Read PCI BARs and see if they have been set up */
+ ret |= sisusb_read_pci_config(sisusb, 0x10, &tmp32);
+ if (ret) return ret;
+ if ((tmp32 & 0xfffffff0) == SISUSB_PCI_MEMBASE) test++;
+
+ ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32);
+ if (ret) return ret;
+ if ((tmp32 & 0xfffffff0) == SISUSB_PCI_MMIOBASE) test++;
+
+ ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32);
+ if (ret) return ret;
+ if ((tmp32 & 0xfffffff0) == SISUSB_PCI_IOPORTBASE) test++;
+ }
+
+ /* No? So reset the device */
+ if ((sisusb->devinit == 0) || (test != 3)) {
+
+ ret |= sisusb_do_init_gfxdevice(sisusb);
+
+ if (ret == 0)
+ sisusb->devinit = 1;
+
+ }
+
+ if (sisusb->devinit) {
+ /* Initialize the graphics core */
+ if (sisusb_init_gfxcore(sisusb) == 0) {
+ sisusb->gfxinit = 1;
+ sisusb_get_ramconfig(sisusb);
+ ret |= sisusb_set_default_mode(sisusb, 1);
+ ret |= sisusb_setup_screen(sisusb, 1, initscreen);
+ }
+ }
+
+ return ret;
+}
+
+/* fops */
+
+static int
+sisusb_open(struct inode *inode, struct file *file)
+{
+ struct sisusb_usb_data *sisusb;
+ struct usb_interface *interface;
+ int subminor = iminor(inode);
+
+ down(&disconnect_sem);
+
+ if (!(interface = usb_find_interface(&sisusb_driver, subminor))) {
+ printk(KERN_ERR "sisusb[%d]: Failed to find interface\n",
+ subminor);
+ up(&disconnect_sem);
+ return -ENODEV;
+ }
+
+ if (!(sisusb = usb_get_intfdata(interface))) {
+ up(&disconnect_sem);
+ return -ENODEV;
+ }
+
+ down(&sisusb->lock);
+
+ if (!sisusb->present || !sisusb->ready) {
+ up(&sisusb->lock);
+ up(&disconnect_sem);
+ return -ENODEV;
+ }
+
+ if (sisusb->isopen) {
+ up(&sisusb->lock);
+ up(&disconnect_sem);
+ return -EBUSY;
+ }
+
+ if (!sisusb->devinit) {
+ if (sisusb->sisusb_dev->speed == USB_SPEED_HIGH) {
+ if (sisusb_init_gfxdevice(sisusb, 0)) {
+ up(&sisusb->lock);
+ up(&disconnect_sem);
+ printk(KERN_ERR
+ "sisusbvga[%d]: Failed to initialize "
+ "device\n",
+ sisusb->minor);
+ return -EIO;
+ }
+ } else {
+ up(&sisusb->lock);
+ up(&disconnect_sem);
+ printk(KERN_ERR
+ "sisusbvga[%d]: Device not attached to "
+ "USB 2.0 hub\n",
+ sisusb->minor);
+ return -EIO;
+ }
+ }
+
+ /* increment usage count for the device */
+ kref_get(&sisusb->kref);
+
+ sisusb->isopen = 1;
+
+ file->private_data = sisusb;
+
+ up(&sisusb->lock);
+
+ up(&disconnect_sem);
+
+ printk(KERN_DEBUG "sisusbvga[%d]: opened", sisusb->minor);
+
+ return 0;
+}
+
+static void
+sisusb_delete(struct kref *kref)
+{
+ struct sisusb_usb_data *sisusb = to_sisusb_dev(kref);
+
+ if (!sisusb)
+ return;
+
+ if (sisusb->sisusb_dev)
+ usb_put_dev(sisusb->sisusb_dev);
+
+ sisusb->sisusb_dev = NULL;
+ sisusb_free_buffers(sisusb);
+ sisusb_free_urbs(sisusb);
+ kfree(sisusb);
+}
+
+static int
+sisusb_release(struct inode *inode, struct file *file)
+{
+ struct sisusb_usb_data *sisusb;
+ int myminor;
+
+ down(&disconnect_sem);
+
+ if (!(sisusb = (struct sisusb_usb_data *)file->private_data)) {
+ up(&disconnect_sem);
+ return -ENODEV;
+ }
+
+ down(&sisusb->lock);
+
+ if (sisusb->present) {
+ /* Wait for all URBs to finish if device still present */
+ if (!sisusb_wait_all_out_complete(sisusb))
+ sisusb_kill_all_busy(sisusb);
+ }
+
+ myminor = sisusb->minor;
+
+ sisusb->isopen = 0;
+ file->private_data = NULL;
+
+ up(&sisusb->lock);
+
+ /* decrement the usage count on our device */
+ kref_put(&sisusb->kref, sisusb_delete);
+
+ up(&disconnect_sem);
+
+ printk(KERN_DEBUG "sisusbvga[%d]: released", myminor);
+
+ return 0;
+}
+
+static ssize_t
+sisusb_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
+{
+ struct sisusb_usb_data *sisusb;
+ ssize_t bytes_read = 0;
+ int errno = 0;
+ u8 buf8;
+ u16 buf16;
+ u32 buf32, address;
+
+ if (!(sisusb = (struct sisusb_usb_data *)file->private_data))
+ return -ENODEV;
+
+ down(&sisusb->lock);
+
+ /* Sanity check */
+ if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
+ up(&sisusb->lock);
+ return -ENODEV;
+ }
+
+ if ((*ppos) >= SISUSB_PCI_PSEUDO_IOPORTBASE &&
+ (*ppos) < SISUSB_PCI_PSEUDO_IOPORTBASE + 128) {
+
+ address = (*ppos) -
+ SISUSB_PCI_PSEUDO_IOPORTBASE +
+ SISUSB_PCI_IOPORTBASE;
+
+ /* Read i/o ports
+ * Byte, word and long(32) can be read. As this
+ * emulates inX instructions, the data returned is
+ * in machine-endianness.
+ */
+ switch (count) {
+
+ case 1:
+ if (sisusb_read_memio_byte(sisusb,
+ SISUSB_TYPE_IO,
+ address, &buf8))
+ errno = -EIO;
+ else if (put_user(buf8, (u8 __user *)buffer))
+ errno = -EFAULT;
+ else
+ bytes_read = 1;
+
+ break;
+
+ case 2:
+ if (sisusb_read_memio_word(sisusb,
+ SISUSB_TYPE_IO,
+ address, &buf16))
+ errno = -EIO;
+ else if (put_user(buf16, (u16 __user *)buffer))
+ errno = -EFAULT;
+ else
+ bytes_read = 2;
+
+ break;
+
+ case 4:
+ if (sisusb_read_memio_long(sisusb,
+ SISUSB_TYPE_IO,
+ address, &buf32))
+ errno = -EIO;
+ else if (put_user(buf32, (u32 __user *)buffer))
+ errno = -EFAULT;
+ else
+ bytes_read = 4;
+
+ break;
+
+ default:
+ errno = -EIO;
+
+ }
+
+ } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MEMBASE &&
+ (*ppos) < SISUSB_PCI_PSEUDO_MEMBASE + sisusb->vramsize) {
+
+ address = (*ppos) -
+ SISUSB_PCI_PSEUDO_MEMBASE +
+ SISUSB_PCI_MEMBASE;
+
+ /* Read video ram
+ * Remember: Data delivered is never endian-corrected
+ */
+ errno = sisusb_read_mem_bulk(sisusb, address,
+ NULL, count, buffer, &bytes_read);
+
+ if (bytes_read)
+ errno = bytes_read;
+
+ } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MMIOBASE &&
+ (*ppos) < SISUSB_PCI_PSEUDO_MMIOBASE + SISUSB_PCI_MMIOSIZE) {
+
+ address = (*ppos) -
+ SISUSB_PCI_PSEUDO_MMIOBASE +
+ SISUSB_PCI_MMIOBASE;
+
+ /* Read MMIO
+ * Remember: Data delivered is never endian-corrected
+ */
+ errno = sisusb_read_mem_bulk(sisusb, address,
+ NULL, count, buffer, &bytes_read);
+
+ if (bytes_read)
+ errno = bytes_read;
+
+ } else if ((*ppos) >= SISUSB_PCI_PSEUDO_PCIBASE &&
+ (*ppos) <= SISUSB_PCI_PSEUDO_PCIBASE + 0x5c) {
+
+ if (count != 4) {
+ up(&sisusb->lock);
+ return -EINVAL;
+ }
+
+ address = (*ppos) - SISUSB_PCI_PSEUDO_PCIBASE;
+
+ /* Read PCI config register
+ * Return value delivered in machine endianness.
+ */
+ if (sisusb_read_pci_config(sisusb, address, &buf32))
+ errno = -EIO;
+ else if (put_user(buf32, (u32 __user *)buffer))
+ errno = -EFAULT;
+ else
+ bytes_read = 4;
+
+ } else {
+
+ errno = -EBADFD;
+
+ }
+
+ (*ppos) += bytes_read;
+
+ up(&sisusb->lock);
+
+ return errno ? errno : bytes_read;
+}
+
+static ssize_t
+sisusb_write(struct file *file, const char __user *buffer, size_t count,
+ loff_t *ppos)
+{
+ struct sisusb_usb_data *sisusb;
+ int errno = 0;
+ ssize_t bytes_written = 0;
+ u8 buf8;
+ u16 buf16;
+ u32 buf32, address;
+
+ if (!(sisusb = (struct sisusb_usb_data *)file->private_data))
+ return -ENODEV;
+
+ down(&sisusb->lock);
+
+ /* Sanity check */
+ if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
+ up(&sisusb->lock);
+ return -ENODEV;
+ }
+
+ if ((*ppos) >= SISUSB_PCI_PSEUDO_IOPORTBASE &&
+ (*ppos) < SISUSB_PCI_PSEUDO_IOPORTBASE + 128) {
+
+ address = (*ppos) -
+ SISUSB_PCI_PSEUDO_IOPORTBASE +
+ SISUSB_PCI_IOPORTBASE;
+
+ /* Write i/o ports
+ * Byte, word and long(32) can be written. As this
+ * emulates outX instructions, the data is expected
+ * in machine-endianness.
+ */
+ switch (count) {
+
+ case 1:
+ if (get_user(buf8, (u8 __user *)buffer))
+ errno = -EFAULT;
+ else if (sisusb_write_memio_byte(sisusb,
+ SISUSB_TYPE_IO,
+ address, buf8))
+ errno = -EIO;
+ else
+ bytes_written = 1;
+
+ break;
+
+ case 2:
+ if (get_user(buf16, (u16 __user *)buffer))
+ errno = -EFAULT;
+ else if (sisusb_write_memio_word(sisusb,
+ SISUSB_TYPE_IO,
+ address, buf16))
+ errno = -EIO;
+ else
+ bytes_written = 2;
+
+ break;
+
+ case 4:
+ if (get_user(buf32, (u32 __user *)buffer))
+ errno = -EFAULT;
+ else if (sisusb_write_memio_long(sisusb,
+ SISUSB_TYPE_IO,
+ address, buf32))
+ errno = -EIO;
+ else
+ bytes_written = 4;
+
+ break;
+
+ default:
+ errno = -EIO;
+ }
+
+ } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MEMBASE &&
+ (*ppos) < SISUSB_PCI_PSEUDO_MEMBASE + sisusb->vramsize) {
+
+ address = (*ppos) -
+ SISUSB_PCI_PSEUDO_MEMBASE +
+ SISUSB_PCI_MEMBASE;
+
+ /* Write video ram.
+ * Buffer is copied 1:1, therefore, on big-endian
+ * machines, the data must be swapped by userland
+ * in advance (if applicable; no swapping in 8bpp
+ * mode or if YUV data is being transferred).
+ */
+ errno = sisusb_write_mem_bulk(sisusb, address, NULL,
+ count, buffer, 0, &bytes_written);
+
+ if (bytes_written)
+ errno = bytes_written;
+
+ } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MMIOBASE &&
+ (*ppos) < SISUSB_PCI_PSEUDO_MMIOBASE + SISUSB_PCI_MMIOSIZE) {
+
+ address = (*ppos) -
+ SISUSB_PCI_PSEUDO_MMIOBASE +
+ SISUSB_PCI_MMIOBASE;
+
+ /* Write MMIO.
+ * Buffer is copied 1:1, therefore, on big-endian
+ * machines, the data must be swapped by userland
+ * in advance.
+ */
+ errno = sisusb_write_mem_bulk(sisusb, address, NULL,
+ count, buffer, 0, &bytes_written);
+
+ if (bytes_written)
+ errno = bytes_written;
+
+ } else if ((*ppos) >= SISUSB_PCI_PSEUDO_PCIBASE &&
+ (*ppos) <= SISUSB_PCI_PSEUDO_PCIBASE + SISUSB_PCI_PCONFSIZE) {
+
+ if (count != 4) {
+ up(&sisusb->lock);
+ return -EINVAL;
+ }
+
+ address = (*ppos) - SISUSB_PCI_PSEUDO_PCIBASE;
+
+ /* Write PCI config register.
+ * Given value expected in machine endianness.
+ */
+ if (get_user(buf32, (u32 __user *)buffer))
+ errno = -EFAULT;
+ else if (sisusb_write_pci_config(sisusb, address, buf32))
+ errno = -EIO;
+ else
+ bytes_written = 4;
+
+
+ } else {
+
+ /* Error */
+ errno = -EBADFD;
+
+ }
+
+ (*ppos) += bytes_written;
+
+ up(&sisusb->lock);
+
+ return errno ? errno : bytes_written;
+}
+
+static loff_t
+sisusb_lseek(struct file *file, loff_t offset, int orig)
+{
+ struct sisusb_usb_data *sisusb;
+ loff_t ret;
+
+ if (!(sisusb = (struct sisusb_usb_data *)file->private_data))
+ return -ENODEV;
+
+ down(&sisusb->lock);
+
+ /* Sanity check */
+ if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
+ up(&sisusb->lock);
+ return -ENODEV;
+ }
+
+ switch (orig) {
+ case 0:
+ file->f_pos = offset;
+ ret = file->f_pos;
+ /* never negative, no force_successful_syscall needed */
+ break;
+ case 1:
+ file->f_pos += offset;
+ ret = file->f_pos;
+ /* never negative, no force_successful_syscall needed */
+ break;
+ default:
+ /* seeking relative to "end of file" is not supported */
+ ret = -EINVAL;
+ }
+
+ up(&sisusb->lock);
+ return ret;
+}
+
+static int
+sisusb_handle_command(struct sisusb_usb_data *sisusb, struct sisusb_command *y,
+ unsigned long arg)
+{
+ int retval, port, length;
+ u32 address;
+
+ port = y->data3 -
+ SISUSB_PCI_PSEUDO_IOPORTBASE +
+ SISUSB_PCI_IOPORTBASE;
+
+ switch (y->operation) {
+ case SUCMD_GET:
+ retval = sisusb_getidxreg(sisusb, port,
+ y->data0, &y->data1);
+ if (!retval) {
+ if (copy_to_user((void __user *)arg, y,
+ sizeof(*y)))
+ retval = -EFAULT;
+ }
+ break;
+
+ case SUCMD_SET:
+ retval = sisusb_setidxreg(sisusb, port,
+ y->data0, y->data1);
+ break;
+
+ case SUCMD_SETOR:
+ retval = sisusb_setidxregor(sisusb, port,
+ y->data0, y->data1);
+ break;
+
+ case SUCMD_SETAND:
+ retval = sisusb_setidxregand(sisusb, port,
+ y->data0, y->data1);
+ break;
+
+ case SUCMD_SETANDOR:
+ retval = sisusb_setidxregandor(sisusb, port,
+ y->data0, y->data1, y->data2);
+ break;
+
+ case SUCMD_SETMASK:
+ retval = sisusb_setidxregmask(sisusb, port,
+ y->data0, y->data1, y->data2);
+ break;
+
+ case SUCMD_CLRSCR:
+ length = (y->data0 << 16) | (y->data1 << 8) | y->data2;
+ address = y->data3 -
+ SISUSB_PCI_PSEUDO_MEMBASE +
+ SISUSB_PCI_MEMBASE;
+ retval = sisusb_clear_vram(sisusb, address, length);
+ break;
+
+ default:
+ retval = -EINVAL;
+ }
+
+ if(retval > 0)
+ retval = -EIO;
+
+ return retval;
+}
+
+static int
+sisusb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ struct sisusb_usb_data *sisusb;
+ struct sisusb_info x;
+ struct sisusb_command y;
+ int retval = 0;
+ u32 __user *argp = (u32 __user *)arg;
+
+ if (!(sisusb = (struct sisusb_usb_data *)file->private_data))
+ return -ENODEV;
+
+ down(&sisusb->lock);
+
+ /* Sanity check */
+ if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
+ retval = -ENODEV;
+ goto err_out;
+ }
+
+ switch (cmd) {
+
+ case SISUSB_GET_CONFIG_SIZE:
+
+ if (put_user(sizeof(x), argp))
+ retval = -EFAULT;
+
+ break;
+
+ case SISUSB_GET_CONFIG:
+
+ x.sisusb_id = SISUSB_ID;
+ x.sisusb_version = SISUSB_VERSION;
+ x.sisusb_revision = SISUSB_REVISION;
+ x.sisusb_patchlevel = SISUSB_PATCHLEVEL;
+ x.sisusb_gfxinit = sisusb->gfxinit;
+ x.sisusb_vrambase = SISUSB_PCI_PSEUDO_MEMBASE;
+ x.sisusb_mmiobase = SISUSB_PCI_PSEUDO_MMIOBASE;
+ x.sisusb_iobase = SISUSB_PCI_PSEUDO_IOPORTBASE;
+ x.sisusb_pcibase = SISUSB_PCI_PSEUDO_PCIBASE;
+ x.sisusb_vramsize = sisusb->vramsize;
+ x.sisusb_minor = sisusb->minor;
+ x.sisusb_fbdevactive= 0;
+
+ if (copy_to_user((void __user *)arg, &x, sizeof(x)))
+ retval = -EFAULT;
+
+ break;
+
+ case SISUSB_COMMAND:
+
+ if (copy_from_user(&y, (void __user *)arg, sizeof(y)))
+ retval = -EFAULT;
+ else
+ retval = sisusb_handle_command(sisusb, &y, arg);
+
+ break;
+
+ default:
+ retval = -EINVAL;
+ break;
+ }
+
+err_out:
+ up(&sisusb->lock);
+ return retval;
+}
+
+#ifdef SISUSB_NEW_CONFIG_COMPAT
+static long
+sisusb_compat_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
+{
+ long retval;
+
+ switch (cmd) {
+ case SISUSB_GET_CONFIG_SIZE:
+ case SISUSB_GET_CONFIG:
+ case SISUSB_COMMAND:
+ lock_kernel();
+ retval = sisusb_ioctl(f->f_dentry->d_inode, f, cmd, arg);
+ unlock_kernel();
+ return retval;
+
+ default:
+ return -ENOIOCTLCMD;
+ }
+}
+#endif
+
+static struct file_operations usb_sisusb_fops = {
+ .owner = THIS_MODULE,
+ .open = sisusb_open,
+ .release = sisusb_release,
+ .read = sisusb_read,
+ .write = sisusb_write,
+ .llseek = sisusb_lseek,
+#ifdef SISUSB_NEW_CONFIG_COMPAT
+ .compat_ioctl = sisusb_compat_ioctl,
+#endif
+ .ioctl = sisusb_ioctl
+};
+
+static struct usb_class_driver usb_sisusb_class = {
+ .name = "usb/sisusbvga%d",
+ .fops = &usb_sisusb_fops,
+ .mode = S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
+ .minor_base = SISUSB_MINOR
+};
+
+static int sisusb_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ struct usb_device *dev = interface_to_usbdev(intf);
+ struct sisusb_usb_data *sisusb;
+ int retval = 0, i;
+ const char *memfail =
+ KERN_ERR
+ "sisusbvga[%d]: Failed to allocate memory for %s buffer\n";
+
+ printk(KERN_INFO "sisusb: USB2VGA dongle found at address %d\n",
+ dev->devnum);
+
+ /* Allocate memory for our private */
+ if (!(sisusb = kmalloc(sizeof(*sisusb), GFP_KERNEL))) {
+ printk(KERN_ERR
+ "sisusb: Failed to allocate memory for private data\n");
+ return -ENOMEM;
+ }
+ memset(sisusb, 0, sizeof(*sisusb));
+ kref_init(&sisusb->kref);
+
+ init_MUTEX(&(sisusb->lock));
+
+ /* Register device */
+ if ((retval = usb_register_dev(intf, &usb_sisusb_class))) {
+ printk(KERN_ERR
+ "sisusb: Failed to get a minor for device %d\n",
+ dev->devnum);
+ retval = -ENODEV;
+ goto error_1;
+ }
+
+ sisusb->sisusb_dev = dev;
+ sisusb->minor = intf->minor;
+ sisusb->vrambase = SISUSB_PCI_MEMBASE;
+ sisusb->mmiobase = SISUSB_PCI_MMIOBASE;
+ sisusb->mmiosize = SISUSB_PCI_MMIOSIZE;
+ sisusb->ioportbase = SISUSB_PCI_IOPORTBASE;
+ /* Everything else is zero */
+
+ /* Allocate buffers */
+ sisusb->ibufsize = SISUSB_IBUF_SIZE;
+ if (!(sisusb->ibuf = usb_buffer_alloc(dev, SISUSB_IBUF_SIZE,
+ GFP_KERNEL, &sisusb->transfer_dma_in))) {
+ printk(memfail, "input", sisusb->minor);
+ retval = -ENOMEM;
+ goto error_2;
+ }
+
+ sisusb->numobufs = 0;
+ sisusb->obufsize = SISUSB_OBUF_SIZE;
+ for (i = 0; i < NUMOBUFS; i++) {
+ if (!(sisusb->obuf[i] = usb_buffer_alloc(dev, SISUSB_OBUF_SIZE,
+ GFP_KERNEL,
+ &sisusb->transfer_dma_out[i]))) {
+ if (i == 0) {
+ printk(memfail, "output", sisusb->minor);
+ retval = -ENOMEM;
+ goto error_3;
+ }
+ break;
+ } else
+ sisusb->numobufs++;
+
+ }
+
+ /* Allocate URBs */
+ if (!(sisusb->sisurbin = usb_alloc_urb(0, GFP_KERNEL))) {
+ printk(KERN_ERR
+ "sisusbvga[%d]: Failed to allocate URBs\n",
+ sisusb->minor);
+ retval = -ENOMEM;
+ goto error_3;
+ }
+ sisusb->completein = 1;
+
+ for (i = 0; i < sisusb->numobufs; i++) {
+ if (!(sisusb->sisurbout[i] = usb_alloc_urb(0, GFP_KERNEL))) {
+ printk(KERN_ERR
+ "sisusbvga[%d]: Failed to allocate URBs\n",
+ sisusb->minor);
+ retval = -ENOMEM;
+ goto error_4;
+ }
+ sisusb->urbout_context[i].sisusb = (void *)sisusb;
+ sisusb->urbout_context[i].urbindex = i;
+ sisusb->urbstatus[i] = 0;
+ }
+
+ printk(KERN_INFO "sisusbvga[%d]: Allocated %d output buffers\n",
+ sisusb->minor, sisusb->numobufs);
+
+ /* Do remaining init stuff */
+
+ init_waitqueue_head(&sisusb->wait_q);
+
+ usb_set_intfdata(intf, sisusb);
+
+#ifdef SISUSB_OLD_CONFIG_COMPAT
+ {
+ int ret;
+ /* Our ioctls are all "32/64bit compatible" */
+ ret = register_ioctl32_conversion(SISUSB_GET_CONFIG_SIZE, NULL);
+ ret |= register_ioctl32_conversion(SISUSB_GET_CONFIG, NULL);
+ ret |= register_ioctl32_conversion(SISUSB_COMMAND, NULL);
+ if (ret)
+ printk(KERN_ERR
+ "sisusbvga[%d]: Error registering ioctl32 "
+ "translations\n",
+ sisusb->minor);
+ else
+ sisusb->ioctl32registered = 1;
+
+ }
+#endif
+
+ sisusb->present = 1;
+
+ if (dev->speed == USB_SPEED_HIGH) {
+ if (sisusb_init_gfxdevice(sisusb, 1))
+ printk(KERN_ERR
+ "sisusbvga[%d]: Failed to early "
+ "initialize device\n",
+ sisusb->minor);
+
+ } else
+ printk(KERN_INFO
+ "sisusbvga[%d]: Not attached to USB 2.0 hub, "
+ "deferring init\n",
+ sisusb->minor);
+
+ sisusb->ready = 1;
+
+ return 0;
+
+error_4:
+ sisusb_free_urbs(sisusb);
+error_3:
+ sisusb_free_buffers(sisusb);
+error_2:
+ usb_deregister_dev(intf, &usb_sisusb_class);
+error_1:
+ kfree(sisusb);
+ return retval;
+}
+
+static void sisusb_disconnect(struct usb_interface *intf)
+{
+ struct sisusb_usb_data *sisusb;
+ int minor;
+
+ down(&disconnect_sem);
+
+ /* This should *not* happen */
+ if (!(sisusb = usb_get_intfdata(intf))) {
+ up(&disconnect_sem);
+ return;
+ }
+
+ down(&sisusb->lock);
+
+ /* Wait for all URBs to complete and kill them in case (MUST do) */
+ if (!sisusb_wait_all_out_complete(sisusb))
+ sisusb_kill_all_busy(sisusb);
+
+ minor = sisusb->minor;
+
+ usb_set_intfdata(intf, NULL);
+
+ usb_deregister_dev(intf, &usb_sisusb_class);
+
+#ifdef SISUSB_OLD_CONFIG_COMPAT
+ if (sisusb->ioctl32registered) {
+ int ret;
+ sisusb->ioctl32registered = 0;
+ ret = unregister_ioctl32_conversion(SISUSB_GET_CONFIG_SIZE);
+ ret |= unregister_ioctl32_conversion(SISUSB_GET_CONFIG);
+ ret |= unregister_ioctl32_conversion(SISUSB_COMMAND);
+ if (ret) {
+ printk(KERN_ERR
+ "sisusbvga[%d]: Error unregistering "
+ "ioctl32 translations\n",
+ minor);
+ }
+ }
+#endif
+
+ sisusb->present = 0;
+ sisusb->ready = 0;
+
+ up(&sisusb->lock);
+
+ /* decrement our usage count */
+ kref_put(&sisusb->kref, sisusb_delete);
+
+ up(&disconnect_sem);
+
+ printk(KERN_INFO "sisusbvga[%d]: Disconnected\n", minor);
+}
+
+static struct usb_device_id sisusb_table [] = {
+ { USB_DEVICE(0x0711, 0x0900) },
+ { }
+};
+
+MODULE_DEVICE_TABLE (usb, sisusb_table);
+
+static struct usb_driver sisusb_driver = {
+ .owner = THIS_MODULE,
+ .name = "sisusb",
+ .probe = sisusb_probe,
+ .disconnect = sisusb_disconnect,
+ .id_table = sisusb_table
+};
+
+static int __init usb_sisusb_init(void)
+{
+ int retval;
+
+ if (!(retval = usb_register(&sisusb_driver))) {
+ printk(KERN_INFO "sisusb: Driver version %d.%d.%d\n",
+ SISUSB_VERSION, SISUSB_REVISION, SISUSB_PATCHLEVEL);
+ printk(KERN_INFO
+ "sisusb: Copyright (C) 2005 Thomas Winischhofer\n");
+ }
+
+ return retval;
+}
+
+static void __exit usb_sisusb_exit(void)
+{
+ usb_deregister(&sisusb_driver);
+}
+
+module_init(usb_sisusb_init);
+module_exit(usb_sisusb_exit);
+
+MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>");
+MODULE_DESCRIPTION("sisusb - Driver for Net2280/SiS315-based USB2VGA dongles");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/usb/misc/sisusbvga/sisusb.h b/drivers/usb/misc/sisusbvga/sisusb.h
new file mode 100644
index 0000000000000..1306d006a25ab
--- /dev/null
+++ b/drivers/usb/misc/sisusbvga/sisusb.h
@@ -0,0 +1,278 @@
+/*
+ * sisusb - usb kernel driver for Net2280/SiS315 based USB2VGA dongles
+ *
+ * Copyright (C) 2005 by Thomas Winischhofer, Vienna, Austria
+ *
+ * If distributed as part of the Linux kernel, this code is licensed under the
+ * terms of the GPL v2.
+ *
+ * Otherwise, the following license terms apply:
+ *
+ * * Redistribution and use in source and binary forms, with or without
+ * * modification, are permitted provided that the following conditions
+ * * are met:
+ * * 1) Redistributions of source code must retain the above copyright
+ * * notice, this list of conditions and the following disclaimer.
+ * * 2) Redistributions in binary form must reproduce the above copyright
+ * * notice, this list of conditions and the following disclaimer in the
+ * * documentation and/or other materials provided with the distribution.
+ * * 3) The name of the author may not be used to endorse or promote products
+ * * derived from this software without specific prior written permission.
+ * *
+ * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR
+ * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Author: Thomas Winischhofer <thomas@winischhofer.net>
+ *
+ */
+
+#ifndef _SISUSB_H_
+#define _SISUSB_H_
+
+#ifdef CONFIG_COMPAT
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,10)
+#include <linux/ioctl32.h>
+#define SISUSB_OLD_CONFIG_COMPAT
+#else
+#define SISUSB_NEW_CONFIG_COMPAT
+#endif
+#endif
+
+/* Version Information */
+
+#define SISUSB_VERSION 0
+#define SISUSB_REVISION 0
+#define SISUSB_PATCHLEVEL 7
+
+/* USB related */
+
+#define SISUSB_MINOR 133 /* FIXME */
+
+/* Size of the sisusb input/output buffers */
+#define SISUSB_IBUF_SIZE 0x01000
+#define SISUSB_OBUF_SIZE 0x10000 /* fixed */
+
+#define NUMOBUFS 8 /* max number of output buffers/output URBs */
+
+/* About endianness:
+ *
+ * 1) I/O ports, PCI config registers. The read/write()
+ * calls emulate inX/outX. Hence, the data is
+ * expected/delivered in machine endiannes by this
+ * driver.
+ * 2) Video memory. The data is copied 1:1. There is
+ * no swapping. Ever. This means for userland that
+ * the data has to be prepared properly. (Hint:
+ * think graphics data format, command queue,
+ * hardware cursor.)
+ * 3) MMIO. Data is copied 1:1. MMIO must be swapped
+ * properly by userland.
+ *
+ */
+
+#ifdef __BIG_ENDIAN
+#define SISUSB_CORRECT_ENDIANNESS_PACKET(p) \
+ do { \
+ p->header = cpu_to_le16(p->header); \
+ p->address = cpu_to_le32(p->address); \
+ p->data = cpu_to_le32(p->data); \
+ } while(0)
+#else
+#define SISUSB_CORRECT_ENDIANNESS_PACKET(p)
+#endif
+
+struct sisusb_usb_data;
+
+struct sisusb_urb_context { /* urb->context for outbound bulk URBs */
+ struct sisusb_usb_data *sisusb;
+ int urbindex;
+ int *actual_length;
+};
+
+struct sisusb_usb_data {
+ struct usb_device *sisusb_dev;
+ struct usb_interface *interface;
+ struct kref kref;
+ wait_queue_head_t wait_q; /* for syncind and timeouts */
+ struct semaphore lock; /* general race avoidance */
+ unsigned int ifnum; /* interface number of the USB device */
+ int minor; /* minor (for logging clarity) */
+ int isopen; /* !=0 if open */
+ int present; /* !=0 if device is present on the bus */
+ int ready; /* !=0 if device is ready for userland */
+#ifdef SISUSB_OLD_CONFIG_COMPAT
+ int ioctl32registered;
+#endif
+ int numobufs; /* number of obufs = number of out urbs */
+ char *obuf[NUMOBUFS], *ibuf; /* transfer buffers */
+ int obufsize, ibufsize;
+ dma_addr_t transfer_dma_out[NUMOBUFS];
+ dma_addr_t transfer_dma_in;
+ struct urb *sisurbout[NUMOBUFS];
+ struct urb *sisurbin;
+ unsigned char urbstatus[NUMOBUFS];
+ unsigned char completein;
+ struct sisusb_urb_context urbout_context[NUMOBUFS];
+ unsigned long flagb0;
+ unsigned long vrambase; /* framebuffer base */
+ unsigned int vramsize; /* framebuffer size (bytes) */
+ unsigned long mmiobase;
+ unsigned int mmiosize;
+ unsigned long ioportbase;
+ unsigned char devinit; /* device initialized? */
+ unsigned char gfxinit; /* graphics core initialized? */
+ unsigned short chipid, chipvendor;
+ unsigned short chiprevision;
+};
+
+#define to_sisusb_dev(d) container_of(d, struct sisusb_usb_data, kref)
+
+/* USB transport related */
+
+/* urbstatus */
+#define SU_URB_BUSY 1
+#define SU_URB_ALLOC 2
+
+/* Endpoints */
+
+#define SISUSB_EP_GFX_IN 0x0e /* gfx std packet out(0e)/in(8e) */
+#define SISUSB_EP_GFX_OUT 0x0e
+
+#define SISUSB_EP_GFX_BULK_OUT 0x01 /* gfx mem bulk out/in */
+#define SISUSB_EP_GFX_BULK_IN 0x02 /* ? 2 is "OUT" ? */
+
+#define SISUSB_EP_GFX_LBULK_OUT 0x03 /* gfx large mem bulk out */
+
+#define SISUSB_EP_UNKNOWN_04 0x04 /* ? 4 is "OUT" ? - unused */
+
+#define SISUSB_EP_BRIDGE_IN 0x0d /* Net2280 out(0d)/in(8d) */
+#define SISUSB_EP_BRIDGE_OUT 0x0d
+
+#define SISUSB_TYPE_MEM 0
+#define SISUSB_TYPE_IO 1
+
+struct sisusb_packet {
+ unsigned short header;
+ u32 address;
+ u32 data;
+} __attribute__((__packed__));
+
+#define CLEARPACKET(packet) memset(packet, 0, 10)
+
+/* PCI bridge related */
+
+#define SISUSB_PCI_MEMBASE 0xd0000000
+#define SISUSB_PCI_MMIOBASE 0xe4000000
+#define SISUSB_PCI_IOPORTBASE 0x0000d000
+
+#define SISUSB_PCI_PSEUDO_MEMBASE 0x10000000
+#define SISUSB_PCI_PSEUDO_MMIOBASE 0x20000000
+#define SISUSB_PCI_PSEUDO_IOPORTBASE 0x0000d000
+#define SISUSB_PCI_PSEUDO_PCIBASE 0x00010000
+
+#define SISUSB_PCI_MMIOSIZE (128*1024)
+#define SISUSB_PCI_PCONFSIZE 0x5c
+
+/* graphics core related */
+
+#define AROFFSET 0x40
+#define ARROFFSET 0x41
+#define GROFFSET 0x4e
+#define SROFFSET 0x44
+#define CROFFSET 0x54
+#define MISCROFFSET 0x4c
+#define MISCWOFFSET 0x42
+#define INPUTSTATOFFSET 0x5A
+#define PART1OFFSET 0x04
+#define PART2OFFSET 0x10
+#define PART3OFFSET 0x12
+#define PART4OFFSET 0x14
+#define PART5OFFSET 0x16
+#define CAPTUREOFFSET 0x00
+#define VIDEOOFFSET 0x02
+#define COLREGOFFSET 0x48
+#define PELMASKOFFSET 0x46
+#define VGAENABLE 0x43
+
+#define SISAR SISUSB_PCI_IOPORTBASE + AROFFSET
+#define SISARR SISUSB_PCI_IOPORTBASE + ARROFFSET
+#define SISGR SISUSB_PCI_IOPORTBASE + GROFFSET
+#define SISSR SISUSB_PCI_IOPORTBASE + SROFFSET
+#define SISCR SISUSB_PCI_IOPORTBASE + CROFFSET
+#define SISMISCR SISUSB_PCI_IOPORTBASE + MISCROFFSET
+#define SISMISCW SISUSB_PCI_IOPORTBASE + MISCWOFFSET
+#define SISINPSTAT SISUSB_PCI_IOPORTBASE + INPUTSTATOFFSET
+#define SISPART1 SISUSB_PCI_IOPORTBASE + PART1OFFSET
+#define SISPART2 SISUSB_PCI_IOPORTBASE + PART2OFFSET
+#define SISPART3 SISUSB_PCI_IOPORTBASE + PART3OFFSET
+#define SISPART4 SISUSB_PCI_IOPORTBASE + PART4OFFSET
+#define SISPART5 SISUSB_PCI_IOPORTBASE + PART5OFFSET
+#define SISCAP SISUSB_PCI_IOPORTBASE + CAPTUREOFFSET
+#define SISVID SISUSB_PCI_IOPORTBASE + VIDEOOFFSET
+#define SISCOLIDXR SISUSB_PCI_IOPORTBASE + COLREGOFFSET - 1
+#define SISCOLIDX SISUSB_PCI_IOPORTBASE + COLREGOFFSET
+#define SISCOLDATA SISUSB_PCI_IOPORTBASE + COLREGOFFSET + 1
+#define SISCOL2IDX SISPART5
+#define SISCOL2DATA SISPART5 + 1
+#define SISPEL SISUSB_PCI_IOPORTBASE + PELMASKOFFSET
+#define SISVGAEN SISUSB_PCI_IOPORTBASE + VGAENABLE
+#define SISDACA SISCOLIDX
+#define SISDACD SISCOLDATA
+
+/* ioctl related */
+
+/* Structure argument for SISUSB_GET_INFO ioctl */
+struct sisusb_info {
+ __u32 sisusb_id; /* for identifying sisusb */
+#define SISUSB_ID 0x53495355 /* Identify myself with 'SISU' */
+ __u8 sisusb_version;
+ __u8 sisusb_revision;
+ __u8 sisusb_patchlevel;
+ __u8 sisusb_gfxinit; /* graphics core initialized? */
+
+ __u32 sisusb_vrambase;
+ __u32 sisusb_mmiobase;
+ __u32 sisusb_iobase;
+ __u32 sisusb_pcibase;
+
+ __u32 sisusb_vramsize; /* framebuffer size in bytes */
+
+ __u32 sisusb_minor;
+
+ __u32 sisusb_fbdevactive; /* != 0 if framebuffer device active */
+
+ __u8 sisusb_reserved[32]; /* for future use */
+};
+
+struct sisusb_command {
+ __u8 operation; /* see below */
+ __u8 data0; /* operation dependent */
+ __u8 data1; /* operation dependent */
+ __u8 data2; /* operation dependent */
+ __u32 data3; /* operation dependent */
+ __u32 data4; /* for future use */
+};
+
+#define SUCMD_GET 0x01 /* for all: data0 = index, data3 = port */
+#define SUCMD_SET 0x02 /* data1 = value */
+#define SUCMD_SETOR 0x03 /* data1 = or */
+#define SUCMD_SETAND 0x04 /* data1 = and */
+#define SUCMD_SETANDOR 0x05 /* data1 = and, data2 = or */
+#define SUCMD_SETMASK 0x06 /* data1 = data, data2 = mask */
+
+#define SUCMD_CLRSCR 0x07 /* data0:1:2 = length, data3 = address */
+
+#define SISUSB_COMMAND _IOWR(0xF3,0x3D,struct sisusb_command)
+#define SISUSB_GET_CONFIG_SIZE _IOR(0xF3,0x3E,__u32)
+#define SISUSB_GET_CONFIG _IOR(0xF3,0x3F,struct sisusb_info)
+
+#endif /* SISUSB_H */
+
diff --git a/drivers/usb/misc/usblcd.c b/drivers/usb/misc/usblcd.c
index da8a43830a822..dcdf9b4abb7cc 100644
--- a/drivers/usb/misc/usblcd.c
+++ b/drivers/usb/misc/usblcd.c
@@ -1,14 +1,16 @@
/*****************************************************************************
* USBLCD Kernel Driver *
- * See http://www.usblcd.de for Hardware and Documentation. *
- * Version 1.03 *
- * (C) 2002 Adams IT Services <info@usblcd.de> *
+ * Version 1.05 *
+ * (C) 2005 Georges Toth <g.toth@e-biz.lu> *
* *
* This file is licensed under the GPL. See COPYING in the package. *
- * Based on rio500.c by Cesar Miquel (miquel@df.uba.ar) which is based on *
- * hp_scanner.c by David E. Nelson (dnelson@jump.net) *
+ * Based on usb-skeleton.c 2.0 by Greg Kroah-Hartman (greg@kroah.com) *
* *
- * 23.7.02 RA changed minor device number to the official assigned one *
+ * *
+ * 28.02.05 Complete rewrite of the original usblcd.c driver, *
+ * based on usb_skeleton.c. *
+ * This new driver allows more than one USB-LCD to be connected *
+ * and controlled, at once *
*****************************************************************************/
#include <linux/module.h>
#include <linux/kernel.h>
@@ -18,74 +20,129 @@
#include <asm/uaccess.h>
#include <linux/usb.h>
-#define DRIVER_VERSION "USBLCD Driver Version 1.04"
+#define DRIVER_VERSION "USBLCD Driver Version 1.05"
#define USBLCD_MINOR 144
#define IOCTL_GET_HARD_VERSION 1
#define IOCTL_GET_DRV_VERSION 2
-/* stall/wait timeout for USBLCD */
-#define NAK_TIMEOUT (10*HZ)
-#define IBUF_SIZE 0x1000
-#define OBUF_SIZE 0x10000
+static struct usb_device_id id_table [] = {
+ { .idVendor = 0x10D2, .match_flags = USB_DEVICE_ID_MATCH_VENDOR, },
+ { },
+};
+MODULE_DEVICE_TABLE (usb, id_table);
+
-struct lcd_usb_data {
- struct usb_device *lcd_dev; /* init: probe_lcd */
- unsigned int ifnum; /* Interface number of the USB device */
- int isopen; /* nz if open */
- int present; /* Device is present on the bus */
- char *obuf, *ibuf; /* transfer buffers */
- char bulk_in_ep, bulk_out_ep; /* Endpoint assignments */
- wait_queue_head_t wait_q; /* for timeouts */
+struct usb_lcd {
+ struct usb_device * udev; /* init: probe_lcd */
+ struct usb_interface * interface; /* the interface for this device */
+ 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 */
+ __u8 bulk_out_endpointAddr; /* the address of the bulk out endpoint */
+ struct kref kref;
};
+#define to_lcd_dev(d) container_of(d, struct usb_lcd, kref)
-static struct lcd_usb_data lcd_instance;
+static struct usb_driver lcd_driver;
-static int open_lcd(struct inode *inode, struct file *file)
+
+static void lcd_delete(struct kref *kref)
{
- struct lcd_usb_data *lcd = &lcd_instance;
+ struct usb_lcd *dev = to_lcd_dev(kref);
+
+ usb_put_dev(dev->udev);
+ kfree (dev->bulk_in_buffer);
+ kfree (dev);
+}
- if (lcd->isopen || !lcd->present) {
- return -EBUSY;
+
+static int lcd_open(struct inode *inode, struct file *file)
+{
+ struct usb_lcd *dev;
+ struct usb_interface *interface;
+ int subminor;
+ int retval = 0;
+
+ subminor = iminor(inode);
+
+ interface = usb_find_interface(&lcd_driver, subminor);
+ if (!interface) {
+ err ("USBLCD: %s - error, can't find device for minor %d",
+ __FUNCTION__, subminor);
+ retval = -ENODEV;
+ goto exit;
}
- lcd->isopen = 1;
- init_waitqueue_head(&lcd->wait_q);
+ dev = usb_get_intfdata(interface);
+ if (!dev) {
+ retval = -ENODEV;
+ goto exit;
+ }
- info("USBLCD opened.");
+ /* increment our usage count for the device */
+ kref_get(&dev->kref);
- return 0;
+ /* save our object in the file's private structure */
+ file->private_data = dev;
+
+exit:
+ return retval;
}
-static int close_lcd(struct inode *inode, struct file *file)
+static int lcd_release(struct inode *inode, struct file *file)
{
- struct lcd_usb_data *lcd = &lcd_instance;
+ struct usb_lcd *dev;
- lcd->isopen = 0;
+ dev = (struct usb_lcd *)file->private_data;
+ if (dev == NULL)
+ return -ENODEV;
- info("USBLCD closed.");
+ /* decrement the count on our device */
+ kref_put(&dev->kref, lcd_delete);
return 0;
}
-static int
-ioctl_lcd(struct inode *inode, struct file *file, unsigned int cmd,
- unsigned long arg)
+static ssize_t lcd_read(struct file *file, char __user * buffer, size_t count, loff_t *ppos)
{
- struct lcd_usb_data *lcd = &lcd_instance;
+ struct usb_lcd *dev;
+ int retval = 0;
+
+ dev = (struct usb_lcd *)file->private_data;
+
+ /* do a blocking bulk read to get data from the device */
+ retval = usb_bulk_msg(dev->udev,
+ usb_rcvbulkpipe(dev->udev, dev->bulk_in_endpointAddr),
+ dev->bulk_in_buffer,
+ min(dev->bulk_in_size, count),
+ &count, 10000);
+
+ /* if the read was successful, copy the data to userspace */
+ if (!retval) {
+ if (copy_to_user(buffer, dev->bulk_in_buffer, count))
+ retval = -EFAULT;
+ else
+ retval = count;
+ }
+
+ return retval;
+}
+
+static int lcd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+{
+ struct usb_lcd *dev;
u16 bcdDevice;
char buf[30];
- /* Sanity check to make sure lcd is connected, powered, etc */
- if (lcd == NULL ||
- lcd->present == 0 ||
- lcd->lcd_dev == NULL)
- return -1;
-
+ dev = (struct usb_lcd *)file->private_data;
+ if (dev == NULL)
+ return -ENODEV;
+
switch (cmd) {
case IOCTL_GET_HARD_VERSION:
- bcdDevice = le16_to_cpu((lcd->lcd_dev)->descriptor.bcdDevice);
+ bcdDevice = le16_to_cpu((dev->udev)->descriptor.bcdDevice);
sprintf(buf,"%1d%1d.%1d%1d",
(bcdDevice & 0xF000)>>12,
(bcdDevice & 0xF00)>>8,
@@ -107,269 +164,240 @@ ioctl_lcd(struct inode *inode, struct file *file, unsigned int cmd,
return 0;
}
-static ssize_t
-write_lcd(struct file *file, const char __user *buffer,
- size_t count, loff_t * ppos)
+static void lcd_write_bulk_callback(struct urb *urb, struct pt_regs *regs)
{
- struct lcd_usb_data *lcd = &lcd_instance;
-
- unsigned long copy_size;
- unsigned long bytes_written = 0;
- unsigned int partial;
-
- int result = 0;
- int maxretry;
+ struct usb_lcd *dev;
- /* Sanity check to make sure lcd is connected, powered, etc */
- if (lcd == NULL ||
- lcd->present == 0 ||
- lcd->lcd_dev == NULL)
- return -1;
+ dev = (struct usb_lcd *)urb->context;
- do {
- unsigned long thistime;
- char *obuf = lcd->obuf;
-
- thistime = copy_size =
- (count >= OBUF_SIZE) ? OBUF_SIZE : count;
- if (copy_from_user(lcd->obuf, buffer, copy_size))
- return -EFAULT;
- maxretry = 5;
- while (thistime) {
- if (!lcd->lcd_dev)
- return -ENODEV;
- if (signal_pending(current)) {
- return bytes_written ? bytes_written : -EINTR;
- }
-
- result = usb_bulk_msg(lcd->lcd_dev,
- usb_sndbulkpipe(lcd->lcd_dev, 1),
- obuf, thistime, &partial, 10 * HZ);
-
- dbg("write stats: result:%d thistime:%lu partial:%u",
- result, thistime, partial);
-
- if (result == -ETIMEDOUT) { /* NAK - so hold for a while */
- if (!maxretry--) {
- return -ETIME;
- }
- interruptible_sleep_on_timeout(&lcd-> wait_q, NAK_TIMEOUT);
- continue;
- } else if (!result && partial) {
- obuf += partial;
- thistime -= partial;
- } else
- break;
- };
- if (result) {
- err("Write Whoops - %x", result);
- return -EIO;
- }
- bytes_written += copy_size;
- count -= copy_size;
- buffer += copy_size;
- } while (count > 0);
+ /* sync/async unlink faults aren't errors */
+ if (urb->status &&
+ !(urb->status == -ENOENT ||
+ urb->status == -ECONNRESET ||
+ urb->status == -ESHUTDOWN)) {
+ dbg("USBLCD: %s - nonzero write bulk status received: %d",
+ __FUNCTION__, urb->status);
+ }
- return bytes_written ? bytes_written : -EIO;
+ /* free up our allocated buffer */
+ usb_buffer_free(urb->dev, urb->transfer_buffer_length,
+ urb->transfer_buffer, urb->transfer_dma);
}
-static ssize_t
-read_lcd(struct file *file, char __user *buffer, size_t count, loff_t * ppos)
+static ssize_t lcd_write(struct file *file, const char __user * user_buffer, size_t count, loff_t *ppos)
{
- struct lcd_usb_data *lcd = &lcd_instance;
- ssize_t read_count;
- unsigned int partial;
- int this_read;
- int result;
- int maxretry = 10;
- char *ibuf = lcd->ibuf;
-
- /* Sanity check to make sure lcd is connected, powered, etc */
- if (lcd == NULL ||
- lcd->present == 0 ||
- lcd->lcd_dev == NULL)
- return -1;
-
- read_count = 0;
+ struct usb_lcd *dev;
+ int retval = 0;
+ struct urb *urb = NULL;
+ char *buf = NULL;
+
+ dev = (struct usb_lcd *)file->private_data;
+
+ /* verify that we actually have some data to write */
+ if (count == 0)
+ 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) {
+ retval = -ENOMEM;
+ goto error;
+ }
+
+ buf = usb_buffer_alloc(dev->udev, count, GFP_KERNEL, &urb->transfer_dma);
+ if (!buf) {
+ retval = -ENOMEM;
+ goto error;
+ }
+
+ if (copy_from_user(buf, user_buffer, count)) {
+ retval = -EFAULT;
+ goto error;
+ }
+
+ /* initialize the urb properly */
+ usb_fill_bulk_urb(urb, dev->udev,
+ usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr),
+ buf, count, lcd_write_bulk_callback, dev);
+ urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+ /* send the data out the bulk port */
+ retval = usb_submit_urb(urb, GFP_KERNEL);
+ if (retval) {
+ err("USBLCD: %s - failed submitting write urb, error %d", __FUNCTION__, retval);
+ goto error;
+ }
+
+ /* release our reference to this urb, the USB core will eventually free it entirely */
+ usb_free_urb(urb);
- while (count > 0) {
- if (signal_pending(current)) {
- return read_count ? read_count : -EINTR;
- }
- if (!lcd->lcd_dev)
- return -ENODEV;
- this_read = (count >= IBUF_SIZE) ? IBUF_SIZE : count;
-
- result = usb_bulk_msg(lcd->lcd_dev,
- usb_rcvbulkpipe(lcd->lcd_dev, 0),
- ibuf, this_read, &partial,
- (int) (HZ * 8));
-
- dbg(KERN_DEBUG "read stats: result:%d this_read:%u partial:%u",
- result, this_read, partial);
-
- if (partial) {
- count = this_read = partial;
- } else if (result == -ETIMEDOUT || result == 15) { /* FIXME: 15 ??? */
- if (!maxretry--) {
- err("read_lcd: maxretry timeout");
- return -ETIME;
- }
- interruptible_sleep_on_timeout(&lcd->wait_q,
- NAK_TIMEOUT);
- continue;
- } else if (result != -EREMOTEIO) {
- err("Read Whoops - result:%u partial:%u this_read:%u",
- result, partial, this_read);
- return -EIO;
- } else {
- return (0);
- }
+exit:
+ return count;
- if (this_read) {
- if (copy_to_user(buffer, ibuf, this_read))
- return -EFAULT;
- count -= this_read;
- read_count += this_read;
- buffer += this_read;
- }
- }
- return read_count;
+error:
+ usb_buffer_free(dev->udev, count, buf, urb->transfer_dma);
+ usb_free_urb(urb);
+ return retval;
}
-static struct
-file_operations usb_lcd_fops = {
- .owner = THIS_MODULE,
- .read = read_lcd,
- .write = write_lcd,
- .ioctl = ioctl_lcd,
- .open = open_lcd,
- .release = close_lcd,
+static struct file_operations lcd_fops = {
+ .owner = THIS_MODULE,
+ .read = lcd_read,
+ .write = lcd_write,
+ .open = lcd_open,
+ .ioctl = lcd_ioctl,
+ .release = lcd_release,
};
-static struct usb_class_driver usb_lcd_class = {
- .name = "usb/lcd%d",
- .fops = &usb_lcd_fops,
- .mode = S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
- .minor_base = USBLCD_MINOR,
+/*
+ * * usb class driver info in order to get a minor number from the usb core,
+ * * and to have the device registered with devfs and the driver core
+ * */
+static struct usb_class_driver lcd_class = {
+ .name = "usb/lcd%d",
+ .fops = &lcd_fops,
+ .mode = S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH,
+ .minor_base = USBLCD_MINOR,
};
-static int probe_lcd(struct usb_interface *intf, const struct usb_device_id *id)
+static int lcd_probe(struct usb_interface *interface, const struct usb_device_id *id)
{
- struct usb_device *dev = interface_to_usbdev(intf);
- struct lcd_usb_data *lcd = &lcd_instance;
+ struct usb_lcd *dev = NULL;
+ struct usb_host_interface *iface_desc;
+ struct usb_endpoint_descriptor *endpoint;
+ size_t buffer_size;
int i;
- int retval;
+ int retval = -ENOMEM;
- if (le16_to_cpu(dev->descriptor.idProduct) != 0x0001) {
- warn(KERN_INFO "USBLCD model not supported.");
- return -ENODEV;
+ /* allocate memory for our device state and initialize it */
+ dev = kmalloc(sizeof(*dev), GFP_KERNEL);
+ if (dev == NULL) {
+ err("Out of memory");
+ goto error;
}
+ memset(dev, 0x00, sizeof(*dev));
+ kref_init(&dev->kref);
+
+ dev->udev = usb_get_dev(interface_to_usbdev(interface));
+ dev->interface = interface;
- if (lcd->present == 1) {
- warn(KERN_INFO "Multiple USBLCDs are not supported!");
+ if (le16_to_cpu(dev->udev->descriptor.idProduct) != 0x0001) {
+ warn(KERN_INFO "USBLCD model not supported.");
return -ENODEV;
}
+
+ /* set up the endpoint information */
+ /* use only the first bulk-in and bulk-out endpoints */
+ iface_desc = interface->cur_altsetting;
+ for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
+ endpoint = &iface_desc->endpoint[i].desc;
+
+ if (!dev->bulk_in_endpointAddr &&
+ (endpoint->bEndpointAddress & USB_DIR_IN) &&
+ ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+ == USB_ENDPOINT_XFER_BULK)) {
+ /* we found a bulk in endpoint */
+ buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
+ dev->bulk_in_size = buffer_size;
+ dev->bulk_in_endpointAddr = endpoint->bEndpointAddress;
+ dev->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL);
+ if (!dev->bulk_in_buffer) {
+ err("Could not allocate bulk_in_buffer");
+ goto error;
+ }
+ }
- i = le16_to_cpu(dev->descriptor.bcdDevice);
-
- info("USBLCD Version %1d%1d.%1d%1d found at address %d",
- (i & 0xF000)>>12,(i & 0xF00)>>8,(i & 0xF0)>>4,(i & 0xF),
- dev->devnum);
-
-
-
- lcd->present = 1;
- lcd->lcd_dev = dev;
-
- if (!(lcd->obuf = (char *) kmalloc(OBUF_SIZE, GFP_KERNEL))) {
- err("probe_lcd: Not enough memory for the output buffer");
- return -ENOMEM;
+ if (!dev->bulk_out_endpointAddr &&
+ !(endpoint->bEndpointAddress & USB_DIR_IN) &&
+ ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+ == USB_ENDPOINT_XFER_BULK)) {
+ /* we found a bulk out endpoint */
+ dev->bulk_out_endpointAddr = endpoint->bEndpointAddress;
+ }
}
- dbg("probe_lcd: obuf address:%p", lcd->obuf);
-
- if (!(lcd->ibuf = (char *) kmalloc(IBUF_SIZE, GFP_KERNEL))) {
- err("probe_lcd: Not enough memory for the input buffer");
- kfree(lcd->obuf);
- return -ENOMEM;
+ if (!(dev->bulk_in_endpointAddr && dev->bulk_out_endpointAddr)) {
+ err("Could not find both bulk-in and bulk-out endpoints");
+ goto error;
}
- dbg("probe_lcd: ibuf address:%p", lcd->ibuf);
- retval = usb_register_dev(intf, &usb_lcd_class);
+ /* save our data pointer in this interface device */
+ usb_set_intfdata(interface, dev);
+
+ /* we can register the device now, as it is ready */
+ retval = usb_register_dev(interface, &lcd_class);
if (retval) {
+ /* something prevented us from registering this driver */
err("Not able to get a minor for this device.");
- kfree(lcd->obuf);
- kfree(lcd->ibuf);
- return -ENOMEM;
+ usb_set_intfdata(interface, NULL);
+ goto error;
}
- usb_set_intfdata (intf, lcd);
+ i = le16_to_cpu(dev->udev->descriptor.bcdDevice);
+
+ info("USBLCD Version %1d%1d.%1d%1d found at address %d",
+ (i & 0xF000)>>12,(i & 0xF00)>>8,(i & 0xF0)>>4,(i & 0xF),
+ dev->udev->devnum);
+
+ /* let the user know what node this device is now attached to */
+ info("USB LCD device now attached to USBLCD-%d", interface->minor);
return 0;
+
+error:
+ if (dev)
+ kref_put(&dev->kref, lcd_delete);
+ return retval;
}
-static void disconnect_lcd(struct usb_interface *intf)
+static void lcd_disconnect(struct usb_interface *interface)
{
- struct lcd_usb_data *lcd = usb_get_intfdata (intf);
+ struct usb_lcd *dev;
+ int minor = interface->minor;
- usb_set_intfdata (intf, NULL);
- if (lcd) {
- usb_deregister_dev(intf, &usb_lcd_class);
+ /* prevent skel_open() from racing skel_disconnect() */
+ lock_kernel();
- if (lcd->isopen) {
- lcd->isopen = 0;
- /* better let it finish - the release will do whats needed */
- lcd->lcd_dev = NULL;
- return;
- }
- kfree(lcd->ibuf);
- kfree(lcd->obuf);
+ dev = usb_get_intfdata(interface);
+ usb_set_intfdata(interface, NULL);
- info("USBLCD disconnected.");
-
- lcd->present = 0;
- }
-}
+ /* give back our minor */
+ usb_deregister_dev(interface, &lcd_class);
+
+ unlock_kernel();
-static struct usb_device_id id_table [] = {
- { .idVendor = 0x10D2, .match_flags = USB_DEVICE_ID_MATCH_VENDOR, },
- {},
-};
+ /* decrement our usage count */
+ kref_put(&dev->kref, lcd_delete);
-MODULE_DEVICE_TABLE (usb, id_table);
+ info("USB LCD #%d now disconnected", minor);
+}
static struct usb_driver lcd_driver = {
.owner = THIS_MODULE,
.name = "usblcd",
- .probe = (void *)probe_lcd,
- .disconnect = disconnect_lcd,
+ .probe = lcd_probe,
+ .disconnect = lcd_disconnect,
.id_table = id_table,
};
static int __init usb_lcd_init(void)
{
- int retval;
- retval = usb_register(&lcd_driver);
- if (retval)
- goto out;
-
- info("%s (C) Adams IT Services http://www.usblcd.de", DRIVER_VERSION);
- info("USBLCD support registered.");
-out:
- return retval;
+ int result;
+
+ result = usb_register(&lcd_driver);
+ if (result)
+ err("usb_register failed. Error number %d", result);
+
+ return result;
}
-static void __exit usb_lcd_cleanup(void)
+static void __exit usb_lcd_exit(void)
{
- struct lcd_usb_data *lcd = &lcd_instance;
-
- lcd->present = 0;
usb_deregister(&lcd_driver);
}
module_init(usb_lcd_init);
-module_exit(usb_lcd_cleanup);
+module_exit(usb_lcd_exit);
-MODULE_AUTHOR("Adams IT Services <info@usblcd.de>");
+MODULE_AUTHOR("Georges Toth <g.toth@e-biz.lu>");
MODULE_DESCRIPTION(DRIVER_VERSION);
MODULE_LICENSE("GPL");
diff --git a/drivers/usb/misc/usbled.c b/drivers/usb/misc/usbled.c
index 4f8bd56352b72..ee329d5e1c5e7 100644
--- a/drivers/usb/misc/usbled.c
+++ b/drivers/usb/misc/usbled.c
@@ -74,7 +74,7 @@ static void change_color(struct usb_led *led)
(0x00 * 0x100) + color,
buffer,
8,
- 2 * HZ);
+ 2000);
if (retval)
dev_dbg(&led->udev->dev, "retval = %d\n", retval);
kfree(buffer);
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
index 38eb2993fc3cb..3104f28f6aa8d 100644
--- a/drivers/usb/misc/usbtest.c
+++ b/drivers/usb/misc/usbtest.c
@@ -472,7 +472,7 @@ static int get_altsetting (struct usbtest_dev *dev)
retval = usb_control_msg (udev, usb_rcvctrlpipe (udev, 0),
USB_REQ_GET_INTERFACE, USB_DIR_IN|USB_RECIP_INTERFACE,
0, iface->altsetting [0].desc.bInterfaceNumber,
- dev->buf, 1, HZ * USB_CTRL_GET_TIMEOUT);
+ dev->buf, 1, USB_CTRL_GET_TIMEOUT);
switch (retval) {
case 1:
return dev->buf [0];
@@ -602,7 +602,7 @@ static int ch9_postconfig (struct usbtest_dev *dev)
retval = usb_control_msg (udev, usb_rcvctrlpipe (udev, 0),
USB_REQ_GET_CONFIGURATION,
USB_DIR_IN | USB_RECIP_DEVICE,
- 0, 0, dev->buf, 1, HZ * USB_CTRL_GET_TIMEOUT);
+ 0, 0, dev->buf, 1, USB_CTRL_GET_TIMEOUT);
if (retval != 1 || dev->buf [0] != expected) {
dev_dbg (&iface->dev,
"get config --> %d (%d)\n", retval,
@@ -851,7 +851,7 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param)
*/
urb = kmalloc (param->sglen * sizeof (struct urb *), SLAB_KERNEL);
if (!urb)
- goto cleanup;
+ return -ENOMEM;
memset (urb, 0, param->sglen * sizeof (struct urb *));
for (i = 0; i < param->sglen; i++) {
int pipe = usb_rcvctrlpipe (udev, 0);
@@ -1173,7 +1173,7 @@ static int test_halt (int ep, struct urb *urb)
retval = usb_control_msg (urb->dev, usb_sndctrlpipe (urb->dev, 0),
USB_REQ_SET_FEATURE, USB_RECIP_ENDPOINT,
USB_ENDPOINT_HALT, ep,
- NULL, 0, HZ * USB_CTRL_SET_TIMEOUT);
+ NULL, 0, USB_CTRL_SET_TIMEOUT);
if (retval < 0) {
dbg ("ep %02x couldn't set halt, %d", ep, retval);
return retval;
@@ -1263,7 +1263,7 @@ static int ctrl_out (struct usbtest_dev *dev,
buf [j] = i + j;
retval = usb_control_msg (udev, usb_sndctrlpipe (udev,0),
0x5b, USB_DIR_OUT|USB_TYPE_VENDOR,
- 0, 0, buf, len, HZ * USB_CTRL_SET_TIMEOUT);
+ 0, 0, buf, len, USB_CTRL_SET_TIMEOUT);
if (retval != len) {
what = "write";
break;
@@ -1272,7 +1272,7 @@ static int ctrl_out (struct usbtest_dev *dev,
/* read it back -- assuming nothing intervened!! */
retval = usb_control_msg (udev, usb_rcvctrlpipe (udev,0),
0x5c, USB_DIR_IN|USB_TYPE_VENDOR,
- 0, 0, buf, len, HZ * USB_CTRL_GET_TIMEOUT);
+ 0, 0, buf, len, USB_CTRL_GET_TIMEOUT);
if (retval != len) {
what = "read";
break;
diff --git a/drivers/usb/misc/uss720.c b/drivers/usb/misc/uss720.c
index de91f8bafe624..faa74436de52c 100644
--- a/drivers/usb/misc/uss720.c
+++ b/drivers/usb/misc/uss720.c
@@ -75,7 +75,7 @@ static int get_1284_register(struct parport *pp, unsigned char reg, unsigned cha
if (!usbdev)
return -1;
- ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev,0), 3, 0xc0, ((unsigned int)reg) << 8, 0, priv->reg, 7, HZ);
+ ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev,0), 3, 0xc0, ((unsigned int)reg) << 8, 0, priv->reg, 7, 1000);
if (ret != 7) {
printk(KERN_DEBUG "uss720: get_1284_register(%d) failed, status 0x%x expected 7\n",
(unsigned int)reg, ret);
@@ -105,7 +105,7 @@ static int set_1284_register(struct parport *pp, unsigned char reg, unsigned cha
if (!usbdev)
return -1;
- ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev,0), 4, 0x40, (((unsigned int)reg) << 8) | val, 0, NULL, 0, HZ);
+ ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev,0), 4, 0x40, (((unsigned int)reg) << 8) | val, 0, NULL, 0, 1000);
if (ret) {
printk(KERN_DEBUG "uss720: set_1284_register(%u,0x%02x) failed, status 0x%x\n",
(unsigned int)reg, (unsigned int)val, ret);
@@ -374,7 +374,7 @@ static size_t parport_uss720_epp_write_data(struct parport *pp, const void *buf,
return 0;
if (change_mode(pp, ECR_EPP))
return 0;
- i = usb_bulk_msg(usbdev, usb_sndbulkpipe(usbdev, 1), (void *)buf, length, &rlen, HZ*20);
+ i = usb_bulk_msg(usbdev, usb_sndbulkpipe(usbdev, 1), (void *)buf, length, &rlen, 20000);
if (i)
printk(KERN_ERR "uss720: sendbulk ep 1 buf %p len %Zu rlen %u\n", buf, length, rlen);
change_mode(pp, ECR_PS2);
@@ -435,7 +435,7 @@ static size_t parport_uss720_ecp_write_data(struct parport *pp, const void *buff
return 0;
if (change_mode(pp, ECR_ECP))
return 0;
- i = usb_bulk_msg(usbdev, usb_sndbulkpipe(usbdev, 1), (void *)buffer, len, &rlen, HZ*20);
+ i = usb_bulk_msg(usbdev, usb_sndbulkpipe(usbdev, 1), (void *)buffer, len, &rlen, 20000);
if (i)
printk(KERN_ERR "uss720: sendbulk ep 1 buf %p len %Zu rlen %u\n", buffer, len, rlen);
change_mode(pp, ECR_PS2);
@@ -453,7 +453,7 @@ static size_t parport_uss720_ecp_read_data(struct parport *pp, void *buffer, siz
return 0;
if (change_mode(pp, ECR_ECP))
return 0;
- i = usb_bulk_msg(usbdev, usb_rcvbulkpipe(usbdev, 2), buffer, len, &rlen, HZ*20);
+ i = usb_bulk_msg(usbdev, usb_rcvbulkpipe(usbdev, 2), buffer, len, &rlen, 20000);
if (i)
printk(KERN_ERR "uss720: recvbulk ep 2 buf %p len %Zu rlen %u\n", buffer, len, rlen);
change_mode(pp, ECR_PS2);
@@ -486,7 +486,7 @@ static size_t parport_uss720_write_compat(struct parport *pp, const void *buffer
return 0;
if (change_mode(pp, ECR_PPF))
return 0;
- i = usb_bulk_msg(usbdev, usb_sndbulkpipe(usbdev, 1), (void *)buffer, len, &rlen, HZ*20);
+ i = usb_bulk_msg(usbdev, usb_sndbulkpipe(usbdev, 1), (void *)buffer, len, &rlen, 20000);
if (i)
printk(KERN_ERR "uss720: sendbulk ep 1 buf %p len %Zu rlen %u\n", buffer, len, rlen);
change_mode(pp, ECR_PS2);
diff --git a/drivers/usb/mon/Kconfig b/drivers/usb/mon/Kconfig
new file mode 100644
index 0000000000000..4e6152aa5f196
--- /dev/null
+++ b/drivers/usb/mon/Kconfig
@@ -0,0 +1,22 @@
+#
+# USB Monitor configuration
+#
+
+# In normal life, it makes little sense to have usbmon as a module, and in fact
+# it is harmful, because there is no way to autoload the module.
+# The 'm' option is allowed for hackers who debug the usbmon itself,
+# and for those who have usbcore as a module.
+config USB_MON
+ tristate "USB Monitor"
+ depends on USB
+ default y
+ help
+ If you say Y here, a component which captures the USB traffic
+ between peripheral-specific drivers and HC drivers will be built.
+ The USB_MON is similar in spirit and may be compatible with Dave
+ Harding's USBMon.
+
+ This is somewhat experimental at this time, but it should be safe,
+ as long as you aren't building this as a module and then removing it.
+
+ If unsure, say Y. Do not say M.
diff --git a/drivers/usb/mon/Makefile b/drivers/usb/mon/Makefile
new file mode 100644
index 0000000000000..3cff8d444bb16
--- /dev/null
+++ b/drivers/usb/mon/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for USB Core files and filesystem
+#
+
+usbmon-objs := mon_main.o mon_stat.o mon_text.o
+
+obj-$(CONFIG_USB_MON) += usbmon.o
diff --git a/drivers/usb/mon/mon_main.c b/drivers/usb/mon/mon_main.c
new file mode 100644
index 0000000000000..aa9d00808e4e3
--- /dev/null
+++ b/drivers/usb/mon/mon_main.c
@@ -0,0 +1,377 @@
+/*
+ * The USB Monitor, inspired by Dave Harding's USBMon.
+ *
+ * mon_main.c: Main file, module initiation and exit, registrations, etc.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/debugfs.h>
+#include <linux/smp_lock.h>
+
+#include "usb_mon.h"
+#include "../core/hcd.h"
+
+static void mon_submit(struct usb_bus *ubus, struct urb *urb);
+static void mon_complete(struct usb_bus *ubus, struct urb *urb);
+static void mon_stop(struct mon_bus *mbus);
+static void mon_dissolve(struct mon_bus *mbus, struct usb_bus *ubus);
+static void mon_bus_drop(struct kref *r);
+static void mon_bus_init(struct dentry *mondir, struct usb_bus *ubus);
+
+DECLARE_MUTEX(mon_lock);
+
+static struct dentry *mon_dir; /* /dbg/usbmon */
+static LIST_HEAD(mon_buses); /* All buses we know: struct mon_bus */
+
+/*
+ * Link a reader into the bus.
+ *
+ * This must be called with mon_lock taken because of mbus->ref.
+ */
+void mon_reader_add(struct mon_bus *mbus, struct mon_reader *r)
+{
+ unsigned long flags;
+ struct usb_bus *ubus;
+
+ spin_lock_irqsave(&mbus->lock, flags);
+ if (mbus->nreaders == 0) {
+ ubus = mbus->u_bus;
+ if (ubus->monitored) {
+ /*
+ * Something is really broken, refuse to go on and
+ * possibly corrupt ops pointers or worse.
+ */
+ printk(KERN_ERR TAG ": bus %d is already monitored\n",
+ ubus->busnum);
+ spin_unlock_irqrestore(&mbus->lock, flags);
+ return;
+ }
+ ubus->monitored = 1;
+ }
+ mbus->nreaders++;
+ list_add_tail(&r->r_link, &mbus->r_list);
+ spin_unlock_irqrestore(&mbus->lock, flags);
+
+ kref_get(&mbus->ref);
+}
+
+/*
+ * Unlink reader from the bus.
+ *
+ * This is called with mon_lock taken, so we can decrement mbus->ref.
+ */
+void mon_reader_del(struct mon_bus *mbus, struct mon_reader *r)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&mbus->lock, flags);
+ list_del(&r->r_link);
+ --mbus->nreaders;
+ if (mbus->nreaders == 0)
+ mon_stop(mbus);
+ spin_unlock_irqrestore(&mbus->lock, flags);
+
+ kref_put(&mbus->ref, mon_bus_drop);
+}
+
+/*
+ */
+static void mon_submit(struct usb_bus *ubus, struct urb *urb)
+{
+ struct mon_bus *mbus;
+ unsigned long flags;
+ struct list_head *pos;
+ struct mon_reader *r;
+
+ mbus = ubus->mon_bus;
+ if (mbus == NULL)
+ goto out_unlocked;
+
+ spin_lock_irqsave(&mbus->lock, flags);
+ if (mbus->nreaders == 0)
+ goto out_locked;
+
+ list_for_each (pos, &mbus->r_list) {
+ r = list_entry(pos, struct mon_reader, r_link);
+ r->rnf_submit(r->r_data, urb);
+ }
+
+ spin_unlock_irqrestore(&mbus->lock, flags);
+ return;
+
+out_locked:
+ spin_unlock_irqrestore(&mbus->lock, flags);
+out_unlocked:
+ return;
+}
+
+/*
+ */
+static void mon_submit_error(struct usb_bus *ubus, struct urb *urb, int err)
+{
+ struct mon_bus *mbus;
+
+ mbus = ubus->mon_bus;
+ if (mbus == NULL)
+ goto out_unlocked;
+
+ /*
+ * XXX Capture the error code and the 'E' event.
+ */
+
+ return;
+
+out_unlocked:
+ return;
+}
+
+/*
+ */
+static void mon_complete(struct usb_bus *ubus, struct urb *urb)
+{
+ struct mon_bus *mbus;
+ unsigned long flags;
+ struct list_head *pos;
+ struct mon_reader *r;
+
+ mbus = ubus->mon_bus;
+ if (mbus == NULL) {
+ /*
+ * This should not happen.
+ * At this point we do not even know the bus number...
+ */
+ printk(KERN_ERR TAG ": Null mon bus in URB, pipe 0x%x\n",
+ urb->pipe);
+ return;
+ }
+
+ spin_lock_irqsave(&mbus->lock, flags);
+ list_for_each (pos, &mbus->r_list) {
+ r = list_entry(pos, struct mon_reader, r_link);
+ r->rnf_complete(r->r_data, urb);
+ }
+ spin_unlock_irqrestore(&mbus->lock, flags);
+}
+
+/* int (*unlink_urb) (struct urb *urb, int status); */
+
+/*
+ * Stop monitoring.
+ * Obviously this must be well locked, so no need to play with mb's.
+ */
+static void mon_stop(struct mon_bus *mbus)
+{
+ struct usb_bus *ubus = mbus->u_bus;
+
+ /*
+ * A stop can be called for a dissolved mon_bus in case of
+ * a reader staying across an rmmod foo_hcd.
+ */
+ if (ubus != NULL) {
+ ubus->monitored = 0;
+ mb();
+ }
+}
+
+/*
+ * Add a USB bus (usually by a modprobe foo-hcd)
+ *
+ * This does not return an error code because the core cannot care less
+ * if monitoring is not established.
+ */
+static void mon_bus_add(struct usb_bus *ubus)
+{
+ mon_bus_init(mon_dir, ubus);
+}
+
+/*
+ * Remove a USB bus (either from rmmod foo-hcd or from a hot-remove event).
+ */
+static void mon_bus_remove(struct usb_bus *ubus)
+{
+ struct mon_bus *mbus = ubus->mon_bus;
+
+ down(&mon_lock);
+ list_del(&mbus->bus_link);
+ debugfs_remove(mbus->dent_t);
+ debugfs_remove(mbus->dent_s);
+
+ mon_dissolve(mbus, ubus);
+ kref_put(&mbus->ref, mon_bus_drop);
+ up(&mon_lock);
+}
+
+/*
+ * Ops
+ */
+static struct usb_mon_operations mon_ops_0 = {
+ .urb_submit = mon_submit,
+ .urb_submit_error = mon_submit_error,
+ .urb_complete = mon_complete,
+ .bus_add = mon_bus_add,
+ .bus_remove = mon_bus_remove,
+};
+
+/*
+ * Tear usb_bus and mon_bus apart.
+ */
+static void mon_dissolve(struct mon_bus *mbus, struct usb_bus *ubus)
+{
+
+ /*
+ * Never happens, but...
+ */
+ if (ubus->monitored) {
+ printk(KERN_ERR TAG ": bus %d is dissolved while monitored\n",
+ ubus->busnum);
+ ubus->monitored = 0;
+ mb();
+ }
+
+ ubus->mon_bus = NULL;
+ mbus->u_bus = NULL;
+ mb();
+ // usb_bus_put(ubus);
+}
+
+/*
+ */
+static void mon_bus_drop(struct kref *r)
+{
+ struct mon_bus *mbus = container_of(r, struct mon_bus, ref);
+ kfree(mbus);
+}
+
+/*
+ * Initialize a bus for us:
+ * - allocate mon_bus
+ * - refcount USB bus struct
+ * - link
+ */
+static void mon_bus_init(struct dentry *mondir, struct usb_bus *ubus)
+{
+ struct dentry *d;
+ struct mon_bus *mbus;
+ enum { NAMESZ = 10 };
+ char name[NAMESZ];
+ int rc;
+
+ if ((mbus = kmalloc(sizeof(struct mon_bus), GFP_KERNEL)) == NULL)
+ goto err_alloc;
+ memset(mbus, 0, sizeof(struct mon_bus));
+ kref_init(&mbus->ref);
+ spin_lock_init(&mbus->lock);
+ INIT_LIST_HEAD(&mbus->r_list);
+
+ /*
+ * This usb_bus_get here is superfluous, because we receive
+ * a notification if usb_bus is about to be removed.
+ */
+ // usb_bus_get(ubus);
+ mbus->u_bus = ubus;
+ ubus->mon_bus = mbus;
+
+ rc = snprintf(name, NAMESZ, "%dt", ubus->busnum);
+ if (rc <= 0 || rc >= NAMESZ)
+ goto err_print_t;
+ d = debugfs_create_file(name, 0600, mondir, mbus, &mon_fops_text);
+ if (d == NULL)
+ goto err_create_t;
+ mbus->dent_t = d;
+
+ rc = snprintf(name, NAMESZ, "%ds", ubus->busnum);
+ if (rc <= 0 || rc >= NAMESZ)
+ goto err_print_s;
+ d = debugfs_create_file(name, 0600, mondir, mbus, &mon_fops_stat);
+ if (d == NULL)
+ goto err_create_s;
+ mbus->dent_s = d;
+
+ down(&mon_lock);
+ list_add_tail(&mbus->bus_link, &mon_buses);
+ up(&mon_lock);
+ return;
+
+err_create_s:
+err_print_s:
+ debugfs_remove(mbus->dent_t);
+err_create_t:
+err_print_t:
+ kfree(mbus);
+err_alloc:
+ return;
+}
+
+static int __init mon_init(void)
+{
+ struct usb_bus *ubus;
+ struct dentry *mondir;
+
+ mondir = debugfs_create_dir("usbmon", NULL);
+ if (IS_ERR(mondir)) {
+ printk(KERN_NOTICE TAG ": debugs is not available\n");
+ return -ENODEV;
+ }
+ if (mondir == NULL) {
+ printk(KERN_NOTICE TAG ": unable to create usbmon directory\n");
+ return -ENODEV;
+ }
+ mon_dir = mondir;
+
+ if (usb_mon_register(&mon_ops_0) != 0) {
+ printk(KERN_NOTICE TAG ": unable to register with the core\n");
+ debugfs_remove(mondir);
+ return -ENODEV;
+ }
+ // MOD_INC_USE_COUNT(which_module?);
+
+ down(&usb_bus_list_lock);
+ list_for_each_entry (ubus, &usb_bus_list, bus_list) {
+ mon_bus_init(mondir, ubus);
+ }
+ up(&usb_bus_list_lock);
+ return 0;
+}
+
+static void __exit mon_exit(void)
+{
+ struct mon_bus *mbus;
+ struct list_head *p;
+
+ usb_mon_deregister();
+
+ down(&mon_lock);
+ while (!list_empty(&mon_buses)) {
+ p = mon_buses.next;
+ mbus = list_entry(p, struct mon_bus, bus_link);
+ list_del(p);
+
+ debugfs_remove(mbus->dent_t);
+ debugfs_remove(mbus->dent_s);
+
+ /*
+ * This never happens, because the open/close paths in
+ * file level maintain module use counters and so rmmod fails
+ * before reaching here. However, better be safe...
+ */
+ if (mbus->nreaders) {
+ printk(KERN_ERR TAG
+ ": Outstanding opens (%d) on usb%d, leaking...\n",
+ mbus->nreaders, mbus->u_bus->busnum);
+ atomic_set(&mbus->ref.refcount, 2); /* Force leak */
+ }
+
+ mon_dissolve(mbus, mbus->u_bus);
+ kref_put(&mbus->ref, mon_bus_drop);
+ }
+ up(&mon_lock);
+
+ debugfs_remove(mon_dir);
+}
+
+module_init(mon_init);
+module_exit(mon_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/mon/mon_stat.c b/drivers/usb/mon/mon_stat.c
new file mode 100644
index 0000000000000..6e4b165d070ad
--- /dev/null
+++ b/drivers/usb/mon/mon_stat.c
@@ -0,0 +1,74 @@
+/*
+ * The USB Monitor, inspired by Dave Harding's USBMon.
+ *
+ * This is the 's' or 'stat' reader which debugs usbmon itself.
+ * Note that this code blows through locks, so make sure that
+ * /dbg/usbmon/0s is well protected from non-root users.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/usb.h>
+#include <asm/uaccess.h>
+
+#include "usb_mon.h"
+
+#define STAT_BUF_SIZE 80
+
+struct snap {
+ int slen;
+ char str[STAT_BUF_SIZE];
+};
+
+static int mon_stat_open(struct inode *inode, struct file *file)
+{
+ struct mon_bus *mbus;
+ struct snap *sp;
+
+ if ((sp = kmalloc(sizeof(struct snap), GFP_KERNEL)) == NULL)
+ return -ENOMEM;
+
+ mbus = inode->u.generic_ip;
+
+ sp->slen = snprintf(sp->str, STAT_BUF_SIZE,
+ "nreaders %d text_lost %u\n",
+ mbus->nreaders, mbus->cnt_text_lost);
+
+ file->private_data = sp;
+ return 0;
+}
+
+static ssize_t mon_stat_read(struct file *file, char __user *buf,
+ size_t nbytes, loff_t *ppos)
+{
+ struct snap *sp = file->private_data;
+ loff_t pos = *ppos;
+ int cnt;
+
+ if (pos < 0 || pos >= sp->slen)
+ return 0;
+ if (nbytes == 0)
+ return 0;
+ if ((cnt = sp->slen - pos) > nbytes)
+ cnt = nbytes;
+ if (copy_to_user(buf, sp->str + pos, cnt))
+ return -EFAULT;
+ *ppos = pos + cnt;
+ return cnt;
+}
+
+static int mon_stat_release(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
+struct file_operations mon_fops_stat = {
+ .owner = THIS_MODULE,
+ .open = mon_stat_open,
+ .llseek = no_llseek,
+ .read = mon_stat_read,
+ /* .write = mon_stat_write, */
+ /* .poll = mon_stat_poll, */
+ /* .ioctl = mon_stat_ioctl, */
+ .release = mon_stat_release,
+};
diff --git a/drivers/usb/mon/mon_text.c b/drivers/usb/mon/mon_text.c
new file mode 100644
index 0000000000000..755a4570477fd
--- /dev/null
+++ b/drivers/usb/mon/mon_text.c
@@ -0,0 +1,405 @@
+/*
+ * The USB Monitor, inspired by Dave Harding's USBMon.
+ *
+ * This is a text format reader.
+ */
+
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/usb.h>
+#include <linux/time.h>
+#include <asm/uaccess.h>
+
+#include "usb_mon.h"
+
+/*
+ * No, we do not want arbitrarily long data strings.
+ * Use the binary interface if you want to capture bulk data!
+ */
+#define DATA_MAX 32
+
+/*
+ * This limit exists to prevent OOMs when the user process stops reading.
+ */
+#define EVENT_MAX 25
+
+#define PRINTF_DFL 120
+
+struct mon_event_text {
+ struct list_head e_link;
+ int type; /* submit, complete, etc. */
+ unsigned int pipe; /* Pipe */
+ unsigned long id; /* From pointer, most of the time */
+ unsigned int tstamp;
+ int length; /* Depends on type: xfer length or act length */
+ int status;
+ char data_flag;
+ unsigned char data[DATA_MAX];
+};
+
+#define SLAB_NAME_SZ 30
+struct mon_reader_text {
+ kmem_cache_t *e_slab;
+ int nevents;
+ struct list_head e_list;
+ struct mon_reader r; /* In C, parent class can be placed anywhere */
+
+ wait_queue_head_t wait;
+ int printf_size;
+ char *printf_buf;
+ struct semaphore printf_lock;
+
+ char slab_name[SLAB_NAME_SZ];
+};
+
+static void mon_text_ctor(void *, kmem_cache_t *, unsigned long);
+static void mon_text_dtor(void *, kmem_cache_t *, unsigned long);
+
+/*
+ * mon_text_submit
+ * mon_text_complete
+ *
+ * May be called from an interrupt.
+ *
+ * This is called with the whole mon_bus locked, so no additional lock.
+ */
+
+static inline char mon_text_get_data(struct mon_event_text *ep, struct urb *urb,
+ int len, char ev_type)
+{
+ int pipe = urb->pipe;
+ unsigned char *data;
+
+ /*
+ * The check to see if it's safe to poke at data has an enormous
+ * number of corner cases, but it seems that the following is
+ * more or less safe.
+ *
+ * We do not even try to look transfer_buffer, because it can
+ * contain non-NULL garbage in case the upper level promised to
+ * set DMA for the HCD.
+ */
+ if (urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)
+ return 'D';
+
+ if (len <= 0)
+ return 'L';
+
+ if ((data = urb->transfer_buffer) == NULL)
+ return 'Z'; /* '0' would be not as pretty. */
+
+ /*
+ * Bulk is easy to shortcut reliably.
+ * XXX Control needs setup packet taken.
+ * 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 (len >= DATA_MAX)
+ len = DATA_MAX;
+ memcpy(ep->data, urb->transfer_buffer, len);
+ return 0;
+}
+
+static inline unsigned int mon_get_timestamp(void)
+{
+ struct timeval tval;
+ unsigned int stamp;
+
+ do_gettimeofday(&tval);
+ stamp = tval.tv_sec & 0xFFFF; /* 2^32 = 4294967296. Limit to 4096s. */
+ stamp = stamp * 1000000 + tval.tv_usec;
+ return stamp;
+}
+
+static void mon_text_event(struct mon_reader_text *rp, struct urb *urb,
+ char ev_type)
+{
+ struct mon_event_text *ep;
+ unsigned int stamp;
+
+ stamp = mon_get_timestamp();
+
+ if (rp->nevents >= EVENT_MAX ||
+ (ep = kmem_cache_alloc(rp->e_slab, SLAB_ATOMIC)) == NULL) {
+ rp->r.m_bus->cnt_text_lost++;
+ return;
+ }
+
+ ep->type = ev_type;
+ ep->pipe = urb->pipe;
+ ep->id = (unsigned long) urb;
+ ep->tstamp = stamp;
+ ep->length = (ev_type == 'S') ?
+ urb->transfer_buffer_length : urb->actual_length;
+ /* Collecting status makes debugging sense for submits, too */
+ ep->status = urb->status;
+
+ ep->data_flag = mon_text_get_data(ep, urb, ep->length, ev_type);
+
+ rp->nevents++;
+ list_add_tail(&ep->e_link, &rp->e_list);
+ wake_up(&rp->wait);
+}
+
+static void mon_text_submit(void *data, struct urb *urb)
+{
+ struct mon_reader_text *rp = data;
+ mon_text_event(rp, urb, 'S');
+}
+
+static void mon_text_complete(void *data, struct urb *urb)
+{
+ struct mon_reader_text *rp = data;
+ mon_text_event(rp, urb, 'C');
+}
+
+/*
+ * Fetch next event from the circular buffer.
+ */
+static struct mon_event_text *mon_text_fetch(struct mon_reader_text *rp,
+ struct mon_bus *mbus)
+{
+ struct list_head *p;
+ unsigned long flags;
+
+ spin_lock_irqsave(&mbus->lock, flags);
+ if (list_empty(&rp->e_list)) {
+ spin_unlock_irqrestore(&mbus->lock, flags);
+ return NULL;
+ }
+ p = rp->e_list.next;
+ list_del(p);
+ --rp->nevents;
+ spin_unlock_irqrestore(&mbus->lock, flags);
+ return list_entry(p, struct mon_event_text, e_link);
+}
+
+/*
+ */
+static int mon_text_open(struct inode *inode, struct file *file)
+{
+ struct mon_bus *mbus;
+ struct usb_bus *ubus;
+ struct mon_reader_text *rp;
+ int rc;
+
+ down(&mon_lock);
+ mbus = inode->u.generic_ip;
+ ubus = mbus->u_bus;
+
+ rp = kmalloc(sizeof(struct mon_reader_text), GFP_KERNEL);
+ if (rp == NULL) {
+ rc = -ENOMEM;
+ goto err_alloc;
+ }
+ memset(rp, 0, sizeof(struct mon_reader_text));
+ INIT_LIST_HEAD(&rp->e_list);
+ init_waitqueue_head(&rp->wait);
+ init_MUTEX(&rp->printf_lock);
+
+ rp->printf_size = PRINTF_DFL;
+ rp->printf_buf = kmalloc(rp->printf_size, GFP_KERNEL);
+ if (rp->printf_buf == NULL) {
+ rc = -ENOMEM;
+ goto err_alloc_pr;
+ }
+
+ rp->r.m_bus = mbus;
+ rp->r.r_data = rp;
+ rp->r.rnf_submit = mon_text_submit;
+ rp->r.rnf_complete = mon_text_complete;
+
+ snprintf(rp->slab_name, SLAB_NAME_SZ, "mon%dt_%lx", ubus->busnum,
+ (long)rp);
+ rp->e_slab = kmem_cache_create(rp->slab_name,
+ sizeof(struct mon_event_text), sizeof(long), 0,
+ mon_text_ctor, mon_text_dtor);
+ if (rp->e_slab == NULL) {
+ rc = -ENOMEM;
+ goto err_slab;
+ }
+
+ mon_reader_add(mbus, &rp->r);
+
+ file->private_data = rp;
+ up(&mon_lock);
+ return 0;
+
+// err_busy:
+// kmem_cache_destroy(rp->e_slab);
+err_slab:
+ kfree(rp->printf_buf);
+err_alloc_pr:
+ kfree(rp);
+err_alloc:
+ up(&mon_lock);
+ return rc;
+}
+
+/*
+ * For simplicity, we read one record in one system call and throw out
+ * what does not fit. This means that the following does not work:
+ * dd if=/dbg/usbmon/0t bs=10
+ * Also, we do not allow seeks and do not bother advancing the offset.
+ */
+static ssize_t mon_text_read(struct file *file, char __user *buf,
+ size_t nbytes, loff_t *ppos)
+{
+ struct mon_reader_text *rp = file->private_data;
+ struct mon_bus *mbus = rp->r.m_bus;
+ DECLARE_WAITQUEUE(waita, current);
+ struct mon_event_text *ep;
+ int cnt, limit;
+ char *pbuf;
+ char udir, utype;
+ int data_len, i;
+
+ add_wait_queue(&rp->wait, &waita);
+ set_current_state(TASK_INTERRUPTIBLE);
+ while ((ep = mon_text_fetch(rp, mbus)) == NULL) {
+ if (file->f_flags & O_NONBLOCK) {
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&rp->wait, &waita);
+ return -EWOULDBLOCK; /* Same as EAGAIN in Linux */
+ }
+ /*
+ * We do not count nwaiters, because ->release is supposed
+ * to be called when all openers are gone only.
+ */
+ schedule();
+ if (signal_pending(current)) {
+ remove_wait_queue(&rp->wait, &waita);
+ return -EINTR;
+ }
+ set_current_state(TASK_INTERRUPTIBLE);
+ }
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&rp->wait, &waita);
+
+ down(&rp->printf_lock);
+ cnt = 0;
+ pbuf = rp->printf_buf;
+ limit = rp->printf_size;
+
+ udir = usb_pipein(ep->pipe) ? 'i' : 'o';
+ switch (usb_pipetype(ep->pipe)) {
+ case PIPE_ISOCHRONOUS: utype = 'Z'; break;
+ case PIPE_INTERRUPT: utype = 'I'; break;
+ case PIPE_CONTROL: utype = 'C'; break;
+ default: /* PIPE_BULK */ utype = 'B';
+ }
+ cnt += snprintf(pbuf + cnt, limit - cnt,
+ "%lx %u %c %c%c:%03u:%02u %d %d",
+ ep->id, ep->tstamp, ep->type,
+ utype, udir, usb_pipedevice(ep->pipe), usb_pipeendpoint(ep->pipe),
+ ep->status, ep->length);
+
+ if ((data_len = ep->length) > 0) {
+ if (ep->data_flag == 0) {
+ cnt += snprintf(pbuf + cnt, limit - cnt, " =");
+ if (data_len >= DATA_MAX)
+ data_len = DATA_MAX;
+ for (i = 0; i < data_len; i++) {
+ if (i % 4 == 0) {
+ cnt += snprintf(pbuf + cnt, limit - cnt,
+ " ");
+ }
+ cnt += snprintf(pbuf + cnt, limit - cnt,
+ "%02x", ep->data[i]);
+ }
+ cnt += snprintf(pbuf + cnt, limit - cnt, "\n");
+ } else {
+ cnt += snprintf(pbuf + cnt, limit - cnt,
+ " %c\n", ep->data_flag);
+ }
+ } else {
+ cnt += snprintf(pbuf + cnt, limit - cnt, "\n");
+ }
+
+ if (copy_to_user(buf, rp->printf_buf, cnt))
+ cnt = -EFAULT;
+ up(&rp->printf_lock);
+ kmem_cache_free(rp->e_slab, ep);
+ return cnt;
+}
+
+static int mon_text_release(struct inode *inode, struct file *file)
+{
+ struct mon_reader_text *rp = file->private_data;
+ struct mon_bus *mbus;
+ /* unsigned long flags; */
+ struct list_head *p;
+ struct mon_event_text *ep;
+
+ down(&mon_lock);
+ mbus = inode->u.generic_ip;
+
+ if (mbus->nreaders <= 0) {
+ printk(KERN_ERR TAG ": consistency error on close\n");
+ up(&mon_lock);
+ return 0;
+ }
+ mon_reader_del(mbus, &rp->r);
+
+ /*
+ * In theory, e_list is protected by mbus->lock. However,
+ * after mon_reader_del has finished, the following is the case:
+ * - we are not on reader list anymore, so new events won't be added;
+ * - whole mbus may be dropped if it was orphaned.
+ * So, we better not touch mbus.
+ */
+ /* spin_lock_irqsave(&mbus->lock, flags); */
+ while (!list_empty(&rp->e_list)) {
+ p = rp->e_list.next;
+ ep = list_entry(p, struct mon_event_text, e_link);
+ list_del(p);
+ --rp->nevents;
+ kmem_cache_free(rp->e_slab, ep);
+ }
+ /* spin_unlock_irqrestore(&mbus->lock, flags); */
+
+ kmem_cache_destroy(rp->e_slab);
+ kfree(rp->printf_buf);
+ kfree(rp);
+
+ up(&mon_lock);
+ return 0;
+}
+
+struct file_operations mon_fops_text = {
+ .owner = THIS_MODULE,
+ .open = mon_text_open,
+ .llseek = no_llseek,
+ .read = mon_text_read,
+ /* .write = mon_text_write, */
+ /* .poll = mon_text_poll, */
+ /* .ioctl = mon_text_ioctl, */
+ .release = mon_text_release,
+};
+
+/*
+ * Slab interface: constructor.
+ */
+static void mon_text_ctor(void *mem, kmem_cache_t *slab, unsigned long sflags)
+{
+ /*
+ * Nothing to initialize. No, really!
+ * So, we fill it with garbage to emulate a reused object.
+ */
+ memset(mem, 0xe5, sizeof(struct mon_event_text));
+}
+
+static void mon_text_dtor(void *mem, kmem_cache_t *slab, unsigned long sflags)
+{
+ ;
+}
diff --git a/drivers/usb/mon/usb_mon.h b/drivers/usb/mon/usb_mon.h
new file mode 100644
index 0000000000000..ed35c18a5c44b
--- /dev/null
+++ b/drivers/usb/mon/usb_mon.h
@@ -0,0 +1,51 @@
+/*
+ * The USB Monitor, inspired by Dave Harding's USBMon.
+ */
+
+#ifndef __USB_MON_H
+#define __USB_MON_H
+
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/kref.h>
+/* #include <linux/usb.h> */ /* We use struct pointers only in this header */
+
+#define TAG "usbmon"
+
+struct mon_bus {
+ struct list_head bus_link;
+ spinlock_t lock;
+ struct dentry *dent_s; /* Debugging file */
+ struct dentry *dent_t; /* Text interface file */
+ struct usb_bus *u_bus;
+
+ /* Ref */
+ int nreaders; /* Under mon_lock AND mbus->lock */
+ struct list_head r_list; /* Chain of readers (usually one) */
+ struct kref ref; /* Under mon_lock */
+
+ /* Stats */
+ unsigned int cnt_text_lost;
+};
+
+/*
+ * An instance of a process which opened a file (but can fork later)
+ */
+struct mon_reader {
+ struct list_head r_link;
+ struct mon_bus *m_bus;
+ void *r_data; /* Use container_of instead? */
+
+ void (*rnf_submit)(void *data, struct urb *urb);
+ void (*rnf_complete)(void *data, struct urb *urb);
+};
+
+void mon_reader_add(struct mon_bus *mbus, struct mon_reader *r);
+void mon_reader_del(struct mon_bus *mbus, struct mon_reader *r);
+
+extern struct semaphore mon_lock;
+
+extern struct file_operations mon_fops_text;
+extern struct file_operations mon_fops_stat;
+
+#endif /* __USB_MON_H */
diff --git a/drivers/usb/net/Kconfig b/drivers/usb/net/Kconfig
index d64409e85472d..db64c908d4a73 100644
--- a/drivers/usb/net/Kconfig
+++ b/drivers/usb/net/Kconfig
@@ -260,13 +260,13 @@ comment "USB Network Adapters"
depends on USB_USBNET
config USB_AX8817X
- boolean "ASIX AX88172 Based USB 2.0 Ethernet Devices"
+ boolean "ASIX AX88xxx Based USB 2.0 Ethernet Devices"
depends on USB_USBNET && NET_ETHERNET
select CRC32
select MII
default y
help
- This option adds support for ASIX AX88172 based USB 2.0
+ This option adds support for ASIX AX88xxx based USB 2.0
10/100 Ethernet devices.
This driver should work with at least the following devices:
@@ -287,4 +287,21 @@ config USB_AX8817X
This driver creates an interface named "ethX", where X depends on
what other networking devices you have in use.
+config USB_ZD1201
+ tristate "USB ZD1201 based Wireless device support"
+ depends on NET_RADIO
+ select FW_LOADER
+ ---help---
+ Say Y if you want to use wireless LAN adapters based on the ZyDAS
+ ZD1201 chip.
+
+ This driver makes the adapter appear as a normal Ethernet interface,
+ typically on wlan0.
+
+ The zd1201 device requires external firmware to be loaded.
+ This can be found at http://linux-lc100020.sourceforge.net/
+
+ To compile this driver as a module, choose M here: the
+ module will be called zd1201.
+
endmenu
diff --git a/drivers/usb/net/Makefile b/drivers/usb/net/Makefile
index 5eec1ed7e40ab..16f352195512e 100644
--- a/drivers/usb/net/Makefile
+++ b/drivers/usb/net/Makefile
@@ -7,3 +7,6 @@ obj-$(CONFIG_USB_KAWETH) += kaweth.o
obj-$(CONFIG_USB_PEGASUS) += pegasus.o
obj-$(CONFIG_USB_RTL8150) += rtl8150.o
obj-$(CONFIG_USB_USBNET) += usbnet.o
+obj-$(CONFIG_USB_ZD1201) += zd1201.o
+
+CFLAGS_zd1201.o = -Idrivers/net/wireless/
diff --git a/drivers/usb/net/catc.c b/drivers/usb/net/catc.c
index af883ae40d653..c8be912f24e1a 100644
--- a/drivers/usb/net/catc.c
+++ b/drivers/usb/net/catc.c
@@ -457,7 +457,7 @@ static int catc_ctrl_msg(struct catc *catc, u8 dir, u8 request, u16 value, u16 i
{
int retval = usb_control_msg(catc->usbdev,
dir ? usb_rcvctrlpipe(catc->usbdev, 0) : usb_sndctrlpipe(catc->usbdev, 0),
- request, 0x40 | dir, value, index, buf, len, HZ);
+ request, 0x40 | dir, value, index, buf, len, 1000);
return retval < 0 ? retval : 0;
}
@@ -664,7 +664,8 @@ static void catc_set_multicast_list(struct net_device *netdev)
}
}
-void catc_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+static void catc_get_drvinfo(struct net_device *dev,
+ struct ethtool_drvinfo *info)
{
struct catc *catc = netdev_priv(dev);
strncpy(info->driver, driver_name, ETHTOOL_BUSINFO_LEN);
diff --git a/drivers/usb/net/kaweth.c b/drivers/usb/net/kaweth.c
index 2a83b0c33c296..a9a7cf4a38ebd 100644
--- a/drivers/usb/net/kaweth.c
+++ b/drivers/usb/net/kaweth.c
@@ -58,6 +58,7 @@
#include <linux/ethtool.h>
#include <linux/pci.h>
#include <linux/dma-mapping.h>
+#include <linux/wait.h>
#include <asm/uaccess.h>
#include <asm/semaphore.h>
#include <asm/byteorder.h>
@@ -593,7 +594,7 @@ static void kaweth_usb_receive(struct urb *urb, struct pt_regs *regs)
struct sk_buff *skb;
- if(unlikely(urb->status == -ECONNRESET || urb->status == -ECONNABORTED || urb->status == -ESHUTDOWN))
+ if(unlikely(urb->status == -ECONNRESET || urb->status == -ESHUTDOWN))
/* we are killed - set a flag and wake the disconnect handler */
{
kaweth->end = 1;
@@ -1180,31 +1181,21 @@ static void usb_api_blocking_completion(struct urb *urb, struct pt_regs *regs)
// Starts urb and waits for completion or timeout
static int usb_start_wait_urb(struct urb *urb, int timeout, int* actual_length)
{
- DECLARE_WAITQUEUE(wait, current);
struct usb_api_data awd;
int status;
init_waitqueue_head(&awd.wqh);
awd.done = 0;
- add_wait_queue(&awd.wqh, &wait);
urb->context = &awd;
status = usb_submit_urb(urb, GFP_NOIO);
if (status) {
// something went wrong
usb_free_urb(urb);
- remove_wait_queue(&awd.wqh, &wait);
return status;
}
- while (timeout && !awd.done) {
- set_current_state(TASK_UNINTERRUPTIBLE);
- timeout = schedule_timeout(timeout);
- }
-
- remove_wait_queue(&awd.wqh, &wait);
-
- if (!timeout) {
+ if (!wait_event_timeout(awd.wqh, awd.done, timeout)) {
// timeout
kaweth_warn("usb_control/bulk_msg: timeout");
usb_kill_urb(urb); // remove urb safely
diff --git a/drivers/usb/net/kawethfw.h b/drivers/usb/net/kawethfw.h
index 2b35baeac717a..cf85fcb0d1a6b 100644
--- a/drivers/usb/net/kawethfw.h
+++ b/drivers/usb/net/kawethfw.h
@@ -551,7 +551,7 @@ static __u8 kaweth_new_code_fix[] =
};
-const int len_kaweth_trigger_code = sizeof(kaweth_trigger_code);
-const int len_kaweth_trigger_code_fix = sizeof(kaweth_trigger_code_fix);
-const int len_kaweth_new_code = sizeof(kaweth_new_code);
-const int len_kaweth_new_code_fix = sizeof(kaweth_new_code_fix);
+static const int len_kaweth_trigger_code = sizeof(kaweth_trigger_code);
+static const int len_kaweth_trigger_code_fix = sizeof(kaweth_trigger_code_fix);
+static const int len_kaweth_new_code = sizeof(kaweth_new_code);
+static const int len_kaweth_new_code_fix = sizeof(kaweth_new_code_fix);
diff --git a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c
index 542481e979e2c..f6c19d73b7da9 100644
--- a/drivers/usb/net/pegasus.c
+++ b/drivers/usb/net/pegasus.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999-2003 Petko Manolov (petkan@users.sourceforge.net)
+ * Copyright (c) 1999-2005 Petko Manolov (petkan@users.sourceforge.net)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -47,7 +47,7 @@
/*
* Version Information
*/
-#define DRIVER_VERSION "v0.5.12 (2005/01/13)"
+#define DRIVER_VERSION "v0.6.12 (2005/01/13)"
#define DRIVER_AUTHOR "Petko Manolov <petkan@users.sourceforge.net>"
#define DRIVER_DESC "Pegasus/Pegasus II USB Ethernet driver"
@@ -85,6 +85,11 @@ module_param(mii_mode, bool, 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");
+/* use ethtool to change the level for any given device */
+static int msg_level = -1;
+module_param (msg_level, int, 0);
+MODULE_PARM_DESC (msg_level, "Override default message level");
+
MODULE_DEVICE_TABLE(usb, pegasus_ids);
static int update_eth_regs_async(pegasus_t *);
@@ -110,7 +115,9 @@ static void ctrl_callback(struct urb *urb, struct pt_regs *regs)
case -ENOENT:
break;
default:
- warn("%s: status %d", __FUNCTION__, urb->status);
+ if (netif_msg_drv(pegasus))
+ dev_err(&pegasus->intf->dev, "%s, status %d\n",
+ __FUNCTION__, urb->status);
}
pegasus->flags &= ~ETH_REGS_CHANGED;
wake_up(&pegasus->ctrl_wait);
@@ -125,7 +132,9 @@ static int get_registers(pegasus_t * pegasus, __u16 indx, __u16 size,
buffer = kmalloc(size, GFP_KERNEL);
if (!buffer) {
- warn("%s: looks like we're out of memory", __FUNCTION__);
+ if (netif_msg_drv(pegasus))
+ dev_warn(&pegasus->intf->dev, "out of memory in %s\n",
+ __FUNCTION__);
return -ENOMEM;
}
add_wait_queue(&pegasus->ctrl_wait, &wait);
@@ -152,7 +161,9 @@ static int get_registers(pegasus_t * pegasus, __u16 indx, __u16 size,
/* using ATOMIC, we'd never wake up if we slept */
if ((ret = usb_submit_urb(pegasus->ctrl_urb, GFP_ATOMIC))) {
- err("%s: BAD CTRLs %d", __FUNCTION__, ret);
+ if (netif_msg_drv(pegasus))
+ dev_err(&pegasus->intf->dev, "%s, status %d\n",
+ __FUNCTION__, ret);
goto out;
}
@@ -174,7 +185,9 @@ static int set_registers(pegasus_t * pegasus, __u16 indx, __u16 size,
buffer = kmalloc(size, GFP_KERNEL);
if (!buffer) {
- warn("%s: looks like we're out of memory", __FUNCTION__);
+ if (netif_msg_drv(pegasus))
+ dev_warn(&pegasus->intf->dev, "out of memory in %s\n",
+ __FUNCTION__);
return -ENOMEM;
}
memcpy(buffer, data, size);
@@ -202,7 +215,9 @@ static int set_registers(pegasus_t * pegasus, __u16 indx, __u16 size,
set_current_state(TASK_UNINTERRUPTIBLE);
if ((ret = usb_submit_urb(pegasus->ctrl_urb, GFP_ATOMIC))) {
- err("%s: BAD CTRL %d", __FUNCTION__, ret);
+ if (netif_msg_drv(pegasus))
+ dev_err(&pegasus->intf->dev, "%s, status %d\n",
+ __FUNCTION__, ret);
goto out;
}
@@ -222,7 +237,9 @@ static int set_register(pegasus_t * pegasus, __u16 indx, __u8 data)
tmp = kmalloc(1, GFP_KERNEL);
if (!tmp) {
- warn("%s: looks like we're out of memory", __FUNCTION__);
+ if (netif_msg_drv(pegasus))
+ dev_warn(&pegasus->intf->dev, "out of memory in %s\n",
+ __FUNCTION__);
return -ENOMEM;
}
memcpy(tmp, &data, 1);
@@ -249,7 +266,9 @@ static int set_register(pegasus_t * pegasus, __u16 indx, __u8 data)
set_current_state(TASK_UNINTERRUPTIBLE);
if ((ret = usb_submit_urb(pegasus->ctrl_urb, GFP_ATOMIC))) {
- err("%s: BAD CTRL %d", __FUNCTION__, ret);
+ if (netif_msg_drv(pegasus))
+ dev_err(&pegasus->intf->dev, "%s, status %d\n",
+ __FUNCTION__, ret);
goto out;
}
@@ -278,8 +297,9 @@ static int update_eth_regs_async(pegasus_t * pegasus)
pegasus->eth_regs, 3, ctrl_callback, pegasus);
if ((ret = usb_submit_urb(pegasus->ctrl_urb, GFP_ATOMIC)))
- err("%s: BAD CTRL %d, flgs %x", __FUNCTION__, ret,
- pegasus->flags);
+ if (netif_msg_drv(pegasus))
+ dev_err(&pegasus->intf->dev, "%s, status %d\n",
+ __FUNCTION__, ret);
return ret;
}
@@ -289,52 +309,57 @@ static int read_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 * regd)
int i;
__u8 data[4] = { phy, 0, 0, indx };
__le16 regdi;
+ int ret;
- set_register(pegasus, PhyCtrl, 0);
- set_registers(pegasus, PhyAddr, sizeof (data), data);
- set_register(pegasus, PhyCtrl, (indx | PHY_READ));
+ ret = set_register(pegasus, PhyCtrl, 0);
+ ret = set_registers(pegasus, PhyAddr, sizeof (data), data);
+ ret = set_register(pegasus, PhyCtrl, (indx | PHY_READ));
for (i = 0; i < REG_TIMEOUT; i++) {
- get_registers(pegasus, PhyCtrl, 1, data);
+ ret = get_registers(pegasus, PhyCtrl, 1, data);
if (data[0] & PHY_DONE)
break;
}
if (i < REG_TIMEOUT) {
- get_registers(pegasus, PhyData, 2, &regdi);
+ ret = get_registers(pegasus, PhyData, 2, &regdi);
*regd = le16_to_cpu(regdi);
- return 0;
+ return 1;
}
- warn("%s: failed", __FUNCTION__);
+ if (netif_msg_drv(pegasus))
+ dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__);
- return 1;
+ return 0;
}
static int mdio_read(struct net_device *dev, int phy_id, int loc)
{
pegasus_t *pegasus = (pegasus_t *) netdev_priv(dev);
- int res;
+ u16 res;
- read_mii_word(pegasus, phy_id, loc, (u16 *) & res);
- return res & 0xffff;
+ read_mii_word(pegasus, phy_id, loc, &res);
+ return (int)res;
}
static int write_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 regd)
{
int i;
__u8 data[4] = { phy, 0, 0, indx };
+ int ret;
- *(data + 1) = cpu_to_le16p(&regd);
- set_register(pegasus, PhyCtrl, 0);
- set_registers(pegasus, PhyAddr, sizeof(data), data);
- set_register(pegasus, PhyCtrl, (indx | PHY_WRITE));
+ 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));
for (i = 0; i < REG_TIMEOUT; i++) {
- get_registers(pegasus, PhyCtrl, 1, data);
+ ret = get_registers(pegasus, PhyCtrl, 1, data);
if (data[0] & PHY_DONE)
break;
}
if (i < REG_TIMEOUT)
return 0;
- warn("%s: failed", __FUNCTION__);
+ if (netif_msg_drv(pegasus))
+ dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__);
return 1;
}
@@ -350,23 +375,25 @@ static int read_eprom_word(pegasus_t * pegasus, __u8 index, __u16 * retdata)
int i;
__u8 tmp;
__le16 retdatai;
+ int ret;
- set_register(pegasus, EpromCtrl, 0);
- set_register(pegasus, EpromOffset, index);
- set_register(pegasus, EpromCtrl, EPROM_READ);
+ ret = set_register(pegasus, EpromCtrl, 0);
+ ret = set_register(pegasus, EpromOffset, index);
+ ret = set_register(pegasus, EpromCtrl, EPROM_READ);
for (i = 0; i < REG_TIMEOUT; i++) {
- get_registers(pegasus, EpromCtrl, 1, &tmp);
+ ret = get_registers(pegasus, EpromCtrl, 1, &tmp);
if (tmp & EPROM_DONE)
break;
}
if (i < REG_TIMEOUT) {
- get_registers(pegasus, EpromData, 2, &retdatai);
+ ret = get_registers(pegasus, EpromData, 2, &retdatai);
*retdata = le16_to_cpu(retdatai);
return 0;
}
- warn("%s: failed", __FUNCTION__);
+ if (netif_msg_drv(pegasus))
+ dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__);
return -1;
}
@@ -374,40 +401,44 @@ static int read_eprom_word(pegasus_t * pegasus, __u8 index, __u16 * retdata)
static inline void enable_eprom_write(pegasus_t * pegasus)
{
__u8 tmp;
+ int ret;
- get_registers(pegasus, EthCtrl2, 1, &tmp);
- set_register(pegasus, EthCtrl2, tmp | EPROM_WR_ENABLE);
+ ret = get_registers(pegasus, EthCtrl2, 1, &tmp);
+ ret = set_register(pegasus, EthCtrl2, tmp | EPROM_WR_ENABLE);
}
static inline void disable_eprom_write(pegasus_t * pegasus)
{
__u8 tmp;
+ int ret;
- get_registers(pegasus, EthCtrl2, 1, &tmp);
- set_register(pegasus, EpromCtrl, 0);
- set_register(pegasus, EthCtrl2, tmp & ~EPROM_WR_ENABLE);
+ ret = get_registers(pegasus, EthCtrl2, 1, &tmp);
+ ret = set_register(pegasus, EpromCtrl, 0);
+ ret = set_register(pegasus, EthCtrl2, tmp & ~EPROM_WR_ENABLE);
}
static int write_eprom_word(pegasus_t * pegasus, __u8 index, __u16 data)
{
int i;
__u8 tmp, d[4] = { 0x3f, 0, 0, EPROM_WRITE };
+ int ret;
- set_registers(pegasus, EpromOffset, 4, d);
+ ret = set_registers(pegasus, EpromOffset, 4, d);
enable_eprom_write(pegasus);
- set_register(pegasus, EpromOffset, index);
- set_registers(pegasus, EpromData, 2, &data);
- set_register(pegasus, EpromCtrl, EPROM_WRITE);
+ ret = set_register(pegasus, EpromOffset, index);
+ ret = set_registers(pegasus, EpromData, 2, &data);
+ ret = set_register(pegasus, EpromCtrl, EPROM_WRITE);
for (i = 0; i < REG_TIMEOUT; i++) {
- get_registers(pegasus, EpromCtrl, 1, &tmp);
+ ret = get_registers(pegasus, EpromCtrl, 1, &tmp);
if (tmp & EPROM_DONE)
break;
}
disable_eprom_write(pegasus);
if (i < REG_TIMEOUT)
return 0;
- warn("%s: failed", __FUNCTION__);
+ if (netif_msg_drv(pegasus))
+ dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__);
return -1;
}
#endif /* PEGASUS_WRITE_EEPROM */
@@ -426,9 +457,10 @@ 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);
- set_registers(pegasus, EthID, sizeof (node_id), node_id);
+ ret = set_registers(pegasus, EthID, sizeof (node_id), node_id);
memcpy(pegasus->net->dev_addr, node_id, sizeof (node_id));
}
@@ -436,19 +468,20 @@ static inline int reset_mac(pegasus_t * pegasus)
{
__u8 data = 0x8;
int i;
+ int ret;
- set_register(pegasus, EthCtrl1, data);
+ ret = set_register(pegasus, EthCtrl1, data);
for (i = 0; i < REG_TIMEOUT; i++) {
- get_registers(pegasus, EthCtrl1, 1, &data);
+ ret = get_registers(pegasus, EthCtrl1, 1, &data);
if (~data & 0x08) {
if (loopback & 1)
break;
if (mii_mode && (pegasus->features & HAS_HOME_PNA))
- set_register(pegasus, Gpio1, 0x34);
+ ret = set_register(pegasus, Gpio1, 0x34);
else
- set_register(pegasus, Gpio1, 0x26);
- set_register(pegasus, Gpio0, pegasus->features);
- set_register(pegasus, Gpio0, DEFAULT_GPIO_SET);
+ ret = set_register(pegasus, Gpio1, 0x26);
+ ret = set_register(pegasus, Gpio0, pegasus->features);
+ ret = set_register(pegasus, Gpio0, DEFAULT_GPIO_SET);
break;
}
}
@@ -457,8 +490,8 @@ static inline int reset_mac(pegasus_t * pegasus)
if (usb_dev_id[pegasus->dev_index].vendor == VENDOR_LINKSYS ||
usb_dev_id[pegasus->dev_index].vendor == VENDOR_DLINK) {
- set_register(pegasus, Gpio0, 0x24);
- set_register(pegasus, Gpio0, 0x26);
+ ret = set_register(pegasus, Gpio0, 0x24);
+ ret = set_register(pegasus, Gpio0, 0x26);
}
if (usb_dev_id[pegasus->dev_index].vendor == VENDOR_ELCON) {
__u16 auxmode;
@@ -474,6 +507,7 @@ static int enable_net_traffic(struct net_device *dev, struct usb_device *usb)
__u16 linkpart;
__u8 data[4];
pegasus_t *pegasus = netdev_priv(dev);
+ int ret;
read_mii_word(pegasus, pegasus->phy, MII_LPA, &linkpart);
data[0] = 0xc9;
@@ -487,7 +521,7 @@ static int enable_net_traffic(struct net_device *dev, struct usb_device *usb)
data[2] = (loopback & 1) ? 0x09 : 0x01;
memcpy(pegasus->eth_regs, data, sizeof (data));
- set_registers(pegasus, EthCtrl0, 3, data);
+ ret = set_registers(pegasus, EthCtrl0, 3, data);
if (usb_dev_id[pegasus->dev_index].vendor == VENDOR_LINKSYS ||
usb_dev_id[pegasus->dev_index].vendor == VENDOR_DLINK) {
@@ -550,48 +584,56 @@ static void read_bulk_callback(struct urb *urb, struct pt_regs *regs)
pegasus_t *pegasus = urb->context;
struct net_device *net;
int rx_status, count = urb->actual_length;
+ u8 *buf = urb->transfer_buffer;
__u16 pkt_len;
- if (!pegasus || !(pegasus->flags & PEGASUS_RUNNING))
+ if (!pegasus)
return;
net = pegasus->net;
- if (!netif_device_present(net))
+ if (!netif_device_present(net) || !netif_running(net))
return;
switch (urb->status) {
case 0:
break;
case -ETIMEDOUT:
- dbg("%s: reset MAC", net->name);
+ if (netif_msg_rx_err(pegasus))
+ pr_debug("%s: reset MAC\n", net->name);
pegasus->flags &= ~PEGASUS_RX_BUSY;
break;
case -EPIPE: /* stall, or disconnect from TT */
/* FIXME schedule work to clear the halt */
- warn("%s: no rx stall recovery", net->name);
+ if (netif_msg_rx_err(pegasus))
+ printk(KERN_WARNING "%s: no rx stall recovery\n",
+ net->name);
return;
case -ENOENT:
case -ECONNRESET:
case -ESHUTDOWN:
- dbg("%s: rx unlink, %d", net->name, urb->status);
+ if (netif_msg_ifdown(pegasus))
+ pr_debug("%s: rx unlink, %d\n", net->name, urb->status);
return;
default:
- dbg("%s: RX status %d", net->name, urb->status);
+ if (netif_msg_rx_err(pegasus))
+ pr_debug("%s: RX status %d\n", net->name, urb->status);
goto goon;
}
- if (!count)
+ if (!count || count < 4)
goto goon;
- rx_status = le32_to_cpu(*(__le32 *) (urb->transfer_buffer + count - 4));
- if (rx_status & 0x000e0000) {
- dbg("%s: RX packet error %x", net->name, rx_status & 0xe0000);
+ rx_status = buf[count - 2];
+ if (rx_status & 0x1e) {
+ if (netif_msg_rx_err(pegasus))
+ pr_debug("%s: RX packet error %x\n",
+ net->name, rx_status);
pegasus->stats.rx_errors++;
- if (rx_status & 0x060000)
+ if (rx_status & 0x06) // long or runt
pegasus->stats.rx_length_errors++;
- if (rx_status & 0x080000)
+ if (rx_status & 0x08)
pegasus->stats.rx_crc_errors++;
- if (rx_status & 0x100000)
+ if (rx_status & 0x10) // extra bits
pegasus->stats.rx_frame_errors++;
goto goon;
}
@@ -600,7 +642,10 @@ static void read_bulk_callback(struct urb *urb, struct pt_regs *regs)
pkt_len &= 0x0fff;
pegasus->rx_skb->data += 2;
} else {
- pkt_len = (rx_status & 0xfff) - 8;
+ pkt_len = buf[count - 3] << 8;
+ pkt_len += buf[count - 4];
+ pkt_len &= 0xfff;
+ pkt_len -= 8;
}
/*
@@ -636,7 +681,7 @@ goon:
return;
- tl_sched:
+tl_sched:
tasklet_schedule(&pegasus->rx_tl);
}
@@ -658,7 +703,9 @@ static void rx_fixup(unsigned long data)
pegasus->rx_skb = pull_skb(pegasus);
}
if (pegasus->rx_skb == NULL) {
- warn("wow, low on memory");
+ if (netif_msg_rx_err(pegasus))
+ printk(KERN_WARNING "%s: low on memory\n",
+ pegasus->net->name);
tasklet_schedule(&pegasus->rx_tl);
goto done;
}
@@ -682,25 +729,29 @@ static void write_bulk_callback(struct urb *urb, struct pt_regs *regs)
pegasus_t *pegasus = urb->context;
struct net_device *net = pegasus->net;
- if (!pegasus || !(pegasus->flags & PEGASUS_RUNNING))
+ if (!pegasus)
return;
- if (!netif_device_present(net))
+ if (!netif_device_present(net) || !netif_running(net))
return;
switch (urb->status) {
case -EPIPE:
/* FIXME schedule_work() to clear the tx halt */
netif_stop_queue(net);
- warn("%s: no tx stall recovery", net->name);
+ if (netif_msg_tx_err(pegasus))
+ printk(KERN_WARNING "%s: no tx stall recovery\n",
+ net->name);
return;
case -ENOENT:
case -ECONNRESET:
case -ESHUTDOWN:
- dbg("%s: tx unlink, %d", net->name, urb->status);
+ if (netif_msg_ifdown(pegasus))
+ pr_debug("%s: tx unlink, %d\n", net->name, urb->status);
return;
default:
- info("%s: TX status %d", net->name, urb->status);
+ if (netif_msg_tx_err(pegasus))
+ pr_info("%s: TX status %d\n", net->name, urb->status);
/* FALL THROUGH */
case 0:
break;
@@ -731,7 +782,9 @@ static void intr_callback(struct urb *urb, struct pt_regs *regs)
/* some Pegasus-I products report LOTS of data
* toggle errors... avoid log spamming
*/
- pr_debug("%s: intr status %d\n", net->name, urb->status);
+ if (netif_msg_timer(pegasus))
+ pr_debug("%s: intr status %d\n", net->name,
+ urb->status);
}
if (urb->actual_length >= 6) {
@@ -763,7 +816,7 @@ static void intr_callback(struct urb *urb, struct pt_regs *regs)
}
status = usb_submit_urb(urb, SLAB_ATOMIC);
- if (status)
+ if (status && netif_msg_timer(pegasus))
printk(KERN_ERR "%s: can't resubmit interrupt urb, %d\n",
net->name, status);
}
@@ -771,7 +824,8 @@ static void intr_callback(struct urb *urb, struct pt_regs *regs)
static void pegasus_tx_timeout(struct net_device *net)
{
pegasus_t *pegasus = netdev_priv(net);
- printk(KERN_WARNING "%s: tx timeout\n", net->name);
+ if (netif_msg_timer(pegasus))
+ printk(KERN_WARNING "%s: tx timeout\n", net->name);
pegasus->tx_urb->transfer_flags |= URB_ASYNC_UNLINK;
usb_unlink_urb(pegasus->tx_urb);
pegasus->stats.tx_errors++;
@@ -793,7 +847,9 @@ static int pegasus_start_xmit(struct sk_buff *skb, struct net_device *net)
pegasus->tx_buff, count,
write_bulk_callback, pegasus);
if ((res = usb_submit_urb(pegasus->tx_urb, GFP_ATOMIC))) {
- warn("failed tx_urb %d", res);
+ if (netif_msg_tx_err(pegasus))
+ printk(KERN_WARNING "%s: fail tx, %d\n",
+ net->name, res);
switch (res) {
case -EPIPE: /* stall, or disconnect from TT */
/* cleanup should already have been scheduled */
@@ -822,8 +878,9 @@ 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;
- set_registers(pegasus, EthCtrl0, 2, &tmp);
+ ret = set_registers(pegasus, EthCtrl0, 2, &tmp);
}
static inline void get_interrupt_interval(pegasus_t * pegasus)
@@ -832,8 +889,10 @@ static inline void get_interrupt_interval(pegasus_t * pegasus)
read_eprom_word(pegasus, 4, (__u16 *) data);
if (data[1] < 0x80) {
- info("intr interval will be changed from %ums to %ums",
- data[1], 0x80);
+ if (netif_msg_timer(pegasus))
+ dev_info(&pegasus->intf->dev,
+ "intr interval changed from %ums to %ums\n",
+ data[1], 0x80);
data[1] = 0x80;
#ifdef PEGASUS_WRITE_EEPROM
write_eprom_word(pegasus, 4, *(__u16 *) data);
@@ -845,14 +904,14 @@ static inline void get_interrupt_interval(pegasus_t * pegasus)
static void set_carrier(struct net_device *net)
{
pegasus_t *pegasus = netdev_priv(net);
- short tmp;
+ u16 tmp;
- read_mii_word(pegasus, pegasus->phy, MII_BMSR, &tmp);
+ if (read_mii_word(pegasus, pegasus->phy, MII_BMSR, &tmp))
+ return;
if (tmp & BMSR_LSTATUS)
netif_carrier_on(net);
else
netif_carrier_off(net);
-
}
static void free_all_urbs(pegasus_t * pegasus)
@@ -912,24 +971,32 @@ static int pegasus_open(struct net_device *net)
if (!pegasus->rx_skb)
return -ENOMEM;
- set_registers(pegasus, EthID, 6, net->dev_addr);
+ res = set_registers(pegasus, EthID, 6, net->dev_addr);
usb_fill_bulk_urb(pegasus->rx_urb, pegasus->usb,
usb_rcvbulkpipe(pegasus->usb, 1),
pegasus->rx_skb->data, PEGASUS_MTU + 8,
read_bulk_callback, pegasus);
- if ((res = usb_submit_urb(pegasus->rx_urb, GFP_KERNEL)))
- warn("%s: failed rx_urb %d", __FUNCTION__, res);
+ if ((res = usb_submit_urb(pegasus->rx_urb, GFP_KERNEL))) {
+ if (netif_msg_ifup(pegasus))
+ pr_debug("%s: failed rx_urb, %d", net->name, res);
+ goto exit;
+ }
+
usb_fill_int_urb(pegasus->intr_urb, pegasus->usb,
usb_rcvintpipe(pegasus->usb, 3),
pegasus->intr_buff, sizeof (pegasus->intr_buff),
intr_callback, pegasus, pegasus->intr_interval);
- if ((res = usb_submit_urb(pegasus->intr_urb, GFP_KERNEL)))
- warn("%s: failed intr_urb %d", __FUNCTION__, res);
- netif_start_queue(net);
- pegasus->flags |= PEGASUS_RUNNING;
+ if ((res = usb_submit_urb(pegasus->intr_urb, GFP_KERNEL))) {
+ if (netif_msg_ifup(pegasus))
+ pr_debug("%s: failed intr_urb, %d\n", net->name, res);
+ usb_kill_urb(pegasus->rx_urb);
+ goto exit;
+ }
if ((res = enable_net_traffic(net, pegasus->usb))) {
- err("can't enable_net_traffic() - %d", res);
+ if (netif_msg_ifup(pegasus))
+ pr_debug("%s: can't enable_net_traffic() - %d\n",
+ net->name, res);
res = -EIO;
usb_kill_urb(pegasus->rx_urb);
usb_kill_urb(pegasus->intr_urb);
@@ -937,6 +1004,9 @@ static int pegasus_open(struct net_device *net)
goto exit;
}
set_carrier(net);
+ netif_start_queue(net);
+ if (netif_msg_ifup(pegasus))
+ pr_debug("%s: open\n", net->name);
res = 0;
exit:
return res;
@@ -946,7 +1016,6 @@ static int pegasus_close(struct net_device *net)
{
pegasus_t *pegasus = netdev_priv(net);
- pegasus->flags &= ~PEGASUS_RUNNING;
netif_stop_queue(net);
if (!(pegasus->flags & PEGASUS_UNPLUG))
disable_net_traffic(pegasus);
@@ -956,7 +1025,8 @@ static int pegasus_close(struct net_device *net)
return 0;
}
-void pegasus_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+static void pegasus_get_drvinfo(struct net_device *dev,
+ struct ethtool_drvinfo *info)
{
pegasus_t *pegasus = netdev_priv(dev);
strncpy(info->driver, driver_name, sizeof (info->driver) - 1);
@@ -989,6 +1059,7 @@ pegasus_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
reg78 |= 0x80;
if (wol->wolopts & WAKE_PHY)
reg78 |= 0x40;
+ /* FIXME this 0x10 bit still needs to get set in the chip... */
if (wol->wolopts)
pegasus->eth_regs[0] |= 0x10;
else
@@ -997,8 +1068,7 @@ pegasus_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
return set_register(pegasus, WakeupControl, reg78);
}
-static inline void
-pegasus_reset_wol(struct net_device *dev)
+static inline void pegasus_reset_wol(struct net_device *dev)
{
struct ethtool_wolinfo wol;
@@ -1009,10 +1079,17 @@ pegasus_reset_wol(struct net_device *dev)
static int
pegasus_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
{
- pegasus_t *pegasus = netdev_priv(dev);
+ pegasus_t *pegasus;
+
+ if (in_atomic())
+ return 0;
+
+ pegasus = netdev_priv(dev);
mii_ethtool_gset(&pegasus->mii, ecmd);
+
return 0;
}
+
static int
pegasus_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
{
@@ -1035,13 +1112,13 @@ static u32 pegasus_get_link(struct net_device *dev)
static u32 pegasus_get_msglevel(struct net_device *dev)
{
pegasus_t *pegasus = netdev_priv(dev);
- return pegasus->msg_level;
+ return pegasus->msg_enable;
}
static void pegasus_set_msglevel(struct net_device *dev, u32 v)
{
pegasus_t *pegasus = netdev_priv(dev);
- pegasus->msg_level = v;
+ pegasus->msg_enable = v;
}
static struct ethtool_ops ops = {
@@ -1087,12 +1164,14 @@ static void pegasus_set_multicast(struct net_device *net)
if (net->flags & IFF_PROMISC) {
pegasus->eth_regs[EthCtrl2] |= RX_PROMISCUOUS;
- pr_info("%s: Promiscuous mode enabled.\n", net->name);
+ if (netif_msg_link(pegasus))
+ pr_info("%s: Promiscuous mode enabled.\n", net->name);
} else if ((net->mc_count > multicast_filter_limit) ||
(net->flags & IFF_ALLMULTI)) {
pegasus->eth_regs[EthCtrl0] |= RX_MULTICAST;
pegasus->eth_regs[EthCtrl2] &= ~RX_PROMISCUOUS;
- pr_info("%s: set allmulti\n", net->name);
+ if (netif_msg_link(pegasus))
+ pr_info("%s: set allmulti\n", net->name);
} else {
pegasus->eth_regs[EthCtrl0] &= ~RX_MULTICAST;
pegasus->eth_regs[EthCtrl2] &= ~RX_PROMISCUOUS;
@@ -1121,17 +1200,18 @@ static __u8 mii_phy_probe(pegasus_t * pegasus)
static inline void setup_pegasus_II(pegasus_t * pegasus)
{
__u8 data = 0xa5;
+ int ret;
- set_register(pegasus, Reg1d, 0);
- set_register(pegasus, Reg7b, 1);
+ ret = set_register(pegasus, Reg1d, 0);
+ ret = set_register(pegasus, Reg7b, 1);
mdelay(100);
if ((pegasus->features & HAS_HOME_PNA) && mii_mode)
- set_register(pegasus, Reg7b, 0);
+ ret = set_register(pegasus, Reg7b, 0);
else
- set_register(pegasus, Reg7b, 2);
+ ret = set_register(pegasus, Reg7b, 2);
- set_register(pegasus, 0x83, data);
- get_registers(pegasus, 0x83, 1, &data);
+ ret = set_register(pegasus, 0x83, data);
+ ret = get_registers(pegasus, 0x83, 1, &data);
if (data == 0xa5) {
pegasus->chip = 0x8513;
@@ -1139,14 +1219,28 @@ static inline void setup_pegasus_II(pegasus_t * pegasus)
pegasus->chip = 0;
}
- set_register(pegasus, 0x80, 0xc0);
- set_register(pegasus, 0x83, 0xff);
- set_register(pegasus, 0x84, 0x01);
+ ret = set_register(pegasus, 0x80, 0xc0);
+ ret = set_register(pegasus, 0x83, 0xff);
+ ret = set_register(pegasus, 0x84, 0x01);
if (pegasus->features & HAS_HOME_PNA && mii_mode)
- set_register(pegasus, Reg81, 6);
+ ret = set_register(pegasus, Reg81, 6);
else
- set_register(pegasus, Reg81, 2);
+ ret = set_register(pegasus, Reg81, 2);
+}
+
+
+static struct workqueue_struct *pegasus_workqueue = NULL;
+#define CARRIER_CHECK_DELAY (2 * HZ)
+
+static void check_carrier(void *data)
+{
+ pegasus_t *pegasus = data;
+ set_carrier(pegasus->net);
+ if (!(pegasus->flags & PEGASUS_UNPLUG)) {
+ queue_delayed_work(pegasus_workqueue, &pegasus->carrier_check,
+ CARRIER_CHECK_DELAY);
+ }
}
static int pegasus_probe(struct usb_interface *intf,
@@ -1161,7 +1255,7 @@ static int pegasus_probe(struct usb_interface *intf,
usb_get_dev(dev);
net = alloc_etherdev(sizeof(struct pegasus));
if (!net) {
- err("out of memory allocating device structure");
+ dev_err(&intf->dev, "can't allocate %s\n", "device");
goto out;
}
@@ -1170,11 +1264,16 @@ static int pegasus_probe(struct usb_interface *intf,
pegasus->dev_index = dev_index;
init_waitqueue_head(&pegasus->ctrl_wait);
- if (!alloc_urbs(pegasus))
+ if (!alloc_urbs(pegasus)) {
+ dev_err(&intf->dev, "can't allocate %s\n", "urbs");
goto out1;
+ }
tasklet_init(&pegasus->rx_tl, rx_fixup, (unsigned long) pegasus);
+ INIT_WORK(&pegasus->carrier_check, check_carrier, pegasus);
+
+ pegasus->intf = intf;
pegasus->usb = dev;
pegasus->net = net;
SET_MODULE_OWNER(net);
@@ -1193,6 +1292,8 @@ static int pegasus_probe(struct usb_interface *intf,
pegasus->mii.phy_id_mask = 0x1f;
pegasus->mii.reg_num_mask = 0x1f;
spin_lock_init(&pegasus->rx_pool_lock);
+ pegasus->msg_enable = netif_msg_init (msg_level, NETIF_MSG_DRV
+ | NETIF_MSG_PROBE | NETIF_MSG_LINK);
pegasus->features = usb_dev_id[dev_index].private;
get_interrupt_interval(pegasus);
@@ -1212,13 +1313,22 @@ static int pegasus_probe(struct usb_interface *intf,
dev_warn(&intf->dev, "can't locate MII phy, using default\n");
pegasus->phy = 1;
}
+ pegasus->mii.phy_id = pegasus->phy;
usb_set_intfdata(intf, pegasus);
SET_NETDEV_DEV(net, &intf->dev);
pegasus_reset_wol(net);
res = register_netdev(net);
if (res)
goto out3;
- pr_info("%s: %s\n", net->name, usb_dev_id[dev_index].name);
+ queue_delayed_work(pegasus_workqueue, &pegasus->carrier_check,
+ CARRIER_CHECK_DELAY);
+
+ dev_info(&intf->dev, "%s, %s, %02x:%02x:%02x:%02x:%02x:%02x\n",
+ net->name,
+ usb_dev_id[dev_index].name,
+ net->dev_addr [0], net->dev_addr [1],
+ net->dev_addr [2], net->dev_addr [3],
+ net->dev_addr [4], net->dev_addr [5]);
return 0;
out3:
@@ -1239,11 +1349,12 @@ static void pegasus_disconnect(struct usb_interface *intf)
usb_set_intfdata(intf, NULL);
if (!pegasus) {
- warn("unregistering non-existant device");
+ dev_dbg(&intf->dev, "unregistering non-bound device?\n");
return;
}
pegasus->flags |= PEGASUS_UNPLUG;
+ cancel_delayed_work(&pegasus->carrier_check);
unregister_netdev(pegasus->net);
usb_put_dev(interface_to_usbdev(intf));
free_all_urbs(pegasus);
@@ -1253,7 +1364,7 @@ static void pegasus_disconnect(struct usb_interface *intf)
free_netdev(pegasus->net);
}
-static int pegasus_suspend (struct usb_interface *intf, u32 state)
+static int pegasus_suspend (struct usb_interface *intf, pm_message_t state)
{
struct pegasus *pegasus = usb_get_intfdata(intf);
@@ -1281,11 +1392,15 @@ static struct usb_driver pegasus_driver = {
static int __init pegasus_init(void)
{
pr_info("%s: %s, " DRIVER_DESC "\n", driver_name, DRIVER_VERSION);
+ pegasus_workqueue = create_singlethread_workqueue("pegasus");
+ if (!pegasus_workqueue)
+ return -ENOMEM;
return usb_register(&pegasus_driver);
}
static void __exit pegasus_exit(void)
{
+ destroy_workqueue(pegasus_workqueue);
usb_deregister(&pegasus_driver);
}
diff --git a/drivers/usb/net/pegasus.h b/drivers/usb/net/pegasus.h
index f043fc382dcc4..13ccedef5c7e0 100644
--- a/drivers/usb/net/pegasus.h
+++ b/drivers/usb/net/pegasus.h
@@ -29,7 +29,6 @@
#define DEFAULT_GPIO_SET 0x26
#define PEGASUS_PRESENT 0x00000001
-#define PEGASUS_RUNNING 0x00000002
#define PEGASUS_TX_BUSY 0x00000004
#define PEGASUS_RX_BUSY 0x00000008
#define CTRL_URB_RUNNING 0x00000010
@@ -86,16 +85,18 @@ enum pegasus_registers {
typedef struct pegasus {
struct usb_device *usb;
+ struct usb_interface *intf;
struct net_device *net;
struct net_device_stats stats;
struct mii_if_info mii;
unsigned flags;
unsigned features;
- u32 msg_level;
+ u32 msg_enable;
u32 wolopts;
int dev_index;
int intr_interval;
struct tasklet_struct rx_tl;
+ struct work_struct carrier_check;
struct urb *ctrl_urb, *rx_urb, *tx_urb, *intr_urb;
struct sk_buff *rx_pool[RX_SKBS];
struct sk_buff *rx_skb;
diff --git a/drivers/usb/net/rtl8150.c b/drivers/usb/net/rtl8150.c
index 2ecba51582b57..8fb223385f2fb 100644
--- a/drivers/usb/net/rtl8150.c
+++ b/drivers/usb/net/rtl8150.c
@@ -195,14 +195,14 @@ static int get_registers(rtl8150_t * dev, u16 indx, u16 size, void *data)
{
return usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
RTL8150_REQ_GET_REGS, RTL8150_REQT_READ,
- indx, 0, data, size, HZ / 2);
+ indx, 0, data, size, 500);
}
static int set_registers(rtl8150_t * dev, u16 indx, u16 size, void *data)
{
return usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
RTL8150_REQ_SET_REGS, RTL8150_REQT_WRITE,
- indx, 0, data, size, HZ / 2);
+ indx, 0, data, size, 500);
}
static void ctrl_callback(struct urb *urb, struct pt_regs *regs)
diff --git a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c
index 9c8d8c25d60c0..dd8b4456ea35e 100644
--- a/drivers/usb/net/usbnet.c
+++ b/drivers/usb/net/usbnet.c
@@ -2,7 +2,8 @@
* USB Networking Links
* Copyright (C) 2000-2003 by David Brownell <dbrownell@users.sourceforge.net>
* Copyright (C) 2002 Pavel Machek <pavel@ucw.cz>
- * Copyright (C) 2003 David Hollis <dhollis@davehollis.com>
+ * Copyright (C) 2003-2005 David Hollis <dhollis@davehollis.com>
+ * Copyright (C) 2005 Phil Chang <pchang23@sbcglobal.net>
* Copyright (c) 2002-2003 TiVo Inc.
*
* This program is free software; you can redistribute it and/or modify
@@ -109,6 +110,7 @@
* (Neil Bortnak)
* 03-nov-2004 Trivial patch for KC2190 (KC-190) chip. (Jonathan McDowell)
*
+ * 01-feb-2005 AX88772 support (Phil Chang & Dave Hollis)
*-------------------------------------------------------------------------*/
// #define DEBUG // error path messages, extra info
@@ -164,8 +166,7 @@
#define THROTTLE_JIFFIES (HZ/8)
// for vendor-specific control operations
-#define CONTROL_TIMEOUT_MS (500) /* msec */
-#define CONTROL_TIMEOUT_JIFFIES ((CONTROL_TIMEOUT_MS * HZ)/1000)
+#define CONTROL_TIMEOUT_MS 500
// between wakeups
#define UNLINK_TIMEOUT_MS 3
@@ -184,13 +185,14 @@ struct usbnet {
// i/o info: pipes etc
unsigned in, out;
+ struct usb_host_endpoint *status;
unsigned maxpacket;
struct timer_list delay;
// protocol/interface state
struct net_device *net;
struct net_device_stats stats;
- int msg_level;
+ int msg_enable;
unsigned long data [5];
struct mii_if_info mii;
@@ -199,6 +201,7 @@ struct usbnet {
struct sk_buff_head rxq;
struct sk_buff_head txq;
struct sk_buff_head done;
+ struct urb *interrupt;
struct tasklet_struct bh;
struct work_struct kevent;
@@ -206,6 +209,7 @@ struct usbnet {
# define EVENT_TX_HALT 0
# define EVENT_RX_HALT 1
# define EVENT_RX_MEMORY 2
+# define EVENT_STS_SPLIT 3
};
// device-specific info used by the driver
@@ -222,6 +226,8 @@ struct driver_info {
#define FLAG_NO_SETINT 0x0010 /* device can't set_interface() */
#define FLAG_ETHER 0x0020 /* maybe use "eth%d" names */
+#define FLAG_FRAMING_AX 0x0040 /* AX88772/178 packets */
+
/* init device ... can sleep, or cause probe() failure */
int (*bind)(struct usbnet *, struct usb_interface *);
@@ -234,6 +240,9 @@ struct driver_info {
/* see if peer is connected ... can sleep */
int (*check_connect)(struct usbnet *);
+ /* for status polling */
+ void (*status)(struct usbnet *, struct urb *);
+
/* fixup rx packet (strip framing) */
int (*rx_fixup)(struct usbnet *dev, struct sk_buff *skb);
@@ -269,13 +278,10 @@ struct skb_data { // skb->cb is one of these
static const char driver_name [] = "usbnet";
/* use ethtool to change the level for any given device */
-static int msg_level = 1;
+static int msg_level = -1;
module_param (msg_level, int, 0);
-MODULE_PARM_DESC (msg_level, "Initial message level (default = 1)");
-
+MODULE_PARM_DESC (msg_level, "Override default message level");
-#define RUN_CONTEXT (in_irq () ? "in_irq" \
- : (in_interrupt () ? "in_interrupt" : "can sleep"))
#ifdef DEBUG
#define devdbg(usbnet, fmt, arg...) \
@@ -290,9 +296,7 @@ MODULE_PARM_DESC (msg_level, "Initial message level (default = 1)");
printk(KERN_WARNING "%s: " fmt "\n" , (usbnet)->net->name , ## arg)
#define devinfo(usbnet, fmt, arg...) \
- do { if ((usbnet)->msg_level >= 1) \
printk(KERN_INFO "%s: " fmt "\n" , (usbnet)->net->name , ## arg); \
- } while (0)
/*-------------------------------------------------------------------------*/
@@ -312,38 +316,52 @@ static int
get_endpoints (struct usbnet *dev, struct usb_interface *intf)
{
int tmp;
- struct usb_host_interface *alt;
- struct usb_host_endpoint *in, *out;
+ struct usb_host_interface *alt = NULL;
+ struct usb_host_endpoint *in = NULL, *out = NULL;
+ struct usb_host_endpoint *status = NULL;
for (tmp = 0; tmp < intf->num_altsetting; tmp++) {
unsigned ep;
- in = out = NULL;
+ in = out = status = NULL;
alt = intf->altsetting + tmp;
/* take the first altsetting with in-bulk + out-bulk;
+ * remember any status endpoint, just in case;
* ignore other endpoints and altsetttings.
*/
for (ep = 0; ep < alt->desc.bNumEndpoints; ep++) {
struct usb_host_endpoint *e;
+ int intr = 0;
e = alt->endpoint + ep;
- if (e->desc.bmAttributes != USB_ENDPOINT_XFER_BULK)
+ switch (e->desc.bmAttributes) {
+ case USB_ENDPOINT_XFER_INT:
+ if (!(e->desc.bEndpointAddress & USB_DIR_IN))
+ continue;
+ intr = 1;
+ /* FALLTHROUGH */
+ case USB_ENDPOINT_XFER_BULK:
+ break;
+ default:
continue;
+ }
if (e->desc.bEndpointAddress & USB_DIR_IN) {
- if (!in)
+ if (!intr && !in)
in = e;
+ else if (intr && !status)
+ status = e;
} else {
if (!out)
out = e;
}
- if (in && out)
- goto found;
}
+ if (in && out)
+ break;
}
- return -EINVAL;
+ if (!alt || !in || !out)
+ return -EINVAL;
-found:
if (alt->desc.bAlternateSetting != 0
|| !(dev->driver_info->flags & FLAG_NO_SETINT)) {
tmp = usb_set_interface (dev->udev, alt->desc.bInterfaceNumber,
@@ -356,9 +374,48 @@ found:
in->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
dev->out = usb_sndbulkpipe (dev->udev,
out->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
+ dev->status = status;
return 0;
}
+static void intr_complete (struct urb *urb, struct pt_regs *regs);
+
+static int init_status (struct usbnet *dev, struct usb_interface *intf)
+{
+ char *buf = NULL;
+ unsigned pipe = 0;
+ unsigned maxp;
+ unsigned period;
+
+ if (!dev->driver_info->status)
+ return 0;
+
+ pipe = usb_rcvintpipe (dev->udev,
+ dev->status->desc.bEndpointAddress
+ & USB_ENDPOINT_NUMBER_MASK);
+ maxp = usb_maxpacket (dev->udev, pipe, 0);
+
+ /* avoid 1 msec chatter: min 8 msec poll rate */
+ period = max ((int) dev->status->desc.bInterval,
+ (dev->udev->speed == USB_SPEED_HIGH) ? 7 : 3);
+
+ buf = kmalloc (maxp, SLAB_KERNEL);
+ if (buf) {
+ dev->interrupt = usb_alloc_urb (0, SLAB_KERNEL);
+ if (!dev->interrupt) {
+ kfree (buf);
+ return -ENOMEM;
+ } else {
+ usb_fill_int_urb(dev->interrupt, dev->udev, pipe,
+ buf, maxp, intr_complete, dev, period);
+ dev_dbg(&intf->dev,
+ "status ep%din, %d bytes period %d\n",
+ usb_pipeendpoint(pipe), maxp, period);
+ }
+ }
+ return 0;
+}
+
static void skb_return (struct usbnet *dev, struct sk_buff *skb)
{
int status;
@@ -368,13 +425,12 @@ static void skb_return (struct usbnet *dev, struct sk_buff *skb)
dev->stats.rx_packets++;
dev->stats.rx_bytes += skb->len;
-#ifdef VERBOSE
- devdbg (dev, "< rx, len %d, type 0x%x",
- skb->len + sizeof (struct ethhdr), skb->protocol);
-#endif
+ if (netif_msg_rx_status (dev))
+ devdbg (dev, "< rx, len %d, type 0x%x",
+ skb->len + sizeof (struct ethhdr), skb->protocol);
memset (skb->cb, 0, sizeof (struct skb_data));
status = netif_rx (skb);
- if (status != NET_RX_SUCCESS)
+ if (status != NET_RX_SUCCESS && netif_msg_rx_err (dev))
devdbg (dev, "netif_rx status %d", status);
}
@@ -435,6 +491,8 @@ static const struct driver_info an2720_info = {
#define AX_CMD_SET_HW_MII 0x0a
#define AX_CMD_READ_EEPROM 0x0b
#define AX_CMD_WRITE_EEPROM 0x0c
+#define AX_CMD_WRITE_ENABLE 0x0d
+#define AX_CMD_WRITE_DISABLE 0x0e
#define AX_CMD_WRITE_RX_CTL 0x10
#define AX_CMD_READ_IPG012 0x11
#define AX_CMD_WRITE_IPG0 0x12
@@ -447,6 +505,10 @@ static const struct driver_info an2720_info = {
#define AX_CMD_READ_MONITOR_MODE 0x1c
#define AX_CMD_WRITE_MONITOR_MODE 0x1d
#define AX_CMD_WRITE_GPIOS 0x1f
+#define AX_CMD_SW_RESET 0x20
+#define AX_CMD_SW_PHY_STATUS 0x21
+#define AX_CMD_SW_PHY_SELECT 0x22
+#define AX88772_CMD_READ_NODE_ID 0x13
#define AX_MONITOR_MODE 0x01
#define AX_MONITOR_LINK 0x02
@@ -458,6 +520,23 @@ static const struct driver_info an2720_info = {
#define AX_INTERRUPT_BUFSIZE 8
+#define AX_EEPROM_LEN 0x40
+
+#define AX_SWRESET_CLEAR 0x00
+#define AX_SWRESET_RR 0x01
+#define AX_SWRESET_RT 0x02
+#define AX_SWRESET_PRTE 0x04
+#define AX_SWRESET_PRL 0x08
+#define AX_SWRESET_BZ 0x10
+#define AX_SWRESET_IPRL 0x20
+#define AX_SWRESET_IPPD 0x40
+
+#define AX88772_IPG0_DEFAULT 0x15
+#define AX88772_IPG1_DEFAULT 0x0c
+#define AX88772_IPG2_DEFAULT 0x12
+
+#define AX_EEPROM_MAGIC 0xdeadbeef
+
/* This structure cannot exceed sizeof(unsigned long [5]) AKA 20 bytes */
struct ax8817x_data {
u8 multi_filter[AX_MCAST_FILTER_SIZE];
@@ -477,7 +556,7 @@ static int ax8817x_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
index,
data,
size,
- CONTROL_TIMEOUT_JIFFIES);
+ CONTROL_TIMEOUT_MS);
}
static int ax8817x_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
@@ -492,7 +571,7 @@ static int ax8817x_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
index,
data,
size,
- CONTROL_TIMEOUT_JIFFIES);
+ CONTROL_TIMEOUT_MS);
}
static void ax8817x_async_cmd_callback(struct urb *urb, struct pt_regs *regs)
@@ -514,18 +593,16 @@ static void ax8817x_interrupt_complete(struct urb *urb, struct pt_regs *regs)
int link;
if (urb->status < 0) {
- printk(KERN_DEBUG "ax8817x_interrupt_complete() failed with %d",
+ devdbg(dev,"ax8817x_interrupt_complete() failed with %d",
urb->status);
} else {
- if (data->int_buf[5] == 0x90) {
- link = data->int_buf[2] & 0x01;
- if (netif_carrier_ok(dev->net) != link) {
- if (link)
- netif_carrier_on(dev->net);
- else
- netif_carrier_off(dev->net);
- devdbg(dev, "ax8817x - Link Status is: %d", link);
- }
+ link = data->int_buf[2] & 0x01;
+ if (netif_carrier_ok(dev->net) != link) {
+ if (link)
+ netif_carrier_on(dev->net);
+ else
+ netif_carrier_off(dev->net);
+ devdbg(dev, "ax8817x - Link Status is: %d", link);
}
usb_submit_urb(data->int_urb, GFP_ATOMIC);
}
@@ -674,6 +751,11 @@ static int ax8817x_set_wol(struct net_device *net, struct ethtool_wolinfo *wolin
return 0;
}
+static int ax8817x_get_eeprom_len(struct net_device *net)
+{
+ return AX_EEPROM_LEN;
+}
+
static int ax8817x_get_eeprom(struct net_device *net,
struct ethtool_eeprom *eeprom, u8 *data)
{
@@ -687,13 +769,15 @@ static int ax8817x_get_eeprom(struct net_device *net,
if (eeprom->len % 2)
return -EINVAL;
+ eeprom->magic = AX_EEPROM_MAGIC;
+
/* ax8817x returns 2 bytes from eeprom on read */
for (i=0; i < eeprom->len / 2; i++) {
if (ax8817x_read_cmd(dev, AX_CMD_READ_EEPROM,
eeprom->offset + i, 0, 2, &ebuf[i]) < 0)
return -EINVAL;
}
- return i * 2;
+ return 0;
}
static void ax8817x_get_drvinfo (struct net_device *net,
@@ -728,6 +812,7 @@ static struct ethtool_ops ax8817x_ethtool_ops = {
.set_msglevel = usbnet_set_msglevel,
.get_wol = ax8817x_get_wol,
.set_wol = ax8817x_set_wol,
+ .get_eeprom_len = ax8817x_get_eeprom_len,
.get_eeprom = ax8817x_get_eeprom,
.get_settings = ax8817x_get_settings,
.set_settings = ax8817x_set_settings,
@@ -735,27 +820,26 @@ static struct ethtool_ops ax8817x_ethtool_ops = {
static int ax8817x_bind(struct usbnet *dev, struct usb_interface *intf)
{
- int ret;
- u8 buf[6];
+ int ret = 0;
+ void *buf;
int i;
unsigned long gpio_bits = dev->driver_info->data;
struct ax8817x_data *data = (struct ax8817x_data *)dev->data;
- dev->in = usb_rcvbulkpipe(dev->udev, 3);
- dev->out = usb_sndbulkpipe(dev->udev, 2);
+ get_endpoints(dev,intf);
- // allocate irq urb
if ((data->int_urb = usb_alloc_urb (0, GFP_KERNEL)) == NULL) {
dbg ("%s: cannot allocate interrupt URB",
dev->net->name);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto out1;
}
if ((data->int_buf = kmalloc(AX_INTERRUPT_BUFSIZE, GFP_KERNEL)) == NULL) {
dbg ("%s: cannot allocate memory for interrupt buffer",
dev->net->name);
- usb_free_urb(data->int_urb);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto out1;
}
memset(data->int_buf, 0, AX_INTERRUPT_BUFSIZE);
@@ -765,36 +849,43 @@ static int ax8817x_bind(struct usbnet *dev, struct usb_interface *intf)
ax8817x_interrupt_complete, dev,
dev->udev->speed == USB_SPEED_HIGH ? 8 : 100);
+ buf = kmalloc(ETH_ALEN, GFP_KERNEL);
+ if(!buf) {
+ ret = -ENOMEM;
+ goto out2;
+ }
+
/* Toggle the GPIOs in a manufacturer/model specific way */
for (i = 2; i >= 0; i--) {
if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS,
(gpio_bits >> (i * 8)) & 0xff, 0, 0,
buf)) < 0)
- return ret;
+ goto out3;
msleep(5);
}
if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL, 0x80, 0, 0, buf)) < 0) {
dbg("send AX_CMD_WRITE_RX_CTL failed: %d", ret);
- return ret;
+ goto out3;
}
/* Get the MAC address */
memset(buf, 0, ETH_ALEN);
if ((ret = ax8817x_read_cmd(dev, AX_CMD_READ_NODE_ID, 0, 0, 6, buf)) < 0) {
dbg("read AX_CMD_READ_NODE_ID failed: %d", ret);
- return ret;
+ goto out3;
}
memcpy(dev->net->dev_addr, buf, ETH_ALEN);
/* Get the PHY id */
if ((ret = ax8817x_read_cmd(dev, AX_CMD_READ_PHY_ID, 0, 0, 2, buf)) < 0) {
dbg("error on read AX_CMD_READ_PHY_ID: %02x", ret);
- return ret;
+ goto out3;
} else if (ret < 2) {
/* this should always return 2 bytes */
dbg("AX_CMD_READ_PHY_ID returned less than 2 bytes: ret=%02x", ret);
- return -EIO;
+ ret = -EIO;
+ goto out3;
}
/* Initialize MII structure */
@@ -803,7 +894,7 @@ static int ax8817x_bind(struct usbnet *dev, struct usb_interface *intf)
dev->mii.mdio_write = ax8817x_mdio_write;
dev->mii.phy_id_mask = 0x3f;
dev->mii.reg_num_mask = 0x1f;
- dev->mii.phy_id = buf[1];
+ dev->mii.phy_id = *((u8 *)buf + 1);
dev->net->set_multicast_list = ax8817x_set_multicast;
dev->net->ethtool_ops = &ax8817x_ethtool_ops;
@@ -816,11 +907,17 @@ static int ax8817x_bind(struct usbnet *dev, struct usb_interface *intf)
if((ret = usb_submit_urb(data->int_urb, GFP_KERNEL)) < 0) {
dbg("Failed to submit interrupt URB: %02x", ret);
- usb_free_urb(data->int_urb);
- return ret;
+ goto out2;
}
return 0;
+out3:
+ kfree(buf);
+out2:
+ kfree(data->int_buf);
+out1:
+ usb_free_urb(data->int_urb);
+ return ret;
}
static void ax8817x_unbind(struct usbnet *dev, struct usb_interface *intf)
@@ -832,6 +929,290 @@ static void ax8817x_unbind(struct usbnet *dev, struct usb_interface *intf)
kfree(data->int_buf);
}
+static struct ethtool_ops ax88772_ethtool_ops = {
+ .get_drvinfo = ax8817x_get_drvinfo,
+ .get_link = ethtool_op_get_link,
+ .get_msglevel = usbnet_get_msglevel,
+ .set_msglevel = usbnet_set_msglevel,
+ .get_wol = ax8817x_get_wol,
+ .set_wol = ax8817x_set_wol,
+ .get_eeprom_len = ax8817x_get_eeprom_len,
+ .get_eeprom = ax8817x_get_eeprom,
+ .get_settings = ax8817x_get_settings,
+ .set_settings = ax8817x_set_settings,
+};
+
+static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
+{
+ int ret;
+ void *buf;
+ struct ax8817x_data *data = (struct ax8817x_data *)dev->data;
+
+ get_endpoints(dev,intf);
+
+ if ((data->int_urb = usb_alloc_urb (0, GFP_KERNEL)) == 0) {
+ dbg ("Cannot allocate interrupt URB");
+ ret = -ENOMEM;
+ goto out1;
+ }
+
+ if ((data->int_buf = kmalloc(AX_INTERRUPT_BUFSIZE, GFP_KERNEL)) == NULL) {
+ dbg ("Cannot allocate memory for interrupt buffer");
+ ret = -ENOMEM;
+ goto out1;
+ }
+ memset(data->int_buf, 0, AX_INTERRUPT_BUFSIZE);
+
+ usb_fill_int_urb (data->int_urb, dev->udev,
+ usb_rcvintpipe (dev->udev, 1),
+ data->int_buf, AX_INTERRUPT_BUFSIZE,
+ ax8817x_interrupt_complete, dev,
+ dev->udev->speed == USB_SPEED_HIGH ? 8 : 100);
+
+ buf = kmalloc(6, GFP_KERNEL);
+ if(!buf) {
+ dbg ("Cannot allocate memory for buffer");
+ ret = -ENOMEM;
+ goto out2;
+ }
+
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS,
+ 0x00B0, 0, 0, buf)) < 0)
+ goto out3;
+
+ msleep(5);
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_SW_PHY_SELECT, 0x0001, 0, 0, buf)) < 0) {
+ dbg("Select PHY #1 failed: %d", ret);
+ goto out3;
+ }
+
+ if ((ret =
+ ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_IPPD, 0, 0, buf)) < 0) {
+ dbg("Failed to power down internal PHY: %d", ret);
+ goto out3;
+ }
+
+ msleep(150);
+ if ((ret =
+ ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_CLEAR, 0, 0, buf)) < 0) {
+ dbg("Failed to perform software reset: %d", ret);
+ goto out3;
+ }
+
+ msleep(150);
+ if ((ret =
+ ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_IPRL | AX_SWRESET_PRL, 0, 0, buf)) < 0) {
+ dbg("Failed to set Internal/External PHY reset control: %d", ret);
+ goto out3;
+ }
+
+ msleep(150);
+ if ((ret =
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL, 0x0000, 0, 0,
+ buf)) < 0) {
+ dbg("Failed to reset RX_CTL: %d", ret);
+ goto out3;
+ }
+
+ /* Get the MAC address */
+ memset(buf, 0, ETH_ALEN);
+ if ((ret = ax8817x_read_cmd(dev, AX88772_CMD_READ_NODE_ID, 0, 0, ETH_ALEN, buf)) < 0) {
+ dbg("Failed to read MAC address: %d", ret);
+ goto out3;
+ }
+ memcpy(dev->net->dev_addr, buf, ETH_ALEN);
+
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_SET_SW_MII, 0, 0, 0, buf)) < 0) {
+ dbg("Enabling software MII failed: %d", ret);
+ goto out3;
+ }
+
+ if (((ret =
+ ax8817x_read_cmd(dev, AX_CMD_READ_MII_REG, 0x0010, 2, 2, buf)) < 0)
+ || (*((u16 *)buf) != 0x003b)) {
+ dbg("Read PHY register 2 must be 0x3b00: %d", ret);
+ goto out3;
+ }
+
+ /* Initialize MII structure */
+ dev->mii.dev = dev->net;
+ dev->mii.mdio_read = ax8817x_mdio_read;
+ dev->mii.mdio_write = ax8817x_mdio_write;
+ dev->mii.phy_id_mask = 0xff;
+ dev->mii.reg_num_mask = 0xff;
+
+ /* Get the PHY id */
+ if ((ret = ax8817x_read_cmd(dev, AX_CMD_READ_PHY_ID, 0, 0, 2, buf)) < 0) {
+ dbg("Error reading PHY ID: %02x", ret);
+ goto out3;
+ } else if (ret < 2) {
+ /* this should always return 2 bytes */
+ dbg("AX_CMD_READ_PHY_ID returned less than 2 bytes: ret=%02x",
+ ret);
+ ret = -EIO;
+ goto out3;
+ }
+ dev->mii.phy_id = *((u8 *)buf + 1);
+
+ if ((ret =
+ ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_PRL, 0, 0, buf)) < 0) {
+ dbg("Set external PHY reset pin level: %d", ret);
+ goto out3;
+ }
+ msleep(150);
+ if ((ret =
+ ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_IPRL | AX_SWRESET_PRL, 0, 0, buf)) < 0) {
+ dbg("Set Internal/External PHY reset control: %d", ret);
+ goto out3;
+ }
+ msleep(150);
+
+
+ dev->net->set_multicast_list = ax8817x_set_multicast;
+ dev->net->ethtool_ops = &ax88772_ethtool_ops;
+
+ ax8817x_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR,
+ cpu_to_le16(BMCR_RESET));
+ ax8817x_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE,
+ cpu_to_le16(ADVERTISE_ALL | ADVERTISE_CSMA));
+ mii_nway_restart(&dev->mii);
+
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, 0x0336, 0, 0, buf)) < 0) {
+ dbg("Write medium mode register: %d", ret);
+ goto out3;
+ }
+
+ if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_IPG0, AX88772_IPG0_DEFAULT | AX88772_IPG1_DEFAULT,AX88772_IPG2_DEFAULT, 0, buf)) < 0) {
+ dbg("Write IPG,IPG1,IPG2 failed: %d", ret);
+ goto out3;
+ }
+ if ((ret =
+ ax8817x_write_cmd(dev, AX_CMD_SET_HW_MII, 0, 0, 0, &buf)) < 0) {
+ dbg("Failed to set hardware MII: %02x", ret);
+ goto out3;
+ }
+
+ /* Set RX_CTL to default values with 2k buffer, and enable cactus */
+ if ((ret =
+ ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL, 0x0088, 0, 0,
+ buf)) < 0) {
+ dbg("Reset RX_CTL failed: %d", ret);
+ goto out3;
+ }
+
+ if((ret = usb_submit_urb(data->int_urb, GFP_KERNEL)) < 0) {
+ dbg("Failed to submit interrupt URB: %02x", ret);
+ goto out3;
+ }
+
+ kfree(buf);
+
+ return 0;
+
+out3:
+ kfree(buf);
+out2:
+ kfree(data->int_buf);
+out1:
+ usb_free_urb(data->int_urb);
+
+ return ret;
+}
+
+static int ax88772_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
+{
+ u32 *header;
+ char *packet;
+ struct sk_buff *ax_skb;
+ u16 size;
+
+ header = (u32 *) skb->data;
+ le32_to_cpus(header);
+ packet = (char *)(header + 1);
+
+ skb_pull(skb, 4);
+
+ while (skb->len > 0) {
+ if ((short)(*header & 0x0000ffff) !=
+ ~((short)((*header & 0xffff0000) >> 16))) {
+ devdbg(dev,"header length data is error");
+ }
+ /* get the packet length */
+ size = (u16) (*header & 0x0000ffff);
+
+ if ((skb->len) - ((size + 1) & 0xfffe) == 0)
+ return 2;
+ if (size > ETH_FRAME_LEN) {
+ devdbg(dev,"invalid rx length %d", size);
+ return 0;
+ }
+ ax_skb = skb_clone(skb, GFP_ATOMIC);
+ if (ax_skb) {
+ ax_skb->len = size;
+ ax_skb->data = packet;
+ ax_skb->tail = packet + size;
+ skb_return(dev, ax_skb);
+ } else {
+ return 0;
+ }
+
+ skb_pull(skb, (size + 1) & 0xfffe);
+
+ if (skb->len == 0)
+ break;
+
+ header = (u32 *) skb->data;
+ le32_to_cpus(header);
+ packet = (char *)(header + 1);
+ skb_pull(skb, 4);
+ }
+
+ if (skb->len < 0) {
+ devdbg(dev,"invalid rx length %d", skb->len);
+ return 0;
+ }
+ return 1;
+}
+
+static struct sk_buff *ax88772_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
+ int flags)
+{
+ int padlen;
+ int headroom = skb_headroom(skb);
+ int tailroom = skb_tailroom(skb);
+ u32 *packet_len;
+ u32 *padbytes_ptr;
+
+ padlen = ((skb->len + 4) % 512) ? 0 : 4;
+
+ if ((!skb_cloned(skb))
+ && ((headroom + tailroom) >= (4 + padlen))) {
+ if ((headroom < 4) || (tailroom < padlen)) {
+ skb->data = memmove(skb->head + 4, skb->data, skb->len);
+ skb->tail = skb->data + skb->len;
+ }
+ } else {
+ struct sk_buff *skb2;
+ skb2 = skb_copy_expand(skb, 4, padlen, flags);
+ dev_kfree_skb_any(skb);
+ skb = skb2;
+ if (!skb)
+ return NULL;
+ }
+
+ packet_len = (u32 *) skb_push(skb, 4);
+
+ packet_len = (u32 *) skb->data;
+ *packet_len = (((skb->len - 4) ^ 0x0000ffff) << 16) + (skb->len - 4);
+
+ if ((skb->len % 512) == 0) {
+ padbytes_ptr = (u32 *) skb->tail;
+ *padbytes_ptr = 0xffff0000;
+ skb_put(skb, padlen);
+ }
+ return skb;
+}
+
static const struct driver_info ax8817x_info = {
.description = "ASIX AX8817x USB 2.0 Ethernet",
.bind = ax8817x_bind,
@@ -864,6 +1245,16 @@ static const struct driver_info hawking_uf200_info = {
.data = 0x001f1d1f,
};
+static const struct driver_info ax88772_info = {
+ .description = "ASIX AX88772 USB 2.0 Ethernet",
+ .bind = ax88772_bind,
+ .unbind = ax8817x_unbind,
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX,
+ .rx_fixup = ax88772_rx_fixup,
+ .tx_fixup = ax88772_tx_fixup,
+ .data = 0x00130103,
+};
+
#endif /* CONFIG_USB_AX8817X */
@@ -911,45 +1302,14 @@ static const struct driver_info belkin_info = {
#ifdef NEED_GENERIC_CDC
-/* "Header Functional Descriptor" from CDC spec 5.2.3.1 */
-struct header_desc {
- u8 bLength;
- u8 bDescriptorType;
- u8 bDescriptorSubType;
-
- u16 bcdCDC;
-} __attribute__ ((packed));
-
-/* "Union Functional Descriptor" from CDC spec 5.2.3.X */
-struct union_desc {
- u8 bLength;
- u8 bDescriptorType;
- u8 bDescriptorSubType;
-
- u8 bMasterInterface0;
- u8 bSlaveInterface0;
- /* ... and there could be other slave interfaces */
-} __attribute__ ((packed));
-
-/* "Ethernet Networking Functional Descriptor" from CDC spec 5.2.3.16 */
-struct ether_desc {
- u8 bLength;
- u8 bDescriptorType;
- u8 bDescriptorSubType;
-
- u8 iMACAddress;
- u32 bmEthernetStatistics;
- __le16 wMaxSegmentSize;
- __le16 wNumberMCFilters;
- u8 bNumberPowerFilters;
-} __attribute__ ((packed));
+#include <linux/usb_cdc.h>
struct cdc_state {
- struct header_desc *header;
- struct union_desc *u;
- struct ether_desc *ether;
- struct usb_interface *control;
- struct usb_interface *data;
+ struct usb_cdc_header_desc *header;
+ struct usb_cdc_union_desc *u;
+ struct usb_cdc_ether_desc *ether;
+ struct usb_interface *control;
+ struct usb_interface *data;
};
static struct usb_driver usbnet_driver;
@@ -1004,7 +1364,7 @@ static int generic_cdc_bind (struct usbnet *dev, struct usb_interface *intf)
* CDC Ethernet achieves with a simple descriptor.
*/
switch (buf [2]) {
- case 0x00: /* Header, mostly useless */
+ case USB_CDC_HEADER_TYPE:
if (info->header) {
dev_dbg (&intf->dev, "extra CDC header\n");
goto bad_desc;
@@ -1016,7 +1376,7 @@ static int generic_cdc_bind (struct usbnet *dev, struct usb_interface *intf)
goto bad_desc;
}
break;
- case 0x06: /* Union (groups interfaces) */
+ case USB_CDC_UNION_TYPE:
if (info->u) {
dev_dbg (&intf->dev, "extra CDC union\n");
goto bad_desc;
@@ -1065,7 +1425,7 @@ static int generic_cdc_bind (struct usbnet *dev, struct usb_interface *intf)
goto bad_desc;
}
break;
- case 0x0F: /* Ethernet Networking */
+ case USB_CDC_ETHERNET_TYPE:
if (info->ether) {
dev_dbg (&intf->dev, "extra CDC ether\n");
goto bad_desc;
@@ -1110,6 +1470,29 @@ next_desc:
usb_driver_release_interface (&usbnet_driver, info->data);
return status;
}
+
+ /* status endpoint: optional for CDC Ethernet, not RNDIS (or ACM) */
+ dev->status = NULL;
+ if (info->control->cur_altsetting->desc.bNumEndpoints == 1) {
+ struct usb_endpoint_descriptor *desc;
+
+ dev->status = &info->control->cur_altsetting->endpoint [0];
+ desc = &dev->status->desc;
+ if (desc->bmAttributes != USB_ENDPOINT_XFER_INT
+ || !(desc->bEndpointAddress & USB_DIR_IN)
+ || (le16_to_cpu(desc->wMaxPacketSize)
+ < sizeof (struct usb_cdc_notification))
+ || !desc->bInterval) {
+ dev_dbg (&intf->dev, "bad notification endpoint\n");
+ dev->status = NULL;
+ }
+ }
+ if (rndis && !dev->status) {
+ dev_dbg (&intf->dev, "missing RNDIS status endpoint\n");
+ usb_set_intfdata(info->data, NULL);
+ usb_driver_release_interface (&usbnet_driver, info->data);
+ return -ENODEV;
+ }
return 0;
bad_desc:
@@ -1138,6 +1521,56 @@ static void cdc_unbind (struct usbnet *dev, struct usb_interface *intf)
}
}
+
+static void dumpspeed (struct usbnet *dev, __le32 *speeds)
+{
+ if (netif_msg_timer (dev))
+ devinfo (dev, "link speeds: %u kbps up, %u kbps down",
+ __le32_to_cpu(speeds[0]) / 1000,
+ __le32_to_cpu(speeds[1]) / 1000);
+}
+
+static void cdc_status (struct usbnet *dev, struct urb *urb)
+{
+ struct usb_cdc_notification *event;
+
+ if (urb->actual_length < sizeof *event)
+ return;
+
+ /* SPEED_CHANGE can get split into two 8-byte packets */
+ if (test_and_clear_bit (EVENT_STS_SPLIT, &dev->flags)) {
+ dumpspeed (dev, (__le32 *) urb->transfer_buffer);
+ return;
+ }
+
+ event = urb->transfer_buffer;
+ switch (event->bNotificationType) {
+ case USB_CDC_NOTIFY_NETWORK_CONNECTION:
+ if (netif_msg_timer (dev))
+ devdbg (dev, "CDC: carrier %s",
+ event->wValue ? "on" : "off");
+ if (event->wValue)
+ netif_carrier_on(dev->net);
+ else
+ netif_carrier_off(dev->net);
+ break;
+ case USB_CDC_NOTIFY_SPEED_CHANGE: /* tx/rx rates */
+ if (netif_msg_timer (dev))
+ devdbg (dev, "CDC: speed change (len %d)",
+ urb->actual_length);
+ if (urb->actual_length != (sizeof *event + 8))
+ set_bit (EVENT_STS_SPLIT, &dev->flags);
+ else
+ dumpspeed (dev, (__le32 *) &event[1]);
+ break;
+ // case USB_CDC_NOTIFY_RESPONSE_AVAILABLE: /* RNDIS; or unsolicited */
+ default:
+ deverr (dev, "CDC: unexpected notification %02x!",
+ event->bNotificationType);
+ break;
+ }
+}
+
#endif /* NEED_GENERIC_CDC */
@@ -1169,7 +1602,7 @@ static u8 nibble (unsigned char c)
}
static inline int
-get_ethernet_addr (struct usbnet *dev, struct ether_desc *e)
+get_ethernet_addr (struct usbnet *dev, struct usb_cdc_ether_desc *e)
{
int tmp, i;
unsigned char buf [13];
@@ -1216,6 +1649,7 @@ static const struct driver_info cdc_info = {
// .check_connect = cdc_check_connect,
.bind = cdc_bind,
.unbind = cdc_unbind,
+ .status = cdc_status,
};
#endif /* CONFIG_USB_CDCETHER */
@@ -1321,7 +1755,7 @@ static inline int gl_control_write (struct usbnet *dev, u8 request, u16 value)
0, // index
0, // data buffer
0, // size
- CONTROL_TIMEOUT_JIFFIES);
+ CONTROL_TIMEOUT_MS);
return retval;
}
@@ -1602,9 +2036,9 @@ static const struct driver_info genelink_info = {
*/
struct nc_header { // packed:
- u16 hdr_len; // sizeof nc_header (LE, all)
- u16 packet_len; // payload size (including ethhdr)
- u16 packet_id; // detects dropped packets
+ __le16 hdr_len; // sizeof nc_header (LE, all)
+ __le16 packet_len; // payload size (including ethhdr)
+ __le16 packet_id; // detects dropped packets
#define MIN_HEADER 6
// all else is optional, and must start with:
@@ -1615,7 +2049,7 @@ struct nc_header { // packed:
#define PAD_BYTE ((unsigned char)0xAC)
struct nc_trailer {
- u16 packet_id;
+ __le16 packet_id;
} __attribute__((__packed__));
// packets may use FLAG_FRAMING_NC and optional pad
@@ -1658,7 +2092,7 @@ nc_vendor_read (struct usbnet *dev, u8 req, u8 regnum, u16 *retval_ptr)
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0, regnum,
retval_ptr, sizeof *retval_ptr,
- CONTROL_TIMEOUT_JIFFIES);
+ CONTROL_TIMEOUT_MS);
if (status > 0)
status = 0;
if (!status)
@@ -1682,7 +2116,7 @@ nc_vendor_write (struct usbnet *dev, u8 req, u8 regnum, u16 value)
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
value, regnum,
NULL, 0, // data is in setup packet
- CONTROL_TIMEOUT_JIFFIES);
+ CONTROL_TIMEOUT_MS);
}
static inline void
@@ -1747,7 +2181,8 @@ static void nc_dump_registers (struct usbnet *dev)
static inline void nc_dump_usbctl (struct usbnet *dev, u16 usbctl)
{
-#ifdef DEBUG
+ if (!netif_msg_link (dev))
+ return;
devdbg (dev, "net1080 %s-%s usbctl 0x%x:%s%s%s%s%s;"
" this%s%s;"
" other%s%s; r/o 0x%x",
@@ -1765,7 +2200,6 @@ static inline void nc_dump_usbctl (struct usbnet *dev, u16 usbctl)
(usbctl & USBCTL_DISCONN_THIS) ? " DIS" : "",
usbctl & ~USBCTL_WRITABLE_MASK
);
-#endif
}
/*-------------------------------------------------------------------------*/
@@ -1792,7 +2226,8 @@ static inline void nc_dump_usbctl (struct usbnet *dev, u16 usbctl)
static inline void nc_dump_status (struct usbnet *dev, u16 status)
{
-#ifdef DEBUG
+ if (!netif_msg_link (dev))
+ return;
devdbg (dev, "net1080 %s-%s status 0x%x:"
" this (%c) PKT=%d%s%s%s;"
" other PKT=%d%s%s%s; unspec 0x%x",
@@ -1815,7 +2250,6 @@ static inline void nc_dump_status (struct usbnet *dev, u16 status)
status & STATUS_UNSPEC_MASK
);
-#endif
}
/*-------------------------------------------------------------------------*/
@@ -1830,15 +2264,10 @@ static inline void nc_dump_status (struct usbnet *dev, u16 status)
static inline void nc_dump_ttl (struct usbnet *dev, u16 ttl)
{
-#ifdef DEBUG
- devdbg (dev, "net1080 %s-%s ttl 0x%x this = %d, other = %d",
- dev->udev->bus->bus_name, dev->udev->devpath,
- ttl,
-
- TTL_THIS (ttl),
- TTL_OTHER (ttl)
- );
-#endif
+ if (netif_msg_link (dev))
+ devdbg (dev, "net1080 %s-%s ttl 0x%x this = %d, other = %d",
+ dev->udev->bus->bus_name, dev->udev->devpath,
+ ttl, TTL_THIS (ttl), TTL_OTHER (ttl));
}
/*-------------------------------------------------------------------------*/
@@ -1860,14 +2289,14 @@ static int net1080_reset (struct usbnet *dev)
goto done;
}
status = *vp;
- // nc_dump_status (dev, status);
+ nc_dump_status (dev, status);
if ((retval = nc_register_read (dev, REG_USBCTL, vp)) < 0) {
dbg ("can't read USBCTL, %d", retval);
goto done;
}
usbctl = *vp;
- // nc_dump_usbctl (dev, usbctl);
+ nc_dump_usbctl (dev, usbctl);
nc_register_write (dev, REG_USBCTL,
USBCTL_FLUSH_THIS | USBCTL_FLUSH_OTHER);
@@ -1883,7 +2312,7 @@ static int net1080_reset (struct usbnet *dev)
MK_TTL (NC_READ_TTL_MS, TTL_OTHER (ttl)) );
dbg ("%s: assigned TTL, %d ms", dev->net->name, NC_READ_TTL_MS);
- if (dev->msg_level >= 2)
+ if (netif_msg_link (dev))
devinfo (dev, "port %c, peer %sconnected",
(status & STATUS_PORT_A) ? 'A' : 'B',
(status & STATUS_CONN_OTHER) ? "" : "dis"
@@ -1964,7 +2393,8 @@ static void nc_ensure_sync (struct usbnet *dev)
return;
}
- devdbg (dev, "flush net1080; too many framing errors");
+ if (netif_msg_rx_err (dev))
+ devdbg (dev, "flush net1080; too many framing errors");
dev->frame_errors = 0;
}
}
@@ -1973,6 +2403,7 @@ static int net1080_rx_fixup (struct usbnet *dev, struct sk_buff *skb)
{
struct nc_header *header;
struct nc_trailer *trailer;
+ u16 hdr_len, packet_len;
if (!(skb->len & 0x01)
|| MIN_FRAMED > skb->len
@@ -1986,50 +2417,50 @@ static int net1080_rx_fixup (struct usbnet *dev, struct sk_buff *skb)
}
header = (struct nc_header *) skb->data;
- le16_to_cpus (&header->hdr_len);
- le16_to_cpus (&header->packet_len);
- if (FRAMED_SIZE (header->packet_len) > MAX_PACKET) {
+ hdr_len = le16_to_cpup (&header->hdr_len);
+ packet_len = le16_to_cpup (&header->packet_len);
+ if (FRAMED_SIZE (packet_len) > MAX_PACKET) {
dev->stats.rx_frame_errors++;
- dbg ("packet too big, %d", header->packet_len);
+ dbg ("packet too big, %d", packet_len);
nc_ensure_sync (dev);
return 0;
- } else if (header->hdr_len < MIN_HEADER) {
+ } else if (hdr_len < MIN_HEADER) {
dev->stats.rx_frame_errors++;
- dbg ("header too short, %d", header->hdr_len);
+ dbg ("header too short, %d", hdr_len);
nc_ensure_sync (dev);
return 0;
- } else if (header->hdr_len > MIN_HEADER) {
+ } else if (hdr_len > MIN_HEADER) {
// out of band data for us?
- dbg ("header OOB, %d bytes",
- header->hdr_len - MIN_HEADER);
+ dbg ("header OOB, %d bytes", hdr_len - MIN_HEADER);
nc_ensure_sync (dev);
// switch (vendor/product ids) { ... }
}
- skb_pull (skb, header->hdr_len);
+ skb_pull (skb, hdr_len);
trailer = (struct nc_trailer *)
(skb->data + skb->len - sizeof *trailer);
skb_trim (skb, skb->len - sizeof *trailer);
- if ((header->packet_len & 0x01) == 0) {
- if (skb->data [header->packet_len] != PAD_BYTE) {
+ if ((packet_len & 0x01) == 0) {
+ if (skb->data [packet_len] != PAD_BYTE) {
dev->stats.rx_frame_errors++;
dbg ("bad pad");
return 0;
}
skb_trim (skb, skb->len - 1);
}
- if (skb->len != header->packet_len) {
+ if (skb->len != packet_len) {
dev->stats.rx_frame_errors++;
dbg ("bad packet len %d (expected %d)",
- skb->len, header->packet_len);
+ skb->len, packet_len);
nc_ensure_sync (dev);
return 0;
}
if (header->packet_id != get_unaligned (&trailer->packet_id)) {
dev->stats.rx_fifo_errors++;
dbg ("(2+ dropped) rx packet_id mismatch 0x%x 0x%x",
- header->packet_id, trailer->packet_id);
+ le16_to_cpu (header->packet_id),
+ le16_to_cpu (trailer->packet_id));
return 0;
}
#if 0
@@ -2125,7 +2556,7 @@ pl_vendor_req (struct usbnet *dev, u8 req, u8 val, u8 index)
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
val, index,
NULL, 0,
- CONTROL_TIMEOUT_JIFFIES);
+ CONTROL_TIMEOUT_MS);
}
static inline int
@@ -2221,11 +2652,17 @@ static const struct driver_info blob_info = {
* For the current version of that driver, the main way that framing is
* nonstandard (also from perspective of the CDC ethernet model!) is a
* crc32, added to help detect when some sa1100 usb-to-memory DMA errata
- * haven't been fully worked around.
+ * haven't been fully worked around. Also, all Zaurii use the same
+ * default Ethernet address.
*
* PXA based models use the same framing, and also can't implement
* set_interface properly.
*
+ * All known Zaurii lie about their standards conformance. Most lie by
+ * saying they support CDC Ethernet. Some lie and say they support CDC
+ * MDLM (as if for access to cell phone modems). Someone, please beat
+ * on Sharp for a while with a cluestick.
+ *
*-------------------------------------------------------------------------*/
static struct sk_buff *
@@ -2277,6 +2714,13 @@ static const struct driver_info zaurus_pxa_info = {
};
#define ZAURUS_PXA_INFO ((unsigned long)&zaurus_pxa_info)
+static const struct driver_info zaurus_pxa_mdlm_info = {
+ .description = "Sharp Zaurus, PXA-255 based",
+ .flags = FLAG_FRAMING_Z,
+ .check_connect = always_connected,
+ .tx_fixup = zaurus_tx_fixup,
+};
+
static const struct driver_info olympus_mxl_info = {
.description = "Olympus R1000",
.flags = FLAG_FRAMING_Z,
@@ -2402,14 +2846,21 @@ static void rx_submit (struct usbnet *dev, struct urb *urb, int flags)
size = RNDIS_MAX_TRANSFER;
else
#endif
+#ifdef CONFIG_USB_AX8817X
+ if (dev->driver_info->flags & FLAG_FRAMING_AX)
+ size = 2048;
+ else
+#endif
size = (sizeof (struct ethhdr) + dev->net->mtu);
- if ((skb = alloc_skb (size, flags)) == NULL) {
- devdbg (dev, "no rx skb");
+ if ((skb = alloc_skb (size + NET_IP_ALIGN, flags)) == NULL) {
+ if (netif_msg_rx_err (dev))
+ devdbg (dev, "no rx skb");
defer_kevent (dev, EVENT_RX_MEMORY);
usb_free_urb (urb);
return;
}
+ skb_reserve (skb, NET_IP_ALIGN);
entry = (struct skb_data *) skb->cb;
entry->urb = urb;
@@ -2434,18 +2885,21 @@ static void rx_submit (struct usbnet *dev, struct urb *urb, int flags)
defer_kevent (dev, EVENT_RX_MEMORY);
break;
case -ENODEV:
- devdbg (dev, "device gone");
+ if (netif_msg_ifdown (dev))
+ devdbg (dev, "device gone");
netif_device_detach (dev->net);
break;
default:
- devdbg (dev, "rx submit, %d", retval);
+ if (netif_msg_rx_err (dev))
+ devdbg (dev, "rx submit, %d", retval);
tasklet_schedule (&dev->bh);
break;
case 0:
__skb_queue_tail (&dev->rxq, skb);
}
} else {
- devdbg (dev, "rx: stopped");
+ if (netif_msg_ifdown (dev))
+ devdbg (dev, "rx: stopped");
retval = -ENOLINK;
}
spin_unlock_irqrestore (&dev->rxq.lock, lockflags);
@@ -2468,7 +2922,8 @@ static inline void rx_process (struct usbnet *dev, struct sk_buff *skb)
if (skb->len)
skb_return (dev, skb);
else {
- devdbg (dev, "drop");
+ if (netif_msg_rx_err (dev))
+ devdbg (dev, "drop");
error:
dev->stats.rx_errors++;
skb_queue_tail (&dev->done, skb);
@@ -2495,7 +2950,8 @@ static void rx_complete (struct urb *urb, struct pt_regs *regs)
entry->state = rx_cleanup;
dev->stats.rx_errors++;
dev->stats.rx_length_errors++;
- devdbg (dev, "rx length %d", skb->len);
+ if (netif_msg_rx_err (dev))
+ devdbg (dev, "rx length %d", skb->len);
}
break;
@@ -2511,9 +2967,8 @@ static void rx_complete (struct urb *urb, struct pt_regs *regs)
// software-driven interface shutdown
case -ECONNRESET: // async unlink
case -ESHUTDOWN: // hardware gone
-#ifdef VERBOSE
- devdbg (dev, "rx shutdown, code %d", urb_status);
-#endif
+ if (netif_msg_ifdown (dev))
+ devdbg (dev, "rx shutdown, code %d", urb_status);
goto block;
// we get controller i/o faults during khubd disconnect() delays.
@@ -2525,7 +2980,8 @@ static void rx_complete (struct urb *urb, struct pt_regs *regs)
dev->stats.rx_errors++;
if (!timer_pending (&dev->delay)) {
mod_timer (&dev->delay, jiffies + THROTTLE_JIFFIES);
- devdbg (dev, "rx throttle %d", urb_status);
+ if (netif_msg_link (dev))
+ devdbg (dev, "rx throttle %d", urb_status);
}
block:
entry->state = rx_cleanup;
@@ -2541,7 +2997,8 @@ block:
default:
entry->state = rx_cleanup;
dev->stats.rx_errors++;
- devdbg (dev, "rx status %d", urb_status);
+ if (netif_msg_rx_err (dev))
+ devdbg (dev, "rx status %d", urb_status);
break;
}
@@ -2555,9 +3012,43 @@ block:
}
usb_free_urb (urb);
}
-#ifdef VERBOSE
- devdbg (dev, "no read resubmitted");
-#endif /* VERBOSE */
+ if (netif_msg_rx_err (dev))
+ devdbg (dev, "no read resubmitted");
+}
+
+static void intr_complete (struct urb *urb, struct pt_regs *regs)
+{
+ struct usbnet *dev = urb->context;
+ int status = urb->status;
+
+ switch (status) {
+ /* success */
+ case 0:
+ dev->driver_info->status(dev, urb);
+ break;
+
+ /* software-driven interface shutdown */
+ case -ENOENT: // urb killed
+ case -ESHUTDOWN: // hardware gone
+ if (netif_msg_ifdown (dev))
+ devdbg (dev, "intr shutdown, code %d", status);
+ return;
+
+ /* NOTE: not throttling like RX/TX, since this endpoint
+ * already polls infrequently
+ */
+ default:
+ devdbg (dev, "intr status %d", status);
+ break;
+ }
+
+ if (!netif_running (dev->net))
+ return;
+
+ memset(urb->transfer_buffer, 0, urb->transfer_buffer_length);
+ status = usb_submit_urb (urb, GFP_ATOMIC);
+ if (status != 0 && netif_msg_timer (dev))
+ deverr(dev, "intr resubmit --> %d", status);
}
/*-------------------------------------------------------------------------*/
@@ -2606,7 +3097,7 @@ static int usbnet_stop (struct net_device *net)
netif_stop_queue (net);
- if (dev->msg_level >= 2)
+ if (netif_msg_ifdown (dev))
devinfo (dev, "stop stats: rx/tx %ld/%ld, errs %ld/%ld",
dev->stats.rx_packets, dev->stats.tx_packets,
dev->stats.rx_errors, dev->stats.tx_errors
@@ -2622,11 +3113,14 @@ static int usbnet_stop (struct net_device *net)
&& skb_queue_len (&dev->txq)
&& skb_queue_len (&dev->done)) {
msleep(UNLINK_TIMEOUT_MS);
- devdbg (dev, "waited for %d urb completions", temp);
+ if (netif_msg_ifdown (dev))
+ devdbg (dev, "waited for %d urb completions", temp);
}
dev->wait = NULL;
remove_wait_queue (&unlink_wakeup, &wait);
+ usb_kill_urb(dev->interrupt);
+
/* deferred work (task, timer, softirq) must also stop.
* can't flush_scheduled_work() until we drop rtnl (later),
* else workers could deadlock; so make workers a NOP.
@@ -2652,21 +3146,34 @@ static int usbnet_open (struct net_device *net)
// put into "known safe" state
if (info->reset && (retval = info->reset (dev)) < 0) {
- devinfo (dev, "open reset fail (%d) usbnet usb-%s-%s, %s",
- retval,
- dev->udev->bus->bus_name, dev->udev->devpath,
+ if (netif_msg_ifup (dev))
+ devinfo (dev,
+ "open reset fail (%d) usbnet usb-%s-%s, %s",
+ retval,
+ dev->udev->bus->bus_name, dev->udev->devpath,
info->description);
goto done;
}
// insist peer be connected
if (info->check_connect && (retval = info->check_connect (dev)) < 0) {
- devdbg (dev, "can't open; %d", retval);
+ if (netif_msg_ifup (dev))
+ devdbg (dev, "can't open; %d", retval);
goto done;
}
+ /* start any status interrupt transfer */
+ if (dev->interrupt) {
+ retval = usb_submit_urb (dev->interrupt, GFP_KERNEL);
+ if (retval < 0) {
+ if (netif_msg_ifup (dev))
+ deverr (dev, "intr submit %d", retval);
+ goto done;
+ }
+ }
+
netif_start_queue (net);
- if (dev->msg_level >= 2) {
+ if (netif_msg_ifup (dev)) {
char *framing;
if (dev->driver_info->flags & FLAG_FRAMING_NC)
@@ -2677,6 +3184,8 @@ static int usbnet_open (struct net_device *net)
framing = "Zaurus";
else if (dev->driver_info->flags & FLAG_FRAMING_RN)
framing = "RNDIS";
+ else if (dev->driver_info->flags & FLAG_FRAMING_AX)
+ framing = "ASIX";
else
framing = "simple";
@@ -2721,14 +3230,14 @@ static u32 usbnet_get_msglevel (struct net_device *net)
{
struct usbnet *dev = netdev_priv(net);
- return dev->msg_level;
+ return dev->msg_enable;
}
static void usbnet_set_msglevel (struct net_device *net, u32 level)
{
struct usbnet *dev = netdev_priv(net);
- dev->msg_level = level;
+ dev->msg_enable = level;
}
static int usbnet_ioctl (struct net_device *net, struct ifreq *rq, int cmd)
@@ -2761,10 +3270,11 @@ kevent (void *data)
if (test_bit (EVENT_TX_HALT, &dev->flags)) {
unlink_urbs (dev, &dev->txq);
status = usb_clear_halt (dev->udev, dev->out);
- if (status < 0 && status != -EPIPE)
- deverr (dev, "can't clear tx halt, status %d",
- status);
- else {
+ if (status < 0 && status != -EPIPE) {
+ if (netif_msg_tx_err (dev))
+ deverr (dev, "can't clear tx halt, status %d",
+ status);
+ } else {
clear_bit (EVENT_TX_HALT, &dev->flags);
netif_wake_queue (dev->net);
}
@@ -2772,10 +3282,11 @@ kevent (void *data)
if (test_bit (EVENT_RX_HALT, &dev->flags)) {
unlink_urbs (dev, &dev->rxq);
status = usb_clear_halt (dev->udev, dev->in);
- if (status < 0 && status != -EPIPE)
- deverr (dev, "can't clear rx halt, status %d",
- status);
- else {
+ if (status < 0 && status != -EPIPE) {
+ if (netif_msg_rx_err (dev))
+ deverr (dev, "can't clear rx halt, status %d",
+ status);
+ } else {
clear_bit (EVENT_RX_HALT, &dev->flags);
tasklet_schedule (&dev->bh);
}
@@ -2820,6 +3331,11 @@ static void tx_complete (struct urb *urb, struct pt_regs *regs)
defer_kevent (dev, EVENT_TX_HALT);
break;
+ /* software-driven interface shutdown */
+ case -ECONNRESET: // async unlink
+ case -ESHUTDOWN: // hardware gone
+ break;
+
// like rx, tx gets controller i/o faults during khubd delays
// and so it uses the same throttling mechanism.
case -EPROTO: // ehci
@@ -2828,12 +3344,15 @@ static void tx_complete (struct urb *urb, struct pt_regs *regs)
if (!timer_pending (&dev->delay)) {
mod_timer (&dev->delay,
jiffies + THROTTLE_JIFFIES);
- devdbg (dev, "tx throttle %d", urb->status);
+ if (netif_msg_link (dev))
+ devdbg (dev, "tx throttle %d",
+ urb->status);
}
netif_stop_queue (dev->net);
break;
default:
- devdbg (dev, "tx err %d", entry->urb->status);
+ if (netif_msg_tx_err (dev))
+ devdbg (dev, "tx err %d", entry->urb->status);
break;
}
}
@@ -2876,14 +3395,16 @@ static int usbnet_start_xmit (struct sk_buff *skb, struct net_device *net)
if (info->tx_fixup) {
skb = info->tx_fixup (dev, skb, GFP_ATOMIC);
if (!skb) {
- devdbg (dev, "can't tx_fixup skb");
+ if (netif_msg_tx_err (dev))
+ devdbg (dev, "can't tx_fixup skb");
goto drop;
}
}
length = skb->len;
if (!(urb = usb_alloc_urb (0, GFP_ATOMIC))) {
- devdbg (dev, "no urb");
+ if (netif_msg_tx_err (dev))
+ devdbg (dev, "no urb");
goto drop;
}
@@ -2941,7 +3462,8 @@ static int usbnet_start_xmit (struct sk_buff *skb, struct net_device *net)
defer_kevent (dev, EVENT_TX_HALT);
break;
default:
- devdbg (dev, "tx: submit urb err %d", retval);
+ if (netif_msg_tx_err (dev))
+ devdbg (dev, "tx: submit urb err %d", retval);
break;
case 0:
net->trans_start = jiffies;
@@ -2952,18 +3474,17 @@ static int usbnet_start_xmit (struct sk_buff *skb, struct net_device *net)
spin_unlock_irqrestore (&dev->txq.lock, flags);
if (retval) {
- devdbg (dev, "drop, code %d", retval);
+ if (netif_msg_tx_err (dev))
+ devdbg (dev, "drop, code %d", retval);
drop:
retval = NET_XMIT_SUCCESS;
dev->stats.tx_dropped++;
if (skb)
dev_kfree_skb_any (skb);
usb_free_urb (urb);
-#ifdef VERBOSE
- } else {
+ } else if (netif_msg_tx_queued (dev)) {
devdbg (dev, "> tx, len %d, type 0x%x",
length, skb->protocol);
-#endif
}
return retval;
}
@@ -3020,7 +3541,7 @@ static void usbnet_bh (unsigned long param)
if (urb != NULL)
rx_submit (dev, urb, GFP_ATOMIC);
}
- if (temp != dev->rxq.qlen)
+ if (temp != dev->rxq.qlen && netif_msg_link (dev))
devdbg (dev, "rxqlen %d --> %d",
temp, dev->rxq.qlen);
if (dev->rxq.qlen < qlen)
@@ -3054,9 +3575,10 @@ static void usbnet_disconnect (struct usb_interface *intf)
xdev = interface_to_usbdev (intf);
- devinfo (dev, "unregister usbnet usb-%s-%s, %s",
- xdev->bus->bus_name, xdev->devpath,
- dev->driver_info->description);
+ if (netif_msg_probe (dev))
+ devinfo (dev, "unregister usbnet usb-%s-%s, %s",
+ xdev->bus->bus_name, xdev->devpath,
+ dev->driver_info->description);
net = dev->net;
unregister_netdev (net);
@@ -3110,7 +3632,8 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
dev = netdev_priv(net);
dev->udev = xdev;
dev->driver_info = info;
- dev->msg_level = msg_level;
+ dev->msg_enable = netif_msg_init (msg_level, NETIF_MSG_DRV
+ | NETIF_MSG_PROBE | NETIF_MSG_LINK);
skb_queue_head_init (&dev->rxq);
skb_queue_head_init (&dev->txq);
skb_queue_head_init (&dev->done);
@@ -3129,7 +3652,7 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
#if 0
// dma_supported() is deeply broken on almost all architectures
// possible with some EHCI controllers
- if (dma_supported (&udev->dev, 0xffffffffffffffffULL))
+ if (dma_supported (&udev->dev, DMA_64BIT_MASK))
net->features |= NETIF_F_HIGHDMA;
#endif
@@ -3166,6 +3689,9 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
status = 0;
}
+
+ if (status == 0 && dev->status)
+ status = init_status (dev, udev);
if (status < 0)
goto out1;
@@ -3175,9 +3701,14 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
status = register_netdev (net);
if (status)
goto out3;
- devinfo (dev, "register usbnet at usb-%s-%s, %s",
- xdev->bus->bus_name, xdev->devpath,
- dev->driver_info->description);
+ if (netif_msg_probe (dev))
+ devinfo (dev, "register usbnet at usb-%s-%s, %s, "
+ "%02x:%02x:%02x:%02x:%02x:%02x",
+ xdev->bus->bus_name, xdev->devpath,
+ dev->driver_info->description,
+ net->dev_addr [0], net->dev_addr [1],
+ net->dev_addr [2], net->dev_addr [3],
+ net->dev_addr [4], net->dev_addr [5]);
// ok, it's ready to go.
usb_set_intfdata (udev, dev);
@@ -3197,6 +3728,32 @@ out:
return status;
}
+/*-------------------------------------------------------------------------*/
+
+#ifdef CONFIG_PM
+
+static int usbnet_suspend (struct usb_interface *intf, u32 state)
+{
+ struct usbnet *dev = usb_get_intfdata(intf);
+
+ netif_device_detach (dev->net);
+ return 0;
+}
+
+static int usbnet_resume (struct usb_interface *intf)
+{
+ struct usbnet *dev = usb_get_intfdata(intf);
+
+ netif_device_attach (dev->net);
+ return 0;
+}
+
+#else /* !CONFIG_PM */
+
+#define usbnet_suspend NULL
+#define usbnet_resume NULL
+
+#endif /* CONFIG_PM */
/*-------------------------------------------------------------------------*/
@@ -3290,6 +3847,10 @@ static const struct usb_device_id products [] = {
// goodway corp usb gwusb2e
USB_DEVICE (0x1631, 0x6200),
.driver_info = (unsigned long) &ax8817x_info,
+}, {
+ // ASIX AX88772 10/100
+ USB_DEVICE (0x0b95, 0x7720),
+ .driver_info = (unsigned long) &ax88772_info,
},
#endif
@@ -3374,6 +3935,7 @@ static const struct usb_device_id products [] = {
.driver_info = (unsigned long) &blob_info,
}, {
// Linux Ethernet/RNDIS gadget on pxa210/25x/26x
+ // e.g. Gumstix, current OpenZaurus, ...
USB_DEVICE_VER (0x0525, 0xa4a2, 0x0203, 0x0203),
.driver_info = (unsigned long) &linuxdev_info,
},
@@ -3385,74 +3947,83 @@ static const struct usb_device_id products [] = {
* Same idea as above, but different framing.
*
* PXA-2xx based models are also lying-about-cdc.
+ * Some models don't even tell the same lies ...
+ *
+ * NOTE: OpenZaurus versions with 2.6 kernels won't use these entries,
+ * unlike the older ones with 2.4 "embedix" kernels.
*
* NOTE: These entries do double-duty, serving as blacklist entries
* whenever Zaurus support isn't enabled, but CDC Ethernet is.
*/
+#define ZAURUS_MASTER_INTERFACE \
+ .bInterfaceClass = USB_CLASS_COMM, \
+ .bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET, \
+ .bInterfaceProtocol = USB_CDC_PROTO_NONE
{
.match_flags = USB_DEVICE_ID_MATCH_INT_INFO
| USB_DEVICE_ID_MATCH_DEVICE,
.idVendor = 0x04DD,
.idProduct = 0x8004,
- /* match the master interface */
- .bInterfaceClass = USB_CLASS_COMM,
- .bInterfaceSubClass = 6 /* Ethernet model */,
- .bInterfaceProtocol = 0,
+ ZAURUS_MASTER_INTERFACE,
.driver_info = ZAURUS_STRONGARM_INFO,
}, {
.match_flags = USB_DEVICE_ID_MATCH_INT_INFO
| USB_DEVICE_ID_MATCH_DEVICE,
.idVendor = 0x04DD,
.idProduct = 0x8005, /* A-300 */
- .bInterfaceClass = USB_CLASS_COMM,
- .bInterfaceSubClass = 6 /* Ethernet model */,
- .bInterfaceProtocol = 0x00,
+ ZAURUS_MASTER_INTERFACE,
.driver_info = ZAURUS_PXA_INFO,
}, {
.match_flags = USB_DEVICE_ID_MATCH_INT_INFO
| USB_DEVICE_ID_MATCH_DEVICE,
.idVendor = 0x04DD,
.idProduct = 0x8006, /* B-500/SL-5600 */
- .bInterfaceClass = USB_CLASS_COMM,
- .bInterfaceSubClass = 6 /* Ethernet model */,
- .bInterfaceProtocol = 0x00,
+ ZAURUS_MASTER_INTERFACE,
.driver_info = ZAURUS_PXA_INFO,
}, {
.match_flags = USB_DEVICE_ID_MATCH_INT_INFO
| USB_DEVICE_ID_MATCH_DEVICE,
.idVendor = 0x04DD,
.idProduct = 0x8007, /* C-700 */
- .bInterfaceClass = USB_CLASS_COMM,
- .bInterfaceSubClass = 6 /* Ethernet model */,
- .bInterfaceProtocol = 0x00,
+ ZAURUS_MASTER_INTERFACE,
.driver_info = ZAURUS_PXA_INFO,
}, {
.match_flags = USB_DEVICE_ID_MATCH_INT_INFO
| USB_DEVICE_ID_MATCH_DEVICE,
.idVendor = 0x04DD,
.idProduct = 0x9031, /* C-750 C-760 */
- .bInterfaceClass = USB_CLASS_COMM,
- .bInterfaceSubClass = 6 /* Ethernet model */,
- .bInterfaceProtocol = 0x00,
+ ZAURUS_MASTER_INTERFACE,
.driver_info = ZAURUS_PXA_INFO,
}, {
.match_flags = USB_DEVICE_ID_MATCH_INT_INFO
| USB_DEVICE_ID_MATCH_DEVICE,
.idVendor = 0x04DD,
.idProduct = 0x9032, /* SL-6000 */
- .bInterfaceClass = USB_CLASS_COMM,
- .bInterfaceSubClass = 6 /* Ethernet model */,
- .bInterfaceProtocol = 0x00,
+ ZAURUS_MASTER_INTERFACE,
.driver_info = ZAURUS_PXA_INFO,
}, {
.match_flags = USB_DEVICE_ID_MATCH_INT_INFO
| USB_DEVICE_ID_MATCH_DEVICE,
.idVendor = 0x04DD,
+ /* reported with some C860 units */
.idProduct = 0x9050, /* C-860 */
- .bInterfaceClass = USB_CLASS_COMM,
- .bInterfaceSubClass = 6 /* Ethernet model */,
- .bInterfaceProtocol = 0x00,
+ ZAURUS_MASTER_INTERFACE,
.driver_info = ZAURUS_PXA_INFO,
+#ifdef CONFIG_USB_ZAURUS
+ /* at least some (reports vary) C-860 units have very different
+ * lies about their standards support.
+ */
+}, {
+ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
+ | USB_DEVICE_ID_MATCH_DEVICE,
+ .idVendor = 0x04DD,
+ /* reported with some C860 units */
+ .idProduct = 0x9031, /* C-860 */
+ .bInterfaceClass = USB_CLASS_COMM,
+ .bInterfaceSubClass = USB_CDC_SUBCLASS_MDLM,
+ .bInterfaceProtocol = USB_CDC_PROTO_NONE,
+ .driver_info = (unsigned long) &zaurus_pxa_mdlm_info,
+#endif
},
/* Olympus has some models with a Zaurus-compatible option.
@@ -3463,9 +4034,7 @@ static const struct usb_device_id products [] = {
| USB_DEVICE_ID_MATCH_DEVICE,
.idVendor = 0x07B4,
.idProduct = 0x0F02, /* R-1000 */
- .bInterfaceClass = USB_CLASS_COMM,
- .bInterfaceSubClass = 6 /* Ethernet model */,
- .bInterfaceProtocol = 0x00,
+ ZAURUS_MASTER_INTERFACE,
.driver_info = OLYMPUS_MXL_INFO,
},
#endif
@@ -3480,7 +4049,8 @@ static const struct usb_device_id products [] = {
* NOTE: this match must come AFTER entries working around
* bugs/quirks in a given product (like Zaurus, above).
*/
- USB_INTERFACE_INFO (USB_CLASS_COMM, 6 /* Ethernet model */, 0),
+ USB_INTERFACE_INFO (USB_CLASS_COMM, USB_CDC_SUBCLASS_ETHERNET,
+ USB_CDC_PROTO_NONE),
.driver_info = (unsigned long) &cdc_info,
},
#endif
@@ -3495,6 +4065,8 @@ static struct usb_driver usbnet_driver = {
.id_table = products,
.probe = usbnet_probe,
.disconnect = usbnet_disconnect,
+ .suspend = usbnet_suspend,
+ .resume = usbnet_resume,
};
/* Default ethtool_ops assigned. Devices can override in their bind() routine */
diff --git a/drivers/usb/net/zd1201.c b/drivers/usb/net/zd1201.c
new file mode 100644
index 0000000000000..938025e2c6469
--- /dev/null
+++ b/drivers/usb/net/zd1201.c
@@ -0,0 +1,1905 @@
+/*
+ * Driver for ZyDAS zd1201 based wireless USB devices.
+ *
+ * Copyright (c) 2004, 2005 Jeroen Vreeken (pe1rxq@amsat.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.
+ *
+ * Parts of this driver have been derived from a wlan-ng version
+ * modified by ZyDAS. They also made documentation available, thanks!
+ * Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved.
+ */
+
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/wireless.h>
+#include <net/iw_handler.h>
+#include <linux/string.h>
+#include <linux/if_arp.h>
+#include <linux/firmware.h>
+#include <ieee802_11.h>
+#include "zd1201.h"
+
+static struct usb_device_id zd1201_table[] = {
+ {USB_DEVICE(0x0586, 0x3400)}, /* Peabird Wireless USB Adapter */
+ {USB_DEVICE(0x0ace, 0x1201)}, /* ZyDAS ZD1201 Wireless USB Adapter */
+ {USB_DEVICE(0x050d, 0x6051)}, /* Belkin F5D6051 usb adapter */
+ {USB_DEVICE(0x0db0, 0x6823)}, /* MSI UB11B usb adapter */
+ {}
+};
+
+static int ap = 0; /* Are we an AP or a normal station? */
+
+#define ZD1201_VERSION "0.15"
+
+MODULE_AUTHOR("Jeroen Vreeken <pe1rxq@amsat.org>");
+MODULE_DESCRIPTION("Driver for ZyDAS ZD1201 based USB Wireless adapters");
+MODULE_VERSION(ZD1201_VERSION);
+MODULE_LICENSE("GPL");
+module_param(ap, int, 0);
+MODULE_PARM_DESC(ap, "If non-zero Access Point firmware will be loaded");
+MODULE_DEVICE_TABLE(usb, zd1201_table);
+
+
+int zd1201_fw_upload(struct usb_device *dev, int apfw)
+{
+ const struct firmware *fw_entry;
+ char* data;
+ unsigned long len;
+ int err;
+ unsigned char ret;
+ char *buf;
+ char *fwfile;
+
+ if (apfw)
+ fwfile = "zd1201-ap.fw";
+ else
+ fwfile = "zd1201.fw";
+
+ err = request_firmware(&fw_entry, fwfile, &dev->dev);
+ if (err) {
+ dev_err(&dev->dev, "Failed to load %s firmware file!\n", fwfile);
+ dev_err(&dev->dev, "Make sure the hotplug firmware loader is installed.\n");
+ dev_err(&dev->dev, "Goto http://linux-lc100020.sourceforge.net for more info\n");
+ return err;
+ }
+
+ data = fw_entry->data;
+ len = fw_entry->size;
+
+ buf = kmalloc(1024, GFP_ATOMIC);
+ if (!buf)
+ goto exit;
+
+ while (len > 0) {
+ int translen = (len > 1024) ? 1024 : len;
+ memcpy(buf, data, translen);
+
+ err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 0,
+ USB_DIR_OUT | 0x40, 0, 0, buf, translen,
+ ZD1201_FW_TIMEOUT);
+ if (err < 0)
+ goto exit;
+
+ len -= translen;
+ data += translen;
+ }
+
+ err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 0x2,
+ USB_DIR_OUT | 0x40, 0, 0, NULL, 0, ZD1201_FW_TIMEOUT);
+ if (err < 0)
+ goto exit;
+
+ err = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), 0x4,
+ USB_DIR_IN | 0x40, 0,0, &ret, sizeof(ret), ZD1201_FW_TIMEOUT);
+ if (err < 0)
+ goto exit;
+
+ if (ret & 0x80) {
+ err = -EIO;
+ goto exit;
+ }
+
+ err = 0;
+exit:
+ if (buf)
+ kfree(buf);
+ release_firmware(fw_entry);
+ return err;
+}
+
+void zd1201_usbfree(struct urb *urb, struct pt_regs *regs)
+{
+ struct zd1201 *zd = urb->context;
+
+ switch(urb->status) {
+ case -EILSEQ:
+ case -ENODEV:
+ case -ETIMEDOUT:
+ case -ENOENT:
+ case -EPIPE:
+ case -EOVERFLOW:
+ case -ESHUTDOWN:
+ dev_warn(&zd->usb->dev, "%s: urb failed: %d\n",
+ zd->dev->name, urb->status);
+ }
+
+ kfree(urb->transfer_buffer);
+ usb_free_urb(urb);
+ return;
+}
+
+/* cmdreq message:
+ u32 type
+ u16 cmd
+ u16 parm0
+ u16 parm1
+ u16 parm2
+ u8 pad[4]
+
+ total: 4 + 2 + 2 + 2 + 2 + 4 = 16
+*/
+int zd1201_docmd(struct zd1201 *zd, int cmd, int parm0, int parm1, int parm2)
+{
+ unsigned char *command;
+ int ret;
+ struct urb *urb;
+
+ command = kmalloc(16, GFP_ATOMIC);
+ if (!command)
+ return -ENOMEM;
+
+ *((__le32*)command) = cpu_to_le32(ZD1201_USB_CMDREQ);
+ *((__le16*)&command[4]) = cpu_to_le16(cmd);
+ *((__le16*)&command[6]) = cpu_to_le16(parm0);
+ *((__le16*)&command[8]) = cpu_to_le16(parm1);
+ *((__le16*)&command[10])= cpu_to_le16(parm2);
+
+ urb = usb_alloc_urb(0, GFP_ATOMIC);
+ if (!urb) {
+ kfree(command);
+ return -ENOMEM;
+ }
+ usb_fill_bulk_urb(urb, zd->usb, usb_sndbulkpipe(zd->usb, zd->endp_out2),
+ command, 16, zd1201_usbfree, zd);
+ ret = usb_submit_urb(urb, GFP_ATOMIC);
+ if (ret) {
+ kfree(command);
+ usb_free_urb(urb);
+ }
+
+ return ret;
+}
+
+/* Callback after sending out a packet */
+void zd1201_usbtx(struct urb *urb, struct pt_regs *regs)
+{
+ struct zd1201 *zd = urb->context;
+ netif_wake_queue(zd->dev);
+ return;
+}
+
+/* Incomming data */
+void zd1201_usbrx(struct urb *urb, struct pt_regs *regs)
+{
+ struct zd1201 *zd = urb->context;
+ int free = 0;
+ unsigned char *data = urb->transfer_buffer;
+ struct sk_buff *skb;
+ unsigned char type;
+
+ if (!zd) {
+ free = 1;
+ goto exit;
+ }
+
+ switch(urb->status) {
+ case -EILSEQ:
+ case -ENODEV:
+ case -ETIMEDOUT:
+ case -ENOENT:
+ case -EPIPE:
+ case -EOVERFLOW:
+ case -ESHUTDOWN:
+ dev_warn(&zd->usb->dev, "%s: rx urb failed: %d\n",
+ zd->dev->name, urb->status);
+ free = 1;
+ goto exit;
+ }
+
+ if (urb->status != 0 || urb->actual_length == 0)
+ goto resubmit;
+
+ type = data[0];
+ if (type == ZD1201_PACKET_EVENTSTAT || type == ZD1201_PACKET_RESOURCE) {
+ memcpy(zd->rxdata, data, urb->actual_length);
+ zd->rxlen = urb->actual_length;
+ zd->rxdatas = 1;
+ wake_up(&zd->rxdataq);
+ }
+ /* Info frame */
+ if (type == ZD1201_PACKET_INQUIRE) {
+ int i = 0;
+ unsigned short infotype, framelen, copylen;
+ framelen = le16_to_cpu(*(__le16*)&data[4]);
+ infotype = le16_to_cpu(*(__le16*)&data[6]);
+
+ if (infotype == ZD1201_INF_LINKSTATUS) {
+ short linkstatus;
+
+ linkstatus = le16_to_cpu(*(__le16*)&data[8]);
+ switch(linkstatus) {
+ case 1:
+ netif_carrier_on(zd->dev);
+ break;
+ case 2:
+ netif_carrier_off(zd->dev);
+ break;
+ case 3:
+ netif_carrier_off(zd->dev);
+ break;
+ case 4:
+ netif_carrier_on(zd->dev);
+ break;
+ default:
+ netif_carrier_off(zd->dev);
+ }
+ goto resubmit;
+ }
+ if (infotype == ZD1201_INF_ASSOCSTATUS) {
+ short status = le16_to_cpu(*(__le16*)(data+8));
+ int event;
+ union iwreq_data wrqu;
+
+ switch (status) {
+ case ZD1201_ASSOCSTATUS_STAASSOC:
+ case ZD1201_ASSOCSTATUS_REASSOC:
+ event = IWEVREGISTERED;
+ break;
+ case ZD1201_ASSOCSTATUS_DISASSOC:
+ case ZD1201_ASSOCSTATUS_ASSOCFAIL:
+ case ZD1201_ASSOCSTATUS_AUTHFAIL:
+ default:
+ event = IWEVEXPIRED;
+ }
+ memcpy(wrqu.addr.sa_data, data+10, ETH_ALEN);
+ wrqu.addr.sa_family = ARPHRD_ETHER;
+
+ /* Send event to user space */
+ wireless_send_event(zd->dev, event, &wrqu, NULL);
+
+ goto resubmit;
+ }
+ if (infotype == ZD1201_INF_AUTHREQ) {
+ union iwreq_data wrqu;
+
+ memcpy(wrqu.addr.sa_data, data+8, ETH_ALEN);
+ wrqu.addr.sa_family = ARPHRD_ETHER;
+ /* There isn't a event that trully fits this request.
+ We assume that userspace will be smart enough to
+ see a new station being expired and sends back a
+ authstation ioctl to authorize it. */
+ wireless_send_event(zd->dev, IWEVEXPIRED, &wrqu, NULL);
+ goto resubmit;
+ }
+ /* Other infotypes are handled outside this handler */
+ zd->rxlen = 0;
+ while (i < urb->actual_length) {
+ copylen = le16_to_cpu(*(__le16*)&data[i+2]);
+ /* Sanity check, sometimes we get junk */
+ if (copylen+zd->rxlen > sizeof(zd->rxdata))
+ break;
+ memcpy(zd->rxdata+zd->rxlen, data+i+4, copylen);
+ zd->rxlen += copylen;
+ i += 64;
+ }
+ if (i >= urb->actual_length) {
+ zd->rxdatas = 1;
+ wake_up(&zd->rxdataq);
+ }
+ goto resubmit;
+ }
+ /* Actual data */
+ if (data[urb->actual_length-1] == ZD1201_PACKET_RXDATA) {
+ int datalen = urb->actual_length-1;
+ unsigned short len, fc, seq;
+ struct hlist_node *node;
+
+ len = ntohs(*(__be16 *)&data[datalen-2]);
+ if (len>datalen)
+ len=datalen;
+ fc = le16_to_cpu(*(__le16 *)&data[datalen-16]);
+ seq = le16_to_cpu(*(__le16 *)&data[datalen-24]);
+
+ if(zd->monitor) {
+ if (datalen < 24)
+ goto resubmit;
+ if (!(skb = dev_alloc_skb(datalen+24)))
+ goto resubmit;
+
+ memcpy(skb_put(skb, 2), &data[datalen-16], 2);
+ memcpy(skb_put(skb, 2), &data[datalen-2], 2);
+ memcpy(skb_put(skb, 6), &data[datalen-14], 6);
+ memcpy(skb_put(skb, 6), &data[datalen-22], 6);
+ memcpy(skb_put(skb, 6), &data[datalen-8], 6);
+ memcpy(skb_put(skb, 2), &data[datalen-24], 2);
+ memcpy(skb_put(skb, len), data, len);
+ skb->dev = zd->dev;
+ skb->dev->last_rx = jiffies;
+ skb->protocol = eth_type_trans(skb, zd->dev);
+ zd->stats.rx_packets++;
+ zd->stats.rx_bytes += skb->len;
+ netif_rx(skb);
+ goto resubmit;
+ }
+
+ if ((seq & IEEE802_11_SCTL_FRAG) ||
+ (fc & IEEE802_11_FCTL_MOREFRAGS)) {
+ struct zd1201_frag *frag = NULL;
+ char *ptr;
+
+ if (datalen<14)
+ goto resubmit;
+ if ((seq & IEEE802_11_SCTL_FRAG) == 0) {
+ frag = kmalloc(sizeof(struct zd1201_frag*),
+ GFP_ATOMIC);
+ if (!frag)
+ goto resubmit;
+ skb = dev_alloc_skb(IEEE802_11_DATA_LEN +14+2);
+ if (!skb) {
+ kfree(frag);
+ goto resubmit;
+ }
+ frag->skb = skb;
+ frag->seq = seq & IEEE802_11_SCTL_SEQ;
+ skb_reserve(skb, 2);
+ memcpy(skb_put(skb, 12), &data[datalen-14], 12);
+ memcpy(skb_put(skb, 2), &data[6], 2);
+ memcpy(skb_put(skb, len), data+8, len);
+ hlist_add_head(&frag->fnode, &zd->fraglist);
+ goto resubmit;
+ }
+ hlist_for_each_entry(frag, node, &zd->fraglist, fnode)
+ if(frag->seq == (seq&IEEE802_11_SCTL_SEQ))
+ break;
+ if (!frag)
+ goto resubmit;
+ skb = frag->skb;
+ ptr = skb_put(skb, len);
+ if (ptr)
+ memcpy(ptr, data+8, len);
+ if (fc & IEEE802_11_FCTL_MOREFRAGS)
+ goto resubmit;
+ hlist_del_init(&frag->fnode);
+ kfree(frag);
+ /* Fallthrough */
+ } else {
+ if (datalen<14)
+ goto resubmit;
+ skb = dev_alloc_skb(len + 14 + 2);
+ if (!skb)
+ goto resubmit;
+ skb_reserve(skb, 2);
+ memcpy(skb_put(skb, 12), &data[datalen-14], 12);
+ memcpy(skb_put(skb, 2), &data[6], 2);
+ memcpy(skb_put(skb, len), data+8, len);
+ }
+ skb->dev = zd->dev;
+ skb->dev->last_rx = jiffies;
+ skb->protocol = eth_type_trans(skb, zd->dev);
+ zd->stats.rx_packets++;
+ zd->stats.rx_bytes += skb->len;
+ netif_rx(skb);
+ }
+resubmit:
+ memset(data, 0, ZD1201_RXSIZE);
+
+ urb->status = 0;
+ urb->dev = zd->usb;
+ if(usb_submit_urb(urb, GFP_ATOMIC))
+ free = 1;
+
+exit:
+ if (free) {
+ zd->rxlen = 0;
+ zd->rxdatas = 1;
+ wake_up(&zd->rxdataq);
+ kfree(urb->transfer_buffer);
+ }
+ return;
+}
+
+static int zd1201_getconfig(struct zd1201 *zd, int rid, void *riddata,
+ unsigned int riddatalen)
+{
+ int err;
+ int i = 0;
+ int code;
+ int rid_fid;
+ int length;
+ unsigned char *pdata;
+
+ zd->rxdatas = 0;
+ err = zd1201_docmd(zd, ZD1201_CMDCODE_ACCESS, rid, 0, 0);
+ if (err)
+ return err;
+
+ wait_event_interruptible(zd->rxdataq, zd->rxdatas);
+ if (!zd->rxlen)
+ return -EIO;
+
+ code = le16_to_cpu(*(__le16*)(&zd->rxdata[4]));
+ rid_fid = le16_to_cpu(*(__le16*)(&zd->rxdata[6]));
+ length = le16_to_cpu(*(__le16*)(&zd->rxdata[8]));
+ if (length > zd->rxlen)
+ length = zd->rxlen-6;
+
+ /* If access bit is not on, then error */
+ if ((code & ZD1201_ACCESSBIT) != ZD1201_ACCESSBIT || rid_fid != rid )
+ return -EINVAL;
+
+ /* Not enough buffer for allocating data */
+ if (riddatalen != (length - 4)) {
+ dev_dbg(&zd->usb->dev, "riddatalen mismatches, expected=%u, (packet=%u) length=%u, rid=0x%04X, rid_fid=0x%04X\n",
+ riddatalen, zd->rxlen, length, rid, rid_fid);
+ return -ENODATA;
+ }
+
+ zd->rxdatas = 0;
+ /* Issue SetRxRid commnd */
+ err = zd1201_docmd(zd, ZD1201_CMDCODE_SETRXRID, rid, 0, length);
+ if (err)
+ return err;
+
+ /* Receive RID record from resource packets */
+ wait_event_interruptible(zd->rxdataq, zd->rxdatas);
+ if (!zd->rxlen)
+ return -EIO;
+
+ if (zd->rxdata[zd->rxlen - 1] != ZD1201_PACKET_RESOURCE) {
+ dev_dbg(&zd->usb->dev, "Packet type mismatch: 0x%x not 0x3\n",
+ zd->rxdata[zd->rxlen-1]);
+ return -EINVAL;
+ }
+
+ /* Set the data pointer and received data length */
+ pdata = zd->rxdata;
+ length = zd->rxlen;
+
+ do {
+ int actual_length;
+
+ actual_length = (length > 64) ? 64 : length;
+
+ if(pdata[0] != 0x3) {
+ dev_dbg(&zd->usb->dev, "Rx Resource packet type error: %02X\n",
+ pdata[0]);
+ return -EINVAL;
+ }
+
+ if (actual_length != 64) {
+ /* Trim the last packet type byte */
+ actual_length--;
+ }
+
+ /* Skip the 4 bytes header (RID length and RID) */
+ if(i == 0) {
+ pdata += 8;
+ actual_length -= 8;
+ }
+ else {
+ pdata += 4;
+ actual_length -= 4;
+ }
+
+ memcpy(riddata, pdata, actual_length);
+ riddata += actual_length;
+ pdata += actual_length;
+ length -= 64;
+ i++;
+ } while (length > 0);
+
+ return 0;
+}
+
+/*
+ * resreq:
+ * byte type
+ * byte sequence
+ * u16 reserved
+ * byte data[12]
+ * total: 16
+ */
+static int zd1201_setconfig(struct zd1201 *zd, int rid, void *buf, int len, int wait)
+{
+ int err;
+ unsigned char *request;
+ int reqlen;
+ char seq=0;
+ struct urb *urb;
+ unsigned int gfp_mask = wait ? GFP_NOIO : GFP_ATOMIC;
+
+ len += 4; /* first 4 are for header */
+
+ zd->rxdatas = 0;
+ zd->rxlen = 0;
+ for (seq=0; len > 0; seq++) {
+ request = kmalloc(16, gfp_mask);
+ if (!request)
+ return -ENOMEM;
+ urb = usb_alloc_urb(0, gfp_mask);
+ if (!urb) {
+ kfree(request);
+ return -ENOMEM;
+ }
+ memset(request, 0, 16);
+ reqlen = len>12 ? 12 : len;
+ request[0] = ZD1201_USB_RESREQ;
+ request[1] = seq;
+ request[2] = 0;
+ request[3] = 0;
+ if (request[1] == 0) {
+ /* add header */
+ *(__le16*)&request[4] = cpu_to_le16((len-2+1)/2);
+ *(__le16*)&request[6] = cpu_to_le16(rid);
+ memcpy(request+8, buf, reqlen-4);
+ buf += reqlen-4;
+ } else {
+ memcpy(request+4, buf, reqlen);
+ buf += reqlen;
+ }
+
+ len -= reqlen;
+
+ usb_fill_bulk_urb(urb, zd->usb, usb_sndbulkpipe(zd->usb,
+ zd->endp_out2), request, 16, zd1201_usbfree, zd);
+ err = usb_submit_urb(urb, gfp_mask);
+ if (err)
+ goto err;
+ }
+
+ request = kmalloc(16, gfp_mask);
+ if (!request)
+ return -ENOMEM;
+ urb = usb_alloc_urb(0, gfp_mask);
+ if (!urb) {
+ kfree(request);
+ return -ENOMEM;
+ }
+ *((__le32*)request) = cpu_to_le32(ZD1201_USB_CMDREQ);
+ *((__le16*)&request[4]) =
+ cpu_to_le16(ZD1201_CMDCODE_ACCESS|ZD1201_ACCESSBIT);
+ *((__le16*)&request[6]) = cpu_to_le16(rid);
+ *((__le16*)&request[8]) = cpu_to_le16(0);
+ *((__le16*)&request[10]) = cpu_to_le16(0);
+ usb_fill_bulk_urb(urb, zd->usb, usb_sndbulkpipe(zd->usb, zd->endp_out2),
+ request, 16, zd1201_usbfree, zd);
+ err = usb_submit_urb(urb, gfp_mask);
+ if (err)
+ goto err;
+
+ if (wait) {
+ wait_event_interruptible(zd->rxdataq, zd->rxdatas);
+ if (!zd->rxlen || le16_to_cpu(*(__le16*)&zd->rxdata[6]) != rid) {
+ dev_dbg(&zd->usb->dev, "wrong or no RID received\n");
+ }
+ }
+
+ return 0;
+err:
+ kfree(request);
+ usb_free_urb(urb);
+ return err;
+}
+
+static inline int zd1201_getconfig16(struct zd1201 *zd, int rid, short *val)
+{
+ int err;
+ __le16 zdval;
+
+ err = zd1201_getconfig(zd, rid, &zdval, sizeof(__le16));
+ if (err)
+ return err;
+ *val = le16_to_cpu(zdval);
+ return 0;
+}
+
+static inline int zd1201_setconfig16(struct zd1201 *zd, int rid, short val)
+{
+ __le16 zdval = cpu_to_le16(val);
+ return (zd1201_setconfig(zd, rid, &zdval, sizeof(__le16), 1));
+}
+
+int zd1201_drvr_start(struct zd1201 *zd)
+{
+ int err, i;
+ short max;
+ __le16 zdmax;
+ unsigned char *buffer;
+
+ buffer = kmalloc(ZD1201_RXSIZE, GFP_KERNEL);
+ if (!buffer)
+ return -ENOMEM;
+ memset(buffer, 0, ZD1201_RXSIZE);
+
+ usb_fill_bulk_urb(zd->rx_urb, zd->usb,
+ usb_rcvbulkpipe(zd->usb, zd->endp_in), buffer, ZD1201_RXSIZE,
+ zd1201_usbrx, zd);
+
+ err = usb_submit_urb(zd->rx_urb, GFP_KERNEL);
+ if (err)
+ goto err_buffer;
+
+ err = zd1201_docmd(zd, ZD1201_CMDCODE_INIT, 0, 0, 0);
+ if (err)
+ goto err_urb;
+
+ err = zd1201_getconfig(zd, ZD1201_RID_CNFMAXTXBUFFERNUMBER, &zdmax,
+ sizeof(__le16));
+ if (err)
+ goto err_urb;
+
+ max = le16_to_cpu(zdmax);
+ for (i=0; i<max; i++) {
+ err = zd1201_docmd(zd, ZD1201_CMDCODE_ALLOC, 1514, 0, 0);
+ if (err)
+ goto err_urb;
+ }
+
+ return 0;
+
+err_urb:
+ usb_kill_urb(zd->rx_urb);
+ return err;
+err_buffer:
+ kfree(buffer);
+ return err;
+}
+
+/* Magic alert: The firmware doesn't seem to like the MAC state being
+ * toggled in promisc (aka monitor) mode.
+ * (It works a number of times, but will halt eventually)
+ * So we turn it of before disabling and on after enabling if needed.
+ */
+static int zd1201_enable(struct zd1201 *zd)
+{
+ int err;
+
+ if (zd->mac_enabled)
+ return 0;
+
+ err = zd1201_docmd(zd, ZD1201_CMDCODE_ENABLE, 0, 0, 0);
+ if (!err)
+ zd->mac_enabled = 1;
+
+ if (zd->monitor)
+ err = zd1201_setconfig16(zd, ZD1201_RID_PROMISCUOUSMODE, 1);
+
+ return err;
+}
+
+static int zd1201_disable(struct zd1201 *zd)
+{
+ int err;
+
+ if (!zd->mac_enabled)
+ return 0;
+ if (zd->monitor) {
+ err = zd1201_setconfig16(zd, ZD1201_RID_PROMISCUOUSMODE, 0);
+ if (err)
+ return err;
+ }
+
+ err = zd1201_docmd(zd, ZD1201_CMDCODE_DISABLE, 0, 0, 0);
+ if (!err)
+ zd->mac_enabled = 0;
+ return err;
+}
+
+static int zd1201_mac_reset(struct zd1201 *zd)
+{
+ if (!zd->mac_enabled)
+ return 0;
+ zd1201_disable(zd);
+ return zd1201_enable(zd);
+}
+
+static int zd1201_join(struct zd1201 *zd, char *essid, int essidlen)
+{
+ int err, val;
+ char buf[IW_ESSID_MAX_SIZE+2];
+
+ err = zd1201_disable(zd);
+ if (err)
+ return err;
+
+ val = ZD1201_CNFAUTHENTICATION_OPENSYSTEM;
+ val |= ZD1201_CNFAUTHENTICATION_SHAREDKEY;
+ err = zd1201_setconfig16(zd, ZD1201_RID_CNFAUTHENTICATION, val);
+ if (err)
+ return err;
+
+ *(__le16 *)buf = cpu_to_le16(essidlen);
+ memcpy(buf+2, essid, essidlen);
+ if (!zd->ap) { /* Normal station */
+ err = zd1201_setconfig(zd, ZD1201_RID_CNFDESIREDSSID, buf,
+ IW_ESSID_MAX_SIZE+2, 1);
+ if (err)
+ return err;
+ } else { /* AP */
+ err = zd1201_setconfig(zd, ZD1201_RID_CNFOWNSSID, buf,
+ IW_ESSID_MAX_SIZE+2, 1);
+ if (err)
+ return err;
+ }
+
+ err = zd1201_setconfig(zd, ZD1201_RID_CNFOWNMACADDR,
+ zd->dev->dev_addr, zd->dev->addr_len, 1);
+ if (err)
+ return err;
+
+ err = zd1201_enable(zd);
+ if (err)
+ return err;
+
+ msleep(100);
+ return 0;
+}
+
+static int zd1201_net_open(struct net_device *dev)
+{
+ struct zd1201 *zd = (struct zd1201 *)dev->priv;
+
+ /* Start MAC with wildcard if no essid set */
+ if (!zd->mac_enabled)
+ zd1201_join(zd, zd->essid, zd->essidlen);
+ netif_start_queue(dev);
+
+ return 0;
+}
+
+static int zd1201_net_stop(struct net_device *dev)
+{
+ netif_stop_queue(dev);
+
+ return 0;
+}
+
+/*
+ RFC 1042 encapsulates Ethernet frames in 802.11 frames
+ by prefixing them with 0xaa, 0xaa, 0x03) followed by a SNAP OID of 0
+ (0x00, 0x00, 0x00). Zd requires an additionnal padding, copy
+ of ethernet addresses, length of the standard RFC 1042 packet
+ and a command byte (which is nul for tx).
+
+ tx frame (from Wlan NG):
+ RFC 1042:
+ llc 0xAA 0xAA 0x03 (802.2 LLC)
+ snap 0x00 0x00 0x00 (Ethernet encapsulated)
+ type 2 bytes, Ethernet type field
+ payload (minus eth header)
+ Zydas specific:
+ padding 1B if (skb->len+8+1)%64==0
+ Eth MAC addr 12 bytes, Ethernet MAC addresses
+ length 2 bytes, RFC 1042 packet length
+ (llc+snap+type+payload)
+ zd 1 null byte, zd1201 packet type
+ */
+static int zd1201_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct zd1201 *zd = (struct zd1201 *)dev->priv;
+ unsigned char *txbuf = zd->txdata;
+ int txbuflen, pad = 0, err;
+ struct urb *urb = zd->tx_urb;
+
+ if (!zd->mac_enabled || zd->monitor) {
+ zd->stats.tx_dropped++;
+ kfree_skb(skb);
+ return 0;
+ }
+ netif_stop_queue(dev);
+
+ txbuflen = skb->len + 8 + 1;
+ if (txbuflen%64 == 0) {
+ pad = 1;
+ txbuflen++;
+ }
+ txbuf[0] = 0xAA;
+ txbuf[1] = 0xAA;
+ txbuf[2] = 0x03;
+ txbuf[3] = 0x00; /* rfc1042 */
+ txbuf[4] = 0x00;
+ txbuf[5] = 0x00;
+
+ memcpy(txbuf+6, skb->data+12, skb->len-12);
+ if (pad)
+ txbuf[skb->len-12+6]=0;
+ memcpy(txbuf+skb->len-12+6+pad, skb->data, 12);
+ *(__be16*)&txbuf[skb->len+6+pad] = htons(skb->len-12+6);
+ txbuf[txbuflen-1] = 0;
+
+ usb_fill_bulk_urb(urb, zd->usb, usb_sndbulkpipe(zd->usb, zd->endp_out),
+ txbuf, txbuflen, zd1201_usbtx, zd);
+
+ err = usb_submit_urb(zd->tx_urb, GFP_ATOMIC);
+ if (err) {
+ zd->stats.tx_errors++;
+ netif_start_queue(dev);
+ return err;
+ }
+ zd->stats.tx_packets++;
+ zd->stats.tx_bytes += skb->len;
+ dev->trans_start = jiffies;
+ kfree_skb(skb);
+
+ return 0;
+}
+
+static void zd1201_tx_timeout(struct net_device *dev)
+{
+ struct zd1201 *zd = (struct zd1201 *)dev->priv;
+
+ if (!zd)
+ return;
+ dev_warn(&zd->usb->dev, "%s: TX timeout, shooting down urb\n",
+ dev->name);
+ zd->tx_urb->transfer_flags |= URB_ASYNC_UNLINK;
+ usb_unlink_urb(zd->tx_urb);
+ zd->stats.tx_errors++;
+ /* Restart the timeout to quiet the watchdog: */
+ dev->trans_start = jiffies;
+}
+
+static int zd1201_set_mac_address(struct net_device *dev, void *p)
+{
+ struct sockaddr *addr = p;
+ struct zd1201 *zd = (struct zd1201 *)dev->priv;
+ int err;
+
+ if (!zd)
+ return -ENODEV;
+
+ err = zd1201_setconfig(zd, ZD1201_RID_CNFOWNMACADDR,
+ addr->sa_data, dev->addr_len, 1);
+ if (err)
+ return err;
+ memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
+
+ return zd1201_mac_reset(zd);
+}
+
+static struct net_device_stats *zd1201_get_stats(struct net_device *dev)
+{
+ struct zd1201 *zd = (struct zd1201 *)dev->priv;
+
+ return &zd->stats;
+}
+
+static struct iw_statistics *zd1201_get_wireless_stats(struct net_device *dev)
+{
+ struct zd1201 *zd = (struct zd1201 *)dev->priv;
+
+ return &zd->iwstats;
+}
+
+static void zd1201_set_multicast(struct net_device *dev)
+{
+ struct zd1201 *zd = (struct zd1201 *)dev->priv;
+ struct dev_mc_list *mc = dev->mc_list;
+ unsigned char reqbuf[ETH_ALEN*ZD1201_MAXMULTI];
+ int i;
+
+ if (dev->mc_count > ZD1201_MAXMULTI)
+ return;
+
+ for (i=0; i<dev->mc_count; i++) {
+ memcpy(reqbuf+i*ETH_ALEN, mc->dmi_addr, ETH_ALEN);
+ mc = mc->next;
+ }
+ zd1201_setconfig(zd, ZD1201_RID_CNFGROUPADDRESS, reqbuf,
+ dev->mc_count*ETH_ALEN, 0);
+
+}
+
+static int zd1201_config_commit(struct net_device *dev,
+ struct iw_request_info *info, struct iw_point *data, char *essid)
+{
+ struct zd1201 *zd = (struct zd1201 *)dev->priv;
+
+ return zd1201_mac_reset(zd);
+}
+
+static int zd1201_get_name(struct net_device *dev,
+ struct iw_request_info *info, char *name, char *extra)
+{
+ strcpy(name, "IEEE 802.11b");
+
+ return 0;
+}
+
+static int zd1201_set_freq(struct net_device *dev,
+ struct iw_request_info *info, struct iw_freq *freq, char *extra)
+{
+ struct zd1201 *zd = (struct zd1201 *)dev->priv;
+ short channel = 0;
+ int err;
+
+ if (freq->e == 0)
+ channel = freq->m;
+ else {
+ if (freq->m >= 2482)
+ channel = 14;
+ if (freq->m >= 2407)
+ channel = (freq->m-2407)/5;
+ }
+
+ err = zd1201_setconfig16(zd, ZD1201_RID_CNFOWNCHANNEL, channel);
+ if (err)
+ return err;
+
+ zd1201_mac_reset(zd);
+
+ return 0;
+}
+
+static int zd1201_get_freq(struct net_device *dev,
+ struct iw_request_info *info, struct iw_freq *freq, char *extra)
+{
+ struct zd1201 *zd = (struct zd1201 *)dev->priv;
+ short channel;
+ int err;
+
+ err = zd1201_getconfig16(zd, ZD1201_RID_CNFOWNCHANNEL, &channel);
+ if (err)
+ return err;
+ freq->e = 0;
+ freq->m = channel;
+
+ return 0;
+}
+
+static int zd1201_set_mode(struct net_device *dev,
+ struct iw_request_info *info, __u32 *mode, char *extra)
+{
+ struct zd1201 *zd = (struct zd1201 *)dev->priv;
+ short porttype, monitor = 0;
+ unsigned char buffer[IW_ESSID_MAX_SIZE+2];
+ int err;
+
+ if (zd->ap) {
+ if (*mode != IW_MODE_MASTER)
+ return -EINVAL;
+ return 0;
+ }
+
+ err = zd1201_setconfig16(zd, ZD1201_RID_PROMISCUOUSMODE, 0);
+ if (err)
+ return err;
+ zd->dev->type = ARPHRD_ETHER;
+ switch(*mode) {
+ case IW_MODE_MONITOR:
+ monitor = 1;
+ zd->dev->type = ARPHRD_IEEE80211;
+ /* Make sure we are no longer associated with by
+ setting an 'impossible' essid.
+ (otherwise we mess up firmware)
+ */
+ zd1201_join(zd, "\0-*#\0", 5);
+ /* Put port in pIBSS */
+ case 8: /* No pseudo-IBSS in wireless extensions (yet) */
+ porttype = ZD1201_PORTTYPE_PSEUDOIBSS;
+ break;
+ case IW_MODE_ADHOC:
+ porttype = ZD1201_PORTTYPE_IBSS;
+ break;
+ case IW_MODE_INFRA:
+ porttype = ZD1201_PORTTYPE_BSS;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ err = zd1201_setconfig16(zd, ZD1201_RID_CNFPORTTYPE, porttype);
+ if (err)
+ return err;
+ if (zd->monitor && !monitor) {
+ zd1201_disable(zd);
+ *(__le16 *)buffer = cpu_to_le16(zd->essidlen);
+ memcpy(buffer+2, zd->essid, zd->essidlen);
+ err = zd1201_setconfig(zd, ZD1201_RID_CNFDESIREDSSID,
+ buffer, IW_ESSID_MAX_SIZE+2, 1);
+ if (err)
+ return err;
+ }
+ zd->monitor=monitor;
+ /* If monitor mode is set we don't actually turn it on here since it
+ * is done during mac reset anyway (see zd1201_mac_enable).
+ */
+
+ zd1201_mac_reset(zd);
+
+ return 0;
+}
+
+static int zd1201_get_mode(struct net_device *dev,
+ struct iw_request_info *info, __u32 *mode, char *extra)
+{
+ struct zd1201 *zd = (struct zd1201 *)dev->priv;
+ short porttype;
+ int err;
+
+ err = zd1201_getconfig16(zd, ZD1201_RID_CNFPORTTYPE, &porttype);
+ if (err)
+ return err;
+ switch(porttype) {
+ case ZD1201_PORTTYPE_IBSS:
+ *mode = IW_MODE_ADHOC;
+ break;
+ case ZD1201_PORTTYPE_BSS:
+ *mode = IW_MODE_INFRA;
+ break;
+ case ZD1201_PORTTYPE_WDS:
+ *mode = IW_MODE_REPEAT;
+ break;
+ case ZD1201_PORTTYPE_PSEUDOIBSS:
+ *mode = 8;/* No Pseudo-IBSS... */
+ break;
+ case ZD1201_PORTTYPE_AP:
+ *mode = IW_MODE_MASTER;
+ break;
+ default:
+ dev_dbg(&zd->usb->dev, "Unknown porttype: %d\n",
+ porttype);
+ *mode = IW_MODE_AUTO;
+ }
+ if (zd->monitor)
+ *mode = IW_MODE_MONITOR;
+
+ return 0;
+}
+
+static int zd1201_get_range(struct net_device *dev,
+ struct iw_request_info *info, struct iw_point *wrq, char *extra)
+{
+ struct iw_range *range = (struct iw_range *)extra;
+
+ wrq->length = sizeof(struct iw_range);
+ memset(range, 0, sizeof(struct iw_range));
+ range->we_version_compiled = WIRELESS_EXT;
+ range->we_version_source = WIRELESS_EXT;
+
+ range->max_qual.qual = 128;
+ range->max_qual.level = 128;
+ range->max_qual.noise = 128;
+ range->max_qual.updated = 7;
+
+ range->encoding_size[0] = 5;
+ range->encoding_size[1] = 13;
+ range->num_encoding_sizes = 2;
+ range->max_encoding_tokens = ZD1201_NUMKEYS;
+
+ range->num_bitrates = 4;
+ range->bitrate[0] = 1000000;
+ range->bitrate[1] = 2000000;
+ range->bitrate[2] = 5500000;
+ range->bitrate[3] = 11000000;
+
+ range->min_rts = 0;
+ range->min_frag = ZD1201_FRAGMIN;
+ range->max_rts = ZD1201_RTSMAX;
+ range->min_frag = ZD1201_FRAGMAX;
+
+ return 0;
+}
+
+/* Little bit of magic here: we only get the quality if we poll
+ * for it, and we never get an actual request to trigger such
+ * a poll. Therefore we 'asume' that the user will soon ask for
+ * the stats after asking the bssid.
+ */
+static int zd1201_get_wap(struct net_device *dev,
+ struct iw_request_info *info, struct sockaddr *ap_addr, char *extra)
+{
+ struct zd1201 *zd = (struct zd1201 *)dev->priv;
+ unsigned char buffer[6];
+
+ if (!zd1201_getconfig(zd, ZD1201_RID_COMMSQUALITY, buffer, 6)) {
+ /* Unfortunatly the quality and noise reported is useless.
+ they seem to be accumulators that increase until you
+ read them, unless we poll on a fixed interval we can't
+ use them
+ */
+ /*zd->iwstats.qual.qual = le16_to_cpu(((__le16 *)buffer)[0]);*/
+ zd->iwstats.qual.level = le16_to_cpu(((__le16 *)buffer)[1]);
+ /*zd->iwstats.qual.noise = le16_to_cpu(((__le16 *)buffer)[2]);*/
+ zd->iwstats.qual.updated = 2;
+ }
+
+ return zd1201_getconfig(zd,ZD1201_RID_CURRENTBSSID,ap_addr->sa_data,6);
+}
+
+static int zd1201_set_scan(struct net_device *dev,
+ struct iw_request_info *info, struct iw_point *srq, char *extra)
+{
+ /* We do everything in get_scan */
+ return 0;
+}
+
+static int zd1201_get_scan(struct net_device *dev,
+ struct iw_request_info *info, struct iw_point *srq, char *extra)
+{
+ struct zd1201 *zd = (struct zd1201 *)dev->priv;
+ int err, i, j, enabled_save;
+ struct iw_event iwe;
+ char *cev = extra;
+ char *end_buf = extra + IW_SCAN_MAX_DATA;
+
+ /* No scanning in AP mode */
+ if (zd->ap)
+ return -EOPNOTSUPP;
+
+ /* Scan doesn't seem to work if disabled */
+ enabled_save = zd->mac_enabled;
+ zd1201_enable(zd);
+
+ zd->rxdatas = 0;
+ err = zd1201_docmd(zd, ZD1201_CMDCODE_INQUIRE,
+ ZD1201_INQ_SCANRESULTS, 0, 0);
+ if (err)
+ return err;
+
+ wait_event_interruptible(zd->rxdataq, zd->rxdatas);
+ if (!zd->rxlen)
+ return -EIO;
+
+ if (le16_to_cpu(*(__le16*)&zd->rxdata[2]) != ZD1201_INQ_SCANRESULTS)
+ return -EIO;
+
+ for(i=8; i<zd->rxlen; i+=62) {
+ iwe.cmd = SIOCGIWAP;
+ iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
+ memcpy(iwe.u.ap_addr.sa_data, zd->rxdata+i+6, 6);
+ cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_ADDR_LEN);
+
+ iwe.cmd = SIOCGIWESSID;
+ iwe.u.data.length = zd->rxdata[i+16];
+ iwe.u.data.flags = 1;
+ cev = iwe_stream_add_point(cev, end_buf, &iwe, zd->rxdata+i+18);
+
+ iwe.cmd = SIOCGIWMODE;
+ if (zd->rxdata[i+14]&0x01)
+ iwe.u.mode = IW_MODE_MASTER;
+ else
+ iwe.u.mode = IW_MODE_ADHOC;
+ cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_UINT_LEN);
+
+ iwe.cmd = SIOCGIWFREQ;
+ iwe.u.freq.m = zd->rxdata[i+0];
+ iwe.u.freq.e = 0;
+ cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_FREQ_LEN);
+
+ iwe.cmd = SIOCGIWRATE;
+ iwe.u.bitrate.fixed = 0;
+ iwe.u.bitrate.disabled = 0;
+ for (j=0; j<10; j++) if (zd->rxdata[i+50+j]) {
+ iwe.u.bitrate.value = (zd->rxdata[i+50+j]&0x7f)*500000;
+ cev=iwe_stream_add_event(cev, end_buf, &iwe,
+ IW_EV_PARAM_LEN);
+ }
+
+ iwe.cmd = SIOCGIWENCODE;
+ iwe.u.data.length = 0;
+ if (zd->rxdata[i+14]&0x10)
+ iwe.u.data.flags = IW_ENCODE_ENABLED;
+ else
+ iwe.u.data.flags = IW_ENCODE_DISABLED;
+ cev = iwe_stream_add_point(cev, end_buf, &iwe, NULL);
+
+ iwe.cmd = IWEVQUAL;
+ iwe.u.qual.qual = zd->rxdata[i+4];
+ iwe.u.qual.noise= zd->rxdata[i+2]/10-100;
+ iwe.u.qual.level = (256+zd->rxdata[i+4]*100)/255-100;
+ iwe.u.qual.updated = 7;
+ cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_QUAL_LEN);
+ }
+
+ if (!enabled_save)
+ zd1201_disable(zd);
+
+ srq->length = cev - extra;
+ srq->flags = 0;
+
+ return 0;
+}
+
+static int zd1201_set_essid(struct net_device *dev,
+ struct iw_request_info *info, struct iw_point *data, char *essid)
+{
+ struct zd1201 *zd = (struct zd1201 *)dev->priv;
+
+ if (data->length > IW_ESSID_MAX_SIZE)
+ return -EINVAL;
+ if (data->length < 1)
+ data->length = 1;
+ zd->essidlen = data->length-1;
+ memset(zd->essid, 0, IW_ESSID_MAX_SIZE+1);
+ memcpy(zd->essid, essid, data->length);
+ return zd1201_join(zd, zd->essid, zd->essidlen);
+}
+
+static int zd1201_get_essid(struct net_device *dev,
+ struct iw_request_info *info, struct iw_point *data, char *essid)
+{
+ struct zd1201 *zd = (struct zd1201 *)dev->priv;
+
+ memcpy(essid, zd->essid, zd->essidlen);
+ data->flags = 1;
+ data->length = zd->essidlen;
+
+ return 0;
+}
+
+static int zd1201_get_nick(struct net_device *dev, struct iw_request_info *info,
+ struct iw_point *data, char *nick)
+{
+ strcpy(nick, "zd1201");
+ data->flags = 1;
+ data->length = strlen(nick);
+ return 0;
+}
+
+static int zd1201_set_rate(struct net_device *dev,
+ struct iw_request_info *info, struct iw_param *rrq, char *extra)
+{
+ struct zd1201 *zd = (struct zd1201 *)dev->priv;
+ short rate;
+ int err;
+
+ switch (rrq->value) {
+ case 1000000:
+ rate = ZD1201_RATEB1;
+ break;
+ case 2000000:
+ rate = ZD1201_RATEB2;
+ break;
+ case 5500000:
+ rate = ZD1201_RATEB5;
+ break;
+ case 11000000:
+ default:
+ rate = ZD1201_RATEB11;
+ break;
+ }
+ if (!rrq->fixed) { /* Also enable all lower bitrates */
+ rate |= rate-1;
+ }
+
+ err = zd1201_setconfig16(zd, ZD1201_RID_TXRATECNTL, rate);
+ if (err)
+ return err;
+
+ return zd1201_mac_reset(zd);
+}
+
+static int zd1201_get_rate(struct net_device *dev,
+ struct iw_request_info *info, struct iw_param *rrq, char *extra)
+{
+ struct zd1201 *zd = (struct zd1201 *)dev->priv;
+ short rate;
+ int err;
+
+ err = zd1201_getconfig16(zd, ZD1201_RID_CURRENTTXRATE, &rate);
+ if (err)
+ return err;
+
+ switch(rate) {
+ case 1:
+ rrq->value = 1000000;
+ break;
+ case 2:
+ rrq->value = 2000000;
+ break;
+ case 5:
+ rrq->value = 5500000;
+ break;
+ case 11:
+ rrq->value = 11000000;
+ break;
+ default:
+ rrq->value = 0;
+ }
+ rrq->fixed = 0;
+ rrq->disabled = 0;
+
+ return 0;
+}
+
+static int zd1201_set_rts(struct net_device *dev, struct iw_request_info *info,
+ struct iw_param *rts, char *extra)
+{
+ struct zd1201 *zd = (struct zd1201 *)dev->priv;
+ int err;
+ short val = rts->value;
+
+ if (rts->disabled || !rts->fixed)
+ val = ZD1201_RTSMAX;
+ if (val > ZD1201_RTSMAX)
+ return -EINVAL;
+ if (val < 0)
+ return -EINVAL;
+
+ err = zd1201_setconfig16(zd, ZD1201_RID_CNFRTSTHRESHOLD, val);
+ if (err)
+ return err;
+ return zd1201_mac_reset(zd);
+}
+
+static int zd1201_get_rts(struct net_device *dev, struct iw_request_info *info,
+ struct iw_param *rts, char *extra)
+{
+ struct zd1201 *zd = (struct zd1201 *)dev->priv;
+ short rtst;
+ int err;
+
+ err = zd1201_getconfig16(zd, ZD1201_RID_CNFRTSTHRESHOLD, &rtst);
+ if (err)
+ return err;
+ rts->value = rtst;
+ rts->disabled = (rts->value == ZD1201_RTSMAX);
+ rts->fixed = 1;
+
+ return 0;
+}
+
+static int zd1201_set_frag(struct net_device *dev, struct iw_request_info *info,
+ struct iw_param *frag, char *extra)
+{
+ struct zd1201 *zd = (struct zd1201 *)dev->priv;
+ int err;
+ short val = frag->value;
+
+ if (frag->disabled || !frag->fixed)
+ val = ZD1201_FRAGMAX;
+ if (val > ZD1201_FRAGMAX)
+ return -EINVAL;
+ if (val < ZD1201_FRAGMIN)
+ return -EINVAL;
+ if (val & 1)
+ return -EINVAL;
+ err = zd1201_setconfig16(zd, ZD1201_RID_CNFFRAGTHRESHOLD, val);
+ if (err)
+ return err;
+ return zd1201_mac_reset(zd);
+}
+
+static int zd1201_get_frag(struct net_device *dev, struct iw_request_info *info,
+ struct iw_param *frag, char *extra)
+{
+ struct zd1201 *zd = (struct zd1201 *)dev->priv;
+ short fragt;
+ int err;
+
+ err = zd1201_getconfig16(zd, ZD1201_RID_CNFFRAGTHRESHOLD, &fragt);
+ if (err)
+ return err;
+ frag->value = fragt;
+ frag->disabled = (frag->value == ZD1201_FRAGMAX);
+ frag->fixed = 1;
+
+ return 0;
+}
+
+static int zd1201_set_retry(struct net_device *dev,
+ struct iw_request_info *info, struct iw_param *rrq, char *extra)
+{
+ return 0;
+}
+
+static int zd1201_get_retry(struct net_device *dev,
+ struct iw_request_info *info, struct iw_param *rrq, char *extra)
+{
+ return 0;
+}
+
+static int zd1201_set_encode(struct net_device *dev,
+ struct iw_request_info *info, struct iw_point *erq, char *key)
+{
+ struct zd1201 *zd = (struct zd1201 *)dev->priv;
+ short i;
+ int err, rid;
+
+ if (erq->length > ZD1201_MAXKEYLEN)
+ return -EINVAL;
+
+ i = (erq->flags & IW_ENCODE_INDEX)-1;
+ if (i == -1) {
+ err = zd1201_getconfig16(zd,ZD1201_RID_CNFDEFAULTKEYID,&i);
+ if (err)
+ return err;
+ } else {
+ err = zd1201_setconfig16(zd, ZD1201_RID_CNFDEFAULTKEYID, i);
+ if (err)
+ return err;
+ }
+
+ if (i < 0 || i >= ZD1201_NUMKEYS)
+ return -EINVAL;
+
+ rid = ZD1201_RID_CNFDEFAULTKEY0 + i;
+ err = zd1201_setconfig(zd, rid, key, erq->length, 1);
+ if (err)
+ return err;
+ zd->encode_keylen[i] = erq->length;
+ memcpy(zd->encode_keys[i], key, erq->length);
+
+ i=0;
+ if (!(erq->flags & IW_ENCODE_DISABLED & IW_ENCODE_MODE)) {
+ i |= 0x01;
+ zd->encode_enabled = 1;
+ } else
+ zd->encode_enabled = 0;
+ if (erq->flags & IW_ENCODE_RESTRICTED & IW_ENCODE_MODE) {
+ i |= 0x02;
+ zd->encode_restricted = 1;
+ } else
+ zd->encode_restricted = 0;
+ err = zd1201_setconfig16(zd, ZD1201_RID_CNFWEBFLAGS, i);
+ if (err)
+ return err;
+
+ if (zd->encode_enabled)
+ i = ZD1201_CNFAUTHENTICATION_SHAREDKEY;
+ else
+ i = ZD1201_CNFAUTHENTICATION_OPENSYSTEM;
+ err = zd1201_setconfig16(zd, ZD1201_RID_CNFAUTHENTICATION, i);
+ if (err)
+ return err;
+
+ return zd1201_mac_reset(zd);
+}
+
+static int zd1201_get_encode(struct net_device *dev,
+ struct iw_request_info *info, struct iw_point *erq, char *key)
+{
+ struct zd1201 *zd = (struct zd1201 *)dev->priv;
+ short i;
+ int err;
+
+ if (zd->encode_enabled)
+ erq->flags = IW_ENCODE_ENABLED;
+ else
+ erq->flags = IW_ENCODE_DISABLED;
+ if (zd->encode_restricted)
+ erq->flags |= IW_ENCODE_RESTRICTED;
+ else
+ erq->flags |= IW_ENCODE_OPEN;
+
+ i = (erq->flags & IW_ENCODE_INDEX) -1;
+ if (i == -1) {
+ err = zd1201_getconfig16(zd, ZD1201_RID_CNFDEFAULTKEYID, &i);
+ if (err)
+ return err;
+ }
+ if (i<0 || i>= ZD1201_NUMKEYS)
+ return -EINVAL;
+
+ erq->flags |= i+1;
+
+ erq->length = zd->encode_keylen[i];
+ memcpy(key, zd->encode_keys[i], erq->length);
+
+ return 0;
+}
+
+static int zd1201_set_power(struct net_device *dev,
+ struct iw_request_info *info, struct iw_param *vwrq, char *extra)
+{
+ struct zd1201 *zd = (struct zd1201 *)dev->priv;
+ short enabled, duration, level;
+ int err;
+
+ enabled = vwrq->disabled ? 0 : 1;
+ if (enabled) {
+ if (vwrq->flags & IW_POWER_PERIOD) {
+ duration = vwrq->value;
+ err = zd1201_setconfig16(zd,
+ ZD1201_RID_CNFMAXSLEEPDURATION, duration);
+ if (err)
+ return err;
+ goto out;
+ }
+ if (vwrq->flags & IW_POWER_TIMEOUT) {
+ err = zd1201_getconfig16(zd,
+ ZD1201_RID_CNFMAXSLEEPDURATION, &duration);
+ if (err)
+ return err;
+ level = vwrq->value * 4 / duration;
+ if (level > 4)
+ level = 4;
+ if (level < 0)
+ level = 0;
+ err = zd1201_setconfig16(zd, ZD1201_RID_CNFPMEPS,
+ level);
+ if (err)
+ return err;
+ goto out;
+ }
+ return -EINVAL;
+ }
+out:
+ err = zd1201_setconfig16(zd, ZD1201_RID_CNFPMENABLED, enabled);
+ if (err)
+ return err;
+
+ return 0;
+}
+
+static int zd1201_get_power(struct net_device *dev,
+ struct iw_request_info *info, struct iw_param *vwrq, char *extra)
+{
+ struct zd1201 *zd = (struct zd1201 *)dev->priv;
+ short enabled, level, duration;
+ int err;
+
+ err = zd1201_getconfig16(zd, ZD1201_RID_CNFPMENABLED, &enabled);
+ if (err)
+ return err;
+ err = zd1201_getconfig16(zd, ZD1201_RID_CNFPMEPS, &level);
+ if (err)
+ return err;
+ err = zd1201_getconfig16(zd, ZD1201_RID_CNFMAXSLEEPDURATION, &duration);
+ if (err)
+ return err;
+ vwrq->disabled = enabled ? 0 : 1;
+ if (vwrq->flags & IW_POWER_TYPE) {
+ if (vwrq->flags & IW_POWER_PERIOD) {
+ vwrq->value = duration;
+ vwrq->flags = IW_POWER_PERIOD;
+ } else {
+ vwrq->value = duration * level / 4;
+ vwrq->flags = IW_POWER_TIMEOUT;
+ }
+ }
+ if (vwrq->flags & IW_POWER_MODE) {
+ if (enabled && level)
+ vwrq->flags = IW_POWER_UNICAST_R;
+ else
+ vwrq->flags = IW_POWER_ALL_R;
+ }
+
+ return 0;
+}
+
+
+static const iw_handler zd1201_iw_handler[] =
+{
+ (iw_handler) zd1201_config_commit, /* SIOCSIWCOMMIT */
+ (iw_handler) zd1201_get_name, /* SIOCGIWNAME */
+ (iw_handler) NULL, /* SIOCSIWNWID */
+ (iw_handler) NULL, /* SIOCGIWNWID */
+ (iw_handler) zd1201_set_freq, /* SIOCSIWFREQ */
+ (iw_handler) zd1201_get_freq, /* SIOCGIWFREQ */
+ (iw_handler) zd1201_set_mode, /* SIOCSIWMODE */
+ (iw_handler) zd1201_get_mode, /* SIOCGIWMODE */
+ (iw_handler) NULL, /* SIOCSIWSENS */
+ (iw_handler) NULL, /* SIOCGIWSENS */
+ (iw_handler) NULL, /* SIOCSIWRANGE */
+ (iw_handler) zd1201_get_range, /* SIOCGIWRANGE */
+ (iw_handler) NULL, /* SIOCSIWPRIV */
+ (iw_handler) NULL, /* SIOCGIWPRIV */
+ (iw_handler) NULL, /* SIOCSIWSTATS */
+ (iw_handler) NULL, /* SIOCGIWSTATS */
+ (iw_handler) NULL, /* SIOCSIWSPY */
+ (iw_handler) NULL, /* SIOCGIWSPY */
+ (iw_handler) NULL, /* -- hole -- */
+ (iw_handler) NULL, /* -- hole -- */
+ (iw_handler) NULL/*zd1201_set_wap*/, /* SIOCSIWAP */
+ (iw_handler) zd1201_get_wap, /* SIOCGIWAP */
+ (iw_handler) NULL, /* -- hole -- */
+ (iw_handler) NULL, /* SIOCGIWAPLIST */
+ (iw_handler) zd1201_set_scan, /* SIOCSIWSCAN */
+ (iw_handler) zd1201_get_scan, /* SIOCGIWSCAN */
+ (iw_handler) zd1201_set_essid, /* SIOCSIWESSID */
+ (iw_handler) zd1201_get_essid, /* SIOCGIWESSID */
+ (iw_handler) NULL, /* SIOCSIWNICKN */
+ (iw_handler) zd1201_get_nick, /* SIOCGIWNICKN */
+ (iw_handler) NULL, /* -- hole -- */
+ (iw_handler) NULL, /* -- hole -- */
+ (iw_handler) zd1201_set_rate, /* SIOCSIWRATE */
+ (iw_handler) zd1201_get_rate, /* SIOCGIWRATE */
+ (iw_handler) zd1201_set_rts, /* SIOCSIWRTS */
+ (iw_handler) zd1201_get_rts, /* SIOCGIWRTS */
+ (iw_handler) zd1201_set_frag, /* SIOCSIWFRAG */
+ (iw_handler) zd1201_get_frag, /* SIOCGIWFRAG */
+ (iw_handler) NULL, /* SIOCSIWTXPOW */
+ (iw_handler) NULL, /* SIOCGIWTXPOW */
+ (iw_handler) zd1201_set_retry, /* SIOCSIWRETRY */
+ (iw_handler) zd1201_get_retry, /* SIOCGIWRETRY */
+ (iw_handler) zd1201_set_encode, /* SIOCSIWENCODE */
+ (iw_handler) zd1201_get_encode, /* SIOCGIWENCODE */
+ (iw_handler) zd1201_set_power, /* SIOCSIWPOWER */
+ (iw_handler) zd1201_get_power, /* SIOCGIWPOWER */
+};
+
+static int zd1201_set_hostauth(struct net_device *dev,
+ struct iw_request_info *info, struct iw_param *rrq, char *extra)
+{
+ struct zd1201 *zd = (struct zd1201 *)dev->priv;
+ int err;
+
+ if (!zd->ap)
+ return -EOPNOTSUPP;
+
+ err = zd1201_setconfig16(zd, ZD1201_RID_CNFHOSTAUTH, rrq->value);
+ if (err)
+ return err;
+ return 0;
+}
+
+static int zd1201_get_hostauth(struct net_device *dev,
+ struct iw_request_info *info, struct iw_param *rrq, char *extra)
+{
+ struct zd1201 *zd = (struct zd1201 *)dev->priv;
+ short hostauth;
+ int err;
+
+ if (!zd->ap)
+ return -EOPNOTSUPP;
+
+ err = zd1201_getconfig16(zd, ZD1201_RID_CNFHOSTAUTH, &hostauth);
+ if (err)
+ return err;
+ rrq->value = hostauth;
+ rrq->fixed = 1;
+
+ return 0;
+}
+
+static int zd1201_auth_sta(struct net_device *dev,
+ struct iw_request_info *info, struct sockaddr *sta, char *extra)
+{
+ struct zd1201 *zd = (struct zd1201 *)dev->priv;
+ unsigned char buffer[10];
+
+ if (!zd->ap)
+ return -EOPNOTSUPP;
+
+ memcpy(buffer, sta->sa_data, ETH_ALEN);
+ *(short*)(buffer+6) = 0; /* 0==success, 1==failure */
+ *(short*)(buffer+8) = 0;
+
+ return zd1201_setconfig(zd, ZD1201_RID_AUTHENTICATESTA, buffer, 10, 1);
+}
+
+static int zd1201_set_maxassoc(struct net_device *dev,
+ struct iw_request_info *info, struct iw_param *rrq, char *extra)
+{
+ struct zd1201 *zd = (struct zd1201 *)dev->priv;
+ int err;
+
+ if (!zd->ap)
+ return -EOPNOTSUPP;
+
+ err = zd1201_setconfig16(zd, ZD1201_RID_CNFMAXASSOCSTATIONS, rrq->value);
+ if (err)
+ return err;
+ return 0;
+}
+
+static int zd1201_get_maxassoc(struct net_device *dev,
+ struct iw_request_info *info, struct iw_param *rrq, char *extra)
+{
+ struct zd1201 *zd = (struct zd1201 *)dev->priv;
+ short maxassoc;
+ int err;
+
+ if (!zd->ap)
+ return -EOPNOTSUPP;
+
+ err = zd1201_getconfig16(zd, ZD1201_RID_CNFMAXASSOCSTATIONS, &maxassoc);
+ if (err)
+ return err;
+ rrq->value = maxassoc;
+ rrq->fixed = 1;
+
+ return 0;
+}
+
+static const iw_handler zd1201_private_handler[] = {
+ (iw_handler) zd1201_set_hostauth, /* ZD1201SIWHOSTAUTH */
+ (iw_handler) zd1201_get_hostauth, /* ZD1201GIWHOSTAUTH */
+ (iw_handler) zd1201_auth_sta, /* ZD1201SIWAUTHSTA */
+ (iw_handler) NULL, /* nothing to get */
+ (iw_handler) zd1201_set_maxassoc, /* ZD1201SIMAXASSOC */
+ (iw_handler) zd1201_get_maxassoc, /* ZD1201GIMAXASSOC */
+};
+
+static const struct iw_priv_args zd1201_private_args[] = {
+ { ZD1201SIWHOSTAUTH, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ 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,
+ IW_PRIV_TYPE_NONE, "authstation" },
+ { ZD1201SIWMAXASSOC, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ IW_PRIV_TYPE_NONE, "setmaxassoc" },
+ { ZD1201GIWMAXASSOC, IW_PRIV_TYPE_NONE,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getmaxassoc" },
+};
+
+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),
+ .standard = (iw_handler *)zd1201_iw_handler,
+ .private = (iw_handler *)zd1201_private_handler,
+ .private_args = (struct iw_priv_args *) zd1201_private_args,
+};
+
+int zd1201_probe(struct usb_interface *interface, const struct usb_device_id *id)
+{
+ struct zd1201 *zd;
+ struct usb_device *usb;
+ int i, err;
+ short porttype;
+ char buf[IW_ESSID_MAX_SIZE+2];
+
+ usb = interface_to_usbdev(interface);
+
+ zd = kmalloc(sizeof(struct zd1201), GFP_KERNEL);
+ if (!zd) {
+ return -ENOMEM;
+ }
+ memset(zd, 0, sizeof(struct zd1201));
+ zd->ap = ap;
+ zd->usb = usb;
+ zd->removed = 0;
+ init_waitqueue_head(&zd->rxdataq);
+ INIT_HLIST_HEAD(&zd->fraglist);
+
+ err = zd1201_fw_upload(usb, zd->ap);
+ if (err) {
+ dev_err(&usb->dev, "zd1201 firmware upload failed: %d\n", err);
+ goto err_zd;
+ }
+
+ zd->endp_in = 1;
+ zd->endp_out = 1;
+ zd->endp_out2 = 2;
+ zd->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
+ zd->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!zd->rx_urb || !zd->tx_urb)
+ goto err_zd;
+
+ for(i = 0; i<100; i++)
+ udelay(1000);
+
+ err = zd1201_drvr_start(zd);
+ if (err)
+ goto err_zd;
+
+ err = zd1201_setconfig16(zd, ZD1201_RID_CNFMAXDATALEN, 2312);
+ if (err)
+ goto err_start;
+
+ err = zd1201_setconfig16(zd, ZD1201_RID_TXRATECNTL,
+ ZD1201_RATEB1 | ZD1201_RATEB2 | ZD1201_RATEB5 | ZD1201_RATEB11);
+ if (err)
+ goto err_start;
+
+ zd->dev = alloc_etherdev(0);
+ if (!zd->dev)
+ goto err_start;
+
+ zd->dev->priv = zd;
+ zd->dev->open = zd1201_net_open;
+ zd->dev->stop = zd1201_net_stop;
+ zd->dev->get_stats = zd1201_get_stats;
+ zd->dev->get_wireless_stats = zd1201_get_wireless_stats;
+ zd->dev->wireless_handlers =
+ (struct iw_handler_def *)&zd1201_iw_handlers;
+ zd->dev->hard_start_xmit = zd1201_hard_start_xmit;
+ zd->dev->watchdog_timeo = ZD1201_TX_TIMEOUT;
+ zd->dev->tx_timeout = zd1201_tx_timeout;
+ zd->dev->set_multicast_list = zd1201_set_multicast;
+ zd->dev->set_mac_address = zd1201_set_mac_address;
+ strcpy(zd->dev->name, "wlan%d");
+
+ err = zd1201_getconfig(zd, ZD1201_RID_CNFOWNMACADDR,
+ zd->dev->dev_addr, zd->dev->addr_len);
+ if (err)
+ goto err_net;
+
+ /* Set wildcard essid to match zd->essid */
+ *(__le16 *)buf = cpu_to_le16(0);
+ err = zd1201_setconfig(zd, ZD1201_RID_CNFDESIREDSSID, buf,
+ IW_ESSID_MAX_SIZE+2, 1);
+ if (err)
+ goto err_net;
+
+ if (zd->ap)
+ porttype = ZD1201_PORTTYPE_AP;
+ else
+ porttype = ZD1201_PORTTYPE_BSS;
+ err = zd1201_setconfig16(zd, ZD1201_RID_CNFPORTTYPE, porttype);
+ if (err)
+ goto err_net;
+
+ err = register_netdev(zd->dev);
+ if (err)
+ goto err_net;
+ dev_info(&usb->dev, "%s: ZD1201 USB Wireless interface\n",
+ zd->dev->name);
+
+ usb_set_intfdata(interface, zd);
+ return 0;
+
+err_net:
+ free_netdev(zd->dev);
+err_start:
+ /* Leave the device in reset state */
+ zd1201_docmd(zd, ZD1201_CMDCODE_INIT, 0, 0, 0);
+err_zd:
+ if (zd->tx_urb)
+ usb_free_urb(zd->tx_urb);
+ if (zd->rx_urb)
+ usb_free_urb(zd->rx_urb);
+ kfree(zd);
+ return err;
+}
+
+void zd1201_disconnect(struct usb_interface *interface)
+{
+ struct zd1201 *zd=(struct zd1201 *)usb_get_intfdata(interface);
+ struct hlist_node *node, *node2;
+ struct zd1201_frag *frag;
+
+ if (!zd)
+ return;
+ usb_set_intfdata(interface, NULL);
+ if (zd->dev) {
+ unregister_netdev(zd->dev);
+ free_netdev(zd->dev);
+ }
+
+ hlist_for_each_entry_safe(frag, node, node2, &zd->fraglist, fnode) {
+ hlist_del_init(&frag->fnode);
+ kfree_skb(frag->skb);
+ kfree(frag);
+ }
+
+ if (zd->tx_urb) {
+ usb_kill_urb(zd->tx_urb);
+ usb_free_urb(zd->tx_urb);
+ }
+ if (zd->rx_urb) {
+ usb_kill_urb(zd->rx_urb);
+ usb_free_urb(zd->rx_urb);
+ }
+ kfree(zd);
+}
+
+struct usb_driver zd1201_usb = {
+ .owner = THIS_MODULE,
+ .name = "zd1201",
+ .probe = zd1201_probe,
+ .disconnect = zd1201_disconnect,
+ .id_table = zd1201_table,
+};
+
+static int __init zd1201_init(void)
+{
+ return usb_register(&zd1201_usb);
+}
+
+static void __exit zd1201_cleanup(void)
+{
+ usb_deregister(&zd1201_usb);
+}
+
+module_init(zd1201_init);
+module_exit(zd1201_cleanup);
diff --git a/drivers/usb/net/zd1201.h b/drivers/usb/net/zd1201.h
new file mode 100644
index 0000000000000..1627c71e80525
--- /dev/null
+++ b/drivers/usb/net/zd1201.h
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2004, 2005 Jeroen Vreeken (pe1rxq@amsat.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.
+ *
+ * Parts of this driver have been derived from a wlan-ng version
+ * modified by ZyDAS.
+ * Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved.
+ */
+
+#ifndef _INCLUDE_ZD1201_H_
+#define _INCLUDE_ZD1201_H_
+
+#define ZD1201_NUMKEYS 4
+#define ZD1201_MAXKEYLEN 13
+#define ZD1201_MAXMULTI 16
+#define ZD1201_FRAGMAX 2500
+#define ZD1201_FRAGMIN 256
+#define ZD1201_RTSMAX 2500
+
+#define ZD1201_RXSIZE 3000
+
+struct zd1201 {
+ struct usb_device *usb;
+ int removed;
+ struct net_device *dev;
+ struct net_device_stats stats;
+ struct iw_statistics iwstats;
+
+ int endp_in;
+ int endp_out;
+ int endp_out2;
+ struct urb *rx_urb;
+ struct urb *tx_urb;
+
+ unsigned char rxdata[ZD1201_RXSIZE];
+ int rxlen;
+ wait_queue_head_t rxdataq;
+ int rxdatas;
+ struct hlist_head fraglist;
+ unsigned char txdata[ZD1201_RXSIZE];
+
+ int ap;
+ char essid[IW_ESSID_MAX_SIZE+1];
+ int essidlen;
+ int mac_enabled;
+ int monitor;
+ int encode_enabled;
+ int encode_restricted;
+ unsigned char encode_keys[ZD1201_NUMKEYS][ZD1201_MAXKEYLEN];
+ int encode_keylen[ZD1201_NUMKEYS];
+};
+
+struct zd1201_frag {
+ struct hlist_node fnode;
+ int seq;
+ struct sk_buff *skb;
+};
+
+#define ZD1201SIWHOSTAUTH SIOCIWFIRSTPRIV
+#define ZD1201GIWHOSTAUTH ZD1201SIWHOSTAUTH+1
+#define ZD1201SIWAUTHSTA SIOCIWFIRSTPRIV+2
+#define ZD1201SIWMAXASSOC SIOCIWFIRSTPRIV+4
+#define ZD1201GIWMAXASSOC ZD1201SIWMAXASSOC+1
+
+#define ZD1201_FW_TIMEOUT (1000)
+
+#define ZD1201_TX_TIMEOUT (2000)
+
+#define ZD1201_USB_CMDREQ 0
+#define ZD1201_USB_RESREQ 1
+
+#define ZD1201_CMDCODE_INIT 0x00
+#define ZD1201_CMDCODE_ENABLE 0x01
+#define ZD1201_CMDCODE_DISABLE 0x02
+#define ZD1201_CMDCODE_ALLOC 0x0a
+#define ZD1201_CMDCODE_INQUIRE 0x11
+#define ZD1201_CMDCODE_SETRXRID 0x17
+#define ZD1201_CMDCODE_ACCESS 0x21
+
+#define ZD1201_PACKET_EVENTSTAT 0x0
+#define ZD1201_PACKET_RXDATA 0x1
+#define ZD1201_PACKET_INQUIRE 0x2
+#define ZD1201_PACKET_RESOURCE 0x3
+
+#define ZD1201_ACCESSBIT 0x0100
+
+#define ZD1201_RID_CNFPORTTYPE 0xfc00
+#define ZD1201_RID_CNFOWNMACADDR 0xfc01
+#define ZD1201_RID_CNFDESIREDSSID 0xfc02
+#define ZD1201_RID_CNFOWNCHANNEL 0xfc03
+#define ZD1201_RID_CNFOWNSSID 0xfc04
+#define ZD1201_RID_CNFMAXDATALEN 0xfc07
+#define ZD1201_RID_CNFPMENABLED 0xfc09
+#define ZD1201_RID_CNFPMEPS 0xfc0a
+#define ZD1201_RID_CNFMAXSLEEPDURATION 0xfc0c
+#define ZD1201_RID_CNFDEFAULTKEYID 0xfc23
+#define ZD1201_RID_CNFDEFAULTKEY0 0xfc24
+#define ZD1201_RID_CNFDEFAULTKEY1 0xfc25
+#define ZD1201_RID_CNFDEFAULTKEY2 0xfc26
+#define ZD1201_RID_CNFDEFAULTKEY3 0xfc27
+#define ZD1201_RID_CNFWEBFLAGS 0xfc28
+#define ZD1201_RID_CNFAUTHENTICATION 0xfc2a
+#define ZD1201_RID_CNFMAXASSOCSTATIONS 0xfc2b
+#define ZD1201_RID_CNFHOSTAUTH 0xfc2e
+#define ZD1201_RID_CNFGROUPADDRESS 0xfc80
+#define ZD1201_RID_CNFFRAGTHRESHOLD 0xfc82
+#define ZD1201_RID_CNFRTSTHRESHOLD 0xfc83
+#define ZD1201_RID_TXRATECNTL 0xfc84
+#define ZD1201_RID_PROMISCUOUSMODE 0xfc85
+#define ZD1201_RID_CNFBASICRATES 0xfcb3
+#define ZD1201_RID_AUTHENTICATESTA 0xfce3
+#define ZD1201_RID_CURRENTBSSID 0xfd42
+#define ZD1201_RID_COMMSQUALITY 0xfd43
+#define ZD1201_RID_CURRENTTXRATE 0xfd44
+#define ZD1201_RID_CNFMAXTXBUFFERNUMBER 0xfda0
+#define ZD1201_RID_CURRENTCHANNEL 0xfdc1
+
+#define ZD1201_INQ_SCANRESULTS 0xf101
+
+#define ZD1201_INF_LINKSTATUS 0xf200
+#define ZD1201_INF_ASSOCSTATUS 0xf201
+#define ZD1201_INF_AUTHREQ 0xf202
+
+#define ZD1201_ASSOCSTATUS_STAASSOC 0x1
+#define ZD1201_ASSOCSTATUS_REASSOC 0x2
+#define ZD1201_ASSOCSTATUS_DISASSOC 0x3
+#define ZD1201_ASSOCSTATUS_ASSOCFAIL 0x4
+#define ZD1201_ASSOCSTATUS_AUTHFAIL 0x5
+
+#define ZD1201_PORTTYPE_IBSS 0
+#define ZD1201_PORTTYPE_BSS 1
+#define ZD1201_PORTTYPE_WDS 2
+#define ZD1201_PORTTYPE_PSEUDOIBSS 3
+#define ZD1201_PORTTYPE_AP 6
+
+#define ZD1201_RATEB1 1
+#define ZD1201_RATEB2 2
+#define ZD1201_RATEB5 4 /* 5.5 really, but 5 is shorter :) */
+#define ZD1201_RATEB11 8
+
+#define ZD1201_CNFAUTHENTICATION_OPENSYSTEM 0x0001
+#define ZD1201_CNFAUTHENTICATION_SHAREDKEY 0x0002
+
+#endif /* _INCLUDE_ZD1201_H_ */
diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig
index 67275dd601207..b869076d9c7c8 100644
--- a/drivers/usb/serial/Kconfig
+++ b/drivers/usb/serial/Kconfig
@@ -89,6 +89,16 @@ config USB_SERIAL_DIGI_ACCELEPORT
To compile this driver as a module, choose M here: the
module will be called digi_acceleport.
+config USB_SERIAL_CP2101
+ tristate "USB CP2101 UART Bridge Controller"
+ depends on USB_SERIAL && EXPERIMENTAL
+ help
+ Say Y here if you want to use a CP2101/CP2102 based USB to RS232
+ converter.
+
+ To compile this driver as a module, choose M here: the
+ module will be called cp2101.
+
config USB_SERIAL_CYPRESS_M8
tristate "USB Cypress M8 USB Serial Driver"
depends on USB_SERIAL && EXPERIMENTAL
diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile
index 1432b18125a65..351b81855b185 100644
--- a/drivers/usb/serial/Makefile
+++ b/drivers/usb/serial/Makefile
@@ -12,6 +12,7 @@ usbserial-obj-$(CONFIG_USB_EZUSB) += ezusb.o
usbserial-objs := usb-serial.o generic.o bus.o $(usbserial-obj-y)
obj-$(CONFIG_USB_SERIAL_BELKIN) += belkin_sa.o
+obj-$(CONFIG_USB_SERIAL_CP2101) += cp2101.o
obj-$(CONFIG_USB_SERIAL_CYBERJACK) += cyberjack.o
obj-$(CONFIG_USB_SERIAL_CYPRESS_M8) += cypress_m8.o
obj-$(CONFIG_USB_SERIAL_DIGI_ACCELEPORT) += digi_acceleport.o
diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c
index a16502e474fe3..86994d117c44a 100644
--- a/drivers/usb/serial/belkin_sa.c
+++ b/drivers/usb/serial/belkin_sa.c
@@ -158,7 +158,7 @@ struct belkin_sa_private {
* ***************************************************************************
*/
-#define WDR_TIMEOUT (HZ * 5 ) /* default urb timeout */
+#define WDR_TIMEOUT 5000 /* default urb timeout */
/* assumes that struct usb_serial *serial is available */
#define BSA_USB_CMD(c,v) usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), \
diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c
new file mode 100644
index 0000000000000..7e9bb63eb466d
--- /dev/null
+++ b/drivers/usb/serial/cp2101.c
@@ -0,0 +1,591 @@
+/*
+ * Silicon Laboratories CP2101/CP2102 USB to RS232 serial adaptor driver
+ *
+ * Copyright (C) 2005 Craig Shelley (craig@microtron.org.uk)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/usb.h>
+#include <asm/uaccess.h>
+#include "usb-serial.h"
+
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v0.03"
+#define DRIVER_DESC "Silicon Labs CP2101/CP2102 RS232 serial adaptor driver"
+
+/*
+ * Function Prototypes
+ */
+static int cp2101_open(struct usb_serial_port*, struct file*);
+static void cp2101_cleanup(struct usb_serial_port*);
+static void cp2101_close(struct usb_serial_port*, struct file*);
+static void cp2101_get_termios(struct usb_serial_port*);
+static void cp2101_set_termios(struct usb_serial_port*, struct termios*);
+static void cp2101_break_ctl(struct usb_serial_port*, int);
+static int cp2101_startup (struct usb_serial *);
+static void cp2101_shutdown(struct usb_serial*);
+
+
+static int debug;
+
+static struct usb_device_id id_table [] = {
+ {USB_DEVICE(0x10c4, 0xea60) }, /*Silicon labs factory default*/
+ {USB_DEVICE(0x10ab, 0x10c5) }, /*Siemens MC60 Cable*/
+ { } /* Terminating Entry*/
+};
+
+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,
+};
+
+static struct usb_serial_device_type cp2101_device = {
+ .owner = THIS_MODULE,
+ .name = "CP2101",
+ .id_table = id_table,
+ .num_interrupt_in = 0,
+ .num_bulk_in = 0,
+ .num_bulk_out = 0,
+ .num_ports = 1,
+ .open = cp2101_open,
+ .close = cp2101_close,
+ .break_ctl = cp2101_break_ctl,
+ .set_termios = cp2101_set_termios,
+ .attach = cp2101_startup,
+ .shutdown = cp2101_shutdown,
+};
+
+/*Config request types*/
+#define REQTYPE_HOST_TO_DEVICE 0x41
+#define REQTYPE_DEVICE_TO_HOST 0xc1
+
+/*Config SET requests. To GET, add 1 to the request number*/
+#define CP2101_UART 0x00 /*Enable / Disable*/
+#define CP2101_BAUDRATE 0x01 /*(BAUD_RATE_GEN_FREQ / baudrate)*/
+#define CP2101_BITS 0x03 /*0x(0)(data bits)(parity)(stop bits)*/
+#define CP2101_BREAK 0x05 /*On / Off*/
+#define CP2101_DTRRTS 0x07 /*101 / 202 ???*/
+#define CP2101_CONFIG_16 0x13 /*16 bytes of config data ???*/
+#define CP2101_CONFIG_6 0x19 /*6 bytes of config data ???*/
+
+/*CP2101_UART*/
+#define UART_ENABLE 0x0001
+#define UART_DISABLE 0x0000
+
+/*CP2101_BAUDRATE*/
+#define BAUD_RATE_GEN_FREQ 0x384000
+
+/*CP2101_BITS*/
+#define BITS_DATA_MASK 0X0f00
+#define BITS_DATA_6 0X0600
+#define BITS_DATA_7 0X0700
+#define BITS_DATA_8 0X0800
+#define BITS_DATA_9 0X0900
+
+#define BITS_PARITY_MASK 0x00f0
+#define BITS_PARITY_NONE 0x0000
+#define BITS_PARITY_ODD 0x0010
+#define BITS_PARITY_EVEN 0x0020
+#define BITS_PARITY_MARK 0x0030
+#define BITS_PARITY_SPACE 0x0040
+
+#define BITS_STOP_MASK 0x000f
+#define BITS_STOP_1 0x0000
+#define BITS_STOP_1_5 0x0001
+#define BITS_STOP_2 0x0002
+#define BREAK_ON 0x0000
+#define BREAK_OFF 0x0001
+
+
+static int cp2101_get_config(struct usb_serial_port* port, u8 request)
+{
+ struct usb_serial *serial = port->serial;
+ unsigned char buf[4];
+ unsigned int value;
+ int result, i;
+
+ /*For get requests, the request number must be incremented*/
+ request++;
+
+ /*Issue the request, attempting to read 4 bytes*/
+ result = usb_control_msg (serial->dev,usb_rcvctrlpipe (serial->dev, 0),
+ request, REQTYPE_DEVICE_TO_HOST, 0x0000,
+ 0, buf, 4, 300);
+
+ if (result < 0) {
+ dev_err(&port->dev, "%s - Unable to send config request, "
+ "request=0x%x result=%d\n",
+ __FUNCTION__, request, result);
+ return result;
+ }
+
+ /*Assemble each byte read into an integer value*/
+ value = 0;
+ for (i=0; i<4 && i<result; i++)
+ value |= (buf[i] << (i * 8));
+
+ dbg( " %s - request=0x%x result=%d value=0x%x",
+ __FUNCTION__, request, result, value);
+
+ return value;
+}
+
+static int cp2101_set_config(struct usb_serial_port* port, u8 request, u16 value)
+{
+ struct usb_serial *serial = port->serial;
+ int result;
+ result = usb_control_msg (serial->dev, usb_sndctrlpipe(serial->dev, 0),
+ request, REQTYPE_HOST_TO_DEVICE, value,
+ 0, NULL, 0, 300);
+
+ if (result <0) {
+ dev_err(&port->dev, "%s - Unable to send config request, "
+ "request=0x%x value=0x%x result=%d\n",
+ __FUNCTION__, request, value, result);
+ return result;
+ }
+
+ dbg(" %s - request=0x%x value=0x%x result=%d",
+ __FUNCTION__, request, value, result);
+
+ return 0;
+}
+
+static int cp2101_open (struct usb_serial_port *port, struct file *filp)
+{
+ struct usb_serial *serial = port->serial;
+ int result;
+
+ dbg("%s - port %d", __FUNCTION__, port->number);
+
+ if (cp2101_set_config(port, CP2101_UART, UART_ENABLE)) {
+ dev_err(&port->dev, "%s - Unable to enable UART\n",
+ __FUNCTION__);
+ return -EPROTO;
+ }
+
+ /* Start reading from the device */
+ usb_fill_bulk_urb (port->read_urb, serial->dev,
+ usb_rcvbulkpipe(serial->dev,
+ port->bulk_in_endpointAddress),
+ port->read_urb->transfer_buffer,
+ port->read_urb->transfer_buffer_length,
+ serial->type->read_bulk_callback,
+ port);
+ result = usb_submit_urb(port->read_urb, GFP_KERNEL);
+ if (result) {
+ dev_err(&port->dev, "%s - failed resubmitting read urb, "
+ "error %d\n", __FUNCTION__, result);
+ return result;
+ }
+
+ /*Configure the termios structure*/
+ cp2101_get_termios(port);
+
+ return 0;
+}
+
+static void cp2101_cleanup (struct usb_serial_port *port)
+{
+ struct usb_serial *serial = port->serial;
+
+ dbg("%s - port %d", __FUNCTION__, port->number);
+
+ if (serial->dev) {
+ /* shutdown any bulk reads that might be going on */
+ if (serial->num_bulk_out)
+ usb_kill_urb(port->write_urb);
+ if (serial->num_bulk_in)
+ usb_kill_urb(port->read_urb);
+ }
+}
+
+static void cp2101_close (struct usb_serial_port *port, struct file * filp)
+{
+ dbg("%s - port %d", __FUNCTION__, port->number);
+
+ /* shutdown our urbs */
+ dbg("%s - shutting down urbs", __FUNCTION__);
+ usb_kill_urb(port->write_urb);
+ usb_kill_urb(port->read_urb);
+
+ cp2101_set_config(port, CP2101_UART, UART_DISABLE);
+}
+
+/* cp2101_get_termios*/
+/* Reads the baud rate, data bits, parity and stop bits from the device*/
+/* Corrects any unsupported values*/
+/* Configures the termios structure to reflect the state of the device*/
+static void cp2101_get_termios (struct usb_serial_port *port)
+{
+ unsigned int cflag;
+ int baud;
+ int bits;
+
+ dbg("%s - port %d", __FUNCTION__, port->number);
+
+ if ((!port->tty) || (!port->tty->termios)) {
+ dbg("%s - no tty structures", __FUNCTION__);
+ return;
+ }
+ cflag = port->tty->termios->c_cflag;
+
+ baud = cp2101_get_config(port, CP2101_BAUDRATE);
+ /*Convert to baudrate*/
+ if (baud)
+ baud = BAUD_RATE_GEN_FREQ / baud;
+
+ dbg("%s - baud rate = %d", __FUNCTION__, baud);
+ cflag &= ~CBAUD;
+ switch (baud) {
+ /* The baud rates which are commented out below
+ * appear to be supported by the device
+ * but are non-standard
+ */
+ case 600: cflag |= B600; break;
+ case 1200: cflag |= B1200; break;
+ case 1800: cflag |= B1800; break;
+ case 2400: cflag |= B2400; break;
+ case 4800: cflag |= B4800; break;
+ /*case 7200: cflag |= B7200; break;*/
+ case 9600: cflag |= B9600; break;
+ /*case 14400: cflag |= B14400; break;*/
+ case 19200: cflag |= B19200; break;
+ /*case 28800: cflag |= B28800; break;*/
+ case 38400: cflag |= B38400; break;
+ /*case 55854: cflag |= B55054; break;*/
+ case 57600: cflag |= B57600; break;
+ case 115200: cflag |= B115200; break;
+ /*case 127117: cflag |= B127117; break;*/
+ case 230400: cflag |= B230400; break;
+ case 460800: cflag |= B460800; break;
+ case 921600: cflag |= B921600; break;
+ /*case 3686400: cflag |= B3686400; break;*/
+ default:
+ dbg("%s - Baud rate is not supported, "
+ "using 9600 baud", __FUNCTION__);
+ cflag |= B9600;
+ cp2101_set_config(port, CP2101_BAUDRATE,
+ (BAUD_RATE_GEN_FREQ/9600));
+ break;
+ }
+
+ bits = cp2101_get_config(port, CP2101_BITS);
+ cflag &= ~CSIZE;
+ switch(bits & BITS_DATA_MASK) {
+ case BITS_DATA_6:
+ dbg("%s - data bits = 6", __FUNCTION__);
+ cflag |= CS6;
+ break;
+ case BITS_DATA_7:
+ dbg("%s - data bits = 7", __FUNCTION__);
+ cflag |= CS7;
+ break;
+ case BITS_DATA_8:
+ dbg("%s - data bits = 8", __FUNCTION__);
+ cflag |= CS8;
+ break;
+ case BITS_DATA_9:
+ dbg("%s - data bits = 9 (not supported, "
+ "using 8 data bits)", __FUNCTION__);
+ cflag |= CS8;
+ bits &= ~BITS_DATA_MASK;
+ bits |= BITS_DATA_8;
+ cp2101_set_config(port, CP2101_BITS, bits);
+ break;
+ default:
+ dbg("%s - Unknown number of data bits, "
+ "using 8", __FUNCTION__);
+ cflag |= CS8;
+ bits &= ~BITS_DATA_MASK;
+ bits |= BITS_DATA_8;
+ cp2101_set_config(port, CP2101_BITS, bits);
+ break;
+ }
+
+ switch(bits & BITS_PARITY_MASK) {
+ case BITS_PARITY_NONE:
+ dbg("%s - parity = NONE", __FUNCTION__);
+ cflag &= ~PARENB;
+ break;
+ case BITS_PARITY_ODD:
+ dbg("%s - parity = ODD", __FUNCTION__);
+ cflag |= (PARENB|PARODD);
+ break;
+ case BITS_PARITY_EVEN:
+ dbg("%s - parity = EVEN", __FUNCTION__);
+ cflag &= ~PARODD;
+ cflag |= PARENB;
+ break;
+ case BITS_PARITY_MARK:
+ dbg("%s - parity = MARK (not supported, "
+ "disabling parity)", __FUNCTION__);
+ cflag &= ~PARENB;
+ bits &= ~BITS_PARITY_MASK;
+ cp2101_set_config(port, CP2101_BITS, bits);
+ break;
+ case BITS_PARITY_SPACE:
+ dbg("%s - parity = SPACE (not supported, "
+ "disabling parity)", __FUNCTION__);
+ cflag &= ~PARENB;
+ bits &= ~BITS_PARITY_MASK;
+ cp2101_set_config(port, CP2101_BITS, bits);
+ break;
+ default:
+ dbg("%s - Unknown parity mode, "
+ "disabling parity", __FUNCTION__);
+ cflag &= ~PARENB;
+ bits &= ~BITS_PARITY_MASK;
+ cp2101_set_config(port, CP2101_BITS, bits);
+ break;
+ }
+
+ cflag &= ~CSTOPB;
+ switch(bits & BITS_STOP_MASK) {
+ case BITS_STOP_1:
+ dbg("%s - stop bits = 1", __FUNCTION__);
+ break;
+ case BITS_STOP_1_5:
+ dbg("%s - stop bits = 1.5 (not supported, "
+ "using 1 stop bit", __FUNCTION__);
+ bits &= ~BITS_STOP_MASK;
+ cp2101_set_config(port, CP2101_BITS, bits);
+ break;
+ case BITS_STOP_2:
+ dbg("%s - stop bits = 2", __FUNCTION__);
+ cflag |= CSTOPB;
+ break;
+ default:
+ dbg("%s - Unknown number of stop bits, "
+ "using 1 stop bit", __FUNCTION__);
+ bits &= ~BITS_STOP_MASK;
+ cp2101_set_config(port, CP2101_BITS, bits);
+ break;
+ }
+
+ port->tty->termios->c_cflag = cflag;
+}
+
+static void cp2101_set_termios (struct usb_serial_port *port,
+ struct termios *old_termios)
+{
+ unsigned int cflag, old_cflag=0;
+ int baud=0;
+ int bits;
+
+ dbg("%s - port %d", __FUNCTION__, port->number);
+
+ if ((!port->tty) || (!port->tty->termios)) {
+ dbg("%s - no tty structures", __FUNCTION__);
+ return;
+ }
+ cflag = port->tty->termios->c_cflag;
+
+ /* check that they really want us to change something */
+ if (old_termios) {
+ if ((cflag == old_termios->c_cflag) &&
+ (RELEVANT_IFLAG(port->tty->termios->c_iflag)
+ == RELEVANT_IFLAG(old_termios->c_iflag))) {
+ dbg("%s - nothing to change...", __FUNCTION__);
+ return;
+ }
+
+ old_cflag = old_termios->c_cflag;
+ }
+
+ /* If the baud rate is to be updated*/
+ if ((cflag & CBAUD) != (old_cflag & CBAUD)) {
+ switch (cflag & CBAUD) {
+ /* The baud rates which are commented out below
+ * appear to be supported by the device
+ * but are non-standard
+ */
+ case B0: baud = 0; break;
+ case B600: baud = 600; break;
+ case B1200: baud = 1200; break;
+ case B1800: baud = 1800; break;
+ case B2400: baud = 2400; break;
+ case B4800: baud = 4800; break;
+ /*case B7200: baud = 7200; break;*/
+ case B9600: baud = 9600; break;
+ /*ase B14400: baud = 14400; break;*/
+ case B19200: baud = 19200; break;
+ /*case B28800: baud = 28800; break;*/
+ case B38400: baud = 38400; break;
+ /*case B55854: baud = 55054; break;*/
+ case B57600: baud = 57600; break;
+ case B115200: baud = 115200; break;
+ /*case B127117: baud = 127117; break;*/
+ case B230400: baud = 230400; break;
+ case B460800: baud = 460800; break;
+ case B921600: baud = 921600; break;
+ /*case B3686400: baud = 3686400; break;*/
+ default:
+ dev_err(&port->dev, "cp2101 driver does not "
+ "support the baudrate requested\n");
+ break;
+ }
+
+ if (baud) {
+ dbg("%s - Setting baud rate to %d baud", __FUNCTION__,
+ baud);
+ if (cp2101_set_config(port, CP2101_BAUDRATE,
+ (BAUD_RATE_GEN_FREQ / baud)))
+ dev_err(&port->dev, "Baud rate requested not "
+ "supported by device\n");
+ }
+ }
+
+ /*If the number of data bits is to be updated*/
+ if ((cflag & CSIZE) != (old_cflag & CSIZE)) {
+ bits = cp2101_get_config(port, CP2101_BITS);
+ bits &= ~BITS_DATA_MASK;
+ switch (cflag & CSIZE) {
+ case CS6:
+ bits |= BITS_DATA_6;
+ dbg("%s - data bits = 6", __FUNCTION__);
+ break;
+ case CS7:
+ bits |= BITS_DATA_7;
+ dbg("%s - data bits = 7", __FUNCTION__);
+ break;
+ case CS8:
+ bits |= BITS_DATA_8;
+ dbg("%s - data bits = 8", __FUNCTION__);
+ break;
+ /*case CS9:
+ bits |= BITS_DATA_9;
+ dbg("%s - data bits = 9", __FUNCTION__);
+ break;*/
+ default:
+ dev_err(&port->dev, "cp2101 driver does not "
+ "support the number of bits requested,"
+ " using 8 bit mode\n");
+ bits |= BITS_DATA_8;
+ break;
+ }
+ if (cp2101_set_config(port, CP2101_BITS, bits))
+ dev_err(&port->dev, "Number of data bits requested "
+ "not supported by device\n");
+ }
+
+ if ((cflag & (PARENB|PARODD)) != (old_cflag & (PARENB|PARODD))) {
+ bits = cp2101_get_config(port, CP2101_BITS);
+ bits &= ~BITS_PARITY_MASK;
+ if (cflag & PARENB) {
+ if (cflag & PARODD) {
+ bits |= BITS_PARITY_ODD;
+ dbg("%s - parity = ODD", __FUNCTION__);
+ } else {
+ bits |= BITS_PARITY_EVEN;
+ dbg("%s - parity = EVEN", __FUNCTION__);
+ }
+ }
+ if (cp2101_set_config(port, CP2101_BITS, bits))
+ dev_err(&port->dev, "Parity mode not supported "
+ "by device\n");
+ }
+
+ if ((cflag & CSTOPB) != (old_cflag & CSTOPB)) {
+ bits = cp2101_get_config(port, CP2101_BITS);
+ bits &= ~BITS_STOP_MASK;
+ if (cflag & CSTOPB) {
+ bits |= BITS_STOP_2;
+ dbg("%s - stop bits = 2", __FUNCTION__);
+ } else {
+ bits |= BITS_STOP_1;
+ dbg("%s - stop bits = 1", __FUNCTION__);
+ }
+ if (cp2101_set_config(port, CP2101_BITS, bits))
+ dev_err(&port->dev, "Number of stop bits requested "
+ "not supported by device\n");
+ }
+}
+
+static void cp2101_break_ctl (struct usb_serial_port *port, int break_state)
+{
+ u16 state;
+
+ dbg("%s - port %d", __FUNCTION__, port->number);
+ if (break_state == 0)
+ state = BREAK_OFF;
+ else
+ state = BREAK_ON;
+ dbg("%s - turning break %s", __FUNCTION__,
+ state==BREAK_OFF ? "off" : "on");
+ cp2101_set_config(port, CP2101_BREAK, state);
+}
+
+static int cp2101_startup (struct usb_serial *serial)
+{
+ /*CP2101 buffers behave strangely unless device is reset*/
+ usb_reset_device(serial->dev);
+ return 0;
+}
+
+static void cp2101_shutdown (struct usb_serial *serial)
+{
+ int i;
+
+ dbg("%s", __FUNCTION__);
+
+ /* stop reads and writes on all ports */
+ for (i=0; i < serial->num_ports; ++i) {
+ cp2101_cleanup(serial->port[i]);
+ }
+}
+
+static int __init cp2101_init (void)
+{
+ int retval;
+
+ retval = usb_serial_register(&cp2101_device);
+ if (retval)
+ return retval; /*Failed to register*/
+
+ retval = usb_register(&cp2101_driver);
+ if (retval) {
+ /*Failed to register*/
+ usb_serial_deregister(&cp2101_device);
+ return retval;
+ }
+
+ /*Success*/
+ info(DRIVER_DESC " " DRIVER_VERSION);
+ return 0;
+}
+
+static void __exit cp2101_exit (void)
+{
+ usb_deregister (&cp2101_driver);
+ usb_serial_deregister (&cp2101_device);
+}
+
+module_init(cp2101_init);
+module_exit(cp2101_exit);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_VERSION(DRIVER_VERSION);
+MODULE_LICENSE("GPL");
+
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Enable verbose debugging messages");
diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c
index 3a367f547f00a..46a204cd40e19 100644
--- a/drivers/usb/serial/cyberjack.c
+++ b/drivers/usb/serial/cyberjack.c
@@ -4,7 +4,7 @@
* Copyright (C) 2001 REINER SCT
* Author: Matthias Bruestle
*
- * Contact: linux-usb@sii.li (see MAINTAINERS)
+ * Contact: support@reiner-sct.com (see MAINTAINERS)
*
* This program is largely derived from work by the linux-usb group
* and associated source files. Please see the usb/serial files for
@@ -20,6 +20,11 @@
*
* In case of problems, please write to the contact e-mail address
* mentioned above.
+ *
+ * Please note that later models of the cyberjack reader family are
+ * supported by a libusb-based userspace device driver.
+ *
+ * Homepage: http://www.reiner-sct.de/support/treiber_cyberjack.php#linux
*/
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
index 58d5019d8236e..db8f472d9e3f2 100644
--- a/drivers/usb/serial/cypress_m8.c
+++ b/drivers/usb/serial/cypress_m8.c
@@ -57,9 +57,10 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/spinlock.h>
-#include <asm/uaccess.h>
#include <linux/usb.h>
#include <linux/serial.h>
+#include <linux/delay.h>
+#include <asm/uaccess.h>
#include "usb-serial.h"
#include "cypress_m8.h"
@@ -1013,8 +1014,7 @@ static void cypress_set_termios (struct usb_serial_port *port, struct termios *o
cypress_serial_control(port, baud_mask, data_bits, stop_bits, parity_enable,
parity_type, 0, CYPRESS_SET_CONFIG);
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(50*HZ/1000); /* give some time between change and read (50ms) */
+ msleep(50); /* give some time between change and read (50ms) */
/* we perform a CYPRESS_GET_CONFIG so that the current settings are filled into the private structure
* this should confirm that all is working if it returns what we just set */
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
index 4b59d75dbfb91..25f92788a6d42 100644
--- a/drivers/usb/serial/digi_acceleport.c
+++ b/drivers/usb/serial/digi_acceleport.c
@@ -246,6 +246,7 @@
#include <linux/workqueue.h>
#include <asm/uaccess.h>
#include <linux/usb.h>
+#include <linux/wait.h>
#include "usb-serial.h"
/* Defines */
@@ -573,23 +574,14 @@ static inline long cond_wait_interruptible_timeout_irqrestore(
wait_queue_head_t *q, long timeout,
spinlock_t *lock, unsigned long flags )
{
+ DEFINE_WAIT(wait);
- wait_queue_t wait;
-
-
- init_waitqueue_entry( &wait, current );
-
- set_current_state( TASK_INTERRUPTIBLE );
-
- add_wait_queue( q, &wait );
-
- spin_unlock_irqrestore( lock, flags );
-
+ prepare_to_wait(q, &wait, TASK_UNINTERRUPTIBLE);
+ spin_unlock_irqrestore(lock, flags);
timeout = schedule_timeout(timeout);
+ finish_wait(q, &wait);
- remove_wait_queue( q, &wait );
-
- return( timeout );
+ return timeout;
}
@@ -1528,7 +1520,7 @@ dbg( "digi_open: TOP: port=%d, open_count=%d", priv->dp_port_num, port->open_cou
static void digi_close( struct usb_serial_port *port, struct file *filp )
{
-
+ DEFINE_WAIT(wait);
int ret;
unsigned char buf[32];
struct tty_struct *tty = port->tty;
@@ -1604,8 +1596,9 @@ dbg( "digi_close: TOP: port=%d, open_count=%d", priv->dp_port_num, port->open_co
dbg( "digi_close: write oob failed, ret=%d", ret );
/* wait for final commands on oob port to complete */
- interruptible_sleep_on_timeout( &priv->dp_flush_wait,
- DIGI_CLOSE_TIMEOUT );
+ prepare_to_wait(&priv->dp_flush_wait, &wait, TASK_UNINTERRUPTIBLE);
+ schedule_timeout(DIGI_CLOSE_TIMEOUT);
+ finish_wait(&priv->dp_flush_wait, &wait);
/* shutdown any outstanding bulk writes */
usb_kill_urb(port->write_urb);
@@ -2002,7 +1995,7 @@ opcode, line, status, val );
} else if( opcode == DIGI_CMD_IFLUSH_FIFO ) {
- wake_up_interruptible( &priv->dp_flush_wait );
+ wake_up( &priv->dp_flush_wait );
}
diff --git a/drivers/usb/serial/ezusb.c b/drivers/usb/serial/ezusb.c
index 93c803b00b65a..1e419c8d7392b 100644
--- a/drivers/usb/serial/ezusb.c
+++ b/drivers/usb/serial/ezusb.c
@@ -38,7 +38,7 @@ int ezusb_writememory (struct usb_serial *serial, int address, unsigned char *da
return -ENOMEM;
}
memcpy (transfer_buffer, data, length);
- result = usb_control_msg (serial->dev, usb_sndctrlpipe(serial->dev, 0), bRequest, 0x40, address, 0, transfer_buffer, length, 3*HZ);
+ result = usb_control_msg (serial->dev, usb_sndctrlpipe(serial->dev, 0), bRequest, 0x40, address, 0, transfer_buffer, length, 3000);
kfree (transfer_buffer);
return result;
}
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 8e75ea1eaedaa..4afd905fe2fe4 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -296,6 +296,7 @@ static struct usb_device_id id_table_8U232AM [] = {
{ USB_DEVICE_VER(FTDI_VID, FTDI_IRTRANS_PID, 0, 0x3ff) },
{ USB_DEVICE_VER(FTDI_VID, FTDI_8U232AM_PID, 0, 0x3ff) },
{ USB_DEVICE_VER(FTDI_VID, FTDI_8U232AM_ALT_PID, 0, 0x3ff) },
+ { USB_DEVICE_VER(FTDI_VID, FTDI_8U232AM_ALT_ALT_PID, 0, 0x3ff) },
{ USB_DEVICE_VER(FTDI_VID, FTDI_RELAIS_PID, 0, 0x3ff) },
{ USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_IOBOARD_PID) },
{ USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_MINI_IOBOARD_PID) },
@@ -381,6 +382,7 @@ static struct usb_device_id id_table_FT232BM [] = {
{ USB_DEVICE_VER(FTDI_VID, FTDI_IRTRANS_PID, 0x400, 0xffff) },
{ USB_DEVICE_VER(FTDI_VID, FTDI_8U232AM_PID, 0x400, 0xffff) },
{ USB_DEVICE_VER(FTDI_VID, FTDI_8U232AM_ALT_PID, 0x400, 0xffff) },
+ { USB_DEVICE_VER(FTDI_VID, FTDI_8U232AM_ALT_ALT_PID, 0x400, 0xffff) },
{ USB_DEVICE_VER(FTDI_VID, FTDI_RELAIS_PID, 0x400, 0xffff) },
{ USB_DEVICE_VER(FTDI_NF_RIC_VID, FTDI_NF_RIC_PID, 0x400, 0xffff) },
{ USB_DEVICE_VER(FTDI_VID, FTDI_XF_632_PID, 0x400, 0xffff) },
@@ -515,6 +517,7 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FTDI_VID, FTDI_SIO_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_8U232AM_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_8U232AM_ALT_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_8U232AM_ALT_ALT_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_8U2232C_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_RELAIS_PID) },
{ USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_IOBOARD_PID) },
@@ -623,6 +626,13 @@ static struct usb_driver ftdi_driver = {
.id_table = id_table_combined,
};
+static char *ftdi_chip_name[] = {
+ [SIO] = "SIO", /* the serial part of FT8U100AX */
+ [FT8U232AM] = "FT8U232AM",
+ [FT232BM] = "FT232BM",
+ [FT2232C] = "FT2232C",
+};
+
/* Constants for read urb and write urb */
#define BUFSZ 512
@@ -852,7 +862,7 @@ static struct usb_serial_device_type ftdi_HE_TIRA1_device = {
-#define WDR_TIMEOUT (HZ * 5 ) /* default urb timeout */
+#define WDR_TIMEOUT 5000 /* default urb timeout */
/* High and low are for DTR, RTS etc etc */
#define HIGH 1
@@ -1001,7 +1011,6 @@ static __u32 get_ftdi_divisor(struct usb_serial_port * port)
struct ftdi_private *priv = usb_get_serial_port_data(port);
__u32 div_value = 0;
int div_okay = 1;
- char *chip_name = "";
int baud;
/*
@@ -1046,7 +1055,6 @@ static __u32 get_ftdi_divisor(struct usb_serial_port * port)
if (!baud) baud = 9600;
switch(priv->chip_type) {
case SIO: /* SIO chip */
- chip_name = "SIO";
switch(baud) {
case 300: div_value = ftdi_sio_b300; break;
case 600: div_value = ftdi_sio_b600; break;
@@ -1066,7 +1074,6 @@ static __u32 get_ftdi_divisor(struct usb_serial_port * port)
}
break;
case FT8U232AM: /* 8U232AM chip */
- chip_name = "FT8U232AM";
if (baud <= 3000000) {
div_value = ftdi_232am_baud_to_divisor(baud);
} else {
@@ -1077,11 +1084,6 @@ static __u32 get_ftdi_divisor(struct usb_serial_port * port)
break;
case FT232BM: /* FT232BM chip */
case FT2232C: /* FT2232C chip */
- if (priv->chip_type == FT2232C) {
- chip_name = "FT2232C";
- } else {
- chip_name = "FT232BM";
- }
if (baud <= 3000000) {
div_value = ftdi_232bm_baud_to_divisor(baud);
} else {
@@ -1094,7 +1096,8 @@ static __u32 get_ftdi_divisor(struct usb_serial_port * port)
if (div_okay) {
dbg("%s - Baud rate set to %d (divisor 0x%lX) on chip %s",
- __FUNCTION__, baud, (unsigned long)div_value, chip_name);
+ __FUNCTION__, baud, (unsigned long)div_value,
+ ftdi_chip_name[priv->chip_type]);
}
return(div_value);
@@ -1184,7 +1187,7 @@ check_and_exit:
* ***************************************************************************
*/
-ssize_t show_latency_timer(struct device *dev, char *buf)
+static ssize_t show_latency_timer(struct device *dev, char *buf)
{
struct usb_serial_port *port = to_usb_serial_port(dev);
struct ftdi_private *priv = usb_get_serial_port_data(port);
@@ -1211,7 +1214,8 @@ ssize_t show_latency_timer(struct device *dev, char *buf)
}
/* Write a new value of the latency timer, in units of milliseconds. */
-ssize_t store_latency_timer(struct device *dev, const char *valbuf, size_t count)
+static ssize_t store_latency_timer(struct device *dev, const char *valbuf,
+ size_t count)
{
struct usb_serial_port *port = to_usb_serial_port(dev);
struct ftdi_private *priv = usb_get_serial_port_data(port);
@@ -1241,7 +1245,8 @@ ssize_t store_latency_timer(struct device *dev, const char *valbuf, size_t count
/* Write an event character directly to the FTDI register. The ASCII
value is in the low 8 bits, with the enable bit in the 9th bit. */
-ssize_t store_event_char(struct device *dev, const char *valbuf, size_t count)
+static ssize_t store_event_char(struct device *dev, const char *valbuf,
+ size_t count)
{
struct usb_serial_port *port = to_usb_serial_port(dev);
struct ftdi_private *priv = usb_get_serial_port_data(port);
@@ -1269,10 +1274,10 @@ ssize_t store_event_char(struct device *dev, const char *valbuf, size_t count)
return count;
}
-static DEVICE_ATTR(latency_timer, S_IWUGO | S_IRUGO, show_latency_timer, store_latency_timer);
-static DEVICE_ATTR(event_char, S_IWUGO, NULL, store_event_char);
+static DEVICE_ATTR(latency_timer, S_IWUSR | S_IRUGO, show_latency_timer, store_latency_timer);
+static DEVICE_ATTR(event_char, S_IWUSR, NULL, store_event_char);
-void create_sysfs_attrs(struct usb_serial *serial)
+static void create_sysfs_attrs(struct usb_serial *serial)
{
struct ftdi_private *priv;
struct usb_device *udev;
@@ -1282,14 +1287,18 @@ void create_sysfs_attrs(struct usb_serial *serial)
priv = usb_get_serial_port_data(serial->port[0]);
udev = serial->dev;
- if (priv->chip_type == FT232BM) {
- dbg("sysfs attributes for FT232BM");
+ /* XXX I've no idea if the original SIO supports the event_char
+ * sysfs parameter, so I'm playing it safe. */
+ if (priv->chip_type != SIO) {
+ dbg("sysfs attributes for %s", ftdi_chip_name[priv->chip_type]);
device_create_file(&udev->dev, &dev_attr_event_char);
- device_create_file(&udev->dev, &dev_attr_latency_timer);
+ if (priv->chip_type == FT232BM || priv->chip_type == FT2232C) {
+ device_create_file(&udev->dev, &dev_attr_latency_timer);
+ }
}
}
-void remove_sysfs_attrs(struct usb_serial *serial)
+static void remove_sysfs_attrs(struct usb_serial *serial)
{
struct ftdi_private *priv;
struct usb_device *udev;
@@ -1299,9 +1308,12 @@ void remove_sysfs_attrs(struct usb_serial *serial)
priv = usb_get_serial_port_data(serial->port[0]);
udev = serial->dev;
- if (priv->chip_type == FT232BM) {
+ /* XXX see create_sysfs_attrs */
+ if (priv->chip_type != SIO) {
device_remove_file(&udev->dev, &dev_attr_event_char);
- device_remove_file(&udev->dev, &dev_attr_latency_timer);
+ if (priv->chip_type == FT232BM || priv->chip_type == FT2232C) {
+ device_remove_file(&udev->dev, &dev_attr_latency_timer);
+ }
}
}
@@ -1403,6 +1415,8 @@ static int ftdi_8U232AM_startup (struct usb_serial *serial)
priv->chip_type = FT8U232AM;
priv->baud_base = 48000000 / 2; /* Would be / 16, but FTDI supports 0.125, 0.25 and 0.5 divisor fractions! */
+ create_sysfs_attrs(serial);
+
return (0);
} /* ftdi_8U232AM_startup */
@@ -1454,6 +1468,8 @@ static int ftdi_FT2232C_startup (struct usb_serial *serial)
}
priv->baud_base = 48000000 / 2; /* Would be / 16, but FT2232C supports multiple of 0.125 divisor fractions! */
+ create_sysfs_attrs(serial);
+
return (0);
} /* ftdi_FT2232C_startup */
diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h
index dbb756437d797..be5d60bf90b90 100644
--- a/drivers/usb/serial/ftdi_sio.h
+++ b/drivers/usb/serial/ftdi_sio.h
@@ -26,6 +26,7 @@
#define FTDI_SIO_PID 0x8372 /* Product Id SIO application of 8U100AX */
#define FTDI_8U232AM_PID 0x6001 /* Similar device to SIO above */
#define FTDI_8U232AM_ALT_PID 0x6006 /* FTDI's alternate PID for above */
+#define FTDI_8U232AM_ALT_ALT_PID 0xf3c0 /* FTDI's second alternate PID for above */
#define FTDI_8U2232C_PID 0x6010 /* Dual channel device */
#define FTDI_RELAIS_PID 0xFA10 /* Relais device from Rudolf Gugler */
#define FTDI_NF_RIC_VID 0x0DCD /* Vendor Id */
diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c
index 1655085d13eb1..2ef614d5c8f2b 100644
--- a/drivers/usb/serial/garmin_gps.c
+++ b/drivers/usb/serial/garmin_gps.c
@@ -614,8 +614,8 @@ static int gsp_receive(struct garmin_data * garmin_data_p,
*
* return <0 on error, 0 if packet is incomplete or > 0 if packet was sent
*/
-int gsp_send(struct garmin_data * garmin_data_p, const unsigned char *buf,
- int count)
+static int gsp_send(struct garmin_data * garmin_data_p,
+ const unsigned char *buf, int count)
{
const unsigned char *src;
unsigned char *dst;
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index b194420025ef9..e35b5adcd5fe7 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -261,6 +261,7 @@
#include <linux/spinlock.h>
#include <linux/serial.h>
#include <linux/ioctl.h>
+#include <linux/wait.h>
#include <asm/uaccess.h>
#include <linux/usb.h>
#include "usb-serial.h"
@@ -971,7 +972,7 @@ static void edge_bulk_out_cmd_callback (struct urb *urb, struct pt_regs *regs)
/* we have completed the command */
edge_port->commandPending = FALSE;
- wake_up_interruptible(&edge_port->wait_command);
+ wake_up(&edge_port->wait_command);
}
@@ -991,7 +992,6 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
struct usb_serial *serial;
struct edgeport_serial *edge_serial;
int response;
- int timeout;
dbg("%s - port %d", __FUNCTION__, port->number);
@@ -1073,10 +1073,7 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
}
/* now wait for the port to be completely opened */
- timeout = OPEN_TIMEOUT;
- while (timeout && edge_port->openPending == TRUE) {
- timeout = interruptible_sleep_on_timeout (&edge_port->wait_open, timeout);
- }
+ wait_event_timeout(edge_port->wait_open, (edge_port->openPending != TRUE), OPEN_TIMEOUT);
if (edge_port->open == FALSE) {
/* open timed out */
@@ -1128,9 +1125,10 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
************************************************************************/
static void block_until_chase_response(struct edgeport_port *edge_port)
{
+ DEFINE_WAIT(wait);
__u16 lastCredits;
int timeout = 1*HZ;
- int wait = 10;
+ int loop = 10;
while (1) {
// Save Last credits
@@ -1148,12 +1146,14 @@ static void block_until_chase_response(struct edgeport_port *edge_port)
}
// Block the thread for a while
- interruptible_sleep_on_timeout (&edge_port->wait_chase, timeout);
+ prepare_to_wait(&edge_port->wait_chase, &wait, TASK_UNINTERRUPTIBLE);
+ schedule_timeout(timeout);
+ finish_wait(&edge_port->wait_chase, &wait);
if (lastCredits == edge_port->txCredits) {
// No activity.. count down.
- wait--;
- if (wait == 0) {
+ loop--;
+ if (loop == 0) {
edge_port->chaseResponsePending = FALSE;
dbg("%s - Chase TIMEOUT", __FUNCTION__);
return;
@@ -1161,7 +1161,7 @@ static void block_until_chase_response(struct edgeport_port *edge_port)
} else {
// Reset timout value back to 10 seconds
dbg("%s - Last %d, Current %d", __FUNCTION__, lastCredits, edge_port->txCredits);
- wait = 10;
+ loop = 10;
}
}
}
@@ -1179,10 +1179,11 @@ static void block_until_chase_response(struct edgeport_port *edge_port)
************************************************************************/
static void block_until_tx_empty (struct edgeport_port *edge_port)
{
+ DEFINE_WAIT(wait);
struct TxFifo *fifo = &edge_port->txfifo;
__u32 lastCount;
int timeout = HZ/10;
- int wait = 30;
+ int loop = 30;
while (1) {
// Save Last count
@@ -1195,20 +1196,22 @@ static void block_until_tx_empty (struct edgeport_port *edge_port)
}
// Block the thread for a while
- interruptible_sleep_on_timeout (&edge_port->wait_chase, timeout);
+ prepare_to_wait (&edge_port->wait_chase, &wait, TASK_UNINTERRUPTIBLE);
+ schedule_timeout(timeout);
+ finish_wait(&edge_port->wait_chase, &wait);
dbg("%s wait", __FUNCTION__);
if (lastCount == fifo->count) {
// No activity.. count down.
- wait--;
- if (wait == 0) {
+ loop--;
+ if (loop == 0) {
dbg("%s - TIMEOUT", __FUNCTION__);
return;
}
} else {
// Reset timout value back to seconds
- wait = 30;
+ loop = 30;
}
}
}
@@ -1836,12 +1839,12 @@ static int get_serial_info(struct edgeport_port *edge_port, struct serial_struct
*****************************************************************************/
static int edge_ioctl (struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg)
{
+ DEFINE_WAIT(wait);
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
struct async_icount cnow;
struct async_icount cprev;
struct serial_icounter_struct icount;
-
dbg("%s - port %d, cmd = 0x%x", __FUNCTION__, port->number, cmd);
switch (cmd) {
@@ -1868,7 +1871,9 @@ static int edge_ioctl (struct usb_serial_port *port, struct file *file, unsigned
dbg("%s (%d) TIOCMIWAIT", __FUNCTION__, port->number);
cprev = edge_port->icount;
while (1) {
- interruptible_sleep_on(&edge_port->delta_msr_wait);
+ prepare_to_wait(&edge_port->delta_msr_wait, &wait, TASK_INTERRUPTIBLE);
+ schedule();
+ finish_wait(&edge_port->delta_msr_wait, &wait);
/* see if a signal did it */
if (signal_pending(current))
return -ERESTARTSYS;
@@ -2108,7 +2113,7 @@ static void process_rcvd_status (struct edgeport_serial *edge_serial, __u8 byte2
// We could choose to do something else when Byte3 says Timeout on Chase from Edgeport,
// like wait longer in block_until_chase_response, but for now we don't.
edge_port->chaseResponsePending = FALSE;
- wake_up_interruptible (&edge_port->wait_chase);
+ wake_up (&edge_port->wait_chase);
return;
case IOSP_EXT_STATUS_RX_CHECK_RSP:
@@ -2131,7 +2136,7 @@ static void process_rcvd_status (struct edgeport_serial *edge_serial, __u8 byte2
/* we have completed the open */
edge_port->openPending = FALSE;
edge_port->open = TRUE;
- wake_up_interruptible(&edge_port->wait_open);
+ wake_up(&edge_port->wait_open);
return;
}
@@ -2500,9 +2505,7 @@ static int write_cmd_usb (struct edgeport_port *edge_port, unsigned char *buffer
// wait for command to finish
timeout = COMMAND_TIMEOUT;
#if 0
- while (timeout && edge_port->commandPending == TRUE) {
- timeout = interruptible_sleep_on_timeout (&edge_port->wait_command, timeout);
- }
+ wait_event (&edge_port->wait_command, (edge_port->commandPending == FALSE));
if (edge_port->commandPending == TRUE) {
/* command timed out */
@@ -3107,4 +3110,4 @@ module_param(debug, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(debug, "Debug enabled or not");
module_param(low_latency, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Low latency enabled or not");
+MODULE_PARM_DESC(low_latency, "Low latency enabled or not");
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
index b9846a5ae636d..6c96fdaec36e3 100644
--- a/drivers/usb/serial/io_ti.c
+++ b/drivers/usb/serial/io_ti.c
@@ -273,7 +273,7 @@ static int TIReadVendorRequestSync (struct usb_device *dev,
index,
data,
size,
- HZ);
+ 1000);
if (status < 0)
return status;
if (status != size) {
@@ -303,8 +303,7 @@ static int TISendVendorRequestSync (struct usb_device *dev,
index,
data,
size,
- HZ);
-
+ 1000);
if (status < 0)
return status;
if (status != size) {
@@ -985,7 +984,7 @@ static int TISendBulkTransferSync (struct usb_serial *serial, void *buffer, int
buffer,
length,
num_sent,
- HZ);
+ 1000);
return status;
}
diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
index 4ffe6e4ac5313..3bd69c4ef24b6 100644
--- a/drivers/usb/serial/ipaq.c
+++ b/drivers/usb/serial/ipaq.c
@@ -662,7 +662,7 @@ static int ipaq_open(struct usb_serial_port *port, struct file *filp)
while (retries--) {
result = usb_control_msg(serial->dev,
usb_sndctrlpipe(serial->dev, 0), 0x22, 0x21,
- 0x1, 0, NULL, 0, HZ / 10 + 1);
+ 0x1, 0, NULL, 0, 100);
if (result == 0) {
return 0;
}
diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c
index 20977939271c8..11105d74f461d 100644
--- a/drivers/usb/serial/ipw.c
+++ b/drivers/usb/serial/ipw.c
@@ -232,7 +232,7 @@ static int ipw_open(struct usb_serial_port *port, struct file *filp)
0, /* index */
NULL,
0,
- 100*HZ);
+ 100000);
if (result < 0)
dev_err(&port->dev, "Init of modem failed (error = %d)", result);
@@ -260,7 +260,7 @@ static int ipw_open(struct usb_serial_port *port, struct file *filp)
0, /* index */
NULL,
0,
- 100*HZ);
+ 100000);
if (result < 0)
dev_err(&port->dev, "Enabling bulk RxRead failed (error = %d)", result);
@@ -273,7 +273,7 @@ static int ipw_open(struct usb_serial_port *port, struct file *filp)
0,
buf_flow_init,
0x10,
- 200*HZ);
+ 200000);
if (result < 0)
dev_err(&port->dev, "initial flowcontrol failed (error = %d)", result);
@@ -287,7 +287,7 @@ static int ipw_open(struct usb_serial_port *port, struct file *filp)
0,
NULL,
0,
- 200*HZ);
+ 200000);
if (result < 0)
dev_err(&port->dev, "setting dtr failed (error = %d)", result);
@@ -300,7 +300,7 @@ static int ipw_open(struct usb_serial_port *port, struct file *filp)
0,
NULL,
0,
- 200*HZ);
+ 200000);
if (result < 0)
dev_err(&port->dev, "setting dtr failed (error = %d)", result);
@@ -327,7 +327,7 @@ static void ipw_close(struct usb_serial_port *port, struct file * filp)
0,
NULL,
0,
- 200*HZ);
+ 200000);
if (result < 0)
dev_err(&port->dev, "dropping dtr failed (error = %d)", result);
@@ -339,7 +339,7 @@ static void ipw_close(struct usb_serial_port *port, struct file * filp)
0,
NULL,
0,
- 200*HZ);
+ 200000);
if (result < 0)
dev_err(&port->dev, "dropping rts failed (error = %d)", result);
@@ -352,7 +352,7 @@ static void ipw_close(struct usb_serial_port *port, struct file * filp)
0,
NULL,
0,
- 200*HZ);
+ 200000);
if (result < 0)
dev_err(&port->dev, "purge failed (error = %d)", result);
@@ -365,7 +365,7 @@ static void ipw_close(struct usb_serial_port *port, struct file * filp)
0, /* index */
NULL,
0,
- 100*HZ);
+ 100000);
if (result < 0)
dev_err(&port->dev, "Disabling bulk RxRead failed (error = %d)", result);
@@ -457,7 +457,7 @@ static struct usb_serial_device_type ipw_device = {
-int usb_ipw_init(void)
+static int usb_ipw_init(void)
{
int retval;
@@ -473,7 +473,7 @@ int usb_ipw_init(void)
return 0;
}
-void usb_ipw_exit(void)
+static void usb_ipw_exit(void)
{
usb_deregister(&usb_ipw_driver);
usb_serial_deregister(&ipw_device);
diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c
index 3003cd04300ef..59f234df5f895 100644
--- a/drivers/usb/serial/ir-usb.c
+++ b/drivers/usb/serial/ir-usb.c
@@ -189,7 +189,7 @@ static struct irda_class_desc *irda_usb_find_class_desc(struct usb_device *dev,
ret = usb_control_msg(dev, usb_rcvctrlpipe(dev,0),
IU_REQ_GET_CLASS_DESC,
USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
- 0, ifnum, desc, sizeof(*desc), HZ);
+ 0, ifnum, desc, sizeof(*desc), 1000);
dbg("%s - ret=%d", __FUNCTION__, ret);
if (ret < sizeof(*desc)) {
diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c
index eaa290bbf40d2..7fd0aa9eccf6e 100644
--- a/drivers/usb/serial/keyspan_pda.c
+++ b/drivers/usb/serial/keyspan_pda.c
@@ -205,7 +205,7 @@ static void keyspan_pda_request_unthrottle( struct usb_serial *serial )
0, /* index */
NULL,
0,
- 2*HZ);
+ 2000);
if (result < 0)
dbg("%s - error %d from usb_control_msg",
__FUNCTION__, result);
@@ -330,7 +330,7 @@ static int keyspan_pda_setbaud (struct usb_serial *serial, int baud)
0, /* index */
NULL, /* &data */
0, /* size */
- 2*HZ); /* timeout */
+ 2000); /* timeout */
return(rc);
}
@@ -348,7 +348,7 @@ static void keyspan_pda_break_ctl (struct usb_serial_port *port, int break_state
result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
4, /* set break */
USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
- value, 0, NULL, 0, 2*HZ);
+ value, 0, NULL, 0, 2000);
if (result < 0)
dbg("%s - error %d from usb_control_msg",
__FUNCTION__, result);
@@ -416,7 +416,7 @@ static int keyspan_pda_get_modem_info(struct usb_serial *serial,
rc = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
3, /* get pins */
USB_TYPE_VENDOR|USB_RECIP_INTERFACE|USB_DIR_IN,
- 0, 0, &data, 1, 2*HZ);
+ 0, 0, &data, 1, 2000);
if (rc > 0)
*value = data;
return rc;
@@ -430,7 +430,7 @@ static int keyspan_pda_set_modem_info(struct usb_serial *serial,
rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
3, /* set pins */
USB_TYPE_VENDOR|USB_RECIP_INTERFACE|USB_DIR_OUT,
- value, 0, NULL, 0, 2*HZ);
+ value, 0, NULL, 0, 2000);
return rc;
}
@@ -545,7 +545,7 @@ static int keyspan_pda_write(struct usb_serial_port *port,
0, /* index */
&room,
1,
- 2*HZ);
+ 2000);
if (rc < 0) {
dbg(" roomquery failed");
goto exit;
@@ -653,7 +653,7 @@ static int keyspan_pda_open (struct usb_serial_port *port, struct file *filp)
0, /* index */
&room,
1,
- 2*HZ);
+ 2000);
if (rc < 0) {
dbg("%s - roomquery failed", __FUNCTION__);
goto error;
diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c
index 2e261c73cfcd3..49c602a0b4dfc 100644
--- a/drivers/usb/serial/kl5kusb105.c
+++ b/drivers/usb/serial/kl5kusb105.c
@@ -178,7 +178,7 @@ struct klsi_105_private {
*/
-#define KLSI_TIMEOUT (HZ * 5 ) /* default urb timeout */
+#define KLSI_TIMEOUT 5000 /* default urb timeout */
static int klsi_105_chg_port_settings(struct usb_serial_port *port,
struct klsi_105_port_settings *settings)
@@ -236,7 +236,7 @@ static int klsi_105_get_line_state(struct usb_serial_port *port,
0, /* value */
0, /* index */
status_buf, KLSI_STATUSBUF_LEN,
- 10*HZ
+ 10000
);
if (rc < 0)
err("Reading line status failed (error = %d)", rc);
@@ -925,45 +925,34 @@ static int klsi_105_ioctl (struct usb_serial_port *port, struct file * file,
/* TODO */
dbg("%s - TIOCMIWAIT not handled", __FUNCTION__);
return -ENOIOCTLCMD;
-
case TIOCGICOUNT:
/* return count of modemline transitions */
/* TODO */
dbg("%s - TIOCGICOUNT not handled", __FUNCTION__);
return -ENOIOCTLCMD;
- case TCGETS: {
- /* return current info to caller */
- int retval;
-
- dbg("%s - TCGETS data faked/incomplete", __FUNCTION__);
-
- retval = verify_area(VERIFY_WRITE, user_arg,
- sizeof(struct termios));
- if (retval)
- return retval;
-
- if (kernel_termios_to_user_termios((struct termios __user *)arg,
- &priv->termios))
- return -EFAULT;
- return(0);
- }
- case TCSETS: {
- /* set port termios to the one given by the user */
- int retval;
+ case TCGETS:
+ /* return current info to caller */
+ dbg("%s - TCGETS data faked/incomplete", __FUNCTION__);
+
+ if (!access_ok(VERIFY_WRITE, user_arg, sizeof(struct termios)))
+ return -EFAULT;
+ if (kernel_termios_to_user_termios((struct termios __user *)arg,
+ &priv->termios))
+ return -EFAULT;
+ return 0;
+ case TCSETS:
+ /* set port termios to the one given by the user */
dbg("%s - TCSETS not handled", __FUNCTION__);
- retval = verify_area(VERIFY_READ, user_arg,
- sizeof(struct termios));
- if (retval)
- return retval;
+ if (!access_ok(VERIFY_READ, user_arg, sizeof(struct termios)))
+ return -EFAULT;
if (user_termios_to_kernel_termios(&priv->termios,
- (struct termios __user *)arg))
+ (struct termios __user *)arg))
return -EFAULT;
klsi_105_set_termios(port, &priv->termios);
- return(0);
- }
+ return 0;
case TCSETSW: {
/* set port termios and try to wait for completion of last
* write operation */
diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c
index 10d5cd1377a58..fe4c98a751714 100644
--- a/drivers/usb/serial/kobil_sct.c
+++ b/drivers/usb/serial/kobil_sct.c
@@ -637,10 +637,9 @@ static int kobil_ioctl(struct usb_serial_port *port, struct file *file,
switch (cmd) {
case TCGETS: // 0x5401
- result = verify_area(VERIFY_WRITE, user_arg, sizeof(struct termios));
- if (result) {
- dbg("%s - port %d Error in verify_area", __FUNCTION__, port->number);
- return(result);
+ if (!access_ok(VERIFY_WRITE, user_arg, sizeof(struct termios))) {
+ dbg("%s - port %d Error in access_ok", __FUNCTION__, port->number);
+ return -EFAULT;
}
if (kernel_termios_to_user_termios((struct termios __user *)arg,
&priv->internal_termios))
@@ -652,10 +651,9 @@ static int kobil_ioctl(struct usb_serial_port *port, struct file *file,
dbg("%s - port %d Error: port->tty->termios is NULL", __FUNCTION__, port->number);
return -ENOTTY;
}
- result = verify_area(VERIFY_READ, user_arg, sizeof(struct termios));
- if (result) {
- dbg("%s - port %d Error in verify_area", __FUNCTION__, port->number);
- return result;
+ if (!access_ok(VERIFY_READ, user_arg, sizeof(struct termios))) {
+ dbg("%s - port %d Error in access_ok", __FUNCTION__, port->number);
+ return -EFAULT;
}
if (user_termios_to_kernel_termios(&priv->internal_termios,
(struct termios __user *)arg))
diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c
index a61fecf5cdd12..50b6369647d25 100644
--- a/drivers/usb/serial/mct_u232.c
+++ b/drivers/usb/serial/mct_u232.c
@@ -166,7 +166,7 @@ struct mct_u232_private {
* Handle vendor specific USB requests
*/
-#define WDR_TIMEOUT (HZ * 5 ) /* default urb timeout */
+#define WDR_TIMEOUT 5000 /* default urb timeout */
/*
* Later day 2.6.0-test kernels have new baud rates like B230400 which
@@ -195,16 +195,16 @@ static int mct_u232_calculate_baud_rate(struct usb_serial *serial, int value)
}
} else {
switch (value) {
- case B300: value = 300;
- case B600: value = 600;
- case B1200: value = 1200;
- case B2400: value = 2400;
- case B4800: value = 4800;
- case B9600: value = 9600;
- case B19200: value = 19200;
- case B38400: value = 38400;
- case B57600: value = 57600;
- case B115200: value = 115200;
+ case B300: value = 300; break;
+ case B600: value = 600; break;
+ case B1200: value = 1200; break;
+ case B2400: value = 2400; break;
+ case B4800: value = 4800; break;
+ case B9600: value = 9600; break;
+ case B19200: value = 19200; break;
+ case B38400: value = 38400; break;
+ case B57600: value = 57600; break;
+ case B115200: value = 115200; break;
default:
err("MCT USB-RS232: unsupported baudrate request 0x%x,"
" using default of B9600", value);
@@ -646,7 +646,7 @@ static void mct_u232_set_termios (struct usb_serial_port *port,
else
new_state &= ~(TIOCM_DTR | TIOCM_RTS);
if (new_state != control_state) {
- mct_u232_set_modem_ctrl(serial, control_state);
+ mct_u232_set_modem_ctrl(serial, new_state);
control_state = new_state;
}
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c
index dc18427cf4e43..98054876cca25 100644
--- a/drivers/usb/serial/ti_usb_3410_5052.c
+++ b/drivers/usb/serial/ti_usb_3410_5052.c
@@ -1580,7 +1580,7 @@ static int ti_command_out_sync(struct ti_device *tdev, __u8 command,
status = usb_control_msg(tdev->td_serial->dev,
usb_sndctrlpipe(tdev->td_serial->dev, 0), command,
(USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT),
- value, moduleid, data, size, HZ);
+ value, moduleid, data, size, 1000);
if (status == size)
status = 0;
@@ -1600,7 +1600,7 @@ static int ti_command_in_sync(struct ti_device *tdev, __u8 command,
status = usb_control_msg(tdev->td_serial->dev,
usb_rcvctrlpipe(tdev->td_serial->dev, 0), command,
(USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN),
- value, moduleid, data, size, HZ);
+ value, moduleid, data, size, 1000);
if (status == size)
status = 0;
@@ -1685,7 +1685,7 @@ static int ti_download_firmware(struct ti_device *tdev,
dbg("%s - downloading firmware", __FUNCTION__);
for (pos = 0; pos < buffer_size; pos += done) {
len = min(buffer_size - pos, TI_DOWNLOAD_MAX_PACKET_SIZE);
- status = usb_bulk_msg(dev, pipe, buffer+pos, len, &done, HZ);
+ status = usb_bulk_msg(dev, pipe, buffer+pos, len, &done, 1000);
if (status)
break;
}
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 2836dfed6be12..4536f63faaeaa 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -1418,11 +1418,11 @@ void usb_serial_deregister(struct usb_serial_device_type *device)
/* If the usb-serial core is built into the core, the usb-serial drivers
need these symbols to load properly as modules. */
-EXPORT_SYMBOL(usb_serial_register);
-EXPORT_SYMBOL(usb_serial_deregister);
-EXPORT_SYMBOL(usb_serial_probe);
-EXPORT_SYMBOL(usb_serial_disconnect);
-EXPORT_SYMBOL(usb_serial_port_softint);
+EXPORT_SYMBOL_GPL(usb_serial_register);
+EXPORT_SYMBOL_GPL(usb_serial_deregister);
+EXPORT_SYMBOL_GPL(usb_serial_probe);
+EXPORT_SYMBOL_GPL(usb_serial_disconnect);
+EXPORT_SYMBOL_GPL(usb_serial_port_softint);
/* Module information */
diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
index 6c0d51638824b..69d313e98fadb 100644
--- a/drivers/usb/serial/visor.c
+++ b/drivers/usb/serial/visor.c
@@ -243,6 +243,8 @@ static struct usb_device_id id_table [] = {
.driver_info = (kernel_ulong_t)&palm_os_4_probe },
{ USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_7135_ID),
.driver_info = (kernel_ulong_t)&palm_os_4_probe },
+ { USB_DEVICE(FOSSIL_VENDOR_ID, FOSSIL_ABACUS_ID),
+ .driver_info = (kernel_ulong_t)&palm_os_4_probe },
{ }, /* optional parameter entry */
{ } /* Terminating entry */
};
@@ -287,6 +289,7 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(GARMIN_VENDOR_ID, GARMIN_IQUE_3600_ID) },
{ USB_DEVICE(ACEECA_VENDOR_ID, ACEECA_MEZ1000_ID) },
{ USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_7135_ID) },
+ { USB_DEVICE(FOSSIL_VENDOR_ID, FOSSIL_ABACUS_ID) },
{ }, /* optional parameter entry */
{ } /* Terminating entry */
};
@@ -386,6 +389,7 @@ struct visor_private {
int bytes_in;
int bytes_out;
int outstanding_urbs;
+ int throttled;
};
/* number of outstanding urbs to prevent userspace DoS from happening */
@@ -415,6 +419,7 @@ static int visor_open (struct usb_serial_port *port, struct file *filp)
priv->bytes_in = 0;
priv->bytes_out = 0;
priv->outstanding_urbs = 0;
+ priv->throttled = 0;
spin_unlock_irqrestore(&priv->lock, flags);
/*
@@ -602,6 +607,7 @@ static void visor_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
struct tty_struct *tty;
unsigned long flags;
int i;
+ int throttled;
int result;
dbg("%s - port %d", __FUNCTION__, port->number);
@@ -627,18 +633,21 @@ static void visor_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
}
spin_lock_irqsave(&priv->lock, flags);
priv->bytes_in += urb->actual_length;
+ throttled = priv->throttled;
spin_unlock_irqrestore(&priv->lock, flags);
- /* Continue trying to always read */
- usb_fill_bulk_urb (port->read_urb, port->serial->dev,
- usb_rcvbulkpipe(port->serial->dev,
- port->bulk_in_endpointAddress),
- port->read_urb->transfer_buffer,
- port->read_urb->transfer_buffer_length,
- visor_read_bulk_callback, port);
- result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
- if (result)
- dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result);
+ /* Continue trying to always read if we should */
+ if (!throttled) {
+ usb_fill_bulk_urb (port->read_urb, port->serial->dev,
+ usb_rcvbulkpipe(port->serial->dev,
+ port->bulk_in_endpointAddress),
+ port->read_urb->transfer_buffer,
+ port->read_urb->transfer_buffer_length,
+ visor_read_bulk_callback, port);
+ result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+ if (result)
+ dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result);
+ }
return;
}
@@ -683,16 +692,26 @@ exit:
static void visor_throttle (struct usb_serial_port *port)
{
+ struct visor_private *priv = usb_get_serial_port_data(port);
+ unsigned long flags;
+
dbg("%s - port %d", __FUNCTION__, port->number);
- usb_kill_urb(port->read_urb);
+ spin_lock_irqsave(&priv->lock, flags);
+ priv->throttled = 1;
+ spin_unlock_irqrestore(&priv->lock, flags);
}
static void visor_unthrottle (struct usb_serial_port *port)
{
+ struct visor_private *priv = usb_get_serial_port_data(port);
+ unsigned long flags;
int result;
dbg("%s - port %d", __FUNCTION__, port->number);
+ spin_lock_irqsave(&priv->lock, flags);
+ priv->throttled = 0;
+ spin_unlock_irqrestore(&priv->lock, flags);
port->read_urb->dev = port->serial->dev;
result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
@@ -891,7 +910,7 @@ static int clie_3_5_startup (struct usb_serial *serial)
/* get the config number */
result = usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0),
USB_REQ_GET_CONFIGURATION, USB_DIR_IN,
- 0, 0, &data, 1, HZ * 3);
+ 0, 0, &data, 1, 3000);
if (result < 0) {
dev_err(dev, "%s: get config number failed: %d\n", __FUNCTION__, result);
return result;
@@ -905,7 +924,7 @@ static int clie_3_5_startup (struct usb_serial *serial)
result = usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0),
USB_REQ_GET_INTERFACE,
USB_DIR_IN | USB_RECIP_INTERFACE,
- 0, 0, &data, 1, HZ * 3);
+ 0, 0, &data, 1, 3000);
if (result < 0) {
dev_err(dev, "%s: get interface number failed: %d\n", __FUNCTION__, result);
return result;
diff --git a/drivers/usb/serial/visor.h b/drivers/usb/serial/visor.h
index 2effcd0f7a197..a2fa2c61a009f 100644
--- a/drivers/usb/serial/visor.h
+++ b/drivers/usb/serial/visor.h
@@ -58,6 +58,9 @@
#define KYOCERA_VENDOR_ID 0x0C88
#define KYOCERA_7135_ID 0x0021
+#define FOSSIL_VENDOR_ID 0x0E67
+#define FOSSIL_ABACUS_ID 0x0002
+
/****************************************************************************
* Handspring Visor Vendor specific request codes (bRequest values)
* A big thank you to Handspring for providing the following information.
diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
index b6384a3133736..cf3bc30675a15 100644
--- a/drivers/usb/serial/whiteheat.c
+++ b/drivers/usb/serial/whiteheat.c
@@ -254,6 +254,7 @@ static int firm_report_tx_done(struct usb_serial_port *port);
#define COMMAND_PORT 4
#define COMMAND_TIMEOUT (2*HZ) /* 2 second timeout for a command */
+#define COMMAND_TIMEOUT_MS 2000
#define CLOSING_DELAY (30 * HZ)
@@ -379,7 +380,7 @@ static int whiteheat_attach (struct usb_serial *serial)
* unlinking bug in disguise. Same for the call below.
*/
usb_clear_halt(serial->dev, pipe);
- ret = usb_bulk_msg (serial->dev, pipe, command, 2, &alen, COMMAND_TIMEOUT);
+ ret = usb_bulk_msg (serial->dev, pipe, command, 2, &alen, COMMAND_TIMEOUT_MS);
if (ret) {
err("%s: Couldn't send command [%d]", serial->type->name, ret);
goto no_firmware;
@@ -391,7 +392,7 @@ static int whiteheat_attach (struct usb_serial *serial)
pipe = usb_rcvbulkpipe (serial->dev, command_port->bulk_in_endpointAddress);
/* See the comment on the usb_clear_halt() above */
usb_clear_halt(serial->dev, pipe);
- ret = usb_bulk_msg (serial->dev, pipe, result, sizeof(*hw_info) + 1, &alen, COMMAND_TIMEOUT);
+ ret = usb_bulk_msg (serial->dev, pipe, result, sizeof(*hw_info) + 1, &alen, COMMAND_TIMEOUT_MS);
if (ret) {
err("%s: Couldn't get results [%d]", serial->type->name, ret);
goto no_firmware;
diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig
index 1099581dea417..f1f1c0608c22a 100644
--- a/drivers/usb/storage/Kconfig
+++ b/drivers/usb/storage/Kconfig
@@ -3,6 +3,7 @@
#
comment "NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information"
+ depends on USB
config USB_STORAGE
tristate "USB Mass Storage support"
@@ -30,28 +31,6 @@ config USB_STORAGE_DEBUG
Say Y here in order to have the USB Mass Storage code generate
verbose debugging messages.
-config USB_STORAGE_RW_DETECT
- bool "USB Mass Storage Write-Protected Media Detection (EXPERIMENTAL)"
- depends on USB_STORAGE && EXPERIMENTAL
- help
- Say Y here in order to have the USB Mass Storage code indicate to
- the SCSI layer that using MODE SENSE(6) and MODE SENSE(10) to
- determine if the media is write-protected is a good thing to do.
-
- Many devices have historically had trouble with these commands,
- hence the default 2.6.x behavior has been to suppress their use.
- 2.4.x used these commands with (at best) mixed results, often
- crashing the firmware of the device. However, the SCSI layer now
- issues these commands in a manner more consistent with other
- "popular" OSes, in an attempt to improve compatibility.
-
- Saying Y here allows these commands to be sent to a USB device.
- If you find a device this doesn't work for, switch to N and let
- us know at <usb-storage@lists.one-eyed-alien.net>
-
- If you say N here, the kernel will assume that all disk-like USB
- devices are write-enabled.
-
config USB_STORAGE_DATAFAB
bool "Datafab Compact Flash Reader support (EXPERIMENTAL)"
depends on USB_STORAGE && EXPERIMENTAL
@@ -89,12 +68,26 @@ config USB_STORAGE_DPCM
Say Y here to support the Microtech/ZiO! CompactFlash reader.
There is a web page at <http://www.ziocorp.com/products/>.
-config USB_STORAGE_HP8200e
- bool "HP CD-Writer 82xx support (EXPERIMENTAL)"
+config USB_STORAGE_USBAT
+ bool "USBAT/USBAT02-based storage support (EXPERIMENTAL)"
depends on USB_STORAGE && EXPERIMENTAL
help
- Say Y here to include additional code to support Hewlett-Packard
- 8200e/8210e/8230e CD-Writer Plus drives.
+ Say Y here to include additional code to support storage devices
+ based on the SCM/Shuttle USBAT/USBAT02 processors.
+
+ Devices reported to work with this driver include:
+ - CompactFlash reader included with Kodak DC3800 camera
+ - Dane-Elec Zmate CompactFlash reader
+ - Delkin Efilm reader2
+ - HP 8200e/8210e/8230e CD-Writer Plus drives
+ - I-JAM JS-50U
+ - Jessops CompactFlash JESDCFRU BLACK
+ - Kingston Technology PCREAD-USB/CF
+ - Maxell UA4 CompactFlash reader
+ - Memorex UCF-100
+ - Microtech ZiO! ICS-45 CF2
+ - RCA LYRA MP3 portable
+ - Sandisk ImageMate SDDR-05b
config USB_STORAGE_SDDR09
bool "SanDisk SDDR-09 (and other SmartMedia) support (EXPERIMENTAL)"
diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile
index 40b535fb6e11e..56652ccc2881c 100644
--- a/drivers/usb/storage/Makefile
+++ b/drivers/usb/storage/Makefile
@@ -10,7 +10,7 @@ EXTRA_CFLAGS := -Idrivers/scsi
obj-$(CONFIG_USB_STORAGE) += usb-storage.o
usb-storage-obj-$(CONFIG_USB_STORAGE_DEBUG) += debug.o
-usb-storage-obj-$(CONFIG_USB_STORAGE_HP8200e) += shuttle_usbat.o
+usb-storage-obj-$(CONFIG_USB_STORAGE_USBAT) += shuttle_usbat.o
usb-storage-obj-$(CONFIG_USB_STORAGE_SDDR09) += sddr09.o
usb-storage-obj-$(CONFIG_USB_STORAGE_SDDR55) += sddr55.o
usb-storage-obj-$(CONFIG_USB_STORAGE_FREECOM) += freecom.o
diff --git a/drivers/usb/storage/datafab.c b/drivers/usb/storage/datafab.c
index 94798eb1a525f..54e3e6c7ecd86 100644
--- a/drivers/usb/storage/datafab.c
+++ b/drivers/usb/storage/datafab.c
@@ -57,9 +57,9 @@
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
+#include "usb.h"
#include "transport.h"
#include "protocol.h"
-#include "usb.h"
#include "debug.h"
#include "datafab.h"
diff --git a/drivers/usb/storage/debug.h b/drivers/usb/storage/debug.h
index c4f4bcf36785f..cd2096acc723e 100644
--- a/drivers/usb/storage/debug.h
+++ b/drivers/usb/storage/debug.h
@@ -47,8 +47,6 @@
#include <linux/config.h>
#include <linux/kernel.h>
-struct scsi_cmnd;
-
#define USB_STORAGE "usb-storage: "
#ifdef CONFIG_USB_STORAGE_DEBUG
diff --git a/drivers/usb/storage/dpcm.c b/drivers/usb/storage/dpcm.c
index 12c15f19a4f33..92b69e4c80478 100644
--- a/drivers/usb/storage/dpcm.c
+++ b/drivers/usb/storage/dpcm.c
@@ -34,9 +34,9 @@
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_device.h>
+#include "usb.h"
#include "transport.h"
#include "protocol.h"
-#include "usb.h"
#include "debug.h"
#include "dpcm.h"
#include "sddr09.h"
diff --git a/drivers/usb/storage/freecom.c b/drivers/usb/storage/freecom.c
index 9df27f05d21cb..30e96050fe0c6 100644
--- a/drivers/usb/storage/freecom.c
+++ b/drivers/usb/storage/freecom.c
@@ -34,9 +34,9 @@
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
+#include "usb.h"
#include "transport.h"
#include "protocol.h"
-#include "usb.h"
#include "debug.h"
#include "freecom.h"
diff --git a/drivers/usb/storage/initializers.c b/drivers/usb/storage/initializers.c
index ff5549a744edd..5b06f9240d05c 100644
--- a/drivers/usb/storage/initializers.c
+++ b/drivers/usb/storage/initializers.c
@@ -39,6 +39,8 @@
#include <linux/sched.h>
#include <linux/errno.h>
+
+#include "usb.h"
#include "initializers.h"
#include "debug.h"
#include "transport.h"
diff --git a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c
index d6ac358bb86e1..ecb328aa9ea1b 100644
--- a/drivers/usb/storage/isd200.c
+++ b/drivers/usb/storage/isd200.c
@@ -54,9 +54,9 @@
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_device.h>
+#include "usb.h"
#include "transport.h"
#include "protocol.h"
-#include "usb.h"
#include "debug.h"
#include "scsiglue.h"
#include "isd200.h"
diff --git a/drivers/usb/storage/jumpshot.c b/drivers/usb/storage/jumpshot.c
index 24464ece5134c..aff9d51c327cd 100644
--- a/drivers/usb/storage/jumpshot.c
+++ b/drivers/usb/storage/jumpshot.c
@@ -54,9 +54,9 @@
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
+#include "usb.h"
#include "transport.h"
#include "protocol.h"
-#include "usb.h"
#include "debug.h"
#include "jumpshot.h"
diff --git a/drivers/usb/storage/protocol.c b/drivers/usb/storage/protocol.c
index 9d3d774525258..9ad30428d2dd5 100644
--- a/drivers/usb/storage/protocol.c
+++ b/drivers/usb/storage/protocol.c
@@ -47,46 +47,14 @@
#include <linux/highmem.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
-#include "protocol.h"
+
#include "usb.h"
+#include "protocol.h"
#include "debug.h"
#include "scsiglue.h"
#include "transport.h"
/***********************************************************************
- * Helper routines
- ***********************************************************************/
-
-/*
- * Fix-up the return data from a READ CAPACITY command. My Feiya reader
- * returns a value that is 1 too large.
- */
-static void fix_read_capacity(struct scsi_cmnd *srb)
-{
- unsigned int index, offset;
- __be32 c;
- unsigned long capacity;
-
- /* verify that it's a READ CAPACITY command */
- if (srb->cmnd[0] != READ_CAPACITY)
- return;
-
- index = offset = 0;
- if (usb_stor_access_xfer_buf((unsigned char *) &c, 4, srb,
- &index, &offset, FROM_XFER_BUF) != 4)
- return;
-
- capacity = be32_to_cpu(c);
- US_DEBUGP("US: Fixing capacity: from %ld to %ld\n",
- capacity+1, capacity);
- c = cpu_to_be32(capacity - 1);
-
- index = offset = 0;
- usb_stor_access_xfer_buf((unsigned char *) &c, 4, srb,
- &index, &offset, TO_XFER_BUF);
-}
-
-/***********************************************************************
* Protocol routines
***********************************************************************/
@@ -174,12 +142,6 @@ void usb_stor_transparent_scsi_command(struct scsi_cmnd *srb,
{
/* send the command to the transport layer */
usb_stor_invoke_transport(srb, us);
-
- if (srb->result == SAM_STAT_GOOD) {
- /* Fix the READ CAPACITY result if necessary */
- if (us->flags & US_FL_FIX_CAPACITY)
- fix_read_capacity(srb);
- }
}
/***********************************************************************
diff --git a/drivers/usb/storage/protocol.h b/drivers/usb/storage/protocol.h
index 7aa460d3b7df8..02bff01ab09c3 100644
--- a/drivers/usb/storage/protocol.h
+++ b/drivers/usb/storage/protocol.h
@@ -41,9 +41,6 @@
#ifndef _PROTOCOL_H_
#define _PROTOCOL_H_
-struct scsi_cmnd;
-struct us_data;
-
/* Sub Classes */
#define US_SC_RBC 0x01 /* Typically, flash devices */
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
index 714e8328c8412..22e48a2b0bd18 100644
--- a/drivers/usb/storage/scsiglue.c
+++ b/drivers/usb/storage/scsiglue.c
@@ -53,10 +53,9 @@
#include <scsi/scsi_devinfo.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_eh.h>
-#include <scsi/scsi_host.h>
-#include "scsiglue.h"
#include "usb.h"
+#include "scsiglue.h"
#include "debug.h"
#include "transport.h"
#include "protocol.h"
@@ -83,7 +82,7 @@ static int slave_alloc (struct scsi_device *sdev)
static int slave_configure(struct scsi_device *sdev)
{
- struct us_data *us = (struct us_data *) sdev->host->hostdata[0];
+ struct us_data *us = host_to_us(sdev->host);
/* Scatter-gather buffers (all but the last) must have a length
* divisible by the bulk maxpacket size. Otherwise a data packet
@@ -137,18 +136,25 @@ static int slave_configure(struct scsi_device *sdev)
* 192 bytes (that's what Windows uses). */
sdev->use_192_bytes_for_3f = 1;
+ /* Some devices don't like MODE SENSE with page=0x3f,
+ * which is the command used for checking if a device
+ * is write-protected. Now that we tell the sd driver
+ * to do a 192-byte transfer with this command the
+ * majority of devices work fine, but a few still can't
+ * handle it. The sd driver will simply assume those
+ * devices are write-enabled. */
+ if (us->flags & US_FL_NO_WP_DETECT)
+ sdev->skip_ms_page_3f = 1;
+
/* A number of devices have problems with MODE SENSE for
* page x08, so we will skip it. */
sdev->skip_ms_page_8 = 1;
-#ifndef CONFIG_USB_STORAGE_RW_DETECT
- /* Some devices may not like MODE SENSE with page=0x3f.
- * Now that we're using 192-byte transfers this may no
- * longer be a problem. So this will be a configuration
- * option. */
- sdev->skip_ms_page_3f = 1;
-#endif
-
+ /* Some disks return the total number of blocks in response
+ * to READ CAPACITY rather than the highest block number.
+ * If this device makes that mistake, tell the sd driver. */
+ if (us->flags & US_FL_FIX_CAPACITY)
+ sdev->fix_capacity = 1;
} else {
/* Non-disk-type devices don't need to blacklist any pages
@@ -157,20 +163,24 @@ static int slave_configure(struct scsi_device *sdev)
sdev->use_10_for_ms = 1;
}
+ /* Some devices choke when they receive a PREVENT-ALLOW MEDIUM
+ * REMOVAL command, so suppress those commands. */
+ if (us->flags & US_FL_NOT_LOCKABLE)
+ sdev->lockable = 0;
+
/* this is to satisfy the compiler, tho I don't think the
* return code is ever checked anywhere. */
return 0;
}
/* queue a command */
-/* This is always called with scsi_lock(srb->host) held */
+/* This is always called with scsi_lock(host) held */
static int queuecommand(struct scsi_cmnd *srb,
void (*done)(struct scsi_cmnd *))
{
- struct us_data *us = (struct us_data *)srb->device->host->hostdata[0];
+ struct us_data *us = host_to_us(srb->device->host);
US_DEBUGP("%s called\n", __FUNCTION__);
- srb->host_scribble = (unsigned char *)us;
/* check for state-transition errors */
if (us->srb != NULL) {
@@ -200,11 +210,10 @@ static int queuecommand(struct scsi_cmnd *srb,
***********************************************************************/
/* Command timeout and abort */
-/* This is always called with scsi_lock(srb->host) held */
-static int command_abort(struct scsi_cmnd *srb )
+/* This is always called with scsi_lock(host) held */
+static int command_abort(struct scsi_cmnd *srb)
{
- struct Scsi_Host *host = srb->device->host;
- struct us_data *us = (struct us_data *) host->hostdata[0];
+ struct us_data *us = host_to_us(srb->device->host);
US_DEBUGP("%s called\n", __FUNCTION__);
@@ -224,13 +233,13 @@ static int command_abort(struct scsi_cmnd *srb )
set_bit(US_FLIDX_ABORTING, &us->flags);
usb_stor_stop_transport(us);
}
- scsi_unlock(host);
+ scsi_unlock(us_to_host(us));
/* Wait for the aborted command to finish */
wait_for_completion(&us->notify);
/* Reacquire the lock and allow USB transfers to resume */
- scsi_lock(host);
+ scsi_lock(us_to_host(us));
clear_bit(US_FLIDX_ABORTING, &us->flags);
clear_bit(US_FLIDX_TIMED_OUT, &us->flags);
return SUCCESS;
@@ -238,15 +247,15 @@ static int command_abort(struct scsi_cmnd *srb )
/* This invokes the transport reset mechanism to reset the state of the
* device */
-/* This is always called with scsi_lock(srb->host) held */
+/* This is always called with scsi_lock(host) held */
static int device_reset(struct scsi_cmnd *srb)
{
- struct us_data *us = (struct us_data *)srb->device->host->hostdata[0];
+ struct us_data *us = host_to_us(srb->device->host);
int result;
US_DEBUGP("%s called\n", __FUNCTION__);
- scsi_unlock(srb->device->host);
+ scsi_unlock(us_to_host(us));
/* lock the device pointers and do the reset */
down(&(us->dev_semaphore));
@@ -258,22 +267,22 @@ static int device_reset(struct scsi_cmnd *srb)
up(&(us->dev_semaphore));
/* lock the host for the return */
- scsi_lock(srb->device->host);
+ scsi_lock(us_to_host(us));
return result;
}
/* This resets the device's USB port. */
/* It refuses to work if there's more than one interface in
* the device, so that other users are not affected. */
-/* This is always called with scsi_lock(srb->host) held */
+/* This is always called with scsi_lock(host) held */
static int bus_reset(struct scsi_cmnd *srb)
{
- struct us_data *us = (struct us_data *)srb->device->host->hostdata[0];
+ struct us_data *us = host_to_us(srb->device->host);
int result, rc;
US_DEBUGP("%s called\n", __FUNCTION__);
- scsi_unlock(srb->device->host);
+ scsi_unlock(us_to_host(us));
/* The USB subsystem doesn't handle synchronisation between
* a device's several drivers. Therefore we reset only devices
@@ -301,7 +310,7 @@ static int bus_reset(struct scsi_cmnd *srb)
up(&(us->dev_semaphore));
/* lock the host for the return */
- scsi_lock(srb->device->host);
+ scsi_lock(us_to_host(us));
return result < 0 ? FAILED : SUCCESS;
}
@@ -311,11 +320,12 @@ static int bus_reset(struct scsi_cmnd *srb)
void usb_stor_report_device_reset(struct us_data *us)
{
int i;
+ struct Scsi_Host *host = us_to_host(us);
- scsi_report_device_reset(us->host, 0, 0);
+ scsi_report_device_reset(host, 0, 0);
if (us->flags & US_FL_SCM_MULT_TARG) {
- for (i = 1; i < us->host->max_id; ++i)
- scsi_report_device_reset(us->host, 0, i);
+ for (i = 1; i < host->max_id; ++i)
+ scsi_report_device_reset(host, 0, i);
}
}
@@ -327,28 +337,41 @@ void usb_stor_report_device_reset(struct us_data *us)
#undef SPRINTF
#define SPRINTF(args...) \
do { if (pos < buffer+length) pos += sprintf(pos, ## args); } while (0)
-#define DO_FLAG(a) \
- do { if (us->flags & US_FL_##a) pos += sprintf(pos, " " #a); } while(0)
-static int proc_info (struct Scsi_Host *hostptr, char *buffer, char **start, off_t offset,
- int length, int inout)
+static int proc_info (struct Scsi_Host *host, char *buffer,
+ char **start, off_t offset, int length, int inout)
{
- struct us_data *us;
+ struct us_data *us = host_to_us(host);
char *pos = buffer;
+ const char *string;
/* if someone is sending us data, just throw it away */
if (inout)
return length;
- us = (struct us_data*)hostptr->hostdata[0];
-
/* print the controller name */
- SPRINTF(" Host scsi%d: usb-storage\n", hostptr->host_no);
+ SPRINTF(" Host scsi%d: usb-storage\n", host->host_no);
/* print product, vendor, and serial number strings */
- SPRINTF(" Vendor: %s\n", us->vendor);
- SPRINTF(" Product: %s\n", us->product);
- SPRINTF("Serial Number: %s\n", us->serial);
+ if (us->pusb_dev->manufacturer)
+ string = us->pusb_dev->manufacturer;
+ else if (us->unusual_dev->vendorName)
+ string = us->unusual_dev->vendorName;
+ else
+ string = "Unknown";
+ SPRINTF(" Vendor: %s\n", string);
+ if (us->pusb_dev->product)
+ string = us->pusb_dev->product;
+ else if (us->unusual_dev->productName)
+ string = us->unusual_dev->productName;
+ else
+ string = "Unknown";
+ SPRINTF(" Product: %s\n", string);
+ if (us->pusb_dev->serial)
+ string = us->pusb_dev->serial;
+ else
+ string = "None";
+ SPRINTF("Serial Number: %s\n", string);
/* show the protocol and transport */
SPRINTF(" Protocol: %s\n", us->protocol_name);
@@ -358,10 +381,10 @@ static int proc_info (struct Scsi_Host *hostptr, char *buffer, char **start, off
if (pos < buffer + length) {
pos += sprintf(pos, " Quirks:");
- DO_FLAG(SINGLE_LUN);
- DO_FLAG(SCM_MULT_TARG);
- DO_FLAG(FIX_INQUIRY);
- DO_FLAG(FIX_CAPACITY);
+#define US_FLAG(name, value) \
+ if (us->flags & value) pos += sprintf(pos, " " #name);
+US_DO_ALL_FLAGS
+#undef US_FLAG
*(pos++) = '\n';
}
@@ -467,15 +490,6 @@ struct scsi_host_template usb_stor_host_template = {
.module = THIS_MODULE
};
-/* For a device that is "Not Ready" */
-unsigned char usb_stor_sense_notready[18] = {
- [0] = 0x70, /* current error */
- [2] = 0x02, /* not ready */
- [7] = 0x0a, /* additional length */
- [12] = 0x04, /* not ready */
- [13] = 0x03 /* manual intervention */
-};
-
/* To Report "Illegal Request: Invalid Field in CDB */
unsigned char usb_stor_sense_invalidCDB[18] = {
[0] = 0x70, /* current error */
diff --git a/drivers/usb/storage/scsiglue.h b/drivers/usb/storage/scsiglue.h
index 70df2a7bc1fa3..d0a49af026c42 100644
--- a/drivers/usb/storage/scsiglue.h
+++ b/drivers/usb/storage/scsiglue.h
@@ -41,14 +41,8 @@
#ifndef _SCSIGLUE_H_
#define _SCSIGLUE_H_
-#include <scsi/scsi_host.h>
-
-struct us_data;
-struct scsi_cmnd;
-
extern void usb_stor_report_device_reset(struct us_data *us);
-extern unsigned char usb_stor_sense_notready[18];
extern unsigned char usb_stor_sense_invalidCDB[18];
extern struct scsi_host_template usb_stor_host_template;
diff --git a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c
index ff81b40c2c69c..0ea2f5ab66ba2 100644
--- a/drivers/usb/storage/sddr09.c
+++ b/drivers/usb/storage/sddr09.c
@@ -48,9 +48,9 @@
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
+#include "usb.h"
#include "transport.h"
#include "protocol.h"
-#include "usb.h"
#include "debug.h"
#include "sddr09.h"
diff --git a/drivers/usb/storage/sddr55.c b/drivers/usb/storage/sddr55.c
index 10270f42a658e..229ca181716b5 100644
--- a/drivers/usb/storage/sddr55.c
+++ b/drivers/usb/storage/sddr55.c
@@ -31,9 +31,9 @@
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
+#include "usb.h"
#include "transport.h"
#include "protocol.h"
-#include "usb.h"
#include "debug.h"
#include "sddr55.h"
diff --git a/drivers/usb/storage/shuttle_usbat.c b/drivers/usb/storage/shuttle_usbat.c
index c98fa393814f2..7eff03d9b041c 100644
--- a/drivers/usb/storage/shuttle_usbat.c
+++ b/drivers/usb/storage/shuttle_usbat.c
@@ -4,10 +4,14 @@
*
* Current development and maintenance by:
* (c) 2000, 2001 Robert Baruch (autophile@starband.net)
+ * (c) 2004, 2005 Daniel Drake <dsd@gentoo.org>
*
* Developed with the assistance of:
* (c) 2002 Alan Stern <stern@rowland.org>
*
+ * Flash support based on earlier work by:
+ * (c) 2002 Thomas Kreiling <usbdev@sm04.de>
+ *
* Many originally ATAPI devices were slightly modified to meet the USB
* market by using some kind of translation from ATAPI to USB on the host,
* and the peripheral would translate from USB back to ATAPI.
@@ -21,8 +25,8 @@
* as well. This driver is only guaranteed to work with the ATAPI
* translation.
*
- * The only peripheral that I know of (as of 27 Mar 2001) that uses this
- * device is the Hewlett-Packard 8200e/8210e/8230e CD-Writer Plus.
+ * See the Kconfig help text for a list of devices known to be supported by
+ * this driver.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -47,9 +51,9 @@
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
+#include "usb.h"
#include "transport.h"
#include "protocol.h"
-#include "usb.h"
#include "debug.h"
#include "shuttle_usbat.h"
@@ -57,46 +61,154 @@
#define LSB_of(s) ((s)&0xFF)
#define MSB_of(s) ((s)>>8)
-int transferred = 0;
+static int transferred = 0;
+
+static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us);
+static int usbat_hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us);
+/*
+ * Convenience function to produce an ATAPI read/write sectors command
+ * Use cmd=0x20 for read, cmd=0x30 for write
+ */
+static void usbat_pack_atapi_sector_cmd(unsigned char *buf,
+ unsigned char thistime,
+ u32 sector, unsigned char cmd)
+{
+ buf[0] = 0;
+ buf[1] = thistime;
+ buf[2] = sector & 0xFF;
+ buf[3] = (sector >> 8) & 0xFF;
+ buf[4] = (sector >> 16) & 0xFF;
+ buf[5] = 0xE0 | ((sector >> 24) & 0x0F);
+ buf[6] = cmd;
+}
+
+/*
+ * Convenience function to get the device type (flash or hp8200)
+ */
+static int usbat_get_device_type(struct us_data *us)
+{
+ return ((struct usbat_info*)us->extra)->devicetype;
+}
+
+/*
+ * Read a register from the device
+ */
static int usbat_read(struct us_data *us,
unsigned char access,
unsigned char reg,
unsigned char *content)
{
- int result;
-
- result = usb_stor_ctrl_transfer(us,
+ return usb_stor_ctrl_transfer(us,
us->recv_ctrl_pipe,
- access,
+ access | USBAT_CMD_READ_REG,
0xC0,
(u16)reg,
0,
content,
1);
-
- return result;
}
+/*
+ * Write to a register on the device
+ */
static int usbat_write(struct us_data *us,
unsigned char access,
unsigned char reg,
unsigned char content)
{
- int result;
-
- result = usb_stor_ctrl_transfer(us,
+ return usb_stor_ctrl_transfer(us,
us->send_ctrl_pipe,
- access|0x01,
+ access | USBAT_CMD_WRITE_REG,
0x40,
short_pack(reg, content),
0,
NULL,
0);
+}
- return result;
+/*
+ * Convenience function to perform a bulk read
+ */
+static int usbat_bulk_read(struct us_data *us,
+ unsigned char *data,
+ unsigned int len)
+{
+ if (len == 0)
+ return USB_STOR_XFER_GOOD;
+
+ US_DEBUGP("usbat_bulk_read: len = %d\n", len);
+ return usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, data, len, NULL);
}
+/*
+ * Convenience function to perform a bulk write
+ */
+static int usbat_bulk_write(struct us_data *us,
+ unsigned char *data,
+ unsigned int len)
+{
+ if (len == 0)
+ return USB_STOR_XFER_GOOD;
+
+ US_DEBUGP("usbat_bulk_write: len = %d\n", len);
+ return usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, data, len, NULL);
+}
+
+/*
+ * Some USBAT-specific commands can only be executed over a command transport
+ * This transport allows one (len=8) or two (len=16) vendor-specific commands
+ * to be executed.
+ */
+static int usbat_execute_command(struct us_data *us,
+ unsigned char *commands,
+ unsigned int len)
+{
+ return usb_stor_ctrl_transfer(us, us->send_ctrl_pipe,
+ USBAT_CMD_EXEC_CMD, 0x40, 0, 0,
+ commands, len);
+}
+
+/*
+ * Read the status register
+ */
+static int usbat_get_status(struct us_data *us, unsigned char *status)
+{
+ int rc;
+ rc = usbat_read(us, USBAT_ATA, USBAT_ATA_STATUS, status);
+
+ US_DEBUGP("usbat_get_status: 0x%02X\n", (unsigned short) (*status));
+ return rc;
+}
+
+/*
+ * Check the device status
+ */
+static int usbat_check_status(struct us_data *us)
+{
+ unsigned char *reply = us->iobuf;
+ int rc;
+
+ if (!us)
+ return USB_STOR_TRANSPORT_ERROR;
+
+ rc = usbat_get_status(us, reply);
+ if (rc != USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_FAILED;
+
+ if (*reply & 0x01 && *reply != 0x51) // error/check condition (0x51 is ok)
+ return USB_STOR_TRANSPORT_FAILED;
+
+ if (*reply & 0x20) // device fault
+ return USB_STOR_TRANSPORT_FAILED;
+
+ return USB_STOR_TRANSPORT_GOOD;
+}
+
+/*
+ * Stores critical information in internal registers in prepartion for the execution
+ * of a conditional usbat_read_blocks or usbat_write_blocks call.
+ */
static int usbat_set_shuttle_features(struct us_data *us,
unsigned char external_trigger,
unsigned char epp_control,
@@ -105,76 +217,44 @@ static int usbat_set_shuttle_features(struct us_data *us,
unsigned char subcountH,
unsigned char subcountL)
{
- int result;
unsigned char *command = us->iobuf;
command[0] = 0x40;
- command[1] = 0x81;
+ command[1] = USBAT_CMD_SET_FEAT;
+
+ // The only bit relevant to ATA access is bit 6
+ // which defines 8 bit data access (set) or 16 bit (unset)
command[2] = epp_control;
+
+ // If FCQ is set in the qualifier (defined in R/W cmd), then bits U0, U1,
+ // ET1 and ET2 define an external event to be checked for on event of a
+ // _read_blocks or _write_blocks operation. The read/write will not take
+ // place unless the defined trigger signal is active.
command[3] = external_trigger;
+
+ // The resultant byte of the mask operation (see mask_byte) is compared for
+ // equivalence with this test pattern. If equal, the read/write will take
+ // place.
command[4] = test_pattern;
+
+ // This value is logically ANDed with the status register field specified
+ // in the read/write command.
command[5] = mask_byte;
+
+ // If ALQ is set in the qualifier, this field contains the address of the
+ // registers where the byte count should be read for transferring the data.
+ // If ALQ is not set, then this field contains the number of bytes to be
+ // transferred.
command[6] = subcountL;
command[7] = subcountH;
- result = usb_stor_ctrl_transfer(us,
- us->send_ctrl_pipe,
- 0x80,
- 0x40,
- 0,
- 0,
- command,
- 8);
-
- return result;
-}
-
-static int usbat_read_block(struct us_data *us,
- unsigned char access,
- unsigned char reg,
- unsigned char *content,
- unsigned short len,
- int use_sg)
-{
- int result;
- unsigned char *command = us->iobuf;
-
- if (!len)
- return USB_STOR_TRANSPORT_GOOD;
-
- command[0] = 0xC0;
- command[1] = access | 0x02;
- command[2] = reg;
- command[3] = 0;
- command[4] = 0;
- command[5] = 0;
- command[6] = LSB_of(len);
- command[7] = MSB_of(len);
-
- result = usb_stor_ctrl_transfer(us,
- us->send_ctrl_pipe,
- 0x80,
- 0x40,
- 0,
- 0,
- command,
- 8);
-
- if (result != USB_STOR_XFER_GOOD)
- return USB_STOR_TRANSPORT_ERROR;
-
- result = usb_stor_bulk_transfer_sg(us, us->recv_bulk_pipe,
- content, len, use_sg, NULL);
-
- return (result == USB_STOR_XFER_GOOD ?
- USB_STOR_TRANSPORT_GOOD : USB_STOR_TRANSPORT_ERROR);
+ return usbat_execute_command(us, command, 8);
}
/*
* Block, waiting for an ATA device to become not busy or to report
* an error condition.
*/
-
static int usbat_wait_not_busy(struct us_data *us, int minutes)
{
int i;
@@ -189,7 +269,7 @@ static int usbat_wait_not_busy(struct us_data *us, int minutes)
for (i=0; i<1200+minutes*60; i++) {
- result = usbat_read(us, USBAT_ATA, 0x17, status);
+ result = usbat_get_status(us, status);
if (result!=USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
@@ -220,12 +300,45 @@ static int usbat_wait_not_busy(struct us_data *us, int minutes)
return USB_STOR_TRANSPORT_FAILED;
}
+/*
+ * Read block data from the data register
+ */
+static int usbat_read_block(struct us_data *us,
+ unsigned char *content,
+ unsigned short len)
+{
+ int result;
+ unsigned char *command = us->iobuf;
+
+ if (!len)
+ return USB_STOR_TRANSPORT_GOOD;
+
+ command[0] = 0xC0;
+ command[1] = USBAT_ATA | USBAT_CMD_READ_BLOCK;
+ command[2] = USBAT_ATA_DATA;
+ command[3] = 0;
+ command[4] = 0;
+ command[5] = 0;
+ command[6] = LSB_of(len);
+ command[7] = MSB_of(len);
+
+ result = usbat_execute_command(us, command, 8);
+ if (result != USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
+
+ result = usbat_bulk_read(us, content, len);
+ return (result == USB_STOR_XFER_GOOD ?
+ USB_STOR_TRANSPORT_GOOD : USB_STOR_TRANSPORT_ERROR);
+}
+
+/*
+ * Write block data via the data register
+ */
static int usbat_write_block(struct us_data *us,
- unsigned char access,
- unsigned char reg,
+ unsigned char access,
unsigned char *content,
unsigned short len,
- int use_sg, int minutes)
+ int minutes)
{
int result;
unsigned char *command = us->iobuf;
@@ -234,57 +347,48 @@ static int usbat_write_block(struct us_data *us,
return USB_STOR_TRANSPORT_GOOD;
command[0] = 0x40;
- command[1] = access | 0x03;
- command[2] = reg;
+ command[1] = access | USBAT_CMD_WRITE_BLOCK;
+ command[2] = USBAT_ATA_DATA;
command[3] = 0;
command[4] = 0;
command[5] = 0;
command[6] = LSB_of(len);
command[7] = MSB_of(len);
- result = usb_stor_ctrl_transfer(us,
- us->send_ctrl_pipe,
- 0x80,
- 0x40,
- 0,
- 0,
- command,
- 8);
+ result = usbat_execute_command(us, command, 8);
if (result != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
- result = usb_stor_bulk_transfer_sg(us, us->send_bulk_pipe,
- content, len, use_sg, NULL);
-
+ result = usbat_bulk_write(us, content, len);
if (result != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
return usbat_wait_not_busy(us, minutes);
}
-static int usbat_rw_block_test(struct us_data *us,
- unsigned char access,
- unsigned char *registers,
- unsigned char *data_out,
- unsigned short num_registers,
- unsigned char data_reg,
- unsigned char status_reg,
- unsigned char timeout,
- unsigned char qualifier,
- int direction,
- unsigned char *content,
- unsigned short len,
- int use_sg,
- int minutes)
+/*
+ * Process read and write requests
+ */
+static int usbat_hp8200e_rw_block_test(struct us_data *us,
+ unsigned char access,
+ unsigned char *registers,
+ unsigned char *data_out,
+ unsigned short num_registers,
+ unsigned char data_reg,
+ unsigned char status_reg,
+ unsigned char timeout,
+ unsigned char qualifier,
+ int direction,
+ unsigned char *content,
+ unsigned short len,
+ int use_sg,
+ int minutes)
{
int result;
unsigned int pipe = (direction == DMA_FROM_DEVICE) ?
us->recv_bulk_pipe : us->send_bulk_pipe;
- // Not really sure the 0x07, 0x17, 0xfc, 0xe7 is necessary here,
- // but that's what came out of the trace every single time.
-
unsigned char *command = us->iobuf;
int i, j;
int cmdlen;
@@ -308,8 +412,11 @@ static int usbat_rw_block_test(struct us_data *us,
if (i==0) {
cmdlen = 16;
+ // Write to multiple registers
+ // Not really sure the 0x07, 0x17, 0xfc, 0xe7 is necessary here,
+ // but that's what came out of the trace every single time.
command[0] = 0x40;
- command[1] = access | 0x07;
+ command[1] = access | USBAT_CMD_WRITE_REGS;
command[2] = 0x07;
command[3] = 0x17;
command[4] = 0xFC;
@@ -319,9 +426,11 @@ static int usbat_rw_block_test(struct us_data *us,
} else
cmdlen = 8;
+ // Conditionally read or write blocks
command[cmdlen-8] = (direction==DMA_TO_DEVICE ? 0x40 : 0xC0);
command[cmdlen-7] = access |
- (direction==DMA_TO_DEVICE ? 0x05 : 0x04);
+ (direction==DMA_TO_DEVICE ?
+ USBAT_CMD_COND_WRITE_BLOCK : USBAT_CMD_COND_READ_BLOCK);
command[cmdlen-6] = data_reg;
command[cmdlen-5] = status_reg;
command[cmdlen-4] = timeout;
@@ -329,14 +438,7 @@ static int usbat_rw_block_test(struct us_data *us,
command[cmdlen-2] = LSB_of(len);
command[cmdlen-1] = MSB_of(len);
- result = usb_stor_ctrl_transfer(us,
- us->send_ctrl_pipe,
- 0x80,
- 0x40,
- 0,
- 0,
- command,
- cmdlen);
+ result = usbat_execute_command(us, command, cmdlen);
if (result != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
@@ -348,10 +450,7 @@ static int usbat_rw_block_test(struct us_data *us,
data[1+(j<<1)] = data_out[j];
}
- result = usb_stor_bulk_transfer_buf(us,
- us->send_bulk_pipe,
- data, num_registers*2, NULL);
-
+ result = usbat_bulk_write(us, data, num_registers*2);
if (result != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
@@ -403,7 +502,8 @@ static int usbat_rw_block_test(struct us_data *us,
*/
result = usbat_read(us, USBAT_ATA,
- direction==DMA_TO_DEVICE ? 0x17 : 0x0E,
+ direction==DMA_TO_DEVICE ?
+ USBAT_ATA_STATUS : USBAT_ATA_ALTSTATUS,
status);
if (result!=USB_STOR_XFER_GOOD)
@@ -430,101 +530,602 @@ static int usbat_rw_block_test(struct us_data *us,
}
/*
- * Write data to multiple registers at once. Not meant for large
- * transfers of data!
+ * Write to multiple registers:
+ * Allows us to write specific data to any registers. The data to be written
+ * gets packed in this sequence: reg0, data0, reg1, data1, ..., regN, dataN
+ * which gets sent through bulk out.
+ * Not designed for large transfers of data!
*/
-
static int usbat_multiple_write(struct us_data *us,
- unsigned char access,
unsigned char *registers,
unsigned char *data_out,
unsigned short num_registers)
{
- int result;
+ int i, result;
unsigned char *data = us->iobuf;
- int i;
unsigned char *command = us->iobuf;
BUG_ON(num_registers > US_IOBUF_SIZE/2);
+ // Write to multiple registers, ATA access
command[0] = 0x40;
- command[1] = access | 0x07;
+ command[1] = USBAT_ATA | USBAT_CMD_WRITE_REGS;
+
+ // No relevance
command[2] = 0;
command[3] = 0;
command[4] = 0;
command[5] = 0;
+
+ // Number of bytes to be transferred (incl. addresses and data)
command[6] = LSB_of(num_registers*2);
command[7] = MSB_of(num_registers*2);
- result = usb_stor_ctrl_transfer(us,
- us->send_ctrl_pipe,
- 0x80,
- 0x40,
- 0,
- 0,
- command,
- 8);
-
+ // The setup command
+ result = usbat_execute_command(us, command, 8);
if (result != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
+ // Create the reg/data, reg/data sequence
for (i=0; i<num_registers; i++) {
data[i<<1] = registers[i];
data[1+(i<<1)] = data_out[i];
}
- result = usb_stor_bulk_transfer_buf(us,
- us->send_bulk_pipe, data, num_registers*2, NULL);
-
+ // Send the data
+ result = usbat_bulk_write(us, data, num_registers*2);
if (result != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
- return usbat_wait_not_busy(us, 0);
+ if (usbat_get_device_type(us) == USBAT_DEV_HP8200)
+ return usbat_wait_not_busy(us, 0);
+ else
+ return USB_STOR_TRANSPORT_GOOD;
+}
+
+/*
+ * Conditionally read blocks from device:
+ * Allows us to read blocks from a specific data register, based upon the
+ * condition that a status register can be successfully masked with a status
+ * qualifier. If this condition is not initially met, the read will wait
+ * up until a maximum amount of time has elapsed, as specified by timeout.
+ * The read will start when the condition is met, otherwise the command aborts.
+ *
+ * The qualifier defined here is not the value that is masked, it defines
+ * conditions for the write to take place. The actual masked qualifier (and
+ * other related details) are defined beforehand with _set_shuttle_features().
+ */
+static int usbat_read_blocks(struct us_data *us,
+ unsigned char *buffer,
+ int len)
+{
+ int result;
+ unsigned char *command = us->iobuf;
+
+ command[0] = 0xC0;
+ command[1] = USBAT_ATA | USBAT_CMD_COND_READ_BLOCK;
+ command[2] = USBAT_ATA_DATA;
+ command[3] = USBAT_ATA_STATUS;
+ command[4] = 0xFD; // Timeout (ms);
+ command[5] = USBAT_QUAL_FCQ;
+ command[6] = LSB_of(len);
+ command[7] = MSB_of(len);
+
+ // Multiple block read setup command
+ result = usbat_execute_command(us, command, 8);
+ if (result != USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_FAILED;
+
+ // Read the blocks we just asked for
+ result = usbat_bulk_read(us, buffer, len);
+ if (result != USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_FAILED;
+
+ return USB_STOR_TRANSPORT_GOOD;
}
+/*
+ * Conditionally write blocks to device:
+ * Allows us to write blocks to a specific data register, based upon the
+ * condition that a status register can be successfully masked with a status
+ * qualifier. If this condition is not initially met, the write will wait
+ * up until a maximum amount of time has elapsed, as specified by timeout.
+ * The read will start when the condition is met, otherwise the command aborts.
+ *
+ * The qualifier defined here is not the value that is masked, it defines
+ * conditions for the write to take place. The actual masked qualifier (and
+ * other related details) are defined beforehand with _set_shuttle_features().
+ */
+static int usbat_write_blocks(struct us_data *us,
+ unsigned char *buffer,
+ int len)
+{
+ int result;
+ unsigned char *command = us->iobuf;
+
+ command[0] = 0x40;
+ command[1] = USBAT_ATA | USBAT_CMD_COND_WRITE_BLOCK;
+ command[2] = USBAT_ATA_DATA;
+ command[3] = USBAT_ATA_STATUS;
+ command[4] = 0xFD; // Timeout (ms)
+ command[5] = USBAT_QUAL_FCQ;
+ command[6] = LSB_of(len);
+ command[7] = MSB_of(len);
+
+ // Multiple block write setup command
+ result = usbat_execute_command(us, command, 8);
+ if (result != USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_FAILED;
+
+ // Write the data
+ result = usbat_bulk_write(us, buffer, len);
+ if (result != USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_FAILED;
+
+ return USB_STOR_TRANSPORT_GOOD;
+}
+
+/*
+ * Read the User IO register
+ */
static int usbat_read_user_io(struct us_data *us, unsigned char *data_flags)
{
int result;
result = usb_stor_ctrl_transfer(us,
us->recv_ctrl_pipe,
- 0x82,
+ USBAT_CMD_UIO,
0xC0,
0,
0,
data_flags,
- 1);
+ USBAT_UIO_READ);
+
+ US_DEBUGP("usbat_read_user_io: UIO register reads %02X\n", (unsigned short) (*data_flags));
return result;
}
+/*
+ * Write to the User IO register
+ */
static int usbat_write_user_io(struct us_data *us,
unsigned char enable_flags,
unsigned char data_flags)
{
- int result;
-
- result = usb_stor_ctrl_transfer(us,
+ return usb_stor_ctrl_transfer(us,
us->send_ctrl_pipe,
- 0x82,
+ USBAT_CMD_UIO,
0x40,
short_pack(enable_flags, data_flags),
0,
NULL,
- 0);
+ USBAT_UIO_WRITE);
+}
+
+/*
+ * Reset the device
+ * Often needed on media change.
+ */
+static int usbat_device_reset(struct us_data *us)
+{
+ int rc;
+
+ // Reset peripheral, enable peripheral control signals
+ // (bring reset signal up)
+ rc = usbat_write_user_io(us,
+ USBAT_UIO_DRVRST | USBAT_UIO_OE1 | USBAT_UIO_OE0,
+ USBAT_UIO_EPAD | USBAT_UIO_1);
+ if (rc != USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
+
+ // Enable peripheral control signals
+ // (bring reset signal down)
+ rc = usbat_write_user_io(us,
+ USBAT_UIO_OE1 | USBAT_UIO_OE0,
+ USBAT_UIO_EPAD | USBAT_UIO_1);
+ if (rc != USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
+
+ return USB_STOR_TRANSPORT_GOOD;
+}
+
+/*
+ * Enable card detect
+ */
+static int usbat_device_enable_cdt(struct us_data *us)
+{
+ int rc;
+
+ // Enable peripheral control signals and card detect
+ rc = usbat_write_user_io(us,
+ USBAT_UIO_ACKD | USBAT_UIO_OE1 | USBAT_UIO_OE0,
+ USBAT_UIO_EPAD | USBAT_UIO_1);
+ if (rc != USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
+
+ return USB_STOR_TRANSPORT_GOOD;
+}
+
+/*
+ * Determine if media is present.
+ */
+static int usbat_flash_check_media_present(unsigned char *uio)
+{
+ if (*uio & USBAT_UIO_UI0) {
+ US_DEBUGP("usbat_flash_check_media_present: no media detected\n");
+ return USBAT_FLASH_MEDIA_NONE;
+ }
+
+ return USBAT_FLASH_MEDIA_CF;
+}
+
+/*
+ * Determine if media has changed since last operation
+ */
+static int usbat_flash_check_media_changed(unsigned char *uio)
+{
+ if (*uio & USBAT_UIO_0) {
+ US_DEBUGP("usbat_flash_check_media_changed: media change detected\n");
+ return USBAT_FLASH_MEDIA_CHANGED;
+ }
+
+ return USBAT_FLASH_MEDIA_SAME;
+}
+
+/*
+ * Check for media change / no media and handle the situation appropriately
+ */
+static int usbat_flash_check_media(struct us_data *us,
+ struct usbat_info *info)
+{
+ int rc;
+ unsigned char *uio = us->iobuf;
+
+ rc = usbat_read_user_io(us, uio);
+ if (rc != USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
+
+ // Check for media existance
+ rc = usbat_flash_check_media_present(uio);
+ if (rc == USBAT_FLASH_MEDIA_NONE) {
+ info->sense_key = 0x02;
+ info->sense_asc = 0x3A;
+ info->sense_ascq = 0x00;
+ return USB_STOR_TRANSPORT_FAILED;
+ }
+
+ // Check for media change
+ rc = usbat_flash_check_media_changed(uio);
+ if (rc == USBAT_FLASH_MEDIA_CHANGED) {
+
+ // Reset and re-enable card detect
+ rc = usbat_device_reset(us);
+ if (rc != USB_STOR_TRANSPORT_GOOD)
+ return rc;
+ rc = usbat_device_enable_cdt(us);
+ if (rc != USB_STOR_TRANSPORT_GOOD)
+ return rc;
+
+ msleep(50);
+
+ rc = usbat_read_user_io(us, uio);
+ if (rc != USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
+
+ info->sense_key = UNIT_ATTENTION;
+ info->sense_asc = 0x28;
+ info->sense_ascq = 0x00;
+ return USB_STOR_TRANSPORT_FAILED;
+ }
+
+ return USB_STOR_TRANSPORT_GOOD;
+}
+
+/*
+ * Determine whether we are controlling a flash-based reader/writer,
+ * or a HP8200-based CD drive.
+ * Sets transport functions as appropriate.
+ */
+static int usbat_identify_device(struct us_data *us,
+ struct usbat_info *info)
+{
+ int rc;
+ unsigned char status;
+
+ if (!us || !info)
+ return USB_STOR_TRANSPORT_ERROR;
+
+ rc = usbat_device_reset(us);
+ if (rc != USB_STOR_TRANSPORT_GOOD)
+ return rc;
+
+ /*
+ * By examining the device signature after a reset, we can identify
+ * whether the device supports the ATAPI packet interface.
+ * The flash-devices do not support this, whereas the HP CDRW's obviously
+ * do.
+ *
+ * This method is not ideal, but works because no other devices have been
+ * produced based on the USBAT/USBAT02.
+ *
+ * Section 9.1 of the ATAPI-4 spec states (amongst other things) that
+ * after a device reset, a Cylinder low of 0x14 indicates that the device
+ * does support packet commands.
+ */
+ rc = usbat_read(us, USBAT_ATA, USBAT_ATA_LBA_ME, &status);
+ if (rc != USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
+
+ US_DEBUGP("usbat_identify_device: Cylinder low is %02X\n", status);
+
+ if (status == 0x14) {
+ // Device is HP 8200
+ US_DEBUGP("usbat_identify_device: Detected HP8200 CDRW\n");
+ info->devicetype = USBAT_DEV_HP8200;
+ } else {
+ // Device is a CompactFlash reader/writer
+ US_DEBUGP("usbat_identify_device: Detected Flash reader/writer\n");
+ info->devicetype = USBAT_DEV_FLASH;
+ }
+
+ return USB_STOR_TRANSPORT_GOOD;
+}
+
+/*
+ * Set the transport function based on the device type
+ */
+static int usbat_set_transport(struct us_data *us,
+ struct usbat_info *info)
+{
+ int rc;
+
+ if (!info->devicetype) {
+ rc = usbat_identify_device(us, info);
+ if (rc != USB_STOR_TRANSPORT_GOOD) {
+ US_DEBUGP("usbat_set_transport: Could not identify device\n");
+ return 1;
+ }
+ }
+
+ if (usbat_get_device_type(us) == USBAT_DEV_HP8200)
+ us->transport = usbat_hp8200e_transport;
+ else if (usbat_get_device_type(us) == USBAT_DEV_FLASH)
+ us->transport = usbat_flash_transport;
+
+ return 0;
+}
+
+/*
+ * Read the media capacity
+ */
+static int usbat_flash_get_sector_count(struct us_data *us,
+ struct usbat_info *info)
+{
+ unsigned char registers[3] = {
+ USBAT_ATA_SECCNT,
+ USBAT_ATA_DEVICE,
+ USBAT_ATA_CMD,
+ };
+ unsigned char command[3] = { 0x01, 0xA0, 0xEC };
+ unsigned char *reply;
+ unsigned char status;
+ int rc;
+
+ if (!us || !info)
+ return USB_STOR_TRANSPORT_ERROR;
+
+ reply = kmalloc(512, GFP_NOIO);
+ if (!reply)
+ return USB_STOR_TRANSPORT_ERROR;
+
+ // ATAPI command : IDENTIFY DEVICE
+ rc = usbat_multiple_write(us, registers, command, 3);
+ if (rc != USB_STOR_XFER_GOOD) {
+ US_DEBUGP("usbat_flash_get_sector_count: Gah! identify_device failed\n");
+ rc = USB_STOR_TRANSPORT_ERROR;
+ goto leave;
+ }
+
+ // Read device status
+ if (usbat_get_status(us, &status) != USB_STOR_XFER_GOOD) {
+ rc = USB_STOR_TRANSPORT_ERROR;
+ goto leave;
+ }
+
+ msleep(100);
+
+ // Read the device identification data
+ rc = usbat_read_block(us, reply, 512);
+ if (rc != USB_STOR_TRANSPORT_GOOD)
+ goto leave;
+
+ info->sectors = ((u32)(reply[117]) << 24) |
+ ((u32)(reply[116]) << 16) |
+ ((u32)(reply[115]) << 8) |
+ ((u32)(reply[114]) );
+
+ rc = USB_STOR_TRANSPORT_GOOD;
+
+ leave:
+ kfree(reply);
+ return rc;
+}
+
+/*
+ * Read data from device
+ */
+static int usbat_flash_read_data(struct us_data *us,
+ struct usbat_info *info,
+ u32 sector,
+ u32 sectors)
+{
+ unsigned char registers[7] = {
+ USBAT_ATA_FEATURES,
+ USBAT_ATA_SECCNT,
+ USBAT_ATA_SECNUM,
+ USBAT_ATA_LBA_ME,
+ USBAT_ATA_LBA_HI,
+ USBAT_ATA_DEVICE,
+ USBAT_ATA_STATUS,
+ };
+ unsigned char command[7];
+ unsigned char *buffer;
+ unsigned char thistime;
+ unsigned int totallen, alloclen;
+ int len, result;
+ unsigned int sg_idx = 0, sg_offset = 0;
+
+ result = usbat_flash_check_media(us, info);
+ if (result != USB_STOR_TRANSPORT_GOOD)
+ return result;
+
+ // we're working in LBA mode. according to the ATA spec,
+ // we can support up to 28-bit addressing. I don't know if Jumpshot
+ // supports beyond 24-bit addressing. It's kind of hard to test
+ // since it requires > 8GB CF card.
+
+ if (sector > 0x0FFFFFFF)
+ return USB_STOR_TRANSPORT_ERROR;
+
+ totallen = sectors * info->ssize;
+
+ // Since we don't read more than 64 KB 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.
+
+ alloclen = min(totallen, 65536u);
+ buffer = kmalloc(alloclen, GFP_NOIO);
+ if (buffer == NULL)
+ return USB_STOR_TRANSPORT_ERROR;
+
+ do {
+ // loop, never allocate or transfer more than 64k at once
+ // (min(128k, 255*info->ssize) is the real limit)
+ len = min(totallen, alloclen);
+ thistime = (len / info->ssize) & 0xff;
+
+ // ATAPI command 0x20 (READ SECTORS)
+ usbat_pack_atapi_sector_cmd(command, thistime, sector, 0x20);
+
+ // Write/execute ATAPI read command
+ result = usbat_multiple_write(us, registers, command, 7);
+ if (result != USB_STOR_TRANSPORT_GOOD)
+ goto leave;
+
+ // Read the data we just requested
+ result = usbat_read_blocks(us, buffer, len);
+ if (result != USB_STOR_TRANSPORT_GOOD)
+ goto leave;
+
+ US_DEBUGP("usbat_flash_read_data: %d bytes\n", len);
+
+ // Store the data in the transfer buffer
+ usb_stor_access_xfer_buf(buffer, len, us->srb,
+ &sg_idx, &sg_offset, TO_XFER_BUF);
+
+ sector += thistime;
+ totallen -= len;
+ } while (totallen > 0);
+
+ kfree(buffer);
+ return USB_STOR_TRANSPORT_GOOD;
+
+leave:
+ kfree(buffer);
+ return USB_STOR_TRANSPORT_ERROR;
+}
+
+/*
+ * Write data to device
+ */
+static int usbat_flash_write_data(struct us_data *us,
+ struct usbat_info *info,
+ u32 sector,
+ u32 sectors)
+{
+ unsigned char registers[7] = {
+ USBAT_ATA_FEATURES,
+ USBAT_ATA_SECCNT,
+ USBAT_ATA_SECNUM,
+ USBAT_ATA_LBA_ME,
+ USBAT_ATA_LBA_HI,
+ USBAT_ATA_DEVICE,
+ USBAT_ATA_STATUS,
+ };
+ unsigned char command[7];
+ unsigned char *buffer;
+ unsigned char thistime;
+ unsigned int totallen, alloclen;
+ int len, result;
+ unsigned int sg_idx = 0, sg_offset = 0;
+
+ result = usbat_flash_check_media(us, info);
+ if (result != USB_STOR_TRANSPORT_GOOD)
+ return result;
+
+ // we're working in LBA mode. according to the ATA spec,
+ // we can support up to 28-bit addressing. I don't know if Jumpshot
+ // supports beyond 24-bit addressing. It's kind of hard to test
+ // since it requires > 8GB CF card.
+ if (sector > 0x0FFFFFFF)
+ return USB_STOR_TRANSPORT_ERROR;
+
+ totallen = sectors * info->ssize;
+
+ // Since we don't write more than 64 KB 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.
+
+ alloclen = min(totallen, 65536u);
+ buffer = kmalloc(alloclen, GFP_NOIO);
+ if (buffer == NULL)
+ return USB_STOR_TRANSPORT_ERROR;
+
+ do {
+ // loop, never allocate or transfer more than 64k at once
+ // (min(128k, 255*info->ssize) is the real limit)
+ len = min(totallen, alloclen);
+ thistime = (len / info->ssize) & 0xff;
+
+ // Get the data from the transfer buffer
+ usb_stor_access_xfer_buf(buffer, len, us->srb,
+ &sg_idx, &sg_offset, FROM_XFER_BUF);
+
+ // ATAPI command 0x30 (WRITE SECTORS)
+ usbat_pack_atapi_sector_cmd(command, thistime, sector, 0x30);
+
+ // Write/execute ATAPI write command
+ result = usbat_multiple_write(us, registers, command, 7);
+ if (result != USB_STOR_TRANSPORT_GOOD)
+ goto leave;
+
+ // Write the data
+ result = usbat_write_blocks(us, buffer, len);
+ if (result != USB_STOR_TRANSPORT_GOOD)
+ goto leave;
+
+ sector += thistime;
+ totallen -= len;
+ } while (totallen > 0);
+
+ kfree(buffer);
return result;
+
+leave:
+ kfree(buffer);
+ return USB_STOR_TRANSPORT_ERROR;
}
/*
* Squeeze a potentially huge (> 65535 byte) read10 command into
* a little ( <= 65535 byte) ATAPI pipe
*/
-
-static int usbat_handle_read10(struct us_data *us,
- unsigned char *registers,
- unsigned char *data,
- struct scsi_cmnd *srb)
+static int usbat_hp8200e_handle_read10(struct us_data *us,
+ unsigned char *registers,
+ unsigned char *data,
+ struct scsi_cmnd *srb)
{
int result = USB_STOR_TRANSPORT_GOOD;
unsigned char *buffer;
@@ -538,9 +1139,10 @@ static int usbat_handle_read10(struct us_data *us,
if (srb->request_bufflen < 0x10000) {
- result = usbat_rw_block_test(us, USBAT_ATA,
+ result = usbat_hp8200e_rw_block_test(us, USBAT_ATA,
registers, data, 19,
- 0x10, 0x17, 0xFD, 0x30,
+ USBAT_ATA_DATA, USBAT_ATA_STATUS, 0xFD,
+ (USBAT_QUAL_FCQ | USBAT_QUAL_ALQ),
DMA_FROM_DEVICE,
srb->request_buffer,
srb->request_bufflen, srb->use_sg, 1);
@@ -607,9 +1209,10 @@ static int usbat_handle_read10(struct us_data *us,
data[7+7] = MSB_of(len / srb->transfersize); // SCSI command
data[7+8] = LSB_of(len / srb->transfersize); // num sectors
- result = usbat_rw_block_test(us, USBAT_ATA,
+ result = usbat_hp8200e_rw_block_test(us, USBAT_ATA,
registers, data, 19,
- 0x10, 0x17, 0xFD, 0x30,
+ USBAT_ATA_DATA, USBAT_ATA_STATUS, 0xFD,
+ (USBAT_QUAL_FCQ | USBAT_QUAL_ALQ),
DMA_FROM_DEVICE,
buffer,
len, 0, 1);
@@ -632,48 +1235,52 @@ static int usbat_handle_read10(struct us_data *us,
return result;
}
-static int hp_8200e_select_and_test_registers(struct us_data *us)
+static int usbat_select_and_test_registers(struct us_data *us)
{
int selector;
unsigned char *status = us->iobuf;
+ unsigned char max_selector = 0xB0;
+ if (usbat_get_device_type(us) == USBAT_DEV_FLASH)
+ max_selector = 0xA0;
// try device = master, then device = slave.
- for (selector = 0xA0; selector <= 0xB0; selector += 0x10) {
+ for (selector = 0xA0; selector <= max_selector; selector += 0x10) {
- if (usbat_write(us, USBAT_ATA, 0x16, selector) !=
+ if (usbat_get_device_type(us) == USBAT_DEV_HP8200 &&
+ usbat_write(us, USBAT_ATA, USBAT_ATA_DEVICE, selector) !=
USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
- if (usbat_read(us, USBAT_ATA, 0x17, status) !=
+ if (usbat_read(us, USBAT_ATA, USBAT_ATA_STATUS, status) !=
USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
- if (usbat_read(us, USBAT_ATA, 0x16, status) !=
+ if (usbat_read(us, USBAT_ATA, USBAT_ATA_DEVICE, status) !=
USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
- if (usbat_read(us, USBAT_ATA, 0x14, status) !=
+ if (usbat_read(us, USBAT_ATA, USBAT_ATA_LBA_ME, status) !=
USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
- if (usbat_read(us, USBAT_ATA, 0x15, status) !=
+ if (usbat_read(us, USBAT_ATA, USBAT_ATA_LBA_HI, status) !=
USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
- if (usbat_write(us, USBAT_ATA, 0x14, 0x55) !=
+ if (usbat_write(us, USBAT_ATA, USBAT_ATA_LBA_ME, 0x55) !=
USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
- if (usbat_write(us, USBAT_ATA, 0x15, 0xAA) !=
+ if (usbat_write(us, USBAT_ATA, USBAT_ATA_LBA_HI, 0xAA) !=
USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
- if (usbat_read(us, USBAT_ATA, 0x14, status) !=
+ if (usbat_read(us, USBAT_ATA, USBAT_ATA_LBA_ME, status) !=
USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
- if (usbat_read(us, USBAT_ATA, 0x15, status) !=
+ if (usbat_read(us, USBAT_ATA, USBAT_ATA_LBA_ME, status) !=
USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
}
@@ -681,125 +1288,131 @@ static int hp_8200e_select_and_test_registers(struct us_data *us)
return USB_STOR_TRANSPORT_GOOD;
}
-int init_8200e(struct us_data *us)
+/*
+ * Initialize the USBAT processor and the storage device
+ */
+int init_usbat(struct us_data *us)
{
- int result;
+ int rc;
+ struct usbat_info *info;
+ unsigned char subcountH = USBAT_ATA_LBA_HI;
+ unsigned char subcountL = USBAT_ATA_LBA_ME;
unsigned char *status = us->iobuf;
- // Enable peripheral control signals
+ us->extra = kmalloc(sizeof(struct usbat_info), GFP_NOIO);
+ if (!us->extra) {
+ US_DEBUGP("init_usbat: Gah! Can't allocate storage for usbat info struct!\n");
+ return 1;
+ }
+ memset(us->extra, 0, sizeof(struct usbat_info));
+ info = (struct usbat_info *) (us->extra);
- if (usbat_write_user_io(us,
- USBAT_UIO_OE1 | USBAT_UIO_OE0,
- USBAT_UIO_EPAD | USBAT_UIO_1) != USB_STOR_XFER_GOOD)
+ // Enable peripheral control signals
+ rc = usbat_write_user_io(us,
+ USBAT_UIO_OE1 | USBAT_UIO_OE0,
+ USBAT_UIO_EPAD | USBAT_UIO_1);
+ if (rc != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
US_DEBUGP("INIT 1\n");
msleep(2000);
- if (usbat_read_user_io(us, status) !=
- USB_STOR_XFER_GOOD)
- return USB_STOR_TRANSPORT_ERROR;
+ rc = usbat_read_user_io(us, status);
+ if (rc != USB_STOR_TRANSPORT_GOOD)
+ return rc;
US_DEBUGP("INIT 2\n");
- if (usbat_read_user_io(us, status) !=
- USB_STOR_XFER_GOOD)
+ rc = usbat_read_user_io(us, status);
+ if (rc != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
- US_DEBUGP("INIT 3\n");
-
- // Reset peripheral, enable periph control signals
- // (bring reset signal up)
-
- if (usbat_write_user_io(us,
- USBAT_UIO_DRVRST | USBAT_UIO_OE1 | USBAT_UIO_OE0,
- USBAT_UIO_EPAD | USBAT_UIO_1) != USB_STOR_XFER_GOOD)
+ rc = usbat_read_user_io(us, status);
+ if (rc != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
- US_DEBUGP("INIT 4\n");
-
- // Enable periph control signals
- // (bring reset signal down)
+ US_DEBUGP("INIT 3\n");
- if (usbat_write_user_io(us,
- USBAT_UIO_OE1 | USBAT_UIO_OE0,
- USBAT_UIO_EPAD | USBAT_UIO_1) != USB_STOR_XFER_GOOD)
+ // At this point, we need to detect which device we are using
+ if (usbat_set_transport(us, info))
return USB_STOR_TRANSPORT_ERROR;
- US_DEBUGP("INIT 5\n");
+ US_DEBUGP("INIT 4\n");
- msleep(250);
+ if (usbat_get_device_type(us) == USBAT_DEV_HP8200) {
+ msleep(250);
- // Write 0x80 to ISA port 0x3F
+ // Write 0x80 to ISA port 0x3F
+ rc = usbat_write(us, USBAT_ISA, 0x3F, 0x80);
+ if (rc != USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
- if (usbat_write(us, USBAT_ISA, 0x3F, 0x80) !=
- USB_STOR_XFER_GOOD)
- return USB_STOR_TRANSPORT_ERROR;
+ US_DEBUGP("INIT 5\n");
- US_DEBUGP("INIT 6\n");
+ // Read ISA port 0x27
+ rc = usbat_read(us, USBAT_ISA, 0x27, status);
+ if (rc != USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
- // Read ISA port 0x27
+ US_DEBUGP("INIT 6\n");
- if (usbat_read(us, USBAT_ISA, 0x27, status) !=
- USB_STOR_XFER_GOOD)
- return USB_STOR_TRANSPORT_ERROR;
+ rc = usbat_read_user_io(us, status);
+ if (rc != USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
- US_DEBUGP("INIT 7\n");
+ US_DEBUGP("INIT 7\n");
+ }
- if (usbat_read_user_io(us, status) !=
- USB_STOR_XFER_GOOD)
- return USB_STOR_TRANSPORT_ERROR;
+ rc = usbat_select_and_test_registers(us);
+ if (rc != USB_STOR_TRANSPORT_GOOD)
+ return rc;
US_DEBUGP("INIT 8\n");
- if ( (result = hp_8200e_select_and_test_registers(us)) !=
- USB_STOR_TRANSPORT_GOOD)
- return result;
+ rc = usbat_read_user_io(us, status);
+ if (rc != USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
US_DEBUGP("INIT 9\n");
- if (usbat_read_user_io(us, status) !=
- USB_STOR_XFER_GOOD)
- return USB_STOR_TRANSPORT_ERROR;
+ // Enable peripheral control signals and card detect
+ rc = usbat_device_enable_cdt(us);
+ if (rc != USB_STOR_TRANSPORT_GOOD)
+ return rc;
US_DEBUGP("INIT 10\n");
- // Enable periph control signals and card detect
-
- if (usbat_write_user_io(us,
- USBAT_UIO_ACKD |USBAT_UIO_OE1 | USBAT_UIO_OE0,
- USBAT_UIO_EPAD | USBAT_UIO_1) != USB_STOR_XFER_GOOD)
+ rc = usbat_read_user_io(us, status);
+ if (rc != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
US_DEBUGP("INIT 11\n");
- if (usbat_read_user_io(us, status) !=
- USB_STOR_XFER_GOOD)
- return USB_STOR_TRANSPORT_ERROR;
-
- US_DEBUGP("INIT 12\n");
-
msleep(1400);
- if (usbat_read_user_io(us, status) !=
- USB_STOR_XFER_GOOD)
+ rc = usbat_read_user_io(us, status);
+ if (rc != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
- US_DEBUGP("INIT 13\n");
+ US_DEBUGP("INIT 12\n");
- if ( (result = hp_8200e_select_and_test_registers(us)) !=
- USB_STOR_TRANSPORT_GOOD)
- return result;
+ rc = usbat_select_and_test_registers(us);
+ if (rc != USB_STOR_TRANSPORT_GOOD)
+ return rc;
- US_DEBUGP("INIT 14\n");
+ US_DEBUGP("INIT 13\n");
- if (usbat_set_shuttle_features(us,
- 0x83, 0x00, 0x88, 0x08, 0x15, 0x14) !=
- USB_STOR_XFER_GOOD)
+ if (usbat_get_device_type(us) == USBAT_DEV_FLASH) {
+ subcountH = 0x02;
+ subcountL = 0x00;
+ }
+ rc = usbat_set_shuttle_features(us, (USBAT_FEAT_ETEN | USBAT_FEAT_ET2 | USBAT_FEAT_ET1),
+ 0x00, 0x88, 0x08, subcountH, subcountL);
+ if (rc != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
- US_DEBUGP("INIT 15\n");
+ US_DEBUGP("INIT 14\n");
return USB_STOR_TRANSPORT_GOOD;
}
@@ -807,7 +1420,7 @@ int init_8200e(struct us_data *us)
/*
* Transport for the HP 8200e
*/
-int hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us)
+static int usbat_hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us)
{
int result;
unsigned char *status = us->iobuf;
@@ -824,13 +1437,13 @@ int hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us)
commands... just ATA Packet Commands.
*/
- registers[0] = 0x11;
- registers[1] = 0x12;
- registers[2] = 0x13;
- registers[3] = 0x14;
- registers[4] = 0x15;
- registers[5] = 0x16;
- registers[6] = 0x17;
+ registers[0] = USBAT_ATA_FEATURES;
+ registers[1] = USBAT_ATA_SECCNT;
+ registers[2] = USBAT_ATA_SECNUM;
+ registers[3] = USBAT_ATA_LBA_ME;
+ registers[4] = USBAT_ATA_LBA_HI;
+ registers[5] = USBAT_ATA_DEVICE;
+ registers[6] = USBAT_ATA_CMD;
data[0] = 0x00;
data[1] = 0x00;
data[2] = 0x00;
@@ -844,7 +1457,7 @@ int hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us)
data[i] = (i-7 >= srb->cmd_len) ? 0 : srb->cmnd[i-7];
}
- result = usbat_read(us, USBAT_ATA, 0x17, status);
+ result = usbat_get_status(us, status);
US_DEBUGP("Status = %02X\n", *status);
if (result != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
@@ -853,9 +1466,10 @@ int hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us)
if (srb->sc_data_direction == DMA_TO_DEVICE) {
- result = usbat_rw_block_test(us, USBAT_ATA,
+ result = usbat_hp8200e_rw_block_test(us, USBAT_ATA,
registers, data, 19,
- 0x10, 0x17, 0xFD, 0x30,
+ USBAT_ATA_DATA, USBAT_ATA_STATUS, 0xFD,
+ (USBAT_QUAL_FCQ | USBAT_QUAL_ALQ),
DMA_TO_DEVICE,
srb->request_buffer,
len, srb->use_sg, 10);
@@ -870,7 +1484,7 @@ int hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us)
} else if (srb->cmnd[0] == READ_10 ||
srb->cmnd[0] == GPCMD_READ_CD) {
- return usbat_handle_read10(us, registers, data, srb);
+ return usbat_hp8200e_handle_read10(us, registers, data, srb);
}
@@ -881,7 +1495,6 @@ int hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us)
}
if ( (result = usbat_multiple_write(us,
- USBAT_ATA,
registers, data, 7)) != USB_STOR_TRANSPORT_GOOD) {
return result;
}
@@ -895,7 +1508,7 @@ int hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us)
// AT SPEED 4 IS UNRELIABLE!!!
if ( (result = usbat_write_block(us,
- USBAT_ATA, 0x10, srb->cmnd, 12, 0,
+ USBAT_ATA, srb->cmnd, 12,
srb->cmnd[0]==GPCMD_BLANK ? 75 : 10)) !=
USB_STOR_TRANSPORT_GOOD) {
return result;
@@ -908,14 +1521,14 @@ int hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us)
// How many bytes to read in? Check cylL register
- if (usbat_read(us, USBAT_ATA, 0x14, status) !=
+ if (usbat_read(us, USBAT_ATA, USBAT_ATA_LBA_ME, status) !=
USB_STOR_XFER_GOOD) {
return USB_STOR_TRANSPORT_ERROR;
}
if (len > 0xFF) { // need to read cylH also
len = *status;
- if (usbat_read(us, USBAT_ATA, 0x15, status) !=
+ if (usbat_read(us, USBAT_ATA, USBAT_ATA_LBA_HI, status) !=
USB_STOR_XFER_GOOD) {
return USB_STOR_TRANSPORT_ERROR;
}
@@ -925,8 +1538,7 @@ int hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us)
len = *status;
- result = usbat_read_block(us, USBAT_ATA, 0x10,
- srb->request_buffer, len, srb->use_sg);
+ result = usbat_read_block(us, srb->request_buffer, len);
/* Debug-print the first 32 bytes of the transfer */
@@ -948,4 +1560,153 @@ int hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us)
return result;
}
+/*
+ * Transport for USBAT02-based CompactFlash and similar storage devices
+ */
+static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us)
+{
+ int rc;
+ struct usbat_info *info = (struct usbat_info *) (us->extra);
+ unsigned long block, blocks;
+ 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("usbat_flash_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] == READ_CAPACITY) {
+ rc = usbat_flash_check_media(us, info);
+ if (rc != USB_STOR_TRANSPORT_GOOD)
+ return rc;
+
+ rc = usbat_flash_get_sector_count(us, info);
+ if (rc != USB_STOR_TRANSPORT_GOOD)
+ return rc;
+
+ info->ssize = 0x200; // hard coded 512 byte sectors as per ATA spec
+ US_DEBUGP("usbat_flash_transport: READ_CAPACITY: %ld sectors, %ld bytes per sector\n",
+ info->sectors, info->ssize);
+
+ // build the reply
+ // note: must return the sector number of the last sector,
+ // *not* the total number of sectors
+ ((__be32 *) ptr)[0] = cpu_to_be32(info->sectors - 1);
+ ((__be32 *) ptr)[1] = cpu_to_be32(info->ssize);
+ usb_stor_set_xfer_buf(ptr, 8, srb);
+
+ return USB_STOR_TRANSPORT_GOOD;
+ }
+
+ if (srb->cmnd[0] == MODE_SELECT_10) {
+ US_DEBUGP("usbat_flash_transport: Gah! MODE_SELECT_10.\n");
+ return USB_STOR_TRANSPORT_ERROR;
+ }
+
+ if (srb->cmnd[0] == READ_10) {
+ block = ((u32)(srb->cmnd[2]) << 24) | ((u32)(srb->cmnd[3]) << 16) |
+ ((u32)(srb->cmnd[4]) << 8) | ((u32)(srb->cmnd[5]));
+
+ blocks = ((u32)(srb->cmnd[7]) << 8) | ((u32)(srb->cmnd[8]));
+
+ US_DEBUGP("usbat_flash_transport: READ_10: read block 0x%04lx count %ld\n", block, blocks);
+ return usbat_flash_read_data(us, info, block, blocks);
+ }
+
+ if (srb->cmnd[0] == READ_12) {
+ // I don't think we'll ever see a READ_12 but support it anyway...
+ block = ((u32)(srb->cmnd[2]) << 24) | ((u32)(srb->cmnd[3]) << 16) |
+ ((u32)(srb->cmnd[4]) << 8) | ((u32)(srb->cmnd[5]));
+
+ blocks = ((u32)(srb->cmnd[6]) << 24) | ((u32)(srb->cmnd[7]) << 16) |
+ ((u32)(srb->cmnd[8]) << 8) | ((u32)(srb->cmnd[9]));
+
+ US_DEBUGP("usbat_flash_transport: READ_12: read block 0x%04lx count %ld\n", block, blocks);
+ return usbat_flash_read_data(us, info, block, blocks);
+ }
+
+ if (srb->cmnd[0] == WRITE_10) {
+ block = ((u32)(srb->cmnd[2]) << 24) | ((u32)(srb->cmnd[3]) << 16) |
+ ((u32)(srb->cmnd[4]) << 8) | ((u32)(srb->cmnd[5]));
+
+ blocks = ((u32)(srb->cmnd[7]) << 8) | ((u32)(srb->cmnd[8]));
+
+ US_DEBUGP("usbat_flash_transport: WRITE_10: write block 0x%04lx count %ld\n", block, blocks);
+ return usbat_flash_write_data(us, info, block, blocks);
+ }
+
+ if (srb->cmnd[0] == WRITE_12) {
+ // I don't think we'll ever see a WRITE_12 but support it anyway...
+ block = ((u32)(srb->cmnd[2]) << 24) | ((u32)(srb->cmnd[3]) << 16) |
+ ((u32)(srb->cmnd[4]) << 8) | ((u32)(srb->cmnd[5]));
+
+ blocks = ((u32)(srb->cmnd[6]) << 24) | ((u32)(srb->cmnd[7]) << 16) |
+ ((u32)(srb->cmnd[8]) << 8) | ((u32)(srb->cmnd[9]));
+
+ US_DEBUGP("usbat_flash_transport: WRITE_12: write block 0x%04lx count %ld\n", block, blocks);
+ return usbat_flash_write_data(us, info, block, blocks);
+ }
+
+
+ if (srb->cmnd[0] == TEST_UNIT_READY) {
+ US_DEBUGP("usbat_flash_transport: TEST_UNIT_READY.\n");
+
+ rc = usbat_flash_check_media(us, info);
+ if (rc != USB_STOR_TRANSPORT_GOOD)
+ return rc;
+
+ return usbat_check_status(us);
+ }
+
+ if (srb->cmnd[0] == REQUEST_SENSE) {
+ US_DEBUGP("usbat_flash_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("usbat_flash_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;
+}
+
+/*
+ * Default transport function. Attempts to detect which transport function
+ * should be called, makes it the new default, and calls it.
+ *
+ * This function should never be called. Our usbat_init() function detects the
+ * device type and changes the us->transport ptr to the transport function
+ * relevant to the device.
+ * However, we'll support this impossible(?) case anyway.
+ */
+int usbat_transport(struct scsi_cmnd *srb, struct us_data *us)
+{
+ struct usbat_info *info = (struct usbat_info*) (us->extra);
+
+ if (usbat_set_transport(us, info))
+ return USB_STOR_TRANSPORT_ERROR;
+
+ return us->transport(srb, us);
+}
diff --git a/drivers/usb/storage/shuttle_usbat.h b/drivers/usb/storage/shuttle_usbat.h
index 9855c1d32d052..5b8e867e2ae5d 100644
--- a/drivers/usb/storage/shuttle_usbat.h
+++ b/drivers/usb/storage/shuttle_usbat.h
@@ -5,8 +5,9 @@
*
* Current development and maintenance by:
* (c) 2000 Robert Baruch (autophile@dol.net)
+ * (c) 2004, 2005 Daniel Drake <dsd@gentoo.org>
*
- * See scm.c for more explanation
+ * See shuttle_usbat.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
@@ -26,13 +27,59 @@
#ifndef _USB_SHUTTLE_USBAT_H
#define _USB_SHUTTLE_USBAT_H
+/* Supported device types */
+#define USBAT_DEV_HP8200 0x01
+#define USBAT_DEV_FLASH 0x02
+
#define USBAT_EPP_PORT 0x10
#define USBAT_EPP_REGISTER 0x30
#define USBAT_ATA 0x40
#define USBAT_ISA 0x50
-/* SCM User I/O Data registers */
+/* Commands (need to be logically OR'd with an access type */
+#define USBAT_CMD_READ_REG 0x00
+#define USBAT_CMD_WRITE_REG 0x01
+#define USBAT_CMD_READ_BLOCK 0x02
+#define USBAT_CMD_WRITE_BLOCK 0x03
+#define USBAT_CMD_COND_READ_BLOCK 0x04
+#define USBAT_CMD_COND_WRITE_BLOCK 0x05
+#define USBAT_CMD_WRITE_REGS 0x07
+
+/* Commands (these don't need an access type) */
+#define USBAT_CMD_EXEC_CMD 0x80
+#define USBAT_CMD_SET_FEAT 0x81
+#define USBAT_CMD_UIO 0x82
+
+/* Methods of accessing UIO register */
+#define USBAT_UIO_READ 1
+#define USBAT_UIO_WRITE 0
+
+/* Qualifier bits */
+#define USBAT_QUAL_FCQ 0x20 // full compare
+#define USBAT_QUAL_ALQ 0x10 // auto load subcount
+
+/* USBAT Flash Media status types */
+#define USBAT_FLASH_MEDIA_NONE 0
+#define USBAT_FLASH_MEDIA_CF 1
+
+/* USBAT Flash Media change types */
+#define USBAT_FLASH_MEDIA_SAME 0
+#define USBAT_FLASH_MEDIA_CHANGED 1
+/* USBAT ATA registers */
+#define USBAT_ATA_DATA 0x10 // read/write data (R/W)
+#define USBAT_ATA_FEATURES 0x11 // set features (W)
+#define USBAT_ATA_ERROR 0x11 // error (R)
+#define USBAT_ATA_SECCNT 0x12 // sector count (R/W)
+#define USBAT_ATA_SECNUM 0x13 // sector number (R/W)
+#define USBAT_ATA_LBA_ME 0x14 // cylinder low (R/W)
+#define USBAT_ATA_LBA_HI 0x15 // cylinder high (R/W)
+#define USBAT_ATA_DEVICE 0x16 // head/device selection (R/W)
+#define USBAT_ATA_STATUS 0x17 // device status (R)
+#define USBAT_ATA_CMD 0x17 // device command (W)
+#define USBAT_ATA_ALTSTATUS 0x0E // status (no clear IRQ) (R)
+
+/* USBAT User I/O Data registers */
#define USBAT_UIO_EPAD 0x80 // Enable Peripheral Control Signals
#define USBAT_UIO_CDT 0x40 // Card Detect (Read Only)
// CDT = ACKD & !UI1 & !UI0
@@ -43,8 +90,7 @@
#define USBAT_UIO_UI0 0x02 // Input 0
#define USBAT_UIO_INTR_ACK 0x01 // Interrupt (ATA & ISA)/Acknowledge (EPP)
-/* SCM User I/O Enable registers */
-
+/* USBAT User I/O Enable registers */
#define USBAT_UIO_DRVRST 0x80 // Reset Peripheral
#define USBAT_UIO_ACKD 0x40 // Enable Card Detect
#define USBAT_UIO_OE1 0x20 // I/O 1 set=output/clr=input
@@ -52,8 +98,26 @@
#define USBAT_UIO_OE0 0x10 // I/O 0 set=output/clr=input
#define USBAT_UIO_ADPRST 0x01 // Reset SCM chip
-/* HP 8200e stuff */
-extern int hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us);
-extern int init_8200e(struct us_data *us);
+/* USBAT Features */
+#define USBAT_FEAT_ETEN 0x80 // External trigger enable
+#define USBAT_FEAT_U1 0x08
+#define USBAT_FEAT_U0 0x04
+#define USBAT_FEAT_ET1 0x02
+#define USBAT_FEAT_ET2 0x01
+
+extern int usbat_transport(struct scsi_cmnd *srb, struct us_data *us);
+extern int init_usbat(struct us_data *us);
+
+struct usbat_info {
+ int devicetype;
+
+ /* Used for Flash readers only */
+ unsigned long sectors; // total sector count
+ unsigned long ssize; // sector size in bytes
+
+ 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/transport.c b/drivers/usb/storage/transport.c
index ddc1e3bcf845b..d2c3d2fa082e9 100644
--- a/drivers/usb/storage/transport.c
+++ b/drivers/usb/storage/transport.c
@@ -54,10 +54,10 @@
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_device.h>
+#include "usb.h"
#include "transport.h"
#include "protocol.h"
#include "scsiglue.h"
-#include "usb.h"
#include "debug.h"
@@ -383,7 +383,8 @@ int usb_stor_ctrl_transfer(struct us_data *us, unsigned int pipe,
* This routine always uses us->recv_intr_pipe as the pipe and
* us->ep_bInterval as the interrupt interval.
*/
-int usb_stor_intr_transfer(struct us_data *us, void *buf, unsigned int length)
+static int usb_stor_intr_transfer(struct us_data *us, void *buf,
+ unsigned int length)
{
int result;
unsigned int pipe = us->recv_intr_pipe;
@@ -436,7 +437,7 @@ int usb_stor_bulk_transfer_buf(struct us_data *us, unsigned int pipe,
* This function does basically the same thing as usb_stor_bulk_transfer_buf()
* above, but it uses the usbcore scatter-gather library.
*/
-int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe,
+static int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe,
struct scatterlist *sg, int num_sg, unsigned int length,
unsigned int *act_len)
{
@@ -991,10 +992,10 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)
/* DATA STAGE */
/* send/receive data payload, if there is any */
- /* Genesys Logic interface chips need a 100us delay between the
+ /* Some USB-IDE converter chips need a 100us delay between the
* command phase and the data phase. Some devices need a little
* more than that, probably because of clock rate inaccuracies. */
- if (le16_to_cpu(us->pusb_dev->descriptor.idVendor) == USB_VENDOR_ID_GENESYS)
+ if (unlikely(us->flags & US_FL_GO_SLOW))
udelay(110);
if (transfer_length) {
@@ -1055,19 +1056,31 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)
US_DEBUGP("Bulk Status S 0x%x T 0x%x R %u Stat 0x%x\n",
le32_to_cpu(bcs->Signature), bcs->Tag,
residue, bcs->Status);
- if ((bcs->Signature != cpu_to_le32(US_BULK_CS_SIGN) &&
- bcs->Signature != cpu_to_le32(US_BULK_CS_OLYMPUS_SIGN)) ||
- bcs->Tag != srb->serial_number ||
- bcs->Status > US_BULK_STAT_PHASE) {
+ if (bcs->Tag != srb->serial_number || bcs->Status > US_BULK_STAT_PHASE) {
US_DEBUGP("Bulk logical error\n");
return USB_STOR_TRANSPORT_ERROR;
}
+ /* Some broken devices report odd signatures, so we do not check them
+ * for validity against the spec. We store the first one we see,
+ * and check subsequent transfers for validity against this signature.
+ */
+ if (!us->bcs_signature) {
+ us->bcs_signature = bcs->Signature;
+ if (us->bcs_signature != cpu_to_le32(US_BULK_CS_SIGN))
+ US_DEBUGP("Learnt BCS signature 0x%08X\n",
+ le32_to_cpu(us->bcs_signature));
+ } else if (bcs->Signature != us->bcs_signature) {
+ US_DEBUGP("Signature mismatch: got %08X, expecting %08X\n",
+ le32_to_cpu(bcs->Signature),
+ le32_to_cpu(us->bcs_signature));
+ return USB_STOR_TRANSPORT_ERROR;
+ }
+
/* try to compute the actual residue, based on how much data
* was really transferred and what the device tells us */
if (residue) {
- if (!(us->flags & US_FL_IGNORE_RESIDUE) ||
- srb->sc_data_direction == DMA_TO_DEVICE) {
+ if (!(us->flags & US_FL_IGNORE_RESIDUE)) {
residue = min(residue, transfer_length);
srb->resid = max(srb->resid, (int) residue);
}
@@ -1126,11 +1139,11 @@ static int usb_stor_reset_common(struct us_data *us,
* RESETTING bit, and clear the ABORTING bit so that the reset
* may proceed.
*/
- scsi_lock(us->host);
+ scsi_lock(us_to_host(us));
usb_stor_report_device_reset(us);
set_bit(US_FLIDX_RESETTING, &us->flags);
clear_bit(US_FLIDX_ABORTING, &us->flags);
- scsi_unlock(us->host);
+ scsi_unlock(us_to_host(us));
/* A 20-second timeout may seem rather long, but a LaCie
* StudioDrive USB2 device takes 16+ seconds to get going
@@ -1146,7 +1159,7 @@ static int usb_stor_reset_common(struct us_data *us,
/* Give the device some time to recover from the reset,
* but don't delay disconnect processing. */
- wait_event_interruptible_timeout(us->dev_reset_wait,
+ wait_event_interruptible_timeout(us->delay_wait,
test_bit(US_FLIDX_DISCONNECTING, &us->flags),
HZ*6);
if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {
diff --git a/drivers/usb/storage/transport.h b/drivers/usb/storage/transport.h
index 153efd623afbb..e25f8d8fc7419 100644
--- a/drivers/usb/storage/transport.h
+++ b/drivers/usb/storage/transport.h
@@ -43,16 +43,13 @@
#include <linux/config.h>
#include <linux/blkdev.h>
-#include "usb.h"
-
-struct scsi_cmnd;
/* 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_HP8200e
+#ifdef CONFIG_USB_STORAGE_USBAT
#define US_PR_SCM_ATAPI 0x80 /* SCM-ATAPI bridge */
#endif
#ifdef CONFIG_USB_STORAGE_SDDR09
@@ -108,8 +105,6 @@ struct bulk_cs_wrap {
#define US_BULK_CS_WRAP_LEN 13
#define US_BULK_CS_SIGN 0x53425355 /* spells out 'USBS' */
-/* This is for Olympus Camedia digital cameras */
-#define US_BULK_CS_OLYMPUS_SIGN 0x55425355 /* spells out 'USBU' */
#define US_BULK_STAT_OK 0
#define US_BULK_STAT_FAIL 1
#define US_BULK_STAT_PHASE 2
@@ -171,13 +166,8 @@ extern int usb_stor_clear_halt(struct us_data *us, unsigned int pipe);
extern int usb_stor_ctrl_transfer(struct us_data *us, unsigned int pipe,
u8 request, u8 requesttype, u16 value, u16 index,
void *data, u16 size);
-extern int usb_stor_intr_transfer(struct us_data *us, void *buf,
- unsigned int length);
extern int usb_stor_bulk_transfer_buf(struct us_data *us, unsigned int pipe,
void *buf, unsigned int length, unsigned int *act_len);
-extern int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe,
- struct scatterlist *sg, int num_sg, unsigned int length,
- unsigned int *act_len);
extern int usb_stor_bulk_transfer_sg(struct us_data *us, unsigned int pipe,
void *buf, unsigned int length, int use_sg, int *residual);
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index e0904aab6b69d..d53f777c4f50f 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -59,16 +59,16 @@ UNUSUAL_DEV( 0x03f0, 0x0107, 0x0200, 0x0200,
"CD-Writer+",
US_SC_8070, US_PR_CB, NULL, 0),
-#ifdef CONFIG_USB_STORAGE_HP8200e
+#ifdef CONFIG_USB_STORAGE_USBAT
UNUSUAL_DEV( 0x03f0, 0x0207, 0x0001, 0x0001,
"HP",
"CD-Writer+ 8200e",
- US_SC_8070, US_PR_SCM_ATAPI, init_8200e, 0),
+ US_SC_8070, US_PR_SCM_ATAPI, init_usbat, 0),
UNUSUAL_DEV( 0x03f0, 0x0307, 0x0001, 0x0001,
"HP",
"CD-Writer+ CD-4e",
- US_SC_8070, US_PR_SCM_ATAPI, init_8200e, 0),
+ US_SC_8070, US_PR_SCM_ATAPI, init_usbat, 0),
#endif
/* Deduced by Jonathan Woithe <jwoithe@physics.adelaide.edu.au>
@@ -123,6 +123,22 @@ UNUSUAL_DEV( 0x04a4, 0x0004, 0x0001, 0x0001,
"DVD-CAM DZ-MV100A Camcorder",
US_SC_SCSI, US_PR_CB, NULL, US_FL_SINGLE_LUN),
+/* Reported by Andreas Bockhold <andreas@bockionline.de> */
+UNUSUAL_DEV( 0x04b0, 0x0405, 0x0100, 0x0100,
+ "NIKON",
+ "NIKON DSC D70",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_FIX_CAPACITY),
+
+/* BENQ DC5330
+ * Reported by Manuel Fombuena <mfombuena@ya.com> and
+ * Frank Copeland <fjc@thingy.apana.org.au> */
+UNUSUAL_DEV( 0x04a5, 0x3010, 0x0100, 0x0100,
+ "Tekom Technologies, Inc",
+ "300_CAMERA",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_IGNORE_RESIDUE ),
+
/* Reported by Simon Levitt <simon@whattf.com>
* This entry needs Sub and Proto fields */
UNUSUAL_DEV( 0x04b8, 0x0601, 0x0100, 0x0100,
@@ -171,15 +187,12 @@ UNUSUAL_DEV( 0x04da, 0x0d05, 0x0000, 0x0000,
"CD-R/RW Drive",
US_SC_8070, US_PR_CB, NULL, 0),
-/* Reported by Adriaan Penning <a.penning@luon.net>
- * Note that these cameras report "Medium not present" after
- * ALLOW_MEDIUM_REMOVAL, so they also need to be marked
- * NOT_LOCKABLE in the SCSI blacklist (and the vendor is MATSHITA). */
+/* Reported by Adriaan Penning <a.penning@luon.net> */
UNUSUAL_DEV( 0x04da, 0x2372, 0x0000, 0x9999,
"Panasonic",
"DMC-LCx Camera",
US_SC_DEVICE, US_PR_DEVICE, NULL,
- US_FL_FIX_CAPACITY ),
+ US_FL_FIX_CAPACITY | US_FL_NOT_LOCKABLE ),
/* Most of the following entries were developed with the help of
* Shuttle/SCM directly.
@@ -268,6 +281,14 @@ UNUSUAL_DEV( 0x04fc, 0x80c2, 0x0100, 0x0100,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_BULK32),
+#ifdef CONFIG_USB_STORAGE_USBAT
+UNUSUAL_DEV( 0x04e6, 0x1010, 0x0000, 0x9999,
+ "SCM",
+ "SCM USBAT-02",
+ US_SC_SCSI, US_PR_SCM_ATAPI, init_usbat,
+ US_FL_SINGLE_LUN),
+#endif
+
/* Reported by Bob Sass <rls@vectordb.com> -- only rev 1.33 tested */
UNUSUAL_DEV( 0x050d, 0x0115, 0x0133, 0x0133,
"Belkin",
@@ -324,12 +345,11 @@ UNUSUAL_DEV( 0x052b, 0x1911, 0x0100, 0x0100,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_IGNORE_RESIDUE ),
-/* This entry is needed because the device reports Sub=ff */
UNUSUAL_DEV( 0x054c, 0x0010, 0x0106, 0x0450,
"Sony",
"DSC-S30/S70/S75/505V/F505/F707/F717/P8",
US_SC_SCSI, US_PR_DEVICE, NULL,
- US_FL_SINGLE_LUN ),
+ US_FL_SINGLE_LUN | US_FL_NOT_LOCKABLE | US_FL_NO_WP_DETECT ),
/* This entry is needed because the device reports Sub=ff */
UNUSUAL_DEV( 0x054c, 0x0010, 0x0500, 0x0500,
@@ -354,6 +374,13 @@ UNUSUAL_DEV( 0x054c, 0x002b, 0x0100, 0x0110,
0 ),
#endif
+/* Submitted by Olaf Hering, <olh@suse.de> SuSE Bugzilla #49049 */
+UNUSUAL_DEV( 0x054c, 0x002c, 0x0501, 0x0501,
+ "Sony",
+ "USB Floppy Drive",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_SINGLE_LUN ),
+
UNUSUAL_DEV( 0x054c, 0x002d, 0x0100, 0x0100,
"Sony",
"Memorystick MSAC-US1",
@@ -497,6 +524,12 @@ UNUSUAL_DEV( 0x05ac, 0x1203, 0x0001, 0x0001,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_CAPACITY ),
+UNUSUAL_DEV( 0x05ac, 0x1205, 0x0001, 0x0001,
+ "Apple",
+ "iPod",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_FIX_CAPACITY ),
+
#ifdef CONFIG_USB_STORAGE_JUMPSHOT
UNUSUAL_DEV( 0x05dc, 0x0001, 0x0000, 0x0001,
"Lexar",
@@ -512,6 +545,25 @@ UNUSUAL_DEV( 0x05dc, 0xb002, 0x0000, 0x0113,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_INQUIRY ),
+/* The following two entries are for a Genesys USB to IDE
+ * converter chip, but it changes its ProductId depending
+ * on whether or not a disk or an optical device is enclosed
+ * They were originally reported by Alexander Oltu
+ * <alexander@all-2.com> and Peter Marks <peter.marks@turner.com>
+ * respectively.
+ */
+UNUSUAL_DEV( 0x05e3, 0x0701, 0x0000, 0xffff,
+ "Genesys Logic",
+ "USB to IDE Optical",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_GO_SLOW ),
+
+UNUSUAL_DEV( 0x05e3, 0x0702, 0x0000, 0xffff,
+ "Genesys Logic",
+ "USB to IDE Disk",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_GO_SLOW ),
+
/* Reported by Hanno Boeck <hanno@gmx.de>
* Taken from the Lycoris Kernel */
UNUSUAL_DEV( 0x0636, 0x0003, 0x0000, 0x9999,
@@ -540,19 +592,19 @@ UNUSUAL_DEV( 0x066f, 0x8000, 0x0001, 0x0001,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_CAPACITY ),
-/* Reported by Alex Butcher <alex.butcher@assursys.co.uk> */
-UNUSUAL_DEV( 0x067b, 0x3507, 0x0001, 0x0001,
+/* Reported by Richard -=[]=- <micro_flyer@hotmail.com> */
+UNUSUAL_DEV( 0x067b, 0x2507, 0x0100, 0x0100,
"Prolific Technology Inc.",
- "ATAPI-6 Bridge Controller",
+ "Mass Storage Device",
US_SC_DEVICE, US_PR_DEVICE, NULL,
- US_FL_FIX_CAPACITY ),
+ US_FL_FIX_CAPACITY | US_FL_GO_SLOW ),
/* Reported by Alex Butcher <alex.butcher@assursys.co.uk> */
UNUSUAL_DEV( 0x067b, 0x3507, 0x0001, 0x0001,
"Prolific Technology Inc.",
"ATAPI-6 Bridge Controller",
US_SC_DEVICE, US_PR_DEVICE, NULL,
- US_FL_FIX_CAPACITY ),
+ US_FL_FIX_CAPACITY | US_FL_GO_SLOW ),
/* Submitted by Benny Sjostrand <benny@hostmobility.com> */
UNUSUAL_DEV( 0x0686, 0x4011, 0x0001, 0x0001,
@@ -582,14 +634,6 @@ UNUSUAL_DEV( 0x0781, 0x0001, 0x0200, 0x0200,
US_SC_SCSI, US_PR_CB, NULL,
US_FL_SINGLE_LUN ),
-#if !defined(CONFIG_BLK_DEV_UB) && !defined(CONFIG_BLK_DEV_UB_MODULE)
-UNUSUAL_DEV( 0x0781, 0x0002, 0x0009, 0x0009,
- "Sandisk",
- "ImageMate SDDR-31",
- US_SC_DEVICE, US_PR_DEVICE, NULL,
- US_FL_IGNORE_SER ),
-#endif
-
UNUSUAL_DEV( 0x0781, 0x0100, 0x0100, 0x0100,
"Sandisk",
"ImageMate SDDR-12",
@@ -661,6 +705,13 @@ UNUSUAL_DEV( 0x07c4, 0xa001, 0x0000, 0xffff,
US_SC_SCSI, US_PR_DATAFAB, NULL,
0 ),
+/* Reported by Josef Reisinger <josef.reisinger@netcologne.de> */
+UNUSUAL_DEV( 0x07c4, 0xa002, 0x0000, 0xffff,
+ "Datafab/Unknown",
+ "MD2/MD3 Disk enclosure",
+ US_SC_SCSI, US_PR_DATAFAB, NULL,
+ US_FL_SINGLE_LUN ),
+
UNUSUAL_DEV( 0x07c4, 0xa003, 0x0000, 0xffff,
"Datafab/Unknown",
"Datafab-based Reader",
@@ -866,6 +917,13 @@ UNUSUAL_DEV( 0x0dda, 0x0001, 0x0012, 0x0012,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_IGNORE_RESIDUE ),
+/* Reported by Ian McConnell <ian at emit.demon.co.uk> */
+UNUSUAL_DEV( 0x0dda, 0x0301, 0x0012, 0x0012,
+ "PNP_MP3",
+ "PNP_MP3 PLAYER",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_IGNORE_RESIDUE ),
+
/* Submitted by Antoine Mairesse <antoine.mairesse@free.fr> */
UNUSUAL_DEV( 0x0ed1, 0x6660, 0x0100, 0x0300,
"USB",
@@ -888,6 +946,13 @@ UNUSUAL_DEV( 0x0ea0, 0x6828, 0x0110, 0x0110,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_IGNORE_RESIDUE ),
+/* Reported by Michael Stattmann <michael@stattmann.com> */
+UNUSUAL_DEV( 0x0fce, 0xd008, 0x0000, 0x0000,
+ "Sony Ericsson",
+ "V800-Vodafone 802",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_NO_WP_DETECT ),
+
/* Reported by Kevin Cernekee <kpc-usbdev@gelato.uiuc.edu>
* Tested on hardware version 1.10.
* Entry is needed only for the initializer function override.
@@ -905,6 +970,13 @@ UNUSUAL_DEV( 0x1370, 0x6828, 0x0110, 0x0110,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_IGNORE_RESIDUE ),
+/* Reported by Radovan Garabik <garabik@kassiopeia.juls.savba.sk> */
+UNUSUAL_DEV( 0x2735, 0x100b, 0x0000, 0x9999,
+ "MPIO",
+ "HS200",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_GO_SLOW ),
+
#ifdef CONFIG_USB_STORAGE_SDDR55
UNUSUAL_DEV( 0x55aa, 0xa103, 0x0000, 0x9999,
"Sandisk",
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index 0a8c42a0a8bf2..35c1ca6b5a8eb 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -51,6 +51,9 @@
#include <linux/sched.h>
#include <linux/errno.h>
#include <linux/suspend.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
@@ -63,7 +66,7 @@
#include "debug.h"
#include "initializers.h"
-#ifdef CONFIG_USB_STORAGE_HP8200e
+#ifdef CONFIG_USB_STORAGE_USBAT
#include "shuttle_usbat.h"
#endif
#ifdef CONFIG_USB_STORAGE_SDDR09
@@ -89,10 +92,6 @@
#endif
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-
/* Some informational data */
MODULE_AUTHOR("Matthew Dharm <mdharm-usb@one-eyed-alien.net>");
MODULE_DESCRIPTION("USB Mass Storage driver for Linux");
@@ -103,6 +102,13 @@ module_param(delay_use, uint, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(delay_use, "seconds to delay before using a new device");
+/* These are used to make sure the module doesn't unload before all the
+ * threads have exited.
+ */
+static atomic_t total_threads = ATOMIC_INIT(0);
+static DECLARE_COMPLETION(threads_gone);
+
+
static int storage_probe(struct usb_interface *iface,
const struct usb_device_id *id);
@@ -144,9 +150,7 @@ static struct usb_device_id storage_usb_ids [] = {
{ 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) },
-#if !defined(CONFIG_BLK_DEV_UB) && !defined(CONFIG_BLK_DEV_UB_MODULE)
{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_SCSI, US_PR_BULK) },
-#endif
/* Terminating entry */
{ }
@@ -220,16 +224,14 @@ static struct us_unusual_dev us_unusual_dev_list[] = {
.useTransport = US_PR_BULK},
{ .useProtocol = US_SC_8070,
.useTransport = US_PR_BULK},
-#if !defined(CONFIG_BLK_DEV_UB) && !defined(CONFIG_BLK_DEV_UB_MODULE)
{ .useProtocol = US_SC_SCSI,
.useTransport = US_PR_BULK},
-#endif
/* Terminating entry */
{ NULL }
};
-struct usb_driver usb_storage_driver = {
+static struct usb_driver usb_storage_driver = {
.owner = THIS_MODULE,
.name = "usb-storage",
.probe = storage_probe,
@@ -282,7 +284,7 @@ void fill_inquiry_response(struct us_data *us, unsigned char *data,
static int usb_stor_control_thread(void * __us)
{
struct us_data *us = (struct us_data *)__us;
- struct Scsi_Host *host = us->host;
+ struct Scsi_Host *host = us_to_host(us);
lock_kernel();
@@ -291,11 +293,13 @@ static int usb_stor_control_thread(void * __us)
* so get rid of all our resources.
*/
daemonize("usb-storage");
-
current->flags |= PF_NOFREEZE;
-
unlock_kernel();
+ /* acquire a reference to the host, so it won't be deallocated
+ * until we're ready to exit */
+ scsi_host_get(host);
+
/* signal that we've started the thread */
complete(&(us->notify));
@@ -309,9 +313,9 @@ static int usb_stor_control_thread(void * __us)
/* lock the device pointers */
down(&(us->dev_semaphore));
- /* if us->srb is NULL, we are being asked to exit */
- if (us->srb == NULL) {
- US_DEBUGP("-- exit command received\n");
+ /* if the device has disconnected, we are free to exit */
+ if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {
+ US_DEBUGP("-- exiting\n");
up(&(us->dev_semaphore));
break;
}
@@ -325,12 +329,6 @@ static int usb_stor_control_thread(void * __us)
goto SkipForAbort;
}
- /* don't do anything if we are disconnecting */
- if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {
- US_DEBUGP("No command during disconnect\n");
- goto SkipForDisconnect;
- }
-
scsi_unlock(host);
/* reject the command if the direction indicator
@@ -398,7 +396,6 @@ SkipForAbort:
complete(&(us->notify));
/* finished working on this command */
-SkipForDisconnect:
us->srb = NULL;
scsi_unlock(host);
@@ -406,6 +403,8 @@ SkipForDisconnect:
up(&(us->dev_semaphore));
} /* for (;;) */
+ scsi_host_put(host);
+
/* notify the exit routine that we're actually exiting now
*
* complete()/wait_for_completion() is similar to up()/down(),
@@ -420,7 +419,7 @@ SkipForDisconnect:
* This is important in preemption kernels, which transfer the flow
* of execution immediately upon a complete().
*/
- complete_and_exit(&(us->notify), 0);
+ complete_and_exit(&threads_gone, 0);
}
/***********************************************************************
@@ -483,6 +482,13 @@ static void get_device_info(struct us_data *us, int id_index)
unusual_dev->useTransport;
us->flags = unusual_dev->flags;
+ /*
+ * This flag is only needed when we're in high-speed, so let's
+ * disable it if we're in full-speed
+ */
+ if (dev->speed != USB_SPEED_HIGH)
+ us->flags &= ~US_FL_GO_SLOW;
+
/* Log a message if a non-generic unusual_dev entry contains an
* unnecessary subclass or protocol override. This may stimulate
* reports from users that will help us remove unneeded entries
@@ -515,37 +521,6 @@ static void get_device_info(struct us_data *us, int id_index)
idesc->bInterfaceProtocol,
msgs[msg]);
}
-
- /* Read the device's string descriptors */
- if (dev->descriptor.iManufacturer)
- usb_string(dev, dev->descriptor.iManufacturer,
- us->vendor, sizeof(us->vendor));
- if (dev->descriptor.iProduct)
- usb_string(dev, dev->descriptor.iProduct,
- us->product, sizeof(us->product));
- if (dev->descriptor.iSerialNumber)
- usb_string(dev, dev->descriptor.iSerialNumber,
- us->serial, sizeof(us->serial));
-
- /* Use the unusual_dev strings if the device didn't provide them */
- if (strlen(us->vendor) == 0) {
- if (unusual_dev->vendorName)
- strlcpy(us->vendor, unusual_dev->vendorName,
- sizeof(us->vendor));
- else
- strcpy(us->vendor, "Unknown");
- }
- if (strlen(us->product) == 0) {
- if (unusual_dev->productName)
- strlcpy(us->product, unusual_dev->productName,
- sizeof(us->product));
- else
- strcpy(us->product, "Unknown");
- }
- if (strlen(us->serial) == 0)
- strcpy(us->serial, "None");
-
- US_DEBUGP("Vendor: %s, Product: %s\n", us->vendor, us->product);
}
/* Get the transport settings */
@@ -572,10 +547,10 @@ static int get_transport(struct us_data *us)
us->transport_reset = usb_stor_Bulk_reset;
break;
-#ifdef CONFIG_USB_STORAGE_HP8200e
+#ifdef CONFIG_USB_STORAGE_USBAT
case US_PR_SCM_ATAPI:
us->transport_name = "SCM/ATAPI";
- us->transport = hp8200e_transport;
+ us->transport = usbat_transport;
us->transport_reset = usb_stor_CB_reset;
us->max_lun = 1;
break;
@@ -785,20 +760,6 @@ static int usb_stor_acquire_resources(struct us_data *us)
up(&us->dev_semaphore);
- /*
- * Since this is a new device, we need to register a SCSI
- * host definition with the higher SCSI layers.
- */
- us->host = scsi_host_alloc(&usb_stor_host_template, sizeof(us));
- if (!us->host) {
- printk(KERN_WARNING USB_STORAGE
- "Unable to allocate the scsi host\n");
- return -EBUSY;
- }
-
- /* Set the hostdata to prepare for scanning */
- us->host->hostdata[0] = (unsigned long) us;
-
/* Start up our control thread */
p = kernel_thread(usb_stor_control_thread, us, CLONE_VM);
if (p < 0) {
@@ -807,6 +768,7 @@ static int usb_stor_acquire_resources(struct us_data *us)
return p;
}
us->pid = p;
+ atomic_inc(&total_threads);
/* Wait for the thread to start */
wait_for_completion(&(us->notify));
@@ -815,37 +777,16 @@ static int usb_stor_acquire_resources(struct us_data *us)
}
/* Release all our dynamic resources */
-void usb_stor_release_resources(struct us_data *us)
+static void usb_stor_release_resources(struct us_data *us)
{
US_DEBUGP("-- %s\n", __FUNCTION__);
- /* Kill the control thread. The SCSI host must already have been
- * removed so it won't try to queue any more commands.
+ /* Tell the control thread to exit. The SCSI host must
+ * already have been removed so it won't try to queue
+ * any more commands.
*/
- if (us->pid) {
-
- /* Wait for the thread to be idle */
- down(&us->dev_semaphore);
- US_DEBUGP("-- sending exit command to thread\n");
-
- /* If the SCSI midlayer queued a final command just before
- * scsi_remove_host() was called, us->srb might not be
- * NULL. We can overwrite it safely, because the midlayer
- * will not wait for the command to finish. Also the
- * control thread will already have been awakened.
- * That's okay, an extra up() on us->sema won't hurt.
- *
- * Enqueue the command, wake up the thread, and wait for
- * notification that it has exited.
- */
- scsi_lock(us->host);
- us->srb = NULL;
- scsi_unlock(us->host);
- up(&us->dev_semaphore);
-
- up(&us->sema);
- wait_for_completion(&us->notify);
- }
+ US_DEBUGP("-- sending exit command to thread\n");
+ up(&us->sema);
/* Call the destructor routine, if it exists */
if (us->extra_destructor) {
@@ -853,16 +794,9 @@ void usb_stor_release_resources(struct us_data *us)
us->extra_destructor(us->extra);
}
- /* Finish the host removal sequence */
- if (us->host)
- scsi_host_put(us->host);
-
/* Free the extra data and the URB */
- if (us->extra)
- kfree(us->extra);
- if (us->current_urb)
- usb_free_urb(us->current_urb);
-
+ kfree(us->extra);
+ usb_free_urb(us->current_urb);
}
/* Dissociate from the USB device */
@@ -880,9 +814,6 @@ static void dissociate_dev(struct us_data *us)
/* Remove our private data from the interface */
usb_set_intfdata(us->pusb_intf, NULL);
-
- /* Free the structure itself */
- kfree(us);
}
/* Thread to carry out delayed SCSI-device scanning */
@@ -898,6 +829,13 @@ static int usb_stor_scan_thread(void * __us)
daemonize("usb-stor-scan");
unlock_kernel();
+ /* Acquire a reference to the host, so it won't be deallocated
+ * until we're ready to exit */
+ scsi_host_get(us_to_host(us));
+
+ /* Signal that we've started the thread */
+ complete(&(us->notify));
+
printk(KERN_DEBUG
"usb-storage: device found at %d\n", us->pusb_dev->devnum);
@@ -906,7 +844,7 @@ static int usb_stor_scan_thread(void * __us)
printk(KERN_DEBUG "usb-storage: waiting for device "
"to settle before scanning\n");
retry:
- wait_event_interruptible_timeout(us->scsi_scan_wait,
+ wait_event_interruptible_timeout(us->delay_wait,
test_bit(US_FLIDX_DISCONNECTING, &us->flags),
delay_use * HZ);
if (current->flags & PF_FREEZE) {
@@ -917,11 +855,14 @@ retry:
/* If the device is still connected, perform the scanning */
if (!test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {
- scsi_scan_host(us->host);
+ scsi_scan_host(us_to_host(us));
printk(KERN_DEBUG "usb-storage: device scan complete\n");
+
+ /* Should we unbind if no devices were detected? */
}
- complete_and_exit(&us->scsi_scan_done, 0);
+ scsi_host_put(us_to_host(us));
+ complete_and_exit(&threads_gone, 0);
}
@@ -929,25 +870,30 @@ retry:
static int storage_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
+ struct Scsi_Host *host;
struct us_data *us;
const int id_index = id - storage_usb_ids;
int result;
US_DEBUGP("USB Mass Storage device detected\n");
- /* Allocate the us_data structure and initialize the mutexes */
- us = (struct us_data *) kmalloc(sizeof(*us), GFP_KERNEL);
- if (!us) {
- printk(KERN_WARNING USB_STORAGE "Out of memory\n");
+ /*
+ * Ask the SCSI layer to allocate a host structure, with extra
+ * space at the end for our private us_data structure.
+ */
+ host = scsi_host_alloc(&usb_stor_host_template, sizeof(*us));
+ if (!host) {
+ printk(KERN_WARNING USB_STORAGE
+ "Unable to allocate the scsi host\n");
return -ENOMEM;
}
+
+ us = host_to_us(host);
memset(us, 0, sizeof(struct us_data));
init_MUTEX(&(us->dev_semaphore));
init_MUTEX_LOCKED(&(us->sema));
init_completion(&(us->notify));
- init_waitqueue_head(&us->dev_reset_wait);
- init_waitqueue_head(&us->scsi_scan_wait);
- init_completion(&us->scsi_scan_done);
+ init_waitqueue_head(&us->delay_wait);
/* Associate the us_data structure with the USB device */
result = associate_dev(us, intf);
@@ -1000,7 +946,7 @@ static int storage_probe(struct usb_interface *intf,
result = usb_stor_acquire_resources(us);
if (result)
goto BadDevice;
- result = scsi_add_host(us->host, &intf->dev);
+ result = scsi_add_host(host, &intf->dev);
if (result) {
printk(KERN_WARNING USB_STORAGE
"Unable to add the scsi host\n");
@@ -1012,17 +958,23 @@ static int storage_probe(struct usb_interface *intf,
if (result < 0) {
printk(KERN_WARNING USB_STORAGE
"Unable to start the device-scanning thread\n");
- scsi_remove_host(us->host);
+ scsi_remove_host(host);
goto BadDevice;
}
+ atomic_inc(&total_threads);
+
+ /* Wait for the thread to start */
+ wait_for_completion(&(us->notify));
return 0;
/* We come here if there are any problems */
BadDevice:
US_DEBUGP("storage_probe() failed\n");
+ set_bit(US_FLIDX_DISCONNECTING, &us->flags);
usb_stor_release_resources(us);
dissociate_dev(us);
+ scsi_host_put(host);
return result;
}
@@ -1034,24 +986,26 @@ static void storage_disconnect(struct usb_interface *intf)
US_DEBUGP("storage_disconnect() called\n");
/* Prevent new USB transfers, stop the current command, and
- * interrupt a device-reset delay */
+ * interrupt a SCSI-scan or device-reset delay */
set_bit(US_FLIDX_DISCONNECTING, &us->flags);
usb_stor_stop_transport(us);
- wake_up(&us->dev_reset_wait);
+ wake_up(&us->delay_wait);
- /* Interrupt the SCSI-device-scanning thread's time delay, and
- * wait for the thread to finish */
- wake_up(&us->scsi_scan_wait);
- wait_for_completion(&us->scsi_scan_done);
+ /* It doesn't matter if the SCSI-scanning thread is still running.
+ * The thread will exit when it sees the DISCONNECTING flag. */
/* Wait for the current command to finish, then remove the host */
down(&us->dev_semaphore);
up(&us->dev_semaphore);
- scsi_remove_host(us->host);
+ scsi_remove_host(us_to_host(us));
/* Wait for everything to become idle and release all our resources */
usb_stor_release_resources(us);
dissociate_dev(us);
+
+ /* Drop our reference to the host; the SCSI core will free it
+ * (and "us" along with it) when the refcount becomes 0. */
+ scsi_host_put(us_to_host(us));
}
/***********************************************************************
@@ -1081,6 +1035,16 @@ static void __exit usb_stor_exit(void)
*/
US_DEBUGP("-- calling usb_deregister()\n");
usb_deregister(&usb_storage_driver) ;
+
+ /* Don't return until all of our control and scanning threads
+ * have exited. Since each thread signals threads_gone as its
+ * last act, we have to call wait_for_completion the right number
+ * of times.
+ */
+ while (atomic_read(&total_threads) > 0) {
+ wait_for_completion(&threads_gone);
+ atomic_dec(&total_threads);
+ }
}
module_init(usb_stor_init);
diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h
index aaaf7ed5455c4..625b7aa980741 100644
--- a/drivers/usb/storage/usb.h
+++ b/drivers/usb/storage/usb.h
@@ -48,6 +48,7 @@
#include <linux/blkdev.h>
#include <linux/smp_lock.h>
#include <linux/completion.h>
+#include <scsi/scsi_host.h>
struct us_data;
struct scsi_cmnd;
@@ -65,16 +66,35 @@ struct us_unusual_dev {
unsigned int flags;
};
-/* Flag definitions: these entries are static */
-#define US_FL_SINGLE_LUN 0x00000001 /* allow access to only LUN 0 */
-#define US_FL_MODE_XLATE 0 /* [no longer used] */
-#define US_FL_NEED_OVERRIDE 0x00000004 /* unusual_devs entry is necessary */
-#define US_FL_IGNORE_SER 0 /* [no longer used] */
-#define US_FL_SCM_MULT_TARG 0x00000020 /* supports multiple targets */
-#define US_FL_FIX_INQUIRY 0x00000040 /* INQUIRY response needs faking */
-#define US_FL_FIX_CAPACITY 0x00000080 /* READ CAPACITY response too big */
-#define US_FL_IGNORE_RESIDUE 0x00000100 /* reported residue is wrong */
-#define US_FL_BULK32 0x00000200 /* Uses 32-byte CBW length */
+/*
+ * 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 */
@@ -121,11 +141,9 @@ struct us_data {
unsigned int recv_intr_pipe;
/* information about the device */
- char vendor[USB_STOR_STRING_LEN];
- char product[USB_STOR_STRING_LEN];
- char serial[USB_STOR_STRING_LEN];
char *transport_name;
char *protocol_name;
+ __le32 bcs_signature;
u8 subclass;
u8 protocol;
u8 max_lun;
@@ -139,7 +157,6 @@ struct us_data {
proto_cmnd proto_handler; /* protocol handler */
/* SCSI interfaces */
- struct Scsi_Host *host; /* our dummy host data */
struct scsi_cmnd *srb; /* current srb */
/* thread information */
@@ -154,19 +171,22 @@ struct us_data {
dma_addr_t iobuf_dma;
/* mutual exclusion and synchronization structures */
- struct semaphore sema; /* to sleep thread on */
- struct completion notify; /* thread begin/end */
- wait_queue_head_t dev_reset_wait; /* wait during reset */
- wait_queue_head_t scsi_scan_wait; /* wait before scanning */
- struct completion scsi_scan_done; /* scan thread end */
+ struct semaphore sema; /* to sleep thread on */
+ struct completion notify; /* thread begin/end */
+ wait_queue_head_t delay_wait; /* wait during scan, reset */
/* subdriver information */
void *extra; /* Any extra data */
extra_data_destructor extra_destructor;/* extra data destructor */
};
-/* The structure which defines our driver */
-extern struct usb_driver usb_storage_driver;
+/* Convert between us_data and the corresponding Scsi_Host */
+static struct Scsi_Host inline *us_to_host(struct us_data *us) {
+ return container_of((void *) us, struct Scsi_Host, hostdata);
+}
+static struct us_data inline *host_to_us(struct Scsi_Host *host) {
+ return (struct us_data *) host->hostdata;
+}
/* Function to fill an inquiry response. See usb.c for details */
extern void fill_inquiry_response(struct us_data *us,
diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c
index 71abda209aa2b..1bb67337fe6f8 100644
--- a/drivers/usb/usb-skeleton.c
+++ b/drivers/usb/usb-skeleton.c
@@ -120,7 +120,7 @@ static ssize_t skel_read(struct file *file, char *buffer, size_t count, loff_t *
usb_rcvbulkpipe(dev->udev, dev->bulk_in_endpointAddr),
dev->bulk_in_buffer,
min(dev->bulk_in_size, count),
- &count, HZ*10);
+ &count, 10000);
/* if the read was successful, copy the data to userspace */
if (!retval) {
@@ -271,7 +271,7 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i
}
if (!dev->bulk_out_endpointAddr &&
- !(endpoint->bEndpointAddress & USB_DIR_IN) &&
+ !(endpoint->bEndpointAddress & USB_DIR_OUT) &&
((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
== USB_ENDPOINT_XFER_BULK)) {
/* we found a bulk out endpoint */
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index eaa557bce1858..2a1c5965de222 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -5,7 +5,7 @@
menu "Graphics support"
config FB
- bool "Support for frame buffer devices"
+ tristate "Support for frame buffer devices"
---help---
The frame buffer device provides an abstraction for the graphics
hardware. It represents the frame buffer of some video hardware and
@@ -38,6 +38,47 @@ config FB
(e.g. an accelerated X server) and that are not frame buffer
device-aware may cause unexpected results. If unsure, say N.
+config FB_CFB_FILLRECT
+ tristate
+ depends on FB
+ default n
+ ---help---
+ Include the cfb_fillrect function for generic software rectangle
+ filling. This is used by drivers that don't provide their own
+ (accelerated) version.
+
+config FB_CFB_COPYAREA
+ tristate
+ depends on FB
+ default n
+ ---help---
+ Include the cfb_copyarea function for generic software area copying.
+ This is used by drivers that don't provide their own (accelerated)
+ version.
+
+config FB_CFB_IMAGEBLIT
+ tristate
+ depends on FB
+ default n
+ ---help---
+ Include the cfb_imageblit function for generic software image
+ blitting. This is used by drivers that don't provide their own
+ (accelerated) version.
+
+config FB_SOFT_CURSOR
+ tristate
+ depends on FB
+ default n
+ ---help---
+ Include the soft_cursor function for generic software cursor support.
+ This is used by drivers that don't provide their own (accelerated)
+ version.
+
+config FB_MACMODES
+ tristate
+ depends on FB
+ default n
+
config FB_MODE_HELPERS
bool "Enable Video Mode Handling Helpers"
depends on FB
@@ -70,6 +111,10 @@ config FB_TILEBLITTING
config FB_CIRRUS
tristate "Cirrus Logic support"
depends on FB && (ZORRO || PCI)
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
---help---
This enables support for Cirrus Logic GD542x/543x based boards on
Amiga: SD64, Piccolo, Picasso II/II+, Picasso IV, or EGS Spectrum.
@@ -85,6 +130,10 @@ config FB_CIRRUS
config FB_PM2
tristate "Permedia2 support"
depends on FB && ((AMIGA && BROKEN) || PCI)
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
help
This is the frame buffer device driver for the Permedia2 AGP frame
buffer card from ASK, aka `Graphic Blaster Exxtreme'. There is a
@@ -100,6 +149,10 @@ config FB_PM2_FIFO_DISCONNECT
config FB_ARMCLCD
tristate "ARM PrimeCell PL110 support"
depends on FB && ARM && ARM_AMBA
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
help
This framebuffer device driver is for the ARM PrimeCell PL110
Colour LCD controller. ARM PrimeCells provide the building
@@ -112,7 +165,11 @@ config FB_ARMCLCD
config FB_ACORN
bool "Acorn VIDC support"
- depends on FB && ARM && ARCH_ACORN
+ depends on (FB = y) && ARM && (ARCH_ACORN || ARCH_CLPS7500)
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
help
This is the frame buffer device driver for the Acorn VIDC graphics
hardware found in Acorn RISC PCs and other ARM-based machines. If
@@ -120,11 +177,19 @@ config FB_ACORN
config FB_CLPS711X
bool "CLPS711X LCD support"
- depends on FB && ARM && ARCH_CLPS711X
+ depends on (FB = y) && ARM && ARCH_CLPS711X
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
config FB_SA1100
bool "SA-1100 LCD support"
- depends on FB && ARM && ARCH_SA1100
+ depends on (FB = y) && ARM && ARCH_SA1100
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
help
This is a framebuffer device for the SA-1100 LCD Controller.
See <http://www.linux-fbdev.org/> for information on framebuffer
@@ -136,6 +201,10 @@ config FB_SA1100
config FB_CYBER2000
tristate "CyberPro 2000/2010/5000 support"
depends on FB && PCI && (BROKEN || !SPARC64)
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
help
This enables support for the Integraphics CyberPro 20x0 and 5000
VGA chips used in the Rebel.com Netwinder and other machines.
@@ -144,17 +213,25 @@ config FB_CYBER2000
config FB_APOLLO
bool
- depends on FB && APOLLO
+ depends on (FB = y) && APOLLO
default y
+ select FB_CFB_FILLRECT
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
config FB_Q40
bool
- depends on FB && Q40
+ depends on (FB = y) && Q40
default y
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
config FB_AMIGA
tristate "Amiga native chipset support"
depends on FB && AMIGA
+ select FB_SOFT_CURSOR
help
This is the frame buffer device driver for the builtin graphics
chipset found in Amigas.
@@ -191,6 +268,10 @@ config FB_AMIGA_AGA
config FB_CYBER
tristate "Amiga CyberVision 64 support"
depends on FB && ZORRO && BROKEN
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
help
This enables support for the Cybervision 64 graphics card from
Phase5. Please note that its use is not all that intuitive (i.e. if
@@ -201,7 +282,11 @@ config FB_CYBER
config FB_VIRGE
bool "Amiga CyberVision 64/3D support "
- depends on FB && ZORRO && BROKEN
+ depends on (FB = y) && ZORRO && BROKEN
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
help
This enables support for the Cybervision 64/3D graphics card from
Phase5. Please note that its use is not all that intuitive (i.e. if
@@ -212,7 +297,7 @@ config FB_VIRGE
config FB_RETINAZ3
tristate "Amiga Retina Z3 support"
- depends on FB && ZORRO && BROKEN
+ depends on (FB = y) && ZORRO && BROKEN
help
This enables support for the Retina Z3 graphics card. Say N unless
you have a Retina Z3 or plan to get one before you next recompile
@@ -220,73 +305,112 @@ config FB_RETINAZ3
config FB_FM2
bool "Amiga FrameMaster II/Rainbow II support"
- depends on FB && ZORRO
+ depends on (FB = y) && ZORRO
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
help
This is the frame buffer device driver for the Amiga FrameMaster
card from BSC (exhibited 1992 but not shipped as a CBM product).
config FB_ATARI
bool "Atari native chipset support"
- depends on FB && ATARI && BROKEN
+ depends on (FB = y) && ATARI && BROKEN
help
This is the frame buffer device driver for the builtin graphics
chipset found in Ataris.
config FB_OF
bool "Open Firmware frame buffer device support"
- depends on FB && (PPC64 || PPC_OF)
+ depends on (FB = y) && (PPC64 || PPC_OF)
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
+ select FB_MACMODES
help
Say Y if you want support with Open Firmware for your graphics
board.
config FB_CONTROL
bool "Apple \"control\" display support"
- depends on FB && PPC_PMAC
+ depends on (FB = y) && PPC_PMAC
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
+ select FB_MACMODES
help
This driver supports a frame buffer for the graphics adapter in the
Power Macintosh 7300 and others.
config FB_PLATINUM
bool "Apple \"platinum\" display support"
- depends on FB && PPC_PMAC
+ depends on (FB = y) && PPC_PMAC
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
+ select FB_MACMODES
help
This driver supports a frame buffer for the "platinum" graphics
adapter in some Power Macintoshes.
config FB_VALKYRIE
bool "Apple \"valkyrie\" display support"
- depends on FB && (MAC || PPC_PMAC)
+ depends on (FB = y) && (MAC || PPC_PMAC)
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
+ select FB_MACMODES
help
This driver supports a frame buffer for the "valkyrie" graphics
adapter in some Power Macintoshes.
config FB_CT65550
bool "Chips 65550 display support"
- depends on FB && PPC
+ depends on (FB = y) && PPC
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
help
This is the frame buffer device driver for the Chips & Technologies
65550 graphics chip in PowerBooks.
config FB_ASILIANT
bool "Chips 69000 display support"
- depends on FB && PCI
+ depends on (FB = y) && PCI
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
config FB_IMSTT
bool "IMS Twin Turbo display support"
- depends on FB && PCI
+ depends on (FB = y) && PCI
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
+ select FB_MACMODES if PPC
help
The IMS Twin Turbo is a PCI-based frame buffer card bundled with
many Macintosh and compatible computers.
config FB_S3TRIO
bool "S3 Trio display support"
- depends on FB && PPC && BROKEN
+ depends on (FB = y) && PPC && BROKEN
help
If you have a S3 Trio say Y. Say N for S3 Virge.
config FB_VGA16
tristate "VGA 16-color graphics support"
depends on FB && (X86 || PPC)
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
help
This is the frame buffer device driver for VGA 16 color graphic
cards. Say Y if you have such a card.
@@ -297,6 +421,10 @@ config FB_VGA16
config FB_STI
tristate "HP STI frame buffer device support"
depends on FB && PARISC
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
default y
---help---
STI refers to the HP "Standard Text Interface" which is a set of
@@ -313,24 +441,40 @@ config FB_STI
config FB_MAC
bool "Generic Macintosh display support"
- depends on FB && MAC
+ depends on (FB = y) && MAC
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
+ select FB_MACMODES
# bool ' Apple DAFB display support' CONFIG_FB_DAFB
config FB_HP300
bool
- depends on FB && HP300
+ depends on (FB = y) && HP300
+ select FB_CFB_FILLRECT
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
default y
config FB_TGA
tristate "TGA framebuffer support"
depends on FB && ALPHA
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
help
This is the frame buffer device driver for generic TGA graphic
cards. Say Y if you have one of those.
config FB_VESA
bool "VESA VGA graphics support"
- depends on FB && (X86 || X86_64)
+ depends on (FB = y) && (X86 || X86_64)
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
help
This is the frame buffer device driver for generic VESA 2.0
compliant graphic cards. The older VESA 1.2 cards are not supported.
@@ -345,6 +489,10 @@ config VIDEO_SELECT
config FB_HGA
tristate "Hercules mono graphics support"
depends on FB && X86
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
help
Say Y here if you have a Hercules mono graphics card.
@@ -364,18 +512,26 @@ config FB_HGA_ACCEL
config VIDEO_SELECT
bool
- depends on FB && X86
+ depends on (FB = y) && X86
default y
config FB_SGIVW
tristate "SGI Visual Workstation framebuffer support"
depends on FB && X86_VISWS
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
help
SGI Visual Workstation support for framebuffer graphics.
config FB_GBE
bool "SGI Graphics Backend frame buffer support"
- depends on FB && (SGI_IP32 || X86_VISWS)
+ depends on (FB = y) && (SGI_IP32 || X86_VISWS)
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
help
This is the frame buffer device driver for SGI Graphics Backend.
This chip is used in SGI O2 and Visual Workstation 320/540.
@@ -390,28 +546,38 @@ config FB_GBE_MEM
config BUS_I2C
bool
- depends on FB && VISWS
+ depends on (FB = y) && VISWS
default y
config FB_SUN3
bool "Sun3 framebuffer support"
- depends on FB && (SUN3 || SUN3X) && BROKEN
+ depends on (FB = y) && (SUN3 || SUN3X) && BROKEN
config FB_BW2
bool "BWtwo support"
- depends on FB && ((SPARC32 || SPARC64) && FB_SBUS || (SUN3 || SUN3X) && FB_SUN3)
+ depends on (FB = y) && ((SPARC32 || SPARC64) && FB_SBUS || (SUN3 || SUN3X) && FB_SUN3)
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
help
This is the frame buffer device driver for the BWtwo frame buffer.
config FB_CG3
bool "CGthree support"
- depends on FB && ((SPARC32 || SPARC64) && FB_SBUS || (SUN3 || SUN3X) && FB_SUN3)
+ depends on (FB = y) && ((SPARC32 || SPARC64) && FB_SBUS || (SUN3 || SUN3X) && FB_SUN3)
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
help
This is the frame buffer device driver for the CGthree frame buffer.
config FB_CG6
bool "CGsix (GX,TurboGX) support"
- depends on FB && ((SPARC32 || SPARC64) && FB_SBUS || (SUN3 || SUN3X) && FB_SUN3)
+ depends on (FB = y) && ((SPARC32 || SPARC64) && FB_SBUS || (SUN3 || SUN3X) && FB_SUN3)
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
help
This is the frame buffer device driver for the CGsix (GX, TurboGX)
frame buffer.
@@ -419,6 +585,10 @@ config FB_CG6
config FB_PVR2
tristate "NEC PowerVR 2 display support"
depends on FB && SH_DREAMCAST
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
---help---
Say Y here if you have a PowerVR 2 card in your box. If you plan to
run linux on your Dreamcast, you will have to say Y here.
@@ -436,19 +606,58 @@ config FB_PVR2
config FB_EPSON1355
bool "Epson 1355 framebuffer support"
- depends on FB && (SUPERH || ARCH_CEIVA)
+ depends on (FB = y) && (SUPERH || ARCH_CEIVA)
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
help
Build in support for the SED1355 Epson Research Embedded RAMDAC
LCD/CRT Controller (since redesignated as the S1D13505) as a
framebuffer. Product specs at
<http://www.erd.epson.com/vdc/html/products.htm>.
+config FB_NVIDIA
+ tristate "nVidia Framebuffer Support"
+ depends on FB && PCI
+ select I2C_ALGOBIT if FB_NVIDIA_I2C
+ select I2C if FB_NVIDIA_I2C
+ select FB_MODE_HELPERS
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
+ help
+ This driver supports graphics boards with the nVidia chips, TNT
+ and newer. For very old chipsets, such as the RIVA128, then use
+ the rivafb.
+ Say Y if you have such a graphics board.
+
+ To compile this driver as a module, choose M here: the
+ module will be called nvidiafb.
+
+config FB_NVIDIA_I2C
+ bool "Enable DDC Support"
+ depends on FB_NVIDIA && !PPC_OF
+ help
+ This enables I2C support for nVidia Chipsets. This is used
+ only for getting EDID information from the attached display
+ allowing for robust video mode handling and switching.
+
+ Because fbdev-2.6 requires that drivers must be able to
+ independently validate video mode parameters, you should say Y
+ here.
+
config FB_RIVA
tristate "nVidia Riva support"
depends on FB && PCI
select I2C_ALGOBIT if FB_RIVA_I2C
select I2C if FB_RIVA_I2C
select FB_MODE_HELPERS
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
help
This driver supports graphics boards with the nVidia Riva/Geforce
chips.
@@ -484,6 +693,10 @@ config FB_I810
select AGP
select AGP_INTEL
select FB_MODE_HELPERS
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
help
This driver supports the on-board graphics built in to the Intel 810
and 815 chipsets. Say Y if you have and plan to use such a board.
@@ -522,6 +735,11 @@ config FB_INTEL
depends on FB && EXPERIMENTAL && PCI && X86 && !X86_64
select AGP
select AGP_INTEL
+ select FB_MODE_HELPERS
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
help
This driver supports the on-board graphics built in to the Intel
830M/845G/852GM/855GM/865G chipsets.
@@ -541,6 +759,12 @@ config FB_INTEL_DEBUG
config FB_MATROX
tristate "Matrox acceleration"
depends on FB && PCI
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
+ select FB_TILEBLITTING
+ select FB_MACMODES if PPC_PMAC
---help---
Say Y here if you have a Matrox Millennium, Matrox Millennium II,
Matrox Mystique, Matrox Mystique 220, Matrox Productiva G100, Matrox
@@ -676,6 +900,11 @@ config FB_MATROX_MULTIHEAD
config FB_RADEON_OLD
tristate "ATI Radeon display support (Old driver)"
depends on FB && PCI
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
+ select FB_MACMODES if PPC
help
Choose this option if you want to use an ATI Radeon graphics card as
a framebuffer device. There are both PCI and AGP versions. You
@@ -689,6 +918,11 @@ config FB_RADEON
select I2C_ALGOBIT if FB_RADEON_I2C
select I2C if FB_RADEON_I2C
select FB_MODE_HELPERS
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
+ select FB_MACMODES if PPC_OF
help
Choose this option if you want to use an ATI Radeon graphics card as
a framebuffer device. There are both PCI and AGP versions. You
@@ -723,6 +957,11 @@ config FB_RADEON_DEBUG
config FB_ATY128
tristate "ATI Rage128 display support"
depends on FB && PCI
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
+ select FB_MACMODES if PPC_PMAC
help
This driver supports graphics boards with the ATI Rage128 chips.
Say Y if you have such a graphics board and read
@@ -734,6 +973,11 @@ config FB_ATY128
config FB_ATY
tristate "ATI Mach64 display support" if PCI || ATARI
depends on FB
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
+ select FB_MACMODES if PPC
help
This driver supports graphics boards with the ATI Mach64 chips.
Say Y if you have such a graphics board.
@@ -781,6 +1025,10 @@ config FB_SAVAGE
select I2C_ALGOBIT if FB_SAVAGE_I2C
select I2C if FB_SAVAGE_I2C
select FB_MODE_HELPERS
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
help
This driver supports notebooks and computers with S3 Savage PCI/AGP
chips.
@@ -791,7 +1039,7 @@ config FB_SAVAGE
will be called savagefb.
config FB_SAVAGE_I2C
- tristate "Enable DDC2 Support"
+ bool "Enable DDC2 Support"
depends on FB_SAVAGE
help
This enables I2C support for S3 Savage Chipsets. This is used
@@ -803,7 +1051,7 @@ config FB_SAVAGE_I2C
here.
config FB_SAVAGE_ACCEL
- tristate "Enable Console Acceleration"
+ bool "Enable Console Acceleration"
depends on FB_SAVAGE
default n
help
@@ -814,6 +1062,10 @@ config FB_SAVAGE_ACCEL
config FB_SIS
tristate "SiS acceleration"
depends on FB && PCI
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
help
This is the frame buffer device driver for the SiS 300, 315 and
330 series VGA chipsets. Specs available at <http://www.sis.com>
@@ -838,6 +1090,10 @@ config FB_NEOMAGIC
tristate "NeoMagic display support"
depends on FB && PCI
select FB_MODE_HELPERS
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
help
This driver supports notebooks with NeoMagic PCI chips.
Say Y if you have such a graphics card.
@@ -848,6 +1104,10 @@ config FB_NEOMAGIC
config FB_KYRO
tristate "IMG Kyro support"
depends on FB && PCI
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
help
Say Y here if you have a STG4000 / Kyro / PowerVR 3 based
graphics board.
@@ -858,6 +1118,10 @@ config FB_KYRO
config FB_3DFX
tristate "3Dfx Banshee/Voodoo3 display support"
depends on FB && PCI
+ select FB_CFB_IMAGEBLIT
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_SOFT_CURSOR
help
This driver supports graphics boards with the 3Dfx Banshee/Voodoo3
chips. Say Y if you have such a graphics board.
@@ -876,6 +1140,10 @@ config FB_3DFX_ACCEL
config FB_VOODOO1
tristate "3Dfx Voodoo Graphics (sst1) support"
depends on FB && PCI
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
---help---
Say Y here if you have a 3Dfx Voodoo Graphics (Voodoo1/sst1) or
Voodoo2 (cvg) based graphics card.
@@ -891,6 +1159,10 @@ config FB_VOODOO1
config FB_TRIDENT
tristate "Trident support"
depends on FB && PCI
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
---help---
This driver is supposed to support graphics boards with the
Trident CyberXXXX/Image/CyberBlade chips mostly found in laptops
@@ -953,17 +1225,22 @@ config PB1500_TFT
config FB_AU1100
bool "Au1100 LCD Driver"
- depends on FB && EXPERIMENTAL && PCI && MIPS && MIPS_PB1100=y
+ depends on (FB = y) && EXPERIMENTAL && PCI && MIPS && MIPS_PB1100=y
+
+source "drivers/video/geode/Kconfig"
config FB_SBUS
bool "SBUS and UPA framebuffers"
- depends on FB && (SPARC32 || SPARC64)
+ depends on (FB = y) && (SPARC32 || SPARC64)
help
Say Y if you want support for SBUS or UPA based frame buffer device.
config FB_FFB
bool "Creator/Creator3D/Elite3D support"
depends on FB_SBUS && SPARC64
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
help
This is the frame buffer device driver for the Creator, Creator3D,
and Elite3D graphics boards.
@@ -971,6 +1248,10 @@ config FB_FFB
config FB_TCX
bool "TCX (SS4/SS5 only) support"
depends on FB_SBUS
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
help
This is the frame buffer device driver for the TCX 24/8bit frame
buffer.
@@ -978,6 +1259,10 @@ config FB_TCX
config FB_CG14
bool "CGfourteen (SX) support"
depends on FB_SBUS
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
help
This is the frame buffer device driver for the CGfourteen frame
buffer on Desktop SPARCsystems with the SX graphics option.
@@ -985,6 +1270,10 @@ config FB_CG14
config FB_P9100
bool "P9100 (Sparcbook 3 only) support"
depends on FB_SBUS
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
help
This is the frame buffer device driver for the P9100 card
supported on Sparcbook 3 machines.
@@ -992,17 +1281,25 @@ config FB_P9100
config FB_LEO
bool "Leo (ZX) support"
depends on FB_SBUS
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
help
This is the frame buffer device driver for the SBUS-based Sun ZX
(leo) frame buffer cards.
config FB_PCI
bool "PCI framebuffers"
- depends on FB && PCI && (SPARC64 || SPARC32)
+ depends on (FB = y) && PCI && (SPARC64 || SPARC32)
config FB_IGA
bool "IGA 168x display support"
depends on SPARC32 && FB_PCI
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
help
This is the framebuffer device for the INTERGRAPHICS 1680 and
successor frame buffer cards.
@@ -1010,27 +1307,43 @@ config FB_IGA
config FB_HIT
tristate "HD64461 Frame Buffer support"
depends on FB && HD64461
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
help
This is the frame buffer device driver for the Hitachi HD64461 LCD
frame buffer card.
config FB_PMAG_AA
bool "PMAG-AA TURBOchannel framebuffer support"
- depends on FB && MACH_DECSTATION && TC
+ depends on (FB = y) && MACH_DECSTATION && TC
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
help
Support for the PMAG-AA TURBOchannel framebuffer card (1280x1024x1)
used mainly in the MIPS-based DECstation series.
config FB_PMAG_BA
bool "PMAG-BA TURBOchannel framebuffer support"
- depends on FB && MACH_DECSTATION && TC
+ depends on (FB = y) && MACH_DECSTATION && TC
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
help
Support for the PMAG-BA TURBOchannel framebuffer card (1024x864x8)
used mainly in the MIPS-based DECstation series.
config FB_PMAGB_B
bool "PMAGB-B TURBOchannel framebuffer support"
- depends on FB && MACH_DECSTATION && TC
+ depends on (FB = y) && MACH_DECSTATION && TC
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
help
Support for the PMAGB-B TURBOchannel framebuffer card used mainly
in the MIPS-based DECstation series. The card is currently only
@@ -1038,7 +1351,11 @@ config FB_PMAGB_B
config FB_MAXINE
bool "Maxine (Personal DECstation) onboard framebuffer support"
- depends on FB && MACH_DECSTATION && TC
+ depends on (FB = y) && MACH_DECSTATION && TC
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
help
Support for the onboard framebuffer (1024x768x8) in the Personal
DECstation series (Personal DECstation 5000/20, /25, /33, /50,
@@ -1046,7 +1363,11 @@ config FB_MAXINE
config FB_TX3912
bool "TMPTX3912/PR31700 frame buffer support"
- depends on FB && NINO
+ depends on (FB = y) && NINO
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
help
The TX3912 is a Toshiba RISC processor based on the MIPS 3900 core
see <http://www.toshiba.com/taec/components/Generic/risc/tx3912.htm>.
@@ -1056,13 +1377,21 @@ config FB_TX3912
config FB_G364
bool
depends on MIPS_MAGNUM_4000 || OLIVETTI_M700
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
help
The G364 driver is the framebuffer used in MIPS Magnum 4000 and
Olivetti M700-10 systems.
config FB_68328
bool "Motorola 68328 native frame buffer support"
- depends on (M68328 || M68EZ328 || M68VZ328)
+ depends on FB && (M68328 || M68EZ328 || M68VZ328)
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
help
Say Y here if you want to support the built-in frame buffer of
the Motorola 68328 CPU family.
@@ -1070,6 +1399,10 @@ config FB_68328
config FB_PXA
tristate "PXA LCD framebuffer support"
depends on FB && ARCH_PXA
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
---help---
Frame buffer driver for the built-in LCD controller in the Intel
PXA2x0 processor.
@@ -1084,6 +1417,10 @@ config FB_PXA
config FB_W100
tristate "W100 frame buffer support"
depends on FB && PXA_SHARPSL
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
---help---
Frame buffer driver for the w100 as found on the Sharp SL-Cxx series.
@@ -1111,9 +1448,25 @@ config FB_PXA_PARAMETERS
<file:Documentation/fb/pxafb.txt> describes the available parameters.
+config FB_S1D13XXX
+ tristate "Epson S1D13XXX framebuffer support"
+ depends on FB
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
+ help
+ Support for S1D13XXX framebuffer device family (currently only
+ working with S1D13806). Product specs at
+ <http://www.erd.epson.com/vdc/html/legacy_13xxx.htm>
+
config FB_VIRTUAL
tristate "Virtual Frame Buffer support (ONLY FOR TESTING!)"
depends on FB
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
---help---
This is a `virtual' frame buffer device. It operates on a chunk of
unswappable kernel memory instead of on the memory of a graphics
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index a0124274825cc..92265b741dc3a 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -8,102 +8,93 @@ obj-$(CONFIG_VT) += console/
obj-$(CONFIG_LOGO) += logo/
obj-$(CONFIG_SYSFS) += backlight/
-obj-$(CONFIG_FB) += fbmem.o fbmon.o fbcmap.o fbsysfs.o modedb.o softcursor.o
-# Only include macmodes.o if we have FB support and are PPC
-ifeq ($(CONFIG_FB),y)
-obj-$(CONFIG_PPC) += macmodes.o
-endif
+obj-$(CONFIG_FB) += fb.o
+fb-y := fbmem.o fbmon.o fbcmap.o fbsysfs.o modedb.o
+fb-objs := $(fb-y)
+
+obj-$(CONFIG_FB_CFB_FILLRECT) += cfbfillrect.o
+obj-$(CONFIG_FB_CFB_COPYAREA) += cfbcopyarea.o
+obj-$(CONFIG_FB_CFB_IMAGEBLIT) += cfbimgblt.o
+obj-$(CONFIG_FB_SOFT_CURSOR) += softcursor.o
+obj-$(CONFIG_FB_MACMODES) += macmodes.o
# Hardware specific drivers go first
obj-$(CONFIG_FB_RETINAZ3) += retz3fb.o
obj-$(CONFIG_FB_AMIGA) += amifb.o c2p.o
-obj-$(CONFIG_FB_CLPS711X) += clps711xfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
+obj-$(CONFIG_FB_CLPS711X) += clps711xfb.o
obj-$(CONFIG_FB_CYBER) += cyberfb.o
-obj-$(CONFIG_FB_CYBER2000) += cyber2000fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_PM2) += pm2fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
+obj-$(CONFIG_FB_CYBER2000) += cyber2000fb.o
+obj-$(CONFIG_FB_PM2) += pm2fb.o
obj-$(CONFIG_FB_PM3) += pm3fb.o
-obj-$(CONFIG_FB_MATROX) += matrox/ cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_RIVA) += riva/ cfbimgblt.o cfbfillrect.o \
- cfbcopyarea.o vgastate.o
-obj-$(CONFIG_FB_ATY) += aty/ cfbcopyarea.o cfbfillrect.o cfbimgblt.o
-obj-$(CONFIG_FB_ATY128) += aty/ cfbcopyarea.o cfbfillrect.o cfbimgblt.o
-obj-$(CONFIG_FB_RADEON) += aty/ cfbcopyarea.o cfbfillrect.o cfbimgblt.o
-obj-$(CONFIG_FB_SIS) += sis/ cfbcopyarea.o cfbfillrect.o cfbimgblt.o
-obj-$(CONFIG_FB_KYRO) += kyro/ cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_SAVAGE) += savage/ cfbfillrect.o cfbcopyarea.o \
- cfbimgblt.o
-obj-$(CONFIG_FB_I810) += cfbcopyarea.o cfbfillrect.o cfbimgblt.o \
- vgastate.o
-obj-$(CONFIG_FB_INTEL) += cfbfillrect.o cfbcopyarea.o \
- cfbimgblt.o
-
-obj-$(CONFIG_FB_RADEON_OLD) += radeonfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_NEOMAGIC) += neofb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o vgastate.o
+obj-$(CONFIG_FB_MATROX) += matrox/
+obj-$(CONFIG_FB_RIVA) += riva/ vgastate.o
+obj-$(CONFIG_FB_NVIDIA) += nvidia/
+obj-$(CONFIG_FB_ATY) += aty/ macmodes.o
+obj-$(CONFIG_FB_ATY128) += aty/ macmodes.o
+obj-$(CONFIG_FB_RADEON) += aty/
+obj-$(CONFIG_FB_SIS) += sis/
+obj-$(CONFIG_FB_KYRO) += kyro/
+obj-$(CONFIG_FB_SAVAGE) += savage/
+obj-$(CONFIG_FB_GEODE) += geode/
+obj-$(CONFIG_FB_I810) += vgastate.o
+obj-$(CONFIG_FB_RADEON_OLD) += radeonfb.o
+obj-$(CONFIG_FB_NEOMAGIC) += neofb.o vgastate.o
obj-$(CONFIG_FB_VIRGE) += virgefb.o
-obj-$(CONFIG_FB_3DFX) += tdfxfb.o cfbimgblt.o
-ifneq ($(CONFIG_FB_3DFX_ACCEL),y)
-obj-$(CONFIG_FB_3DFX) += cfbfillrect.o cfbcopyarea.o
-endif
-obj-$(CONFIG_FB_CONTROL) += controlfb.o macmodes.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_PLATINUM) += platinumfb.o macmodes.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_VALKYRIE) += valkyriefb.o macmodes.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_CT65550) += chipsfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_IMSTT) += imsttfb.o cfbimgblt.o
+obj-$(CONFIG_FB_3DFX) += tdfxfb.o
+obj-$(CONFIG_FB_CONTROL) += controlfb.o
+obj-$(CONFIG_FB_PLATINUM) += platinumfb.o
+obj-$(CONFIG_FB_VALKYRIE) += valkyriefb.o
+obj-$(CONFIG_FB_CT65550) += chipsfb.o
+obj-$(CONFIG_FB_IMSTT) += imsttfb.o
obj-$(CONFIG_FB_S3TRIO) += S3triofb.o
-obj-$(CONFIG_FB_FM2) += fm2fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_TRIDENT) += tridentfb.o cfbfillrect.o cfbimgblt.o cfbcopyarea.o
-obj-$(CONFIG_FB_STI) += stifb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_FFB) += ffb.o sbuslib.o cfbimgblt.o cfbcopyarea.o
-obj-$(CONFIG_FB_CG6) += cg6.o sbuslib.o cfbimgblt.o cfbcopyarea.o
-obj-$(CONFIG_FB_CG3) += cg3.o sbuslib.o cfbimgblt.o cfbcopyarea.o \
- cfbfillrect.o
-obj-$(CONFIG_FB_BW2) += bw2.o sbuslib.o cfbimgblt.o cfbcopyarea.o \
- cfbfillrect.o
-obj-$(CONFIG_FB_CG14) += cg14.o sbuslib.o cfbimgblt.o cfbcopyarea.o \
- cfbfillrect.o
-obj-$(CONFIG_FB_P9100) += p9100.o sbuslib.o cfbimgblt.o cfbcopyarea.o \
- cfbfillrect.o
-obj-$(CONFIG_FB_TCX) += tcx.o sbuslib.o cfbimgblt.o cfbcopyarea.o \
- cfbfillrect.o
-obj-$(CONFIG_FB_LEO) += leo.o sbuslib.o cfbimgblt.o cfbcopyarea.o \
- cfbfillrect.o
-obj-$(CONFIG_FB_SGIVW) += sgivwfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_ACORN) += acornfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
+obj-$(CONFIG_FB_FM2) += fm2fb.o
+obj-$(CONFIG_FB_TRIDENT) += tridentfb.o
+obj-$(CONFIG_FB_STI) += stifb.o
+obj-$(CONFIG_FB_FFB) += ffb.o sbuslib.o
+obj-$(CONFIG_FB_CG6) += cg6.o sbuslib.o
+obj-$(CONFIG_FB_CG3) += cg3.o sbuslib.o
+obj-$(CONFIG_FB_BW2) += bw2.o sbuslib.o
+obj-$(CONFIG_FB_CG14) += cg14.o sbuslib.o
+obj-$(CONFIG_FB_P9100) += p9100.o sbuslib.o
+obj-$(CONFIG_FB_TCX) += tcx.o sbuslib.o
+obj-$(CONFIG_FB_LEO) += leo.o sbuslib.o
+obj-$(CONFIG_FB_SGIVW) += sgivwfb.o
+obj-$(CONFIG_FB_ACORN) += acornfb.o
obj-$(CONFIG_FB_ATARI) += atafb.o
-obj-$(CONFIG_FB_MAC) += macfb.o macmodes.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_HGA) += hgafb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_IGA) += igafb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_APOLLO) += dnfb.o cfbfillrect.o cfbimgblt.o
-obj-$(CONFIG_FB_Q40) += q40fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_TGA) += tgafb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_HP300) += hpfb.o cfbfillrect.o cfbimgblt.o
-obj-$(CONFIG_FB_G364) += g364fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_SA1100) += sa1100fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
+obj-$(CONFIG_FB_MAC) += macfb.o
+obj-$(CONFIG_FB_HGA) += hgafb.o
+obj-$(CONFIG_FB_IGA) += igafb.o
+obj-$(CONFIG_FB_APOLLO) += dnfb.o
+obj-$(CONFIG_FB_Q40) += q40fb.o
+obj-$(CONFIG_FB_TGA) += tgafb.o
+obj-$(CONFIG_FB_HP300) += hpfb.o
+obj-$(CONFIG_FB_G364) += g364fb.o
+obj-$(CONFIG_FB_SA1100) += sa1100fb.o
obj-$(CONFIG_FB_SUN3) += sun3fb.o
-obj-$(CONFIG_FB_HIT) += hitfb.o cfbfillrect.o cfbimgblt.o
-obj-$(CONFIG_FB_EPSON1355) += epson1355fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_PVR2) += pvr2fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_VOODOO1) += sstfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_ARMCLCD) += amba-clcd.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_68328) += 68328fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_GBE) += gbefb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_CIRRUS) += cirrusfb.o cfbfillrect.o cfbimgblt.o cfbcopyarea.o
-obj-$(CONFIG_FB_ASILIANT) += asiliantfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_PXA) += pxafb.o cfbimgblt.o cfbcopyarea.o cfbfillrect.o
-obj-$(CONFIG_FB_W100) += w100fb.o cfbimgblt.o cfbcopyarea.o cfbfillrect.o
+obj-$(CONFIG_FB_HIT) += hitfb.o
+obj-$(CONFIG_FB_EPSON1355) += epson1355fb.o
+obj-$(CONFIG_FB_PVR2) += pvr2fb.o
+obj-$(CONFIG_FB_VOODOO1) += sstfb.o
+obj-$(CONFIG_FB_ARMCLCD) += amba-clcd.o
+obj-$(CONFIG_FB_68328) += 68328fb.o
+obj-$(CONFIG_FB_GBE) += gbefb.o
+obj-$(CONFIG_FB_CIRRUS) += cirrusfb.o
+obj-$(CONFIG_FB_ASILIANT) += asiliantfb.o
+obj-$(CONFIG_FB_PXA) += pxafb.o
+obj-$(CONFIG_FB_W100) += w100fb.o
obj-$(CONFIG_FB_AU1100) += au1100fb.o fbgen.o
-obj-$(CONFIG_FB_PMAG_AA) += pmag-aa-fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_PMAG_BA) += pmag-ba-fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_PMAGB_B) += pmagb-b-fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_MAXINE) += maxinefb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_TX3912) += tx3912fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
+obj-$(CONFIG_FB_PMAG_AA) += pmag-aa-fb.o
+obj-$(CONFIG_FB_PMAG_BA) += pmag-ba-fb.o
+obj-$(CONFIG_FB_PMAGB_B) += pmagb-b-fb.o
+obj-$(CONFIG_FB_MAXINE) += maxinefb.o
+obj-$(CONFIG_FB_TX3912) += tx3912fb.o
+obj-$(CONFIG_FB_S1D13XXX) += s1d13xxxfb.o
# Platform or fallback drivers go here
-obj-$(CONFIG_FB_VESA) += vesafb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_VGA16) += vga16fb.o cfbfillrect.o cfbcopyarea.o \
- cfbimgblt.o vgastate.o
-obj-$(CONFIG_FB_OF) += offb.o cfbfillrect.o cfbimgblt.o cfbcopyarea.o
+obj-$(CONFIG_FB_VESA) += vesafb.o
+obj-$(CONFIG_FB_VGA16) += vga16fb.o vgastate.o
+obj-$(CONFIG_FB_OF) += offb.o
# the test framebuffer is last
-obj-$(CONFIG_FB_VIRTUAL) += vfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
+obj-$(CONFIG_FB_VIRTUAL) += vfb.o
diff --git a/drivers/video/acornfb.c b/drivers/video/acornfb.c
index 9e1a835f7e5cd..f02965f395016 100644
--- a/drivers/video/acornfb.c
+++ b/drivers/video/acornfb.c
@@ -909,7 +909,7 @@ acornfb_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma
* some updates to the screen occasionally, but process switches
* should cause the caches and buffers to be flushed often enough.
*/
- if (io_remap_page_range(vma, vma->vm_start, off,
+ if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
vma->vm_end - vma->vm_start,
vma->vm_page_prot))
return -EAGAIN;
diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c
index 99c538f201a46..cf8bb67462dc5 100644
--- a/drivers/video/amifb.c
+++ b/drivers/video/amifb.c
@@ -3338,7 +3338,7 @@ static int ami_get_var_cursorinfo(struct fb_var_cursorinfo *var, u_char *data)
register short delta;
register u_char color;
short height, width, bits, words;
- int i, size, alloc;
+ int size, alloc;
size = par->crsr.height*par->crsr.width;
alloc = var->height*var->width;
@@ -3348,8 +3348,8 @@ 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 ((i = verify_area(VERIFY_WRITE, (void *)data, size)))
- return i;
+ if (!access_ok(VERIFY_WRITE, (void *)data, size))
+ return -EFAULT;
delta = 1<<par->crsr.fmode;
lspr = lofsprite + (delta<<1);
if (par->bplcon0 & BPC0_LACE)
@@ -3413,7 +3413,6 @@ static int ami_set_var_cursorinfo(struct fb_var_cursorinfo *var, u_char *data)
register short delta;
u_short fmode;
short height, width, bits, words;
- int i;
if (!var->width)
return -EINVAL;
@@ -3429,8 +3428,8 @@ static int ami_set_var_cursorinfo(struct fb_var_cursorinfo *var, u_char *data)
return -EINVAL;
if (!var->height)
return -EINVAL;
- if ((i = verify_area(VERIFY_READ, (void *)data, var->width*var->height)))
- return i;
+ if (!access_ok(VERIFY_READ, (void *)data, var->width*var->height))
+ return -EFAULT;
delta = 1<<fmode;
lofsprite = shfsprite = (u_short *)spritememory;
lspr = lofsprite + (delta<<1);
diff --git a/drivers/video/asiliantfb.c b/drivers/video/asiliantfb.c
index 15e09259057a0..f4729f4df8cec 100644
--- a/drivers/video/asiliantfb.c
+++ b/drivers/video/asiliantfb.c
@@ -46,7 +46,7 @@
#include <asm/io.h>
/* Built in clock of the 69030 */
-const unsigned Fref = 14318180;
+static const unsigned Fref = 14318180;
#define mmio_base (p->screen_base + 0x400000)
@@ -91,11 +91,6 @@ static void mm_write_ar(struct fb_info *p, u8 reg, u8 data)
}
#define write_ar(num, val) mm_write_ar(p, num, val)
-/*
- * Exported functions
- */
-int asiliantfb_init(void);
-
static int asiliantfb_pci_init(struct pci_dev *dp, const struct pci_device_id *);
static int asiliantfb_check_var(struct fb_var_screeninfo *var,
struct fb_info *info);
@@ -465,7 +460,7 @@ static struct chips_init_reg chips_init_xr[] =
{0xd1, 0x01},
};
-static void __init chips_hw_init(struct fb_info *p)
+static void __devinit chips_hw_init(struct fb_info *p)
{
int i;
@@ -488,7 +483,7 @@ static void __init chips_hw_init(struct fb_info *p)
write_fr(chips_init_fr[i].addr, chips_init_fr[i].data);
}
-static struct fb_fix_screeninfo asiliantfb_fix __initdata = {
+static struct fb_fix_screeninfo asiliantfb_fix __devinitdata = {
.id = "Asiliant 69000",
.type = FB_TYPE_PACKED_PIXELS,
.visual = FB_VISUAL_PSEUDOCOLOR,
@@ -497,7 +492,7 @@ static struct fb_fix_screeninfo asiliantfb_fix __initdata = {
.smem_len = 0x200000, /* 2MB */
};
-static struct fb_var_screeninfo asiliantfb_var __initdata = {
+static struct fb_var_screeninfo asiliantfb_var __devinitdata = {
.xres = 640,
.yres = 480,
.xres_virtual = 640,
@@ -518,7 +513,7 @@ static struct fb_var_screeninfo asiliantfb_var __initdata = {
.vsync_len = 2,
};
-static void __init init_asiliant(struct fb_info *p, unsigned long addr)
+static void __devinit init_asiliant(struct fb_info *p, unsigned long addr)
{
p->fix = asiliantfb_fix;
p->fix.smem_start = addr;
@@ -604,12 +599,12 @@ static struct pci_driver asiliantfb_driver = {
.remove = __devexit_p(asiliantfb_remove),
};
-int __init asiliantfb_init(void)
+static int __init asiliantfb_init(void)
{
if (fb_get_options("asiliantfb", NULL))
return -ENODEV;
- return pci_module_init(&asiliantfb_driver);
+ return pci_register_driver(&asiliantfb_driver);
}
module_init(asiliantfb_init);
diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c
index b7fc32c8f44ec..8a4ba3bb98728 100644
--- a/drivers/video/aty/aty128fb.c
+++ b/drivers/video/aty/aty128fb.c
@@ -166,7 +166,7 @@ static const char *r128_family[] __devinitdata = {
static int aty128_probe(struct pci_dev *pdev,
const struct pci_device_id *ent);
static void aty128_remove(struct pci_dev *pdev);
-static int aty128_pci_suspend(struct pci_dev *pdev, u32 state);
+static int aty128_pci_suspend(struct pci_dev *pdev, pm_message_t state);
static int aty128_pci_resume(struct pci_dev *pdev);
static int aty128_do_resume(struct pci_dev *pdev);
@@ -425,11 +425,6 @@ struct aty128fb_par {
#define round_div(n, d) ((n+(d/2))/d)
- /*
- * Interface used by the world
- */
-int aty128fb_init(void);
-
static int aty128fb_check_var(struct fb_var_screeninfo *var,
struct fb_info *info);
static int aty128fb_set_par(struct fb_info *info);
@@ -1648,7 +1643,8 @@ static int aty128fb_sync(struct fb_info *info)
return 0;
}
-int __init aty128fb_setup(char *options)
+#ifndef MODULE
+static int __init aty128fb_setup(char *options)
{
char *this_opt;
@@ -1701,6 +1697,7 @@ int __init aty128fb_setup(char *options)
}
return 0;
}
+#endif /* MODULE */
/*
@@ -2330,10 +2327,11 @@ static void aty128_set_suspend(struct aty128fb_par *par, int suspend)
}
}
-static int aty128_pci_suspend(struct pci_dev *pdev, u32 state)
+static int aty128_pci_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct fb_info *info = pci_get_drvdata(pdev);
struct aty128fb_par *par = info->par;
+ u8 agp;
/* We don't do anything but D2, for now we return 0, but
* we may want to change that. How do we know if the BIOS
@@ -2371,6 +2369,27 @@ static int aty128_pci_suspend(struct pci_dev *pdev, u32 state)
par->asleep = 1;
par->lock_blank = 1;
+ /* Disable AGP. The AGP host should have done it, but since ordering
+ * isn't always properly guaranteed in this specific case, let's make
+ * sure it's disabled on card side now. Ultimately, when merging fbdev
+ * and dri into some common infrastructure, this will be handled
+ * more nicely. The host bridge side will (or will not) be dealt with
+ * by the bridge AGP driver, we don't attempt to touch it here.
+ */
+ agp = pci_find_capability(pdev, PCI_CAP_ID_AGP);
+ if (agp) {
+ u32 cmd;
+
+ pci_read_config_dword(pdev, agp + PCI_AGP_COMMAND, &cmd);
+ if (cmd & PCI_AGP_COMMAND_AGP) {
+ printk(KERN_INFO "aty128fb: AGP was enabled, "
+ "disabling ...\n");
+ cmd &= ~PCI_AGP_COMMAND_AGP;
+ pci_write_config_dword(pdev, agp + PCI_AGP_COMMAND,
+ cmd);
+ }
+ }
+
/* We need a way to make sure the fbdev layer will _not_ touch the
* framebuffer before we put the chip to suspend state. On 2.4, I
* used dummy fb ops, 2.5 need proper support for this at the
@@ -2413,7 +2432,7 @@ static int aty128_do_resume(struct pci_dev *pdev)
par->lock_blank = 0;
aty128fb_blank(0, info);
- pdev->dev.power.power_state = 0;
+ pdev->dev.power.power_state = PMSG_ON;
printk(KERN_DEBUG "aty128fb: resumed !\n");
@@ -2432,7 +2451,7 @@ static int aty128_pci_resume(struct pci_dev *pdev)
}
-int __init aty128fb_init(void)
+static int __init aty128fb_init(void)
{
#ifndef MODULE
char *option = NULL;
@@ -2442,7 +2461,7 @@ int __init aty128fb_init(void)
aty128fb_setup(option);
#endif
- return pci_module_init(&aty128fb_driver);
+ return pci_register_driver(&aty128fb_driver);
}
static void __exit aty128fb_exit(void)
@@ -2452,7 +2471,6 @@ static void __exit aty128fb_exit(void)
module_init(aty128fb_init);
-#ifdef MODULE
module_exit(aty128fb_exit);
MODULE_AUTHOR("(c)1999-2003 Brad Douglas <brad@neruo.com>");
@@ -2464,5 +2482,4 @@ MODULE_PARM_DESC(mode_option, "Specify resolution as \"<xres>x<yres>[-<bpp>][@<r
module_param_named(nomtrr, mtrr, invbool, 0);
MODULE_PARM_DESC(nomtrr, "bool: Disable MTRR support (0 or 1=disabled) (default=0)");
#endif
-#endif
diff --git a/drivers/video/aty/atyfb.h b/drivers/video/aty/atyfb.h
index 0264ca6a2d92a..09de173c1164b 100644
--- a/drivers/video/aty/atyfb.h
+++ b/drivers/video/aty/atyfb.h
@@ -334,7 +334,6 @@ extern u8 aty_ld_pll_ct(int offset, const struct atyfb_par *par);
*/
extern int aty_init_cursor(struct fb_info *info);
-extern int atyfb_cursor(struct fb_info *info, struct fb_cursor *cursor);
/*
* Hardware acceleration
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c
index b9a06fb69de64..8c42538dc8c12 100644
--- a/drivers/video/aty/atyfb_base.c
+++ b/drivers/video/aty/atyfb_base.c
@@ -100,8 +100,8 @@
/*
* Debug flags.
*/
-/*#undef DEBUG*/
-#define DEBUG
+#undef DEBUG
+/*#define DEBUG*/
/* Make sure n * PAGE_SIZE is protected at end of Aperture for GUI-regs */
/* - must be large enough to catch all GUI-Regs */
@@ -209,7 +209,7 @@ struct pci_mmap_map {
unsigned long prot_mask;
};
-static struct fb_fix_screeninfo atyfb_fix __initdata = {
+static struct fb_fix_screeninfo atyfb_fix __devinitdata = {
.id = "ATY Mach64",
.type = FB_TYPE_PACKED_PIXELS,
.visual = FB_VISUAL_PSEUDOCOLOR,
@@ -265,7 +265,7 @@ static int read_aty_sense(const struct atyfb_par *par);
* Interface used by the world
*/
-struct fb_var_screeninfo default_var = {
+static struct fb_var_screeninfo default_var = {
/* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */
640, 480, 640, 480, 0, 0, 8, 0,
{0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
@@ -307,6 +307,7 @@ static int vram;
static int pll;
static int mclk;
static int xclk;
+static int comp_sync __initdata = -1;
static char *mode;
#ifdef CONFIG_PPC
@@ -361,7 +362,7 @@ static struct {
const char *name;
int pll, mclk, xclk;
u32 features;
-} aty_chips[] __initdata = {
+} aty_chips[] __devinitdata = {
#ifdef CONFIG_FB_ATY_GX
/* Mach64 GX */
{ PCI_CHIP_MACH64GX, "ATI888GX00 (Mach64 GX)", 135, 50, 50, ATI_CHIP_88800GX },
@@ -492,31 +493,31 @@ static int __devinit correct_chipset(struct atyfb_par *par)
return 0;
}
-static char ram_dram[] __initdata = "DRAM";
-static char ram_resv[] __initdata = "RESV";
+static char ram_dram[] __devinitdata = "DRAM";
+static char ram_resv[] __devinitdata = "RESV";
#ifdef CONFIG_FB_ATY_GX
-static char ram_vram[] __initdata = "VRAM";
+static char ram_vram[] __devinitdata = "VRAM";
#endif /* CONFIG_FB_ATY_GX */
#ifdef CONFIG_FB_ATY_CT
-static char ram_edo[] __initdata = "EDO";
-static char ram_sdram[] __initdata = "SDRAM (1:1)";
-static char ram_sgram[] __initdata = "SGRAM (1:1)";
-static char ram_sdram32[] __initdata = "SDRAM (2:1) (32-bit)";
-static char ram_off[] __initdata = "OFF";
+static char ram_edo[] __devinitdata = "EDO";
+static char ram_sdram[] __devinitdata = "SDRAM (1:1)";
+static char ram_sgram[] __devinitdata = "SGRAM (1:1)";
+static char ram_sdram32[] __devinitdata = "SDRAM (2:1) (32-bit)";
+static char ram_off[] __devinitdata = "OFF";
#endif /* CONFIG_FB_ATY_CT */
static u32 pseudo_palette[17];
#ifdef CONFIG_FB_ATY_GX
-static char *aty_gx_ram[8] __initdata = {
+static char *aty_gx_ram[8] __devinitdata = {
ram_dram, ram_vram, ram_vram, ram_dram,
ram_dram, ram_vram, ram_vram, ram_resv
};
#endif /* CONFIG_FB_ATY_GX */
#ifdef CONFIG_FB_ATY_CT
-static char *aty_ct_ram[8] __initdata = {
+static char *aty_ct_ram[8] __devinitdata = {
ram_off, ram_dram, ram_edo, ram_edo,
ram_sdram, ram_sgram, ram_sdram32, ram_resv
};
@@ -2016,7 +2017,7 @@ static int aty_power_mgmt(int sleep, struct atyfb_par *par)
return timeout ? 0 : -EIO;
}
-static int atyfb_pci_suspend(struct pci_dev *pdev, u32 state)
+static int atyfb_pci_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct fb_info *info = pci_get_drvdata(pdev);
struct atyfb_par *par = (struct atyfb_par *) info->par;
@@ -2091,7 +2092,7 @@ static int atyfb_pci_resume(struct pci_dev *pdev)
release_console_sem();
- pdev->dev.power.power_state = 0;
+ pdev->dev.power.power_state = PMSG_ON;
return 0;
}
@@ -2527,6 +2528,13 @@ static int __init aty_init(struct fb_info *info, const char *name)
else
var.accel_flags |= FB_ACCELF_TEXT;
+ if (comp_sync != -1) {
+ if (!comp_sync)
+ var.sync &= ~FB_SYNC_COMP_HIGH_ACT;
+ else
+ var.sync |= FB_SYNC_COMP_HIGH_ACT;
+ }
+
if (var.yres == var.yres_virtual) {
u32 videoram = (info->fix.smem_len - (PAGE_SIZE << 2));
var.yres_virtual = ((videoram * 8) / var.bits_per_pixel) / var.xres_virtual;
@@ -2990,7 +2998,7 @@ static int __devinit atyfb_setup_sparc(struct pci_dev *pdev,
#ifdef __i386__
#ifdef CONFIG_FB_ATY_GENERIC_LCD
-void aty_init_lcd(struct atyfb_par *par, u32 bios_base)
+static void aty_init_lcd(struct atyfb_par *par, u32 bios_base)
{
u32 driv_inf_tab, sig;
u16 lcd_ofs;
@@ -3427,8 +3435,7 @@ static int __devinit atyfb_pci_probe(struct pci_dev *pdev, const struct pci_devi
err_release_io:
#ifdef __sparc__
- if (par->mmap_map)
- kfree(par->mmap_map);
+ kfree(par->mmap_map);
#else
if (par->ati_regbase)
iounmap(par->ati_regbase);
@@ -3436,7 +3443,7 @@ err_release_io:
iounmap(info->screen_base);
#endif
err_release_mem:
- if(par->aux_start)
+ if (par->aux_start)
release_mem_region(par->aux_start, par->aux_size);
release_mem_region(par->res_start, par->res_size);
@@ -3543,8 +3550,7 @@ static void __devexit atyfb_remove(struct fb_info *info)
#endif
#endif
#ifdef __sparc__
- if (par->mmap_map)
- kfree(par->mmap_map);
+ kfree(par->mmap_map);
#endif
if (par->aux_start)
release_mem_region(par->aux_start, par->aux_size);
@@ -3589,7 +3595,8 @@ static struct pci_driver atyfb_driver = {
#endif /* CONFIG_PCI */
-int __init atyfb_setup(char *options)
+#ifndef MODULE
+static int __init atyfb_setup(char *options)
{
char *this_opt;
@@ -3611,6 +3618,8 @@ int __init atyfb_setup(char *options)
mclk = simple_strtoul(this_opt + 5, NULL, 0);
else if (!strncmp(this_opt, "xclk:", 5))
xclk = simple_strtoul(this_opt+5, NULL, 0);
+ else if (!strncmp(this_opt, "comp_sync:", 10))
+ comp_sync = simple_strtoul(this_opt+10, NULL, 0);
#ifdef CONFIG_PPC
else if (!strncmp(this_opt, "vmode:", 6)) {
unsigned int vmode =
@@ -3657,8 +3666,9 @@ int __init atyfb_setup(char *options)
}
return 0;
}
+#endif /* MODULE */
-int __init atyfb_init(void)
+static int __init atyfb_init(void)
{
#ifndef MODULE
char *option = NULL;
@@ -3669,7 +3679,7 @@ int __init atyfb_init(void)
#endif
#ifdef CONFIG_PCI
- pci_module_init(&atyfb_driver);
+ pci_register_driver(&atyfb_driver);
#endif
#ifdef CONFIG_ATARI
atyfb_atari_probe();
@@ -3677,7 +3687,7 @@ int __init atyfb_init(void)
return 0;
}
-void __exit atyfb_exit(void)
+static void __exit atyfb_exit(void)
{
#ifdef CONFIG_PCI
pci_unregister_driver(&atyfb_driver);
@@ -3685,9 +3695,7 @@ void __exit atyfb_exit(void)
}
module_init(atyfb_init);
-#ifdef MODULE
module_exit(atyfb_exit);
-#endif
MODULE_DESCRIPTION("FBDev driver for ATI Mach64 cards");
MODULE_LICENSE("GPL");
@@ -3701,6 +3709,9 @@ module_param(mclk, int, 0);
MODULE_PARM_DESC(mclk, "int: override memory clock");
module_param(xclk, int, 0);
MODULE_PARM_DESC(xclk, "int: override accelerated engine clock");
+module_param(comp_sync, int, 0);
+MODULE_PARM_DESC(comp_sync,
+ "Set composite sync signal to low (0) or high (1)");
module_param(mode, charp, 0);
MODULE_PARM_DESC(mode, "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" ");
#ifdef CONFIG_MTRR
diff --git a/drivers/video/aty/mach64_ct.c b/drivers/video/aty/mach64_ct.c
index e3325d5426cb9..9bdb2aab01aa2 100644
--- a/drivers/video/aty/mach64_ct.c
+++ b/drivers/video/aty/mach64_ct.c
@@ -359,7 +359,8 @@ void aty_set_pll_ct(const struct fb_info *info, const union aty_pll *pll)
#endif
}
-void __init aty_get_pll_ct(const struct fb_info *info, union aty_pll *pll)
+static void __init aty_get_pll_ct(const struct fb_info *info,
+ union aty_pll *pll)
{
struct atyfb_par *par = (struct atyfb_par *) info->par;
u8 tmp, clock;
@@ -382,7 +383,9 @@ void __init aty_get_pll_ct(const struct fb_info *info, union aty_pll *pll)
}
}
-int __init aty_init_pll_ct(const struct fb_info *info, union aty_pll *pll) {
+static int __init aty_init_pll_ct(const struct fb_info *info,
+ union aty_pll *pll)
+{
struct atyfb_par *par = (struct atyfb_par *) info->par;
u8 mpost_div, xpost_div, sclk_post_div_real, sclk_fb_div, spll_cntl2;
u32 q, i, memcntl, trp;
diff --git a/drivers/video/aty/mach64_cursor.c b/drivers/video/aty/mach64_cursor.c
index fbba31e404855..ad8b7496f8539 100644
--- a/drivers/video/aty/mach64_cursor.c
+++ b/drivers/video/aty/mach64_cursor.c
@@ -71,7 +71,7 @@ static const u8 cursor_mask_lookup[16] = {
0xa8, 0x28, 0x88, 0x08, 0xa0, 0x20, 0x80, 0x00
};
-int atyfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
+static int atyfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
{
struct atyfb_par *par = (struct atyfb_par *) info->par;
u16 xoff, yoff;
diff --git a/drivers/video/aty/radeon_accel.c b/drivers/video/aty/radeon_accel.c
index dc8598dacbcb2..3ca27cb13caa0 100644
--- a/drivers/video/aty/radeon_accel.c
+++ b/drivers/video/aty/radeon_accel.c
@@ -189,32 +189,6 @@ void radeonfb_engine_reset(struct radeonfb_info *rinfo)
radeon_engine_flush (rinfo);
- /* Some ASICs have bugs with dynamic-on feature, which are
- * ASIC-version dependent, so we force all blocks on for now
- * -- from XFree86
- * We don't do that on macs, things just work here with dynamic
- * clocking... --BenH
- */
-#ifdef CONFIG_ALL_PPC
- if (_machine != _MACH_Pmac && rinfo->hasCRTC2)
-#else
- if (rinfo->has_CRTC2)
-#endif
- {
- u32 tmp;
-
- tmp = INPLL(SCLK_CNTL);
- OUTPLL(SCLK_CNTL, ((tmp & ~DYN_STOP_LAT_MASK) |
- CP_MAX_DYN_STOP_LAT |
- SCLK_FORCEON_MASK));
-
- if (rinfo->family == CHIP_FAMILY_RV200)
- {
- tmp = INPLL(SCLK_MORE_CNTL);
- OUTPLL(SCLK_MORE_CNTL, tmp | SCLK_MORE_FORCEON);
- }
- }
-
clock_cntl_index = INREG(CLOCK_CNTL_INDEX);
mclk_cntl = INPLL(MCLK_CNTL);
@@ -274,8 +248,6 @@ void radeonfb_engine_reset(struct radeonfb_info *rinfo)
OUTREG(CLOCK_CNTL_INDEX, clock_cntl_index);
OUTPLL(MCLK_CNTL, mclk_cntl);
- if (rinfo->R300_cg_workaround)
- R300_cg_workardound(rinfo);
}
void radeonfb_engine_init (struct radeonfb_info *rinfo)
diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c
index 4bec134eb12ce..e8eb124754b13 100644
--- a/drivers/video/aty/radeon_base.c
+++ b/drivers/video/aty/radeon_base.c
@@ -1,4 +1,3 @@
-
/*
* drivers/video/aty/radeon_base.c
*
@@ -531,6 +530,7 @@ static int __devinit radeon_probe_pll_params(struct radeonfb_info *rinfo)
}
ppll_div_sel = INREG8(CLOCK_CNTL_INDEX + 1) & 0x3;
+ radeon_pll_errata_after_index(rinfo);
n = (INPLL(PPLL_DIV_0 + ppll_div_sel) & 0x7ff);
m = (INPLL(PPLL_REF_DIV) & 0x3ff);
@@ -913,7 +913,7 @@ static int radeonfb_ioctl (struct inode *inode, struct file *file, unsigned int
OUTREG(CRTC_EXT_CNTL, tmp);
- break;
+ return 0;
case FBIO_RADEON_GET_MIRROR:
if (!rinfo->is_mobility)
return -EINVAL;
@@ -1139,7 +1139,8 @@ static int radeonfb_setcolreg (unsigned regno, unsigned red, unsigned green,
}
-void radeon_save_state (struct radeonfb_info *rinfo, struct radeon_regs *save)
+static void radeon_save_state (struct radeonfb_info *rinfo,
+ struct radeon_regs *save)
{
/* CRTC regs */
save->crtc_gen_cntl = INREG(CRTC_GEN_CNTL);
@@ -1169,6 +1170,7 @@ void radeon_save_state (struct radeonfb_info *rinfo, struct radeon_regs *save)
/* PLL regs */
save->clk_cntl_index = INREG(CLOCK_CNTL_INDEX) & ~0x3f;
+ radeon_pll_errata_after_index(rinfo);
save->ppll_div_3 = INPLL(PPLL_DIV_3);
save->ppll_ref_div = INPLL(PPLL_REF_DIV);
}
@@ -1198,6 +1200,8 @@ static void radeon_write_pll_regs(struct radeonfb_info *rinfo, struct radeon_reg
OUTREGP(CLOCK_CNTL_INDEX,
mode->clk_cntl_index & PPLL_DIV_SEL_MASK,
~PPLL_DIV_SEL_MASK);
+ radeon_pll_errata_after_index(rinfo);
+ radeon_pll_errata_after_data(rinfo);
return;
}
}
@@ -1214,6 +1218,8 @@ static void radeon_write_pll_regs(struct radeonfb_info *rinfo, struct radeon_reg
OUTREGP(CLOCK_CNTL_INDEX,
mode->clk_cntl_index & PPLL_DIV_SEL_MASK,
~PPLL_DIV_SEL_MASK);
+ radeon_pll_errata_after_index(rinfo);
+ radeon_pll_errata_after_data(rinfo);
/* Set PPLL ref. div */
if (rinfo->family == CHIP_FAMILY_R300 ||
@@ -1737,8 +1743,7 @@ static int radeonfb_set_par(struct fb_info *info)
} else {
/* DFP */
newmode->fp_gen_cntl |= (FP_FPON | FP_TMDS_EN);
- newmode->tmds_transmitter_cntl = (TMDS_RAN_PAT_RST | TMDS_ICHCSEL) &
- ~(TMDS_PLLRST);
+ newmode->tmds_transmitter_cntl &= ~(TMDS_PLLRST);
/* TMDS_PLL_EN bit is reversed on RV (and mobility) chips */
if (IS_R300_VARIANT(rinfo) ||
(rinfo->family == CHIP_FAMILY_R200) || !rinfo->has_CRTC2)
@@ -2231,7 +2236,7 @@ static int radeonfb_pci_register (struct pci_dev *pdev,
rinfo->has_CRTC2 = (ent->driver_data & CHIP_HAS_CRTC2) != 0;
rinfo->is_mobility = (ent->driver_data & CHIP_IS_MOBILITY) != 0;
rinfo->is_IGP = (ent->driver_data & CHIP_IS_IGP) != 0;
-
+
/* Set base addrs */
rinfo->fb_base_phys = pci_resource_start (pdev, 0);
rinfo->mmio_base_phys = pci_resource_start (pdev, 2);
@@ -2254,6 +2259,24 @@ static int radeonfb_pci_register (struct pci_dev *pdev,
rinfo->fb_local_base = INREG(MC_FB_LOCATION) << 16;
+ /*
+ * Check for errata
+ */
+ rinfo->errata = 0;
+ if (rinfo->family == CHIP_FAMILY_R300 &&
+ (INREG(CONFIG_CNTL) & CFG_ATI_REV_ID_MASK)
+ == CFG_ATI_REV_A11)
+ rinfo->errata |= CHIP_ERRATA_R300_CG;
+
+ if (rinfo->family == CHIP_FAMILY_RV200 ||
+ rinfo->family == CHIP_FAMILY_RS200)
+ rinfo->errata |= CHIP_ERRATA_PLL_DUMMYREADS;
+
+ if (rinfo->family == CHIP_FAMILY_RV100 ||
+ rinfo->family == CHIP_FAMILY_RS100 ||
+ rinfo->family == CHIP_FAMILY_RS200)
+ rinfo->errata |= CHIP_ERRATA_PLL_DELAY;
+
#ifdef CONFIG_PPC_OF
/* On PPC, we obtain the OF device-node pointer to the firmware
* data for this chip
@@ -2293,13 +2316,6 @@ static int radeonfb_pci_register (struct pci_dev *pdev,
rinfo->mapped_vram/1024);
/*
- * Check for required workaround for PLL accesses
- */
- rinfo->R300_cg_workaround = (rinfo->family == CHIP_FAMILY_R300 &&
- (INREG(CONFIG_CNTL) & CFG_ATI_REV_ID_MASK)
- == CFG_ATI_REV_A11);
-
- /*
* Map the BIOS ROM if any and retreive 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
@@ -2359,6 +2375,15 @@ static int radeonfb_pci_register (struct pci_dev *pdev,
radeon_save_state (rinfo, &rinfo->init_state);
memcpy(&rinfo->state, &rinfo->init_state, sizeof(struct radeon_regs));
+ /* Setup Power Management capabilities */
+ if (default_dynclk < -1) {
+ /* -2 is special: means ON on mobility chips and do not
+ * change on others
+ */
+ radeonfb_pm_init(rinfo, rinfo->is_mobility ? 1 : -1);
+ } else
+ radeonfb_pm_init(rinfo, default_dynclk);
+
pci_set_drvdata(pdev, info);
/* Register with fbdev layer */
@@ -2369,13 +2394,6 @@ static int radeonfb_pci_register (struct pci_dev *pdev,
goto err_unmap_fb;
}
- /* Setup Power Management capabilities */
- if (default_dynclk < -1) {
- /* -2 is special: means ON on mobility chips and do not change on others */
- radeonfb_pm_init(rinfo, rinfo->is_mobility ? 1 : -1);
- } else
- radeonfb_pm_init(rinfo, default_dynclk);
-
#ifdef CONFIG_MTRR
rinfo->mtrr_hdl = nomtrr ? -1 : mtrr_add(rinfo->fb_base_phys,
rinfo->video_ram,
@@ -2401,10 +2419,8 @@ static int radeonfb_pci_register (struct pci_dev *pdev,
err_unmap_fb:
iounmap(rinfo->fb_base);
err_unmap_rom:
- if (rinfo->mon1_EDID)
- kfree(rinfo->mon1_EDID);
- if (rinfo->mon2_EDID)
- kfree(rinfo->mon2_EDID);
+ kfree(rinfo->mon1_EDID);
+ kfree(rinfo->mon2_EDID);
if (rinfo->mon1_modedb)
fb_destroy_modedb(rinfo->mon1_modedb);
fb_dealloc_cmap(&info->cmap);
@@ -2460,10 +2476,8 @@ static void __devexit radeonfb_pci_unregister (struct pci_dev *pdev)
pci_release_regions(pdev);
- if (rinfo->mon1_EDID)
- kfree(rinfo->mon1_EDID);
- if (rinfo->mon2_EDID)
- kfree(rinfo->mon2_EDID);
+ kfree(rinfo->mon1_EDID);
+ kfree(rinfo->mon2_EDID);
if (rinfo->mon1_modedb)
fb_destroy_modedb(rinfo->mon1_modedb);
#ifdef CONFIG_FB_RADEON_I2C
@@ -2486,27 +2500,8 @@ static struct pci_driver radeonfb_driver = {
#endif /* CONFIG_PM */
};
-int __init radeonfb_setup (char *options);
-
-int __init radeonfb_init (void)
-{
#ifndef MODULE
- char *option = NULL;
-
- if (fb_get_options("radeonfb", &option))
- return -ENODEV;
- radeonfb_setup(option);
-#endif
- return pci_module_init (&radeonfb_driver);
-}
-
-
-void __exit radeonfb_exit (void)
-{
- pci_unregister_driver (&radeonfb_driver);
-}
-
-int __init radeonfb_setup (char *options)
+static int __init radeonfb_setup (char *options)
{
char *this_opt;
@@ -2540,18 +2535,34 @@ int __init radeonfb_setup (char *options)
}
return 0;
}
+#endif /* MODULE */
-module_init(radeonfb_init);
+static int __init radeonfb_init (void)
+{
+#ifndef MODULE
+ char *option = NULL;
-#ifdef MODULE
-module_exit(radeonfb_exit);
+ if (fb_get_options("radeonfb", &option))
+ return -ENODEV;
+ radeonfb_setup(option);
#endif
+ return pci_register_driver (&radeonfb_driver);
+}
+
+
+static void __exit radeonfb_exit (void)
+{
+ pci_unregister_driver (&radeonfb_driver);
+}
+
+module_init(radeonfb_init);
+module_exit(radeonfb_exit);
MODULE_AUTHOR("Ani Joshi");
MODULE_DESCRIPTION("framebuffer driver for ATI Radeon chipset");
MODULE_LICENSE("GPL");
module_param(noaccel, bool, 0);
-module_param(default_dynclk, int, -2);
+module_param(default_dynclk, int, 0);
MODULE_PARM_DESC(default_dynclk, "int: -2=enable on mobility only,-1=do not change,0=off,1=on");
MODULE_PARM_DESC(noaccel, "bool: disable acceleration");
module_param(nomodeset, bool, 0);
diff --git a/drivers/video/aty/radeon_i2c.c b/drivers/video/aty/radeon_i2c.c
index e87ef153d87bb..762244164c81a 100644
--- a/drivers/video/aty/radeon_i2c.c
+++ b/drivers/video/aty/radeon_i2c.c
@@ -236,6 +236,12 @@ int radeon_probe_i2c_connector(struct radeonfb_info *rinfo, int conn, u8 **out_e
if (edid)
break;
}
+ /* Release the DDC lines when done or the Apple Cinema HD display
+ * will switch off
+ */
+ OUTREG(reg, INREG(reg) & ~(VGA_DDC_CLK_OUT_EN | VGA_DDC_DATA_OUT_EN));
+ (void)INREG(reg);
+
if (out_edid)
*out_edid = edid;
if (!edid) {
diff --git a/drivers/video/aty/radeon_monitor.c b/drivers/video/aty/radeon_monitor.c
index 9094137ccde0a..ea7c863069184 100644
--- a/drivers/video/aty/radeon_monitor.c
+++ b/drivers/video/aty/radeon_monitor.c
@@ -618,11 +618,9 @@ void __devinit radeon_probe_screens(struct radeonfb_info *rinfo,
}
}
if (ignore_edid) {
- if (rinfo->mon1_EDID)
- kfree(rinfo->mon1_EDID);
+ kfree(rinfo->mon1_EDID);
rinfo->mon1_EDID = NULL;
- if (rinfo->mon2_EDID)
- kfree(rinfo->mon2_EDID);
+ kfree(rinfo->mon2_EDID);
rinfo->mon2_EDID = NULL;
}
@@ -655,8 +653,11 @@ static void radeon_fixup_panel_info(struct radeonfb_info *rinfo)
*/
if (!rinfo->panel_info.use_bios_dividers && rinfo->mon1_type == MT_LCD
&& rinfo->is_mobility) {
- int ppll_div_sel = INREG8(CLOCK_CNTL_INDEX + 1) & 0x3;
- u32 ppll_divn = INPLL(PPLL_DIV_0 + ppll_div_sel);
+ int ppll_div_sel;
+ u32 ppll_divn;
+ ppll_div_sel = INREG8(CLOCK_CNTL_INDEX + 1) & 0x3;
+ radeon_pll_errata_after_index(rinfo);
+ ppll_divn = INPLL(PPLL_DIV_0 + ppll_div_sel);
rinfo->panel_info.ref_divider = rinfo->pll.ref_div;
rinfo->panel_info.fbk_divider = ppll_divn & 0x7ff;
rinfo->panel_info.post_divider = (ppll_divn >> 16) & 0x7;
@@ -900,7 +901,7 @@ void __devinit radeon_check_modes(struct radeonfb_info *rinfo, const char *mode_
*/
/*
- * This is used when looking for modes. We assign a "goodness" value
+ * This is used when looking for modes. We assign a "distance" value
* to a mode in the modedb depending how "close" it is from what we
* are looking for.
* Currently, we don't compare that much, we could do better but
@@ -909,13 +910,11 @@ void __devinit radeon_check_modes(struct radeonfb_info *rinfo, const char *mode_
static int radeon_compare_modes(const struct fb_var_screeninfo *var,
const struct fb_videomode *mode)
{
- int goodness = 0;
+ int distance = 0;
- if (var->yres == mode->yres)
- goodness += 10;
- if (var->xres == mode->xres)
- goodness += 9;
- return goodness;
+ distance = mode->yres - var->yres;
+ distance += (mode->xres - var->xres)/2;
+ return distance;
}
/*
@@ -937,7 +936,7 @@ int radeon_match_mode(struct radeonfb_info *rinfo,
const struct fb_videomode *db = vesa_modes;
int i, dbsize = 34;
int has_rmx, native_db = 0;
- int goodness = 0;
+ int distance = INT_MAX;
const struct fb_videomode *candidate = NULL;
/* Start with a copy of the requested mode */
@@ -973,19 +972,19 @@ int radeon_match_mode(struct radeonfb_info *rinfo,
/* Now look for a mode in the database */
while (db) {
for (i = 0; i < dbsize; i++) {
- int g;
+ int d;
if (db[i].yres < src->yres)
continue;
if (db[i].xres < src->xres)
continue;
- g = radeon_compare_modes(src, &db[i]);
+ d = radeon_compare_modes(src, &db[i]);
/* If the new mode is at least as good as the previous one,
* then it's our new candidate
*/
- if (g >= goodness) {
+ if (d < distance) {
candidate = &db[i];
- goodness = g;
+ distance = d;
}
}
db = NULL;
diff --git a/drivers/video/aty/radeon_pm.c b/drivers/video/aty/radeon_pm.c
index 498dc4e520cc4..23c677e5093fd 100644
--- a/drivers/video/aty/radeon_pm.c
+++ b/drivers/video/aty/radeon_pm.c
@@ -27,7 +27,7 @@
#include "ati_ids.h"
-void radeon_pm_disable_dynamic_mode(struct radeonfb_info *rinfo)
+static void radeon_pm_disable_dynamic_mode(struct radeonfb_info *rinfo)
{
u32 tmp;
@@ -229,7 +229,7 @@ void radeon_pm_disable_dynamic_mode(struct radeonfb_info *rinfo)
radeon_msleep(16);
}
-void radeon_pm_enable_dynamic_mode(struct radeonfb_info *rinfo)
+static void radeon_pm_enable_dynamic_mode(struct radeonfb_info *rinfo)
{
u32 tmp;
@@ -1373,7 +1373,9 @@ static void radeon_pm_start_mclk_sclk(struct radeonfb_info *rinfo)
/* Reconfigure SPLL charge pump, VCO gain, duty cycle */
tmp = INPLL(pllSPLL_CNTL);
OUTREG8(CLOCK_CNTL_INDEX, pllSPLL_CNTL + PLL_WR_EN);
+ radeon_pll_errata_after_index(rinfo);
OUTREG8(CLOCK_CNTL_DATA + 1, (tmp >> 8) & 0xff);
+ radeon_pll_errata_after_data(rinfo);
/* Set SPLL feedback divider */
tmp = INPLL(pllM_SPLL_REF_FB_DIV);
@@ -1406,7 +1408,9 @@ static void radeon_pm_start_mclk_sclk(struct radeonfb_info *rinfo)
/* Reconfigure MPLL charge pump, VCO gain, duty cycle */
tmp = INPLL(pllMPLL_CNTL);
OUTREG8(CLOCK_CNTL_INDEX, pllMPLL_CNTL + PLL_WR_EN);
+ radeon_pll_errata_after_index(rinfo);
OUTREG8(CLOCK_CNTL_DATA + 1, (tmp >> 8) & 0xff);
+ radeon_pll_errata_after_data(rinfo);
/* Set MPLL feedback divider */
tmp = INPLL(pllM_SPLL_REF_FB_DIV);
@@ -1525,7 +1529,9 @@ static void radeon_pm_restore_pixel_pll(struct radeonfb_info *rinfo)
u32 tmp;
OUTREG8(CLOCK_CNTL_INDEX, pllHTOTAL_CNTL + PLL_WR_EN);
+ radeon_pll_errata_after_index(rinfo);
OUTREG8(CLOCK_CNTL_DATA, 0);
+ radeon_pll_errata_after_data(rinfo);
tmp = INPLL(pllVCLK_ECP_CNTL);
OUTPLL(pllVCLK_ECP_CNTL, tmp | 0x80);
@@ -1541,11 +1547,9 @@ static void radeon_pm_restore_pixel_pll(struct radeonfb_info *rinfo)
*/
tmp = INPLL(pllPPLL_CNTL);
OUTREG8(CLOCK_CNTL_INDEX, pllSPLL_CNTL + PLL_WR_EN);
+ radeon_pll_errata_after_index(rinfo);
OUTREG8(CLOCK_CNTL_DATA + 1, (tmp >> 8) & 0xff);
-
- /* Not sure what was intended here ... */
- tmp = INREG(CLOCK_CNTL_INDEX);
- OUTREG(CLOCK_CNTL_INDEX, tmp);
+ radeon_pll_errata_after_data(rinfo);
/* Restore our "reference" PPLL divider set by firmware
* according to proper spread spectrum calculations
@@ -1570,6 +1574,8 @@ static void radeon_pm_restore_pixel_pll(struct radeonfb_info *rinfo)
/* Switch pixel clock to firmware default div 0 */
OUTREG8(CLOCK_CNTL_INDEX+1, 0);
+ radeon_pll_errata_after_index(rinfo);
+ radeon_pll_errata_after_data(rinfo);
}
static void radeon_pm_m10_reconfigure_mc(struct radeonfb_info *rinfo)
@@ -2157,7 +2163,9 @@ static void radeon_reinitialize_QW(struct radeonfb_info *rinfo)
tmp = INPLL(MPLL_CNTL);
OUTREG8(CLOCK_CNTL_INDEX, MPLL_CNTL + PLL_WR_EN);
+ radeon_pll_errata_after_index(rinfo);
OUTREG8(CLOCK_CNTL_DATA + 1, (tmp >> 8) & 0xff);
+ radeon_pll_errata_after_data(rinfo);
tmp = INPLL(M_SPLL_REF_FB_DIV);
OUTPLL(M_SPLL_REF_FB_DIV, tmp | 0x5900);
@@ -2178,7 +2186,9 @@ static void radeon_reinitialize_QW(struct radeonfb_info *rinfo)
tmp = INPLL(SPLL_CNTL);
OUTREG8(CLOCK_CNTL_INDEX, SPLL_CNTL + PLL_WR_EN);
+ radeon_pll_errata_after_index(rinfo);
OUTREG8(CLOCK_CNTL_DATA + 1, (tmp >> 8) & 0xff);
+ radeon_pll_errata_after_data(rinfo);
tmp = INPLL(M_SPLL_REF_FB_DIV);
OUTPLL(M_SPLL_REF_FB_DIV, tmp | 0x780000);
@@ -2306,7 +2316,9 @@ static void radeon_reinitialize_QW(struct radeonfb_info *rinfo)
OUTREG(CRTC_H_SYNC_STRT_WID, 0x008e0580);
OUTREG(CRTC_H_TOTAL_DISP, 0x009f00d2);
OUTREG8(CLOCK_CNTL_INDEX, HTOTAL_CNTL + PLL_WR_EN);
+ radeon_pll_errata_after_index(rinfo);
OUTREG8(CLOCK_CNTL_DATA, 0);
+ radeon_pll_errata_after_data(rinfo);
OUTREG(CRTC_V_SYNC_STRT_WID, 0x00830403);
OUTREG(CRTC_V_TOTAL_DISP, 0x03ff0429);
OUTREG(FP_CRTC_H_TOTAL_DISP, 0x009f0033);
@@ -2328,10 +2340,15 @@ static void radeon_reinitialize_QW(struct radeonfb_info *rinfo)
INPLL(PPLL_REF_DIV);
OUTREG8(CLOCK_CNTL_INDEX, PPLL_CNTL + PLL_WR_EN);
+ radeon_pll_errata_after_index(rinfo);
OUTREG8(CLOCK_CNTL_DATA + 1, 0xbc);
+ radeon_pll_errata_after_data(rinfo);
tmp = INREG(CLOCK_CNTL_INDEX);
+ radeon_pll_errata_after_index(rinfo);
OUTREG(CLOCK_CNTL_INDEX, tmp & 0xff);
+ radeon_pll_errata_after_index(rinfo);
+ radeon_pll_errata_after_data(rinfo);
OUTPLL(PPLL_DIV_0, 0x48090);
@@ -2400,7 +2417,8 @@ static void radeon_set_suspend(struct radeonfb_info *rinfo, int suspend)
* including PCI config registers, clocks, AGP conf, ...)
*/
if (suspend) {
- printk(KERN_DEBUG "radeonfb: switching to D2 state...\n");
+ printk(KERN_DEBUG "radeonfb (%s): switching to D2 state...\n",
+ pci_name(rinfo->pdev));
/* Disable dynamic power management of clocks for the
* duration of the suspend/resume process
@@ -2453,7 +2471,8 @@ static void radeon_set_suspend(struct radeonfb_info *rinfo, int suspend)
mdelay(500);
}
} else {
- printk(KERN_DEBUG "radeonfb: switching to D0 state...\n");
+ printk(KERN_DEBUG "radeonfb (%s): switching to D0 state...\n",
+ pci_name(rinfo->pdev));
/* Switch back PCI powermanagment to D0 */
mdelay(200);
@@ -2503,10 +2522,11 @@ static int radeon_restore_pci_cfg(struct radeonfb_info *rinfo)
static/*extern*/ int susdisking = 0;
-int radeonfb_pci_suspend(struct pci_dev *pdev, u32 state)
+int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct fb_info *info = pci_get_drvdata(pdev);
struct radeonfb_info *rinfo = info->par;
+ u8 agp;
int i;
if (state == pdev->dev.power.power_state)
@@ -2523,7 +2543,8 @@ int radeonfb_pci_suspend(struct pci_dev *pdev, u32 state)
if (state != PM_SUSPEND_MEM)
goto done;
if (susdisking) {
- printk("suspending to disk but state = %d\n", state);
+ printk("radeonfb (%s): suspending to disk but state = %d\n",
+ pci_name(pdev), state);
goto done;
}
@@ -2546,6 +2567,28 @@ int radeonfb_pci_suspend(struct pci_dev *pdev, u32 state)
rinfo->lock_blank = 1;
del_timer_sync(&rinfo->lvds_timer);
+ /* Disable AGP. The AGP host should have done it, but since ordering
+ * isn't always properly guaranteed in this specific case, let's make
+ * sure it's disabled on card side now. Ultimately, when merging fbdev
+ * and dri into some common infrastructure, this will be handled
+ * more nicely. The host bridge side will (or will not) be dealt with
+ * by the bridge AGP driver, we don't attempt to touch it here.
+ */
+ agp = pci_find_capability(pdev, PCI_CAP_ID_AGP);
+ if (agp) {
+ u32 cmd;
+
+ pci_read_config_dword(pdev, agp + PCI_AGP_COMMAND, &cmd);
+ if (cmd & PCI_AGP_COMMAND_AGP) {
+ printk(KERN_INFO "radeonfb (%s): AGP was enabled, "
+ "disabling ...\n",
+ pci_name(pdev));
+ cmd &= ~PCI_AGP_COMMAND_AGP;
+ pci_write_config_dword(pdev, agp + PCI_AGP_COMMAND,
+ cmd);
+ }
+ }
+
/* If we support wakeup from poweroff, we save all regs we can including cfg
* space
*/
@@ -2569,12 +2612,11 @@ int radeonfb_pci_suspend(struct pci_dev *pdev, u32 state)
OUTREG(LVDS_PLL_CNTL, (INREG(LVDS_PLL_CNTL) & ~30000) | 0x20000);
mdelay(20);
OUTREG(LVDS_GEN_CNTL, INREG(LVDS_GEN_CNTL) & ~(LVDS_DIGON));
-
- // FIXME: Use PCI layer
- for (i = 0; i < 64; ++i)
- pci_read_config_dword(rinfo->pdev, i * 4,
- &rinfo->cfg_save[i]);
}
+ // FIXME: Use PCI layer
+ for (i = 0; i < 64; ++i)
+ pci_read_config_dword(pdev, i * 4, &rinfo->cfg_save[i]);
+ pci_disable_device(pdev);
}
/* If we support D2, we go to it (should be fixed later with a flag forcing
* D3 only for some laptops)
@@ -2663,7 +2705,7 @@ int radeonfb_pci_resume(struct pci_dev *pdev)
else if (rinfo->dynclk == 0)
radeon_pm_disable_dynamic_mode(rinfo);
- pdev->dev.power.power_state = 0;
+ pdev->dev.power.power_state = PMSG_ON;
bail:
release_console_sem();
@@ -2727,8 +2769,6 @@ void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk)
if (!strcmp(rinfo->of_node->name, "ATY,ViaParent")) {
rinfo->reinit_func = radeon_reinitialize_M9P;
rinfo->pm_mode |= radeon_pm_off;
- /* Workaround not used for now */
- rinfo->m9p_workaround = 1;
}
/* If any of the above is set, we assume the machine can sleep/resume.
diff --git a/drivers/video/aty/radeonfb.h b/drivers/video/aty/radeonfb.h
index a01aa344c99ea..659bc9f62244a 100644
--- a/drivers/video/aty/radeonfb.h
+++ b/drivers/video/aty/radeonfb.h
@@ -22,11 +22,6 @@
#include <video/radeon.h>
-/* Some weird black magic use by Apple driver that we don't use for
- * now --BenH
- */
-#undef HAS_PLL_M9_GPIO_MAGIC
-
/***************************************************************
* Most of the definitions here are adapted right from XFree86 *
***************************************************************/
@@ -82,6 +77,15 @@ enum radeon_chip_flags {
CHIP_HAS_CRTC2 = 0x00040000UL,
};
+/*
+ * Errata workarounds
+ */
+enum radeon_errata {
+ CHIP_ERRATA_R300_CG = 0x00000001,
+ CHIP_ERRATA_PLL_DUMMYREADS = 0x00000002,
+ CHIP_ERRATA_PLL_DELAY = 0x00000004,
+};
+
/*
* Monitor types
@@ -300,6 +304,7 @@ struct radeonfb_info {
int chipset;
u8 family;
u8 rev;
+ unsigned int errata;
unsigned long video_ram;
unsigned long mapped_vram;
int vram_width;
@@ -310,8 +315,6 @@ struct radeonfb_info {
int has_CRTC2;
int is_mobility;
int is_IGP;
- int R300_cg_workaround;
- int m9p_workaround;
int reversed_DAC;
int reversed_TMDS;
struct panel_info panel_info;
@@ -375,6 +378,21 @@ struct radeonfb_info {
* IO macros
*/
+/* Note about this function: we have some rare cases where we must not schedule,
+ * this typically happen with our special "wake up early" hook which allows us to
+ * wake up the graphic chip (and thus get the console back) before everything else
+ * on some machines that support that mecanism. At this point, interrupts are off
+ * and scheduling is not permitted
+ */
+static inline void _radeon_msleep(struct radeonfb_info *rinfo, unsigned long ms)
+{
+ if (rinfo->no_schedule || oops_in_progress)
+ mdelay(ms);
+ else
+ msleep(ms);
+}
+
+
#define INREG8(addr) readb((rinfo->mmio_base)+addr)
#define OUTREG8(addr,val) writeb(val, (rinfo->mmio_base)+addr)
#define INREG(addr) readl((rinfo->mmio_base)+addr)
@@ -396,117 +414,85 @@ static inline void _OUTREGP(struct radeonfb_info *rinfo, u32 addr,
#define OUTREGP(addr,val,mask) _OUTREGP(rinfo, addr, val,mask)
-static inline void R300_cg_workardound(struct radeonfb_info *rinfo)
+/*
+ * Note about PLL register accesses:
+ *
+ * I have removed the spinlock on them on purpose. The driver now
+ * expects that it will only manipulate the PLL registers in normal
+ * task environment, where radeon_msleep() will be called, protected
+ * by a semaphore (currently the console semaphore) so that no conflict
+ * will happen on the PLL register index.
+ *
+ * With the latest changes to the VT layer, this is guaranteed for all
+ * calls except the actual drawing/blits which aren't supposed to use
+ * the PLL registers anyway
+ *
+ * This is very important for the workarounds to work properly. The only
+ * possible exception to this rule is the call to unblank(), which may
+ * be done at irq time if an oops is in progress.
+ */
+static inline void radeon_pll_errata_after_index(struct radeonfb_info *rinfo)
{
- u32 save, tmp;
- save = INREG(CLOCK_CNTL_INDEX);
- tmp = save & ~(0x3f | PLL_WR_EN);
- OUTREG(CLOCK_CNTL_INDEX, tmp);
- tmp = INREG(CLOCK_CNTL_DATA);
- OUTREG(CLOCK_CNTL_INDEX, save);
-}
+ if (!(rinfo->errata & CHIP_ERRATA_PLL_DUMMYREADS))
+ return;
+ (void)INREG(CLOCK_CNTL_DATA);
+ (void)INREG(CRTC_GEN_CNTL);
+}
-static inline u32 __INPLL(struct radeonfb_info *rinfo, u32 addr)
+static inline void radeon_pll_errata_after_data(struct radeonfb_info *rinfo)
{
- u32 data;
-#ifdef HAS_PLL_M9_GPIO_MAGIC
- u32 sv[3];
-
- if (rinfo->m9p_workaround) {
- sv[0] = INREG(0x19c);
- sv[1] = INREG(0x1a0);
- sv[2] = INREG(0x198);
- OUTREG(0x198, 0);
- OUTREG(0x1a0, 0);
- OUTREG(0x19c, 0);
+ if (rinfo->errata & CHIP_ERRATA_PLL_DELAY) {
+ /* we can't deal with posted writes here ... */
+ _radeon_msleep(rinfo, 5);
}
-#endif /* HAS_PLL_M9_GPIO_MAGIC */
-
- OUTREG8(CLOCK_CNTL_INDEX, addr & 0x0000003f);
- data = (INREG(CLOCK_CNTL_DATA));
-
-#ifdef HAS_PLL_M9_GPIO_MAGIC
- if (rinfo->m9p_workaround) {
- (void)INREG(CRTC_GEN_CNTL);
- data = INREG(CLOCK_CNTL_DATA);
- OUTREG(0x19c, sv[0]);
- OUTREG(0x1a0, sv[1]);
- OUTREG(0x198, sv[2]);
+ if (rinfo->errata & CHIP_ERRATA_R300_CG) {
+ u32 save, tmp;
+ save = INREG(CLOCK_CNTL_INDEX);
+ tmp = save & ~(0x3f | PLL_WR_EN);
+ OUTREG(CLOCK_CNTL_INDEX, tmp);
+ tmp = INREG(CLOCK_CNTL_DATA);
+ OUTREG(CLOCK_CNTL_INDEX, save);
}
-#endif /* HAS_PLL_M9_GPIO_MAGIC */
- if (rinfo->R300_cg_workaround)
- R300_cg_workardound(rinfo);
- return data;
}
-static inline u32 _INPLL(struct radeonfb_info *rinfo, u32 addr)
+static inline u32 __INPLL(struct radeonfb_info *rinfo, u32 addr)
{
- unsigned long flags;
u32 data;
- spin_lock_irqsave(&rinfo->reg_lock, flags);
- data = __INPLL(rinfo, addr);
- spin_unlock_irqrestore(&rinfo->reg_lock, flags);
+ OUTREG8(CLOCK_CNTL_INDEX, addr & 0x0000003f);
+ radeon_pll_errata_after_index(rinfo);
+ data = INREG(CLOCK_CNTL_DATA);
+ radeon_pll_errata_after_data(rinfo);
return data;
}
-#define INPLL(addr) _INPLL(rinfo, addr)
-
-
-static inline void __OUTPLL(struct radeonfb_info *rinfo, unsigned int index, u32 val)
+static inline void __OUTPLL(struct radeonfb_info *rinfo, unsigned int index,
+ u32 val)
{
-#ifdef HAS_PLL_M9_GPIO_MAGIC
- u32 sv[3];
-
- if (rinfo->m9p_workaround) {
- sv[0] = INREG(0x19c);
- sv[1] = INREG(0x1a0);
- sv[2] = INREG(0x198);
- OUTREG(0x198, 0);
- OUTREG(0x1a0, 0);
- OUTREG(0x19c, 0);
- mdelay(1);
- }
-#endif /* HAS_PLL_M9_GPIO_MAGIC */
OUTREG8(CLOCK_CNTL_INDEX, (index & 0x0000003f) | 0x00000080);
+ radeon_pll_errata_after_index(rinfo);
OUTREG(CLOCK_CNTL_DATA, val);
-
-#ifdef HAS_PLL_M9_GPIO_MAGIC
- if (rinfo->m9p_workaround) {
- OUTREG(0x19c, sv[0]);
- OUTREG(0x1a0, sv[1]);
- OUTREG(0x198, sv[2]);
- }
-#endif /* HAS_PLL_M9_GPIO_MAGIC */
+ radeon_pll_errata_after_data(rinfo);
}
-static inline void _OUTPLL(struct radeonfb_info *rinfo, unsigned int index, u32 val)
-{
- unsigned long flags;
- spin_lock_irqsave(&rinfo->reg_lock, flags);
- __OUTPLL(rinfo, index, val);
- spin_unlock_irqrestore(&rinfo->reg_lock, flags);
-}
-static inline void _OUTPLLP(struct radeonfb_info *rinfo, unsigned int index,
- u32 val, u32 mask)
+static inline void __OUTPLLP(struct radeonfb_info *rinfo, unsigned int index,
+ u32 val, u32 mask)
{
- unsigned long flags;
unsigned int tmp;
- spin_lock_irqsave(&rinfo->reg_lock, flags);
tmp = __INPLL(rinfo, index);
tmp &= (mask);
tmp |= (val);
__OUTPLL(rinfo, index, tmp);
- spin_unlock_irqrestore(&rinfo->reg_lock, flags);
}
-#define OUTPLL(index, val) _OUTPLL(rinfo, index, val)
-#define OUTPLLP(index, val, mask) _OUTPLLP(rinfo, index, val, mask)
+#define INPLL(addr) __INPLL(rinfo, addr)
+#define OUTPLL(index, val) __OUTPLL(rinfo, index, val)
+#define OUTPLLP(index, val, mask) __OUTPLLP(rinfo, index, val, mask)
#define BIOS_IN8(v) (readb(rinfo->bios_seg + (v)))
@@ -598,20 +584,6 @@ static inline void _radeon_engine_idle(struct radeonfb_info *rinfo)
printk(KERN_ERR "radeonfb: Idle Timeout !\n");
}
-/* Note about this function: we have some rare cases where we must not schedule,
- * this typically happen with our special "wake up early" hook which allows us to
- * wake up the graphic chip (and thus get the console back) before everything else
- * on some machines that support that mecanism. At this point, interrupts are off
- * and scheduling is not permitted
- */
-static inline void _radeon_msleep(struct radeonfb_info *rinfo, unsigned long ms)
-{
- if (rinfo->no_schedule)
- mdelay(ms);
- else
- msleep(ms);
-}
-
#define radeon_engine_idle() _radeon_engine_idle(rinfo)
#define radeon_fifo_wait(entries) _radeon_fifo_wait(rinfo,entries)
@@ -624,7 +596,7 @@ extern void radeon_delete_i2c_busses(struct radeonfb_info *rinfo);
extern int radeon_probe_i2c_connector(struct radeonfb_info *rinfo, int conn, u8 **out_edid);
/* PM Functions */
-extern int radeonfb_pci_suspend(struct pci_dev *pdev, u32 state);
+extern int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t state);
extern int radeonfb_pci_resume(struct pci_dev *pdev);
extern void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk);
extern void radeonfb_pm_exit(struct radeonfb_info *rinfo);
@@ -647,7 +619,6 @@ extern void radeonfb_engine_reset(struct radeonfb_info *rinfo);
/* Other functions */
extern int radeon_screen_blank(struct radeonfb_info *rinfo, int blank, int mode_switch);
-extern void radeon_save_state (struct radeonfb_info *rinfo, struct radeon_regs *save);
extern void radeon_write_mode (struct radeonfb_info *rinfo, struct radeon_regs *mode,
int reg_only);
diff --git a/drivers/video/au1100fb.c b/drivers/video/au1100fb.c
index 1aa9112627ea7..cacd88cc84ab6 100644
--- a/drivers/video/au1100fb.c
+++ b/drivers/video/au1100fb.c
@@ -408,7 +408,7 @@ au1100fb_mmap(struct fb_info *_fb,
/* This is an IO map - tell maydump to skip this VMA */
vma->vm_flags |= VM_IO;
- if (io_remap_page_range(vma, vma->vm_start, off,
+ if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
vma->vm_end - vma->vm_start,
vma->vm_page_prot)) {
return -EAGAIN;
diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c
index 23bd9eedb1465..acc81cb01d566 100644
--- a/drivers/video/backlight/backlight.c
+++ b/drivers/video/backlight/backlight.c
@@ -111,7 +111,7 @@ static void backlight_class_release(struct class_device *dev)
kfree(bd);
}
-struct class backlight_class = {
+static struct class backlight_class = {
.name = "backlight",
.release = backlight_class_release,
};
diff --git a/drivers/video/backlight/corgi_bl.c b/drivers/video/backlight/corgi_bl.c
index b54ec447725d3..3c026b036c86c 100644
--- a/drivers/video/backlight/corgi_bl.c
+++ b/drivers/video/backlight/corgi_bl.c
@@ -52,9 +52,9 @@ static void corgibl_send_intensity(int intensity)
corgi_ssp_blduty_set(intensity & 0x1f);
/* Bit 5 is via SCOOP */
if (intensity & 0x0020)
- set_scoop_gpio(CORGI_SCP_BACKLIGHT_CONT);
+ set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_BACKLIGHT_CONT);
else
- reset_scoop_gpio(CORGI_SCP_BACKLIGHT_CONT);
+ reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_BACKLIGHT_CONT);
spin_unlock_irqrestore(&bl_lock, flags);
}
diff --git a/drivers/video/backlight/lcd.c b/drivers/video/backlight/lcd.c
index 4f298241d9253..470e6f0ee4dd8 100644
--- a/drivers/video/backlight/lcd.c
+++ b/drivers/video/backlight/lcd.c
@@ -111,7 +111,7 @@ static void lcd_class_release(struct class_device *dev)
kfree(ld);
}
-struct class lcd_class = {
+static struct class lcd_class = {
.name = "lcd",
.release = lcd_class_release,
};
diff --git a/drivers/video/cfbcopyarea.c b/drivers/video/cfbcopyarea.c
index b4b286a4cfb12..67711f7b11b14 100644
--- a/drivers/video/cfbcopyarea.c
+++ b/drivers/video/cfbcopyarea.c
@@ -1,25 +1,29 @@
/*
* Generic function for frame buffer with packed pixels of any depth.
*
- * Copyright (C) June 1999 James Simmons
+ * Copyright (C) 1999-2005 James Simmons <jsimmons@www.infradead.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.
*
* NOTES:
- *
- * This is for cfb packed pixels. Iplan and such are incorporated in the
+ *
+ * This is for cfb packed pixels. Iplan and such are incorporated in the
* drivers that need them.
- *
+ *
* FIXME
- * The code for 24 bit is horrible. It copies byte by byte size instead of
- * longs like the other sizes. Needs to be optimized.
*
- * Also need to add code to deal with cards endians that are different than
+ * Also need to add code to deal with cards endians that are different than
* the native cpu endians. I also need to deal with MSB position in the word.
- *
+ *
+ * The two functions or copying forward and backward could be split up like
+ * the ones for filling, i.e. in aligned and unaligned versions. This would
+ * help moving some redundant computations and branches out of the loop, too.
*/
+
+
+
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
@@ -29,58 +33,61 @@
#include <asm/types.h>
#include <asm/io.h>
-#define LONG_MASK (BITS_PER_LONG - 1)
-
#if BITS_PER_LONG == 32
-#define FB_WRITEL fb_writel
-#define FB_READL fb_readl
-#define SHIFT_PER_LONG 5
-#define BYTES_PER_LONG 4
+# define FB_WRITEL fb_writel
+# define FB_READL fb_readl
#else
-#define FB_WRITEL fb_writeq
-#define FB_READL fb_readq
-#define SHIFT_PER_LONG 6
-#define BYTES_PER_LONG 8
+# define FB_WRITEL fb_writeq
+# define FB_READL fb_readq
#endif
-static void bitcpy(unsigned long __iomem *dst, int dst_idx,
- const unsigned long __iomem *src, int src_idx,
- unsigned long n)
+ /*
+ * Compose two values, using a bitmask as decision value
+ * This is equivalent to (a & mask) | (b & ~mask)
+ */
+
+static inline unsigned long
+comp(unsigned long a, unsigned long b, unsigned long mask)
+{
+ return ((a ^ b) & mask) ^ b;
+}
+
+ /*
+ * Generic bitwise copy algorithm
+ */
+
+static void
+bitcpy(unsigned long __iomem *dst, int dst_idx, const unsigned long __iomem *src,
+ int src_idx, int bits, unsigned n)
{
unsigned long first, last;
- int shift = dst_idx-src_idx, left, right;
- unsigned long d0, d1;
- int m;
-
- if (!n)
- return;
-
- shift = dst_idx-src_idx;
+ int const shift = dst_idx-src_idx;
+ int left, right;
+
first = ~0UL >> dst_idx;
- last = ~(~0UL >> ((dst_idx+n) % BITS_PER_LONG));
-
+ last = ~(~0UL >> ((dst_idx+n) % bits));
+
if (!shift) {
// Same alignment for source and dest
-
- if (dst_idx+n <= BITS_PER_LONG) {
+
+ if (dst_idx+n <= bits) {
// Single word
if (last)
first &= last;
- FB_WRITEL((FB_READL(src) & first) | (FB_READL(dst) & ~first), dst);
+ FB_WRITEL( comp( FB_READL(src), FB_READL(dst), first), dst);
} else {
// Multiple destination words
+
// Leading bits
- if (first) {
-
- FB_WRITEL((FB_READL(src) & first) |
- (FB_READL(dst) & ~first), dst);
+ if (first != ~0UL) {
+ FB_WRITEL( comp( FB_READL(src), FB_READL(dst), first), dst);
dst++;
src++;
- n -= BITS_PER_LONG-dst_idx;
+ n -= bits - dst_idx;
}
-
+
// Main chunk
- n /= BITS_PER_LONG;
+ n /= bits;
while (n >= 8) {
FB_WRITEL(FB_READL(src++), dst++);
FB_WRITEL(FB_READL(src++), dst++);
@@ -94,58 +101,61 @@ static void bitcpy(unsigned long __iomem *dst, int dst_idx,
}
while (n--)
FB_WRITEL(FB_READL(src++), dst++);
+
// Trailing bits
if (last)
- FB_WRITEL((FB_READL(src) & last) | (FB_READL(dst) & ~last), dst);
+ FB_WRITEL( comp( FB_READL(src), FB_READL(dst), last), dst);
}
} else {
+ unsigned long d0, d1;
+ int m;
// Different alignment for source and dest
-
- right = shift & (BITS_PER_LONG-1);
- left = -shift & (BITS_PER_LONG-1);
-
- if (dst_idx+n <= BITS_PER_LONG) {
+
+ right = shift & (bits - 1);
+ left = -shift & (bits - 1);
+
+ if (dst_idx+n <= bits) {
// Single destination word
if (last)
first &= last;
if (shift > 0) {
// Single source word
- FB_WRITEL(((FB_READL(src) >> right) & first) |
- (FB_READL(dst) & ~first), dst);
- } else if (src_idx+n <= BITS_PER_LONG) {
+ FB_WRITEL( comp( FB_READL(src) >> right, FB_READL(dst), first), dst);
+ } else if (src_idx+n <= bits) {
// Single source word
- FB_WRITEL(((FB_READL(src) << left) & first) |
- (FB_READL(dst) & ~first), dst);
+ FB_WRITEL( comp(FB_READL(src) << left, FB_READL(dst), first), dst);
} else {
// 2 source words
d0 = FB_READL(src++);
d1 = FB_READL(src);
- FB_WRITEL(((d0<<left | d1>>right) & first) |
- (FB_READL(dst) & ~first), dst);
+ FB_WRITEL( comp(d0<<left | d1>>right, FB_READL(dst), first), dst);
}
} else {
// Multiple destination words
+ /** We must always remember the last value read, because in case
+ SRC and DST overlap bitwise (e.g. when moving just one pixel in
+ 1bpp), we always collect one full long for DST and that might
+ overlap with the current long from SRC. We store this value in
+ 'd0'. */
d0 = FB_READL(src++);
// Leading bits
if (shift > 0) {
// Single source word
- FB_WRITEL(((d0 >> right) & first) |
- (FB_READL(dst) & ~first), dst);
+ FB_WRITEL( comp(d0 >> right, FB_READL(dst), first), dst);
dst++;
- n -= BITS_PER_LONG-dst_idx;
+ n -= bits - dst_idx;
} else {
// 2 source words
d1 = FB_READL(src++);
- FB_WRITEL(((d0<<left | d1>>right) & first) |
- (FB_READL(dst) & ~first), dst);
+ FB_WRITEL( comp(d0<<left | d1>>right, FB_READL(dst), first), dst);
d0 = d1;
dst++;
- n -= BITS_PER_LONG-dst_idx;
+ n -= bits - dst_idx;
}
-
+
// Main chunk
- m = n % BITS_PER_LONG;
- n /= BITS_PER_LONG;
+ m = n % bits;
+ n /= bits;
while (n >= 4) {
d1 = FB_READL(src++);
FB_WRITEL(d0 << left | d1 >> right, dst++);
@@ -166,72 +176,70 @@ static void bitcpy(unsigned long __iomem *dst, int dst_idx,
FB_WRITEL(d0 << left | d1 >> right, dst++);
d0 = d1;
}
-
+
// Trailing bits
if (last) {
if (m <= right) {
// Single source word
- FB_WRITEL(((d0 << left) & last) |
- (FB_READL(dst) & ~last),
- dst);
+ FB_WRITEL( comp(d0 << left, FB_READL(dst), last), dst);
} else {
// 2 source words
d1 = FB_READL(src);
- FB_WRITEL(((d0<<left | d1>>right) &
- last) | (FB_READL(dst) &
- ~last), dst);
+ FB_WRITEL( comp(d0<<left | d1>>right, FB_READL(dst), last), dst);
}
}
}
}
}
-static void bitcpy_rev(unsigned long __iomem *dst, int dst_idx,
- const unsigned long __iomem *src, int src_idx, unsigned long n)
+ /*
+ * Generic bitwise copy algorithm, operating backward
+ */
+
+static void
+bitcpy_rev(unsigned long __iomem *dst, int dst_idx, const unsigned long __iomem *src,
+ int src_idx, int bits, unsigned n)
{
unsigned long first, last;
- int shift = dst_idx-src_idx, left, right;
- unsigned long d0, d1;
- int m;
-
- if (!n)
- return;
-
- dst += (n-1)/BITS_PER_LONG;
- src += (n-1)/BITS_PER_LONG;
- if ((n-1) % BITS_PER_LONG) {
- dst_idx += (n-1) % BITS_PER_LONG;
- dst += dst_idx >> SHIFT_PER_LONG;
- dst_idx &= BITS_PER_LONG-1;
- src_idx += (n-1) % BITS_PER_LONG;
- src += src_idx >> SHIFT_PER_LONG;
- src_idx &= BITS_PER_LONG-1;
+ int shift;
+
+ dst += (n-1)/bits;
+ src += (n-1)/bits;
+ if ((n-1) % bits) {
+ dst_idx += (n-1) % bits;
+ dst += dst_idx >> (ffs(bits) - 1);
+ dst_idx &= bits - 1;
+ src_idx += (n-1) % bits;
+ src += src_idx >> (ffs(bits) - 1);
+ src_idx &= bits - 1;
}
-
+
shift = dst_idx-src_idx;
- first = ~0UL << (BITS_PER_LONG-1-dst_idx);
- last = ~(~0UL << (BITS_PER_LONG-1-((dst_idx-n) % BITS_PER_LONG)));
-
+
+ first = ~0UL << (bits - 1 - dst_idx);
+ last = ~(~0UL << (bits - 1 - ((dst_idx-n) % bits)));
+
if (!shift) {
// Same alignment for source and dest
-
+
if ((unsigned long)dst_idx+1 >= n) {
// Single word
if (last)
first &= last;
- FB_WRITEL((FB_READL(src) & first) | (FB_READL(dst) & ~first), dst);
+ FB_WRITEL( comp( FB_READL(src), FB_READL(dst), first), dst);
} else {
// Multiple destination words
+
// Leading bits
- if (first) {
- FB_WRITEL((FB_READL(src) & first) | (FB_READL(dst) & ~first), dst);
+ if (first != ~0UL) {
+ FB_WRITEL( comp( FB_READL(src), FB_READL(dst), first), dst);
dst--;
src--;
n -= dst_idx+1;
}
-
+
// Main chunk
- n /= BITS_PER_LONG;
+ n /= bits;
while (n >= 8) {
FB_WRITEL(FB_READL(src--), dst--);
FB_WRITEL(FB_READL(src--), dst--);
@@ -245,59 +253,58 @@ static void bitcpy_rev(unsigned long __iomem *dst, int dst_idx,
}
while (n--)
FB_WRITEL(FB_READL(src--), dst--);
-
+
// Trailing bits
if (last)
- FB_WRITEL((FB_READL(src) & last) | (FB_READL(dst) & ~last), dst);
+ FB_WRITEL( comp( FB_READL(src), FB_READL(dst), last), dst);
}
} else {
// Different alignment for source and dest
-
- right = shift & (BITS_PER_LONG-1);
- left = -shift & (BITS_PER_LONG-1);
-
+
+ int const left = -shift & (bits-1);
+ int const right = shift & (bits-1);
+
if ((unsigned long)dst_idx+1 >= n) {
// Single destination word
if (last)
first &= last;
if (shift < 0) {
// Single source word
- FB_WRITEL((FB_READL(src) << left & first) |
- (FB_READL(dst) & ~first), dst);
+ FB_WRITEL( comp( FB_READL(src)<<left, FB_READL(dst), first), dst);
} else if (1+(unsigned long)src_idx >= n) {
// Single source word
- FB_WRITEL(((FB_READL(src) >> right) & first) |
- (FB_READL(dst) & ~first), dst);
+ FB_WRITEL( comp( FB_READL(src)>>right, FB_READL(dst), first), dst);
} else {
// 2 source words
- d0 = FB_READL(src--);
- d1 = FB_READL(src);
- FB_WRITEL(((d0>>right | d1<<left) & first) |
- (FB_READL(dst) & ~first), dst);
+ FB_WRITEL( comp( (FB_READL(src)>>right | FB_READL(src-1)<<left), FB_READL(dst), first), dst);
}
} else {
// Multiple destination words
+ /** We must always remember the last value read, because in case
+ SRC and DST overlap bitwise (e.g. when moving just one pixel in
+ 1bpp), we always collect one full long for DST and that might
+ overlap with the current long from SRC. We store this value in
+ 'd0'. */
+ unsigned long d0, d1;
+ int m;
+
d0 = FB_READL(src--);
// Leading bits
if (shift < 0) {
// Single source word
- FB_WRITEL(((d0 << left) & first) |
- (FB_READL(dst) & ~first), dst);
- dst--;
- n -= dst_idx+1;
+ FB_WRITEL( comp( (d0 << left), FB_READL(dst), first), dst);
} else {
// 2 source words
d1 = FB_READL(src--);
- FB_WRITEL(((d0>>right | d1<<left) & first) |
- (FB_READL(dst) & ~first), dst);
+ FB_WRITEL( comp( (d0>>right | d1<<left), FB_READL(dst), first), dst);
d0 = d1;
- dst--;
- n -= dst_idx+1;
}
-
+ dst--;
+ n -= dst_idx+1;
+
// Main chunk
- m = n % BITS_PER_LONG;
- n /= BITS_PER_LONG;
+ m = n % bits;
+ n /= bits;
while (n >= 4) {
d1 = FB_READL(src--);
FB_WRITEL(d0 >> right | d1 << left, dst--);
@@ -318,20 +325,16 @@ static void bitcpy_rev(unsigned long __iomem *dst, int dst_idx,
FB_WRITEL(d0 >> right | d1 << left, dst--);
d0 = d1;
}
-
+
// Trailing bits
if (last) {
if (m <= left) {
// Single source word
- FB_WRITEL(((d0 >> right) & last) |
- (FB_READL(dst) & ~last),
- dst);
+ FB_WRITEL( comp(d0 >> right, FB_READL(dst), last), dst);
} else {
// 2 source words
d1 = FB_READL(src);
- FB_WRITEL(((d0>>right | d1<<left) &
- last) | (FB_READL(dst) &
- ~last), dst);
+ FB_WRITEL( comp(d0>>right | d1<<left, FB_READL(dst), last), dst);
}
}
}
@@ -342,30 +345,27 @@ void cfb_copyarea(struct fb_info *p, const struct fb_copyarea *area)
{
u32 dx = area->dx, dy = area->dy, sx = area->sx, sy = area->sy;
u32 height = area->height, width = area->width;
- int x2, y2, old_dx, old_dy, vxres, vyres;
- unsigned long next_line = p->fix.line_length;
- int dst_idx = 0, src_idx = 0, rev_copy = 0;
+ unsigned long const bits_per_line = p->fix.line_length*8u;
unsigned long __iomem *dst = NULL, *src = NULL;
+ int bits = BITS_PER_LONG, bytes = bits >> 3;
+ int dst_idx = 0, src_idx = 0, rev_copy = 0;
+ int x2, y2, vxres, vyres;
if (p->state != FBINFO_STATE_RUNNING)
return;
/* We want rotation but lack hardware to do it for us. */
if (!p->fbops->fb_rotate && p->var.rotate) {
- }
-
+ }
+
vxres = p->var.xres_virtual;
vyres = p->var.yres_virtual;
- if (area->dx > vxres || area->sx > vxres ||
+ if (area->dx > vxres || area->sx > vxres ||
area->dy > vyres || area->sy > vyres)
return;
- /* clip the destination */
- old_dx = area->dx;
- old_dy = area->dy;
-
- /*
+ /* clip the destination
* We could use hardware clipping but on many cards you get around
* hardware clipping by writing to framebuffer directly.
*/
@@ -378,53 +378,58 @@ void cfb_copyarea(struct fb_info *p, const struct fb_copyarea *area)
width = x2 - dx;
height = y2 - dy;
+ if ((width==0) ||(height==0))
+ return;
+
/* update sx1,sy1 */
- sx += (dx - old_dx);
- sy += (dy - old_dy);
+ sx += (dx - area->dx);
+ sy += (dy - area->dy);
/* the source must be completely inside the virtual screen */
- if (sx < 0 || sy < 0 ||
- (sx + width) > vxres ||
- (sy + height) > vyres)
+ if (sx < 0 || sy < 0 || (sx + width) > vxres || (sy + height) > vyres)
return;
- if ((dy == sy && dx > sx) ||
- (dy > sy)) {
+ /* if the beginning of the target area might overlap with the end of
+ the source area, be have to copy the area reverse. */
+ if ((dy == sy && dx > sx) || (dy > sy)) {
dy += height;
sy += height;
rev_copy = 1;
}
- dst = src = (unsigned long __iomem *)((unsigned long)p->screen_base &
- ~(BYTES_PER_LONG-1));
- dst_idx = src_idx = (unsigned long)p->screen_base & (BYTES_PER_LONG-1);
- dst_idx += dy*next_line*8 + dx*p->var.bits_per_pixel;
- src_idx += sy*next_line*8 + sx*p->var.bits_per_pixel;
-
+ // split the base of the framebuffer into a long-aligned address and the
+ // index of the first bit
+ dst = src = (unsigned long __iomem *)((unsigned long)p->screen_base & ~(bytes-1));
+ dst_idx = src_idx = 8*((unsigned long)p->screen_base & (bytes-1));
+ // add offset of source and target area
+ dst_idx += dy*bits_per_line + dx*p->var.bits_per_pixel;
+ src_idx += sy*bits_per_line + sx*p->var.bits_per_pixel;
+
if (p->fbops->fb_sync)
p->fbops->fb_sync(p);
+
if (rev_copy) {
while (height--) {
- dst_idx -= next_line*8;
- src_idx -= next_line*8;
- dst += dst_idx >> SHIFT_PER_LONG;
- dst_idx &= (BYTES_PER_LONG-1);
- src += src_idx >> SHIFT_PER_LONG;
- src_idx &= (BYTES_PER_LONG-1);
- bitcpy_rev(dst, dst_idx, src, src_idx,
- width*p->var.bits_per_pixel);
- }
+ dst_idx -= bits_per_line;
+ src_idx -= bits_per_line;
+ dst += dst_idx >> (ffs(bits) - 1);
+ dst_idx &= (bytes - 1);
+ src += src_idx >> (ffs(bits) - 1);
+ src_idx &= (bytes - 1);
+ bitcpy_rev(dst, dst_idx, src, src_idx, bits,
+ width*p->var.bits_per_pixel);
+ }
} else {
while (height--) {
- dst += dst_idx >> SHIFT_PER_LONG;
- dst_idx &= (BYTES_PER_LONG-1);
- src += src_idx >> SHIFT_PER_LONG;
- src_idx &= (BYTES_PER_LONG-1);
- bitcpy(dst, dst_idx, src, src_idx,
- width*p->var.bits_per_pixel);
- dst_idx += next_line*8;
- src_idx += next_line*8;
- }
+ dst += dst_idx >> (ffs(bits) - 1);
+ dst_idx &= (bytes - 1);
+ src += src_idx >> (ffs(bits) - 1);
+ src_idx &= (bytes - 1);
+ bitcpy(dst, dst_idx, src, src_idx, bits,
+ width*p->var.bits_per_pixel);
+ dst_idx += bits_per_line;
+ src_idx += bits_per_line;
+ }
}
}
diff --git a/drivers/video/cfbfillrect.c b/drivers/video/cfbfillrect.c
index 4a94bf85e79e6..e4fc42b013ebd 100644
--- a/drivers/video/cfbfillrect.c
+++ b/drivers/video/cfbfillrect.c
@@ -1,7 +1,7 @@
/*
- * Generic fillrect for frame buffers with packed pixels of any depth.
+ * Generic fillrect for frame buffers with packed pixels of any depth.
*
- * Copyright (C) 2000 James Simmons (jsimmons@linux-fbdev.org)
+ * Copyright (C) 2000 James Simmons (jsimmons@linux-fbdev.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
@@ -9,8 +9,8 @@
*
* NOTES:
*
- * The code for depths like 24 that don't have integer number of pixels per
- * long is broken and needs to be fixed. For now I turned these types of
+ * The code for depths like 24 that don't have integer number of pixels per
+ * long is broken and needs to be fixed. For now I turned these types of
* mode off.
*
* Also need to add code to deal with cards endians that are different than
@@ -24,149 +24,129 @@
#include <asm/types.h>
#if BITS_PER_LONG == 32
-#define FB_WRITEL fb_writel
-#define FB_READL fb_readl
-#define BYTES_PER_LONG 4
-#define SHIFT_PER_LONG 5
+# define FB_WRITEL fb_writel
+# define FB_READL fb_readl
#else
-#define FB_WRITEL fb_writeq
-#define FB_READL fb_readq
-#define BYTES_PER_LONG 8
-#define SHIFT_PER_LONG 6
+# define FB_WRITEL fb_writeq
+# define FB_READL fb_readq
#endif
-#define EXP1(x) 0xffffffffU*x
-#define EXP2(x) 0x55555555U*x
-#define EXP4(x) 0x11111111U*0x ## x
-
-typedef u32 pixel_t;
-
-static const u32 bpp1tab[2] = {
- EXP1(0), EXP1(1)
-};
-
-static const u32 bpp2tab[4] = {
- EXP2(0), EXP2(1), EXP2(2), EXP2(3)
-};
-
-static const u32 bpp4tab[16] = {
- EXP4(0), EXP4(1), EXP4(2), EXP4(3), EXP4(4), EXP4(5), EXP4(6), EXP4(7),
- EXP4(8), EXP4(9), EXP4(a), EXP4(b), EXP4(c), EXP4(d), EXP4(e), EXP4(f)
-};
-
/*
* Compose two values, using a bitmask as decision value
* This is equivalent to (a & mask) | (b & ~mask)
*/
-static inline unsigned long comp(unsigned long a, unsigned long b,
- unsigned long mask)
+static inline unsigned long
+comp(unsigned long a, unsigned long b, unsigned long mask)
{
return ((a ^ b) & mask) ^ b;
}
-static inline u32 pixel_to_pat32(const struct fb_info *p, pixel_t pixel)
-{
- u32 pat = pixel;
+ /*
+ * Create a pattern with the given pixel's color
+ */
- switch (p->var.bits_per_pixel) {
+#if BITS_PER_LONG == 64
+static inline unsigned long
+pixel_to_pat( u32 bpp, u32 pixel)
+{
+ switch (bpp) {
case 1:
- pat = bpp1tab[pat];
- break;
-
+ return 0xfffffffffffffffful*pixel;
case 2:
- pat = bpp2tab[pat];
- break;
-
+ return 0x5555555555555555ul*pixel;
case 4:
- pat = bpp4tab[pat];
- break;
-
+ return 0x1111111111111111ul*pixel;
case 8:
- pat |= pat << 8;
- // Fall through
+ return 0x0101010101010101ul*pixel;
+ case 12:
+ return 0x0001001001001001ul*pixel;
case 16:
- pat |= pat << 16;
- // Fall through
+ return 0x0001000100010001ul*pixel;
+ case 24:
+ return 0x0000000001000001ul*pixel;
case 32:
- break;
+ return 0x0000000100000001ul*pixel;
+ default:
+ panic("pixel_to_pat(): unsupported pixelformat\n");
}
- return pat;
}
-
- /*
- * Expand a pixel value to a generic 32/64-bit pattern and rotate it to
- * the correct start position
- */
-
-static inline unsigned long pixel_to_pat(const struct fb_info *p,
- pixel_t pixel, int left)
+#else
+static inline unsigned long
+pixel_to_pat( u32 bpp, u32 pixel)
{
- unsigned long pat = pixel;
- u32 bpp = p->var.bits_per_pixel;
- int i;
-
- /* expand pixel value */
- for (i = bpp; i < BITS_PER_LONG; i *= 2)
- pat |= pat << i;
-
- /* rotate pattern to correct start position */
- pat = pat << left | pat >> (bpp-left);
- return pat;
+ switch (bpp) {
+ case 1:
+ return 0xfffffffful*pixel;
+ case 2:
+ return 0x55555555ul*pixel;
+ case 4:
+ return 0x11111111ul*pixel;
+ case 8:
+ return 0x01010101ul*pixel;
+ case 12:
+ return 0x00001001ul*pixel;
+ case 16:
+ return 0x00010001ul*pixel;
+ case 24:
+ return 0x00000001ul*pixel;
+ case 32:
+ return 0x00000001ul*pixel;
+ default:
+ panic("pixel_to_pat(): unsupported pixelformat\n");
+ }
}
+#endif
/*
- * Unaligned 32-bit pattern fill using 32/64-bit memory accesses
+ * Aligned pattern fill using 32/64-bit memory accesses
*/
-void bitfill32(unsigned long __iomem *dst, int dst_idx, u32 pat, u32 n)
+static void
+bitfill_aligned(unsigned long __iomem *dst, int dst_idx, unsigned long pat, unsigned n, int bits)
{
- unsigned long val = pat;
unsigned long first, last;
-
+
if (!n)
return;
-
-#if BITS_PER_LONG == 64
- val |= val << 32;
-#endif
-
+
first = ~0UL >> dst_idx;
- last = ~(~0UL >> ((dst_idx+n) % BITS_PER_LONG));
-
- if (dst_idx+n <= BITS_PER_LONG) {
+ last = ~(~0UL >> ((dst_idx+n) % bits));
+
+ if (dst_idx+n <= bits) {
// Single word
if (last)
first &= last;
- FB_WRITEL(comp(val, FB_READL(dst), first), dst);
+ FB_WRITEL(comp(pat, FB_READL(dst), first), dst);
} else {
// Multiple destination words
+
// Leading bits
- if (first) {
- FB_WRITEL(comp(val, FB_READL(dst), first), dst);
+ if (first!= ~0UL) {
+ FB_WRITEL(comp(pat, FB_READL(dst), first), dst);
dst++;
- n -= BITS_PER_LONG-dst_idx;
+ n -= bits - dst_idx;
}
-
+
// Main chunk
- n /= BITS_PER_LONG;
+ n /= bits;
while (n >= 8) {
- FB_WRITEL(val, dst++);
- FB_WRITEL(val, dst++);
- FB_WRITEL(val, dst++);
- FB_WRITEL(val, dst++);
- FB_WRITEL(val, dst++);
- FB_WRITEL(val, dst++);
- FB_WRITEL(val, dst++);
- FB_WRITEL(val, dst++);
+ FB_WRITEL(pat, dst++);
+ FB_WRITEL(pat, dst++);
+ FB_WRITEL(pat, dst++);
+ FB_WRITEL(pat, dst++);
+ FB_WRITEL(pat, dst++);
+ FB_WRITEL(pat, dst++);
+ FB_WRITEL(pat, dst++);
+ FB_WRITEL(pat, dst++);
n -= 8;
}
while (n--)
- FB_WRITEL(val, dst++);
-
+ FB_WRITEL(pat, dst++);
+
// Trailing bits
if (last)
- FB_WRITEL(comp(val, FB_READL(dst), first), dst);
+ FB_WRITEL(comp(pat, FB_READL(dst), last), dst);
}
}
@@ -178,18 +158,19 @@ void bitfill32(unsigned long __iomem *dst, int dst_idx, u32 pat, u32 n)
* used for the next 32/64-bit word
*/
-void bitfill(unsigned long __iomem *dst, int dst_idx, unsigned long pat, int left,
- int right, u32 n)
+static void
+bitfill_unaligned(unsigned long __iomem *dst, int dst_idx, unsigned long pat,
+ int left, int right, unsigned n, int bits)
{
unsigned long first, last;
if (!n)
return;
-
+
first = ~0UL >> dst_idx;
- last = ~(~0UL >> ((dst_idx+n) % BITS_PER_LONG));
-
- if (dst_idx+n <= BITS_PER_LONG) {
+ last = ~(~0UL >> ((dst_idx+n) % bits));
+
+ if (dst_idx+n <= bits) {
// Single word
if (last)
first &= last;
@@ -201,11 +182,11 @@ void bitfill(unsigned long __iomem *dst, int dst_idx, unsigned long pat, int lef
FB_WRITEL(comp(pat, FB_READL(dst), first), dst);
dst++;
pat = pat << left | pat >> right;
- n -= BITS_PER_LONG-dst_idx;
+ n -= bits - dst_idx;
}
-
+
// Main chunk
- n /= BITS_PER_LONG;
+ n /= bits;
while (n >= 4) {
FB_WRITEL(pat, dst++);
pat = pat << left | pat >> right;
@@ -221,29 +202,29 @@ void bitfill(unsigned long __iomem *dst, int dst_idx, unsigned long pat, int lef
FB_WRITEL(pat, dst++);
pat = pat << left | pat >> right;
}
-
+
// Trailing bits
if (last)
FB_WRITEL(comp(pat, FB_READL(dst), first), dst);
}
}
-void bitfill32_rev(unsigned long __iomem *dst, int dst_idx, u32 pat, u32 n)
+ /*
+ * Aligned pattern invert using 32/64-bit memory accesses
+ */
+static void
+bitfill_aligned_rev(unsigned long __iomem *dst, int dst_idx, unsigned long pat, unsigned n, int bits)
{
unsigned long val = pat, dat;
unsigned long first, last;
-
+
if (!n)
return;
-
-#if BITS_PER_LONG == 64
- val |= val << 32;
-#endif
-
+
first = ~0UL >> dst_idx;
- last = ~(~0UL >> ((dst_idx+n) % BITS_PER_LONG));
-
- if (dst_idx+n <= BITS_PER_LONG) {
+ last = ~(~0UL >> ((dst_idx+n) % bits));
+
+ if (dst_idx+n <= bits) {
// Single word
if (last)
first &= last;
@@ -252,15 +233,15 @@ void bitfill32_rev(unsigned long __iomem *dst, int dst_idx, u32 pat, u32 n)
} else {
// Multiple destination words
// Leading bits
- if (first) {
+ if (first!=0UL) {
dat = FB_READL(dst);
FB_WRITEL(comp(dat ^ val, dat, first), dst);
dst++;
- n -= BITS_PER_LONG-dst_idx;
+ n -= bits - dst_idx;
}
-
+
// Main chunk
- n /= BITS_PER_LONG;
+ n /= bits;
while (n >= 8) {
FB_WRITEL(FB_READL(dst) ^ val, dst);
dst++;
@@ -283,35 +264,36 @@ void bitfill32_rev(unsigned long __iomem *dst, int dst_idx, u32 pat, u32 n)
while (n--) {
FB_WRITEL(FB_READL(dst) ^ val, dst);
dst++;
- }
+ }
// Trailing bits
if (last) {
dat = FB_READL(dst);
- FB_WRITEL(comp(dat ^ val, dat, first), dst);
+ FB_WRITEL(comp(dat ^ val, dat, last), dst);
}
}
}
/*
- * Unaligned generic pattern fill using 32/64-bit memory accesses
+ * Unaligned generic pattern invert using 32/64-bit memory accesses
* The pattern must have been expanded to a full 32/64-bit value
* Left/right are the appropriate shifts to convert to the pattern to be
* used for the next 32/64-bit word
*/
-void bitfill_rev(unsigned long __iomem *dst, int dst_idx, unsigned long pat, int left,
- int right, u32 n)
+static void
+bitfill_unaligned_rev(unsigned long __iomem *dst, int dst_idx, unsigned long pat,
+ int left, int right, unsigned n, int bits)
{
unsigned long first, last, dat;
if (!n)
return;
-
+
first = ~0UL >> dst_idx;
- last = ~(~0UL >> ((dst_idx+n) % BITS_PER_LONG));
-
- if (dst_idx+n <= BITS_PER_LONG) {
+ last = ~(~0UL >> ((dst_idx+n) % bits));
+
+ if (dst_idx+n <= bits) {
// Single word
if (last)
first &= last;
@@ -319,17 +301,18 @@ void bitfill_rev(unsigned long __iomem *dst, int dst_idx, unsigned long pat, int
FB_WRITEL(comp(dat ^ pat, dat, first), dst);
} else {
// Multiple destination words
+
// Leading bits
- if (first) {
+ if (first != 0UL) {
dat = FB_READL(dst);
FB_WRITEL(comp(dat ^ pat, dat, first), dst);
dst++;
pat = pat << left | pat >> right;
- n -= BITS_PER_LONG-dst_idx;
+ n -= bits - dst_idx;
}
-
+
// Main chunk
- n /= BITS_PER_LONG;
+ n /= bits;
while (n >= 4) {
FB_WRITEL(FB_READL(dst) ^ pat, dst);
dst++;
@@ -350,20 +333,20 @@ void bitfill_rev(unsigned long __iomem *dst, int dst_idx, unsigned long pat, int
dst++;
pat = pat << left | pat >> right;
}
-
+
// Trailing bits
if (last) {
dat = FB_READL(dst);
- FB_WRITEL(comp(dat ^ pat, dat, first), dst);
+ FB_WRITEL(comp(dat ^ pat, dat, last), dst);
}
}
}
void cfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
{
+ unsigned long x2, y2, vxres, vyres, height, width, pat, fg;
+ int bits = BITS_PER_LONG, bytes = bits >> 3;
u32 bpp = p->var.bits_per_pixel;
- unsigned long x2, y2, vxres, vyres;
- unsigned long height, width, fg;
unsigned long __iomem *dst;
int dst_idx, left;
@@ -372,81 +355,91 @@ void cfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
/* We want rotation but lack hardware to do it for us. */
if (!p->fbops->fb_rotate && p->var.rotate) {
- }
-
+ }
+
vxres = p->var.xres_virtual;
vyres = p->var.yres_virtual;
- if (!rect->width || !rect->height ||
+ if (!rect->width || !rect->height ||
rect->dx > vxres || rect->dy > vyres)
return;
/* We could use hardware clipping but on many cards you get around
* hardware clipping by writing to framebuffer directly. */
-
+
x2 = rect->dx + rect->width;
y2 = rect->dy + rect->height;
x2 = x2 < vxres ? x2 : vxres;
y2 = y2 < vyres ? y2 : vyres;
width = x2 - rect->dx;
height = y2 - rect->dy;
-
+
if (p->fix.visual == FB_VISUAL_TRUECOLOR ||
p->fix.visual == FB_VISUAL_DIRECTCOLOR )
fg = ((u32 *) (p->pseudo_palette))[rect->color];
else
fg = rect->color;
-
- dst = (unsigned long __iomem *)((unsigned long)p->screen_base &
- ~(BYTES_PER_LONG-1));
- dst_idx = ((unsigned long)p->screen_base & (BYTES_PER_LONG-1))*8;
+
+ pat = pixel_to_pat( bpp, fg);
+
+ dst = (unsigned long __iomem *)((unsigned long)p->screen_base & ~(bytes-1));
+ dst_idx = ((unsigned long)p->screen_base & (bytes - 1))*8;
dst_idx += rect->dy*p->fix.line_length*8+rect->dx*bpp;
/* FIXME For now we support 1-32 bpp only */
- left = BITS_PER_LONG % bpp;
+ left = bits % bpp;
if (p->fbops->fb_sync)
p->fbops->fb_sync(p);
if (!left) {
- u32 pat = pixel_to_pat32(p, fg);
- void (*fill_op32)(unsigned long __iomem *dst, int dst_idx, u32 pat,
- u32 n) = NULL;
-
+ void (*fill_op32)(unsigned long __iomem *dst, int dst_idx,
+ unsigned long pat, unsigned n, int bits) = NULL;
+
switch (rect->rop) {
case ROP_XOR:
- fill_op32 = bitfill32_rev;
+ fill_op32 = bitfill_aligned_rev;
break;
case ROP_COPY:
+ fill_op32 = bitfill_aligned;
+ break;
default:
- fill_op32 = bitfill32;
+ printk( KERN_ERR "cfb_fillrect(): unknown rop, defaulting to ROP_COPY\n");
+ fill_op32 = bitfill_aligned;
break;
}
while (height--) {
- dst += dst_idx >> SHIFT_PER_LONG;
- dst_idx &= (BITS_PER_LONG-1);
- fill_op32(dst, dst_idx, pat, width*bpp);
+ dst += dst_idx >> (ffs(bits) - 1);
+ dst_idx &= (bits - 1);
+ fill_op32(dst, dst_idx, pat, width*bpp, bits);
dst_idx += p->fix.line_length*8;
}
} else {
- unsigned long pat = pixel_to_pat(p, fg, (left-dst_idx) % bpp);
- int right = bpp-left;
+ int right;
int r;
- void (*fill_op)(unsigned long __iomem *dst, int dst_idx,
- unsigned long pat, int left, int right,
- u32 n) = NULL;
-
+ int rot = (left-dst_idx) % bpp;
+ void (*fill_op)(unsigned long __iomem *dst, int dst_idx,
+ unsigned long pat, int left, int right,
+ unsigned n, int bits) = NULL;
+
+ /* rotate pattern to correct start position */
+ pat = pat << rot | pat >> (bpp-rot);
+
+ right = bpp-left;
switch (rect->rop) {
case ROP_XOR:
- fill_op = bitfill_rev;
+ fill_op = bitfill_unaligned_rev;
break;
case ROP_COPY:
+ fill_op = bitfill_unaligned;
+ break;
default:
- fill_op = bitfill;
+ printk( KERN_ERR "cfb_fillrect(): unknown rop, defaulting to ROP_COPY\n");
+ fill_op = bitfill_unaligned;
break;
}
while (height--) {
- dst += dst_idx >> SHIFT_PER_LONG;
- dst_idx &= (BITS_PER_LONG-1);
- fill_op(dst, dst_idx, pat, left, right,
- width*bpp);
+ dst += dst_idx >> (ffs(bits) - 1);
+ dst_idx &= (bits - 1);
+ fill_op(dst, dst_idx, pat, left, right,
+ width*bpp, bits);
r = (p->fix.line_length*8) % bpp;
pat = pat << (bpp-r) | pat >> r;
dst_idx += p->fix.line_length*8;
diff --git a/drivers/video/chipsfb.c b/drivers/video/chipsfb.c
index a51f4d2b69d8b..ab98f225fe3ee 100644
--- a/drivers/video/chipsfb.c
+++ b/drivers/video/chipsfb.c
@@ -465,7 +465,7 @@ int __init chips_init(void)
if (fb_get_options("chipsfb", NULL))
return -ENODEV;
- return pci_module_init(&chipsfb_driver);
+ return pci_register_driver(&chipsfb_driver);
}
module_init(chips_init);
diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c
index 617f63e691347..a3040429c27b7 100644
--- a/drivers/video/cirrusfb.c
+++ b/drivers/video/cirrusfb.c
@@ -515,23 +515,25 @@ static const struct {
/*--- Interface used by the world ------------------------------------------*/
-int cirrusfb_init (void);
-int cirrusfb_setup (char *options);
-
-int cirrusfb_open (struct fb_info *info, int user);
-int cirrusfb_release (struct fb_info *info, int user);
-int cirrusfb_setcolreg (unsigned regno, unsigned red, unsigned green,
- unsigned blue, unsigned transp,
- struct fb_info *info);
-int cirrusfb_check_var (struct fb_var_screeninfo *var,
- struct fb_info *info);
-int cirrusfb_set_par (struct fb_info *info);
-int cirrusfb_pan_display (struct fb_var_screeninfo *var,
- struct fb_info *info);
-int cirrusfb_blank (int blank_mode, struct fb_info *info);
-void cirrusfb_fillrect (struct fb_info *info, const struct fb_fillrect *region);
-void cirrusfb_copyarea(struct fb_info *info, const struct fb_copyarea *area);
-void cirrusfb_imageblit(struct fb_info *info, const struct fb_image *image);
+static int cirrusfb_init (void);
+#ifndef MODULE
+static int cirrusfb_setup (char *options);
+#endif
+
+static int cirrusfb_open (struct fb_info *info, int user);
+static int cirrusfb_release (struct fb_info *info, int user);
+static int cirrusfb_setcolreg (unsigned regno, unsigned red, unsigned green,
+ unsigned blue, unsigned transp,
+ struct fb_info *info);
+static int cirrusfb_check_var (struct fb_var_screeninfo *var,
+ struct fb_info *info);
+static int cirrusfb_set_par (struct fb_info *info);
+static int cirrusfb_pan_display (struct fb_var_screeninfo *var,
+ struct fb_info *info);
+static int cirrusfb_blank (int blank_mode, struct fb_info *info);
+static void cirrusfb_fillrect (struct fb_info *info, const struct fb_fillrect *region);
+static void cirrusfb_copyarea(struct fb_info *info, const struct fb_copyarea *area);
+static void cirrusfb_imageblit(struct fb_info *info, const struct fb_image *image);
/* function table of the above functions */
static struct fb_ops cirrusfb_ops = {
@@ -600,7 +602,7 @@ static void cirrusfb_dbg_print_byte (const char *name, unsigned char val);
static int opencount = 0;
/*--- Open /dev/fbx ---------------------------------------------------------*/
-int cirrusfb_open (struct fb_info *info, int user)
+static int cirrusfb_open (struct fb_info *info, int user)
{
if (opencount++ == 0)
switch_monitor (info->par, 1);
@@ -608,7 +610,7 @@ int cirrusfb_open (struct fb_info *info, int user)
}
/*--- Close /dev/fbx --------------------------------------------------------*/
-int cirrusfb_release (struct fb_info *info, int user)
+static int cirrusfb_release (struct fb_info *info, int user)
{
if (--opencount == 0)
switch_monitor (info->par, 0);
@@ -660,8 +662,8 @@ static long cirrusfb_get_mclk (long freq, int bpp, long *div)
return mclk;
}
-int cirrusfb_check_var(struct fb_var_screeninfo *var,
- struct fb_info *info)
+static int cirrusfb_check_var(struct fb_var_screeninfo *var,
+ struct fb_info *info)
{
struct cirrusfb_info *cinfo = info->par;
int nom, den; /* translyting from pixels->bytes */
@@ -1573,15 +1575,15 @@ static int cirrusfb_set_par_foo (struct fb_info *info)
/* for some reason incomprehensible to me, cirrusfb requires that you write
* the registers twice for the settings to take..grr. -dte */
-int cirrusfb_set_par (struct fb_info *info)
+static int cirrusfb_set_par (struct fb_info *info)
{
cirrusfb_set_par_foo (info);
return cirrusfb_set_par_foo (info);
}
-int cirrusfb_setcolreg (unsigned regno, unsigned red, unsigned green,
- unsigned blue, unsigned transp,
- struct fb_info *info)
+static int cirrusfb_setcolreg (unsigned regno, unsigned red, unsigned green,
+ unsigned blue, unsigned transp,
+ struct fb_info *info)
{
struct cirrusfb_info *cinfo = info->par;
@@ -1632,8 +1634,8 @@ int cirrusfb_setcolreg (unsigned regno, unsigned red, unsigned green,
performs display panning - provided hardware permits this
**************************************************************************/
-int cirrusfb_pan_display (struct fb_var_screeninfo *var,
- struct fb_info *info)
+static int cirrusfb_pan_display (struct fb_var_screeninfo *var,
+ struct fb_info *info)
{
int xoffset = 0;
int yoffset = 0;
@@ -1702,7 +1704,7 @@ int cirrusfb_pan_display (struct fb_var_screeninfo *var,
}
-int cirrusfb_blank (int blank_mode, struct fb_info *info)
+static int cirrusfb_blank (int blank_mode, struct fb_info *info)
{
/*
* Blank the screen if blank_mode != 0, else unblank. If blank == NULL
@@ -2036,7 +2038,7 @@ static void cirrusfb_prim_fillrect(struct cirrusfb_info *cinfo,
return;
}
-void cirrusfb_fillrect (struct fb_info *info, const struct fb_fillrect *region)
+static void cirrusfb_fillrect (struct fb_info *info, const struct fb_fillrect *region)
{
struct cirrusfb_info *cinfo = info->par;
struct fb_fillrect modded;
@@ -2086,7 +2088,7 @@ static void cirrusfb_prim_copyarea(struct cirrusfb_info *cinfo,
}
-void cirrusfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
+static void cirrusfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
{
struct cirrusfb_info *cinfo = info->par;
struct fb_copyarea modded;
@@ -2121,7 +2123,7 @@ void cirrusfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
cirrusfb_prim_copyarea(cinfo, &modded);
}
-void cirrusfb_imageblit(struct fb_info *info, const struct fb_image *image)
+static void cirrusfb_imageblit(struct fb_info *info, const struct fb_image *image)
{
struct cirrusfb_info *cinfo = info->par;
@@ -2459,7 +2461,7 @@ err_out:
return ret;
}
-void __devexit cirrusfb_pci_unregister (struct pci_dev *pdev)
+static void __devexit cirrusfb_pci_unregister (struct pci_dev *pdev)
{
struct fb_info *info = pci_get_drvdata(pdev);
DPRINTK ("ENTER\n");
@@ -2605,7 +2607,7 @@ static struct zorro_driver cirrusfb_zorro_driver = {
};
#endif /* CONFIG_ZORRO */
-int __init cirrusfb_init(void)
+static int __init cirrusfb_init(void)
{
int error = 0;
@@ -2621,7 +2623,7 @@ int __init cirrusfb_init(void)
error |= zorro_module_init(&cirrusfb_zorro_driver);
#endif
#ifdef CONFIG_PCI
- error |= pci_module_init(&cirrusfb_pci_driver);
+ error |= pci_register_driver(&cirrusfb_pci_driver);
#endif
return error;
}
@@ -2629,7 +2631,7 @@ int __init cirrusfb_init(void)
#ifndef MODULE
-int __init cirrusfb_setup(char *options) {
+static int __init cirrusfb_setup(char *options) {
char *this_opt, s[32];
int i;
@@ -2664,7 +2666,7 @@ MODULE_AUTHOR("Copyright 1999,2000 Jeff Garzik <jgarzik@pobox.com>");
MODULE_DESCRIPTION("Accelerated FBDev driver for Cirrus Logic chips");
MODULE_LICENSE("GPL");
-void __exit cirrusfb_exit (void)
+static void __exit cirrusfb_exit (void)
{
#ifdef CONFIG_PCI
pci_unregister_driver(&cirrusfb_pci_driver);
diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index ab3ce8e46f77b..ccf55811d24fd 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -43,7 +43,7 @@ config VIDEO_SELECT
about the Video mode selection support. If unsure, say N.
config MDA_CONSOLE
- depends on !M68K && ISA
+ depends on !M68K && !PARISC && ISA
tristate "MDA text console (dual-headed) (EXPERIMENTAL)"
---help---
Say Y here if you have an old MDA or monochrome Hercules graphics
@@ -65,30 +65,6 @@ config SGI_NEWPORT_CONSOLE
card of your Indy. Most people say Y here.
# bool 'IODC console' CONFIG_IODC_CONSOLE
-config STI_CONSOLE
- tristate "STI text console"
- depends on PARISC && FRAMEBUFFER_CONSOLE
- default y
- help
- The STI console is the builtin display/keyboard on HP-PARISC
- machines. Say Y here to build support for it into your kernel.
- The alternative is to use your primary serial port as a console.
-
-config DUMMY_CONSOLE_COLUMNS
- int "Initial number of console screen columns" if STI_CONSOLE
- depends on PARISC
- default "160"
- help
- The default value is 160, which should fit a 1280x1024 monitor.
- Select 80 if you use a 640x480 resolution by default.
-
-config DUMMY_CONSOLE_ROWS
- int "Initial number of console screen rows" if STI_CONSOLE
- depends on PARISC
- default "64"
- help
- The default value is 64, which should fit a 1280x1024 monitor.
- Select 25 if you use a 640x480 resolution by default.
config PROM_CONSOLE
bool "PROM console"
@@ -102,11 +78,36 @@ config DUMMY_CONSOLE
depends on PROM_CONSOLE!=y || VGA_CONSOLE!=y || SGI_NEWPORT_CONSOLE!=y
default y
+config DUMMY_CONSOLE_COLUMNS
+ int "Initial number of console screen columns"
+ depends on PARISC && DUMMY_CONSOLE
+ default "160"
+ help
+ The default value is 160, which should fit a 1280x1024 monitor.
+ Select 80 if you use a 640x480 resolution by default.
+
+config DUMMY_CONSOLE_ROWS
+ int "Initial number of console screen rows"
+ depends on PARISC && DUMMY_CONSOLE
+ default "64"
+ help
+ The default value is 64, which should fit a 1280x1024 monitor.
+ Select 25 if you use a 640x480 resolution by default.
+
config FRAMEBUFFER_CONSOLE
tristate "Framebuffer Console support"
depends on FB
select CRC32
+config STI_CONSOLE
+ tristate "STI text console"
+ depends on PARISC
+ default y
+ help
+ The STI console is the builtin display/keyboard on HP-PARISC
+ machines. Say Y here to build support for it into your kernel.
+ The alternative is to use your primary serial port as a console.
+
config FONTS
bool "Select compiled-in fonts"
depends on FRAMEBUFFER_CONSOLE
diff --git a/drivers/video/console/Makefile b/drivers/video/console/Makefile
index e5fa93b680431..33516447f9f2e 100644
--- a/drivers/video/console/Makefile
+++ b/drivers/video/console/Makefile
@@ -21,13 +21,15 @@ font-objs += $(font-objs-y)
obj-$(CONFIG_DUMMY_CONSOLE) += dummycon.o
obj-$(CONFIG_SGI_NEWPORT_CONSOLE) += newport_con.o font.o
obj-$(CONFIG_PROM_CONSOLE) += promcon.o promcon_tbl.o
-obj-$(CONFIG_STI_CONSOLE) += sticon.o sticore.o
+obj-$(CONFIG_STI_CONSOLE) += sticon.o sticore.o font.o
obj-$(CONFIG_VGA_CONSOLE) += vgacon.o
obj-$(CONFIG_MDA_CONSOLE) += mdacon.o
obj-$(CONFIG_FRAMEBUFFER_CONSOLE) += fbcon.o bitblit.o font.o
-obj-$(CONFIG_FB_TILEBLITTING) += tileblit.o
+ifeq ($(CONFIG_FB_TILEBLITTING),y)
+obj-$(CONFIG_FRAMEBUFFER_CONSOLE) += tileblit.o
+endif
-obj-$(CONFIG_FB_STI) += sticore.o
+obj-$(CONFIG_FB_STI) += sticore.o font.o
# Targets that kbuild needs to know about
targets := promcon_tbl.c
@@ -37,5 +39,5 @@ quiet_cmd_conmakehash = CNMKHSH $@
sed -e '/\#include <[^>]*>/p' -e 's/types/init/' \
-e 's/dfont\(_uni.*\]\)/promfont\1 __initdata/' > $@
-$(obj)/promcon_tbl.c: $(src)/prom.uni FORCE
- $(call if_changed,conmakehash)
+$(obj)/promcon_tbl.c: $(src)/prom.uni
+ $(call cmd,conmakehash)
diff --git a/drivers/video/console/bitblit.c b/drivers/video/console/bitblit.c
index 2ab37d69a83e1..b28a4b0e395e6 100644
--- a/drivers/video/console/bitblit.c
+++ b/drivers/video/console/bitblit.c
@@ -39,7 +39,7 @@ static inline int get_attribute(struct fb_info *info, u16 c)
{
int attribute = 0;
- if (fb_get_color_depth(info) == 1) {
+ if (fb_get_color_depth(&info->var) == 1) {
if (attr_underline(c))
attribute |= FBCON_ATTRIBUTE_UNDERLINE;
if (attr_reverse(c))
@@ -199,7 +199,10 @@ static void bit_putcs(struct vc_data *vc, struct fb_info *info,
count -= cnt;
}
- if (buf)
+ /* buf is always NULL except when in monochrome mode, so in this case
+ it's a gain to check buf against NULL even though kfree() handles
+ NULL pointers just fine */
+ if (unlikely(buf))
kfree(buf);
}
@@ -236,7 +239,7 @@ 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 fg, int bg)
+ struct display *p, int mode, int softback_lines, int fg, int bg)
{
struct fb_cursor cursor;
struct fbcon_ops *ops = (struct fbcon_ops *) info->fbcon_par;
@@ -248,6 +251,15 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info,
cursor.set = 0;
+ if (softback_lines) {
+ if (y + softback_lines >= vc->vc_rows) {
+ mode = CM_ERASE;
+ ops->cursor_flash = 0;
+ return;
+ } else
+ y += softback_lines;
+ }
+
c = scr_readw((u16 *) vc->vc_pos);
attribute = get_attribute(info, c);
src = vc->vc_font.data + ((c & charmask) * (w * vc->vc_font.height));
@@ -264,8 +276,7 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info,
dst = kmalloc(w * vc->vc_font.height, GFP_ATOMIC);
if (!dst)
return;
- if (ops->cursor_data)
- kfree(ops->cursor_data);
+ kfree(ops->cursor_data);
ops->cursor_data = dst;
update_attr(dst, src, attribute, vc);
src = dst;
@@ -312,8 +323,7 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info,
if (!mask)
return;
- if (ops->cursor_state.mask)
- kfree(ops->cursor_state.mask);
+ kfree(ops->cursor_state.mask);
ops->cursor_state.mask = mask;
p->cursor_shape = vc->vc_cursor_type;
diff --git a/drivers/video/console/dummycon.c b/drivers/video/console/dummycon.c
index 3ac5d5842e726..1ecda91e5a9ce 100644
--- a/drivers/video/console/dummycon.c
+++ b/drivers/video/console/dummycon.c
@@ -42,7 +42,7 @@ static void dummycon_init(struct vc_data *vc, int init)
vc->vc_cols = DUMMY_COLUMNS;
vc->vc_rows = DUMMY_ROWS;
} else
- vc_resize(vc->vc_num, DUMMY_COLUMNS, DUMMY_ROWS);
+ vc_resize(vc, DUMMY_COLUMNS, DUMMY_ROWS);
}
static int dummycon_dummy(void)
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index 661685cc823df..59e3b4b4e7e3e 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -107,15 +107,15 @@ enum {
};
struct display fb_display[MAX_NR_CONSOLES];
-signed char con2fb_map[MAX_NR_CONSOLES];
-signed char con2fb_map_boot[MAX_NR_CONSOLES];
+static signed char con2fb_map[MAX_NR_CONSOLES];
+static signed char con2fb_map_boot[MAX_NR_CONSOLES];
static int logo_height;
static int logo_lines;
/* logo_shown is an index to vc_cons when >= 0; otherwise follows FBCON_LOGO
enums. */
static int logo_shown = FBCON_LOGO_CANSHOW;
/* Software scrollback */
-int fbcon_softback_size = 32768;
+static int fbcon_softback_size = 32768;
static unsigned long softback_buf, softback_curr;
static unsigned long softback_in;
static unsigned long softback_top, softback_end;
@@ -130,6 +130,8 @@ static char fontname[40];
/* current fb_info */
static int info_idx = -1;
+static const struct consw fb_con;
+
#define CM_SOFTBACK (8)
#define advance_row(p, delta) (unsigned short *)((unsigned long)(p) + (delta) * vc->vc_size_row)
@@ -182,8 +184,10 @@ static __inline__ void ypan_up(struct vc_data *vc, int count);
static __inline__ void ypan_down(struct vc_data *vc, int count);
static void fbcon_bmove_rec(struct vc_data *vc, struct display *p, int sy, int sx,
int dy, int dx, int height, int width, u_int y_break);
-static void fbcon_set_disp(struct fb_info *info, struct vc_data *vc);
-static void fbcon_preset_disp(struct fb_info *info, int unit);
+static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var,
+ struct vc_data *vc);
+static void fbcon_preset_disp(struct fb_info *info, struct fb_var_screeninfo *var,
+ int unit);
static void fbcon_redraw_move(struct vc_data *vc, struct display *p,
int line, int count, int dy);
@@ -202,14 +206,16 @@ static irqreturn_t fb_vbl_detect(int irq, void *dummy, struct pt_regs *fp)
static inline int fbcon_is_inactive(struct vc_data *vc, struct fb_info *info)
{
+ struct fbcon_ops *ops = info->fbcon_par;
+
return (info->state != FBINFO_STATE_RUNNING ||
- vt_cons[vc->vc_num]->vc_mode != KD_TEXT);
+ vc->vc_mode != KD_TEXT || ops->graphics);
}
static inline int get_color(struct vc_data *vc, struct fb_info *info,
u16 c, int is_fg)
{
- int depth = fb_get_color_depth(info);
+ int depth = fb_get_color_depth(&info->var);
int color = 0;
if (console_blanked) {
@@ -277,7 +283,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, get_color(vc, info, c, 1),
+ ops->cursor(vc, info, p, mode, softback_lines, get_color(vc, info, c, 1),
get_color(vc, info, c, 0));
release_console_sem();
}
@@ -305,7 +311,8 @@ static void cursor_timer_handler(unsigned long dev_addr)
mod_timer(&ops->cursor_timer, jiffies + HZ/5);
}
-int __init fb_console_setup(char *this_opt)
+#ifndef MODULE
+static int __init fb_console_setup(char *this_opt)
{
char *options;
int i, j;
@@ -359,6 +366,7 @@ int __init fb_console_setup(char *this_opt)
}
__setup("fbcon=", fb_console_setup);
+#endif
static int search_fb_in_map(int idx)
{
@@ -418,7 +426,7 @@ static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info,
* remove underline attribute from erase character
* if black and white framebuffer.
*/
- if (fb_get_color_depth(info) == 1)
+ if (fb_get_color_depth(&info->var) == 1)
erase &= ~0x400;
logo_height = fb_prepare_logo(info);
logo_lines = (logo_height + vc->vc_font.height - 1) /
@@ -456,9 +464,9 @@ static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info,
erase,
vc->vc_size_row * logo_lines);
- if (CON_IS_VISIBLE(vc) && vt_cons[vc->vc_num]->vc_mode == KD_TEXT) {
+ if (CON_IS_VISIBLE(vc) && vc->vc_mode == KD_TEXT) {
fbcon_clear_margins(vc, 0);
- update_screen(vc->vc_num);
+ update_screen(vc);
}
if (save) {
@@ -591,13 +599,16 @@ static void con2fb_init_display(struct vc_data *vc, struct fb_info *info,
ops->currcon = fg_console;
- if (info->fbops->fb_set_par)
+ if (info->fbops->fb_set_par && !(ops->flags & FBCON_FLAGS_INIT))
info->fbops->fb_set_par(info);
+ ops->flags |= FBCON_FLAGS_INIT;
+ ops->graphics = 0;
+
if (vc)
- fbcon_set_disp(info, vc);
+ fbcon_set_disp(info, &info->var, vc);
else
- fbcon_preset_disp(info, unit);
+ fbcon_preset_disp(info, &info->var, unit);
if (show_logo) {
struct vc_data *fg_vc = vc_cons[fg_console].d;
@@ -609,7 +620,7 @@ static void con2fb_init_display(struct vc_data *vc, struct fb_info *info,
fg_vc->vc_rows);
}
- switch_screen(fg_console);
+ update_screen(vc_cons[fg_console].d);
}
/**
@@ -693,6 +704,7 @@ static int var_to_display(struct display *disp,
disp->green = var->green;
disp->blue = var->blue;
disp->transp = var->transp;
+ disp->rotate = var->rotate;
disp->mode = fb_match_mode(var, &info->modelist);
if (disp->mode == NULL)
/* This should not happen */
@@ -716,6 +728,7 @@ static void display_to_var(struct fb_var_screeninfo *var,
var->green = disp->green;
var->blue = disp->blue;
var->transp = disp->transp;
+ var->rotate = disp->rotate;
}
static const char *fbcon_startup(void)
@@ -761,6 +774,7 @@ static const char *fbcon_startup(void)
memset(ops, 0, sizeof(struct fbcon_ops));
ops->currcon = -1;
+ ops->graphics = 1;
info->fbcon_par = ops;
set_blitting_type(vc, info, NULL);
@@ -802,7 +816,7 @@ static const char *fbcon_startup(void)
cols = info->var.xres / vc->vc_font.width;
rows = info->var.yres / vc->vc_font.height;
- vc_resize(vc->vc_num, cols, rows);
+ vc_resize(vc, cols, rows);
DPRINTK("mode: %s\n", info->fix.id);
DPRINTK("visual: %d\n", info->fix.visual);
@@ -887,16 +901,16 @@ static const char *fbcon_startup(void)
static void fbcon_init(struct vc_data *vc, int init)
{
struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
+ struct fbcon_ops *ops;
struct vc_data **default_mode = vc->vc_display_fg;
struct vc_data *svc = *default_mode;
struct display *t, *p = &fb_display[vc->vc_num];
- int display_fg = (*default_mode)->vc_num;
int logo = 1, new_rows, new_cols, rows, cols, charcnt = 256;
int cap = info->flags;
if (info_idx == -1 || info == NULL)
return;
- if (vc->vc_num != display_fg || logo_shown == FBCON_LOGO_DONTSHOW ||
+ if (vc != svc || logo_shown == FBCON_LOGO_DONTSHOW ||
(info->fix.type == FB_TYPE_TEXT))
logo = 0;
@@ -907,7 +921,7 @@ static void fbcon_init(struct vc_data *vc, int init)
/* If we are not the first console on this
fb, copy the font from that console */
- t = &fb_display[display_fg];
+ t = &fb_display[svc->vc_num];
if (!vc->vc_font.data) {
vc->vc_font.data = p->fontdata = t->fontdata;
vc->vc_font.width = (*default_mode)->vc_font.width;
@@ -918,7 +932,7 @@ static void fbcon_init(struct vc_data *vc, int init)
}
if (p->userfont)
charcnt = FNTCHARCNT(p->fontdata);
- vc->vc_can_do_color = (fb_get_color_depth(info) != 1);
+ vc->vc_can_do_color = (fb_get_color_depth(&info->var) != 1);
vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800;
if (charcnt == 256) {
vc->vc_hi_font_mask = 0;
@@ -929,15 +943,17 @@ static void fbcon_init(struct vc_data *vc, int init)
}
if (!*svc->vc_uni_pagedir_loc)
- con_set_default_unimap(display_fg);
+ con_set_default_unimap(svc);
if (!*vc->vc_uni_pagedir_loc)
- con_copy_unimap(vc->vc_num, display_fg);
+ con_copy_unimap(vc, svc);
cols = vc->vc_cols;
rows = vc->vc_rows;
new_cols = info->var.xres / vc->vc_font.width;
new_rows = info->var.yres / vc->vc_font.height;
- vc_resize(vc->vc_num, new_cols, new_rows);
+ vc_resize(vc, new_cols, new_rows);
+
+ ops = info->fbcon_par;
/*
* We must always set the mode. The mode of the previous console
* driver could be in the same resolution but we are using different
@@ -945,9 +961,14 @@ 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) && info->fbops->fb_set_par)
- info->fbops->fb_set_par(info);
+ if (CON_IS_VISIBLE(vc)) {
+ if (info->fbops->fb_set_par &&
+ !(ops->flags & FBCON_FLAGS_INIT))
+ info->fbops->fb_set_par(info);
+ ops->flags |= FBCON_FLAGS_INIT;
+ }
+ ops->graphics = 0;
if ((cap & FBINFO_HWACCEL_COPYAREA) &&
!(cap & FBINFO_HWACCEL_DISABLED))
@@ -968,7 +989,7 @@ static void fbcon_init(struct vc_data *vc, int init)
if (logo)
fbcon_prepare_logo(vc, info, cols, rows, new_cols, new_rows);
- if (vc->vc_num == display_fg && softback_buf) {
+ if (vc == svc && softback_buf) {
int l = fbcon_softback_size / vc->vc_size_row;
if (l > 5)
softback_end = softback_buf + l * vc->vc_size_row;
@@ -1085,27 +1106,23 @@ 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 = real_y(p, vc->vc_y);
+ int y;
int c = scr_readw((u16 *) vc->vc_pos);
if (fbcon_is_inactive(vc, info))
return;
- ops->cursor_flash = 1;
+ ops->cursor_flash = (mode == CM_ERASE) ? 0 : 1;
if (mode & CM_SOFTBACK) {
mode &= ~CM_SOFTBACK;
- if (softback_lines) {
- if (y + softback_lines >= vc->vc_rows) {
- mode = CM_ERASE;
- ops->cursor_flash = 0;
- }
- else
- y += softback_lines;
- }
- } else if (softback_lines)
- fbcon_set_origin(vc);
+ y = softback_lines;
+ } else {
+ if (softback_lines)
+ fbcon_set_origin(vc);
+ y = 0;
+ }
- ops->cursor(vc, info, p, mode, get_color(vc, info, c, 1),
+ ops->cursor(vc, info, p, mode, y, get_color(vc, info, c, 1),
get_color(vc, info, c, 0));
vbl_cursor_cnt = CURSOR_DRAW_DELAY;
}
@@ -1114,7 +1131,7 @@ static int scrollback_phys_max = 0;
static int scrollback_max = 0;
static int scrollback_current = 0;
-int update_var(int con, struct fb_info *info)
+static int update_var(int con, struct fb_info *info)
{
if (con == ((struct fbcon_ops *)info->fbcon_par)->currcon)
return fb_pan_display(info, &info->var);
@@ -1124,13 +1141,14 @@ int update_var(int con, struct fb_info *info)
/*
* If no vc is existent yet, just set struct display
*/
-static void fbcon_preset_disp(struct fb_info *info, int unit)
+static void fbcon_preset_disp(struct fb_info *info, struct fb_var_screeninfo *var,
+ int unit)
{
struct display *p = &fb_display[unit];
struct display *t = &fb_display[fg_console];
- info->var.xoffset = info->var.yoffset = p->yscroll = 0;
- if (var_to_display(p, &info->var, info))
+ var->xoffset = var->yoffset = p->yscroll = 0;
+ if (var_to_display(p, var, info))
return;
p->fontdata = t->fontdata;
@@ -1139,18 +1157,18 @@ static void fbcon_preset_disp(struct fb_info *info, int unit)
REFCOUNT(p->fontdata)++;
}
-static void fbcon_set_disp(struct fb_info *info, struct vc_data *vc)
+static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var,
+ struct vc_data *vc)
{
struct display *p = &fb_display[vc->vc_num], *t;
struct vc_data **default_mode = vc->vc_display_fg;
struct vc_data *svc = *default_mode;
- int display_fg = (*default_mode)->vc_num;
int rows, cols, charcnt = 256;
- info->var.xoffset = info->var.yoffset = p->yscroll = 0;
- if (var_to_display(p, &info->var, info))
+ var->xoffset = var->yoffset = p->yscroll = 0;
+ if (var_to_display(p, var, info))
return;
- t = &fb_display[display_fg];
+ t = &fb_display[svc->vc_num];
if (!vc->vc_font.data) {
vc->vc_font.data = p->fontdata = t->fontdata;
vc->vc_font.width = (*default_mode)->vc_font.width;
@@ -1162,7 +1180,7 @@ static void fbcon_set_disp(struct fb_info *info, struct vc_data *vc)
if (p->userfont)
charcnt = FNTCHARCNT(p->fontdata);
- vc->vc_can_do_color = (fb_get_color_depth(info) != 1);
+ vc->vc_can_do_color = (fb_get_color_depth(var) != 1);
vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800;
if (charcnt == 256) {
vc->vc_hi_font_mask = 0;
@@ -1173,15 +1191,15 @@ static void fbcon_set_disp(struct fb_info *info, struct vc_data *vc)
}
if (!*svc->vc_uni_pagedir_loc)
- con_set_default_unimap(display_fg);
+ con_set_default_unimap(svc);
if (!*vc->vc_uni_pagedir_loc)
- con_copy_unimap(vc->vc_num, display_fg);
+ con_copy_unimap(vc, svc);
- cols = info->var.xres / vc->vc_font.width;
- rows = info->var.yres / vc->vc_font.height;
- vc_resize(vc->vc_num, cols, rows);
+ cols = var->xres / vc->vc_font.width;
+ rows = var->yres / vc->vc_font.height;
+ vc_resize(vc, cols, rows);
if (CON_IS_VISIBLE(vc)) {
- update_screen(vc->vc_num);
+ update_screen(vc);
if (softback_buf) {
int l = fbcon_softback_size / vc->vc_size_row;
@@ -1873,7 +1891,6 @@ static int fbcon_resize(struct vc_data *vc, unsigned int width,
var.activate = FB_ACTIVATE_NOW |
FB_ACTIVATE_FORCE;
fb_set_var(info, &var);
- info->flags &= ~FBINFO_MISC_MODESWITCH;
}
var_to_display(p, &info->var, info);
}
@@ -1886,7 +1903,7 @@ static int fbcon_switch(struct vc_data *vc)
struct fb_info *info;
struct display *p = &fb_display[vc->vc_num];
struct fb_var_screeninfo var;
- int i, prev_console, do_set_par = 0;
+ int i, prev_console;
info = registered_fb[con2fb_map[vc->vc_num]];
@@ -1945,19 +1962,14 @@ static int fbcon_switch(struct vc_data *vc)
fb_set_var(info, &var);
if (prev_console != -1 &&
- registered_fb[con2fb_map[prev_console]] != info)
- do_set_par = 1;
-
- if (do_set_par || info->flags & FBINFO_MISC_MODESWITCH) {
- if (info->fbops->fb_set_par)
- info->fbops->fb_set_par(info);
- info->flags &= ~FBINFO_MISC_MODESWITCH;
- }
+ registered_fb[con2fb_map[prev_console]] != info &&
+ info->fbops->fb_set_par)
+ info->fbops->fb_set_par(info);
set_blitting_type(vc, info, p);
((struct fbcon_ops *)info->fbcon_par)->cursor_reset = 1;
- vc->vc_can_do_color = (fb_get_color_depth(info) != 1);
+ vc->vc_can_do_color = (fb_get_color_depth(&info->var) != 1);
vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800;
updatescrollmode(p, info, vc);
@@ -1987,7 +1999,7 @@ static int fbcon_switch(struct vc_data *vc)
logo_shown = fg_console;
/* This is protected above by initmem_freed */
fb_show_logo(info);
- update_region(fg_console,
+ update_region(vc,
vc->vc_origin + vc->vc_size_row * vc->vc_top,
vc->vc_size_row * (vc->vc_bottom -
vc->vc_top) / 2);
@@ -2015,29 +2027,20 @@ static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch)
{
struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
struct fbcon_ops *ops = info->fbcon_par;
- int active = !fbcon_is_inactive(vc, info);
if (mode_switch) {
struct fb_var_screeninfo var = info->var;
-/*
- * HACK ALERT: Some hardware will require reinitializion at this stage,
- * others will require it to be done as late as possible.
- * For now, we differentiate this with the
- * FBINFO_MISC_MODESWITCHLATE bitflag. Worst case will be
- * hardware that requires it here and another one later.
- * A definitive solution may require fixing X or the VT
- * system.
- */
- if (info->flags & FBINFO_MISC_MODESWITCHLATE)
- info->flags |= FBINFO_MISC_MODESWITCH;
- if (!blank && !(info->flags & FBINFO_MISC_MODESWITCHLATE)) {
+ ops->graphics = 1;
+
+ if (!blank) {
var.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE;
fb_set_var(info, &var);
+ ops->graphics = 0;
}
}
- if (active) {
+ if (!fbcon_is_inactive(vc, info)) {
if (ops->blank_state != blank) {
ops->blank_state = blank;
fbcon_cursor(vc, blank ? CM_ERASE : CM_DRAW);
@@ -2048,7 +2051,7 @@ static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch)
}
if (!blank)
- update_screen(vc->vc_num);
+ update_screen(vc);
}
return 0;
@@ -2198,7 +2201,7 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h,
if (resize) {
/* reset wrap/pan */
info->var.xoffset = info->var.yoffset = p->yscroll = 0;
- vc_resize(vc->vc_num, info->var.xres / w, info->var.yres / h);
+ vc_resize(vc, info->var.xres / w, info->var.yres / h);
if (CON_IS_VISIBLE(vc) && softback_buf) {
int l = fbcon_softback_size / vc->vc_size_row;
if (l > 5)
@@ -2211,9 +2214,9 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h,
}
}
} else if (CON_IS_VISIBLE(vc)
- && vt_cons[vc->vc_num]->vc_mode == KD_TEXT) {
+ && vc->vc_mode == KD_TEXT) {
fbcon_clear_margins(vc, 0);
- update_screen(vc->vc_num);
+ update_screen(vc);
}
if (old_data && (--REFCOUNT(old_data) == 0))
@@ -2328,7 +2331,10 @@ static int fbcon_set_palette(struct vc_data *vc, unsigned char *table)
if (fbcon_is_inactive(vc, info))
return -EINVAL;
- depth = fb_get_color_depth(info);
+ if (!CON_IS_VISIBLE(vc))
+ return 0;
+
+ depth = fb_get_color_depth(&info->var);
if (depth > 3) {
for (i = j = 0; i < 16; i++) {
k = table[i];
@@ -2438,7 +2444,7 @@ static int fbcon_scrolldelta(struct vc_data *vc, int lines)
if (softback_top) {
if (vc->vc_num != fg_console)
return 0;
- if (vt_cons[vc->vc_num]->vc_mode != KD_TEXT || !lines)
+ if (vc->vc_mode != KD_TEXT || !lines)
return 0;
if (logo_shown >= 0) {
struct vc_data *conp2 = vc_cons[logo_shown].d;
@@ -2464,7 +2470,7 @@ static int fbcon_scrolldelta(struct vc_data *vc, int lines)
vc->vc_size_row);
}
softback_in = p;
- update_region(vc->vc_num, vc->vc_origin,
+ update_region(vc, vc->vc_origin,
logo_lines * vc->vc_cols);
}
logo_shown = FBCON_LOGO_CANSHOW;
@@ -2545,7 +2551,7 @@ static void fbcon_resumed(struct fb_info *info)
return;
vc = vc_cons[ops->currcon].d;
- update_screen(vc->vc_num);
+ update_screen(vc);
}
static void fbcon_modechanged(struct fb_info *info)
@@ -2555,11 +2561,11 @@ static void fbcon_modechanged(struct fb_info *info)
struct display *p;
int rows, cols;
- if (!ops || ops->currcon < 0 || vt_cons[ops->currcon]->vc_mode !=
- KD_TEXT || registered_fb[con2fb_map[ops->currcon]] != info)
+ if (!ops || ops->currcon < 0)
return;
-
vc = vc_cons[ops->currcon].d;
+ if (vc->vc_mode != KD_TEXT || registered_fb[con2fb_map[ops->currcon]] != info)
+ return;
p = &fb_display[vc->vc_num];
@@ -2569,13 +2575,13 @@ static void fbcon_modechanged(struct fb_info *info)
var_to_display(p, &info->var, info);
cols = info->var.xres / vc->vc_font.width;
rows = info->var.yres / vc->vc_font.height;
- vc_resize(vc->vc_num, cols, rows);
+ vc_resize(vc, cols, rows);
updatescrollmode(p, info, vc);
scrollback_max = 0;
scrollback_current = 0;
update_var(vc->vc_num, info);
fbcon_set_palette(vc, color_table);
- update_screen(vc->vc_num);
+ update_screen(vc);
if (softback_buf) {
int l = fbcon_softback_size / vc->vc_size_row;
if (l > 5)
@@ -2641,25 +2647,47 @@ static int fbcon_fb_registered(int idx)
static void fbcon_fb_blanked(struct fb_info *info, int blank)
{
struct fbcon_ops *ops = info->fbcon_par;
- int valid = 1;
+ struct vc_data *vc;
- if (!ops || ops->currcon < 0 ||
- vt_cons[ops->currcon]->vc_mode != KD_TEXT ||
- registered_fb[con2fb_map[ops->currcon]] != info)
- valid = 0;
+ if (!ops || ops->currcon < 0)
+ return;
- if (valid) {
- struct vc_data *vc;
+ vc = vc_cons[ops->currcon].d;
+ if (vc->vc_mode != KD_TEXT ||
+ registered_fb[con2fb_map[ops->currcon]] != info)
+ return;
- vc = vc_cons[ops->currcon].d;
+ if (CON_IS_VISIBLE(vc)) {
+ if (blank)
+ do_blank_screen(0);
+ else
+ do_unblank_screen(0);
+ }
+ ops->blank_state = blank;
+}
+
+static void fbcon_new_modelist(struct fb_info *info)
+{
+ int i;
+ struct vc_data *vc;
+ struct fb_var_screeninfo var;
+ struct fb_videomode *mode;
+
+ for (i = 0; i < MAX_NR_CONSOLES; i++) {
+ if (registered_fb[con2fb_map[i]] != info)
+ continue;
+ if (!fb_display[i].mode)
+ continue;
+ vc = vc_cons[i].d;
+ display_to_var(&var, &fb_display[i]);
+ mode = fb_find_nearest_mode(&var, &info->modelist);
+ fb_videomode_to_var(&var, mode);
+
+ if (vc)
+ fbcon_set_disp(info, &var, vc);
+ else
+ fbcon_preset_disp(info, &var, i);
- if (CON_IS_VISIBLE(vc)) {
- if (blank)
- do_blank_screen(0);
- else
- do_unblank_screen(0);
- }
- ops->blank_state = blank;
}
}
@@ -2701,6 +2729,9 @@ static int fbcon_event_notify(struct notifier_block *self,
case FB_EVENT_BLANK:
fbcon_fb_blanked(info, *(int *)event->data);
break;
+ case FB_EVENT_NEW_MODELIST:
+ fbcon_new_modelist(info);
+ break;
}
return ret;
@@ -2710,7 +2741,7 @@ static int fbcon_event_notify(struct notifier_block *self,
* The console `switch' structure for the frame buffer based console
*/
-const struct consw fb_con = {
+static const struct consw fb_con = {
.owner = THIS_MODULE,
.con_startup = fbcon_startup,
.con_init = fbcon_init,
@@ -2740,7 +2771,7 @@ static struct notifier_block fbcon_event_notifier = {
.notifier_call = fbcon_event_notify,
};
-int __init fb_console_init(void)
+static int __init fb_console_init(void)
{
int i;
@@ -2768,7 +2799,7 @@ module_init(fb_console_init);
#ifdef MODULE
-void __exit fb_console_exit(void)
+static void __exit fb_console_exit(void)
{
acquire_console_sem();
fb_unregister_client(&fbcon_event_notifier);
@@ -2780,10 +2811,4 @@ module_exit(fb_console_exit);
#endif
-/*
- * Visible symbols for modules
- */
-
-EXPORT_SYMBOL(fb_con);
-
MODULE_LICENSE("GPL");
diff --git a/drivers/video/console/fbcon.h b/drivers/video/console/fbcon.h
index befa1e725b1f7..5d377860bce28 100644
--- a/drivers/video/console/fbcon.h
+++ b/drivers/video/console/fbcon.h
@@ -18,6 +18,8 @@
#include <asm/io.h>
+#define FBCON_FLAGS_INIT 1
+
/*
* This is the interface between the low-level console driver and the
* low-level frame buffer device
@@ -41,6 +43,7 @@ struct display {
u32 grayscale;
u32 nonstd;
u32 accel_flags;
+ u32 rotate;
struct fb_bitfield red;
struct fb_bitfield green;
struct fb_bitfield blue;
@@ -59,7 +62,7 @@ struct fbcon_ops {
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 fg, int bg);
+ struct display *p, int mode, int softback_lines, int fg, int bg);
struct timer_list cursor_timer; /* Cursor timer */
struct fb_cursor cursor_state;
@@ -67,6 +70,8 @@ struct fbcon_ops {
int cursor_flash;
int cursor_reset;
int blank_state;
+ int graphics;
+ int flags;
char *cursor_data;
};
/*
@@ -156,13 +161,10 @@ struct fbcon_ops {
#define SCROLL_REDRAW 0x004
#define SCROLL_PAN_REDRAW 0x005
-extern int fb_console_init(void);
#ifdef CONFIG_FB_TILEBLITTING
extern void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info,
struct display *p, struct fbcon_ops *ops);
#endif
extern void fbcon_set_bitops(struct fbcon_ops *ops);
-extern const struct consw fb_con;
-
#endif /* _VIDEO_FBCON_H */
diff --git a/drivers/video/console/mdacon.c b/drivers/video/console/mdacon.c
index be3d53596f8d3..989e4d49e5bbe 100644
--- a/drivers/video/console/mdacon.c
+++ b/drivers/video/console/mdacon.c
@@ -351,10 +351,9 @@ static void mdacon_init(struct vc_data *c, int init)
if (init) {
c->vc_cols = mda_num_columns;
c->vc_rows = mda_num_lines;
- } else {
- vc_resize(c->vc_num, mda_num_columns, mda_num_lines);
- }
-
+ } else
+ vc_resize(c, mda_num_columns, mda_num_lines);
+
/* make the first MDA console visible */
if (mda_display_fg == NULL)
@@ -565,7 +564,7 @@ static int mdacon_scroll(struct vc_data *c, int t, int b, int dir, int lines)
* The console `switch' structure for the MDA based console
*/
-const struct consw mda_con = {
+static const struct consw mda_con = {
.owner = THIS_MODULE,
.con_startup = mdacon_startup,
.con_init = mdacon_init,
@@ -592,7 +591,7 @@ int __init mda_console_init(void)
return take_over_console(&mda_con, mda_first_vc-1, mda_last_vc-1, 0);
}
-void __exit mda_console_exit(void)
+static void __exit mda_console_exit(void)
{
give_up_console(&mda_con);
}
diff --git a/drivers/video/console/promcon.c b/drivers/video/console/promcon.c
index fec664e615514..04f42fcaac59d 100644
--- a/drivers/video/console/promcon.c
+++ b/drivers/video/console/promcon.c
@@ -155,9 +155,9 @@ promcon_init_unimap(struct vc_data *conp)
k++;
}
set_fs(KERNEL_DS);
- con_clear_unimap(conp->vc_num, NULL);
- con_set_unimap(conp->vc_num, k, p);
- con_protect_unimap(conp->vc_num, 1);
+ con_clear_unimap(conp, NULL);
+ con_set_unimap(conp, k, p);
+ con_protect_unimap(conp, 1);
set_fs(old_fs);
kfree(p);
}
@@ -175,7 +175,7 @@ promcon_init(struct vc_data *conp, int init)
p = *conp->vc_uni_pagedir_loc;
if (conp->vc_uni_pagedir_loc == &conp->vc_uni_pagedir ||
!--conp->vc_uni_pagedir_loc[1])
- con_free_unimap(conp->vc_num);
+ con_free_unimap(conp);
conp->vc_uni_pagedir_loc = promcon_uni_pagedir;
promcon_uni_pagedir[1]++;
if (!promcon_uni_pagedir[0] && p) {
@@ -183,7 +183,7 @@ promcon_init(struct vc_data *conp, int init)
}
if (!init) {
if (conp->vc_cols != pw + 1 || conp->vc_rows != ph + 1)
- vc_resize(conp->vc_num, pw + 1, ph + 1);
+ vc_resize(conp, pw + 1, ph + 1);
}
}
@@ -192,9 +192,9 @@ promcon_deinit(struct vc_data *conp)
{
/* When closing the last console, reset video origin */
if (!--promcon_uni_pagedir[1])
- con_free_unimap(conp->vc_num);
+ con_free_unimap(conp);
conp->vc_uni_pagedir_loc = &conp->vc_uni_pagedir;
- con_set_default_unimap(conp->vc_num);
+ con_set_default_unimap(conp);
}
static int
diff --git a/drivers/video/console/sticon.c b/drivers/video/console/sticon.c
index 99262680fdd8a..fd5940f412716 100644
--- a/drivers/video/console/sticon.c
+++ b/drivers/video/console/sticon.c
@@ -87,13 +87,12 @@ static int sticon_set_palette(struct vc_data *c, unsigned char *table)
static void sticon_putc(struct vc_data *conp, int c, int ypos, int xpos)
{
- int unit = conp->vc_num;
int redraw_cursor = 0;
if (vga_is_gfx || console_blanked)
return;
-
- if (vt_cons[unit]->vc_mode != KD_TEXT)
+
+ if (conp->vc_mode != KD_TEXT)
return;
#if 0
if ((p->cursor_x == xpos) && (p->cursor_y == ypos)) {
@@ -111,15 +110,14 @@ static void sticon_putc(struct vc_data *conp, int c, int ypos, int xpos)
static void sticon_putcs(struct vc_data *conp, const unsigned short *s,
int count, int ypos, int xpos)
{
- int unit = conp->vc_num;
int redraw_cursor = 0;
if (vga_is_gfx || console_blanked)
return;
- if (vt_cons[unit]->vc_mode != KD_TEXT)
+ if (conp->vc_mode != KD_TEXT)
return;
-
+
#if 0
if ((p->cursor_y == ypos) && (xpos <= p->cursor_x) &&
(p->cursor_x < (xpos + count))) {
@@ -217,7 +215,7 @@ static void sticon_init(struct vc_data *c, int init)
} else {
/* vc_rows = (c->vc_rows > vc_rows) ? vc_rows : c->vc_rows; */
/* vc_cols = (c->vc_cols > vc_cols) ? vc_cols : c->vc_cols; */
- vc_resize(c->vc_num, vc_cols, vc_rows);
+ vc_resize(c, vc_cols, vc_rows);
/* vc_resize_con(vc_rows, vc_cols, c->vc_num); */
}
}
diff --git a/drivers/video/console/sticore.c b/drivers/video/console/sticore.c
index 836196d3517ef..d940f605acb68 100644
--- a/drivers/video/console/sticore.c
+++ b/drivers/video/console/sticore.c
@@ -249,13 +249,13 @@ sti_rom_copy(unsigned long base, unsigned long count, void *dest)
/* this still needs to be revisited (see arch/parisc/mm/init.c:246) ! */
while (count >= 4) {
count -= 4;
- *(u32 *)dest = __raw_readl(base);
+ *(u32 *)dest = gsc_readl(base);
base += 4;
dest += 4;
}
while (count) {
count--;
- *(u8 *)dest = __raw_readb(base);
+ *(u8 *)dest = gsc_readb(base);
base++;
dest++;
}
@@ -460,12 +460,20 @@ sti_init_glob_cfg(struct sti_struct *sti,
/* remap virtually */
/* FIXME: add BTLB support if btlb==1 */
len = sti->regions[i].region_desc.length * 4096;
-
+
+/* XXX: Enabling IOREMAP debugging causes a crash, so we must be passing
+ * a virtual address to something expecting a physical address that doesn't
+ * go through a readX macro */
+#if 0
if (len)
glob_cfg->region_ptrs[i] = (unsigned long) (
sti->regions[i].region_desc.cache ?
ioremap(sti->regions_phys[i], len) :
ioremap_nocache(sti->regions_phys[i], len) );
+#else
+ if (len)
+ glob_cfg->region_ptrs[i] = sti->regions_phys[i];
+#endif
DPRINTK(("region #%d: phys %08lx, virt %08x, len=%lukB, "
"btlb=%d, sysonly=%d, cache=%d, last=%d\n",
@@ -680,7 +688,7 @@ sti_bmode_rom_copy(unsigned long base, unsigned long count, void *dest)
while (count) {
count--;
- *(u8 *)dest = __raw_readl(base);
+ *(u8 *)dest = gsc_readl(base);
base += 4;
dest++;
}
@@ -730,7 +738,7 @@ sti_get_wmode_rom (unsigned long address)
unsigned long size;
/* read the ROM size directly from the struct in ROM */
- size = __raw_readl(address + offsetof(struct sti_rom,last_addr));
+ size = gsc_readl(address + offsetof(struct sti_rom,last_addr));
raw = kmalloc(size, GFP_KERNEL);
if(raw)
@@ -790,11 +798,8 @@ sti_read_rom(int wordmode, struct sti_struct *sti, unsigned long address)
return 1;
out_err:
- if(raw)
- kfree(raw);
- if(cooked)
- kfree(cooked);
-
+ kfree(raw);
+ kfree(cooked);
return 0;
}
@@ -825,13 +830,13 @@ test_rom:
if (pdc_add_valid(address))
goto out_err;
- sig = __raw_readl(address);
+ sig = gsc_readl(address);
/* check for a PCI ROM structure */
if ((le32_to_cpu(sig)==0xaa55)) {
unsigned int i, rm_offset;
u32 *rm;
- i = __raw_readl(address+0x04);
+ i = gsc_readl(address+0x04);
if (i != 1) {
/* The ROM could have multiple architecture
* dependent images (e.g. i386, parisc,...) */
@@ -842,17 +847,17 @@ test_rom:
sti->pd = pd;
- i = __raw_readl(address+0x0c);
+ i = gsc_readl(address+0x0c);
DPRINTK(("PCI ROM size (from header) = %d kB\n",
le16_to_cpu(i>>16)*512/1024));
rm_offset = le16_to_cpu(i & 0xffff);
if (rm_offset) {
/* read 16 bytes from the pci region mapper array */
rm = (u32*) &sti->rm_entry;
- *rm++ = __raw_readl(address+rm_offset+0x00);
- *rm++ = __raw_readl(address+rm_offset+0x04);
- *rm++ = __raw_readl(address+rm_offset+0x08);
- *rm++ = __raw_readl(address+rm_offset+0x0c);
+ *rm++ = gsc_readl(address+rm_offset+0x00);
+ *rm++ = gsc_readl(address+rm_offset+0x04);
+ *rm++ = gsc_readl(address+rm_offset+0x08);
+ *rm++ = gsc_readl(address+rm_offset+0x0c);
DPRINTK(("PCI region Mapper offset = %08x: ",
rm_offset));
for (i=0; i<16; i++)
@@ -860,7 +865,7 @@ test_rom:
DPRINTK(("\n"));
}
- address += le32_to_cpu(__raw_readl(address+8));
+ address += le32_to_cpu(gsc_readl(address+8));
DPRINTK(("sig %04x, PCI STI ROM at %08lx\n", sig, address));
goto test_rom;
}
@@ -1003,17 +1008,17 @@ static void __devexit sticore_pci_remove(struct pci_dev *pd)
static struct pci_device_id sti_pci_tbl[] = {
- { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_VISUALIZE_EG, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_VISUALIZE_FX6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_VISUALIZE_FX4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_VISUALIZE_FX2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_VISUALIZE_FXE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ { PCI_DEVICE(PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_VISUALIZE_EG) },
+ { PCI_DEVICE(PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_VISUALIZE_FX6) },
+ { PCI_DEVICE(PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_VISUALIZE_FX4) },
+ { PCI_DEVICE(PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_VISUALIZE_FX2) },
+ { PCI_DEVICE(PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_VISUALIZE_FXE) },
{ 0, } /* terminate list */
};
MODULE_DEVICE_TABLE(pci, sti_pci_tbl);
static struct pci_driver pci_sti_driver = {
- .name = "sti (pci)",
+ .name = "sti",
.id_table = sti_pci_tbl,
.probe = sticore_pci_init,
.remove = sticore_pci_remove,
@@ -1026,7 +1031,7 @@ static struct parisc_device_id sti_pa_tbl[] = {
};
static struct parisc_driver pa_sti_driver = {
- .name = "sti (native)",
+ .name = "sti",
.id_table = sti_pa_tbl,
.probe = sticore_pa_init,
};
@@ -1050,7 +1055,7 @@ static void __init sti_init_roms(void)
/* Register drivers for native & PCI cards */
register_parisc_driver(&pa_sti_driver);
- pci_module_init(&pci_sti_driver);
+ pci_register_driver(&pci_sti_driver);
/* if we didn't find the given default sti, take the first one */
if (!default_sti)
diff --git a/drivers/video/console/tileblit.c b/drivers/video/console/tileblit.c
index 0984adc13f288..7f76e2c6a4a17 100644
--- a/drivers/video/console/tileblit.c
+++ b/drivers/video/console/tileblit.c
@@ -81,7 +81,8 @@ static void tile_clear_margins(struct vc_data *vc, struct fb_info *info,
}
static void tile_cursor(struct vc_data *vc, struct fb_info *info,
- struct display *p, int mode, int fg, int bg)
+ struct display *p, int mode, int softback_lines,
+ int fg, int bg)
{
struct fb_tilecursor cursor;
int use_sw = (vc->vc_cursor_type & 0x01);
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index fb5d5943d8ac5..7d1ae06667c64 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -340,11 +340,11 @@ static void vgacon_init(struct vc_data *c, int init)
p = *c->vc_uni_pagedir_loc;
if (c->vc_uni_pagedir_loc == &c->vc_uni_pagedir ||
!--c->vc_uni_pagedir_loc[1])
- con_free_unimap(c->vc_num);
+ con_free_unimap(c);
c->vc_uni_pagedir_loc = vgacon_uni_pagedir;
vgacon_uni_pagedir[1]++;
if (!vgacon_uni_pagedir[0] && p)
- con_set_default_unimap(c->vc_num);
+ con_set_default_unimap(c);
}
static inline void vga_set_mem_top(struct vc_data *c)
@@ -358,10 +358,10 @@ static void vgacon_deinit(struct vc_data *c)
if (!--vgacon_uni_pagedir[1]) {
c->vc_visible_origin = vga_vram_base;
vga_set_mem_top(c);
- con_free_unimap(c->vc_num);
+ con_free_unimap(c);
}
c->vc_uni_pagedir_loc = &c->vc_uni_pagedir;
- con_set_default_unimap(c->vc_num);
+ con_set_default_unimap(c);
}
static u8 vgacon_build_attr(struct vc_data *c, u8 color, u8 intensity,
@@ -908,7 +908,7 @@ static int vgacon_adjust_height(struct vc_data *vc, unsigned fontheight)
c->vc_sw->con_cursor(c, CM_DRAW);
}
c->vc_font.height = fontheight;
- vc_resize(c->vc_num, 0, rows); /* Adjust console size */
+ vc_resize(c, 0, rows); /* Adjust console size */
}
}
return 0;
diff --git a/drivers/video/controlfb.c b/drivers/video/controlfb.c
index f0eb993dd6f7d..989e700159e01 100644
--- a/drivers/video/controlfb.c
+++ b/drivers/video/controlfb.c
@@ -315,7 +315,7 @@ static int controlfb_mmap(struct fb_info *info, struct file *file,
return -EINVAL;
off += start;
vma->vm_pgoff = off >> PAGE_SHIFT;
- if (io_remap_page_range(vma, vma->vm_start, off,
+ if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
vma->vm_end - vma->vm_start, vma->vm_page_prot))
return -EAGAIN;
diff --git a/drivers/video/cyber2000fb.c b/drivers/video/cyber2000fb.c
index c6aa0458c5b62..8b1b7c687a991 100644
--- a/drivers/video/cyber2000fb.c
+++ b/drivers/video/cyber2000fb.c
@@ -92,7 +92,6 @@ struct cfb_info {
u_char ramdac_powerdown;
};
-static char default_font_storage[40];
static char *default_font = "Acorn8x8";
module_param(default_font, charp, 0);
MODULE_PARM_DESC(default_font, "Default font name");
@@ -1306,7 +1305,8 @@ cyberpro_free_fb_info(struct cfb_info *cfb)
* Parse Cyber2000fb options. Usage:
* video=cyber2000:font:fontname
*/
-int
+#ifndef MODULE
+static int
cyber2000fb_setup(char *options)
{
char *opt;
@@ -1319,6 +1319,8 @@ cyber2000fb_setup(char *options)
continue;
if (strncmp(opt, "font:", 5) == 0) {
+ static char default_font_storage[40];
+
strlcpy(default_font_storage, opt + 5, sizeof(default_font_storage));
default_font = default_font_storage;
continue;
@@ -1328,6 +1330,7 @@ cyber2000fb_setup(char *options)
}
return 0;
}
+#endif /* MODULE */
/*
* The CyberPro chips can be placed on many different bus types.
@@ -1665,7 +1668,7 @@ static void __devexit cyberpro_pci_remove(struct pci_dev *dev)
}
}
-static int cyberpro_pci_suspend(struct pci_dev *dev, u32 state)
+static int cyberpro_pci_suspend(struct pci_dev *dev, pm_message_t state)
{
return 0;
}
@@ -1717,7 +1720,7 @@ static struct pci_driver cyberpro_driver = {
*
* Tony: "module_init" is now required
*/
-int __init cyber2000fb_init(void)
+static int __init cyber2000fb_init(void)
{
int ret = -1, err;
@@ -1737,7 +1740,7 @@ int __init cyber2000fb_init(void)
}
#endif
#ifdef CONFIG_PCI
- err = pci_module_init(&cyberpro_driver);
+ err = pci_register_driver(&cyberpro_driver);
if (!err)
ret = 0;
#endif
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 92f4a9781d582..25f460ca0daf1 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -62,10 +62,8 @@ int num_registered_fb;
* Helpers
*/
-int fb_get_color_depth(struct fb_info *info)
+int fb_get_color_depth(struct fb_var_screeninfo *var)
{
- struct fb_var_screeninfo *var = &info->var;
-
if (var->green.length == var->blue.length &&
var->green.length == var->red.length &&
!var->green.offset && !var->blue.offset &&
@@ -300,7 +298,7 @@ static void fb_set_logo(struct fb_info *info,
const u8 *src = logo->data;
u8 d, xor = (info->fix.visual == FB_VISUAL_MONO01) ? 0xff : 0;
- if (fb_get_color_depth(info) == 3)
+ if (fb_get_color_depth(&info->var) == 3)
fg = 7;
switch (depth) {
@@ -365,7 +363,7 @@ static struct logo_data {
int fb_prepare_logo(struct fb_info *info)
{
- int depth = fb_get_color_depth(info);
+ int depth = fb_get_color_depth(&info->var);
memset(&fb_logo, 0, sizeof(struct logo_data));
@@ -448,8 +446,7 @@ int fb_show_logo(struct fb_info *info)
logo_new = kmalloc(fb_logo.logo->width * fb_logo.logo->height,
GFP_KERNEL);
if (logo_new == NULL) {
- if (palette)
- kfree(palette);
+ kfree(palette);
if (saved_pseudo_palette)
info->pseudo_palette = saved_pseudo_palette;
return 0;
@@ -468,12 +465,10 @@ int fb_show_logo(struct fb_info *info)
info->fbops->fb_imageblit(info, &image);
}
- if (palette != NULL)
- kfree(palette);
+ kfree(palette);
if (saved_pseudo_palette != NULL)
info->pseudo_palette = saved_pseudo_palette;
- if (logo_new != NULL)
- kfree(logo_new);
+ kfree(logo_new);
return fb_logo.logo->height;
}
#else
@@ -876,7 +871,8 @@ fb_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
int fbidx = iminor(file->f_dentry->d_inode);
struct fb_info *info = registered_fb[fbidx];
struct fb_ops *fb = info->fbops;
- int ret;
+ long ret;
+
if (fb->fb_compat_ioctl == NULL)
return -ENOIOCTLCMD;
lock_kernel();
@@ -941,8 +937,8 @@ fb_mmap(struct file *file, struct vm_area_struct * vma)
/* This is an IO map - tell maydump to skip this VMA */
vma->vm_flags |= VM_IO | VM_RESERVED;
#if defined(__sparc_v9__)
- if (io_remap_page_range(vma, vma->vm_start, off,
- vma->vm_end - vma->vm_start, vma->vm_page_prot, 0))
+ if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
+ vma->vm_end - vma->vm_start, vma->vm_page_prot))
return -EAGAIN;
#else
#if defined(__mc68000__)
@@ -958,7 +954,9 @@ fb_mmap(struct file *file, struct vm_area_struct * vma)
}
#endif
#elif defined(__powerpc__)
- pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE|_PAGE_GUARDED;
+ vma->vm_page_prot = phys_mem_access_prot(file, off,
+ vma->vm_end - vma->vm_start,
+ vma->vm_page_prot);
#elif defined(__alpha__)
/* Caching is off in the I/O space quadrant by design. */
#elif defined(__i386__) || defined(__x86_64__)
@@ -978,7 +976,7 @@ fb_mmap(struct file *file, struct vm_area_struct * vma)
#else
#warning What do we have to do here??
#endif
- if (io_remap_page_range(vma, vma->vm_start, off,
+ if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
vma->vm_end - vma->vm_start, vma->vm_page_prot))
return -EAGAIN;
#endif /* !__sparc_v9__ */
@@ -1058,7 +1056,6 @@ int
register_framebuffer(struct fb_info *fb_info)
{
int i;
- struct class_device *c;
struct fb_event event;
if (num_registered_fb == FB_MAX)
@@ -1069,13 +1066,15 @@ register_framebuffer(struct fb_info *fb_info)
break;
fb_info->node = i;
- c = class_simple_device_add(fb_class, MKDEV(FB_MAJOR, i),
+ fb_info->class_device = class_simple_device_add(fb_class, MKDEV(FB_MAJOR, i),
fb_info->device, "fb%d", i);
- if (IS_ERR(c)) {
+ if (IS_ERR(fb_info->class_device)) {
/* Not fatal */
- printk(KERN_WARNING "Unable to create class_device for framebuffer %d; errno = %ld\n", i, PTR_ERR(c));
- }
-
+ printk(KERN_WARNING "Unable to create class_device for framebuffer %d; errno = %ld\n", i, PTR_ERR(fb_info->class_device));
+ fb_info->class_device = NULL;
+ } else
+ fb_init_class_device(fb_info);
+
if (fb_info->pixmap.addr == NULL) {
fb_info->pixmap.addr = kmalloc(FBPIXMAPSIZE, GFP_KERNEL);
if (fb_info->pixmap.addr) {
@@ -1134,6 +1133,7 @@ unregister_framebuffer(struct fb_info *fb_info)
fb_destroy_modelist(&fb_info->modelist);
registered_fb[i]=NULL;
num_registered_fb--;
+ fb_cleanup_class_device(fb_info);
class_simple_device_remove(MKDEV(FB_MAJOR, i));
return 0;
}
@@ -1188,7 +1188,7 @@ void fb_set_suspend(struct fb_info *info, int state)
*
*/
-int __init
+static int __init
fbmem_init(void)
{
create_proc_read_entry("fb", 0, NULL, fbmem_read_proc, NULL);
@@ -1204,16 +1204,65 @@ fbmem_init(void)
}
return 0;
}
+
+#ifdef MODULE
+module_init(fbmem_init);
+static void __exit
+fbmem_exit(void)
+{
+ class_simple_destroy(fb_class);
+}
+
+module_exit(fbmem_exit);
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Framebuffer base");
+#else
subsys_initcall(fbmem_init);
+#endif
+
+int fb_new_modelist(struct fb_info *info)
+{
+ struct fb_event event;
+ struct fb_var_screeninfo var = info->var;
+ struct list_head *pos, *n;
+ struct fb_modelist *modelist;
+ struct fb_videomode *m, mode;
+ int err = 1;
+
+ list_for_each_safe(pos, n, &info->modelist) {
+ modelist = list_entry(pos, struct fb_modelist, list);
+ m = &modelist->mode;
+ fb_videomode_to_var(&var, m);
+ var.activate = FB_ACTIVATE_TEST;
+ err = fb_set_var(info, &var);
+ fb_var_to_videomode(&mode, &var);
+ if (err || !fb_mode_is_equal(m, &mode)) {
+ list_del(pos);
+ kfree(pos);
+ }
+ }
+
+ err = 1;
+
+ if (!list_empty(&info->modelist)) {
+ event.info = info;
+ err = notifier_call_chain(&fb_notifier_list,
+ FB_EVENT_NEW_MODELIST,
+ &event);
+ }
+
+ return err;
+}
static char *video_options[FB_MAX];
static int ofonly;
/**
* fb_get_options - get kernel boot parameters
- * @name - framebuffer name as it would appear in
- * the boot parameter line
- * (video=<name>:<options>)
+ * @name: framebuffer name as it would appear in
+ * the boot parameter line
+ * (video=<name>:<options>)
+ * @option: the option will be stored here
*
* NOTE: Needed to maintain backwards compatibility
*/
@@ -1248,6 +1297,9 @@ int fb_get_options(char *name, char **option)
return retval;
}
+
+extern const char *global_mode_option;
+
/**
* video_setup - process command line options
* @options: string of options
@@ -1261,9 +1313,6 @@ int fb_get_options(char *name, char **option)
* Returns zero.
*
*/
-
-extern const char *global_mode_option;
-
int __init video_setup(char *options)
{
int i, global = 0;
@@ -1317,5 +1366,6 @@ EXPORT_SYMBOL(fb_set_suspend);
EXPORT_SYMBOL(fb_register_client);
EXPORT_SYMBOL(fb_unregister_client);
EXPORT_SYMBOL(fb_get_options);
+EXPORT_SYMBOL(fb_new_modelist);
MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbmon.c b/drivers/video/fbmon.c
index 520d9924173ec..978def0135879 100644
--- a/drivers/video/fbmon.c
+++ b/drivers/video/fbmon.c
@@ -74,10 +74,9 @@ static struct broken_edid brokendb[] = {
},
};
-const unsigned char edid_v1_header[] = { 0x00, 0xff, 0xff, 0xff,
+static const unsigned char edid_v1_header[] = { 0x00, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x00
};
-const unsigned char edid_v1_descriptor_flag[] = { 0x00, 0x00 };
static void copy_string(unsigned char *c, unsigned char *s)
{
@@ -518,7 +517,7 @@ static void get_detailed_timing(unsigned char *block,
* This function builds a mode database using the contents of the EDID
* data
*/
-struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize)
+static struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize)
{
struct fb_videomode *mode, *m;
unsigned char *block;
@@ -589,11 +588,10 @@ struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize)
*/
void fb_destroy_modedb(struct fb_videomode *modedb)
{
- if (modedb)
- kfree(modedb);
+ kfree(modedb);
}
-int fb_get_monitor_limits(unsigned char *edid, struct fb_monspecs *specs)
+static int fb_get_monitor_limits(unsigned char *edid, struct fb_monspecs *specs)
{
int i, retval = 1;
unsigned char *block;
@@ -872,18 +870,6 @@ void fb_edid_to_monspecs(unsigned char *edid, struct fb_monspecs *specs)
DPRINTK("========================================\n");
}
-char *get_EDID_from_firmware(struct device *dev)
-{
- unsigned char *pedid = NULL;
-
-#if defined(CONFIG_EDID_FIRMWARE) && defined(CONFIG_X86)
- pedid = edid_info.dummy;
- if (!pedid)
- return NULL;
-#endif
- return pedid;
-}
-
/*
* VESA Generalized Timing Formula (GTF)
*/
@@ -1193,21 +1179,9 @@ void fb_edid_to_monspecs(unsigned char *edid, struct fb_monspecs *specs)
{
specs = NULL;
}
-char *get_EDID_from_firmware(struct device *dev)
-{
- return NULL;
-}
-struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize)
-{
- return NULL;
-}
void fb_destroy_modedb(struct fb_videomode *modedb)
{
}
-int fb_get_monitor_limits(unsigned char *edid, struct fb_monspecs *specs)
-{
- return 1;
-}
int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var,
struct fb_info *info)
{
@@ -1278,10 +1252,7 @@ int fb_validate_mode(const struct fb_var_screeninfo *var, struct fb_info *info)
EXPORT_SYMBOL(fb_parse_edid);
EXPORT_SYMBOL(fb_edid_to_monspecs);
-EXPORT_SYMBOL(get_EDID_from_firmware);
EXPORT_SYMBOL(fb_get_mode);
EXPORT_SYMBOL(fb_validate_mode);
-EXPORT_SYMBOL(fb_create_modedb);
EXPORT_SYMBOL(fb_destroy_modedb);
-EXPORT_SYMBOL(fb_get_monitor_limits);
diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c
index 4fec33dc8e318..2bdda4010b81d 100644
--- a/drivers/video/fbsysfs.c
+++ b/drivers/video/fbsysfs.c
@@ -17,6 +17,7 @@
#include <linux/kernel.h>
#include <linux/fb.h>
+#include <linux/console.h>
/**
* framebuffer_alloc - creates a new frame buffer info structure
@@ -57,6 +58,7 @@ struct fb_info *framebuffer_alloc(size_t size, struct device *dev)
#undef PADDING
#undef BYTES_PER_LONG
}
+EXPORT_SYMBOL(framebuffer_alloc);
/**
* framebuffer_release - marks the structure available for freeing
@@ -71,6 +73,317 @@ void framebuffer_release(struct fb_info *info)
{
kfree(info);
}
-
EXPORT_SYMBOL(framebuffer_release);
-EXPORT_SYMBOL(framebuffer_alloc);
+
+static int activate(struct fb_info *fb_info, struct fb_var_screeninfo *var)
+{
+ int err;
+
+ var->activate |= FB_ACTIVATE_FORCE;
+ acquire_console_sem();
+ fb_info->flags |= FBINFO_MISC_USEREVENT;
+ err = fb_set_var(fb_info, var);
+ fb_info->flags &= ~FBINFO_MISC_USEREVENT;
+ release_console_sem();
+ if (err)
+ return err;
+ return 0;
+}
+
+static int mode_string(char *buf, unsigned int offset,
+ const struct fb_videomode *mode)
+{
+ char m = 'U';
+ if (mode->flag & FB_MODE_IS_DETAILED)
+ m = 'D';
+ if (mode->flag & FB_MODE_IS_VESA)
+ m = 'V';
+ if (mode->flag & FB_MODE_IS_STANDARD)
+ m = 'S';
+ return snprintf(&buf[offset], PAGE_SIZE - offset, "%c:%dx%d-%d\n", m, mode->xres, mode->yres, mode->refresh);
+}
+
+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);
+ char mstr[100];
+ struct fb_var_screeninfo var;
+ struct fb_modelist *modelist;
+ struct fb_videomode *mode;
+ struct list_head *pos;
+ size_t i;
+ int err;
+
+ memset(&var, 0, sizeof(var));
+
+ list_for_each(pos, &fb_info->modelist) {
+ modelist = list_entry(pos, struct fb_modelist, list);
+ mode = &modelist->mode;
+ i = mode_string(mstr, 0, mode);
+ if (strncmp(mstr, buf, max(count, i)) == 0) {
+
+ var = fb_info->var;
+ fb_videomode_to_var(&var, mode);
+ if ((err = activate(fb_info, &var)))
+ return err;
+ fb_info->mode = mode;
+ return count;
+ }
+ }
+ return -EINVAL;
+}
+
+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);
+
+ if (!fb_info->mode)
+ return 0;
+
+ return mode_string(buf, 0, fb_info->mode);
+}
+
+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);
+ LIST_HEAD(old_list);
+ int i = count / sizeof(struct fb_videomode);
+
+ if (i * sizeof(struct fb_videomode) != count)
+ return -EINVAL;
+
+ acquire_console_sem();
+ list_splice(&fb_info->modelist, &old_list);
+ fb_videomode_to_modelist((struct fb_videomode *)buf, i,
+ &fb_info->modelist);
+ if (fb_new_modelist(fb_info)) {
+ fb_destroy_modelist(&fb_info->modelist);
+ list_splice(&old_list, &fb_info->modelist);
+ } else
+ fb_destroy_modelist(&old_list);
+
+ release_console_sem();
+
+ return 0;
+}
+
+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);
+ unsigned int i;
+ struct list_head *pos;
+ struct fb_modelist *modelist;
+ const struct fb_videomode *mode;
+
+ i = 0;
+ list_for_each(pos, &fb_info->modelist) {
+ modelist = list_entry(pos, struct fb_modelist, list);
+ mode = &modelist->mode;
+ i += mode_string(buf, i, mode);
+ }
+ return i;
+}
+
+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_var_screeninfo var;
+ char ** last = NULL;
+ int err;
+
+ var = fb_info->var;
+ var.bits_per_pixel = simple_strtoul(buf, last, 0);
+ if ((err = activate(fb_info, &var)))
+ return err;
+ return count;
+}
+
+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);
+ return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->var.bits_per_pixel);
+}
+
+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_var_screeninfo var;
+ char *last = NULL;
+ int err;
+
+ var = fb_info->var;
+ var.xres_virtual = simple_strtoul(buf, &last, 0);
+ last++;
+ if (last - buf >= count)
+ return -EINVAL;
+ var.yres_virtual = simple_strtoul(last, &last, 0);
+ printk(KERN_ERR "fb: xres %d yres %d\n", var.xres_virtual,
+ var.yres_virtual);
+
+ if ((err = activate(fb_info, &var)))
+ return err;
+ return count;
+}
+
+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);
+ return snprintf(buf, PAGE_SIZE, "%d,%d\n", fb_info->var.xres_virtual,
+ fb_info->var.xres_virtual);
+}
+
+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);
+ return 0;
+}
+
+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);
+ unsigned int offset = 0, i;
+
+ if (!fb_info->cmap.red || !fb_info->cmap.blue ||
+ fb_info->cmap.green || fb_info->cmap.transp)
+ return -EINVAL;
+
+ for (i = 0; i < fb_info->cmap.len; i++) {
+ offset += snprintf(buf, PAGE_SIZE - offset,
+ "%d,%d,%d,%d,%d\n", i + fb_info->cmap.start,
+ fb_info->cmap.red[i], fb_info->cmap.blue[i],
+ fb_info->cmap.green[i],
+ fb_info->cmap.transp[i]);
+ }
+ return offset;
+}
+
+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);
+ char *last = NULL;
+ int err;
+
+ acquire_console_sem();
+ fb_info->flags |= FBINFO_MISC_USEREVENT;
+ err = fb_blank(fb_info, simple_strtoul(buf, &last, 0));
+ fb_info->flags &= ~FBINFO_MISC_USEREVENT;
+ release_console_sem();
+ if (err < 0)
+ return err;
+ return count;
+}
+
+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);
+ 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);
+ 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);
+ 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);
+ 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);
+ 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_var_screeninfo var;
+ char *last = NULL;
+ int err;
+
+ var = fb_info->var;
+ var.xoffset = simple_strtoul(buf, &last, 0);
+ last++;
+ if (last - buf >= count)
+ return -EINVAL;
+ var.yoffset = simple_strtoul(last, &last, 0);
+
+ acquire_console_sem();
+ err = fb_pan_display(fb_info, &var);
+ release_console_sem();
+
+ if (err < 0)
+ return err;
+ return count;
+}
+
+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);
+ return snprintf(buf, PAGE_SIZE, "%d,%d\n", fb_info->var.xoffset,
+ fb_info->var.xoffset);
+}
+
+struct class_device_attribute class_device_attrs[] = {
+ __ATTR(bits_per_pixel, S_IRUGO|S_IWUSR, show_bpp, store_bpp),
+ __ATTR(blank, S_IRUGO|S_IWUSR, show_blank, store_blank),
+ __ATTR(color_map, S_IRUGO|S_IWUSR, show_cmap, store_cmap),
+ __ATTR(console, S_IRUGO|S_IWUSR, show_console, store_console),
+ __ATTR(cursor, S_IRUGO|S_IWUSR, show_cursor, store_cursor),
+ __ATTR(mode, S_IRUGO|S_IWUSR, show_mode, store_mode),
+ __ATTR(modes, S_IRUGO|S_IWUSR, show_modes, store_modes),
+ __ATTR(pan, S_IRUGO|S_IWUSR, show_pan, store_pan),
+ __ATTR(virtual_size, S_IRUGO|S_IWUSR, show_virtual, store_virtual),
+};
+
+int fb_init_class_device(struct fb_info *fb_info)
+{
+ unsigned int i;
+ class_set_devdata(fb_info->class_device, fb_info);
+
+ for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++)
+ class_device_create_file(fb_info->class_device,
+ &class_device_attrs[i]);
+ return 0;
+}
+
+void fb_cleanup_class_device(struct fb_info *fb_info)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++)
+ class_device_remove_file(fb_info->class_device,
+ &class_device_attrs[i]);
+}
+
+
diff --git a/drivers/video/geode/Kconfig b/drivers/video/geode/Kconfig
new file mode 100644
index 0000000000000..b075fd02de311
--- /dev/null
+++ b/drivers/video/geode/Kconfig
@@ -0,0 +1,29 @@
+#
+# Geode family framebuffer configuration
+#
+config FB_GEODE
+ bool "AMD Geode family framebuffer support (EXPERIMENTAL)"
+ default n
+ depends on FB && EXPERIMENTAL && X86
+ ---help---
+ Say 'Y' here to allow you to select framebuffer drivers for
+ the AMD Geode family of processors.
+
+config FB_GEODE_GX1
+ tristate "AMD Geode GX1 framebuffer support (EXPERIMENTAL)"
+ default n
+ depends on FB_GEODE && EXPERIMENTAL
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
+ ---help---
+ Framebuffer driver for the display controller integrated into the
+ AMD Geode GX1 processor.
+
+ This driver is also available as a module ( = code which can be
+ inserted and removed from the running kernel whenever you want). The
+ module will be called gx1fb. If you want to compile it as a module,
+ say M here and read <file:Documentation/modules.txt>.
+
+ If unsure, say N.
diff --git a/drivers/video/geode/Makefile b/drivers/video/geode/Makefile
new file mode 100644
index 0000000000000..13ad501ea990c
--- /dev/null
+++ b/drivers/video/geode/Makefile
@@ -0,0 +1,5 @@
+# Makefile for the Geode family framebuffer drivers
+
+obj-$(CONFIG_FB_GEODE_GX1) += gx1fb.o
+
+gx1fb-objs := gx1fb_core.o display_gx1.o video_cs5530.o
diff --git a/drivers/video/geode/display_gx1.c b/drivers/video/geode/display_gx1.c
new file mode 100644
index 0000000000000..f4983879fcc4b
--- /dev/null
+++ b/drivers/video/geode/display_gx1.c
@@ -0,0 +1,214 @@
+/*
+ * drivers/video/geode/display_gx1.c
+ * -- Geode GX1 display controller
+ *
+ * Copyright (C) 2005 Arcom Control Systems Ltd.
+ *
+ * Based on AMD's original 2.4 driver:
+ * Copyright (C) 2004 Advanced Micro Devices, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#include <linux/spinlock.h>
+#include <linux/fb.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+#include <asm/div64.h>
+#include <asm/delay.h>
+
+#include "geodefb.h"
+#include "display_gx1.h"
+
+static spinlock_t gx1_conf_reg_lock = SPIN_LOCK_UNLOCKED;
+
+static u8 gx1_read_conf_reg(u8 reg)
+{
+ u8 val, ccr3;
+ unsigned long flags;
+
+ spin_lock_irqsave(&gx1_conf_reg_lock, flags);
+
+ outb(CONFIG_CCR3, 0x22);
+ ccr3 = inb(0x23);
+ outb(CONFIG_CCR3, 0x22);
+ outb(ccr3 | CONFIG_CCR3_MAPEN, 0x23);
+ outb(reg, 0x22);
+ val = inb(0x23);
+ outb(CONFIG_CCR3, 0x22);
+ outb(ccr3, 0x23);
+
+ spin_unlock_irqrestore(&gx1_conf_reg_lock, flags);
+
+ return val;
+}
+
+unsigned gx1_gx_base(void)
+{
+ return (gx1_read_conf_reg(CONFIG_GCR) & 0x03) << 30;
+}
+
+int gx1_frame_buffer_size(void)
+{
+ void __iomem *mc_regs;
+ u32 bank_cfg;
+ int d;
+ unsigned dram_size = 0, fb_base;
+
+ mc_regs = ioremap(gx1_gx_base() + 0x8400, 0x100);
+ if (!mc_regs)
+ return -ENOMEM;
+
+
+ /* Calculate the total size of both DIMM0 and DIMM1. */
+ bank_cfg = readl(mc_regs + MC_BANK_CFG);
+
+ for (d = 0; d < 2; d++) {
+ if ((bank_cfg & MC_BCFG_DIMM0_PG_SZ_MASK) != MC_BCFG_DIMM0_PG_SZ_NO_DIMM)
+ dram_size += 0x400000 << ((bank_cfg & MC_BCFG_DIMM0_SZ_MASK) >> 8);
+ bank_cfg >>= 16; /* look at DIMM1 next */
+ }
+
+ fb_base = (readl(mc_regs + MC_GBASE_ADD) & MC_GADD_GBADD_MASK) << 19;
+
+ iounmap(mc_regs);
+
+ return dram_size - fb_base;
+}
+
+static void gx1_set_mode(struct fb_info *info)
+{
+ struct geodefb_par *par = info->par;
+ u32 gcfg, tcfg, ocfg, dclk_div, val;
+ int hactive, hblankstart, hsyncstart, hsyncend, hblankend, htotal;
+ int vactive, vblankstart, vsyncstart, vsyncend, vblankend, vtotal;
+
+ /* Unlock the display controller registers. */
+ readl(par->dc_regs + DC_UNLOCK);
+ writel(DC_UNLOCK_CODE, par->dc_regs + DC_UNLOCK);
+
+ gcfg = readl(par->dc_regs + DC_GENERAL_CFG);
+ tcfg = readl(par->dc_regs + DC_TIMING_CFG);
+
+ /* Blank the display and disable the timing generator. */
+ tcfg &= ~(DC_TCFG_BLKE | DC_TCFG_TGEN);
+ writel(tcfg, par->dc_regs + DC_TIMING_CFG);
+
+ /* Wait for pending memory requests before disabling the FIFO load. */
+ udelay(100);
+
+ /* Disable FIFO load and compression. */
+ gcfg &= ~(DC_GCFG_DFLE | DC_GCFG_CMPE | DC_GCFG_DECE);
+ writel(gcfg, par->dc_regs + DC_GENERAL_CFG);
+
+ /* Setup DCLK and its divisor. */
+ gcfg &= ~DC_GCFG_DCLK_MASK;
+ writel(gcfg, par->dc_regs + DC_GENERAL_CFG);
+
+ par->vid_ops->set_dclk(info);
+
+ dclk_div = DC_GCFG_DCLK_DIV_1; /* FIXME: may need to divide DCLK by 2 sometimes? */
+ gcfg |= dclk_div;
+ writel(gcfg, par->dc_regs + DC_GENERAL_CFG);
+
+ /* Wait for the clock generatation to settle. This is needed since
+ * some of the register writes that follow require that clock to be
+ * present. */
+ udelay(1000); /* FIXME: seems a little long */
+
+ /*
+ * Setup new mode.
+ */
+
+ /* Clear all unused feature bits. */
+ gcfg = DC_GCFG_VRDY | dclk_div;
+
+ /* Set FIFO priority (default 6/5) and enable. */
+ /* FIXME: increase fifo priority for 1280x1024 modes? */
+ gcfg |= (6 << DC_GCFG_DFHPEL_POS) | (5 << DC_GCFG_DFHPSL_POS) | DC_GCFG_DFLE;
+
+ /* FIXME: Set pixel and line double bits if necessary. */
+
+ /* Framebuffer start offset. */
+ writel(0, par->dc_regs + DC_FB_ST_OFFSET);
+
+ /* Line delta and line buffer length. */
+ writel(info->fix.line_length >> 2, par->dc_regs + DC_LINE_DELTA);
+ writel(((info->var.xres * info->var.bits_per_pixel/8) >> 3) + 2,
+ par->dc_regs + DC_BUF_SIZE);
+
+ /* Output configuration. Enable panel data, set pixel format. */
+ ocfg = DC_OCFG_PCKE | DC_OCFG_PDEL | DC_OCFG_PDEH;
+ if (info->var.bits_per_pixel == 8) ocfg |= DC_OCFG_8BPP;
+
+ /* Enable timing generator, sync and FP data. */
+ tcfg = DC_TCFG_FPPE | DC_TCFG_HSYE | DC_TCFG_VSYE | DC_TCFG_BLKE
+ | DC_TCFG_TGEN;
+
+ /* Horizontal and vertical timings. */
+ hactive = info->var.xres;
+ hblankstart = hactive;
+ hsyncstart = hblankstart + info->var.right_margin;
+ hsyncend = hsyncstart + info->var.hsync_len;
+ hblankend = hsyncend + info->var.left_margin;
+ htotal = hblankend;
+
+ vactive = info->var.yres;
+ vblankstart = vactive;
+ vsyncstart = vblankstart + info->var.lower_margin;
+ vsyncend = vsyncstart + info->var.vsync_len;
+ vblankend = vsyncend + info->var.upper_margin;
+ vtotal = vblankend;
+
+ val = (hactive - 1) | ((htotal - 1) << 16);
+ writel(val, par->dc_regs + DC_H_TIMING_1);
+ val = (hblankstart - 1) | ((hblankend - 1) << 16);
+ writel(val, par->dc_regs + DC_H_TIMING_2);
+ val = (hsyncstart - 1) | ((hsyncend - 1) << 16);
+ writel(val, par->dc_regs + DC_H_TIMING_3);
+ writel(val, par->dc_regs + DC_FP_H_TIMING);
+ val = (vactive - 1) | ((vtotal - 1) << 16);
+ writel(val, par->dc_regs + DC_V_TIMING_1);
+ val = (vblankstart - 1) | ((vblankend - 1) << 16);
+ writel(val, par->dc_regs + DC_V_TIMING_2);
+ val = (vsyncstart - 1) | ((vsyncend - 1) << 16);
+ writel(val, par->dc_regs + DC_V_TIMING_3);
+ val = (vsyncstart - 2) | ((vsyncend - 2) << 16);
+ writel(val, par->dc_regs + DC_FP_V_TIMING);
+
+ /* Write final register values. */
+ writel(ocfg, par->dc_regs + DC_OUTPUT_CFG);
+ writel(tcfg, par->dc_regs + DC_TIMING_CFG);
+ udelay(1000); /* delay after TIMING_CFG. FIXME: perhaps a little long */
+ writel(gcfg, par->dc_regs + DC_GENERAL_CFG);
+
+ par->vid_ops->configure_display(info);
+
+ /* Relock display controller registers */
+ writel(0, par->dc_regs + DC_UNLOCK);
+
+ /* FIXME: write line_length and bpp to Graphics Pipeline GP_BLT_STATUS
+ * register. */
+}
+
+static void gx1_set_hw_palette_reg(struct fb_info *info, unsigned regno,
+ unsigned red, unsigned green, unsigned blue)
+{
+ struct geodefb_par *par = info->par;
+ int val;
+
+ /* Hardware palette is in RGB 6-6-6 format. */
+ val = (red << 2) & 0x3f000;
+ val |= (green >> 4) & 0x00fc0;
+ val |= (blue >> 10) & 0x0003f;
+
+ writel(regno, par->dc_regs + DC_PAL_ADDRESS);
+ writel(val, par->dc_regs + DC_PAL_DATA);
+}
+
+struct geode_dc_ops gx1_dc_ops = {
+ .set_mode = gx1_set_mode,
+ .set_palette_reg = gx1_set_hw_palette_reg,
+};
diff --git a/drivers/video/geode/display_gx1.h b/drivers/video/geode/display_gx1.h
new file mode 100644
index 0000000000000..671c05558c795
--- /dev/null
+++ b/drivers/video/geode/display_gx1.h
@@ -0,0 +1,154 @@
+/*
+ * drivers/video/geode/display_gx1.h
+ * -- Geode GX1 display controller
+ *
+ * Copyright (C) 2005 Arcom Control Systems Ltd.
+ *
+ * Based on AMD's original 2.4 driver:
+ * Copyright (C) 2004 Advanced Micro Devices, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#ifndef __DISPLAY_GX1_H__
+#define __DISPLAY_GX1_H__
+
+unsigned gx1_gx_base(void);
+int gx1_frame_buffer_size(void);
+
+extern struct geode_dc_ops gx1_dc_ops;
+
+/* GX1 configuration I/O registers */
+
+#define CONFIG_CCR3 0xc3
+# define CONFIG_CCR3_MAPEN 0x10
+#define CONFIG_GCR 0xb8
+
+/* Memory controller registers */
+
+#define MC_BANK_CFG 0x08
+# define MC_BCFG_DIMM0_SZ_MASK 0x00000700
+# define MC_BCFG_DIMM0_PG_SZ_MASK 0x00000070
+# define MC_BCFG_DIMM0_PG_SZ_NO_DIMM 0x00000070
+
+#define MC_GBASE_ADD 0x14
+# define MC_GADD_GBADD_MASK 0x000003ff
+
+/* Display controller registers */
+
+#define DC_PAL_ADDRESS 0x70
+#define DC_PAL_DATA 0x74
+
+#define DC_UNLOCK 0x00
+# define DC_UNLOCK_CODE 0x00004758
+
+#define DC_GENERAL_CFG 0x04
+# define DC_GCFG_DFLE 0x00000001
+# define DC_GCFG_CURE 0x00000002
+# define DC_GCFG_VCLK_DIV 0x00000004
+# define DC_GCFG_PLNO 0x00000004
+# define DC_GCFG_PPC 0x00000008
+# define DC_GCFG_CMPE 0x00000010
+# define DC_GCFG_DECE 0x00000020
+# define DC_GCFG_DCLK_MASK 0x000000C0
+# define DC_GCFG_DCLK_DIV_1 0x00000080
+# define DC_GCFG_DFHPSL_MASK 0x00000F00
+# define DC_GCFG_DFHPSL_POS 8
+# define DC_GCFG_DFHPEL_MASK 0x0000F000
+# define DC_GCFG_DFHPEL_POS 12
+# define DC_GCFG_CIM_MASK 0x00030000
+# define DC_GCFG_CIM_POS 16
+# define DC_GCFG_FDTY 0x00040000
+# define DC_GCFG_RTPM 0x00080000
+# define DC_GCFG_DAC_RS_MASK 0x00700000
+# define DC_GCFG_DAC_RS_POS 20
+# define DC_GCFG_CKWR 0x00800000
+# define DC_GCFG_LDBL 0x01000000
+# define DC_GCFG_DIAG 0x02000000
+# define DC_GCFG_CH4S 0x04000000
+# define DC_GCFG_SSLC 0x08000000
+# define DC_GCFG_VIDE 0x10000000
+# define DC_GCFG_VRDY 0x20000000
+# define DC_GCFG_DPCK 0x40000000
+# define DC_GCFG_DDCK 0x80000000
+
+#define DC_TIMING_CFG 0x08
+# define DC_TCFG_FPPE 0x00000001
+# define DC_TCFG_HSYE 0x00000002
+# define DC_TCFG_VSYE 0x00000004
+# define DC_TCFG_BLKE 0x00000008
+# define DC_TCFG_DDCK 0x00000010
+# define DC_TCFG_TGEN 0x00000020
+# define DC_TCFG_VIEN 0x00000040
+# define DC_TCFG_BLNK 0x00000080
+# define DC_TCFG_CHSP 0x00000100
+# define DC_TCFG_CVSP 0x00000200
+# define DC_TCFG_FHSP 0x00000400
+# define DC_TCFG_FVSP 0x00000800
+# define DC_TCFG_FCEN 0x00001000
+# define DC_TCFG_CDCE 0x00002000
+# define DC_TCFG_PLNR 0x00002000
+# define DC_TCFG_INTL 0x00004000
+# define DC_TCFG_PXDB 0x00008000
+# define DC_TCFG_BKRT 0x00010000
+# define DC_TCFG_PSD_MASK 0x000E0000
+# define DC_TCFG_PSD_POS 17
+# define DC_TCFG_DDCI 0x08000000
+# define DC_TCFG_SENS 0x10000000
+# define DC_TCFG_DNA 0x20000000
+# define DC_TCFG_VNA 0x40000000
+# define DC_TCFG_VINT 0x80000000
+
+#define DC_OUTPUT_CFG 0x0C
+# define DC_OCFG_8BPP 0x00000001
+# define DC_OCFG_555 0x00000002
+# define DC_OCFG_PCKE 0x00000004
+# define DC_OCFG_FRME 0x00000008
+# define DC_OCFG_DITE 0x00000010
+# define DC_OCFG_2PXE 0x00000020
+# define DC_OCFG_2XCK 0x00000040
+# define DC_OCFG_2IND 0x00000080
+# define DC_OCFG_34ADD 0x00000100
+# define DC_OCFG_FRMS 0x00000200
+# define DC_OCFG_CKSL 0x00000400
+# define DC_OCFG_PRMP 0x00000800
+# define DC_OCFG_PDEL 0x00001000
+# define DC_OCFG_PDEH 0x00002000
+# define DC_OCFG_CFRW 0x00004000
+# define DC_OCFG_DIAG 0x00008000
+
+#define DC_FB_ST_OFFSET 0x10
+#define DC_CB_ST_OFFSET 0x14
+#define DC_CURS_ST_OFFSET 0x18
+#define DC_ICON_ST_OFFSET 0x1C
+#define DC_VID_ST_OFFSET 0x20
+#define DC_LINE_DELTA 0x24
+#define DC_BUF_SIZE 0x28
+
+#define DC_H_TIMING_1 0x30
+#define DC_H_TIMING_2 0x34
+#define DC_H_TIMING_3 0x38
+#define DC_FP_H_TIMING 0x3C
+
+#define DC_V_TIMING_1 0x40
+#define DC_V_TIMING_2 0x44
+#define DC_V_TIMING_3 0x48
+#define DC_FP_V_TIMING 0x4C
+
+#define DC_CURSOR_X 0x50
+#define DC_ICON_X 0x54
+#define DC_V_LINE_CNT 0x54
+#define DC_CURSOR_Y 0x58
+#define DC_ICON_Y 0x5C
+#define DC_SS_LINE_CMP 0x5C
+#define DC_CURSOR_COLOR 0x60
+#define DC_ICON_COLOR 0x64
+#define DC_BORDER_COLOR 0x68
+#define DC_PAL_ADDRESS 0x70
+#define DC_PAL_DATA 0x74
+#define DC_DFIFO_DIAG 0x78
+#define DC_CFIFO_DIAG 0x7C
+
+#endif /* !__DISPLAY_GX1_H__ */
diff --git a/drivers/video/geode/geodefb.h b/drivers/video/geode/geodefb.h
new file mode 100644
index 0000000000000..b7bac0a526b38
--- /dev/null
+++ b/drivers/video/geode/geodefb.h
@@ -0,0 +1,39 @@
+/*
+ * drivers/video/geode/geodefb.h
+ * -- Geode framebuffer driver
+ *
+ * Copyright (C) 2005 Arcom Control Systems Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#ifndef __GEODEFB_H__
+#define __GEODEFB_H__
+
+struct geodefb_info;
+
+struct geode_dc_ops {
+ void (*set_mode)(struct fb_info *);
+ void (*set_palette_reg)(struct fb_info *, unsigned, unsigned, unsigned, unsigned);
+};
+
+struct geode_vid_ops {
+ void (*set_dclk)(struct fb_info *);
+ void (*configure_display)(struct fb_info *);
+ int (*blank_display)(struct fb_info *, int blank_mode);
+};
+
+struct geodefb_par {
+ int enable_crt;
+ int panel_x; /* dimensions of an attached flat panel, non-zero => enable panel */
+ int panel_y;
+ struct pci_dev *vid_dev;
+ void __iomem *dc_regs;
+ void __iomem *vid_regs;
+ struct geode_dc_ops *dc_ops;
+ struct geode_vid_ops *vid_ops;
+};
+
+#endif /* !__GEODEFB_H__ */
diff --git a/drivers/video/geode/gx1fb_core.c b/drivers/video/geode/gx1fb_core.c
new file mode 100644
index 0000000000000..83830d24bcdaa
--- /dev/null
+++ b/drivers/video/geode/gx1fb_core.c
@@ -0,0 +1,359 @@
+/*
+ * drivers/video/geode/gx1fb_core.c
+ * -- Geode GX1 framebuffer driver
+ *
+ * Copyright (C) 2005 Arcom Control Systems Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+
+#include "geodefb.h"
+#include "display_gx1.h"
+#include "video_cs5530.h"
+
+static char mode_option[32] = "640x480-16@60";
+static int crt_option = 1;
+static char panel_option[32] = "";
+
+static int gx1_line_delta(int xres, int bpp)
+{
+ int line_delta = xres * (bpp >> 3);
+
+ if (line_delta > 2048)
+ line_delta = 4096;
+ else if (line_delta > 1024)
+ line_delta = 2048;
+ else
+ line_delta = 1024;
+ return line_delta;
+}
+
+static int gx1fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+ struct geodefb_par *par = info->par;
+
+ printk(KERN_DEBUG "%s()\n", __FUNCTION__);
+
+ /* Maximum resolution is 1280x1024. */
+ if (var->xres > 1280 || var->yres > 1024)
+ return -EINVAL;
+
+ if (par->panel_x && (var->xres > par->panel_x || var->yres > par->panel_y))
+ return -EINVAL;
+
+ /* Only 16 bpp and 8 bpp is supported by the hardware. */
+ if (var->bits_per_pixel == 16) {
+ var->red.offset = 11; var->red.length = 5;
+ var->green.offset = 5; var->green.length = 6;
+ var->blue.offset = 0; var->blue.length = 5;
+ var->transp.offset = 0; var->transp.length = 0;
+ } else if (var->bits_per_pixel == 8) {
+ var->red.offset = 0; var->red.length = 8;
+ var->green.offset = 0; var->green.length = 8;
+ var->blue.offset = 0; var->blue.length = 8;
+ var->transp.offset = 0; var->transp.length = 0;
+ } else
+ return -EINVAL;
+
+ /* Enough video memory? */
+ if (gx1_line_delta(var->xres, var->bits_per_pixel) * var->yres > info->fix.smem_len)
+ return -EINVAL;
+
+ /* FIXME: Check timing parameters here? */
+
+ return 0;
+}
+
+static int gx1fb_set_par(struct fb_info *info)
+{
+ struct geodefb_par *par = info->par;
+
+ if (info->var.bits_per_pixel == 16) {
+ info->fix.visual = FB_VISUAL_TRUECOLOR;
+ fb_dealloc_cmap(&info->cmap);
+ } else {
+ info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+ fb_alloc_cmap(&info->cmap, 1<<info->var.bits_per_pixel, 0);
+ }
+
+ info->fix.line_length = gx1_line_delta(info->var.xres, info->var.bits_per_pixel);
+
+ par->dc_ops->set_mode(info);
+
+ return 0;
+}
+
+static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf)
+{
+ chan &= 0xffff;
+ chan >>= 16 - bf->length;
+ return chan << bf->offset;
+}
+
+static int gx1fb_setcolreg(unsigned regno, unsigned red, unsigned green,
+ unsigned blue, unsigned transp,
+ struct fb_info *info)
+{
+ struct geodefb_par *par = info->par;
+
+ if (info->var.grayscale) {
+ /* grayscale = 0.30*R + 0.59*G + 0.11*B */
+ red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
+ }
+
+ /* Truecolor has hardware independent palette */
+ if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
+ u32 *pal = info->pseudo_palette;
+ u32 v;
+
+ if (regno >= 16)
+ return -EINVAL;
+
+ v = chan_to_field(red, &info->var.red);
+ v |= chan_to_field(green, &info->var.green);
+ v |= chan_to_field(blue, &info->var.blue);
+
+ pal[regno] = v;
+ } else {
+ if (regno >= 256)
+ return -EINVAL;
+
+ par->dc_ops->set_palette_reg(info, regno, red, green, blue);
+ }
+
+ return 0;
+}
+
+static int gx1fb_blank(int blank_mode, struct fb_info *info)
+{
+ struct geodefb_par *par = info->par;
+
+ return par->vid_ops->blank_display(info, blank_mode);
+}
+
+static int __init gx1fb_map_video_memory(struct fb_info *info)
+{
+ struct geodefb_par *par = info->par;
+ unsigned gx_base;
+ int fb_len;
+
+ gx_base = gx1_gx_base();
+ if (!gx_base)
+ return -ENODEV;
+
+ par->vid_dev = pci_get_device(PCI_VENDOR_ID_CYRIX,
+ PCI_DEVICE_ID_CYRIX_5530_VIDEO, NULL);
+ if (!par->vid_dev)
+ return -ENODEV;
+
+ par->vid_regs = ioremap(pci_resource_start(par->vid_dev, 1),
+ pci_resource_len(par->vid_dev, 1));
+ if (!par->vid_regs)
+ return -ENOMEM;
+
+ par->dc_regs = ioremap(gx_base + 0x8300, 0x100);
+ if (!par->dc_regs)
+ return -ENOMEM;
+
+ info->fix.smem_start = gx_base + 0x800000;
+ if ((fb_len = gx1_frame_buffer_size()) < 0)
+ return -ENOMEM;
+ info->fix.smem_len = fb_len;
+ info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len);
+ if (!info->screen_base)
+ return -ENOMEM;
+
+ printk(KERN_INFO "%s: %d Kibyte of video memory at 0x%lx\n",
+ info->fix.id, info->fix.smem_len / 1024, info->fix.smem_start);
+
+ return 0;
+}
+
+static int parse_panel_option(struct fb_info *info)
+{
+ struct geodefb_par *par = info->par;
+
+ if (strcmp(panel_option, "") != 0) {
+ int x, y;
+ char *s;
+ x = simple_strtol(panel_option, &s, 10);
+ if (!x)
+ return -EINVAL;
+ y = simple_strtol(s + 1, NULL, 10);
+ if (!y)
+ return -EINVAL;
+ par->panel_x = x;
+ par->panel_y = y;
+ }
+ return 0;
+}
+
+static struct fb_ops gx1fb_ops = {
+ .owner = THIS_MODULE,
+ .fb_check_var = gx1fb_check_var,
+ .fb_set_par = gx1fb_set_par,
+ .fb_setcolreg = gx1fb_setcolreg,
+ .fb_blank = gx1fb_blank,
+ /* No HW acceleration for now. */
+ .fb_fillrect = cfb_fillrect,
+ .fb_copyarea = cfb_copyarea,
+ .fb_imageblit = cfb_imageblit,
+ .fb_cursor = soft_cursor,
+};
+
+static struct fb_info * __init gx1fb_init_fbinfo(void)
+{
+ struct fb_info *info;
+ struct geodefb_par *par;
+
+ /* Alloc enough space for the pseudo palette. */
+ info = framebuffer_alloc(sizeof(struct geodefb_par) + sizeof(u32) * 16, NULL);
+ if (!info)
+ return NULL;
+
+ par = info->par;
+
+ strcpy(info->fix.id, "GX1");
+
+ info->fix.type = FB_TYPE_PACKED_PIXELS;
+ info->fix.type_aux = 0;
+ info->fix.xpanstep = 0;
+ info->fix.ypanstep = 0;
+ info->fix.ywrapstep = 0;
+ info->fix.accel = FB_ACCEL_NONE;
+
+ info->var.nonstd = 0;
+ info->var.activate = FB_ACTIVATE_NOW;
+ info->var.height = -1;
+ info->var.width = -1;
+ info->var.accel_flags = 0;
+ info->var.vmode = FB_VMODE_NONINTERLACED;
+
+ info->fbops = &gx1fb_ops;
+ info->flags = FBINFO_DEFAULT;
+ info->node = -1;
+
+ info->pseudo_palette = (void *)par + sizeof(struct geodefb_par);
+
+ info->var.grayscale = 0;
+
+ /* CRT and panel options */
+ par->enable_crt = crt_option;
+ if (parse_panel_option(info) < 0)
+ printk(KERN_WARNING "%s: invalid 'panel' option -- disabling flat panel\n",
+ info->fix.id);
+ if (!par->panel_x)
+ par->enable_crt = 1; /* fall back to CRT if no panel is specified */
+
+ return info;
+}
+
+
+static struct fb_info *gx1fb_info;
+
+static int __init gx1fb_init(void)
+{
+ struct fb_info *info;
+ struct geodefb_par *par;
+ int ret;
+
+#ifndef MODULE
+ if (fb_get_options("gx1fb", NULL))
+ return -ENODEV;
+#endif
+
+ info = gx1fb_init_fbinfo();
+ if (!info)
+ return -ENOMEM;
+ gx1fb_info = info;
+
+ par = info->par;
+
+ /* GX1 display controller and CS5530 video device */
+ par->dc_ops = &gx1_dc_ops;
+ par->vid_ops = &cs5530_vid_ops;
+
+ if ((ret = gx1fb_map_video_memory(info)) < 0) {
+ printk(KERN_ERR "%s: gx1fb_map_video_memory() failed\n", info->fix.id);
+ goto err;
+ }
+
+ ret = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 16);
+ if (ret == 0 || ret == 4) {
+ printk(KERN_ERR "%s: could not find valid video mode\n", info->fix.id);
+ ret = -EINVAL;
+ goto err;
+ }
+
+ /* Clear the frame buffer of garbage. */
+ memset_io(info->screen_base, 0, info->fix.smem_len);
+
+ gx1fb_check_var(&info->var, info);
+ gx1fb_set_par(info);
+
+ if (register_framebuffer(info) < 0) {
+ ret = -EINVAL;
+ goto err;
+ }
+ printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, info->fix.id);
+ return 0;
+
+ err:
+ if (info->screen_base)
+ iounmap(info->screen_base);
+ if (par->vid_regs)
+ iounmap(par->vid_regs);
+ if (par->dc_regs)
+ iounmap(par->dc_regs);
+ if (par->vid_dev)
+ pci_dev_put(par->vid_dev);
+ if (info)
+ framebuffer_release(info);
+ return ret;
+}
+
+static void __exit gx1fb_cleanup(void)
+{
+ struct fb_info *info = gx1fb_info;
+ struct geodefb_par *par = gx1fb_info->par;
+
+ unregister_framebuffer(info);
+
+ iounmap((void __iomem *)info->screen_base);
+ iounmap(par->vid_regs);
+ iounmap(par->dc_regs);
+
+ pci_dev_put(par->vid_dev);
+
+ framebuffer_release(info);
+}
+
+module_init(gx1fb_init);
+module_exit(gx1fb_cleanup);
+
+module_param_string(mode, mode_option, sizeof(mode_option), 0444);
+MODULE_PARM_DESC(mode, "video mode (<x>x<y>[-<bpp>][@<refr>])");
+
+module_param_named(crt, crt_option, int, 0444);
+MODULE_PARM_DESC(crt, "enable CRT output. 0 = off, 1 = on (default)");
+
+module_param_string(panel, panel_option, sizeof(panel_option), 0444);
+MODULE_PARM_DESC(panel, "size of attached flat panel (<x>x<y>)");
+
+MODULE_DESCRIPTION("framebuffer driver for the AMD Geode GX1");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/geode/video_cs5530.c b/drivers/video/geode/video_cs5530.c
new file mode 100644
index 0000000000000..d3764acf8443f
--- /dev/null
+++ b/drivers/video/geode/video_cs5530.c
@@ -0,0 +1,195 @@
+/*
+ * drivers/video/geode/video_cs5530.c
+ * -- CS5530 video device
+ *
+ * Copyright (C) 2005 Arcom Control Systems Ltd.
+ *
+ * Based on AMD's original 2.4 driver:
+ * Copyright (C) 2004 Advanced Micro Devices, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#include <linux/fb.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+#include <asm/delay.h>
+
+#include "geodefb.h"
+#include "video_cs5530.h"
+
+/*
+ * CS5530 PLL table. This maps pixclocks to the appropriate PLL register
+ * value.
+ */
+struct cs5530_pll_entry {
+ long pixclock; /* ps */
+ u32 pll_value;
+};
+
+static const struct cs5530_pll_entry cs5530_pll_table[] = {
+ { 39721, 0x31C45801, }, /* 25.1750 MHz */
+ { 35308, 0x20E36802, }, /* 28.3220 */
+ { 31746, 0x33915801, }, /* 31.5000 */
+ { 27777, 0x31EC4801, }, /* 36.0000 */
+ { 26666, 0x21E22801, }, /* 37.5000 */
+ { 25000, 0x33088801, }, /* 40.0000 */
+ { 22271, 0x33E22801, }, /* 44.9000 */
+ { 20202, 0x336C4801, }, /* 49.5000 */
+ { 20000, 0x23088801, }, /* 50.0000 */
+ { 19860, 0x23088801, }, /* 50.3500 */
+ { 18518, 0x3708A801, }, /* 54.0000 */
+ { 17777, 0x23E36802, }, /* 56.2500 */
+ { 17733, 0x23E36802, }, /* 56.3916 */
+ { 17653, 0x23E36802, }, /* 56.6444 */
+ { 16949, 0x37C45801, }, /* 59.0000 */
+ { 15873, 0x23EC4801, }, /* 63.0000 */
+ { 15384, 0x37911801, }, /* 65.0000 */
+ { 14814, 0x37963803, }, /* 67.5000 */
+ { 14124, 0x37058803, }, /* 70.8000 */
+ { 13888, 0x3710C805, }, /* 72.0000 */
+ { 13333, 0x37E22801, }, /* 75.0000 */
+ { 12698, 0x27915801, }, /* 78.7500 */
+ { 12500, 0x37D8D802, }, /* 80.0000 */
+ { 11135, 0x27588802, }, /* 89.8000 */
+ { 10582, 0x27EC4802, }, /* 94.5000 */
+ { 10101, 0x27AC6803, }, /* 99.0000 */
+ { 10000, 0x27088801, }, /* 100.0000 */
+ { 9259, 0x2710C805, }, /* 108.0000 */
+ { 8888, 0x27E36802, }, /* 112.5000 */
+ { 7692, 0x27C58803, }, /* 130.0000 */
+ { 7407, 0x27316803, }, /* 135.0000 */
+ { 6349, 0x2F915801, }, /* 157.5000 */
+ { 6172, 0x2F08A801, }, /* 162.0000 */
+ { 5714, 0x2FB11802, }, /* 175.0000 */
+ { 5291, 0x2FEC4802, }, /* 189.0000 */
+ { 4950, 0x2F963803, }, /* 202.0000 */
+ { 4310, 0x2FB1B802, }, /* 232.0000 */
+};
+
+#define NUM_CS5530_FREQUENCIES sizeof(cs5530_pll_table)/sizeof(struct cs5530_pll_entry)
+
+static void cs5530_set_dclk_frequency(struct fb_info *info)
+{
+ struct geodefb_par *par = info->par;
+ int i;
+ u32 value;
+ long min, diff;
+
+ /* Search the table for the closest pixclock. */
+ value = cs5530_pll_table[0].pll_value;
+ min = cs5530_pll_table[0].pixclock - info->var.pixclock;
+ if (min < 0) min = -min;
+ for (i = 1; i < NUM_CS5530_FREQUENCIES; i++) {
+ diff = cs5530_pll_table[i].pixclock - info->var.pixclock;
+ if (diff < 0L) diff = -diff;
+ if (diff < min) {
+ min = diff;
+ value = cs5530_pll_table[i].pll_value;
+ }
+ }
+
+ writel(value, par->vid_regs + CS5530_DOT_CLK_CONFIG);
+ writel(value | 0x80000100, par->vid_regs + CS5530_DOT_CLK_CONFIG); /* set reset and bypass */
+ udelay(500); /* wait for PLL to settle */
+ writel(value & 0x7FFFFFFF, par->vid_regs + CS5530_DOT_CLK_CONFIG); /* clear reset */
+ writel(value & 0x7FFFFEFF, par->vid_regs + CS5530_DOT_CLK_CONFIG); /* clear bypass */
+}
+
+static void cs5530_configure_display(struct fb_info *info)
+{
+ struct geodefb_par *par = info->par;
+ u32 dcfg;
+
+ dcfg = readl(par->vid_regs + CS5530_DISPLAY_CONFIG);
+
+ /* Clear bits from existing mode. */
+ dcfg &= ~(CS5530_DCFG_CRT_SYNC_SKW_MASK | CS5530_DCFG_PWR_SEQ_DLY_MASK
+ | CS5530_DCFG_CRT_HSYNC_POL | CS5530_DCFG_CRT_VSYNC_POL
+ | CS5530_DCFG_FP_PWR_EN | CS5530_DCFG_FP_DATA_EN
+ | CS5530_DCFG_DAC_PWR_EN | CS5530_DCFG_VSYNC_EN
+ | CS5530_DCFG_HSYNC_EN);
+
+ /* Set default sync skew and power sequence delays. */
+ dcfg |= (CS5530_DCFG_CRT_SYNC_SKW_INIT | CS5530_DCFG_PWR_SEQ_DLY_INIT
+ | CS5530_DCFG_GV_PAL_BYP);
+
+ /* Enable DACs, hsync and vsync for CRTs */
+ if (par->enable_crt) {
+ dcfg |= CS5530_DCFG_DAC_PWR_EN;
+ dcfg |= CS5530_DCFG_HSYNC_EN | CS5530_DCFG_VSYNC_EN;
+ }
+ /* Enable panel power and data if using a flat panel. */
+ if (par->panel_x > 0) {
+ dcfg |= CS5530_DCFG_FP_PWR_EN;
+ dcfg |= CS5530_DCFG_FP_DATA_EN;
+ }
+
+ /* Sync polarities. */
+ if (info->var.sync & FB_SYNC_HOR_HIGH_ACT)
+ dcfg |= CS5530_DCFG_CRT_HSYNC_POL;
+ if (info->var.sync & FB_SYNC_VERT_HIGH_ACT)
+ dcfg |= CS5530_DCFG_CRT_VSYNC_POL;
+
+ writel(dcfg, par->vid_regs + CS5530_DISPLAY_CONFIG);
+}
+
+static int cs5530_blank_display(struct fb_info *info, int blank_mode)
+{
+ struct geodefb_par *par = info->par;
+ u32 dcfg;
+ int blank, hsync, vsync;
+
+ switch (blank_mode) {
+ case FB_BLANK_UNBLANK:
+ blank = 0; hsync = 1; vsync = 1;
+ break;
+ case FB_BLANK_NORMAL:
+ blank = 1; hsync = 1; vsync = 1;
+ break;
+ case FB_BLANK_VSYNC_SUSPEND:
+ blank = 1; hsync = 1; vsync = 0;
+ break;
+ case FB_BLANK_HSYNC_SUSPEND:
+ blank = 1; hsync = 0; vsync = 1;
+ break;
+ case FB_BLANK_POWERDOWN:
+ blank = 1; hsync = 0; vsync = 0;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ dcfg = readl(par->vid_regs + CS5530_DISPLAY_CONFIG);
+
+ dcfg &= ~(CS5530_DCFG_DAC_BL_EN | CS5530_DCFG_DAC_PWR_EN
+ | CS5530_DCFG_HSYNC_EN | CS5530_DCFG_VSYNC_EN
+ | CS5530_DCFG_FP_DATA_EN | CS5530_DCFG_FP_PWR_EN);
+
+ if (par->enable_crt) {
+ if (!blank)
+ dcfg |= CS5530_DCFG_DAC_BL_EN | CS5530_DCFG_DAC_PWR_EN;
+ if (hsync)
+ dcfg |= CS5530_DCFG_HSYNC_EN;
+ if (vsync)
+ dcfg |= CS5530_DCFG_VSYNC_EN;
+ }
+ if (par->panel_x > 0) {
+ if (!blank)
+ dcfg |= CS5530_DCFG_FP_DATA_EN;
+ if (hsync && vsync)
+ dcfg |= CS5530_DCFG_FP_PWR_EN;
+ }
+
+ writel(dcfg, par->vid_regs + CS5530_DISPLAY_CONFIG);
+
+ return 0;
+}
+
+struct geode_vid_ops cs5530_vid_ops = {
+ .set_dclk = cs5530_set_dclk_frequency,
+ .configure_display = cs5530_configure_display,
+ .blank_display = cs5530_blank_display,
+};
diff --git a/drivers/video/geode/video_cs5530.h b/drivers/video/geode/video_cs5530.h
new file mode 100644
index 0000000000000..56cecca7f1ced
--- /dev/null
+++ b/drivers/video/geode/video_cs5530.h
@@ -0,0 +1,75 @@
+/*
+ * drivers/video/geode/video_cs5530.h
+ * -- CS5530 video device
+ *
+ * Copyright (C) 2005 Arcom Control Systems Ltd.
+ *
+ * Based on AMD's original 2.4 driver:
+ * Copyright (C) 2004 Advanced Micro Devices, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#ifndef __VIDEO_CS5530_H__
+#define __VIDEO_CS5530_H__
+
+extern struct geode_vid_ops cs5530_vid_ops;
+
+/* CS5530 Video device registers */
+
+#define CS5530_VIDEO_CONFIG 0x0000
+# define CS5530_VCFG_VID_EN 0x00000001
+# define CS5530_VCFG_VID_REG_UPDATE 0x00000002
+# define CS5530_VCFG_VID_INP_FORMAT 0x0000000C
+# define CS5530_VCFG_8_BIT_4_2_0 0x00000004
+# define CS5530_VCFG_16_BIT_4_2_0 0x00000008
+# define CS5530_VCFG_GV_SEL 0x00000010
+# define CS5530_VCFG_CSC_BYPASS 0x00000020
+# define CS5530_VCFG_X_FILTER_EN 0x00000040
+# define CS5530_VCFG_Y_FILTER_EN 0x00000080
+# define CS5530_VCFG_LINE_SIZE_LOWER_MASK 0x0000FF00
+# define CS5530_VCFG_INIT_READ_MASK 0x01FF0000
+# define CS5530_VCFG_EARLY_VID_RDY 0x02000000
+# define CS5530_VCFG_LINE_SIZE_UPPER 0x08000000
+# define CS5530_VCFG_4_2_0_MODE 0x10000000
+# define CS5530_VCFG_16_BIT_EN 0x20000000
+# define CS5530_VCFG_HIGH_SPD_INT 0x40000000
+
+#define CS5530_DISPLAY_CONFIG 0x0004
+# define CS5530_DCFG_DIS_EN 0x00000001
+# define CS5530_DCFG_HSYNC_EN 0x00000002
+# define CS5530_DCFG_VSYNC_EN 0x00000004
+# define CS5530_DCFG_DAC_BL_EN 0x00000008
+# define CS5530_DCFG_DAC_PWR_EN 0x00000020
+# define CS5530_DCFG_FP_PWR_EN 0x00000040
+# define CS5530_DCFG_FP_DATA_EN 0x00000080
+# define CS5530_DCFG_CRT_HSYNC_POL 0x00000100
+# define CS5530_DCFG_CRT_VSYNC_POL 0x00000200
+# define CS5530_DCFG_FP_HSYNC_POL 0x00000400
+# define CS5530_DCFG_FP_VSYNC_POL 0x00000800
+# define CS5530_DCFG_XGA_FP 0x00001000
+# define CS5530_DCFG_FP_DITH_EN 0x00002000
+# define CS5530_DCFG_CRT_SYNC_SKW_MASK 0x0001C000
+# define CS5530_DCFG_CRT_SYNC_SKW_INIT 0x00010000
+# define CS5530_DCFG_PWR_SEQ_DLY_MASK 0x000E0000
+# define CS5530_DCFG_PWR_SEQ_DLY_INIT 0x00080000
+# define CS5530_DCFG_VG_CK 0x00100000
+# define CS5530_DCFG_GV_PAL_BYP 0x00200000
+# define CS5530_DCFG_DDC_SCL 0x00400000
+# define CS5530_DCFG_DDC_SDA 0x00800000
+# define CS5530_DCFG_DDC_OE 0x01000000
+# define CS5530_DCFG_16_BIT_EN 0x02000000
+
+#define CS5530_VIDEO_X_POS 0x0008
+#define CS5530_VIDEO_Y_POS 0x000C
+#define CS5530_VIDEO_SCALE 0x0010
+#define CS5530_VIDEO_COLOR_KEY 0x0014
+#define CS5530_VIDEO_COLOR_MASK 0x0018
+#define CS5530_PALETTE_ADDRESS 0x001C
+#define CS5530_PALETTE_DATA 0x0020
+#define CS5530_DOT_CLK_CONFIG 0x0024
+#define CS5530_CRCSIG_TFT_TV 0x0028
+
+#endif /* !__VIDEO_CS5530_H__ */
diff --git a/drivers/video/hgafb.c b/drivers/video/hgafb.c
index c2a06ca2ea980..b37cea7d1094b 100644
--- a/drivers/video/hgafb.c
+++ b/drivers/video/hgafb.c
@@ -412,7 +412,8 @@ static int hgafb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
* A zero is returned on success and %-EINVAL for failure.
*/
-int hgafb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
+static int hgafb_pan_display(struct fb_var_screeninfo *var,
+ struct fb_info *info)
{
if (var->vmode & FB_VMODE_YWRAP) {
if (var->yoffset < 0 ||
@@ -548,7 +549,7 @@ static struct fb_ops hgafb_ops = {
* Initialization
*/
-int __init hgafb_init(void)
+static int __init hgafb_init(void)
{
if (fb_get_options("hgafb", NULL))
return -ENODEV;
@@ -587,15 +588,6 @@ int __init hgafb_init(void)
return 0;
}
- /*
- * Setup
- */
-
-int __init hgafb_setup(char *options)
-{
- return 0;
-}
-
#ifdef MODULE
static void __exit hgafb_exit(void)
{
diff --git a/drivers/video/hitfb.c b/drivers/video/hitfb.c
index 9d2ea3b4a2e31..0d376ba54814f 100644
--- a/drivers/video/hitfb.c
+++ b/drivers/video/hitfb.c
@@ -1,6 +1,6 @@
/*
- * $Id: hitfb.c,v 1.12 2004/03/16 00:07:51 lethal Exp $
* linux/drivers/video/hitfb.c -- Hitachi LCD frame buffer device
+ *
* (C) 1999 Mihai Spatar
* (C) 2000 YAEGASHI Takeshi
* (C) 2003, 2004 Paul Mundt
@@ -40,15 +40,15 @@
static struct fb_var_screeninfo hitfb_var __initdata = {
.activate = FB_ACTIVATE_NOW,
.height = -1,
- .width = -1,
- .vmode = FB_VMODE_NONINTERLACED,
+ .width = -1,
+ .vmode = FB_VMODE_NONINTERLACED,
};
static struct fb_fix_screeninfo hitfb_fix __initdata = {
- .id = "Hitachi HD64461",
- .type = FB_TYPE_PACKED_PIXELS,
- .ypanstep = 8,
- .accel = FB_ACCEL_NONE,
+ .id = "Hitachi HD64461",
+ .type = FB_TYPE_PACKED_PIXELS,
+ .ypanstep = 8,
+ .accel = FB_ACCEL_NONE,
};
static u32 pseudo_palette[16];
@@ -255,14 +255,14 @@ static int hitfb_setcolreg(unsigned regno, unsigned red, unsigned green,
}
static struct fb_ops hitfb_ops = {
- .owner = THIS_MODULE,
- .fb_setcolreg = hitfb_setcolreg,
- .fb_blank = hitfb_blank,
+ .owner = THIS_MODULE,
+ .fb_setcolreg = hitfb_setcolreg,
+ .fb_blank = hitfb_blank,
.fb_pan_display = hitfb_pan_display,
- .fb_fillrect = hitfb_fillrect,
- .fb_copyarea = hitfb_copyarea,
- .fb_imageblit = cfb_imageblit,
- .fb_cursor = soft_cursor,
+ .fb_fillrect = hitfb_fillrect,
+ .fb_copyarea = hitfb_copyarea,
+ .fb_imageblit = cfb_imageblit,
+ .fb_cursor = soft_cursor,
};
int __init hitfb_init(void)
@@ -324,7 +324,7 @@ int __init hitfb_init(void)
fb_info.var = hitfb_var;
fb_info.fix = hitfb_fix;
fb_info.pseudo_palette = pseudo_palette;
- fb_info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
+ fb_info.flags = FBINFO_DEFAULT;
fb_info.screen_base = (void *)hitfb_fix.smem_start;
@@ -345,9 +345,6 @@ static void __exit hitfb_exit(void)
}
module_init(hitfb_init);
-
-#ifdef MODULE
module_exit(hitfb_exit);
-#endif
MODULE_LICENSE("GPL");
diff --git a/drivers/video/i810/i810_gtf.c b/drivers/video/i810/i810_gtf.c
index 814698b90fb6a..64f087a4466bc 100644
--- a/drivers/video/i810/i810_gtf.c
+++ b/drivers/video/i810/i810_gtf.c
@@ -26,7 +26,7 @@ struct wm_info {
u32 wm;
};
-struct wm_info i810_wm_8_100[] = {
+static struct wm_info i810_wm_8_100[] = {
{ 15, 0x0070c000 }, { 19, 0x0070c000 }, { 25, 0x22003000 },
{ 28, 0x22003000 }, { 31, 0x22003000 }, { 36, 0x22007000 },
{ 40, 0x22007000 }, { 45, 0x22007000 }, { 49, 0x22008000 },
@@ -40,7 +40,7 @@ struct wm_info i810_wm_8_100[] = {
{ 218, 0x2220f000 }, { 229, 0x22210000 }, { 234, 0x22210000 },
};
-struct wm_info i810_wm_16_100[] = {
+static struct wm_info i810_wm_16_100[] = {
{ 15, 0x0070c000 }, { 19, 0x0020c000 }, { 25, 0x22006000 },
{ 28, 0x22006000 }, { 31, 0x22007000 }, { 36, 0x22007000 },
{ 40, 0x22007000 }, { 45, 0x22007000 }, { 49, 0x22009000 },
@@ -54,7 +54,7 @@ struct wm_info i810_wm_16_100[] = {
{ 218, 0x22416000 }, { 229, 0x22416000 },
};
-struct wm_info i810_wm_24_100[] = {
+static struct wm_info i810_wm_24_100[] = {
{ 15, 0x0020c000 }, { 19, 0x0040c000 }, { 25, 0x22009000 },
{ 28, 0x22009000 }, { 31, 0x2200a000 }, { 36, 0x2210c000 },
{ 40, 0x2210c000 }, { 45, 0x2210c000 }, { 49, 0x22111000 },
@@ -67,7 +67,7 @@ struct wm_info i810_wm_24_100[] = {
{ 195, 0x44419000 }, { 202, 0x44419000 }, { 204, 0x44419000 },
};
-struct wm_info i810_wm_8_133[] = {
+static struct wm_info i810_wm_8_133[] = {
{ 15, 0x0070c000 }, { 19, 0x0070c000 }, { 25, 0x22003000 },
{ 28, 0x22003000 }, { 31, 0x22003000 }, { 36, 0x22007000 },
{ 40, 0x22007000 }, { 45, 0x22007000 }, { 49, 0x22008000 },
@@ -81,7 +81,7 @@ struct wm_info i810_wm_8_133[] = {
{ 218, 0x2220f000 }, { 229, 0x22210000 }, { 234, 0x22210000 },
};
-struct wm_info i810_wm_16_133[] = {
+static struct wm_info i810_wm_16_133[] = {
{ 15, 0x0020c000 }, { 19, 0x0020c000 }, { 25, 0x22006000 },
{ 28, 0x22006000 }, { 31, 0x22007000 }, { 36, 0x22007000 },
{ 40, 0x22007000 }, { 45, 0x22007000 }, { 49, 0x22009000 },
@@ -95,7 +95,7 @@ struct wm_info i810_wm_16_133[] = {
{ 218, 0x22416000 }, { 229, 0x22416000 },
};
-struct wm_info i810_wm_24_133[] = {
+static struct wm_info i810_wm_24_133[] = {
{ 15, 0x0020c000 }, { 19, 0x00408000 }, { 25, 0x22009000 },
{ 28, 0x22009000 }, { 31, 0x2200a000 }, { 36, 0x2210c000 },
{ 40, 0x2210c000 }, { 45, 0x2210c000 }, { 49, 0x22111000 },
diff --git a/drivers/video/i810/i810_main.c b/drivers/video/i810/i810_main.c
index f11c76a9e136f..9ec8781794c01 100644
--- a/drivers/video/i810/i810_main.c
+++ b/drivers/video/i810/i810_main.c
@@ -635,7 +635,7 @@ static void i810_save_vga_state(struct i810fb_par *par)
* DESCRIPTION:
* Calculates buffer pitch in bytes.
*/
-u32 get_line_length(struct i810fb_par *par, int xres_virtual, int bpp)
+static u32 get_line_length(struct i810fb_par *par, int xres_virtual, int bpp)
{
u32 length;
@@ -724,7 +724,7 @@ static void i810_calc_dclk(u32 freq, u32 *m, u32 *n, u32 *p)
* Description:
* Shows or hides the hardware cursor
*/
-void i810_enable_cursor(u8 __iomem *mmio, int mode)
+static void i810_enable_cursor(u8 __iomem *mmio, int mode)
{
u32 temp;
@@ -1492,7 +1492,7 @@ static struct fb_ops i810fb_ops __devinitdata = {
/***********************************************************************
* Power Management *
***********************************************************************/
-static int i810fb_suspend(struct pci_dev *dev, u32 state)
+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;
@@ -1524,7 +1524,7 @@ static int i810fb_suspend(struct pci_dev *dev, u32 state)
pci_disable_device(dev);
}
pci_save_state(dev);
- pci_set_power_state(dev, state);
+ pci_set_power_state(dev, pci_choose_state(dev, state));
return 0;
}
@@ -1538,7 +1538,7 @@ static int i810fb_resume(struct pci_dev *dev)
return 0;
pci_restore_state(dev);
- pci_set_power_state(dev, 0);
+ pci_set_power_state(dev, PCI_D0);
pci_enable_device(dev);
agp_bind_memory(par->i810_gtt.i810_fb_memory,
par->fb.offset);
@@ -1591,40 +1591,41 @@ static int __devinit i810_alloc_agp_mem(struct fb_info *info)
{
struct i810fb_par *par = (struct i810fb_par *) info->par;
int size;
+ struct agp_bridge_data *bridge;
i810_fix_offsets(par);
size = par->fb.size + par->iring.size;
- if (agp_backend_acquire()) {
+ if (!(bridge = agp_backend_acquire(par->dev))) {
printk("i810fb_alloc_fbmem: cannot acquire agpgart\n");
return -ENODEV;
}
if (!(par->i810_gtt.i810_fb_memory =
- agp_allocate_memory(size >> 12, AGP_NORMAL_MEMORY))) {
+ agp_allocate_memory(bridge, size >> 12, AGP_NORMAL_MEMORY))) {
printk("i810fb_alloc_fbmem: can't allocate framebuffer "
"memory\n");
- agp_backend_release();
+ agp_backend_release(bridge);
return -ENOMEM;
}
if (agp_bind_memory(par->i810_gtt.i810_fb_memory,
par->fb.offset)) {
printk("i810fb_alloc_fbmem: can't bind framebuffer memory\n");
- agp_backend_release();
+ agp_backend_release(bridge);
return -EBUSY;
}
if (!(par->i810_gtt.i810_cursor_memory =
- agp_allocate_memory(par->cursor_heap.size >> 12,
+ agp_allocate_memory(bridge, par->cursor_heap.size >> 12,
AGP_PHYSICAL_MEMORY))) {
printk("i810fb_alloc_cursormem: can't allocate"
"cursor memory\n");
- agp_backend_release();
+ agp_backend_release(bridge);
return -ENOMEM;
}
if (agp_bind_memory(par->i810_gtt.i810_cursor_memory,
par->cursor_heap.offset)) {
printk("i810fb_alloc_cursormem: cannot bind cursor memory\n");
- agp_backend_release();
+ agp_backend_release(bridge);
return -EBUSY;
}
@@ -1632,7 +1633,7 @@ static int __devinit i810_alloc_agp_mem(struct fb_info *info)
i810_fix_pointers(par);
- agp_backend_release();
+ agp_backend_release(bridge);
return 0;
}
@@ -1804,8 +1805,9 @@ i810_allocate_pci_resource(struct i810fb_par *par,
return 0;
}
-
-int __init i810fb_setup(char *options)
+
+#ifndef MODULE
+static int __init i810fb_setup(char *options)
{
char *this_opt, *suffix = NULL;
@@ -1850,6 +1852,7 @@ int __init i810fb_setup(char *options)
}
return 0;
}
+#endif
static int __devinit i810fb_init_pci (struct pci_dev *dev,
const struct pci_device_id *entry)
@@ -1976,7 +1979,7 @@ static void __exit i810fb_remove_pci(struct pci_dev *dev)
}
#ifndef MODULE
-int __init i810fb_init(void)
+static int __init i810fb_init(void)
{
char *option = NULL;
@@ -1994,7 +1997,7 @@ int __init i810fb_init(void)
#ifdef MODULE
-int __init i810fb_init(void)
+static int __init i810fb_init(void)
{
hsync1 *= 1000;
hsync2 *= 1000;
diff --git a/drivers/video/i810/i810_main.h b/drivers/video/i810/i810_main.h
index 0f2caf3575f8a..43b4297b4d481 100644
--- a/drivers/video/i810/i810_main.h
+++ b/drivers/video/i810/i810_main.h
@@ -18,7 +18,7 @@ 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, u32 state);
+static int i810fb_suspend(struct pci_dev *dev, pm_message_t state);
/*
* voffset - framebuffer offset in MiB from aperture start address. In order for
diff --git a/drivers/video/igafb.c b/drivers/video/igafb.c
index 2da19ea040d0f..e326f44f652d7 100644
--- a/drivers/video/igafb.c
+++ b/drivers/video/igafb.c
@@ -536,8 +536,7 @@ int __init igafb_init(void)
if (!iga_init(info, par)) {
iounmap((void *)par->io_base);
iounmap(info->screen_base);
- if (par->mmap_map)
- kfree(par->mmap_map);
+ kfree(par->mmap_map);
kfree(info);
}
diff --git a/drivers/video/imsttfb.c b/drivers/video/imsttfb.c
index 233884c84f518..5a72ca3c01385 100644
--- a/drivers/video/imsttfb.c
+++ b/drivers/video/imsttfb.c
@@ -228,7 +228,7 @@ struct initvalues {
__u8 addr, value;
};
-static struct initvalues ibm_initregs[] __initdata = {
+static struct initvalues ibm_initregs[] __devinitdata = {
{ CLKCTL, 0x21 },
{ SYNCCTL, 0x00 },
{ HSYNCPOS, 0x00 },
@@ -275,7 +275,7 @@ static struct initvalues ibm_initregs[] __initdata = {
{ KEYCTL, 0x00 }
};
-static struct initvalues tvp_initregs[] __initdata = {
+static struct initvalues tvp_initregs[] __devinitdata = {
{ TVPIRICC, 0x00 },
{ TVPIRBRC, 0xe4 },
{ TVPIRLAC, 0x06 },
@@ -338,7 +338,7 @@ enum {
static int inverse = 0;
static char fontname[40] __initdata = { 0 };
#if defined(CONFIG_PPC)
-static signed char init_vmode __initdata = -1, init_cmode __initdata = -1;
+static signed char init_vmode __devinitdata = -1, init_cmode __devinitdata = -1;
#endif
static struct imstt_regvals tvp_reg_init_2 = {
@@ -1348,7 +1348,7 @@ static struct fb_ops imsttfb_ops = {
.fb_ioctl = imsttfb_ioctl,
};
-static void __init
+static void __devinit
init_imstt(struct fb_info *info)
{
struct imstt_par *par = (struct imstt_par *) info->par;
@@ -1547,7 +1547,7 @@ imsttfb_remove(struct pci_dev *pdev)
}
#ifndef MODULE
-int __init
+static int __init
imsttfb_setup(char *options)
{
char *this_opt;
@@ -1601,7 +1601,7 @@ imsttfb_setup(char *options)
#endif /* MODULE */
-int __init imsttfb_init(void)
+static int __init imsttfb_init(void)
{
#ifndef MODULE
char *option = NULL;
@@ -1611,7 +1611,7 @@ int __init imsttfb_init(void)
imsttfb_setup(option);
#endif
- return pci_module_init(&imsttfb_pci_driver);
+ return pci_register_driver(&imsttfb_pci_driver);
}
static void __exit imsttfb_exit(void)
@@ -1619,9 +1619,8 @@ static void __exit imsttfb_exit(void)
pci_unregister_driver(&imsttfb_pci_driver);
}
-#ifdef MODULE
MODULE_LICENSE("GPL");
-#endif
+
module_init(imsttfb_init);
module_exit(imsttfb_exit);
diff --git a/drivers/video/intelfb/intelfb.h b/drivers/video/intelfb/intelfb.h
index 1c5b472ead816..6680ec9ba69ea 100644
--- a/drivers/video/intelfb/intelfb.h
+++ b/drivers/video/intelfb/intelfb.h
@@ -10,7 +10,7 @@
/*** Version/name ***/
#define INTELFB_VERSION "0.9.2"
#define INTELFB_MODULE_NAME "intelfb"
-#define SUPPORTED_CHIPSETS "830M/845G/852GM/855GM/865G"
+#define SUPPORTED_CHIPSETS "830M/845G/852GM/855GM/865G/915G"
/*** Debug/feature defines ***/
@@ -36,7 +36,7 @@
#endif
#ifndef PREFERRED_MODE
-#define PREFERRED_MODE "1024x768-16@60"
+#define PREFERRED_MODE "1024x768-32@70"
#endif
/*** hw-related values ***/
@@ -46,6 +46,7 @@
#define PCI_DEVICE_ID_INTEL_845G 0x2562
#define PCI_DEVICE_ID_INTEL_85XGM 0x3582
#define PCI_DEVICE_ID_INTEL_865G 0x2572
+#define PCI_DEVICE_ID_INTEL_915G 0x2582
/* Size of MMIO region */
#define INTEL_REG_SIZE 0x80000
@@ -117,7 +118,8 @@ enum intel_chips {
INTEL_852GME,
INTEL_855GM,
INTEL_855GME,
- INTEL_865G
+ INTEL_865G,
+ INTEL_915G
};
struct intelfb_hwstate {
diff --git a/drivers/video/intelfb/intelfbdrv.c b/drivers/video/intelfb/intelfbdrv.c
index c4bfbc11c0d60..6a05b70008301 100644
--- a/drivers/video/intelfb/intelfbdrv.c
+++ b/drivers/video/intelfb/intelfbdrv.c
@@ -1,7 +1,7 @@
/*
* intelfb
*
- * Linux framebuffer driver for Intel(R) 830M/845G/852GM/855GM/865G
+ * Linux framebuffer driver for Intel(R) 830M/845G/852GM/855GM/865G/915G
* integrated graphics chips.
*
* Copyright © 2002, 2003 David Dawes <dawes@xfree86.org>
@@ -153,6 +153,7 @@ static struct pci_device_id intelfb_pci_table[] __devinitdata = {
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_845G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_845G },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_85XGM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_85XGM },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_865G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_865G },
+ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_915G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_915G },
{ 0, }
};
@@ -226,42 +227,6 @@ MODULE_PARM_DESC(bailearly, "Bail out early, depending on value (debug)");
module_param(mode, charp, S_IRUGO);
MODULE_PARM_DESC(mode,
"Initial video mode \"<xres>x<yres>[-<depth>][@<refresh>]\"");
-/***************************************************************
- * modules entry points *
- ***************************************************************/
-
-/* module load/unload entry points */
-int __init
-intelfb_init(void)
-{
-#ifndef MODULE
- char *option = NULL;
-#endif
-
- DBG_MSG("intelfb_init\n");
-
- INF_MSG("Framebuffer driver for "
- "Intel(R) " SUPPORTED_CHIPSETS " chipsets\n");
- INF_MSG("Version " INTELFB_VERSION "\n");
-
- if (idonly)
- return -ENODEV;
-
-#ifndef MODULE
- if (fb_get_options("intelfb", &option))
- return -ENODEV;
- intelfb_setup(option);
-#endif
-
- return pci_module_init(&intelfb_driver);
-}
-
-static void __exit
-intelfb_exit(void)
-{
- DBG_MSG("intelfb_exit\n");
- pci_unregister_driver(&intelfb_driver);
-}
#ifndef MODULE
#define OPT_EQUAL(opt, name) (!strncmp(opt, name, strlen(name)))
@@ -321,7 +286,7 @@ get_opt_bool(const char *this_opt, const char *name, int *ret)
return 1;
}
-int __init
+static int __init
intelfb_setup(char *options)
{
char *this_opt;
@@ -373,12 +338,41 @@ intelfb_setup(char *options)
#endif
-module_init(intelfb_init);
+static int __init
+intelfb_init(void)
+{
+#ifndef MODULE
+ char *option = NULL;
+#endif
-#ifdef MODULE
-module_exit(intelfb_exit);
+ DBG_MSG("intelfb_init\n");
+
+ INF_MSG("Framebuffer driver for "
+ "Intel(R) " SUPPORTED_CHIPSETS " chipsets\n");
+ INF_MSG("Version " INTELFB_VERSION "\n");
+
+ if (idonly)
+ return -ENODEV;
+
+#ifndef MODULE
+ if (fb_get_options("intelfb", &option))
+ return -ENODEV;
+ intelfb_setup(option);
#endif
+ return pci_register_driver(&intelfb_driver);
+}
+
+static void __exit
+intelfb_exit(void)
+{
+ DBG_MSG("intelfb_exit\n");
+ pci_unregister_driver(&intelfb_driver);
+}
+
+module_init(intelfb_init);
+module_exit(intelfb_exit);
+
/***************************************************************
* mtrr support functions *
***************************************************************/
@@ -470,6 +464,9 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
struct agp_kern_info gtt_info;
int agp_memtype;
const char *s;
+ struct agp_bridge_data *bridge;
+ int aperture_bar = 0;
+ int mmio_bar = 1;
DBG_MSG("intelfb_pci_register\n");
@@ -516,13 +513,20 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
}
/* Set base addresses. */
- dinfo->aperture.physical = pci_resource_start(pdev, 0);
- dinfo->aperture.size = pci_resource_len(pdev, 0);
- dinfo->mmio_base_phys = pci_resource_start(pdev, 1);
-
- DBG_MSG("fb aperture: 0x%lx/0x%lx, MMIO region: 0x%lx/0x%lx\n",
- pci_resource_start(pdev, 0), pci_resource_len(pdev, 0),
- pci_resource_start(pdev, 1), pci_resource_len(pdev, 1));
+ if (ent->device == PCI_DEVICE_ID_INTEL_915G) {
+ aperture_bar = 2;
+ mmio_bar = 0;
+ /* Disable HW cursor on 915G (not implemented yet) */
+ hwcursor = 0;
+ }
+ dinfo->aperture.physical = pci_resource_start(pdev, aperture_bar);
+ dinfo->aperture.size = pci_resource_len(pdev, aperture_bar);
+ dinfo->mmio_base_phys = pci_resource_start(pdev, mmio_bar);
+ DBG_MSG("fb aperture: 0x%llx/0x%llx, MMIO region: 0x%llx/0x%llx\n",
+ (unsigned long long)pci_resource_start(pdev, aperture_bar),
+ (unsigned long long)pci_resource_len(pdev, aperture_bar),
+ (unsigned long long)pci_resource_start(pdev, mmio_bar),
+ (unsigned long long)pci_resource_len(pdev, mmio_bar));
/* Reserve the fb and MMIO regions */
if (!request_mem_region(dinfo->aperture.physical, dinfo->aperture.size,
@@ -605,16 +609,16 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
}
/* Use agpgart to manage the GATT */
- if (agp_backend_acquire()) {
+ if (!(bridge = agp_backend_acquire(pdev))) {
ERR_MSG("cannot acquire agp\n");
cleanup(dinfo);
return -ENODEV;
}
/* get the current gatt info */
- if (agp_copy_info(&gtt_info)) {
+ if (agp_copy_info(bridge, &gtt_info)) {
ERR_MSG("cannot get agp info\n");
- agp_backend_release();
+ agp_backend_release(bridge);
cleanup(dinfo);
return -ENODEV;
}
@@ -637,17 +641,17 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
/* Allocate memories (which aren't stolen) */
if (dinfo->accel) {
if (!(dinfo->gtt_ring_mem =
- agp_allocate_memory(dinfo->ring.size >> 12,
+ agp_allocate_memory(bridge, dinfo->ring.size >> 12,
AGP_NORMAL_MEMORY))) {
ERR_MSG("cannot allocate ring buffer memory\n");
- agp_backend_release();
+ agp_backend_release(bridge);
cleanup(dinfo);
return -ENOMEM;
}
if (agp_bind_memory(dinfo->gtt_ring_mem,
dinfo->ring.offset)) {
ERR_MSG("cannot bind ring buffer memory\n");
- agp_backend_release();
+ agp_backend_release(bridge);
cleanup(dinfo);
return -EBUSY;
}
@@ -661,17 +665,17 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
agp_memtype = dinfo->mobile ? AGP_PHYSICAL_MEMORY
: AGP_NORMAL_MEMORY;
if (!(dinfo->gtt_cursor_mem =
- agp_allocate_memory(dinfo->cursor.size >> 12,
+ agp_allocate_memory(bridge, dinfo->cursor.size >> 12,
agp_memtype))) {
ERR_MSG("cannot allocate cursor memory\n");
- agp_backend_release();
+ agp_backend_release(bridge);
cleanup(dinfo);
return -ENOMEM;
}
if (agp_bind_memory(dinfo->gtt_cursor_mem,
dinfo->cursor.offset)) {
ERR_MSG("cannot bind cursor memory\n");
- agp_backend_release();
+ agp_backend_release(bridge);
cleanup(dinfo);
return -EBUSY;
}
@@ -686,7 +690,7 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
}
if (dinfo->fbmem_gart) {
if (!(dinfo->gtt_fb_mem =
- agp_allocate_memory(dinfo->fb.size >> 12,
+ agp_allocate_memory(bridge, dinfo->fb.size >> 12,
AGP_NORMAL_MEMORY))) {
WRN_MSG("cannot allocate framebuffer memory - use "
"the stolen one\n");
@@ -709,7 +713,7 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
dinfo->fb_start = dinfo->fb.offset << 12;
/* release agpgart */
- agp_backend_release();
+ agp_backend_release(bridge);
if (mtrr)
set_mtrr(dinfo);
@@ -989,13 +993,15 @@ intelfb_init_var(struct intelfb_info *dinfo)
} else {
if (mode) {
msrc = fb_find_mode(var, dinfo->info, mode,
- NULL, 0, NULL, 0);
+ vesa_modes, VESA_MODEDB_SIZE,
+ NULL, 0);
if (msrc)
msrc |= 8;
}
if (!msrc) {
msrc = fb_find_mode(var, dinfo->info, PREFERRED_MODE,
- NULL, 0, NULL, 0);
+ vesa_modes, VESA_MODEDB_SIZE,
+ NULL, 0);
}
}
diff --git a/drivers/video/intelfb/intelfbdrv.h b/drivers/video/intelfb/intelfbdrv.h
index f05dffae0533b..cc30581288840 100644
--- a/drivers/video/intelfb/intelfbdrv.h
+++ b/drivers/video/intelfb/intelfbdrv.h
@@ -5,7 +5,7 @@
******************************************************************************
* intelfb
*
- * Linux framebuffer driver for Intel(R) 830M/845G/852GM/855GM/865G
+ * Linux framebuffer driver for Intel(R) 830M/845G/852GM/855GM/865G/915G
* integrated graphics chips.
*
* Copyright © 2004 Sylvain Meyer
@@ -28,7 +28,6 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-int __init intelfb_setup(char *options);
static void __devinit get_initial_mode(struct intelfb_info *dinfo);
static void update_dinfo(struct intelfb_info *dinfo,
struct fb_var_screeninfo *var);
diff --git a/drivers/video/intelfb/intelfbhw.c b/drivers/video/intelfb/intelfbhw.c
index df4010875d4b0..f5bed581dc45f 100644
--- a/drivers/video/intelfb/intelfbhw.c
+++ b/drivers/video/intelfb/intelfbhw.c
@@ -98,6 +98,11 @@ intelfbhw_get_chipset(struct pci_dev *pdev, const char **name, int *chipset,
*chipset = INTEL_865G;
*mobile = 0;
return 0;
+ case PCI_DEVICE_ID_INTEL_915G:
+ *name = "Intel(R) 915G";
+ *chipset = INTEL_915G;
+ *mobile = 0;
+ return 0;
default:
return 1;
}
@@ -169,6 +174,12 @@ intelfbhw_get_memory(struct pci_dev *pdev, int *aperture_size,
case INTEL_855_GMCH_GMS_STOLEN_32M:
*stolen_size = MB(32) - KB(132);
return 0;
+ case INTEL_915G_GMCH_GMS_STOLEN_48M:
+ *stolen_size = MB(48) - KB(132);
+ return 0;
+ case INTEL_915G_GMCH_GMS_STOLEN_64M:
+ *stolen_size = MB(64) - KB(132);
+ return 0;
case INTEL_855_GMCH_GMS_DISABLED:
ERR_MSG("video memory is disabled\n");
return 0;
diff --git a/drivers/video/intelfb/intelfbhw.h b/drivers/video/intelfb/intelfbhw.h
index d4336ccce62a7..ba1920159f526 100644
--- a/drivers/video/intelfb/intelfbhw.h
+++ b/drivers/video/intelfb/intelfbhw.h
@@ -46,6 +46,9 @@
#define INTEL_855_GMCH_GMS_STOLEN_16M (0x4 << 4)
#define INTEL_855_GMCH_GMS_STOLEN_32M (0x5 << 4)
+#define INTEL_915G_GMCH_GMS_STOLEN_48M (0x6 << 4)
+#define INTEL_915G_GMCH_GMS_STOLEN_64M (0x7 << 4)
+
/* HW registers */
/* Fence registers */
diff --git a/drivers/video/kyro/STG4000InitDevice.c b/drivers/video/kyro/STG4000InitDevice.c
index 7035ed1b7a19b..7e33cd307d47f 100644
--- a/drivers/video/kyro/STG4000InitDevice.c
+++ b/drivers/video/kyro/STG4000InitDevice.c
@@ -79,8 +79,8 @@ volatile u32 i,count=0; \
for(i=0;i<X;i++) count++; \
}
-u32 InitSDRAMRegisters(volatile STG4000REG __iomem *pSTGReg, u32 dwSubSysID,
- u32 dwRevID)
+static u32 InitSDRAMRegisters(volatile STG4000REG __iomem *pSTGReg,
+ u32 dwSubSysID, u32 dwRevID)
{
u32 adwSDRAMArgCfg0[] = { 0xa0, 0x80, 0xa0, 0xa0, 0xa0 };
u32 adwSDRAMCfg1[] = { 0x8732, 0x8732, 0xa732, 0xa732, 0x8732 };
diff --git a/drivers/video/kyro/STG4000OverlayDevice.c b/drivers/video/kyro/STG4000OverlayDevice.c
index fcdc5328920f3..2ae9bafacdd0c 100644
--- a/drivers/video/kyro/STG4000OverlayDevice.c
+++ b/drivers/video/kyro/STG4000OverlayDevice.c
@@ -42,8 +42,8 @@
#define STG4000_OVRL_MAX_HEIGHT 576
/* Decimation and Scaling */
-u32 adwDecim8[33] = {
- 0xffffffff, 0xfffeffff, 0xffdffbff, 0xfefefeff, 0xfdf7efbf,
+static u32 adwDecim8[33] = {
+ 0xffffffff, 0xfffeffff, 0xffdffbff, 0xfefefeff, 0xfdf7efbf,
0xfbdf7bdf, 0xf7bbddef, 0xeeeeeeef, 0xeeddbb77, 0xedb76db7,
0xdb6db6db, 0xdb5b5b5b, 0xdab5ad6b, 0xd5ab55ab, 0xd555aaab,
0xaaaaaaab, 0xaaaa5555, 0xaa952a55, 0xa94a5295, 0xa5252525,
diff --git a/drivers/video/kyro/STG4000Ramdac.c b/drivers/video/kyro/STG4000Ramdac.c
index 76a3527efc8be..e6ad037e43961 100644
--- a/drivers/video/kyro/STG4000Ramdac.c
+++ b/drivers/video/kyro/STG4000Ramdac.c
@@ -18,7 +18,6 @@
static u32 STG_PIXEL_BUS_WIDTH = 128; /* 128 bit bus width */
static u32 REF_CLOCK = 14318;
-STG4000REG __iomem *pSTGReg;
int InitialiseRamdac(volatile STG4000REG __iomem * pSTGReg,
u32 displayDepth,
diff --git a/drivers/video/kyro/fbdev.c b/drivers/video/kyro/fbdev.c
index 1cf2208c8af87..d8bac9e978421 100644
--- a/drivers/video/kyro/fbdev.c
+++ b/drivers/video/kyro/fbdev.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/video/kyro/kyrofb.c
+ * linux/drivers/video/kyro/fbdev.c
*
* Copyright (C) 2002 STMicroelectronics
* Copyright (C) 2003, 2004 Paul Mundt
@@ -43,14 +43,14 @@
#define KHZ2PICOS(a) (1000000000UL/(a))
/****************************************************************************/
-static struct fb_fix_screeninfo kyro_fix __initdata = {
+static struct fb_fix_screeninfo kyro_fix __devinitdata = {
.id = "ST Kyro",
.type = FB_TYPE_PACKED_PIXELS,
.visual = FB_VISUAL_TRUECOLOR,
.accel = FB_ACCEL_NONE,
};
-static struct fb_var_screeninfo kyro_var __initdata = {
+static struct fb_var_screeninfo kyro_var __devinitdata = {
/* 640x480, 16bpp @ 60 Hz */
.xres = 640,
.yres = 480,
@@ -86,18 +86,18 @@ typedef struct {
/* global graphics card info structure (one per card) */
static device_info_t deviceInfo;
-static char *mode_option __initdata = NULL;
-static int nopan __initdata = 0;
-static int nowrap __initdata = 1;
+static char *mode_option __devinitdata = NULL;
+static int nopan __devinitdata = 0;
+static int nowrap __devinitdata = 1;
#ifdef CONFIG_MTRR
-static int nomtrr __initdata = 0;
+static int nomtrr __devinitdata = 0;
#endif
/* PCI driver prototypes */
static int kyrofb_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
static void kyrofb_remove(struct pci_dev *pdev);
-static struct fb_videomode kyro_modedb[] __initdata = {
+static struct fb_videomode kyro_modedb[] __devinitdata = {
{
/* 640x350 @ 85Hz */
NULL, 85, 640, 350, KHZ2PICOS(31500),
@@ -307,7 +307,7 @@ enum {
};
/* Accessors */
-int kyro_dev_video_mode_set(struct fb_info *info)
+static int kyro_dev_video_mode_set(struct fb_info *info)
{
struct kyrofb_info *par = (struct kyrofb_info *)info->par;
@@ -339,8 +339,8 @@ int kyro_dev_video_mode_set(struct fb_info *info)
return 0;
}
-int kyro_dev_overlay_create(u32 ulWidth,
- u32 ulHeight, int bLinear)
+static int kyro_dev_overlay_create(u32 ulWidth,
+ u32 ulHeight, int bLinear)
{
u32 offset;
u32 stride, uvStride;
@@ -376,7 +376,7 @@ int kyro_dev_overlay_create(u32 ulWidth,
return 0;
}
-int kyro_dev_overlay_viewport_set(u32 x, u32 y, u32 ulWidth, u32 ulHeight)
+static int kyro_dev_overlay_viewport_set(u32 x, u32 y, u32 ulWidth, u32 ulHeight)
{
if (deviceInfo.ulOverlayOffset == 0)
/* probably haven't called CreateOverlay yet */
@@ -558,7 +558,8 @@ static int kyrofb_setcolreg(u_int regno, u_int red, u_int green,
return 0;
}
-int __init kyrofb_setup(char *options)
+#ifndef MODULE
+static int __init kyrofb_setup(char *options)
{
char *this_opt;
@@ -583,6 +584,7 @@ int __init kyrofb_setup(char *options)
return 0;
}
+#endif
static int kyrofb_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg,
@@ -594,7 +596,8 @@ static int kyrofb_ioctl(struct inode *inode, struct file *file,
switch (cmd) {
case KYRO_IOCTL_OVERLAY_CREATE:
- copy_from_user(&ol_create, argp, sizeof(overlay_create));
+ if (copy_from_user(&ol_create, argp, sizeof(overlay_create)))
+ return -EFAULT;
if (kyro_dev_overlay_create(ol_create.ulWidth,
ol_create.ulHeight, 0) < 0) {
@@ -604,8 +607,9 @@ static int kyrofb_ioctl(struct inode *inode, struct file *file,
}
break;
case KYRO_IOCTL_OVERLAY_VIEWPORT_SET:
- copy_from_user(&ol_viewport_set, argp,
- sizeof(overlay_viewport_set));
+ if (copy_from_user(&ol_viewport_set, argp,
+ sizeof(overlay_viewport_set)))
+ return -EFAULT;
if (kyro_dev_overlay_viewport_set(ol_viewport_set.xOrgin,
ol_viewport_set.yOrgin,
@@ -625,13 +629,16 @@ static int kyrofb_ioctl(struct inode *inode, struct file *file,
}
break;
case KYRO_IOCTL_UVSTRIDE:
- copy_to_user(argp, &deviceInfo.ulOverlayUVStride, sizeof(unsigned long));
+ if (copy_to_user(argp, &deviceInfo.ulOverlayUVStride, sizeof(unsigned long)))
+ return -EFAULT;
break;
case KYRO_IOCTL_STRIDE:
- copy_to_user(argp, &deviceInfo.ulOverlayStride, sizeof(unsigned long));
+ if (copy_to_user(argp, &deviceInfo.ulOverlayStride, sizeof(unsigned long)))
+ return -EFAULT;
break;
case KYRO_IOCTL_OVERLAY_OFFSET:
- copy_to_user(argp, &deviceInfo.ulOverlayOffset, sizeof(unsigned long));
+ if (copy_to_user(argp, &deviceInfo.ulOverlayOffset, sizeof(unsigned long)))
+ return -EFAULT;
break;
}
@@ -786,7 +793,7 @@ static void __devexit kyrofb_remove(struct pci_dev *pdev)
kfree(info);
}
-int __init kyrofb_init(void)
+static int __init kyrofb_init(void)
{
#ifndef MODULE
char *option = NULL;
@@ -795,7 +802,7 @@ int __init kyrofb_init(void)
return -ENODEV;
kyrofb_setup(option);
#endif
- return pci_module_init(&kyrofb_pci_driver);
+ return pci_register_driver(&kyrofb_pci_driver);
}
static void __exit kyrofb_exit(void)
diff --git a/drivers/video/logo/Kconfig b/drivers/video/logo/Kconfig
index badf0cb9dc872..849b47b210ec0 100644
--- a/drivers/video/logo/Kconfig
+++ b/drivers/video/logo/Kconfig
@@ -25,7 +25,7 @@ config LOGO_LINUX_CLUT224
config LOGO_DEC_CLUT224
bool "224-color Digital Equipment Corporation Linux logo"
- depends on LOGO && MACH_DECSTATION
+ depends on LOGO && (MACH_DECSTATION || ALPHA)
default y
config LOGO_MAC_CLUT224
diff --git a/drivers/video/logo/Makefile b/drivers/video/logo/Makefile
index 662acb17e6692..b0d995020bd16 100644
--- a/drivers/video/logo/Makefile
+++ b/drivers/video/logo/Makefile
@@ -23,35 +23,32 @@ logo-cfiles = $(notdir $(patsubst %.$(2), %.c, \
# Mono logos
extra-y += $(call logo-cfiles,_mono,pbm)
-quiet_cmd_logo_mono = MONO $@
- cmd_logo_mono = scripts/pnmtologo -t mono -n $*_mono -o $@ $<
-
-$(obj)/%_mono.c: $(src)/%_mono.pbm FORCE
- $(call if_changed,logo_mono)
-
# VGA16 logos
extra-y += $(call logo-cfiles,_vga16,ppm)
-quiet_cmd_logo_vga16 = VGA16 $@
- cmd_logo_vga16 = scripts/pnmtologo -t vga16 -n $*_vga16 -o $@ $<
-
-$(obj)/%_vga16.c: $(src)/%_vga16.ppm FORCE
- $(call if_changed,logo_vga16)
-
-#224 Logos
+# 224 Logos
extra-y += $(call logo-cfiles,_clut224,ppm)
-quiet_cmd_logo_clut224 = CLUT224 $@
- cmd_logo_clut224 = scripts/pnmtologo -t clut224 -n $*_clut224 -o $@ $<
-
-$(obj)/%_clut224.c: $(src)/%_clut224.ppm FORCE
- $(call if_changed,logo_clut224)
-
# Gray 256
extra-y += $(call logo-cfiles,_gray256,pgm)
-quiet_cmd_logo_gray256 = GRAY256 $@
- cmd_logo_gray256 = scripts/pnmtologo -t gray256 -n $*_gray256 -o $@ $<
+# Create commands like "pnmtologo -t mono -n logo_mac_mono -o ..."
+quiet_cmd_logo = LOGO $@
+ cmd_logo = scripts/pnmtologo \
+ -t $(patsubst $*_%,%,$(notdir $(basename $<))) \
+ -n $(notdir $(basename $<)) -o $@ $<
+
+$(obj)/%_mono.c: $(src)/%_mono.pbm FORCE
+ $(call if_changed,logo)
+
+$(obj)/%_vga16.c: $(src)/%_vga16.ppm FORCE
+ $(call if_changed,logo)
+
+$(obj)/%_clut224.c: $(src)/%_clut224.ppm FORCE
+ $(call if_changed,logo)
$(obj)/%_gray256.c: $(src)/%_gray256.pgm FORCE
- $(call if_changed,logo_gray256)
+ $(call if_changed,logo)
+
+# Files generated that shall be removed upon make clean
+clean-files := *.o *_mono.c *_vga16.c *_clut224.c *_gray256.c
diff --git a/drivers/video/logo/logo.c b/drivers/video/logo/logo.c
index 0ba8d342fab02..77b6220750015 100644
--- a/drivers/video/logo/logo.c
+++ b/drivers/video/logo/logo.c
@@ -12,6 +12,7 @@
#include <linux/config.h>
#include <linux/linux_logo.h>
#include <linux/stddef.h>
+#include <linux/module.h>
#ifdef CONFIG_M68K
#include <asm/setup.h>
@@ -66,8 +67,10 @@ const struct linux_logo *fb_find_logo(int depth)
logo = &logo_linux_clut224;
#endif
#ifdef CONFIG_LOGO_DEC_CLUT224
- /* DEC Linux logo on MIPS/MIPS64 */
+ /* DEC Linux logo on MIPS/MIPS64 or ALPHA */
+#ifndef CONFIG_ALPHA
if (mips_machgroup == MACH_GROUP_DEC)
+#endif
logo = &logo_dec_clut224;
#endif
#ifdef CONFIG_LOGO_MAC_CLUT224
@@ -97,4 +100,4 @@ const struct linux_logo *fb_find_logo(int depth)
}
return logo;
}
-
+EXPORT_SYMBOL_GPL(fb_find_logo);
diff --git a/drivers/video/macmodes.c b/drivers/video/macmodes.c
index 3cd1145a6c662..de5a0f3836008 100644
--- a/drivers/video/macmodes.c
+++ b/drivers/video/macmodes.c
@@ -19,6 +19,7 @@
#include <linux/errno.h>
#include <linux/fb.h>
#include <linux/string.h>
+#include <linux/module.h>
#include "macmodes.h"
@@ -281,7 +282,7 @@ int mac_vmode_to_var(int vmode, int cmode, struct fb_var_screeninfo *var)
var->vmode = mode->vmode;
return 0;
}
-
+EXPORT_SYMBOL(mac_vmode_to_var);
/**
* mac_var_to_vmode - convert var structure to MacOS vmode/cmode pair
@@ -326,7 +327,7 @@ int mac_var_to_vmode(const struct fb_var_screeninfo *var, int *vmode,
}
return -EINVAL;
}
-
+EXPORT_SYMBOL(mac_var_to_vmode);
/**
* mac_map_monitor_sense - Convert monitor sense to vmode
@@ -348,7 +349,7 @@ int mac_map_monitor_sense(int sense)
break;
return map->vmode;
}
-
+EXPORT_SYMBOL(mac_map_monitor_sense);
/**
* mac_find_mode - find a video mode
@@ -384,3 +385,5 @@ int __init mac_find_mode(struct fb_var_screeninfo *var, struct fb_info *info,
return fb_find_mode(var, info, mode_option, db, dbsize,
&mac_modedb[DEFAULT_MODEDB_INDEX], default_bpp);
}
+EXPORT_SYMBOL(mac_find_mode);
+
diff --git a/drivers/video/matrox/matroxfb_accel.c b/drivers/video/matrox/matroxfb_accel.c
index 8f14c9b300c28..c7f3e1321224d 100644
--- a/drivers/video/matrox/matroxfb_accel.c
+++ b/drivers/video/matrox/matroxfb_accel.c
@@ -438,13 +438,21 @@ static void matroxfb_1bpp_imageblit(WPMINFO u_int32_t fgx, u_int32_t bgx,
} else if (step == 1) {
/* Special case for 1..8bit widths */
while (height--) {
- mga_writel(mmio, 0, *chardata);
+#if defined(__BIG_ENDIAN)
+ fb_writel((*chardata) << 24, mmio.vaddr);
+#else
+ fb_writel(*chardata, mmio.vaddr);
+#endif
chardata++;
}
} else if (step == 2) {
/* Special case for 9..15bit widths */
while (height--) {
- mga_writel(mmio, 0, *(u_int16_t*)chardata);
+#if defined(__BIG_ENDIAN)
+ fb_writel((*(u_int16_t*)chardata) << 16, mmio.vaddr);
+#else
+ fb_writel(*(u_int16_t*)chardata, mmio.vaddr);
+#endif
chardata += 2;
}
} else {
@@ -454,7 +462,7 @@ static void matroxfb_1bpp_imageblit(WPMINFO u_int32_t fgx, u_int32_t bgx,
for (i = 0; i < step; i += 4) {
/* Hope that there are at least three readable bytes beyond the end of bitmap */
- mga_writel(mmio, 0, get_unaligned((u_int32_t*)(chardata + i)));
+ fb_writel(get_unaligned((u_int32_t*)(chardata + i)),mmio.vaddr);
}
chardata += step;
}
diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c
index cc37117f4c052..98e00d8601e5b 100644
--- a/drivers/video/matrox/matroxfb_base.c
+++ b/drivers/video/matrox/matroxfb_base.c
@@ -1908,8 +1908,8 @@ fail:;
return err;
}
-LIST_HEAD(matroxfb_list);
-LIST_HEAD(matroxfb_driver_list);
+static LIST_HEAD(matroxfb_list);
+static LIST_HEAD(matroxfb_driver_list);
#define matroxfb_l(x) list_entry(x, struct matrox_fb_info, next_fb)
#define matroxfb_driver_l(x) list_entry(x, struct matroxfb_driver, node)
@@ -2287,7 +2287,7 @@ static void __exit matrox_done(void) {
/* ************************* init in-kernel code ************************** */
-int __init matroxfb_setup(char *options) {
+static int __init matroxfb_setup(char *options) {
char *this_opt;
DBG(__FUNCTION__)
@@ -2428,7 +2428,7 @@ int __init matroxfb_setup(char *options) {
static int __initdata initialized = 0;
-int __init matroxfb_init(void)
+static int __init matroxfb_init(void)
{
char *option = NULL;
diff --git a/drivers/video/matrox/matroxfb_base.h b/drivers/video/matrox/matroxfb_base.h
index a98de7952868c..85a0b25584527 100644
--- a/drivers/video/matrox/matroxfb_base.h
+++ b/drivers/video/matrox/matroxfb_base.h
@@ -170,14 +170,14 @@ static inline void mga_memcpy_toio(vaddr_t va, const void* src, int len) {
if ((unsigned long)src & 3) {
while (len >= 4) {
- writel(get_unaligned((u32 *)src), addr);
+ fb_writel(get_unaligned((u32 *)src), addr);
addr++;
len -= 4;
src += 4;
}
} else {
while (len >= 4) {
- writel(*(u32 *)src, addr);
+ fb_writel(*(u32 *)src, addr);
addr++;
len -= 4;
src += 4;
@@ -764,7 +764,6 @@ void matroxfb_unregister_driver(struct matroxfb_driver* drv);
#define matroxfb_DAC_unlock_irqrestore(flags) spin_unlock_irqrestore(&ACCESS_FBINFO(lock.DAC),flags)
extern void matroxfb_DAC_out(CPMINFO int reg, int val);
extern int matroxfb_DAC_in(CPMINFO int reg);
-extern struct list_head matroxfb_list;
extern void matroxfb_var2my(struct fb_var_screeninfo* fvsi, struct my_timming* mt);
extern int matroxfb_wait_for_sync(WPMINFO u_int32_t crtc);
extern int matroxfb_enable_irq(WPMINFO int reenable);
diff --git a/drivers/video/modedb.c b/drivers/video/modedb.c
index 951b036353566..fbf659b6dab01 100644
--- a/drivers/video/modedb.c
+++ b/drivers/video/modedb.c
@@ -37,7 +37,7 @@ const char *global_mode_option;
#define DEFAULT_MODEDB_INDEX 0
-static const __init struct fb_videomode modedb[] = {
+static const struct fb_videomode modedb[] = {
{
/* 640x400 @ 70 Hz, 31.5 kHz hsync */
NULL, 70, 640, 400, 39721, 40, 24, 39, 9, 96, 2,
@@ -404,8 +404,8 @@ static int my_atoi(const char *name)
*
*/
-int fb_try_mode(struct fb_var_screeninfo *var, struct fb_info *info,
- const struct fb_videomode *mode, unsigned int bpp)
+static int fb_try_mode(struct fb_var_screeninfo *var, struct fb_info *info,
+ const struct fb_videomode *mode, unsigned int bpp)
{
int err = 0;
@@ -722,6 +722,47 @@ struct fb_videomode *fb_find_best_mode(struct fb_var_screeninfo *var,
}
/**
+ * fb_find_nearest_mode - find mode closest video mode
+ *
+ * @var: pointer to struct fb_var_screeninfo
+ * @head: pointer to modelist
+ *
+ * Finds best matching videomode, smaller or greater in dimension.
+ * If more than 1 videomode is found, will return the videomode with
+ * the closest refresh rate
+ */
+struct fb_videomode *fb_find_nearest_mode(struct fb_var_screeninfo *var,
+ struct list_head *head)
+{
+ struct list_head *pos;
+ struct fb_modelist *modelist;
+ struct fb_videomode *mode, *best = NULL;
+ u32 diff = -1, diff_refresh = -1;
+
+ list_for_each(pos, head) {
+ u32 d;
+
+ modelist = list_entry(pos, struct fb_modelist, list);
+ mode = &modelist->mode;
+
+ d = abs(mode->xres - var->xres) +
+ abs(mode->yres - var->yres);
+ if (diff > d) {
+ diff = d;
+ best = mode;
+ } else if (diff == d) {
+ d = abs(mode->refresh - best->refresh);
+ if (diff_refresh > d) {
+ diff_refresh = d;
+ best = mode;
+ }
+ }
+ }
+
+ return best;
+}
+
+/**
* fb_match_mode - find a videomode which exactly matches the timings in var
* @var: pointer to struct fb_var_screeninfo
* @head: pointer to struct list_head of modelist
@@ -846,5 +887,6 @@ EXPORT_SYMBOL(fb_delete_videomode);
EXPORT_SYMBOL(fb_destroy_modelist);
EXPORT_SYMBOL(fb_match_mode);
EXPORT_SYMBOL(fb_find_best_mode);
+EXPORT_SYMBOL(fb_find_nearest_mode);
EXPORT_SYMBOL(fb_videomode_to_modelist);
EXPORT_SYMBOL(fb_find_mode);
diff --git a/drivers/video/neofb.c b/drivers/video/neofb.c
index f9e0dd7f1c535..5d424a30270ac 100644
--- a/drivers/video/neofb.c
+++ b/drivers/video/neofb.c
@@ -93,7 +93,7 @@ static int external;
static int libretto;
static int nostretch;
static int nopciburst;
-static char *mode_option __initdata = NULL;
+static char *mode_option __devinitdata = NULL;
#ifdef MODULE
@@ -400,21 +400,21 @@ static void neoUnlock(void)
*/
static int paletteEnabled = 0;
-inline void VGAenablePalette(void)
+static inline void VGAenablePalette(void)
{
vga_r(NULL, VGA_IS1_RC);
vga_w(NULL, VGA_ATT_W, 0x00);
paletteEnabled = 1;
}
-inline void VGAdisablePalette(void)
+static inline void VGAdisablePalette(void)
{
vga_r(NULL, VGA_IS1_RC);
vga_w(NULL, VGA_ATT_W, 0x20);
paletteEnabled = 0;
}
-inline void VGAwATTR(u8 index, u8 value)
+static inline void VGAwATTR(u8 index, u8 value)
{
if (paletteEnabled)
index &= ~0x20;
@@ -425,7 +425,7 @@ inline void VGAwATTR(u8 index, u8 value)
vga_wattr(NULL, index, value);
}
-void vgaHWProtect(int on)
+static void vgaHWProtect(int on)
{
unsigned char tmp;
@@ -1315,7 +1315,7 @@ static int neofb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
/*
* (Un)Blank the display.
*/
-int neofb_blank(int blank_mode, struct fb_info *info)
+static int neofb_blank(int blank_mode, struct fb_info *info)
{
/*
* Blank the screen if blank_mode != 0, else unblank.
@@ -1691,7 +1691,27 @@ static int __devinit neo_map_mmio(struct fb_info *info,
DBG("neo_map_mmio");
- info->fix.mmio_start = pci_resource_start(dev, 1);
+ switch (info->fix.accel) {
+ case FB_ACCEL_NEOMAGIC_NM2070:
+ info->fix.mmio_start = pci_resource_start(dev, 0)+
+ 0x100000;
+ break;
+ case FB_ACCEL_NEOMAGIC_NM2090:
+ case FB_ACCEL_NEOMAGIC_NM2093:
+ info->fix.mmio_start = pci_resource_start(dev, 0)+
+ 0x200000;
+ break;
+ case FB_ACCEL_NEOMAGIC_NM2160:
+ case FB_ACCEL_NEOMAGIC_NM2097:
+ case FB_ACCEL_NEOMAGIC_NM2200:
+ case FB_ACCEL_NEOMAGIC_NM2230:
+ case FB_ACCEL_NEOMAGIC_NM2360:
+ case FB_ACCEL_NEOMAGIC_NM2380:
+ info->fix.mmio_start = pci_resource_start(dev, 1);
+ break;
+ default:
+ info->fix.mmio_start = pci_resource_start(dev, 0);
+ }
info->fix.mmio_len = MMIO_SIZE;
if (!request_mem_region
@@ -2010,6 +2030,7 @@ static struct fb_info *__devinit neo_alloc_fb_info(struct pci_dev *dev, const st
par->internal_display = internal;
par->external_display = external;
+ info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
switch (info->fix.accel) {
case FB_ACCEL_NEOMAGIC_NM2070:
@@ -2029,15 +2050,27 @@ static struct fb_info *__devinit neo_alloc_fb_info(struct pci_dev *dev, const st
break;
case FB_ACCEL_NEOMAGIC_NM2200:
sprintf(info->fix.id, "MagicGraph 256AV");
+ info->flags |= FBINFO_HWACCEL_IMAGEBLIT |
+ FBINFO_HWACCEL_COPYAREA |
+ FBINFO_HWACCEL_FILLRECT;
break;
case FB_ACCEL_NEOMAGIC_NM2230:
sprintf(info->fix.id, "MagicGraph 256AV+");
+ info->flags |= FBINFO_HWACCEL_IMAGEBLIT |
+ FBINFO_HWACCEL_COPYAREA |
+ FBINFO_HWACCEL_FILLRECT;
break;
case FB_ACCEL_NEOMAGIC_NM2360:
sprintf(info->fix.id, "MagicGraph 256ZX");
+ info->flags |= FBINFO_HWACCEL_IMAGEBLIT |
+ FBINFO_HWACCEL_COPYAREA |
+ FBINFO_HWACCEL_FILLRECT;
break;
case FB_ACCEL_NEOMAGIC_NM2380:
sprintf(info->fix.id, "MagicGraph 256XL+");
+ info->flags |= FBINFO_HWACCEL_IMAGEBLIT |
+ FBINFO_HWACCEL_COPYAREA |
+ FBINFO_HWACCEL_FILLRECT;
break;
}
@@ -2049,9 +2082,6 @@ 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->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN |
- FBINFO_HWACCEL_IMAGEBLIT | FBINFO_HWACCEL_COPYAREA |
- FBINFO_HWACCEL_COPYAREA;
info->pseudo_palette = (void *) (par + 1);
return info;
}
@@ -2230,7 +2260,8 @@ static struct pci_driver neofb_driver = {
/* ************************* init in-kernel code ************************** */
-int __init neofb_setup(char *options)
+#ifndef MODULE
+static int __init neofb_setup(char *options)
{
char *this_opt;
@@ -2258,8 +2289,9 @@ int __init neofb_setup(char *options)
}
return 0;
}
+#endif /* MODULE */
-int __init neofb_init(void)
+static int __init neofb_init(void)
{
#ifndef MODULE
char *option = NULL;
diff --git a/drivers/video/nvidia/Makefile b/drivers/video/nvidia/Makefile
new file mode 100644
index 0000000000000..690d37e8de5bb
--- /dev/null
+++ b/drivers/video/nvidia/Makefile
@@ -0,0 +1,12 @@
+#
+# Makefile for the nVidia framebuffer driver
+#
+
+obj-$(CONFIG_FB_NVIDIA) += nvidiafb.o
+
+nvidiafb-y := nvidia.o nv_hw.o nv_setup.o \
+ nv_accel.o
+nvidiafb-$(CONFIG_FB_NVIDIA_I2C) += nv_i2c.o
+nvidiafb-$(CONFIG_PPC_OF) += nv_of.o
+
+nvidiafb-objs := $(nvidiafb-y) \ No newline at end of file
diff --git a/drivers/video/nvidia/nv_accel.c b/drivers/video/nvidia/nv_accel.c
new file mode 100644
index 0000000000000..f377a29ec97a6
--- /dev/null
+++ b/drivers/video/nvidia/nv_accel.c
@@ -0,0 +1,419 @@
+ /***************************************************************************\
+|* *|
+|* Copyright 1993-2003 NVIDIA, Corporation. All rights reserved. *|
+|* *|
+|* NOTICE TO USER: The source code is copyrighted under U.S. and *|
+|* international laws. Users and possessors of this source code are *|
+|* hereby granted a nonexclusive, royalty-free copyright license to *|
+|* use this code in individual and commercial software. *|
+|* *|
+|* Any use of this source code must include, in the user documenta- *|
+|* tion and internal comments to the code, notices to the end user *|
+|* as follows: *|
+|* *|
+|* Copyright 1993-2003 NVIDIA, Corporation. All rights reserved. *|
+|* *|
+|* NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY *|
+|* OF THIS SOURCE CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" *|
+|* WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND. NVIDIA, CORPOR- *|
+|* ATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOURCE CODE, *|
+|* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE- *|
+|* MENT, AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL *|
+|* NVIDIA, CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT, INCI- *|
+|* DENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RE- *|
+|* SULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION *|
+|* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF *|
+|* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE. *|
+|* *|
+|* U.S. Government End Users. This source code is a "commercial *|
+|* item," as that term is defined at 48 C.F.R. 2.101 (OCT 1995), *|
+|* consisting of "commercial computer software" and "commercial *|
+|* computer software documentation," as such terms are used in *|
+|* 48 C.F.R. 12.212 (SEPT 1995) and is provided to the U.S. Govern- *|
+|* ment only as a commercial end item. Consistent with 48 C.F.R. *|
+|* 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (JUNE 1995), *|
+|* all U.S. Government End Users acquire the source code with only *|
+|* those rights set forth herein. *|
+|* *|
+ \***************************************************************************/
+
+/*
+ * GPL Licensing Note - According to Mark Vojkovich, author of the Xorg/
+ * XFree86 'nv' driver, this source code is provided under MIT-style licensing
+ * where the source code is provided "as is" without warranty of any kind.
+ * The only usage restriction is for the copyright notices to be retained
+ * whenever code is used.
+ *
+ * Antonino Daplas <adaplas@pol.net> 2005-03-11
+ */
+
+#include <linux/fb.h>
+#include "nv_type.h"
+#include "nv_proto.h"
+#include "nv_dma.h"
+#include "nv_local.h"
+
+/* There is a HW race condition with videoram command buffers.
+ You can't jump to the location of your put offset. We write put
+ at the jump offset + SKIPS dwords with noop padding in between
+ to solve this problem */
+#define SKIPS 8
+
+static const int NVCopyROP[16] = {
+ 0xCC, /* copy */
+ 0x55 /* invert */
+};
+
+static const int NVCopyROP_PM[16] = {
+ 0xCA, /* copy */
+ 0x5A, /* invert */
+};
+
+static inline void NVFlush(struct nvidia_par *par)
+{
+ int count = 1000000000;
+
+ while (--count && READ_GET(par) != par->dmaPut) ;
+
+ if (!count) {
+ printk("nvidiafb: DMA Flush lockup\n");
+ par->lockup = 1;
+ }
+}
+
+static inline void NVSync(struct nvidia_par *par)
+{
+ int count = 1000000000;
+
+ while (--count && NV_RD32(par->PGRAPH, 0x0700)) ;
+
+ if (!count) {
+ printk("nvidiafb: DMA Sync lockup\n");
+ par->lockup = 1;
+ }
+}
+
+static void NVDmaKickoff(struct nvidia_par *par)
+{
+ if (par->dmaCurrent != par->dmaPut) {
+ par->dmaPut = par->dmaCurrent;
+ WRITE_PUT(par, par->dmaPut);
+ }
+}
+
+static void NVDmaWait(struct nvidia_par *par, int size)
+{
+ int dmaGet;
+ int count = 1000000000, cnt;
+ size++;
+
+ while (par->dmaFree < size && --count && !par->lockup) {
+ dmaGet = READ_GET(par);
+
+ if (par->dmaPut >= dmaGet) {
+ par->dmaFree = par->dmaMax - par->dmaCurrent;
+ if (par->dmaFree < size) {
+ NVDmaNext(par, 0x20000000);
+ if (dmaGet <= SKIPS) {
+ if (par->dmaPut <= SKIPS)
+ WRITE_PUT(par, SKIPS + 1);
+ cnt = 1000000000;
+ do {
+ dmaGet = READ_GET(par);
+ } while (--cnt && dmaGet <= SKIPS);
+ if (!cnt) {
+ printk("DMA Get lockup\n");
+ par->lockup = 1;
+ }
+ }
+ WRITE_PUT(par, SKIPS);
+ par->dmaCurrent = par->dmaPut = SKIPS;
+ par->dmaFree = dmaGet - (SKIPS + 1);
+ }
+ } else
+ par->dmaFree = dmaGet - par->dmaCurrent - 1;
+ }
+
+ if (!count) {
+ printk("DMA Wait Lockup\n");
+ par->lockup = 1;
+ }
+}
+
+static void NVSetPattern(struct nvidia_par *par, u32 clr0, u32 clr1,
+ u32 pat0, u32 pat1)
+{
+ NVDmaStart(par, PATTERN_COLOR_0, 4);
+ NVDmaNext(par, clr0);
+ NVDmaNext(par, clr1);
+ NVDmaNext(par, pat0);
+ NVDmaNext(par, pat1);
+}
+
+static void NVSetRopSolid(struct nvidia_par *par, u32 rop, u32 planemask)
+{
+ if (planemask != ~0) {
+ NVSetPattern(par, 0, planemask, ~0, ~0);
+ if (par->currentRop != (rop + 32)) {
+ NVDmaStart(par, ROP_SET, 1);
+ NVDmaNext(par, NVCopyROP_PM[rop]);
+ par->currentRop = rop + 32;
+ }
+ } else if (par->currentRop != rop) {
+ if (par->currentRop >= 16)
+ NVSetPattern(par, ~0, ~0, ~0, ~0);
+ NVDmaStart(par, ROP_SET, 1);
+ NVDmaNext(par, NVCopyROP[rop]);
+ par->currentRop = rop;
+ }
+}
+
+static void NVSetClippingRectangle(struct fb_info *info, int x1, int y1,
+ int x2, int y2)
+{
+ struct nvidia_par *par = info->par;
+ int h = y2 - y1 + 1;
+ int w = x2 - x1 + 1;
+
+ NVDmaStart(par, CLIP_POINT, 2);
+ NVDmaNext(par, (y1 << 16) | x1);
+ NVDmaNext(par, (h << 16) | w);
+}
+
+void NVResetGraphics(struct fb_info *info)
+{
+ struct nvidia_par *par = info->par;
+ u32 surfaceFormat, patternFormat, rectFormat, lineFormat;
+ int pitch, i;
+
+ pitch = info->fix.line_length;
+
+ par->dmaBase = (u32 __iomem *) (&par->FbStart[par->FbUsableSize]);
+
+ for (i = 0; i < SKIPS; i++)
+ NV_WR32(&par->dmaBase[i], 0, 0x00000000);
+
+ NV_WR32(&par->dmaBase[0x0 + SKIPS], 0, 0x00040000);
+ NV_WR32(&par->dmaBase[0x1 + SKIPS], 0, 0x80000010);
+ NV_WR32(&par->dmaBase[0x2 + SKIPS], 0, 0x00042000);
+ NV_WR32(&par->dmaBase[0x3 + SKIPS], 0, 0x80000011);
+ NV_WR32(&par->dmaBase[0x4 + SKIPS], 0, 0x00044000);
+ NV_WR32(&par->dmaBase[0x5 + SKIPS], 0, 0x80000012);
+ NV_WR32(&par->dmaBase[0x6 + SKIPS], 0, 0x00046000);
+ NV_WR32(&par->dmaBase[0x7 + SKIPS], 0, 0x80000013);
+ NV_WR32(&par->dmaBase[0x8 + SKIPS], 0, 0x00048000);
+ NV_WR32(&par->dmaBase[0x9 + SKIPS], 0, 0x80000014);
+ NV_WR32(&par->dmaBase[0xA + SKIPS], 0, 0x0004A000);
+ NV_WR32(&par->dmaBase[0xB + SKIPS], 0, 0x80000015);
+ NV_WR32(&par->dmaBase[0xC + SKIPS], 0, 0x0004C000);
+ NV_WR32(&par->dmaBase[0xD + SKIPS], 0, 0x80000016);
+ NV_WR32(&par->dmaBase[0xE + SKIPS], 0, 0x0004E000);
+ NV_WR32(&par->dmaBase[0xF + SKIPS], 0, 0x80000017);
+
+ par->dmaPut = 0;
+ par->dmaCurrent = 16 + SKIPS;
+ par->dmaMax = 8191;
+ par->dmaFree = par->dmaMax - par->dmaCurrent;
+
+ switch (info->var.bits_per_pixel) {
+ case 32:
+ case 24:
+ surfaceFormat = SURFACE_FORMAT_DEPTH24;
+ patternFormat = PATTERN_FORMAT_DEPTH24;
+ rectFormat = RECT_FORMAT_DEPTH24;
+ lineFormat = LINE_FORMAT_DEPTH24;
+ break;
+ case 16:
+ surfaceFormat = SURFACE_FORMAT_DEPTH16;
+ patternFormat = PATTERN_FORMAT_DEPTH16;
+ rectFormat = RECT_FORMAT_DEPTH16;
+ lineFormat = LINE_FORMAT_DEPTH16;
+ break;
+ default:
+ surfaceFormat = SURFACE_FORMAT_DEPTH8;
+ patternFormat = PATTERN_FORMAT_DEPTH8;
+ rectFormat = RECT_FORMAT_DEPTH8;
+ lineFormat = LINE_FORMAT_DEPTH8;
+ break;
+ }
+
+ NVDmaStart(par, SURFACE_FORMAT, 4);
+ NVDmaNext(par, surfaceFormat);
+ NVDmaNext(par, pitch | (pitch << 16));
+ NVDmaNext(par, 0);
+ NVDmaNext(par, 0);
+
+ NVDmaStart(par, PATTERN_FORMAT, 1);
+ NVDmaNext(par, patternFormat);
+
+ NVDmaStart(par, RECT_FORMAT, 1);
+ NVDmaNext(par, rectFormat);
+
+ NVDmaStart(par, LINE_FORMAT, 1);
+ NVDmaNext(par, lineFormat);
+
+ par->currentRop = ~0; /* set to something invalid */
+ NVSetRopSolid(par, ROP_COPY, ~0);
+
+ NVSetClippingRectangle(info, 0, 0, info->var.xres_virtual,
+ info->var.yres_virtual);
+
+ NVDmaKickoff(par);
+}
+
+u8 byte_rev[256] = {
+ 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
+ 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
+ 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
+ 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
+ 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
+ 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
+ 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
+ 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
+ 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
+ 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
+ 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
+ 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
+ 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
+ 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
+ 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
+ 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
+ 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
+ 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
+ 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
+ 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
+ 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
+ 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
+ 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
+ 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
+ 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
+ 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
+ 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
+ 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
+ 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
+ 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
+ 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
+ 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
+};
+
+int nvidiafb_sync(struct fb_info *info)
+{
+ struct nvidia_par *par = info->par;
+
+ if (!par->lockup)
+ NVFlush(par);
+
+ if (!par->lockup)
+ NVSync(par);
+
+ return 0;
+}
+
+void nvidiafb_copyarea(struct fb_info *info, const struct fb_copyarea *region)
+{
+ struct nvidia_par *par = info->par;
+
+ if (par->lockup)
+ return cfb_copyarea(info, region);
+
+ NVDmaStart(par, BLIT_POINT_SRC, 3);
+ NVDmaNext(par, (region->sy << 16) | region->sx);
+ NVDmaNext(par, (region->dy << 16) | region->dx);
+ NVDmaNext(par, (region->height << 16) | region->width);
+
+ NVDmaKickoff(par);
+}
+
+void nvidiafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+{
+ struct nvidia_par *par = info->par;
+ u32 color;
+
+ if (par->lockup)
+ return cfb_fillrect(info, rect);
+
+ if (info->var.bits_per_pixel == 8)
+ color = rect->color;
+ else
+ color = ((u32 *) info->pseudo_palette)[rect->color];
+
+ if (rect->rop != ROP_COPY)
+ NVSetRopSolid(par, rect->rop, ~0);
+
+ NVDmaStart(par, RECT_SOLID_COLOR, 1);
+ NVDmaNext(par, color);
+
+ NVDmaStart(par, RECT_SOLID_RECTS(0), 2);
+ NVDmaNext(par, (rect->dx << 16) | rect->dy);
+ NVDmaNext(par, (rect->width << 16) | rect->height);
+
+ NVDmaKickoff(par);
+
+ if (rect->rop != ROP_COPY)
+ NVSetRopSolid(par, ROP_COPY, ~0);
+}
+
+static void nvidiafb_mono_color_expand(struct fb_info *info,
+ const struct fb_image *image)
+{
+ struct nvidia_par *par = info->par;
+ u32 fg, bg, mask = ~(~0 >> (32 - info->var.bits_per_pixel));
+ u32 dsize, width, *data = (u32 *) image->data, tmp;
+ int j, k = 0;
+
+ width = (image->width + 31) & ~31;
+ dsize = (width * image->height) >> 5;
+
+ if (info->var.bits_per_pixel == 8) {
+ fg = image->fg_color | mask;
+ bg = image->bg_color | mask;
+ } else {
+ fg = ((u32 *) info->pseudo_palette)[image->fg_color] | mask;
+ bg = ((u32 *) info->pseudo_palette)[image->bg_color] | mask;
+ }
+
+ NVDmaStart(par, RECT_EXPAND_TWO_COLOR_CLIP, 7);
+ NVDmaNext(par, (image->dy << 16) | (image->dx & 0xffff));
+ NVDmaNext(par, ((image->dy + image->height) << 16) |
+ ((image->dx + image->width) & 0xffff));
+ NVDmaNext(par, bg);
+ NVDmaNext(par, fg);
+ NVDmaNext(par, (image->height << 16) | width);
+ NVDmaNext(par, (image->height << 16) | width);
+ NVDmaNext(par, (image->dy << 16) | (image->dx & 0xffff));
+
+ while (dsize >= RECT_EXPAND_TWO_COLOR_DATA_MAX_DWORDS) {
+ NVDmaStart(par, RECT_EXPAND_TWO_COLOR_DATA(0),
+ RECT_EXPAND_TWO_COLOR_DATA_MAX_DWORDS);
+
+ for (j = RECT_EXPAND_TWO_COLOR_DATA_MAX_DWORDS; j--;) {
+ tmp = data[k++];
+ reverse_order(&tmp);
+ NVDmaNext(par, tmp);
+ }
+
+ dsize -= RECT_EXPAND_TWO_COLOR_DATA_MAX_DWORDS;
+ }
+
+ if (dsize) {
+ NVDmaStart(par, RECT_EXPAND_TWO_COLOR_DATA(0), dsize);
+
+ for (j = dsize; j--;) {
+ tmp = data[k++];
+ reverse_order(&tmp);
+ NVDmaNext(par, tmp);
+ }
+ }
+
+ NVDmaKickoff(par);
+}
+
+void nvidiafb_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+ struct nvidia_par *par = info->par;
+
+ if (image->depth == 1 && !par->lockup)
+ nvidiafb_mono_color_expand(info, image);
+ else
+ cfb_imageblit(info, image);
+}
diff --git a/drivers/video/nvidia/nv_dma.h b/drivers/video/nvidia/nv_dma.h
new file mode 100644
index 0000000000000..a7ed1c0acbbbd
--- /dev/null
+++ b/drivers/video/nvidia/nv_dma.h
@@ -0,0 +1,188 @@
+
+ /***************************************************************************\
+|* *|
+|* Copyright 2003 NVIDIA, Corporation. All rights reserved. *|
+|* *|
+|* NOTICE TO USER: The source code is copyrighted under U.S. and *|
+|* international laws. Users and possessors of this source code are *|
+|* hereby granted a nonexclusive, royalty-free copyright license to *|
+|* use this code in individual and commercial software. *|
+|* *|
+|* Any use of this source code must include, in the user documenta- *|
+|* tion and internal comments to the code, notices to the end user *|
+|* as follows: *|
+|* *|
+|* Copyright 2003 NVIDIA, Corporation. All rights reserved. *|
+|* *|
+|* NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY *|
+|* OF THIS SOURCE CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" *|
+|* WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND. NVIDIA, CORPOR- *|
+|* ATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOURCE CODE, *|
+|* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE- *|
+|* MENT, AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL *|
+|* NVIDIA, CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT, INCI- *|
+|* DENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RE- *|
+|* SULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION *|
+|* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF *|
+|* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE. *|
+|* *|
+|* U.S. Government End Users. This source code is a "commercial *|
+|* item," as that term is defined at 48 C.F.R. 2.101 (OCT 1995), *|
+|* consisting of "commercial computer software" and "commercial *|
+|* computer software documentation," as such terms are used in *|
+|* 48 C.F.R. 12.212 (SEPT 1995) and is provided to the U.S. Govern- *|
+|* ment only as a commercial end item. Consistent with 48 C.F.R. *|
+|* 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (JUNE 1995), *|
+|* all U.S. Government End Users acquire the source code with only *|
+|* those rights set forth herein. *|
+|* *|
+ \***************************************************************************/
+
+/*
+ * GPL Licensing Note - According to Mark Vojkovich, author of the Xorg/
+ * XFree86 'nv' driver, this source code is provided under MIT-style licensing
+ * where the source code is provided "as is" without warranty of any kind.
+ * The only usage restriction is for the copyright notices to be retained
+ * whenever code is used.
+ *
+ * Antonino Daplas <adaplas@pol.net> 2005-03-11
+ */
+
+#define SURFACE_FORMAT 0x00000300
+#define SURFACE_FORMAT_DEPTH8 0x00000001
+#define SURFACE_FORMAT_DEPTH15 0x00000002
+#define SURFACE_FORMAT_DEPTH16 0x00000004
+#define SURFACE_FORMAT_DEPTH24 0x00000006
+#define SURFACE_PITCH 0x00000304
+#define SURFACE_PITCH_SRC 15:0
+#define SURFACE_PITCH_DST 31:16
+#define SURFACE_OFFSET_SRC 0x00000308
+#define SURFACE_OFFSET_DST 0x0000030C
+
+#define ROP_SET 0x00002300
+
+#define PATTERN_FORMAT 0x00004300
+#define PATTERN_FORMAT_DEPTH8 0x00000003
+#define PATTERN_FORMAT_DEPTH16 0x00000001
+#define PATTERN_FORMAT_DEPTH24 0x00000003
+#define PATTERN_COLOR_0 0x00004310
+#define PATTERN_COLOR_1 0x00004314
+#define PATTERN_PATTERN_0 0x00004318
+#define PATTERN_PATTERN_1 0x0000431C
+
+#define CLIP_POINT 0x00006300
+#define CLIP_POINT_X 15:0
+#define CLIP_POINT_Y 31:16
+#define CLIP_SIZE 0x00006304
+#define CLIP_SIZE_WIDTH 15:0
+#define CLIP_SIZE_HEIGHT 31:16
+
+#define LINE_FORMAT 0x00008300
+#define LINE_FORMAT_DEPTH8 0x00000003
+#define LINE_FORMAT_DEPTH16 0x00000001
+#define LINE_FORMAT_DEPTH24 0x00000003
+#define LINE_COLOR 0x00008304
+#define LINE_MAX_LINES 16
+#define LINE_LINES(i) 0x00008400\
+ +(i)*8
+#define LINE_LINES_POINT0_X 15:0
+#define LINE_LINES_POINT0_Y 31:16
+#define LINE_LINES_POINT1_X 47:32
+#define LINE_LINES_POINT1_Y 63:48
+
+#define BLIT_POINT_SRC 0x0000A300
+#define BLIT_POINT_SRC_X 15:0
+#define BLIT_POINT_SRC_Y 31:16
+#define BLIT_POINT_DST 0x0000A304
+#define BLIT_POINT_DST_X 15:0
+#define BLIT_POINT_DST_Y 31:16
+#define BLIT_SIZE 0x0000A308
+#define BLIT_SIZE_WIDTH 15:0
+#define BLIT_SIZE_HEIGHT 31:16
+
+#define RECT_FORMAT 0x0000C300
+#define RECT_FORMAT_DEPTH8 0x00000003
+#define RECT_FORMAT_DEPTH16 0x00000001
+#define RECT_FORMAT_DEPTH24 0x00000003
+#define RECT_SOLID_COLOR 0x0000C3FC
+#define RECT_SOLID_RECTS_MAX_RECTS 32
+#define RECT_SOLID_RECTS(i) 0x0000C400\
+ +(i)*8
+#define RECT_SOLID_RECTS_Y 15:0
+#define RECT_SOLID_RECTS_X 31:16
+#define RECT_SOLID_RECTS_HEIGHT 47:32
+#define RECT_SOLID_RECTS_WIDTH 63:48
+
+#define RECT_EXPAND_ONE_COLOR_CLIP 0x0000C7EC
+#define RECT_EXPAND_ONE_COLOR_CLIP_POINT0_X 15:0
+#define RECT_EXPAND_ONE_COLOR_CLIP_POINT0_Y 31:16
+#define RECT_EXPAND_ONE_COLOR_CLIP_POINT1_X 47:32
+#define RECT_EXPAND_ONE_COLOR_CLIP_POINT1_Y 63:48
+#define RECT_EXPAND_ONE_COLOR_COLOR 0x0000C7F4
+#define RECT_EXPAND_ONE_COLOR_SIZE 0x0000C7F8
+#define RECT_EXPAND_ONE_COLOR_SIZE_WIDTH 15:0
+#define RECT_EXPAND_ONE_COLOR_SIZE_HEIGHT 31:16
+#define RECT_EXPAND_ONE_COLOR_POINT 0x0000C7FC
+#define RECT_EXPAND_ONE_COLOR_POINT_X 15:0
+#define RECT_EXPAND_ONE_COLOR_POINT_Y 31:16
+#define RECT_EXPAND_ONE_COLOR_DATA_MAX_DWORDS 128
+#define RECT_EXPAND_ONE_COLOR_DATA(i) 0x0000C800\
+ +(i)*4
+
+#define RECT_EXPAND_TWO_COLOR_CLIP 0x0000CBE4
+#define RECT_EXPAND_TWO_COLOR_CLIP_POINT0_X 15:0
+#define RECT_EXPAND_TWO_COLOR_CLIP_POINT0_Y 31:16
+#define RECT_EXPAND_TWO_COLOR_CLIP_POINT1_X 47:32
+#define RECT_EXPAND_TWO_COLOR_CLIP_POINT1_Y 63:48
+#define RECT_EXPAND_TWO_COLOR_COLOR_0 0x0000CBEC
+#define RECT_EXPAND_TWO_COLOR_COLOR_1 0x0000CBF0
+#define RECT_EXPAND_TWO_COLOR_SIZE_IN 0x0000CBF4
+#define RECT_EXPAND_TWO_COLOR_SIZE_IN_WIDTH 15:0
+#define RECT_EXPAND_TWO_COLOR_SIZE_IN_HEIGHT 31:16
+#define RECT_EXPAND_TWO_COLOR_SIZE_OUT 0x0000CBF8
+#define RECT_EXPAND_TWO_COLOR_SIZE_OUT_WIDTH 15:0
+#define RECT_EXPAND_TWO_COLOR_SIZE_OUT_HEIGHT 31:16
+#define RECT_EXPAND_TWO_COLOR_POINT 0x0000CBFC
+#define RECT_EXPAND_TWO_COLOR_POINT_X 15:0
+#define RECT_EXPAND_TWO_COLOR_POINT_Y 31:16
+#define RECT_EXPAND_TWO_COLOR_DATA_MAX_DWORDS 128
+#define RECT_EXPAND_TWO_COLOR_DATA(i) 0x0000CC00\
+ +(i)*4
+
+#define STRETCH_BLIT_FORMAT 0x0000E300
+#define STRETCH_BLIT_FORMAT_DEPTH8 0x00000004
+#define STRETCH_BLIT_FORMAT_DEPTH16 0x00000007
+#define STRETCH_BLIT_FORMAT_DEPTH24 0x00000004
+#define STRETCH_BLIT_FORMAT_X8R8G8B8 0x00000004
+#define STRETCH_BLIT_FORMAT_YUYV 0x00000005
+#define STRETCH_BLIT_FORMAT_UYVY 0x00000006
+#define STRETCH_BLIT_CLIP_POINT 0x0000E308
+#define STRETCH_BLIT_CLIP_POINT_X 15:0
+#define STRETCH_BLIT_CLIP_POINT_Y 31:16
+#define STRETCH_BLIT_CLIP_POINT 0x0000E308
+#define STRETCH_BLIT_CLIP_SIZE 0x0000E30C
+#define STRETCH_BLIT_CLIP_SIZE_WIDTH 15:0
+#define STRETCH_BLIT_CLIP_SIZE_HEIGHT 31:16
+#define STRETCH_BLIT_DST_POINT 0x0000E310
+#define STRETCH_BLIT_DST_POINT_X 15:0
+#define STRETCH_BLIT_DST_POINT_Y 31:16
+#define STRETCH_BLIT_DST_SIZE 0x0000E314
+#define STRETCH_BLIT_DST_SIZE_WIDTH 15:0
+#define STRETCH_BLIT_DST_SIZE_HEIGHT 31:16
+#define STRETCH_BLIT_DU_DX 0x0000E318
+#define STRETCH_BLIT_DV_DY 0x0000E31C
+#define STRETCH_BLIT_SRC_SIZE 0x0000E400
+#define STRETCH_BLIT_SRC_SIZE_WIDTH 15:0
+#define STRETCH_BLIT_SRC_SIZE_HEIGHT 31:16
+#define STRETCH_BLIT_SRC_FORMAT 0x0000E404
+#define STRETCH_BLIT_SRC_FORMAT_PITCH 15:0
+#define STRETCH_BLIT_SRC_FORMAT_ORIGIN 23:16
+#define STRETCH_BLIT_SRC_FORMAT_ORIGIN_CENTER 0x00000001
+#define STRETCH_BLIT_SRC_FORMAT_ORIGIN_CORNER 0x00000002
+#define STRETCH_BLIT_SRC_FORMAT_FILTER 31:24
+#define STRETCH_BLIT_SRC_FORMAT_FILTER_POINT_SAMPLE 0x00000000
+#define STRETCH_BLIT_SRC_FORMAT_FILTER_BILINEAR 0x00000001
+#define STRETCH_BLIT_SRC_OFFSET 0x0000E408
+#define STRETCH_BLIT_SRC_POINT 0x0000E40C
+#define STRETCH_BLIT_SRC_POINT_U 15:0
+#define STRETCH_BLIT_SRC_POINT_V 31:16
diff --git a/drivers/video/nvidia/nv_hw.c b/drivers/video/nvidia/nv_hw.c
new file mode 100644
index 0000000000000..b989358437b37
--- /dev/null
+++ b/drivers/video/nvidia/nv_hw.c
@@ -0,0 +1,1593 @@
+ /***************************************************************************\
+|* *|
+|* Copyright 1993-2003 NVIDIA, Corporation. All rights reserved. *|
+|* *|
+|* NOTICE TO USER: The source code is copyrighted under U.S. and *|
+|* international laws. Users and possessors of this source code are *|
+|* hereby granted a nonexclusive, royalty-free copyright license to *|
+|* use this code in individual and commercial software. *|
+|* *|
+|* Any use of this source code must include, in the user documenta- *|
+|* tion and internal comments to the code, notices to the end user *|
+|* as follows: *|
+|* *|
+|* Copyright 1993-2003 NVIDIA, Corporation. All rights reserved. *|
+|* *|
+|* NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY *|
+|* OF THIS SOURCE CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" *|
+|* WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND. NVIDIA, CORPOR- *|
+|* ATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOURCE CODE, *|
+|* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE- *|
+|* MENT, AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL *|
+|* NVIDIA, CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT, INCI- *|
+|* DENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RE- *|
+|* SULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION *|
+|* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF *|
+|* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE. *|
+|* *|
+|* U.S. Government End Users. This source code is a "commercial *|
+|* item," as that term is defined at 48 C.F.R. 2.101 (OCT 1995), *|
+|* consisting of "commercial computer software" and "commercial *|
+|* computer software documentation," as such terms are used in *|
+|* 48 C.F.R. 12.212 (SEPT 1995) and is provided to the U.S. Govern- *|
+|* ment only as a commercial end item. Consistent with 48 C.F.R. *|
+|* 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (JUNE 1995), *|
+|* all U.S. Government End Users acquire the source code with only *|
+|* those rights set forth herein. *|
+|* *|
+ \***************************************************************************/
+
+/*
+ * GPL Licensing Note - According to Mark Vojkovich, author of the Xorg/
+ * XFree86 'nv' driver, this source code is provided under MIT-style licensing
+ * where the source code is provided "as is" without warranty of any kind.
+ * The only usage restriction is for the copyright notices to be retained
+ * whenever code is used.
+ *
+ * Antonino Daplas <adaplas@pol.net> 2005-03-11
+ */
+
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/nv_hw.c,v 1.4 2003/11/03 05:11:25 tsi Exp $ */
+
+#include <linux/pci.h>
+#include "nv_type.h"
+#include "nv_local.h"
+
+void NVLockUnlock(struct nvidia_par *par, int Lock)
+{
+ u8 cr11;
+
+ VGA_WR08(par->PCIO, 0x3D4, 0x1F);
+ VGA_WR08(par->PCIO, 0x3D5, Lock ? 0x99 : 0x57);
+
+ VGA_WR08(par->PCIO, 0x3D4, 0x11);
+ cr11 = VGA_RD08(par->PCIO, 0x3D5);
+ if (Lock)
+ cr11 |= 0x80;
+ else
+ cr11 &= ~0x80;
+ VGA_WR08(par->PCIO, 0x3D5, cr11);
+}
+
+int NVShowHideCursor(struct nvidia_par *par, int ShowHide)
+{
+ int cur = par->CurrentState->cursor1;
+
+ par->CurrentState->cursor1 = (par->CurrentState->cursor1 & 0xFE) |
+ (ShowHide & 0x01);
+ VGA_WR08(par->PCIO, 0x3D4, 0x31);
+ VGA_WR08(par->PCIO, 0x3D5, par->CurrentState->cursor1);
+
+ if (par->Architecture == NV_ARCH_40)
+ NV_WR32(par->PRAMDAC, 0x0300, NV_RD32(par->PRAMDAC, 0x0300));
+
+ return (cur & 0x01);
+}
+
+/****************************************************************************\
+* *
+* The video arbitration routines calculate some "magic" numbers. Fixes *
+* the snow seen when accessing the framebuffer without it. *
+* It just works (I hope). *
+* *
+\****************************************************************************/
+
+typedef struct {
+ int graphics_lwm;
+ int video_lwm;
+ int graphics_burst_size;
+ int video_burst_size;
+ int valid;
+} nv4_fifo_info;
+
+typedef struct {
+ int pclk_khz;
+ int mclk_khz;
+ int nvclk_khz;
+ char mem_page_miss;
+ char mem_latency;
+ int memory_width;
+ char enable_video;
+ char gr_during_vid;
+ char pix_bpp;
+ char mem_aligned;
+ char enable_mp;
+} nv4_sim_state;
+
+typedef struct {
+ int graphics_lwm;
+ int video_lwm;
+ int graphics_burst_size;
+ int video_burst_size;
+ int valid;
+} nv10_fifo_info;
+
+typedef struct {
+ int pclk_khz;
+ int mclk_khz;
+ int nvclk_khz;
+ char mem_page_miss;
+ char mem_latency;
+ int memory_type;
+ int memory_width;
+ char enable_video;
+ char gr_during_vid;
+ char pix_bpp;
+ char mem_aligned;
+ char enable_mp;
+} nv10_sim_state;
+
+static void nvGetClocks(struct nvidia_par *par, unsigned int *MClk,
+ unsigned int *NVClk)
+{
+ unsigned int pll, N, M, MB, NB, P;
+
+ if (par->Architecture >= NV_ARCH_40) {
+ pll = NV_RD32(par->PMC, 0x4020);
+ P = (pll >> 16) & 0x03;
+ pll = NV_RD32(par->PMC, 0x4024);
+ M = pll & 0xFF;
+ N = (pll >> 8) & 0xFF;
+ MB = (pll >> 16) & 0xFF;
+ NB = (pll >> 24) & 0xFF;
+ *MClk = ((N * NB * par->CrystalFreqKHz) / (M * MB)) >> P;
+
+ pll = NV_RD32(par->PMC, 0x4000);
+ P = (pll >> 16) & 0x03;
+ pll = NV_RD32(par->PMC, 0x4004);
+ M = pll & 0xFF;
+ N = (pll >> 8) & 0xFF;
+ MB = (pll >> 16) & 0xFF;
+ NB = (pll >> 24) & 0xFF;
+
+ *NVClk = ((N * NB * par->CrystalFreqKHz) / (M * MB)) >> P;
+ } else if (par->twoStagePLL) {
+ pll = NV_RD32(par->PRAMDAC0, 0x0504);
+ M = pll & 0xFF;
+ N = (pll >> 8) & 0xFF;
+ P = (pll >> 16) & 0x0F;
+ pll = NV_RD32(par->PRAMDAC0, 0x0574);
+ if (pll & 0x80000000) {
+ MB = pll & 0xFF;
+ NB = (pll >> 8) & 0xFF;
+ } else {
+ MB = 1;
+ NB = 1;
+ }
+ *MClk = ((N * NB * par->CrystalFreqKHz) / (M * MB)) >> P;
+
+ pll = NV_RD32(par->PRAMDAC0, 0x0500);
+ M = pll & 0xFF;
+ N = (pll >> 8) & 0xFF;
+ P = (pll >> 16) & 0x0F;
+ pll = NV_RD32(par->PRAMDAC0, 0x0570);
+ if (pll & 0x80000000) {
+ MB = pll & 0xFF;
+ NB = (pll >> 8) & 0xFF;
+ } else {
+ MB = 1;
+ NB = 1;
+ }
+ *NVClk = ((N * NB * par->CrystalFreqKHz) / (M * MB)) >> P;
+ } else
+ if (((par->Chipset & 0x0ff0) == 0x0300) ||
+ ((par->Chipset & 0x0ff0) == 0x0330)) {
+ pll = NV_RD32(par->PRAMDAC0, 0x0504);
+ M = pll & 0x0F;
+ N = (pll >> 8) & 0xFF;
+ P = (pll >> 16) & 0x07;
+ if (pll & 0x00000080) {
+ MB = (pll >> 4) & 0x07;
+ NB = (pll >> 19) & 0x1f;
+ } else {
+ MB = 1;
+ NB = 1;
+ }
+ *MClk = ((N * NB * par->CrystalFreqKHz) / (M * MB)) >> P;
+
+ pll = NV_RD32(par->PRAMDAC0, 0x0500);
+ M = pll & 0x0F;
+ N = (pll >> 8) & 0xFF;
+ P = (pll >> 16) & 0x07;
+ if (pll & 0x00000080) {
+ MB = (pll >> 4) & 0x07;
+ NB = (pll >> 19) & 0x1f;
+ } else {
+ MB = 1;
+ NB = 1;
+ }
+ *NVClk = ((N * NB * par->CrystalFreqKHz) / (M * MB)) >> P;
+ } else {
+ pll = NV_RD32(par->PRAMDAC0, 0x0504);
+ M = pll & 0xFF;
+ N = (pll >> 8) & 0xFF;
+ P = (pll >> 16) & 0x0F;
+ *MClk = (N * par->CrystalFreqKHz / M) >> P;
+
+ pll = NV_RD32(par->PRAMDAC0, 0x0500);
+ M = pll & 0xFF;
+ N = (pll >> 8) & 0xFF;
+ P = (pll >> 16) & 0x0F;
+ *NVClk = (N * par->CrystalFreqKHz / M) >> P;
+ }
+}
+
+static void nv4CalcArbitration(nv4_fifo_info * fifo, nv4_sim_state * arb)
+{
+ int data, pagemiss, cas, width, video_enable, bpp;
+ int nvclks, mclks, pclks, vpagemiss, crtpagemiss, vbs;
+ int found, mclk_extra, mclk_loop, cbs, m1, p1;
+ int mclk_freq, pclk_freq, nvclk_freq, mp_enable;
+ int us_m, us_n, us_p, video_drain_rate, crtc_drain_rate;
+ int vpm_us, us_video, vlwm, video_fill_us, cpm_us, us_crt, clwm;
+
+ fifo->valid = 1;
+ pclk_freq = arb->pclk_khz;
+ mclk_freq = arb->mclk_khz;
+ nvclk_freq = arb->nvclk_khz;
+ pagemiss = arb->mem_page_miss;
+ cas = arb->mem_latency;
+ width = arb->memory_width >> 6;
+ video_enable = arb->enable_video;
+ bpp = arb->pix_bpp;
+ mp_enable = arb->enable_mp;
+ clwm = 0;
+ vlwm = 0;
+ cbs = 128;
+ pclks = 2;
+ nvclks = 2;
+ nvclks += 2;
+ nvclks += 1;
+ mclks = 5;
+ mclks += 3;
+ mclks += 1;
+ mclks += cas;
+ mclks += 1;
+ mclks += 1;
+ mclks += 1;
+ mclks += 1;
+ mclk_extra = 3;
+ nvclks += 2;
+ nvclks += 1;
+ nvclks += 1;
+ nvclks += 1;
+ if (mp_enable)
+ mclks += 4;
+ nvclks += 0;
+ pclks += 0;
+ found = 0;
+ vbs = 0;
+ while (found != 1) {
+ fifo->valid = 1;
+ found = 1;
+ mclk_loop = mclks + mclk_extra;
+ us_m = mclk_loop * 1000 * 1000 / mclk_freq;
+ us_n = nvclks * 1000 * 1000 / nvclk_freq;
+ us_p = nvclks * 1000 * 1000 / pclk_freq;
+ if (video_enable) {
+ video_drain_rate = pclk_freq * 2;
+ crtc_drain_rate = pclk_freq * bpp / 8;
+ vpagemiss = 2;
+ vpagemiss += 1;
+ crtpagemiss = 2;
+ vpm_us =
+ (vpagemiss * pagemiss) * 1000 * 1000 / mclk_freq;
+ if (nvclk_freq * 2 > mclk_freq * width)
+ video_fill_us =
+ cbs * 1000 * 1000 / 16 / nvclk_freq;
+ else
+ video_fill_us =
+ cbs * 1000 * 1000 / (8 * width) /
+ mclk_freq;
+ us_video = vpm_us + us_m + us_n + us_p + video_fill_us;
+ vlwm = us_video * video_drain_rate / (1000 * 1000);
+ vlwm++;
+ vbs = 128;
+ if (vlwm > 128)
+ vbs = 64;
+ if (vlwm > (256 - 64))
+ vbs = 32;
+ if (nvclk_freq * 2 > mclk_freq * width)
+ video_fill_us =
+ vbs * 1000 * 1000 / 16 / nvclk_freq;
+ else
+ video_fill_us =
+ vbs * 1000 * 1000 / (8 * width) /
+ mclk_freq;
+ cpm_us =
+ crtpagemiss * pagemiss * 1000 * 1000 / mclk_freq;
+ us_crt =
+ us_video + video_fill_us + cpm_us + us_m + us_n +
+ us_p;
+ clwm = us_crt * crtc_drain_rate / (1000 * 1000);
+ clwm++;
+ } else {
+ crtc_drain_rate = pclk_freq * bpp / 8;
+ crtpagemiss = 2;
+ crtpagemiss += 1;
+ cpm_us =
+ crtpagemiss * pagemiss * 1000 * 1000 / mclk_freq;
+ us_crt = cpm_us + us_m + us_n + us_p;
+ clwm = us_crt * crtc_drain_rate / (1000 * 1000);
+ clwm++;
+ }
+ m1 = clwm + cbs - 512;
+ p1 = m1 * pclk_freq / mclk_freq;
+ p1 = p1 * bpp / 8;
+ if ((p1 < m1) && (m1 > 0)) {
+ fifo->valid = 0;
+ found = 0;
+ if (mclk_extra == 0)
+ found = 1;
+ mclk_extra--;
+ } else if (video_enable) {
+ if ((clwm > 511) || (vlwm > 255)) {
+ fifo->valid = 0;
+ found = 0;
+ if (mclk_extra == 0)
+ found = 1;
+ mclk_extra--;
+ }
+ } else {
+ if (clwm > 519) {
+ fifo->valid = 0;
+ found = 0;
+ if (mclk_extra == 0)
+ found = 1;
+ mclk_extra--;
+ }
+ }
+ if (clwm < 384)
+ clwm = 384;
+ if (vlwm < 128)
+ vlwm = 128;
+ data = (int)(clwm);
+ fifo->graphics_lwm = data;
+ fifo->graphics_burst_size = 128;
+ data = (int)((vlwm + 15));
+ fifo->video_lwm = data;
+ fifo->video_burst_size = vbs;
+ }
+}
+
+static void nv4UpdateArbitrationSettings(unsigned VClk,
+ unsigned pixelDepth,
+ unsigned *burst,
+ unsigned *lwm, struct nvidia_par *par)
+{
+ nv4_fifo_info fifo_data;
+ nv4_sim_state sim_data;
+ unsigned int MClk, NVClk, cfg1;
+
+ nvGetClocks(par, &MClk, &NVClk);
+
+ cfg1 = NV_RD32(par->PFB, 0x00000204);
+ sim_data.pix_bpp = (char)pixelDepth;
+ sim_data.enable_video = 0;
+ sim_data.enable_mp = 0;
+ sim_data.memory_width = (NV_RD32(par->PEXTDEV, 0x0000) & 0x10) ?
+ 128 : 64;
+ sim_data.mem_latency = (char)cfg1 & 0x0F;
+ sim_data.mem_aligned = 1;
+ sim_data.mem_page_miss =
+ (char)(((cfg1 >> 4) & 0x0F) + ((cfg1 >> 31) & 0x01));
+ sim_data.gr_during_vid = 0;
+ sim_data.pclk_khz = VClk;
+ sim_data.mclk_khz = MClk;
+ sim_data.nvclk_khz = NVClk;
+ nv4CalcArbitration(&fifo_data, &sim_data);
+ if (fifo_data.valid) {
+ int b = fifo_data.graphics_burst_size >> 4;
+ *burst = 0;
+ while (b >>= 1)
+ (*burst)++;
+ *lwm = fifo_data.graphics_lwm >> 3;
+ }
+}
+
+static void nv10CalcArbitration(nv10_fifo_info * fifo, nv10_sim_state * arb)
+{
+ int data, pagemiss, width, video_enable, bpp;
+ int nvclks, mclks, pclks, vpagemiss, crtpagemiss;
+ int nvclk_fill;
+ int found, mclk_extra, mclk_loop, cbs, m1;
+ int mclk_freq, pclk_freq, nvclk_freq, mp_enable;
+ int us_m, us_m_min, us_n, us_p, crtc_drain_rate;
+ int vus_m;
+ int vpm_us, us_video, cpm_us, us_crt, clwm;
+ int clwm_rnd_down;
+ int m2us, us_pipe_min, p1clk, p2;
+ int min_mclk_extra;
+ int us_min_mclk_extra;
+
+ fifo->valid = 1;
+ pclk_freq = arb->pclk_khz; /* freq in KHz */
+ mclk_freq = arb->mclk_khz;
+ nvclk_freq = arb->nvclk_khz;
+ pagemiss = arb->mem_page_miss;
+ width = arb->memory_width / 64;
+ video_enable = arb->enable_video;
+ bpp = arb->pix_bpp;
+ mp_enable = arb->enable_mp;
+ clwm = 0;
+
+ cbs = 512;
+
+ pclks = 4; /* lwm detect. */
+
+ nvclks = 3; /* lwm -> sync. */
+ nvclks += 2; /* fbi bus cycles (1 req + 1 busy) */
+ /* 2 edge sync. may be very close to edge so just put one. */
+ mclks = 1;
+ mclks += 1; /* arb_hp_req */
+ mclks += 5; /* ap_hp_req tiling pipeline */
+
+ mclks += 2; /* tc_req latency fifo */
+ mclks += 2; /* fb_cas_n_ memory request to fbio block */
+ mclks += 7; /* sm_d_rdv data returned from fbio block */
+
+ /* fb.rd.d.Put_gc need to accumulate 256 bits for read */
+ if (arb->memory_type == 0)
+ if (arb->memory_width == 64) /* 64 bit bus */
+ mclks += 4;
+ else
+ mclks += 2;
+ else if (arb->memory_width == 64) /* 64 bit bus */
+ mclks += 2;
+ else
+ mclks += 1;
+
+ if ((!video_enable) && (arb->memory_width == 128)) {
+ mclk_extra = (bpp == 32) ? 31 : 42; /* Margin of error */
+ min_mclk_extra = 17;
+ } else {
+ mclk_extra = (bpp == 32) ? 8 : 4; /* Margin of error */
+ /* mclk_extra = 4; *//* Margin of error */
+ min_mclk_extra = 18;
+ }
+
+ /* 2 edge sync. may be very close to edge so just put one. */
+ nvclks += 1;
+ nvclks += 1; /* fbi_d_rdv_n */
+ nvclks += 1; /* Fbi_d_rdata */
+ nvclks += 1; /* crtfifo load */
+
+ if (mp_enable)
+ mclks += 4; /* Mp can get in with a burst of 8. */
+ /* Extra clocks determined by heuristics */
+
+ nvclks += 0;
+ pclks += 0;
+ found = 0;
+ while (found != 1) {
+ fifo->valid = 1;
+ found = 1;
+ mclk_loop = mclks + mclk_extra;
+ /* Mclk latency in us */
+ us_m = mclk_loop * 1000 * 1000 / mclk_freq;
+ /* Minimum Mclk latency in us */
+ us_m_min = mclks * 1000 * 1000 / mclk_freq;
+ us_min_mclk_extra = min_mclk_extra * 1000 * 1000 / mclk_freq;
+ /* nvclk latency in us */
+ us_n = nvclks * 1000 * 1000 / nvclk_freq;
+ /* nvclk latency in us */
+ us_p = pclks * 1000 * 1000 / pclk_freq;
+ us_pipe_min = us_m_min + us_n + us_p;
+
+ /* Mclk latency in us */
+ vus_m = mclk_loop * 1000 * 1000 / mclk_freq;
+
+ if (video_enable) {
+ crtc_drain_rate = pclk_freq * bpp / 8; /* MB/s */
+
+ vpagemiss = 1; /* self generating page miss */
+ vpagemiss += 1; /* One higher priority before */
+
+ crtpagemiss = 2; /* self generating page miss */
+ if (mp_enable)
+ crtpagemiss += 1; /* if MA0 conflict */
+
+ vpm_us =
+ (vpagemiss * pagemiss) * 1000 * 1000 / mclk_freq;
+
+ /* Video has separate read return path */
+ us_video = vpm_us + vus_m;
+
+ cpm_us =
+ crtpagemiss * pagemiss * 1000 * 1000 / mclk_freq;
+ /* Wait for video */
+ us_crt = us_video
+ + cpm_us /* CRT Page miss */
+ + us_m + us_n + us_p /* other latency */
+ ;
+
+ clwm = us_crt * crtc_drain_rate / (1000 * 1000);
+ /* fixed point <= float_point - 1. Fixes that */
+ clwm++;
+ } else {
+ /* bpp * pclk/8 */
+ crtc_drain_rate = pclk_freq * bpp / 8;
+
+ crtpagemiss = 1; /* self generating page miss */
+ crtpagemiss += 1; /* MA0 page miss */
+ if (mp_enable)
+ crtpagemiss += 1; /* if MA0 conflict */
+ cpm_us =
+ crtpagemiss * pagemiss * 1000 * 1000 / mclk_freq;
+ us_crt = cpm_us + us_m + us_n + us_p;
+ clwm = us_crt * crtc_drain_rate / (1000 * 1000);
+ /* fixed point <= float_point - 1. Fixes that */
+ clwm++;
+
+ /* Finally, a heuristic check when width == 64 bits */
+ if (width == 1) {
+ nvclk_fill = nvclk_freq * 8;
+ if (crtc_drain_rate * 100 >= nvclk_fill * 102)
+ /*Large number to fail */
+ clwm = 0xfff;
+
+ else if (crtc_drain_rate * 100 >=
+ nvclk_fill * 98) {
+ clwm = 1024;
+ cbs = 512;
+ }
+ }
+ }
+
+ /*
+ Overfill check:
+ */
+
+ clwm_rnd_down = ((int)clwm / 8) * 8;
+ if (clwm_rnd_down < clwm)
+ clwm += 8;
+
+ m1 = clwm + cbs - 1024; /* Amount of overfill */
+ m2us = us_pipe_min + us_min_mclk_extra;
+
+ /* pclk cycles to drain */
+ p1clk = m2us * pclk_freq / (1000 * 1000);
+ p2 = p1clk * bpp / 8; /* bytes drained. */
+
+ if ((p2 < m1) && (m1 > 0)) {
+ fifo->valid = 0;
+ found = 0;
+ if (min_mclk_extra == 0) {
+ if (cbs <= 32) {
+ /* Can't adjust anymore! */
+ found = 1;
+ } else {
+ /* reduce the burst size */
+ cbs = cbs / 2;
+ }
+ } else {
+ min_mclk_extra--;
+ }
+ } else {
+ if (clwm > 1023) { /* Have some margin */
+ fifo->valid = 0;
+ found = 0;
+ if (min_mclk_extra == 0)
+ /* Can't adjust anymore! */
+ found = 1;
+ else
+ min_mclk_extra--;
+ }
+ }
+
+ if (clwm < (1024 - cbs + 8))
+ clwm = 1024 - cbs + 8;
+ data = (int)(clwm);
+ /* printf("CRT LWM: %f bytes, prog: 0x%x, bs: 256\n",
+ clwm, data ); */
+ fifo->graphics_lwm = data;
+ fifo->graphics_burst_size = cbs;
+
+ fifo->video_lwm = 1024;
+ fifo->video_burst_size = 512;
+ }
+}
+
+static void nv10UpdateArbitrationSettings(unsigned VClk,
+ unsigned pixelDepth,
+ unsigned *burst,
+ unsigned *lwm,
+ struct nvidia_par *par)
+{
+ nv10_fifo_info fifo_data;
+ nv10_sim_state sim_data;
+ unsigned int MClk, NVClk, cfg1;
+
+ nvGetClocks(par, &MClk, &NVClk);
+
+ cfg1 = NV_RD32(par->PFB, 0x0204);
+ sim_data.pix_bpp = (char)pixelDepth;
+ sim_data.enable_video = 1;
+ sim_data.enable_mp = 0;
+ sim_data.memory_type = (NV_RD32(par->PFB, 0x0200) & 0x01) ? 1 : 0;
+ sim_data.memory_width = (NV_RD32(par->PEXTDEV, 0x0000) & 0x10) ?
+ 128 : 64;
+ sim_data.mem_latency = (char)cfg1 & 0x0F;
+ sim_data.mem_aligned = 1;
+ sim_data.mem_page_miss =
+ (char)(((cfg1 >> 4) & 0x0F) + ((cfg1 >> 31) & 0x01));
+ sim_data.gr_during_vid = 0;
+ sim_data.pclk_khz = VClk;
+ sim_data.mclk_khz = MClk;
+ sim_data.nvclk_khz = NVClk;
+ nv10CalcArbitration(&fifo_data, &sim_data);
+ if (fifo_data.valid) {
+ int b = fifo_data.graphics_burst_size >> 4;
+ *burst = 0;
+ while (b >>= 1)
+ (*burst)++;
+ *lwm = fifo_data.graphics_lwm >> 3;
+ }
+}
+
+static void nv30UpdateArbitrationSettings (
+ struct nvidia_par *par,
+ unsigned int *burst,
+ unsigned int *lwm
+)
+{
+ unsigned int MClk, NVClk;
+ unsigned int fifo_size, burst_size, graphics_lwm;
+
+ fifo_size = 2048;
+ burst_size = 512;
+ graphics_lwm = fifo_size - burst_size;
+
+ nvGetClocks(par, &MClk, &NVClk);
+
+ *burst = 0;
+ burst_size >>= 5;
+ while(burst_size >>= 1) (*burst)++;
+ *lwm = graphics_lwm >> 3;
+}
+
+static void nForceUpdateArbitrationSettings(unsigned VClk,
+ unsigned pixelDepth,
+ unsigned *burst,
+ unsigned *lwm,
+ struct nvidia_par *par)
+{
+ nv10_fifo_info fifo_data;
+ nv10_sim_state sim_data;
+ unsigned int M, N, P, pll, MClk, NVClk, memctrl;
+ struct pci_dev *dev;
+
+ if ((par->Chipset & 0x0FF0) == 0x01A0) {
+ unsigned int uMClkPostDiv;
+ dev = pci_find_slot(0, 3);
+ pci_read_config_dword(dev, 0x6C, &uMClkPostDiv);
+ uMClkPostDiv = (uMClkPostDiv >> 8) & 0xf;
+
+ if (!uMClkPostDiv)
+ uMClkPostDiv = 4;
+ MClk = 400000 / uMClkPostDiv;
+ } else {
+ dev = pci_find_slot(0, 5);
+ pci_read_config_dword(dev, 0x4c, &MClk);
+ MClk /= 1000;
+ }
+
+ pll = NV_RD32(par->PRAMDAC0, 0x0500);
+ M = (pll >> 0) & 0xFF;
+ N = (pll >> 8) & 0xFF;
+ P = (pll >> 16) & 0x0F;
+ NVClk = (N * par->CrystalFreqKHz / M) >> P;
+ sim_data.pix_bpp = (char)pixelDepth;
+ sim_data.enable_video = 0;
+ sim_data.enable_mp = 0;
+ pci_find_slot(0, 1);
+ pci_read_config_dword(dev, 0x7C, &sim_data.memory_type);
+ sim_data.memory_type = (sim_data.memory_type >> 12) & 1;
+ sim_data.memory_width = 64;
+
+ dev = pci_find_slot(0, 3);
+ pci_read_config_dword(dev, 0, &memctrl);
+ memctrl >>= 16;
+
+ if ((memctrl == 0x1A9) || (memctrl == 0x1AB) || (memctrl == 0x1ED)) {
+ int dimm[3];
+
+ pci_find_slot(0, 2);
+ pci_read_config_dword(dev, 0x40, &dimm[0]);
+ dimm[0] = (dimm[0] >> 8) & 0x4f;
+ pci_read_config_dword(dev, 0x44, &dimm[1]);
+ dimm[1] = (dimm[1] >> 8) & 0x4f;
+ pci_read_config_dword(dev, 0x48, &dimm[2]);
+ dimm[2] = (dimm[2] >> 8) & 0x4f;
+
+ if ((dimm[0] + dimm[1]) != dimm[2]) {
+ printk("nvidiafb: your nForce DIMMs are not arranged "
+ "in optimal banks!\n");
+ }
+ }
+
+ sim_data.mem_latency = 3;
+ sim_data.mem_aligned = 1;
+ sim_data.mem_page_miss = 10;
+ sim_data.gr_during_vid = 0;
+ sim_data.pclk_khz = VClk;
+ sim_data.mclk_khz = MClk;
+ sim_data.nvclk_khz = NVClk;
+ nv10CalcArbitration(&fifo_data, &sim_data);
+ if (fifo_data.valid) {
+ int b = fifo_data.graphics_burst_size >> 4;
+ *burst = 0;
+ while (b >>= 1)
+ (*burst)++;
+ *lwm = fifo_data.graphics_lwm >> 3;
+ }
+}
+
+/****************************************************************************\
+* *
+* RIVA Mode State Routines *
+* *
+\****************************************************************************/
+
+/*
+ * Calculate the Video Clock parameters for the PLL.
+ */
+static void CalcVClock(int clockIn,
+ int *clockOut, u32 * pllOut, struct nvidia_par *par)
+{
+ unsigned lowM, highM;
+ unsigned DeltaNew, DeltaOld;
+ unsigned VClk, Freq;
+ unsigned M, N, P;
+
+ DeltaOld = 0xFFFFFFFF;
+
+ VClk = (unsigned)clockIn;
+
+ if (par->CrystalFreqKHz == 13500) {
+ lowM = 7;
+ highM = 13;
+ } else {
+ lowM = 8;
+ highM = 14;
+ }
+
+ for (P = 0; P <= 4; P++) {
+ Freq = VClk << P;
+ if ((Freq >= 128000) && (Freq <= 350000)) {
+ for (M = lowM; M <= highM; M++) {
+ N = ((VClk << P) * M) / par->CrystalFreqKHz;
+ if (N <= 255) {
+ Freq =
+ ((par->CrystalFreqKHz * N) /
+ M) >> P;
+ if (Freq > VClk)
+ DeltaNew = Freq - VClk;
+ else
+ DeltaNew = VClk - Freq;
+ if (DeltaNew < DeltaOld) {
+ *pllOut =
+ (P << 16) | (N << 8) | M;
+ *clockOut = Freq;
+ DeltaOld = DeltaNew;
+ }
+ }
+ }
+ }
+ }
+}
+
+static void CalcVClock2Stage(int clockIn,
+ int *clockOut,
+ u32 * pllOut,
+ u32 * pllBOut, struct nvidia_par *par)
+{
+ unsigned DeltaNew, DeltaOld;
+ unsigned VClk, Freq;
+ unsigned M, N, P;
+
+ DeltaOld = 0xFFFFFFFF;
+
+ *pllBOut = 0x80000401; /* fixed at x4 for now */
+
+ VClk = (unsigned)clockIn;
+
+ for (P = 0; P <= 6; P++) {
+ Freq = VClk << P;
+ if ((Freq >= 400000) && (Freq <= 1000000)) {
+ for (M = 1; M <= 13; M++) {
+ N = ((VClk << P) * M) /
+ (par->CrystalFreqKHz << 2);
+ if ((N >= 5) && (N <= 255)) {
+ Freq =
+ (((par->CrystalFreqKHz << 2) * N) /
+ M) >> P;
+ if (Freq > VClk)
+ DeltaNew = Freq - VClk;
+ else
+ DeltaNew = VClk - Freq;
+ if (DeltaNew < DeltaOld) {
+ *pllOut =
+ (P << 16) | (N << 8) | M;
+ *clockOut = Freq;
+ DeltaOld = DeltaNew;
+ }
+ }
+ }
+ }
+ }
+}
+
+/*
+ * Calculate extended mode parameters (SVGA) and save in a
+ * mode state structure.
+ */
+void NVCalcStateExt(struct nvidia_par *par,
+ RIVA_HW_STATE * state,
+ int bpp,
+ int width,
+ int hDisplaySize, int height, int dotClock, int flags)
+{
+ int pixelDepth, VClk;
+ /*
+ * Save mode parameters.
+ */
+ state->bpp = bpp; /* this is not bitsPerPixel, it's 8,15,16,32 */
+ state->width = width;
+ state->height = height;
+ /*
+ * Extended RIVA registers.
+ */
+ pixelDepth = (bpp + 1) / 8;
+ if (par->twoStagePLL)
+ CalcVClock2Stage(dotClock, &VClk, &state->pll, &state->pllB,
+ par);
+ else
+ CalcVClock(dotClock, &VClk, &state->pll, par);
+
+ switch (par->Architecture) {
+ case NV_ARCH_04:
+ nv4UpdateArbitrationSettings(VClk,
+ pixelDepth * 8,
+ &(state->arbitration0),
+ &(state->arbitration1), par);
+ state->cursor0 = 0x00;
+ state->cursor1 = 0xbC;
+ if (flags & FB_VMODE_DOUBLE)
+ state->cursor1 |= 2;
+ state->cursor2 = 0x00000000;
+ state->pllsel = 0x10000700;
+ state->config = 0x00001114;
+ state->general = bpp == 16 ? 0x00101100 : 0x00100100;
+ state->repaint1 = hDisplaySize < 1280 ? 0x04 : 0x00;
+ break;
+ case NV_ARCH_10:
+ case NV_ARCH_20:
+ case NV_ARCH_30:
+ default:
+ if (((par->Chipset & 0xffff) == 0x01A0) ||
+ ((par->Chipset & 0xffff) == 0x01f0)) {
+ nForceUpdateArbitrationSettings(VClk,
+ pixelDepth * 8,
+ &(state->arbitration0),
+ &(state->arbitration1),
+ par);
+ } else if (par->Architecture < NV_ARCH_30) {
+ nv10UpdateArbitrationSettings(VClk,
+ pixelDepth * 8,
+ &(state->arbitration0),
+ &(state->arbitration1),
+ par);
+ } else {
+ nv30UpdateArbitrationSettings(par,
+ &(state->arbitration0),
+ &(state->arbitration1));
+ }
+
+ state->cursor0 = 0x80 | (par->CursorStart >> 17);
+ state->cursor1 = (par->CursorStart >> 11) << 2;
+ state->cursor2 = par->CursorStart >> 24;
+ if (flags & FB_VMODE_DOUBLE)
+ state->cursor1 |= 2;
+ state->pllsel = 0x10000700;
+ state->config = NV_RD32(par->PFB, 0x00000200);
+ state->general = bpp == 16 ? 0x00101100 : 0x00100100;
+ state->repaint1 = hDisplaySize < 1280 ? 0x04 : 0x00;
+ break;
+ }
+
+ if (bpp != 8) /* DirectColor */
+ state->general |= 0x00000030;
+
+ state->repaint0 = (((width / 8) * pixelDepth) & 0x700) >> 3;
+ state->pixel = (pixelDepth > 2) ? 3 : pixelDepth;
+}
+
+void NVLoadStateExt(struct nvidia_par *par, RIVA_HW_STATE * state)
+{
+ int i;
+
+ NV_WR32(par->PMC, 0x0140, 0x00000000);
+ NV_WR32(par->PMC, 0x0200, 0xFFFF00FF);
+ NV_WR32(par->PMC, 0x0200, 0xFFFFFFFF);
+
+ NV_WR32(par->PTIMER, 0x0200 * 4, 0x00000008);
+ NV_WR32(par->PTIMER, 0x0210 * 4, 0x00000003);
+ NV_WR32(par->PTIMER, 0x0140 * 4, 0x00000000);
+ NV_WR32(par->PTIMER, 0x0100 * 4, 0xFFFFFFFF);
+
+ 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 {
+ for (i = 0; i < 8; i++) {
+ NV_WR32(par->PFB, 0x0240 + (i * 0x10), 0);
+ NV_WR32(par->PFB, 0x0244 + (i * 0x10), par->FbMapSize - 1);
+ }
+ }
+
+ if (par->Architecture >= NV_ARCH_40) {
+ NV_WR32(par->PRAMIN, 0x0000 * 4, 0x80000010);
+ NV_WR32(par->PRAMIN, 0x0001 * 4, 0x00101202);
+ NV_WR32(par->PRAMIN, 0x0002 * 4, 0x80000011);
+ NV_WR32(par->PRAMIN, 0x0003 * 4, 0x00101204);
+ NV_WR32(par->PRAMIN, 0x0004 * 4, 0x80000012);
+ NV_WR32(par->PRAMIN, 0x0005 * 4, 0x00101206);
+ NV_WR32(par->PRAMIN, 0x0006 * 4, 0x80000013);
+ NV_WR32(par->PRAMIN, 0x0007 * 4, 0x00101208);
+ NV_WR32(par->PRAMIN, 0x0008 * 4, 0x80000014);
+ NV_WR32(par->PRAMIN, 0x0009 * 4, 0x0010120A);
+ NV_WR32(par->PRAMIN, 0x000A * 4, 0x80000015);
+ NV_WR32(par->PRAMIN, 0x000B * 4, 0x0010120C);
+ NV_WR32(par->PRAMIN, 0x000C * 4, 0x80000016);
+ NV_WR32(par->PRAMIN, 0x000D * 4, 0x0010120E);
+ NV_WR32(par->PRAMIN, 0x000E * 4, 0x80000017);
+ NV_WR32(par->PRAMIN, 0x000F * 4, 0x00101210);
+ NV_WR32(par->PRAMIN, 0x0800 * 4, 0x00003000);
+ NV_WR32(par->PRAMIN, 0x0801 * 4, par->FbMapSize - 1);
+ NV_WR32(par->PRAMIN, 0x0802 * 4, 0x00000002);
+ NV_WR32(par->PRAMIN, 0x0808 * 4, 0x02080062);
+ NV_WR32(par->PRAMIN, 0x0809 * 4, 0x00000000);
+ NV_WR32(par->PRAMIN, 0x080A * 4, 0x00001200);
+ NV_WR32(par->PRAMIN, 0x080B * 4, 0x00001200);
+ NV_WR32(par->PRAMIN, 0x080C * 4, 0x00000000);
+ NV_WR32(par->PRAMIN, 0x080D * 4, 0x00000000);
+ NV_WR32(par->PRAMIN, 0x0810 * 4, 0x02080043);
+ NV_WR32(par->PRAMIN, 0x0811 * 4, 0x00000000);
+ NV_WR32(par->PRAMIN, 0x0812 * 4, 0x00000000);
+ NV_WR32(par->PRAMIN, 0x0813 * 4, 0x00000000);
+ NV_WR32(par->PRAMIN, 0x0814 * 4, 0x00000000);
+ NV_WR32(par->PRAMIN, 0x0815 * 4, 0x00000000);
+ NV_WR32(par->PRAMIN, 0x0818 * 4, 0x02080044);
+ NV_WR32(par->PRAMIN, 0x0819 * 4, 0x02000000);
+ NV_WR32(par->PRAMIN, 0x081A * 4, 0x00000000);
+ NV_WR32(par->PRAMIN, 0x081B * 4, 0x00000000);
+ NV_WR32(par->PRAMIN, 0x081C * 4, 0x00000000);
+ NV_WR32(par->PRAMIN, 0x081D * 4, 0x00000000);
+ NV_WR32(par->PRAMIN, 0x0820 * 4, 0x02080019);
+ NV_WR32(par->PRAMIN, 0x0821 * 4, 0x00000000);
+ NV_WR32(par->PRAMIN, 0x0822 * 4, 0x00000000);
+ NV_WR32(par->PRAMIN, 0x0823 * 4, 0x00000000);
+ NV_WR32(par->PRAMIN, 0x0824 * 4, 0x00000000);
+ NV_WR32(par->PRAMIN, 0x0825 * 4, 0x00000000);
+ NV_WR32(par->PRAMIN, 0x0828 * 4, 0x020A005C);
+ NV_WR32(par->PRAMIN, 0x0829 * 4, 0x00000000);
+ NV_WR32(par->PRAMIN, 0x082A * 4, 0x00000000);
+ NV_WR32(par->PRAMIN, 0x082B * 4, 0x00000000);
+ NV_WR32(par->PRAMIN, 0x082C * 4, 0x00000000);
+ NV_WR32(par->PRAMIN, 0x082D * 4, 0x00000000);
+ NV_WR32(par->PRAMIN, 0x0830 * 4, 0x0208009F);
+ NV_WR32(par->PRAMIN, 0x0831 * 4, 0x00000000);
+ NV_WR32(par->PRAMIN, 0x0832 * 4, 0x00001200);
+ NV_WR32(par->PRAMIN, 0x0833 * 4, 0x00001200);
+ NV_WR32(par->PRAMIN, 0x0834 * 4, 0x00000000);
+ NV_WR32(par->PRAMIN, 0x0835 * 4, 0x00000000);
+ NV_WR32(par->PRAMIN, 0x0838 * 4, 0x0208004A);
+ NV_WR32(par->PRAMIN, 0x0839 * 4, 0x02000000);
+ NV_WR32(par->PRAMIN, 0x083A * 4, 0x00000000);
+ NV_WR32(par->PRAMIN, 0x083B * 4, 0x00000000);
+ NV_WR32(par->PRAMIN, 0x083C * 4, 0x00000000);
+ NV_WR32(par->PRAMIN, 0x083D * 4, 0x00000000);
+ NV_WR32(par->PRAMIN, 0x0840 * 4, 0x02080077);
+ NV_WR32(par->PRAMIN, 0x0841 * 4, 0x00000000);
+ NV_WR32(par->PRAMIN, 0x0842 * 4, 0x00001200);
+ NV_WR32(par->PRAMIN, 0x0843 * 4, 0x00001200);
+ NV_WR32(par->PRAMIN, 0x0844 * 4, 0x00000000);
+ NV_WR32(par->PRAMIN, 0x0845 * 4, 0x00000000);
+ NV_WR32(par->PRAMIN, 0x084C * 4, 0x00003002);
+ NV_WR32(par->PRAMIN, 0x084D * 4, 0x00007FFF);
+ NV_WR32(par->PRAMIN, 0x084E * 4,
+ par->FbUsableSize | 0x00000002);
+
+#ifdef __BIG_ENDIAN
+ NV_WR32(par->PRAMIN, 0x080A * 4,
+ NV_RD32(par->PRAMIN, 0x080A * 4) | 0x01000000);
+ NV_WR32(par->PRAMIN, 0x0812 * 4,
+ NV_RD32(par->PRAMIN, 0x0812 * 4) | 0x01000000);
+ NV_WR32(par->PRAMIN, 0x081A * 4,
+ NV_RD32(par->PRAMIN, 0x081A * 4) | 0x01000000);
+ NV_WR32(par->PRAMIN, 0x0822 * 4,
+ NV_RD32(par->PRAMIN, 0x0822 * 4) | 0x01000000);
+ NV_WR32(par->PRAMIN, 0x082A * 4,
+ NV_RD32(par->PRAMIN, 0x082A * 4) | 0x01000000);
+ NV_WR32(par->PRAMIN, 0x0832 * 4,
+ NV_RD32(par->PRAMIN, 0x0832 * 4) | 0x01000000);
+ NV_WR32(par->PRAMIN, 0x083A * 4,
+ NV_RD32(par->PRAMIN, 0x083A * 4) | 0x01000000);
+ NV_WR32(par->PRAMIN, 0x0842 * 4,
+ NV_RD32(par->PRAMIN, 0x0842 * 4) | 0x01000000);
+ NV_WR32(par->PRAMIN, 0x0819 * 4, 0x01000000);
+ NV_WR32(par->PRAMIN, 0x0839 * 4, 0x01000000);
+#endif
+ } else {
+ NV_WR32(par->PRAMIN, 0x0000 * 4, 0x80000010);
+ NV_WR32(par->PRAMIN, 0x0001 * 4, 0x80011201);
+ NV_WR32(par->PRAMIN, 0x0002 * 4, 0x80000011);
+ NV_WR32(par->PRAMIN, 0x0003 * 4, 0x80011202);
+ NV_WR32(par->PRAMIN, 0x0004 * 4, 0x80000012);
+ NV_WR32(par->PRAMIN, 0x0005 * 4, 0x80011203);
+ NV_WR32(par->PRAMIN, 0x0006 * 4, 0x80000013);
+ NV_WR32(par->PRAMIN, 0x0007 * 4, 0x80011204);
+ NV_WR32(par->PRAMIN, 0x0008 * 4, 0x80000014);
+ NV_WR32(par->PRAMIN, 0x0009 * 4, 0x80011205);
+ NV_WR32(par->PRAMIN, 0x000A * 4, 0x80000015);
+ NV_WR32(par->PRAMIN, 0x000B * 4, 0x80011206);
+ NV_WR32(par->PRAMIN, 0x000C * 4, 0x80000016);
+ NV_WR32(par->PRAMIN, 0x000D * 4, 0x80011207);
+ NV_WR32(par->PRAMIN, 0x000E * 4, 0x80000017);
+ NV_WR32(par->PRAMIN, 0x000F * 4, 0x80011208);
+ NV_WR32(par->PRAMIN, 0x0800 * 4, 0x00003000);
+ NV_WR32(par->PRAMIN, 0x0801 * 4, par->FbMapSize - 1);
+ NV_WR32(par->PRAMIN, 0x0802 * 4, 0x00000002);
+ NV_WR32(par->PRAMIN, 0x0803 * 4, 0x00000002);
+ if (par->Architecture >= NV_ARCH_10)
+ NV_WR32(par->PRAMIN, 0x0804 * 4, 0x01008062);
+ else
+ NV_WR32(par->PRAMIN, 0x0804 * 4, 0x01008042);
+ NV_WR32(par->PRAMIN, 0x0805 * 4, 0x00000000);
+ NV_WR32(par->PRAMIN, 0x0806 * 4, 0x12001200);
+ NV_WR32(par->PRAMIN, 0x0807 * 4, 0x00000000);
+ NV_WR32(par->PRAMIN, 0x0808 * 4, 0x01008043);
+ NV_WR32(par->PRAMIN, 0x0809 * 4, 0x00000000);
+ NV_WR32(par->PRAMIN, 0x080A * 4, 0x00000000);
+ NV_WR32(par->PRAMIN, 0x080B * 4, 0x00000000);
+ NV_WR32(par->PRAMIN, 0x080C * 4, 0x01008044);
+ NV_WR32(par->PRAMIN, 0x080D * 4, 0x00000002);
+ NV_WR32(par->PRAMIN, 0x080E * 4, 0x00000000);
+ NV_WR32(par->PRAMIN, 0x080F * 4, 0x00000000);
+ NV_WR32(par->PRAMIN, 0x0810 * 4, 0x01008019);
+ NV_WR32(par->PRAMIN, 0x0811 * 4, 0x00000000);
+ NV_WR32(par->PRAMIN, 0x0812 * 4, 0x00000000);
+ NV_WR32(par->PRAMIN, 0x0813 * 4, 0x00000000);
+ NV_WR32(par->PRAMIN, 0x0814 * 4, 0x0100A05C);
+ NV_WR32(par->PRAMIN, 0x0815 * 4, 0x00000000);
+ NV_WR32(par->PRAMIN, 0x0816 * 4, 0x00000000);
+ NV_WR32(par->PRAMIN, 0x0817 * 4, 0x00000000);
+ if (par->WaitVSyncPossible)
+ NV_WR32(par->PRAMIN, 0x0818 * 4, 0x0100809F);
+ else
+ NV_WR32(par->PRAMIN, 0x0818 * 4, 0x0100805F);
+ NV_WR32(par->PRAMIN, 0x0819 * 4, 0x00000000);
+ NV_WR32(par->PRAMIN, 0x081A * 4, 0x12001200);
+ NV_WR32(par->PRAMIN, 0x081B * 4, 0x00000000);
+ NV_WR32(par->PRAMIN, 0x081C * 4, 0x0100804A);
+ NV_WR32(par->PRAMIN, 0x081D * 4, 0x00000002);
+ NV_WR32(par->PRAMIN, 0x081E * 4, 0x00000000);
+ NV_WR32(par->PRAMIN, 0x081F * 4, 0x00000000);
+ NV_WR32(par->PRAMIN, 0x0820 * 4, 0x01018077);
+ NV_WR32(par->PRAMIN, 0x0821 * 4, 0x00000000);
+ NV_WR32(par->PRAMIN, 0x0822 * 4, 0x12001200);
+ NV_WR32(par->PRAMIN, 0x0823 * 4, 0x00000000);
+ NV_WR32(par->PRAMIN, 0x0824 * 4, 0x00003002);
+ NV_WR32(par->PRAMIN, 0x0825 * 4, 0x00007FFF);
+ NV_WR32(par->PRAMIN, 0x0826 * 4,
+ par->FbUsableSize | 0x00000002);
+ NV_WR32(par->PRAMIN, 0x0827 * 4, 0x00000002);
+#ifdef __BIG_ENDIAN
+ NV_WR32(par->PRAMIN, 0x0804 * 4,
+ NV_RD32(par->PRAMIN, 0x0804 * 4) | 0x00080000);
+ NV_WR32(par->PRAMIN, 0x0808 * 4,
+ NV_RD32(par->PRAMIN, 0x0808 * 4) | 0x00080000);
+ NV_WR32(par->PRAMIN, 0x080C * 4,
+ NV_RD32(par->PRAMIN, 0x080C * 4) | 0x00080000);
+ NV_WR32(par->PRAMIN, 0x0810 * 4,
+ NV_RD32(par->PRAMIN, 0x0810 * 4) | 0x00080000);
+ NV_WR32(par->PRAMIN, 0x0814 * 4,
+ NV_RD32(par->PRAMIN, 0x0814 * 4) | 0x00080000);
+ NV_WR32(par->PRAMIN, 0x0818 * 4,
+ NV_RD32(par->PRAMIN, 0x0818 * 4) | 0x00080000);
+ NV_WR32(par->PRAMIN, 0x081C * 4,
+ NV_RD32(par->PRAMIN, 0x081C * 4) | 0x00080000);
+ NV_WR32(par->PRAMIN, 0x0820 * 4,
+ NV_RD32(par->PRAMIN, 0x0820 * 4) | 0x00080000);
+ NV_WR32(par->PRAMIN, 0x080D * 4, 0x00000001);
+ NV_WR32(par->PRAMIN, 0x081D * 4, 0x00000001);
+#endif
+ }
+ if (par->Architecture < NV_ARCH_10) {
+ if ((par->Chipset & 0x0fff) == 0x0020) {
+ NV_WR32(par->PRAMIN, 0x0824 * 4,
+ NV_RD32(par->PRAMIN, 0x0824 * 4) | 0x00020000);
+ NV_WR32(par->PRAMIN, 0x0826 * 4,
+ NV_RD32(par->PRAMIN,
+ 0x0826 * 4) + par->FbAddress);
+ }
+ NV_WR32(par->PGRAPH, 0x0080, 0x000001FF);
+ NV_WR32(par->PGRAPH, 0x0080, 0x1230C000);
+ NV_WR32(par->PGRAPH, 0x0084, 0x72111101);
+ NV_WR32(par->PGRAPH, 0x0088, 0x11D5F071);
+ NV_WR32(par->PGRAPH, 0x008C, 0x0004FF31);
+ NV_WR32(par->PGRAPH, 0x008C, 0x4004FF31);
+ NV_WR32(par->PGRAPH, 0x0140, 0x00000000);
+ NV_WR32(par->PGRAPH, 0x0100, 0xFFFFFFFF);
+ NV_WR32(par->PGRAPH, 0x0170, 0x10010100);
+ NV_WR32(par->PGRAPH, 0x0710, 0xFFFFFFFF);
+ NV_WR32(par->PGRAPH, 0x0720, 0x00000001);
+ NV_WR32(par->PGRAPH, 0x0810, 0x00000000);
+ NV_WR32(par->PGRAPH, 0x0608, 0xFFFFFFFF);
+ } else {
+ NV_WR32(par->PGRAPH, 0x0080, 0xFFFFFFFF);
+ NV_WR32(par->PGRAPH, 0x0080, 0x00000000);
+
+ NV_WR32(par->PGRAPH, 0x0140, 0x00000000);
+ NV_WR32(par->PGRAPH, 0x0100, 0xFFFFFFFF);
+ NV_WR32(par->PGRAPH, 0x0144, 0x10010100);
+ NV_WR32(par->PGRAPH, 0x0714, 0xFFFFFFFF);
+ NV_WR32(par->PGRAPH, 0x0720, 0x00000001);
+ NV_WR32(par->PGRAPH, 0x0710,
+ NV_RD32(par->PGRAPH, 0x0710) & 0x0007ff00);
+ NV_WR32(par->PGRAPH, 0x0710,
+ NV_RD32(par->PGRAPH, 0x0710) | 0x00020100);
+
+ if (par->Architecture == NV_ARCH_10) {
+ NV_WR32(par->PGRAPH, 0x0084, 0x00118700);
+ NV_WR32(par->PGRAPH, 0x0088, 0x24E00810);
+ NV_WR32(par->PGRAPH, 0x008C, 0x55DE0030);
+
+ for (i = 0; i < 32; i++)
+ NV_WR32(&par->PGRAPH[(0x0B00 / 4) + i], 0,
+ NV_RD32(&par->PFB[(0x0240 / 4) + i],
+ 0));
+
+ NV_WR32(par->PGRAPH, 0x640, 0);
+ NV_WR32(par->PGRAPH, 0x644, 0);
+ NV_WR32(par->PGRAPH, 0x684, par->FbMapSize - 1);
+ NV_WR32(par->PGRAPH, 0x688, par->FbMapSize - 1);
+
+ NV_WR32(par->PGRAPH, 0x0810, 0x00000000);
+ NV_WR32(par->PGRAPH, 0x0608, 0xFFFFFFFF);
+ } else {
+ if (par->Architecture >= NV_ARCH_40) {
+ NV_WR32(par->PGRAPH, 0x0084, 0x401287c0);
+ NV_WR32(par->PGRAPH, 0x008C, 0x60de8051);
+ NV_WR32(par->PGRAPH, 0x0090, 0x00008000);
+ NV_WR32(par->PGRAPH, 0x0610, 0x00be3c5f);
+
+ if ((par->Chipset & 0xfff0) == 0x0040) {
+ NV_WR32(par->PGRAPH, 0x09b0,
+ 0x83280fff);
+ NV_WR32(par->PGRAPH, 0x09b4,
+ 0x000000a0);
+ } else {
+ NV_WR32(par->PGRAPH, 0x0820,
+ 0x83280eff);
+ NV_WR32(par->PGRAPH, 0x0824,
+ 0x000000a0);
+ }
+
+ switch (par->Chipset & 0xfff0) {
+ case 0x0040:
+ case 0x0210:
+ NV_WR32(par->PGRAPH, 0x09b8,
+ 0x0078e366);
+ NV_WR32(par->PGRAPH, 0x09bc,
+ 0x0000014c);
+ NV_WR32(par->PFB, 0x033C,
+ NV_RD32(par->PFB, 0x33C) &
+ 0xffff7fff);
+ break;
+ case 0x00C0:
+ NV_WR32(par->PGRAPH, 0x0828,
+ 0x007596ff);
+ NV_WR32(par->PGRAPH, 0x082C,
+ 0x00000108);
+ break;
+ case 0x0160:
+ case 0x01D0:
+ NV_WR32(par->PMC, 0x1700,
+ NV_RD32(par->PFB, 0x020C));
+ NV_WR32(par->PMC, 0x1704, 0);
+ NV_WR32(par->PMC, 0x1708, 0);
+ NV_WR32(par->PMC, 0x170C,
+ NV_RD32(par->PFB, 0x020C));
+ NV_WR32(par->PGRAPH, 0x0860, 0);
+ NV_WR32(par->PGRAPH, 0x0864, 0);
+ NV_WR32(par->PRAMDAC, 0x0608,
+ NV_RD32(par->PRAMDAC,
+ 0x0608) | 0x00100000);
+ break;
+ case 0x0140:
+ NV_WR32(par->PGRAPH, 0x0828,
+ 0x0072cb77);
+ NV_WR32(par->PGRAPH, 0x082C,
+ 0x00000108);
+ break;
+ case 0x0220:
+ case 0x0230:
+ NV_WR32(par->PGRAPH, 0x0860, 0);
+ NV_WR32(par->PGRAPH, 0x0864, 0);
+ NV_WR32(par->PRAMDAC, 0x0608,
+ NV_RD32(par->PRAMDAC, 0x0608) |
+ 0x00100000);
+ break;
+ case 0x0090:
+ NV_WR32(par->PRAMDAC, 0x0608,
+ NV_RD32(par->PRAMDAC, 0x0608) |
+ 0x00100000);
+ NV_WR32(par->PGRAPH, 0x0828,
+ 0x07830610);
+ NV_WR32(par->PGRAPH, 0x082C,
+ 0x0000016A);
+ break;
+ default:
+ break;
+ };
+
+ NV_WR32(par->PGRAPH, 0x0b38, 0x2ffff800);
+ NV_WR32(par->PGRAPH, 0x0b3c, 0x00006000);
+ NV_WR32(par->PGRAPH, 0x032C, 0x01000000);
+ NV_WR32(par->PGRAPH, 0x0220, 0x00001200);
+ } else if (par->Architecture == NV_ARCH_30) {
+ NV_WR32(par->PGRAPH, 0x0084, 0x40108700);
+ NV_WR32(par->PGRAPH, 0x0890, 0x00140000);
+ NV_WR32(par->PGRAPH, 0x008C, 0xf00e0431);
+ NV_WR32(par->PGRAPH, 0x0090, 0x00008000);
+ NV_WR32(par->PGRAPH, 0x0610, 0xf04b1f36);
+ NV_WR32(par->PGRAPH, 0x0B80, 0x1002d888);
+ NV_WR32(par->PGRAPH, 0x0B88, 0x62ff007f);
+ } else {
+ NV_WR32(par->PGRAPH, 0x0084, 0x00118700);
+ NV_WR32(par->PGRAPH, 0x008C, 0xF20E0431);
+ NV_WR32(par->PGRAPH, 0x0090, 0x00000000);
+ NV_WR32(par->PGRAPH, 0x009C, 0x00000040);
+
+ if ((par->Chipset & 0x0ff0) >= 0x0250) {
+ NV_WR32(par->PGRAPH, 0x0890,
+ 0x00080000);
+ NV_WR32(par->PGRAPH, 0x0610,
+ 0x304B1FB6);
+ NV_WR32(par->PGRAPH, 0x0B80,
+ 0x18B82880);
+ NV_WR32(par->PGRAPH, 0x0B84,
+ 0x44000000);
+ NV_WR32(par->PGRAPH, 0x0098,
+ 0x40000080);
+ NV_WR32(par->PGRAPH, 0x0B88,
+ 0x000000ff);
+ } else {
+ NV_WR32(par->PGRAPH, 0x0880,
+ 0x00080000);
+ NV_WR32(par->PGRAPH, 0x0094,
+ 0x00000005);
+ NV_WR32(par->PGRAPH, 0x0B80,
+ 0x45CAA208);
+ NV_WR32(par->PGRAPH, 0x0B84,
+ 0x24000000);
+ NV_WR32(par->PGRAPH, 0x0098,
+ 0x00000040);
+ NV_WR32(par->PGRAPH, 0x0750,
+ 0x00E00038);
+ NV_WR32(par->PGRAPH, 0x0754,
+ 0x00000030);
+ NV_WR32(par->PGRAPH, 0x0750,
+ 0x00E10038);
+ NV_WR32(par->PGRAPH, 0x0754,
+ 0x00000030);
+ }
+ }
+
+ if ((par->Chipset & 0xfff0) == 0x0090) {
+ for (i = 0; i < 60; i++)
+ NV_WR32(par->PGRAPH, 0x0D00 + i,
+ NV_RD32(par->PFB, 0x0600 + i));
+ } else {
+ for (i = 0; i < 32; i++)
+ NV_WR32(par->PGRAPH, 0x0900 + i,
+ NV_RD32(par->PFB, 0x0240 + i));
+ }
+
+ if (par->Architecture >= NV_ARCH_40) {
+ if ((par->Chipset & 0xfff0) == 0x0040) {
+ NV_WR32(par->PGRAPH, 0x09A4,
+ NV_RD32(par->PFB, 0x0200));
+ NV_WR32(par->PGRAPH, 0x09A8,
+ NV_RD32(par->PFB, 0x0204));
+ NV_WR32(par->PGRAPH, 0x69A4,
+ NV_RD32(par->PFB, 0x0200));
+ NV_WR32(par->PGRAPH, 0x69A8,
+ NV_RD32(par->PFB, 0x0204));
+
+ NV_WR32(par->PGRAPH, 0x0820, 0);
+ NV_WR32(par->PGRAPH, 0x0824, 0);
+ NV_WR32(par->PGRAPH, 0x0864,
+ par->FbMapSize - 1);
+ NV_WR32(par->PGRAPH, 0x0868,
+ par->FbMapSize - 1);
+ } else {
+ if((par->Chipset & 0xfff0) == 0x0090) {
+ NV_WR32(par->PGRAPH, 0x0DF0,
+ NV_RD32(par->PFB, 0x0200));
+ NV_WR32(par->PGRAPH, 0x0DF4,
+ NV_RD32(par->PFB, 0x0204));
+ } else {
+ NV_WR32(par->PGRAPH, 0x09F0,
+ NV_RD32(par->PFB, 0x0200));
+ NV_WR32(par->PGRAPH, 0x09F4,
+ NV_RD32(par->PFB, 0x0204));
+ }
+ NV_WR32(par->PGRAPH, 0x69F0,
+ NV_RD32(par->PFB, 0x0200));
+ NV_WR32(par->PGRAPH, 0x69F4,
+ NV_RD32(par->PFB, 0x0204));
+
+ NV_WR32(par->PGRAPH, 0x0840, 0);
+ NV_WR32(par->PGRAPH, 0x0844, 0);
+ NV_WR32(par->PGRAPH, 0x08a0,
+ par->FbMapSize - 1);
+ NV_WR32(par->PGRAPH, 0x08a4,
+ par->FbMapSize - 1);
+ }
+ } else {
+ NV_WR32(par->PGRAPH, 0x09A4,
+ NV_RD32(par->PFB, 0x0200));
+ NV_WR32(par->PGRAPH, 0x09A8,
+ NV_RD32(par->PFB, 0x0204));
+ NV_WR32(par->PGRAPH, 0x0750, 0x00EA0000);
+ NV_WR32(par->PGRAPH, 0x0754,
+ NV_RD32(par->PFB, 0x0200));
+ NV_WR32(par->PGRAPH, 0x0750, 0x00EA0004);
+ NV_WR32(par->PGRAPH, 0x0754,
+ NV_RD32(par->PFB, 0x0204));
+
+ NV_WR32(par->PGRAPH, 0x0820, 0);
+ NV_WR32(par->PGRAPH, 0x0824, 0);
+ NV_WR32(par->PGRAPH, 0x0864,
+ par->FbMapSize - 1);
+ NV_WR32(par->PGRAPH, 0x0868,
+ par->FbMapSize - 1);
+ }
+ NV_WR32(par->PGRAPH, 0x0B20, 0x00000000);
+ NV_WR32(par->PGRAPH, 0x0B04, 0xFFFFFFFF);
+ }
+ }
+ NV_WR32(par->PGRAPH, 0x053C, 0);
+ NV_WR32(par->PGRAPH, 0x0540, 0);
+ NV_WR32(par->PGRAPH, 0x0544, 0x00007FFF);
+ NV_WR32(par->PGRAPH, 0x0548, 0x00007FFF);
+
+ NV_WR32(par->PFIFO, 0x0140 * 4, 0x00000000);
+ NV_WR32(par->PFIFO, 0x0141 * 4, 0x00000001);
+ NV_WR32(par->PFIFO, 0x0480 * 4, 0x00000000);
+ NV_WR32(par->PFIFO, 0x0494 * 4, 0x00000000);
+ if (par->Architecture >= NV_ARCH_40)
+ NV_WR32(par->PFIFO, 0x0481 * 4, 0x00010000);
+ else
+ NV_WR32(par->PFIFO, 0x0481 * 4, 0x00000100);
+ NV_WR32(par->PFIFO, 0x0490 * 4, 0x00000000);
+ NV_WR32(par->PFIFO, 0x0491 * 4, 0x00000000);
+ if (par->Architecture >= NV_ARCH_40)
+ NV_WR32(par->PFIFO, 0x048B * 4, 0x00001213);
+ else
+ NV_WR32(par->PFIFO, 0x048B * 4, 0x00001209);
+ NV_WR32(par->PFIFO, 0x0400 * 4, 0x00000000);
+ NV_WR32(par->PFIFO, 0x0414 * 4, 0x00000000);
+ NV_WR32(par->PFIFO, 0x0084 * 4, 0x03000100);
+ NV_WR32(par->PFIFO, 0x0085 * 4, 0x00000110);
+ NV_WR32(par->PFIFO, 0x0086 * 4, 0x00000112);
+ NV_WR32(par->PFIFO, 0x0143 * 4, 0x0000FFFF);
+ NV_WR32(par->PFIFO, 0x0496 * 4, 0x0000FFFF);
+ NV_WR32(par->PFIFO, 0x0050 * 4, 0x00000000);
+ NV_WR32(par->PFIFO, 0x0040 * 4, 0xFFFFFFFF);
+ NV_WR32(par->PFIFO, 0x0415 * 4, 0x00000001);
+ NV_WR32(par->PFIFO, 0x048C * 4, 0x00000000);
+ NV_WR32(par->PFIFO, 0x04A0 * 4, 0x00000000);
+#ifdef __BIG_ENDIAN
+ NV_WR32(par->PFIFO, 0x0489 * 4, 0x800F0078);
+#else
+ NV_WR32(par->PFIFO, 0x0489 * 4, 0x000F0078);
+#endif
+ NV_WR32(par->PFIFO, 0x0488 * 4, 0x00000001);
+ NV_WR32(par->PFIFO, 0x0480 * 4, 0x00000001);
+ NV_WR32(par->PFIFO, 0x0494 * 4, 0x00000001);
+ NV_WR32(par->PFIFO, 0x0495 * 4, 0x00000001);
+ NV_WR32(par->PFIFO, 0x0140 * 4, 0x00000001);
+ if (par->Architecture >= NV_ARCH_10) {
+ if (par->twoHeads) {
+ NV_WR32(par->PCRTC0, 0x0860, state->head);
+ NV_WR32(par->PCRTC0, 0x2860, state->head2);
+ }
+ NV_WR32(par->PRAMDAC, 0x0404, NV_RD32(par->PRAMDAC, 0x0404) |
+ (1 << 25));
+
+ NV_WR32(par->PMC, 0x8704, 1);
+ NV_WR32(par->PMC, 0x8140, 0);
+ NV_WR32(par->PMC, 0x8920, 0);
+ NV_WR32(par->PMC, 0x8924, 0);
+ NV_WR32(par->PMC, 0x8908, par->FbMapSize - 1);
+ NV_WR32(par->PMC, 0x890C, par->FbMapSize - 1);
+ NV_WR32(par->PMC, 0x1588, 0);
+
+ NV_WR32(par->PCRTC, 0x0810, state->cursorConfig);
+ NV_WR32(par->PCRTC, 0x0830, state->displayV - 3);
+ NV_WR32(par->PCRTC, 0x0834, state->displayV - 1);
+
+ if (par->FlatPanel) {
+ if ((par->Chipset & 0x0ff0) == 0x0110) {
+ NV_WR32(par->PRAMDAC, 0x0528, state->dither);
+ } else if (par->twoHeads) {
+ NV_WR32(par->PRAMDAC, 0x083C, state->dither);
+ }
+
+ VGA_WR08(par->PCIO, 0x03D4, 0x53);
+ VGA_WR08(par->PCIO, 0x03D5, state->timingH);
+ VGA_WR08(par->PCIO, 0x03D4, 0x54);
+ VGA_WR08(par->PCIO, 0x03D5, state->timingV);
+ VGA_WR08(par->PCIO, 0x03D4, 0x21);
+ VGA_WR08(par->PCIO, 0x03D5, 0xfa);
+ }
+
+ VGA_WR08(par->PCIO, 0x03D4, 0x41);
+ VGA_WR08(par->PCIO, 0x03D5, state->extra);
+ }
+
+ VGA_WR08(par->PCIO, 0x03D4, 0x19);
+ VGA_WR08(par->PCIO, 0x03D5, state->repaint0);
+ VGA_WR08(par->PCIO, 0x03D4, 0x1A);
+ VGA_WR08(par->PCIO, 0x03D5, state->repaint1);
+ VGA_WR08(par->PCIO, 0x03D4, 0x25);
+ VGA_WR08(par->PCIO, 0x03D5, state->screen);
+ VGA_WR08(par->PCIO, 0x03D4, 0x28);
+ VGA_WR08(par->PCIO, 0x03D5, state->pixel);
+ VGA_WR08(par->PCIO, 0x03D4, 0x2D);
+ VGA_WR08(par->PCIO, 0x03D5, state->horiz);
+ VGA_WR08(par->PCIO, 0x03D4, 0x1C);
+ VGA_WR08(par->PCIO, 0x03D5, state->fifo);
+ VGA_WR08(par->PCIO, 0x03D4, 0x1B);
+ VGA_WR08(par->PCIO, 0x03D5, state->arbitration0);
+ VGA_WR08(par->PCIO, 0x03D4, 0x20);
+ VGA_WR08(par->PCIO, 0x03D5, state->arbitration1);
+
+ if(par->Architecture >= NV_ARCH_30) {
+ VGA_WR08(par->PCIO, 0x03D4, 0x47);
+ VGA_WR08(par->PCIO, 0x03D5, state->arbitration1 >> 8);
+ }
+
+ VGA_WR08(par->PCIO, 0x03D4, 0x30);
+ VGA_WR08(par->PCIO, 0x03D5, state->cursor0);
+ VGA_WR08(par->PCIO, 0x03D4, 0x31);
+ VGA_WR08(par->PCIO, 0x03D5, state->cursor1);
+ VGA_WR08(par->PCIO, 0x03D4, 0x2F);
+ VGA_WR08(par->PCIO, 0x03D5, state->cursor2);
+ VGA_WR08(par->PCIO, 0x03D4, 0x39);
+ VGA_WR08(par->PCIO, 0x03D5, state->interlace);
+
+ if (!par->FlatPanel) {
+ NV_WR32(par->PRAMDAC0, 0x050C, state->pllsel);
+ NV_WR32(par->PRAMDAC0, 0x0508, state->vpll);
+ if (par->twoHeads)
+ NV_WR32(par->PRAMDAC0, 0x0520, state->vpll2);
+ if (par->twoStagePLL) {
+ NV_WR32(par->PRAMDAC0, 0x0578, state->vpllB);
+ NV_WR32(par->PRAMDAC0, 0x057C, state->vpll2B);
+ }
+ } else {
+ NV_WR32(par->PRAMDAC, 0x0848, state->scale);
+ NV_WR32(par->PRAMDAC, 0x0828, state->crtcSync +
+ par->PanelTweak);
+ }
+
+ NV_WR32(par->PRAMDAC, 0x0600, state->general);
+
+ NV_WR32(par->PCRTC, 0x0140, 0);
+ NV_WR32(par->PCRTC, 0x0100, 1);
+
+ par->CurrentState = state;
+}
+
+void NVUnloadStateExt(struct nvidia_par *par, RIVA_HW_STATE * state) {
+ VGA_WR08(par->PCIO, 0x03D4, 0x19);
+ state->repaint0 = VGA_RD08(par->PCIO, 0x03D5);
+ VGA_WR08(par->PCIO, 0x03D4, 0x1A);
+ state->repaint1 = VGA_RD08(par->PCIO, 0x03D5);
+ VGA_WR08(par->PCIO, 0x03D4, 0x25);
+ state->screen = VGA_RD08(par->PCIO, 0x03D5);
+ VGA_WR08(par->PCIO, 0x03D4, 0x28);
+ state->pixel = VGA_RD08(par->PCIO, 0x03D5);
+ VGA_WR08(par->PCIO, 0x03D4, 0x2D);
+ state->horiz = VGA_RD08(par->PCIO, 0x03D5);
+ VGA_WR08(par->PCIO, 0x03D4, 0x1C);
+ state->fifo = VGA_RD08(par->PCIO, 0x03D5);
+ VGA_WR08(par->PCIO, 0x03D4, 0x1B);
+ state->arbitration0 = VGA_RD08(par->PCIO, 0x03D5);
+ VGA_WR08(par->PCIO, 0x03D4, 0x20);
+ state->arbitration1 = VGA_RD08(par->PCIO, 0x03D5);
+
+ if(par->Architecture >= NV_ARCH_30) {
+ VGA_WR08(par->PCIO, 0x03D4, 0x47);
+ state->arbitration1 |= (VGA_RD08(par->PCIO, 0x03D5) & 1) << 8;
+ }
+
+ VGA_WR08(par->PCIO, 0x03D4, 0x30);
+ state->cursor0 = VGA_RD08(par->PCIO, 0x03D5);
+ VGA_WR08(par->PCIO, 0x03D4, 0x31);
+ state->cursor1 = VGA_RD08(par->PCIO, 0x03D5);
+ VGA_WR08(par->PCIO, 0x03D4, 0x2F);
+ state->cursor2 = VGA_RD08(par->PCIO, 0x03D5);
+ VGA_WR08(par->PCIO, 0x03D4, 0x39);
+ state->interlace = VGA_RD08(par->PCIO, 0x03D5);
+ state->vpll = NV_RD32(par->PRAMDAC0, 0x0508);
+ if (par->twoHeads)
+ state->vpll2 = NV_RD32(par->PRAMDAC0, 0x0520);
+ if (par->twoStagePLL) {
+ state->vpllB = NV_RD32(par->PRAMDAC0, 0x0578);
+ state->vpll2B = NV_RD32(par->PRAMDAC0, 0x057C);
+ }
+ state->pllsel = NV_RD32(par->PRAMDAC0, 0x050C);
+ state->general = NV_RD32(par->PRAMDAC, 0x0600);
+ state->scale = NV_RD32(par->PRAMDAC, 0x0848);
+ state->config = NV_RD32(par->PFB, 0x0200);
+
+ if (par->Architecture >= NV_ARCH_10) {
+ if (par->twoHeads) {
+ state->head = NV_RD32(par->PCRTC0, 0x0860);
+ state->head2 = NV_RD32(par->PCRTC0, 0x2860);
+ VGA_WR08(par->PCIO, 0x03D4, 0x44);
+ state->crtcOwner = VGA_RD08(par->PCIO, 0x03D5);
+ }
+ VGA_WR08(par->PCIO, 0x03D4, 0x41);
+ state->extra = VGA_RD08(par->PCIO, 0x03D5);
+ state->cursorConfig = NV_RD32(par->PCRTC, 0x0810);
+
+ if ((par->Chipset & 0x0ff0) == 0x0110) {
+ state->dither = NV_RD32(par->PRAMDAC, 0x0528);
+ } else if (par->twoHeads) {
+ state->dither = NV_RD32(par->PRAMDAC, 0x083C);
+ }
+
+ if (par->FlatPanel) {
+ VGA_WR08(par->PCIO, 0x03D4, 0x53);
+ state->timingH = VGA_RD08(par->PCIO, 0x03D5);
+ VGA_WR08(par->PCIO, 0x03D4, 0x54);
+ state->timingV = VGA_RD08(par->PCIO, 0x03D5);
+ }
+ }
+}
+
+void NVSetStartAddress(struct nvidia_par *par, u32 start)
+{
+ NV_WR32(par->PCRTC, 0x800, start);
+}
diff --git a/drivers/video/nvidia/nv_i2c.c b/drivers/video/nvidia/nv_i2c.c
new file mode 100644
index 0000000000000..3757c1407c190
--- /dev/null
+++ b/drivers/video/nvidia/nv_i2c.c
@@ -0,0 +1,215 @@
+/*
+ * linux/drivers/video/nvidia/nvidia-i2c.c - nVidia i2c
+ *
+ * Copyright 2004 Antonino A. Daplas <adaplas @pol.net>
+ *
+ * Based on rivafb-i2c.c
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/fb.h>
+
+#include <asm/io.h>
+
+#include "nv_type.h"
+#include "nv_local.h"
+#include "nv_proto.h"
+
+#include "../edid.h"
+
+static void nvidia_gpio_setscl(void *data, int state)
+{
+ struct nvidia_i2c_chan *chan = data;
+ struct nvidia_par *par = chan->par;
+ u32 val;
+
+ VGA_WR08(par->PCIO, 0x3d4, chan->ddc_base + 1);
+ val = VGA_RD08(par->PCIO, 0x3d5) & 0xf0;
+
+ if (state)
+ val |= 0x20;
+ else
+ val &= ~0x20;
+
+ VGA_WR08(par->PCIO, 0x3d4, chan->ddc_base + 1);
+ VGA_WR08(par->PCIO, 0x3d5, val | 0x1);
+}
+
+static void nvidia_gpio_setsda(void *data, int state)
+{
+ struct nvidia_i2c_chan *chan = (struct nvidia_i2c_chan *)data;
+ struct nvidia_par *par = chan->par;
+ u32 val;
+
+ VGA_WR08(par->PCIO, 0x3d4, chan->ddc_base + 1);
+ val = VGA_RD08(par->PCIO, 0x3d5) & 0xf0;
+
+ if (state)
+ val |= 0x10;
+ else
+ val &= ~0x10;
+
+ VGA_WR08(par->PCIO, 0x3d4, chan->ddc_base + 1);
+ VGA_WR08(par->PCIO, 0x3d5, val | 0x1);
+}
+
+static int nvidia_gpio_getscl(void *data)
+{
+ struct nvidia_i2c_chan *chan = (struct nvidia_i2c_chan *)data;
+ struct nvidia_par *par = chan->par;
+ u32 val = 0;
+
+ VGA_WR08(par->PCIO, 0x3d4, chan->ddc_base);
+ if (VGA_RD08(par->PCIO, 0x3d5) & 0x04)
+ val = 1;
+
+ val = VGA_RD08(par->PCIO, 0x3d5);
+
+ return val;
+}
+
+static int nvidia_gpio_getsda(void *data)
+{
+ struct nvidia_i2c_chan *chan = (struct nvidia_i2c_chan *)data;
+ struct nvidia_par *par = chan->par;
+ u32 val = 0;
+
+ VGA_WR08(par->PCIO, 0x3d4, chan->ddc_base);
+ if (VGA_RD08(par->PCIO, 0x3d5) & 0x08)
+ val = 1;
+
+ return val;
+}
+
+#define I2C_ALGO_NVIDIA 0x0e0000
+static int nvidia_setup_i2c_bus(struct nvidia_i2c_chan *chan, const char *name)
+{
+ int rc;
+
+ strcpy(chan->adapter.name, name);
+ chan->adapter.owner = THIS_MODULE;
+ chan->adapter.id = I2C_ALGO_NVIDIA;
+ chan->adapter.algo_data = &chan->algo;
+ chan->adapter.dev.parent = &chan->par->pci_dev->dev;
+ chan->algo.setsda = nvidia_gpio_setsda;
+ chan->algo.setscl = nvidia_gpio_setscl;
+ chan->algo.getsda = nvidia_gpio_getsda;
+ chan->algo.getscl = nvidia_gpio_getscl;
+ chan->algo.udelay = 40;
+ chan->algo.timeout = msecs_to_jiffies(2);
+ chan->algo.data = chan;
+
+ i2c_set_adapdata(&chan->adapter, chan);
+
+ /* Raise SCL and SDA */
+ nvidia_gpio_setsda(chan, 1);
+ nvidia_gpio_setscl(chan, 1);
+ udelay(20);
+
+ rc = i2c_bit_add_bus(&chan->adapter);
+ if (rc == 0)
+ dev_dbg(&chan->par->pci_dev->dev,
+ "I2C bus %s registered.\n", name);
+ else {
+ dev_warn(&chan->par->pci_dev->dev,
+ "Failed to register I2C bus %s.\n", name);
+ chan->par = NULL;
+ }
+
+ return rc;
+}
+
+void nvidia_create_i2c_busses(struct nvidia_par *par)
+{
+ par->bus = 3;
+
+ par->chan[0].par = par;
+ par->chan[1].par = par;
+ par->chan[2].par = par;
+
+ par->chan[0].ddc_base = 0x3e;
+ nvidia_setup_i2c_bus(&par->chan[0], "BUS1");
+
+ par->chan[1].ddc_base = 0x36;
+ nvidia_setup_i2c_bus(&par->chan[1], "BUS2");
+
+ par->chan[2].ddc_base = 0x50;
+ nvidia_setup_i2c_bus(&par->chan[2], "BUS3");
+}
+
+void nvidia_delete_i2c_busses(struct nvidia_par *par)
+{
+ if (par->chan[0].par)
+ i2c_bit_del_bus(&par->chan[0].adapter);
+ par->chan[0].par = NULL;
+
+ if (par->chan[1].par)
+ i2c_bit_del_bus(&par->chan[1].adapter);
+ par->chan[1].par = NULL;
+
+ if (par->chan[2].par)
+ i2c_bit_del_bus(&par->chan[2].adapter);
+ par->chan[2].par = NULL;
+
+}
+
+static u8 *nvidia_do_probe_i2c_edid(struct nvidia_i2c_chan *chan)
+{
+ u8 start = 0x0;
+ struct i2c_msg msgs[] = {
+ {
+ .addr = 0x50,
+ .len = 1,
+ .buf = &start,
+ }, {
+ .addr = 0x50,
+ .flags = I2C_M_RD,
+ .len = EDID_LENGTH,
+ },
+ };
+ u8 *buf;
+
+ if (!chan->par)
+ return NULL;
+
+ buf = kmalloc(EDID_LENGTH, GFP_KERNEL);
+ if (!buf) {
+ dev_warn(&chan->par->pci_dev->dev, "Out of memory!\n");
+ return NULL;
+ }
+ msgs[1].buf = buf;
+
+ if (i2c_transfer(&chan->adapter, msgs, 2) == 2)
+ return buf;
+ dev_dbg(&chan->par->pci_dev->dev, "Unable to read EDID block.\n");
+ kfree(buf);
+ return NULL;
+}
+
+int nvidia_probe_i2c_connector(struct nvidia_par *par, int conn, u8 **out_edid)
+{
+ u8 *edid = NULL;
+ int i;
+
+ for (i = 0; i < 3; i++) {
+ /* Do the real work */
+ edid = nvidia_do_probe_i2c_edid(&par->chan[conn - 1]);
+ if (edid)
+ break;
+ }
+ if (out_edid)
+ *out_edid = edid;
+ if (!edid)
+ return 1;
+
+ return 0;
+}
diff --git a/drivers/video/nvidia/nv_local.h b/drivers/video/nvidia/nv_local.h
new file mode 100644
index 0000000000000..9da320986f4c9
--- /dev/null
+++ b/drivers/video/nvidia/nv_local.h
@@ -0,0 +1,107 @@
+/***************************************************************************\
+|* *|
+|* Copyright 1993-2003 NVIDIA, Corporation. All rights reserved. *|
+|* *|
+|* NOTICE TO USER: The source code is copyrighted under U.S. and *|
+|* international laws. Users and possessors of this source code are *|
+|* hereby granted a nonexclusive, royalty-free copyright license to *|
+|* use this code in individual and commercial software. *|
+|* *|
+|* Any use of this source code must include, in the user documenta- *|
+|* tion and internal comments to the code, notices to the end user *|
+|* as follows: *|
+|* *|
+|* Copyright 1993-1999 NVIDIA, Corporation. All rights reserved. *|
+|* *|
+|* NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY *|
+|* OF THIS SOURCE CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" *|
+|* WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND. NVIDIA, CORPOR- *|
+|* ATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOURCE CODE, *|
+|* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE- *|
+|* MENT, AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL *|
+|* NVIDIA, CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT, INCI- *|
+|* DENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RE- *|
+|* SULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION *|
+|* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF *|
+|* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE. *|
+|* *|
+|* U.S. Government End Users. This source code is a "commercial *|
+|* item," as that term is defined at 48 C.F.R. 2.101 (OCT 1995), *|
+|* consisting of "commercial computer software" and "commercial *|
+|* computer software documentation," as such terms are used in *|
+|* 48 C.F.R. 12.212 (SEPT 1995) and is provided to the U.S. Govern- *|
+|* ment only as a commercial end item. Consistent with 48 C.F.R. *|
+|* 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (JUNE 1995), *|
+|* all U.S. Government End Users acquire the source code with only *|
+|* those rights set forth herein. *|
+|* *|
+ \***************************************************************************/
+
+/*
+ * GPL Licensing Note - According to Mark Vojkovich, author of the Xorg/
+ * XFree86 'nv' driver, this source code is provided under MIT-style licensing
+ * where the source code is provided "as is" without warranty of any kind.
+ * The only usage restriction is for the copyright notices to be retained
+ * whenever code is used.
+ *
+ * Antonino Daplas <adaplas@pol.net> 2005-03-11
+ */
+
+#ifndef __NV_LOCAL_H__
+#define __NV_LOCAL_H__
+
+/*
+ * This file includes any environment or machine specific values to access the
+ * HW. Put all affected includes, typdefs, etc. here so the riva_hw.* files
+ * can stay generic in nature.
+ */
+
+/*
+ * HW access macros. These assume memory-mapped I/O, and not normal I/O space.
+ */
+#define NV_WR08(p,i,d) (__raw_writeb((d), (void __iomem *)(p) + (i)))
+#define NV_RD08(p,i) (__raw_readb((void __iomem *)(p) + (i)))
+#define NV_WR16(p,i,d) (__raw_writew((d), (void __iomem *)(p) + (i)))
+#define NV_RD16(p,i) (__raw_readw((void __iomem *)(p) + (i)))
+#define NV_WR32(p,i,d) (__raw_writel((d), (void __iomem *)(p) + (i)))
+#define NV_RD32(p,i) (__raw_readl((void __iomem *)(p) + (i)))
+
+/* VGA I/O is now always done through MMIO */
+#define VGA_WR08(p,i,d) (writeb((d), (void __iomem *)(p) + (i)))
+#define VGA_RD08(p,i) (readb((void __iomem *)(p) + (i)))
+
+#define NVDmaNext(par, data) \
+ NV_WR32(&(par)->dmaBase[(par)->dmaCurrent++], 0, (data))
+
+#define NVDmaStart(par, tag, size) { \
+ if((par)->dmaFree <= (size)) \
+ NVDmaWait(par, size); \
+ NVDmaNext(par, ((size) << 18) | (tag)); \
+ (par)->dmaFree -= ((size) + 1); \
+}
+
+#if defined(__i386__)
+#define _NV_FENCE() outb(0, 0x3D0);
+#else
+#define _NV_FENCE() mb();
+#endif
+
+#define WRITE_PUT(par, data) { \
+ _NV_FENCE() \
+ NV_RD08((par)->FbStart, 0); \
+ NV_WR32(&(par)->FIFO[0x0010], 0, (data) << 2); \
+ mb(); \
+}
+
+#define READ_GET(par) (NV_RD32(&(par)->FIFO[0x0011], 0) >> 2)
+
+#define reverse_order(l) \
+do { \
+ u8 *a = (u8 *)(l); \
+ *a = byte_rev[*a], a++; \
+ *a = byte_rev[*a], a++; \
+ *a = byte_rev[*a], a++; \
+ *a = byte_rev[*a]; \
+} while(0)
+
+#endif /* __NV_LOCAL_H__ */
diff --git a/drivers/video/nvidia/nv_of.c b/drivers/video/nvidia/nv_of.c
new file mode 100644
index 0000000000000..7d12eb85310de
--- /dev/null
+++ b/drivers/video/nvidia/nv_of.c
@@ -0,0 +1,59 @@
+/*
+ * linux/drivers/video/nvidia/nv_of.c
+ *
+ * Copyright 2004 Antonino A. Daplas <adaplas @pol.net>
+ *
+ * Based on rivafb-i2c.c
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/fb.h>
+
+#include <asm/io.h>
+
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+
+#include "nv_type.h"
+#include "nv_local.h"
+#include "nv_proto.h"
+
+void nvidia_create_i2c_busses(struct nvidia_par *par) {}
+void nvidia_delete_i2c_busses(struct nvidia_par *par) {}
+
+int nvidia_probe_i2c_connector(struct nvidia_par *par, int conn, u8 **out_edid)
+{
+ struct device_node *dp;
+ unsigned char *pedid = NULL;
+ unsigned char *disptype = NULL;
+ static char *propnames[] = {
+ "DFP,EDID", "LCD,EDID", "EDID", "EDID1", "EDID,B", "EDID,A", NULL };
+ int i;
+
+ dp = pci_device_to_OF_node(par->pci_dev);
+ for (; dp != NULL; dp = dp->child) {
+ disptype = (unsigned char *)get_property(dp, "display-type", NULL);
+ if (disptype == NULL)
+ continue;
+ if (strncmp(disptype, "LCD", 3) != 0)
+ continue;
+ for (i = 0; propnames[i] != NULL; ++i) {
+ pedid = (unsigned char *)
+ get_property(dp, propnames[i], NULL);
+ if (pedid != NULL) {
+ *out_edid = pedid;
+ return 0;
+ }
+ }
+ }
+ return 1;
+}
diff --git a/drivers/video/nvidia/nv_proto.h b/drivers/video/nvidia/nv_proto.h
new file mode 100644
index 0000000000000..42847ce1b8dd7
--- /dev/null
+++ b/drivers/video/nvidia/nv_proto.h
@@ -0,0 +1,58 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/nv_proto.h,v 1.10 2003/07/31 20:24:29 mvojkovi Exp $ */
+
+#ifndef __NV_PROTO_H__
+#define __NV_PROTO_H__
+
+/* in nv_setup.c */
+void 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);
+u8 NVReadGr(struct nvidia_par *par, u8 index);
+void NVWriteSeq(struct nvidia_par *par, u8 index, u8 value);
+u8 NVReadSeq(struct nvidia_par *par, u8 index);
+void NVWriteAttr(struct nvidia_par *par, u8 index, u8 value);
+u8 NVReadAttr(struct nvidia_par *par, u8 index);
+void NVWriteMiscOut(struct nvidia_par *par, u8 value);
+u8 NVReadMiscOut(struct nvidia_par *par);
+void NVWriteDacMask(struct nvidia_par *par, u8 value);
+void NVWriteDacReadAddr(struct nvidia_par *par, u8 value);
+void NVWriteDacWriteAddr(struct nvidia_par *par, u8 value);
+void NVWriteDacData(struct nvidia_par *par, u8 value);
+u8 NVReadDacData(struct nvidia_par *par);
+
+/* in nv_hw.c */
+void NVCalcStateExt(struct nvidia_par *par, struct _riva_hw_state *,
+ int, int, int, int, int, int);
+void NVLoadStateExt(struct nvidia_par *par, struct _riva_hw_state *);
+void NVUnloadStateExt(struct nvidia_par *par, struct _riva_hw_state *);
+void NVSetStartAddress(struct nvidia_par *par, u32);
+int NVShowHideCursor(struct nvidia_par *par, int);
+void NVLockUnlock(struct nvidia_par *par, int);
+
+/* in nvidia-i2c.c */
+#if defined(CONFIG_FB_NVIDIA_I2C) || defined (CONFIG_PPC_OF)
+void nvidia_create_i2c_busses(struct nvidia_par *par);
+void nvidia_delete_i2c_busses(struct nvidia_par *par);
+int nvidia_probe_i2c_connector(struct nvidia_par *par, int conn,
+ u8 ** out_edid);
+#else
+#define nvidia_create_i2c_busses(...)
+#define nvidia_delete_i2c_busses(...)
+#define nvidia_probe_i2c_connector(p, c, edid) \
+do { \
+ *(edid) = NULL; \
+} while(0)
+#endif
+
+/* in nv_accel.c */
+extern void NVResetGraphics(struct fb_info *info);
+extern void nvidiafb_copyarea(struct fb_info *info,
+ const struct fb_copyarea *region);
+extern void nvidiafb_fillrect(struct fb_info *info,
+ const struct fb_fillrect *rect);
+extern void nvidiafb_imageblit(struct fb_info *info,
+ const struct fb_image *image);
+extern int nvidiafb_sync(struct fb_info *info);
+extern u8 byte_rev[256];
+#endif /* __NV_PROTO_H__ */
diff --git a/drivers/video/nvidia/nv_setup.c b/drivers/video/nvidia/nv_setup.c
new file mode 100644
index 0000000000000..0bbdca2e0f911
--- /dev/null
+++ b/drivers/video/nvidia/nv_setup.c
@@ -0,0 +1,636 @@
+ /***************************************************************************\
+|* *|
+|* Copyright 2003 NVIDIA, Corporation. All rights reserved. *|
+|* *|
+|* NOTICE TO USER: The source code is copyrighted under U.S. and *|
+|* international laws. Users and possessors of this source code are *|
+|* hereby granted a nonexclusive, royalty-free copyright license to *|
+|* use this code in individual and commercial software. *|
+|* *|
+|* Any use of this source code must include, in the user documenta- *|
+|* tion and internal comments to the code, notices to the end user *|
+|* as follows: *|
+|* *|
+|* Copyright 2003 NVIDIA, Corporation. All rights reserved. *|
+|* *|
+|* NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY *|
+|* OF THIS SOURCE CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" *|
+|* WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND. NVIDIA, CORPOR- *|
+|* ATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOURCE CODE, *|
+|* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE- *|
+|* MENT, AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL *|
+|* NVIDIA, CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT, INCI- *|
+|* DENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RE- *|
+|* SULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION *|
+|* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF *|
+|* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE. *|
+|* *|
+|* U.S. Government End Users. This source code is a "commercial *|
+|* item," as that term is defined at 48 C.F.R. 2.101 (OCT 1995), *|
+|* consisting of "commercial computer software" and "commercial *|
+|* computer software documentation," as such terms are used in *|
+|* 48 C.F.R. 12.212 (SEPT 1995) and is provided to the U.S. Govern- *|
+|* ment only as a commercial end item. Consistent with 48 C.F.R. *|
+|* 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (JUNE 1995), *|
+|* all U.S. Government End Users acquire the source code with only *|
+|* those rights set forth herein. *|
+|* *|
+ \***************************************************************************/
+
+/*
+ * GPL Licensing Note - According to Mark Vojkovich, author of the Xorg/
+ * XFree86 'nv' driver, this source code is provided under MIT-style licensing
+ * where the source code is provided "as is" without warranty of any kind.
+ * The only usage restriction is for the copyright notices to be retained
+ * whenever code is used.
+ *
+ * Antonino Daplas <adaplas@pol.net> 2005-03-11
+ */
+
+#include <video/vga.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include "nv_type.h"
+#include "nv_local.h"
+#include "nv_proto.h"
+/*
+ * Override VGA I/O routines.
+ */
+void NVWriteCrtc(struct nvidia_par *par, u8 index, u8 value)
+{
+ VGA_WR08(par->PCIO, par->IOBase + 0x04, index);
+ VGA_WR08(par->PCIO, par->IOBase + 0x05, value);
+}
+u8 NVReadCrtc(struct nvidia_par *par, u8 index)
+{
+ VGA_WR08(par->PCIO, par->IOBase + 0x04, index);
+ return (VGA_RD08(par->PCIO, par->IOBase + 0x05));
+}
+void NVWriteGr(struct nvidia_par *par, u8 index, u8 value)
+{
+ VGA_WR08(par->PVIO, VGA_GFX_I, index);
+ VGA_WR08(par->PVIO, VGA_GFX_D, value);
+}
+u8 NVReadGr(struct nvidia_par *par, u8 index)
+{
+ VGA_WR08(par->PVIO, VGA_GFX_I, index);
+ return (VGA_RD08(par->PVIO, VGA_GFX_D));
+}
+void NVWriteSeq(struct nvidia_par *par, u8 index, u8 value)
+{
+ VGA_WR08(par->PVIO, VGA_SEQ_I, index);
+ VGA_WR08(par->PVIO, VGA_SEQ_D, value);
+}
+u8 NVReadSeq(struct nvidia_par *par, u8 index)
+{
+ VGA_WR08(par->PVIO, VGA_SEQ_I, index);
+ return (VGA_RD08(par->PVIO, VGA_SEQ_D));
+}
+void NVWriteAttr(struct nvidia_par *par, u8 index, u8 value)
+{
+ volatile u8 tmp;
+
+ tmp = VGA_RD08(par->PCIO, par->IOBase + 0x0a);
+ if (par->paletteEnabled)
+ index &= ~0x20;
+ else
+ index |= 0x20;
+ VGA_WR08(par->PCIO, VGA_ATT_IW, index);
+ VGA_WR08(par->PCIO, VGA_ATT_W, value);
+}
+u8 NVReadAttr(struct nvidia_par *par, u8 index)
+{
+ volatile u8 tmp;
+
+ tmp = VGA_RD08(par->PCIO, par->IOBase + 0x0a);
+ if (par->paletteEnabled)
+ index &= ~0x20;
+ else
+ index |= 0x20;
+ VGA_WR08(par->PCIO, VGA_ATT_IW, index);
+ return (VGA_RD08(par->PCIO, VGA_ATT_R));
+}
+void NVWriteMiscOut(struct nvidia_par *par, u8 value)
+{
+ VGA_WR08(par->PVIO, VGA_MIS_W, value);
+}
+u8 NVReadMiscOut(struct nvidia_par *par)
+{
+ return (VGA_RD08(par->PVIO, VGA_MIS_R));
+}
+#if 0
+void NVEnablePalette(struct nvidia_par *par)
+{
+ volatile u8 tmp;
+
+ tmp = VGA_RD08(par->PCIO, par->IOBase + 0x0a);
+ VGA_WR08(par->PCIO, VGA_ATT_IW, 0x00);
+ par->paletteEnabled = 1;
+}
+void NVDisablePalette(struct nvidia_par *par)
+{
+ volatile u8 tmp;
+
+ tmp = VGA_RD08(par->PCIO, par->IOBase + 0x0a);
+ VGA_WR08(par->PCIO, VGA_ATT_IW, 0x20);
+ par->paletteEnabled = 0;
+}
+#endif /* 0 */
+void NVWriteDacMask(struct nvidia_par *par, u8 value)
+{
+ VGA_WR08(par->PDIO, VGA_PEL_MSK, value);
+}
+#if 0
+u8 NVReadDacMask(struct nvidia_par *par)
+{
+ return (VGA_RD08(par->PDIO, VGA_PEL_MSK));
+}
+#endif /* 0 */
+void NVWriteDacReadAddr(struct nvidia_par *par, u8 value)
+{
+ VGA_WR08(par->PDIO, VGA_PEL_IR, value);
+}
+void NVWriteDacWriteAddr(struct nvidia_par *par, u8 value)
+{
+ VGA_WR08(par->PDIO, VGA_PEL_IW, value);
+}
+void NVWriteDacData(struct nvidia_par *par, u8 value)
+{
+ VGA_WR08(par->PDIO, VGA_PEL_D, value);
+}
+u8 NVReadDacData(struct nvidia_par *par)
+{
+ return (VGA_RD08(par->PDIO, VGA_PEL_D));
+}
+
+static int NVIsConnected(struct nvidia_par *par, int output)
+{
+ volatile u32 __iomem *PRAMDAC = par->PRAMDAC0;
+ u32 reg52C, reg608;
+ int present;
+
+ if (output)
+ PRAMDAC += 0x800;
+
+ reg52C = NV_RD32(PRAMDAC, 0x052C);
+ reg608 = NV_RD32(PRAMDAC, 0x0608);
+
+ NV_WR32(PRAMDAC, 0x0608, reg608 & ~0x00010000);
+
+ NV_WR32(PRAMDAC, 0x052C, reg52C & 0x0000FEEE);
+ msleep(1);
+ NV_WR32(PRAMDAC, 0x052C, NV_RD32(PRAMDAC, 0x052C) | 1);
+
+ NV_WR32(par->PRAMDAC0, 0x0610, 0x94050140);
+ NV_WR32(par->PRAMDAC0, 0x0608, NV_RD32(par->PRAMDAC0, 0x0608) |
+ 0x00001000);
+
+ msleep(1);
+
+ present = (NV_RD32(PRAMDAC, 0x0608) & (1 << 28)) ? 1 : 0;
+
+ if (present)
+ printk("nvidiafb: CRTC%i found\n", output);
+ else
+ printk("nvidiafb: CRTC%i not found\n", output);
+
+ NV_WR32(par->PRAMDAC0, 0x0608, NV_RD32(par->PRAMDAC0, 0x0608) &
+ 0x0000EFFF);
+
+ NV_WR32(PRAMDAC, 0x052C, reg52C);
+ NV_WR32(PRAMDAC, 0x0608, reg608);
+
+ return present;
+}
+
+static void NVSelectHeadRegisters(struct nvidia_par *par, int head)
+{
+ if (head) {
+ par->PCIO = par->PCIO0 + 0x2000;
+ par->PCRTC = par->PCRTC0 + 0x800;
+ par->PRAMDAC = par->PRAMDAC0 + 0x800;
+ par->PDIO = par->PDIO0 + 0x2000;
+ } else {
+ par->PCIO = par->PCIO0;
+ par->PCRTC = par->PCRTC0;
+ par->PRAMDAC = par->PRAMDAC0;
+ par->PDIO = par->PDIO0;
+ }
+}
+
+static void nv4GetConfig(struct nvidia_par *par)
+{
+ if (NV_RD32(par->PFB, 0x0000) & 0x00000100) {
+ par->RamAmountKBytes =
+ ((NV_RD32(par->PFB, 0x0000) >> 12) & 0x0F) * 1024 * 2 +
+ 1024 * 2;
+ } else {
+ switch (NV_RD32(par->PFB, 0x0000) & 0x00000003) {
+ case 0:
+ par->RamAmountKBytes = 1024 * 32;
+ break;
+ case 1:
+ par->RamAmountKBytes = 1024 * 4;
+ break;
+ case 2:
+ par->RamAmountKBytes = 1024 * 8;
+ break;
+ case 3:
+ default:
+ par->RamAmountKBytes = 1024 * 16;
+ break;
+ }
+ }
+ par->CrystalFreqKHz = (NV_RD32(par->PEXTDEV, 0x0000) & 0x00000040) ?
+ 14318 : 13500;
+ par->CURSOR = &par->PRAMIN[0x1E00];
+ par->MinVClockFreqKHz = 12000;
+ par->MaxVClockFreqKHz = 350000;
+}
+
+static void nv10GetConfig(struct nvidia_par *par)
+{
+ struct pci_dev *dev;
+ u32 implementation = par->Chipset & 0x0ff0;
+
+#ifdef __BIG_ENDIAN
+ /* turn on big endian register access */
+ if (!(NV_RD32(par->PMC, 0x0004) & 0x01000001)) {
+ NV_WR32(par->PMC, 0x0004, 0x01000001);
+ mb();
+ }
+#endif
+
+ dev = pci_find_slot(0, 1);
+ if ((par->Chipset && 0xffff) == 0x01a0) {
+ int amt = 0;
+
+ pci_read_config_dword(dev, 0x7c, &amt);
+ par->RamAmountKBytes = (((amt >> 6) & 31) + 1) * 1024;
+ } else if ((par->Chipset & 0xffff) == 0x01f0) {
+ int amt = 0;
+
+ pci_read_config_dword(dev, 0x84, &amt);
+ par->RamAmountKBytes = (((amt >> 4) & 127) + 1) * 1024;
+ } else {
+ par->RamAmountKBytes =
+ (NV_RD32(par->PFB, 0x020C) & 0xFFF00000) >> 10;
+ }
+
+ par->CrystalFreqKHz = (NV_RD32(par->PEXTDEV, 0x0000) & (1 << 6)) ?
+ 14318 : 13500;
+
+ if (par->twoHeads && (implementation != 0x0110)) {
+ if (NV_RD32(par->PEXTDEV, 0x0000) & (1 << 22))
+ 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)
+{
+ struct nvidia_par *par = info->par;
+ struct fb_var_screeninfo var;
+ u16 implementation = par->Chipset & 0x0ff0;
+ u8 *edidA = NULL, *edidB = NULL;
+ 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;
+
+ par->PRAMIN = par->REGS + (0x00710000 / 4);
+ par->PCRTC0 = par->REGS + (0x00600000 / 4);
+ par->PRAMDAC0 = par->REGS + (0x00680000 / 4);
+ par->PFB = par->REGS + (0x00100000 / 4);
+ par->PFIFO = par->REGS + (0x00002000 / 4);
+ par->PGRAPH = par->REGS + (0x00400000 / 4);
+ par->PEXTDEV = par->REGS + (0x00101000 / 4);
+ par->PTIMER = par->REGS + (0x00009000 / 4);
+ par->PMC = par->REGS + (0x00000000 / 4);
+ par->FIFO = par->REGS + (0x00800000 / 4);
+
+ /* 8 bit registers */
+ par->PCIO0 = (u8 __iomem *) par->REGS + 0x00601000;
+ par->PDIO0 = (u8 __iomem *) par->REGS + 0x00681000;
+ par->PVIO = (u8 __iomem *) par->REGS + 0x000C0000;
+
+ par->twoHeads = (par->Architecture >= NV_ARCH_10) &&
+ (implementation != 0x0100) &&
+ (implementation != 0x0150) &&
+ (implementation != 0x01A0) && (implementation != 0x0200);
+
+ par->fpScaler = (par->FpScale && par->twoHeads &&
+ (implementation != 0x0110));
+
+ par->twoStagePLL = (implementation == 0x0310) ||
+ (implementation == 0x0340) || (par->Architecture >= NV_ARCH_40);
+
+ par->WaitVSyncPossible = (par->Architecture >= NV_ARCH_10) &&
+ (implementation != 0x0100);
+
+ par->BlendingPossible = ((par->Chipset & 0xffff) != 0x0020);
+
+ /* look for known laptop chips */
+ switch (par->Chipset & 0xffff) {
+ case 0x0112:
+ case 0x0174:
+ case 0x0175:
+ case 0x0176:
+ case 0x0177:
+ case 0x0179:
+ case 0x017C:
+ case 0x017D:
+ case 0x0186:
+ case 0x0187:
+ case 0x018D:
+ case 0x0286:
+ case 0x028C:
+ case 0x0316:
+ case 0x0317:
+ case 0x031A:
+ case 0x031B:
+ case 0x031C:
+ case 0x031D:
+ case 0x031E:
+ case 0x031F:
+ case 0x0324:
+ case 0x0325:
+ case 0x0328:
+ case 0x0329:
+ case 0x032C:
+ case 0x032D:
+ case 0x0347:
+ case 0x0348:
+ case 0x0349:
+ case 0x034B:
+ case 0x034C:
+ case 0x0160:
+ case 0x0166:
+ case 0x00C8:
+ case 0x00CC:
+ case 0x0144:
+ case 0x0146:
+ case 0x0147:
+ case 0x0148:
+ mobile = 1;
+ break;
+ default:
+ break;
+ }
+
+ if (par->Architecture == NV_ARCH_04)
+ nv4GetConfig(par);
+ else
+ nv10GetConfig(par);
+
+ NVSelectHeadRegisters(par, 0);
+
+ NVLockUnlock(par, 0);
+
+ par->IOBase = (NVReadMiscOut(par) & 0x01) ? 0x3d0 : 0x3b0;
+
+ par->Television = 0;
+
+ nvidia_create_i2c_busses(par);
+ if (!par->twoHeads) {
+ par->CRTCnumber = 0;
+ nvidia_probe_i2c_connector(par, 1, &edidA);
+ if (edidA && !fb_parse_edid(edidA, &var)) {
+ printk("nvidiafb: EDID found from BUS1\n");
+ monA = &monitorA;
+ fb_edid_to_monspecs(edidA, monA);
+ FlatPanel = (monA->input & FB_DISP_DDI) ? 1 : 0;
+
+ /* NV4 doesn't support FlatPanels */
+ if ((par->Chipset & 0x0fff) <= 0x0020)
+ FlatPanel = 0;
+ } else {
+ VGA_WR08(par->PCIO, 0x03D4, 0x28);
+ if (VGA_RD08(par->PCIO, 0x03D5) & 0x80) {
+ VGA_WR08(par->PCIO, 0x03D4, 0x33);
+ if (!(VGA_RD08(par->PCIO, 0x03D5) & 0x01))
+ Television = 1;
+ FlatPanel = 1;
+ } else {
+ FlatPanel = 0;
+ }
+ printk("nvidiafb: HW is currently programmed for %s\n",
+ FlatPanel ? (Television ? "TV" : "DFP") :
+ "CRT");
+ }
+
+ if (par->FlatPanel == -1) {
+ par->FlatPanel = FlatPanel;
+ par->Television = Television;
+ } else {
+ printk("nvidiafb: Forcing display type to %s as "
+ "specified\n", par->FlatPanel ? "DFP" : "CRT");
+ }
+ } else {
+ u8 outputAfromCRTC, outputBfromCRTC;
+ int CRTCnumber = -1;
+ u8 slaved_on_A, slaved_on_B;
+ int analog_on_A, analog_on_B;
+ u32 oldhead;
+ u8 cr44;
+
+ if (implementation != 0x0110) {
+ if (NV_RD32(par->PRAMDAC0, 0x0000052C) & 0x100)
+ outputAfromCRTC = 1;
+ else
+ outputAfromCRTC = 0;
+ if (NV_RD32(par->PRAMDAC0, 0x0000252C) & 0x100)
+ outputBfromCRTC = 1;
+ else
+ outputBfromCRTC = 0;
+ analog_on_A = NVIsConnected(par, 0);
+ analog_on_B = NVIsConnected(par, 1);
+ } else {
+ outputAfromCRTC = 0;
+ outputBfromCRTC = 1;
+ analog_on_A = 0;
+ analog_on_B = 0;
+ }
+
+ VGA_WR08(par->PCIO, 0x03D4, 0x44);
+ cr44 = VGA_RD08(par->PCIO, 0x03D5);
+
+ VGA_WR08(par->PCIO, 0x03D5, 3);
+ NVSelectHeadRegisters(par, 1);
+ NVLockUnlock(par, 0);
+
+ VGA_WR08(par->PCIO, 0x03D4, 0x28);
+ slaved_on_B = VGA_RD08(par->PCIO, 0x03D5) & 0x80;
+ if (slaved_on_B) {
+ VGA_WR08(par->PCIO, 0x03D4, 0x33);
+ tvB = !(VGA_RD08(par->PCIO, 0x03D5) & 0x01);
+ }
+
+ VGA_WR08(par->PCIO, 0x03D4, 0x44);
+ VGA_WR08(par->PCIO, 0x03D5, 0);
+ NVSelectHeadRegisters(par, 0);
+ NVLockUnlock(par, 0);
+
+ VGA_WR08(par->PCIO, 0x03D4, 0x28);
+ slaved_on_A = VGA_RD08(par->PCIO, 0x03D5) & 0x80;
+ if (slaved_on_A) {
+ VGA_WR08(par->PCIO, 0x03D4, 0x33);
+ tvA = !(VGA_RD08(par->PCIO, 0x03D5) & 0x01);
+ }
+
+ oldhead = NV_RD32(par->PCRTC0, 0x00000860);
+ NV_WR32(par->PCRTC0, 0x00000860, oldhead | 0x00000010);
+
+ nvidia_probe_i2c_connector(par, 1, &edidA);
+ if (edidA && !fb_parse_edid(edidA, &var)) {
+ printk("nvidiafb: EDID found from BUS1\n");
+ monA = &monitorA;
+ fb_edid_to_monspecs(edidA, monA);
+ }
+
+ nvidia_probe_i2c_connector(par, 2, &edidB);
+ if (edidB && !fb_parse_edid(edidB, &var)) {
+ printk("nvidiafb: EDID found from BUS2\n");
+ monB = &monitorB;
+ fb_edid_to_monspecs(edidB, monB);
+ }
+
+ if (slaved_on_A && !tvA) {
+ CRTCnumber = 0;
+ FlatPanel = 1;
+ printk("nvidiafb: CRTC 0 is currently programmed for "
+ "DFP\n");
+ } else if (slaved_on_B && !tvB) {
+ CRTCnumber = 1;
+ FlatPanel = 1;
+ printk("nvidiafb: CRTC 1 is currently programmed "
+ "for DFP\n");
+ } else if (analog_on_A) {
+ CRTCnumber = outputAfromCRTC;
+ FlatPanel = 0;
+ printk("nvidiafb: CRTC %i appears to have a "
+ "CRT attached\n", CRTCnumber);
+ } else if (analog_on_B) {
+ CRTCnumber = outputBfromCRTC;
+ FlatPanel = 0;
+ printk("nvidiafb: CRTC %i"
+ "appears to have a "
+ "CRT attached\n", CRTCnumber);
+ } else if (slaved_on_A) {
+ CRTCnumber = 0;
+ FlatPanel = 1;
+ Television = 1;
+ printk("nvidiafb: CRTC 0 is currently programmed "
+ "for TV\n");
+ } else if (slaved_on_B) {
+ CRTCnumber = 1;
+ FlatPanel = 1;
+ Television = 1;
+ printk("nvidiafb: CRTC 1 is currently programmed for "
+ "TV\n");
+ } else if (monA) {
+ FlatPanel = (monA->input & FB_DISP_DDI) ? 1 : 0;
+ } else if (monB) {
+ FlatPanel = (monB->input & FB_DISP_DDI) ? 1 : 0;
+ }
+
+ if (par->FlatPanel == -1) {
+ if (FlatPanel != -1) {
+ par->FlatPanel = FlatPanel;
+ par->Television = Television;
+ } else {
+ printk("nvidiafb: Unable to detect display "
+ "type...\n");
+ if (mobile) {
+ printk("...On a laptop, assuming "
+ "DFP\n");
+ par->FlatPanel = 1;
+ } else {
+ printk("...Using default of CRT\n");
+ par->FlatPanel = 0;
+ }
+ }
+ } else {
+ printk("nvidiafb: Forcing display type to %s as "
+ "specified\n", par->FlatPanel ? "DFP" : "CRT");
+ }
+
+ if (par->CRTCnumber == -1) {
+ if (CRTCnumber != -1)
+ par->CRTCnumber = CRTCnumber;
+ else {
+ printk("nvidiafb: Unable to detect which "
+ "CRTCNumber...\n");
+ if (par->FlatPanel)
+ par->CRTCnumber = 1;
+ else
+ par->CRTCnumber = 0;
+ printk("...Defaulting to CRTCNumber %i\n",
+ par->CRTCnumber);
+ }
+ } else {
+ printk("nvidiafb: Forcing CRTCNumber %i as "
+ "specified\n", par->CRTCnumber);
+ }
+
+ if (monA) {
+ if (((monA->input & FB_DISP_DDI) &&
+ par->FlatPanel) ||
+ ((!(monA->input & FB_DISP_DDI)) &&
+ !par->FlatPanel)) {
+ if (monB) {
+ fb_destroy_modedb(monB->modedb);
+ monB = NULL;
+ }
+ } else {
+ fb_destroy_modedb(monA->modedb);
+ monA = NULL;
+ }
+ }
+
+ if (monB) {
+ if (((monB->input & FB_DISP_DDI) &&
+ !par->FlatPanel) ||
+ ((!(monB->input & FB_DISP_DDI)) &&
+ par->FlatPanel)) {
+ fb_destroy_modedb(monB->modedb);
+ monB = NULL;
+ } else
+ monA = monB;
+ }
+
+ if (implementation == 0x0110)
+ cr44 = par->CRTCnumber * 0x3;
+
+ NV_WR32(par->PCRTC0, 0x00000860, oldhead);
+
+ VGA_WR08(par->PCIO, 0x03D4, 0x44);
+ VGA_WR08(par->PCIO, 0x03D5, cr44);
+ NVSelectHeadRegisters(par, par->CRTCnumber);
+ }
+
+ printk("nvidiafb: Using %s on CRTC %i\n",
+ par->FlatPanel ? (par->Television ? "TV" : "DFP") : "CRT",
+ par->CRTCnumber);
+
+ if (par->FlatPanel && !par->Television) {
+ par->fpWidth = NV_RD32(par->PRAMDAC, 0x0820) + 1;
+ par->fpHeight = NV_RD32(par->PRAMDAC, 0x0800) + 1;
+ par->fpSyncs = NV_RD32(par->PRAMDAC, 0x0848) & 0x30000033;
+
+ printk("Panel size is %i x %i\n", par->fpWidth, par->fpHeight);
+ }
+
+ if (monA)
+ info->monspecs = *monA;
+
+ kfree(edidA);
+ kfree(edidB);
+}
diff --git a/drivers/video/nvidia/nv_type.h b/drivers/video/nvidia/nv_type.h
new file mode 100644
index 0000000000000..e4a5b1da71c43
--- /dev/null
+++ b/drivers/video/nvidia/nv_type.h
@@ -0,0 +1,174 @@
+#ifndef __NV_TYPE_H__
+#define __NV_TYPE_H__
+
+#include <linux/fb.h>
+#include <linux/types.h>
+#include <linux/i2c.h>
+#include <linux/i2c-id.h>
+#include <linux/i2c-algo-bit.h>
+
+#define NV_ARCH_04 0x04
+#define NV_ARCH_10 0x10
+#define NV_ARCH_20 0x20
+#define NV_ARCH_30 0x30
+#define NV_ARCH_40 0x40
+
+#define BITMASK(t,b) (((unsigned)(1U << (((t)-(b)+1)))-1) << (b))
+#define MASKEXPAND(mask) BITMASK(1?mask,0?mask)
+#define SetBF(mask,value) ((value) << (0?mask))
+#define GetBF(var,mask) (((unsigned)((var) & MASKEXPAND(mask))) >> (0?mask) )
+#define SetBitField(value,from,to) SetBF(to, GetBF(value,from))
+#define SetBit(n) (1<<(n))
+#define Set8Bits(value) ((value)&0xff)
+
+#define V_DBLSCAN 1
+
+typedef struct {
+ int bitsPerPixel;
+ int depth;
+ int displayWidth;
+ int weight;
+} NVFBLayout;
+
+#define NUM_SEQ_REGS 0x05
+#define NUM_CRT_REGS 0x41
+#define NUM_GRC_REGS 0x09
+#define NUM_ATC_REGS 0x15
+
+struct nvidia_par;
+
+struct nvidia_i2c_chan {
+ struct nvidia_par *par;
+ unsigned long ddc_base;
+ struct i2c_adapter adapter;
+ struct i2c_algo_bit_data algo;
+};
+
+typedef struct _riva_hw_state {
+ u8 attr[NUM_ATC_REGS];
+ u8 crtc[NUM_CRT_REGS];
+ u8 gra[NUM_GRC_REGS];
+ u8 seq[NUM_SEQ_REGS];
+ u8 misc_output;
+ u32 bpp;
+ u32 width;
+ u32 height;
+ u32 interlace;
+ u32 repaint0;
+ u32 repaint1;
+ u32 screen;
+ u32 scale;
+ u32 dither;
+ u32 extra;
+ u32 fifo;
+ u32 pixel;
+ u32 horiz;
+ u32 arbitration0;
+ u32 arbitration1;
+ u32 pll;
+ u32 pllB;
+ u32 vpll;
+ u32 vpll2;
+ u32 vpllB;
+ u32 vpll2B;
+ u32 pllsel;
+ u32 general;
+ u32 crtcOwner;
+ u32 head;
+ u32 head2;
+ u32 config;
+ u32 cursorConfig;
+ u32 cursor0;
+ u32 cursor1;
+ u32 cursor2;
+ u32 timingH;
+ u32 timingV;
+ u32 displayV;
+ u32 crtcSync;
+} RIVA_HW_STATE;
+
+struct riva_regs {
+ RIVA_HW_STATE ext;
+};
+
+struct nvidia_par {
+ RIVA_HW_STATE SavedReg;
+ RIVA_HW_STATE ModeReg;
+ RIVA_HW_STATE *CurrentState;
+ u32 pseudo_palette[16];
+ struct pci_dev *pci_dev;
+ u32 Architecture;
+ u32 CursorStart;
+ int Chipset;
+ int bus;
+ unsigned long FbAddress;
+ u8 __iomem *FbStart;
+ u32 FbMapSize;
+ u32 FbUsableSize;
+ u32 ScratchBufferSize;
+ u32 ScratchBufferStart;
+ int FpScale;
+ u32 MinVClockFreqKHz;
+ u32 MaxVClockFreqKHz;
+ u32 CrystalFreqKHz;
+ u32 RamAmountKBytes;
+ u32 IOBase;
+ NVFBLayout CurrentLayout;
+ int cursor_reset;
+ int lockup;
+ int videoKey;
+ int FlatPanel;
+ int FPDither;
+ int Television;
+ int CRTCnumber;
+ int alphaCursor;
+ int twoHeads;
+ int twoStagePLL;
+ int fpScaler;
+ int fpWidth;
+ int fpHeight;
+ int PanelTweak;
+ int paneltweak;
+ u32 crtcSync_read;
+ u32 fpSyncs;
+ u32 dmaPut;
+ u32 dmaCurrent;
+ u32 dmaFree;
+ u32 dmaMax;
+ u32 __iomem *dmaBase;
+ u32 currentRop;
+ int WaitVSyncPossible;
+ int BlendingPossible;
+ u32 paletteEnabled;
+ u32 forceCRTC;
+ u8 DDCBase;
+#ifdef CONFIG_MTRR
+ struct {
+ int vram;
+ int vram_valid;
+ } mtrr;
+#endif
+ struct nvidia_i2c_chan chan[3];
+
+ volatile u32 __iomem *REGS;
+ volatile u32 __iomem *PCRTC0;
+ volatile u32 __iomem *PCRTC;
+ volatile u32 __iomem *PRAMDAC0;
+ volatile u32 __iomem *PFB;
+ volatile u32 __iomem *PFIFO;
+ volatile u32 __iomem *PGRAPH;
+ volatile u32 __iomem *PEXTDEV;
+ volatile u32 __iomem *PTIMER;
+ volatile u32 __iomem *PMC;
+ volatile u32 __iomem *PRAMIN;
+ volatile u32 __iomem *FIFO;
+ volatile u32 __iomem *CURSOR;
+ volatile u8 __iomem *PCIO0;
+ volatile u8 __iomem *PCIO;
+ volatile u8 __iomem *PVIO;
+ volatile u8 __iomem *PDIO0;
+ volatile u8 __iomem *PDIO;
+ volatile u32 __iomem *PRAMDAC;
+};
+
+#endif /* __NV_TYPE_H__ */
diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c
new file mode 100644
index 0000000000000..3a6555a8aaa25
--- /dev/null
+++ b/drivers/video/nvidia/nvidia.c
@@ -0,0 +1,1729 @@
+/*
+ * linux/drivers/video/nvidia/nvidia.c - nVidia fb driver
+ *
+ * Copyright 2004 Antonino Daplas <adaplas@pol.net>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive
+ * for more details.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#ifdef CONFIG_MTRR
+#include <asm/mtrr.h>
+#endif
+#ifdef CONFIG_PPC_OF
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+#endif
+#ifdef CONFIG_PMAC_BACKLIGHT
+#include <asm/backlight.h>
+#endif
+
+#include "nv_local.h"
+#include "nv_type.h"
+#include "nv_proto.h"
+#include "nv_dma.h"
+
+#ifndef CONFIG_PCI /* sanity check */
+#error This driver requires PCI support.
+#endif
+
+#undef CONFIG_FB_NVIDIA_DEBUG
+#ifdef CONFIG_FB_NVIDIA_DEBUG
+#define NVTRACE printk
+#else
+#define NVTRACE if (0) printk
+#endif
+
+#define NVTRACE_ENTER(...) NVTRACE("%s START\n", __FUNCTION__)
+#define NVTRACE_LEAVE(...) NVTRACE("%s END\n", __FUNCTION__)
+
+#ifdef CONFIG_FB_NVIDIA_DEBUG
+#define assert(expr) \
+ if (!(expr)) { \
+ printk( "Assertion failed! %s,%s,%s,line=%d\n",\
+ #expr,__FILE__,__FUNCTION__,__LINE__); \
+ BUG(); \
+ }
+#else
+#define assert(expr)
+#endif
+
+#define PFX "nvidiafb: "
+
+/* HW cursor parameters */
+#define MAX_CURS 32
+
+static struct pci_device_id nvidiafb_pci_tbl[] = {
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_TNT,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_TNT2,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_UTNT2,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_TNT_UNKNOWN,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_VTNT2,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_UVTNT2,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_ITNT2,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_SDR,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_DDR,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_MX,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_MX2,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_GO,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO2_MXR,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_GTS,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_GTS2,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_ULTRA,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO2_PRO,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_460,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_420,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440_SE,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_440_GO,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_420_GO,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_460_GO,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_420_GO_M32,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_500XGL,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_440_GO_M64,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_200,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_550XGL,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_500_GOGL,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_410_GO_M16,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440_8X,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440SE_8X,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_420_8X,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_448_GO,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_488_GO,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_580_XGL,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_MAC,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_280_NVS,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_380_XGL,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_IGEFORCE2,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE3,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE3_1,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE3_2,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_DDC,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4600,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4400,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4200,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_900XGL,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_750XGL,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_700XGL,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800_8X,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800SE,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_4200_GO,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_980_XGL,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_780_XGL,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_700_GOGL,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5800_ULTRA,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5800,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_FX_2000,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_FX_1000,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5600_ULTRA,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5600,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5600SE,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5600,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5650,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_FX_GO700,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5200,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5200_ULTRA,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5200_1,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5200SE,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5200,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5250,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5250_32,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO_5200,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_NVS_280_PCI,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_FX_500,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5300,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5100,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5900_ULTRA,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5900,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5900XT,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5950_ULTRA,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_FX_3000,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5700_ULTRA,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5700,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5700LE,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5700VE,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5700_1,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5700_2,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_FX_GO1000,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_FX_1100,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5500,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5100,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_FX_700,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5900ZT,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6800_ULTRA,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6800,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6800_LE,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6800_GT,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_FX_4000,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6600_GT,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6600,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6610_XL,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_FX_540,
+ 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, 0x0252,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, 0x0313,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, 0x0316,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, 0x0317,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, 0x031D,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, 0x031E,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, 0x031F,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, 0x0329,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, 0x032F,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, 0x0345,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, 0x0349,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, 0x034B,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, 0x034F,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, 0x00c0,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_GEFORCE_6800A,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_GEFORCE_6800A_LE,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_GEFORCE_GO_6800,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_GEFORCE_GO_6800_ULTRA,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_QUADRO_FX_GO1400,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, 0x00cd,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_QUADRO_FX_1400,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, 0x0142,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, 0x0143,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, 0x0144,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, 0x0145,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, 0x0146,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, 0x0147,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, 0x0148,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, 0x0149,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, 0x014b,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, 0x14c,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, 0x014d,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, 0x0160,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6200_TURBOCACHE,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, 0x0162,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, 0x0163,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_6200,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, 0x0165,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_6250,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_6200_1,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_6250_1,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, 0x0169,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, 0x016b,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, 0x016c,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, 0x016d,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, 0x016e,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, 0x0210,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6800B,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6800B_LE,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6800B_GT,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, 0x021d,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, 0x021e,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, 0x0220,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, 0x0221,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, 0x0222,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, 0x0228,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {0,} /* terminate list */
+};
+
+MODULE_DEVICE_TABLE(pci, nvidiafb_pci_tbl);
+
+/* command line data, set in nvidiafb_setup() */
+static int flatpanel __devinitdata = -1; /* Autodetect later */
+static int forceCRTC __devinitdata = -1;
+static int hwcur __devinitdata = 0;
+static int noaccel __devinitdata = 0;
+static int noscale __devinitdata = 0;
+static int paneltweak __devinitdata = 0;
+#ifdef CONFIG_MTRR
+static int nomtrr __devinitdata = 0;
+#endif
+
+static char *mode_option __devinitdata = NULL;
+
+static struct fb_fix_screeninfo __devinitdata nvidiafb_fix = {
+ .type = FB_TYPE_PACKED_PIXELS,
+ .xpanstep = 8,
+ .ypanstep = 1,
+};
+
+static struct fb_var_screeninfo __devinitdata nvidiafb_default_var = {
+ .xres = 640,
+ .yres = 480,
+ .xres_virtual = 640,
+ .yres_virtual = 480,
+ .bits_per_pixel = 8,
+ .red = {0, 8, 0},
+ .green = {0, 8, 0},
+ .blue = {0, 8, 0},
+ .transp = {0, 0, 0},
+ .activate = FB_ACTIVATE_NOW,
+ .height = -1,
+ .width = -1,
+ .pixclock = 39721,
+ .left_margin = 40,
+ .right_margin = 24,
+ .upper_margin = 32,
+ .lower_margin = 11,
+ .hsync_len = 96,
+ .vsync_len = 2,
+ .vmode = FB_VMODE_NONINTERLACED
+};
+
+/*
+ * Backlight control
+ */
+#ifdef CONFIG_PMAC_BACKLIGHT
+
+static int nvidia_backlight_levels[] = {
+ 0x158,
+ 0x192,
+ 0x1c6,
+ 0x200,
+ 0x234,
+ 0x268,
+ 0x2a2,
+ 0x2d6,
+ 0x310,
+ 0x344,
+ 0x378,
+ 0x3b2,
+ 0x3e6,
+ 0x41a,
+ 0x454,
+ 0x534,
+};
+
+/* ------------------------------------------------------------------------- *
+ *
+ * Backlight operations
+ *
+ * ------------------------------------------------------------------------- */
+
+static int nvidia_set_backlight_enable(int on, int level, void *data)
+{
+ struct nvidia_par *par = (struct nvidia_par *)data;
+ u32 tmp_pcrt, tmp_pmc, fpcontrol;
+
+ tmp_pmc = NV_RD32(par->PMC, 0x10F0) & 0x0000FFFF;
+ tmp_pcrt = NV_RD32(par->PCRTC0, 0x081C) & 0xFFFFFFFC;
+ fpcontrol = NV_RD32(par->PRAMDAC, 0x0848) & 0xCFFFFFCC;
+
+ if (on && (level > BACKLIGHT_OFF)) {
+ tmp_pcrt |= 0x1;
+ tmp_pmc |= (1 << 31); // backlight bit
+ tmp_pmc |= nvidia_backlight_levels[level - 1] << 16;
+ }
+
+ if (on)
+ fpcontrol |= par->fpSyncs;
+ else
+ fpcontrol |= 0x20000022;
+
+ NV_WR32(par->PCRTC0, 0x081C, tmp_pcrt);
+ NV_WR32(par->PMC, 0x10F0, tmp_pmc);
+ NV_WR32(par->PRAMDAC, 0x848, fpcontrol);
+
+ return 0;
+}
+
+static int nvidia_set_backlight_level(int level, void *data)
+{
+ return nvidia_set_backlight_enable(1, level, data);
+}
+
+static struct backlight_controller nvidia_backlight_controller = {
+ nvidia_set_backlight_enable,
+ nvidia_set_backlight_level
+};
+
+#endif /* CONFIG_PMAC_BACKLIGHT */
+
+static void nvidiafb_load_cursor_image(struct nvidia_par *par, u8 * data8,
+ u16 bg, u16 fg, u32 w, u32 h)
+{
+ int i, j, k = 0;
+ u32 b, tmp;
+ u32 *data = (u32 *) data8;
+
+ w = (w + 1) & ~1;
+
+ for (i = 0; i < h; i++) {
+ b = *data++;
+ reverse_order(&b);
+
+ for (j = 0; j < w / 2; j++) {
+ tmp = 0;
+#if defined (__BIG_ENDIAN)
+ tmp = (b & (1 << 31)) ? fg << 16 : bg << 16;
+ b <<= 1;
+ tmp |= (b & (1 << 31)) ? fg : bg;
+ b <<= 1;
+#else
+ tmp = (b & 1) ? fg : bg;
+ b >>= 1;
+ tmp |= (b & 1) ? fg << 16 : bg << 16;
+ b >>= 1;
+#endif
+ NV_WR32(&par->CURSOR[k++], 0, tmp);
+ }
+ k += (MAX_CURS - w) / 2;
+ }
+}
+
+static void nvidia_write_clut(struct nvidia_par *par,
+ u8 regnum, u8 red, u8 green, u8 blue)
+{
+ NVWriteDacMask(par, 0xff);
+ NVWriteDacWriteAddr(par, regnum);
+ NVWriteDacData(par, red);
+ NVWriteDacData(par, green);
+ NVWriteDacData(par, blue);
+}
+
+static void nvidia_read_clut(struct nvidia_par *par,
+ u8 regnum, u8 * red, u8 * green, u8 * blue)
+{
+ NVWriteDacMask(par, 0xff);
+ NVWriteDacReadAddr(par, regnum);
+ *red = NVReadDacData(par);
+ *green = NVReadDacData(par);
+ *blue = NVReadDacData(par);
+}
+
+static int nvidia_panel_tweak(struct nvidia_par *par,
+ struct _riva_hw_state *state)
+{
+ int tweak = 0;
+
+ if (par->paneltweak) {
+ tweak = par->paneltweak;
+ } else {
+ /* begin flat panel hacks */
+ /* This is unfortunate, but some chips need this register
+ tweaked or else you get artifacts where adjacent pixels are
+ swapped. There are no hard rules for what to set here so all
+ we can do is experiment and apply hacks. */
+
+ if(((par->Chipset & 0xffff) == 0x0328) && (state->bpp == 32)) {
+ /* At least one NV34 laptop needs this workaround. */
+ tweak = -1;
+ }
+
+ if((par->Chipset & 0xfff0) == 0x0310) {
+ tweak = 1;
+ }
+ /* end flat panel hacks */
+ }
+
+ return tweak;
+}
+
+static void nvidia_save_vga(struct nvidia_par *par,
+ struct _riva_hw_state *state)
+{
+ int i;
+
+ NVTRACE_ENTER();
+ NVLockUnlock(par, 0);
+
+ NVUnloadStateExt(par, state);
+
+ state->misc_output = NVReadMiscOut(par);
+
+ for (i = 0; i < NUM_CRT_REGS; i++)
+ state->crtc[i] = NVReadCrtc(par, i);
+
+ for (i = 0; i < NUM_ATC_REGS; i++)
+ state->attr[i] = NVReadAttr(par, i);
+
+ for (i = 0; i < NUM_GRC_REGS; i++)
+ state->gra[i] = NVReadGr(par, i);
+
+ for (i = 0; i < NUM_SEQ_REGS; i++)
+ state->seq[i] = NVReadSeq(par, i);
+ NVTRACE_LEAVE();
+}
+
+static void nvidia_write_regs(struct nvidia_par *par)
+{
+ struct _riva_hw_state *state = &par->ModeReg;
+ int i;
+
+ NVTRACE_ENTER();
+ NVWriteCrtc(par, 0x11, 0x00);
+
+ NVLockUnlock(par, 0);
+
+ NVLoadStateExt(par, state);
+
+ NVWriteMiscOut(par, state->misc_output);
+
+ for (i = 0; i < NUM_CRT_REGS; i++) {
+ switch (i) {
+ case 0x19:
+ case 0x20 ... 0x40:
+ break;
+ default:
+ NVWriteCrtc(par, i, state->crtc[i]);
+ }
+ }
+
+ for (i = 0; i < NUM_ATC_REGS; i++)
+ NVWriteAttr(par, i, state->attr[i]);
+
+ for (i = 0; i < NUM_GRC_REGS; i++)
+ NVWriteGr(par, i, state->gra[i]);
+
+ for (i = 0; i < NUM_SEQ_REGS; i++)
+ NVWriteSeq(par, i, state->seq[i]);
+ NVTRACE_LEAVE();
+}
+
+static int nvidia_calc_regs(struct fb_info *info)
+{
+ struct nvidia_par *par = info->par;
+ struct _riva_hw_state *state = &par->ModeReg;
+ int i, depth = fb_get_color_depth(&info->var);
+ int h_display = info->var.xres / 8 - 1;
+ int h_start = (info->var.xres + info->var.right_margin) / 8 - 1;
+ int h_end = (info->var.xres + info->var.right_margin +
+ info->var.hsync_len) / 8 - 1;
+ int h_total = (info->var.xres + info->var.right_margin +
+ info->var.hsync_len + info->var.left_margin) / 8 - 5;
+ int h_blank_s = h_display;
+ int h_blank_e = h_total + 4;
+ int v_display = info->var.yres - 1;
+ int v_start = info->var.yres + info->var.lower_margin - 1;
+ int v_end = (info->var.yres + info->var.lower_margin +
+ info->var.vsync_len) - 1;
+ int v_total = (info->var.yres + info->var.lower_margin +
+ info->var.vsync_len + info->var.upper_margin) - 2;
+ int v_blank_s = v_display;
+ int v_blank_e = v_total + 1;
+
+ /*
+ * Set all CRTC values.
+ */
+
+ if (info->var.vmode & FB_VMODE_INTERLACED)
+ v_total |= 1;
+
+ if (par->FlatPanel == 1) {
+ v_start = v_total - 3;
+ v_end = v_total - 2;
+ v_blank_s = v_start;
+ h_start = h_total - 5;
+ h_end = h_total - 2;
+ h_blank_e = h_total + 4;
+ }
+
+ state->crtc[0x0] = Set8Bits(h_total);
+ state->crtc[0x1] = Set8Bits(h_display);
+ state->crtc[0x2] = Set8Bits(h_blank_s);
+ state->crtc[0x3] = SetBitField(h_blank_e, 4: 0, 4:0)
+ | SetBit(7);
+ state->crtc[0x4] = Set8Bits(h_start);
+ state->crtc[0x5] = SetBitField(h_blank_e, 5: 5, 7:7)
+ | SetBitField(h_end, 4: 0, 4:0);
+ state->crtc[0x6] = SetBitField(v_total, 7: 0, 7:0);
+ state->crtc[0x7] = SetBitField(v_total, 8: 8, 0:0)
+ | SetBitField(v_display, 8: 8, 1:1)
+ | SetBitField(v_start, 8: 8, 2:2)
+ | SetBitField(v_blank_s, 8: 8, 3:3)
+ | SetBit(4)
+ | SetBitField(v_total, 9: 9, 5:5)
+ | SetBitField(v_display, 9: 9, 6:6)
+ | SetBitField(v_start, 9: 9, 7:7);
+ state->crtc[0x9] = SetBitField(v_blank_s, 9: 9, 5:5)
+ | SetBit(6)
+ | ((info->var.vmode & FB_VMODE_DOUBLE) ? 0x80 : 0x00);
+ state->crtc[0x10] = Set8Bits(v_start);
+ state->crtc[0x11] = SetBitField(v_end, 3: 0, 3:0) | SetBit(5);
+ state->crtc[0x12] = Set8Bits(v_display);
+ state->crtc[0x13] = ((info->var.xres_virtual / 8) *
+ (info->var.bits_per_pixel / 8));
+ state->crtc[0x15] = Set8Bits(v_blank_s);
+ state->crtc[0x16] = Set8Bits(v_blank_e);
+
+ state->attr[0x10] = 0x01;
+
+ if (par->Television)
+ state->attr[0x11] = 0x00;
+
+ state->screen = SetBitField(h_blank_e, 6: 6, 4:4)
+ | SetBitField(v_blank_s, 10: 10, 3:3)
+ | SetBitField(v_start, 10: 10, 2:2)
+ | SetBitField(v_display, 10: 10, 1:1)
+ | SetBitField(v_total, 10: 10, 0:0);
+
+ state->horiz = SetBitField(h_total, 8: 8, 0:0)
+ | SetBitField(h_display, 8: 8, 1:1)
+ | SetBitField(h_blank_s, 8: 8, 2:2)
+ | SetBitField(h_start, 8: 8, 3:3);
+
+ state->extra = SetBitField(v_total, 11: 11, 0:0)
+ | SetBitField(v_display, 11: 11, 2:2)
+ | SetBitField(v_start, 11: 11, 4:4)
+ | SetBitField(v_blank_s, 11: 11, 6:6);
+
+ if (info->var.vmode & FB_VMODE_INTERLACED) {
+ h_total = (h_total >> 1) & ~1;
+ state->interlace = Set8Bits(h_total);
+ state->horiz |= SetBitField(h_total, 8: 8, 4:4);
+ } else {
+ state->interlace = 0xff; /* interlace off */
+ }
+
+ /*
+ * Calculate the extended registers.
+ */
+
+ if (depth < 24)
+ i = depth;
+ else
+ i = 32;
+
+ if (par->Architecture >= NV_ARCH_10)
+ par->CURSOR = (volatile u32 __iomem *)(info->screen_base +
+ par->CursorStart);
+
+ if (info->var.sync & FB_SYNC_HOR_HIGH_ACT)
+ state->misc_output &= ~0x40;
+ else
+ state->misc_output |= 0x40;
+ if (info->var.sync & FB_SYNC_VERT_HIGH_ACT)
+ state->misc_output &= ~0x80;
+ else
+ state->misc_output |= 0x80;
+
+ NVCalcStateExt(par, state, i, info->var.xres_virtual,
+ info->var.xres, info->var.yres_virtual,
+ 1000000000 / info->var.pixclock, info->var.vmode);
+
+ state->scale = NV_RD32(par->PRAMDAC, 0x00000848) & 0xfff000ff;
+ if (par->FlatPanel == 1) {
+ state->pixel |= (1 << 7);
+
+ if (!par->fpScaler || (par->fpWidth <= info->var.xres)
+ || (par->fpHeight <= info->var.yres)) {
+ state->scale |= (1 << 8);
+ }
+
+ if (!par->crtcSync_read) {
+ state->crtcSync = NV_RD32(par->PRAMDAC, 0x0828);
+ par->crtcSync_read = 1;
+ }
+
+ par->PanelTweak = nvidia_panel_tweak(par, state);
+ }
+
+ state->vpll = state->pll;
+ state->vpll2 = state->pll;
+ state->vpllB = state->pllB;
+ state->vpll2B = state->pllB;
+
+ VGA_WR08(par->PCIO, 0x03D4, 0x1C);
+ state->fifo = VGA_RD08(par->PCIO, 0x03D5) & ~(1<<5);
+
+ if (par->CRTCnumber) {
+ state->head = NV_RD32(par->PCRTC0, 0x00000860) & ~0x00001000;
+ state->head2 = NV_RD32(par->PCRTC0, 0x00002860) | 0x00001000;
+ state->crtcOwner = 3;
+ state->pllsel |= 0x20000800;
+ state->vpll = NV_RD32(par->PRAMDAC0, 0x00000508);
+ if (par->twoStagePLL)
+ state->vpllB = NV_RD32(par->PRAMDAC0, 0x00000578);
+ } else if (par->twoHeads) {
+ state->head = NV_RD32(par->PCRTC0, 0x00000860) | 0x00001000;
+ state->head2 = NV_RD32(par->PCRTC0, 0x00002860) & ~0x00001000;
+ state->crtcOwner = 0;
+ state->vpll2 = NV_RD32(par->PRAMDAC0, 0x0520);
+ if (par->twoStagePLL)
+ state->vpll2B = NV_RD32(par->PRAMDAC0, 0x057C);
+ }
+
+ state->cursorConfig = 0x00000100;
+
+ if (info->var.vmode & FB_VMODE_DOUBLE)
+ state->cursorConfig |= (1 << 4);
+
+ if (par->alphaCursor) {
+ if ((par->Chipset & 0x0ff0) != 0x0110)
+ state->cursorConfig |= 0x04011000;
+ else
+ state->cursorConfig |= 0x14011000;
+ state->general |= (1 << 29);
+ } else
+ state->cursorConfig |= 0x02000000;
+
+ if (par->twoHeads) {
+ if ((par->Chipset & 0x0ff0) == 0x0110) {
+ state->dither = NV_RD32(par->PRAMDAC, 0x0528) &
+ ~0x00010000;
+ if (par->FPDither)
+ state->dither |= 0x00010000;
+ } else {
+ state->dither = NV_RD32(par->PRAMDAC, 0x083C) & ~1;
+ if (par->FPDither)
+ state->dither |= 1;
+ }
+ }
+
+ state->timingH = 0;
+ state->timingV = 0;
+ state->displayV = info->var.xres;
+
+ return 0;
+}
+
+static void nvidia_init_vga(struct fb_info *info)
+{
+ struct nvidia_par *par = info->par;
+ struct _riva_hw_state *state = &par->ModeReg;
+ int i;
+
+ for (i = 0; i < 0x10; i++)
+ state->attr[i] = i;
+ state->attr[0x10] = 0x41;
+ state->attr[0x11] = 0x01;
+ state->attr[0x12] = 0x0f;
+ state->attr[0x13] = 0x00;
+ state->attr[0x14] = 0x00;
+
+ memset(state->crtc, 0x00, NUM_CRT_REGS);
+ state->crtc[0x0a] = 0x20;
+ state->crtc[0x17] = 0xe3;
+ state->crtc[0x18] = 0xff;
+ state->crtc[0x28] = 0x40;
+
+ memset(state->gra, 0x00, NUM_GRC_REGS);
+ state->gra[0x05] = 0x40;
+ state->gra[0x06] = 0x05;
+ state->gra[0x07] = 0x0f;
+ state->gra[0x08] = 0xff;
+
+ state->seq[0x00] = 0x03;
+ state->seq[0x01] = 0x01;
+ state->seq[0x02] = 0x0f;
+ state->seq[0x03] = 0x00;
+ state->seq[0x04] = 0x0e;
+
+ state->misc_output = 0xeb;
+}
+
+static int nvidiafb_cursor(struct fb_info *info, struct fb_cursor *cursor)
+{
+ struct nvidia_par *par = info->par;
+ u8 data[MAX_CURS * MAX_CURS / 8];
+ u16 fg, bg;
+ int i, set = cursor->set;
+
+ if (cursor->image.width > MAX_CURS || cursor->image.height > MAX_CURS)
+ return soft_cursor(info, cursor);
+
+ NVShowHideCursor(par, 0);
+
+ if (par->cursor_reset) {
+ set = FB_CUR_SETALL;
+ par->cursor_reset = 0;
+ }
+
+ if (set & FB_CUR_SETSIZE)
+ memset_io(par->CURSOR, 0, MAX_CURS * MAX_CURS * 2);
+
+ if (set & FB_CUR_SETPOS) {
+ u32 xx, yy, temp;
+
+ yy = cursor->image.dy - info->var.yoffset;
+ xx = cursor->image.dx - info->var.xoffset;
+ temp = xx & 0xFFFF;
+ temp |= yy << 16;
+
+ NV_WR32(par->PRAMDAC, 0x0000300, temp);
+ }
+
+ if (set & (FB_CUR_SETSHAPE | FB_CUR_SETCMAP | FB_CUR_SETIMAGE)) {
+ u32 bg_idx = cursor->image.bg_color;
+ u32 fg_idx = cursor->image.fg_color;
+ u32 s_pitch = (cursor->image.width + 7) >> 3;
+ u32 d_pitch = MAX_CURS / 8;
+ u8 *dat = (u8 *) cursor->image.data;
+ u8 *msk = (u8 *) cursor->mask;
+ u8 *src;
+
+ src = kmalloc(s_pitch * cursor->image.height, GFP_ATOMIC);
+
+ if (src) {
+ switch (cursor->rop) {
+ case ROP_XOR:
+ for (i = 0; i < s_pitch * cursor->image.height;
+ i++)
+ src[i] = dat[i] ^ msk[i];
+ break;
+ case ROP_COPY:
+ default:
+ for (i = 0; i < s_pitch * cursor->image.height;
+ i++)
+ src[i] = dat[i] & msk[i];
+ break;
+ }
+
+ fb_sysmove_buf_aligned(info, &info->pixmap, data,
+ d_pitch, src, s_pitch,
+ cursor->image.height);
+
+ bg = ((info->cmap.red[bg_idx] & 0xf8) << 7) |
+ ((info->cmap.green[bg_idx] & 0xf8) << 2) |
+ ((info->cmap.blue[bg_idx] & 0xf8) >> 3) | 1 << 15;
+
+ fg = ((info->cmap.red[fg_idx] & 0xf8) << 7) |
+ ((info->cmap.green[fg_idx] & 0xf8) << 2) |
+ ((info->cmap.blue[fg_idx] & 0xf8) >> 3) | 1 << 15;
+
+ NVLockUnlock(par, 0);
+
+ nvidiafb_load_cursor_image(par, data, bg, fg,
+ cursor->image.width,
+ cursor->image.height);
+ kfree(src);
+ }
+ }
+
+ if (cursor->enable)
+ NVShowHideCursor(par, 1);
+
+ return 0;
+}
+
+static int nvidiafb_set_par(struct fb_info *info)
+{
+ struct nvidia_par *par = info->par;
+
+ NVTRACE_ENTER();
+
+ NVLockUnlock(par, 1);
+ if (!par->FlatPanel || (info->var.bits_per_pixel != 24) ||
+ !par->twoHeads)
+ par->FPDither = 0;
+
+ nvidia_init_vga(info);
+ nvidia_calc_regs(info);
+ nvidia_write_regs(par);
+
+ NVLockUnlock(par, 0);
+ if (par->twoHeads) {
+ VGA_WR08(par->PCIO, 0x03D4, 0x44);
+ VGA_WR08(par->PCIO, 0x03D5, par->ModeReg.crtcOwner);
+ NVLockUnlock(par, 0);
+ }
+
+ NVWriteCrtc(par, 0x11, 0x00);
+ info->fix.line_length = (info->var.xres_virtual *
+ info->var.bits_per_pixel) >> 3;
+ info->fix.visual = (info->var.bits_per_pixel == 8) ?
+ FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
+
+ if (info->var.accel_flags) {
+ info->fbops->fb_imageblit = nvidiafb_imageblit;
+ info->fbops->fb_fillrect = nvidiafb_fillrect;
+ info->fbops->fb_copyarea = nvidiafb_copyarea;
+ info->fbops->fb_sync = nvidiafb_sync;
+ info->pixmap.scan_align = 4;
+ info->flags &= ~FBINFO_HWACCEL_DISABLED;
+ NVResetGraphics(info);
+ } else {
+ info->fbops->fb_imageblit = cfb_imageblit;
+ info->fbops->fb_fillrect = cfb_fillrect;
+ info->fbops->fb_copyarea = cfb_copyarea;
+ info->fbops->fb_sync = NULL;
+ info->pixmap.scan_align = 1;
+ info->flags |= FBINFO_HWACCEL_DISABLED;
+ }
+
+ par->cursor_reset = 1;
+
+ NVWriteCrtc(par, 0x11, 0xff);
+
+ NVTRACE_LEAVE();
+ return 0;
+}
+
+static int nvidiafb_setcolreg(unsigned regno, unsigned red, unsigned green,
+ unsigned blue, unsigned transp,
+ struct fb_info *info)
+{
+ struct nvidia_par *par = info->par;
+ int i;
+
+ NVTRACE_ENTER();
+ if (regno >= (1 << info->var.green.length))
+ return -EINVAL;
+
+ if (info->var.grayscale) {
+ /* gray = 0.30*R + 0.59*G + 0.11*B */
+ red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
+ }
+
+ if (regno < 16 && info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
+ ((u32 *) info->pseudo_palette)[regno] =
+ (regno << info->var.red.offset) |
+ (regno << info->var.green.offset) |
+ (regno << info->var.blue.offset);
+ }
+
+ switch (info->var.bits_per_pixel) {
+ case 8:
+ /* "transparent" stuff is completely ignored. */
+ nvidia_write_clut(par, regno, red >> 8, green >> 8, blue >> 8);
+ break;
+ case 16:
+ if (info->var.green.length == 5) {
+ for (i = 0; i < 8; i++) {
+ nvidia_write_clut(par, regno * 8 + i, red >> 8,
+ green >> 8, blue >> 8);
+ }
+ } else {
+ u8 r, g, b;
+
+ if (regno < 32) {
+ for (i = 0; i < 8; i++) {
+ nvidia_write_clut(par, regno * 8 + i,
+ red >> 8, green >> 8,
+ blue >> 8);
+ }
+ }
+
+ nvidia_read_clut(par, regno * 4, &r, &g, &b);
+
+ for (i = 0; i < 4; i++)
+ nvidia_write_clut(par, regno * 4 + i, r,
+ green >> 8, b);
+ }
+ break;
+ case 32:
+ nvidia_write_clut(par, regno, red >> 8, green >> 8, blue >> 8);
+ break;
+ default:
+ /* do nothing */
+ break;
+ }
+
+ NVTRACE_LEAVE();
+ return 0;
+}
+
+static int nvidiafb_check_var(struct fb_var_screeninfo *var,
+ struct fb_info *info)
+{
+ struct nvidia_par *par = info->par;
+ int memlen, vramlen, mode_valid = 0;
+ int pitch, err = 0;
+
+ NVTRACE_ENTER();
+
+ var->transp.offset = 0;
+ var->transp.length = 0;
+
+ var->xres &= ~7;
+
+ if (var->bits_per_pixel <= 8)
+ var->bits_per_pixel = 8;
+ else if (var->bits_per_pixel <= 16)
+ var->bits_per_pixel = 16;
+ else
+ var->bits_per_pixel = 32;
+
+ switch (var->bits_per_pixel) {
+ case 8:
+ var->red.offset = 0;
+ var->red.length = 8;
+ var->green.offset = 0;
+ var->green.length = 8;
+ var->blue.offset = 0;
+ var->blue.length = 8;
+ var->transp.offset = 0;
+ var->transp.length = 0;
+ break;
+ case 16:
+ var->green.length = (var->green.length < 6) ? 5 : 6;
+ var->red.length = 5;
+ var->blue.length = 5;
+ var->transp.length = 6 - var->green.length;
+ var->blue.offset = 0;
+ var->green.offset = 5;
+ var->red.offset = 5 + var->green.length;
+ var->transp.offset = (5 + var->red.offset) & 15;
+ break;
+ case 32: /* RGBA 8888 */
+ var->red.offset = 16;
+ var->red.length = 8;
+ var->green.offset = 8;
+ var->green.length = 8;
+ var->blue.offset = 0;
+ var->blue.length = 8;
+ var->transp.length = 8;
+ var->transp.offset = 24;
+ break;
+ }
+
+ var->red.msb_right = 0;
+ var->green.msb_right = 0;
+ var->blue.msb_right = 0;
+ var->transp.msb_right = 0;
+
+ if (!info->monspecs.hfmax || !info->monspecs.vfmax ||
+ !info->monspecs.dclkmax || !fb_validate_mode(var, info))
+ mode_valid = 1;
+
+ /* calculate modeline if supported by monitor */
+ if (!mode_valid && info->monspecs.gtf) {
+ if (!fb_get_mode(FB_MAXTIMINGS, 0, var, info))
+ mode_valid = 1;
+ }
+
+ if (!mode_valid) {
+ struct fb_videomode *mode;
+
+ mode = fb_find_best_mode(var, &info->modelist);
+ if (mode) {
+ fb_videomode_to_var(var, mode);
+ mode_valid = 1;
+ }
+ }
+
+ if (!mode_valid && info->monspecs.modedb_len)
+ return -EINVAL;
+
+ if (par->fpWidth && par->fpHeight && (par->fpWidth < var->xres ||
+ par->fpHeight < var->yres))
+ return -EINVAL;
+
+ if (var->yres_virtual < var->yres)
+ var->yres_virtual = var->yres;
+
+ if (var->xres_virtual < var->xres)
+ var->xres_virtual = var->xres;
+
+ var->xres_virtual = (var->xres_virtual + 63) & ~63;
+
+ vramlen = info->fix.smem_len;
+ pitch = ((var->xres_virtual * var->bits_per_pixel) + 7) / 8;
+ memlen = pitch * var->yres_virtual;
+
+ if (memlen > vramlen) {
+ var->yres_virtual = vramlen / pitch;
+
+ if (var->yres_virtual < var->yres) {
+ var->yres_virtual = var->yres;
+ var->xres_virtual = vramlen / var->yres_virtual;
+ var->xres_virtual /= var->bits_per_pixel / 8;
+ var->xres_virtual &= ~63;
+ pitch = (var->xres_virtual *
+ var->bits_per_pixel + 7) / 8;
+ memlen = pitch * var->yres;
+
+ if (var->xres_virtual < var->xres) {
+ printk("nvidiafb: required video memory, "
+ "%d bytes, for %dx%d-%d (virtual) "
+ "is out of range\n",
+ memlen, var->xres_virtual,
+ var->yres_virtual, var->bits_per_pixel);
+ err = -ENOMEM;
+ }
+ }
+ }
+
+ if (var->accel_flags) {
+ if (var->yres_virtual > 0x7fff)
+ var->yres_virtual = 0x7fff;
+ if (var->xres_virtual > 0x7fff)
+ var->xres_virtual = 0x7fff;
+ }
+
+ var->xres_virtual &= ~63;
+
+ NVTRACE_LEAVE();
+
+ return err;
+}
+
+static int nvidiafb_pan_display(struct fb_var_screeninfo *var,
+ struct fb_info *info)
+{
+ struct nvidia_par *par = info->par;
+ u32 total;
+
+ total = info->var.yoffset * info->fix.line_length + info->var.xoffset;
+
+ NVSetStartAddress(par, total);
+
+ return 0;
+}
+
+static int nvidiafb_blank(int blank, struct fb_info *info)
+{
+ struct nvidia_par *par = info->par;
+ unsigned char tmp, vesa;
+
+ tmp = NVReadSeq(par, 0x01) & ~0x20; /* screen on/off */
+ vesa = NVReadCrtc(par, 0x1a) & ~0xc0; /* sync on/off */
+
+ NVTRACE_ENTER();
+
+ if (blank)
+ tmp |= 0x20;
+
+ switch (blank) {
+ case FB_BLANK_UNBLANK:
+ case FB_BLANK_NORMAL:
+ break;
+ case FB_BLANK_VSYNC_SUSPEND:
+ vesa |= 0x80;
+ break;
+ case FB_BLANK_HSYNC_SUSPEND:
+ vesa |= 0x40;
+ break;
+ case FB_BLANK_POWERDOWN:
+ vesa |= 0xc0;
+ break;
+ }
+
+ NVWriteSeq(par, 0x01, tmp);
+ NVWriteCrtc(par, 0x1a, vesa);
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+ if (par->FlatPanel && _machine == _MACH_Pmac) {
+ set_backlight_enable(!blank);
+ }
+#endif
+
+ NVTRACE_LEAVE();
+
+ return 0;
+}
+
+static struct fb_ops nvidia_fb_ops = {
+ .owner = THIS_MODULE,
+ .fb_check_var = nvidiafb_check_var,
+ .fb_set_par = nvidiafb_set_par,
+ .fb_setcolreg = nvidiafb_setcolreg,
+ .fb_pan_display = nvidiafb_pan_display,
+ .fb_blank = nvidiafb_blank,
+ .fb_fillrect = nvidiafb_fillrect,
+ .fb_copyarea = nvidiafb_copyarea,
+ .fb_imageblit = nvidiafb_imageblit,
+ .fb_cursor = nvidiafb_cursor,
+ .fb_sync = nvidiafb_sync,
+};
+
+static int __devinit nvidia_set_fbinfo(struct fb_info *info)
+{
+ struct fb_monspecs *specs = &info->monspecs;
+ struct fb_videomode modedb;
+ struct nvidia_par *par = info->par;
+ int lpitch;
+
+ NVTRACE_ENTER();
+ info->flags = FBINFO_DEFAULT
+ | FBINFO_HWACCEL_IMAGEBLIT
+ | FBINFO_HWACCEL_FILLRECT
+ | FBINFO_HWACCEL_COPYAREA
+ | FBINFO_HWACCEL_YPAN;
+
+ fb_videomode_to_modelist(info->monspecs.modedb,
+ info->monspecs.modedb_len, &info->modelist);
+ fb_var_to_videomode(&modedb, &nvidiafb_default_var);
+
+ if (specs->modedb != NULL) {
+ /* get preferred timing */
+ if (specs->misc & FB_MISC_1ST_DETAIL) {
+ int i;
+
+ for (i = 0; i < specs->modedb_len; i++) {
+ if (specs->modedb[i].flag & FB_MODE_IS_FIRST) {
+ modedb = specs->modedb[i];
+ break;
+ }
+ }
+ } else {
+ /* otherwise, get first mode in database */
+ modedb = specs->modedb[0];
+ }
+
+ fb_videomode_to_var(&nvidiafb_default_var, &modedb);
+ nvidiafb_default_var.bits_per_pixel = 8;
+ }
+
+ if (mode_option)
+ fb_find_mode(&nvidiafb_default_var, info, mode_option,
+ specs->modedb, specs->modedb_len, &modedb, 8);
+
+ info->var = nvidiafb_default_var;
+ info->fix.visual = (info->var.bits_per_pixel == 8) ?
+ FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
+ info->pseudo_palette = par->pseudo_palette;
+ fb_alloc_cmap(&info->cmap, 256, 0);
+ fb_destroy_modedb(info->monspecs.modedb);
+ info->monspecs.modedb = NULL;
+
+ /* maximize virtual vertical length */
+ lpitch = info->var.xres_virtual *
+ ((info->var.bits_per_pixel + 7) >> 3);
+ info->var.yres_virtual = info->fix.smem_len / lpitch;
+
+ info->pixmap.scan_align = 4;
+ info->pixmap.buf_align = 4;
+ info->pixmap.size = 8 * 1024;
+ info->pixmap.flags = FB_PIXMAP_SYSTEM;
+
+ if (!hwcur)
+ info->fbops->fb_cursor = soft_cursor;
+ info->var.accel_flags = (!noaccel);
+
+ switch (par->Architecture) {
+ case NV_ARCH_04:
+ info->fix.accel = FB_ACCEL_NV4;
+ break;
+ case NV_ARCH_10:
+ info->fix.accel = FB_ACCEL_NV_10;
+ break;
+ case NV_ARCH_20:
+ info->fix.accel = FB_ACCEL_NV_20;
+ break;
+ case NV_ARCH_30:
+ info->fix.accel = FB_ACCEL_NV_30;
+ break;
+ case NV_ARCH_40:
+ info->fix.accel = FB_ACCEL_NV_40;
+ break;
+ }
+
+ NVTRACE_LEAVE();
+
+ return nvidiafb_check_var(&info->var, info);
+}
+
+static u32 __devinit nvidia_get_arch(struct pci_dev *pd)
+{
+ u32 arch = 0;
+
+ switch (pd->device & 0x0ff0) {
+ case 0x0100: /* GeForce 256 */
+ case 0x0110: /* GeForce2 MX */
+ case 0x0150: /* GeForce2 */
+ case 0x0170: /* GeForce4 MX */
+ case 0x0180: /* GeForce4 MX (8x AGP) */
+ case 0x01A0: /* nForce */
+ case 0x01F0: /* nForce2 */
+ arch = NV_ARCH_10;
+ break;
+ case 0x0200: /* GeForce3 */
+ case 0x0250: /* GeForce4 Ti */
+ case 0x0280: /* GeForce4 Ti (8x AGP) */
+ arch = NV_ARCH_20;
+ break;
+ case 0x0300: /* GeForceFX 5800 */
+ case 0x0310: /* GeForceFX 5600 */
+ case 0x0320: /* GeForceFX 5200 */
+ case 0x0330: /* GeForceFX 5900 */
+ case 0x0340: /* GeForceFX 5700 */
+ arch = NV_ARCH_30;
+ break;
+ case 0x0040:
+ case 0x00C0:
+ case 0x0120:
+ case 0x0130:
+ case 0x0140:
+ case 0x0160:
+ case 0x01D0:
+ case 0x0090:
+ case 0x0210:
+ case 0x0220:
+ case 0x0230:
+ arch = NV_ARCH_40;
+ break;
+ case 0x0020: /* TNT, TNT2 */
+ arch = NV_ARCH_04;
+ break;
+ default: /* unknown architecture */
+ break;
+ }
+
+ return arch;
+}
+
+static int __devinit nvidiafb_probe(struct pci_dev *pd,
+ const struct pci_device_id *ent)
+{
+ struct nvidia_par *par;
+ struct fb_info *info;
+ unsigned short cmd;
+
+
+ NVTRACE_ENTER();
+ assert(pd != NULL);
+
+ info = framebuffer_alloc(sizeof(struct nvidia_par), &pd->dev);
+
+ if (!info)
+ goto err_out;
+
+ par = (struct nvidia_par *)info->par;
+ par->pci_dev = pd;
+
+ info->pixmap.addr = kmalloc(8 * 1024, GFP_KERNEL);
+
+ if (info->pixmap.addr == NULL)
+ goto err_out_kfree;
+
+ memset(info->pixmap.addr, 0, 8 * 1024);
+
+ if (pci_enable_device(pd)) {
+ printk(KERN_ERR PFX "cannot enable PCI device\n");
+ goto err_out_enable;
+ }
+
+ if (pci_request_regions(pd, "nvidiafb")) {
+ printk(KERN_ERR PFX "cannot request PCI regions\n");
+ 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);
+
+#ifdef CONFIG_PCI_NAMES
+ printk(KERN_INFO PFX "%s\n", pd->pretty_name);
+#endif
+
+ if (par->Architecture == 0) {
+ printk(KERN_ERR PFX "unknown NV_ARCH\n");
+ goto err_out_free_base0;
+ }
+
+ sprintf(nvidiafb_fix.id, "NV%x", (pd->device & 0x0ff0) >> 4);
+
+ par->FlatPanel = flatpanel;
+
+ if (flatpanel == 1)
+ printk(KERN_INFO PFX "flatpanel support enabled\n");
+
+ par->CRTCnumber = forceCRTC;
+ par->FpScale = (!noscale);
+ par->paneltweak = paneltweak;
+
+ /* enable IO and mem if not already done */
+ pci_read_config_word(pd, PCI_COMMAND, &cmd);
+ cmd |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
+ pci_write_config_word(pd, PCI_COMMAND, cmd);
+
+ nvidiafb_fix.mmio_start = pci_resource_start(pd, 0);
+ nvidiafb_fix.smem_start = pci_resource_start(pd, 1);
+ nvidiafb_fix.mmio_len = pci_resource_len(pd, 0);
+
+ par->REGS = ioremap(nvidiafb_fix.mmio_start, nvidiafb_fix.mmio_len);
+
+ if (!par->REGS) {
+ printk(KERN_ERR PFX "cannot ioremap MMIO base\n");
+ goto err_out_free_base0;
+ }
+
+ NVCommonSetup(info);
+
+ par->FbAddress = nvidiafb_fix.smem_start;
+ par->FbMapSize = par->RamAmountKBytes * 1024;
+ par->FbUsableSize = par->FbMapSize - (128 * 1024);
+ par->ScratchBufferSize = (par->Architecture < NV_ARCH_10) ? 8 * 1024 :
+ 16 * 1024;
+ par->ScratchBufferStart = par->FbUsableSize - par->ScratchBufferSize;
+ info->screen_base = ioremap(nvidiafb_fix.smem_start, par->FbMapSize);
+ nvidiafb_fix.smem_len = par->FbUsableSize;
+
+ if (!info->screen_base) {
+ printk(KERN_ERR PFX "cannot ioremap FB base\n");
+ goto err_out_free_base1;
+ }
+
+ par->FbStart = info->screen_base;
+
+#ifdef CONFIG_MTRR
+ if (!nomtrr) {
+ par->mtrr.vram = mtrr_add(nvidiafb_fix.smem_start,
+ par->FbMapSize, MTRR_TYPE_WRCOMB, 1);
+ if (par->mtrr.vram < 0) {
+ printk(KERN_ERR PFX "unable to setup MTRR\n");
+ } else {
+ par->mtrr.vram_valid = 1;
+ /* let there be speed */
+ printk(KERN_INFO PFX "MTRR set to ON\n");
+ }
+ }
+#endif /* CONFIG_MTRR */
+
+ info->fbops = &nvidia_fb_ops;
+ info->fix = nvidiafb_fix;
+
+ if (nvidia_set_fbinfo(info) < 0) {
+ printk(KERN_ERR PFX "error setting initial video mode\n");
+ goto err_out_iounmap_fb;
+ }
+
+ nvidia_save_vga(par, &par->SavedReg);
+
+ if (register_framebuffer(info) < 0) {
+ printk(KERN_ERR PFX "error registering nVidia framebuffer\n");
+ goto err_out_iounmap_fb;
+ }
+
+ pci_set_drvdata(pd, info);
+
+ printk(KERN_INFO PFX
+ "PCI nVidia %s framebuffer (%dMB @ 0x%lX)\n",
+ info->fix.id,
+ par->FbMapSize / (1024 * 1024), info->fix.smem_start);
+#ifdef CONFIG_PMAC_BACKLIGHT
+ if (par->FlatPanel && _machine == _MACH_Pmac)
+ register_backlight_controller(&nvidia_backlight_controller,
+ par, "mnca");
+#endif
+ NVTRACE_LEAVE();
+ return 0;
+
+ err_out_iounmap_fb:
+ iounmap(info->screen_base);
+ fb_destroy_modedb(info->monspecs.modedb);
+ nvidia_delete_i2c_busses(par);
+ err_out_free_base1:
+ iounmap(par->REGS);
+ err_out_free_base0:
+ pci_release_regions(pd);
+ err_out_request:
+ pci_disable_device(pd);
+ err_out_enable:
+ kfree(info->pixmap.addr);
+ err_out_kfree:
+ framebuffer_release(info);
+ err_out:
+ return -ENODEV;
+}
+
+static void __exit nvidiafb_remove(struct pci_dev *pd)
+{
+ struct fb_info *info = pci_get_drvdata(pd);
+ struct nvidia_par *par = info->par;
+
+ NVTRACE_ENTER();
+ if (!info)
+ return;
+
+ unregister_framebuffer(info);
+#ifdef CONFIG_MTRR
+ if (par->mtrr.vram_valid)
+ mtrr_del(par->mtrr.vram, info->fix.smem_start,
+ info->fix.smem_len);
+#endif /* CONFIG_MTRR */
+
+ iounmap(info->screen_base);
+ fb_destroy_modedb(info->monspecs.modedb);
+ nvidia_delete_i2c_busses(par);
+ iounmap(par->REGS);
+ pci_release_regions(pd);
+ pci_disable_device(pd);
+ kfree(info->pixmap.addr);
+ framebuffer_release(info);
+ pci_set_drvdata(pd, NULL);
+ NVTRACE_LEAVE();
+}
+
+/* ------------------------------------------------------------------------- *
+ *
+ * initialization
+ *
+ * ------------------------------------------------------------------------- */
+
+#ifndef MODULE
+static int __devinit nvidiafb_setup(char *options)
+{
+ char *this_opt;
+
+ NVTRACE_ENTER();
+ if (!options || !*options)
+ return 0;
+
+ while ((this_opt = strsep(&options, ",")) != NULL) {
+ if (!strncmp(this_opt, "forceCRTC", 9)) {
+ char *p;
+
+ p = this_opt + 9;
+ if (!*p || !*(++p))
+ continue;
+ forceCRTC = *p - '0';
+ if (forceCRTC < 0 || forceCRTC > 1)
+ forceCRTC = -1;
+ } else if (!strncmp(this_opt, "flatpanel", 9)) {
+ flatpanel = 1;
+ } else if (!strncmp(this_opt, "hwcur", 5)) {
+ hwcur = 1;
+ } else if (!strncmp(this_opt, "noaccel", 6)) {
+ noaccel = 1;
+ } else if (!strncmp(this_opt, "noscale", 7)) {
+ noscale = 1;
+ } else if (!strncmp(this_opt, "paneltweak:", 11)) {
+ paneltweak = simple_strtoul(this_opt+11, NULL, 0);
+#ifdef CONFIG_MTRR
+ } else if (!strncmp(this_opt, "nomtrr", 6)) {
+ nomtrr = 1;
+#endif
+ } else
+ mode_option = this_opt;
+ }
+ NVTRACE_LEAVE();
+ return 0;
+}
+#endif /* !MODULE */
+
+static struct pci_driver nvidiafb_driver = {
+ .name = "nvidiafb",
+ .id_table = nvidiafb_pci_tbl,
+ .probe = nvidiafb_probe,
+ .remove = __exit_p(nvidiafb_remove),
+};
+
+/* ------------------------------------------------------------------------- *
+ *
+ * modularization
+ *
+ * ------------------------------------------------------------------------- */
+
+static int __devinit nvidiafb_init(void)
+{
+#ifndef MODULE
+ char *option = NULL;
+
+ if (fb_get_options("nvidiafb", &option))
+ return -ENODEV;
+ nvidiafb_setup(option);
+#endif
+ return pci_register_driver(&nvidiafb_driver);
+}
+
+module_init(nvidiafb_init);
+
+#ifdef MODULE
+static void __exit nvidiafb_exit(void)
+{
+ pci_unregister_driver(&nvidiafb_driver);
+}
+
+module_exit(nvidiafb_exit);
+
+module_param(flatpanel, int, 0);
+MODULE_PARM_DESC(flatpanel,
+ "Enables experimental flat panel support for some chipsets. "
+ "(0 or 1=enabled) (default=0)");
+module_param(hwcur, int, 0);
+MODULE_PARM_DESC(hwcur,
+ "Enables hardware cursor implementation. (0 or 1=enabled) "
+ "(default=0)");
+module_param(noaccel, int, 0);
+MODULE_PARM_DESC(noaccel,
+ "Disables hardware acceleration. (0 or 1=disable) "
+ "(default=0)");
+module_param(noscale, int, 0);
+MODULE_PARM_DESC(noscale,
+ "Disables screen scaleing. (0 or 1=disable) "
+ "(default=0, do scaling)");
+module_param(paneltweak, int, 0);
+MODULE_PARM_DESC(paneltweak,
+ "Tweak display settings for flatpanels. "
+ "(default=0, no tweaks)");
+module_param(forceCRTC, int, 0);
+MODULE_PARM_DESC(forceCRTC,
+ "Forces usage of a particular CRTC in case autodetection "
+ "fails. (0 or 1) (default=autodetect)");
+#ifdef CONFIG_MTRR
+module_param(nomtrr, bool, 0);
+MODULE_PARM_DESC(nomtrr, "Disables MTRR support (0 or 1=disabled) "
+ "(default=0)");
+#endif
+
+MODULE_AUTHOR("Antonino Daplas");
+MODULE_DESCRIPTION("Framebuffer driver for nVidia graphics chipset");
+MODULE_LICENSE("GPL");
+#endif /* MODULE */
+
diff --git a/drivers/video/offb.c b/drivers/video/offb.c
index f5a776364c72b..42a6591e863f8 100644
--- a/drivers/video/offb.c
+++ b/drivers/video/offb.c
@@ -29,6 +29,10 @@
#include <asm/io.h>
#include <asm/prom.h>
+#ifdef CONFIG_PPC64
+#include <asm/pci-bridge.h>
+#endif
+
#ifdef CONFIG_PPC32
#include <asm/bootx.h>
#endif
@@ -322,7 +326,8 @@ 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 *up, address;
+ unsigned *up;
+ unsigned long address;
if ((pp = (int *) get_property(dp, "depth", &len)) != NULL
&& len == sizeof(int))
@@ -357,6 +362,10 @@ static void __init offb_init_nodriver(struct device_node *dp)
address = (u_long) dp->addrs[i].address;
+#ifdef CONFIG_PPC64
+ address += dp->phb->pci_mem_offset;
+#endif
+
/* kludge for valkyrie */
if (strcmp(dp->name, "valkyrie") == 0)
address += 0x1000;
diff --git a/drivers/video/pm2fb.c b/drivers/video/pm2fb.c
index 144ac3e28d73f..5dceddedf5075 100644
--- a/drivers/video/pm2fb.c
+++ b/drivers/video/pm2fb.c
@@ -62,7 +62,7 @@
/*
* Driver data
*/
-static char *mode __initdata = NULL;
+static char *mode __devinitdata = NULL;
/*
* The XFree GLINT driver will (I think to implement hardware cursor
@@ -73,8 +73,8 @@ static char *mode __initdata = NULL;
* these flags allow the user to specify that requests for +ve sync
* should be silently turned in -ve sync.
*/
-static int lowhsync __initdata = 0;
-static int lowvsync __initdata = 0;
+static int lowhsync __devinitdata = 0;
+static int lowvsync __devinitdata = 0;
/*
* The hardware state of the graphics card that isn't part of the
@@ -97,7 +97,7 @@ struct pm2fb_par
* Here we define the default structs fb_fix_screeninfo and fb_var_screeninfo
* if we don't use modedb.
*/
-static struct fb_fix_screeninfo pm2fb_fix __initdata = {
+static struct fb_fix_screeninfo pm2fb_fix __devinitdata = {
.id = "",
.type = FB_TYPE_PACKED_PIXELS,
.visual = FB_VISUAL_PSEUDOCOLOR,
@@ -110,7 +110,7 @@ static struct fb_fix_screeninfo pm2fb_fix __initdata = {
/*
* Default video mode. In case the modedb doesn't work.
*/
-static struct fb_var_screeninfo pm2fb_var __initdata = {
+static struct fb_var_screeninfo pm2fb_var __devinitdata = {
/* "640x480, 8 bpp @ 60 Hz */
.xres = 640,
.yres = 480,
@@ -747,7 +747,7 @@ static int pm2fb_set_par(struct fb_info *info)
}
if ((info->var.vmode & FB_VMODE_MASK)==FB_VMODE_DOUBLE)
video |= PM2F_LINE_DOUBLE;
- if (info->var.activate==FB_ACTIVATE_NOW)
+ if ((info->var.activate & FB_ACTIVATE_MASK)==FB_ACTIVATE_NOW)
video |= PM2F_VIDEO_ENABLE;
par->video = video;
@@ -1243,47 +1243,13 @@ static struct pci_driver pm2fb_driver = {
MODULE_DEVICE_TABLE(pci, pm2fb_id_table);
-/*
- * Initialization
- */
-
-int __init pm2fb_setup(char *options);
-
-int __init pm2fb_init(void)
-{
-#ifndef MODULE
- char *option = NULL;
-
- if (fb_get_options("pm2fb", &option))
- return -ENODEV;
- pm2fb_setup(option);
-#endif
-
- return pci_module_init(&pm2fb_driver);
-}
-
-#ifdef MODULE
-/*
- * Cleanup
- */
-
-static void __exit pm2fb_exit(void)
-{
- pci_unregister_driver(&pm2fb_driver);
-}
-#endif
-
-/*
- * Setup
- */
-
#ifndef MODULE
/**
* Parse user speficied options.
*
* This is, comma-separated options following `video=pm2fb:'.
*/
-int __init pm2fb_setup(char *options)
+static int __init pm2fb_setup(char *options)
{
char* this_opt;
@@ -1306,15 +1272,33 @@ int __init pm2fb_setup(char *options)
#endif
-/* ------------------------------------------------------------------------- */
-
-/* ------------------------------------------------------------------------- */
+static int __init pm2fb_init(void)
+{
+#ifndef MODULE
+ char *option = NULL;
+ if (fb_get_options("pm2fb", &option))
+ return -ENODEV;
+ pm2fb_setup(option);
+#endif
+ return pci_register_driver(&pm2fb_driver);
+}
module_init(pm2fb_init);
#ifdef MODULE
+/*
+ * Cleanup
+ */
+
+static void __exit pm2fb_exit(void)
+{
+ pci_unregister_driver(&pm2fb_driver);
+}
+#endif
+
+#ifdef MODULE
module_exit(pm2fb_exit);
module_param(mode, charp, 0);
diff --git a/drivers/video/pm3fb.c b/drivers/video/pm3fb.c
index c8b16d86c3cfb..8e024aad1b573 100644
--- a/drivers/video/pm3fb.c
+++ b/drivers/video/pm3fb.c
@@ -137,9 +137,6 @@ struct pm3fb_info {
unsigned long use_current;
struct pm3fb_par *current_par;
struct pci_dev *dev; /* PCI device */
-#ifdef SUPPORT_FB_OF
- struct device_node *dn; /* OF node for the PCI device */
-#endif /* SUPPORT_FB_OF */
unsigned long board_type; /* index in the cardbase */
unsigned char *fb_base; /* framebuffer memory base */
u32 fb_size; /* framebuffer memory size */
@@ -665,20 +662,6 @@ static int pm3fb_ioctl(struct inode *inode, struct file *file,
/* the struct that hold them together */
-#ifdef KERNEL_2_2
-struct fbgen_hwswitch pm3fb_switch = {
- pm3fb_detect, pm3fb_encode_fix, pm3fb_decode_var, pm3fb_encode_var,
- pm3fb_get_par, pm3fb_set_par, pm3fb_getcolreg, pm3fb_setcolreg,
- pm3fb_pan_display, pm3fb_blank, pm3fb_set_disp
-};
-
-static struct fb_ops pm3fb_ops = {
- fbgen_get_fix, fbgen_get_var, fbgen_set_var,
- fbgen_get_cmap, fbgen_set_cmap, fbgen_pan_display, pm3fb_ioctl,
- NULL, NULL
-};
-#endif /* KERNEL_2_2 */
-#if (defined KERNEL_2_4) || (defined KERNEL_2_5)
struct fbgen_hwswitch pm3fb_switch = {
pm3fb_detect, pm3fb_encode_fix, pm3fb_decode_var, pm3fb_encode_var,
pm3fb_get_par, pm3fb_set_par, pm3fb_getcolreg,
@@ -697,7 +680,7 @@ static struct fb_ops pm3fb_ops = {
.fb_blank = fbgen_blank,
.fb_ioctl = pm3fb_ioctl,
};
-#endif /* KERNEL_2_4 or KERNEL_2_5 */
+
#ifdef PM3FB_USE_ACCEL
#ifdef FBCON_HAS_CFB32
static struct display_switch pm3fb_cfb32 = {
@@ -1451,26 +1434,11 @@ static unsigned long pm3fb_size_memory(struct pm3fb_info *l_fb_info)
/* pm3 split up memory, replicates, and do a lot of nasty stuff IMHO ;-) */
for (i = 0; i < 32; i++) {
-#ifdef KERNEL_2_2
-#ifdef MUST_BYTESWAP
- writel(__swab32(i * 0x00345678),
- (l_fb_info->v_fb + (i * 1048576)));
-#else
- writel(i * 0x00345678, (l_fb_info->v_fb + (i * 1048576)));
-#endif
- mb();
-#ifdef MUST_BYTESWAP
- temp1 = __swab32(readl((l_fb_info->v_fb + (i * 1048576))));
-#else
- temp1 = readl((l_fb_info->v_fb + (i * 1048576)));
-#endif
-#endif /* KERNEL_2_2 */
-#if (defined KERNEL_2_4) || (defined KERNEL_2_5)
fb_writel(i * 0x00345678,
(l_fb_info->v_fb + (i * 1048576)));
mb();
temp1 = fb_readl((l_fb_info->v_fb + (i * 1048576)));
-#endif /* KERNEL_2_4 or KERNEL_2_5 */
+
/* Let's check for wrapover, write will fail at 16MB boundary */
if (temp1 == (i * 0x00345678))
memsize = i;
@@ -1489,31 +1457,6 @@ static unsigned long pm3fb_size_memory(struct pm3fb_info *l_fb_info)
}
for (i = 32; i < 64; i++) {
-#ifdef KERNEL_2_2
-#ifdef MUST_BYTESWAP
- writel(__swab32(i * 0x00345678),
- (l_fb_info->v_fb + (i * 1048576)));
-#else
- writel(i * 0x00345678,
- (l_fb_info->v_fb + (i * 1048576)));
-#endif
- mb();
-#ifdef MUST_BYTESWAP
- temp1 =
- __swab32(readl
- ((l_fb_info->v_fb + (i * 1048576))));
- temp2 =
- __swab32(readl
- ((l_fb_info->v_fb +
- ((i - 32) * 1048576))));
-#else
- temp1 = readl((l_fb_info->v_fb + (i * 1048576)));
- temp2 =
- readl((l_fb_info->v_fb +
- ((i - 32) * 1048576)));
-#endif
-#endif /* KERNEL_2_2 */
-#if (defined KERNEL_2_4) || (defined KERNEL_2_5)
fb_writel(i * 0x00345678,
(l_fb_info->v_fb + (i * 1048576)));
mb();
@@ -1522,7 +1465,6 @@ static unsigned long pm3fb_size_memory(struct pm3fb_info *l_fb_info)
temp2 =
fb_readl((l_fb_info->v_fb +
((i - 32) * 1048576)));
-#endif /* KERNEL_2_4 or KERNEL_2_5 */
if ((temp1 == (i * 0x00345678)) && (temp2 == 0)) /* different value, different RAM... */
memsize = i;
else
@@ -1565,16 +1507,7 @@ static void pm3fb_clear_memory(struct pm3fb_info *l_fb_info, u32 cc)
for (i = 0; i < (l_fb_info->fb_size / sizeof(u32)) ; i++) /* clear entire FB memory to black */
{
-#ifdef KERNEL_2_2
-#ifdef MUST_BYTESWAP
- writel(__swab32(cc), (l_fb_info->v_fb + (i * sizeof(u32))));
-#else
- writel(cc, (l_fb_info->v_fb + (i * sizeof(u32))));
-#endif
-#endif
-#if (defined KERNEL_2_4) || (defined KERNEL_2_5)
fb_writel(cc, (l_fb_info->v_fb + (i * sizeof(u32))));
-#endif
}
}
@@ -3424,89 +3357,63 @@ static void pm3fb_detect(void)
for (i = 0; i < PM3_MAX_BOARD; i++) {
l_fb_info = &(fb_info[i]);
if ((l_fb_info->dev) && (!disable[i])) { /* PCI device was found and not disabled by user */
-#ifdef SUPPORT_FB_OF
- struct device_node *dp =
- find_pci_device_OFnode(l_fb_info->dev->bus->
- number,
- l_fb_info->dev->devfn);
-
- if ((dp) && (!strncmp(dp->name, "formacGA12", 10))) {
- /* do nothing, init of board is done in pm3fb_of_init */
- } else {
-#endif
- DPRINTK(2,
- "found @%lx Vendor %lx Device %lx ; base @ : %lx - %lx - %lx - %lx - %lx - %lx, irq %ld\n",
- (unsigned long) l_fb_info->dev,
- (unsigned long) l_fb_info->dev->
- vendor,
- (unsigned long) l_fb_info->dev->
- device,
- (unsigned long)
- pci_resource_start(l_fb_info->dev,
- 0),
- (unsigned long)
- pci_resource_start(l_fb_info->dev,
- 1),
- (unsigned long)
- pci_resource_start(l_fb_info->dev,
- 2),
- (unsigned long)
- pci_resource_start(l_fb_info->dev,
- 3),
- (unsigned long)
- pci_resource_start(l_fb_info->dev,
- 4),
- (unsigned long)
- pci_resource_start(l_fb_info->dev,
- 5),
- (unsigned long) l_fb_info->dev->
- irq);
-
- l_fb_info->pIOBase =
- (unsigned char *)
- pci_resource_start(l_fb_info->dev, 0);
+ DPRINTK(2,
+ "found @%lx Vendor %lx Device %lx ; base @ : %lx - %lx - %lx - %lx - %lx - %lx, irq %ld\n",
+ (unsigned long) l_fb_info->dev,
+ (unsigned long) l_fb_info->dev->vendor,
+ (unsigned long) l_fb_info->dev->device,
+ (unsigned long)
+ pci_resource_start(l_fb_info->dev, 0),
+ (unsigned long)
+ pci_resource_start(l_fb_info->dev, 1),
+ (unsigned long)
+ pci_resource_start(l_fb_info->dev, 2),
+ (unsigned long)
+ pci_resource_start(l_fb_info->dev, 3),
+ (unsigned long)
+ pci_resource_start(l_fb_info->dev, 4),
+ (unsigned long)
+ pci_resource_start(l_fb_info->dev, 5),
+ (unsigned long) l_fb_info->dev->irq);
+
+ l_fb_info->pIOBase =
+ (unsigned char *)
+ pci_resource_start(l_fb_info->dev, 0);
#ifdef __BIG_ENDIAN
- l_fb_info->pIOBase += PM3_REGS_SIZE;
+ l_fb_info->pIOBase += PM3_REGS_SIZE;
#endif
- l_fb_info->vIOBase = (unsigned char *) -1;
- l_fb_info->p_fb =
- (unsigned char *)
- pci_resource_start(l_fb_info->dev, 1);
- l_fb_info->v_fb = (unsigned char *) -1;
+ l_fb_info->vIOBase = (unsigned char *) -1;
+ l_fb_info->p_fb =
+ (unsigned char *)
+ pci_resource_start(l_fb_info->dev, 1);
+ l_fb_info->v_fb = (unsigned char *) -1;
-#if (defined KERNEL_2_4) || (defined KERNEL_2_5) /* full resource management, new in linux-2.4.x */
if (!request_mem_region
- ((unsigned long)l_fb_info->p_fb, 64 * 1024 * 1024, /* request full aperture size */
- "pm3fb")) {
- printk
- (KERN_ERR "pm3fb: Error: couldn't request framebuffer memory, board #%ld\n",
- l_fb_info->board_num);
- continue;
- }
- if (!request_mem_region
- ((unsigned long)l_fb_info->pIOBase, PM3_REGS_SIZE,
- "pm3fb I/O regs")) {
- printk
- (KERN_ERR "pm3fb: Error: couldn't request IObase memory, board #%ld\n",
- l_fb_info->board_num);
- continue;
- }
-#endif /* KERNEL_2_4 or KERNEL_2_5 */
- if (forcesize[l_fb_info->board_num])
- l_fb_info->fb_size = forcesize[l_fb_info->board_num];
-
- l_fb_info->fb_size =
- pm3fb_size_memory(l_fb_info);
+ ((unsigned long)l_fb_info->p_fb, 64 * 1024 * 1024, /* request full aperture size */
+ "pm3fb")) {
+ printk
+ (KERN_ERR "pm3fb: Error: couldn't request framebuffer memory, board #%ld\n",
+ l_fb_info->board_num);
+ continue;
+ }
+ if (!request_mem_region
+ ((unsigned long)l_fb_info->pIOBase, PM3_REGS_SIZE,
+ "pm3fb I/O regs")) {
+ printk
+ (KERN_ERR "pm3fb: Error: couldn't request IObase memory, board #%ld\n",
+ l_fb_info->board_num);
+ continue;
+ }
+ if (forcesize[l_fb_info->board_num])
+ l_fb_info->fb_size = forcesize[l_fb_info->board_num];
+ l_fb_info->fb_size =
+ pm3fb_size_memory(l_fb_info);
if (l_fb_info->fb_size) {
- (void) pci_enable_device(l_fb_info->dev);
- pm3fb_common_init(l_fb_info);
- } else
- printk(KERN_ERR "pm3fb: memory problem, not enabling board #%ld\n", l_fb_info->board_num);
-
-#ifdef SUPPORT_FB_OF
- }
-#endif /* SUPPORT_FB_OF */
+ (void) pci_enable_device(l_fb_info->dev);
+ pm3fb_common_init(l_fb_info);
+ } else
+ printk(KERN_ERR "pm3fb: memory problem, not enabling board #%ld\n", l_fb_info->board_num);
}
}
}
@@ -3590,12 +3497,7 @@ static int pm3fb_ioctl(struct inode *inode, struct file *file,
/* ***** standard FB API init functions ***** */
/* ****************************************** */
-#if (defined KERNEL_2_4) || (defined KERNEL_2_5)
int __init pm3fb_setup(char *options)
-#endif
-#ifdef KERNEL_2_2
-__initfunc(void pm3fb_setup(char *options, int *ints))
-#endif
{
long opsi = strlen(options);
@@ -3606,17 +3508,10 @@ __initfunc(void pm3fb_setup(char *options, int *ints))
PM3_OPTIONS_SIZE) ? PM3_OPTIONS_SIZE : (opsi + 1));
g_options[PM3_OPTIONS_SIZE - 1] = 0;
-#if (defined KERNEL_2_4) || (defined KERNEL_2_5)
return (0);
-#endif
}
-#if (defined KERNEL_2_4) || (defined KERNEL_2_5)
int __init pm3fb_init(void)
-#endif
-#ifdef KERNEL_2_2
-__initfunc(void pm3fb_init(void))
-#endif
{
DTRACE;
@@ -3629,82 +3524,8 @@ __initfunc(void pm3fb_init(void))
if (!fb_info[0].dev) { /* not even one board ??? */
DPRINTK(1, "No PCI Permedia3 board detected\n");
}
-#if (defined KERNEL_2_4) || (defined KERNEL_2_5)
return (0);
-#endif
-}
-
-#ifdef SUPPORT_FB_OF /* linux-2.2.x only */
-__initfunc(void pm3fb_of_init(struct device_node *dp))
-{
- struct pm3fb_info *l_fb_info = NULL;
- unsigned long i;
- long bn = -1;
- struct device_node *dn;
-
- DTRACE;
-
- DPRINTK(2, "OpenFirmware board : %s\n", dp->full_name);
-
- for (i = 0; i < dp->n_addrs; i++) {
- DPRINTK(2, "MemRange : 0x%08x - 0x%x\n",
- dp->addrs[i].address, dp->addrs[i].size);
- }
-
- for (i = 0; i < PM3_MAX_BOARD; i++) { /* find which PCI board is the OF device */
- if (fb_info[i].dev) {
- dn = find_pci_device_OFnode(fb_info[i].dev->bus->
- number,
- fb_info[i].dev->devfn);
- if (dn == dp) {
- if (bn == -1)
- bn = i;
- else {
- DPRINTK(1,
- "Error: Multiple PCI device for a single OpenFirmware node\n");
- }
- }
- }
- }
-
- if (bn == -1) {
- DPRINTK(1, "Warning: non-PCI Permedia3 found\n");
- i = 0;
- while (fb_info[i].dev && (i < PM3_MAX_BOARD))
- i++;
- if (i < PM3_MAX_BOARD)
- bn = i;
- else {
- printk
- (KERN_ERR "pm3fb: Error: Couldn't find room for OpenFirmware device");
- return;
- }
- }
-
- l_fb_info = &(fb_info[bn]);
-
- l_fb_info->dn = dp;
-
- l_fb_info->pIOBase = (unsigned char *) dp->addrs[3].address;
-#ifdef __BIG_ENDIAN
- l_fb_info->pIOBase += PM3_REGS_SIZE;
-#endif
- l_fb_info->vIOBase = (unsigned char *) -1;
- l_fb_info->p_fb = (unsigned char *) dp->addrs[1].address;
- l_fb_info->v_fb = (unsigned char *) -1;
-
- l_fb_info->fb_size = pm3fb_size_memory(l_fb_info); /* (unsigned long)dp->addrs[1].size; *//* OF is a liar ! it claims 256 Mb */
-
- DPRINTK(2,
- "OpenFirmware board (#%ld) : IOBase 0x%08lx, p_fb 0x%08lx, fb_size %d KB\n",
- bn, (unsigned long) l_fb_info->pIOBase,
- (unsigned long) l_fb_info->p_fb, l_fb_info->fb_size >> 10);
-
- l_fb_info->use_current = 1; /* will use current mode by default */
-
- pm3fb_common_init(l_fb_info);
}
-#endif /* SUPPORT_FB_OF */
/* ************************* */
/* **** Module support ***** */
@@ -3808,14 +3629,12 @@ void cleanup_module(void)
if (l_fb_info->vIOBase !=
(unsigned char *) -1) {
pm3fb_unmapIO(l_fb_info);
-#if (defined KERNEL_2_4) || (defined KERNEL_2_5)
release_mem_region(l_fb_info->p_fb,
l_fb_info->
fb_size);
release_mem_region(l_fb_info->
pIOBase,
PM3_REGS_SIZE);
-#endif /* KERNEL_2_4 or KERNEL_2_5 */
}
unregister_framebuffer(&l_fb_info->gen.
info);
diff --git a/drivers/video/pvr2fb.c b/drivers/video/pvr2fb.c
index f4b20704db6ca..31c547fd383bf 100644
--- a/drivers/video/pvr2fb.c
+++ b/drivers/video/pvr2fb.c
@@ -4,7 +4,7 @@
* Dreamcast.
*
* Copyright (c) 2001 M. R. Brown <mrbrown@0xd6.org>
- * Copyright (c) 2001, 2002, 2003, 2004 Paul Mundt <lethal@linux-sh.org>
+ * Copyright (c) 2001, 2002, 2003, 2004, 2005 Paul Mundt <lethal@linux-sh.org>
*
* This file is part of the LinuxDC project (linuxdc.sourceforge.net).
*
@@ -33,7 +33,7 @@
* Then, when it's time to convert back to hardware settings, the only
* constants are the borderstart_* offsets, all other values are derived from
* the fb video mode:
- *
+ *
* // PAL
* borderstart_h = 116;
* borderstart_v = 44;
@@ -939,7 +939,8 @@ static int __devinit pvr2fb_pci_probe(struct pci_dev *pdev,
pvr2_fix.mmio_start = pci_resource_start(pdev, 1);
pvr2_fix.mmio_len = pci_resource_len(pdev, 1);
- fbinfo->device = &pdev->dev;
+
+ fb_info->device = &pdev->dev;
return pvr2fb_common_init();
}
@@ -966,7 +967,7 @@ static struct pci_driver pvr2fb_pci_driver = {
static int __init pvr2fb_pci_init(void)
{
- return pci_module_init(&pvr2fb_pci_driver);
+ return pci_register_driver(&pvr2fb_pci_driver);
}
static void pvr2fb_pci_exit(void)
@@ -1068,7 +1069,6 @@ int __init pvr2fb_init(void)
size = sizeof(struct fb_info) + sizeof(struct pvr2fb_par) + 16 * sizeof(u32);
fb_info = kmalloc(size, GFP_KERNEL);
-
if (!fb_info) {
printk(KERN_ERR "Failed to allocate memory for fb_info\n");
return -ENOMEM;
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c
index 552a38e5f143f..483ad9bab5390 100644
--- a/drivers/video/pxafb.c
+++ b/drivers/video/pxafb.c
@@ -1343,8 +1343,7 @@ int __init pxafb_probe(struct device *dev)
failed:
dev_set_drvdata(dev, NULL);
- if (fbi)
- kfree(fbi);
+ kfree(fbi);
return ret;
}
diff --git a/drivers/video/radeonfb.c b/drivers/video/radeonfb.c
index 9a2e3adea0fd5..d9a084e77a632 100644
--- a/drivers/video/radeonfb.c
+++ b/drivers/video/radeonfb.c
@@ -657,14 +657,17 @@ static __inline__ int _max(int val1, int val2)
/*
* globals
*/
-
-static char *mode_option __initdata;
+
+#ifndef MODULE
+static char *mode_option;
+#endif
+
static char noaccel = 0;
static char mirror = 0;
-static int panel_yres __initdata = 0;
-static char force_dfp __initdata = 0;
+static int panel_yres = 0;
+static char force_dfp = 0;
static struct radeonfb_info *board_list = NULL;
-static char nomtrr __initdata = 0;
+static char nomtrr = 0;
/*
* prototypes
@@ -3109,28 +3112,8 @@ static struct pci_driver radeonfb_driver = {
.remove = __devexit_p(radeonfb_pci_unregister),
};
-int __init radeonfb_old_setup (char *options);
-
-int __init radeonfb_old_init (void)
-{
#ifndef MODULE
- char *option = NULL;
-
- if (fb_get_options("radeonfb_old", &option))
- return -ENODEV;
- radeonfb_old_setup(option);
-#endif
- return pci_module_init (&radeonfb_driver);
-}
-
-
-void __exit radeonfb_old_exit (void)
-{
- pci_unregister_driver (&radeonfb_driver);
-}
-
-
-int __init radeonfb_old_setup (char *options)
+static int __init radeonfb_old_setup (char *options)
{
char *this_opt;
@@ -3156,12 +3139,28 @@ int __init radeonfb_old_setup (char *options)
return 0;
}
+#endif /* MODULE */
-module_init(radeonfb_old_init);
+static int __init radeonfb_old_init (void)
+{
+#ifndef MODULE
+ char *option = NULL;
-#ifdef MODULE
-module_exit(radeonfb_old_exit);
+ if (fb_get_options("radeonfb_old", &option))
+ return -ENODEV;
+ radeonfb_old_setup(option);
#endif
+ return pci_register_driver (&radeonfb_driver);
+}
+
+
+static void __exit radeonfb_old_exit (void)
+{
+ pci_unregister_driver (&radeonfb_driver);
+}
+
+module_init(radeonfb_old_init);
+module_exit(radeonfb_old_exit);
MODULE_AUTHOR("Ani Joshi");
diff --git a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c
index 04706b6d7a85b..b0c886de04043 100644
--- a/drivers/video/riva/fbdev.c
+++ b/drivers/video/riva/fbdev.c
@@ -208,23 +208,23 @@ MODULE_DEVICE_TABLE(pci, rivafb_pci_tbl);
* ------------------------------------------------------------------------- */
/* command line data, set in rivafb_setup() */
-static int flatpanel __initdata = -1; /* Autodetect later */
-static int forceCRTC __initdata = -1;
-static int noaccel __initdata = 0;
+static int flatpanel __devinitdata = -1; /* Autodetect later */
+static int forceCRTC __devinitdata = -1;
+static int noaccel __devinitdata = 0;
#ifdef CONFIG_MTRR
-static int nomtrr __initdata = 0;
+static int nomtrr __devinitdata = 0;
#endif
-static char *mode_option __initdata = NULL;
+static char *mode_option __devinitdata = NULL;
static int strictmode = 0;
-static struct fb_fix_screeninfo __initdata rivafb_fix = {
+static struct fb_fix_screeninfo __devinitdata rivafb_fix = {
.type = FB_TYPE_PACKED_PIXELS,
.xpanstep = 1,
.ypanstep = 1,
};
-static struct fb_var_screeninfo __initdata rivafb_default_var = {
+static struct fb_var_screeninfo __devinitdata rivafb_default_var = {
.xres = 640,
.yres = 480,
.xres_virtual = 640,
@@ -906,7 +906,7 @@ riva_set_pattern(struct riva_par *par, int clr0, int clr1, int pat0, int pat1)
}
/* acceleration routines */
-inline void wait_for_idle(struct riva_par *par)
+static inline void wait_for_idle(struct riva_par *par)
{
while (par->riva.Busy(&par->riva));
}
@@ -923,7 +923,7 @@ riva_set_rop_solid(struct riva_par *par, int rop)
}
-void riva_setup_accel(struct fb_info *info)
+static void riva_setup_accel(struct fb_info *info)
{
struct riva_par *par = (struct riva_par *) info->par;
@@ -1708,8 +1708,7 @@ static int __devinit riva_set_fbinfo(struct fb_info *info)
| FBINFO_HWACCEL_YPAN
| FBINFO_HWACCEL_COPYAREA
| FBINFO_HWACCEL_FILLRECT
- | FBINFO_HWACCEL_IMAGEBLIT
- | FBINFO_MISC_MODESWITCHLATE;
+ | FBINFO_HWACCEL_IMAGEBLIT;
/* Accel seems to not work properly on NV30 yet...*/
if ((par->riva.Architecture == NV_ARCH_30) || noaccel) {
@@ -2109,8 +2108,7 @@ static void __exit rivafb_remove(struct pci_dev *pd)
#ifdef CONFIG_FB_RIVA_I2C
riva_delete_i2c_busses(par);
- if (par->EDID)
- kfree(par->EDID);
+ kfree(par->EDID);
#endif
unregister_framebuffer(info);
@@ -2139,7 +2137,7 @@ static void __exit rivafb_remove(struct pci_dev *pd)
* ------------------------------------------------------------------------- */
#ifndef MODULE
-int __init rivafb_setup(char *options)
+static int __init rivafb_setup(char *options)
{
char *this_opt;
@@ -2189,7 +2187,7 @@ static struct pci_driver rivafb_driver = {
*
* ------------------------------------------------------------------------- */
-int __devinit rivafb_init(void)
+static int __devinit rivafb_init(void)
{
#ifndef MODULE
char *option = NULL;
diff --git a/drivers/video/riva/rivafb-i2c.c b/drivers/video/riva/rivafb-i2c.c
index c7c9a4921a0c6..da1334dfd51d3 100644
--- a/drivers/video/riva/rivafb-i2c.c
+++ b/drivers/video/riva/rivafb-i2c.c
@@ -120,8 +120,12 @@ static int riva_setup_i2c_bus(struct riva_i2c_chan *chan, const char *name)
rc = i2c_bit_add_bus(&chan->adapter);
if (rc == 0)
dev_dbg(&chan->par->pdev->dev, "I2C bus %s registered.\n", name);
- else
- dev_warn(&chan->par->pdev->dev, "Failed to register I2C bus %s.\n", name);
+ else {
+ dev_warn(&chan->par->pdev->dev,
+ "Failed to register I2C bus %s.\n", name);
+ chan->par = NULL;
+ }
+
return rc;
}
@@ -172,6 +176,9 @@ static u8 *riva_do_probe_i2c_edid(struct riva_i2c_chan *chan)
};
u8 *buf;
+ if (!chan->par)
+ return NULL;
+
buf = kmalloc(EDID_LENGTH, GFP_KERNEL);
if (!buf) {
dev_warn(&chan->par->pdev->dev, "Out of memory!\n");
diff --git a/drivers/video/s1d13xxxfb.c b/drivers/video/s1d13xxxfb.c
new file mode 100644
index 0000000000000..b637c389e4f48
--- /dev/null
+++ b/drivers/video/s1d13xxxfb.c
@@ -0,0 +1,772 @@
+/* drivers/video/s1d13xxxfb.c
+ *
+ * (c) 2004 Simtec Electronics
+ * (c) 2005 Thibaut VARENE <varenet@parisc-linux.org>
+ *
+ * Driver for Epson S1D13xxx series framebuffer chips
+ *
+ * Adapted from
+ * linux/drivers/video/skeletonfb.c
+ * linux/drivers/video/epson1355fb.c
+ * linux/drivers/video/epson/s1d13xxxfb.c (2.4 driver by Epson)
+ *
+ * Note, currently only tested on S1D13806 with 16bit CRT.
+ * As such, this driver might still contain some hardcoded bits relating to
+ * S1D13806.
+ * Making it work on other S1D13XXX chips should merely be a matter of adding
+ * a few switch()s, some missing glue here and there maybe, and split header
+ * files.
+ *
+ * TODO: - handle dual screen display (CRT and LCD at the same time).
+ * - check_var(), mode change, etc.
+ * - PM untested.
+ * - Accelerated interfaces.
+ * - Probably not SMP safe :)
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/mm.h>
+#include <linux/mman.h>
+#include <linux/fb.h>
+
+#include <asm/io.h>
+
+#include <video/s1d13xxxfb.h>
+
+#define PFX "s1d13xxxfb: "
+
+#if 0
+#define dbg(fmt, args...) do { printk(KERN_INFO fmt, ## args); } while(0)
+#else
+#define dbg(fmt, args...) do { } while (0)
+#endif
+
+/*
+ * Here we define the default struct fb_fix_screeninfo
+ */
+static struct fb_fix_screeninfo __devinitdata s1d13xxxfb_fix = {
+ .id = S1D_FBID,
+ .type = FB_TYPE_PACKED_PIXELS,
+ .visual = FB_VISUAL_PSEUDOCOLOR,
+ .xpanstep = 0,
+ .ypanstep = 1,
+ .ywrapstep = 0,
+ .accel = FB_ACCEL_NONE,
+};
+
+static inline u8
+s1d13xxxfb_readreg(struct s1d13xxxfb_par *par, u16 regno)
+{
+ return readb(par->regs + regno);
+}
+
+static inline void
+s1d13xxxfb_writereg(struct s1d13xxxfb_par *par, u16 regno, u8 value)
+{
+ writeb(value, par->regs + regno);
+}
+
+static inline void
+s1d13xxxfb_runinit(struct s1d13xxxfb_par *par,
+ const struct s1d13xxxfb_regval *initregs,
+ const unsigned int size)
+{
+ int i;
+
+ for (i = 0; i < size; i++) {
+ if ((initregs[i].addr == S1DREG_DELAYOFF) ||
+ (initregs[i].addr == S1DREG_DELAYON))
+ mdelay((int)initregs[i].value);
+ else {
+ s1d13xxxfb_writereg(par, initregs[i].addr, initregs[i].value);
+ }
+ }
+
+ /* make sure the hardware can cope with us */
+ mdelay(1);
+}
+
+static inline void
+lcd_enable(struct s1d13xxxfb_par *par, int enable)
+{
+ u8 mode = s1d13xxxfb_readreg(par, S1DREG_COM_DISP_MODE);
+
+ if (enable)
+ mode |= 0x01;
+ else
+ mode &= ~0x01;
+
+ s1d13xxxfb_writereg(par, S1DREG_COM_DISP_MODE, mode);
+}
+
+static inline void
+crt_enable(struct s1d13xxxfb_par *par, int enable)
+{
+ u8 mode = s1d13xxxfb_readreg(par, S1DREG_COM_DISP_MODE);
+
+ if (enable)
+ mode |= 0x02;
+ else
+ mode &= ~0x02;
+
+ s1d13xxxfb_writereg(par, S1DREG_COM_DISP_MODE, mode);
+}
+
+/* framebuffer control routines */
+
+static inline void
+s1d13xxxfb_setup_pseudocolour(struct fb_info *info)
+{
+ info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+
+ info->var.red.length = 4;
+ info->var.green.length = 4;
+ info->var.blue.length = 4;
+}
+
+static inline void
+s1d13xxxfb_setup_truecolour(struct fb_info *info)
+{
+ info->fix.visual = FB_VISUAL_TRUECOLOR;
+ info->var.bits_per_pixel = 16;
+
+ info->var.red.length = 5;
+ info->var.red.offset = 11;
+
+ info->var.green.length = 6;
+ info->var.green.offset = 5;
+
+ info->var.blue.length = 5;
+ info->var.blue.offset = 0;
+}
+
+/**
+ * s1d13xxxfb_set_par - Alters the hardware state.
+ * @info: frame buffer structure
+ *
+ * Using the fb_var_screeninfo in fb_info we set the depth of the
+ * framebuffer. This function alters the par AND the
+ * 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.
+ *
+ * XXX TODO: write proper s1d13xxxfb_check_var(), without which that
+ * function is quite useless.
+ */
+static int
+s1d13xxxfb_set_par(struct fb_info *info)
+{
+ struct s1d13xxxfb_par *s1dfb = info->par;
+ unsigned int val;
+
+ dbg("s1d13xxxfb_set_par: bpp=%d\n", info->var.bits_per_pixel);
+
+ if ((s1dfb->display & 0x01)) /* LCD */
+ val = s1d13xxxfb_readreg(s1dfb, S1DREG_LCD_DISP_MODE); /* read colour control */
+ else /* CRT */
+ val = s1d13xxxfb_readreg(s1dfb, S1DREG_CRT_DISP_MODE); /* read colour control */
+
+ val &= ~0x07;
+
+ switch (info->var.bits_per_pixel) {
+ case 4:
+ dbg("pseudo colour 4\n");
+ s1d13xxxfb_setup_pseudocolour(info);
+ val |= 2;
+ break;
+ case 8:
+ dbg("pseudo colour 8\n");
+ s1d13xxxfb_setup_pseudocolour(info);
+ val |= 3;
+ break;
+ case 16:
+ dbg("true colour\n");
+ s1d13xxxfb_setup_truecolour(info);
+ val |= 5;
+ break;
+
+ default:
+ dbg("bpp not supported!\n");
+ return -EINVAL;
+ }
+
+ dbg("writing %02x to display mode register\n", val);
+
+ if ((s1dfb->display & 0x01)) /* LCD */
+ s1d13xxxfb_writereg(s1dfb, S1DREG_LCD_DISP_MODE, val);
+ else /* CRT */
+ s1d13xxxfb_writereg(s1dfb, S1DREG_CRT_DISP_MODE, val);
+
+ info->fix.line_length = info->var.xres * info->var.bits_per_pixel;
+ info->fix.line_length /= 8;
+
+ dbg("setting line_length to %d\n", info->fix.line_length);
+
+ dbg("done setup\n");
+
+ return 0;
+}
+
+/**
+ * s1d13xxxfb_setcolreg - sets a color register.
+ * @regno: Which register in the CLUT we are programming
+ * @red: The red value which can be up to 16 bits wide
+ * @green: The green value which can be up to 16 bits wide
+ * @blue: The blue value which can be up to 16 bits wide.
+ * @transp: If supported the alpha value which can be up to 16 bits wide.
+ * @info: frame buffer info structure
+ *
+ * Returns negative errno on error, or zero on success.
+ */
+static int
+s1d13xxxfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+ u_int transp, struct fb_info *info)
+{
+ struct s1d13xxxfb_par *s1dfb = info->par;
+ unsigned int pseudo_val;
+
+ if (regno >= S1D_PALETTE_SIZE)
+ return -EINVAL;
+
+ dbg("s1d13xxxfb_setcolreg: %d: rgb=%d,%d,%d, tr=%d\n",
+ regno, red, green, blue, transp);
+
+ if (info->var.grayscale)
+ red = green = blue = (19595*red + 38470*green + 7471*blue) >> 16;
+
+ switch (info->fix.visual) {
+ case FB_VISUAL_TRUECOLOR:
+ if (regno >= 16)
+ return -EINVAL;
+
+ /* deal with creating pseudo-palette entries */
+
+ pseudo_val = (red >> 11) << info->var.red.offset;
+ pseudo_val |= (green >> 10) << info->var.green.offset;
+ pseudo_val |= (blue >> 11) << info->var.blue.offset;
+
+ dbg("s1d13xxxfb_setcolreg: pseudo %d, val %08x\n",
+ regno, pseudo_val);
+
+ ((u32 *)info->pseudo_palette)[regno] = pseudo_val;
+
+ break;
+ case FB_VISUAL_PSEUDOCOLOR:
+ s1d13xxxfb_writereg(s1dfb, S1DREG_LKUP_ADDR, regno);
+ s1d13xxxfb_writereg(s1dfb, S1DREG_LKUP_DATA, red);
+ s1d13xxxfb_writereg(s1dfb, S1DREG_LKUP_DATA, green);
+ s1d13xxxfb_writereg(s1dfb, S1DREG_LKUP_DATA, blue);
+
+ break;
+ default:
+ return -ENOSYS;
+ }
+
+ dbg("s1d13xxxfb_setcolreg: done\n");
+
+ return 0;
+}
+
+/**
+ * s1d13xxxfb_blank - blanks the display.
+ * @blank_mode: the blank mode we want.
+ * @info: frame buffer structure that represents a single frame buffer
+ *
+ * Blank the screen if blank_mode != 0, else unblank. Return 0 if
+ * blanking succeeded, != 0 if un-/blanking failed due to e.g. a
+ * video mode which doesn't support it. Implements VESA suspend
+ * and powerdown modes on hardware that supports disabling hsync/vsync:
+ * blank_mode == 2: suspend vsync
+ * blank_mode == 3: suspend hsync
+ * blank_mode == 4: powerdown
+ *
+ * Returns negative errno on error, or zero on success.
+ */
+static int
+s1d13xxxfb_blank(int blank_mode, struct fb_info *info)
+{
+ struct s1d13xxxfb_par *par = info->par;
+
+ dbg("s1d13xxxfb_blank: blank=%d, info=%p\n", blank_mode, info);
+
+ switch (blank_mode) {
+ case FB_BLANK_UNBLANK:
+ case FB_BLANK_NORMAL:
+ if ((par->display & 0x01) != 0)
+ lcd_enable(par, 1);
+ if ((par->display & 0x02) != 0)
+ crt_enable(par, 1);
+ break;
+ case FB_BLANK_VSYNC_SUSPEND:
+ case FB_BLANK_HSYNC_SUSPEND:
+ break;
+ case FB_BLANK_POWERDOWN:
+ lcd_enable(par, 0);
+ crt_enable(par, 0);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* let fbcon do a soft blank for us */
+ return ((blank_mode == FB_BLANK_NORMAL) ? 1 : 0);
+}
+
+/**
+ * s1d13xxxfb_pan_display - Pans the display.
+ * @var: frame buffer variable screen structure
+ * @info: frame buffer structure that represents a single frame buffer
+ *
+ * Pan (or wrap, depending on the `vmode' field) the display using the
+ * `yoffset' field of the `var' structure (`xoffset' not yet supported).
+ * If the values don't fit, return -EINVAL.
+ *
+ * Returns negative errno on error, or zero on success.
+ */
+static int
+s1d13xxxfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+ struct s1d13xxxfb_par *par = info->par;
+ u32 start;
+
+ if (var->xoffset != 0) /* not yet ... */
+ return -EINVAL;
+
+ if (var->yoffset + info->var.yres > info->var.yres_virtual)
+ return -EINVAL;
+
+ start = (info->fix.line_length >> 1) * var->yoffset;
+
+ if ((par->display & 0x01)) {
+ /* LCD */
+ s1d13xxxfb_writereg(par, S1DREG_LCD_DISP_START0, (start & 0xff));
+ s1d13xxxfb_writereg(par, S1DREG_LCD_DISP_START1, ((start >> 8) & 0xff));
+ s1d13xxxfb_writereg(par, S1DREG_LCD_DISP_START2, ((start >> 16) & 0x0f));
+ } else {
+ /* CRT */
+ s1d13xxxfb_writereg(par, S1DREG_CRT_DISP_START0, (start & 0xff));
+ s1d13xxxfb_writereg(par, S1DREG_CRT_DISP_START1, ((start >> 8) & 0xff));
+ s1d13xxxfb_writereg(par, S1DREG_CRT_DISP_START2, ((start >> 16) & 0x0f));
+ }
+
+ return 0;
+}
+
+
+/* framebuffer information structures */
+
+static struct fb_ops s1d13xxxfb_fbops = {
+ .owner = THIS_MODULE,
+ .fb_set_par = s1d13xxxfb_set_par,
+ .fb_setcolreg = s1d13xxxfb_setcolreg,
+ .fb_blank = s1d13xxxfb_blank,
+
+ .fb_pan_display = s1d13xxxfb_pan_display,
+
+ /* to be replaced by any acceleration we can */
+ .fb_fillrect = cfb_fillrect,
+ .fb_copyarea = cfb_copyarea,
+ .fb_imageblit = cfb_imageblit,
+ .fb_cursor = soft_cursor
+};
+
+static int s1d13xxxfb_width_tab[2][4] __devinitdata = {
+ {4, 8, 16, -1},
+ {9, 12, 18, -1},
+};
+
+/**
+ * s1d13xxxfb_fetch_hw_state - Configure the framebuffer according to
+ * hardware setup.
+ * @info: frame buffer structure
+ *
+ * We setup the framebuffer structures according to the current
+ * hardware setup. On some machines, the BIOS will have filled
+ * the chip registers with such info, on others, these values will
+ * have been written in some init procedure. In any case, the
+ * software values needs to match the hardware ones. This is what
+ * this function ensures.
+ *
+ * Note: some of the hardcoded values here might need some love to
+ * work on various chips, and might need to no longer be hardcoded.
+ */
+static void __devinit
+s1d13xxxfb_fetch_hw_state(struct fb_info *info)
+{
+ struct fb_var_screeninfo *var = &info->var;
+ struct fb_fix_screeninfo *fix = &info->fix;
+ struct s1d13xxxfb_par *par = info->par;
+ u8 panel, display;
+ u16 offset;
+ u32 xres, yres;
+ u32 xres_virtual, yres_virtual;
+ int bpp, lcd_bpp;
+ int is_color, is_dual, is_tft;
+ int lcd_enabled, crt_enabled;
+
+ fix->type = FB_TYPE_PACKED_PIXELS;
+
+ /* general info */
+ par->display = s1d13xxxfb_readreg(par, S1DREG_COM_DISP_MODE);
+ crt_enabled = (par->display & 0x02) != 0;
+ lcd_enabled = (par->display & 0x01) != 0;
+
+ if (lcd_enabled && crt_enabled)
+ printk(KERN_WARNING PFX "Warning: LCD and CRT detected, using LCD\n");
+
+ if (lcd_enabled)
+ display = s1d13xxxfb_readreg(par, S1DREG_LCD_DISP_MODE);
+ else /* CRT */
+ display = s1d13xxxfb_readreg(par, S1DREG_CRT_DISP_MODE);
+
+ bpp = display & 0x07;
+
+ switch (bpp) {
+ case 2: /* 4 bpp */
+ case 3: /* 8 bpp */
+ var->bits_per_pixel = 8;
+ var->red.offset = var->green.offset = var->blue.offset = 0;
+ var->red.length = var->green.length = var->blue.length = 8;
+ break;
+ case 5: /* 16 bpp */
+ s1d13xxxfb_setup_truecolour(info);
+ break;
+ default:
+ dbg("bpp: %i\n", bpp);
+ }
+ fb_alloc_cmap(&info->cmap, 256, 0);
+
+ /* LCD info */
+ panel = s1d13xxxfb_readreg(par, S1DREG_PANEL_TYPE);
+ is_color = (panel & 0x04) != 0;
+ is_dual = (panel & 0x02) != 0;
+ is_tft = (panel & 0x01) != 0;
+ lcd_bpp = s1d13xxxfb_width_tab[is_tft][(panel >> 4) & 3];
+
+ if (lcd_enabled) {
+ xres = (s1d13xxxfb_readreg(par, S1DREG_LCD_DISP_HWIDTH) + 1) * 8;
+ yres = (s1d13xxxfb_readreg(par, S1DREG_LCD_DISP_VHEIGHT0) +
+ ((s1d13xxxfb_readreg(par, S1DREG_LCD_DISP_VHEIGHT1) & 0x03) << 8) + 1);
+
+ offset = (s1d13xxxfb_readreg(par, S1DREG_LCD_MEM_OFF0) +
+ ((s1d13xxxfb_readreg(par, S1DREG_LCD_MEM_OFF1) & 0x7) << 8));
+ } else { /* crt */
+ xres = (s1d13xxxfb_readreg(par, S1DREG_CRT_DISP_HWIDTH) + 1) * 8;
+ yres = (s1d13xxxfb_readreg(par, S1DREG_CRT_DISP_VHEIGHT0) +
+ ((s1d13xxxfb_readreg(par, S1DREG_CRT_DISP_VHEIGHT1) & 0x03) << 8) + 1);
+
+ offset = (s1d13xxxfb_readreg(par, S1DREG_CRT_MEM_OFF0) +
+ ((s1d13xxxfb_readreg(par, S1DREG_CRT_MEM_OFF1) & 0x7) << 8));
+ }
+ xres_virtual = offset * 16 / var->bits_per_pixel;
+ yres_virtual = fix->smem_len / (offset * 2);
+
+ var->xres = xres;
+ var->yres = yres;
+ var->xres_virtual = xres_virtual;
+ var->yres_virtual = yres_virtual;
+ var->xoffset = var->yoffset = 0;
+
+ fix->line_length = offset * 2;
+
+ var->grayscale = !is_color;
+
+ var->activate = FB_ACTIVATE_NOW;
+
+ dbg(PFX "bpp=%d, lcd_bpp=%d, "
+ "crt_enabled=%d, lcd_enabled=%d\n",
+ var->bits_per_pixel, lcd_bpp, crt_enabled, lcd_enabled);
+ dbg(PFX "xres=%d, yres=%d, vxres=%d, vyres=%d "
+ "is_color=%d, is_dual=%d, is_tft=%d\n",
+ xres, yres, xres_virtual, yres_virtual, is_color, is_dual, is_tft);
+}
+
+
+static int __devexit
+s1d13xxxfb_remove(struct device *dev)
+{
+ struct fb_info *info = dev_get_drvdata(dev);
+ struct platform_device *pdev = to_platform_device(dev);
+ struct s1d13xxxfb_par *par = NULL;
+
+ if (info) {
+ par = info->par;
+ if (par && par->regs) {
+ /* disable output & enable powersave */
+ s1d13xxxfb_writereg(par, S1DREG_COM_DISP_MODE, 0x00);
+ s1d13xxxfb_writereg(par, S1DREG_PS_CNF, 0x11);
+ iounmap(par->regs);
+ }
+
+ fb_dealloc_cmap(&info->cmap);
+
+ if (info->screen_base)
+ iounmap(info->screen_base);
+
+ framebuffer_release(info);
+ }
+
+ release_mem_region(pdev->resource[0].start,
+ pdev->resource[0].end - pdev->resource[0].start +1);
+ release_mem_region(pdev->resource[1].start,
+ pdev->resource[1].end - pdev->resource[1].start +1);
+ return 0;
+}
+
+static int __devinit
+s1d13xxxfb_probe(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct s1d13xxxfb_par *default_par;
+ struct fb_info *info;
+ struct s1d13xxxfb_pdata *pdata = NULL;
+ int ret = 0;
+ u8 revision;
+
+ dbg("probe called: device is %p\n", dev);
+
+ printk(KERN_INFO "Epson S1D13XXX FB Driver\n");
+
+ /* enable platform-dependent hardware glue, if any */
+ if (dev->platform_data)
+ pdata = dev->platform_data;
+
+ if (pdata && pdata->platform_init_video)
+ pdata->platform_init_video();
+
+
+ if (pdev->num_resources != 2) {
+ dev_err(&pdev->dev, "invalid num_resources: %i\n",
+ pdev->num_resources);
+ ret = -ENODEV;
+ goto bail;
+ }
+
+ /* resource[0] is VRAM, resource[1] is registers */
+ if (pdev->resource[0].flags != IORESOURCE_MEM
+ || pdev->resource[1].flags != IORESOURCE_MEM) {
+ dev_err(&pdev->dev, "invalid resource type\n");
+ ret = -ENODEV;
+ goto bail;
+ }
+
+ if (!request_mem_region(pdev->resource[0].start,
+ pdev->resource[0].end - pdev->resource[0].start +1, "s1d13xxxfb mem")) {
+ dev_dbg(dev, "request_mem_region failed\n");
+ ret = -EBUSY;
+ goto bail;
+ }
+
+ if (!request_mem_region(pdev->resource[1].start,
+ pdev->resource[1].end - pdev->resource[1].start +1, "s1d13xxxfb regs")) {
+ dev_dbg(dev, "request_mem_region failed\n");
+ ret = -EBUSY;
+ goto bail;
+ }
+
+ info = framebuffer_alloc(sizeof(struct s1d13xxxfb_par) + sizeof(u32) * 256, &pdev->dev);
+ if (!info) {
+ ret = -ENOMEM;
+ goto bail;
+ }
+
+ default_par = info->par;
+ default_par->regs = ioremap_nocache(pdev->resource[1].start,
+ pdev->resource[1].end - pdev->resource[1].start +1);
+ if (!default_par->regs) {
+ printk(KERN_ERR PFX "unable to map registers\n");
+ ret = -ENOMEM;
+ goto bail;
+ }
+ info->pseudo_palette = default_par->pseudo_palette;
+
+ info->screen_base = ioremap_nocache(pdev->resource[0].start,
+ pdev->resource[0].end - pdev->resource[0].start +1);
+
+ if (!info->screen_base) {
+ printk(KERN_ERR PFX "unable to map framebuffer\n");
+ ret = -ENOMEM;
+ goto bail;
+ }
+
+ revision = s1d13xxxfb_readreg(default_par, S1DREG_REV_CODE);
+ if ((revision >> 2) != S1D_CHIP_REV) {
+ printk(KERN_INFO PFX "chip not found: %i\n", (revision >> 2));
+ ret = -ENODEV;
+ goto bail;
+ }
+
+ info->fix = s1d13xxxfb_fix;
+ info->fix.mmio_start = pdev->resource[1].start;
+ info->fix.mmio_len = pdev->resource[1].end - pdev->resource[1].start +1;
+ info->fix.smem_start = pdev->resource[0].start;
+ info->fix.smem_len = pdev->resource[0].end - pdev->resource[0].start +1;
+
+ printk(KERN_INFO PFX "regs mapped at 0x%p, fb %d KiB mapped at 0x%p\n",
+ default_par->regs, info->fix.smem_len / 1024, info->screen_base);
+
+ info->par = default_par;
+ info->fbops = &s1d13xxxfb_fbops;
+ info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
+
+ /* perform "manual" chip initialization, if needed */
+ if (pdata && pdata->initregs)
+ s1d13xxxfb_runinit(info->par, pdata->initregs, pdata->initregssize);
+
+ s1d13xxxfb_fetch_hw_state(info);
+
+ if (register_framebuffer(info) < 0) {
+ ret = -EINVAL;
+ goto bail;
+ }
+
+ dev_set_drvdata(&pdev->dev, info);
+
+ printk(KERN_INFO "fb%d: %s frame buffer device\n",
+ info->node, info->fix.id);
+
+ return 0;
+
+bail:
+ s1d13xxxfb_remove(dev);
+ return ret;
+
+}
+
+#ifdef CONFIG_PM
+static int s1d13xxxfb_suspend(struct device *dev, u32 state, u32 level)
+{
+ struct fb_info *info = dev_get_drvdata(dev);
+ struct s1d13xxxfb_par *s1dfb = info->par;
+ struct s1d13xxxfb_pdata *pdata = NULL;
+
+ /* disable display */
+ lcd_enable(s1dfb, 0);
+ crt_enable(s1dfb, 0);
+
+ if (dev->platform_data)
+ pdata = dev->platform_data;
+
+#if 0
+ if (!s1dfb->disp_save)
+ s1dfb->disp_save = kmalloc(info->fix.smem_len, GFP_KERNEL);
+
+ if (!s1dfb->disp_save) {
+ printk(KERN_ERR PFX "no memory to save screen");
+ return -ENOMEM;
+ }
+
+ memcpy_fromio(s1dfb->disp_save, info->screen_base, info->fix.smem_len);
+#else
+ s1dfb->disp_save = NULL;
+#endif
+
+ if (!s1dfb->regs_save)
+ s1dfb->regs_save = kmalloc(info->fix.mmio_len, GFP_KERNEL);
+
+ if (!s1dfb->regs_save) {
+ printk(KERN_ERR PFX "no memory to save registers");
+ return -ENOMEM;
+ }
+
+ /* backup all registers */
+ memcpy_fromio(s1dfb->regs_save, s1dfb->regs, info->fix.mmio_len);
+
+ /* now activate power save mode */
+ s1d13xxxfb_writereg(s1dfb, S1DREG_PS_CNF, 0x11);
+
+ if (pdata && pdata->platform_suspend_video)
+ return pdata->platform_suspend_video();
+ else
+ return 0;
+}
+
+static int s1d13xxxfb_resume(struct device *dev, u32 level)
+{
+ struct fb_info *info = dev_get_drvdata(dev);
+ struct s1d13xxxfb_par *s1dfb = info->par;
+ struct s1d13xxxfb_pdata *pdata = NULL;
+
+ if (level != RESUME_ENABLE)
+ return 0;
+
+ /* awaken the chip */
+ s1d13xxxfb_writereg(s1dfb, S1DREG_PS_CNF, 0x10);
+
+ /* do not let go until SDRAM "wakes up" */
+ while ((s1d13xxxfb_readreg(s1dfb, S1DREG_PS_STATUS) & 0x01))
+ udelay(10);
+
+ if (dev->platform_data)
+ pdata = dev->platform_data;
+
+ if (s1dfb->regs_save) {
+ /* will write RO regs, *should* get away with it :) */
+ memcpy_toio(s1dfb->regs, s1dfb->regs_save, info->fix.mmio_len);
+ kfree(s1dfb->regs_save);
+ }
+
+ if (s1dfb->disp_save) {
+ memcpy_toio(info->screen_base, s1dfb->disp_save,
+ info->fix.smem_len);
+ kfree(s1dfb->disp_save); /* XXX kmalloc()'d when? */
+ }
+
+ if ((s1dfb->display & 0x01) != 0)
+ lcd_enable(s1dfb, 1);
+ if ((s1dfb->display & 0x02) != 0)
+ crt_enable(s1dfb, 1);
+
+ if (pdata && pdata->platform_resume_video)
+ return pdata->platform_resume_video();
+ else
+ return 0;
+}
+#endif /* CONFIG_PM */
+
+static struct device_driver s1d13xxxfb_driver = {
+ .name = S1D_DEVICENAME,
+ .bus = &platform_bus_type,
+ .probe = s1d13xxxfb_probe,
+ .remove = s1d13xxxfb_remove,
+#ifdef CONFIG_PM
+ .suspend = s1d13xxxfb_suspend,
+ .resume = s1d13xxxfb_resume
+#endif
+};
+
+
+static int __init
+s1d13xxxfb_init(void)
+{
+ if (fb_get_options("s1d13xxxfb", NULL))
+ return -ENODEV;
+
+ return driver_register(&s1d13xxxfb_driver);
+}
+
+
+static void __exit
+s1d13xxxfb_exit(void)
+{
+ driver_unregister(&s1d13xxxfb_driver);
+}
+
+module_init(s1d13xxxfb_init);
+module_exit(s1d13xxxfb_exit);
+
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Framebuffer driver for S1D13xxx devices");
+MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>, Thibaut VARENE <varenet@parisc-linux.org>");
diff --git a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c
index 6439fb0731586..4f8043a71f21d 100644
--- a/drivers/video/sa1100fb.c
+++ b/drivers/video/sa1100fb.c
@@ -836,7 +836,7 @@ static int sa1100fb_mmap(struct fb_info *info, struct file *file,
vma->vm_pgoff = off >> PAGE_SHIFT;
vma->vm_flags |= VM_IO;
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
- return io_remap_page_range(vma, vma->vm_start, off,
+ return io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
vma->vm_end - vma->vm_start,
vma->vm_page_prot);
}
@@ -1507,8 +1507,7 @@ static int __init sa1100fb_probe(struct device *dev)
failed:
dev_set_drvdata(dev, NULL);
- if (fbi)
- kfree(fbi);
+ kfree(fbi);
release_mem_region(0xb0100000, 0x10000);
return ret;
}
diff --git a/drivers/video/savage/Makefile b/drivers/video/savage/Makefile
index 48591154b5de4..e09770fff8eaa 100644
--- a/drivers/video/savage/Makefile
+++ b/drivers/video/savage/Makefile
@@ -2,7 +2,8 @@
# Makefile for the S3 Savage framebuffer driver
#
-obj-$(CONFIG_FB_SAVAGE) += savagefb.o
-obj-$(CONFIG_FB_SAVAGE_I2C) += savagefb-i2c.o
-obj-$(CONFIG_FB_SAVAGE_ACCEL) += savagefb_accel.o
+obj-$(CONFIG_FB_SAVAGE) += savagefb.o
+savagefb-y += savagefb_driver.o
+savagefb-$(CONFIG_FB_SAVAGE_I2C) += savagefb-i2c.o
+savagefb-$(CONFIG_FB_SAVAGE_ACCEL) += savagefb_accel.o
diff --git a/drivers/video/savage/savagefb-i2c.c b/drivers/video/savage/savagefb-i2c.c
index 55270d2ad06c7..024a0cecff156 100644
--- a/drivers/video/savage/savagefb-i2c.c
+++ b/drivers/video/savage/savagefb-i2c.c
@@ -207,7 +207,6 @@ void savagefb_create_i2c_busses(struct fb_info *info)
savage_setup_i2c_bus(&par->chan, "SAVAGE DDC2");
}
-EXPORT_SYMBOL(savagefb_create_i2c_busses);
void savagefb_delete_i2c_busses(struct fb_info *info)
{
@@ -222,7 +221,6 @@ void savagefb_delete_i2c_busses(struct fb_info *info)
par->chan.par = NULL;
}
-EXPORT_SYMBOL(savagefb_delete_i2c_busses);
static u8 *savage_do_probe_i2c_edid(struct savagefb_i2c_chan *chan)
{
@@ -280,6 +278,5 @@ int savagefb_probe_i2c_connector(struct savagefb_par *par, u8 **out_edid)
return 0;
}
-EXPORT_SYMBOL(savagefb_probe_i2c_connector);
MODULE_LICENSE("GPL");
diff --git a/drivers/video/savage/savagefb_accel.c b/drivers/video/savage/savagefb_accel.c
index da5fb8f692432..bac8ea3a0108a 100644
--- a/drivers/video/savage/savagefb_accel.c
+++ b/drivers/video/savage/savagefb_accel.c
@@ -26,7 +26,6 @@ int savagefb_sync(struct fb_info *info)
par->SavageWaitIdle(par);
return 0;
}
-EXPORT_SYMBOL(savagefb_sync);
void savagefb_copyarea(struct fb_info *info, const struct fb_copyarea *region)
{
@@ -61,7 +60,6 @@ void savagefb_copyarea(struct fb_info *info, const struct fb_copyarea *region)
BCI_SEND(BCI_X_Y(dx, dy));
BCI_SEND(BCI_W_H(region->width, region->height));
}
-EXPORT_SYMBOL(savagefb_copyarea);
void savagefb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
{
@@ -89,7 +87,6 @@ void savagefb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
BCI_SEND( BCI_X_Y(rect->dx, rect->dy) );
BCI_SEND( BCI_W_H(rect->width, rect->height) );
}
-EXPORT_SYMBOL(savagefb_fillrect);
void savagefb_imageblit(struct fb_info *info, const struct fb_image *image)
{
@@ -135,6 +132,5 @@ void savagefb_imageblit(struct fb_info *info, const struct fb_image *image)
for (i = 0; i < size; i++)
BCI_SEND(src[i]);
}
-EXPORT_SYMBOL(savagefb_imageblit);
MODULE_LICENSE("GPL");
diff --git a/drivers/video/savage/savagefb.c b/drivers/video/savage/savagefb_driver.c
index 4c5edfaf0e052..e1c9c946be2dc 100644
--- a/drivers/video/savage/savagefb.c
+++ b/drivers/video/savage/savagefb_driver.c
@@ -1459,7 +1459,7 @@ static void savage_enable_mmio (struct savagefb_par *par)
}
-void savage_disable_mmio (struct savagefb_par *par)
+static void savage_disable_mmio (struct savagefb_par *par)
{
unsigned char val;
@@ -1498,7 +1498,7 @@ static int __devinit savage_map_mmio (struct fb_info *info)
info->fix.mmio_start = par->mmio.pbase;
info->fix.mmio_len = par->mmio.len;
- par->bci_base = (u32 __iomem *)(par->mmio.vbase + BCI_BUFFER_OFFSET);
+ par->bci_base = (u32*)(par->mmio.vbase + BCI_BUFFER_OFFSET);
par->bci_ptr = 0;
savage_enable_mmio (par);
@@ -1514,7 +1514,7 @@ static void __devinit savage_unmap_mmio (struct fb_info *info)
savage_disable_mmio(par);
if (par->mmio.vbase) {
- iounmap ((void __iomem *)par->mmio.vbase);
+ iounmap ((void *)par->mmio.vbase);
par->mmio.vbase = NULL;
}
}
@@ -1551,6 +1551,10 @@ static int __devinit savage_map_video (struct fb_info *info,
par->video.mtrr = mtrr_add (par->video.pbase, video_len,
MTRR_TYPE_WRCOMB, 1);
#endif
+
+ /* Clear framebuffer, it's all white in memory after boot */
+ memset (par->video.vbase, 0, par->video.len);
+
return 0;
}
@@ -1879,8 +1883,7 @@ static int __devinit savage_init_fb_info (struct fb_info *info,
info->fbops = &savagefb_ops;
info->flags = FBINFO_DEFAULT |
FBINFO_HWACCEL_YPAN |
- FBINFO_HWACCEL_XPAN |
- FBINFO_MISC_MODESWITCHLATE;
+ FBINFO_HWACCEL_XPAN;
info->pseudo_palette = par->pseudo_palette;
@@ -2243,7 +2246,7 @@ static void __exit savage_done (void)
/* ************************* init in-kernel code ************************** */
-int __init savagefb_setup(char *options)
+static int __init savagefb_setup(char *options)
{
#ifndef MODULE
char *this_opt;
@@ -2258,7 +2261,7 @@ int __init savagefb_setup(char *options)
return 0;
}
-int __init savagefb_init(void)
+static int __init savagefb_init(void)
{
char *option;
diff --git a/drivers/video/sbuslib.c b/drivers/video/sbuslib.c
index 70e875aaa2f56..34f72edba820e 100644
--- a/drivers/video/sbuslib.c
+++ b/drivers/video/sbuslib.c
@@ -74,10 +74,12 @@ int sbusfb_mmap_helper(struct sbus_mmap_map *map,
}
if (page + map_size > size)
map_size = size - page;
- r = io_remap_page_range(vma,
+ r = io_remap_pfn_range(vma,
vma->vm_start + page,
- map_offset, map_size,
- vma->vm_page_prot, iospace);
+ MK_IOSPACE_PFN(iospace,
+ map_offset >> PAGE_SHIFT),
+ map_size,
+ vma->vm_page_prot);
if (r)
return -EAGAIN;
page += map_size;
diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c
index 74944ce516aa8..b773c98f6513d 100644
--- a/drivers/video/sis/sis_main.c
+++ b/drivers/video/sis/sis_main.c
@@ -50,6 +50,7 @@
#include <linux/fb.h>
#include <linux/console.h>
#include <linux/selection.h>
+#include <linux/smp_lock.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/pci.h>
@@ -144,7 +145,7 @@ sisfb_setdefaultparms(void)
#endif
}
-static void __init
+static void __devinit
sisfb_search_vesamode(unsigned int vesamode, BOOLEAN quiet)
{
int i = 0, j = 0;
@@ -5639,7 +5640,7 @@ static void __devexit sisfb_remove(struct pci_dev *pdev)
/* Unmap */
iounmap(ivideo->video_vbase);
iounmap(ivideo->mmio_vbase);
- if(ivideo->bios_abase) vfree(ivideo->bios_abase);
+ vfree(ivideo->bios_abase);
/* Release mem regions */
release_mem_region(ivideo->video_base, ivideo->video_size);
@@ -5694,7 +5695,7 @@ SISINITSTATIC int __init sisfb_init(void)
sisfb_setup(options);
#endif
#endif
- return(pci_module_init(&sisfb_driver));
+ return(pci_register_driver(&sisfb_driver));
}
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8)
@@ -5939,7 +5940,7 @@ MODULE_PARM_DESC(videoram,
#endif
#endif
-int __init sisfb_init_module(void)
+int __devinit sisfb_init_module(void)
{
sisfb_setdefaultparms();
diff --git a/drivers/video/skeletonfb.c b/drivers/video/skeletonfb.c
index a6ccc3ae53c15..7b43716ab6656 100644
--- a/drivers/video/skeletonfb.c
+++ b/drivers/video/skeletonfb.c
@@ -120,7 +120,7 @@ static struct fb_fix_screeninfo xxxfb_fix __initdata = {
static struct fb_info info;
/*
- * Each one represents the a state of the hardware. Most hardware have
+ * Each one represents the state of the hardware. Most hardware have
* just one hardware state. These here represent the default state(s).
*/
static struct xxx_par __initdata current_par;
@@ -139,6 +139,8 @@ int xxxfb_setup(char*);
* Usually you don't need to provide this function. The case where it
* is used is to change from a text mode hardware state to a graphics
* mode state.
+ *
+ * Returns negative errno on error, or zero on success.
*/
static int xxxfb_open(const struct fb_info *info, int user)
{
@@ -156,6 +158,8 @@ static int xxxfb_open(const struct fb_info *info, int user)
* console system is released. Usually you don't need this function.
* The case where it is usually used is to go from a graphics state
* to a text mode state.
+ *
+ * Returns negative errno on error, or zero on success.
*/
static int xxxfb_release(const struct fb_info *info, int user)
{
@@ -201,8 +205,9 @@ static int xxxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
* 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.
- * Again if you can't can't the resolution you don't need this function.
+ * Again if you can't change the resolution you don't need this function.
*
+ * Returns negative errno on error, or zero on success.
*/
static int xxxfb_set_par(struct fb_info *info)
{
@@ -217,14 +222,14 @@ static int xxxfb_set_par(struct fb_info *info)
* @red: The red value which can be up to 16 bits wide
* @green: The green value which can be up to 16 bits wide
* @blue: The blue value which can be up to 16 bits wide.
- * @transp: If supported the alpha value which can be up to 16 bits wide.
+ * @transp: If supported, the alpha value which can be up to 16 bits wide.
* @info: frame buffer info structure
*
* Set a single color register. The values supplied have a 16 bit
* magnitude which needs to be scaled in this function for the hardware.
* Things to take into consideration are how many color registers, if
* any, are supported with the current color visual. With truecolor mode
- * no color palettes are supported. Here a psuedo palette is created
+ * no color palettes are supported. Here a pseudo palette is created
* which we store the value in pseudo_palette in struct fb_info. For
* pseudocolor mode we have a limited color palette. To deal with this
* we can program what color is displayed for a particular pixel value.
@@ -238,7 +243,7 @@ static int xxxfb_setcolreg(unsigned regno, unsigned red, unsigned green,
const struct fb_info *info)
{
if (regno >= 256) /* no. of hw registers */
- return 1;
+ return -EINVAL;
/*
* Program hardware... do anything you want with transp
*/
@@ -295,7 +300,7 @@ static int xxxfb_setcolreg(unsigned regno, unsigned red, unsigned green,
u32 v;
if (regno >= 16)
- return 1;
+ return -EINVAL;
v = (red << info->var.red.offset) |
(green << info->var.green.offset) |
@@ -563,7 +568,7 @@ int __init xxxfb_init(void)
#endif
/*
- * Here we set the screen_base to the vitrual memory address
+ * Here we set the screen_base to the virtual memory address
* for the framebuffer. Usually we obtain the resource address
* from the bus layer and then translate it to virtual memory
* space via ioremap. Consult ioport.h.
@@ -621,6 +626,7 @@ static void __exit xxxfb_cleanup(void)
*/
unregister_framebuffer(info);
+ fb_dealloc_cmap(&info.cmap);
/* ... */
}
diff --git a/drivers/video/sstfb.c b/drivers/video/sstfb.c
index 9c67b4b0b7a8f..663d53657fa4c 100644
--- a/drivers/video/sstfb.c
+++ b/drivers/video/sstfb.c
@@ -1338,8 +1338,8 @@ static void __devexit sst_shutdown(struct fb_info *info)
/*
* Interface to the world
*/
-
-int __init sstfb_setup(char *options)
+#ifndef MODULE
+static int __init sstfb_setup(char *options)
{
char *this_opt;
@@ -1372,6 +1372,7 @@ int __init sstfb_setup(char *options)
}
return 0;
}
+#endif
static struct fb_ops sstfb_ops = {
.owner = THIS_MODULE,
@@ -1565,7 +1566,7 @@ static struct pci_driver sstfb_driver = {
};
-int __devinit sstfb_init(void)
+static int __devinit sstfb_init(void)
{
#ifndef MODULE
char *option = NULL;
@@ -1574,13 +1575,15 @@ int __devinit sstfb_init(void)
return -ENODEV;
sstfb_setup(option);
#endif
- return pci_module_init(&sstfb_driver);
+ return pci_register_driver(&sstfb_driver);
}
-void __devexit sstfb_exit(void)
+#ifdef MODULE
+static void __devexit sstfb_exit(void)
{
pci_unregister_driver(&sstfb_driver);
}
+#endif
/*
diff --git a/drivers/video/stifb.c b/drivers/video/stifb.c
index 8b76a919297e4..9e52794768e61 100644
--- a/drivers/video/stifb.c
+++ b/drivers/video/stifb.c
@@ -112,11 +112,10 @@ struct stifb_info {
ngle_rom_t ngle_rom;
struct sti_struct *sti;
int deviceSpecificConfig;
- u32 pseudo_palette[16];
+ u32 pseudo_palette[256];
};
-static int __initdata bpp = 8; /* parameter from modprobe */
-static int __initdata stifb_force_bpp[MAX_STI_ROMS];
+static int __initdata stifb_bpp_pref[MAX_STI_ROMS];
/* ------------------- chipset specific functions -------------------------- */
@@ -155,15 +154,15 @@ static int __initdata stifb_force_bpp[MAX_STI_ROMS];
#define REG_44 0x210030
#define REG_45 0x210034
-#define READ_BYTE(fb,reg) __raw_readb((fb)->info.fix.mmio_start + (reg))
-#define READ_WORD(fb,reg) __raw_readl((fb)->info.fix.mmio_start + (reg))
+#define READ_BYTE(fb,reg) gsc_readb((fb)->info.fix.mmio_start + (reg))
+#define READ_WORD(fb,reg) gsc_readl((fb)->info.fix.mmio_start + (reg))
#ifndef DEBUG_STIFB_REGS
# define DEBUG_OFF()
# define DEBUG_ON()
-# define WRITE_BYTE(value,fb,reg) __raw_writeb((value),(fb)->info.fix.mmio_start + (reg))
-# define WRITE_WORD(value,fb,reg) __raw_writel((value),(fb)->info.fix.mmio_start + (reg))
+# define WRITE_BYTE(value,fb,reg) gsc_writeb((value),(fb)->info.fix.mmio_start + (reg))
+# define WRITE_WORD(value,fb,reg) gsc_writel((value),(fb)->info.fix.mmio_start + (reg))
#else
static int debug_on = 1;
# define DEBUG_OFF() debug_on=0
@@ -171,11 +170,11 @@ static int __initdata stifb_force_bpp[MAX_STI_ROMS];
# define WRITE_BYTE(value,fb,reg) do { if (debug_on) \
printk(KERN_DEBUG "%30s: WRITE_BYTE(0x%06x) = 0x%02x (old=0x%02x)\n", \
__FUNCTION__, reg, value, READ_BYTE(fb,reg)); \
- __raw_writeb((value),(fb)->info.fix.mmio_start + (reg)); } while (0)
+ gsc_writeb((value),(fb)->info.fix.mmio_start + (reg)); } while (0)
# define WRITE_WORD(value,fb,reg) do { if (debug_on) \
printk(KERN_DEBUG "%30s: WRITE_WORD(0x%06x) = 0x%08x (old=0x%08x)\n", \
__FUNCTION__, reg, value, READ_WORD(fb,reg)); \
- __raw_writel((value),(fb)->info.fix.mmio_start + (reg)); } while (0)
+ gsc_writel((value),(fb)->info.fix.mmio_start + (reg)); } while (0)
#endif /* DEBUG_STIFB_REGS */
@@ -1018,6 +1017,15 @@ 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;
+ }
+
WRITE_IMAGE_COLOR(fb, regno, color);
if (fb->id == S9000_ID_HCRX) {
@@ -1031,14 +1039,6 @@ stifb_setcolreg(u_int regno, u_int red, u_int green,
/* 0x100 is same as used in WRITE_IMAGE_COLOR() */
START_COLORMAPLOAD(fb, lutBltCtl.all);
SETUP_FB(fb);
-
- /* info->var.bits_per_pixel == 32 */
- if (regno < 16)
- ((u32 *)(info->pseudo_palette))[regno] =
- (red << info->var.red.offset) |
- (green << info->var.green.offset) |
- (blue << info->var.blue.offset);
-
} else {
/* cleanup colormap hardware */
FINISH_IMAGE_COLORMAP_ACCESS(fb);
@@ -1156,7 +1156,7 @@ static struct fb_ops stifb_ops = {
*/
int __init
-stifb_init_fb(struct sti_struct *sti, int force_bpp)
+stifb_init_fb(struct sti_struct *sti, int bpp_pref)
{
struct fb_fix_screeninfo *fix;
struct fb_var_screeninfo *var;
@@ -1257,10 +1257,10 @@ stifb_init_fb(struct sti_struct *sti, int force_bpp)
#ifdef __LP64__
sti_rom_address |= 0xffffffff00000000;
#endif
- fb->deviceSpecificConfig = __raw_readl(sti_rom_address);
+ fb->deviceSpecificConfig = gsc_readl(sti_rom_address);
if (IS_24_DEVICE(fb)) {
- if (force_bpp == 8 || force_bpp == 32)
- bpp = force_bpp;
+ if (bpp_pref == 8 || bpp_pref == 32)
+ bpp = bpp_pref;
else
bpp = 32;
} else
@@ -1409,21 +1409,24 @@ stifb_init(void)
def_sti = sti_get_rom(0);
if (def_sti) {
- for (i = 1; i < MAX_STI_ROMS; i++) {
+ for (i = 1; i <= MAX_STI_ROMS; i++) {
sti = sti_get_rom(i);
- if (sti == def_sti && bpp > 0)
- stifb_force_bpp[i] = bpp;
+ if (!sti)
+ break;
+ if (sti == def_sti) {
+ stifb_init_fb(sti, stifb_bpp_pref[i - 1]);
+ break;
+ }
}
- stifb_init_fb(def_sti, stifb_force_bpp[i]);
}
- for (i = 1; i < MAX_STI_ROMS; i++) {
+ for (i = 1; i <= MAX_STI_ROMS; i++) {
sti = sti_get_rom(i);
- if (!sti || sti==def_sti)
+ if (!sti)
break;
- if (bpp > 0)
- stifb_force_bpp[i] = bpp;
- stifb_init_fb(sti, stifb_force_bpp[i]);
+ if (sti == def_sti)
+ continue;
+ stifb_init_fb(sti, stifb_bpp_pref[i - 1]);
}
return 0;
}
@@ -1438,7 +1441,7 @@ stifb_cleanup(void)
struct sti_struct *sti;
int i;
- for (i = 1; i < MAX_STI_ROMS; i++) {
+ for (i = 1; i <= MAX_STI_ROMS; i++) {
sti = sti_get_rom(i);
if (!sti)
break;
@@ -1470,11 +1473,9 @@ stifb_setup(char *options)
if (strncmp(options, "bpp", 3) == 0) {
options += 3;
for (i = 0; i < MAX_STI_ROMS; i++) {
- if (*options++ == ':') {
- stifb_force_bpp[i] = simple_strtoul(options, &options, 10);
- bpp = -1;
- } else
+ if (*options++ != ':')
break;
+ stifb_bpp_pref[i] = simple_strtoul(options, &options, 10);
}
}
return 0;
diff --git a/drivers/video/sun3fb.c b/drivers/video/sun3fb.c
index bfed02b7aa293..9b36b9df535f2 100644
--- a/drivers/video/sun3fb.c
+++ b/drivers/video/sun3fb.c
@@ -505,7 +505,7 @@ void sun3fb_palette(int enter)
if (fb->restore_palette) {
if (enter)
fb->restore_palette(fb);
- else if (vt_cons[i]->vc_mode != KD_GRAPHICS)
+ else if (vc_cons[i].d->vc_mode != KD_GRAPHICS)
vc_cons[i].d->vc_sw->con_set_palette(vc_cons[i].d, color_table);
}
}
diff --git a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c
index 4e509d6821289..c34ba39b6f7e7 100644
--- a/drivers/video/tdfxfb.c
+++ b/drivers/video/tdfxfb.c
@@ -89,7 +89,7 @@
#define VOODOO3_MAX_PIXCLOCK 300000
#define VOODOO5_MAX_PIXCLOCK 350000
-static struct fb_fix_screeninfo tdfx_fix __initdata = {
+static struct fb_fix_screeninfo tdfx_fix __devinitdata = {
.id = "3Dfx",
.type = FB_TYPE_PACKED_PIXELS,
.visual = FB_VISUAL_PSEUDOCOLOR,
@@ -98,7 +98,7 @@ static struct fb_fix_screeninfo tdfx_fix __initdata = {
.accel = FB_ACCEL_3DFX_BANSHEE
};
-static struct fb_var_screeninfo tdfx_var __initdata = {
+static struct fb_var_screeninfo tdfx_var __devinitdata = {
/* "640x480, 8 bpp @ 60 Hz */
.xres = 640,
.yres = 480,
@@ -154,9 +154,6 @@ MODULE_DEVICE_TABLE(pci, tdfxfb_id_table);
/*
* Frame buffer device API
*/
-int tdfxfb_init(void);
-void tdfxfb_setup(char *options);
-
static int tdfxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fb);
static int tdfxfb_set_par(struct fb_info *info);
static int tdfxfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
@@ -202,7 +199,7 @@ static unsigned long do_lfb_size(struct tdfx_par *par, unsigned short);
*/
static int nopan = 0;
static int nowrap = 1; // not implemented (yet)
-static char *mode_option __initdata = NULL;
+static char *mode_option __devinitdata = NULL;
/* -------------------------------------------------------------------------
* Hardware-specific funcions
@@ -1292,6 +1289,28 @@ out_err:
return -ENXIO;
}
+#ifndef MODULE
+void tdfxfb_setup(char *options)
+{
+ char* this_opt;
+
+ if (!options || !*options)
+ return;
+
+ while ((this_opt = strsep(&options, ",")) != NULL) {
+ if (!*this_opt)
+ continue;
+ if(!strcmp(this_opt, "nopan")) {
+ nopan = 1;
+ } else if(!strcmp(this_opt, "nowrap")) {
+ nowrap = 1;
+ } else {
+ mode_option = this_opt;
+ }
+ }
+}
+#endif
+
/**
* tdfxfb_remove - Device removal
*
@@ -1321,7 +1340,7 @@ static void __devexit tdfxfb_remove(struct pci_dev *pdev)
framebuffer_release(info);
}
-int __init tdfxfb_init(void)
+static int __init tdfxfb_init(void)
{
#ifndef MODULE
char *option = NULL;
@@ -1331,7 +1350,7 @@ int __init tdfxfb_init(void)
tdfxfb_setup(option);
#endif
- return pci_module_init(&tdfxfb_driver);
+ return pci_register_driver(&tdfxfb_driver);
}
static void __exit tdfxfb_exit(void)
@@ -1345,27 +1364,3 @@ MODULE_LICENSE("GPL");
module_init(tdfxfb_init);
module_exit(tdfxfb_exit);
-
-
-#ifndef MODULE
-void tdfxfb_setup(char *options)
-{
- char* this_opt;
-
- if (!options || !*options)
- return;
-
- while ((this_opt = strsep(&options, ",")) != NULL) {
- if (!*this_opt)
- continue;
- if(!strcmp(this_opt, "nopan")) {
- nopan = 1;
- } else if(!strcmp(this_opt, "nowrap")) {
- nowrap = 1;
- } else {
- mode_option = this_opt;
- }
- }
-}
-#endif
-
diff --git a/drivers/video/tgafb.c b/drivers/video/tgafb.c
index 075c66de9af0e..3099630d0c3d0 100644
--- a/drivers/video/tgafb.c
+++ b/drivers/video/tgafb.c
@@ -1540,7 +1540,7 @@ tgafb_init(void)
return -ENODEV;
tgafb_setup(option);
#endif
- return pci_module_init(&tgafb_driver);
+ return pci_register_driver(&tgafb_driver);
}
/*
diff --git a/drivers/video/tridentfb.c b/drivers/video/tridentfb.c
index 42e18fda51dcf..da8004e5d03de 100644
--- a/drivers/video/tridentfb.c
+++ b/drivers/video/tridentfb.c
@@ -31,7 +31,7 @@ struct tridentfb_par {
void __iomem * io_virt; //iospace virtual memory address
};
-unsigned char eng_oper; //engine operation...
+static unsigned char eng_oper; //engine operation...
static struct fb_ops tridentfb_ops;
static struct tridentfb_par default_par;
@@ -91,7 +91,7 @@ module_param(crt, int, 0);
static int chip3D;
static int chipcyber;
-int is3Dchip(int id)
+static int is3Dchip(int id)
{
return ((id == BLADE3D) || (id == CYBERBLADEE4) ||
(id == CYBERBLADEi7) || (id == CYBERBLADEi7D) ||
@@ -104,7 +104,7 @@ int is3Dchip(int id)
(id == CYBERBLADEXPAi1));
}
-int iscyber(int id)
+static int iscyber(int id)
{
switch (id) {
case CYBER9388:
@@ -1163,7 +1163,7 @@ static int __devinit trident_pci_probe(struct pci_dev * dev, const struct pci_de
fb_info.var = default_var;
fb_info.device = &dev->dev;
if (register_framebuffer(&fb_info) < 0) {
- output("Could not register Trident framebuffer\n");
+ printk(KERN_ERR "tridentfb: could not register Trident framebuffer\n");
return -EINVAL;
}
output("fb%d: %s frame buffer device %dx%d-%dbpp\n",
@@ -1216,33 +1216,13 @@ static struct pci_driver tridentfb_pci_driver = {
.remove = __devexit_p(trident_pci_remove)
};
-int tridentfb_setup(char *options);
-
-int __init tridentfb_init(void)
-{
-#ifndef MODULE
- char *option = NULL;
-
- if (fb_get_options("tridentfb", &option))
- return -ENODEV;
- tridentfb_setup(option);
-#endif
- output("Trident framebuffer %s initializing\n", VERSION);
- return pci_module_init(&tridentfb_pci_driver);
-}
-
-void __exit tridentfb_exit(void)
-{
- pci_unregister_driver(&tridentfb_pci_driver);
-}
-
-
/*
* Parse user specified options (`video=trident:')
* example:
* video=trident:800x600,bpp=16,noaccel
*/
-int tridentfb_setup(char *options)
+#ifndef MODULE
+static int tridentfb_setup(char *options)
{
char * opt;
if (!options || !*options)
@@ -1272,6 +1252,25 @@ int tridentfb_setup(char *options)
}
return 0;
}
+#endif
+
+static int __init tridentfb_init(void)
+{
+#ifndef MODULE
+ char *option = NULL;
+
+ if (fb_get_options("tridentfb", &option))
+ return -ENODEV;
+ tridentfb_setup(option);
+#endif
+ output("Trident framebuffer %s initializing\n", VERSION);
+ return pci_register_driver(&tridentfb_pci_driver);
+}
+
+static void __exit tridentfb_exit(void)
+{
+ pci_unregister_driver(&tridentfb_pci_driver);
+}
static struct fb_ops tridentfb_ops = {
.owner = THIS_MODULE,
diff --git a/drivers/video/vesafb.c b/drivers/video/vesafb.c
index ab2f5c3c1d2dd..8fc1278d7fbdd 100644
--- a/drivers/video/vesafb.c
+++ b/drivers/video/vesafb.c
@@ -185,7 +185,7 @@ static struct fb_ops vesafb_ops = {
.fb_cursor = soft_cursor,
};
-int __init vesafb_setup(char *options)
+static int __init vesafb_setup(char *options)
{
char *this_opt;
@@ -434,7 +434,7 @@ static struct platform_device vesafb_device = {
.name = "vesafb",
};
-int __init vesafb_init(void)
+static int __init vesafb_init(void)
{
int ret;
char *option = NULL;
@@ -453,12 +453,4 @@ int __init vesafb_init(void)
}
module_init(vesafb_init);
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
-
MODULE_LICENSE("GPL");
diff --git a/drivers/video/vfb.c b/drivers/video/vfb.c
index 2a2a765c63210..b137a3fe07525 100644
--- a/drivers/video/vfb.c
+++ b/drivers/video/vfb.c
@@ -72,12 +72,6 @@ static struct fb_fix_screeninfo vfb_fix __initdata = {
static int vfb_enable __initdata = 0; /* disabled by default */
module_param(vfb_enable, bool, 0);
- /*
- * Interface used by the world
- */
-int vfb_init(void);
-int vfb_setup(char *);
-
static int vfb_check_var(struct fb_var_screeninfo *var,
struct fb_info *info);
static int vfb_set_par(struct fb_info *info);
@@ -379,7 +373,8 @@ static int vfb_mmap(struct fb_info *info, struct file *file,
return -EINVAL;
}
-int __init vfb_setup(char *options)
+#ifndef MODULE
+static int __init vfb_setup(char *options)
{
char *this_opt;
@@ -396,6 +391,7 @@ int __init vfb_setup(char *options)
}
return 1;
}
+#endif /* MODULE */
/*
* Initialisation
@@ -492,7 +488,7 @@ static struct platform_device vfb_device = {
}
};
-int __init vfb_init(void)
+static int __init vfb_init(void)
{
int ret = 0;
diff --git a/drivers/video/vga16fb.c b/drivers/video/vga16fb.c
index 4e508df8212eb..b46454c55c91b 100644
--- a/drivers/video/vga16fb.c
+++ b/drivers/video/vga16fb.c
@@ -874,7 +874,7 @@ static int vga16fb_blank(int blank, struct fb_info *info)
return 0;
}
-void vga_8planes_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+static void vga_8planes_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
{
u32 dx = rect->dx, width = rect->width;
char oldindex = getindex();
@@ -928,7 +928,7 @@ void vga_8planes_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
setindex(oldindex);
}
-void vga16fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+static void vga16fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
{
int x, x2, y2, vxres, vyres, width, height, line_ofs;
char __iomem *dst;
@@ -1003,7 +1003,7 @@ void vga16fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
}
}
-void vga_8planes_copyarea(struct fb_info *info, const struct fb_copyarea *area)
+static void vga_8planes_copyarea(struct fb_info *info, const struct fb_copyarea *area)
{
char oldindex = getindex();
char oldmode = setmode(0x41);
@@ -1058,7 +1058,7 @@ void vga_8planes_copyarea(struct fb_info *info, const struct fb_copyarea *area)
setindex(oldindex);
}
-void vga16fb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
+static void vga16fb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
{
u32 dx = area->dx, dy = area->dy, sx = area->sx, sy = area->sy;
int x, x2, y2, old_dx, old_dy, vxres, vyres;
@@ -1166,7 +1166,7 @@ static unsigned int transl_l[] =
#endif
#endif
-void vga_8planes_imageblit(struct fb_info *info, const struct fb_image *image)
+static void vga_8planes_imageblit(struct fb_info *info, const struct fb_image *image)
{
char oldindex = getindex();
char oldmode = setmode(0x40);
@@ -1197,7 +1197,7 @@ void vga_8planes_imageblit(struct fb_info *info, const struct fb_image *image)
setindex(oldindex);
}
-void vga_imageblit_expand(struct fb_info *info, const struct fb_image *image)
+static void vga_imageblit_expand(struct fb_info *info, const struct fb_image *image)
{
char __iomem *where = info->screen_base + (image->dx/8) +
image->dy * info->fix.line_length;
@@ -1261,7 +1261,7 @@ void vga_imageblit_expand(struct fb_info *info, const struct fb_image *image)
}
}
-void vga_imageblit_color(struct fb_info *info, const struct fb_image *image)
+static void vga_imageblit_color(struct fb_info *info, const struct fb_image *image)
{
/*
* Draw logo
@@ -1306,7 +1306,7 @@ void vga_imageblit_color(struct fb_info *info, const struct fb_image *image)
}
}
-void vga16fb_imageblit(struct fb_info *info, const struct fb_image *image)
+static void vga16fb_imageblit(struct fb_info *info, const struct fb_image *image)
{
if (image->depth == 1)
vga_imageblit_expand(info, image);
@@ -1329,7 +1329,8 @@ static struct fb_ops vga16fb_ops = {
.fb_cursor = soft_cursor,
};
-int vga16fb_setup(char *options)
+#ifndef MODULE
+static int vga16fb_setup(char *options)
{
char *this_opt;
@@ -1341,8 +1342,9 @@ int vga16fb_setup(char *options)
}
return 0;
}
+#endif
-int __init vga16fb_init(void)
+static int __init vga16fb_init(void)
{
int i;
int ret;
@@ -1427,9 +1429,7 @@ static void __exit vga16fb_exit(void)
/* XXX unshare VGA regions */
}
-#ifdef MODULE
MODULE_LICENSE("GPL");
-#endif
module_init(vga16fb_init);
module_exit(vga16fb_exit);
diff --git a/drivers/video/w100fb.c b/drivers/video/w100fb.c
index e118285293298..057e154c8858d 100644
--- a/drivers/video/w100fb.c
+++ b/drivers/video/w100fb.c
@@ -22,7 +22,6 @@
#include <linux/device.h>
#include <linux/string.h>
#include <linux/proc_fs.h>
-#include <linux/vmalloc.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <video/w100fb.h>
@@ -90,8 +89,6 @@ struct w100fb_par {
static struct w100fb_par *current_par;
-static u16 *gSaveImagePtr = NULL;
-
/* Remapped addresses for base cfg, memmapped regs and the frame buffer itself */
static void *remapped_base;
static void *remapped_regs;
@@ -494,42 +491,54 @@ static void w100fb_clear_screen(u32 mode, long int offset)
}
+/* Need to split up the buffers to stay within the limits of kmalloc */
+#define W100_BUF_NUM 6
+static uint32_t *gSaveImagePtr[W100_BUF_NUM] = { NULL };
+
static void w100fb_save_buffer(void)
{
- int i;
-
- if (gSaveImagePtr != NULL) {
- vfree(gSaveImagePtr);
- gSaveImagePtr = NULL;
- }
- gSaveImagePtr = vmalloc(current_par->xres * current_par->yres * BITS_PER_PIXEL / 8);
- if (gSaveImagePtr != NULL) {
- for (i = 0; i < (current_par->xres * current_par->yres); i++)
- *(gSaveImagePtr + i) = readw(remapped_fbuf + (2*i));
- } else {
- printk(KERN_WARNING "can't alloc pre-off image buffer\n");
+ int i, j, bufsize;
+
+ bufsize=(current_par->xres * current_par->yres * BITS_PER_PIXEL / 8) / W100_BUF_NUM;
+ for (i = 0; i < W100_BUF_NUM; i++) {
+ if (gSaveImagePtr[i] == NULL)
+ gSaveImagePtr[i] = kmalloc(bufsize, GFP_KERNEL);
+ if (gSaveImagePtr[i] == NULL) {
+ w100fb_clear_buffer();
+ printk(KERN_WARNING "can't alloc pre-off image buffer %d\n", i);
+ break;
+ }
+ for (j = 0; j < bufsize/4; j++)
+ *(gSaveImagePtr[i] + j) = readl(remapped_fbuf + (bufsize*i) + j*4);
}
}
static void w100fb_restore_buffer(void)
{
- int i;
+ int i, j, bufsize;
- if (gSaveImagePtr != NULL) {
- for (i = 0; i < (current_par->xres * current_par->yres); i++) {
- writew(*(gSaveImagePtr + i),remapped_fbuf + (2*i));
- }
- vfree(gSaveImagePtr);
- gSaveImagePtr = NULL;
+ bufsize=(current_par->xres * current_par->yres * BITS_PER_PIXEL / 8) / W100_BUF_NUM;
+ for (i = 0; i < W100_BUF_NUM; i++) {
+ if (gSaveImagePtr[i] == NULL) {
+ printk(KERN_WARNING "can't find pre-off image buffer %d\n", i);
+ w100fb_clear_buffer();
+ break;
+ }
+ for (j = 0; j < (bufsize/4); j++)
+ writel(*(gSaveImagePtr[i] + j),remapped_fbuf + (bufsize*i) + (j*4));
+ kfree(gSaveImagePtr[i]);
+ gSaveImagePtr[i] = NULL;
}
}
+
static void w100fb_clear_buffer(void)
{
- if (gSaveImagePtr != NULL) {
- vfree(gSaveImagePtr);
- gSaveImagePtr = NULL;
+ int i;
+ for (i = 0; i < W100_BUF_NUM; i++) {
+ kfree(gSaveImagePtr[i]);
+ gSaveImagePtr[i] = NULL;
}
}
diff --git a/drivers/w1/dscore.c b/drivers/w1/dscore.c
index 284f378bb1b19..eee6644d33d6e 100644
--- a/drivers/w1/dscore.c
+++ b/drivers/w1/dscore.c
@@ -45,9 +45,6 @@ int ds_set_speed(struct ds_device *, int);
int ds_reset(struct ds_device *, struct ds_status *);
int ds_detect(struct ds_device *, struct ds_status *);
int ds_stop_pulse(struct ds_device *, int);
-int ds_send_data(struct ds_device *, unsigned char *, int);
-int ds_recv_data(struct ds_device *, unsigned char *, int);
-int ds_recv_status(struct ds_device *, struct ds_status *);
struct ds_device * ds_get_device(void);
void ds_put_device(struct ds_device *);
@@ -84,7 +81,7 @@ static int ds_send_control_cmd(struct ds_device *dev, u16 value, u16 index)
int err;
err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]),
- CONTROL_CMD, 0x40, value, index, NULL, 0, HZ);
+ CONTROL_CMD, 0x40, value, index, NULL, 0, 1000);
if (err < 0) {
printk(KERN_ERR "Failed to send command control message %x.%x: err=%d.\n",
value, index, err);
@@ -99,7 +96,7 @@ static int ds_send_control_mode(struct ds_device *dev, u16 value, u16 index)
int err;
err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]),
- MODE_CMD, 0x40, value, index, NULL, 0, HZ);
+ MODE_CMD, 0x40, value, index, NULL, 0, 1000);
if (err < 0) {
printk(KERN_ERR "Failed to send mode control message %x.%x: err=%d.\n",
value, index, err);
@@ -114,7 +111,7 @@ static int ds_send_control(struct ds_device *dev, u16 value, u16 index)
int err;
err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]),
- COMM_CMD, 0x40, value, index, NULL, 0, HZ);
+ COMM_CMD, 0x40, value, index, NULL, 0, 1000);
if (err < 0) {
printk(KERN_ERR "Failed to send control message %x.%x: err=%d.\n",
value, index, err);
@@ -148,7 +145,7 @@ int ds_recv_status_nodump(struct ds_device *dev, struct ds_status *st, unsigned
return count;
}
-int ds_recv_status(struct ds_device *dev, struct ds_status *st)
+static int ds_recv_status(struct ds_device *dev, struct ds_status *st)
{
unsigned char buf[64];
int count, err = 0, i;
@@ -206,14 +203,14 @@ int ds_recv_status(struct ds_device *dev, struct ds_status *st)
return err;
}
-int ds_recv_data(struct ds_device *dev, unsigned char *buf, int size)
+static int ds_recv_data(struct ds_device *dev, unsigned char *buf, int size)
{
int count, err;
struct ds_status st;
count = 0;
err = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN]),
- buf, size, &count, HZ);
+ buf, size, &count, 1000);
if (err < 0) {
printk(KERN_INFO "Clearing ep0x%x.\n", dev->ep[EP_DATA_IN]);
usb_clear_halt(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN]));
@@ -234,12 +231,12 @@ int ds_recv_data(struct ds_device *dev, unsigned char *buf, int size)
return count;
}
-int ds_send_data(struct ds_device *dev, unsigned char *buf, int len)
+static int ds_send_data(struct ds_device *dev, unsigned char *buf, int len)
{
int count, err;
count = 0;
- err = usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, dev->ep[EP_DATA_OUT]), buf, len, &count, HZ);
+ err = usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, dev->ep[EP_DATA_OUT]), buf, len, &count, 1000);
if (err < 0) {
printk(KERN_ERR "Failed to read 1-wire data from 0x02: err=%d.\n", err);
return err;
@@ -774,15 +771,19 @@ EXPORT_SYMBOL(ds_read_block);
EXPORT_SYMBOL(ds_write_byte);
EXPORT_SYMBOL(ds_write_bit);
EXPORT_SYMBOL(ds_write_block);
+EXPORT_SYMBOL(ds_reset);
+EXPORT_SYMBOL(ds_get_device);
+EXPORT_SYMBOL(ds_put_device);
+
+/*
+ * This functions can be used for EEPROM programming,
+ * when driver will be included into mainline this will
+ * require uncommenting.
+ */
+#if 0
EXPORT_SYMBOL(ds_start_pulse);
EXPORT_SYMBOL(ds_set_speed);
-EXPORT_SYMBOL(ds_reset);
EXPORT_SYMBOL(ds_detect);
EXPORT_SYMBOL(ds_stop_pulse);
-EXPORT_SYMBOL(ds_send_data);
-EXPORT_SYMBOL(ds_recv_data);
-EXPORT_SYMBOL(ds_recv_status);
EXPORT_SYMBOL(ds_search);
-EXPORT_SYMBOL(ds_get_device);
-EXPORT_SYMBOL(ds_put_device);
-
+#endif
diff --git a/drivers/w1/dscore.h b/drivers/w1/dscore.h
index f30b438fe3a34..9c767ef4ac248 100644
--- a/drivers/w1/dscore.h
+++ b/drivers/w1/dscore.h
@@ -161,9 +161,6 @@ int ds_set_speed(struct ds_device *, int);
int ds_reset(struct ds_device *, struct ds_status *);
int ds_detect(struct ds_device *, struct ds_status *);
int ds_stop_pulse(struct ds_device *, int);
-int ds_send_data(struct ds_device *, unsigned char *, int);
-int ds_recv_data(struct ds_device *, unsigned char *, int);
-int ds_recv_status(struct ds_device *, struct ds_status *);
struct ds_device * ds_get_device(void);
void ds_put_device(struct ds_device *);
int ds_write_block(struct ds_device *, u8 *, int);
diff --git a/drivers/w1/matrox_w1.c b/drivers/w1/matrox_w1.c
index a219fd5855134..e565416458ead 100644
--- a/drivers/w1/matrox_w1.c
+++ b/drivers/w1/matrox_w1.c
@@ -235,7 +235,7 @@ static void __devexit matrox_w1_remove(struct pci_dev *pdev)
static int __init matrox_w1_init(void)
{
- return pci_module_init(&matrox_w1_pci_driver);
+ return pci_register_driver(&matrox_w1_pci_driver);
}
static void __exit matrox_w1_fini(void)
diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c
index 731ca8409edb5..fd630cec0e791 100644
--- a/drivers/w1/w1.c
+++ b/drivers/w1/w1.c
@@ -19,8 +19,6 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include <asm/atomic.h>
-
#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/module.h>
@@ -33,6 +31,8 @@
#include <linux/slab.h>
#include <linux/sched.h>
+#include <asm/atomic.h>
+
#include "w1.h"
#include "w1_io.h"
#include "w1_log.h"
@@ -58,7 +58,6 @@ LIST_HEAD(w1_masters);
static pid_t control_thread;
static int control_needs_exit;
static DECLARE_COMPLETION(w1_control_complete);
-static DECLARE_WAIT_QUEUE_HEAD(w1_control_wait);
static int w1_master_match(struct device *dev, struct device_driver *drv)
{
@@ -100,7 +99,7 @@ static ssize_t w1_default_read_bin(struct kobject *kobj, char *buf, loff_t off,
return sprintf(buf, "No family registered.\n");
}
-struct bus_type w1_bus_type = {
+static struct bus_type w1_bus_type = {
.name = "w1",
.match = w1_master_match,
};
@@ -138,7 +137,7 @@ static struct device_attribute w1_slave_attribute_val = {
.show = &w1_default_read_name,
};
-ssize_t w1_master_attribute_show_name(struct device *dev, char *buf)
+static ssize_t w1_master_attribute_show_name(struct device *dev, char *buf)
{
struct w1_master *md = container_of (dev, struct w1_master, dev);
ssize_t count;
@@ -153,7 +152,7 @@ ssize_t w1_master_attribute_show_name(struct device *dev, char *buf)
return count;
}
-ssize_t w1_master_attribute_show_pointer(struct device *dev, char *buf)
+static ssize_t w1_master_attribute_show_pointer(struct device *dev, char *buf)
{
struct w1_master *md = container_of(dev, struct w1_master, dev);
ssize_t count;
@@ -167,14 +166,14 @@ ssize_t w1_master_attribute_show_pointer(struct device *dev, char *buf)
return count;
}
-ssize_t w1_master_attribute_show_timeout(struct device *dev, char *buf)
+static ssize_t w1_master_attribute_show_timeout(struct device *dev, char *buf)
{
ssize_t count;
count = sprintf(buf, "%d\n", w1_timeout);
return count;
}
-ssize_t w1_master_attribute_show_max_slave_count(struct device *dev, char *buf)
+static ssize_t w1_master_attribute_show_max_slave_count(struct device *dev, char *buf)
{
struct w1_master *md = container_of(dev, struct w1_master, dev);
ssize_t count;
@@ -188,7 +187,7 @@ ssize_t w1_master_attribute_show_max_slave_count(struct device *dev, char *buf)
return count;
}
-ssize_t w1_master_attribute_show_attempts(struct device *dev, char *buf)
+static ssize_t w1_master_attribute_show_attempts(struct device *dev, char *buf)
{
struct w1_master *md = container_of(dev, struct w1_master, dev);
ssize_t count;
@@ -202,7 +201,7 @@ ssize_t w1_master_attribute_show_attempts(struct device *dev, char *buf)
return count;
}
-ssize_t w1_master_attribute_show_slave_count(struct device *dev, char *buf)
+static ssize_t w1_master_attribute_show_slave_count(struct device *dev, char *buf)
{
struct w1_master *md = container_of(dev, struct w1_master, dev);
ssize_t count;
@@ -216,7 +215,7 @@ ssize_t w1_master_attribute_show_slave_count(struct device *dev, char *buf)
return count;
}
-ssize_t w1_master_attribute_show_slaves(struct device *dev, char *buf)
+static ssize_t w1_master_attribute_show_slaves(struct device *dev, char *buf)
{
struct w1_master *md = container_of(dev, struct w1_master, dev);
@@ -413,7 +412,8 @@ static int w1_attach_slave_device(struct w1_master *dev, struct w1_reg_num *rn)
if (!f) {
spin_unlock(&w1_flock);
dev_info(&dev->dev, "Family %x for %02x.%012llx.%02x is not registered.\n",
- rn->family, rn->family, rn->id, rn->crc);
+ rn->family, rn->family,
+ (unsigned long long)rn->id, rn->crc);
kfree(sl);
return -ENODEV;
}
@@ -522,9 +522,10 @@ void w1_slave_found(unsigned long data, u64 rn)
slave_count++;
}
- if (slave_count == dev->slave_count &&
- rn && ((rn >> 56) & 0xff) == w1_calc_crc8((u8 *)&rn, 7)) {
- w1_attach_slave_device(dev, (struct w1_reg_num *) &rn);
+ if (slave_count == dev->slave_count && rn ) {
+ tmp = cpu_to_le64(rn);
+ if(((rn >> 56) & 0xff) == w1_calc_crc8((u8 *)&tmp, 7))
+ w1_attach_slave_device(dev, (struct w1_reg_num *) &rn);
}
atomic_dec(&dev->refcnt);
@@ -649,7 +650,7 @@ int w1_control(void *data)
struct w1_slave *sl;
struct w1_master *dev;
struct list_head *ent, *ment, *n, *mn;
- int err, have_to_wait = 0, timeout;
+ int err, have_to_wait = 0;
daemonize("w1_control");
allow_signal(SIGTERM);
@@ -657,11 +658,8 @@ int w1_control(void *data)
while (!control_needs_exit || have_to_wait) {
have_to_wait = 0;
- timeout = w1_timeout*HZ;
- do {
- timeout = interruptible_sleep_on_timeout(&w1_control_wait, timeout);
- try_to_freeze(PF_FREEZE);
- } while (!signal_pending(current) && (timeout > 0));
+ try_to_freeze(PF_FREEZE);
+ msleep_interruptible(w1_timeout * 1000);
if (signal_pending(current))
flush_signals(current);
@@ -721,7 +719,6 @@ int w1_control(void *data)
int w1_process(void *data)
{
struct w1_master *dev = (struct w1_master *) data;
- unsigned long timeout;
struct list_head *ent, *n;
struct w1_slave *sl;
@@ -729,11 +726,8 @@ int w1_process(void *data)
allow_signal(SIGTERM);
while (!dev->need_exit) {
- timeout = w1_timeout*HZ;
- do {
- timeout = interruptible_sleep_on_timeout(&dev->kwait, timeout);
- try_to_freeze(PF_FREEZE);
- } while (!signal_pending(current) && (timeout > 0));
+ try_to_freeze(PF_FREEZE);
+ msleep_interruptible(w1_timeout * 1000);
if (signal_pending(current))
flush_signals(current);
@@ -839,6 +833,3 @@ void w1_fini(void)
module_init(w1_init);
module_exit(w1_fini);
-
-EXPORT_SYMBOL(w1_create_master_attributes);
-EXPORT_SYMBOL(w1_destroy_master_attributes);
diff --git a/drivers/w1/w1.h b/drivers/w1/w1.h
index 0abbcfdffed86..abbddaf3f8e28 100644
--- a/drivers/w1/w1.h
+++ b/drivers/w1/w1.h
@@ -24,9 +24,17 @@
struct w1_reg_num
{
+#if defined(__LITTLE_ENDIAN_BITFIELD)
__u64 family:8,
id:48,
crc:8;
+#elif defined(__BIG_ENDIAN_BITFIELD)
+ __u64 crc:8,
+ id:48,
+ family:8;
+#else
+#error "Please fix <asm/byteorder.h>"
+#endif
};
#ifdef __KERNEL__
@@ -115,7 +123,6 @@ struct w1_master
int need_exit;
pid_t kpid;
- wait_queue_head_t kwait;
struct semaphore mutex;
struct device_driver *driver;
diff --git a/drivers/w1/w1_family.c b/drivers/w1/w1_family.c
index ccde36d0fed55..d1d56eca1061c 100644
--- a/drivers/w1/w1_family.c
+++ b/drivers/w1/w1_family.c
@@ -138,13 +138,13 @@ void w1_family_get(struct w1_family *f)
void __w1_family_get(struct w1_family *f)
{
+ smp_mb__before_atomic_inc();
atomic_inc(&f->refcnt);
+ smp_mb__after_atomic_inc();
}
EXPORT_SYMBOL(w1_family_get);
EXPORT_SYMBOL(w1_family_put);
-EXPORT_SYMBOL(__w1_family_get);
-EXPORT_SYMBOL(__w1_family_put);
EXPORT_SYMBOL(w1_family_registered);
EXPORT_SYMBOL(w1_unregister_family);
EXPORT_SYMBOL(w1_register_family);
diff --git a/drivers/w1/w1_int.c b/drivers/w1/w1_int.c
index 7497ac731334b..5f0bafbbd5753 100644
--- a/drivers/w1/w1_int.c
+++ b/drivers/w1/w1_int.c
@@ -74,7 +74,6 @@ struct w1_master * w1_alloc_dev(u32 id, int slave_count, int slave_ttl,
INIT_LIST_HEAD(&dev->slist);
init_MUTEX(&dev->mutex);
- init_waitqueue_head(&dev->kwait);
init_completion(&dev->dev_released);
init_completion(&dev->dev_exited);
@@ -217,8 +216,5 @@ void w1_remove_master_device(struct w1_bus_master *bm)
__w1_remove_master_device(dev);
}
-EXPORT_SYMBOL(w1_alloc_dev);
-EXPORT_SYMBOL(w1_free_dev);
EXPORT_SYMBOL(w1_add_master_device);
EXPORT_SYMBOL(w1_remove_master_device);
-EXPORT_SYMBOL(__w1_remove_master_device);
diff --git a/drivers/w1/w1_therm.c b/drivers/w1/w1_therm.c
index 8ca23df9da7b0..0b18178905034 100644
--- a/drivers/w1/w1_therm.c
+++ b/drivers/w1/w1_therm.c
@@ -26,6 +26,7 @@
#include <linux/moduleparam.h>
#include <linux/device.h>
#include <linux/types.h>
+#include <linux/delay.h>
#include "w1.h"
#include "w1_io.h"
@@ -103,6 +104,7 @@ static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, si
int i, max_trying = 10;
atomic_inc(&sl->refcnt);
+ smp_mb__after_atomic_inc();
if (down_interruptible(&sl->master->mutex)) {
count = 0;
goto out_dec;
@@ -128,7 +130,7 @@ static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, si
if (!w1_reset_bus (dev)) {
int count = 0;
u8 match[9] = {W1_MATCH_ROM, };
- unsigned long tm;
+ unsigned int tm = 750;
memcpy(&match[1], (u64 *) & sl->reg_num, 8);
@@ -136,11 +138,8 @@ static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, si
w1_write_8(dev, W1_CONVERT_TEMP);
- tm = jiffies + msecs_to_jiffies(750);
- while(time_before(jiffies, tm)) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(tm-jiffies);
-
+ while (tm) {
+ tm = msleep_interruptible(tm);
if (signal_pending(current))
flush_signals(current);
}
@@ -181,6 +180,7 @@ static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, si
out:
up(&dev->mutex);
out_dec:
+ smp_mb__before_atomic_inc();
atomic_dec(&sl->refcnt);
return count;
diff --git a/drivers/zorro/zorro.c b/drivers/zorro/zorro.c
index 6d70b40d3fa58..d3c05dfe20d20 100644
--- a/drivers/zorro/zorro.c
+++ b/drivers/zorro/zorro.c
@@ -134,7 +134,7 @@ static int __init zorro_init(void)
if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(ZORRO))
return 0;
- printk("Zorro: Probing AutoConfig expansion devices: %d device%s\n",
+ pr_info("Zorro: Probing AutoConfig expansion devices: %d device%s\n",
zorro_num_autocon, zorro_num_autocon == 1 ? "" : "s");
/* Initialize the Zorro bus */
diff --git a/fs/Kconfig b/fs/Kconfig
index 4bb214ea133a6..6a4ad4bb7a54e 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -936,6 +936,7 @@ config HFS_FS
config HFSPLUS_FS
tristate "Apple Extended HFS file system support"
select NLS
+ select NLS_UTF8
help
If you say Y here, you will be able to mount extended format
Macintosh-formatted hard drive partitions with full read-write access.
diff --git a/fs/adfs/dir_f.c b/fs/adfs/dir_f.c
index b61648b2d1dda..bbfc862592721 100644
--- a/fs/adfs/dir_f.c
+++ b/fs/adfs/dir_f.c
@@ -65,23 +65,6 @@ static inline int adfs_readname(char *buf, char *ptr, int maxlen)
return buf - old_buf;
}
-static inline void adfs_writename(char *to, char *from, int maxlen)
-{
- int i;
-
- for (i = 0; i < maxlen; i++) {
- if (from[i] == '\0')
- break;
- if (from[i] == '.')
- to[i] = '/';
- else
- to[i] = from[i];
- }
-
- for (; i < maxlen; i++)
- to[i] = '\0';
-}
-
#define ror13(v) ((v >> 13) | (v << 19))
#define dir_u8(idx) \
diff --git a/fs/afs/kafsasyncd.c b/fs/afs/kafsasyncd.c
index e179e17acdc6f..6fc88ae8ad947 100644
--- a/fs/afs/kafsasyncd.c
+++ b/fs/afs/kafsasyncd.c
@@ -116,6 +116,8 @@ static int kafsasyncd(void *arg)
remove_wait_queue(&kafsasyncd_sleepq, &myself);
set_current_state(TASK_RUNNING);
+ try_to_freeze(PF_FREEZE);
+
/* discard pending signals */
afs_discard_my_signals();
diff --git a/fs/afs/kafstimod.c b/fs/afs/kafstimod.c
index e8bbffee58660..86e710dd057e7 100644
--- a/fs/afs/kafstimod.c
+++ b/fs/afs/kafstimod.c
@@ -91,6 +91,8 @@ static int kafstimod(void *arg)
complete_and_exit(&kafstimod_dead, 0);
}
+ try_to_freeze(PF_FREEZE);
+
/* discard pending signals */
afs_discard_my_signals();
diff --git a/fs/afs/main.c b/fs/afs/main.c
index a26979b732bfe..913c689bdb357 100644
--- a/fs/afs/main.c
+++ b/fs/afs/main.c
@@ -29,18 +29,9 @@
struct rxrpc_transport *afs_transport;
-static int afs_init(void);
-static void afs_exit(void);
static int afs_adding_peer(struct rxrpc_peer *peer);
static void afs_discarding_peer(struct rxrpc_peer *peer);
-/* XXX late_initcall is kludgy, but the only alternative seems to create
- * a transport upon the first mount, which is worse. Or is it?
- */
-/* module_init(afs_init); */
-late_initcall(afs_init); /* must be called after net/ to create socket */
-
-module_exit(afs_exit);
MODULE_DESCRIPTION("AFS Client File System");
MODULE_AUTHOR("Red Hat, Inc.");
@@ -76,7 +67,7 @@ struct cachefs_netfs afs_cache_netfs = {
/*
* initialise the AFS client FS module
*/
-static int afs_init(void)
+static int __init afs_init(void)
{
int loop, ret;
@@ -156,6 +147,10 @@ static int afs_init(void)
return ret;
} /* end afs_init() */
+/* XXX late_initcall is kludgy, but the only alternative seems to create
+ * a transport upon the first mount, which is worse. Or is it?
+ */
+late_initcall(afs_init); /* must be called after net/ to create socket */
/*****************************************************************************/
/*
* clean up on module removal
@@ -179,6 +174,8 @@ static void __exit afs_exit(void)
} /* end afs_exit() */
+module_exit(afs_exit);
+
/*****************************************************************************/
/*
* notification that new peer record is being added
diff --git a/fs/aio.c b/fs/aio.c
index 9980002ac3f37..d06a266769bcb 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -1,6 +1,6 @@
/*
* An async IO implementation for Linux
- * Written by Benjamin LaHaise <bcrl@redhat.com>
+ * Written by Benjamin LaHaise <bcrl@kvack.org>
*
* Implements an efficient asynchronous io interface.
*
diff --git a/fs/attr.c b/fs/attr.c
index d8524fc01e109..c3c76fe783464 100644
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -135,14 +135,17 @@ int setattr_mask(unsigned int ia_valid)
int notify_change(struct dentry * dentry, struct iattr * attr)
{
struct inode *inode = dentry->d_inode;
- mode_t mode = inode->i_mode;
+ mode_t mode;
int error;
- struct timespec now = current_fs_time(inode->i_sb);
+ struct timespec now;
unsigned int ia_valid = attr->ia_valid;
if (!inode)
BUG();
+ mode = inode->i_mode;
+ now = current_fs_time(inode->i_sb);
+
attr->ia_ctime = now;
if (!(ia_valid & ATTR_ATIME_SET))
attr->ia_atime = now;
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
index 82ef8ed2fabc0..3765c047f157e 100644
--- a/fs/autofs4/root.c
+++ b/fs/autofs4/root.c
@@ -605,7 +605,9 @@ static int autofs4_dir_rmdir(struct inode *dir, struct dentry *dentry)
spin_unlock(&dcache_lock);
return -ENOTEMPTY;
}
+ spin_lock(&dentry->d_lock);
__d_drop(dentry);
+ spin_unlock(&dentry->d_lock);
spin_unlock(&dcache_lock);
dput(ino->dentry);
diff --git a/fs/autofs4/waitq.c b/fs/autofs4/waitq.c
index b2f2e885d94bd..1ab24a662e09f 100644
--- a/fs/autofs4/waitq.c
+++ b/fs/autofs4/waitq.c
@@ -224,6 +224,7 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
} else {
atomic_inc(&wq->wait_ctr);
up(&sbi->wq_sem);
+ kfree(name);
DPRINTK("existing wait id = 0x%08lx, name = %.*s, nfy=%d",
(unsigned long) wq->wait_queue_token, wq->len, wq->name, notify);
}
diff --git a/fs/bad_inode.c b/fs/bad_inode.c
index 90ce87a582319..672a31924f3cd 100644
--- a/fs/bad_inode.c
+++ b/fs/bad_inode.c
@@ -15,17 +15,6 @@
#include <linux/smp_lock.h>
#include <linux/namei.h>
-/*
- * The follow_link operation is special: it must behave as a no-op
- * so that a bad root inode can at least be unmounted. To do this
- * we must dput() the base and return the dentry with a dget().
- */
-static int bad_follow_link(struct dentry *dent, struct nameidata *nd)
-{
- nd_set_link(nd, ERR_PTR(-EIO));
- return 0;
-}
-
static int return_EIO(void)
{
return -EIO;
@@ -70,7 +59,8 @@ struct inode_operations bad_inode_ops =
.mknod = EIO_ERROR,
.rename = EIO_ERROR,
.readlink = EIO_ERROR,
- .follow_link = bad_follow_link,
+ /* follow_link must be no-op, otherwise unmounting this inode
+ won't work */
.truncate = EIO_ERROR,
.permission = EIO_ERROR,
.getattr = EIO_ERROR,
diff --git a/fs/binfmt_aout.c b/fs/binfmt_aout.c
index a53d9a9e0de4a..009b8920c1fff 100644
--- a/fs/binfmt_aout.c
+++ b/fs/binfmt_aout.c
@@ -148,14 +148,14 @@ static int aout_core_dump(long signr, struct pt_regs * regs, struct file *file)
/* make sure we actually have a data and stack area to dump */
set_fs(USER_DS);
#ifdef __sparc__
- if (verify_area(VERIFY_READ, (void __user *)START_DATA(dump), dump.u_dsize))
+ if (!access_ok(VERIFY_READ, (void __user *)START_DATA(dump), dump.u_dsize))
dump.u_dsize = 0;
- if (verify_area(VERIFY_READ, (void __user *)START_STACK(dump), dump.u_ssize))
+ if (!access_ok(VERIFY_READ, (void __user *)START_STACK(dump), dump.u_ssize))
dump.u_ssize = 0;
#else
- if (verify_area(VERIFY_READ, (void __user *)START_DATA(dump), dump.u_dsize << PAGE_SHIFT))
+ if (!access_ok(VERIFY_READ, (void __user *)START_DATA(dump), dump.u_dsize << PAGE_SHIFT))
dump.u_dsize = 0;
- if (verify_area(VERIFY_READ, (void __user *)START_STACK(dump), dump.u_ssize << PAGE_SHIFT))
+ if (!access_ok(VERIFY_READ, (void __user *)START_STACK(dump), dump.u_ssize << PAGE_SHIFT))
dump.u_ssize = 0;
#endif
@@ -317,7 +317,7 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
(current->mm->start_brk = N_BSSADDR(ex));
current->mm->free_area_cache = current->mm->mmap_base;
- current->mm->rss = 0;
+ set_mm_counter(current->mm, rss, 0);
current->mm->mmap = NULL;
compute_creds(bprm);
current->flags &= ~PF_FORKNOEXEC;
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 1ba738d614703..76ec9d8939ffe 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -37,6 +37,7 @@
#include <linux/pagemap.h>
#include <linux/security.h>
#include <linux/syscalls.h>
+#include <linux/random.h>
#include <asm/uaccess.h>
#include <asm/param.h>
@@ -165,21 +166,14 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr * exec,
if (k_platform) {
size_t len = strlen(k_platform) + 1;
-#ifdef CONFIG_X86_HT
/*
* In some cases (e.g. Hyper-Threading), we want to avoid L1
* evictions by the processes running on the same package. One
* thing we can do is to shuffle the initial stack for them.
- *
- * The conditionals here are unneeded, but kept in to make the
- * code behaviour the same as pre change unless we have
- * hyperthreaded processors. This should be cleaned up
- * before 2.6
*/
- if (smp_num_siblings > 1)
- STACK_ALLOC(p, ((current->pid % 64) << 7));
-#endif
+ p = arch_align_stack(p);
+
u_platform = (elf_addr_t __user *)STACK_ALLOC(p, len);
if (__copy_to_user(u_platform, k_platform, len))
return -EFAULT;
@@ -501,6 +495,19 @@ out:
#define INTERPRETER_ELF 2
+static unsigned long randomize_stack_top(unsigned long stack_top)
+{
+ unsigned int random_variable = 0;
+
+ if (current->flags & PF_RANDOMIZE)
+ random_variable = get_random_int() % (8*1024*1024);
+#ifdef CONFIG_STACK_GROWSUP
+ return PAGE_ALIGN(stack_top + random_variable);
+#else
+ return PAGE_ALIGN(stack_top - random_variable);
+#endif
+}
+
static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
{
struct file *interpreter = NULL; /* to shut gcc up */
@@ -760,18 +767,29 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
if (elf_read_implies_exec(loc->elf_ex, executable_stack))
current->personality |= READ_IMPLIES_EXEC;
+ if ( !(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
+ current->flags |= PF_RANDOMIZE;
arch_pick_mmap_layout(current->mm);
/* Do this so that we can load the interpreter, if need be. We will
change some of these later */
- current->mm->rss = 0;
+ set_mm_counter(current->mm, rss, 0);
current->mm->free_area_cache = current->mm->mmap_base;
- retval = setup_arg_pages(bprm, STACK_TOP, executable_stack);
+ retval = setup_arg_pages(bprm, randomize_stack_top(STACK_TOP),
+ executable_stack);
if (retval < 0) {
send_sig(SIGKILL, current, 0);
goto out_free_dentry;
}
+#ifdef ARCH_HAS_SETUP_ADDITIONAL_PAGES
+ retval = arch_setup_additional_pages(bprm, executable_stack);
+ if (retval < 0) {
+ send_sig(SIGKILL, current, 0);
+ goto out_free_dentry;
+ }
+#endif /* ARCH_HAS_SETUP_ADDITIONAL_PAGES */
+
current->mm->start_stack = bprm->p;
/* Now we do a little grungy work by mmaping the ELF image into
@@ -803,13 +821,14 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
nbyte = ELF_MIN_ALIGN - nbyte;
if (nbyte > elf_brk - elf_bss)
nbyte = elf_brk - elf_bss;
- /*
- * This bss-zeroing can fail if the ELF file
- * specifies odd protections. So we don't check
- * the return value
- */
- (void)clear_user((void __user *)elf_bss +
- load_bias, nbyte);
+ if (clear_user((void __user *)elf_bss +
+ load_bias, nbyte)) {
+ /*
+ * This bss-zeroing can fail if the ELF
+ * file specifies odd protections. So
+ * we don't check the return value
+ */
+ }
}
}
@@ -1007,6 +1026,7 @@ out_free_ph:
static int load_elf_library(struct file *file)
{
struct elf_phdr *elf_phdata;
+ struct elf_phdr *eppnt;
unsigned long elf_bss, bss, len;
int retval, error, i, j;
struct elfhdr elf_ex;
@@ -1030,44 +1050,47 @@ static int load_elf_library(struct file *file)
/* j < ELF_MIN_ALIGN because elf_ex.e_phnum <= 2 */
error = -ENOMEM;
- elf_phdata = (struct elf_phdr *) kmalloc(j, GFP_KERNEL);
+ elf_phdata = kmalloc(j, GFP_KERNEL);
if (!elf_phdata)
goto out;
+ eppnt = elf_phdata;
error = -ENOEXEC;
- retval = kernel_read(file, elf_ex.e_phoff, (char *) elf_phdata, j);
+ retval = kernel_read(file, elf_ex.e_phoff, (char *)eppnt, j);
if (retval != j)
goto out_free_ph;
for (j = 0, i = 0; i<elf_ex.e_phnum; i++)
- if ((elf_phdata + i)->p_type == PT_LOAD) j++;
+ if ((eppnt + i)->p_type == PT_LOAD)
+ j++;
if (j != 1)
goto out_free_ph;
- while (elf_phdata->p_type != PT_LOAD) elf_phdata++;
+ while (eppnt->p_type != PT_LOAD)
+ eppnt++;
/* Now use mmap to map the library into memory. */
down_write(&current->mm->mmap_sem);
error = do_mmap(file,
- ELF_PAGESTART(elf_phdata->p_vaddr),
- (elf_phdata->p_filesz +
- ELF_PAGEOFFSET(elf_phdata->p_vaddr)),
+ ELF_PAGESTART(eppnt->p_vaddr),
+ (eppnt->p_filesz +
+ ELF_PAGEOFFSET(eppnt->p_vaddr)),
PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,
- (elf_phdata->p_offset -
- ELF_PAGEOFFSET(elf_phdata->p_vaddr)));
+ (eppnt->p_offset -
+ ELF_PAGEOFFSET(eppnt->p_vaddr)));
up_write(&current->mm->mmap_sem);
- if (error != ELF_PAGESTART(elf_phdata->p_vaddr))
+ if (error != ELF_PAGESTART(eppnt->p_vaddr))
goto out_free_ph;
- elf_bss = elf_phdata->p_vaddr + elf_phdata->p_filesz;
+ elf_bss = eppnt->p_vaddr + eppnt->p_filesz;
if (padzero(elf_bss)) {
error = -EFAULT;
goto out_free_ph;
}
- len = ELF_PAGESTART(elf_phdata->p_filesz + elf_phdata->p_vaddr + ELF_MIN_ALIGN - 1);
- bss = elf_phdata->p_memsz + elf_phdata->p_vaddr;
+ len = ELF_PAGESTART(eppnt->p_filesz + eppnt->p_vaddr + ELF_MIN_ALIGN - 1);
+ bss = eppnt->p_memsz + eppnt->p_vaddr;
if (bss > len) {
down_write(&current->mm->mmap_sem);
do_brk(len, bss - len);
@@ -1121,10 +1144,14 @@ static int dump_seek(struct file *file, off_t off)
*/
static int maydump(struct vm_area_struct *vma)
{
- /* Do not dump I/O mapped devices, shared memory, or special mappings */
- if (vma->vm_flags & (VM_IO | VM_SHARED | VM_RESERVED))
+ /* Do not dump I/O mapped devices or special mappings */
+ if (vma->vm_flags & (VM_IO | VM_RESERVED))
return 0;
+ /* Dump shared memory only if mapped from an anonymous file. */
+ if (vma->vm_flags & VM_SHARED)
+ return vma->vm_file->f_dentry->d_inode->i_nlink == 0;
+
/* If it hasn't been written to, don't write it out */
if (!vma->anon_vma)
return 0;
@@ -1584,7 +1611,7 @@ static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file)
DUMP_SEEK (file->f_pos + PAGE_SIZE);
} else {
void *kaddr;
- flush_cache_page(vma, addr);
+ flush_cache_page(vma, addr, page_to_pfn(page));
kaddr = kmap(page);
if ((size += PAGE_SIZE) > limit ||
!dump_write(file, kaddr,
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c
index 745e9b8b3a5ea..134c9c0d1f54f 100644
--- a/fs/binfmt_elf_fdpic.c
+++ b/fs/binfmt_elf_fdpic.c
@@ -299,7 +299,7 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm, struct pt_regs *regs
/* do this so that we can load the interpreter, if need be
* - we will change some of these later
*/
- current->mm->rss = 0;
+ set_mm_counter(current->mm, rss, 0);
#ifdef CONFIG_MMU
retval = setup_arg_pages(bprm, current->mm->start_stack, executable_stack);
diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c
index fb440602cfc17..f0cd67d9d31b9 100644
--- a/fs/binfmt_flat.c
+++ b/fs/binfmt_flat.c
@@ -650,7 +650,7 @@ static int load_flat_file(struct linux_binprm * bprm,
current->mm->start_brk = datapos + data_len + bss_len;
current->mm->brk = (current->mm->start_brk + 3) & ~3;
current->mm->context.end_brk = memp + ksize((void *) memp) - stack_len;
- current->mm->rss = 0;
+ set_mm_counter(current->mm, rss, 0);
}
if (flags & FLAT_FLAG_KTRACE)
diff --git a/fs/binfmt_som.c b/fs/binfmt_som.c
index f02ee506dd654..227a2682d2bfa 100644
--- a/fs/binfmt_som.c
+++ b/fs/binfmt_som.c
@@ -259,7 +259,7 @@ load_som_binary(struct linux_binprm * bprm, struct pt_regs * regs)
create_som_tables(bprm);
current->mm->start_stack = bprm->p;
- current->mm->rss = 0;
+ set_mm_counter(current->mm, rss, 0);
#if 0
printk("(start_brk) %08lx\n" , (unsigned long) current->mm->start_brk);
diff --git a/fs/bio.c b/fs/bio.c
index d23d9782377e0..e5349e834563d 100644
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -28,7 +28,6 @@
#define BIO_POOL_SIZE 256
-static mempool_t *bio_pool;
static kmem_cache_t *bio_slab;
#define BIOVEC_NR_POOLS 6
@@ -40,11 +39,10 @@ static kmem_cache_t *bio_slab;
#define BIO_SPLIT_ENTRIES 8
mempool_t *bio_split_pool;
-struct biovec_pool {
+struct biovec_slab {
int nr_vecs;
char *name;
kmem_cache_t *slab;
- mempool_t *pool;
};
/*
@@ -54,15 +52,32 @@ struct biovec_pool {
*/
#define BV(x) { .nr_vecs = x, .name = "biovec-"__stringify(x) }
-static struct biovec_pool bvec_array[BIOVEC_NR_POOLS] = {
+static struct biovec_slab bvec_slabs[BIOVEC_NR_POOLS] = {
BV(1), BV(4), BV(16), BV(64), BV(128), BV(BIO_MAX_PAGES),
};
#undef BV
-static inline struct bio_vec *bvec_alloc(int gfp_mask, int nr, unsigned long *idx)
+/*
+ * bio_set is used to allow other portions of the IO system to
+ * allocate their own private memory pools for bio and iovec structures.
+ * These memory pools in turn all allocate from the bio_slab
+ * and the bvec_slabs[].
+ */
+struct bio_set {
+ mempool_t *bio_pool;
+ mempool_t *bvec_pools[BIOVEC_NR_POOLS];
+};
+
+/*
+ * fs_bio_set is the bio_set containing bio and iovec memory pools used by
+ * IO code that does not need private memory pools.
+ */
+static struct bio_set *fs_bio_set;
+
+static inline struct bio_vec *bvec_alloc_bs(unsigned int __nocast gfp_mask, int nr, unsigned long *idx, struct bio_set *bs)
{
- struct biovec_pool *bp;
struct bio_vec *bvl;
+ struct biovec_slab *bp;
/*
* see comment near bvec_array define!
@@ -80,26 +95,27 @@ static inline struct bio_vec *bvec_alloc(int gfp_mask, int nr, unsigned long *id
/*
* idx now points to the pool we want to allocate from
*/
- bp = bvec_array + *idx;
- bvl = mempool_alloc(bp->pool, gfp_mask);
+ bp = bvec_slabs + *idx;
+ bvl = mempool_alloc(bs->bvec_pools[*idx], gfp_mask);
if (bvl)
memset(bvl, 0, bp->nr_vecs * sizeof(struct bio_vec));
+
return bvl;
}
/*
- * default destructor for a bio allocated with bio_alloc()
+ * default destructor for a bio allocated with bio_alloc_bioset()
*/
static void bio_destructor(struct bio *bio)
{
const int pool_idx = BIO_POOL_IDX(bio);
- struct biovec_pool *bp = bvec_array + pool_idx;
+ struct bio_set *bs = bio->bi_set;
BIO_BUG_ON(pool_idx >= BIOVEC_NR_POOLS);
- mempool_free(bio->bi_io_vec, bp->pool);
- mempool_free(bio, bio_pool);
+ mempool_free(bio->bi_io_vec, bs->bvec_pools[pool_idx]);
+ mempool_free(bio, bs->bio_pool);
}
inline void bio_init(struct bio *bio)
@@ -121,18 +137,21 @@ inline void bio_init(struct bio *bio)
}
/**
- * bio_alloc - allocate a bio for I/O
+ * bio_alloc_bioset - allocate a bio for I/O
* @gfp_mask: the GFP_ mask given to the slab allocator
* @nr_iovecs: number of iovecs to pre-allocate
*
* Description:
- * bio_alloc will first try it's on mempool to satisfy the allocation.
+ * bio_alloc_bioset will first try it's on mempool to satisfy the allocation.
* If %__GFP_WAIT is set then we will block on the internal pool waiting
* for a &struct bio to become free.
+ *
+ * allocate bio and iovecs from the memory pools specified by the
+ * bio_set structure.
**/
-struct bio *bio_alloc(int gfp_mask, int nr_iovecs)
+struct bio *bio_alloc_bioset(unsigned int __nocast gfp_mask, int nr_iovecs, struct bio_set *bs)
{
- struct bio *bio = mempool_alloc(bio_pool, gfp_mask);
+ struct bio *bio = mempool_alloc(bs->bio_pool, gfp_mask);
if (likely(bio)) {
struct bio_vec *bvl = NULL;
@@ -141,22 +160,43 @@ struct bio *bio_alloc(int gfp_mask, int nr_iovecs)
if (likely(nr_iovecs)) {
unsigned long idx;
- bvl = bvec_alloc(gfp_mask, nr_iovecs, &idx);
+ bvl = bvec_alloc_bs(gfp_mask, nr_iovecs, &idx, bs);
if (unlikely(!bvl)) {
- mempool_free(bio, bio_pool);
+ mempool_free(bio, bs->bio_pool);
bio = NULL;
goto out;
}
bio->bi_flags |= idx << BIO_POOL_OFFSET;
- bio->bi_max_vecs = bvec_array[idx].nr_vecs;
+ bio->bi_max_vecs = bvec_slabs[idx].nr_vecs;
}
bio->bi_io_vec = bvl;
bio->bi_destructor = bio_destructor;
+ bio->bi_set = bs;
}
out:
return bio;
}
+struct bio *bio_alloc(unsigned int __nocast gfp_mask, int nr_iovecs)
+{
+ return bio_alloc_bioset(gfp_mask, nr_iovecs, fs_bio_set);
+}
+
+void zero_fill_bio(struct bio *bio)
+{
+ unsigned long flags;
+ struct bio_vec *bv;
+ int i;
+
+ bio_for_each_segment(bv, bio, i) {
+ char *data = bvec_kmap_irq(bv, &flags);
+ memset(data, 0, bv->bv_len);
+ flush_dcache_page(bv->bv_page);
+ bvec_kunmap_irq(data, &flags);
+ }
+}
+EXPORT_SYMBOL(zero_fill_bio);
+
/**
* bio_put - release a reference to a bio
* @bio: bio to release reference to
@@ -231,9 +271,9 @@ inline void __bio_clone(struct bio *bio, struct bio *bio_src)
*
* Like __bio_clone, only also allocates the returned bio
*/
-struct bio *bio_clone(struct bio *bio, int gfp_mask)
+struct bio *bio_clone(struct bio *bio, unsigned int __nocast gfp_mask)
{
- struct bio *b = bio_alloc(gfp_mask, bio->bi_max_vecs);
+ struct bio *b = bio_alloc_bioset(gfp_mask, bio->bi_max_vecs, fs_bio_set);
if (b)
__bio_clone(b, bio);
@@ -894,7 +934,7 @@ struct bio_pair *bio_split(struct bio *bi, mempool_t *pool, int first_sectors)
return bp;
}
-static void *bio_pair_alloc(int gfp_flags, void *data)
+static void *bio_pair_alloc(unsigned int __nocast gfp_flags, void *data)
{
return kmalloc(sizeof(struct bio_pair), gfp_flags);
}
@@ -904,11 +944,99 @@ static void bio_pair_free(void *bp, void *data)
kfree(bp);
}
-static void __init biovec_init_pools(void)
+
+/*
+ * create memory pools for biovec's in a bio_set.
+ * use the global biovec slabs created for general use.
+ */
+static int biovec_create_pools(struct bio_set *bs, int pool_entries, int scale)
{
- int i, size, megabytes, pool_entries = BIO_POOL_SIZE;
+ int i;
+
+ for (i = 0; i < BIOVEC_NR_POOLS; i++) {
+ struct biovec_slab *bp = bvec_slabs + i;
+ mempool_t **bvp = bs->bvec_pools + i;
+
+ if (i >= scale)
+ pool_entries >>= 1;
+
+ *bvp = mempool_create(pool_entries, mempool_alloc_slab,
+ mempool_free_slab, bp->slab);
+ if (!*bvp)
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+static void biovec_free_pools(struct bio_set *bs)
+{
+ int i;
+
+ for (i = 0; i < BIOVEC_NR_POOLS; i++) {
+ mempool_t *bvp = bs->bvec_pools[i];
+
+ if (bvp)
+ mempool_destroy(bvp);
+ }
+
+}
+
+void bioset_free(struct bio_set *bs)
+{
+ if (bs->bio_pool)
+ mempool_destroy(bs->bio_pool);
+
+ biovec_free_pools(bs);
+
+ kfree(bs);
+}
+
+struct bio_set *bioset_create(int bio_pool_size, int bvec_pool_size, int scale)
+{
+ struct bio_set *bs = kmalloc(sizeof(*bs), GFP_KERNEL);
+
+ if (!bs)
+ return NULL;
+
+ memset(bs, 0, sizeof(*bs));
+ bs->bio_pool = mempool_create(bio_pool_size, mempool_alloc_slab,
+ mempool_free_slab, bio_slab);
+
+ if (!bs->bio_pool)
+ goto bad;
+
+ if (!biovec_create_pools(bs, bvec_pool_size, scale))
+ return bs;
+
+bad:
+ bioset_free(bs);
+ return NULL;
+}
+
+static void __init biovec_init_slabs(void)
+{
+ int i;
+
+ for (i = 0; i < BIOVEC_NR_POOLS; i++) {
+ int size;
+ struct biovec_slab *bvs = bvec_slabs + i;
+
+ size = bvs->nr_vecs * sizeof(struct bio_vec);
+ bvs->slab = kmem_cache_create(bvs->name, size, 0,
+ SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL);
+ }
+}
+
+static int __init init_bio(void)
+{
+ int megabytes, bvec_pool_entries;
int scale = BIOVEC_NR_POOLS;
+ bio_slab = kmem_cache_create("bio", sizeof(struct bio), 0,
+ SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL);
+
+ biovec_init_slabs();
+
megabytes = nr_free_pages() >> (20 - PAGE_SHIFT);
/*
@@ -928,38 +1056,13 @@ static void __init biovec_init_pools(void)
/*
* scale number of entries
*/
- pool_entries = megabytes * 2;
- if (pool_entries > 256)
- pool_entries = 256;
-
- for (i = 0; i < BIOVEC_NR_POOLS; i++) {
- struct biovec_pool *bp = bvec_array + i;
-
- size = bp->nr_vecs * sizeof(struct bio_vec);
-
- bp->slab = kmem_cache_create(bp->name, size, 0,
- SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL);
-
- if (i >= scale)
- pool_entries >>= 1;
-
- bp->pool = mempool_create(pool_entries, mempool_alloc_slab,
- mempool_free_slab, bp->slab);
- if (!bp->pool)
- panic("biovec: can't init mempool\n");
- }
-}
-
-static int __init init_bio(void)
-{
- bio_slab = kmem_cache_create("bio", sizeof(struct bio), 0,
- SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL);
- bio_pool = mempool_create(BIO_POOL_SIZE, mempool_alloc_slab,
- mempool_free_slab, bio_slab);
- if (!bio_pool)
- panic("bio: can't create mempool\n");
+ bvec_pool_entries = megabytes * 2;
+ if (bvec_pool_entries > 256)
+ bvec_pool_entries = 256;
- biovec_init_pools();
+ fs_bio_set = bioset_create(BIO_POOL_SIZE, bvec_pool_entries, scale);
+ if (!fs_bio_set)
+ panic("bio: can't allocate bios\n");
bio_split_pool = mempool_create(BIO_SPLIT_ENTRIES,
bio_pair_alloc, bio_pair_free, NULL);
@@ -988,3 +1091,6 @@ EXPORT_SYMBOL(bio_split);
EXPORT_SYMBOL(bio_split_pool);
EXPORT_SYMBOL(bio_copy_user);
EXPORT_SYMBOL(bio_uncopy_user);
+EXPORT_SYMBOL(bioset_create);
+EXPORT_SYMBOL(bioset_free);
+EXPORT_SYMBOL(bio_alloc_bioset);
diff --git a/fs/buffer.c b/fs/buffer.c
index 3c40d6382925b..f961605a904b1 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -39,6 +39,7 @@
#include <linux/notifier.h>
#include <linux/cpu.h>
#include <linux/bitops.h>
+#include <linux/mpage.h>
static int fsync_buffers_list(spinlock_t *lock, struct list_head *list);
static void invalidate_bh_lrus(void);
@@ -875,15 +876,15 @@ int __set_page_dirty_buffers(struct page *page)
spin_unlock(&mapping->private_lock);
if (!TestSetPageDirty(page)) {
- spin_lock_irq(&mapping->tree_lock);
+ write_lock_irq(&mapping->tree_lock);
if (page->mapping) { /* Race with truncate? */
- if (!mapping->backing_dev_info->memory_backed)
+ if (mapping_cap_account_dirty(mapping))
inc_page_state(nr_dirty);
radix_tree_tag_set(&mapping->page_tree,
page_index(page),
PAGECACHE_TAG_DIRTY);
}
- spin_unlock_irq(&mapping->tree_lock);
+ write_unlock_irq(&mapping->tree_lock);
__mark_inode_dirty(mapping->host, I_DIRTY_PAGES);
}
@@ -2509,6 +2510,61 @@ int nobh_commit_write(struct file *file, struct page *page,
EXPORT_SYMBOL(nobh_commit_write);
/*
+ * nobh_writepage() - based on block_full_write_page() except
+ * that it tries to operate without attaching bufferheads to
+ * the page.
+ */
+int nobh_writepage(struct page *page, get_block_t *get_block,
+ struct writeback_control *wbc)
+{
+ struct inode * const inode = page->mapping->host;
+ loff_t i_size = i_size_read(inode);
+ const pgoff_t end_index = i_size >> PAGE_CACHE_SHIFT;
+ unsigned offset;
+ void *kaddr;
+ int ret;
+
+ /* Is the page fully inside i_size? */
+ if (page->index < end_index)
+ goto out;
+
+ /* Is the page fully outside i_size? (truncate in progress) */
+ offset = i_size & (PAGE_CACHE_SIZE-1);
+ if (page->index >= end_index+1 || !offset) {
+ /*
+ * The page may have dirty, unmapped buffers. For example,
+ * they may have been added in ext3_writepage(). Make them
+ * freeable here, so the page does not leak.
+ */
+#if 0
+ /* Not really sure about this - do we need this ? */
+ if (page->mapping->a_ops->invalidatepage)
+ page->mapping->a_ops->invalidatepage(page, offset);
+#endif
+ unlock_page(page);
+ return 0; /* don't care */
+ }
+
+ /*
+ * The page straddles i_size. It must be zeroed out on each and every
+ * writepage invocation because it may be mmapped. "A file is mapped
+ * in multiples of the page size. For a file that is not a multiple of
+ * the page size, the remaining memory is zeroed when mapped, and
+ * writes to that region are not written out to the file."
+ */
+ kaddr = kmap_atomic(page, KM_USER0);
+ memset(kaddr + offset, 0, PAGE_CACHE_SIZE - offset);
+ flush_dcache_page(page);
+ kunmap_atomic(kaddr, KM_USER0);
+out:
+ ret = mpage_writepage(page, get_block, wbc);
+ if (ret == -EAGAIN)
+ ret = __block_write_full_page(inode, page, get_block, wbc);
+ return ret;
+}
+EXPORT_SYMBOL(nobh_writepage);
+
+/*
* This function assumes that ->prepare_write() uses nobh_prepare_write().
*/
int nobh_truncate_page(struct address_space *mapping, loff_t from)
@@ -2996,7 +3052,7 @@ static void recalc_bh_state(void)
buffer_heads_over_limit = (tot > max_buffer_heads);
}
-struct buffer_head *alloc_buffer_head(int gfp_flags)
+struct buffer_head *alloc_buffer_head(unsigned int __nocast gfp_flags)
{
struct buffer_head *ret = kmem_cache_alloc(bh_cachep, gfp_flags);
if (ret) {
diff --git a/fs/char_dev.c b/fs/char_dev.c
index cd42dc317a5bb..7357a9127df15 100644
--- a/fs/char_dev.c
+++ b/fs/char_dev.c
@@ -26,9 +26,10 @@
static struct kobj_map *cdev_map;
-#define MAX_PROBE_HASH 255 /* random */
+/* degrade to linked list for small systems */
+#define MAX_PROBE_HASH (CONFIG_BASE_SMALL ? 1 : 255)
-static DEFINE_RWLOCK(chrdevs_lock);
+static DECLARE_MUTEX(chrdevs_lock);
static struct char_device_struct {
struct char_device_struct *next;
@@ -54,13 +55,13 @@ int get_chrdev_list(char *page)
len = sprintf(page, "Character devices:\n");
- read_lock(&chrdevs_lock);
+ down(&chrdevs_lock);
for (i = 0; i < ARRAY_SIZE(chrdevs) ; i++) {
for (cd = chrdevs[i]; cd; cd = cd->next)
len += sprintf(page+len, "%3d %s\n",
cd->major, cd->name);
}
- read_unlock(&chrdevs_lock);
+ up(&chrdevs_lock);
return len;
}
@@ -90,7 +91,7 @@ __register_chrdev_region(unsigned int major, unsigned int baseminor,
memset(cd, 0, sizeof(struct char_device_struct));
- write_lock_irq(&chrdevs_lock);
+ down(&chrdevs_lock);
/* temporary */
if (major == 0) {
@@ -125,10 +126,10 @@ __register_chrdev_region(unsigned int major, unsigned int baseminor,
}
cd->next = *cp;
*cp = cd;
- write_unlock_irq(&chrdevs_lock);
+ up(&chrdevs_lock);
return cd;
out:
- write_unlock_irq(&chrdevs_lock);
+ up(&chrdevs_lock);
kfree(cd);
return ERR_PTR(ret);
}
@@ -139,7 +140,7 @@ __unregister_chrdev_region(unsigned major, unsigned baseminor, int minorct)
struct char_device_struct *cd = NULL, **cp;
int i = major_to_index(major);
- write_lock_irq(&chrdevs_lock);
+ up(&chrdevs_lock);
for (cp = &chrdevs[i]; *cp; cp = &(*cp)->next)
if ((*cp)->major == major &&
(*cp)->baseminor == baseminor &&
@@ -149,7 +150,7 @@ __unregister_chrdev_region(unsigned major, unsigned baseminor, int minorct)
cd = *cp;
*cp = cd->next;
}
- write_unlock_irq(&chrdevs_lock);
+ up(&chrdevs_lock);
return cd;
}
@@ -380,8 +381,6 @@ void cdev_del(struct cdev *p)
}
-static decl_subsys(cdev, NULL, NULL);
-
static void cdev_default_release(struct kobject *kobj)
{
struct cdev *p = container_of(kobj, struct cdev, kobj);
@@ -434,13 +433,7 @@ static struct kobject *base_probe(dev_t dev, int *part, void *data)
void __init chrdev_init(void)
{
-/*
- * Keep cdev_subsys around because (and only because) the kobj_map code
- * depends on the rwsem it contains. We don't make it public in sysfs,
- * however.
- */
- subsystem_init(&cdev_subsys);
- cdev_map = kobj_map_init(base_probe, &cdev_subsys);
+ cdev_map = kobj_map_init(base_probe, &chrdevs_lock);
}
diff --git a/fs/cifs/AUTHORS b/fs/cifs/AUTHORS
index fccc9ca446087..acce36e25d2ee 100644
--- a/fs/cifs/AUTHORS
+++ b/fs/cifs/AUTHORS
@@ -25,6 +25,8 @@ Sergey Vlasov
Richard Hughes
Yury Umanets
Mark Hamzy
+Domen Puncer
+Jesper Juhl
Test case and Bug Report contributors
-------------------------------------
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index 4aaceb3733ed9..5316c8dd6bfff 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -1,3 +1,31 @@
+Version 1.31
+------------
+Fix oops in ls when Transact2 FindFirst (or FindNext) returns more than one
+transact response for an SMB request and search entry split across two frames.
+Fix updates of DOS attributes and time fields so that files on NT4 servers
+do not get marked delete on close. Display sizes of cifs buffer pools in
+cifs stats. Fix oops in unmount when cifsd thread being killed by
+shutdown. Add generic readv/writev and aio support. Report inode numbers
+consistently in readdir and lookup (when serverino mount option is
+specified use the inode number that the server reports - for both lookup
+and readdir, otherwise by default the locally generated inode number is used
+for inodes created in either path since servers are not always able to
+provide unique inode numbers when exporting multiple volumes from under one
+sharename).
+
+Version 1.30
+------------
+Allow new nouser_xattr mount parm to disable xattr support for user namespace.
+Do not flag user_xattr mount parm in dmesg. Retry failures setting file time
+(mostly affects NT4 servers) by retry with handle based network operation.
+Add new POSIX Query FS Info for returning statfs info more accurately.
+Handle passwords with multiple commas in them.
+
+Version 1.29
+------------
+Fix default mode in sysfs of cifs module parms. Remove old readdir routine.
+Fix capabilities flags for large readx so as to allow reads larger than 64K.
+
Version 1.28
------------
Add module init parm for large SMB buffer size (to allow it to be changed
@@ -7,7 +35,8 @@ returning from mount when experimental ExtendedSecurity enabled and
SpnegoNegotiated returning invalid error. Fix case to retry better when
peek returns from 1 to 3 bytes on socket which should have more data.
Fixed path based calls (such as cifs lookup) to handle path names
-longer than 530 (now can handle PATH_MAX).
+longer than 530 (now can handle PATH_MAX). Fix pass through authentication
+from Samba server to DC (Samba required dummy LM password).
Version 1.27
------------
diff --git a/fs/cifs/Makefile b/fs/cifs/Makefile
index ec52a34fa023c..7384947a0f932 100644
--- a/fs/cifs/Makefile
+++ b/fs/cifs/Makefile
@@ -3,4 +3,4 @@
#
obj-$(CONFIG_CIFS) += cifs.o
-cifs-objs := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o fcntl.o readdir.o
+cifs-objs := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o fcntl.o readdir.o ioctl.o
diff --git a/fs/cifs/README b/fs/cifs/README
index 1643ef5426cc9..0f20edc935b5d 100644
--- a/fs/cifs/README
+++ b/fs/cifs/README
@@ -122,12 +122,14 @@ cifs client, and that EA support is present in later versions of Samba (e.g.
3.0.6 and later (also EA support works in all versions of Windows, at least to
shares on NTFS filesystems). Extended Attribute (xattr) support is an optional
feature of most Linux filesystems which may require enabling via
-make menuconfig.
+make menuconfig. Client support for extended attributes (user xattr) can be
+disabled on a per-mount basis by specifying "nouser_xattr" on mount.
The CIFS client can get and set POSIX ACLs (getfacl, setfacl) to Samba servers
version 3.10 and later. Setting POSIX ACLs requires enabling both XATTR and
then POSIX support in the CIFS configuration options when building the cifs
-module.
+module. POSIX ACL support can be disabled on a per mount basic by specifying
+"noacl" on mount.
Some administrators may want to change Samba's smb.conf "map archive" and
"create mask" parameters from the default. Unless the create mask is changed
@@ -370,6 +372,10 @@ A partial list of the supported mount options follows:
acl Allow setfacl and getfacl to manage posix ACLs if server
supports them. (default)
noacl Do not allow setfacl and getfacl calls on this mount
+ user_xattr Allow getting and setting user xattrs as OS/2 EAs (extended
+ attributes) to the server (default) e.g. via setfattr
+ and getfattr utilities.
+ nouser_xattr Do not allow getfattr/setfattr to get/set xattrs
The mount.cifs mount helper also accepts a few mount options before -o
including:
diff --git a/fs/cifs/asn1.c b/fs/cifs/asn1.c
index 60f67697bceb8..e02010dd73ec5 100644
--- a/fs/cifs/asn1.c
+++ b/fs/cifs/asn1.c
@@ -26,6 +26,7 @@
#include "cifspdu.h"
#include "cifsglob.h"
#include "cifs_debug.h"
+#include "cifsproto.h"
/*****************************************************************************
*
@@ -77,8 +78,8 @@
#define SPNEGO_OID_LEN 7
#define NTLMSSP_OID_LEN 10
-unsigned long SPNEGO_OID[7] = { 1, 3, 6, 1, 5, 5, 2 };
-unsigned long NTLMSSP_OID[10] = { 1, 3, 6, 1, 4, 1, 311, 2, 2, 10 };
+static unsigned long SPNEGO_OID[7] = { 1, 3, 6, 1, 5, 5, 2 };
+static unsigned long NTLMSSP_OID[10] = { 1, 3, 6, 1, 4, 1, 311, 2, 2, 10 };
/*
* ASN.1 context.
@@ -210,7 +211,7 @@ asn1_eoc_decode(struct asn1_ctx *ctx, unsigned char *eoc)
{
unsigned char ch;
- if (eoc == 0) {
+ if (eoc == NULL) {
if (!asn1_octet_decode(ctx, &ch))
return 0;
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c
index 716dd019bcd1f..db28b561cd4b5 100644
--- a/fs/cifs/cifs_debug.c
+++ b/fs/cifs/cifs_debug.c
@@ -57,7 +57,7 @@ cifs_dump_mem(char *label, void *data, int length)
}
#ifdef CONFIG_PROC_FS
-int
+static int
cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
int count, int *eof, void *data)
{
@@ -89,12 +89,13 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
length =
sprintf(buf,
- "\n%d) Name: %s Domain: %s Mounts: %d ServerOS: %s \n\tServerNOS: %s\tCapabilities: 0x%x\n\tSMB session status: %d\tTCP status: %d",
+ "\n%d) Name: %s Domain: %s Mounts: %d ServerOS: %s \n\tServerNOS: %s\tCapabilities: 0x%x\n\tSMB session status: %d\t",
i, ses->serverName, ses->serverDomain, atomic_read(&ses->inUse),
- ses->serverOS, ses->serverNOS, ses->capabilities,ses->status,ses->server->tcpStatus);
+ ses->serverOS, ses->serverNOS, ses->capabilities,ses->status);
buf += length;
if(ses->server) {
- buf += sprintf(buf, "\n\tLocal Users To Server: %d SecMode: 0x%x Req Active: %d",
+ buf += sprintf(buf, "TCP status: %d\n\tLocal Users To Server: %d SecMode: 0x%x Req Active: %d",
+ ses->server->tcpStatus,
atomic_read(&ses->server->socketUseCount),
ses->server->secMode,
atomic_read(&ses->server->inFlight));
@@ -178,7 +179,7 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
}
#ifdef CONFIG_CIFS_STATS
-int
+static int
cifs_stats_read(char *buf, char **beginBuffer, off_t offset,
int count, int *eof, void *data)
{
@@ -198,13 +199,13 @@ cifs_stats_read(char *buf, char **beginBuffer, off_t offset,
length += item_length;
buf += item_length;
item_length =
- sprintf(buf,"SMB Request/Response Buffer: %d\n",
- bufAllocCount.counter);
+ sprintf(buf,"SMB Request/Response Buffer: %d Pool size: %d\n",
+ bufAllocCount.counter,cifs_min_rcv + tcpSesAllocCount.counter);
length += item_length;
buf += item_length;
item_length =
- sprintf(buf,"SMB Small Req/Resp Buffer: %d\n",
- smBufAllocCount.counter);
+ sprintf(buf,"SMB Small Req/Resp Buffer: %d Pool size: %d\n",
+ smBufAllocCount.counter,cifs_min_small);
length += item_length;
buf += item_length;
item_length =
@@ -286,7 +287,7 @@ cifs_stats_read(char *buf, char **beginBuffer, off_t offset,
}
#endif
-struct proc_dir_entry *proc_fs_cifs;
+static struct proc_dir_entry *proc_fs_cifs;
read_proc_t cifs_txanchor_read;
static read_proc_t cifsFYI_read;
static write_proc_t cifsFYI_write;
diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h
index b6c62f5915689..77da902d8f329 100644
--- a/fs/cifs/cifs_fs_sb.h
+++ b/fs/cifs/cifs_fs_sb.h
@@ -21,7 +21,8 @@
#define CIFS_MOUNT_NO_PERM 1 /* do not do client vfs_perm check */
#define CIFS_MOUNT_SET_UID 2 /* set current->euid in create etc. */
#define CIFS_MOUNT_SERVER_INUM 4 /* inode numbers from uniqueid from server */
-#define CIFS_MOUNT_DIRECT_IO 8 /* do not write nor read through page cache */
+#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 */
struct cifs_sb_info {
struct cifsTconInfo *tcon; /* primary mount */
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index 17823106208d3..78829e7d8cd01 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -25,6 +25,7 @@
#include "cifs_debug.h"
#include "md5.h"
#include "cifs_unicode.h"
+#include "cifsproto.h"
/* Calculate and return the CIFS signature based on the mac key and the smb pdu */
/* the 16 byte signature must be allocated by the caller */
diff --git a/fs/cifs/cifsencrypt.h b/fs/cifs/cifsencrypt.h
new file mode 100644
index 0000000000000..03e359b328611
--- /dev/null
+++ b/fs/cifs/cifsencrypt.h
@@ -0,0 +1,34 @@
+/*
+ * fs/cifs/cifsencrypt.h
+ *
+ * Copyright (c) International Business Machines Corp., 2005
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ * Externs for misc. small encryption routines
+ * so we do not have to put them in cifsproto.h
+ *
+ * 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
+ */
+
+/* md4.c */
+extern void mdfour(unsigned char *out, unsigned char *in, int n);
+/* smbdes.c */
+extern void E_P16(unsigned char *p14, unsigned char *p16);
+extern void E_P24(unsigned char *p21, unsigned char *c8, unsigned char *p24);
+extern void D_P16(unsigned char *p14, unsigned char *in, unsigned char *out);
+extern void E_old_pw_hash(unsigned char *, unsigned char *, unsigned char *);
+
+
+
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index b0884aa697984..5082fce3c566d 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -57,29 +57,28 @@ unsigned int multiuser_mount = 0;
unsigned int extended_security = 0;
unsigned int ntlmv2_support = 0;
unsigned int sign_CIFS_PDUs = 1;
+extern struct task_struct * oplockThread; /* remove sparse warning */
struct task_struct * oplockThread = NULL;
unsigned int CIFSMaxBufSize = CIFS_MAX_MSGSIZE;
-module_param(CIFSMaxBufSize, int, CIFS_MAX_MSGSIZE);
+module_param(CIFSMaxBufSize, int, 0);
MODULE_PARM_DESC(CIFSMaxBufSize,"Network buffer size (not including header). Default: 16384 Range: 8192 to 130048");
unsigned int cifs_min_rcv = CIFS_MIN_RCV_POOL;
-module_param(cifs_min_rcv, int, CIFS_MIN_RCV_POOL);
+module_param(cifs_min_rcv, int, 0);
MODULE_PARM_DESC(cifs_min_rcv,"Network buffers in pool. Default: 4 Range: 1 to 64");
unsigned int cifs_min_small = 30;
-module_param(cifs_min_small, int, 30);
-MODULE_PARM_DESC(cifs_small_rcv,"Small network buffers in pool. Default: 30 Range: 2 to 256");
+module_param(cifs_min_small, int, 0);
+MODULE_PARM_DESC(cifs_min_small,"Small network buffers in pool. Default: 30 Range: 2 to 256");
unsigned int cifs_max_pending = CIFS_MAX_REQ;
-module_param(cifs_max_pending, int, CIFS_MAX_REQ);
+module_param(cifs_max_pending, int, 0);
MODULE_PARM_DESC(cifs_max_pending,"Simultaneous requests to server. Default: 50 Range: 2 to 256");
-
-extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *,
- const char *);
-extern int cifs_umount(struct super_block *, struct cifs_sb_info *);
-void cifs_proc_init(void);
-void cifs_proc_clean(void);
-
static DECLARE_COMPLETION(cifs_oplock_exited);
+extern mempool_t *cifs_sm_req_poolp;
+extern mempool_t *cifs_req_poolp;
+extern mempool_t *cifs_mid_poolp;
+
+extern kmem_cache_t *cifs_oplock_cachep;
static int
cifs_read_super(struct super_block *sb, void *data,
@@ -170,7 +169,7 @@ cifs_put_super(struct super_block *sb)
static int
cifs_statfs(struct super_block *sb, struct kstatfs *buf)
{
- int xid, rc;
+ int xid, rc = -EOPNOTSUPP;
struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon;
@@ -189,6 +188,15 @@ cifs_statfs(struct super_block *sb, struct kstatfs *buf)
buf->f_files = 0; /* undefined */
buf->f_ffree = 0; /* unlimited */
+#ifdef CONFIG_CIFS_EXPERIMENTAL
+/* BB we could add a second check for a QFS Unix capability bit */
+ if (pTcon->ses->capabilities & CAP_UNIX)
+ rc = CIFSSMBQFSPosixInfo(xid, pTcon, buf, cifs_sb->local_nls);
+
+ /* Only need to call the old QFSInfo if failed
+ on newer one */
+ if(rc)
+#endif /* CIFS_EXPERIMENTAL */
rc = CIFSSMBQFSInfo(xid, pTcon, buf, cifs_sb->local_nls);
/*
@@ -228,9 +236,7 @@ static struct inode *
cifs_alloc_inode(struct super_block *sb)
{
struct cifsInodeInfo *cifs_inode;
- cifs_inode =
- (struct cifsInodeInfo *) kmem_cache_alloc(cifs_inode_cachep,
- SLAB_KERNEL);
+ cifs_inode = kmem_cache_alloc(cifs_inode_cachep, SLAB_KERNEL);
if (!cifs_inode)
return NULL;
cifs_inode->cifsAttrs = 0x20; /* default */
@@ -437,28 +443,13 @@ static ssize_t
cifs_read_wrapper(struct file * file, char __user *read_data, size_t read_size,
loff_t * poffset)
{
- if(file == NULL)
- return -EIO;
- else if(file->f_dentry == NULL)
+ if(file->f_dentry == NULL)
return -EIO;
else if(file->f_dentry->d_inode == NULL)
return -EIO;
cFYI(1,("In read_wrapper size %zd at %lld",read_size,*poffset));
-#ifdef CONFIG_CIFS_EXPERIMENTAL
- /* check whether we can cache writes locally */
- if(file->f_dentry->d_sb) {
- struct cifs_sb_info *cifs_sb;
- cifs_sb = CIFS_SB(file->f_dentry->d_sb);
- if(cifs_sb != NULL) {
- if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
- return cifs_user_read(file,read_data,
- read_size,poffset);
- }
- }
-#endif /* CIFS_EXPERIMENTAL */
-
if(CIFS_I(file->f_dentry->d_inode)->clientCanCacheRead) {
return generic_file_read(file,read_data,read_size,poffset);
} else {
@@ -482,28 +473,13 @@ cifs_write_wrapper(struct file * file, const char __user *write_data,
{
ssize_t written;
- if(file == NULL)
- return -EIO;
- else if(file->f_dentry == NULL)
+ if(file->f_dentry == NULL)
return -EIO;
else if(file->f_dentry->d_inode == NULL)
return -EIO;
cFYI(1,("In write_wrapper size %zd at %lld",write_size,*poffset));
-#ifdef CONFIG_CIFS_EXPERIMENTAL /* BB fixme - fix user char * to kernel char * mapping here BB */
- /* check whether we can cache writes locally */
- if(file->f_dentry->d_sb) {
- struct cifs_sb_info *cifs_sb;
- cifs_sb = CIFS_SB(file->f_dentry->d_sb);
- if(cifs_sb != NULL) {
- if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
- return cifs_user_write(file,write_data,
- write_size,poffset);
- }
- }
- }
-#endif /* CIFS_EXPERIMENTAL */
written = generic_file_write(file,write_data,write_size,poffset);
if(!CIFS_I(file->f_dentry->d_inode)->clientCanCacheAll) {
if(file->f_dentry->d_inode->i_mapping) {
@@ -584,6 +560,26 @@ struct file_operations cifs_file_ops = {
.mmap = cifs_file_mmap,
.sendfile = generic_file_sendfile,
#ifdef CONFIG_CIFS_EXPERIMENTAL
+ .readv = generic_file_readv,
+ .writev = generic_file_writev,
+ .aio_read = generic_file_aio_read,
+ .aio_write = generic_file_aio_write,
+ .dir_notify = cifs_dir_notify,
+#endif /* CONFIG_CIFS_EXPERIMENTAL */
+};
+
+struct file_operations cifs_file_direct_ops = {
+ /* no mmap, no aio, no readv -
+ BB reevaluate whether they can be done with directio, no cache */
+ .read = cifs_user_read,
+ .write = cifs_user_write,
+ .open = cifs_open,
+ .release = cifs_close,
+ .lock = cifs_lock,
+ .fsync = cifs_fsync,
+ .flush = cifs_flush,
+ .sendfile = generic_file_sendfile, /* BB removeme BB */
+#ifdef CONFIG_CIFS_EXPERIMENTAL
.dir_notify = cifs_dir_notify,
#endif /* CONFIG_CIFS_EXPERIMENTAL */
};
@@ -600,7 +596,7 @@ struct file_operations cifs_dir_ops = {
static void
cifs_init_once(void *inode, kmem_cache_t * cachep, unsigned long flags)
{
- struct cifsInodeInfo *cifsi = (struct cifsInodeInfo *) inode;
+ struct cifsInodeInfo *cifsi = inode;
if ((flags & (SLAB_CTOR_VERIFY | SLAB_CTOR_CONSTRUCTOR)) ==
SLAB_CTOR_CONSTRUCTOR) {
@@ -653,7 +649,7 @@ cifs_init_request_bufs(void)
cifs_min_rcv = 1;
else if (cifs_min_rcv > 64) {
cifs_min_rcv = 64;
- cFYI(1,("cifs_min_rcv set to maximum (64)"));
+ cERROR(1,("cifs_min_rcv set to maximum (64)"));
}
cifs_req_poolp = mempool_create(cifs_min_rcv,
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index 9175b3849cb54..451f18af32069 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -42,8 +42,10 @@ extern void cifs_delete_inode(struct inode *);
/* Functions related to inodes */
extern struct inode_operations cifs_dir_inode_ops;
-extern int cifs_create(struct inode *, struct dentry *, int, struct nameidata *);
-extern struct dentry *cifs_lookup(struct inode *, struct dentry *, struct nameidata *);
+extern int cifs_create(struct inode *, struct dentry *, int,
+ struct nameidata *);
+extern struct dentry * cifs_lookup(struct inode *, struct dentry *,
+ struct nameidata *);
extern int cifs_unlink(struct inode *, struct dentry *);
extern int cifs_hardlink(struct dentry *, struct inode *, struct dentry *);
extern int cifs_mknod(struct inode *, struct dentry *, int, dev_t);
@@ -60,6 +62,7 @@ extern struct inode_operations cifs_symlink_inode_ops;
/* Functions related to files and directories */
extern struct file_operations cifs_file_ops;
+extern struct file_operations cifs_file_direct_ops; /* if directio mount */
extern int cifs_open(struct inode *inode, struct file *file);
extern int cifs_close(struct inode *inode, struct file *file);
extern int cifs_closedir(struct inode *inode, struct file *file);
@@ -82,7 +85,8 @@ extern struct dentry_operations cifs_dentry_ops;
/* Functions related to symlinks */
extern int cifs_follow_link(struct dentry *direntry, struct nameidata *nd);
extern void cifs_put_link(struct dentry *direntry, struct nameidata *nd);
-extern int cifs_readlink(struct dentry *direntry, char __user *buffer, int buflen);
+extern int cifs_readlink(struct dentry *direntry, char __user *buffer,
+ int buflen);
extern int cifs_symlink(struct inode *inode, struct dentry *direntry,
const char *symname);
extern int cifs_removexattr(struct dentry *, const char *);
@@ -90,5 +94,5 @@ extern int cifs_setxattr(struct dentry *, const char *, const void *,
size_t, int);
extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t);
extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
-#define CIFS_VERSION "1.28"
+#define CIFS_VERSION "1.31"
#endif /* _CIFSFS_H */
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 87e8b3d760bd1..69aff1a7da9b3 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -176,6 +176,7 @@ struct cifsSesInfo {
enum statusEnum status;
__u32 sequence_number; /* needed for CIFS PDU signature */
__u16 ipc_tid; /* special tid for connection to IPC share */
+ __u16 flags;
char mac_signing_key[CIFS_SESSION_KEY_SIZE + 16];
char *serverOS; /* name of operating system underlying the server */
char *serverNOS; /* name of network operating system that the server is running */
@@ -188,6 +189,8 @@ struct cifsSesInfo {
char domainName[MAX_USERNAME_SIZE + 1];
char * password;
};
+/* session flags */
+#define CIFS_SES_NT4 1
/*
* there is one of these for each connection to a resource on a particular
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
index ae31f666ec53f..bcd4a6136f08a 100644
--- a/fs/cifs/cifspdu.h
+++ b/fs/cifs/cifspdu.h
@@ -36,6 +36,7 @@
#define SMB_COM_CLOSE 0x04 /* triv req/rsp, timestamp ignored */
#define SMB_COM_DELETE 0x06 /* trivial response */
#define SMB_COM_RENAME 0x07 /* trivial response */
+#define SMB_COM_SETATTR 0x09 /* trivial response */
#define SMB_COM_LOCKING_ANDX 0x24 /* trivial response */
#define SMB_COM_COPY 0x29 /* trivial rsp, fail filename ignrd*/
#define SMB_COM_READ_ANDX 0x2E
@@ -568,7 +569,6 @@ typedef struct smb_com_tconx_rsp {
#define SMB_SHARE_IS_IN_DFS 0x0002
typedef struct smb_com_logoff_andx_req {
-
struct smb_hdr hdr; /* wct = 2 */
__u8 AndXCommand;
__u8 AndXReserved;
@@ -695,7 +695,8 @@ typedef struct smb_com_write_rsp {
__le16 AndXOffset;
__le16 Count;
__le16 Remaining;
- __le32 Reserved;
+ __le16 CountHigh;
+ __u16 Reserved;
__u16 ByteCount;
} WRITE_RSP;
@@ -865,6 +866,24 @@ typedef struct smb_com_create_directory_rsp {
__u16 ByteCount; /* bct = 0 */
} CREATE_DIRECTORY_RSP;
+typedef struct smb_com_setattr_req {
+ struct smb_hdr hdr; /* wct = 8 */
+ __le16 attr;
+ __le16 time_low;
+ __le16 time_high;
+ __le16 reserved[5]; /* must be zero */
+ __u16 ByteCount;
+ __u8 BufferFormat; /* 4 = ASCII */
+ unsigned char fileName[1];
+} SETATTR_REQ;
+
+typedef struct smb_com_setattr_rsp {
+ struct smb_hdr hdr; /* wct = 0 */
+ __u16 ByteCount; /* bct = 0 */
+} SETATTR_RSP;
+
+/* empty wct response to setattr */
+
/***************************************************/
/* NT Transact structure defintions follow */
/* Currently only ioctl and notify are implemented */
@@ -1078,6 +1097,7 @@ struct smb_t2_rsp {
#define SMB_QUERY_FILE_UNIX_LINK 0x201
#define SMB_QUERY_POSIX_ACL 0x204
#define SMB_QUERY_XATTR 0x205
+#define SMB_QUERY_ATTR_FLAGS 0x206 /* append,immutable etc. */
#define SMB_QUERY_FILE_INTERNAL_INFO 0x3ee
#define SMB_QUERY_FILE_ACCESS_INFO 0x3f0
#define SMB_QUERY_FILE_NAME_INFO2 0x3f1 /* 0x30 bytes */
@@ -1095,6 +1115,7 @@ struct smb_t2_rsp {
#define SMB_SET_FILE_UNIX_HLINK 0x203
#define SMB_SET_POSIX_ACL 0x204
#define SMB_SET_XATTR 0x205
+#define SMB_SET_ATTR_FLAGS 0x206 /* append, immutable etc. */
#define SMB_SET_FILE_BASIC_INFO2 0x3ec
#define SMB_SET_FILE_RENAME_INFORMATION 0x3f2 /* BB check if qpathinfo level too */
#define SMB_FILE_ALL_INFO2 0x3fa
@@ -1325,6 +1346,7 @@ typedef struct smb_com_transaction2_fnext_rsp_parms {
#define SMB_QUERY_FS_DEVICE_INFO 0x104
#define SMB_QUERY_FS_ATTRIBUTE_INFO 0x105
#define SMB_QUERY_CIFS_UNIX_INFO 0x200
+#define SMB_QUERY_POSIX_FS_INFO 0x201
#define SMB_QUERY_LABEL_INFO 0x3ea
#define SMB_QUERY_FS_QUOTA_INFO 0x3ee
#define SMB_QUERY_FS_FULL_SIZE_INFO 0x3ef
@@ -1505,6 +1527,28 @@ typedef struct {
#define CIFS_UNIX_POSIX_ACL_CAP 0x00000002
#define CIFS_UNIX_XATTR_CAP 0x00000004 /*support for new namespace*/
+typedef struct {
+ /* For undefined recommended transfer size return -1 in that field */
+ __le32 OptimalTransferSize; /* bsize on some os, iosize on other os */
+ __le32 BlockSize;
+ /* The next three fields are in terms of the block size.
+ (above). If block size is unknown, 4096 would be a
+ reasonable block size for a server to report.
+ Note that returning the blocks/blocksavail removes need
+ to make a second call (to QFSInfo level 0x103 to get this info.
+ UserBlockAvail is typically less than or equal to BlocksAvail,
+ if no distinction is made return the same value in each */
+ __le64 TotalBlocks;
+ __le64 BlocksAvail; /* bfree */
+ __le64 UserBlocksAvail; /* bavail */
+ /* For undefined Node fields or FSID return -1 */
+ __le64 TotalFileNodes;
+ __le64 FreeFileNodes;
+ __le64 FileSysIdentifier; /* fsid */
+ /* NB Namelen comes from FILE_SYSTEM_ATTRIBUTE_INFO call */
+ /* NB flags can come from FILE_SYSTEM_DEVICE_INFO call */
+} FILE_SYSTEM_POSIX_INFO;
+
/* DeviceType Flags */
#define FILE_DEVICE_CD_ROM 0x00000002
#define FILE_DEVICE_CD_ROM_FILE_SYSTEM 0x00000003
@@ -1592,17 +1636,32 @@ typedef struct {
char LinkDest[1];
} FILE_UNIX_LINK_INFO; /* level 0x201 QPathInfo */
+/* The following three structures are needed only for
+ setting time to NT4 and some older servers via
+ the primitive DOS time format */
+typedef struct {
+ __u16 Day:5;
+ __u16 Month:4;
+ __u16 Year:7;
+} SMB_DATE;
+
typedef struct {
- __u16 CreationDate;
- __u16 CreationTime;
- __u16 LastAccessDate;
- __u16 LastAccessTime;
- __u16 LastWriteDate;
- __u16 LastWriteTime;
- __u32 DataSize; /* File Size (EOF) */
- __u32 AllocationSize;
- __u16 Attributes; /* verify not u32 */
- __u32 EASize;
+ __u16 TwoSeconds:5;
+ __u16 Minutes:6;
+ __u16 Hours:5;
+} SMB_TIME;
+
+typedef struct {
+ __le16 CreationDate; /* SMB Date see above */
+ __le16 CreationTime; /* SMB Time */
+ __le16 LastAccessDate;
+ __le16 LastAccessTime;
+ __le16 LastWriteDate;
+ __le16 LastWriteTime;
+ __le32 DataSize; /* File Size (EOF) */
+ __le32 AllocationSize;
+ __le16 Attributes; /* verify not u32 */
+ __le32 EASize;
} FILE_INFO_STANDARD; /* level 1 SetPath/FileInfo */
typedef struct {
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 308ed2a4a4e08..787eef4d86d37 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -1,7 +1,7 @@
/*
* fs/cifs/cifsproto.h
*
- * Copyright (c) International Business Machines Corp., 2002,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
@@ -50,16 +50,18 @@ extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *,
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);
+extern int is_size_safe_to_change(struct cifsInodeInfo *);
extern unsigned int smbCalcSize(struct smb_hdr *ptr);
extern int decode_negTokenInit(unsigned char *security_blob, int length,
enum securityEnum *secType);
+extern int cifs_inet_pton(int, char * source, void *dst);
extern int map_smb_to_linux_error(struct smb_hdr *smb);
extern void header_assemble(struct smb_hdr *, char /* command */ ,
const struct cifsTconInfo *, int
/* length of fixed section (word count) in two byte units */
);
-struct oplock_q_entry * AllocOplockQEntry(struct inode *, u16, struct cifsTconInfo *);
-void DeleteOplockQEntry(struct oplock_q_entry *);
+extern struct oplock_q_entry * AllocOplockQEntry(struct inode *, u16, struct cifsTconInfo *);
+extern void DeleteOplockQEntry(struct oplock_q_entry *);
extern struct timespec cifs_NTtimeToUnix(u64 /* utc nanoseconds since 1601 */ );
extern u64 cifs_UnixTimeToNT(struct timespec);
extern int cifs_get_inode_info(struct inode **pinode,
@@ -70,6 +72,12 @@ extern int cifs_get_inode_info_unix(struct inode **pinode,
const unsigned char *search_path,
struct super_block *sb,int xid);
+extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *,
+ const char *);
+extern int cifs_umount(struct super_block *, struct cifs_sb_info *);
+void cifs_proc_init(void);
+void cifs_proc_clean(void);
+
extern int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
struct nls_table * nls_info);
extern int CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses);
@@ -79,18 +87,11 @@ 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,
- FILE_DIRECTORY_INFO * findData,
- T2_FFIRST_RSP_PARMS * findParms,
- const struct nls_table *nls_codepage,
- int *pUnicodeFlag,
- int *pUnixFlag /* if Unix extensions used */ );
+ const char *searchName, const struct nls_table *nls_codepage,
+ __u16 *searchHandle, struct cifs_search_info * psrch_inf);
+
extern int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
- FILE_DIRECTORY_INFO * findData,
- T2_FNEXT_RSP_PARMS * findParms,
- const __u16 searchHandle, char * resume_name,
- int name_length, __u32 resume_key,
- int *UnicodeFlag, int *pUnixFlag);
+ __u16 searchHandle, struct cifs_search_info * psrch_inf);
extern int CIFSFindClose(const int, struct cifsTconInfo *tcon,
const __u16 search_handle);
@@ -128,10 +129,19 @@ extern int CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon,
const struct nls_table *nls_codepage);
extern int CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon,
const struct nls_table *nls_codepage);
+extern int CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
+ struct kstatfs *FSData, const struct nls_table *nls_codepage);
extern int CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon,
const char *fileName, const FILE_BASIC_INFO * data,
const struct nls_table *nls_codepage);
+extern int CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon,
+ const FILE_BASIC_INFO * data, __u16 fid);
+#if 0
+extern int CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon,
+ char *fileName, __u16 dos_attributes,
+ const struct nls_table *nls_codepage);
+#endif /* possibly unneeded function */
extern int CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon,
const char *fileName, __u64 size,int setAllocationSizeFlag,
const struct nls_table *nls_codepage);
@@ -194,6 +204,16 @@ extern int CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
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,
+ const char __user *buf,const int long_op);
+extern int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
+ const unsigned char *searchName, __u64 * inode_number,
+ const struct nls_table *nls_codepage);
+#endif /* CONFIG_CIFS_EXPERIMENTAL */
+
extern int CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
const __u16 netfid, const __u64 len,
const __u64 offset, const __u32 numUnlock,
@@ -211,10 +231,10 @@ extern void tconInfoFree(struct cifsTconInfo *);
extern int cifs_reconnect(struct TCP_Server_Info *server);
extern int cifs_sign_smb(struct smb_hdr *, struct cifsSesInfo *,__u32 *);
-extern int cifs_verify_signature(const struct smb_hdr *, const char * mac_key,
+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);
-extern void CalcNTLMv2_partial_mac_key(struct cifsSesInfo *, struct nls_table *);
+extern int CalcNTLMv2_partial_mac_key(struct cifsSesInfo *, struct nls_table *);
extern void CalcNTLMv2_response(const struct cifsSesInfo *,char * );
extern int CIFSSMBCopy(int xid,
struct cifsTconInfo *source_tcon,
@@ -244,4 +264,6 @@ extern int CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
const unsigned char *fileName,
const char *local_acl, const int buflen, const int acl_type,
const struct nls_table *nls_codepage);
+int cifs_ioctl (struct inode * inode, struct file * filep,
+ unsigned int command, unsigned long arg);
#endif /* _CIFSPROTO_H */
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 81a6c9ebda6ad..df6a619a68213 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -1,7 +1,7 @@
/*
* fs/cifs/cifssmb.c
*
- * Copyright (C) International Business Machines Corp., 2002,2003
+ * Copyright (C) International Business Machines Corp., 2002,2005
* Author(s): Steve French (sfrench@us.ibm.com)
*
* Contains the routines for constructing the SMB PDUs themselves
@@ -78,6 +78,7 @@ static void mark_open_files_invalid(struct cifsTconInfo * pTcon)
/* BB Add call to invalidate_inodes(sb) for all superblocks mounted to this tcon */
}
+/* If the return code is zero, this function must fill in request_buf pointer */
static int
small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
void **request_buf /* returned */)
@@ -154,7 +155,7 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
return rc;
*request_buf = cifs_small_buf_get();
- if (*request_buf == 0) {
+ if (*request_buf == NULL) {
/* BB should we add a retry in here if not a writepage? */
return -ENOMEM;
}
@@ -169,6 +170,7 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
return rc;
}
+/* If the return code is zero, this function must fill in request_buf pointer */
static int
smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
void **request_buf /* returned */ ,
@@ -246,7 +248,7 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
return rc;
*request_buf = cifs_buf_get();
- if (*request_buf == 0) {
+ if (*request_buf == NULL) {
/* BB should we add a retry in here if not a writepage? */
return -ENOMEM;
}
@@ -448,7 +450,7 @@ CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
return 0;
}
- if((tcon->ses == 0) || (tcon->ses->server == 0)) {
+ if((tcon->ses == NULL) || (tcon->ses->server == NULL)) {
up(&tcon->tconSem);
return -EIO;
}
@@ -496,6 +498,11 @@ CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
return -EBUSY;
}
rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
+ if (rc) {
+ up(&ses->sesSem);
+ return rc;
+ }
+
smb_buffer_response = (struct smb_hdr *)pSMB; /* BB removeme BB */
if(ses->server) {
@@ -504,11 +511,6 @@ CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
}
- if (rc) {
- up(&ses->sesSem);
- return rc;
- }
-
pSMB->hdr.Uid = ses->Suid;
pSMB->AndXCommand = 0xFF;
@@ -579,8 +581,7 @@ DelFileRetry:
}
#endif
- if (pSMB)
- cifs_buf_release(pSMB);
+ cifs_buf_release(pSMB);
if (rc == -EAGAIN)
goto DelFileRetry;
@@ -630,8 +631,7 @@ RmDirRetry:
}
#endif
- if (pSMB)
- cifs_buf_release(pSMB);
+ cifs_buf_release(pSMB);
if (rc == -EAGAIN)
goto RmDirRetry;
return rc;
@@ -679,8 +679,7 @@ MkDirRetry:
atomic_inc(&tcon->num_mkdirs);
}
#endif
- if (pSMB)
- cifs_buf_release(pSMB);
+ cifs_buf_release(pSMB);
if (rc == -EAGAIN)
goto MkDirRetry;
return rc;
@@ -780,8 +779,7 @@ openRetry:
atomic_inc(&tcon->num_opens);
#endif
}
- if (pSMB)
- cifs_buf_release(pSMB);
+ cifs_buf_release(pSMB);
if (rc == -EAGAIN)
goto openRetry;
return rc;
@@ -802,6 +800,8 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
char *pReadData = NULL;
int bytes_returned;
+ cFYI(1,("Reading %d bytes on fid %d",count,netfid));
+
*nbytes = 0;
rc = smb_init(SMB_COM_READ_ANDX, 12, tcon, (void **) &pSMB,
(void **) &pSMBr);
@@ -817,8 +817,8 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
pSMB->Remaining = 0;
- pSMB->MaxCount = cpu_to_le16(count);
- pSMB->MaxCountHigh = 0;
+ pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
+ pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
pSMB->ByteCount = 0; /* no need to do le conversion since it is 0 */
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
@@ -826,8 +826,11 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
if (rc) {
cERROR(1, ("Send error in read = %d", rc));
} else {
- __u16 data_length = le16_to_cpu(pSMBr->DataLength);
+ int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
+ data_length = data_length << 16;
+ data_length += le16_to_cpu(pSMBr->DataLength);
*nbytes = data_length;
+
/*check that DataLength would not go beyond end of SMB */
if ((data_length > CIFSMaxBufSize)
|| (data_length > count)) {
@@ -846,12 +849,10 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
memcpy(*buf,pReadData,data_length);
}
}
- if (pSMB) {
- if(*buf)
- cifs_buf_release(pSMB);
- else
- *buf = (char *)pSMB;
- }
+ if(*buf)
+ cifs_buf_release(pSMB);
+ else
+ *buf = (char *)pSMB;
/* Note: On -EAGAIN error only caller can retry on handle based calls
since file handle passed in no longer valid */
@@ -868,9 +869,10 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
WRITE_REQ *pSMB = NULL;
WRITE_RSP *pSMBr = NULL;
int bytes_returned;
- unsigned bytes_sent;
+ __u32 bytes_sent;
__u16 byte_count;
+ /* cFYI(1,("write at %lld %d bytes",offset,count));*/
rc = smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB,
(void **) &pSMBr);
if (rc)
@@ -886,31 +888,39 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
pSMB->Reserved = 0xFFFFFFFF;
pSMB->WriteMode = 0;
pSMB->Remaining = 0;
- /* BB can relax this if buffer is big enough in some cases - ie we can
- send more if LARGE_WRITE_X capability returned by the server and if
+
+ /* Can increase buffer size if buffer is big enough in some cases - ie we
+ can send more if LARGE_WRITE_X capability returned by the server and if
our buffer is big enough or if we convert to iovecs on socket writes
and eliminate the copy to the CIFS buffer */
- bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & ~0xFF;
+ if(tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
+ bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
+ } else {
+ bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
+ & ~0xFF;
+ }
+
if (bytes_sent > count)
bytes_sent = count;
- pSMB->DataLengthHigh = 0;
pSMB->DataOffset =
cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
- if(buf)
+ if(buf)
memcpy(pSMB->Data,buf,bytes_sent);
- else if(ubuf)
- copy_from_user(pSMB->Data,ubuf,bytes_sent);
- else {
- /* No buffer */
- if(pSMB)
+ else if(ubuf) {
+ if(copy_from_user(pSMB->Data,ubuf,bytes_sent)) {
cifs_buf_release(pSMB);
+ return -EFAULT;
+ }
+ } else {
+ /* No buffer */
+ cifs_buf_release(pSMB);
return -EINVAL;
}
- byte_count = bytes_sent + 1 /* pad */ ;
- pSMB->DataLengthLow = cpu_to_le16(bytes_sent);
- pSMB->DataLengthHigh = 0;
- pSMB->hdr.smb_buf_length += byte_count;
+ byte_count = bytes_sent + 1 /* pad */ ; /* BB fix this for sends > 64K */
+ pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
+ pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
+ pSMB->hdr.smb_buf_length += bytes_sent+1;
pSMB->ByteCount = cpu_to_le16(byte_count);
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
@@ -918,11 +928,13 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
if (rc) {
cFYI(1, ("Send error in write = %d", rc));
*nbytes = 0;
- } else
- *nbytes = le16_to_cpu(pSMBr->Count);
+ } else {
+ *nbytes = le16_to_cpu(pSMBr->CountHigh);
+ *nbytes = (*nbytes) << 16;
+ *nbytes += le16_to_cpu(pSMBr->Count);
+ }
- if (pSMB)
- cifs_buf_release(pSMB);
+ cifs_buf_release(pSMB);
/* Note: On -EAGAIN error only caller can retry on handle based calls
since file handle passed in no longer valid */
@@ -944,10 +956,12 @@ int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
__u16 byte_count;
rc = small_smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB);
- pSMBr = (WRITE_RSP *)pSMB; /* BB removeme BB */
- if (rc)
+ if (rc)
return rc;
+
+ pSMBr = (WRITE_RSP *)pSMB; /* BB removeme BB */
+
/* tcon and ses pointer are checked in smb_init */
if (tcon->ses->server == NULL)
return -ECONNABORTED;
@@ -980,8 +994,7 @@ int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
} else
*nbytes = le16_to_cpu(pSMBr->Count);
- if (pSMB)
- cifs_small_buf_release(pSMB);
+ cifs_small_buf_release(pSMB);
/* Note: On -EAGAIN error only caller can retry on handle based calls
since file handle passed in no longer valid */
@@ -1046,8 +1059,7 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
if (rc) {
cFYI(1, ("Send error in Lock = %d", rc));
}
- if (pSMB)
- cifs_buf_release(pSMB);
+ cifs_buf_release(pSMB);
/* Note: On -EAGAIN error only caller can retry on handle based calls
since file handle passed in no longer valid */
@@ -1065,12 +1077,13 @@ CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
/* do not retry on dead session on close */
rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
- pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
if(rc == -EAGAIN)
return 0;
if (rc)
return rc;
+ pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
+
pSMB->FileID = (__u16) smb_file_id;
pSMB->LastWriteTime = 0;
pSMB->ByteCount = 0;
@@ -1083,8 +1096,7 @@ CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
}
}
- if (pSMB)
- cifs_small_buf_release(pSMB);
+ cifs_small_buf_release(pSMB);
/* Since session is dead, file will be closed on server already */
if(rc == -EAGAIN)
@@ -1161,8 +1173,7 @@ renameRetry:
}
#endif
- if (pSMB)
- cifs_buf_release(pSMB);
+ cifs_buf_release(pSMB);
if (rc == -EAGAIN)
goto renameRetry;
@@ -1241,8 +1252,7 @@ int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
atomic_inc(&pTcon->num_t2renames);
}
#endif
- if (pSMB)
- cifs_buf_release(pSMB);
+ cifs_buf_release(pSMB);
/* Note: On -EAGAIN error only caller can retry on handle based calls
since file handle passed in no longer valid */
@@ -1492,8 +1502,7 @@ createHardLinkRetry:
cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
}
- if (pSMB)
- cifs_buf_release(pSMB);
+ cifs_buf_release(pSMB);
if (rc == -EAGAIN)
goto createHardLinkRetry;
@@ -1564,8 +1573,7 @@ winCreateHardLinkRetry:
if (rc) {
cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
}
- if (pSMB)
- cifs_buf_release(pSMB);
+ cifs_buf_release(pSMB);
if (rc == -EAGAIN)
goto winCreateHardLinkRetry;
@@ -1665,15 +1673,12 @@ querySymLinkRetry:
/* just in case so calling code does not go off the end of buffer */
}
}
- if (pSMB)
- cifs_buf_release(pSMB);
+ cifs_buf_release(pSMB);
if (rc == -EAGAIN)
goto querySymLinkRetry;
return rc;
}
-
-
int
CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
const unsigned char *searchName,
@@ -1723,9 +1728,23 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
rc = -EIO; /* bad smb */
else {
if(data_count && (data_count < 2048)) {
- /* could also validate reparse tag && better check name length */
+ char * end_of_smb = pSMBr->ByteCount + (char *)&pSMBr->ByteCount;
+
struct reparse_data * reparse_buf = (struct reparse_data *)
((char *)&pSMBr->hdr.Protocol + data_offset);
+ if((char*)reparse_buf >= end_of_smb) {
+ rc = -EIO;
+ goto qreparse_out;
+ }
+ if((reparse_buf->LinkNamesBuf +
+ reparse_buf->TargetNameOffset +
+ reparse_buf->TargetNameLen) >
+ end_of_smb) {
+ cFYI(1,("reparse buf extended beyond SMB"));
+ rc = -EIO;
+ goto qreparse_out;
+ }
+
if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len = UniStrnlen((wchar_t *)
(reparse_buf->LinkNamesBuf +
@@ -1749,6 +1768,7 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
cFYI(1,("readlink result - %s ",symlinkinfo));
}
}
+qreparse_out:
if (pSMB)
cifs_buf_release(pSMB);
@@ -1826,7 +1846,7 @@ static int cifs_copy_posix_acl(char * trgt,char * src, const int buflen,const in
return size;
}
-__u16 convert_ace_to_cifs_ace(struct cifs_posix_ace * cifs_ace,
+static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace * cifs_ace,
const posix_acl_xattr_entry * local_ace)
{
__u16 rc = 0; /* 0 = ACL converted ok */
@@ -1844,7 +1864,7 @@ __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace * cifs_ace,
}
/* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
-__u16 ACL_to_cifs_posix(char * parm_data,const char * pACL,const int buflen,
+static __u16 ACL_to_cifs_posix(char * parm_data,const char * pACL,const int buflen,
const int acl_type)
{
__u16 rc = 0;
@@ -1913,14 +1933,13 @@ queryAclRetry:
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
- /* BB fixme find define for this maxpathcomponent */
, nls_codepage);
name_len++; /* trailing null */
name_len *= 2;
pSMB->FileName[name_len] = 0;
pSMB->FileName[name_len+1] = 0;
} else { /* BB improve the check for buffer overruns BB */
- name_len = strnlen(searchName, PATH_MAX /* BB fixme */);
+ name_len = strnlen(searchName, PATH_MAX);
name_len++; /* trailing null */
strncpy(pSMB->FileName, searchName, name_len);
}
@@ -1969,8 +1988,7 @@ queryAclRetry:
buflen,acl_type,count);
}
}
- if (pSMB)
- cifs_buf_release(pSMB);
+ cifs_buf_release(pSMB);
if (rc == -EAGAIN)
goto queryAclRetry;
return rc;
@@ -1996,10 +2014,9 @@ setAclRetry:
(void **) &pSMBr);
if (rc)
return rc;
- if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, PATH_MAX
- /* BB fixme find define for this maxpathcomponent */
, nls_codepage);
name_len++; /* trailing null */
name_len *= 2;
@@ -2049,11 +2066,10 @@ setAclRetry:
}
setACLerrorExit:
- if (pSMB)
- cifs_buf_release(pSMB);
- if (rc == -EAGAIN)
+ cifs_buf_release(pSMB);
+ if (rc == -EAGAIN)
goto setAclRetry;
- return rc;
+ return rc;
}
#endif
@@ -2072,7 +2088,7 @@ CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
int name_len;
__u16 params, byte_count;
-/* cFYI(1, ("In QPathInfo path %s", searchName)); */ /* BB fixme BB */
+/* cFYI(1, ("In QPathInfo path %s", searchName)); */
QPathInfoRetry:
rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
(void **) &pSMBr);
@@ -2133,8 +2149,7 @@ QPathInfoRetry:
} else
rc = -ENOMEM;
}
- if (pSMB)
- cifs_buf_release(pSMB);
+ cifs_buf_release(pSMB);
if (rc == -EAGAIN)
goto QPathInfoRetry;
@@ -2217,17 +2232,15 @@ UnixQPathInfoRetry:
sizeof (FILE_UNIX_BASIC_INFO));
}
}
- if (pSMB)
- cifs_buf_release(pSMB);
+ cifs_buf_release(pSMB);
if (rc == -EAGAIN)
goto UnixQPathInfoRetry;
return rc;
}
-#ifdef CONFIG_CIFS_EXPERIMENTAL /* function unused at present */
-int
-CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
+#if 0 /* function unused at present */
+int CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
const char *searchName, FILE_ALL_INFO * findData,
const struct nls_table *nls_codepage)
{
@@ -2297,127 +2310,18 @@ findUniqueRetry:
/* BB fill in */
}
- if (pSMB)
- cifs_buf_release(pSMB);
- if (rc == -EAGAIN)
- goto findUniqueRetry;
-
- return rc;
-}
-#endif /* CIFS_EXPERIMENTAL */
-
-int
-CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
- const char *searchName, FILE_DIRECTORY_INFO * findData,
- T2_FFIRST_RSP_PARMS * findParms,
- const struct nls_table *nls_codepage, int *pUnicodeFlag,
- int *pUnixFlag)
-{
-/* level 257 SMB_ */
- TRANSACTION2_FFIRST_REQ *pSMB = NULL;
- TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
- char *response_data;
- int rc = 0;
- int bytes_returned;
- int name_len;
- __u16 params, byte_count;
-
- cFYI(1, ("In FindFirst"));
-findFirstRetry:
- rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
- (void **) &pSMBr);
- if (rc)
- return rc;
-
- if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
- name_len =
- cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
- /* find define for this maxpathcomponent */
- , nls_codepage);
- name_len++; /* trailing null */
- name_len *= 2;
- } else { /* BB improve the check for buffer overruns BB */
- name_len = strnlen(searchName, PATH_MAX);
- name_len++; /* trailing null */
- strncpy(pSMB->FileName, searchName, name_len);
- }
-
- params = 12 + name_len /* includes null */ ;
- pSMB->TotalDataCount = 0; /* no EAs */
- pSMB->MaxParameterCount = cpu_to_le16(10);
- pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
- MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
- pSMB->MaxSetupCount = 0;
- pSMB->Reserved = 0;
- pSMB->Flags = 0;
- pSMB->Timeout = 0;
- pSMB->Reserved2 = 0;
- byte_count = params + 1 /* pad */ ;
- pSMB->TotalParameterCount = cpu_to_le16(params);
- pSMB->ParameterCount = pSMB->TotalParameterCount;
- pSMB->ParameterOffset = cpu_to_le16(
- offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes) - 4);
- pSMB->DataCount = 0;
- pSMB->DataOffset = 0;
- pSMB->SetupCount = 1; /* one byte no need to make endian neutral */
- pSMB->Reserved3 = 0;
- pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
- pSMB->SearchAttributes =
- cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
- ATTR_DIRECTORY);
- pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_DIRECTORY_INFO)); /* should this be shrunk even more ? */
- pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
-
- /* test for Unix extensions */
- if (tcon->ses->capabilities & CAP_UNIX) {
- pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
- *pUnixFlag = TRUE;
- } else {
- pSMB->InformationLevel =
- cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
- *pUnixFlag = FALSE;
- }
- pSMB->SearchStorageType = 0; /* BB what should we set this to? It is not clear if it matters BB */
- pSMB->hdr.smb_buf_length += byte_count;
- pSMB->ByteCount = cpu_to_le16(byte_count);
-
- rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
- (struct smb_hdr *) pSMBr, &bytes_returned, 0);
-
- if (rc) { /* BB add logic to retry regular search if Unix search rejected unexpectedly by server */
- cFYI(1, ("Error in FindFirst = %d", rc));
- } else {
- rc = validate_t2((struct smb_t2_rsp *)pSMBr);
- if(!rc) {
- /* decode response */
- /* BB add safety checks for these memcpys */
- if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
- *pUnicodeFlag = TRUE;
- else
- *pUnicodeFlag = FALSE;
- memcpy(findParms,
- (char *) &pSMBr->hdr.Protocol +
- le16_to_cpu(pSMBr->t2.ParameterOffset),
- sizeof (T2_FFIRST_RSP_PARMS));
- response_data =
- (char *) &pSMBr->hdr.Protocol +
- le16_to_cpu(pSMBr->t2.DataOffset);
- memcpy(findData, response_data,
- le16_to_cpu(pSMBr->t2.DataCount));
- }
- }
- if (pSMB)
- cifs_buf_release(pSMB);
+ cifs_buf_release(pSMB);
if (rc == -EAGAIN)
- goto findFirstRetry;
+ goto findUniqueRetry;
return rc;
}
+#endif /* end unused (temporarily) function */
/* xid, tcon, searchName and codepage are input parms, rest are returned */
int
-CIFSFindFirst2(const int xid, struct cifsTconInfo *tcon,
+CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
const char *searchName,
const struct nls_table *nls_codepage,
__u16 * pnetfid,
@@ -2432,9 +2336,9 @@ CIFSFindFirst2(const int xid, struct cifsTconInfo *tcon,
int name_len;
__u16 params, byte_count;
- cFYI(1, ("In FindFirst2"));
+ cFYI(1, ("In FindFirst"));
-findFirst2Retry:
+findFirstRetry:
rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
(void **) &pSMBr);
if (rc)
@@ -2504,7 +2408,7 @@ findFirst2Retry:
/* BB eventually could optimize out free and realloc of buf */
/* for this case */
if (rc == -EAGAIN)
- goto findFirst2Retry;
+ goto findFirstRetry;
} else { /* decode response */
/* BB remember to free buffer if error BB */
rc = validate_t2((struct smb_t2_rsp *)pSMBr);
@@ -2533,15 +2437,14 @@ findFirst2Retry:
/*cFYI(1,("entries in buf %d index_of_last %d",psrch_inf->entries_in_buffer,psrch_inf->index_of_last_entry)); */
*pnetfid = parms->SearchHandle;
} else {
- if(pSMB)
- cifs_buf_release(pSMB);
+ cifs_buf_release(pSMB);
}
}
return rc;
}
-int CIFSFindNext2(const int xid, struct cifsTconInfo *tcon,
+int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
__u16 searchHandle, struct cifs_search_info * psrch_inf)
{
TRANSACTION2_FNEXT_REQ *pSMB = NULL;
@@ -2552,7 +2455,7 @@ int CIFSFindNext2(const int xid, struct cifsTconInfo *tcon,
int bytes_returned, name_len;
__u16 params, byte_count;
- cFYI(1, ("In FindNext2"));
+ cFYI(1, ("In FindNext"));
if(psrch_inf->endOfSearch == TRUE)
return -ENOENT;
@@ -2659,120 +2562,13 @@ int CIFSFindNext2(const int xid, struct cifsTconInfo *tcon,
/* Note: On -EAGAIN error only caller can retry on handle based calls
since file handle passed in no longer valid */
FNext2_err_exit:
- if ((rc != 0) && pSMB)
+ if (rc != 0)
cifs_buf_release(pSMB);
return rc;
}
int
-CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
- FILE_DIRECTORY_INFO * findData, T2_FNEXT_RSP_PARMS * findParms,
- const __u16 searchHandle, char * resume_file_name, int name_len,
- __u32 resume_key, int *pUnicodeFlag, int *pUnixFlag)
-{
-/* level 257 SMB_ */
- TRANSACTION2_FNEXT_REQ *pSMB = NULL;
- TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
- char *response_data;
- int rc = 0;
- int bytes_returned;
- __u16 params, byte_count;
-
- cFYI(1, ("In FindNext"));
-
- if(resume_file_name == NULL) {
- return -EIO;
- }
- rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
- (void **) &pSMBr);
- if (rc)
- return rc;
-
- params = 14; /* includes 2 bytes of null string, converted to LE below */
- byte_count = 0;
- pSMB->TotalDataCount = 0; /* no EAs */
- pSMB->MaxParameterCount = cpu_to_le16(8);
- pSMB->MaxDataCount =
- cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
- pSMB->MaxSetupCount = 0;
- pSMB->Reserved = 0;
- pSMB->Flags = 0;
- pSMB->Timeout = 0;
- pSMB->Reserved2 = 0;
- pSMB->ParameterOffset = cpu_to_le16(
- offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
- pSMB->DataCount = 0;
- pSMB->DataOffset = 0;
- pSMB->SetupCount = 1;
- pSMB->Reserved3 = 0;
- pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
- pSMB->SearchHandle = searchHandle; /* always kept as le */
- findParms->SearchCount = 0; /* set to zero in case of error */
- pSMB->SearchCount =
- cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_UNIX_INFO));
- /* test for Unix extensions */
- if (tcon->ses->capabilities & CAP_UNIX) {
- pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
- *pUnixFlag = TRUE;
- } else {
- pSMB->InformationLevel =
- cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
- *pUnixFlag = FALSE;
- }
- pSMB->ResumeKey = resume_key;
- pSMB->SearchFlags =
- cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
- /* BB add check to make sure we do not cross end of smb */
- if(name_len < PATH_MAX) {
- memcpy(pSMB->ResumeFileName, resume_file_name, name_len);
- byte_count += name_len;
- }
- params += name_len;
- byte_count = params + 1 /* pad */ ;
- pSMB->TotalParameterCount = cpu_to_le16(params);
- pSMB->ParameterCount = pSMB->TotalParameterCount;
- /* BB improve error handling here */
- pSMB->hdr.smb_buf_length += byte_count;
- pSMB->ByteCount = cpu_to_le16(byte_count);
-
- rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
- (struct smb_hdr *) pSMBr, &bytes_returned, 0);
-
- if (rc) {
- if (rc == -EBADF)
- rc = 0; /* search probably was closed at end of search above */
- else
- cFYI(1, ("FindNext returned = %d", rc));
- } else { /* decode response */
- rc = validate_t2((struct smb_t2_rsp *)pSMBr);
-
- /* BB add safety checks for these memcpys */
- if(rc == 0) {
- if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
- *pUnicodeFlag = TRUE;
- else
- *pUnicodeFlag = FALSE;
- memcpy(findParms,
- (char *) &pSMBr->hdr.Protocol +
- le16_to_cpu(pSMBr->t2.ParameterOffset),
- sizeof (T2_FNEXT_RSP_PARMS));
- response_data =
- (char *) &pSMBr->hdr.Protocol +
- le16_to_cpu(pSMBr->t2.DataOffset);
- memcpy(findData,response_data,le16_to_cpu(pSMBr->t2.DataCount));
- }
- }
- if (pSMB)
- cifs_buf_release(pSMB);
-
- /* Note: On -EAGAIN error only caller can retry on handle based calls
- since file handle passed in no longer valid */
-
- return rc;
-}
-
-int
CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle)
{
int rc = 0;
@@ -2782,14 +2578,15 @@ CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle
cFYI(1, ("In CIFSSMBFindClose"));
rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
- pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
+
/* no sense returning error if session restarted
- file handle has been closed */
+ as file handle has been closed */
if(rc == -EAGAIN)
return 0;
if (rc)
return rc;
+ pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
pSMB->FileID = searchHandle;
pSMB->ByteCount = 0;
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
@@ -2797,8 +2594,7 @@ CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle
if (rc) {
cERROR(1, ("Send error in FindClose = %d", rc));
}
- if (pSMB)
- cifs_small_buf_release(pSMB);
+ cifs_small_buf_release(pSMB);
/* Since session is dead, search handle closed on server already */
if (rc == -EAGAIN)
@@ -2817,23 +2613,86 @@ CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
int rc = 0;
TRANSACTION2_QPI_REQ *pSMB = NULL;
TRANSACTION2_QPI_RSP *pSMBr = NULL;
+ int name_len, bytes_returned;
+ __u16 params, byte_count;
- cFYI(1,("In GetSrvInodeNumber for %s",searchName));
+ cFYI(1,("In GetSrvInodeNum for %s",searchName));
if(tcon == NULL)
return -ENODEV;
- cFYI(1, ("In QPathInfo path %s", searchName));
GetInodeNumberRetry:
rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
(void **) &pSMBr);
if (rc)
return rc;
-/* BB add missing code here */
- if (pSMB)
- cifs_buf_release(pSMB);
-
+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+ name_len =
+ cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName,
+ PATH_MAX,nls_codepage);
+ name_len++; /* trailing null */
+ name_len *= 2;
+ } else { /* BB improve the check for buffer overruns BB */
+ name_len = strnlen(searchName, PATH_MAX);
+ name_len++; /* trailing null */
+ strncpy(pSMB->FileName, searchName, name_len);
+ }
+
+ params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
+ pSMB->TotalDataCount = 0;
+ pSMB->MaxParameterCount = cpu_to_le16(2);
+ /* BB find exact max data count below from sess structure BB */
+ pSMB->MaxDataCount = cpu_to_le16(4000);
+ pSMB->MaxSetupCount = 0;
+ pSMB->Reserved = 0;
+ pSMB->Flags = 0;
+ pSMB->Timeout = 0;
+ pSMB->Reserved2 = 0;
+ pSMB->ParameterOffset = cpu_to_le16(offsetof(
+ struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
+ pSMB->DataCount = 0;
+ pSMB->DataOffset = 0;
+ pSMB->SetupCount = 1;
+ pSMB->Reserved3 = 0;
+ pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
+ byte_count = params + 1 /* pad */ ;
+ pSMB->TotalParameterCount = cpu_to_le16(params);
+ pSMB->ParameterCount = pSMB->TotalParameterCount;
+ pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
+ pSMB->Reserved4 = 0;
+ pSMB->hdr.smb_buf_length += byte_count;
+ pSMB->ByteCount = cpu_to_le16(byte_count);
+
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ if (rc) {
+ cFYI(1, ("error %d in QueryInternalInfo", rc));
+ } else {
+ /* decode response */
+ rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+ if (rc || (pSMBr->ByteCount < 2))
+ /* BB also check enough total bytes returned */
+ /* If rc should we check for EOPNOSUPP and
+ disable the srvino flag? or in caller? */
+ rc = -EIO; /* bad smb */
+ else {
+ __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
+ __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
+ struct file_internal_info * pfinfo;
+ /* BB Do we need a cast or hash here ? */
+ if(count < 8) {
+ cFYI(1, ("Illegal size ret in QryIntrnlInf"));
+ rc = -EIO;
+ goto GetInodeNumOut;
+ }
+ pfinfo = (struct file_internal_info *)
+ (data_offset + (char *) &pSMBr->hdr.Protocol);
+ *inode_number = pfinfo->UniqueId;
+ }
+ }
+GetInodeNumOut:
+ cifs_buf_release(pSMB);
if (rc == -EAGAIN)
goto GetInodeNumberRetry;
return rc;
@@ -3087,8 +2946,7 @@ QFSInfoRetry:
FSData->f_bsize));
}
}
- if (pSMB)
- cifs_buf_release(pSMB);
+ cifs_buf_release(pSMB);
if (rc == -EAGAIN)
goto QFSInfoRetry;
@@ -3157,8 +3015,7 @@ QFSAttributeRetry:
sizeof (FILE_SYSTEM_ATTRIBUTE_INFO));
}
}
- if (pSMB)
- cifs_buf_release(pSMB);
+ cifs_buf_release(pSMB);
if (rc == -EAGAIN)
goto QFSAttributeRetry;
@@ -3228,8 +3085,7 @@ QFSDeviceRetry:
sizeof (FILE_SYSTEM_DEVICE_INFO));
}
}
- if (pSMB)
- cifs_buf_release(pSMB);
+ cifs_buf_release(pSMB);
if (rc == -EAGAIN)
goto QFSDeviceRetry;
@@ -3298,8 +3154,7 @@ QFSUnixRetry:
sizeof (FILE_SYSTEM_UNIX_INFO));
}
}
- if (pSMB)
- cifs_buf_release(pSMB);
+ cifs_buf_release(pSMB);
if (rc == -EAGAIN)
goto QFSUnixRetry;
@@ -3308,6 +3163,93 @@ QFSUnixRetry:
return rc;
}
+
+int
+CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
+ struct kstatfs *FSData, const struct nls_table *nls_codepage)
+{
+/* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
+ TRANSACTION2_QFSI_REQ *pSMB = NULL;
+ TRANSACTION2_QFSI_RSP *pSMBr = NULL;
+ FILE_SYSTEM_POSIX_INFO *response_data;
+ int rc = 0;
+ int bytes_returned = 0;
+ __u16 params, byte_count;
+
+ cFYI(1, ("In QFSPosixInfo"));
+QFSPosixRetry:
+ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ params = 2; /* level */
+ pSMB->TotalDataCount = 0;
+ pSMB->DataCount = 0;
+ pSMB->DataOffset = 0;
+ pSMB->MaxParameterCount = cpu_to_le16(2);
+ pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
+ pSMB->MaxSetupCount = 0;
+ pSMB->Reserved = 0;
+ pSMB->Flags = 0;
+ pSMB->Timeout = 0;
+ pSMB->Reserved2 = 0;
+ byte_count = params + 1 /* pad */ ;
+ pSMB->ParameterCount = cpu_to_le16(params);
+ pSMB->TotalParameterCount = pSMB->ParameterCount;
+ pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
+ smb_com_transaction2_qfsi_req, InformationLevel) - 4);
+ pSMB->SetupCount = 1;
+ pSMB->Reserved3 = 0;
+ pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
+ pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
+ pSMB->hdr.smb_buf_length += byte_count;
+ pSMB->ByteCount = cpu_to_le16(byte_count);
+
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ if (rc) {
+ cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
+ } else { /* decode response */
+ rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+
+ if (rc || (pSMBr->ByteCount < 13)) {
+ rc = -EIO; /* bad smb */
+ } else {
+ __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
+ response_data =
+ (FILE_SYSTEM_POSIX_INFO
+ *) (((char *) &pSMBr->hdr.Protocol) +
+ data_offset);
+ FSData->f_bsize =
+ le32_to_cpu(response_data->BlockSize);
+ FSData->f_blocks =
+ le64_to_cpu(response_data->TotalBlocks);
+ FSData->f_bfree =
+ le64_to_cpu(response_data->BlocksAvail);
+ if(response_data->UserBlocksAvail == -1) {
+ FSData->f_bavail = FSData->f_bfree;
+ } else {
+ FSData->f_bavail =
+ le64_to_cpu(response_data->UserBlocksAvail);
+ }
+ if(response_data->TotalFileNodes != -1)
+ FSData->f_files =
+ le64_to_cpu(response_data->TotalFileNodes);
+ if(response_data->FreeFileNodes != -1)
+ FSData->f_ffree =
+ le64_to_cpu(response_data->FreeFileNodes);
+ }
+ }
+ cifs_buf_release(pSMB);
+
+ if (rc == -EAGAIN)
+ goto QFSPosixRetry;
+
+ return rc;
+}
+
+
/* We can not use write of zero bytes trick to
set file size due to need for large file support. Also note that
this SetPathInfo is preferred to SetFileInfo based method in next
@@ -3396,8 +3338,7 @@ SetEOFRetry:
cFYI(1, ("SetPathInfo (file size) returned %d", rc));
}
- if (pSMB)
- cifs_buf_release(pSMB);
+ cifs_buf_release(pSMB);
if (rc == -EAGAIN)
goto SetEOFRetry;
@@ -3491,90 +3432,87 @@ CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
return rc;
}
+/* Some legacy servers such as NT4 require that the file times be set on
+ an open handle, rather than by pathname - this is awkward due to
+ potential access conflicts on the open, but it is unavoidable for these
+ old servers since the only other choice is to go from 100 nanosecond DCE
+ time and resort to the original setpathinfo level which takes the ancient
+ DOS time format with 2 second granularity */
int
-CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName,
- const FILE_BASIC_INFO * data,
- const struct nls_table *nls_codepage)
+CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, const FILE_BASIC_INFO * data,
+ __u16 fid)
{
- TRANSACTION2_SPI_REQ *pSMB = NULL;
- TRANSACTION2_SPI_RSP *pSMBr = NULL;
- int name_len;
+ struct smb_com_transaction2_sfi_req *pSMB = NULL;
+ struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
+ char *data_offset;
int rc = 0;
int bytes_returned = 0;
- char *data_offset;
__u16 params, param_offset, offset, byte_count, count;
- cFYI(1, ("In SetTimes"));
-
-SetTimesRetry:
+ cFYI(1, ("Set Times (via SetFileInfo)"));
rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
(void **) &pSMBr);
if (rc)
return rc;
- if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
- name_len =
- cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, PATH_MAX
- /* find define for this maxpathcomponent */
- , nls_codepage);
- name_len++; /* trailing null */
- name_len *= 2;
- } else { /* BB improve the check for buffer overruns BB */
- name_len = strnlen(fileName, PATH_MAX);
- name_len++; /* trailing null */
- strncpy(pSMB->FileName, fileName, name_len);
- }
-
- params = 6 + name_len;
- count = sizeof (FILE_BASIC_INFO);
- pSMB->MaxParameterCount = cpu_to_le16(2);
- pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
+ /* At this point there is no need to override the current pid
+ with the pid of the opener, but that could change if we someday
+ use an existing handle (rather than opening one on the fly) */
+ /* pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
+ pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));*/
+
+ params = 6;
pSMB->MaxSetupCount = 0;
pSMB->Reserved = 0;
pSMB->Flags = 0;
pSMB->Timeout = 0;
pSMB->Reserved2 = 0;
- param_offset = offsetof(struct smb_com_transaction2_spi_req,
- InformationLevel) - 4;
+ param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
offset = param_offset + params;
- data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
- pSMB->ParameterOffset = cpu_to_le16(param_offset);
- pSMB->DataOffset = cpu_to_le16(offset);
+
+ data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
+
+ count = sizeof (FILE_BASIC_INFO);
+ pSMB->MaxParameterCount = cpu_to_le16(2);
+ pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
pSMB->SetupCount = 1;
pSMB->Reserved3 = 0;
- pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
+ pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
byte_count = 3 /* pad */ + params + count;
-
pSMB->DataCount = cpu_to_le16(count);
pSMB->ParameterCount = cpu_to_le16(params);
pSMB->TotalDataCount = pSMB->DataCount;
pSMB->TotalParameterCount = pSMB->ParameterCount;
+ pSMB->ParameterOffset = cpu_to_le16(param_offset);
+ pSMB->DataOffset = cpu_to_le16(offset);
+ pSMB->Fid = fid;
if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
else
pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
pSMB->Reserved4 = 0;
pSMB->hdr.smb_buf_length += byte_count;
- memcpy(data_offset, data, sizeof (FILE_BASIC_INFO));
pSMB->ByteCount = cpu_to_le16(byte_count);
+ memcpy(data_offset,data,sizeof(FILE_BASIC_INFO));
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
- cFYI(1, ("SetPathInfo (times) returned %d", rc));
+ cFYI(1,("Send error in Set Time (SetFileInfo) = %d",rc));
}
- if (pSMB)
- cifs_buf_release(pSMB);
+ cifs_buf_release(pSMB);
- if (rc == -EAGAIN)
- goto SetTimesRetry;
+ /* Note: On -EAGAIN error only caller can retry on handle based calls
+ since file handle passed in no longer valid */
return rc;
}
+
int
-CIFSSMBSetTimesLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
- FILE_INFO_STANDARD * data, const struct nls_table *nls_codepage)
+CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName,
+ const FILE_BASIC_INFO * data,
+ const struct nls_table *nls_codepage)
{
TRANSACTION2_SPI_REQ *pSMB = NULL;
TRANSACTION2_SPI_RSP *pSMBr = NULL;
@@ -3582,11 +3520,11 @@ CIFSSMBSetTimesLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
int rc = 0;
int bytes_returned = 0;
char *data_offset;
- __u16 params, param_offset, count, offset, byte_count;
+ __u16 params, param_offset, offset, byte_count, count;
- cFYI(1, ("In SetTimesLegacy"));
+ cFYI(1, ("In SetTimes"));
-SetTimesRetryLegacy:
+SetTimesRetry:
rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
(void **) &pSMBr);
if (rc)
@@ -3604,10 +3542,9 @@ SetTimesRetryLegacy:
name_len++; /* trailing null */
strncpy(pSMB->FileName, fileName, name_len);
}
-/* BB fixme - we have to map to FILE_STANDARD_INFO (level 1 info
- in parent function, from the better and ususal FILE_BASIC_INFO */
+
params = 6 + name_len;
- count = sizeof (FILE_INFO_STANDARD);
+ count = sizeof (FILE_BASIC_INFO);
pSMB->MaxParameterCount = cpu_to_le16(2);
pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
pSMB->MaxSetupCount = 0;
@@ -3630,25 +3567,80 @@ SetTimesRetryLegacy:
pSMB->ParameterCount = cpu_to_le16(params);
pSMB->TotalDataCount = pSMB->DataCount;
pSMB->TotalParameterCount = pSMB->ParameterCount;
- pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
+ if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
+ pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
+ else
+ pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
pSMB->Reserved4 = 0;
pSMB->hdr.smb_buf_length += byte_count;
- memcpy(data_offset, data, sizeof (FILE_INFO_STANDARD));
+ memcpy(data_offset, data, sizeof (FILE_BASIC_INFO));
pSMB->ByteCount = cpu_to_le16(byte_count);
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
- cFYI(1, ("SetPathInfo (times legacy) returned %d", rc));
+ cFYI(1, ("SetPathInfo (times) returned %d", rc));
}
- if (pSMB)
- cifs_buf_release(pSMB);
+ cifs_buf_release(pSMB);
+
+ if (rc == -EAGAIN)
+ goto SetTimesRetry;
+
+ return rc;
+}
+
+/* Can not be used to set time stamps yet (due to old DOS time format) */
+/* Can be used to set attributes */
+#if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
+ handling it anyway and NT4 was what we thought it would be needed for
+ Do not delete it until we prove whether needed for Win9x though */
+int
+CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
+ __u16 dos_attrs, const struct nls_table *nls_codepage)
+{
+ SETATTR_REQ *pSMB = NULL;
+ SETATTR_RSP *pSMBr = NULL;
+ int rc = 0;
+ int bytes_returned;
+ int name_len;
+
+ cFYI(1, ("In SetAttrLegacy"));
+
+SetAttrLgcyRetry:
+ rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
+ (void **) &pSMBr);
+ if (rc)
+ return rc;
+
+ if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+ name_len =
+ cifs_strtoUCS((wchar_t *) pSMB->fileName, fileName,
+ PATH_MAX, nls_codepage);
+ name_len++; /* trailing null */
+ name_len *= 2;
+ } else { /* BB improve the check for buffer overruns BB */
+ name_len = strnlen(fileName, PATH_MAX);
+ name_len++; /* trailing null */
+ strncpy(pSMB->fileName, fileName, name_len);
+ }
+ pSMB->attr = cpu_to_le16(dos_attrs);
+ pSMB->BufferFormat = 0x04;
+ pSMB->hdr.smb_buf_length += name_len + 1;
+ pSMB->ByteCount = cpu_to_le16(name_len + 1);
+ rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+ (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ if (rc) {
+ cFYI(1, ("Error in LegacySetAttr = %d", rc));
+ }
+
+ cifs_buf_release(pSMB);
if (rc == -EAGAIN)
- goto SetTimesRetryLegacy;
+ goto SetAttrLgcyRetry;
return rc;
}
+#endif /* temporarily unneeded SetAttr legacy function */
int
CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
@@ -3789,10 +3781,7 @@ int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
if (rc) {
cFYI(1, ("Error in Notify = %d", rc));
}
- if (pSMB)
- cifs_buf_release(pSMB);
-/* if (rc == -EAGAIN)
- goto NotifyRetry; */
+ cifs_buf_release(pSMB);
return rc;
}
#ifdef CONFIG_CIFS_XATTR
@@ -4162,7 +4151,8 @@ SetEARetry:
/* we checked above that name len is less than 255 */
parm_data->list[0].name_len = (__u8)name_len;;
/* EA names are always ASCII */
- strncpy(parm_data->list[0].name,ea_name,name_len);
+ if(ea_name)
+ strncpy(parm_data->list[0].name,ea_name,name_len);
parm_data->list[0].name[name_len] = 0;
parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
/* caller ensures that ea_value_len is less than 64K but
@@ -4185,8 +4175,7 @@ SetEARetry:
cFYI(1, ("SetPathInfo (EA) returned %d", rc));
}
- if (pSMB)
- cifs_buf_release(pSMB);
+ cifs_buf_release(pSMB);
if (rc == -EAGAIN)
goto SetEARetry;
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index ff8a4df480f3d..40470b9d5477a 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -47,7 +47,6 @@ extern void SMBencrypt(unsigned char *passwd, unsigned char *c8,
unsigned char *p24);
extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8,
unsigned char *p24);
-extern int cifs_inet_pton(int, const char *, void *dst);
extern mempool_t *cifs_req_poolp;
@@ -70,6 +69,7 @@ struct smb_vol {
unsigned setuids:1;
unsigned noperm:1;
unsigned no_psx_acl:1; /* set if posix acl support should be disabled */
+ 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 int rsize;
@@ -210,7 +210,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
current->flags |= PF_MEMALLOC;
server->tsk = current; /* save process info to wake at shutdown */
cFYI(1, ("Demultiplex PID: %d", current->pid));
- write_lock(&GlobalSMBSeslock);
+ write_lock(&GlobalSMBSeslock);
atomic_inc(&tcpSesAllocCount);
length = tcpSesAllocCount.counter;
write_unlock(&GlobalSMBSeslock);
@@ -233,17 +233,12 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
continue;
}
iov.iov_base = smb_buffer;
- iov.iov_len = sizeof (struct smb_hdr) - 1;
- /* 1 byte less above since wct is not always returned in error cases */
+ iov.iov_len = 4;
smb_msg.msg_control = NULL;
smb_msg.msg_controllen = 0;
-
length =
kernel_recvmsg(csocket, &smb_msg,
- &iov, 1,
- sizeof (struct smb_hdr) -
- 1 /* RFC1001 header and SMB header */ ,
- MSG_PEEK /* flags see socket.h */ );
+ &iov, 1, 4, 0 /* BB see socket.h flags */);
if(server->tcpStatus == CifsExiting) {
break;
@@ -253,8 +248,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
cFYI(1,("call to reconnect done"));
csocket = server->ssocket;
continue;
- } else if ((length == -ERESTARTSYS) || (length == -EAGAIN)
- || ((length > 0) && (length <= 3)) ) {
+ } else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) {
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(1); /* minimum sleep to prevent looping
allowing socket to clear and app threads to set
@@ -277,29 +271,18 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
csocket = server->ssocket;
wake_up(&server->response_q);
continue;
- }
-
- pdu_length = 4 + ntohl(smb_buffer->smb_buf_length);
+ } else if (length > 3) {
+ pdu_length = ntohl(smb_buffer->smb_buf_length);
/* Only read pdu_length after below checks for too short (due
to e.g. int overflow) and too long ie beyond end of buf */
- cFYI(1, ("Peek length rcvd: 0x%x beginning 0x%x)", length, pdu_length));
+ cFYI(1,("rfc1002 length(big endian)0x%x)", pdu_length+4));
- temp = (char *) smb_buffer;
- if (length > 3) {
+ temp = (char *) smb_buffer;
if (temp[0] == (char) RFC1002_SESSION_KEEP_ALIVE) {
- iov.iov_base = smb_buffer;
- iov.iov_len = 4;
- length = kernel_recvmsg(csocket, &smb_msg,
- &iov, 1, 4, 0);
cFYI(0,("Received 4 byte keep alive packet"));
} else if (temp[0] == (char) RFC1002_POSITIVE_SESSION_RESPONSE) {
- iov.iov_base = smb_buffer;
- iov.iov_len = 4;
- length = kernel_recvmsg(csocket, &smb_msg,
- &iov, 1, 4, 0);
cFYI(1,("Good RFC 1002 session rsp"));
- } else if ((temp[0] == (char)RFC1002_NEGATIVE_SESSION_RESPONSE)
- && (length == 5)) {
+ } else if (temp[0] == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) {
/* we get this from Windows 98 instead of error on SMB negprot response */
cFYI(1,("Negative RFC 1002 Session Response Error 0x%x)",temp[4]));
if(server->tcpStatus == CifsNew) {
@@ -330,38 +313,22 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
csocket = server->ssocket;
continue;
} else {
- if (length < 16) {
- /* We can not validate the SMB unless
- at least this much of SMB available
- so give the socket time to copy
- a few more bytes and retry */
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(10);
- continue;
- } else if( (pdu_length >
- CIFSMaxBufSize + MAX_CIFS_HDR_SIZE)
- || (pdu_length <
- sizeof (struct smb_hdr) - 1)
- || (checkSMBhdr
- (smb_buffer, smb_buffer->Mid))) {
+ if((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)
+ || (pdu_length < sizeof (struct smb_hdr) - 1 - 4)) {
cERROR(1,
- ("Invalid size or format for SMB found with length %d and pdu_length %d",
- length, pdu_length));
- cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr)+3);
- /* could we fix this network corruption by finding next
- smb header (instead of killing the session) and
- restart reading from next valid SMB found? */
+ ("Invalid size SMB length %d and pdu_length %d",
+ length, pdu_length+4));
cifs_reconnect(server);
csocket = server->ssocket;
+ wake_up(&server->response_q);
continue;
- } else { /* length ok */
-
+ } else { /* length ok */
length = 0;
- iov.iov_base = smb_buffer;
+ iov.iov_base = 4 + (char *)smb_buffer;
iov.iov_len = pdu_length;
for (total_read = 0;
total_read < pdu_length;
- total_read += length) {
+ total_read += length) {
length = kernel_recvmsg(csocket, &smb_msg,
&iov, 1,
pdu_length - total_read, 0);
@@ -371,14 +338,16 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
pdu_length - total_read));
cifs_reconnect(server);
csocket = server->ssocket;
+ wake_up(&server->response_q);
continue;
}
}
+ length += 4; /* account for rfc1002 hdr */
}
dump_smb(smb_buffer, length);
if (checkSMB
- (smb_buffer, smb_buffer->Mid, total_read)) {
+ (smb_buffer, smb_buffer->Mid, total_read+4)) {
cERROR(1, ("Bad SMB Received "));
continue;
}
@@ -410,17 +379,13 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
}
}
} else {
- cFYI(0,
- ("Frame less than four bytes received %d bytes long.",
+ cFYI(1,
+ ("Frame less than four bytes received %d bytes long.",
length));
- if (length > 0) {
- length = kernel_recvmsg(csocket, &smb_msg,
- &iov, 1,
- length, 0); /* throw away junk frame */
- cFYI(1,
- (" with junk 0x%x in it ",
- *(__u32 *) smb_buffer));
- }
+ cifs_reconnect(server);
+ csocket = server->ssocket;
+ wake_up(&server->response_q);
+ continue;
}
}
spin_lock(&GlobalMid_Lock);
@@ -505,7 +470,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
}
static void *
-cifs_kcalloc(size_t size, int type)
+cifs_kcalloc(size_t size, unsigned int __nocast type)
{
void *addr;
addr = kmalloc(size, type);
@@ -560,7 +525,12 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
continue;
if ((value = strchr(data, '=')) != NULL)
*value++ = '\0';
- if (strnicmp(data, "user", 4) == 0) {
+
+ if (strnicmp(data, "user_xattr",10) == 0) {/*parse before user*/
+ vol->no_xattr = 0;
+ } else if (strnicmp(data, "nouser_xattr",12) == 0) {
+ vol->no_xattr = 1;
+ } else if (strnicmp(data, "user", 4) == 0) {
if (!value || !*value) {
printk(KERN_WARNING
"CIFS: invalid or missing username\n");
@@ -573,9 +543,18 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
return 1;
}
} else if (strnicmp(data, "pass", 4) == 0) {
- if (!value || !*value) {
+ if (!value) {
vol->password = NULL;
continue;
+ } else if(value[0] == 0) {
+ /* check if string begins with double comma
+ since that would mean the password really
+ does start with a comma, and would not
+ indicate an empty string */
+ if(value[1] != separator[0]) {
+ vol->password = NULL;
+ continue;
+ }
}
temp_len = strlen(value);
/* removed password length check, NTLM passwords
@@ -590,15 +569,20 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
/* NB: password legally can have multiple commas and
the only illegal character in a password is null */
-
+
if ((value[temp_len] == 0) && (value[temp_len+1] == separator[0])) {
/* reinsert comma */
value[temp_len] = separator[0];
temp_len+=2; /* move after the second comma */
while(value[temp_len] != 0) {
- if((value[temp_len] == separator[0]) && (value[temp_len+1] != separator[0])) {
- /* single comma indicating start of next parm */
- break;
+ if (value[temp_len] == separator[0]) {
+ if (value[temp_len+1] == separator[0]) {
+ temp_len++; /* skip second comma */
+ } else {
+ /* single comma indicating start
+ of next parm */
+ break;
+ }
}
temp_len++;
}
@@ -606,10 +590,12 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
options = NULL;
} else {
value[temp_len] = 0;
- /* move options to point to start of next parm */
+ /* point option to start of next parm */
options = value + temp_len + 1;
}
- /* go from value to (value + temp_len) condensing double commas to singles */
+ /* go from value to value + temp_len condensing
+ double commas to singles. Note that this ends up
+ allocating a few bytes too many, which is ok */
vol->password = cifs_kcalloc(temp_len, GFP_KERNEL);
for(i=0,j=0;i<temp_len;i++,j++) {
vol->password[j] = value[i];
@@ -618,8 +604,7 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
i++;
}
}
- /* value[temp_len] is zeroed above so
- vol->password[temp_len] guaranteed to be null */
+ vol->password[j] = 0;
} else {
vol->password = cifs_kcalloc(temp_len + 1, GFP_KERNEL);
strcpy(vol->password, value);
@@ -845,7 +830,7 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
return 1;
}
}
- if(vol->UNCip == 0)
+ if(vol->UNCip == NULL)
vol->UNCip = &vol->UNC[2];
return 0;
@@ -1212,6 +1197,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
}
if (volume_info.username) {
+ /* BB fixme parse for domain name here */
cFYI(1, ("Username: %s ", volume_info.username));
} else {
@@ -1409,14 +1395,14 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
/* search for existing tcon to this server share */
if (!rc) {
- if((volume_info.rsize) && (volume_info.rsize + MAX_CIFS_HDR_SIZE < srvTcp->maxBuf))
+ if((volume_info.rsize) && (volume_info.rsize <= CIFSMaxBufSize))
cifs_sb->rsize = volume_info.rsize;
else
cifs_sb->rsize = srvTcp->maxBuf - MAX_CIFS_HDR_SIZE; /* default */
- if((volume_info.wsize) && (volume_info.wsize + MAX_CIFS_HDR_SIZE < srvTcp->maxBuf))
+ if((volume_info.wsize) && (volume_info.wsize <= CIFSMaxBufSize))
cifs_sb->wsize = volume_info.wsize;
else
- cifs_sb->wsize = srvTcp->maxBuf - MAX_CIFS_HDR_SIZE; /* default */
+ cifs_sb->wsize = CIFSMaxBufSize; /* default */
if(cifs_sb->rsize < PAGE_CACHE_SIZE) {
cifs_sb->rsize = PAGE_CACHE_SIZE;
cERROR(1,("Attempt to set readsize for mount to less than one page (4096)"));
@@ -1433,6 +1419,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
if(volume_info.server_ino)
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
+ if(volume_info.no_xattr)
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
if(volume_info.direct_io) {
cERROR(1,("mounting share using direct i/o"));
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
@@ -1504,7 +1492,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
/* If find_unc succeeded then rc == 0 so we can not end */
if (tcon) /* up accidently freeing someone elses tcon struct */
tconInfoFree(tcon);
- if (existingCifsSes == 0) {
+ if (existingCifsSes == NULL) {
if (pSesInfo) {
if ((pSesInfo->server) &&
(pSesInfo->status == CifsGood)) {
@@ -1575,7 +1563,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
user = ses->userName;
domain = ses->domainName;
smb_buffer = cifs_buf_get();
- if (smb_buffer == 0) {
+ if (smb_buffer == NULL) {
return -ENOMEM;
}
smb_buffer_response = smb_buffer;
@@ -1592,7 +1580,8 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
- capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS;
+ capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
+ CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;
if (ses->capabilities & CAP_UNICODE) {
smb_buffer->Flags2 |= SMBFLG2_UNICODE;
capabilities |= CAP_UNICODE;
@@ -1619,7 +1608,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
bcc_ptr += CIFS_SESSION_KEY_SIZE;
if (ses->capabilities & CAP_UNICODE) {
- if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */
+ if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */
*bcc_ptr = 0;
bcc_ptr++;
}
@@ -1629,7 +1618,8 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
bytes_returned =
cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100,
nls_codepage);
- bcc_ptr += 2 * bytes_returned; /* convert num 16 bit words to bytes */
+ /* convert number of 16 bit words to bytes */
+ bcc_ptr += 2 * bytes_returned;
bcc_ptr += 2; /* trailing null */
if (domain == NULL)
bytes_returned =
@@ -1646,8 +1636,8 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
32, nls_codepage);
bcc_ptr += 2 * bytes_returned;
bytes_returned =
- cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
- nls_codepage);
+ cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release,
+ 32, nls_codepage);
bcc_ptr += 2 * bytes_returned;
bcc_ptr += 2;
bytes_returned =
@@ -1733,6 +1723,11 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
bcc_ptr += 2 * (len + 1);
ses->serverNOS[2 * len] = 0;
ses->serverNOS[1 + (2 * len)] = 0;
+ if(strncmp(ses->serverNOS,
+ "NT LAN Manager 4",16) == 0) {
+ cFYI(1,("NT4 server"));
+ ses->flags |= CIFS_SES_NT4;
+ }
remaining_words -= len + 1;
if (remaining_words > 0) {
len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
@@ -1828,7 +1823,7 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
domain = ses->domainName;
smb_buffer = cifs_buf_get();
- if (smb_buffer == 0) {
+ if (smb_buffer == NULL) {
return -ENOMEM;
}
smb_buffer_response = smb_buffer;
@@ -2093,7 +2088,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
domain = ses->domainName;
*pNTLMv2_flag = FALSE;
smb_buffer = cifs_buf_get();
- if (smb_buffer == 0) {
+ if (smb_buffer == NULL) {
return -ENOMEM;
}
smb_buffer_response = smb_buffer;
@@ -2435,7 +2430,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
user = ses->userName;
domain = ses->domainName;
smb_buffer = cifs_buf_get();
- if (smb_buffer == 0) {
+ if (smb_buffer == NULL) {
return -ENOMEM;
}
smb_buffer_response = smb_buffer;
@@ -2809,7 +2804,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
return -EIO;
smb_buffer = cifs_buf_get();
- if (smb_buffer == 0) {
+ if (smb_buffer == NULL) {
return -ENOMEM;
}
smb_buffer_response = smb_buffer;
@@ -2937,7 +2932,8 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
return 0;
} else if (rc == -ESHUTDOWN) {
cFYI(1,("Waking up socket by sending it signal"));
- send_sig(SIGKILL,cifsd_task,1);
+ if(cifsd_task)
+ send_sig(SIGKILL,cifsd_task,1);
rc = 0;
} /* else - we have an smb session
left on this socket do not kill cifsd */
@@ -3011,16 +3007,21 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
if(ntlmv2_flag) {
char * v2_response;
cFYI(1,("Can use more secure NTLM version 2 password hash"));
- CalcNTLMv2_partial_mac_key(pSesInfo,
- nls_info);
- v2_response = kmalloc(16 + 64 /* blob */, GFP_KERNEL);
+ if(CalcNTLMv2_partial_mac_key(pSesInfo,
+ nls_info)) {
+ rc = -ENOMEM;
+ goto ss_err_exit;
+ } else
+ v2_response = kmalloc(16 + 64 /* blob */, GFP_KERNEL);
if(v2_response) {
CalcNTLMv2_response(pSesInfo,v2_response);
/* cifs_calculate_ntlmv2_mac_key(pSesInfo->mac_signing_key, response, ntlm_session_key, */
kfree(v2_response);
/* BB Put dummy sig in SessSetup PDU? */
- } else
+ } else {
rc = -ENOMEM;
+ goto ss_err_exit;
+ }
} else {
SMBNTencrypt(pSesInfo->password,
@@ -3057,6 +3058,7 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
pSesInfo->status = CifsGood;
}
}
+ss_err_exit:
return rc;
}
diff --git a/fs/cifs/fcntl.c b/fs/cifs/fcntl.c
index 9babaf869025a..9d24c40f1967a 100644
--- a/fs/cifs/fcntl.c
+++ b/fs/cifs/fcntl.c
@@ -27,8 +27,9 @@
#include "cifsproto.h"
#include "cifs_unicode.h"
#include "cifs_debug.h"
+#include "cifsfs.h"
-__u32 convert_to_cifs_notify_flags(unsigned long fcntl_notify_flags)
+static __u32 convert_to_cifs_notify_flags(unsigned long fcntl_notify_flags)
{
__u32 cifs_ntfy_flags = 0;
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 3d9b91d27d3ac..dcab7cf1b53bf 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -35,10 +35,117 @@
#include "cifs_debug.h"
#include "cifs_fs_sb.h"
-extern int cifs_readdir2(struct file *file, void *direntry, filldir_t filldir); /* BB removeme BB */
+static inline struct cifsFileInfo *cifs_init_private(
+ struct cifsFileInfo *private_data, struct inode *inode,
+ struct file *file, __u16 netfid)
+{
+ memset(private_data, 0, sizeof(struct cifsFileInfo));
+ private_data->netfid = netfid;
+ private_data->pid = current->tgid;
+ init_MUTEX(&private_data->fh_sem);
+ private_data->pfile = file; /* needed for writepage */
+ private_data->pInode = inode;
+ private_data->invalidHandle = FALSE;
+ private_data->closePend = FALSE;
+
+ return private_data;
+}
+
+static inline int cifs_convert_flags(unsigned int flags)
+{
+ if ((flags & O_ACCMODE) == O_RDONLY)
+ return GENERIC_READ;
+ else if ((flags & O_ACCMODE) == O_WRONLY)
+ return GENERIC_WRITE;
+ else if ((flags & O_ACCMODE) == O_RDWR) {
+ /* GENERIC_ALL is too much permission to request
+ can cause unnecessary access denied on create */
+ /* return GENERIC_ALL; */
+ return (GENERIC_READ | GENERIC_WRITE);
+ }
+
+ return 0x20197;
+}
+
+static inline int cifs_get_disposition(unsigned int flags)
+{
+ if ((flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
+ return FILE_CREATE;
+ else if ((flags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))
+ return FILE_OVERWRITE_IF;
+ else if ((flags & O_CREAT) == O_CREAT)
+ return FILE_OPEN_IF;
+ else
+ return FILE_OPEN;
+}
-int
-cifs_open(struct inode *inode, struct file *file)
+/* all arguments to this function must be checked for validity in caller */
+static inline int cifs_open_inode_helper(struct inode *inode, struct file *file,
+ struct cifsInodeInfo *pCifsInode, struct cifsFileInfo *pCifsFile,
+ struct cifsTconInfo *pTcon, int *oplock, FILE_ALL_INFO *buf,
+ char *full_path, int xid)
+{
+ struct timespec temp;
+ int rc;
+
+ /* want handles we can use to read with first
+ in the list so we do not have to walk the
+ list to search for one in prepare_write */
+ if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
+ list_add_tail(&pCifsFile->flist,
+ &pCifsInode->openFileList);
+ } else {
+ list_add(&pCifsFile->flist,
+ &pCifsInode->openFileList);
+ }
+ write_unlock(&GlobalSMBSeslock);
+ write_unlock(&file->f_owner.lock);
+ if (pCifsInode->clientCanCacheRead) {
+ /* we have the inode open somewhere else
+ no need to discard cache data */
+ goto client_can_cache;
+ }
+
+ /* BB need same check in cifs_create too? */
+ /* if not oplocked, invalidate inode pages if mtime or file
+ size changed */
+ temp = cifs_NTtimeToUnix(le64_to_cpu(buf->LastWriteTime));
+ if (timespec_equal(&file->f_dentry->d_inode->i_mtime, &temp) &&
+ (file->f_dentry->d_inode->i_size ==
+ (loff_t)le64_to_cpu(buf->EndOfFile))) {
+ cFYI(1, ("inode unchanged on server"));
+ } else {
+ 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);
+ }
+ cFYI(1, ("invalidating remote inode since open detected it "
+ "changed"));
+ invalidate_remote_inode(file->f_dentry->d_inode);
+ }
+
+client_can_cache:
+ if (pTcon->ses->capabilities & CAP_UNIX)
+ rc = cifs_get_inode_info_unix(&file->f_dentry->d_inode,
+ full_path, inode->i_sb, xid);
+ else
+ rc = cifs_get_inode_info(&file->f_dentry->d_inode,
+ full_path, buf, inode->i_sb, xid);
+
+ if ((*oplock & 0xF) == OPLOCK_EXCLUSIVE) {
+ pCifsInode->clientCanCacheAll = TRUE;
+ pCifsInode->clientCanCacheRead = TRUE;
+ cFYI(1, ("Exclusive Oplock granted on inode %p",
+ file->f_dentry->d_inode));
+ } else if ((*oplock & 0xF) == OPLOCK_READ)
+ pCifsInode->clientCanCacheRead = TRUE;
+
+ return rc;
+}
+
+int cifs_open(struct inode *inode, struct file *file)
{
int rc = -EACCES;
int xid, oplock;
@@ -46,12 +153,12 @@ cifs_open(struct inode *inode, struct file *file)
struct cifsTconInfo *pTcon;
struct cifsFileInfo *pCifsFile;
struct cifsInodeInfo *pCifsInode;
- struct list_head * tmp;
+ struct list_head *tmp;
char *full_path = NULL;
- int desiredAccess = 0x20197;
+ int desiredAccess;
int disposition;
__u16 netfid;
- FILE_ALL_INFO * buf = NULL;
+ FILE_ALL_INFO *buf = NULL;
xid = GetXid();
@@ -59,48 +166,46 @@ cifs_open(struct inode *inode, struct file *file)
pTcon = cifs_sb->tcon;
if (file->f_flags & O_CREAT) {
- /* search inode for this file and fill in file->private_data = */
+ /* search inode for this file and fill in file->private_data */
pCifsInode = CIFS_I(file->f_dentry->d_inode);
read_lock(&GlobalSMBSeslock);
- list_for_each(tmp, &pCifsInode->openFileList) {
- pCifsFile = list_entry(tmp,struct cifsFileInfo, flist);
- if((pCifsFile->pfile == NULL)&& (pCifsFile->pid == current->tgid)){
- /* mode set in cifs_create */
- pCifsFile->pfile = file; /* needed for writepage */
+ list_for_each(tmp, &pCifsInode->openFileList) {
+ pCifsFile = list_entry(tmp, struct cifsFileInfo,
+ flist);
+ if ((pCifsFile->pfile == NULL) &&
+ (pCifsFile->pid == current->tgid)) {
+ /* mode set in cifs_create */
+
+ /* needed for writepage */
+ pCifsFile->pfile = file;
+
file->private_data = pCifsFile;
break;
}
}
read_unlock(&GlobalSMBSeslock);
- if(file->private_data != NULL) {
+ if (file->private_data != NULL) {
rc = 0;
FreeXid(xid);
return rc;
} else {
- if(file->f_flags & O_EXCL)
- cERROR(1,("could not find file instance for new file %p ",file));
+ if (file->f_flags & O_EXCL)
+ cERROR(1, ("could not find file instance for "
+ "new file %p ", file));
}
}
down(&inode->i_sb->s_vfs_rename_sem);
full_path = build_path_from_dentry(file->f_dentry);
up(&inode->i_sb->s_vfs_rename_sem);
- if(full_path == NULL) {
+ if (full_path == NULL) {
FreeXid(xid);
return -ENOMEM;
}
- cFYI(1, (" inode = 0x%p file flags are 0x%x for %s", inode, file->f_flags,full_path));
- if ((file->f_flags & O_ACCMODE) == O_RDONLY)
- desiredAccess = GENERIC_READ;
- else if ((file->f_flags & O_ACCMODE) == O_WRONLY)
- desiredAccess = GENERIC_WRITE;
- else if ((file->f_flags & O_ACCMODE) == O_RDWR) {
- /* GENERIC_ALL is too much permission to request */
- /* can cause unnecessary access denied on create */
- /* desiredAccess = GENERIC_ALL; */
- desiredAccess = GENERIC_READ | GENERIC_WRITE;
- }
+ cFYI(1, (" inode = 0x%p file flags are 0x%x for %s",
+ inode, file->f_flags, full_path));
+ desiredAccess = cifs_convert_flags(file->f_flags);
/*********************************************************************
* open flag mapping table:
@@ -126,14 +231,7 @@ cifs_open(struct inode *inode, struct file *file)
* O_FASYNC, O_NOFOLLOW, O_NONBLOCK need further investigation
*********************************************************************/
- if((file->f_flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
- disposition = FILE_CREATE;
- else if((file->f_flags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))
- disposition = FILE_OVERWRITE_IF;
- else if((file->f_flags & O_CREAT) == O_CREAT)
- disposition = FILE_OPEN_IF;
- else
- disposition = FILE_OPEN;
+ disposition = cifs_get_disposition(file->f_flags);
if (oplockEnabled)
oplock = REQ_OPLOCK;
@@ -142,125 +240,73 @@ cifs_open(struct inode *inode, struct file *file)
/* BB pass O_SYNC flag through on file attributes .. BB */
- /* Also refresh inode by passing in file_info buf returned by SMBOpen
- and calling get_inode_info with returned buf (at least
- helps non-Unix server case */
+ /* Also refresh inode by passing in file_info buf returned by SMBOpen
+ and calling get_inode_info with returned buf (at least helps
+ non-Unix server case) */
/* BB we can not do this if this is the second open of a file
- and the first handle has writebehind data, we might be
- able to simply do a filemap_fdatawrite/filemap_fdatawait first */
- buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
- if(buf== NULL) {
- if (full_path)
- kfree(full_path);
- FreeXid(xid);
- return -ENOMEM;
+ and the first handle has writebehind data, we might be
+ able to simply do a filemap_fdatawrite/filemap_fdatawait first */
+ buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
+ if (!buf) {
+ rc = -ENOMEM;
+ goto out;
}
rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess,
- CREATE_NOT_DIR, &netfid, &oplock, buf, cifs_sb->local_nls);
+ CREATE_NOT_DIR, &netfid, &oplock, buf,
+ cifs_sb->local_nls);
if (rc) {
cFYI(1, ("cifs_open returned 0x%x ", rc));
- cFYI(1, ("oplock: %d ", oplock));
+ goto out;
+ }
+ file->private_data =
+ kmalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
+ if (file->private_data == NULL) {
+ rc = -ENOMEM;
+ goto out;
+ }
+ pCifsFile = cifs_init_private(file->private_data, inode, file, netfid);
+ write_lock(&file->f_owner.lock);
+ write_lock(&GlobalSMBSeslock);
+ list_add(&pCifsFile->tlist, &pTcon->openFileList);
+
+ pCifsInode = CIFS_I(file->f_dentry->d_inode);
+ if (pCifsInode) {
+ rc = cifs_open_inode_helper(inode, file, pCifsInode,
+ pCifsFile, pTcon,
+ &oplock, buf, full_path, xid);
} else {
- file->private_data =
- kmalloc(sizeof (struct cifsFileInfo), GFP_KERNEL);
- if (file->private_data) {
- memset(file->private_data, 0, sizeof(struct cifsFileInfo));
- pCifsFile = (struct cifsFileInfo *) file->private_data;
- pCifsFile->netfid = netfid;
- pCifsFile->pid = current->tgid;
- init_MUTEX(&pCifsFile->fh_sem);
- pCifsFile->pfile = file; /* needed for writepage */
- pCifsFile->pInode = inode;
- pCifsFile->invalidHandle = FALSE;
- pCifsFile->closePend = FALSE;
- write_lock(&file->f_owner.lock);
- write_lock(&GlobalSMBSeslock);
- list_add(&pCifsFile->tlist,&pTcon->openFileList);
- pCifsInode = CIFS_I(file->f_dentry->d_inode);
- if(pCifsInode) {
- /* want handles we can use to read with first */
- /* in the list so we do not have to walk the */
- /* list to search for one in prepare_write */
- if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
- list_add_tail(&pCifsFile->flist,&pCifsInode->openFileList);
- } else {
- list_add(&pCifsFile->flist,&pCifsInode->openFileList);
- }
- write_unlock(&GlobalSMBSeslock);
- write_unlock(&file->f_owner.lock);
- if(pCifsInode->clientCanCacheRead) {
- /* we have the inode open somewhere else
- no need to discard cache data */
- } else {
- if(buf) {
- /* BB need same check in cifs_create too? */
-
- /* if not oplocked, invalidate inode pages if mtime
- or file size changed */
- struct timespec temp;
- temp = cifs_NTtimeToUnix(le64_to_cpu(buf->LastWriteTime));
- if(timespec_equal(&file->f_dentry->d_inode->i_mtime,&temp) &&
- (file->f_dentry->d_inode->i_size == (loff_t)le64_to_cpu(buf->EndOfFile))) {
- cFYI(1,("inode unchanged on server"));
- } else {
- 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);
- }
- cFYI(1,("invalidating remote inode since open detected it changed"));
- invalidate_remote_inode(file->f_dentry->d_inode);
- }
- }
- }
- if (pTcon->ses->capabilities & CAP_UNIX)
- rc = cifs_get_inode_info_unix(&file->f_dentry->d_inode,
- full_path, inode->i_sb,xid);
- else
- rc = cifs_get_inode_info(&file->f_dentry->d_inode,
- full_path, buf, inode->i_sb,xid);
-
- if((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
- pCifsInode->clientCanCacheAll = TRUE;
- pCifsInode->clientCanCacheRead = TRUE;
- cFYI(1,("Exclusive Oplock granted on inode %p",file->f_dentry->d_inode));
- } else if((oplock & 0xF) == OPLOCK_READ)
- pCifsInode->clientCanCacheRead = TRUE;
- } else {
- write_unlock(&GlobalSMBSeslock);
- write_unlock(&file->f_owner.lock);
- }
- if(oplock & CIFS_CREATE_ACTION) {
- /* time to set mode which we can not set earlier due
- to problems creating new read-only files */
- if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
- CIFSSMBUnixSetPerms(xid, pTcon, full_path, inode->i_mode,
- (__u64)-1,
- (__u64)-1,
- 0 /* dev */,
- cifs_sb->local_nls);
- else {/* BB implement via Windows security descriptors */
- /* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/
- /* in the meantime could set r/o dos attribute when perms are eg:
- mode & 0222 == 0 */
- }
- }
+ write_unlock(&GlobalSMBSeslock);
+ write_unlock(&file->f_owner.lock);
+ }
+
+ if (oplock & CIFS_CREATE_ACTION) {
+ /* time to set mode which we can not set earlier due to
+ problems creating new read-only files */
+ if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) {
+ CIFSSMBUnixSetPerms(xid, pTcon, full_path,
+ inode->i_mode,
+ (__u64)-1, (__u64)-1, 0 /* dev */,
+ cifs_sb->local_nls);
+ } else {
+ /* BB implement via Windows security descriptors eg
+ CIFSSMBWinSetPerms(xid, pTcon, full_path, mode,
+ -1, -1, local_nls);
+ in the meantime could set r/o dos attribute when
+ perms are eg: mode & 0222 == 0 */
}
}
- if (buf)
- kfree(buf);
- if (full_path)
- kfree(full_path);
+out:
+ kfree(buf);
+ kfree(full_path);
FreeXid(xid);
return rc;
}
/* Try to reaquire byte range locks that were released when session */
/* to server was lost */
-static int cifs_relock_file(struct cifsFileInfo * cifsFile)
+static int cifs_relock_file(struct cifsFileInfo *cifsFile)
{
int rc = 0;
@@ -269,7 +315,8 @@ static int cifs_relock_file(struct cifsFileInfo * cifsFile)
return rc;
}
-static int cifs_reopen_file(struct inode *inode, struct file *file, int can_flush)
+static int cifs_reopen_file(struct inode *inode, struct file *file,
+ int can_flush)
{
int rc = -EACCES;
int xid, oplock;
@@ -278,78 +325,69 @@ static int cifs_reopen_file(struct inode *inode, struct file *file, int can_flus
struct cifsFileInfo *pCifsFile;
struct cifsInodeInfo *pCifsInode;
char *full_path = NULL;
- int desiredAccess = 0x20197;
+ int desiredAccess;
int disposition = FILE_OPEN;
__u16 netfid;
- if(inode == NULL)
+ if (inode == NULL)
return -EBADF;
if (file->private_data) {
- pCifsFile = (struct cifsFileInfo *) file->private_data;
+ pCifsFile = (struct cifsFileInfo *)file->private_data;
} else
return -EBADF;
xid = GetXid();
down(&pCifsFile->fh_sem);
- if(pCifsFile->invalidHandle == FALSE) {
+ if (pCifsFile->invalidHandle == FALSE) {
up(&pCifsFile->fh_sem);
FreeXid(xid);
return 0;
}
- if(file->f_dentry == NULL) {
+ if (file->f_dentry == NULL) {
up(&pCifsFile->fh_sem);
- cFYI(1,("failed file reopen, no valid name if dentry freed"));
+ cFYI(1, ("failed file reopen, no valid name if dentry freed"));
FreeXid(xid);
return -EBADF;
}
cifs_sb = CIFS_SB(inode->i_sb);
pTcon = cifs_sb->tcon;
/* can not grab rename sem here because various ops, including
-those that already have the rename sem can end up causing writepage
-to get called and if the server was down that means we end up here,
-and we can never tell if the caller already has the rename_sem */
+ those that already have the rename sem can end up causing writepage
+ to get called and if the server was down that means we end up here,
+ and we can never tell if the caller already has the rename_sem */
full_path = build_path_from_dentry(file->f_dentry);
- if(full_path == NULL) {
+ if (full_path == NULL) {
up(&pCifsFile->fh_sem);
FreeXid(xid);
return -ENOMEM;
}
- cFYI(1, (" inode = 0x%p file flags are 0x%x for %s", inode, file->f_flags,full_path));
- if ((file->f_flags & O_ACCMODE) == O_RDONLY)
- desiredAccess = GENERIC_READ;
- else if ((file->f_flags & O_ACCMODE) == O_WRONLY)
- desiredAccess = GENERIC_WRITE;
- else if ((file->f_flags & O_ACCMODE) == O_RDWR) {
- /* GENERIC_ALL is too much permission to request */
- /* can cause unnecessary access denied on create */
- /* desiredAccess = GENERIC_ALL; */
- desiredAccess = GENERIC_READ | GENERIC_WRITE;
- }
+ cFYI(1, (" inode = 0x%p file flags are 0x%x for %s",
+ inode, file->f_flags,full_path));
+ desiredAccess = cifs_convert_flags(file->f_flags);
if (oplockEnabled)
oplock = REQ_OPLOCK;
else
oplock = FALSE;
-
/* Can not refresh inode by passing in file_info buf to be returned
- by SMBOpen and then calling get_inode_info with returned buf
- since file might have write behind data that needs to be flushed
- and server version of file size can be stale. If we
- knew for sure that inode was not dirty locally we could do this */
+ by SMBOpen and then calling get_inode_info with returned buf
+ since file might have write behind data that needs to be flushed
+ and server version of file size can be stale. If we knew for sure
+ that inode was not dirty locally we could do this */
-/* buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
- if(buf==0) {
+/* buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
+ if (buf == 0) {
up(&pCifsFile->fh_sem);
- if (full_path)
- kfree(full_path);
+ kfree(full_path);
FreeXid(xid);
return -ENOMEM;
- }*/
+ } */
rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess,
- CREATE_NOT_DIR, &netfid, &oplock, NULL, cifs_sb->local_nls);
+ CREATE_NOT_DIR, &netfid, &oplock, NULL,
+ cifs_sb->local_nls);
if (rc) {
up(&pCifsFile->fh_sem);
cFYI(1, ("cifs_open returned 0x%x ", rc));
@@ -359,104 +397,103 @@ and we can never tell if the caller already has the rename_sem */
pCifsFile->invalidHandle = FALSE;
up(&pCifsFile->fh_sem);
pCifsInode = CIFS_I(inode);
- if(pCifsInode) {
- if(can_flush) {
+ if (pCifsInode) {
+ if (can_flush) {
filemap_fdatawrite(inode->i_mapping);
filemap_fdatawait(inode->i_mapping);
/* temporarily disable caching while we
- go to server to get inode info */
+ go to server to get inode info */
pCifsInode->clientCanCacheAll = FALSE;
pCifsInode->clientCanCacheRead = FALSE;
if (pTcon->ses->capabilities & CAP_UNIX)
rc = cifs_get_inode_info_unix(&inode,
- full_path, inode->i_sb,xid);
+ full_path, inode->i_sb, xid);
else
rc = cifs_get_inode_info(&inode,
- full_path, NULL, inode->i_sb,xid);
+ full_path, NULL, inode->i_sb,
+ xid);
} /* else we are writing out data to server already
- and could deadlock if we tried to flush data, and
- since we do not know if we have data that would
- invalidate the current end of file on the server
- we can not go to the server to get the new
- inod info */
- if((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
- pCifsInode->clientCanCacheAll = TRUE;
+ and could deadlock if we tried to flush data, and
+ since we do not know if we have data that would
+ invalidate the current end of file on the server
+ we can not go to the server to get the new inod
+ info */
+ if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
+ pCifsInode->clientCanCacheAll = TRUE;
pCifsInode->clientCanCacheRead = TRUE;
- cFYI(1,("Exclusive Oplock granted on inode %p",file->f_dentry->d_inode));
- } else if((oplock & 0xF) == OPLOCK_READ) {
+ cFYI(1, ("Exclusive Oplock granted on inode %p",
+ file->f_dentry->d_inode));
+ } else if ((oplock & 0xF) == OPLOCK_READ) {
pCifsInode->clientCanCacheRead = TRUE;
- pCifsInode->clientCanCacheAll = FALSE;
+ pCifsInode->clientCanCacheAll = FALSE;
} else {
pCifsInode->clientCanCacheRead = FALSE;
- pCifsInode->clientCanCacheAll = FALSE;
+ pCifsInode->clientCanCacheAll = FALSE;
}
cifs_relock_file(pCifsFile);
}
}
- if (full_path)
- kfree(full_path);
+ kfree(full_path);
FreeXid(xid);
return rc;
}
-int
-cifs_close(struct inode *inode, struct file *file)
+int cifs_close(struct inode *inode, struct file *file)
{
int rc = 0;
int xid;
struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon;
struct cifsFileInfo *pSMBFile =
- (struct cifsFileInfo *) file->private_data;
+ (struct cifsFileInfo *)file->private_data;
xid = GetXid();
cifs_sb = CIFS_SB(inode->i_sb);
pTcon = cifs_sb->tcon;
if (pSMBFile) {
- pSMBFile->closePend = TRUE;
+ pSMBFile->closePend = TRUE;
write_lock(&file->f_owner.lock);
- if(pTcon) {
+ if (pTcon) {
/* no sense reconnecting to close a file that is
- already closed */
+ already closed */
if (pTcon->tidStatus != CifsNeedReconnect) {
write_unlock(&file->f_owner.lock);
- rc = CIFSSMBClose(xid,pTcon,pSMBFile->netfid);
+ rc = CIFSSMBClose(xid, pTcon,
+ pSMBFile->netfid);
write_lock(&file->f_owner.lock);
}
}
list_del(&pSMBFile->flist);
list_del(&pSMBFile->tlist);
write_unlock(&file->f_owner.lock);
- if(pSMBFile->search_resume_name)
- kfree(pSMBFile->search_resume_name);
+ kfree(pSMBFile->search_resume_name);
kfree(file->private_data);
file->private_data = NULL;
} else
rc = -EBADF;
- if(list_empty(&(CIFS_I(inode)->openFileList))) {
- cFYI(1,("closing last open instance for inode %p",inode));
- /* if the file is not open we do not know if we can cache
- info on this inode, much less write behind and read ahead */
+ if (list_empty(&(CIFS_I(inode)->openFileList))) {
+ cFYI(1, ("closing last open instance for inode %p", inode));
+ /* if the file is not open we do not know if we can cache info
+ on this inode, much less write behind and read ahead */
CIFS_I(inode)->clientCanCacheRead = FALSE;
CIFS_I(inode)->clientCanCacheAll = FALSE;
}
- if((rc ==0) && CIFS_I(inode)->write_behind_rc)
+ if ((rc ==0) && CIFS_I(inode)->write_behind_rc)
rc = CIFS_I(inode)->write_behind_rc;
FreeXid(xid);
return rc;
}
-int
-cifs_closedir(struct inode *inode, struct file *file)
+int cifs_closedir(struct inode *inode, struct file *file)
{
int rc = 0;
int xid;
struct cifsFileInfo *pCFileStruct =
- (struct cifsFileInfo *) file->private_data;
- char * ptmp;
+ (struct cifsFileInfo *)file->private_data;
+ char *ptmp;
cFYI(1, ("Closedir inode = 0x%p with ", inode));
@@ -464,27 +501,28 @@ cifs_closedir(struct inode *inode, struct file *file)
if (pCFileStruct) {
struct cifsTconInfo *pTcon;
- struct cifs_sb_info * cifs_sb = CIFS_SB(file->f_dentry->d_sb);
+ struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_dentry->d_sb);
pTcon = cifs_sb->tcon;
cFYI(1, ("Freeing private data in close dir"));
- if(pCFileStruct->srch_inf.endOfSearch == FALSE) {
+ if (pCFileStruct->srch_inf.endOfSearch == FALSE) {
pCFileStruct->invalidHandle = TRUE;
rc = CIFSFindClose(xid, pTcon, pCFileStruct->netfid);
- cFYI(1,("Closing uncompleted readdir with rc %d",rc));
- /* not much we can do if it fails anywway, ignore rc */
+ cFYI(1, ("Closing uncompleted readdir with rc %d",
+ rc));
+ /* not much we can do if it fails anyway, ignore rc */
rc = 0;
}
ptmp = pCFileStruct->srch_inf.ntwrk_buf_start;
- if(ptmp) {
- cFYI(1,("freeing smb buf in srch struct in closedir")); /* BB removeme BB */
+ if (ptmp) {
+ /* BB removeme BB */ cFYI(1, ("freeing smb buf in srch struct in closedir"));
pCFileStruct->srch_inf.ntwrk_buf_start = NULL;
cifs_buf_release(ptmp);
}
ptmp = pCFileStruct->search_resume_name;
- if(ptmp) {
- cFYI(1,("freeing resume name in closedir")); /* BB removeme BB */
+ if (ptmp) {
+ /* BB removeme BB */ cFYI(1, ("freeing resume name in closedir"));
pCFileStruct->search_resume_name = NULL;
kfree(ptmp);
}
@@ -496,8 +534,7 @@ cifs_closedir(struct inode *inode, struct file *file)
return rc;
}
-int
-cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
+int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
{
int rc, xid;
__u32 lockType = LOCKING_ANDX_LARGE_FILES;
@@ -507,16 +544,15 @@ cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
int wait_flag = FALSE;
struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon;
- length = 1 + pfLock->fl_end - pfLock->fl_start;
+ length = 1 + pfLock->fl_end - pfLock->fl_start;
rc = -EACCES;
-
xid = GetXid();
- cFYI(1,
- ("Lock parm: 0x%x flockflags: 0x%x flocktype: 0x%x start: %lld end: %lld",
- cmd, pfLock->fl_flags, pfLock->fl_type, pfLock->fl_start,
- pfLock->fl_end));
+ cFYI(1, ("Lock parm: 0x%x flockflags: "
+ "0x%x flocktype: 0x%x start: %lld end: %lld",
+ cmd, pfLock->fl_flags, pfLock->fl_type, pfLock->fl_start,
+ pfLock->fl_end));
if (pfLock->fl_flags & FL_POSIX)
cFYI(1, ("Posix "));
@@ -527,11 +563,13 @@ cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
wait_flag = TRUE;
}
if (pfLock->fl_flags & FL_ACCESS)
- cFYI(1, ("Process suspended by mandatory locking - not implemented yet "));
+ cFYI(1, ("Process suspended by mandatory locking - "
+ "not implemented yet "));
if (pfLock->fl_flags & FL_LEASE)
cFYI(1, ("Lease on file - not implemented yet"));
- if (pfLock->fl_flags & (~(FL_POSIX | FL_FLOCK | FL_SLEEP | FL_ACCESS | FL_LEASE)))
- cFYI(1, ("Unknown lock flags 0x%x",pfLock->fl_flags));
+ if (pfLock->fl_flags &
+ (~(FL_POSIX | FL_FLOCK | FL_SLEEP | FL_ACCESS | FL_LEASE)))
+ cFYI(1, ("Unknown lock flags 0x%x", pfLock->fl_flags));
if (pfLock->fl_type == F_WRLCK) {
cFYI(1, ("F_WRLCK "));
@@ -563,7 +601,7 @@ cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
if (IS_GETLK(cmd)) {
rc = CIFSSMBLock(xid, pTcon,
- ((struct cifsFileInfo *) file->
+ ((struct cifsFileInfo *)file->
private_data)->netfid,
length,
pfLock->fl_start, 0, 1, lockType,
@@ -578,14 +616,15 @@ cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
0 /* wait flag */ );
pfLock->fl_type = F_UNLCK;
if (rc != 0)
- cERROR(1,
- ("Error unlocking previously locked range %d during test of lock ",
- rc));
+ cERROR(1, ("Error unlocking previously locked "
+ "range %d during test of lock ",
+ rc));
rc = 0;
} else {
/* if rc == ERR_SHARING_VIOLATION ? */
- rc = 0; /* do not change lock type to unlock since range in use */
+ rc = 0; /* do not change lock type to unlock
+ since range in use */
}
FreeXid(xid);
@@ -603,9 +642,8 @@ cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
return rc;
}
-ssize_t
-cifs_user_write(struct file * file, const char __user * write_data,
- size_t write_size, loff_t * poffset)
+ssize_t cifs_user_write(struct file *file, const char __user *write_data,
+ size_t write_size, loff_t *poffset)
{
int rc = 0;
unsigned int bytes_written = 0;
@@ -613,77 +651,78 @@ cifs_user_write(struct file * file, const char __user * write_data,
struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon;
int xid, long_op;
- struct cifsFileInfo * open_file;
+ struct cifsFileInfo *open_file;
- if(file->f_dentry == NULL)
+ if (file->f_dentry == NULL)
return -EBADF;
cifs_sb = CIFS_SB(file->f_dentry->d_sb);
- if(cifs_sb == NULL) {
+ if (cifs_sb == NULL)
return -EBADF;
- }
+
pTcon = cifs_sb->tcon;
- /*cFYI(1,
+ /* cFYI(1,
(" write %d bytes to offset %lld of %s", write_size,
*poffset, file->f_dentry->d_name.name)); */
- if (file->private_data == NULL) {
+ if (file->private_data == NULL)
return -EBADF;
- } else {
+ else
open_file = (struct cifsFileInfo *) file->private_data;
- }
xid = GetXid();
- if(file->f_dentry->d_inode == NULL) {
+ if (file->f_dentry->d_inode == NULL) {
FreeXid(xid);
return -EBADF;
}
if (*poffset > file->f_dentry->d_inode->i_size)
- long_op = 2; /* writes past end of file can take a long time */
+ long_op = 2; /* writes past end of file can take a long time */
else
long_op = 1;
for (total_written = 0; write_size > total_written;
total_written += bytes_written) {
rc = -EAGAIN;
- while(rc == -EAGAIN) {
- if(file->private_data == NULL) {
+ while (rc == -EAGAIN) {
+ if (file->private_data == NULL) {
/* file has been closed on us */
FreeXid(xid);
/* if we have gotten here we have written some data
- and blocked, and the file has been freed on us
- while we blocked so return what we managed to write */
+ and blocked, and the file has been freed on us while
+ we blocked so return what we managed to write */
return total_written;
}
- if(open_file->closePend) {
+ if (open_file->closePend) {
FreeXid(xid);
- if(total_written)
+ if (total_written)
return total_written;
else
return -EBADF;
}
if (open_file->invalidHandle) {
- if((file->f_dentry == NULL) ||
- (file->f_dentry->d_inode == NULL)) {
+ if ((file->f_dentry == NULL) ||
+ (file->f_dentry->d_inode == NULL)) {
FreeXid(xid);
return total_written;
}
/* we could deadlock if we called
- filemap_fdatawait from here so tell
- reopen_file not to flush data to server now */
+ filemap_fdatawait from here so tell
+ reopen_file not to flush data to server
+ now */
rc = cifs_reopen_file(file->f_dentry->d_inode,
- file,FALSE);
- if(rc != 0)
+ file, FALSE);
+ if (rc != 0)
break;
}
rc = CIFSSMBWrite(xid, pTcon,
- open_file->netfid,
- write_size - total_written, *poffset,
- &bytes_written,
- NULL, write_data + total_written, long_op);
+ open_file->netfid,
+ min_t(const int, cifs_sb->wsize,
+ write_size - total_written),
+ *poffset, &bytes_written,
+ NULL, write_data + total_written, long_op);
}
if (rc || (bytes_written == 0)) {
if (total_written)
@@ -694,11 +733,12 @@ cifs_user_write(struct file * file, const char __user * write_data,
}
} else
*poffset += bytes_written;
- long_op = FALSE; /* subsequent writes fast - 15 seconds is plenty */
+ long_op = FALSE; /* subsequent writes fast -
+ 15 seconds is plenty */
}
#ifdef CONFIG_CIFS_STATS
- if(total_written > 0) {
+ if (total_written > 0) {
atomic_inc(&pTcon->num_writes);
spin_lock(&pTcon->stat_lock);
pTcon->bytes_written += total_written;
@@ -707,14 +747,15 @@ cifs_user_write(struct file * file, const char __user * write_data,
#endif
/* since the write may have blocked check these pointers again */
- if(file->f_dentry) {
- if(file->f_dentry->d_inode) {
+ if (file->f_dentry) {
+ if (file->f_dentry->d_inode) {
struct inode *inode = file->f_dentry->d_inode;
inode->i_ctime = inode->i_mtime =
current_fs_time(inode->i_sb);
if (total_written > 0) {
if (*poffset > file->f_dentry->d_inode->i_size)
- i_size_write(file->f_dentry->d_inode, *poffset);
+ i_size_write(file->f_dentry->d_inode,
+ *poffset);
}
mark_inode_dirty_sync(file->f_dentry->d_inode);
}
@@ -723,9 +764,8 @@ cifs_user_write(struct file * file, const char __user * write_data,
return total_written;
}
-static ssize_t
-cifs_write(struct file * file, const char *write_data,
- size_t write_size, loff_t * poffset)
+static ssize_t cifs_write(struct file *file, const char *write_data,
+ size_t write_size, loff_t *poffset)
{
int rc = 0;
unsigned int bytes_written = 0;
@@ -733,77 +773,79 @@ cifs_write(struct file * file, const char *write_data,
struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon;
int xid, long_op;
- struct cifsFileInfo * open_file;
+ struct cifsFileInfo *open_file;
- if(file->f_dentry == NULL)
+ if (file->f_dentry == NULL)
return -EBADF;
cifs_sb = CIFS_SB(file->f_dentry->d_sb);
- if(cifs_sb == NULL) {
+ if (cifs_sb == NULL)
return -EBADF;
- }
+
pTcon = cifs_sb->tcon;
- /*cFYI(1,
+ /* cFYI(1,
(" write %d bytes to offset %lld of %s", write_size,
*poffset, file->f_dentry->d_name.name)); */
- if (file->private_data == NULL) {
+ if (file->private_data == NULL)
return -EBADF;
- } else {
- open_file = (struct cifsFileInfo *) file->private_data;
- }
+ else
+ open_file = (struct cifsFileInfo *)file->private_data;
xid = GetXid();
- if(file->f_dentry->d_inode == NULL) {
+ if (file->f_dentry->d_inode == NULL) {
FreeXid(xid);
return -EBADF;
}
if (*poffset > file->f_dentry->d_inode->i_size)
- long_op = 2; /* writes past end of file can take a long time */
+ long_op = 2; /* writes past end of file can take a long time */
else
long_op = 1;
for (total_written = 0; write_size > total_written;
total_written += bytes_written) {
rc = -EAGAIN;
- while(rc == -EAGAIN) {
- if(file->private_data == NULL) {
+ while (rc == -EAGAIN) {
+ if (file->private_data == NULL) {
/* file has been closed on us */
FreeXid(xid);
/* if we have gotten here we have written some data
- and blocked, and the file has been freed on us
- while we blocked so return what we managed to write */
+ and blocked, and the file has been freed on us
+ while we blocked so return what we managed to
+ write */
return total_written;
}
- if(open_file->closePend) {
+ if (open_file->closePend) {
FreeXid(xid);
- if(total_written)
+ if (total_written)
return total_written;
else
return -EBADF;
}
if (open_file->invalidHandle) {
- if((file->f_dentry == NULL) ||
+ if ((file->f_dentry == NULL) ||
(file->f_dentry->d_inode == NULL)) {
FreeXid(xid);
return total_written;
}
/* we could deadlock if we called
- filemap_fdatawait from here so tell
- reopen_file not to flush data to server now */
+ filemap_fdatawait from here so tell
+ reopen_file not to flush data to
+ server now */
rc = cifs_reopen_file(file->f_dentry->d_inode,
- file,FALSE);
- if(rc != 0)
+ file, FALSE);
+ if (rc != 0)
break;
}
rc = CIFSSMBWrite(xid, pTcon,
- open_file->netfid,
- write_size - total_written, *poffset,
- &bytes_written,
- write_data + total_written, NULL, long_op);
+ open_file->netfid,
+ min_t(const int, cifs_sb->wsize,
+ write_size - total_written),
+ *poffset, &bytes_written,
+ write_data + total_written, NULL, long_op);
}
if (rc || (bytes_written == 0)) {
if (total_written)
@@ -814,11 +856,12 @@ cifs_write(struct file * file, const char *write_data,
}
} else
*poffset += bytes_written;
- long_op = FALSE; /* subsequent writes fast - 15 seconds is plenty */
+ long_op = FALSE; /* subsequent writes fast -
+ 15 seconds is plenty */
}
#ifdef CONFIG_CIFS_STATS
- if(total_written > 0) {
+ if (total_written > 0) {
atomic_inc(&pTcon->num_writes);
spin_lock(&pTcon->stat_lock);
pTcon->bytes_written += total_written;
@@ -827,13 +870,14 @@ cifs_write(struct file * file, const char *write_data,
#endif
/* since the write may have blocked check these pointers again */
- if(file->f_dentry) {
- if(file->f_dentry->d_inode) {
- file->f_dentry->d_inode->i_ctime = file->f_dentry->d_inode->i_mtime =
- CURRENT_TIME;
+ if (file->f_dentry) {
+ if (file->f_dentry->d_inode) {
+ file->f_dentry->d_inode->i_ctime =
+ file->f_dentry->d_inode->i_mtime = CURRENT_TIME;
if (total_written > 0) {
if (*poffset > file->f_dentry->d_inode->i_size)
- i_size_write(file->f_dentry->d_inode, *poffset);
+ i_size_write(file->f_dentry->d_inode,
+ *poffset);
}
mark_inode_dirty_sync(file->f_dentry->d_inode);
}
@@ -842,12 +886,11 @@ cifs_write(struct file * file, const char *write_data,
return total_written;
}
-static int
-cifs_partialpagewrite(struct page *page,unsigned from, unsigned to)
+static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
{
struct address_space *mapping = page->mapping;
loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
- char * write_data;
+ char *write_data;
int rc = -EFAULT;
int bytes_written = 0;
struct cifs_sb_info *cifs_sb;
@@ -858,11 +901,8 @@ cifs_partialpagewrite(struct page *page,unsigned from, unsigned to)
struct list_head *tmp;
struct list_head *tmp1;
- if (!mapping) {
- return -EFAULT;
- } else if(!mapping->host) {
+ if (!mapping || !mapping->host)
return -EFAULT;
- }
inode = page->mapping->host;
cifs_sb = CIFS_SB(inode->i_sb);
@@ -872,64 +912,65 @@ cifs_partialpagewrite(struct page *page,unsigned from, unsigned to)
write_data = kmap(page);
write_data += from;
- if((to > PAGE_CACHE_SIZE) || (from > to)) {
+ if ((to > PAGE_CACHE_SIZE) || (from > to)) {
kunmap(page);
return -EIO;
}
/* racing with truncate? */
- if(offset > mapping->host->i_size) {
+ if (offset > mapping->host->i_size) {
kunmap(page);
return 0; /* don't care */
}
/* check to make sure that we are not extending the file */
- if(mapping->host->i_size - offset < (loff_t)to)
+ if (mapping->host->i_size - offset < (loff_t)to)
to = (unsigned)(mapping->host->i_size - offset);
-
cifsInode = CIFS_I(mapping->host);
read_lock(&GlobalSMBSeslock);
/* BB we should start at the end */
list_for_each_safe(tmp, tmp1, &cifsInode->openFileList) {
- open_file = list_entry(tmp,struct cifsFileInfo, flist);
- if(open_file->closePend)
+ open_file = list_entry(tmp, struct cifsFileInfo, flist);
+ if (open_file->closePend)
continue;
/* We check if file is open for writing first */
- if((open_file->pfile) &&
+ if ((open_file->pfile) &&
((open_file->pfile->f_flags & O_RDWR) ||
(open_file->pfile->f_flags & O_WRONLY))) {
read_unlock(&GlobalSMBSeslock);
- bytes_written = cifs_write(open_file->pfile, write_data,
- to-from, &offset);
+ bytes_written = cifs_write(open_file->pfile,
+ write_data, to-from,
+ &offset);
read_lock(&GlobalSMBSeslock);
/* Does mm or vfs already set times? */
- inode->i_atime = inode->i_mtime = current_fs_time(inode->i_sb);
+ inode->i_atime =
+ inode->i_mtime = current_fs_time(inode->i_sb);
if ((bytes_written > 0) && (offset)) {
rc = 0;
- } else if(bytes_written < 0) {
- if(rc == -EBADF) {
- /* have seen a case in which
- kernel seemed to have closed/freed a file
- even with writes active so we might as well
- see if there are other file structs to try
- for the same inode before giving up */
+ } else if (bytes_written < 0) {
+ if (rc == -EBADF) {
+ /* have seen a case in which kernel seemed to
+ have closed/freed a file even with writes
+ active so we might as well see if there are
+ other file structs to try for the same
+ inode before giving up */
continue;
} else
rc = bytes_written;
}
- break; /* now that we found a valid file handle
- and tried to write to it we are done, no
- sense continuing to loop looking for another */
+ break; /* now that we found a valid file handle and
+ tried to write to it we are done, no sense
+ continuing to loop looking for another */
}
- if(tmp->next == NULL) {
- cFYI(1,("File instance %p removed",tmp));
+ if (tmp->next == NULL) {
+ cFYI(1, ("File instance %p removed", tmp));
break;
}
}
read_unlock(&GlobalSMBSeslock);
- if(open_file == NULL) {
- cFYI(1,("No writeable filehandles for inode"));
+ if (open_file == NULL) {
+ cFYI(1, ("No writeable filehandles for inode"));
rc = -EIO;
}
@@ -938,21 +979,24 @@ cifs_partialpagewrite(struct page *page,unsigned from, unsigned to)
}
#if 0
-static int
-cifs_writepages(struct address_space *mapping, struct writeback_control *wbc)
+static int cifs_writepages(struct address_space *mapping,
+ struct writeback_control *wbc)
{
int rc = -EFAULT;
int xid;
xid = GetXid();
-/* call 16K write then Setpageuptodate */
+
+ /* Find contiguous pages then iterate through repeating
+ call 16K write then Setpageuptodate or if LARGE_WRITE_X
+ support then send larger writes via kevec so as to eliminate
+ a memcpy */
FreeXid(xid);
return rc;
}
#endif
-static int
-cifs_writepage(struct page* page, struct writeback_control *wbc)
+static int cifs_writepage(struct page* page, struct writeback_control *wbc)
{
int rc = -EFAULT;
int xid;
@@ -961,10 +1005,10 @@ cifs_writepage(struct page* page, struct writeback_control *wbc)
/* BB add check for wbc flags */
page_cache_get(page);
if (!PageUptodate(page)) {
- cFYI(1,("ppw - page not up to date"));
+ cFYI(1, ("ppw - page not up to date"));
}
- rc = cifs_partialpagewrite(page,0,PAGE_CACHE_SIZE);
+ rc = cifs_partialpagewrite(page, 0, PAGE_CACHE_SIZE);
SetPageUptodate(page); /* BB add check for error and Clearuptodate? */
unlock_page(page);
page_cache_release(page);
@@ -972,66 +1016,67 @@ cifs_writepage(struct page* page, struct writeback_control *wbc)
return rc;
}
-static int
-cifs_commit_write(struct file *file, struct page *page, unsigned offset,
- unsigned to)
+static int cifs_commit_write(struct file *file, struct page *page,
+ unsigned offset, unsigned to)
{
int xid;
int rc = 0;
struct inode *inode = page->mapping->host;
loff_t position = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
- char * page_data;
+ char *page_data;
xid = GetXid();
- cFYI(1,("commit write for page %p up to position %lld for %d",page,position,to));
- if (position > inode->i_size){
+ cFYI(1, ("commit write for page %p up to position %lld for %d",
+ page, position, to));
+ if (position > inode->i_size) {
i_size_write(inode, position);
- /*if (file->private_data == NULL) {
+ /* if (file->private_data == NULL) {
rc = -EBADF;
} else {
open_file = (struct cifsFileInfo *)file->private_data;
cifs_sb = CIFS_SB(inode->i_sb);
rc = -EAGAIN;
- while(rc == -EAGAIN) {
- if((open_file->invalidHandle) &&
- (!open_file->closePend)) {
- rc = cifs_reopen_file(file->f_dentry->d_inode,file);
- if(rc != 0)
+ while (rc == -EAGAIN) {
+ if ((open_file->invalidHandle) &&
+ (!open_file->closePend)) {
+ rc = cifs_reopen_file(
+ file->f_dentry->d_inode, file);
+ if (rc != 0)
break;
}
- if(!open_file->closePend) {
- rc = CIFSSMBSetFileSize(xid, cifs_sb->tcon,
- position, open_file->netfid,
- open_file->pid,FALSE);
+ if (!open_file->closePend) {
+ rc = CIFSSMBSetFileSize(xid,
+ cifs_sb->tcon, position,
+ open_file->netfid,
+ open_file->pid, FALSE);
} else {
rc = -EBADF;
break;
}
}
- cFYI(1,(" SetEOF (commit write) rc = %d",rc));
- }*/
+ cFYI(1, (" SetEOF (commit write) rc = %d", rc));
+ } */
}
if (!PageUptodate(page)) {
position = ((loff_t)page->index << PAGE_CACHE_SHIFT) + offset;
/* can not rely on (or let) writepage write this data */
- if(to < offset) {
- cFYI(1,("Illegal offsets, can not copy from %d to %d",
- offset,to));
+ if (to < offset) {
+ cFYI(1, ("Illegal offsets, can not copy from %d to %d",
+ offset, to));
FreeXid(xid);
return rc;
}
- /* this is probably better than directly calling
- partialpage_write since in this function
- the file handle is known which we might as well
- leverage */
- /* BB check if anything else missing out of ppw */
- /* such as updating last write time */
+ /* this is probably better than directly calling
+ partialpage_write since in this function the file handle is
+ known which we might as well leverage */
+ /* BB check if anything else missing out of ppw
+ such as updating last write time */
page_data = kmap(page);
- rc = cifs_write(file, page_data+offset,to-offset,
- &position);
- if(rc > 0)
+ rc = cifs_write(file, page_data + offset, to-offset,
+ &position);
+ if (rc > 0)
rc = 0;
- /* else if rc < 0 should we set writebehind rc? */
+ /* else if (rc < 0) should we set writebehind rc? */
kunmap(page);
} else {
set_page_dirty(page);
@@ -1041,12 +1086,11 @@ cifs_commit_write(struct file *file, struct page *page, unsigned offset,
return rc;
}
-int
-cifs_fsync(struct file *file, struct dentry *dentry, int datasync)
+int cifs_fsync(struct file *file, struct dentry *dentry, int datasync)
{
int xid;
int rc = 0;
- struct inode * inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_dentry->d_inode;
xid = GetXid();
@@ -1054,14 +1098,13 @@ cifs_fsync(struct file *file, struct dentry *dentry, int datasync)
dentry->d_name.name, datasync));
rc = filemap_fdatawrite(inode->i_mapping);
- if(rc == 0)
+ if (rc == 0)
CIFS_I(inode)->write_behind_rc = 0;
FreeXid(xid);
return rc;
}
-/* static int
-cifs_sync_page(struct page *page)
+/* static int cifs_sync_page(struct page *page)
{
struct address_space *mapping;
struct inode *inode;
@@ -1069,18 +1112,18 @@ cifs_sync_page(struct page *page)
unsigned int rpages = 0;
int rc = 0;
- cFYI(1,("sync page %p",page));
+ cFYI(1, ("sync page %p",page));
mapping = page->mapping;
if (!mapping)
return 0;
inode = mapping->host;
if (!inode)
- return 0;*/
+ return 0; */
/* fill in rpages then
- result = cifs_pagein_inode(inode, index, rpages); *//* BB finish */
+ result = cifs_pagein_inode(inode, index, rpages); */ /* BB finish */
-/* cFYI(1, ("rpages is %d for sync page of Index %ld ", rpages, index));
+/* cFYI(1, ("rpages is %d for sync page of Index %ld ", rpages, index));
if (rc < 0)
return rc;
@@ -1090,35 +1133,32 @@ cifs_sync_page(struct page *page)
/*
* As file closes, flush all cached write data for this inode checking
* for write behind errors.
- *
*/
int cifs_flush(struct file *file)
{
struct inode * inode = file->f_dentry->d_inode;
int rc = 0;
- /* Rather than do the steps manually: */
- /* lock the inode for writing */
- /* loop through pages looking for write behind data (dirty pages) */
- /* coalesce into contiguous 16K (or smaller) chunks to write to server */
- /* send to server (prefer in parallel) */
- /* deal with writebehind errors */
- /* unlock inode for writing */
- /* filemapfdatawrite appears easier for the time being */
+ /* Rather than do the steps manually:
+ lock the inode for writing
+ loop through pages looking for write behind data (dirty pages)
+ coalesce into contiguous 16K (or smaller) chunks to write to server
+ send to server (prefer in parallel)
+ deal with writebehind errors
+ unlock inode for writing
+ filemapfdatawrite appears easier for the time being */
rc = filemap_fdatawrite(inode->i_mapping);
- if(rc == 0) /* reset wb rc if we were able to write out dirty pages */
+ if (!rc) /* reset wb rc if we were able to write out dirty pages */
CIFS_I(inode)->write_behind_rc = 0;
- cFYI(1,("Flush inode %p file %p rc %d",inode,file,rc));
+ cFYI(1, ("Flush inode %p file %p rc %d",inode,file,rc));
return rc;
}
-
-ssize_t
-cifs_user_read(struct file * file, char __user *read_data, size_t read_size,
- loff_t * poffset)
+ssize_t cifs_user_read(struct file *file, char __user *read_data,
+ size_t read_size, loff_t *poffset)
{
int rc = -EACCES;
unsigned int bytes_read = 0;
@@ -1127,10 +1167,10 @@ cifs_user_read(struct file * file, char __user *read_data, size_t read_size,
struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon;
int xid;
- struct cifsFileInfo * open_file;
- char * smb_read_data;
- char __user * current_offset;
- struct smb_com_read_rsp * pSMBr;
+ struct cifsFileInfo *open_file;
+ char *smb_read_data;
+ char __user *current_offset;
+ struct smb_com_read_rsp *pSMBr;
xid = GetXid();
cifs_sb = CIFS_SB(file->f_dentry->d_sb);
@@ -1142,20 +1182,22 @@ cifs_user_read(struct file * file, char __user *read_data, size_t read_size,
}
open_file = (struct cifsFileInfo *)file->private_data;
- if((file->f_flags & O_ACCMODE) == O_WRONLY) {
- cFYI(1,("attempting read on write only file instance"));
+ if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
+ cFYI(1, ("attempting read on write only file instance"));
}
-
- for (total_read = 0,current_offset=read_data; read_size > total_read;
- total_read += bytes_read,current_offset+=bytes_read) {
- current_read_size = min_t(const int,read_size - total_read,cifs_sb->rsize);
+ for (total_read = 0, current_offset = read_data;
+ read_size > total_read;
+ total_read += bytes_read, current_offset += bytes_read) {
+ current_read_size = min_t(const int, read_size - total_read,
+ cifs_sb->rsize);
rc = -EAGAIN;
smb_read_data = NULL;
- while(rc == -EAGAIN) {
- if ((open_file->invalidHandle) && (!open_file->closePend)) {
+ while (rc == -EAGAIN) {
+ if ((open_file->invalidHandle) &&
+ (!open_file->closePend)) {
rc = cifs_reopen_file(file->f_dentry->d_inode,
- file,TRUE);
- if(rc != 0)
+ file, TRUE);
+ if (rc != 0)
break;
}
@@ -1165,9 +1207,15 @@ cifs_user_read(struct file * file, char __user *read_data, size_t read_size,
&bytes_read, &smb_read_data);
pSMBr = (struct smb_com_read_rsp *)smb_read_data;
- copy_to_user(current_offset,smb_read_data + 4/* RFC1001 hdr*/
- + le16_to_cpu(pSMBr->DataOffset), bytes_read);
- if(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);
smb_read_data = NULL;
}
@@ -1193,9 +1241,9 @@ cifs_user_read(struct file * file, char __user *read_data, size_t read_size,
return total_read;
}
-static ssize_t
-cifs_read(struct file * file, char *read_data, size_t read_size,
- loff_t * poffset)
+
+static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
+ loff_t *poffset)
{
int rc = -EACCES;
unsigned int bytes_read = 0;
@@ -1204,8 +1252,8 @@ cifs_read(struct file * file, char *read_data, size_t read_size,
struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon;
int xid;
- char * current_offset;
- struct cifsFileInfo * open_file;
+ char *current_offset;
+ struct cifsFileInfo *open_file;
xid = GetXid();
cifs_sb = CIFS_SB(file->f_dentry->d_sb);
@@ -1217,19 +1265,21 @@ cifs_read(struct file * file, char *read_data, size_t read_size,
}
open_file = (struct cifsFileInfo *)file->private_data;
- if((file->f_flags & O_ACCMODE) == O_WRONLY) {
- cFYI(1,("attempting read on write only file instance"));
- }
+ if ((file->f_flags & O_ACCMODE) == O_WRONLY)
+ cFYI(1, ("attempting read on write only file instance"));
- for (total_read = 0,current_offset=read_data; read_size > total_read;
- total_read += bytes_read,current_offset+=bytes_read) {
- current_read_size = min_t(const int,read_size - total_read,cifs_sb->rsize);
+ for (total_read = 0, current_offset = read_data;
+ read_size > total_read;
+ total_read += bytes_read, current_offset += bytes_read) {
+ current_read_size = min_t(const int, read_size - total_read,
+ cifs_sb->rsize);
rc = -EAGAIN;
- while(rc == -EAGAIN) {
- if ((open_file->invalidHandle) && (!open_file->closePend)) {
+ while (rc == -EAGAIN) {
+ if ((open_file->invalidHandle) &&
+ (!open_file->closePend)) {
rc = cifs_reopen_file(file->f_dentry->d_inode,
- file,TRUE);
- if(rc != 0)
+ file, TRUE);
+ if (rc != 0)
break;
}
@@ -1259,26 +1309,15 @@ cifs_read(struct file * file, char *read_data, size_t read_size,
return total_read;
}
-int cifs_file_mmap(struct file * file, struct vm_area_struct * vma)
+int cifs_file_mmap(struct file *file, struct vm_area_struct *vma)
{
- struct dentry * dentry = file->f_dentry;
- int rc, xid;
-
-#ifdef CIFS_EXPERIMENTAL /* BB fixme reenable when cifs_read_wrapper fixed */
- if(dentry->d_sb) {
- struct cifs_sb_info *cifs_sb;
- cifs_sb = CIFS_SB(sb);
- if(cifs_sb != NULL) {
- if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
- return -ENODEV
- }
- }
-#endif /* CIFS_EXPERIMENTAL */
+ struct dentry *dentry = file->f_dentry;
+ int rc, xid;
xid = GetXid();
rc = cifs_revalidate(dentry);
if (rc) {
- cFYI(1,("Validation prior to mmap failed, error=%d", rc));
+ cFYI(1, ("Validation prior to mmap failed, error=%d", rc));
FreeXid(xid);
return rc;
}
@@ -1287,38 +1326,41 @@ int cifs_file_mmap(struct file * file, struct vm_area_struct * vma)
return rc;
}
+
static void cifs_copy_cache_pages(struct address_space *mapping,
- struct list_head *pages, int bytes_read,
- char *data,struct pagevec * plru_pvec)
+ struct list_head *pages, int bytes_read, char *data,
+ struct pagevec *plru_pvec)
{
struct page *page;
- char * target;
+ char *target;
while (bytes_read > 0) {
- if(list_empty(pages))
+ if (list_empty(pages))
break;
page = list_entry(pages->prev, struct page, lru);
list_del(&page->lru);
- if (add_to_page_cache(page, mapping, page->index, GFP_KERNEL)) {
+ if (add_to_page_cache(page, mapping, page->index,
+ GFP_KERNEL)) {
page_cache_release(page);
- cFYI(1,("Add page cache failed"));
+ cFYI(1, ("Add page cache failed"));
continue;
}
target = kmap_atomic(page,KM_USER0);
- if(PAGE_CACHE_SIZE > bytes_read) {
- memcpy(target,data,bytes_read);
+ if (PAGE_CACHE_SIZE > bytes_read) {
+ memcpy(target, data, bytes_read);
/* zero the tail end of this partial page */
- memset(target+bytes_read,0,PAGE_CACHE_SIZE-bytes_read);
+ memset(target + bytes_read, 0,
+ PAGE_CACHE_SIZE - bytes_read);
bytes_read = 0;
} else {
- memcpy(target,data,PAGE_CACHE_SIZE);
+ memcpy(target, data, PAGE_CACHE_SIZE);
bytes_read -= PAGE_CACHE_SIZE;
}
- kunmap_atomic(target,KM_USER0);
+ kunmap_atomic(target, KM_USER0);
flush_dcache_page(page);
SetPageUptodate(page);
@@ -1330,23 +1372,21 @@ static void cifs_copy_cache_pages(struct address_space *mapping,
return;
}
-
-static int
-cifs_readpages(struct file *file, struct address_space *mapping,
- struct list_head *page_list, unsigned num_pages)
+static int cifs_readpages(struct file *file, struct address_space *mapping,
+ struct list_head *page_list, unsigned num_pages)
{
int rc = -EACCES;
int xid;
loff_t offset;
- struct page * page;
+ struct page *page;
struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon;
int bytes_read = 0;
unsigned int read_size,i;
- char * smb_read_data = NULL;
- struct smb_com_read_rsp * pSMBr;
+ char *smb_read_data = NULL;
+ struct smb_com_read_rsp *pSMBr;
struct pagevec lru_pvec;
- struct cifsFileInfo * open_file;
+ struct cifsFileInfo *open_file;
xid = GetXid();
if (file->private_data == NULL) {
@@ -1359,44 +1399,46 @@ cifs_readpages(struct file *file, struct address_space *mapping,
pagevec_init(&lru_pvec, 0);
- for(i = 0;i<num_pages;) {
+ for (i = 0; i < num_pages; ) {
unsigned contig_pages;
- struct page * tmp_page;
+ struct page *tmp_page;
unsigned long expected_index;
- if(list_empty(page_list)) {
+ if (list_empty(page_list))
break;
- }
+
page = list_entry(page_list->prev, struct page, lru);
offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
/* count adjacent pages that we will read into */
contig_pages = 0;
- expected_index = list_entry(page_list->prev,struct page,lru)->index;
+ expected_index =
+ list_entry(page_list->prev, struct page, lru)->index;
list_for_each_entry_reverse(tmp_page,page_list,lru) {
- if(tmp_page->index == expected_index) {
+ if (tmp_page->index == expected_index) {
contig_pages++;
expected_index++;
- } else {
+ } else
break;
- }
}
- if(contig_pages + i > num_pages) {
+ if (contig_pages + i > num_pages)
contig_pages = num_pages - i;
- }
- /* for reads over a certain size could initiate async read ahead */
+ /* for reads over a certain size could initiate async
+ read ahead */
read_size = contig_pages * PAGE_CACHE_SIZE;
/* Read size needs to be in multiples of one page */
- read_size = min_t(const unsigned int,read_size,cifs_sb->rsize & PAGE_CACHE_MASK);
+ read_size = min_t(const unsigned int, read_size,
+ cifs_sb->rsize & PAGE_CACHE_MASK);
rc = -EAGAIN;
- while(rc == -EAGAIN) {
- if ((open_file->invalidHandle) && (!open_file->closePend)) {
+ while (rc == -EAGAIN) {
+ if ((open_file->invalidHandle) &&
+ (!open_file->closePend)) {
rc = cifs_reopen_file(file->f_dentry->d_inode,
file, TRUE);
- if(rc != 0)
+ if (rc != 0)
break;
}
@@ -1405,18 +1447,19 @@ cifs_readpages(struct file *file, struct address_space *mapping,
read_size, offset,
&bytes_read, &smb_read_data);
/* BB need to check return code here */
- if(rc== -EAGAIN) {
- if(smb_read_data) {
+ if (rc== -EAGAIN) {
+ if (smb_read_data) {
cifs_buf_release(smb_read_data);
smb_read_data = NULL;
}
}
}
if ((rc < 0) || (smb_read_data == NULL)) {
- cFYI(1,("Read error in readpages: %d",rc));
+ cFYI(1, ("Read error in readpages: %d", rc));
/* clean up remaing pages off list */
while (!list_empty(page_list) && (i < num_pages)) {
- page = list_entry(page_list->prev, struct page, lru);
+ page = list_entry(page_list->prev, struct page,
+ lru);
list_del(&page->lru);
page_cache_release(page);
}
@@ -1434,31 +1477,40 @@ cifs_readpages(struct file *file, struct address_space *mapping,
pTcon->bytes_read += bytes_read;
spin_unlock(&pTcon->stat_lock);
#endif
- if((int)(bytes_read & PAGE_CACHE_MASK) != bytes_read) {
+ if ((int)(bytes_read & PAGE_CACHE_MASK) != bytes_read) {
i++; /* account for partial page */
- /* server copy of file can have smaller size than client */
- /* BB do we need to verify this common case ? this case is ok -
- if we are at server EOF we will hit it on next read */
+ /* server copy of file can have smaller size
+ than client */
+ /* BB do we need to verify this common case ?
+ this case is ok - if we are at server EOF
+ we will hit it on next read */
- /* while(!list_empty(page_list) && (i < num_pages)) {
- page = list_entry(page_list->prev,struct page, list);
+ /* while (!list_empty(page_list) && (i < num_pages)) {
+ page = list_entry(page_list->prev,
+ struct page, list);
list_del(&page->list);
page_cache_release(page);
}
break; */
}
} else {
- cFYI(1,("No bytes read (%d) at offset %lld . Cleaning remaining pages from readahead list",bytes_read,offset));
- /* BB turn off caching and do new lookup on file size at server? */
+ cFYI(1, ("No bytes read (%d) at offset %lld . "
+ "Cleaning remaining pages from readahead list",
+ bytes_read, offset));
+ /* BB turn off caching and do new lookup on
+ file size at server? */
while (!list_empty(page_list) && (i < num_pages)) {
- page = list_entry(page_list->prev, struct page, lru);
+ page = list_entry(page_list->prev, struct page,
+ lru);
list_del(&page->lru);
- page_cache_release(page); /* BB removeme - replace with zero of page? */
+
+ /* BB removeme - replace with zero of page? */
+ page_cache_release(page);
}
break;
}
- if(smb_read_data) {
+ if (smb_read_data) {
cifs_buf_release(smb_read_data);
smb_read_data = NULL;
}
@@ -1468,7 +1520,7 @@ cifs_readpages(struct file *file, struct address_space *mapping,
pagevec_lru_add(&lru_pvec);
/* need to free smb_read_data buf before exit */
- if(smb_read_data) {
+ if (smb_read_data) {
cifs_buf_release(smb_read_data);
smb_read_data = NULL;
}
@@ -1477,9 +1529,10 @@ cifs_readpages(struct file *file, struct address_space *mapping,
return rc;
}
-static int cifs_readpage_worker(struct file *file, struct page *page, loff_t * poffset)
+static int cifs_readpage_worker(struct file *file, struct page *page,
+ loff_t *poffset)
{
- char * read_data;
+ char *read_data;
int rc;
page_cache_get(page);
@@ -1490,16 +1543,15 @@ static int cifs_readpage_worker(struct file *file, struct page *page, loff_t * p
if (rc < 0)
goto io_error;
- else {
- cFYI(1,("Bytes read %d ",rc));
- }
+ else
+ cFYI(1, ("Bytes read %d ",rc));
file->f_dentry->d_inode->i_atime =
current_fs_time(file->f_dentry->d_inode->i_sb);
- if(PAGE_CACHE_SIZE > rc) {
- memset(read_data+rc, 0, PAGE_CACHE_SIZE - rc);
- }
+ if (PAGE_CACHE_SIZE > rc)
+ memset(read_data + rc, 0, PAGE_CACHE_SIZE - rc);
+
flush_dcache_page(page);
SetPageUptodate(page);
rc = 0;
@@ -1510,8 +1562,7 @@ io_error:
return rc;
}
-static int
-cifs_readpage(struct file *file, struct page *page)
+static int cifs_readpage(struct file *file, struct page *page)
{
loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
int rc = -EACCES;
@@ -1524,9 +1575,10 @@ cifs_readpage(struct file *file, struct page *page)
return -EBADF;
}
- cFYI(1,("readpage %p at offset %d 0x%x\n",page,(int)offset,(int)offset));
+ cFYI(1, ("readpage %p at offset %d 0x%x\n",
+ page, (int)offset, (int)offset));
- rc = cifs_readpage_worker(file,page,&offset);
+ rc = cifs_readpage_worker(file, page, &offset);
unlock_page(page);
@@ -1540,35 +1592,34 @@ cifs_readpage(struct file *file, struct page *page)
refreshing the inode only on increases in the file size
but this is tricky to do without racing with writebehind
page caching in the current Linux kernel design */
-
-int is_size_safe_to_change(struct cifsInodeInfo * cifsInode)
+int is_size_safe_to_change(struct cifsInodeInfo *cifsInode)
{
struct list_head *tmp;
struct list_head *tmp1;
struct cifsFileInfo *open_file = NULL;
int rc = TRUE;
- if(cifsInode == NULL)
+ if (cifsInode == NULL)
return rc;
read_lock(&GlobalSMBSeslock);
list_for_each_safe(tmp, tmp1, &cifsInode->openFileList) {
- open_file = list_entry(tmp,struct cifsFileInfo, flist);
- if(open_file == NULL)
+ open_file = list_entry(tmp, struct cifsFileInfo, flist);
+ if (open_file == NULL)
break;
- if(open_file->closePend)
+ if (open_file->closePend)
continue;
/* We check if file is open for writing,
- BB we could supplement this with a check to see if file size
- changes have been flushed to server - ie inode metadata dirty */
- if((open_file->pfile) &&
- ((open_file->pfile->f_flags & O_RDWR) ||
- (open_file->pfile->f_flags & O_WRONLY))) {
- rc = FALSE;
- break;
+ BB we could supplement this with a check to see if file size
+ changes have been flushed to server - ie inode metadata dirty */
+ if ((open_file->pfile) &&
+ ((open_file->pfile->f_flags & O_RDWR) ||
+ (open_file->pfile->f_flags & O_WRONLY))) {
+ rc = FALSE;
+ break;
}
- if(tmp->next == NULL) {
- cFYI(1,("File instance %p removed",tmp));
+ if (tmp->next == NULL) {
+ cFYI(1, ("File instance %p removed", tmp));
break;
}
}
@@ -1577,829 +1628,12 @@ int is_size_safe_to_change(struct cifsInodeInfo * cifsInode)
}
-void
-fill_in_inode(struct inode *tmp_inode,
- FILE_DIRECTORY_INFO * pfindData, int *pobject_type)
-{
- struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
- struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb);
- __u32 attr = le32_to_cpu(pfindData->ExtFileAttributes);
- __u64 allocation_size = le64_to_cpu(pfindData->AllocationSize);
- __u64 end_of_file = le64_to_cpu(pfindData->EndOfFile);
-
- cifsInfo->cifsAttrs = attr;
- cifsInfo->time = jiffies;
-
- /* Linux can not store file creation time unfortunately so ignore it */
- tmp_inode->i_atime =
- cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
- tmp_inode->i_mtime =
- cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime));
- tmp_inode->i_ctime =
- cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
- /* treat dos attribute of read-only as read-only mode bit e.g. 555? */
- /* 2767 perms - indicate mandatory locking */
- /* BB fill in uid and gid here? with help from winbind?
- or retrieve from NTFS stream extended attribute */
- if(atomic_read(&cifsInfo->inUse) == 0) {
- tmp_inode->i_uid = cifs_sb->mnt_uid;
- tmp_inode->i_gid = cifs_sb->mnt_gid;
- /* set default mode. will override for dirs below */
- tmp_inode->i_mode = cifs_sb->mnt_file_mode;
- }
-
- cFYI(0,
- ("CIFS FFIRST: Attributes came in as 0x%x",
- attr));
- if (attr & ATTR_DIRECTORY) {
- *pobject_type = DT_DIR;
- /* override default perms since we do not lock dirs */
- if(atomic_read(&cifsInfo->inUse) == 0) {
- tmp_inode->i_mode = cifs_sb->mnt_dir_mode;
- }
- tmp_inode->i_mode |= S_IFDIR;
-/* we no longer mark these because we could not follow them */
-/* } else if (attr & ATTR_REPARSE) {
- *pobject_type = DT_LNK;
- tmp_inode->i_mode |= S_IFLNK;*/
- } else {
- *pobject_type = DT_REG;
- tmp_inode->i_mode |= S_IFREG;
- if(attr & ATTR_READONLY)
- tmp_inode->i_mode &= ~(S_IWUGO);
- }/* could add code here - to validate if device or weird share type? */
-
- /* can not fill in nlink here as in qpathinfo version and Unx search */
- if(atomic_read(&cifsInfo->inUse) == 0) {
- atomic_set(&cifsInfo->inUse,1);
- }
-
- if(is_size_safe_to_change(cifsInfo)) {
- /* can not safely change the file size here if the
- client is writing to it due to potential races */
- i_size_write(tmp_inode,end_of_file);
-
- /* 512 bytes (2**9) is the fake blocksize that must be used */
- /* for this calculation, even though the reported blocksize is larger */
- tmp_inode->i_blocks = (512 - 1 + allocation_size) >> 9;
- }
-
- if (allocation_size < end_of_file)
- cFYI(1, ("Possible sparse file: allocation size less than end of file "));
- cFYI(1,
- ("File Size %ld and blocks %ld and blocksize %ld",
- (unsigned long) tmp_inode->i_size, tmp_inode->i_blocks,
- tmp_inode->i_blksize));
- if (S_ISREG(tmp_inode->i_mode)) {
- cFYI(1, (" File inode "));
- tmp_inode->i_op = &cifs_file_inode_ops;
- tmp_inode->i_fop = &cifs_file_ops;
- tmp_inode->i_data.a_ops = &cifs_addr_ops;
- } else if (S_ISDIR(tmp_inode->i_mode)) {
- cFYI(1, (" Directory inode"));
- tmp_inode->i_op = &cifs_dir_inode_ops;
- tmp_inode->i_fop = &cifs_dir_ops;
- } else if (S_ISLNK(tmp_inode->i_mode)) {
- cFYI(1, (" Symbolic Link inode "));
- tmp_inode->i_op = &cifs_symlink_inode_ops;
- } else {
- cFYI(1, (" Init special inode "));
- init_special_inode(tmp_inode, tmp_inode->i_mode,
- tmp_inode->i_rdev);
- }
-}
-
-void
-unix_fill_in_inode(struct inode *tmp_inode,
- FILE_UNIX_INFO * pfindData, int *pobject_type)
-{
- struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
- __u32 type = le32_to_cpu(pfindData->Type);
- __u64 num_of_bytes = le64_to_cpu(pfindData->NumOfBytes);
- __u64 end_of_file = le64_to_cpu(pfindData->EndOfFile);
- cifsInfo->time = jiffies;
- atomic_inc(&cifsInfo->inUse);
-
- tmp_inode->i_atime =
- cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
- tmp_inode->i_mtime =
- cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastModificationTime));
- tmp_inode->i_ctime =
- cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastStatusChange));
-
- tmp_inode->i_mode = le64_to_cpu(pfindData->Permissions);
- if (type == UNIX_FILE) {
- *pobject_type = DT_REG;
- tmp_inode->i_mode |= S_IFREG;
- } else if (type == UNIX_SYMLINK) {
- *pobject_type = DT_LNK;
- tmp_inode->i_mode |= S_IFLNK;
- } else if (type == UNIX_DIR) {
- *pobject_type = DT_DIR;
- tmp_inode->i_mode |= S_IFDIR;
- } else if (type == UNIX_CHARDEV) {
- *pobject_type = DT_CHR;
- tmp_inode->i_mode |= S_IFCHR;
- tmp_inode->i_rdev = MKDEV(le64_to_cpu(pfindData->DevMajor),
- le64_to_cpu(pfindData->DevMinor) & MINORMASK);
- } else if (type == UNIX_BLOCKDEV) {
- *pobject_type = DT_BLK;
- tmp_inode->i_mode |= S_IFBLK;
- tmp_inode->i_rdev = MKDEV(le64_to_cpu(pfindData->DevMajor),
- le64_to_cpu(pfindData->DevMinor) & MINORMASK);
- } else if (type == UNIX_FIFO) {
- *pobject_type = DT_FIFO;
- tmp_inode->i_mode |= S_IFIFO;
- } else if (type == UNIX_SOCKET) {
- *pobject_type = DT_SOCK;
- tmp_inode->i_mode |= S_IFSOCK;
- }
-
- tmp_inode->i_uid = le64_to_cpu(pfindData->Uid);
- tmp_inode->i_gid = le64_to_cpu(pfindData->Gid);
- tmp_inode->i_nlink = le64_to_cpu(pfindData->Nlinks);
-
-
- if(is_size_safe_to_change(cifsInfo)) {
- /* can not safely change the file size here if the
- client is writing to it due to potential races */
- i_size_write(tmp_inode,end_of_file);
-
- /* 512 bytes (2**9) is the fake blocksize that must be used */
- /* for this calculation, not the real blocksize */
- tmp_inode->i_blocks = (512 - 1 + num_of_bytes) >> 9;
- }
-
- if (S_ISREG(tmp_inode->i_mode)) {
- cFYI(1, ("File inode"));
- tmp_inode->i_op = &cifs_file_inode_ops;
- tmp_inode->i_fop = &cifs_file_ops;
- tmp_inode->i_data.a_ops = &cifs_addr_ops;
- } else if (S_ISDIR(tmp_inode->i_mode)) {
- cFYI(1, ("Directory inode"));
- tmp_inode->i_op = &cifs_dir_inode_ops;
- tmp_inode->i_fop = &cifs_dir_ops;
- } else if (S_ISLNK(tmp_inode->i_mode)) {
- cFYI(1, ("Symbolic Link inode"));
- tmp_inode->i_op = &cifs_symlink_inode_ops;
-/* tmp_inode->i_fop = *//* do not need to set to anything */
- } else {
- cFYI(1, ("Special inode"));
- init_special_inode(tmp_inode, tmp_inode->i_mode,
- tmp_inode->i_rdev);
- }
-}
-
-/* Returns one if new inode created (which therefore needs to be hashed) */
-/* Might check in the future if inode number changed so we can rehash inode */
-int
-construct_dentry(struct qstr *qstring, struct file *file,
- struct inode **ptmp_inode, struct dentry **pnew_dentry)
-{
- struct dentry *tmp_dentry;
- struct cifs_sb_info *cifs_sb;
- struct cifsTconInfo *pTcon;
- int rc = 0;
-
- cFYI(1, ("For %s ", qstring->name));
- cifs_sb = CIFS_SB(file->f_dentry->d_sb);
- pTcon = cifs_sb->tcon;
-
- qstring->hash = full_name_hash(qstring->name, qstring->len);
- tmp_dentry = d_lookup(file->f_dentry, qstring);
- if (tmp_dentry) {
- cFYI(0, (" existing dentry with inode 0x%p", tmp_dentry->d_inode));
- *ptmp_inode = tmp_dentry->d_inode;
- /* BB overwrite the old name? i.e. tmp_dentry->d_name and tmp_dentry->d_name.len ?? */
- if(*ptmp_inode == NULL) {
- *ptmp_inode = new_inode(file->f_dentry->d_sb);
- if(*ptmp_inode == NULL)
- return rc;
- rc = 1;
- d_instantiate(tmp_dentry, *ptmp_inode);
- }
- } else {
- tmp_dentry = d_alloc(file->f_dentry, qstring);
- if(tmp_dentry == NULL) {
- cERROR(1,("Failed allocating dentry"));
- *ptmp_inode = NULL;
- return rc;
- }
-
- *ptmp_inode = new_inode(file->f_dentry->d_sb);
- tmp_dentry->d_op = &cifs_dentry_ops;
- if(*ptmp_inode == NULL)
- return rc;
- rc = 1;
- d_instantiate(tmp_dentry, *ptmp_inode);
- d_rehash(tmp_dentry);
- }
-
- tmp_dentry->d_time = jiffies;
- *pnew_dentry = tmp_dentry;
- return rc;
-}
-
-static void reset_resume_key(struct file * dir_file,
- unsigned char * filename,
- unsigned int len,int Unicode,struct nls_table * nls_tab) {
- struct cifsFileInfo *cifsFile;
-
- cifsFile = (struct cifsFileInfo *)dir_file->private_data;
- if(cifsFile == NULL)
- return;
- if(cifsFile->search_resume_name) {
- kfree(cifsFile->search_resume_name);
- }
-
- if(Unicode)
- len *= 2;
- cifsFile->resume_name_length = len;
-
- cifsFile->search_resume_name =
- kmalloc(cifsFile->resume_name_length, GFP_KERNEL);
-
- if(cifsFile->search_resume_name == NULL) {
- cERROR(1,("failed new resume key allocate, length %d",
- cifsFile->resume_name_length));
- return;
- }
- if(Unicode)
- cifs_strtoUCS((wchar_t *) cifsFile->search_resume_name,
- filename, len, nls_tab);
- else
- memcpy(cifsFile->search_resume_name, filename,
- cifsFile->resume_name_length);
- cFYI(1,("Reset resume key to: %s with len %d",filename,len));
- return;
-}
-
-
-
-static int
-cifs_filldir(struct qstr *pqstring, FILE_DIRECTORY_INFO * pfindData,
- struct file *file, filldir_t filldir, void *direntry)
-{
- struct inode *tmp_inode;
- struct dentry *tmp_dentry;
- int object_type,rc;
-
- pqstring->name = pfindData->FileName;
- /* pqstring->len is already set by caller */
-
- rc = construct_dentry(pqstring, file, &tmp_inode, &tmp_dentry);
- if((tmp_inode == NULL) || (tmp_dentry == NULL)) {
- return -ENOMEM;
- }
- fill_in_inode(tmp_inode, pfindData, &object_type);
- if(rc) {
- /* We have no reliable way to get inode numbers
- from servers w/o Unix extensions yet so we can not set
- i_ino from pfindData yet */
-
- /* new inode created, let us hash it */
- insert_inode_hash(tmp_inode);
- } /* else if inode number changed do we rehash it? */
- rc = filldir(direntry, pfindData->FileName, pqstring->len, file->f_pos,
- tmp_inode->i_ino, object_type);
- if(rc) {
- /* due to readdir error we need to recalculate resume
- key so next readdir will restart on right entry */
- cFYI(1,("Error %d on filldir of %s",rc ,pfindData->FileName));
- }
- dput(tmp_dentry);
- return rc;
-}
-
-static int
-cifs_filldir_unix(struct qstr *pqstring,
- FILE_UNIX_INFO * pUnixFindData, struct file *file,
- filldir_t filldir, void *direntry)
-{
- struct inode *tmp_inode;
- struct dentry *tmp_dentry;
- int object_type, rc;
-
- pqstring->name = pUnixFindData->FileName;
- pqstring->len = strnlen(pUnixFindData->FileName, MAX_PATHCONF);
-
- rc = construct_dentry(pqstring, file, &tmp_inode, &tmp_dentry);
- if((tmp_inode == NULL) || (tmp_dentry == NULL)) {
- return -ENOMEM;
- }
- if(rc) {
- struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb);
-
- if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
- tmp_inode->i_ino =
- (unsigned long)pUnixFindData->UniqueId;
- }
- insert_inode_hash(tmp_inode);
- } /* else if i_ino has changed should we rehash it? */
- unix_fill_in_inode(tmp_inode, pUnixFindData, &object_type);
- rc = filldir(direntry, pUnixFindData->FileName, pqstring->len,
- file->f_pos, tmp_inode->i_ino, object_type);
- if(rc) {
- /* due to readdir error we need to recalculate resume
- key so next readdir will restart on right entry */
- cFYI(1,("Error %d on filldir of %s",rc ,pUnixFindData->FileName));
- }
- dput(tmp_dentry);
- return rc;
-}
-
-int
-cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
-{
- int rc = 0;
- int xid;
- int Unicode = FALSE;
- int UnixSearch = FALSE;
- unsigned int bufsize, i;
- __u16 searchHandle;
- struct cifs_sb_info *cifs_sb;
- struct cifsTconInfo *pTcon;
- struct cifsFileInfo *cifsFile = NULL;
- char *full_path = NULL;
- char *data;
- struct qstr qstring;
- T2_FFIRST_RSP_PARMS findParms;
- T2_FNEXT_RSP_PARMS findNextParms;
- FILE_DIRECTORY_INFO *pfindData;
- FILE_DIRECTORY_INFO *lastFindData;
- FILE_UNIX_INFO *pfindDataUnix;
-
-
- /* BB removeme begin */
- if(!experimEnabled)
- return cifs_readdir2(file,direntry,filldir);
- /* BB removeme end */
-
-
- xid = GetXid();
-
- if(file->f_dentry == NULL) {
- rc = -EIO;
- FreeXid(xid);
- return rc;
- }
- cifs_sb = CIFS_SB(file->f_dentry->d_sb);
- pTcon = cifs_sb->tcon;
- bufsize = pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE;
- if(bufsize > CIFSMaxBufSize) {
- rc = -EIO;
- FreeXid(xid);
- return rc;
- }
- data = kmalloc(bufsize, GFP_KERNEL);
- pfindData = (FILE_DIRECTORY_INFO *) data;
- if(data == NULL) {
- rc = -ENOMEM;
- FreeXid(xid);
- return rc;
- }
- down(&file->f_dentry->d_sb->s_vfs_rename_sem);
- full_path = build_wildcard_path_from_dentry(file->f_dentry);
- up(&file->f_dentry->d_sb->s_vfs_rename_sem);
-
- if(full_path == NULL) {
- kfree(data);
- FreeXid(xid);
- return -ENOMEM;
- }
- cFYI(1, ("Full path: %s start at: %lld ", full_path, file->f_pos));
-
- switch ((int) file->f_pos) {
- case 0:
- if (filldir(direntry, ".", 1, file->f_pos,
- file->f_dentry->d_inode->i_ino, DT_DIR) < 0) {
- cERROR(1, ("Filldir for current dir failed "));
- break;
- }
- file->f_pos++;
- /* fallthrough */
- case 1:
- if (filldir(direntry, "..", 2, file->f_pos,
- file->f_dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) {
- cERROR(1, ("Filldir for parent dir failed "));
- break;
- }
- file->f_pos++;
- /* fallthrough */
- case 2:
- if (file->private_data != NULL) {
- cifsFile =
- (struct cifsFileInfo *) file->private_data;
- if (cifsFile->srch_inf.endOfSearch) {
- if(cifsFile->srch_inf.emptyDir) {
- cFYI(1, ("End of search, empty dir"));
- rc = 0;
- break;
- }
- } else {
- cifsFile->invalidHandle = TRUE;
- CIFSFindClose(xid, pTcon, cifsFile->netfid);
- }
- if(cifsFile->search_resume_name) {
- kfree(cifsFile->search_resume_name);
- cifsFile->search_resume_name = NULL;
- }
- }
- rc = CIFSFindFirst(xid, pTcon, full_path, pfindData,
- &findParms, cifs_sb->local_nls,
- &Unicode, &UnixSearch);
- cFYI(1, ("Count: %d End: %d ",
- le16_to_cpu(findParms.SearchCount),
- le16_to_cpu(findParms.EndofSearch)));
-
- if (rc == 0) {
- __u16 count = le16_to_cpu(findParms.SearchCount);
- searchHandle = findParms.SearchHandle;
- if(file->private_data == NULL)
- file->private_data =
- kmalloc(sizeof(struct cifsFileInfo),GFP_KERNEL);
- if (file->private_data) {
- memset(file->private_data, 0,
- sizeof (struct cifsFileInfo));
- cifsFile =
- (struct cifsFileInfo *) file->private_data;
- cifsFile->netfid = searchHandle;
- cifsFile->invalidHandle = FALSE;
- init_MUTEX(&cifsFile->fh_sem);
- } else {
- rc = -ENOMEM;
- break;
- }
-
- renew_parental_timestamps(file->f_dentry);
- lastFindData =
- (FILE_DIRECTORY_INFO *) ((char *) pfindData +
- le16_to_cpu(findParms.LastNameOffset));
- if((char *)lastFindData > (char *)pfindData + bufsize) {
- cFYI(1,("last search entry past end of packet"));
- rc = -EIO;
- break;
- }
- /* Offset of resume key same for levels 257 and 514 */
- cifsFile->srch_inf.resume_key = lastFindData->FileIndex;
- if(UnixSearch == FALSE) {
- cifsFile->resume_name_length =
- le32_to_cpu(lastFindData->FileNameLength);
- if(cifsFile->resume_name_length > bufsize - 64) {
- cFYI(1,("Illegal resume file name length %d",
- cifsFile->resume_name_length));
- rc = -ENOMEM;
- break;
- }
- cifsFile->search_resume_name =
- kmalloc(cifsFile->resume_name_length, GFP_KERNEL);
- cFYI(1,("Last file: %s with name %d bytes long",
- lastFindData->FileName,
- cifsFile->resume_name_length));
- if(cifsFile->search_resume_name == NULL) {
- rc = -ENOMEM;
- break;
- }
- memcpy(cifsFile->search_resume_name,
- lastFindData->FileName,
- cifsFile->resume_name_length);
- } else {
- pfindDataUnix = (FILE_UNIX_INFO *)lastFindData;
- if (Unicode == TRUE) {
- for(i=0;(pfindDataUnix->FileName[i]
- | pfindDataUnix->FileName[i+1]);
- i+=2) {
- if(i > bufsize-64)
- break;
- }
- cifsFile->resume_name_length = i + 2;
- } else {
- cifsFile->resume_name_length =
- strnlen(pfindDataUnix->FileName,
- bufsize-63);
- }
- if(cifsFile->resume_name_length > bufsize - 64) {
- cFYI(1,("Illegal resume file name length %d",
- cifsFile->resume_name_length));
- rc = -ENOMEM;
- break;
- }
- cifsFile->search_resume_name =
- kmalloc(cifsFile->resume_name_length, GFP_KERNEL);
- cFYI(1,("Last file: %s with name %d bytes long",
- pfindDataUnix->FileName,
- cifsFile->resume_name_length));
- if(cifsFile->search_resume_name == NULL) {
- rc = -ENOMEM;
- break;
- }
- memcpy(cifsFile->search_resume_name,
- pfindDataUnix->FileName,
- cifsFile->resume_name_length);
- }
- for (i = 2; i < count + 2; i++) {
- if (UnixSearch == FALSE) {
- __u32 len = le32_to_cpu(pfindData->FileNameLength);
- if (Unicode == TRUE)
- len =
- cifs_strfromUCS_le
- (pfindData->FileName,
- (wchar_t *)
- pfindData->FileName,
- len / 2,
- cifs_sb->local_nls);
- qstring.len = len;
- if (((len != 1)
- || (pfindData->FileName[0] != '.'))
- && ((len != 2)
- || (pfindData->
- FileName[0] != '.')
- || (pfindData->
- FileName[1] != '.'))) {
- if(cifs_filldir(&qstring,
- pfindData,
- file, filldir,
- direntry)) {
- /* do not end search if
- kernel not ready to take
- remaining entries yet */
- reset_resume_key(file, pfindData->FileName,qstring.len,
- Unicode, cifs_sb->local_nls);
- findParms.EndofSearch = 0;
- break;
- }
- file->f_pos++;
- }
- } else { /* UnixSearch */
- pfindDataUnix =
- (FILE_UNIX_INFO *) pfindData;
- if (Unicode == TRUE)
- qstring.len =
- cifs_strfromUCS_le
- (pfindDataUnix->FileName,
- (wchar_t *)
- pfindDataUnix->FileName,
- MAX_PATHCONF,
- cifs_sb->local_nls);
- else
- qstring.len =
- strnlen(pfindDataUnix->
- FileName,
- MAX_PATHCONF);
- if (((qstring.len != 1)
- || (pfindDataUnix->
- FileName[0] != '.'))
- && ((qstring.len != 2)
- || (pfindDataUnix->
- FileName[0] != '.')
- || (pfindDataUnix->
- FileName[1] != '.'))) {
- if(cifs_filldir_unix(&qstring,
- pfindDataUnix,
- file,
- filldir,
- direntry)) {
- /* do not end search if
- kernel not ready to take
- remaining entries yet */
- findParms.EndofSearch = 0;
- reset_resume_key(file, pfindDataUnix->FileName,
- qstring.len,Unicode,cifs_sb->local_nls);
- break;
- }
- file->f_pos++;
- }
- }
- /* works also for Unix ff struct since first field of both */
- pfindData =
- (FILE_DIRECTORY_INFO *) ((char *) pfindData
- + le32_to_cpu(pfindData->NextEntryOffset));
- /* BB also should check to make sure that pointer is not beyond the end of the SMB */
- /* if(pfindData > lastFindData) rc = -EIO; break; */
- } /* end for loop */
- if ((findParms.EndofSearch != 0) && cifsFile) {
- cifsFile->srch_inf.endOfSearch = TRUE;
- if(findParms.SearchCount == cpu_to_le16(2))
- cifsFile->srch_inf.emptyDir = TRUE;
- }
- } else {
- if (cifsFile)
- cifsFile->srch_inf.endOfSearch = TRUE;
- /* unless parent directory gone do not return error */
- rc = 0;
- }
- break;
- default:
- if (file->private_data == NULL) {
- rc = -EBADF;
- cFYI(1,
- ("Readdir on closed srch, pos = %lld",
- file->f_pos));
- } else {
- cifsFile = (struct cifsFileInfo *) file->private_data;
- if (cifsFile->srch_inf.endOfSearch) {
- rc = 0;
- cFYI(1, ("End of search "));
- break;
- }
- searchHandle = cifsFile->netfid;
- rc = CIFSFindNext(xid, pTcon, pfindData,
- &findNextParms, searchHandle,
- cifsFile->search_resume_name,
- cifsFile->resume_name_length,
- cifsFile->srch_inf.resume_key,
- &Unicode, &UnixSearch);
- cFYI(1,("Count: %d End: %d ",
- le16_to_cpu(findNextParms.SearchCount),
- le16_to_cpu(findNextParms.EndofSearch)));
- if ((rc == 0) && (findNextParms.SearchCount != 0)) {
- /* BB save off resume key, key name and name length */
- __u16 count = le16_to_cpu(findNextParms.SearchCount);
- lastFindData =
- (FILE_DIRECTORY_INFO *) ((char *) pfindData
- + le16_to_cpu(findNextParms.LastNameOffset));
- if((char *)lastFindData > (char *)pfindData + bufsize) {
- cFYI(1,("last search entry past end of packet"));
- rc = -EIO;
- break;
- }
- /* Offset of resume key same for levels 257 and 514 */
- cifsFile->srch_inf.resume_key = lastFindData->FileIndex;
-
- if(UnixSearch == FALSE) {
- cifsFile->resume_name_length =
- le32_to_cpu(lastFindData->FileNameLength);
- if(cifsFile->resume_name_length > bufsize - 64) {
- cFYI(1,("Illegal resume file name length %d",
- cifsFile->resume_name_length));
- rc = -ENOMEM;
- break;
- }
- /* Free the memory allocated by previous findfirst
- or findnext call - we can not reuse the memory since
- the resume name may not be same string length */
- if(cifsFile->search_resume_name)
- kfree(cifsFile->search_resume_name);
- cifsFile->search_resume_name =
- kmalloc(cifsFile->resume_name_length, GFP_KERNEL);
- cFYI(1,("Last file: %s with name %d bytes long",
- lastFindData->FileName,
- cifsFile->resume_name_length));
- if(cifsFile->search_resume_name == NULL) {
- rc = -ENOMEM;
- break;
- }
-
- memcpy(cifsFile->search_resume_name,
- lastFindData->FileName,
- cifsFile->resume_name_length);
- } else {
- pfindDataUnix = (FILE_UNIX_INFO *)lastFindData;
- if (Unicode == TRUE) {
- for(i=0;(pfindDataUnix->FileName[i]
- | pfindDataUnix->FileName[i+1]);
- i+=2) {
- if(i > bufsize-64)
- break;
- }
- cifsFile->resume_name_length = i + 2;
- } else {
- cifsFile->resume_name_length =
- strnlen(pfindDataUnix->
- FileName,
- MAX_PATHCONF);
- }
- if(cifsFile->resume_name_length > bufsize - 64) {
- cFYI(1,("Illegal resume file name length %d",
- cifsFile->resume_name_length));
- rc = -ENOMEM;
- break;
- }
- /* Free the memory allocated by previous findfirst
- or findnext call - we can not reuse the memory since
- the resume name may not be same string length */
- if(cifsFile->search_resume_name)
- kfree(cifsFile->search_resume_name);
- cifsFile->search_resume_name =
- kmalloc(cifsFile->resume_name_length, GFP_KERNEL);
- cFYI(1,("fnext last file: %s with name %d bytes long",
- pfindDataUnix->FileName,
- cifsFile->resume_name_length));
- if(cifsFile->search_resume_name == NULL) {
- rc = -ENOMEM;
- break;
- }
- memcpy(cifsFile->search_resume_name,
- pfindDataUnix->FileName,
- cifsFile->resume_name_length);
- }
-
- for (i = 0; i < count; i++) {
- __u32 len = le32_to_cpu(pfindData->
- FileNameLength);
- if (UnixSearch == FALSE) {
- if (Unicode == TRUE)
- len =
- cifs_strfromUCS_le
- (pfindData->FileName,
- (wchar_t *)
- pfindData->FileName,
- len / 2,
- cifs_sb->local_nls);
- qstring.len = len;
- if (((len != 1)
- || (pfindData->FileName[0] != '.'))
- && ((len != 2)
- || (pfindData->FileName[0] != '.')
- || (pfindData->FileName[1] !=
- '.'))) {
- if(cifs_filldir
- (&qstring,
- pfindData,
- file, filldir,
- direntry)) {
- /* do not end search if
- kernel not ready to take
- remaining entries yet */
- findNextParms.EndofSearch = 0;
- reset_resume_key(file, pfindData->FileName,qstring.len,
- Unicode,cifs_sb->local_nls);
- break;
- }
- file->f_pos++;
- }
- } else { /* UnixSearch */
- pfindDataUnix =
- (FILE_UNIX_INFO *)
- pfindData;
- if (Unicode == TRUE)
- qstring.len =
- cifs_strfromUCS_le
- (pfindDataUnix->FileName,
- (wchar_t *)
- pfindDataUnix->FileName,
- MAX_PATHCONF,
- cifs_sb->local_nls);
- else
- qstring.len =
- strnlen
- (pfindDataUnix->
- FileName,
- MAX_PATHCONF);
- if (((qstring.len != 1)
- || (pfindDataUnix->
- FileName[0] != '.'))
- && ((qstring.len != 2)
- || (pfindDataUnix->
- FileName[0] != '.')
- || (pfindDataUnix->
- FileName[1] !=
- '.'))) {
- if(cifs_filldir_unix
- (&qstring,
- pfindDataUnix,
- file, filldir,
- direntry)) {
- /* do not end search if
- kernel not ready to take
- remaining entries yet */
- findNextParms.EndofSearch = 0;
- reset_resume_key(file, pfindDataUnix->FileName,qstring.len,
- Unicode,cifs_sb->local_nls);
- break;
- }
- file->f_pos++;
- }
- }
- pfindData = (FILE_DIRECTORY_INFO *) ((char *) pfindData +
- le32_to_cpu(pfindData->NextEntryOffset));
- /* works also for Unix find struct since first field of both */
- /* BB also should check to ensure pointer not beyond end of SMB */
- } /* end for loop */
- if (findNextParms.EndofSearch != 0) {
- cifsFile->srch_inf.endOfSearch = TRUE;
- }
- } else {
- cifsFile->srch_inf.endOfSearch = TRUE;
- rc = 0; /* unless parent directory disappeared - do not
- return error here (eg Access Denied or no more files) */
- }
- }
- } /* end switch */
- if (data)
- kfree(data);
- if (full_path)
- kfree(full_path);
- FreeXid(xid);
-
- return rc;
-}
-int cifs_prepare_write(struct file *file, struct page *page,
- unsigned from, unsigned to)
+static int cifs_prepare_write(struct file *file, struct page *page,
+ unsigned from, unsigned to)
{
int rc = 0;
loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
- cFYI(1,("prepare write for page %p from %d to %d",page,from,to));
+ cFYI(1, ("prepare write for page %p from %d to %d",page,from,to));
if (!PageUptodate(page)) {
/* if (to - from != PAGE_CACHE_SIZE) {
void *kaddr = kmap_atomic(page, KM_USER0);
@@ -2409,33 +1643,33 @@ int cifs_prepare_write(struct file *file, struct page *page,
kunmap_atomic(kaddr, KM_USER0);
} */
/* If we are writing a full page it will be up to date,
- no need to read from the server */
- if((to==PAGE_CACHE_SIZE) && (from == 0))
+ no need to read from the server */
+ if ((to == PAGE_CACHE_SIZE) && (from == 0))
SetPageUptodate(page);
/* might as well read a page, it is fast enough */
- if((file->f_flags & O_ACCMODE) != O_WRONLY) {
- rc = cifs_readpage_worker(file,page,&offset);
+ if ((file->f_flags & O_ACCMODE) != O_WRONLY) {
+ rc = cifs_readpage_worker(file, page, &offset);
} else {
- /* should we try using another
- file handle if there is one - how would we lock it
- to prevent close of that handle racing with this read? */
- /* In any case this will be written out by commit_write */
+ /* should we try using another file handle if there is one -
+ how would we lock it to prevent close of that handle
+ racing with this read?
+ In any case this will be written out by commit_write */
}
}
- /* BB should we pass any errors back? e.g. if we do not have read access to the file */
+ /* BB should we pass any errors back?
+ e.g. if we do not have read access to the file */
return 0;
}
-
struct address_space_operations cifs_addr_ops = {
.readpage = cifs_readpage,
.readpages = cifs_readpages,
.writepage = cifs_writepage,
- .prepare_write = cifs_prepare_write,
+ .prepare_write = cifs_prepare_write,
.commit_write = cifs_commit_write,
.set_page_dirty = __set_page_dirty_nobuffers,
- /* .sync_page = cifs_sync_page, */
- /*.direct_IO = */
+ /* .sync_page = cifs_sync_page, */
+ /* .direct_IO = */
};
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 80ab68c3892c8..d73b0aa86775e 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -1,7 +1,7 @@
/*
* fs/cifs/inode.c
*
- * 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
@@ -30,12 +30,8 @@
#include "cifs_debug.h"
#include "cifs_fs_sb.h"
-extern int is_size_safe_to_change(struct cifsInodeInfo *);
-
-int
-cifs_get_inode_info_unix(struct inode **pinode,
- const unsigned char *search_path,
- struct super_block *sb,int xid)
+int cifs_get_inode_info_unix(struct inode **pinode,
+ const unsigned char *search_path, struct super_block *sb, int xid)
{
int rc = 0;
FILE_UNIX_BASIC_INFO findData;
@@ -46,23 +42,24 @@ cifs_get_inode_info_unix(struct inode **pinode,
pTcon = cifs_sb->tcon;
cFYI(1, (" Getting info on %s ", search_path));
- /* we could have done a find first instead but this returns more info */
+ /* could have done a find first instead but this returns more info */
rc = CIFSSMBUnixQPathInfo(xid, pTcon, search_path, &findData,
cifs_sb->local_nls);
- /* dump_mem("\nUnixQPathInfo return data", &findData, sizeof(findData)); */
+/* dump_mem("\nUnixQPathInfo return data", &findData,
+ sizeof(findData)); */
if (rc) {
if (rc == -EREMOTE) {
tmp_path =
- kmalloc(strnlen
- (pTcon->treeName,
- MAX_TREE_SIZE + 1) +
+ kmalloc(strnlen(pTcon->treeName,
+ MAX_TREE_SIZE + 1) +
strnlen(search_path, MAX_PATHCONF) + 1,
GFP_KERNEL);
if (tmp_path == NULL) {
return -ENOMEM;
}
- /* have to skip first of the double backslash of UNC name */
- strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE);
+ /* have to skip first of the double backslash of
+ UNC name */
+ strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE);
strncat(tmp_path, search_path, MAX_PATHCONF);
rc = connect_to_dfs_path(xid, pTcon->ses,
/* treename + */ tmp_path,
@@ -73,7 +70,6 @@ cifs_get_inode_info_unix(struct inode **pinode,
} else if (rc) {
return rc;
}
-
} else {
struct cifsInodeInfo *cifsInfo;
__u32 type = le32_to_cpu(findData.Type);
@@ -87,21 +83,22 @@ cifs_get_inode_info_unix(struct inode **pinode,
return -ENOMEM;
/* Is an i_ino of zero legal? */
/* Are there sanity checks we can use to ensure that
- the server is really filling in that field? */
+ the server is really filling in that field? */
if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
- (*pinode)->i_ino =
+ (*pinode)->i_ino =
(unsigned long)findData.UniqueId;
} /* note ino incremented to unique num in new_inode */
insert_inode_hash(*pinode);
}
-
+
inode = *pinode;
cifsInfo = CIFS_I(inode);
cFYI(1, (" Old time %ld ", cifsInfo->time));
cifsInfo->time = jiffies;
cFYI(1, (" New time %ld ", cifsInfo->time));
- atomic_set(&cifsInfo->inUse,1); /* ok to set on every refresh of inode */
+ /* this is ok to set on every inode revalidate */
+ atomic_set(&cifsInfo->inUse,1);
inode->i_atime =
cifs_NTtimeToUnix(le64_to_cpu(findData.LastAccessTime));
@@ -135,22 +132,19 @@ cifs_get_inode_info_unix(struct inode **pinode,
inode->i_nlink = le64_to_cpu(findData.Nlinks);
if(is_size_safe_to_change(cifsInfo)) {
- /* can not safely change the file size here if the
+ /* can not safely change the file size here if the
client is writing to it due to potential races */
i_size_write(inode, end_of_file);
-/* blksize needs to be multiple of two. So safer to default to blksize
- and blkbits set in superblock so 2**blkbits and blksize will match */
-/* inode->i_blksize =
- (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/
- /* This seems incredibly stupid but it turns out that
- i_blocks is not related to (i_size / i_blksize), instead a
- size of 512 is required to be used for calculating num blocks */
-
+ /* blksize needs to be multiple of two. So safer to default to
+ blksize and blkbits set in superblock so 2**blkbits and blksize
+ will match rather than setting to:
+ (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/
-/* inode->i_blocks =
- (inode->i_blksize - 1 + num_of_bytes) >> inode->i_blkbits;*/
+ /* This seems incredibly stupid but it turns out that i_blocks
+ is not related to (i_size / i_blksize), instead 512 byte size
+ is required for calculating num blocks */
/* 512 bytes (2**9) is the fake blocksize that must be used */
/* for this calculation */
@@ -158,14 +152,17 @@ cifs_get_inode_info_unix(struct inode **pinode,
}
if (num_of_bytes < end_of_file)
- cFYI(1, ("Server inconsistency Error: it says allocation size less than end of file "));
+ cFYI(1, ("allocation size less than end of file "));
cFYI(1,
- ("Size %ld and blocks %ld ",
+ ("Size %ld and blocks %ld",
(unsigned long) inode->i_size, inode->i_blocks));
if (S_ISREG(inode->i_mode)) {
cFYI(1, (" File inode "));
inode->i_op = &cifs_file_inode_ops;
- inode->i_fop = &cifs_file_ops;
+ if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
+ inode->i_fop = &cifs_file_direct_ops;
+ else
+ inode->i_fop = &cifs_file_ops;
inode->i_data.a_ops = &cifs_addr_ops;
} else if (S_ISDIR(inode->i_mode)) {
cFYI(1, (" Directory inode"));
@@ -174,7 +171,7 @@ cifs_get_inode_info_unix(struct inode **pinode,
} else if (S_ISLNK(inode->i_mode)) {
cFYI(1, (" Symbolic Link inode "));
inode->i_op = &cifs_symlink_inode_ops;
-/* tmp_inode->i_fop = *//* do not need to set to anything */
+ /* tmp_inode->i_fop = */ /* do not need to set to anything */
} else {
cFYI(1, (" Init special inode "));
init_special_inode(inode, inode->i_mode,
@@ -184,9 +181,9 @@ cifs_get_inode_info_unix(struct inode **pinode,
return rc;
}
-int
-cifs_get_inode_info(struct inode **pinode, const unsigned char *search_path,
- FILE_ALL_INFO * pfindData, struct super_block *sb, int xid)
+int cifs_get_inode_info(struct inode **pinode,
+ const unsigned char *search_path, FILE_ALL_INFO *pfindData,
+ struct super_block *sb, int xid)
{
int rc = 0;
struct cifsTconInfo *pTcon;
@@ -200,18 +197,18 @@ cifs_get_inode_info(struct inode **pinode, const unsigned char *search_path,
if((pfindData == NULL) && (*pinode != NULL)) {
if(CIFS_I(*pinode)->clientCanCacheRead) {
- cFYI(1,("No need to revalidate inode sizes on cached file "));
+ cFYI(1,("No need to revalidate cached inode sizes"));
return rc;
}
}
/* if file info not passed in then get it from server */
if(pfindData == NULL) {
- buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
+ buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
if(buf == NULL)
return -ENOMEM;
pfindData = (FILE_ALL_INFO *)buf;
- /* could do find first instead but this returns more info */
+ /* could do find first instead but this returns more info */
rc = CIFSSMBQPathInfo(xid, pTcon, search_path, pfindData,
cifs_sb->local_nls);
}
@@ -225,8 +222,7 @@ cifs_get_inode_info(struct inode **pinode, const unsigned char *search_path,
strnlen(search_path, MAX_PATHCONF) + 1,
GFP_KERNEL);
if (tmp_path == NULL) {
- if(buf)
- kfree(buf);
+ kfree(buf);
return -ENOMEM;
}
@@ -238,8 +234,7 @@ cifs_get_inode_info(struct inode **pinode, const unsigned char *search_path,
kfree(tmp_path);
/* BB fix up inode etc. */
} else if (rc) {
- if(buf)
- kfree(buf);
+ kfree(buf);
return rc;
}
} else {
@@ -249,23 +244,38 @@ cifs_get_inode_info(struct inode **pinode, const unsigned char *search_path,
/* get new inode */
if (*pinode == NULL) {
*pinode = new_inode(sb);
- if(*pinode == NULL)
+ if (*pinode == NULL)
return -ENOMEM;
- /* Is an i_ino of zero legal? */
- /* Are there sanity checks we can use to ensure that
- the server is really filling in that field? */
-
- /* We can not use the IndexNumber from either
- Windows or Samba as it is frequently set to zero */
- /* There may be higher info levels that work but
- Are there Windows server or network appliances
- for which IndexNumber field is not guaranteed unique? */
-
- /* if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
- (*pinode)->i_ino =
- (unsigned long)pfindData->IndexNumber;
- } */ /*NB: ino incremented to unique num in new_inode*/
-
+ /* Is an i_ino of zero legal? Can we use that to check
+ if the server supports returning inode numbers? Are
+ there other sanity checks we can use to ensure that
+ the server is really filling in that field? */
+
+ /* We can not use the IndexNumber field by default from
+ Windows or Samba (in ALL_INFO buf) but we can request
+ it explicitly. It may not be unique presumably if
+ the server has multiple devices mounted under one
+ share */
+
+ /* There may be higher info levels that work but are
+ there Windows server or network appliances for which
+ IndexNumber field is not guaranteed unique? */
+
+#ifdef CONFIG_CIFS_EXPERIMENTAL
+ if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM){
+ int rc1 = 0;
+ __u64 inode_num;
+
+ rc1 = CIFSGetSrvInodeNumber(xid, pTcon,
+ search_path, &inode_num,
+ cifs_sb->local_nls);
+ if(rc1) {
+ cFYI(1,("GetSrvInodeNum rc %d", rc1));
+ /* BB EOPNOSUPP disable SERVER_INUM? */
+ } else /* do we need cast or hash to ino? */
+ (*pinode)->i_ino = inode_num;
+ } /* else ino incremented to unique num in new_inode*/
+#endif /* CIFS_EXPERIMENTAL */
insert_inode_hash(*pinode);
}
inode = *pinode;
@@ -275,10 +285,10 @@ cifs_get_inode_info(struct inode **pinode, const unsigned char *search_path,
cifsInfo->time = jiffies;
cFYI(1, (" New time %ld ", cifsInfo->time));
-/* blksize needs to be multiple of two. So safer to default to blksize
- and blkbits set in superblock so 2**blkbits and blksize will match */
-/* inode->i_blksize =
- (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/
+ /* blksize needs to be multiple of two. So safer to default to
+ blksize and blkbits set in superblock so 2**blkbits and blksize
+ will match rather than setting to:
+ (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/
/* Linux can not store file creation time unfortunately so we ignore it */
inode->i_atime =
@@ -287,56 +297,60 @@ cifs_get_inode_info(struct inode **pinode, const unsigned char *search_path,
cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime));
inode->i_ctime =
cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
- cFYI(0,
- (" Attributes came in as 0x%x ", attr));
+ cFYI(0, (" Attributes came in as 0x%x ", attr));
/* set default mode. will override for dirs below */
- if(atomic_read(&cifsInfo->inUse) == 0)
+ if (atomic_read(&cifsInfo->inUse) == 0)
/* new inode, can safely set these fields */
inode->i_mode = cifs_sb->mnt_file_mode;
/* if (attr & ATTR_REPARSE) */
-/* We no longer handle these as symlinks because we could not */
-/* follow them due to the absolute path with drive letter */
+ /* We no longer handle these as symlinks because we could not
+ follow them due to the absolute path with drive letter */
if (attr & ATTR_DIRECTORY) {
- /* override default perms since we do not do byte range locking on dirs */
+ /* override default perms since we do not do byte range locking
+ on dirs */
inode->i_mode = cifs_sb->mnt_dir_mode;
inode->i_mode |= S_IFDIR;
} else {
inode->i_mode |= S_IFREG;
- /* treat the dos attribute of read-only as read-only mode e.g. 555 */
- if(cifsInfo->cifsAttrs & ATTR_READONLY)
+ /* treat the dos attribute of read-only as read-only
+ mode e.g. 555 */
+ if (cifsInfo->cifsAttrs & ATTR_READONLY)
inode->i_mode &= ~(S_IWUGO);
- /* BB add code here - validate if device or weird share or device type? */
+ /* BB add code here -
+ validate if device or weird share or device type? */
}
- if(is_size_safe_to_change(cifsInfo)) {
- /* can not safely change the file size here if the
- client is writing to it due to potential races */
-
+ if (is_size_safe_to_change(cifsInfo)) {
+ /* can not safely change the file size here if the
+ client is writing to it due to potential races */
i_size_write(inode,le64_to_cpu(pfindData->EndOfFile));
- /* 512 bytes (2**9) is the fake blocksize that must be used */
- /* for this calculation */
- inode->i_blocks = (512 - 1 + le64_to_cpu(pfindData->AllocationSize))
- >> 9;
+ /* 512 bytes (2**9) is the fake blocksize that must be
+ used for this calculation */
+ inode->i_blocks = (512 - 1 + le64_to_cpu(
+ pfindData->AllocationSize)) >> 9;
}
inode->i_nlink = le32_to_cpu(pfindData->NumberOfLinks);
/* BB fill in uid and gid here? with help from winbind?
- or retrieve from NTFS stream extended attribute */
- if(atomic_read(&cifsInfo->inUse) == 0) {
+ or retrieve from NTFS stream extended attribute */
+ if (atomic_read(&cifsInfo->inUse) == 0) {
inode->i_uid = cifs_sb->mnt_uid;
inode->i_gid = cifs_sb->mnt_gid;
/* set so we do not keep refreshing these fields with
- bad data after user has changed them in memory */
+ bad data after user has changed them in memory */
atomic_set(&cifsInfo->inUse,1);
}
-
+
if (S_ISREG(inode->i_mode)) {
cFYI(1, (" File inode "));
inode->i_op = &cifs_file_inode_ops;
- inode->i_fop = &cifs_file_ops;
+ if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
+ inode->i_fop = &cifs_file_direct_ops;
+ else
+ inode->i_fop = &cifs_file_ops;
inode->i_data.a_ops = &cifs_addr_ops;
} else if (S_ISDIR(inode->i_mode)) {
cFYI(1, (" Directory inode "));
@@ -350,14 +364,13 @@ cifs_get_inode_info(struct inode **pinode, const unsigned char *search_path,
inode->i_rdev);
}
}
- if(buf)
- kfree(buf);
+ kfree(buf);
return rc;
}
-void
-cifs_read_inode(struct inode *inode)
-{ /* gets root inode */
+/* gets root inode */
+void cifs_read_inode(struct inode *inode)
+{
int xid;
struct cifs_sb_info *cifs_sb;
@@ -371,8 +384,7 @@ cifs_read_inode(struct inode *inode)
_FreeXid(xid);
}
-int
-cifs_unlink(struct inode *inode, struct dentry *direntry)
+int cifs_unlink(struct inode *inode, struct dentry *direntry)
{
int rc = 0;
int xid;
@@ -380,7 +392,7 @@ cifs_unlink(struct inode *inode, struct dentry *direntry)
struct cifsTconInfo *pTcon;
char *full_path = NULL;
struct cifsInodeInfo *cifsInode;
- FILE_BASIC_INFO * pinfo_buf;
+ FILE_BASIC_INFO *pinfo_buf;
cFYI(1, (" cifs_unlink, inode = 0x%p with ", inode));
@@ -389,12 +401,12 @@ cifs_unlink(struct inode *inode, struct dentry *direntry)
cifs_sb = CIFS_SB(inode->i_sb);
pTcon = cifs_sb->tcon;
-/* Unlink can be called from rename so we can not grab
- the sem here since we deadlock otherwise */
+ /* Unlink can be called from rename so we can not grab the sem here
+ since we deadlock otherwise */
/* down(&direntry->d_sb->s_vfs_rename_sem);*/
full_path = build_path_from_dentry(direntry);
/* up(&direntry->d_sb->s_vfs_rename_sem);*/
- if(full_path == NULL) {
+ if (full_path == NULL) {
FreeXid(xid);
return -ENOMEM;
}
@@ -408,39 +420,76 @@ cifs_unlink(struct inode *inode, struct dentry *direntry)
int oplock = FALSE;
__u16 netfid;
- rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, DELETE,
- CREATE_NOT_DIR | CREATE_DELETE_ON_CLOSE,
- &netfid, &oplock, NULL, cifs_sb->local_nls);
- if(rc==0) {
- CIFSSMBRenameOpenFile(xid,pTcon,netfid,
- NULL, cifs_sb->local_nls);
+ rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, DELETE,
+ CREATE_NOT_DIR | CREATE_DELETE_ON_CLOSE,
+ &netfid, &oplock, NULL, cifs_sb->local_nls);
+ if (rc==0) {
+ CIFSSMBRenameOpenFile(xid, pTcon, netfid, NULL,
+ cifs_sb->local_nls);
CIFSSMBClose(xid, pTcon, netfid);
direntry->d_inode->i_nlink--;
}
} else if (rc == -EACCES) {
/* try only if r/o attribute set in local lookup data? */
- pinfo_buf = (FILE_BASIC_INFO *)kmalloc(sizeof(FILE_BASIC_INFO),GFP_KERNEL);
- if(pinfo_buf) {
- memset(pinfo_buf,0,sizeof(FILE_BASIC_INFO));
- /* ATTRS set to normal clears r/o bit */
+ pinfo_buf = kmalloc(sizeof(FILE_BASIC_INFO), GFP_KERNEL);
+ if (pinfo_buf) {
+ memset(pinfo_buf, 0, sizeof(FILE_BASIC_INFO));
+ /* ATTRS set to normal clears r/o bit */
pinfo_buf->Attributes = cpu_to_le32(ATTR_NORMAL);
- rc = CIFSSMBSetTimes(xid, pTcon, full_path, pinfo_buf,
- cifs_sb->local_nls);
+ if (!(pTcon->ses->flags & CIFS_SES_NT4))
+ rc = CIFSSMBSetTimes(xid, pTcon, full_path,
+ pinfo_buf,
+ cifs_sb->local_nls);
+ else
+ rc = -EOPNOTSUPP;
+
+ if (rc == -EOPNOTSUPP) {
+ int oplock = FALSE;
+ __u16 netfid;
+ /* rc = CIFSSMBSetAttrLegacy(xid, pTcon,
+ full_path,
+ (__u16)ATTR_NORMAL,
+ cifs_sb->local_nls);
+ For some strange reason it seems that NT4 eats the
+ old setattr call without actually setting the
+ attributes so on to the third attempted workaround
+ */
+
+ /* BB could scan to see if we already have it open
+ and pass in pid of opener to function */
+ rc = CIFSSMBOpen(xid, pTcon, full_path,
+ FILE_OPEN, SYNCHRONIZE |
+ FILE_WRITE_ATTRIBUTES, 0,
+ &netfid, &oplock, NULL,
+ cifs_sb->local_nls);
+ if (rc==0) {
+ rc = CIFSSMBSetFileTimes(xid, pTcon,
+ pinfo_buf,
+ netfid);
+ CIFSSMBClose(xid, pTcon, netfid);
+ }
+ }
kfree(pinfo_buf);
}
- if(rc==0) {
- rc = CIFSSMBDelFile(xid, pTcon, full_path, cifs_sb->local_nls);
+ if (rc==0) {
+ rc = CIFSSMBDelFile(xid, pTcon, full_path,
+ cifs_sb->local_nls);
if (!rc) {
direntry->d_inode->i_nlink--;
} else if (rc == -ETXTBSY) {
int oplock = FALSE;
__u16 netfid;
- rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, DELETE,
- CREATE_NOT_DIR | CREATE_DELETE_ON_CLOSE,
- &netfid, &oplock, NULL, cifs_sb->local_nls);
- if(rc==0) {
- CIFSSMBRenameOpenFile(xid,pTcon,netfid,NULL,cifs_sb->local_nls);
+ rc = CIFSSMBOpen(xid, pTcon, full_path,
+ FILE_OPEN, DELETE,
+ CREATE_NOT_DIR |
+ CREATE_DELETE_ON_CLOSE,
+ &netfid, &oplock, NULL,
+ cifs_sb->local_nls);
+ if (rc==0) {
+ CIFSSMBRenameOpenFile(xid, pTcon,
+ netfid, NULL,
+ cifs_sb->local_nls);
CIFSSMBClose(xid, pTcon, netfid);
direntry->d_inode->i_nlink--;
}
@@ -449,20 +498,19 @@ cifs_unlink(struct inode *inode, struct dentry *direntry)
}
}
cifsInode = CIFS_I(direntry->d_inode);
- cifsInode->time = 0; /* will force revalidate to get info when needed */
+ cifsInode->time = 0; /* will force revalidate to get info when
+ needed */
direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime =
- current_fs_time(inode->i_sb);
+ current_fs_time(inode->i_sb);
cifsInode = CIFS_I(inode);
cifsInode->time = 0; /* force revalidate of dir as well */
- if (full_path)
- kfree(full_path);
+ kfree(full_path);
FreeXid(xid);
return rc;
}
-int
-cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
+int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
{
int rc = 0;
int xid;
@@ -481,7 +529,7 @@ cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
down(&inode->i_sb->s_vfs_rename_sem);
full_path = build_path_from_dentry(direntry);
up(&inode->i_sb->s_vfs_rename_sem);
- if(full_path == NULL) {
+ if (full_path == NULL) {
FreeXid(xid);
return -ENOMEM;
}
@@ -496,40 +544,39 @@ cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
rc = cifs_get_inode_info_unix(&newinode, full_path,
inode->i_sb,xid);
else
- rc = cifs_get_inode_info(&newinode, full_path,NULL,
+ rc = cifs_get_inode_info(&newinode, full_path, NULL,
inode->i_sb,xid);
direntry->d_op = &cifs_dentry_ops;
d_instantiate(direntry, newinode);
- if(direntry->d_inode)
+ if (direntry->d_inode)
direntry->d_inode->i_nlink = 2;
if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
- CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
- (__u64)current->euid,
- (__u64)current->egid,
- 0 /* dev_t */,
- cifs_sb->local_nls);
+ CIFSSMBUnixSetPerms(xid, pTcon, full_path,
+ mode,
+ (__u64)current->euid,
+ (__u64)current->egid,
+ 0 /* dev_t */,
+ cifs_sb->local_nls);
} else {
- CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
- (__u64)-1,
- (__u64)-1,
- 0 /* dev_t */,
- cifs_sb->local_nls);
+ CIFSSMBUnixSetPerms(xid, pTcon, full_path,
+ mode, (__u64)-1,
+ (__u64)-1, 0 /* dev_t */,
+ cifs_sb->local_nls);
}
- else { /* BB to be implemented via Windows secrty descriptors*/
- /* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/
+ else {
+ /* BB to be implemented via Windows secrty descriptors
+ eg CIFSSMBWinSetPerms(xid, pTcon, full_path, mode,
+ -1, -1, local_nls); */
}
}
- if (full_path)
- kfree(full_path);
+ kfree(full_path);
FreeXid(xid);
-
return rc;
}
-int
-cifs_rmdir(struct inode *inode, struct dentry *direntry)
+int cifs_rmdir(struct inode *inode, struct dentry *direntry)
{
int rc = 0;
int xid;
@@ -548,7 +595,7 @@ cifs_rmdir(struct inode *inode, struct dentry *direntry)
down(&inode->i_sb->s_vfs_rename_sem);
full_path = build_path_from_dentry(direntry);
up(&inode->i_sb->s_vfs_rename_sem);
- if(full_path == NULL) {
+ if (full_path == NULL) {
FreeXid(xid);
return -ENOMEM;
}
@@ -562,19 +609,18 @@ cifs_rmdir(struct inode *inode, struct dentry *direntry)
}
cifsInode = CIFS_I(direntry->d_inode);
- cifsInode->time = 0; /* force revalidate to go get info when needed */
+ cifsInode->time = 0; /* force revalidate to go get info when
+ needed */
direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime =
- current_fs_time(inode->i_sb);
+ current_fs_time(inode->i_sb);
- if (full_path)
- kfree(full_path);
+ kfree(full_path);
FreeXid(xid);
return rc;
}
-int
-cifs_rename(struct inode *source_inode, struct dentry *source_direntry,
- struct inode *target_inode, struct dentry *target_direntry)
+int cifs_rename(struct inode *source_inode, struct dentry *source_direntry,
+ struct inode *target_inode, struct dentry *target_direntry)
{
char *fromName;
char *toName;
@@ -591,83 +637,90 @@ cifs_rename(struct inode *source_inode, struct dentry *source_direntry,
pTcon = cifs_sb_source->tcon;
if (pTcon != cifs_sb_target->tcon) {
- FreeXid(xid);
- return -EXDEV; /* BB actually could be allowed if same server, but
- different share. Might eventually add support for this */
+ FreeXid(xid);
+ return -EXDEV; /* BB actually could be allowed if same server,
+ but different share.
+ Might eventually add support for this */
}
- /* we already have the rename sem so we do not need
- to grab it again here to protect the path integrity */
+ /* we already have the rename sem so we do not need to grab it again
+ here to protect the path integrity */
fromName = build_path_from_dentry(source_direntry);
toName = build_path_from_dentry(target_direntry);
- if((fromName == NULL) || (toName == NULL)) {
+ if ((fromName == NULL) || (toName == NULL)) {
rc = -ENOMEM;
goto cifs_rename_exit;
}
rc = CIFSSMBRename(xid, pTcon, fromName, toName,
cifs_sb_source->local_nls);
- if(rc == -EEXIST) {
- /* check if they are the same file
- because rename of hardlinked files is a noop */
- FILE_UNIX_BASIC_INFO * info_buf_source;
- FILE_UNIX_BASIC_INFO * info_buf_target;
-
- info_buf_source =
- kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO),GFP_KERNEL);
- if(info_buf_source != NULL) {
- info_buf_target = info_buf_source+1;
- rc = CIFSSMBUnixQPathInfo(xid, pTcon, fromName,
+ if (rc == -EEXIST) {
+ /* check if they are the same file because rename of hardlinked
+ files is a noop */
+ FILE_UNIX_BASIC_INFO *info_buf_source;
+ FILE_UNIX_BASIC_INFO *info_buf_target;
+
+ info_buf_source =
+ kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
+ if (info_buf_source != NULL) {
+ info_buf_target = info_buf_source + 1;
+ rc = CIFSSMBUnixQPathInfo(xid, pTcon, fromName,
info_buf_source, cifs_sb_source->local_nls);
- if(rc == 0) {
- rc = CIFSSMBUnixQPathInfo(xid,pTcon,toName,
+ if (rc == 0) {
+ rc = CIFSSMBUnixQPathInfo(xid, pTcon, toName,
info_buf_target,
cifs_sb_target->local_nls);
}
- if((rc == 0) &&
- (info_buf_source->UniqueId ==
- info_buf_target->UniqueId)) {
- /* do not rename since the files are hardlinked
- which is a noop */
+ if ((rc == 0) &&
+ (info_buf_source->UniqueId ==
+ info_buf_target->UniqueId)) {
+ /* do not rename since the files are hardlinked which
+ is a noop */
} else {
/* we either can not tell the files are hardlinked
- (as with Windows servers) or files are not hardlinked
- so delete the target manually before renaming to
- follow POSIX rather than Windows semantics */
+ (as with Windows servers) or files are not
+ hardlinked so delete the target manually before
+ renaming to follow POSIX rather than Windows
+ semantics */
cifs_unlink(target_inode, target_direntry);
- rc = CIFSSMBRename(xid, pTcon, fromName, toName,
- cifs_sb_source->local_nls);
+ rc = CIFSSMBRename(xid, pTcon, fromName,
+ toName,
+ cifs_sb_source->local_nls);
}
kfree(info_buf_source);
} /* if we can not get memory just leave rc as EEXIST */
}
- if((rc == -EIO)||(rc == -EEXIST)) {
+ if (rc) {
+ cFYI(1, ("rename rc %d", rc));
+ }
+
+ if ((rc == -EIO) || (rc == -EEXIST)) {
int oplock = FALSE;
__u16 netfid;
+ /* BB FIXME Is Generic Read correct for rename? */
+ /* if renaming directory - we should not say CREATE_NOT_DIR,
+ need to test renaming open directory, also GENERIC_READ
+ might not right be right access to request */
rc = CIFSSMBOpen(xid, pTcon, fromName, FILE_OPEN, GENERIC_READ,
- CREATE_NOT_DIR,
- &netfid, &oplock, NULL, cifs_sb_source->local_nls);
- if(rc==0) {
- CIFSSMBRenameOpenFile(xid,pTcon,netfid,
- toName, cifs_sb_source->local_nls);
+ CREATE_NOT_DIR, &netfid, &oplock, NULL,
+ cifs_sb_source->local_nls);
+ if (rc==0) {
+ CIFSSMBRenameOpenFile(xid, pTcon, netfid, toName,
+ cifs_sb_source->local_nls);
CIFSSMBClose(xid, pTcon, netfid);
}
}
cifs_rename_exit:
- if (fromName)
- kfree(fromName);
- if (toName)
- kfree(toName);
-
+ kfree(fromName);
+ kfree(toName);
FreeXid(xid);
return rc;
}
-int
-cifs_revalidate(struct dentry *direntry)
+int cifs_revalidate(struct dentry *direntry)
{
int xid;
int rc = 0;
@@ -678,118 +731,120 @@ cifs_revalidate(struct dentry *direntry)
struct timespec local_mtime;
int invalidate_inode = FALSE;
- if(direntry->d_inode == NULL)
+ if (direntry->d_inode == NULL)
return -ENOENT;
cifsInode = CIFS_I(direntry->d_inode);
- if(cifsInode == NULL)
+ if (cifsInode == NULL)
return -ENOENT;
/* no sense revalidating inode info on file that no one can write */
- if(CIFS_I(direntry->d_inode)->clientCanCacheRead)
+ if (CIFS_I(direntry->d_inode)->clientCanCacheRead)
return rc;
xid = GetXid();
cifs_sb = CIFS_SB(direntry->d_sb);
- /* can not safely grab the rename sem here if
- rename calls revalidate since that would deadlock */
+ /* can not safely grab the rename sem here if rename calls revalidate
+ since that would deadlock */
full_path = build_path_from_dentry(direntry);
- if(full_path == NULL) {
+ if (full_path == NULL) {
FreeXid(xid);
return -ENOMEM;
}
- cFYI(1,
- ("Revalidate: %s inode 0x%p count %d dentry: 0x%p d_time %ld jiffies %ld",
- full_path, direntry->d_inode,
- direntry->d_inode->i_count.counter, direntry,
- direntry->d_time, jiffies));
+ cFYI(1, ("Revalidate: %s inode 0x%p count %d dentry: 0x%p d_time %ld "
+ "jiffies %ld", full_path, direntry->d_inode,
+ direntry->d_inode->i_count.counter, direntry,
+ direntry->d_time, jiffies));
- if (cifsInode->time == 0){
+ if (cifsInode->time == 0) {
/* was set to zero previously to force revalidate */
- } else if (time_before(jiffies, cifsInode->time + HZ) && lookupCacheEnabled) {
- if((S_ISREG(direntry->d_inode->i_mode) == 0) ||
- (direntry->d_inode->i_nlink == 1)) {
- if (full_path)
- kfree(full_path);
+ } else if (time_before(jiffies, cifsInode->time + HZ) &&
+ lookupCacheEnabled) {
+ if ((S_ISREG(direntry->d_inode->i_mode) == 0) ||
+ (direntry->d_inode->i_nlink == 1)) {
+ kfree(full_path);
FreeXid(xid);
return rc;
} else {
- cFYI(1,("Have to revalidate file due to hardlinks"));
- }
+ cFYI(1, ("Have to revalidate file due to hardlinks"));
+ }
}
-
+
/* save mtime and size */
local_mtime = direntry->d_inode->i_mtime;
- local_size = direntry->d_inode->i_size;
+ local_size = direntry->d_inode->i_size;
if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) {
rc = cifs_get_inode_info_unix(&direntry->d_inode, full_path,
- direntry->d_sb,xid);
- if(rc) {
- cFYI(1,("error on getting revalidate info %d",rc));
-/* if(rc != -ENOENT)
- rc = 0; */ /* BB should we cache info on certain errors? */
+ direntry->d_sb,xid);
+ if (rc) {
+ cFYI(1, ("error on getting revalidate info %d", rc));
+/* if (rc != -ENOENT)
+ rc = 0; */ /* BB should we cache info on
+ certain errors? */
}
} else {
rc = cifs_get_inode_info(&direntry->d_inode, full_path, NULL,
- direntry->d_sb,xid);
- if(rc) {
- cFYI(1,("error on getting revalidate info %d",rc));
-/* if(rc != -ENOENT)
- rc = 0; */ /* BB should we cache info on certain errors? */
+ direntry->d_sb,xid);
+ if (rc) {
+ cFYI(1, ("error on getting revalidate info %d", rc));
+/* if (rc != -ENOENT)
+ rc = 0; */ /* BB should we cache info on
+ certain errors? */
}
}
/* should we remap certain errors, access denied?, to zero */
- /* if not oplocked, we invalidate inode pages if mtime
- or file size had changed on server */
+ /* if not oplocked, we invalidate inode pages if mtime or file size
+ had changed on server */
- if(timespec_equal(&local_mtime,&direntry->d_inode->i_mtime) &&
- (local_size == direntry->d_inode->i_size)) {
- cFYI(1,("cifs_revalidate - inode unchanged"));
+ if (timespec_equal(&local_mtime,&direntry->d_inode->i_mtime) &&
+ (local_size == direntry->d_inode->i_size)) {
+ cFYI(1, ("cifs_revalidate - inode unchanged"));
} else {
/* file may have changed on server */
- if(cifsInode->clientCanCacheRead) {
- /* no need to invalidate inode pages since we were
- the only ones who could have modified the file and
- the server copy is staler than ours */
+ if (cifsInode->clientCanCacheRead) {
+ /* no need to invalidate inode pages since we were the
+ only ones who could have modified the file and the
+ server copy is staler than ours */
} else {
invalidate_inode = TRUE;
}
}
- /* 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 */
+ /* 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);*/
/* need to write out dirty pages here */
- if(direntry->d_inode->i_mapping) {
- /* do we need to lock inode until after invalidate completes below? */
+ if (direntry->d_inode->i_mapping) {
+ /* do we need to lock inode until after invalidate completes
+ below? */
filemap_fdatawrite(direntry->d_inode->i_mapping);
}
- if(invalidate_inode) {
- filemap_fdatawait(direntry->d_inode->i_mapping);
+ if (invalidate_inode) {
+ if (direntry->d_inode->i_mapping)
+ filemap_fdatawait(direntry->d_inode->i_mapping);
/* may eventually have to do this for open files too */
- if(list_empty(&(cifsInode->openFileList))) {
+ if (list_empty(&(cifsInode->openFileList))) {
/* Has changed on server - flush read ahead pages */
- cFYI(1,("Invalidating read ahead data on closed file"));
+ cFYI(1, ("Invalidating read ahead data on "
+ "closed file"));
invalidate_remote_inode(direntry->d_inode);
}
}
-/* up(&direntry->d_inode->i_sem);*/
+/* up(&direntry->d_inode->i_sem); */
- if (full_path)
- kfree(full_path);
+ kfree(full_path);
FreeXid(xid);
-
return rc;
}
-int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
+int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry,
+ struct kstat *stat)
{
int err = cifs_revalidate(dentry);
if (!err)
@@ -800,7 +855,7 @@ int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat
static int cifs_truncate_page(struct address_space *mapping, loff_t from)
{
pgoff_t index = from >> PAGE_CACHE_SHIFT;
- unsigned offset = from & (PAGE_CACHE_SIZE-1);
+ unsigned offset = from & (PAGE_CACHE_SIZE - 1);
struct page *page;
char *kaddr;
int rc = 0;
@@ -818,8 +873,7 @@ static int cifs_truncate_page(struct address_space *mapping, loff_t from)
return rc;
}
-int
-cifs_setattr(struct dentry *direntry, struct iattr *attrs)
+int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
{
int xid;
struct cifs_sb_info *cifs_sb;
@@ -834,20 +888,19 @@ cifs_setattr(struct dentry *direntry, struct iattr *attrs)
__u64 uid = 0xFFFFFFFFFFFFFFFFULL;
__u64 gid = 0xFFFFFFFFFFFFFFFFULL;
struct cifsInodeInfo *cifsInode;
- struct list_head * tmp;
+ struct list_head *tmp;
xid = GetXid();
- cFYI(1,
- (" In cifs_setattr, name = %s attrs->iavalid 0x%x ",
- direntry->d_name.name, attrs->ia_valid));
+ cFYI(1, (" In cifs_setattr, name = %s attrs->iavalid 0x%x ",
+ direntry->d_name.name, attrs->ia_valid));
cifs_sb = CIFS_SB(direntry->d_inode->i_sb);
pTcon = cifs_sb->tcon;
down(&direntry->d_sb->s_vfs_rename_sem);
full_path = build_path_from_dentry(direntry);
up(&direntry->d_sb->s_vfs_rename_sem);
- if(full_path == NULL) {
+ if (full_path == NULL) {
FreeXid(xid);
return -ENOMEM;
}
@@ -856,73 +909,84 @@ 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_fdatawrite(direntry->d_inode->i_mapping);
filemap_fdatawait(direntry->d_inode->i_mapping);
if (attrs->ia_valid & ATTR_SIZE) {
- read_lock(&GlobalSMBSeslock);
- /* To avoid spurious oplock breaks from server, in the case
- of inodes that we already have open, avoid doing path
- based setting of file size if we can do it by handle.
- This keeps our caching token (oplock) and avoids
- timeouts when the local oplock break takes longer to flush
- writebehind data than the SMB timeout for the SetPathInfo
- request would allow */
- list_for_each(tmp, &cifsInode->openFileList) {
- open_file = list_entry(tmp,struct cifsFileInfo, flist);
+ read_lock(&GlobalSMBSeslock);
+ /* To avoid spurious oplock breaks from server, in the case of
+ inodes that we already have open, avoid doing path based
+ setting of file size if we can do it by handle.
+ This keeps our caching token (oplock) and avoids timeouts
+ when the local oplock break takes longer to flush
+ writebehind data than the SMB timeout for the SetPathInfo
+ request would allow */
+ list_for_each(tmp, &cifsInode->openFileList) {
+ open_file = list_entry(tmp, struct cifsFileInfo,
+ flist);
/* We check if file is open for writing first */
- if((open_file->pfile) &&
- ((open_file->pfile->f_flags & O_RDWR) ||
- (open_file->pfile->f_flags & O_WRONLY))) {
- if(open_file->invalidHandle == FALSE) {
- /* we found a valid, writeable network file
- handle to use to try to set the file size */
+ if ((open_file->pfile) &&
+ ((open_file->pfile->f_flags & O_RDWR) ||
+ (open_file->pfile->f_flags & O_WRONLY))) {
+ if (open_file->invalidHandle == FALSE) {
+ /* we found a valid, writeable network
+ file handle to use to try to set the
+ file size */
__u16 nfid = open_file->netfid;
__u32 npid = open_file->pid;
read_unlock(&GlobalSMBSeslock);
found = TRUE;
- rc = CIFSSMBSetFileSize(xid, pTcon, attrs->ia_size,
- nfid,npid,FALSE);
- cFYI(1,("SetFileSize by handle (setattrs) rc = %d",rc));
- /* Do not need reopen and retry on EAGAIN since we will
- retry by pathname below */
-
- break; /* now that we found one valid file handle no
- sense continuing to loop trying others */
+ rc = CIFSSMBSetFileSize(xid, pTcon,
+ attrs->ia_size, nfid, npid,
+ FALSE);
+ cFYI(1, ("SetFileSize by handle "
+ "(setattrs) rc = %d", rc));
+ /* Do not need reopen and retry on
+ EAGAIN since we will retry by
+ pathname below */
+
+ /* now that we found one valid file
+ handle no sense continuing to loop
+ trying others, so break here */
+ break;
}
}
}
- if(found == FALSE) {
+ if (found == FALSE)
read_unlock(&GlobalSMBSeslock);
- }
-
- if(rc != 0) {
- /* Set file size by pathname rather than by handle either
- because no valid, writeable file handle for it was found or
- because there was an error setting it by handle */
- rc = CIFSSMBSetEOF(xid, pTcon, full_path, attrs->ia_size,FALSE,
- cifs_sb->local_nls);
- cFYI(1,(" SetEOF by path (setattrs) rc = %d",rc));
+ if (rc != 0) {
+ /* Set file size by pathname rather than by handle
+ either because no valid, writeable file handle for
+ it was found or because there was an error setting
+ it by handle */
+ rc = CIFSSMBSetEOF(xid, pTcon, full_path,
+ attrs->ia_size, FALSE,
+ cifs_sb->local_nls);
+ cFYI(1, (" SetEOF by path (setattrs) rc = %d", rc));
}
-
- /* Server is ok setting allocation size implicitly - no need to call: */
- /*CIFSSMBSetEOF(xid, pTcon, full_path, attrs->ia_size, TRUE, cifs_sb->local_nls);*/
+
+ /* Server is ok setting allocation size implicitly - no need
+ to call:
+ CIFSSMBSetEOF(xid, pTcon, full_path, attrs->ia_size, TRUE,
+ cifs_sb->local_nls);
+ */
if (rc == 0) {
rc = vmtruncate(direntry->d_inode, attrs->ia_size);
- cifs_truncate_page(direntry->d_inode->i_mapping, direntry->d_inode->i_size);
+ cifs_truncate_page(direntry->d_inode->i_mapping,
+ direntry->d_inode->i_size);
}
}
if (attrs->ia_valid & ATTR_UID) {
cFYI(1, (" CIFS - UID changed to %d", attrs->ia_uid));
uid = attrs->ia_uid;
- /* entry->uid = cpu_to_le16(attr->ia_uid); */
+ /* entry->uid = cpu_to_le16(attr->ia_uid); */
}
if (attrs->ia_valid & ATTR_GID) {
cFYI(1, (" CIFS - GID changed to %d", attrs->ia_gid));
gid = attrs->ia_gid;
- /* entry->gid = cpu_to_le16(attr->ia_gid); */
+ /* entry->gid = cpu_to_le16(attr->ia_gid); */
}
time_buf.Attributes = 0;
@@ -935,19 +999,23 @@ cifs_setattr(struct dentry *direntry, struct iattr *attrs)
if ((cifs_sb->tcon->ses->capabilities & CAP_UNIX)
&& (attrs->ia_valid & (ATTR_MODE | ATTR_GID | ATTR_UID)))
rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, uid, gid,
- 0 /* dev_t */, cifs_sb->local_nls);
+ 0 /* dev_t */, cifs_sb->local_nls);
else if (attrs->ia_valid & ATTR_MODE) {
- if((mode & S_IWUGO) == 0) /* not writeable */ {
- if((cifsInode->cifsAttrs & ATTR_READONLY) == 0)
- time_buf.Attributes =
- cpu_to_le32(cifsInode->cifsAttrs | ATTR_READONLY);
- } else if((mode & S_IWUGO) == S_IWUGO) {
- if(cifsInode->cifsAttrs & ATTR_READONLY)
- time_buf.Attributes =
- cpu_to_le32(cifsInode->cifsAttrs & (~ATTR_READONLY));
+ if ((mode & S_IWUGO) == 0) /* not writeable */ {
+ if ((cifsInode->cifsAttrs & ATTR_READONLY) == 0)
+ time_buf.Attributes =
+ cpu_to_le32(cifsInode->cifsAttrs |
+ ATTR_READONLY);
+ } else if ((mode & S_IWUGO) == S_IWUGO) {
+ if (cifsInode->cifsAttrs & ATTR_READONLY)
+ time_buf.Attributes =
+ cpu_to_le32(cifsInode->cifsAttrs &
+ (~ATTR_READONLY));
}
- /* BB to be implemented - via Windows security descriptors or streams */
- /* CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,uid,gid,cifs_sb->local_nls);*/
+ /* BB to be implemented -
+ via Windows security descriptors or streams */
+ /* CIFSSMBWinSetPerms(xid, pTcon, full_path, mode, uid, gid,
+ cifs_sb->local_nls); */
}
if (attrs->ia_valid & ATTR_ATIME) {
@@ -966,45 +1034,63 @@ cifs_setattr(struct dentry *direntry, struct iattr *attrs)
if (attrs->ia_valid & ATTR_CTIME) {
set_time = TRUE;
- cFYI(1, (" CIFS - CTIME changed ")); /* BB probably do not need */
+ cFYI(1, (" CIFS - CTIME changed ")); /* BB probably no need */
time_buf.ChangeTime =
cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime));
} else
time_buf.ChangeTime = 0;
if (set_time || time_buf.Attributes) {
- /* BB what if setting one attribute fails
- (such as size) but time setting works */
+ /* BB what if setting one attribute fails (such as size) but
+ time setting works? */
time_buf.CreationTime = 0; /* do not change */
/* In the future we should experiment - try setting timestamps
- via Handle (SetFileInfo) instead of by path */
- rc = CIFSSMBSetTimes(xid, pTcon, full_path, &time_buf,
- cifs_sb->local_nls);
- if(rc == -EOPNOTSUPP) {
- cFYI(1,("OS2 level of SetPathInfo not implemented"));
- /* Need to convert time_buf into old format,
- but probably better to do that inside the function
- below rather than here */
- /* Better to return EOPNOTSUPP until function
- below is ready */
- /* CIFSSMBSetTimesLegacy(xid, pTcon, full_path,
- FILE_INFO_STANDARD * data, cifs_sb->local_nls); */
+ via Handle (SetFileInfo) instead of by path */
+ if (!(pTcon->ses->flags & CIFS_SES_NT4))
+ rc = CIFSSMBSetTimes(xid, pTcon, full_path, &time_buf,
+ cifs_sb->local_nls);
+ else
+ rc = -EOPNOTSUPP;
+
+ if (rc == -EOPNOTSUPP) {
+ int oplock = FALSE;
+ __u16 netfid;
+
+ cFYI(1, ("calling SetFileInfo since SetPathInfo for "
+ "times not supported by this server"));
+ /* BB we could scan to see if we already have it open
+ and pass in pid of opener to function */
+ rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN,
+ SYNCHRONIZE | FILE_WRITE_ATTRIBUTES,
+ CREATE_NOT_DIR, &netfid, &oplock,
+ NULL, cifs_sb->local_nls);
+ if (rc==0) {
+ rc = CIFSSMBSetFileTimes(xid, pTcon, &time_buf,
+ netfid);
+ CIFSSMBClose(xid, pTcon, netfid);
+ } else {
+ /* BB For even older servers we could convert time_buf
+ into old DOS style which uses two second
+ granularity */
+
+ /* rc = CIFSSMBSetTimesLegacy(xid, pTcon, full_path,
+ &time_buf, cifs_sb->local_nls); */
+ }
}
}
- /* do not need local check to inode_check_ok since the server does that */
+ /* do not need local check to inode_check_ok since the server does
+ that */
if (!rc)
rc = inode_setattr(direntry->d_inode, attrs);
- if (full_path)
- kfree(full_path);
+ kfree(full_path);
FreeXid(xid);
return rc;
}
-void
-cifs_delete_inode(struct inode *inode)
+void cifs_delete_inode(struct inode *inode)
{
cFYI(1, ("In cifs_delete_inode, inode = 0x%p ", inode));
/* may have to add back in if and when safe distributed caching of
- directories added e.g. via FindNotify */
+ directories added e.g. via FindNotify */
}
diff --git a/fs/cifs/ioctl.c b/fs/cifs/ioctl.c
new file mode 100644
index 0000000000000..b4b8e201d428d
--- /dev/null
+++ b/fs/cifs/ioctl.c
@@ -0,0 +1,49 @@
+/*
+ * fs/cifs/ioctl.c
+ *
+ * vfs operations that deal with io control
+ *
+ * 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
+ */
+#include <linux/fs.h>
+#include <linux/ext2_fs.h>
+#include "cifspdu.h"
+#include "cifsglob.h"
+#include "cifsproto.h"
+#include "cifs_debug.h"
+
+int cifs_ioctl (struct inode * inode, struct file * filep,
+ unsigned int command, unsigned long arg)
+{
+ int rc = -ENOTTY; /* strange error - but the precedent */
+#ifdef CONFIG_CIFS_POSIX
+ cFYI(1,("ioctl file %p cmd %u arg %lu",filep,command,arg));
+ switch(command) {
+ case EXT2_IOC_GETFLAGS:
+ cFYI(1,("get flags not implemented yet"));
+ return -EOPNOTSUPP;
+ case EXT2_IOC_SETFLAGS:
+ cFYI(1,("set flags not implemented yet"));
+ return -EOPNOTSUPP;
+ default:
+ cFYI(1,("unsupported ioctl"));
+ return rc;
+ }
+#endif /* CONFIG_CIFS_POSIX */
+ return rc;
+}
diff --git a/fs/cifs/md4.c b/fs/cifs/md4.c
index 1edbe22c953b7..46d62c9dda0fa 100644
--- a/fs/cifs/md4.c
+++ b/fs/cifs/md4.c
@@ -21,6 +21,8 @@
*/
#include <linux/module.h>
#include <linux/fs.h>
+#include "cifsencrypt.h"
+
/* NOTE: This code makes no attempt to be fast! */
static __u32
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index c79d8f707771c..7b38d3059a83d 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -33,7 +33,7 @@ extern mempool_t *cifs_sm_req_poolp;
extern mempool_t *cifs_req_poolp;
extern struct task_struct * oplockThread;
-__u16 GlobalMid; /* multiplex id - rotating counter */
+static __u16 GlobalMid; /* multiplex id - rotating counter */
/* The xid serves as a useful identifier for each incoming vfs request,
in a similar way to the mid which is useful to track each sent smb,
@@ -353,10 +353,14 @@ checkSMB(struct smb_hdr *smb, __u16 mid, int length)
if (((unsigned int)length < 2 + sizeof (struct smb_hdr)) ||
(len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)) {
if ((unsigned int)length < 2 + sizeof (struct smb_hdr)) {
- cERROR(1, ("Length less than 2 + sizeof smb_hdr "));
- if (((unsigned int)length >= sizeof (struct smb_hdr) - 1)
- && (smb->Status.CifsError != 0))
+ if (((unsigned int)length >=
+ sizeof (struct smb_hdr) - 1)
+ && (smb->Status.CifsError != 0)) {
+ smb->WordCount = 0;
return 0; /* some error cases do not return wct and bcc */
+ } else {
+ cERROR(1, ("Length less than smb header size"));
+ }
}
if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c
index b1f5248363e93..4e34c89cec5dc 100644
--- a/fs/cifs/netmisc.c
+++ b/fs/cifs/netmisc.c
@@ -43,7 +43,7 @@ struct smb_to_posix_error {
int posix_code;
};
-const struct smb_to_posix_error mapping_table_ERRDOS[] = {
+static const struct smb_to_posix_error mapping_table_ERRDOS[] = {
{ERRbadfunc, -EINVAL},
{ERRbadfile, -ENOENT},
{ERRbadpath, -ENOTDIR},
@@ -81,7 +81,7 @@ const struct smb_to_posix_error mapping_table_ERRDOS[] = {
{0, 0}
};
-const struct smb_to_posix_error mapping_table_ERRSRV[] = {
+static const struct smb_to_posix_error mapping_table_ERRSRV[] = {
{ERRerror, -EIO},
{ERRbadpw, -EPERM},
{ERRbadtype, -EREMOTE},
@@ -120,7 +120,7 @@ const struct smb_to_posix_error mapping_table_ERRSRV[] = {
{0, 0}
};
-const struct smb_to_posix_error mapping_table_ERRHRD[] = {
+static const struct smb_to_posix_error mapping_table_ERRHRD[] = {
{0, 0}
};
diff --git a/fs/cifs/ntlmssp.h b/fs/cifs/ntlmssp.h
index 5b15cee2ca2ab..6facb41117a3e 100644
--- a/fs/cifs/ntlmssp.h
+++ b/fs/cifs/ntlmssp.h
@@ -35,7 +35,7 @@
#define NTLMSSP_NEGOTIATE_SIGN 0x0010 // Request signature capability
#define NTLMSSP_NEGOTIATE_SEAL 0x0020 // Request confidentiality
#define NTLMSSP_NEGOTIATE_DGRAM 0x0040
-#define NTLMSSP_NEGOTIATE_LM_KEY 0x0080 // Use LM session key for sign/seal
+#define NTLMSSP_NEGOTIATE_LM_KEY 0x0080 // Use LM session key for sign/seal
#define NTLMSSP_NEGOTIATE_NTLM 0x0200 // NTLM authentication
#define NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED 0x1000
#define NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED 0x2000
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index 0fe23d2efd1bd..f8bea395ec9e2 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -29,31 +29,15 @@
#include "cifs_unicode.h"
#include "cifs_debug.h"
#include "cifs_fs_sb.h"
-
-extern int CIFSFindFirst2(const int xid, struct cifsTconInfo *tcon,
- const char *searchName, const struct nls_table *nls_codepage,
- __u16 *searchHandle, struct cifs_search_info * psrch_inf);
-
-extern int CIFSFindNext2(const int xid, struct cifsTconInfo *tcon,
- __u16 searchHandle, struct cifs_search_info * psrch_inf);
-
-extern int construct_dentry(struct qstr *qstring, struct file *file,
- struct inode **ptmp_inode, struct dentry **pnew_dentry);
-
-extern void fill_in_inode(struct inode *tmp_inode,
- FILE_DIRECTORY_INFO * pfindData, int *pobject_type);
-
-extern void unix_fill_in_inode(struct inode *tmp_inode,
- FILE_UNIX_INFO * pfindData, int *pobject_type);
-
+#include "cifsfs.h"
/* BB fixme - add debug wrappers around this function to disable it fixme BB */
-/* static void dump_cifs_file_struct(struct file * file, char * label)
+/* static void dump_cifs_file_struct(struct file *file, char *label)
{
struct cifsFileInfo * cf;
if(file) {
- cf = (struct cifsFileInfo *)file->private_data;
+ cf = file->private_data;
if(cf == NULL) {
cFYI(1,("empty cifs private file data"));
return;
@@ -71,7 +55,232 @@ extern void unix_fill_in_inode(struct inode *tmp_inode,
}
} */
-static int initiate_cifs_search(const int xid, struct file * file)
+/* Returns one if new inode created (which therefore needs to be hashed) */
+/* Might check in the future if inode number changed so we can rehash inode */
+static int construct_dentry(struct qstr *qstring, struct file *file,
+ struct inode **ptmp_inode, struct dentry **pnew_dentry)
+{
+ struct dentry *tmp_dentry;
+ struct cifs_sb_info *cifs_sb;
+ struct cifsTconInfo *pTcon;
+ int rc = 0;
+
+ cFYI(1, ("For %s ", qstring->name));
+ cifs_sb = CIFS_SB(file->f_dentry->d_sb);
+ pTcon = cifs_sb->tcon;
+
+ qstring->hash = full_name_hash(qstring->name, qstring->len);
+ tmp_dentry = d_lookup(file->f_dentry, qstring);
+ if (tmp_dentry) {
+ cFYI(0, (" existing dentry with inode 0x%p", tmp_dentry->d_inode));
+ *ptmp_inode = tmp_dentry->d_inode;
+/* BB overwrite old name? i.e. tmp_dentry->d_name and tmp_dentry->d_name.len??*/
+ if(*ptmp_inode == NULL) {
+ *ptmp_inode = new_inode(file->f_dentry->d_sb);
+ if(*ptmp_inode == NULL)
+ return rc;
+ rc = 1;
+ d_instantiate(tmp_dentry, *ptmp_inode);
+ }
+ } else {
+ tmp_dentry = d_alloc(file->f_dentry, qstring);
+ if(tmp_dentry == NULL) {
+ cERROR(1,("Failed allocating dentry"));
+ *ptmp_inode = NULL;
+ return rc;
+ }
+
+ *ptmp_inode = new_inode(file->f_dentry->d_sb);
+ tmp_dentry->d_op = &cifs_dentry_ops;
+ if(*ptmp_inode == NULL)
+ return rc;
+ rc = 1;
+ d_instantiate(tmp_dentry, *ptmp_inode);
+ d_rehash(tmp_dentry);
+ }
+
+ tmp_dentry->d_time = jiffies;
+ *pnew_dentry = tmp_dentry;
+ return rc;
+}
+
+static void fill_in_inode(struct inode *tmp_inode,
+ FILE_DIRECTORY_INFO *pfindData, int *pobject_type)
+{
+ struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
+ struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb);
+ __u32 attr = le32_to_cpu(pfindData->ExtFileAttributes);
+ __u64 allocation_size = le64_to_cpu(pfindData->AllocationSize);
+ __u64 end_of_file = le64_to_cpu(pfindData->EndOfFile);
+
+ cifsInfo->cifsAttrs = attr;
+ cifsInfo->time = jiffies;
+
+ /* Linux can not store file creation time unfortunately so ignore it */
+ tmp_inode->i_atime =
+ cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
+ tmp_inode->i_mtime =
+ cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime));
+ tmp_inode->i_ctime =
+ cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
+ /* treat dos attribute of read-only as read-only mode bit e.g. 555? */
+ /* 2767 perms - indicate mandatory locking */
+ /* BB fill in uid and gid here? with help from winbind?
+ or retrieve from NTFS stream extended attribute */
+ if (atomic_read(&cifsInfo->inUse) == 0) {
+ tmp_inode->i_uid = cifs_sb->mnt_uid;
+ tmp_inode->i_gid = cifs_sb->mnt_gid;
+ /* set default mode. will override for dirs below */
+ tmp_inode->i_mode = cifs_sb->mnt_file_mode;
+ }
+
+ cFYI(0,("CIFS FFIRST: Attributes came in as 0x%x",attr));
+ if (attr & ATTR_DIRECTORY) {
+ *pobject_type = DT_DIR;
+ /* override default perms since we do not lock dirs */
+ if(atomic_read(&cifsInfo->inUse) == 0) {
+ tmp_inode->i_mode = cifs_sb->mnt_dir_mode;
+ }
+ tmp_inode->i_mode |= S_IFDIR;
+/* we no longer mark these because we could not follow them */
+/* } else if (attr & ATTR_REPARSE) {
+ *pobject_type = DT_LNK;
+ tmp_inode->i_mode |= S_IFLNK; */
+ } else {
+ *pobject_type = DT_REG;
+ tmp_inode->i_mode |= S_IFREG;
+ if (attr & ATTR_READONLY)
+ tmp_inode->i_mode &= ~(S_IWUGO);
+ } /* could add code here - to validate if device or weird share type? */
+
+ /* can not fill in nlink here as in qpathinfo version and Unx search */
+ if (atomic_read(&cifsInfo->inUse) == 0) {
+ atomic_set(&cifsInfo->inUse, 1);
+ }
+
+ if (is_size_safe_to_change(cifsInfo)) {
+ /* can not safely change the file size here if the
+ client is writing to it due to potential races */
+ i_size_write(tmp_inode, end_of_file);
+
+ /* 512 bytes (2**9) is the fake blocksize that must be used */
+ /* for this calculation, even though the reported blocksize is larger */
+ tmp_inode->i_blocks = (512 - 1 + allocation_size) >> 9;
+ }
+
+ if (allocation_size < end_of_file)
+ cFYI(1, ("May be sparse file, allocation less than file size"));
+ cFYI(1,
+ ("File Size %ld and blocks %ld and blocksize %ld",
+ (unsigned long)tmp_inode->i_size, tmp_inode->i_blocks,
+ tmp_inode->i_blksize));
+ 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;
+ else
+ tmp_inode->i_fop = &cifs_file_ops;
+ tmp_inode->i_data.a_ops = &cifs_addr_ops;
+ } else if (S_ISDIR(tmp_inode->i_mode)) {
+ cFYI(1, (" Directory inode"));
+ tmp_inode->i_op = &cifs_dir_inode_ops;
+ tmp_inode->i_fop = &cifs_dir_ops;
+ } else if (S_ISLNK(tmp_inode->i_mode)) {
+ cFYI(1, (" Symbolic Link inode "));
+ tmp_inode->i_op = &cifs_symlink_inode_ops;
+ } else {
+ cFYI(1, (" Init special inode "));
+ init_special_inode(tmp_inode, tmp_inode->i_mode,
+ tmp_inode->i_rdev);
+ }
+}
+
+static void unix_fill_in_inode(struct inode *tmp_inode,
+ FILE_UNIX_INFO *pfindData, int *pobject_type)
+{
+ struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
+ struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb);
+
+ __u32 type = le32_to_cpu(pfindData->Type);
+ __u64 num_of_bytes = le64_to_cpu(pfindData->NumOfBytes);
+ __u64 end_of_file = le64_to_cpu(pfindData->EndOfFile);
+ cifsInfo->time = jiffies;
+ atomic_inc(&cifsInfo->inUse);
+
+ tmp_inode->i_atime =
+ cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
+ tmp_inode->i_mtime =
+ cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastModificationTime));
+ tmp_inode->i_ctime =
+ cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastStatusChange));
+
+ tmp_inode->i_mode = le64_to_cpu(pfindData->Permissions);
+ if (type == UNIX_FILE) {
+ *pobject_type = DT_REG;
+ tmp_inode->i_mode |= S_IFREG;
+ } else if (type == UNIX_SYMLINK) {
+ *pobject_type = DT_LNK;
+ tmp_inode->i_mode |= S_IFLNK;
+ } else if (type == UNIX_DIR) {
+ *pobject_type = DT_DIR;
+ tmp_inode->i_mode |= S_IFDIR;
+ } else if (type == UNIX_CHARDEV) {
+ *pobject_type = DT_CHR;
+ tmp_inode->i_mode |= S_IFCHR;
+ tmp_inode->i_rdev = MKDEV(le64_to_cpu(pfindData->DevMajor),
+ le64_to_cpu(pfindData->DevMinor) & MINORMASK);
+ } else if (type == UNIX_BLOCKDEV) {
+ *pobject_type = DT_BLK;
+ tmp_inode->i_mode |= S_IFBLK;
+ tmp_inode->i_rdev = MKDEV(le64_to_cpu(pfindData->DevMajor),
+ le64_to_cpu(pfindData->DevMinor) & MINORMASK);
+ } else if (type == UNIX_FIFO) {
+ *pobject_type = DT_FIFO;
+ tmp_inode->i_mode |= S_IFIFO;
+ } else if (type == UNIX_SOCKET) {
+ *pobject_type = DT_SOCK;
+ tmp_inode->i_mode |= S_IFSOCK;
+ }
+
+ tmp_inode->i_uid = le64_to_cpu(pfindData->Uid);
+ tmp_inode->i_gid = le64_to_cpu(pfindData->Gid);
+ tmp_inode->i_nlink = le64_to_cpu(pfindData->Nlinks);
+
+ if (is_size_safe_to_change(cifsInfo)) {
+ /* can not safely change the file size here if the
+ client is writing to it due to potential races */
+ i_size_write(tmp_inode,end_of_file);
+
+ /* 512 bytes (2**9) is the fake blocksize that must be used */
+ /* for this calculation, not the real blocksize */
+ tmp_inode->i_blocks = (512 - 1 + num_of_bytes) >> 9;
+ }
+
+ 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;
+ else
+ tmp_inode->i_fop = &cifs_file_ops;
+ tmp_inode->i_data.a_ops = &cifs_addr_ops;
+ } else if (S_ISDIR(tmp_inode->i_mode)) {
+ cFYI(1, ("Directory inode"));
+ tmp_inode->i_op = &cifs_dir_inode_ops;
+ tmp_inode->i_fop = &cifs_dir_ops;
+ } else if (S_ISLNK(tmp_inode->i_mode)) {
+ cFYI(1, ("Symbolic Link inode"));
+ tmp_inode->i_op = &cifs_symlink_inode_ops;
+/* tmp_inode->i_fop = *//* do not need to set to anything */
+ } else {
+ cFYI(1, ("Special inode"));
+ init_special_inode(tmp_inode, tmp_inode->i_mode,
+ tmp_inode->i_rdev);
+ }
+}
+
+static int initiate_cifs_search(const int xid, struct file *file)
{
int rc = 0;
char * full_path;
@@ -89,10 +298,13 @@ static int initiate_cifs_search(const int xid, struct file * file)
} else {
memset(file->private_data,0,sizeof(struct cifsFileInfo));
}
- cifsFile = (struct cifsFileInfo *)file->private_data;
+ cifsFile = file->private_data;
cifsFile->invalidHandle = TRUE;
cifsFile->srch_inf.endOfSearch = FALSE;
+ if(file->f_dentry == NULL)
+ return -ENOENT;
+
cifs_sb = CIFS_SB(file->f_dentry->d_sb);
if(cifs_sb == NULL)
return -EINVAL;
@@ -101,9 +313,6 @@ static int initiate_cifs_search(const int xid, struct file * file)
if(pTcon == NULL)
return -EINVAL;
- if(file->f_dentry == NULL)
- return -ENOENT;
-
down(&file->f_dentry->d_sb->s_vfs_rename_sem);
full_path = build_wildcard_path_from_dentry(file->f_dentry);
up(&file->f_dentry->d_sb->s_vfs_rename_sem);
@@ -116,24 +325,23 @@ static int initiate_cifs_search(const int xid, struct file * file)
/* test for Unix extensions */
if (pTcon->ses->capabilities & CAP_UNIX) {
- cifsFile->srch_inf.info_level = SMB_FIND_FILE_UNIX;
+ cifsFile->srch_inf.info_level = SMB_FIND_FILE_UNIX;
} else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
cifsFile->srch_inf.info_level = SMB_FIND_FILE_ID_FULL_DIR_INFO;
} else /* not srvinos - BB fixme add check for backlevel? */ {
cifsFile->srch_inf.info_level = SMB_FIND_FILE_DIRECTORY_INFO;
}
- rc = CIFSFindFirst2(xid, pTcon,full_path,cifs_sb->local_nls,
+ rc = CIFSFindFirst(xid, pTcon,full_path,cifs_sb->local_nls,
&cifsFile->netfid, &cifsFile->srch_inf);
if(rc == 0)
cifsFile->invalidHandle = FALSE;
- if(full_path)
- kfree(full_path);
+ kfree(full_path);
return rc;
}
/* return length of unicode string in bytes */
-static int cifs_unicode_bytelen(char * str)
+static int cifs_unicode_bytelen(char *str)
{
int len;
__le16 * ustr = (__le16 *)str;
@@ -146,7 +354,7 @@ static int cifs_unicode_bytelen(char * str)
return len << 1;
}
-static char * nxt_dir_entry(char * old_entry, char * end_of_smb)
+static char *nxt_dir_entry(char *old_entry, char *end_of_smb)
{
char * new_entry;
FILE_DIRECTORY_INFO * pDirInfo = (FILE_DIRECTORY_INFO *)old_entry;
@@ -166,7 +374,7 @@ static char * nxt_dir_entry(char * old_entry, char * end_of_smb)
#define UNICODE_DOT cpu_to_le16(0x2e)
/* return 0 if no match and 1 for . (current directory) and 2 for .. (parent) */
-static int cifs_entry_is_dot(char * current_entry, struct cifsFileInfo * cfile)
+static int cifs_entry_is_dot(char *current_entry, struct cifsFileInfo *cfile)
{
int rc = 0;
char * filename = NULL;
@@ -238,14 +446,14 @@ static int cifs_entry_is_dot(char * current_entry, struct cifsFileInfo * cfile)
assume that they are located in the findfirst return buffer.*/
/* We start counting in the buffer with entry 2 and increment for every
entry (do not increment for . or .. entry) */
-static int find_cifs_entry(const int xid, struct cifsTconInfo * pTcon,
- struct file * file, char ** ppCurrentEntry,int * num_to_ret)
+static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
+ struct file *file, char **ppCurrentEntry, int *num_to_ret)
{
int rc = 0;
int pos_in_buf = 0;
loff_t first_entry_in_buffer;
loff_t index_to_find = file->f_pos;
- struct cifsFileInfo * cifsFile = (struct cifsFileInfo *)file->private_data;
+ struct cifsFileInfo * cifsFile = file->private_data;
/* check if index in the buffer */
if((cifsFile == NULL) || (ppCurrentEntry == NULL) || (num_to_ret == NULL))
@@ -261,12 +469,10 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo * pTcon,
cFYI(1,("search backing up - close and restart search"));
cifsFile->invalidHandle = TRUE;
CIFSFindClose(xid, pTcon, cifsFile->netfid);
- if(cifsFile->search_resume_name) {
- kfree(cifsFile->search_resume_name);
- cifsFile->search_resume_name = NULL;
- }
+ kfree(cifsFile->search_resume_name);
+ cifsFile->search_resume_name = NULL;
if(cifsFile->srch_inf.ntwrk_buf_start) {
- cFYI(1,("freeing SMB ff cache buf on search rewind"));
+ cFYI(1,("freeing SMB ff cache buf on search rewind"));
cifs_buf_release(cifsFile->srch_inf.ntwrk_buf_start);
}
rc = initiate_cifs_search(xid,file);
@@ -279,7 +485,7 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo * pTcon,
while((index_to_find >= cifsFile->srch_inf.index_of_last_entry) &&
(rc == 0) && (cifsFile->srch_inf.endOfSearch == FALSE)){
cFYI(1,("calling findnext2"));
- rc = CIFSFindNext2(xid,pTcon,cifsFile->netfid, &cifsFile->srch_inf);
+ rc = CIFSFindNext(xid,pTcon,cifsFile->netfid, &cifsFile->srch_inf);
if(rc)
return -ENOENT;
}
@@ -289,10 +495,11 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo * pTcon,
int i;
char * current_entry;
char * end_of_smb = cifsFile->srch_inf.ntwrk_buf_start +
- smbCalcSize((struct smb_hdr *)cifsFile->srch_inf.ntwrk_buf_start);
+ smbCalcSize((struct smb_hdr *)
+ cifsFile->srch_inf.ntwrk_buf_start);
/* dump_cifs_file_struct(file,"found entry in fce "); */
- first_entry_in_buffer = cifsFile->srch_inf.index_of_last_entry -
- cifsFile->srch_inf.entries_in_buffer;
+ first_entry_in_buffer = cifsFile->srch_inf.index_of_last_entry
+ - cifsFile->srch_inf.entries_in_buffer;
pos_in_buf = index_to_find - first_entry_in_buffer;
cFYI(1,("found entry - pos_in_buf %d",pos_in_buf));
current_entry = cifsFile->srch_inf.srch_entries_start;
@@ -311,7 +518,10 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo * pTcon,
current_entry = nxt_dir_entry(current_entry,end_of_smb);
}
if((current_entry == NULL) && (i < pos_in_buf)) {
- cERROR(1,("reached end of buf searching for pos in buf %d index to find %lld rc %d",pos_in_buf,index_to_find,rc)); /* BB removeme BB */
+ /* BB fixme - check if we should flag this error */
+ cERROR(1,("reached end of buf searching for pos in buf"
+ " %d index to find %lld rc %d",
+ pos_in_buf,index_to_find,rc));
}
rc = 0;
*ppCurrentEntry = current_entry;
@@ -331,13 +541,14 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo * pTcon,
}
/* inode num, inode type and filename returned */
-static int cifs_get_name_from_search_buf(struct qstr * pqst,char * current_entry,
- __u16 level,unsigned int unicode,struct nls_table * nlt,
- ino_t * pinum)
+static int cifs_get_name_from_search_buf(struct qstr *pqst,
+ char *current_entry, __u16 level, unsigned int unicode,
+ struct cifs_sb_info * cifs_sb, ino_t *pinum)
{
int rc = 0;
unsigned int len = 0;
char * filename;
+ struct nls_table * nlt = cifs_sb->local_nls;
*pinum = 0;
@@ -353,7 +564,8 @@ static int cifs_get_name_from_search_buf(struct qstr * pqst,char * current_entry
}
/* BB fixme - hash low and high 32 bits if not 64 bit arch BB fixme */
- *pinum = pFindData->UniqueId;
+ if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
+ *pinum = pFindData->UniqueId;
} else if(level == SMB_FIND_FILE_DIRECTORY_INFO) {
FILE_DIRECTORY_INFO * pFindData =
(FILE_DIRECTORY_INFO *)current_entry;
@@ -392,10 +604,8 @@ static int cifs_get_name_from_search_buf(struct qstr * pqst,char * current_entry
return rc;
}
-
-static int
-cifs_filldir2(char * pfindEntry, struct file *file,
- filldir_t filldir, void *direntry,char * scratch_buf)
+static int cifs_filldir(char *pfindEntry, struct file *file,
+ filldir_t filldir, void *direntry, char *scratch_buf)
{
int rc = 0;
struct qstr qstring;
@@ -425,7 +635,7 @@ cifs_filldir2(char * pfindEntry, struct file *file,
qstring.name = scratch_buf;
rc = cifs_get_name_from_search_buf(&qstring,pfindEntry,
pCifsF->srch_inf.info_level,
- pCifsF->srch_inf.unicode,cifs_sb->local_nls,
+ pCifsF->srch_inf.unicode,cifs_sb,
&inum /* returned */);
if(rc)
@@ -459,7 +669,8 @@ cifs_filldir2(char * pfindEntry, struct file *file,
return rc;
}
-int cifs_save_resume_key(const char * current_entry,struct cifsFileInfo * cifsFile)
+static int cifs_save_resume_key(const char *current_entry,
+ struct cifsFileInfo *cifsFile)
{
int rc = 0;
unsigned int len = 0;
@@ -515,7 +726,7 @@ int cifs_save_resume_key(const char * current_entry,struct cifsFileInfo * cifsFi
return rc;
}
-int cifs_readdir2(struct file *file, void *direntry, filldir_t filldir)
+int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
{
int rc = 0;
int xid,i;
@@ -579,7 +790,7 @@ int cifs_readdir2(struct file *file, void *direntry, filldir_t filldir)
FreeXid(xid);
return rc;
}
- cifsFile = (struct cifsFileInfo *) file->private_data;
+ cifsFile = file->private_data;
if (cifsFile->srch_inf.endOfSearch) {
if(cifsFile->srch_inf.emptyDir) {
cFYI(1, ("End of search, empty dir"));
@@ -590,11 +801,10 @@ int cifs_readdir2(struct file *file, void *direntry, filldir_t filldir)
cifsFile->invalidHandle = TRUE;
CIFSFindClose(xid, pTcon, cifsFile->netfid);
}
- if(cifsFile->search_resume_name) {
- kfree(cifsFile->search_resume_name);
- cifsFile->search_resume_name = NULL;
- } */
-/* BB account for . and .. in f_pos */
+ kfree(cifsFile->search_resume_name);
+ cifsFile->search_resume_name = NULL; */
+
+ /* BB account for . and .. in f_pos as special case */
/* dump_cifs_file_struct(file, "rdir after default ");*/
rc = find_cifs_entry(xid,pTcon, file,
@@ -610,33 +820,43 @@ int cifs_readdir2(struct file *file, void *direntry, filldir_t filldir)
}
cFYI(1,("loop through %d times filling dir for net buf %p",
num_to_fill,cifsFile->srch_inf.ntwrk_buf_start));
- end_of_smb = cifsFile->srch_inf.ntwrk_buf_start +
- smbCalcSize((struct smb_hdr *)cifsFile->srch_inf.ntwrk_buf_start);
+ end_of_smb = cifsFile->srch_inf.ntwrk_buf_start +
+ smbCalcSize((struct smb_hdr *)
+ cifsFile->srch_inf.ntwrk_buf_start);
tmp_buf = kmalloc(NAME_MAX+1,GFP_KERNEL);
for(i=0;(i<num_to_fill) && (rc == 0);i++) {
if(current_entry == NULL) {
- cERROR(1,("beyond end of smb with num to fill %d i %d",num_to_fill,i)); /* BB removeme BB */
+ /* evaluate whether this case is an error */
+ cERROR(1,("past end of SMB num to fill %d i %d",
+ num_to_fill, i));
break;
}
-/* if((!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) ||
- (cifsFile->srch_inf.info_level != something that supports server inodes)) {
+
+ /* BB FIXME - need to enable the below code BB */
+
+ /* if((!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) ||
+ (cifsFile->srch_inf.info_level !=
+ something that supports server inodes)) {
create dentry
create inode
- fill in inode new_inode (which makes number locally)
+ fill in inode new_inode (getting local i_ino)
}
- also create local inode for per reasons unless new mount parm says otherwise */
- rc = cifs_filldir2(current_entry, file,
+ also create local inode for performance reasons (so we
+ have a cache of inode metadata) unless this new mount
+ parm says otherwise */
+
+ rc = cifs_filldir(current_entry, file,
filldir, direntry,tmp_buf);
file->f_pos++;
if(file->f_pos == cifsFile->srch_inf.index_of_last_entry) {
- cFYI(1,("last entry in buf at pos %lld %s",file->f_pos,tmp_buf)); /* BB removeme BB */
+ cFYI(1,("last entry in buf at pos %lld %s",
+ file->f_pos,tmp_buf)); /* BB removeme BB */
cifs_save_resume_key(current_entry,cifsFile);
break;
} else
current_entry = nxt_dir_entry(current_entry,end_of_smb);
}
- if(tmp_buf != NULL)
- kfree(tmp_buf);
+ kfree(tmp_buf);
break;
} /* end switch */
@@ -645,4 +865,3 @@ rddir2_exit:
FreeXid(xid);
return rc;
}
-
diff --git a/fs/cifs/smbdes.c b/fs/cifs/smbdes.c
index 4d765f737f5d0..efaa044523a70 100644
--- a/fs/cifs/smbdes.c
+++ b/fs/cifs/smbdes.c
@@ -45,6 +45,7 @@
up with a different answer to the one above)
*/
#include <linux/slab.h>
+#include "cifsencrypt.h"
#define uchar unsigned char
static uchar perm1[56] = { 57, 49, 41, 33, 25, 17, 9,
@@ -376,7 +377,9 @@ E_old_pw_hash(unsigned char *p14, unsigned char *in, unsigned char *out)
smbhash(out, in, p14, 1);
smbhash(out + 8, in + 8, p14 + 7, 1);
}
-
+#if 0
+/* these routines are currently unneeded, but may be
+ needed later */
void
cred_hash1(unsigned char *out, unsigned char *in, unsigned char *key)
{
@@ -406,3 +409,4 @@ cred_hash3(unsigned char *out, unsigned char *in, unsigned char *key, int forw)
key2[0] = key[7];
smbhash(out + 8, in + 8, key2, forw);
}
+#endif /* unneeded routines */
diff --git a/fs/cifs/smbencrypt.c b/fs/cifs/smbencrypt.c
index c6dfc2277cbb7..6103bcdfb16d9 100644
--- a/fs/cifs/smbencrypt.c
+++ b/fs/cifs/smbencrypt.c
@@ -32,6 +32,7 @@
#include "cifspdu.h"
#include "md5.h"
#include "cifs_debug.h"
+#include "cifsencrypt.h"
#ifndef FALSE
#define FALSE 0
@@ -45,27 +46,12 @@
#define SSVALX(buf,pos,val) (CVAL(buf,pos)=(val)&0xFF,CVAL(buf,pos+1)=(val)>>8)
#define SSVAL(buf,pos,val) SSVALX((buf),(pos),((__u16)(val)))
-/*The following definitions come from lib/md4.c */
-
-void mdfour(unsigned char *out, unsigned char *in, int n);
-
-/*The following definitions come from libsmb/smbdes.c */
-
-void E_P16(unsigned char *p14, unsigned char *p16);
-void E_P24(unsigned char *p21, unsigned char *c8, unsigned char *p24);
-void D_P16(unsigned char *p14, unsigned char *in, unsigned char *out);
-void E_old_pw_hash(unsigned char *p14, unsigned char *in, unsigned char *out);
-void cred_hash1(unsigned char *out, unsigned char *in, unsigned char *key);
-void cred_hash2(unsigned char *out, unsigned char *in, unsigned char *key);
-void cred_hash3(unsigned char *out, unsigned char *in, unsigned char *key,
- int forw);
-
/*The following definitions come from libsmb/smbencrypt.c */
void SMBencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24);
void E_md4hash(const unsigned char *passwd, unsigned char *p16);
void nt_lm_owf_gen(char *pwd, unsigned char nt_p16[16], unsigned char p16[16]);
-void SMBOWFencrypt(unsigned char passwd[16], unsigned char *c8,
+static void SMBOWFencrypt(unsigned char passwd[16], unsigned char *c8,
unsigned char p24[24]);
void NTLMSSPOWFencrypt(unsigned char passwd[8],
unsigned char *ntlmchalresp, unsigned char p24[24]);
@@ -186,7 +172,8 @@ nt_lm_owf_gen(char *pwd, unsigned char nt_p16[16], unsigned char p16[16])
}
/* Does the NTLMv2 owfs of a user's password */
-void
+#if 0 /* function not needed yet - but will be soon */
+static void
ntv2_owf_gen(const unsigned char owf[16], const char *user_n,
const char *domain_n, unsigned char kr_buf[16],
const struct nls_table *nls_codepage)
@@ -219,9 +206,10 @@ ntv2_owf_gen(const unsigned char owf[16], const char *user_n,
kfree(user_u);
}
+#endif
/* Does the des encryption from the NT or LM MD4 hash. */
-void
+static void
SMBOWFencrypt(unsigned char passwd[16], unsigned char *c8,
unsigned char p24[24])
{
@@ -260,8 +248,11 @@ SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24)
SMBOWFencrypt(p21, c8, p24);
}
+
/* Does the md5 encryption from the NT hash for NTLMv2. */
-void
+/* These routines will be needed later */
+#if 0
+static void
SMBOWFencrypt_ntv2(const unsigned char kr[16],
const struct data_blob * srv_chal,
const struct data_blob * cli_chal, unsigned char resp_buf[16])
@@ -274,7 +265,7 @@ SMBOWFencrypt_ntv2(const unsigned char kr[16],
hmac_md5_final(resp_buf, &ctx);
}
-void
+static void
SMBsesskeygen_ntv2(const unsigned char kr[16],
const unsigned char *nt_resp, __u8 sess_key[16])
{
@@ -285,9 +276,10 @@ SMBsesskeygen_ntv2(const unsigned char kr[16],
hmac_md5_final((unsigned char *) sess_key, &ctx);
}
-void
+static void
SMBsesskeygen_ntv1(const unsigned char kr[16],
const unsigned char *nt_resp, __u8 sess_key[16])
{
mdfour((unsigned char *) sess_key, (unsigned char *) kr, 16);
}
+#endif
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index 79f0992a2c6b9..af13e526b150c 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -23,6 +23,7 @@
#include <linux/list.h>
#include <linux/wait.h>
#include <linux/net.h>
+#include <linux/delay.h>
#include <asm/uaccess.h>
#include <asm/processor.h>
#include <linux/mempool.h>
@@ -34,7 +35,7 @@
extern mempool_t *cifs_mid_poolp;
extern kmem_cache_t *cifs_oplock_cachep;
-struct mid_q_entry *
+static struct mid_q_entry *
AllocMidQEntry(struct smb_hdr *smb_buffer, struct cifsSesInfo *ses)
{
struct mid_q_entry *temp;
@@ -70,7 +71,7 @@ AllocMidQEntry(struct smb_hdr *smb_buffer, struct cifsSesInfo *ses)
return temp;
}
-void
+static void
DeleteMidQEntry(struct mid_q_entry *midEntry)
{
spin_lock(&GlobalMid_Lock);
@@ -156,8 +157,7 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
rc = -EAGAIN;
break;
}
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(HZ/2);
+ msleep(500);
continue;
}
if (rc < 0)
@@ -179,6 +179,70 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
#ifdef CIFS_EXPERIMENTAL
/* BB finish off this function, adding support for writing set of pages as iovec */
/* and also adding support for operations that need to parse the response smb */
+
+int
+smb_sendv(struct socket *ssocket, struct smb_hdr *smb_buffer,
+ unsigned int smb_buf_length, struct kvec * write_vector /* page list */, struct sockaddr *sin)
+{
+ int rc = 0;
+ int i = 0;
+ struct msghdr smb_msg;
+ number_of_pages += 1; /* account for SMB header */
+ struct kvec * piov = kmalloc(number_of_pages * sizeof(struct kvec));
+ if(i=0;i<num_pages-1;i++
+ unsigned len = smb_buf_length + 4;
+
+ if(ssocket == NULL)
+ return -ENOTSOCK; /* BB eventually add reconnect code here */
+ iov.iov_base = smb_buffer;
+ iov.iov_len = len;
+
+ smb_msg.msg_name = sin;
+ smb_msg.msg_namelen = sizeof (struct sockaddr);
+ smb_msg.msg_control = NULL;
+ smb_msg.msg_controllen = 0;
+ smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; /* BB add more flags?*/
+
+ /* smb header is converted in header_assemble. bcc and rest of SMB word
+ area, and byte area if necessary, is converted to littleendian in
+ cifssmb.c and RFC1001 len is converted to bigendian in smb_send
+ Flags2 is converted in SendReceive */
+
+ smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length);
+ cFYI(1, ("Sending smb of length %d ", smb_buf_length));
+ dump_smb(smb_buffer, len);
+
+ while (len > 0) {
+ rc = kernel_sendmsg(ssocket, &smb_msg, &iov, number_of_pages, len?);
+ if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
+ i++;
+ if(i > 60) {
+ cERROR(1,
+ ("sends on sock %p stuck for 30 seconds",
+ ssocket));
+ rc = -EAGAIN;
+ break;
+ }
+ msleep(500);
+ continue;
+ }
+ if (rc < 0)
+ break;
+ iov.iov_base += rc;
+ iov.iov_len -= rc;
+ len -= rc;
+ }
+
+ if (rc < 0) {
+ cERROR(1,("Error %d sending data on socket to server.", rc));
+ } else {
+ rc = 0;
+ }
+
+ return rc;
+}
+
+
int
CIFSSendRcv(const unsigned int xid, struct cifsSesInfo *ses,
struct smb_hdr *in_buf, struct kvec * write_vector /* page list */, int *pbytes_returned, const int long_op)
@@ -285,7 +349,7 @@ CIFSSendRcv(const unsigned int xid, struct cifsSesInfo *ses,
rc = cifs_sign_smb(in_buf, ses, &midQ->sequence_number);
midQ->midState = MID_REQUEST_SUBMITTED;
-/* rc = smb_send2(ses->server->ssocket, in_buf, in_buf->smb_buf_length, piovec,
+/* rc = smb_sendv(ses->server->ssocket, in_buf, in_buf->smb_buf_length, piovec,
(struct sockaddr *) &(ses->server->addr.sockAddr));*/
if(rc < 0) {
DeleteMidQEntry(midQ);
diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c
index 22f909ee7a77d..549afa184fd67 100644
--- a/fs/cifs/xattr.c
+++ b/fs/cifs/xattr.c
@@ -71,16 +71,21 @@ int cifs_removexattr(struct dentry * direntry, const char * ea_name)
}
if(ea_name == NULL) {
cFYI(1,("Null xattr names not supported"));
- } else if(strncmp(ea_name,CIFS_XATTR_USER_PREFIX,5)) {
+ } else if(strncmp(ea_name,CIFS_XATTR_USER_PREFIX,5)
+ && (strncmp(ea_name,CIFS_XATTR_OS2_PREFIX,4))) {
cFYI(1,("illegal xattr namespace %s (only user namespace supported)",ea_name));
/* BB what if no namespace prefix? */
/* Should we just pass them to server, except for
system and perhaps security prefixes? */
} else {
+ if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
+ goto remove_ea_exit;
+
ea_name+=5; /* skip past user. prefix */
rc = CIFSSMBSetEA(xid,pTcon,full_path,ea_name,NULL,
(__u16)0, cifs_sb->local_nls);
}
+remove_ea_exit:
if (full_path)
kfree(full_path);
FreeXid(xid);
@@ -135,6 +140,8 @@ int cifs_setxattr(struct dentry * direntry, const char * ea_name,
if(ea_name == NULL) {
cFYI(1,("Null xattr names not supported"));
} else if(strncmp(ea_name,CIFS_XATTR_USER_PREFIX,5) == 0) {
+ if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
+ goto set_ea_exit;
if(strncmp(ea_name,CIFS_XATTR_DOS_ATTRIB,14) == 0) {
cFYI(1,("attempt to set cifs inode metadata"));
}
@@ -142,6 +149,9 @@ int cifs_setxattr(struct dentry * direntry, const char * ea_name,
rc = CIFSSMBSetEA(xid,pTcon,full_path,ea_name,ea_value,
(__u16)value_size, cifs_sb->local_nls);
} else if(strncmp(ea_name, CIFS_XATTR_OS2_PREFIX,4) == 0) {
+ if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
+ goto set_ea_exit;
+
ea_name += 4; /* skip past os2. prefix */
rc = CIFSSMBSetEA(xid,pTcon,full_path,ea_name,ea_value,
(__u16)value_size, cifs_sb->local_nls);
@@ -174,7 +184,8 @@ int cifs_setxattr(struct dentry * direntry, const char * ea_name,
system and perhaps security prefixes? */
}
}
-
+
+set_ea_exit:
if (full_path)
kfree(full_path);
FreeXid(xid);
@@ -218,6 +229,9 @@ ssize_t cifs_getxattr(struct dentry * direntry, const char * ea_name,
if(ea_name == NULL) {
cFYI(1,("Null xattr names not supported"));
} else if(strncmp(ea_name,CIFS_XATTR_USER_PREFIX,5) == 0) {
+ if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
+ goto get_ea_exit;
+
if(strncmp(ea_name,CIFS_XATTR_DOS_ATTRIB,14) == 0) {
cFYI(1,("attempt to query cifs inode metadata"));
/* revalidate/getattr then populate from inode */
@@ -226,6 +240,9 @@ 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);
} else if(strncmp(ea_name, CIFS_XATTR_OS2_PREFIX,4) == 0) {
+ if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
+ goto get_ea_exit;
+
ea_name += 4; /* skip past os2. prefix */
rc = CIFSSMBQueryEA(xid,pTcon,full_path,ea_name,ea_value,
buf_size, cifs_sb->local_nls);
@@ -263,6 +280,7 @@ ssize_t cifs_getxattr(struct dentry * direntry, const char * ea_name,
if(rc == -EINVAL)
rc = -EOPNOTSUPP;
+get_ea_exit:
if (full_path)
kfree(full_path);
FreeXid(xid);
diff --git a/fs/compat.c b/fs/compat.c
index e6c8fffe56d41..a912bdf691cfc 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -131,7 +131,7 @@ static int put_compat_statfs(struct compat_statfs __user *ubuf, struct kstatfs *
&& (kbuf->f_ffree & 0xffffffff00000000ULL))
return -EOVERFLOW;
}
- if (verify_area(VERIFY_WRITE, ubuf, sizeof(*ubuf)) ||
+ if (!access_ok(VERIFY_WRITE, ubuf, sizeof(*ubuf)) ||
__put_user(kbuf->f_type, &ubuf->f_type) ||
__put_user(kbuf->f_bsize, &ubuf->f_bsize) ||
__put_user(kbuf->f_blocks, &ubuf->f_blocks) ||
@@ -205,7 +205,7 @@ static int put_compat_statfs64(struct compat_statfs64 __user *ubuf, struct kstat
&& (kbuf->f_ffree & 0xffffffff00000000ULL))
return -EOVERFLOW;
}
- if (verify_area(VERIFY_WRITE, ubuf, sizeof(*ubuf)) ||
+ if (!access_ok(VERIFY_WRITE, ubuf, sizeof(*ubuf)) ||
__put_user(kbuf->f_type, &ubuf->f_type) ||
__put_user(kbuf->f_bsize, &ubuf->f_bsize) ||
__put_user(kbuf->f_blocks, &ubuf->f_blocks) ||
@@ -1152,7 +1152,7 @@ static ssize_t compat_do_readv_writev(int type, struct file *file,
goto out;
}
ret = -EFAULT;
- if (verify_area(VERIFY_READ, uvector, nr_segs*sizeof(*uvector)))
+ if (!access_ok(VERIFY_READ, uvector, nr_segs*sizeof(*uvector)))
goto out;
/*
@@ -1537,7 +1537,7 @@ int compat_get_fd_set(unsigned long nr, compat_ulong_t __user *ufdset,
if (ufdset) {
unsigned long odd;
- if (verify_area(VERIFY_WRITE, ufdset, nr*sizeof(compat_ulong_t)))
+ if (!access_ok(VERIFY_WRITE, ufdset, nr*sizeof(compat_ulong_t)))
return -EFAULT;
odd = nr & 1UL;
@@ -1620,18 +1620,19 @@ compat_sys_select(int n, compat_ulong_t __user *inp, compat_ulong_t __user *outp
fd_set_bits fds;
char *bits;
long timeout;
- int ret, size, max_fdset;
+ int size, max_fdset, ret = -EINVAL;
timeout = MAX_SCHEDULE_TIMEOUT;
if (tvp) {
time_t sec, usec;
- if ((ret = verify_area(VERIFY_READ, tvp, sizeof(*tvp)))
- || (ret = __get_user(sec, &tvp->tv_sec))
- || (ret = __get_user(usec, &tvp->tv_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;
@@ -1641,7 +1642,6 @@ compat_sys_select(int n, compat_ulong_t __user *inp, compat_ulong_t __user *outp
}
}
- ret = -EINVAL;
if (n < 0)
goto out_nofds;
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c
index a14dc212e3017..155e612635f13 100644
--- a/fs/compat_ioctl.c
+++ b/fs/compat_ioctl.c
@@ -1281,35 +1281,9 @@ struct mtpos32 {
};
#define MTIOCPOS32 _IOR('m', 3, struct mtpos32)
-struct mtconfiginfo32 {
- compat_long_t mt_type;
- compat_long_t ifc_type;
- unsigned short irqnr;
- unsigned short dmanr;
- unsigned short port;
- compat_ulong_t debug;
- compat_uint_t have_dens:1;
- compat_uint_t have_bsf:1;
- compat_uint_t have_fsr:1;
- compat_uint_t have_bsr:1;
- compat_uint_t have_eod:1;
- compat_uint_t have_seek:1;
- compat_uint_t have_tell:1;
- compat_uint_t have_ras1:1;
- compat_uint_t have_ras2:1;
- compat_uint_t have_ras3:1;
- compat_uint_t have_qfa:1;
- compat_uint_t pad1:5;
- char reserved[10];
-};
-#define MTIOCGETCONFIG32 _IOR('m', 4, struct mtconfiginfo32)
-#define MTIOCSETCONFIG32 _IOW('m', 5, struct mtconfiginfo32)
-
static int mt_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
{
mm_segment_t old_fs = get_fs();
- struct mtconfiginfo info;
- struct mtconfiginfo32 __user *uinfo32;
struct mtget get;
struct mtget32 __user *umget32;
struct mtpos pos;
@@ -1327,27 +1301,6 @@ static int mt_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
kcmd = MTIOCGET;
karg = &get;
break;
- case MTIOCGETCONFIG32:
- kcmd = MTIOCGETCONFIG;
- karg = &info;
- break;
- case MTIOCSETCONFIG32:
- kcmd = MTIOCSETCONFIG;
- karg = &info;
- uinfo32 = compat_ptr(arg);
- err = __get_user(info.mt_type, &uinfo32->mt_type);
- err |= __get_user(info.ifc_type, &uinfo32->ifc_type);
- err |= __get_user(info.irqnr, &uinfo32->irqnr);
- err |= __get_user(info.dmanr, &uinfo32->dmanr);
- err |= __get_user(info.port, &uinfo32->port);
- err |= __get_user(info.debug, &uinfo32->debug);
- err |= __copy_from_user((char *)&info.debug
- + sizeof(info.debug),
- (char __user *)&uinfo32->debug
- + sizeof(uinfo32->debug), sizeof(__u32));
- if (err)
- return -EFAULT;
- break;
default:
do {
static int count;
@@ -1378,20 +1331,6 @@ static int mt_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
err |= __put_user(get.mt_fileno, &umget32->mt_fileno);
err |= __put_user(get.mt_blkno, &umget32->mt_blkno);
break;
- case MTIOCGETCONFIG32:
- uinfo32 = compat_ptr(arg);
- err = __put_user(info.mt_type, &uinfo32->mt_type);
- err |= __put_user(info.ifc_type, &uinfo32->ifc_type);
- err |= __put_user(info.irqnr, &uinfo32->irqnr);
- err |= __put_user(info.dmanr, &uinfo32->dmanr);
- err |= __put_user(info.port, &uinfo32->port);
- err |= __put_user(info.debug, &uinfo32->debug);
- err |= __copy_to_user((char __user *)&uinfo32->debug
- + sizeof(uinfo32->debug),
- (char *)&info.debug + sizeof(info.debug), sizeof(__u32));
- break;
- case MTIOCSETCONFIG32:
- break;
}
return err ? -EFAULT: 0;
}
@@ -1620,7 +1559,7 @@ static int do_fontx_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg,
get_user(data, &user_cfd->chardata))
return -EFAULT;
op.data = compat_ptr(data);
- return con_font_op(fg_console, &op);
+ return con_font_op(vc_cons[fg_console].d, &op);
case GIO_FONTX:
op.op = KD_FONT_OP_GET;
op.flags = 0;
@@ -1632,7 +1571,7 @@ static int do_fontx_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg,
if (!data)
return 0;
op.data = compat_ptr(data);
- i = con_font_op(fg_console, &op);
+ i = con_font_op(vc_cons[fg_console].d, &op);
if (i)
return i;
if (put_user(op.height, &user_cfd->charheight) ||
@@ -1658,7 +1597,7 @@ static int do_kdfontop_ioctl(unsigned int fd, unsigned int cmd, unsigned long ar
struct console_font_op op;
struct console_font_op32 __user *fontop = compat_ptr(arg);
int perm = vt_check(file), i;
- struct vt_struct *vt;
+ struct vc_data *vc;
if (perm < 0) return perm;
@@ -1668,9 +1607,10 @@ static int do_kdfontop_ioctl(unsigned int fd, unsigned int cmd, unsigned long ar
return -EPERM;
op.data = compat_ptr(((struct console_font_op32 *)&op)->data);
op.flags |= KD_FONT_FLAG_OLD;
- vt = (struct vt_struct *)((struct tty_struct *)file->private_data)->driver_data;
- i = con_font_op(vt->vc_num, &op);
- if (i) return i;
+ vc = ((struct tty_struct *)file->private_data)->driver_data;
+ i = con_font_op(vc, &op);
+ if (i)
+ return i;
((struct console_font_op32 *)&op)->data = (unsigned long)op.data;
if (copy_to_user(fontop, &op, sizeof(struct console_font_op32)))
return -EFAULT;
@@ -1694,9 +1634,9 @@ static int do_unimap_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg,
switch (cmd) {
case PIO_UNIMAP:
if (!perm) return -EPERM;
- return con_set_unimap(fg_console, tmp.entry_ct, compat_ptr(tmp.entries));
+ return con_set_unimap(vc_cons[fg_console].d, tmp.entry_ct, compat_ptr(tmp.entries));
case GIO_UNIMAP:
- return con_get_unimap(fg_console, tmp.entry_ct, &(user_ud->entry_ct), compat_ptr(tmp.entries));
+ return con_get_unimap(vc_cons[fg_console].d, tmp.entry_ct, &(user_ud->entry_ct), compat_ptr(tmp.entries));
}
return 0;
}
@@ -2342,11 +2282,8 @@ static int mtd_rw_oob(unsigned int fd, unsigned int cmd, unsigned long arg)
static long
put_dirent32 (struct dirent *d, struct compat_dirent __user *d32)
{
- int ret;
-
- if ((ret = verify_area(VERIFY_WRITE, d32,
- sizeof(struct compat_dirent))))
- return ret;
+ if (!access_ok(VERIFY_WRITE, d32, sizeof(struct compat_dirent)))
+ return -EFAULT;
__put_user(d->d_ino, &d32->d_ino);
__put_user(d->d_off, &d32->d_off);
@@ -2354,7 +2291,7 @@ put_dirent32 (struct dirent *d, struct compat_dirent __user *d32)
if (__copy_to_user(d32->d_name, d->d_name, d->d_reclen))
return -EFAULT;
- return ret;
+ return 0;
}
static int vfat_ioctl32(unsigned fd, unsigned cmd, unsigned long arg)
@@ -2405,9 +2342,8 @@ static int get_raw32_request(struct raw_config_request *req, struct raw32_config
{
int ret;
- if ((ret = verify_area(VERIFY_READ, user_req,
- sizeof(struct raw32_config_request))))
- return ret;
+ if (!access_ok(VERIFY_READ, user_req, sizeof(struct raw32_config_request)))
+ return -EFAULT;
ret = __get_user(req->raw_minor, &user_req->raw_minor);
ret |= __get_user(req->block_major, &user_req->block_major);
@@ -2420,9 +2356,8 @@ static int set_raw32_request(struct raw_config_request *req, struct raw32_config
{
int ret;
- if ((ret = verify_area(VERIFY_WRITE, user_req,
- sizeof(struct raw32_config_request))))
- return ret;
+ if (!access_ok(VERIFY_WRITE, user_req, sizeof(struct raw32_config_request)))
+ return -EFAULT;
ret = __put_user(req->raw_minor, &user_req->raw_minor);
ret |= __put_user(req->block_major, &user_req->block_major);
@@ -2494,7 +2429,7 @@ static int serial_struct_ioctl(unsigned fd, unsigned cmd, unsigned long arg)
__u32 udata;
if (cmd == TIOCSSERIAL) {
- if (verify_area(VERIFY_READ, ss32, sizeof(SS32)))
+ if (!access_ok(VERIFY_READ, ss32, sizeof(SS32)))
return -EFAULT;
if (__copy_from_user(&ss, ss32, offsetof(SS32, iomem_base)))
return -EFAULT;
@@ -2508,7 +2443,7 @@ static int serial_struct_ioctl(unsigned fd, unsigned cmd, unsigned long arg)
err = sys_ioctl(fd,cmd,(unsigned long)(&ss));
set_fs(oldseg);
if (cmd == TIOCGSERIAL && err >= 0) {
- if (verify_area(VERIFY_WRITE, ss32, sizeof(SS32)))
+ if (!access_ok(VERIFY_WRITE, ss32, sizeof(SS32)))
return -EFAULT;
if (__copy_to_user(ss32,&ss,offsetof(SS32,iomem_base)))
return -EFAULT;
@@ -2575,229 +2510,11 @@ static int do_usbdevfs_bulk(unsigned int fd, unsigned int cmd, unsigned long arg
return sys_ioctl(fd, USBDEVFS_BULK, (unsigned long)p);
}
-/* This needs more work before we can enable it. Unfortunately
- * because of the fancy asynchronous way URB status/error is written
- * back to userspace, we'll need to fiddle with USB devio internals
- * and/or reimplement entirely the frontend of it ourselves. -DaveM
- *
- * The issue is:
- *
- * When an URB is submitted via usbdevicefs it is put onto an
- * asynchronous queue. When the URB completes, it may be reaped
- * via another ioctl. During this reaping the status is written
- * back to userspace along with the length of the transfer.
- *
- * We must translate into 64-bit kernel types so we pass in a kernel
- * space copy of the usbdevfs_urb structure. This would mean that we
- * must do something to deal with the async entry reaping. First we
- * have to deal somehow with this transitory memory we've allocated.
- * This is problematic since there are many call sites from which the
- * async entries can be destroyed (and thus when we'd need to free up
- * this kernel memory). One of which is the close() op of usbdevicefs.
- * To handle that we'd need to make our own file_operations struct which
- * overrides usbdevicefs's release op with our own which runs usbdevicefs's
- * real release op then frees up the kernel memory.
- *
- * But how to keep track of these kernel buffers? We'd need to either
- * keep track of them in some table _or_ know about usbdevicefs internals
- * (ie. the exact layout of its file private, which is actually defined
- * in linux/usbdevice_fs.h, the layout of the async queues are private to
- * devio.c)
- *
- * There is one possible other solution I considered, also involving knowledge
- * of usbdevicefs internals:
- *
- * After an URB is submitted, we "fix up" the address back to the user
- * space one. This would work if the status/length fields written back
- * by the async URB completion lines up perfectly in the 32-bit type with
- * the 64-bit kernel type. Unfortunately, it does not because the iso
- * frame descriptors, at the end of the struct, can be written back.
- *
- * I think we'll just need to simply duplicate the devio URB engine here.
- */
-#if 0
-struct usbdevfs_urb32 {
- unsigned char type;
- unsigned char endpoint;
- compat_int_t status;
- compat_uint_t flags;
- compat_caddr_t buffer;
- compat_int_t buffer_length;
- compat_int_t actual_length;
- compat_int_t start_frame;
- compat_int_t number_of_packets;
- compat_int_t error_count;
- compat_uint_t signr;
- compat_caddr_t usercontext; /* unused */
- struct usbdevfs_iso_packet_desc iso_frame_desc[0];
-};
-
-#define USBDEVFS_SUBMITURB32 _IOR('U', 10, struct usbdevfs_urb32)
-
-static int get_urb32(struct usbdevfs_urb *kurb,
- struct usbdevfs_urb32 *uurb)
-{
- if (get_user(kurb->type, &uurb->type) ||
- __get_user(kurb->endpoint, &uurb->endpoint) ||
- __get_user(kurb->status, &uurb->status) ||
- __get_user(kurb->flags, &uurb->flags) ||
- __get_user(kurb->buffer_length, &uurb->buffer_length) ||
- __get_user(kurb->actual_length, &uurb->actual_length) ||
- __get_user(kurb->start_frame, &uurb->start_frame) ||
- __get_user(kurb->number_of_packets, &uurb->number_of_packets) ||
- __get_user(kurb->error_count, &uurb->error_count) ||
- __get_user(kurb->signr, &uurb->signr))
- return -EFAULT;
-
- kurb->usercontext = 0; /* unused currently */
-
- return 0;
-}
-
-/* Just put back the values which usbdevfs actually changes. */
-static int put_urb32(struct usbdevfs_urb *kurb,
- struct usbdevfs_urb32 *uurb)
-{
- if (put_user(kurb->status, &uurb->status) ||
- __put_user(kurb->actual_length, &uurb->actual_length) ||
- __put_user(kurb->error_count, &uurb->error_count))
- return -EFAULT;
-
- if (kurb->number_of_packets != 0) {
- int i;
-
- for (i = 0; i < kurb->number_of_packets; i++) {
- if (__put_user(kurb->iso_frame_desc[i].actual_length,
- &uurb->iso_frame_desc[i].actual_length) ||
- __put_user(kurb->iso_frame_desc[i].status,
- &uurb->iso_frame_desc[i].status))
- return -EFAULT;
- }
- }
-
- return 0;
-}
-
-static int get_urb32_isoframes(struct usbdevfs_urb *kurb,
- struct usbdevfs_urb32 *uurb)
-{
- unsigned int totlen;
- int i;
-
- if (kurb->type != USBDEVFS_URB_TYPE_ISO) {
- kurb->number_of_packets = 0;
- return 0;
- }
-
- if (kurb->number_of_packets < 1 ||
- kurb->number_of_packets > 128)
- return -EINVAL;
- if (copy_from_user(&kurb->iso_frame_desc[0],
- &uurb->iso_frame_desc[0],
- sizeof(struct usbdevfs_iso_packet_desc) *
- kurb->number_of_packets))
- return -EFAULT;
-
- totlen = 0;
- for (i = 0; i < kurb->number_of_packets; i++) {
- unsigned int this_len;
-
- this_len = kurb->iso_frame_desc[i].length;
- if (this_len > 1023)
- return -EINVAL;
-
- totlen += this_len;
- }
-
- if (totlen > 32768)
- return -EINVAL;
-
- kurb->buffer_length = totlen;
-
- return 0;
-}
-
-static int do_usbdevfs_urb(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
- struct usbdevfs_urb *kurb;
- struct usbdevfs_urb32 *uurb;
- mm_segment_t old_fs;
- __u32 udata;
- void *uptr, *kptr;
- unsigned int buflen;
- int err;
-
- uurb = compat_ptr(arg);
-
- err = -ENOMEM;
- kurb = kmalloc(sizeof(struct usbdevfs_urb) +
- (sizeof(struct usbdevfs_iso_packet_desc) * 128),
- GFP_KERNEL);
- if (!kurb)
- goto out;
-
- err = -EFAULT;
- if (get_urb32(kurb, uurb))
- goto out;
-
- err = get_urb32_isoframes(kurb, uurb);
- if (err)
- goto out;
-
- err = -EFAULT;
- if (__get_user(udata, &uurb->buffer))
- goto out;
- uptr = compat_ptr(udata);
-
- buflen = kurb->buffer_length;
- err = verify_area(VERIFY_WRITE, uptr, buflen);
- if (err)
- goto out;
-
-
- old_fs = get_fs();
- set_fs(KERNEL_DS);
- err = sys_ioctl(fd, USBDEVFS_SUBMITURB, (unsigned long) kurb);
- set_fs(old_fs);
-
- if (err >= 0) {
- /* RED-PEN Shit, this doesn't work for async URBs :-( XXX */
- if (put_urb32(kurb, uurb)) {
- err = -EFAULT;
- }
- }
-
-out:
- kfree(kurb);
- return err;
-}
-#endif
-
-#define USBDEVFS_REAPURB32 _IOW('U', 12, u32)
-#define USBDEVFS_REAPURBNDELAY32 _IOW('U', 13, u32)
-
-static int do_usbdevfs_reapurb(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
- mm_segment_t old_fs;
- void *kptr;
- int err;
-
- old_fs = get_fs();
- set_fs(KERNEL_DS);
- err = sys_ioctl(fd,
- (cmd == USBDEVFS_REAPURB32 ?
- USBDEVFS_REAPURB :
- USBDEVFS_REAPURBNDELAY),
- (unsigned long) &kptr);
- set_fs(old_fs);
-
- if (err >= 0 &&
- put_user((u32)(u64)kptr, (u32 __user *)compat_ptr(arg)))
- err = -EFAULT;
-
- return err;
-}
+/*
+ * USBDEVFS_SUBMITURB, USBDEVFS_REAPURB and USBDEVFS_REAPURBNDELAY
+ * are handled in usbdevfs core. -Christopher Li
+ */
struct usbdevfs_disconnectsignal32 {
compat_int_t signr;
@@ -2903,11 +2620,11 @@ static int do_i2c_smbus_ioctl(unsigned int fd, unsigned int cmd, unsigned long a
tdata = compat_alloc_user_space(sizeof(*tdata));
if (tdata == NULL)
return -ENOMEM;
- if (verify_area(VERIFY_WRITE, tdata, sizeof(*tdata)))
+ if (!access_ok(VERIFY_WRITE, tdata, sizeof(*tdata)))
return -EFAULT;
udata = compat_ptr(arg);
- if (verify_area(VERIFY_READ, udata, sizeof(*udata)))
+ if (!access_ok(VERIFY_READ, udata, sizeof(*udata)))
return -EFAULT;
if (__copy_in_user(&tdata->read_write, &udata->read_write, 2 * sizeof(u8)))
@@ -2944,7 +2661,7 @@ static int do_wireless_ioctl(unsigned int fd, unsigned int cmd, unsigned long ar
iwp = &iwr->u.data;
- if (verify_area(VERIFY_WRITE, iwr, sizeof(*iwr)))
+ if (!access_ok(VERIFY_WRITE, iwr, sizeof(*iwr)))
return -EFAULT;
if (__copy_in_user(&iwr->ifr_ifrn.ifrn_name[0],
@@ -3259,8 +2976,6 @@ HANDLE_IOCTL(PPPIOCSPASS32, ppp_sock_fprog_ioctl_trans)
HANDLE_IOCTL(PPPIOCSACTIVE32, ppp_sock_fprog_ioctl_trans)
HANDLE_IOCTL(MTIOCGET32, mt_ioctl_trans)
HANDLE_IOCTL(MTIOCPOS32, mt_ioctl_trans)
-HANDLE_IOCTL(MTIOCGETCONFIG32, mt_ioctl_trans)
-HANDLE_IOCTL(MTIOCSETCONFIG32, mt_ioctl_trans)
HANDLE_IOCTL(CDROMREADAUDIO, cdrom_ioctl_trans)
HANDLE_IOCTL(CDROM_SEND_PACKET, cdrom_ioctl_trans)
HANDLE_IOCTL(LOOP_SET_STATUS, loop_status)
@@ -3331,9 +3046,6 @@ HANDLE_IOCTL(TIOCSSERIAL, serial_struct_ioctl)
/* Usbdevfs */
HANDLE_IOCTL(USBDEVFS_CONTROL32, do_usbdevfs_control)
HANDLE_IOCTL(USBDEVFS_BULK32, do_usbdevfs_bulk)
-/*HANDLE_IOCTL(USBDEVFS_SUBMITURB32, do_usbdevfs_urb)*/
-HANDLE_IOCTL(USBDEVFS_REAPURB32, do_usbdevfs_reapurb)
-HANDLE_IOCTL(USBDEVFS_REAPURBNDELAY32, do_usbdevfs_reapurb)
HANDLE_IOCTL(USBDEVFS_DISCSIGNAL32, do_usbdevfs_discsignal)
/* i2c */
HANDLE_IOCTL(I2C_FUNCS, w_long)
diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c
index 23099366a8884..6c285efa20043 100644
--- a/fs/cramfs/inode.c
+++ b/fs/cramfs/inode.c
@@ -70,6 +70,7 @@ static struct inode *get_cramfs_inode(struct super_block *sb, struct cramfs_inod
inode->i_data.a_ops = &cramfs_aops;
} else {
inode->i_size = 0;
+ inode->i_blocks = 0;
init_special_inode(inode, inode->i_mode,
old_decode_dev(cramfs_inode->size));
}
diff --git a/fs/dcache.c b/fs/dcache.c
index ed90b724af788..496a4e08369c4 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -36,6 +36,7 @@
/* #define DCACHE_DEBUG 1 */
int sysctl_vfs_cache_pressure = 100;
+EXPORT_SYMBOL_GPL(sysctl_vfs_cache_pressure);
__cacheline_aligned_in_smp DEFINE_SPINLOCK(dcache_lock);
seqlock_t rename_lock __cacheline_aligned_in_smp = SEQLOCK_UNLOCKED;
@@ -340,13 +341,16 @@ restart:
tmp = head;
while ((tmp = tmp->next) != head) {
struct dentry *dentry = list_entry(tmp, struct dentry, d_alias);
+ spin_lock(&dentry->d_lock);
if (!atomic_read(&dentry->d_count)) {
__dget_locked(dentry);
__d_drop(dentry);
+ spin_unlock(&dentry->d_lock);
spin_unlock(&dcache_lock);
dput(dentry);
goto restart;
}
+ spin_unlock(&dentry->d_lock);
}
spin_unlock(&dcache_lock);
}
@@ -1529,7 +1533,6 @@ int is_subdir(struct dentry * new_dentry, struct dentry * old_dentry)
struct dentry * saved = new_dentry;
unsigned long seq;
- result = 0;
/* need rcu_readlock to protect against the d_parent trashing due to
* d_move
*/
@@ -1537,6 +1540,7 @@ int is_subdir(struct dentry * new_dentry, struct dentry * old_dentry)
do {
/* for restarting inner loop in case of seq retry */
new_dentry = saved;
+ result = 0;
seq = read_seqbegin(&rename_lock);
for (;;) {
if (new_dentry != old_dentry) {
diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c
index 1e105f916fc0c..548556ff25060 100644
--- a/fs/debugfs/file.c
+++ b/fs/debugfs/file.c
@@ -52,7 +52,7 @@ static ssize_t read_file_##type(struct file *file, char __user *user_buf, \
char buf[32]; \
type *val = file->private_data; \
\
- snprintf(buf, sizeof(buf), format, *val); \
+ snprintf(buf, sizeof(buf), format "\n", *val); \
return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));\
} \
static ssize_t write_file_##type(struct file *file, const char __user *user_buf,\
@@ -186,7 +186,7 @@ static ssize_t read_file_bool(struct file *file, char __user *user_buf,
char buf[3];
u32 *val = file->private_data;
- if (val)
+ if (*val)
buf[0] = 'Y';
else
buf[0] = 'N';
diff --git a/fs/direct-io.c b/fs/direct-io.c
index 283268396a157..5a674a0c71461 100644
--- a/fs/direct-io.c
+++ b/fs/direct-io.c
@@ -1206,7 +1206,8 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
*/
dio->lock_type = dio_lock_type;
if (dio_lock_type != DIO_NO_LOCKING) {
- if (rw == READ) {
+ /* watch out for a 0 len io from a tricksy fs */
+ if (rw == READ && end > offset) {
struct address_space *mapping;
mapping = iocb->ki_filp->f_mapping;
@@ -1214,7 +1215,9 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
down(&inode->i_sem);
reader_with_isem = 1;
}
- retval = filemap_write_and_wait(mapping);
+
+ retval = filemap_write_and_wait_range(mapping, offset,
+ end - 1);
if (retval) {
kfree(dio);
goto out;
diff --git a/fs/dquot.c b/fs/dquot.c
index 478a86e657ebe..11048e0b32c92 100644
--- a/fs/dquot.c
+++ b/fs/dquot.c
@@ -505,14 +505,12 @@ static void prune_dqcache(int count)
static int shrink_dqcache_memory(int nr, unsigned int gfp_mask)
{
- int ret;
-
- spin_lock(&dq_list_lock);
- if (nr)
+ if (nr) {
+ spin_lock(&dq_list_lock);
prune_dqcache(nr);
- ret = dqstats.allocated_dquots;
- spin_unlock(&dq_list_lock);
- return ret;
+ spin_unlock(&dq_list_lock);
+ }
+ return (dqstats.free_dquots / 100) * sysctl_vfs_cache_pressure;
}
/*
@@ -1092,7 +1090,7 @@ warn_put_all:
}
/*
- * This is a non-blocking operation.
+ * This operation can block, but only after everything is updated
*/
int dquot_free_space(struct inode *inode, qsize_t number)
{
@@ -1128,7 +1126,7 @@ out_sub:
}
/*
- * This is a non-blocking operation.
+ * This operation can block, but only after everything is updated
*/
int dquot_free_inode(const struct inode *inode, unsigned long number)
{
@@ -1163,6 +1161,7 @@ int dquot_free_inode(const struct inode *inode, unsigned long number)
* Transfer the number of inode and blocks from one diskquota to an other.
*
* This operation can block, but only after everything is updated
+ * A transaction must be started when entering this function.
*/
int dquot_transfer(struct inode *inode, struct iattr *iattr)
{
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index b11ab1a9ceeed..05b966cd6f769 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -619,6 +619,7 @@ eexit_1:
return error;
}
+#define MAX_EVENTS (INT_MAX / sizeof(struct epoll_event))
/*
* Implement the event wait interface for the eventpoll file. It is the kernel
@@ -635,12 +636,14 @@ asmlinkage long sys_epoll_wait(int epfd, struct epoll_event __user *events,
current, epfd, events, maxevents, timeout));
/* The maximum number of event must be greater than zero */
- if (maxevents <= 0)
+ if (maxevents <= 0 || maxevents > MAX_EVENTS)
return -EINVAL;
/* Verify that the area passed by the user is writeable */
- if ((error = verify_area(VERIFY_WRITE, events, maxevents * sizeof(struct epoll_event))))
+ if (!access_ok(VERIFY_WRITE, events, maxevents * sizeof(struct epoll_event))) {
+ error = -EFAULT;
goto eexit_1;
+ }
/* Get the "struct file *" for the eventpoll file */
error = -EBADF;
diff --git a/fs/exec.c b/fs/exec.c
index ee58e91a9d7f4..a8394499926cd 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -326,9 +326,9 @@ void install_arg_page(struct vm_area_struct *vma,
pte_unmap(pte);
goto out;
}
- mm->rss++;
+ inc_mm_counter(mm, rss);
lru_cache_add_active(page);
- set_pte(pte, pte_mkdirty(pte_mkwrite(mk_pte(
+ set_pte_at(mm, address, pte, pte_mkdirty(pte_mkwrite(mk_pte(
page, vma->vm_page_prot))));
page_add_anon_rmap(page, vma, address);
pte_unmap(pte);
@@ -400,7 +400,8 @@ int setup_arg_pages(struct linux_binprm *bprm,
while (i < MAX_ARG_PAGES)
bprm->page[i++] = NULL;
#else
- stack_base = stack_top - MAX_ARG_PAGES * PAGE_SIZE;
+ stack_base = arch_align_stack(stack_top - MAX_ARG_PAGES*PAGE_SIZE);
+ stack_base = PAGE_ALIGN(stack_base);
bprm->p += stack_base;
mm->arg_start = bprm->p;
arg_size = stack_top - (PAGE_MASK & (unsigned long) mm->arg_start);
@@ -814,7 +815,7 @@ void get_task_comm(char *buf, struct task_struct *tsk)
{
/* buf must be at least sizeof(tsk->comm) in size */
task_lock(tsk);
- memcpy(buf, tsk->comm, sizeof(tsk->comm));
+ strncpy(buf, tsk->comm, sizeof(tsk->comm));
task_unlock(tsk);
}
@@ -877,6 +878,7 @@ int flush_old_exec(struct linux_binprm * bprm)
tcomm[i] = '\0';
set_task_comm(current, tcomm);
+ current->flags &= ~PF_RANDOMIZE;
flush_thread();
if (bprm->e_uid != current->euid || bprm->e_gid != current->egid ||
@@ -1191,8 +1193,8 @@ int do_execve(char * filename,
/* execve success */
security_bprm_free(bprm);
- acct_update_integrals();
- update_mem_hiwater();
+ acct_update_integrals(current);
+ update_mem_hiwater(current);
kfree(bprm);
return retval;
}
diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c
index 0a6f7b06b8d79..c49d6254379aa 100644
--- a/fs/exportfs/expfs.c
+++ b/fs/exportfs/expfs.c
@@ -55,7 +55,7 @@ find_exported_dentry(struct super_block *sb, void *obj, void *parent,
struct list_head *le, *head;
struct dentry *toput = NULL;
int noprogress;
-
+ char nbuf[NAME_MAX+1];
/*
* Attempt to find the inode.
@@ -176,7 +176,6 @@ find_exported_dentry(struct super_block *sb, void *obj, void *parent,
*/
struct dentry *ppd;
struct dentry *npd;
- char nbuf[NAME_MAX+1];
down(&pd->d_inode->i_sem);
ppd = CALL(nops,get_parent)(pd);
@@ -241,7 +240,6 @@ find_exported_dentry(struct super_block *sb, void *obj, void *parent,
/* if we weren't after a directory, have one more step to go */
if (result != target_dir) {
struct dentry *nresult;
- char nbuf[NAME_MAX+1];
err = CALL(nops,get_name)(target_dir, nbuf, result);
if (!err) {
down(&target_dir->d_inode->i_sem);
diff --git a/fs/ext2/dir.c b/fs/ext2/dir.c
index e009152297a64..5b5f52876b427 100644
--- a/fs/ext2/dir.c
+++ b/fs/ext2/dir.c
@@ -592,6 +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);
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/inode.c b/fs/ext2/inode.c
index e10be1afeacbc..b890be0224963 100644
--- a/fs/ext2/inode.c
+++ b/fs/ext2/inode.c
@@ -626,6 +626,12 @@ ext2_nobh_prepare_write(struct file *file, struct page *page,
return nobh_prepare_write(page,from,to,ext2_get_block);
}
+static int ext2_nobh_writepage(struct page *page,
+ struct writeback_control *wbc)
+{
+ return nobh_writepage(page, ext2_get_block, wbc);
+}
+
static sector_t ext2_bmap(struct address_space *mapping, sector_t block)
{
return generic_block_bmap(mapping,block,ext2_get_block);
@@ -675,7 +681,7 @@ struct address_space_operations ext2_aops = {
struct address_space_operations ext2_nobh_aops = {
.readpage = ext2_readpage,
.readpages = ext2_readpages,
- .writepage = ext2_writepage,
+ .writepage = ext2_nobh_writepage,
.sync_page = block_sync_page,
.prepare_write = ext2_nobh_prepare_write,
.commit_write = nobh_commit_write,
diff --git a/fs/ext2/super.c b/fs/ext2/super.c
index 1d0e117095110..37ca77a157ba5 100644
--- a/fs/ext2/super.c
+++ b/fs/ext2/super.c
@@ -518,12 +518,18 @@ static int ext2_check_descriptors (struct super_block * sb)
static loff_t ext2_max_size(int bits)
{
loff_t res = EXT2_NDIR_BLOCKS;
+ /* This constant is calculated to be the largest file size for a
+ * dense, 4k-blocksize file such that the total number of
+ * sectors in the file, including data and all indirect blocks,
+ * does not exceed 2^32. */
+ const loff_t upper_limit = 0x1ff7fffd000LL;
+
res += 1LL << (bits-2);
res += 1LL << (2*(bits-2));
res += 1LL << (3*(bits-2));
res <<= bits;
- if (res > (512LL << 32) - (1 << bits))
- res = (512LL << 32) - (1 << bits);
+ if (res > upper_limit)
+ res = upper_limit;
return res;
}
diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c
index 03cd803e0b28a..6a18447e9dd7f 100644
--- a/fs/ext3/balloc.c
+++ b/fs/ext3/balloc.c
@@ -43,34 +43,34 @@ struct ext3_group_desc * ext3_get_group_desc(struct super_block * sb,
struct buffer_head ** bh)
{
unsigned long group_desc;
- unsigned long desc;
- struct ext3_group_desc * gdp;
+ unsigned long offset;
+ struct ext3_group_desc * desc;
+ struct ext3_sb_info *sbi = EXT3_SB(sb);
- if (block_group >= EXT3_SB(sb)->s_groups_count) {
+ if (block_group >= sbi->s_groups_count) {
ext3_error (sb, "ext3_get_group_desc",
"block_group >= groups_count - "
"block_group = %d, groups_count = %lu",
- block_group, EXT3_SB(sb)->s_groups_count);
+ block_group, sbi->s_groups_count);
return NULL;
}
smp_rmb();
group_desc = block_group >> EXT3_DESC_PER_BLOCK_BITS(sb);
- desc = block_group & (EXT3_DESC_PER_BLOCK(sb) - 1);
- if (!EXT3_SB(sb)->s_group_desc[group_desc]) {
+ offset = block_group & (EXT3_DESC_PER_BLOCK(sb) - 1);
+ if (!sbi->s_group_desc[group_desc]) {
ext3_error (sb, "ext3_get_group_desc",
"Group descriptor not loaded - "
"block_group = %d, group_desc = %lu, desc = %lu",
- block_group, group_desc, desc);
+ block_group, group_desc, offset);
return NULL;
}
- gdp = (struct ext3_group_desc *)
- EXT3_SB(sb)->s_group_desc[group_desc]->b_data;
+ desc = (struct ext3_group_desc *) sbi->s_group_desc[group_desc]->b_data;
if (bh)
- *bh = EXT3_SB(sb)->s_group_desc[group_desc];
- return gdp + desc;
+ *bh = sbi->s_group_desc[group_desc];
+ return desc + offset;
}
/*
@@ -268,7 +268,8 @@ void ext3_discard_reservation(struct inode *inode)
if (!rsv_is_empty(&rsv->rsv_window)) {
spin_lock(rsv_lock);
- rsv_window_remove(inode->i_sb, rsv);
+ if (!rsv_is_empty(&rsv->rsv_window))
+ rsv_window_remove(inode->i_sb, rsv);
spin_unlock(rsv_lock);
}
}
@@ -284,14 +285,15 @@ void ext3_free_blocks_sb(handle_t *handle, struct super_block *sb,
unsigned long bit;
unsigned long i;
unsigned long overflow;
- struct ext3_group_desc * gdp;
+ struct ext3_group_desc * desc;
struct ext3_super_block * es;
struct ext3_sb_info *sbi;
int err = 0, ret;
+ unsigned group_freed;
*pdquot_freed_blocks = 0;
sbi = EXT3_SB(sb);
- es = EXT3_SB(sb)->s_es;
+ es = sbi->s_es;
if (block < le32_to_cpu(es->s_first_data_block) ||
block + count < block ||
block + count > le32_to_cpu(es->s_blocks_count)) {
@@ -301,7 +303,7 @@ void ext3_free_blocks_sb(handle_t *handle, struct super_block *sb,
goto error_return;
}
- ext3_debug ("freeing block %lu\n", block);
+ ext3_debug ("freeing block(s) %lu-%lu\n", block, block + count - 1);
do_more:
overflow = 0;
@@ -321,16 +323,16 @@ do_more:
bitmap_bh = read_block_bitmap(sb, block_group);
if (!bitmap_bh)
goto error_return;
- gdp = ext3_get_group_desc (sb, block_group, &gd_bh);
- if (!gdp)
+ desc = ext3_get_group_desc (sb, block_group, &gd_bh);
+ if (!desc)
goto error_return;
- if (in_range (le32_to_cpu(gdp->bg_block_bitmap), block, count) ||
- in_range (le32_to_cpu(gdp->bg_inode_bitmap), block, count) ||
- in_range (block, le32_to_cpu(gdp->bg_inode_table),
- EXT3_SB(sb)->s_itb_per_group) ||
- in_range (block + count - 1, le32_to_cpu(gdp->bg_inode_table),
- EXT3_SB(sb)->s_itb_per_group))
+ if (in_range (le32_to_cpu(desc->bg_block_bitmap), block, count) ||
+ in_range (le32_to_cpu(desc->bg_inode_bitmap), block, count) ||
+ in_range (block, le32_to_cpu(desc->bg_inode_table),
+ sbi->s_itb_per_group) ||
+ in_range (block + count - 1, le32_to_cpu(desc->bg_inode_table),
+ sbi->s_itb_per_group))
ext3_error (sb, "ext3_free_blocks",
"Freeing blocks in system zones - "
"Block = %lu, count = %lu",
@@ -342,7 +344,7 @@ do_more:
*/
/* @@@ check errors */
BUFFER_TRACE(bitmap_bh, "getting undo access");
- err = ext3_journal_get_undo_access(handle, bitmap_bh, NULL);
+ err = ext3_journal_get_undo_access(handle, bitmap_bh);
if (err)
goto error_return;
@@ -358,7 +360,7 @@ do_more:
jbd_lock_bh_state(bitmap_bh);
- for (i = 0; i < count; i++) {
+ for (i = 0, group_freed = 0; i < count; i++) {
/*
* An HJ special. This is expensive...
*/
@@ -421,15 +423,15 @@ do_more:
jbd_lock_bh_state(bitmap_bh);
BUFFER_TRACE(bitmap_bh, "bit already cleared");
} else {
- (*pdquot_freed_blocks)++;
+ group_freed++;
}
}
jbd_unlock_bh_state(bitmap_bh);
spin_lock(sb_bgl_lock(sbi, block_group));
- gdp->bg_free_blocks_count =
- cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count) +
- *pdquot_freed_blocks);
+ desc->bg_free_blocks_count =
+ cpu_to_le16(le16_to_cpu(desc->bg_free_blocks_count) +
+ group_freed);
spin_unlock(sb_bgl_lock(sbi, block_group));
percpu_counter_mod(&sbi->s_freeblocks_counter, count);
@@ -441,6 +443,7 @@ do_more:
BUFFER_TRACE(gd_bh, "dirtied group descriptor block");
ret = ext3_journal_dirty_metadata(handle, gd_bh);
if (!err) err = ret;
+ *pdquot_freed_blocks += group_freed;
if (overflow && !err) {
block += count;
@@ -991,7 +994,6 @@ ext3_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle,
unsigned long group_first_block;
int ret = 0;
int fatal;
- int credits = 0;
*errp = 0;
@@ -1001,7 +1003,7 @@ ext3_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle,
* if the buffer is in BJ_Forget state in the committing transaction.
*/
BUFFER_TRACE(bitmap_bh, "get undo access for new block");
- fatal = ext3_journal_get_undo_access(handle, bitmap_bh, &credits);
+ fatal = ext3_journal_get_undo_access(handle, bitmap_bh);
if (fatal) {
*errp = fatal;
return -1;
@@ -1092,7 +1094,7 @@ out:
}
BUFFER_TRACE(bitmap_bh, "journal_release_buffer");
- ext3_journal_release_buffer(handle, bitmap_bh, credits);
+ ext3_journal_release_buffer(handle, bitmap_bh);
return ret;
}
@@ -1429,9 +1431,8 @@ unsigned long ext3_count_free_blocks(struct super_block *sb)
#endif
}
-static inline int block_in_use(unsigned long block,
- struct super_block * sb,
- unsigned char * map)
+static inline int
+block_in_use(unsigned long block, struct super_block *sb, unsigned char *map)
{
return ext3_test_bit ((block -
le32_to_cpu(EXT3_SB(sb)->s_es->s_first_data_block)) %
@@ -1451,8 +1452,10 @@ static int ext3_group_sparse(int group)
{
if (group <= 1)
return 1;
- return (test_root(group, 3) || test_root(group, 5) ||
- test_root(group, 7));
+ if (!(group & 1))
+ return 0;
+ return (test_root(group, 7) || test_root(group, 5) ||
+ test_root(group, 3));
}
/**
diff --git a/fs/ext3/hash.c b/fs/ext3/hash.c
index f3780279f5c50..5a2d1235ead01 100644
--- a/fs/ext3/hash.c
+++ b/fs/ext3/hash.c
@@ -13,6 +13,7 @@
#include <linux/jbd.h>
#include <linux/sched.h>
#include <linux/ext3_fs.h>
+#include <linux/cryptohash.h>
#define DELTA 0x9E3779B9
@@ -33,73 +34,6 @@ static void TEA_transform(__u32 buf[4], __u32 const in[])
buf[1] += b1;
}
-/* F, G and H are basic MD4 functions: selection, majority, parity */
-#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
-#define G(x, y, z) (((x) & (y)) + (((x) ^ (y)) & (z)))
-#define H(x, y, z) ((x) ^ (y) ^ (z))
-
-/*
- * The generic round function. The application is so specific that
- * we don't bother protecting all the arguments with parens, as is generally
- * good macro practice, in favor of extra legibility.
- * Rotation is separate from addition to prevent recomputation
- */
-#define ROUND(f, a, b, c, d, x, s) \
- (a += f(b, c, d) + x, a = (a << s) | (a >> (32-s)))
-#define K1 0
-#define K2 013240474631UL
-#define K3 015666365641UL
-
-/*
- * Basic cut-down MD4 transform. Returns only 32 bits of result.
- */
-static void halfMD4Transform (__u32 buf[4], __u32 const in[])
-{
- __u32 a = buf[0], b = buf[1], c = buf[2], d = buf[3];
-
- /* Round 1 */
- ROUND(F, a, b, c, d, in[0] + K1, 3);
- ROUND(F, d, a, b, c, in[1] + K1, 7);
- ROUND(F, c, d, a, b, in[2] + K1, 11);
- ROUND(F, b, c, d, a, in[3] + K1, 19);
- ROUND(F, a, b, c, d, in[4] + K1, 3);
- ROUND(F, d, a, b, c, in[5] + K1, 7);
- ROUND(F, c, d, a, b, in[6] + K1, 11);
- ROUND(F, b, c, d, a, in[7] + K1, 19);
-
- /* Round 2 */
- ROUND(G, a, b, c, d, in[1] + K2, 3);
- ROUND(G, d, a, b, c, in[3] + K2, 5);
- ROUND(G, c, d, a, b, in[5] + K2, 9);
- ROUND(G, b, c, d, a, in[7] + K2, 13);
- ROUND(G, a, b, c, d, in[0] + K2, 3);
- ROUND(G, d, a, b, c, in[2] + K2, 5);
- ROUND(G, c, d, a, b, in[4] + K2, 9);
- ROUND(G, b, c, d, a, in[6] + K2, 13);
-
- /* Round 3 */
- ROUND(H, a, b, c, d, in[3] + K3, 3);
- ROUND(H, d, a, b, c, in[7] + K3, 9);
- ROUND(H, c, d, a, b, in[2] + K3, 11);
- ROUND(H, b, c, d, a, in[6] + K3, 15);
- ROUND(H, a, b, c, d, in[1] + K3, 3);
- ROUND(H, d, a, b, c, in[5] + K3, 9);
- ROUND(H, c, d, a, b, in[0] + K3, 11);
- ROUND(H, b, c, d, a, in[4] + K3, 15);
-
- buf[0] += a;
- buf[1] += b;
- buf[2] += c;
- buf[3] += d;
-}
-
-#undef ROUND
-#undef F
-#undef G
-#undef H
-#undef K1
-#undef K2
-#undef K3
/* The old legacy hash */
static __u32 dx_hack_hash (const char *name, int len)
@@ -187,7 +121,7 @@ int ext3fs_dirhash(const char *name, int len, struct dx_hash_info *hinfo)
p = name;
while (len > 0) {
str2hashbuf(p, len, in, 8);
- halfMD4Transform(buf, in);
+ half_md4_transform(buf, in);
len -= 32;
p += 32;
}
diff --git a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c
index 3ec7af54e51ed..121ecbe1039e8 100644
--- a/fs/ext3/ialloc.c
+++ b/fs/ext3/ialloc.c
@@ -460,9 +460,12 @@ struct inode *ext3_new_inode(handle_t *handle, struct inode * dir, int mode)
goto out;
for (i = 0; i < sbi->s_groups_count; i++) {
+ err = -EIO;
+
gdp = ext3_get_group_desc(sb, group, &bh2);
+ if (!gdp)
+ goto fail;
- err = -EIO;
brelse(bitmap_bh);
bitmap_bh = read_inode_bitmap(sb, group);
if (!bitmap_bh)
@@ -474,11 +477,9 @@ repeat_in_this_group:
ino = ext3_find_next_zero_bit((unsigned long *)
bitmap_bh->b_data, EXT3_INODES_PER_GROUP(sb), ino);
if (ino < EXT3_INODES_PER_GROUP(sb)) {
- int credits = 0;
BUFFER_TRACE(bitmap_bh, "get_write_access");
- err = ext3_journal_get_write_access_credits(handle,
- bitmap_bh, &credits);
+ err = ext3_journal_get_write_access(handle, bitmap_bh);
if (err)
goto fail;
@@ -494,7 +495,7 @@ repeat_in_this_group:
goto got;
}
/* we lost it */
- journal_release_buffer(handle, bitmap_bh, credits);
+ journal_release_buffer(handle, bitmap_bh);
if (++ino < EXT3_INODES_PER_GROUP(sb))
goto repeat_in_this_group;
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index 01fae128a1fe7..05be496c892f1 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -858,6 +858,12 @@ get_block:
return ret;
}
+static int ext3_writepages_get_block(struct inode *inode, sector_t iblock,
+ struct buffer_head *bh, int create)
+{
+ return ext3_direct_io_get_blocks(inode, iblock, 1, bh, create);
+}
+
/*
* `handle' can be NULL if create is zero
*/
@@ -1010,7 +1016,10 @@ retry:
ret = PTR_ERR(handle);
goto out;
}
- ret = block_prepare_write(page, from, to, ext3_get_block);
+ if (test_opt(inode->i_sb, NOBH))
+ ret = nobh_prepare_write(page, from, to, ext3_get_block);
+ else
+ ret = block_prepare_write(page, from, to, ext3_get_block);
if (ret)
goto prepare_write_failed;
@@ -1094,7 +1103,12 @@ static int ext3_writeback_commit_write(struct file *file, struct page *page,
new_i_size = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
if (new_i_size > EXT3_I(inode)->i_disksize)
EXT3_I(inode)->i_disksize = new_i_size;
- ret = generic_commit_write(file, page, from, to);
+
+ if (test_opt(inode->i_sb, NOBH))
+ ret = nobh_commit_write(file, page, from, to);
+ else
+ ret = generic_commit_write(file, page, from, to);
+
ret2 = ext3_journal_stop(handle);
if (!ret)
ret = ret2;
@@ -1323,6 +1337,45 @@ out_fail:
return ret;
}
+static int
+ext3_writeback_writepage_helper(struct page *page,
+ struct writeback_control *wbc)
+{
+ return block_write_full_page(page, ext3_get_block, wbc);
+}
+
+static int
+ext3_writeback_writepages(struct address_space *mapping,
+ struct writeback_control *wbc)
+{
+ struct inode *inode = mapping->host;
+ handle_t *handle = NULL;
+ int err, ret = 0;
+
+ if (!mapping_tagged(mapping, PAGECACHE_TAG_DIRTY))
+ return ret;
+
+ handle = ext3_journal_start(inode, ext3_writepage_trans_blocks(inode));
+ if (IS_ERR(handle)) {
+ ret = PTR_ERR(handle);
+ return ret;
+ }
+
+ ret = __mpage_writepages(mapping, wbc, ext3_writepages_get_block,
+ ext3_writeback_writepage_helper);
+
+ /*
+ * Need to reaquire the handle since ext3_writepages_get_block()
+ * can restart the handle
+ */
+ handle = journal_current_handle();
+
+ err = ext3_journal_stop(handle);
+ if (!ret)
+ ret = err;
+ return ret;
+}
+
static int ext3_writeback_writepage(struct page *page,
struct writeback_control *wbc)
{
@@ -1340,7 +1393,11 @@ static int ext3_writeback_writepage(struct page *page,
goto out_fail;
}
- ret = block_write_full_page(page, ext3_get_block, wbc);
+ if (test_opt(inode->i_sb, NOBH))
+ ret = nobh_writepage(page, ext3_get_block, wbc);
+ else
+ ret = block_write_full_page(page, ext3_get_block, wbc);
+
err = ext3_journal_stop(handle);
if (!ret)
ret = err;
@@ -1439,6 +1496,8 @@ static int ext3_releasepage(struct page *page, int wait)
journal_t *journal = EXT3_JOURNAL(page->mapping->host);
WARN_ON(PageChecked(page));
+ if (!page_has_buffers(page))
+ return 0;
return journal_try_to_free_buffers(journal, page, wait);
}
@@ -1554,6 +1613,7 @@ static struct address_space_operations ext3_writeback_aops = {
.readpage = ext3_readpage,
.readpages = ext3_readpages,
.writepage = ext3_writeback_writepage,
+ .writepages = ext3_writeback_writepages,
.sync_page = block_sync_page,
.prepare_write = ext3_prepare_write,
.commit_write = ext3_writeback_commit_write,
@@ -1600,13 +1660,28 @@ static int ext3_block_truncate_page(handle_t *handle, struct page *page,
unsigned blocksize, iblock, length, pos;
struct inode *inode = mapping->host;
struct buffer_head *bh;
- int err;
+ int err = 0;
void *kaddr;
blocksize = inode->i_sb->s_blocksize;
length = blocksize - (offset & (blocksize - 1));
iblock = index << (PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits);
+ /*
+ * For "nobh" option, we can only work if we don't need to
+ * read-in the page - otherwise we create buffers to do the IO.
+ */
+ if (!page_has_buffers(page) && test_opt(inode->i_sb, NOBH)) {
+ if (PageUptodate(page)) {
+ kaddr = kmap_atomic(page, KM_USER0);
+ memset(kaddr + offset, 0, length);
+ flush_dcache_page(page);
+ kunmap_atomic(kaddr, KM_USER0);
+ set_page_dirty(page);
+ goto unlock;
+ }
+ }
+
if (!page_has_buffers(page))
create_empty_buffers(page, blocksize, 0);
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index aa0f1b545bb6a..34288e100d957 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -576,7 +576,7 @@ enum {
Opt_resgid, Opt_resuid, Opt_sb, Opt_err_cont, Opt_err_panic, Opt_err_ro,
Opt_nouid32, Opt_check, Opt_nocheck, Opt_debug, Opt_oldalloc, Opt_orlov,
Opt_user_xattr, Opt_nouser_xattr, Opt_acl, Opt_noacl,
- Opt_reservation, Opt_noreservation, Opt_noload,
+ Opt_reservation, Opt_noreservation, Opt_noload, Opt_nobh,
Opt_commit, Opt_journal_update, Opt_journal_inum,
Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback,
Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota,
@@ -611,6 +611,7 @@ static match_table_t tokens = {
{Opt_reservation, "reservation"},
{Opt_noreservation, "noreservation"},
{Opt_noload, "noload"},
+ {Opt_nobh, "nobh"},
{Opt_commit, "commit=%u"},
{Opt_journal_update, "journal=update"},
{Opt_journal_inum, "journal=%u"},
@@ -924,6 +925,9 @@ clear_qf_name:
match_int(&args[0], &option);
*n_blocks_count = option;
break;
+ case Opt_nobh:
+ set_opt(sbi->s_mount_opt, NOBH);
+ break;
default:
printk (KERN_ERR
"EXT3-fs: Unrecognized mount option \"%s\" "
@@ -1193,12 +1197,18 @@ static void ext3_orphan_cleanup (struct super_block * sb,
static loff_t ext3_max_size(int bits)
{
loff_t res = EXT3_NDIR_BLOCKS;
+ /* This constant is calculated to be the largest file size for a
+ * dense, 4k-blocksize file such that the total number of
+ * sectors in the file, including data and all indirect blocks,
+ * does not exceed 2^32. */
+ const loff_t upper_limit = 0x1ff7fffd000LL;
+
res += 1LL << (bits-2);
res += 1LL << (2*(bits-2));
res += 1LL << (3*(bits-2));
res <<= bits;
- if (res > (512LL << 32) - (1 << bits))
- res = (512LL << 32) - (1 << bits);
+ if (res > upper_limit)
+ res = upper_limit;
return res;
}
@@ -1563,6 +1573,19 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
break;
}
+ if (test_opt(sb, NOBH)) {
+ if (sb->s_blocksize_bits != PAGE_CACHE_SHIFT) {
+ printk(KERN_WARNING "EXT3-fs: Ignoring nobh option "
+ "since filesystem blocksize doesn't match "
+ "pagesize\n");
+ clear_opt(sbi->s_mount_opt, NOBH);
+ }
+ if (!(test_opt(sb, DATA_FLAGS) == EXT3_MOUNT_WRITEBACK_DATA)) {
+ printk(KERN_WARNING "EXT3-fs: Ignoring nobh option - "
+ "its supported only with writeback mode\n");
+ clear_opt(sbi->s_mount_opt, NOBH);
+ }
+ }
/*
* The journal_load will have done any necessary log recovery,
* so we can safely mount the rest of the filesystem now.
diff --git a/fs/fat/Makefile b/fs/fat/Makefile
index 73e0267a8cb63..bfb5f06cf2c8c 100644
--- a/fs/fat/Makefile
+++ b/fs/fat/Makefile
@@ -4,4 +4,4 @@
obj-$(CONFIG_FAT_FS) += fat.o
-fat-objs := cache.o dir.o file.o inode.o misc.o
+fat-objs := cache.o dir.o fatent.o file.o inode.o misc.o
diff --git a/fs/fat/cache.c b/fs/fat/cache.c
index f10e9caf96938..7c52e465a6190 100644
--- a/fs/fat/cache.c
+++ b/fs/fat/cache.c
@@ -203,124 +203,6 @@ void fat_cache_inval_inode(struct inode *inode)
spin_unlock(&MSDOS_I(inode)->cache_lru_lock);
}
-static int __fat_access(struct super_block *sb, int nr, int new_value)
-{
- struct msdos_sb_info *sbi = MSDOS_SB(sb);
- struct buffer_head *bh, *bh2, *c_bh, *c_bh2;
- unsigned char *p_first, *p_last;
- int copy, first, last, next, b;
-
- if (sbi->fat_bits == 32) {
- first = last = nr*4;
- } else if (sbi->fat_bits == 16) {
- first = last = nr*2;
- } else {
- first = nr*3/2;
- last = first+1;
- }
- b = sbi->fat_start + (first >> sb->s_blocksize_bits);
- if (!(bh = sb_bread(sb, b))) {
- printk(KERN_ERR "FAT: bread(block %d) in"
- " fat_access failed\n", b);
- return -EIO;
- }
- if ((first >> sb->s_blocksize_bits) == (last >> sb->s_blocksize_bits)) {
- bh2 = bh;
- } else {
- if (!(bh2 = sb_bread(sb, b + 1))) {
- brelse(bh);
- printk(KERN_ERR "FAT: bread(block %d) in"
- " fat_access failed\n", b + 1);
- return -EIO;
- }
- }
- if (sbi->fat_bits == 32) {
- p_first = p_last = NULL; /* GCC needs that stuff */
- next = le32_to_cpu(((__le32 *) bh->b_data)[(first &
- (sb->s_blocksize - 1)) >> 2]);
- /* Fscking Microsoft marketing department. Their "32" is 28. */
- next &= 0x0fffffff;
- } else if (sbi->fat_bits == 16) {
- p_first = p_last = NULL; /* GCC needs that stuff */
- next = le16_to_cpu(((__le16 *) bh->b_data)[(first &
- (sb->s_blocksize - 1)) >> 1]);
- } else {
- p_first = &((__u8 *)bh->b_data)[first & (sb->s_blocksize - 1)];
- p_last = &((__u8 *)bh2->b_data)[(first + 1) & (sb->s_blocksize - 1)];
- if (nr & 1)
- next = ((*p_first >> 4) | (*p_last << 4)) & 0xfff;
- else
- next = (*p_first+(*p_last << 8)) & 0xfff;
- }
- if (new_value != -1) {
- if (sbi->fat_bits == 32) {
- ((__le32 *)bh->b_data)[(first & (sb->s_blocksize - 1)) >> 2]
- = cpu_to_le32(new_value);
- } else if (sbi->fat_bits == 16) {
- ((__le16 *)bh->b_data)[(first & (sb->s_blocksize - 1)) >> 1]
- = cpu_to_le16(new_value);
- } else {
- if (nr & 1) {
- *p_first = (*p_first & 0xf) | (new_value << 4);
- *p_last = new_value >> 4;
- }
- else {
- *p_first = new_value & 0xff;
- *p_last = (*p_last & 0xf0) | (new_value >> 8);
- }
- mark_buffer_dirty(bh2);
- }
- mark_buffer_dirty(bh);
- for (copy = 1; copy < sbi->fats; copy++) {
- b = sbi->fat_start + (first >> sb->s_blocksize_bits)
- + sbi->fat_length * copy;
- if (!(c_bh = sb_bread(sb, b)))
- break;
- if (bh != bh2) {
- if (!(c_bh2 = sb_bread(sb, b+1))) {
- brelse(c_bh);
- break;
- }
- memcpy(c_bh2->b_data, bh2->b_data, sb->s_blocksize);
- mark_buffer_dirty(c_bh2);
- brelse(c_bh2);
- }
- memcpy(c_bh->b_data, bh->b_data, sb->s_blocksize);
- mark_buffer_dirty(c_bh);
- brelse(c_bh);
- }
- }
- brelse(bh);
- if (bh != bh2)
- brelse(bh2);
- return next;
-}
-
-/*
- * Returns the this'th FAT entry, -1 if it is an end-of-file entry. If
- * new_value is != -1, that FAT entry is replaced by it.
- */
-int fat_access(struct super_block *sb, int nr, int new_value)
-{
- int next;
-
- next = -EIO;
- if (nr < FAT_START_ENT || MSDOS_SB(sb)->max_cluster <= nr) {
- fat_fs_panic(sb, "invalid access to FAT (entry 0x%08x)", nr);
- goto out;
- }
- if (new_value == FAT_ENT_EOF)
- new_value = EOF_FAT(sb);
-
- next = __fat_access(sb, nr, new_value);
- if (next < 0)
- goto out;
- if (next >= BAD_FAT(sb))
- next = FAT_ENT_EOF;
-out:
- return next;
-}
-
static inline int cache_contiguous(struct fat_cache_id *cid, int dclus)
{
cid->nr_contig++;
@@ -339,6 +221,7 @@ int fat_get_cluster(struct inode *inode, int cluster, int *fclus, int *dclus)
{
struct super_block *sb = inode->i_sb;
const int limit = sb->s_maxbytes >> MSDOS_SB(sb)->cluster_bits;
+ struct fat_entry fatent;
struct fat_cache_id cid;
int nr;
@@ -357,34 +240,40 @@ int fat_get_cluster(struct inode *inode, int cluster, int *fclus, int *dclus)
cache_init(&cid, -1, -1);
}
+ fatent_init(&fatent);
while (*fclus < cluster) {
/* prevent the infinite loop of cluster chain */
if (*fclus > limit) {
fat_fs_panic(sb, "%s: detected the cluster chain loop"
" (i_pos %lld)", __FUNCTION__,
MSDOS_I(inode)->i_pos);
- return -EIO;
+ nr = -EIO;
+ goto out;
}
- nr = fat_access(sb, *dclus, -1);
+ nr = fat_ent_read(inode, &fatent, *dclus);
if (nr < 0)
- return nr;
+ goto out;
else if (nr == FAT_ENT_FREE) {
fat_fs_panic(sb, "%s: invalid cluster chain"
" (i_pos %lld)", __FUNCTION__,
MSDOS_I(inode)->i_pos);
- return -EIO;
+ nr = -EIO;
+ goto out;
} else if (nr == FAT_ENT_EOF) {
fat_cache_add(inode, &cid);
- return FAT_ENT_EOF;
+ goto out;
}
(*fclus)++;
*dclus = nr;
if (!cache_contiguous(&cid, *dclus))
cache_init(&cid, *fclus, *dclus);
}
+ nr = 0;
fat_cache_add(inode, &cid);
- return 0;
+out:
+ fatent_brelse(&fatent);
+ return nr;
}
static int fat_bmap_cluster(struct inode *inode, int cluster)
@@ -414,9 +303,7 @@ int fat_bmap(struct inode *inode, sector_t sector, sector_t *phys)
int cluster, offset;
*phys = 0;
- if ((sbi->fat_bits != 32) &&
- (inode->i_ino == MSDOS_ROOT_INO || (S_ISDIR(inode->i_mode) &&
- !MSDOS_I(inode)->i_start))) {
+ if ((sbi->fat_bits != 32) && (inode->i_ino == MSDOS_ROOT_INO)) {
if (sector < (sbi->dir_entries >> sbi->dir_per_block_bits))
*phys = sector + sbi->dir_start;
return 0;
diff --git a/fs/fat/dir.c b/fs/fat/dir.c
index fdb7153718148..e5ae1b720dde8 100644
--- a/fs/fat/dir.c
+++ b/fs/fat/dir.c
@@ -22,6 +22,72 @@
#include <linux/buffer_head.h>
#include <asm/uaccess.h>
+static inline loff_t fat_make_i_pos(struct super_block *sb,
+ struct buffer_head *bh,
+ struct msdos_dir_entry *de)
+{
+ return ((loff_t)bh->b_blocknr << MSDOS_SB(sb)->dir_per_block_bits)
+ | (de - (struct msdos_dir_entry *)bh->b_data);
+}
+
+/* Returns the inode number of the directory entry at offset pos. If bh is
+ non-NULL, it is brelse'd before. Pos is incremented. The buffer header is
+ returned in bh.
+ AV. Most often we do it item-by-item. Makes sense to optimize.
+ AV. OK, there we go: if both bh and de are non-NULL we assume that we just
+ AV. want the next entry (took one explicit de=NULL in vfat/namei.c).
+ AV. It's done in fat_get_entry() (inlined), here the slow case lives.
+ AV. Additionally, when we return -1 (i.e. reached the end of directory)
+ AV. we make bh NULL.
+ */
+static int fat__get_entry(struct inode *dir, loff_t *pos,
+ struct buffer_head **bh, struct msdos_dir_entry **de)
+{
+ struct super_block *sb = dir->i_sb;
+ sector_t phys, iblock;
+ int offset;
+ int err;
+
+next:
+ if (*bh)
+ brelse(*bh);
+
+ *bh = NULL;
+ iblock = *pos >> sb->s_blocksize_bits;
+ err = fat_bmap(dir, iblock, &phys);
+ if (err || !phys)
+ return -1; /* beyond EOF or error */
+
+ *bh = sb_bread(sb, phys);
+ if (*bh == NULL) {
+ printk(KERN_ERR "FAT: Directory bread(block %llu) failed\n",
+ (unsigned long long)phys);
+ /* skip this block */
+ *pos = (iblock + 1) << sb->s_blocksize_bits;
+ goto next;
+ }
+
+ offset = *pos & (sb->s_blocksize - 1);
+ *pos += sizeof(struct msdos_dir_entry);
+ *de = (struct msdos_dir_entry *)((*bh)->b_data + offset);
+
+ return 0;
+}
+
+static inline int fat_get_entry(struct inode *dir, loff_t *pos,
+ struct buffer_head **bh,
+ struct msdos_dir_entry **de)
+{
+ /* Fast stuff first */
+ if (*bh && *de &&
+ (*de - (struct msdos_dir_entry *)(*bh)->b_data) < MSDOS_SB(dir->i_sb)->dir_per_block - 1) {
+ *pos += sizeof(struct msdos_dir_entry);
+ (*de)++;
+ return 0;
+ }
+ return fat__get_entry(dir, pos, bh, de);
+}
+
/*
* Convert Unicode 16 to UTF8, translated Unicode, or ASCII.
* If uni_xlate is enabled and we can't get a 1:1 conversion, use a
@@ -136,28 +202,31 @@ fat_shortname2uni(struct nls_table *nls, unsigned char *buf, int buf_size,
* value is the total amount of slots, including the shortname entry.
*/
int fat_search_long(struct inode *inode, const unsigned char *name,
- int name_len, int anycase, loff_t *spos, loff_t *lpos)
+ int name_len, struct fat_slot_info *sinfo)
{
struct super_block *sb = inode->i_sb;
+ struct msdos_sb_info *sbi = MSDOS_SB(sb);
struct buffer_head *bh = NULL;
struct msdos_dir_entry *de;
- struct nls_table *nls_io = MSDOS_SB(sb)->nls_io;
- struct nls_table *nls_disk = MSDOS_SB(sb)->nls_disk;
+ struct nls_table *nls_io = sbi->nls_io;
+ struct nls_table *nls_disk = sbi->nls_disk;
wchar_t bufuname[14];
- unsigned char xlate_len, long_slots;
+ unsigned char xlate_len, nr_slots;
wchar_t *unicode = NULL;
unsigned char work[8], bufname[260]; /* 256 + 4 */
- int uni_xlate = MSDOS_SB(sb)->options.unicode_xlate;
- int utf8 = MSDOS_SB(sb)->options.utf8;
- unsigned short opt_shortname = MSDOS_SB(sb)->options.shortname;
- int chl, i, j, last_u, res = 0;
- loff_t i_pos, cpos = 0;
-
+ int uni_xlate = sbi->options.unicode_xlate;
+ int utf8 = sbi->options.utf8;
+ int anycase = (sbi->options.name_check != 's');
+ unsigned short opt_shortname = sbi->options.shortname;
+ loff_t cpos = 0;
+ int chl, i, j, last_u, err;
+
+ err = -ENOENT;
while(1) {
- if (fat_get_entry(inode,&cpos,&bh,&de,&i_pos) == -1)
+ if (fat_get_entry(inode, &cpos, &bh, &de) == -1)
goto EODir;
parse_record:
- long_slots = 0;
+ nr_slots = 0;
if (de->name[0] == DELETED_FLAG)
continue;
if (de->attr != ATTR_EXT && (de->attr & ATTR_VOLUME))
@@ -189,7 +258,7 @@ parse_long:
slots = id & ~0x40;
if (slots > 20 || !slots) /* ceil(256 * 2 / 26) */
continue;
- long_slots = slots;
+ nr_slots = slots;
alias_checksum = ds->alias_checksum;
slot = slots;
@@ -205,7 +274,7 @@ parse_long:
if (ds->id & 0x40) {
unicode[offset + 13] = 0;
}
- if (fat_get_entry(inode,&cpos,&bh,&de,&i_pos)<0)
+ if (fat_get_entry(inode, &cpos, &bh, &de) < 0)
goto EODir;
if (slot == 0)
break;
@@ -226,7 +295,7 @@ parse_long:
for (sum = 0, i = 0; i < 11; i++)
sum = (((sum&1)<<7)|((sum&0xfe)>>1)) + de->name[i];
if (sum != alias_checksum)
- long_slots = 0;
+ nr_slots = 0;
}
memcpy(work, de->name, sizeof(de->name));
@@ -274,7 +343,7 @@ parse_long:
xlate_len)))
goto Found;
- if (long_slots) {
+ if (nr_slots) {
xlate_len = utf8
?utf8_wcstombs(bufname, unicode, sizeof(bufname))
:uni16_to_x8(bufname, unicode, uni_xlate, nls_io);
@@ -288,15 +357,18 @@ parse_long:
}
Found:
- res = long_slots + 1;
- *spos = cpos - sizeof(struct msdos_dir_entry);
- *lpos = cpos - res*sizeof(struct msdos_dir_entry);
+ nr_slots++; /* include the de */
+ sinfo->slot_off = cpos - nr_slots * sizeof(*de);
+ sinfo->nr_slots = nr_slots;
+ sinfo->de = de;
+ sinfo->bh = bh;
+ sinfo->i_pos = fat_make_i_pos(sb, sinfo->bh, sinfo->de);
+ err = 0;
EODir:
- brelse(bh);
- if (unicode) {
- free_page((unsigned long) unicode);
- }
- return res;
+ if (unicode)
+ free_page((unsigned long)unicode);
+
+ return err;
}
EXPORT_SYMBOL(fat_search_long);
@@ -315,10 +387,11 @@ static int fat_readdirx(struct inode *inode, struct file *filp, void *dirent,
filldir_t filldir, int short_only, int both)
{
struct super_block *sb = inode->i_sb;
+ struct msdos_sb_info *sbi = MSDOS_SB(sb);
struct buffer_head *bh;
struct msdos_dir_entry *de;
- struct nls_table *nls_io = MSDOS_SB(sb)->nls_io;
- struct nls_table *nls_disk = MSDOS_SB(sb)->nls_disk;
+ struct nls_table *nls_io = sbi->nls_io;
+ struct nls_table *nls_disk = sbi->nls_disk;
unsigned char long_slots;
const char *fill_name;
int fill_len;
@@ -326,14 +399,14 @@ static int fat_readdirx(struct inode *inode, struct file *filp, void *dirent,
wchar_t *unicode = NULL;
unsigned char c, work[8], bufname[56], *ptname = bufname;
unsigned long lpos, dummy, *furrfu = &lpos;
- int uni_xlate = MSDOS_SB(sb)->options.unicode_xlate;
- int isvfat = MSDOS_SB(sb)->options.isvfat;
- int utf8 = MSDOS_SB(sb)->options.utf8;
- int nocase = MSDOS_SB(sb)->options.nocase;
- unsigned short opt_shortname = MSDOS_SB(sb)->options.shortname;
+ int uni_xlate = sbi->options.unicode_xlate;
+ int isvfat = sbi->options.isvfat;
+ int utf8 = sbi->options.utf8;
+ int nocase = sbi->options.nocase;
+ unsigned short opt_shortname = sbi->options.shortname;
unsigned long inum;
int chi, chl, i, i2, j, last, last_u, dotoffset = 0;
- loff_t i_pos, cpos;
+ loff_t cpos;
int ret = 0;
lock_kernel();
@@ -361,7 +434,7 @@ static int fat_readdirx(struct inode *inode, struct file *filp, void *dirent,
bh = NULL;
GetNew:
long_slots = 0;
- if (fat_get_entry(inode,&cpos,&bh,&de,&i_pos) == -1)
+ if (fat_get_entry(inode, &cpos, &bh, &de) == -1)
goto EODir;
/* Check for long filename entry */
if (isvfat) {
@@ -418,7 +491,7 @@ ParseLong:
if (ds->id & 0x40) {
unicode[offset + 13] = 0;
}
- if (fat_get_entry(inode,&cpos,&bh,&de,&i_pos) == -1)
+ if (fat_get_entry(inode, &cpos, &bh, &de) == -1)
goto EODir;
if (slot == 0)
break;
@@ -442,9 +515,13 @@ ParseLong:
long_slots = 0;
}
- if ((de->attr & ATTR_HIDDEN) && MSDOS_SB(sb)->options.dotsOK) {
- *ptname++ = '.';
- dotoffset = 1;
+ if (sbi->options.dotsOK) {
+ ptname = bufname;
+ dotoffset = 0;
+ if (de->attr & ATTR_HIDDEN) {
+ *ptname++ = '.';
+ dotoffset = 1;
+ }
}
memcpy(work, de->name, sizeof(de->name));
@@ -501,11 +578,12 @@ ParseLong:
j = last_u;
lpos = cpos - (long_slots+1)*sizeof(struct msdos_dir_entry);
- if (!memcmp(de->name,MSDOS_DOT,11))
+ if (!memcmp(de->name, MSDOS_DOT, MSDOS_NAME))
inum = inode->i_ino;
- else if (!memcmp(de->name,MSDOS_DOTDOT,11)) {
+ else if (!memcmp(de->name, MSDOS_DOTDOT, MSDOS_NAME)) {
inum = parent_ino(filp->f_dentry);
} else {
+ loff_t i_pos = fat_make_i_pos(sb, bh, de);
struct inode *tmp = fat_iget(sb, i_pos);
if (tmp) {
inum = tmp->i_ino;
@@ -639,7 +717,7 @@ static int fat_dir_ioctl(struct inode * inode, struct file * filp,
both = 1;
break;
default:
- return -EINVAL;
+ return fat_generic_ioctl(inode, filp, cmd, arg);
}
d1 = (struct dirent __user *)arg;
@@ -676,9 +754,9 @@ struct file_operations fat_dir_operations = {
static int fat_get_short_entry(struct inode *dir, loff_t *pos,
struct buffer_head **bh,
- struct msdos_dir_entry **de, loff_t *i_pos)
+ struct msdos_dir_entry **de)
{
- while (fat_get_entry(dir, pos, bh, de, i_pos) >= 0) {
+ while (fat_get_entry(dir, pos, bh, de) >= 0) {
/* free entry or long name entry or volume label */
if (!IS_FREE((*de)->name) && !((*de)->attr & ATTR_VOLUME))
return 0;
@@ -686,17 +764,39 @@ static int fat_get_short_entry(struct inode *dir, loff_t *pos,
return -ENOENT;
}
+/*
+ * The ".." entry can not provide the "struct fat_slot_info" informations
+ * for inode. So, this function provide the some informations only.
+ */
+int fat_get_dotdot_entry(struct inode *dir, struct buffer_head **bh,
+ struct msdos_dir_entry **de, loff_t *i_pos)
+{
+ loff_t offset;
+
+ offset = 0;
+ *bh = NULL;
+ while (fat_get_short_entry(dir, &offset, bh, de) >= 0) {
+ if (!strncmp((*de)->name, MSDOS_DOTDOT, MSDOS_NAME)) {
+ *i_pos = fat_make_i_pos(dir->i_sb, *bh, *de);
+ return 0;
+ }
+ }
+ return -ENOENT;
+}
+
+EXPORT_SYMBOL(fat_get_dotdot_entry);
+
/* See if directory is empty */
int fat_dir_empty(struct inode *dir)
{
struct buffer_head *bh;
struct msdos_dir_entry *de;
- loff_t cpos, i_pos;
+ loff_t cpos;
int result = 0;
bh = NULL;
cpos = 0;
- while (fat_get_short_entry(dir, &cpos, &bh, &de, &i_pos) >= 0) {
+ while (fat_get_short_entry(dir, &cpos, &bh, &de) >= 0) {
if (strncmp(de->name, MSDOS_DOT , MSDOS_NAME) &&
strncmp(de->name, MSDOS_DOTDOT, MSDOS_NAME)) {
result = -ENOTEMPTY;
@@ -717,12 +817,12 @@ int fat_subdirs(struct inode *dir)
{
struct buffer_head *bh;
struct msdos_dir_entry *de;
- loff_t cpos, i_pos;
+ loff_t cpos;
int count = 0;
bh = NULL;
cpos = 0;
- while (fat_get_short_entry(dir, &cpos, &bh, &de, &i_pos) >= 0) {
+ while (fat_get_short_entry(dir, &cpos, &bh, &de) >= 0) {
if (de->attr & ATTR_DIR)
count++;
}
@@ -735,140 +835,437 @@ int fat_subdirs(struct inode *dir)
* Returns an error code or zero.
*/
int fat_scan(struct inode *dir, const unsigned char *name,
- struct buffer_head **bh, struct msdos_dir_entry **de,
- loff_t *i_pos)
+ struct fat_slot_info *sinfo)
{
- loff_t cpos;
+ struct super_block *sb = dir->i_sb;
- *bh = NULL;
- cpos = 0;
- while (fat_get_short_entry(dir, &cpos, bh, de, i_pos) >= 0) {
- if (!strncmp((*de)->name, name, MSDOS_NAME))
+ sinfo->slot_off = 0;
+ sinfo->bh = NULL;
+ while (fat_get_short_entry(dir, &sinfo->slot_off, &sinfo->bh,
+ &sinfo->de) >= 0) {
+ if (!strncmp(sinfo->de->name, name, MSDOS_NAME)) {
+ sinfo->slot_off -= sizeof(*sinfo->de);
+ sinfo->nr_slots = 1;
+ sinfo->i_pos = fat_make_i_pos(sb, sinfo->bh, sinfo->de);
return 0;
+ }
}
return -ENOENT;
}
EXPORT_SYMBOL(fat_scan);
-static struct buffer_head *fat_extend_dir(struct inode *inode)
+static int __fat_remove_entries(struct inode *dir, loff_t pos, int nr_slots)
{
- struct super_block *sb = inode->i_sb;
- struct buffer_head *bh, *res = NULL;
- int nr, sec_per_clus = MSDOS_SB(sb)->sec_per_clus;
- sector_t sector, last_sector;
-
- if (MSDOS_SB(sb)->fat_bits != 32) {
- if (inode->i_ino == MSDOS_ROOT_INO)
- return ERR_PTR(-ENOSPC);
- }
-
- nr = fat_add_cluster(inode);
- if (nr < 0)
- return ERR_PTR(nr);
-
- sector = fat_clus_to_blknr(MSDOS_SB(sb), nr);
- last_sector = sector + sec_per_clus;
- for ( ; sector < last_sector; sector++) {
- if ((bh = sb_getblk(sb, sector))) {
- memset(bh->b_data, 0, sb->s_blocksize);
- set_buffer_uptodate(bh);
- mark_buffer_dirty(bh);
- if (!res)
- res = bh;
- else
- brelse(bh);
+ struct super_block *sb = dir->i_sb;
+ struct buffer_head *bh;
+ struct msdos_dir_entry *de, *endp;
+ int err = 0, orig_slots;
+
+ while (nr_slots) {
+ bh = NULL;
+ if (fat_get_entry(dir, &pos, &bh, &de) < 0) {
+ err = -EIO;
+ break;
}
+
+ orig_slots = nr_slots;
+ endp = (struct msdos_dir_entry *)(bh->b_data + sb->s_blocksize);
+ while (nr_slots && de < endp) {
+ de->name[0] = DELETED_FLAG;
+ de++;
+ nr_slots--;
+ }
+ mark_buffer_dirty(bh);
+ if (IS_DIRSYNC(dir))
+ err = sync_dirty_buffer(bh);
+ brelse(bh);
+ if (err)
+ break;
+
+ /* pos is *next* de's position, so this does `- sizeof(de)' */
+ pos += ((orig_slots - nr_slots) * sizeof(*de)) - sizeof(*de);
}
- if (res == NULL)
- res = ERR_PTR(-EIO);
- if (inode->i_size & (sb->s_blocksize - 1)) {
- fat_fs_panic(sb, "Odd directory size");
- inode->i_size = (inode->i_size + sb->s_blocksize)
- & ~((loff_t)sb->s_blocksize - 1);
+
+ return err;
+}
+
+int fat_remove_entries(struct inode *dir, struct fat_slot_info *sinfo)
+{
+ struct msdos_dir_entry *de;
+ struct buffer_head *bh;
+ int err = 0, nr_slots;
+
+ /*
+ * First stage: Remove the shortname. By this, the directory
+ * entry is removed.
+ */
+ nr_slots = sinfo->nr_slots;
+ de = sinfo->de;
+ sinfo->de = NULL;
+ bh = sinfo->bh;
+ sinfo->bh = NULL;
+ while (nr_slots && de >= (struct msdos_dir_entry *)bh->b_data) {
+ de->name[0] = DELETED_FLAG;
+ de--;
+ nr_slots--;
+ }
+ mark_buffer_dirty(bh);
+ if (IS_DIRSYNC(dir))
+ err = sync_dirty_buffer(bh);
+ brelse(bh);
+ if (err)
+ return err;
+ dir->i_version++;
+
+ if (nr_slots) {
+ /*
+ * Second stage: remove the remaining longname slots.
+ * (This directory entry is already removed, and so return
+ * the success)
+ */
+ err = __fat_remove_entries(dir, sinfo->slot_off, nr_slots);
+ if (err) {
+ printk(KERN_WARNING
+ "FAT: Couldn't remove the long name slots\n");
+ }
}
- inode->i_size += MSDOS_SB(sb)->cluster_size;
- MSDOS_I(inode)->mmu_private += MSDOS_SB(sb)->cluster_size;
- return res;
+ dir->i_mtime = dir->i_atime = CURRENT_TIME_SEC;
+ if (IS_DIRSYNC(dir))
+ (void)fat_sync_inode(dir);
+ else
+ mark_inode_dirty(dir);
+
+ return 0;
}
-/* This assumes that size of cluster is above the 32*slots */
+EXPORT_SYMBOL(fat_remove_entries);
-int fat_add_entries(struct inode *dir,int slots, struct buffer_head **bh,
- struct msdos_dir_entry **de, loff_t *i_pos)
+static int fat_zeroed_cluster(struct inode *dir, sector_t blknr, int nr_used,
+ struct buffer_head **bhs, int nr_bhs)
{
struct super_block *sb = dir->i_sb;
- loff_t offset, curr;
- int row;
- struct buffer_head *new_bh;
-
- offset = curr = 0;
- *bh = NULL;
- row = 0;
- while (fat_get_entry(dir, &curr, bh, de, i_pos) > -1) {
- /* check the maximum size of directory */
- if (curr >= FAT_MAX_DIR_SIZE) {
- brelse(*bh);
- return -ENOSPC;
+ sector_t last_blknr = blknr + MSDOS_SB(sb)->sec_per_clus;
+ int err, i, n;
+
+ /* Zeroing the unused blocks on this cluster */
+ blknr += nr_used;
+ n = nr_used;
+ while (blknr < last_blknr) {
+ bhs[n] = sb_getblk(sb, blknr);
+ if (!bhs[n]) {
+ err = -ENOMEM;
+ goto error;
}
-
- if (IS_FREE((*de)->name)) {
- if (++row == slots)
- return offset;
- } else {
- row = 0;
- offset = curr;
+ memset(bhs[n]->b_data, 0, sb->s_blocksize);
+ set_buffer_uptodate(bhs[n]);
+ mark_buffer_dirty(bhs[n]);
+
+ n++;
+ blknr++;
+ if (n == nr_bhs) {
+ if (IS_DIRSYNC(dir)) {
+ err = fat_sync_bhs(bhs, n);
+ if (err)
+ goto error;
+ }
+ for (i = 0; i < n; i++)
+ brelse(bhs[i]);
+ n = 0;
}
}
- if ((dir->i_ino == MSDOS_ROOT_INO) && (MSDOS_SB(sb)->fat_bits != 32))
- return -ENOSPC;
- new_bh = fat_extend_dir(dir);
- if (IS_ERR(new_bh))
- return PTR_ERR(new_bh);
- brelse(new_bh);
- do {
- fat_get_entry(dir, &curr, bh, de, i_pos);
- } while (++row < slots);
+ if (IS_DIRSYNC(dir)) {
+ err = fat_sync_bhs(bhs, n);
+ if (err)
+ goto error;
+ }
+ for (i = 0; i < n; i++)
+ brelse(bhs[i]);
- return offset;
-}
+ return 0;
-EXPORT_SYMBOL(fat_add_entries);
+error:
+ for (i = 0; i < n; i++)
+ bforget(bhs[i]);
+ return err;
+}
-int fat_new_dir(struct inode *dir, struct inode *parent, int is_vfat)
+int fat_alloc_new_dir(struct inode *dir, struct timespec *ts)
{
- struct buffer_head *bh;
+ struct super_block *sb = dir->i_sb;
+ struct msdos_sb_info *sbi = MSDOS_SB(sb);
+ struct buffer_head *bhs[MAX_BUF_PER_PAGE];
struct msdos_dir_entry *de;
+ sector_t blknr;
__le16 date, time;
+ int err, cluster;
+
+ err = fat_alloc_clusters(dir, &cluster, 1);
+ if (err)
+ goto error;
+
+ blknr = fat_clus_to_blknr(sbi, cluster);
+ bhs[0] = sb_getblk(sb, blknr);
+ if (!bhs[0]) {
+ err = -ENOMEM;
+ goto error_free;
+ }
- bh = fat_extend_dir(dir);
- if (IS_ERR(bh))
- return PTR_ERR(bh);
+ fat_date_unix2dos(ts->tv_sec, &time, &date);
- /* zeroed out, so... */
- fat_date_unix2dos(dir->i_mtime.tv_sec,&time,&date);
- de = (struct msdos_dir_entry*)&bh->b_data[0];
- memcpy(de[0].name,MSDOS_DOT,MSDOS_NAME);
- memcpy(de[1].name,MSDOS_DOTDOT,MSDOS_NAME);
- de[0].attr = de[1].attr = ATTR_DIR;
+ de = (struct msdos_dir_entry *)bhs[0]->b_data;
+ /* filling the new directory slots ("." and ".." entries) */
+ memcpy(de[0].name, MSDOS_DOT, MSDOS_NAME);
+ memcpy(de[1].name, MSDOS_DOTDOT, MSDOS_NAME);
+ de->attr = de[1].attr = ATTR_DIR;
+ de[0].lcase = de[1].lcase = 0;
de[0].time = de[1].time = time;
de[0].date = de[1].date = date;
- if (is_vfat) { /* extra timestamps */
+ de[0].ctime_cs = de[1].ctime_cs = 0;
+ if (sbi->options.isvfat) {
+ /* extra timestamps */
de[0].ctime = de[1].ctime = time;
- de[0].adate = de[0].cdate =
- de[1].adate = de[1].cdate = date;
+ de[0].adate = de[0].cdate = de[1].adate = de[1].cdate = date;
+ } else {
+ de[0].ctime = de[1].ctime = 0;
+ de[0].adate = de[0].cdate = de[1].adate = de[1].cdate = 0;
}
- de[0].start = cpu_to_le16(MSDOS_I(dir)->i_logstart);
- de[0].starthi = cpu_to_le16(MSDOS_I(dir)->i_logstart>>16);
- de[1].start = cpu_to_le16(MSDOS_I(parent)->i_logstart);
- de[1].starthi = cpu_to_le16(MSDOS_I(parent)->i_logstart>>16);
- mark_buffer_dirty(bh);
- brelse(bh);
- dir->i_atime = dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC;
- mark_inode_dirty(dir);
+ de[0].start = cpu_to_le16(cluster);
+ de[0].starthi = cpu_to_le16(cluster >> 16);
+ de[1].start = cpu_to_le16(MSDOS_I(dir)->i_logstart);
+ de[1].starthi = cpu_to_le16(MSDOS_I(dir)->i_logstart >> 16);
+ de[0].size = de[1].size = 0;
+ memset(de + 2, 0, sb->s_blocksize - 2 * sizeof(*de));
+ set_buffer_uptodate(bhs[0]);
+ mark_buffer_dirty(bhs[0]);
+
+ err = fat_zeroed_cluster(dir, blknr, 1, bhs, MAX_BUF_PER_PAGE);
+ if (err)
+ goto error_free;
+
+ return cluster;
+
+error_free:
+ fat_free_clusters(dir, cluster);
+error:
+ return err;
+}
+
+EXPORT_SYMBOL(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,
+ struct buffer_head **bh, loff_t *i_pos)
+{
+ struct super_block *sb = dir->i_sb;
+ struct msdos_sb_info *sbi = MSDOS_SB(sb);
+ struct buffer_head *bhs[MAX_BUF_PER_PAGE];
+ sector_t blknr, start_blknr, last_blknr;
+ unsigned long size, copy;
+ int err, i, n, offset, cluster[2];
+
+ /*
+ * The minimum cluster size is 512bytes, and maximum entry
+ * size is 32*slots (672bytes). So, iff the cluster size is
+ * 512bytes, we may need two clusters.
+ */
+ size = nr_slots * sizeof(struct msdos_dir_entry);
+ *nr_cluster = (size + (sbi->cluster_size - 1)) >> sbi->cluster_bits;
+ BUG_ON(*nr_cluster > 2);
+
+ err = fat_alloc_clusters(dir, cluster, *nr_cluster);
+ if (err)
+ goto error;
+
+ /*
+ * First stage: Fill the directory entry. NOTE: This cluster
+ * is not referenced from any inode yet, so updates order is
+ * not important.
+ */
+ i = n = copy = 0;
+ do {
+ start_blknr = blknr = fat_clus_to_blknr(sbi, cluster[i]);
+ last_blknr = start_blknr + sbi->sec_per_clus;
+ while (blknr < last_blknr) {
+ bhs[n] = sb_getblk(sb, blknr);
+ if (!bhs[n]) {
+ err = -ENOMEM;
+ goto error_nomem;
+ }
+
+ /* fill the directory entry */
+ copy = min(size, sb->s_blocksize);
+ memcpy(bhs[n]->b_data, slots, copy);
+ slots += copy;
+ size -= copy;
+ set_buffer_uptodate(bhs[n]);
+ mark_buffer_dirty(bhs[n]);
+ if (!size)
+ break;
+ n++;
+ blknr++;
+ }
+ } while (++i < *nr_cluster);
+
+ memset(bhs[n]->b_data + copy, 0, sb->s_blocksize - copy);
+ offset = copy - sizeof(struct msdos_dir_entry);
+ get_bh(bhs[n]);
+ *bh = bhs[n];
+ *de = (struct msdos_dir_entry *)((*bh)->b_data + offset);
+ *i_pos = fat_make_i_pos(sb, *bh, *de);
+
+ /* Second stage: clear the rest of cluster, and write outs */
+ err = fat_zeroed_cluster(dir, start_blknr, ++n, bhs, MAX_BUF_PER_PAGE);
+ if (err)
+ goto error_free;
+
+ return cluster[0];
+
+error_free:
+ brelse(*bh);
+ *bh = NULL;
+ n = 0;
+error_nomem:
+ for (i = 0; i < n; i++)
+ bforget(bhs[i]);
+ fat_free_clusters(dir, cluster[0]);
+error:
+ return err;
+}
+
+int fat_add_entries(struct inode *dir, void *slots, int nr_slots,
+ struct fat_slot_info *sinfo)
+{
+ struct super_block *sb = dir->i_sb;
+ struct msdos_sb_info *sbi = MSDOS_SB(sb);
+ struct buffer_head *bh, *prev, *bhs[3]; /* 32*slots (672bytes) */
+ struct msdos_dir_entry *de;
+ int err, free_slots, i, nr_bhs;
+ loff_t pos, i_pos;
+
+ sinfo->nr_slots = nr_slots;
+
+ /* First stage: search free direcotry entries */
+ free_slots = nr_bhs = 0;
+ bh = prev = NULL;
+ pos = 0;
+ err = -ENOSPC;
+ while (fat_get_entry(dir, &pos, &bh, &de) > -1) {
+ /* check the maximum size of directory */
+ if (pos >= FAT_MAX_DIR_SIZE)
+ goto error;
+
+ if (IS_FREE(de->name)) {
+ if (prev != bh) {
+ get_bh(bh);
+ bhs[nr_bhs] = prev = bh;
+ nr_bhs++;
+ }
+ free_slots++;
+ if (free_slots == nr_slots)
+ goto found;
+ } else {
+ for (i = 0; i < nr_bhs; i++)
+ brelse(bhs[i]);
+ prev = NULL;
+ free_slots = nr_bhs = 0;
+ }
+ }
+ if (dir->i_ino == MSDOS_ROOT_INO) {
+ if (sbi->fat_bits != 32)
+ goto error;
+ } else if (MSDOS_I(dir)->i_start == 0) {
+ printk(KERN_ERR "FAT: Corrupted directory (i_pos %lld)\n",
+ MSDOS_I(dir)->i_pos);
+ err = -EIO;
+ goto error;
+ }
+
+found:
+ err = 0;
+ pos -= free_slots * sizeof(*de);
+ nr_slots -= free_slots;
+ if (free_slots) {
+ /*
+ * Second stage: filling the free entries with new entries.
+ * NOTE: If this slots has shortname, first, we write
+ * the long name slots, then write the short name.
+ */
+ int size = free_slots * sizeof(*de);
+ int offset = pos & (sb->s_blocksize - 1);
+ int long_bhs = nr_bhs - (nr_slots == 0);
+
+ /* Fill the long name slots. */
+ for (i = 0; i < long_bhs; i++) {
+ int copy = min_t(int, sb->s_blocksize - offset, size);
+ memcpy(bhs[i]->b_data + offset, slots, copy);
+ mark_buffer_dirty(bhs[i]);
+ offset = 0;
+ slots += copy;
+ size -= copy;
+ }
+ if (long_bhs && IS_DIRSYNC(dir))
+ err = fat_sync_bhs(bhs, long_bhs);
+ if (!err && i < nr_bhs) {
+ /* Fill the short name slot. */
+ int copy = min_t(int, sb->s_blocksize - offset, size);
+ memcpy(bhs[i]->b_data + offset, slots, copy);
+ mark_buffer_dirty(bhs[i]);
+ if (IS_DIRSYNC(dir))
+ err = sync_dirty_buffer(bhs[i]);
+ }
+ for (i = 0; i < nr_bhs; i++)
+ brelse(bhs[i]);
+ if (err)
+ goto error_remove;
+ }
+
+ if (nr_slots) {
+ int cluster, nr_cluster;
+
+ /*
+ * Third stage: allocate the cluster for new entries.
+ * And initialize the cluster with new entries, then
+ * add the cluster to dir.
+ */
+ cluster = fat_add_new_entries(dir, slots, nr_slots, &nr_cluster,
+ &de, &bh, &i_pos);
+ if (cluster < 0) {
+ err = cluster;
+ goto error_remove;
+ }
+ err = fat_chain_add(dir, cluster, nr_cluster);
+ if (err) {
+ fat_free_clusters(dir, cluster);
+ goto error_remove;
+ }
+ if (dir->i_size & (sbi->cluster_size - 1)) {
+ fat_fs_panic(sb, "Odd directory size");
+ dir->i_size = (dir->i_size + sbi->cluster_size - 1)
+ & ~((loff_t)sbi->cluster_size - 1);
+ }
+ dir->i_size += nr_cluster << sbi->cluster_bits;
+ MSDOS_I(dir)->mmu_private += nr_cluster << sbi->cluster_bits;
+ }
+ sinfo->slot_off = pos;
+ sinfo->de = de;
+ sinfo->bh = bh;
+ sinfo->i_pos = fat_make_i_pos(sb, sinfo->bh, sinfo->de);
return 0;
+
+error:
+ brelse(bh);
+ for (i = 0; i < nr_bhs; i++)
+ brelse(bhs[i]);
+ return err;
+
+error_remove:
+ brelse(bh);
+ if (free_slots)
+ __fat_remove_entries(dir, pos, free_slots);
+ return err;
}
-EXPORT_SYMBOL(fat_new_dir);
+EXPORT_SYMBOL(fat_add_entries);
diff --git a/fs/fat/fatent.c b/fs/fat/fatent.c
new file mode 100644
index 0000000000000..4164cd54c4d1e
--- /dev/null
+++ b/fs/fat/fatent.c
@@ -0,0 +1,612 @@
+/*
+ * Copyright (C) 2004, OGAWA Hirofumi
+ * Released under GPL v2.
+ */
+
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/msdos_fs.h>
+
+struct fatent_operations {
+ void (*ent_blocknr)(struct super_block *, int, int *, sector_t *);
+ void (*ent_set_ptr)(struct fat_entry *, int);
+ int (*ent_bread)(struct super_block *, struct fat_entry *,
+ int, sector_t);
+ int (*ent_get)(struct fat_entry *);
+ void (*ent_put)(struct fat_entry *, int);
+ int (*ent_next)(struct fat_entry *);
+};
+
+static void fat12_ent_blocknr(struct super_block *sb, int entry,
+ int *offset, sector_t *blocknr)
+{
+ struct msdos_sb_info *sbi = MSDOS_SB(sb);
+ int bytes = entry + (entry >> 1);
+ WARN_ON(entry < FAT_START_ENT || sbi->max_cluster <= entry);
+ *offset = bytes & (sb->s_blocksize - 1);
+ *blocknr = sbi->fat_start + (bytes >> sb->s_blocksize_bits);
+}
+
+static void fat_ent_blocknr(struct super_block *sb, int entry,
+ int *offset, sector_t *blocknr)
+{
+ struct msdos_sb_info *sbi = MSDOS_SB(sb);
+ int bytes = (entry << sbi->fatent_shift);
+ WARN_ON(entry < FAT_START_ENT || sbi->max_cluster <= entry);
+ *offset = bytes & (sb->s_blocksize - 1);
+ *blocknr = sbi->fat_start + (bytes >> sb->s_blocksize_bits);
+}
+
+static void fat12_ent_set_ptr(struct fat_entry *fatent, int offset)
+{
+ struct buffer_head **bhs = fatent->bhs;
+ if (fatent->nr_bhs == 1) {
+ WARN_ON(offset >= (bhs[0]->b_size - 1));
+ fatent->u.ent12_p[0] = bhs[0]->b_data + offset;
+ fatent->u.ent12_p[1] = bhs[0]->b_data + (offset + 1);
+ } else {
+ WARN_ON(offset != (bhs[0]->b_size - 1));
+ fatent->u.ent12_p[0] = bhs[0]->b_data + offset;
+ fatent->u.ent12_p[1] = bhs[1]->b_data;
+ }
+}
+
+static void fat16_ent_set_ptr(struct fat_entry *fatent, int offset)
+{
+ WARN_ON(offset & (2 - 1));
+ fatent->u.ent16_p = (__le16 *)(fatent->bhs[0]->b_data + offset);
+}
+
+static void fat32_ent_set_ptr(struct fat_entry *fatent, int offset)
+{
+ WARN_ON(offset & (4 - 1));
+ fatent->u.ent32_p = (__le32 *)(fatent->bhs[0]->b_data + offset);
+}
+
+static int fat12_ent_bread(struct super_block *sb, struct fat_entry *fatent,
+ int offset, sector_t blocknr)
+{
+ struct buffer_head **bhs = fatent->bhs;
+
+ WARN_ON(blocknr < MSDOS_SB(sb)->fat_start);
+ bhs[0] = sb_bread(sb, blocknr);
+ if (!bhs[0])
+ goto err;
+
+ if ((offset + 1) < sb->s_blocksize)
+ fatent->nr_bhs = 1;
+ else {
+ /* This entry is block boundary, it needs the next block */
+ blocknr++;
+ bhs[1] = sb_bread(sb, blocknr);
+ if (!bhs[1])
+ goto err_brelse;
+ fatent->nr_bhs = 2;
+ }
+ fat12_ent_set_ptr(fatent, offset);
+ return 0;
+
+err_brelse:
+ brelse(bhs[0]);
+err:
+ printk(KERN_ERR "FAT: FAT read failed (blocknr %llu)\n",
+ (unsigned long long)blocknr);
+ return -EIO;
+}
+
+static int fat_ent_bread(struct super_block *sb, struct fat_entry *fatent,
+ int offset, sector_t blocknr)
+{
+ struct fatent_operations *ops = MSDOS_SB(sb)->fatent_ops;
+
+ WARN_ON(blocknr < MSDOS_SB(sb)->fat_start);
+ fatent->bhs[0] = sb_bread(sb, blocknr);
+ if (!fatent->bhs[0]) {
+ printk(KERN_ERR "FAT: FAT read failed (blocknr %llu)\n",
+ (unsigned long long)blocknr);
+ return -EIO;
+ }
+ fatent->nr_bhs = 1;
+ ops->ent_set_ptr(fatent, offset);
+ return 0;
+}
+
+static int fat12_ent_get(struct fat_entry *fatent)
+{
+ u8 **ent12_p = fatent->u.ent12_p;
+ int next;
+
+ if (fatent->entry & 1)
+ next = (*ent12_p[0] >> 4) | (*ent12_p[1] << 4);
+ else
+ next = (*ent12_p[1] << 8) | *ent12_p[0];
+ next &= 0x0fff;
+ if (next >= BAD_FAT12)
+ next = FAT_ENT_EOF;
+ return next;
+}
+
+static int fat16_ent_get(struct fat_entry *fatent)
+{
+ int next = le16_to_cpu(*fatent->u.ent16_p);
+ WARN_ON((unsigned long)fatent->u.ent16_p & (2 - 1));
+ if (next >= BAD_FAT16)
+ next = FAT_ENT_EOF;
+ return next;
+}
+
+static int fat32_ent_get(struct fat_entry *fatent)
+{
+ int next = le32_to_cpu(*fatent->u.ent32_p) & 0x0fffffff;
+ WARN_ON((unsigned long)fatent->u.ent32_p & (4 - 1));
+ if (next >= BAD_FAT32)
+ next = FAT_ENT_EOF;
+ return next;
+}
+
+static void fat12_ent_put(struct fat_entry *fatent, int new)
+{
+ u8 **ent12_p = fatent->u.ent12_p;
+
+ if (new == FAT_ENT_EOF)
+ new = EOF_FAT12;
+
+ if (fatent->entry & 1) {
+ *ent12_p[0] = (new << 4) | (*ent12_p[0] & 0x0f);
+ *ent12_p[1] = new >> 4;
+ } else {
+ *ent12_p[0] = new & 0xff;
+ *ent12_p[1] = (*ent12_p[1] & 0xf0) | (new >> 8);
+ }
+
+ mark_buffer_dirty(fatent->bhs[0]);
+ if (fatent->nr_bhs == 2)
+ mark_buffer_dirty(fatent->bhs[1]);
+}
+
+static void fat16_ent_put(struct fat_entry *fatent, int new)
+{
+ if (new == FAT_ENT_EOF)
+ new = EOF_FAT16;
+
+ *fatent->u.ent16_p = cpu_to_le16(new);
+ mark_buffer_dirty(fatent->bhs[0]);
+}
+
+static void fat32_ent_put(struct fat_entry *fatent, int new)
+{
+ if (new == FAT_ENT_EOF)
+ new = EOF_FAT32;
+
+ WARN_ON(new & 0xf0000000);
+ new |= le32_to_cpu(*fatent->u.ent32_p) & ~0x0fffffff;
+ *fatent->u.ent32_p = cpu_to_le32(new);
+ mark_buffer_dirty(fatent->bhs[0]);
+}
+
+static int fat12_ent_next(struct fat_entry *fatent)
+{
+ u8 **ent12_p = fatent->u.ent12_p;
+ struct buffer_head **bhs = fatent->bhs;
+ u8 *nextp = ent12_p[1] + 1 + (fatent->entry & 1);
+
+ fatent->entry++;
+ if (fatent->nr_bhs == 1) {
+ WARN_ON(ent12_p[0] > (u8 *)(bhs[0]->b_data + (bhs[0]->b_size - 2)));
+ WARN_ON(ent12_p[1] > (u8 *)(bhs[0]->b_data + (bhs[0]->b_size - 1)));
+ if (nextp < (u8 *)(bhs[0]->b_data + (bhs[0]->b_size - 1))) {
+ ent12_p[0] = nextp - 1;
+ ent12_p[1] = nextp;
+ return 1;
+ }
+ } else {
+ WARN_ON(ent12_p[0] != (u8 *)(bhs[0]->b_data + (bhs[0]->b_size - 1)));
+ WARN_ON(ent12_p[1] != (u8 *)bhs[1]->b_data);
+ ent12_p[0] = nextp - 1;
+ ent12_p[1] = nextp;
+ brelse(bhs[0]);
+ bhs[0] = bhs[1];
+ fatent->nr_bhs = 1;
+ return 1;
+ }
+ ent12_p[0] = NULL;
+ ent12_p[1] = NULL;
+ return 0;
+}
+
+static int fat16_ent_next(struct fat_entry *fatent)
+{
+ const struct buffer_head *bh = fatent->bhs[0];
+ fatent->entry++;
+ if (fatent->u.ent16_p < (__le16 *)(bh->b_data + (bh->b_size - 2))) {
+ fatent->u.ent16_p++;
+ return 1;
+ }
+ fatent->u.ent16_p = NULL;
+ return 0;
+}
+
+static int fat32_ent_next(struct fat_entry *fatent)
+{
+ const struct buffer_head *bh = fatent->bhs[0];
+ fatent->entry++;
+ if (fatent->u.ent32_p < (__le32 *)(bh->b_data + (bh->b_size - 4))) {
+ fatent->u.ent32_p++;
+ return 1;
+ }
+ fatent->u.ent32_p = NULL;
+ return 0;
+}
+
+static struct fatent_operations fat12_ops = {
+ .ent_blocknr = fat12_ent_blocknr,
+ .ent_set_ptr = fat12_ent_set_ptr,
+ .ent_bread = fat12_ent_bread,
+ .ent_get = fat12_ent_get,
+ .ent_put = fat12_ent_put,
+ .ent_next = fat12_ent_next,
+};
+
+static struct fatent_operations fat16_ops = {
+ .ent_blocknr = fat_ent_blocknr,
+ .ent_set_ptr = fat16_ent_set_ptr,
+ .ent_bread = fat_ent_bread,
+ .ent_get = fat16_ent_get,
+ .ent_put = fat16_ent_put,
+ .ent_next = fat16_ent_next,
+};
+
+static struct fatent_operations fat32_ops = {
+ .ent_blocknr = fat_ent_blocknr,
+ .ent_set_ptr = fat32_ent_set_ptr,
+ .ent_bread = fat_ent_bread,
+ .ent_get = fat32_ent_get,
+ .ent_put = fat32_ent_put,
+ .ent_next = fat32_ent_next,
+};
+
+static inline void lock_fat(struct msdos_sb_info *sbi)
+{
+ down(&sbi->fat_lock);
+}
+
+static inline void unlock_fat(struct msdos_sb_info *sbi)
+{
+ up(&sbi->fat_lock);
+}
+
+void fat_ent_access_init(struct super_block *sb)
+{
+ struct msdos_sb_info *sbi = MSDOS_SB(sb);
+
+ init_MUTEX(&sbi->fat_lock);
+
+ switch (sbi->fat_bits) {
+ case 32:
+ sbi->fatent_shift = 2;
+ sbi->fatent_ops = &fat32_ops;
+ break;
+ case 16:
+ sbi->fatent_shift = 1;
+ sbi->fatent_ops = &fat16_ops;
+ break;
+ case 12:
+ sbi->fatent_shift = -1;
+ sbi->fatent_ops = &fat12_ops;
+ break;
+ }
+}
+
+static inline int fat_ent_update_ptr(struct super_block *sb,
+ struct fat_entry *fatent,
+ int offset, sector_t blocknr)
+{
+ struct msdos_sb_info *sbi = MSDOS_SB(sb);
+ struct fatent_operations *ops = sbi->fatent_ops;
+ struct buffer_head **bhs = fatent->bhs;
+
+ /* Is this fatent's blocks including this entry? */
+ if (!fatent->nr_bhs || bhs[0]->b_blocknr != blocknr)
+ return 0;
+ /* Does this entry need the next block? */
+ if (sbi->fat_bits == 12 && (offset + 1) >= sb->s_blocksize) {
+ if (fatent->nr_bhs != 2 || bhs[1]->b_blocknr != (blocknr + 1))
+ return 0;
+ }
+ ops->ent_set_ptr(fatent, offset);
+ return 1;
+}
+
+int fat_ent_read(struct inode *inode, struct fat_entry *fatent, int entry)
+{
+ struct super_block *sb = inode->i_sb;
+ struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
+ struct fatent_operations *ops = sbi->fatent_ops;
+ int err, offset;
+ sector_t blocknr;
+
+ if (entry < FAT_START_ENT || sbi->max_cluster <= entry) {
+ fatent_brelse(fatent);
+ fat_fs_panic(sb, "invalid access to FAT (entry 0x%08x)", entry);
+ return -EIO;
+ }
+
+ fatent_set_entry(fatent, entry);
+ ops->ent_blocknr(sb, entry, &offset, &blocknr);
+
+ if (!fat_ent_update_ptr(sb, fatent, offset, blocknr)) {
+ fatent_brelse(fatent);
+ err = ops->ent_bread(sb, fatent, offset, blocknr);
+ if (err)
+ return err;
+ }
+ return ops->ent_get(fatent);
+}
+
+/* FIXME: We can write the blocks as more big chunk. */
+static int fat_mirror_bhs(struct super_block *sb, struct buffer_head **bhs,
+ int nr_bhs)
+{
+ struct msdos_sb_info *sbi = MSDOS_SB(sb);
+ struct buffer_head *c_bh;
+ int err, n, copy;
+
+ err = 0;
+ for (copy = 1; copy < sbi->fats; copy++) {
+ sector_t backup_fat = sbi->fat_length * copy;
+
+ for (n = 0; n < nr_bhs; n++) {
+ c_bh = sb_getblk(sb, backup_fat + bhs[n]->b_blocknr);
+ if (!c_bh) {
+ err = -ENOMEM;
+ goto error;
+ }
+ memcpy(c_bh->b_data, bhs[n]->b_data, sb->s_blocksize);
+ set_buffer_uptodate(c_bh);
+ mark_buffer_dirty(c_bh);
+ if (sb->s_flags & MS_SYNCHRONOUS)
+ err = sync_dirty_buffer(c_bh);
+ brelse(c_bh);
+ if (err)
+ goto error;
+ }
+ }
+error:
+ return err;
+}
+
+int fat_ent_write(struct inode *inode, struct fat_entry *fatent,
+ int new, int wait)
+{
+ struct super_block *sb = inode->i_sb;
+ struct fatent_operations *ops = MSDOS_SB(sb)->fatent_ops;
+ int err;
+
+ ops->ent_put(fatent, new);
+ if (wait) {
+ err = fat_sync_bhs(fatent->bhs, fatent->nr_bhs);
+ if (err)
+ return err;
+ }
+ return fat_mirror_bhs(sb, fatent->bhs, fatent->nr_bhs);
+}
+
+static inline int fat_ent_next(struct msdos_sb_info *sbi,
+ struct fat_entry *fatent)
+{
+ if (sbi->fatent_ops->ent_next(fatent)) {
+ if (fatent->entry < sbi->max_cluster)
+ return 1;
+ }
+ return 0;
+}
+
+static inline int fat_ent_read_block(struct super_block *sb,
+ struct fat_entry *fatent)
+{
+ struct fatent_operations *ops = MSDOS_SB(sb)->fatent_ops;
+ sector_t blocknr;
+ int offset;
+
+ fatent_brelse(fatent);
+ ops->ent_blocknr(sb, fatent->entry, &offset, &blocknr);
+ return ops->ent_bread(sb, fatent, offset, blocknr);
+}
+
+static void fat_collect_bhs(struct buffer_head **bhs, int *nr_bhs,
+ struct fat_entry *fatent)
+{
+ int n, i;
+
+ for (n = 0; n < fatent->nr_bhs; n++) {
+ for (i = 0; i < *nr_bhs; i++) {
+ if (fatent->bhs[n] == bhs[i])
+ break;
+ }
+ if (i == *nr_bhs) {
+ get_bh(fatent->bhs[n]);
+ bhs[i] = fatent->bhs[n];
+ (*nr_bhs)++;
+ }
+ }
+}
+
+int fat_alloc_clusters(struct inode *inode, int *cluster, int nr_cluster)
+{
+ struct super_block *sb = inode->i_sb;
+ struct msdos_sb_info *sbi = MSDOS_SB(sb);
+ struct fatent_operations *ops = sbi->fatent_ops;
+ struct fat_entry fatent, prev_ent;
+ struct buffer_head *bhs[MAX_BUF_PER_PAGE];
+ int i, count, err, nr_bhs, idx_clus;
+
+ BUG_ON(nr_cluster > (MAX_BUF_PER_PAGE / 2)); /* fixed limit */
+
+ lock_fat(sbi);
+ if (sbi->free_clusters != -1 && sbi->free_clusters < nr_cluster) {
+ unlock_fat(sbi);
+ return -ENOSPC;
+ }
+
+ err = nr_bhs = idx_clus = 0;
+ count = FAT_START_ENT;
+ fatent_init(&prev_ent);
+ fatent_init(&fatent);
+ fatent_set_entry(&fatent, sbi->prev_free + 1);
+ while (count < sbi->max_cluster) {
+ if (fatent.entry >= sbi->max_cluster)
+ fatent.entry = FAT_START_ENT;
+ fatent_set_entry(&fatent, fatent.entry);
+ err = fat_ent_read_block(sb, &fatent);
+ if (err)
+ goto out;
+
+ /* Find the free entries in a block */
+ do {
+ if (ops->ent_get(&fatent) == FAT_ENT_FREE) {
+ int entry = fatent.entry;
+
+ /* make the cluster chain */
+ ops->ent_put(&fatent, FAT_ENT_EOF);
+ if (prev_ent.nr_bhs)
+ ops->ent_put(&prev_ent, entry);
+
+ fat_collect_bhs(bhs, &nr_bhs, &fatent);
+
+ sbi->prev_free = entry;
+ if (sbi->free_clusters != -1)
+ sbi->free_clusters--;
+
+ cluster[idx_clus] = entry;
+ idx_clus++;
+ if (idx_clus == nr_cluster)
+ goto out;
+
+ /*
+ * fat_collect_bhs() gets ref-count of bhs,
+ * so we can still use the prev_ent.
+ */
+ prev_ent = fatent;
+ }
+ count++;
+ if (count == sbi->max_cluster)
+ break;
+ } while (fat_ent_next(sbi, &fatent));
+ }
+
+ /* Couldn't allocate the free entries */
+ sbi->free_clusters = 0;
+ err = -ENOSPC;
+
+out:
+ unlock_fat(sbi);
+ fatent_brelse(&fatent);
+ if (!err) {
+ if (inode_needs_sync(inode))
+ err = fat_sync_bhs(bhs, nr_bhs);
+ if (!err)
+ err = fat_mirror_bhs(sb, bhs, nr_bhs);
+ }
+ for (i = 0; i < nr_bhs; i++)
+ brelse(bhs[i]);
+ fat_clusters_flush(sb);
+
+ if (err && idx_clus)
+ fat_free_clusters(inode, cluster[0]);
+
+ return err;
+}
+
+int fat_free_clusters(struct inode *inode, int cluster)
+{
+ struct super_block *sb = inode->i_sb;
+ struct msdos_sb_info *sbi = MSDOS_SB(sb);
+ struct fatent_operations *ops = sbi->fatent_ops;
+ struct fat_entry fatent;
+ struct buffer_head *bhs[MAX_BUF_PER_PAGE];
+ int i, err, nr_bhs;
+
+ nr_bhs = 0;
+ fatent_init(&fatent);
+ lock_fat(sbi);
+ do {
+ cluster = fat_ent_read(inode, &fatent, cluster);
+ if (cluster < 0) {
+ err = cluster;
+ goto error;
+ } else if (cluster == FAT_ENT_FREE) {
+ fat_fs_panic(sb, "%s: deleting FAT entry beyond EOF",
+ __FUNCTION__);
+ err = -EIO;
+ goto error;
+ }
+
+ ops->ent_put(&fatent, FAT_ENT_FREE);
+ if (sbi->free_clusters != -1)
+ sbi->free_clusters++;
+
+ if (nr_bhs + fatent.nr_bhs > MAX_BUF_PER_PAGE) {
+ if (sb->s_flags & MS_SYNCHRONOUS) {
+ err = fat_sync_bhs(bhs, nr_bhs);
+ if (err)
+ goto error;
+ }
+ err = fat_mirror_bhs(sb, bhs, nr_bhs);
+ if (err)
+ goto error;
+ for (i = 0; i < nr_bhs; i++)
+ brelse(bhs[i]);
+ nr_bhs = 0;
+ }
+ fat_collect_bhs(bhs, &nr_bhs, &fatent);
+ } while (cluster != FAT_ENT_EOF);
+
+ if (sb->s_flags & MS_SYNCHRONOUS) {
+ err = fat_sync_bhs(bhs, nr_bhs);
+ if (err)
+ goto error;
+ }
+ err = fat_mirror_bhs(sb, bhs, nr_bhs);
+error:
+ fatent_brelse(&fatent);
+ for (i = 0; i < nr_bhs; i++)
+ brelse(bhs[i]);
+ unlock_fat(sbi);
+
+ fat_clusters_flush(sb);
+
+ return err;
+}
+
+EXPORT_SYMBOL(fat_free_clusters);
+
+int fat_count_free_clusters(struct super_block *sb)
+{
+ struct msdos_sb_info *sbi = MSDOS_SB(sb);
+ struct fatent_operations *ops = sbi->fatent_ops;
+ struct fat_entry fatent;
+ int err = 0, free;
+
+ lock_fat(sbi);
+ if (sbi->free_clusters != -1)
+ goto out;
+
+ free = 0;
+ fatent_init(&fatent);
+ fatent_set_entry(&fatent, FAT_START_ENT);
+ while (fatent.entry < sbi->max_cluster) {
+ err = fat_ent_read_block(sb, &fatent);
+ if (err)
+ goto out;
+
+ do {
+ if (ops->ent_get(&fatent) == FAT_ENT_FREE)
+ free++;
+ } while (fat_ent_next(sbi, &fatent));
+ }
+ sbi->free_clusters = free;
+ fatent_brelse(&fatent);
+out:
+ unlock_fat(sbi);
+ return err;
+}
diff --git a/fs/fat/file.c b/fs/fat/file.c
index 815f219064c50..62ffa91394008 100644
--- a/fs/fat/file.c
+++ b/fs/fat/file.c
@@ -12,13 +12,31 @@
#include <linux/smp_lock.h>
#include <linux/buffer_head.h>
-static ssize_t fat_file_write(struct file *filp, const char __user *buf,
- size_t count, loff_t *ppos)
+static ssize_t fat_file_aio_write(struct kiocb *iocb, const char __user *buf,
+ size_t count, loff_t pos)
+{
+ struct inode *inode = iocb->ki_filp->f_dentry->d_inode;
+ int retval;
+
+ retval = generic_file_aio_write(iocb, buf, count, pos);
+ if (retval > 0) {
+ inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC;
+ MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
+ mark_inode_dirty(inode);
+// check the locking rules
+// if (IS_SYNC(inode))
+// fat_sync_inode(inode);
+ }
+ return retval;
+}
+
+static ssize_t fat_file_writev(struct file *filp, const struct iovec *iov,
+ unsigned long nr_segs, loff_t *ppos)
{
struct inode *inode = filp->f_dentry->d_inode;
int retval;
- retval = generic_file_write(filp, buf, count, ppos);
+ retval = generic_file_writev(filp, iov, nr_segs, ppos);
if (retval > 0) {
inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC;
MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
@@ -27,14 +45,115 @@ static ssize_t fat_file_write(struct file *filp, const char __user *buf,
return retval;
}
+int fat_generic_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
+{
+ struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
+ u32 __user *user_attr = (u32 __user *)arg;
+
+ switch (cmd) {
+ case FAT_IOCTL_GET_ATTRIBUTES:
+ {
+ u32 attr;
+
+ if (inode->i_ino == MSDOS_ROOT_INO)
+ attr = ATTR_DIR;
+ else
+ attr = fat_attr(inode);
+
+ return put_user(attr, user_attr);
+ }
+ case FAT_IOCTL_SET_ATTRIBUTES:
+ {
+ u32 attr, oldattr;
+ int err, is_dir = S_ISDIR(inode->i_mode);
+ struct iattr ia;
+
+ err = get_user(attr, user_attr);
+ if (err)
+ return err;
+
+ down(&inode->i_sem);
+
+ if (IS_RDONLY(inode)) {
+ err = -EROFS;
+ goto up;
+ }
+
+ /*
+ * ATTR_VOLUME and ATTR_DIR cannot be changed; this also
+ * prevents the user from turning us into a VFAT
+ * longname entry. Also, we obviously can't set
+ * any of the NTFS attributes in the high 24 bits.
+ */
+ attr &= 0xff & ~(ATTR_VOLUME | ATTR_DIR);
+ /* Merge in ATTR_VOLUME and ATTR_DIR */
+ attr |= (MSDOS_I(inode)->i_attrs & ATTR_VOLUME) |
+ (is_dir ? ATTR_DIR : 0);
+ oldattr = fat_attr(inode);
+
+ /* Equivalent to a chmod() */
+ ia.ia_valid = ATTR_MODE | ATTR_CTIME;
+ if (is_dir) {
+ ia.ia_mode = MSDOS_MKMODE(attr,
+ S_IRWXUGO & ~sbi->options.fs_dmask)
+ | S_IFDIR;
+ } else {
+ ia.ia_mode = MSDOS_MKMODE(attr,
+ (S_IRUGO | S_IWUGO | (inode->i_mode & S_IXUGO))
+ & ~sbi->options.fs_fmask)
+ | S_IFREG;
+ }
+
+ /* The root directory has no attributes */
+ if (inode->i_ino == MSDOS_ROOT_INO && attr != ATTR_DIR) {
+ err = -EINVAL;
+ goto up;
+ }
+
+ if (sbi->options.sys_immutable) {
+ if ((attr | oldattr) & ATTR_SYS) {
+ if (!capable(CAP_LINUX_IMMUTABLE)) {
+ err = -EPERM;
+ goto up;
+ }
+ }
+ }
+
+ /* This MUST be done before doing anything irreversible... */
+ err = notify_change(filp->f_dentry, &ia);
+ if (err)
+ goto up;
+
+ if (sbi->options.sys_immutable) {
+ if (attr & ATTR_SYS)
+ inode->i_flags |= S_IMMUTABLE;
+ else
+ inode->i_flags &= S_IMMUTABLE;
+ }
+
+ MSDOS_I(inode)->i_attrs = attr & ATTR_UNUSED;
+ mark_inode_dirty(inode);
+ up:
+ up(&inode->i_sem);
+ return err;
+ }
+ default:
+ return -ENOTTY; /* Inappropriate ioctl for device */
+ }
+}
+
struct file_operations fat_file_operations = {
.llseek = generic_file_llseek,
- .read = generic_file_read,
- .write = fat_file_write,
+ .read = do_sync_read,
+ .write = do_sync_write,
+ .readv = generic_file_readv,
+ .writev = fat_file_writev,
+ .aio_read = generic_file_aio_read,
+ .aio_write = fat_file_aio_write,
.mmap = generic_file_mmap,
+ .ioctl = fat_generic_ioctl,
.fsync = file_fsync,
- .readv = generic_file_readv,
- .writev = generic_file_writev,
.sendfile = generic_file_sendfile,
};
@@ -93,62 +212,74 @@ EXPORT_SYMBOL(fat_notify_change);
static int fat_free(struct inode *inode, int skip)
{
struct super_block *sb = inode->i_sb;
- int nr, ret, fclus, dclus;
+ int err, wait, free_start, i_start, i_logstart;
if (MSDOS_I(inode)->i_start == 0)
return 0;
+ /*
+ * Write a new EOF, and get the remaining cluster chain for freeing.
+ */
+ wait = IS_DIRSYNC(inode);
if (skip) {
+ struct fat_entry fatent;
+ int ret, fclus, dclus;
+
ret = fat_get_cluster(inode, skip - 1, &fclus, &dclus);
if (ret < 0)
return ret;
else if (ret == FAT_ENT_EOF)
return 0;
- nr = fat_access(sb, dclus, -1);
- if (nr == FAT_ENT_EOF)
+ fatent_init(&fatent);
+ ret = fat_ent_read(inode, &fatent, dclus);
+ if (ret == FAT_ENT_EOF) {
+ fatent_brelse(&fatent);
return 0;
- else if (nr > 0) {
- /*
- * write a new EOF, and get the remaining cluster
- * chain for freeing.
- */
- nr = fat_access(sb, dclus, FAT_ENT_EOF);
+ } else if (ret == FAT_ENT_FREE) {
+ fat_fs_panic(sb,
+ "%s: invalid cluster chain (i_pos %lld)",
+ __FUNCTION__, MSDOS_I(inode)->i_pos);
+ ret = -EIO;
+ } else if (ret > 0) {
+ err = fat_ent_write(inode, &fatent, FAT_ENT_EOF, wait);
+ if (err)
+ ret = err;
}
- if (nr < 0)
- return nr;
+ fatent_brelse(&fatent);
+ if (ret < 0)
+ return ret;
+ free_start = ret;
+ i_start = i_logstart = 0;
fat_cache_inval_inode(inode);
} else {
fat_cache_inval_inode(inode);
- nr = MSDOS_I(inode)->i_start;
+ i_start = free_start = MSDOS_I(inode)->i_start;
+ i_logstart = MSDOS_I(inode)->i_logstart;
MSDOS_I(inode)->i_start = 0;
MSDOS_I(inode)->i_logstart = 0;
- mark_inode_dirty(inode);
}
-
- lock_fat(sb);
- do {
- nr = fat_access(sb, nr, FAT_ENT_FREE);
- if (nr < 0)
- goto error;
- else if (nr == FAT_ENT_FREE) {
- fat_fs_panic(sb, "%s: deleting beyond EOF (i_pos %lld)",
- __FUNCTION__, MSDOS_I(inode)->i_pos);
- nr = -EIO;
+ MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
+ inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC;
+ if (wait) {
+ err = fat_sync_inode(inode);
+ if (err)
goto error;
- }
- if (MSDOS_SB(sb)->free_clusters != -1)
- MSDOS_SB(sb)->free_clusters++;
- inode->i_blocks -= MSDOS_SB(sb)->cluster_size >> 9;
- } while (nr != FAT_ENT_EOF);
- fat_clusters_flush(sb);
- nr = 0;
-error:
- unlock_fat(sb);
+ } else
+ mark_inode_dirty(inode);
+ inode->i_blocks = skip << (MSDOS_SB(sb)->cluster_bits - 9);
- return nr;
+ /* Freeing the remained cluster chain */
+ return fat_free_clusters(inode, free_start);
+
+error:
+ if (i_start) {
+ MSDOS_I(inode)->i_start = i_start;
+ MSDOS_I(inode)->i_logstart = i_logstart;
+ }
+ return err;
}
void fat_truncate(struct inode *inode)
@@ -168,10 +299,7 @@ void fat_truncate(struct inode *inode)
lock_kernel();
fat_free(inode, nr_clusters);
- MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
unlock_kernel();
- inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC;
- mark_inode_dirty(inode);
}
struct inode_operations fat_file_inode_operations = {
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index 7245657c1c0a4..8ccee8415488a 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -33,6 +33,21 @@ static int fat_default_codepage = CONFIG_FAT_DEFAULT_CODEPAGE;
static char fat_default_iocharset[] = CONFIG_FAT_DEFAULT_IOCHARSET;
+static int fat_add_cluster(struct inode *inode)
+{
+ int err, cluster;
+
+ err = fat_alloc_clusters(inode, &cluster, 1);
+ if (err)
+ return err;
+ /* FIXME: this cluster should be added after data of this
+ * cluster is writed */
+ err = fat_chain_add(inode, cluster, 1);
+ if (err)
+ fat_free_clusters(inode, cluster);
+ return err;
+}
+
static int fat_get_block(struct inode *inode, sector_t iblock,
struct buffer_head *bh_result, int create)
{
@@ -55,11 +70,9 @@ static int fat_get_block(struct inode *inode, sector_t iblock,
return -EIO;
}
if (!((unsigned long)iblock & (MSDOS_SB(sb)->sec_per_clus - 1))) {
- int error;
-
- error = fat_add_cluster(inode);
- if (error < 0)
- return error;
+ err = fat_add_cluster(inode);
+ if (err)
+ return err;
}
MSDOS_I(inode)->mmu_private += sb->s_blocksize;
err = fat_bmap(inode, iblock, &phys);
@@ -220,8 +233,7 @@ static int fat_calc_dir_size(struct inode *inode)
/* doesn't deal with root inode */
static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de)
{
- struct super_block *sb = inode->i_sb;
- struct msdos_sb_info *sbi = MSDOS_SB(sb);
+ struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
int error;
MSDOS_I(inode)->i_pos = 0;
@@ -266,9 +278,10 @@ static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de)
inode->i_mapping->a_ops = &fat_aops;
MSDOS_I(inode)->mmu_private = inode->i_size;
}
- if(de->attr & ATTR_SYS)
+ if (de->attr & ATTR_SYS) {
if (sbi->options.sys_immutable)
inode->i_flags |= S_IMMUTABLE;
+ }
MSDOS_I(inode)->i_attrs = de->attr & ATTR_UNUSED;
/* this is as close to the truth as we can get ... */
inode->i_blksize = sbi->cluster_size;
@@ -277,34 +290,39 @@ static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de)
inode->i_mtime.tv_sec = inode->i_atime.tv_sec =
date_dos2unix(le16_to_cpu(de->time), le16_to_cpu(de->date));
inode->i_mtime.tv_nsec = inode->i_atime.tv_nsec = 0;
- inode->i_ctime.tv_sec =
- MSDOS_SB(sb)->options.isvfat
- ? date_dos2unix(le16_to_cpu(de->ctime), le16_to_cpu(de->cdate))
- : inode->i_mtime.tv_sec;
- inode->i_ctime.tv_nsec = de->ctime_ms * 1000000;
- MSDOS_I(inode)->i_ctime_ms = de->ctime_ms;
+ if (sbi->options.isvfat) {
+ int secs = de->ctime_cs / 100;
+ int csecs = de->ctime_cs % 100;
+ inode->i_ctime.tv_sec =
+ date_dos2unix(le16_to_cpu(de->ctime),
+ le16_to_cpu(de->cdate)) + secs;
+ inode->i_ctime.tv_nsec = csecs * 10000000;
+ } else
+ inode->i_ctime = inode->i_mtime;
return 0;
}
struct inode *fat_build_inode(struct super_block *sb,
- struct msdos_dir_entry *de, loff_t i_pos, int *res)
+ struct msdos_dir_entry *de, loff_t i_pos)
{
struct inode *inode;
- *res = 0;
+ int err;
+
inode = fat_iget(sb, i_pos);
if (inode)
goto out;
inode = new_inode(sb);
- *res = -ENOMEM;
- if (!inode)
+ if (!inode) {
+ inode = ERR_PTR(-ENOMEM);
goto out;
+ }
inode->i_ino = iunique(sb, MSDOS_ROOT_INO);
inode->i_version = 1;
- *res = fat_fill_inode(inode, de);
- if (*res < 0) {
+ err = fat_fill_inode(inode, de);
+ if (err) {
iput(inode);
- inode = NULL;
+ inode = ERR_PTR(err);
goto out;
}
fat_attach(inode, i_pos);
@@ -413,41 +431,27 @@ static void __exit fat_destroy_inodecache(void)
static int fat_remount(struct super_block *sb, int *flags, char *data)
{
- *flags |= MS_NODIRATIME;
+ struct msdos_sb_info *sbi = MSDOS_SB(sb);
+ *flags |= MS_NODIRATIME | (sbi->options.isvfat ? 0 : MS_NOATIME);
return 0;
}
static int fat_statfs(struct super_block *sb, struct kstatfs *buf)
{
struct msdos_sb_info *sbi = MSDOS_SB(sb);
- int free, nr, ret;
-
- if (sbi->free_clusters != -1)
- free = sbi->free_clusters;
- else {
- lock_fat(sb);
- if (sbi->free_clusters != -1)
- free = sbi->free_clusters;
- else {
- free = 0;
- for (nr = FAT_START_ENT; nr < sbi->max_cluster; nr++) {
- ret = fat_access(sb, nr, -1);
- if (ret < 0) {
- unlock_fat(sb);
- return ret;
- } else if (ret == FAT_ENT_FREE)
- free++;
- }
- sbi->free_clusters = free;
- }
- unlock_fat(sb);
+
+ /* If the count of free cluster is still unknown, counts it here. */
+ if (sbi->free_clusters == -1) {
+ int err = fat_count_free_clusters(sb);
+ if (err)
+ return err;
}
buf->f_type = sb->s_magic;
buf->f_bsize = sbi->cluster_size;
buf->f_blocks = sbi->max_cluster - FAT_START_ENT;
- buf->f_bfree = free;
- buf->f_bavail = free;
+ buf->f_bfree = sbi->free_clusters;
+ buf->f_bavail = sbi->free_clusters;
buf->f_namelen = sbi->options.isvfat ? 260 : 12;
return 0;
@@ -460,18 +464,20 @@ static int fat_write_inode(struct inode *inode, int wait)
struct buffer_head *bh;
struct msdos_dir_entry *raw_entry;
loff_t i_pos;
+ int err = 0;
retry:
i_pos = MSDOS_I(inode)->i_pos;
- if (inode->i_ino == MSDOS_ROOT_INO || !i_pos) {
+ if (inode->i_ino == MSDOS_ROOT_INO || !i_pos)
return 0;
- }
+
lock_kernel();
- if (!(bh = sb_bread(sb, i_pos >> sbi->dir_per_block_bits))) {
+ bh = sb_bread(sb, i_pos >> sbi->dir_per_block_bits);
+ if (!bh) {
printk(KERN_ERR "FAT: unable to read inode block "
"for updating (i_pos %lld)\n", i_pos);
- unlock_kernel();
- return -EIO;
+ err = -EIO;
+ goto out;
}
spin_lock(&sbi->inode_hash_lock);
if (i_pos != MSDOS_I(inode)->i_pos) {
@@ -483,30 +489,36 @@ retry:
raw_entry = &((struct msdos_dir_entry *) (bh->b_data))
[i_pos & (sbi->dir_per_block - 1)];
- if (S_ISDIR(inode->i_mode)) {
- raw_entry->attr = ATTR_DIR;
+ if (S_ISDIR(inode->i_mode))
raw_entry->size = 0;
- }
- else {
- raw_entry->attr = ATTR_NONE;
+ else
raw_entry->size = cpu_to_le32(inode->i_size);
- }
- raw_entry->attr |= MSDOS_MKATTR(inode->i_mode) |
- MSDOS_I(inode)->i_attrs;
+ raw_entry->attr = fat_attr(inode);
raw_entry->start = cpu_to_le16(MSDOS_I(inode)->i_logstart);
raw_entry->starthi = cpu_to_le16(MSDOS_I(inode)->i_logstart >> 16);
fat_date_unix2dos(inode->i_mtime.tv_sec, &raw_entry->time, &raw_entry->date);
if (sbi->options.isvfat) {
fat_date_unix2dos(inode->i_ctime.tv_sec,&raw_entry->ctime,&raw_entry->cdate);
- raw_entry->ctime_ms = MSDOS_I(inode)->i_ctime_ms; /* use i_ctime.tv_nsec? */
+ raw_entry->ctime_cs = (inode->i_ctime.tv_sec & 1) * 100 +
+ inode->i_ctime.tv_nsec / 10000000;
}
spin_unlock(&sbi->inode_hash_lock);
mark_buffer_dirty(bh);
+ if (wait)
+ err = sync_dirty_buffer(bh);
brelse(bh);
+out:
unlock_kernel();
- return 0;
+ return err;
+}
+
+int fat_sync_inode(struct inode *inode)
+{
+ return fat_write_inode(inode, 1);
}
+EXPORT_SYMBOL(fat_sync_inode);
+
static int fat_show_options(struct seq_file *m, struct vfsmount *mnt);
static struct super_operations fat_sops = {
.alloc_inode = fat_alloc_inode,
@@ -636,39 +648,35 @@ fat_encode_fh(struct dentry *de, __u32 *fh, int *lenp, int connectable)
static struct dentry *fat_get_parent(struct dentry *child)
{
- struct buffer_head *bh=NULL;
- struct msdos_dir_entry *de = NULL;
- struct dentry *parent = NULL;
- int res;
- loff_t i_pos = 0;
+ struct buffer_head *bh;
+ struct msdos_dir_entry *de;
+ loff_t i_pos;
+ struct dentry *parent;
struct inode *inode;
+ int err;
lock_kernel();
- res = fat_scan(child->d_inode, MSDOS_DOTDOT, &bh, &de, &i_pos);
- if (res < 0)
+ err = fat_get_dotdot_entry(child->d_inode, &bh, &de, &i_pos);
+ if (err) {
+ parent = ERR_PTR(err);
goto out;
- inode = fat_build_inode(child->d_sb, de, i_pos, &res);
- if (res)
+ }
+ inode = fat_build_inode(child->d_sb, de, i_pos);
+ brelse(bh);
+ if (IS_ERR(inode)) {
+ parent = ERR_PTR(PTR_ERR(inode));
goto out;
- if (!inode)
- res = -EACCES;
- else {
- parent = d_alloc_anon(inode);
- if (!parent) {
- iput(inode);
- res = -ENOMEM;
- }
}
-
- out:
- if(bh)
- brelse(bh);
+ parent = d_alloc_anon(inode);
+ if (!parent) {
+ iput(inode);
+ parent = ERR_PTR(-ENOMEM);
+ }
+out:
unlock_kernel();
- if (res)
- return ERR_PTR(res);
- else
- return parent;
+
+ return parent;
}
static struct export_operations fat_export_ops = {
@@ -1026,10 +1034,9 @@ static int fat_read_root(struct inode *inode)
MSDOS_I(inode)->i_logstart = 0;
MSDOS_I(inode)->mmu_private = inode->i_size;
- MSDOS_I(inode)->i_attrs = 0;
+ MSDOS_I(inode)->i_attrs = ATTR_NONE;
inode->i_mtime.tv_sec = inode->i_atime.tv_sec = inode->i_ctime.tv_sec = 0;
inode->i_mtime.tv_nsec = inode->i_atime.tv_nsec = inode->i_ctime.tv_nsec = 0;
- MSDOS_I(inode)->i_ctime_ms = 0;
inode->i_nlink = fat_subdirs(inode)+2;
return 0;
@@ -1068,10 +1075,6 @@ int fat_fill_super(struct super_block *sb, void *data, int silent,
if (error)
goto out_fail;
- /* set up enough so that it can read an inode */
- fat_hash_init(sb);
- init_MUTEX(&sbi->fat_lock);
-
error = -EIO;
sb_min_blocksize(sb, 512);
bh = sb_bread(sb, 0);
@@ -1161,7 +1164,7 @@ int fat_fill_super(struct super_block *sb, void *data, int silent,
sbi->fat_length = le16_to_cpu(b->fat_length);
sbi->root_cluster = 0;
sbi->free_clusters = -1; /* Don't know yet */
- sbi->prev_free = -1;
+ sbi->prev_free = FAT_START_ENT;
if (!sbi->fat_length && b->fat32_length) {
struct fat_boot_fsinfo *fsinfo;
@@ -1245,9 +1248,17 @@ int fat_fill_super(struct super_block *sb, void *data, int silent,
/* check the free_clusters, it's not necessarily correct */
if (sbi->free_clusters != -1 && sbi->free_clusters > total_clusters)
sbi->free_clusters = -1;
+ /* check the prev_free, it's not necessarily correct */
+ sbi->prev_free %= sbi->max_cluster;
+ if (sbi->prev_free < FAT_START_ENT)
+ sbi->prev_free = FAT_START_ENT;
brelse(bh);
+ /* set up enough so that it can read an inode */
+ fat_hash_init(sb);
+ fat_ent_access_init(sb);
+
/*
* The low byte of FAT's first entry must have same value with
* media-field. But in real world, too many devices is
diff --git a/fs/fat/misc.c b/fs/fat/misc.c
index ffe2cd9d38d6d..2a0df2122f5d3 100644
--- a/fs/fat/misc.c
+++ b/fs/fat/misc.c
@@ -33,15 +33,7 @@ void fat_fs_panic(struct super_block *s, const char *fmt, ...)
}
}
-void lock_fat(struct super_block *sb)
-{
- down(&(MSDOS_SB(sb)->fat_lock));
-}
-
-void unlock_fat(struct super_block *sb)
-{
- up(&(MSDOS_SB(sb)->fat_lock));
-}
+EXPORT_SYMBOL(fat_fs_panic);
/* Flushes the number of free clusters on FAT32 */
/* XXX: Need to write one per FSINFO block. Currently only writes 1 */
@@ -56,7 +48,7 @@ void fat_clusters_flush(struct super_block *sb)
bh = sb_bread(sb, sbi->fsinfo_sector);
if (bh == NULL) {
- printk(KERN_ERR "FAT bread failed in fat_clusters_flush\n");
+ printk(KERN_ERR "FAT: bread failed in fat_clusters_flush\n");
return;
}
@@ -75,31 +67,29 @@ 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);
}
/*
- * fat_add_cluster tries to allocate a new cluster and adds it to the
- * file represented by inode.
+ * fat_chain_add() adds a new cluster to the chain of clusters represented
+ * by inode.
*/
-int fat_add_cluster(struct inode *inode)
+int fat_chain_add(struct inode *inode, int new_dclus, int nr_cluster)
{
struct super_block *sb = inode->i_sb;
struct msdos_sb_info *sbi = MSDOS_SB(sb);
- int ret, count, limit, new_dclus, new_fclus, last;
- int cluster_bits = sbi->cluster_bits;
+ int ret, new_fclus, last;
/*
* We must locate the last cluster of the file to add this new
* one (new_dclus) to the end of the link list (the FAT).
- *
- * In order to confirm that the cluster chain is valid, we
- * find out EOF first.
*/
last = new_fclus = 0;
if (MSDOS_I(inode)->i_start) {
- int ret, fclus, dclus;
+ int fclus, dclus;
ret = fat_get_cluster(inode, FAT_ENT_EOF, &fclus, &dclus);
if (ret < 0)
@@ -108,66 +98,42 @@ int fat_add_cluster(struct inode *inode)
last = dclus;
}
- /* find free FAT entry */
- lock_fat(sb);
-
- if (sbi->free_clusters == 0) {
- unlock_fat(sb);
- return -ENOSPC;
- }
-
- limit = sbi->max_cluster;
- new_dclus = sbi->prev_free + 1;
- for (count = FAT_START_ENT; count < limit; count++, new_dclus++) {
- new_dclus = new_dclus % limit;
- if (new_dclus < FAT_START_ENT)
- new_dclus = FAT_START_ENT;
-
- ret = fat_access(sb, new_dclus, -1);
- if (ret < 0) {
- unlock_fat(sb);
- return ret;
- } else if (ret == FAT_ENT_FREE)
- break;
- }
- if (count >= limit) {
- sbi->free_clusters = 0;
- unlock_fat(sb);
- return -ENOSPC;
- }
-
- ret = fat_access(sb, new_dclus, FAT_ENT_EOF);
- if (ret < 0) {
- unlock_fat(sb);
- return ret;
- }
-
- sbi->prev_free = new_dclus;
- if (sbi->free_clusters != -1)
- sbi->free_clusters--;
- fat_clusters_flush(sb);
-
- unlock_fat(sb);
-
/* add new one to the last of the cluster chain */
if (last) {
- ret = fat_access(sb, last, new_dclus);
+ struct fat_entry fatent;
+
+ fatent_init(&fatent);
+ ret = fat_ent_read(inode, &fatent, last);
+ if (ret >= 0) {
+ int wait = inode_needs_sync(inode);
+ ret = fat_ent_write(inode, &fatent, new_dclus, wait);
+ fatent_brelse(&fatent);
+ }
if (ret < 0)
return ret;
// fat_cache_add(inode, new_fclus, new_dclus);
} else {
MSDOS_I(inode)->i_start = new_dclus;
MSDOS_I(inode)->i_logstart = new_dclus;
- mark_inode_dirty(inode);
+ /*
+ * Since generic_osync_inode() synchronize later if
+ * this is not directory, we don't here.
+ */
+ if (S_ISDIR(inode->i_mode) && IS_DIRSYNC(inode)) {
+ ret = fat_sync_inode(inode);
+ if (ret)
+ return ret;
+ } else
+ mark_inode_dirty(inode);
}
- if (new_fclus != (inode->i_blocks >> (cluster_bits - 9))) {
+ if (new_fclus != (inode->i_blocks >> (sbi->cluster_bits - 9))) {
fat_fs_panic(sb, "clusters badly computed (%d != %lu)",
- new_fclus, inode->i_blocks >> (cluster_bits - 9));
+ new_fclus, inode->i_blocks >> (sbi->cluster_bits - 9));
fat_cache_inval_inode(inode);
}
- inode->i_blocks += sbi->cluster_size >> 9;
+ inode->i_blocks += nr_cluster << (sbi->cluster_bits - 9);
- return new_dclus;
+ return 0;
}
extern struct timezone sys_tz;
@@ -230,52 +196,30 @@ void fat_date_unix2dos(int unix_date, __le16 *time, __le16 *date)
EXPORT_SYMBOL(fat_date_unix2dos);
-/* Returns the inode number of the directory entry at offset pos. If bh is
- non-NULL, it is brelse'd before. Pos is incremented. The buffer header is
- returned in bh.
- AV. Most often we do it item-by-item. Makes sense to optimize.
- AV. OK, there we go: if both bh and de are non-NULL we assume that we just
- AV. want the next entry (took one explicit de=NULL in vfat/namei.c).
- AV. It's done in fat_get_entry() (inlined), here the slow case lives.
- AV. Additionally, when we return -1 (i.e. reached the end of directory)
- AV. we make bh NULL.
- */
-
-int fat__get_entry(struct inode *dir, loff_t *pos, struct buffer_head **bh,
- struct msdos_dir_entry **de, loff_t *i_pos)
+int fat_sync_bhs(struct buffer_head **bhs, int nr_bhs)
{
- struct super_block *sb = dir->i_sb;
- struct msdos_sb_info *sbi = MSDOS_SB(sb);
- sector_t phys, iblock;
- loff_t offset;
- int err;
-
-next:
- offset = *pos;
- if (*bh)
- brelse(*bh);
-
- *bh = NULL;
- iblock = *pos >> sb->s_blocksize_bits;
- err = fat_bmap(dir, iblock, &phys);
- if (err || !phys)
- return -1; /* beyond EOF or error */
-
- *bh = sb_bread(sb, phys);
- if (*bh == NULL) {
- printk(KERN_ERR "FAT: Directory bread(block %llu) failed\n",
- (unsigned long long)phys);
- /* skip this block */
- *pos = (iblock + 1) << sb->s_blocksize_bits;
- goto next;
+ int i, e, err = 0;
+
+ for (i = 0; i < nr_bhs; i++) {
+ lock_buffer(bhs[i]);
+ if (test_clear_buffer_dirty(bhs[i])) {
+ get_bh(bhs[i]);
+ bhs[i]->b_end_io = end_buffer_write_sync;
+ e = submit_bh(WRITE, bhs[i]);
+ if (!err && e)
+ err = e;
+ } else
+ unlock_buffer(bhs[i]);
}
-
- offset &= sb->s_blocksize - 1;
- *pos += sizeof(struct msdos_dir_entry);
- *de = (struct msdos_dir_entry *)((*bh)->b_data + offset);
- *i_pos = ((loff_t)phys << sbi->dir_per_block_bits) + (offset >> MSDOS_DIR_BITS);
-
- return 0;
+ for (i = 0; i < nr_bhs; i++) {
+ wait_on_buffer(bhs[i]);
+ if (buffer_eopnotsupp(bhs[i])) {
+ clear_buffer_eopnotsupp(bhs[i]);
+ err = -EOPNOTSUPP;
+ } else if (!err && !buffer_uptodate(bhs[i]))
+ err = -EIO;
+ }
+ return err;
}
-EXPORT_SYMBOL(fat__get_entry);
+EXPORT_SYMBOL(fat_sync_bhs);
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index 6d0e70efd3990..d6efb36cab2a7 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -315,7 +315,7 @@ sync_sb_inodes(struct super_block *sb, struct writeback_control *wbc)
struct backing_dev_info *bdi = mapping->backing_dev_info;
long pages_skipped;
- if (bdi->memory_backed) {
+ if (!bdi_cap_writeback_dirty(bdi)) {
list_move(&inode->i_list, &sb->s_dirty);
if (sb == blockdev_superblock) {
/*
@@ -566,7 +566,7 @@ int write_inode_now(struct inode *inode, int sync)
.sync_mode = WB_SYNC_ALL,
};
- if (inode->i_mapping->backing_dev_info->memory_backed)
+ if (!mapping_cap_writeback_dirty(inode->i_mapping))
return 0;
might_sleep();
diff --git a/fs/hfs/bnode.c b/fs/hfs/bnode.c
index b47ab4283cca6..6ad1211f84edb 100644
--- a/fs/hfs/bnode.c
+++ b/fs/hfs/bnode.c
@@ -285,6 +285,10 @@ static struct hfs_bnode *__hfs_bnode_create(struct hfs_btree *tree, u32 cnid)
page = read_cache_page(mapping, block++, (filler_t *)mapping->a_ops->readpage, NULL);
if (IS_ERR(page))
goto fail;
+ if (PageError(page)) {
+ page_cache_release(page);
+ goto fail;
+ }
#if !REF_PAGES
page_cache_release(page);
#endif
@@ -326,12 +330,16 @@ struct hfs_bnode *hfs_bnode_find(struct hfs_btree *tree, u32 num)
hfs_bnode_get(node);
spin_unlock(&tree->hash_lock);
wait_event(node->lock_wq, !test_bit(HFS_BNODE_NEW, &node->flags));
+ if (test_bit(HFS_BNODE_ERROR, &node->flags))
+ goto node_error;
return node;
}
spin_unlock(&tree->hash_lock);
node = __hfs_bnode_create(tree, num);
if (!node)
return ERR_PTR(-ENOMEM);
+ if (test_bit(HFS_BNODE_ERROR, &node->flags))
+ goto node_error;
if (!test_bit(HFS_BNODE_NEW, &node->flags))
return node;
@@ -416,6 +424,10 @@ struct hfs_bnode *hfs_bnode_create(struct hfs_btree *tree, u32 num)
node = __hfs_bnode_create(tree, num);
if (!node)
return ERR_PTR(-ENOMEM);
+ if (test_bit(HFS_BNODE_ERROR, &node->flags)) {
+ hfs_bnode_put(node);
+ return ERR_PTR(-EIO);
+ }
pagep = node->page;
memset(kmap(*pagep) + node->page_offset, 0,
diff --git a/fs/hfs/brec.c b/fs/hfs/brec.c
index 10e986c2fcddf..7d8fff2c25fc9 100644
--- a/fs/hfs/brec.c
+++ b/fs/hfs/brec.c
@@ -10,6 +10,10 @@
#include "btree.h"
+static struct hfs_bnode *hfs_bnode_split(struct hfs_find_data *fd);
+static int hfs_brec_update_parent(struct hfs_find_data *fd);
+static int hfs_btree_inc_height(struct hfs_btree *tree);
+
/* Get the length and offset of the given record in the given node */
u16 hfs_brec_lenoff(struct hfs_bnode *node, u16 rec, u16 *off)
{
@@ -211,7 +215,7 @@ skip:
return 0;
}
-struct hfs_bnode *hfs_bnode_split(struct hfs_find_data *fd)
+static struct hfs_bnode *hfs_bnode_split(struct hfs_find_data *fd)
{
struct hfs_btree *tree;
struct hfs_bnode *node, *new_node;
@@ -320,7 +324,7 @@ struct hfs_bnode *hfs_bnode_split(struct hfs_find_data *fd)
return new_node;
}
-int hfs_brec_update_parent(struct hfs_find_data *fd)
+static int hfs_brec_update_parent(struct hfs_find_data *fd)
{
struct hfs_btree *tree;
struct hfs_bnode *node, *new_node, *parent;
@@ -418,7 +422,7 @@ out:
return 0;
}
-int hfs_btree_inc_height(struct hfs_btree *tree)
+static int hfs_btree_inc_height(struct hfs_btree *tree)
{
struct hfs_bnode *node, *new_node;
struct hfs_bnode_desc node_desc;
diff --git a/fs/hfs/btree.h b/fs/hfs/btree.h
index 87eaa9ff8355d..cc51905ac21de 100644
--- a/fs/hfs/btree.h
+++ b/fs/hfs/btree.h
@@ -111,9 +111,6 @@ extern u16 hfs_brec_lenoff(struct hfs_bnode *, u16, u16 *);
extern u16 hfs_brec_keylen(struct hfs_bnode *, u16);
extern int hfs_brec_insert(struct hfs_find_data *, void *, int);
extern int hfs_brec_remove(struct hfs_find_data *);
-extern struct hfs_bnode *hfs_bnode_split(struct hfs_find_data *);
-extern int hfs_brec_update_parent(struct hfs_find_data *);
-extern int hfs_btree_inc_height(struct hfs_btree *);
/* bfind.c */
extern int hfs_find_init(struct hfs_btree *, struct hfs_find_data *);
diff --git a/fs/hfs/catalog.c b/fs/hfs/catalog.c
index 14a5f73290528..65dedefcabfc5 100644
--- a/fs/hfs/catalog.c
+++ b/fs/hfs/catalog.c
@@ -33,7 +33,7 @@ void hfs_cat_build_key(btree_key *key, u32 parent, struct qstr *name)
}
}
-int hfs_cat_build_record(hfs_cat_rec *rec, u32 cnid, struct inode *inode)
+static int hfs_cat_build_record(hfs_cat_rec *rec, u32 cnid, struct inode *inode)
{
__be32 mtime = hfs_mtime();
diff --git a/fs/hfs/dir.c b/fs/hfs/dir.c
index ff77bd83cc81e..c55998262aed5 100644
--- a/fs/hfs/dir.c
+++ b/fs/hfs/dir.c
@@ -17,8 +17,8 @@
/*
* hfs_lookup()
*/
-struct dentry *hfs_lookup(struct inode *dir, struct dentry *dentry,
- struct nameidata *nd)
+static struct dentry *hfs_lookup(struct inode *dir, struct dentry *dentry,
+ struct nameidata *nd)
{
hfs_cat_rec rec;
struct hfs_find_data fd;
@@ -51,7 +51,7 @@ done:
/*
* hfs_readdir
*/
-int hfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
+static int hfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
{
struct inode *inode = filp->f_dentry->d_inode;
struct super_block *sb = inode->i_sb;
@@ -177,8 +177,8 @@ static int hfs_dir_release(struct inode *inode, struct file *file)
* a directory and return a corresponding inode, given the inode for
* the directory and the name (and its length) of the new file.
*/
-int hfs_create(struct inode *dir, struct dentry *dentry, int mode,
- struct nameidata *nd)
+static int hfs_create(struct inode *dir, struct dentry *dentry, int mode,
+ struct nameidata *nd)
{
struct inode *inode;
int res;
@@ -207,7 +207,7 @@ int hfs_create(struct inode *dir, struct dentry *dentry, int mode,
* in a directory, given the inode for the parent directory and the
* name (and its length) of the new directory.
*/
-int hfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
+static int hfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
{
struct inode *inode;
int res;
@@ -236,7 +236,7 @@ int hfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
* file, given the inode for the parent directory and the name
* (and its length) of the existing file.
*/
-int hfs_unlink(struct inode *dir, struct dentry *dentry)
+static int hfs_unlink(struct inode *dir, struct dentry *dentry)
{
struct inode *inode;
int res;
@@ -262,7 +262,7 @@ int hfs_unlink(struct inode *dir, struct dentry *dentry)
* directory, given the inode for the parent directory and the name
* (and its length) of the existing directory.
*/
-int hfs_rmdir(struct inode *dir, struct dentry *dentry)
+static int hfs_rmdir(struct inode *dir, struct dentry *dentry)
{
struct inode *inode;
int res;
@@ -291,8 +291,8 @@ int hfs_rmdir(struct inode *dir, struct dentry *dentry)
* new file/directory.
* XXX: how do you handle must_be dir?
*/
-int hfs_rename(struct inode *old_dir, struct dentry *old_dentry,
- struct inode *new_dir, struct dentry *new_dentry)
+static int hfs_rename(struct inode *old_dir, struct dentry *old_dentry,
+ struct inode *new_dir, struct dentry *new_dentry)
{
int res;
diff --git a/fs/hfs/extent.c b/fs/hfs/extent.c
index 2ea3c8932bd30..cbc8510ad2221 100644
--- a/fs/hfs/extent.c
+++ b/fs/hfs/extent.c
@@ -49,22 +49,21 @@ static void hfs_ext_build_key(hfs_btree_key *key, u32 cnid, u16 block, u8 type)
* This function has no side-effects */
int hfs_ext_keycmp(const btree_key *key1, const btree_key *key2)
{
- unsigned int tmp;
- int retval;
-
- tmp = be32_to_cpu(key1->ext.FNum) - be32_to_cpu(key2->ext.FNum);
- if (tmp != 0) {
- retval = (int)tmp;
- } else {
- tmp = (unsigned char)key1->ext.FkType - (unsigned char)key2->ext.FkType;
- if (tmp != 0) {
- retval = (int)tmp;
- } else {
- retval = (int)(be16_to_cpu(key1->ext.FABN)
- - be16_to_cpu(key2->ext.FABN));
- }
- }
- return retval;
+ __be32 fnum1, fnum2;
+ __be16 block1, block2;
+
+ fnum1 = key1->ext.FNum;
+ fnum2 = key2->ext.FNum;
+ if (fnum1 != fnum2)
+ return be32_to_cpu(fnum1) < be32_to_cpu(fnum2) ? -1 : 1;
+ if (key1->ext.FkType != key2->ext.FkType)
+ return key1->ext.FkType < key2->ext.FkType ? -1 : 1;
+
+ block1 = key1->ext.FABN;
+ block2 = key2->ext.FABN;
+ if (block1 == block2)
+ return 0;
+ return be16_to_cpu(block1) < be16_to_cpu(block2) ? -1 : 1;
}
/*
@@ -231,8 +230,8 @@ static int hfs_add_extent(struct hfs_extent *extent, u16 offset,
return -EIO;
}
-int hfs_free_extents(struct super_block *sb, struct hfs_extent *extent,
- u16 offset, u16 block_nr)
+static int hfs_free_extents(struct super_block *sb, struct hfs_extent *extent,
+ u16 offset, u16 block_nr)
{
u16 count, start;
int i;
diff --git a/fs/hfs/hfs_fs.h b/fs/hfs/hfs_fs.h
index 03634a3674615..0dc8ef8e14de6 100644
--- a/fs/hfs/hfs_fs.h
+++ b/fs/hfs/hfs_fs.h
@@ -174,12 +174,6 @@ extern void hfs_cat_build_key(btree_key *, u32, struct qstr *);
extern struct file_operations hfs_dir_operations;
extern struct inode_operations hfs_dir_inode_operations;
-extern int hfs_mkdir(struct inode *, struct dentry *, int);
-extern int hfs_unlink(struct inode *, struct dentry *);
-extern int hfs_rmdir(struct inode *, struct dentry *);
-extern int hfs_rename(struct inode *, struct dentry *,
- struct inode *, struct dentry *);
-
/* extent.c */
extern int hfs_ext_keycmp(const btree_key *, const btree_key *);
extern int hfs_free_fork(struct super_block *, struct hfs_cat_file *, int);
@@ -187,10 +181,6 @@ extern void hfs_ext_write_extent(struct inode *);
extern int hfs_extend_file(struct inode *);
extern void hfs_file_truncate(struct inode *);
-/* file.c */
-extern struct inode_operations hfs_file_inode_operations;
-extern struct file_operations hfs_file_operations;
-
extern int hfs_get_block(struct inode *, sector_t, struct buffer_head *, int);
/* inode.c */
diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c
index 674acb1400bcf..7519123260945 100644
--- a/fs/hfs/inode.c
+++ b/fs/hfs/inode.c
@@ -18,6 +18,9 @@
#include "hfs_fs.h"
#include "btree.h"
+static struct file_operations hfs_file_operations;
+static struct inode_operations hfs_file_inode_operations;
+
/*================ Variable-like macros ================*/
#define HFS_VALID_MODE_BITS (S_IFREG | S_IFDIR | S_IRWXUGO)
@@ -43,7 +46,7 @@ static sector_t hfs_bmap(struct address_space *mapping, sector_t block)
return generic_block_bmap(mapping, block, hfs_get_block);
}
-int hfs_releasepage(struct page *page, int mask)
+static int hfs_releasepage(struct page *page, int mask)
{
struct inode *inode = page->mapping->host;
struct super_block *sb = inode->i_sb;
@@ -71,12 +74,6 @@ int hfs_releasepage(struct page *page, int mask)
;
else if (atomic_read(&node->refcnt))
res = 0;
- else for (i = 0; i < tree->pages_per_bnode; i++) {
- if (PageActive(node->page[i])) {
- res = 0;
- break;
- }
- }
if (res && node) {
hfs_bnode_unhash(node);
hfs_bnode_free(node);
@@ -100,7 +97,7 @@ int hfs_releasepage(struct page *page, int mask)
spin_unlock(&tree->hash_lock);
}
//printk("releasepage: %lu,%x = %d\n", page->index, mask, res);
- return res;
+ return res ? try_to_free_buffers(page) : 0;
}
static int hfs_get_blocks(struct inode *inode, sector_t iblock, unsigned long max_blocks,
@@ -174,14 +171,16 @@ struct inode *hfs_new_inode(struct inode *dir, struct qstr *name, int mode)
HFS_I(inode)->flags = 0;
HFS_I(inode)->rsrc_inode = NULL;
HFS_I(inode)->fs_blocks = 0;
- if (S_ISDIR(inode->i_mode)) {
+ if (S_ISDIR(mode)) {
inode->i_size = 2;
HFS_SB(sb)->folder_count++;
if (dir->i_ino == HFS_ROOT_CNID)
HFS_SB(sb)->root_dirs++;
inode->i_op = &hfs_dir_inode_operations;
inode->i_fop = &hfs_dir_operations;
- } else if (S_ISREG(inode->i_mode)) {
+ inode->i_mode |= S_IRWXUGO;
+ inode->i_mode &= ~HFS_SB(inode->i_sb)->s_dir_umask;
+ } else if (S_ISREG(mode)) {
HFS_I(inode)->clump_blocks = HFS_SB(sb)->clumpablks;
HFS_SB(sb)->file_count++;
if (dir->i_ino == HFS_ROOT_CNID)
@@ -189,6 +188,10 @@ struct inode *hfs_new_inode(struct inode *dir, struct qstr *name, int mode)
inode->i_op = &hfs_file_inode_operations;
inode->i_fop = &hfs_file_operations;
inode->i_mapping->a_ops = &hfs_aops;
+ inode->i_mode |= S_IRUGO|S_IXUGO;
+ if (mode & S_IWUSR)
+ inode->i_mode |= S_IWUGO;
+ inode->i_mode &= ~HFS_SB(inode->i_sb)->s_file_umask;
HFS_I(inode)->phys_size = 0;
HFS_I(inode)->alloc_blocks = 0;
HFS_I(inode)->first_blocks = 0;
@@ -259,7 +262,7 @@ struct hfs_iget_data {
hfs_cat_rec *rec;
};
-int hfs_test_inode(struct inode *inode, void *data)
+static int hfs_test_inode(struct inode *inode, void *data)
{
struct hfs_iget_data *idata = data;
hfs_cat_rec *rec;
@@ -279,7 +282,7 @@ int hfs_test_inode(struct inode *inode, void *data)
/*
* hfs_read_inode
*/
-int hfs_read_inode(struct inode *inode, void *data)
+static int hfs_read_inode(struct inode *inode, void *data)
{
struct hfs_iget_data *idata = data;
struct hfs_sb_info *hsb = HFS_SB(inode->i_sb);
@@ -317,7 +320,7 @@ int hfs_read_inode(struct inode *inode, void *data)
inode->i_mode = S_IRUGO | S_IXUGO;
if (!(rec->file.Flags & HFS_FIL_LOCK))
inode->i_mode |= S_IWUGO;
- inode->i_mode &= hsb->s_file_umask;
+ inode->i_mode &= ~hsb->s_file_umask;
inode->i_mode |= S_IFREG;
inode->i_ctime = inode->i_atime = inode->i_mtime =
hfs_m_to_utime(rec->file.MdDat);
@@ -329,7 +332,7 @@ int hfs_read_inode(struct inode *inode, void *data)
inode->i_ino = be32_to_cpu(rec->dir.DirID);
inode->i_size = be16_to_cpu(rec->dir.Val) + 2;
HFS_I(inode)->fs_blocks = 0;
- inode->i_mode = S_IFDIR | (S_IRWXUGO & hsb->s_dir_umask);
+ inode->i_mode = S_IFDIR | (S_IRWXUGO & ~hsb->s_dir_umask);
inode->i_ctime = inode->i_atime = inode->i_mtime =
hfs_m_to_utime(rec->dir.MdDat);
inode->i_op = &hfs_dir_inode_operations;
@@ -611,7 +614,7 @@ int hfs_inode_setattr(struct dentry *dentry, struct iattr * attr)
}
-struct file_operations hfs_file_operations = {
+static struct file_operations hfs_file_operations = {
.llseek = generic_file_llseek,
.read = generic_file_read,
.write = generic_file_write,
@@ -622,7 +625,7 @@ struct file_operations hfs_file_operations = {
.release = hfs_file_release,
};
-struct inode_operations hfs_file_inode_operations = {
+static struct inode_operations hfs_file_inode_operations = {
.lookup = hfs_file_lookup,
.truncate = hfs_file_truncate,
.setattr = hfs_inode_setattr,
diff --git a/fs/hfs/super.c b/fs/hfs/super.c
index 884aeace678db..1e2c193134cc8 100644
--- a/fs/hfs/super.c
+++ b/fs/hfs/super.c
@@ -16,13 +16,12 @@
#include <linux/module.h>
#include <linux/blkdev.h>
#include <linux/init.h>
+#include <linux/parser.h>
#include <linux/vfs.h>
#include "hfs_fs.h"
#include "btree.h"
-const char hfs_version[]="0.96";
-
static kmem_cache_t *hfs_inode_cachep;
MODULE_LICENSE("GPL");
@@ -92,7 +91,7 @@ static int hfs_statfs(struct super_block *sb, struct kstatfs *buf)
return 0;
}
-int hfs_remount(struct super_block *sb, int *flags, char *data)
+static int hfs_remount(struct super_block *sb, int *flags, char *data)
{
*flags |= MS_NODIRATIME;
if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
@@ -136,6 +135,34 @@ static struct super_operations hfs_super_operations = {
.remount_fs = hfs_remount,
};
+enum {
+ opt_uid, opt_gid, opt_umask, opt_file_umask, opt_dir_umask,
+ opt_part, opt_session, opt_type, opt_creator, opt_quiet,
+ opt_err
+};
+
+static match_table_t tokens = {
+ { opt_uid, "uid=%u" },
+ { opt_gid, "gid=%u" },
+ { opt_umask, "umask=%o" },
+ { opt_file_umask, "file_umask=%o" },
+ { opt_dir_umask, "dir_umask=%o" },
+ { opt_part, "part=%u" },
+ { opt_session, "session=%u" },
+ { opt_type, "type=%s" },
+ { opt_creator, "creator=%s" },
+ { opt_quiet, "quiet" },
+ { opt_err, NULL }
+};
+
+static inline int match_fourchar(substring_t *arg, u32 *result)
+{
+ if (arg->to - arg->from != 4)
+ return -EINVAL;
+ memcpy(result, arg->from, 4);
+ return 0;
+}
+
/*
* parse_options()
*
@@ -144,13 +171,15 @@ static struct super_operations hfs_super_operations = {
*/
static int parse_options(char *options, struct hfs_sb_info *hsb)
{
- char *this_char, *value;
+ char *p;
+ substring_t args[MAX_OPT_ARGS];
+ int tmp, token;
/* initialize the sb with defaults */
hsb->s_uid = current->uid;
hsb->s_gid = current->gid;
- hsb->s_file_umask = 0644;
- hsb->s_dir_umask = 0755;
+ hsb->s_file_umask = 0133;
+ hsb->s_dir_umask = 0022;
hsb->s_type = hsb->s_creator = cpu_to_be32(0x3f3f3f3f); /* == '????' */
hsb->s_quiet = 0;
hsb->part = -1;
@@ -159,77 +188,82 @@ static int parse_options(char *options, struct hfs_sb_info *hsb)
if (!options)
return 1;
- while ((this_char = strsep(&options, ",")) != 0) {
- if (!*this_char)
+ while ((p = strsep(&options, ",")) != NULL) {
+ if (!*p)
continue;
- value = strchr(this_char, '=');
- if (value)
- *value++ = 0;
- /* Numeric-valued options */
- if (!strcmp(this_char, "uid")) {
- if (!value || !*value)
+ token = match_token(p, tokens, args);
+ switch (token) {
+ case opt_uid:
+ if (match_int(&args[0], &tmp)) {
+ printk("HFS: uid requires an argument\n");
return 0;
- hsb->s_uid = simple_strtoul(value, &value, 0);
- if (*value)
+ }
+ hsb->s_uid = (uid_t)tmp;
+ break;
+ case opt_gid:
+ if (match_int(&args[0], &tmp)) {
+ printk("HFS: gid requires an argument\n");
return 0;
- } else if (!strcmp(this_char, "gid")) {
- if (!value || !*value)
+ }
+ hsb->s_gid = (gid_t)tmp;
+ break;
+ case opt_umask:
+ if (match_octal(&args[0], &tmp)) {
+ printk("HFS: umask requires a value\n");
return 0;
- hsb->s_gid = simple_strtoul(value, &value, 0);
- if (*value)
+ }
+ hsb->s_file_umask = (umode_t)tmp;
+ hsb->s_dir_umask = (umode_t)tmp;
+ break;
+ case opt_file_umask:
+ if (match_octal(&args[0], &tmp)) {
+ printk("HFS: file_umask requires a value\n");
return 0;
- } else if (!strcmp(this_char, "umask")) {
- if (!value || !*value)
+ }
+ 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");
return 0;
- hsb->s_file_umask = simple_strtoul(value, &value, 8);
- hsb->s_dir_umask = hsb->s_file_umask;
- if (*value)
+ }
+ 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");
return 0;
- } else if (!strcmp(this_char, "file_umask")) {
- if (!value || !*value)
+ }
+ break;
+ case opt_session:
+ if (match_int(&args[0], &hsb->session)) {
+ printk("HFS: session requires an argument\n");
return 0;
- hsb->s_file_umask = simple_strtoul(value, &value, 8);
- if (*value)
+ }
+ break;
+ case opt_type:
+ if (match_fourchar(&args[0], &hsb->s_type)) {
+ printk("HFS+-fs: type requires a 4 character value\n");
return 0;
- } else if (!strcmp(this_char, "dir_umask")) {
- if (!value || !*value)
- return 0;
- hsb->s_dir_umask = simple_strtoul(value, &value, 8);
- if (*value)
- return 0;
- } else if (!strcmp(this_char, "part")) {
- if (!value || !*value)
- return 0;
- hsb->part = simple_strtoul(value, &value, 0);
- if (*value)
- return 0;
- } else if (!strcmp(this_char, "session")) {
- if (!value || !*value)
- return 0;
- hsb->session = simple_strtoul(value, &value, 0);
- if (*value)
- return 0;
- /* String-valued options */
- } else if (!strcmp(this_char, "type") && value) {
- if (strlen(value) != 4)
- return 0;
- memcpy(&hsb->s_type, value, 4);
- } else if (!strcmp(this_char, "creator") && value) {
- if (strlen(value) != 4)
- return 0;
- memcpy(&hsb->s_creator, value, 4);
- /* Boolean-valued options */
- } else if (!strcmp(this_char, "quiet")) {
- if (value)
+ }
+ break;
+ case opt_creator:
+ if (match_fourchar(&args[0], &hsb->s_creator)) {
+ printk("HFS+-fs: creator requires a 4 character value\n");
return 0;
+ }
+ break;
+ case opt_quiet:
hsb->s_quiet = 1;
- } else
+ break;
+ default:
return 0;
+ }
}
hsb->s_dir_umask &= 0777;
- hsb->s_file_umask &= 0777;
+ hsb->s_file_umask &= 0577;
return 1;
}
diff --git a/fs/hfsplus/bnode.c b/fs/hfsplus/bnode.c
index e0edb707ce77a..267872e84d714 100644
--- a/fs/hfsplus/bnode.c
+++ b/fs/hfsplus/bnode.c
@@ -446,6 +446,10 @@ static struct hfs_bnode *__hfs_bnode_create(struct hfs_btree *tree, u32 cnid)
page = read_cache_page(mapping, block, (filler_t *)mapping->a_ops->readpage, NULL);
if (IS_ERR(page))
goto fail;
+ if (PageError(page)) {
+ page_cache_release(page);
+ goto fail;
+ }
#if !REF_PAGES
page_cache_release(page);
#endif
@@ -487,12 +491,16 @@ struct hfs_bnode *hfs_bnode_find(struct hfs_btree *tree, u32 num)
hfs_bnode_get(node);
spin_unlock(&tree->hash_lock);
wait_event(node->lock_wq, !test_bit(HFS_BNODE_NEW, &node->flags));
+ if (test_bit(HFS_BNODE_ERROR, &node->flags))
+ goto node_error;
return node;
}
spin_unlock(&tree->hash_lock);
node = __hfs_bnode_create(tree, num);
if (!node)
return ERR_PTR(-ENOMEM);
+ if (test_bit(HFS_BNODE_ERROR, &node->flags))
+ goto node_error;
if (!test_bit(HFS_BNODE_NEW, &node->flags))
return node;
@@ -579,6 +587,10 @@ struct hfs_bnode *hfs_bnode_create(struct hfs_btree *tree, u32 num)
node = __hfs_bnode_create(tree, num);
if (!node)
return ERR_PTR(-ENOMEM);
+ if (test_bit(HFS_BNODE_ERROR, &node->flags)) {
+ hfs_bnode_put(node);
+ return ERR_PTR(-EIO);
+ }
pagep = node->page;
memset(kmap(*pagep) + node->page_offset, 0,
@@ -648,14 +660,3 @@ void hfs_bnode_put(struct hfs_bnode *node)
}
}
-void hfsplus_lock_bnode(struct hfs_bnode *node)
-{
- wait_event(node->lock_wq, !test_and_set_bit(HFS_BNODE_LOCK, &node->flags));
-}
-
-void hfsplus_unlock_bnode(struct hfs_bnode *node)
-{
- clear_bit(HFS_BNODE_LOCK, &node->flags);
- if (waitqueue_active(&node->lock_wq))
- wake_up(&node->lock_wq);
-}
diff --git a/fs/hfsplus/brec.c b/fs/hfsplus/brec.c
index f5df0a3b2974f..0ccef2ab790c0 100644
--- a/fs/hfsplus/brec.c
+++ b/fs/hfsplus/brec.c
@@ -11,6 +11,10 @@
#include "hfsplus_fs.h"
#include "hfsplus_raw.h"
+static struct hfs_bnode *hfs_bnode_split(struct hfs_find_data *fd);
+static int hfs_brec_update_parent(struct hfs_find_data *fd);
+static int hfs_btree_inc_height(struct hfs_btree *);
+
/* Get the length and offset of the given record in the given node */
u16 hfs_brec_lenoff(struct hfs_bnode *node, u16 rec, u16 *off)
{
@@ -209,7 +213,7 @@ skip:
return 0;
}
-struct hfs_bnode *hfs_bnode_split(struct hfs_find_data *fd)
+static struct hfs_bnode *hfs_bnode_split(struct hfs_find_data *fd)
{
struct hfs_btree *tree;
struct hfs_bnode *node, *new_node;
@@ -318,7 +322,7 @@ struct hfs_bnode *hfs_bnode_split(struct hfs_find_data *fd)
return new_node;
}
-int hfs_brec_update_parent(struct hfs_find_data *fd)
+static int hfs_brec_update_parent(struct hfs_find_data *fd)
{
struct hfs_btree *tree;
struct hfs_bnode *node, *new_node, *parent;
@@ -414,7 +418,7 @@ out:
return 0;
}
-int hfs_btree_inc_height(struct hfs_btree *tree)
+static int hfs_btree_inc_height(struct hfs_btree *tree)
{
struct hfs_bnode *node, *new_node;
struct hfs_bnode_desc node_desc;
diff --git a/fs/hfsplus/catalog.c b/fs/hfsplus/catalog.c
index 8f194a492a27c..94712790c8b3f 100644
--- a/fs/hfsplus/catalog.c
+++ b/fs/hfsplus/catalog.c
@@ -25,14 +25,14 @@ int hfsplus_cat_cmp_key(hfsplus_btree_key *k1, hfsplus_btree_key *k2)
return hfsplus_unistrcmp(&k1->cat.name, &k2->cat.name);
}
-void hfsplus_cat_build_key(hfsplus_btree_key *key, u32 parent,
- struct qstr *str)
+void hfsplus_cat_build_key(struct super_block *sb, hfsplus_btree_key *key,
+ u32 parent, struct qstr *str)
{
int len;
key->cat.parent = cpu_to_be32(parent);
if (str) {
- hfsplus_asc2uni(&key->cat.name, str->name, str->len);
+ hfsplus_asc2uni(sb, &key->cat.name, str->name, str->len);
len = be16_to_cpu(key->cat.name.length);
} else {
key->cat.name.length = 0;
@@ -113,13 +113,14 @@ static int hfsplus_cat_build_record(hfsplus_cat_entry *entry, u32 cnid, struct i
}
}
-static int hfsplus_fill_cat_thread(hfsplus_cat_entry *entry, int type,
+static int hfsplus_fill_cat_thread(struct super_block *sb,
+ hfsplus_cat_entry *entry, int type,
u32 parentid, struct qstr *str)
{
entry->type = cpu_to_be16(type);
entry->thread.reserved = 0;
entry->thread.parentID = cpu_to_be32(parentid);
- hfsplus_asc2uni(&entry->thread.nodeName, str->name, str->len);
+ hfsplus_asc2uni(sb, &entry->thread.nodeName, str->name, str->len);
return 10 + be16_to_cpu(entry->thread.nodeName.length) * 2;
}
@@ -131,7 +132,7 @@ int hfsplus_find_cat(struct super_block *sb, u32 cnid,
int err;
u16 type;
- hfsplus_cat_build_key(fd->search_key, cnid, NULL);
+ hfsplus_cat_build_key(sb, fd->search_key, cnid, NULL);
err = hfs_brec_read(fd, &tmp, sizeof(hfsplus_cat_entry));
if (err)
return err;
@@ -159,8 +160,8 @@ int hfsplus_create_cat(u32 cnid, struct inode *dir, struct qstr *str, struct ino
sb = dir->i_sb;
hfs_find_init(HFSPLUS_SB(sb).cat_tree, &fd);
- hfsplus_cat_build_key(fd.search_key, cnid, NULL);
- entry_size = hfsplus_fill_cat_thread(&entry, S_ISDIR(inode->i_mode) ?
+ hfsplus_cat_build_key(sb, fd.search_key, cnid, NULL);
+ entry_size = hfsplus_fill_cat_thread(sb, &entry, S_ISDIR(inode->i_mode) ?
HFSPLUS_FOLDER_THREAD : HFSPLUS_FILE_THREAD,
dir->i_ino, str);
err = hfs_brec_find(&fd);
@@ -173,7 +174,7 @@ int hfsplus_create_cat(u32 cnid, struct inode *dir, struct qstr *str, struct ino
if (err)
goto err2;
- hfsplus_cat_build_key(fd.search_key, dir->i_ino, str);
+ hfsplus_cat_build_key(sb, fd.search_key, dir->i_ino, str);
entry_size = hfsplus_cat_build_record(&entry, cnid, inode);
err = hfs_brec_find(&fd);
if (err != -ENOENT) {
@@ -193,7 +194,7 @@ int hfsplus_create_cat(u32 cnid, struct inode *dir, struct qstr *str, struct ino
return 0;
err1:
- hfsplus_cat_build_key(fd.search_key, cnid, NULL);
+ hfsplus_cat_build_key(sb, fd.search_key, cnid, NULL);
if (!hfs_brec_find(&fd))
hfs_brec_remove(&fd);
err2:
@@ -217,7 +218,7 @@ int hfsplus_delete_cat(u32 cnid, struct inode *dir, struct qstr *str)
if (!str) {
int len;
- hfsplus_cat_build_key(fd.search_key, cnid, NULL);
+ hfsplus_cat_build_key(sb, fd.search_key, cnid, NULL);
err = hfs_brec_find(&fd);
if (err)
goto out;
@@ -229,7 +230,7 @@ int hfsplus_delete_cat(u32 cnid, struct inode *dir, struct qstr *str)
hfs_bnode_read(fd.bnode, &fd.search_key->cat.name.unicode, off + 2, len);
fd.search_key->key_len = cpu_to_be16(6 + len);
} else
- hfsplus_cat_build_key(fd.search_key, dir->i_ino, str);
+ hfsplus_cat_build_key(sb, fd.search_key, dir->i_ino, str);
err = hfs_brec_find(&fd);
if (err)
@@ -259,7 +260,7 @@ int hfsplus_delete_cat(u32 cnid, struct inode *dir, struct qstr *str)
if (err)
goto out;
- hfsplus_cat_build_key(fd.search_key, cnid, NULL);
+ hfsplus_cat_build_key(sb, fd.search_key, cnid, NULL);
err = hfs_brec_find(&fd);
if (err)
goto out;
@@ -294,7 +295,7 @@ int hfsplus_rename_cat(u32 cnid,
dst_fd = src_fd;
/* find the old dir entry and read the data */
- hfsplus_cat_build_key(src_fd.search_key, src_dir->i_ino, src_name);
+ hfsplus_cat_build_key(sb, src_fd.search_key, src_dir->i_ino, src_name);
err = hfs_brec_find(&src_fd);
if (err)
goto out;
@@ -303,7 +304,7 @@ int hfsplus_rename_cat(u32 cnid,
src_fd.entrylength);
/* create new dir entry with the data from the old entry */
- hfsplus_cat_build_key(dst_fd.search_key, dst_dir->i_ino, dst_name);
+ hfsplus_cat_build_key(sb, dst_fd.search_key, dst_dir->i_ino, dst_name);
err = hfs_brec_find(&dst_fd);
if (err != -ENOENT) {
if (!err)
@@ -319,7 +320,7 @@ int hfsplus_rename_cat(u32 cnid,
mark_inode_dirty(dst_dir);
/* finally remove the old entry */
- hfsplus_cat_build_key(src_fd.search_key, src_dir->i_ino, src_name);
+ hfsplus_cat_build_key(sb, src_fd.search_key, src_dir->i_ino, src_name);
err = hfs_brec_find(&src_fd);
if (err)
goto out;
@@ -331,7 +332,7 @@ int hfsplus_rename_cat(u32 cnid,
mark_inode_dirty(src_dir);
/* remove old thread entry */
- hfsplus_cat_build_key(src_fd.search_key, cnid, NULL);
+ hfsplus_cat_build_key(sb, src_fd.search_key, cnid, NULL);
err = hfs_brec_find(&src_fd);
if (err)
goto out;
@@ -341,8 +342,8 @@ int hfsplus_rename_cat(u32 cnid,
goto out;
/* create new thread entry */
- hfsplus_cat_build_key(dst_fd.search_key, cnid, NULL);
- entry_size = hfsplus_fill_cat_thread(&entry, type, dst_dir->i_ino, dst_name);
+ hfsplus_cat_build_key(sb, dst_fd.search_key, cnid, NULL);
+ entry_size = hfsplus_fill_cat_thread(sb, &entry, type, dst_dir->i_ino, dst_name);
err = hfs_brec_find(&dst_fd);
if (err != -ENOENT) {
if (!err)
diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c
index 1c62bb82d0414..7bda76667a4af 100644
--- a/fs/hfsplus/dir.c
+++ b/fs/hfsplus/dir.c
@@ -40,7 +40,7 @@ static struct dentry *hfsplus_lookup(struct inode *dir, struct dentry *dentry,
sb = dir->i_sb;
dentry->d_fsdata = NULL;
hfs_find_init(HFSPLUS_SB(sb).cat_tree, &fd);
- hfsplus_cat_build_key(fd.search_key, dir->i_ino, &dentry->d_name);
+ hfsplus_cat_build_key(sb, fd.search_key, dir->i_ino, &dentry->d_name);
again:
err = hfs_brec_read(&fd, &entry, sizeof(entry));
if (err) {
@@ -80,7 +80,7 @@ again:
linkid = be32_to_cpu(entry.file.permissions.dev);
str.len = sprintf(name, "iNode%d", linkid);
str.name = name;
- hfsplus_cat_build_key(fd.search_key, HFSPLUS_SB(sb).hidden_dir->i_ino, &str);
+ 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;
@@ -118,7 +118,7 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir)
return 0;
hfs_find_init(HFSPLUS_SB(sb).cat_tree, &fd);
- hfsplus_cat_build_key(fd.search_key, inode->i_ino, NULL);
+ hfsplus_cat_build_key(sb, fd.search_key, inode->i_ino, NULL);
err = hfs_brec_find(&fd);
if (err)
goto out;
@@ -164,7 +164,7 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir)
hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, fd.entrylength);
type = be16_to_cpu(entry.type);
len = HFSPLUS_MAX_STRLEN;
- err = hfsplus_uni2asc(&fd.key->cat.name, strbuf, &len);
+ err = hfsplus_uni2asc(sb, &fd.key->cat.name, strbuf, &len);
if (err)
goto out;
if (type == HFSPLUS_FOLDER) {
@@ -228,8 +228,8 @@ static int hfsplus_dir_release(struct inode *inode, struct file *file)
return 0;
}
-int hfsplus_create(struct inode *dir, struct dentry *dentry, int mode,
- struct nameidata *nd)
+static int hfsplus_create(struct inode *dir, struct dentry *dentry, int mode,
+ struct nameidata *nd)
{
struct inode *inode;
int res;
@@ -250,7 +250,8 @@ int hfsplus_create(struct inode *dir, struct dentry *dentry, int mode,
return 0;
}
-int hfsplus_link(struct dentry *src_dentry, struct inode *dst_dir, struct dentry *dst_dentry)
+static int hfsplus_link(struct dentry *src_dentry, struct inode *dst_dir,
+ struct dentry *dst_dentry)
{
struct super_block *sb = dst_dir->i_sb;
struct inode *inode = src_dentry->d_inode;
@@ -302,7 +303,7 @@ int hfsplus_link(struct dentry *src_dentry, struct inode *dst_dir, struct dentry
return 0;
}
-int hfsplus_unlink(struct inode *dir, struct dentry *dentry)
+static int hfsplus_unlink(struct inode *dir, struct dentry *dentry)
{
struct super_block *sb = dir->i_sb;
struct inode *inode = dentry->d_inode;
@@ -346,7 +347,7 @@ int hfsplus_unlink(struct inode *dir, struct dentry *dentry)
return res;
}
-int hfsplus_mkdir(struct inode *dir, struct dentry *dentry, int mode)
+static int hfsplus_mkdir(struct inode *dir, struct dentry *dentry, int mode)
{
struct inode *inode;
int res;
@@ -367,7 +368,7 @@ int hfsplus_mkdir(struct inode *dir, struct dentry *dentry, int mode)
return 0;
}
-int hfsplus_rmdir(struct inode *dir, struct dentry *dentry)
+static int hfsplus_rmdir(struct inode *dir, struct dentry *dentry)
{
struct inode *inode;
int res;
@@ -385,7 +386,8 @@ int hfsplus_rmdir(struct inode *dir, struct dentry *dentry)
return 0;
}
-int hfsplus_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
+static int hfsplus_symlink(struct inode *dir, struct dentry *dentry,
+ const char *symname)
{
struct super_block *sb;
struct inode *inode;
@@ -415,7 +417,8 @@ int hfsplus_symlink(struct inode *dir, struct dentry *dentry, const char *symnam
return res;
}
-int hfsplus_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
+static int hfsplus_mknod(struct inode *dir, struct dentry *dentry,
+ int mode, dev_t rdev)
{
struct super_block *sb;
struct inode *inode;
@@ -440,8 +443,8 @@ int hfsplus_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev
return 0;
}
-int hfsplus_rename(struct inode *old_dir, struct dentry *old_dentry,
- struct inode *new_dir, struct dentry *new_dentry)
+static int hfsplus_rename(struct inode *old_dir, struct dentry *old_dentry,
+ struct inode *new_dir, struct dentry *new_dentry)
{
int res;
diff --git a/fs/hfsplus/extents.c b/fs/hfsplus/extents.c
index bfc8657a8ae29..376498cc64fdd 100644
--- a/fs/hfsplus/extents.c
+++ b/fs/hfsplus/extents.c
@@ -37,8 +37,8 @@ int hfsplus_ext_cmp_key(hfsplus_btree_key *k1, hfsplus_btree_key *k2)
return be32_to_cpu(k1s) < be32_to_cpu(k2s) ? -1 : 1;
}
-void hfsplus_ext_build_key(hfsplus_btree_key *key, u32 cnid,
- u32 block, u8 type)
+static void hfsplus_ext_build_key(hfsplus_btree_key *key, u32 cnid,
+ u32 block, u8 type)
{
key->key_len = cpu_to_be16(HFSPLUS_EXT_KEYLEN - 2);
key->ext.cnid = cpu_to_be32(cnid);
@@ -263,8 +263,9 @@ static int hfsplus_add_extent(struct hfsplus_extent *extent, u32 offset,
return -EIO;
}
-int hfsplus_free_extents(struct super_block *sb, struct hfsplus_extent *extent,
- u32 offset, u32 block_nr)
+static int hfsplus_free_extents(struct super_block *sb,
+ struct hfsplus_extent *extent,
+ u32 offset, u32 block_nr)
{
u32 count, start;
int i;
diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h
index 4d976d286cab1..533094a570df3 100644
--- a/fs/hfsplus/hfsplus_fs.h
+++ b/fs/hfsplus/hfsplus_fs.h
@@ -114,6 +114,7 @@ struct hfsplus_sb_info {
struct hfs_btree *attr_tree;
struct inode *alloc_file;
struct inode *hidden_dir;
+ struct nls_table *nls;
/* Runtime variables */
u32 blockoffset;
@@ -150,6 +151,7 @@ struct hfsplus_sb_info {
};
#define HFSPLUS_SB_WRITEBACKUP 0x0001
+#define HFSPLUS_SB_NODECOMPOSE 0x0002
struct hfsplus_inode_info {
@@ -230,9 +232,6 @@ struct hfsplus_readdir_data {
#define hfs_brec_keylen hfsplus_brec_keylen
#define hfs_brec_insert hfsplus_brec_insert
#define hfs_brec_remove hfsplus_brec_remove
-#define hfs_bnode_split hfsplus_bnode_split
-#define hfs_brec_update_parent hfsplus_brec_update_parent
-#define hfs_btree_inc_height hfsplus_btree_inc_height
#define hfs_find_init hfsplus_find_init
#define hfs_find_exit hfsplus_find_exit
#define __hfs_brec_find __hplusfs_brec_find
@@ -297,9 +296,6 @@ u16 hfs_brec_lenoff(struct hfs_bnode *, u16, u16 *);
u16 hfs_brec_keylen(struct hfs_bnode *, u16);
int hfs_brec_insert(struct hfs_find_data *, void *, int);
int hfs_brec_remove(struct hfs_find_data *);
-struct hfs_bnode *hfs_bnode_split(struct hfs_find_data *);
-int hfs_brec_update_parent(struct hfs_find_data *);
-int hfs_btree_inc_height(struct hfs_btree *);
/* bfind.c */
int hfs_find_init(struct hfs_btree *, struct hfs_find_data *);
@@ -311,7 +307,7 @@ int hfs_brec_goto(struct hfs_find_data *, int);
/* catalog.c */
int hfsplus_cat_cmp_key(hfsplus_btree_key *, hfsplus_btree_key *);
-void hfsplus_cat_build_key(hfsplus_btree_key *, u32, struct qstr *);
+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 *);
int hfsplus_delete_cat(u32, struct inode *, struct qstr *);
@@ -320,7 +316,6 @@ int hfsplus_rename_cat(u32, struct inode *, struct qstr *,
/* extents.c */
int hfsplus_ext_cmp_key(hfsplus_btree_key *, hfsplus_btree_key *);
-void hfsplus_ext_build_key(hfsplus_btree_key *, u32, u32, u8);
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);
@@ -352,12 +347,14 @@ int parse_options(char *, struct hfsplus_sb_info *);
void fill_defaults(struct hfsplus_sb_info *);
/* tables.c */
-extern u16 case_fold_table[];
+extern u16 hfsplus_case_fold_table[];
+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_uni2asc(const struct hfsplus_unistr *, char *, int *);
-int hfsplus_asc2uni(struct hfsplus_unistr *, const char *, int);
+int hfsplus_uni2asc(struct super_block *, const struct hfsplus_unistr *, char *, int *);
+int hfsplus_asc2uni(struct super_block *, struct hfsplus_unistr *, const char *, int);
/* wrapper.c */
int hfsplus_read_wrapper(struct super_block *);
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c
index d260dd3ef446c..d5642705f6336 100644
--- a/fs/hfsplus/inode.c
+++ b/fs/hfsplus/inode.c
@@ -40,7 +40,7 @@ static sector_t hfsplus_bmap(struct address_space *mapping, sector_t block)
return generic_block_bmap(mapping, block, hfsplus_get_block);
}
-int hfsplus_releasepage(struct page *page, int mask)
+static int hfsplus_releasepage(struct page *page, int mask)
{
struct inode *inode = page->mapping->host;
struct super_block *sb = inode->i_sb;
@@ -71,12 +71,6 @@ int hfsplus_releasepage(struct page *page, int mask)
;
else if (atomic_read(&node->refcnt))
res = 0;
- else for (i = 0; i < tree->pages_per_bnode; i++) {
- if (PageActive(node->page[i])) {
- res = 0;
- break;
- }
- }
if (res && node) {
hfs_bnode_unhash(node);
hfs_bnode_free(node);
@@ -100,7 +94,7 @@ int hfsplus_releasepage(struct page *page, int mask)
spin_unlock(&tree->hash_lock);
}
//printk("releasepage: %lu,%x = %d\n", page->index, mask, res);
- return res;
+ return res ? try_to_free_buffers(page) : 0;
}
static int hfsplus_get_blocks(struct inode *inode, sector_t iblock, unsigned long max_blocks,
@@ -297,7 +291,7 @@ static int hfsplus_file_release(struct inode *inode, struct file *file)
extern struct inode_operations hfsplus_dir_inode_operations;
extern struct file_operations hfsplus_dir_operations;
-struct inode_operations hfsplus_file_inode_operations = {
+static struct inode_operations hfsplus_file_inode_operations = {
.lookup = hfsplus_file_lookup,
.truncate = hfsplus_file_truncate,
.permission = hfsplus_permission,
@@ -306,7 +300,7 @@ struct inode_operations hfsplus_file_inode_operations = {
.listxattr = hfsplus_listxattr,
};
-struct file_operations hfsplus_file_operations = {
+static struct file_operations hfsplus_file_operations = {
.llseek = generic_file_llseek,
.read = generic_file_read,
.write = generic_file_write,
diff --git a/fs/hfsplus/options.c b/fs/hfsplus/options.c
index 20c802ff5db04..1cca0102c98d3 100644
--- a/fs/hfsplus/options.c
+++ b/fs/hfsplus/options.c
@@ -11,8 +11,32 @@
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/sched.h>
+#include <linux/parser.h>
+#include <linux/nls.h>
#include "hfsplus_fs.h"
+enum {
+ opt_creator, opt_type,
+ opt_umask, opt_uid, opt_gid,
+ opt_part, opt_session, opt_nls,
+ opt_nodecompose, opt_decompose,
+ opt_err
+};
+
+static match_table_t tokens = {
+ { opt_creator, "creator=%s" },
+ { opt_type, "type=%s" },
+ { opt_umask, "umask=%o" },
+ { opt_uid, "uid=%u" },
+ { opt_gid, "gid=%u" },
+ { opt_part, "part=%u" },
+ { opt_session, "session=%u" },
+ { opt_nls, "nls=%s" },
+ { opt_decompose, "decompose" },
+ { opt_nodecompose, "nodecompose" },
+ { opt_err, NULL }
+};
+
/* Initialize an options object to reasonable defaults */
void fill_defaults(struct hfsplus_sb_info *opts)
{
@@ -29,99 +53,110 @@ void fill_defaults(struct hfsplus_sb_info *opts)
}
/* convert a "four byte character" to a 32 bit int with error checks */
-static int fill_fourchar(u32 *result, char *input)
-{
- u32 out;
- int i;
-
- if (!result || !input || !*input || (strlen(input) != 4))
- return 0;
-
- for (out = 0, i = 0; i < 4; i++) {
- out <<= 8;
- out |= ((int)(input[i])) & 0xFF;
- }
- *result = out;
- return 1;
-}
-
-/* convert a string to int with error checks */
-static int fill_int(int *result, char *input, int base)
+static inline int match_fourchar(substring_t *arg, u32 *result)
{
- char *tmp = input;
- int intval;
-
- if (!result || !input || !*input)
- return 0;
-
- intval = simple_strtoul(tmp, &tmp, base);
- if (*tmp)
- return 0;
-
- *result = intval;
- return 1;
+ if (arg->to - arg->from != 4)
+ return -EINVAL;
+ memcpy(result, arg->from, 4);
+ return 0;
}
/* Parse options from mount. Returns 0 on failure */
/* input is the options passed to mount() as a string */
-int parse_options(char *input, struct hfsplus_sb_info *results)
+int parse_options(char *input, struct hfsplus_sb_info *sbi)
{
- char *curropt, *value;
- int tmp;
+ char *p;
+ substring_t args[MAX_OPT_ARGS];
+ int tmp, token;
if (!input)
- return 1;
+ goto done;
- while ((curropt = strsep(&input,",")) != NULL) {
- if (!*curropt)
+ while ((p = strsep(&input, ",")) != NULL) {
+ if (!*p)
continue;
- if ((value = strchr(curropt, '=')) != NULL)
- *value++ = '\0';
-
- if (!strcmp(curropt, "creator")) {
- if (!fill_fourchar(&(results->creator), value)) {
+ token = match_token(p, tokens, args);
+ switch (token) {
+ case opt_creator:
+ if (match_fourchar(&args[0], &sbi->creator)) {
printk("HFS+-fs: creator requires a 4 character value\n");
return 0;
}
- } else if (!strcmp(curropt, "type")) {
- if (!fill_fourchar(&(results->type), value)) {
+ break;
+ case opt_type:
+ if (match_fourchar(&args[0], &sbi->type)) {
printk("HFS+-fs: type requires a 4 character value\n");
return 0;
}
- } else if (!strcmp(curropt, "umask")) {
- if (!fill_int(&tmp, value, 8)) {
+ break;
+ case opt_umask:
+ if (match_octal(&args[0], &tmp)) {
printk("HFS+-fs: umask requires a value\n");
return 0;
}
- results->umask = (umode_t)tmp;
- } else if (!strcmp(curropt, "uid")) {
- if (!fill_int(&tmp, value, 0)) {
+ sbi->umask = (umode_t)tmp;
+ break;
+ case opt_uid:
+ if (match_int(&args[0], &tmp)) {
printk("HFS+-fs: uid requires an argument\n");
return 0;
}
- results->uid = (uid_t)tmp;
- } else if (!strcmp(curropt, "gid")) {
- if (!fill_int(&tmp, value, 0)) {
+ sbi->uid = (uid_t)tmp;
+ break;
+ case opt_gid:
+ if (match_int(&args[0], &tmp)) {
printk("HFS+-fs: gid requires an argument\n");
return 0;
}
- results->gid = (gid_t)tmp;
- } else if (!strcmp(curropt, "part")) {
- if (!fill_int(&results->part, value, 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");
return 0;
}
- } else if (!strcmp(curropt, "session")) {
- if (!fill_int(&results->session, value, 0)) {
+ break;
+ case opt_session:
+ if (match_int(&args[0], &sbi->session)) {
printk("HFS+-fs: session requires an argument\n");
return 0;
}
- } else {
- printk("HFS+-fs: unknown option %s\n", curropt);
+ break;
+ case opt_nls:
+ if (sbi->nls) {
+ printk("HFS+-fs: 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);
+ kfree(p);
+ return 0;
+ }
+ kfree(p);
+ break;
+ case opt_decompose:
+ sbi->flags &= ~HFSPLUS_SB_NODECOMPOSE;
+ break;
+ case opt_nodecompose:
+ sbi->flags |= HFSPLUS_SB_NODECOMPOSE;
+ break;
+ default:
return 0;
}
}
+done:
+ if (!sbi->nls) {
+ /* try utf8 first, as this is the old default behaviour */
+ sbi->nls = load_nls("utf8");
+ if (!sbi->nls)
+ sbi->nls = load_nls_default();
+ if (!sbi->nls)
+ return 0;
+ }
+
return 1;
}
diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c
index 09242d50096db..5f8044664a3c4 100644
--- a/fs/hfsplus/super.c
+++ b/fs/hfsplus/super.c
@@ -16,6 +16,7 @@
#include <linux/slab.h>
#include <linux/version.h>
#include <linux/vfs.h>
+#include <linux/nls.h>
static struct inode *hfsplus_alloc_inode(struct super_block *sb);
static void hfsplus_destroy_inode(struct inode *inode);
@@ -94,7 +95,7 @@ static void hfsplus_read_inode(struct inode *inode)
make_bad_inode(inode);
}
-int hfsplus_write_inode(struct inode *inode, int unused)
+static int hfsplus_write_inode(struct inode *inode, int unused)
{
struct hfsplus_vh *vhdr;
int ret = 0;
@@ -223,6 +224,8 @@ static void hfsplus_put_super(struct super_block *sb)
iput(HFSPLUS_SB(sb).alloc_file);
iput(HFSPLUS_SB(sb).hidden_dir);
brelse(HFSPLUS_SB(sb).s_vhbh);
+ if (HFSPLUS_SB(sb).nls)
+ unload_nls(HFSPLUS_SB(sb).nls);
}
static int hfsplus_statfs(struct super_block *sb, struct kstatfs *buf)
@@ -239,7 +242,7 @@ static int hfsplus_statfs(struct super_block *sb, struct kstatfs *buf)
return 0;
}
-int hfsplus_remount(struct super_block *sb, int *flags, char *data)
+static int hfsplus_remount(struct super_block *sb, int *flags, char *data)
{
if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
return 0;
@@ -280,13 +283,13 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
struct hfs_find_data fd;
struct inode *root;
struct qstr str;
+ struct nls_table *nls = NULL;
int err = -EINVAL;
sbi = kmalloc(sizeof(struct hfsplus_sb_info), GFP_KERNEL);
- if (!sbi) {
- err = -ENOMEM;
- goto out2;
- }
+ if (!sbi)
+ return -ENOMEM;
+
memset(sbi, 0, sizeof(HFSPLUS_SB(sb)));
sb->s_fs_info = sbi;
INIT_HLIST_HEAD(&sbi->rsrc_inodes);
@@ -295,7 +298,16 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
if (!silent)
printk("HFS+-fs: unable to parse mount options\n");
err = -EINVAL;
- goto out2;
+ goto cleanup;
+ }
+
+ /* 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");
+ err = -EINVAL;
+ goto cleanup;
}
/* Grab the volume header */
@@ -303,7 +315,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
if (!silent)
printk("HFS+-fs: unable to find HFS+ superblock\n");
err = -EINVAL;
- goto out2;
+ goto cleanup;
}
vhdr = HFSPLUS_SB(sb).s_vhdr;
@@ -376,7 +388,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
str.len = sizeof(HFSP_HIDDENDIR_NAME) - 1;
str.name = HFSP_HIDDENDIR_NAME;
hfs_find_init(HFSPLUS_SB(sb).cat_tree, &fd);
- hfsplus_cat_build_key(fd.search_key, HFSPLUS_ROOT_CNID, &str);
+ hfsplus_cat_build_key(sb, fd.search_key, HFSPLUS_ROOT_CNID, &str);
if (!hfs_brec_read(&fd, &entry, sizeof(entry))) {
hfs_find_exit(&fd);
if (entry.type != cpu_to_be16(HFSPLUS_FOLDER))
@@ -410,11 +422,14 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
mark_inode_dirty(HFSPLUS_SB(sb).hidden_dir);
}
out:
+ unload_nls(sbi->nls);
+ sbi->nls = nls;
return 0;
cleanup:
hfsplus_put_super(sb);
-out2:
+ if (nls)
+ unload_nls(nls);
return err;
}
diff --git a/fs/hfsplus/tables.c b/fs/hfsplus/tables.c
index ce2ed6657715a..1b911730a0c10 100644
--- a/fs/hfsplus/tables.c
+++ b/fs/hfsplus/tables.c
@@ -11,7 +11,7 @@
* (HFS Plus Volume Format)
*/
-u16 case_fold_table[] = {
+u16 hfsplus_case_fold_table[] = {
/*
* The lower case table consists of a 256-entry high-byte table followed by
* some number of 256-entry subtables. The high-byte table contains either an
@@ -406,3 +406,2840 @@ u16 case_fold_table[] = {
/* F */ 0xFFF0, 0xFFF1, 0xFFF2, 0xFFF3, 0xFFF4, 0xFFF5, 0xFFF6, 0xFFF7,
0xFFF8, 0xFFF9, 0xFFFA, 0xFFFB, 0xFFFC, 0xFFFD, 0xFFFE, 0xFFFF,
};
+
+u16 hfsplus_decompose_table[] = {
+ /* base table */
+ 0x0010, 0x04c0, 0x0000, 0x06f0, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 0x07b0,
+ /* char table 0x0___ */
+ 0x0020, 0x0070, 0x0160, 0x0190, 0x0230, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x02d0, 0x0340, 0x0360, 0x03b0, 0x03e0, 0x0400, 0x0430,
+ /* char table 0x00__ */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0030, 0x0040, 0x0050, 0x0060,
+ /* char values 0x00c_ */
+ 0x2042, 0x204a, 0x2052, 0x205a, 0x2062, 0x206a, 0x0000, 0x2072,
+ 0x207a, 0x2082, 0x208a, 0x2092, 0x209a, 0x20a2, 0x20aa, 0x20b2,
+ /* char values 0x00d_ */
+ 0x0000, 0x20ba, 0x20c2, 0x20ca, 0x20d2, 0x20da, 0x20e2, 0x0000,
+ 0x0000, 0x20ea, 0x20f2, 0x20fa, 0x2102, 0x210a, 0x0000, 0x0000,
+ /* char values 0x00e_ */
+ 0x2112, 0x211a, 0x2122, 0x212a, 0x2132, 0x213a, 0x0000, 0x2142,
+ 0x214a, 0x2152, 0x215a, 0x2162, 0x216a, 0x2172, 0x217a, 0x2182,
+ /* char values 0x00f_ */
+ 0x0000, 0x218a, 0x2192, 0x219a, 0x21a2, 0x21aa, 0x21b2, 0x0000,
+ 0x0000, 0x21ba, 0x21c2, 0x21ca, 0x21d2, 0x21da, 0x0000, 0x21e2,
+ /* char table 0x01__ */
+ 0x0080, 0x0090, 0x00a0, 0x00b0, 0x00c0, 0x00d0, 0x00e0, 0x00f0,
+ 0x0000, 0x0000, 0x0100, 0x0110, 0x0120, 0x0130, 0x0140, 0x0150,
+ /* char values 0x010_ */
+ 0x21ea, 0x21f2, 0x21fa, 0x2202, 0x220a, 0x2212, 0x221a, 0x2222,
+ 0x222a, 0x2232, 0x223a, 0x2242, 0x224a, 0x2252, 0x225a, 0x2262,
+ /* char values 0x011_ */
+ 0x0000, 0x0000, 0x226a, 0x2272, 0x227a, 0x2282, 0x228a, 0x2292,
+ 0x229a, 0x22a2, 0x22aa, 0x22b2, 0x22ba, 0x22c2, 0x22ca, 0x22d2,
+ /* char values 0x012_ */
+ 0x22da, 0x22e2, 0x22ea, 0x22f2, 0x22fa, 0x2302, 0x0000, 0x0000,
+ 0x230a, 0x2312, 0x231a, 0x2322, 0x232a, 0x2332, 0x233a, 0x2342,
+ /* char values 0x013_ */
+ 0x234a, 0x0000, 0x0000, 0x0000, 0x2352, 0x235a, 0x2362, 0x236a,
+ 0x0000, 0x2372, 0x237a, 0x2382, 0x238a, 0x2392, 0x239a, 0x0000,
+ /* char values 0x014_ */
+ 0x0000, 0x0000, 0x0000, 0x23a2, 0x23aa, 0x23b2, 0x23ba, 0x23c2,
+ 0x23ca, 0x0000, 0x0000, 0x0000, 0x23d2, 0x23da, 0x23e2, 0x23ea,
+ /* char values 0x015_ */
+ 0x23f2, 0x23fa, 0x0000, 0x0000, 0x2402, 0x240a, 0x2412, 0x241a,
+ 0x2422, 0x242a, 0x2432, 0x243a, 0x2442, 0x244a, 0x2452, 0x245a,
+ /* char values 0x016_ */
+ 0x2462, 0x246a, 0x2472, 0x247a, 0x2482, 0x248a, 0x0000, 0x0000,
+ 0x2492, 0x249a, 0x24a2, 0x24aa, 0x24b2, 0x24ba, 0x24c2, 0x24ca,
+ /* char values 0x017_ */
+ 0x24d2, 0x24da, 0x24e2, 0x24ea, 0x24f2, 0x24fa, 0x2502, 0x250a,
+ 0x2512, 0x251a, 0x2522, 0x252a, 0x2532, 0x253a, 0x2542, 0x0000,
+ /* char values 0x01a_ */
+ 0x254a, 0x2552, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x255a,
+ /* char values 0x01b_ */
+ 0x2562, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* char values 0x01c_ */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x256a, 0x2572, 0x257a,
+ /* char values 0x01d_ */
+ 0x2582, 0x258a, 0x2592, 0x259a, 0x25a2, 0x25ab, 0x25b7, 0x25c3,
+ 0x25cf, 0x25db, 0x25e7, 0x25f3, 0x25ff, 0x0000, 0x260b, 0x2617,
+ /* char values 0x01e_ */
+ 0x2623, 0x262f, 0x263a, 0x2642, 0x0000, 0x0000, 0x264a, 0x2652,
+ 0x265a, 0x2662, 0x266a, 0x2672, 0x267b, 0x2687, 0x2692, 0x269a,
+ /* char values 0x01f_ */
+ 0x26a2, 0x0000, 0x0000, 0x0000, 0x26aa, 0x26b2, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x26bb, 0x26c7, 0x26d2, 0x26da, 0x26e2, 0x26ea,
+ /* char table 0x02__ */
+ 0x0170, 0x0180, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* char values 0x020_ */
+ 0x26f2, 0x26fa, 0x2702, 0x270a, 0x2712, 0x271a, 0x2722, 0x272a,
+ 0x2732, 0x273a, 0x2742, 0x274a, 0x2752, 0x275a, 0x2762, 0x276a,
+ /* char values 0x021_ */
+ 0x2772, 0x277a, 0x2782, 0x278a, 0x2792, 0x279a, 0x27a2, 0x27aa,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* char table 0x03__ */
+ 0x0000, 0x01a0, 0x0000, 0x0000, 0x01b0, 0x0000, 0x0000, 0x01c0,
+ 0x01d0, 0x01e0, 0x01f0, 0x0200, 0x0210, 0x0220, 0x0000, 0x0000,
+ /* char values 0x031_ */
+ 0x27b2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* char values 0x034_ */
+ 0x27b9, 0x27bd, 0x0000, 0x27c1, 0x27c6, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* char values 0x037_ */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x27cd, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x27d1, 0x0000,
+ /* char values 0x038_ */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x27d6, 0x27de, 0x27e5,
+ 0x27ea, 0x27f2, 0x27fa, 0x0000, 0x2802, 0x0000, 0x280a, 0x2812,
+ /* char values 0x039_ */
+ 0x281b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* char values 0x03a_ */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x2826, 0x282e, 0x2836, 0x283e, 0x2846, 0x284e,
+ /* char values 0x03b_ */
+ 0x2857, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* char values 0x03c_ */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x2862, 0x286a, 0x2872, 0x287a, 0x2882, 0x0000,
+ /* char values 0x03d_ */
+ 0x0000, 0x0000, 0x0000, 0x288a, 0x2892, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* char table 0x04__ */
+ 0x0240, 0x0250, 0x0000, 0x0260, 0x0000, 0x0270, 0x0000, 0x0280,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0290, 0x02a0, 0x02b0, 0x02c0,
+ /* char values 0x040_ */
+ 0x0000, 0x289a, 0x0000, 0x28a2, 0x0000, 0x0000, 0x0000, 0x28aa,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x28b2, 0x0000, 0x28ba, 0x0000,
+ /* char values 0x041_ */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x28c2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* char values 0x043_ */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x28ca, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* char values 0x045_ */
+ 0x0000, 0x28d2, 0x0000, 0x28da, 0x0000, 0x0000, 0x0000, 0x28e2,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x28ea, 0x0000, 0x28f2, 0x0000,
+ /* char values 0x047_ */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x28fa, 0x2902,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* char values 0x04c_ */
+ 0x0000, 0x290a, 0x2912, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* char values 0x04d_ */
+ 0x291a, 0x2922, 0x292a, 0x2932, 0x2939, 0x293d, 0x2942, 0x294a,
+ 0x2951, 0x2955, 0x295a, 0x2962, 0x296a, 0x2972, 0x297a, 0x2982,
+ /* char values 0x04e_ */
+ 0x2989, 0x298d, 0x2992, 0x299a, 0x29a2, 0x29aa, 0x29b2, 0x29ba,
+ 0x29c1, 0x29c5, 0x29ca, 0x29d2, 0x0000, 0x0000, 0x29da, 0x29e2,
+ /* char values 0x04f_ */
+ 0x29ea, 0x29f2, 0x29fa, 0x2a02, 0x2a0a, 0x2a12, 0x0000, 0x0000,
+ 0x2a1a, 0x2a22, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* char table 0x09__ */
+ 0x0000, 0x0000, 0x02e0, 0x02f0, 0x0000, 0x0300, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0310, 0x0320, 0x0330, 0x0000, 0x0000,
+ /* char values 0x092_ */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x2a2a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* char values 0x093_ */
+ 0x0000, 0x2a32, 0x0000, 0x0000, 0x2a3a, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* char values 0x095_ */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x2a42, 0x2a4a, 0x2a52, 0x2a5a, 0x2a62, 0x2a6a, 0x2a72, 0x2a7a,
+ /* char values 0x09b_ */
+ 0x2a82, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* char values 0x09c_ */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x2a8a, 0x2a92, 0x0000, 0x0000, 0x0000,
+ /* char values 0x09d_ */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x2a9a, 0x2aa2, 0x0000, 0x2aaa,
+ /* char table 0x0a__ */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0350, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* char values 0x0a5_ */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x2ab2, 0x2aba, 0x2ac2, 0x2aca, 0x0000, 0x2ad2, 0x0000,
+ /* char table 0x0b__ */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0370, 0x0380, 0x0000, 0x0000,
+ 0x0000, 0x0390, 0x0000, 0x0000, 0x03a0, 0x0000, 0x0000, 0x0000,
+ /* char values 0x0b4_ */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x2ada, 0x0000, 0x0000, 0x2ae2, 0x2aea, 0x0000, 0x0000, 0x0000,
+ /* char values 0x0b5_ */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x2af2, 0x2afa, 0x0000, 0x2b02,
+ /* char values 0x0b9_ */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x2b0a, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* char values 0x0bc_ */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x2b12, 0x2b1a, 0x2b22, 0x0000, 0x0000, 0x0000,
+ /* char table 0x0c__ */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x03c0, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x03d0, 0x0000, 0x0000, 0x0000,
+ /* char values 0x0c4_ */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x2b2a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* char values 0x0cc_ */
+ 0x2b32, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2b3a,
+ 0x2b42, 0x0000, 0x2b4a, 0x2b53, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* char table 0x0d__ */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x03f0, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* char values 0x0d4_ */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x2b5e, 0x2b66, 0x2b6e, 0x0000, 0x0000, 0x0000,
+ /* char table 0x0e__ */
+ 0x0000, 0x0000, 0x0000, 0x0410, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0420, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* char values 0x0e3_ */
+ 0x0000, 0x0000, 0x0000, 0x2b76, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* char values 0x0eb_ */
+ 0x0000, 0x0000, 0x0000, 0x2b7e, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* char table 0x0f__ */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0440, 0x0450, 0x0460, 0x0470,
+ 0x0480, 0x0490, 0x04a0, 0x04b0, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* char values 0x0f4_ */
+ 0x0000, 0x0000, 0x0000, 0x2b86, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2b8e, 0x0000, 0x0000,
+ /* char values 0x0f5_ */
+ 0x0000, 0x0000, 0x2b96, 0x0000, 0x0000, 0x0000, 0x0000, 0x2b9e,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x2ba6, 0x0000, 0x0000, 0x0000,
+ /* char values 0x0f6_ */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x2bae, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* char values 0x0f7_ */
+ 0x0000, 0x0000, 0x0000, 0x2bb6, 0x0000, 0x2bbe, 0x2bc6, 0x2bcf,
+ 0x2bda, 0x2be3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* char values 0x0f8_ */
+ 0x0000, 0x2bee, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* char values 0x0f9_ */
+ 0x0000, 0x0000, 0x0000, 0x2bf6, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2bfe, 0x0000, 0x0000,
+ /* char values 0x0fa_ */
+ 0x0000, 0x0000, 0x2c06, 0x0000, 0x0000, 0x0000, 0x0000, 0x2c0e,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x2c16, 0x0000, 0x0000, 0x0000,
+ /* char values 0x0fb_ */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x2c1e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* char table 0x1___ */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x04d0, 0x05e0,
+ /* char table 0x1e__ */
+ 0x04e0, 0x04f0, 0x0500, 0x0510, 0x0520, 0x0530, 0x0540, 0x0550,
+ 0x0560, 0x0570, 0x0580, 0x0590, 0x05a0, 0x05b0, 0x05c0, 0x05d0,
+ /* char values 0x1e0_ */
+ 0x2c26, 0x2c2e, 0x2c36, 0x2c3e, 0x2c46, 0x2c4e, 0x2c56, 0x2c5e,
+ 0x2c67, 0x2c73, 0x2c7e, 0x2c86, 0x2c8e, 0x2c96, 0x2c9e, 0x2ca6,
+ /* char values 0x1e1_ */
+ 0x2cae, 0x2cb6, 0x2cbe, 0x2cc6, 0x2ccf, 0x2cdb, 0x2ce7, 0x2cf3,
+ 0x2cfe, 0x2d06, 0x2d0e, 0x2d16, 0x2d1f, 0x2d2b, 0x2d36, 0x2d3e,
+ /* char values 0x1e2_ */
+ 0x2d46, 0x2d4e, 0x2d56, 0x2d5e, 0x2d66, 0x2d6e, 0x2d76, 0x2d7e,
+ 0x2d86, 0x2d8e, 0x2d96, 0x2d9e, 0x2da6, 0x2dae, 0x2db7, 0x2dc3,
+ /* char values 0x1e3_ */
+ 0x2dce, 0x2dd6, 0x2dde, 0x2de6, 0x2dee, 0x2df6, 0x2dfe, 0x2e06,
+ 0x2e0f, 0x2e1b, 0x2e26, 0x2e2e, 0x2e36, 0x2e3e, 0x2e46, 0x2e4e,
+ /* char values 0x1e4_ */
+ 0x2e56, 0x2e5e, 0x2e66, 0x2e6e, 0x2e76, 0x2e7e, 0x2e86, 0x2e8e,
+ 0x2e96, 0x2e9e, 0x2ea6, 0x2eae, 0x2eb7, 0x2ec3, 0x2ecf, 0x2edb,
+ /* char values 0x1e5_ */
+ 0x2ee7, 0x2ef3, 0x2eff, 0x2f0b, 0x2f16, 0x2f1e, 0x2f26, 0x2f2e,
+ 0x2f36, 0x2f3e, 0x2f46, 0x2f4e, 0x2f57, 0x2f63, 0x2f6e, 0x2f76,
+ /* char values 0x1e6_ */
+ 0x2f7e, 0x2f86, 0x2f8e, 0x2f96, 0x2f9f, 0x2fab, 0x2fb7, 0x2fc3,
+ 0x2fcf, 0x2fdb, 0x2fe6, 0x2fee, 0x2ff6, 0x2ffe, 0x3006, 0x300e,
+ /* char values 0x1e7_ */
+ 0x3016, 0x301e, 0x3026, 0x302e, 0x3036, 0x303e, 0x3046, 0x304e,
+ 0x3057, 0x3063, 0x306f, 0x307b, 0x3086, 0x308e, 0x3096, 0x309e,
+ /* char values 0x1e8_ */
+ 0x30a6, 0x30ae, 0x30b6, 0x30be, 0x30c6, 0x30ce, 0x30d6, 0x30de,
+ 0x30e6, 0x30ee, 0x30f6, 0x30fe, 0x3106, 0x310e, 0x3116, 0x311e,
+ /* char values 0x1e9_ */
+ 0x3126, 0x312e, 0x3136, 0x313e, 0x3146, 0x314e, 0x3156, 0x315e,
+ 0x3166, 0x316e, 0x0000, 0x3176, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* char values 0x1ea_ */
+ 0x317e, 0x3186, 0x318e, 0x3196, 0x319f, 0x31ab, 0x31b7, 0x31c3,
+ 0x31cf, 0x31db, 0x31e7, 0x31f3, 0x31ff, 0x320b, 0x3217, 0x3223,
+ /* char values 0x1eb_ */
+ 0x322f, 0x323b, 0x3247, 0x3253, 0x325f, 0x326b, 0x3277, 0x3283,
+ 0x328e, 0x3296, 0x329e, 0x32a6, 0x32ae, 0x32b6, 0x32bf, 0x32cb,
+ /* char values 0x1ec_ */
+ 0x32d7, 0x32e3, 0x32ef, 0x32fb, 0x3307, 0x3313, 0x331f, 0x332b,
+ 0x3336, 0x333e, 0x3346, 0x334e, 0x3356, 0x335e, 0x3366, 0x336e,
+ /* char values 0x1ed_ */
+ 0x3377, 0x3383, 0x338f, 0x339b, 0x33a7, 0x33b3, 0x33bf, 0x33cb,
+ 0x33d7, 0x33e3, 0x33ef, 0x33fb, 0x3407, 0x3413, 0x341f, 0x342b,
+ /* char values 0x1ee_ */
+ 0x3437, 0x3443, 0x344f, 0x345b, 0x3466, 0x346e, 0x3476, 0x347e,
+ 0x3487, 0x3493, 0x349f, 0x34ab, 0x34b7, 0x34c3, 0x34cf, 0x34db,
+ /* char values 0x1ef_ */
+ 0x34e7, 0x34f3, 0x34fe, 0x3506, 0x350e, 0x3516, 0x351e, 0x3526,
+ 0x352e, 0x3536, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* char table 0x1f__ */
+ 0x05f0, 0x0600, 0x0610, 0x0620, 0x0630, 0x0640, 0x0650, 0x0660,
+ 0x0670, 0x0680, 0x0690, 0x06a0, 0x06b0, 0x06c0, 0x06d0, 0x06e0,
+ /* char values 0x1f0_ */
+ 0x353e, 0x3546, 0x354f, 0x355b, 0x3567, 0x3573, 0x357f, 0x358b,
+ 0x3596, 0x359e, 0x35a7, 0x35b3, 0x35bf, 0x35cb, 0x35d7, 0x35e3,
+ /* char values 0x1f1_ */
+ 0x35ee, 0x35f6, 0x35ff, 0x360b, 0x3617, 0x3623, 0x0000, 0x0000,
+ 0x362e, 0x3636, 0x363f, 0x364b, 0x3657, 0x3663, 0x0000, 0x0000,
+ /* char values 0x1f2_ */
+ 0x366e, 0x3676, 0x367f, 0x368b, 0x3697, 0x36a3, 0x36af, 0x36bb,
+ 0x36c6, 0x36ce, 0x36d7, 0x36e3, 0x36ef, 0x36fb, 0x3707, 0x3713,
+ /* char values 0x1f3_ */
+ 0x371e, 0x3726, 0x372f, 0x373b, 0x3747, 0x3753, 0x375f, 0x376b,
+ 0x3776, 0x377e, 0x3787, 0x3793, 0x379f, 0x37ab, 0x37b7, 0x37c3,
+ /* char values 0x1f4_ */
+ 0x37ce, 0x37d6, 0x37df, 0x37eb, 0x37f7, 0x3803, 0x0000, 0x0000,
+ 0x380e, 0x3816, 0x381f, 0x382b, 0x3837, 0x3843, 0x0000, 0x0000,
+ /* char values 0x1f5_ */
+ 0x384e, 0x3856, 0x385f, 0x386b, 0x3877, 0x3883, 0x388f, 0x389b,
+ 0x0000, 0x38a6, 0x0000, 0x38af, 0x0000, 0x38bb, 0x0000, 0x38c7,
+ /* char values 0x1f6_ */
+ 0x38d2, 0x38da, 0x38e3, 0x38ef, 0x38fb, 0x3907, 0x3913, 0x391f,
+ 0x392a, 0x3932, 0x393b, 0x3947, 0x3953, 0x395f, 0x396b, 0x3977,
+ /* char values 0x1f7_ */
+ 0x3982, 0x398a, 0x3992, 0x399a, 0x39a2, 0x39aa, 0x39b2, 0x39ba,
+ 0x39c2, 0x39ca, 0x39d2, 0x39da, 0x39e2, 0x39ea, 0x0000, 0x0000,
+ /* char values 0x1f8_ */
+ 0x39f3, 0x39ff, 0x3a0c, 0x3a1c, 0x3a2c, 0x3a3c, 0x3a4c, 0x3a5c,
+ 0x3a6b, 0x3a77, 0x3a84, 0x3a94, 0x3aa4, 0x3ab4, 0x3ac4, 0x3ad4,
+ /* char values 0x1f9_ */
+ 0x3ae3, 0x3aef, 0x3afc, 0x3b0c, 0x3b1c, 0x3b2c, 0x3b3c, 0x3b4c,
+ 0x3b5b, 0x3b67, 0x3b74, 0x3b84, 0x3b94, 0x3ba4, 0x3bb4, 0x3bc4,
+ /* char values 0x1fa_ */
+ 0x3bd3, 0x3bdf, 0x3bec, 0x3bfc, 0x3c0c, 0x3c1c, 0x3c2c, 0x3c3c,
+ 0x3c4b, 0x3c57, 0x3c64, 0x3c74, 0x3c84, 0x3c94, 0x3ca4, 0x3cb4,
+ /* char values 0x1fb_ */
+ 0x3cc2, 0x3cca, 0x3cd3, 0x3cde, 0x3ce7, 0x0000, 0x3cf2, 0x3cfb,
+ 0x3d06, 0x3d0e, 0x3d16, 0x3d1e, 0x3d26, 0x0000, 0x3d2d, 0x0000,
+ /* char values 0x1fc_ */
+ 0x0000, 0x3d32, 0x3d3b, 0x3d46, 0x3d4f, 0x0000, 0x3d5a, 0x3d63,
+ 0x3d6e, 0x3d76, 0x3d7e, 0x3d86, 0x3d8e, 0x3d96, 0x3d9e, 0x3da6,
+ /* char values 0x1fd_ */
+ 0x3dae, 0x3db6, 0x3dbf, 0x3dcb, 0x0000, 0x0000, 0x3dd6, 0x3ddf,
+ 0x3dea, 0x3df2, 0x3dfa, 0x3e02, 0x0000, 0x3e0a, 0x3e12, 0x3e1a,
+ /* char values 0x1fe_ */
+ 0x3e22, 0x3e2a, 0x3e33, 0x3e3f, 0x3e4a, 0x3e52, 0x3e5a, 0x3e63,
+ 0x3e6e, 0x3e76, 0x3e7e, 0x3e86, 0x3e8e, 0x3e96, 0x3e9e, 0x3ea5,
+ /* char values 0x1ff_ */
+ 0x0000, 0x0000, 0x3eab, 0x3eb6, 0x3ebf, 0x0000, 0x3eca, 0x3ed3,
+ 0x3ede, 0x3ee6, 0x3eee, 0x3ef6, 0x3efe, 0x3f05, 0x0000, 0x0000,
+ /* char table 0x3___ */
+ 0x0700, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* char table 0x30__ */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0710, 0x0720, 0x0730, 0x0740,
+ 0x0000, 0x0750, 0x0760, 0x0770, 0x0780, 0x0790, 0x0000, 0x07a0,
+ /* char values 0x304_ */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3f0a, 0x0000, 0x3f12, 0x0000,
+ /* char values 0x305_ */
+ 0x3f1a, 0x0000, 0x3f22, 0x0000, 0x3f2a, 0x0000, 0x3f32, 0x0000,
+ 0x3f3a, 0x0000, 0x3f42, 0x0000, 0x3f4a, 0x0000, 0x3f52, 0x0000,
+ /* char values 0x306_ */
+ 0x3f5a, 0x0000, 0x3f62, 0x0000, 0x0000, 0x3f6a, 0x0000, 0x3f72,
+ 0x0000, 0x3f7a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* char values 0x307_ */
+ 0x3f82, 0x3f8a, 0x0000, 0x3f92, 0x3f9a, 0x0000, 0x3fa2, 0x3faa,
+ 0x0000, 0x3fb2, 0x3fba, 0x0000, 0x3fc2, 0x3fca, 0x0000, 0x0000,
+ /* char values 0x309_ */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3fd2, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3fda, 0x0000,
+ /* char values 0x30a_ */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x3fe2, 0x0000, 0x3fea, 0x0000,
+ /* char values 0x30b_ */
+ 0x3ff2, 0x0000, 0x3ffa, 0x0000, 0x4002, 0x0000, 0x400a, 0x0000,
+ 0x4012, 0x0000, 0x401a, 0x0000, 0x4022, 0x0000, 0x402a, 0x0000,
+ /* char values 0x30c_ */
+ 0x4032, 0x0000, 0x403a, 0x0000, 0x0000, 0x4042, 0x0000, 0x404a,
+ 0x0000, 0x4052, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* char values 0x30d_ */
+ 0x405a, 0x4062, 0x0000, 0x406a, 0x4072, 0x0000, 0x407a, 0x4082,
+ 0x0000, 0x408a, 0x4092, 0x0000, 0x409a, 0x40a2, 0x0000, 0x0000,
+ /* char values 0x30f_ */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x40aa, 0x0000, 0x0000, 0x40b2,
+ 0x40ba, 0x40c2, 0x40ca, 0x0000, 0x0000, 0x0000, 0x40d2, 0x0000,
+ /* char table 0xf___ */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x07c0, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* char table 0xfb__ */
+ 0x0000, 0x07d0, 0x07e0, 0x07f0, 0x0800, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* char values 0xfb1_ */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x40da,
+ /* char values 0xfb2_ */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x40e2, 0x40ea, 0x40f3, 0x40ff, 0x410a, 0x4112,
+ /* char values 0xfb3_ */
+ 0x411a, 0x4122, 0x412a, 0x4132, 0x413a, 0x4142, 0x414a, 0x0000,
+ 0x4152, 0x415a, 0x4162, 0x416a, 0x4172, 0x0000, 0x417a, 0x0000,
+ /* char values 0xfb4_ */
+ 0x4182, 0x418a, 0x0000, 0x4192, 0x419a, 0x0000, 0x41a2, 0x41aa,
+ 0x41b2, 0x41ba, 0x41c2, 0x41ca, 0x41d2, 0x41da, 0x41e2, 0x0000,
+ /* decomposed characters */
+ 0x0041, 0x0300, 0x0041, 0x0301, 0x0041, 0x0302, 0x0041, 0x0303,
+ 0x0041, 0x0308, 0x0041, 0x030a, 0x0043, 0x0327, 0x0045, 0x0300,
+ 0x0045, 0x0301, 0x0045, 0x0302, 0x0045, 0x0308, 0x0049, 0x0300,
+ 0x0049, 0x0301, 0x0049, 0x0302, 0x0049, 0x0308, 0x004e, 0x0303,
+ 0x004f, 0x0300, 0x004f, 0x0301, 0x004f, 0x0302, 0x004f, 0x0303,
+ 0x004f, 0x0308, 0x0055, 0x0300, 0x0055, 0x0301, 0x0055, 0x0302,
+ 0x0055, 0x0308, 0x0059, 0x0301, 0x0061, 0x0300, 0x0061, 0x0301,
+ 0x0061, 0x0302, 0x0061, 0x0303, 0x0061, 0x0308, 0x0061, 0x030a,
+ 0x0063, 0x0327, 0x0065, 0x0300, 0x0065, 0x0301, 0x0065, 0x0302,
+ 0x0065, 0x0308, 0x0069, 0x0300, 0x0069, 0x0301, 0x0069, 0x0302,
+ 0x0069, 0x0308, 0x006e, 0x0303, 0x006f, 0x0300, 0x006f, 0x0301,
+ 0x006f, 0x0302, 0x006f, 0x0303, 0x006f, 0x0308, 0x0075, 0x0300,
+ 0x0075, 0x0301, 0x0075, 0x0302, 0x0075, 0x0308, 0x0079, 0x0301,
+ 0x0079, 0x0308, 0x0041, 0x0304, 0x0061, 0x0304, 0x0041, 0x0306,
+ 0x0061, 0x0306, 0x0041, 0x0328, 0x0061, 0x0328, 0x0043, 0x0301,
+ 0x0063, 0x0301, 0x0043, 0x0302, 0x0063, 0x0302, 0x0043, 0x0307,
+ 0x0063, 0x0307, 0x0043, 0x030c, 0x0063, 0x030c, 0x0044, 0x030c,
+ 0x0064, 0x030c, 0x0045, 0x0304, 0x0065, 0x0304, 0x0045, 0x0306,
+ 0x0065, 0x0306, 0x0045, 0x0307, 0x0065, 0x0307, 0x0045, 0x0328,
+ 0x0065, 0x0328, 0x0045, 0x030c, 0x0065, 0x030c, 0x0047, 0x0302,
+ 0x0067, 0x0302, 0x0047, 0x0306, 0x0067, 0x0306, 0x0047, 0x0307,
+ 0x0067, 0x0307, 0x0047, 0x0327, 0x0067, 0x0327, 0x0048, 0x0302,
+ 0x0068, 0x0302, 0x0049, 0x0303, 0x0069, 0x0303, 0x0049, 0x0304,
+ 0x0069, 0x0304, 0x0049, 0x0306, 0x0069, 0x0306, 0x0049, 0x0328,
+ 0x0069, 0x0328, 0x0049, 0x0307, 0x004a, 0x0302, 0x006a, 0x0302,
+ 0x004b, 0x0327, 0x006b, 0x0327, 0x004c, 0x0301, 0x006c, 0x0301,
+ 0x004c, 0x0327, 0x006c, 0x0327, 0x004c, 0x030c, 0x006c, 0x030c,
+ 0x004e, 0x0301, 0x006e, 0x0301, 0x004e, 0x0327, 0x006e, 0x0327,
+ 0x004e, 0x030c, 0x006e, 0x030c, 0x004f, 0x0304, 0x006f, 0x0304,
+ 0x004f, 0x0306, 0x006f, 0x0306, 0x004f, 0x030b, 0x006f, 0x030b,
+ 0x0052, 0x0301, 0x0072, 0x0301, 0x0052, 0x0327, 0x0072, 0x0327,
+ 0x0052, 0x030c, 0x0072, 0x030c, 0x0053, 0x0301, 0x0073, 0x0301,
+ 0x0053, 0x0302, 0x0073, 0x0302, 0x0053, 0x0327, 0x0073, 0x0327,
+ 0x0053, 0x030c, 0x0073, 0x030c, 0x0054, 0x0327, 0x0074, 0x0327,
+ 0x0054, 0x030c, 0x0074, 0x030c, 0x0055, 0x0303, 0x0075, 0x0303,
+ 0x0055, 0x0304, 0x0075, 0x0304, 0x0055, 0x0306, 0x0075, 0x0306,
+ 0x0055, 0x030a, 0x0075, 0x030a, 0x0055, 0x030b, 0x0075, 0x030b,
+ 0x0055, 0x0328, 0x0075, 0x0328, 0x0057, 0x0302, 0x0077, 0x0302,
+ 0x0059, 0x0302, 0x0079, 0x0302, 0x0059, 0x0308, 0x005a, 0x0301,
+ 0x007a, 0x0301, 0x005a, 0x0307, 0x007a, 0x0307, 0x005a, 0x030c,
+ 0x007a, 0x030c, 0x004f, 0x031b, 0x006f, 0x031b, 0x0055, 0x031b,
+ 0x0075, 0x031b, 0x0041, 0x030c, 0x0061, 0x030c, 0x0049, 0x030c,
+ 0x0069, 0x030c, 0x004f, 0x030c, 0x006f, 0x030c, 0x0055, 0x030c,
+ 0x0075, 0x030c, 0x0055, 0x0308, 0x0304, 0x0075, 0x0308, 0x0304,
+ 0x0055, 0x0308, 0x0301, 0x0075, 0x0308, 0x0301, 0x0055, 0x0308,
+ 0x030c, 0x0075, 0x0308, 0x030c, 0x0055, 0x0308, 0x0300, 0x0075,
+ 0x0308, 0x0300, 0x0041, 0x0308, 0x0304, 0x0061, 0x0308, 0x0304,
+ 0x0041, 0x0307, 0x0304, 0x0061, 0x0307, 0x0304, 0x00c6, 0x0304,
+ 0x00e6, 0x0304, 0x0047, 0x030c, 0x0067, 0x030c, 0x004b, 0x030c,
+ 0x006b, 0x030c, 0x004f, 0x0328, 0x006f, 0x0328, 0x004f, 0x0328,
+ 0x0304, 0x006f, 0x0328, 0x0304, 0x01b7, 0x030c, 0x0292, 0x030c,
+ 0x006a, 0x030c, 0x0047, 0x0301, 0x0067, 0x0301, 0x0041, 0x030a,
+ 0x0301, 0x0061, 0x030a, 0x0301, 0x00c6, 0x0301, 0x00e6, 0x0301,
+ 0x00d8, 0x0301, 0x00f8, 0x0301, 0x0041, 0x030f, 0x0061, 0x030f,
+ 0x0041, 0x0311, 0x0061, 0x0311, 0x0045, 0x030f, 0x0065, 0x030f,
+ 0x0045, 0x0311, 0x0065, 0x0311, 0x0049, 0x030f, 0x0069, 0x030f,
+ 0x0049, 0x0311, 0x0069, 0x0311, 0x004f, 0x030f, 0x006f, 0x030f,
+ 0x004f, 0x0311, 0x006f, 0x0311, 0x0052, 0x030f, 0x0072, 0x030f,
+ 0x0052, 0x0311, 0x0072, 0x0311, 0x0055, 0x030f, 0x0075, 0x030f,
+ 0x0055, 0x0311, 0x0075, 0x0311, 0x0306, 0x0307, 0x0300, 0x0301,
+ 0x0313, 0x0308, 0x030d, 0x02b9, 0x003b, 0x00a8, 0x030d, 0x0391,
+ 0x030d, 0x00b7, 0x0395, 0x030d, 0x0397, 0x030d, 0x0399, 0x030d,
+ 0x039f, 0x030d, 0x03a5, 0x030d, 0x03a9, 0x030d, 0x03b9, 0x0308,
+ 0x030d, 0x0399, 0x0308, 0x03a5, 0x0308, 0x03b1, 0x030d, 0x03b5,
+ 0x030d, 0x03b7, 0x030d, 0x03b9, 0x030d, 0x03c5, 0x0308, 0x030d,
+ 0x03b9, 0x0308, 0x03c5, 0x0308, 0x03bf, 0x030d, 0x03c5, 0x030d,
+ 0x03c9, 0x030d, 0x03d2, 0x030d, 0x03d2, 0x0308, 0x0415, 0x0308,
+ 0x0413, 0x0301, 0x0406, 0x0308, 0x041a, 0x0301, 0x0423, 0x0306,
+ 0x0418, 0x0306, 0x0438, 0x0306, 0x0435, 0x0308, 0x0433, 0x0301,
+ 0x0456, 0x0308, 0x043a, 0x0301, 0x0443, 0x0306, 0x0474, 0x030f,
+ 0x0475, 0x030f, 0x0416, 0x0306, 0x0436, 0x0306, 0x0410, 0x0306,
+ 0x0430, 0x0306, 0x0410, 0x0308, 0x0430, 0x0308, 0x00c6, 0x00e6,
+ 0x0415, 0x0306, 0x0435, 0x0306, 0x018f, 0x0259, 0x018f, 0x0308,
+ 0x0259, 0x0308, 0x0416, 0x0308, 0x0436, 0x0308, 0x0417, 0x0308,
+ 0x0437, 0x0308, 0x01b7, 0x0292, 0x0418, 0x0304, 0x0438, 0x0304,
+ 0x0418, 0x0308, 0x0438, 0x0308, 0x041e, 0x0308, 0x043e, 0x0308,
+ 0x019f, 0x0275, 0x019f, 0x0308, 0x0275, 0x0308, 0x0423, 0x0304,
+ 0x0443, 0x0304, 0x0423, 0x0308, 0x0443, 0x0308, 0x0423, 0x030b,
+ 0x0443, 0x030b, 0x0427, 0x0308, 0x0447, 0x0308, 0x042b, 0x0308,
+ 0x044b, 0x0308, 0x0928, 0x093c, 0x0930, 0x093c, 0x0933, 0x093c,
+ 0x0915, 0x093c, 0x0916, 0x093c, 0x0917, 0x093c, 0x091c, 0x093c,
+ 0x0921, 0x093c, 0x0922, 0x093c, 0x092b, 0x093c, 0x092f, 0x093c,
+ 0x09ac, 0x09bc, 0x09c7, 0x09be, 0x09c7, 0x09d7, 0x09a1, 0x09bc,
+ 0x09a2, 0x09bc, 0x09af, 0x09bc, 0x0a16, 0x0a3c, 0x0a17, 0x0a3c,
+ 0x0a1c, 0x0a3c, 0x0a21, 0x0a3c, 0x0a2b, 0x0a3c, 0x0b47, 0x0b56,
+ 0x0b47, 0x0b3e, 0x0b47, 0x0b57, 0x0b21, 0x0b3c, 0x0b22, 0x0b3c,
+ 0x0b2f, 0x0b3c, 0x0b92, 0x0bd7, 0x0bc6, 0x0bbe, 0x0bc7, 0x0bbe,
+ 0x0bc6, 0x0bd7, 0x0c46, 0x0c56, 0x0cbf, 0x0cd5, 0x0cc6, 0x0cd5,
+ 0x0cc6, 0x0cd6, 0x0cc6, 0x0cc2, 0x0cc6, 0x0cc2, 0x0cd5, 0x0d46,
+ 0x0d3e, 0x0d47, 0x0d3e, 0x0d46, 0x0d57, 0x0e4d, 0x0e32, 0x0ecd,
+ 0x0eb2, 0x0f42, 0x0fb7, 0x0f4c, 0x0fb7, 0x0f51, 0x0fb7, 0x0f56,
+ 0x0fb7, 0x0f5b, 0x0fb7, 0x0f40, 0x0fb5, 0x0f72, 0x0f71, 0x0f74,
+ 0x0f71, 0x0fb2, 0x0f80, 0x0fb2, 0x0f80, 0x0f71, 0x0fb3, 0x0f80,
+ 0x0fb3, 0x0f80, 0x0f71, 0x0f80, 0x0f71, 0x0f92, 0x0fb7, 0x0f9c,
+ 0x0fb7, 0x0fa1, 0x0fb7, 0x0fa6, 0x0fb7, 0x0fab, 0x0fb7, 0x0f90,
+ 0x0fb5, 0x0041, 0x0325, 0x0061, 0x0325, 0x0042, 0x0307, 0x0062,
+ 0x0307, 0x0042, 0x0323, 0x0062, 0x0323, 0x0042, 0x0331, 0x0062,
+ 0x0331, 0x0043, 0x0327, 0x0301, 0x0063, 0x0327, 0x0301, 0x0044,
+ 0x0307, 0x0064, 0x0307, 0x0044, 0x0323, 0x0064, 0x0323, 0x0044,
+ 0x0331, 0x0064, 0x0331, 0x0044, 0x0327, 0x0064, 0x0327, 0x0044,
+ 0x032d, 0x0064, 0x032d, 0x0045, 0x0304, 0x0300, 0x0065, 0x0304,
+ 0x0300, 0x0045, 0x0304, 0x0301, 0x0065, 0x0304, 0x0301, 0x0045,
+ 0x032d, 0x0065, 0x032d, 0x0045, 0x0330, 0x0065, 0x0330, 0x0045,
+ 0x0327, 0x0306, 0x0065, 0x0327, 0x0306, 0x0046, 0x0307, 0x0066,
+ 0x0307, 0x0047, 0x0304, 0x0067, 0x0304, 0x0048, 0x0307, 0x0068,
+ 0x0307, 0x0048, 0x0323, 0x0068, 0x0323, 0x0048, 0x0308, 0x0068,
+ 0x0308, 0x0048, 0x0327, 0x0068, 0x0327, 0x0048, 0x032e, 0x0068,
+ 0x032e, 0x0049, 0x0330, 0x0069, 0x0330, 0x0049, 0x0308, 0x0301,
+ 0x0069, 0x0308, 0x0301, 0x004b, 0x0301, 0x006b, 0x0301, 0x004b,
+ 0x0323, 0x006b, 0x0323, 0x004b, 0x0331, 0x006b, 0x0331, 0x004c,
+ 0x0323, 0x006c, 0x0323, 0x004c, 0x0323, 0x0304, 0x006c, 0x0323,
+ 0x0304, 0x004c, 0x0331, 0x006c, 0x0331, 0x004c, 0x032d, 0x006c,
+ 0x032d, 0x004d, 0x0301, 0x006d, 0x0301, 0x004d, 0x0307, 0x006d,
+ 0x0307, 0x004d, 0x0323, 0x006d, 0x0323, 0x004e, 0x0307, 0x006e,
+ 0x0307, 0x004e, 0x0323, 0x006e, 0x0323, 0x004e, 0x0331, 0x006e,
+ 0x0331, 0x004e, 0x032d, 0x006e, 0x032d, 0x004f, 0x0303, 0x0301,
+ 0x006f, 0x0303, 0x0301, 0x004f, 0x0303, 0x0308, 0x006f, 0x0303,
+ 0x0308, 0x004f, 0x0304, 0x0300, 0x006f, 0x0304, 0x0300, 0x004f,
+ 0x0304, 0x0301, 0x006f, 0x0304, 0x0301, 0x0050, 0x0301, 0x0070,
+ 0x0301, 0x0050, 0x0307, 0x0070, 0x0307, 0x0052, 0x0307, 0x0072,
+ 0x0307, 0x0052, 0x0323, 0x0072, 0x0323, 0x0052, 0x0323, 0x0304,
+ 0x0072, 0x0323, 0x0304, 0x0052, 0x0331, 0x0072, 0x0331, 0x0053,
+ 0x0307, 0x0073, 0x0307, 0x0053, 0x0323, 0x0073, 0x0323, 0x0053,
+ 0x0301, 0x0307, 0x0073, 0x0301, 0x0307, 0x0053, 0x030c, 0x0307,
+ 0x0073, 0x030c, 0x0307, 0x0053, 0x0323, 0x0307, 0x0073, 0x0323,
+ 0x0307, 0x0054, 0x0307, 0x0074, 0x0307, 0x0054, 0x0323, 0x0074,
+ 0x0323, 0x0054, 0x0331, 0x0074, 0x0331, 0x0054, 0x032d, 0x0074,
+ 0x032d, 0x0055, 0x0324, 0x0075, 0x0324, 0x0055, 0x0330, 0x0075,
+ 0x0330, 0x0055, 0x032d, 0x0075, 0x032d, 0x0055, 0x0303, 0x0301,
+ 0x0075, 0x0303, 0x0301, 0x0055, 0x0304, 0x0308, 0x0075, 0x0304,
+ 0x0308, 0x0056, 0x0303, 0x0076, 0x0303, 0x0056, 0x0323, 0x0076,
+ 0x0323, 0x0057, 0x0300, 0x0077, 0x0300, 0x0057, 0x0301, 0x0077,
+ 0x0301, 0x0057, 0x0308, 0x0077, 0x0308, 0x0057, 0x0307, 0x0077,
+ 0x0307, 0x0057, 0x0323, 0x0077, 0x0323, 0x0058, 0x0307, 0x0078,
+ 0x0307, 0x0058, 0x0308, 0x0078, 0x0308, 0x0059, 0x0307, 0x0079,
+ 0x0307, 0x005a, 0x0302, 0x007a, 0x0302, 0x005a, 0x0323, 0x007a,
+ 0x0323, 0x005a, 0x0331, 0x007a, 0x0331, 0x0068, 0x0331, 0x0074,
+ 0x0308, 0x0077, 0x030a, 0x0079, 0x030a, 0x017f, 0x0307, 0x0041,
+ 0x0323, 0x0061, 0x0323, 0x0041, 0x0309, 0x0061, 0x0309, 0x0041,
+ 0x0302, 0x0301, 0x0061, 0x0302, 0x0301, 0x0041, 0x0302, 0x0300,
+ 0x0061, 0x0302, 0x0300, 0x0041, 0x0302, 0x0309, 0x0061, 0x0302,
+ 0x0309, 0x0041, 0x0302, 0x0303, 0x0061, 0x0302, 0x0303, 0x0041,
+ 0x0323, 0x0302, 0x0061, 0x0323, 0x0302, 0x0041, 0x0306, 0x0301,
+ 0x0061, 0x0306, 0x0301, 0x0041, 0x0306, 0x0300, 0x0061, 0x0306,
+ 0x0300, 0x0041, 0x0306, 0x0309, 0x0061, 0x0306, 0x0309, 0x0041,
+ 0x0306, 0x0303, 0x0061, 0x0306, 0x0303, 0x0041, 0x0323, 0x0306,
+ 0x0061, 0x0323, 0x0306, 0x0045, 0x0323, 0x0065, 0x0323, 0x0045,
+ 0x0309, 0x0065, 0x0309, 0x0045, 0x0303, 0x0065, 0x0303, 0x0045,
+ 0x0302, 0x0301, 0x0065, 0x0302, 0x0301, 0x0045, 0x0302, 0x0300,
+ 0x0065, 0x0302, 0x0300, 0x0045, 0x0302, 0x0309, 0x0065, 0x0302,
+ 0x0309, 0x0045, 0x0302, 0x0303, 0x0065, 0x0302, 0x0303, 0x0045,
+ 0x0323, 0x0302, 0x0065, 0x0323, 0x0302, 0x0049, 0x0309, 0x0069,
+ 0x0309, 0x0049, 0x0323, 0x0069, 0x0323, 0x004f, 0x0323, 0x006f,
+ 0x0323, 0x004f, 0x0309, 0x006f, 0x0309, 0x004f, 0x0302, 0x0301,
+ 0x006f, 0x0302, 0x0301, 0x004f, 0x0302, 0x0300, 0x006f, 0x0302,
+ 0x0300, 0x004f, 0x0302, 0x0309, 0x006f, 0x0302, 0x0309, 0x004f,
+ 0x0302, 0x0303, 0x006f, 0x0302, 0x0303, 0x004f, 0x0323, 0x0302,
+ 0x006f, 0x0323, 0x0302, 0x004f, 0x031b, 0x0301, 0x006f, 0x031b,
+ 0x0301, 0x004f, 0x031b, 0x0300, 0x006f, 0x031b, 0x0300, 0x004f,
+ 0x031b, 0x0309, 0x006f, 0x031b, 0x0309, 0x004f, 0x031b, 0x0303,
+ 0x006f, 0x031b, 0x0303, 0x004f, 0x031b, 0x0323, 0x006f, 0x031b,
+ 0x0323, 0x0055, 0x0323, 0x0075, 0x0323, 0x0055, 0x0309, 0x0075,
+ 0x0309, 0x0055, 0x031b, 0x0301, 0x0075, 0x031b, 0x0301, 0x0055,
+ 0x031b, 0x0300, 0x0075, 0x031b, 0x0300, 0x0055, 0x031b, 0x0309,
+ 0x0075, 0x031b, 0x0309, 0x0055, 0x031b, 0x0303, 0x0075, 0x031b,
+ 0x0303, 0x0055, 0x031b, 0x0323, 0x0075, 0x031b, 0x0323, 0x0059,
+ 0x0300, 0x0079, 0x0300, 0x0059, 0x0323, 0x0079, 0x0323, 0x0059,
+ 0x0309, 0x0079, 0x0309, 0x0059, 0x0303, 0x0079, 0x0303, 0x03b1,
+ 0x0313, 0x03b1, 0x0314, 0x03b1, 0x0313, 0x0300, 0x03b1, 0x0314,
+ 0x0300, 0x03b1, 0x0313, 0x0301, 0x03b1, 0x0314, 0x0301, 0x03b1,
+ 0x0313, 0x0342, 0x03b1, 0x0314, 0x0342, 0x0391, 0x0313, 0x0391,
+ 0x0314, 0x0391, 0x0313, 0x0300, 0x0391, 0x0314, 0x0300, 0x0391,
+ 0x0313, 0x0301, 0x0391, 0x0314, 0x0301, 0x0391, 0x0313, 0x0342,
+ 0x0391, 0x0314, 0x0342, 0x03b5, 0x0313, 0x03b5, 0x0314, 0x03b5,
+ 0x0313, 0x0300, 0x03b5, 0x0314, 0x0300, 0x03b5, 0x0313, 0x0301,
+ 0x03b5, 0x0314, 0x0301, 0x0395, 0x0313, 0x0395, 0x0314, 0x0395,
+ 0x0313, 0x0300, 0x0395, 0x0314, 0x0300, 0x0395, 0x0313, 0x0301,
+ 0x0395, 0x0314, 0x0301, 0x03b7, 0x0313, 0x03b7, 0x0314, 0x03b7,
+ 0x0313, 0x0300, 0x03b7, 0x0314, 0x0300, 0x03b7, 0x0313, 0x0301,
+ 0x03b7, 0x0314, 0x0301, 0x03b7, 0x0313, 0x0342, 0x03b7, 0x0314,
+ 0x0342, 0x0397, 0x0313, 0x0397, 0x0314, 0x0397, 0x0313, 0x0300,
+ 0x0397, 0x0314, 0x0300, 0x0397, 0x0313, 0x0301, 0x0397, 0x0314,
+ 0x0301, 0x0397, 0x0313, 0x0342, 0x0397, 0x0314, 0x0342, 0x03b9,
+ 0x0313, 0x03b9, 0x0314, 0x03b9, 0x0313, 0x0300, 0x03b9, 0x0314,
+ 0x0300, 0x03b9, 0x0313, 0x0301, 0x03b9, 0x0314, 0x0301, 0x03b9,
+ 0x0313, 0x0342, 0x03b9, 0x0314, 0x0342, 0x0399, 0x0313, 0x0399,
+ 0x0314, 0x0399, 0x0313, 0x0300, 0x0399, 0x0314, 0x0300, 0x0399,
+ 0x0313, 0x0301, 0x0399, 0x0314, 0x0301, 0x0399, 0x0313, 0x0342,
+ 0x0399, 0x0314, 0x0342, 0x03bf, 0x0313, 0x03bf, 0x0314, 0x03bf,
+ 0x0313, 0x0300, 0x03bf, 0x0314, 0x0300, 0x03bf, 0x0313, 0x0301,
+ 0x03bf, 0x0314, 0x0301, 0x039f, 0x0313, 0x039f, 0x0314, 0x039f,
+ 0x0313, 0x0300, 0x039f, 0x0314, 0x0300, 0x039f, 0x0313, 0x0301,
+ 0x039f, 0x0314, 0x0301, 0x03c5, 0x0313, 0x03c5, 0x0314, 0x03c5,
+ 0x0313, 0x0300, 0x03c5, 0x0314, 0x0300, 0x03c5, 0x0313, 0x0301,
+ 0x03c5, 0x0314, 0x0301, 0x03c5, 0x0313, 0x0342, 0x03c5, 0x0314,
+ 0x0342, 0x03a5, 0x0314, 0x03a5, 0x0314, 0x0300, 0x03a5, 0x0314,
+ 0x0301, 0x03a5, 0x0314, 0x0342, 0x03c9, 0x0313, 0x03c9, 0x0314,
+ 0x03c9, 0x0313, 0x0300, 0x03c9, 0x0314, 0x0300, 0x03c9, 0x0313,
+ 0x0301, 0x03c9, 0x0314, 0x0301, 0x03c9, 0x0313, 0x0342, 0x03c9,
+ 0x0314, 0x0342, 0x03a9, 0x0313, 0x03a9, 0x0314, 0x03a9, 0x0313,
+ 0x0300, 0x03a9, 0x0314, 0x0300, 0x03a9, 0x0313, 0x0301, 0x03a9,
+ 0x0314, 0x0301, 0x03a9, 0x0313, 0x0342, 0x03a9, 0x0314, 0x0342,
+ 0x03b1, 0x0300, 0x03b1, 0x0301, 0x03b5, 0x0300, 0x03b5, 0x0301,
+ 0x03b7, 0x0300, 0x03b7, 0x0301, 0x03b9, 0x0300, 0x03b9, 0x0301,
+ 0x03bf, 0x0300, 0x03bf, 0x0301, 0x03c5, 0x0300, 0x03c5, 0x0301,
+ 0x03c9, 0x0300, 0x03c9, 0x0301, 0x03b1, 0x0345, 0x0313, 0x03b1,
+ 0x0345, 0x0314, 0x03b1, 0x0345, 0x0313, 0x0300, 0x03b1, 0x0345,
+ 0x0314, 0x0300, 0x03b1, 0x0345, 0x0313, 0x0301, 0x03b1, 0x0345,
+ 0x0314, 0x0301, 0x03b1, 0x0345, 0x0313, 0x0342, 0x03b1, 0x0345,
+ 0x0314, 0x0342, 0x0391, 0x0345, 0x0313, 0x0391, 0x0345, 0x0314,
+ 0x0391, 0x0345, 0x0313, 0x0300, 0x0391, 0x0345, 0x0314, 0x0300,
+ 0x0391, 0x0345, 0x0313, 0x0301, 0x0391, 0x0345, 0x0314, 0x0301,
+ 0x0391, 0x0345, 0x0313, 0x0342, 0x0391, 0x0345, 0x0314, 0x0342,
+ 0x03b7, 0x0345, 0x0313, 0x03b7, 0x0345, 0x0314, 0x03b7, 0x0345,
+ 0x0313, 0x0300, 0x03b7, 0x0345, 0x0314, 0x0300, 0x03b7, 0x0345,
+ 0x0313, 0x0301, 0x03b7, 0x0345, 0x0314, 0x0301, 0x03b7, 0x0345,
+ 0x0313, 0x0342, 0x03b7, 0x0345, 0x0314, 0x0342, 0x0397, 0x0345,
+ 0x0313, 0x0397, 0x0345, 0x0314, 0x0397, 0x0345, 0x0313, 0x0300,
+ 0x0397, 0x0345, 0x0314, 0x0300, 0x0397, 0x0345, 0x0313, 0x0301,
+ 0x0397, 0x0345, 0x0314, 0x0301, 0x0397, 0x0345, 0x0313, 0x0342,
+ 0x0397, 0x0345, 0x0314, 0x0342, 0x03c9, 0x0345, 0x0313, 0x03c9,
+ 0x0345, 0x0314, 0x03c9, 0x0345, 0x0313, 0x0300, 0x03c9, 0x0345,
+ 0x0314, 0x0300, 0x03c9, 0x0345, 0x0313, 0x0301, 0x03c9, 0x0345,
+ 0x0314, 0x0301, 0x03c9, 0x0345, 0x0313, 0x0342, 0x03c9, 0x0345,
+ 0x0314, 0x0342, 0x03a9, 0x0345, 0x0313, 0x03a9, 0x0345, 0x0314,
+ 0x03a9, 0x0345, 0x0313, 0x0300, 0x03a9, 0x0345, 0x0314, 0x0300,
+ 0x03a9, 0x0345, 0x0313, 0x0301, 0x03a9, 0x0345, 0x0314, 0x0301,
+ 0x03a9, 0x0345, 0x0313, 0x0342, 0x03a9, 0x0345, 0x0314, 0x0342,
+ 0x03b1, 0x0306, 0x03b1, 0x0304, 0x03b1, 0x0345, 0x0300, 0x03b1,
+ 0x0345, 0x03b1, 0x0345, 0x0301, 0x03b1, 0x0342, 0x03b1, 0x0345,
+ 0x0342, 0x0391, 0x0306, 0x0391, 0x0304, 0x0391, 0x0300, 0x0391,
+ 0x0301, 0x0391, 0x0345, 0x03b9, 0x00a8, 0x0342, 0x03b7, 0x0345,
+ 0x0300, 0x03b7, 0x0345, 0x03b7, 0x0345, 0x0301, 0x03b7, 0x0342,
+ 0x03b7, 0x0345, 0x0342, 0x0395, 0x0300, 0x0395, 0x0301, 0x0397,
+ 0x0300, 0x0397, 0x0301, 0x0397, 0x0345, 0x1fbf, 0x0300, 0x1fbf,
+ 0x0301, 0x1fbf, 0x0342, 0x03b9, 0x0306, 0x03b9, 0x0304, 0x03b9,
+ 0x0308, 0x0300, 0x03b9, 0x0308, 0x0301, 0x03b9, 0x0342, 0x03b9,
+ 0x0308, 0x0342, 0x0399, 0x0306, 0x0399, 0x0304, 0x0399, 0x0300,
+ 0x0399, 0x0301, 0x1ffe, 0x0300, 0x1ffe, 0x0301, 0x1ffe, 0x0342,
+ 0x03c5, 0x0306, 0x03c5, 0x0304, 0x03c5, 0x0308, 0x0300, 0x03c5,
+ 0x0308, 0x0301, 0x03c1, 0x0313, 0x03c1, 0x0314, 0x03c5, 0x0342,
+ 0x03c5, 0x0308, 0x0342, 0x03a5, 0x0306, 0x03a5, 0x0304, 0x03a5,
+ 0x0300, 0x03a5, 0x0301, 0x03a1, 0x0314, 0x00a8, 0x0300, 0x00a8,
+ 0x0301, 0x0060, 0x03c9, 0x0345, 0x0300, 0x03c9, 0x0345, 0x03bf,
+ 0x0345, 0x0301, 0x03c9, 0x0342, 0x03c9, 0x0345, 0x0342, 0x039f,
+ 0x0300, 0x039f, 0x0301, 0x03a9, 0x0300, 0x03a9, 0x0301, 0x03a9,
+ 0x0345, 0x00b4, 0x304b, 0x3099, 0x304d, 0x3099, 0x304f, 0x3099,
+ 0x3051, 0x3099, 0x3053, 0x3099, 0x3055, 0x3099, 0x3057, 0x3099,
+ 0x3059, 0x3099, 0x305b, 0x3099, 0x305d, 0x3099, 0x305f, 0x3099,
+ 0x3061, 0x3099, 0x3064, 0x3099, 0x3066, 0x3099, 0x3068, 0x3099,
+ 0x306f, 0x3099, 0x306f, 0x309a, 0x3072, 0x3099, 0x3072, 0x309a,
+ 0x3075, 0x3099, 0x3075, 0x309a, 0x3078, 0x3099, 0x3078, 0x309a,
+ 0x307b, 0x3099, 0x307b, 0x309a, 0x3046, 0x3099, 0x309d, 0x3099,
+ 0x30ab, 0x3099, 0x30ad, 0x3099, 0x30af, 0x3099, 0x30b1, 0x3099,
+ 0x30b3, 0x3099, 0x30b5, 0x3099, 0x30b7, 0x3099, 0x30b9, 0x3099,
+ 0x30bb, 0x3099, 0x30bd, 0x3099, 0x30bf, 0x3099, 0x30c1, 0x3099,
+ 0x30c4, 0x3099, 0x30c6, 0x3099, 0x30c8, 0x3099, 0x30cf, 0x3099,
+ 0x30cf, 0x309a, 0x30d2, 0x3099, 0x30d2, 0x309a, 0x30d5, 0x3099,
+ 0x30d5, 0x309a, 0x30d8, 0x3099, 0x30d8, 0x309a, 0x30db, 0x3099,
+ 0x30db, 0x309a, 0x30a6, 0x3099, 0x30ef, 0x3099, 0x30f0, 0x3099,
+ 0x30f1, 0x3099, 0x30f2, 0x3099, 0x30fd, 0x3099, 0x05f2, 0x05b7,
+ 0x05e9, 0x05c1, 0x05e9, 0x05c2, 0x05e9, 0x05bc, 0x05c1, 0x05e9,
+ 0x05bc, 0x05c2, 0x05d0, 0x05b7, 0x05d0, 0x05b8, 0x05d0, 0x05bc,
+ 0x05d1, 0x05bc, 0x05d2, 0x05bc, 0x05d3, 0x05bc, 0x05d4, 0x05bc,
+ 0x05d5, 0x05bc, 0x05d6, 0x05bc, 0x05d8, 0x05bc, 0x05d9, 0x05bc,
+ 0x05da, 0x05bc, 0x05db, 0x05bc, 0x05dc, 0x05bc, 0x05de, 0x05bc,
+ 0x05e0, 0x05bc, 0x05e1, 0x05bc, 0x05e3, 0x05bc, 0x05e4, 0x05bc,
+ 0x05e6, 0x05bc, 0x05e7, 0x05bc, 0x05e8, 0x05bc, 0x05e9, 0x05bc,
+ 0x05ea, 0x05bc, 0x05d5, 0x05b9, 0x05d1, 0x05bf, 0x05db, 0x05bf,
+ 0x05e4, 0x05bf
+};
+
+u16 hfsplus_compose_table[] = {
+ /* base */
+ 0x0000, 0x0050, 0x0300, 0x00a4, 0x0301, 0x00e4, 0x0302, 0x015c,
+ 0x0303, 0x0192, 0x0304, 0x01b4, 0x0306, 0x01e6, 0x0307, 0x0220,
+ 0x0308, 0x0270, 0x0309, 0x02d2, 0x030a, 0x02ec, 0x030b, 0x02fa,
+ 0x030c, 0x0308, 0x030d, 0x034c, 0x030f, 0x0370, 0x0311, 0x038e,
+ 0x0313, 0x03a8, 0x0314, 0x03c6, 0x031b, 0x03e8, 0x0323, 0x03f2,
+ 0x0324, 0x0440, 0x0325, 0x0446, 0x0327, 0x044c, 0x0328, 0x047a,
+ 0x032d, 0x0490, 0x032e, 0x04aa, 0x0330, 0x04b0, 0x0331, 0x04be,
+ 0x0342, 0x04e2, 0x0345, 0x04f4, 0x05b7, 0x0504, 0x05b8, 0x050a,
+ 0x05b9, 0x050e, 0x05bc, 0x0512, 0x05bf, 0x0540, 0x05c1, 0x0548,
+ 0x05c2, 0x054c, 0x093c, 0x0550, 0x09bc, 0x0568, 0x09be, 0x0572,
+ 0x09d7, 0x0576, 0x0a3c, 0x057a, 0x0b3c, 0x0586, 0x0b3e, 0x058e,
+ 0x0b56, 0x0592, 0x0b57, 0x0596, 0x0bbe, 0x059a, 0x0bd7, 0x05a0,
+ 0x0c56, 0x05a6, 0x0cc2, 0x05aa, 0x0cd5, 0x05ae, 0x0cd6, 0x05b4,
+ 0x0d3e, 0x05b8, 0x0d57, 0x05be, 0x0e32, 0x05c2, 0x0eb2, 0x05c6,
+ 0x0f71, 0x05ca, 0x0f80, 0x05d2, 0x0fb5, 0x05d8, 0x0fb7, 0x05de,
+ 0x1100, 0x00a2, 0x1101, 0x00a2, 0x1102, 0x00a2, 0x1103, 0x00a2,
+ 0x1104, 0x00a2, 0x1105, 0x00a2, 0x1106, 0x00a2, 0x1107, 0x00a2,
+ 0x1108, 0x00a2, 0x1109, 0x00a2, 0x110a, 0x00a2, 0x110b, 0x00a2,
+ 0x110c, 0x00a2, 0x110d, 0x00a2, 0x110e, 0x00a2, 0x110f, 0x00a2,
+ 0x1110, 0x00a2, 0x1111, 0x00a2, 0x1112, 0x00a2, 0x3099, 0x05f4,
+ 0x309a, 0x0656,
+ /* hangul marker */
+ 0xffff, 0x0000,
+ /* 0x0300 */
+ 0x0340, 0x001f, 0x0041, 0x066c, 0x0045, 0x066e, 0x0049, 0x0670,
+ 0x004f, 0x0672, 0x0055, 0x0674, 0x0057, 0x0676, 0x0059, 0x0678,
+ 0x0061, 0x067a, 0x0065, 0x067c, 0x0069, 0x067e, 0x006f, 0x0680,
+ 0x0075, 0x0682, 0x0077, 0x0684, 0x0079, 0x0686, 0x00a8, 0x0688,
+ 0x0391, 0x068a, 0x0395, 0x068c, 0x0397, 0x068e, 0x0399, 0x0690,
+ 0x039f, 0x0692, 0x03a5, 0x0694, 0x03a9, 0x0696, 0x03b1, 0x0698,
+ 0x03b5, 0x069a, 0x03b7, 0x069c, 0x03b9, 0x069e, 0x03bf, 0x06a0,
+ 0x03c5, 0x06a2, 0x03c9, 0x06a4, 0x1fbf, 0x06a6, 0x1ffe, 0x06a8,
+ /* 0x0301 */
+ 0x0341, 0x003b, 0x0041, 0x06aa, 0x0043, 0x06ac, 0x0045, 0x06ae,
+ 0x0047, 0x06b0, 0x0049, 0x06b2, 0x004b, 0x06b4, 0x004c, 0x06b6,
+ 0x004d, 0x06b8, 0x004e, 0x06ba, 0x004f, 0x06bc, 0x0050, 0x06be,
+ 0x0052, 0x06c0, 0x0053, 0x06c2, 0x0055, 0x06c6, 0x0057, 0x06c8,
+ 0x0059, 0x06ca, 0x005a, 0x06cc, 0x0061, 0x06ce, 0x0063, 0x06d0,
+ 0x0065, 0x06d2, 0x0067, 0x06d4, 0x0069, 0x06d6, 0x006b, 0x06d8,
+ 0x006c, 0x06da, 0x006d, 0x06dc, 0x006e, 0x06de, 0x006f, 0x06e0,
+ 0x0070, 0x06e2, 0x0072, 0x06e4, 0x0073, 0x06e6, 0x0075, 0x06ea,
+ 0x0077, 0x06ec, 0x0079, 0x06ee, 0x007a, 0x06f0, 0x00a8, 0x06f2,
+ 0x00c6, 0x06f4, 0x00d8, 0x06f6, 0x00e6, 0x06f8, 0x00f8, 0x06fa,
+ 0x0391, 0x06fc, 0x0395, 0x06fe, 0x0397, 0x0700, 0x0399, 0x0702,
+ 0x039f, 0x0704, 0x03a5, 0x0706, 0x03a9, 0x0708, 0x03b1, 0x070a,
+ 0x03b5, 0x070c, 0x03b7, 0x070e, 0x03b9, 0x0710, 0x03bf, 0x0712,
+ 0x03c5, 0x0714, 0x03c9, 0x0716, 0x0413, 0x0718, 0x041a, 0x071a,
+ 0x0433, 0x071c, 0x043a, 0x071e, 0x1fbf, 0x0720, 0x1ffe, 0x0722,
+ /* 0x0302 */
+ 0x0000, 0x001a, 0x0041, 0x0724, 0x0043, 0x072e, 0x0045, 0x0730,
+ 0x0047, 0x073a, 0x0048, 0x073c, 0x0049, 0x073e, 0x004a, 0x0740,
+ 0x004f, 0x0742, 0x0053, 0x074c, 0x0055, 0x074e, 0x0057, 0x0750,
+ 0x0059, 0x0752, 0x005a, 0x0754, 0x0061, 0x0756, 0x0063, 0x0760,
+ 0x0065, 0x0762, 0x0067, 0x076c, 0x0068, 0x076e, 0x0069, 0x0770,
+ 0x006a, 0x0772, 0x006f, 0x0774, 0x0073, 0x077e, 0x0075, 0x0780,
+ 0x0077, 0x0782, 0x0079, 0x0784, 0x007a, 0x0786,
+ /* 0x0303 */
+ 0x0000, 0x0010, 0x0041, 0x0788, 0x0045, 0x078a, 0x0049, 0x078c,
+ 0x004e, 0x078e, 0x004f, 0x0790, 0x0055, 0x0796, 0x0056, 0x079a,
+ 0x0059, 0x079c, 0x0061, 0x079e, 0x0065, 0x07a0, 0x0069, 0x07a2,
+ 0x006e, 0x07a4, 0x006f, 0x07a6, 0x0075, 0x07ac, 0x0076, 0x07b0,
+ 0x0079, 0x07b2,
+ /* 0x0304 */
+ 0x0000, 0x0018, 0x0041, 0x07b4, 0x0045, 0x07b6, 0x0047, 0x07bc,
+ 0x0049, 0x07be, 0x004f, 0x07c0, 0x0055, 0x07c6, 0x0061, 0x07ca,
+ 0x0065, 0x07cc, 0x0067, 0x07d2, 0x0069, 0x07d4, 0x006f, 0x07d6,
+ 0x0075, 0x07dc, 0x00c6, 0x07e0, 0x00e6, 0x07e2, 0x0391, 0x07e4,
+ 0x0399, 0x07e6, 0x03a5, 0x07e8, 0x03b1, 0x07ea, 0x03b9, 0x07ec,
+ 0x03c5, 0x07ee, 0x0418, 0x07f0, 0x0423, 0x07f2, 0x0438, 0x07f4,
+ 0x0443, 0x07f6,
+ /* 0x0306 */
+ 0x0000, 0x001c, 0x0041, 0x07f8, 0x0045, 0x0802, 0x0047, 0x0804,
+ 0x0049, 0x0806, 0x004f, 0x0808, 0x0055, 0x080a, 0x0061, 0x080c,
+ 0x0065, 0x0816, 0x0067, 0x0818, 0x0069, 0x081a, 0x006f, 0x081c,
+ 0x0075, 0x081e, 0x0391, 0x0820, 0x0399, 0x0822, 0x03a5, 0x0824,
+ 0x03b1, 0x0826, 0x03b9, 0x0828, 0x03c5, 0x082a, 0x0410, 0x082c,
+ 0x0415, 0x082e, 0x0416, 0x0830, 0x0418, 0x0832, 0x0423, 0x0834,
+ 0x0430, 0x0836, 0x0435, 0x0838, 0x0436, 0x083a, 0x0438, 0x083c,
+ 0x0443, 0x083e,
+ /* 0x0307 */
+ 0x0000, 0x0027, 0x0041, 0x0840, 0x0042, 0x0844, 0x0043, 0x0846,
+ 0x0044, 0x0848, 0x0045, 0x084a, 0x0046, 0x084c, 0x0047, 0x084e,
+ 0x0048, 0x0850, 0x0049, 0x0852, 0x004d, 0x0854, 0x004e, 0x0856,
+ 0x0050, 0x0858, 0x0052, 0x085a, 0x0053, 0x085c, 0x0054, 0x085e,
+ 0x0057, 0x0860, 0x0058, 0x0862, 0x0059, 0x0864, 0x005a, 0x0866,
+ 0x0061, 0x0868, 0x0062, 0x086c, 0x0063, 0x086e, 0x0064, 0x0870,
+ 0x0065, 0x0872, 0x0066, 0x0874, 0x0067, 0x0876, 0x0068, 0x0878,
+ 0x006d, 0x087a, 0x006e, 0x087c, 0x0070, 0x087e, 0x0072, 0x0880,
+ 0x0073, 0x0882, 0x0074, 0x0884, 0x0077, 0x0886, 0x0078, 0x0888,
+ 0x0079, 0x088a, 0x007a, 0x088c, 0x017f, 0x088e, 0x0306, 0x0890,
+ /* 0x0308 */
+ 0x0000, 0x0030, 0x0041, 0x0892, 0x0045, 0x0896, 0x0048, 0x0898,
+ 0x0049, 0x089a, 0x004f, 0x089e, 0x0055, 0x08a0, 0x0057, 0x08aa,
+ 0x0058, 0x08ac, 0x0059, 0x08ae, 0x0061, 0x08b0, 0x0065, 0x08b4,
+ 0x0068, 0x08b6, 0x0069, 0x08b8, 0x006f, 0x08bc, 0x0074, 0x08be,
+ 0x0075, 0x08c0, 0x0077, 0x08ca, 0x0078, 0x08cc, 0x0079, 0x08ce,
+ 0x018f, 0x08d0, 0x019f, 0x08d2, 0x0259, 0x08d4, 0x0275, 0x08d6,
+ 0x0399, 0x08d8, 0x03a5, 0x08da, 0x03b9, 0x08dc, 0x03c5, 0x08e6,
+ 0x03d2, 0x08f0, 0x0406, 0x08f2, 0x0410, 0x08f4, 0x0415, 0x08f6,
+ 0x0416, 0x08f8, 0x0417, 0x08fa, 0x0418, 0x08fc, 0x041e, 0x08fe,
+ 0x0423, 0x0900, 0x0427, 0x0902, 0x042b, 0x0904, 0x0430, 0x0906,
+ 0x0435, 0x0908, 0x0436, 0x090a, 0x0437, 0x090c, 0x0438, 0x090e,
+ 0x043e, 0x0910, 0x0443, 0x0912, 0x0447, 0x0914, 0x044b, 0x0916,
+ 0x0456, 0x0918,
+ /* 0x0309 */
+ 0x0000, 0x000c, 0x0041, 0x091a, 0x0045, 0x091c, 0x0049, 0x091e,
+ 0x004f, 0x0920, 0x0055, 0x0922, 0x0059, 0x0924, 0x0061, 0x0926,
+ 0x0065, 0x0928, 0x0069, 0x092a, 0x006f, 0x092c, 0x0075, 0x092e,
+ 0x0079, 0x0930,
+ /* 0x030a */
+ 0x0000, 0x0006, 0x0041, 0x0932, 0x0055, 0x0936, 0x0061, 0x0938,
+ 0x0075, 0x093c, 0x0077, 0x093e, 0x0079, 0x0940,
+ /* 0x030b */
+ 0x0000, 0x0006, 0x004f, 0x0942, 0x0055, 0x0944, 0x006f, 0x0946,
+ 0x0075, 0x0948, 0x0423, 0x094a, 0x0443, 0x094c,
+ /* 0x030c */
+ 0x0000, 0x0021, 0x0041, 0x094e, 0x0043, 0x0950, 0x0044, 0x0952,
+ 0x0045, 0x0954, 0x0047, 0x0956, 0x0049, 0x0958, 0x004b, 0x095a,
+ 0x004c, 0x095c, 0x004e, 0x095e, 0x004f, 0x0960, 0x0052, 0x0962,
+ 0x0053, 0x0964, 0x0054, 0x0968, 0x0055, 0x096a, 0x005a, 0x096c,
+ 0x0061, 0x096e, 0x0063, 0x0970, 0x0064, 0x0972, 0x0065, 0x0974,
+ 0x0067, 0x0976, 0x0069, 0x0978, 0x006a, 0x097a, 0x006b, 0x097c,
+ 0x006c, 0x097e, 0x006e, 0x0980, 0x006f, 0x0982, 0x0072, 0x0984,
+ 0x0073, 0x0986, 0x0074, 0x098a, 0x0075, 0x098c, 0x007a, 0x098e,
+ 0x01b7, 0x0990, 0x0292, 0x0992,
+ /* 0x030d */
+ 0x0000, 0x0011, 0x00a8, 0x0994, 0x0308, 0x0996, 0x0391, 0x0998,
+ 0x0395, 0x099a, 0x0397, 0x099c, 0x0399, 0x099e, 0x039f, 0x09a0,
+ 0x03a5, 0x09a2, 0x03a9, 0x09a4, 0x03b1, 0x09a6, 0x03b5, 0x09a8,
+ 0x03b7, 0x09aa, 0x03b9, 0x09ac, 0x03bf, 0x09ae, 0x03c5, 0x09b0,
+ 0x03c9, 0x09b2, 0x03d2, 0x09b4,
+ /* 0x030f */
+ 0x0000, 0x000e, 0x0041, 0x09b6, 0x0045, 0x09b8, 0x0049, 0x09ba,
+ 0x004f, 0x09bc, 0x0052, 0x09be, 0x0055, 0x09c0, 0x0061, 0x09c2,
+ 0x0065, 0x09c4, 0x0069, 0x09c6, 0x006f, 0x09c8, 0x0072, 0x09ca,
+ 0x0075, 0x09cc, 0x0474, 0x09ce, 0x0475, 0x09d0,
+ /* 0x0311 */
+ 0x0000, 0x000c, 0x0041, 0x09d2, 0x0045, 0x09d4, 0x0049, 0x09d6,
+ 0x004f, 0x09d8, 0x0052, 0x09da, 0x0055, 0x09dc, 0x0061, 0x09de,
+ 0x0065, 0x09e0, 0x0069, 0x09e2, 0x006f, 0x09e4, 0x0072, 0x09e6,
+ 0x0075, 0x09e8,
+ /* 0x0313 */
+ 0x0343, 0x000e, 0x0391, 0x09ea, 0x0395, 0x09f2, 0x0397, 0x09f8,
+ 0x0399, 0x0a00, 0x039f, 0x0a08, 0x03a9, 0x0a0e, 0x03b1, 0x0a16,
+ 0x03b5, 0x0a1e, 0x03b7, 0x0a24, 0x03b9, 0x0a2c, 0x03bf, 0x0a34,
+ 0x03c1, 0x0a3a, 0x03c5, 0x0a3c, 0x03c9, 0x0a44,
+ /* 0x0314 */
+ 0x0000, 0x0010, 0x0391, 0x0a4c, 0x0395, 0x0a54, 0x0397, 0x0a5a,
+ 0x0399, 0x0a62, 0x039f, 0x0a6a, 0x03a1, 0x0a70, 0x03a5, 0x0a72,
+ 0x03a9, 0x0a7a, 0x03b1, 0x0a82, 0x03b5, 0x0a8a, 0x03b7, 0x0a90,
+ 0x03b9, 0x0a98, 0x03bf, 0x0aa0, 0x03c1, 0x0aa6, 0x03c5, 0x0aa8,
+ 0x03c9, 0x0ab0,
+ /* 0x031b */
+ 0x0000, 0x0004, 0x004f, 0x0ab8, 0x0055, 0x0ac4, 0x006f, 0x0ad0,
+ 0x0075, 0x0adc,
+ /* 0x0323 */
+ 0x0000, 0x0026, 0x0041, 0x0ae8, 0x0042, 0x0aee, 0x0044, 0x0af0,
+ 0x0045, 0x0af2, 0x0048, 0x0af6, 0x0049, 0x0af8, 0x004b, 0x0afa,
+ 0x004c, 0x0afc, 0x004d, 0x0b00, 0x004e, 0x0b02, 0x004f, 0x0b04,
+ 0x0052, 0x0b08, 0x0053, 0x0b0c, 0x0054, 0x0b10, 0x0055, 0x0b12,
+ 0x0056, 0x0b14, 0x0057, 0x0b16, 0x0059, 0x0b18, 0x005a, 0x0b1a,
+ 0x0061, 0x0b1c, 0x0062, 0x0b22, 0x0064, 0x0b24, 0x0065, 0x0b26,
+ 0x0068, 0x0b2a, 0x0069, 0x0b2c, 0x006b, 0x0b2e, 0x006c, 0x0b30,
+ 0x006d, 0x0b34, 0x006e, 0x0b36, 0x006f, 0x0b38, 0x0072, 0x0b3c,
+ 0x0073, 0x0b40, 0x0074, 0x0b44, 0x0075, 0x0b46, 0x0076, 0x0b48,
+ 0x0077, 0x0b4a, 0x0079, 0x0b4c, 0x007a, 0x0b4e,
+ /* 0x0324 */
+ 0x0000, 0x0002, 0x0055, 0x0b50, 0x0075, 0x0b52,
+ /* 0x0325 */
+ 0x0000, 0x0002, 0x0041, 0x0b54, 0x0061, 0x0b56,
+ /* 0x0327 */
+ 0x0000, 0x0016, 0x0043, 0x0b58, 0x0044, 0x0b5c, 0x0045, 0x0b5e,
+ 0x0047, 0x0b62, 0x0048, 0x0b64, 0x004b, 0x0b66, 0x004c, 0x0b68,
+ 0x004e, 0x0b6a, 0x0052, 0x0b6c, 0x0053, 0x0b6e, 0x0054, 0x0b70,
+ 0x0063, 0x0b72, 0x0064, 0x0b76, 0x0065, 0x0b78, 0x0067, 0x0b7c,
+ 0x0068, 0x0b7e, 0x006b, 0x0b80, 0x006c, 0x0b82, 0x006e, 0x0b84,
+ 0x0072, 0x0b86, 0x0073, 0x0b88, 0x0074, 0x0b8a,
+ /* 0x0328 */
+ 0x0000, 0x000a, 0x0041, 0x0b8c, 0x0045, 0x0b8e, 0x0049, 0x0b90,
+ 0x004f, 0x0b92, 0x0055, 0x0b96, 0x0061, 0x0b98, 0x0065, 0x0b9a,
+ 0x0069, 0x0b9c, 0x006f, 0x0b9e, 0x0075, 0x0ba2,
+ /* 0x032d */
+ 0x0000, 0x000c, 0x0044, 0x0ba4, 0x0045, 0x0ba6, 0x004c, 0x0ba8,
+ 0x004e, 0x0baa, 0x0054, 0x0bac, 0x0055, 0x0bae, 0x0064, 0x0bb0,
+ 0x0065, 0x0bb2, 0x006c, 0x0bb4, 0x006e, 0x0bb6, 0x0074, 0x0bb8,
+ 0x0075, 0x0bba,
+ /* 0x032e */
+ 0x0000, 0x0002, 0x0048, 0x0bbc, 0x0068, 0x0bbe,
+ /* 0x0330 */
+ 0x0000, 0x0006, 0x0045, 0x0bc0, 0x0049, 0x0bc2, 0x0055, 0x0bc4,
+ 0x0065, 0x0bc6, 0x0069, 0x0bc8, 0x0075, 0x0bca,
+ /* 0x0331 */
+ 0x0000, 0x0011, 0x0042, 0x0bcc, 0x0044, 0x0bce, 0x004b, 0x0bd0,
+ 0x004c, 0x0bd2, 0x004e, 0x0bd4, 0x0052, 0x0bd6, 0x0054, 0x0bd8,
+ 0x005a, 0x0bda, 0x0062, 0x0bdc, 0x0064, 0x0bde, 0x0068, 0x0be0,
+ 0x006b, 0x0be2, 0x006c, 0x0be4, 0x006e, 0x0be6, 0x0072, 0x0be8,
+ 0x0074, 0x0bea, 0x007a, 0x0bec,
+ /* 0x0342 */
+ 0x0000, 0x0008, 0x00a8, 0x0bee, 0x03b1, 0x0bf0, 0x03b7, 0x0bf2,
+ 0x03b9, 0x0bf4, 0x03c5, 0x0bf6, 0x03c9, 0x0bf8, 0x1fbf, 0x0bfa,
+ 0x1ffe, 0x0bfc,
+ /* 0x0345 */
+ 0x0000, 0x0007, 0x0391, 0x0bfe, 0x0397, 0x0c04, 0x03a9, 0x0c0a,
+ 0x03b1, 0x0c10, 0x03b7, 0x0c1c, 0x03bf, 0x0c28, 0x03c9, 0x0c2c,
+ /* 0x05b7 */
+ 0x0000, 0x0002, 0x05d0, 0x0c36, 0x05f2, 0x0c38,
+ /* 0x05b8 */
+ 0x0000, 0x0001, 0x05d0, 0x0c3a,
+ /* 0x05b9 */
+ 0x0000, 0x0001, 0x05d5, 0x0c3c,
+ /* 0x05bc */
+ 0x0000, 0x0016, 0x05d0, 0x0c3e, 0x05d1, 0x0c40, 0x05d2, 0x0c42,
+ 0x05d3, 0x0c44, 0x05d4, 0x0c46, 0x05d5, 0x0c48, 0x05d6, 0x0c4a,
+ 0x05d8, 0x0c4c, 0x05d9, 0x0c4e, 0x05da, 0x0c50, 0x05db, 0x0c52,
+ 0x05dc, 0x0c54, 0x05de, 0x0c56, 0x05e0, 0x0c58, 0x05e1, 0x0c5a,
+ 0x05e3, 0x0c5c, 0x05e4, 0x0c5e, 0x05e6, 0x0c60, 0x05e7, 0x0c62,
+ 0x05e8, 0x0c64, 0x05e9, 0x0c66, 0x05ea, 0x0c6c,
+ /* 0x05bf */
+ 0x0000, 0x0003, 0x05d1, 0x0c6e, 0x05db, 0x0c70, 0x05e4, 0x0c72,
+ /* 0x05c1 */
+ 0x0000, 0x0001, 0x05e9, 0x0c74,
+ /* 0x05c2 */
+ 0x0000, 0x0001, 0x05e9, 0x0c76,
+ /* 0x093c */
+ 0x0000, 0x000b, 0x0915, 0x0c78, 0x0916, 0x0c7a, 0x0917, 0x0c7c,
+ 0x091c, 0x0c7e, 0x0921, 0x0c80, 0x0922, 0x0c82, 0x0928, 0x0c84,
+ 0x092b, 0x0c86, 0x092f, 0x0c88, 0x0930, 0x0c8a, 0x0933, 0x0c8c,
+ /* 0x09bc */
+ 0x0000, 0x0004, 0x09a1, 0x0c8e, 0x09a2, 0x0c90, 0x09ac, 0x0c92,
+ 0x09af, 0x0c94,
+ /* 0x09be */
+ 0x0000, 0x0001, 0x09c7, 0x0c96,
+ /* 0x09d7 */
+ 0x0000, 0x0001, 0x09c7, 0x0c98,
+ /* 0x0a3c */
+ 0x0000, 0x0005, 0x0a16, 0x0c9a, 0x0a17, 0x0c9c, 0x0a1c, 0x0c9e,
+ 0x0a21, 0x0ca0, 0x0a2b, 0x0ca2,
+ /* 0x0b3c */
+ 0x0000, 0x0003, 0x0b21, 0x0ca4, 0x0b22, 0x0ca6, 0x0b2f, 0x0ca8,
+ /* 0x0b3e */
+ 0x0000, 0x0001, 0x0b47, 0x0caa,
+ /* 0x0b56 */
+ 0x0000, 0x0001, 0x0b47, 0x0cac,
+ /* 0x0b57 */
+ 0x0000, 0x0001, 0x0b47, 0x0cae,
+ /* 0x0bbe */
+ 0x0000, 0x0002, 0x0bc6, 0x0cb0, 0x0bc7, 0x0cb2,
+ /* 0x0bd7 */
+ 0x0000, 0x0002, 0x0b92, 0x0cb4, 0x0bc6, 0x0cb6,
+ /* 0x0c56 */
+ 0x0000, 0x0001, 0x0c46, 0x0cb8,
+ /* 0x0cc2 */
+ 0x0000, 0x0001, 0x0cc6, 0x0cba,
+ /* 0x0cd5 */
+ 0x0000, 0x0002, 0x0cbf, 0x0cbe, 0x0cc6, 0x0cc0,
+ /* 0x0cd6 */
+ 0x0000, 0x0001, 0x0cc6, 0x0cc2,
+ /* 0x0d3e */
+ 0x0000, 0x0002, 0x0d46, 0x0cc4, 0x0d47, 0x0cc6,
+ /* 0x0d57 */
+ 0x0000, 0x0001, 0x0d46, 0x0cc8,
+ /* 0x0e32 */
+ 0x0000, 0x0001, 0x0e4d, 0x0cca,
+ /* 0x0eb2 */
+ 0x0000, 0x0001, 0x0ecd, 0x0ccc,
+ /* 0x0f71 */
+ 0x0000, 0x0003, 0x0f72, 0x0cce, 0x0f74, 0x0cd0, 0x0f80, 0x0cd2,
+ /* 0x0f80 */
+ 0x0000, 0x0002, 0x0fb2, 0x0cd4, 0x0fb3, 0x0cd8,
+ /* 0x0fb5 */
+ 0x0000, 0x0002, 0x0f40, 0x0cdc, 0x0f90, 0x0cde,
+ /* 0x0fb7 */
+ 0x0000, 0x000a, 0x0f42, 0x0ce0, 0x0f4c, 0x0ce2, 0x0f51, 0x0ce4,
+ 0x0f56, 0x0ce6, 0x0f5b, 0x0ce8, 0x0f92, 0x0cea, 0x0f9c, 0x0cec,
+ 0x0fa1, 0x0cee, 0x0fa6, 0x0cf0, 0x0fab, 0x0cf2,
+ /* 0x3099 */
+ 0x0000, 0x0030, 0x3046, 0x0cf4, 0x304b, 0x0cf6, 0x304d, 0x0cf8,
+ 0x304f, 0x0cfa, 0x3051, 0x0cfc, 0x3053, 0x0cfe, 0x3055, 0x0d00,
+ 0x3057, 0x0d02, 0x3059, 0x0d04, 0x305b, 0x0d06, 0x305d, 0x0d08,
+ 0x305f, 0x0d0a, 0x3061, 0x0d0c, 0x3064, 0x0d0e, 0x3066, 0x0d10,
+ 0x3068, 0x0d12, 0x306f, 0x0d14, 0x3072, 0x0d16, 0x3075, 0x0d18,
+ 0x3078, 0x0d1a, 0x307b, 0x0d1c, 0x309d, 0x0d1e, 0x30a6, 0x0d20,
+ 0x30ab, 0x0d22, 0x30ad, 0x0d24, 0x30af, 0x0d26, 0x30b1, 0x0d28,
+ 0x30b3, 0x0d2a, 0x30b5, 0x0d2c, 0x30b7, 0x0d2e, 0x30b9, 0x0d30,
+ 0x30bb, 0x0d32, 0x30bd, 0x0d34, 0x30bf, 0x0d36, 0x30c1, 0x0d38,
+ 0x30c4, 0x0d3a, 0x30c6, 0x0d3c, 0x30c8, 0x0d3e, 0x30cf, 0x0d40,
+ 0x30d2, 0x0d42, 0x30d5, 0x0d44, 0x30d8, 0x0d46, 0x30db, 0x0d48,
+ 0x30ef, 0x0d4a, 0x30f0, 0x0d4c, 0x30f1, 0x0d4e, 0x30f2, 0x0d50,
+ 0x30fd, 0x0d52,
+ /* 0x309a */
+ 0x0000, 0x000a, 0x306f, 0x0d54, 0x3072, 0x0d56, 0x3075, 0x0d58,
+ 0x3078, 0x0d5a, 0x307b, 0x0d5c, 0x30cf, 0x0d5e, 0x30d2, 0x0d60,
+ 0x30d5, 0x0d62, 0x30d8, 0x0d64, 0x30db, 0x0d66,
+ /* 0x0041 0x0300 */
+ 0x00c0, 0x0000,
+ /* 0x0045 0x0300 */
+ 0x00c8, 0x0000,
+ /* 0x0049 0x0300 */
+ 0x00cc, 0x0000,
+ /* 0x004f 0x0300 */
+ 0x00d2, 0x0000,
+ /* 0x0055 0x0300 */
+ 0x00d9, 0x0000,
+ /* 0x0057 0x0300 */
+ 0x1e80, 0x0000,
+ /* 0x0059 0x0300 */
+ 0x1ef2, 0x0000,
+ /* 0x0061 0x0300 */
+ 0x00e0, 0x0000,
+ /* 0x0065 0x0300 */
+ 0x00e8, 0x0000,
+ /* 0x0069 0x0300 */
+ 0x00ec, 0x0000,
+ /* 0x006f 0x0300 */
+ 0x00f2, 0x0000,
+ /* 0x0075 0x0300 */
+ 0x00f9, 0x0000,
+ /* 0x0077 0x0300 */
+ 0x1e81, 0x0000,
+ /* 0x0079 0x0300 */
+ 0x1ef3, 0x0000,
+ /* 0x00a8 0x0300 */
+ 0x1fed, 0x0000,
+ /* 0x0391 0x0300 */
+ 0x1fba, 0x0000,
+ /* 0x0395 0x0300 */
+ 0x1fc8, 0x0000,
+ /* 0x0397 0x0300 */
+ 0x1fca, 0x0000,
+ /* 0x0399 0x0300 */
+ 0x1fda, 0x0000,
+ /* 0x039f 0x0300 */
+ 0x1ff8, 0x0000,
+ /* 0x03a5 0x0300 */
+ 0x1fea, 0x0000,
+ /* 0x03a9 0x0300 */
+ 0x1ffa, 0x0000,
+ /* 0x03b1 0x0300 */
+ 0x1f70, 0x0000,
+ /* 0x03b5 0x0300 */
+ 0x1f72, 0x0000,
+ /* 0x03b7 0x0300 */
+ 0x1f74, 0x0000,
+ /* 0x03b9 0x0300 */
+ 0x1f76, 0x0000,
+ /* 0x03bf 0x0300 */
+ 0x1f78, 0x0000,
+ /* 0x03c5 0x0300 */
+ 0x1f7a, 0x0000,
+ /* 0x03c9 0x0300 */
+ 0x1f7c, 0x0000,
+ /* 0x1fbf 0x0300 */
+ 0x1fcd, 0x0000,
+ /* 0x1ffe 0x0300 */
+ 0x1fdd, 0x0000,
+ /* 0x0041 0x0301 */
+ 0x00c1, 0x0000,
+ /* 0x0043 0x0301 */
+ 0x0106, 0x0000,
+ /* 0x0045 0x0301 */
+ 0x00c9, 0x0000,
+ /* 0x0047 0x0301 */
+ 0x01f4, 0x0000,
+ /* 0x0049 0x0301 */
+ 0x00cd, 0x0000,
+ /* 0x004b 0x0301 */
+ 0x1e30, 0x0000,
+ /* 0x004c 0x0301 */
+ 0x0139, 0x0000,
+ /* 0x004d 0x0301 */
+ 0x1e3e, 0x0000,
+ /* 0x004e 0x0301 */
+ 0x0143, 0x0000,
+ /* 0x004f 0x0301 */
+ 0x00d3, 0x0000,
+ /* 0x0050 0x0301 */
+ 0x1e54, 0x0000,
+ /* 0x0052 0x0301 */
+ 0x0154, 0x0000,
+ /* 0x0053 0x0301 */
+ 0x015a, 0x0001, 0x0307, 0x0d68,
+ /* 0x0055 0x0301 */
+ 0x00da, 0x0000,
+ /* 0x0057 0x0301 */
+ 0x1e82, 0x0000,
+ /* 0x0059 0x0301 */
+ 0x00dd, 0x0000,
+ /* 0x005a 0x0301 */
+ 0x0179, 0x0000,
+ /* 0x0061 0x0301 */
+ 0x00e1, 0x0000,
+ /* 0x0063 0x0301 */
+ 0x0107, 0x0000,
+ /* 0x0065 0x0301 */
+ 0x00e9, 0x0000,
+ /* 0x0067 0x0301 */
+ 0x01f5, 0x0000,
+ /* 0x0069 0x0301 */
+ 0x00ed, 0x0000,
+ /* 0x006b 0x0301 */
+ 0x1e31, 0x0000,
+ /* 0x006c 0x0301 */
+ 0x013a, 0x0000,
+ /* 0x006d 0x0301 */
+ 0x1e3f, 0x0000,
+ /* 0x006e 0x0301 */
+ 0x0144, 0x0000,
+ /* 0x006f 0x0301 */
+ 0x00f3, 0x0000,
+ /* 0x0070 0x0301 */
+ 0x1e55, 0x0000,
+ /* 0x0072 0x0301 */
+ 0x0155, 0x0000,
+ /* 0x0073 0x0301 */
+ 0x015b, 0x0001, 0x0307, 0x0d6a,
+ /* 0x0075 0x0301 */
+ 0x00fa, 0x0000,
+ /* 0x0077 0x0301 */
+ 0x1e83, 0x0000,
+ /* 0x0079 0x0301 */
+ 0x00fd, 0x0000,
+ /* 0x007a 0x0301 */
+ 0x017a, 0x0000,
+ /* 0x00a8 0x0301 */
+ 0x1fee, 0x0000,
+ /* 0x00c6 0x0301 */
+ 0x01fc, 0x0000,
+ /* 0x00d8 0x0301 */
+ 0x01fe, 0x0000,
+ /* 0x00e6 0x0301 */
+ 0x01fd, 0x0000,
+ /* 0x00f8 0x0301 */
+ 0x01ff, 0x0000,
+ /* 0x0391 0x0301 */
+ 0x1fbb, 0x0000,
+ /* 0x0395 0x0301 */
+ 0x1fc9, 0x0000,
+ /* 0x0397 0x0301 */
+ 0x1fcb, 0x0000,
+ /* 0x0399 0x0301 */
+ 0x1fdb, 0x0000,
+ /* 0x039f 0x0301 */
+ 0x1ff9, 0x0000,
+ /* 0x03a5 0x0301 */
+ 0x1feb, 0x0000,
+ /* 0x03a9 0x0301 */
+ 0x1ffb, 0x0000,
+ /* 0x03b1 0x0301 */
+ 0x1f71, 0x0000,
+ /* 0x03b5 0x0301 */
+ 0x1f73, 0x0000,
+ /* 0x03b7 0x0301 */
+ 0x1f75, 0x0000,
+ /* 0x03b9 0x0301 */
+ 0x1f77, 0x0000,
+ /* 0x03bf 0x0301 */
+ 0x1f79, 0x0000,
+ /* 0x03c5 0x0301 */
+ 0x1f7b, 0x0000,
+ /* 0x03c9 0x0301 */
+ 0x1f7d, 0x0000,
+ /* 0x0413 0x0301 */
+ 0x0403, 0x0000,
+ /* 0x041a 0x0301 */
+ 0x040c, 0x0000,
+ /* 0x0433 0x0301 */
+ 0x0453, 0x0000,
+ /* 0x043a 0x0301 */
+ 0x045c, 0x0000,
+ /* 0x1fbf 0x0301 */
+ 0x1fce, 0x0000,
+ /* 0x1ffe 0x0301 */
+ 0x1fde, 0x0000,
+ /* 0x0041 0x0302 */
+ 0x00c2, 0x0004, 0x0300, 0x0d6c, 0x0301, 0x0d6e, 0x0303, 0x0d70,
+ 0x0309, 0x0d72,
+ /* 0x0043 0x0302 */
+ 0x0108, 0x0000,
+ /* 0x0045 0x0302 */
+ 0x00ca, 0x0004, 0x0300, 0x0d74, 0x0301, 0x0d76, 0x0303, 0x0d78,
+ 0x0309, 0x0d7a,
+ /* 0x0047 0x0302 */
+ 0x011c, 0x0000,
+ /* 0x0048 0x0302 */
+ 0x0124, 0x0000,
+ /* 0x0049 0x0302 */
+ 0x00ce, 0x0000,
+ /* 0x004a 0x0302 */
+ 0x0134, 0x0000,
+ /* 0x004f 0x0302 */
+ 0x00d4, 0x0004, 0x0300, 0x0d7c, 0x0301, 0x0d7e, 0x0303, 0x0d80,
+ 0x0309, 0x0d82,
+ /* 0x0053 0x0302 */
+ 0x015c, 0x0000,
+ /* 0x0055 0x0302 */
+ 0x00db, 0x0000,
+ /* 0x0057 0x0302 */
+ 0x0174, 0x0000,
+ /* 0x0059 0x0302 */
+ 0x0176, 0x0000,
+ /* 0x005a 0x0302 */
+ 0x1e90, 0x0000,
+ /* 0x0061 0x0302 */
+ 0x00e2, 0x0004, 0x0300, 0x0d84, 0x0301, 0x0d86, 0x0303, 0x0d88,
+ 0x0309, 0x0d8a,
+ /* 0x0063 0x0302 */
+ 0x0109, 0x0000,
+ /* 0x0065 0x0302 */
+ 0x00ea, 0x0004, 0x0300, 0x0d8c, 0x0301, 0x0d8e, 0x0303, 0x0d90,
+ 0x0309, 0x0d92,
+ /* 0x0067 0x0302 */
+ 0x011d, 0x0000,
+ /* 0x0068 0x0302 */
+ 0x0125, 0x0000,
+ /* 0x0069 0x0302 */
+ 0x00ee, 0x0000,
+ /* 0x006a 0x0302 */
+ 0x0135, 0x0000,
+ /* 0x006f 0x0302 */
+ 0x00f4, 0x0004, 0x0300, 0x0d94, 0x0301, 0x0d96, 0x0303, 0x0d98,
+ 0x0309, 0x0d9a,
+ /* 0x0073 0x0302 */
+ 0x015d, 0x0000,
+ /* 0x0075 0x0302 */
+ 0x00fb, 0x0000,
+ /* 0x0077 0x0302 */
+ 0x0175, 0x0000,
+ /* 0x0079 0x0302 */
+ 0x0177, 0x0000,
+ /* 0x007a 0x0302 */
+ 0x1e91, 0x0000,
+ /* 0x0041 0x0303 */
+ 0x00c3, 0x0000,
+ /* 0x0045 0x0303 */
+ 0x1ebc, 0x0000,
+ /* 0x0049 0x0303 */
+ 0x0128, 0x0000,
+ /* 0x004e 0x0303 */
+ 0x00d1, 0x0000,
+ /* 0x004f 0x0303 */
+ 0x00d5, 0x0002, 0x0301, 0x0d9c, 0x0308, 0x0d9e,
+ /* 0x0055 0x0303 */
+ 0x0168, 0x0001, 0x0301, 0x0da0,
+ /* 0x0056 0x0303 */
+ 0x1e7c, 0x0000,
+ /* 0x0059 0x0303 */
+ 0x1ef8, 0x0000,
+ /* 0x0061 0x0303 */
+ 0x00e3, 0x0000,
+ /* 0x0065 0x0303 */
+ 0x1ebd, 0x0000,
+ /* 0x0069 0x0303 */
+ 0x0129, 0x0000,
+ /* 0x006e 0x0303 */
+ 0x00f1, 0x0000,
+ /* 0x006f 0x0303 */
+ 0x00f5, 0x0002, 0x0301, 0x0da2, 0x0308, 0x0da4,
+ /* 0x0075 0x0303 */
+ 0x0169, 0x0001, 0x0301, 0x0da6,
+ /* 0x0076 0x0303 */
+ 0x1e7d, 0x0000,
+ /* 0x0079 0x0303 */
+ 0x1ef9, 0x0000,
+ /* 0x0041 0x0304 */
+ 0x0100, 0x0000,
+ /* 0x0045 0x0304 */
+ 0x0112, 0x0002, 0x0300, 0x0da8, 0x0301, 0x0daa,
+ /* 0x0047 0x0304 */
+ 0x1e20, 0x0000,
+ /* 0x0049 0x0304 */
+ 0x012a, 0x0000,
+ /* 0x004f 0x0304 */
+ 0x014c, 0x0002, 0x0300, 0x0dac, 0x0301, 0x0dae,
+ /* 0x0055 0x0304 */
+ 0x016a, 0x0001, 0x0308, 0x0db0,
+ /* 0x0061 0x0304 */
+ 0x0101, 0x0000,
+ /* 0x0065 0x0304 */
+ 0x0113, 0x0002, 0x0300, 0x0db2, 0x0301, 0x0db4,
+ /* 0x0067 0x0304 */
+ 0x1e21, 0x0000,
+ /* 0x0069 0x0304 */
+ 0x012b, 0x0000,
+ /* 0x006f 0x0304 */
+ 0x014d, 0x0002, 0x0300, 0x0db6, 0x0301, 0x0db8,
+ /* 0x0075 0x0304 */
+ 0x016b, 0x0001, 0x0308, 0x0dba,
+ /* 0x00c6 0x0304 */
+ 0x01e2, 0x0000,
+ /* 0x00e6 0x0304 */
+ 0x01e3, 0x0000,
+ /* 0x0391 0x0304 */
+ 0x1fb9, 0x0000,
+ /* 0x0399 0x0304 */
+ 0x1fd9, 0x0000,
+ /* 0x03a5 0x0304 */
+ 0x1fe9, 0x0000,
+ /* 0x03b1 0x0304 */
+ 0x1fb1, 0x0000,
+ /* 0x03b9 0x0304 */
+ 0x1fd1, 0x0000,
+ /* 0x03c5 0x0304 */
+ 0x1fe1, 0x0000,
+ /* 0x0418 0x0304 */
+ 0x04e2, 0x0000,
+ /* 0x0423 0x0304 */
+ 0x04ee, 0x0000,
+ /* 0x0438 0x0304 */
+ 0x04e3, 0x0000,
+ /* 0x0443 0x0304 */
+ 0x04ef, 0x0000,
+ /* 0x0041 0x0306 */
+ 0x0102, 0x0004, 0x0300, 0x0dbc, 0x0301, 0x0dbe, 0x0303, 0x0dc0,
+ 0x0309, 0x0dc2,
+ /* 0x0045 0x0306 */
+ 0x0114, 0x0000,
+ /* 0x0047 0x0306 */
+ 0x011e, 0x0000,
+ /* 0x0049 0x0306 */
+ 0x012c, 0x0000,
+ /* 0x004f 0x0306 */
+ 0x014e, 0x0000,
+ /* 0x0055 0x0306 */
+ 0x016c, 0x0000,
+ /* 0x0061 0x0306 */
+ 0x0103, 0x0004, 0x0300, 0x0dc4, 0x0301, 0x0dc6, 0x0303, 0x0dc8,
+ 0x0309, 0x0dca,
+ /* 0x0065 0x0306 */
+ 0x0115, 0x0000,
+ /* 0x0067 0x0306 */
+ 0x011f, 0x0000,
+ /* 0x0069 0x0306 */
+ 0x012d, 0x0000,
+ /* 0x006f 0x0306 */
+ 0x014f, 0x0000,
+ /* 0x0075 0x0306 */
+ 0x016d, 0x0000,
+ /* 0x0391 0x0306 */
+ 0x1fb8, 0x0000,
+ /* 0x0399 0x0306 */
+ 0x1fd8, 0x0000,
+ /* 0x03a5 0x0306 */
+ 0x1fe8, 0x0000,
+ /* 0x03b1 0x0306 */
+ 0x1fb0, 0x0000,
+ /* 0x03b9 0x0306 */
+ 0x1fd0, 0x0000,
+ /* 0x03c5 0x0306 */
+ 0x1fe0, 0x0000,
+ /* 0x0410 0x0306 */
+ 0x04d0, 0x0000,
+ /* 0x0415 0x0306 */
+ 0x04d6, 0x0000,
+ /* 0x0416 0x0306 */
+ 0x04c1, 0x0000,
+ /* 0x0418 0x0306 */
+ 0x0419, 0x0000,
+ /* 0x0423 0x0306 */
+ 0x040e, 0x0000,
+ /* 0x0430 0x0306 */
+ 0x04d1, 0x0000,
+ /* 0x0435 0x0306 */
+ 0x04d7, 0x0000,
+ /* 0x0436 0x0306 */
+ 0x04c2, 0x0000,
+ /* 0x0438 0x0306 */
+ 0x0439, 0x0000,
+ /* 0x0443 0x0306 */
+ 0x045e, 0x0000,
+ /* 0x0041 0x0307 */
+ 0x0000, 0x0001, 0x0304, 0x0dcc,
+ /* 0x0042 0x0307 */
+ 0x1e02, 0x0000,
+ /* 0x0043 0x0307 */
+ 0x010a, 0x0000,
+ /* 0x0044 0x0307 */
+ 0x1e0a, 0x0000,
+ /* 0x0045 0x0307 */
+ 0x0116, 0x0000,
+ /* 0x0046 0x0307 */
+ 0x1e1e, 0x0000,
+ /* 0x0047 0x0307 */
+ 0x0120, 0x0000,
+ /* 0x0048 0x0307 */
+ 0x1e22, 0x0000,
+ /* 0x0049 0x0307 */
+ 0x0130, 0x0000,
+ /* 0x004d 0x0307 */
+ 0x1e40, 0x0000,
+ /* 0x004e 0x0307 */
+ 0x1e44, 0x0000,
+ /* 0x0050 0x0307 */
+ 0x1e56, 0x0000,
+ /* 0x0052 0x0307 */
+ 0x1e58, 0x0000,
+ /* 0x0053 0x0307 */
+ 0x1e60, 0x0000,
+ /* 0x0054 0x0307 */
+ 0x1e6a, 0x0000,
+ /* 0x0057 0x0307 */
+ 0x1e86, 0x0000,
+ /* 0x0058 0x0307 */
+ 0x1e8a, 0x0000,
+ /* 0x0059 0x0307 */
+ 0x1e8e, 0x0000,
+ /* 0x005a 0x0307 */
+ 0x017b, 0x0000,
+ /* 0x0061 0x0307 */
+ 0x0000, 0x0001, 0x0304, 0x0dce,
+ /* 0x0062 0x0307 */
+ 0x1e03, 0x0000,
+ /* 0x0063 0x0307 */
+ 0x010b, 0x0000,
+ /* 0x0064 0x0307 */
+ 0x1e0b, 0x0000,
+ /* 0x0065 0x0307 */
+ 0x0117, 0x0000,
+ /* 0x0066 0x0307 */
+ 0x1e1f, 0x0000,
+ /* 0x0067 0x0307 */
+ 0x0121, 0x0000,
+ /* 0x0068 0x0307 */
+ 0x1e23, 0x0000,
+ /* 0x006d 0x0307 */
+ 0x1e41, 0x0000,
+ /* 0x006e 0x0307 */
+ 0x1e45, 0x0000,
+ /* 0x0070 0x0307 */
+ 0x1e57, 0x0000,
+ /* 0x0072 0x0307 */
+ 0x1e59, 0x0000,
+ /* 0x0073 0x0307 */
+ 0x1e61, 0x0000,
+ /* 0x0074 0x0307 */
+ 0x1e6b, 0x0000,
+ /* 0x0077 0x0307 */
+ 0x1e87, 0x0000,
+ /* 0x0078 0x0307 */
+ 0x1e8b, 0x0000,
+ /* 0x0079 0x0307 */
+ 0x1e8f, 0x0000,
+ /* 0x007a 0x0307 */
+ 0x017c, 0x0000,
+ /* 0x017f 0x0307 */
+ 0x1e9b, 0x0000,
+ /* 0x0306 0x0307 */
+ 0x0310, 0x0000,
+ /* 0x0041 0x0308 */
+ 0x00c4, 0x0001, 0x0304, 0x0dd0,
+ /* 0x0045 0x0308 */
+ 0x00cb, 0x0000,
+ /* 0x0048 0x0308 */
+ 0x1e26, 0x0000,
+ /* 0x0049 0x0308 */
+ 0x00cf, 0x0001, 0x0301, 0x0dd2,
+ /* 0x004f 0x0308 */
+ 0x00d6, 0x0000,
+ /* 0x0055 0x0308 */
+ 0x00dc, 0x0004, 0x0300, 0x0dd4, 0x0301, 0x0dd6, 0x0304, 0x0dd8,
+ 0x030c, 0x0dda,
+ /* 0x0057 0x0308 */
+ 0x1e84, 0x0000,
+ /* 0x0058 0x0308 */
+ 0x1e8c, 0x0000,
+ /* 0x0059 0x0308 */
+ 0x0178, 0x0000,
+ /* 0x0061 0x0308 */
+ 0x00e4, 0x0001, 0x0304, 0x0ddc,
+ /* 0x0065 0x0308 */
+ 0x00eb, 0x0000,
+ /* 0x0068 0x0308 */
+ 0x1e27, 0x0000,
+ /* 0x0069 0x0308 */
+ 0x00ef, 0x0001, 0x0301, 0x0dde,
+ /* 0x006f 0x0308 */
+ 0x00f6, 0x0000,
+ /* 0x0074 0x0308 */
+ 0x1e97, 0x0000,
+ /* 0x0075 0x0308 */
+ 0x00fc, 0x0004, 0x0300, 0x0de0, 0x0301, 0x0de2, 0x0304, 0x0de4,
+ 0x030c, 0x0de6,
+ /* 0x0077 0x0308 */
+ 0x1e85, 0x0000,
+ /* 0x0078 0x0308 */
+ 0x1e8d, 0x0000,
+ /* 0x0079 0x0308 */
+ 0x00ff, 0x0000,
+ /* 0x018f 0x0308 */
+ 0x04da, 0x0000,
+ /* 0x019f 0x0308 */
+ 0x04ea, 0x0000,
+ /* 0x0259 0x0308 */
+ 0x04db, 0x0000,
+ /* 0x0275 0x0308 */
+ 0x04eb, 0x0000,
+ /* 0x0399 0x0308 */
+ 0x03aa, 0x0000,
+ /* 0x03a5 0x0308 */
+ 0x03ab, 0x0000,
+ /* 0x03b9 0x0308 */
+ 0x03ca, 0x0004, 0x0300, 0x0de8, 0x0301, 0x0dea, 0x030d, 0x0dec,
+ 0x0342, 0x0dee,
+ /* 0x03c5 0x0308 */
+ 0x03cb, 0x0004, 0x0300, 0x0df0, 0x0301, 0x0df2, 0x030d, 0x0df4,
+ 0x0342, 0x0df6,
+ /* 0x03d2 0x0308 */
+ 0x03d4, 0x0000,
+ /* 0x0406 0x0308 */
+ 0x0407, 0x0000,
+ /* 0x0410 0x0308 */
+ 0x04d2, 0x0000,
+ /* 0x0415 0x0308 */
+ 0x0401, 0x0000,
+ /* 0x0416 0x0308 */
+ 0x04dc, 0x0000,
+ /* 0x0417 0x0308 */
+ 0x04de, 0x0000,
+ /* 0x0418 0x0308 */
+ 0x04e4, 0x0000,
+ /* 0x041e 0x0308 */
+ 0x04e6, 0x0000,
+ /* 0x0423 0x0308 */
+ 0x04f0, 0x0000,
+ /* 0x0427 0x0308 */
+ 0x04f4, 0x0000,
+ /* 0x042b 0x0308 */
+ 0x04f8, 0x0000,
+ /* 0x0430 0x0308 */
+ 0x04d3, 0x0000,
+ /* 0x0435 0x0308 */
+ 0x0451, 0x0000,
+ /* 0x0436 0x0308 */
+ 0x04dd, 0x0000,
+ /* 0x0437 0x0308 */
+ 0x04df, 0x0000,
+ /* 0x0438 0x0308 */
+ 0x04e5, 0x0000,
+ /* 0x043e 0x0308 */
+ 0x04e7, 0x0000,
+ /* 0x0443 0x0308 */
+ 0x04f1, 0x0000,
+ /* 0x0447 0x0308 */
+ 0x04f5, 0x0000,
+ /* 0x044b 0x0308 */
+ 0x04f9, 0x0000,
+ /* 0x0456 0x0308 */
+ 0x0457, 0x0000,
+ /* 0x0041 0x0309 */
+ 0x1ea2, 0x0000,
+ /* 0x0045 0x0309 */
+ 0x1eba, 0x0000,
+ /* 0x0049 0x0309 */
+ 0x1ec8, 0x0000,
+ /* 0x004f 0x0309 */
+ 0x1ece, 0x0000,
+ /* 0x0055 0x0309 */
+ 0x1ee6, 0x0000,
+ /* 0x0059 0x0309 */
+ 0x1ef6, 0x0000,
+ /* 0x0061 0x0309 */
+ 0x1ea3, 0x0000,
+ /* 0x0065 0x0309 */
+ 0x1ebb, 0x0000,
+ /* 0x0069 0x0309 */
+ 0x1ec9, 0x0000,
+ /* 0x006f 0x0309 */
+ 0x1ecf, 0x0000,
+ /* 0x0075 0x0309 */
+ 0x1ee7, 0x0000,
+ /* 0x0079 0x0309 */
+ 0x1ef7, 0x0000,
+ /* 0x0041 0x030a */
+ 0x00c5, 0x0001, 0x0301, 0x0df8,
+ /* 0x0055 0x030a */
+ 0x016e, 0x0000,
+ /* 0x0061 0x030a */
+ 0x00e5, 0x0001, 0x0301, 0x0dfa,
+ /* 0x0075 0x030a */
+ 0x016f, 0x0000,
+ /* 0x0077 0x030a */
+ 0x1e98, 0x0000,
+ /* 0x0079 0x030a */
+ 0x1e99, 0x0000,
+ /* 0x004f 0x030b */
+ 0x0150, 0x0000,
+ /* 0x0055 0x030b */
+ 0x0170, 0x0000,
+ /* 0x006f 0x030b */
+ 0x0151, 0x0000,
+ /* 0x0075 0x030b */
+ 0x0171, 0x0000,
+ /* 0x0423 0x030b */
+ 0x04f2, 0x0000,
+ /* 0x0443 0x030b */
+ 0x04f3, 0x0000,
+ /* 0x0041 0x030c */
+ 0x01cd, 0x0000,
+ /* 0x0043 0x030c */
+ 0x010c, 0x0000,
+ /* 0x0044 0x030c */
+ 0x010e, 0x0000,
+ /* 0x0045 0x030c */
+ 0x011a, 0x0000,
+ /* 0x0047 0x030c */
+ 0x01e6, 0x0000,
+ /* 0x0049 0x030c */
+ 0x01cf, 0x0000,
+ /* 0x004b 0x030c */
+ 0x01e8, 0x0000,
+ /* 0x004c 0x030c */
+ 0x013d, 0x0000,
+ /* 0x004e 0x030c */
+ 0x0147, 0x0000,
+ /* 0x004f 0x030c */
+ 0x01d1, 0x0000,
+ /* 0x0052 0x030c */
+ 0x0158, 0x0000,
+ /* 0x0053 0x030c */
+ 0x0160, 0x0001, 0x0307, 0x0dfc,
+ /* 0x0054 0x030c */
+ 0x0164, 0x0000,
+ /* 0x0055 0x030c */
+ 0x01d3, 0x0000,
+ /* 0x005a 0x030c */
+ 0x017d, 0x0000,
+ /* 0x0061 0x030c */
+ 0x01ce, 0x0000,
+ /* 0x0063 0x030c */
+ 0x010d, 0x0000,
+ /* 0x0064 0x030c */
+ 0x010f, 0x0000,
+ /* 0x0065 0x030c */
+ 0x011b, 0x0000,
+ /* 0x0067 0x030c */
+ 0x01e7, 0x0000,
+ /* 0x0069 0x030c */
+ 0x01d0, 0x0000,
+ /* 0x006a 0x030c */
+ 0x01f0, 0x0000,
+ /* 0x006b 0x030c */
+ 0x01e9, 0x0000,
+ /* 0x006c 0x030c */
+ 0x013e, 0x0000,
+ /* 0x006e 0x030c */
+ 0x0148, 0x0000,
+ /* 0x006f 0x030c */
+ 0x01d2, 0x0000,
+ /* 0x0072 0x030c */
+ 0x0159, 0x0000,
+ /* 0x0073 0x030c */
+ 0x0161, 0x0001, 0x0307, 0x0dfe,
+ /* 0x0074 0x030c */
+ 0x0165, 0x0000,
+ /* 0x0075 0x030c */
+ 0x01d4, 0x0000,
+ /* 0x007a 0x030c */
+ 0x017e, 0x0000,
+ /* 0x01b7 0x030c */
+ 0x01ee, 0x0000,
+ /* 0x0292 0x030c */
+ 0x01ef, 0x0000,
+ /* 0x00a8 0x030d */
+ 0x0385, 0x0000,
+ /* 0x0308 0x030d */
+ 0x0344, 0x0000,
+ /* 0x0391 0x030d */
+ 0x0386, 0x0000,
+ /* 0x0395 0x030d */
+ 0x0388, 0x0000,
+ /* 0x0397 0x030d */
+ 0x0389, 0x0000,
+ /* 0x0399 0x030d */
+ 0x038a, 0x0000,
+ /* 0x039f 0x030d */
+ 0x038c, 0x0000,
+ /* 0x03a5 0x030d */
+ 0x038e, 0x0000,
+ /* 0x03a9 0x030d */
+ 0x038f, 0x0000,
+ /* 0x03b1 0x030d */
+ 0x03ac, 0x0000,
+ /* 0x03b5 0x030d */
+ 0x03ad, 0x0000,
+ /* 0x03b7 0x030d */
+ 0x03ae, 0x0000,
+ /* 0x03b9 0x030d */
+ 0x03af, 0x0000,
+ /* 0x03bf 0x030d */
+ 0x03cc, 0x0000,
+ /* 0x03c5 0x030d */
+ 0x03cd, 0x0000,
+ /* 0x03c9 0x030d */
+ 0x03ce, 0x0000,
+ /* 0x03d2 0x030d */
+ 0x03d3, 0x0000,
+ /* 0x0041 0x030f */
+ 0x0200, 0x0000,
+ /* 0x0045 0x030f */
+ 0x0204, 0x0000,
+ /* 0x0049 0x030f */
+ 0x0208, 0x0000,
+ /* 0x004f 0x030f */
+ 0x020c, 0x0000,
+ /* 0x0052 0x030f */
+ 0x0210, 0x0000,
+ /* 0x0055 0x030f */
+ 0x0214, 0x0000,
+ /* 0x0061 0x030f */
+ 0x0201, 0x0000,
+ /* 0x0065 0x030f */
+ 0x0205, 0x0000,
+ /* 0x0069 0x030f */
+ 0x0209, 0x0000,
+ /* 0x006f 0x030f */
+ 0x020d, 0x0000,
+ /* 0x0072 0x030f */
+ 0x0211, 0x0000,
+ /* 0x0075 0x030f */
+ 0x0215, 0x0000,
+ /* 0x0474 0x030f */
+ 0x0476, 0x0000,
+ /* 0x0475 0x030f */
+ 0x0477, 0x0000,
+ /* 0x0041 0x0311 */
+ 0x0202, 0x0000,
+ /* 0x0045 0x0311 */
+ 0x0206, 0x0000,
+ /* 0x0049 0x0311 */
+ 0x020a, 0x0000,
+ /* 0x004f 0x0311 */
+ 0x020e, 0x0000,
+ /* 0x0052 0x0311 */
+ 0x0212, 0x0000,
+ /* 0x0055 0x0311 */
+ 0x0216, 0x0000,
+ /* 0x0061 0x0311 */
+ 0x0203, 0x0000,
+ /* 0x0065 0x0311 */
+ 0x0207, 0x0000,
+ /* 0x0069 0x0311 */
+ 0x020b, 0x0000,
+ /* 0x006f 0x0311 */
+ 0x020f, 0x0000,
+ /* 0x0072 0x0311 */
+ 0x0213, 0x0000,
+ /* 0x0075 0x0311 */
+ 0x0217, 0x0000,
+ /* 0x0391 0x0313 */
+ 0x1f08, 0x0003, 0x0300, 0x0e00, 0x0301, 0x0e02, 0x0342, 0x0e04,
+ /* 0x0395 0x0313 */
+ 0x1f18, 0x0002, 0x0300, 0x0e06, 0x0301, 0x0e08,
+ /* 0x0397 0x0313 */
+ 0x1f28, 0x0003, 0x0300, 0x0e0a, 0x0301, 0x0e0c, 0x0342, 0x0e0e,
+ /* 0x0399 0x0313 */
+ 0x1f38, 0x0003, 0x0300, 0x0e10, 0x0301, 0x0e12, 0x0342, 0x0e14,
+ /* 0x039f 0x0313 */
+ 0x1f48, 0x0002, 0x0300, 0x0e16, 0x0301, 0x0e18,
+ /* 0x03a9 0x0313 */
+ 0x1f68, 0x0003, 0x0300, 0x0e1a, 0x0301, 0x0e1c, 0x0342, 0x0e1e,
+ /* 0x03b1 0x0313 */
+ 0x1f00, 0x0003, 0x0300, 0x0e20, 0x0301, 0x0e22, 0x0342, 0x0e24,
+ /* 0x03b5 0x0313 */
+ 0x1f10, 0x0002, 0x0300, 0x0e26, 0x0301, 0x0e28,
+ /* 0x03b7 0x0313 */
+ 0x1f20, 0x0003, 0x0300, 0x0e2a, 0x0301, 0x0e2c, 0x0342, 0x0e2e,
+ /* 0x03b9 0x0313 */
+ 0x1f30, 0x0003, 0x0300, 0x0e30, 0x0301, 0x0e32, 0x0342, 0x0e34,
+ /* 0x03bf 0x0313 */
+ 0x1f40, 0x0002, 0x0300, 0x0e36, 0x0301, 0x0e38,
+ /* 0x03c1 0x0313 */
+ 0x1fe4, 0x0000,
+ /* 0x03c5 0x0313 */
+ 0x1f50, 0x0003, 0x0300, 0x0e3a, 0x0301, 0x0e3c, 0x0342, 0x0e3e,
+ /* 0x03c9 0x0313 */
+ 0x1f60, 0x0003, 0x0300, 0x0e40, 0x0301, 0x0e42, 0x0342, 0x0e44,
+ /* 0x0391 0x0314 */
+ 0x1f09, 0x0003, 0x0300, 0x0e46, 0x0301, 0x0e48, 0x0342, 0x0e4a,
+ /* 0x0395 0x0314 */
+ 0x1f19, 0x0002, 0x0300, 0x0e4c, 0x0301, 0x0e4e,
+ /* 0x0397 0x0314 */
+ 0x1f29, 0x0003, 0x0300, 0x0e50, 0x0301, 0x0e52, 0x0342, 0x0e54,
+ /* 0x0399 0x0314 */
+ 0x1f39, 0x0003, 0x0300, 0x0e56, 0x0301, 0x0e58, 0x0342, 0x0e5a,
+ /* 0x039f 0x0314 */
+ 0x1f49, 0x0002, 0x0300, 0x0e5c, 0x0301, 0x0e5e,
+ /* 0x03a1 0x0314 */
+ 0x1fec, 0x0000,
+ /* 0x03a5 0x0314 */
+ 0x1f59, 0x0003, 0x0300, 0x0e60, 0x0301, 0x0e62, 0x0342, 0x0e64,
+ /* 0x03a9 0x0314 */
+ 0x1f69, 0x0003, 0x0300, 0x0e66, 0x0301, 0x0e68, 0x0342, 0x0e6a,
+ /* 0x03b1 0x0314 */
+ 0x1f01, 0x0003, 0x0300, 0x0e6c, 0x0301, 0x0e6e, 0x0342, 0x0e70,
+ /* 0x03b5 0x0314 */
+ 0x1f11, 0x0002, 0x0300, 0x0e72, 0x0301, 0x0e74,
+ /* 0x03b7 0x0314 */
+ 0x1f21, 0x0003, 0x0300, 0x0e76, 0x0301, 0x0e78, 0x0342, 0x0e7a,
+ /* 0x03b9 0x0314 */
+ 0x1f31, 0x0003, 0x0300, 0x0e7c, 0x0301, 0x0e7e, 0x0342, 0x0e80,
+ /* 0x03bf 0x0314 */
+ 0x1f41, 0x0002, 0x0300, 0x0e82, 0x0301, 0x0e84,
+ /* 0x03c1 0x0314 */
+ 0x1fe5, 0x0000,
+ /* 0x03c5 0x0314 */
+ 0x1f51, 0x0003, 0x0300, 0x0e86, 0x0301, 0x0e88, 0x0342, 0x0e8a,
+ /* 0x03c9 0x0314 */
+ 0x1f61, 0x0003, 0x0300, 0x0e8c, 0x0301, 0x0e8e, 0x0342, 0x0e90,
+ /* 0x004f 0x031b */
+ 0x01a0, 0x0005, 0x0300, 0x0e92, 0x0301, 0x0e94, 0x0303, 0x0e96,
+ 0x0309, 0x0e98, 0x0323, 0x0e9a,
+ /* 0x0055 0x031b */
+ 0x01af, 0x0005, 0x0300, 0x0e9c, 0x0301, 0x0e9e, 0x0303, 0x0ea0,
+ 0x0309, 0x0ea2, 0x0323, 0x0ea4,
+ /* 0x006f 0x031b */
+ 0x01a1, 0x0005, 0x0300, 0x0ea6, 0x0301, 0x0ea8, 0x0303, 0x0eaa,
+ 0x0309, 0x0eac, 0x0323, 0x0eae,
+ /* 0x0075 0x031b */
+ 0x01b0, 0x0005, 0x0300, 0x0eb0, 0x0301, 0x0eb2, 0x0303, 0x0eb4,
+ 0x0309, 0x0eb6, 0x0323, 0x0eb8,
+ /* 0x0041 0x0323 */
+ 0x1ea0, 0x0002, 0x0302, 0x0eba, 0x0306, 0x0ebc,
+ /* 0x0042 0x0323 */
+ 0x1e04, 0x0000,
+ /* 0x0044 0x0323 */
+ 0x1e0c, 0x0000,
+ /* 0x0045 0x0323 */
+ 0x1eb8, 0x0001, 0x0302, 0x0ebe,
+ /* 0x0048 0x0323 */
+ 0x1e24, 0x0000,
+ /* 0x0049 0x0323 */
+ 0x1eca, 0x0000,
+ /* 0x004b 0x0323 */
+ 0x1e32, 0x0000,
+ /* 0x004c 0x0323 */
+ 0x1e36, 0x0001, 0x0304, 0x0ec0,
+ /* 0x004d 0x0323 */
+ 0x1e42, 0x0000,
+ /* 0x004e 0x0323 */
+ 0x1e46, 0x0000,
+ /* 0x004f 0x0323 */
+ 0x1ecc, 0x0001, 0x0302, 0x0ec2,
+ /* 0x0052 0x0323 */
+ 0x1e5a, 0x0001, 0x0304, 0x0ec4,
+ /* 0x0053 0x0323 */
+ 0x1e62, 0x0001, 0x0307, 0x0ec6,
+ /* 0x0054 0x0323 */
+ 0x1e6c, 0x0000,
+ /* 0x0055 0x0323 */
+ 0x1ee4, 0x0000,
+ /* 0x0056 0x0323 */
+ 0x1e7e, 0x0000,
+ /* 0x0057 0x0323 */
+ 0x1e88, 0x0000,
+ /* 0x0059 0x0323 */
+ 0x1ef4, 0x0000,
+ /* 0x005a 0x0323 */
+ 0x1e92, 0x0000,
+ /* 0x0061 0x0323 */
+ 0x1ea1, 0x0002, 0x0302, 0x0ec8, 0x0306, 0x0eca,
+ /* 0x0062 0x0323 */
+ 0x1e05, 0x0000,
+ /* 0x0064 0x0323 */
+ 0x1e0d, 0x0000,
+ /* 0x0065 0x0323 */
+ 0x1eb9, 0x0001, 0x0302, 0x0ecc,
+ /* 0x0068 0x0323 */
+ 0x1e25, 0x0000,
+ /* 0x0069 0x0323 */
+ 0x1ecb, 0x0000,
+ /* 0x006b 0x0323 */
+ 0x1e33, 0x0000,
+ /* 0x006c 0x0323 */
+ 0x1e37, 0x0001, 0x0304, 0x0ece,
+ /* 0x006d 0x0323 */
+ 0x1e43, 0x0000,
+ /* 0x006e 0x0323 */
+ 0x1e47, 0x0000,
+ /* 0x006f 0x0323 */
+ 0x1ecd, 0x0001, 0x0302, 0x0ed0,
+ /* 0x0072 0x0323 */
+ 0x1e5b, 0x0001, 0x0304, 0x0ed2,
+ /* 0x0073 0x0323 */
+ 0x1e63, 0x0001, 0x0307, 0x0ed4,
+ /* 0x0074 0x0323 */
+ 0x1e6d, 0x0000,
+ /* 0x0075 0x0323 */
+ 0x1ee5, 0x0000,
+ /* 0x0076 0x0323 */
+ 0x1e7f, 0x0000,
+ /* 0x0077 0x0323 */
+ 0x1e89, 0x0000,
+ /* 0x0079 0x0323 */
+ 0x1ef5, 0x0000,
+ /* 0x007a 0x0323 */
+ 0x1e93, 0x0000,
+ /* 0x0055 0x0324 */
+ 0x1e72, 0x0000,
+ /* 0x0075 0x0324 */
+ 0x1e73, 0x0000,
+ /* 0x0041 0x0325 */
+ 0x1e00, 0x0000,
+ /* 0x0061 0x0325 */
+ 0x1e01, 0x0000,
+ /* 0x0043 0x0327 */
+ 0x00c7, 0x0001, 0x0301, 0x0ed6,
+ /* 0x0044 0x0327 */
+ 0x1e10, 0x0000,
+ /* 0x0045 0x0327 */
+ 0x0000, 0x0001, 0x0306, 0x0ed8,
+ /* 0x0047 0x0327 */
+ 0x0122, 0x0000,
+ /* 0x0048 0x0327 */
+ 0x1e28, 0x0000,
+ /* 0x004b 0x0327 */
+ 0x0136, 0x0000,
+ /* 0x004c 0x0327 */
+ 0x013b, 0x0000,
+ /* 0x004e 0x0327 */
+ 0x0145, 0x0000,
+ /* 0x0052 0x0327 */
+ 0x0156, 0x0000,
+ /* 0x0053 0x0327 */
+ 0x015e, 0x0000,
+ /* 0x0054 0x0327 */
+ 0x0162, 0x0000,
+ /* 0x0063 0x0327 */
+ 0x00e7, 0x0001, 0x0301, 0x0eda,
+ /* 0x0064 0x0327 */
+ 0x1e11, 0x0000,
+ /* 0x0065 0x0327 */
+ 0x0000, 0x0001, 0x0306, 0x0edc,
+ /* 0x0067 0x0327 */
+ 0x0123, 0x0000,
+ /* 0x0068 0x0327 */
+ 0x1e29, 0x0000,
+ /* 0x006b 0x0327 */
+ 0x0137, 0x0000,
+ /* 0x006c 0x0327 */
+ 0x013c, 0x0000,
+ /* 0x006e 0x0327 */
+ 0x0146, 0x0000,
+ /* 0x0072 0x0327 */
+ 0x0157, 0x0000,
+ /* 0x0073 0x0327 */
+ 0x015f, 0x0000,
+ /* 0x0074 0x0327 */
+ 0x0163, 0x0000,
+ /* 0x0041 0x0328 */
+ 0x0104, 0x0000,
+ /* 0x0045 0x0328 */
+ 0x0118, 0x0000,
+ /* 0x0049 0x0328 */
+ 0x012e, 0x0000,
+ /* 0x004f 0x0328 */
+ 0x01ea, 0x0001, 0x0304, 0x0ede,
+ /* 0x0055 0x0328 */
+ 0x0172, 0x0000,
+ /* 0x0061 0x0328 */
+ 0x0105, 0x0000,
+ /* 0x0065 0x0328 */
+ 0x0119, 0x0000,
+ /* 0x0069 0x0328 */
+ 0x012f, 0x0000,
+ /* 0x006f 0x0328 */
+ 0x01eb, 0x0001, 0x0304, 0x0ee0,
+ /* 0x0075 0x0328 */
+ 0x0173, 0x0000,
+ /* 0x0044 0x032d */
+ 0x1e12, 0x0000,
+ /* 0x0045 0x032d */
+ 0x1e18, 0x0000,
+ /* 0x004c 0x032d */
+ 0x1e3c, 0x0000,
+ /* 0x004e 0x032d */
+ 0x1e4a, 0x0000,
+ /* 0x0054 0x032d */
+ 0x1e70, 0x0000,
+ /* 0x0055 0x032d */
+ 0x1e76, 0x0000,
+ /* 0x0064 0x032d */
+ 0x1e13, 0x0000,
+ /* 0x0065 0x032d */
+ 0x1e19, 0x0000,
+ /* 0x006c 0x032d */
+ 0x1e3d, 0x0000,
+ /* 0x006e 0x032d */
+ 0x1e4b, 0x0000,
+ /* 0x0074 0x032d */
+ 0x1e71, 0x0000,
+ /* 0x0075 0x032d */
+ 0x1e77, 0x0000,
+ /* 0x0048 0x032e */
+ 0x1e2a, 0x0000,
+ /* 0x0068 0x032e */
+ 0x1e2b, 0x0000,
+ /* 0x0045 0x0330 */
+ 0x1e1a, 0x0000,
+ /* 0x0049 0x0330 */
+ 0x1e2c, 0x0000,
+ /* 0x0055 0x0330 */
+ 0x1e74, 0x0000,
+ /* 0x0065 0x0330 */
+ 0x1e1b, 0x0000,
+ /* 0x0069 0x0330 */
+ 0x1e2d, 0x0000,
+ /* 0x0075 0x0330 */
+ 0x1e75, 0x0000,
+ /* 0x0042 0x0331 */
+ 0x1e06, 0x0000,
+ /* 0x0044 0x0331 */
+ 0x1e0e, 0x0000,
+ /* 0x004b 0x0331 */
+ 0x1e34, 0x0000,
+ /* 0x004c 0x0331 */
+ 0x1e3a, 0x0000,
+ /* 0x004e 0x0331 */
+ 0x1e48, 0x0000,
+ /* 0x0052 0x0331 */
+ 0x1e5e, 0x0000,
+ /* 0x0054 0x0331 */
+ 0x1e6e, 0x0000,
+ /* 0x005a 0x0331 */
+ 0x1e94, 0x0000,
+ /* 0x0062 0x0331 */
+ 0x1e07, 0x0000,
+ /* 0x0064 0x0331 */
+ 0x1e0f, 0x0000,
+ /* 0x0068 0x0331 */
+ 0x1e96, 0x0000,
+ /* 0x006b 0x0331 */
+ 0x1e35, 0x0000,
+ /* 0x006c 0x0331 */
+ 0x1e3b, 0x0000,
+ /* 0x006e 0x0331 */
+ 0x1e49, 0x0000,
+ /* 0x0072 0x0331 */
+ 0x1e5f, 0x0000,
+ /* 0x0074 0x0331 */
+ 0x1e6f, 0x0000,
+ /* 0x007a 0x0331 */
+ 0x1e95, 0x0000,
+ /* 0x00a8 0x0342 */
+ 0x1fc1, 0x0000,
+ /* 0x03b1 0x0342 */
+ 0x1fb6, 0x0000,
+ /* 0x03b7 0x0342 */
+ 0x1fc6, 0x0000,
+ /* 0x03b9 0x0342 */
+ 0x1fd6, 0x0000,
+ /* 0x03c5 0x0342 */
+ 0x1fe6, 0x0000,
+ /* 0x03c9 0x0342 */
+ 0x1ff6, 0x0000,
+ /* 0x1fbf 0x0342 */
+ 0x1fcf, 0x0000,
+ /* 0x1ffe 0x0342 */
+ 0x1fdf, 0x0000,
+ /* 0x0391 0x0345 */
+ 0x1fbc, 0x0002, 0x0313, 0x0ee2, 0x0314, 0x0eea,
+ /* 0x0397 0x0345 */
+ 0x1fcc, 0x0002, 0x0313, 0x0ef2, 0x0314, 0x0efa,
+ /* 0x03a9 0x0345 */
+ 0x1ffc, 0x0002, 0x0313, 0x0f02, 0x0314, 0x0f0a,
+ /* 0x03b1 0x0345 */
+ 0x1fb3, 0x0005, 0x0300, 0x0f12, 0x0301, 0x0f14, 0x0313, 0x0f16,
+ 0x0314, 0x0f1e, 0x0342, 0x0f26,
+ /* 0x03b7 0x0345 */
+ 0x1fc3, 0x0005, 0x0300, 0x0f28, 0x0301, 0x0f2a, 0x0313, 0x0f2c,
+ 0x0314, 0x0f34, 0x0342, 0x0f3c,
+ /* 0x03bf 0x0345 */
+ 0x0000, 0x0001, 0x0301, 0x0f3e,
+ /* 0x03c9 0x0345 */
+ 0x1ff3, 0x0004, 0x0300, 0x0f40, 0x0313, 0x0f42, 0x0314, 0x0f4a,
+ 0x0342, 0x0f52,
+ /* 0x05d0 0x05b7 */
+ 0xfb2e, 0x0000,
+ /* 0x05f2 0x05b7 */
+ 0xfb1f, 0x0000,
+ /* 0x05d0 0x05b8 */
+ 0xfb2f, 0x0000,
+ /* 0x05d5 0x05b9 */
+ 0xfb4b, 0x0000,
+ /* 0x05d0 0x05bc */
+ 0xfb30, 0x0000,
+ /* 0x05d1 0x05bc */
+ 0xfb31, 0x0000,
+ /* 0x05d2 0x05bc */
+ 0xfb32, 0x0000,
+ /* 0x05d3 0x05bc */
+ 0xfb33, 0x0000,
+ /* 0x05d4 0x05bc */
+ 0xfb34, 0x0000,
+ /* 0x05d5 0x05bc */
+ 0xfb35, 0x0000,
+ /* 0x05d6 0x05bc */
+ 0xfb36, 0x0000,
+ /* 0x05d8 0x05bc */
+ 0xfb38, 0x0000,
+ /* 0x05d9 0x05bc */
+ 0xfb39, 0x0000,
+ /* 0x05da 0x05bc */
+ 0xfb3a, 0x0000,
+ /* 0x05db 0x05bc */
+ 0xfb3b, 0x0000,
+ /* 0x05dc 0x05bc */
+ 0xfb3c, 0x0000,
+ /* 0x05de 0x05bc */
+ 0xfb3e, 0x0000,
+ /* 0x05e0 0x05bc */
+ 0xfb40, 0x0000,
+ /* 0x05e1 0x05bc */
+ 0xfb41, 0x0000,
+ /* 0x05e3 0x05bc */
+ 0xfb43, 0x0000,
+ /* 0x05e4 0x05bc */
+ 0xfb44, 0x0000,
+ /* 0x05e6 0x05bc */
+ 0xfb46, 0x0000,
+ /* 0x05e7 0x05bc */
+ 0xfb47, 0x0000,
+ /* 0x05e8 0x05bc */
+ 0xfb48, 0x0000,
+ /* 0x05e9 0x05bc */
+ 0xfb49, 0x0002, 0x05c1, 0x0f54, 0x05c2, 0x0f56,
+ /* 0x05ea 0x05bc */
+ 0xfb4a, 0x0000,
+ /* 0x05d1 0x05bf */
+ 0xfb4c, 0x0000,
+ /* 0x05db 0x05bf */
+ 0xfb4d, 0x0000,
+ /* 0x05e4 0x05bf */
+ 0xfb4e, 0x0000,
+ /* 0x05e9 0x05c1 */
+ 0xfb2a, 0x0000,
+ /* 0x05e9 0x05c2 */
+ 0xfb2b, 0x0000,
+ /* 0x0915 0x093c */
+ 0x0958, 0x0000,
+ /* 0x0916 0x093c */
+ 0x0959, 0x0000,
+ /* 0x0917 0x093c */
+ 0x095a, 0x0000,
+ /* 0x091c 0x093c */
+ 0x095b, 0x0000,
+ /* 0x0921 0x093c */
+ 0x095c, 0x0000,
+ /* 0x0922 0x093c */
+ 0x095d, 0x0000,
+ /* 0x0928 0x093c */
+ 0x0929, 0x0000,
+ /* 0x092b 0x093c */
+ 0x095e, 0x0000,
+ /* 0x092f 0x093c */
+ 0x095f, 0x0000,
+ /* 0x0930 0x093c */
+ 0x0931, 0x0000,
+ /* 0x0933 0x093c */
+ 0x0934, 0x0000,
+ /* 0x09a1 0x09bc */
+ 0x09dc, 0x0000,
+ /* 0x09a2 0x09bc */
+ 0x09dd, 0x0000,
+ /* 0x09ac 0x09bc */
+ 0x09b0, 0x0000,
+ /* 0x09af 0x09bc */
+ 0x09df, 0x0000,
+ /* 0x09c7 0x09be */
+ 0x09cb, 0x0000,
+ /* 0x09c7 0x09d7 */
+ 0x09cc, 0x0000,
+ /* 0x0a16 0x0a3c */
+ 0x0a59, 0x0000,
+ /* 0x0a17 0x0a3c */
+ 0x0a5a, 0x0000,
+ /* 0x0a1c 0x0a3c */
+ 0x0a5b, 0x0000,
+ /* 0x0a21 0x0a3c */
+ 0x0a5c, 0x0000,
+ /* 0x0a2b 0x0a3c */
+ 0x0a5e, 0x0000,
+ /* 0x0b21 0x0b3c */
+ 0x0b5c, 0x0000,
+ /* 0x0b22 0x0b3c */
+ 0x0b5d, 0x0000,
+ /* 0x0b2f 0x0b3c */
+ 0x0b5f, 0x0000,
+ /* 0x0b47 0x0b3e */
+ 0x0b4b, 0x0000,
+ /* 0x0b47 0x0b56 */
+ 0x0b48, 0x0000,
+ /* 0x0b47 0x0b57 */
+ 0x0b4c, 0x0000,
+ /* 0x0bc6 0x0bbe */
+ 0x0bca, 0x0000,
+ /* 0x0bc7 0x0bbe */
+ 0x0bcb, 0x0000,
+ /* 0x0b92 0x0bd7 */
+ 0x0b94, 0x0000,
+ /* 0x0bc6 0x0bd7 */
+ 0x0bcc, 0x0000,
+ /* 0x0c46 0x0c56 */
+ 0x0c48, 0x0000,
+ /* 0x0cc6 0x0cc2 */
+ 0x0cca, 0x0001, 0x0cd5, 0x0f58,
+ /* 0x0cbf 0x0cd5 */
+ 0x0cc0, 0x0000,
+ /* 0x0cc6 0x0cd5 */
+ 0x0cc7, 0x0000,
+ /* 0x0cc6 0x0cd6 */
+ 0x0cc8, 0x0000,
+ /* 0x0d46 0x0d3e */
+ 0x0d4a, 0x0000,
+ /* 0x0d47 0x0d3e */
+ 0x0d4b, 0x0000,
+ /* 0x0d46 0x0d57 */
+ 0x0d4c, 0x0000,
+ /* 0x0e4d 0x0e32 */
+ 0x0e33, 0x0000,
+ /* 0x0ecd 0x0eb2 */
+ 0x0eb3, 0x0000,
+ /* 0x0f72 0x0f71 */
+ 0x0f73, 0x0000,
+ /* 0x0f74 0x0f71 */
+ 0x0f75, 0x0000,
+ /* 0x0f80 0x0f71 */
+ 0x0f81, 0x0000,
+ /* 0x0fb2 0x0f80 */
+ 0x0f76, 0x0001, 0x0f71, 0x0f5a,
+ /* 0x0fb3 0x0f80 */
+ 0x0f78, 0x0001, 0x0f71, 0x0f5c,
+ /* 0x0f40 0x0fb5 */
+ 0x0f69, 0x0000,
+ /* 0x0f90 0x0fb5 */
+ 0x0fb9, 0x0000,
+ /* 0x0f42 0x0fb7 */
+ 0x0f43, 0x0000,
+ /* 0x0f4c 0x0fb7 */
+ 0x0f4d, 0x0000,
+ /* 0x0f51 0x0fb7 */
+ 0x0f52, 0x0000,
+ /* 0x0f56 0x0fb7 */
+ 0x0f57, 0x0000,
+ /* 0x0f5b 0x0fb7 */
+ 0x0f5c, 0x0000,
+ /* 0x0f92 0x0fb7 */
+ 0x0f93, 0x0000,
+ /* 0x0f9c 0x0fb7 */
+ 0x0f9d, 0x0000,
+ /* 0x0fa1 0x0fb7 */
+ 0x0fa2, 0x0000,
+ /* 0x0fa6 0x0fb7 */
+ 0x0fa7, 0x0000,
+ /* 0x0fab 0x0fb7 */
+ 0x0fac, 0x0000,
+ /* 0x3046 0x3099 */
+ 0x3094, 0x0000,
+ /* 0x304b 0x3099 */
+ 0x304c, 0x0000,
+ /* 0x304d 0x3099 */
+ 0x304e, 0x0000,
+ /* 0x304f 0x3099 */
+ 0x3050, 0x0000,
+ /* 0x3051 0x3099 */
+ 0x3052, 0x0000,
+ /* 0x3053 0x3099 */
+ 0x3054, 0x0000,
+ /* 0x3055 0x3099 */
+ 0x3056, 0x0000,
+ /* 0x3057 0x3099 */
+ 0x3058, 0x0000,
+ /* 0x3059 0x3099 */
+ 0x305a, 0x0000,
+ /* 0x305b 0x3099 */
+ 0x305c, 0x0000,
+ /* 0x305d 0x3099 */
+ 0x305e, 0x0000,
+ /* 0x305f 0x3099 */
+ 0x3060, 0x0000,
+ /* 0x3061 0x3099 */
+ 0x3062, 0x0000,
+ /* 0x3064 0x3099 */
+ 0x3065, 0x0000,
+ /* 0x3066 0x3099 */
+ 0x3067, 0x0000,
+ /* 0x3068 0x3099 */
+ 0x3069, 0x0000,
+ /* 0x306f 0x3099 */
+ 0x3070, 0x0000,
+ /* 0x3072 0x3099 */
+ 0x3073, 0x0000,
+ /* 0x3075 0x3099 */
+ 0x3076, 0x0000,
+ /* 0x3078 0x3099 */
+ 0x3079, 0x0000,
+ /* 0x307b 0x3099 */
+ 0x307c, 0x0000,
+ /* 0x309d 0x3099 */
+ 0x309e, 0x0000,
+ /* 0x30a6 0x3099 */
+ 0x30f4, 0x0000,
+ /* 0x30ab 0x3099 */
+ 0x30ac, 0x0000,
+ /* 0x30ad 0x3099 */
+ 0x30ae, 0x0000,
+ /* 0x30af 0x3099 */
+ 0x30b0, 0x0000,
+ /* 0x30b1 0x3099 */
+ 0x30b2, 0x0000,
+ /* 0x30b3 0x3099 */
+ 0x30b4, 0x0000,
+ /* 0x30b5 0x3099 */
+ 0x30b6, 0x0000,
+ /* 0x30b7 0x3099 */
+ 0x30b8, 0x0000,
+ /* 0x30b9 0x3099 */
+ 0x30ba, 0x0000,
+ /* 0x30bb 0x3099 */
+ 0x30bc, 0x0000,
+ /* 0x30bd 0x3099 */
+ 0x30be, 0x0000,
+ /* 0x30bf 0x3099 */
+ 0x30c0, 0x0000,
+ /* 0x30c1 0x3099 */
+ 0x30c2, 0x0000,
+ /* 0x30c4 0x3099 */
+ 0x30c5, 0x0000,
+ /* 0x30c6 0x3099 */
+ 0x30c7, 0x0000,
+ /* 0x30c8 0x3099 */
+ 0x30c9, 0x0000,
+ /* 0x30cf 0x3099 */
+ 0x30d0, 0x0000,
+ /* 0x30d2 0x3099 */
+ 0x30d3, 0x0000,
+ /* 0x30d5 0x3099 */
+ 0x30d6, 0x0000,
+ /* 0x30d8 0x3099 */
+ 0x30d9, 0x0000,
+ /* 0x30db 0x3099 */
+ 0x30dc, 0x0000,
+ /* 0x30ef 0x3099 */
+ 0x30f7, 0x0000,
+ /* 0x30f0 0x3099 */
+ 0x30f8, 0x0000,
+ /* 0x30f1 0x3099 */
+ 0x30f9, 0x0000,
+ /* 0x30f2 0x3099 */
+ 0x30fa, 0x0000,
+ /* 0x30fd 0x3099 */
+ 0x30fe, 0x0000,
+ /* 0x306f 0x309a */
+ 0x3071, 0x0000,
+ /* 0x3072 0x309a */
+ 0x3074, 0x0000,
+ /* 0x3075 0x309a */
+ 0x3077, 0x0000,
+ /* 0x3078 0x309a */
+ 0x307a, 0x0000,
+ /* 0x307b 0x309a */
+ 0x307d, 0x0000,
+ /* 0x30cf 0x309a */
+ 0x30d1, 0x0000,
+ /* 0x30d2 0x309a */
+ 0x30d4, 0x0000,
+ /* 0x30d5 0x309a */
+ 0x30d7, 0x0000,
+ /* 0x30d8 0x309a */
+ 0x30da, 0x0000,
+ /* 0x30db 0x309a */
+ 0x30dd, 0x0000,
+ /* 0x0307 0x0053 0x0301 */
+ 0x1e64, 0x0000,
+ /* 0x0307 0x0073 0x0301 */
+ 0x1e65, 0x0000,
+ /* 0x0300 0x0041 0x0302 */
+ 0x1ea6, 0x0000,
+ /* 0x0301 0x0041 0x0302 */
+ 0x1ea4, 0x0000,
+ /* 0x0303 0x0041 0x0302 */
+ 0x1eaa, 0x0000,
+ /* 0x0309 0x0041 0x0302 */
+ 0x1ea8, 0x0000,
+ /* 0x0300 0x0045 0x0302 */
+ 0x1ec0, 0x0000,
+ /* 0x0301 0x0045 0x0302 */
+ 0x1ebe, 0x0000,
+ /* 0x0303 0x0045 0x0302 */
+ 0x1ec4, 0x0000,
+ /* 0x0309 0x0045 0x0302 */
+ 0x1ec2, 0x0000,
+ /* 0x0300 0x004f 0x0302 */
+ 0x1ed2, 0x0000,
+ /* 0x0301 0x004f 0x0302 */
+ 0x1ed0, 0x0000,
+ /* 0x0303 0x004f 0x0302 */
+ 0x1ed6, 0x0000,
+ /* 0x0309 0x004f 0x0302 */
+ 0x1ed4, 0x0000,
+ /* 0x0300 0x0061 0x0302 */
+ 0x1ea7, 0x0000,
+ /* 0x0301 0x0061 0x0302 */
+ 0x1ea5, 0x0000,
+ /* 0x0303 0x0061 0x0302 */
+ 0x1eab, 0x0000,
+ /* 0x0309 0x0061 0x0302 */
+ 0x1ea9, 0x0000,
+ /* 0x0300 0x0065 0x0302 */
+ 0x1ec1, 0x0000,
+ /* 0x0301 0x0065 0x0302 */
+ 0x1ebf, 0x0000,
+ /* 0x0303 0x0065 0x0302 */
+ 0x1ec5, 0x0000,
+ /* 0x0309 0x0065 0x0302 */
+ 0x1ec3, 0x0000,
+ /* 0x0300 0x006f 0x0302 */
+ 0x1ed3, 0x0000,
+ /* 0x0301 0x006f 0x0302 */
+ 0x1ed1, 0x0000,
+ /* 0x0303 0x006f 0x0302 */
+ 0x1ed7, 0x0000,
+ /* 0x0309 0x006f 0x0302 */
+ 0x1ed5, 0x0000,
+ /* 0x0301 0x004f 0x0303 */
+ 0x1e4c, 0x0000,
+ /* 0x0308 0x004f 0x0303 */
+ 0x1e4e, 0x0000,
+ /* 0x0301 0x0055 0x0303 */
+ 0x1e78, 0x0000,
+ /* 0x0301 0x006f 0x0303 */
+ 0x1e4d, 0x0000,
+ /* 0x0308 0x006f 0x0303 */
+ 0x1e4f, 0x0000,
+ /* 0x0301 0x0075 0x0303 */
+ 0x1e79, 0x0000,
+ /* 0x0300 0x0045 0x0304 */
+ 0x1e14, 0x0000,
+ /* 0x0301 0x0045 0x0304 */
+ 0x1e16, 0x0000,
+ /* 0x0300 0x004f 0x0304 */
+ 0x1e50, 0x0000,
+ /* 0x0301 0x004f 0x0304 */
+ 0x1e52, 0x0000,
+ /* 0x0308 0x0055 0x0304 */
+ 0x1e7a, 0x0000,
+ /* 0x0300 0x0065 0x0304 */
+ 0x1e15, 0x0000,
+ /* 0x0301 0x0065 0x0304 */
+ 0x1e17, 0x0000,
+ /* 0x0300 0x006f 0x0304 */
+ 0x1e51, 0x0000,
+ /* 0x0301 0x006f 0x0304 */
+ 0x1e53, 0x0000,
+ /* 0x0308 0x0075 0x0304 */
+ 0x1e7b, 0x0000,
+ /* 0x0300 0x0041 0x0306 */
+ 0x1eb0, 0x0000,
+ /* 0x0301 0x0041 0x0306 */
+ 0x1eae, 0x0000,
+ /* 0x0303 0x0041 0x0306 */
+ 0x1eb4, 0x0000,
+ /* 0x0309 0x0041 0x0306 */
+ 0x1eb2, 0x0000,
+ /* 0x0300 0x0061 0x0306 */
+ 0x1eb1, 0x0000,
+ /* 0x0301 0x0061 0x0306 */
+ 0x1eaf, 0x0000,
+ /* 0x0303 0x0061 0x0306 */
+ 0x1eb5, 0x0000,
+ /* 0x0309 0x0061 0x0306 */
+ 0x1eb3, 0x0000,
+ /* 0x0304 0x0041 0x0307 */
+ 0x01e0, 0x0000,
+ /* 0x0304 0x0061 0x0307 */
+ 0x01e1, 0x0000,
+ /* 0x0304 0x0041 0x0308 */
+ 0x01de, 0x0000,
+ /* 0x0301 0x0049 0x0308 */
+ 0x1e2e, 0x0000,
+ /* 0x0300 0x0055 0x0308 */
+ 0x01db, 0x0000,
+ /* 0x0301 0x0055 0x0308 */
+ 0x01d7, 0x0000,
+ /* 0x0304 0x0055 0x0308 */
+ 0x01d5, 0x0000,
+ /* 0x030c 0x0055 0x0308 */
+ 0x01d9, 0x0000,
+ /* 0x0304 0x0061 0x0308 */
+ 0x01df, 0x0000,
+ /* 0x0301 0x0069 0x0308 */
+ 0x1e2f, 0x0000,
+ /* 0x0300 0x0075 0x0308 */
+ 0x01dc, 0x0000,
+ /* 0x0301 0x0075 0x0308 */
+ 0x01d8, 0x0000,
+ /* 0x0304 0x0075 0x0308 */
+ 0x01d6, 0x0000,
+ /* 0x030c 0x0075 0x0308 */
+ 0x01da, 0x0000,
+ /* 0x0300 0x03b9 0x0308 */
+ 0x1fd2, 0x0000,
+ /* 0x0301 0x03b9 0x0308 */
+ 0x1fd3, 0x0000,
+ /* 0x030d 0x03b9 0x0308 */
+ 0x0390, 0x0000,
+ /* 0x0342 0x03b9 0x0308 */
+ 0x1fd7, 0x0000,
+ /* 0x0300 0x03c5 0x0308 */
+ 0x1fe2, 0x0000,
+ /* 0x0301 0x03c5 0x0308 */
+ 0x1fe3, 0x0000,
+ /* 0x030d 0x03c5 0x0308 */
+ 0x03b0, 0x0000,
+ /* 0x0342 0x03c5 0x0308 */
+ 0x1fe7, 0x0000,
+ /* 0x0301 0x0041 0x030a */
+ 0x01fa, 0x0000,
+ /* 0x0301 0x0061 0x030a */
+ 0x01fb, 0x0000,
+ /* 0x0307 0x0053 0x030c */
+ 0x1e66, 0x0000,
+ /* 0x0307 0x0073 0x030c */
+ 0x1e67, 0x0000,
+ /* 0x0300 0x0391 0x0313 */
+ 0x1f0a, 0x0000,
+ /* 0x0301 0x0391 0x0313 */
+ 0x1f0c, 0x0000,
+ /* 0x0342 0x0391 0x0313 */
+ 0x1f0e, 0x0000,
+ /* 0x0300 0x0395 0x0313 */
+ 0x1f1a, 0x0000,
+ /* 0x0301 0x0395 0x0313 */
+ 0x1f1c, 0x0000,
+ /* 0x0300 0x0397 0x0313 */
+ 0x1f2a, 0x0000,
+ /* 0x0301 0x0397 0x0313 */
+ 0x1f2c, 0x0000,
+ /* 0x0342 0x0397 0x0313 */
+ 0x1f2e, 0x0000,
+ /* 0x0300 0x0399 0x0313 */
+ 0x1f3a, 0x0000,
+ /* 0x0301 0x0399 0x0313 */
+ 0x1f3c, 0x0000,
+ /* 0x0342 0x0399 0x0313 */
+ 0x1f3e, 0x0000,
+ /* 0x0300 0x039f 0x0313 */
+ 0x1f4a, 0x0000,
+ /* 0x0301 0x039f 0x0313 */
+ 0x1f4c, 0x0000,
+ /* 0x0300 0x03a9 0x0313 */
+ 0x1f6a, 0x0000,
+ /* 0x0301 0x03a9 0x0313 */
+ 0x1f6c, 0x0000,
+ /* 0x0342 0x03a9 0x0313 */
+ 0x1f6e, 0x0000,
+ /* 0x0300 0x03b1 0x0313 */
+ 0x1f02, 0x0000,
+ /* 0x0301 0x03b1 0x0313 */
+ 0x1f04, 0x0000,
+ /* 0x0342 0x03b1 0x0313 */
+ 0x1f06, 0x0000,
+ /* 0x0300 0x03b5 0x0313 */
+ 0x1f12, 0x0000,
+ /* 0x0301 0x03b5 0x0313 */
+ 0x1f14, 0x0000,
+ /* 0x0300 0x03b7 0x0313 */
+ 0x1f22, 0x0000,
+ /* 0x0301 0x03b7 0x0313 */
+ 0x1f24, 0x0000,
+ /* 0x0342 0x03b7 0x0313 */
+ 0x1f26, 0x0000,
+ /* 0x0300 0x03b9 0x0313 */
+ 0x1f32, 0x0000,
+ /* 0x0301 0x03b9 0x0313 */
+ 0x1f34, 0x0000,
+ /* 0x0342 0x03b9 0x0313 */
+ 0x1f36, 0x0000,
+ /* 0x0300 0x03bf 0x0313 */
+ 0x1f42, 0x0000,
+ /* 0x0301 0x03bf 0x0313 */
+ 0x1f44, 0x0000,
+ /* 0x0300 0x03c5 0x0313 */
+ 0x1f52, 0x0000,
+ /* 0x0301 0x03c5 0x0313 */
+ 0x1f54, 0x0000,
+ /* 0x0342 0x03c5 0x0313 */
+ 0x1f56, 0x0000,
+ /* 0x0300 0x03c9 0x0313 */
+ 0x1f62, 0x0000,
+ /* 0x0301 0x03c9 0x0313 */
+ 0x1f64, 0x0000,
+ /* 0x0342 0x03c9 0x0313 */
+ 0x1f66, 0x0000,
+ /* 0x0300 0x0391 0x0314 */
+ 0x1f0b, 0x0000,
+ /* 0x0301 0x0391 0x0314 */
+ 0x1f0d, 0x0000,
+ /* 0x0342 0x0391 0x0314 */
+ 0x1f0f, 0x0000,
+ /* 0x0300 0x0395 0x0314 */
+ 0x1f1b, 0x0000,
+ /* 0x0301 0x0395 0x0314 */
+ 0x1f1d, 0x0000,
+ /* 0x0300 0x0397 0x0314 */
+ 0x1f2b, 0x0000,
+ /* 0x0301 0x0397 0x0314 */
+ 0x1f2d, 0x0000,
+ /* 0x0342 0x0397 0x0314 */
+ 0x1f2f, 0x0000,
+ /* 0x0300 0x0399 0x0314 */
+ 0x1f3b, 0x0000,
+ /* 0x0301 0x0399 0x0314 */
+ 0x1f3d, 0x0000,
+ /* 0x0342 0x0399 0x0314 */
+ 0x1f3f, 0x0000,
+ /* 0x0300 0x039f 0x0314 */
+ 0x1f4b, 0x0000,
+ /* 0x0301 0x039f 0x0314 */
+ 0x1f4d, 0x0000,
+ /* 0x0300 0x03a5 0x0314 */
+ 0x1f5b, 0x0000,
+ /* 0x0301 0x03a5 0x0314 */
+ 0x1f5d, 0x0000,
+ /* 0x0342 0x03a5 0x0314 */
+ 0x1f5f, 0x0000,
+ /* 0x0300 0x03a9 0x0314 */
+ 0x1f6b, 0x0000,
+ /* 0x0301 0x03a9 0x0314 */
+ 0x1f6d, 0x0000,
+ /* 0x0342 0x03a9 0x0314 */
+ 0x1f6f, 0x0000,
+ /* 0x0300 0x03b1 0x0314 */
+ 0x1f03, 0x0000,
+ /* 0x0301 0x03b1 0x0314 */
+ 0x1f05, 0x0000,
+ /* 0x0342 0x03b1 0x0314 */
+ 0x1f07, 0x0000,
+ /* 0x0300 0x03b5 0x0314 */
+ 0x1f13, 0x0000,
+ /* 0x0301 0x03b5 0x0314 */
+ 0x1f15, 0x0000,
+ /* 0x0300 0x03b7 0x0314 */
+ 0x1f23, 0x0000,
+ /* 0x0301 0x03b7 0x0314 */
+ 0x1f25, 0x0000,
+ /* 0x0342 0x03b7 0x0314 */
+ 0x1f27, 0x0000,
+ /* 0x0300 0x03b9 0x0314 */
+ 0x1f33, 0x0000,
+ /* 0x0301 0x03b9 0x0314 */
+ 0x1f35, 0x0000,
+ /* 0x0342 0x03b9 0x0314 */
+ 0x1f37, 0x0000,
+ /* 0x0300 0x03bf 0x0314 */
+ 0x1f43, 0x0000,
+ /* 0x0301 0x03bf 0x0314 */
+ 0x1f45, 0x0000,
+ /* 0x0300 0x03c5 0x0314 */
+ 0x1f53, 0x0000,
+ /* 0x0301 0x03c5 0x0314 */
+ 0x1f55, 0x0000,
+ /* 0x0342 0x03c5 0x0314 */
+ 0x1f57, 0x0000,
+ /* 0x0300 0x03c9 0x0314 */
+ 0x1f63, 0x0000,
+ /* 0x0301 0x03c9 0x0314 */
+ 0x1f65, 0x0000,
+ /* 0x0342 0x03c9 0x0314 */
+ 0x1f67, 0x0000,
+ /* 0x0300 0x004f 0x031b */
+ 0x1edc, 0x0000,
+ /* 0x0301 0x004f 0x031b */
+ 0x1eda, 0x0000,
+ /* 0x0303 0x004f 0x031b */
+ 0x1ee0, 0x0000,
+ /* 0x0309 0x004f 0x031b */
+ 0x1ede, 0x0000,
+ /* 0x0323 0x004f 0x031b */
+ 0x1ee2, 0x0000,
+ /* 0x0300 0x0055 0x031b */
+ 0x1eea, 0x0000,
+ /* 0x0301 0x0055 0x031b */
+ 0x1ee8, 0x0000,
+ /* 0x0303 0x0055 0x031b */
+ 0x1eee, 0x0000,
+ /* 0x0309 0x0055 0x031b */
+ 0x1eec, 0x0000,
+ /* 0x0323 0x0055 0x031b */
+ 0x1ef0, 0x0000,
+ /* 0x0300 0x006f 0x031b */
+ 0x1edd, 0x0000,
+ /* 0x0301 0x006f 0x031b */
+ 0x1edb, 0x0000,
+ /* 0x0303 0x006f 0x031b */
+ 0x1ee1, 0x0000,
+ /* 0x0309 0x006f 0x031b */
+ 0x1edf, 0x0000,
+ /* 0x0323 0x006f 0x031b */
+ 0x1ee3, 0x0000,
+ /* 0x0300 0x0075 0x031b */
+ 0x1eeb, 0x0000,
+ /* 0x0301 0x0075 0x031b */
+ 0x1ee9, 0x0000,
+ /* 0x0303 0x0075 0x031b */
+ 0x1eef, 0x0000,
+ /* 0x0309 0x0075 0x031b */
+ 0x1eed, 0x0000,
+ /* 0x0323 0x0075 0x031b */
+ 0x1ef1, 0x0000,
+ /* 0x0302 0x0041 0x0323 */
+ 0x1eac, 0x0000,
+ /* 0x0306 0x0041 0x0323 */
+ 0x1eb6, 0x0000,
+ /* 0x0302 0x0045 0x0323 */
+ 0x1ec6, 0x0000,
+ /* 0x0304 0x004c 0x0323 */
+ 0x1e38, 0x0000,
+ /* 0x0302 0x004f 0x0323 */
+ 0x1ed8, 0x0000,
+ /* 0x0304 0x0052 0x0323 */
+ 0x1e5c, 0x0000,
+ /* 0x0307 0x0053 0x0323 */
+ 0x1e68, 0x0000,
+ /* 0x0302 0x0061 0x0323 */
+ 0x1ead, 0x0000,
+ /* 0x0306 0x0061 0x0323 */
+ 0x1eb7, 0x0000,
+ /* 0x0302 0x0065 0x0323 */
+ 0x1ec7, 0x0000,
+ /* 0x0304 0x006c 0x0323 */
+ 0x1e39, 0x0000,
+ /* 0x0302 0x006f 0x0323 */
+ 0x1ed9, 0x0000,
+ /* 0x0304 0x0072 0x0323 */
+ 0x1e5d, 0x0000,
+ /* 0x0307 0x0073 0x0323 */
+ 0x1e69, 0x0000,
+ /* 0x0301 0x0043 0x0327 */
+ 0x1e08, 0x0000,
+ /* 0x0306 0x0045 0x0327 */
+ 0x1e1c, 0x0000,
+ /* 0x0301 0x0063 0x0327 */
+ 0x1e09, 0x0000,
+ /* 0x0306 0x0065 0x0327 */
+ 0x1e1d, 0x0000,
+ /* 0x0304 0x004f 0x0328 */
+ 0x01ec, 0x0000,
+ /* 0x0304 0x006f 0x0328 */
+ 0x01ed, 0x0000,
+ /* 0x0313 0x0391 0x0345 */
+ 0x1f88, 0x0003, 0x0300, 0x0f5e, 0x0301, 0x0f60, 0x0342, 0x0f62,
+ /* 0x0314 0x0391 0x0345 */
+ 0x1f89, 0x0003, 0x0300, 0x0f64, 0x0301, 0x0f66, 0x0342, 0x0f68,
+ /* 0x0313 0x0397 0x0345 */
+ 0x1f98, 0x0003, 0x0300, 0x0f6a, 0x0301, 0x0f6c, 0x0342, 0x0f6e,
+ /* 0x0314 0x0397 0x0345 */
+ 0x1f99, 0x0003, 0x0300, 0x0f70, 0x0301, 0x0f72, 0x0342, 0x0f74,
+ /* 0x0313 0x03a9 0x0345 */
+ 0x1fa8, 0x0003, 0x0300, 0x0f76, 0x0301, 0x0f78, 0x0342, 0x0f7a,
+ /* 0x0314 0x03a9 0x0345 */
+ 0x1fa9, 0x0003, 0x0300, 0x0f7c, 0x0301, 0x0f7e, 0x0342, 0x0f80,
+ /* 0x0300 0x03b1 0x0345 */
+ 0x1fb2, 0x0000,
+ /* 0x0301 0x03b1 0x0345 */
+ 0x1fb4, 0x0000,
+ /* 0x0313 0x03b1 0x0345 */
+ 0x1f80, 0x0003, 0x0300, 0x0f82, 0x0301, 0x0f84, 0x0342, 0x0f86,
+ /* 0x0314 0x03b1 0x0345 */
+ 0x1f81, 0x0003, 0x0300, 0x0f88, 0x0301, 0x0f8a, 0x0342, 0x0f8c,
+ /* 0x0342 0x03b1 0x0345 */
+ 0x1fb7, 0x0000,
+ /* 0x0300 0x03b7 0x0345 */
+ 0x1fc2, 0x0000,
+ /* 0x0301 0x03b7 0x0345 */
+ 0x1fc4, 0x0000,
+ /* 0x0313 0x03b7 0x0345 */
+ 0x1f90, 0x0003, 0x0300, 0x0f8e, 0x0301, 0x0f90, 0x0342, 0x0f92,
+ /* 0x0314 0x03b7 0x0345 */
+ 0x1f91, 0x0003, 0x0300, 0x0f94, 0x0301, 0x0f96, 0x0342, 0x0f98,
+ /* 0x0342 0x03b7 0x0345 */
+ 0x1fc7, 0x0000,
+ /* 0x0301 0x03bf 0x0345 */
+ 0x1ff4, 0x0000,
+ /* 0x0300 0x03c9 0x0345 */
+ 0x1ff2, 0x0000,
+ /* 0x0313 0x03c9 0x0345 */
+ 0x1fa0, 0x0003, 0x0300, 0x0f9a, 0x0301, 0x0f9c, 0x0342, 0x0f9e,
+ /* 0x0314 0x03c9 0x0345 */
+ 0x1fa1, 0x0003, 0x0300, 0x0fa0, 0x0301, 0x0fa2, 0x0342, 0x0fa4,
+ /* 0x0342 0x03c9 0x0345 */
+ 0x1ff7, 0x0000,
+ /* 0x05c1 0x05e9 0x05bc */
+ 0xfb2c, 0x0000,
+ /* 0x05c2 0x05e9 0x05bc */
+ 0xfb2d, 0x0000,
+ /* 0x0cd5 0x0cc6 0x0cc2 */
+ 0x0ccb, 0x0000,
+ /* 0x0f71 0x0fb2 0x0f80 */
+ 0x0f77, 0x0000,
+ /* 0x0f71 0x0fb3 0x0f80 */
+ 0x0f79, 0x0000,
+ /* 0x0300 0x0313 0x0391 0x0345 */
+ 0x1f8a, 0x0000,
+ /* 0x0301 0x0313 0x0391 0x0345 */
+ 0x1f8c, 0x0000,
+ /* 0x0342 0x0313 0x0391 0x0345 */
+ 0x1f8e, 0x0000,
+ /* 0x0300 0x0314 0x0391 0x0345 */
+ 0x1f8b, 0x0000,
+ /* 0x0301 0x0314 0x0391 0x0345 */
+ 0x1f8d, 0x0000,
+ /* 0x0342 0x0314 0x0391 0x0345 */
+ 0x1f8f, 0x0000,
+ /* 0x0300 0x0313 0x0397 0x0345 */
+ 0x1f9a, 0x0000,
+ /* 0x0301 0x0313 0x0397 0x0345 */
+ 0x1f9c, 0x0000,
+ /* 0x0342 0x0313 0x0397 0x0345 */
+ 0x1f9e, 0x0000,
+ /* 0x0300 0x0314 0x0397 0x0345 */
+ 0x1f9b, 0x0000,
+ /* 0x0301 0x0314 0x0397 0x0345 */
+ 0x1f9d, 0x0000,
+ /* 0x0342 0x0314 0x0397 0x0345 */
+ 0x1f9f, 0x0000,
+ /* 0x0300 0x0313 0x03a9 0x0345 */
+ 0x1faa, 0x0000,
+ /* 0x0301 0x0313 0x03a9 0x0345 */
+ 0x1fac, 0x0000,
+ /* 0x0342 0x0313 0x03a9 0x0345 */
+ 0x1fae, 0x0000,
+ /* 0x0300 0x0314 0x03a9 0x0345 */
+ 0x1fab, 0x0000,
+ /* 0x0301 0x0314 0x03a9 0x0345 */
+ 0x1fad, 0x0000,
+ /* 0x0342 0x0314 0x03a9 0x0345 */
+ 0x1faf, 0x0000,
+ /* 0x0300 0x0313 0x03b1 0x0345 */
+ 0x1f82, 0x0000,
+ /* 0x0301 0x0313 0x03b1 0x0345 */
+ 0x1f84, 0x0000,
+ /* 0x0342 0x0313 0x03b1 0x0345 */
+ 0x1f86, 0x0000,
+ /* 0x0300 0x0314 0x03b1 0x0345 */
+ 0x1f83, 0x0000,
+ /* 0x0301 0x0314 0x03b1 0x0345 */
+ 0x1f85, 0x0000,
+ /* 0x0342 0x0314 0x03b1 0x0345 */
+ 0x1f87, 0x0000,
+ /* 0x0300 0x0313 0x03b7 0x0345 */
+ 0x1f92, 0x0000,
+ /* 0x0301 0x0313 0x03b7 0x0345 */
+ 0x1f94, 0x0000,
+ /* 0x0342 0x0313 0x03b7 0x0345 */
+ 0x1f96, 0x0000,
+ /* 0x0300 0x0314 0x03b7 0x0345 */
+ 0x1f93, 0x0000,
+ /* 0x0301 0x0314 0x03b7 0x0345 */
+ 0x1f95, 0x0000,
+ /* 0x0342 0x0314 0x03b7 0x0345 */
+ 0x1f97, 0x0000,
+ /* 0x0300 0x0313 0x03c9 0x0345 */
+ 0x1fa2, 0x0000,
+ /* 0x0301 0x0313 0x03c9 0x0345 */
+ 0x1fa4, 0x0000,
+ /* 0x0342 0x0313 0x03c9 0x0345 */
+ 0x1fa6, 0x0000,
+ /* 0x0300 0x0314 0x03c9 0x0345 */
+ 0x1fa3, 0x0000,
+ /* 0x0301 0x0314 0x03c9 0x0345 */
+ 0x1fa5, 0x0000,
+ /* 0x0342 0x0314 0x03c9 0x0345 */
+ 0x1fa7, 0x0000,
+};
diff --git a/fs/hfsplus/unicode.c b/fs/hfsplus/unicode.c
index 4821cd239d595..060c69048c3dd 100644
--- a/fs/hfsplus/unicode.c
+++ b/fs/hfsplus/unicode.c
@@ -19,9 +19,9 @@ static inline u16 case_fold(u16 c)
{
u16 tmp;
- tmp = case_fold_table[(c>>8)];
+ tmp = hfsplus_case_fold_table[c >> 8];
if (tmp)
- tmp = case_fold_table[tmp + (c & 0xFF)];
+ tmp = hfsplus_case_fold_table[tmp + (c & 0xff)];
else
tmp = c;
return tmp;
@@ -59,69 +59,175 @@ int hfsplus_unistrcmp(const struct hfsplus_unistr *s1, const struct hfsplus_unis
}
}
-int hfsplus_uni2asc(const struct hfsplus_unistr *ustr, char *astr, int *len)
+#define Hangul_SBase 0xac00
+#define Hangul_LBase 0x1100
+#define Hangul_VBase 0x1161
+#define Hangul_TBase 0x11a7
+#define Hangul_SCount 11172
+#define Hangul_LCount 19
+#define Hangul_VCount 21
+#define Hangul_TCount 28
+#define Hangul_NCount (Hangul_VCount * Hangul_TCount)
+
+
+static u16 *hfsplus_compose_lookup(u16 *p, u16 cc)
+{
+ int i, s, e;
+
+ s = 1;
+ e = p[1];
+ if (!e || cc < p[s * 2] || cc > p[e * 2])
+ return NULL;
+ do {
+ i = (s + e) / 2;
+ if (cc > p[i * 2])
+ s = i + 1;
+ else if (cc < p[i * 2])
+ e = i - 1;
+ else
+ return hfsplus_compose_table + p[i * 2 + 1];
+ } while (s <= e);
+ return NULL;
+}
+
+int hfsplus_uni2asc(struct super_block *sb, const struct hfsplus_unistr *ustr, char *astr, int *len_p)
{
const hfsplus_unichr *ip;
+ struct nls_table *nls = HFSPLUS_SB(sb).nls;
u8 *op;
- u16 ustrlen, cc;
- int size, tmp;
+ u16 cc, c0, c1;
+ u16 *ce1, *ce2;
+ int i, len, ustrlen, res, compose;
op = astr;
ip = ustr->unicode;
ustrlen = be16_to_cpu(ustr->length);
- tmp = *len;
- while (ustrlen > 0 && tmp > 0) {
- cc = be16_to_cpu(*ip);
- switch (cc) {
+ len = *len_p;
+ ce1 = NULL;
+ compose = !(HFSPLUS_SB(sb).flags & HFSPLUS_SB_NODECOMPOSE);
+
+ while (ustrlen > 0) {
+ c0 = be16_to_cpu(*ip++);
+ ustrlen--;
+ /* search for single decomposed char */
+ if (likely(compose))
+ ce1 = hfsplus_compose_lookup(hfsplus_compose_table, c0);
+ if (ce1 && (cc = ce1[0])) {
+ /* start of a possibly decomposed Hangul char */
+ if (cc != 0xffff)
+ goto done;
+ if (!ustrlen)
+ goto same;
+ c1 = be16_to_cpu(*ip) - Hangul_VBase;
+ if (c1 < Hangul_VCount) {
+ /* compose the Hangul char */
+ cc = (c0 - Hangul_LBase) * Hangul_VCount;
+ cc = (cc + c1) * Hangul_TCount;
+ cc += Hangul_SBase;
+ ip++;
+ ustrlen--;
+ if (!ustrlen)
+ goto done;
+ c1 = be16_to_cpu(*ip) - Hangul_TBase;
+ if (c1 > 0 && c1 < Hangul_TCount) {
+ cc += c1;
+ ip++;
+ ustrlen--;
+ }
+ goto done;
+ }
+ }
+ while (1) {
+ /* main loop for common case of not composed chars */
+ if (!ustrlen)
+ goto same;
+ c1 = be16_to_cpu(*ip);
+ if (likely(compose))
+ ce1 = hfsplus_compose_lookup(hfsplus_compose_table, c1);
+ if (ce1)
+ break;
+ switch (c0) {
+ case 0:
+ c0 = 0x2400;
+ break;
+ case '/':
+ c0 = ':';
+ break;
+ }
+ res = nls->uni2char(c0, op, len);
+ if (res < 0) {
+ if (res == -ENAMETOOLONG)
+ goto out;
+ *op = '?';
+ res = 1;
+ }
+ op += res;
+ len -= res;
+ c0 = c1;
+ ip++;
+ ustrlen--;
+ }
+ ce2 = hfsplus_compose_lookup(ce1, c0);
+ if (ce2) {
+ i = 1;
+ while (i < ustrlen) {
+ ce1 = hfsplus_compose_lookup(ce2, be16_to_cpu(ip[i]));
+ if (!ce1)
+ break;
+ i++;
+ ce2 = ce1;
+ }
+ if ((cc = ce2[0])) {
+ ip += i;
+ ustrlen -= i;
+ goto done;
+ }
+ }
+ same:
+ switch (c0) {
case 0:
cc = 0x2400;
break;
case '/':
cc = ':';
break;
+ default:
+ cc = c0;
}
- if (cc > 0x7f) {
- size = utf8_wctomb(op, cc, tmp);
- if (size == -1) {
- /* ignore */
- } else {
- op += size;
- tmp -= size;
- }
- } else {
- *op++ = (u8) cc;
- tmp--;
+ done:
+ res = nls->uni2char(cc, op, len);
+ if (res < 0) {
+ if (res == -ENAMETOOLONG)
+ goto out;
+ *op = '?';
+ res = 1;
}
- ip++;
- ustrlen--;
+ op += res;
+ len -= res;
}
- *len = (char *)op - astr;
- if (ustrlen)
- return -ENAMETOOLONG;
- return 0;
+ res = 0;
+out:
+ *len_p = (char *)op - astr;
+ return res;
}
-int hfsplus_asc2uni(struct hfsplus_unistr *ustr, const char *astr, int len)
+int hfsplus_asc2uni(struct super_block *sb, struct hfsplus_unistr *ustr, const char *astr, int len)
{
- int tmp;
+ struct nls_table *nls = HFSPLUS_SB(sb).nls;
+ int size, off, decompose;
wchar_t c;
u16 outlen = 0;
- while (outlen <= HFSPLUS_MAX_STRLEN && len > 0) {
- if (*astr & 0x80) {
- tmp = utf8_mbtowc(&c, astr, len);
- if (tmp < 0) {
- astr++;
- len--;
- continue;
- } else {
- astr += tmp;
- len -= tmp;
- }
- } else {
- c = *astr++;
- len--;
+ decompose = !(HFSPLUS_SB(sb).flags & HFSPLUS_SB_NODECOMPOSE);
+
+ while (outlen < HFSPLUS_MAX_STRLEN && len > 0) {
+ size = nls->char2uni(astr, len, &c);
+ if (size <= 0) {
+ c = '?';
+ size = 1;
}
+ astr += size;
+ len -= size;
switch (c) {
case 0x2400:
c = 0;
@@ -130,8 +236,33 @@ int hfsplus_asc2uni(struct hfsplus_unistr *ustr, const char *astr, int len)
c = '/';
break;
}
- ustr->unicode[outlen] = cpu_to_be16(c);
- outlen++;
+ if (c >= 0xc0 && decompose) {
+ off = hfsplus_decompose_table[(c >> 12) & 0xf];
+ if (!off)
+ goto done;
+ if (off == 0xffff) {
+ goto done;
+ }
+ off = hfsplus_decompose_table[off + ((c >> 8) & 0xf)];
+ if (!off)
+ goto done;
+ off = hfsplus_decompose_table[off + ((c >> 4) & 0xf)];
+ if (!off)
+ goto done;
+ off = hfsplus_decompose_table[off + (c & 0xf)];
+ size = off & 3;
+ if (!size)
+ goto done;
+ off /= 4;
+ if (outlen + size > HFSPLUS_MAX_STRLEN)
+ break;
+ do {
+ ustr->unicode[outlen++] = cpu_to_be16(hfsplus_decompose_table[off++]);
+ } while (--size > 0);
+ continue;
+ }
+ done:
+ ustr->unicode[outlen++] = cpu_to_be16(c);
}
ustr->length = cpu_to_be16(outlen);
if (len > 0)
diff --git a/fs/hostfs/Makefile b/fs/hostfs/Makefile
index 0f8e01cb3c3ff..d5beaffad43b7 100644
--- a/fs/hostfs/Makefile
+++ b/fs/hostfs/Makefile
@@ -3,24 +3,9 @@
# Licensed under the GPL
#
-# struct stat64 changed the inode field name between 2.2 and 2.4 from st_ino
-# to __st_ino. It stayed in the same place, so as long as the correct name
-# is used, hostfs compiled on 2.2 should work on 2.4 and vice versa.
-
-STAT64_INO_FIELD := $(shell grep -q __st_ino /usr/include/bits/stat.h && \
- echo __)st_ino
-
hostfs-objs := hostfs_kern.o hostfs_user.o
-obj-y =
+obj-y :=
obj-$(CONFIG_HOSTFS) += hostfs.o
-SINGLE_OBJS = $(foreach f,$(patsubst %.o,%,$(obj-y) $(obj-m)),$($(f)-objs))
-
-USER_OBJS := $(filter %_user.o,$(obj-y) $(obj-m) $(SINGLE_OBJS))
-USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
-
-USER_CFLAGS += -DSTAT64_INO_FIELD=$(STAT64_INO_FIELD)
-
-$(USER_OBJS) : %.o: %.c
- $(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
+include arch/um/scripts/Makefile.rules
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
index 144ff70fbd55e..a88ad29248511 100644
--- a/fs/hostfs/hostfs_kern.c
+++ b/fs/hostfs/hostfs_kern.c
@@ -806,15 +806,21 @@ int hostfs_permission(struct inode *ino, int desired, struct nameidata *nd)
char *name;
int r = 0, w = 0, x = 0, err;
- if(desired & MAY_READ) r = 1;
- if(desired & MAY_WRITE) w = 1;
- if(desired & MAY_EXEC) x = 1;
+ if (desired & MAY_READ) r = 1;
+ if (desired & MAY_WRITE) w = 1;
+ if (desired & MAY_EXEC) x = 1;
name = inode_name(ino, 0);
- if(name == NULL) return(-ENOMEM);
- err = access_file(name, r, w, x);
+ if (name == NULL) return(-ENOMEM);
+
+ if (S_ISCHR(ino->i_mode) || S_ISBLK(ino->i_mode) ||
+ S_ISFIFO(ino->i_mode) || S_ISSOCK(ino->i_mode))
+ err = 0;
+ else
+ err = access_file(name, r, w, x);
kfree(name);
- if(!err) err = generic_permission(ino, desired, NULL);
- return(err);
+ if(!err)
+ err = generic_permission(ino, desired, NULL);
+ return err;
}
int hostfs_setattr(struct dentry *dentry, struct iattr *attr)
@@ -845,7 +851,7 @@ int hostfs_setattr(struct dentry *dentry, struct iattr *attr)
if(attr->ia_valid & ATTR_GID){
if((dentry->d_inode->i_sb->s_dev == ROOT_DEV) &&
(attr->ia_gid == 0))
- attr->ia_gid = getuid();
+ attr->ia_gid = getgid();
attrs.ia_valid |= HOSTFS_ATTR_GID;
attrs.ia_gid = attr->ia_gid;
}
diff --git a/fs/hostfs/hostfs_user.c b/fs/hostfs/hostfs_user.c
index 16974dc07e5a6..4796e8490f7d4 100644
--- a/fs/hostfs/hostfs_user.c
+++ b/fs/hostfs/hostfs_user.c
@@ -28,10 +28,7 @@ int stat_file(const char *path, unsigned long long *inode_out, int *mode_out,
if(lstat64(path, &buf) < 0)
return(-errno);
- /* See the Makefile for why STAT64_INO_FIELD is passed in
- * by the build
- */
- if(inode_out != NULL) *inode_out = buf.STAT64_INO_FIELD;
+ if(inode_out != NULL) *inode_out = buf.st_ino;
if(mode_out != NULL) *mode_out = buf.st_mode;
if(nlink_out != NULL) *nlink_out = buf.st_nlink;
if(uid_out != NULL) *uid_out = buf.st_uid;
diff --git a/fs/hpfs/alloc.c b/fs/hpfs/alloc.c
index 2baa977ffa1d5..5503e2c289101 100644
--- a/fs/hpfs/alloc.c
+++ b/fs/hpfs/alloc.c
@@ -8,6 +8,8 @@
#include "hpfs_fn.h"
+static int hpfs_alloc_if_possible_nolock(struct super_block *s, secno sec);
+
/*
* Check if a sector is allocated in bitmap
* This is really slow. Turned on only if chk==2
@@ -243,7 +245,7 @@ static secno alloc_in_dirband(struct super_block *s, secno near, int lock)
/* Alloc sector if it's free */
-int hpfs_alloc_if_possible_nolock(struct super_block *s, secno sec)
+static int hpfs_alloc_if_possible_nolock(struct super_block *s, secno sec)
{
struct quad_buffer_head qbh;
unsigned *bmp;
diff --git a/fs/hpfs/dentry.c b/fs/hpfs/dentry.c
index 706c6fef471c2..08319126b2afa 100644
--- a/fs/hpfs/dentry.c
+++ b/fs/hpfs/dentry.c
@@ -12,7 +12,7 @@
* Note: the dentry argument is the parent dentry.
*/
-int hpfs_hash_dentry(struct dentry *dentry, struct qstr *qstr)
+static int hpfs_hash_dentry(struct dentry *dentry, struct qstr *qstr)
{
unsigned long hash;
int i;
@@ -34,7 +34,7 @@ int hpfs_hash_dentry(struct dentry *dentry, struct qstr *qstr)
return 0;
}
-int hpfs_compare_dentry(struct dentry *dentry, struct qstr *a, struct qstr *b)
+static int hpfs_compare_dentry(struct dentry *dentry, struct qstr *a, struct qstr *b)
{
unsigned al=a->len;
unsigned bl=b->len;
@@ -49,7 +49,7 @@ int hpfs_compare_dentry(struct dentry *dentry, struct qstr *a, struct qstr *b)
return 0;
}
-struct dentry_operations hpfs_dentry_operations = {
+static struct dentry_operations hpfs_dentry_operations = {
.d_hash = hpfs_hash_dentry,
.d_compare = hpfs_compare_dentry,
};
diff --git a/fs/hpfs/dnode.c b/fs/hpfs/dnode.c
index 9794e2fc2b9a4..1d21307730a83 100644
--- a/fs/hpfs/dnode.c
+++ b/fs/hpfs/dnode.c
@@ -78,7 +78,7 @@ static void for_all_poss(struct inode *inode, void (*f)(loff_t *, loff_t, loff_t
return;
}
-void hpfs_pos_subst(loff_t *p, loff_t f, loff_t t)
+static void hpfs_pos_subst(loff_t *p, loff_t f, loff_t t)
{
if (*p == f) *p = t;
}
@@ -88,7 +88,7 @@ void hpfs_pos_subst(loff_t *p, loff_t f, loff_t t)
if ((*p & ~0x3f) == (f & ~0x3f)) *p = (t & ~0x3f) | (*p & 0x3f);
}*/
-void hpfs_pos_ins(loff_t *p, loff_t d, loff_t c)
+static void hpfs_pos_ins(loff_t *p, loff_t d, loff_t c)
{
if ((*p & ~0x3f) == (d & ~0x3f) && (*p & 0x3f) >= (d & 0x3f)) {
int n = (*p & 0x3f) + c;
@@ -97,7 +97,7 @@ void hpfs_pos_ins(loff_t *p, loff_t d, loff_t c)
}
}
-void hpfs_pos_del(loff_t *p, loff_t d, loff_t c)
+static void hpfs_pos_del(loff_t *p, loff_t d, loff_t c)
{
if ((*p & ~0x3f) == (d & ~0x3f) && (*p & 0x3f) >= (d & 0x3f)) {
int n = (*p & 0x3f) - c;
@@ -189,7 +189,8 @@ struct hpfs_dirent *hpfs_add_de(struct super_block *s, struct dnode *d, unsigned
/* Delete dirent and don't care about its subtree */
-void hpfs_delete_de(struct super_block *s, struct dnode *d, struct hpfs_dirent *de)
+static void hpfs_delete_de(struct super_block *s, struct dnode *d,
+ struct hpfs_dirent *de)
{
if (de->last) {
hpfs_error(s, "attempt to delete last dirent in dnode %08x", d->self);
@@ -221,8 +222,9 @@ static void fix_up_ptrs(struct super_block *s, struct dnode *d)
/* Add an entry to dnode and do dnode splitting if required */
-int hpfs_add_to_dnode(struct inode *i, dnode_secno dno, unsigned char *name, unsigned namelen,
- struct hpfs_dirent *new_de, dnode_secno down_ptr)
+static int hpfs_add_to_dnode(struct inode *i, dnode_secno dno,
+ unsigned char *name, unsigned namelen,
+ struct hpfs_dirent *new_de, dnode_secno down_ptr)
{
struct quad_buffer_head qbh, qbh1, qbh2;
struct dnode *d, *ad, *rd, *nd = NULL;
diff --git a/fs/hpfs/hpfs.h b/fs/hpfs/hpfs.h
index da40420c781cb..0e84c73cd9c4e 100644
--- a/fs/hpfs/hpfs.h
+++ b/fs/hpfs/hpfs.h
@@ -27,6 +27,8 @@ typedef secno dnode_secno; /* sector number of a dnode */
typedef secno fnode_secno; /* sector number of an fnode */
typedef secno anode_secno; /* sector number of an anode */
+typedef u32 time32_t; /* 32-bit time_t type */
+
/* sector 0 */
/* The boot block is very like a FAT boot block, except that the
@@ -84,9 +86,9 @@ struct hpfs_super_block
unsigned zero1; /* 0 */
secno badblocks; /* bad block list */
unsigned zero3; /* 0 */
- time_t last_chkdsk; /* date last checked, 0 if never */
+ time32_t last_chkdsk; /* date last checked, 0 if never */
/*unsigned zero4;*/ /* 0 */
- time_t last_optimize; /* date last optimized, 0 if never */
+ time32_t last_optimize; /* date last optimized, 0 if never */
secno n_dir_band; /* number of sectors in dir band */
secno dir_band_start; /* first sector in dir band */
secno dir_band_end; /* last sector in dir band */
@@ -287,10 +289,10 @@ struct hpfs_dirent {
unsigned not_8x3: 1; /* name is not 8.3 */
unsigned flag15: 1;
fnode_secno fnode; /* fnode giving allocation info */
- time_t write_date; /* mtime */
+ time32_t write_date; /* mtime */
unsigned file_size; /* file length, bytes */
- time_t read_date; /* atime */
- time_t creation_date; /* ctime */
+ time32_t read_date; /* atime */
+ time32_t creation_date; /* ctime */
unsigned ea_size; /* total EA length, bytes */
unsigned char no_of_acls : 3; /* number of ACL's */
unsigned char reserver : 5;
diff --git a/fs/hpfs/hpfs_fn.h b/fs/hpfs/hpfs_fn.h
index ebe670a021707..6628c3b352cb4 100644
--- a/fs/hpfs/hpfs_fn.h
+++ b/fs/hpfs/hpfs_fn.h
@@ -202,7 +202,6 @@ static inline unsigned tstbits(unsigned *bmp, unsigned b, unsigned n)
int hpfs_chk_sectors(struct super_block *, secno, int, char *);
secno hpfs_alloc_sector(struct super_block *, secno, unsigned, int, int);
-int hpfs_alloc_if_possible_nolock(struct super_block *, secno);
int hpfs_alloc_if_possible(struct super_block *, secno);
void hpfs_free_sectors(struct super_block *, secno, unsigned);
int hpfs_check_free_dnodes(struct super_block *, int);
@@ -247,8 +246,6 @@ extern struct file_operations hpfs_dir_ops;
void hpfs_add_pos(struct inode *, loff_t *);
void hpfs_del_pos(struct inode *, loff_t *);
struct hpfs_dirent *hpfs_add_de(struct super_block *, struct dnode *, unsigned char *, unsigned, secno);
-void hpfs_delete_de(struct super_block *, struct dnode *, struct hpfs_dirent *);
-int hpfs_add_to_dnode(struct inode *, dnode_secno, unsigned char *, unsigned, struct hpfs_dirent *, dnode_secno);
int hpfs_add_dirent(struct inode *, unsigned char *, unsigned, struct hpfs_dirent *, int);
int hpfs_remove_dirent(struct inode *, dnode_secno, struct hpfs_dirent *, struct quad_buffer_head *, int);
void hpfs_count_dnodes(struct super_block *, dnode_secno, int *, int *, int *);
@@ -276,7 +273,6 @@ extern struct address_space_operations hpfs_aops;
void hpfs_init_inode(struct inode *);
void hpfs_read_inode(struct inode *);
-void hpfs_write_inode_ea(struct inode *, struct fnode *);
void hpfs_write_inode(struct inode *);
void hpfs_write_inode_nolock(struct inode *);
int hpfs_notify_change(struct dentry *, struct iattr *);
@@ -329,13 +325,13 @@ unsigned hpfs_count_one_bitmap(struct super_block *, secno);
* local time (HPFS) to GMT (Unix)
*/
-static inline time_t local_to_gmt(struct super_block *s, time_t t)
+static inline time_t local_to_gmt(struct super_block *s, time32_t t)
{
extern struct timezone sys_tz;
return t + sys_tz.tz_minuteswest * 60 + hpfs_sb(s)->sb_timeshift;
}
-static inline time_t gmt_to_local(struct super_block *s, time_t t)
+static inline time32_t gmt_to_local(struct super_block *s, time_t t)
{
extern struct timezone sys_tz;
return t - sys_tz.tz_minuteswest * 60 - hpfs_sb(s)->sb_timeshift;
diff --git a/fs/hpfs/inode.c b/fs/hpfs/inode.c
index 28483e9e76dc9..38b1741fa539f 100644
--- a/fs/hpfs/inode.c
+++ b/fs/hpfs/inode.c
@@ -141,7 +141,7 @@ void hpfs_read_inode(struct inode *i)
brelse(bh);
}
-void hpfs_write_inode_ea(struct inode *i, struct fnode *fnode)
+static void hpfs_write_inode_ea(struct inode *i, struct fnode *fnode)
{
struct hpfs_inode_info *hpfs_inode = hpfs_i(i);
/*if (fnode->acl_size_l || fnode->acl_size_s) {
diff --git a/fs/hpfs/name.c b/fs/hpfs/name.c
index cb703c2ad1303..1f4a964384eb3 100644
--- a/fs/hpfs/name.c
+++ b/fs/hpfs/name.c
@@ -8,12 +8,12 @@
#include "hpfs_fn.h"
-char *text_postfix[]={
+static char *text_postfix[]={
".ASM", ".BAS", ".BAT", ".C", ".CC", ".CFG", ".CMD", ".CON", ".CPP", ".DEF",
".DOC", ".DPR", ".ERX", ".H", ".HPP", ".HTM", ".HTML", ".JAVA", ".LOG", ".PAS",
".RC", ".TEX", ".TXT", ".Y", ""};
-char *text_prefix[]={
+static char *text_prefix[]={
"AUTOEXEC.", "CHANGES", "COPYING", "CONFIG.", "CREDITS", "FAQ", "FILE_ID.DIZ",
"MAKEFILE", "READ.ME", "README", "TERMCAP", ""};
diff --git a/fs/hpfs/super.c b/fs/hpfs/super.c
index 34074b3782c3a..8eefa6366db74 100644
--- a/fs/hpfs/super.c
+++ b/fs/hpfs/super.c
@@ -246,9 +246,9 @@ static match_table_t tokens = {
{Opt_err, NULL},
};
-int parse_opts(char *opts, uid_t *uid, gid_t *gid, umode_t *umask,
- int *lowercase, int *conv, int *eas, int *chk, int *errs,
- int *chkdsk, int *timeshift)
+static int parse_opts(char *opts, uid_t *uid, gid_t *gid, umode_t *umask,
+ int *lowercase, int *conv, int *eas, int *chk, int *errs,
+ int *chkdsk, int *timeshift)
{
char *p;
int option;
diff --git a/fs/hppfs/Makefile b/fs/hppfs/Makefile
index a2d5c4d05e30d..6890433f7595c 100644
--- a/fs/hppfs/Makefile
+++ b/fs/hppfs/Makefile
@@ -7,13 +7,3 @@ hppfs-objs := hppfs_kern.o
obj-y =
obj-$(CONFIG_HPPFS) += hppfs.o
-
-clean:
-
-modules:
-
-fastdep:
-
-dep:
-
-archmrproper: clean
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index 7a006cc6e1c24..2af3338f891bb 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -40,7 +40,7 @@ static struct inode_operations hugetlbfs_inode_operations;
static struct backing_dev_info hugetlbfs_backing_dev_info = {
.ra_pages = 0, /* No readahead */
- .memory_backed = 1, /* Does not contribute to dirty memory */
+ .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK,
};
int sysctl_hugetlb_shm_group;
diff --git a/fs/inode.c b/fs/inode.c
index d76a6e4b3ee11..90025a39a789f 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -196,7 +196,7 @@ void inode_init_once(struct inode *inode)
sema_init(&inode->i_sem, 1);
init_rwsem(&inode->i_alloc_sem);
INIT_RADIX_TREE(&inode->i_data.page_tree, GFP_ATOMIC);
- spin_lock_init(&inode->i_data.tree_lock);
+ rwlock_init(&inode->i_data.tree_lock);
spin_lock_init(&inode->i_data.i_mmap_lock);
INIT_LIST_HEAD(&inode->i_data.private_list);
spin_lock_init(&inode->i_data.private_lock);
@@ -1098,15 +1098,16 @@ static inline void iput_final(struct inode *inode)
* @inode: inode to put
*
* Puts an inode, dropping its usage count. If the inode use count hits
- * zero the inode is also then freed and may be destroyed.
+ * zero, the inode is then freed and may also be destroyed.
+ *
+ * Consequently, iput() can sleep.
*/
void iput(struct inode *inode)
{
if (inode) {
struct super_operations *op = inode->i_sb->s_op;
- if (inode->i_state == I_CLEAR)
- BUG();
+ BUG_ON(inode->i_state == I_CLEAR);
if (op && op->put_inode)
op->put_inode(inode);
diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c
index 0ee7beb9d48ad..b9256e65e144c 100644
--- a/fs/isofs/inode.c
+++ b/fs/isofs/inode.c
@@ -685,6 +685,8 @@ root_found:
sbi->s_log_zone_size = isonum_723 (h_pri->logical_block_size);
sbi->s_max_size = isonum_733(h_pri->volume_space_size);
} else {
+ if (!pri)
+ goto out_freebh;
rootp = (struct iso_directory_record *) pri->root_directory_record;
sbi->s_nzones = isonum_733 (pri->volume_space_size);
sbi->s_log_zone_size = isonum_723 (pri->logical_block_size);
@@ -1395,6 +1397,9 @@ struct inode *isofs_iget(struct super_block *sb,
struct inode *inode;
struct isofs_iget5_callback_data data;
+ if (offset >= 1ul << sb->s_blocksize_bits)
+ return NULL;
+
data.block = block;
data.offset = offset;
diff --git a/fs/isofs/rock.c b/fs/isofs/rock.c
index 19d999fd450c2..8bdd3e409543b 100644
--- a/fs/isofs/rock.c
+++ b/fs/isofs/rock.c
@@ -53,6 +53,7 @@
if(LEN & 1) LEN++; \
CHR = ((unsigned char *) DE) + LEN; \
LEN = *((unsigned char *) DE) - LEN; \
+ if (LEN<0) LEN=0; \
if (ISOFS_SB(inode->i_sb)->s_rock_offset!=-1) \
{ \
LEN-=ISOFS_SB(inode->i_sb)->s_rock_offset; \
@@ -73,6 +74,10 @@
offset1 = 0; \
pbh = sb_bread(DEV->i_sb, block); \
if(pbh){ \
+ if (offset > pbh->b_size || offset + cont_size > pbh->b_size){ \
+ brelse(pbh); \
+ goto out; \
+ } \
memcpy(buffer + offset1, pbh->b_data + offset, cont_size - offset1); \
brelse(pbh); \
chr = (unsigned char *) buffer; \
@@ -103,12 +108,13 @@ int get_rock_ridge_filename(struct iso_directory_record * de,
struct rock_ridge * rr;
int sig;
- while (len > 1){ /* There may be one byte for padding somewhere */
+ while (len > 2){ /* There may be one byte for padding somewhere */
rr = (struct rock_ridge *) chr;
- if (rr->len == 0) goto out; /* Something got screwed up here */
+ if (rr->len < 3) goto out; /* Something got screwed up here */
sig = isonum_721(chr);
chr += rr->len;
len -= rr->len;
+ if (len < 0) goto out; /* corrupted isofs */
switch(sig){
case SIG('R','R'):
@@ -122,6 +128,7 @@ int get_rock_ridge_filename(struct iso_directory_record * de,
break;
case SIG('N','M'):
if (truncate) break;
+ if (rr->len < 5) break;
/*
* If the flags are 2 or 4, this indicates '.' or '..'.
* We don't want to do anything with this, because it
@@ -186,12 +193,13 @@ parse_rock_ridge_inode_internal(struct iso_directory_record *de,
struct rock_ridge * rr;
int rootflag;
- while (len > 1){ /* There may be one byte for padding somewhere */
+ while (len > 2){ /* There may be one byte for padding somewhere */
rr = (struct rock_ridge *) chr;
- if (rr->len == 0) goto out; /* Something got screwed up here */
+ if (rr->len < 3) goto out; /* Something got screwed up here */
sig = isonum_721(chr);
chr += rr->len;
len -= rr->len;
+ if (len < 0) goto out; /* corrupted isofs */
switch(sig){
#ifndef CONFIG_ZISOFS /* No flag for SF or ZF */
@@ -462,7 +470,7 @@ static int rock_ridge_symlink_readpage(struct file *file, struct page *page)
struct rock_ridge *rr;
if (!ISOFS_SB(inode->i_sb)->s_rock)
- panic ("Cannot have symlink with high sierra variant of iso filesystem\n");
+ goto error;
block = ei->i_iget5_block;
lock_kernel();
@@ -487,13 +495,15 @@ static int rock_ridge_symlink_readpage(struct file *file, struct page *page)
SETUP_ROCK_RIDGE(raw_inode, chr, len);
repeat:
- while (len > 1) { /* There may be one byte for padding somewhere */
+ while (len > 2) { /* There may be one byte for padding somewhere */
rr = (struct rock_ridge *) chr;
- if (rr->len == 0)
+ if (rr->len < 3)
goto out; /* Something got screwed up here */
sig = isonum_721(chr);
chr += rr->len;
len -= rr->len;
+ if (len < 0)
+ goto out; /* corrupted isofs */
switch (sig) {
case SIG('R', 'R'):
@@ -543,6 +553,7 @@ static int rock_ridge_symlink_readpage(struct file *file, struct page *page)
fail:
brelse(bh);
unlock_kernel();
+ error:
SetPageError(page);
kunmap(page);
unlock_page(page);
diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c
index aa5f22435d0c2..dac720c837abf 100644
--- a/fs/jbd/commit.c
+++ b/fs/jbd/commit.c
@@ -93,6 +93,73 @@ static int inverted_lock(journal_t *journal, struct buffer_head *bh)
return 1;
}
+/* Done it all: now write the commit record. We should have
+ * cleaned up our previous buffers by now, so if we are in abort
+ * mode we can now just skip the rest of the journal write
+ * entirely.
+ *
+ * Returns 1 if the journal needs to be aborted or 0 on success
+ */
+static int journal_write_commit_record(journal_t *journal,
+ transaction_t *commit_transaction)
+{
+ struct journal_head *descriptor;
+ struct buffer_head *bh;
+ int i, ret;
+ int barrier_done = 0;
+
+ if (is_journal_aborted(journal))
+ return 0;
+
+ descriptor = journal_get_descriptor_buffer(journal);
+ if (!descriptor)
+ return 1;
+
+ bh = jh2bh(descriptor);
+
+ /* AKPM: buglet - add `i' to tmp! */
+ for (i = 0; i < bh->b_size; i += 512) {
+ journal_header_t *tmp = (journal_header_t*)bh->b_data;
+ tmp->h_magic = cpu_to_be32(JFS_MAGIC_NUMBER);
+ tmp->h_blocktype = cpu_to_be32(JFS_COMMIT_BLOCK);
+ tmp->h_sequence = cpu_to_be32(commit_transaction->t_tid);
+ }
+
+ JBUFFER_TRACE(descriptor, "write commit block");
+ set_buffer_dirty(bh);
+ if (journal->j_flags & JFS_BARRIER) {
+ set_buffer_ordered(bh);
+ barrier_done = 1;
+ }
+ ret = sync_dirty_buffer(bh);
+ /* is it possible for another commit to fail at roughly
+ * the same time as this one? If so, we don't want to
+ * trust the barrier flag in the super, but instead want
+ * to remember if we sent a barrier request
+ */
+ if (ret == -EOPNOTSUPP && barrier_done) {
+ char b[BDEVNAME_SIZE];
+
+ printk(KERN_WARNING
+ "JBD: barrier-based sync failed on %s - "
+ "disabling barriers\n",
+ bdevname(journal->j_dev, b));
+ spin_lock(&journal->j_state_lock);
+ journal->j_flags &= ~JFS_BARRIER;
+ spin_unlock(&journal->j_state_lock);
+
+ /* And try again, without the barrier */
+ clear_buffer_ordered(bh);
+ set_buffer_uptodate(bh);
+ set_buffer_dirty(bh);
+ ret = sync_dirty_buffer(bh);
+ }
+ put_bh(bh); /* One for getblk() */
+ journal_put_journal_head(descriptor);
+
+ return (ret == -EIO);
+}
+
/*
* journal_commit_transaction
*
@@ -103,7 +170,7 @@ void journal_commit_transaction(journal_t *journal)
{
transaction_t *commit_transaction;
struct journal_head *jh, *new_jh, *descriptor;
- struct buffer_head *wbuf[64];
+ struct buffer_head **wbuf = journal->j_wbuf;
int bufs;
int flags;
int err;
@@ -229,6 +296,22 @@ void journal_commit_transaction(journal_t *journal)
jbd_debug (3, "JBD: commit phase 2\n");
/*
+ * First, drop modified flag: all accesses to the buffers
+ * will be tracked for a new trasaction only -bzzz
+ */
+ spin_lock(&journal->j_list_lock);
+ if (commit_transaction->t_buffers) {
+ new_jh = jh = commit_transaction->t_buffers->b_tnext;
+ do {
+ J_ASSERT_JH(new_jh, new_jh->b_modified == 1 ||
+ new_jh->b_modified == 0);
+ new_jh->b_modified = 0;
+ new_jh = new_jh->b_tnext;
+ } while (new_jh != jh);
+ }
+ spin_unlock(&journal->j_list_lock);
+
+ /*
* Now start flushing things to disk, in the order they appear
* on the transaction lists. Data blocks go first.
*/
@@ -258,7 +341,7 @@ write_out_data:
BUFFER_TRACE(bh, "locked");
if (!inverted_lock(journal, bh))
goto write_out_data;
- __journal_unfile_buffer(jh);
+ __journal_temp_unlink_buffer(jh);
__journal_file_buffer(jh, commit_transaction,
BJ_Locked);
jbd_unlock_bh_state(bh);
@@ -271,7 +354,7 @@ write_out_data:
BUFFER_TRACE(bh, "start journal writeout");
get_bh(bh);
wbuf[bufs++] = bh;
- if (bufs == ARRAY_SIZE(wbuf)) {
+ if (bufs == journal->j_wbufsize) {
jbd_debug(2, "submit %d writes\n",
bufs);
spin_unlock(&journal->j_list_lock);
@@ -487,7 +570,7 @@ write_out_data:
/* If there's no more to do, or if the descriptor is full,
let the IO rip! */
- if (bufs == ARRAY_SIZE(wbuf) ||
+ if (bufs == journal->j_wbufsize ||
commit_transaction->t_buffers == NULL ||
space_left < sizeof(journal_block_tag_t) + 16) {
@@ -616,79 +699,17 @@ wait_for_iobuf:
jbd_debug(3, "JBD: commit phase 6\n");
- if (is_journal_aborted(journal))
- goto skip_commit;
-
- /* Done it all: now write the commit record. We should have
- * cleaned up our previous buffers by now, so if we are in abort
- * mode we can now just skip the rest of the journal write
- * entirely. */
+ if (journal_write_commit_record(journal, commit_transaction))
+ err = -EIO;
- descriptor = journal_get_descriptor_buffer(journal);
- if (!descriptor) {
+ if (err)
__journal_abort_hard(journal);
- goto skip_commit;
- }
-
- /* AKPM: buglet - add `i' to tmp! */
- for (i = 0; i < jh2bh(descriptor)->b_size; i += 512) {
- journal_header_t *tmp =
- (journal_header_t*)jh2bh(descriptor)->b_data;
- tmp->h_magic = cpu_to_be32(JFS_MAGIC_NUMBER);
- tmp->h_blocktype = cpu_to_be32(JFS_COMMIT_BLOCK);
- tmp->h_sequence = cpu_to_be32(commit_transaction->t_tid);
- }
-
- JBUFFER_TRACE(descriptor, "write commit block");
- {
- struct buffer_head *bh = jh2bh(descriptor);
- int ret;
- int barrier_done = 0;
-
- set_buffer_dirty(bh);
- if (journal->j_flags & JFS_BARRIER) {
- set_buffer_ordered(bh);
- barrier_done = 1;
- }
- ret = sync_dirty_buffer(bh);
- /* is it possible for another commit to fail at roughly
- * the same time as this one? If so, we don't want to
- * trust the barrier flag in the super, but instead want
- * to remember if we sent a barrier request
- */
- if (ret == -EOPNOTSUPP && barrier_done) {
- char b[BDEVNAME_SIZE];
-
- printk(KERN_WARNING
- "JBD: barrier-based sync failed on %s - "
- "disabling barriers\n",
- bdevname(journal->j_dev, b));
- spin_lock(&journal->j_state_lock);
- journal->j_flags &= ~JFS_BARRIER;
- spin_unlock(&journal->j_state_lock);
-
- /* And try again, without the barrier */
- clear_buffer_ordered(bh);
- set_buffer_uptodate(bh);
- set_buffer_dirty(bh);
- ret = sync_dirty_buffer(bh);
- }
- if (unlikely(ret == -EIO))
- err = -EIO;
- put_bh(bh); /* One for getblk() */
- journal_put_journal_head(descriptor);
- }
/* End of a transaction! Finally, we can do checkpoint
processing: any buffers committed as a result of this
transaction can be removed from any checkpoint list it was on
before. */
-skip_commit: /* The journal should be unlocked by now. */
-
- if (err)
- __journal_abort_hard(journal);
-
jbd_debug(3, "JBD: commit phase 7\n");
J_ASSERT(commit_transaction->t_sync_datalist == NULL);
diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c
index 71614e3184654..1e6f2e2ad4a33 100644
--- a/fs/jbd/journal.c
+++ b/fs/jbd/journal.c
@@ -721,6 +721,7 @@ journal_t * journal_init_dev(struct block_device *bdev,
{
journal_t *journal = journal_init_common();
struct buffer_head *bh;
+ int n;
if (!journal)
return NULL;
@@ -736,6 +737,17 @@ journal_t * journal_init_dev(struct block_device *bdev,
journal->j_sb_buffer = bh;
journal->j_superblock = (journal_superblock_t *)bh->b_data;
+ /* journal descriptor can store up to n blocks -bzzz */
+ n = journal->j_blocksize / sizeof(journal_block_tag_t);
+ journal->j_wbufsize = n;
+ journal->j_wbuf = kmalloc(n * sizeof(struct buffer_head*), GFP_KERNEL);
+ if (!journal->j_wbuf) {
+ printk(KERN_ERR "%s: Cant allocate bhs for commit thread\n",
+ __FUNCTION__);
+ kfree(journal);
+ journal = NULL;
+ }
+
return journal;
}
@@ -752,6 +764,7 @@ journal_t * journal_init_inode (struct inode *inode)
struct buffer_head *bh;
journal_t *journal = journal_init_common();
int err;
+ int n;
unsigned long blocknr;
if (!journal)
@@ -768,6 +781,17 @@ journal_t * journal_init_inode (struct inode *inode)
journal->j_maxlen = inode->i_size >> inode->i_sb->s_blocksize_bits;
journal->j_blocksize = inode->i_sb->s_blocksize;
+ /* journal descriptor can store up to n blocks -bzzz */
+ n = journal->j_blocksize / sizeof(journal_block_tag_t);
+ journal->j_wbufsize = n;
+ journal->j_wbuf = kmalloc(n * sizeof(struct buffer_head*), GFP_KERNEL);
+ if (!journal->j_wbuf) {
+ printk(KERN_ERR "%s: Cant allocate bhs for commit thread\n",
+ __FUNCTION__);
+ kfree(journal);
+ return NULL;
+ }
+
err = journal_bmap(journal, 0, &blocknr);
/* If that failed, give up */
if (err) {
@@ -1141,12 +1165,17 @@ void journal_destroy(journal_t *journal)
iput(journal->j_inode);
if (journal->j_revoke)
journal_destroy_revoke(journal);
+ kfree(journal->j_wbuf);
kfree(journal);
}
/**
*int journal_check_used_features () - Check if features specified are used.
+ * @journal: Journal to check.
+ * @compat: bitmask of compatible features
+ * @ro: bitmask of features that force read-only mount
+ * @incompat: bitmask of incompatible features
*
* Check whether the journal uses all of a given set of
* features. Return true (non-zero) if it does.
@@ -1174,6 +1203,10 @@ int journal_check_used_features (journal_t *journal, unsigned long compat,
/**
* int journal_check_available_features() - Check feature set in journalling layer
+ * @journal: Journal to check.
+ * @compat: bitmask of compatible features
+ * @ro: bitmask of features that force read-only mount
+ * @incompat: bitmask of incompatible features
*
* Check whether the journaling code supports the use of
* all of a given set of features on this journal. Return true
@@ -1206,6 +1239,10 @@ int journal_check_available_features (journal_t *journal, unsigned long compat,
/**
* int journal_set_features () - Mark a given journal feature in the superblock
+ * @journal: Journal to act on.
+ * @compat: bitmask of compatible features
+ * @ro: bitmask of features that force read-only mount
+ * @incompat: bitmask of incompatible features
*
* Mark a given journal feature as present on the
* superblock. Returns true if the requested features could be set.
@@ -1238,6 +1275,7 @@ int journal_set_features (journal_t *journal, unsigned long compat,
/**
* int journal_update_format () - Update on-disk journal structure.
+ * @journal: Journal to act on.
*
* Given an initialised but unloaded journal struct, poke about in the
* on-disk structure to update it to the most recent supported version.
@@ -1538,6 +1576,7 @@ int journal_errno(journal_t *journal)
/**
* int journal_clear_err () - clears the journal's error state
+ * @journal: journal to act on.
*
* An error must be cleared or Acked to take a FS out of readonly
* mode.
@@ -1557,6 +1596,7 @@ int journal_clear_err(journal_t *journal)
/**
* void journal_ack_err() - Ack journal err.
+ * @journal: journal to act on.
*
* An error must be cleared or Acked to take a FS out of readonly
* mode.
@@ -1575,11 +1615,7 @@ int journal_blocks_per_page(struct inode *inode)
}
/*
- * Simple support for retying memory allocations. Introduced to help to
- * debug different VM deadlock avoidance strategies.
- */
-/*
- * Simple support for retying memory allocations. Introduced to help to
+ * Simple support for retrying memory allocations. Introduced to help to
* debug different VM deadlock avoidance strategies.
*/
void * __jbd_kmalloc (const char *where, size_t size, int flags, int retry)
@@ -1767,6 +1803,7 @@ static void __journal_remove_journal_head(struct buffer_head *bh)
if (jh->b_transaction == NULL &&
jh->b_next_transaction == NULL &&
jh->b_cp_transaction == NULL) {
+ J_ASSERT_JH(jh, jh->b_jlist == BJ_None);
J_ASSERT_BH(bh, buffer_jbd(bh));
J_ASSERT_BH(bh, jh2bh(jh) == bh);
BUFFER_TRACE(bh, "remove journal_head");
diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c
index 2cc2b38b23245..932e7c1ef4a1c 100644
--- a/fs/jbd/transaction.c
+++ b/fs/jbd/transaction.c
@@ -522,7 +522,7 @@ static void jbd_unexpected_dirty_buffer(struct journal_head *jh)
*/
static int
do_get_write_access(handle_t *handle, struct journal_head *jh,
- int force_copy, int *credits)
+ int force_copy)
{
struct buffer_head *bh;
transaction_t *transaction;
@@ -604,11 +604,6 @@ repeat:
JBUFFER_TRACE(jh, "has frozen data");
J_ASSERT_JH(jh, jh->b_next_transaction == NULL);
jh->b_next_transaction = transaction;
-
- J_ASSERT_JH(jh, handle->h_buffer_credits > 0);
- handle->h_buffer_credits--;
- if (credits)
- (*credits)++;
goto done;
}
@@ -688,10 +683,6 @@ repeat:
jh->b_next_transaction = transaction;
}
- J_ASSERT(handle->h_buffer_credits > 0);
- handle->h_buffer_credits--;
- if (credits)
- (*credits)++;
/*
* Finally, if the buffer is not journaled right now, we need to make
@@ -742,6 +733,7 @@ out:
* int journal_get_write_access() - notify intent to modify a buffer for metadata (not data) update.
* @handle: transaction to add buffer modifications to
* @bh: bh to be used for metadata writes
+ * @credits: variable that will receive credits for the buffer
*
* Returns an error code or 0 on success.
*
@@ -749,8 +741,7 @@ out:
* because we're write()ing a buffer which is also part of a shared mapping.
*/
-int journal_get_write_access(handle_t *handle,
- struct buffer_head *bh, int *credits)
+int journal_get_write_access(handle_t *handle, struct buffer_head *bh)
{
struct journal_head *jh = journal_add_journal_head(bh);
int rc;
@@ -758,7 +749,7 @@ int journal_get_write_access(handle_t *handle,
/* We do not want to get caught playing with fields which the
* log thread also manipulates. Make sure that the buffer
* completes any outstanding IO before proceeding. */
- rc = do_get_write_access(handle, jh, 0, credits);
+ rc = do_get_write_access(handle, jh, 0);
journal_put_journal_head(jh);
return rc;
}
@@ -814,9 +805,6 @@ int journal_get_create_access(handle_t *handle, struct buffer_head *bh)
J_ASSERT_JH(jh, jh->b_next_transaction == NULL);
J_ASSERT_JH(jh, buffer_locked(jh2bh(jh)));
- J_ASSERT_JH(jh, handle->h_buffer_credits > 0);
- handle->h_buffer_credits--;
-
if (jh->b_transaction == NULL) {
jh->b_transaction = transaction;
JBUFFER_TRACE(jh, "file as BJ_Reserved");
@@ -869,8 +857,7 @@ out:
*
* Returns error number or 0 on success.
*/
-int journal_get_undo_access(handle_t *handle, struct buffer_head *bh,
- int *credits)
+int journal_get_undo_access(handle_t *handle, struct buffer_head *bh)
{
int err;
struct journal_head *jh = journal_add_journal_head(bh);
@@ -883,7 +870,7 @@ int journal_get_undo_access(handle_t *handle, struct buffer_head *bh,
* make sure that obtaining the committed_data is done
* atomically wrt. completion of any outstanding commits.
*/
- err = do_get_write_access(handle, jh, 1, credits);
+ err = do_get_write_access(handle, jh, 1);
if (err)
goto out;
@@ -1044,7 +1031,12 @@ int journal_dirty_data(handle_t *handle, struct buffer_head *bh)
/* journal_clean_data_list() may have got there first */
if (jh->b_transaction != NULL) {
JBUFFER_TRACE(jh, "unfile from commit");
- __journal_unfile_buffer(jh);
+ __journal_temp_unlink_buffer(jh);
+ /* It still points to the committing
+ * transaction; move it to this one so
+ * that the refile assert checks are
+ * happy. */
+ jh->b_transaction = handle->h_transaction;
}
/* The buffer will be refiled below */
@@ -1058,7 +1050,8 @@ int journal_dirty_data(handle_t *handle, struct buffer_head *bh)
if (jh->b_jlist != BJ_SyncData && jh->b_jlist != BJ_Locked) {
JBUFFER_TRACE(jh, "not on correct data list: unfile");
J_ASSERT_JH(jh, jh->b_jlist != BJ_Shadow);
- __journal_unfile_buffer(jh);
+ __journal_temp_unlink_buffer(jh);
+ jh->b_transaction = handle->h_transaction;
JBUFFER_TRACE(jh, "file as data");
__journal_file_buffer(jh, handle->h_transaction,
BJ_SyncData);
@@ -1111,6 +1104,17 @@ int journal_dirty_metadata(handle_t *handle, struct buffer_head *bh)
jbd_lock_bh_state(bh);
+ if (jh->b_modified == 0) {
+ /*
+ * This buffer's got modified and becoming part
+ * of the transaction. This needs to be done
+ * once a transaction -bzzz
+ */
+ jh->b_modified = 1;
+ J_ASSERT_JH(jh, handle->h_buffer_credits > 0);
+ handle->h_buffer_credits--;
+ }
+
/*
* fastpath, to avoid expensive locking. If this buffer is already
* on the running transaction's metadata list there is nothing to do.
@@ -1161,24 +1165,11 @@ out:
* journal_release_buffer: undo a get_write_access without any buffer
* updates, if the update decided in the end that it didn't need access.
*
- * The caller passes in the number of credits which should be put back for
- * this buffer (zero or one).
- *
- * We leave the buffer attached to t_reserved_list because even though this
- * handle doesn't want it, some other concurrent handle may want to journal
- * this buffer. If that handle is curently in between get_write_access() and
- * journal_dirty_metadata() then it expects the buffer to be reserved. If
- * we were to rip it off t_reserved_list here, the other handle will explode
- * when journal_dirty_metadata is presented with a non-reserved buffer.
- *
- * If nobody really wants to journal this buffer then it will be thrown
- * away at the start of commit.
*/
void
-journal_release_buffer(handle_t *handle, struct buffer_head *bh, int credits)
+journal_release_buffer(handle_t *handle, struct buffer_head *bh)
{
BUFFER_TRACE(bh, "entry");
- handle->h_buffer_credits += credits;
}
/**
@@ -1203,6 +1194,7 @@ int journal_forget (handle_t *handle, struct buffer_head *bh)
transaction_t *transaction = handle->h_transaction;
journal_t *journal = transaction->t_journal;
struct journal_head *jh;
+ int drop_reserve = 0;
int err = 0;
BUFFER_TRACE(bh, "entry");
@@ -1222,6 +1214,12 @@ int journal_forget (handle_t *handle, struct buffer_head *bh)
goto not_jbd;
}
+ /*
+ * The buffer's going from the transaction, we must drop
+ * all references -bzzz
+ */
+ jh->b_modified = 0;
+
if (jh->b_transaction == handle->h_transaction) {
J_ASSERT_JH(jh, !jh->b_frozen_data);
@@ -1233,7 +1231,7 @@ int journal_forget (handle_t *handle, struct buffer_head *bh)
JBUFFER_TRACE(jh, "belongs to current transaction: unfile");
- __journal_unfile_buffer(jh);
+ drop_reserve = 1;
/*
* We are no longer going to journal this buffer.
@@ -1248,15 +1246,17 @@ int journal_forget (handle_t *handle, struct buffer_head *bh)
*/
if (jh->b_cp_transaction) {
+ __journal_temp_unlink_buffer(jh);
__journal_file_buffer(jh, transaction, BJ_Forget);
} else {
+ __journal_unfile_buffer(jh);
journal_remove_journal_head(bh);
__brelse(bh);
if (!buffer_jbd(bh)) {
spin_unlock(&journal->j_list_lock);
jbd_unlock_bh_state(bh);
__bforget(bh);
- return 0;
+ goto drop;
}
}
} else if (jh->b_transaction) {
@@ -1271,6 +1271,7 @@ int journal_forget (handle_t *handle, struct buffer_head *bh)
if (jh->b_next_transaction) {
J_ASSERT(jh->b_next_transaction == transaction);
jh->b_next_transaction = NULL;
+ drop_reserve = 1;
}
}
@@ -1278,6 +1279,11 @@ not_jbd:
spin_unlock(&journal->j_list_lock);
jbd_unlock_bh_state(bh);
__brelse(bh);
+drop:
+ if (drop_reserve) {
+ /* no need to reserve log space for this block -bzzz */
+ handle->h_buffer_credits++;
+ }
return err;
}
@@ -1469,7 +1475,7 @@ __blist_del_buffer(struct journal_head **list, struct journal_head *jh)
*
* Called under j_list_lock. The journal may not be locked.
*/
-void __journal_unfile_buffer(struct journal_head *jh)
+void __journal_temp_unlink_buffer(struct journal_head *jh)
{
struct journal_head **list = NULL;
transaction_t *transaction;
@@ -1486,7 +1492,7 @@ void __journal_unfile_buffer(struct journal_head *jh)
switch (jh->b_jlist) {
case BJ_None:
- goto out;
+ return;
case BJ_SyncData:
list = &transaction->t_sync_datalist;
break;
@@ -1519,7 +1525,11 @@ void __journal_unfile_buffer(struct journal_head *jh)
jh->b_jlist = BJ_None;
if (test_clear_buffer_jbddirty(bh))
mark_buffer_dirty(bh); /* Expose it to the VM */
-out:
+}
+
+void __journal_unfile_buffer(struct journal_head *jh)
+{
+ __journal_temp_unlink_buffer(jh);
jh->b_transaction = NULL;
}
@@ -1578,7 +1588,7 @@ out:
* int journal_try_to_free_buffers() - try to free page buffers.
* @journal: journal for operation
* @page: to try and free
- * @gfp_mask: 'IO' mode for try_to_free_buffers()
+ * @unused_gfp_mask: unused
*
*
* For all the buffers on this page,
@@ -1775,10 +1785,10 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh)
JBUFFER_TRACE(jh, "checkpointed: add to BJ_Forget");
ret = __dispose_buffer(jh,
journal->j_running_transaction);
+ journal_put_journal_head(jh);
spin_unlock(&journal->j_list_lock);
jbd_unlock_bh_state(bh);
spin_unlock(&journal->j_state_lock);
- journal_put_journal_head(jh);
return ret;
} else {
/* There is no currently-running transaction. So the
@@ -1789,10 +1799,10 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh)
JBUFFER_TRACE(jh, "give to committing trans");
ret = __dispose_buffer(jh,
journal->j_committing_transaction);
+ journal_put_journal_head(jh);
spin_unlock(&journal->j_list_lock);
jbd_unlock_bh_state(bh);
spin_unlock(&journal->j_state_lock);
- journal_put_journal_head(jh);
return ret;
} else {
/* The orphan record's transaction has
@@ -1813,10 +1823,10 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh)
journal->j_running_transaction);
jh->b_next_transaction = NULL;
}
+ journal_put_journal_head(jh);
spin_unlock(&journal->j_list_lock);
jbd_unlock_bh_state(bh);
spin_unlock(&journal->j_state_lock);
- journal_put_journal_head(jh);
return 0;
} else {
/* Good, the buffer belongs to the running transaction.
@@ -1929,7 +1939,7 @@ void __journal_file_buffer(struct journal_head *jh,
}
if (jh->b_transaction)
- __journal_unfile_buffer(jh);
+ __journal_temp_unlink_buffer(jh);
jh->b_transaction = transaction;
switch (jlist) {
@@ -2012,7 +2022,7 @@ void __journal_refile_buffer(struct journal_head *jh)
*/
was_dirty = test_clear_buffer_jbddirty(bh);
- __journal_unfile_buffer(jh);
+ __journal_temp_unlink_buffer(jh);
jh->b_transaction = jh->b_next_transaction;
jh->b_next_transaction = NULL;
__journal_file_buffer(jh, jh->b_transaction, BJ_Metadata);
diff --git a/fs/jffs/inode-v23.c b/fs/jffs/inode-v23.c
index 8bb849a0dbdd1..bfbeb4c86e03a 100644
--- a/fs/jffs/inode-v23.c
+++ b/fs/jffs/inode-v23.c
@@ -334,7 +334,7 @@ out:
} /* jffs_notify_change() */
-struct inode *
+static struct inode *
jffs_new_inode(const struct inode * dir, struct jffs_raw_inode *raw_inode,
int * err)
{
@@ -376,7 +376,7 @@ jffs_new_inode(const struct inode * dir, struct jffs_raw_inode *raw_inode,
}
/* Get statistics of the file system. */
-int
+static int
jffs_statfs(struct super_block *sb, struct kstatfs *buf)
{
struct jffs_control *c = (struct jffs_control *) sb->s_fs_info;
@@ -410,7 +410,7 @@ jffs_statfs(struct super_block *sb, struct kstatfs *buf)
/* Rename a file. */
-int
+static int
jffs_rename(struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_dentry)
{
@@ -1739,7 +1739,7 @@ jffs_read_inode(struct inode *inode)
}
-void
+static void
jffs_delete_inode(struct inode *inode)
{
struct jffs_file *f;
@@ -1762,7 +1762,7 @@ jffs_delete_inode(struct inode *inode)
}
-void
+static void
jffs_write_super(struct super_block *sb)
{
struct jffs_control *c = (struct jffs_control *)sb->s_fs_info;
diff --git a/fs/jffs/intrep.c b/fs/jffs/intrep.c
index 273a3c9cc5b0f..8cc6893fc56cd 100644
--- a/fs/jffs/intrep.c
+++ b/fs/jffs/intrep.c
@@ -72,7 +72,7 @@
#include "jffs_fm.h"
long no_jffs_node = 0;
-long no_jffs_file = 0;
+static long no_jffs_file = 0;
#if defined(JFFS_MEMORY_DEBUG) && JFFS_MEMORY_DEBUG
long no_jffs_control = 0;
long no_jffs_raw_inode = 0;
@@ -85,6 +85,32 @@ long no_name = 0;
static int jffs_scan_flash(struct jffs_control *c);
static int jffs_update_file(struct jffs_file *f, struct jffs_node *node);
+static int jffs_build_file(struct jffs_file *f);
+static int jffs_free_file(struct jffs_file *f);
+static int jffs_free_node_list(struct jffs_file *f);
+static int jffs_garbage_collect_now(struct jffs_control *c);
+static int jffs_insert_file_into_hash(struct jffs_file *f);
+static int jffs_remove_redundant_nodes(struct jffs_file *f);
+
+/* Is there enough space on the flash? */
+static inline int JFFS_ENOUGH_SPACE(struct jffs_control *c, __u32 space)
+{
+ struct jffs_fmcontrol *fmc = c->fmc;
+
+ while (1) {
+ if ((fmc->flash_size - (fmc->used_size + fmc->dirty_size))
+ >= fmc->min_free_size + space) {
+ return 1;
+ }
+ if (fmc->dirty_size < fmc->sector_size)
+ return 0;
+
+ if (jffs_garbage_collect_now(c)) {
+ D1(printk("JFFS_ENOUGH_SPACE: jffs_garbage_collect_now() failed.\n"));
+ return 0;
+ }
+ }
+}
#if CONFIG_JFFS_FS_VERBOSE > 0
static __u8
@@ -331,7 +357,7 @@ flash_erase_region(struct mtd_info *mtd, loff_t start,
}
/* This routine calculates checksums in JFFS. */
-__u32
+static __u32
jffs_checksum(const void *data, int size)
{
__u32 sum = 0;
@@ -344,7 +370,7 @@ jffs_checksum(const void *data, int size)
}
-int
+static int
jffs_checksum_flash(struct mtd_info *mtd, loff_t start, int size, __u32 *result)
{
__u32 sum = 0;
@@ -646,7 +672,7 @@ jffs_build_fs_fail:
a (even) higher degree of confidence in your mount process.
A higher number would of course slow down your mount.
*/
-int check_partly_erased_sectors(struct jffs_fmcontrol *fmc){
+static int check_partly_erased_sectors(struct jffs_fmcontrol *fmc){
#define NUM_REREADS 4 /* see note above */
#define READ_AHEAD_BYTES 4096 /* must be a multiple of 4,
@@ -1478,7 +1504,7 @@ jffs_classify_node(struct jffs_node *node)
/* Remove redundant nodes from a file. Mark the on-flash memory
as dirty. */
-int
+static int
jffs_remove_redundant_nodes(struct jffs_file *f)
{
struct jffs_node *newest_node;
@@ -1532,7 +1558,7 @@ jffs_remove_redundant_nodes(struct jffs_file *f)
/* Insert a file into the hash table. */
-int
+static int
jffs_insert_file_into_hash(struct jffs_file *f)
{
int i = f->ino % f->c->hash_len;
@@ -1580,7 +1606,7 @@ jffs_insert_file_into_tree(struct jffs_file *f)
/* Remove a file from the hash table. */
-int
+static int
jffs_unlink_file_from_hash(struct jffs_file *f)
{
D3(printk("jffs_unlink_file_from_hash(): f: 0x%p, "
@@ -2038,7 +2064,7 @@ jffs_foreach_file(struct jffs_control *c, int (*func)(struct jffs_file *))
/* Free all nodes associated with a file. */
-int
+static int
jffs_free_node_list(struct jffs_file *f)
{
struct jffs_node *node;
@@ -2058,7 +2084,7 @@ jffs_free_node_list(struct jffs_file *f)
/* Free a file and its name. */
-int
+static int
jffs_free_file(struct jffs_file *f)
{
D3(printk("jffs_free_file: f #%u, \"%s\"\n",
@@ -2073,7 +2099,7 @@ jffs_free_file(struct jffs_file *f)
return 0;
}
-long
+static long
jffs_get_file_count(void)
{
return no_jffs_file;
@@ -2127,7 +2153,7 @@ jffs_file_count(struct jffs_file *f)
/* Build up a file's range list from scratch by going through the
version list. */
-int
+static int
jffs_build_file(struct jffs_file *f)
{
struct jffs_node *n;
@@ -2481,7 +2507,6 @@ jffs_update_file(struct jffs_file *f, struct jffs_node *node)
return 0;
}
-
/* Print the contents of a node. */
void
jffs_print_node(struct jffs_node *n)
@@ -2541,6 +2566,7 @@ jffs_print_raw_inode(struct jffs_raw_inode *raw_inode)
/* Print the contents of a file. */
+#if 0
int
jffs_print_file(struct jffs_file *f)
{
@@ -2580,7 +2606,7 @@ jffs_print_file(struct jffs_file *f)
D(printk("}\n"));
return 0;
}
-
+#endif /* 0 */
void
jffs_print_hash_table(struct jffs_control *c)
@@ -2655,7 +2681,7 @@ jffs_print_memory_allocation_statistics(void)
/* Rewrite `size' bytes, and begin at `node'. */
-int
+static int
jffs_rewrite_data(struct jffs_file *f, struct jffs_node *node, __u32 size)
{
struct jffs_control *c = f->c;
@@ -2858,7 +2884,7 @@ retry:
process and is often called multiple times at each occasion of a
garbage collect. */
-int
+static int
jffs_garbage_collect_next(struct jffs_control *c)
{
struct jffs_fmcontrol *fmc = c->fmc;
@@ -3097,7 +3123,7 @@ jffs_clear_end_of_node(struct jffs_control *c, __u32 erase_size)
} /* jffs_clear_end_of_node() */
/* Try to erase as much as possible of the dirt in the flash memory. */
-long
+static long
jffs_try_to_erase(struct jffs_control *c)
{
struct jffs_fmcontrol *fmc = c->fmc;
@@ -3198,7 +3224,7 @@ jffs_try_to_erase(struct jffs_control *c)
collection can be. */
-int
+static int
jffs_garbage_collect_now(struct jffs_control *c)
{
struct jffs_fmcontrol *fmc = c->fmc;
diff --git a/fs/jffs/intrep.h b/fs/jffs/intrep.h
index cbd4ed790490d..4ae97b17911c5 100644
--- a/fs/jffs/intrep.h
+++ b/fs/jffs/intrep.h
@@ -20,9 +20,6 @@
struct jffs_node *jffs_alloc_node(void);
void jffs_free_node(struct jffs_node *n);
int jffs_get_node_inuse(void);
-long jffs_get_file_count(void);
-
-__u32 jffs_checksum(const void *data, int size);
void jffs_cleanup_control(struct jffs_control *c);
int jffs_build_fs(struct super_block *sb);
@@ -36,15 +33,9 @@ struct jffs_file *jffs_find_child(struct jffs_file *dir, const char *name, int l
void jffs_free_node(struct jffs_node *node);
int jffs_foreach_file(struct jffs_control *c, int (*func)(struct jffs_file *));
-int jffs_free_node_list(struct jffs_file *f);
-int jffs_free_file(struct jffs_file *f);
int jffs_possibly_delete_file(struct jffs_file *f);
-int jffs_build_file(struct jffs_file *f);
-int jffs_insert_file_into_hash(struct jffs_file *f);
int jffs_insert_file_into_tree(struct jffs_file *f);
-int jffs_unlink_file_from_hash(struct jffs_file *f);
int jffs_unlink_file_from_tree(struct jffs_file *f);
-int jffs_remove_redundant_nodes(struct jffs_file *f);
int jffs_file_count(struct jffs_file *f);
int jffs_write_node(struct jffs_control *c, struct jffs_node *node,
@@ -56,32 +47,13 @@ int jffs_read_data(struct jffs_file *f, unsigned char *buf, __u32 read_offset, _
/* Garbage collection stuff. */
int jffs_garbage_collect_thread(void *c);
void jffs_garbage_collect_trigger(struct jffs_control *c);
-int jffs_garbage_collect_now(struct jffs_control *c);
-
-/* Is there enough space on the flash? */
-static inline int JFFS_ENOUGH_SPACE(struct jffs_control *c, __u32 space)
-{
- struct jffs_fmcontrol *fmc = c->fmc;
-
- while (1) {
- if ((fmc->flash_size - (fmc->used_size + fmc->dirty_size))
- >= fmc->min_free_size + space) {
- return 1;
- }
- if (fmc->dirty_size < fmc->sector_size)
- return 0;
-
- if (jffs_garbage_collect_now(c)) {
- D1(printk("JFFS_ENOUGH_SPACE: jffs_garbage_collect_now() failed.\n"));
- return 0;
- }
- }
-}
/* For debugging purposes. */
void jffs_print_node(struct jffs_node *n);
void jffs_print_raw_inode(struct jffs_raw_inode *raw_inode);
+#if 0
int jffs_print_file(struct jffs_file *f);
+#endif /* 0 */
void jffs_print_hash_table(struct jffs_control *c);
void jffs_print_tree(struct jffs_file *first_file, int indent);
diff --git a/fs/jffs/jffs_fm.c b/fs/jffs/jffs_fm.c
index fae439d48398a..0cab8da49d3c4 100644
--- a/fs/jffs/jffs_fm.c
+++ b/fs/jffs/jffs_fm.c
@@ -25,6 +25,9 @@
static int jffs_mark_obsolete(struct jffs_fmcontrol *fmc, __u32 fm_offset);
#endif
+static struct jffs_fm *jffs_alloc_fm(void);
+static void jffs_free_fm(struct jffs_fm *n);
+
extern kmem_cache_t *fm_cache;
extern kmem_cache_t *node_cache;
@@ -602,7 +605,7 @@ jffs_mark_obsolete(struct jffs_fmcontrol *fmc, __u32 fm_offset)
/* check if it's possible to erase the wanted range, and if not, return
* the range that IS erasable, or a negative error code.
*/
-long
+static long
jffs_flash_erasable_size(struct mtd_info *mtd, __u32 offset, __u32 size)
{
u_long ssize;
@@ -700,7 +703,7 @@ jffs_erasable_size(struct jffs_fmcontrol *fmc)
return (ret >= 0 ? ret : 0);
}
-struct jffs_fm *jffs_alloc_fm(void)
+static struct jffs_fm *jffs_alloc_fm(void)
{
struct jffs_fm *fm;
@@ -710,7 +713,7 @@ struct jffs_fm *jffs_alloc_fm(void)
return fm;
}
-void jffs_free_fm(struct jffs_fm *n)
+static void jffs_free_fm(struct jffs_fm *n)
{
kmem_cache_free(fm_cache,n);
DJM(no_jffs_fm--);
@@ -778,6 +781,7 @@ jffs_print_fm(struct jffs_fm *fm)
D(printk("}\n"));
}
+#if 0
void
jffs_print_node_ref(struct jffs_node_ref *ref)
{
@@ -787,3 +791,5 @@ jffs_print_node_ref(struct jffs_node_ref *ref)
D(printk(" 0x%p, /* next */\n", ref->next));
D(printk("}\n"));
}
+#endif /* 0 */
+
diff --git a/fs/jffs/jffs_fm.h b/fs/jffs/jffs_fm.h
index 6c433787ccfe9..bc291c4318225 100644
--- a/fs/jffs/jffs_fm.h
+++ b/fs/jffs/jffs_fm.h
@@ -64,10 +64,6 @@
-void jffs_free_fm(struct jffs_fm *n);
-struct jffs_fm *jffs_alloc_fm(void);
-
-
struct jffs_node_ref
{
struct jffs_node *node;
@@ -145,6 +141,8 @@ void jffs_fmfree_partly(struct jffs_fmcontrol *fmc, struct jffs_fm *fm,
void jffs_print_fmcontrol(struct jffs_fmcontrol *fmc);
void jffs_print_fm(struct jffs_fm *fm);
+#if 0
void jffs_print_node_ref(struct jffs_node_ref *ref);
+#endif /* 0 */
#endif /* __LINUX_JFFS_FM_H__ */
diff --git a/fs/jffs2/compr.c b/fs/jffs2/compr.c
index 48732546dc035..af922a9618ac0 100644
--- a/fs/jffs2/compr.c
+++ b/fs/jffs2/compr.c
@@ -23,16 +23,6 @@ static LIST_HEAD(jffs2_compressor_list);
/* Actual compression mode */
static int jffs2_compression_mode = JFFS2_COMPR_MODE_PRIORITY;
-void jffs2_set_compression_mode(int mode)
-{
- jffs2_compression_mode = mode;
-}
-
-int jffs2_get_compression_mode(void)
-{
- return jffs2_compression_mode;
-}
-
/* Statistics for blocks stored without compression */
static uint32_t none_stat_compr_blocks=0,none_stat_decompr_blocks=0,none_stat_compr_size=0;
diff --git a/fs/jffs2/compr.h b/fs/jffs2/compr.h
index 6777d8c915247..89ceeed201eb8 100644
--- a/fs/jffs2/compr.h
+++ b/fs/jffs2/compr.h
@@ -41,9 +41,6 @@
#define JFFS2_COMPR_MODE_PRIORITY 1
#define JFFS2_COMPR_MODE_SIZE 2
-void jffs2_set_compression_mode(int mode);
-int jffs2_get_compression_mode(void);
-
struct jffs2_compressor {
struct list_head list;
int priority; /* used by prirority comr. mode */
diff --git a/fs/jffs2/compr_rtime.c b/fs/jffs2/compr_rtime.c
index 3bfe27773e42a..3931294186668 100644
--- a/fs/jffs2/compr_rtime.c
+++ b/fs/jffs2/compr_rtime.c
@@ -29,8 +29,10 @@
#include "compr.h"
/* _compress returns the compressed size, -1 if bigger */
-int jffs2_rtime_compress(unsigned char *data_in, unsigned char *cpage_out,
- uint32_t *sourcelen, uint32_t *dstlen, void *model)
+static int jffs2_rtime_compress(unsigned char *data_in,
+ unsigned char *cpage_out,
+ uint32_t *sourcelen, uint32_t *dstlen,
+ void *model)
{
short positions[256];
int outpos = 0;
@@ -69,8 +71,10 @@ int jffs2_rtime_compress(unsigned char *data_in, unsigned char *cpage_out,
}
-int jffs2_rtime_decompress(unsigned char *data_in, unsigned char *cpage_out,
- uint32_t srclen, uint32_t destlen, void *model)
+static int jffs2_rtime_decompress(unsigned char *data_in,
+ unsigned char *cpage_out,
+ uint32_t srclen, uint32_t destlen,
+ void *model)
{
short positions[256];
int outpos = 0;
diff --git a/fs/jffs2/erase.c b/fs/jffs2/erase.c
index 8a00b27622dcb..41451e8bf3612 100644
--- a/fs/jffs2/erase.c
+++ b/fs/jffs2/erase.c
@@ -33,7 +33,8 @@ static void jffs2_erase_succeeded(struct jffs2_sb_info *c, struct jffs2_eraseblo
static void jffs2_free_all_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb);
static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb);
-void jffs2_erase_block(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
+static void jffs2_erase_block(struct jffs2_sb_info *c,
+ struct jffs2_eraseblock *jeb)
{
int ret;
uint32_t bad_offset;
diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c
index 1fc3cf673279a..0c607c1388f44 100644
--- a/fs/jffs2/file.c
+++ b/fs/jffs2/file.c
@@ -25,6 +25,11 @@
extern int generic_file_open(struct inode *, struct file *) __attribute__((weak));
extern loff_t generic_file_llseek(struct file *file, loff_t offset, int origin) __attribute__((weak));
+static int jffs2_commit_write (struct file *filp, struct page *pg,
+ unsigned start, unsigned end);
+static int jffs2_prepare_write (struct file *filp, struct page *pg,
+ unsigned start, unsigned end);
+static int jffs2_readpage (struct file *filp, struct page *pg);
int jffs2_fsync(struct file *filp, struct dentry *dentry, int datasync)
{
@@ -65,7 +70,7 @@ struct address_space_operations jffs2_file_address_operations =
.commit_write = jffs2_commit_write
};
-int jffs2_do_readpage_nolock (struct inode *inode, struct page *pg)
+static int jffs2_do_readpage_nolock (struct inode *inode, struct page *pg)
{
struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
@@ -105,7 +110,7 @@ int jffs2_do_readpage_unlock(struct inode *inode, struct page *pg)
}
-int jffs2_readpage (struct file *filp, struct page *pg)
+static int jffs2_readpage (struct file *filp, struct page *pg)
{
struct jffs2_inode_info *f = JFFS2_INODE_INFO(pg->mapping->host);
int ret;
@@ -116,7 +121,8 @@ int jffs2_readpage (struct file *filp, struct page *pg)
return ret;
}
-int jffs2_prepare_write (struct file *filp, struct page *pg, unsigned start, unsigned end)
+static int jffs2_prepare_write (struct file *filp, struct page *pg,
+ unsigned start, unsigned end)
{
struct inode *inode = pg->mapping->host;
struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
@@ -198,7 +204,8 @@ int jffs2_prepare_write (struct file *filp, struct page *pg, unsigned start, uns
return ret;
}
-int jffs2_commit_write (struct file *filp, struct page *pg, unsigned start, unsigned end)
+static int jffs2_commit_write (struct file *filp, struct page *pg,
+ unsigned start, unsigned end)
{
/* Actually commit the write from the page cache page we're looking at.
* For now, we write the full page out each time. It sucks, but it's simple
diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c
index 3a72e6f4d50dd..30ab233fe4230 100644
--- a/fs/jffs2/fs.c
+++ b/fs/jffs2/fs.c
@@ -25,6 +25,7 @@
#include <linux/crc32.h>
#include "nodelist.h"
+static int jffs2_flash_setup(struct jffs2_sb_info *c);
static int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
{
@@ -644,7 +645,7 @@ void jffs2_gc_release_page(struct jffs2_sb_info *c,
page_cache_release(pg);
}
-int jffs2_flash_setup(struct jffs2_sb_info *c) {
+static int jffs2_flash_setup(struct jffs2_sb_info *c) {
int ret = 0;
if (jffs2_cleanmarker_oob(c)) {
diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h
index bb49491b88df6..a4864d05ea926 100644
--- a/fs/jffs2/nodelist.h
+++ b/fs/jffs2/nodelist.h
@@ -460,7 +460,6 @@ void jffs2_rotate_lists(struct jffs2_sb_info *c);
int jffs2_do_mount_fs(struct jffs2_sb_info *c);
/* erase.c */
-void jffs2_erase_block(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb);
void jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count);
#ifdef CONFIG_JFFS2_FS_NAND
diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h
index 55c0982a909be..03b0acc37b736 100644
--- a/fs/jffs2/os-linux.h
+++ b/fs/jffs2/os-linux.h
@@ -173,11 +173,7 @@ extern struct file_operations jffs2_file_operations;
extern struct inode_operations jffs2_file_inode_operations;
extern struct address_space_operations jffs2_file_address_operations;
int jffs2_fsync(struct file *, struct dentry *, int);
-int jffs2_do_readpage_nolock (struct inode *inode, struct page *pg);
int jffs2_do_readpage_unlock (struct inode *inode, struct page *pg);
-int jffs2_readpage (struct file *, struct page *);
-int jffs2_prepare_write (struct file *, struct page *, unsigned, unsigned);
-int jffs2_commit_write (struct file *, struct page *, unsigned, unsigned);
/* ioctl.c */
int jffs2_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
@@ -208,7 +204,6 @@ unsigned char *jffs2_gc_fetch_page(struct jffs2_sb_info *c,
void jffs2_gc_release_page(struct jffs2_sb_info *c,
unsigned char *pg,
unsigned long *priv);
-int jffs2_flash_setup(struct jffs2_sb_info *c);
void jffs2_flash_cleanup(struct jffs2_sb_info *c);
diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c
index 5aa0a718d1345..c8128069ecf0a 100644
--- a/fs/jffs2/wbuf.c
+++ b/fs/jffs2/wbuf.c
@@ -1087,7 +1087,7 @@ static struct nand_oobinfo jffs2_oobinfo_docecc = {
};
-int jffs2_nand_set_oobinfo(struct jffs2_sb_info *c)
+static int jffs2_nand_set_oobinfo(struct jffs2_sb_info *c)
{
struct nand_oobinfo *oinfo = &c->mtd->oobinfo;
diff --git a/fs/jfs/inode.c b/fs/jfs/inode.c
index 69e397ef94f6e..7bc906677b0d5 100644
--- a/fs/jfs/inode.c
+++ b/fs/jfs/inode.c
@@ -52,8 +52,6 @@ void jfs_read_inode(struct inode *inode)
} else if (S_ISDIR(inode->i_mode)) {
inode->i_op = &jfs_dir_inode_operations;
inode->i_fop = &jfs_dir_operations;
- inode->i_mapping->a_ops = &jfs_aops;
- mapping_set_gfp_mask(inode->i_mapping, GFP_NOFS);
} else if (S_ISLNK(inode->i_mode)) {
if (inode->i_size >= IDATASIZE) {
inode->i_op = &page_symlink_inode_operations;
@@ -176,7 +174,6 @@ jfs_get_blocks(struct inode *ip, sector_t lblock, unsigned long max_blocks,
struct buffer_head *bh_result, int create)
{
s64 lblock64 = lblock;
- int no_size_check = 0;
int rc = 0;
int take_locks;
xad_t xad;
@@ -185,11 +182,11 @@ jfs_get_blocks(struct inode *ip, sector_t lblock, unsigned long max_blocks,
s32 xlen;
/*
- * If this is a special inode (imap, dmap) or directory,
+ * If this is a special inode (imap, dmap)
* the lock should already be taken
*/
- take_locks = ((JFS_IP(ip)->fileset != AGGREGATE_I) &&
- !S_ISDIR(ip->i_mode));
+ take_locks = (JFS_IP(ip)->fileset != AGGREGATE_I);
+
/*
* Take appropriate lock on inode
*/
@@ -200,16 +197,8 @@ jfs_get_blocks(struct inode *ip, sector_t lblock, unsigned long max_blocks,
IREAD_LOCK(ip);
}
- /*
- * A directory's "data" is the inode index table, but i_size is the
- * size of the d-tree, so don't check the offset against i_size
- */
- if (S_ISDIR(ip->i_mode))
- no_size_check = 1;
-
- if ((no_size_check ||
- ((lblock64 << ip->i_sb->s_blocksize_bits) < ip->i_size)) &&
- (xtLookup(ip, lblock64, max_blocks, &xflag, &xaddr, &xlen, no_size_check)
+ if (((lblock64 << ip->i_sb->s_blocksize_bits) < ip->i_size) &&
+ (xtLookup(ip, lblock64, max_blocks, &xflag, &xaddr, &xlen, 0)
== 0) && xlen) {
if (xflag & XAD_NOTRECORDED) {
if (!create)
@@ -286,7 +275,7 @@ static int jfs_get_block(struct inode *ip, sector_t lblock,
static int jfs_writepage(struct page *page, struct writeback_control *wbc)
{
- return block_write_full_page(page, jfs_get_block, wbc);
+ return nobh_writepage(page, jfs_get_block, wbc);
}
static int jfs_writepages(struct address_space *mapping,
diff --git a/fs/jfs/jfs_dtree.c b/fs/jfs/jfs_dtree.c
index 23b916a697548..e357890adfb2b 100644
--- a/fs/jfs/jfs_dtree.c
+++ b/fs/jfs/jfs_dtree.c
@@ -268,7 +268,7 @@ static struct dir_table_slot *find_index(struct inode *ip, u32 index,
return NULL;
}
- if (jfs_ip->next_index <= (MAX_INLINE_DIRTABLE_ENTRY + 1)) {
+ if (jfs_dirtable_inline(ip)) {
/*
* Inline directory table
*/
@@ -2828,7 +2828,7 @@ void dtInitRoot(tid_t tid, struct inode *ip, u32 idotdot)
* the old directory table.
*/
if (DO_INDEX(ip)) {
- if (jfs_ip->next_index > (MAX_INLINE_DIRTABLE_ENTRY + 1)) {
+ if (!jfs_dirtable_inline(ip)) {
struct tblock *tblk = tid_to_tblock(tid);
/*
* We're playing games with the tid's xflag. If
diff --git a/fs/jfs/jfs_incore.h b/fs/jfs/jfs_incore.h
index 2357d95c2a902..ebd77c1bed663 100644
--- a/fs/jfs/jfs_incore.h
+++ b/fs/jfs/jfs_incore.h
@@ -178,6 +178,11 @@ static inline struct jfs_inode_info *JFS_IP(struct inode *inode)
return list_entry(inode, struct jfs_inode_info, vfs_inode);
}
+static inline int jfs_dirtable_inline(struct inode *inode)
+{
+ return (JFS_IP(inode)->next_index <= (MAX_INLINE_DIRTABLE_ENTRY + 1));
+}
+
static inline struct jfs_sb_info *JFS_SBI(struct super_block *sb)
{
return sb->s_fs_info;
@@ -189,5 +194,4 @@ static inline int isReadOnly(struct inode *inode)
return 0;
return 1;
}
-
#endif /* _H_JFS_INCORE */
diff --git a/fs/jfs/jfs_logmgr.c b/fs/jfs/jfs_logmgr.c
index dfa771c272a23..b6a6869ebb4f5 100644
--- a/fs/jfs/jfs_logmgr.c
+++ b/fs/jfs/jfs_logmgr.c
@@ -67,6 +67,7 @@
#include <linux/buffer_head.h> /* for sync_blockdev() */
#include <linux/bio.h>
#include <linux/suspend.h>
+#include <linux/delay.h>
#include "jfs_incore.h"
#include "jfs_filsys.h"
#include "jfs_metapage.h"
@@ -1118,6 +1119,7 @@ int lmLogOpen(struct super_block *sb)
}
memset(log, 0, sizeof(struct jfs_log));
INIT_LIST_HEAD(&log->sb_list);
+ init_waitqueue_head(&log->syncwait);
/*
* external log as separate logical volume
@@ -1191,6 +1193,7 @@ static int open_inline_log(struct super_block *sb)
return -ENOMEM;
memset(log, 0, sizeof(struct jfs_log));
INIT_LIST_HEAD(&log->sb_list);
+ init_waitqueue_head(&log->syncwait);
set_bit(log_INLINELOG, &log->flag);
log->bdev = sb->s_bdev;
@@ -1228,6 +1231,7 @@ static int open_dummy_log(struct super_block *sb)
}
memset(dummy_log, 0, sizeof(struct jfs_log));
INIT_LIST_HEAD(&dummy_log->sb_list);
+ init_waitqueue_head(&dummy_log->syncwait);
dummy_log->no_integrity = 1;
/* Make up some stuff */
dummy_log->base = 0;
@@ -1290,8 +1294,6 @@ int lmLogInit(struct jfs_log * log)
INIT_LIST_HEAD(&log->synclist);
- init_waitqueue_head(&log->syncwait);
-
INIT_LIST_HEAD(&log->cqueue);
log->flush_tblk = NULL;
@@ -1612,8 +1614,7 @@ void jfs_flush_journal(struct jfs_log *log, int wait)
*/
if ((!list_empty(&log->cqueue)) || !list_empty(&log->synclist)) {
for (i = 0; i < 800; i++) { /* Too much? */
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(HZ / 4);
+ msleep(250);
if (list_empty(&log->cqueue) &&
list_empty(&log->synclist))
break;
diff --git a/fs/jfs/jfs_metapage.c b/fs/jfs/jfs_metapage.c
index 1cd9bdff2f598..4c0a3ac75c081 100644
--- a/fs/jfs/jfs_metapage.c
+++ b/fs/jfs/jfs_metapage.c
@@ -21,6 +21,7 @@
#include <linux/init.h>
#include <linux/buffer_head.h>
#include <linux/mempool.h>
+#include <linux/delay.h>
#include "jfs_incore.h"
#include "jfs_superblock.h"
#include "jfs_filsys.h"
@@ -242,14 +243,14 @@ again:
mp = search_hash(hash_ptr, mapping, lblock);
if (mp) {
page_found:
- mp->count++;
- lock_metapage(mp);
- spin_unlock(&meta_lock);
if (test_bit(META_stale, &mp->flag)) {
- release_metapage(mp);
- yield(); /* Let other waiters release it, too */
+ spin_unlock(&meta_lock);
+ msleep(1);
goto again;
}
+ mp->count++;
+ lock_metapage(mp);
+ spin_unlock(&meta_lock);
if (test_bit(META_discard, &mp->flag)) {
if (!new) {
jfs_error(inode->i_sb,
@@ -461,7 +462,6 @@ void release_metapage(struct metapage * mp)
}
if (mp->page) {
- /* Releasing spinlock, we have to check mp->count later */
set_bit(META_stale, &mp->flag);
spin_unlock(&meta_lock);
kunmap(mp->page);
@@ -498,12 +498,6 @@ void release_metapage(struct metapage * mp)
list_del(&mp->synclist);
LOGSYNC_UNLOCK(log);
}
- if (mp->count) {
- /* Someone else is trying to get this metpage */
- unlock_metapage(mp);
- spin_unlock(&meta_lock);
- return;
- }
remove_from_hash(mp, meta_hash(mp->mapping, mp->index));
spin_unlock(&meta_lock);
@@ -532,12 +526,8 @@ again:
mp = search_hash(hash_ptr, mapping, lblock);
if (mp) {
if (test_bit(META_stale, &mp->flag)) {
- /* Racing with release_metapage */
- mp->count++;
- lock_metapage(mp);
spin_unlock(&meta_lock);
- /* racing release_metapage should be done now */
- release_metapage(mp);
+ msleep(1);
goto again;
}
diff --git a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c
index 1d870dc3dfaa5..f40301d93f740 100644
--- a/fs/jfs/jfs_txnmgr.c
+++ b/fs/jfs/jfs_txnmgr.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) International Business Machines Corp., 2000-2004
+ * Copyright (C) International Business Machines Corp., 2000-2005
* Portions Copyright (C) Christoph Hellwig, 2001-2002
*
* This program is free software; you can redistribute it and/or modify
@@ -93,15 +93,15 @@ static struct {
} TxStat;
#endif
-static int nTxBlock = 512; /* number of transaction blocks */
+static int nTxBlock = -1; /* number of transaction blocks */
module_param(nTxBlock, int, 0);
MODULE_PARM_DESC(nTxBlock,
- "Number of transaction blocks (default:512, max:65536)");
+ "Number of transaction blocks (max:65536)");
-static int nTxLock = 4096; /* number of transaction locks */
+static int nTxLock = -1; /* number of transaction locks */
module_param(nTxLock, int, 0);
MODULE_PARM_DESC(nTxLock,
- "Number of transaction locks (default:4096, max:65536)");
+ "Number of transaction locks (max:65536)");
struct tblock *TxBlock; /* transaction block table */
static int TxLockLWM; /* Low water mark for number of txLocks used */
@@ -124,6 +124,7 @@ static DEFINE_SPINLOCK(jfsTxnLock);
DECLARE_WAIT_QUEUE_HEAD(jfs_sync_thread_wait);
DECLARE_WAIT_QUEUE_HEAD(jfs_commit_thread_wait);
+static int jfs_commit_thread_waking;
/*
* Retry logic exist outside these macros to protect from spurrious wakeups.
@@ -249,6 +250,25 @@ static void txLockFree(lid_t lid)
int txInit(void)
{
int k, size;
+ struct sysinfo si;
+
+ /* Set defaults for nTxLock and nTxBlock if unset */
+
+ if (nTxLock == -1) {
+ if (nTxBlock == -1) {
+ /* Base default on memory size */
+ si_meminfo(&si);
+ if (si.totalram > (256 * 1024)) /* 1 GB */
+ nTxLock = 64 * 1024;
+ else
+ nTxLock = si.totalram >> 2;
+ } else if (nTxBlock > (8 * 1024))
+ nTxLock = 64 * 1024;
+ else
+ nTxLock = nTxBlock << 3;
+ }
+ if (nTxBlock == -1)
+ nTxBlock = nTxLock >> 3;
/* Verify tunable parameters */
if (nTxBlock < 16)
@@ -259,6 +279,9 @@ int txInit(void)
nTxLock = 256; /* No one should set it this low */
if (nTxLock > 65536)
nTxLock = 65536;
+
+ printk(KERN_INFO "JFS: nTxBlock = %d, nTxLock = %d\n",
+ nTxBlock, nTxLock);
/*
* initialize transaction block (tblock) table
*
@@ -266,8 +289,8 @@ int txInit(void)
* tid = 0 is reserved.
*/
TxLockLWM = (nTxLock * 4) / 10;
- TxLockHWM = (nTxLock * 8) / 10;
- TxLockVHWM = (nTxLock * 9) / 10;
+ TxLockHWM = (nTxLock * 7) / 10;
+ TxLockVHWM = (nTxLock * 8) / 10;
size = sizeof(struct tblock) * nTxBlock;
TxBlock = (struct tblock *) vmalloc(size);
@@ -1544,7 +1567,7 @@ static int dataLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
/* log after-image for logredo(): */
lrd->type = cpu_to_le16(LOG_REDOPAGE);
- if (JFS_IP(tlck->ip)->next_index < MAX_INLINE_DIRTABLE_ENTRY) {
+ if (jfs_dirtable_inline(tlck->ip)) {
/*
* The table has been truncated, we've must have deleted
* the last entry, so don't bother logging this
@@ -2732,6 +2755,7 @@ int jfs_lazycommit(void *arg)
do {
LAZY_LOCK(flags);
+ jfs_commit_thread_waking = 0; /* OK to wake another thread */
while (!list_empty(&TxAnchor.unlock_queue)) {
WorkDone = 0;
list_for_each_entry(tblk, &TxAnchor.unlock_queue,
@@ -2772,6 +2796,8 @@ int jfs_lazycommit(void *arg)
if (!WorkDone)
break;
}
+ /* In case a wakeup came while all threads were active */
+ jfs_commit_thread_waking = 0;
if (current->flags & PF_FREEZE) {
LAZY_UNLOCK(flags);
@@ -2804,10 +2830,13 @@ void txLazyUnlock(struct tblock * tblk)
list_add_tail(&tblk->cqueue, &TxAnchor.unlock_queue);
/*
* Don't wake up a commit thread if there is already one servicing
- * this superblock.
+ * this superblock, or if the last one we woke up hasn't started yet.
*/
- if (!(JFS_SBI(tblk->sb)->commit_state & IN_LAZYCOMMIT))
+ if (!(JFS_SBI(tblk->sb)->commit_state & IN_LAZYCOMMIT) &&
+ !jfs_commit_thread_waking) {
+ jfs_commit_thread_waking = 1;
wake_up(&jfs_commit_thread_wait);
+ }
LAZY_UNLOCK(flags);
}
diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c
index b7c5fb74194b6..8413a368f4493 100644
--- a/fs/jfs/namei.c
+++ b/fs/jfs/namei.c
@@ -262,8 +262,6 @@ static int jfs_mkdir(struct inode *dip, struct dentry *dentry, int mode)
ip->i_nlink = 2; /* for '.' */
ip->i_op = &jfs_dir_inode_operations;
ip->i_fop = &jfs_dir_operations;
- ip->i_mapping->a_ops = &jfs_aops;
- mapping_set_gfp_mask(ip->i_mapping, GFP_NOFS);
insert_inode_hash(ip);
mark_inode_dirty(ip);
diff --git a/fs/jfs/super.c b/fs/jfs/super.c
index 45b372ddf7cd5..5856866e24fc8 100644
--- a/fs/jfs/super.c
+++ b/fs/jfs/super.c
@@ -235,7 +235,7 @@ static match_table_t tokens = {
static int parse_options(char *options, struct super_block *sb, s64 *newLVSize,
int *flag)
{
- void *nls_map = NULL;
+ void *nls_map = (void *)-1; /* -1: no change; NULL: none */
char *p;
struct jfs_sb_info *sbi = JFS_SBI(sb);
@@ -263,12 +263,17 @@ static int parse_options(char *options, struct super_block *sb, s64 *newLVSize,
/* Don't do anything ;-) */
break;
case Opt_iocharset:
- if (nls_map) /* specified iocharset twice! */
+ if (nls_map && nls_map != (void *) -1)
unload_nls(nls_map);
- nls_map = load_nls(args[0].from);
- if (!nls_map) {
- printk(KERN_ERR "JFS: charset not found\n");
- goto cleanup;
+ if (!strcmp(args[0].from, "none"))
+ nls_map = NULL;
+ else {
+ nls_map = load_nls(args[0].from);
+ if (!nls_map) {
+ printk(KERN_ERR
+ "JFS: charset not found\n");
+ goto cleanup;
+ }
}
break;
case Opt_resize:
@@ -318,7 +323,7 @@ static int parse_options(char *options, struct super_block *sb, s64 *newLVSize,
}
}
- if (nls_map) {
+ if (nls_map != (void *) -1) {
/* Discard old (if remount) */
if (sbi->nls_tab)
unload_nls(sbi->nls_tab);
@@ -327,7 +332,7 @@ static int parse_options(char *options, struct super_block *sb, s64 *newLVSize,
return 1;
cleanup:
- if (nls_map)
+ if (nls_map && nls_map != (void *) -1)
unload_nls(nls_map);
return 0;
}
@@ -622,7 +627,7 @@ static int __init init_jfs_fs(void)
if (commit_threads < 1)
commit_threads = num_online_cpus();
- else if (commit_threads > MAX_COMMIT_THREADS)
+ if (commit_threads > MAX_COMMIT_THREADS)
commit_threads = MAX_COMMIT_THREADS;
for (i = 0; i < commit_threads; i++) {
diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c
index 5fc0a3b0f8704..a4407619b1f16 100644
--- a/fs/lockd/clntproc.c
+++ b/fs/lockd/clntproc.c
@@ -312,6 +312,7 @@ static int nlm_wait_on_grace(wait_queue_head_t *queue)
prepare_to_wait(queue, &wait, TASK_INTERRUPTIBLE);
if (!signalled ()) {
schedule_timeout(NLMCLNT_GRACE_WAIT);
+ try_to_freeze(PF_FREEZE);
if (!signalled ())
status = 0;
}
@@ -322,14 +323,13 @@ static int nlm_wait_on_grace(wait_queue_head_t *queue)
/*
* Generic NLM call
*/
-int
+static int
nlmclnt_call(struct nlm_rqst *req, u32 proc)
{
struct nlm_host *host = req->a_host;
struct rpc_clnt *clnt;
struct nlm_args *argp = &req->a_args;
struct nlm_res *resp = &req->a_res;
- struct file *filp = argp->lock.fl.fl_file;
struct rpc_message msg = {
.rpc_argp = argp,
.rpc_resp = resp,
@@ -339,9 +339,6 @@ nlmclnt_call(struct nlm_rqst *req, u32 proc)
dprintk("lockd: call procedure %d on %s\n",
(int)proc, host->h_name);
- if (filp)
- msg.rpc_cred = nfs_file_cred(filp);
-
do {
if (host->h_reclaiming && !argp->reclaim)
goto in_grace_period;
@@ -428,14 +425,13 @@ nlmsvc_async_call(struct nlm_rqst *req, u32 proc, rpc_action callback)
return status;
}
-int
+static int
nlmclnt_async_call(struct nlm_rqst *req, u32 proc, rpc_action callback)
{
struct nlm_host *host = req->a_host;
struct rpc_clnt *clnt;
struct nlm_args *argp = &req->a_args;
struct nlm_res *resp = &req->a_res;
- struct file *file = argp->lock.fl.fl_file;
struct rpc_message msg = {
.rpc_argp = argp,
.rpc_resp = resp,
@@ -450,11 +446,9 @@ nlmclnt_async_call(struct nlm_rqst *req, u32 proc, rpc_action callback)
return -ENOLCK;
msg.rpc_proc = &clnt->cl_procinfo[proc];
- /* bootstrap and kick off the async RPC call */
- if (file)
- msg.rpc_cred = nfs_file_cred(file);
/* 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);
if (status < 0)
nlm_release_host(host);
@@ -516,6 +510,24 @@ static void nlmclnt_locks_init_private(struct file_lock *fl, struct nlm_host *ho
fl->fl_ops = &nlmclnt_lock_ops;
}
+static void do_vfs_lock(struct file_lock *fl)
+{
+ int res = 0;
+ switch (fl->fl_flags & (FL_POSIX|FL_FLOCK)) {
+ case FL_POSIX:
+ res = posix_lock_file_wait(fl->fl_file, fl);
+ break;
+ case FL_FLOCK:
+ res = flock_lock_file_wait(fl->fl_file, fl);
+ break;
+ default:
+ BUG();
+ }
+ if (res < 0)
+ printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n",
+ __FUNCTION__);
+}
+
/*
* LOCK: Try to create a lock
*
@@ -564,9 +576,7 @@ nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl)
fl->fl_u.nfs_fl.state = host->h_state;
fl->fl_u.nfs_fl.flags |= NFS_LCK_GRANTED;
fl->fl_flags |= FL_SLEEP;
- if (posix_lock_file_wait(fl->fl_file, fl) < 0)
- printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n",
- __FUNCTION__);
+ do_vfs_lock(fl);
}
status = nlm_stat_to_errno(resp->status);
out:
@@ -635,7 +645,7 @@ nlmclnt_unlock(struct nlm_rqst *req, struct file_lock *fl)
nlmclnt_unlock_callback);
/* Hrmf... Do the unlock early since locks_remove_posix()
* really expects us to free the lock synchronously */
- posix_lock_file(fl->fl_file, fl);
+ do_vfs_lock(fl);
if (status < 0) {
nlmclnt_release_lockargs(req);
kfree(req);
@@ -648,7 +658,7 @@ nlmclnt_unlock(struct nlm_rqst *req, struct file_lock *fl)
if (status < 0)
return status;
- posix_lock_file(fl->fl_file, fl);
+ do_vfs_lock(fl);
if (resp->status == NLM_LCK_GRANTED)
return 0;
diff --git a/fs/lockd/host.c b/fs/lockd/host.c
index 54f25ae2ad649..52707c5ad6ea7 100644
--- a/fs/lockd/host.c
+++ b/fs/lockd/host.c
@@ -110,7 +110,6 @@ nlm_lookup_host(int server, struct sockaddr_in *sin,
host->h_addr.sin_port = 0; /* ouch! */
host->h_version = version;
host->h_proto = proto;
- host->h_authflavor = RPC_AUTH_UNIX;
host->h_rpcclnt = NULL;
init_MUTEX(&host->h_sema);
host->h_nextrebind = jiffies + NLM_HOST_REBIND;
@@ -191,8 +190,9 @@ nlm_bind_host(struct nlm_host *host)
xprt_set_timeout(&xprt->timeout, 5, nlmsvc_timeout);
+ /* Existing NLM servers accept AUTH_UNIX only */
clnt = rpc_create_client(xprt, host->h_name, &nlm_program,
- host->h_version, host->h_authflavor);
+ host->h_version, RPC_AUTH_UNIX);
if (IS_ERR(clnt)) {
xprt_destroy(xprt);
goto forgetit;
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
index d3ee09c5196eb..b82e470912e83 100644
--- a/fs/lockd/svc.c
+++ b/fs/lockd/svc.c
@@ -403,6 +403,38 @@ static int param_set_##name(const char *val, struct kernel_param *kp) \
return 0; \
}
+static inline int is_callback(u32 proc)
+{
+ return proc == NLMPROC_GRANTED
+ || proc == NLMPROC_GRANTED_MSG
+ || proc == NLMPROC_TEST_RES
+ || proc == NLMPROC_LOCK_RES
+ || proc == NLMPROC_CANCEL_RES
+ || proc == NLMPROC_UNLOCK_RES
+ || proc == NLMPROC_NSM_NOTIFY;
+}
+
+
+static int lockd_authenticate(struct svc_rqst *rqstp)
+{
+ rqstp->rq_client = NULL;
+ switch (rqstp->rq_authop->flavour) {
+ case RPC_AUTH_NULL:
+ case RPC_AUTH_UNIX:
+ if (rqstp->rq_proc == 0)
+ return SVC_OK;
+ if (is_callback(rqstp->rq_proc)) {
+ /* Leave it to individual procedures to
+ * call nlmsvc_lookup_host(rqstp)
+ */
+ return SVC_OK;
+ }
+ return svc_set_client(rqstp);
+ }
+ return SVC_DENIED;
+}
+
+
param_set_min_max(port, int, simple_strtol, 0, 65535)
param_set_min_max(grace_period, unsigned long, simple_strtoul,
nlm_grace_period_min, nlm_grace_period_max)
@@ -483,4 +515,5 @@ static struct svc_program nlmsvc_program = {
.pg_name = "lockd", /* service name */
.pg_class = "nfsd", /* share authentication with nfsd */
.pg_stats = &nlmsvc_stats, /* stats table */
+ .pg_authenticate = &lockd_authenticate /* export authentication */
};
diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c
index de3f50afa4247..49f959796b665 100644
--- a/fs/lockd/svclock.c
+++ b/fs/lockd/svclock.c
@@ -641,7 +641,6 @@ nlmsvc_grant_reply(struct svc_rqst *rqstp, struct nlm_cookie *cookie, u32 status
} else {
/* Lock is now held by client, or has been rejected.
* In both cases, the block should be removed. */
- file->f_count++;
up(&file->f_sema);
if (status == NLM_LCK_GRANTED)
nlmsvc_delete_block(block, 0);
diff --git a/fs/locks.c b/fs/locks.c
index c42d125f7ec13..1792ce547af7b 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -406,9 +406,16 @@ static void lease_release_private_callback(struct file_lock *fl)
fl->fl_file->f_owner.signum = 0;
}
+int lease_mylease_callback(struct file_lock *fl, struct file_lock *try)
+{
+ return fl->fl_file == try->fl_file;
+}
+
struct lock_manager_operations lease_manager_ops = {
.fl_break = lease_break_callback,
.fl_release_private = lease_release_private_callback,
+ .fl_mylease = lease_mylease_callback,
+ .fl_change = lease_modify,
};
/*
@@ -1058,7 +1065,7 @@ int locks_mandatory_area(int read_write, struct inode *inode,
EXPORT_SYMBOL(locks_mandatory_area);
/* We already had a lease on this file; just change its type */
-static int lease_modify(struct file_lock **before, int arg)
+int lease_modify(struct file_lock **before, int arg)
{
struct file_lock *fl = *before;
int error = assign_type(fl, arg);
@@ -1071,6 +1078,8 @@ static int lease_modify(struct file_lock **before, int arg)
return 0;
}
+EXPORT_SYMBOL(lease_modify);
+
static void time_out_leases(struct inode *inode)
{
struct file_lock **before;
@@ -1090,24 +1099,6 @@ static void time_out_leases(struct inode *inode)
}
}
- /**
-* remove_lease - let time_out_leases remove the lease.
-* @@file_lock: the lease to remove
-*/
-void remove_lease(struct file_lock *fl)
-{
- lock_kernel();
- if (!fl || !IS_LEASE(fl))
- goto out;
- fl->fl_type = F_UNLCK | F_INPROGRESS;
- fl->fl_break_time = jiffies - 10;
- time_out_leases(fl->fl_file->f_dentry->d_inode);
-out:
- unlock_kernel();
-}
-
-EXPORT_SYMBOL(remove_lease);
-
/**
* __break_lease - revoke all outstanding leases on file
* @inode: the inode of the file to return
@@ -1172,10 +1163,8 @@ int __break_lease(struct inode *inode, unsigned int mode)
if (fl->fl_type != future) {
fl->fl_type = future;
fl->fl_break_time = break_time;
- if (fl->fl_lmops && fl->fl_lmops->fl_break)
- fl->fl_lmops->fl_break(fl);
- else /* lease must have lmops break callback */
- BUG();
+ /* lease must have lmops break callback */
+ fl->fl_lmops->fl_break(fl);
}
}
@@ -1317,7 +1306,7 @@ int __setlease(struct file *filp, long arg, struct file_lock **flp)
for (before = &inode->i_flock;
((fl = *before) != NULL) && IS_LEASE(fl);
before = &fl->fl_next) {
- if (fl->fl_file == filp)
+ if (lease->fl_lmops->fl_mylease(fl, lease))
my_before = before;
else if (fl->fl_type == (F_INPROGRESS | F_UNLCK))
/*
@@ -1335,7 +1324,7 @@ int __setlease(struct file *filp, long arg, struct file_lock **flp)
goto out;
if (my_before != NULL) {
- error = lease_modify(my_before, arg);
+ error = lease->fl_lmops->fl_change(my_before, arg);
goto out;
}
@@ -1876,8 +1865,13 @@ void locks_remove_flock(struct file *filp)
return;
if (filp->f_op && filp->f_op->flock) {
- struct file_lock fl = { .fl_flags = FL_FLOCK,
- .fl_type = F_UNLCK };
+ struct file_lock fl = {
+ .fl_pid = current->tgid,
+ .fl_file = filp,
+ .fl_flags = FL_FLOCK,
+ .fl_type = F_UNLCK,
+ .fl_end = OFFSET_MAX,
+ };
filp->f_op->flock(filp, F_SETLKW, &fl);
}
diff --git a/fs/mbcache.c b/fs/mbcache.c
index 801cc23478326..f9e4d2700cd81 100644
--- a/fs/mbcache.c
+++ b/fs/mbcache.c
@@ -225,7 +225,7 @@ mb_cache_shrink_fn(int nr_to_scan, unsigned int gfp_mask)
e_lru_list), gfp_mask);
}
out:
- return count;
+ return (count / 100) * sysctl_vfs_cache_pressure;
}
diff --git a/fs/mpage.c b/fs/mpage.c
index 4bbf15ee91fe0..e7d8d1a776061 100644
--- a/fs/mpage.c
+++ b/fs/mpage.c
@@ -98,7 +98,8 @@ struct bio *mpage_bio_submit(int rw, struct bio *bio)
static struct bio *
mpage_alloc(struct block_device *bdev,
- sector_t first_sector, int nr_vecs, int gfp_flags)
+ sector_t first_sector, int nr_vecs,
+ unsigned int __nocast gfp_flags)
{
struct bio *bio;
@@ -386,8 +387,9 @@ EXPORT_SYMBOL(mpage_readpage);
* just allocate full-size (16-page) BIOs.
*/
static struct bio *
-mpage_writepage(struct bio *bio, struct page *page, get_block_t get_block,
- sector_t *last_block_in_bio, int *ret, struct writeback_control *wbc)
+__mpage_writepage(struct bio *bio, struct page *page, get_block_t get_block,
+ sector_t *last_block_in_bio, int *ret, struct writeback_control *wbc,
+ writepage_t writepage_fn)
{
struct address_space *mapping = page->mapping;
struct inode *inode = page->mapping->host;
@@ -580,7 +582,13 @@ alloc_new:
confused:
if (bio)
bio = mpage_bio_submit(WRITE, bio);
- *ret = page->mapping->a_ops->writepage(page, wbc);
+
+ if (writepage_fn) {
+ *ret = (*writepage_fn)(page, wbc);
+ } else {
+ *ret = -EAGAIN;
+ goto out;
+ }
/*
* The caller has a ref on the inode, so *mapping is stable
*/
@@ -619,6 +627,15 @@ int
mpage_writepages(struct address_space *mapping,
struct writeback_control *wbc, get_block_t get_block)
{
+ return __mpage_writepages(mapping, wbc, get_block,
+ mapping->a_ops->writepage);
+}
+
+int
+__mpage_writepages(struct address_space *mapping,
+ struct writeback_control *wbc, get_block_t get_block,
+ writepage_t writepage_fn)
+{
struct backing_dev_info *bdi = mapping->backing_dev_info;
struct bio *bio = NULL;
sector_t last_block_in_bio = 0;
@@ -706,8 +723,9 @@ retry:
&mapping->flags);
}
} else {
- bio = mpage_writepage(bio, page, get_block,
- &last_block_in_bio, &ret, wbc);
+ bio = __mpage_writepage(bio, page, get_block,
+ &last_block_in_bio, &ret, wbc,
+ writepage_fn);
}
if (ret || (--(wbc->nr_to_write) <= 0))
done = 1;
@@ -735,3 +753,20 @@ retry:
return ret;
}
EXPORT_SYMBOL(mpage_writepages);
+EXPORT_SYMBOL(__mpage_writepages);
+
+int mpage_writepage(struct page *page, get_block_t get_block,
+ struct writeback_control *wbc)
+{
+ int ret = 0;
+ struct bio *bio;
+ sector_t last_block_in_bio = 0;
+
+ bio = __mpage_writepage(NULL, page, get_block,
+ &last_block_in_bio, &ret, wbc, NULL);
+ if (bio)
+ mpage_bio_submit(WRITE, bio);
+
+ return ret;
+}
+EXPORT_SYMBOL(mpage_writepage);
diff --git a/fs/msdos/namei.c b/fs/msdos/namei.c
index cb452cf390567..154f511c72457 100644
--- a/fs/msdos/namei.c
+++ b/fs/msdos/namei.c
@@ -137,29 +137,29 @@ static int msdos_format_name(const unsigned char *name, int len,
/***** Locates a directory entry. Uses unformatted name. */
static int msdos_find(struct inode *dir, const unsigned char *name, int len,
- struct buffer_head **bh, struct msdos_dir_entry **de,
- loff_t *i_pos)
+ struct fat_slot_info *sinfo)
{
+ struct msdos_sb_info *sbi = MSDOS_SB(dir->i_sb);
unsigned char msdos_name[MSDOS_NAME];
- char dotsOK;
- int res;
+ int err;
- dotsOK = MSDOS_SB(dir->i_sb)->options.dotsOK;
- res = msdos_format_name(name, len, msdos_name,
- &MSDOS_SB(dir->i_sb)->options);
- if (res < 0)
+ err = msdos_format_name(name, len, msdos_name, &sbi->options);
+ if (err)
return -ENOENT;
- res = fat_scan(dir, msdos_name, bh, de, i_pos);
- if (!res && dotsOK) {
+
+ err = fat_scan(dir, msdos_name, sinfo);
+ if (!err && sbi->options.dotsOK) {
if (name[0] == '.') {
- if (!((*de)->attr & ATTR_HIDDEN))
- res = -ENOENT;
+ if (!(sinfo->de->attr & ATTR_HIDDEN))
+ err = -ENOENT;
} else {
- if ((*de)->attr & ATTR_HIDDEN)
- res = -ENOENT;
+ if (sinfo->de->attr & ATTR_HIDDEN)
+ err = -ENOENT;
}
+ if (err)
+ brelse(sinfo->bh);
}
- return res;
+ return err;
}
/*
@@ -221,31 +221,30 @@ static struct dentry *msdos_lookup(struct inode *dir, struct dentry *dentry,
struct nameidata *nd)
{
struct super_block *sb = dir->i_sb;
+ struct fat_slot_info sinfo;
struct inode *inode = NULL;
- struct msdos_dir_entry *de;
- struct buffer_head *bh = NULL;
- loff_t i_pos;
int res;
dentry->d_op = &msdos_dentry_operations;
lock_kernel();
- res = msdos_find(dir, dentry->d_name.name, dentry->d_name.len, &bh,
- &de, &i_pos);
+ res = msdos_find(dir, dentry->d_name.name, dentry->d_name.len, &sinfo);
if (res == -ENOENT)
goto add;
if (res < 0)
goto out;
- inode = fat_build_inode(sb, de, i_pos, &res);
- if (res)
+ inode = fat_build_inode(sb, sinfo.de, sinfo.i_pos);
+ brelse(sinfo.bh);
+ if (IS_ERR(inode)) {
+ res = PTR_ERR(inode);
goto out;
+ }
add:
res = 0;
dentry = d_splice_alias(inode, dentry);
if (dentry)
dentry->d_op = &msdos_dentry_operations;
out:
- brelse(bh);
unlock_kernel();
if (!res)
return dentry;
@@ -254,31 +253,38 @@ out:
/***** Creates a directory entry (name is already formatted). */
static int msdos_add_entry(struct inode *dir, const unsigned char *name,
- struct buffer_head **bh,
- struct msdos_dir_entry **de,
- loff_t *i_pos, int is_dir, int is_hid)
+ int is_dir, int is_hid, int cluster,
+ struct timespec *ts, struct fat_slot_info *sinfo)
{
- int res;
-
- res = fat_add_entries(dir, 1, bh, de, i_pos);
- if (res < 0)
- return res;
+ struct msdos_dir_entry de;
+ __le16 time, date;
+ int err;
- /*
- * XXX all times should be set by caller upon successful completion.
- */
- dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC;
- mark_inode_dirty(dir);
-
- memcpy((*de)->name, name, MSDOS_NAME);
- (*de)->attr = is_dir ? ATTR_DIR : ATTR_ARCH;
+ memcpy(de.name, name, MSDOS_NAME);
+ de.attr = is_dir ? ATTR_DIR : ATTR_ARCH;
if (is_hid)
- (*de)->attr |= ATTR_HIDDEN;
- (*de)->start = 0;
- (*de)->starthi = 0;
- fat_date_unix2dos(dir->i_mtime.tv_sec, &(*de)->time, &(*de)->date);
- (*de)->size = 0;
- mark_buffer_dirty(*bh);
+ de.attr |= ATTR_HIDDEN;
+ de.lcase = 0;
+ fat_date_unix2dos(ts->tv_sec, &time, &date);
+ de.cdate = de.adate = 0;
+ de.ctime = 0;
+ de.ctime_cs = 0;
+ de.time = time;
+ de.date = date;
+ de.start = cpu_to_le16(cluster);
+ de.starthi = cpu_to_le16(cluster >> 16);
+ de.size = 0;
+
+ err = fat_add_entries(dir, &de, 1, sinfo);
+ if (err)
+ return err;
+
+ dir->i_ctime = dir->i_mtime = *ts;
+ if (IS_DIRSYNC(dir))
+ (void)fat_sync_inode(dir);
+ else
+ mark_inode_dirty(dir);
+
return 0;
}
@@ -287,320 +293,366 @@ static int msdos_create(struct inode *dir, struct dentry *dentry, int mode,
struct nameidata *nd)
{
struct super_block *sb = dir->i_sb;
- struct buffer_head *bh;
- struct msdos_dir_entry *de;
struct inode *inode;
- loff_t i_pos;
- int res, is_hid;
+ struct fat_slot_info sinfo;
+ struct timespec ts;
unsigned char msdos_name[MSDOS_NAME];
+ int err, is_hid;
lock_kernel();
- res = msdos_format_name(dentry->d_name.name, dentry->d_name.len,
+
+ err = msdos_format_name(dentry->d_name.name, dentry->d_name.len,
msdos_name, &MSDOS_SB(sb)->options);
- if (res < 0) {
- unlock_kernel();
- return res;
- }
+ if (err)
+ goto out;
is_hid = (dentry->d_name.name[0] == '.') && (msdos_name[0] != '.');
/* Have to do it due to foo vs. .foo conflicts */
- if (fat_scan(dir, msdos_name, &bh, &de, &i_pos) >= 0) {
- brelse(bh);
- unlock_kernel();
- return -EINVAL;
- }
- inode = NULL;
- res = msdos_add_entry(dir, msdos_name, &bh, &de, &i_pos, 0, is_hid);
- if (res) {
- unlock_kernel();
- return res;
+ if (!fat_scan(dir, msdos_name, &sinfo)) {
+ brelse(sinfo.bh);
+ err = -EINVAL;
+ goto out;
}
- inode = fat_build_inode(dir->i_sb, de, i_pos, &res);
- brelse(bh);
- if (!inode) {
- unlock_kernel();
- return res;
+
+ ts = CURRENT_TIME_SEC;
+ err = msdos_add_entry(dir, msdos_name, 0, is_hid, 0, &ts, &sinfo);
+ if (err)
+ goto out;
+ inode = fat_build_inode(sb, sinfo.de, sinfo.i_pos);
+ brelse(sinfo.bh);
+ if (IS_ERR(inode)) {
+ err = PTR_ERR(inode);
+ goto out;
}
- inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
- mark_inode_dirty(inode);
+ inode->i_mtime = inode->i_atime = inode->i_ctime = ts;
+ /* timestamp is already written, so mark_inode_dirty() is unneeded. */
+
d_instantiate(dentry, inode);
+out:
unlock_kernel();
- return 0;
+ return err;
}
/***** Remove a directory */
static int msdos_rmdir(struct inode *dir, struct dentry *dentry)
{
struct inode *inode = dentry->d_inode;
- loff_t i_pos;
- int res;
- struct buffer_head *bh;
- struct msdos_dir_entry *de;
+ struct fat_slot_info sinfo;
+ int err;
- bh = NULL;
lock_kernel();
- res = msdos_find(dir, dentry->d_name.name, dentry->d_name.len,
- &bh, &de, &i_pos);
- if (res < 0)
- goto rmdir_done;
/*
* Check whether the directory is not in use, then check
* whether it is empty.
*/
- res = fat_dir_empty(inode);
- if (res)
- goto rmdir_done;
+ err = fat_dir_empty(inode);
+ if (err)
+ goto out;
+ err = msdos_find(dir, dentry->d_name.name, dentry->d_name.len, &sinfo);
+ if (err)
+ goto out;
- de->name[0] = DELETED_FLAG;
- mark_buffer_dirty(bh);
- fat_detach(inode);
- inode->i_nlink = 0;
- inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC;
+ err = fat_remove_entries(dir, &sinfo); /* and releases bh */
+ if (err)
+ goto out;
dir->i_nlink--;
- mark_inode_dirty(inode);
- mark_inode_dirty(dir);
- res = 0;
-rmdir_done:
- brelse(bh);
+ inode->i_nlink = 0;
+ inode->i_ctime = CURRENT_TIME_SEC;
+ fat_detach(inode);
+out:
unlock_kernel();
- return res;
+
+ return err;
}
/***** Make a directory */
static int msdos_mkdir(struct inode *dir, struct dentry *dentry, int mode)
{
struct super_block *sb = dir->i_sb;
- struct buffer_head *bh;
- struct msdos_dir_entry *de;
+ struct fat_slot_info sinfo;
struct inode *inode;
- int res, is_hid;
unsigned char msdos_name[MSDOS_NAME];
- loff_t i_pos;
+ struct timespec ts;
+ int err, is_hid, cluster;
lock_kernel();
- res = msdos_format_name(dentry->d_name.name, dentry->d_name.len,
+
+ err = msdos_format_name(dentry->d_name.name, dentry->d_name.len,
msdos_name, &MSDOS_SB(sb)->options);
- if (res < 0) {
- unlock_kernel();
- return res;
- }
+ if (err)
+ goto out;
is_hid = (dentry->d_name.name[0] == '.') && (msdos_name[0] != '.');
/* foo vs .foo situation */
- if (fat_scan(dir, msdos_name, &bh, &de, &i_pos) >= 0)
- goto out_exist;
-
- res = msdos_add_entry(dir, msdos_name, &bh, &de, &i_pos, 1, is_hid);
- if (res)
- goto out_unlock;
- inode = fat_build_inode(dir->i_sb, de, i_pos, &res);
- if (!inode) {
- brelse(bh);
- goto out_unlock;
+ if (!fat_scan(dir, msdos_name, &sinfo)) {
+ brelse(sinfo.bh);
+ err = -EINVAL;
+ goto out;
}
- res = 0;
+ ts = CURRENT_TIME_SEC;
+ cluster = fat_alloc_new_dir(dir, &ts);
+ if (cluster < 0) {
+ err = cluster;
+ goto out;
+ }
+ err = msdos_add_entry(dir, msdos_name, 1, is_hid, cluster, &ts, &sinfo);
+ if (err)
+ goto out_free;
dir->i_nlink++;
- inode->i_nlink = 2; /* no need to mark them dirty */
- res = fat_new_dir(inode, dir, 0);
- if (res)
- goto mkdir_error;
+ inode = fat_build_inode(sb, sinfo.de, sinfo.i_pos);
+ brelse(sinfo.bh);
+ if (IS_ERR(inode)) {
+ err = PTR_ERR(inode);
+ /* the directory was completed, just return a error */
+ goto out;
+ }
+ inode->i_nlink = 2;
+ inode->i_mtime = inode->i_atime = inode->i_ctime = ts;
+ /* timestamp is already written, so mark_inode_dirty() is unneeded. */
- brelse(bh);
d_instantiate(dentry, inode);
- res = 0;
-out_unlock:
unlock_kernel();
- return res;
-
-mkdir_error:
- inode->i_nlink = 0;
- inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC;
- dir->i_nlink--;
- mark_inode_dirty(inode);
- mark_inode_dirty(dir);
- de->name[0] = DELETED_FLAG;
- mark_buffer_dirty(bh);
- brelse(bh);
- fat_detach(inode);
- iput(inode);
- goto out_unlock;
+ return 0;
-out_exist:
- brelse(bh);
- res = -EINVAL;
- goto out_unlock;
+out_free:
+ fat_free_clusters(dir, cluster);
+out:
+ unlock_kernel();
+ return err;
}
/***** Unlink a file */
static int msdos_unlink(struct inode *dir, struct dentry *dentry)
{
struct inode *inode = dentry->d_inode;
- loff_t i_pos;
- int res;
- struct buffer_head *bh;
- struct msdos_dir_entry *de;
+ struct fat_slot_info sinfo;
+ int err;
- bh = NULL;
lock_kernel();
- res = msdos_find(dir, dentry->d_name.name, dentry->d_name.len,
- &bh, &de, &i_pos);
- if (res < 0)
- goto unlink_done;
+ err = msdos_find(dir, dentry->d_name.name, dentry->d_name.len, &sinfo);
+ if (err)
+ goto out;
- de->name[0] = DELETED_FLAG;
- mark_buffer_dirty(bh);
- fat_detach(inode);
- brelse(bh);
+ err = fat_remove_entries(dir, &sinfo); /* and releases bh */
+ if (err)
+ goto out;
inode->i_nlink = 0;
- inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC;
- mark_inode_dirty(inode);
- mark_inode_dirty(dir);
- res = 0;
-unlink_done:
+ inode->i_ctime = CURRENT_TIME_SEC;
+ fat_detach(inode);
+out:
unlock_kernel();
- return res;
+
+ return err;
}
static int do_msdos_rename(struct inode *old_dir, unsigned char *old_name,
struct dentry *old_dentry,
struct inode *new_dir, unsigned char *new_name,
- struct dentry *new_dentry,
- struct buffer_head *old_bh,
- struct msdos_dir_entry *old_de, loff_t old_i_pos,
- int is_hid)
+ struct dentry *new_dentry, int is_hid)
{
- struct buffer_head *new_bh = NULL, *dotdot_bh = NULL;
- struct msdos_dir_entry *new_de, *dotdot_de;
+ struct buffer_head *dotdot_bh;
+ struct msdos_dir_entry *dotdot_de;
+ loff_t dotdot_i_pos;
struct inode *old_inode, *new_inode;
- loff_t new_i_pos, dotdot_i_pos;
- int error;
- int is_dir;
+ struct fat_slot_info old_sinfo, sinfo;
+ struct timespec ts;
+ int err, old_attrs, is_dir, update_dotdot, corrupt = 0;
+ old_sinfo.bh = sinfo.bh = dotdot_bh = NULL;
old_inode = old_dentry->d_inode;
new_inode = new_dentry->d_inode;
+
+ err = fat_scan(old_dir, old_name, &old_sinfo);
+ if (err) {
+ err = -EIO;
+ goto out;
+ }
+
is_dir = S_ISDIR(old_inode->i_mode);
+ update_dotdot = (is_dir && old_dir != new_dir);
+ if (update_dotdot) {
+ if (fat_get_dotdot_entry(old_inode, &dotdot_bh, &dotdot_de,
+ &dotdot_i_pos) < 0) {
+ err = -EIO;
+ goto out;
+ }
+ }
- if (fat_scan(new_dir, new_name, &new_bh, &new_de, &new_i_pos) >= 0 &&
- !new_inode)
- goto degenerate_case;
- if (is_dir) {
- if (new_inode) {
- error = fat_dir_empty(new_inode);
- if (error)
+ old_attrs = MSDOS_I(old_inode)->i_attrs;
+ err = fat_scan(new_dir, new_name, &sinfo);
+ if (!err) {
+ if (!new_inode) {
+ /* "foo" -> ".foo" case. just change the ATTR_HIDDEN */
+ if (sinfo.de != old_sinfo.de) {
+ err = -EINVAL;
goto out;
- }
- if (fat_scan(old_inode, MSDOS_DOTDOT, &dotdot_bh,
- &dotdot_de, &dotdot_i_pos) < 0) {
- error = -EIO;
+ }
+ if (is_hid)
+ MSDOS_I(old_inode)->i_attrs |= ATTR_HIDDEN;
+ else
+ MSDOS_I(old_inode)->i_attrs &= ~ATTR_HIDDEN;
+ if (IS_DIRSYNC(old_dir)) {
+ err = fat_sync_inode(old_inode);
+ if (err) {
+ MSDOS_I(old_inode)->i_attrs = old_attrs;
+ goto out;
+ }
+ } else
+ mark_inode_dirty(old_inode);
+
+ old_dir->i_version++;
+ old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME_SEC;
+ if (IS_DIRSYNC(old_dir))
+ (void)fat_sync_inode(old_dir);
+ else
+ mark_inode_dirty(old_dir);
goto out;
}
}
- if (!new_bh) {
- error = msdos_add_entry(new_dir, new_name, &new_bh, &new_de,
- &new_i_pos, is_dir, is_hid);
- if (error)
+
+ ts = CURRENT_TIME_SEC;
+ if (new_inode) {
+ if (err)
+ goto out;
+ if (MSDOS_I(new_inode)->i_pos != sinfo.i_pos) {
+ /* WTF??? Cry and fail. */
+ printk(KERN_WARNING "msdos_rename: fs corrupted\n");
+ goto out;
+ }
+
+ if (is_dir) {
+ err = fat_dir_empty(new_inode);
+ if (err)
+ goto out;
+ }
+ fat_detach(new_inode);
+ } else {
+ err = msdos_add_entry(new_dir, new_name, is_dir, is_hid, 0,
+ &ts, &sinfo);
+ if (err)
goto out;
}
new_dir->i_version++;
- /* There we go */
-
- if (new_inode)
- fat_detach(new_inode);
- old_de->name[0] = DELETED_FLAG;
- mark_buffer_dirty(old_bh);
fat_detach(old_inode);
- fat_attach(old_inode, new_i_pos);
+ fat_attach(old_inode, sinfo.i_pos);
if (is_hid)
MSDOS_I(old_inode)->i_attrs |= ATTR_HIDDEN;
else
MSDOS_I(old_inode)->i_attrs &= ~ATTR_HIDDEN;
- mark_inode_dirty(old_inode);
- old_dir->i_version++;
- old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME_SEC;
- mark_inode_dirty(old_dir);
- if (new_inode) {
- new_inode->i_nlink--;
- new_inode->i_ctime = CURRENT_TIME_SEC;
- mark_inode_dirty(new_inode);
- }
- if (dotdot_bh) {
- dotdot_de->start = cpu_to_le16(MSDOS_I(new_dir)->i_logstart);
- dotdot_de->starthi =
- cpu_to_le16((MSDOS_I(new_dir)->i_logstart) >> 16);
+ if (IS_DIRSYNC(new_dir)) {
+ err = fat_sync_inode(old_inode);
+ if (err)
+ goto error_inode;
+ } else
+ mark_inode_dirty(old_inode);
+
+ if (update_dotdot) {
+ int start = MSDOS_I(new_dir)->i_logstart;
+ dotdot_de->start = cpu_to_le16(start);
+ dotdot_de->starthi = cpu_to_le16(start >> 16);
mark_buffer_dirty(dotdot_bh);
+ if (IS_DIRSYNC(new_dir)) {
+ err = sync_dirty_buffer(dotdot_bh);
+ if (err)
+ goto error_dotdot;
+ }
old_dir->i_nlink--;
+ if (!new_inode)
+ new_dir->i_nlink++;
+ }
+
+ err = fat_remove_entries(old_dir, &old_sinfo); /* and releases bh */
+ old_sinfo.bh = NULL;
+ if (err)
+ goto error_dotdot;
+ old_dir->i_version++;
+ old_dir->i_ctime = old_dir->i_mtime = ts;
+ if (IS_DIRSYNC(old_dir))
+ (void)fat_sync_inode(old_dir);
+ else
mark_inode_dirty(old_dir);
- if (new_inode) {
+
+ if (new_inode) {
+ if (is_dir)
+ new_inode->i_nlink -= 2;
+ else
new_inode->i_nlink--;
- mark_inode_dirty(new_inode);
- } else {
- new_dir->i_nlink++;
- mark_inode_dirty(new_dir);
- }
+ new_inode->i_ctime = ts;
}
- error = 0;
out:
- brelse(new_bh);
+ brelse(sinfo.bh);
brelse(dotdot_bh);
- return error;
+ brelse(old_sinfo.bh);
+ return err;
-degenerate_case:
- error = -EINVAL;
- if (new_de != old_de)
- goto out;
- if (is_hid)
- MSDOS_I(old_inode)->i_attrs |= ATTR_HIDDEN;
- else
- MSDOS_I(old_inode)->i_attrs &= ~ATTR_HIDDEN;
- mark_inode_dirty(old_inode);
- old_dir->i_version++;
- old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME_SEC;
- mark_inode_dirty(old_dir);
- return 0;
+error_dotdot:
+ /* data cluster is shared, serious corruption */
+ corrupt = 1;
+
+ if (update_dotdot) {
+ int start = MSDOS_I(old_dir)->i_logstart;
+ dotdot_de->start = cpu_to_le16(start);
+ dotdot_de->starthi = cpu_to_le16(start >> 16);
+ mark_buffer_dirty(dotdot_bh);
+ corrupt |= sync_dirty_buffer(dotdot_bh);
+ }
+error_inode:
+ fat_detach(old_inode);
+ fat_attach(old_inode, old_sinfo.i_pos);
+ MSDOS_I(old_inode)->i_attrs = old_attrs;
+ if (new_inode) {
+ fat_attach(new_inode, sinfo.i_pos);
+ if (corrupt)
+ corrupt |= fat_sync_inode(new_inode);
+ } else {
+ /*
+ * If new entry was not sharing the data cluster, it
+ * shouldn't be serious corruption.
+ */
+ int err2 = fat_remove_entries(new_dir, &sinfo);
+ if (corrupt)
+ corrupt |= err2;
+ sinfo.bh = NULL;
+ }
+ if (corrupt < 0) {
+ fat_fs_panic(new_dir->i_sb,
+ "%s: Filesystem corrupted (i_pos %lld)",
+ __FUNCTION__, sinfo.i_pos);
+ }
+ goto out;
}
/***** Rename, a wrapper for rename_same_dir & rename_diff_dir */
static int msdos_rename(struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_dentry)
{
- struct buffer_head *old_bh;
- struct msdos_dir_entry *old_de;
- loff_t old_i_pos;
- int error, is_hid, old_hid; /* if new file and old file are hidden */
unsigned char old_msdos_name[MSDOS_NAME], new_msdos_name[MSDOS_NAME];
+ int err, is_hid;
lock_kernel();
- error = msdos_format_name(old_dentry->d_name.name,
- old_dentry->d_name.len, old_msdos_name,
- &MSDOS_SB(old_dir->i_sb)->options);
- if (error < 0)
- goto rename_done;
- error = msdos_format_name(new_dentry->d_name.name,
- new_dentry->d_name.len, new_msdos_name,
- &MSDOS_SB(new_dir->i_sb)->options);
- if (error < 0)
- goto rename_done;
+
+ err = msdos_format_name(old_dentry->d_name.name,
+ old_dentry->d_name.len, old_msdos_name,
+ &MSDOS_SB(old_dir->i_sb)->options);
+ if (err)
+ goto out;
+ err = msdos_format_name(new_dentry->d_name.name,
+ new_dentry->d_name.len, new_msdos_name,
+ &MSDOS_SB(new_dir->i_sb)->options);
+ if (err)
+ goto out;
is_hid =
(new_dentry->d_name.name[0] == '.') && (new_msdos_name[0] != '.');
- old_hid =
- (old_dentry->d_name.name[0] == '.') && (old_msdos_name[0] != '.');
- error = fat_scan(old_dir, old_msdos_name, &old_bh, &old_de, &old_i_pos);
- if (error < 0)
- goto rename_done;
-
- error = do_msdos_rename(old_dir, old_msdos_name, old_dentry,
- new_dir, new_msdos_name, new_dentry,
- old_bh, old_de, old_i_pos, is_hid);
- brelse(old_bh);
-
-rename_done:
+ err = do_msdos_rename(old_dir, old_msdos_name, old_dentry,
+ new_dir, new_msdos_name, new_dentry, is_hid);
+out:
unlock_kernel();
- return error;
+ return err;
}
static struct inode_operations msdos_dir_inode_operations = {
@@ -621,6 +673,7 @@ static int msdos_fill_super(struct super_block *sb, void *data, int silent)
if (res)
return res;
+ sb->s_flags |= MS_NOATIME;
sb->s_root->d_op = &msdos_dentry_operations;
return 0;
}
diff --git a/fs/namei.c b/fs/namei.c
index 281ca91fd1cc5..9e4aef2a1a21d 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -148,11 +148,22 @@ char * getname(const char __user * filename)
result = ERR_PTR(retval);
}
}
- if (unlikely(current->audit_context) && !IS_ERR(result) && result)
- audit_getname(result);
+ audit_getname(result);
return result;
}
+#ifdef CONFIG_AUDITSYSCALL
+void putname(const char *name)
+{
+ if (unlikely(current->audit_context))
+ audit_putname(name);
+ else
+ __putname(name);
+}
+EXPORT_SYMBOL(putname);
+#endif
+
+
/**
* generic_permission - check for access rights on a Posix-like filesystem
* @inode: inode to check access rights for
@@ -681,7 +692,7 @@ fail:
*
* We expect 'base' to be positive and a directory.
*/
-int fastcall link_path_walk(const char * name, struct nameidata *nd)
+static fastcall int __link_path_walk(const char * name, struct nameidata *nd)
{
struct path next;
struct inode *inode;
@@ -881,6 +892,37 @@ return_err:
return err;
}
+/*
+ * Wrapper to retry pathname resolution whenever the underlying
+ * file system returns an ESTALE.
+ *
+ * Retry the whole path once, forcing real lookup requests
+ * instead of relying on the dcache.
+ */
+int fastcall link_path_walk(const char *name, struct nameidata *nd)
+{
+ struct nameidata save = *nd;
+ int result;
+
+ /* make sure the stuff we saved doesn't go away */
+ dget(save.dentry);
+ mntget(save.mnt);
+
+ result = __link_path_walk(name, nd);
+ if (result == -ESTALE) {
+ *nd = save;
+ dget(nd->dentry);
+ mntget(nd->mnt);
+ nd->flags |= LOOKUP_REVAL;
+ result = __link_path_walk(name, nd);
+ }
+
+ dput(save.dentry);
+ mntput(save.mnt);
+
+ return result;
+}
+
int fastcall path_walk(const char * name, struct nameidata *nd)
{
current->total_link_count = 0;
@@ -981,9 +1023,7 @@ int fastcall path_lookup(const char *name, unsigned int flags, struct nameidata
retval = link_path_walk(name, nd);
if (unlikely(current->audit_context
&& nd && nd->dentry && nd->dentry->d_inode))
- audit_inode(name,
- nd->dentry->d_inode->i_ino,
- nd->dentry->d_inode->i_rdev);
+ audit_inode(name, nd->dentry->d_inode);
return retval;
}
@@ -1685,17 +1725,13 @@ out:
void dentry_unhash(struct dentry *dentry)
{
dget(dentry);
- spin_lock(&dcache_lock);
- switch (atomic_read(&dentry->d_count)) {
- default:
- spin_unlock(&dcache_lock);
+ if (atomic_read(&dentry->d_count))
shrink_dcache_parent(dentry);
- spin_lock(&dcache_lock);
- if (atomic_read(&dentry->d_count) != 2)
- break;
- case 2:
+ spin_lock(&dcache_lock);
+ spin_lock(&dentry->d_lock);
+ if (atomic_read(&dentry->d_count) == 2)
__d_drop(dentry);
- }
+ spin_unlock(&dentry->d_lock);
spin_unlock(&dcache_lock);
}
diff --git a/fs/namespace.c b/fs/namespace.c
index 755b081c0bd24..3b93e5d750ebf 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -1255,10 +1255,19 @@ static void chroot_fs_refs(struct nameidata *old_nd, struct nameidata *new_nd)
}
/*
- * Moves the current root to put_root, and sets root/cwd of all processes
- * which had them on the old root to new_root.
+ * pivot_root Semantics:
+ * Moves the root file system of the current process to the directory put_old,
+ * makes new_root as the new root file system of the current process, and sets
+ * root/cwd of all processes which had them on the current root to new_root.
*
- * Note:
+ * Restrictions:
+ * The new_root and put_old must be directories, and must not be on the
+ * same file system as the current process root. The put_old must be
+ * underneath new_root, i.e. adding a non-zero number of /.. to the string
+ * 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.
+ *
+ * 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)
* - it's okay to pick a root that isn't the root of a file system, e.g.
@@ -1313,10 +1322,10 @@ asmlinkage long sys_pivot_root(const char __user *new_root, const char __user *p
goto out2;
error = -EBUSY;
if (new_nd.mnt == user_nd.mnt || old_nd.mnt == user_nd.mnt)
- goto out2; /* loop */
+ goto out2; /* loop, on the same file system */
error = -EINVAL;
if (user_nd.mnt->mnt_root != user_nd.dentry)
- goto out2;
+ goto out2; /* not a mountpoint */
if (new_nd.mnt->mnt_root != new_nd.dentry)
goto out2; /* not a mountpoint */
tmp = old_nd.mnt; /* make sure we can reach put_old from new_root */
@@ -1324,7 +1333,7 @@ asmlinkage long sys_pivot_root(const char __user *new_root, const char __user *p
if (tmp != new_nd.mnt) {
for (;;) {
if (tmp->mnt_parent == tmp)
- goto out3;
+ goto out3; /* already mounted on put_old */
if (tmp->mnt_parent == new_nd.mnt)
break;
tmp = tmp->mnt_parent;
@@ -1335,8 +1344,8 @@ asmlinkage long sys_pivot_root(const char __user *new_root, const char __user *p
goto out3;
detach_mnt(new_nd.mnt, &parent_nd);
detach_mnt(user_nd.mnt, &root_parent);
- attach_mnt(user_nd.mnt, &old_nd);
- attach_mnt(new_nd.mnt, &root_parent);
+ attach_mnt(user_nd.mnt, &old_nd); /* mount old root on put_old */
+ attach_mnt(new_nd.mnt, &root_parent); /* mount new_root on / */
spin_unlock(&vfsmount_lock);
chroot_fs_refs(&user_nd, &new_nd);
security_sb_post_pivotroot(&user_nd, &new_nd);
@@ -1392,16 +1401,14 @@ static void __init init_mount_tree(void)
void __init mnt_init(unsigned long mempages)
{
struct list_head *d;
- unsigned long order;
unsigned int nr_hash;
int i;
mnt_cache = kmem_cache_create("mnt_cache", sizeof(struct vfsmount),
0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL);
- order = 0;
mount_hashtable = (struct list_head *)
- __get_free_pages(GFP_ATOMIC, order);
+ __get_free_page(GFP_ATOMIC);
if (!mount_hashtable)
panic("Failed to allocate mount hash table\n");
@@ -1411,7 +1418,7 @@ void __init mnt_init(unsigned long mempages)
* We don't guarantee that "sizeof(struct list_head)" is necessarily
* a power-of-two.
*/
- nr_hash = (1UL << order) * PAGE_SIZE / sizeof(struct list_head);
+ nr_hash = PAGE_SIZE / sizeof(struct list_head);
hash_bits = 0;
do {
hash_bits++;
@@ -1425,8 +1432,7 @@ void __init mnt_init(unsigned long mempages)
nr_hash = 1UL << hash_bits;
hash_mask = nr_hash-1;
- printk("Mount-cache hash table entries: %d (order: %ld, %ld bytes)\n",
- nr_hash, order, (PAGE_SIZE << order));
+ printk("Mount-cache hash table entries: %d\n", nr_hash);
/* And initialize the newly allocated array */
d = mount_hashtable;
diff --git a/fs/ncpfs/ncplib_kernel.c b/fs/ncpfs/ncplib_kernel.c
index 51969f278a6b2..e4eb5ed4bee45 100644
--- a/fs/ncpfs/ncplib_kernel.c
+++ b/fs/ncpfs/ncplib_kernel.c
@@ -933,7 +933,7 @@ int ncp_search_for_fileset(struct ncp_server *server,
return 0;
}
-int
+static int
ncp_RenameNSEntry(struct ncp_server *server,
struct inode *old_dir, char *old_name, __le16 old_type,
struct inode *new_dir, char *new_name)
diff --git a/fs/ncpfs/ncpsign_kernel.c b/fs/ncpfs/ncpsign_kernel.c
index dcac251c14ff5..a6ec90cd8894b 100644
--- a/fs/ncpfs/ncpsign_kernel.c
+++ b/fs/ncpfs/ncpsign_kernel.c
@@ -11,10 +11,9 @@
#include <linux/string.h>
#include <linux/ncp.h>
+#include <linux/bitops.h>
#include "ncpsign_kernel.h"
-#define rol32(i,c) (((((i)&0xffffffff)<<c)&0xffffffff)| \
- (((i)&0xffffffff)>>(32-c)))
/* i386: 32-bit, little endian, handles mis-alignment */
#ifdef __i386__
#define GET_LE32(p) (*(int *)(p))
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c
index ad7677b4f21df..560d6175dd58a 100644
--- a/fs/nfs/callback.c
+++ b/fs/nfs/callback.c
@@ -139,133 +139,10 @@ out:
return ret;
}
-/*
- * AUTH_NULL authentication
- */
-static int nfs_callback_null_accept(struct svc_rqst *rqstp, u32 *authp)
-{
- struct kvec *argv = &rqstp->rq_arg.head[0];
- struct kvec *resv = &rqstp->rq_res.head[0];
-
- if (argv->iov_len < 3*4)
- return SVC_GARBAGE;
-
- if (svc_getu32(argv) != 0) {
- dprintk("svc: bad null cred\n");
- *authp = rpc_autherr_badcred;
- return SVC_DENIED;
- }
- if (svc_getu32(argv) != RPC_AUTH_NULL || svc_getu32(argv) != 0) {
- dprintk("svc: bad null verf\n");
- *authp = rpc_autherr_badverf;
- return SVC_DENIED;
- }
-
- /* Signal that mapping to nobody uid/gid is required */
- rqstp->rq_cred.cr_uid = (uid_t) -1;
- rqstp->rq_cred.cr_gid = (gid_t) -1;
- rqstp->rq_cred.cr_group_info = groups_alloc(0);
- if (rqstp->rq_cred.cr_group_info == NULL)
- return SVC_DROP; /* kmalloc failure - client must retry */
-
- /* Put NULL verifier */
- svc_putu32(resv, RPC_AUTH_NULL);
- svc_putu32(resv, 0);
- dprintk("%s: success, returning %d!\n", __FUNCTION__, SVC_OK);
- return SVC_OK;
-}
-
-static int nfs_callback_null_release(struct svc_rqst *rqstp)
-{
- if (rqstp->rq_cred.cr_group_info)
- put_group_info(rqstp->rq_cred.cr_group_info);
- rqstp->rq_cred.cr_group_info = NULL;
- return 0; /* don't drop */
-}
-
-static struct auth_ops nfs_callback_auth_null = {
- .name = "null",
- .flavour = RPC_AUTH_NULL,
- .accept = nfs_callback_null_accept,
- .release = nfs_callback_null_release,
-};
-
-/*
- * AUTH_SYS authentication
- */
-static int nfs_callback_unix_accept(struct svc_rqst *rqstp, u32 *authp)
-{
- struct kvec *argv = &rqstp->rq_arg.head[0];
- struct kvec *resv = &rqstp->rq_res.head[0];
- struct svc_cred *cred = &rqstp->rq_cred;
- u32 slen, i;
- int len = argv->iov_len;
-
- dprintk("%s: start\n", __FUNCTION__);
- cred->cr_group_info = NULL;
- rqstp->rq_client = NULL;
- if ((len -= 3*4) < 0)
- return SVC_GARBAGE;
-
- /* Get length, time stamp and machine name */
- svc_getu32(argv);
- svc_getu32(argv);
- slen = XDR_QUADLEN(ntohl(svc_getu32(argv)));
- if (slen > 64 || (len -= (slen + 3)*4) < 0)
- goto badcred;
- argv->iov_base = (void*)((u32*)argv->iov_base + slen);
- argv->iov_len -= slen*4;
-
- cred->cr_uid = ntohl(svc_getu32(argv));
- cred->cr_gid = ntohl(svc_getu32(argv));
- slen = ntohl(svc_getu32(argv));
- if (slen > 16 || (len -= (slen + 2)*4) < 0)
- goto badcred;
- cred->cr_group_info = groups_alloc(slen);
- if (cred->cr_group_info == NULL)
- return SVC_DROP;
- for (i = 0; i < slen; i++)
- GROUP_AT(cred->cr_group_info, i) = ntohl(svc_getu32(argv));
-
- if (svc_getu32(argv) != RPC_AUTH_NULL || svc_getu32(argv) != 0) {
- *authp = rpc_autherr_badverf;
- return SVC_DENIED;
- }
- /* Put NULL verifier */
- svc_putu32(resv, RPC_AUTH_NULL);
- svc_putu32(resv, 0);
- dprintk("%s: success, returning %d!\n", __FUNCTION__, SVC_OK);
- return SVC_OK;
-badcred:
- *authp = rpc_autherr_badcred;
- return SVC_DENIED;
-}
-
-static int nfs_callback_unix_release(struct svc_rqst *rqstp)
-{
- if (rqstp->rq_cred.cr_group_info)
- put_group_info(rqstp->rq_cred.cr_group_info);
- rqstp->rq_cred.cr_group_info = NULL;
- return 0;
-}
-
-static struct auth_ops nfs_callback_auth_unix = {
- .name = "unix",
- .flavour = RPC_AUTH_UNIX,
- .accept = nfs_callback_unix_accept,
- .release = nfs_callback_unix_release,
-};
-
-/*
- * Hook the authentication protocol
- */
-static int nfs_callback_auth(struct svc_rqst *rqstp, u32 *authp)
+static int nfs_callback_authenticate(struct svc_rqst *rqstp)
{
struct in_addr *addr = &rqstp->rq_addr.sin_addr;
struct nfs4_client *clp;
- struct kvec *argv = &rqstp->rq_arg.head[0];
- int flavour;
- int retval;
/* Don't talk to strangers */
clp = nfs4_find_client(addr);
@@ -273,34 +150,19 @@ static int nfs_callback_auth(struct svc_rqst *rqstp, u32 *authp)
return SVC_DROP;
dprintk("%s: %u.%u.%u.%u NFSv4 callback!\n", __FUNCTION__, NIPQUAD(addr));
nfs4_put_client(clp);
- flavour = ntohl(svc_getu32(argv));
- switch(flavour) {
+ switch (rqstp->rq_authop->flavour) {
case RPC_AUTH_NULL:
- if (rqstp->rq_proc != CB_NULL) {
- *authp = rpc_autherr_tooweak;
- retval = SVC_DENIED;
- break;
- }
- rqstp->rq_authop = &nfs_callback_auth_null;
- retval = nfs_callback_null_accept(rqstp, authp);
+ if (rqstp->rq_proc != CB_NULL)
+ return SVC_DENIED;
break;
case RPC_AUTH_UNIX:
- /* Eat the authentication flavour */
- rqstp->rq_authop = &nfs_callback_auth_unix;
- retval = nfs_callback_unix_accept(rqstp, authp);
break;
+ case RPC_AUTH_GSS:
+ /* FIXME: RPCSEC_GSS handling? */
default:
- /* FIXME: need to add RPCSEC_GSS upcalls */
-#if 0
- svc_ungetu32(argv);
- retval = svc_authenticate(rqstp, authp);
-#else
- *authp = rpc_autherr_rejectedcred;
- retval = SVC_DENIED;
-#endif
+ return SVC_DENIED;
}
- dprintk("%s: flavour %d returning error %d\n", __FUNCTION__, flavour, retval);
- return retval;
+ return SVC_OK;
}
/*
@@ -321,5 +183,5 @@ static struct svc_program nfs4_callback_program = {
.pg_name = "NFSv4 callback", /* service name */
.pg_class = "nfs", /* authentication class */
.pg_stats = &nfs4_callback_stats,
- .pg_authenticate = nfs_callback_auth,
+ .pg_authenticate = nfs_callback_authenticate,
};
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 1018f1f97c2aa..73f96acd5d378 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -529,13 +529,24 @@ static inline void nfs_renew_times(struct dentry * dentry)
}
static inline
-int nfs_lookup_verify_inode(struct inode *inode, int isopen)
+int nfs_lookup_verify_inode(struct inode *inode, struct nameidata *nd)
{
struct nfs_server *server = NFS_SERVER(inode);
- if (isopen && !(server->flags & NFS_MOUNT_NOCTO))
- return __nfs_revalidate_inode(server, inode);
+ if (nd != NULL) {
+ int ndflags = nd->flags;
+ /* VFS wants an on-the-wire revalidation */
+ if (ndflags & LOOKUP_REVAL)
+ goto out_force;
+ /* This is an open(2) */
+ if ((ndflags & LOOKUP_OPEN) &&
+ !(ndflags & LOOKUP_CONTINUE) &&
+ !(server->flags & NFS_MOUNT_NOCTO))
+ goto out_force;
+ }
return nfs_revalidate_inode(server, inode);
+out_force:
+ return __nfs_revalidate_inode(server, inode);
}
/*
@@ -579,16 +590,12 @@ static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd)
struct nfs_fh fhandle;
struct nfs_fattr fattr;
unsigned long verifier;
- int isopen = 0;
parent = dget_parent(dentry);
lock_kernel();
dir = parent->d_inode;
inode = dentry->d_inode;
- if (nd && !(nd->flags & LOOKUP_CONTINUE) && (nd->flags & LOOKUP_OPEN))
- isopen = 1;
-
if (!inode) {
if (nfs_neg_need_reval(dir, dentry, nd))
goto out_bad;
@@ -602,11 +609,12 @@ static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd)
}
/* Revalidate parent directory attribute cache */
- nfs_revalidate_inode(NFS_SERVER(dir), dir);
+ if (nfs_revalidate_inode(NFS_SERVER(dir), dir) < 0)
+ goto out_zap_parent;
/* Force a full look up iff the parent directory has changed */
if (nfs_check_verifier(dir, dentry)) {
- if (nfs_lookup_verify_inode(inode, isopen))
+ if (nfs_lookup_verify_inode(inode, nd))
goto out_zap_parent;
goto out_valid;
}
@@ -722,7 +730,11 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru
lock_kernel();
/* Revalidate parent directory attribute cache */
- nfs_revalidate_inode(NFS_SERVER(dir), dir);
+ error = nfs_revalidate_inode(NFS_SERVER(dir), dir);
+ if (error < 0) {
+ res = ERR_PTR(error);
+ goto out_unlock;
+ }
/* If we're doing an exclusive create, optimize away the lookup */
if (nfs_is_exclusive_create(dir, nd))
@@ -780,6 +792,7 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry
{
struct dentry *res = NULL;
struct inode *inode = NULL;
+ int error;
/* Check that we are indeed trying to open this file */
if (!is_atomic_open(dir, nd))
@@ -798,7 +811,11 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry
/* Open the file on the server */
lock_kernel();
/* Revalidate parent directory attribute cache */
- nfs_revalidate_inode(NFS_SERVER(dir), dir);
+ error = nfs_revalidate_inode(NFS_SERVER(dir), dir);
+ if (error < 0) {
+ res = ERR_PTR(error);
+ goto out;
+ }
if (nd->intent.open.flags & O_CREAT) {
nfs_begin_data_update(dir);
@@ -808,7 +825,7 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry
inode = nfs4_atomic_open(dir, dentry, nd);
unlock_kernel();
if (IS_ERR(inode)) {
- int error = PTR_ERR(inode);
+ error = PTR_ERR(inode);
switch (error) {
/* Make a negative dentry */
case -ENOENT:
@@ -938,7 +955,7 @@ static struct dentry *nfs_readdir_lookup(nfs_readdir_descriptor_t *desc)
/*
* Code common to create, mkdir, and mknod.
*/
-static int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle,
+int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle,
struct nfs_fattr *fattr)
{
struct inode *inode;
@@ -959,14 +976,12 @@ static int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle,
if (error < 0)
goto out_err;
}
- inode = nfs_fhget(dentry->d_sb, fhandle, fattr);
- if (inode) {
- d_instantiate(dentry, inode);
- nfs_renew_times(dentry);
- nfs_set_verifier(dentry, nfs_save_change_attribute(dentry->d_parent->d_inode));
- return 0;
- }
error = -ENOMEM;
+ inode = nfs_fhget(dentry->d_sb, fhandle, fattr);
+ if (inode == NULL)
+ goto out_err;
+ d_instantiate(dentry, inode);
+ return 0;
out_err:
d_drop(dentry);
return error;
@@ -982,7 +997,6 @@ static int nfs_create(struct inode *dir, struct dentry *dentry, int mode,
struct nameidata *nd)
{
struct iattr attr;
- struct inode *inode;
int error;
int open_flags = 0;
@@ -997,18 +1011,17 @@ static int nfs_create(struct inode *dir, struct dentry *dentry, int mode,
lock_kernel();
nfs_begin_data_update(dir);
- inode = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags);
+ error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags);
nfs_end_data_update(dir);
- if (!IS_ERR(inode)) {
- d_instantiate(dentry, inode);
- nfs_renew_times(dentry);
- nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
- error = 0;
- } else {
- error = PTR_ERR(inode);
- d_drop(dentry);
- }
+ if (error != 0)
+ goto out_err;
+ nfs_renew_times(dentry);
+ nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
+ unlock_kernel();
+ return 0;
+out_err:
unlock_kernel();
+ d_drop(dentry);
return error;
}
@@ -1019,9 +1032,7 @@ static int
nfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
{
struct iattr attr;
- struct nfs_fattr fattr;
- struct nfs_fh fhandle;
- int error;
+ int status;
dfprintk(VFS, "NFS: mknod(%s/%ld, %s\n", dir->i_sb->s_id,
dir->i_ino, dentry->d_name.name);
@@ -1034,15 +1045,18 @@ nfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
lock_kernel();
nfs_begin_data_update(dir);
- error = NFS_PROTO(dir)->mknod(dir, &dentry->d_name, &attr, rdev,
- &fhandle, &fattr);
+ status = NFS_PROTO(dir)->mknod(dir, dentry, &attr, rdev);
nfs_end_data_update(dir);
- if (!error)
- error = nfs_instantiate(dentry, &fhandle, &fattr);
- else
- d_drop(dentry);
+ if (status != 0)
+ goto out_err;
+ nfs_renew_times(dentry);
+ nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
unlock_kernel();
- return error;
+ return 0;
+out_err:
+ unlock_kernel();
+ d_drop(dentry);
+ return status;
}
/*
@@ -1051,8 +1065,6 @@ nfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
static int nfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
{
struct iattr attr;
- struct nfs_fattr fattr;
- struct nfs_fh fhandle;
int error;
dfprintk(VFS, "NFS: mkdir(%s/%ld, %s\n", dir->i_sb->s_id,
@@ -1062,23 +1074,17 @@ static int nfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
attr.ia_mode = mode | S_IFDIR;
lock_kernel();
-#if 0
- /*
- * Always drop the dentry, we can't always depend on
- * the fattr returned by the server (AIX seems to be
- * broken). We're better off doing another lookup than
- * depending on potentially bogus information.
- */
- d_drop(dentry);
-#endif
nfs_begin_data_update(dir);
- error = NFS_PROTO(dir)->mkdir(dir, &dentry->d_name, &attr, &fhandle,
- &fattr);
+ error = NFS_PROTO(dir)->mkdir(dir, dentry, &attr);
nfs_end_data_update(dir);
- if (!error)
- error = nfs_instantiate(dentry, &fhandle, &fattr);
- else
- d_drop(dentry);
+ if (error != 0)
+ goto out_err;
+ nfs_renew_times(dentry);
+ nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
+ unlock_kernel();
+ return 0;
+out_err:
+ d_drop(dentry);
unlock_kernel();
return error;
}
@@ -1107,7 +1113,7 @@ static int nfs_sillyrename(struct inode *dir, struct dentry *dentry)
static unsigned int sillycounter;
const int i_inosize = sizeof(dir->i_ino)*2;
const int countersize = sizeof(sillycounter)*2;
- const int slen = strlen(".nfs") + i_inosize + countersize;
+ const int slen = sizeof(".nfs") + i_inosize + countersize - 1;
char silly[slen+1];
struct qstr qsilly;
struct dentry *sdentry;
@@ -1466,8 +1472,8 @@ void nfs_access_add_cache(struct inode *inode, struct nfs_access_entry *set)
if (cache->cred)
put_rpccred(cache->cred);
cache->cred = get_rpccred(set->cred);
- NFS_FLAGS(inode) &= ~NFS_INO_INVALID_ACCESS;
}
+ NFS_FLAGS(inode) &= ~NFS_INO_INVALID_ACCESS;
cache->jiffies = set->jiffies;
cache->mask = set->mask;
}
@@ -1498,34 +1504,52 @@ out:
int nfs_permission(struct inode *inode, int mask, struct nameidata *nd)
{
struct rpc_cred *cred;
- int res;
+ int res = 0;
if (mask == 0)
- return 0;
+ goto out;
+ /* Is this sys_access() ? */
+ if (nd != NULL && (nd->flags & LOOKUP_ACCESS))
+ goto force_lookup;
- /* Are we checking permissions on anything other than lookup/execute? */
- if ((mask & MAY_EXEC) == 0) {
- /* We only need to check permissions on file open() and access() */
- if (!nd || !(nd->flags & (LOOKUP_OPEN|LOOKUP_ACCESS)))
- return 0;
- /* NFSv4 has atomic_open... */
- if (NFS_PROTO(inode)->version > 3 && (nd->flags & LOOKUP_OPEN))
- return 0;
+ switch (inode->i_mode & S_IFMT) {
+ case S_IFLNK:
+ goto out;
+ case S_IFREG:
+ /* NFSv4 has atomic_open... */
+ if (nfs_server_capable(inode, NFS_CAP_ATOMIC_OPEN)
+ && nd != NULL
+ && (nd->flags & LOOKUP_OPEN))
+ goto out;
+ break;
+ case S_IFDIR:
+ /*
+ * Optimize away all write operations, since the server
+ * will check permissions when we perform the op.
+ */
+ if ((mask & MAY_WRITE) && !(mask & MAY_READ))
+ goto out;
}
+force_lookup:
lock_kernel();
if (!NFS_PROTO(inode)->access)
goto out_notsup;
cred = rpcauth_lookupcred(NFS_CLIENT(inode)->cl_auth, 0);
- res = nfs_do_access(inode, cred, mask);
- put_rpccred(cred);
+ if (!IS_ERR(cred)) {
+ res = nfs_do_access(inode, cred, mask);
+ put_rpccred(cred);
+ } else
+ res = PTR_ERR(cred);
unlock_kernel();
+out:
return res;
out_notsup:
- nfs_revalidate_inode(NFS_SERVER(inode), inode);
- res = generic_permission(inode, mask, NULL);
+ res = nfs_revalidate_inode(NFS_SERVER(inode), inode);
+ if (res == 0)
+ res = generic_permission(inode, mask, NULL);
unlock_kernel();
return res;
}
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index 57ccbd277fcec..f06eee6dcff57 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -44,6 +44,8 @@ static ssize_t nfs_file_write(struct kiocb *, const char __user *, size_t, loff_
static int nfs_file_flush(struct file *);
static int nfs_fsync(struct file *, struct dentry *dentry, int datasync);
static int nfs_check_flags(int flags);
+static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl);
+static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl);
struct file_operations nfs_file_operations = {
.llseek = remote_llseek,
@@ -57,6 +59,7 @@ struct file_operations nfs_file_operations = {
.release = nfs_file_release,
.fsync = nfs_fsync,
.lock = nfs_lock,
+ .flock = nfs_flock,
.sendfile = nfs_file_sendfile,
.check_flags = nfs_check_flags,
};
@@ -105,6 +108,9 @@ nfs_file_open(struct inode *inode, struct file *filp)
static int
nfs_file_release(struct inode *inode, struct file *filp)
{
+ /* Ensure that dirty pages are flushed out with the right creds */
+ if (filp->f_mode & FMODE_WRITE)
+ filemap_fdatawrite(filp->f_mapping);
return NFS_PROTO(inode)->file_release(inode, filp);
}
@@ -312,6 +318,25 @@ static int do_getlk(struct file *filp, int cmd, struct file_lock *fl)
return status;
}
+static int do_vfs_lock(struct file *file, struct file_lock *fl)
+{
+ int res = 0;
+ switch (fl->fl_flags & (FL_POSIX|FL_FLOCK)) {
+ case FL_POSIX:
+ res = posix_lock_file_wait(file, fl);
+ break;
+ case FL_FLOCK:
+ res = flock_lock_file_wait(file, fl);
+ break;
+ default:
+ BUG();
+ }
+ if (res < 0)
+ printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n",
+ __FUNCTION__);
+ return res;
+}
+
static int do_unlk(struct file *filp, int cmd, struct file_lock *fl)
{
struct inode *inode = filp->f_mapping->host;
@@ -338,7 +363,7 @@ static int do_unlk(struct file *filp, int cmd, struct file_lock *fl)
if (!(NFS_SERVER(inode)->flags & NFS_MOUNT_NONLM))
status = NFS_PROTO(inode)->lock(filp, cmd, fl);
else
- status = posix_lock_file_wait(filp, fl);
+ status = do_vfs_lock(filp, fl);
unlock_kernel();
rpc_clnt_sigunmask(NFS_CLIENT(inode), &oldset);
return status;
@@ -377,9 +402,9 @@ static int do_setlk(struct file *filp, int cmd, struct file_lock *fl)
* the process exits.
*/
if (status == -EINTR || status == -ERESTARTSYS)
- posix_lock_file_wait(filp, fl);
+ do_vfs_lock(filp, fl);
} else
- status = posix_lock_file_wait(filp, fl);
+ status = do_vfs_lock(filp, fl);
unlock_kernel();
if (status < 0)
goto out;
@@ -401,8 +426,7 @@ out:
/*
* Lock a (portion of) a file
*/
-int
-nfs_lock(struct file *filp, int cmd, struct file_lock *fl)
+static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl)
{
struct inode * inode = filp->f_mapping->host;
@@ -418,6 +442,27 @@ nfs_lock(struct file *filp, int cmd, struct file_lock *fl)
if ((inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID)
return -ENOLCK;
+ if (IS_GETLK(cmd))
+ return do_getlk(filp, cmd, fl);
+ if (fl->fl_type == F_UNLCK)
+ return do_unlk(filp, cmd, fl);
+ return do_setlk(filp, cmd, fl);
+}
+
+/*
+ * Lock a (portion of) a file
+ */
+static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl)
+{
+ struct inode * inode = filp->f_mapping->host;
+
+ dprintk("NFS: nfs_flock(f=%s/%ld, t=%x, fl=%x)\n",
+ inode->i_sb->s_id, inode->i_ino,
+ fl->fl_type, fl->fl_flags);
+
+ if (!inode)
+ return -EINVAL;
+
/*
* No BSD flocks over NFS allowed.
* Note: we could try to fake a POSIX lock request here by
@@ -425,11 +470,14 @@ nfs_lock(struct file *filp, int cmd, struct file_lock *fl)
* Not sure whether that would be unique, though, or whether
* that would break in other places.
*/
- if (!fl->fl_owner || !(fl->fl_flags & FL_POSIX))
+ if (!(fl->fl_flags & FL_FLOCK))
return -ENOLCK;
- if (IS_GETLK(cmd))
- return do_getlk(filp, cmd, fl);
+ /* We're simulating flock() locks using posix locks on the server */
+ fl->fl_owner = (fl_owner_t)filp;
+ fl->fl_start = 0;
+ fl->fl_end = OFFSET_MAX;
+
if (fl->fl_type == F_UNLCK)
return do_unlk(filp, cmd, fl);
return do_setlk(filp, cmd, fl);
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 5e732f7cd6b52..6345f26e87ee9 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -64,6 +64,8 @@ static void nfs_umount_begin(struct super_block *);
static int nfs_statfs(struct super_block *, struct kstatfs *);
static int nfs_show_options(struct seq_file *, struct vfsmount *);
+static struct rpc_program nfs_program;
+
static struct super_operations nfs_sops = {
.alloc_inode = nfs_alloc_inode,
.destroy_inode = nfs_destroy_inode,
@@ -78,7 +80,7 @@ static struct super_operations nfs_sops = {
/*
* RPC cruft for NFS
*/
-struct rpc_stat nfs_rpcstat = {
+static struct rpc_stat nfs_rpcstat = {
.program = &nfs_program
};
static struct rpc_version * nfs_version[] = {
@@ -95,7 +97,7 @@ static struct rpc_version * nfs_version[] = {
#endif
};
-struct rpc_program nfs_program = {
+static struct rpc_program nfs_program = {
.name = "nfs",
.number = NFS_PROGRAM,
.nrvers = sizeof(nfs_version) / sizeof(nfs_version[0]),
@@ -247,6 +249,7 @@ nfs_sb_init(struct super_block *sb, rpc_authflavor_t authflavor)
.fattr = &fattr,
};
int no_root_error = 0;
+ unsigned long max_rpc_payload;
/* We probably want something more informative here */
snprintf(sb->s_id, sizeof(sb->s_id), "%x:%x", MAJOR(sb->s_dev), MINOR(sb->s_dev));
@@ -283,6 +286,12 @@ nfs_sb_init(struct super_block *sb, rpc_authflavor_t authflavor)
if (fsinfo.wtmax >= 512 && server->wsize > fsinfo.wtmax)
server->wsize = nfs_block_size(fsinfo.wtmax, NULL);
+ 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;
+
server->rpages = (server->rsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
if (server->rpages > NFS_READ_MAXIOV) {
server->rpages = NFS_READ_MAXIOV;
@@ -317,6 +326,9 @@ nfs_sb_init(struct super_block *sb, rpc_authflavor_t authflavor)
if (sb->s_maxbytes > MAX_LFS_FILESIZE)
sb->s_maxbytes = MAX_LFS_FILESIZE;
+ server->client->cl_intr = (server->flags & NFS_MOUNT_INTR) ? 1 : 0;
+ server->client->cl_softrtry = (server->flags & NFS_MOUNT_SOFT) ? 1 : 0;
+
/* We're airborne Set socket buffersize */
rpc_setbufsize(server->client, server->wsize + 100, server->rsize + 100);
return 0;
@@ -364,9 +376,8 @@ nfs_create_client(struct nfs_server *server, const struct nfs_mount_data *data)
goto out_fail;
}
- clnt->cl_intr = (server->flags & NFS_MOUNT_INTR) ? 1 : 0;
- clnt->cl_softrtry = (server->flags & NFS_MOUNT_SOFT) ? 1 : 0;
- clnt->cl_droppriv = (server->flags & NFS_MOUNT_BROKEN_SUID) ? 1 : 0;
+ clnt->cl_intr = 1;
+ clnt->cl_softrtry = 1;
clnt->cl_chatty = 1;
return clnt;
@@ -538,7 +549,6 @@ static int nfs_show_options(struct seq_file *m, struct vfsmount *mnt)
{ NFS_MOUNT_NOCTO, ",nocto", "" },
{ NFS_MOUNT_NOAC, ",noac", "" },
{ NFS_MOUNT_NONLM, ",nolock", ",lock" },
- { NFS_MOUNT_BROKEN_SUID, ",broken_suid", "" },
{ 0, NULL, NULL }
};
struct proc_nfs_info *nfs_infop;
@@ -792,7 +802,7 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr)
* Wait for the inode to get unlocked.
* (Used for NFS_INO_LOCKED and NFS_INO_REVALIDATING).
*/
-int
+static int
nfs_wait_on_inode(struct inode *inode, int flag)
{
struct rpc_clnt *clnt = NFS_CLIENT(inode);
@@ -856,6 +866,12 @@ struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx)
void put_nfs_open_context(struct nfs_open_context *ctx)
{
if (atomic_dec_and_test(&ctx->count)) {
+ if (!list_empty(&ctx->list)) {
+ struct inode *inode = ctx->dentry->d_inode;
+ spin_lock(&inode->i_lock);
+ list_del(&ctx->list);
+ spin_unlock(&inode->i_lock);
+ }
if (ctx->state != NULL)
nfs4_close_state(ctx->state, ctx->mode);
if (ctx->cred != NULL)
@@ -904,7 +920,7 @@ void nfs_file_clear_open_context(struct file *filp)
if (ctx) {
filp->private_data = NULL;
spin_lock(&inode->i_lock);
- list_del(&ctx->list);
+ list_move_tail(&ctx->list, &NFS_I(inode)->open_files);
spin_unlock(&inode->i_lock);
put_nfs_open_context(ctx);
}
@@ -918,8 +934,9 @@ int nfs_open(struct inode *inode, struct file *filp)
struct nfs_open_context *ctx;
struct rpc_cred *cred;
- if ((cred = rpcauth_lookupcred(NFS_CLIENT(inode)->cl_auth, 0)) == NULL)
- return -ENOMEM;
+ cred = rpcauth_lookupcred(NFS_CLIENT(inode)->cl_auth, 0);
+ if (IS_ERR(cred))
+ return PTR_ERR(cred);
ctx = alloc_nfs_open_context(filp->f_dentry, cred);
put_rpccred(cred);
if (ctx == NULL)
@@ -1542,6 +1559,7 @@ static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data,
if (data->wsize != 0)
server->wsize = nfs_block_size(data->wsize, NULL);
server->flags = data->flags & NFS_MOUNT_FLAGMASK;
+ server->caps = NFS_CAP_ATOMIC_OPEN;
server->acregmin = data->acregmin*HZ;
server->acregmax = data->acregmax*HZ;
@@ -1609,9 +1627,17 @@ static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data,
err = PTR_ERR(clnt);
goto out_fail;
}
+ 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);
}
@@ -1634,8 +1660,6 @@ static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data,
return PTR_ERR(clnt);
}
- clnt->cl_intr = (server->flags & NFS4_MOUNT_INTR) ? 1 : 0;
- clnt->cl_softrtry = (server->flags & NFS4_MOUNT_SOFT) ? 1 : 0;
server->client = clnt;
if (server->nfs4_state->cl_idmap == NULL) {
diff --git a/fs/nfs/mount_clnt.c b/fs/nfs/mount_clnt.c
index 857e3ea4c40b2..9d3ddad96d9ea 100644
--- a/fs/nfs/mount_clnt.c
+++ b/fs/nfs/mount_clnt.c
@@ -31,7 +31,7 @@
static struct rpc_clnt * mnt_create(char *, struct sockaddr_in *,
int, int);
-struct rpc_program mnt_program;
+static struct rpc_program mnt_program;
struct mnt_fhstatus {
unsigned int status;
@@ -174,7 +174,7 @@ static struct rpc_version * mnt_version[] = {
static struct rpc_stat mnt_stats;
-struct rpc_program mnt_program = {
+static struct rpc_program mnt_program = {
.name = "mount",
.number = NFS_MNT_PROGRAM,
.nrvers = sizeof(mnt_version)/sizeof(mnt_version[0]),
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index 828945d683422..3878494dfc2c8 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -295,7 +295,7 @@ static int nfs3_proc_commit(struct nfs_write_data *cdata)
* Create a regular file.
* For now, we don't implement O_EXCL.
*/
-static struct inode *
+static int
nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
int flags)
{
@@ -342,29 +342,19 @@ again:
break;
case NFS3_CREATE_UNCHECKED:
- goto exit;
+ goto out;
}
goto again;
}
-exit:
- dprintk("NFS reply create: %d\n", status);
-
+ if (status == 0)
+ status = nfs_instantiate(dentry, &fhandle, &fattr);
if (status != 0)
goto out;
- if (fhandle.size == 0 || !(fattr.valid & NFS_ATTR_FATTR)) {
- status = nfs3_proc_lookup(dir, &dentry->d_name, &fhandle, &fattr);
- if (status != 0)
- goto out;
- }
/* When we created the file with exclusive semantics, make
* sure we set the attributes afterwards. */
if (arg.createmode == NFS3_CREATE_EXCLUSIVE) {
- struct nfs3_sattrargs arg = {
- .fh = &fhandle,
- .sattr = sattr,
- };
dprintk("NFS call setattr (post-create)\n");
if (!(sattr->ia_valid & ATTR_ATIME_SET))
@@ -375,20 +365,13 @@ exit:
/* Note: we could use a guarded setattr here, but I'm
* not sure this buys us anything (and I'd have
* to revamp the NFSv3 XDR code) */
- fattr.valid = 0;
- status = rpc_call(NFS_CLIENT(dir), NFS3PROC_SETATTR,
- &arg, &fattr, 0);
+ status = nfs3_proc_setattr(dentry, &fattr, sattr);
+ nfs_refresh_inode(dentry->d_inode, &fattr);
dprintk("NFS reply setattr (post-create): %d\n", status);
}
- if (status == 0) {
- struct inode *inode;
- inode = nfs_fhget(dir->i_sb, &fhandle, &fattr);
- if (inode)
- return inode;
- status = -ENOMEM;
- }
out:
- return ERR_PTR(status);
+ dprintk("NFS reply create: %d\n", status);
+ return status;
}
static int
@@ -540,28 +523,30 @@ nfs3_proc_symlink(struct inode *dir, struct qstr *name, struct qstr *path,
}
static int
-nfs3_proc_mkdir(struct inode *dir, struct qstr *name, struct iattr *sattr,
- struct nfs_fh *fhandle, struct nfs_fattr *fattr)
+nfs3_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr)
{
- struct nfs_fattr dir_attr;
+ struct nfs_fh fhandle;
+ struct nfs_fattr fattr, dir_attr;
struct nfs3_mkdirargs arg = {
.fh = NFS_FH(dir),
- .name = name->name,
- .len = name->len,
+ .name = dentry->d_name.name,
+ .len = dentry->d_name.len,
.sattr = sattr
};
struct nfs3_diropres res = {
.dir_attr = &dir_attr,
- .fh = fhandle,
- .fattr = fattr
+ .fh = &fhandle,
+ .fattr = &fattr
};
int status;
- dprintk("NFS call mkdir %s\n", name->name);
+ dprintk("NFS call mkdir %s\n", dentry->d_name.name);
dir_attr.valid = 0;
- fattr->valid = 0;
+ fattr.valid = 0;
status = rpc_call(NFS_CLIENT(dir), NFS3PROC_MKDIR, &arg, &res, 0);
nfs_refresh_inode(dir, &dir_attr);
+ if (status == 0)
+ status = nfs_instantiate(dentry, &fhandle, &fattr);
dprintk("NFS reply mkdir: %d\n", status);
return status;
}
@@ -639,23 +624,24 @@ nfs3_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
}
static int
-nfs3_proc_mknod(struct inode *dir, struct qstr *name, struct iattr *sattr,
- dev_t rdev, struct nfs_fh *fh, struct nfs_fattr *fattr)
+nfs3_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
+ dev_t rdev)
{
- struct nfs_fattr dir_attr;
+ struct nfs_fh fh;
+ struct nfs_fattr fattr, dir_attr;
struct nfs3_mknodargs arg = {
.fh = NFS_FH(dir),
- .name = name->name,
- .len = name->len,
+ .name = dentry->d_name.name,
+ .len = dentry->d_name.len,
.sattr = sattr,
.rdev = rdev
};
struct nfs3_diropres res = {
.dir_attr = &dir_attr,
- .fh = fh,
- .fattr = fattr
+ .fh = &fh,
+ .fattr = &fattr
};
- int status;
+ int status;
switch (sattr->ia_mode & S_IFMT) {
case S_IFBLK: arg.type = NF3BLK; break;
@@ -665,12 +651,14 @@ nfs3_proc_mknod(struct inode *dir, struct qstr *name, struct iattr *sattr,
default: return -EINVAL;
}
- dprintk("NFS call mknod %s %u:%u\n", name->name,
+ dprintk("NFS call mknod %s %u:%u\n", dentry->d_name.name,
MAJOR(rdev), MINOR(rdev));
dir_attr.valid = 0;
- fattr->valid = 0;
+ fattr.valid = 0;
status = rpc_call(NFS_CLIENT(dir), NFS3PROC_MKNOD, &arg, &res, 0);
nfs_refresh_inode(dir, &dir_attr);
+ if (status == 0)
+ status = nfs_instantiate(dentry, &fh, &fattr);
dprintk("NFS reply mknod: %d\n", status);
return status;
}
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 7d56ca4d63b72..1d5cb3e80c3e9 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -37,6 +37,7 @@
#include <linux/mm.h>
#include <linux/utsname.h>
+#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/sunrpc/clnt.h>
@@ -57,16 +58,17 @@
static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *);
static int nfs4_async_handle_error(struct rpc_task *, struct nfs_server *);
static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry);
+static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struct nfs4_exception *exception);
extern u32 *nfs4_decode_dirent(u32 *p, struct nfs_entry *entry, int plus);
extern struct rpc_procinfo nfs4_procedures[];
extern nfs4_stateid zero_stateid;
/* Prevent leaks of NFSv4 errors into userland */
-static inline int nfs4_map_errors(int err)
+int nfs4_map_errors(int err)
{
if (err < -1000) {
- printk(KERN_WARNING "%s could not handle NFSv4 error %d\n",
+ dprintk("%s could not handle NFSv4 error %d\n",
__FUNCTION__, -err);
return -EIO;
}
@@ -188,6 +190,23 @@ static void update_changeattr(struct inode *inode, struct nfs4_change_info *cinf
nfsi->change_attr = cinfo->after;
}
+static void update_open_stateid(struct nfs4_state *state, nfs4_stateid *stateid, int open_flags)
+{
+ struct inode *inode = state->inode;
+
+ open_flags &= (FMODE_READ|FMODE_WRITE);
+ /* Protect against nfs4_find_state() */
+ spin_lock(&inode->i_lock);
+ state->state |= open_flags;
+ /* NB! List reordering - see the reclaim code for why. */
+ if ((open_flags & FMODE_WRITE) && 0 == state->nwriters++)
+ list_move(&state->open_states, &state->owner->so_states);
+ if (open_flags & FMODE_READ)
+ state->nreaders++;
+ memcpy(&state->stateid, stateid, sizeof(state->stateid));
+ spin_unlock(&inode->i_lock);
+}
+
/*
* OPEN_RECLAIM:
* reclaim state on the server after a reboot.
@@ -244,7 +263,7 @@ static int _nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *st
return status;
}
-int nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *state)
+static int nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *state)
{
struct nfs_server *server = NFS_SERVER(state->inode);
struct nfs4_exception exception = { };
@@ -332,7 +351,7 @@ 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)
+static inline int _nfs4_proc_open_confirm(struct rpc_clnt *clnt, const struct nfs_fh *fh, struct nfs4_state_owner *sp, nfs4_stateid *stateid)
{
struct nfs_open_confirmargs arg = {
.fh = fh,
@@ -355,11 +374,49 @@ static int _nfs4_proc_open_confirm(struct rpc_clnt *clnt, const struct nfs_fh *f
return status;
}
-static int _nfs4_do_access(struct inode *inode, struct rpc_cred *cred, int mask)
+static int _nfs4_proc_open(struct inode *dir, struct nfs4_state_owner *sp, struct nfs_openargs *o_arg, struct nfs_openres *o_res)
+{
+ struct nfs_server *server = NFS_SERVER(dir);
+ struct rpc_message msg = {
+ .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN],
+ .rpc_argp = o_arg,
+ .rpc_resp = o_res,
+ .rpc_cred = sp->so_cred,
+ };
+ int status;
+
+ /* Update sequence id. The caller must serialize! */
+ o_arg->seqid = sp->so_seqid;
+ o_arg->id = sp->so_id;
+ o_arg->clientid = sp->so_client->cl_clientid;
+
+ status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR);
+ nfs4_increment_seqid(status, sp);
+ if (status != 0)
+ goto out;
+ update_changeattr(dir, &o_res->cinfo);
+ if(o_res->rflags & NFS4_OPEN_RESULT_CONFIRM) {
+ status = _nfs4_proc_open_confirm(server->client, &o_res->fh,
+ sp, &o_res->stateid);
+ if (status != 0)
+ goto out;
+ }
+ 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;
+}
+
+static int _nfs4_do_access(struct inode *inode, struct rpc_cred *cred, int openflags)
{
struct nfs_access_entry cache;
+ int mask = 0;
int status;
+ if (openflags & FMODE_READ)
+ mask |= MAY_READ;
+ if (openflags & FMODE_WRITE)
+ mask |= MAY_WRITE;
status = nfs_access_get_cached(inode, cred, &cache);
if (status == 0)
goto out;
@@ -379,9 +436,103 @@ out:
}
/*
+ * OPEN_EXPIRED:
+ * reclaim state on the server after a network partition.
+ * Assumes caller holds the appropriate lock
+ */
+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 = {
+ .valid = 0,
+ };
+ 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,
+ .server = server,
+ };
+ int status = 0;
+
+ if (delegation != NULL && !(delegation->flags & NFS_DELEGATION_NEED_RECLAIM)) {
+ status = _nfs4_do_access(inode, sp->so_cred, state->state);
+ if (status < 0)
+ goto out;
+ memcpy(&state->stateid, &delegation->stateid, sizeof(state->stateid));
+ set_bit(NFS_DELEGATED_STATE, &state->flags);
+ goto out;
+ }
+ 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);
+ }
+out_nodeleg:
+ 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;
+}
+
+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;
+
+ 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_open_expired(sp, state, ctx->dentry);
+ put_nfs_open_context(ctx);
+ return status;
+ }
+ spin_unlock(&state->inode->i_lock);
+ return -ENOENT;
+}
+
+/*
* Returns an nfs4_state + an extra reference to the inode
*/
-int _nfs4_open_delegated(struct inode *inode, int flags, struct rpc_cred *cred, struct nfs4_state **res)
+static int _nfs4_open_delegated(struct inode *inode, int flags, struct rpc_cred *cred, struct nfs4_state **res)
{
struct nfs_delegation *delegation;
struct nfs_server *server = NFS_SERVER(inode);
@@ -390,7 +541,6 @@ int _nfs4_open_delegated(struct inode *inode, int flags, struct rpc_cred *cred,
struct nfs4_state_owner *sp = NULL;
struct nfs4_state *state = NULL;
int open_flags = flags & (FMODE_READ|FMODE_WRITE);
- int mask = 0;
int err;
/* Protect against reboot recovery - NOTE ORDER! */
@@ -424,20 +574,12 @@ int _nfs4_open_delegated(struct inode *inode, int flags, struct rpc_cred *cred,
goto out_err;
lock_kernel();
- err = _nfs4_do_access(inode, cred, mask);
+ err = _nfs4_do_access(inode, cred, open_flags);
unlock_kernel();
if (err != 0)
goto out_err;
- spin_lock(&inode->i_lock);
- memcpy(state->stateid.data, delegation->stateid.data,
- sizeof(state->stateid.data));
- state->state |= open_flags;
- if (open_flags & FMODE_READ)
- state->nreaders++;
- if (open_flags & FMODE_WRITE)
- state->nwriters++;
set_bit(NFS_DELEGATED_STATE, &state->flags);
- spin_unlock(&inode->i_lock);
+ update_open_stateid(state, &delegation->stateid, open_flags);
out_ok:
up(&sp->so_sema);
nfs4_put_state_owner(sp);
@@ -500,12 +642,6 @@ static int _nfs4_do_open(struct inode *dir, struct dentry *dentry, int flags, st
.f_attr = &f_attr,
.server = server,
};
- struct rpc_message msg = {
- .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN],
- .rpc_argp = &o_arg,
- .rpc_resp = &o_res,
- .rpc_cred = cred,
- };
/* Protect against reboot recovery conflicts */
down_read(&clp->cl_sem);
@@ -522,26 +658,10 @@ static int _nfs4_do_open(struct inode *dir, struct dentry *dentry, int flags, st
o_arg.u.attrs = sattr;
/* Serialization for the sequence id */
down(&sp->so_sema);
- o_arg.seqid = sp->so_seqid;
- o_arg.id = sp->so_id;
- o_arg.clientid = clp->cl_clientid,
- status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR);
- nfs4_increment_seqid(status, sp);
- if (status)
+ status = _nfs4_proc_open(dir, sp, &o_arg, &o_res);
+ if (status != 0)
goto out_err;
- update_changeattr(dir, &o_res.cinfo);
- if(o_res.rflags & NFS4_OPEN_RESULT_CONFIRM) {
- status = _nfs4_proc_open_confirm(server->client, &o_res.fh,
- sp, &o_res.stateid);
- if (status != 0)
- goto out_err;
- }
- if (!(f_attr.valid & NFS_ATTR_FATTR)) {
- status = server->rpc_ops->getattr(server, &o_res.fh, &f_attr);
- if (status < 0)
- goto out_err;
- }
status = -ENOMEM;
inode = nfs_fhget(dir->i_sb, &o_res.fh, &f_attr);
@@ -550,14 +670,7 @@ static int _nfs4_do_open(struct inode *dir, struct dentry *dentry, int flags, st
state = nfs4_get_open_state(inode, sp);
if (!state)
goto out_err;
- memcpy(&state->stateid, &o_res.stateid, sizeof(state->stateid));
- spin_lock(&inode->i_lock);
- if (flags & FMODE_READ)
- state->nreaders++;
- if (flags & FMODE_WRITE)
- state->nwriters++;
- state->state |= flags & (FMODE_READ|FMODE_WRITE);
- spin_unlock(&inode->i_lock);
+ update_open_stateid(state, &o_res.stateid, flags);
if (o_res.delegation_type != 0)
nfs_inode_set_delegation(inode, cred, &o_res);
up(&sp->so_sema);
@@ -581,7 +694,7 @@ out_err:
}
-struct nfs4_state *nfs4_do_open(struct inode *dir, struct dentry *dentry, int flags, struct iattr *sattr, struct rpc_cred *cred)
+static struct nfs4_state *nfs4_do_open(struct inode *dir, struct dentry *dentry, int flags, struct iattr *sattr, struct rpc_cred *cred)
{
struct nfs4_exception exception = { };
struct nfs4_state *res;
@@ -645,7 +758,7 @@ static int _nfs4_do_setattr(struct nfs_server *server, struct nfs_fattr *fattr,
return rpc_call_sync(server->client, &msg, 0);
}
-int nfs4_do_setattr(struct nfs_server *server, struct nfs_fattr *fattr,
+static int nfs4_do_setattr(struct nfs_server *server, struct nfs_fattr *fattr,
struct nfs_fh *fhandle, struct iattr *sattr,
struct nfs4_state *state)
{
@@ -680,7 +793,6 @@ static void nfs4_close_done(struct rpc_task *task)
nfs4_increment_seqid(task->tk_status, sp);
switch (task->tk_status) {
case 0:
- state->state = calldata->arg.open_flags;
memcpy(&state->stateid, &calldata->res.stateid,
sizeof(state->stateid));
break;
@@ -695,6 +807,7 @@ static void nfs4_close_done(struct rpc_task *task)
return;
}
}
+ state->state = calldata->arg.open_flags;
nfs4_put_open_state(state);
up(&sp->so_sema);
nfs4_put_state_owner(sp);
@@ -774,6 +887,8 @@ nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
}
cred = rpcauth_lookupcred(NFS_SERVER(dir)->client->cl_auth, 0);
+ if (IS_ERR(cred))
+ return (struct inode *)cred;
state = nfs4_do_open(dir, dentry, nd->intent.open.flags, &attr, cred);
put_rpccred(cred);
if (IS_ERR(state))
@@ -789,6 +904,8 @@ nfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags)
struct inode *inode;
cred = rpcauth_lookupcred(NFS_SERVER(dir)->client->cl_auth, 0);
+ if (IS_ERR(cred))
+ return PTR_ERR(cred);
state = nfs4_open_delegated(dentry->d_inode, openflags, cred);
if (IS_ERR(state))
state = nfs4_do_open(dir, dentry, openflags, NULL, cred);
@@ -1009,6 +1126,8 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
if (size_change) {
struct rpc_cred *cred = rpcauth_lookupcred(NFS_SERVER(inode)->client->cl_auth, 0);
+ if (IS_ERR(cred))
+ return PTR_ERR(cred);
state = nfs4_find_state(inode, cred, FMODE_WRITE);
if (state == NULL) {
state = nfs4_open_delegated(dentry->d_inode,
@@ -1315,33 +1434,37 @@ static int nfs4_proc_commit(struct nfs_write_data *cdata)
* opens the file O_RDONLY. This will all be resolved with the VFS changes.
*/
-static struct inode *
+static int
nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
int flags)
{
- struct inode *inode;
- struct nfs4_state *state = NULL;
+ struct nfs4_state *state;
struct rpc_cred *cred;
+ int status = 0;
cred = rpcauth_lookupcred(NFS_SERVER(dir)->client->cl_auth, 0);
+ if (IS_ERR(cred)) {
+ status = PTR_ERR(cred);
+ goto out;
+ }
state = nfs4_do_open(dir, dentry, flags, sattr, cred);
put_rpccred(cred);
- if (!IS_ERR(state)) {
- inode = state->inode;
- if (flags & O_EXCL) {
- struct nfs_fattr fattr;
- int status;
- status = nfs4_do_setattr(NFS_SERVER(dir), &fattr,
- NFS_FH(inode), sattr, state);
- if (status != 0) {
- nfs4_close_state(state, flags);
- iput(inode);
- inode = ERR_PTR(status);
- }
- }
- } else
- inode = (struct inode *)state;
- return inode;
+ if (IS_ERR(state)) {
+ status = PTR_ERR(state);
+ goto out;
+ }
+ d_instantiate(dentry, state->inode);
+ if (flags & O_EXCL) {
+ struct nfs_fattr fattr;
+ status = nfs4_do_setattr(NFS_SERVER(dir), &fattr,
+ NFS_FH(state->inode), sattr, state);
+ if (status == 0)
+ goto out;
+ } else if (flags != 0)
+ goto out;
+ nfs4_close_state(state, flags);
+out:
+ return status;
}
static int _nfs4_proc_remove(struct inode *dir, struct qstr *name)
@@ -1539,23 +1662,24 @@ static int nfs4_proc_symlink(struct inode *dir, struct qstr *name,
return err;
}
-static int _nfs4_proc_mkdir(struct inode *dir, struct qstr *name,
- struct iattr *sattr, struct nfs_fh *fhandle,
- struct nfs_fattr *fattr)
+static int _nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry,
+ struct iattr *sattr)
{
struct nfs_server *server = NFS_SERVER(dir);
+ struct nfs_fh fhandle;
+ struct nfs_fattr fattr;
struct nfs4_create_arg arg = {
.dir_fh = NFS_FH(dir),
.server = server,
- .name = name,
+ .name = &dentry->d_name,
.attrs = sattr,
.ftype = NF4DIR,
.bitmask = server->attr_bitmask,
};
struct nfs4_create_res res = {
.server = server,
- .fh = fhandle,
- .fattr = fattr,
+ .fh = &fhandle,
+ .fattr = &fattr,
};
struct rpc_message msg = {
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE],
@@ -1564,24 +1688,24 @@ static int _nfs4_proc_mkdir(struct inode *dir, struct qstr *name,
};
int status;
- fattr->valid = 0;
+ fattr.valid = 0;
status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
- if (!status)
+ if (!status) {
update_changeattr(dir, &res.dir_cinfo);
+ status = nfs_instantiate(dentry, &fhandle, &fattr);
+ }
return status;
}
-static int nfs4_proc_mkdir(struct inode *dir, struct qstr *name,
- struct iattr *sattr, struct nfs_fh *fhandle,
- struct nfs_fattr *fattr)
+static int nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry,
+ struct iattr *sattr)
{
struct nfs4_exception exception = { };
int err;
do {
err = nfs4_handle_exception(NFS_SERVER(dir),
- _nfs4_proc_mkdir(dir, name, sattr,
- fhandle, fattr),
+ _nfs4_proc_mkdir(dir, dentry, sattr),
&exception);
} while (exception.retry);
return err;
@@ -1596,6 +1720,7 @@ static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
.pages = &page,
.pgbase = 0,
.count = count,
+ .bitmask = NFS_SERVER(dentry->d_inode)->attr_bitmask,
};
struct nfs4_readdir_res res;
struct rpc_message msg = {
@@ -1630,22 +1755,23 @@ static int nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
return err;
}
-static int _nfs4_proc_mknod(struct inode *dir, struct qstr *name,
- struct iattr *sattr, dev_t rdev, struct nfs_fh *fh,
- struct nfs_fattr *fattr)
+static int _nfs4_proc_mknod(struct inode *dir, struct dentry *dentry,
+ struct iattr *sattr, dev_t rdev)
{
struct nfs_server *server = NFS_SERVER(dir);
+ struct nfs_fh fh;
+ struct nfs_fattr fattr;
struct nfs4_create_arg arg = {
.dir_fh = NFS_FH(dir),
.server = server,
- .name = name,
+ .name = &dentry->d_name,
.attrs = sattr,
.bitmask = server->attr_bitmask,
};
struct nfs4_create_res res = {
.server = server,
- .fh = fh,
- .fattr = fattr,
+ .fh = &fh,
+ .fattr = &fattr,
};
struct rpc_message msg = {
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE],
@@ -1655,7 +1781,7 @@ static int _nfs4_proc_mknod(struct inode *dir, struct qstr *name,
int status;
int mode = sattr->ia_mode;
- fattr->valid = 0;
+ fattr.valid = 0;
BUG_ON(!(sattr->ia_valid & ATTR_MODE));
BUG_ON(!S_ISFIFO(mode) && !S_ISBLK(mode) && !S_ISCHR(mode) && !S_ISSOCK(mode));
@@ -1675,21 +1801,21 @@ static int _nfs4_proc_mknod(struct inode *dir, struct qstr *name,
arg.ftype = NF4SOCK;
status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
- if (!status)
+ if (status == 0) {
update_changeattr(dir, &res.dir_cinfo);
+ status = nfs_instantiate(dentry, &fh, &fattr);
+ }
return status;
}
-static int nfs4_proc_mknod(struct inode *dir, struct qstr *name,
- struct iattr *sattr, dev_t rdev, struct nfs_fh *fh,
- struct nfs_fattr *fattr)
+static int nfs4_proc_mknod(struct inode *dir, struct dentry *dentry,
+ struct iattr *sattr, dev_t rdev)
{
struct nfs4_exception exception = { };
int err;
do {
err = nfs4_handle_exception(NFS_SERVER(dir),
- _nfs4_proc_mknod(dir, name, sattr, rdev,
- fh, fattr),
+ _nfs4_proc_mknod(dir, dentry, sattr, rdev),
&exception);
} while (exception.retry);
return err;
@@ -2001,8 +2127,8 @@ nfs4_proc_file_open(struct inode *inode, struct file *filp)
/* Find our open stateid */
cred = rpcauth_lookupcred(NFS_SERVER(inode)->client->cl_auth, 0);
- if (unlikely(cred == NULL))
- return -ENOMEM;
+ if (IS_ERR(cred))
+ return PTR_ERR(cred);
ctx = alloc_nfs_open_context(dentry, cred);
put_rpccred(cred);
if (unlikely(ctx == NULL))
@@ -2067,7 +2193,7 @@ nfs4_async_handle_error(struct rpc_task *task, struct nfs_server *server)
return 0;
}
-int nfs4_wait_clnt_recover(struct rpc_clnt *clnt, struct nfs4_client *clp)
+static int nfs4_wait_clnt_recover(struct rpc_clnt *clnt, struct nfs4_client *clp)
{
DEFINE_WAIT(wait);
sigset_t oldset;
@@ -2151,9 +2277,7 @@ int nfs4_handle_exception(struct nfs_server *server, int errorcode, struct nfs4_
int nfs4_proc_setclientid(struct nfs4_client *clp, u32 program, unsigned short port)
{
- static nfs4_verifier sc_verifier;
- static int initialized;
-
+ nfs4_verifier sc_verifier;
struct nfs4_setclientid setclientid = {
.sc_verifier = &sc_verifier,
.sc_prog = program,
@@ -2164,27 +2288,38 @@ int nfs4_proc_setclientid(struct nfs4_client *clp, u32 program, unsigned short p
.rpc_resp = clp,
.rpc_cred = clp->cl_cred,
};
+ u32 *p;
+ int loop = 0;
+ int status;
- if (!initialized) {
- struct timespec boot_time;
- u32 *p;
-
- initialized = 1;
- boot_time = CURRENT_TIME;
- p = (u32*)sc_verifier.data;
- *p++ = htonl((u32)boot_time.tv_sec);
- *p = htonl((u32)boot_time.tv_nsec);
+ p = (u32*)sc_verifier.data;
+ *p++ = htonl((u32)clp->cl_boot_time.tv_sec);
+ *p = htonl((u32)clp->cl_boot_time.tv_nsec);
+
+ for(;;) {
+ 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,
+ clp->cl_id_uniquifier);
+ setclientid.sc_netid_len = scnprintf(setclientid.sc_netid,
+ sizeof(setclientid.sc_netid), "tcp");
+ setclientid.sc_uaddr_len = scnprintf(setclientid.sc_uaddr,
+ sizeof(setclientid.sc_uaddr), "%s.%d.%d",
+ clp->cl_ipaddr, port >> 8, port & 255);
+
+ status = rpc_call_sync(clp->cl_rpcclient, &msg, 0);
+ if (status != -NFS4ERR_CLID_INUSE)
+ break;
+ if (signalled())
+ break;
+ if (loop++ & 1)
+ ssleep(clp->cl_lease_time + 1);
+ else
+ if (++clp->cl_id_uniquifier == 0)
+ break;
}
- setclientid.sc_name_len = scnprintf(setclientid.sc_name,
- sizeof(setclientid.sc_name), "%s/%u.%u.%u.%u",
- clp->cl_ipaddr, NIPQUAD(clp->cl_addr.s_addr));
- setclientid.sc_netid_len = scnprintf(setclientid.sc_netid,
- sizeof(setclientid.sc_netid), "tcp");
- setclientid.sc_uaddr_len = scnprintf(setclientid.sc_uaddr,
- sizeof(setclientid.sc_uaddr), "%s.%d.%d",
- clp->cl_ipaddr, port >> 8, port & 255);
-
- return rpc_call_sync(clp->cl_rpcclient, &msg, 0);
+ return status;
}
int
@@ -2361,6 +2496,25 @@ static int nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock *
return err;
}
+static int do_vfs_lock(struct file *file, struct file_lock *fl)
+{
+ int res = 0;
+ switch (fl->fl_flags & (FL_POSIX|FL_FLOCK)) {
+ case FL_POSIX:
+ res = posix_lock_file_wait(file, fl);
+ break;
+ case FL_FLOCK:
+ res = flock_lock_file_wait(file, fl);
+ break;
+ default:
+ BUG();
+ }
+ if (res < 0)
+ printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n",
+ __FUNCTION__);
+ return res;
+}
+
static int _nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *request)
{
struct inode *inode = state->inode;
@@ -2408,7 +2562,7 @@ static int _nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock
out:
up(&state->lock_sema);
if (status == 0)
- posix_lock_file(request->fl_file, request);
+ do_vfs_lock(request->fl_file, request);
up_read(&clp->cl_sem);
return status;
}
@@ -2500,11 +2654,16 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *r
return status;
}
-int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request)
+static int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request)
{
return _nfs4_do_setlk(state, F_SETLK, request, 1);
}
+static int nfs4_lock_expired(struct nfs4_state *state, struct file_lock *request)
+{
+ return _nfs4_do_setlk(state, F_SETLK, request, 0);
+}
+
static int _nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock *request)
{
struct nfs4_client *clp = state->owner->so_client;
@@ -2517,7 +2676,7 @@ static int _nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock
if (status == 0) {
/* Note: we always want to sleep here! */
request->fl_flags |= FL_SLEEP;
- if (posix_lock_file_wait(request->fl_file, request) < 0)
+ if (do_vfs_lock(request->fl_file, request) < 0)
printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n", __FUNCTION__);
}
up_read(&clp->cl_sem);
@@ -2574,6 +2733,16 @@ nfs4_proc_lock(struct file *filp, int cmd, struct file_lock *request)
return status;
}
+struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops = {
+ .recover_open = nfs4_open_reclaim,
+ .recover_lock = nfs4_lock_reclaim,
+};
+
+struct nfs4_state_recovery_ops nfs4_network_partition_recovery_ops = {
+ .recover_open = nfs4_open_expired,
+ .recover_lock = nfs4_lock_expired,
+};
+
struct nfs_rpc_ops nfs_v4_clientops = {
.version = 4, /* protocol version */
.dentry_ops = &nfs4_dentry_operations,
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 67b0f48984903..231cebce3c876 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -116,6 +116,7 @@ nfs4_alloc_client(struct in_addr *addr)
INIT_LIST_HEAD(&clp->cl_superblocks);
init_waitqueue_head(&clp->cl_waitq);
rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS4 client");
+ clp->cl_boot_time = CURRENT_TIME;
clp->cl_state = 1 << NFS4CLNT_OK;
return clp;
}
@@ -205,7 +206,7 @@ nfs4_put_client(struct nfs4_client *clp)
nfs4_free_client(clp);
}
-int nfs4_init_client(struct nfs4_client *clp)
+static int __nfs4_init_client(struct nfs4_client *clp)
{
int status = nfs4_proc_setclientid(clp, NFS4_CALLBACK, nfs_callback_tcpport);
if (status == 0)
@@ -215,6 +216,11 @@ int nfs4_init_client(struct nfs4_client *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)
{
@@ -274,8 +280,8 @@ nfs4_alloc_state_owner(void)
return sp;
}
-static void
-nfs4_unhash_state_owner(struct nfs4_state_owner *sp)
+void
+nfs4_drop_state_owner(struct nfs4_state_owner *sp)
{
struct nfs4_client *clp = sp->so_client;
spin_lock(&clp->cl_lock);
@@ -441,7 +447,9 @@ nfs4_get_open_state(struct inode *inode, struct nfs4_state_owner *owner)
if (state == NULL && new != NULL) {
state = new;
/* Caller *must* be holding owner->so_sem */
- list_add(&state->open_states, &owner->so_states);
+ /* Note: The reclaim code dictates that we add stateless
+ * and read-only stateids to the end of the list */
+ list_add_tail(&state->open_states, &owner->so_states);
state->owner = owner;
atomic_inc(&owner->so_count);
list_add(&state->inode_states, &nfsi->open_states);
@@ -497,8 +505,12 @@ void nfs4_close_state(struct nfs4_state *state, mode_t mode)
state->nreaders--;
if (mode & FMODE_WRITE)
state->nwriters--;
- if (state->nwriters == 0 && state->nreaders == 0)
- list_del_init(&state->inode_states);
+ if (state->nwriters == 0) {
+ if (state->nreaders == 0)
+ list_del_init(&state->inode_states);
+ /* See reclaim code */
+ list_move_tail(&state->open_states, &owner->so_states);
+ }
spin_unlock(&inode->i_lock);
newstate = 0;
if (state->state != 0) {
@@ -708,7 +720,7 @@ void nfs4_increment_seqid(int status, struct nfs4_state_owner *sp)
sp->so_seqid++;
/* If the server returns BAD_SEQID, unhash state_owner here */
if (status == -NFS4ERR_BAD_SEQID)
- nfs4_unhash_state_owner(sp);
+ nfs4_drop_state_owner(sp);
}
static int reclaimer(void *);
@@ -753,7 +765,7 @@ nfs4_schedule_state_recovery(struct nfs4_client *clp)
schedule_work(&clp->cl_recoverd);
}
-static int nfs4_reclaim_locks(struct nfs4_state *state)
+static int nfs4_reclaim_locks(struct nfs4_state_recovery_ops *ops, struct nfs4_state *state)
{
struct inode *inode = state->inode;
struct file_lock *fl;
@@ -764,7 +776,7 @@ static int nfs4_reclaim_locks(struct nfs4_state *state)
continue;
if (((struct nfs_open_context *)fl->fl_file->private_data)->state != state)
continue;
- status = nfs4_lock_reclaim(state, fl);
+ status = ops->recover_lock(state, fl);
if (status >= 0)
continue;
switch (status) {
@@ -786,20 +798,28 @@ out_err:
return status;
}
-static int nfs4_reclaim_open_state(struct nfs4_state_owner *sp)
+static int nfs4_reclaim_open_state(struct nfs4_state_recovery_ops *ops, struct nfs4_state_owner *sp)
{
struct nfs4_state *state;
struct nfs4_lock_state *lock;
int status = 0;
+ /* Note: we rely on the sp->so_states list being ordered
+ * so that we always reclaim open(O_RDWR) and/or open(O_WRITE)
+ * states first.
+ * This is needed to ensure that the server won't give us any
+ * read delegations that we have to return if, say, we are
+ * recovering after a network partition or a reboot from a
+ * server that doesn't support a grace period.
+ */
list_for_each_entry(state, &sp->so_states, open_states) {
if (state->state == 0)
continue;
- status = nfs4_open_reclaim(sp, state);
+ status = ops->recover_open(sp, state);
list_for_each_entry(lock, &state->lock_states, ls_locks)
lock->ls_flags &= ~NFS_LOCK_INITIALIZED;
if (status >= 0) {
- status = nfs4_reclaim_locks(state);
+ status = nfs4_reclaim_locks(ops, state);
if (status < 0)
goto out_err;
list_for_each_entry(lock, &state->lock_states, ls_locks) {
@@ -813,8 +833,7 @@ static int nfs4_reclaim_open_state(struct nfs4_state_owner *sp)
default:
printk(KERN_ERR "%s: unhandled error %d. Zeroing state\n",
__FUNCTION__, status);
- case -NFS4ERR_EXPIRED:
- case -NFS4ERR_NO_GRACE:
+ case -ENOENT:
case -NFS4ERR_RECLAIM_BAD:
case -NFS4ERR_RECLAIM_CONFLICT:
/*
@@ -826,6 +845,8 @@ static int nfs4_reclaim_open_state(struct nfs4_state_owner *sp)
/* Mark the file as being 'closed' */
state->state = 0;
break;
+ case -NFS4ERR_EXPIRED:
+ case -NFS4ERR_NO_GRACE:
case -NFS4ERR_STALE_CLIENTID:
goto out_err;
}
@@ -840,6 +861,7 @@ static int reclaimer(void *ptr)
struct reclaimer_args *args = (struct reclaimer_args *)ptr;
struct nfs4_client *clp = args->clp;
struct nfs4_state_owner *sp;
+ struct nfs4_state_recovery_ops *ops;
int status = 0;
daemonize("%u.%u.%u.%u-reclaim", NIPQUAD(clp->cl_addr));
@@ -856,20 +878,34 @@ static int reclaimer(void *ptr)
goto out;
restart_loop:
status = nfs4_proc_renew(clp);
- if (status == 0 || status == -NFS4ERR_CB_PATH_DOWN)
- goto out;
- status = nfs4_init_client(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;
+ };
+ status = __nfs4_init_client(clp);
if (status)
goto out_error;
- /* Mark all delagations for reclaim */
+ /* Mark all delegations for reclaim */
nfs_delegation_mark_reclaim(clp);
/* Note: list is protected by exclusive lock on cl->cl_sem */
list_for_each_entry(sp, &clp->cl_state_owners, so_list) {
- status = nfs4_reclaim_open_state(sp);
+ status = nfs4_reclaim_open_state(ops, sp);
if (status < 0) {
+ if (status == -NFS4ERR_NO_GRACE) {
+ ops = &nfs4_network_partition_recovery_ops;
+ status = nfs4_reclaim_open_state(ops, sp);
+ }
if (status == -NFS4ERR_STALE_CLIENTID)
goto restart_loop;
- goto out_error;
+ if (status == -NFS4ERR_EXPIRED)
+ goto restart_loop;
}
}
nfs_delegation_reap_unclaimed(clp);
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 481cb039626fc..5f4de05763c98 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -1010,8 +1010,13 @@ static int encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg
WRITE32(readdir->count >> 1); /* We're not doing readdirplus */
WRITE32(readdir->count);
WRITE32(2);
- WRITE32(FATTR4_WORD0_FILEID);
- WRITE32(0);
+ if (readdir->bitmask[1] & FATTR4_WORD1_MOUNTED_ON_FILEID) {
+ WRITE32(0);
+ WRITE32(FATTR4_WORD1_MOUNTED_ON_FILEID);
+ } else {
+ WRITE32(FATTR4_WORD0_FILEID);
+ WRITE32(0);
+ }
/* set up reply kvec
* toplevel_status + taglen + rescount + OP_PUTFH + status
@@ -3175,7 +3180,7 @@ static int decode_setclientid(struct xdr_stream *xdr, struct nfs4_client *clp)
READ_BUF(4);
READ32(len);
READ_BUF(len);
- return -EEXIST;
+ return -NFSERR_CLID_INUSE;
} else
return -nfs_stat_to_errno(nfserr);
@@ -3857,7 +3862,7 @@ static int nfs4_xdr_dec_delegreturn(struct rpc_rqst *rqstp, uint32_t *p, void *d
uint32_t *nfs4_decode_dirent(uint32_t *p, struct nfs_entry *entry, int plus)
{
- uint32_t bitmap[1] = {0};
+ uint32_t bitmap[2] = {0};
uint32_t len;
if (!*p++) {
@@ -3881,13 +3886,18 @@ uint32_t *nfs4_decode_dirent(uint32_t *p, struct nfs_entry *entry, int plus)
entry->ino = 1;
len = ntohl(*p++); /* bitmap length */
- if (len > 0) {
- bitmap[0] = ntohl(*p);
- p += len;
+ if (len-- > 0) {
+ bitmap[0] = ntohl(*p++);
+ if (len-- > 0) {
+ bitmap[1] = ntohl(*p++);
+ p += len;
+ }
}
len = XDR_QUADLEN(ntohl(*p++)); /* attribute buffer length */
if (len > 0) {
- if (bitmap[0] == FATTR4_WORD0_FILEID)
+ if (bitmap[0] == 0 && bitmap[1] == FATTR4_WORD1_MOUNTED_ON_FILEID)
+ xdr_decode_hyper(p, &entry->ino);
+ else if (bitmap[0] == FATTR4_WORD0_FILEID)
xdr_decode_hyper(p, &entry->ino);
p += len;
}
diff --git a/fs/nfs/nfsroot.c b/fs/nfs/nfsroot.c
index 8646159168625..fd5bc596fe8a7 100644
--- a/fs/nfs/nfsroot.c
+++ b/fs/nfs/nfsroot.c
@@ -124,7 +124,6 @@ enum {
Opt_soft, Opt_hard, Opt_intr,
Opt_nointr, Opt_posix, Opt_noposix, Opt_cto, Opt_nocto, Opt_ac,
Opt_noac, Opt_lock, Opt_nolock, Opt_v2, Opt_v3, Opt_udp, Opt_tcp,
- Opt_broken_suid,
/* Error token */
Opt_err
};
@@ -159,7 +158,6 @@ static match_table_t __initdata tokens = {
{Opt_udp, "udp"},
{Opt_tcp, "proto=tcp"},
{Opt_tcp, "tcp"},
- {Opt_broken_suid, "broken_suid"},
{Opt_err, NULL}
};
@@ -268,9 +266,6 @@ static int __init root_nfs_parse(char *name, char *buf)
case Opt_tcp:
nfs_data.flags |= NFS_MOUNT_TCP;
break;
- case Opt_broken_suid:
- nfs_data.flags |= NFS_MOUNT_BROKEN_SUID;
- break;
default :
return 0;
}
@@ -351,7 +346,7 @@ static void __init root_nfs_print(void)
#endif
-int __init root_nfs_init(void)
+static int __init root_nfs_init(void)
{
#ifdef NFSROOT_DEBUG
nfs_debug |= NFSDBG_ROOT;
@@ -379,15 +374,15 @@ int __init root_nfs_init(void)
* Parse NFS server and directory information passed on the kernel
* command line.
*/
-int __init nfs_root_setup(char *line)
+static int __init nfs_root_setup(char *line)
{
ROOT_DEV = Root_NFS;
if (line[0] == '/' || line[0] == ',' || (line[0] >= '0' && line[0] <= '9')) {
strlcpy(nfs_root_name, line, sizeof(nfs_root_name));
} else {
- int n = strlen(line) + strlen(NFS_ROOT);
+ int n = strlen(line) + sizeof(NFS_ROOT) - 1;
if (n >= sizeof(nfs_root_name))
- line[sizeof(nfs_root_name) - strlen(NFS_ROOT) - 1] = '\0';
+ line[sizeof(nfs_root_name) - sizeof(NFS_ROOT) - 2] = '\0';
sprintf(nfs_root_name, NFS_ROOT, line);
}
root_server_addr = root_nfs_parse_addr(nfs_root_name);
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c
index 3ddaaa1e93742..d31b4d6e5a5e2 100644
--- a/fs/nfs/proc.c
+++ b/fs/nfs/proc.c
@@ -212,7 +212,7 @@ static int nfs_proc_write(struct nfs_write_data *wdata)
return status < 0? status : wdata->res.count;
}
-static struct inode *
+static int
nfs_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
int flags)
{
@@ -233,37 +233,34 @@ nfs_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
fattr.valid = 0;
dprintk("NFS call create %s\n", dentry->d_name.name);
status = rpc_call(NFS_CLIENT(dir), NFSPROC_CREATE, &arg, &res, 0);
+ if (status == 0)
+ status = nfs_instantiate(dentry, &fhandle, &fattr);
dprintk("NFS reply create: %d\n", status);
- if (status == 0) {
- struct inode *inode;
- inode = nfs_fhget(dir->i_sb, &fhandle, &fattr);
- if (inode)
- return inode;
- status = -ENOMEM;
- }
- return ERR_PTR(status);
+ return status;
}
/*
* In NFSv2, mknod is grafted onto the create call.
*/
static int
-nfs_proc_mknod(struct inode *dir, struct qstr *name, struct iattr *sattr,
- dev_t rdev, struct nfs_fh *fhandle, struct nfs_fattr *fattr)
+nfs_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
+ dev_t rdev)
{
+ struct nfs_fh fhandle;
+ struct nfs_fattr fattr;
struct nfs_createargs arg = {
.fh = NFS_FH(dir),
- .name = name->name,
- .len = name->len,
+ .name = dentry->d_name.name,
+ .len = dentry->d_name.len,
.sattr = sattr
};
struct nfs_diropok res = {
- .fh = fhandle,
- .fattr = fattr
+ .fh = &fhandle,
+ .fattr = &fattr
};
- int status, mode;
+ int status, mode;
- dprintk("NFS call mknod %s\n", name->name);
+ dprintk("NFS call mknod %s\n", dentry->d_name.name);
mode = sattr->ia_mode;
if (S_ISFIFO(mode)) {
@@ -274,14 +271,16 @@ nfs_proc_mknod(struct inode *dir, struct qstr *name, struct iattr *sattr,
sattr->ia_size = new_encode_dev(rdev);/* get out your barf bag */
}
- fattr->valid = 0;
+ fattr.valid = 0;
status = rpc_call(NFS_CLIENT(dir), NFSPROC_CREATE, &arg, &res, 0);
if (status == -EINVAL && S_ISFIFO(mode)) {
sattr->ia_mode = mode;
- fattr->valid = 0;
+ fattr.valid = 0;
status = rpc_call(NFS_CLIENT(dir), NFSPROC_CREATE, &arg, &res, 0);
}
+ if (status == 0)
+ status = nfs_instantiate(dentry, &fhandle, &fattr);
dprintk("NFS reply mknod: %d\n", status);
return status;
}
@@ -398,24 +397,27 @@ nfs_proc_symlink(struct inode *dir, struct qstr *name, struct qstr *path,
}
static int
-nfs_proc_mkdir(struct inode *dir, struct qstr *name, struct iattr *sattr,
- struct nfs_fh *fhandle, struct nfs_fattr *fattr)
+nfs_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr)
{
+ struct nfs_fh fhandle;
+ struct nfs_fattr fattr;
struct nfs_createargs arg = {
.fh = NFS_FH(dir),
- .name = name->name,
- .len = name->len,
+ .name = dentry->d_name.name,
+ .len = dentry->d_name.len,
.sattr = sattr
};
struct nfs_diropok res = {
- .fh = fhandle,
- .fattr = fattr
+ .fh = &fhandle,
+ .fattr = &fattr
};
int status;
- dprintk("NFS call mkdir %s\n", name->name);
- fattr->valid = 0;
+ dprintk("NFS call mkdir %s\n", dentry->d_name.name);
+ fattr.valid = 0;
status = rpc_call(NFS_CLIENT(dir), NFSPROC_MKDIR, &arg, &res, 0);
+ if (status == 0)
+ status = nfs_instantiate(dentry, &fhandle, &fattr);
dprintk("NFS reply mkdir: %d\n", status);
return status;
}
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index cb6f7bfe373b2..a0042fb586341 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -370,7 +370,7 @@ out_bad:
return -ENOMEM;
}
-int
+static int
nfs_pagein_list(struct list_head *head, int rpages)
{
LIST_HEAD(one_request);
diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c
index 2b0a0cc642aa2..f732541a33329 100644
--- a/fs/nfs/unlink.c
+++ b/fs/nfs/unlink.c
@@ -167,6 +167,11 @@ nfs_async_unlink(struct dentry *dentry)
goto out;
memset(data, 0, sizeof(*data));
+ data->cred = rpcauth_lookupcred(clnt->cl_auth, 0);
+ if (IS_ERR(data->cred)) {
+ status = PTR_ERR(data->cred);
+ goto out_free;
+ }
data->dir = dget(dir);
data->dentry = dentry;
@@ -183,12 +188,14 @@ nfs_async_unlink(struct dentry *dentry)
spin_lock(&dentry->d_lock);
dentry->d_flags |= DCACHE_NFSFS_RENAMED;
spin_unlock(&dentry->d_lock);
- data->cred = rpcauth_lookupcred(clnt->cl_auth, 0);
rpc_sleep_on(&nfs_delete_queue, task, NULL, NULL);
status = 0;
out:
return status;
+out_free:
+ kfree(data);
+ return status;
}
/**
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index ad7eb9bdff462..6f7a4af3bc46d 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -80,14 +80,31 @@ static void nfs_writeback_done_partial(struct nfs_write_data *, int);
static void nfs_writeback_done_full(struct nfs_write_data *, int);
static int nfs_wait_on_write_congestion(struct address_space *, int);
static int nfs_wait_on_requests(struct inode *, unsigned long, unsigned int);
+static int nfs_flush_inode(struct inode *inode, unsigned long idx_start,
+ unsigned int npages, int how);
static kmem_cache_t *nfs_wdata_cachep;
mempool_t *nfs_wdata_mempool;
-mempool_t *nfs_commit_mempool;
+static mempool_t *nfs_commit_mempool;
static DECLARE_WAIT_QUEUE_HEAD(nfs_write_congestion);
-void nfs_writedata_release(struct rpc_task *task)
+static inline struct nfs_write_data *nfs_commit_alloc(void)
+{
+ struct nfs_write_data *p = mempool_alloc(nfs_commit_mempool, SLAB_NOFS);
+ if (p) {
+ memset(p, 0, sizeof(*p));
+ INIT_LIST_HEAD(&p->pages);
+ }
+ return p;
+}
+
+static inline void nfs_commit_free(struct nfs_write_data *p)
+{
+ mempool_free(p, nfs_commit_mempool);
+}
+
+static void nfs_writedata_release(struct rpc_task *task)
{
struct nfs_write_data *wdata = (struct nfs_write_data *)task->tk_calldata;
nfs_writedata_free(wdata);
@@ -990,7 +1007,7 @@ static int nfs_flush_one(struct list_head *head, struct inode *inode, int how)
return -ENOMEM;
}
-int
+static int
nfs_flush_list(struct list_head *head, int wpages, int how)
{
LIST_HEAD(one_request);
@@ -1240,7 +1257,7 @@ static void nfs_commit_rpcsetup(struct list_head *head,
/*
* Commit dirty pages
*/
-int
+static int
nfs_commit_list(struct list_head *head, int how)
{
struct nfs_write_data *data;
@@ -1314,8 +1331,8 @@ nfs_commit_done(struct rpc_task *task)
}
#endif
-int nfs_flush_inode(struct inode *inode, unsigned long idx_start,
- unsigned int npages, int how)
+static int nfs_flush_inode(struct inode *inode, unsigned long idx_start,
+ unsigned int npages, int how)
{
struct nfs_inode *nfsi = NFS_I(inode);
LIST_HEAD(head);
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
index 96c0ea8f60cea..9a11aa39e2e4e 100644
--- a/fs/nfsd/export.c
+++ b/fs/nfsd/export.c
@@ -79,9 +79,9 @@ void expkey_put(struct cache_head *item, struct cache_detail *cd)
}
}
-void expkey_request(struct cache_detail *cd,
- struct cache_head *h,
- char **bpp, int *blen)
+static void expkey_request(struct cache_detail *cd,
+ struct cache_head *h,
+ char **bpp, int *blen)
{
/* client fsidtype \xfsid */
struct svc_expkey *ek = container_of(h, struct svc_expkey, h);
@@ -95,7 +95,7 @@ void expkey_request(struct cache_detail *cd,
}
static struct svc_expkey *svc_expkey_lookup(struct svc_expkey *, int);
-int expkey_parse(struct cache_detail *cd, char *mesg, int mlen)
+static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen)
{
/* client fsidtype fsid [path] */
char *buf;
@@ -284,9 +284,9 @@ void svc_export_put(struct cache_head *item, struct cache_detail *cd)
}
}
-void svc_export_request(struct cache_detail *cd,
- struct cache_head *h,
- char **bpp, int *blen)
+static void svc_export_request(struct cache_detail *cd,
+ struct cache_head *h,
+ char **bpp, int *blen)
{
/* client path */
struct svc_export *exp = container_of(h, struct svc_export, h);
@@ -340,7 +340,7 @@ static int check_export(struct inode *inode, int flags)
}
-int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
+static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
{
/* client path expiry [flags anonuid anongid fsid] */
char *buf;
@@ -510,8 +510,8 @@ exp_find_key(svc_client *clp, int fsid_type, u32 *fsidv, struct cache_req *reqp)
return ek;
}
-int exp_set_key(svc_client *clp, int fsid_type, u32 *fsidv,
- struct svc_export *exp)
+static int exp_set_key(svc_client *clp, int fsid_type, u32 *fsidv,
+ struct svc_export *exp)
{
struct svc_expkey key, *ek;
@@ -999,7 +999,7 @@ static void e_stop(struct seq_file *m, void *p)
exp_readunlock();
}
-struct flags {
+static struct flags {
int flag;
char *name[2];
} expflags[] = {
diff --git a/fs/nfsd/lockd.c b/fs/nfsd/lockd.c
index 3397bec470855..7b889ff15ae63 100644
--- a/fs/nfsd/lockd.c
+++ b/fs/nfsd/lockd.c
@@ -60,7 +60,7 @@ nlm_fclose(struct file *filp)
fput(filp);
}
-struct nlmsvc_binding nfsd_nlm_ops = {
+static struct nlmsvc_binding nfsd_nlm_ops = {
.fopen = nlm_fopen, /* open file for locking */
.fclose = nlm_fclose, /* close file */
};
diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c
index effcd19130908..041380fe667b0 100644
--- a/fs/nfsd/nfs3proc.c
+++ b/fs/nfsd/nfs3proc.c
@@ -171,7 +171,7 @@ nfsd3_proc_read(struct svc_rqst *rqstp, struct nfsd3_readargs *argp,
svc_reserve(rqstp, ((1 + NFS3_POST_OP_ATTR_WORDS + 3)<<2) + resp->count +4);
fh_copy(&resp->fh, &argp->fh);
- nfserr = nfsd_read(rqstp, &resp->fh,
+ nfserr = nfsd_read(rqstp, &resp->fh, NULL,
argp->offset,
argp->vec, argp->vlen,
&resp->count);
@@ -201,7 +201,7 @@ nfsd3_proc_write(struct svc_rqst *rqstp, struct nfsd3_writeargs *argp,
fh_copy(&resp->fh, &argp->fh);
resp->committed = argp->stable;
- nfserr = nfsd_write(rqstp, &resp->fh,
+ nfserr = nfsd_write(rqstp, &resp->fh, NULL,
argp->offset,
argp->vec, argp->vlen,
argp->len,
diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
index 941881de48a1f..11f806835c5a6 100644
--- a/fs/nfsd/nfs3xdr.c
+++ b/fs/nfsd/nfs3xdr.c
@@ -801,6 +801,11 @@ compose_entry_fh(struct nfsd3_readdirres *cd, struct svc_fh *fhp,
if (isdotent(name, namlen)) {
if (namlen == 2) {
dchild = dget_parent(dparent);
+ if (dchild == dparent) {
+ /* filesystem root - cannot return filehandle for ".." */
+ dput(dchild);
+ return 1;
+ }
} else
dchild = dget(dparent);
} else
diff --git a/fs/nfsd/nfs4acl.c b/fs/nfsd/nfs4acl.c
index 172393942ac0c..11ebf6c4aa54c 100644
--- a/fs/nfsd/nfs4acl.c
+++ b/fs/nfsd/nfs4acl.c
@@ -49,12 +49,16 @@
/* mode bit translations: */
-#define NFS4_READ_MODE (NFS4_ACE_READ_DATA | NFS4_ACE_READ_NAMED_ATTRS)
-#define NFS4_WRITE_MODE (NFS4_ACE_WRITE_DATA | NFS4_ACE_WRITE_NAMED_ATTRS | NFS4_ACE_APPEND_DATA)
+#define NFS4_READ_MODE (NFS4_ACE_READ_DATA)
+#define NFS4_WRITE_MODE (NFS4_ACE_WRITE_DATA | NFS4_ACE_APPEND_DATA)
#define NFS4_EXECUTE_MODE NFS4_ACE_EXECUTE
#define NFS4_ANYONE_MODE (NFS4_ACE_READ_ATTRIBUTES | NFS4_ACE_READ_ACL | NFS4_ACE_SYNCHRONIZE)
#define NFS4_OWNER_MODE (NFS4_ACE_WRITE_ATTRIBUTES | NFS4_ACE_WRITE_ACL)
+/* We don't support these bits; insist they be neither allowed nor denied */
+#define NFS4_MASK_UNSUPP (NFS4_ACE_DELETE | NFS4_ACE_WRITE_OWNER \
+ | NFS4_ACE_READ_NAMED_ATTRS | NFS4_ACE_WRITE_NAMED_ATTRS)
+
/* flags used to simulate posix default ACLs */
#define NFS4_INHERITANCE_FLAGS (NFS4_ACE_FILE_INHERIT_ACE \
| NFS4_ACE_DIRECTORY_INHERIT_ACE | NFS4_ACE_INHERIT_ONLY_ACE)
@@ -83,12 +87,15 @@ mask_from_posix(unsigned short perm, unsigned int flags)
static u32
deny_mask(u32 allow_mask, unsigned int flags)
{
- u32 ret = ~allow_mask & ~NFS4_ACE_DELETE;
+ u32 ret = ~allow_mask & ~NFS4_MASK_UNSUPP;
if (!(flags & NFS4_ACL_DIR))
ret &= ~NFS4_ACE_DELETE_CHILD;
return ret;
}
+/* XXX: modify functions to return NFS errors; they're only ever
+ * used by nfs code, after all.... */
+
static int
mode_from_nfs4(u32 perm, unsigned short *mode, unsigned int flags)
{
@@ -940,35 +947,8 @@ match_who(struct nfs4_ace *ace, uid_t owner, gid_t group, uid_t who)
}
}
-/* 0 = granted, -EACCES = denied; mask is an nfsv4 mask, not mode bits */
-int
-nfs4_acl_permission(struct nfs4_acl *acl, uid_t owner, gid_t group,
- uid_t who, u32 mask)
-{
- struct nfs4_ace *ace;
- u32 allowed = 0;
-
- list_for_each_entry(ace, &acl->ace_head, l_ace) {
- if (!match_who(ace, group, owner, who))
- continue;
- switch (ace->type) {
- case NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE:
- allowed |= ace->access_mask;
- if ((allowed & mask) == mask)
- return 0;
- break;
- case NFS4_ACE_ACCESS_DENIED_ACE_TYPE:
- if (ace->access_mask & mask)
- return -EACCES;
- break;
- }
- }
- return -EACCES;
-}
-
EXPORT_SYMBOL(nfs4_acl_new);
EXPORT_SYMBOL(nfs4_acl_free);
EXPORT_SYMBOL(nfs4_acl_add_ace);
EXPORT_SYMBOL(nfs4_acl_get_whotype);
EXPORT_SYMBOL(nfs4_acl_write_who);
-EXPORT_SYMBOL(nfs4_acl_permission);
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index 1fe7f53d7b884..c70de9c2af746 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -38,6 +38,7 @@
#include <linux/list.h>
#include <linux/inet.h>
#include <linux/errno.h>
+#include <linux/delay.h>
#include <linux/sunrpc/xdr.h>
#include <linux/sunrpc/svc.h>
#include <linux/sunrpc/clnt.h>
@@ -246,6 +247,7 @@ nfs4_xdr_enc_cb_recall(struct rpc_rqst *req, u32 *p, struct nfs4_cb_recall *args
{
struct xdr_stream xdr;
struct nfs4_cb_compound_hdr hdr = {
+ .ident = args->cbr_ident,
.nops = 1,
};
@@ -308,7 +310,7 @@ nfs4_xdr_dec_cb_recall(struct rpc_rqst *rqstp, u32 *p)
if (status)
goto out;
status = decode_cb_op_hdr(&xdr, OP_CB_RECALL);
-out :
+out:
return status;
}
@@ -351,10 +353,8 @@ nfsd4_lookupcred(struct nfs4_client *clp, int taskflags)
{
struct auth_cred acred;
struct rpc_clnt *clnt = clp->cl_callback.cb_client;
- struct rpc_cred *ret = NULL;
+ struct rpc_cred *ret;
- if (!clnt)
- goto out;
get_group_info(clp->cl_cred.cr_group_info);
acred.uid = clp->cl_cred.cr_uid;
acred.gid = clp->cl_cred.cr_gid;
@@ -364,7 +364,6 @@ nfsd4_lookupcred(struct nfs4_client *clp, int taskflags)
clnt->cl_auth->au_ops->au_name);
ret = rpcauth_lookup_credcache(clnt->cl_auth, &acred, taskflags);
put_group_info(clp->cl_cred.cr_group_info);
-out:
return ret;
}
@@ -401,7 +400,7 @@ nfsd4_probe_callback(struct nfs4_client *clp)
/* Initialize timeout */
timeparms.to_initval = (NFSD_LEASE_TIME/4) * HZ;
- timeparms.to_retries = 5;
+ timeparms.to_retries = 0;
timeparms.to_maxval = (NFSD_LEASE_TIME/2) * HZ;
timeparms.to_exponential = 1;
@@ -431,10 +430,9 @@ nfsd4_probe_callback(struct nfs4_client *clp)
dprintk("NFSD: couldn't create callback client\n");
goto out_xprt;
}
- clnt->cl_intr = 1;
+ clnt->cl_intr = 0;
clnt->cl_softrtry = 1;
clnt->cl_chatty = 1;
- cb->cb_client = clnt;
/* Kick rpciod, put the call on the wire. */
@@ -444,10 +442,14 @@ nfsd4_probe_callback(struct nfs4_client *clp)
}
/* the task holds a reference to the nfs4_client struct */
+ cb->cb_client = clnt;
atomic_inc(&clp->cl_count);
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);
+ put_rpccred(msg.rpc_cred);
if (status != 0) {
dprintk("NFSD: asynchronous NFSPROC4_CB_NULL failed!\n");
@@ -456,6 +458,7 @@ nfsd4_probe_callback(struct nfs4_client *clp)
return;
out_rpciod:
+ atomic_dec(&clp->cl_count);
rpciod_down();
out_clnt:
rpc_shutdown_client(clnt);
@@ -489,95 +492,56 @@ out:
}
/*
- * Called with dp->dl_count incremented
- */
-static void
-nfs4_cb_recall_done(struct rpc_task *task)
-{
- struct nfs4_cb_recall *cbr = (struct nfs4_cb_recall *)task->tk_calldata;
- struct nfs4_delegation *dp = cbr->cbr_dp;
- int status;
-
- /* all is well... */
- if (task->tk_status == 0)
- goto out;
-
- /* network partition, retry nfsd4_cb_recall once. */
- if (task->tk_status == -EIO) {
- if (atomic_read(&dp->dl_recall_cnt) == 0)
- goto retry;
- else
- /* callback channel no longer available */
- atomic_set(&dp->dl_client->cl_callback.cb_set, 0);
- }
-
- /* Race: a recall occurred miliseconds after a delegation was granted.
- * Client may have received recall prior to delegation. retry recall
- * once.
- */
- if ((task->tk_status == -EBADHANDLE) || (task->tk_status == -NFS4ERR_BAD_STATEID)){
- if (atomic_read(&dp->dl_recall_cnt) == 0)
- goto retry;
- }
- atomic_set(&dp->dl_state, NFS4_RECALL_COMPLETE);
-
-out:
- if (atomic_dec_and_test(&dp->dl_count))
- atomic_set(&dp->dl_state, NFS4_REAP_DELEG);
- BUG_ON(atomic_read(&dp->dl_count) < 0);
- dprintk("NFSD: nfs4_cb_recall_done: dp %p dl_flock %p dl_count %d\n",dp, dp->dl_flock, atomic_read(&dp->dl_count));
- return;
-
-retry:
- atomic_inc(&dp->dl_recall_cnt);
- /* sleep 2 seconds before retrying recall */
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(2*HZ);
- status = nfsd4_cb_recall(dp);
- dprintk("NFSD: nfs4_cb_recall_done: retry status: %d dp %p dl_flock %p\n",status,dp, dp->dl_flock);
-}
-
-/*
* called with dp->dl_count inc'ed.
* nfs4_lock_state() may or may not have been called.
*/
-int
+void
nfsd4_cb_recall(struct nfs4_delegation *dp)
{
- struct nfs4_client *clp;
- struct rpc_clnt *clnt;
+ struct nfs4_client *clp = dp->dl_client;
+ struct rpc_clnt *clnt = clp->cl_callback.cb_client;
+ struct nfs4_cb_recall *cbr = &dp->dl_recall;
struct rpc_message msg = {
.rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_RECALL],
+ .rpc_argp = cbr,
};
- struct nfs4_cb_recall *cbr = &dp->dl_recall;
- int status;
+ int retries = 1;
+ int status = 0;
- dprintk("NFSD: nfsd4_cb_recall NFS4_enc_cb_recall_sz %d NFS4_dec_cb_recall_sz %d \n",NFS4_enc_cb_recall_sz,NFS4_dec_cb_recall_sz);
-
- clp = dp->dl_client;
- clnt = clp->cl_callback.cb_client;
- status = EIO;
if ((!atomic_read(&clp->cl_callback.cb_set)) || !clnt)
- goto out_free;
+ return;
- msg.rpc_argp = cbr;
- msg.rpc_resp = cbr;
- msg.rpc_cred = nfsd4_lookupcred(clp,0);
+ msg.rpc_cred = nfsd4_lookupcred(clp, 0);
+ if (IS_ERR(msg.rpc_cred))
+ goto out;
cbr->cbr_trunc = 0; /* XXX need to implement truncate optimization */
cbr->cbr_dp = dp;
- if ((status = rpc_call_async(clnt, &msg, RPC_TASK_SOFT,
- nfs4_cb_recall_done, cbr ))) {
- dprintk("NFSD: recall_delegation: rpc_call_async failed %d\n",
- status);
- goto out_fail;
+ status = rpc_call_sync(clnt, &msg, RPC_TASK_SOFT);
+ while (retries--) {
+ switch (status) {
+ case -EIO:
+ /* Network partition? */
+ case -EBADHANDLE:
+ case -NFS4ERR_BAD_STATEID:
+ /* Race: client probably got cb_recall
+ * before open reply granting delegation */
+ break;
+ default:
+ goto out_put_cred;
+ }
+ ssleep(2);
+ status = rpc_call_sync(clnt, &msg, RPC_TASK_SOFT);
}
+out_put_cred:
+ put_rpccred(msg.rpc_cred);
out:
- return status;
-out_fail:
- status = nfserrno(status);
- out_free:
- kfree(cbr);
- goto out;
+ if (status == -EIO)
+ atomic_set(&clp->cl_callback.cb_set, 0);
+ /* Success or failure, now we're either waiting for lease expiration
+ * or deleg_return. */
+ dprintk("NFSD: nfs4_cb_recall: dp %p dl_flock %p dl_count %d\n",dp, dp->dl_flock, atomic_read(&dp->dl_count));
+ nfs4_put_delegation(dp);
+ return;
}
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index 6c23964e6155e..e8158741e8b5c 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -117,7 +117,6 @@ do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_o
/* set reply cache */
fh_dup2(current_fh, &resfh);
- /* XXXJBF: keep a saved svc_fh struct instead?? */
open->op_stateowner->so_replay.rp_openfh_len =
resfh.fh_handle.fh_size;
memcpy(open->op_stateowner->so_replay.rp_openfh,
@@ -153,7 +152,7 @@ do_open_fhandle(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_
current_fh->fh_handle.fh_size);
open->op_truncate = (open->op_iattr.ia_valid & ATTR_SIZE) &&
- !open->op_iattr.ia_size;
+ (open->op_iattr.ia_size == 0);
status = do_open_permission(rqstp, current_fh, open);
@@ -198,30 +197,40 @@ nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open
}
if (status)
goto out;
- if (open->op_claim_type == NFS4_OPEN_CLAIM_NULL) {
- /*
- * This block of code will (1) set CURRENT_FH to the file being opened,
- * creating it if necessary, (2) set open->op_cinfo,
- * (3) set open->op_truncate if the file is to be truncated
- * after opening, (4) do permission checking.
- */
- status = do_open_lookup(rqstp, current_fh, open);
- if (status)
+ switch (open->op_claim_type) {
+ case NFS4_OPEN_CLAIM_NULL:
+ /*
+ * (1) set CURRENT_FH to the file being opened,
+ * creating it if necessary, (2) set open->op_cinfo,
+ * (3) set open->op_truncate if the file is to be
+ * truncated after opening, (4) do permission checking.
+ */
+ status = do_open_lookup(rqstp, current_fh, open);
+ if (status)
+ goto out;
+ break;
+ case NFS4_OPEN_CLAIM_PREVIOUS:
+ /*
+ * The CURRENT_FH is already set to the file being
+ * opened. (1) set open->op_cinfo, (2) set
+ * open->op_truncate if the file is to be truncated
+ * after opening, (3) do permission checking.
+ */
+ status = do_open_fhandle(rqstp, current_fh, open);
+ if (status)
+ goto out;
+ break;
+ case NFS4_OPEN_CLAIM_DELEGATE_CUR:
+ case NFS4_OPEN_CLAIM_DELEGATE_PREV:
+ printk("NFSD: unsupported OPEN claim type %d\n",
+ open->op_claim_type);
+ status = nfserr_notsupp;
goto out;
- } else if (open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS) {
- /*
- * The CURRENT_FH is already set to the file being opened. This
- * block of code will (1) set open->op_cinfo, (2) set
- * open->op_truncate if the file is to be truncated after opening,
- * (3) do permission checking.
- */
- status = do_open_fhandle(rqstp, current_fh, open);
- if (status)
+ default:
+ printk("NFSD: Invalid OPEN claim type %d\n",
+ open->op_claim_type);
+ status = nfserr_inval;
goto out;
- } else {
- printk("NFSD: unsupported OPEN claim type\n");
- status = nfserr_inval;
- goto out;
}
/*
* nfsd4_process_open2() does the actual opening of the file. If
@@ -464,37 +473,17 @@ static inline int
nfsd4_read(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_read *read)
{
int status;
+ struct file *filp = NULL;
/* no need to check permission - this will be done in nfsd_read() */
- if (nfs4_in_grace())
- return nfserr_grace;
if (read->rd_offset >= OFFSET_MAX)
return nfserr_inval;
nfs4_lock_state();
- status = nfs_ok;
- /* For stateid -1, we don't check share reservations. */
- if (ONE_STATEID(&read->rd_stateid)) {
- dprintk("NFSD: nfsd4_read: -1 stateid...\n");
- goto out;
- }
- /*
- * For stateid 0, the client doesn't have to have the file open, but
- * we still check for share reservation conflicts.
- */
- if (ZERO_STATEID(&read->rd_stateid)) {
- dprintk("NFSD: nfsd4_read: zero stateid...\n");
- if ((status = nfs4_share_conflict(current_fh, NFS4_SHARE_DENY_READ))) {
- dprintk("NFSD: nfsd4_read: conflicting share reservation!\n");
- goto out;
- }
- status = nfs_ok;
- goto out;
- }
/* check stateid */
- if ((status = nfs4_preprocess_stateid_op(current_fh, &read->rd_stateid,
- CHECK_FH | RD_STATE))) {
+ if ((status = nfs4_preprocess_stateid_op(current_fh, &read->rd_stateid,
+ CHECK_FH | RD_STATE, &filp))) {
dprintk("NFSD: nfsd4_read: couldn't process stateid!\n");
goto out;
}
@@ -503,6 +492,7 @@ out:
nfs4_unlock_state();
read->rd_rqstp = rqstp;
read->rd_fhp = current_fh;
+ read->rd_filp = filp;
return status;
}
@@ -587,25 +577,15 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_se
{
int status = nfs_ok;
- if (nfs4_in_grace())
- return nfserr_grace;
-
if (!current_fh->fh_dentry)
return nfserr_nofilehandle;
status = nfs_ok;
if (setattr->sa_iattr.ia_valid & ATTR_SIZE) {
-
- status = nfserr_bad_stateid;
- if (ZERO_STATEID(&setattr->sa_stateid) || ONE_STATEID(&setattr->sa_stateid)) {
- dprintk("NFSD: nfsd4_setattr: magic stateid!\n");
- goto out;
- }
-
nfs4_lock_state();
- if ((status = nfs4_preprocess_stateid_op(current_fh,
- &setattr->sa_stateid,
- CHECK_FH | WR_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;
}
@@ -629,44 +609,33 @@ static inline int
nfsd4_write(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_write *write)
{
stateid_t *stateid = &write->wr_stateid;
+ struct file *filp = NULL;
u32 *p;
int status = nfs_ok;
- if (nfs4_in_grace())
- return nfserr_grace;
-
/* no need to check permission - this will be done in nfsd_write() */
if (write->wr_offset >= OFFSET_MAX)
return nfserr_inval;
nfs4_lock_state();
- if (ZERO_STATEID(stateid) || ONE_STATEID(stateid)) {
- dprintk("NFSD: nfsd4_write: zero stateid...\n");
- if ((status = nfs4_share_conflict(current_fh, NFS4_SHARE_DENY_WRITE))) {
- dprintk("NFSD: nfsd4_write: conflicting share reservation!\n");
- goto out;
- }
- goto zero_stateid;
- }
- if ((status = nfs4_preprocess_stateid_op(current_fh, stateid,
- CHECK_FH | WR_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;
}
-
-zero_stateid:
-
nfs4_unlock_state();
+
write->wr_bytes_written = write->wr_buflen;
write->wr_how_written = write->wr_stable_how;
p = (u32 *)write->wr_verifier.data;
*p++ = nfssvc_boot.tv_sec;
*p++ = nfssvc_boot.tv_usec;
- status = nfsd_write(rqstp, current_fh, write->wr_offset,
- write->wr_vec, write->wr_vlen, write->wr_buflen,
- &write->wr_how_written);
+ status = nfsd_write(rqstp, current_fh, filp, write->wr_offset,
+ write->wr_vec, write->wr_vlen, write->wr_buflen,
+ &write->wr_how_written);
+
if (status == nfserr_symlink)
status = nfserr_inval;
return status;
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 498f30290fa9b..579f7fea79681 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -72,19 +72,15 @@ u32 add_perclient = 0;
u32 del_perclient = 0;
u32 alloc_file = 0;
u32 free_file = 0;
-u32 alloc_sowner = 0;
-u32 free_sowner = 0;
u32 vfsopen = 0;
u32 vfsclose = 0;
-u32 alloc_lsowner= 0;
u32 alloc_delegation= 0;
u32 free_delegation= 0;
/* forward declarations */
struct nfs4_stateid * find_stateid(stateid_t *stid, int flags);
static struct nfs4_delegation * find_delegation_stateid(struct inode *ino, stateid_t *stid);
-static void release_delegation(struct nfs4_delegation *dp);
-static void release_stateid_lockowner(struct nfs4_stateid *open_stp);
+static void release_stateid_lockowners(struct nfs4_stateid *open_stp);
/* Locking:
*
@@ -133,9 +129,11 @@ spinlock_t recall_lock;
static struct list_head del_recall_lru;
static struct nfs4_delegation *
-alloc_init_deleg(struct nfs4_client *clp, struct nfs4_file *fp, struct svc_fh *current_fh, u32 type)
+alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_fh *current_fh, u32 type)
{
struct nfs4_delegation *dp;
+ struct nfs4_file *fp = stp->st_file;
+ struct nfs4_callback *cb = &stp->st_stateowner->so_client->cl_callback;
dprintk("NFSD alloc_init_deleg\n");
if ((dp = kmalloc(sizeof(struct nfs4_delegation),
@@ -147,10 +145,11 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_file *fp, struct svc_fh *c
dp->dl_client = clp;
dp->dl_file = fp;
dp->dl_flock = NULL;
- dp->dl_stp = NULL;
+ get_file(stp->st_vfs_file);
+ dp->dl_vfs_file = stp->st_vfs_file;
dp->dl_type = type;
dp->dl_recall.cbr_dp = NULL;
- dp->dl_recall.cbr_ident = 0;
+ dp->dl_recall.cbr_ident = cb->cb_ident;
dp->dl_recall.cbr_trunc = 0;
dp->dl_stateid.si_boot = boot_time;
dp->dl_stateid.si_stateownerid = current_delegid++;
@@ -160,74 +159,53 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_file *fp, struct svc_fh *c
memcpy(dp->dl_fhval, &current_fh->fh_handle.fh_base,
current_fh->fh_handle.fh_size);
dp->dl_time = 0;
- atomic_set(&dp->dl_state, NFS4_NO_RECALL);
atomic_set(&dp->dl_count, 1);
- atomic_set(&dp->dl_recall_cnt, 0);
list_add(&dp->dl_del_perfile, &fp->fi_del_perfile);
list_add(&dp->dl_del_perclnt, &clp->cl_del_perclnt);
alloc_delegation++;
return dp;
}
-/*
- * Free the delegation structure.
- * Called with the recall_lock held.
- */
-static void
-nfs4_free_delegation(struct nfs4_delegation *dp)
+void
+nfs4_put_delegation(struct nfs4_delegation *dp)
{
- dprintk("NFSD: nfs4_free_delegation freeing dp %p\n",dp);
- list_del(&dp->dl_recall_lru);
- kfree(dp);
- free_delegation++;
+ if (atomic_dec_and_test(&dp->dl_count)) {
+ dprintk("NFSD: freeing dp %p\n",dp);
+ kfree(dp);
+ free_delegation++;
+ }
}
-/* release_delegation:
- *
- * Remove the associated file_lock first, then remove the delegation.
+/* Remove the associated file_lock first, then remove the delegation.
* lease_modify() is called to remove the FS_LEASE file_lock from
* the i_flock list, eventually calling nfsd's lock_manager
* fl_release_callback.
- *
- * call either:
- * nfsd_close : if last close, locks_remove_flock calls lease_modify.
- * otherwise, recalled state set to NFS4_RECALL_COMPLETE
- * so that it will be reaped by the laundromat service.
- * or
- * remove_lease (calls time_out_lease which calls lease_modify).
- * and nfs4_free_delegation.
- *
- * Called with nfs_lock_state() held.
- * Called with the recall_lock held.
*/
-
static void
-release_delegation(struct nfs4_delegation *dp)
+nfs4_close_delegation(struct nfs4_delegation *dp)
{
- /* delayed nfsd_close */
- if (dp->dl_stp) {
- struct file *filp = dp->dl_stp->st_vfs_file;
+ struct file *filp = dp->dl_vfs_file;
- dprintk("NFSD: release_delegation CLOSE\n");
- release_stateid_lockowner(dp->dl_stp);
- kfree(dp->dl_stp);
- dp->dl_stp = NULL;
- atomic_set(&dp->dl_state, NFS4_RECALL_COMPLETE);
- nfsd_close(filp);
- vfsclose++;
- } else {
- dprintk("NFSD: release_delegation remove lease dl_flock %p\n",
- dp->dl_flock);
- remove_lease(dp->dl_flock);
- list_del_init(&dp->dl_del_perfile);
- list_del_init(&dp->dl_del_perclnt);
- /* dl_count > 0 => outstanding recall rpc */
- dprintk("NFSD: release_delegation free deleg dl_count %d\n",
- atomic_read(&dp->dl_count));
- if ((atomic_read(&dp->dl_state) == NFS4_REAP_DELEG)
- || atomic_dec_and_test(&dp->dl_count))
- nfs4_free_delegation(dp);
- }
+ dprintk("NFSD: close_delegation dp %p\n",dp);
+ dp->dl_vfs_file = NULL;
+ /* The following nfsd_close may not actually close the file,
+ * but we want to remove the lease in any case. */
+ setlease(filp, F_UNLCK, &dp->dl_flock);
+ nfsd_close(filp);
+ vfsclose++;
+}
+
+/* Called under the state lock. */
+static void
+unhash_delegation(struct nfs4_delegation *dp)
+{
+ list_del_init(&dp->dl_del_perfile);
+ list_del_init(&dp->dl_del_perclnt);
+ spin_lock(&recall_lock);
+ list_del_init(&dp->dl_recall_lru);
+ spin_unlock(&recall_lock);
+ nfs4_close_delegation(dp);
+ nfs4_put_delegation(dp);
}
/*
@@ -260,7 +238,7 @@ release_delegation(struct nfs4_delegation *dp)
* for last close replay.
*/
static struct list_head reclaim_str_hashtbl[CLIENT_HASH_SIZE];
-static int reclaim_str_hashtbl_size;
+static int reclaim_str_hashtbl_size = 0;
static struct list_head conf_id_hashtbl[CLIENT_HASH_SIZE];
static struct list_head conf_str_hashtbl[CLIENT_HASH_SIZE];
static struct list_head unconf_str_hashtbl[CLIENT_HASH_SIZE];
@@ -339,6 +317,7 @@ expire_client(struct nfs4_client *clp)
struct nfs4_delegation *dp;
struct nfs4_callback *cb = &clp->cl_callback;
struct rpc_clnt *clnt = clp->cl_callback.cb_client;
+ struct list_head reaplist;
dprintk("NFSD: expire_client cl_count %d\n",
atomic_read(&clp->cl_count));
@@ -348,17 +327,22 @@ expire_client(struct nfs4_client *clp)
rpc_shutdown_client(clnt);
clnt = clp->cl_callback.cb_client = NULL;
}
+
+ INIT_LIST_HEAD(&reaplist);
spin_lock(&recall_lock);
while (!list_empty(&clp->cl_del_perclnt)) {
dp = list_entry(clp->cl_del_perclnt.next, struct nfs4_delegation, dl_del_perclnt);
- dprintk("NFSD: expire client. dp %p, dl_state %d, fp %p\n",
- dp, atomic_read(&dp->dl_state), dp->dl_flock);
-
- /* force release of delegation. */
- atomic_set(&dp->dl_state, NFS4_RECALL_COMPLETE);
- release_delegation(dp);
+ dprintk("NFSD: expire client. dp %p, fp %p\n", dp,
+ dp->dl_flock);
+ list_del_init(&dp->dl_del_perclnt);
+ list_move(&dp->dl_recall_lru, &reaplist);
}
spin_unlock(&recall_lock);
+ while (!list_empty(&reaplist)) {
+ dp = list_entry(reaplist.next, struct nfs4_delegation, dl_recall_lru);
+ list_del_init(&dp->dl_recall_lru);
+ unhash_delegation(dp);
+ }
list_del(&clp->cl_idhash);
list_del(&clp->cl_strhash);
list_del(&clp->cl_lru);
@@ -474,8 +458,9 @@ add_to_unconfirmed(struct nfs4_client *clp, unsigned int strhashval)
}
void
-move_to_confirmed(struct nfs4_client *clp, unsigned int idhashval)
+move_to_confirmed(struct nfs4_client *clp)
{
+ unsigned int idhashval = clientid_hashval(clp->cl_clientid.cl_id);
unsigned int strhashval;
dprintk("NFSD: move_to_confirm nfs4_client %p\n", clp);
@@ -488,6 +473,31 @@ move_to_confirmed(struct nfs4_client *clp, unsigned int idhashval)
renew_client(clp);
}
+static struct nfs4_client *
+find_confirmed_client(clientid_t *clid)
+{
+ struct nfs4_client *clp;
+ unsigned int idhashval = clientid_hashval(clid->cl_id);
+
+ list_for_each_entry(clp, &conf_id_hashtbl[idhashval], cl_idhash) {
+ if (cmp_clid(&clp->cl_clientid, clid))
+ return clp;
+ }
+ return NULL;
+}
+
+static struct nfs4_client *
+find_unconfirmed_client(clientid_t *clid)
+{
+ struct nfs4_client *clp;
+ unsigned int idhashval = clientid_hashval(clid->cl_id);
+
+ list_for_each_entry(clp, &unconf_id_hashtbl[idhashval], cl_idhash) {
+ if (cmp_clid(&clp->cl_clientid, clid))
+ return clp;
+ }
+ return NULL;
+}
/* a helper function for parse_callback */
static int
@@ -796,7 +806,6 @@ int
nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_setclientid_confirm *setclientid_confirm)
{
u32 ip_addr = rqstp->rq_addr.sin_addr.s_addr;
- unsigned int idhashval;
struct nfs4_client *clp, *conf = NULL, *unconf = NULL;
nfs4_verifier confirm = setclientid_confirm->sc_confirm;
clientid_t * clid = &setclientid_confirm->sc_clientid;
@@ -809,12 +818,9 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_setclientid_confi
* We get here on a DRC miss.
*/
- idhashval = clientid_hashval(clid->cl_id);
nfs4_lock_state();
- list_for_each_entry(clp, &conf_id_hashtbl[idhashval], cl_idhash) {
- if (!cmp_clid(&clp->cl_clientid, clid))
- continue;
-
+ clp = find_confirmed_client(clid);
+ if (clp) {
status = nfserr_inval;
/*
* Found a record for this clientid. If the IP addresses
@@ -828,11 +834,9 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_setclientid_confi
goto out;
}
conf = clp;
- break;
}
- list_for_each_entry(clp, &unconf_id_hashtbl[idhashval], cl_idhash) {
- if (!cmp_clid(&clp->cl_clientid, clid))
- continue;
+ clp = find_unconfirmed_client(clid);
+ if (clp) {
status = nfserr_inval;
if (clp->cl_addr != ip_addr) {
printk("NFSD: setclientid: string in use by client"
@@ -841,7 +845,6 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_setclientid_confi
goto out;
}
unconf = clp;
- break;
}
/* CASE 1:
* unconf record that matches input clientid and input confirm.
@@ -858,7 +861,7 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_setclientid_confi
else {
expire_client(conf);
clp = unconf;
- move_to_confirmed(unconf, idhashval);
+ move_to_confirmed(unconf);
status = nfs_ok;
}
goto out;
@@ -891,7 +894,7 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_setclientid_confi
} else {
status = nfs_ok;
clp = unconf;
- move_to_confirmed(unconf, idhashval);
+ move_to_confirmed(unconf);
}
goto out;
}
@@ -952,8 +955,11 @@ static struct list_head stateid_hashtbl[STATEID_HASH_SIZE];
/* OPEN Share state helper functions */
static inline struct nfs4_file *
-alloc_init_file(unsigned int hashval, struct inode *ino) {
+alloc_init_file(struct inode *ino)
+{
struct nfs4_file *fp;
+ unsigned int hashval = file_hashval(ino);
+
if ((fp = kmalloc(sizeof(struct nfs4_file),GFP_KERNEL))) {
INIT_LIST_HEAD(&fp->fi_hash);
INIT_LIST_HEAD(&fp->fi_perfile);
@@ -985,15 +991,38 @@ release_all_files(void)
}
}
-/* should use a slab cache */
+kmem_cache_t *stateowner_slab = NULL;
+
+static int
+nfsd4_init_slabs(void)
+{
+ stateowner_slab = kmem_cache_create("nfsd4_stateowners",
+ sizeof(struct nfs4_stateowner), 0, 0, NULL, NULL);
+ if (stateowner_slab == NULL) {
+ dprintk("nfsd4: out of memory while initializing nfsv4\n");
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+static void
+nfsd4_free_slabs(void)
+{
+ int status = 0;
+
+ if (stateowner_slab)
+ status = kmem_cache_destroy(stateowner_slab);
+ stateowner_slab = NULL;
+ BUG_ON(status);
+}
+
void
nfs4_free_stateowner(struct kref *kref)
{
struct nfs4_stateowner *sop =
container_of(kref, struct nfs4_stateowner, so_ref);
kfree(sop->so_owner.data);
- kfree(sop);
- free_sowner++;
+ kmem_cache_free(stateowner_slab, sop);
}
static inline struct nfs4_stateowner *
@@ -1001,14 +1030,14 @@ alloc_stateowner(struct xdr_netobj *owner)
{
struct nfs4_stateowner *sop;
- if ((sop = kmalloc(sizeof(struct nfs4_stateowner),GFP_KERNEL))) {
+ if ((sop = kmem_cache_alloc(stateowner_slab, GFP_KERNEL))) {
if ((sop->so_owner.data = kmalloc(owner->len, GFP_KERNEL))) {
memcpy(sop->so_owner.data, owner->data, owner->len);
sop->so_owner.len = owner->len;
kref_init(&sop->so_ref);
return sop;
}
- kfree(sop);
+ kmem_cache_free(stateowner_slab, sop);
}
return NULL;
}
@@ -1042,12 +1071,11 @@ alloc_init_open_stateowner(unsigned int strhashval, struct nfs4_client *clp, str
rp->rp_status = NFSERR_SERVERFAULT;
rp->rp_buflen = 0;
rp->rp_buf = rp->rp_ibuf;
- alloc_sowner++;
return sop;
}
static void
-release_stateid_lockowner(struct nfs4_stateid *open_stp)
+release_stateid_lockowners(struct nfs4_stateid *open_stp)
{
struct nfs4_stateowner *lock_sop;
@@ -1067,9 +1095,11 @@ unhash_stateowner(struct nfs4_stateowner *sop)
list_del(&sop->so_idhash);
list_del(&sop->so_strhash);
- list_del(&sop->so_perclient);
+ if (sop->so_is_open_owner) {
+ list_del(&sop->so_perclient);
+ del_perclient++;
+ }
list_del(&sop->so_perlockowner);
- del_perclient++;
while (!list_empty(&sop->so_perfilestate)) {
stp = list_entry(sop->so_perfilestate.next,
struct nfs4_stateid, st_perfilestate);
@@ -1089,7 +1119,8 @@ release_stateowner(struct nfs4_stateowner *sop)
}
static inline void
-init_stateid(struct nfs4_stateid *stp, struct nfs4_file *fp, struct nfs4_stateowner *sop, struct nfsd4_open *open) {
+init_stateid(struct nfs4_stateid *stp, struct nfs4_file *fp, struct nfsd4_open *open) {
+ struct nfs4_stateowner *sop = open->op_stateowner;
unsigned int hashval = stateid_hashval(sop->so_id, fp->fi_id);
INIT_LIST_HEAD(&stp->st_hash);
@@ -1112,37 +1143,22 @@ init_stateid(struct nfs4_stateid *stp, struct nfs4_file *fp, struct nfs4_stateow
__set_bit(open->op_share_deny, &stp->st_deny_bmap);
}
-/*
-* Because nfsd_close() can call locks_remove_flock() which removes leases,
-* delay nfsd_close() for delegations from the nfsd_open() clientid
-* until the delegation is reaped.
-*/
static void
release_stateid(struct nfs4_stateid *stp, int flags)
{
- struct nfs4_delegation *dp;
- struct nfs4_file *fp = stp->st_file;
+ struct file *filp = stp->st_vfs_file;
list_del(&stp->st_hash);
list_del_perfile++;
list_del(&stp->st_perfile);
list_del(&stp->st_perfilestate);
- if ((stp->st_vfs_set) && (flags & OPEN_STATE)) {
- list_for_each_entry(dp, &fp->fi_del_perfile, dl_del_perfile) {
- if(cmp_clid(&dp->dl_client->cl_clientid,
- &stp->st_stateowner->so_client->cl_clientid)) {
- dp->dl_stp = stp;
- return;
- }
- }
- release_stateid_lockowner(stp);
- nfsd_close(stp->st_vfs_file);
+ if (flags & OPEN_STATE) {
+ release_stateid_lockowners(stp);
+ stp->st_vfs_file = NULL;
+ nfsd_close(filp);
vfsclose++;
- } else if ((stp->st_vfs_set) && (flags & LOCK_STATE)) {
- struct file *filp = stp->st_vfs_file;
-
+ } else if (flags & LOCK_STATE)
locks_remove_posix(filp, (fl_owner_t) stp->st_stateowner);
- }
kfree(stp);
stp = NULL;
}
@@ -1167,8 +1183,7 @@ move_to_close_lru(struct nfs4_stateowner *sop)
}
void
-release_state_owner(struct nfs4_stateid *stp, struct nfs4_stateowner **sopp,
- int flag)
+release_state_owner(struct nfs4_stateid *stp, int flag)
{
struct nfs4_stateowner *sop = stp->st_stateowner;
struct nfs4_file *fp = stp->st_file;
@@ -1195,49 +1210,30 @@ cmp_owner_str(struct nfs4_stateowner *sop, struct xdr_netobj *owner, clientid_t
(sop->so_client->cl_clientid.cl_id == clid->cl_id));
}
-/* search ownerstr_hashtbl[] for owner */
-static int
-find_openstateowner_str(unsigned int hashval, struct nfsd4_open *open, struct nfs4_stateowner **op) {
- struct nfs4_stateowner *local = NULL;
-
- list_for_each_entry(local, &ownerstr_hashtbl[hashval], so_strhash) {
- if (!cmp_owner_str(local, &open->op_owner, &open->op_clientid))
- continue;
- *op = local;
- return(1);
- }
- return 0;
-}
-
-/* see if clientid is in confirmed hash table */
-static int
-verify_clientid(struct nfs4_client **client, clientid_t *clid) {
-
- struct nfs4_client *clp;
- unsigned int idhashval = clientid_hashval(clid->cl_id);
+static struct nfs4_stateowner *
+find_openstateowner_str(unsigned int hashval, struct nfsd4_open *open)
+{
+ struct nfs4_stateowner *so = NULL;
- list_for_each_entry(clp, &conf_id_hashtbl[idhashval], cl_idhash) {
- if (!cmp_clid(&clp->cl_clientid, clid))
- continue;
- *client = clp;
- return 1;
+ list_for_each_entry(so, &ownerstr_hashtbl[hashval], so_strhash) {
+ if (cmp_owner_str(so, &open->op_owner, &open->op_clientid))
+ return so;
}
- *client = NULL;
- return 0;
+ return NULL;
}
/* search file_hashtbl[] for file */
-static int
-find_file(unsigned int hashval, struct inode *ino, struct nfs4_file **fp) {
- struct nfs4_file *local = NULL;
+static struct nfs4_file *
+find_file(struct inode *ino)
+{
+ unsigned int hashval = file_hashval(ino);
+ struct nfs4_file *fp;
- list_for_each_entry(local, &file_hashtbl[hashval], fi_hash) {
- if (local->fi_inode == ino) {
- *fp = local;
- return(1);
- }
+ list_for_each_entry(fp, &file_hashtbl[hashval], fi_hash) {
+ if (fp->fi_inode == ino)
+ return fp;
}
- return 0;
+ return NULL;
}
#define TEST_ACCESS(x) ((x > 0 || x < 4)?1:0)
@@ -1284,14 +1280,13 @@ int
nfs4_share_conflict(struct svc_fh *current_fh, unsigned int deny_type)
{
struct inode *ino = current_fh->fh_dentry->d_inode;
- unsigned int fi_hashval;
struct nfs4_file *fp;
struct nfs4_stateid *stp;
dprintk("NFSD: nfs4_share_conflict\n");
- fi_hashval = file_hashval(ino);
- if (find_file(fi_hashval, ino, &fp)) {
+ fp = find_file(ino);
+ if (fp) {
/* Search for conflicting share reservations */
list_for_each_entry(stp, &fp->fi_perfile, st_perfile) {
if (test_bit(deny_type, &stp->st_deny_bmap) ||
@@ -1321,7 +1316,6 @@ do_recall(void *__dp)
daemonize("nfsv4-recall");
- atomic_inc(&dp->dl_count);
nfsd4_cb_recall(dp);
return 0;
}
@@ -1330,8 +1324,9 @@ do_recall(void *__dp)
* Spawn a thread to perform a recall on the delegation represented
* by the lease (file_lock)
*
- * Called from break_lease() with lock_kernel() held,
- *
+ * Called from break_lease() with lock_kernel() held.
+ * Note: we assume break_lease will only call this *once* for any given
+ * lease.
*/
static
void nfsd_break_deleg_cb(struct file_lock *fl)
@@ -1343,9 +1338,14 @@ void nfsd_break_deleg_cb(struct file_lock *fl)
if (!dp)
return;
- /* schedule delegation for recall */
+ /* We're assuming the state code never drops its reference
+ * without first removing the lease. Since we're in this lease
+ * callback (and since the lease code is serialized by the kernel
+ * lock) we know the server hasn't removed the lease yet, we know
+ * it's safe to take a reference: */
+ atomic_inc(&dp->dl_count);
+
spin_lock(&recall_lock);
- atomic_set(&dp->dl_state, NFS4_RECALL_IN_PROGRESS);
list_add_tail(&dp->dl_recall_lru, &del_recall_lru);
spin_unlock(&recall_lock);
@@ -1362,6 +1362,7 @@ void nfsd_break_deleg_cb(struct file_lock *fl)
printk(KERN_INFO "NFSD: Callback thread failed for "
"for client (clientid %08x/%08x)\n",
clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id);
+ nfs4_put_delegation(dp);
}
}
@@ -1375,11 +1376,10 @@ void nfsd_release_deleg_cb(struct file_lock *fl)
{
struct nfs4_delegation *dp = (struct nfs4_delegation *)fl->fl_owner;
- dprintk("NFSD nfsd_release_deleg_cb: fl %p dp %p dl_count %d, dl_state %d\n", fl,dp, atomic_read(&dp->dl_count), atomic_read(&dp->dl_state));
+ dprintk("NFSD nfsd_release_deleg_cb: fl %p dp %p dl_count %d\n", fl,dp, atomic_read(&dp->dl_count));
if (!(fl->fl_flags & FL_LEASE) || !dp)
return;
- atomic_set(&dp->dl_state,NFS4_RECALL_COMPLETE);
dp->dl_flock = NULL;
}
@@ -1399,14 +1399,42 @@ void nfsd_copy_lock_deleg_cb(struct file_lock *new, struct file_lock *fl)
dp->dl_flock = new;
}
+/*
+ * Called from __setlease() with lock_kernel() held
+ */
+static
+int nfsd_same_client_deleg_cb(struct file_lock *onlist, struct file_lock *try)
+{
+ struct nfs4_delegation *onlistd =
+ (struct nfs4_delegation *)onlist->fl_owner;
+ struct nfs4_delegation *tryd =
+ (struct nfs4_delegation *)try->fl_owner;
+
+ if (onlist->fl_lmops != try->fl_lmops)
+ return 0;
+
+ return onlistd->dl_client == tryd->dl_client;
+}
+
+
+static
+int nfsd_change_deleg_cb(struct file_lock **onlist, int arg)
+{
+ if (arg & F_UNLCK)
+ return lease_modify(onlist, arg);
+ else
+ return -EAGAIN;
+}
+
struct lock_manager_operations nfsd_lease_mng_ops = {
- .fl_break = nfsd_break_deleg_cb,
- .fl_release_private = nfsd_release_deleg_cb,
- .fl_copy_lock = nfsd_copy_lock_deleg_cb,
+ .fl_break = nfsd_break_deleg_cb,
+ .fl_release_private = nfsd_release_deleg_cb,
+ .fl_copy_lock = nfsd_copy_lock_deleg_cb,
+ .fl_mylease = nfsd_same_client_deleg_cb,
+ .fl_change = nfsd_change_deleg_cb,
};
-
/*
* nfsd4_process_open1()
* lookup stateowner.
@@ -1436,65 +1464,60 @@ nfsd4_process_open1(struct nfsd4_open *open)
if (!check_name(open->op_owner))
goto out;
- status = nfserr_stale_clientid;
if (STALE_CLIENTID(&open->op_clientid))
- return status;
+ return nfserr_stale_clientid;
strhashval = ownerstr_hashval(clientid->cl_id, open->op_owner);
- if (find_openstateowner_str(strhashval, open, &sop)) {
+ sop = find_openstateowner_str(strhashval, open);
+ if (sop) {
open->op_stateowner = sop;
/* check for replay */
if (open->op_seqid == sop->so_seqid){
- if (!sop->so_replay.rp_buflen) {
- /*
- * The original OPEN failed in 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");
- status = NFS_OK;
+ 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;
}
- /* replay: indicate to calling function */
- status = NFSERR_REPLAY_ME;
- return status;
- }
- if (sop->so_confirmed) {
- if (open->op_seqid == sop->so_seqid + 1) {
- status = nfs_ok;
+ } else if (sop->so_confirmed) {
+ if (open->op_seqid == sop->so_seqid + 1)
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);
}
- /* If we get here, we received and OPEN for an unconfirmed
- * nfs4_stateowner.
- * Since the sequid's are different, purge the
- * existing nfs4_stateowner, and instantiate a new one.
+ } 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.
*/
- clp = sop->so_client;
- release_stateowner(sop);
- goto instantiate_new_owner;
- }
- /* 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.
- *
- * XXX compare clp->cl_addr with rqstp addr?
- */
- status = nfserr_expired;
- if (!verify_clientid(&clp, clientid))
- goto out;
-instantiate_new_owner:
+ status = nfserr_expired;
+ clp = find_confirmed_client(clientid);
+ if (clp == NULL)
+ goto out;
+ }
status = nfserr_resource;
- if (!(sop = alloc_init_open_stateowner(strhashval, clp, open)))
+ sop = alloc_init_open_stateowner(strhashval, clp, open);
+ if (sop == NULL)
goto out;
open->op_stateowner = sop;
- status = nfs_ok;
renew:
+ status = nfs_ok;
renew_client(sop->so_client);
out:
if (status && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS)
@@ -1503,57 +1526,19 @@ out:
}
static int
-nfs4_deleg_conflict(u32 share, u32 dtype)
-{
- return (((share & NFS4_SHARE_ACCESS_WRITE) &&
- dtype == NFS4_OPEN_DELEGATE_READ) ||
- ((share & NFS4_SHARE_ACCESS_READ) &&
- dtype == NFS4_OPEN_DELEGATE_WRITE));
-}
-
-#define DONT_DELEGATE 8
-
-/*
- * nfs4_check_deleg_recall()
- *
- * Test any delegation that is currently within an incompleted recalled
- * state, and return NFSERR_DELAY for conflicting open share.
- * flag is set to DONT_DELEGATE for shares that match the deleg type.
- */
-static int
-nfs4_check_deleg_recall(struct nfs4_file *fp, struct nfsd4_open *op, int *flag)
-{
- struct nfs4_delegation *dp;
- int status = 0;
-
- list_for_each_entry(dp, &fp->fi_del_perfile, dl_del_perfile) {
- dprintk("NFSD: found delegation %p with dl_state %d\n",
- dp, atomic_read(&dp->dl_state));
- if (atomic_read(&dp->dl_state) == NFS4_RECALL_IN_PROGRESS) {
- if(nfs4_deleg_conflict(op->op_share_access, dp->dl_type))
- status = nfserr_jukebox;
- else
- *flag = DONT_DELEGATE;
- }
- }
- return status;
-}
-
-static int
-nfs4_check_open(struct nfs4_file *fp, struct nfs4_stateowner *sop, struct nfsd4_open *open, struct nfs4_stateid **stpp)
+nfs4_check_open(struct nfs4_file *fp, struct nfsd4_open *open, struct nfs4_stateid **stpp)
{
struct nfs4_stateid *local;
int status = nfserr_share_denied;
+ struct nfs4_stateowner *sop = open->op_stateowner;
list_for_each_entry(local, &fp->fi_perfile, st_perfile) {
- /* have we seen this open owner */
- if (local->st_stateowner == sop) {
- *stpp = local;
- continue;
- }
/* ignore lock owners */
if (local->st_stateowner->so_is_open_owner == 0)
continue;
+ /* remember if we have seen this open owner */
+ if (local->st_stateowner == sop)
+ *stpp = local;
/* check for conflicting share reservations */
if (!test_share(local, open))
goto out;
@@ -1582,11 +1567,25 @@ nfs4_new_open(struct svc_rqst *rqstp, struct nfs4_stateid **stpp,
return status;
}
vfsopen++;
- stp->st_vfs_set = 1;
*stpp = stp;
return 0;
}
+static inline int
+nfsd4_truncate(struct svc_rqst *rqstp, struct svc_fh *fh,
+ struct nfsd4_open *open)
+{
+ struct iattr iattr = {
+ .ia_valid = ATTR_SIZE,
+ .ia_size = 0,
+ };
+ if (!open->op_truncate)
+ return 0;
+ if (!(open->op_share_access & NFS4_SHARE_ACCESS_WRITE))
+ return -EINVAL;
+ return nfsd_setattr(rqstp, fh, &iattr, 0, (time_t)0);
+}
+
static int
nfs4_upgrade_open(struct svc_rqst *rqstp, struct svc_fh *cur_fh, struct nfs4_stateid *stp, struct nfsd4_open *open)
{
@@ -1599,29 +1598,22 @@ nfs4_upgrade_open(struct svc_rqst *rqstp, struct svc_fh *cur_fh, struct nfs4_sta
share_access = ~share_access;
share_access &= open->op_share_access;
- /* update the struct file */
- if (share_access & NFS4_SHARE_ACCESS_WRITE) {
- status = get_write_access(inode);
- if (status)
- return nfserrno(status);
- if (open->op_truncate) {
- struct iattr iattr = {
- .ia_valid = ATTR_SIZE,
- .ia_size = 0,
- };
- status = nfsd_setattr(rqstp, cur_fh, &iattr, 0,
- (time_t)0);
- if (status) {
- put_write_access(inode);
- return status;
- }
- }
+ if (!(share_access & NFS4_SHARE_ACCESS_WRITE))
+ return nfsd4_truncate(rqstp, cur_fh, open);
- /* remember the open */
- filp->f_mode = (filp->f_mode | FMODE_WRITE) & ~FMODE_READ;
- set_bit(open->op_share_access, &stp->st_access_bmap);
- set_bit(open->op_share_deny, &stp->st_deny_bmap);
+ status = get_write_access(inode);
+ if (status)
+ return nfserrno(status);
+ status = nfsd4_truncate(rqstp, cur_fh, open);
+ if (status) {
+ put_write_access(inode);
+ return status;
}
+ /* remember the open */
+ filp->f_mode = (filp->f_mode | FMODE_WRITE) & ~FMODE_READ;
+ set_bit(open->op_share_access, &stp->st_access_bmap);
+ set_bit(open->op_share_deny, &stp->st_deny_bmap);
+
return nfs_ok;
}
@@ -1644,33 +1636,29 @@ nfs4_set_claim_prev(struct nfsd4_open *open, int *status)
* Attempt to hand out a delegation.
*/
static void
-nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_stateid *stp, int *flag)
+nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_stateid *stp)
{
struct nfs4_delegation *dp;
struct nfs4_stateowner *sop = stp->st_stateowner;
struct nfs4_callback *cb = &sop->so_client->cl_callback;
struct file_lock fl, *flp = &fl;
- int status;
+ int status, flag = 0;
- if (*flag == DONT_DELEGATE) {
- *flag = NFS4_OPEN_DELEGATE_NONE;
- return;
- }
-
- /* set flag */
- *flag = NFS4_OPEN_DELEGATE_NONE;
+ flag = NFS4_OPEN_DELEGATE_NONE;
if (open->op_claim_type != NFS4_OPEN_CLAIM_NULL
|| !atomic_read(&cb->cb_set) || !sop->so_confirmed)
- return;
-
- if (!(open->op_share_access & NFS4_SHARE_ACCESS_WRITE))
- *flag = NFS4_OPEN_DELEGATE_READ;
+ goto out;
- else if (!(open->op_share_access & NFS4_SHARE_ACCESS_READ))
- *flag = NFS4_OPEN_DELEGATE_WRITE;
+ if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE)
+ flag = NFS4_OPEN_DELEGATE_WRITE;
+ else
+ flag = NFS4_OPEN_DELEGATE_READ;
- if (!(dp = alloc_init_deleg(sop->so_client, stp->st_file, fh, *flag)))
- return;
+ dp = alloc_init_deleg(sop->so_client, stp, fh, flag);
+ if (dp == NULL) {
+ flag = NFS4_OPEN_DELEGATE_NONE;
+ goto out;
+ }
locks_init_lock(&fl);
fl.fl_lmops = &nfsd_lease_mng_ops;
fl.fl_flags = FL_LEASE;
@@ -1679,15 +1667,18 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_sta
fl.fl_file = stp->st_vfs_file;
fl.fl_pid = current->tgid;
+ /* setlease checks to see if delegation should be handed out.
+ * the lock_manager callbacks fl_mylease and fl_change are used
+ */
if ((status = setlease(stp->st_vfs_file,
- *flag == NFS4_OPEN_DELEGATE_READ? F_RDLCK: F_WRLCK, &flp))) {
+ flag == NFS4_OPEN_DELEGATE_READ? F_RDLCK: F_WRLCK, &flp))) {
dprintk("NFSD: setlease failed [%d], no delegation\n", status);
list_del(&dp->dl_del_perfile);
list_del(&dp->dl_del_perclnt);
- kfree(dp);
+ nfs4_put_delegation(dp);
free_delegation++;
- *flag = NFS4_OPEN_DELEGATE_NONE;
- return;
+ flag = NFS4_OPEN_DELEGATE_NONE;
+ goto out;
}
memcpy(&open->op_delegate_stateid, &dp->dl_stateid, sizeof(dp->dl_stateid));
@@ -1697,6 +1688,8 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_sta
dp->dl_stateid.si_stateownerid,
dp->dl_stateid.si_fileid,
dp->dl_stateid.si_generation);
+out:
+ open->op_delegate_type = flag;
}
/*
@@ -1705,12 +1698,10 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_sta
int
nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open)
{
- struct nfs4_stateowner *sop = open->op_stateowner;
struct nfs4_file *fp = NULL;
struct inode *ino = current_fh->fh_dentry->d_inode;
- unsigned int fi_hashval;
struct nfs4_stateid *stp = NULL;
- int status, delegflag = 0;
+ int status;
status = nfserr_inval;
if (!TEST_ACCESS(open->op_share_access) || !TEST_DENY(open->op_share_deny))
@@ -1720,15 +1711,14 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
* and check for delegations in the process of being recalled.
* If not found, create the nfs4_file struct
*/
- fi_hashval = file_hashval(ino);
- if (find_file(fi_hashval, ino, &fp)) {
- if ((status = nfs4_check_open(fp, sop, open, &stp)))
- goto out;
- if ((status = nfs4_check_deleg_recall(fp, open, &delegflag)))
+ fp = find_file(ino);
+ if (fp) {
+ if ((status = nfs4_check_open(fp, open, &stp)))
goto out;
} else {
status = nfserr_resource;
- if ((fp = alloc_init_file(fi_hashval, ino)) == NULL)
+ fp = alloc_init_file(ino);
+ if (fp == NULL)
goto out;
}
@@ -1750,18 +1740,11 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
flags = MAY_READ;
if ((status = nfs4_new_open(rqstp, &stp, current_fh, flags)))
goto out;
- init_stateid(stp, fp, sop, open);
- if (open->op_truncate) {
- struct iattr iattr = {
- .ia_valid = ATTR_SIZE,
- .ia_size = 0,
- };
- status = nfsd_setattr(rqstp, current_fh, &iattr, 0,
- (time_t)0);
- if (status) {
- release_stateid(stp, OPEN_STATE);
- goto out;
- }
+ init_stateid(stp, fp, open);
+ status = nfsd4_truncate(rqstp, current_fh, open);
+ if (status) {
+ release_stateid(stp, OPEN_STATE);
+ goto out;
}
}
memcpy(&open->op_stateid, &stp->st_stateid, sizeof(stateid_t));
@@ -1770,8 +1753,7 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
* Attempt to hand out a delegation. No error return, because the
* OPEN succeeds even if we fail.
*/
- nfs4_open_delegation(current_fh, open, stp, &delegflag);
- open->op_delegate_type = delegflag;
+ nfs4_open_delegation(current_fh, open, stp);
status = nfs_ok;
@@ -1780,7 +1762,7 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
stp->st_stateid.si_fileid, stp->st_stateid.si_generation);
out:
/* take the opportunity to clean up unused state */
- if (fp && list_empty(&fp->fi_perfile))
+ if (fp && list_empty(&fp->fi_perfile) && list_empty(&fp->fi_del_perfile))
release_file(fp);
/* CLAIM_PREVIOUS has different error returns */
@@ -1803,7 +1785,6 @@ int
nfsd4_renew(clientid_t *clid)
{
struct nfs4_client *clp;
- unsigned int idhashval;
int status;
nfs4_lock_state();
@@ -1812,27 +1793,19 @@ nfsd4_renew(clientid_t *clid)
status = nfserr_stale_clientid;
if (STALE_CLIENTID(clid))
goto out;
- status = nfs_ok;
- idhashval = clientid_hashval(clid->cl_id);
- list_for_each_entry(clp, &conf_id_hashtbl[idhashval], cl_idhash) {
- if (!cmp_clid(&clp->cl_clientid, clid))
- continue;
- renew_client(clp);
+ clp = find_confirmed_client(clid);
+ status = nfserr_expired;
+ if (clp == NULL) {
+ /* We assume the client took too long to RENEW. */
+ dprintk("nfsd4_renew: clientid not found!\n");
goto out;
}
- list_for_each_entry(clp, &unconf_id_hashtbl[idhashval], cl_idhash) {
- if (!cmp_clid(&clp->cl_clientid, clid))
- continue;
- renew_client(clp);
- goto out;
- }
- /*
- * Couldn't find an nfs4_client for this clientid.
- * Presumably this is because the client took too long to
- * RENEW, so return NFS4ERR_EXPIRED.
- */
- dprintk("nfsd4_renew: clientid not found!\n");
- status = nfserr_expired;
+ renew_client(clp);
+ status = nfserr_cb_path_down;
+ if (!list_empty(&clp->cl_del_perclnt)
+ && !atomic_read(&clp->cl_callback.cb_set))
+ goto out;
+ status = nfs_ok;
out:
nfs4_unlock_state();
return status;
@@ -1844,7 +1817,7 @@ nfs4_laundromat(void)
struct nfs4_client *clp;
struct nfs4_stateowner *sop;
struct nfs4_delegation *dp;
- struct list_head *pos, *next;
+ struct list_head *pos, *next, reaplist;
time_t cutoff = get_seconds() - NFSD_LEASE_TIME;
time_t t, clientid_val = NFSD_LEASE_TIME;
time_t u, test_val = NFSD_LEASE_TIME;
@@ -1864,23 +1837,26 @@ nfs4_laundromat(void)
clp->cl_clientid.cl_id);
expire_client(clp);
}
+ INIT_LIST_HEAD(&reaplist);
spin_lock(&recall_lock);
list_for_each_safe(pos, next, &del_recall_lru) {
dp = list_entry (pos, struct nfs4_delegation, dl_recall_lru);
- if (atomic_read(&dp->dl_state) == NFS4_RECALL_COMPLETE)
- goto reap;
if (time_after((unsigned long)dp->dl_time, (unsigned long)cutoff)) {
u = dp->dl_time - cutoff;
if (test_val > u)
test_val = u;
break;
}
-reap:
dprintk("NFSD: purging unused delegation dp %p, fp %p\n",
dp, dp->dl_flock);
- release_delegation(dp);
+ list_move(&dp->dl_recall_lru, &reaplist);
}
spin_unlock(&recall_lock);
+ list_for_each_safe(pos, next, &reaplist) {
+ dp = list_entry (pos, struct nfs4_delegation, dl_recall_lru);
+ list_del_init(&dp->dl_recall_lru);
+ unhash_delegation(dp);
+ }
test_val = NFSD_LEASE_TIME;
list_for_each_safe(pos, next, &close_lru) {
sop = list_entry(pos, struct nfs4_stateowner, so_close_lru);
@@ -1931,8 +1907,7 @@ find_openstateowner_id(u32 st_id, int flags) {
static inline int
nfs4_check_fh(struct svc_fh *fhp, struct nfs4_stateid *stp)
{
- return (stp->st_vfs_set == 0 ||
- fhp->fh_dentry->d_inode != stp->st_vfs_file->f_dentry->d_inode);
+ return fhp->fh_dentry->d_inode != stp->st_vfs_file->f_dentry->d_inode;
}
static int
@@ -1950,7 +1925,8 @@ static inline int
access_permit_read(unsigned long access_bmap)
{
return test_bit(NFS4_SHARE_ACCESS_READ, &access_bmap) ||
- test_bit(NFS4_SHARE_ACCESS_BOTH, &access_bmap);
+ test_bit(NFS4_SHARE_ACCESS_BOTH, &access_bmap) ||
+ test_bit(NFS4_SHARE_ACCESS_WRITE, &access_bmap);
}
static inline int
@@ -1974,34 +1950,69 @@ out:
return status;
}
-static int
+static inline int
nfs4_check_delegmode(struct nfs4_delegation *dp, int flags)
{
- int status = nfserr_openmode;
+ if ((flags & WR_STATE) && (dp->dl_type == NFS4_OPEN_DELEGATE_READ))
+ return nfserr_openmode;
+ else
+ return nfs_ok;
+}
- if ((flags & WR_STATE) & (dp->dl_type == NFS4_OPEN_DELEGATE_READ))
- goto out;
- if ((flags & RD_STATE) & (dp->dl_type == NFS4_OPEN_DELEGATE_WRITE))
- goto out;
- status = nfs_ok;
-out:
- return status;
+static inline int
+check_special_stateids(svc_fh *current_fh, stateid_t *stateid, int flags)
+{
+ /* Trying to call delegreturn with a special stateid? Yuch: */
+ if (!(flags & (RD_STATE | WR_STATE)))
+ return nfserr_bad_stateid;
+ else if (ONE_STATEID(stateid) && (flags & RD_STATE))
+ return nfs_ok;
+ else if (nfs4_in_grace()) {
+ /* Answer in remaining cases depends on existance of
+ * conflicting state; so we must wait out the grace period. */
+ return nfserr_grace;
+ } else if (flags & WR_STATE)
+ return nfs4_share_conflict(current_fh,
+ NFS4_SHARE_DENY_WRITE);
+ else /* (flags & RD_STATE) && ZERO_STATEID(stateid) */
+ return nfs4_share_conflict(current_fh,
+ NFS4_SHARE_DENY_READ);
+}
+
+/*
+ * Allow READ/WRITE during grace period on recovered state only for files
+ * that are not able to provide mandatory locking.
+ */
+static inline int
+io_during_grace_disallowed(struct inode *inode, int flags)
+{
+ return nfs4_in_grace() && (flags & (RD_STATE | WR_STATE))
+ && MANDATORY_LOCK(inode);
}
/*
* Checks for stateid operations
*/
int
-nfs4_preprocess_stateid_op(struct svc_fh *current_fh, stateid_t *stateid, int flags)
+nfs4_preprocess_stateid_op(struct svc_fh *current_fh, stateid_t *stateid, int flags, struct file **filpp)
{
struct nfs4_stateid *stp = NULL;
struct nfs4_delegation *dp = NULL;
stateid_t *stidp;
+ struct inode *ino = current_fh->fh_dentry->d_inode;
int status;
dprintk("NFSD: preprocess_stateid_op: stateid = (%08x/%08x/%08x/%08x)\n",
stateid->si_boot, stateid->si_stateownerid,
stateid->si_fileid, stateid->si_generation);
+ if (filpp)
+ *filpp = NULL;
+
+ if (io_during_grace_disallowed(ino, flags))
+ return nfserr_grace;
+
+ if (ZERO_STATEID(stateid) || ONE_STATEID(stateid))
+ return check_special_stateids(current_fh, stateid, flags);
/* STALE STATEID */
status = nfserr_stale_stateid;
@@ -2011,16 +2022,18 @@ nfs4_preprocess_stateid_op(struct svc_fh *current_fh, stateid_t *stateid, int fl
/* BAD STATEID */
status = nfserr_bad_stateid;
if (!stateid->si_fileid) { /* delegation stateid */
- struct inode *ino = current_fh->fh_dentry->d_inode;
-
if(!(dp = find_delegation_stateid(ino, stateid))) {
dprintk("NFSD: delegation stateid not found\n");
+ if (nfs4_in_grace())
+ status = nfserr_grace;
goto out;
}
stidp = &dp->dl_stateid;
} else { /* open or lock stateid */
if (!(stp = find_stateid(stateid, flags))) {
dprintk("NFSD: open or lock stateid not found\n");
+ if (nfs4_in_grace())
+ status = nfserr_grace;
goto out;
}
if ((flags & CHECK_FH) && nfs4_check_fh(current_fh, stp))
@@ -2040,16 +2053,16 @@ nfs4_preprocess_stateid_op(struct svc_fh *current_fh, stateid_t *stateid, int fl
if ((status = nfs4_check_openmode(stp,flags)))
goto out;
renew_client(stp->st_stateowner->so_client);
+ if (filpp)
+ *filpp = stp->st_vfs_file;
} else if (dp) {
if ((status = nfs4_check_delegmode(dp, flags)))
goto out;
renew_client(dp->dl_client);
- if (flags & DELEG_RET) {
- atomic_set(&dp->dl_state,NFS4_RECALL_COMPLETE);
- spin_lock(&recall_lock);
- release_delegation(dp);
- spin_unlock(&recall_lock);
- }
+ if (flags & DELEG_RET)
+ unhash_delegation(dp);
+ if (filpp)
+ *filpp = dp->dl_vfs_file;
}
status = nfs_ok;
out:
@@ -2117,7 +2130,6 @@ nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *statei
if ((flags & CHECK_FH) && nfs4_check_fh(current_fh, stp)) {
printk("NFSD: preprocess_seqid_op: fh-stateid mismatch!\n");
- stp->st_vfs_set = 0;
goto out;
}
@@ -2188,17 +2200,6 @@ check_replay:
goto out;
}
-/*
- * eventually, this will perform an upcall to the 'state daemon' as well as
- * set the cl_first_state field.
- */
-void
-first_state(struct nfs4_client *clp)
-{
- if (!clp->cl_first_state)
- clp->cl_first_state = get_seconds();
-}
-
int
nfsd4_open_confirm(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open_confirm *oc)
{
@@ -2231,8 +2232,6 @@ nfsd4_open_confirm(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfs
stp->st_stateid.si_stateownerid,
stp->st_stateid.si_fileid,
stp->st_stateid.si_generation);
- status = nfs_ok;
- first_state(sop->so_client);
out:
if (oc->oc_stateowner)
nfs4_get_stateowner(oc->oc_stateowner);
@@ -2342,7 +2341,7 @@ nfsd4_close(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_clos
memcpy(&close->cl_stateid, &stp->st_stateid, sizeof(stateid_t));
/* release_state_owner() calls nfsd_close() if needed */
- release_state_owner(stp, &close->cl_stateowner, OPEN_STATE);
+ release_state_owner(stp, OPEN_STATE);
out:
if (close->cl_stateowner)
nfs4_get_stateowner(close->cl_stateowner);
@@ -2359,7 +2358,7 @@ nfsd4_delegreturn(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd
goto out;
nfs4_lock_state();
- status = nfs4_preprocess_stateid_op(current_fh, &dr->dr_stateid, DELEG_RET);
+ status = nfs4_preprocess_stateid_op(current_fh, &dr->dr_stateid, DELEG_RET, NULL);
nfs4_unlock_state();
out:
return status;
@@ -2376,8 +2375,15 @@ out:
#define lockownerid_hashval(id) \
((id) & LOCK_HASH_MASK)
-#define lock_ownerstr_hashval(x, clientid, ownername) \
- ((file_hashval(x) + (clientid) + opaque_hashval((ownername.data), (ownername.len))) & LOCK_HASH_MASK)
+
+static inline unsigned int
+lock_ownerstr_hashval(struct inode *inode, u32 cl_id,
+ struct xdr_netobj *ownername)
+{
+ return (file_hashval(inode) + cl_id
+ + opaque_hashval(ownername->data, ownername->len))
+ & LOCK_HASH_MASK;
+}
static struct list_head lock_ownerid_hashtbl[LOCK_HASH_SIZE];
static struct list_head lock_ownerstr_hashtbl[LOCK_HASH_SIZE];
@@ -2418,17 +2424,14 @@ find_delegation_stateid(struct inode *ino, stateid_t *stid)
struct nfs4_delegation *dp = NULL;
struct nfs4_file *fp = NULL;
u32 st_id;
- unsigned int fi_hashval;
dprintk("NFSD:find_delegation_stateid stateid=(%08x/%08x/%08x/%08x)\n",
stid->si_boot, stid->si_stateownerid,
stid->si_fileid, stid->si_generation);
- if(!ino || !stid)
- return NULL;
st_id = stid->si_stateownerid;
- fi_hashval = file_hashval(ino);
- if (find_file(fi_hashval, ino, &fp)) {
+ fp = find_file(ino);
+ if (fp) {
list_for_each_entry(dp, &fp->fi_del_perfile, dl_del_perfile) {
if(dp->dl_stateid.si_stateownerid == st_id) {
dprintk("NFSD: find_delegation dp %p\n",dp);
@@ -2512,18 +2515,18 @@ find_lockstateowner(struct xdr_netobj *owner, clientid_t *clid)
return NULL;
}
-static int
-find_lockstateowner_str(unsigned int hashval, struct xdr_netobj *owner, clientid_t *clid, struct nfs4_stateowner **op) {
- struct nfs4_stateowner *local = NULL;
+static struct nfs4_stateowner *
+find_lockstateowner_str(struct inode *inode, clientid_t *clid,
+ struct xdr_netobj *owner)
+{
+ unsigned int hashval = lock_ownerstr_hashval(inode, clid->cl_id, owner);
+ struct nfs4_stateowner *op;
- list_for_each_entry(local, &lock_ownerstr_hashtbl[hashval], so_strhash) {
- if (!cmp_owner_str(local, owner, clid))
- continue;
- *op = local;
- return(1);
+ list_for_each_entry(op, &lock_ownerstr_hashtbl[hashval], so_strhash) {
+ if (cmp_owner_str(op, owner, clid))
+ return op;
}
- *op = NULL;
- return 0;
+ return NULL;
}
/*
@@ -2553,9 +2556,7 @@ alloc_init_lock_stateowner(unsigned int strhashval, struct nfs4_client *clp, str
sop->so_time = 0;
list_add(&sop->so_idhash, &lock_ownerid_hashtbl[idhashval]);
list_add(&sop->so_strhash, &lock_ownerstr_hashtbl[strhashval]);
- list_add(&sop->so_perclient, &clp->cl_perclient);
list_add(&sop->so_perlockowner, &open_stp->st_perlockowner);
- add_perclient++;
sop->so_is_open_owner = 0;
sop->so_id = current_ownerid++;
sop->so_client = clp;
@@ -2565,7 +2566,6 @@ alloc_init_lock_stateowner(unsigned int strhashval, struct nfs4_client *clp, str
rp->rp_status = NFSERR_SERVERFAULT;
rp->rp_buflen = 0;
rp->rp_buf = rp->rp_ibuf;
- alloc_lsowner++;
return sop;
}
@@ -2593,7 +2593,6 @@ alloc_init_lock_stateid(struct nfs4_stateowner *sop, struct nfs4_file *fp, struc
stp->st_stateid.si_fileid = fp->fi_id;
stp->st_stateid.si_generation = 0;
stp->st_vfs_file = open_stp->st_vfs_file; /* FIXME refcount?? */
- stp->st_vfs_set = open_stp->st_vfs_set;
stp->st_access_bmap = open_stp->st_access_bmap;
stp->st_deny_bmap = open_stp->st_deny_bmap;
@@ -2672,7 +2671,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
fp = open_stp->st_file;
strhashval = lock_ownerstr_hashval(fp->fi_inode,
open_sop->so_client->cl_clientid.cl_id,
- lock->v.new.owner);
+ &lock->v.new.owner);
/*
* If we already have this lock owner, the client is in
* error (or our bookeeping is wrong!)
@@ -2785,7 +2784,7 @@ out_destroy_new_stateid:
if (!seqid_mutating_err(status))
open_sop->so_seqid--;
- release_state_owner(lock_stp, &lock->lk_stateowner, LOCK_STATE);
+ release_state_owner(lock_stp, LOCK_STATE);
}
out:
if (lock->lk_stateowner)
@@ -2804,7 +2803,6 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
struct file file;
struct file_lock file_lock;
struct file_lock *conflicting_lock;
- unsigned int strhashval;
int status;
if (nfs4_in_grace())
@@ -2846,12 +2844,8 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
goto out;
}
- strhashval = lock_ownerstr_hashval(inode,
- lockt->lt_clientid.cl_id, lockt->lt_owner);
-
- find_lockstateowner_str(strhashval, &lockt->lt_owner,
- &lockt->lt_clientid,
- &lockt->lt_stateowner);
+ lockt->lt_stateowner = find_lockstateowner_str(inode,
+ &lockt->lt_clientid, &lockt->lt_owner);
if (lockt->lt_stateowner)
file_lock.fl_owner = (fl_owner_t)lockt->lt_stateowner;
file_lock.fl_pid = current->tgid;
@@ -3005,10 +2999,8 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp, struct nfsd4_release_lockowner *
status = nfserr_locks_held;
list_for_each_entry(stp, &local->so_perfilestate,
st_perfilestate) {
- if (stp->st_vfs_set) {
- if (check_for_locks(stp->st_vfs_file, local))
- goto out;
- }
+ if (check_for_locks(stp->st_vfs_file, local))
+ goto out;
}
/* no locks held by (lock) stateowner */
status = nfs_ok;
@@ -3039,21 +3031,21 @@ alloc_reclaim(int namelen)
* failure => all reset bets are off, nfserr_no_grace...
*/
static int
-nfs4_client_to_reclaim(struct nfs4_client *clp)
+nfs4_client_to_reclaim(char *name, int namlen)
{
unsigned int strhashval;
struct nfs4_client_reclaim *crp = NULL;
- crp = alloc_reclaim(clp->cl_name.len);
+ dprintk("NFSD nfs4_client_to_reclaim NAME: %.*s\n", namlen, name);
+ crp = alloc_reclaim(namlen);
if (!crp)
return 0;
- strhashval = clientstr_hashval(clp->cl_name.data, clp->cl_name.len);
+ strhashval = clientstr_hashval(name, namlen);
INIT_LIST_HEAD(&crp->cr_strhash);
list_add(&crp->cr_strhash, &reclaim_str_hashtbl[strhashval]);
- memcpy(crp->cr_name.data, clp->cl_name.data, clp->cl_name.len);
- crp->cr_name.len = clp->cl_name.len;
- crp->cr_first_state = clp->cl_first_state;
- crp->cr_expired = 0;
+ memcpy(crp->cr_name.data, name, namlen);
+ crp->cr_name.len = namlen;
+ reclaim_str_hashtbl_size++;
return 1;
}
@@ -3082,27 +3074,23 @@ nfs4_release_reclaim(void)
struct nfs4_client_reclaim *
nfs4_find_reclaim_client(clientid_t *clid)
{
- unsigned int idhashval = clientid_hashval(clid->cl_id);
unsigned int strhashval;
- struct nfs4_client *clp, *client = NULL;
+ struct nfs4_client *clp;
struct nfs4_client_reclaim *crp = NULL;
/* find clientid in conf_id_hashtbl */
- list_for_each_entry(clp, &conf_id_hashtbl[idhashval], cl_idhash) {
- if (cmp_clid(&clp->cl_clientid, clid)) {
- client = clp;
- break;
- }
- }
- if (!client)
+ clp = find_confirmed_client(clid);
+ if (clp == NULL)
return NULL;
+ dprintk("NFSD: nfs4_find_reclaim_client for %.*s\n",
+ clp->cl_name.len, clp->cl_name.data);
+
/* find clp->cl_name in reclaim_str_hashtbl */
- strhashval = clientstr_hashval(client->cl_name.data,
- client->cl_name.len);
+ strhashval = clientstr_hashval(clp->cl_name.data, clp->cl_name.len);
list_for_each_entry(crp, &reclaim_str_hashtbl[strhashval], cr_strhash) {
- if (cmp_name(&crp->cr_name, &client->cl_name)) {
+ if (cmp_name(&crp->cr_name, &clp->cl_name)) {
return crp;
}
}
@@ -3119,8 +3107,6 @@ nfs4_check_open_reclaim(clientid_t *clid)
if ((crp = nfs4_find_reclaim_client(clid)) == NULL)
return nfserr_reclaim_bad;
- if (crp->cr_expired)
- return nfserr_no_grace;
return nfs_ok;
}
@@ -3129,14 +3115,12 @@ nfs4_check_open_reclaim(clientid_t *clid)
* Start and stop routines
*/
-void
-nfs4_state_init(void)
+static void
+__nfs4_state_init(void)
{
int i;
time_t grace_time;
- if (nfs4_init)
- return;
if (!nfs4_reclaim_init) {
for (i = 0; i < CLIENT_HASH_SIZE; i++)
INIT_LIST_HEAD(&reclaim_str_hashtbl[i]);
@@ -3180,7 +3164,21 @@ nfs4_state_init(void)
grace_end = boot_time + grace_time;
INIT_WORK(&laundromat_work,laundromat_main, NULL);
schedule_delayed_work(&laundromat_work, NFSD_LEASE_TIME*HZ);
+}
+
+int
+nfs4_state_init(void)
+{
+ int status;
+
+ if (nfs4_init)
+ return 0;
+ status = nfsd4_init_slabs();
+ if (status)
+ return status;
+ __nfs4_state_init();
nfs4_init = 1;
+ return 0;
}
int
@@ -3208,7 +3206,14 @@ __nfs4_state_shutdown(void)
int i;
struct nfs4_client *clp = NULL;
struct nfs4_delegation *dp = NULL;
- struct list_head *pos, *next;
+ struct nfs4_stateowner *sop = NULL;
+ struct list_head *pos, *next, reaplist;
+
+ list_for_each_safe(pos, next, &close_lru) {
+ sop = list_entry(pos, struct nfs4_stateowner, so_close_lru);
+ list_del(&sop->so_close_lru);
+ nfs4_put_stateowner(sop);
+ }
for (i = 0; i < CLIENT_HASH_SIZE; i++) {
while (!list_empty(&conf_id_hashtbl[i])) {
@@ -3220,13 +3225,18 @@ __nfs4_state_shutdown(void)
expire_client(clp);
}
}
+ INIT_LIST_HEAD(&reaplist);
spin_lock(&recall_lock);
list_for_each_safe(pos, next, &del_recall_lru) {
dp = list_entry (pos, struct nfs4_delegation, dl_recall_lru);
- atomic_set(&dp->dl_state, NFS4_RECALL_COMPLETE);
- release_delegation(dp);
+ list_move(&dp->dl_recall_lru, &reaplist);
}
spin_unlock(&recall_lock);
+ list_for_each_safe(pos, next, &reaplist) {
+ dp = list_entry (pos, struct nfs4_delegation, dl_recall_lru);
+ list_del_init(&dp->dl_recall_lru);
+ unhash_delegation(dp);
+ }
release_all_files();
cancel_delayed_work(&laundromat_work);
@@ -3238,8 +3248,6 @@ __nfs4_state_shutdown(void)
add_perclient, del_perclient);
dprintk("NFSD: alloc_file %d free_file %d\n",
alloc_file, free_file);
- dprintk("NFSD: alloc_sowner %d alloc_lsowner %d free_sowner %d\n",
- alloc_sowner, alloc_lsowner, free_sowner);
dprintk("NFSD: vfsopen %d vfsclose %d\n",
vfsopen, vfsclose);
dprintk("NFSD: alloc_delegation %d free_delegation %d\n",
@@ -3253,6 +3261,7 @@ nfs4_state_shutdown(void)
nfs4_lock_state();
nfs4_release_reclaim();
__nfs4_state_shutdown();
+ nfsd4_free_slabs();
nfs4_unlock_state();
}
@@ -3296,16 +3305,16 @@ nfs4_reset_lease(time_t leasetime)
/* populate reclaim_str_hashtbl with current confirmed nfs4_clientid */
for (i = 0; i < CLIENT_HASH_SIZE; i++) {
list_for_each_entry(clp, &conf_id_hashtbl[i], cl_idhash) {
- if (!nfs4_client_to_reclaim(clp)) {
+ if (!nfs4_client_to_reclaim(clp->cl_name.data,
+ clp->cl_name.len)) {
nfs4_release_reclaim();
goto init_state;
}
- reclaim_str_hashtbl_size++;
}
}
init_state:
__nfs4_state_shutdown();
- nfs4_state_init();
+ __nfs4_state_init();
nfs4_unlock_state();
}
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 7abe3d33ace50..36a058a112d57 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -60,121 +60,6 @@
#define NFSDDBG_FACILITY NFSDDBG_XDR
-static const char utf8_byte_len[256] = {
- 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
- 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
- 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
- 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
- 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, 4,4,4,4,4,4,4,4,5,5,5,5,6,6,0,0
-};
-
-static inline int
-is_legal_utf8_sequence(unsigned char *source, int length)
-{
- unsigned char *ptr;
- unsigned char c;
-
- if (length==1) return 1;
-
- /* Check for overlong sequence, and check second byte */
- c = *(source + 1);
- switch (*source) {
- case 0xE0: /* 3 bytes */
- if ( c < 0xA0 ) return 0;
- break;
- case 0xF0: /* 4 bytes */
- if ( c < 0x90 ) return 0;
- break;
- case 0xF8: /* 5 bytes */
- if ( c < 0xC8 ) return 0;
- break;
- case 0xFC: /* 6 bytes */
- if ( c < 0x84 ) return 0;
- break;
- default:
- if ( (c & 0xC0) != 0x80) return 0;
- }
-
- /* Check that trailing bytes look like 10xxxxxx */
- for (ptr = source++ + length - 1; ptr>source; ptr--)
- if ( ((*ptr) & 0xC0) != 0x80 ) return 0;
- return 1;
-}
-
-/* This does some screening on disallowed unicode characters. It is NOT
- * comprehensive.
- */
-static int
-is_allowed_utf8_char(unsigned char *source, int length)
-{
- /* We assume length and source point to a valid utf8 sequence */
- unsigned char c;
-
- /* Disallow F0000 and up (in utf8, F3B08080) */
- if (*source > 0xF3 ) return 0;
- c = *(source + 1);
- switch (*source) {
- case 0xF3:
- if (c >= 0xB0) return 0;
- break;
- /* Disallow D800-F8FF (in utf8, EDA080-EFA3BF */
- case 0xED:
- if (c >= 0xA0) return 0;
- break;
- case 0xEE:
- return 0;
- break;
- case 0xEF:
- if (c <= 0xA3) return 0;
- /* Disallow FFF9-FFFF (EFBFB9-EFBFBF) */
- if (c==0xBF)
- /* Don't need to check <=0xBF, since valid utf8 */
- if ( *(source+2) >= 0xB9) return 0;
- break;
- }
- return 1;
-}
-
-/* This routine should really check to see that the proper stringprep
- * mappings have been applied. Instead, we do a simple screen of some
- * of the more obvious illegal values by calling is_allowed_utf8_char.
- * This will allow many illegal strings through, but if a client behaves,
- * it will get full functionality. The other option (apart from full
- * stringprep checking) is to limit everything to an easily handled subset,
- * such as 7-bit ascii.
- *
- * Note - currently calling routines ignore return value except as boolean.
- */
-static int
-check_utf8(char *str, int len)
-{
- unsigned char *chunk, *sourceend;
- int chunklen;
-
- chunk = str;
- sourceend = str + len;
-
- while (chunk < sourceend) {
- chunklen = utf8_byte_len[*chunk];
- if (!chunklen)
- return nfserr_inval;
- if (chunk + chunklen > sourceend)
- return nfserr_inval;
- if (!is_legal_utf8_sequence(chunk, chunklen))
- return nfserr_inval;
- if (!is_allowed_utf8_char(chunk, chunklen))
- return nfserr_inval;
- if ( (chunklen==1) && (!*chunk) )
- return nfserr_inval; /* Disallow embedded nulls */
- chunk += chunklen;
- }
-
- return 0;
-}
-
static int
check_filename(char *str, int len, int err)
{
@@ -187,7 +72,7 @@ check_filename(char *str, int len, int err)
for (i = 0; i < len; i++)
if (str[i] == '/')
return err;
- return check_utf8(str, len);
+ return 0;
}
/*
@@ -403,8 +288,6 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, struct iattr *ia
READ_BUF(dummy32);
len += XDR_QUADLEN(dummy32) << 2;
READMEM(buf, dummy32);
- if (check_utf8(buf, dummy32))
- return nfserr_inval;
ace.whotype = nfs4_acl_get_whotype(buf, dummy32);
status = 0;
if (ace.whotype != NFS4_ACL_WHO_NAMED)
@@ -439,8 +322,6 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, struct iattr *ia
READ_BUF(dummy32);
len += (XDR_QUADLEN(dummy32) << 2);
READMEM(buf, dummy32);
- if (check_utf8(buf, dummy32))
- return nfserr_inval;
if ((status = nfsd_map_name_to_uid(argp->rqstp, buf, dummy32, &iattr->ia_uid)))
goto out_nfserr;
iattr->ia_valid |= ATTR_UID;
@@ -452,8 +333,6 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, struct iattr *ia
READ_BUF(dummy32);
len += (XDR_QUADLEN(dummy32) << 2);
READMEM(buf, dummy32);
- if (check_utf8(buf, dummy32))
- return nfserr_inval;
if ((status = nfsd_map_name_to_gid(argp->rqstp, buf, dummy32, &iattr->ia_gid)))
goto out_nfserr;
iattr->ia_valid |= ATTR_GID;
@@ -585,8 +464,6 @@ nfsd4_decode_create(struct nfsd4_compoundargs *argp, struct nfsd4_create *create
READ32(create->cr_linklen);
READ_BUF(create->cr_linklen);
SAVEMEM(create->cr_linkname, create->cr_linklen);
- if (check_utf8(create->cr_linkname, create->cr_linklen))
- return nfserr_inval;
break;
case NF4BLK:
case NF4CHR:
@@ -1454,7 +1331,10 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
if (bmval0 & FATTR4_WORD0_ACL) {
if (status == -EOPNOTSUPP)
bmval0 &= ~FATTR4_WORD0_ACL;
- else if (status != 0)
+ else if (status == -EINVAL) {
+ status = nfserr_attrnotsupp;
+ goto out;
+ } else if (status != 0)
goto out_nfserr;
}
}
@@ -2191,10 +2071,10 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_read
}
read->rd_vlen = v;
- nfserr = nfsd_read(read->rd_rqstp, read->rd_fhp,
- read->rd_offset,
- read->rd_iov, read->rd_vlen,
- &maxcount);
+ nfserr = nfsd_read(read->rd_rqstp, read->rd_fhp, read->rd_filp,
+ read->rd_offset, read->rd_iov, read->rd_vlen,
+ &maxcount);
+
if (nfserr == nfserr_symlink)
nfserr = nfserr_inval;
if (nfserr)
diff --git a/fs/nfsd/nfscache.c b/fs/nfsd/nfscache.c
index a3236dfedf98b..119e4d4495b89 100644
--- a/fs/nfsd/nfscache.c
+++ b/fs/nfsd/nfscache.c
@@ -15,6 +15,7 @@
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/spinlock.h>
+#include <linux/list.h>
#include <linux/sunrpc/svc.h>
#include <linux/nfsd/nfsd.h>
@@ -30,15 +31,8 @@
#define HASHSIZE 64
#define REQHASH(xid) ((((xid) >> 24) ^ (xid)) & (HASHSIZE-1))
-struct nfscache_head {
- struct svc_cacherep * next;
- struct svc_cacherep * prev;
-};
-
-static struct nfscache_head * hash_list;
-static struct svc_cacherep * lru_head;
-static struct svc_cacherep * lru_tail;
-static struct svc_cacherep * nfscache;
+static struct hlist_head * hash_list;
+static struct list_head lru_head;
static int cache_disabled = 1;
static int nfsd_cache_append(struct svc_rqst *rqstp, struct kvec *vec);
@@ -54,46 +48,32 @@ void
nfsd_cache_init(void)
{
struct svc_cacherep *rp;
- struct nfscache_head *rh;
- size_t i;
- unsigned long order;
-
-
- i = CACHESIZE * sizeof (struct svc_cacherep);
- for (order = 0; (PAGE_SIZE << order) < i; order++)
- ;
- nfscache = (struct svc_cacherep *)
- __get_free_pages(GFP_KERNEL, order);
- if (!nfscache) {
- printk (KERN_ERR "nfsd: cannot allocate %Zd bytes for reply cache\n", i);
- return;
+ int i;
+
+ INIT_LIST_HEAD(&lru_head);
+ i = CACHESIZE;
+ while(i) {
+ rp = kmalloc(sizeof(*rp), GFP_KERNEL);
+ if (!rp) break;
+ list_add(&rp->c_lru, &lru_head);
+ rp->c_state = RC_UNUSED;
+ rp->c_type = RC_NOCACHE;
+ INIT_HLIST_NODE(&rp->c_hash);
+ i--;
}
- memset(nfscache, 0, i);
- i = HASHSIZE * sizeof (struct nfscache_head);
- hash_list = kmalloc (i, GFP_KERNEL);
+ if (i)
+ printk (KERN_ERR "nfsd: cannot allocate all %d cache entries, only got %d\n",
+ CACHESIZE, CACHESIZE-i);
+
+ hash_list = kmalloc (HASHSIZE * sizeof(struct hlist_head), GFP_KERNEL);
if (!hash_list) {
- free_pages ((unsigned long)nfscache, order);
- nfscache = NULL;
- printk (KERN_ERR "nfsd: cannot allocate %Zd bytes for hash list\n", i);
+ nfsd_cache_shutdown();
+ printk (KERN_ERR "nfsd: cannot allocate %Zd bytes for hash list\n",
+ HASHSIZE * sizeof(struct hlist_head));
return;
}
-
- for (i = 0, rh = hash_list; i < HASHSIZE; i++, rh++)
- rh->next = rh->prev = (struct svc_cacherep *) rh;
-
- for (i = 0, rp = nfscache; i < CACHESIZE; i++, rp++) {
- rp->c_state = RC_UNUSED;
- rp->c_type = RC_NOCACHE;
- rp->c_hash_next =
- rp->c_hash_prev = rp;
- rp->c_lru_next = rp + 1;
- rp->c_lru_prev = rp - 1;
- }
- lru_head = nfscache;
- lru_tail = nfscache + CACHESIZE - 1;
- lru_head->c_lru_prev = NULL;
- lru_tail->c_lru_next = NULL;
+ memset(hash_list, 0, HASHSIZE * sizeof(struct hlist_head));
cache_disabled = 0;
}
@@ -102,48 +82,30 @@ void
nfsd_cache_shutdown(void)
{
struct svc_cacherep *rp;
- size_t i;
- unsigned long order;
- for (rp = lru_head; rp; rp = rp->c_lru_next) {
+ while (!list_empty(&lru_head)) {
+ rp = list_entry(lru_head.next, struct svc_cacherep, c_lru);
if (rp->c_state == RC_DONE && rp->c_type == RC_REPLBUFF)
kfree(rp->c_replvec.iov_base);
+ list_del(&rp->c_lru);
+ kfree(rp);
}
cache_disabled = 1;
- i = CACHESIZE * sizeof (struct svc_cacherep);
- for (order = 0; (PAGE_SIZE << order) < i; order++)
- ;
- free_pages ((unsigned long)nfscache, order);
- nfscache = NULL;
- kfree (hash_list);
+ if (hash_list)
+ kfree (hash_list);
hash_list = NULL;
}
/*
- * Move cache entry to front of LRU list
+ * Move cache entry to end of LRU list
*/
static void
-lru_put_front(struct svc_cacherep *rp)
+lru_put_end(struct svc_cacherep *rp)
{
- struct svc_cacherep *prev = rp->c_lru_prev,
- *next = rp->c_lru_next;
-
- if (prev)
- prev->c_lru_next = next;
- else
- lru_head = next;
- if (next)
- next->c_lru_prev = prev;
- else
- lru_tail = prev;
-
- rp->c_lru_next = lru_head;
- rp->c_lru_prev = NULL;
- if (lru_head)
- lru_head->c_lru_prev = rp;
- lru_head = rp;
+ list_del(&rp->c_lru);
+ list_add_tail(&rp->c_lru, &lru_head);
}
/*
@@ -152,17 +114,8 @@ lru_put_front(struct svc_cacherep *rp)
static void
hash_refile(struct svc_cacherep *rp)
{
- struct svc_cacherep *prev = rp->c_hash_prev,
- *next = rp->c_hash_next;
- struct nfscache_head *head = hash_list + REQHASH(rp->c_xid);
-
- prev->c_hash_next = next;
- next->c_hash_prev = prev;
-
- rp->c_hash_next = head->next;
- rp->c_hash_prev = (struct svc_cacherep *) head;
- head->next->c_hash_prev = rp;
- head->next = rp;
+ hlist_del_init(&rp->c_hash);
+ hlist_add_head(&rp->c_hash, hash_list + REQHASH(rp->c_xid));
}
/*
@@ -173,7 +126,9 @@ hash_refile(struct svc_cacherep *rp)
int
nfsd_cache_lookup(struct svc_rqst *rqstp, int type)
{
- struct svc_cacherep *rh, *rp;
+ struct hlist_node *hn;
+ struct hlist_head *rh;
+ struct svc_cacherep *rp;
u32 xid = rqstp->rq_xid,
proto = rqstp->rq_prot,
vers = rqstp->rq_vers,
@@ -190,8 +145,8 @@ nfsd_cache_lookup(struct svc_rqst *rqstp, int type)
spin_lock(&cache_lock);
rtn = RC_DOIT;
- rp = rh = (struct svc_cacherep *) &hash_list[REQHASH(xid)];
- while ((rp = rp->c_hash_next) != rh) {
+ rh = &hash_list[REQHASH(xid)];
+ hlist_for_each_entry(rp, hn, rh, c_hash) {
if (rp->c_state != RC_UNUSED &&
xid == rp->c_xid && proc == rp->c_proc &&
proto == rp->c_prot && vers == rp->c_vers &&
@@ -206,7 +161,7 @@ nfsd_cache_lookup(struct svc_rqst *rqstp, int type)
/* This loop shouldn't take more than a few iterations normally */
{
int safe = 0;
- for (rp = lru_tail; rp; rp = rp->c_lru_prev) {
+ list_for_each_entry(rp, &lru_head, c_lru) {
if (rp->c_state != RC_INPROG)
break;
if (safe++ > CACHESIZE) {
@@ -254,7 +209,7 @@ found_entry:
/* We found a matching entry which is either in progress or done. */
age = jiffies - rp->c_timestamp;
rp->c_timestamp = jiffies;
- lru_put_front(rp);
+ lru_put_end(rp);
rtn = RC_DROPIT;
/* Request being processed or excessive rexmits */
@@ -343,7 +298,7 @@ nfsd_cache_update(struct svc_rqst *rqstp, int cachetype, u32 *statp)
break;
}
spin_lock(&cache_lock);
- lru_put_front(rp);
+ lru_put_end(rp);
rp->c_secure = rqstp->rq_secure;
rp->c_type = cachetype;
rp->c_state = RC_DONE;
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
index 0cf106106674d..7a3e397b4ed38 100644
--- a/fs/nfsd/nfsfh.c
+++ b/fs/nfsd/nfsfh.c
@@ -41,7 +41,7 @@ extern struct export_operations export_op_default;
* if not, require that we can walk up to exp->ex_dentry
* doing some checks on the 'x' bits
*/
-int nfsd_acceptable(void *expv, struct dentry *dentry)
+static int nfsd_acceptable(void *expv, struct dentry *dentry)
{
struct svc_export *exp = expv;
int rv;
@@ -280,8 +280,8 @@ out:
* an inode. In this case a call to fh_update should be made
* before the fh goes out on the wire ...
*/
-inline int _fh_update(struct dentry *dentry, struct svc_export *exp,
- __u32 *datap, int *maxsize)
+static inline int _fh_update(struct dentry *dentry, struct svc_export *exp,
+ __u32 *datap, int *maxsize)
{
struct export_operations *nop = exp->ex_mnt->mnt_sb->s_export_op;
@@ -297,8 +297,9 @@ inline int _fh_update(struct dentry *dentry, struct svc_export *exp,
/*
* for composing old style file handles
*/
-inline void _fh_update_old(struct dentry *dentry, struct svc_export *exp,
- struct knfsd_fh *fh)
+static inline void _fh_update_old(struct dentry *dentry,
+ struct svc_export *exp,
+ struct knfsd_fh *fh)
{
fh->ofh_ino = ino_t_to_u32(dentry->d_inode->i_ino);
fh->ofh_generation = dentry->d_inode->i_generation;
diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
index f3bf5368551c8..757f9d2080340 100644
--- a/fs/nfsd/nfsproc.c
+++ b/fs/nfsd/nfsproc.c
@@ -137,7 +137,7 @@ nfsd_proc_read(struct svc_rqst *rqstp, struct nfsd_readargs *argp,
svc_reserve(rqstp, (19<<2) + argp->count + 4);
resp->count = argp->count;
- nfserr = nfsd_read(rqstp, fh_copy(&resp->fh, &argp->fh),
+ nfserr = nfsd_read(rqstp, fh_copy(&resp->fh, &argp->fh), NULL,
argp->offset,
argp->vec, argp->vlen,
&resp->count);
@@ -160,7 +160,7 @@ nfsd_proc_write(struct svc_rqst *rqstp, struct nfsd_writeargs *argp,
SVCFH_fmt(&argp->fh),
argp->len, argp->offset);
- nfserr = nfsd_write(rqstp, fh_copy(&resp->fh, &argp->fh),
+ nfserr = nfsd_write(rqstp, fh_copy(&resp->fh, &argp->fh), NULL,
argp->offset,
argp->vec, argp->vlen,
argp->len,
@@ -590,6 +590,7 @@ nfserrno (int errno)
{ nfserr_dropit, -EAGAIN },
{ nfserr_dropit, -ENOMEM },
{ nfserr_badname, -ESRCH },
+ { nfserr_io, -ETXTBSY },
{ -1, -EIO }
};
int i;
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index 291dd8cd32147..39551657e6565 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -60,7 +60,7 @@ struct nfsd_list {
struct list_head list;
struct task_struct *task;
};
-struct list_head nfsd_list = LIST_HEAD_INIT(nfsd_list);
+static struct list_head nfsd_list = LIST_HEAD_INIT(nfsd_list);
/*
* Maximum number of nfsd processes
@@ -92,7 +92,9 @@ nfsd_svc(unsigned short port, int nrservs)
/* Readahead param cache - will no-op if it already exists */
error = nfsd_racache_init(2*nrservs);
- nfs4_state_init();
+ if (error<0)
+ goto out;
+ error = nfs4_state_init();
if (error<0)
goto out;
if (!nfsd_serv) {
@@ -378,4 +380,6 @@ struct svc_program nfsd_program = {
.pg_name = "nfsd", /* program name */
.pg_class = "nfsd", /* authentication class */
.pg_stats = &nfsd_svcstats, /* version table */
+ .pg_authenticate = &svc_set_client, /* export authentication */
+
};
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index a5a58a1dba0ad..e3e9d217236e4 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -36,6 +36,7 @@
#include <linux/module.h>
#include <linux/namei.h>
#include <linux/vfs.h>
+#include <linux/delay.h>
#include <linux/sunrpc/svc.h>
#include <linux/nfsd/nfsd.h>
#ifdef CONFIG_NFSD_V3
@@ -392,7 +393,7 @@ set_nfsv4_acl_one(struct dentry *dentry, struct posix_acl *pacl, char *key)
}
out:
kfree(buf);
- return (error);
+ return error;
}
int
@@ -416,7 +417,10 @@ nfsd4_set_nfs4_acl(struct svc_rqst *rqstp, struct svc_fh *fhp,
flags = NFS4_ACL_DIR;
error = nfs4_acl_nfsv4_to_posix(acl, &pacl, &dpacl, flags);
- if (error < 0)
+ if (error == -EINVAL) {
+ error = nfserr_attrnotsupp;
+ goto out;
+ } else if (error < 0)
goto out_nfserr;
if (pacl) {
@@ -707,8 +711,8 @@ nfsd_close(struct file *filp)
* As this calls fsync (not fdatasync) there is no need for a write_inode
* after it.
*/
-inline void nfsd_dosync(struct file *filp, struct dentry *dp,
- struct file_operations *fop)
+static inline void 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);
@@ -720,7 +724,7 @@ inline void nfsd_dosync(struct file *filp, struct dentry *dp,
}
-void
+static void
nfsd_sync(struct file *filp)
{
struct inode *inode = filp->f_dentry->d_inode;
@@ -730,7 +734,7 @@ nfsd_sync(struct file *filp)
up(&inode->i_sem);
}
-void
+static void
nfsd_sync_dir(struct dentry *dp)
{
nfsd_dosync(NULL, dp, dp->d_inode->i_fop);
@@ -810,30 +814,21 @@ nfsd_read_actor(read_descriptor_t *desc, struct page *page, unsigned long offset
return size;
}
-/*
- * Read data from a file. count must contain the requested read count
- * on entry. On return, *count contains the number of bytes actually read.
- * N.B. After this call fhp needs an fh_put
- */
-int
-nfsd_read(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
- struct kvec *vec, int vlen, unsigned long *count)
+static inline 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)
{
+ struct inode *inode;
struct raparms *ra;
mm_segment_t oldfs;
int err;
- struct file *file;
- struct inode *inode;
- err = nfsd_open(rqstp, fhp, S_IFREG, MAY_READ, &file);
- if (err)
- goto out;
err = nfserr_perm;
inode = file->f_dentry->d_inode;
#ifdef MSNFS
if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) &&
(!lock_may_read(inode, offset, *count)))
- goto out_close;
+ goto out;
#endif
/* Get readahead parameters */
@@ -869,41 +864,28 @@ nfsd_read(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
dnotify_parent(file->f_dentry, DN_ACCESS);
} else
err = nfserrno(err);
-out_close:
- nfsd_close(file);
out:
return err;
}
-/*
- * Write data to a file.
- * The stable flag requests synchronous writes.
- * N.B. After this call fhp needs an fh_put
- */
-int
-nfsd_write(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
- struct kvec *vec, int vlen,
+static inline 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)
{
struct svc_export *exp;
- struct file *file;
struct dentry *dentry;
struct inode *inode;
mm_segment_t oldfs;
int err = 0;
int stable = *stablep;
- err = nfsd_open(rqstp, fhp, S_IFREG, MAY_WRITE, &file);
- if (err)
- goto out;
- if (!cnt)
- goto out_close;
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_close;
+ goto out;
#endif
dentry = file->f_dentry;
@@ -968,8 +950,7 @@ nfsd_write(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
if (atomic_read(&inode->i_writecount) > 1
|| (last_ino == inode->i_ino && last_dev == inode->i_sb->s_dev)) {
dprintk("nfsd: write defer %d\n", current->pid);
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout((HZ+99)/100);
+ msleep(10);
dprintk("nfsd: write resume %d\n", current->pid);
}
@@ -990,12 +971,71 @@ nfsd_write(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
err = 0;
else
err = nfserrno(err);
-out_close:
- nfsd_close(file);
out:
return err;
}
+/*
+ * Read data from a file. count must contain the requested read count
+ * on entry. On return, *count contains the number of bytes actually read.
+ * N.B. After this call fhp needs an fh_put
+ */
+int
+nfsd_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
+ loff_t offset, struct kvec *vec, int vlen,
+ unsigned long *count)
+{
+ int err;
+
+ if (file) {
+ err = nfsd_permission(fhp->fh_export, fhp->fh_dentry,
+ MAY_READ|MAY_OWNER_OVERRIDE);
+ if (err)
+ goto out;
+ err = nfsd_vfs_read(rqstp, fhp, file, offset, vec, vlen, count);
+ } else {
+ err = nfsd_open(rqstp, fhp, S_IFREG, MAY_READ, &file);
+ if (err)
+ goto out;
+ err = nfsd_vfs_read(rqstp, fhp, file, offset, vec, vlen, count);
+ nfsd_close(file);
+ }
+out:
+ return err;
+}
+
+/*
+ * Write data to a file.
+ * The stable flag requests synchronous writes.
+ * N.B. After this call fhp needs an fh_put
+ */
+int
+nfsd_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)
+{
+ int err = 0;
+
+ if (file) {
+ err = nfsd_permission(fhp->fh_export, fhp->fh_dentry,
+ MAY_WRITE|MAY_OWNER_OVERRIDE);
+ if (err)
+ goto out;
+ err = nfsd_vfs_write(rqstp, fhp, file, offset, vec, vlen, cnt,
+ stablep);
+ } else {
+ err = nfsd_open(rqstp, fhp, S_IFREG, MAY_WRITE, &file);
+ if (err)
+ goto out;
+
+ if (cnt)
+ err = nfsd_vfs_write(rqstp, fhp, file, offset, vec, vlen,
+ cnt, stablep);
+ nfsd_close(file);
+ }
+out:
+ return err;
+}
#ifdef CONFIG_NFSD_V3
/*
diff --git a/fs/partitions/Kconfig b/fs/partitions/Kconfig
index aa52b76b9d563..deb25b661f048 100644
--- a/fs/partitions/Kconfig
+++ b/fs/partitions/Kconfig
@@ -203,7 +203,7 @@ config ULTRIX_PARTITION
config SUN_PARTITION
bool "Sun partition tables support" if PARTITION_ADVANCED
- default y if (SPARC32 || SPARC64)
+ default y if (SPARC32 || SPARC64 || SUN3 || SUN3X)
---help---
Like most systems, SunOS uses its own hard disk partition table
format, incompatible with all others. Saying Y here allows you to
diff --git a/fs/partitions/msdos.c b/fs/partitions/msdos.c
index 584a27b2bbd5a..17ee1b4ff087e 100644
--- a/fs/partitions/msdos.c
+++ b/fs/partitions/msdos.c
@@ -114,6 +114,9 @@ parse_extended(struct parsed_partitions *state, struct block_device *bdev,
*/
for (i=0; i<4; i++, p++) {
u32 offs, size, next;
+
+ if (SYS_IND(p) == 0)
+ continue;
if (!NR_SECTS(p) || is_extended_partition(p))
continue;
@@ -430,6 +433,8 @@ int msdos_partition(struct parsed_partitions *state, struct block_device *bdev)
for (slot = 1 ; slot <= 4 ; slot++, p++) {
u32 start = START_SECT(p)*sector_size;
u32 size = NR_SECTS(p)*sector_size;
+ if (SYS_IND(p) == 0)
+ continue;
if (!size)
continue;
if (is_extended_partition(p)) {
diff --git a/fs/pipe.c b/fs/pipe.c
index a4932d971fe17..25aa09f9d09d0 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -224,6 +224,7 @@ pipe_writev(struct file *filp, const struct iovec *_iov,
int do_wakeup;
struct iovec *iov = (struct iovec *)_iov;
size_t total_len;
+ ssize_t chars;
total_len = iov_length(iov, nr_segs);
/* Null write succeeds. */
@@ -235,25 +236,33 @@ pipe_writev(struct file *filp, const struct iovec *_iov,
down(PIPE_SEM(*inode));
info = inode->i_pipe;
+ if (!PIPE_READERS(*inode)) {
+ send_sig(SIGPIPE, current, 0);
+ ret = -EPIPE;
+ goto out;
+ }
+
/* We try to merge small writes */
- if (info->nrbufs && total_len < PAGE_SIZE) {
+ chars = total_len & (PAGE_SIZE-1); /* size of the last buffer */
+ if (info->nrbufs && chars != 0) {
int lastbuf = (info->curbuf + info->nrbufs - 1) & (PIPE_BUFFERS-1);
struct pipe_buffer *buf = info->bufs + lastbuf;
struct pipe_buf_operations *ops = buf->ops;
int offset = buf->offset + buf->len;
- if (ops->can_merge && offset + total_len <= PAGE_SIZE) {
+ if (ops->can_merge && offset + chars <= PAGE_SIZE) {
void *addr = ops->map(filp, info, buf);
- int error = pipe_iov_copy_from_user(offset + addr, iov, total_len);
+ int error = pipe_iov_copy_from_user(offset + addr, iov, chars);
ops->unmap(info, buf);
ret = error;
do_wakeup = 1;
if (error)
goto out;
- buf->len += total_len;
- ret = total_len;
- goto out;
+ buf->len += chars;
+ total_len -= chars;
+ ret = chars;
+ if (!total_len)
+ goto out;
}
-
}
for (;;) {
@@ -265,7 +274,6 @@ pipe_writev(struct file *filp, const struct iovec *_iov,
}
bufs = info->nrbufs;
if (bufs < PIPE_BUFFERS) {
- ssize_t chars;
int newbuf = (info->curbuf + bufs) & (PIPE_BUFFERS-1);
struct pipe_buffer *buf = info->bufs + newbuf;
struct page *page = info->tmp_page;
@@ -398,13 +406,18 @@ pipe_poll(struct file *filp, poll_table *wait)
/* Reading only -- no need for acquiring the semaphore. */
nrbufs = info->nrbufs;
- mask = (nrbufs > 0) ? POLLIN | POLLRDNORM : 0;
- mask |= (nrbufs < PIPE_BUFFERS) ? POLLOUT | POLLWRNORM : 0;
+ mask = 0;
+ if (filp->f_mode & FMODE_READ) {
+ mask = (nrbufs > 0) ? POLLIN | POLLRDNORM : 0;
+ if (!PIPE_WRITERS(*inode) && filp->f_version != PIPE_WCOUNTER(*inode))
+ mask |= POLLHUP;
+ }
- if (!PIPE_WRITERS(*inode) && filp->f_version != PIPE_WCOUNTER(*inode))
- mask |= POLLHUP;
- if (!PIPE_READERS(*inode))
- mask |= POLLERR;
+ if (filp->f_mode & FMODE_WRITE) {
+ mask |= (nrbufs < PIPE_BUFFERS) ? POLLOUT | POLLWRNORM : 0;
+ if (!PIPE_READERS(*inode))
+ mask |= POLLERR;
+ }
return mask;
}
diff --git a/fs/posix_acl.c b/fs/posix_acl.c
index 97fbb86195ef1..296480e96dd5f 100644
--- a/fs/posix_acl.c
+++ b/fs/posix_acl.c
@@ -35,7 +35,7 @@ EXPORT_SYMBOL(posix_acl_permission);
* Allocate a new ACL with the specified number of entries.
*/
struct posix_acl *
-posix_acl_alloc(int count, int flags)
+posix_acl_alloc(int count, unsigned int __nocast flags)
{
const size_t size = sizeof(struct posix_acl) +
count * sizeof(struct posix_acl_entry);
@@ -51,7 +51,7 @@ posix_acl_alloc(int count, int flags)
* Clone an ACL.
*/
struct posix_acl *
-posix_acl_clone(const struct posix_acl *acl, int flags)
+posix_acl_clone(const struct posix_acl *acl, unsigned int __nocast flags)
{
struct posix_acl *clone = NULL;
@@ -185,7 +185,7 @@ posix_acl_equiv_mode(const struct posix_acl *acl, mode_t *mode_p)
* Create an ACL representing the file mode permission bits of an inode.
*/
struct posix_acl *
-posix_acl_from_mode(mode_t mode, int flags)
+posix_acl_from_mode(mode_t mode, unsigned int __nocast flags)
{
struct posix_acl *acl = posix_acl_alloc(3, flags);
if (!acl)
diff --git a/fs/proc/array.c b/fs/proc/array.c
index eb5c084ede4ac..37668fe998ad0 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -73,6 +73,7 @@
#include <linux/highmem.h>
#include <linux/file.h>
#include <linux/times.h>
+#include <linux/cpuset.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
@@ -239,6 +240,8 @@ static inline char * task_sig(struct task_struct *p, char *buffer)
{
sigset_t pending, shpending, blocked, ignored, caught;
int num_threads = 0;
+ unsigned long qsize = 0;
+ unsigned long qlim = 0;
sigemptyset(&pending);
sigemptyset(&shpending);
@@ -255,11 +258,14 @@ static inline char * task_sig(struct task_struct *p, char *buffer)
blocked = p->blocked;
collect_sigign_sigcatch(p, &ignored, &caught);
num_threads = atomic_read(&p->signal->count);
+ qsize = atomic_read(&p->user->sigpending);
+ qlim = p->signal->rlim[RLIMIT_SIGPENDING].rlim_cur;
spin_unlock_irq(&p->sighand->siglock);
}
read_unlock(&tasklist_lock);
buffer += sprintf(buffer, "Threads:\t%d\n", num_threads);
+ buffer += sprintf(buffer, "SigQ:\t%lu/%lu\n", qsize, qlim);
/* render them all */
buffer = render_sigset_t("SigPnd:\t", &pending, buffer);
@@ -295,6 +301,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)
buffer = task_show_regs(task, buffer);
#endif
@@ -317,6 +324,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;
struct task_struct *t;
char tcomm[sizeof(task->comm)];
@@ -372,6 +380,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;
}
ppid = pid_alive(task) ? task->group_leader->real_parent->tgid : 0;
read_unlock(&tasklist_lock);
@@ -420,10 +429,10 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole)
priority,
nice,
num_threads,
- jiffies_to_clock_t(task->it_real_value),
+ jiffies_to_clock_t(it_real_value),
start_time,
vsize,
- mm ? mm->rss : 0, /* you might want to shift this left 3 */
+ mm ? get_mm_counter(mm, rss) : 0, /* you might want to shift this left 3 */
rsslim,
mm ? mm->start_code : 0,
mm ? mm->end_code : 0,
diff --git a/fs/proc/base.c b/fs/proc/base.c
index b30ee97c308f9..dad8ea4e00a03 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -32,6 +32,9 @@
#include <linux/mount.h>
#include <linux/security.h>
#include <linux/ptrace.h>
+#include <linux/seccomp.h>
+#include <linux/cpuset.h>
+#include <linux/audit.h>
#include "internal.h"
/*
@@ -49,6 +52,9 @@ enum pid_directory_inos {
PROC_TGID_TASK,
PROC_TGID_STATUS,
PROC_TGID_MEM,
+#ifdef CONFIG_SECCOMP
+ PROC_TGID_SECCOMP,
+#endif
PROC_TGID_CWD,
PROC_TGID_ROOT,
PROC_TGID_EXE,
@@ -64,6 +70,9 @@ enum pid_directory_inos {
#ifdef CONFIG_SCHEDSTATS
PROC_TGID_SCHEDSTAT,
#endif
+#ifdef CONFIG_CPUSETS
+ PROC_TGID_CPUSET,
+#endif
#ifdef CONFIG_SECURITY
PROC_TGID_ATTR,
PROC_TGID_ATTR_CURRENT,
@@ -80,6 +89,9 @@ enum pid_directory_inos {
PROC_TID_INO,
PROC_TID_STATUS,
PROC_TID_MEM,
+#ifdef CONFIG_SECCOMP
+ PROC_TID_SECCOMP,
+#endif
PROC_TID_CWD,
PROC_TID_ROOT,
PROC_TID_EXE,
@@ -95,6 +107,9 @@ enum pid_directory_inos {
#ifdef CONFIG_SCHEDSTATS
PROC_TID_SCHEDSTAT,
#endif
+#ifdef CONFIG_CPUSETS
+ PROC_TID_CPUSET,
+#endif
#ifdef CONFIG_SECURITY
PROC_TID_ATTR,
PROC_TID_ATTR_CURRENT,
@@ -130,6 +145,9 @@ static struct pid_entry tgid_base_stuff[] = {
E(PROC_TGID_STATM, "statm", S_IFREG|S_IRUGO),
E(PROC_TGID_MAPS, "maps", S_IFREG|S_IRUGO),
E(PROC_TGID_MEM, "mem", S_IFREG|S_IRUSR|S_IWUSR),
+#ifdef CONFIG_SECCOMP
+ E(PROC_TGID_SECCOMP, "seccomp", S_IFREG|S_IRUSR|S_IWUSR),
+#endif
E(PROC_TGID_CWD, "cwd", S_IFLNK|S_IRWXUGO),
E(PROC_TGID_ROOT, "root", S_IFLNK|S_IRWXUGO),
E(PROC_TGID_EXE, "exe", S_IFLNK|S_IRWXUGO),
@@ -143,6 +161,9 @@ static struct pid_entry tgid_base_stuff[] = {
#ifdef CONFIG_SCHEDSTATS
E(PROC_TGID_SCHEDSTAT, "schedstat", S_IFREG|S_IRUGO),
#endif
+#ifdef CONFIG_CPUSETS
+ E(PROC_TGID_CPUSET, "cpuset", S_IFREG|S_IRUGO),
+#endif
E(PROC_TGID_OOM_SCORE, "oom_score",S_IFREG|S_IRUGO),
E(PROC_TGID_OOM_ADJUST,"oom_adj", S_IFREG|S_IRUGO|S_IWUSR),
#ifdef CONFIG_AUDITSYSCALL
@@ -160,6 +181,9 @@ static struct pid_entry tid_base_stuff[] = {
E(PROC_TID_STATM, "statm", S_IFREG|S_IRUGO),
E(PROC_TID_MAPS, "maps", S_IFREG|S_IRUGO),
E(PROC_TID_MEM, "mem", S_IFREG|S_IRUSR|S_IWUSR),
+#ifdef CONFIG_SECCOMP
+ E(PROC_TID_SECCOMP, "seccomp", S_IFREG|S_IRUSR|S_IWUSR),
+#endif
E(PROC_TID_CWD, "cwd", S_IFLNK|S_IRWXUGO),
E(PROC_TID_ROOT, "root", S_IFLNK|S_IRWXUGO),
E(PROC_TID_EXE, "exe", S_IFLNK|S_IRWXUGO),
@@ -173,6 +197,9 @@ static struct pid_entry tid_base_stuff[] = {
#ifdef CONFIG_SCHEDSTATS
E(PROC_TID_SCHEDSTAT, "schedstat",S_IFREG|S_IRUGO),
#endif
+#ifdef CONFIG_CPUSETS
+ E(PROC_TID_CPUSET, "cpuset", S_IFREG|S_IRUGO),
+#endif
E(PROC_TID_OOM_SCORE, "oom_score",S_IFREG|S_IRUGO),
E(PROC_TID_OOM_ADJUST, "oom_adj", S_IFREG|S_IRUGO|S_IWUSR),
#ifdef CONFIG_AUDITSYSCALL
@@ -689,7 +716,7 @@ static struct file_operations proc_mem_operations = {
.open = mem_open,
};
-static ssize_t oom_adjust_read(struct file *file, char *buf,
+static ssize_t oom_adjust_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
struct task_struct *task = proc_task(file->f_dentry->d_inode);
@@ -709,7 +736,7 @@ static ssize_t oom_adjust_read(struct file *file, char *buf,
return count;
}
-static ssize_t oom_adjust_write(struct file *file, const char *buf,
+static ssize_t oom_adjust_write(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
struct task_struct *task = proc_task(file->f_dentry->d_inode);
@@ -735,8 +762,8 @@ static ssize_t oom_adjust_write(struct file *file, const char *buf,
}
static struct file_operations proc_oom_adjust_operations = {
- read: oom_adjust_read,
- write: oom_adjust_write,
+ .read = oom_adjust_read,
+ .write = oom_adjust_write,
};
static struct inode_operations proc_mem_inode_operations = {
@@ -808,6 +835,61 @@ static struct file_operations proc_loginuid_operations = {
};
#endif
+#ifdef CONFIG_SECCOMP
+static ssize_t seccomp_read(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct task_struct *tsk = proc_task(file->f_dentry->d_inode);
+ char __buf[20];
+ loff_t __ppos = *ppos;
+ size_t len;
+
+ /* no need to print the trailing zero, so use only len */
+ len = sprintf(__buf, "%u\n", tsk->seccomp.mode);
+ if (__ppos >= len)
+ return 0;
+ if (count > len - __ppos)
+ count = len - __ppos;
+ if (copy_to_user(buf, __buf + __ppos, count))
+ return -EFAULT;
+ *ppos = __ppos + count;
+ return count;
+}
+
+static ssize_t seccomp_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct task_struct *tsk = proc_task(file->f_dentry->d_inode);
+ char __buf[20], *end;
+ unsigned int seccomp_mode;
+
+ /* can set it only once to be even more secure */
+ if (unlikely(tsk->seccomp.mode))
+ return -EPERM;
+
+ memset(__buf, 0, sizeof(__buf));
+ count = min(count, sizeof(__buf) - 1);
+ if (copy_from_user(__buf, buf, count))
+ return -EFAULT;
+ seccomp_mode = simple_strtoul(__buf, &end, 0);
+ if (*end == '\n')
+ end++;
+ if (seccomp_mode && seccomp_mode <= NR_SECCOMP_MODES) {
+ tsk->seccomp.mode = seccomp_mode;
+ set_tsk_thread_flag(tsk, TIF_SECCOMP);
+ } else
+ return -EINVAL;
+ if (unlikely(!(end - __buf)))
+ return -EIO;
+ return end - __buf;
+}
+
+static struct file_operations proc_seccomp_operations = {
+ .read = seccomp_read,
+ .write = seccomp_write,
+};
+#endif /* CONFIG_SECCOMP */
+
static int proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd)
{
struct inode *inode = dentry->d_inode;
@@ -1443,6 +1525,12 @@ static struct dentry *proc_pident_lookup(struct inode *dir,
inode->i_op = &proc_mem_inode_operations;
inode->i_fop = &proc_mem_operations;
break;
+#ifdef CONFIG_SECCOMP
+ case PROC_TID_SECCOMP:
+ case PROC_TGID_SECCOMP:
+ inode->i_fop = &proc_seccomp_operations;
+ break;
+#endif /* CONFIG_SECCOMP */
case PROC_TID_MOUNTS:
case PROC_TGID_MOUNTS:
inode->i_fop = &proc_mounts_operations;
@@ -1483,6 +1571,12 @@ static struct dentry *proc_pident_lookup(struct inode *dir,
ei->op.proc_read = proc_pid_schedstat;
break;
#endif
+#ifdef CONFIG_CPUSETS
+ case PROC_TID_CPUSET:
+ case PROC_TGID_CPUSET:
+ inode->i_fop = &proc_cpuset_operations;
+ break;
+#endif
case PROC_TID_OOM_SCORE:
case PROC_TGID_OOM_SCORE:
inode->i_fop = &proc_info_file_operations;
@@ -1630,11 +1724,15 @@ struct dentry *proc_pid_unhash(struct task_struct *p)
if (proc_dentry != NULL) {
spin_lock(&dcache_lock);
+ spin_lock(&proc_dentry->d_lock);
if (!d_unhashed(proc_dentry)) {
dget_locked(proc_dentry);
__d_drop(proc_dentry);
- } else
+ spin_unlock(&proc_dentry->d_lock);
+ } else {
+ spin_unlock(&proc_dentry->d_lock);
proc_dentry = NULL;
+ }
spin_unlock(&dcache_lock);
}
return proc_dentry;
diff --git a/fs/proc/inode.c b/fs/proc/inode.c
index fa361c9b4e0ce..133c286851056 100644
--- a/fs/proc/inode.c
+++ b/fs/proc/inode.c
@@ -14,7 +14,6 @@
#include <linux/limits.h>
#include <linux/init.h>
#include <linux/module.h>
-#include <linux/parser.h>
#include <linux/smp_lock.h>
#include <asm/system.h>
@@ -143,51 +142,6 @@ static struct super_operations proc_sops = {
.remount_fs = proc_remount,
};
-enum {
- Opt_uid, Opt_gid, Opt_err
-};
-
-static match_table_t tokens = {
- {Opt_uid, "uid=%u"},
- {Opt_gid, "gid=%u"},
- {Opt_err, NULL}
-};
-
-static int parse_options(char *options,uid_t *uid,gid_t *gid)
-{
- char *p;
- int option;
-
- *uid = current->uid;
- *gid = current->gid;
- if (!options)
- return 1;
-
- while ((p = strsep(&options, ",")) != NULL) {
- substring_t args[MAX_OPT_ARGS];
- int token;
- if (!*p)
- continue;
-
- token = match_token(p, tokens, args);
- switch (token) {
- case Opt_uid:
- if (match_int(args, &option))
- return 0;
- *uid = option;
- break;
- case Opt_gid:
- if (match_int(args, &option))
- return 0;
- *gid = option;
- break;
- default:
- return 0;
- }
- }
- return 1;
-}
-
struct inode *proc_get_inode(struct super_block *sb, unsigned int ino,
struct proc_dir_entry *de)
{
@@ -249,10 +203,11 @@ int proc_fill_super(struct super_block *s, void *data, int silent)
* Fixup the root inode's nlink value
*/
root_inode->i_nlink += nr_processes();
+ root_inode->i_uid = 0;
+ root_inode->i_gid = 0;
s->s_root = d_alloc_root(root_inode);
if (!s->s_root)
goto out_no_root;
- parse_options(data, &root_inode->i_uid, &root_inode->i_gid);
return 0;
out_no_root:
diff --git a/fs/proc/kcore.c b/fs/proc/kcore.c
index 5ab9c2aca0f99..1c7da988fcc3a 100644
--- a/fs/proc/kcore.c
+++ b/fs/proc/kcore.c
@@ -84,7 +84,7 @@ static size_t get_kcore_size(int *nphdr, size_t *elf_buflen)
}
*elf_buflen = sizeof(struct elfhdr) +
(*nphdr + 2)*sizeof(struct elf_phdr) +
- 3 * sizeof(struct memelfnote) +
+ 3 * (sizeof(struct elf_note) + 4) +
sizeof(struct elf_prstatus) +
sizeof(struct elf_prpsinfo) +
sizeof(struct task_struct);
diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c
index 89d09007df5d1..1d75d6ab6897d 100644
--- a/fs/proc/proc_misc.c
+++ b/fs/proc/proc_misc.c
@@ -189,7 +189,7 @@ static int meminfo_read_proc(char *page, char **start, off_t off,
K(allowed),
K(committed),
K(ps.nr_page_table_pages),
- VMALLOC_TOTAL >> 10,
+ (unsigned long)VMALLOC_TOTAL >> 10,
vmi.used >> 10,
vmi.largest_chunk >> 10
);
@@ -524,7 +524,7 @@ static ssize_t write_sysrq_trigger(struct file *file, const char __user *buf,
if (get_user(c, buf))
return -EFAULT;
- __handle_sysrq(c, NULL, NULL);
+ __handle_sysrq(c, NULL, NULL, 0);
}
return count;
}
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index 01353ebb51b3b..28b4a0253a921 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -24,7 +24,7 @@ char *task_mem(struct mm_struct *mm, char *buffer)
"VmPTE:\t%8lu kB\n",
(mm->total_vm - mm->reserved_vm) << (PAGE_SHIFT-10),
mm->locked_vm << (PAGE_SHIFT-10),
- mm->rss << (PAGE_SHIFT-10),
+ get_mm_counter(mm, rss) << (PAGE_SHIFT-10),
data << (PAGE_SHIFT-10),
mm->stack_vm << (PAGE_SHIFT-10), text, lib,
(PTRS_PER_PTE*sizeof(pte_t)*mm->nr_ptes) >> 10);
@@ -39,11 +39,13 @@ unsigned long task_vsize(struct mm_struct *mm)
int task_statm(struct mm_struct *mm, int *shared, int *text,
int *data, int *resident)
{
- *shared = mm->rss - mm->anon_rss;
+ int rss = get_mm_counter(mm, rss);
+
+ *shared = rss - get_mm_counter(mm, anon_rss);
*text = (PAGE_ALIGN(mm->end_code) - (mm->start_code & PAGE_MASK))
>> PAGE_SHIFT;
*data = mm->total_vm - mm->shared_vm;
- *resident = mm->rss;
+ *resident = rss;
return mm->total_vm;
}
@@ -77,9 +79,19 @@ out:
return result;
}
+static void pad_len_spaces(struct seq_file *m, int len)
+{
+ len = 25 + sizeof(void*) * 6 - len;
+ if (len < 1)
+ len = 1;
+ seq_printf(m, "%*c", len, ' ');
+}
+
static int show_map(struct seq_file *m, void *v)
{
+ struct task_struct *task = m->private;
struct vm_area_struct *map = v;
+ struct mm_struct *mm = map->vm_mm;
struct file *file = map->vm_file;
int flags = map->vm_flags;
unsigned long ino = 0;
@@ -102,38 +114,93 @@ static int show_map(struct seq_file *m, void *v)
map->vm_pgoff << PAGE_SHIFT,
MAJOR(dev), MINOR(dev), ino, &len);
+ /*
+ * Print the dentry name for named mappings, and a
+ * special [heap] marker for the heap:
+ */
if (map->vm_file) {
- len = 25 + sizeof(void*) * 6 - len;
- if (len < 1)
- len = 1;
- seq_printf(m, "%*c", len, ' ');
+ pad_len_spaces(m, len);
seq_path(m, file->f_vfsmnt, file->f_dentry, "");
+ } else {
+ if (mm) {
+ if (map->vm_start <= mm->start_brk &&
+ map->vm_end >= mm->brk) {
+ pad_len_spaces(m, len);
+ seq_puts(m, "[heap]");
+ } else {
+ if (map->vm_start <= mm->start_stack &&
+ map->vm_end >= mm->start_stack) {
+
+ pad_len_spaces(m, len);
+ seq_puts(m, "[stack]");
+ }
+ }
+ } else {
+ pad_len_spaces(m, len);
+ seq_puts(m, "[vdso]");
+ }
}
seq_putc(m, '\n');
+ if (m->count < m->size) /* map is copied successfully */
+ m->version = (map != get_gate_vma(task))? map->vm_start: 0;
return 0;
}
static void *m_start(struct seq_file *m, loff_t *pos)
{
struct task_struct *task = m->private;
- struct mm_struct *mm = get_task_mm(task);
- struct vm_area_struct * map;
+ unsigned long last_addr = m->version;
+ struct mm_struct *mm;
+ struct vm_area_struct *map, *tail_map;
loff_t l = *pos;
+ /*
+ * We remember last_addr rather than next_addr to hit with
+ * mmap_cache most of the time. We have zero last_addr at
+ * the begining and also after lseek. We will have -1 last_addr
+ * after the end of the maps.
+ */
+
+ if (last_addr == -1UL)
+ return NULL;
+
+ mm = get_task_mm(task);
if (!mm)
return NULL;
+ tail_map = get_gate_vma(task);
down_read(&mm->mmap_sem);
- map = mm->mmap;
- while (l-- && map)
+
+ /* Start with last addr hint */
+ if (last_addr && (map = find_vma(mm, last_addr))) {
map = map->vm_next;
- if (!map) {
- up_read(&mm->mmap_sem);
- mmput(mm);
- if (l == -1)
- map = get_gate_vma(task);
+ goto out;
+ }
+
+ /*
+ * Check the map index is within the range and do
+ * sequential scan until m_index.
+ */
+ map = NULL;
+ if ((unsigned long)l < mm->map_count) {
+ map = mm->mmap;
+ while (l-- && map)
+ map = map->vm_next;
+ goto out;
}
- return map;
+
+ if (l != mm->map_count)
+ tail_map = NULL; /* After gate map */
+
+out:
+ if (map)
+ return map;
+
+ /* End of maps has reached */
+ m->version = (tail_map != NULL)? 0: -1UL;
+ up_read(&mm->mmap_sem);
+ mmput(mm);
+ return tail_map;
}
static void m_stop(struct seq_file *m, void *v)
@@ -151,13 +218,13 @@ static void *m_next(struct seq_file *m, void *v, loff_t *pos)
{
struct task_struct *task = m->private;
struct vm_area_struct *map = v;
+ struct vm_area_struct *tail_map = get_gate_vma(task);
+
(*pos)++;
- if (map->vm_next)
+ if (map && (map != tail_map) && map->vm_next)
return map->vm_next;
m_stop(m, v);
- if (map != get_gate_vma(task))
- return get_gate_vma(task);
- return NULL;
+ return (map != tail_map)? tail_map: NULL;
}
struct seq_operations proc_pid_maps_op = {
diff --git a/fs/qnx4/bitmap.c b/fs/qnx4/bitmap.c
index ea634dc47b92b..991253927658b 100644
--- a/fs/qnx4/bitmap.c
+++ b/fs/qnx4/bitmap.c
@@ -28,8 +28,8 @@ int qnx4_new_block(struct super_block *sb)
return 0;
}
-void count_bits(register const char *bmPart, register int size,
- int *const tf)
+static void count_bits(register const char *bmPart, register int size,
+ int *const tf)
{
char b;
int tot = *tf;
diff --git a/fs/qnx4/inode.c b/fs/qnx4/inode.c
index d46a09f9afbce..aa92d6b76a9af 100644
--- a/fs/qnx4/inode.c
+++ b/fs/qnx4/inode.c
@@ -162,8 +162,8 @@ static int qnx4_remount(struct super_block *sb, int *flags, char *data)
return 0;
}
-struct buffer_head *qnx4_getblk(struct inode *inode, int nr,
- int create)
+static struct buffer_head *qnx4_getblk(struct inode *inode, int nr,
+ int create)
{
struct buffer_head *result = NULL;
@@ -212,7 +212,7 @@ struct buffer_head *qnx4_bread(struct inode *inode, int block, int create)
return NULL;
}
-int qnx4_get_block( struct inode *inode, sector_t iblock, struct buffer_head *bh, int create )
+static int qnx4_get_block( struct inode *inode, sector_t iblock, struct buffer_head *bh, int create )
{
unsigned long phys;
@@ -447,7 +447,7 @@ static sector_t qnx4_bmap(struct address_space *mapping, sector_t block)
{
return generic_block_bmap(mapping,block,qnx4_get_block);
}
-struct address_space_operations qnx4_aops = {
+static struct address_space_operations qnx4_aops = {
.readpage = qnx4_readpage,
.writepage = qnx4_writepage,
.sync_page = block_sync_page,
diff --git a/fs/quota.c b/fs/quota.c
index d59ccf2358b59..3f0333a51a23d 100644
--- a/fs/quota.c
+++ b/fs/quota.c
@@ -16,8 +16,8 @@
#include <linux/syscalls.h>
#include <linux/buffer_head.h>
-/* Check validity of quotactl */
-static int check_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t id)
+/* Check validity of generic quotactl commands */
+static int generic_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t id)
{
if (type >= MAXQUOTAS)
return -EINVAL;
@@ -58,6 +58,48 @@ static int check_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t
if (sb && !sb->s_qcop->quota_sync)
return -ENOSYS;
break;
+ default:
+ return -EINVAL;
+ }
+
+ /* Is quota turned on for commands which need it? */
+ switch (cmd) {
+ case Q_GETFMT:
+ case Q_GETINFO:
+ case Q_QUOTAOFF:
+ case Q_SETINFO:
+ case Q_SETQUOTA:
+ case Q_GETQUOTA:
+ /* This is just informative test so we are satisfied without a lock */
+ if (!sb_has_quota_enabled(sb, type))
+ return -ESRCH;
+ }
+
+ /* Check privileges */
+ if (cmd == Q_GETQUOTA) {
+ if (((type == USRQUOTA && current->euid != id) ||
+ (type == GRPQUOTA && !in_egroup_p(id))) &&
+ !capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ }
+ else if (cmd != Q_GETFMT && cmd != Q_SYNC && cmd != Q_GETINFO)
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ return 0;
+}
+
+/* Check validity of XFS Quota Manager commands */
+static int xqm_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t id)
+{
+ if (type >= XQM_MAXQUOTAS)
+ return -EINVAL;
+ if (!sb)
+ return -ENODEV;
+ if (!sb->s_qcop)
+ return -ENOSYS;
+
+ switch (cmd) {
case Q_XQUOTAON:
case Q_XQUOTAOFF:
case Q_XQUOTARM:
@@ -80,30 +122,31 @@ static int check_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t
return -EINVAL;
}
- /* Is quota turned on for commands which need it? */
- switch (cmd) {
- case Q_GETFMT:
- case Q_GETINFO:
- case Q_QUOTAOFF:
- case Q_SETINFO:
- case Q_SETQUOTA:
- case Q_GETQUOTA:
- /* This is just informative test so we are satisfied without a lock */
- if (!sb_has_quota_enabled(sb, type))
- return -ESRCH;
- }
/* Check privileges */
- if (cmd == Q_GETQUOTA || cmd == Q_XGETQUOTA) {
- if (((type == USRQUOTA && current->euid != id) ||
- (type == GRPQUOTA && !in_egroup_p(id))) &&
- !capable(CAP_SYS_ADMIN))
+ if (cmd == Q_XGETQUOTA) {
+ if (((type == XQM_USRQUOTA && current->euid != id) ||
+ (type == XQM_GRPQUOTA && !in_egroup_p(id))) &&
+ !capable(CAP_SYS_ADMIN))
return -EPERM;
- }
- else if (cmd != Q_GETFMT && cmd != Q_SYNC && cmd != Q_GETINFO && cmd != Q_XGETQSTAT)
+ } else if (cmd != Q_XGETQSTAT) {
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
+ }
+
+ return 0;
+}
+
+static int check_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t id)
+{
+ int error;
- return security_quotactl (cmd, type, id, sb);
+ if (XQM_COMMAND(cmd))
+ error = xqm_quotactl_valid(sb, type, cmd, id);
+ else
+ error = generic_quotactl_valid(sb, type, cmd, id);
+ if (!error)
+ error = security_quotactl(cmd, type, id, sb);
+ return error;
}
static struct super_block *get_super_to_sync(int type)
diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c
index 97a7a8f30eb4e..0a88917605aee 100644
--- a/fs/ramfs/inode.c
+++ b/fs/ramfs/inode.c
@@ -45,7 +45,9 @@ static struct inode_operations ramfs_dir_inode_operations;
static struct backing_dev_info ramfs_backing_dev_info = {
.ra_pages = 0, /* No readahead */
- .memory_backed = 1, /* Does not contribute to dirty memory */
+ .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK |
+ BDI_CAP_MAP_DIRECT | BDI_CAP_MAP_COPY |
+ BDI_CAP_READ_MAP | BDI_CAP_WRITE_MAP | BDI_CAP_EXEC_MAP,
};
struct inode *ramfs_get_inode(struct super_block *sb, int mode, dev_t dev)
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index 6060b3d6e8351..7543031396f48 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -1843,6 +1843,8 @@ int reiserfs_new_inode (struct reiserfs_transaction_handle *th,
} else if (inode->i_sb->s_flags & MS_POSIXACL) {
reiserfs_warning (inode->i_sb, "ACLs aren't enabled in the fs, "
"but vfs thinks they are!");
+ } else if (is_reiserfs_priv_object (dir)) {
+ reiserfs_mark_inode_private (inode);
}
insert_inode_hash (inode);
diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c
index 856e5c4e9fa2f..c9ad3a7849f41 100644
--- a/fs/reiserfs/journal.c
+++ b/fs/reiserfs/journal.c
@@ -3011,6 +3011,8 @@ static int remove_from_transaction(struct super_block *p_s_sb, b_blocknr_t block
if (!already_cleaned) {
clear_buffer_journal_dirty (bh);
+ clear_buffer_dirty(bh);
+ clear_buffer_journal_test (bh);
put_bh(bh) ;
if (atomic_read(&(bh->b_count)) < 0) {
reiserfs_warning (p_s_sb, "journal-1752: remove from trans, b_count < 0");
@@ -3317,6 +3319,8 @@ int journal_mark_freed(struct reiserfs_transaction_handle *th, struct super_bloc
** in the current trans
*/
clear_buffer_journal_dirty (cn->bh);
+ clear_buffer_dirty(cn->bh);
+ clear_buffer_journal_test(cn->bh);
cleaned = 1 ;
put_bh(cn->bh) ;
if (atomic_read(&(cn->bh->b_count)) < 0) {
diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c
index eb292870b53f9..80e92d9b81cbf 100644
--- a/fs/reiserfs/namei.c
+++ b/fs/reiserfs/namei.c
@@ -353,7 +353,7 @@ static struct dentry * reiserfs_lookup (struct inode * dir, struct dentry * dent
/* Propogate the priv_object flag so we know we're in the priv tree */
if (is_reiserfs_priv_object (dir))
- REISERFS_I(inode)->i_flags |= i_priv_object;
+ reiserfs_mark_inode_private (inode);
}
reiserfs_write_unlock(dir->i_sb);
if ( retval == IO_ERROR ) {
@@ -1255,7 +1255,6 @@ static int reiserfs_rename (struct inode * old_dir, struct dentry *old_dentry,
return retval;
}
-
/* add new entry (or find the existing one) */
retval = reiserfs_add_entry (&th, new_dir, new_dentry->d_name.name, new_dentry->d_name.len,
old_inode, 0);
@@ -1283,8 +1282,13 @@ static int reiserfs_rename (struct inode * old_dir, struct dentry *old_dentry,
while (1) {
// look for old name using corresponding entry key (found by reiserfs_find_entry)
- if (search_by_entry_key (new_dir->i_sb, &old_de.de_entry_key, &old_entry_path, &old_de) != NAME_FOUND)
- BUG ();
+ if ((retval = search_by_entry_key (new_dir->i_sb, &old_de.de_entry_key,
+ &old_entry_path, &old_de)) != NAME_FOUND) {
+ pathrelse(&old_entry_path);
+ journal_end(&th, old_dir->i_sb, jbegin_count);
+ reiserfs_write_unlock(old_dir->i_sb);
+ return -EIO;
+ }
copy_item_head(&old_entry_ih, get_ih(&old_entry_path)) ;
@@ -1296,16 +1300,28 @@ static int reiserfs_rename (struct inode * old_dir, struct dentry *old_dentry,
&new_entry_path, &new_de);
// reiserfs_add_entry should not return IO_ERROR, because it is called with essentially same parameters from
// reiserfs_add_entry above, and we'll catch any i/o errors before we get here.
- if (retval != NAME_FOUND_INVISIBLE && retval != NAME_FOUND)
- BUG ();
+ if (retval != NAME_FOUND_INVISIBLE && retval != NAME_FOUND) {
+ pathrelse(&new_entry_path);
+ pathrelse(&old_entry_path);
+ journal_end(&th, old_dir->i_sb, jbegin_count);
+ reiserfs_write_unlock(old_dir->i_sb);
+ return -EIO;
+ }
copy_item_head(&new_entry_ih, get_ih(&new_entry_path)) ;
reiserfs_prepare_for_journal(old_inode->i_sb, new_de.de_bh, 1) ;
if (S_ISDIR(old_inode->i_mode)) {
- if (search_by_entry_key (new_dir->i_sb, &dot_dot_de.de_entry_key, &dot_dot_entry_path, &dot_dot_de) != NAME_FOUND)
- BUG ();
+ if ((retval = search_by_entry_key (new_dir->i_sb, &dot_dot_de.de_entry_key,
+ &dot_dot_entry_path, &dot_dot_de)) != NAME_FOUND) {
+ pathrelse(&dot_dot_entry_path);
+ pathrelse(&new_entry_path);
+ pathrelse(&old_entry_path);
+ journal_end(&th, old_dir->i_sb, jbegin_count);
+ reiserfs_write_unlock(old_dir->i_sb);
+ return -EIO;
+ }
copy_item_head(&dot_dot_ih, get_ih(&dot_dot_entry_path)) ;
// node containing ".." gets into transaction
reiserfs_prepare_for_journal(old_inode->i_sb, dot_dot_de.de_bh, 1) ;
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c
index 0b1247c4750b2..45582fe8b466b 100644
--- a/fs/reiserfs/xattr.c
+++ b/fs/reiserfs/xattr.c
@@ -181,8 +181,6 @@ open_xa_dir (const struct inode *inode, int flags)
dput (xadir);
return ERR_PTR (-ENODATA);
}
- /* Newly created object.. Need to mark it private */
- REISERFS_I(xadir->d_inode)->i_flags |= i_priv_object;
}
dput (xaroot);
@@ -230,8 +228,6 @@ get_xa_file_dentry (const struct inode *inode, const char *name, int flags)
dput (xafile);
goto out;
}
- /* Newly created object.. Need to mark it private */
- REISERFS_I(xafile->d_inode)->i_flags |= i_priv_object;
}
out:
@@ -1316,7 +1312,7 @@ reiserfs_xattr_init (struct super_block *s, int mount_flags)
if (!err && dentry) {
s->s_root->d_op = &xattr_lookup_poison_ops;
- REISERFS_I(dentry->d_inode)->i_flags |= i_priv_object;
+ reiserfs_mark_inode_private (dentry->d_inode);
REISERFS_SB(s)->priv_root = dentry;
} else if (!(mount_flags & MS_RDONLY)) { /* xattrs are unavailable */
/* If we're read-only it just means that the dir hasn't been
diff --git a/fs/reiserfs/xattr_acl.c b/fs/reiserfs/xattr_acl.c
index df4592a4f107c..e302071903a1d 100644
--- a/fs/reiserfs/xattr_acl.c
+++ b/fs/reiserfs/xattr_acl.c
@@ -339,7 +339,7 @@ reiserfs_inherit_default_acl (struct inode *dir, struct dentry *dentry, struct i
* would be useless since permissions are ignored, and a pain because
* it introduces locking cycles */
if (is_reiserfs_priv_object (dir)) {
- REISERFS_I(inode)->i_flags |= i_priv_object;
+ reiserfs_mark_inode_private (inode);
goto apply_umask;
}
diff --git a/fs/select.c b/fs/select.c
index 1de9b6ac7d352..25b1ccac2f2cd 100644
--- a/fs/select.c
+++ b/fs/select.c
@@ -302,10 +302,12 @@ sys_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp, s
if (tvp) {
time_t sec, usec;
- if ((ret = verify_area(VERIFY_READ, tvp, sizeof(*tvp)))
- || (ret = __get_user(sec, &tvp->tv_sec))
- || (ret = __get_user(usec, &tvp->tv_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)
diff --git a/fs/seq_file.c b/fs/seq_file.c
index 5a73e085fb4e5..650c43ba86c47 100644
--- a/fs/seq_file.c
+++ b/fs/seq_file.c
@@ -36,6 +36,13 @@ int seq_open(struct file *file, struct seq_operations *op)
p->op = op;
file->private_data = p;
+ /*
+ * Wrappers around seq_open(e.g. swaps_open) need to be
+ * aware of this. If they set f_version themselves, they
+ * should call seq_open first and then set f_version.
+ */
+ file->f_version = 0;
+
/* SEQ files support lseek, but not pread/pwrite */
file->f_mode &= ~(FMODE_PREAD | FMODE_PWRITE);
return 0;
@@ -58,6 +65,18 @@ ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
int err = 0;
down(&m->sem);
+ /*
+ * seq_file->op->..m_start/m_stop/m_next may do special actions
+ * or optimisations based on the file->f_version, so we want to
+ * pass the file->f_version to those methods.
+ *
+ * seq_file->version is just copy of f_version, and seq_file
+ * methods can treat it simply as file version.
+ * It is copied in first and copied out after all operations.
+ * It is convenient to have it as part of structure to avoid the
+ * need of passing another argument to all the seq_file methods.
+ */
+ m->version = file->f_version;
/* grab buffer if we didn't have one */
if (!m->buf) {
m->buf = kmalloc(m->size = PAGE_SIZE, GFP_KERNEL);
@@ -98,6 +117,7 @@ ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
if (!m->buf)
goto Enomem;
m->count = 0;
+ m->version = 0;
}
m->op->stop(m, p);
m->count = 0;
@@ -136,6 +156,7 @@ Done:
copied = err;
else
*ppos += copied;
+ file->f_version = m->version;
up(&m->sem);
return copied;
Enomem:
@@ -153,6 +174,7 @@ static int traverse(struct seq_file *m, loff_t offset)
int error = 0;
void *p;
+ m->version = 0;
m->index = 0;
m->count = m->from = 0;
if (!offset)
@@ -207,6 +229,7 @@ loff_t seq_lseek(struct file *file, loff_t offset, int origin)
long long retval = -EINVAL;
down(&m->sem);
+ m->version = file->f_version;
switch (origin) {
case 1:
offset += file->f_pos;
@@ -220,6 +243,7 @@ loff_t seq_lseek(struct file *file, loff_t offset, int origin)
if (retval) {
/* with extreme prejudice... */
file->f_pos = 0;
+ m->version = 0;
m->index = 0;
m->count = 0;
} else {
@@ -228,6 +252,7 @@ loff_t seq_lseek(struct file *file, loff_t offset, int origin)
}
}
up(&m->sem);
+ file->f_version = m->version;
return retval;
}
EXPORT_SYMBOL(seq_lseek);
diff --git a/fs/super.c b/fs/super.c
index 785bc1ffcc60b..3a1b8ca04ba60 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -143,7 +143,7 @@ int __put_super_and_need_restart(struct super_block *sb)
/**
* put_super - drop a temporary reference to superblock
- * @s: superblock in question
+ * @sb: superblock in question
*
* Drops a temporary reference, frees superblock if there's no
* references left.
@@ -732,7 +732,7 @@ void kill_block_super(struct super_block *sb)
bdev_uevent(bdev, KOBJ_UMOUNT);
generic_shutdown_super(sb);
- set_blocksize(bdev, sb->s_old_blocksize);
+ sync_blockdev(bdev);
close_bdev_excl(bdev);
}
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index 52d2e5a8d258f..352f966a11746 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -231,15 +231,16 @@ static ssize_t
sysfs_write_file(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
{
struct sysfs_buffer * buffer = file->private_data;
+ ssize_t len;
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;
+ len = fill_write_buffer(buffer, buf, count);
+ if (len > 0)
+ len = flush_write_buffer(file->f_dentry, buffer, len);
+ if (len > 0)
+ *ppos += len;
up(&buffer->sem);
- return count;
+ return len;
}
static int check_perm(struct inode * inode, struct file * file)
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
index 204d071baa5c0..aff7b2dfa8eed 100644
--- a/fs/sysfs/inode.c
+++ b/fs/sysfs/inode.c
@@ -23,7 +23,7 @@ static struct address_space_operations sysfs_aops = {
static struct backing_dev_info sysfs_backing_dev_info = {
.ra_pages = 0, /* No readahead */
- .memory_backed = 1, /* Does not contribute to dirty memory */
+ .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK,
};
struct inode * sysfs_new_inode(mode_t mode)
@@ -129,13 +129,17 @@ void sysfs_drop_dentry(struct sysfs_dirent * sd, struct dentry * parent)
if (dentry) {
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);
spin_unlock(&dcache_lock);
simple_unlink(parent->d_inode, dentry);
- } else
+ } else {
+ spin_unlock(&dentry->d_lock);
spin_unlock(&dcache_lock);
+ }
}
}
diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c
index 361c43b00c9f4..5c805bb1a4b75 100644
--- a/fs/sysfs/mount.c
+++ b/fs/sysfs/mount.c
@@ -93,6 +93,7 @@ int __init sysfs_init(void)
printk(KERN_ERR "sysfs: could not mount!\n");
err = PTR_ERR(sysfs_mount);
sysfs_mount = NULL;
+ unregister_filesystem(&sysfs_fs_type);
goto out_err;
}
} else
@@ -101,5 +102,6 @@ out:
return err;
out_err:
kmem_cache_destroy(sysfs_dir_cachep);
+ sysfs_dir_cachep = NULL;
goto out;
}
diff --git a/fs/ufs/super.c b/fs/ufs/super.c
index 7bcd4fc8d6519..f036d694ba5af 100644
--- a/fs/ufs/super.c
+++ b/fs/ufs/super.c
@@ -1196,6 +1196,11 @@ static void destroy_inodecache(void)
printk(KERN_INFO "ufs_inode_cache: not all structures were freed\n");
}
+#ifdef CONFIG_QUOTA
+static ssize_t ufs_quota_read(struct super_block *, int, char *,size_t, loff_t);
+static ssize_t ufs_quota_write(struct super_block *, int, const char *, size_t, loff_t);
+#endif
+
static struct super_operations ufs_super_ops = {
.alloc_inode = ufs_alloc_inode,
.destroy_inode = ufs_destroy_inode,
@@ -1206,8 +1211,102 @@ static struct super_operations ufs_super_ops = {
.write_super = ufs_write_super,
.statfs = ufs_statfs,
.remount_fs = ufs_remount,
+#ifdef CONFIG_QUOTA
+ .quota_read = ufs_quota_read,
+ .quota_write = ufs_quota_write,
+#endif
};
+#ifdef CONFIG_QUOTA
+
+/* Read data from quotafile - avoid pagecache and such because we cannot afford
+ * acquiring the locks... As quota files are never truncated and quota code
+ * itself serializes the operations (and noone else should touch the files)
+ * we don't have to be afraid of races */
+static ssize_t ufs_quota_read(struct super_block *sb, int type, char *data,
+ size_t len, loff_t off)
+{
+ struct inode *inode = sb_dqopt(sb)->files[type];
+ sector_t blk = off >> sb->s_blocksize_bits;
+ int err = 0;
+ int offset = off & (sb->s_blocksize - 1);
+ int tocopy;
+ size_t toread;
+ struct buffer_head *bh;
+ loff_t i_size = i_size_read(inode);
+
+ if (off > i_size)
+ return 0;
+ if (off+len > i_size)
+ len = i_size-off;
+ toread = len;
+ while (toread > 0) {
+ tocopy = sb->s_blocksize - offset < toread ?
+ sb->s_blocksize - offset : toread;
+
+ bh = ufs_bread(inode, blk, 0, &err);
+ if (err)
+ return err;
+ if (!bh) /* A hole? */
+ memset(data, 0, tocopy);
+ else {
+ memcpy(data, bh->b_data+offset, tocopy);
+ brelse(bh);
+ }
+ offset = 0;
+ toread -= tocopy;
+ data += tocopy;
+ blk++;
+ }
+ return len;
+}
+
+/* Write to quotafile */
+static ssize_t ufs_quota_write(struct super_block *sb, int type,
+ const char *data, size_t len, loff_t off)
+{
+ struct inode *inode = sb_dqopt(sb)->files[type];
+ sector_t blk = off >> sb->s_blocksize_bits;
+ int err = 0;
+ int offset = off & (sb->s_blocksize - 1);
+ int tocopy;
+ size_t towrite = len;
+ struct buffer_head *bh;
+
+ down(&inode->i_sem);
+ while (towrite > 0) {
+ tocopy = sb->s_blocksize - offset < towrite ?
+ sb->s_blocksize - offset : towrite;
+
+ bh = ufs_bread(inode, blk, 1, &err);
+ if (!bh)
+ goto out;
+ lock_buffer(bh);
+ memcpy(bh->b_data+offset, data, tocopy);
+ flush_dcache_page(bh->b_page);
+ set_buffer_uptodate(bh);
+ mark_buffer_dirty(bh);
+ unlock_buffer(bh);
+ brelse(bh);
+ offset = 0;
+ towrite -= tocopy;
+ data += tocopy;
+ blk++;
+ }
+out:
+ if (len == towrite)
+ 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);
+ return len - towrite;
+}
+
+#endif
+
static struct super_block *ufs_get_sb(struct file_system_type *fs_type,
int flags, const char *dev_name, void *data)
{
diff --git a/fs/vfat/namei.c b/fs/vfat/namei.c
index 19cb6934d589e..1c6f6b57ef1cf 100644
--- a/fs/vfat/namei.c
+++ b/fs/vfat/namei.c
@@ -208,15 +208,11 @@ static int vfat_valid_longname(const unsigned char *name, unsigned int len)
static int vfat_find_form(struct inode *dir, unsigned char *name)
{
- struct msdos_dir_entry *de;
- struct buffer_head *bh = NULL;
- loff_t i_pos;
- int res;
-
- res = fat_scan(dir, name, &bh, &de, &i_pos);
- brelse(bh);
- if (res < 0)
+ struct fat_slot_info sinfo;
+ int err = fat_scan(dir, name, &sinfo);
+ if (err)
return -ENOENT;
+ brelse(sinfo.bh);
return 0;
}
@@ -305,6 +301,7 @@ static int vfat_create_shortname(struct inode *dir, struct nls_table *nls,
wchar_t *uname, int ulen,
unsigned char *name_res, unsigned char *lcase)
{
+ struct fat_mount_options *opts = &MSDOS_SB(dir->i_sb)->options;
wchar_t *ip, *ext_start, *end, *name_start;
unsigned char base[9], ext[4], buf[8], *p;
unsigned char charbuf[NLS_MAX_CHARSET_SIZE];
@@ -312,7 +309,6 @@ static int vfat_create_shortname(struct inode *dir, struct nls_table *nls,
int sz = 0, extlen, baselen, i, numtail_baselen, numtail2_baselen;
int is_shortname;
struct shortname_info base_info, ext_info;
- unsigned short opt_shortname = MSDOS_SB(dir->i_sb)->options.shortname;
is_shortname = 1;
INIT_SHORTNAME_INFO(&base_info);
@@ -425,9 +421,9 @@ static int vfat_create_shortname(struct inode *dir, struct nls_table *nls,
if (vfat_find_form(dir, name_res) == 0)
return -EEXIST;
- if (opt_shortname & VFAT_SFN_CREATE_WIN95) {
+ if (opts->shortname & VFAT_SFN_CREATE_WIN95) {
return (base_info.upper && ext_info.upper);
- } else if (opt_shortname & VFAT_SFN_CREATE_WINNT) {
+ } else if (opts->shortname & VFAT_SFN_CREATE_WINNT) {
if ((base_info.upper || base_info.lower) &&
(ext_info.upper || ext_info.lower)) {
if (!base_info.upper && base_info.lower)
@@ -442,7 +438,7 @@ static int vfat_create_shortname(struct inode *dir, struct nls_table *nls,
}
}
- if (MSDOS_SB(dir->i_sb)->options.numtail == 0)
+ if (opts->numtail == 0)
if (vfat_find_form(dir, name_res) < 0)
return 0;
@@ -579,8 +575,9 @@ xlate_to_uni(const unsigned char *name, int len, unsigned char *outname,
}
static int vfat_build_slots(struct inode *dir, const unsigned char *name,
- int len, struct msdos_dir_slot *ds,
- int *slots, int is_dir)
+ int len, int is_dir, int cluster,
+ struct timespec *ts,
+ struct msdos_dir_slot *slots, int *nr_slots)
{
struct msdos_sb_info *sbi = MSDOS_SB(dir->i_sb);
struct fat_mount_options *opts = &sbi->options;
@@ -590,193 +587,144 @@ static int vfat_build_slots(struct inode *dir, const unsigned char *name,
unsigned char cksum, lcase;
unsigned char msdos_name[MSDOS_NAME];
wchar_t *uname;
- int res, slot, ulen, usize, i;
+ __le16 time, date;
+ int err, ulen, usize, i;
loff_t offset;
- *slots = 0;
- res = vfat_valid_longname(name, len);
- if (res)
- return res;
+ *nr_slots = 0;
+ err = vfat_valid_longname(name, len);
+ if (err)
+ return err;
page = __get_free_page(GFP_KERNEL);
if (!page)
return -ENOMEM;
uname = (wchar_t *)page;
- res = xlate_to_uni(name, len, (unsigned char *)uname, &ulen, &usize,
+ err = xlate_to_uni(name, len, (unsigned char *)uname, &ulen, &usize,
opts->unicode_xlate, opts->utf8, sbi->nls_io);
- if (res < 0)
+ if (err)
goto out_free;
- res = vfat_is_used_badchars(uname, ulen);
- if (res < 0)
+ err = vfat_is_used_badchars(uname, ulen);
+ if (err)
goto out_free;
- res = vfat_create_shortname(dir, sbi->nls_disk, uname, ulen,
+ err = vfat_create_shortname(dir, sbi->nls_disk, uname, ulen,
msdos_name, &lcase);
- if (res < 0)
+ if (err < 0)
goto out_free;
- else if (res == 1) {
- de = (struct msdos_dir_entry *)ds;
- res = 0;
+ else if (err == 1) {
+ de = (struct msdos_dir_entry *)slots;
+ err = 0;
goto shortname;
}
/* build the entry of long file name */
- *slots = usize / 13;
for (cksum = i = 0; i < 11; i++)
cksum = (((cksum&1)<<7)|((cksum&0xfe)>>1)) + msdos_name[i];
- for (ps = ds, slot = *slots; slot > 0; slot--, ps++) {
- ps->id = slot;
+ *nr_slots = usize / 13;
+ for (ps = slots, i = *nr_slots; i > 0; i--, ps++) {
+ ps->id = i;
ps->attr = ATTR_EXT;
ps->reserved = 0;
ps->alias_checksum = cksum;
ps->start = 0;
- offset = (slot - 1) * 13;
+ offset = (i - 1) * 13;
fatwchar_to16(ps->name0_4, uname + offset, 5);
fatwchar_to16(ps->name5_10, uname + offset + 5, 6);
fatwchar_to16(ps->name11_12, uname + offset + 11, 2);
}
- ds[0].id |= 0x40;
+ slots[0].id |= 0x40;
de = (struct msdos_dir_entry *)ps;
shortname:
/* build the entry of 8.3 alias name */
- (*slots)++;
+ (*nr_slots)++;
memcpy(de->name, msdos_name, MSDOS_NAME);
de->attr = is_dir ? ATTR_DIR : ATTR_ARCH;
de->lcase = lcase;
- de->adate = de->cdate = de->date = 0;
- de->ctime = de->time = 0;
- de->ctime_ms = 0;
- de->start = 0;
- de->starthi = 0;
+ fat_date_unix2dos(ts->tv_sec, &time, &date);
+ de->time = de->ctime = time;
+ de->date = de->cdate = de->adate = date;
+ de->ctime_cs = 0;
+ de->start = cpu_to_le16(cluster);
+ de->starthi = cpu_to_le16(cluster >> 16);
de->size = 0;
-
out_free:
free_page(page);
- return res;
+ return err;
}
-static int vfat_add_entry(struct inode *dir, struct qstr *qname,
- int is_dir, struct vfat_slot_info *sinfo_out,
- struct buffer_head **bh, struct msdos_dir_entry **de)
+static int vfat_add_entry(struct inode *dir, struct qstr *qname, int is_dir,
+ int cluster, struct timespec *ts,
+ struct fat_slot_info *sinfo)
{
- struct msdos_dir_slot *dir_slots;
- loff_t offset;
- int res, slots, slot;
+ struct msdos_dir_slot *slots;
unsigned int len;
- struct msdos_dir_entry *dummy_de;
- struct buffer_head *dummy_bh;
- loff_t dummy_i_pos;
+ int err, nr_slots;
len = vfat_striptail_len(qname);
if (len == 0)
return -ENOENT;
- dir_slots = kmalloc(sizeof(*dir_slots) * MSDOS_SLOTS, GFP_KERNEL);
- if (dir_slots == NULL)
+ slots = kmalloc(sizeof(*slots) * MSDOS_SLOTS, GFP_KERNEL);
+ if (slots == NULL)
return -ENOMEM;
- res = vfat_build_slots(dir, qname->name, len,
- dir_slots, &slots, is_dir);
- if (res < 0)
+ err = vfat_build_slots(dir, qname->name, len, is_dir, cluster, ts,
+ slots, &nr_slots);
+ if (err)
goto cleanup;
- /* build the empty directory entry of number of slots */
- offset =
- fat_add_entries(dir, slots, &dummy_bh, &dummy_de, &dummy_i_pos);
- if (offset < 0) {
- res = offset;
+ err = fat_add_entries(dir, slots, nr_slots, sinfo);
+ if (err)
goto cleanup;
- }
- brelse(dummy_bh);
-
- /* Now create the new entry */
- *bh = NULL;
- for (slot = 0; slot < slots; slot++) {
- if (fat_get_entry(dir, &offset, bh, de, &sinfo_out->i_pos) < 0) {
- res = -EIO;
- goto cleanup;
- }
- memcpy(*de, dir_slots + slot, sizeof(struct msdos_dir_slot));
- mark_buffer_dirty(*bh);
- }
- res = 0;
/* update timestamp */
- dir->i_ctime = dir->i_mtime = dir->i_atime = CURRENT_TIME_SEC;
- mark_inode_dirty(dir);
-
- fat_date_unix2dos(dir->i_mtime.tv_sec, &(*de)->time, &(*de)->date);
- dir->i_mtime.tv_nsec = 0;
- (*de)->ctime = (*de)->time;
- (*de)->adate = (*de)->cdate = (*de)->date;
-
- mark_buffer_dirty(*bh);
-
- /* slots can't be less than 1 */
- sinfo_out->long_slots = slots - 1;
- sinfo_out->longname_offset =
- offset - sizeof(struct msdos_dir_slot) * slots;
-
+ dir->i_ctime = dir->i_mtime = dir->i_atime = *ts;
+ if (IS_DIRSYNC(dir))
+ (void)fat_sync_inode(dir);
+ else
+ mark_inode_dirty(dir);
cleanup:
- kfree(dir_slots);
- return res;
+ kfree(slots);
+ return err;
}
static int vfat_find(struct inode *dir, struct qstr *qname,
- struct vfat_slot_info *sinfo, struct buffer_head **last_bh,
- struct msdos_dir_entry **last_de)
+ struct fat_slot_info *sinfo)
{
- struct super_block *sb = dir->i_sb;
- loff_t offset;
- unsigned int len;
- int res;
-
- len = vfat_striptail_len(qname);
+ unsigned int len = vfat_striptail_len(qname);
if (len == 0)
return -ENOENT;
-
- res = fat_search_long(dir, qname->name, len,
- (MSDOS_SB(sb)->options.name_check != 's'),
- &offset, &sinfo->longname_offset);
- if (res > 0) {
- sinfo->long_slots = res - 1;
- if (fat_get_entry(dir, &offset, last_bh, last_de, &sinfo->i_pos) >= 0)
- return 0;
- res = -EIO;
- }
- return res ? res : -ENOENT;
+ return fat_search_long(dir, qname->name, len, sinfo);
}
static struct dentry *vfat_lookup(struct inode *dir, struct dentry *dentry,
struct nameidata *nd)
{
- int res;
- struct vfat_slot_info sinfo;
- struct inode *inode;
+ struct super_block *sb = dir->i_sb;
+ struct fat_slot_info sinfo;
+ struct inode *inode = NULL;
struct dentry *alias;
- struct buffer_head *bh = NULL;
- struct msdos_dir_entry *de;
- int table;
+ int err, table;
lock_kernel();
- table = (MSDOS_SB(dir->i_sb)->options.name_check == 's') ? 2 : 0;
+ table = (MSDOS_SB(sb)->options.name_check == 's') ? 2 : 0;
dentry->d_op = &vfat_dentry_ops[table];
- inode = NULL;
- res = vfat_find(dir, &dentry->d_name, &sinfo, &bh, &de);
- if (res < 0) {
+ err = vfat_find(dir, &dentry->d_name, &sinfo);
+ if (err) {
table++;
goto error;
}
- inode = fat_build_inode(dir->i_sb, de, sinfo.i_pos, &res);
- brelse(bh);
- if (res) {
+ inode = fat_build_inode(sb, sinfo.de, sinfo.i_pos);
+ brelse(sinfo.bh);
+ if (IS_ERR(inode)) {
unlock_kernel();
- return ERR_PTR(res);
+ return ERR_PTR(PTR_ERR(inode));
}
alias = d_find_alias(inode);
if (alias) {
@@ -805,245 +753,274 @@ static int vfat_create(struct inode *dir, struct dentry *dentry, int mode,
struct nameidata *nd)
{
struct super_block *sb = dir->i_sb;
- struct inode *inode = NULL;
- struct buffer_head *bh = NULL;
- struct msdos_dir_entry *de;
- struct vfat_slot_info sinfo;
- int res;
+ struct inode *inode;
+ struct fat_slot_info sinfo;
+ struct timespec ts;
+ int err;
lock_kernel();
- res = vfat_add_entry(dir, &dentry->d_name, 0, &sinfo, &bh, &de);
- if (res < 0)
+
+ ts = CURRENT_TIME_SEC;
+ err = vfat_add_entry(dir, &dentry->d_name, 0, 0, &ts, &sinfo);
+ if (err)
goto out;
- inode = fat_build_inode(sb, de, sinfo.i_pos, &res);
- brelse(bh);
- if (!inode)
+ dir->i_version++;
+
+ inode = fat_build_inode(sb, sinfo.de, sinfo.i_pos);
+ brelse(sinfo.bh);
+ if (IS_ERR(inode)) {
+ err = PTR_ERR(inode);
goto out;
- res = 0;
- inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
- mark_inode_dirty(inode);
+ }
inode->i_version++;
- dir->i_version++;
+ inode->i_mtime = inode->i_atime = inode->i_ctime = ts;
+ /* timestamp is already written, so mark_inode_dirty() is unneeded. */
+
dentry->d_time = dentry->d_parent->d_inode->i_version;
d_instantiate(dentry, inode);
out:
unlock_kernel();
- return res;
-}
-
-static void vfat_remove_entry(struct inode *dir, struct vfat_slot_info *sinfo,
- struct buffer_head *bh,
- struct msdos_dir_entry *de)
-{
- loff_t offset, i_pos;
- int i;
-
- /* remove the shortname */
- dir->i_mtime = dir->i_atime = CURRENT_TIME_SEC;
- dir->i_version++;
- mark_inode_dirty(dir);
- de->name[0] = DELETED_FLAG;
- mark_buffer_dirty(bh);
- /* remove the longname */
- offset = sinfo->longname_offset;
- de = NULL;
- for (i = sinfo->long_slots; i > 0; --i) {
- if (fat_get_entry(dir, &offset, &bh, &de, &i_pos) < 0)
- continue;
- de->name[0] = DELETED_FLAG;
- de->attr = ATTR_NONE;
- mark_buffer_dirty(bh);
- }
- brelse(bh);
+ return err;
}
static int vfat_rmdir(struct inode *dir, struct dentry *dentry)
{
struct inode *inode = dentry->d_inode;
- struct vfat_slot_info sinfo;
- struct buffer_head *bh = NULL;
- struct msdos_dir_entry *de;
- int res;
+ struct fat_slot_info sinfo;
+ int err;
lock_kernel();
- res = fat_dir_empty(inode);
- if (res)
+
+ err = fat_dir_empty(inode);
+ if (err)
+ goto out;
+ err = vfat_find(dir, &dentry->d_name, &sinfo);
+ if (err)
goto out;
- res = vfat_find(dir, &dentry->d_name, &sinfo, &bh, &de);
- if (res < 0)
+ err = fat_remove_entries(dir, &sinfo); /* and releases bh */
+ if (err)
goto out;
+ dir->i_nlink--;
- res = 0;
inode->i_nlink = 0;
inode->i_mtime = inode->i_atime = CURRENT_TIME_SEC;
fat_detach(inode);
- mark_inode_dirty(inode);
- /* releases bh */
- vfat_remove_entry(dir, &sinfo, bh, de);
- dir->i_nlink--;
out:
unlock_kernel();
- return res;
+
+ return err;
}
static int vfat_unlink(struct inode *dir, struct dentry *dentry)
{
struct inode *inode = dentry->d_inode;
- struct vfat_slot_info sinfo;
- struct buffer_head *bh = NULL;
- struct msdos_dir_entry *de;
- int res;
+ struct fat_slot_info sinfo;
+ int err;
lock_kernel();
- res = vfat_find(dir, &dentry->d_name, &sinfo, &bh, &de);
- if (res < 0)
+
+ err = vfat_find(dir, &dentry->d_name, &sinfo);
+ if (err)
+ goto out;
+
+ err = fat_remove_entries(dir, &sinfo); /* and releases bh */
+ if (err)
goto out;
inode->i_nlink = 0;
inode->i_mtime = inode->i_atime = CURRENT_TIME_SEC;
fat_detach(inode);
- mark_inode_dirty(inode);
- /* releases bh */
- vfat_remove_entry(dir, &sinfo, bh, de);
out:
unlock_kernel();
- return res;
+ return err;
}
static int vfat_mkdir(struct inode *dir, struct dentry *dentry, int mode)
{
struct super_block *sb = dir->i_sb;
- struct inode *inode = NULL;
- struct vfat_slot_info sinfo;
- struct buffer_head *bh = NULL;
- struct msdos_dir_entry *de;
- int res;
+ struct inode *inode;
+ struct fat_slot_info sinfo;
+ struct timespec ts;
+ int err, cluster;
lock_kernel();
- res = vfat_add_entry(dir, &dentry->d_name, 1, &sinfo, &bh, &de);
- if (res < 0)
+
+ ts = CURRENT_TIME_SEC;
+ cluster = fat_alloc_new_dir(dir, &ts);
+ if (cluster < 0) {
+ err = cluster;
goto out;
- inode = fat_build_inode(sb, de, sinfo.i_pos, &res);
- if (!inode)
- goto out_brelse;
- inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
- mark_inode_dirty(inode);
- inode->i_version++;
+ }
+ err = vfat_add_entry(dir, &dentry->d_name, 1, cluster, &ts, &sinfo);
+ if (err)
+ goto out_free;
dir->i_version++;
dir->i_nlink++;
- inode->i_nlink = 2; /* no need to mark them dirty */
- res = fat_new_dir(inode, dir, 1);
- if (res < 0)
- goto mkdir_failed;
+
+ inode = fat_build_inode(sb, sinfo.de, sinfo.i_pos);
+ brelse(sinfo.bh);
+ if (IS_ERR(inode)) {
+ err = PTR_ERR(inode);
+ /* the directory was completed, just return a error */
+ goto out;
+ }
+ inode->i_version++;
+ inode->i_nlink = 2;
+ inode->i_mtime = inode->i_atime = inode->i_ctime = ts;
+ /* timestamp is already written, so mark_inode_dirty() is unneeded. */
+
dentry->d_time = dentry->d_parent->d_inode->i_version;
d_instantiate(dentry, inode);
-out_brelse:
- brelse(bh);
-out:
+
unlock_kernel();
- return res;
+ return 0;
-mkdir_failed:
- inode->i_nlink = 0;
- inode->i_mtime = inode->i_atime = CURRENT_TIME_SEC;
- fat_detach(inode);
- mark_inode_dirty(inode);
- /* releases bh */
- vfat_remove_entry(dir, &sinfo, bh, de);
- iput(inode);
- dir->i_nlink--;
- goto out;
+out_free:
+ fat_free_clusters(dir, cluster);
+out:
+ unlock_kernel();
+ return err;
}
static int vfat_rename(struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_dentry)
{
- struct buffer_head *old_bh, *new_bh, *dotdot_bh;
- struct msdos_dir_entry *old_de, *new_de, *dotdot_de;
+ struct buffer_head *dotdot_bh;
+ struct msdos_dir_entry *dotdot_de;
loff_t dotdot_i_pos;
struct inode *old_inode, *new_inode;
- int res, is_dir;
- struct vfat_slot_info old_sinfo, sinfo;
+ struct fat_slot_info old_sinfo, sinfo;
+ struct timespec ts;
+ int err, is_dir, update_dotdot, corrupt = 0;
- old_bh = new_bh = dotdot_bh = NULL;
+ old_sinfo.bh = sinfo.bh = dotdot_bh = NULL;
old_inode = old_dentry->d_inode;
new_inode = new_dentry->d_inode;
lock_kernel();
- res = vfat_find(old_dir, &old_dentry->d_name, &old_sinfo, &old_bh,
- &old_de);
- if (res < 0)
- goto rename_done;
+ err = vfat_find(old_dir, &old_dentry->d_name, &old_sinfo);
+ if (err)
+ goto out;
is_dir = S_ISDIR(old_inode->i_mode);
-
- if (is_dir) {
- if (fat_scan(old_inode, MSDOS_DOTDOT, &dotdot_bh,
- &dotdot_de, &dotdot_i_pos) < 0) {
- res = -EIO;
- goto rename_done;
+ update_dotdot = (is_dir && old_dir != new_dir);
+ if (update_dotdot) {
+ if (fat_get_dotdot_entry(old_inode, &dotdot_bh, &dotdot_de,
+ &dotdot_i_pos) < 0) {
+ err = -EIO;
+ goto out;
}
}
- if (new_dentry->d_inode) {
- res = vfat_find(new_dir, &new_dentry->d_name, &sinfo, &new_bh,
- &new_de);
- if (res < 0 || MSDOS_I(new_inode)->i_pos != sinfo.i_pos) {
+ ts = CURRENT_TIME_SEC;
+ if (new_inode) {
+ err = vfat_find(new_dir, &new_dentry->d_name, &sinfo);
+ if (err)
+ goto out;
+ if (MSDOS_I(new_inode)->i_pos != sinfo.i_pos) {
/* WTF??? Cry and fail. */
printk(KERN_WARNING "vfat_rename: fs corrupted\n");
- goto rename_done;
+ goto out;
}
if (is_dir) {
- res = fat_dir_empty(new_inode);
- if (res)
- goto rename_done;
+ err = fat_dir_empty(new_inode);
+ if (err)
+ goto out;
}
fat_detach(new_inode);
} else {
- res = vfat_add_entry(new_dir, &new_dentry->d_name, is_dir,
- &sinfo, &new_bh, &new_de);
- if (res < 0)
- goto rename_done;
+ err = vfat_add_entry(new_dir, &new_dentry->d_name, is_dir, 0,
+ &ts, &sinfo);
+ if (err)
+ goto out;
}
-
new_dir->i_version++;
- /* releases old_bh */
- vfat_remove_entry(old_dir, &old_sinfo, old_bh, old_de);
- old_bh = NULL;
fat_detach(old_inode);
fat_attach(old_inode, sinfo.i_pos);
- mark_inode_dirty(old_inode);
-
- old_dir->i_version++;
- old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME_SEC;
- mark_inode_dirty(old_dir);
- if (new_inode) {
- new_inode->i_nlink--;
- new_inode->i_ctime = CURRENT_TIME_SEC;
- }
-
- if (is_dir) {
+ if (IS_DIRSYNC(new_dir)) {
+ err = fat_sync_inode(old_inode);
+ if (err)
+ goto error_inode;
+ } else
+ mark_inode_dirty(old_inode);
+
+ if (update_dotdot) {
int start = MSDOS_I(new_dir)->i_logstart;
dotdot_de->start = cpu_to_le16(start);
- dotdot_de->starthi = cpu_to_le16(start>>16);
+ dotdot_de->starthi = cpu_to_le16(start >> 16);
mark_buffer_dirty(dotdot_bh);
- old_dir->i_nlink--;
- if (new_inode) {
- new_inode->i_nlink--;
- } else {
- new_dir->i_nlink++;
- mark_inode_dirty(new_dir);
+ if (IS_DIRSYNC(new_dir)) {
+ err = sync_dirty_buffer(dotdot_bh);
+ if (err)
+ goto error_dotdot;
}
+ old_dir->i_nlink--;
+ if (!new_inode)
+ new_dir->i_nlink++;
}
-rename_done:
+ err = fat_remove_entries(old_dir, &old_sinfo); /* and releases bh */
+ old_sinfo.bh = NULL;
+ if (err)
+ goto error_dotdot;
+ old_dir->i_version++;
+ old_dir->i_ctime = old_dir->i_mtime = ts;
+ if (IS_DIRSYNC(old_dir))
+ (void)fat_sync_inode(old_dir);
+ else
+ mark_inode_dirty(old_dir);
+
+ if (new_inode) {
+ if (is_dir)
+ new_inode->i_nlink -= 2;
+ else
+ new_inode->i_nlink--;
+ new_inode->i_ctime = ts;
+ }
+out:
+ brelse(sinfo.bh);
brelse(dotdot_bh);
- brelse(old_bh);
- brelse(new_bh);
+ brelse(old_sinfo.bh);
unlock_kernel();
- return res;
+
+ return err;
+
+error_dotdot:
+ /* data cluster is shared, serious corruption */
+ corrupt = 1;
+
+ if (update_dotdot) {
+ int start = MSDOS_I(old_dir)->i_logstart;
+ dotdot_de->start = cpu_to_le16(start);
+ dotdot_de->starthi = cpu_to_le16(start >> 16);
+ mark_buffer_dirty(dotdot_bh);
+ corrupt |= sync_dirty_buffer(dotdot_bh);
+ }
+error_inode:
+ fat_detach(old_inode);
+ fat_attach(old_inode, old_sinfo.i_pos);
+ if (new_inode) {
+ fat_attach(new_inode, sinfo.i_pos);
+ if (corrupt)
+ corrupt |= fat_sync_inode(new_inode);
+ } else {
+ /*
+ * If new entry was not sharing the data cluster, it
+ * shouldn't be serious corruption.
+ */
+ int err2 = fat_remove_entries(new_dir, &sinfo);
+ if (corrupt)
+ corrupt |= err2;
+ sinfo.bh = NULL;
+ }
+ if (corrupt < 0) {
+ fat_fs_panic(new_dir->i_sb,
+ "%s: Filesystem corrupted (i_pos %lld)",
+ __FUNCTION__, sinfo.i_pos);
+ }
+ goto out;
}
static struct inode_operations vfat_dir_inode_operations = {
diff --git a/fs/xfs/linux-2.6/kmem.h b/fs/xfs/linux-2.6/kmem.h
index 466b2d504395c..1397b669b059f 100644
--- a/fs/xfs/linux-2.6/kmem.h
+++ b/fs/xfs/linux-2.6/kmem.h
@@ -125,12 +125,6 @@ kmem_zone_destroy(kmem_zone_t *zone)
BUG();
}
-static __inline int
-kmem_zone_shrink(kmem_zone_t *zone)
-{
- return kmem_cache_shrink(zone);
-}
-
extern void *kmem_zone_zalloc(kmem_zone_t *, int);
extern void *kmem_zone_alloc(kmem_zone_t *, int);
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c
index 690cc7799a7c5..23e0eb67fc25e 100644
--- a/fs/xfs/linux-2.6/xfs_buf.c
+++ b/fs/xfs/linux-2.6/xfs_buf.c
@@ -966,7 +966,7 @@ pagebuf_cond_lock( /* lock buffer, if not locked */
return(locked ? 0 : -EBUSY);
}
-#ifdef DEBUG
+#if defined(DEBUG) || defined(XFS_BLI_TRACE)
/*
* pagebuf_lock_value
*
@@ -1283,7 +1283,7 @@ STATIC void
_pagebuf_ioapply(
xfs_buf_t *pb)
{
- int i, map_i, total_nr_pages, nr_pages;
+ int i, rw, map_i, total_nr_pages, nr_pages;
struct bio *bio;
int offset = pb->pb_offset;
int size = pb->pb_count_desired;
@@ -1294,6 +1294,13 @@ _pagebuf_ioapply(
total_nr_pages = pb->pb_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;
+ } else {
+ rw = (pb->pb_flags & PBF_READ) ? READ : WRITE;
+ }
+
/* Special code path for reading a sub page size pagebuf in --
* we populate up the whole page, and hence the other metadata
* in the same page. This optimization is only valid when the
@@ -1365,19 +1372,13 @@ next_chunk:
submit_io:
if (likely(bio->bi_size)) {
- submit_bio((pb->pb_flags & PBF_READ) ? READ : WRITE, bio);
+ submit_bio(rw, bio);
if (size)
goto next_chunk;
} else {
bio_put(bio);
pagebuf_ioerror(pb, EIO);
}
-
- if (pb->pb_flags & _PBF_RUN_QUEUES) {
- pb->pb_flags &= ~_PBF_RUN_QUEUES;
- if (atomic_read(&pb->pb_io_remaining) > 1)
- blk_run_address_space(pb->pb_target->pbr_mapping);
- }
}
/*
diff --git a/fs/xfs/linux-2.6/xfs_export.c b/fs/xfs/linux-2.6/xfs_export.c
index 772d216d81465..f372a1a5e1680 100644
--- a/fs/xfs/linux-2.6/xfs_export.c
+++ b/fs/xfs/linux-2.6/xfs_export.c
@@ -31,6 +31,25 @@
*/
#include "xfs.h"
+#include "xfs_types.h"
+#include "xfs_dmapi.h"
+#include "xfs_log.h"
+#include "xfs_trans.h"
+#include "xfs_sb.h"
+#include "xfs_dir.h"
+#include "xfs_mount.h"
+#include "xfs_export.h"
+
+/*
+ * XFS encode and decodes the fileid portion of NFS filehandles
+ * itself instead of letting the generic NFS code do it. This
+ * allows filesystems with 64 bit inode numbers to be exported.
+ *
+ * Note that a side effect is that xfs_vget() won't be passed a
+ * zero inode/generation pair under normal circumstances. As
+ * however a malicious client could send us such data, the check
+ * remains in that code.
+ */
STATIC struct dentry *
@@ -44,26 +63,87 @@ linvfs_decode_fh(
struct dentry *de),
void *context)
{
- __u32 parent[2];
- parent[0] = parent[1] = 0;
-
- if (fh_len < 2 || fileid_type > 2)
+ xfs_fid2_t ifid;
+ xfs_fid2_t pfid;
+ void *parent = NULL;
+ int is64 = 0;
+ __u32 *p = fh;
+
+#if XFS_BIG_INUMS
+ is64 = (fileid_type & XFS_FILEID_TYPE_64FLAG);
+ fileid_type &= ~XFS_FILEID_TYPE_64FLAG;
+#endif
+
+ /*
+ * Note that we only accept fileids which are long enough
+ * rather than allow the parent generation number to default
+ * to zero. XFS considers zero a valid generation number not
+ * an invalid/wildcard value. There's little point printk'ing
+ * a warning here as we don't have the client information
+ * which would make such a warning useful.
+ */
+ if (fileid_type > 2 ||
+ fh_len < xfs_fileid_length((fileid_type == 2), is64))
return NULL;
-
- if (fileid_type == 2 && fh_len > 2) {
- if (fh_len == 3) {
- printk(KERN_WARNING
- "XFS: detected filehandle without "
- "parent inode generation information.");
- return ERR_PTR(-ESTALE);
- }
-
- parent[0] = fh[2];
- parent[1] = fh[3];
+
+ p = xfs_fileid_decode_fid2(p, &ifid, is64);
+
+ if (fileid_type == 2) {
+ p = xfs_fileid_decode_fid2(p, &pfid, is64);
+ parent = &pfid;
}
+ fh = (__u32 *)&ifid;
return find_exported_dentry(sb, fh, parent, acceptable, context);
+}
+
+STATIC int
+linvfs_encode_fh(
+ struct dentry *dentry,
+ __u32 *fh,
+ int *max_len,
+ int connectable)
+{
+ struct inode *inode = dentry->d_inode;
+ int type = 1;
+ __u32 *p = fh;
+ int len;
+ int is64 = 0;
+#if XFS_BIG_INUMS
+ vfs_t *vfs = LINVFS_GET_VFS(inode->i_sb);
+ xfs_mount_t *mp = XFS_VFSTOM(vfs);
+
+ if (!(mp->m_flags & XFS_MOUNT_32BITINOOPT)) {
+ /* filesystem may contain 64bit inode numbers */
+ is64 = XFS_FILEID_TYPE_64FLAG;
+ }
+#endif
+
+ /* Directories don't need their parent encoded, they have ".." */
+ if (S_ISDIR(inode->i_mode))
+ connectable = 0;
+
+ /*
+ * Only encode if there is enough space given. In practice
+ * this means we can't export a filesystem with 64bit inodes
+ * over NFSv2 with the subtree_check export option; the other
+ * seven combinations work. The real answer is "don't use v2".
+ */
+ len = xfs_fileid_length(connectable, is64);
+ if (*max_len < len)
+ return 255;
+ *max_len = len;
+
+ p = xfs_fileid_encode_inode(p, inode, is64);
+ if (connectable) {
+ spin_lock(&dentry->d_lock);
+ p = xfs_fileid_encode_inode(p, dentry->d_parent->d_inode, is64);
+ spin_unlock(&dentry->d_lock);
+ type = 2;
+ }
+ BUG_ON((p - fh) != len);
+ return type | is64;
}
STATIC struct dentry *
@@ -74,16 +154,10 @@ linvfs_get_dentry(
vnode_t *vp;
struct inode *inode;
struct dentry *result;
- xfs_fid2_t xfid;
vfs_t *vfsp = LINVFS_GET_VFS(sb);
int error;
- xfid.fid_len = sizeof(xfs_fid2_t) - sizeof(xfid.fid_len);
- xfid.fid_pad = 0;
- xfid.fid_gen = ((__u32 *)data)[1];
- xfid.fid_ino = ((__u32 *)data)[0];
-
- VFS_VGET(vfsp, &vp, (fid_t *)&xfid, error);
+ VFS_VGET(vfsp, &vp, (fid_t *)data, error);
if (error || vp == NULL)
return ERR_PTR(-ESTALE) ;
@@ -125,6 +199,7 @@ linvfs_get_parent(
struct export_operations linvfs_export_ops = {
.decode_fh = linvfs_decode_fh,
+ .encode_fh = linvfs_encode_fh,
.get_parent = linvfs_get_parent,
.get_dentry = linvfs_get_dentry,
};
diff --git a/fs/xfs/linux-2.6/xfs_export.h b/fs/xfs/linux-2.6/xfs_export.h
new file mode 100644
index 0000000000000..60b2abac1c18b
--- /dev/null
+++ b/fs/xfs/linux-2.6/xfs_export.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2005 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like. Any license provided herein, whether implied or
+ * otherwise, applies only to this software file. Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA 94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+#ifndef __XFS_EXPORT_H__
+#define __XFS_EXPORT_H__
+
+/*
+ * Common defines for code related to exporting XFS filesystems over NFS.
+ *
+ * The NFS fileid goes out on the wire as an array of
+ * 32bit unsigned ints in host order. There are 5 possible
+ * formats.
+ *
+ * (1) fileid_type=0x00
+ * (no fileid data; handled by the generic code)
+ *
+ * (2) fileid_type=0x01
+ * inode-num
+ * generation
+ *
+ * (3) fileid_type=0x02
+ * inode-num
+ * generation
+ * parent-inode-num
+ * parent-generation
+ *
+ * (4) fileid_type=0x81
+ * inode-num-lo32
+ * inode-num-hi32
+ * generation
+ *
+ * (5) fileid_type=0x82
+ * inode-num-lo32
+ * inode-num-hi32
+ * generation
+ * parent-inode-num-lo32
+ * parent-inode-num-hi32
+ * parent-generation
+ *
+ * Note, the NFS filehandle also includes an fsid portion which
+ * may have an inode number in it. That number is hardcoded to
+ * 32bits and there is no way for XFS to intercept it. In
+ * practice this means when exporting an XFS filesytem with 64bit
+ * inodes you should either export the mountpoint (rather than
+ * a subdirectory) or use the "fsid" export option.
+ */
+
+/* This flag goes on the wire. Don't play with it. */
+#define XFS_FILEID_TYPE_64FLAG 0x80 /* NFS fileid has 64bit inodes */
+
+/* Calculate the length in u32 units of the fileid data */
+static inline int
+xfs_fileid_length(int hasparent, int is64)
+{
+ return hasparent ? (is64 ? 6 : 4) : (is64 ? 3 : 2);
+}
+
+/*
+ * Decode encoded inode information (either for the inode itself
+ * or the parent) into an xfs_fid2_t structure. Advances and
+ * returns the new data pointer
+ */
+static inline __u32 *
+xfs_fileid_decode_fid2(__u32 *p, xfs_fid2_t *fid, int is64)
+{
+ fid->fid_len = sizeof(xfs_fid2_t) - sizeof(fid->fid_len);
+ fid->fid_pad = 0;
+ fid->fid_ino = *p++;
+#if XFS_BIG_INUMS
+ if (is64)
+ fid->fid_ino |= (((__u64)(*p++)) << 32);
+#endif
+ fid->fid_gen = *p++;
+ return p;
+}
+
+/*
+ * Encode inode information (either for the inode itself or the
+ * parent) into a fileid buffer. Advances and returns the new
+ * data pointer.
+ */
+static inline __u32 *
+xfs_fileid_encode_inode(__u32 *p, struct inode *inode, int is64)
+{
+ *p++ = (__u32)inode->i_ino;
+#if XFS_BIG_INUMS
+ if (is64)
+ *p++ = (__u32)(inode->i_ino >> 32);
+#endif
+ *p++ = inode->i_generation;
+ return p;
+}
+
+#endif /* __XFS_EXPORT_H__ */
diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c
index 7321db1c2fb43..9f057a4a5b06a 100644
--- a/fs/xfs/linux-2.6/xfs_file.c
+++ b/fs/xfs/linux-2.6/xfs_file.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000-2004 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
@@ -482,6 +482,38 @@ linvfs_mprotect(
}
#endif /* HAVE_VMOP_MPROTECT */
+#ifdef HAVE_FOP_OPEN_EXEC
+/* If the user is attempting to execute a file that is offline then
+ * we have to trigger a DMAPI READ event before the file is marked as busy
+ * otherwise the invisible I/O will not be able to write to the file to bring
+ * it back online.
+ */
+STATIC int
+linvfs_open_exec(
+ struct inode *inode)
+{
+ 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) {
+ 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);
+ }
+ }
+open_exec_out:
+ return error;
+}
+#endif /* HAVE_FOP_OPEN_EXEC */
struct file_operations linvfs_file_operations = {
.llseek = generic_file_llseek,
@@ -500,6 +532,9 @@ struct file_operations linvfs_file_operations = {
.open = linvfs_open,
.release = linvfs_release,
.fsync = linvfs_fsync,
+#ifdef HAVE_FOP_OPEN_EXEC
+ .open_exec = linvfs_open_exec,
+#endif
};
struct file_operations linvfs_invis_file_operations = {
diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c
index 77c393654537d..69809eef8a54b 100644
--- a/fs/xfs/linux-2.6/xfs_ioctl.c
+++ b/fs/xfs/linux-2.6/xfs_ioctl.c
@@ -202,10 +202,6 @@ STATIC int
xfs_vget_fsop_handlereq(
xfs_mount_t *mp,
struct inode *parinode, /* parent inode pointer */
- int cap, /* capability level for op */
- void __user *arg, /* userspace data pointer */
- unsigned long size, /* size of expected struct */
- /* output arguments */
xfs_fsop_handlereq_t *hreq,
vnode_t **vp,
struct inode **inode)
@@ -222,22 +218,12 @@ xfs_vget_fsop_handlereq(
__u32 igen;
int error;
- if (!capable(cap))
- return XFS_ERROR(EPERM);
-
/*
* Only allow handle opens under a directory.
*/
if (!S_ISDIR(parinode->i_mode))
return XFS_ERROR(ENOTDIR);
- /*
- * Copy the handle down from the user and validate
- * that it looks to be in the correct format.
- */
- if (copy_from_user(hreq, arg, size))
- return XFS_ERROR(EFAULT);
-
hanp = hreq->ihandle;
hlen = hreq->ihandlen;
handlep = &handle;
@@ -305,9 +291,12 @@ xfs_open_by_handle(
vnode_t *vp;
xfs_fsop_handlereq_t hreq;
- error = xfs_vget_fsop_handlereq(mp, parinode, CAP_SYS_ADMIN, arg,
- sizeof(xfs_fsop_handlereq_t),
- &hreq, &vp, &inode);
+ if (!capable(CAP_SYS_ADMIN))
+ return -XFS_ERROR(EPERM);
+ if (copy_from_user(&hreq, arg, sizeof(xfs_fsop_handlereq_t)))
+ return -XFS_ERROR(EFAULT);
+
+ error = xfs_vget_fsop_handlereq(mp, parinode, &hreq, &vp, &inode);
if (error)
return -error;
@@ -387,9 +376,12 @@ xfs_readlink_by_handle(
vnode_t *vp;
__u32 olen;
- error = xfs_vget_fsop_handlereq(mp, parinode, CAP_SYS_ADMIN, arg,
- sizeof(xfs_fsop_handlereq_t),
- &hreq, &vp, &inode);
+ if (!capable(CAP_SYS_ADMIN))
+ return -XFS_ERROR(EPERM);
+ if (copy_from_user(&hreq, arg, sizeof(xfs_fsop_handlereq_t)))
+ return -XFS_ERROR(EFAULT);
+
+ error = xfs_vget_fsop_handlereq(mp, parinode, &hreq, &vp, &inode);
if (error)
return -error;
@@ -432,10 +424,12 @@ xfs_fssetdm_by_handle(
bhv_desc_t *bdp;
vnode_t *vp;
- error = xfs_vget_fsop_handlereq(mp, parinode, CAP_MKNOD, arg,
- sizeof(xfs_fsop_setdm_handlereq_t),
- (xfs_fsop_handlereq_t *)&dmhreq,
- &vp, &inode);
+ if (!capable(CAP_MKNOD))
+ return -XFS_ERROR(EPERM);
+ if (copy_from_user(&dmhreq, arg, sizeof(xfs_fsop_setdm_handlereq_t)))
+ return -XFS_ERROR(EFAULT);
+
+ error = xfs_vget_fsop_handlereq(mp, parinode, &dmhreq.hreq, &vp, &inode);
if (error)
return -error;
@@ -470,21 +464,113 @@ xfs_attrlist_by_handle(
xfs_fsop_attrlist_handlereq_t al_hreq;
struct inode *inode;
vnode_t *vp;
+ char *kbuf;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -XFS_ERROR(EPERM);
+ if (copy_from_user(&al_hreq, arg, sizeof(xfs_fsop_attrlist_handlereq_t)))
+ return -XFS_ERROR(EFAULT);
+ if (al_hreq.buflen > XATTR_LIST_MAX)
+ return -XFS_ERROR(EINVAL);
- error = xfs_vget_fsop_handlereq(mp, parinode, CAP_SYS_ADMIN, arg,
- sizeof(xfs_fsop_attrlist_handlereq_t),
- (xfs_fsop_handlereq_t *)&al_hreq,
- &vp, &inode);
+ error = xfs_vget_fsop_handlereq(mp, parinode, &al_hreq.hreq,
+ &vp, &inode);
if (error)
- return -error;
+ goto out;
+
+ kbuf = kmalloc(al_hreq.buflen, GFP_KERNEL);
+ if (!kbuf)
+ goto out_vn_rele;
cursor = (attrlist_cursor_kern_t *)&al_hreq.pos;
- VOP_ATTR_LIST(vp, al_hreq.buffer, al_hreq.buflen, al_hreq.flags,
+ VOP_ATTR_LIST(vp, kbuf, al_hreq.buflen, al_hreq.flags,
cursor, NULL, error);
+ if (error)
+ goto out_kfree;
+
+ if (copy_to_user(al_hreq.buffer, kbuf, al_hreq.buflen))
+ error = -EFAULT;
+
+ out_kfree:
+ kfree(kbuf);
+ out_vn_rele:
VN_RELE(vp);
+ out:
+ return -error;
+}
+
+STATIC int
+xfs_attrmulti_attr_get(
+ struct vnode *vp,
+ char *name,
+ char __user *ubuf,
+ __uint32_t *len,
+ __uint32_t flags)
+{
+ char *kbuf;
+ int error = EFAULT;
+
+ if (*len > XATTR_SIZE_MAX)
+ return EINVAL;
+ kbuf = kmalloc(*len, GFP_KERNEL);
+ if (!kbuf)
+ return ENOMEM;
+
+ VOP_ATTR_GET(vp, name, kbuf, len, flags, NULL, error);
if (error)
- return -error;
- return 0;
+ goto out_kfree;
+
+ if (copy_to_user(ubuf, kbuf, *len))
+ error = EFAULT;
+
+ out_kfree:
+ kfree(kbuf);
+ return error;
+}
+
+STATIC int
+xfs_attrmulti_attr_set(
+ struct vnode *vp,
+ char *name,
+ const char __user *ubuf,
+ __uint32_t len,
+ __uint32_t flags)
+{
+ char *kbuf;
+ int error = EFAULT;
+
+ if (IS_IMMUTABLE(&vp->v_inode) || IS_APPEND(&vp->v_inode))
+ return EPERM;
+ if (len > XATTR_SIZE_MAX)
+ return EINVAL;
+
+ kbuf = kmalloc(len, GFP_KERNEL);
+ if (!kbuf)
+ return ENOMEM;
+
+ if (copy_from_user(kbuf, ubuf, len))
+ goto out_kfree;
+
+ VOP_ATTR_SET(vp, name, kbuf, len, flags, NULL, error);
+
+ out_kfree:
+ kfree(kbuf);
+ return error;
+}
+
+STATIC int
+xfs_attrmulti_attr_remove(
+ struct vnode *vp,
+ char *name,
+ __uint32_t flags)
+{
+ int error;
+
+ if (IS_IMMUTABLE(&vp->v_inode) || IS_APPEND(&vp->v_inode))
+ return EPERM;
+
+ VOP_ATTR_REMOVE(vp, name, flags, NULL, error);
+ return error;
}
STATIC int
@@ -500,55 +586,59 @@ xfs_attrmulti_by_handle(
struct inode *inode;
vnode_t *vp;
unsigned int i, size;
+ char *attr_name;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -XFS_ERROR(EPERM);
+ if (copy_from_user(&am_hreq, arg, sizeof(xfs_fsop_attrmulti_handlereq_t)))
+ return -XFS_ERROR(EFAULT);
- error = xfs_vget_fsop_handlereq(mp, parinode, CAP_SYS_ADMIN, arg,
- sizeof(xfs_fsop_attrmulti_handlereq_t),
- (xfs_fsop_handlereq_t *)&am_hreq,
- &vp, &inode);
+ error = xfs_vget_fsop_handlereq(mp, parinode, &am_hreq.hreq, &vp, &inode);
if (error)
- return -error;
+ goto out;
+ error = E2BIG;
size = am_hreq.opcount * sizeof(attr_multiop_t);
- if (!size || size > 16 * PAGE_SIZE) {
- VN_RELE(vp);
- return -XFS_ERROR(E2BIG);
- }
+ if (!size || size > 16 * PAGE_SIZE)
+ goto out_vn_rele;
- ops = (xfs_attr_multiop_t *)kmalloc(size, GFP_KERNEL);
- if (!ops) {
- VN_RELE(vp);
- return -XFS_ERROR(ENOMEM);
- }
+ error = ENOMEM;
+ ops = kmalloc(size, GFP_KERNEL);
+ if (!ops)
+ goto out_vn_rele;
+
+ error = EFAULT;
+ if (copy_from_user(ops, am_hreq.ops, size))
+ goto out_kfree_ops;
+
+ attr_name = kmalloc(MAXNAMELEN, GFP_KERNEL);
+ if (!attr_name)
+ goto out_kfree_ops;
- if (copy_from_user(ops, am_hreq.ops, size)) {
- kfree(ops);
- VN_RELE(vp);
- return -XFS_ERROR(EFAULT);
- }
+ error = 0;
for (i = 0; i < am_hreq.opcount; i++) {
- switch(ops[i].am_opcode) {
+ ops[i].am_error = strncpy_from_user(attr_name,
+ ops[i].am_attrname, MAXNAMELEN);
+ if (ops[i].am_error == 0 || ops[i].am_error == MAXNAMELEN)
+ error = -ERANGE;
+ if (ops[i].am_error < 0)
+ break;
+
+ switch (ops[i].am_opcode) {
case ATTR_OP_GET:
- VOP_ATTR_GET(vp,ops[i].am_attrname, ops[i].am_attrvalue,
- &ops[i].am_length, ops[i].am_flags,
- NULL, ops[i].am_error);
+ ops[i].am_error = xfs_attrmulti_attr_get(vp,
+ attr_name, ops[i].am_attrvalue,
+ &ops[i].am_length, ops[i].am_flags);
break;
case ATTR_OP_SET:
- if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) {
- ops[i].am_error = EPERM;
- break;
- }
- VOP_ATTR_SET(vp,ops[i].am_attrname, ops[i].am_attrvalue,
- ops[i].am_length, ops[i].am_flags,
- NULL, ops[i].am_error);
+ ops[i].am_error = xfs_attrmulti_attr_set(vp,
+ attr_name, ops[i].am_attrvalue,
+ ops[i].am_length, ops[i].am_flags);
break;
case ATTR_OP_REMOVE:
- if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) {
- ops[i].am_error = EPERM;
- break;
- }
- VOP_ATTR_REMOVE(vp, ops[i].am_attrname, ops[i].am_flags,
- NULL, ops[i].am_error);
+ ops[i].am_error = xfs_attrmulti_attr_remove(vp,
+ attr_name, ops[i].am_flags);
break;
default:
ops[i].am_error = EINVAL;
@@ -556,11 +646,15 @@ xfs_attrmulti_by_handle(
}
if (copy_to_user(am_hreq.ops, ops, size))
- error = -XFS_ERROR(EFAULT);
+ error = XFS_ERROR(EFAULT);
+ kfree(attr_name);
+ out_kfree_ops:
kfree(ops);
+ out_vn_rele:
VN_RELE(vp);
- return error;
+ out:
+ return -error;
}
/* prototypes for a few of the stack-hungry cases that have
@@ -1149,7 +1243,7 @@ xfs_ioc_xattr(
va.va_mask = XFS_AT_XFLAGS;
va.va_xflags = xfs_merge_ioc_xflags(flags,
- xfs_dic2xflags(&ip->i_d, ARCH_NOCONVERT));
+ xfs_ip2xflags(ip));
VOP_SETATTR(vp, &va, attr_flags, NULL, error);
if (!error)
diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h
index 42e2c2666d878..71bb41019a12c 100644
--- a/fs/xfs/linux-2.6/xfs_linux.h
+++ b/fs/xfs/linux-2.6/xfs_linux.h
@@ -88,6 +88,7 @@
#include <linux/list.h>
#include <linux/proc_fs.h>
#include <linux/version.h>
+#include <linux/sort.h>
#include <asm/page.h>
#include <asm/div64.h>
@@ -368,4 +369,6 @@ static inline __uint64_t roundup_64(__uint64_t x, __uint32_t y)
return(x * y);
}
+#define qsort(a, n, s, cmp) sort(a, n, s, cmp, NULL)
+
#endif /* __XFS_LINUX__ */
diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c
index 9bec802f12061..ff145fd0d1a42 100644
--- a/fs/xfs/linux-2.6/xfs_lrw.c
+++ b/fs/xfs/linux-2.6/xfs_lrw.c
@@ -871,6 +871,7 @@ retry:
goto out_unlock_isem;
xfs_rwlock(bdp, locktype);
pos = xip->i_d.di_size;
+ ret = 0;
goto retry;
}
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c
index 0c084a1155e4a..53dc658cafa63 100644
--- a/fs/xfs/linux-2.6/xfs_super.c
+++ b/fs/xfs/linux-2.6/xfs_super.c
@@ -76,7 +76,6 @@
STATIC struct quotactl_ops linvfs_qops;
STATIC struct super_operations linvfs_sops;
STATIC kmem_zone_t *linvfs_inode_zone;
-STATIC kmem_shaker_t xfs_inode_shaker;
STATIC struct xfs_mount_args *
xfs_args_allocate(
@@ -91,6 +90,10 @@ xfs_args_allocate(
/* Copy the already-parsed mount(2) flags we're interested in */
if (sb->s_flags & MS_NOATIME)
args->flags |= XFSMNT_NOATIME;
+ if (sb->s_flags & MS_DIRSYNC)
+ args->flags |= XFSMNT_DIRSYNC;
+ if (sb->s_flags & MS_SYNCHRONOUS)
+ args->flags |= XFSMNT_WSYNC;
/* Default to 32 bit inodes on Linux all the time */
args->flags |= XFSMNT_32BITINODES;
@@ -286,18 +289,6 @@ linvfs_destroy_inode(
kmem_cache_free(linvfs_inode_zone, LINVFS_GET_VP(inode));
}
-STATIC int
-xfs_inode_shake(
- int priority,
- unsigned int gfp_mask)
-{
- int pages;
-
- pages = kmem_zone_shrink(linvfs_inode_zone);
- pages += kmem_zone_shrink(xfs_inode_zone);
- return pages;
-}
-
STATIC void
init_once(
void *data,
@@ -885,12 +876,6 @@ init_xfs_fs( void )
uuid_init();
vfs_initquota();
- xfs_inode_shaker = kmem_shake_register(xfs_inode_shake);
- if (!xfs_inode_shaker) {
- error = -ENOMEM;
- goto undo_shaker;
- }
-
error = register_filesystem(&xfs_fs_type);
if (error)
goto undo_register;
@@ -898,9 +883,6 @@ init_xfs_fs( void )
return 0;
undo_register:
- kmem_shake_deregister(xfs_inode_shaker);
-
-undo_shaker:
pagebuf_terminate();
undo_pagebuf:
@@ -916,7 +898,6 @@ exit_xfs_fs( void )
vfs_exitquota();
XFS_DM_EXIT(&xfs_fs_type);
unregister_filesystem(&xfs_fs_type);
- kmem_shake_deregister(xfs_inode_shaker);
xfs_cleanup();
pagebuf_terminate();
destroy_inodecache();
diff --git a/fs/xfs/linux-2.6/xfs_vfs.c b/fs/xfs/linux-2.6/xfs_vfs.c
index cce462dcbaea2..669c61644959c 100644
--- a/fs/xfs/linux-2.6/xfs_vfs.c
+++ b/fs/xfs/linux-2.6/xfs_vfs.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) 2000-2004 Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
diff --git a/fs/xfs/linux-2.6/xfs_vfs.h b/fs/xfs/linux-2.6/xfs_vfs.h
index aab70136c4e89..76493991578ff 100644
--- a/fs/xfs/linux-2.6/xfs_vfs.h
+++ b/fs/xfs/linux-2.6/xfs_vfs.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) 2000-2004 Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
diff --git a/fs/xfs/quota/xfs_dquot.c b/fs/xfs/quota/xfs_dquot.c
index fbfb24c7066ed..740d20d331874 100644
--- a/fs/xfs/quota/xfs_dquot.c
+++ b/fs/xfs/quota/xfs_dquot.c
@@ -261,21 +261,19 @@ xfs_qm_adjust_dqlimits(
{
xfs_quotainfo_t *q = mp->m_quotainfo;
- ASSERT(!INT_ISZERO(d->d_id, ARCH_CONVERT));
+ ASSERT(d->d_id);
- if (q->qi_bsoftlimit && INT_ISZERO(d->d_blk_softlimit, ARCH_CONVERT))
+ if (q->qi_bsoftlimit && !d->d_blk_softlimit)
INT_SET(d->d_blk_softlimit, ARCH_CONVERT, q->qi_bsoftlimit);
- if (q->qi_bhardlimit && INT_ISZERO(d->d_blk_hardlimit, ARCH_CONVERT))
+ if (q->qi_bhardlimit && !d->d_blk_hardlimit)
INT_SET(d->d_blk_hardlimit, ARCH_CONVERT, q->qi_bhardlimit);
- if (q->qi_isoftlimit && INT_ISZERO(d->d_ino_softlimit, ARCH_CONVERT))
+ if (q->qi_isoftlimit && !d->d_ino_softlimit)
INT_SET(d->d_ino_softlimit, ARCH_CONVERT, q->qi_isoftlimit);
- if (q->qi_ihardlimit && INT_ISZERO(d->d_ino_hardlimit, ARCH_CONVERT))
+ if (q->qi_ihardlimit && !d->d_ino_hardlimit)
INT_SET(d->d_ino_hardlimit, ARCH_CONVERT, q->qi_ihardlimit);
- if (q->qi_rtbsoftlimit &&
- INT_ISZERO(d->d_rtb_softlimit, ARCH_CONVERT))
+ if (q->qi_rtbsoftlimit && !d->d_rtb_softlimit)
INT_SET(d->d_rtb_softlimit, ARCH_CONVERT, q->qi_rtbsoftlimit);
- if (q->qi_rtbhardlimit &&
- INT_ISZERO(d->d_rtb_hardlimit, ARCH_CONVERT))
+ if (q->qi_rtbhardlimit && !d->d_rtb_hardlimit)
INT_SET(d->d_rtb_hardlimit, ARCH_CONVERT, q->qi_rtbhardlimit);
}
@@ -295,7 +293,7 @@ xfs_qm_adjust_dqtimers(
xfs_mount_t *mp,
xfs_disk_dquot_t *d)
{
- ASSERT(!INT_ISZERO(d->d_id, ARCH_CONVERT));
+ ASSERT(d->d_id);
#ifdef QUOTADEBUG
if (INT_GET(d->d_blk_hardlimit, ARCH_CONVERT))
@@ -308,7 +306,7 @@ xfs_qm_adjust_dqtimers(
ASSERT(INT_GET(d->d_rtb_softlimit, ARCH_CONVERT) <=
INT_GET(d->d_rtb_hardlimit, ARCH_CONVERT));
#endif
- if (INT_ISZERO(d->d_btimer, ARCH_CONVERT)) {
+ if (!d->d_btimer) {
if ((INT_GET(d->d_blk_softlimit, ARCH_CONVERT) &&
(INT_GET(d->d_bcount, ARCH_CONVERT) >=
INT_GET(d->d_blk_softlimit, ARCH_CONVERT))) ||
@@ -319,17 +317,17 @@ xfs_qm_adjust_dqtimers(
get_seconds() + XFS_QI_BTIMELIMIT(mp));
}
} else {
- if ((INT_ISZERO(d->d_blk_softlimit, ARCH_CONVERT) ||
+ if ((!d->d_blk_softlimit ||
(INT_GET(d->d_bcount, ARCH_CONVERT) <
INT_GET(d->d_blk_softlimit, ARCH_CONVERT))) &&
- (INT_ISZERO(d->d_blk_hardlimit, ARCH_CONVERT) ||
+ (!d->d_blk_hardlimit ||
(INT_GET(d->d_bcount, ARCH_CONVERT) <
INT_GET(d->d_blk_hardlimit, ARCH_CONVERT)))) {
- INT_ZERO(d->d_btimer, ARCH_CONVERT);
+ d->d_btimer = 0;
}
}
- if (INT_ISZERO(d->d_itimer, ARCH_CONVERT)) {
+ if (!d->d_itimer) {
if ((INT_GET(d->d_ino_softlimit, ARCH_CONVERT) &&
(INT_GET(d->d_icount, ARCH_CONVERT) >=
INT_GET(d->d_ino_softlimit, ARCH_CONVERT))) ||
@@ -340,17 +338,17 @@ xfs_qm_adjust_dqtimers(
get_seconds() + XFS_QI_ITIMELIMIT(mp));
}
} else {
- if ((INT_ISZERO(d->d_ino_softlimit, ARCH_CONVERT) ||
+ if ((!d->d_ino_softlimit ||
(INT_GET(d->d_icount, ARCH_CONVERT) <
INT_GET(d->d_ino_softlimit, ARCH_CONVERT))) &&
- (INT_ISZERO(d->d_ino_hardlimit, ARCH_CONVERT) ||
+ (!d->d_ino_hardlimit ||
(INT_GET(d->d_icount, ARCH_CONVERT) <
INT_GET(d->d_ino_hardlimit, ARCH_CONVERT)))) {
- INT_ZERO(d->d_itimer, ARCH_CONVERT);
+ d->d_itimer = 0;
}
}
- if (INT_ISZERO(d->d_rtbtimer, ARCH_CONVERT)) {
+ if (!d->d_rtbtimer) {
if ((INT_GET(d->d_rtb_softlimit, ARCH_CONVERT) &&
(INT_GET(d->d_rtbcount, ARCH_CONVERT) >=
INT_GET(d->d_rtb_softlimit, ARCH_CONVERT))) ||
@@ -361,13 +359,13 @@ xfs_qm_adjust_dqtimers(
get_seconds() + XFS_QI_RTBTIMELIMIT(mp));
}
} else {
- if ((INT_ISZERO(d->d_rtb_softlimit, ARCH_CONVERT) ||
+ if ((!d->d_rtb_softlimit ||
(INT_GET(d->d_rtbcount, ARCH_CONVERT) <
INT_GET(d->d_rtb_softlimit, ARCH_CONVERT))) &&
- (INT_ISZERO(d->d_rtb_hardlimit, ARCH_CONVERT) ||
+ (!d->d_rtb_hardlimit ||
(INT_GET(d->d_rtbcount, ARCH_CONVERT) <
INT_GET(d->d_rtb_hardlimit, ARCH_CONVERT)))) {
- INT_ZERO(d->d_rtbtimer, ARCH_CONVERT);
+ d->d_rtbtimer = 0;
}
}
}
@@ -385,7 +383,7 @@ xfs_qm_dqwarn(
/*
* root's limits are not real limits.
*/
- if (INT_ISZERO(d->d_id, ARCH_CONVERT))
+ if (!d->d_id)
return (0);
warned = 0;
@@ -397,10 +395,10 @@ xfs_qm_dqwarn(
warned++;
}
} else {
- if (INT_ISZERO(d->d_blk_softlimit, ARCH_CONVERT) ||
+ if (!d->d_blk_softlimit ||
(INT_GET(d->d_bcount, ARCH_CONVERT) <
INT_GET(d->d_blk_softlimit, ARCH_CONVERT))) {
- INT_ZERO(d->d_bwarns, ARCH_CONVERT);
+ d->d_bwarns = 0;
}
}
@@ -412,10 +410,10 @@ xfs_qm_dqwarn(
warned++;
}
} else {
- if ((INT_ISZERO(d->d_ino_softlimit, ARCH_CONVERT)) ||
+ if (!d->d_ino_softlimit ||
(INT_GET(d->d_icount, ARCH_CONVERT) <
INT_GET(d->d_ino_softlimit, ARCH_CONVERT))) {
- INT_ZERO(d->d_iwarns, ARCH_CONVERT);
+ d->d_iwarns = 0;
}
}
#ifdef QUOTADEBUG
diff --git a/fs/xfs/quota/xfs_qm_syscalls.c b/fs/xfs/quota/xfs_qm_syscalls.c
index 3548ced327243..229f5b5a2d25e 100644
--- a/fs/xfs/quota/xfs_qm_syscalls.c
+++ b/fs/xfs/quota/xfs_qm_syscalls.c
@@ -1211,8 +1211,7 @@ xfs_dqtest_cmp2(
if (INT_GET(dqp->q_core.d_blk_softlimit, ARCH_CONVERT) &&
INT_GET(dqp->q_core.d_bcount, ARCH_CONVERT) >=
INT_GET(dqp->q_core.d_blk_softlimit, ARCH_CONVERT)) {
- if (INT_ISZERO(dqp->q_core.d_btimer, ARCH_CONVERT) &&
- !INT_ISZERO(dqp->q_core.d_id, ARCH_CONVERT)) {
+ if (!dqp->q_core.d_btimer && dqp->q_core.d_id) {
cmn_err(CE_DEBUG,
"%d [%s] [0x%p] BLK TIMER NOT STARTED",
d->d_id, DQFLAGTO_TYPESTR(d), d->q_mount);
@@ -1222,8 +1221,7 @@ xfs_dqtest_cmp2(
if (INT_GET(dqp->q_core.d_ino_softlimit, ARCH_CONVERT) &&
INT_GET(dqp->q_core.d_icount, ARCH_CONVERT) >=
INT_GET(dqp->q_core.d_ino_softlimit, ARCH_CONVERT)) {
- if (INT_ISZERO(dqp->q_core.d_itimer, ARCH_CONVERT) &&
- !INT_ISZERO(dqp->q_core.d_id, ARCH_CONVERT)) {
+ if (!dqp->q_core.d_itimer && dqp->q_core.d_id) {
cmn_err(CE_DEBUG,
"%d [%s] [0x%p] INO TIMER NOT STARTED",
d->d_id, DQFLAGTO_TYPESTR(d), d->q_mount);
diff --git a/fs/xfs/quota/xfs_quota_priv.h b/fs/xfs/quota/xfs_quota_priv.h
index eeda93a2b9510..414b6004af216 100644
--- a/fs/xfs/quota/xfs_quota_priv.h
+++ b/fs/xfs/quota/xfs_quota_priv.h
@@ -104,15 +104,15 @@ static inline int XQMISLCKD(struct xfs_dqhash *h)
#define XFS_IS_DQTYPE_ON(mp, type) (type == XFS_DQ_USER ? \
XFS_IS_UQUOTA_ON(mp):XFS_IS_GQUOTA_ON(mp))
#define XFS_IS_DQUOT_UNINITIALIZED(dqp) ( \
- INT_ISZERO(dqp->q_core.d_blk_hardlimit, ARCH_CONVERT) && \
- INT_ISZERO(dqp->q_core.d_blk_softlimit, ARCH_CONVERT) && \
- INT_ISZERO(dqp->q_core.d_rtb_hardlimit, ARCH_CONVERT) && \
- INT_ISZERO(dqp->q_core.d_rtb_softlimit, ARCH_CONVERT) && \
- INT_ISZERO(dqp->q_core.d_ino_hardlimit, ARCH_CONVERT) && \
- INT_ISZERO(dqp->q_core.d_ino_softlimit, ARCH_CONVERT) && \
- INT_ISZERO(dqp->q_core.d_bcount, ARCH_CONVERT) && \
- INT_ISZERO(dqp->q_core.d_rtbcount, ARCH_CONVERT) && \
- INT_ISZERO(dqp->q_core.d_icount, ARCH_CONVERT))
+ !dqp->q_core.d_blk_hardlimit && \
+ !dqp->q_core.d_blk_softlimit && \
+ !dqp->q_core.d_rtb_hardlimit && \
+ !dqp->q_core.d_rtb_softlimit && \
+ !dqp->q_core.d_ino_hardlimit && \
+ !dqp->q_core.d_ino_softlimit && \
+ !dqp->q_core.d_bcount && \
+ !dqp->q_core.d_rtbcount && \
+ !dqp->q_core.d_icount)
#define HL_PREVP dq_hashlist.ql_prevp
#define HL_NEXT dq_hashlist.ql_next
@@ -174,7 +174,7 @@ for ((dqp) = (qlist)->qh_next; (dqp) != (xfs_dquot_t *)(qlist); \
(tp)->t_dqinfo->dqa_usrdquots : \
(tp)->t_dqinfo->dqa_grpdquots)
#define XFS_IS_SUSER_DQUOT(dqp) \
- (INT_ISZERO((dqp)->q_core.d_id, ARCH_CONVERT))
+ (!((dqp)->q_core.d_id))
#define XFS_PURGE_INODE(ip) \
{ \
diff --git a/fs/xfs/quota/xfs_trans_dquot.c b/fs/xfs/quota/xfs_trans_dquot.c
index 25079b5727e44..149b2a1fd949b 100644
--- a/fs/xfs/quota/xfs_trans_dquot.c
+++ b/fs/xfs/quota/xfs_trans_dquot.c
@@ -455,7 +455,7 @@ xfs_trans_apply_dquot_deltas(
* Get any default limits in use.
* Start/reset the timer(s) if needed.
*/
- if (!INT_ISZERO(d->d_id, ARCH_CONVERT)) {
+ if (d->d_id) {
xfs_qm_adjust_dqlimits(tp->t_mountp, d);
xfs_qm_adjust_dqtimers(tp->t_mountp, d);
}
@@ -669,7 +669,7 @@ xfs_trans_dqresv(
error = 0;
if ((flags & XFS_QMOPT_FORCE_RES) == 0 &&
- !INT_ISZERO(dqp->q_core.d_id, ARCH_CONVERT) &&
+ dqp->q_core.d_id &&
XFS_IS_QUOTA_ENFORCED(dqp->q_mount)) {
#ifdef QUOTADEBUG
cmn_err(CE_DEBUG, "BLK Res: nblks=%ld + resbcount=%Ld"
@@ -694,7 +694,7 @@ xfs_trans_dqresv(
* return EDQUOT
*/
if ((btimer != 0 && get_seconds() > btimer) ||
- (!INT_ISZERO(dqp->q_core.d_bwarns, ARCH_CONVERT) &&
+ (dqp->q_core.d_bwarns &&
INT_GET(dqp->q_core.d_bwarns, ARCH_CONVERT) >=
XFS_QI_BWARNLIMIT(dqp->q_mount))) {
error = EDQUOT;
@@ -719,9 +719,9 @@ xfs_trans_dqresv(
* If timer or warnings has expired,
* return EDQUOT
*/
- if ((!INT_ISZERO(dqp->q_core.d_itimer, ARCH_CONVERT) &&
+ if ((dqp->q_core.d_itimer &&
get_seconds() > INT_GET(dqp->q_core.d_itimer, ARCH_CONVERT)) ||
- (!INT_ISZERO(dqp->q_core.d_iwarns, ARCH_CONVERT) &&
+ (dqp->q_core.d_iwarns &&
INT_GET(dqp->q_core.d_iwarns, ARCH_CONVERT) >=
XFS_QI_IWARNLIMIT(dqp->q_mount))) {
error = EDQUOT;
diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c
index b800f8f4e058d..8d01dce8c532f 100644
--- a/fs/xfs/xfs_acl.c
+++ b/fs/xfs/xfs_acl.c
@@ -403,38 +403,6 @@ xfs_acl_allow_set(
}
/*
- * Look for any effective exec access, to allow CAP_DAC_OVERRIDE for exec.
- * Ignore checking for exec in USER_OBJ when there is no mask, because
- * in this "minimal acl" case we don't have any actual acls, and we
- * won't even be here.
- */
-STATIC int
-xfs_acl_find_any_exec(
- xfs_acl_t *fap)
-{
- int i;
- int masked_aces = 0;
- int mask = 0;
-
- for (i = 0; i < fap->acl_cnt; i++) {
- if (fap->acl_entry[i].ae_perm & ACL_EXECUTE) {
- if (fap->acl_entry[i].ae_tag & (ACL_USER_OBJ|ACL_OTHER))
- return 1;
-
- if (fap->acl_entry[i].ae_tag == ACL_MASK)
- mask = fap->acl_entry[i].ae_perm;
- else
- masked_aces |= fap->acl_entry[i].ae_perm;
-
- if ((mask & masked_aces) & ACL_EXECUTE)
- return 1;
- }
- }
-
- return 0;
-}
-
-/*
* The access control process to determine the access permission:
* if uid == file owner id, use the file owner bits.
* if gid == file owner group id, use the file group bits.
@@ -443,24 +411,19 @@ xfs_acl_find_any_exec(
* until all acl entries are exhausted. The final permission produced
* by matching acl entry or entries needs to be & with group permission.
* if not owner, owning group, or matching entry in ACL, use file
- * other bits. Don't allow CAP_DAC_OVERRIDE on exec access unless
- * there is some effective exec access somewhere.
+ * other bits.
*/
STATIC int
xfs_acl_capability_check(
mode_t mode,
- cred_t *cr,
- xfs_acl_t *fap)
+ cred_t *cr)
{
if ((mode & ACL_READ) && !capable_cred(cr, CAP_DAC_READ_SEARCH))
return EACCES;
if ((mode & ACL_WRITE) && !capable_cred(cr, CAP_DAC_OVERRIDE))
return EACCES;
- if ((mode & ACL_EXECUTE) &&
- (!capable_cred(cr, CAP_DAC_OVERRIDE) ||
- !xfs_acl_find_any_exec(fap))) {
+ if ((mode & ACL_EXECUTE) && !capable_cred(cr, CAP_DAC_OVERRIDE))
return EACCES;
- }
return 0;
}
@@ -567,7 +530,7 @@ xfs_acl_access(
break;
}
- return xfs_acl_capability_check(md, cr, fap);
+ return xfs_acl_capability_check(md, cr);
}
/*
diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c
index fa8799d55fb78..36603db10fe97 100644
--- a/fs/xfs/xfs_alloc.c
+++ b/fs/xfs/xfs_alloc.c
@@ -2009,7 +2009,7 @@ xfs_alloc_get_freelist(
/*
* Freelist is empty, give up.
*/
- if (INT_ISZERO(agf->agf_flcount, ARCH_CONVERT)) {
+ if (!agf->agf_flcount) {
*bnop = NULLAGBLOCK;
return 0;
}
@@ -2028,7 +2028,7 @@ xfs_alloc_get_freelist(
INT_MOD(agf->agf_flfirst, ARCH_CONVERT, 1);
xfs_trans_brelse(tp, agflbp);
if (INT_GET(agf->agf_flfirst, ARCH_CONVERT) == XFS_AGFL_SIZE(mp))
- INT_ZERO(agf->agf_flfirst, ARCH_CONVERT);
+ agf->agf_flfirst = 0;
pag = &mp->m_perag[INT_GET(agf->agf_seqno, ARCH_CONVERT)];
INT_MOD(agf->agf_flcount, ARCH_CONVERT, -1);
xfs_trans_agflist_delta(tp, -1);
@@ -2128,7 +2128,7 @@ xfs_alloc_put_freelist(
agfl = XFS_BUF_TO_AGFL(agflbp);
INT_MOD(agf->agf_fllast, ARCH_CONVERT, 1);
if (INT_GET(agf->agf_fllast, ARCH_CONVERT) == XFS_AGFL_SIZE(mp))
- INT_ZERO(agf->agf_fllast, ARCH_CONVERT);
+ agf->agf_fllast = 0;
pag = &mp->m_perag[INT_GET(agf->agf_seqno, ARCH_CONVERT)];
INT_MOD(agf->agf_flcount, ARCH_CONVERT, 1);
xfs_trans_agflist_delta(tp, 1);
diff --git a/fs/xfs/xfs_alloc_btree.c b/fs/xfs/xfs_alloc_btree.c
index 6b5de3a284e3f..e0355a12d946a 100644
--- a/fs/xfs/xfs_alloc_btree.c
+++ b/fs/xfs/xfs_alloc_btree.c
@@ -209,7 +209,7 @@ xfs_alloc_delrec(
* No free extents left.
*/
else
- INT_ZERO(agf->agf_longest, ARCH_CONVERT);
+ agf->agf_longest = 0;
mp->m_perag[INT_GET(agf->agf_seqno, ARCH_CONVERT)].pagf_longest =
INT_GET(agf->agf_longest, ARCH_CONVERT);
xfs_alloc_log_agf(cur->bc_tp, cur->bc_private.a.agbp,
diff --git a/fs/xfs/xfs_arch.h b/fs/xfs/xfs_arch.h
index 3c7a90bfb0e31..ae35189b3d700 100644
--- a/fs/xfs/xfs_arch.h
+++ b/fs/xfs/xfs_arch.h
@@ -72,69 +72,18 @@
((sizeof(type) == 2) ? INT_SWAP16(type,var) : \
(var))))
-#define INT_SWAP_UNALIGNED_32(from,to) \
- { \
- ((__u8*)(to))[0] = ((__u8*)(from))[3]; \
- ((__u8*)(to))[1] = ((__u8*)(from))[2]; \
- ((__u8*)(to))[2] = ((__u8*)(from))[1]; \
- ((__u8*)(to))[3] = ((__u8*)(from))[0]; \
- }
-
-#define INT_SWAP_UNALIGNED_64(from,to) \
- { \
- INT_SWAP_UNALIGNED_32( ((__u8*)(from)) + 4, ((__u8*)(to))); \
- INT_SWAP_UNALIGNED_32( ((__u8*)(from)), ((__u8*)(to)) + 4); \
- }
-
/*
* get and set integers from potentially unaligned locations
*/
-#define INT_GET_UNALIGNED_16_LE(pointer) \
- ((__u16)((((__u8*)(pointer))[0] ) | (((__u8*)(pointer))[1] << 8 )))
#define INT_GET_UNALIGNED_16_BE(pointer) \
((__u16)((((__u8*)(pointer))[0] << 8) | (((__u8*)(pointer))[1])))
-#define INT_SET_UNALIGNED_16_LE(pointer,value) \
- { \
- ((__u8*)(pointer))[0] = (((value) ) & 0xff); \
- ((__u8*)(pointer))[1] = (((value) >> 8) & 0xff); \
- }
#define INT_SET_UNALIGNED_16_BE(pointer,value) \
{ \
((__u8*)(pointer))[0] = (((value) >> 8) & 0xff); \
((__u8*)(pointer))[1] = (((value) ) & 0xff); \
}
-#define INT_GET_UNALIGNED_32_LE(pointer) \
- ((__u32)((((__u8*)(pointer))[0] ) | (((__u8*)(pointer))[1] << 8 ) \
- |(((__u8*)(pointer))[2] << 16) | (((__u8*)(pointer))[3] << 24)))
-#define INT_GET_UNALIGNED_32_BE(pointer) \
- ((__u32)((((__u8*)(pointer))[0] << 24) | (((__u8*)(pointer))[1] << 16) \
- |(((__u8*)(pointer))[2] << 8) | (((__u8*)(pointer))[3] )))
-
-#define INT_GET_UNALIGNED_64_LE(pointer) \
- (((__u64)(INT_GET_UNALIGNED_32_LE(((__u8*)(pointer))+4)) << 32 ) \
- |((__u64)(INT_GET_UNALIGNED_32_LE(((__u8*)(pointer)) )) ))
-#define INT_GET_UNALIGNED_64_BE(pointer) \
- (((__u64)(INT_GET_UNALIGNED_32_BE(((__u8*)(pointer)) )) << 32 ) \
- |((__u64)(INT_GET_UNALIGNED_32_BE(((__u8*)(pointer))+4)) ))
-
-/*
- * now pick the right ones for our MACHINE ARCHITECTURE
- */
-
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-#define INT_GET_UNALIGNED_16(pointer) INT_GET_UNALIGNED_16_LE(pointer)
-#define INT_SET_UNALIGNED_16(pointer,value) INT_SET_UNALIGNED_16_LE(pointer,value)
-#define INT_GET_UNALIGNED_32(pointer) INT_GET_UNALIGNED_32_LE(pointer)
-#define INT_GET_UNALIGNED_64(pointer) INT_GET_UNALIGNED_64_LE(pointer)
-#else
-#define INT_GET_UNALIGNED_16(pointer) INT_GET_UNALIGNED_16_BE(pointer)
-#define INT_SET_UNALIGNED_16(pointer,value) INT_SET_UNALIGNED_16_BE(pointer,value)
-#define INT_GET_UNALIGNED_32(pointer) INT_GET_UNALIGNED_32_BE(pointer)
-#define INT_GET_UNALIGNED_64(pointer) INT_GET_UNALIGNED_64_BE(pointer)
-#endif
-
/* define generic INT_ macros */
#define INT_GET(reference,arch) \
@@ -213,64 +162,52 @@
} \
}
-#define INT_ISZERO(reference,arch) \
- ((reference) == 0)
-
-#define INT_ZERO(reference,arch) \
- ((reference) = 0)
-
-#define INT_GET_UNALIGNED_16_ARCH(pointer,arch) \
- ( ((arch) == ARCH_NOCONVERT) \
- ? \
- (INT_GET_UNALIGNED_16(pointer)) \
- : \
- (INT_GET_UNALIGNED_16_BE(pointer)) \
- )
-#define INT_SET_UNALIGNED_16_ARCH(pointer,value,arch) \
- if ((arch) == ARCH_NOCONVERT) { \
- INT_SET_UNALIGNED_16(pointer,value); \
- } else { \
- INT_SET_UNALIGNED_16_BE(pointer,value); \
- }
-
-#define DIRINO4_GET_ARCH(pointer,arch) \
- ( ((arch) == ARCH_NOCONVERT) \
- ? \
- (INT_GET_UNALIGNED_32(pointer)) \
- : \
- (INT_GET_UNALIGNED_32_BE(pointer)) \
- )
-
-#if XFS_BIG_INUMS
-#define DIRINO_GET_ARCH(pointer,arch) \
- ( ((arch) == ARCH_NOCONVERT) \
- ? \
- (INT_GET_UNALIGNED_64(pointer)) \
- : \
- (INT_GET_UNALIGNED_64_BE(pointer)) \
- )
-#else
-/* MACHINE ARCHITECTURE dependent */
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-#define DIRINO_GET_ARCH(pointer,arch) \
- DIRINO4_GET_ARCH((((__u8*)pointer)+4),arch)
-#else
-#define DIRINO_GET_ARCH(pointer,arch) \
- DIRINO4_GET_ARCH(pointer,arch)
-#endif
-#endif
-
-#define DIRINO_COPY_ARCH(from,to,arch) \
- if ((arch) == ARCH_NOCONVERT) { \
- memcpy(to,from,sizeof(xfs_ino_t)); \
- } else { \
- INT_SWAP_UNALIGNED_64(from,to); \
- }
-#define DIRINO4_COPY_ARCH(from,to,arch) \
- if ((arch) == ARCH_NOCONVERT) { \
- memcpy(to,(((__u8*)from+4)),sizeof(xfs_dir2_ino4_t)); \
- } else { \
- INT_SWAP_UNALIGNED_32(from,to); \
- }
-
+/*
+ * In directories inode numbers are stored as unaligned arrays of unsigned
+ * 8bit integers on disk.
+ *
+ * For v1 directories or v2 directories that contain inode numbers that
+ * do not fit into 32bit the array has eight members, but the first member
+ * is always zero:
+ *
+ * |unused|48-55|40-47|32-39|24-31|16-23| 8-15| 0- 7|
+ *
+ * For v2 directories that only contain entries with inode numbers that fit
+ * into 32bits a four-member array is used:
+ *
+ * |24-31|16-23| 8-15| 0- 7|
+ */
+
+#define XFS_GET_DIR_INO4(di) \
+ (((u32)(di).i[0] << 24) | ((di).i[1] << 16) | ((di).i[2] << 8) | ((di).i[3]))
+
+#define XFS_PUT_DIR_INO4(from, di) \
+do { \
+ (di).i[0] = (((from) & 0xff000000ULL) >> 24); \
+ (di).i[1] = (((from) & 0x00ff0000ULL) >> 16); \
+ (di).i[2] = (((from) & 0x0000ff00ULL) >> 8); \
+ (di).i[3] = ((from) & 0x000000ffULL); \
+} while (0)
+
+#define XFS_DI_HI(di) \
+ (((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]))
+
+#define XFS_GET_DIR_INO8(di) \
+ (((xfs_ino_t)XFS_DI_LO(di) & 0xffffffffULL) | \
+ ((xfs_ino_t)XFS_DI_HI(di) << 32))
+
+#define XFS_PUT_DIR_INO8(from, di) \
+do { \
+ (di).i[0] = 0; \
+ (di).i[1] = (((from) & 0x00ff000000000000ULL) >> 48); \
+ (di).i[2] = (((from) & 0x0000ff0000000000ULL) >> 40); \
+ (di).i[3] = (((from) & 0x000000ff00000000ULL) >> 32); \
+ (di).i[4] = (((from) & 0x00000000ff000000ULL) >> 24); \
+ (di).i[5] = (((from) & 0x0000000000ff0000ULL) >> 16); \
+ (di).i[6] = (((from) & 0x000000000000ff00ULL) >> 8); \
+ (di).i[7] = ((from) & 0x00000000000000ffULL); \
+} while (0)
+
#endif /* __XFS_ARCH_H__ */
diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c
index 6cd3b58467b1a..ee8b5904ec7cc 100644
--- a/fs/xfs/xfs_attr.c
+++ b/fs/xfs/xfs_attr.c
@@ -1884,7 +1884,7 @@ xfs_attr_node_list(xfs_attr_list_context_t *context)
return(XFS_ERROR(EFSCORRUPTED));
}
error = xfs_attr_leaf_list_int(bp, context);
- if (error || (INT_ISZERO(leaf->hdr.info.forw, ARCH_CONVERT)))
+ if (error || !leaf->hdr.info.forw)
break; /* not really an error, buffer full or EOF */
cursor->blkno = INT_GET(leaf->hdr.info.forw, ARCH_CONVERT);
xfs_da_brelse(NULL, bp);
diff --git a/fs/xfs/xfs_attr_leaf.c b/fs/xfs/xfs_attr_leaf.c
index 444f341ed5eef..b11256e58bf4f 100644
--- a/fs/xfs/xfs_attr_leaf.c
+++ b/fs/xfs/xfs_attr_leaf.c
@@ -129,7 +129,7 @@ xfs_attr_shortform_create(xfs_da_args_t *args)
}
xfs_idata_realloc(dp, sizeof(*hdr), XFS_ATTR_FORK);
hdr = (xfs_attr_sf_hdr_t *)ifp->if_u1.if_data;
- INT_ZERO(hdr->count, ARCH_CONVERT);
+ hdr->count = 0;
INT_SET(hdr->totsize, ARCH_CONVERT, sizeof(*hdr));
xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_ADATA);
return(0);
@@ -443,7 +443,7 @@ xfs_attr_shortform_list(xfs_attr_list_context_t *context)
ASSERT(dp->i_afp != NULL);
sf = (xfs_attr_shortform_t *)dp->i_afp->if_u1.if_data;
ASSERT(sf != NULL);
- if (INT_ISZERO(sf->hdr.count, ARCH_CONVERT))
+ if (!sf->hdr.count)
return(0);
cursor = context->cursor;
ASSERT(cursor != NULL);
@@ -686,7 +686,7 @@ xfs_attr_leaf_to_shortform(xfs_dabuf_t *bp, xfs_da_args_t *args)
for (i = 0; i < INT_GET(leaf->hdr.count, ARCH_CONVERT); entry++, i++) {
if (entry->flags & XFS_ATTR_INCOMPLETE)
continue; /* don't copy partial entries */
- if (INT_ISZERO(entry->nameidx, ARCH_CONVERT))
+ if (!entry->nameidx)
continue;
ASSERT(entry->flags & XFS_ATTR_LOCAL);
name_loc = XFS_ATTR_LEAF_NAME_LOCAL(leaf, i);
@@ -795,7 +795,7 @@ xfs_attr_leaf_create(xfs_da_args_t *args, xfs_dablk_t blkno, xfs_dabuf_t **bpp)
hdr = &leaf->hdr;
INT_SET(hdr->info.magic, ARCH_CONVERT, XFS_ATTR_LEAF_MAGIC);
INT_SET(hdr->firstused, ARCH_CONVERT, XFS_LBSIZE(dp->i_mount));
- if (INT_ISZERO(hdr->firstused, ARCH_CONVERT)) {
+ if (!hdr->firstused) {
INT_SET(hdr->firstused, ARCH_CONVERT,
XFS_LBSIZE(dp->i_mount) - XFS_ATTR_LEAF_NAME_ALIGN);
}
@@ -898,7 +898,7 @@ xfs_attr_leaf_add(xfs_dabuf_t *bp, xfs_da_args_t *args)
sum += INT_GET(map->size, ARCH_CONVERT);
continue;
}
- if (INT_ISZERO(map->size, ARCH_CONVERT))
+ if (!map->size)
continue; /* no space in this map */
tmp = entsize;
if (INT_GET(map->base, ARCH_CONVERT)
@@ -1031,8 +1031,8 @@ xfs_attr_leaf_add_work(xfs_dabuf_t *bp, xfs_da_args_t *args, int mapindex)
memcpy((char *)name_rmt->name, args->name, args->namelen);
entry->flags |= XFS_ATTR_INCOMPLETE;
/* just in case */
- INT_ZERO(name_rmt->valuelen, ARCH_CONVERT);
- INT_ZERO(name_rmt->valueblk, ARCH_CONVERT);
+ name_rmt->valuelen = 0;
+ name_rmt->valueblk = 0;
args->rmtblkno = 1;
args->rmtblkcnt = XFS_B_TO_FSB(mp, args->valuelen);
}
@@ -1097,12 +1097,12 @@ xfs_attr_leaf_compact(xfs_trans_t *trans, xfs_dabuf_t *bp)
hdr_d->info = hdr_s->info; /* struct copy */
INT_SET(hdr_d->firstused, ARCH_CONVERT, XFS_LBSIZE(mp));
/* handle truncation gracefully */
- if (INT_ISZERO(hdr_d->firstused, ARCH_CONVERT)) {
+ if (!hdr_d->firstused) {
INT_SET(hdr_d->firstused, ARCH_CONVERT,
XFS_LBSIZE(mp) - XFS_ATTR_LEAF_NAME_ALIGN);
}
- INT_ZERO(hdr_d->usedbytes, ARCH_CONVERT);
- INT_ZERO(hdr_d->count, ARCH_CONVERT);
+ hdr_d->usedbytes = 0;
+ hdr_d->count = 0;
hdr_d->holes = 0;
INT_SET(hdr_d->freemap[0].base, ARCH_CONVERT,
sizeof(xfs_attr_leaf_hdr_t));
@@ -1456,7 +1456,7 @@ xfs_attr_leaf_toosmall(xfs_da_state_t *state, int *action)
* Make altpath point to the block we want to keep and
* path point to the block we want to drop (this one).
*/
- forward = (!INT_ISZERO(info->forw, ARCH_CONVERT));
+ forward = info->forw;
memcpy(&state->altpath, &state->path, sizeof(state->path));
error = xfs_da_path_shift(state, &state->altpath, forward,
0, &retval);
@@ -1617,8 +1617,8 @@ xfs_attr_leaf_remove(xfs_dabuf_t *bp, xfs_da_args_t *args)
INT_MOD(map->size, ARCH_CONVERT,
INT_GET(hdr->freemap[after].size,
ARCH_CONVERT));
- INT_ZERO(hdr->freemap[after].base, ARCH_CONVERT);
- INT_ZERO(hdr->freemap[after].size, ARCH_CONVERT);
+ hdr->freemap[after].base = 0;
+ hdr->freemap[after].size = 0;
} else if (before >= 0) {
map = &hdr->freemap[before];
INT_MOD(map->size, ARCH_CONVERT, entsize);
@@ -1686,7 +1686,7 @@ xfs_attr_leaf_remove(xfs_dabuf_t *bp, xfs_da_args_t *args)
tmp = INT_GET(entry->nameidx, ARCH_CONVERT);
}
INT_SET(hdr->firstused, ARCH_CONVERT, tmp);
- if (INT_ISZERO(hdr->firstused, ARCH_CONVERT)) {
+ if (!hdr->firstused) {
INT_SET(hdr->firstused, ARCH_CONVERT,
tmp - XFS_ATTR_LEAF_NAME_ALIGN);
}
@@ -1772,13 +1772,13 @@ xfs_attr_leaf_unbalance(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk,
tmp_leaf = (xfs_attr_leafblock_t *)tmpbuffer;
tmp_hdr = &tmp_leaf->hdr;
tmp_hdr->info = save_hdr->info; /* struct copy */
- INT_ZERO(tmp_hdr->count, ARCH_CONVERT);
+ tmp_hdr->count = 0;
INT_SET(tmp_hdr->firstused, ARCH_CONVERT, state->blocksize);
- if (INT_ISZERO(tmp_hdr->firstused, ARCH_CONVERT)) {
+ if (!tmp_hdr->firstused) {
INT_SET(tmp_hdr->firstused, ARCH_CONVERT,
state->blocksize - XFS_ATTR_LEAF_NAME_ALIGN);
}
- INT_ZERO(tmp_hdr->usedbytes, ARCH_CONVERT);
+ tmp_hdr->usedbytes = 0;
if (xfs_attr_leaf_order(save_blk->bp, drop_blk->bp)) {
xfs_attr_leaf_moveents(drop_leaf, 0, tmp_leaf, 0,
(int)INT_GET(drop_hdr->count, ARCH_CONVERT),
@@ -1860,8 +1860,8 @@ xfs_attr_leaf_lookup_int(xfs_dabuf_t *bp, xfs_da_args_t *args)
else
break;
}
- ASSERT((probe >= 0) && \
- ((INT_ISZERO(leaf->hdr.count, ARCH_CONVERT))
+ ASSERT((probe >= 0) &&
+ (!leaf->hdr.count
|| (probe < INT_GET(leaf->hdr.count, ARCH_CONVERT))));
ASSERT((span <= 4) || (INT_GET(entry->hashval, ARCH_CONVERT)
== hashval));
@@ -2151,10 +2151,10 @@ xfs_attr_leaf_moveents(xfs_attr_leafblock_t *leaf_s, int start_s,
INT_SET(hdr_d->freemap[0].size, ARCH_CONVERT,
INT_GET(hdr_d->firstused, ARCH_CONVERT)
- INT_GET(hdr_d->freemap[0].base, ARCH_CONVERT));
- INT_ZERO(hdr_d->freemap[1].base, ARCH_CONVERT);
- INT_ZERO(hdr_d->freemap[2].base, ARCH_CONVERT);
- INT_ZERO(hdr_d->freemap[1].size, ARCH_CONVERT);
- INT_ZERO(hdr_d->freemap[2].size, ARCH_CONVERT);
+ hdr_d->freemap[1].base = 0;
+ hdr_d->freemap[2].base = 0;
+ hdr_d->freemap[1].size = 0;
+ hdr_d->freemap[2].size = 0;
hdr_s->holes = 1; /* leaf may not be compact */
}
@@ -2199,7 +2199,7 @@ xfs_attr_leaf_lasthash(xfs_dabuf_t *bp, int *count)
== XFS_ATTR_LEAF_MAGIC);
if (count)
*count = INT_GET(leaf->hdr.count, ARCH_CONVERT);
- if (INT_ISZERO(leaf->hdr.count, ARCH_CONVERT))
+ if (!leaf->hdr.count)
return(0);
return(INT_GET(leaf->entries[INT_GET(leaf->hdr.count,
ARCH_CONVERT)-1].hashval, ARCH_CONVERT));
@@ -2543,8 +2543,8 @@ xfs_attr_leaf_setflag(xfs_da_args_t *args)
XFS_DA_LOGRANGE(leaf, entry, sizeof(*entry)));
if ((entry->flags & XFS_ATTR_LOCAL) == 0) {
name_rmt = XFS_ATTR_LEAF_NAME_REMOTE(leaf, args->index);
- INT_ZERO(name_rmt->valueblk, ARCH_CONVERT);
- INT_ZERO(name_rmt->valuelen, ARCH_CONVERT);
+ name_rmt->valueblk = 0;
+ name_rmt->valuelen = 0;
xfs_da_log_buf(args->trans, bp,
XFS_DA_LOGRANGE(leaf, name_rmt, sizeof(*name_rmt)));
}
@@ -2661,8 +2661,8 @@ xfs_attr_leaf_flipflags(xfs_da_args_t *args)
XFS_DA_LOGRANGE(leaf2, entry2, sizeof(*entry2)));
if ((entry2->flags & XFS_ATTR_LOCAL) == 0) {
name_rmt = XFS_ATTR_LEAF_NAME_REMOTE(leaf2, args->index2);
- INT_ZERO(name_rmt->valueblk, ARCH_CONVERT);
- INT_ZERO(name_rmt->valuelen, ARCH_CONVERT);
+ name_rmt->valueblk = 0;
+ name_rmt->valuelen = 0;
xfs_da_log_buf(args->trans, bp2,
XFS_DA_LOGRANGE(leaf2, name_rmt, sizeof(*name_rmt)));
}
@@ -2871,7 +2871,7 @@ xfs_attr_leaf_inactive(xfs_trans_t **trans, xfs_inode_t *dp, xfs_dabuf_t *bp)
if ( INT_GET(entry->nameidx, ARCH_CONVERT)
&& ((entry->flags & XFS_ATTR_LOCAL) == 0)) {
name_rmt = XFS_ATTR_LEAF_NAME_REMOTE(leaf, i);
- if (!INT_ISZERO(name_rmt->valueblk, ARCH_CONVERT))
+ if (name_rmt->valueblk)
count++;
}
}
@@ -2899,7 +2899,7 @@ xfs_attr_leaf_inactive(xfs_trans_t **trans, xfs_inode_t *dp, xfs_dabuf_t *bp)
if ( INT_GET(entry->nameidx, ARCH_CONVERT)
&& ((entry->flags & XFS_ATTR_LOCAL) == 0)) {
name_rmt = XFS_ATTR_LEAF_NAME_REMOTE(leaf, i);
- if (!INT_ISZERO(name_rmt->valueblk, ARCH_CONVERT)) {
+ if (name_rmt->valueblk) {
/* both on-disk, don't endian flip twice */
lp->valueblk = name_rmt->valueblk;
INT_SET(lp->valuelen, ARCH_CONVERT,
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c
index 4b0738238809c..de31624186630 100644
--- a/fs/xfs/xfs_bmap.c
+++ b/fs/xfs/xfs_bmap.c
@@ -3261,7 +3261,7 @@ xfs_bmap_extents_to_btree(
*/
ablock = XFS_BUF_TO_BMBT_BLOCK(abp);
INT_SET(ablock->bb_magic, ARCH_CONVERT, XFS_BMAP_MAGIC);
- INT_ZERO(ablock->bb_level, ARCH_CONVERT);
+ ablock->bb_level = 0;
INT_SET(ablock->bb_leftsib, ARCH_CONVERT, NULLDFSBNO);
INT_SET(ablock->bb_rightsib, ARCH_CONVERT, NULLDFSBNO);
arp = XFS_BMAP_REC_IADDR(ablock, 1, cur);
diff --git a/fs/xfs/xfs_bmap_btree.c b/fs/xfs/xfs_bmap_btree.c
index 0ed189102257d..163305a79fcc5 100644
--- a/fs/xfs/xfs_bmap_btree.c
+++ b/fs/xfs/xfs_bmap_btree.c
@@ -2017,7 +2017,7 @@ xfs_bmbt_get_state(
ext_flag);
}
-#if ARCH_CONVERT != ARCH_NOCONVERT
+#if __BYTE_ORDER != __BIG_ENDIAN
/* Endian flipping versions of the bmbt extraction functions */
void
xfs_bmbt_disk_get_all(
@@ -2545,7 +2545,7 @@ xfs_bmbt_set_allf(
#endif /* XFS_BIG_BLKNOS */
}
-#if ARCH_CONVERT != ARCH_NOCONVERT
+#if __BYTE_ORDER != __BIG_ENDIAN
/*
* Set all the fields in a bmap extent record from the uncompressed form.
*/
diff --git a/fs/xfs/xfs_bmap_btree.h b/fs/xfs/xfs_bmap_btree.h
index 1c0904d0857bf..843ff12b4bf22 100644
--- a/fs/xfs/xfs_bmap_btree.h
+++ b/fs/xfs/xfs_bmap_btree.h
@@ -505,7 +505,7 @@ xfs_exntst_t
xfs_bmbt_get_state(
xfs_bmbt_rec_t *r);
-#if ARCH_CONVERT != ARCH_NOCONVERT
+#if __BYTE_ORDER != __BIG_ENDIAN
void
xfs_bmbt_disk_get_all(
xfs_bmbt_rec_t *r,
@@ -631,7 +631,7 @@ xfs_bmbt_set_state(
xfs_bmbt_rec_t *r,
xfs_exntst_t v);
-#if ARCH_CONVERT != ARCH_NOCONVERT
+#if __BYTE_ORDER != __BIG_ENDIAN
void
xfs_bmbt_disk_set_all(
xfs_bmbt_rec_t *r,
diff --git a/fs/xfs/xfs_btree.c b/fs/xfs/xfs_btree.c
index 099e26aae2a1f..9dd22dd95487d 100644
--- a/fs/xfs/xfs_btree.c
+++ b/fs/xfs/xfs_btree.c
@@ -208,10 +208,10 @@ xfs_btree_check_lblock(
INT_GET(block->bb_level, ARCH_CONVERT) == level &&
INT_GET(block->bb_numrecs, ARCH_CONVERT) <=
xfs_btree_maxrecs(cur, (xfs_btree_block_t *)block) &&
- !INT_ISZERO(block->bb_leftsib, ARCH_CONVERT) &&
+ block->bb_leftsib &&
(INT_GET(block->bb_leftsib, ARCH_CONVERT) == NULLDFSBNO ||
XFS_FSB_SANITY_CHECK(mp, INT_GET(block->bb_leftsib, ARCH_CONVERT))) &&
- !INT_ISZERO(block->bb_rightsib, ARCH_CONVERT) &&
+ block->bb_rightsib &&
(INT_GET(block->bb_rightsib, ARCH_CONVERT) == NULLDFSBNO ||
XFS_FSB_SANITY_CHECK(mp, INT_GET(block->bb_rightsib, ARCH_CONVERT)));
if (unlikely(XFS_TEST_ERROR(!lblock_ok, mp, XFS_ERRTAG_BTREE_CHECK_LBLOCK,
@@ -329,10 +329,10 @@ xfs_btree_check_sblock(
xfs_btree_maxrecs(cur, (xfs_btree_block_t *)block) &&
(INT_GET(block->bb_leftsib, ARCH_CONVERT) == NULLAGBLOCK ||
INT_GET(block->bb_leftsib, ARCH_CONVERT) < agflen) &&
- !INT_ISZERO(block->bb_leftsib, ARCH_CONVERT) &&
+ block->bb_leftsib &&
(INT_GET(block->bb_rightsib, ARCH_CONVERT) == NULLAGBLOCK ||
INT_GET(block->bb_rightsib, ARCH_CONVERT) < agflen) &&
- !INT_ISZERO(block->bb_rightsib, ARCH_CONVERT);
+ block->bb_rightsib;
if (unlikely(XFS_TEST_ERROR(!sblock_ok, cur->bc_mp,
XFS_ERRTAG_BTREE_CHECK_SBLOCK,
XFS_RANDOM_BTREE_CHECK_SBLOCK))) {
@@ -484,7 +484,7 @@ xfs_btree_firstrec(
/*
* It's empty, there is no such record.
*/
- if (INT_ISZERO(block->bb_h.bb_numrecs, ARCH_CONVERT))
+ if (!block->bb_h.bb_numrecs)
return 0;
/*
* Set the ptr value to 1, that's the first record/key.
@@ -698,7 +698,7 @@ xfs_btree_lastrec(
/*
* It's empty, there is no such record.
*/
- if (INT_ISZERO(block->bb_h.bb_numrecs, ARCH_CONVERT))
+ if (!block->bb_h.bb_numrecs)
return 0;
/*
* Set the ptr value to numrecs, that's the last record/key.
diff --git a/fs/xfs/xfs_clnt.h b/fs/xfs/xfs_clnt.h
index 795a11e2dbe97..b3215ffe0be86 100644
--- a/fs/xfs/xfs_clnt.h
+++ b/fs/xfs/xfs_clnt.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000-2004 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
@@ -103,5 +103,8 @@ struct xfs_mount_args {
#define XFSMNT_IDELETE 0x08000000 /* inode cluster delete */
#define XFSMNT_SWALLOC 0x10000000 /* turn on stripe width
* allocation */
+#define XFSMNT_IHASHSIZE 0x20000000 /* inode hash table size */
+#define XFSMNT_DIRSYNC 0x40000000 /* sync creat,link,unlink,rename
+ * symlink,mkdir,rmdir,mknod */
#endif /* __XFS_CLNT_H__ */
diff --git a/fs/xfs/xfs_da_btree.c b/fs/xfs/xfs_da_btree.c
index bbe00dc550d65..d7fe288667644 100644
--- a/fs/xfs/xfs_da_btree.c
+++ b/fs/xfs/xfs_da_btree.c
@@ -137,11 +137,11 @@ xfs_da_node_create(xfs_da_args_t *args, xfs_dablk_t blkno, int level,
return(error);
ASSERT(bp != NULL);
node = bp->data;
- INT_ZERO(node->hdr.info.forw, ARCH_CONVERT);
- INT_ZERO(node->hdr.info.back, ARCH_CONVERT);
+ node->hdr.info.forw = 0;
+ node->hdr.info.back = 0;
INT_SET(node->hdr.info.magic, ARCH_CONVERT, XFS_DA_NODE_MAGIC);
- INT_ZERO(node->hdr.info.pad, ARCH_CONVERT);
- INT_ZERO(node->hdr.count, ARCH_CONVERT);
+ node->hdr.info.pad = 0;
+ node->hdr.count = 0;
INT_SET(node->hdr.level, ARCH_CONVERT, level);
xfs_da_log_buf(tp, bp,
@@ -306,7 +306,7 @@ xfs_da_split(xfs_da_state_t *state)
*/
node = oldblk->bp->data;
- if (!INT_ISZERO(node->hdr.info.forw, ARCH_CONVERT)) {
+ if (node->hdr.info.forw) {
if (INT_GET(node->hdr.info.forw, ARCH_CONVERT) == addblk->blkno) {
bp = addblk->bp;
} else {
@@ -791,8 +791,8 @@ xfs_da_root_join(xfs_da_state_t *state, xfs_da_state_blk_t *root_blk)
ASSERT(root_blk->magic == XFS_DA_NODE_MAGIC);
oldroot = root_blk->bp->data;
ASSERT(INT_GET(oldroot->hdr.info.magic, ARCH_CONVERT) == XFS_DA_NODE_MAGIC);
- ASSERT(INT_ISZERO(oldroot->hdr.info.forw, ARCH_CONVERT));
- ASSERT(INT_ISZERO(oldroot->hdr.info.back, ARCH_CONVERT));
+ ASSERT(!oldroot->hdr.info.forw);
+ ASSERT(!oldroot->hdr.info.back);
/*
* If the root has more than one child, then don't do anything.
@@ -818,8 +818,8 @@ xfs_da_root_join(xfs_da_state_t *state, xfs_da_state_blk_t *root_blk)
} else {
ASSERT(INT_GET(blkinfo->magic, ARCH_CONVERT) == XFS_DA_NODE_MAGIC);
}
- ASSERT(INT_ISZERO(blkinfo->forw, ARCH_CONVERT));
- ASSERT(INT_ISZERO(blkinfo->back, ARCH_CONVERT));
+ ASSERT(!blkinfo->forw);
+ ASSERT(!blkinfo->back);
memcpy(root_blk->bp->data, bp->data, state->blocksize);
xfs_da_log_buf(args->trans, root_blk->bp, 0, state->blocksize - 1);
error = xfs_da_shrink_inode(args, child, bp);
@@ -871,7 +871,7 @@ xfs_da_node_toosmall(xfs_da_state_t *state, int *action)
* Make altpath point to the block we want to keep and
* path point to the block we want to drop (this one).
*/
- forward = (!INT_ISZERO(info->forw, ARCH_CONVERT));
+ forward = info->forw;
memcpy(&state->altpath, &state->path, sizeof(state->path));
error = xfs_da_path_shift(state, &state->altpath, forward,
0, &retval);
@@ -1416,7 +1416,7 @@ xfs_da_node_lasthash(xfs_dabuf_t *bp, int *count)
ASSERT(INT_GET(node->hdr.info.magic, ARCH_CONVERT) == XFS_DA_NODE_MAGIC);
if (count)
*count = INT_GET(node->hdr.count, ARCH_CONVERT);
- if (INT_ISZERO(node->hdr.count, ARCH_CONVERT))
+ if (!node->hdr.count)
return(0);
return(INT_GET(node->btree[ INT_GET(node->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT));
}
@@ -1627,40 +1627,38 @@ xfs_da_hashname(uchar_t *name, int namelen)
{
xfs_dahash_t hash;
-#define ROTL(x,y) (((x) << (y)) | ((x) >> (32 - (y))))
#ifdef SLOWVERSION
/*
* This is the old one-byte-at-a-time version.
*/
- for (hash = 0; namelen > 0; namelen--) {
- hash = *name++ ^ ROTL(hash, 7);
- }
+ for (hash = 0; namelen > 0; namelen--)
+ hash = *name++ ^ rol32(hash, 7);
+
return(hash);
#else
/*
* Do four characters at a time as long as we can.
*/
- for (hash = 0; namelen >= 4; namelen -= 4, name += 4) {
+ for (hash = 0; namelen >= 4; namelen -= 4, name += 4)
hash = (name[0] << 21) ^ (name[1] << 14) ^ (name[2] << 7) ^
- (name[3] << 0) ^ ROTL(hash, 7 * 4);
- }
+ (name[3] << 0) ^ rol32(hash, 7 * 4);
+
/*
* Now do the rest of the characters.
*/
switch (namelen) {
case 3:
return (name[0] << 14) ^ (name[1] << 7) ^ (name[2] << 0) ^
- ROTL(hash, 7 * 3);
+ rol32(hash, 7 * 3);
case 2:
- return (name[0] << 7) ^ (name[1] << 0) ^ ROTL(hash, 7 * 2);
+ return (name[0] << 7) ^ (name[1] << 0) ^ rol32(hash, 7 * 2);
case 1:
- return (name[0] << 0) ^ ROTL(hash, 7 * 1);
+ return (name[0] << 0) ^ rol32(hash, 7 * 1);
case 0:
return hash;
}
/* NOTREACHED */
#endif
-#undef ROTL
return 0; /* keep gcc happy */
}
diff --git a/fs/xfs/xfs_dinode.h b/fs/xfs/xfs_dinode.h
index d395f783833a1..f5c932b064e6c 100644
--- a/fs/xfs/xfs_dinode.h
+++ b/fs/xfs/xfs_dinode.h
@@ -204,58 +204,59 @@ int xfs_litino(struct xfs_mount *mp);
* Inode data & attribute fork sizes, per inode.
*/
#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_CFORK_Q)
-int xfs_cfork_q_arch(xfs_dinode_core_t *dcp, xfs_arch_t arch);
+int xfs_cfork_q_disk(xfs_dinode_core_t *dcp);
int xfs_cfork_q(xfs_dinode_core_t *dcp);
-#define XFS_CFORK_Q_ARCH(dcp,arch) xfs_cfork_q_arch(dcp,arch)
+#define XFS_CFORK_Q_DISK(dcp) xfs_cfork_q_disk(dcp)
#define XFS_CFORK_Q(dcp) xfs_cfork_q(dcp)
#else
-#define XFS_CFORK_Q_ARCH(dcp,arch) (!INT_ISZERO((dcp)->di_forkoff, arch))
+#define XFS_CFORK_Q_DISK(dcp) ((dcp)->di_forkoff != 0)
#define XFS_CFORK_Q(dcp) ((dcp)->di_forkoff != 0)
#endif
#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_CFORK_BOFF)
-int xfs_cfork_boff_arch(xfs_dinode_core_t *dcp, xfs_arch_t arch);
+int xfs_cfork_boff_disk(xfs_dinode_core_t *dcp);
int xfs_cfork_boff(xfs_dinode_core_t *dcp);
-#define XFS_CFORK_BOFF_ARCH(dcp,arch) xfs_cfork_boff_arch(dcp,arch)
+#define XFS_CFORK_BOFF_DISK(dcp) xfs_cfork_boff_disk(dcp)
#define XFS_CFORK_BOFF(dcp) xfs_cfork_boff(dcp)
#else
-#define XFS_CFORK_BOFF_ARCH(dcp,arch) ((int)(INT_GET((dcp)->di_forkoff, arch) << 3))
+#define XFS_CFORK_BOFF_DISK(dcp) ((int)(INT_GET((dcp)->di_forkoff, ARCH_CONVERT) << 3))
#define XFS_CFORK_BOFF(dcp) ((int)((dcp)->di_forkoff << 3))
#endif
#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_CFORK_DSIZE)
-int xfs_cfork_dsize_arch(xfs_dinode_core_t *dcp, struct xfs_mount *mp, xfs_arch_t arch);
+int xfs_cfork_dsize_disk(xfs_dinode_core_t *dcp, struct xfs_mount *mp);
int xfs_cfork_dsize(xfs_dinode_core_t *dcp, struct xfs_mount *mp);
-#define XFS_CFORK_DSIZE_ARCH(dcp,mp,arch) xfs_cfork_dsize_arch(dcp,mp,arch)
+#define XFS_CFORK_DSIZE_DISK(dcp,mp) xfs_cfork_dsize_disk(dcp,mp)
#define XFS_CFORK_DSIZE(dcp,mp) xfs_cfork_dsize(dcp,mp)
#else
-#define XFS_CFORK_DSIZE_ARCH(dcp,mp,arch) \
- (XFS_CFORK_Q_ARCH(dcp, arch) ? XFS_CFORK_BOFF_ARCH(dcp, arch) : XFS_LITINO(mp))
+#define XFS_CFORK_DSIZE_DISK(dcp,mp) \
+ (XFS_CFORK_Q_DISK(dcp) ? XFS_CFORK_BOFF_DISK(dcp) : XFS_LITINO(mp))
#define XFS_CFORK_DSIZE(dcp,mp) \
(XFS_CFORK_Q(dcp) ? XFS_CFORK_BOFF(dcp) : XFS_LITINO(mp))
#endif
#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_CFORK_ASIZE)
-int xfs_cfork_asize_arch(xfs_dinode_core_t *dcp, struct xfs_mount *mp, xfs_arch_t arch);
+int xfs_cfork_asize_disk(xfs_dinode_core_t *dcp, struct xfs_mount *mp);
int xfs_cfork_asize(xfs_dinode_core_t *dcp, struct xfs_mount *mp);
-#define XFS_CFORK_ASIZE_ARCH(dcp,mp,arch) xfs_cfork_asize_arch(dcp,mp,arch)
+#define XFS_CFORK_ASIZE_DISK(dcp,mp) xfs_cfork_asize_disk(dcp,mp)
#define XFS_CFORK_ASIZE(dcp,mp) xfs_cfork_asize(dcp,mp)
#else
-#define XFS_CFORK_ASIZE_ARCH(dcp,mp,arch) \
- (XFS_CFORK_Q_ARCH(dcp, arch) ? XFS_LITINO(mp) - XFS_CFORK_BOFF_ARCH(dcp, arch) : 0)
+#define XFS_CFORK_ASIZE_DISK(dcp,mp) \
+ (XFS_CFORK_Q_DISK(dcp) ? XFS_LITINO(mp) - XFS_CFORK_BOFF_DISK(dcp) : 0)
#define XFS_CFORK_ASIZE(dcp,mp) \
(XFS_CFORK_Q(dcp) ? XFS_LITINO(mp) - XFS_CFORK_BOFF(dcp) : 0)
#endif
#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_CFORK_SIZE)
-int xfs_cfork_size_arch(xfs_dinode_core_t *dcp, struct xfs_mount *mp, int w, xfs_arch_t arch);
+int xfs_cfork_size_disk(xfs_dinode_core_t *dcp, struct xfs_mount *mp, int w);
int xfs_cfork_size(xfs_dinode_core_t *dcp, struct xfs_mount *mp, int w);
-#define XFS_CFORK_SIZE_ARCH(dcp,mp,w,arch) xfs_cfork_size_arch(dcp,mp,w,arch)
+#define XFS_CFORK_SIZE_DISK(dcp,mp,w) xfs_cfork_size_disk(dcp,mp,w)
#define XFS_CFORK_SIZE(dcp,mp,w) xfs_cfork_size(dcp,mp,w)
#else
-#define XFS_CFORK_SIZE_ARCH(dcp,mp,w,arch) \
+#define XFS_CFORK_SIZE_DISK(dcp,mp,w) \
((w) == XFS_DATA_FORK ? \
- XFS_CFORK_DSIZE_ARCH(dcp, mp, arch) : XFS_CFORK_ASIZE_ARCH(dcp, mp, arch))
+ XFS_CFORK_DSIZE_DISK(dcp, mp) : \
+ XFS_CFORK_ASIZE_DISK(dcp, mp))
#define XFS_CFORK_SIZE(dcp,mp,w) \
((w) == XFS_DATA_FORK ? \
XFS_CFORK_DSIZE(dcp, mp) : XFS_CFORK_ASIZE(dcp, mp))
@@ -263,33 +264,24 @@ int xfs_cfork_size(xfs_dinode_core_t *dcp, struct xfs_mount *mp, int w);
#endif
#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_DFORK_DSIZE)
-int xfs_dfork_dsize_arch(xfs_dinode_t *dip, struct xfs_mount *mp, xfs_arch_t arch);
int xfs_dfork_dsize(xfs_dinode_t *dip, struct xfs_mount *mp);
-#define XFS_DFORK_DSIZE_ARCH(dip,mp,arch) xfs_dfork_dsize_arch(dip,mp,arch)
#define XFS_DFORK_DSIZE(dip,mp) xfs_dfork_dsize(dip,mp)
#else
-#define XFS_DFORK_DSIZE_ARCH(dip,mp,arch) XFS_CFORK_DSIZE_ARCH(&(dip)->di_core, mp, arch)
-#define XFS_DFORK_DSIZE(dip,mp) XFS_DFORK_DSIZE_ARCH(dip,mp,ARCH_NOCONVERT)
+#define XFS_DFORK_DSIZE(dip,mp) XFS_CFORK_DSIZE_DISK(&(dip)->di_core, mp)
#endif
#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_DFORK_ASIZE)
-int xfs_dfork_asize_arch(xfs_dinode_t *dip, struct xfs_mount *mp, xfs_arch_t arch);
int xfs_dfork_asize(xfs_dinode_t *dip, struct xfs_mount *mp);
-#define XFS_DFORK_ASIZE_ARCH(dip,mp,arch) xfs_dfork_asize_arch(dip,mp,arch)
#define XFS_DFORK_ASIZE(dip,mp) xfs_dfork_asize(dip,mp)
#else
-#define XFS_DFORK_ASIZE_ARCH(dip,mp,arch) XFS_CFORK_ASIZE_ARCH(&(dip)->di_core, mp, arch)
-#define XFS_DFORK_ASIZE(dip,mp) XFS_DFORK_ASIZE_ARCH(dip,mp,ARCH_NOCONVERT)
+#define XFS_DFORK_ASIZE(dip,mp) XFS_CFORK_ASIZE_DISK(&(dip)->di_core, mp)
#endif
#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_DFORK_SIZE)
-int xfs_dfork_size_arch(xfs_dinode_t *dip, struct xfs_mount *mp, int w, xfs_arch_t arch);
int xfs_dfork_size(xfs_dinode_t *dip, struct xfs_mount *mp, int w);
-#define XFS_DFORK_SIZE_ARCH(dip,mp,w,arch) xfs_dfork_size_arch(dip,mp,w,arch)
#define XFS_DFORK_SIZE(dip,mp,w) xfs_dfork_size(dip,mp,w)
#else
-#define XFS_DFORK_SIZE_ARCH(dip,mp,w,arch) XFS_CFORK_SIZE_ARCH(&(dip)->di_core, mp, w, arch)
-#define XFS_DFORK_SIZE(dip,mp,w) XFS_DFORK_SIZE_ARCH(dip,mp,w,ARCH_NOCONVERT)
+#define XFS_DFORK_SIZE(dip,mp,w) XFS_CFORK_SIZE_DISK(&(dip)->di_core, mp, w)
#endif
@@ -297,143 +289,89 @@ int xfs_dfork_size(xfs_dinode_t *dip, struct xfs_mount *mp, int w);
* Macros for accessing per-fork disk inode information.
*/
#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_DFORK_Q)
-int xfs_dfork_q_arch(xfs_dinode_t *dip, xfs_arch_t arch);
int xfs_dfork_q(xfs_dinode_t *dip);
-#define XFS_DFORK_Q_ARCH(dip,arch) xfs_dfork_q_arch(dip,arch)
#define XFS_DFORK_Q(dip) xfs_dfork_q(dip)
#else
-#define XFS_DFORK_Q_ARCH(dip,arch) XFS_CFORK_Q_ARCH(&(dip)->di_core, arch)
-#define XFS_DFORK_Q(dip) XFS_DFORK_Q_ARCH(dip,ARCH_NOCONVERT)
+#define XFS_DFORK_Q(dip) XFS_CFORK_Q_DISK(&(dip)->di_core)
#endif
#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_DFORK_BOFF)
-int xfs_dfork_boff_arch(xfs_dinode_t *dip, xfs_arch_t arch);
int xfs_dfork_boff(xfs_dinode_t *dip);
-#define XFS_DFORK_BOFF_ARCH(dip,arch) xfs_dfork_boff_arch(dip,arch)
-#define XFS_DFORK_BOFF(dip) xfs_dfork_boff(dip)
+#define XFS_DFORK_BOFF(dip) xfs_dfork_boff(dip)
#else
-#define XFS_DFORK_BOFF_ARCH(dip,arch) XFS_CFORK_BOFF_ARCH(&(dip)->di_core, arch)
-#define XFS_DFORK_BOFF(dip) XFS_DFORK_BOFF_ARCH(dip,ARCH_NOCONVERT)
+#define XFS_DFORK_BOFF(dip) XFS_CFORK_BOFF_DISK(&(dip)->di_core)
#endif
#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_DFORK_DPTR)
-char *xfs_dfork_dptr_arch(xfs_dinode_t *dip, xfs_arch_t arch);
char *xfs_dfork_dptr(xfs_dinode_t *dip);
-#define XFS_DFORK_DPTR_ARCH(dip,arch) xfs_dfork_dptr_arch(dip,arch)
#define XFS_DFORK_DPTR(dip) xfs_dfork_dptr(dip)
#else
-#define XFS_DFORK_DPTR_ARCH(dip,arch) ((dip)->di_u.di_c)
-#define XFS_DFORK_DPTR(dip) XFS_DFORK_DPTR_ARCH(dip,ARCH_NOCONVERT)
+#define XFS_DFORK_DPTR(dip) ((dip)->di_u.di_c)
#endif
#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_DFORK_APTR)
-char *xfs_dfork_aptr_arch(xfs_dinode_t *dip, xfs_arch_t arch);
char *xfs_dfork_aptr(xfs_dinode_t *dip);
-#define XFS_DFORK_APTR_ARCH(dip,arch) xfs_dfork_aptr_arch(dip,arch)
#define XFS_DFORK_APTR(dip) xfs_dfork_aptr(dip)
#else
-#define XFS_DFORK_APTR_ARCH(dip,arch) ((dip)->di_u.di_c + XFS_DFORK_BOFF_ARCH(dip, arch))
-#define XFS_DFORK_APTR(dip) XFS_DFORK_APTR_ARCH(dip,ARCH_NOCONVERT)
+#define XFS_DFORK_APTR(dip) ((dip)->di_u.di_c + XFS_DFORK_BOFF(dip))
#endif
#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_DFORK_PTR)
-char *xfs_dfork_ptr_arch(xfs_dinode_t *dip, int w, xfs_arch_t arch);
char *xfs_dfork_ptr(xfs_dinode_t *dip, int w);
-#define XFS_DFORK_PTR_ARCH(dip,w,arch) xfs_dfork_ptr_arch(dip,w,arch)
#define XFS_DFORK_PTR(dip,w) xfs_dfork_ptr(dip,w)
#else
-#define XFS_DFORK_PTR_ARCH(dip,w,arch) \
- ((w) == XFS_DATA_FORK ? XFS_DFORK_DPTR_ARCH(dip, arch) : XFS_DFORK_APTR_ARCH(dip, arch))
-#define XFS_DFORK_PTR(dip,w) XFS_DFORK_PTR_ARCH(dip,w,ARCH_NOCONVERT)
+#define XFS_DFORK_PTR(dip,w) \
+ ((w) == XFS_DATA_FORK ? XFS_DFORK_DPTR(dip) : XFS_DFORK_APTR(dip))
#endif
#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_CFORK_FORMAT)
-int xfs_cfork_format_arch(xfs_dinode_core_t *dcp, int w, xfs_arch_t arch);
int xfs_cfork_format(xfs_dinode_core_t *dcp, int w);
-#define XFS_CFORK_FORMAT_ARCH(dcp,w,arch) xfs_cfork_format_arch(dcp,w,arch)
#define XFS_CFORK_FORMAT(dcp,w) xfs_cfork_format(dcp,w)
#else
-#define XFS_CFORK_FORMAT_ARCH(dcp,w,arch) \
- ((w) == XFS_DATA_FORK ? INT_GET((dcp)->di_format, arch) : INT_GET((dcp)->di_aformat, arch))
-#define XFS_CFORK_FORMAT(dcp,w) XFS_CFORK_FORMAT_ARCH(dcp,w,ARCH_NOCONVERT)
+#define XFS_CFORK_FORMAT(dcp,w) \
+ ((w) == XFS_DATA_FORK ? (dcp)->di_format : (dcp)->di_aformat)
#endif
#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_CFORK_FMT_SET)
-void xfs_cfork_fmt_set_arch(xfs_dinode_core_t *dcp, int w, int n, xfs_arch_t arch);
void xfs_cfork_fmt_set(xfs_dinode_core_t *dcp, int w, int n);
-#define XFS_CFORK_FMT_SET_ARCH(dcp,w,n,arch) xfs_cfork_fmt_set_arch(dcp,w,n,arch)
#define XFS_CFORK_FMT_SET(dcp,w,n) xfs_cfork_fmt_set(dcp,w,n)
#else
-#define XFS_CFORK_FMT_SET_ARCH(dcp,w,n,arch) \
+#define XFS_CFORK_FMT_SET(dcp,w,n) \
((w) == XFS_DATA_FORK ? \
- (INT_SET((dcp)->di_format, arch, (n))) : \
- (INT_SET((dcp)->di_aformat, arch, (n))))
-#define XFS_CFORK_FMT_SET(dcp,w,n) XFS_CFORK_FMT_SET_ARCH(dcp,w,n,ARCH_NOCONVERT)
+ ((dcp)->di_format = (n)) : \
+ ((dcp)->di_aformat = (n)))
#endif
#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_CFORK_NEXTENTS)
-int xfs_cfork_nextents_arch(xfs_dinode_core_t *dcp, int w, xfs_arch_t arch);
+int xfs_cfork_nextents_disk(xfs_dinode_core_t *dcp, int w);
int xfs_cfork_nextents(xfs_dinode_core_t *dcp, int w);
-#define XFS_CFORK_NEXTENTS_ARCH(dcp,w,arch) xfs_cfork_nextents_arch(dcp,w,arch)
+#define XFS_CFORK_NEXTENTS_DISK(dcp,w) xfs_cfork_nextents_disk(dcp,w)
#define XFS_CFORK_NEXTENTS(dcp,w) xfs_cfork_nextents(dcp,w)
#else
-#define XFS_CFORK_NEXTENTS_ARCH(dcp,w,arch) \
- ((w) == XFS_DATA_FORK ? INT_GET((dcp)->di_nextents, arch) : INT_GET((dcp)->di_anextents, arch))
-#define XFS_CFORK_NEXTENTS(dcp,w) XFS_CFORK_NEXTENTS_ARCH(dcp,w,ARCH_NOCONVERT)
+#define XFS_CFORK_NEXTENTS_DISK(dcp,w) \
+ ((w) == XFS_DATA_FORK ? \
+ INT_GET((dcp)->di_nextents, ARCH_CONVERT) : \
+ INT_GET((dcp)->di_anextents, ARCH_CONVERT))
+#define XFS_CFORK_NEXTENTS(dcp,w) \
+ ((w) == XFS_DATA_FORK ? (dcp)->di_nextents : (dcp)->di_anextents)
#endif
#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_CFORK_NEXT_SET)
-void xfs_cfork_next_set_arch(xfs_dinode_core_t *dcp, int w, int n, xfs_arch_t arch);
void xfs_cfork_next_set(xfs_dinode_core_t *dcp, int w, int n);
-#define XFS_CFORK_NEXT_SET_ARCH(dcp,w,n,arch) xfs_cfork_next_set_arch(dcp,w,n,arch)
#define XFS_CFORK_NEXT_SET(dcp,w,n) xfs_cfork_next_set(dcp,w,n)
#else
-#define XFS_CFORK_NEXT_SET_ARCH(dcp,w,n,arch) \
+#define XFS_CFORK_NEXT_SET(dcp,w,n) \
((w) == XFS_DATA_FORK ? \
- (INT_SET((dcp)->di_nextents, arch, (n))) : \
- (INT_SET((dcp)->di_anextents, arch, (n))))
-#define XFS_CFORK_NEXT_SET(dcp,w,n) XFS_CFORK_NEXT_SET_ARCH(dcp,w,n,ARCH_NOCONVERT)
+ ((dcp)->di_nextents = (n)) : \
+ ((dcp)->di_anextents = (n)))
#endif
-#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_DFORK_FORMAT)
-int xfs_dfork_format_arch(xfs_dinode_t *dip, int w, xfs_arch_t arch);
-int xfs_dfork_format(xfs_dinode_t *dip, int w);
-#define XFS_DFORK_FORMAT_ARCH(dip,w,arch) xfs_dfork_format_arch(dip,w,arch)
-#define XFS_DFORK_FORMAT(dip,w) xfs_dfork_format(dip,w)
-#else
-#define XFS_DFORK_FORMAT_ARCH(dip,w,arch) XFS_CFORK_FORMAT_ARCH(&(dip)->di_core, w, arch)
-#define XFS_DFORK_FORMAT(dip,w) XFS_DFORK_FORMAT_ARCH(dip,w,ARCH_NOCONVERT)
-
-#endif
-#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_DFORK_FMT_SET)
-void xfs_dfork_fmt_set_arch(xfs_dinode_t *dip, int w, int n, xfs_arch_t arch);
-void xfs_dfork_fmt_set(xfs_dinode_t *dip, int w, int n);
-#define XFS_DFORK_FMT_SET_ARCH(dip,w,n,arch) xfs_dfork_fmt_set_arch(dip,w,n,arch)
-#define XFS_DFORK_FMT_SET(dip,w,n) xfs_dfork_fmt_set(dip,w,n)
-#else
-#define XFS_DFORK_FMT_SET_ARCH(dip,w,n,arch) XFS_CFORK_FMT_SET_ARCH(&(dip)->di_core, w, n, arch)
-#define XFS_DFORK_FMT_SET(dip,w,n) XFS_DFORK_FMT_SET_ARCH(dip,w,n,ARCH_NOCONVERT)
-#endif
#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_DFORK_NEXTENTS)
-int xfs_dfork_nextents_arch(xfs_dinode_t *dip, int w, xfs_arch_t arch);
int xfs_dfork_nextents(xfs_dinode_t *dip, int w);
-#define XFS_DFORK_NEXTENTS_ARCH(dip,w,arch) xfs_dfork_nextents_arch(dip,w,arch)
-#define XFS_DFORK_NEXTENTS(dip,w) xfs_dfork_nextents(dip,w)
+#define XFS_DFORK_NEXTENTS(dip,w) xfs_dfork_nextents(dip,w)
#else
-#define XFS_DFORK_NEXTENTS_ARCH(dip,w,arch) XFS_CFORK_NEXTENTS_ARCH(&(dip)->di_core, w, arch)
-#define XFS_DFORK_NEXTENTS(dip,w) XFS_DFORK_NEXTENTS_ARCH(dip,w,ARCH_NOCONVERT)
-
-#endif
-#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_DFORK_NEXT_SET)
-void xfs_dfork_next_set_arch(xfs_dinode_t *dip, int w, int n, xfs_arch_t arch);
-void xfs_dfork_next_set(xfs_dinode_t *dip, int w, int n);
-#define XFS_DFORK_NEXT_SET_ARCH(dip,w,n,arch) xfs_dfork_next_set_arch(dip,w,n,arch)
-#define XFS_DFORK_NEXT_SET(dip,w,n) xfs_dfork_next_set(dip,w,n)
-#else
-#define XFS_DFORK_NEXT_SET_ARCH(dip,w,n,arch) XFS_CFORK_NEXT_SET_ARCH(&(dip)->di_core, w, n, arch)
-#define XFS_DFORK_NEXT_SET(dip,w,n) XFS_DFORK_NEXT_SET_ARCH(dip,w,n,ARCH_NOCONVERT)
-
+#define XFS_DFORK_NEXTENTS(dip,w) XFS_CFORK_NEXTENTS_DISK(&(dip)->di_core, w)
#endif
#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_BUF_TO_DINODE)
diff --git a/fs/xfs/xfs_dir.c b/fs/xfs/xfs_dir.c
index 3ea04f9ac2310..ba30bc7682f2f 100644
--- a/fs/xfs/xfs_dir.c
+++ b/fs/xfs/xfs_dir.c
@@ -557,7 +557,7 @@ xfs_dir_shortform_validate_ondisk(xfs_mount_t *mp, xfs_dinode_t *dp)
return 1;
}
sf = (xfs_dir_shortform_t *)(&dp->di_u.di_dirsf);
- ino = XFS_GET_DIR_INO_ARCH(mp, sf->hdr.parent, ARCH_CONVERT);
+ ino = XFS_GET_DIR_INO8(sf->hdr.parent);
if (xfs_dir_ino_validate(mp, ino))
return 1;
@@ -575,7 +575,7 @@ xfs_dir_shortform_validate_ondisk(xfs_mount_t *mp, xfs_dinode_t *dp)
namelen_sum = 0;
sfe = &sf->list[0];
for (i = sf->hdr.count - 1; i >= 0; i--) {
- ino = XFS_GET_DIR_INO_ARCH(mp, sfe->inumber, ARCH_CONVERT);
+ ino = XFS_GET_DIR_INO8(sfe->inumber);
xfs_dir_ino_validate(mp, ino);
if (sfe->namelen >= XFS_LITINO(mp)) {
xfs_fs_cmn_err(CE_WARN, mp,
@@ -716,7 +716,7 @@ xfs_dir_leaf_replace(xfs_da_args_t *args)
entry = &leaf->entries[index];
namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, INT_GET(entry->nameidx, ARCH_CONVERT));
/* XXX - replace assert? */
- XFS_DIR_SF_PUT_DIRINO_ARCH(&inum, &namest->inumber, ARCH_CONVERT);
+ XFS_DIR_SF_PUT_DIRINO(&inum, &namest->inumber);
xfs_da_log_buf(args->trans, bp,
XFS_DA_LOGRANGE(leaf, namest, sizeof(namest->inumber)));
xfs_da_buf_done(bp);
@@ -1065,7 +1065,7 @@ xfs_dir_node_replace(xfs_da_args_t *args)
entry = &leaf->entries[blk->index];
namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, INT_GET(entry->nameidx, ARCH_CONVERT));
/* XXX - replace assert ? */
- XFS_DIR_SF_PUT_DIRINO_ARCH(&inum, &namest->inumber, ARCH_CONVERT);
+ XFS_DIR_SF_PUT_DIRINO(&inum, &namest->inumber);
xfs_da_log_buf(args->trans, bp,
XFS_DA_LOGRANGE(leaf, namest, sizeof(namest->inumber)));
xfs_da_buf_done(bp);
diff --git a/fs/xfs/xfs_dir2.c b/fs/xfs/xfs_dir2.c
index bd062886d5841..49fc0a3695ae4 100644
--- a/fs/xfs/xfs_dir2.c
+++ b/fs/xfs/xfs_dir2.c
@@ -165,7 +165,7 @@ xfs_dir2_isempty(
if (dp->i_d.di_size > XFS_IFORK_DSIZE(dp))
return 0;
sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
- return INT_ISZERO(sfp->hdr.count, ARCH_CONVERT);
+ return !sfp->hdr.count;
}
/*
diff --git a/fs/xfs/xfs_dir2_block.c b/fs/xfs/xfs_dir2_block.c
index 696f77da94459..bc4c40fcd479a 100644
--- a/fs/xfs/xfs_dir2_block.c
+++ b/fs/xfs/xfs_dir2_block.c
@@ -135,11 +135,11 @@ xfs_dir2_block_addname(
*/
bf = block->hdr.bestfree;
btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
- blp = XFS_DIR2_BLOCK_LEAF_P_ARCH(btp, ARCH_CONVERT);
+ blp = XFS_DIR2_BLOCK_LEAF_P(btp);
/*
* No stale entries? Need space for entry and new leaf.
*/
- if (INT_ISZERO(btp->stale, ARCH_CONVERT)) {
+ if (!btp->stale) {
/*
* Tag just before the first leaf entry.
*/
@@ -327,7 +327,7 @@ xfs_dir2_block_addname(
/*
* No stale entries, will use enddup space to hold new leaf.
*/
- if (INT_ISZERO(btp->stale, ARCH_CONVERT)) {
+ if (!btp->stale) {
/*
* Mark the space needed for the new leaf entry, now in use.
*/
@@ -494,7 +494,7 @@ xfs_dir2_block_getdents(
*/
btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
ptr = (char *)block->u;
- endptr = (char *)XFS_DIR2_BLOCK_LEAF_P_ARCH(btp, ARCH_CONVERT);
+ endptr = (char *)XFS_DIR2_BLOCK_LEAF_P(btp);
p.dbp = dbp;
p.put = put;
p.uio = uio;
@@ -585,7 +585,7 @@ xfs_dir2_block_log_leaf(
mp = tp->t_mountp;
block = bp->data;
btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
- blp = XFS_DIR2_BLOCK_LEAF_P_ARCH(btp, ARCH_CONVERT);
+ blp = XFS_DIR2_BLOCK_LEAF_P(btp);
xfs_da_log_buf(tp, bp, (uint)((char *)&blp[first] - (char *)block),
(uint)((char *)&blp[last + 1] - (char *)block - 1));
}
@@ -639,7 +639,7 @@ xfs_dir2_block_lookup(
block = bp->data;
xfs_dir2_data_check(dp, bp);
btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
- blp = XFS_DIR2_BLOCK_LEAF_P_ARCH(btp, ARCH_CONVERT);
+ blp = XFS_DIR2_BLOCK_LEAF_P(btp);
/*
* Get the offset from the leaf entry, to point to the data.
*/
@@ -691,7 +691,7 @@ xfs_dir2_block_lookup_int(
block = bp->data;
xfs_dir2_data_check(dp, bp);
btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
- blp = XFS_DIR2_BLOCK_LEAF_P_ARCH(btp, ARCH_CONVERT);
+ blp = XFS_DIR2_BLOCK_LEAF_P(btp);
/*
* Loop doing a binary search for our hash value.
* Find our entry, ENOENT if it's not there.
@@ -784,7 +784,7 @@ xfs_dir2_block_removename(
mp = dp->i_mount;
block = bp->data;
btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
- blp = XFS_DIR2_BLOCK_LEAF_P_ARCH(btp, ARCH_CONVERT);
+ blp = XFS_DIR2_BLOCK_LEAF_P(btp);
/*
* Point to the data entry using the leaf entry.
*/
@@ -860,7 +860,7 @@ xfs_dir2_block_replace(
mp = dp->i_mount;
block = bp->data;
btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
- blp = XFS_DIR2_BLOCK_LEAF_P_ARCH(btp, ARCH_CONVERT);
+ blp = XFS_DIR2_BLOCK_LEAF_P(btp);
/*
* Point to the data entry we need to change.
*/
@@ -936,7 +936,7 @@ xfs_dir2_leaf_to_block(
* These will show up in the leaf bests table.
*/
while (dp->i_d.di_size > mp->m_dirblksize) {
- bestsp = XFS_DIR2_LEAF_BESTS_P_ARCH(ltp, ARCH_CONVERT);
+ bestsp = XFS_DIR2_LEAF_BESTS_P(ltp);
if (INT_GET(bestsp[INT_GET(ltp->bestcount, ARCH_CONVERT) - 1], ARCH_CONVERT) ==
mp->m_dirblksize - (uint)sizeof(block->hdr)) {
if ((error =
@@ -991,12 +991,12 @@ xfs_dir2_leaf_to_block(
*/
btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
INT_SET(btp->count, ARCH_CONVERT, INT_GET(leaf->hdr.count, ARCH_CONVERT) - INT_GET(leaf->hdr.stale, ARCH_CONVERT));
- INT_ZERO(btp->stale, ARCH_CONVERT);
+ btp->stale = 0;
xfs_dir2_block_log_tail(tp, dbp);
/*
* Initialize the block leaf area. We compact out stale entries.
*/
- lep = XFS_DIR2_BLOCK_LEAF_P_ARCH(btp, ARCH_CONVERT);
+ lep = XFS_DIR2_BLOCK_LEAF_P(btp);
for (from = to = 0; from < INT_GET(leaf->hdr.count, ARCH_CONVERT); from++) {
if (INT_GET(leaf->ents[from].address, ARCH_CONVERT) == XFS_DIR2_NULL_DATAPTR)
continue;
@@ -1137,8 +1137,8 @@ xfs_dir2_sf_to_block(
*/
btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
INT_SET(btp->count, ARCH_CONVERT, INT_GET(sfp->hdr.count, ARCH_CONVERT) + 2); /* ., .. */
- INT_ZERO(btp->stale, ARCH_CONVERT);
- blp = XFS_DIR2_BLOCK_LEAF_P_ARCH(btp, ARCH_CONVERT);
+ btp->stale = 0;
+ blp = XFS_DIR2_BLOCK_LEAF_P(btp);
endoffset = (uint)((char *)blp - (char *)block);
/*
* Remove the freespace, we'll manage it.
@@ -1164,7 +1164,7 @@ xfs_dir2_sf_to_block(
*/
dep = (xfs_dir2_data_entry_t *)
((char *)block + XFS_DIR2_DATA_DOTDOT_OFFSET);
- INT_SET(dep->inumber, ARCH_CONVERT, XFS_DIR2_SF_GET_INUMBER_ARCH(sfp, &sfp->hdr.parent, ARCH_CONVERT));
+ INT_SET(dep->inumber, ARCH_CONVERT, XFS_DIR2_SF_GET_INUMBER(sfp, &sfp->hdr.parent));
dep->namelen = 2;
dep->name[0] = dep->name[1] = '.';
tagp = XFS_DIR2_DATA_ENTRY_TAG_P(dep);
@@ -1191,7 +1191,7 @@ xfs_dir2_sf_to_block(
if (sfep == NULL)
newoffset = endoffset;
else
- newoffset = XFS_DIR2_SF_GET_OFFSET_ARCH(sfep, ARCH_CONVERT);
+ newoffset = XFS_DIR2_SF_GET_OFFSET(sfep);
/*
* There should be a hole here, make one.
*/
@@ -1200,7 +1200,7 @@ xfs_dir2_sf_to_block(
((char *)block + offset);
INT_SET(dup->freetag, ARCH_CONVERT, XFS_DIR2_DATA_FREE_TAG);
INT_SET(dup->length, ARCH_CONVERT, newoffset - offset);
- INT_SET(*XFS_DIR2_DATA_UNUSED_TAG_P_ARCH(dup, ARCH_CONVERT), ARCH_CONVERT,
+ INT_SET(*XFS_DIR2_DATA_UNUSED_TAG_P(dup), ARCH_CONVERT,
(xfs_dir2_data_off_t)
((char *)dup - (char *)block));
xfs_dir2_data_log_unused(tp, bp, dup);
@@ -1213,8 +1213,8 @@ xfs_dir2_sf_to_block(
* Copy a real entry.
*/
dep = (xfs_dir2_data_entry_t *)((char *)block + newoffset);
- INT_SET(dep->inumber, ARCH_CONVERT, XFS_DIR2_SF_GET_INUMBER_ARCH(sfp,
- XFS_DIR2_SF_INUMBERP(sfep), ARCH_CONVERT));
+ INT_SET(dep->inumber, ARCH_CONVERT, XFS_DIR2_SF_GET_INUMBER(sfp,
+ XFS_DIR2_SF_INUMBERP(sfep)));
dep->namelen = sfep->namelen;
memcpy(dep->name, sfep->name, dep->namelen);
tagp = XFS_DIR2_DATA_ENTRY_TAG_P(dep);
diff --git a/fs/xfs/xfs_dir2_block.h b/fs/xfs/xfs_dir2_block.h
index 3c4f70c915eff..5a578b84e2466 100644
--- a/fs/xfs/xfs_dir2_block.h
+++ b/fs/xfs/xfs_dir2_block.h
@@ -87,13 +87,12 @@ xfs_dir2_block_tail_p(struct xfs_mount *mp, xfs_dir2_block_t *block);
* Pointer to the leaf entries embedded in a data block (1-block format)
*/
#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_DIR2_BLOCK_LEAF_P)
-struct xfs_dir2_leaf_entry *xfs_dir2_block_leaf_p_arch(
- xfs_dir2_block_tail_t *btp, xfs_arch_t arch);
-#define XFS_DIR2_BLOCK_LEAF_P_ARCH(btp,arch) \
- xfs_dir2_block_leaf_p_arch(btp,arch)
+struct xfs_dir2_leaf_entry *xfs_dir2_block_leaf_p(xfs_dir2_block_tail_t *btp);
+#define XFS_DIR2_BLOCK_LEAF_P(btp) \
+ xfs_dir2_block_leaf_p(btp)
#else
-#define XFS_DIR2_BLOCK_LEAF_P_ARCH(btp,arch) \
- (((struct xfs_dir2_leaf_entry *)(btp)) - INT_GET((btp)->count, arch))
+#define XFS_DIR2_BLOCK_LEAF_P(btp) \
+ (((struct xfs_dir2_leaf_entry *)(btp)) - INT_GET((btp)->count, ARCH_CONVERT))
#endif
/*
diff --git a/fs/xfs/xfs_dir2_data.c b/fs/xfs/xfs_dir2_data.c
index c1b8ea010a91d..db9887a107dea 100644
--- a/fs/xfs/xfs_dir2_data.c
+++ b/fs/xfs/xfs_dir2_data.c
@@ -98,7 +98,7 @@ xfs_dir2_data_check(
p = (char *)d->u;
if (INT_GET(d->hdr.magic, ARCH_CONVERT) == XFS_DIR2_BLOCK_MAGIC) {
btp = XFS_DIR2_BLOCK_TAIL_P(mp, (xfs_dir2_block_t *)d);
- lep = XFS_DIR2_BLOCK_LEAF_P_ARCH(btp, ARCH_CONVERT);
+ lep = XFS_DIR2_BLOCK_LEAF_P(btp);
endp = (char *)lep;
} else
endp = (char *)d + mp->m_dirblksize;
@@ -106,16 +106,16 @@ xfs_dir2_data_check(
/*
* Account for zero bestfree entries.
*/
- if (INT_ISZERO(bf[0].length, ARCH_CONVERT)) {
- ASSERT(INT_ISZERO(bf[0].offset, ARCH_CONVERT));
+ if (!bf[0].length) {
+ ASSERT(!bf[0].offset);
freeseen |= 1 << 0;
}
- if (INT_ISZERO(bf[1].length, ARCH_CONVERT)) {
- ASSERT(INT_ISZERO(bf[1].offset, ARCH_CONVERT));
+ if (!bf[1].length) {
+ ASSERT(!bf[1].offset);
freeseen |= 1 << 1;
}
- if (INT_ISZERO(bf[2].length, ARCH_CONVERT)) {
- ASSERT(INT_ISZERO(bf[2].offset, ARCH_CONVERT));
+ if (!bf[2].length) {
+ ASSERT(!bf[2].offset);
freeseen |= 1 << 2;
}
ASSERT(INT_GET(bf[0].length, ARCH_CONVERT) >= INT_GET(bf[1].length, ARCH_CONVERT));
@@ -132,7 +132,7 @@ xfs_dir2_data_check(
*/
if (INT_GET(dup->freetag, ARCH_CONVERT) == XFS_DIR2_DATA_FREE_TAG) {
ASSERT(lastfree == 0);
- ASSERT(INT_GET(*XFS_DIR2_DATA_UNUSED_TAG_P_ARCH(dup, ARCH_CONVERT), ARCH_CONVERT) ==
+ ASSERT(INT_GET(*XFS_DIR2_DATA_UNUSED_TAG_P(dup), ARCH_CONVERT) ==
(char *)dup - (char *)d);
dfp = xfs_dir2_data_freefind(d, dup);
if (dfp) {
@@ -217,8 +217,8 @@ xfs_dir2_data_freefind(
for (dfp = &d->hdr.bestfree[0], seenzero = matched = 0;
dfp < &d->hdr.bestfree[XFS_DIR2_DATA_FD_COUNT];
dfp++) {
- if (INT_ISZERO(dfp->offset, ARCH_CONVERT)) {
- ASSERT(INT_ISZERO(dfp->length, ARCH_CONVERT));
+ if (!dfp->offset) {
+ ASSERT(!dfp->length);
seenzero = 1;
continue;
}
@@ -247,7 +247,7 @@ xfs_dir2_data_freefind(
for (dfp = &d->hdr.bestfree[0];
dfp < &d->hdr.bestfree[XFS_DIR2_DATA_FD_COUNT];
dfp++) {
- if (INT_ISZERO(dfp->offset, ARCH_CONVERT))
+ if (!dfp->offset)
return NULL;
if (INT_GET(dfp->offset, ARCH_CONVERT) == off)
return dfp;
@@ -334,8 +334,8 @@ xfs_dir2_data_freeremove(
/*
* Clear the 3rd entry, must be zero now.
*/
- INT_ZERO(d->hdr.bestfree[2].length, ARCH_CONVERT);
- INT_ZERO(d->hdr.bestfree[2].offset, ARCH_CONVERT);
+ d->hdr.bestfree[2].length = 0;
+ d->hdr.bestfree[2].offset = 0;
*loghead = 1;
}
@@ -372,7 +372,7 @@ xfs_dir2_data_freescan(
endp = aendp;
else if (INT_GET(d->hdr.magic, ARCH_CONVERT) == XFS_DIR2_BLOCK_MAGIC) {
btp = XFS_DIR2_BLOCK_TAIL_P(mp, (xfs_dir2_block_t *)d);
- endp = (char *)XFS_DIR2_BLOCK_LEAF_P_ARCH(btp, ARCH_CONVERT);
+ endp = (char *)XFS_DIR2_BLOCK_LEAF_P(btp);
} else
endp = (char *)d + mp->m_dirblksize;
/*
@@ -385,7 +385,7 @@ xfs_dir2_data_freescan(
*/
if (INT_GET(dup->freetag, ARCH_CONVERT) == XFS_DIR2_DATA_FREE_TAG) {
ASSERT((char *)dup - (char *)d ==
- INT_GET(*XFS_DIR2_DATA_UNUSED_TAG_P_ARCH(dup, ARCH_CONVERT), ARCH_CONVERT));
+ INT_GET(*XFS_DIR2_DATA_UNUSED_TAG_P(dup), ARCH_CONVERT));
xfs_dir2_data_freeinsert(d, dup, loghead);
p += INT_GET(dup->length, ARCH_CONVERT);
}
@@ -440,8 +440,8 @@ xfs_dir2_data_init(
INT_SET(d->hdr.magic, ARCH_CONVERT, XFS_DIR2_DATA_MAGIC);
INT_SET(d->hdr.bestfree[0].offset, ARCH_CONVERT, (xfs_dir2_data_off_t)sizeof(d->hdr));
for (i = 1; i < XFS_DIR2_DATA_FD_COUNT; i++) {
- INT_ZERO(d->hdr.bestfree[i].length, ARCH_CONVERT);
- INT_ZERO(d->hdr.bestfree[i].offset, ARCH_CONVERT);
+ d->hdr.bestfree[i].length = 0;
+ d->hdr.bestfree[i].offset = 0;
}
/*
* Set up an unused entry for the block's body.
@@ -452,7 +452,7 @@ xfs_dir2_data_init(
t=mp->m_dirblksize - (uint)sizeof(d->hdr);
INT_SET(d->hdr.bestfree[0].length, ARCH_CONVERT, t);
INT_SET(dup->length, ARCH_CONVERT, t);
- INT_SET(*XFS_DIR2_DATA_UNUSED_TAG_P_ARCH(dup, ARCH_CONVERT), ARCH_CONVERT,
+ INT_SET(*XFS_DIR2_DATA_UNUSED_TAG_P(dup), ARCH_CONVERT,
(xfs_dir2_data_off_t)((char *)dup - (char *)d));
/*
* Log it and return it.
@@ -523,8 +523,8 @@ xfs_dir2_data_log_unused(
* Log the end (tag) of the unused entry.
*/
xfs_da_log_buf(tp, bp,
- (uint)((char *)XFS_DIR2_DATA_UNUSED_TAG_P_ARCH(dup, ARCH_CONVERT) - (char *)d),
- (uint)((char *)XFS_DIR2_DATA_UNUSED_TAG_P_ARCH(dup, ARCH_CONVERT) - (char *)d +
+ (uint)((char *)XFS_DIR2_DATA_UNUSED_TAG_P(dup) - (char *)d),
+ (uint)((char *)XFS_DIR2_DATA_UNUSED_TAG_P(dup) - (char *)d +
sizeof(xfs_dir2_data_off_t) - 1));
}
@@ -562,7 +562,7 @@ xfs_dir2_data_make_free(
ASSERT(INT_GET(d->hdr.magic, ARCH_CONVERT) == XFS_DIR2_BLOCK_MAGIC);
btp = XFS_DIR2_BLOCK_TAIL_P(mp, (xfs_dir2_block_t *)d);
- endptr = (char *)XFS_DIR2_BLOCK_LEAF_P_ARCH(btp, ARCH_CONVERT);
+ endptr = (char *)XFS_DIR2_BLOCK_LEAF_P(btp);
}
/*
* If this isn't the start of the block, then back up to
@@ -608,12 +608,12 @@ xfs_dir2_data_make_free(
* since the third bestfree is there, there might be more
* entries.
*/
- needscan = !INT_ISZERO(d->hdr.bestfree[2].length, ARCH_CONVERT);
+ needscan = d->hdr.bestfree[2].length;
/*
* Fix up the new big freespace.
*/
INT_MOD(prevdup->length, ARCH_CONVERT, len + INT_GET(postdup->length, ARCH_CONVERT));
- INT_SET(*XFS_DIR2_DATA_UNUSED_TAG_P_ARCH(prevdup, ARCH_CONVERT), ARCH_CONVERT,
+ INT_SET(*XFS_DIR2_DATA_UNUSED_TAG_P(prevdup), ARCH_CONVERT,
(xfs_dir2_data_off_t)((char *)prevdup - (char *)d));
xfs_dir2_data_log_unused(tp, bp, prevdup);
if (!needscan) {
@@ -637,8 +637,8 @@ xfs_dir2_data_make_free(
dfp = xfs_dir2_data_freeinsert(d, prevdup, needlogp);
ASSERT(dfp == &d->hdr.bestfree[0]);
ASSERT(INT_GET(dfp->length, ARCH_CONVERT) == INT_GET(prevdup->length, ARCH_CONVERT));
- ASSERT(INT_ISZERO(dfp[1].length, ARCH_CONVERT));
- ASSERT(INT_ISZERO(dfp[2].length, ARCH_CONVERT));
+ ASSERT(!dfp[1].length);
+ ASSERT(!dfp[2].length);
}
}
/*
@@ -647,7 +647,7 @@ xfs_dir2_data_make_free(
else if (prevdup) {
dfp = xfs_dir2_data_freefind(d, prevdup);
INT_MOD(prevdup->length, ARCH_CONVERT, len);
- INT_SET(*XFS_DIR2_DATA_UNUSED_TAG_P_ARCH(prevdup, ARCH_CONVERT), ARCH_CONVERT,
+ INT_SET(*XFS_DIR2_DATA_UNUSED_TAG_P(prevdup), ARCH_CONVERT,
(xfs_dir2_data_off_t)((char *)prevdup - (char *)d));
xfs_dir2_data_log_unused(tp, bp, prevdup);
/*
@@ -673,7 +673,7 @@ xfs_dir2_data_make_free(
newdup = (xfs_dir2_data_unused_t *)((char *)d + offset);
INT_SET(newdup->freetag, ARCH_CONVERT, XFS_DIR2_DATA_FREE_TAG);
INT_SET(newdup->length, ARCH_CONVERT, len + INT_GET(postdup->length, ARCH_CONVERT));
- INT_SET(*XFS_DIR2_DATA_UNUSED_TAG_P_ARCH(newdup, ARCH_CONVERT), ARCH_CONVERT,
+ INT_SET(*XFS_DIR2_DATA_UNUSED_TAG_P(newdup), ARCH_CONVERT,
(xfs_dir2_data_off_t)((char *)newdup - (char *)d));
xfs_dir2_data_log_unused(tp, bp, newdup);
/*
@@ -698,7 +698,7 @@ xfs_dir2_data_make_free(
newdup = (xfs_dir2_data_unused_t *)((char *)d + offset);
INT_SET(newdup->freetag, ARCH_CONVERT, XFS_DIR2_DATA_FREE_TAG);
INT_SET(newdup->length, ARCH_CONVERT, len);
- INT_SET(*XFS_DIR2_DATA_UNUSED_TAG_P_ARCH(newdup, ARCH_CONVERT), ARCH_CONVERT,
+ INT_SET(*XFS_DIR2_DATA_UNUSED_TAG_P(newdup), ARCH_CONVERT,
(xfs_dir2_data_off_t)((char *)newdup - (char *)d));
xfs_dir2_data_log_unused(tp, bp, newdup);
(void)xfs_dir2_data_freeinsert(d, newdup, needlogp);
@@ -734,7 +734,7 @@ xfs_dir2_data_use_free(
ASSERT(INT_GET(dup->freetag, ARCH_CONVERT) == XFS_DIR2_DATA_FREE_TAG);
ASSERT(offset >= (char *)dup - (char *)d);
ASSERT(offset + len <= (char *)dup + INT_GET(dup->length, ARCH_CONVERT) - (char *)d);
- ASSERT((char *)dup - (char *)d == INT_GET(*XFS_DIR2_DATA_UNUSED_TAG_P_ARCH(dup, ARCH_CONVERT), ARCH_CONVERT));
+ ASSERT((char *)dup - (char *)d == INT_GET(*XFS_DIR2_DATA_UNUSED_TAG_P(dup), ARCH_CONVERT));
/*
* Look up the entry in the bestfree table.
*/
@@ -754,7 +754,7 @@ xfs_dir2_data_use_free(
*/
if (matchfront && matchback) {
if (dfp) {
- needscan = !INT_ISZERO(d->hdr.bestfree[2].offset, ARCH_CONVERT);
+ needscan = d->hdr.bestfree[2].offset;
if (!needscan)
xfs_dir2_data_freeremove(d, dfp, needlogp);
}
@@ -767,7 +767,7 @@ xfs_dir2_data_use_free(
newdup = (xfs_dir2_data_unused_t *)((char *)d + offset + len);
INT_SET(newdup->freetag, ARCH_CONVERT, XFS_DIR2_DATA_FREE_TAG);
INT_SET(newdup->length, ARCH_CONVERT, oldlen - len);
- INT_SET(*XFS_DIR2_DATA_UNUSED_TAG_P_ARCH(newdup, ARCH_CONVERT), ARCH_CONVERT,
+ INT_SET(*XFS_DIR2_DATA_UNUSED_TAG_P(newdup), ARCH_CONVERT,
(xfs_dir2_data_off_t)((char *)newdup - (char *)d));
xfs_dir2_data_log_unused(tp, bp, newdup);
/*
@@ -795,7 +795,7 @@ xfs_dir2_data_use_free(
newdup = dup;
INT_SET(newdup->length, ARCH_CONVERT, (xfs_dir2_data_off_t)
(((char *)d + offset) - (char *)newdup));
- INT_SET(*XFS_DIR2_DATA_UNUSED_TAG_P_ARCH(newdup, ARCH_CONVERT), ARCH_CONVERT,
+ INT_SET(*XFS_DIR2_DATA_UNUSED_TAG_P(newdup), ARCH_CONVERT,
(xfs_dir2_data_off_t)((char *)newdup - (char *)d));
xfs_dir2_data_log_unused(tp, bp, newdup);
/*
@@ -823,13 +823,13 @@ xfs_dir2_data_use_free(
newdup = dup;
INT_SET(newdup->length, ARCH_CONVERT, (xfs_dir2_data_off_t)
(((char *)d + offset) - (char *)newdup));
- INT_SET(*XFS_DIR2_DATA_UNUSED_TAG_P_ARCH(newdup, ARCH_CONVERT), ARCH_CONVERT,
+ INT_SET(*XFS_DIR2_DATA_UNUSED_TAG_P(newdup), ARCH_CONVERT,
(xfs_dir2_data_off_t)((char *)newdup - (char *)d));
xfs_dir2_data_log_unused(tp, bp, newdup);
newdup2 = (xfs_dir2_data_unused_t *)((char *)d + offset + len);
INT_SET(newdup2->freetag, ARCH_CONVERT, XFS_DIR2_DATA_FREE_TAG);
INT_SET(newdup2->length, ARCH_CONVERT, oldlen - len - INT_GET(newdup->length, ARCH_CONVERT));
- INT_SET(*XFS_DIR2_DATA_UNUSED_TAG_P_ARCH(newdup2, ARCH_CONVERT), ARCH_CONVERT,
+ INT_SET(*XFS_DIR2_DATA_UNUSED_TAG_P(newdup2), ARCH_CONVERT,
(xfs_dir2_data_off_t)((char *)newdup2 - (char *)d));
xfs_dir2_data_log_unused(tp, bp, newdup2);
/*
@@ -841,7 +841,7 @@ xfs_dir2_data_use_free(
* the 2 new will work.
*/
if (dfp) {
- needscan = !INT_ISZERO(d->hdr.bestfree[2].length, ARCH_CONVERT);
+ needscan = d->hdr.bestfree[2].length;
if (!needscan) {
xfs_dir2_data_freeremove(d, dfp, needlogp);
(void)xfs_dir2_data_freeinsert(d, newdup,
diff --git a/fs/xfs/xfs_dir2_data.h b/fs/xfs/xfs_dir2_data.h
index b9e16ab5f6223..3f02294ccff0a 100644
--- a/fs/xfs/xfs_dir2_data.h
+++ b/fs/xfs/xfs_dir2_data.h
@@ -163,14 +163,13 @@ xfs_dir2_data_off_t *xfs_dir2_data_entry_tag_p(xfs_dir2_data_entry_t *dep);
* Pointer to a freespace's tag word.
*/
#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_DIR2_DATA_UNUSED_TAG_P)
-xfs_dir2_data_off_t *xfs_dir2_data_unused_tag_p_arch(
- xfs_dir2_data_unused_t *dup, xfs_arch_t arch);
-#define XFS_DIR2_DATA_UNUSED_TAG_P_ARCH(dup,arch) \
- xfs_dir2_data_unused_tag_p_arch(dup,arch)
+xfs_dir2_data_off_t *xfs_dir2_data_unused_tag_p(xfs_dir2_data_unused_t *dup);
+#define XFS_DIR2_DATA_UNUSED_TAG_P(dup) \
+ xfs_dir2_data_unused_tag_p(dup)
#else
-#define XFS_DIR2_DATA_UNUSED_TAG_P_ARCH(dup,arch) \
+#define XFS_DIR2_DATA_UNUSED_TAG_P(dup) \
((xfs_dir2_data_off_t *)\
- ((char *)(dup) + INT_GET((dup)->length, arch) \
+ ((char *)(dup) + INT_GET((dup)->length, ARCH_CONVERT) \
- (uint)sizeof(xfs_dir2_data_off_t)))
#endif
diff --git a/fs/xfs/xfs_dir2_leaf.c b/fs/xfs/xfs_dir2_leaf.c
index c75d54f3fda7c..262d1e86df30f 100644
--- a/fs/xfs/xfs_dir2_leaf.c
+++ b/fs/xfs/xfs_dir2_leaf.c
@@ -127,7 +127,7 @@ xfs_dir2_block_to_leaf(
block = dbp->data;
xfs_dir2_data_check(dp, dbp);
btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
- blp = XFS_DIR2_BLOCK_LEAF_P_ARCH(btp, ARCH_CONVERT);
+ blp = XFS_DIR2_BLOCK_LEAF_P(btp);
/*
* Set the counts in the leaf header.
*/
@@ -162,7 +162,7 @@ xfs_dir2_block_to_leaf(
*/
ltp = XFS_DIR2_LEAF_TAIL_P(mp, leaf);
INT_SET(ltp->bestcount, ARCH_CONVERT, 1);
- bestsp = XFS_DIR2_LEAF_BESTS_P_ARCH(ltp, ARCH_CONVERT);
+ bestsp = XFS_DIR2_LEAF_BESTS_P(ltp);
INT_COPY(bestsp[0], block->hdr.bestfree[0].length, ARCH_CONVERT);
/*
* Log the data header and leaf bests table.
@@ -233,7 +233,7 @@ xfs_dir2_leaf_addname(
index = xfs_dir2_leaf_search_hash(args, lbp);
leaf = lbp->data;
ltp = XFS_DIR2_LEAF_TAIL_P(mp, leaf);
- bestsp = XFS_DIR2_LEAF_BESTS_P_ARCH(ltp, ARCH_CONVERT);
+ bestsp = XFS_DIR2_LEAF_BESTS_P(ltp);
length = XFS_DIR2_DATA_ENTSIZE(args->namelen);
/*
* See if there are any entries with the same hash value
@@ -274,7 +274,7 @@ xfs_dir2_leaf_addname(
* How many bytes do we need in the leaf block?
*/
needbytes =
- (!INT_ISZERO(leaf->hdr.stale, ARCH_CONVERT) ? 0 : (uint)sizeof(leaf->ents[0])) +
+ (leaf->hdr.stale ? 0 : (uint)sizeof(leaf->ents[0])) +
(use_block != -1 ? 0 : (uint)sizeof(leaf->bests[0]));
/*
* Now kill use_block if it refers to a missing block, so we
@@ -456,7 +456,7 @@ xfs_dir2_leaf_addname(
* Now we need to make room to insert the leaf entry.
* If there are no stale entries, we just insert a hole at index.
*/
- if (INT_ISZERO(leaf->hdr.stale, ARCH_CONVERT)) {
+ if (!leaf->hdr.stale) {
/*
* lep is still good as the index leaf entry.
*/
@@ -595,7 +595,7 @@ xfs_dir2_leaf_check(
* Leaves and bests don't overlap.
*/
ASSERT((char *)&leaf->ents[INT_GET(leaf->hdr.count, ARCH_CONVERT)] <=
- (char *)XFS_DIR2_LEAF_BESTS_P_ARCH(ltp, ARCH_CONVERT));
+ (char *)XFS_DIR2_LEAF_BESTS_P(ltp));
/*
* Check hash value order, count stale entries.
*/
@@ -625,7 +625,7 @@ xfs_dir2_leaf_compact(
int to; /* target leaf index */
leaf = bp->data;
- if (INT_ISZERO(leaf->hdr.stale, ARCH_CONVERT)) {
+ if (!leaf->hdr.stale) {
return;
}
/*
@@ -649,7 +649,7 @@ xfs_dir2_leaf_compact(
*/
ASSERT(INT_GET(leaf->hdr.stale, ARCH_CONVERT) == from - to);
INT_MOD(leaf->hdr.count, ARCH_CONVERT, -(INT_GET(leaf->hdr.stale, ARCH_CONVERT)));
- INT_ZERO(leaf->hdr.stale, ARCH_CONVERT);
+ leaf->hdr.stale = 0;
xfs_dir2_leaf_log_header(args->trans, bp);
if (loglow != -1)
xfs_dir2_leaf_log_ents(args->trans, bp, loglow, to - 1);
@@ -1192,10 +1192,10 @@ xfs_dir2_leaf_init(
* Initialize the header.
*/
INT_SET(leaf->hdr.info.magic, ARCH_CONVERT, magic);
- INT_ZERO(leaf->hdr.info.forw, ARCH_CONVERT);
- INT_ZERO(leaf->hdr.info.back, ARCH_CONVERT);
- INT_ZERO(leaf->hdr.count, ARCH_CONVERT);
- INT_ZERO(leaf->hdr.stale, ARCH_CONVERT);
+ leaf->hdr.info.forw = 0;
+ leaf->hdr.info.back = 0;
+ leaf->hdr.count = 0;
+ leaf->hdr.stale = 0;
xfs_dir2_leaf_log_header(tp, bp);
/*
* If it's a leaf-format directory initialize the tail.
@@ -1204,7 +1204,7 @@ xfs_dir2_leaf_init(
*/
if (magic == XFS_DIR2_LEAF1_MAGIC) {
ltp = XFS_DIR2_LEAF_TAIL_P(mp, leaf);
- INT_ZERO(ltp->bestcount, ARCH_CONVERT);
+ ltp->bestcount = 0;
xfs_dir2_leaf_log_tail(tp, bp);
}
*bpp = bp;
@@ -1229,8 +1229,8 @@ xfs_dir2_leaf_log_bests(
leaf = bp->data;
ASSERT(INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) == XFS_DIR2_LEAF1_MAGIC);
ltp = XFS_DIR2_LEAF_TAIL_P(tp->t_mountp, leaf);
- firstb = XFS_DIR2_LEAF_BESTS_P_ARCH(ltp, ARCH_CONVERT) + first;
- lastb = XFS_DIR2_LEAF_BESTS_P_ARCH(ltp, ARCH_CONVERT) + last;
+ firstb = XFS_DIR2_LEAF_BESTS_P(ltp) + first;
+ lastb = XFS_DIR2_LEAF_BESTS_P(ltp) + last;
xfs_da_log_buf(tp, bp, (uint)((char *)firstb - (char *)leaf),
(uint)((char *)lastb - (char *)leaf + sizeof(*lastb) - 1));
}
@@ -1497,7 +1497,7 @@ xfs_dir2_leaf_removename(
needscan = needlog = 0;
oldbest = INT_GET(data->hdr.bestfree[0].length, ARCH_CONVERT);
ltp = XFS_DIR2_LEAF_TAIL_P(mp, leaf);
- bestsp = XFS_DIR2_LEAF_BESTS_P_ARCH(ltp, ARCH_CONVERT);
+ bestsp = XFS_DIR2_LEAF_BESTS_P(ltp);
ASSERT(INT_GET(bestsp[db], ARCH_CONVERT) == oldbest);
/*
* Mark the former data entry unused.
@@ -1658,7 +1658,7 @@ xfs_dir2_leaf_search_hash(
leaf = lbp->data;
#ifndef __KERNEL__
- if (INT_ISZERO(leaf->hdr.count, ARCH_CONVERT))
+ if (!leaf->hdr.count)
return 0;
#endif
/*
@@ -1749,7 +1749,7 @@ xfs_dir2_leaf_trim_data(
/*
* Eliminate the last bests entry from the table.
*/
- bestsp = XFS_DIR2_LEAF_BESTS_P_ARCH(ltp, ARCH_CONVERT);
+ bestsp = XFS_DIR2_LEAF_BESTS_P(ltp);
INT_MOD(ltp->bestcount, ARCH_CONVERT, -1);
memmove(&bestsp[1], &bestsp[0], INT_GET(ltp->bestcount, ARCH_CONVERT) * sizeof(*bestsp));
xfs_dir2_leaf_log_tail(tp, lbp);
@@ -1835,7 +1835,7 @@ xfs_dir2_node_to_leaf(
}
free = fbp->data;
ASSERT(INT_GET(free->hdr.magic, ARCH_CONVERT) == XFS_DIR2_FREE_MAGIC);
- ASSERT(INT_ISZERO(free->hdr.firstdb, ARCH_CONVERT));
+ ASSERT(!free->hdr.firstdb);
/*
* Now see if the leafn and free data will fit in a leaf1.
* If not, release the buffer and give up.
@@ -1865,7 +1865,7 @@ xfs_dir2_node_to_leaf(
/*
* Set up the leaf bests table.
*/
- memcpy(XFS_DIR2_LEAF_BESTS_P_ARCH(ltp, ARCH_CONVERT), free->bests,
+ memcpy(XFS_DIR2_LEAF_BESTS_P(ltp), free->bests,
INT_GET(ltp->bestcount, ARCH_CONVERT) * sizeof(leaf->bests[0]));
xfs_dir2_leaf_log_bests(tp, lbp, 0, INT_GET(ltp->bestcount, ARCH_CONVERT) - 1);
xfs_dir2_leaf_log_tail(tp, lbp);
diff --git a/fs/xfs/xfs_dir2_leaf.h b/fs/xfs/xfs_dir2_leaf.h
index d3b5145a9b4f1..7f20eee56a52a 100644
--- a/fs/xfs/xfs_dir2_leaf.h
+++ b/fs/xfs/xfs_dir2_leaf.h
@@ -144,11 +144,11 @@ xfs_dir2_leaf_tail_p(struct xfs_mount *mp, xfs_dir2_leaf_t *lp);
*/
#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_DIR2_LEAF_BESTS_P)
xfs_dir2_data_off_t *
-xfs_dir2_leaf_bests_p_arch(xfs_dir2_leaf_tail_t *ltp, xfs_arch_t arch);
-#define XFS_DIR2_LEAF_BESTS_P_ARCH(ltp,arch) xfs_dir2_leaf_bests_p_arch(ltp,arch)
+xfs_dir2_leaf_bests_p(xfs_dir2_leaf_tail_t *ltp);
+#define XFS_DIR2_LEAF_BESTS_P(ltp) xfs_dir2_leaf_bests_p(ltp)
#else
-#define XFS_DIR2_LEAF_BESTS_P_ARCH(ltp,arch) \
- ((xfs_dir2_data_off_t *)(ltp) - INT_GET((ltp)->bestcount, arch))
+#define XFS_DIR2_LEAF_BESTS_P(ltp) \
+ ((xfs_dir2_data_off_t *)(ltp) - INT_GET((ltp)->bestcount, ARCH_CONVERT))
#endif
/*
diff --git a/fs/xfs/xfs_dir2_node.c b/fs/xfs/xfs_dir2_node.c
index ec42931d04987..a7615d86bfb7f 100644
--- a/fs/xfs/xfs_dir2_node.c
+++ b/fs/xfs/xfs_dir2_node.c
@@ -172,14 +172,14 @@ xfs_dir2_leaf_to_node(
* Initialize the freespace block header.
*/
INT_SET(free->hdr.magic, ARCH_CONVERT, XFS_DIR2_FREE_MAGIC);
- INT_ZERO(free->hdr.firstdb, ARCH_CONVERT);
+ free->hdr.firstdb = 0;
ASSERT(INT_GET(ltp->bestcount, ARCH_CONVERT) <= (uint)dp->i_d.di_size / mp->m_dirblksize);
INT_COPY(free->hdr.nvalid, ltp->bestcount, ARCH_CONVERT);
/*
* Copy freespace entries from the leaf block to the new block.
* Count active entries.
*/
- for (i = n = 0, from = XFS_DIR2_LEAF_BESTS_P_ARCH(ltp, ARCH_CONVERT), to = free->bests;
+ for (i = n = 0, from = XFS_DIR2_LEAF_BESTS_P(ltp), to = free->bests;
i < INT_GET(ltp->bestcount, ARCH_CONVERT); i++, from++, to++) {
if ((off = INT_GET(*from, ARCH_CONVERT)) != NULLDATAOFF)
n++;
@@ -240,7 +240,7 @@ xfs_dir2_leafn_add(
*/
if (INT_GET(leaf->hdr.count, ARCH_CONVERT) == XFS_DIR2_MAX_LEAF_ENTS(mp)) {
- if (INT_ISZERO(leaf->hdr.stale, ARCH_CONVERT))
+ if (!leaf->hdr.stale)
return XFS_ERROR(ENOSPC);
compact = INT_GET(leaf->hdr.stale, ARCH_CONVERT) > 1;
} else
@@ -263,14 +263,14 @@ xfs_dir2_leafn_add(
/*
* Set impossible logging indices for this case.
*/
- else if (!INT_ISZERO(leaf->hdr.stale, ARCH_CONVERT)) {
+ else if (leaf->hdr.stale) {
lfloglow = INT_GET(leaf->hdr.count, ARCH_CONVERT);
lfloghigh = -1;
}
/*
* No stale entries, just insert a space for the new entry.
*/
- if (INT_ISZERO(leaf->hdr.stale, ARCH_CONVERT)) {
+ if (!leaf->hdr.stale) {
lep = &leaf->ents[index];
if (index < INT_GET(leaf->hdr.count, ARCH_CONVERT))
memmove(lep + 1, lep,
@@ -403,7 +403,7 @@ xfs_dir2_leafn_lasthash(
ASSERT(INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) == XFS_DIR2_LEAFN_MAGIC);
if (count)
*count = INT_GET(leaf->hdr.count, ARCH_CONVERT);
- if (INT_ISZERO(leaf->hdr.count, ARCH_CONVERT))
+ if (!leaf->hdr.count)
return 0;
return INT_GET(leaf->ents[INT_GET(leaf->hdr.count, ARCH_CONVERT) - 1].hashval, ARCH_CONVERT);
}
@@ -690,7 +690,7 @@ xfs_dir2_leafn_moveents(
* If the source has stale leaves, count the ones in the copy range
* so we can update the header correctly.
*/
- if (!INT_ISZERO(leaf_s->hdr.stale, ARCH_CONVERT)) {
+ if (leaf_s->hdr.stale) {
int i; /* temp leaf index */
for (i = start_s, stale = 0; i < start_s + count; i++) {
@@ -1020,7 +1020,7 @@ xfs_dir2_leafn_remove(
* If there are no useful entries left in the block,
* get rid of the block if we can.
*/
- if (INT_ISZERO(free->hdr.nused, ARCH_CONVERT)) {
+ if (!free->hdr.nused) {
error = xfs_dir2_shrink_inode(args, fdb, fbp);
if (error == 0) {
fbp = NULL;
@@ -1182,7 +1182,7 @@ xfs_dir2_leafn_toosmall(
* Make altpath point to the block we want to keep and
* path point to the block we want to drop (this one).
*/
- forward = !INT_ISZERO(info->forw, ARCH_CONVERT);
+ forward = info->forw;
memcpy(&state->altpath, &state->path, sizeof(state->path));
error = xfs_da_path_shift(state, &state->altpath, forward, 0,
&rval);
@@ -1634,8 +1634,8 @@ xfs_dir2_node_addname_int(
INT_SET(free->hdr.firstdb, ARCH_CONVERT,
(fbno - XFS_DIR2_FREE_FIRSTDB(mp)) *
XFS_DIR2_MAX_FREE_BESTS(mp));
- INT_ZERO(free->hdr.nvalid, ARCH_CONVERT);
- INT_ZERO(free->hdr.nused, ARCH_CONVERT);
+ free->hdr.nvalid = 0;
+ free->hdr.nused = 0;
} else {
free = fbp->data;
ASSERT(INT_GET(free->hdr.magic, ARCH_CONVERT) == XFS_DIR2_FREE_MAGIC);
diff --git a/fs/xfs/xfs_dir2_sf.c b/fs/xfs/xfs_dir2_sf.c
index 9e9b3836eb27f..6bbc61674411c 100644
--- a/fs/xfs/xfs_dir2_sf.c
+++ b/fs/xfs/xfs_dir2_sf.c
@@ -114,7 +114,7 @@ xfs_dir2_block_sfsize(
count = i8count = namelen = 0;
btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
- blp = XFS_DIR2_BLOCK_LEAF_P_ARCH(btp, ARCH_CONVERT);
+ blp = XFS_DIR2_BLOCK_LEAF_P(btp);
/*
* Iterate over the block's data entries by using the leaf pointers.
@@ -163,7 +163,7 @@ xfs_dir2_block_sfsize(
*/
sfhp->count = count;
sfhp->i8count = i8count;
- XFS_DIR2_SF_PUT_INUMBER_ARCH((xfs_dir2_sf_t *)sfhp, &parent, &sfhp->parent, ARCH_CONVERT);
+ XFS_DIR2_SF_PUT_INUMBER((xfs_dir2_sf_t *)sfhp, &parent, &sfhp->parent);
return size;
}
@@ -230,7 +230,7 @@ xfs_dir2_block_to_sf(
*/
btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
ptr = (char *)block->u;
- endptr = (char *)XFS_DIR2_BLOCK_LEAF_P_ARCH(btp, ARCH_CONVERT);
+ endptr = (char *)XFS_DIR2_BLOCK_LEAF_P(btp);
sfep = XFS_DIR2_SF_FIRSTENTRY(sfp);
/*
* Loop over the active and unused entries.
@@ -257,19 +257,19 @@ xfs_dir2_block_to_sf(
else if (dep->namelen == 2 &&
dep->name[0] == '.' && dep->name[1] == '.')
ASSERT(INT_GET(dep->inumber, ARCH_CONVERT) ==
- XFS_DIR2_SF_GET_INUMBER_ARCH(sfp, &sfp->hdr.parent, ARCH_CONVERT));
+ XFS_DIR2_SF_GET_INUMBER(sfp, &sfp->hdr.parent));
/*
* Normal entry, copy it into shortform.
*/
else {
sfep->namelen = dep->namelen;
- XFS_DIR2_SF_PUT_OFFSET_ARCH(sfep,
+ XFS_DIR2_SF_PUT_OFFSET(sfep,
(xfs_dir2_data_aoff_t)
- ((char *)dep - (char *)block), ARCH_CONVERT);
+ ((char *)dep - (char *)block));
memcpy(sfep->name, dep->name, dep->namelen);
temp=INT_GET(dep->inumber, ARCH_CONVERT);
- XFS_DIR2_SF_PUT_INUMBER_ARCH(sfp, &temp,
- XFS_DIR2_SF_INUMBERP(sfep), ARCH_CONVERT);
+ XFS_DIR2_SF_PUT_INUMBER(sfp, &temp,
+ XFS_DIR2_SF_INUMBERP(sfep));
sfep = XFS_DIR2_SF_NEXTENTRY(sfp, sfep);
}
ptr += XFS_DIR2_DATA_ENTSIZE(dep->namelen);
@@ -427,10 +427,10 @@ xfs_dir2_sf_addname_easy(
* Fill in the new entry.
*/
sfep->namelen = args->namelen;
- XFS_DIR2_SF_PUT_OFFSET_ARCH(sfep, offset, ARCH_CONVERT);
+ XFS_DIR2_SF_PUT_OFFSET(sfep, offset);
memcpy(sfep->name, args->name, sfep->namelen);
- XFS_DIR2_SF_PUT_INUMBER_ARCH(sfp, &args->inumber,
- XFS_DIR2_SF_INUMBERP(sfep), ARCH_CONVERT);
+ XFS_DIR2_SF_PUT_INUMBER(sfp, &args->inumber,
+ XFS_DIR2_SF_INUMBERP(sfep));
/*
* Update the header and inode.
*/
@@ -494,7 +494,7 @@ xfs_dir2_sf_addname_hard(
offset = new_offset + XFS_DIR2_DATA_ENTSIZE(oldsfep->namelen),
oldsfep = XFS_DIR2_SF_NEXTENTRY(oldsfp, oldsfep),
eof = (char *)oldsfep == &buf[old_isize]) {
- new_offset = XFS_DIR2_SF_GET_OFFSET_ARCH(oldsfep, ARCH_CONVERT);
+ new_offset = XFS_DIR2_SF_GET_OFFSET(oldsfep);
if (offset + add_datasize <= new_offset)
break;
}
@@ -519,10 +519,10 @@ xfs_dir2_sf_addname_hard(
* Fill in the new entry, and update the header counts.
*/
sfep->namelen = args->namelen;
- XFS_DIR2_SF_PUT_OFFSET_ARCH(sfep, offset, ARCH_CONVERT);
+ XFS_DIR2_SF_PUT_OFFSET(sfep, offset);
memcpy(sfep->name, args->name, sfep->namelen);
- XFS_DIR2_SF_PUT_INUMBER_ARCH(sfp, &args->inumber,
- XFS_DIR2_SF_INUMBERP(sfep), ARCH_CONVERT);
+ XFS_DIR2_SF_PUT_INUMBER(sfp, &args->inumber,
+ XFS_DIR2_SF_INUMBERP(sfep));
sfp->hdr.count++;
#if XFS_BIG_INUMS
if (args->inumber > XFS_DIR2_MAX_SHORT_INUM && !objchange)
@@ -579,8 +579,8 @@ xfs_dir2_sf_addname_pick(
*/
for (i = 0; i < sfp->hdr.count; i++) {
if (!holefit)
- holefit = offset + size <= XFS_DIR2_SF_GET_OFFSET_ARCH(sfep, ARCH_CONVERT);
- offset = XFS_DIR2_SF_GET_OFFSET_ARCH(sfep, ARCH_CONVERT) +
+ holefit = offset + size <= XFS_DIR2_SF_GET_OFFSET(sfep);
+ offset = XFS_DIR2_SF_GET_OFFSET(sfep) +
XFS_DIR2_DATA_ENTSIZE(sfep->namelen);
sfep = XFS_DIR2_SF_NEXTENTRY(sfp, sfep);
}
@@ -641,17 +641,17 @@ xfs_dir2_sf_check(
sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
offset = XFS_DIR2_DATA_FIRST_OFFSET;
- ino = XFS_DIR2_SF_GET_INUMBER_ARCH(sfp, &sfp->hdr.parent, ARCH_CONVERT);
+ ino = XFS_DIR2_SF_GET_INUMBER(sfp, &sfp->hdr.parent);
i8count = ino > XFS_DIR2_MAX_SHORT_INUM;
for (i = 0, sfep = XFS_DIR2_SF_FIRSTENTRY(sfp);
i < sfp->hdr.count;
i++, sfep = XFS_DIR2_SF_NEXTENTRY(sfp, sfep)) {
- ASSERT(XFS_DIR2_SF_GET_OFFSET_ARCH(sfep, ARCH_CONVERT) >= offset);
- ino = XFS_DIR2_SF_GET_INUMBER_ARCH(sfp, XFS_DIR2_SF_INUMBERP(sfep), ARCH_CONVERT);
+ ASSERT(XFS_DIR2_SF_GET_OFFSET(sfep) >= offset);
+ ino = XFS_DIR2_SF_GET_INUMBER(sfp, XFS_DIR2_SF_INUMBERP(sfep));
i8count += ino > XFS_DIR2_MAX_SHORT_INUM;
offset =
- XFS_DIR2_SF_GET_OFFSET_ARCH(sfep, ARCH_CONVERT) +
+ XFS_DIR2_SF_GET_OFFSET(sfep) +
XFS_DIR2_DATA_ENTSIZE(sfep->namelen);
}
ASSERT(i8count == sfp->hdr.i8count);
@@ -708,7 +708,7 @@ xfs_dir2_sf_create(
/*
* Now can put in the inode number, since i8count is set.
*/
- XFS_DIR2_SF_PUT_INUMBER_ARCH(sfp, &pino, &sfp->hdr.parent, ARCH_CONVERT);
+ XFS_DIR2_SF_PUT_INUMBER(sfp, &pino, &sfp->hdr.parent);
sfp->hdr.count = 0;
dp->i_d.di_size = size;
xfs_dir2_sf_check(args);
@@ -800,8 +800,7 @@ xfs_dir2_sf_getdents(
XFS_DIR2_DATA_DOTDOT_OFFSET)) {
p.cook = XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk,
XFS_DIR2_DATA_FIRST_OFFSET);
- p.ino = XFS_DIR2_SF_GET_INUMBER_ARCH(sfp, &sfp->hdr.parent,
- ARCH_CONVERT);
+ p.ino = XFS_DIR2_SF_GET_INUMBER(sfp, &sfp->hdr.parent);
#if XFS_BIG_INUMS
p.ino += mp->m_inoadd;
#endif
@@ -826,7 +825,7 @@ xfs_dir2_sf_getdents(
i++, sfep = XFS_DIR2_SF_NEXTENTRY(sfp, sfep)) {
off = XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk,
- XFS_DIR2_SF_GET_OFFSET_ARCH(sfep, ARCH_CONVERT));
+ XFS_DIR2_SF_GET_OFFSET(sfep));
if (dir_offset > off)
continue;
@@ -834,11 +833,10 @@ xfs_dir2_sf_getdents(
p.namelen = sfep->namelen;
p.cook = XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk,
- XFS_DIR2_SF_GET_OFFSET_ARCH(sfep, ARCH_CONVERT) +
+ XFS_DIR2_SF_GET_OFFSET(sfep) +
XFS_DIR2_DATA_ENTSIZE(p.namelen));
- p.ino = XFS_DIR2_SF_GET_INUMBER_ARCH(sfp,
- XFS_DIR2_SF_INUMBERP(sfep), ARCH_CONVERT);
+ p.ino = XFS_DIR2_SF_GET_INUMBER(sfp, XFS_DIR2_SF_INUMBERP(sfep));
#if XFS_BIG_INUMS
p.ino += mp->m_inoadd;
#endif
@@ -904,7 +902,7 @@ xfs_dir2_sf_lookup(
*/
if (args->namelen == 2 &&
args->name[0] == '.' && args->name[1] == '.') {
- args->inumber = XFS_DIR2_SF_GET_INUMBER_ARCH(sfp, &sfp->hdr.parent, ARCH_CONVERT);
+ args->inumber = XFS_DIR2_SF_GET_INUMBER(sfp, &sfp->hdr.parent);
return XFS_ERROR(EEXIST);
}
/*
@@ -917,8 +915,8 @@ xfs_dir2_sf_lookup(
sfep->name[0] == args->name[0] &&
memcmp(args->name, sfep->name, args->namelen) == 0) {
args->inumber =
- XFS_DIR2_SF_GET_INUMBER_ARCH(sfp,
- XFS_DIR2_SF_INUMBERP(sfep), ARCH_CONVERT);
+ XFS_DIR2_SF_GET_INUMBER(sfp,
+ XFS_DIR2_SF_INUMBERP(sfep));
return XFS_ERROR(EEXIST);
}
}
@@ -971,8 +969,8 @@ xfs_dir2_sf_removename(
if (sfep->namelen == args->namelen &&
sfep->name[0] == args->name[0] &&
memcmp(sfep->name, args->name, args->namelen) == 0) {
- ASSERT(XFS_DIR2_SF_GET_INUMBER_ARCH(sfp,
- XFS_DIR2_SF_INUMBERP(sfep), ARCH_CONVERT) ==
+ ASSERT(XFS_DIR2_SF_GET_INUMBER(sfp,
+ XFS_DIR2_SF_INUMBERP(sfep)) ==
args->inumber);
break;
}
@@ -1093,10 +1091,10 @@ xfs_dir2_sf_replace(
if (args->namelen == 2 &&
args->name[0] == '.' && args->name[1] == '.') {
#if XFS_BIG_INUMS || defined(DEBUG)
- ino = XFS_DIR2_SF_GET_INUMBER_ARCH(sfp, &sfp->hdr.parent, ARCH_CONVERT);
+ ino = XFS_DIR2_SF_GET_INUMBER(sfp, &sfp->hdr.parent);
ASSERT(args->inumber != ino);
#endif
- XFS_DIR2_SF_PUT_INUMBER_ARCH(sfp, &args->inumber, &sfp->hdr.parent, ARCH_CONVERT);
+ XFS_DIR2_SF_PUT_INUMBER(sfp, &args->inumber, &sfp->hdr.parent);
}
/*
* Normal entry, look for the name.
@@ -1109,12 +1107,12 @@ xfs_dir2_sf_replace(
sfep->name[0] == args->name[0] &&
memcmp(args->name, sfep->name, args->namelen) == 0) {
#if XFS_BIG_INUMS || defined(DEBUG)
- ino = XFS_DIR2_SF_GET_INUMBER_ARCH(sfp,
- XFS_DIR2_SF_INUMBERP(sfep), ARCH_CONVERT);
+ ino = XFS_DIR2_SF_GET_INUMBER(sfp,
+ XFS_DIR2_SF_INUMBERP(sfep));
ASSERT(args->inumber != ino);
#endif
- XFS_DIR2_SF_PUT_INUMBER_ARCH(sfp, &args->inumber,
- XFS_DIR2_SF_INUMBERP(sfep), ARCH_CONVERT);
+ XFS_DIR2_SF_PUT_INUMBER(sfp, &args->inumber,
+ XFS_DIR2_SF_INUMBERP(sfep));
break;
}
}
@@ -1215,8 +1213,8 @@ xfs_dir2_sf_toino4(
*/
sfp->hdr.count = oldsfp->hdr.count;
sfp->hdr.i8count = 0;
- ino = XFS_DIR2_SF_GET_INUMBER_ARCH(oldsfp, &oldsfp->hdr.parent, ARCH_CONVERT);
- XFS_DIR2_SF_PUT_INUMBER_ARCH(sfp, &ino, &sfp->hdr.parent, ARCH_CONVERT);
+ ino = XFS_DIR2_SF_GET_INUMBER(oldsfp, &oldsfp->hdr.parent);
+ XFS_DIR2_SF_PUT_INUMBER(sfp, &ino, &sfp->hdr.parent);
/*
* Copy the entries field by field.
*/
@@ -1228,9 +1226,9 @@ xfs_dir2_sf_toino4(
sfep->namelen = oldsfep->namelen;
sfep->offset = oldsfep->offset;
memcpy(sfep->name, oldsfep->name, sfep->namelen);
- ino = XFS_DIR2_SF_GET_INUMBER_ARCH(oldsfp,
- XFS_DIR2_SF_INUMBERP(oldsfep), ARCH_CONVERT);
- XFS_DIR2_SF_PUT_INUMBER_ARCH(sfp, &ino, XFS_DIR2_SF_INUMBERP(sfep), ARCH_CONVERT);
+ ino = XFS_DIR2_SF_GET_INUMBER(oldsfp,
+ XFS_DIR2_SF_INUMBERP(oldsfep));
+ XFS_DIR2_SF_PUT_INUMBER(sfp, &ino, XFS_DIR2_SF_INUMBERP(sfep));
}
/*
* Clean up the inode.
@@ -1292,8 +1290,8 @@ xfs_dir2_sf_toino8(
*/
sfp->hdr.count = oldsfp->hdr.count;
sfp->hdr.i8count = 1;
- ino = XFS_DIR2_SF_GET_INUMBER_ARCH(oldsfp, &oldsfp->hdr.parent, ARCH_CONVERT);
- XFS_DIR2_SF_PUT_INUMBER_ARCH(sfp, &ino, &sfp->hdr.parent, ARCH_CONVERT);
+ ino = XFS_DIR2_SF_GET_INUMBER(oldsfp, &oldsfp->hdr.parent);
+ XFS_DIR2_SF_PUT_INUMBER(sfp, &ino, &sfp->hdr.parent);
/*
* Copy the entries field by field.
*/
@@ -1305,9 +1303,9 @@ xfs_dir2_sf_toino8(
sfep->namelen = oldsfep->namelen;
sfep->offset = oldsfep->offset;
memcpy(sfep->name, oldsfep->name, sfep->namelen);
- ino = XFS_DIR2_SF_GET_INUMBER_ARCH(oldsfp,
- XFS_DIR2_SF_INUMBERP(oldsfep), ARCH_CONVERT);
- XFS_DIR2_SF_PUT_INUMBER_ARCH(sfp, &ino, XFS_DIR2_SF_INUMBERP(sfep), ARCH_CONVERT);
+ ino = XFS_DIR2_SF_GET_INUMBER(oldsfp,
+ XFS_DIR2_SF_INUMBERP(oldsfep));
+ XFS_DIR2_SF_PUT_INUMBER(sfp, &ino, XFS_DIR2_SF_INUMBERP(sfep));
}
/*
* Clean up the inode.
diff --git a/fs/xfs/xfs_dir2_sf.h b/fs/xfs/xfs_dir2_sf.h
index 3fea83ecd59cb..bac6f5a2a312a 100644
--- a/fs/xfs/xfs_dir2_sf.h
+++ b/fs/xfs/xfs_dir2_sf.h
@@ -59,21 +59,12 @@ struct xfs_trans;
*/
typedef struct { __uint8_t i[8]; } xfs_dir2_ino8_t;
-#define XFS_DIR2_SF_GET_INO8_ARCH(di,arch) \
- (xfs_ino_t)(DIRINO_GET_ARCH(&di,arch))
-#define XFS_DIR2_SF_GET_INO8(di) \
- XFS_DIR2_SF_GET_INO8_ARCH(di,ARCH_NOCONVERT)
-
/*
* Inode number stored as 4 8-bit values.
* Works a lot of the time, when all the inode numbers in a directory
* fit in 32 bits.
*/
typedef struct { __uint8_t i[4]; } xfs_dir2_ino4_t;
-#define XFS_DIR2_SF_GET_INO4_ARCH(di,arch) \
- (xfs_ino_t)(DIRINO4_GET_ARCH(&di,arch))
-#define XFS_DIR2_SF_GET_INO4(di) \
- XFS_DIR2_SF_GET_INO4_ARCH(di,ARCH_NOCONVERT)
typedef union {
xfs_dir2_ino8_t i8;
@@ -132,51 +123,48 @@ xfs_dir2_inou_t *xfs_dir2_sf_inumberp(xfs_dir2_sf_entry_t *sfep);
#endif
#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_DIR2_SF_GET_INUMBER)
-xfs_intino_t xfs_dir2_sf_get_inumber_arch(xfs_dir2_sf_t *sfp, xfs_dir2_inou_t *from,
- xfs_arch_t arch);
-#define XFS_DIR2_SF_GET_INUMBER_ARCH(sfp, from, arch) \
- xfs_dir2_sf_get_inumber_arch(sfp, from, arch)
+xfs_intino_t xfs_dir2_sf_get_inumber(xfs_dir2_sf_t *sfp, xfs_dir2_inou_t *from);
+#define XFS_DIR2_SF_GET_INUMBER(sfp, from) \
+ xfs_dir2_sf_get_inumber(sfp, from)
#else
-#define XFS_DIR2_SF_GET_INUMBER_ARCH(sfp, from, arch) \
+#define XFS_DIR2_SF_GET_INUMBER(sfp, from) \
((sfp)->hdr.i8count == 0 ? \
- (xfs_intino_t)XFS_DIR2_SF_GET_INO4_ARCH(*(from), arch) : \
- (xfs_intino_t)XFS_DIR2_SF_GET_INO8_ARCH(*(from), arch))
+ (xfs_intino_t)XFS_GET_DIR_INO4((from)->i4) : \
+ (xfs_intino_t)XFS_GET_DIR_INO8((from)->i8))
#endif
#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_DIR2_SF_PUT_INUMBER)
-void xfs_dir2_sf_put_inumber_arch(xfs_dir2_sf_t *sfp, xfs_ino_t *from,
- xfs_dir2_inou_t *to, xfs_arch_t arch);
-#define XFS_DIR2_SF_PUT_INUMBER_ARCH(sfp,from,to,arch) \
- xfs_dir2_sf_put_inumber_arch(sfp,from,to,arch)
+void xfs_dir2_sf_put_inumber(xfs_dir2_sf_t *sfp, xfs_ino_t *from,
+ xfs_dir2_inou_t *to);
+#define XFS_DIR2_SF_PUT_INUMBER(sfp,from,to) \
+ xfs_dir2_sf_put_inumber(sfp,from,to)
#else
-#define XFS_DIR2_SF_PUT_INUMBER_ARCH(sfp,from,to,arch) \
+#define XFS_DIR2_SF_PUT_INUMBER(sfp,from,to) \
if ((sfp)->hdr.i8count == 0) { \
- DIRINO4_COPY_ARCH(from,to,arch); \
+ XFS_PUT_DIR_INO4(*(from), (to)->i4); \
} else { \
- DIRINO_COPY_ARCH(from,to,arch); \
+ XFS_PUT_DIR_INO8(*(from), (to)->i8); \
}
#endif
#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_DIR2_SF_GET_OFFSET)
-xfs_dir2_data_aoff_t xfs_dir2_sf_get_offset_arch(xfs_dir2_sf_entry_t *sfep,
- xfs_arch_t arch);
xfs_dir2_data_aoff_t xfs_dir2_sf_get_offset(xfs_dir2_sf_entry_t *sfep);
-#define XFS_DIR2_SF_GET_OFFSET_ARCH(sfep,arch) \
- xfs_dir2_sf_get_offset_arch(sfep,arch)
+#define XFS_DIR2_SF_GET_OFFSET(sfep) \
+ xfs_dir2_sf_get_offset(sfep)
#else
-#define XFS_DIR2_SF_GET_OFFSET_ARCH(sfep,arch) \
- INT_GET_UNALIGNED_16_ARCH(&(sfep)->offset.i,arch)
+#define XFS_DIR2_SF_GET_OFFSET(sfep) \
+ INT_GET_UNALIGNED_16_BE(&(sfep)->offset.i)
#endif
#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_DIR2_SF_PUT_OFFSET)
-void xfs_dir2_sf_put_offset_arch(xfs_dir2_sf_entry_t *sfep,
- xfs_dir2_data_aoff_t off, xfs_arch_t arch);
-#define XFS_DIR2_SF_PUT_OFFSET_ARCH(sfep,off,arch) \
- xfs_dir2_sf_put_offset_arch(sfep,off,arch)
+void xfs_dir2_sf_put_offset(xfs_dir2_sf_entry_t *sfep,
+ xfs_dir2_data_aoff_t off);
+#define XFS_DIR2_SF_PUT_OFFSET(sfep,off) \
+ xfs_dir2_sf_put_offset(sfep,off)
#else
-#define XFS_DIR2_SF_PUT_OFFSET_ARCH(sfep,off,arch) \
- INT_SET_UNALIGNED_16_ARCH(&(sfep)->offset.i,off,arch)
+#define XFS_DIR2_SF_PUT_OFFSET(sfep,off) \
+ INT_SET_UNALIGNED_16_BE(&(sfep)->offset.i,off)
#endif
#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_DIR2_SF_ENTSIZE_BYNAME)
diff --git a/fs/xfs/xfs_dir_leaf.c b/fs/xfs/xfs_dir_leaf.c
index 2f889ce88f4cc..617018d6bbdc0 100644
--- a/fs/xfs/xfs_dir_leaf.c
+++ b/fs/xfs/xfs_dir_leaf.c
@@ -160,9 +160,9 @@ xfs_dir_shortform_create(xfs_da_args_t *args, xfs_ino_t parent)
ASSERT(dp->i_df.if_bytes == 0);
xfs_idata_realloc(dp, sizeof(*hdr), XFS_DATA_FORK);
hdr = (xfs_dir_sf_hdr_t *)dp->i_df.if_u1.if_data;
- XFS_DIR_SF_PUT_DIRINO_ARCH(&parent, &hdr->parent, ARCH_CONVERT);
+ XFS_DIR_SF_PUT_DIRINO(&parent, &hdr->parent);
- INT_ZERO(hdr->count, ARCH_CONVERT);
+ 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);
@@ -208,7 +208,7 @@ xfs_dir_shortform_addname(xfs_da_args_t *args)
sf = (xfs_dir_shortform_t *)dp->i_df.if_u1.if_data;
sfe = (xfs_dir_sf_entry_t *)((char *)sf + offset);
- XFS_DIR_SF_PUT_DIRINO_ARCH(&args->inumber, &sfe->inumber, ARCH_CONVERT);
+ XFS_DIR_SF_PUT_DIRINO(&args->inumber, &sfe->inumber);
sfe->namelen = args->namelen;
memcpy(sfe->name, args->name, sfe->namelen);
INT_MOD(sf->hdr.count, ARCH_CONVERT, +1);
@@ -298,7 +298,7 @@ xfs_dir_shortform_lookup(xfs_da_args_t *args)
sf = (xfs_dir_shortform_t *)dp->i_df.if_u1.if_data;
if (args->namelen == 2 &&
args->name[0] == '.' && args->name[1] == '.') {
- XFS_DIR_SF_GET_DIRINO_ARCH(&sf->hdr.parent, &args->inumber, ARCH_CONVERT);
+ XFS_DIR_SF_GET_DIRINO(&sf->hdr.parent, &args->inumber);
return(XFS_ERROR(EEXIST));
}
if (args->namelen == 1 && args->name[0] == '.') {
@@ -310,7 +310,7 @@ xfs_dir_shortform_lookup(xfs_da_args_t *args)
if (sfe->namelen == args->namelen &&
sfe->name[0] == args->name[0] &&
memcmp(args->name, sfe->name, args->namelen) == 0) {
- XFS_DIR_SF_GET_DIRINO_ARCH(&sfe->inumber, &args->inumber, ARCH_CONVERT);
+ XFS_DIR_SF_GET_DIRINO(&sfe->inumber, &args->inumber);
return(XFS_ERROR(EEXIST));
}
sfe = XFS_DIR_SF_NEXTENTRY(sfe);
@@ -353,7 +353,7 @@ xfs_dir_shortform_to_leaf(xfs_da_args_t *iargs)
memcpy(tmpbuffer, dp->i_df.if_u1.if_data, size);
sf = (xfs_dir_shortform_t *)tmpbuffer;
- XFS_DIR_SF_GET_DIRINO_ARCH(&sf->hdr.parent, &inumber, ARCH_CONVERT);
+ XFS_DIR_SF_GET_DIRINO(&sf->hdr.parent, &inumber);
xfs_idata_realloc(dp, -size, XFS_DATA_FORK);
dp->i_d.di_size = 0;
@@ -398,7 +398,7 @@ xfs_dir_shortform_to_leaf(xfs_da_args_t *iargs)
args.namelen = sfe->namelen;
args.hashval = xfs_da_hashname((char *)(sfe->name),
sfe->namelen);
- XFS_DIR_SF_GET_DIRINO_ARCH(&sfe->inumber, &args.inumber, ARCH_CONVERT);
+ XFS_DIR_SF_GET_DIRINO(&sfe->inumber, &args.inumber);
retval = xfs_dir_leaf_addname(&args);
if (retval)
goto out;
@@ -470,7 +470,7 @@ xfs_dir_shortform_getdents(xfs_inode_t *dp, uio_t *uio, int *eofp,
sbp->entno = 1;
sbp->seqno = 0;
sbp->hash = xfs_dir_hash_dotdot;
- sbp->ino = XFS_GET_DIR_INO_ARCH(mp, sf->hdr.parent, ARCH_CONVERT);
+ sbp->ino = XFS_GET_DIR_INO8(sf->hdr.parent);
sbp->name = "..";
sbp->namelen = 2;
sbp++;
@@ -494,7 +494,7 @@ xfs_dir_shortform_getdents(xfs_inode_t *dp, uio_t *uio, int *eofp,
sbp->entno = i + 2;
sbp->seqno = 0;
sbp->hash = xfs_da_hashname((char *)sfe->name, sfe->namelen);
- sbp->ino = XFS_GET_DIR_INO_ARCH(mp, sfe->inumber, ARCH_CONVERT);
+ sbp->ino = XFS_GET_DIR_INO8(sfe->inumber);
sbp->name = (char *)sfe->name;
sbp->namelen = sfe->namelen;
sfe = XFS_DIR_SF_NEXTENTRY(sfe);
@@ -612,7 +612,7 @@ xfs_dir_shortform_replace(xfs_da_args_t *args)
if (args->namelen == 2 &&
args->name[0] == '.' && args->name[1] == '.') {
/* XXX - replace assert? */
- XFS_DIR_SF_PUT_DIRINO_ARCH(&args->inumber, &sf->hdr.parent, ARCH_CONVERT);
+ XFS_DIR_SF_PUT_DIRINO(&args->inumber, &sf->hdr.parent);
xfs_trans_log_inode(args->trans, dp, XFS_ILOG_DDATA);
return(0);
}
@@ -624,7 +624,7 @@ xfs_dir_shortform_replace(xfs_da_args_t *args)
memcmp(args->name, sfe->name, args->namelen) == 0) {
ASSERT(memcmp((char *)&args->inumber,
(char *)&sfe->inumber, sizeof(xfs_ino_t)));
- XFS_DIR_SF_PUT_DIRINO_ARCH(&args->inumber, &sfe->inumber, ARCH_CONVERT);
+ XFS_DIR_SF_PUT_DIRINO(&args->inumber, &sfe->inumber);
xfs_trans_log_inode(args->trans, dp, XFS_ILOG_DDATA);
return(0);
}
@@ -675,10 +675,10 @@ xfs_dir_leaf_to_shortform(xfs_da_args_t *iargs)
if ((entry->namelen == 2) &&
(namest->name[0] == '.') &&
(namest->name[1] == '.')) {
- XFS_DIR_SF_GET_DIRINO_ARCH(&namest->inumber, &parent, ARCH_CONVERT);
- INT_ZERO(entry->nameidx, ARCH_CONVERT);
+ XFS_DIR_SF_GET_DIRINO(&namest->inumber, &parent);
+ entry->nameidx = 0;
} else if ((entry->namelen == 1) && (namest->name[0] == '.')) {
- INT_ZERO(entry->nameidx, ARCH_CONVERT);
+ entry->nameidx = 0;
}
}
retval = xfs_da_shrink_inode(iargs, 0, bp);
@@ -701,13 +701,13 @@ xfs_dir_leaf_to_shortform(xfs_da_args_t *iargs)
args.justcheck = 0;
args.addname = args.oknoent = 1;
for (i = 0; i < INT_GET(hdr->count, ARCH_CONVERT); entry++, i++) {
- if (INT_ISZERO(entry->nameidx, ARCH_CONVERT))
+ if (!entry->nameidx)
continue;
namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, INT_GET(entry->nameidx, ARCH_CONVERT));
args.name = (char *)(namest->name);
args.namelen = entry->namelen;
args.hashval = INT_GET(entry->hashval, ARCH_CONVERT);
- XFS_DIR_SF_GET_DIRINO_ARCH(&namest->inumber, &args.inumber, ARCH_CONVERT);
+ XFS_DIR_SF_GET_DIRINO(&namest->inumber, &args.inumber);
xfs_dir_shortform_addname(&args);
}
@@ -801,7 +801,7 @@ xfs_dir_leaf_create(xfs_da_args_t *args, xfs_dablk_t blkno, xfs_dabuf_t **bpp)
hdr = &leaf->hdr;
INT_SET(hdr->info.magic, ARCH_CONVERT, XFS_DIR_LEAF_MAGIC);
INT_SET(hdr->firstused, ARCH_CONVERT, XFS_LBSIZE(dp->i_mount));
- if (INT_ISZERO(hdr->firstused, ARCH_CONVERT))
+ if (!hdr->firstused)
INT_SET(hdr->firstused, ARCH_CONVERT, XFS_LBSIZE(dp->i_mount) - 1);
INT_SET(hdr->freemap[0].base, ARCH_CONVERT, sizeof(xfs_dir_leaf_hdr_t));
INT_SET(hdr->freemap[0].size, ARCH_CONVERT, INT_GET(hdr->firstused, ARCH_CONVERT) - INT_GET(hdr->freemap[0].base, ARCH_CONVERT));
@@ -895,7 +895,7 @@ xfs_dir_leaf_add(xfs_dabuf_t *bp, xfs_da_args_t *args, int index)
sum += INT_GET(map->size, ARCH_CONVERT);
continue;
}
- if (INT_ISZERO(map->size, ARCH_CONVERT))
+ if (!map->size)
continue; /* no space in this map */
tmp = entsize;
if (INT_GET(map->base, ARCH_CONVERT) < INT_GET(hdr->firstused, ARCH_CONVERT))
@@ -995,7 +995,7 @@ xfs_dir_leaf_add_work(xfs_dabuf_t *bp, xfs_da_args_t *args, int index,
* Copy the string and inode number into the new space.
*/
namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, INT_GET(entry->nameidx, ARCH_CONVERT));
- XFS_DIR_SF_PUT_DIRINO_ARCH(&args->inumber, &namest->inumber, ARCH_CONVERT);
+ XFS_DIR_SF_PUT_DIRINO(&args->inumber, &namest->inumber);
memcpy(namest->name, args->name, args->namelen);
xfs_da_log_buf(args->trans, bp,
XFS_DA_LOGRANGE(leaf, namest, XFS_DIR_LEAF_ENTSIZE_BYENTRY(entry)));
@@ -1060,10 +1060,10 @@ xfs_dir_leaf_compact(xfs_trans_t *trans, xfs_dabuf_t *bp, int musthave,
hdr_d = &leaf_d->hdr;
hdr_d->info = hdr_s->info; /* struct copy */
INT_SET(hdr_d->firstused, ARCH_CONVERT, lbsize);
- if (INT_ISZERO(hdr_d->firstused, ARCH_CONVERT))
+ if (!hdr_d->firstused)
INT_SET(hdr_d->firstused, ARCH_CONVERT, lbsize - 1);
- INT_ZERO(hdr_d->namebytes, ARCH_CONVERT);
- INT_ZERO(hdr_d->count, ARCH_CONVERT);
+ hdr_d->namebytes = 0;
+ hdr_d->count = 0;
hdr_d->holes = 0;
INT_SET(hdr_d->freemap[0].base, ARCH_CONVERT, sizeof(xfs_dir_leaf_hdr_t));
INT_SET(hdr_d->freemap[0].size, ARCH_CONVERT, INT_GET(hdr_d->firstused, ARCH_CONVERT) - INT_GET(hdr_d->freemap[0].base, ARCH_CONVERT));
@@ -1366,7 +1366,7 @@ xfs_dir_leaf_toosmall(xfs_da_state_t *state, int *action)
* Make altpath point to the block we want to keep and
* path point to the block we want to drop (this one).
*/
- forward = !INT_ISZERO(info->forw, ARCH_CONVERT);
+ forward = info->forw;
memcpy(&state->altpath, &state->path, sizeof(state->path));
error = xfs_da_path_shift(state, &state->altpath, forward,
0, &retval);
@@ -1515,8 +1515,8 @@ xfs_dir_leaf_remove(xfs_trans_t *trans, xfs_dabuf_t *bp, int index)
map = &hdr->freemap[before];
INT_MOD(map->size, ARCH_CONVERT, entsize);
INT_MOD(map->size, ARCH_CONVERT, INT_GET(hdr->freemap[after].size, ARCH_CONVERT));
- INT_ZERO(hdr->freemap[after].base, ARCH_CONVERT);
- INT_ZERO(hdr->freemap[after].size, ARCH_CONVERT);
+ hdr->freemap[after].base = 0;
+ hdr->freemap[after].size = 0;
} else if (before >= 0) {
map = &hdr->freemap[before];
INT_MOD(map->size, ARCH_CONVERT, entsize);
@@ -1576,7 +1576,7 @@ xfs_dir_leaf_remove(xfs_trans_t *trans, xfs_dabuf_t *bp, int index)
tmp = INT_GET(entry->nameidx, ARCH_CONVERT);
}
INT_SET(hdr->firstused, ARCH_CONVERT, tmp);
- if (INT_ISZERO(hdr->firstused, ARCH_CONVERT))
+ if (!hdr->firstused)
INT_SET(hdr->firstused, ARCH_CONVERT, tmp - 1);
} else {
hdr->holes = 1; /* mark as needing compaction */
@@ -1656,11 +1656,11 @@ xfs_dir_leaf_unbalance(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk,
tmp_leaf = (xfs_dir_leafblock_t *)tmpbuffer;
tmp_hdr = &tmp_leaf->hdr;
tmp_hdr->info = save_hdr->info; /* struct copy */
- INT_ZERO(tmp_hdr->count, ARCH_CONVERT);
+ tmp_hdr->count = 0;
INT_SET(tmp_hdr->firstused, ARCH_CONVERT, state->blocksize);
- if (INT_ISZERO(tmp_hdr->firstused, ARCH_CONVERT))
+ if (!tmp_hdr->firstused)
INT_SET(tmp_hdr->firstused, ARCH_CONVERT, state->blocksize - 1);
- INT_ZERO(tmp_hdr->namebytes, ARCH_CONVERT);
+ tmp_hdr->namebytes = 0;
if (xfs_dir_leaf_order(save_blk->bp, drop_blk->bp)) {
xfs_dir_leaf_moveents(drop_leaf, 0, tmp_leaf, 0,
(int)INT_GET(drop_hdr->count, ARCH_CONVERT), mp);
@@ -1732,7 +1732,7 @@ xfs_dir_leaf_lookup_int(xfs_dabuf_t *bp, xfs_da_args_t *args, int *index)
break;
}
ASSERT((probe >= 0) && \
- ((INT_ISZERO(leaf->hdr.count, ARCH_CONVERT)) || (probe < INT_GET(leaf->hdr.count, ARCH_CONVERT))));
+ ((!leaf->hdr.count) || (probe < INT_GET(leaf->hdr.count, ARCH_CONVERT))));
ASSERT((span <= 4) || (INT_GET(entry->hashval, ARCH_CONVERT) == hashval));
/*
@@ -1761,7 +1761,7 @@ xfs_dir_leaf_lookup_int(xfs_dabuf_t *bp, xfs_da_args_t *args, int *index)
if (entry->namelen == args->namelen &&
namest->name[0] == args->name[0] &&
memcmp(args->name, namest->name, args->namelen) == 0) {
- XFS_DIR_SF_GET_DIRINO_ARCH(&namest->inumber, &args->inumber, ARCH_CONVERT);
+ XFS_DIR_SF_GET_DIRINO(&namest->inumber, &args->inumber);
*index = probe;
return(XFS_ERROR(EEXIST));
}
@@ -1886,8 +1886,8 @@ xfs_dir_leaf_moveents(xfs_dir_leafblock_t *leaf_s, int start_s,
INT_SET(hdr_d->freemap[0].base, ARCH_CONVERT, (uint)sizeof(xfs_dir_leaf_hdr_t));
INT_MOD(hdr_d->freemap[0].base, ARCH_CONVERT, INT_GET(hdr_d->count, ARCH_CONVERT) * (uint)sizeof(xfs_dir_leaf_entry_t));
INT_SET(hdr_d->freemap[0].size, ARCH_CONVERT, INT_GET(hdr_d->firstused, ARCH_CONVERT) - INT_GET(hdr_d->freemap[0].base, ARCH_CONVERT));
- INT_SET(hdr_d->freemap[1].base, ARCH_CONVERT, INT_ZERO(hdr_d->freemap[2].base, ARCH_CONVERT));
- INT_SET(hdr_d->freemap[1].size, ARCH_CONVERT, INT_ZERO(hdr_d->freemap[2].size, ARCH_CONVERT));
+ INT_SET(hdr_d->freemap[1].base, ARCH_CONVERT, (hdr_d->freemap[2].base = 0));
+ INT_SET(hdr_d->freemap[1].size, ARCH_CONVERT, (hdr_d->freemap[2].size = 0));
hdr_s->holes = 1; /* leaf may not be compact */
}
@@ -1925,7 +1925,7 @@ xfs_dir_leaf_lasthash(xfs_dabuf_t *bp, int *count)
ASSERT(INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) == XFS_DIR_LEAF_MAGIC);
if (count)
*count = INT_GET(leaf->hdr.count, ARCH_CONVERT);
- if (INT_ISZERO(leaf->hdr.count, ARCH_CONVERT))
+ if (!leaf->hdr.count)
return(0);
return(INT_GET(leaf->entries[ INT_GET(leaf->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT));
}
@@ -2140,7 +2140,7 @@ xfs_dir_leaf_getdents_int(
* then restore the UIO to the first entry in the current
* run of equal-hashval entries (probably one 1 entry long).
*/
- p.ino = XFS_GET_DIR_INO_ARCH(mp, namest->inumber, ARCH_CONVERT);
+ p.ino = XFS_GET_DIR_INO8(namest->inumber);
#if XFS_BIG_INUMS
p.ino += mp->m_inoadd;
#endif
diff --git a/fs/xfs/xfs_dir_leaf.h b/fs/xfs/xfs_dir_leaf.h
index ad74774011d21..00d68d33cc7a3 100644
--- a/fs/xfs/xfs_dir_leaf.h
+++ b/fs/xfs/xfs_dir_leaf.h
@@ -140,11 +140,6 @@ 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))
-#define XFS_GET_DIR_INO_ARCH(mp,di,arch) \
- DIRINO_GET_ARCH(&(di),arch)
-#define XFS_GET_DIR_INO(mp,di) \
- XFS_GET_DIR_INO_ARCH(mp,di,ARCH_NOCONVERT)
-
typedef struct xfs_dir_put_args
{
xfs_dircook_t cook; /* cookie of (next) entry */
diff --git a/fs/xfs/xfs_dir_sf.h b/fs/xfs/xfs_dir_sf.h
index a363d1a01356c..a61bcfc2a87d2 100644
--- a/fs/xfs/xfs_dir_sf.h
+++ b/fs/xfs/xfs_dir_sf.h
@@ -77,22 +77,16 @@ typedef struct xfs_dir_sf_sort {
} xfs_dir_sf_sort_t;
#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_DIR_SF_GET_DIRINO)
-void xfs_dir_sf_get_dirino_arch(xfs_dir_ino_t *from, xfs_ino_t *to, xfs_arch_t arch);
void xfs_dir_sf_get_dirino(xfs_dir_ino_t *from, xfs_ino_t *to);
-#define XFS_DIR_SF_GET_DIRINO_ARCH(from,to,arch) xfs_dir_sf_get_dirino_arch(from, to, arch)
#define XFS_DIR_SF_GET_DIRINO(from,to) xfs_dir_sf_get_dirino(from, to)
#else
-#define XFS_DIR_SF_GET_DIRINO_ARCH(from,to,arch) DIRINO_COPY_ARCH(from,to,arch)
-#define XFS_DIR_SF_GET_DIRINO(from,to) DIRINO_COPY_ARCH(from,to,ARCH_NOCONVERT)
+#define XFS_DIR_SF_GET_DIRINO(from,to) (*(to) = XFS_GET_DIR_INO8(*from))
#endif
#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_DIR_SF_PUT_DIRINO)
-void xfs_dir_sf_put_dirino_arch(xfs_ino_t *from, xfs_dir_ino_t *to, xfs_arch_t arch);
void xfs_dir_sf_put_dirino(xfs_ino_t *from, xfs_dir_ino_t *to);
-#define XFS_DIR_SF_PUT_DIRINO_ARCH(from,to,arch) xfs_dir_sf_put_dirino_arch(from, to, arch)
-#define XFS_DIR_SF_PUT_DIRINO(from,to) xfs_dir_sf_put_dirino(from, to)
+#define XFS_DIR_SF_PUT_DIRINO(from,to) xfs_dir_sf_put_dirino(from, to)
#else
-#define XFS_DIR_SF_PUT_DIRINO_ARCH(from,to,arch) DIRINO_COPY_ARCH(from,to,arch)
-#define XFS_DIR_SF_PUT_DIRINO(from,to) DIRINO_COPY_ARCH(from,to,ARCH_NOCONVERT)
+#define XFS_DIR_SF_PUT_DIRINO(from,to) XFS_PUT_DIR_INO8(*(from), *(to))
#endif
#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_DIR_SF_ENTSIZE_BYNAME)
int xfs_dir_sf_entsize_byname(int len);
diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c
index ebc2f27ce9e1b..21213057c27f9 100644
--- a/fs/xfs/xfs_fsops.c
+++ b/fs/xfs/xfs_fsops.c
@@ -220,9 +220,9 @@ xfs_growfs_data_private(
XFS_CNT_BLOCK(mp));
INT_SET(agf->agf_levels[XFS_BTNUM_BNOi], ARCH_CONVERT, 1);
INT_SET(agf->agf_levels[XFS_BTNUM_CNTi], ARCH_CONVERT, 1);
- INT_ZERO(agf->agf_flfirst, ARCH_CONVERT);
+ agf->agf_flfirst = 0;
INT_SET(agf->agf_fllast, ARCH_CONVERT, XFS_AGFL_SIZE(mp) - 1);
- INT_ZERO(agf->agf_flcount, ARCH_CONVERT);
+ agf->agf_flcount = 0;
tmpsize = agsize - XFS_PREALLOC_BLOCKS(mp);
INT_SET(agf->agf_freeblks, ARCH_CONVERT, tmpsize);
INT_SET(agf->agf_longest, ARCH_CONVERT, tmpsize);
@@ -242,10 +242,10 @@ xfs_growfs_data_private(
INT_SET(agi->agi_versionnum, ARCH_CONVERT, XFS_AGI_VERSION);
INT_SET(agi->agi_seqno, ARCH_CONVERT, agno);
INT_SET(agi->agi_length, ARCH_CONVERT, agsize);
- INT_ZERO(agi->agi_count, ARCH_CONVERT);
+ agi->agi_count = 0;
INT_SET(agi->agi_root, ARCH_CONVERT, XFS_IBT_BLOCK(mp));
INT_SET(agi->agi_level, ARCH_CONVERT, 1);
- INT_ZERO(agi->agi_freecount, ARCH_CONVERT);
+ agi->agi_freecount = 0;
INT_SET(agi->agi_newino, ARCH_CONVERT, NULLAGINO);
INT_SET(agi->agi_dirino, ARCH_CONVERT, NULLAGINO);
for (bucket = 0; bucket < XFS_AGI_UNLINKED_BUCKETS; bucket++)
@@ -264,7 +264,7 @@ xfs_growfs_data_private(
block = XFS_BUF_TO_SBLOCK(bp);
memset(block, 0, mp->m_sb.sb_blocksize);
INT_SET(block->bb_magic, ARCH_CONVERT, XFS_ABTB_MAGIC);
- INT_ZERO(block->bb_level, ARCH_CONVERT);
+ block->bb_level = 0;
INT_SET(block->bb_numrecs, ARCH_CONVERT, 1);
INT_SET(block->bb_leftsib, ARCH_CONVERT, NULLAGBLOCK);
INT_SET(block->bb_rightsib, ARCH_CONVERT, NULLAGBLOCK);
@@ -287,7 +287,7 @@ xfs_growfs_data_private(
block = XFS_BUF_TO_SBLOCK(bp);
memset(block, 0, mp->m_sb.sb_blocksize);
INT_SET(block->bb_magic, ARCH_CONVERT, XFS_ABTC_MAGIC);
- INT_ZERO(block->bb_level, ARCH_CONVERT);
+ block->bb_level = 0;
INT_SET(block->bb_numrecs, ARCH_CONVERT, 1);
INT_SET(block->bb_leftsib, ARCH_CONVERT, NULLAGBLOCK);
INT_SET(block->bb_rightsib, ARCH_CONVERT, NULLAGBLOCK);
@@ -311,8 +311,8 @@ xfs_growfs_data_private(
block = XFS_BUF_TO_SBLOCK(bp);
memset(block, 0, mp->m_sb.sb_blocksize);
INT_SET(block->bb_magic, ARCH_CONVERT, XFS_IBT_MAGIC);
- INT_ZERO(block->bb_level, ARCH_CONVERT);
- INT_ZERO(block->bb_numrecs, ARCH_CONVERT);
+ block->bb_level = 0;
+ block->bb_numrecs = 0;
INT_SET(block->bb_leftsib, ARCH_CONVERT, NULLAGBLOCK);
INT_SET(block->bb_rightsib, ARCH_CONVERT, NULLAGBLOCK);
error = xfs_bwrite(mp, bp);
@@ -393,7 +393,7 @@ xfs_growfs_data_private(
break;
}
sbp = XFS_BUF_TO_SBP(bp);
- xfs_xlatesb(sbp, &mp->m_sb, -1, ARCH_CONVERT, XFS_SB_ALL_BITS);
+ xfs_xlatesb(sbp, &mp->m_sb, -1, XFS_SB_ALL_BITS);
/*
* If we get an error writing out the alternate superblocks,
* just issue a warning and continue. The real work is
diff --git a/fs/xfs/xfs_ialloc.c b/fs/xfs/xfs_ialloc.c
index 76ffe4a8b4fe1..ce5fee9eaec5e 100644
--- a/fs/xfs/xfs_ialloc.c
+++ b/fs/xfs/xfs_ialloc.c
@@ -580,7 +580,7 @@ xfs_dialloc(
* allocation groups upward, wrapping at the end.
*/
*alloc_done = B_FALSE;
- while (INT_ISZERO(agi->agi_freecount, ARCH_CONVERT)) {
+ while (!agi->agi_freecount) {
/*
* Don't do anything if we're not supposed to allocate
* any blocks, just go on to the next ag.
@@ -662,7 +662,7 @@ nextag:
XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
do {
if ((error = xfs_inobt_get_rec(cur, &rec.ir_startino,
- &rec.ir_freecount, &rec.ir_free, &i, ARCH_NOCONVERT)))
+ &rec.ir_freecount, &rec.ir_free, &i)))
goto error0;
XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
freecount += rec.ir_freecount;
@@ -682,7 +682,7 @@ nextag:
goto error0;
if (i != 0 &&
(error = xfs_inobt_get_rec(cur, &rec.ir_startino,
- &rec.ir_freecount, &rec.ir_free, &j, ARCH_NOCONVERT)) == 0 &&
+ &rec.ir_freecount, &rec.ir_free, &j)) == 0 &&
j == 1 &&
rec.ir_freecount > 0) {
/*
@@ -717,7 +717,7 @@ nextag:
if ((error = xfs_inobt_get_rec(tcur,
&trec.ir_startino,
&trec.ir_freecount,
- &trec.ir_free, &i, ARCH_NOCONVERT)))
+ &trec.ir_free, &i)))
goto error1;
XFS_WANT_CORRUPTED_GOTO(i == 1, error1);
}
@@ -731,7 +731,7 @@ nextag:
if ((error = xfs_inobt_get_rec(cur,
&rec.ir_startino,
&rec.ir_freecount,
- &rec.ir_free, &i, ARCH_NOCONVERT)))
+ &rec.ir_free, &i)))
goto error1;
XFS_WANT_CORRUPTED_GOTO(i == 1, error1);
}
@@ -795,7 +795,7 @@ nextag:
tcur,
&trec.ir_startino,
&trec.ir_freecount,
- &trec.ir_free, &i, ARCH_NOCONVERT)))
+ &trec.ir_free, &i)))
goto error1;
XFS_WANT_CORRUPTED_GOTO(i == 1,
error1);
@@ -815,7 +815,7 @@ nextag:
cur,
&rec.ir_startino,
&rec.ir_freecount,
- &rec.ir_free, &i, ARCH_NOCONVERT)))
+ &rec.ir_free, &i)))
goto error1;
XFS_WANT_CORRUPTED_GOTO(i == 1,
error1);
@@ -835,7 +835,7 @@ nextag:
goto error0;
if (i == 1 &&
(error = xfs_inobt_get_rec(cur, &rec.ir_startino,
- &rec.ir_freecount, &rec.ir_free, &j, ARCH_NOCONVERT)) == 0 &&
+ &rec.ir_freecount, &rec.ir_free, &j)) == 0 &&
j == 1 &&
rec.ir_freecount > 0) {
/*
@@ -856,7 +856,7 @@ nextag:
if ((error = xfs_inobt_get_rec(cur,
&rec.ir_startino,
&rec.ir_freecount, &rec.ir_free,
- &i, ARCH_NOCONVERT)))
+ &i)))
goto error0;
XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
if (rec.ir_freecount > 0)
@@ -873,7 +873,7 @@ nextag:
ASSERT((XFS_AGINO_TO_OFFSET(mp, rec.ir_startino) %
XFS_INODES_PER_CHUNK) == 0);
ino = XFS_AGINO_TO_INO(mp, agno, rec.ir_startino + offset);
- XFS_INOBT_CLR_FREE(&rec, offset, ARCH_NOCONVERT);
+ XFS_INOBT_CLR_FREE(&rec, offset);
rec.ir_freecount--;
if ((error = xfs_inobt_update(cur, rec.ir_startino, rec.ir_freecount,
rec.ir_free)))
@@ -891,7 +891,7 @@ nextag:
goto error0;
do {
if ((error = xfs_inobt_get_rec(cur, &rec.ir_startino,
- &rec.ir_freecount, &rec.ir_free, &i, ARCH_NOCONVERT)))
+ &rec.ir_freecount, &rec.ir_free, &i)))
goto error0;
XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
freecount += rec.ir_freecount;
@@ -998,7 +998,7 @@ xfs_difree(
goto error0;
do {
if ((error = xfs_inobt_get_rec(cur, &rec.ir_startino,
- &rec.ir_freecount, &rec.ir_free, &i, ARCH_NOCONVERT)))
+ &rec.ir_freecount, &rec.ir_free, &i)))
goto error0;
if (i) {
freecount += rec.ir_freecount;
@@ -1021,7 +1021,7 @@ xfs_difree(
}
XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
if ((error = xfs_inobt_get_rec(cur, &rec.ir_startino, &rec.ir_freecount,
- &rec.ir_free, &i, ARCH_NOCONVERT))) {
+ &rec.ir_free, &i))) {
cmn_err(CE_WARN,
"xfs_difree: xfs_inobt_get_rec() returned an error %d on %s. Returning error.",
error, mp->m_fsname);
@@ -1033,11 +1033,11 @@ xfs_difree(
*/
off = agino - rec.ir_startino;
ASSERT(off >= 0 && off < XFS_INODES_PER_CHUNK);
- ASSERT(!XFS_INOBT_IS_FREE(&rec, off, ARCH_NOCONVERT));
+ ASSERT(!XFS_INOBT_IS_FREE(&rec, off));
/*
* Mark the inode free & increment the count.
*/
- XFS_INOBT_SET_FREE(&rec, off, ARCH_NOCONVERT);
+ XFS_INOBT_SET_FREE(&rec, off);
rec.ir_freecount++;
/*
@@ -1103,8 +1103,7 @@ xfs_difree(
if ((error = xfs_inobt_get_rec(cur,
&rec.ir_startino,
&rec.ir_freecount,
- &rec.ir_free, &i,
- ARCH_NOCONVERT)))
+ &rec.ir_free, &i)))
goto error0;
if (i) {
freecount += rec.ir_freecount;
@@ -1232,7 +1231,7 @@ xfs_dilocate(
goto error0;
}
if ((error = xfs_inobt_get_rec(cur, &chunk_agino, &chunk_cnt,
- &chunk_free, &i, ARCH_NOCONVERT))) {
+ &chunk_free, &i))) {
#ifdef DEBUG
xfs_fs_cmn_err(CE_ALERT, mp, "xfs_dilocate: "
"xfs_inobt_get_rec() failed");
@@ -1392,7 +1391,7 @@ xfs_ialloc_read_agi(
int i;
for (i = 0; i < XFS_AGI_UNLINKED_BUCKETS; i++)
- ASSERT(!INT_ISZERO(agi->agi_unlinked[i], ARCH_CONVERT));
+ ASSERT(agi->agi_unlinked[i]);
}
#endif
diff --git a/fs/xfs/xfs_ialloc_btree.c b/fs/xfs/xfs_ialloc_btree.c
index 804fc4bc3711f..2d4daecec9905 100644
--- a/fs/xfs/xfs_ialloc_btree.c
+++ b/fs/xfs/xfs_ialloc_btree.c
@@ -1801,8 +1801,7 @@ xfs_inobt_get_rec(
xfs_agino_t *ino, /* output: starting inode of chunk */
__int32_t *fcnt, /* output: number of free inodes */
xfs_inofree_t *free, /* output: free inode mask */
- int *stat, /* output: success/failure */
- xfs_arch_t arch) /* input: architecture */
+ int *stat) /* output: success/failure */
{
xfs_inobt_block_t *block; /* btree block */
xfs_buf_t *bp; /* buffer containing btree block */
@@ -1830,16 +1829,9 @@ xfs_inobt_get_rec(
* Point to the record and extract its data.
*/
rec = XFS_INOBT_REC_ADDR(block, ptr, cur);
- ASSERT(arch == ARCH_NOCONVERT || arch == ARCH_CONVERT);
- if (arch == ARCH_NOCONVERT) {
- *ino = INT_GET(rec->ir_startino, ARCH_CONVERT);
- *fcnt = INT_GET(rec->ir_freecount, ARCH_CONVERT);
- *free = INT_GET(rec->ir_free, ARCH_CONVERT);
- } else {
- INT_COPY(*ino, rec->ir_startino, ARCH_CONVERT);
- INT_COPY(*fcnt, rec->ir_freecount, ARCH_CONVERT);
- INT_COPY(*free, rec->ir_free, ARCH_CONVERT);
- }
+ *ino = INT_GET(rec->ir_startino, ARCH_CONVERT);
+ *fcnt = INT_GET(rec->ir_freecount, ARCH_CONVERT);
+ *free = INT_GET(rec->ir_free, ARCH_CONVERT);
*stat = 1;
return 0;
}
diff --git a/fs/xfs/xfs_ialloc_btree.h b/fs/xfs/xfs_ialloc_btree.h
index dbda2ed8128e3..803c4d17a057b 100644
--- a/fs/xfs/xfs_ialloc_btree.h
+++ b/fs/xfs/xfs_ialloc_btree.h
@@ -99,23 +99,22 @@ xfs_inofree_t xfs_inobt_mask(int i);
#define XFS_INOBT_MASK(i) ((xfs_inofree_t)1 << (i))
#endif
#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_INOBT_IS_FREE)
-int xfs_inobt_is_free(xfs_inobt_rec_t *rp, int i, xfs_arch_t arch);
-#define XFS_INOBT_IS_FREE(rp,i,arch) xfs_inobt_is_free(rp,i,arch)
+int xfs_inobt_is_free(xfs_inobt_rec_t *rp, int i);
+#define XFS_INOBT_IS_FREE(rp,i) xfs_inobt_is_free(rp,i)
#else
-#define XFS_INOBT_IS_FREE(rp,i,arch) ((INT_GET((rp)->ir_free, arch) \
- & XFS_INOBT_MASK(i)) != 0)
+#define XFS_INOBT_IS_FREE(rp,i) (((rp)->ir_free & XFS_INOBT_MASK(i)) != 0)
#endif
#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_INOBT_SET_FREE)
-void xfs_inobt_set_free(xfs_inobt_rec_t *rp, int i, xfs_arch_t arch);
-#define XFS_INOBT_SET_FREE(rp,i,arch) xfs_inobt_set_free(rp,i,arch)
+void xfs_inobt_set_free(xfs_inobt_rec_t *rp, int i);
+#define XFS_INOBT_SET_FREE(rp,i) xfs_inobt_set_free(rp,i)
#else
-#define XFS_INOBT_SET_FREE(rp,i,arch) (INT_MOD_EXPR((rp)->ir_free, arch, |= XFS_INOBT_MASK(i)))
+#define XFS_INOBT_SET_FREE(rp,i) ((rp)->ir_free |= XFS_INOBT_MASK(i))
#endif
#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_INOBT_CLR_FREE)
-void xfs_inobt_clr_free(xfs_inobt_rec_t *rp, int i, xfs_arch_t arch);
-#define XFS_INOBT_CLR_FREE(rp,i,arch) xfs_inobt_clr_free(rp,i,arch)
+void xfs_inobt_clr_free(xfs_inobt_rec_t *rp, int i);
+#define XFS_INOBT_CLR_FREE(rp,i) xfs_inobt_clr_free(rp,i)
#else
-#define XFS_INOBT_CLR_FREE(rp,i,arch) (INT_MOD_EXPR((rp)->ir_free, arch, &= ~XFS_INOBT_MASK(i)))
+#define XFS_INOBT_CLR_FREE(rp,i) ((rp)->ir_free &= ~XFS_INOBT_MASK(i))
#endif
/*
@@ -244,8 +243,7 @@ xfs_inobt_get_rec(
xfs_agino_t *ino, /* output: starting inode of chunk */
__int32_t *fcnt, /* output: number of free inodes */
xfs_inofree_t *free, /* output: free inode mask */
- int *stat, /* output: success/failure */
- xfs_arch_t arch); /* output: architecture */
+ int *stat); /* output: success/failure */
/*
* Increment cursor by one record at the level.
diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c
index 1bf1cc15bdcd5..3a0ba1dfd0e87 100644
--- a/fs/xfs/xfs_iget.c
+++ b/fs/xfs/xfs_iget.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
@@ -61,7 +61,8 @@
* Initialize the inode hash table for the newly mounted file system.
* Choose an initial table size based on user specified value, else
* use a simple algorithm using the maximum number of inodes as an
- * indicator for table size, and cap it at 16 pages (gettin' big).
+ * indicator for table size, and clamp it between one and some large
+ * number of pages.
*/
void
xfs_ihash_init(xfs_mount_t *mp)
@@ -72,8 +73,10 @@ xfs_ihash_init(xfs_mount_t *mp)
if (!mp->m_ihsize) {
icount = mp->m_maxicount ? mp->m_maxicount :
(mp->m_sb.sb_dblocks << mp->m_sb.sb_inopblog);
- mp->m_ihsize = 1 << max_t(uint, xfs_highbit64(icount) / 3, 8);
- mp->m_ihsize = min_t(uint, mp->m_ihsize, 16 * PAGE_SIZE);
+ mp->m_ihsize = 1 << max_t(uint, 8,
+ (xfs_highbit64(icount) + 1) / 2);
+ mp->m_ihsize = min_t(uint, mp->m_ihsize,
+ (64 * NBPP) / sizeof(xfs_ihash_t));
}
while (!(mp->m_ihash = (xfs_ihash_t *)kmem_zalloc(mp->m_ihsize *
@@ -490,6 +493,11 @@ inode_allocate:
goto retry;
}
+ if (is_bad_inode(inode)) {
+ iput(inode);
+ return EIO;
+ }
+
bdp = vn_bhv_lookup(VN_BHV_HEAD(vp), &xfs_vnodeops);
if (bdp == NULL) {
XFS_STATS_INC(xs_ig_dup);
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index 5573702347ed6..43c632ab86adc 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -135,11 +135,11 @@ xfs_inobp_check(
for (i = 0; i < j; i++) {
dip = (xfs_dinode_t *)xfs_buf_offset(bp,
i * mp->m_sb.sb_inodesize);
- if (INT_ISZERO(dip->di_next_unlinked, ARCH_CONVERT)) {
+ if (!dip->di_next_unlinked) {
xfs_fs_cmn_err(CE_ALERT, mp,
"Detected a bogus zero next_unlinked field in incore inode buffer 0x%p. About to pop an ASSERT.",
bp);
- ASSERT(!INT_ISZERO(dip->di_next_unlinked, ARCH_CONVERT));
+ ASSERT(dip->di_next_unlinked);
}
}
}
@@ -176,7 +176,7 @@ xfs_inobp_bwcheck(xfs_buf_t *bp)
xfs_fs_cmn_err(CE_WARN, mp,
"corrupt, unmount and run xfs_repair");
}
- if (INT_ISZERO(dip->di_next_unlinked, ARCH_CONVERT)) {
+ if (!dip->di_next_unlinked) {
cmn_err(CE_WARN,
"Bad next_unlinked field (0) in XFS inode buffer 0x%p, starting blockno %Ld, offset 0x%x",
(__uint64_t)(__psunsigned_t) bp,
@@ -520,8 +520,7 @@ xfs_iformat(
}
di_size = INT_GET(dip->di_core.di_size, ARCH_CONVERT);
- if (unlikely(di_size >
- XFS_DFORK_DSIZE_ARCH(dip, ip->i_mount, 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.",
(unsigned long long) ip->i_ino,
@@ -555,7 +554,7 @@ xfs_iformat(
if (error) {
return error;
}
- if (!XFS_DFORK_Q_ARCH(dip, ARCH_CONVERT))
+ if (!XFS_DFORK_Q(dip))
return 0;
ASSERT(ip->i_afp == NULL);
ip->i_afp = kmem_zone_zalloc(xfs_ifork_zone, KM_SLEEP);
@@ -563,7 +562,7 @@ xfs_iformat(
XFS_IFORK_ASIZE(ip) / (uint)sizeof(xfs_bmbt_rec_t);
switch (INT_GET(dip->di_core.di_aformat, ARCH_CONVERT)) {
case XFS_DINODE_FMT_LOCAL:
- atp = (xfs_attr_shortform_t *)XFS_DFORK_APTR_ARCH(dip, ARCH_CONVERT);
+ atp = (xfs_attr_shortform_t *)XFS_DFORK_APTR(dip);
size = (int)INT_GET(atp->hdr.totsize, ARCH_CONVERT);
error = xfs_iformat_local(ip, dip, XFS_ATTR_FORK, size);
break;
@@ -610,11 +609,11 @@ xfs_iformat_local(
* is wrong and we just bail out rather than crash in
* kmem_alloc() or memcpy() below.
*/
- if (unlikely(size > XFS_DFORK_SIZE_ARCH(dip, ip->i_mount, whichfork, ARCH_CONVERT))) {
+ 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.",
(unsigned long long) ip->i_ino, size,
- XFS_DFORK_SIZE_ARCH(dip, ip->i_mount, whichfork, ARCH_CONVERT));
+ XFS_DFORK_SIZE(dip, ip->i_mount, whichfork));
XFS_CORRUPTION_ERROR("xfs_iformat_local", XFS_ERRLEVEL_LOW,
ip->i_mount, dip);
return XFS_ERROR(EFSCORRUPTED);
@@ -632,8 +631,7 @@ xfs_iformat_local(
ifp->if_bytes = size;
ifp->if_real_bytes = real_size;
if (size)
- memcpy(ifp->if_u1.if_data,
- XFS_DFORK_PTR_ARCH(dip, whichfork, ARCH_CONVERT), size);
+ memcpy(ifp->if_u1.if_data, XFS_DFORK_PTR(dip, whichfork), size);
ifp->if_flags &= ~XFS_IFEXTENTS;
ifp->if_flags |= XFS_IFINLINE;
return 0;
@@ -662,7 +660,7 @@ xfs_iformat_extents(
int i;
ifp = XFS_IFORK_PTR(ip, whichfork);
- nex = XFS_DFORK_NEXTENTS_ARCH(dip, whichfork, ARCH_CONVERT);
+ nex = XFS_DFORK_NEXTENTS(dip, whichfork);
size = nex * (uint)sizeof(xfs_bmbt_rec_t);
/*
@@ -670,7 +668,7 @@ xfs_iformat_extents(
* is wrong and we just bail out rather than crash in
* kmem_alloc() or memcpy() below.
*/
- if (unlikely(size < 0 || size > XFS_DFORK_SIZE_ARCH(dip, ip->i_mount, whichfork, ARCH_CONVERT))) {
+ 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.",
(unsigned long long) ip->i_ino, nex);
@@ -692,8 +690,7 @@ xfs_iformat_extents(
ifp->if_bytes = size;
ifp->if_real_bytes = real_size;
if (size) {
- dp = (xfs_bmbt_rec_t *)
- XFS_DFORK_PTR_ARCH(dip, whichfork, ARCH_CONVERT);
+ dp = (xfs_bmbt_rec_t *) XFS_DFORK_PTR(dip, whichfork);
xfs_validate_extents(dp, nex, 1, XFS_EXTFMT_INODE(ip));
ep = ifp->if_u1.if_extents;
for (i = 0; i < nex; i++, ep++, dp++) {
@@ -739,7 +736,7 @@ xfs_iformat_btree(
int size;
ifp = XFS_IFORK_PTR(ip, whichfork);
- dfp = (xfs_bmdr_block_t *)XFS_DFORK_PTR_ARCH(dip, whichfork, ARCH_CONVERT);
+ dfp = (xfs_bmdr_block_t *)XFS_DFORK_PTR(dip, whichfork);
size = XFS_BMAP_BROOT_SPACE(dfp);
nrecs = XFS_BMAP_BROOT_NUMRECS(dfp);
@@ -752,7 +749,7 @@ xfs_iformat_btree(
*/
if (unlikely(XFS_IFORK_NEXTENTS(ip, whichfork) <= ifp->if_ext_max
|| XFS_BMDR_SPACE_CALC(nrecs) >
- XFS_DFORK_SIZE_ARCH(dip, ip->i_mount, whichfork, ARCH_CONVERT)
+ 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.",
@@ -769,7 +766,7 @@ xfs_iformat_btree(
* Copy and convert from the on-disk structure
* to the in-memory structure.
*/
- xfs_bmdr_to_bmbt(dfp, XFS_DFORK_SIZE_ARCH(dip, ip->i_mount, whichfork, ARCH_CONVERT),
+ xfs_bmdr_to_bmbt(dfp, XFS_DFORK_SIZE(dip, ip->i_mount, whichfork),
ifp->if_broot, size);
ifp->if_flags &= ~XFS_IFEXTENTS;
ifp->if_flags |= XFS_IFBROOT;
@@ -785,29 +782,18 @@ xfs_iformat_btree(
* dip = native representation
* dir = direction - +ve -> disk to native
* -ve -> native to disk
- * arch = on-disk architecture
*/
void
xfs_xlate_dinode_core(
xfs_caddr_t buf,
xfs_dinode_core_t *dip,
- int dir,
- xfs_arch_t arch)
+ int dir)
{
xfs_dinode_core_t *buf_core = (xfs_dinode_core_t *)buf;
xfs_dinode_core_t *mem_core = (xfs_dinode_core_t *)dip;
+ xfs_arch_t arch = ARCH_CONVERT;
ASSERT(dir);
- if (arch == ARCH_NOCONVERT) {
- if (dir > 0) {
- memcpy((xfs_caddr_t)mem_core, (xfs_caddr_t)buf_core,
- sizeof(xfs_dinode_core_t));
- } else {
- memcpy((xfs_caddr_t)buf_core, (xfs_caddr_t)mem_core,
- sizeof(xfs_dinode_core_t));
- }
- return;
- }
INT_XLATE(buf_core->di_magic, mem_core->di_magic, dir, arch);
INT_XLATE(buf_core->di_mode, mem_core->di_mode, dir, arch);
@@ -854,16 +840,13 @@ xfs_xlate_dinode_core(
INT_XLATE(buf_core->di_gen, mem_core->di_gen, dir, arch);
}
-uint
-xfs_dic2xflags(
+STATIC uint
+_xfs_dic2xflags(
xfs_dinode_core_t *dic,
- xfs_arch_t arch)
+ __uint16_t di_flags)
{
- __uint16_t di_flags;
- uint flags;
+ uint flags = 0;
- di_flags = INT_GET(dic->di_flags, arch);
- flags = XFS_CFORK_Q_ARCH(dic, arch) ? XFS_XFLAG_HASATTR : 0;
if (di_flags & XFS_DIFLAG_ANY) {
if (di_flags & XFS_DIFLAG_REALTIME)
flags |= XFS_XFLAG_REALTIME;
@@ -886,9 +869,28 @@ xfs_dic2xflags(
if (di_flags & XFS_DIFLAG_NOSYMLINKS)
flags |= XFS_XFLAG_NOSYMLINKS;
}
+
return flags;
}
+uint
+xfs_ip2xflags(
+ xfs_inode_t *ip)
+{
+ xfs_dinode_core_t *dic = &ip->i_d;
+
+ return _xfs_dic2xflags(dic, dic->di_flags) |
+ (XFS_CFORK_Q(dic) ? XFS_XFLAG_HASATTR : 0);
+}
+
+uint
+xfs_dic2xflags(
+ xfs_dinode_core_t *dic)
+{
+ return _xfs_dic2xflags(dic, INT_GET(dic->di_flags, ARCH_CONVERT)) |
+ (XFS_CFORK_Q_DISK(dic) ? XFS_XFLAG_HASATTR : 0);
+}
+
/*
* Given a mount structure and an inode number, return a pointer
* to a newly allocated in-core inode coresponding to the given
@@ -974,9 +976,9 @@ xfs_iread(
* specific information.
* Otherwise, just get the truly permanent information.
*/
- if (!INT_ISZERO(dip->di_core.di_mode, ARCH_CONVERT)) {
+ if (dip->di_core.di_mode) {
xfs_xlate_dinode_core((xfs_caddr_t)&dip->di_core,
- &(ip->i_d), 1, ARCH_CONVERT);
+ &(ip->i_d), 1);
error = xfs_iformat(ip, dip);
if (error) {
kmem_zone_free(xfs_inode_zone, ip);
@@ -1931,7 +1933,7 @@ xfs_iunlink(
agino = XFS_INO_TO_AGINO(mp, ip->i_ino);
ASSERT(agino != 0);
bucket_index = agino % XFS_AGI_UNLINKED_BUCKETS;
- ASSERT(!INT_ISZERO(agi->agi_unlinked[bucket_index], ARCH_CONVERT));
+ ASSERT(agi->agi_unlinked[bucket_index]);
ASSERT(INT_GET(agi->agi_unlinked[bucket_index], ARCH_CONVERT) != agino);
if (INT_GET(agi->agi_unlinked[bucket_index], ARCH_CONVERT) != NULLAGINO) {
@@ -1946,7 +1948,7 @@ xfs_iunlink(
return error;
}
ASSERT(INT_GET(dip->di_next_unlinked, ARCH_CONVERT) == NULLAGINO);
- ASSERT(!INT_ISZERO(dip->di_next_unlinked, ARCH_CONVERT));
+ ASSERT(dip->di_next_unlinked);
/* both on-disk, don't endian flip twice */
dip->di_next_unlinked = agi->agi_unlinked[bucket_index];
offset = ip->i_boffset +
@@ -2039,7 +2041,7 @@ xfs_iunlink_remove(
ASSERT(agino != 0);
bucket_index = agino % XFS_AGI_UNLINKED_BUCKETS;
ASSERT(INT_GET(agi->agi_unlinked[bucket_index], ARCH_CONVERT) != NULLAGINO);
- ASSERT(!INT_ISZERO(agi->agi_unlinked[bucket_index], ARCH_CONVERT));
+ ASSERT(agi->agi_unlinked[bucket_index]);
if (INT_GET(agi->agi_unlinked[bucket_index], ARCH_CONVERT) == agino) {
/*
@@ -3015,7 +3017,7 @@ xfs_iflush_fork(
ASSERT(whichfork == XFS_ATTR_FORK);
return 0;
}
- cp = XFS_DFORK_PTR_ARCH(dip, whichfork, ARCH_CONVERT);
+ cp = XFS_DFORK_PTR(dip, whichfork);
mp = ip->i_mount;
switch (XFS_IFORK_FORMAT(ip, whichfork)) {
case XFS_DINODE_FMT_LOCAL:
@@ -3056,7 +3058,7 @@ xfs_iflush_fork(
XFS_BROOT_SIZE_ADJ));
xfs_bmbt_to_bmdr(ifp->if_broot, ifp->if_broot_bytes,
(xfs_bmdr_block_t *)cp,
- XFS_DFORK_SIZE_ARCH(dip, mp, whichfork, ARCH_CONVERT));
+ XFS_DFORK_SIZE(dip, mp, whichfork));
}
break;
@@ -3474,8 +3476,7 @@ xfs_iflush_int(
* because if the inode is dirty at all the core must
* be.
*/
- xfs_xlate_dinode_core((xfs_caddr_t)&(dip->di_core), &(ip->i_d),
- -1, ARCH_CONVERT);
+ xfs_xlate_dinode_core((xfs_caddr_t)&(dip->di_core), &(ip->i_d), -1);
/* Wrap, we never let the log put out DI_MAX_FLUSH */
if (ip->i_d.di_flushiter == DI_MAX_FLUSH)
@@ -3505,7 +3506,7 @@ xfs_iflush_int(
ip->i_d.di_version = XFS_DINODE_VERSION_2;
INT_SET(dip->di_core.di_version, ARCH_CONVERT, XFS_DINODE_VERSION_2);
ip->i_d.di_onlink = 0;
- INT_ZERO(dip->di_core.di_onlink, ARCH_CONVERT);
+ dip->di_core.di_onlink = 0;
memset(&(ip->i_d.di_pad[0]), 0, sizeof(ip->i_d.di_pad));
memset(&(dip->di_core.di_pad[0]), 0,
sizeof(dip->di_core.di_pad));
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index 3d427c2b065c9..a53b1ccf60700 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -499,8 +499,9 @@ int xfs_ialloc(struct xfs_trans *, xfs_inode_t *, mode_t, nlink_t,
xfs_dev_t, struct cred *, xfs_prid_t, int,
struct xfs_buf **, boolean_t *, xfs_inode_t **);
void xfs_xlate_dinode_core(xfs_caddr_t, struct xfs_dinode_core *,
- int, xfs_arch_t);
-uint xfs_dic2xflags(struct xfs_dinode_core *, xfs_arch_t);
+ int);
+uint xfs_ip2xflags(struct xfs_inode *);
+uint xfs_dic2xflags(struct xfs_dinode_core *);
int xfs_ifree(struct xfs_trans *, xfs_inode_t *,
struct xfs_bmap_free *);
void xfs_itruncate_start(xfs_inode_t *, uint, xfs_fsize_t);
diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c
index 2900528c62da2..768cb1816b8ea 100644
--- a/fs/xfs/xfs_inode_item.c
+++ b/fs/xfs/xfs_inode_item.c
@@ -339,7 +339,7 @@ xfs_inode_item_format(
nrecs = ip->i_df.if_bytes /
(uint)sizeof(xfs_bmbt_rec_t);
ASSERT(nrecs > 0);
-#if ARCH_CONVERT == ARCH_NOCONVERT
+#if __BYTE_ORDER == __BIG_ENDIAN
if (nrecs == ip->i_d.di_nextents) {
/*
* There are no delayed allocation
@@ -467,7 +467,7 @@ xfs_inode_item_format(
#endif
ASSERT(nrecs > 0);
ASSERT(nrecs == ip->i_d.di_anextents);
-#if ARCH_CONVERT == ARCH_NOCONVERT
+#if __BYTE_ORDER == __BIG_ENDIAN
/*
* There are not delayed allocation extents
* for attributes, so just point at the array.
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
index 0e86be199cd10..8fbc8d3781885 100644
--- a/fs/xfs/xfs_itable.c
+++ b/fs/xfs/xfs_itable.c
@@ -60,128 +60,137 @@
#define unuseracc(ubuffer, size, flags)
#endif
-/*
- * Return stat information for one inode.
- * Return 0 if ok, else errno.
- */
-int /* error status */
-xfs_bulkstat_one(
+STATIC int
+xfs_bulkstat_one_iget(
xfs_mount_t *mp, /* mount point for filesystem */
xfs_ino_t ino, /* inode number to get data for */
- void __user *buffer, /* buffer to place output in */
- int ubsize, /* size of buffer */
- void *private_data, /* my private data */
xfs_daddr_t bno, /* starting bno of inode cluster */
- int *ubused, /* bytes used by me */
- void *dibuff, /* on-disk inode buffer */
+ xfs_bstat_t *buf, /* return buffer */
int *stat) /* BULKSTAT_RV_... */
{
- xfs_bstat_t *buf; /* return buffer */
- int error; /* error value */
- xfs_dinode_t *dip; /* dinode inode pointer */
xfs_dinode_core_t *dic; /* dinode core info pointer */
- xfs_inode_t *ip = NULL; /* incore inode pointer */
- xfs_arch_t arch; /* these are set according to */
-
- dip = (xfs_dinode_t *)dibuff;
+ xfs_inode_t *ip; /* incore inode pointer */
+ int error;
- if (!buffer || ino == mp->m_sb.sb_rbmino || ino == mp->m_sb.sb_rsumino ||
- (XFS_SB_VERSION_HASQUOTA(&mp->m_sb) &&
- (ino == mp->m_sb.sb_uquotino || ino == mp->m_sb.sb_gquotino))) {
+ error = xfs_iget(mp, NULL, ino, 0, XFS_ILOCK_SHARED, &ip, bno);
+ if (error) {
*stat = BULKSTAT_RV_NOTHING;
- return XFS_ERROR(EINVAL);
+ return error;
}
- if (ubsize < sizeof(*buf)) {
+
+ ASSERT(ip != NULL);
+ ASSERT(ip->i_blkno != (xfs_daddr_t)0);
+ if (ip->i_d.di_mode == 0) {
*stat = BULKSTAT_RV_NOTHING;
- return XFS_ERROR(ENOMEM);
+ error = XFS_ERROR(ENOENT);
+ goto out_iput;
}
- buf = kmem_alloc(sizeof(*buf), KM_SLEEP);
+ dic = &ip->i_d;
- if (dip == NULL) {
- /* We're not being passed a pointer to a dinode. This happens
- * if BULKSTAT_FG_IGET is selected. Do the iget.
- */
- error = xfs_iget(mp, NULL, ino, 0, XFS_ILOCK_SHARED, &ip, bno);
- if (error) {
- *stat = BULKSTAT_RV_NOTHING;
- return error;
- }
- ASSERT(ip != NULL);
- ASSERT(ip->i_blkno != (xfs_daddr_t)0);
- if (ip->i_d.di_mode == 0) {
- xfs_iput_new(ip, XFS_ILOCK_SHARED);
- *stat = BULKSTAT_RV_NOTHING;
- kmem_free(buf, sizeof(*buf));
- return XFS_ERROR(ENOENT);
- }
- dic = &ip->i_d;
- arch = ARCH_NOCONVERT; /* in-core! */
- ASSERT(dic != NULL);
+ /* xfs_iget returns the following without needing
+ * further change.
+ */
+ buf->bs_nlink = dic->di_nlink;
+ buf->bs_projid = dic->di_projid;
+ buf->bs_ino = ino;
+ buf->bs_mode = dic->di_mode;
+ 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;
+ 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;
+ buf->bs_ctime.tv_nsec = dic->di_ctime.t_nsec;
+ buf->bs_xflags = xfs_ip2xflags(ip);
+ buf->bs_extsize = dic->di_extsize << mp->m_sb.sb_blocklog;
+ buf->bs_extents = dic->di_nextents;
+ buf->bs_gen = dic->di_gen;
+ memset(buf->bs_pad, 0, sizeof(buf->bs_pad));
+ buf->bs_dmevmask = dic->di_dmevmask;
+ buf->bs_dmstate = dic->di_dmstate;
+ buf->bs_aextents = dic->di_anextents;
- /* xfs_iget returns the following without needing
- * further change.
- */
- buf->bs_nlink = dic->di_nlink;
- buf->bs_projid = dic->di_projid;
+ switch (dic->di_format) {
+ case XFS_DINODE_FMT_DEV:
+ buf->bs_rdev = ip->i_df.if_u2.if_rdev;
+ buf->bs_blksize = BLKDEV_IOSIZE;
+ buf->bs_blocks = 0;
+ break;
+ case XFS_DINODE_FMT_LOCAL:
+ case XFS_DINODE_FMT_UUID:
+ buf->bs_rdev = 0;
+ buf->bs_blksize = mp->m_sb.sb_blocksize;
+ buf->bs_blocks = 0;
+ break;
+ case XFS_DINODE_FMT_EXTENTS:
+ case XFS_DINODE_FMT_BTREE:
+ buf->bs_rdev = 0;
+ buf->bs_blksize = mp->m_sb.sb_blocksize;
+ buf->bs_blocks = dic->di_nblocks + ip->i_delayed_blks;
+ break;
+ }
- } else {
- dic = &dip->di_core;
- ASSERT(dic != NULL);
+ out_iput:
+ xfs_iput(ip, XFS_ILOCK_SHARED);
+ return error;
+}
- /* buffer dinode_core is in on-disk arch */
- arch = ARCH_CONVERT;
+STATIC int
+xfs_bulkstat_one_dinode(
+ xfs_mount_t *mp, /* mount point for filesystem */
+ xfs_ino_t ino, /* inode number to get data for */
+ xfs_dinode_t *dip, /* dinode inode pointer */
+ xfs_bstat_t *buf) /* return buffer */
+{
+ xfs_dinode_core_t *dic; /* dinode core info pointer */
- /*
- * The inode format changed when we moved the link count and
- * made it 32 bits long. If this is an old format inode,
- * convert it in memory to look like a new one. If it gets
- * flushed to disk we will convert back before flushing or
- * logging it. We zero out the new projid field and the old link
- * count field. We'll handle clearing the pad field (the remains
- * of the old uuid field) when we actually convert the inode to
- * the new format. We don't change the version number so that we
- * can distinguish this from a real new format inode.
- */
- if (INT_GET(dic->di_version, arch) == XFS_DINODE_VERSION_1) {
- buf->bs_nlink = INT_GET(dic->di_onlink, arch);
- buf->bs_projid = 0;
- }
- else {
- buf->bs_nlink = INT_GET(dic->di_nlink, arch);
- buf->bs_projid = INT_GET(dic->di_projid, arch);
- }
+ dic = &dip->di_core;
+ /*
+ * The inode format changed when we moved the link count and
+ * made it 32 bits long. If this is an old format inode,
+ * convert it in memory to look like a new one. If it gets
+ * flushed to disk we will convert back before flushing or
+ * logging it. We zero out the new projid field and the old link
+ * count field. We'll handle clearing the pad field (the remains
+ * of the old uuid field) when we actually convert the inode to
+ * the new format. We don't change the version number so that we
+ * can distinguish this from a real new format inode.
+ */
+ if (INT_GET(dic->di_version, ARCH_CONVERT) == XFS_DINODE_VERSION_1) {
+ buf->bs_nlink = INT_GET(dic->di_onlink, ARCH_CONVERT);
+ buf->bs_projid = 0;
+ } else {
+ buf->bs_nlink = INT_GET(dic->di_nlink, ARCH_CONVERT);
+ buf->bs_projid = INT_GET(dic->di_projid, ARCH_CONVERT);
}
buf->bs_ino = ino;
- buf->bs_mode = INT_GET(dic->di_mode, arch);
- buf->bs_uid = INT_GET(dic->di_uid, arch);
- buf->bs_gid = INT_GET(dic->di_gid, arch);
- buf->bs_size = INT_GET(dic->di_size, arch);
- buf->bs_atime.tv_sec = INT_GET(dic->di_atime.t_sec, arch);
- buf->bs_atime.tv_nsec = INT_GET(dic->di_atime.t_nsec, arch);
- buf->bs_mtime.tv_sec = INT_GET(dic->di_mtime.t_sec, arch);
- buf->bs_mtime.tv_nsec = INT_GET(dic->di_mtime.t_nsec, arch);
- buf->bs_ctime.tv_sec = INT_GET(dic->di_ctime.t_sec, arch);
- buf->bs_ctime.tv_nsec = INT_GET(dic->di_ctime.t_nsec, arch);
- buf->bs_xflags = xfs_dic2xflags(dic, arch);
- buf->bs_extsize = INT_GET(dic->di_extsize, arch) << mp->m_sb.sb_blocklog;
- buf->bs_extents = INT_GET(dic->di_nextents, arch);
- buf->bs_gen = INT_GET(dic->di_gen, arch);
+ buf->bs_mode = INT_GET(dic->di_mode, ARCH_CONVERT);
+ buf->bs_uid = INT_GET(dic->di_uid, ARCH_CONVERT);
+ buf->bs_gid = INT_GET(dic->di_gid, ARCH_CONVERT);
+ buf->bs_size = INT_GET(dic->di_size, ARCH_CONVERT);
+ buf->bs_atime.tv_sec = INT_GET(dic->di_atime.t_sec, ARCH_CONVERT);
+ buf->bs_atime.tv_nsec = INT_GET(dic->di_atime.t_nsec, ARCH_CONVERT);
+ buf->bs_mtime.tv_sec = INT_GET(dic->di_mtime.t_sec, ARCH_CONVERT);
+ buf->bs_mtime.tv_nsec = INT_GET(dic->di_mtime.t_nsec, ARCH_CONVERT);
+ buf->bs_ctime.tv_sec = INT_GET(dic->di_ctime.t_sec, ARCH_CONVERT);
+ buf->bs_ctime.tv_nsec = INT_GET(dic->di_ctime.t_nsec, ARCH_CONVERT);
+ buf->bs_xflags = xfs_dic2xflags(dic);
+ buf->bs_extsize = INT_GET(dic->di_extsize, ARCH_CONVERT) << mp->m_sb.sb_blocklog;
+ buf->bs_extents = INT_GET(dic->di_nextents, ARCH_CONVERT);
+ buf->bs_gen = INT_GET(dic->di_gen, ARCH_CONVERT);
memset(buf->bs_pad, 0, sizeof(buf->bs_pad));
- buf->bs_dmevmask = INT_GET(dic->di_dmevmask, arch);
- buf->bs_dmstate = INT_GET(dic->di_dmstate, arch);
- buf->bs_aextents = INT_GET(dic->di_anextents, arch);
+ buf->bs_dmevmask = INT_GET(dic->di_dmevmask, ARCH_CONVERT);
+ buf->bs_dmstate = INT_GET(dic->di_dmstate, ARCH_CONVERT);
+ buf->bs_aextents = INT_GET(dic->di_anextents, ARCH_CONVERT);
- switch (INT_GET(dic->di_format, arch)) {
+ switch (INT_GET(dic->di_format, ARCH_CONVERT)) {
case XFS_DINODE_FMT_DEV:
- if ( ip ) {
- buf->bs_rdev = ip->i_df.if_u2.if_rdev;
- } else {
- buf->bs_rdev = INT_GET(dip->di_u.di_dev, arch);
- }
-
+ buf->bs_rdev = INT_GET(dip->di_u.di_dev, ARCH_CONVERT);
buf->bs_blksize = BLKDEV_IOSIZE;
buf->bs_blocks = 0;
break;
@@ -195,29 +204,72 @@ xfs_bulkstat_one(
case XFS_DINODE_FMT_BTREE:
buf->bs_rdev = 0;
buf->bs_blksize = mp->m_sb.sb_blocksize;
- if ( ip ) {
- buf->bs_blocks = INT_GET(dic->di_nblocks, arch) + ip->i_delayed_blks;
- } else {
- buf->bs_blocks = INT_GET(dic->di_nblocks, arch);
- }
+ buf->bs_blocks = INT_GET(dic->di_nblocks, ARCH_CONVERT);
break;
}
- if (ip) {
- xfs_iput(ip, XFS_ILOCK_SHARED);
+ return 0;
+}
+
+/*
+ * Return stat information for one inode.
+ * Return 0 if ok, else errno.
+ */
+int /* error status */
+xfs_bulkstat_one(
+ xfs_mount_t *mp, /* mount point for filesystem */
+ xfs_ino_t ino, /* inode number to get data for */
+ void __user *buffer, /* buffer to place output in */
+ int ubsize, /* size of buffer */
+ void *private_data, /* my private data */
+ xfs_daddr_t bno, /* starting bno of inode cluster */
+ int *ubused, /* bytes used by me */
+ void *dibuff, /* on-disk inode buffer */
+ int *stat) /* BULKSTAT_RV_... */
+{
+ xfs_bstat_t *buf; /* return buffer */
+ int error = 0; /* error value */
+ xfs_dinode_t *dip; /* dinode inode pointer */
+
+ dip = (xfs_dinode_t *)dibuff;
+
+ if (!buffer || ino == mp->m_sb.sb_rbmino || ino == mp->m_sb.sb_rsumino ||
+ (XFS_SB_VERSION_HASQUOTA(&mp->m_sb) &&
+ (ino == mp->m_sb.sb_uquotino || ino == mp->m_sb.sb_gquotino))) {
+ *stat = BULKSTAT_RV_NOTHING;
+ return XFS_ERROR(EINVAL);
+ }
+ if (ubsize < sizeof(*buf)) {
+ *stat = BULKSTAT_RV_NOTHING;
+ return XFS_ERROR(ENOMEM);
+ }
+
+ buf = kmem_alloc(sizeof(*buf), KM_SLEEP);
+
+ if (dip == NULL) {
+ /* We're not being passed a pointer to a dinode. This happens
+ * if BULKSTAT_FG_IGET is selected. Do the iget.
+ */
+ error = xfs_bulkstat_one_iget(mp, ino, bno, buf, stat);
+ if (error)
+ goto out_free;
+ } else {
+ xfs_bulkstat_one_dinode(mp, ino, dip, buf);
}
if (copy_to_user(buffer, buf, sizeof(*buf))) {
- kmem_free(buf, sizeof(*buf));
*stat = BULKSTAT_RV_NOTHING;
- return EFAULT;
+ error = EFAULT;
+ goto out_free;
}
- kmem_free(buf, sizeof(*buf));
*stat = BULKSTAT_RV_DIDONE;
if (ubused)
*ubused = sizeof(*buf);
- return 0;
+
+ out_free:
+ kmem_free(buf, sizeof(*buf));
+ return error;
}
/*
@@ -352,7 +404,7 @@ xfs_bulkstat(
tmp && /* lookup succeeded */
/* got the record, should always work */
!(error = xfs_inobt_get_rec(cur, &gino, &gcnt,
- &gfree, &i, ARCH_NOCONVERT)) &&
+ &gfree, &i)) &&
i == 1 &&
/* this is the right chunk */
agino < gino + XFS_INODES_PER_CHUNK &&
@@ -421,7 +473,7 @@ xfs_bulkstat(
*/
if (error ||
(error = xfs_inobt_get_rec(cur, &gino, &gcnt,
- &gfree, &i, ARCH_NOCONVERT)) ||
+ &gfree, &i)) ||
i == 0) {
end_of_ag = 1;
break;
@@ -744,7 +796,7 @@ xfs_inumbers(
}
}
if ((error = xfs_inobt_get_rec(cur, &gino, &gcnt, &gfree,
- &i, ARCH_NOCONVERT)) ||
+ &i)) ||
i == 0) {
xfs_buf_relse(agbp);
agbp = NULL;
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
index 4ee4da88ce47b..092d5fb096b13 100644
--- a/fs/xfs/xfs_log.c
+++ b/fs/xfs/xfs_log.c
@@ -175,8 +175,8 @@ xlog_trace_loggrant(xlog_t *log, xlog_ticket_t *tic, xfs_caddr_t string)
(void *)((unsigned long)log->l_grant_write_bytes),
(void *)((unsigned long)log->l_curr_cycle),
(void *)((unsigned long)log->l_curr_block),
- (void *)((unsigned long)CYCLE_LSN(log->l_tail_lsn, ARCH_NOCONVERT)),
- (void *)((unsigned long)BLOCK_LSN(log->l_tail_lsn, ARCH_NOCONVERT)),
+ (void *)((unsigned long)CYCLE_LSN(log->l_tail_lsn)),
+ (void *)((unsigned long)BLOCK_LSN(log->l_tail_lsn)),
(void *)string,
(void *)((unsigned long)13),
(void *)((unsigned long)14),
@@ -890,8 +890,8 @@ xlog_space_left(xlog_t *log, int cycle, int bytes)
int tail_bytes;
int tail_cycle;
- tail_bytes = BBTOB(BLOCK_LSN(log->l_tail_lsn, ARCH_NOCONVERT));
- tail_cycle = CYCLE_LSN(log->l_tail_lsn, ARCH_NOCONVERT);
+ tail_bytes = BBTOB(BLOCK_LSN(log->l_tail_lsn));
+ tail_cycle = CYCLE_LSN(log->l_tail_lsn);
if ((tail_cycle == cycle) && (bytes >= tail_bytes)) {
free_bytes = log->l_logsize - (bytes - tail_bytes);
} else if ((tail_cycle + 1) < cycle) {
@@ -1164,7 +1164,7 @@ xlog_alloc_log(xfs_mount_t *mp,
log->l_flags |= XLOG_ACTIVE_RECOVERY;
log->l_prev_block = -1;
- ASSIGN_ANY_LSN(log->l_tail_lsn, 1, 0, ARCH_NOCONVERT);
+ ASSIGN_ANY_LSN_HOST(log->l_tail_lsn, 1, 0);
/* log->l_tail_lsn = 0x100000000LL; cycle = 1; current block = 0 */
log->l_last_sync_lsn = log->l_tail_lsn;
log->l_curr_cycle = 1; /* 0 is bad since this is initial value */
@@ -1321,19 +1321,19 @@ xlog_grant_push_ail(xfs_mount_t *mp,
free_threshold = MAX(free_threshold, (log->l_logBBsize >> 2));
free_threshold = MAX(free_threshold, 256);
if (free_blocks < free_threshold) {
- threshold_block = BLOCK_LSN(tail_lsn, ARCH_NOCONVERT) + free_threshold;
- threshold_cycle = CYCLE_LSN(tail_lsn, ARCH_NOCONVERT);
+ threshold_block = BLOCK_LSN(tail_lsn) + free_threshold;
+ threshold_cycle = CYCLE_LSN(tail_lsn);
if (threshold_block >= log->l_logBBsize) {
threshold_block -= log->l_logBBsize;
threshold_cycle += 1;
}
- ASSIGN_ANY_LSN(threshold_lsn, threshold_cycle,
- threshold_block, ARCH_NOCONVERT);
+ ASSIGN_ANY_LSN_HOST(threshold_lsn, threshold_cycle,
+ threshold_block);
/* Don't pass in an lsn greater than the lsn of the last
* log record known to be on disk.
*/
- if (XFS_LSN_CMP_ARCH(threshold_lsn, log->l_last_sync_lsn, ARCH_NOCONVERT) > 0)
+ if (XFS_LSN_CMP(threshold_lsn, log->l_last_sync_lsn) > 0)
threshold_lsn = log->l_last_sync_lsn;
}
GRANT_UNLOCK(log, s);
@@ -1435,7 +1435,7 @@ xlog_sync(xlog_t *log,
bp = iclog->ic_bp;
ASSERT(XFS_BUF_FSPRIVATE2(bp, unsigned long) == (unsigned long)1);
XFS_BUF_SET_FSPRIVATE2(bp, (unsigned long)2);
- XFS_BUF_SET_ADDR(bp, BLOCK_LSN(iclog->ic_header.h_lsn, ARCH_CONVERT));
+ XFS_BUF_SET_ADDR(bp, BLOCK_LSN(INT_GET(iclog->ic_header.h_lsn, ARCH_CONVERT)));
XFS_STATS_ADD(xs_log_blocks, BTOBB(count));
@@ -1728,9 +1728,9 @@ xlog_write(xfs_mount_t * mp,
logop_head = (xlog_op_header_t *)ptr;
INT_SET(logop_head->oh_tid, ARCH_CONVERT, ticket->t_tid);
logop_head->oh_clientid = ticket->t_clientid;
- INT_ZERO(logop_head->oh_len, ARCH_CONVERT);
+ logop_head->oh_len = 0;
logop_head->oh_flags = XLOG_START_TRANS;
- INT_ZERO(logop_head->oh_res2, ARCH_CONVERT);
+ logop_head->oh_res2 = 0;
ticket->t_flags &= ~XLOG_TIC_INITED; /* clear bit */
record_cnt++;
@@ -1742,7 +1742,7 @@ xlog_write(xfs_mount_t * mp,
logop_head = (xlog_op_header_t *)ptr;
INT_SET(logop_head->oh_tid, ARCH_CONVERT, ticket->t_tid);
logop_head->oh_clientid = ticket->t_clientid;
- INT_ZERO(logop_head->oh_res2, ARCH_CONVERT);
+ logop_head->oh_res2 = 0;
/* header copied directly */
xlog_write_adv_cnt(ptr, len, log_offset, sizeof(xlog_op_header_t));
@@ -1888,10 +1888,10 @@ xlog_state_clean_log(xlog_t *log)
*/
changed = 2;
}
- INT_ZERO(iclog->ic_header.h_num_logops, ARCH_CONVERT);
+ iclog->ic_header.h_num_logops = 0;
memset(iclog->ic_header.h_cycle_data, 0,
sizeof(iclog->ic_header.h_cycle_data));
- INT_ZERO(iclog->ic_header.h_lsn, ARCH_CONVERT);
+ iclog->ic_header.h_lsn = 0;
} else if (iclog->ic_state == XLOG_STATE_ACTIVE)
/* do nothing */;
else
@@ -1948,7 +1948,7 @@ xlog_get_lowest_lsn(
if (!(lsn_log->ic_state & (XLOG_STATE_ACTIVE|XLOG_STATE_DIRTY))) {
lsn = INT_GET(lsn_log->ic_header.h_lsn, ARCH_CONVERT);
if ((lsn && !lowest_lsn) ||
- (XFS_LSN_CMP_ARCH(lsn, lowest_lsn, ARCH_NOCONVERT) < 0)) {
+ (XFS_LSN_CMP(lsn, lowest_lsn) < 0)) {
lowest_lsn = lsn;
}
}
@@ -2049,10 +2049,9 @@ xlog_state_do_callback(
lowest_lsn = xlog_get_lowest_lsn(log);
if (lowest_lsn && (
- XFS_LSN_CMP_ARCH(
+ XFS_LSN_CMP(
lowest_lsn,
- INT_GET(iclog->ic_header.h_lsn, ARCH_CONVERT),
- ARCH_NOCONVERT
+ INT_GET(iclog->ic_header.h_lsn, ARCH_CONVERT)
)<0)) {
iclog = iclog->ic_next;
continue; /* Leave this iclog for
@@ -2068,10 +2067,9 @@ xlog_state_do_callback(
* No one else can be here except us.
*/
s = GRANT_LOCK(log);
- ASSERT(XFS_LSN_CMP_ARCH(
+ ASSERT(XFS_LSN_CMP(
log->l_last_sync_lsn,
- INT_GET(iclog->ic_header.h_lsn, ARCH_CONVERT),
- ARCH_NOCONVERT
+ INT_GET(iclog->ic_header.h_lsn, ARCH_CONVERT)
)<=0);
log->l_last_sync_lsn = INT_GET(iclog->ic_header.h_lsn, ARCH_CONVERT);
GRANT_UNLOCK(log, s);
@@ -2285,7 +2283,7 @@ restart:
if (log_offset == 0) {
ticket->t_curr_res -= log->l_iclog_hsize;
INT_SET(head->h_cycle, ARCH_CONVERT, log->l_curr_cycle);
- ASSIGN_LSN(head->h_lsn, log, ARCH_CONVERT);
+ ASSIGN_LSN(head->h_lsn, log);
ASSERT(log->l_curr_block >= 0);
}
@@ -2427,9 +2425,9 @@ redo:
* Otherwise, make sure that the cycles differ by exactly one and
* check the byte count.
*/
- if (CYCLE_LSN(tail_lsn, ARCH_NOCONVERT) != log->l_grant_write_cycle) {
- ASSERT(log->l_grant_write_cycle-1 == CYCLE_LSN(tail_lsn, ARCH_NOCONVERT));
- ASSERT(log->l_grant_write_bytes <= BBTOB(BLOCK_LSN(tail_lsn, ARCH_NOCONVERT)));
+ if (CYCLE_LSN(tail_lsn) != log->l_grant_write_cycle) {
+ ASSERT(log->l_grant_write_cycle-1 == CYCLE_LSN(tail_lsn));
+ ASSERT(log->l_grant_write_bytes <= BBTOB(BLOCK_LSN(tail_lsn)));
}
#endif
xlog_trace_loggrant(log, tic, "xlog_grant_log_space: exit");
@@ -2560,9 +2558,9 @@ redo:
XLOG_GRANT_ADD_SPACE(log, need_bytes, 'w'); /* we've got enough space */
#ifdef DEBUG
tail_lsn = log->l_tail_lsn;
- if (CYCLE_LSN(tail_lsn, ARCH_NOCONVERT) != log->l_grant_write_cycle) {
- ASSERT(log->l_grant_write_cycle-1 == CYCLE_LSN(tail_lsn, ARCH_NOCONVERT));
- ASSERT(log->l_grant_write_bytes <= BBTOB(BLOCK_LSN(tail_lsn, ARCH_NOCONVERT)));
+ if (CYCLE_LSN(tail_lsn) != log->l_grant_write_cycle) {
+ ASSERT(log->l_grant_write_cycle-1 == CYCLE_LSN(tail_lsn));
+ ASSERT(log->l_grant_write_bytes <= BBTOB(BLOCK_LSN(tail_lsn)));
}
#endif
@@ -3269,18 +3267,18 @@ xlog_verify_tail_lsn(xlog_t *log,
{
int blocks;
- if (CYCLE_LSN(tail_lsn, ARCH_NOCONVERT) == log->l_prev_cycle) {
+ if (CYCLE_LSN(tail_lsn) == log->l_prev_cycle) {
blocks =
- log->l_logBBsize - (log->l_prev_block - BLOCK_LSN(tail_lsn, ARCH_NOCONVERT));
+ log->l_logBBsize - (log->l_prev_block - BLOCK_LSN(tail_lsn));
if (blocks < BTOBB(iclog->ic_offset)+BTOBB(log->l_iclog_hsize))
xlog_panic("xlog_verify_tail_lsn: ran out of log space");
} else {
- ASSERT(CYCLE_LSN(tail_lsn, ARCH_NOCONVERT)+1 == log->l_prev_cycle);
+ ASSERT(CYCLE_LSN(tail_lsn)+1 == log->l_prev_cycle);
- if (BLOCK_LSN(tail_lsn, ARCH_NOCONVERT) == log->l_prev_block)
+ if (BLOCK_LSN(tail_lsn) == log->l_prev_block)
xlog_panic("xlog_verify_tail_lsn: tail wrapped");
- blocks = BLOCK_LSN(tail_lsn, ARCH_NOCONVERT) - log->l_prev_block;
+ blocks = BLOCK_LSN(tail_lsn) - log->l_prev_block;
if (blocks < BTOBB(iclog->ic_offset) + 1)
xlog_panic("xlog_verify_tail_lsn: ran out of log space");
}
diff --git a/fs/xfs/xfs_log.h b/fs/xfs/xfs_log.h
index 3b1f395b67bbe..0db122ddda3f3 100644
--- a/fs/xfs/xfs_log.h
+++ b/fs/xfs/xfs_log.h
@@ -32,20 +32,12 @@
#ifndef __XFS_LOG_H__
#define __XFS_LOG_H__
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-#define LSN_FIELD_CYCLE(arch) (((arch)==ARCH_NOCONVERT)?1:0)
-#define LSN_FIELD_BLOCK(arch) (((arch)==ARCH_NOCONVERT)?0:1)
-#else
-#define LSN_FIELD_CYCLE(arch) (0)
-#define LSN_FIELD_BLOCK(arch) (1)
-#endif
-
/* get lsn fields */
-#define CYCLE_LSN(lsn,arch) (INT_GET(((uint *)&(lsn))[LSN_FIELD_CYCLE(arch)], arch))
-#define BLOCK_LSN(lsn,arch) (INT_GET(((uint *)&(lsn))[LSN_FIELD_BLOCK(arch)], arch))
+#define CYCLE_LSN(lsn) ((uint)((lsn)>>32))
+#define BLOCK_LSN(lsn) ((uint)(lsn))
/* this is used in a spot where we might otherwise double-endian-flip */
-#define CYCLE_LSN_NOCONV(lsn,arch) (((uint *)&(lsn))[LSN_FIELD_CYCLE(arch)])
+#define CYCLE_LSN_DISK(lsn) (((uint *)&(lsn))[0])
#ifdef __KERNEL__
/*
@@ -58,21 +50,18 @@ __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, xfs_arch_t arch)
+xfs_lsn_t _lsn_cmp(xfs_lsn_t lsn1, xfs_lsn_t lsn2)
{
- if (CYCLE_LSN(lsn1, arch) != CYCLE_LSN(lsn2, arch))
- return (CYCLE_LSN(lsn1, arch)<CYCLE_LSN(lsn2, arch))? -999 : 999;
+ if (CYCLE_LSN(lsn1) != CYCLE_LSN(lsn2))
+ return (CYCLE_LSN(lsn1)<CYCLE_LSN(lsn2))? -999 : 999;
- if (BLOCK_LSN(lsn1, arch) != BLOCK_LSN(lsn2, arch))
- return (BLOCK_LSN(lsn1, arch)<BLOCK_LSN(lsn2, arch))? -999 : 999;
+ if (BLOCK_LSN(lsn1) != BLOCK_LSN(lsn2))
+ return (BLOCK_LSN(lsn1)<BLOCK_LSN(lsn2))? -999 : 999;
return 0;
}
-#define XFS_LSN_CMP_ARCH(x,y,arch) _lsn_cmp(x, y, arch)
-#define XFS_LSN_CMP(x,y) XFS_LSN_CMP_ARCH(x,y,ARCH_NOCONVERT)
-#define XFS_LSN_DIFF_ARCH(x,y,arch) _lsn_cmp(x, y, arch)
-#define XFS_LSN_DIFF(x,y) XFS_LSN_DIFF_ARCH(x,y,ARCH_NOCONVERT)
+#define XFS_LSN_CMP(x,y) _lsn_cmp(x,y)
/*
* Macros, structures, prototypes for interface to the log manager.
diff --git a/fs/xfs/xfs_log_priv.h b/fs/xfs/xfs_log_priv.h
index 0505a3069e025..c31e3ce3be660 100644
--- a/fs/xfs/xfs_log_priv.h
+++ b/fs/xfs/xfs_log_priv.h
@@ -74,17 +74,17 @@ struct xfs_mount;
* set lsns
*/
-#define ASSIGN_LSN_CYCLE(lsn,cycle,arch) \
- INT_SET(((uint *)&(lsn))[LSN_FIELD_CYCLE(arch)], arch, (cycle));
-#define ASSIGN_LSN_BLOCK(lsn,block,arch) \
- INT_SET(((uint *)&(lsn))[LSN_FIELD_BLOCK(arch)], arch, (block));
-#define ASSIGN_ANY_LSN(lsn,cycle,block,arch) \
+#define ASSIGN_ANY_LSN_HOST(lsn,cycle,block) \
{ \
- ASSIGN_LSN_CYCLE(lsn,cycle,arch); \
- ASSIGN_LSN_BLOCK(lsn,block,arch); \
+ (lsn) = ((xfs_lsn_t)(cycle)<<32)|(block); \
}
-#define ASSIGN_LSN(lsn,log,arch) \
- ASSIGN_ANY_LSN(lsn,(log)->l_curr_cycle,(log)->l_curr_block,arch);
+#define ASSIGN_ANY_LSN_DISK(lsn,cycle,block) \
+ { \
+ INT_SET(((uint *)&(lsn))[0], ARCH_CONVERT, (cycle)); \
+ INT_SET(((uint *)&(lsn))[1], ARCH_CONVERT, (block)); \
+ }
+#define ASSIGN_LSN(lsn,log) \
+ ASSIGN_ANY_LSN_DISK(lsn,(log)->l_curr_cycle,(log)->l_curr_block);
#define XLOG_SET(f,b) (((f) & (b)) == (b))
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index 6079aad901569..9824b5bf0ec03 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -873,7 +873,7 @@ xlog_find_tail(
/* find blk_no of tail of log */
rhead = (xlog_rec_header_t *)offset;
- *tail_blk = BLOCK_LSN(rhead->h_tail_lsn, ARCH_CONVERT);
+ *tail_blk = BLOCK_LSN(INT_GET(rhead->h_tail_lsn, ARCH_CONVERT));
/*
* Reset log values according to the state of the log when we
@@ -940,10 +940,10 @@ xlog_find_tail(
* log records will point recovery to after the
* current unmount record.
*/
- ASSIGN_ANY_LSN(log->l_tail_lsn, log->l_curr_cycle,
- after_umount_blk, ARCH_NOCONVERT);
- ASSIGN_ANY_LSN(log->l_last_sync_lsn, log->l_curr_cycle,
- after_umount_blk, ARCH_NOCONVERT);
+ ASSIGN_ANY_LSN_HOST(log->l_tail_lsn, log->l_curr_cycle,
+ after_umount_blk);
+ ASSIGN_ANY_LSN_HOST(log->l_last_sync_lsn, log->l_curr_cycle,
+ after_umount_blk);
*tail_blk = after_umount_blk;
}
}
@@ -1110,8 +1110,8 @@ xlog_add_record(
INT_SET(recp->h_cycle, ARCH_CONVERT, cycle);
INT_SET(recp->h_version, ARCH_CONVERT,
XFS_SB_VERSION_HASLOGV2(&log->l_mp->m_sb) ? 2 : 1);
- ASSIGN_ANY_LSN(recp->h_lsn, cycle, block, ARCH_CONVERT);
- ASSIGN_ANY_LSN(recp->h_tail_lsn, tail_cycle, tail_block, ARCH_CONVERT);
+ ASSIGN_ANY_LSN_DISK(recp->h_lsn, cycle, block);
+ ASSIGN_ANY_LSN_DISK(recp->h_tail_lsn, tail_cycle, tail_block);
INT_SET(recp->h_fmt, ARCH_CONVERT, XLOG_FMT);
memcpy(&recp->h_fs_uuid, &log->l_mp->m_sb.sb_uuid, sizeof(uuid_t));
}
@@ -1217,8 +1217,8 @@ xlog_clear_stale_blocks(
int distance;
int error;
- tail_cycle = CYCLE_LSN(tail_lsn, ARCH_NOCONVERT);
- tail_block = BLOCK_LSN(tail_lsn, ARCH_NOCONVERT);
+ tail_cycle = CYCLE_LSN(tail_lsn);
+ tail_block = BLOCK_LSN(tail_lsn);
head_cycle = log->l_curr_cycle;
head_block = log->l_curr_block;
@@ -2047,11 +2047,11 @@ xfs_qm_dqcheck(
errs++;
}
- if (! errs && !INT_ISZERO(ddq->d_id, ARCH_CONVERT)) {
+ if (!errs && ddq->d_id) {
if (INT_GET(ddq->d_blk_softlimit, ARCH_CONVERT) &&
INT_GET(ddq->d_bcount, ARCH_CONVERT) >=
INT_GET(ddq->d_blk_softlimit, ARCH_CONVERT)) {
- if (INT_ISZERO(ddq->d_btimer, ARCH_CONVERT)) {
+ if (!ddq->d_btimer) {
if (flags & XFS_QMOPT_DOWARN)
cmn_err(CE_ALERT,
"%s : Dquot ID 0x%x (0x%p) "
@@ -2064,7 +2064,7 @@ xfs_qm_dqcheck(
if (INT_GET(ddq->d_ino_softlimit, ARCH_CONVERT) &&
INT_GET(ddq->d_icount, ARCH_CONVERT) >=
INT_GET(ddq->d_ino_softlimit, ARCH_CONVERT)) {
- if (INT_ISZERO(ddq->d_itimer, ARCH_CONVERT)) {
+ if (!ddq->d_itimer) {
if (flags & XFS_QMOPT_DOWARN)
cmn_err(CE_ALERT,
"%s : Dquot ID 0x%x (0x%p) "
@@ -2077,7 +2077,7 @@ xfs_qm_dqcheck(
if (INT_GET(ddq->d_rtb_softlimit, ARCH_CONVERT) &&
INT_GET(ddq->d_rtbcount, ARCH_CONVERT) >=
INT_GET(ddq->d_rtb_softlimit, ARCH_CONVERT)) {
- if (INT_ISZERO(ddq->d_rtbtimer, ARCH_CONVERT)) {
+ if (!ddq->d_rtbtimer) {
if (flags & XFS_QMOPT_DOWARN)
cmn_err(CE_ALERT,
"%s : Dquot ID 0x%x (0x%p) "
@@ -2452,8 +2452,8 @@ xlog_recover_do_inode_trans(
/* The core is in in-core format */
xfs_xlate_dinode_core((xfs_caddr_t)&dip->di_core,
- (xfs_dinode_core_t*)item->ri_buf[1].i_addr,
- -1, ARCH_CONVERT);
+ (xfs_dinode_core_t*)item->ri_buf[1].i_addr, -1);
+
/* the rest is in on-disk format */
if (item->ri_buf[1].i_len > sizeof(xfs_dinode_core_t)) {
memcpy((xfs_caddr_t) dip + sizeof(xfs_dinode_core_t),
@@ -3395,7 +3395,7 @@ xlog_pack_data(
xlog_pack_data_checksum(log, iclog, size);
- cycle_lsn = CYCLE_LSN_NOCONV(iclog->ic_header.h_lsn, ARCH_CONVERT);
+ cycle_lsn = CYCLE_LSN_DISK(iclog->ic_header.h_lsn);
dp = iclog->ic_datap;
for (i = 0; i < BTOBB(size) &&
@@ -3438,7 +3438,7 @@ xlog_unpack_data_checksum(
up++;
}
if (chksum != INT_GET(rhead->h_chksum, ARCH_CONVERT)) {
- if (!INT_ISZERO(rhead->h_chksum, ARCH_CONVERT) ||
+ if (rhead->h_chksum ||
((log->l_flags & XLOG_CHKSUM_MISMATCH) == 0)) {
cmn_err(CE_DEBUG,
"XFS: LogR chksum mismatch: was (0x%x) is (0x%x)",
@@ -3501,7 +3501,7 @@ xlog_valid_rec_header(
return XFS_ERROR(EFSCORRUPTED);
}
if (unlikely(
- (INT_ISZERO(rhead->h_version, ARCH_CONVERT) ||
+ (!rhead->h_version ||
(INT_GET(rhead->h_version, ARCH_CONVERT) &
(~XLOG_VERSION_OKBITS)) != 0))) {
xlog_warn("XFS: %s: unrecognised log version (%d).",
@@ -3894,7 +3894,7 @@ xlog_do_recover(
/* Convert superblock from on-disk format */
sbp = &log->l_mp->m_sb;
- xfs_xlatesb(XFS_BUF_TO_SBP(bp), sbp, 1, ARCH_CONVERT, XFS_SB_ALL_BITS);
+ xfs_xlatesb(XFS_BUF_TO_SBP(bp), sbp, 1, XFS_SB_ALL_BITS);
ASSERT(sbp->sb_magicnum == XFS_SB_MAGIC);
ASSERT(XFS_SB_GOOD_VERSION(sbp));
xfs_buf_relse(bp);
@@ -4073,7 +4073,7 @@ xlog_recover_check_summary(
sbbp = xfs_getsb(mp, 0);
#ifdef XFS_LOUD_RECOVERY
sbp = &mp->m_sb;
- xfs_xlatesb(XFS_BUF_TO_SBP(sbbp), sbp, 1, ARCH_CONVERT, XFS_SB_ALL_BITS);
+ xfs_xlatesb(XFS_BUF_TO_SBP(sbbp), sbp, 1, XFS_SB_ALL_BITS);
cmn_err(CE_NOTE,
"xlog_recover_check_summary: sb_icount %Lu itotal %Lu",
sbp->sb_icount, itotal);
diff --git a/fs/xfs/xfs_macros.c b/fs/xfs/xfs_macros.c
index 626be21c1e282..ce4f46c6b3aba 100644
--- a/fs/xfs/xfs_macros.c
+++ b/fs/xfs/xfs_macros.c
@@ -705,9 +705,9 @@ xfs_buf_to_sbp(xfs_buf_t *bp)
#if XFS_WANT_FUNCS_C || (XFS_WANT_SPACE_C && XFSSO_XFS_CFORK_ASIZE)
int
-xfs_cfork_asize_arch(xfs_dinode_core_t *dcp, xfs_mount_t *mp, xfs_arch_t arch)
+xfs_cfork_asize_disk(xfs_dinode_core_t *dcp, xfs_mount_t *mp)
{
- return XFS_CFORK_ASIZE_ARCH(dcp, mp, arch);
+ return XFS_CFORK_ASIZE_DISK(dcp, mp);
}
int
xfs_cfork_asize(xfs_dinode_core_t *dcp, xfs_mount_t *mp)
@@ -718,9 +718,9 @@ xfs_cfork_asize(xfs_dinode_core_t *dcp, xfs_mount_t *mp)
#if XFS_WANT_FUNCS_C || (XFS_WANT_SPACE_C && XFSSO_XFS_CFORK_BOFF)
int
-xfs_cfork_boff_arch(xfs_dinode_core_t *dcp, xfs_arch_t arch)
+xfs_cfork_boff_disk(xfs_dinode_core_t *dcp)
{
- return XFS_CFORK_BOFF_ARCH(dcp, arch);
+ return XFS_CFORK_BOFF_DISK(dcp);
}
int
xfs_cfork_boff(xfs_dinode_core_t *dcp)
@@ -731,9 +731,9 @@ xfs_cfork_boff(xfs_dinode_core_t *dcp)
#if XFS_WANT_FUNCS_C || (XFS_WANT_SPACE_C && XFSSO_XFS_CFORK_DSIZE)
int
-xfs_cfork_dsize_arch(xfs_dinode_core_t *dcp, xfs_mount_t *mp, xfs_arch_t arch)
+xfs_cfork_dsize_disk(xfs_dinode_core_t *dcp, xfs_mount_t *mp)
{
- return XFS_CFORK_DSIZE_ARCH(dcp, mp, arch);
+ return XFS_CFORK_DSIZE_DISK(dcp, mp);
}
int
xfs_cfork_dsize(xfs_dinode_core_t *dcp, xfs_mount_t *mp)
@@ -744,11 +744,6 @@ xfs_cfork_dsize(xfs_dinode_core_t *dcp, xfs_mount_t *mp)
#if XFS_WANT_FUNCS_C || (XFS_WANT_SPACE_C && XFSSO_XFS_CFORK_FMT_SET)
void
-xfs_cfork_fmt_set_arch(xfs_dinode_core_t *dcp, int w, int n, xfs_arch_t arch)
-{
- XFS_CFORK_FMT_SET_ARCH(dcp, w, n, arch);
-}
-void
xfs_cfork_fmt_set(xfs_dinode_core_t *dcp, int w, int n)
{
XFS_CFORK_FMT_SET(dcp, w, n);
@@ -757,11 +752,6 @@ xfs_cfork_fmt_set(xfs_dinode_core_t *dcp, int w, int n)
#if XFS_WANT_FUNCS_C || (XFS_WANT_SPACE_C && XFSSO_XFS_CFORK_FORMAT)
int
-xfs_cfork_format_arch(xfs_dinode_core_t *dcp, int w, xfs_arch_t arch)
-{
- return XFS_CFORK_FORMAT_ARCH(dcp, w, arch);
-}
-int
xfs_cfork_format(xfs_dinode_core_t *dcp, int w)
{
return XFS_CFORK_FORMAT(dcp, w);
@@ -770,11 +760,6 @@ xfs_cfork_format(xfs_dinode_core_t *dcp, int w)
#if XFS_WANT_FUNCS_C || (XFS_WANT_SPACE_C && XFSSO_XFS_CFORK_NEXT_SET)
void
-xfs_cfork_next_set_arch(xfs_dinode_core_t *dcp, int w, int n, xfs_arch_t arch)
-{
- XFS_CFORK_NEXT_SET_ARCH(dcp, w, n, arch);
-}
-void
xfs_cfork_next_set(xfs_dinode_core_t *dcp, int w, int n)
{
XFS_CFORK_NEXT_SET(dcp, w, n);
@@ -783,9 +768,9 @@ xfs_cfork_next_set(xfs_dinode_core_t *dcp, int w, int n)
#if XFS_WANT_FUNCS_C || (XFS_WANT_SPACE_C && XFSSO_XFS_CFORK_NEXTENTS)
int
-xfs_cfork_nextents_arch(xfs_dinode_core_t *dcp, int w, xfs_arch_t arch)
+xfs_cfork_nextents_disk(xfs_dinode_core_t *dcp, int w)
{
- return XFS_CFORK_NEXTENTS_ARCH(dcp, w, arch);
+ return XFS_CFORK_NEXTENTS_DISK(dcp, w);
}
int
xfs_cfork_nextents(xfs_dinode_core_t *dcp, int w)
@@ -796,9 +781,9 @@ xfs_cfork_nextents(xfs_dinode_core_t *dcp, int w)
#if XFS_WANT_FUNCS_C || (XFS_WANT_SPACE_C && XFSSO_XFS_CFORK_Q)
int
-xfs_cfork_q_arch(xfs_dinode_core_t *dcp, xfs_arch_t arch)
+xfs_cfork_q_disk(xfs_dinode_core_t *dcp)
{
- return XFS_CFORK_Q_ARCH(dcp, arch);
+ return XFS_CFORK_Q_DISK(dcp);
}
int
xfs_cfork_q(xfs_dinode_core_t *dcp)
@@ -809,9 +794,9 @@ xfs_cfork_q(xfs_dinode_core_t *dcp)
#if XFS_WANT_FUNCS_C || (XFS_WANT_SPACE_C && XFSSO_XFS_CFORK_SIZE)
int
-xfs_cfork_size_arch(xfs_dinode_core_t *dcp, xfs_mount_t *mp, int w, xfs_arch_t arch)
+xfs_cfork_size_disk(xfs_dinode_core_t *dcp, xfs_mount_t *mp, int w)
{
- return XFS_CFORK_SIZE_ARCH(dcp, mp, w, arch);
+ return XFS_CFORK_SIZE_DISK(dcp, mp, w);
}
int
xfs_cfork_size(xfs_dinode_core_t *dcp, xfs_mount_t *mp, int w)
@@ -896,11 +881,6 @@ xfs_daddr_to_fsb(xfs_mount_t *mp, xfs_daddr_t d)
#if XFS_WANT_FUNCS_C || (XFS_WANT_SPACE_C && XFSSO_XFS_DFORK_APTR)
char *
-xfs_dfork_aptr_arch(xfs_dinode_t *dip, xfs_arch_t arch)
-{
- return XFS_DFORK_APTR_ARCH(dip, arch);
-}
-char *
xfs_dfork_aptr(xfs_dinode_t *dip)
{
return XFS_DFORK_APTR(dip);
@@ -909,11 +889,6 @@ xfs_dfork_aptr(xfs_dinode_t *dip)
#if XFS_WANT_FUNCS_C || (XFS_WANT_SPACE_C && XFSSO_XFS_DFORK_ASIZE)
int
-xfs_dfork_asize_arch(xfs_dinode_t *dip, xfs_mount_t *mp, xfs_arch_t arch)
-{
- return XFS_DFORK_ASIZE_ARCH(dip, mp, arch);
-}
-int
xfs_dfork_asize(xfs_dinode_t *dip, xfs_mount_t *mp)
{
return XFS_DFORK_ASIZE(dip, mp);
@@ -922,11 +897,6 @@ xfs_dfork_asize(xfs_dinode_t *dip, xfs_mount_t *mp)
#if XFS_WANT_FUNCS_C || (XFS_WANT_SPACE_C && XFSSO_XFS_DFORK_BOFF)
int
-xfs_dfork_boff_arch(xfs_dinode_t *dip, xfs_arch_t arch)
-{
- return XFS_DFORK_BOFF_ARCH(dip, arch);
-}
-int
xfs_dfork_boff(xfs_dinode_t *dip)
{
return XFS_DFORK_BOFF(dip);
@@ -935,11 +905,6 @@ xfs_dfork_boff(xfs_dinode_t *dip)
#if XFS_WANT_FUNCS_C || (XFS_WANT_SPACE_C && XFSSO_XFS_DFORK_DPTR)
char *
-xfs_dfork_dptr_arch(xfs_dinode_t *dip, xfs_arch_t arch)
-{
- return XFS_DFORK_DPTR_ARCH(dip, arch);
-}
-char *
xfs_dfork_dptr(xfs_dinode_t *dip)
{
return XFS_DFORK_DPTR(dip);
@@ -948,63 +913,14 @@ xfs_dfork_dptr(xfs_dinode_t *dip)
#if XFS_WANT_FUNCS_C || (XFS_WANT_SPACE_C && XFSSO_XFS_DFORK_DSIZE)
int
-xfs_dfork_dsize_arch(xfs_dinode_t *dip, xfs_mount_t *mp, xfs_arch_t arch)
-{
- return XFS_DFORK_DSIZE_ARCH(dip, mp, arch);
-}
-int
xfs_dfork_dsize(xfs_dinode_t *dip, xfs_mount_t *mp)
{
return XFS_DFORK_DSIZE(dip, mp);
}
#endif
-#if XFS_WANT_FUNCS_C || (XFS_WANT_SPACE_C && XFSSO_XFS_DFORK_FMT_SET)
-void
-xfs_dfork_fmt_set_arch(xfs_dinode_t *dip, int w, int n, xfs_arch_t arch)
-{
- XFS_DFORK_FMT_SET_ARCH(dip, w, n, arch);
-}
-void
-xfs_dfork_fmt_set(xfs_dinode_t *dip, int w, int n)
-{
- XFS_DFORK_FMT_SET(dip, w, n);
-}
-#endif
-
-#if XFS_WANT_FUNCS_C || (XFS_WANT_SPACE_C && XFSSO_XFS_DFORK_FORMAT)
-int
-xfs_dfork_format_arch(xfs_dinode_t *dip, int w, xfs_arch_t arch)
-{
- return XFS_DFORK_FORMAT_ARCH(dip, w, arch);
-}
-int
-xfs_dfork_format(xfs_dinode_t *dip, int w)
-{
- return XFS_DFORK_FORMAT(dip, w);
-}
-#endif
-
-#if XFS_WANT_FUNCS_C || (XFS_WANT_SPACE_C && XFSSO_XFS_DFORK_NEXT_SET)
-void
-xfs_dfork_next_set_arch(xfs_dinode_t *dip, int w, int n, xfs_arch_t arch)
-{
- XFS_DFORK_NEXT_SET_ARCH(dip, w, n, arch);
-}
-void
-xfs_dfork_next_set(xfs_dinode_t *dip, int w, int n)
-{
- XFS_DFORK_NEXT_SET(dip, w, n);
-}
-#endif
-
#if XFS_WANT_FUNCS_C || (XFS_WANT_SPACE_C && XFSSO_XFS_DFORK_NEXTENTS)
int
-xfs_dfork_nextents_arch(xfs_dinode_t *dip, int w, xfs_arch_t arch)
-{
- return XFS_DFORK_NEXTENTS_ARCH(dip, w, arch);
-}
-int
xfs_dfork_nextents(xfs_dinode_t *dip, int w)
{
return XFS_DFORK_NEXTENTS(dip, w);
@@ -1013,11 +929,6 @@ xfs_dfork_nextents(xfs_dinode_t *dip, int w)
#if XFS_WANT_FUNCS_C || (XFS_WANT_SPACE_C && XFSSO_XFS_DFORK_PTR)
char *
-xfs_dfork_ptr_arch(xfs_dinode_t *dip, int w, xfs_arch_t arch)
-{
- return XFS_DFORK_PTR_ARCH(dip, w, arch);
-}
-char *
xfs_dfork_ptr(xfs_dinode_t *dip, int w)
{
return XFS_DFORK_PTR(dip, w);
@@ -1026,11 +937,6 @@ xfs_dfork_ptr(xfs_dinode_t *dip, int w)
#if XFS_WANT_FUNCS_C || (XFS_WANT_SPACE_C && XFSSO_XFS_DFORK_Q)
int
-xfs_dfork_q_arch(xfs_dinode_t *dip, xfs_arch_t arch)
-{
- return XFS_DFORK_Q_ARCH(dip, arch);
-}
-int
xfs_dfork_q(xfs_dinode_t *dip)
{
return XFS_DFORK_Q(dip);
@@ -1039,11 +945,6 @@ xfs_dfork_q(xfs_dinode_t *dip)
#if XFS_WANT_FUNCS_C || (XFS_WANT_SPACE_C && XFSSO_XFS_DFORK_SIZE)
int
-xfs_dfork_size_arch(xfs_dinode_t *dip, xfs_mount_t *mp, int w, xfs_arch_t arch)
-{
- return XFS_DFORK_SIZE_ARCH(dip, mp, w, arch);
-}
-int
xfs_dfork_size(xfs_dinode_t *dip, xfs_mount_t *mp, int w)
{
return XFS_DFORK_SIZE(dip, mp, w);
@@ -1108,11 +1009,6 @@ xfs_dir_sf_entsize_byname(int len)
#if XFS_WANT_FUNCS_C || (XFS_WANT_SPACE_C && XFSSO_XFS_DIR_SF_GET_DIRINO)
void
-xfs_dir_sf_get_dirino_arch(xfs_dir_ino_t *from, xfs_ino_t *to, xfs_arch_t arch)
-{
- XFS_DIR_SF_GET_DIRINO_ARCH(from, to, arch);
-}
-void
xfs_dir_sf_get_dirino(xfs_dir_ino_t *from, xfs_ino_t *to)
{
XFS_DIR_SF_GET_DIRINO(from, to);
@@ -1129,11 +1025,6 @@ xfs_dir_sf_nextentry(xfs_dir_sf_entry_t *sfep)
#if XFS_WANT_FUNCS_C || (XFS_WANT_SPACE_C && XFSSO_XFS_DIR_SF_PUT_DIRINO)
void
-xfs_dir_sf_put_dirino_arch(xfs_ino_t *from, xfs_dir_ino_t *to, xfs_arch_t arch)
-{
- XFS_DIR_SF_PUT_DIRINO_ARCH(from, to, arch);
-}
-void
xfs_dir_sf_put_dirino(xfs_ino_t *from, xfs_dir_ino_t *to)
{
XFS_DIR_SF_PUT_DIRINO(from, to);
@@ -1142,9 +1033,9 @@ xfs_dir_sf_put_dirino(xfs_ino_t *from, xfs_dir_ino_t *to)
#if XFS_WANT_FUNCS_C || (XFS_WANT_SPACE_C && XFSSO_XFS_DIR2_BLOCK_LEAF_P)
xfs_dir2_leaf_entry_t *
-xfs_dir2_block_leaf_p_arch(xfs_dir2_block_tail_t *btp, xfs_arch_t arch)
+xfs_dir2_block_leaf_p(xfs_dir2_block_tail_t *btp)
{
- return XFS_DIR2_BLOCK_LEAF_P_ARCH(btp,arch);
+ return XFS_DIR2_BLOCK_LEAF_P(btp);
}
#endif
@@ -1223,9 +1114,9 @@ xfs_dir2_data_entsize(int n)
#if XFS_WANT_FUNCS_C || (XFS_WANT_SPACE_C && XFSSO_XFS_DIR2_DATA_UNUSED_TAG_P)
xfs_dir2_data_off_t *
-xfs_dir2_data_unused_tag_p_arch(xfs_dir2_data_unused_t *dup, xfs_arch_t arch)
+xfs_dir2_data_unused_tag_p(xfs_dir2_data_unused_t *dup)
{
- return XFS_DIR2_DATA_UNUSED_TAG_P_ARCH(dup,arch);
+ return XFS_DIR2_DATA_UNUSED_TAG_P(dup);
}
#endif
@@ -1298,9 +1189,9 @@ xfs_dir2_db_to_fdindex(xfs_mount_t *mp, xfs_dir2_db_t db)
#if XFS_WANT_FUNCS_C || (XFS_WANT_SPACE_C && XFSSO_XFS_DIR2_LEAF_BESTS_P)
xfs_dir2_data_off_t *
-xfs_dir2_leaf_bests_p_arch(xfs_dir2_leaf_tail_t *ltp, xfs_arch_t arch)
+xfs_dir2_leaf_bests_p(xfs_dir2_leaf_tail_t *ltp)
{
- return XFS_DIR2_LEAF_BESTS_P_ARCH(ltp, arch);
+ return XFS_DIR2_LEAF_BESTS_P(ltp);
}
#endif
@@ -1346,17 +1237,17 @@ xfs_dir2_sf_entsize_byname(xfs_dir2_sf_t *sfp, int len)
#if XFS_WANT_FUNCS_C || (XFS_WANT_SPACE_C && XFSSO_XFS_DIR2_SF_GET_INUMBER)
xfs_intino_t
-xfs_dir2_sf_get_inumber_arch(xfs_dir2_sf_t *sfp, xfs_dir2_inou_t *from, xfs_arch_t arch)
+xfs_dir2_sf_get_inumber(xfs_dir2_sf_t *sfp, xfs_dir2_inou_t *from)
{
- return XFS_DIR2_SF_GET_INUMBER_ARCH(sfp, from, arch);
+ return XFS_DIR2_SF_GET_INUMBER(sfp, from);
}
#endif
#if XFS_WANT_FUNCS_C || (XFS_WANT_SPACE_C && XFSSO_XFS_DIR2_SF_GET_OFFSET)
xfs_dir2_data_aoff_t
-xfs_dir2_sf_get_offset_arch(xfs_dir2_sf_entry_t *sfep, xfs_arch_t arch)
+xfs_dir2_sf_get_offset(xfs_dir2_sf_entry_t *sfep)
{
- return XFS_DIR2_SF_GET_OFFSET_ARCH(sfep, arch);
+ return XFS_DIR2_SF_GET_OFFSET(sfep);
}
#endif
@@ -1386,17 +1277,17 @@ xfs_dir2_sf_nextentry(xfs_dir2_sf_t *sfp, xfs_dir2_sf_entry_t *sfep)
#if XFS_WANT_FUNCS_C || (XFS_WANT_SPACE_C && XFSSO_XFS_DIR2_SF_PUT_INUMBER)
void
-xfs_dir2_sf_put_inumber_arch(xfs_dir2_sf_t *sfp, xfs_ino_t *from, xfs_dir2_inou_t *to, xfs_arch_t arch)
+xfs_dir2_sf_put_inumber(xfs_dir2_sf_t *sfp, xfs_ino_t *from, xfs_dir2_inou_t *to)
{
- XFS_DIR2_SF_PUT_INUMBER_ARCH(sfp, from, to, arch);
+ XFS_DIR2_SF_PUT_INUMBER(sfp, from, to);
}
#endif
#if XFS_WANT_FUNCS_C || (XFS_WANT_SPACE_C && XFSSO_XFS_DIR2_SF_PUT_OFFSET)
void
-xfs_dir2_sf_put_offset_arch(xfs_dir2_sf_entry_t *sfep, xfs_dir2_data_aoff_t off, xfs_arch_t arch)
+xfs_dir2_sf_put_offset(xfs_dir2_sf_entry_t *sfep, xfs_dir2_data_aoff_t off)
{
- XFS_DIR2_SF_PUT_OFFSET_ARCH(sfep, off, arch);
+ XFS_DIR2_SF_PUT_OFFSET(sfep, off);
}
#endif
@@ -1755,17 +1646,17 @@ xfs_inobt_block_size(int lev, xfs_btree_cur_t *cur)
#if XFS_WANT_FUNCS_C || (XFS_WANT_SPACE_C && XFSSO_XFS_INOBT_CLR_FREE)
void
-xfs_inobt_clr_free(xfs_inobt_rec_t *rp, int i, xfs_arch_t arch)
+xfs_inobt_clr_free(xfs_inobt_rec_t *rp, int i)
{
- XFS_INOBT_CLR_FREE(rp, i, arch);
+ XFS_INOBT_CLR_FREE(rp, i);
}
#endif
#if XFS_WANT_FUNCS_C || (XFS_WANT_SPACE_C && XFSSO_XFS_INOBT_IS_FREE)
int
-xfs_inobt_is_free(xfs_inobt_rec_t *rp, int i, xfs_arch_t arch)
+xfs_inobt_is_free(xfs_inobt_rec_t *rp, int i)
{
- return XFS_INOBT_IS_FREE(rp, i, arch);
+ return XFS_INOBT_IS_FREE(rp, i);
}
#endif
@@ -1821,9 +1712,9 @@ xfs_inobt_rec_addr(xfs_inobt_block_t *bb, int i, xfs_btree_cur_t *cur)
#if XFS_WANT_FUNCS_C || (XFS_WANT_SPACE_C && XFSSO_XFS_INOBT_SET_FREE)
void
-xfs_inobt_set_free(xfs_inobt_rec_t *rp, int i, xfs_arch_t arch)
+xfs_inobt_set_free(xfs_inobt_rec_t *rp, int i)
{
- XFS_INOBT_SET_FREE(rp, i, arch);
+ XFS_INOBT_SET_FREE(rp, i);
}
#endif
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index 96e94778940aa..b57423caef9b8 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -65,8 +65,6 @@ STATIC void xfs_mount_log_sbunit(xfs_mount_t *, __int64_t);
STATIC int xfs_uuid_mount(xfs_mount_t *);
STATIC void xfs_uuid_unmount(xfs_mount_t *mp);
-void xfs_xlatesb(void *, xfs_sb_t *, int, xfs_arch_t, __int64_t);
-
static struct {
short offset;
short type; /* 0 = integer
@@ -387,7 +385,6 @@ xfs_initialize_perag(xfs_mount_t *mp, xfs_agnumber_t agcount)
* sb - a superblock
* dir - conversion direction: <0 - convert sb to buf
* >0 - convert buf to sb
- * arch - architecture to read/write from/to buf
* fields - which fields to copy (bitmask)
*/
void
@@ -395,7 +392,6 @@ xfs_xlatesb(
void *data,
xfs_sb_t *sb,
int dir,
- xfs_arch_t arch,
__int64_t fields)
{
xfs_caddr_t buf_ptr;
@@ -420,9 +416,7 @@ xfs_xlatesb(
ASSERT(xfs_sb_info[f].type == 0 || xfs_sb_info[f].type == 1);
- if (arch == ARCH_NOCONVERT ||
- size == 1 ||
- xfs_sb_info[f].type == 1) {
+ if (size == 1 || xfs_sb_info[f].type == 1) {
if (dir > 0) {
memcpy(mem_ptr + first, buf_ptr + first, size);
} else {
@@ -433,16 +427,16 @@ xfs_xlatesb(
case 2:
INT_XLATE(*(__uint16_t*)(buf_ptr+first),
*(__uint16_t*)(mem_ptr+first),
- dir, arch);
+ dir, ARCH_CONVERT);
break;
case 4:
INT_XLATE(*(__uint32_t*)(buf_ptr+first),
*(__uint32_t*)(mem_ptr+first),
- dir, arch);
+ dir, ARCH_CONVERT);
break;
case 8:
INT_XLATE(*(__uint64_t*)(buf_ptr+first),
- *(__uint64_t*)(mem_ptr+first), dir, arch);
+ *(__uint64_t*)(mem_ptr+first), dir, ARCH_CONVERT);
break;
default:
ASSERT(0);
@@ -493,8 +487,7 @@ xfs_readsb(xfs_mount_t *mp)
* But first do some basic consistency checking.
*/
sbp = XFS_BUF_TO_SBP(bp);
- xfs_xlatesb(XFS_BUF_PTR(bp), &(mp->m_sb), 1,
- ARCH_CONVERT, XFS_SB_ALL_BITS);
+ xfs_xlatesb(XFS_BUF_PTR(bp), &(mp->m_sb), 1, XFS_SB_ALL_BITS);
error = xfs_mount_validate_sb(mp, &(mp->m_sb));
if (error) {
@@ -1227,7 +1220,7 @@ xfs_mod_sb(xfs_trans_t *tp, __int64_t fields)
/* translate/copy */
- xfs_xlatesb(XFS_BUF_PTR(bp), &(mp->m_sb), -1, ARCH_CONVERT, fields);
+ xfs_xlatesb(XFS_BUF_PTR(bp), &(mp->m_sb), -1, fields);
/* find modified range */
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index ef727508e3a2a..5fc6201dd8e29 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000-2004 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
@@ -418,6 +418,8 @@ typedef struct xfs_mount {
#define XFS_MOUNT_IDELETE 0x00040000 /* delete empty inode clusters*/
#define XFS_MOUNT_SWALLOC 0x00080000 /* turn on stripe width
* allocation */
+#define XFS_MOUNT_IHASHSIZE 0x00100000 /* inode hash table size */
+#define XFS_MOUNT_DIRSYNC 0x00200000 /* synchronous directory ops */
/*
* Default minimum read and write sizes.
@@ -554,8 +556,7 @@ extern void xfs_freesb(xfs_mount_t *);
extern void xfs_do_force_shutdown(bhv_desc_t *, int, char *, int);
extern int xfs_syncsub(xfs_mount_t *, int, int, int *);
extern xfs_agnumber_t xfs_initialize_perag(xfs_mount_t *, xfs_agnumber_t);
-extern void xfs_xlatesb(void *, struct xfs_sb *, int, xfs_arch_t,
- __int64_t);
+extern void xfs_xlatesb(void *, struct xfs_sb *, int, __int64_t);
extern struct vfsops xfs_vfsops;
extern struct vnodeops xfs_vnodeops;
diff --git a/fs/xfs/xfs_rename.c b/fs/xfs/xfs_rename.c
index 876f6908212e6..cb13f9a1d45ba 100644
--- a/fs/xfs/xfs_rename.c
+++ b/fs/xfs/xfs_rename.c
@@ -589,7 +589,7 @@ xfs_rename(
* rename transaction goes to disk before returning to
* the user.
*/
- if (mp->m_flags & XFS_MOUNT_WSYNC) {
+ if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC)) {
xfs_trans_set_sync(tp);
}
diff --git a/fs/xfs/xfs_vfsops.c b/fs/xfs/xfs_vfsops.c
index 7745d23eae7fc..00aae9c6a904e 100644
--- a/fs/xfs/xfs_vfsops.c
+++ b/fs/xfs/xfs_vfsops.c
@@ -1,7 +1,7 @@
/*
* XFS filesystem operations.
*
- * Copyright (c) 2000-2004 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
@@ -258,11 +258,6 @@ xfs_start_flags(
mp->m_fsname = kmem_alloc(mp->m_fsname_len, KM_SLEEP);
strcpy(mp->m_fsname, ap->fsname);
- /*
- * Pull in the 'wsync' and 'ino64' mount options before we do the real
- * work of mounting and recovery. The arg pointer will
- * be NULL when we are being called from the root mount code.
- */
if (ap->flags & XFSMNT_WSYNC)
mp->m_flags |= XFS_MOUNT_WSYNC;
#if XFS_BIG_INUMS
@@ -302,9 +297,16 @@ xfs_start_flags(
mp->m_flags |= XFS_MOUNT_DFLT_IOSIZE;
mp->m_readio_log = mp->m_writeio_log = ap->iosizelog;
}
+
+ if (ap->flags & XFSMNT_IHASHSIZE)
+ mp->m_flags |= XFS_MOUNT_IHASHSIZE;
+
if (ap->flags & XFSMNT_IDELETE)
mp->m_flags |= XFS_MOUNT_IDELETE;
+ if (ap->flags & XFSMNT_DIRSYNC)
+ mp->m_flags |= XFS_MOUNT_DIRSYNC;
+
/*
* no recovery flag requires a read-only mount
*/
@@ -1742,6 +1744,7 @@ xfs_parseargs(
this_char);
return EINVAL;
}
+ args->flags |= XFSMNT_IHASHSIZE;
args->ihashsize = simple_strtoul(value, &eov, 10);
} else if (!strcmp(this_char, MNTOPT_WSYNC)) {
args->flags |= XFSMNT_WSYNC;
@@ -1870,6 +1873,9 @@ xfs_showargs(
seq_puts(m, xfs_infop->str);
}
+ if (mp->m_flags & XFS_MOUNT_IHASHSIZE)
+ seq_printf(m, "," MNTOPT_IHASHSIZE "=%d", mp->m_ihsize);
+
if (mp->m_flags & XFS_MOUNT_DFLT_IOSIZE)
seq_printf(m, "," MNTOPT_BIOSIZE "=%d", mp->m_writeio_log);
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index 4a2b6a5483e8e..70092963ca9eb 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) 2000-2004 Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
@@ -248,7 +248,7 @@ xfs_getattr(
/*
* Convert di_flags to xflags.
*/
- vap->va_xflags = xfs_dic2xflags(&ip->i_d, ARCH_NOCONVERT);
+ vap->va_xflags = xfs_ip2xflags(ip);
/*
* Exit for inode revalidate. See if any of the rest of
@@ -1995,7 +1995,7 @@ xfs_create(
* create transaction goes to disk before returning to
* the user.
*/
- if (mp->m_flags & XFS_MOUNT_WSYNC) {
+ if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC)) {
xfs_trans_set_sync(tp);
}
@@ -2492,7 +2492,7 @@ xfs_remove(
* remove transaction goes to disk before returning to
* the user.
*/
- if (mp->m_flags & XFS_MOUNT_WSYNC) {
+ if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC)) {
xfs_trans_set_sync(tp);
}
@@ -2704,7 +2704,7 @@ xfs_link(
* link transaction goes to disk before returning to
* the user.
*/
- if (mp->m_flags & XFS_MOUNT_WSYNC) {
+ if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC)) {
xfs_trans_set_sync(tp);
}
@@ -2921,7 +2921,7 @@ xfs_mkdir(
* mkdir transaction goes to disk before returning to
* the user.
*/
- if (mp->m_flags & XFS_MOUNT_WSYNC) {
+ if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC)) {
xfs_trans_set_sync(tp);
}
@@ -3168,7 +3168,7 @@ xfs_rmdir(
* rmdir transaction goes to disk before returning to
* the user.
*/
- if (mp->m_flags & XFS_MOUNT_WSYNC) {
+ if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC)) {
xfs_trans_set_sync(tp);
}
@@ -3520,7 +3520,7 @@ xfs_symlink(
* symlink transaction goes to disk before returning to
* the user.
*/
- if (mp->m_flags & XFS_MOUNT_WSYNC) {
+ if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC)) {
xfs_trans_set_sync(tp);
}
diff --git a/include/asm-alpha/bitops.h b/include/asm-alpha/bitops.h
index c9d69c99e4700..578ed3f1a6071 100644
--- a/include/asm-alpha/bitops.h
+++ b/include/asm-alpha/bitops.h
@@ -353,9 +353,9 @@ static inline unsigned long hweight64(unsigned long w)
return __kernel_ctpop(w);
}
-#define hweight32(x) hweight64((x) & 0xfffffffful)
-#define hweight16(x) hweight64((x) & 0xfffful)
-#define hweight8(x) hweight64((x) & 0xfful)
+#define hweight32(x) (unsigned int) hweight64((x) & 0xfffffffful)
+#define hweight16(x) (unsigned int) hweight64((x) & 0xfffful)
+#define hweight8(x) (unsigned int) hweight64((x) & 0xfful)
#else
static inline unsigned long hweight64(unsigned long w)
{
diff --git a/include/asm-alpha/cacheflush.h b/include/asm-alpha/cacheflush.h
index 40a11e4cfff3e..3fc6ef726d8c2 100644
--- a/include/asm-alpha/cacheflush.h
+++ b/include/asm-alpha/cacheflush.h
@@ -8,7 +8,7 @@
#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)
-#define flush_cache_page(vma, vmaddr) do { } while (0)
+#define flush_cache_page(vma, vmaddr, pfn) do { } while (0)
#define flush_dcache_page(page) do { } while (0)
#define flush_dcache_mmap_lock(mapping) do { } while (0)
#define flush_dcache_mmap_unlock(mapping) do { } while (0)
diff --git a/include/asm-alpha/io.h b/include/asm-alpha/io.h
index 68907d940af1e..871dd7ad909d0 100644
--- a/include/asm-alpha/io.h
+++ b/include/asm-alpha/io.h
@@ -666,6 +666,17 @@ isa_memcpy_toio(unsigned long offset, const void *src, long n)
#define writeq writeq
#define readq readq
+/*
+ * Convert a physical pointer to a virtual kernel pointer for /dev/mem
+ * access
+ */
+#define xlate_dev_mem_ptr(p) __va(p)
+
+/*
+ * Convert a virtual cached pointer to an uncached pointer
+ */
+#define xlate_dev_kmem_ptr(p) p
+
#endif /* __KERNEL__ */
#endif /* __ALPHA_IO_H */
diff --git a/include/asm-alpha/pci.h b/include/asm-alpha/pci.h
index bbefe1238d636..0c7b57bc043a6 100644
--- a/include/asm-alpha/pci.h
+++ b/include/asm-alpha/pci.h
@@ -223,22 +223,21 @@ pci_dac_dma_sync_single_for_device(struct pci_dev *pdev, dma64_addr_t dma_addr,
/* Nothing to do. */
}
+/* TODO: integrate with include/asm-generic/pci.h ? */
+static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
+{
+ return channel ? 15 : 14;
+}
+
extern void pcibios_resource_to_bus(struct pci_dev *, struct pci_bus_region *,
struct resource *);
#define pci_domain_nr(bus) ((struct pci_controller *)(bus)->sysdata)->index
-static inline int
-pci_name_bus(char *name, struct pci_bus *bus)
+static inline int pci_proc_domain(struct pci_bus *bus)
{
struct pci_controller *hose = bus->sysdata;
-
- if (likely(hose->need_domain_info == 0)) {
- sprintf(name, "%02x", bus->number);
- } else {
- sprintf(name, "%04x:%02x", hose->index, bus->number);
- }
- return 0;
+ return hose->need_domain_info;
}
static inline void
diff --git a/include/asm-alpha/pgtable.h b/include/asm-alpha/pgtable.h
index a22e394a3d526..faae196d83773 100644
--- a/include/asm-alpha/pgtable.h
+++ b/include/asm-alpha/pgtable.h
@@ -22,6 +22,7 @@
* hook is made available.
*/
#define set_pte(pteptr, pteval) ((*(pteptr)) = (pteval))
+#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
/* PMD_SHIFT determines the size of the area a second-level page table can map */
#define PMD_SHIFT (PAGE_SHIFT + (PAGE_SHIFT-3))
@@ -235,7 +236,10 @@ extern inline unsigned long pgd_page(pgd_t pgd)
extern inline int pte_none(pte_t pte) { return !pte_val(pte); }
extern inline int pte_present(pte_t pte) { return pte_val(pte) & _PAGE_VALID; }
-extern inline void pte_clear(pte_t *ptep) { pte_val(*ptep) = 0; }
+extern inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
+{
+ pte_val(*ptep) = 0;
+}
extern inline int pmd_none(pmd_t pmd) { return !pmd_val(pmd); }
extern inline int pmd_bad(pmd_t pmd) { return (pmd_val(pmd) & ~_PFN_MASK) != _PAGE_TABLE; }
@@ -336,6 +340,13 @@ extern inline pte_t mk_swap_pte(unsigned long type, unsigned long offset)
remap_pfn_range(vma, start, pfn, size, prot); \
})
+#define io_remap_pfn_range(vma, start, pfn, size, prot) \
+ remap_pfn_range(vma, start, pfn, size, prot)
+
+#define MK_IOSPACE_PFN(space, pfn) (pfn)
+#define GET_IOSPACE(pfn) 0
+#define GET_PFN(pfn) (pfn)
+
#define pte_ERROR(e) \
printk("%s:%d: bad pte %016lx.\n", __FILE__, __LINE__, pte_val(e))
#define pmd_ERROR(e) \
diff --git a/include/asm-alpha/resource.h b/include/asm-alpha/resource.h
index f9fb6607d3656..c10874ff59736 100644
--- a/include/asm-alpha/resource.h
+++ b/include/asm-alpha/resource.h
@@ -2,32 +2,20 @@
#define _ALPHA_RESOURCE_H
/*
- * Resource limits
+ * Alpha/Linux-specific ordering of these four resource limit IDs,
+ * the rest comes from the generic header:
*/
-
-#define RLIMIT_CPU 0 /* CPU time in ms */
-#define RLIMIT_FSIZE 1 /* Maximum filesize */
-#define RLIMIT_DATA 2 /* max data size */
-#define RLIMIT_STACK 3 /* max stack size */
-#define RLIMIT_CORE 4 /* max core file size */
-#define RLIMIT_RSS 5 /* max resident set size */
-#define RLIMIT_NOFILE 6 /* max number of open files */
-#define RLIMIT_AS 7 /* address space limit(?) */
-#define RLIMIT_NPROC 8 /* max number of processes */
-#define RLIMIT_MEMLOCK 9 /* max locked-in-memory address space */
-#define RLIMIT_LOCKS 10 /* maximum file locks held */
-#define RLIMIT_SIGPENDING 11 /* max number of pending signals */
-#define RLIMIT_MSGQUEUE 12 /* maximum bytes in POSIX mqueues */
-
-#define RLIM_NLIMITS 13
-#define __ARCH_RLIMIT_ORDER
+#define RLIMIT_NOFILE 6 /* max number of open files */
+#define RLIMIT_AS 7 /* address space limit */
+#define RLIMIT_NPROC 8 /* max number of processes */
+#define RLIMIT_MEMLOCK 9 /* max locked-in-memory address space */
/*
* SuS says limits have to be unsigned. Fine, it's unsigned, but
* we retain the old value for compatibility, especially with DU.
* When you run into the 2^63 barrier, you call me.
*/
-#define RLIM_INFINITY 0x7ffffffffffffffful
+#define RLIM_INFINITY 0x7ffffffffffffffful
#include <asm-generic/resource.h>
diff --git a/include/asm-alpha/spinlock.h b/include/asm-alpha/spinlock.h
index 5e35c5d7aa7f5..80780dba9986f 100644
--- a/include/asm-alpha/spinlock.h
+++ b/include/asm-alpha/spinlock.h
@@ -15,7 +15,7 @@
*/
typedef struct {
- volatile unsigned int lock /*__attribute__((aligned(32))) */;
+ volatile unsigned int lock;
#ifdef CONFIG_DEBUG_SPINLOCK
int on_cpu;
int line_no;
@@ -23,40 +23,26 @@ typedef struct {
struct task_struct * task;
const char *base_file;
#endif
-#ifdef CONFIG_PREEMPT
- unsigned int break_lock;
-#endif
} spinlock_t;
#ifdef CONFIG_DEBUG_SPINLOCK
-#define SPIN_LOCK_UNLOCKED (spinlock_t) {0, -1, 0, NULL, NULL, NULL}
-#define spin_lock_init(x) \
- ((x)->lock = 0, (x)->on_cpu = -1, (x)->previous = NULL, (x)->task = NULL)
+#define SPIN_LOCK_UNLOCKED (spinlock_t){ 0, -1, 0, NULL, NULL, NULL }
#else
-#define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 }
-#define spin_lock_init(x) ((x)->lock = 0)
+#define SPIN_LOCK_UNLOCKED (spinlock_t){ 0 }
#endif
+#define spin_lock_init(x) do { *(x) = SPIN_LOCK_UNLOCKED; } while(0)
#define spin_is_locked(x) ((x)->lock != 0)
-#define spin_unlock_wait(x) ({ do { barrier(); } while ((x)->lock); })
-#define _raw_spin_lock_flags(lock, flags) _raw_spin_lock(lock)
+#define spin_unlock_wait(x) do { barrier(); } while ((x)->lock)
#ifdef CONFIG_DEBUG_SPINLOCK
extern void _raw_spin_unlock(spinlock_t * lock);
extern void debug_spin_lock(spinlock_t * lock, const char *, int);
extern int debug_spin_trylock(spinlock_t * lock, const char *, int);
-
-#define _raw_spin_lock(LOCK) debug_spin_lock(LOCK, __BASE_FILE__, __LINE__)
-#define _raw_spin_trylock(LOCK) debug_spin_trylock(LOCK, __BASE_FILE__, __LINE__)
-
-#define spin_lock_own(LOCK, LOCATION) \
-do { \
- if (!((LOCK)->lock && (LOCK)->on_cpu == smp_processor_id())) \
- printk("%s: called on %d from %p but lock %s on %d\n", \
- LOCATION, smp_processor_id(), \
- __builtin_return_address(0), \
- (LOCK)->lock ? "taken" : "freed", (LOCK)->on_cpu); \
-} while (0)
+#define _raw_spin_lock(LOCK) \
+ debug_spin_lock(LOCK, __BASE_FILE__, __LINE__)
+#define _raw_spin_trylock(LOCK) \
+ debug_spin_trylock(LOCK, __BASE_FILE__, __LINE__)
#else
static inline void _raw_spin_unlock(spinlock_t * lock)
{
@@ -68,19 +54,16 @@ static inline void _raw_spin_lock(spinlock_t * lock)
{
long tmp;
- /* Use sub-sections to put the actual loop at the end
- of this object file's text section so as to perfect
- branch prediction. */
__asm__ __volatile__(
"1: ldl_l %0,%1\n"
- " blbs %0,2f\n"
- " or %0,1,%0\n"
+ " bne %0,2f\n"
+ " lda %0,1\n"
" stl_c %0,%1\n"
" beq %0,2f\n"
" mb\n"
".subsection 2\n"
"2: ldl %0,%1\n"
- " blbs %0,2b\n"
+ " bne %0,2b\n"
" br 1b\n"
".previous"
: "=&r" (tmp), "=m" (lock->lock)
@@ -91,22 +74,29 @@ static inline int _raw_spin_trylock(spinlock_t *lock)
{
return !test_and_set_bit(0, &lock->lock);
}
-
-#define spin_lock_own(LOCK, LOCATION) ((void)0)
#endif /* CONFIG_DEBUG_SPINLOCK */
+#define _raw_spin_lock_flags(lock, flags) _raw_spin_lock(lock)
+
/***********************************************************/
typedef struct {
- volatile unsigned int write_lock:1, read_counter:31;
-#ifdef CONFIG_PREEMPT
- unsigned int break_lock;
-#endif
-} /*__attribute__((aligned(32)))*/ rwlock_t;
+ volatile unsigned int lock;
+} rwlock_t;
-#define RW_LOCK_UNLOCKED (rwlock_t) { 0, 0 }
+#define RW_LOCK_UNLOCKED (rwlock_t){ 0 }
-#define rwlock_init(x) do { *(x) = RW_LOCK_UNLOCKED; } while(0)
+#define rwlock_init(x) do { *(x) = RW_LOCK_UNLOCKED; } while(0)
+
+static inline int read_can_lock(rwlock_t *lock)
+{
+ return (lock->lock & 1) == 0;
+}
+
+static inline int write_can_lock(rwlock_t *lock)
+{
+ return lock->lock == 0;
+}
#ifdef CONFIG_DEBUG_RWLOCK
extern void _raw_write_lock(rwlock_t * lock);
@@ -119,7 +109,7 @@ static inline void _raw_write_lock(rwlock_t * lock)
__asm__ __volatile__(
"1: ldl_l %1,%0\n"
" bne %1,6f\n"
- " or $31,1,%1\n"
+ " lda %1,1\n"
" stl_c %1,%0\n"
" beq %1,6f\n"
" mb\n"
@@ -142,7 +132,7 @@ static inline void _raw_read_lock(rwlock_t * lock)
" subl %1,2,%1\n"
" stl_c %1,%0\n"
" beq %1,6f\n"
- "4: mb\n"
+ " mb\n"
".subsection 2\n"
"6: ldl %1,%0\n"
" blbs %1,6b\n"
@@ -153,6 +143,28 @@ static inline void _raw_read_lock(rwlock_t * lock)
}
#endif /* CONFIG_DEBUG_RWLOCK */
+static inline int _raw_read_trylock(rwlock_t * lock)
+{
+ long regx;
+ int success;
+
+ __asm__ __volatile__(
+ "1: ldl_l %1,%0\n"
+ " lda %2,0\n"
+ " blbs %1,2f\n"
+ " subl %1,2,%2\n"
+ " stl_c %2,%0\n"
+ " beq %2,6f\n"
+ "2: mb\n"
+ ".subsection 2\n"
+ "6: br 1b\n"
+ ".previous"
+ : "=m" (*lock), "=&r" (regx), "=&r" (success)
+ : "m" (*lock) : "memory");
+
+ return success;
+}
+
static inline int _raw_write_trylock(rwlock_t * lock)
{
long regx;
@@ -162,10 +174,9 @@ static inline int _raw_write_trylock(rwlock_t * lock)
"1: ldl_l %1,%0\n"
" lda %2,0\n"
" bne %1,2f\n"
- " or $31,1,%1\n"
- " stl_c %1,%0\n"
- " beq %1,6f\n"
" lda %2,1\n"
+ " stl_c %2,%0\n"
+ " beq %2,6f\n"
"2: mb\n"
".subsection 2\n"
"6: br 1b\n"
@@ -179,7 +190,7 @@ static inline int _raw_write_trylock(rwlock_t * lock)
static inline void _raw_write_unlock(rwlock_t * lock)
{
mb();
- *(volatile int *)lock = 0;
+ lock->lock = 0;
}
static inline void _raw_read_unlock(rwlock_t * lock)
diff --git a/include/asm-alpha/system.h b/include/asm-alpha/system.h
index bba276c50b15e..c08ce970ff8c9 100644
--- a/include/asm-alpha/system.h
+++ b/include/asm-alpha/system.h
@@ -621,4 +621,6 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
#endif /* __ASSEMBLY__ */
+#define arch_align_stack(x) (x)
+
#endif
diff --git a/include/asm-alpha/timex.h b/include/asm-alpha/timex.h
index f3737a1ee6986..afa0c45e3e987 100644
--- a/include/asm-alpha/timex.h
+++ b/include/asm-alpha/timex.h
@@ -20,7 +20,6 @@
*/
typedef unsigned int cycles_t;
-extern cycles_t cacheflush_time;
static inline cycles_t get_cycles (void)
{
diff --git a/include/asm-alpha/uaccess.h b/include/asm-alpha/uaccess.h
index a656a38df0b35..4c39ee750f388 100644
--- a/include/asm-alpha/uaccess.h
+++ b/include/asm-alpha/uaccess.h
@@ -48,7 +48,8 @@
__access_ok(((unsigned long)(addr)),(size),get_fs()); \
})
-extern inline int verify_area(int type, const void __user * addr, unsigned long size)
+/* this function will go away soon - use access_ok() instead */
+extern inline int __deprecated verify_area(int type, const void __user * addr, unsigned long size)
{
return access_ok(type,addr,size) ? 0 : -EFAULT;
}
diff --git a/include/asm-alpha/unaligned.h b/include/asm-alpha/unaligned.h
index 2090db872bcc4..a1d72846f61ca 100644
--- a/include/asm-alpha/unaligned.h
+++ b/include/asm-alpha/unaligned.h
@@ -1,114 +1,6 @@
#ifndef __ALPHA_UNALIGNED_H
#define __ALPHA_UNALIGNED_H
-/*
- * The main single-value unaligned transfer routines.
- */
-#define get_unaligned(ptr) \
- ((__typeof__(*(ptr)))__get_unaligned((ptr), sizeof(*(ptr))))
-#define put_unaligned(x,ptr) \
- __put_unaligned((unsigned long)(x), (ptr), sizeof(*(ptr)))
-
-/*
- * This is a silly but good way to make sure that
- * the get/put functions are indeed always optimized,
- * and that we use the correct sizes.
- */
-extern void bad_unaligned_access_length(void) __attribute__((noreturn));
-
-/*
- * EGCS 1.1 knows about arbitrary unaligned loads. Define some
- * packed structures to talk about such things with.
- */
-
-struct __una_u64 { __u64 x __attribute__((packed)); };
-struct __una_u32 { __u32 x __attribute__((packed)); };
-struct __una_u16 { __u16 x __attribute__((packed)); };
-
-/*
- * Elemental unaligned loads
- */
-
-extern inline unsigned long __uldq(const unsigned long * r11)
-{
- const struct __una_u64 *ptr = (const struct __una_u64 *) r11;
- return ptr->x;
-}
-
-extern inline unsigned long __uldl(const unsigned int * r11)
-{
- const struct __una_u32 *ptr = (const struct __una_u32 *) r11;
- return ptr->x;
-}
-
-extern inline unsigned long __uldw(const unsigned short * r11)
-{
- const struct __una_u16 *ptr = (const struct __una_u16 *) r11;
- return ptr->x;
-}
-
-/*
- * Elemental unaligned stores
- */
-
-extern inline void __ustq(unsigned long r5, unsigned long * r11)
-{
- struct __una_u64 *ptr = (struct __una_u64 *) r11;
- ptr->x = r5;
-}
-
-extern inline void __ustl(unsigned long r5, unsigned int * r11)
-{
- struct __una_u32 *ptr = (struct __una_u32 *) r11;
- ptr->x = r5;
-}
-
-extern inline void __ustw(unsigned long r5, unsigned short * r11)
-{
- struct __una_u16 *ptr = (struct __una_u16 *) r11;
- ptr->x = r5;
-}
-
-extern inline unsigned long __get_unaligned(const void *ptr, size_t size)
-{
- unsigned long val;
- switch (size) {
- case 1:
- val = *(const unsigned char *)ptr;
- break;
- case 2:
- val = __uldw((const unsigned short *)ptr);
- break;
- case 4:
- val = __uldl((const unsigned int *)ptr);
- break;
- case 8:
- val = __uldq((const unsigned long *)ptr);
- break;
- default:
- bad_unaligned_access_length();
- }
- return val;
-}
-
-extern inline void __put_unaligned(unsigned long val, void *ptr, size_t size)
-{
- switch (size) {
- case 1:
- *(unsigned char *)ptr = (val);
- break;
- case 2:
- __ustw(val, (unsigned short *)ptr);
- break;
- case 4:
- __ustl(val, (unsigned int *)ptr);
- break;
- case 8:
- __ustq(val, (unsigned long *)ptr);
- break;
- default:
- bad_unaligned_access_length();
- }
-}
+#include <asm-generic/unaligned.h>
#endif
diff --git a/include/asm-alpha/unistd.h b/include/asm-alpha/unistd.h
index 947e5a40e9713..c4e70e8617eb6 100644
--- a/include/asm-alpha/unistd.h
+++ b/include/asm-alpha/unistd.h
@@ -651,6 +651,6 @@ asmlinkage long sys_rt_sigaction(int sig,
have declarations. If we use no prototype, then we get warnings from
-Wstrict-prototypes. Ho hum. */
-#define cond_syscall(x) asm(".weak\t" #x "\n" #x " = sys_ni_syscall");
+#define cond_syscall(x) asm(".weak\t" #x "\n" #x " = sys_ni_syscall")
#endif /* _ALPHA_UNISTD_H */
diff --git a/include/asm-arm/arch-cl7500/hardware.h b/include/asm-arm/arch-cl7500/hardware.h
index 06dc927ad7615..2339b764f69f6 100644
--- a/include/asm-arm/arch-cl7500/hardware.h
+++ b/include/asm-arm/arch-cl7500/hardware.h
@@ -13,6 +13,12 @@
#include <asm/arch/memory.h>
#include <asm/hardware/iomd.h>
+#ifdef __ASSEMBLY__
+#define IOMEM(x) x
+#else
+#define IOMEM(x) ((void __iomem *)(x))
+#endif
+
/*
* What hardware must be present
*/
@@ -27,7 +33,7 @@
#define IO_START 0x03000000 /* I/O */
#define IO_SIZE 0x01000000
-#define IO_BASE 0xe0000000
+#define IO_BASE IOMEM(0xe0000000)
#define ISA_START 0x0c000000 /* ISA */
#define ISA_SIZE 0x00010000
@@ -49,11 +55,11 @@
#define FLUSH_BASE 0xdf000000
-#define VIDC_BASE 0xe0400000
-#define IOMD_BASE 0xe0200000
-#define IOC_BASE 0xe0200000
-#define FLOPPYDMA_BASE 0xe002a000
-#define PCIO_BASE 0xe0010000
+#define VIDC_BASE (void __iomem *)0xe0400000
+#define IOMD_BASE IOMEM(0xe0200000)
+#define IOC_BASE IOMEM(0xe0200000)
+#define FLOPPYDMA_BASE IOMEM(0xe002a000)
+#define PCIO_BASE IOMEM(0xe0010000)
#define FLUSH_BASE_PHYS 0x00000000 /* ROM */
@@ -63,4 +69,3 @@
#define ISASLOT_IO 0x80400000
#endif
-
diff --git a/include/asm-arm/arch-imx/hardware.h b/include/asm-arm/arch-imx/hardware.h
index c5d559fdb6235..adffb6acf42a2 100644
--- a/include/asm-arm/arch-imx/hardware.h
+++ b/include/asm-arm/arch-imx/hardware.h
@@ -26,9 +26,7 @@
#ifndef __ASSEMBLY__
# define __REG(x) (*((volatile u32 *)IO_ADDRESS(x)))
-# define __REG2(x,y) \
- ( __builtin_constant_p(y) ? (__REG((x) + (y))) \
- : (*(volatile u32 *)((u32)&__REG(x) + (y))) )
+# define __REG2(x,y) (*(volatile u32 *)((u32)&__REG(x) + (y)))
#endif
/*
diff --git a/include/asm-arm/arch-ixp2000/entry-macro.S b/include/asm-arm/arch-ixp2000/entry-macro.S
index 44db57c79c898..e3a4e41212985 100644
--- a/include/asm-arm/arch-ixp2000/entry-macro.S
+++ b/include/asm-arm/arch-ixp2000/entry-macro.S
@@ -15,8 +15,7 @@
mov \irqnr, #0x0 @clear out irqnr as default
mov \base, #0xfe000000
- orr \base, \base, #0x00ff0000
- orr \base, \base, #0x0000a000
+ orr \base, \base, #0x00e00000
orr \base, \base, #0x08
ldr \irqstat, [\base] @ get interrupts
@@ -35,8 +34,8 @@
bne 1001f
mov \base, #0xfe000000
- orr \base, \base, #0x00fd0000
- orr \base, \base, #0x0000e100
+ orr \base, \base, #0x00c00000
+ orr \base, \base, #0x00000100
orr \base, \base, #0x00000058
ldr \irqstat, [\base]
diff --git a/include/asm-arm/arch-ixp2000/io.h b/include/asm-arm/arch-ixp2000/io.h
index d6971efbd583f..a8e3c2daefd61 100644
--- a/include/asm-arm/arch-ixp2000/io.h
+++ b/include/asm-arm/arch-ixp2000/io.h
@@ -1,5 +1,5 @@
/*
- * linux/include/asm-arm/arch-ixdp2000/io.h
+ * linux/include/asm-arm/arch-ixp2000/io.h
*
* Original Author: Naeem M Afzal <naeem.m.afzal@intel.com>
* Maintainer: Deepak Saxena <dsaxena@plexity.net>
@@ -17,20 +17,20 @@
#define IO_SPACE_LIMIT 0xffffffff
#define __mem_pci(a) (a)
-
-/*
- * Pick up VMALLOC_END
- */
#define ___io(p) ((void __iomem *)((p)+IXP2000_PCI_IO_VIRT_BASE))
/*
- * IXP2000 does not do proper byte-lane conversion for PCI addresses,
- * so we need to override standard functions.
+ * The IXP2400 before revision B0 asserts byte lanes for PCI I/O
+ * transactions the other way round (MEM transactions don't have this
+ * issue), so we need to override the standard functions. B0 and later
+ * have a bit that can be set to 1 to get the 'proper' behavior, but
+ * since that isn't available on the A? revisions we just keep doing
+ * things manually.
*/
-#define alignb(addr) (((unsigned long)addr & ~3) + (3 - ((unsigned long)addr & 3)))
-#define alignw(addr) (((unsigned long)addr & ~2) + (2 - ((unsigned long)addr & 2)))
+#define alignb(addr) (void __iomem *)((unsigned long)addr ^ 3)
+#define alignw(addr) (void __iomem *)((unsigned long)addr ^ 2)
-#define outb(v,p) __raw_writeb(v,alignb(___io(p)))
+#define outb(v,p) __raw_writeb((v),alignb(___io(p)))
#define outw(v,p) __raw_writew((v),alignw(___io(p)))
#define outl(v,p) __raw_writel((v),___io(p))
@@ -53,8 +53,8 @@
/*
* 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 easilly
- * make it contigous to the PCI I/O address range, and it also does not
+ * 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
diff --git a/include/asm-arm/arch-ixp2000/irqs.h b/include/asm-arm/arch-ixp2000/irqs.h
index 6ef085909c103..0deb96c12adb6 100644
--- a/include/asm-arm/arch-ixp2000/irqs.h
+++ b/include/asm-arm/arch-ixp2000/irqs.h
@@ -45,12 +45,12 @@
#define IRQ_IXP2000_ME_ATTN 14
#define IRQ_IXP2000_PCI 15 /* PCI INTA or INTB */
#define IRQ_IXP2000_THDA0 16 /* thread 0-31A */
-#define IRQ_IXP2000_THDA1 17 /* thread 32-63A */
-#define IRQ_IXP2000_THDA2 18 /* thread 64-95A, IXP2800 only */
+#define IRQ_IXP2000_THDA1 17 /* thread 32-63A, IXP2800 only */
+#define IRQ_IXP2000_THDA2 18 /* thread 64-95A */
#define IRQ_IXP2000_THDA3 19 /* thread 96-127A, IXP2800 only */
#define IRQ_IXP2000_THDB0 24 /* thread 0-31B */
-#define IRQ_IXP2000_THDB1 25 /* thread 32-63B */
-#define IRQ_IXP2000_THDB2 26 /* thread 64-95B, IXP2800 only */
+#define IRQ_IXP2000_THDB1 25 /* thread 32-63B, IXP2800 only */
+#define IRQ_IXP2000_THDB2 26 /* thread 64-95B */
#define IRQ_IXP2000_THDB3 27 /* thread 96-127B, IXP2800 only */
/* define generic GPIOs */
diff --git a/include/asm-arm/arch-ixp2000/ixdp2x00.h b/include/asm-arm/arch-ixp2000/ixdp2x00.h
index 84ca02781c844..3a398dfbf125c 100644
--- a/include/asm-arm/arch-ixp2000/ixdp2x00.h
+++ b/include/asm-arm/arch-ixp2000/ixdp2x00.h
@@ -21,7 +21,7 @@
* On board CPLD memory map
*/
#define IXDP2X00_PHYS_CPLD_BASE 0xc7000000
-#define IXDP2X00_VIRT_CPLD_BASE 0xfefdd000
+#define IXDP2X00_VIRT_CPLD_BASE 0xfafff000
#define IXDP2X00_CPLD_SIZE 0x00001000
diff --git a/include/asm-arm/arch-ixp2000/ixdp2x01.h b/include/asm-arm/arch-ixp2000/ixdp2x01.h
index 46469c4d5ddc9..b3a1bcda8d010 100644
--- a/include/asm-arm/arch-ixp2000/ixdp2x01.h
+++ b/include/asm-arm/arch-ixp2000/ixdp2x01.h
@@ -1,5 +1,5 @@
/*
- * include/asm/arch/ixdp2x01.h
+ * include/asm-arm/arch-ixp2000/ixdp2x01.h
*
* Platform definitions for IXDP2X01 && IXDP2801 systems
*
@@ -18,10 +18,10 @@
#define __IXDP2X01_H__
#define IXDP2X01_PHYS_CPLD_BASE 0xc6024000
-#define IXDP2X01_VIRT_CPLD_BASE 0xfefdd000
-#define IXDP2X01_CPLD_REGION_SIZE 0x1000
+#define IXDP2X01_VIRT_CPLD_BASE 0xfafff000
+#define IXDP2X01_CPLD_REGION_SIZE 0x00001000
-#define IXDP2X01_CPLD_VIRT_REG(reg) (volatile u32*)(IXDP2X01_VIRT_CPLD_BASE | reg)
+#define IXDP2X01_CPLD_VIRT_REG(reg) (volatile unsigned long*)(IXDP2X01_VIRT_CPLD_BASE | reg)
#define IXDP2X01_CPLD_PHYS_REG(reg) (volatile u32*)(IXDP2X01_PHYS_CPLD_BASE | reg)
#define IXDP2X01_UART1_VIRT_BASE IXDP2X01_CPLD_VIRT_REG(0x40)
diff --git a/include/asm-arm/arch-ixp2000/ixp2000-regs.h b/include/asm-arm/arch-ixp2000/ixp2000-regs.h
index 99dd524eaecba..6c56708d0ff0c 100644
--- a/include/asm-arm/arch-ixp2000/ixp2000-regs.h
+++ b/include/asm-arm/arch-ixp2000/ixp2000-regs.h
@@ -19,41 +19,57 @@
#define _IXP2000_REGS_H_
/*
- * Static I/O regions. The manual defines each region as being several
- * MB in size, but all the registers are within the first 4K, so there's
- * no purpose in mapping the whole region in.
+ * Static I/O regions.
+ *
+ * Most of the registers are clumped in 4K regions spread throughout
+ * the 0xc0000000 -> 0xc0100000 address range, but we just map in
+ * the whole range using a single 1 MB section instead of small
+ * 4K pages. This has two advantages for us:
+ *
+ * 1) We use only one TLB entry for large number of on-chip I/O devices.
+ *
+ * 2) We can easily set the Section attributes to XCB=101 on the IXP2400
+ * as required per erratum #66. We accomplish this by using a
+ * new MT_IXP2000_DEVICE memory type with the bits set as required.
+ *
+ * CAP stands for CSR Access Proxy.
+ *
+ * If you change the virtual address of this mapping, please propagate
+ * the change to arch/arm/kernel/debug.S, which hardcodes the virtual
+ * address of the UART located in this region.
*/
-#define IXP2000_SLOWPORT_CSR_PHYS_BASE 0xc0080000
-#define IXP2000_SLOWPORT_CSR_VIRT_BASE 0xfefff000
-#define IXP2000_SLOWPORT_CSR_SIZE 0x1000
-#define IXP2000_GLOBAL_REG_PHYS_BASE 0xc0004000
-#define IXP2000_GLOBAL_REG_VIRT_BASE 0xfeffe000
-#define IXP2000_GLOBAL_REG_SIZE 0x1000
+#define IXP2000_CAP_PHYS_BASE 0xc0000000
+#define IXP2000_CAP_VIRT_BASE 0xfef00000
+#define IXP2000_CAP_SIZE 0x00100000
+/*
+ * Addresses for specific on-chip peripherals
+ */
+#define IXP2000_SLOWPORT_CSR_VIRT_BASE 0xfef80000
+#define IXP2000_GLOBAL_REG_VIRT_BASE 0xfef04000
#define IXP2000_UART_PHYS_BASE 0xc0030000
#define IXP2000_UART_VIRT_BASE 0xfef30000
-#define IXP2000_UART_SIZE 0x1000
-
-#define IXP2000_TIMER_PHYS_BASE 0xc0020000
-#define IXP2000_TIMER_VIRT_BASE 0xfeffc000
-#define IXP2000_TIMER_SIZE 0x1000
-
-#define IXP2000_GPIO_PHYS_BASE 0xc0010000
-#define IXP2000_GPIO_VIRT_BASE 0xfeffb000
-#define IXP2000_GPIO_SIZE 0x1000
+#define IXP2000_TIMER_VIRT_BASE 0xfef20000
+#define IXP2000_GPIO_VIRT_BASE 0Xfef10000
+/*
+ * Devices outside of the 0xc0000000 -> 0xc0100000 range. The virtual
+ * addresses of the INTCTL and PCI_CSR mappings are hardcoded in
+ * entry-macro.S, so if you ever change these please propagate
+ * the change.
+ */
#define IXP2000_INTCTL_PHYS_BASE 0xd6000000
-#define IXP2000_INTCTL_VIRT_BASE 0xfeffa000
-#define IXP2000_INTCTL_SIZE 0x01000
+#define IXP2000_INTCTL_VIRT_BASE 0xfee00000
+#define IXP2000_INTCTL_SIZE 0x00100000
#define IXP2000_PCI_CREG_PHYS_BASE 0xde000000
-#define IXP2000_PCI_CREG_VIRT_BASE 0xfeff0000
-#define IXP2000_PCI_CREG_SIZE 0x1000
+#define IXP2000_PCI_CREG_VIRT_BASE 0xfed00000
+#define IXP2000_PCI_CREG_SIZE 0x00100000
#define IXP2000_PCI_CSR_PHYS_BASE 0xdf000000
-#define IXP2000_PCI_CSR_VIRT_BASE 0xfefde000
-#define IXP2000_PCI_CSR_SIZE 0x1000
+#define IXP2000_PCI_CSR_VIRT_BASE 0xfec00000
+#define IXP2000_PCI_CSR_SIZE 0x00100000
#define IXP2000_PCI_IO_PHYS_BASE 0xd8000000
#define IXP2000_PCI_IO_VIRT_BASE 0xfd000000
@@ -67,7 +83,6 @@
#define IXP2000_PCI_CFG1_VIRT_BASE 0xfb000000
#define IXP2000_PCI_CFG1_SIZE 0x01000000
-
/*
* Timers
*/
@@ -113,6 +128,30 @@
#define IXP2000_IRQ_ERR_ENABLE_SET IXP2000_INTCTL_REG(0x2c)
#define IXP2000_FIQ_ERR_ENABLE_CLR IXP2000_INTCTL_REG(0x30)
#define IXP2000_IRQ_ERR_ENABLE_CLR IXP2000_INTCTL_REG(0x34)
+#define IXP2000_IRQ_THD_RAW_STATUS_A_0 IXP2000_INTCTL_REG(0x60)
+#define IXP2000_IRQ_THD_RAW_STATUS_A_1 IXP2000_INTCTL_REG(0x64)
+#define IXP2000_IRQ_THD_RAW_STATUS_A_2 IXP2000_INTCTL_REG(0x68)
+#define IXP2000_IRQ_THD_RAW_STATUS_A_3 IXP2000_INTCTL_REG(0x6c)
+#define IXP2000_IRQ_THD_RAW_STATUS_B_0 IXP2000_INTCTL_REG(0x80)
+#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_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)
+#define IXP2000_IRQ_THD_ENABLE_SET_A_3 IXP2000_INTCTL_REG(0x16c)
+#define IXP2000_IRQ_THD_ENABLE_SET_B_0 IXP2000_INTCTL_REG(0x180)
+#define IXP2000_IRQ_THD_ENABLE_SET_B_1 IXP2000_INTCTL_REG(0x184)
+#define IXP2000_IRQ_THD_ENABLE_SET_B_2 IXP2000_INTCTL_REG(0x188)
+#define IXP2000_IRQ_THD_ENABLE_SET_B_3 IXP2000_INTCTL_REG(0x18c)
+#define IXP2000_IRQ_THD_ENABLE_CLEAR_A_0 IXP2000_INTCTL_REG(0x1e0)
+#define IXP2000_IRQ_THD_ENABLE_CLEAR_A_1 IXP2000_INTCTL_REG(0x1e4)
+#define IXP2000_IRQ_THD_ENABLE_CLEAR_A_2 IXP2000_INTCTL_REG(0x1e8)
+#define IXP2000_IRQ_THD_ENABLE_CLEAR_A_3 IXP2000_INTCTL_REG(0x1ec)
+#define IXP2000_IRQ_THD_ENABLE_CLEAR_B_0 IXP2000_INTCTL_REG(0x200)
+#define IXP2000_IRQ_THD_ENABLE_CLEAR_B_1 IXP2000_INTCTL_REG(0x204)
+#define IXP2000_IRQ_THD_ENABLE_CLEAR_B_2 IXP2000_INTCTL_REG(0x208)
+#define IXP2000_IRQ_THD_ENABLE_CLEAR_B_3 IXP2000_INTCTL_REG(0x20c)
/*
* Mask of valid IRQs in the 32-bit IRQ register. We use
@@ -195,7 +234,7 @@
#define IXP2000_PCICNTL_PNR (1<<17) /* PCI not Reset bit of PCI_CONTROL */
#define IXP2000_PCICNTL_PCF (1<<28) /* PCI Centrolfunction bit */
-#define IXP2000_XSCALE_INT (1<<1) /* Interrupt from XScale to PCI */
+#define IXP2000_XSCALE_INT (1<<1) /* Interrupt from XScale to PCI */
/* These are from the IRQ register in the PCI ISR register */
#define PCI_CONTROL_BE_DEO (1 << 22) /* Big Endian Data Enable Out */
diff --git a/include/asm-arm/arch-ixp2000/platform.h b/include/asm-arm/arch-ixp2000/platform.h
index 16e4a240199db..509e44d528d82 100644
--- a/include/asm-arm/arch-ixp2000/platform.h
+++ b/include/asm-arm/arch-ixp2000/platform.h
@@ -1,5 +1,5 @@
/*
- * include/asm-arh/arch-ixp2000/platform.h
+ * include/asm-arm/arch-ixp2000/platform.h
*
* Various bits of code used by platform-level code.
*
@@ -20,7 +20,7 @@
* to on-chip I/O register to not complete fully. What this means is
* that if you have a write to on-chip I/O followed by a back-to-back
* read or write, the first write will happen twice. OR...if it's
- * not a back-to-back trasaction, the read or write will generate
+ * not a back-to-back transaction, the read or write will generate
* incorrect data.
*
* The official work around for this is to set the on-chip I/O regions
@@ -50,7 +50,7 @@ static inline void ixp2000_reg_write(volatile unsigned long *reg, unsigned long
* Boards may multiplex different devices on the 2nd channel of
* the slowport interface that each need different configuration
* settings. For example, the IXDP2400 uses channel 2 on the interface
- * to access the CPLD, the switch fabric card, and te media card. Each
+ * to access the CPLD, the switch fabric card, and the media card. Each
* one needs a different mode so drivers must save/restore the mode
* before and after each operation.
*
diff --git a/include/asm-arm/arch-ixp2000/system.h b/include/asm-arm/arch-ixp2000/system.h
index f9eb8ad435fb4..4f489cc0dfa53 100644
--- a/include/asm-arm/arch-ixp2000/system.h
+++ b/include/asm-arm/arch-ixp2000/system.h
@@ -19,7 +19,7 @@ static inline void arch_idle(void)
static inline void arch_reset(char mode)
{
- cli();
+ local_irq_disable();
/*
* Reset flash banking register so that we are pointing at
diff --git a/include/asm-arm/arch-ixp2000/vmalloc.h b/include/asm-arm/arch-ixp2000/vmalloc.h
index f2705a85e1ff8..2e4bcbcf31f0f 100644
--- a/include/asm-arm/arch-ixp2000/vmalloc.h
+++ b/include/asm-arm/arch-ixp2000/vmalloc.h
@@ -20,4 +20,4 @@
#define VMALLOC_OFFSET (8*1024*1024)
#define VMALLOC_START (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
#define VMALLOC_VMADDR(x) ((unsigned long)(x))
-#define VMALLOC_END 0xfb000000
+#define VMALLOC_END 0xfaffefff
diff --git a/include/asm-arm/arch-ixp4xx/platform.h b/include/asm-arm/arch-ixp4xx/platform.h
index d0e195b329533..3a626c03ea266 100644
--- a/include/asm-arm/arch-ixp4xx/platform.h
+++ b/include/asm-arm/arch-ixp4xx/platform.h
@@ -15,6 +15,12 @@
#include <asm/types.h>
+#ifndef __ARMEB__
+#define REG_OFFSET 0
+#else
+#define REG_OFFSET 3
+#endif
+
/*
* Expansion bus memory regions
*/
diff --git a/include/asm-arm/arch-omap/aic23.h b/include/asm-arm/arch-omap/aic23.h
new file mode 100644
index 0000000000000..590bac25b7c44
--- /dev/null
+++ b/include/asm-arm/arch-omap/aic23.h
@@ -0,0 +1,112 @@
+/*
+ * linux/include/asm-arm/arch-omap/aic23.h
+ *
+ * Hardware definitions for TI TLV320AIC23 audio codec
+ *
+ * Copyright (C) 2002 RidgeRun, Inc.
+ * Author: Steve Johnson
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __ASM_ARCH_AIC23_H
+#define __ASM_ARCH_AIC23_H
+
+// Codec TLV320AIC23
+#define LEFT_LINE_VOLUME_ADDR 0x00
+#define RIGHT_LINE_VOLUME_ADDR 0x01
+#define LEFT_CHANNEL_VOLUME_ADDR 0x02
+#define RIGHT_CHANNEL_VOLUME_ADDR 0x03
+#define ANALOG_AUDIO_CONTROL_ADDR 0x04
+#define DIGITAL_AUDIO_CONTROL_ADDR 0x05
+#define POWER_DOWN_CONTROL_ADDR 0x06
+#define DIGITAL_AUDIO_FORMAT_ADDR 0x07
+#define SAMPLE_RATE_CONTROL_ADDR 0x08
+#define DIGITAL_INTERFACE_ACT_ADDR 0x09
+#define RESET_CONTROL_ADDR 0x0F
+
+// Left (right) line input volume control register
+#define LRS_ENABLED 0x0100
+#define LIM_MUTED 0x0080
+#define LIV_DEFAULT 0x0017
+#define LIV_MAX 0x001f
+#define LIV_MIN 0x0000
+
+// Left (right) channel headphone volume control register
+#define LZC_ON 0x0080
+#define LHV_DEFAULT 0x0079
+#define LHV_MAX 0x007f
+#define LHV_MIN 0x0000
+
+// Analog audio path control register
+#define STE_ENABLED 0x0020
+#define DAC_SELECTED 0x0010
+#define BYPASS_ON 0x0008
+#define INSEL_MIC 0x0004
+#define MICM_MUTED 0x0002
+#define MICB_20DB 0x0001
+
+// Digital audio path control register
+#define DACM_MUTE 0x0008
+#define DEEMP_32K 0x0002
+#define DEEMP_44K 0x0004
+#define DEEMP_48K 0x0006
+#define ADCHP_ON 0x0001
+
+// Power control down register
+#define DEVICE_POWER_OFF 0x0080
+#define CLK_OFF 0x0040
+#define OSC_OFF 0x0020
+#define OUT_OFF 0x0010
+#define DAC_OFF 0x0008
+#define ADC_OFF 0x0004
+#define MIC_OFF 0x0002
+#define LINE_OFF 0x0001
+
+// Digital audio interface register
+#define MS_MASTER 0x0040
+#define LRSWAP_ON 0x0020
+#define LRP_ON 0x0010
+#define IWL_16 0x0000
+#define IWL_20 0x0004
+#define IWL_24 0x0008
+#define IWL_32 0x000C
+#define FOR_I2S 0x0002
+#define FOR_DSP 0x0003
+
+// Sample rate control register
+#define CLKOUT_HALF 0x0080
+#define CLKIN_HALF 0x0040
+#define BOSR_384fs 0x0002 // BOSR_272fs when in USB mode
+#define USB_CLK_ON 0x0001
+#define SR_MASK 0xf
+#define CLKOUT_SHIFT 7
+#define CLKIN_SHIFT 6
+#define SR_SHIFT 2
+#define BOSR_SHIFT 1
+
+// Digital interface register
+#define ACT_ON 0x0001
+
+#define TLV320AIC23ID1 (0x1a) // cs low
+#define TLV320AIC23ID2 (0x1b) // cs high
+
+#endif /* __ASM_ARCH_AIC23_H */
diff --git a/include/asm-arm/arch-omap/board-h2.h b/include/asm-arm/arch-omap/board-h2.h
index 9c8ad42999476..60f002b729832 100644
--- a/include/asm-arm/arch-omap/board-h2.h
+++ b/include/asm-arm/arch-omap/board-h2.h
@@ -21,8 +21,8 @@
* (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.,
+ * You 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.
*/
@@ -32,9 +32,7 @@
/* Placeholder for H2 specific defines */
/* At OMAP1610 Innovator the Ethernet is directly connected to CS1 */
-#define OMAP1610_ETHR_BASE 0xE8000000
-#define OMAP1610_ETHR_SIZE SZ_4K
-#define OMAP1610_ETHR_START 0x04000000
+#define OMAP1610_ETHR_START 0x04000300
/* Intel STRATA NOR flash at CS3 or CS2B(NAND Boot) */
#define OMAP_NOR_FLASH_SIZE SZ_32M
diff --git a/include/asm-arm/arch-omap/board-h3.h b/include/asm-arm/arch-omap/board-h3.h
index 3f48583db9562..e4d1cd231731a 100644
--- a/include/asm-arm/arch-omap/board-h3.h
+++ b/include/asm-arm/arch-omap/board-h3.h
@@ -28,9 +28,7 @@
#define __ASM_ARCH_OMAP_H3_H
/* In OMAP1710 H3 the Ethernet is directly connected to CS1 */
-#define OMAP1710_ETHR_BASE 0xE8000000
-#define OMAP1710_ETHR_SIZE SZ_4K
-#define OMAP1710_ETHR_START 0x04000000
+#define OMAP1710_ETHR_START 0x04000300
/* Intel STRATA NOR flash at CS3 or CS2B(NAND Boot) */
#define OMAP_NOR_FLASH_SIZE SZ_32M
diff --git a/include/asm-arm/arch-omap/board-h4.h b/include/asm-arm/arch-omap/board-h4.h
index eb2a5d81a5d60..79138dcfb4acc 100644
--- a/include/asm-arm/arch-omap/board-h4.h
+++ b/include/asm-arm/arch-omap/board-h4.h
@@ -21,8 +21,8 @@
* (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.,
+ * You 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.
*/
diff --git a/include/asm-arm/arch-omap/board-innovator.h b/include/asm-arm/arch-omap/board-innovator.h
index 9229b2d1fa6ed..0f1abaefe4dec 100644
--- a/include/asm-arm/arch-omap/board-innovator.h
+++ b/include/asm-arm/arch-omap/board-innovator.h
@@ -19,8 +19,8 @@
* (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.,
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __ASM_ARCH_OMAP_INNOVATOR_H
@@ -74,8 +74,7 @@ unsigned char fpga_read(int reg);
#if defined (CONFIG_ARCH_OMAP16XX)
/* At OMAP1610 Innovator the Ethernet is directly connected to CS1 */
-#define INNOVATOR1610_ETHR_START 0x04000000
-#define INNOVATOR1610_ETHR_SIZE SZ_4K
+#define INNOVATOR1610_ETHR_START 0x04000300
#endif /* CONFIG_ARCH_OMAP1610 */
#endif /* __ASM_ARCH_OMAP_INNOVATOR_H */
diff --git a/include/asm-arm/arch-omap/board-netstar.h b/include/asm-arm/arch-omap/board-netstar.h
new file mode 100644
index 0000000000000..77cc0fb54d54c
--- /dev/null
+++ b/include/asm-arm/arch-omap/board-netstar.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2004 2N Telekomunikace, Ladislav Michl <michl@2n.cz>
+ *
+ * Hardware definitions for OMAP5910 based NetStar board.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_ARCH_NETSTAR_H
+#define __ASM_ARCH_NETSTAR_H
+
+#include <asm/arch/tc.h>
+
+#define OMAP_NAND_FLASH_START1 OMAP_CS1_PHYS + (1 << 23)
+#define OMAP_NAND_FLASH_START2 OMAP_CS1_PHYS + (2 << 23)
+
+#endif /* __ASM_ARCH_NETSTAR_H */
diff --git a/include/asm-arm/arch-omap/board-osk.h b/include/asm-arm/arch-omap/board-osk.h
index 839928da4620f..aaa49a0fbd218 100644
--- a/include/asm-arm/arch-omap/board-osk.h
+++ b/include/asm-arm/arch-omap/board-osk.h
@@ -21,8 +21,8 @@
* (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.,
+ * You 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.
*/
@@ -30,9 +30,7 @@
#define __ASM_ARCH_OMAP_OSK_H
/* At OMAP5912 OSK the Ethernet is directly connected to CS1 */
-#define OMAP_OSK_ETHR_BASE 0xE8800000
-#define OMAP_OSK_ETHR_SIZE SZ_4K
-#define OMAP_OSK_ETHR_START 0x04800000
+#define OMAP_OSK_ETHR_START 0x04800300
/* Micron NOR flash at CS3 mapped to address 0x0 if BM bit is 1 */
#define OMAP_OSK_NOR_FLASH_BASE 0xD8000000
diff --git a/include/asm-arm/arch-omap/board-voiceblue.h b/include/asm-arm/arch-omap/board-voiceblue.h
new file mode 100644
index 0000000000000..33977b8956fbb
--- /dev/null
+++ b/include/asm-arm/arch-omap/board-voiceblue.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2004 2N Telekomunikace, Ladislav Michl <michl@2n.cz>
+ *
+ * Hardware definitions for OMAP5910 based VoiceBlue board.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_ARCH_VOICEBLUE_H
+#define __ASM_ARCH_VOICEBLUE_H
+
+#if (EXTERNAL_MAX_NR_PORTS < 4)
+#undef EXTERNAL_MAX_NR_PORTS
+#define EXTERNAL_MAX_NR_PORTS 4
+#endif
+
+extern void voiceblue_wdt_enable(void);
+extern void voiceblue_wdt_disable(void);
+extern void voiceblue_wdt_ping(void);
+extern void voiceblue_reset(void);
+
+#endif /* __ASM_ARCH_VOICEBLUE_H */
+
diff --git a/include/asm-arm/arch-omap/clocks.h b/include/asm-arm/arch-omap/clocks.h
deleted file mode 100644
index b2c5f8e73a132..0000000000000
--- a/include/asm-arm/arch-omap/clocks.h
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- * OMAP clock interface
- *
- * Copyright (C) 2001 RidgeRun, Inc
- * Written by Gordon McNutt <gmcnutt@ridgerun.com>
- * Updated 2004 for Linux 2.6 by Tony Lindgren <tony@atomide.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef __ASM_ARM_CLOCKS_H
-#define __ASM_ARM_CLOCKS_H
-
-#include <linux/config.h>
-
-/* ARM_CKCTL bit shifts */
-#define PERDIV 0
-#define LCDDIV 2
-#define ARMDIV 4
-#define DSPDIV 6
-#define TCDIV 8
-#define DSPMMUDIV 10
-#define ARM_TIMXO 12
-#define EN_DSPCK 13
-#define ARM_INTHCK_SEL 14 /* REVISIT: Where is this used? */
-
-/* ARM_IDLECT1 bit shifts */
-#define IDLWDT_ARM 0
-#define IDLXORP_ARM 1
-#define IDLPER_ARM 2
-#define IDLLCD_ARM 3
-#define IDLLB_ARM 4
-#define IDLHSAB_ARM 5
-#define IDLIF_ARM 6
-#define IDLDPLL_ARM 7
-#define IDLAPI_ARM 8
-#define IDLTIM_ARM 9
-#define SETARM_IDLE 11
-
-/* ARM_IDLECT2 bit shifts */
-#define EN_WDTCK 0
-#define EN_XORPCK 1
-#define EN_PERCK 2
-#define EN_LCDCK 3
-#define EN_LBCK 4
-#define EN_HSABCK 5
-#define EN_APICK 6
-#define EN_TIMCK 7
-#define DMACK_REQ 8
-#define EN_GPIOCK 9
-#define EN_LBFREECK 10
-
-/*
- * OMAP clocks
- */
-typedef enum {
- /* Fixed system clock */
- OMAP_CLKIN = 0,
-
- /* DPLL1 */
- OMAP_CK_GEN1, OMAP_CK_GEN2, OMAP_CK_GEN3,
-
- /* TC usually needs to be checked before anything else */
- OMAP_TC_CK,
-
- /* CLKM1 */
- OMAP_ARM_CK, OMAP_MPUPER_CK, OMAP_ARM_GPIO_CK, OMAP_MPUXOR_CK,
- OMAP_MPUTIM_CK, OMAP_MPUWD_CK,
-
- /* CLKM2 */
- OMAP_DSP_CK, OMAP_DSPMMU_CK,
-#if 0
- /* Accessible only from the dsp */
- OMAP_DSPPER_CK, OMAP_GPIO_CK, OMAP_DSPXOR_CK, OMAP_DSPTIM_CK,
- OMAP_DSPWD_CK, OMAP_UART_CK,
-#endif
- /* CLKM3 */
- OMAP_DMA_CK, OMAP_API_CK, OMAP_HSAB_CK, OMAP_LBFREE_CK,
- OMAP_LB_CK, OMAP_LCD_CK
-} ck_t;
-
-typedef enum {
- /* Reset the MPU */
- OMAP_ARM_RST,
-
- /* Reset the DSP */
- OMAP_DSP_RST,
-
- /* Reset priority registers, EMIF config, and MPUI control logic */
- OMAP_API_RST,
-
- /* Reset DSP, MPU, and Peripherals */
- OMAP_SW_RST,
-} reset_t;
-
-#define OMAP_CK_MIN OMAP_CLKIN
-#define OMAP_CK_MAX OMAP_LCD_CK
-
-#if defined(CONFIG_OMAP_ARM_30MHZ)
-#define OMAP_CK_MAX_RATE 30
-#elif defined(CONFIG_OMAP_ARM_60MHZ)
-#define OMAP_CK_MAX_RATE 60
-#elif defined(CONFIG_OMAP_ARM_96MHZ)
-#define OMAP_CK_MAX_RATE 96
-#elif defined(CONFIG_OMAP_ARM_120MHZ)
-#define OMAP_CK_MAX_RATE 120
-#elif defined(CONFIG_OMAP_ARM_168MHZ)
-#define OMAP_CK_MAX_RATE 168
-#elif defined(CONFIG_OMAP_ARM_182MHZ)
-#define OMAP_CK_MAX_RATE 182
-#elif defined(CONFIG_OMAP_ARM_192MHZ)
-#define OMAP_CK_MAX_RATE 192
-#elif defined(CONFIG_OMAP_ARM_195MHZ)
-#define OMAP_CK_MAX_RATE 195
-#endif
-
-#define CK_DPLL_MASK 0x0fe0
-
-/* Shared by CK and DSPC */
-#define MPUI_STROBE_MAX_1509 24
-#define MPUI_STROBE_MAX_1510 30
-
-/*
- * ----------------------------------------------------------------------------
- * Clock interface functions
- * ----------------------------------------------------------------------------
- */
-
-/* Clock initialization. */
-int init_ck(void);
-
-/*
- * For some clocks you have a choice of which "parent" clocks they are derived
- * from. Use this to select a "parent". See the platform documentation for
- * valid combinations.
- */
-int ck_can_set_input(ck_t);
-int ck_set_input(ck_t ck, ck_t input);
-int ck_get_input(ck_t ck, ck_t *input);
-
-/*
- * Use this to set a clock rate. If other clocks are derived from this one,
- * their rates will all change too. If this is a derived clock and I can't
- * change it to match your request unless I also change the parent clock, then
- * tough luck -- I won't change the parent automatically. I'll return an error
- * if I can't get the clock within 10% of what you want. Otherwise I'll return
- * the value I actually set it to. If I have to switch parents to get the rate
- * then I will do this automatically (since it only affects this clock and its
- * descendants).
- */
-int ck_can_set_rate(ck_t);
-int ck_set_rate(ck_t ck, int val_in_mhz);
-int ck_get_rate(ck_t ck);
-
-/*
- * Use this to get a bitmap of available rates for the clock. Caller allocates
- * the buffer and passes in the length. Clock module fills up to len bytes of
- * the buffer & passes back actual bytes used.
- */
-int ck_get_rates(ck_t ck, void *buf, int len);
-int ck_valid_rate(int rate);
-
-/*
- * Idle a clock. What happens next depends on the clock ;). For example, if
- * you idle the ARM_CK you might well end up in sleep mode on some platforms.
- * If you try to idle a clock that doesn't support it I'll return an error.
- * Note that idling a clock does not always take affect until certain h/w
- * conditions are met. Consult the platform specs to learn more.
- */
-int ck_can_idle(ck_t);
-int ck_idle(ck_t);
-int ck_activate(ck_t);
-int ck_is_idle(ck_t);
-
-/*
- * Enable/disable a clock. I'll return an error if the h/w doesn't support it.
- * If you disable a clock being used by an active device then you probably
- * just screwed it. YOU are responsible for making sure this doesn't happen.
- */
-int ck_can_disable(ck_t);
-int ck_enable(ck_t);
-int ck_disable(ck_t);
-int ck_is_enabled(ck_t);
-
-/* Enable/reset ARM peripherals (remove/set reset signal) */
-void ck_enable_peripherals(void);
-void ck_reset_peripherals(void);
-
-/* Generate/clear a MPU or DSP reset */
-void ck_generate_reset(reset_t reset);
-void ck_release_from_reset(reset_t reset);
-
-/* This gets a string representation of the clock's name. Useful for proc. */
-char *ck_get_name(ck_t);
-
-extern void start_mputimer1(unsigned long);
-
-#endif
diff --git a/include/asm-arm/arch-omap/fpga.h b/include/asm-arm/arch-omap/fpga.h
index dc9f61a43cb9b..676807dc50e12 100644
--- a/include/asm-arm/arch-omap/fpga.h
+++ b/include/asm-arm/arch-omap/fpga.h
@@ -38,8 +38,7 @@ extern void omap1510_fpga_init_irq(void);
#define H2P2_DBG_FPGA_SIZE SZ_4K /* SIZE */
#define H2P2_DBG_FPGA_START 0x04000000 /* PA */
-#define H2P2_DBG_FPGA_ETHR_START H2P2_DBG_FPGA_START
-#define H2P2_DBG_FPGA_ETHR_BASE H2P2_DBG_FPGA_BASE
+#define H2P2_DBG_FPGA_ETHR_START (H2P2_DBG_FPGA_START + 0x300)
#define H2P2_DBG_FPGA_FPGA_REV (H2P2_DBG_FPGA_BASE + 0x10) /* FPGA Revision */
#define H2P2_DBG_FPGA_BOARD_REV (H2P2_DBG_FPGA_BASE + 0x12) /* Board Revision */
#define H2P2_DBG_FPGA_GPIO (H2P2_DBG_FPGA_BASE + 0x14) /* GPIO outputs */
@@ -48,12 +47,31 @@ extern void omap1510_fpga_init_irq(void);
#define H2P2_DBG_FPGA_LAN_STATUS (H2P2_DBG_FPGA_BASE + 0x1A) /* LAN Status line */
#define H2P2_DBG_FPGA_LAN_RESET (H2P2_DBG_FPGA_BASE + 0x1C) /* LAN Reset line */
-/* LEDs definition on debug board (16 LEDs) */
-#define H2P2_DBG_FPGA_LED_CLAIMRELEASE (1 << 15)
-#define H2P2_DBG_FPGA_LED_STARTSTOP (1 << 14)
-#define H2P2_DBG_FPGA_LED_HALTED (1 << 13)
-#define H2P2_DBG_FPGA_LED_IDLE (1 << 12)
-#define H2P2_DBG_FPGA_LED_TIMER (1 << 11)
+/* NOTE: most boards don't have a static mapping for the FPGA ... */
+struct h2p2_dbg_fpga {
+ /* offset 0x00 */
+ u16 smc91x[8];
+ /* offset 0x10 */
+ u16 fpga_rev;
+ u16 board_rev;
+ u16 gpio_outputs;
+ u16 leds;
+ /* offset 0x18 */
+ u16 misc_inputs;
+ u16 lan_status;
+ u16 lan_reset;
+ u16 reserved0;
+ /* offset 0x20 */
+ u16 ps2_data;
+ u16 ps2_ctrl;
+ /* plus also 4 rs232 ports ... */
+};
+
+/* LEDs definition on debug board (16 LEDs, all physically green) */
+#define H2P2_DBG_FPGA_LED_GREEN (1 << 15)
+#define H2P2_DBG_FPGA_LED_AMBER (1 << 14)
+#define H2P2_DBG_FPGA_LED_RED (1 << 13)
+#define H2P2_DBG_FPGA_LED_BLUE (1 << 12)
/* cpu0 load-meter LEDs */
#define H2P2_DBG_FPGA_LOAD_METER (1 << 0) // A bit of fun on our board ...
#define H2P2_DBG_FPGA_LOAD_METER_SIZE 11
@@ -116,7 +134,6 @@ extern void omap1510_fpga_init_irq(void);
#define INNOVATOR_FPGA_IMR2 (OMAP1510_FPGA_BASE + 0x210)
#define OMAP1510_FPGA_ETHR_START (OMAP1510_FPGA_START + 0x300)
-#define OMAP1510_FPGA_ETHR_BASE (OMAP1510_FPGA_BASE + 0x300)
/*
* Power up Giga UART driver, turn on HID clock.
diff --git a/include/asm-arm/arch-omap/hardware.h b/include/asm-arm/arch-omap/hardware.h
index 8930a0e21a837..37e06c782bdf0 100644
--- a/include/asm-arm/arch-omap/hardware.h
+++ b/include/asm-arm/arch-omap/hardware.h
@@ -89,58 +89,31 @@
#define ULPD_REG_BASE (0xfffe0800)
#define ULPD_IT_STATUS (ULPD_REG_BASE + 0x14)
#define ULPD_CLOCK_CTRL (ULPD_REG_BASE + 0x30)
+# define DIS_USB_PVCI_CLK (1 << 5) /* no USB/FAC synch */
+# define USB_MCLK_EN (1 << 4) /* enable W4_USB_CLKO */
#define ULPD_SOFT_REQ (ULPD_REG_BASE + 0x34)
+# define SOFT_UDC_REQ (1 << 4)
+# define SOFT_USB_CLK_REQ (1 << 3)
+# define SOFT_DPLL_REQ (1 << 0)
#define ULPD_DPLL_CTRL (ULPD_REG_BASE + 0x3c)
#define ULPD_STATUS_REQ (ULPD_REG_BASE + 0x40)
#define ULPD_APLL_CTRL (ULPD_REG_BASE + 0x4c)
#define ULPD_POWER_CTRL (ULPD_REG_BASE + 0x50)
+#define ULPD_SOFT_DISABLE_REQ_REG (ULPD_REG_BASE + 0x68)
+# define DIS_MMC2_DPLL_REQ (1 << 11)
+# define DIS_MMC1_DPLL_REQ (1 << 10)
+# define DIS_UART3_DPLL_REQ (1 << 9)
+# define DIS_UART2_DPLL_REQ (1 << 8)
+# define DIS_UART1_DPLL_REQ (1 << 7)
+# define DIS_USB_HOST_DPLL_REQ (1 << 6)
+#define ULPD_SDW_CLK_DIV_CTRL_SEL (ULPD_REG_BASE + 0x74)
#define ULPD_CAM_CLK_CTRL (ULPD_REG_BASE + 0x7c)
/*
* ---------------------------------------------------------------------------
- * Timers
+ * Watchdog timer
* ---------------------------------------------------------------------------
*/
-#define OMAP_32kHz_TIMER_BASE 0xfffb9000
-
-/* 32k Timer Registers */
-#define TIMER32k_CR 0x08
-#define TIMER32k_TVR 0x00
-#define TIMER32k_TCR 0x04
-
-/* 32k Timer Control Register definition */
-#define TIMER32k_TSS (1<<0)
-#define TIMER32k_TRB (1<<1)
-#define TIMER32k_INT (1<<2)
-#define TIMER32k_ARL (1<<3)
-
-/* MPU Timer base addresses */
-#define OMAP_TIMER1_BASE (0xfffec500)
-#define OMAP_TIMER2_BASE (0xfffec600)
-#define OMAP_TIMER3_BASE (0xfffec700)
-#define OMAP_MPUTIMER_BASE OMAP_TIMER1_BASE
-#define OMAP_MPUTIMER_OFFSET 0x100
-
-/* MPU Timer Registers */
-#define OMAP_TIMER1_CNTL (OMAP_TIMER_BASE1 + 0x0)
-#define OMAP_TIMER1_LOAD_TIM (OMAP_TIMER_BASE1 + 0x4)
-#define OMAP_TIMER1_READ_TIM (OMAP_TIMER_BASE1 + 0x8)
-
-#define OMAP_TIMER2_CNTL (OMAP_TIMER_BASE2 + 0x0)
-#define OMAP_TIMER2_LOAD_TIM (OMAP_TIMER_BASE2 + 0x4)
-#define OMAP_TIMER2_READ_TIM (OMAP_TIMER_BASE2 + 0x8)
-
-#define OMAP_TIMER3_CNTL (OMAP_TIMER_BASE3 + 0x0)
-#define OMAP_TIMER3_LOAD_TIM (OMAP_TIMER_BASE3 + 0x4)
-#define OMAP_TIMER3_READ_TIM (OMAP_TIMER_BASE3 + 0x8)
-
-/* CNTL_TIMER register bits */
-#define MPUTIM_FREE (1<<6)
-#define MPUTIM_CLOCK_ENABLE (1<<5)
-#define MPUTIM_PTV_MASK (0x7<<MPUTIM_PTV_BIT)
-#define MPUTIM_PTV_BIT 2
-#define MPUTIM_AR (1<<1)
-#define MPUTIM_ST (1<<0)
/* Watchdog timer within the OMAP3.2 gigacell */
#define OMAP_MPU_WATCHDOG_BASE (0xfffec800)
@@ -183,29 +156,6 @@
#define IRQ_GMR_REG_OFFSET 0xa0
/*
- * ---------------------------------------------------------------------------
- * Traffic controller memory interface
- * ---------------------------------------------------------------------------
- */
-#define TCMIF_BASE 0xfffecc00
-#define IMIF_PRIO (TCMIF_BASE + 0x00)
-#define EMIFS_PRIO (TCMIF_BASE + 0x04)
-#define EMIFF_PRIO (TCMIF_BASE + 0x08)
-#define EMIFS_CONFIG (TCMIF_BASE + 0x0c)
-#define EMIFS_CS0_CONFIG (TCMIF_BASE + 0x10)
-#define EMIFS_CS1_CONFIG (TCMIF_BASE + 0x14)
-#define EMIFS_CS2_CONFIG (TCMIF_BASE + 0x18)
-#define EMIFS_CS3_CONFIG (TCMIF_BASE + 0x1c)
-#define EMIFF_SDRAM_CONFIG (TCMIF_BASE + 0x20)
-#define EMIFF_MRS (TCMIF_BASE + 0x24)
-#define TC_TIMEOUT1 (TCMIF_BASE + 0x28)
-#define TC_TIMEOUT2 (TCMIF_BASE + 0x2c)
-#define TC_TIMEOUT3 (TCMIF_BASE + 0x30)
-#define TC_ENDIANISM (TCMIF_BASE + 0x34)
-#define EMIFF_SDRAM_CONFIG_2 (TCMIF_BASE + 0x3c)
-#define EMIF_CFG_DYNAMIC_WS (TCMIF_BASE + 0x40)
-
-/*
* ----------------------------------------------------------------------------
* System control registers
* ----------------------------------------------------------------------------
@@ -279,6 +229,18 @@
#define MPUI_DSP_BOOT_CONFIG (MPUI_BASE + 0x18)
#define MPUI_DSP_API_CONFIG (MPUI_BASE + 0x1c)
+/*
+ * ----------------------------------------------------------------------------
+ * LED Pulse Generator
+ * ----------------------------------------------------------------------------
+ */
+#define OMAP_LPG1_BASE 0xfffbd000
+#define OMAP_LPG2_BASE 0xfffbd800
+#define OMAP_LPG1_LCR (OMAP_LPG1_BASE + 0x00)
+#define OMAP_LPG1_PMR (OMAP_LPG1_BASE + 0x04)
+#define OMAP_LPG2_LCR (OMAP_LPG2_BASE + 0x00)
+#define OMAP_LPG2_PMR (OMAP_LPG2_BASE + 0x04)
+
#ifndef __ASSEMBLER__
/*
@@ -293,12 +255,12 @@
#define OMAP1510_BASE_BAUD (12000000/16)
#define OMAP16XX_BASE_BAUD (48000000/16)
-#define is_omap_port(p) ({int __ret = 0; \
- if (p == (char*)IO_ADDRESS(OMAP_UART1_BASE) || \
- p == (char*)IO_ADDRESS(OMAP_UART2_BASE) || \
- p == (char*)IO_ADDRESS(OMAP_UART3_BASE)) \
- __ret = 1; \
- __ret; \
+#define is_omap_port(p) ({int __ret = 0; \
+ if (p == IO_ADDRESS(OMAP_UART1_BASE) || \
+ p == IO_ADDRESS(OMAP_UART2_BASE) || \
+ p == IO_ADDRESS(OMAP_UART3_BASE)) \
+ __ret = 1; \
+ __ret; \
})
/*
@@ -349,6 +311,14 @@
#include "board-osk.h"
#endif
+#ifdef CONFIG_MACH_VOICEBLUE
+#include "board-voiceblue.h"
+#endif
+
+#ifdef CONFIG_MACH_NETSTAR
+#include "board-netstar.h"
+#endif
+
#endif /* !__ASSEMBLER__ */
#endif /* __ASM_ARCH_OMAP_HARDWARE_H */
diff --git a/include/asm-arm/arch-omap/irqs.h b/include/asm-arm/arch-omap/irqs.h
index b6cd47a85b4bc..6701fd9e5f9b9 100644
--- a/include/asm-arm/arch-omap/irqs.h
+++ b/include/asm-arm/arch-omap/irqs.h
@@ -149,9 +149,16 @@
#define INT_1610_McBSP2RX_OF (31 + IH2_BASE)
#define INT_1610_STI (32 + IH2_BASE)
#define INT_1610_STI_WAKEUP (33 + IH2_BASE)
+#define INT_1610_GPTIMER3 (34 + IH2_BASE)
+#define INT_1610_GPTIMER4 (35 + IH2_BASE)
+#define INT_1610_GPTIMER5 (36 + IH2_BASE)
+#define INT_1610_GPTIMER6 (37 + IH2_BASE)
+#define INT_1610_GPTIMER7 (38 + IH2_BASE)
+#define INT_1610_GPTIMER8 (39 + IH2_BASE)
#define INT_1610_GPIO_BANK2 (40 + IH2_BASE)
#define INT_1610_GPIO_BANK3 (41 + IH2_BASE)
#define INT_1610_MMC2 (42 + IH2_BASE)
+#define INT_1610_CF (43 + IH2_BASE)
#define INT_1610_GPIO_BANK4 (48 + IH2_BASE)
#define INT_1610_SPI (49 + IH2_BASE)
#define INT_1610_DMA_CH6 (53 + IH2_BASE)
diff --git a/include/asm-arm/arch-omap/mcbsp.h b/include/asm-arm/arch-omap/mcbsp.h
index eb3032510508b..305bdeb16ab88 100644
--- a/include/asm-arm/arch-omap/mcbsp.h
+++ b/include/asm-arm/arch-omap/mcbsp.h
@@ -250,4 +250,8 @@ int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer, unsigned int leng
/* SPI specific API */
void omap_mcbsp_set_spi_mode(unsigned int id, const struct omap_mcbsp_spi_cfg * spi_cfg);
+/* Polled read/write functions */
+int omap_mcbsp_pollread(unsigned int id, u16 * buf);
+int omap_mcbsp_pollwrite(unsigned int id, u16 buf);
+
#endif
diff --git a/include/asm-arm/arch-omap/memory.h b/include/asm-arm/arch-omap/memory.h
index 3182aa43d4c06..f6b57dd846a31 100644
--- a/include/asm-arm/arch-omap/memory.h
+++ b/include/asm-arm/arch-omap/memory.h
@@ -25,8 +25,8 @@
* (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.,
+ * You 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.
*/
diff --git a/include/asm-arm/arch-omap/mux.h b/include/asm-arm/arch-omap/mux.h
index f2142b09104e1..39f99decbb7ba 100644
--- a/include/asm-arm/arch-omap/mux.h
+++ b/include/asm-arm/arch-omap/mux.h
@@ -174,6 +174,7 @@ typedef enum {
M14_1510_GPIO2,
/* OMAP1610 GPIO */
+ P18_1610_GPIO3,
Y15_1610_GPIO17,
/* OMAP-1710 GPIO */
@@ -239,6 +240,7 @@ typedef enum {
V5_1610_GPIO24,
AA20_1610_GPIO_41,
W19_1610_GPIO48,
+ M7_1610_GPIO62,
/* OMAP-1610 uWire */
V19_1610_UWIRE_SCLK,
@@ -316,6 +318,12 @@ typedef enum {
R10_1610_MCLK_ON,
R10_1610_MCLK_OFF,
+ /* CompactFlash controller */
+ P11_1610_CF_CD2,
+ R11_1610_CF_IOIS16,
+ V10_1610_CF_IREQ,
+ W10_1610_CF_RESET,
+ W11_1610_CF_CD1,
} reg_cfg_t;
#if defined(__MUX_C__) && defined(CONFIG_OMAP_MUX)
@@ -355,7 +363,8 @@ MUX_CFG("PWL", 6, 3, 1, 0, 31, 1, NA, 0, 0)
/* USB internal master generic */
MUX_CFG("R18_USB_VBUS", 7, 9, 2, 1, 11, 0, NA, 0, 1)
MUX_CFG("R18_1510_USB_GPIO0", 7, 9, 0, 1, 11, 1, NA, 0, 1)
-MUX_CFG("W4_USB_PUEN", D, 3, 0, 3, 5, 1, NA, 0, 1)
+/* works around erratum: W4_USB_PUEN and W4_USB_PUDIS are switched! */
+MUX_CFG("W4_USB_PUEN", D, 3, 3, 3, 5, 1, NA, 0, 1)
MUX_CFG("W4_USB_CLKO", D, 3, 1, 3, 5, 0, NA, 0, 1)
MUX_CFG("W4_USB_HIGHZ", D, 3, 4, 3, 5, 0, 3, 0, 1)
MUX_CFG("W4_GPIO58", D, 3, 7, 3, 5, 0, 3, 0, 1)
@@ -388,6 +397,7 @@ MUX_CFG("R19_1510_GPIO1", 7, 6, 0, 1, 10, 1, 0, 0, 1)
MUX_CFG("M14_1510_GPIO2", 7, 3, 0, 1, 9, 1, 0, 0, 1)
/* OMAP1610 GPIO */
+MUX_CFG("P18_1610_GPIO3", 7, 0, 0, 1, 8, 0, NA, 0, 1)
MUX_CFG("Y15_1610_GPIO17", A, 0, 7, 2, 6, 0, NA, 0, 1)
/* OMAP-1710 GPIO */
@@ -454,6 +464,7 @@ MUX_CFG("P10_1610_GPIO22", C, 0, 7, 2, 26, 0, 2, 1, 1)
MUX_CFG("V5_1610_GPIO24", B, 15, 7, 2, 21, 0, 2, 1, 1)
MUX_CFG("AA20_1610_GPIO_41", 9, 9, 7, 1, 31, 0, 1, 1, 1)
MUX_CFG("W19_1610_GPIO48", 8, 15, 7, 1, 23, 1, 1, 0, 1)
+MUX_CFG("M7_1610_GPIO62", 10, 0, 0, 4, 24, 0, 4, 0, 1)
/* OMAP-1610 uWire */
MUX_CFG("V19_1610_UWIRE_SCLK", 8, 6, 0, 1, 20, 0, 1, 1, 1)
@@ -528,6 +539,13 @@ MUX_CFG("V5_1710_MCLK_ON", B, 15, 0, NA, 0, 0, NA, 0, 0)
MUX_CFG("V5_1710_MCLK_OFF", B, 15, 6, NA, 0, 0, NA, 0, 0)
MUX_CFG("R10_1610_MCLK_ON", B, 18, 0, NA, 22, 0, NA, 1, 0)
MUX_CFG("R10_1610_MCLK_OFF", B, 18, 6, 2, 22, 1, 2, 1, 1)
+
+/* CompactFlash controller, conflicts with MMC1 */
+MUX_CFG("P11_1610_CF_CD2", A, 27, 3, 2, 15, 1, 2, 1, 1)
+MUX_CFG("R11_1610_CF_IOIS16", B, 0, 3, 2, 16, 1, 2, 1, 1)
+MUX_CFG("V10_1610_CF_IREQ", A, 24, 3, 2, 14, 0, 2, 0, 1)
+MUX_CFG("W10_1610_CF_RESET", A, 18, 3, 2, 12, 1, 2, 1, 1)
+MUX_CFG("W11_1610_CF_CD1", 10, 15, 3, 3, 8, 1, 3, 1, 1)
};
#endif /* __MUX_C__ */
diff --git a/include/asm-arm/arch-omap/omap16xx.h b/include/asm-arm/arch-omap/omap16xx.h
index 16db097d1a78e..88b1fe43ae9eb 100644
--- a/include/asm-arm/arch-omap/omap16xx.h
+++ b/include/asm-arm/arch-omap/omap16xx.h
@@ -121,6 +121,13 @@
#define OMAP16XX_SUBLVDS_CONF_VALID (1 << 13)
/*
+ * ----------------------------------------------------------------------------
+ * System control registers
+ * ----------------------------------------------------------------------------
+ */
+#define OMAP1610_RESET_CONTROL 0xfffe1140
+
+/*
* ---------------------------------------------------------------------------
* TIPB bus interface
* ---------------------------------------------------------------------------
diff --git a/include/asm-arm/arch-omap/param.h b/include/asm-arm/arch-omap/param.h
index 8d7fc79ce4c51..face9ad41e97a 100644
--- a/include/asm-arm/arch-omap/param.h
+++ b/include/asm-arm/arch-omap/param.h
@@ -1,24 +1,8 @@
/*
* linux/include/asm-arm/arch-omap/param.h
*
- * Initially based on linux/include/asm-arm/arch-integrator/param.h
- * Copyright (C) 1999 ARM Limited
- *
- * BRIEF MODULE DESCRIPTION
- * a place holder
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the 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
*/
+#ifdef CONFIG_OMAP_32K_TIMER_HZ
+#define HZ CONFIG_OMAP_32K_TIMER_HZ
+#endif
diff --git a/include/asm-arm/arch-omap/tc.h b/include/asm-arm/arch-omap/tc.h
index a1d2e5a206750..8ded218cbea5f 100644
--- a/include/asm-arm/arch-omap/tc.h
+++ b/include/asm-arm/arch-omap/tc.h
@@ -24,22 +24,33 @@
#ifndef __ASM_ARCH_TC_H
#define __ASM_ARCH_TC_H
-#define OMAP_TC_OCPT1_PRIOR 0xFFFECC00
-#define OMAP_TC_EMIFS_PRIOR 0xFFFECC04
-#define OMAP_TC_EMIFF_PRIOR 0xFFFECC08
-#define OMAP_TC_OCPT2_PRIOR 0xFFFECCD0
-
-
-/* EMIF Slow Interface Configuration Register */
-#define OMAP_EMIFS_CONFIG_REG __REG32(EMIFS_CONFIG)
-
-#define OMAP_EMIFS_CONFIG_FR (1 << 4)
-#define OMAP_EMIFS_CONFIG_PDE (1 << 3)
-#define OMAP_EMIFS_CONFIG_PWD_EN (1 << 2)
-#define OMAP_EMIFS_CONFIG_BM (1 << 1)
-#define OMAP_EMIFS_CONFIG_WP (1 << 0)
+#define TCMIF_BASE 0xfffecc00
+#define OMAP_TC_OCPT1_PRIOR (TCMIF_BASE + 0x00)
+#define OMAP_TC_EMIFS_PRIOR (TCMIF_BASE + 0x04)
+#define OMAP_TC_EMIFF_PRIOR (TCMIF_BASE + 0x08)
+#define EMIFS_CONFIG (TCMIF_BASE + 0x0c)
+#define EMIFS_CS0_CONFIG (TCMIF_BASE + 0x10)
+#define EMIFS_CS1_CONFIG (TCMIF_BASE + 0x14)
+#define EMIFS_CS2_CONFIG (TCMIF_BASE + 0x18)
+#define EMIFS_CS3_CONFIG (TCMIF_BASE + 0x1c)
+#define EMIFF_SDRAM_CONFIG (TCMIF_BASE + 0x20)
+#define EMIFF_MRS (TCMIF_BASE + 0x24)
+#define TC_TIMEOUT1 (TCMIF_BASE + 0x28)
+#define TC_TIMEOUT2 (TCMIF_BASE + 0x2c)
+#define TC_TIMEOUT3 (TCMIF_BASE + 0x30)
+#define TC_ENDIANISM (TCMIF_BASE + 0x34)
+#define EMIFF_SDRAM_CONFIG_2 (TCMIF_BASE + 0x3c)
+#define EMIF_CFG_DYNAMIC_WS (TCMIF_BASE + 0x40)
+#define EMIFS_ACS0 (TCMIF_BASE + 0x50)
+#define EMIFS_ACS1 (TCMIF_BASE + 0x54)
+#define EMIFS_ACS2 (TCMIF_BASE + 0x58)
+#define EMIFS_ACS3 (TCMIF_BASE + 0x5c)
+#define OMAP_TC_OCPT2_PRIOR (TCMIF_BASE + 0xd0)
/* external EMIFS chipselect regions */
+#define OMAP_CS0_PHYS 0x00000000
+#define OMAP_CS0_SIZE SZ_64M
+
#define OMAP_CS1_PHYS 0x04000000
#define OMAP_CS1_SIZE SZ_64M
@@ -61,4 +72,37 @@
#define OMAP_CS3_PHYS 0x0c000000
#define OMAP_CS3_SIZE SZ_64M
+#ifndef __ASSEMBLER__
+
+/* EMIF Slow Interface Configuration Register */
+#define OMAP_EMIFS_CONFIG_REG __REG32(EMIFS_CONFIG)
+
+#define OMAP_EMIFS_CONFIG_FR (1 << 4)
+#define OMAP_EMIFS_CONFIG_PDE (1 << 3)
+#define OMAP_EMIFS_CONFIG_PWD_EN (1 << 2)
+#define OMAP_EMIFS_CONFIG_BM (1 << 1)
+#define OMAP_EMIFS_CONFIG_WP (1 << 0)
+
+#define EMIFS_CCS(n) __REG32(EMIFS_CS0_CONFIG + (4 * (n)))
+#define EMIFS_ACS(n) __REG32(EMIFS_ACS0 + (4 * (n)))
+
+/* Almost all documentation for chip and board memory maps assumes
+ * BM is clear. Most devel boards have a switch to control booting
+ * from NOR flash (using external chipselect 3) rather than mask ROM,
+ * which uses BM to interchange the physical CS0 and CS3 addresses.
+ */
+static inline u32 omap_cs0_phys(void)
+{
+ return (OMAP_EMIFS_CONFIG_REG & OMAP_EMIFS_CONFIG_BM)
+ ? OMAP_CS3_PHYS : 0;
+}
+
+static inline u32 omap_cs3_phys(void)
+{
+ return (OMAP_EMIFS_CONFIG_REG & OMAP_EMIFS_CONFIG_BM)
+ ? 0 : OMAP_CS3_PHYS;
+}
+
+#endif /* __ASSEMBLER__ */
+
#endif /* __ASM_ARCH_TC_H */
diff --git a/include/asm-arm/arch-pxa/corgi.h b/include/asm-arm/arch-pxa/corgi.h
index 950c9378a6a68..4f69467327d1e 100644
--- a/include/asm-arm/arch-pxa/corgi.h
+++ b/include/asm-arm/arch-pxa/corgi.h
@@ -133,6 +133,10 @@ struct sharpsl_flash_param_info {
unsigned int phadadj;
};
+/*
+ * Shared data structures
+ */
+extern struct platform_device corgiscoop_device;
/*
* External Functions
diff --git a/include/asm-arm/arch-pxa/idp.h b/include/asm-arm/arch-pxa/idp.h
index e496ed7f496af..e7ef497417bbe 100644
--- a/include/asm-arm/arch-pxa/idp.h
+++ b/include/asm-arm/arch-pxa/idp.h
@@ -10,20 +10,20 @@
* 2001-09-13: Cliff Brake <cbrake@accelent.com>
* Initial code
*
+ * 2005-02-15: Cliff Brake <cliff.brake@gmail.com>
+ * <http://www.vibren.com> <http://bec-systems.com>
+ * Changes for 2.6 kernel.
*/
#include <linux/config.h>
/*
* Note: this file must be safe to include in assembly files
+ *
+ * Support for the Vibren PXA255 IDP requires rev04 or later
+ * IDP hardware.
*/
-/* comment out following if you have a rev01 board */
-#define PXA_IDP_REV02 1
-
-#ifdef PXA_IDP_REV02
-//Use this as well for 0017-x004 and greater pcb's:
-#define PXA_IDP_REV04 1
#define IDP_FLASH_PHYS (PXA_CS0_PHYS)
#define IDP_ALT_FLASH_PHYS (PXA_CS1_PHYS)
@@ -38,26 +38,18 @@
* virtual memory map
*/
-#define IDP_IDE_BASE (0xf0000000)
-#define IDP_IDE_SIZE (1*1024*1024)
-#define IDE_REG_STRIDE 4
-
-#define IDP_ETH_BASE (IDP_IDE_BASE + IDP_IDE_SIZE)
-#define IDP_ETH_SIZE (1*1024*1024)
-#define ETH_BASE IDP_ETH_BASE //smc9194 driver compatibility issue
-
-#define IDP_COREVOLT_BASE (IDP_ETH_BASE + IDP_ETH_SIZE)
+#define IDP_COREVOLT_VIRT (0xf0000000)
#define IDP_COREVOLT_SIZE (1*1024*1024)
-#define IDP_CPLD_BASE (IDP_COREVOLT_BASE + IDP_COREVOLT_SIZE)
+#define IDP_CPLD_VIRT (IDP_COREVOLT_VIRT + IDP_COREVOLT_SIZE)
#define IDP_CPLD_SIZE (1*1024*1024)
-#if (IDP_CPLD_BASE + IDP_CPLD_SIZE) > 0xfc000000
+#if (IDP_CPLD_VIRT + IDP_CPLD_SIZE) > 0xfc000000
#error Your custom IO space is getting a bit large !!
#endif
-#define CPLD_P2V(x) ((x) - IDP_CPLD_PHYS + IDP_CPLD_BASE)
-#define CPLD_V2P(x) ((x) - IDP_CPLD_BASE + IDP_CPLD_PHYS)
+#define CPLD_P2V(x) ((x) - IDP_CPLD_PHYS + IDP_CPLD_VIRT)
+#define CPLD_V2P(x) ((x) - IDP_CPLD_VIRT + IDP_CPLD_PHYS)
#ifndef __ASSEMBLY__
# define __CPLD_REG(x) (*((volatile unsigned long *)CPLD_P2V(x)))
@@ -65,7 +57,7 @@
# define __CPLD_REG(x) CPLD_P2V(x)
#endif
-/* board level registers in the CPLD: (offsets from CPLD_BASE) */
+/* board level registers in the CPLD: (offsets from CPLD_VIRT) */
#define _IDP_CPLD_REV (IDP_CPLD_PHYS + 0x00)
#define _IDP_CPLD_PERIPH_PWR (IDP_CPLD_PHYS + 0x04)
@@ -142,32 +134,10 @@
#define PCC_DETECT(x) (GPLR(7 + (x)) & GPIO_bit(7 + (x)))
-/*
- * Macros for LCD Driver
- */
-
-#ifdef CONFIG_FB_PXA
-
-#define FB_BACKLIGHT_ON() (IDP_CPLD_LCD |= (1<<1))
-#define FB_BACKLIGHT_OFF() (IDP_CPLD_LCD &= ~(1<<1))
-
-#define FB_PWR_ON() (IDP_CPLD_LCD |= (1<< 0))
-#define FB_PWR_OFF() (IDP_CPLD_LCD &= ~(1<<0))
-
-#define FB_VLCD_ON() (IDP_CPLD_LCD |= (1<<2))
-#define FB_VLCD_OFF() (IDP_CPLD_LCD &= ~(1<<2))
-
-#endif
-
/* A listing of interrupts used by external hardware devices */
-#ifdef PXA_IDP_REV04
#define TOUCH_PANEL_IRQ IRQ_GPIO(5)
#define IDE_IRQ IRQ_GPIO(21)
-#else
-#define TOUCH_PANEL_IRQ IRQ_GPIO(21)
-#define IDE_IRQ IRQ_GPIO(5)
-#endif
#define TOUCH_PANEL_IRQ_EDGE IRQT_FALLING
@@ -196,8 +166,6 @@
#define IDP_LEDS_MASK (IDP_HB_LED | IDP_BUSY_LED)
-#define IDP_WRITE_LEDS(value) (IDP_CPLD_LED_CONTROL = (IDP_CPLD_LED_CONTROL & (~(IDP_LEDS_MASK)) | value))
-
/*
* macros for MTD driver
*/
@@ -229,238 +197,4 @@
inputs = (IDP_CPLD_KB_ROW & 0x7f);\
}
-#else
-
-/*
- * following is for rev01 boards only
- */
-
-#define IDP_FLASH_PHYS (PXA_CS0_PHYS)
-#define IDP_ALT_FLASH_PHYS (PXA_CS1_PHYS)
-#define IDP_MEDIAQ_PHYS (PXA_CS3_PHYS)
-#define IDP_CTRL_PORT_PHYS (PXA_CS5_PHYS + 0x02C00000)
-#define IDP_IDE_PHYS (PXA_CS5_PHYS + 0x03000000)
-#define IDP_ETH_PHYS (PXA_CS5_PHYS + 0x03400000)
-#define IDP_COREVOLT_PHYS (PXA_CS5_PHYS + 0x03800000)
-#define IDP_CPLD_PHYS (PXA_CS5_PHYS + 0x03C00000)
-
-
-/*
- * virtual memory map
- */
-
-#define IDP_CTRL_PORT_BASE (0xf0000000)
-#define IDP_CTRL_PORT_SIZE (1*1024*1024)
-
-#define IDP_IDE_BASE (IDP_CTRL_PORT_BASE + IDP_CTRL_PORT_SIZE)
-#define IDP_IDE_SIZE (1*1024*1024)
-
-#define IDP_ETH_BASE (IDP_IDE_BASE + IDP_IDE_SIZE)
-#define IDP_ETH_SIZE (1*1024*1024)
-
-#define IDP_COREVOLT_BASE (IDP_ETH_BASE + IDP_ETH_SIZE)
-#define IDP_COREVOLT_SIZE (1*1024*1024)
-
-#define IDP_CPLD_BASE (IDP_COREVOLT_BASE + IDP_COREVOLT_SIZE)
-#define IDP_CPLD_SIZE (1*1024*1024)
-
-#if (IDP_CPLD_BASE + IDP_CPLD_SIZE) > 0xfc000000
-#error Your custom IO space is getting a bit large !!
-#endif
-
-#define CPLD_P2V(x) ((x) - IDP_CPLD_PHYS + IDP_CPLD_BASE)
-#define CPLD_V2P(x) ((x) - IDP_CPLD_BASE + IDP_CPLD_PHYS)
-
-#ifndef __ASSEMBLY__
-# define __CPLD_REG(x) (*((volatile unsigned long *)CPLD_P2V(x)))
-#else
-# define __CPLD_REG(x) CPLD_P2V(x)
-#endif
-
-/* board level registers in the CPLD: (offsets from CPLD_BASE) */
-
-#define _IDP_CPLD_LED_CONTROL (IDP_CPLD_PHYS + 0x00)
-#define _IDP_CPLD_PERIPH_PWR (IDP_CPLD_PHYS + 0x04)
-#define _IDP_CPLD_CIR (IDP_CPLD_PHYS + 0x08)
-#define _IDP_CPLD_KB_COL_HIGH (IDP_CPLD_PHYS + 0x0C)
-#define _IDP_CPLD_KB_COL_LOW (IDP_CPLD_PHYS + 0x10)
-#define _IDP_CPLD_PCCARD_EN (IDP_CPLD_PHYS + 0x14)
-#define _IDP_CPLD_GPIOH_DIR (IDP_CPLD_PHYS + 0x18)
-#define _IDP_CPLD_GPIOH_VALUE (IDP_CPLD_PHYS + 0x1C)
-#define _IDP_CPLD_GPIOL_DIR (IDP_CPLD_PHYS + 0x20)
-#define _IDP_CPLD_GPIOL_VALUE (IDP_CPLD_PHYS + 0x24)
-#define _IDP_CPLD_MISC (IDP_CPLD_PHYS + 0x28)
-#define _IDP_CPLD_PCCARD0_STATUS (IDP_CPLD_PHYS + 0x2C)
-#define _IDP_CPLD_PCCARD1_STATUS (IDP_CPLD_PHYS + 0x30)
-
-/* FPGA register virtual addresses */
-#define IDP_CPLD_LED_CONTROL __CPLD_REG(_IDP_CPLD_LED_CONTROL) /* write only */
-#define IDP_CPLD_PERIPH_PWR __CPLD_REG(_IDP_CPLD_PERIPH_PWR) /* write only */
-#define IDP_CPLD_CIR __CPLD_REG(_IDP_CPLD_CIR) /* write only */
-#define IDP_CPLD_KB_COL_HIGH __CPLD_REG(_IDP_CPLD_KB_COL_HIGH) /* write only */
-#define IDP_CPLD_KB_COL_LOW __CPLD_REG(_IDP_CPLD_KB_COL_LOW) /* write only */
-#define IDP_CPLD_PCCARD_EN __CPLD_REG(_IDP_CPLD_PCCARD_EN) /* write only */
-#define IDP_CPLD_GPIOH_DIR __CPLD_REG(_IDP_CPLD_GPIOH_DIR) /* write only */
-#define IDP_CPLD_GPIOH_VALUE __CPLD_REG(_IDP_CPLD_GPIOH_VALUE) /* write only */
-#define IDP_CPLD_GPIOL_DIR __CPLD_REG(_IDP_CPLD_GPIOL_DIR) /* write only */
-#define IDP_CPLD_GPIOL_VALUE __CPLD_REG(_IDP_CPLD_GPIOL_VALUE) /* write only */
-#define IDP_CPLD_MISC __CPLD_REG(_IDP_CPLD_MISC) /* read only */
-#define IDP_CPLD_PCCARD0_STATUS __CPLD_REG(_IDP_CPLD_PCCARD0_STATUS) /* read only */
-#define IDP_CPLD_PCCARD1_STATUS __CPLD_REG(_IDP_CPLD_PCCARD1_STATUS) /* read only */
-
-
-#ifndef __ASSEMBLY__
-
-/* shadow registers for write only registers */
-extern unsigned int idp_cpld_led_control_shadow;
-extern unsigned int idp_cpld_periph_pwr_shadow;
-extern unsigned int idp_cpld_cir_shadow;
-extern unsigned int idp_cpld_kb_col_high_shadow;
-extern unsigned int idp_cpld_kb_col_low_shadow;
-extern unsigned int idp_cpld_pccard_en_shadow;
-extern unsigned int idp_cpld_gpioh_dir_shadow;
-extern unsigned int idp_cpld_gpioh_value_shadow;
-extern unsigned int idp_cpld_gpiol_dir_shadow;
-extern unsigned int idp_cpld_gpiol_value_shadow;
-
-extern unsigned int idp_control_port_shadow;
-
-/*
- * macros to write to write only register
- *
- * none of these macros are protected from
- * multiple drivers using them in interrupt context.
- */
-
-#define WRITE_IDP_CPLD_LED_CONTROL(value, mask) \
-{\
- idp_cpld_led_control_shadow = (((value & mask) | (idp_cpld_led_control_shadow & ~mask)));\
- IDP_CPLD_LED_CONTROL = idp_cpld_led_control_shadow;\
-}
-#define WRITE_IDP_CPLD_PERIPH_PWR(value, mask) \
-{\
- idp_cpld_periph_pwr_shadow = ((value & mask) | (idp_cpld_periph_pwr_shadow & ~mask));\
- IDP_CPLD_PERIPH_PWR = idp_cpld_periph_pwr_shadow;\
-}
-#define WRITE_IDP_CPLD_CIR(value, mask) \
-{\
- idp_cpld_cir_shadow = ((value & mask) | (idp_cpld_cir_shadow & ~mask));\
- IDP_CPLD_CIR = idp_cpld_cir_shadow;\
-}
-#define WRITE_IDP_CPLD_KB_COL_HIGH(value, mask) \
-{\
- idp_cpld_kb_col_high_shadow = ((value & mask) | (idp_cpld_kb_col_high_shadow & ~mask));\
- IDP_CPLD_KB_COL_HIGH = idp_cpld_kb_col_high_shadow;\
-}
-#define WRITE_IDP_CPLD_KB_COL_LOW(value, mask) \
-{\
- idp_cpld_kb_col_low_shadow = ((value & mask) | (idp_cpld_kb_col_low_shadow & ~mask));\
- IDP_CPLD_KB_COL_LOW = idp_cpld_kb_col_low_shadow;\
-}
-#define WRITE_IDP_CPLD_PCCARD_EN(value, mask) \
-{\
- idp_cpld_ = ((value & mask) | (idp_cpld_led_control_shadow & ~mask));\
- IDP_CPLD_LED_CONTROL = idp_cpld_led_control_shadow;\
-}
-#define WRITE_IDP_CPLD_GPIOH_DIR(value, mask) \
-{\
- idp_cpld_gpioh_dir_shadow = ((value & mask) | (idp_cpld_gpioh_dir_shadow & ~mask));\
- IDP_CPLD_GPIOH_DIR = idp_cpld_gpioh_dir_shadow;\
-}
-#define WRITE_IDP_CPLD_GPIOH_VALUE(value, mask) \
-{\
- idp_cpld_gpioh_value_shadow = ((value & mask) | (idp_cpld_gpioh_value_shadow & ~mask));\
- IDP_CPLD_GPIOH_VALUE = idp_cpld_gpioh_value_shadow;\
-}
-#define WRITE_IDP_CPLD_GPIOL_DIR(value, mask) \
-{\
- idp_cpld_gpiol_dir_shadow = ((value & mask) | (idp_cpld_gpiol_dir_shadow & ~mask));\
- IDP_CPLD_GPIOL_DIR = idp_cpld_gpiol_dir_shadow;\
-}
-#define WRITE_IDP_CPLD_GPIOL_VALUE(value, mask) \
-{\
- idp_cpld_gpiol_value_shadow = ((value & mask) | (idp_cpld_gpiol_value_shadow & ~mask));\
- IDP_CPLD_GPIOL_VALUE = idp_cpld_gpiol_value_shadow;\
-}
-
-#define WRITE_IDP_CONTROL_PORT(value, mask) \
-{\
- idp_control_port_shadow = ((value & mask) | (idp_control_port_shadow & ~mask));\
- (*((volatile unsigned long *)IDP_CTRL_PORT_BASE)) = idp_control_port_shadow;\
-}
-
-#endif
-/* A listing of interrupts used by external hardware devices */
-
-#define TOUCH_PANEL_IRQ IRQ_GPIO(21)
-#define TOUCH_PANEL_IRQ_EGDE IRQT_FALLING
-
-#define ETHERNET_IRQ IRQ_GPIO(4)
-#define ETHERNET_IRQ_EDGE IRQT_RISING
-
-/*
- * Bit masks for various registers
- */
-
-
-/* control port */
-#define IDP_CONTROL_PORT_PCSLOT0_0 (1 << 0)
-#define IDP_CONTROL_PORT_PCSLOT0_1 (1 << 1)
-#define IDP_CONTROL_PORT_PCSLOT0_2 (1 << 2)
-#define IDP_CONTROL_PORT_PCSLOT0_3 (1 << 3)
-#define IDP_CONTROL_PORT_PCSLOT1_1 (1 << 4)
-#define IDP_CONTROL_PORT_PCSLOT1_2 (1 << 5)
-#define IDP_CONTROL_PORT_PCSLOT1_3 (1 << 6)
-#define IDP_CONTROL_PORT_PCSLOT1_4 (1 << 7)
-#define IDP_CONTROL_PORT_SERIAL1_EN (1 << 9)
-#define IDP_CONTROL_PORT_SERIAL2_EN (1 << 10)
-#define IDP_CONTROL_PORT_SERIAL3_EN (1 << 11)
-#define IDP_CONTROL_PORT_IRDA_FIR (1 << 12)
-#define IDP_CONTROL_PORT_IRDA_M0 (1 << 13)
-#define IDP_CONTROL_PORT_IRDA_M1 (1 << 14)
-#define IDP_CONTROL_PORT_I2S_PWR (1 << 15)
-#define IDP_CONTROL_PORT_FLASH_WP (1 << 19)
-#define IDP_CONTROL_PORT_MILL_EN (1 << 20)
-#define IDP_CONTROL_PORT_LCD_PWR (1 << 21)
-#define IDP_CONTROL_PORT_LCD_BKLEN (1 << 22)
-#define IDP_CONTROL_PORT_LCD_ENAVLCD (1 << 23)
-
-/*
- * Macros for LCD Driver
- */
-
-#ifdef CONFIG_FB_PXA
-
-#define FB_BACKLIGHT_ON() WRITE_IDP_CONTROL_PORT(IDP_CONTROL_PORT_LCD_BKLEN, IDP_CONTROL_PORT_LCD_BKLEN)
-#define FB_BACKLIGHT_OFF() WRITE_IDP_CONTROL_PORT(0, IDP_CONTROL_PORT_LCD_BKLEN)
-
-#define FB_PWR_ON() WRITE_IDP_CONTROL_PORT(IDP_CONTROL_PORT_LCD_PWR, IDP_CONTROL_PORT_LCD_PWR)
-#define FB_PWR_OFF() WRITE_IDP_CONTROL_PORT(0, IDP_CONTROL_PORT_LCD_PWR)
-
-#define FB_VLCD_ON() WRITE_IDP_CONTROL_PORT(IDP_CONTROL_PORT_LCD_ENAVLCD, IDP_CONTROL_PORT_LCD_ENAVLCD)
-#define FB_VLCD_OFF() WRITE_IDP_CONTROL_PORT(0, IDP_CONTROL_PORT_LCD_ENAVLCD)
-
-#endif
-
-
-/*
- * Macros for LED Driver
- */
-
-/* leds 0 = ON */
-#define IDP_HB_LED 0x1
-#define IDP_BUSY_LED 0x2
-
-#define IDP_LEDS_MASK (IDP_HB_LED | IDP_BUSY_LED)
-
-#define IDP_WRITE_LEDS(value) WRITE_IDP_CPLD_LED_CONTROL(value, IDP_LEDS_MASK)
-
-/*
- * macros for MTD driver
- */
-
-#define FLASH_WRITE_PROTECT_DISABLE() WRITE_IDP_CONTROL_PORT(0, IDP_CONTROL_PORT_FLASH_WP)
-#define FLASH_WRITE_PROTECT_ENABLE() WRITE_IDP_CONTROL_PORT(IDP_CONTROL_PORT_FLASH_WP, IDP_CONTROL_PORT_FLASH_WP)
-
-#endif
diff --git a/include/asm-arm/arch-pxa/irqs.h b/include/asm-arm/arch-pxa/irqs.h
index 3d9b92a466ca2..05c4b70275929 100644
--- a/include/asm-arm/arch-pxa/irqs.h
+++ b/include/asm-arm/arch-pxa/irqs.h
@@ -140,14 +140,41 @@
#define IRQ_S0_BVD1_STSCHG (IRQ_BOARD_END + 53)
#define IRQ_S1_BVD1_STSCHG (IRQ_BOARD_END + 54)
+#define IRQ_LOCOMO_START (IRQ_BOARD_END)
+#define IRQ_LOCOMO_KEY (IRQ_BOARD_END + 0)
+#define IRQ_LOCOMO_GPIO0 (IRQ_BOARD_END + 1)
+#define IRQ_LOCOMO_GPIO1 (IRQ_BOARD_END + 2)
+#define IRQ_LOCOMO_GPIO2 (IRQ_BOARD_END + 3)
+#define IRQ_LOCOMO_GPIO3 (IRQ_BOARD_END + 4)
+#define IRQ_LOCOMO_GPIO4 (IRQ_BOARD_END + 5)
+#define IRQ_LOCOMO_GPIO5 (IRQ_BOARD_END + 6)
+#define IRQ_LOCOMO_GPIO6 (IRQ_BOARD_END + 7)
+#define IRQ_LOCOMO_GPIO7 (IRQ_BOARD_END + 8)
+#define IRQ_LOCOMO_GPIO8 (IRQ_BOARD_END + 9)
+#define IRQ_LOCOMO_GPIO9 (IRQ_BOARD_END + 10)
+#define IRQ_LOCOMO_GPIO10 (IRQ_BOARD_END + 11)
+#define IRQ_LOCOMO_GPIO11 (IRQ_BOARD_END + 12)
+#define IRQ_LOCOMO_GPIO12 (IRQ_BOARD_END + 13)
+#define IRQ_LOCOMO_GPIO13 (IRQ_BOARD_END + 14)
+#define IRQ_LOCOMO_GPIO14 (IRQ_BOARD_END + 15)
+#define IRQ_LOCOMO_GPIO15 (IRQ_BOARD_END + 16)
+#define IRQ_LOCOMO_LT (IRQ_BOARD_END + 17)
+#define IRQ_LOCOMO_SPI_RFR (IRQ_BOARD_END + 18)
+#define IRQ_LOCOMO_SPI_RFW (IRQ_BOARD_END + 19)
+#define IRQ_LOCOMO_SPI_OVRN (IRQ_BOARD_END + 20)
+#define IRQ_LOCOMO_SPI_TEND (IRQ_BOARD_END + 21)
+
/*
* Figure out the MAX IRQ number.
*
* If we have an SA1111, the max IRQ is S1_BVD1_STSCHG+1.
+ * If we have an LoCoMo, the max IRQ is IRQ_LOCOMO_SPI_TEND+1
* Otherwise, we have the standard IRQs only.
*/
#ifdef CONFIG_SA1111
#define NR_IRQS (IRQ_S1_BVD1_STSCHG + 1)
+#elif defined(CONFIG_SHARP_LOCOMO)
+#define NR_IRQS (IRQ_LOCOMO_SPI_TEND + 1)
#elif defined(CONFIG_ARCH_LUBBOCK) || \
defined(CONFIG_MACH_MAINSTONE)
#define NR_IRQS (IRQ_BOARD_END)
@@ -185,3 +212,8 @@
#define MAINSTONE_S1_STSCHG_IRQ MAINSTONE_IRQ(14)
#define MAINSTONE_S1_IRQ MAINSTONE_IRQ(15)
+/* LoCoMo Interrupts (CONFIG_SHARP_LOCOMO) */
+#define IRQ_LOCOMO_KEY_BASE (IRQ_BOARD_START + 0)
+#define IRQ_LOCOMO_GPIO_BASE (IRQ_BOARD_START + 1)
+#define IRQ_LOCOMO_LT_BASE (IRQ_BOARD_START + 2)
+#define IRQ_LOCOMO_SPI_BASE (IRQ_BOARD_START + 3)
diff --git a/include/asm-arm/arch-pxa/poodle.h b/include/asm-arm/arch-pxa/poodle.h
new file mode 100644
index 0000000000000..027573d38ee47
--- /dev/null
+++ b/include/asm-arm/arch-pxa/poodle.h
@@ -0,0 +1,111 @@
+/*
+ * linux/include/asm-arm/arch-pxa/poodle.h
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License. See linux/COPYING for more information.
+ *
+ * Based on:
+ * linux/include/asm-arm/arch-sa1100/collie.h
+ *
+ * ChangeLog:
+ * 04-06-2001 Lineo Japan, Inc.
+ * 04-16-2001 SHARP Corporation
+ * Update to 2.6 John Lenz
+ */
+#ifndef __ASM_ARCH_POODLE_H
+#define __ASM_ARCH_POODLE_H 1
+
+/*
+ * GPIOs
+ */
+/* PXA GPIOs */
+#define POODLE_GPIO_ON_KEY (0)
+#define POODLE_GPIO_AC_IN (1)
+#define POODLE_GPIO_CO 16
+#define POODLE_GPIO_TP_INT (5)
+#define POODLE_GPIO_WAKEUP (11) /* change battery */
+#define POODLE_GPIO_GA_INT (10)
+#define POODLE_GPIO_IR_ON (22)
+#define POODLE_GPIO_HP_IN (4)
+#define POODLE_GPIO_CF_IRQ (17)
+#define POODLE_GPIO_CF_CD (14)
+#define POODLE_GPIO_CF_STSCHG (14)
+#define POODLE_GPIO_SD_PWR (33)
+#define POODLE_GPIO_nSD_CLK (6)
+#define POODLE_GPIO_nSD_WP (7)
+#define POODLE_GPIO_nSD_INT (8)
+#define POODLE_GPIO_nSD_DETECT (9)
+#define POODLE_GPIO_MAIN_BAT_LOW (13)
+#define POODLE_GPIO_BAT_COVER (13)
+#define POODLE_GPIO_ADC_TEMP_ON (21)
+#define POODLE_GPIO_BYPASS_ON (36)
+#define POODLE_GPIO_CHRG_ON (38)
+#define POODLE_GPIO_CHRG_FULL (16)
+
+/* PXA GPIOs */
+#define POODLE_IRQ_GPIO_ON_KEY IRQ_GPIO0
+#define POODLE_IRQ_GPIO_AC_IN IRQ_GPIO1
+#define POODLE_IRQ_GPIO_HP_IN IRQ_GPIO4
+#define POODLE_IRQ_GPIO_CO IRQ_GPIO16
+#define POODLE_IRQ_GPIO_TP_INT IRQ_GPIO5
+#define POODLE_IRQ_GPIO_WAKEUP IRQ_GPIO11
+#define POODLE_IRQ_GPIO_GA_INT IRQ_GPIO10
+#define POODLE_IRQ_GPIO_CF_IRQ IRQ_GPIO17
+#define POODLE_IRQ_GPIO_CF_CD IRQ_GPIO14
+#define POODLE_IRQ_GPIO_nSD_INT IRQ_GPIO8
+#define POODLE_IRQ_GPIO_nSD_DETECT IRQ_GPIO9
+#define POODLE_IRQ_GPIO_MAIN_BAT_LOW IRQ_GPIO13
+
+/* SCOOP GPIOs */
+#define POODLE_SCOOP_CHARGE_ON SCOOP_GPCR_PA11
+#define POODLE_SCOOP_CP401 SCOOP_GPCR_PA13
+#define POODLE_SCOOP_VPEN SCOOP_GPCR_PA18
+#define POODLE_SCOOP_L_PCLK SCOOP_GPCR_PA20
+#define POODLE_SCOOP_L_LCLK SCOOP_GPCR_PA21
+#define POODLE_SCOOP_HS_OUT SCOOP_GPCR_PA22
+
+#define POODLE_SCOOP_IO_DIR ( POODLE_SCOOP_VPEN | POODLE_SCOOP_HS_OUT )
+#define POODLE_SCOOP_IO_OUT ( 0 )
+
+/*
+ * Flash Memory mappings
+ *
+ * We have the following mapping:
+ * phys virt
+ * boot ROM 00000000 ef800000
+ */
+#define FLASH_MEM_BASE 0xa0000a00
+#define FLASH_DATA(adr) (*(volatile unsigned int*)(FLASH_MEM_BASE+(adr)))
+#define FLASH_DATA_F(adr) (*(volatile float32 *)(FLASH_MEM_BASE+(adr)))
+#define FLASH_MAGIC_CHG(a,b,c,d) ( ( d << 24 ) | ( c << 16 ) | ( b << 8 ) | a )
+
+/* COMADJ */
+#define FLASH_COMADJ_MAJIC FLASH_MAGIC_CHG('C','M','A','D')
+#define FLASH_COMADJ_MAGIC_ADR 0x00
+#define FLASH_COMADJ_DATA_ADR 0x04
+
+/* UUID */
+#define FLASH_UUID_MAJIC FLASH_MAGIC_CHG('U','U','I','D')
+#define FLASH_UUID_MAGIC_ADR 0x08
+#define FLASH_UUID_DATA_ADR 0x0C
+
+/* TOUCH PANEL */
+#define FLASH_TOUCH_MAJIC FLASH_MAGIC_CHG('T','U','C','H')
+#define FLASH_TOUCH_MAGIC_ADR 0x1C
+#define FLASH_TOUCH_XP_DATA_ADR 0x20
+#define FLASH_TOUCH_YP_DATA_ADR 0x24
+#define FLASH_TOUCH_XD_DATA_ADR 0x28
+#define FLASH_TOUCH_YD_DATA_ADR 0x2C
+
+/* AD */
+#define FLASH_AD_MAJIC FLASH_MAGIC_CHG('B','V','A','D')
+#define FLASH_AD_MAGIC_ADR 0x30
+#define FLASH_AD_DATA_ADR 0x34
+
+/* PHAD */
+#define FLASH_PHAD_MAJIC FLASH_MAGIC_CHG('P','H','A','D')
+#define FLASH_PHAD_MAGIC_ADR 0x38
+#define FLASH_PHAD_DATA_ADR 0x3C
+
+
+#endif /* __ASM_ARCH_POODLE_H */
diff --git a/include/asm-arm/arch-rpc/hardware.h b/include/asm-arm/arch-rpc/hardware.h
index 9dc5f5d4b9122..be9754a05c19f 100644
--- a/include/asm-arm/arch-rpc/hardware.h
+++ b/include/asm-arm/arch-rpc/hardware.h
@@ -14,6 +14,12 @@
#include <asm/arch/memory.h>
+#ifndef __ASSEMBLY__
+#define IOMEM(x) ((void __iomem *)(x))
+#else
+#define IOMEM(x) x
+#endif /* __ASSEMBLY__ */
+
/*
* What hardware must be present
*/
@@ -34,7 +40,7 @@
#define IO_START 0x03000000 /* I/O */
#define IO_SIZE 0x01000000
-#define IO_BASE 0xe0000000
+#define IO_BASE IOMEM(0xe0000000)
#define SCREEN_START 0x02000000 /* VRAM */
#define SCREEN_END 0xdfc00000
@@ -46,12 +52,12 @@
/*
* IO Addresses
*/
-#define VIDC_BASE 0xe0400000
+#define VIDC_BASE (void __iomem *)0xe0400000
#define EXPMASK_BASE 0xe0360000
-#define IOMD_BASE 0xe0200000
-#define IOC_BASE 0xe0200000
-#define PCIO_BASE 0xe0010000
-#define FLOPPYDMA_BASE 0xe002a000
+#define IOMD_BASE IOMEM(0xe0200000)
+#define IOC_BASE IOMEM(0xe0200000)
+#define PCIO_BASE IOMEM(0xe0010000)
+#define FLOPPYDMA_BASE IOMEM(0xe002a000)
#define FLUSH_BASE_PHYS 0x00000000 /* ROM */
diff --git a/include/asm-arm/arch-rpc/io.h b/include/asm-arm/arch-rpc/io.h
index f53c72c204230..24453c405a87f 100644
--- a/include/asm-arm/arch-rpc/io.h
+++ b/include/asm-arm/arch-rpc/io.h
@@ -128,9 +128,9 @@ static inline void __iomem *__ioaddr(unsigned int port)
{
void __iomem *ret;
if (__PORT_PCIO(port))
- ret = (void __iomem *)PCIO_BASE;
+ ret = PCIO_BASE;
else
- ret = (void __iomem *)IO_BASE;
+ ret = IO_BASE;
return ret + (port << 2);
}
@@ -230,8 +230,8 @@ DECLARE_IO(int,l,"")
result; \
})
-#define __ioaddrc(port) \
- ((void __iomem *)(__PORT_PCIO((port)) ? PCIO_BASE : IO_BASE) + ((port) << 2))
+#define __ioaddrc(port) \
+ ((__PORT_PCIO(port) ? PCIO_BASE : IO_BASE) + ((port) << 2))
#define inb(p) (__builtin_constant_p((p)) ? __inbc(p) : __inb(p))
#define inw(p) (__builtin_constant_p((p)) ? __inwc(p) : __inw(p))
diff --git a/include/asm-arm/arch-s3c2410/debug-macro.S b/include/asm-arm/arch-s3c2410/debug-macro.S
index eab2d12ed4f41..abfbe45cd17c9 100644
--- a/include/asm-arm/arch-s3c2410/debug-macro.S
+++ b/include/asm-arm/arch-s3c2410/debug-macro.S
@@ -11,6 +11,8 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
+ * Modifications:
+ * 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA
*/
#include <asm/arch/map.h>
@@ -24,7 +26,7 @@
mrc p15, 0, \rx, c1, c0
tst \rx, #1
ldreq \rx, = S3C2410_PA_UART
- ldrne \rx, = S3C2410_VA_UART
+ ldrne \rx, = S3C24XX_VA_UART
#if CONFIG_DEBUG_S3C2410_UART != 0
add \rx, \rx, #(S3C2410_UART1_OFF * CONFIG_DEBUG_S3C2410_UART)
#endif
@@ -43,7 +45,7 @@
mrc p15, 0, \rd, c1, c0
tst \rd, #1
addeq \rd, \rx, #(S3C2410_PA_GPIO - S3C2410_PA_UART)
- addne \rd, \rx, #(S3C2410_VA_GPIO - S3C2410_VA_UART)
+ addne \rd, \rx, #(S3C24XX_VA_GPIO - S3C24XX_VA_UART)
bic \rd, \rd, #0xff000
ldr \rd, [ \rd, # S3C2410_GSTATUS1 - S3C2410_GPIOREG(0) ]
and \rd, \rd, #0x00ff0000
@@ -74,7 +76,7 @@
mrc p15, 0, \rd, c1, c0
tst \rd, #1
addeq \rd, \rx, #(S3C2410_PA_GPIO - S3C2410_PA_UART)
- addne \rd, \rx, #(S3C2410_VA_GPIO - S3C2410_VA_UART)
+ addne \rd, \rx, #(S3C24XX_VA_GPIO - S3C24XX_VA_UART)
bic \rd, \rd, #0xff000
ldr \rd, [ \rd, # S3C2410_GSTATUS1 - S3C2410_GPIOREG(0) ]
and \rd, \rd, #0x00ff0000
diff --git a/include/asm-arm/arch-s3c2410/entry-macro.S b/include/asm-arm/arch-s3c2410/entry-macro.S
index 4cc886ed1dbbe..b7d4d7f4422d9 100644
--- a/include/asm-arm/arch-s3c2410/entry-macro.S
+++ b/include/asm-arm/arch-s3c2410/entry-macro.S
@@ -6,12 +6,15 @@
* 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.
+
+ * Modifications:
+ * 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA
*/
.macro get_irqnr_and_base, irqnr, irqstat, base, tmp
- mov \tmp, #S3C2410_VA_IRQ
+ mov \tmp, #S3C24XX_VA_IRQ
ldr \irqnr, [ \tmp, #0x14 ] @ get irq no
30000:
teq \irqnr, #4
@@ -45,7 +48,7 @@
.align 4
20004:
mov r1, #1
- mov \tmp, #S3C2410_VA_IRQ
+ mov \tmp, #S3C24XX_VA_IRQ
ldmfd r13!, { r0 - r4 , r8-r12, r14 }
#endif
@@ -83,7 +86,7 @@
@ we get here from no main or external interrupts pending
1002:
- add \tmp, \tmp, #S3C2410_VA_GPIO - S3C2410_VA_IRQ
+ add \tmp, \tmp, #S3C24XX_VA_GPIO - S3C24XX_VA_IRQ
ldr \irqstat, [ \tmp, # 0xa8 ] @ EXTINTPEND
ldr \irqnr, [ \tmp, # 0xa4 ] @ EXTINTMASK
diff --git a/include/asm-arm/arch-s3c2410/hardware.h b/include/asm-arm/arch-s3c2410/hardware.h
index 7b489fde8fdf4..48a39918a7609 100644
--- a/include/asm-arm/arch-s3c2410/hardware.h
+++ b/include/asm-arm/arch-s3c2410/hardware.h
@@ -97,11 +97,7 @@ extern unsigned int s3c2410_modify_misccr(unsigned int clr, unsigned int chg);
#include <asm/sizes.h>
#include <asm/arch/map.h>
-/* machine specific includes, such as the BAST */
-
-#if defined(CONFIG_ARCH_BAST)
-#include <asm/arch/bast-cpld.h>
-#endif
+/* machine specific hardware definitions should go after this */
/* currently here until moved into config (todo) */
#define CONFIG_NO_MULTIWORD_IO
diff --git a/include/asm-arm/arch-s3c2410/io.h b/include/asm-arm/arch-s3c2410/io.h
index 291b862e3f565..418233a7ee6fb 100644
--- a/include/asm-arm/arch-s3c2410/io.h
+++ b/include/asm-arm/arch-s3c2410/io.h
@@ -8,6 +8,7 @@
* Modifications:
* 06-Dec-1997 RMK Created.
* 02-Sep-2003 BJD Modified for S3C2410
+ * 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA
*
*/
@@ -26,10 +27,10 @@
#define __PORT_PCIO(x) ((x) < (1<<28))
-#define PCIO_BASE (S3C2410_VA_ISA_WORD)
-#define PCIO_BASE_b (S3C2410_VA_ISA_BYTE)
-#define PCIO_BASE_w (S3C2410_VA_ISA_WORD)
-#define PCIO_BASE_l (S3C2410_VA_ISA_WORD)
+#define PCIO_BASE (S3C24XX_VA_ISA_WORD)
+#define PCIO_BASE_b (S3C24XX_VA_ISA_BYTE)
+#define PCIO_BASE_w (S3C24XX_VA_ISA_WORD)
+#define PCIO_BASE_l (S3C24XX_VA_ISA_WORD)
/*
* Dynamic IO functions - let the compiler
* optimize the expressions
@@ -65,9 +66,9 @@ static inline unsigned sz __in##fnsuffix (unsigned int port) \
return (unsigned sz)value; \
}
-static inline void __iomem *__ioaddr (unsigned int port)
+static inline void __iomem *__ioaddr (unsigned long port)
{
- return (void __iomem *)(__PORT_PCIO(port) ? PCIO_BASE + port : port);
+ return __PORT_PCIO(port) ? (PCIO_BASE + port) : (void __iomem *)port;
}
#define DECLARE_IO(sz,fnsuffix,instr) \
@@ -167,7 +168,7 @@ DECLARE_IO(int,l,"")
result; \
})
-#define __ioaddrc(port) ((void __iomem *)(__PORT_PCIO(port) ? PCIO_BASE + (port) : (port)))
+#define __ioaddrc(port) ((__PORT_PCIO(port) ? PCIO_BASE + (port) : (void __iomem *)(port)))
#define inb(p) (__builtin_constant_p((p)) ? __inbc(p) : __inb(p))
#define inw(p) (__builtin_constant_p((p)) ? __inwc(p) : __inw(p))
@@ -177,7 +178,7 @@ DECLARE_IO(int,l,"")
#define outl(v,p) (__builtin_constant_p((p)) ? __outlc(v,p) : __outl(v,p))
#define __ioaddr(p) (__builtin_constant_p((p)) ? __ioaddr(p) : __ioaddrc(p))
/* the following macro is deprecated */
-#define ioaddr(port) __ioaddr((port))
+#define ioaddr(port) __ioaddr((port))
#define insb(p,d,l) __raw_readsb(__ioaddr(p),d,l)
#define insw(p,d,l) __raw_readsw(__ioaddr(p),d,l)
diff --git a/include/asm-arm/arch-s3c2410/irqs.h b/include/asm-arm/arch-s3c2410/irqs.h
index 0a05189899b90..d9773d6972688 100644
--- a/include/asm-arm/arch-s3c2410/irqs.h
+++ b/include/asm-arm/arch-s3c2410/irqs.h
@@ -1,6 +1,6 @@
/* linux/include/asm-arm/arch-s3c2410/irqs.h
*
- * Copyright (c) 2003 Simtec Electronics
+ * Copyright (c) 2003-2005 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
*
* This program is free software; you can redistribute it and/or modify
@@ -11,6 +11,8 @@
* 12-May-2003 BJD Created file
* 08-Jan-2003 BJD Linux 2.6.0 version, moved BAST bits out
* 12-Mar-2004 BJD Fixed bug in header protection
+ * 10-Feb-2005 BJD Added camera IRQ from guillaume.gourat@nexvision.tv
+ * 28-Feb-2005 BJD Updated s3c2440 IRQs
*/
@@ -35,7 +37,8 @@
#define IRQ_EINT3 S3C2410_IRQ(3)
#define IRQ_EINT4t7 S3C2410_IRQ(4) /* 20 */
#define IRQ_EINT8t23 S3C2410_IRQ(5)
-#define IRQ_RESERVED6 S3C2410_IRQ(6)
+#define IRQ_RESERVED6 S3C2410_IRQ(6) /* for s3c2410 */
+#define IRQ_CAM S3C2410_IRQ(6) /* for s3c2440 */
#define IRQ_BATT_FLT S3C2410_IRQ(7)
#define IRQ_TICK S3C2410_IRQ(8) /* 24 */
#define IRQ_WDT S3C2410_IRQ(9)
@@ -54,6 +57,7 @@
#define IRQ_SPI0 S3C2410_IRQ(22)
#define IRQ_UART1 S3C2410_IRQ(23)
#define IRQ_RESERVED24 S3C2410_IRQ(24) /* 40 */
+#define IRQ_NFCON S3C2410_IRQ(24) /* for s3c2440 */
#define IRQ_USBD S3C2410_IRQ(25)
#define IRQ_USBH S3C2410_IRQ(26)
#define IRQ_IIC S3C2410_IRQ(27)
@@ -109,7 +113,14 @@
#define IRQ_TC S3C2410_IRQ(63)
#define IRQ_ADC S3C2410_IRQ(64)
-#define NR_IRQS (IRQ_ADC+1)
+/* extra irqs for s3c2440 */
+
+#define IRQ_S3C2440_CAM_C S3C2410_IRQ(65)
+#define IRQ_S3C2440_CAM_P S3C2410_IRQ(66)
+#define IRQ_S3C2440_WDT S3C2410_IRQ(67)
+#define IRQ_S3C2440_AC97 S3C2410_IRQ(68)
+
+#define NR_IRQS (IRQ_S3C2440_AC97+1)
#endif /* __ASM_ARCH_IRQ_H */
diff --git a/include/asm-arm/arch-s3c2410/map.h b/include/asm-arm/arch-s3c2410/map.h
index 4be0bf44b5a06..1833ea5c4220b 100644
--- a/include/asm-arm/arch-s3c2410/map.h
+++ b/include/asm-arm/arch-s3c2410/map.h
@@ -10,8 +10,10 @@
* published by the Free Software Foundation.
*
* Changelog:
- * 12-May-2003 BJD Created file
- * 06-Jan-2003 BJD Linux 2.6.0 version, moved bast specifics out
+ * 12-May-2003 BJD Created file
+ * 06-Jan-2003 BJD Linux 2.6.0 version, moved bast specifics out
+ * 10-Feb-2005 BJD Added CAMIF definition from guillaume.gourat@nexvision.tv
+ * 10-Mar-2005 LCVR Added support to S3C2400, changed {VA,SZ} names
*/
#ifndef __ASM_ARCH_MAP_H
@@ -28,108 +30,139 @@
* as they are only useful to certain drivers...
*/
+#ifndef __ASSEMBLY__
+#define S3C2410_ADDR(x) ((void __iomem *)0xF0000000 + (x))
+#else
#define S3C2410_ADDR(x) (0xF0000000 + (x))
+#endif
+
+#define S3C2400_ADDR(x) S3C2410_ADDR(x)
/* interrupt controller is the first thing we put in, to make
* the assembly code for the irq detection easier
*/
-#define S3C2410_VA_IRQ S3C2410_ADDR(0x00000000)
+#define S3C24XX_VA_IRQ S3C2410_ADDR(0x00000000)
+#define S3C2400_PA_IRQ (0x14400000)
#define S3C2410_PA_IRQ (0x4A000000)
-#define S3C2410_SZ_IRQ SZ_1M
+#define S3C24XX_SZ_IRQ SZ_1M
/* memory controller registers */
-#define S3C2410_VA_MEMCTRL S3C2410_ADDR(0x00100000)
+#define S3C24XX_VA_MEMCTRL S3C2410_ADDR(0x00100000)
+#define S3C2400_PA_MEMCTRL (0x14000000)
#define S3C2410_PA_MEMCTRL (0x48000000)
-#define S3C2410_SZ_MEMCTRL SZ_1M
+#define S3C24XX_SZ_MEMCTRL SZ_1M
/* USB host controller */
-#define S3C2410_VA_USBHOST S3C2410_ADDR(0x00200000)
+#define S3C24XX_VA_USBHOST S3C2410_ADDR(0x00200000)
+#define S3C2400_PA_USBHOST (0x14200000)
#define S3C2410_PA_USBHOST (0x49000000)
-#define S3C2410_SZ_USBHOST SZ_1M
+#define S3C24XX_SZ_USBHOST SZ_1M
/* DMA controller */
-#define S3C2410_VA_DMA S3C2410_ADDR(0x00300000)
+#define S3C24XX_VA_DMA S3C2410_ADDR(0x00300000)
+#define S3C2400_PA_DMA (0x14600000)
#define S3C2410_PA_DMA (0x4B000000)
-#define S3C2410_SZ_DMA SZ_1M
+#define S3C24XX_SZ_DMA SZ_1M
/* Clock and Power management */
-#define S3C2410_VA_CLKPWR S3C2410_ADDR(0x00400000)
+#define S3C24XX_VA_CLKPWR S3C2410_ADDR(0x00400000)
+#define S3C2400_PA_CLKPWR (0x14800000)
#define S3C2410_PA_CLKPWR (0x4C000000)
-#define S3C2410_SZ_CLKPWR SZ_1M
+#define S3C24XX_SZ_CLKPWR SZ_1M
/* LCD controller */
-#define S3C2410_VA_LCD S3C2410_ADDR(0x00600000)
+#define S3C24XX_VA_LCD S3C2410_ADDR(0x00600000)
+#define S3C2400_PA_LCD (0x14A00000)
#define S3C2410_PA_LCD (0x4D000000)
-#define S3C2410_SZ_LCD SZ_1M
+#define S3C24XX_SZ_LCD SZ_1M
/* NAND flash controller */
-#define S3C2410_VA_NAND S3C2410_ADDR(0x00700000)
+#define S3C24XX_VA_NAND S3C2410_ADDR(0x00700000)
#define S3C2410_PA_NAND (0x4E000000)
-#define S3C2410_SZ_NAND SZ_1M
+#define S3C24XX_SZ_NAND SZ_1M
+
+/* MMC controller - available on the S3C2400 */
+#define S3C2400_VA_MMC S3C2400_ADDR(0x00700000)
+#define S3C2400_PA_MMC (0x15A00000)
+#define S3C2400_SZ_MMC SZ_1M
/* UARTs */
-#define S3C2410_VA_UART S3C2410_ADDR(0x00800000)
+#define S3C24XX_VA_UART S3C2410_ADDR(0x00800000)
+#define S3C2400_PA_UART (0x15000000)
#define S3C2410_PA_UART (0x50000000)
-#define S3C2410_SZ_UART SZ_1M
+#define S3C24XX_SZ_UART SZ_1M
/* Timers */
-#define S3C2410_VA_TIMER S3C2410_ADDR(0x00900000)
+#define S3C24XX_VA_TIMER S3C2410_ADDR(0x00900000)
+#define S3C2400_PA_TIMER (0x15100000)
#define S3C2410_PA_TIMER (0x51000000)
-#define S3C2410_SZ_TIMER SZ_1M
+#define S3C24XX_SZ_TIMER SZ_1M
/* USB Device port */
-#define S3C2410_VA_USBDEV S3C2410_ADDR(0x00A00000)
+#define S3C24XX_VA_USBDEV S3C2410_ADDR(0x00A00000)
+#define S3C2400_PA_USBDEV (0x15200140)
#define S3C2410_PA_USBDEV (0x52000000)
-#define S3C2410_SZ_USBDEV SZ_1M
+#define S3C24XX_SZ_USBDEV SZ_1M
/* Watchdog */
-#define S3C2410_VA_WATCHDOG S3C2410_ADDR(0x00B00000)
+#define S3C24XX_VA_WATCHDOG S3C2410_ADDR(0x00B00000)
+#define S3C2400_PA_WATCHDOG (0x15300000)
#define S3C2410_PA_WATCHDOG (0x53000000)
-#define S3C2410_SZ_WATCHDOG SZ_1M
+#define S3C24XX_SZ_WATCHDOG SZ_1M
/* IIC hardware controller */
-#define S3C2410_VA_IIC S3C2410_ADDR(0x00C00000)
+#define S3C24XX_VA_IIC S3C2410_ADDR(0x00C00000)
+#define S3C2400_PA_IIC (0x15400000)
#define S3C2410_PA_IIC (0x54000000)
-#define S3C2410_SZ_IIC SZ_1M
+#define S3C24XX_SZ_IIC SZ_1M
-#define VA_IIC_BASE (S3C2410_VA_IIC)
+#define VA_IIC_BASE (S3C24XX_VA_IIC)
/* IIS controller */
-#define S3C2410_VA_IIS S3C2410_ADDR(0x00D00000)
+#define S3C24XX_VA_IIS S3C2410_ADDR(0x00D00000)
+#define S3C2400_PA_IIS (0x15508000)
#define S3C2410_PA_IIS (0x55000000)
-#define S3C2410_SZ_IIS SZ_1M
+#define S3C24XX_SZ_IIS SZ_1M
/* GPIO ports */
-#define S3C2410_VA_GPIO S3C2410_ADDR(0x00E00000)
+#define S3C24XX_VA_GPIO S3C2410_ADDR(0x00E00000)
+#define S3C2400_PA_GPIO (0x15600000)
#define S3C2410_PA_GPIO (0x56000000)
-#define S3C2410_SZ_GPIO SZ_1M
+#define S3C24XX_SZ_GPIO SZ_1M
/* RTC */
-#define S3C2410_VA_RTC S3C2410_ADDR(0x00F00000)
+#define S3C24XX_VA_RTC S3C2410_ADDR(0x00F00000)
+#define S3C2400_PA_RTC (0x15700040)
#define S3C2410_PA_RTC (0x57000000)
-#define S3C2410_SZ_RTC SZ_1M
+#define S3C24XX_SZ_RTC SZ_1M
/* ADC */
-#define S3C2410_VA_ADC S3C2410_ADDR(0x01000000)
+#define S3C24XX_VA_ADC S3C2410_ADDR(0x01000000)
+#define S3C2400_PA_ADC (0x15800000)
#define S3C2410_PA_ADC (0x58000000)
-#define S3C2410_SZ_ADC SZ_1M
+#define S3C24XX_SZ_ADC SZ_1M
/* SPI */
-#define S3C2410_VA_SPI S3C2410_ADDR(0x01100000)
+#define S3C24XX_VA_SPI S3C2410_ADDR(0x01100000)
+#define S3C2400_PA_SPI (0x15900000)
#define S3C2410_PA_SPI (0x59000000)
-#define S3C2410_SZ_SPI SZ_1M
+#define S3C24XX_SZ_SPI SZ_1M
/* SDI */
-#define S3C2410_VA_SDI S3C2410_ADDR(0x01200000)
+#define S3C24XX_VA_SDI S3C2410_ADDR(0x01200000)
#define S3C2410_PA_SDI (0x5A000000)
-#define S3C2410_SZ_SDI SZ_1M
+#define S3C24XX_SZ_SDI SZ_1M
+
+/* CAMIF */
+#define S3C2440_PA_CAMIF (0x4F000000)
+#define S3C2440_SZ_CAMIF SZ_1M
/* ISA style IO, for each machine to sort out mappings for, if it
* implements it. We reserve two 16M regions for ISA.
*/
-#define S3C2410_VA_ISA_WORD S3C2410_ADDR(0x02000000)
-#define S3C2410_VA_ISA_BYTE S3C2410_ADDR(0x03000000)
+#define S3C24XX_VA_ISA_WORD S3C2410_ADDR(0x02000000)
+#define S3C24XX_VA_ISA_BYTE S3C2410_ADDR(0x03000000)
/* physical addresses of all the chip-select areas */
@@ -144,5 +177,16 @@
#define S3C2410_SDRAM_PA (S3C2410_CS6)
+#define S3C2400_CS0 (0x00000000)
+#define S3C2400_CS1 (0x02000000)
+#define S3C2400_CS2 (0x04000000)
+#define S3C2400_CS3 (0x06000000)
+#define S3C2400_CS4 (0x08000000)
+#define S3C2400_CS5 (0x0A000000)
+#define S3C2400_CS6 (0x0C000000)
+#define S3C2400_CS7 (0x0E000000)
+
+#define S3C2400_SDRAM_PA (S3C2400_CS6)
+
#endif /* __ASM_ARCH_MAP_H */
diff --git a/include/asm-arm/arch-s3c2410/memory.h b/include/asm-arm/arch-s3c2410/memory.h
index 5321b97468f85..3380ab1d07494 100644
--- a/include/asm-arm/arch-s3c2410/memory.h
+++ b/include/asm-arm/arch-s3c2410/memory.h
@@ -17,15 +17,21 @@
* 21-Mar-1999 RMK Renamed to memory.h
* RMK Added TASK_SIZE and PAGE_OFFSET
* 05-Apr-2004 BJD Copied and altered for arch-s3c2410
+ * 17-Mar-2005 LCVR Modified for S3C2400
*/
#ifndef __ASM_ARCH_MEMORY_H
#define __ASM_ARCH_MEMORY_H
/*
- * DRAM starts at 0x30000000
+ * DRAM starts at 0x30000000 for S3C2410/S3C2440
+ * and at 0x0C000000 for S3C2400
*/
+#ifdef CONFIG_CPU_S3C2400
+#define PHYS_OFFSET (0x0C000000UL)
+#else
#define PHYS_OFFSET (0x30000000UL)
+#endif
/*
* These are exactly the same on the S3C2410 as the
diff --git a/include/asm-arm/arch-s3c2410/otom-map.h b/include/asm-arm/arch-s3c2410/otom-map.h
new file mode 100644
index 0000000000000..e40c934298542
--- /dev/null
+++ b/include/asm-arm/arch-s3c2410/otom-map.h
@@ -0,0 +1,30 @@
+/* linux/include/asm-arm/arch-s3c2410/otom-map.h
+ *
+ * (c) 2005 Guillaume GOURAT / NexVision
+ * guillaume.gourat@nexvision.fr
+ *
+ * NexVision OTOM board memory map definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+/* needs arch/map.h including with this */
+
+/* ok, we've used up to 0x01300000, now we need to find space for the
+ * peripherals that live in the nGCS[x] areas, which are quite numerous
+ * in their space.
+ */
+
+#ifndef __ASM_ARCH_OTOMMAP_H
+#define __ASM_ARCH_OTOMMAP_H
+
+#define OTOM_PA_CS8900A_BASE (S3C2410_CS3 + 0x01000000) /* nGCS3 +0x01000000 */
+#define OTOM_VA_CS8900A_BASE S3C2410_ADDR(0x04000000) /* 0xF4000000 */
+
+/* physical offset addresses for the peripherals */
+
+#define OTOM_PA_FLASH0_BASE (S3C2410_CS0) /* Bank 0 */
+
+#endif /* __ASM_ARCH_OTOMMAP_H */
diff --git a/include/asm-arm/arch-s3c2410/regs-adc.h b/include/asm-arm/arch-s3c2410/regs-adc.h
new file mode 100644
index 0000000000000..15bfc2f5754e5
--- /dev/null
+++ b/include/asm-arm/arch-s3c2410/regs-adc.h
@@ -0,0 +1,63 @@
+/* linux/include/asm/arch-s3c2410/regs-adc.h
+ *
+ * Copyright (c) 2004 Shannon Holland <holland@loser.net>
+ *
+ * This program is free software; yosu 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.
+ *
+ * S3C2410 ADC registers
+ *
+ * Changelog:
+ * 27-09-2004 SAH Created file
+*/
+
+#ifndef __ASM_ARCH_REGS_ADC_H
+#define __ASM_ARCH_REGS_ADC_H "regs-adc.h"
+
+#define S3C2410_ADCREG(x) (x)
+
+#define S3C2410_ADCCON S3C2410_ADCREG(0x00)
+#define S3C2410_ADCTSC S3C2410_ADCREG(0x04)
+#define S3C2410_ADCDLY S3C2410_ADCREG(0x08)
+#define S3C2410_ADCDAT0 S3C2410_ADCREG(0x0C)
+#define S3C2410_ADCDAT1 S3C2410_ADCREG(0x10)
+
+
+/* ADCCON Register Bits */
+#define S3C2410_ADCCON_ECFLG (1<<15)
+#define S3C2410_ADCCON_PRSCEN (1<<14)
+#define S3C2410_ADCCON_PRSCVL(x) (((x)&0xFF)<<6)
+#define S3C2410_ADCCON_PRSCVLMASK (0xFF<<6)
+#define S3C2410_ADCCON_SELMUX(x) (((x)&0x7)<<3)
+#define S3C2410_ADCCON_MUXMASK (0x7<<3)
+#define S3C2410_ADCCON_STDBM (1<<2)
+#define S3C2410_ADCCON_READ_START (1<<1)
+#define S3C2410_ADCCON_ENABLE_START (1<<0)
+#define S3C2410_ADCCON_STARTMASK (0x3<<0)
+
+
+/* ADCTSC Register Bits */
+#define S3C2410_ADCTSC_YM_SEN (1<<7)
+#define S3C2410_ADCTSC_YP_SEN (1<<6)
+#define S3C2410_ADCTSC_XM_SEN (1<<5)
+#define S3C2410_ADCTSC_XP_SEN (1<<4)
+#define S3C2410_ADCTSC_PULL_UP_DISABLE (1<<3)
+#define S3C2410_ADCTSC_AUTO_PST (1<<2)
+#define S3C2410_ADCTSC_XY_PST (0x3<<0)
+
+/* ADCDAT0 Bits */
+#define S3C2410_ADCDAT0_UPDOWN (1<<15)
+#define S3C2410_ADCDAT0_AUTO_PST (1<<14)
+#define S3C2410_ADCDAT0_XY_PST (0x3<<12)
+#define S3C2410_ADCDAT0_XPDATA_MASK (0x03FF)
+
+/* ADCDAT1 Bits */
+#define S3C2410_ADCDAT1_UPDOWN (1<<15)
+#define S3C2410_ADCDAT1_AUTO_PST (1<<14)
+#define S3C2410_ADCDAT1_XY_PST (0x3<<12)
+#define S3C2410_ADCDAT1_YPDATA_MASK (0x03FF)
+
+#endif /* __ASM_ARCH_REGS_ADC_H */
+
+
diff --git a/include/asm-arm/arch-s3c2410/regs-clock.h b/include/asm-arm/arch-s3c2410/regs-clock.h
index a6281f464d813..e5e938b79accf 100644
--- a/include/asm-arm/arch-s3c2410/regs-clock.h
+++ b/include/asm-arm/arch-s3c2410/regs-clock.h
@@ -10,18 +10,19 @@
* S3C2410 clock register definitions
*
* Changelog:
- * 18-Aug-2004 Ben Dooks Added 2440 definitions
- * 08-Aug-2004 Herbert Pötzl Added CLKCON definitions
- * 19-06-2003 Ben Dooks Created file
- * 12-03-2004 Ben Dooks Updated include protection
- * 29-Sep-2004 Ben Dooks Fixed usage for assembly inclusion
- * 10-Feb-2005 Ben Dooks Fixed CAMDIVN address (Guillaume Gourat)
+ * 18-Aug-2004 Ben Dooks Added 2440 definitions
+ * 08-Aug-2004 Herbert Pötzl Added CLKCON definitions
+ * 19-06-2003 Ben Dooks Created file
+ * 12-03-2004 Ben Dooks Updated include protection
+ * 29-Sep-2004 Ben Dooks Fixed usage for assembly inclusion
+ * 10-Feb-2005 Ben Dooks Fixed CAMDIVN address (Guillaume Gourat)
+ * 10-Mar-2005 Lucas Villa Real Changed S3C2410_VA to S3C24XX_VA
*/
#ifndef __ASM_ARM_REGS_CLOCK
#define __ASM_ARM_REGS_CLOCK "$Id: clock.h,v 1.4 2003/04/30 14:50:51 ben Exp $"
-#define S3C2410_CLKREG(x) ((x) + S3C2410_VA_CLKPWR)
+#define S3C2410_CLKREG(x) ((x) + S3C24XX_VA_CLKPWR)
#define S3C2410_PLLVAL(_m,_p,_s) ((_m) << 12 | ((_p) << 4) | ((_s)))
diff --git a/include/asm-arm/arch-s3c2410/regs-gpio.h b/include/asm-arm/arch-s3c2410/regs-gpio.h
index 07c17f95a92b8..2053cbacffc3d 100644
--- a/include/asm-arm/arch-s3c2410/regs-gpio.h
+++ b/include/asm-arm/arch-s3c2410/regs-gpio.h
@@ -18,6 +18,8 @@
* 17-10-2004 BJD Added GSTATUS1 register definitions
* 18-11-2004 BJD Fixed definitions of GPE3, GPE4, GPE5 and GPE6
* 18-11-2004 BJD Added S3C2440 AC97 controls
+ * 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA
+ * 28-Mar-2005 LCVR Fixed definition of GPB10
*/
@@ -35,7 +37,7 @@
#define S3C2410_GPIO_BANKG (32*6)
#define S3C2410_GPIO_BANKH (32*7)
-#define S3C2410_GPIO_BASE(pin) ((((pin) & ~31) >> 1) + S3C2410_VA_GPIO)
+#define S3C2410_GPIO_BASE(pin) ((((pin) & ~31) >> 1) + S3C24XX_VA_GPIO)
#define S3C2410_GPIO_OFFSET(pin) ((pin) & 31)
/* general configuration options */
@@ -44,7 +46,7 @@
/* configure GPIO ports A..G */
-#define S3C2410_GPIOREG(x) ((x) + S3C2410_VA_GPIO)
+#define S3C2410_GPIOREG(x) ((x) + S3C24XX_VA_GPIO)
/* port A - 22bits, zero in bit X makes pin X output
* 1 makes port special function, this is default
@@ -211,9 +213,9 @@
#define S3C2410_GPB9_nXDACK0 (0x02 << 18)
#define S3C2410_GPB10 S3C2410_GPIONO(S3C2410_GPIO_BANKB, 10)
-#define S3C2410_GPB10_INP (0x00 << 18)
-#define S3C2410_GPB10_OUTP (0x01 << 18)
-#define S3C2410_GPB10_nXDRE0 (0x02 << 18)
+#define S3C2410_GPB10_INP (0x00 << 20)
+#define S3C2410_GPB10_OUTP (0x01 << 20)
+#define S3C2410_GPB10_nXDRE0 (0x02 << 20)
/* Port C consits of 16 GPIO/Special function
*
diff --git a/include/asm-arm/arch-s3c2410/regs-iis.h b/include/asm-arm/arch-s3c2410/regs-iis.h
index a3fde605f5c82..7ae8e1f45bc17 100644
--- a/include/asm-arm/arch-s3c2410/regs-iis.h
+++ b/include/asm-arm/arch-s3c2410/regs-iis.h
@@ -13,6 +13,7 @@
* 19-06-2003 BJD Created file
* 26-06-2003 BJD Finished off definitions for register addresses
* 12-03-2004 BJD Updated include protection
+ * 07-03-2005 BJD Added FIFO size flags and S3C2440 MPLL
*/
#ifndef __ASM_ARCH_REGS_IIS_H
@@ -20,6 +21,7 @@
#define S3C2410_IISCON (0x00)
+#define S3C2440_IISCON_MPLL (1<<9)
#define S3C2410_IISCON_LRINDEX (1<<8)
#define S3C2410_IISCON_TXFIFORDY (1<<7)
#define S3C2410_IISCON_RXFIFORDY (1<<6)
@@ -42,6 +44,7 @@
#define S3C2410_IISMOD_MSB (1<<4)
#define S3C2410_IISMOD_8BIT (0<<3)
#define S3C2410_IISMOD_16BIT (1<<3)
+#define S3C2410_IISMOD_BITMASK (1<<3)
#define S3C2410_IISMOD_256FS (0<<1)
#define S3C2410_IISMOD_384FS (1<<1)
#define S3C2410_IISMOD_16FS (0<<0)
@@ -50,7 +53,7 @@
#define S3C2410_IISPSR (0x08)
#define S3C2410_IISPSR_INTMASK (31<<5)
-#define S3C2410_IISPSR_INTSHFIT (5)
+#define S3C2410_IISPSR_INTSHIFT (5)
#define S3C2410_IISPSR_EXTMASK (31<<0)
#define S3C2410_IISPSR_EXTSHFIT (0)
@@ -60,8 +63,10 @@
#define S3C2410_IISFCON_RXDMA (1<<14)
#define S3C2410_IISFCON_TXENABLE (1<<13)
#define S3C2410_IISFCON_RXENABLE (1<<12)
+#define S3C2410_IISFCON_TXMASK (0x3f << 6)
+#define S3C2410_IISFCON_TXSHIFT (6)
+#define S3C2410_IISFCON_RXMASK (0x3f)
+#define S3C2410_IISFCON_RXSHIFT (0)
#define S3C2410_IISFIFO (0x10)
-
#endif /* __ASM_ARCH_REGS_IIS_H */
-
diff --git a/include/asm-arm/arch-s3c2410/regs-irq.h b/include/asm-arm/arch-s3c2410/regs-irq.h
index 87edb61ede098..24b7292df79e2 100644
--- a/include/asm-arm/arch-s3c2410/regs-irq.h
+++ b/include/asm-arm/arch-s3c2410/regs-irq.h
@@ -12,6 +12,7 @@
* Changelog:
* 19-06-2003 BJD Created file
* 12-03-2004 BJD Updated include protection
+ * 10-03-2005 LCVR Changed S3C2410_VA to S3C24XX_VA
*/
@@ -20,8 +21,8 @@
/* interrupt controller */
-#define S3C2410_IRQREG(x) ((x) + S3C2410_VA_IRQ)
-#define S3C2410_EINTREG(x) ((x) + S3C2410_VA_GPIO)
+#define S3C2410_IRQREG(x) ((x) + S3C24XX_VA_IRQ)
+#define S3C2410_EINTREG(x) ((x) + S3C24XX_VA_GPIO)
#define S3C2410_SRCPND S3C2410_IRQREG(0x000)
#define S3C2410_INTMOD S3C2410_IRQREG(0x004)
diff --git a/include/asm-arm/arch-s3c2410/regs-lcd.h b/include/asm-arm/arch-s3c2410/regs-lcd.h
index eda2a7b9bf16f..7f882ea92b2a7 100644
--- a/include/asm-arm/arch-s3c2410/regs-lcd.h
+++ b/include/asm-arm/arch-s3c2410/regs-lcd.h
@@ -13,13 +13,14 @@
* 12-06-2003 BJD Created file
* 26-06-2003 BJD Updated LCDCON register definitions
* 12-03-2004 BJD Updated include protection
+ * 10-03-2005 LCVR Changed S3C2410_VA to S3C24XX_VA
*/
#ifndef ___ASM_ARCH_REGS_LCD_H
#define ___ASM_ARCH_REGS_LCD_H "$Id: lcd.h,v 1.3 2003/06/26 13:25:06 ben Exp $"
-#define S3C2410_LCDREG(x) ((x) + S3C2410_VA_LCD)
+#define S3C2410_LCDREG(x) ((x) + S3C24XX_VA_LCD)
/* LCD control registers */
#define S3C2410_LCDCON1 S3C2410_LCDREG(0x00)
diff --git a/include/asm-arm/arch-s3c2410/regs-mem.h b/include/asm-arm/arch-s3c2410/regs-mem.h
index 400fbd77d605b..1a1328ac0d79b 100644
--- a/include/asm-arm/arch-s3c2410/regs-mem.h
+++ b/include/asm-arm/arch-s3c2410/regs-mem.h
@@ -11,6 +11,7 @@
*
* Changelog:
* 29-Sep-2004 BJD Initial include for Linux
+ * 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA
*
*/
@@ -18,7 +19,7 @@
#define __ASM_ARM_MEMREGS_H "$Id: regs.h,v 1.8 2003/05/01 15:55:41 ben Exp $"
#ifndef S3C2410_MEMREG
-#define S3C2410_MEMREG(x) (S3C2410_VA_MEMCTRL + (x))
+#define S3C2410_MEMREG(x) (S3C24XX_VA_MEMCTRL + (x))
#endif
/* bus width, and wait state control */
@@ -133,8 +134,29 @@
#define S3C2410_BANKCON_Tacs4 (0x3 << 13)
#define S3C2410_BANKCON_SRAM (0x0 << 15)
+#define S3C2400_BANKCON_EDODRAM (0x2 << 15)
#define S3C2410_BANKCON_SDRAM (0x3 << 15)
+/* next bits only for EDO DRAM in 6,7 */
+#define S3C2400_BANKCON_EDO_Trdc1 (0x00 << 4)
+#define S3C2400_BANKCON_EDO_Trdc2 (0x01 << 4)
+#define S3C2400_BANKCON_EDO_Trdc3 (0x02 << 4)
+#define S3C2400_BANKCON_EDO_Trdc4 (0x03 << 4)
+
+/* CAS pulse width */
+#define S3C2400_BANKCON_EDO_PULSE1 (0x00 << 3)
+#define S3C2400_BANKCON_EDO_PULSE2 (0x01 << 3)
+
+/* CAS pre-charge */
+#define S3C2400_BANKCON_EDO_TCP1 (0x00 << 2)
+#define S3C2400_BANKCON_EDO_TCP2 (0x01 << 2)
+
+/* control column address select */
+#define S3C2400_BANKCON_EDO_SCANb8 (0x00 << 0)
+#define S3C2400_BANKCON_EDO_SCANb9 (0x01 << 0)
+#define S3C2400_BANKCON_EDO_SCANb10 (0x02 << 0)
+#define S3C2400_BANKCON_EDO_SCANb11 (0x03 << 0)
+
/* next bits only for SDRAM in 6,7 */
#define S3C2410_BANKCON_Trdc2 (0x00 << 2)
#define S3C2410_BANKCON_Trdc3 (0x01 << 2)
diff --git a/include/asm-arm/arch-s3c2410/regs-rtc.h b/include/asm-arm/arch-s3c2410/regs-rtc.h
index 408cf04266e89..228983f89bc87 100644
--- a/include/asm-arm/arch-s3c2410/regs-rtc.h
+++ b/include/asm-arm/arch-s3c2410/regs-rtc.h
@@ -12,12 +12,13 @@
* Changelog:
* 19-06-2003 BJD Created file
* 12-03-2004 BJD Updated include protection
+ * 15-01-2005 LCVR Changed S3C2410_VA to S3C24XX_VA (s3c2400 support)
*/
#ifndef __ASM_ARCH_REGS_RTC_H
#define __ASM_ARCH_REGS_RTC_H __FILE__
-#define S3C2410_RTCREG(x) ((x) + S3C2410_VA_RTC)
+#define S3C2410_RTCREG(x) ((x) + S3C24XX_VA_RTC)
#define S3C2410_RTCCON S3C2410_RTCREG(0x40)
#define S3C2410_RTCCON_RTCEN (1<<0)
diff --git a/include/asm-arm/arch-s3c2410/regs-serial.h b/include/asm-arm/arch-s3c2410/regs-serial.h
index 33a4842f64cfa..ce1bbbaad6d36 100644
--- a/include/asm-arm/arch-s3c2410/regs-serial.h
+++ b/include/asm-arm/arch-s3c2410/regs-serial.h
@@ -27,14 +27,17 @@
* You should have received a copy of the 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
+ *
+ * Modifications:
+ * 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA (s3c2400 support)
*/
#ifndef __ASM_ARM_REGS_SERIAL_H
#define __ASM_ARM_REGS_SERIAL_H
-#define S3C2410_VA_UART0 (S3C2410_VA_UART)
-#define S3C2410_VA_UART1 (S3C2410_VA_UART + 0x4000 )
-#define S3C2410_VA_UART2 (S3C2410_VA_UART + 0x8000 )
+#define S3C24XX_VA_UART0 (S3C24XX_VA_UART)
+#define S3C24XX_VA_UART1 (S3C24XX_VA_UART + 0x4000 )
+#define S3C24XX_VA_UART2 (S3C24XX_VA_UART + 0x8000 )
#define S3C2410_PA_UART0 (S3C2410_PA_UART)
#define S3C2410_PA_UART1 (S3C2410_PA_UART + 0x4000 )
@@ -73,6 +76,11 @@
#define S3C2440_UCON_UCLK (1<<10)
#define S3C2440_UCON_PCLK2 (2<<10)
#define S3C2440_UCON_FCLK (3<<10)
+#define S3C2440_UCON2_FCLK_EN (1<<15)
+#define S3C2440_UCON0_DIVMASK (15 << 12)
+#define S3C2440_UCON1_DIVMASK (15 << 12)
+#define S3C2440_UCON2_DIVMASK (7 << 12)
+#define S3C2440_UCON_DIVSHIFT (12)
#define S3C2410_UCON_UCLK (1<<10)
#define S3C2410_UCON_SBREAK (1<<4)
diff --git a/include/asm-arm/arch-s3c2410/regs-timer.h b/include/asm-arm/arch-s3c2410/regs-timer.h
index b5b4aaf3dbf9d..169064e275203 100644
--- a/include/asm-arm/arch-s3c2410/regs-timer.h
+++ b/include/asm-arm/arch-s3c2410/regs-timer.h
@@ -13,13 +13,15 @@
* 05-06-2003 BJD Created file
* 26-06-2003 BJD Added more timer definitions to mux / control
* 12-03-2004 BJD Updated include protection
+ * 10-02-2005 BJD Added S3C2410_TCFG1_MUX4_SHIFT (Guillaume Gourat)
+ * 10-03-2005 LCVR Changed S3C2410_VA to S3C24XX_VA
*/
#ifndef __ASM_ARCH_REGS_TIMER_H
#define __ASM_ARCH_REGS_TIMER_H "$Id: timer.h,v 1.4 2003/05/06 19:30:50 ben Exp $"
-#define S3C2410_TIMERREG(x) (S3C2410_VA_TIMER + (x))
+#define S3C2410_TIMERREG(x) (S3C24XX_VA_TIMER + (x))
#define S3C2410_TIMERREG2(tmr,reg) S3C2410_TIMERREG((reg)+0x0c+((tmr)*0x0c))
#define S3C2410_TCFG0 S3C2410_TIMERREG(0x00)
@@ -38,6 +40,7 @@
#define S3C2410_TCFG1_MUX4_DIV16 (3<<16)
#define S3C2410_TCFG1_MUX4_TCLK1 (4<<16)
#define S3C2410_TCFG1_MUX4_MASK (15<<16)
+#define S3C2410_TCFG1_MUX4_SHIFT (16)
#define S3C2410_TCFG1_MUX3_DIV2 (0<<12)
#define S3C2410_TCFG1_MUX3_DIV4 (1<<12)
diff --git a/include/asm-arm/arch-s3c2410/regs-udc.h b/include/asm-arm/arch-s3c2410/regs-udc.h
index ad550bbf7285f..bf315b763252d 100644
--- a/include/asm-arm/arch-s3c2410/regs-udc.h
+++ b/include/asm-arm/arch-s3c2410/regs-udc.h
@@ -11,13 +11,14 @@
* 01-08-2004 Initial creation
* 12-09-2004 Cleanup for submission
* 24-10-2004 Fixed S3C2410_UDC_MAXP_REG definition
+ * 10-03-2005 Changed S3C2410_VA to S3C24XX_VA
*/
#ifndef __ASM_ARCH_REGS_UDC_H
#define __ASM_ARCH_REGS_UDC_H
-#define S3C2410_USBDREG(x) ((x) + S3C2410_VA_USBDEV)
+#define S3C2410_USBDREG(x) ((x) + S3C24XX_VA_USBDEV)
#define S3C2410_UDC_FUNC_ADDR_REG S3C2410_USBDREG(0x0140)
#define S3C2410_UDC_PWR_REG S3C2410_USBDREG(0x0144)
diff --git a/include/asm-arm/arch-s3c2410/regs-watchdog.h b/include/asm-arm/arch-s3c2410/regs-watchdog.h
index b09d5107a1eb1..d199ca6aff22b 100644
--- a/include/asm-arm/arch-s3c2410/regs-watchdog.h
+++ b/include/asm-arm/arch-s3c2410/regs-watchdog.h
@@ -12,13 +12,14 @@
* Changelog:
* 21-06-2003 BJD Created file
* 12-03-2004 BJD Updated include protection
+ * 10-03-2005 LCVR Changed S3C2410_VA to S3C24XX_VA
*/
#ifndef __ASM_ARCH_REGS_WATCHDOG_H
#define __ASM_ARCH_REGS_WATCHDOG_H "$Id: watchdog.h,v 1.2 2003/04/29 13:31:09 ben Exp $"
-#define S3C2410_WDOGREG(x) ((x) + S3C2410_VA_WATCHDOG)
+#define S3C2410_WDOGREG(x) ((x) + S3C24XX_VA_WATCHDOG)
#define S3C2410_WTCON S3C2410_WDOGREG(0x00)
#define S3C2410_WTDAT S3C2410_WDOGREG(0x04)
diff --git a/include/asm-arm/arch-s3c2410/system.h b/include/asm-arm/arch-s3c2410/system.h
index 2760cf5547b17..9b0d85024cb43 100644
--- a/include/asm-arm/arch-s3c2410/system.h
+++ b/include/asm-arm/arch-s3c2410/system.h
@@ -30,7 +30,7 @@ void (*s3c24xx_idle)(void);
void s3c24xx_default_idle(void)
{
- unsigned long reg = S3C2410_CLKCON;
+ void __iomem *reg = S3C2410_CLKCON;
unsigned long tmp;
int i;
diff --git a/include/asm-arm/arch-s3c2410/uncompress.h b/include/asm-arm/arch-s3c2410/uncompress.h
index fa240af7f591c..ad4252e27799b 100644
--- a/include/asm-arm/arch-s3c2410/uncompress.h
+++ b/include/asm-arm/arch-s3c2410/uncompress.h
@@ -15,6 +15,7 @@
* 12-Mar-2004 BJD Updated header protection
* 12-Oct-2004 BJD Take account of debug uart configuration
* 15-Nov-2004 BJD Fixed uart configuration
+ * 22-Feb-2005 BJD Added watchdog to uncompress
*/
#ifndef __ASM_ARCH_UNCOMPRESS_H
@@ -25,12 +26,16 @@
/* defines for UART registers */
#include "asm/arch/regs-serial.h"
#include "asm/arch/regs-gpio.h"
+#include "asm/arch/regs-watchdog.h"
#include <asm/arch/map.h>
/* working in physical space... */
#undef S3C2410_GPIOREG
+#undef S3C2410_WDOGREG
+
#define S3C2410_GPIOREG(x) ((S3C2410_PA_GPIO + (x)))
+#define S3C2410_WDOGREG(x) ((S3C2410_PA_WATCHDOG + (x)))
/* how many bytes we allow into the FIFO at a time in FIFO mode */
#define FIFO_MAX (14)
@@ -56,21 +61,6 @@ uart_rd(unsigned int reg)
}
-/* currently we do not need the watchdog... */
-#define arch_decomp_wdog()
-
-
-static void error(char *err);
-
-static void
-arch_decomp_setup(void)
-{
- /* we may need to setup the uart(s) here if we are not running
- * on an BAST... the BAST will have left the uarts configured
- * after calling linux.
- */
-}
-
/* we can deal with the case the UARTs are being run
* in FIFO mode, so that we don't hold up our execution
* waiting for tx to happen...
@@ -122,4 +112,47 @@ putstr(const char *ptr)
}
}
+/* CONFIG_S3C2410_BOOT_WATCHDOG
+ *
+ * Simple boot-time watchdog setup, to reboot the system if there is
+ * any problem with the boot process
+*/
+
+#ifdef CONFIG_S3C2410_BOOT_WATCHDOG
+
+#define WDOG_COUNT (0xff00)
+
+#define __raw_writel(d,ad) do { *((volatile unsigned int *)(ad)) = (d); } while(0)
+
+static inline void arch_decomp_wdog(void)
+{
+ __raw_writel(WDOG_COUNT, S3C2410_WTCNT);
+}
+
+static void arch_decomp_wdog_start(void)
+{
+ __raw_writel(WDOG_COUNT, S3C2410_WTDAT);
+ __raw_writel(WDOG_COUNT, S3C2410_WTCNT);
+ __raw_writel(S3C2410_WTCON_ENABLE | S3C2410_WTCON_DIV128 | S3C2410_WTCON_RSTEN | S3C2410_WTCON_PRESCALE(0x40), S3C2410_WTCON);
+}
+
+#else
+#define arch_decomp_wdog_start()
+#define arch_decomp_wdog()
+#endif
+
+static void error(char *err);
+
+static void
+arch_decomp_setup(void)
+{
+ /* we may need to setup the uart(s) here if we are not running
+ * on an BAST... the BAST will have left the uarts configured
+ * after calling linux.
+ */
+
+ arch_decomp_wdog_start();
+}
+
+
#endif /* __ASM_ARCH_UNCOMPRESS_H */
diff --git a/include/asm-arm/atomic.h b/include/asm-arm/atomic.h
index dc96af6e9caab..2885972b0855c 100644
--- a/include/asm-arm/atomic.h
+++ b/include/asm-arm/atomic.h
@@ -151,6 +151,7 @@ static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr)
#define atomic_dec_and_test(v) (atomic_sub_return(1, v) == 0)
#define atomic_inc_return(v) (atomic_add_return(1, v))
#define atomic_dec_return(v) (atomic_sub_return(1, v))
+#define atomic_sub_and_test(i, v) (atomic_sub_return(i, v) == 0)
#define atomic_add_negative(i,v) (atomic_add_return(i, v) < 0)
diff --git a/include/asm-arm/cacheflush.h b/include/asm-arm/cacheflush.h
index d38a1cadf0b79..09ffeed507c20 100644
--- a/include/asm-arm/cacheflush.h
+++ b/include/asm-arm/cacheflush.h
@@ -237,16 +237,16 @@ extern void dmac_flush_range(unsigned long, unsigned long);
* space" model to handle this.
*/
#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
- do { \
- flush_cache_page(vma, vaddr); \
- memcpy(dst, src, len); \
- flush_dcache_page(page); \
+ do { \
+ flush_cache_page(vma, vaddr, page_to_pfn(page));\
+ memcpy(dst, src, len); \
+ flush_dcache_page(page); \
} while (0)
#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
- do { \
- flush_cache_page(vma, vaddr); \
- memcpy(dst, src, len); \
+ do { \
+ flush_cache_page(vma, vaddr, page_to_pfn(page));\
+ memcpy(dst, src, len); \
} while (0)
/*
@@ -269,7 +269,7 @@ flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long
}
static inline void
-flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr)
+flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr, unsigned long pfn)
{
if (cpu_isset(smp_processor_id(), vma->vm_mm->cpu_vm_mask)) {
unsigned long addr = user_addr & PAGE_MASK;
@@ -312,9 +312,9 @@ flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr)
extern void flush_dcache_page(struct page *);
#define flush_dcache_mmap_lock(mapping) \
- spin_lock_irq(&(mapping)->tree_lock)
+ write_lock_irq(&(mapping)->tree_lock)
#define flush_dcache_mmap_unlock(mapping) \
- spin_unlock_irq(&(mapping)->tree_lock)
+ write_unlock_irq(&(mapping)->tree_lock)
#define flush_icache_user_range(vma,page,addr,len) \
flush_dcache_page(page)
diff --git a/include/asm-arm/ecard.h b/include/asm-arm/ecard.h
index 358799f28df00..a0ae2b954d291 100644
--- a/include/asm-arm/ecard.h
+++ b/include/asm-arm/ecard.h
@@ -155,8 +155,8 @@ struct expansion_card {
struct resource resource[ECARD_NUM_RESOURCES];
/* Public data */
- volatile unsigned char *irqaddr; /* address of IRQ register */
- volatile unsigned char *fiqaddr; /* address of FIQ register */
+ void __iomem *irqaddr; /* address of IRQ register */
+ void __iomem *fiqaddr; /* address of FIQ register */
unsigned char irqmask; /* IRQ mask */
unsigned char fiqmask; /* FIQ mask */
unsigned char claimed; /* Card claimed? */
@@ -207,9 +207,16 @@ struct in_chunk_dir {
extern int ecard_readchunk (struct in_chunk_dir *cd, struct expansion_card *ec, int id, int num);
/*
- * Obtain the address of a card
+ * Obtain the address of a card. This returns the "old style" address
+ * and should no longer be used.
*/
-extern __deprecated unsigned int ecard_address (struct expansion_card *ec, card_type_t card_type, card_speed_t speed);
+static inline unsigned int __deprecated
+ecard_address(struct expansion_card *ec, card_type_t type, card_speed_t speed)
+{
+ extern unsigned int __ecard_address(struct expansion_card *,
+ card_type_t, card_speed_t);
+ return __ecard_address(ec, type, speed);
+}
/*
* Request and release ecard resources
diff --git a/include/asm-arm/hardware/locomo.h b/include/asm-arm/hardware/locomo.h
index 98d6da2dc424f..5f9218c151429 100644
--- a/include/asm-arm/hardware/locomo.h
+++ b/include/asm-arm/hardware/locomo.h
@@ -35,146 +35,139 @@
#define LOCOMO_MCSX3 0x1c
/* Touch panel controller */
-#define LOCOMO_ASD 0x20 /* AD start delay */
-#define LOCOMO_HSD 0x28 /* HSYS delay */
-#define LOCOMO_HSC 0x2c /* HSYS period */
-#define LOCOMO_TADC 0x30 /* tablet ADC clock */
+#define LOCOMO_ASD 0x20 /* AD start delay */
+#define LOCOMO_HSD 0x28 /* HSYS delay */
+#define LOCOMO_HSC 0x2c /* HSYS period */
+#define LOCOMO_TADC 0x30 /* tablet ADC clock */
-/* TFT signal */
-#define LOCOMO_TC 0x38 /* TFT control signal */
-#define LOCOMO_CPSD 0x3c /* CPS delay */
-
-/* Key controller */
-#define LOCOMO_KIB 0x40 /* KIB level */
-#define LOCOMO_KSC 0x44 /* KSTRB control */
-#define LOCOMO_KCMD 0x48 /* KSTRB command */
-#define LOCOMO_KIC 0x4c /* Key interrupt */
-
-/* Audio clock */
-#define LOCOMO_ACC 0x54
-
-/* SPI interface */
-#define LOCOMO_SPIMD 0x60 /* SPI mode setting */
-#define LOCOMO_SPICT 0x64 /* SPI mode control */
-#define LOCOMO_SPIST 0x68 /* SPI status */
-#define LOCOMO_SPIIS 0x70 /* SPI interrupt status */
-#define LOCOMO_SPIWE 0x74 /* SPI interrupt status write enable */
-#define LOCOMO_SPIIE 0x78 /* SPI interrupt enable */
-#define LOCOMO_SPIIR 0x7c /* SPI interrupt request */
-#define LOCOMO_SPITD 0x80 /* SPI transfer data write */
-#define LOCOMO_SPIRD 0x84 /* SPI receive data read */
-#define LOCOMO_SPITS 0x88 /* SPI transfer data shift */
-#define LOCOMO_SPIRS 0x8C /* SPI receive data shift */
-
-#define LOCOMO_SPI_TEND (1 << 3) /* Transfer end bit */
-#define LOCOMO_SPI_OVRN (1 << 2) /* Over Run bit */
-#define LOCOMO_SPI_RFW (1 << 1) /* write buffer bit */
-#define LOCOMO_SPI_RFR (1) /* read buffer bit */
-
-/* GPIO */
-#define LOCOMO_GPD 0x90 /* GPIO direction */
-#define LOCOMO_GPE 0x94 /* GPIO input enable */
-#define LOCOMO_GPL 0x98 /* GPIO level */
-#define LOCOMO_GPO 0x9c /* GPIO out data setteing */
-#define LOCOMO_GRIE 0xa0 /* GPIO rise detection */
-#define LOCOMO_GFIE 0xa4 /* GPIO fall detection */
-#define LOCOMO_GIS 0xa8 /* GPIO edge detection status */
-#define LOCOMO_GWE 0xac /* GPIO status write enable */
-#define LOCOMO_GIE 0xb0 /* GPIO interrupt enable */
-#define LOCOMO_GIR 0xb4 /* GPIO interrupt request */
-
-#define LOCOMO_GPIO0 (1<<0)
-#define LOCOMO_GPIO1 (1<<1)
-#define LOCOMO_GPIO2 (1<<2)
-#define LOCOMO_GPIO3 (1<<3)
-#define LOCOMO_GPIO4 (1<<4)
-#define LOCOMO_GPIO5 (1<<5)
-#define LOCOMO_GPIO6 (1<<6)
-#define LOCOMO_GPIO7 (1<<7)
-#define LOCOMO_GPIO8 (1<<8)
-#define LOCOMO_GPIO9 (1<<9)
-#define LOCOMO_GPIO10 (1<<10)
-#define LOCOMO_GPIO11 (1<<11)
-#define LOCOMO_GPIO12 (1<<12)
-#define LOCOMO_GPIO13 (1<<13)
-#define LOCOMO_GPIO14 (1<<14)
-#define LOCOMO_GPIO15 (1<<15)
-
-/* Front light adjustment controller */
-#define LOCOMO_ALS 0xc8 /* Adjust light cycle */
-#define LOCOMO_ALD 0xcc /* Adjust light duty */
-
-/* PCM audio interface */
-#define LOCOMO_PAIF 0xd0
/* Long time timer */
-#define LOCOMO_LTC 0xd8 /* LTC interrupt setting */
-#define LOCOMO_LTINT 0xdc /* LTC interrupt */
+#define LOCOMO_LTC 0xd8 /* LTC interrupt setting */
+#define LOCOMO_LTINT 0xdc /* LTC interrupt */
/* DAC control signal for LCD (COMADJ ) */
-#define LOCOMO_DAC 0xe0
-
+#define LOCOMO_DAC 0xe0
/* DAC control */
#define LOCOMO_DAC_SCLOEB 0x08 /* SCL pin output data */
#define LOCOMO_DAC_TEST 0x04 /* Test bit */
#define LOCOMO_DAC_SDA 0x02 /* SDA pin level (read-only) */
#define LOCOMO_DAC_SDAOEB 0x01 /* SDA pin output data */
-/* LED controller */
-#define LOCOMO_LPT0 0xe8 /* LEDPWM0 timer */
-#define LOCOMO_LPT1 0xec /* LEDPWM1 timer */
+/* SPI interface */
+#define LOCOMO_SPIMD 0x60 /* SPI mode setting */
+#define LOCOMO_SPICT 0x64 /* SPI mode control */
+#define LOCOMO_SPIST 0x68 /* SPI status */
+#define LOCOMO_SPIIS 0x70 /* SPI interrupt status */
+#define LOCOMO_SPIWE 0x74 /* SPI interrupt status write enable */
+#define LOCOMO_SPIIE 0x78 /* SPI interrupt enable */
+#define LOCOMO_SPIIR 0x7c /* SPI interrupt request */
+#define LOCOMO_SPITD 0x80 /* SPI transfer data write */
+#define LOCOMO_SPIRD 0x84 /* SPI receive data read */
+#define LOCOMO_SPITS 0x88 /* SPI transfer data shift */
+#define LOCOMO_SPIRS 0x8C /* SPI receive data shift */
+#define LOCOMO_SPI_TEND (1 << 3) /* Transfer end bit */
+#define LOCOMO_SPI_OVRN (1 << 2) /* Over Run bit */
+#define LOCOMO_SPI_RFW (1 << 1) /* write buffer bit */
+#define LOCOMO_SPI_RFR (1) /* read buffer bit */
-#define LOCOMO_LPT_TOFH 0x80 /* */
-#define LOCOMO_LPT_TOFL 0x08 /* */
-#define LOCOMO_LPT_TOH(TOH) ((TOH & 0x7) << 4) /* */
-#define LOCOMO_LPT_TOL(TOL) ((TOL & 0x7)) /* */
+/* GPIO */
+#define LOCOMO_GPD 0x90 /* GPIO direction */
+#define LOCOMO_GPE 0x94 /* GPIO input enable */
+#define LOCOMO_GPL 0x98 /* GPIO level */
+#define LOCOMO_GPO 0x9c /* GPIO out data setteing */
+#define LOCOMO_GRIE 0xa0 /* GPIO rise detection */
+#define LOCOMO_GFIE 0xa4 /* GPIO fall detection */
+#define LOCOMO_GIS 0xa8 /* GPIO edge detection status */
+#define LOCOMO_GWE 0xac /* GPIO status write enable */
+#define LOCOMO_GIE 0xb0 /* GPIO interrupt enable */
+#define LOCOMO_GIR 0xb4 /* GPIO interrupt request */
+#define LOCOMO_GPIO(Nb) (0x01 << (Nb))
+#define LOCOMO_GPIO_RTS LOCOMO_GPIO(0)
+#define LOCOMO_GPIO_CTS LOCOMO_GPIO(1)
+#define LOCOMO_GPIO_DSR LOCOMO_GPIO(2)
+#define LOCOMO_GPIO_DTR LOCOMO_GPIO(3)
+#define LOCOMO_GPIO_LCD_VSHA_ON LOCOMO_GPIO(4)
+#define LOCOMO_GPIO_LCD_VSHD_ON LOCOMO_GPIO(5)
+#define LOCOMO_GPIO_LCD_VEE_ON LOCOMO_GPIO(6)
+#define LOCOMO_GPIO_LCD_MOD LOCOMO_GPIO(7)
+#define LOCOMO_GPIO_DAC_ON LOCOMO_GPIO(8)
+#define LOCOMO_GPIO_FL_VR LOCOMO_GPIO(9)
+#define LOCOMO_GPIO_DAC_SDATA LOCOMO_GPIO(10)
+#define LOCOMO_GPIO_DAC_SCK LOCOMO_GPIO(11)
+#define LOCOMO_GPIO_DAC_SLOAD LOCOMO_GPIO(12)
+
+/* Start the definitions of the devices. Each device has an initial
+ * base address and a series of offsets from that base address. */
+
+/* Keyboard controller */
+#define LOCOMO_KEYBOARD 0x40
+#define LOCOMO_KIB 0x00 /* KIB level */
+#define LOCOMO_KSC 0x04 /* KSTRB control */
+#define LOCOMO_KCMD 0x08 /* KSTRB command */
+#define LOCOMO_KIC 0x0c /* Key interrupt */
+/* Front light adjustment controller */
+#define LOCOMO_FRONTLIGHT 0xc8
+#define LOCOMO_ALS 0x00 /* Adjust light cycle */
+#define LOCOMO_ALD 0x04 /* Adjust light duty */
+
+/* Backlight controller: TFT signal */
+#define LOCOMO_BACKLIGHT 0x38
+#define LOCOMO_TC 0x00 /* TFT control signal */
+#define LOCOMO_CPSD 0x04 /* CPS delay */
+
+/* Audio controller */
+#define LOCOMO_AUDIO 0x54
+#define LOCOMO_ACC 0x00 /* Audio clock */
+#define LOCOMO_PAIF 0x7C /* PCM audio interface */
/* Audio clock */
-#define LOCOMO_ACC_XON 0x80 /* */
-#define LOCOMO_ACC_XEN 0x40 /* */
-#define LOCOMO_ACC_XSEL0 0x00 /* */
-#define LOCOMO_ACC_XSEL1 0x20 /* */
-#define LOCOMO_ACC_MCLKEN 0x10 /* */
-#define LOCOMO_ACC_64FSEN 0x08 /* */
+#define LOCOMO_ACC_XON 0x80
+#define LOCOMO_ACC_XEN 0x40
+#define LOCOMO_ACC_XSEL0 0x00
+#define LOCOMO_ACC_XSEL1 0x20
+#define LOCOMO_ACC_MCLKEN 0x10
+#define LOCOMO_ACC_64FSEN 0x08
#define LOCOMO_ACC_CLKSEL000 0x00 /* mclk 2 */
#define LOCOMO_ACC_CLKSEL001 0x01 /* mclk 3 */
#define LOCOMO_ACC_CLKSEL010 0x02 /* mclk 4 */
#define LOCOMO_ACC_CLKSEL011 0x03 /* mclk 6 */
#define LOCOMO_ACC_CLKSEL100 0x04 /* mclk 8 */
#define LOCOMO_ACC_CLKSEL101 0x05 /* mclk 12 */
-
/* PCM audio interface */
-#define LOCOMO_PAIF_SCINV 0x20 /* */
-#define LOCOMO_PAIF_SCEN 0x10 /* */
-#define LOCOMO_PAIF_LRCRST 0x08 /* */
-#define LOCOMO_PAIF_LRCEVE 0x04 /* */
-#define LOCOMO_PAIF_LRCINV 0x02 /* */
-#define LOCOMO_PAIF_LRCEN 0x01 /* */
+#define LOCOMO_PAIF_SCINV 0x20
+#define LOCOMO_PAIF_SCEN 0x10
+#define LOCOMO_PAIF_LRCRST 0x08
+#define LOCOMO_PAIF_LRCEVE 0x04
+#define LOCOMO_PAIF_LRCINV 0x02
+#define LOCOMO_PAIF_LRCEN 0x01
-/* GPIO */
-#define LOCOMO_GPIO(Nb) (0x01 << (Nb)) /* LoCoMo GPIO [0...15] */
-#define LOCOMO_GPIO_RTS LOCOMO_GPIO(0) /* LoCoMo GPIO [0] */
-#define LOCOMO_GPIO_CTS LOCOMO_GPIO(1) /* LoCoMo GPIO [1] */
-#define LOCOMO_GPIO_DSR LOCOMO_GPIO(2) /* LoCoMo GPIO [2] */
-#define LOCOMO_GPIO_DTR LOCOMO_GPIO(3) /* LoCoMo GPIO [3] */
-#define LOCOMO_GPIO_LCD_VSHA_ON LOCOMO_GPIO(4) /* LoCoMo GPIO [4] */
-#define LOCOMO_GPIO_LCD_VSHD_ON LOCOMO_GPIO(5) /* LoCoMo GPIO [5] */
-#define LOCOMO_GPIO_LCD_VEE_ON LOCOMO_GPIO(6) /* LoCoMo GPIO [6] */
-#define LOCOMO_GPIO_LCD_MOD LOCOMO_GPIO(7) /* LoCoMo GPIO [7] */
-#define LOCOMO_GPIO_DAC_ON LOCOMO_GPIO(8) /* LoCoMo GPIO [8] */
-#define LOCOMO_GPIO_FL_VR LOCOMO_GPIO(9) /* LoCoMo GPIO [9] */
-#define LOCOMO_GPIO_DAC_SDATA LOCOMO_GPIO(10) /* LoCoMo GPIO [10] */
-#define LOCOMO_GPIO_DAC_SCK LOCOMO_GPIO(11) /* LoCoMo GPIO [11] */
-#define LOCOMO_GPIO_DAC_SLOAD LOCOMO_GPIO(12) /* LoCoMo GPIO [12] */
+/* LED controller */
+#define LOCOMO_LED 0xe8
+#define LOCOMO_LPT0 0x00
+#define LOCOMO_LPT1 0x04
+/* LED control */
+#define LOCOMO_LPT_TOFH 0x80
+#define LOCOMO_LPT_TOFL 0x08
+#define LOCOMO_LPT_TOH(TOH) ((TOH & 0x7) << 4)
+#define LOCOMO_LPT_TOL(TOL) ((TOL & 0x7))
extern struct bus_type locomo_bus_type;
+#define LOCOMO_DEVID_KEYBOARD 0
+#define LOCOMO_DEVID_FRONTLIGHT 1
+#define LOCOMO_DEVID_BACKLIGHT 2
+#define LOCOMO_DEVID_AUDIO 3
+#define LOCOMO_DEVID_LED 4
+#define LOCOMO_DEVID_UART 5
+
struct locomo_dev {
struct device dev;
unsigned int devid;
- struct resource res;
- void *mapbase;
unsigned int irq[1];
+
+ void *mapbase;
+ unsigned long length;
+
u64 dma_mask;
};
@@ -201,4 +194,13 @@ void locomo_lcd_power(struct locomo_dev *, int, unsigned int);
int locomo_driver_register(struct locomo_driver *);
void locomo_driver_unregister(struct locomo_driver *);
+/* GPIO control functions */
+void locomo_gpio_set_dir(struct locomo_dev *ldev, unsigned int bits, unsigned int dir);
+unsigned int locomo_gpio_read_level(struct locomo_dev *ldev, unsigned int bits);
+unsigned int locomo_gpio_read_output(struct locomo_dev *ldev, unsigned int bits);
+void locomo_gpio_write(struct locomo_dev *ldev, unsigned int bits, unsigned int set);
+
+/* M62332 control function */
+void locomo_m62332_senddata(struct locomo_dev *ldev, unsigned int dac_data, int channel);
+
#endif
diff --git a/include/asm-arm/hardware/scoop.h b/include/asm-arm/hardware/scoop.h
index 669b7df6e570e..7ea771ff61449 100644
--- a/include/asm-arm/hardware/scoop.h
+++ b/include/asm-arm/hardware/scoop.h
@@ -40,8 +40,8 @@ struct scoop_config {
unsigned short io_dir;
};
-void reset_scoop(void);
-unsigned short set_scoop_gpio(unsigned short bit);
-unsigned short reset_scoop_gpio(unsigned short bit);
-unsigned short read_scoop_reg(unsigned short reg);
-void write_scoop_reg(unsigned short reg, unsigned short data);
+void reset_scoop(struct device *dev);
+unsigned short set_scoop_gpio(struct device *dev, unsigned short bit);
+unsigned short reset_scoop_gpio(struct device *dev, unsigned short bit);
+unsigned short read_scoop_reg(struct device *dev, unsigned short reg);
+void write_scoop_reg(struct device *dev, unsigned short reg, unsigned short data);
diff --git a/include/asm-arm/io.h b/include/asm-arm/io.h
index 60513375e728e..69bc7a3e81606 100644
--- a/include/asm-arm/io.h
+++ b/include/asm-arm/io.h
@@ -47,13 +47,13 @@ extern void __raw_readsb(void __iomem *addr, void *data, int bytelen);
extern void __raw_readsw(void __iomem *addr, void *data, int wordlen);
extern void __raw_readsl(void __iomem *addr, void *data, int longlen);
-#define __raw_writeb(v,a) (*(volatile unsigned char __force *)(a) = (v))
-#define __raw_writew(v,a) (*(volatile unsigned short __force *)(a) = (v))
-#define __raw_writel(v,a) (*(volatile unsigned int __force *)(a) = (v))
+#define __raw_writeb(v,a) (__chk_io_ptr(a), *(volatile unsigned char __force *)(a) = (v))
+#define __raw_writew(v,a) (__chk_io_ptr(a), *(volatile unsigned short __force *)(a) = (v))
+#define __raw_writel(v,a) (__chk_io_ptr(a), *(volatile unsigned int __force *)(a) = (v))
-#define __raw_readb(a) (*(volatile unsigned char __force *)(a))
-#define __raw_readw(a) (*(volatile unsigned short __force *)(a))
-#define __raw_readl(a) (*(volatile unsigned int __force *)(a))
+#define __raw_readb(a) (__chk_io_ptr(a), *(volatile unsigned char __force *)(a))
+#define __raw_readw(a) (__chk_io_ptr(a), *(volatile unsigned short __force *)(a))
+#define __raw_readl(a) (__chk_io_ptr(a), *(volatile unsigned int __force *)(a))
/*
* Bad read/write accesses...
@@ -271,5 +271,16 @@ extern void __iounmap(void __iomem *addr);
#define BIOVEC_MERGEABLE(vec1, vec2) \
((bvec_to_phys((vec1)) + (vec1)->bv_len) == bvec_to_phys((vec2)))
+/*
+ * Convert a physical pointer to a virtual kernel pointer for /dev/mem
+ * access
+ */
+#define xlate_dev_mem_ptr(p) __va(p)
+
+/*
+ * Convert a virtual cached pointer to an uncached pointer
+ */
+#define xlate_dev_kmem_ptr(p) p
+
#endif /* __KERNEL__ */
#endif /* __ASM_ARM_IO_H */
diff --git a/include/asm-arm/ipc.h b/include/asm-arm/ipc.h
index affae4b95f973..a46e3d9c2a3fc 100644
--- a/include/asm-arm/ipc.h
+++ b/include/asm-arm/ipc.h
@@ -1,28 +1 @@
-#ifndef __ASMARM_IPC_H
-#define __ASMARM_IPC_H
-
-/*
- * These are used to wrap system calls on ARM.
- *
- * See arch/arm/kernel/sys-arm.c for ugly details..
- */
-struct ipc_kludge {
- struct msgbuf __user *msgp;
- long msgtyp;
-};
-
-#define SEMOP 1
-#define SEMGET 2
-#define SEMCTL 3
-#define MSGSND 11
-#define MSGRCV 12
-#define MSGGET 13
-#define MSGCTL 14
-#define SHMAT 21
-#define SHMDT 22
-#define SHMGET 23
-#define SHMCTL 24
-
-#define IPCCALL(version,op) ((version)<<16 | (op))
-
-#endif
+#include <asm-generic/ipc.h>
diff --git a/include/asm-arm/mach/arch.h b/include/asm-arm/mach/arch.h
index 993467c37b5bd..3a32e929ec8c1 100644
--- a/include/asm-arm/mach/arch.h
+++ b/include/asm-arm/mach/arch.h
@@ -16,7 +16,7 @@ struct sys_timer;
struct machine_desc {
/*
- * Note! The first four elements are used
+ * Note! The first five elements are used
* by assembler code in head-armv.S
*/
unsigned int nr; /* architecture number */
diff --git a/include/asm-arm/mach/map.h b/include/asm-arm/mach/map.h
index 0dbac30ed127a..9ac47cf8d2e4e 100644
--- a/include/asm-arm/mach/map.h
+++ b/include/asm-arm/mach/map.h
@@ -18,13 +18,14 @@ struct map_desc {
struct meminfo;
-#define MT_DEVICE 0
-#define MT_CACHECLEAN 1
-#define MT_MINICLEAN 2
-#define MT_LOW_VECTORS 3
-#define MT_HIGH_VECTORS 4
-#define MT_MEMORY 5
-#define MT_ROM 6
+#define MT_DEVICE 0
+#define MT_CACHECLEAN 1
+#define MT_MINICLEAN 2
+#define MT_LOW_VECTORS 3
+#define MT_HIGH_VECTORS 4
+#define MT_MEMORY 5
+#define MT_ROM 6
+#define MT_IXP2000_DEVICE 7
extern void create_memmap_holes(struct meminfo *);
extern void memtable_init(struct meminfo *);
diff --git a/include/asm-arm/pgtable.h b/include/asm-arm/pgtable.h
index 10d747ba0ce03..91ffb1f4cd102 100644
--- a/include/asm-arm/pgtable.h
+++ b/include/asm-arm/pgtable.h
@@ -106,6 +106,13 @@ extern void __pgd_error(const char *file, int line, unsigned long val);
#define USER_PTRS_PER_PGD ((TASK_SIZE/PGDIR_SIZE) - FIRST_USER_PGD_NR)
/*
+ * ARMv6 supersection address mask and size definitions.
+ */
+#define SUPERSECTION_SHIFT 24
+#define SUPERSECTION_SIZE (1UL << SUPERSECTION_SHIFT)
+#define SUPERSECTION_MASK (~(SUPERSECTION_SIZE-1))
+
+/*
* Hardware page table definitions.
*
* + Level 1 descriptor (PMD)
@@ -129,6 +136,7 @@ extern void __pgd_error(const char *file, int line, unsigned long val);
#define PMD_SECT_APX (1 << 15) /* v6 */
#define PMD_SECT_S (1 << 16) /* v6 */
#define PMD_SECT_nG (1 << 17) /* v6 */
+#define PMD_SECT_SUPER (1 << 18) /* v6 */
#define PMD_SECT_UNCACHED (0)
#define PMD_SECT_BUFFERED (PMD_SECT_BUFFERABLE)
@@ -254,7 +262,7 @@ extern struct page *empty_zero_page;
#define pfn_pte(pfn,prot) (__pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot)))
#define pte_none(pte) (!pte_val(pte))
-#define pte_clear(ptep) set_pte((ptep), __pte(0))
+#define pte_clear(mm,addr,ptep) set_pte_at((mm),(addr),(ptep), __pte(0))
#define pte_page(pte) (pfn_to_page(pte_pfn(pte)))
#define pte_offset_kernel(dir,addr) (pmd_page_kernel(*(dir)) + __pte_index(addr))
#define pte_offset_map(dir,addr) (pmd_page_kernel(*(dir)) + __pte_index(addr))
@@ -263,6 +271,7 @@ extern struct page *empty_zero_page;
#define pte_unmap_nested(pte) do { } while (0)
#define set_pte(ptep, pte) cpu_set_pte(ptep,pte)
+#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
/*
* The following only work if pte_present() is true.
@@ -308,12 +317,6 @@ PTE_BIT_FUNC(mkyoung, |= L_PTE_YOUNG);
#define pmd_present(pmd) (pmd_val(pmd))
#define pmd_bad(pmd) (pmd_val(pmd) & 2)
-#define set_pmd(pmdp,pmd) \
- do { \
- *(pmdp) = pmd; \
- flush_pmd_entry(pmdp); \
- } while (0)
-
#define copy_pmd(pmdpd,pmdps) \
do { \
pmdpd[0] = pmdps[0]; \
@@ -416,6 +419,13 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
#define io_remap_page_range(vma,from,phys,size,prot) \
remap_pfn_range(vma, from, (phys) >> PAGE_SHIFT, size, prot)
+#define io_remap_pfn_range(vma,from,pfn,size,prot) \
+ remap_pfn_range(vma, from, pfn, size, prot)
+
+#define MK_IOSPACE_PFN(space, pfn) (pfn)
+#define GET_IOSPACE(pfn) 0
+#define GET_PFN(pfn) (pfn)
+
#define pgtable_cache_init() do { } while (0)
#endif /* !__ASSEMBLY__ */
diff --git a/include/asm-arm/ptrace.h b/include/asm-arm/ptrace.h
index a9a95fd25f4d4..604e3a186cf9b 100644
--- a/include/asm-arm/ptrace.h
+++ b/include/asm-arm/ptrace.h
@@ -17,6 +17,9 @@
#define PTRACE_GETFPREGS 14
#define PTRACE_SETFPREGS 15
+#define PTRACE_GETWMMXREGS 18
+#define PTRACE_SETWMMXREGS 19
+
#define PTRACE_OLDSETOPTIONS 21
#define PTRACE_GET_THREAD_AREA 22
diff --git a/include/asm-arm/rtc.h b/include/asm-arm/rtc.h
index c3e330ded8600..aa7e16b2e2255 100644
--- a/include/asm-arm/rtc.h
+++ b/include/asm-arm/rtc.h
@@ -27,6 +27,7 @@ struct rtc_ops {
void rtc_time_to_tm(unsigned long, struct rtc_time *);
int rtc_tm_to_time(struct rtc_time *, unsigned long *);
+int rtc_valid_tm(struct rtc_time *);
void rtc_next_alarm_time(struct rtc_time *, struct rtc_time *, struct rtc_time *);
void rtc_update(unsigned long, unsigned long);
int register_rtc(struct rtc_ops *);
diff --git a/include/asm-arm/system.h b/include/asm-arm/system.h
index 77d0dcf0b713c..b5731290b4e5a 100644
--- a/include/asm-arm/system.h
+++ b/include/asm-arm/system.h
@@ -383,6 +383,8 @@ static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size
#endif /* __ASSEMBLY__ */
+#define arch_align_stack(x) (x)
+
#endif /* __KERNEL__ */
#endif
diff --git a/include/asm-arm/timex.h b/include/asm-arm/timex.h
index 0713f0de6117b..7b8d4cb24be0b 100644
--- a/include/asm-arm/timex.h
+++ b/include/asm-arm/timex.h
@@ -16,8 +16,6 @@
typedef unsigned long cycles_t;
-extern cycles_t cacheflush_time;
-
static inline cycles_t get_cycles (void)
{
return 0;
diff --git a/include/asm-arm/tlb.h b/include/asm-arm/tlb.h
index 0843a876b3ceb..9bb325c54645e 100644
--- a/include/asm-arm/tlb.h
+++ b/include/asm-arm/tlb.h
@@ -54,38 +54,44 @@ tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end)
{
struct mm_struct *mm = tlb->mm;
unsigned long freed = tlb->freed;
- int rss = mm->rss;
+ int rss = get_mm_counter(mm, rss);
if (rss < freed)
freed = rss;
- mm->rss = rss - freed;
+ add_mm_counter(mm, rss, -freed);
- if (freed) {
+ if (tlb->fullmm)
flush_tlb_mm(mm);
- tlb->flushes++;
- } else {
- tlb->avoided_flushes++;
- }
/* keep the page table cache within bounds */
check_pgt_cache();
}
-static inline unsigned int
-tlb_is_full_mm(struct mmu_gather *tlb)
+static inline unsigned int tlb_is_full_mm(struct mmu_gather *tlb)
{
- return tlb->fullmm;
+ return tlb->fullmm;
}
#define tlb_remove_tlb_entry(tlb,ptep,address) do { } while (0)
-#define tlb_start_vma(tlb,vma) \
- do { \
- if (!tlb->fullmm) \
- flush_cache_range(vma, vma->vm_start, vma->vm_end); \
- } while (0)
+/*
+ * In the case of tlb vma handling, we can optimise these away in the
+ * case where we're doing a full MM flush. When we're doing a munmap,
+ * the vmas are adjusted to only cover the region to be torn down.
+ */
+static inline void
+tlb_start_vma(struct mmu_gather *tlb, struct vm_area_struct *vma)
+{
+ if (!tlb->fullmm)
+ flush_cache_range(vma, vma->vm_start, vma->vm_end);
+}
-#define tlb_end_vma(tlb,vma) do { } while (0)
+static inline void
+tlb_end_vma(struct mmu_gather *tlb, struct vm_area_struct *vma)
+{
+ if (!tlb->fullmm)
+ flush_tlb_range(vma, vma->vm_start, vma->vm_end);
+}
#define tlb_remove_page(tlb,page) free_page_and_swap_cache(page)
#define pte_free_tlb(tlb,ptep) pte_free(ptep)
diff --git a/include/asm-arm/uaccess.h b/include/asm-arm/uaccess.h
index abda6082b5cb2..a7c018b8a0d4b 100644
--- a/include/asm-arm/uaccess.h
+++ b/include/asm-arm/uaccess.h
@@ -77,7 +77,8 @@ static inline void set_fs (mm_segment_t fs)
#define access_ok(type,addr,size) (__range_ok(addr,size) == 0)
-static inline int verify_area(int type, const void __user *addr, unsigned long size)
+/* this function will go away soon - use access_ok() instead */
+static inline int __deprecated verify_area(int type, const void __user *addr, unsigned long size)
{
return access_ok(type, addr, size) ? 0 : -EFAULT;
}
diff --git a/include/asm-arm/unistd.h b/include/asm-arm/unistd.h
index b3efbb2c3f9e8..a19ec09eaa016 100644
--- a/include/asm-arm/unistd.h
+++ b/include/asm-arm/unistd.h
@@ -1,7 +1,7 @@
/*
* linux/include/asm-arm/unistd.h
*
- * Copyright (C) 2001-2003 Russell King
+ * Copyright (C) 2001-2005 Russell King
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -307,6 +307,50 @@
#define __NR_mq_getsetattr (__NR_SYSCALL_BASE+279)
#define __NR_waitid (__NR_SYSCALL_BASE+280)
+#if 0 /* reserve these for un-muxing socketcall */
+#define __NR_socket (__NR_SYSCALL_BASE+281)
+#define __NR_bind (__NR_SYSCALL_BASE+282)
+#define __NR_connect (__NR_SYSCALL_BASE+283)
+#define __NR_listen (__NR_SYSCALL_BASE+284)
+#define __NR_accept (__NR_SYSCALL_BASE+285)
+#define __NR_getsockname (__NR_SYSCALL_BASE+286)
+#define __NR_getpeername (__NR_SYSCALL_BASE+287)
+#define __NR_socketpair (__NR_SYSCALL_BASE+288)
+#define __NR_send (__NR_SYSCALL_BASE+289)
+#define __NR_sendto (__NR_SYSCALL_BASE+290)
+#define __NR_recv (__NR_SYSCALL_BASE+291)
+#define __NR_recvfrom (__NR_SYSCALL_BASE+292)
+#define __NR_shutdown (__NR_SYSCALL_BASE+293)
+#define __NR_setsockopt (__NR_SYSCALL_BASE+294)
+#define __NR_getsockopt (__NR_SYSCALL_BASE+295)
+#define __NR_sendmsg (__NR_SYSCALL_BASE+296)
+#define __NR_recvmsg (__NR_SYSCALL_BASE+297)
+#endif
+
+#if 0 /* reserve these for un-muxing ipc */
+#define __NR_semop (__NR_SYSCALL_BASE+298)
+#define __NR_semget (__NR_SYSCALL_BASE+299)
+#define __NR_semctl (__NR_SYSCALL_BASE+300)
+#define __NR_msgsnd (__NR_SYSCALL_BASE+301)
+#define __NR_msgrcv (__NR_SYSCALL_BASE+302)
+#define __NR_msgget (__NR_SYSCALL_BASE+303)
+#define __NR_msgctl (__NR_SYSCALL_BASE+304)
+#define __NR_shmat (__NR_SYSCALL_BASE+305)
+#define __NR_shmdt (__NR_SYSCALL_BASE+306)
+#define __NR_shmget (__NR_SYSCALL_BASE+307)
+#define __NR_shmctl (__NR_SYSCALL_BASE+308)
+#endif
+
+#define __NR_add_key (__NR_SYSCALL_BASE+309)
+#define __NR_request_key (__NR_SYSCALL_BASE+310)
+#define __NR_keyctl (__NR_SYSCALL_BASE+311)
+
+#if 0 /* reserved for un-muxing ipc */
+#define __NR_semtimedop (__NR_SYSCALL_BASE+312)
+#endif
+
+#define __NR_vserver (__NR_SYSCALL_BASE+313)
+
/*
* The following SWIs are ARM private.
*/
@@ -335,7 +379,7 @@
#define __syscall_return(type, res) \
do { \
- if ((unsigned long)(res) >= (unsigned long)(-125)) { \
+ if ((unsigned long)(res) >= (unsigned long)(-129)) { \
errno = -(res); \
res = -1; \
} \
@@ -509,6 +553,6 @@ asmlinkage long sys_rt_sigaction(int sig,
* What we want is __attribute__((weak,alias("sys_ni_syscall"))),
* but it doesn't work on all toolchains, so we just do it by hand
*/
-#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
+#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
#endif /* __ASM_ARM_UNISTD_H */
diff --git a/include/asm-arm26/cacheflush.h b/include/asm-arm26/cacheflush.h
index eb887710735a7..9c1b9c7f2ebd1 100644
--- a/include/asm-arm26/cacheflush.h
+++ b/include/asm-arm26/cacheflush.h
@@ -23,7 +23,7 @@
#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)
-#define flush_cache_page(vma,vmaddr) do { } while (0)
+#define flush_cache_page(vma,vmaddr,pfn) do { } while (0)
#define flush_cache_vmap(start, end) do { } while (0)
#define flush_cache_vunmap(start, end) do { } while (0)
diff --git a/include/asm-arm26/io.h b/include/asm-arm26/io.h
index bc20793f9f4f8..02f94d88a1247 100644
--- a/include/asm-arm26/io.h
+++ b/include/asm-arm26/io.h
@@ -420,5 +420,16 @@ extern void consistent_sync(void *vaddr, size_t size, int rw);
#define BIOVEC_MERGEABLE(vec1, vec2) \
((bvec_to_phys((vec1)) + (vec1)->bv_len) == bvec_to_phys((vec2)))
+/*
+ * Convert a physical pointer to a virtual kernel pointer for /dev/mem
+ * access
+ */
+#define xlate_dev_mem_ptr(p) __va(p)
+
+/*
+ * Convert a virtual cached pointer to an uncached pointer
+ */
+#define xlate_dev_kmem_ptr(p) p
+
#endif /* __KERNEL__ */
#endif /* __ASM_ARM_IO_H */
diff --git a/include/asm-arm26/ipc.h b/include/asm-arm26/ipc.h
index c330504ba3f4c..a46e3d9c2a3fc 100644
--- a/include/asm-arm26/ipc.h
+++ b/include/asm-arm26/ipc.h
@@ -1,28 +1 @@
-#ifndef __ASMARM_IPC_H
-#define __ASMARM_IPC_H
-
-/*
- * These are used to wrap system calls on ARM.
- *
- * See arch/arm/kernel/sys-arm.c for ugly details..
- */
-struct ipc_kludge {
- struct msgbuf *msgp;
- long msgtyp;
-};
-
-#define SEMOP 1
-#define SEMGET 2
-#define SEMCTL 3
-#define MSGSND 11
-#define MSGRCV 12
-#define MSGGET 13
-#define MSGCTL 14
-#define SHMAT 21
-#define SHMDT 22
-#define SHMGET 23
-#define SHMCTL 24
-
-#define IPCCALL(version,op) ((version)<<16 | (op))
-
-#endif
+#include <asm-generic/ipc.h>
diff --git a/include/asm-arm26/pgtable.h b/include/asm-arm26/pgtable.h
index fdebe15334054..af0b8907dc143 100644
--- a/include/asm-arm26/pgtable.h
+++ b/include/asm-arm26/pgtable.h
@@ -154,7 +154,8 @@ extern struct page *empty_zero_page;
#define pte_none(pte) (!pte_val(pte))
#define pte_present(pte) (pte_val(pte) & _PAGE_PRESENT)
#define set_pte(pte_ptr, pte) ((*(pte_ptr)) = (pte))
-#define pte_clear(ptep) set_pte((ptep), __pte(0))
+#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
+#define pte_clear(mm,addr,ptep) set_pte_at((mm),(addr),(ptep), __pte(0))
/* macros to ease the getting of pointers to stuff... */
#define pgd_offset(mm, addr) ((pgd_t *)(mm)->pgd + __pgd_index(addr))
@@ -292,6 +293,13 @@ static inline pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot)
#define io_remap_page_range(vma,from,phys,size,prot) \
remap_pfn_range(vma, from, (phys) >> PAGE_SHIFT, size, prot)
+#define io_remap_pfn_range(vma,from,pfn,size,prot) \
+ remap_pfn_range(vma, from, pfn, size, prot)
+
+#define MK_IOSPACE_PFN(space, pfn) (pfn)
+#define GET_IOSPACE(pfn) 0
+#define GET_PFN(pfn) (pfn)
+
#endif /* !__ASSEMBLY__ */
#endif /* _ASMARM_PGTABLE_H */
diff --git a/include/asm-arm26/system.h b/include/asm-arm26/system.h
index 6361b6c71f8c4..f23fac1938f31 100644
--- a/include/asm-arm26/system.h
+++ b/include/asm-arm26/system.h
@@ -245,6 +245,8 @@ static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size
#endif /* __ASSEMBLY__ */
+#define arch_align_stack(x) (x)
+
#endif /* __KERNEL__ */
#endif
diff --git a/include/asm-arm26/timex.h b/include/asm-arm26/timex.h
index 756214ae57f10..68322fbc1aedf 100644
--- a/include/asm-arm26/timex.h
+++ b/include/asm-arm26/timex.h
@@ -21,8 +21,6 @@
typedef unsigned long cycles_t;
-extern cycles_t cacheflush_time;
-
static inline cycles_t get_cycles (void)
{
return 0;
diff --git a/include/asm-arm26/tlb.h b/include/asm-arm26/tlb.h
index 7a3ac8815c1d8..1316352a58f3d 100644
--- a/include/asm-arm26/tlb.h
+++ b/include/asm-arm26/tlb.h
@@ -37,11 +37,11 @@ tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end)
{
struct mm_struct *mm = tlb->mm;
unsigned long freed = tlb->freed;
- int rss = mm->rss;
+ int rss = get_mm_counter(mm, rss);
if (rss < freed)
freed = rss;
- mm->rss = rss - freed;
+ add_mm_counter(mm, rss, -freed);
if (freed) {
flush_tlb_mm(mm);
diff --git a/include/asm-arm26/uaccess.h b/include/asm-arm26/uaccess.h
index 9060a348f6596..ab9ce38c6aec9 100644
--- a/include/asm-arm26/uaccess.h
+++ b/include/asm-arm26/uaccess.h
@@ -40,7 +40,8 @@ extern int fixup_exception(struct pt_regs *regs);
#define access_ok(type,addr,size) (__range_ok(addr,size) == 0)
-static inline int verify_area(int type, const void * addr, unsigned long size)
+/* this function will go away soon - use access_ok() instead */
+static inline int __deprecated verify_area(int type, const void * addr, unsigned long size)
{
return access_ok(type, addr, size) ? 0 : -EFAULT;
}
diff --git a/include/asm-arm26/unistd.h b/include/asm-arm26/unistd.h
index 54548a29b8bf6..dfa0b0c30aa3b 100644
--- a/include/asm-arm26/unistd.h
+++ b/include/asm-arm26/unistd.h
@@ -495,6 +495,6 @@ asmlinkage long sys_rt_sigaction(int sig,
* What we want is __attribute__((weak,alias("sys_ni_syscall"))),
* but it doesn't work on all toolchains, so we just do it by hand
*/
-#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
+#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
#endif /* __ASM_ARM_UNISTD_H */
diff --git a/include/asm-cris/cacheflush.h b/include/asm-cris/cacheflush.h
index 793fea286006c..72cc71dffe70e 100644
--- a/include/asm-cris/cacheflush.h
+++ b/include/asm-cris/cacheflush.h
@@ -10,7 +10,7 @@
#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)
-#define flush_cache_page(vma, vmaddr) do { } while (0)
+#define flush_cache_page(vma, vmaddr, pfn) do { } while (0)
#define flush_dcache_page(page) do { } while (0)
#define flush_dcache_mmap_lock(mapping) do { } while (0)
#define flush_dcache_mmap_unlock(mapping) do { } while (0)
diff --git a/include/asm-cris/io.h b/include/asm-cris/io.h
index b7222312be27d..1d2b51701e8d7 100644
--- a/include/asm-cris/io.h
+++ b/include/asm-cris/io.h
@@ -86,4 +86,15 @@ extern void iounmap(void *addr);
#define outsw(x,y,z)
#define outsl(x,y,z)
+/*
+ * Convert a physical pointer to a virtual kernel pointer for /dev/mem
+ * access
+ */
+#define xlate_dev_mem_ptr(p) __va(p)
+
+/*
+ * Convert a virtual cached pointer to an uncached pointer
+ */
+#define xlate_dev_kmem_ptr(p) p
+
#endif
diff --git a/include/asm-cris/ipc.h b/include/asm-cris/ipc.h
index f086af6fa03ff..a46e3d9c2a3fc 100644
--- a/include/asm-cris/ipc.h
+++ b/include/asm-cris/ipc.h
@@ -1,35 +1 @@
-#ifndef __CRIS_IPC_H__
-#define __CRIS_IPC_H__
-
-/*
- * These are used to wrap system calls on CRIS.
- *
- * See arch/cris/kernel/sys_cris.c for ugly details..
- *
- * Same as x86 version.
- *
- */
-struct ipc_kludge {
- struct msgbuf *msgp;
- long msgtyp;
-};
-
-#define SEMOP 1
-#define SEMGET 2
-#define SEMCTL 3
-#define SEMTIMEDOP 4
-#define MSGSND 11
-#define MSGRCV 12
-#define MSGGET 13
-#define MSGCTL 14
-#define SHMAT 21
-#define SHMDT 22
-#define SHMGET 23
-#define SHMCTL 24
-
-/* Used by the DIPC package, try and avoid reusing it */
-#define DIPC 25
-
-#define IPCCALL(version,op) ((version)<<16 | (op))
-
-#endif
+#include <asm-generic/ipc.h>
diff --git a/include/asm-cris/pgalloc.h b/include/asm-cris/pgalloc.h
index 7f313d563c28b..b202e62ed6e0b 100644
--- a/include/asm-cris/pgalloc.h
+++ b/include/asm-cris/pgalloc.h
@@ -1,7 +1,6 @@
#ifndef _CRIS_PGALLOC_H
#define _CRIS_PGALLOC_H
-#include <asm/page.h>
#include <linux/threads.h>
#include <linux/mm.h>
diff --git a/include/asm-cris/pgtable.h b/include/asm-cris/pgtable.h
index fc052d4a5032a..957dd92d108dd 100644
--- a/include/asm-cris/pgtable.h
+++ b/include/asm-cris/pgtable.h
@@ -34,6 +34,8 @@ extern void paging_init(void);
* hook is made available.
*/
#define set_pte(pteptr, pteval) ((*(pteptr)) = (pteval))
+#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
+
/*
* (pmds are folded into pgds so this doesn't get actually called,
* but the define is needed for a generic inline function.)
@@ -101,7 +103,7 @@ extern unsigned long empty_zero_page;
#define pte_none(x) (!pte_val(x))
#define pte_present(x) (pte_val(x) & _PAGE_PRESENT)
-#define pte_clear(xp) do { pte_val(*(xp)) = 0; } while (0)
+#define pte_clear(mm,addr,xp) do { pte_val(*(xp)) = 0; } while (0)
#define pmd_none(x) (!pmd_val(x))
/* by removing the _PAGE_KERNEL bit from the comparision, the same pmd_bad
diff --git a/include/asm-cris/system.h b/include/asm-cris/system.h
index f9cf802625745..e06739806d4e4 100644
--- a/include/asm-cris/system.h
+++ b/include/asm-cris/system.h
@@ -69,4 +69,6 @@ extern inline unsigned long __xchg(unsigned long x, volatile void * ptr, int siz
return x;
}
+#define arch_align_stack(x) (x)
+
#endif
diff --git a/include/asm-cris/uaccess.h b/include/asm-cris/uaccess.h
index 2f58e19df4b25..6db17221fd9e5 100644
--- a/include/asm-cris/uaccess.h
+++ b/include/asm-cris/uaccess.h
@@ -91,7 +91,8 @@
#define __access_ok(addr,size) (__kernel_ok || __user_ok((addr),(size)))
#define access_ok(type,addr,size) __access_ok((unsigned long)(addr),(size))
-extern inline int verify_area(int type, const void __user * addr, unsigned long size)
+/* this function will go away soon - use access_ok() instead */
+extern inline int __deprecated verify_area(int type, const void __user * addr, unsigned long size)
{
return access_ok(type,addr,size) ? 0 : -EFAULT;
}
diff --git a/include/asm-cris/unistd.h b/include/asm-cris/unistd.h
index 0b58c457b9724..e80bf276b1011 100644
--- a/include/asm-cris/unistd.h
+++ b/include/asm-cris/unistd.h
@@ -387,6 +387,6 @@ extern inline _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options)
* What we want is __attribute__((weak,alias("sys_ni_syscall"))),
* but it doesn't work on all toolchains, so we just do it by hand
*/
-#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
+#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
#endif /* _ASM_CRIS_UNISTD_H_ */
diff --git a/include/asm-frv/cacheflush.h b/include/asm-frv/cacheflush.h
index 85adcf7e79c1b..3007deccb4904 100644
--- a/include/asm-frv/cacheflush.h
+++ b/include/asm-frv/cacheflush.h
@@ -21,7 +21,7 @@
#define flush_cache_all() do {} while(0)
#define flush_cache_mm(mm) do {} while(0)
#define flush_cache_range(mm, start, end) do {} while(0)
-#define flush_cache_page(vma, vmaddr) do {} while(0)
+#define flush_cache_page(vma, vmaddr, pfn) do {} while(0)
#define flush_cache_vmap(start, end) do {} while(0)
#define flush_cache_vunmap(start, end) do {} while(0)
#define flush_dcache_mmap_lock(mapping) do {} while(0)
diff --git a/include/asm-frv/highmem.h b/include/asm-frv/highmem.h
index 6203b502781cb..295f74a57f229 100644
--- a/include/asm-frv/highmem.h
+++ b/include/asm-frv/highmem.h
@@ -44,8 +44,6 @@ extern unsigned long highstart_pfn, highend_pfn;
#define kmap_pte ______kmap_pte_in_TLB
extern pte_t *pkmap_page_table;
-extern void kmap_init(void);
-
#define flush_cache_kmaps() do { } while (0)
/*
diff --git a/include/asm-frv/io.h b/include/asm-frv/io.h
index e5812fbd35aae..48829f7272422 100644
--- a/include/asm-frv/io.h
+++ b/include/asm-frv/io.h
@@ -273,6 +273,18 @@ static inline void flush_write_buffers(void)
__asm__ __volatile__ ("membar" : : :"memory");
}
+
+/*
+ * Convert a physical pointer to a virtual kernel pointer for /dev/mem
+ * access
+ */
+#define xlate_dev_mem_ptr(p) __va(p)
+
+/*
+ * Convert a virtual cached pointer to an uncached pointer
+ */
+#define xlate_dev_kmem_ptr(p) p
+
#endif /* __KERNEL__ */
#endif /* _ASM_IO_H */
diff --git a/include/asm-frv/ipc.h b/include/asm-frv/ipc.h
index 2f72065c63377..a46e3d9c2a3fc 100644
--- a/include/asm-frv/ipc.h
+++ b/include/asm-frv/ipc.h
@@ -1,33 +1 @@
-#ifndef __ASM_IPC_H__
-#define __ASM_IPC_H__
-
-/*
- * These are used to wrap system calls on FR-V
- *
- * See arch/frv/kernel/sys_frv.c for ugly details..
- */
-struct ipc_kludge {
- struct msgbuf __user *msgp;
- long msgtyp;
-};
-
-#define SEMOP 1
-#define SEMGET 2
-#define SEMCTL 3
-#define SEMTIMEDOP 4
-#define MSGSND 11
-#define MSGRCV 12
-#define MSGGET 13
-#define MSGCTL 14
-#define SHMAT 21
-#define SHMDT 22
-#define SHMGET 23
-#define SHMCTL 24
-
-/* Used by the DIPC package, try and avoid reusing it */
-#define DIPC 25
-
-#define IPCCALL(version,op) ((version)<<16 | (op))
-
-#endif
-
+#include <asm-generic/ipc.h>
diff --git a/include/asm-frv/pgtable.h b/include/asm-frv/pgtable.h
index eb56c87217d81..cc1373c4b7906 100644
--- a/include/asm-frv/pgtable.h
+++ b/include/asm-frv/pgtable.h
@@ -173,6 +173,7 @@ do { \
*(pteptr) = (pteval); \
asm volatile("dcf %M0" :: "U"(*pteptr)); \
} while(0)
+#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
#define set_pte_atomic(pteptr, pteval) set_pte((pteptr), (pteval))
@@ -353,7 +354,7 @@ static inline pmd_t *pmd_offset(pud_t *dir, unsigned long address)
#undef TEST_VERIFY_AREA
#define pte_present(x) (pte_val(x) & _PAGE_PRESENT)
-#define pte_clear(xp) do { set_pte(xp, __pte(0)); } while (0)
+#define pte_clear(mm,addr,xp) do { set_pte_at(mm, addr, xp, __pte(0)); } while (0)
#define pmd_none(x) (!pmd_val(x))
#define pmd_present(x) (pmd_val(x) & _PAGE_PRESENT)
@@ -390,39 +391,33 @@ static inline pte_t pte_mkdirty(pte_t pte) { (pte).pte |= _PAGE_DIRTY; return pt
static inline pte_t pte_mkyoung(pte_t pte) { (pte).pte |= _PAGE_ACCESSED; return pte; }
static inline pte_t pte_mkwrite(pte_t pte) { (pte).pte &= ~_PAGE_WP; return pte; }
-static inline int ptep_test_and_clear_dirty(pte_t *ptep)
+static inline int ptep_test_and_clear_dirty(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
{
int i = test_and_clear_bit(_PAGE_BIT_DIRTY, ptep);
asm volatile("dcf %M0" :: "U"(*ptep));
return i;
}
-static inline int ptep_test_and_clear_young(pte_t *ptep)
+static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
{
int i = test_and_clear_bit(_PAGE_BIT_ACCESSED, ptep);
asm volatile("dcf %M0" :: "U"(*ptep));
return i;
}
-static inline pte_t ptep_get_and_clear(pte_t *ptep)
+static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
{
unsigned long x = xchg(&ptep->pte, 0);
asm volatile("dcf %M0" :: "U"(*ptep));
return __pte(x);
}
-static inline void ptep_set_wrprotect(pte_t *ptep)
+static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
{
set_bit(_PAGE_BIT_WP, ptep);
asm volatile("dcf %M0" :: "U"(*ptep));
}
-static inline void ptep_mkdirty(pte_t *ptep)
-{
- set_bit(_PAGE_BIT_DIRTY, ptep);
- asm volatile("dcf %M0" :: "U"(*ptep));
-}
-
/*
* Conversion functions: convert a page and protection to a page entry,
* and a page entry and page directory to the page they refer to.
@@ -508,11 +503,17 @@ static inline int pte_file(pte_t pte)
#define io_remap_page_range(vma, vaddr, paddr, size, prot) \
remap_pfn_range(vma, vaddr, (paddr) >> PAGE_SHIFT, size, prot)
+#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
+ remap_pfn_range(vma, vaddr, pfn, size, prot)
+
+#define MK_IOSPACE_PFN(space, pfn) (pfn)
+#define GET_IOSPACE(pfn) 0
+#define GET_PFN(pfn) (pfn)
+
#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
#define __HAVE_ARCH_PTEP_SET_WRPROTECT
-#define __HAVE_ARCH_PTEP_MKDIRTY
#define __HAVE_ARCH_PTE_SAME
#include <asm-generic/pgtable.h>
diff --git a/include/asm-frv/system.h b/include/asm-frv/system.h
index 29cfa21ec2fe3..d2aea70a5f64c 100644
--- a/include/asm-frv/system.h
+++ b/include/asm-frv/system.h
@@ -123,4 +123,6 @@ do { \
extern void die_if_kernel(const char *, ...) __attribute__((format(printf, 1, 2)));
extern void free_initmem(void);
+#define arch_align_stack(x) (x)
+
#endif /* _ASM_SYSTEM_H */
diff --git a/include/asm-frv/tlbflush.h b/include/asm-frv/tlbflush.h
index c66aeb169208e..bc34626250846 100644
--- a/include/asm-frv/tlbflush.h
+++ b/include/asm-frv/tlbflush.h
@@ -58,7 +58,8 @@ do { \
#define __flush_tlb_global() flush_tlb_all()
#define flush_tlb() flush_tlb_all()
#define flush_tlb_kernel_range(start, end) flush_tlb_all()
-#define flush_tlb_pgtables(mm,start,end) asm volatile("movgs gr0,scr0 ! movgs gr0,scr1");
+#define flush_tlb_pgtables(mm,start,end) \
+ asm volatile("movgs %0,scr0 ! movgs %0,scr1" :: "r"(ULONG_MAX) : "memory");
#else
diff --git a/include/asm-frv/uaccess.h b/include/asm-frv/uaccess.h
index a5bd9bd396d63..32dc52e883e54 100644
--- a/include/asm-frv/uaccess.h
+++ b/include/asm-frv/uaccess.h
@@ -67,7 +67,8 @@ static inline int ___range_ok(unsigned long addr, unsigned long size)
#define access_ok(type,addr,size) (__range_ok((addr), (size)) == 0)
#define __access_ok(addr,size) (__range_ok((addr), (size)) == 0)
-static inline int verify_area(int type, const void * addr, unsigned long size)
+/* this function will go away soon - use access_ok() / __range_ok() instead */
+static inline int __deprecated verify_area(int type, const void * addr, unsigned long size)
{
return __range_ok(addr, size);
}
diff --git a/include/asm-frv/unistd.h b/include/asm-frv/unistd.h
index 7299398afdc7e..5cf989b448d52 100644
--- a/include/asm-frv/unistd.h
+++ b/include/asm-frv/unistd.h
@@ -495,7 +495,7 @@ static inline pid_t wait(int * wait_stat)
* but it doesn't work on all toolchains, so we just do it by hand
*/
#ifndef cond_syscall
-#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
+#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
#endif
#endif /* _ASM_UNISTD_H_ */
diff --git a/include/asm-generic/4level-fixup.h b/include/asm-generic/4level-fixup.h
index 02675742f472f..c20ec257ecc05 100644
--- a/include/asm-generic/4level-fixup.h
+++ b/include/asm-generic/4level-fixup.h
@@ -2,6 +2,7 @@
#define _4LEVEL_FIXUP_H
#define __ARCH_HAS_4LEVEL_HACK
+#define __PAGETABLE_PUD_FOLDED
#define PUD_SIZE PGDIR_SIZE
#define PUD_MASK PGDIR_MASK
@@ -31,4 +32,7 @@
#define pud_free(x) do { } while (0)
#define __pud_free_tlb(tlb, x) do { } while (0)
+#undef pud_addr_end
+#define pud_addr_end(addr, end) (end)
+
#endif
diff --git a/include/asm-generic/cputime.h b/include/asm-generic/cputime.h
index 7943c66945be4..6f178563e336c 100644
--- a/include/asm-generic/cputime.h
+++ b/include/asm-generic/cputime.h
@@ -10,6 +10,8 @@ typedef unsigned long cputime_t;
#define cputime_max ((~0UL >> 1) - 1)
#define cputime_add(__a, __b) ((__a) + (__b))
#define cputime_sub(__a, __b) ((__a) - (__b))
+#define cputime_div(__a, __n) ((__a) / (__n))
+#define cputime_halve(__a) ((__a) >> 1)
#define cputime_eq(__a, __b) ((__a) == (__b))
#define cputime_gt(__a, __b) ((__a) > (__b))
#define cputime_ge(__a, __b) ((__a) >= (__b))
diff --git a/include/asm-generic/dma-mapping.h b/include/asm-generic/dma-mapping.h
index 04a28e6dd366b..8cef663c5cd9f 100644
--- a/include/asm-generic/dma-mapping.h
+++ b/include/asm-generic/dma-mapping.h
@@ -35,7 +35,7 @@ dma_set_mask(struct device *dev, u64 dma_mask)
static inline void *
dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
- int flag)
+ unsigned int __nocast flag)
{
BUG_ON(dev->bus != &pci_bus_type);
@@ -168,7 +168,7 @@ dma_set_mask(struct device *dev, u64 dma_mask)
static inline void *
dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
- int flag)
+ unsigned int __nocast flag)
{
BUG();
return NULL;
diff --git a/include/asm-generic/ipc.h b/include/asm-generic/ipc.h
new file mode 100644
index 0000000000000..a40407a165cec
--- /dev/null
+++ b/include/asm-generic/ipc.h
@@ -0,0 +1,31 @@
+#ifndef _ASM_GENERIC_IPC_H
+#define _ASM_GENERIC_IPC_H
+/*
+ * These are used to wrap system calls.
+ *
+ * See architecture code for ugly details..
+ */
+struct ipc_kludge {
+ struct msgbuf __user *msgp;
+ long msgtyp;
+};
+
+#define SEMOP 1
+#define SEMGET 2
+#define SEMCTL 3
+#define SEMTIMEDOP 4
+#define MSGSND 11
+#define MSGRCV 12
+#define MSGGET 13
+#define MSGCTL 14
+#define SHMAT 21
+#define SHMDT 22
+#define SHMGET 23
+#define SHMCTL 24
+
+/* Used by the DIPC package, try and avoid reusing it */
+#define DIPC 25
+
+#define IPCCALL(version,op) ((version)<<16 | (op))
+
+#endif /* _ASM_GENERIC_IPC_H */
diff --git a/include/asm-generic/pgtable-nopmd.h b/include/asm-generic/pgtable-nopmd.h
index b7714d41138cb..c8d53ba20e190 100644
--- a/include/asm-generic/pgtable-nopmd.h
+++ b/include/asm-generic/pgtable-nopmd.h
@@ -5,6 +5,8 @@
#include <asm-generic/pgtable-nopud.h>
+#define __PAGETABLE_PMD_FOLDED
+
/*
* Having the pmd type consist of a pud gets the size right, and allows
* us to conceptually access the pud entry that this pmd is folded into
@@ -55,6 +57,9 @@ static inline pmd_t * pmd_offset(pud_t * pud, unsigned long address)
#define pmd_free(x) do { } while (0)
#define __pmd_free_tlb(tlb, x) do { } while (0)
+#undef pmd_addr_end
+#define pmd_addr_end(addr, end) (end)
+
#endif /* __ASSEMBLY__ */
#endif /* _PGTABLE_NOPMD_H */
diff --git a/include/asm-generic/pgtable-nopud.h b/include/asm-generic/pgtable-nopud.h
index ffce31fef970f..82e29f0ce4671 100644
--- a/include/asm-generic/pgtable-nopud.h
+++ b/include/asm-generic/pgtable-nopud.h
@@ -3,6 +3,8 @@
#ifndef __ASSEMBLY__
+#define __PAGETABLE_PUD_FOLDED
+
/*
* Having the pud type consist of a pgd gets the size right, and allows
* us to conceptually access the pgd entry that this pud is folded into
@@ -52,5 +54,8 @@ static inline pud_t * pud_offset(pgd_t * pgd, unsigned long address)
#define pud_free(x) do { } while (0)
#define __pud_free_tlb(tlb, x) do { } while (0)
+#undef pud_addr_end
+#define pud_addr_end(addr, end) (end)
+
#endif /* __ASSEMBLY__ */
#endif /* _PGTABLE_NOPUD_H */
diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h
index cf791b073e76b..a3b28710d56cc 100644
--- a/include/asm-generic/pgtable.h
+++ b/include/asm-generic/pgtable.h
@@ -16,7 +16,7 @@
#ifndef __HAVE_ARCH_SET_PTE_ATOMIC
#define ptep_establish(__vma, __address, __ptep, __entry) \
do { \
- set_pte(__ptep, __entry); \
+ set_pte_at((__vma)->vm_mm, (__address), __ptep, __entry); \
flush_tlb_page(__vma, __address); \
} while (0)
#else /* __HAVE_ARCH_SET_PTE_ATOMIC */
@@ -37,26 +37,30 @@ do { \
*/
#define ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \
do { \
- set_pte(__ptep, __entry); \
+ set_pte_at((__vma)->vm_mm, (__address), __ptep, __entry); \
flush_tlb_page(__vma, __address); \
} while (0)
#endif
#ifndef __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
-static inline int ptep_test_and_clear_young(pte_t *ptep)
-{
- pte_t pte = *ptep;
- if (!pte_young(pte))
- return 0;
- set_pte(ptep, pte_mkold(pte));
- return 1;
-}
+#define ptep_test_and_clear_young(__vma, __address, __ptep) \
+({ \
+ pte_t __pte = *(__ptep); \
+ int r = 1; \
+ if (!pte_young(__pte)) \
+ r = 0; \
+ else \
+ set_pte_at((__vma)->vm_mm, (__address), \
+ (__ptep), pte_mkold(__pte)); \
+ r; \
+})
#endif
#ifndef __HAVE_ARCH_PTEP_CLEAR_YOUNG_FLUSH
#define ptep_clear_flush_young(__vma, __address, __ptep) \
({ \
- int __young = ptep_test_and_clear_young(__ptep); \
+ int __young; \
+ __young = ptep_test_and_clear_young(__vma, __address, __ptep); \
if (__young) \
flush_tlb_page(__vma, __address); \
__young; \
@@ -64,20 +68,24 @@ static inline int ptep_test_and_clear_young(pte_t *ptep)
#endif
#ifndef __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
-static inline int ptep_test_and_clear_dirty(pte_t *ptep)
-{
- pte_t pte = *ptep;
- if (!pte_dirty(pte))
- return 0;
- set_pte(ptep, pte_mkclean(pte));
- return 1;
-}
+#define ptep_test_and_clear_dirty(__vma, __address, __ptep) \
+({ \
+ pte_t __pte = *__ptep; \
+ int r = 1; \
+ if (!pte_dirty(__pte)) \
+ r = 0; \
+ else \
+ set_pte_at((__vma)->vm_mm, (__address), (__ptep), \
+ pte_mkclean(__pte)); \
+ r; \
+})
#endif
#ifndef __HAVE_ARCH_PTEP_CLEAR_DIRTY_FLUSH
#define ptep_clear_flush_dirty(__vma, __address, __ptep) \
({ \
- int __dirty = ptep_test_and_clear_dirty(__ptep); \
+ int __dirty; \
+ __dirty = ptep_test_and_clear_dirty(__vma, __address, __ptep); \
if (__dirty) \
flush_tlb_page(__vma, __address); \
__dirty; \
@@ -85,36 +93,29 @@ static inline int ptep_test_and_clear_dirty(pte_t *ptep)
#endif
#ifndef __HAVE_ARCH_PTEP_GET_AND_CLEAR
-static inline pte_t ptep_get_and_clear(pte_t *ptep)
-{
- pte_t pte = *ptep;
- pte_clear(ptep);
- return pte;
-}
+#define ptep_get_and_clear(__mm, __address, __ptep) \
+({ \
+ pte_t __pte = *(__ptep); \
+ pte_clear((__mm), (__address), (__ptep)); \
+ __pte; \
+})
#endif
#ifndef __HAVE_ARCH_PTEP_CLEAR_FLUSH
#define ptep_clear_flush(__vma, __address, __ptep) \
({ \
- pte_t __pte = ptep_get_and_clear(__ptep); \
+ pte_t __pte; \
+ __pte = ptep_get_and_clear((__vma)->vm_mm, __address, __ptep); \
flush_tlb_page(__vma, __address); \
__pte; \
})
#endif
#ifndef __HAVE_ARCH_PTEP_SET_WRPROTECT
-static inline void ptep_set_wrprotect(pte_t *ptep)
+static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long address, pte_t *ptep)
{
pte_t old_pte = *ptep;
- set_pte(ptep, pte_wrprotect(old_pte));
-}
-#endif
-
-#ifndef __HAVE_ARCH_PTEP_MKDIRTY
-static inline void ptep_mkdirty(pte_t *ptep)
-{
- pte_t old_pte = *ptep;
- set_pte(ptep, pte_mkdirty(old_pte));
+ set_pte_at(mm, address, ptep, pte_wrprotect(old_pte));
}
#endif
@@ -134,4 +135,79 @@ static inline void ptep_mkdirty(pte_t *ptep)
#define pgd_offset_gate(mm, addr) pgd_offset(mm, addr)
#endif
+#ifndef __HAVE_ARCH_LAZY_MMU_PROT_UPDATE
+#define lazy_mmu_prot_update(pte) do { } while (0)
+#endif
+
+/*
+ * When walking page tables, get the address of the next boundary, or
+ * the end address of the range if that comes earlier. Although end might
+ * wrap to 0 only in clear_page_range, __boundary may wrap to 0 throughout.
+ */
+
+#ifndef pgd_addr_end
+#define pgd_addr_end(addr, end) \
+({ unsigned long __boundary = ((addr) + PGDIR_SIZE) & PGDIR_MASK; \
+ (__boundary - 1 < (end) - 1)? __boundary: (end); \
+})
+#endif
+
+#ifndef pud_addr_end
+#define pud_addr_end(addr, end) \
+({ unsigned long __boundary = ((addr) + PUD_SIZE) & PUD_MASK; \
+ (__boundary - 1 < (end) - 1)? __boundary: (end); \
+})
+#endif
+
+#ifndef pmd_addr_end
+#define pmd_addr_end(addr, end) \
+({ unsigned long __boundary = ((addr) + PMD_SIZE) & PMD_MASK; \
+ (__boundary - 1 < (end) - 1)? __boundary: (end); \
+})
+#endif
+
+#ifndef __ASSEMBLY__
+/*
+ * When walking page tables, we usually want to skip any p?d_none entries;
+ * and any p?d_bad entries - reporting the error before resetting to none.
+ * Do the tests inline, but report and clear the bad entry in mm/memory.c.
+ */
+void pgd_clear_bad(pgd_t *);
+void pud_clear_bad(pud_t *);
+void pmd_clear_bad(pmd_t *);
+
+static inline int pgd_none_or_clear_bad(pgd_t *pgd)
+{
+ if (pgd_none(*pgd))
+ return 1;
+ if (unlikely(pgd_bad(*pgd))) {
+ pgd_clear_bad(pgd);
+ return 1;
+ }
+ return 0;
+}
+
+static inline int pud_none_or_clear_bad(pud_t *pud)
+{
+ if (pud_none(*pud))
+ return 1;
+ if (unlikely(pud_bad(*pud))) {
+ pud_clear_bad(pud);
+ return 1;
+ }
+ return 0;
+}
+
+static inline int pmd_none_or_clear_bad(pmd_t *pmd)
+{
+ if (pmd_none(*pmd))
+ return 1;
+ if (unlikely(pmd_bad(*pmd))) {
+ pmd_clear_bad(pmd);
+ return 1;
+ }
+ return 0;
+}
+#endif /* !__ASSEMBLY__ */
+
#endif /* _ASM_GENERIC_PGTABLE_H */
diff --git a/include/asm-generic/resource.h b/include/asm-generic/resource.h
index 7ba1bfc6254f7..b1fcda9eac23d 100644
--- a/include/asm-generic/resource.h
+++ b/include/asm-generic/resource.h
@@ -2,57 +2,85 @@
#define _ASM_GENERIC_RESOURCE_H
/*
- * Resource limits
+ * Resource limit IDs
+ *
+ * ( Compatibility detail: there are architectures that have
+ * a different rlimit ID order in the 5-9 range and want
+ * to keep that order for binary compatibility. The reasons
+ * are historic and all new rlimits are identical across all
+ * arches. If an arch has such special order for some rlimits
+ * then it defines them prior including asm-generic/resource.h. )
*/
-/* Allow arch to control resource order */
-#ifndef __ARCH_RLIMIT_ORDER
#define RLIMIT_CPU 0 /* CPU time in ms */
#define RLIMIT_FSIZE 1 /* Maximum filesize */
#define RLIMIT_DATA 2 /* max data size */
#define RLIMIT_STACK 3 /* max stack size */
#define RLIMIT_CORE 4 /* max core file size */
-#define RLIMIT_RSS 5 /* max resident set size */
-#define RLIMIT_NPROC 6 /* max number of processes */
-#define RLIMIT_NOFILE 7 /* max number of open files */
-#define RLIMIT_MEMLOCK 8 /* max locked-in-memory address space */
-#define RLIMIT_AS 9 /* address space limit */
+
+#ifndef RLIMIT_RSS
+# define RLIMIT_RSS 5 /* max resident set size */
+#endif
+
+#ifndef RLIMIT_NPROC
+# define RLIMIT_NPROC 6 /* max number of processes */
+#endif
+
+#ifndef RLIMIT_NOFILE
+# define RLIMIT_NOFILE 7 /* max number of open files */
+#endif
+
+#ifndef RLIMIT_MEMLOCK
+# define RLIMIT_MEMLOCK 8 /* max locked-in-memory address space */
+#endif
+
+#ifndef RLIMIT_AS
+# define RLIMIT_AS 9 /* address space limit */
+#endif
+
#define RLIMIT_LOCKS 10 /* maximum file locks held */
#define RLIMIT_SIGPENDING 11 /* max number of pending signals */
#define RLIMIT_MSGQUEUE 12 /* maximum bytes in POSIX mqueues */
#define RLIM_NLIMITS 13
-#endif
/*
* SuS says limits have to be unsigned.
* Which makes a ton more sense anyway.
+ *
+ * Some architectures override this (for compatibility reasons):
*/
#ifndef RLIM_INFINITY
-#define RLIM_INFINITY (~0UL)
+# define RLIM_INFINITY (~0UL)
#endif
+/*
+ * RLIMIT_STACK default maximum - some architectures override it:
+ */
#ifndef _STK_LIM_MAX
-#define _STK_LIM_MAX RLIM_INFINITY
+# define _STK_LIM_MAX RLIM_INFINITY
#endif
#ifdef __KERNEL__
+/*
+ * boot-time rlimit defaults for the init task:
+ */
#define INIT_RLIMITS \
{ \
- [RLIMIT_CPU] = { RLIM_INFINITY, RLIM_INFINITY }, \
- [RLIMIT_FSIZE] = { RLIM_INFINITY, RLIM_INFINITY }, \
- [RLIMIT_DATA] = { RLIM_INFINITY, RLIM_INFINITY }, \
- [RLIMIT_STACK] = { _STK_LIM, _STK_LIM_MAX }, \
- [RLIMIT_CORE] = { 0, RLIM_INFINITY }, \
- [RLIMIT_RSS] = { RLIM_INFINITY, RLIM_INFINITY }, \
- [RLIMIT_NPROC] = { 0, 0 }, \
- [RLIMIT_NOFILE] = { INR_OPEN, INR_OPEN }, \
- [RLIMIT_MEMLOCK] = { MLOCK_LIMIT, MLOCK_LIMIT }, \
- [RLIMIT_AS] = { RLIM_INFINITY, RLIM_INFINITY }, \
- [RLIMIT_LOCKS] = { RLIM_INFINITY, RLIM_INFINITY }, \
- [RLIMIT_SIGPENDING] = { MAX_SIGPENDING, MAX_SIGPENDING }, \
- [RLIMIT_MSGQUEUE] = { MQ_BYTES_MAX, MQ_BYTES_MAX }, \
+ [RLIMIT_CPU] = { RLIM_INFINITY, RLIM_INFINITY }, \
+ [RLIMIT_FSIZE] = { RLIM_INFINITY, RLIM_INFINITY }, \
+ [RLIMIT_DATA] = { RLIM_INFINITY, RLIM_INFINITY }, \
+ [RLIMIT_STACK] = { _STK_LIM, _STK_LIM_MAX }, \
+ [RLIMIT_CORE] = { 0, RLIM_INFINITY }, \
+ [RLIMIT_RSS] = { RLIM_INFINITY, RLIM_INFINITY }, \
+ [RLIMIT_NPROC] = { 0, 0 }, \
+ [RLIMIT_NOFILE] = { INR_OPEN, INR_OPEN }, \
+ [RLIMIT_MEMLOCK] = { MLOCK_LIMIT, MLOCK_LIMIT }, \
+ [RLIMIT_AS] = { RLIM_INFINITY, RLIM_INFINITY }, \
+ [RLIMIT_LOCKS] = { RLIM_INFINITY, RLIM_INFINITY }, \
+ [RLIMIT_SIGPENDING] = { 0, 0 }, \
+ [RLIMIT_MSGQUEUE] = { MQ_BYTES_MAX, MQ_BYTES_MAX }, \
}
#endif /* __KERNEL__ */
diff --git a/include/asm-generic/siginfo.h b/include/asm-generic/siginfo.h
index 8336d0c787120..9cac8e8dde519 100644
--- a/include/asm-generic/siginfo.h
+++ b/include/asm-generic/siginfo.h
@@ -3,7 +3,6 @@
#include <linux/compiler.h>
#include <linux/types.h>
-#include <linux/resource.h>
typedef union sigval {
int sival_int;
diff --git a/include/asm-generic/tlb.h b/include/asm-generic/tlb.h
index 0dac231d565bf..faff403e10615 100644
--- a/include/asm-generic/tlb.h
+++ b/include/asm-generic/tlb.h
@@ -88,11 +88,11 @@ tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end)
{
int freed = tlb->freed;
struct mm_struct *mm = tlb->mm;
- int rss = mm->rss;
+ int rss = get_mm_counter(mm, rss);
if (rss < freed)
freed = rss;
- mm->rss = rss - freed;
+ add_mm_counter(mm, rss, -freed);
tlb_flush_mmu(tlb, start, end);
/* keep the page table cache within bounds */
diff --git a/include/asm-generic/unaligned.h b/include/asm-generic/unaligned.h
index 57b14024ca579..c856a43e3b455 100644
--- a/include/asm-generic/unaligned.h
+++ b/include/asm-generic/unaligned.h
@@ -4,17 +4,118 @@
/*
* For the benefit of those who are trying to port Linux to another
* architecture, here are some C-language equivalents.
+ *
+ * This is based almost entirely upon Richard Henderson's
+ * asm-alpha/unaligned.h implementation. Some comments were
+ * taken from David Mosberger's asm-ia64/unaligned.h header.
*/
-#include <asm/string.h>
-
+#include <linux/types.h>
+/*
+ * The main single-value unaligned transfer routines.
+ */
#define get_unaligned(ptr) \
- ({ __typeof__(*(ptr)) __tmp; memcpy(&__tmp, (ptr), sizeof(*(ptr))); __tmp; })
+ ((__typeof__(*(ptr)))__get_unaligned((ptr), sizeof(*(ptr))))
+#define put_unaligned(x,ptr) \
+ __put_unaligned((unsigned long)(x), (ptr), sizeof(*(ptr)))
+
+/*
+ * This function doesn't actually exist. The idea is that when
+ * someone uses the macros below with an unsupported size (datatype),
+ * the linker will alert us to the problem via an unresolved reference
+ * error.
+ */
+extern void bad_unaligned_access_length(void) __attribute__((noreturn));
+
+struct __una_u64 { __u64 x __attribute__((packed)); };
+struct __una_u32 { __u32 x __attribute__((packed)); };
+struct __una_u16 { __u16 x __attribute__((packed)); };
+
+/*
+ * Elemental unaligned loads
+ */
+
+static inline unsigned long __uldq(const __u64 *addr)
+{
+ const struct __una_u64 *ptr = (const struct __una_u64 *) addr;
+ return ptr->x;
+}
+
+static inline unsigned long __uldl(const __u32 *addr)
+{
+ const struct __una_u32 *ptr = (const struct __una_u32 *) addr;
+ return ptr->x;
+}
+
+static inline unsigned long __uldw(const __u16 *addr)
+{
+ const struct __una_u16 *ptr = (const struct __una_u16 *) addr;
+ return ptr->x;
+}
+
+/*
+ * Elemental unaligned stores
+ */
+
+static inline void __ustq(__u64 val, __u64 *addr)
+{
+ struct __una_u64 *ptr = (struct __una_u64 *) addr;
+ ptr->x = val;
+}
+
+static inline void __ustl(__u32 val, __u32 *addr)
+{
+ struct __una_u32 *ptr = (struct __una_u32 *) addr;
+ ptr->x = val;
+}
+
+static inline void __ustw(__u16 val, __u16 *addr)
+{
+ struct __una_u16 *ptr = (struct __una_u16 *) addr;
+ ptr->x = val;
+}
+
+static inline unsigned long __get_unaligned(const void *ptr, size_t size)
+{
+ unsigned long val;
+ switch (size) {
+ case 1:
+ val = *(const __u8 *)ptr;
+ break;
+ case 2:
+ val = __uldw((const __u16 *)ptr);
+ break;
+ case 4:
+ val = __uldl((const __u32 *)ptr);
+ break;
+ case 8:
+ val = __uldq((const __u64 *)ptr);
+ break;
+ default:
+ bad_unaligned_access_length();
+ };
+ return val;
+}
-#define put_unaligned(val, ptr) \
- ({ __typeof__(*(ptr)) __tmp = (val); \
- memcpy((ptr), &__tmp, sizeof(*(ptr))); \
- (void)0; })
+static inline void __put_unaligned(unsigned long val, void *ptr, size_t size)
+{
+ switch (size) {
+ case 1:
+ *(__u8 *)ptr = val;
+ break;
+ case 2:
+ __ustw(val, (__u16 *)ptr);
+ break;
+ case 4:
+ __ustl(val, (__u32 *)ptr);
+ break;
+ case 8:
+ __ustq(val, (__u64 *)ptr);
+ break;
+ default:
+ bad_unaligned_access_length();
+ };
+}
#endif /* _ASM_GENERIC_UNALIGNED_H */
diff --git a/include/asm-h8300/cacheflush.h b/include/asm-h8300/cacheflush.h
index d9583676f5d59..1e4d95bb5ec9c 100644
--- a/include/asm-h8300/cacheflush.h
+++ b/include/asm-h8300/cacheflush.h
@@ -13,7 +13,7 @@
#define flush_cache_all()
#define flush_cache_mm(mm)
#define flush_cache_range(vma,a,b)
-#define flush_cache_page(vma,p)
+#define flush_cache_page(vma,p,pfn)
#define flush_dcache_page(page)
#define flush_dcache_mmap_lock(mapping)
#define flush_dcache_mmap_unlock(mapping)
diff --git a/include/asm-h8300/io.h b/include/asm-h8300/io.h
index 57574c8aefa4e..1773e373e9c6c 100644
--- a/include/asm-h8300/io.h
+++ b/include/asm-h8300/io.h
@@ -317,6 +317,17 @@ static __inline__ void ctrl_outl(unsigned long b, unsigned long addr)
#define virt_to_bus virt_to_phys
#define bus_to_virt phys_to_virt
+/*
+ * Convert a physical pointer to a virtual kernel pointer for /dev/mem
+ * access
+ */
+#define xlate_dev_mem_ptr(p) __va(p)
+
+/*
+ * Convert a virtual cached pointer to an uncached pointer
+ */
+#define xlate_dev_kmem_ptr(p) p
+
#endif /* __KERNEL__ */
#endif /* _H8300_IO_H */
diff --git a/include/asm-h8300/ipc.h b/include/asm-h8300/ipc.h
index 6219d8a90e552..a46e3d9c2a3fc 100644
--- a/include/asm-h8300/ipc.h
+++ b/include/asm-h8300/ipc.h
@@ -1,31 +1 @@
-#ifndef __H8300_IPC_H__
-#define __H8300_IPC_H__
-
-/*
- * These are used to wrap system calls on H8/300.
- *
- * See arch/h8300/kernel/sys_h8300.c for ugly details..
- */
-struct ipc_kludge {
- struct msgbuf *msgp;
- long msgtyp;
-};
-
-#define SEMOP 1
-#define SEMGET 2
-#define SEMCTL 3
-#define MSGSND 11
-#define MSGRCV 12
-#define MSGGET 13
-#define MSGCTL 14
-#define SHMAT 21
-#define SHMDT 22
-#define SHMGET 23
-#define SHMCTL 24
-
-/* Used by the DIPC package, try and avoid reusing it */
-#define DIPC 25
-
-#define IPCCALL(version,op) ((version)<<16 | (op))
-
-#endif
+#include <asm-generic/ipc.h>
diff --git a/include/asm-h8300/pgtable.h b/include/asm-h8300/pgtable.h
index 1fd6e7191d00c..69076eb314760 100644
--- a/include/asm-h8300/pgtable.h
+++ b/include/asm-h8300/pgtable.h
@@ -55,6 +55,13 @@ extern int is_in_rom(unsigned long);
#define io_remap_page_range(vma, vaddr, paddr, size, prot) \
remap_pfn_range(vma, vaddr, (paddr) >> PAGE_SHIFT, size, prot)
+#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
+ remap_pfn_range(vma, vaddr, pfn, size, prot)
+
+#define MK_IOSPACE_PFN(space, pfn) (pfn)
+#define GET_IOSPACE(pfn) 0
+#define GET_PFN(pfn) (pfn)
+
/*
* All 32bit addresses are effectively valid for vmalloc...
* Sort of meaningless for non-VM targets.
diff --git a/include/asm-h8300/system.h b/include/asm-h8300/system.h
index b91dae2a90c35..dfe96c7121cfe 100644
--- a/include/asm-h8300/system.h
+++ b/include/asm-h8300/system.h
@@ -144,4 +144,6 @@ static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int siz
asm("jmp @@0"); \
})
+#define arch_align_stack(x) (x)
+
#endif /* _H8300_SYSTEM_H */
diff --git a/include/asm-h8300/uaccess.h b/include/asm-h8300/uaccess.h
index f3f4ffe0b5dc7..1480f307a4749 100644
--- a/include/asm-h8300/uaccess.h
+++ b/include/asm-h8300/uaccess.h
@@ -24,7 +24,8 @@ static inline int __access_ok(unsigned long addr, unsigned long size)
return(RANGE_CHECK_OK(addr, size, 0L, (unsigned long)&_ramend));
}
-static inline int verify_area(int type, const void *addr, unsigned long size)
+/* this function will go away soon - use access_ok() instead */
+static inline int __deprecated verify_area(int type, const void *addr, unsigned long size)
{
return access_ok(type,addr,size)?0:-EFAULT;
}
diff --git a/include/asm-i386/acpi.h b/include/asm-i386/acpi.h
index a4ab82cb2b721..c976c1dadece6 100644
--- a/include/asm-i386/acpi.h
+++ b/include/asm-i386/acpi.h
@@ -174,7 +174,6 @@ static inline int acpi_irq_balance_set(char *str) { return 0; }
/* routines for saving/restoring kernel state */
extern int acpi_save_state_mem(void);
-extern int acpi_save_state_disk(void);
extern void acpi_restore_state_mem(void);
extern unsigned long acpi_wakeup_address;
diff --git a/include/asm-i386/cacheflush.h b/include/asm-i386/cacheflush.h
index 183361ebe0bc1..2ea36dea37d90 100644
--- a/include/asm-i386/cacheflush.h
+++ b/include/asm-i386/cacheflush.h
@@ -8,7 +8,7 @@
#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)
-#define flush_cache_page(vma, vmaddr) do { } while (0)
+#define flush_cache_page(vma, vmaddr, pfn) do { } while (0)
#define flush_dcache_page(page) do { } while (0)
#define flush_dcache_mmap_lock(mapping) do { } while (0)
#define flush_dcache_mmap_unlock(mapping) do { } while (0)
diff --git a/include/asm-i386/cpu.h b/include/asm-i386/cpu.h
index a2e581ffc91f4..002740b219511 100644
--- a/include/asm-i386/cpu.h
+++ b/include/asm-i386/cpu.h
@@ -11,7 +11,6 @@
struct i386_cpu {
struct cpu cpu;
};
-extern struct i386_cpu cpu_devices[NR_CPUS];
extern int arch_register_cpu(int num);
#ifdef CONFIG_HOTPLUG_CPU
extern void arch_unregister_cpu(int);
diff --git a/include/asm-i386/desc.h b/include/asm-i386/desc.h
index fb8cdcf41d4b5..11e67811a9901 100644
--- a/include/asm-i386/desc.h
+++ b/include/asm-i386/desc.h
@@ -4,6 +4,8 @@
#include <asm/ldt.h>
#include <asm/segment.h>
+#define CPU_16BIT_STACK_SIZE 1024
+
#ifndef __ASSEMBLY__
#include <linux/preempt.h>
@@ -15,6 +17,8 @@
extern struct desc_struct cpu_gdt_table[GDT_ENTRIES];
DECLARE_PER_CPU(struct desc_struct, cpu_gdt_table[GDT_ENTRIES]);
+DECLARE_PER_CPU(unsigned char, cpu_16bit_stack[CPU_16BIT_STACK_SIZE]);
+
struct Xgt_desc_struct {
unsigned short size;
unsigned long address __attribute__((packed));
diff --git a/include/asm-i386/dma-mapping.h b/include/asm-i386/dma-mapping.h
index 8d432bd90f2b3..563964b2995b4 100644
--- a/include/asm-i386/dma-mapping.h
+++ b/include/asm-i386/dma-mapping.h
@@ -11,7 +11,7 @@
#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
void *dma_alloc_coherent(struct device *dev, size_t size,
- dma_addr_t *dma_handle, int flag);
+ dma_addr_t *dma_handle, unsigned int __nocast flag);
void dma_free_coherent(struct device *dev, size_t size,
void *vaddr, dma_addr_t dma_handle);
diff --git a/include/asm-i386/hardirq.h b/include/asm-i386/hardirq.h
index 95db6fd1735d3..ee754d3597341 100644
--- a/include/asm-i386/hardirq.h
+++ b/include/asm-i386/hardirq.h
@@ -12,8 +12,13 @@ typedef struct {
unsigned int apic_timer_irqs; /* arch dependent */
} ____cacheline_aligned irq_cpustat_t;
-#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */
+DECLARE_PER_CPU(irq_cpustat_t, irq_stat);
+extern irq_cpustat_t irq_stat[];
+
+#define __ARCH_IRQ_STAT
+#define __IRQ_STAT(cpu, member) (per_cpu(irq_stat, cpu).member)
void ack_bad_irq(unsigned int irq);
+#include <linux/irq_cpustat.h>
#endif /* __ASM_HARDIRQ_H */
diff --git a/include/asm-i386/highmem.h b/include/asm-i386/highmem.h
index 0fcc858e941bf..1df42bf347df6 100644
--- a/include/asm-i386/highmem.h
+++ b/include/asm-i386/highmem.h
@@ -33,8 +33,6 @@ extern pte_t *kmap_pte;
extern pgprot_t kmap_prot;
extern pte_t *pkmap_page_table;
-extern void kmap_init(void);
-
/*
* Right now we initialize only a single pte table. It can be extended
* easily, subsequent pte tables have to be allocated in one physical
diff --git a/include/asm-i386/hpet.h b/include/asm-i386/hpet.h
index 76fb1e0fdcb52..6e20b079f1d3b 100644
--- a/include/asm-i386/hpet.h
+++ b/include/asm-i386/hpet.h
@@ -90,7 +90,6 @@
*/
#define HPET_MIN_PERIOD (100000UL)
-extern unsigned long hpet_period; /* fsecs / HPET clock */
extern unsigned long hpet_tick; /* hpet clks count per tick */
extern unsigned long hpet_address; /* hpet memory map physical address */
@@ -100,7 +99,6 @@ extern int hpet_reenable(void);
extern int is_hpet_enabled(void);
extern int is_hpet_capable(void);
extern int hpet_readl(unsigned long a);
-extern void hpet_writel(unsigned long d, unsigned long a);
#ifdef CONFIG_HPET_EMULATE_RTC
extern int hpet_mask_rtc_irq_bit(unsigned long bit_mask);
diff --git a/include/asm-i386/i387.h b/include/asm-i386/i387.h
index e9ad79b0e4374..f6feb98a93972 100644
--- a/include/asm-i386/i387.h
+++ b/include/asm-i386/i387.h
@@ -17,7 +17,6 @@
#include <asm/sigcontext.h>
#include <asm/user.h>
-extern unsigned long mxcsr_feature_mask;
extern void mxcsr_feature_mask_init(void);
extern void init_fpu(struct task_struct *);
/*
@@ -86,13 +85,8 @@ static inline void save_init_fpu( struct task_struct *tsk )
*/
extern unsigned short get_fpu_cwd( struct task_struct *tsk );
extern unsigned short get_fpu_swd( struct task_struct *tsk );
-extern unsigned short get_fpu_twd( struct task_struct *tsk );
extern unsigned short get_fpu_mxcsr( struct task_struct *tsk );
-extern void set_fpu_cwd( struct task_struct *tsk, unsigned short cwd );
-extern void set_fpu_swd( struct task_struct *tsk, unsigned short swd );
-extern void set_fpu_twd( struct task_struct *tsk, unsigned short twd );
-
/*
* Signal frame handlers...
*/
diff --git a/include/asm-i386/io.h b/include/asm-i386/io.h
index 479e976ed86c4..7babb97a02eb6 100644
--- a/include/asm-i386/io.h
+++ b/include/asm-i386/io.h
@@ -49,6 +49,17 @@
#include <linux/vmalloc.h>
+/*
+ * Convert a physical pointer to a virtual kernel pointer for /dev/mem
+ * access
+ */
+#define xlate_dev_mem_ptr(p) __va(p)
+
+/*
+ * Convert a virtual cached pointer to an uncached pointer
+ */
+#define xlate_dev_kmem_ptr(p) p
+
/**
* virt_to_phys - map virtual addresses to physical
* @address: address to remap
diff --git a/include/asm-i386/ipc.h b/include/asm-i386/ipc.h
index 810a449f8a7e9..a46e3d9c2a3fc 100644
--- a/include/asm-i386/ipc.h
+++ b/include/asm-i386/ipc.h
@@ -1,32 +1 @@
-#ifndef __i386_IPC_H__
-#define __i386_IPC_H__
-
-/*
- * These are used to wrap system calls on x86.
- *
- * See arch/i386/kernel/sys_i386.c for ugly details..
- */
-struct ipc_kludge {
- struct msgbuf __user *msgp;
- long msgtyp;
-};
-
-#define SEMOP 1
-#define SEMGET 2
-#define SEMCTL 3
-#define SEMTIMEDOP 4
-#define MSGSND 11
-#define MSGRCV 12
-#define MSGGET 13
-#define MSGCTL 14
-#define SHMAT 21
-#define SHMDT 22
-#define SHMGET 23
-#define SHMCTL 24
-
-/* Used by the DIPC package, try and avoid reusing it */
-#define DIPC 25
-
-#define IPCCALL(version,op) ((version)<<16 | (op))
-
-#endif
+#include <asm-generic/ipc.h>
diff --git a/include/asm-i386/mach-default/mach_traps.h b/include/asm-i386/mach-default/mach_traps.h
index c98c2880c5c97..625438b8a6eb4 100644
--- a/include/asm-i386/mach-default/mach_traps.h
+++ b/include/asm-i386/mach-default/mach_traps.h
@@ -7,6 +7,8 @@
#ifndef _MACH_TRAPS_H
#define _MACH_TRAPS_H
+#include <asm/mc146818rtc.h>
+
static inline void clear_mem_error(unsigned char reason)
{
reason = (reason & 0xf) | 4;
@@ -20,10 +22,20 @@ static inline unsigned char get_nmi_reason(void)
static inline void reassert_nmi(void)
{
+ int old_reg = -1;
+
+ if (do_i_have_lock_cmos())
+ old_reg = current_lock_cmos_reg();
+ else
+ lock_cmos(0); /* register doesn't matter here */
outb(0x8f, 0x70);
inb(0x71); /* dummy */
outb(0x0f, 0x70);
inb(0x71); /* dummy */
+ if (old_reg >= 0)
+ outb(old_reg, 0x70);
+ else
+ unlock_cmos();
}
#endif /* !_MACH_TRAPS_H */
diff --git a/include/asm-i386/mc146818rtc.h b/include/asm-i386/mc146818rtc.h
index d6e3009430c1e..99a890047023c 100644
--- a/include/asm-i386/mc146818rtc.h
+++ b/include/asm-i386/mc146818rtc.h
@@ -5,24 +5,89 @@
#define _ASM_MC146818RTC_H
#include <asm/io.h>
+#include <asm/system.h>
+#include <linux/mc146818rtc.h>
#ifndef RTC_PORT
#define RTC_PORT(x) (0x70 + (x))
#define RTC_ALWAYS_BCD 1 /* RTC operates in binary mode */
#endif
+#ifdef __HAVE_ARCH_CMPXCHG
+/*
+ * This lock provides nmi access to the CMOS/RTC registers. It has some
+ * special properties. It is owned by a CPU and stores the index register
+ * currently being accessed (if owned). The idea here is that it works
+ * like a normal lock (normally). However, in an NMI, the NMI code will
+ * first check to see if its CPU owns the lock, meaning that the NMI
+ * interrupted during the read/write of the device. If it does, it goes ahead
+ * and performs the access and then restores the index register. If it does
+ * not, it locks normally.
+ *
+ * Note that since we are working with NMIs, we need this lock even in
+ * a non-SMP machine just to mark that the lock is owned.
+ *
+ * This only works with compare-and-swap. There is no other way to
+ * atomically claim the lock and set the owner.
+ */
+#include <linux/smp.h>
+extern volatile unsigned long cmos_lock;
+
+/*
+ * All of these below must be called with interrupts off, preempt
+ * disabled, etc.
+ */
+
+static inline void lock_cmos(unsigned char reg)
+{
+ unsigned long new;
+ new = ((smp_processor_id()+1) << 8) | reg;
+ for (;;) {
+ if (cmos_lock)
+ continue;
+ if (__cmpxchg(&cmos_lock, 0, new, sizeof(cmos_lock)) == 0)
+ return;
+ }
+}
+
+static inline void unlock_cmos(void)
+{
+ cmos_lock = 0;
+}
+static inline int do_i_have_lock_cmos(void)
+{
+ return (cmos_lock >> 8) == (smp_processor_id()+1);
+}
+static inline unsigned char current_lock_cmos_reg(void)
+{
+ return cmos_lock & 0xff;
+}
+#define lock_cmos_prefix(reg) \
+ do { \
+ unsigned long cmos_flags; \
+ local_irq_save(cmos_flags); \
+ lock_cmos(reg)
+#define lock_cmos_suffix(reg) \
+ unlock_cmos(); \
+ local_irq_restore(cmos_flags); \
+ } while (0)
+#else
+#define lock_cmos_prefix(reg) do {} while (0)
+#define lock_cmos_suffix(reg) do {} while (0)
+#define lock_cmos(reg)
+#define unlock_cmos()
+#define do_i_have_lock_cmos() 0
+#define current_lock_cmos_reg() 0
+#endif
+
/*
* The yet supported machines all access the RTC index register via
* an ISA port access but the way to access the date register differs ...
*/
-#define CMOS_READ(addr) ({ \
-outb_p((addr),RTC_PORT(0)); \
-inb_p(RTC_PORT(1)); \
-})
-#define CMOS_WRITE(val, addr) ({ \
-outb_p((addr),RTC_PORT(0)); \
-outb_p((val),RTC_PORT(1)); \
-})
+#define CMOS_READ(addr) rtc_cmos_read(addr)
+#define CMOS_WRITE(val, addr) rtc_cmos_write(val, addr)
+unsigned char rtc_cmos_read(unsigned char addr);
+void rtc_cmos_write(unsigned char val, unsigned char addr);
#define RTC_IRQ 8
diff --git a/include/asm-i386/module.h b/include/asm-i386/module.h
index 14cacba9ccbbf..508865e26308e 100644
--- a/include/asm-i386/module.h
+++ b/include/asm-i386/module.h
@@ -52,6 +52,8 @@ struct mod_arch_specific
#define MODULE_PROC_FAMILY "CYRIXIII "
#elif defined CONFIG_MVIAC3_2
#define MODULE_PROC_FAMILY "VIAC3-2 "
+#elif CONFIG_MGEODE
+#define MODULE_PROC_FAMILY "GEODE "
#else
#error unknown processor family
#endif
diff --git a/include/asm-i386/mpspec.h b/include/asm-i386/mpspec.h
index e96814d75bae7..d9fafba075bc4 100644
--- a/include/asm-i386/mpspec.h
+++ b/include/asm-i386/mpspec.h
@@ -22,7 +22,6 @@ extern int mp_irq_entries;
extern struct mpc_config_intsrc mp_irqs [MAX_IRQ_SOURCES];
extern int mpc_default_type;
extern int mp_bus_id_to_pci_bus [MAX_MP_BUSSES];
-extern int mp_current_pci_id;
extern unsigned long mp_lapic_addr;
extern int pic_mode;
extern int using_apic_timer;
diff --git a/include/asm-i386/msr.h b/include/asm-i386/msr.h
index 3589c36b865cc..c76fce8badbbb 100644
--- a/include/asm-i386/msr.h
+++ b/include/asm-i386/msr.h
@@ -32,6 +32,21 @@ static inline void wrmsrl (unsigned long msr, unsigned long long val)
wrmsr (msr, lo, hi);
}
+/* wrmsr with exception handling */
+#define wrmsr_safe(msr,a,b) ({ int ret__; \
+ asm volatile("2: wrmsr ; xorl %0,%0\n" \
+ "1:\n\t" \
+ ".section .fixup,\"ax\"\n\t" \
+ "3: movl %4,%0 ; jmp 1b\n\t" \
+ ".previous\n\t" \
+ ".section __ex_table,\"a\"\n" \
+ " .align 4\n\t" \
+ " .long 2b,3b\n\t" \
+ ".previous" \
+ : "=a" (ret__) \
+ : "c" (msr), "0" (a), "d" (b), "i" (-EFAULT));\
+ ret__; })
+
#define rdtsc(low,high) \
__asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high))
diff --git a/include/asm-i386/pgalloc.h b/include/asm-i386/pgalloc.h
index 3d6a5d11eb509..0380c3dc1f7e8 100644
--- a/include/asm-i386/pgalloc.h
+++ b/include/asm-i386/pgalloc.h
@@ -2,7 +2,6 @@
#define _I386_PGALLOC_H
#include <linux/config.h>
-#include <asm/processor.h>
#include <asm/fixmap.h>
#include <linux/threads.h>
#include <linux/mm.h> /* for struct page */
diff --git a/include/asm-i386/pgtable-2level.h b/include/asm-i386/pgtable-2level.h
index 58026f6c987ae..fa07bd6c75294 100644
--- a/include/asm-i386/pgtable-2level.h
+++ b/include/asm-i386/pgtable-2level.h
@@ -14,10 +14,11 @@
* hook is made available.
*/
#define set_pte(pteptr, pteval) (*(pteptr) = pteval)
+#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
#define set_pte_atomic(pteptr, pteval) set_pte(pteptr,pteval)
#define set_pmd(pmdptr, pmdval) (*(pmdptr) = (pmdval))
-#define ptep_get_and_clear(xp) __pte(xchg(&(xp)->pte_low, 0))
+#define ptep_get_and_clear(mm,addr,xp) __pte(xchg(&(xp)->pte_low, 0))
#define pte_same(a, b) ((a).pte_low == (b).pte_low)
#define pte_page(x) pfn_to_page(pte_pfn(x))
#define pte_none(x) (!(x).pte_low)
diff --git a/include/asm-i386/pgtable-3level.h b/include/asm-i386/pgtable-3level.h
index 0b8a0da756783..d609f9c2c1f03 100644
--- a/include/asm-i386/pgtable-3level.h
+++ b/include/asm-i386/pgtable-3level.h
@@ -56,6 +56,8 @@ static inline void set_pte(pte_t *ptep, pte_t pte)
smp_wmb();
ptep->pte_low = pte.pte_low;
}
+#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
+
#define __HAVE_ARCH_SET_PTE_ATOMIC
#define set_pte_atomic(pteptr,pteval) \
set_64bit((unsigned long long *)(pteptr),pte_val(pteval))
@@ -88,7 +90,7 @@ static inline void pud_clear (pud_t * pud) { }
#define pmd_offset(pud, address) ((pmd_t *) pud_page(*(pud)) + \
pmd_index(address))
-static inline pte_t ptep_get_and_clear(pte_t *ptep)
+static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
{
pte_t res;
diff --git a/include/asm-i386/pgtable.h b/include/asm-i386/pgtable.h
index f34be5140a23f..488c2b4befa57 100644
--- a/include/asm-i386/pgtable.h
+++ b/include/asm-i386/pgtable.h
@@ -201,7 +201,7 @@ extern unsigned long long __PAGE_KERNEL, __PAGE_KERNEL_EXEC;
extern unsigned long pg0[];
#define pte_present(x) ((x).pte_low & (_PAGE_PRESENT | _PAGE_PROTNONE))
-#define pte_clear(xp) do { set_pte(xp, __pte(0)); } while (0)
+#define pte_clear(mm,addr,xp) do { set_pte_at(mm, addr, xp, __pte(0)); } while (0)
#define pmd_none(x) (!pmd_val(x))
#define pmd_present(x) (pmd_val(x) & _PAGE_PRESENT)
@@ -243,22 +243,24 @@ static inline pte_t pte_mkwrite(pte_t pte) { (pte).pte_low |= _PAGE_RW; return p
# include <asm/pgtable-2level.h>
#endif
-static inline int ptep_test_and_clear_dirty(pte_t *ptep)
+static inline int ptep_test_and_clear_dirty(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
{
if (!pte_dirty(*ptep))
return 0;
return test_and_clear_bit(_PAGE_BIT_DIRTY, &ptep->pte_low);
}
-static inline int ptep_test_and_clear_young(pte_t *ptep)
+static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
{
if (!pte_young(*ptep))
return 0;
return test_and_clear_bit(_PAGE_BIT_ACCESSED, &ptep->pte_low);
}
-static inline void ptep_set_wrprotect(pte_t *ptep) { clear_bit(_PAGE_BIT_RW, &ptep->pte_low); }
-static inline void ptep_mkdirty(pte_t *ptep) { set_bit(_PAGE_BIT_DIRTY, &ptep->pte_low); }
+static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
+{
+ clear_bit(_PAGE_BIT_RW, &ptep->pte_low);
+}
/*
* Macro to mark a page protection value as "uncacheable". On processors which do not support
@@ -403,11 +405,17 @@ extern void noexec_setup(const char *str);
#define io_remap_page_range(vma, vaddr, paddr, size, prot) \
remap_pfn_range(vma, vaddr, (paddr) >> PAGE_SHIFT, size, prot)
+#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
+ remap_pfn_range(vma, vaddr, pfn, size, prot)
+
+#define MK_IOSPACE_PFN(space, pfn) (pfn)
+#define GET_IOSPACE(pfn) 0
+#define GET_PFN(pfn) (pfn)
+
#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
#define __HAVE_ARCH_PTEP_SET_WRPROTECT
-#define __HAVE_ARCH_PTEP_MKDIRTY
#define __HAVE_ARCH_PTE_SAME
#include <asm-generic/pgtable.h>
diff --git a/include/asm-i386/processor.h b/include/asm-i386/processor.h
index 70a48f509d240..be258b0e5a5fb 100644
--- a/include/asm-i386/processor.h
+++ b/include/asm-i386/processor.h
@@ -103,7 +103,6 @@ extern char ignore_fpu_irq;
extern void identify_cpu(struct cpuinfo_x86 *);
extern void print_cpu_info(struct cpuinfo_x86 *);
extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c);
-extern void dodgy_tsc(void);
#ifdef CONFIG_X86_HT
extern void detect_ht(struct cpuinfo_x86 *c);
@@ -137,7 +136,7 @@ static inline void detect_ht(struct cpuinfo_x86 *c) {}
* clear %ecx since some cpus (Cyrix MII) do not set or clear %ecx
* resulting in stale register contents being returned.
*/
-static inline void cpuid(int op, int *eax, int *ebx, int *ecx, int *edx)
+static inline void cpuid(unsigned int op, unsigned int *eax, unsigned int *ebx, unsigned int *ecx, unsigned int *edx)
{
__asm__("cpuid"
: "=a" (*eax),
@@ -147,6 +146,18 @@ static inline void cpuid(int op, int *eax, int *ebx, int *ecx, int *edx)
: "0" (op), "c"(0));
}
+/* Some CPUID calls want 'count' to be placed in ecx */
+static inline void cpuid_count(int op, int count, int *eax, int *ebx, int *ecx,
+ int *edx)
+{
+ __asm__("cpuid"
+ : "=a" (*eax),
+ "=b" (*ebx),
+ "=c" (*ecx),
+ "=d" (*edx)
+ : "0" (op), "c" (count));
+}
+
/*
* CPUID functions returning a single datum
*/
diff --git a/include/asm-i386/seccomp.h b/include/asm-i386/seccomp.h
new file mode 100644
index 0000000000000..18da19e89bff2
--- /dev/null
+++ b/include/asm-i386/seccomp.h
@@ -0,0 +1,16 @@
+#ifndef _ASM_SECCOMP_H
+
+#include <linux/thread_info.h>
+
+#ifdef TIF_32BIT
+#error "unexpected TIF_32BIT on i386"
+#endif
+
+#include <linux/unistd.h>
+
+#define __NR_seccomp_read __NR_read
+#define __NR_seccomp_write __NR_write
+#define __NR_seccomp_exit __NR_exit
+#define __NR_seccomp_sigreturn __NR_sigreturn
+
+#endif /* _ASM_SECCOMP_H */
diff --git a/include/asm-i386/segment.h b/include/asm-i386/segment.h
index abe3440a93ceb..bb5ff5b2c02ec 100644
--- a/include/asm-i386/segment.h
+++ b/include/asm-i386/segment.h
@@ -38,7 +38,7 @@
* 24 - APM BIOS support
* 25 - APM BIOS support
*
- * 26 - unused
+ * 26 - ESPFIX small SS
* 27 - unused
* 28 - unused
* 29 - unused
@@ -71,6 +71,9 @@
#define GDT_ENTRY_PNPBIOS_BASE (GDT_ENTRY_KERNEL_BASE + 6)
#define GDT_ENTRY_APMBIOS_BASE (GDT_ENTRY_KERNEL_BASE + 11)
+#define GDT_ENTRY_ESPFIX_SS (GDT_ENTRY_KERNEL_BASE + 14)
+#define __ESPFIX_SS (GDT_ENTRY_ESPFIX_SS * 8)
+
#define GDT_ENTRY_DOUBLEFAULT_TSS 31
/*
diff --git a/include/asm-i386/semaphore.h b/include/asm-i386/semaphore.h
index 1452af116f924..ea563da63e24d 100644
--- a/include/asm-i386/semaphore.h
+++ b/include/asm-i386/semaphore.h
@@ -92,11 +92,6 @@ fastcall int __down_failed_interruptible(void /* params in registers */);
fastcall int __down_failed_trylock(void /* params in registers */);
fastcall void __up_wakeup(void /* special register calling convention */);
-fastcall void __down(struct semaphore * sem);
-fastcall int __down_interruptible(struct semaphore * sem);
-fastcall int __down_trylock(struct semaphore * sem);
-fastcall void __up(struct semaphore * sem);
-
/*
* This is ugly, but we want the default case to fall through.
* "__down_failed" is a special asm handler that calls the C
diff --git a/include/asm-i386/signal.h b/include/asm-i386/signal.h
index de3da5b31077f..7ef343b6812d0 100644
--- a/include/asm-i386/signal.h
+++ b/include/asm-i386/signal.h
@@ -223,7 +223,14 @@ 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 { } while (0)
+
+#define ptrace_signal_deliver(regs, cookie) \
+ do { \
+ if (current->ptrace & PT_DTRACE) { \
+ current->ptrace &= ~PT_DTRACE; \
+ (regs)->eflags &= ~TF_MASK; \
+ } \
+ } while (0)
#endif /* __KERNEL__ */
diff --git a/include/asm-i386/smp.h b/include/asm-i386/smp.h
index db46b2924ae80..dd1491225d519 100644
--- a/include/asm-i386/smp.h
+++ b/include/asm-i386/smp.h
@@ -62,9 +62,6 @@ static inline int num_booting_cpus(void)
return cpus_weight(cpu_callout_map);
}
-extern void map_cpu_to_logical_apicid(void);
-extern void unmap_cpu_to_logical_apicid(int cpu);
-
#ifdef CONFIG_X86_LOCAL_APIC
#ifdef APIC_DEFINITION
diff --git a/include/asm-i386/suspend.h b/include/asm-i386/suspend.h
index f63799f2d2f9b..dfc1114c1b6f8 100644
--- a/include/asm-i386/suspend.h
+++ b/include/asm-i386/suspend.h
@@ -10,10 +10,12 @@ static inline int
arch_prepare_suspend(void)
{
/* If you want to make non-PSE machine work, turn off paging
- in do_magic. swsusp_pg_dir should have identity mapping, so
+ in swsusp_arch_suspend. swsusp_pg_dir should have identity mapping, so
it could work... */
- if (!cpu_has_pse)
+ if (!cpu_has_pse) {
+ printk(KERN_ERR "PSE is required for swsusp.\n");
return -EPERM;
+ }
return 0;
}
@@ -61,5 +63,4 @@ static inline void acpi_save_register_state(unsigned long return_point)
/* routines for saving/restoring kernel state */
extern int acpi_save_state_mem(void);
-extern int acpi_save_state_disk(void);
#endif
diff --git a/include/asm-i386/system.h b/include/asm-i386/system.h
index c705fa77b1387..6f74d4c44a0ea 100644
--- a/include/asm-i386/system.h
+++ b/include/asm-i386/system.h
@@ -468,4 +468,6 @@ void enable_hlt(void);
extern int es7000_plat;
void cpu_idle_wait(void);
+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 de75216b624bd..2cd57271801dc 100644
--- a/include/asm-i386/thread_info.h
+++ b/include/asm-i386/thread_info.h
@@ -140,6 +140,7 @@ register unsigned long current_stack_pointer asm("esp") __attribute_used__;
#define TIF_SINGLESTEP 4 /* restore singlestep on return to user mode */
#define TIF_IRET 5 /* return with iret */
#define TIF_SYSCALL_AUDIT 7 /* syscall auditing active */
+#define TIF_SECCOMP 8 /* secure computing */
#define TIF_POLLING_NRFLAG 16 /* true if poll_idle() is polling TIF_NEED_RESCHED */
#define TIF_MEMDIE 17
@@ -150,12 +151,14 @@ register unsigned long current_stack_pointer asm("esp") __attribute_used__;
#define _TIF_SINGLESTEP (1<<TIF_SINGLESTEP)
#define _TIF_IRET (1<<TIF_IRET)
#define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT)
+#define _TIF_SECCOMP (1<<TIF_SECCOMP)
#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
/* work to do on interrupt/exception return */
#define _TIF_WORK_MASK \
- (0x0000FFFF & ~(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP))
-#define _TIF_ALLWORK_MASK 0x0000FFFF /* work to do on any return to u-space */
+ (0x0000FFFF & ~(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP|_TIF_SECCOMP))
+/* work to do on any return to u-space */
+#define _TIF_ALLWORK_MASK (0x0000FFFF & ~_TIF_SECCOMP)
/*
* Thread-synchronous status.
diff --git a/include/asm-i386/timex.h b/include/asm-i386/timex.h
index ef53334ac043a..b41e484c34456 100644
--- a/include/asm-i386/timex.h
+++ b/include/asm-i386/timex.h
@@ -32,8 +32,6 @@
*/
typedef unsigned long long cycles_t;
-extern cycles_t cacheflush_time;
-
static inline cycles_t get_cycles (void)
{
unsigned long long ret=0;
diff --git a/include/asm-i386/topology.h b/include/asm-i386/topology.h
index dcbed87f1c71b..63e5cfc3ee6cb 100644
--- a/include/asm-i386/topology.h
+++ b/include/asm-i386/topology.h
@@ -88,6 +88,12 @@ static inline cpumask_t pcibus_to_cpumask(int bus)
.nr_balance_failed = 0, \
}
+extern unsigned long node_start_pfn[];
+extern unsigned long node_end_pfn[];
+extern unsigned long node_remap_size[];
+
+#define node_has_online_mem(nid) (node_start_pfn[nid] != node_end_pfn[nid])
+
#else /* !CONFIG_NUMA */
/*
* Other i386 platforms should define their own version of the
diff --git a/include/asm-i386/uaccess.h b/include/asm-i386/uaccess.h
index d3ddd436ca911..886867aea9470 100644
--- a/include/asm-i386/uaccess.h
+++ b/include/asm-i386/uaccess.h
@@ -84,7 +84,8 @@ extern struct movsl_mask {
#define access_ok(type,addr,size) (likely(__range_ok(addr,size) == 0))
/**
- * verify_area: - Obsolete, use access_ok()
+ * verify_area: - Obsolete/deprecated and will go away soon,
+ * use access_ok() instead.
* @type: Type of access: %VERIFY_READ or %VERIFY_WRITE
* @addr: User space pointer to start of block to check
* @size: Size of block to check
@@ -100,7 +101,7 @@ extern struct movsl_mask {
*
* See access_ok() for more details.
*/
-static inline int verify_area(int type, const void __user * addr, unsigned long size)
+static inline int __deprecated verify_area(int type, const void __user * addr, unsigned long size)
{
return access_ok(type,addr,size) ? 0 : -EFAULT;
}
@@ -185,6 +186,21 @@ extern void __get_user_4(void);
extern void __put_user_bad(void);
+/*
+ * Strange magic calling convention: pointer in %ecx,
+ * value in %eax(:%edx), return value in %eax, no clobbers.
+ */
+extern void __put_user_1(void);
+extern void __put_user_2(void);
+extern void __put_user_4(void);
+extern void __put_user_8(void);
+
+#define __put_user_1(x, ptr) __asm__ __volatile__("call __put_user_1":"=a" (__ret_pu):"0" ((typeof(*(ptr)))(x)), "c" (ptr))
+#define __put_user_2(x, ptr) __asm__ __volatile__("call __put_user_2":"=a" (__ret_pu):"0" ((typeof(*(ptr)))(x)), "c" (ptr))
+#define __put_user_4(x, ptr) __asm__ __volatile__("call __put_user_4":"=a" (__ret_pu):"0" ((typeof(*(ptr)))(x)), "c" (ptr))
+#define __put_user_8(x, ptr) __asm__ __volatile__("call __put_user_8":"=a" (__ret_pu):"A" ((typeof(*(ptr)))(x)), "c" (ptr))
+#define __put_user_X(x, ptr) __asm__ __volatile__("call __put_user_X":"=a" (__ret_pu):"c" (ptr))
+
/**
* put_user: - Write a simple value into user space.
* @x: Value to copy to user space.
@@ -201,9 +217,35 @@ extern void __put_user_bad(void);
*
* Returns zero on success, or -EFAULT on error.
*/
-#define put_user(x,ptr) \
- __put_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
+#ifdef CONFIG_X86_WP_WORKS_OK
+#define put_user(x,ptr) \
+({ int __ret_pu; \
+ __chk_user_ptr(ptr); \
+ switch(sizeof(*(ptr))) { \
+ case 1: __put_user_1(x, ptr); break; \
+ case 2: __put_user_2(x, ptr); break; \
+ case 4: __put_user_4(x, ptr); break; \
+ case 8: __put_user_8(x, ptr); break; \
+ default:__put_user_X(x, ptr); break; \
+ } \
+ __ret_pu; \
+})
+
+#else
+#define put_user(x,ptr) \
+({ \
+ int __ret_pu; \
+ __typeof__(*(ptr)) __pus_tmp = x; \
+ __ret_pu=0; \
+ if(unlikely(__copy_to_user_ll(ptr, &__pus_tmp, \
+ sizeof(*(ptr))) != 0)) \
+ __ret_pu=-EFAULT; \
+ __ret_pu; \
+ })
+
+
+#endif
/**
* __get_user: - Get a simple variable from user space, with less checking.
@@ -259,16 +301,6 @@ extern void __put_user_bad(void);
})
-#define __put_user_check(x,ptr,size) \
-({ \
- long __pu_err = -EFAULT; \
- __typeof__(*(ptr)) __user *__pu_addr = (ptr); \
- might_sleep(); \
- if (access_ok(VERIFY_WRITE,__pu_addr,size)) \
- __put_user_size((x),__pu_addr,(size),__pu_err,-EFAULT); \
- __pu_err; \
-})
-
#define __put_user_u64(x, addr, err) \
__asm__ __volatile__( \
"1: movl %%eax,0(%2)\n" \
diff --git a/include/asm-i386/unistd.h b/include/asm-i386/unistd.h
index c093c8bba146a..61bcc1b1e3f43 100644
--- a/include/asm-i386/unistd.h
+++ b/include/asm-i386/unistd.h
@@ -460,7 +460,7 @@ asmlinkage long sys_rt_sigaction(int sig,
* but it doesn't work on all toolchains, so we just do it by hand
*/
#ifndef cond_syscall
-#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
+#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
#endif
#endif /* _ASM_I386_UNISTD_H_ */
diff --git a/include/asm-ia64/bitops.h b/include/asm-ia64/bitops.h
index 8052500a7c09e..925d54cee475e 100644
--- a/include/asm-ia64/bitops.h
+++ b/include/asm-ia64/bitops.h
@@ -353,9 +353,9 @@ hweight64 (unsigned long x)
return result;
}
-#define hweight32(x) hweight64 ((x) & 0xfffffffful)
-#define hweight16(x) hweight64 ((x) & 0xfffful)
-#define hweight8(x) hweight64 ((x) & 0xfful)
+#define hweight32(x) (unsigned int) hweight64((x) & 0xfffffffful)
+#define hweight16(x) (unsigned int) hweight64((x) & 0xfffful)
+#define hweight8(x) (unsigned int) hweight64((x) & 0xfful)
#endif /* __KERNEL__ */
diff --git a/include/asm-ia64/cacheflush.h b/include/asm-ia64/cacheflush.h
index ef0e256f2355b..f2dacb4245ec1 100644
--- a/include/asm-ia64/cacheflush.h
+++ b/include/asm-ia64/cacheflush.h
@@ -19,7 +19,7 @@
#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)
-#define flush_cache_page(vma, vmaddr) do { } while (0)
+#define flush_cache_page(vma, vmaddr, pfn) do { } while (0)
#define flush_icache_page(vma,page) do { } while (0)
#define flush_cache_vmap(start, end) do { } while (0)
#define flush_cache_vunmap(start, end) do { } while (0)
diff --git a/include/asm-ia64/page.h b/include/asm-ia64/page.h
index 24770c011fd87..24aab801a8caa 100644
--- a/include/asm-ia64/page.h
+++ b/include/asm-ia64/page.h
@@ -137,7 +137,7 @@ typedef union ia64_va {
# define htlbpage_to_page(x) (((unsigned long) REGION_NUMBER(x) << 61) \
| (REGION_OFFSET(x) >> (HPAGE_SHIFT-PAGE_SHIFT)))
# define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT)
-# define is_hugepage_only_range(addr, len) \
+# define is_hugepage_only_range(mm, addr, len) \
(REGION_NUMBER(addr) == REGION_HPAGE && \
REGION_NUMBER((addr)+(len)) == REGION_HPAGE)
extern unsigned int hpage_shift;
diff --git a/include/asm-ia64/pci.h b/include/asm-ia64/pci.h
index 48e565fb5e0fe..a8314ee4e7d25 100644
--- a/include/asm-ia64/pci.h
+++ b/include/asm-ia64/pci.h
@@ -121,14 +121,9 @@ struct pci_controller {
extern struct pci_ops pci_root_ops;
-static inline int pci_name_bus(char *name, struct pci_bus *bus)
+static inline int pci_proc_domain(struct pci_bus *bus)
{
- if (pci_domain_nr(bus) == 0) {
- sprintf(name, "%02x", bus->number);
- } else {
- sprintf(name, "%04x:%02x", pci_domain_nr(bus), bus->number);
- }
- return 0;
+ return (pci_domain_nr(bus) != 0);
}
static inline void pcibios_add_platform_entries(struct pci_dev *dev)
diff --git a/include/asm-ia64/pgalloc.h b/include/asm-ia64/pgalloc.h
index fda0dba0b1871..0f05dc8bd4601 100644
--- a/include/asm-ia64/pgalloc.h
+++ b/include/asm-ia64/pgalloc.h
@@ -21,7 +21,6 @@
#include <linux/threads.h>
#include <asm/mmu_context.h>
-#include <asm/processor.h>
/*
* Very stupidly, we used to get new pgd's and pmd's, init their contents
diff --git a/include/asm-ia64/pgtable.h b/include/asm-ia64/pgtable.h
index 594f73f8b5744..1757a811f4361 100644
--- a/include/asm-ia64/pgtable.h
+++ b/include/asm-ia64/pgtable.h
@@ -202,6 +202,7 @@ ia64_phys_addr_valid (unsigned long addr)
* the PTE in a page table. Nothing special needs to be on IA-64.
*/
#define set_pte(ptep, pteval) (*(ptep) = (pteval))
+#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
#define RGN_SIZE (1UL << 61)
#define RGN_KERNEL 7
@@ -243,7 +244,7 @@ ia64_phys_addr_valid (unsigned long addr)
#define pte_none(pte) (!pte_val(pte))
#define pte_present(pte) (pte_val(pte) & (_PAGE_P | _PAGE_PROTNONE))
-#define pte_clear(pte) (pte_val(*(pte)) = 0UL)
+#define pte_clear(mm,addr,pte) (pte_val(*(pte)) = 0UL)
/* pte_page() returns the "struct page *" corresponding to the PTE: */
#define pte_page(pte) virt_to_page(((pte_val(pte) & _PFN_MASK) + PAGE_OFFSET))
@@ -345,7 +346,7 @@ pgd_offset (struct mm_struct *mm, unsigned long address)
/* atomic versions of the some PTE manipulations: */
static inline int
-ptep_test_and_clear_young (pte_t *ptep)
+ptep_test_and_clear_young (struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
{
#ifdef CONFIG_SMP
if (!pte_young(*ptep))
@@ -355,13 +356,13 @@ ptep_test_and_clear_young (pte_t *ptep)
pte_t pte = *ptep;
if (!pte_young(pte))
return 0;
- set_pte(ptep, pte_mkold(pte));
+ set_pte_at(vma->vm_mm, addr, ptep, pte_mkold(pte));
return 1;
#endif
}
static inline int
-ptep_test_and_clear_dirty (pte_t *ptep)
+ptep_test_and_clear_dirty (struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
{
#ifdef CONFIG_SMP
if (!pte_dirty(*ptep))
@@ -371,25 +372,25 @@ ptep_test_and_clear_dirty (pte_t *ptep)
pte_t pte = *ptep;
if (!pte_dirty(pte))
return 0;
- set_pte(ptep, pte_mkclean(pte));
+ set_pte_at(vma->vm_mm, addr, ptep, pte_mkclean(pte));
return 1;
#endif
}
static inline pte_t
-ptep_get_and_clear (pte_t *ptep)
+ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
{
#ifdef CONFIG_SMP
return __pte(xchg((long *) ptep, 0));
#else
pte_t pte = *ptep;
- pte_clear(ptep);
+ pte_clear(mm, addr, ptep);
return pte;
#endif
}
static inline void
-ptep_set_wrprotect (pte_t *ptep)
+ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
{
#ifdef CONFIG_SMP
unsigned long new, old;
@@ -400,18 +401,7 @@ ptep_set_wrprotect (pte_t *ptep)
} while (cmpxchg((unsigned long *) ptep, old, new) != old);
#else
pte_t old_pte = *ptep;
- set_pte(ptep, pte_wrprotect(old_pte));
-#endif
-}
-
-static inline void
-ptep_mkdirty (pte_t *ptep)
-{
-#ifdef CONFIG_SMP
- set_bit(_PAGE_D_BIT, ptep);
-#else
- pte_t old_pte = *ptep;
- set_pte(ptep, pte_mkdirty(old_pte));
+ set_pte_at(mm, addr, ptep, pte_wrprotect(old_pte));
#endif
}
@@ -421,6 +411,8 @@ pte_same (pte_t a, pte_t b)
return pte_val(a) == pte_val(b);
}
+#define update_mmu_cache(vma, address, pte) do { } while (0)
+
extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
extern void paging_init (void);
@@ -457,6 +449,13 @@ extern void paging_init (void);
#define io_remap_page_range(vma, vaddr, paddr, size, prot) \
remap_pfn_range(vma, vaddr, (paddr) >> PAGE_SHIFT, size, prot)
+#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
+ remap_pfn_range(vma, vaddr, pfn, size, prot)
+
+#define MK_IOSPACE_PFN(space, pfn) (pfn)
+#define GET_IOSPACE(pfn) 0
+#define GET_PFN(pfn) (pfn)
+
/*
* ZERO_PAGE is a global shared page that is always zero: used
* for zero-mapped memory areas etc..
@@ -482,7 +481,7 @@ extern void hugetlb_free_pgtables(struct mmu_gather *tlb,
* information. However, we use this routine to take care of any (delayed) i-cache
* flushing that may be necessary.
*/
-extern void update_mmu_cache (struct vm_area_struct *vma, unsigned long vaddr, pte_t pte);
+extern void lazy_mmu_prot_update (pte_t pte);
#define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
/*
@@ -558,10 +557,37 @@ do { \
#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
#define __HAVE_ARCH_PTEP_SET_WRPROTECT
-#define __HAVE_ARCH_PTEP_MKDIRTY
#define __HAVE_ARCH_PTE_SAME
#define __HAVE_ARCH_PGD_OFFSET_GATE
-#include <asm-generic/pgtable.h>
+#define __HAVE_ARCH_LAZY_MMU_PROT_UPDATE
+
+/*
+ * Override for pgd_addr_end() to deal with the virtual address space holes
+ * in each region. In regions 0..4 virtual address bits are used like this:
+ * +--------+------+--------+-----+-----+--------+
+ * | pgdhi3 | rsvd | pgdlow | pmd | pte | offset |
+ * +--------+------+--------+-----+-----+--------+
+ * 'pgdlow' overflows to pgdhi3 (a.k.a. region bits) leaving rsvd==0
+ */
+#define IA64_PGD_OVERFLOW (PGDIR_SIZE << (PAGE_SHIFT-6))
+
+#define pgd_addr_end(addr, end) \
+({ unsigned long __boundary = ((addr) + PGDIR_SIZE) & PGDIR_MASK; \
+ if (REGION_NUMBER(__boundary) < 5 && \
+ __boundary & IA64_PGD_OVERFLOW) \
+ __boundary += (RGN_SIZE - 1) & ~(IA64_PGD_OVERFLOW - 1);\
+ (__boundary - 1 < (end) - 1)? __boundary: (end); \
+})
+
+#define pmd_addr_end(addr, end) \
+({ unsigned long __boundary = ((addr) + PMD_SIZE) & PMD_MASK; \
+ if (REGION_NUMBER(__boundary) < 5 && \
+ __boundary & IA64_PGD_OVERFLOW) \
+ __boundary += (RGN_SIZE - 1) & ~(IA64_PGD_OVERFLOW - 1);\
+ (__boundary - 1 < (end) - 1)? __boundary: (end); \
+})
+
#include <asm-generic/pgtable-nopud.h>
+#include <asm-generic/pgtable.h>
#endif /* _ASM_IA64_PGTABLE_H */
diff --git a/include/asm-ia64/system.h b/include/asm-ia64/system.h
index f28b920e90891..6f516e76d1f0c 100644
--- a/include/asm-ia64/system.h
+++ b/include/asm-ia64/system.h
@@ -285,6 +285,9 @@ do { \
#define ia64_platform_is(x) (strcmp(x, platform_name) == 0)
void cpu_idle_wait(void);
+
+#define arch_align_stack(x) (x)
+
#endif /* __KERNEL__ */
#endif /* __ASSEMBLY__ */
diff --git a/include/asm-ia64/tlb.h b/include/asm-ia64/tlb.h
index aec6e832ddbc0..3a9a6d1be75cf 100644
--- a/include/asm-ia64/tlb.h
+++ b/include/asm-ia64/tlb.h
@@ -161,11 +161,11 @@ tlb_finish_mmu (struct mmu_gather *tlb, unsigned long start, unsigned long end)
{
unsigned long freed = tlb->freed;
struct mm_struct *mm = tlb->mm;
- unsigned long rss = mm->rss;
+ unsigned long rss = get_mm_counter(mm, rss);
if (rss < freed)
freed = rss;
- mm->rss = rss - freed;
+ add_mm_counter(mm, rss, -freed);
/*
* Note: tlb->nr may be 0 at this point, so we can't rely on tlb->start_addr and
* tlb->end_addr.
diff --git a/include/asm-ia64/uaccess.h b/include/asm-ia64/uaccess.h
index 1ffc804e0f16c..8edd9a90949cf 100644
--- a/include/asm-ia64/uaccess.h
+++ b/include/asm-ia64/uaccess.h
@@ -35,9 +35,12 @@
#include <linux/compiler.h>
#include <linux/errno.h>
#include <linux/sched.h>
+#include <linux/page-flags.h>
+#include <linux/mm.h>
#include <asm/intrinsics.h>
#include <asm/pgtable.h>
+#include <asm/io.h>
/*
* For historical reasons, the following macros are grossly misnamed:
@@ -69,7 +72,8 @@
})
#define access_ok(type, addr, size) __access_ok((addr), (size), get_fs())
-static inline int
+/* this function will go away soon - use access_ok() instead */
+static inline int __deprecated
verify_area (int type, const void __user *addr, unsigned long size)
{
return access_ok(type, addr, size) ? 0 : -EFAULT;
@@ -367,4 +371,38 @@ ia64_done_with_exception (struct pt_regs *regs)
return 0;
}
+#define ARCH_HAS_TRANSLATE_MEM_PTR 1
+static __inline__ char *
+xlate_dev_mem_ptr (unsigned long p)
+{
+ struct page *page;
+ char * ptr;
+
+ page = pfn_to_page(p >> PAGE_SHIFT);
+ if (PageUncached(page))
+ ptr = (char *)p + __IA64_UNCACHED_OFFSET;
+ else
+ ptr = __va(p);
+
+ return ptr;
+}
+
+/*
+ * Convert a virtual cached kernel memory pointer to an uncached pointer
+ */
+static __inline__ char *
+xlate_dev_kmem_ptr (char * p)
+{
+ struct page *page;
+ char * ptr;
+
+ page = virt_to_page((unsigned long)p >> PAGE_SHIFT);
+ if (PageUncached(page))
+ ptr = (char *)__pa(p) + __IA64_UNCACHED_OFFSET;
+ else
+ ptr = p;
+
+ return ptr;
+}
+
#endif /* _ASM_IA64_UACCESS_H */
diff --git a/include/asm-ia64/unaligned.h b/include/asm-ia64/unaligned.h
index b5d28366fd3ec..bb85598881035 100644
--- a/include/asm-ia64/unaligned.h
+++ b/include/asm-ia64/unaligned.h
@@ -1,121 +1,6 @@
#ifndef _ASM_IA64_UNALIGNED_H
#define _ASM_IA64_UNALIGNED_H
-#include <linux/types.h>
-
-/*
- * The main single-value unaligned transfer routines.
- *
- * Based on <asm-alpha/unaligned.h>.
- *
- * Copyright (C) 1998, 1999, 2003 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- */
-#define get_unaligned(ptr) \
- ((__typeof__(*(ptr)))ia64_get_unaligned((ptr), sizeof(*(ptr))))
-
-#define put_unaligned(x,ptr) \
- ia64_put_unaligned((unsigned long)(x), (ptr), sizeof(*(ptr)))
-
-struct __una_u64 { __u64 x __attribute__((packed)); };
-struct __una_u32 { __u32 x __attribute__((packed)); };
-struct __una_u16 { __u16 x __attribute__((packed)); };
-
-static inline unsigned long
-__uld8 (const unsigned long * addr)
-{
- const struct __una_u64 *ptr = (const struct __una_u64 *) addr;
- return ptr->x;
-}
-
-static inline unsigned long
-__uld4 (const unsigned int * addr)
-{
- const struct __una_u32 *ptr = (const struct __una_u32 *) addr;
- return ptr->x;
-}
-
-static inline unsigned long
-__uld2 (const unsigned short * addr)
-{
- const struct __una_u16 *ptr = (const struct __una_u16 *) addr;
- return ptr->x;
-}
-
-static inline void
-__ust8 (unsigned long val, unsigned long * addr)
-{
- struct __una_u64 *ptr = (struct __una_u64 *) addr;
- ptr->x = val;
-}
-
-static inline void
-__ust4 (unsigned long val, unsigned int * addr)
-{
- struct __una_u32 *ptr = (struct __una_u32 *) addr;
- ptr->x = val;
-}
-
-static inline void
-__ust2 (unsigned long val, unsigned short * addr)
-{
- struct __una_u16 *ptr = (struct __una_u16 *) addr;
- ptr->x = val;
-}
-
-
-/*
- * This function doesn't actually exist. The idea is that when someone uses the macros
- * below with an unsupported size (datatype), the linker will alert us to the problem via
- * an unresolved reference error.
- */
-extern unsigned long ia64_bad_unaligned_access_length (void);
-
-#define ia64_get_unaligned(_ptr,size) \
-({ \
- const void *__ia64_ptr = (_ptr); \
- unsigned long __ia64_val; \
- \
- switch (size) { \
- case 1: \
- __ia64_val = *(const unsigned char *) __ia64_ptr; \
- break; \
- case 2: \
- __ia64_val = __uld2((const unsigned short *)__ia64_ptr); \
- break; \
- case 4: \
- __ia64_val = __uld4((const unsigned int *)__ia64_ptr); \
- break; \
- case 8: \
- __ia64_val = __uld8((const unsigned long *)__ia64_ptr); \
- break; \
- default: \
- __ia64_val = ia64_bad_unaligned_access_length(); \
- } \
- __ia64_val; \
-})
-
-#define ia64_put_unaligned(_val,_ptr,size) \
-do { \
- const void *__ia64_ptr = (_ptr); \
- unsigned long __ia64_val = (_val); \
- \
- switch (size) { \
- case 1: \
- *(unsigned char *)__ia64_ptr = (__ia64_val); \
- break; \
- case 2: \
- __ust2(__ia64_val, (unsigned short *)__ia64_ptr); \
- break; \
- case 4: \
- __ust4(__ia64_val, (unsigned int *)__ia64_ptr); \
- break; \
- case 8: \
- __ust8(__ia64_val, (unsigned long *)__ia64_ptr); \
- break; \
- default: \
- ia64_bad_unaligned_access_length(); \
- } \
-} while (0)
+#include <asm-generic/unaligned.h>
#endif /* _ASM_IA64_UNALIGNED_H */
diff --git a/include/asm-ia64/unistd.h b/include/asm-ia64/unistd.h
index 863f3b95a0e9e..33e26c557c5c6 100644
--- a/include/asm-ia64/unistd.h
+++ b/include/asm-ia64/unistd.h
@@ -392,7 +392,7 @@ asmlinkage long sys_rt_sigaction(int sig,
* proper prototype, but we can't use __typeof__ either, because not all cond_syscall()
* declarations have prototypes at the moment.
*/
-#define cond_syscall(x) asmlinkage long x (void) __attribute__((weak,alias("sys_ni_syscall")));
+#define cond_syscall(x) asmlinkage long x (void) __attribute__((weak,alias("sys_ni_syscall")))
#endif /* !__ASSEMBLY__ */
#endif /* __KERNEL__ */
diff --git a/include/asm-m32r/bug.h b/include/asm-m32r/bug.h
index a6d1efea11644..4cc0462c15b82 100644
--- a/include/asm-m32r/bug.h
+++ b/include/asm-m32r/bug.h
@@ -1,22 +1,4 @@
#ifndef _M32R_BUG_H
#define _M32R_BUG_H
-
-#define BUG() do { \
- printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \
-} while (0)
-
-#define PAGE_BUG(page) do { BUG(); } while (0)
-
-#define BUG_ON(condition) \
- do { if (unlikely((condition)!=0)) BUG(); } while(0)
-
-#define WARN_ON(condition) do { \
- if (unlikely((condition)!=0)) { \
- printk("Badness in %s at %s:%d\n", __FUNCTION__, \
- __FILE__, __LINE__); \
- dump_stack(); \
- } \
-} while (0)
-
-#endif /* _M32R_BUG_H */
-
+#include <asm-generic/bug.h>
+#endif
diff --git a/include/asm-m32r/cacheflush.h b/include/asm-m32r/cacheflush.h
index cf65b74634111..46fc4c3251082 100644
--- a/include/asm-m32r/cacheflush.h
+++ b/include/asm-m32r/cacheflush.h
@@ -11,7 +11,7 @@ extern void _flush_cache_copyback_all(void);
#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)
-#define flush_cache_page(vma, vmaddr) do { } while (0)
+#define flush_cache_page(vma, vmaddr, pfn) do { } while (0)
#define flush_dcache_page(page) do { } while (0)
#define flush_dcache_mmap_lock(mapping) do { } while (0)
#define flush_dcache_mmap_unlock(mapping) do { } while (0)
@@ -31,7 +31,7 @@ extern void smp_flush_cache_all(void);
#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)
-#define flush_cache_page(vma, vmaddr) do { } while (0)
+#define flush_cache_page(vma, vmaddr, pfn) do { } while (0)
#define flush_dcache_page(page) do { } while (0)
#define flush_dcache_mmap_lock(mapping) do { } while (0)
#define flush_dcache_mmap_unlock(mapping) do { } while (0)
@@ -43,7 +43,7 @@ extern void smp_flush_cache_all(void);
#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)
-#define flush_cache_page(vma, vmaddr) do { } while (0)
+#define flush_cache_page(vma, vmaddr, pfn) do { } while (0)
#define flush_dcache_page(page) do { } while (0)
#define flush_dcache_mmap_lock(mapping) do { } while (0)
#define flush_dcache_mmap_unlock(mapping) do { } while (0)
diff --git a/include/asm-m32r/io.h b/include/asm-m32r/io.h
index a5d3abee0ef40..8e9e481e6996a 100644
--- a/include/asm-m32r/io.h
+++ b/include/asm-m32r/io.h
@@ -216,6 +216,17 @@ memcpy_toio(volatile void __iomem *dst, const void *src, int count)
memcpy((void __force *) dst, src, count);
}
+/*
+ * Convert a physical pointer to a virtual kernel pointer for /dev/mem
+ * access
+ */
+#define xlate_dev_mem_ptr(p) __va(p)
+
+/*
+ * Convert a virtual cached pointer to an uncached pointer
+ */
+#define xlate_dev_kmem_ptr(p) p
+
#endif /* __KERNEL__ */
#endif /* _ASM_M32R_IO_H */
diff --git a/include/asm-m32r/ipc.h b/include/asm-m32r/ipc.h
index 03aac6644b587..a46e3d9c2a3fc 100644
--- a/include/asm-m32r/ipc.h
+++ b/include/asm-m32r/ipc.h
@@ -1,35 +1 @@
-#ifndef __M32R_IPC_H__
-#define __M32R_IPC_H__
-
-/* orig : i386/ipc.h 2.6.0-test3 */
-
-/*
- * These are used to wrap system calls on x86.
- *
- * See arch/i386/kernel/sys_i386.c for ugly details..
- */
-struct ipc_kludge {
- struct msgbuf __user *msgp;
- long msgtyp;
-};
-
-#define SEMOP 1
-#define SEMGET 2
-#define SEMCTL 3
-#define SEMTIMEDOP 4
-#define MSGSND 11
-#define MSGRCV 12
-#define MSGGET 13
-#define MSGCTL 14
-#define SHMAT 21
-#define SHMDT 22
-#define SHMGET 23
-#define SHMCTL 24
-
-/* Used by the DIPC package, try and avoid reusing it */
-#define DIPC 25
-
-#define IPCCALL(version,op) ((version)<<16 | (op))
-
-#endif /* __M32R_IPC_H__ */
-
+#include <asm-generic/ipc.h>
diff --git a/include/asm-m32r/mmu.h b/include/asm-m32r/mmu.h
index 930093ac48303..9c00eb78ee502 100644
--- a/include/asm-m32r/mmu.h
+++ b/include/asm-m32r/mmu.h
@@ -1,25 +1,12 @@
#ifndef _ASM_M32R_MMU_H
#define _ASM_M32R_MMU_H
-/* $Id$ */
-
#include <linux/config.h>
#if !defined(CONFIG_MMU)
-struct mm_rblock_struct {
- int size;
- int refcount;
- void *kblock;
-};
-
-struct mm_tblock_struct {
- struct mm_rblock_struct *rblock;
- struct mm_tblock_struct *next;
-};
-
typedef struct {
- struct mm_tblock_struct tblock;
- unsigned long end_brk;
+ struct vm_list_struct *vmlist;
+ unsigned long end_brk;
} mm_context_t;
#else
@@ -32,4 +19,3 @@ typedef unsigned long mm_context_t[NR_CPUS];
#endif /* CONFIG_MMU */
#endif /* _ASM_M32R_MMU_H */
-
diff --git a/include/asm-m32r/pgalloc.h b/include/asm-m32r/pgalloc.h
index da6dd7bd75294..6da309b6fda7f 100644
--- a/include/asm-m32r/pgalloc.h
+++ b/include/asm-m32r/pgalloc.h
@@ -7,7 +7,6 @@
#include <linux/mm.h>
#include <asm/io.h>
-#include <asm/pgtable.h>
#define pmd_populate_kernel(mm, pmd, pte) \
set_pmd(pmd, __pmd(_PAGE_TABLE + __pa(pte)))
diff --git a/include/asm-m32r/pgtable-2level.h b/include/asm-m32r/pgtable-2level.h
index 8af66284b436b..861727c20e8f5 100644
--- a/include/asm-m32r/pgtable-2level.h
+++ b/include/asm-m32r/pgtable-2level.h
@@ -44,6 +44,7 @@ static inline int pgd_present(pgd_t pgd) { return 1; }
* hook is made available.
*/
#define set_pte(pteptr, pteval) (*(pteptr) = pteval)
+#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
#define set_pte_atomic(pteptr, pteval) set_pte(pteptr, pteval)
/*
* (pmds are folded into pgds so this doesnt get actually called,
@@ -60,7 +61,7 @@ static inline pmd_t *pmd_offset(pgd_t * dir, unsigned long address)
return (pmd_t *) dir;
}
-#define ptep_get_and_clear(xp) __pte(xchg(&(xp)->pte, 0))
+#define ptep_get_and_clear(mm,addr,xp) __pte(xchg(&(xp)->pte, 0))
#define pte_same(a, b) (pte_val(a) == pte_val(b))
#define pte_page(x) pfn_to_page(pte_pfn(x))
#define pte_none(x) (!pte_val(x))
diff --git a/include/asm-m32r/pgtable.h b/include/asm-m32r/pgtable.h
index d2b67741e3814..70a0eb68fdf6c 100644
--- a/include/asm-m32r/pgtable.h
+++ b/include/asm-m32r/pgtable.h
@@ -176,7 +176,7 @@ extern unsigned long empty_zero_page[1024];
/* page table for 0-4MB for everybody */
#define pte_present(x) (pte_val(x) & (_PAGE_PRESENT | _PAGE_PROTNONE))
-#define pte_clear(xp) do { set_pte(xp, __pte(0)); } while (0)
+#define pte_clear(mm,addr,xp) do { set_pte_at(mm, addr, xp, __pte(0)); } while (0)
#define pmd_none(x) (!pmd_val(x))
#define pmd_present(x) (pmd_val(x) & _PAGE_PRESENT)
@@ -282,26 +282,21 @@ static inline pte_t pte_mkwrite(pte_t pte)
return pte;
}
-static inline int ptep_test_and_clear_dirty(pte_t *ptep)
+static inline int ptep_test_and_clear_dirty(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
{
return test_and_clear_bit(_PAGE_BIT_DIRTY, ptep);
}
-static inline int ptep_test_and_clear_young(pte_t *ptep)
+static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
{
return test_and_clear_bit(_PAGE_BIT_ACCESSED, ptep);
}
-static inline void ptep_set_wrprotect(pte_t *ptep)
+static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
{
clear_bit(_PAGE_BIT_WRITE, ptep);
}
-static inline void ptep_mkdirty(pte_t *ptep)
-{
- set_bit(_PAGE_BIT_DIRTY, ptep);
-}
-
/*
* Macro and implementation to make a page protection as uncachable.
*/
@@ -386,11 +381,17 @@ static inline void pmd_set(pmd_t * pmdp, pte_t * ptep)
#define io_remap_page_range(vma, vaddr, paddr, size, prot) \
remap_pfn_range(vma, vaddr, (paddr) >> PAGE_SHIFT, size, prot)
+#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
+ remap_pfn_range(vma, vaddr, pfn, size, prot)
+
+#define MK_IOSPACE_PFN(space, pfn) (pfn)
+#define GET_IOSPACE(pfn) 0
+#define GET_PFN(pfn) (pfn)
+
#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
#define __HAVE_ARCH_PTEP_SET_WRPROTECT
-#define __HAVE_ARCH_PTEP_MKDIRTY
#define __HAVE_ARCH_PTE_SAME
#include <asm-generic/pgtable.h>
diff --git a/include/asm-m32r/serial.h b/include/asm-m32r/serial.h
index bf14299310806..d0e56b1bf4511 100644
--- a/include/asm-m32r/serial.h
+++ b/include/asm-m32r/serial.h
@@ -1,10 +1,6 @@
#ifndef _ASM_M32R_SERIAL_H
#define _ASM_M32R_SERIAL_H
-/* $Id$ */
-
-/* orig : i386 2.4.18 */
-
/*
* include/asm-m32r/serial.h
*/
@@ -21,131 +17,31 @@
*/
#define BASE_BAUD ( 1843200 / 16 )
-/* Standard COM flags (except for COM4, because of the 8514 problem) */
-#ifdef CONFIG_SERIAL_DETECT_IRQ
-#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ)
-#define STD_COM4_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_AUTO_IRQ)
-#else
+/* Standard COM flags */
#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
-#define STD_COM4_FLAGS ASYNC_BOOT_AUTOCONF
-#endif
-
-#ifdef CONFIG_SERIAL_MANY_PORTS
-#define FOURPORT_FLAGS ASYNC_FOURPORT
-#define ACCENT_FLAGS 0
-#define BOCA_FLAGS 0
-#define HUB6_FLAGS 0
-#define RS_TABLE_SIZE 64
-#else
-#define RS_TABLE_SIZE
-#endif
-
-#define MCA_COM_FLAGS (STD_COM_FLAGS|ASYNC_BOOT_ONLYMCA)
-
-/*
- * The following define the access methods for the HUB6 card. All
- * access is through two ports for all 24 possible chips. The card is
- * selected through the high 2 bits, the port on that card with the
- * "middle" 3 bits, and the register on that port with the bottom
- * 3 bits.
- *
- * While the access port and interrupt is configurable, the default
- * port locations are 0x302 for the port control register, and 0x303
- * for the data read/write register. Normally, the interrupt is at irq3
- * but can be anything from 3 to 7 inclusive. Note that using 3 will
- * require disabling com2.
- */
-
-#define C_P(card,port) (((card)<<6|(port)<<3) + 1)
-#define STD_SERIAL_PORT_DEFNS \
- /* UART CLK PORT IRQ FLAGS */ \
- { 0, BASE_BAUD, 0x3F8, 4, STD_COM_FLAGS }, /* ttyS0 */ \
- { 0, BASE_BAUD, 0x2F8, 3, STD_COM_FLAGS }, /* ttyS1 */ \
- { 0, BASE_BAUD, 0x3E8, 4, STD_COM_FLAGS }, /* ttyS2 */ \
- { 0, BASE_BAUD, 0x2E8, 3, STD_COM4_FLAGS }, /* ttyS3 */
+/* Standard PORT definitions */
+#if defined(CONFIG_PLAT_USRV)
+#define STD_SERIAL_PORT_DEFNS \
+ /* UART CLK PORT IRQ FLAGS */ \
+ { 0, BASE_BAUD, 0x3F8, PLD_IRQ_UART0, STD_COM_FLAGS }, /* ttyS0 */ \
+ { 0, BASE_BAUD, 0x2F8, PLD_IRQ_UART1, STD_COM_FLAGS }, /* ttyS1 */
-#ifdef CONFIG_SERIAL_MANY_PORTS
-#define EXTRA_SERIAL_PORT_DEFNS \
- { 0, BASE_BAUD, 0x1A0, 9, FOURPORT_FLAGS }, /* ttyS4 */ \
- { 0, BASE_BAUD, 0x1A8, 9, FOURPORT_FLAGS }, /* ttyS5 */ \
- { 0, BASE_BAUD, 0x1B0, 9, FOURPORT_FLAGS }, /* ttyS6 */ \
- { 0, BASE_BAUD, 0x1B8, 9, FOURPORT_FLAGS }, /* ttyS7 */ \
- { 0, BASE_BAUD, 0x2A0, 5, FOURPORT_FLAGS }, /* ttyS8 */ \
- { 0, BASE_BAUD, 0x2A8, 5, FOURPORT_FLAGS }, /* ttyS9 */ \
- { 0, BASE_BAUD, 0x2B0, 5, FOURPORT_FLAGS }, /* ttyS10 */ \
- { 0, BASE_BAUD, 0x2B8, 5, FOURPORT_FLAGS }, /* ttyS11 */ \
- { 0, BASE_BAUD, 0x330, 4, ACCENT_FLAGS }, /* ttyS12 */ \
- { 0, BASE_BAUD, 0x338, 4, ACCENT_FLAGS }, /* ttyS13 */ \
- { 0, BASE_BAUD, 0x000, 0, 0 }, /* ttyS14 (spare) */ \
- { 0, BASE_BAUD, 0x000, 0, 0 }, /* ttyS15 (spare) */ \
- { 0, BASE_BAUD, 0x100, 12, BOCA_FLAGS }, /* ttyS16 */ \
- { 0, BASE_BAUD, 0x108, 12, BOCA_FLAGS }, /* ttyS17 */ \
- { 0, BASE_BAUD, 0x110, 12, BOCA_FLAGS }, /* ttyS18 */ \
- { 0, BASE_BAUD, 0x118, 12, BOCA_FLAGS }, /* ttyS19 */ \
- { 0, BASE_BAUD, 0x120, 12, BOCA_FLAGS }, /* ttyS20 */ \
- { 0, BASE_BAUD, 0x128, 12, BOCA_FLAGS }, /* ttyS21 */ \
- { 0, BASE_BAUD, 0x130, 12, BOCA_FLAGS }, /* ttyS22 */ \
- { 0, BASE_BAUD, 0x138, 12, BOCA_FLAGS }, /* ttyS23 */ \
- { 0, BASE_BAUD, 0x140, 12, BOCA_FLAGS }, /* ttyS24 */ \
- { 0, BASE_BAUD, 0x148, 12, BOCA_FLAGS }, /* ttyS25 */ \
- { 0, BASE_BAUD, 0x150, 12, BOCA_FLAGS }, /* ttyS26 */ \
- { 0, BASE_BAUD, 0x158, 12, BOCA_FLAGS }, /* ttyS27 */ \
- { 0, BASE_BAUD, 0x160, 12, BOCA_FLAGS }, /* ttyS28 */ \
- { 0, BASE_BAUD, 0x168, 12, BOCA_FLAGS }, /* ttyS29 */ \
- { 0, BASE_BAUD, 0x170, 12, BOCA_FLAGS }, /* ttyS30 */ \
- { 0, BASE_BAUD, 0x178, 12, BOCA_FLAGS }, /* ttyS31 */
-#else
-#define EXTRA_SERIAL_PORT_DEFNS
-#endif
-
-/* You can have up to four HUB6's in the system, but I've only
- * included two cards here for a total of twelve ports.
- */
-#if (defined(CONFIG_HUB6) && defined(CONFIG_SERIAL_MANY_PORTS))
-#define HUB6_SERIAL_PORT_DFNS \
- { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(0,0) }, /* ttyS32 */ \
- { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(0,1) }, /* ttyS33 */ \
- { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(0,2) }, /* ttyS34 */ \
- { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(0,3) }, /* ttyS35 */ \
- { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(0,4) }, /* ttyS36 */ \
- { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(0,5) }, /* ttyS37 */ \
- { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(1,0) }, /* ttyS38 */ \
- { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(1,1) }, /* ttyS39 */ \
- { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(1,2) }, /* ttyS40 */ \
- { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(1,3) }, /* ttyS41 */ \
- { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(1,4) }, /* ttyS42 */ \
- { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(1,5) }, /* ttyS43 */
-#else
-#define HUB6_SERIAL_PORT_DFNS
-#endif
+#else /* !CONFIG_PLAT_USRV */
-#ifdef CONFIG_MCA
-#define MCA_SERIAL_PORT_DFNS \
- { 0, BASE_BAUD, 0x3220, 3, MCA_COM_FLAGS }, \
- { 0, BASE_BAUD, 0x3228, 3, MCA_COM_FLAGS }, \
- { 0, BASE_BAUD, 0x4220, 3, MCA_COM_FLAGS }, \
- { 0, BASE_BAUD, 0x4228, 3, MCA_COM_FLAGS }, \
- { 0, BASE_BAUD, 0x5220, 3, MCA_COM_FLAGS }, \
- { 0, BASE_BAUD, 0x5228, 3, MCA_COM_FLAGS },
+#if defined(CONFIG_SERIAL_M32R_PLDSIO)
+#define STD_SERIAL_PORT_DEFNS \
+ { 0, BASE_BAUD, ((unsigned long)PLD_ESIO0CR), PLD_IRQ_SIO0_RCV, \
+ STD_COM_FLAGS }, /* ttyS0 */
#else
-#define MCA_SERIAL_PORT_DFNS
+#define STD_SERIAL_PORT_DEFNS \
+ { 0, BASE_BAUD, M32R_SIO_OFFSET, M32R_IRQ_SIO0_R, \
+ STD_COM_FLAGS }, /* ttyS0 */
#endif
-#ifndef CONFIG_PLAT_USRV
-#define SERIAL_PORT_DFNS \
- STD_SERIAL_PORT_DEFNS \
- EXTRA_SERIAL_PORT_DEFNS \
- HUB6_SERIAL_PORT_DFNS \
- MCA_SERIAL_PORT_DFNS
-
-#else /* CONFIG_PLAT_USRV */
+#endif /* !CONFIG_PLAT_USRV */
-#define SERIAL_PORT_DFNS \
- /* UART CLK PORT IRQ FLAGS */ \
- { 0, BASE_BAUD, 0x3F8, PLD_IRQ_UART0, STD_COM_FLAGS }, /* ttyS0 */ \
- { 0, BASE_BAUD, 0x2F8, PLD_IRQ_UART1, STD_COM_FLAGS }, /* ttyS1 */
-#endif /* CONFIG_PLAT_USRV */
+#define SERIAL_PORT_DFNS STD_SERIAL_PORT_DEFNS
#endif /* _ASM_M32R_SERIAL_H */
diff --git a/include/asm-m32r/spinlock.h b/include/asm-m32r/spinlock.h
index ecf80b74d2c11..6608d8371c508 100644
--- a/include/asm-m32r/spinlock.h
+++ b/include/asm-m32r/spinlock.h
@@ -102,10 +102,8 @@ static inline void _raw_spin_lock(spinlock_t *lock)
unsigned long tmp0, tmp1;
#ifdef CONFIG_DEBUG_SPINLOCK
- __label__ here;
-here:
- if (lock->magic != SPINLOCK_MAGIC) {
- printk("pc: %p\n", &&here);
+ if (unlikely(lock->magic != SPINLOCK_MAGIC)) {
+ printk("pc: %p\n", __builtin_return_address(0));
BUG();
}
#endif
diff --git a/include/asm-m32r/system.h b/include/asm-m32r/system.h
index 5828af7d41220..73348c3f858b6 100644
--- a/include/asm-m32r/system.h
+++ b/include/asm-m32r/system.h
@@ -294,4 +294,6 @@ static __inline__ unsigned long __xchg(unsigned long x, volatile void * ptr,
#define set_mb(var, value) do { xchg(&var, value); } while (0)
#define set_wmb(var, value) do { var = value; wmb(); } while (0)
+#define arch_align_stack(x) (x)
+
#endif /* _ASM_M32R_SYSTEM_H */
diff --git a/include/asm-m32r/timex.h b/include/asm-m32r/timex.h
index e102aaf675a99..abf12e7ffbf35 100644
--- a/include/asm-m32r/timex.h
+++ b/include/asm-m32r/timex.h
@@ -25,8 +25,6 @@
typedef unsigned long long cycles_t;
-extern cycles_t cacheflush_time;
-
static __inline__ cycles_t get_cycles (void)
{
return 0;
diff --git a/include/asm-m32r/uaccess.h b/include/asm-m32r/uaccess.h
index 58530a34cecbc..bbb8ac4018a07 100644
--- a/include/asm-m32r/uaccess.h
+++ b/include/asm-m32r/uaccess.h
@@ -121,7 +121,8 @@ static inline int access_ok(int type, const void *addr, unsigned long size)
#endif /* CONFIG_MMU */
/**
- * verify_area: - Obsolete, use access_ok()
+ * verify_area: - Obsolete/deprecated and will go away soon,
+ * use access_ok() instead.
* @type: Type of access: %VERIFY_READ or %VERIFY_WRITE
* @addr: User space pointer to start of block to check
* @size: Size of block to check
@@ -137,7 +138,7 @@ static inline int access_ok(int type, const void *addr, unsigned long size)
*
* See access_ok() for more details.
*/
-static inline int verify_area(int type, const void __user *addr,
+static inline int __deprecated verify_area(int type, const void __user *addr,
unsigned long size)
{
return access_ok(type, addr, size) ? 0 : -EFAULT;
diff --git a/include/asm-m32r/unistd.h b/include/asm-m32r/unistd.h
index f71dfa15db747..8552d8f45ab10 100644
--- a/include/asm-m32r/unistd.h
+++ b/include/asm-m32r/unistd.h
@@ -468,7 +468,7 @@ asmlinkage long sys_rt_sigaction(int sig,
* but it doesn't work on all toolchains, so we just do it by hand
*/
#ifndef cond_syscall
-#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
+#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
#endif
#endif /* _ASM_M32R_UNISTD_H */
diff --git a/include/asm-m68k/cacheflush.h b/include/asm-m68k/cacheflush.h
index 3b2e5205b50cb..e4773946f10dc 100644
--- a/include/asm-m68k/cacheflush.h
+++ b/include/asm-m68k/cacheflush.h
@@ -99,8 +99,7 @@ static inline void flush_cache_range(struct vm_area_struct *vma,
__flush_cache_030();
}
-static inline void flush_cache_page(struct vm_area_struct *vma,
- unsigned long vmaddr)
+static inline void flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr, unsigned long pfn)
{
if (vma->vm_mm == current->mm)
__flush_cache_030();
@@ -134,15 +133,15 @@ static inline void __flush_page_to_ram(void *vaddr)
#define flush_icache_user_range(vma,pg,adr,len) do { } while (0)
#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
- do { \
- flush_cache_page(vma, vaddr); \
- memcpy(dst, src, len); \
+ do { \
+ flush_cache_page(vma, vaddr, page_to_pfn(page));\
+ memcpy(dst, src, len); \
} while (0)
#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
- do { \
- flush_cache_page(vma, vaddr); \
- memcpy(dst, src, len); \
+ do { \
+ flush_cache_page(vma, vaddr, page_to_pfn(page));\
+ memcpy(dst, src, len); \
} while (0)
extern void flush_icache_range(unsigned long address, unsigned long endaddr);
diff --git a/include/asm-m68k/checksum.h b/include/asm-m68k/checksum.h
index c0d6516958128..78860c20db01b 100644
--- a/include/asm-m68k/checksum.h
+++ b/include/asm-m68k/checksum.h
@@ -43,20 +43,21 @@ static inline unsigned short
ip_fast_csum(unsigned char *iph, unsigned int ihl)
{
unsigned int sum = 0;
+ unsigned long tmp;
__asm__ ("subqw #1,%2\n"
"1:\t"
- "movel %1@+,%/d0\n\t"
- "addxl %/d0,%0\n\t"
+ "movel %1@+,%3\n\t"
+ "addxl %3,%0\n\t"
"dbra %2,1b\n\t"
- "movel %0,%/d0\n\t"
- "swap %/d0\n\t"
- "addxw %/d0,%0\n\t"
- "clrw %/d0\n\t"
- "addxw %/d0,%0\n\t"
- : "=d" (sum), "=a" (iph), "=d" (ihl)
+ "movel %0,%3\n\t"
+ "swap %3\n\t"
+ "addxw %3,%0\n\t"
+ "clrw %3\n\t"
+ "addxw %3,%0\n\t"
+ : "=d" (sum), "=&a" (iph), "=&d" (ihl), "=&d" (tmp)
: "0" (sum), "1" (iph), "2" (ihl)
- : "d0");
+ : "memory");
return ~sum;
}
@@ -72,31 +73,31 @@ static inline unsigned int csum_fold(unsigned int sum)
"clrw %1\n\t"
"addxw %1, %0"
: "=&d" (sum), "=&d" (tmp)
- : "0" (sum), "1" (sum));
+ : "0" (sum), "1" (tmp));
return ~sum;
}
-/*
- * computes the checksum of the TCP/UDP pseudo-header
- * returns a 16-bit checksum, already complemented
- */
-
static inline unsigned int
csum_tcpudp_nofold(unsigned long saddr, unsigned long daddr, unsigned short len,
unsigned short proto, unsigned int sum)
{
- __asm__ ("addl %1,%0\n\t"
+ __asm__ ("addl %2,%0\n\t"
+ "addxl %3,%0\n\t"
"addxl %4,%0\n\t"
- "addxl %5,%0\n\t"
"clrl %1\n\t"
"addxl %1,%0"
- : "=&d" (sum), "=&d" (saddr)
- : "0" (daddr), "1" (saddr), "d" (len + proto),
- "d"(sum));
+ : "=&d" (sum), "=d" (saddr)
+ : "g" (daddr), "1" (saddr), "d" (len + proto),
+ "0" (sum));
return sum;
}
+
+/*
+ * computes the checksum of the TCP/UDP pseudo-header
+ * returns a 16-bit checksum, already complemented
+ */
static inline unsigned short int
csum_tcpudp_magic(unsigned long saddr, unsigned long daddr, unsigned short len,
unsigned short proto, unsigned int sum)
diff --git a/include/asm-m68k/io.h b/include/asm-m68k/io.h
index c963b138a142b..6bb8b0d8f99d1 100644
--- a/include/asm-m68k/io.h
+++ b/include/asm-m68k/io.h
@@ -359,4 +359,18 @@ extern void dma_cache_inv(unsigned long start, unsigned long size);
#endif
#endif /* __KERNEL__ */
+
+#define __ARCH_HAS_NO_PAGE_ZERO_MAPPED 1
+
+/*
+ * Convert a physical pointer to a virtual kernel pointer for /dev/mem
+ * access
+ */
+#define xlate_dev_mem_ptr(p) __va(p)
+
+/*
+ * Convert a virtual cached pointer to an uncached pointer
+ */
+#define xlate_dev_kmem_ptr(p) p
+
#endif /* _IO_H */
diff --git a/include/asm-m68k/ipc.h b/include/asm-m68k/ipc.h
index 19e9cbe3f2661..a46e3d9c2a3fc 100644
--- a/include/asm-m68k/ipc.h
+++ b/include/asm-m68k/ipc.h
@@ -1,31 +1 @@
-#ifndef __m68k_IPC_H__
-#define __m68k_IPC_H__
-
-/*
- * These are used to wrap system calls on m68k.
- *
- * See arch/m68k/kernel/sys_m68k.c for ugly details..
- */
-struct ipc_kludge {
- struct msgbuf *msgp;
- long msgtyp;
-};
-
-#define SEMOP 1
-#define SEMGET 2
-#define SEMCTL 3
-#define MSGSND 11
-#define MSGRCV 12
-#define MSGGET 13
-#define MSGCTL 14
-#define SHMAT 21
-#define SHMDT 22
-#define SHMGET 23
-#define SHMCTL 24
-
-/* Used by the DIPC package, try and avoid reusing it */
-#define DIPC 25
-
-#define IPCCALL(version,op) ((version)<<16 | (op))
-
-#endif
+#include <asm-generic/ipc.h>
diff --git a/include/asm-m68k/motorola_pgtable.h b/include/asm-m68k/motorola_pgtable.h
index f9391dfbb7102..1628723458f5b 100644
--- a/include/asm-m68k/motorola_pgtable.h
+++ b/include/asm-m68k/motorola_pgtable.h
@@ -129,7 +129,7 @@ static inline void pgd_set(pgd_t *pgdp, pmd_t *pmdp)
#define pte_none(pte) (!pte_val(pte))
#define pte_present(pte) (pte_val(pte) & (_PAGE_PRESENT | _PAGE_PROTNONE))
-#define pte_clear(ptep) ({ pte_val(*(ptep)) = 0; })
+#define pte_clear(mm,addr,ptep) ({ pte_val(*(ptep)) = 0; })
#define pte_page(pte) (mem_map + ((unsigned long)(__va(pte_val(pte)) - PAGE_OFFSET) >> PAGE_SHIFT))
#define pte_pfn(pte) (pte_val(pte) >> PAGE_SHIFT)
diff --git a/include/asm-m68k/pgtable.h b/include/asm-m68k/pgtable.h
index 05b3d68cb2617..0eef32778df25 100644
--- a/include/asm-m68k/pgtable.h
+++ b/include/asm-m68k/pgtable.h
@@ -26,6 +26,7 @@
do{ \
*(pteptr) = (pteval); \
} while(0)
+#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
/* PMD_SHIFT determines the size of the area a second-level page table can map */
@@ -143,6 +144,13 @@ static inline void update_mmu_cache(struct vm_area_struct *vma,
#define io_remap_page_range(vma, vaddr, paddr, size, prot) \
remap_pfn_range(vma, vaddr, (paddr) >> PAGE_SHIFT, size, prot)
+#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
+ remap_pfn_range(vma, vaddr, pfn, size, prot)
+
+#define MK_IOSPACE_PFN(space, pfn) (pfn)
+#define GET_IOSPACE(pfn) 0
+#define GET_PFN(pfn) (pfn)
+
/* MMU-specific headers */
#ifdef CONFIG_SUN3
diff --git a/include/asm-m68k/processor.h b/include/asm-m68k/processor.h
index db174ce801dd4..df1575db32afb 100644
--- a/include/asm-m68k/processor.h
+++ b/include/asm-m68k/processor.h
@@ -62,7 +62,8 @@ struct task_work {
char need_resched;
unsigned char delayed_trace; /* single step a syscall */
unsigned char syscall_trace; /* count of syscall interceptors */
- unsigned char pad[3];
+ unsigned char memdie; /* task was selected to be killed */
+ unsigned char pad[2];
};
struct thread_struct {
diff --git a/include/asm-m68k/signal.h b/include/asm-m68k/signal.h
index 5f8fd935977a5..6681bb6a5523d 100644
--- a/include/asm-m68k/signal.h
+++ b/include/asm-m68k/signal.h
@@ -213,7 +213,7 @@ static inline int sigfindinword(unsigned long word)
return word ^ 31;
}
-#define HAVE_ARCH_GET_SIGNAL_TO_DELIVER
+extern void ptrace_signal_deliver(struct pt_regs *regs, void *cookie);
#endif /* __KERNEL__ */
diff --git a/include/asm-m68k/sun3_pgtable.h b/include/asm-m68k/sun3_pgtable.h
index e5485e830bd74..e974bb072047b 100644
--- a/include/asm-m68k/sun3_pgtable.h
+++ b/include/asm-m68k/sun3_pgtable.h
@@ -123,7 +123,10 @@ static inline void pgd_set(pgd_t *pgdp, pmd_t *pmdp)
static inline int pte_none (pte_t pte) { return !pte_val (pte); }
static inline int pte_present (pte_t pte) { return pte_val (pte) & SUN3_PAGE_VALID; }
-static inline void pte_clear (pte_t *ptep) { pte_val (*ptep) = 0; }
+static inline void pte_clear (struct mm_struct *mm, unsigned long addr, pte_t *ptep)
+{
+ pte_val (*ptep) = 0;
+}
#define pte_pfn(pte) (pte_val(pte) & SUN3_PAGE_PGNUM_MASK)
#define pfn_pte(pfn, pgprot) \
diff --git a/include/asm-m68k/system.h b/include/asm-m68k/system.h
index f0f36fca11bb7..64d3481df74c6 100644
--- a/include/asm-m68k/system.h
+++ b/include/asm-m68k/system.h
@@ -194,6 +194,8 @@ static inline unsigned long __cmpxchg(volatile void *p, unsigned long old,
(unsigned long)(n),sizeof(*(ptr))))
#endif
+#define arch_align_stack(x) (x)
+
#endif /* __KERNEL__ */
#endif /* _M68K_SYSTEM_H */
diff --git a/include/asm-m68k/thread_info.h b/include/asm-m68k/thread_info.h
index 9de3c930ccbf1..5f58939c59db7 100644
--- a/include/asm-m68k/thread_info.h
+++ b/include/asm-m68k/thread_info.h
@@ -68,6 +68,9 @@ extern int thread_flag_fixme(void);
case TIF_SYSCALL_TRACE: \
tsk->thread.work.syscall_trace = val; \
break; \
+ case TIF_MEMDIE: \
+ tsk->thread.work.memdie = val; \
+ break; \
default: \
thread_flag_fixme(); \
} \
@@ -85,6 +88,9 @@ extern int thread_flag_fixme(void);
case TIF_SYSCALL_TRACE: \
___res = tsk->thread.work.syscall_trace;\
break; \
+ case TIF_MEMDIE: \
+ ___res = tsk->thread.work.memdie;\
+ break; \
default: \
___res = thread_flag_fixme(); \
} \
diff --git a/include/asm-m68k/uaccess.h b/include/asm-m68k/uaccess.h
index 38388dc47ec83..605e6cb811f80 100644
--- a/include/asm-m68k/uaccess.h
+++ b/include/asm-m68k/uaccess.h
@@ -14,9 +14,10 @@
/* We let the MMU do all checking */
#define access_ok(type,addr,size) 1
-static inline int verify_area(int type, const void *addr, unsigned long size)
+/* this function will go away soon - use access_ok() instead */
+static inline int __deprecated verify_area(int type, const void *addr, unsigned long size)
{
- return access_ok(type,addr,size)?0:-EFAULT;
+ return access_ok(type,addr,size) ? 0 : -EFAULT;
}
/*
diff --git a/include/asm-m68k/unistd.h b/include/asm-m68k/unistd.h
index 4795f611f03bb..cbabde4f8a45b 100644
--- a/include/asm-m68k/unistd.h
+++ b/include/asm-m68k/unistd.h
@@ -460,6 +460,6 @@ asmlinkage long sys_rt_sigaction(int sig,
* What we want is __attribute__((weak,alias("sys_ni_syscall"))),
* but it doesn't work on all toolchains, so we just do it by hand
*/
-#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
+#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
#endif /* _ASM_M68K_UNISTD_H_ */
diff --git a/include/asm-m68knommu/cacheflush.h b/include/asm-m68knommu/cacheflush.h
index f7182c4c876f7..aa7a2ffa41af1 100644
--- a/include/asm-m68knommu/cacheflush.h
+++ b/include/asm-m68knommu/cacheflush.h
@@ -9,7 +9,7 @@
#define flush_cache_all() __flush_cache_all()
#define flush_cache_mm(mm) do { } while (0)
#define flush_cache_range(vma, start, end) do { } while (0)
-#define flush_cache_page(vma, vmaddr) do { } while (0)
+#define flush_cache_page(vma, vmaddr, pfn) do { } while (0)
#define flush_dcache_range(start,len) do { } while (0)
#define flush_dcache_page(page) do { } while (0)
#define flush_dcache_mmap_lock(mapping) do { } while (0)
diff --git a/include/asm-m68knommu/entry.h b/include/asm-m68knommu/entry.h
index 7d9b3ddd3994d..06f5aa70b0b52 100644
--- a/include/asm-m68knommu/entry.h
+++ b/include/asm-m68knommu/entry.h
@@ -22,8 +22,9 @@
* 24(sp) - orig_d0
* 28(sp) - stack adjustment
* 2C(sp) - [ sr ] [ format & vector ]
- * 2E(sp) - [ pc ] [ sr ]
- * 30(sp) - [ format & vector ] [ pc ]
+ * 2E(sp) - [ pc-hiword ] [ sr ]
+ * 30(sp) - [ pc-loword ] [ pc-hiword ]
+ * 32(sp) - [ format & vector ] [ pc-loword ]
* ^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^
* M68K COLDFIRE
*/
@@ -42,12 +43,6 @@ PF_DTRACE_BIT = 5
LENOSYS = 38
-LD0 = 0x20
-LORIG_D0 = 0x24
-LFORMATVEC = 0x2c
-LSR = 0x2e
-LPC = 0x30
-
#define SWITCH_STACK_SIZE (6*4+4) /* Includes return address */
/*
@@ -72,36 +67,36 @@ LPC = 0x30
addql #8,sw_usp /* remove exception */
movel sw_ksp,%sp /* kernel sp */
subql #8,%sp /* room for exception */
- clrl %sp@- /* stk_adj */
+ clrl %sp@- /* stkadj */
movel %d0,%sp@- /* orig d0 */
movel %d0,%sp@- /* d0 */
- subl #32,%sp /* space for 8 regs */
+ lea %sp@(-32),%sp /* space for 8 regs */
moveml %d1-%d5/%a0-%a2,%sp@
movel sw_usp,%a0 /* get usp */
- moveml %a0@(-8),%d1-%d2 /* get exception */
- moveml %d1-%d2,%sp@(LFORMATVEC) /* copy exception */
+ movel %a0@-,%sp@(PT_PC) /* copy exception program counter */
+ movel %a0@-,%sp@(PT_FORMATVEC)/* copy exception format/vector/sr */
bra 7f
6:
- clrl %sp@- /* stk_adj */
+ clrl %sp@- /* stkadj */
movel %d0,%sp@- /* orig d0 */
movel %d0,%sp@- /* d0 */
- subl #32,%sp /* space for 7 regs */
+ lea %sp@(-32),%sp /* space for 8 regs */
moveml %d1-%d5/%a0-%a2,%sp@
7:
.endm
.macro RESTORE_ALL
- btst #5,%sp@(LSR) /* going user? */
+ btst #5,%sp@(PT_SR) /* going user? */
bnes 8f /* no, skip */
move #0x2700,%sr /* disable intrs */
movel sw_usp,%a0 /* get usp */
- moveml %sp@(LFORMATVEC),%d1-%d2 /* copy exception */
- moveml %d1-%d2,%a0@(-8)
+ movel %sp@(PT_PC),%a0@- /* copy exception program counter */
+ movel %sp@(PT_FORMATVEC),%a0@-/* copy exception format/vector/sr */
moveml %sp@,%d1-%d5/%a0-%a2
- addl #32,%sp /* space for 8 regs */
+ lea %sp@(32),%sp /* space for 8 regs */
movel %sp@+,%d0
addql #4,%sp /* orig d0 */
- addl %sp@+,%sp /* stk adj */
+ addl %sp@+,%sp /* stkadj */
addql #8,%sp /* remove exception */
movel %sp,sw_ksp /* save ksp */
subql #8,sw_usp /* set exception */
@@ -109,10 +104,10 @@ LPC = 0x30
rte
8:
moveml %sp@,%d1-%d5/%a0-%a2
- addl #32,%sp /* space for 8 regs */
+ lea %sp@(32),%sp /* space for 8 regs */
movel %sp@+,%d0
addql #4,%sp /* orig d0 */
- addl %sp@+,%sp /* stk adj */
+ addl %sp@+,%sp /* stkadj */
rte
.endm
@@ -121,30 +116,30 @@ LPC = 0x30
*/
.macro SAVE_LOCAL
move #0x2700,%sr /* disable intrs */
- clrl %sp@- /* stk_adj */
+ clrl %sp@- /* stkadj */
movel %d0,%sp@- /* orig d0 */
movel %d0,%sp@- /* d0 */
- subl #32,%sp /* space for 8 regs */
+ lea %sp@(-32),%sp /* space for 8 regs */
moveml %d1-%d5/%a0-%a2,%sp@
.endm
.macro RESTORE_LOCAL
moveml %sp@,%d1-%d5/%a0-%a2
- addl #32,%sp /* space for 8 regs */
+ lea %sp@(32),%sp /* space for 8 regs */
movel %sp@+,%d0
addql #4,%sp /* orig d0 */
- addl %sp@+,%sp /* stk adj */
+ addl %sp@+,%sp /* stkadj */
rte
.endm
.macro SAVE_SWITCH_STACK
- subl #24,%sp /* 6 regs */
+ lea %sp@(-24),%sp /* 6 regs */
moveml %a3-%a6/%d6-%d7,%sp@
.endm
.macro RESTORE_SWITCH_STACK
moveml %sp@,%a3-%a6/%d6-%d7
- addl #24,%sp /* 6 regs */
+ lea %sp@(24),%sp /* 6 regs */
.endm
/*
@@ -161,7 +156,7 @@ LPC = 0x30
* Standard 68k interrupt entry and exit macros.
*/
.macro SAVE_ALL
- clrl %sp@- /* stk_adj */
+ clrl %sp@- /* stkadj */
movel %d0,%sp@- /* orig d0 */
movel %d0,%sp@- /* d0 */
moveml %d1-%d5/%a0-%a2,%sp@-
@@ -171,7 +166,7 @@ LPC = 0x30
moveml %sp@+,%a0-%a2/%d1-%d5
movel %sp@+,%d0
addql #4,%sp /* orig d0 */
- addl %sp@+,%sp /* stk adj */
+ addl %sp@+,%sp /* stkadj */
rte
.endm
diff --git a/include/asm-m68knommu/io.h b/include/asm-m68knommu/io.h
index e14f03e3ac1e8..30fade4149b81 100644
--- a/include/asm-m68knommu/io.h
+++ b/include/asm-m68knommu/io.h
@@ -187,6 +187,17 @@ extern void iounmap(void *addr);
#define virt_to_bus virt_to_phys
#define bus_to_virt phys_to_virt
+/*
+ * Convert a physical pointer to a virtual kernel pointer for /dev/mem
+ * access
+ */
+#define xlate_dev_mem_ptr(p) __va(p)
+
+/*
+ * Convert a virtual cached pointer to an uncached pointer
+ */
+#define xlate_dev_kmem_ptr(p) p
+
#endif /* __KERNEL__ */
#endif /* _M68KNOMMU_IO_H */
diff --git a/include/asm-m68knommu/io_hw_swap.h b/include/asm-m68knommu/io_hw_swap.h
deleted file mode 100644
index b573e9fdc2e9d..0000000000000
--- a/include/asm-m68knommu/io_hw_swap.h
+++ /dev/null
@@ -1,113 +0,0 @@
-#ifndef _M68K_IO_HW_SWAP_H
-#define _M68K_IO_HW_SWAP_H
-
-/*
- * swap functions are sometimes needed to interface little-endian hardware
- */
-static inline unsigned short _swapw(volatile unsigned short v)
-{
- return ((v << 8) | (v >> 8));
-}
-
-static inline unsigned int _swapl(volatile unsigned long v)
-{
- return ((v << 24) | ((v & 0xff00) << 8) | ((v & 0xff0000) >> 8) | (v >> 24));
-}
-
-/*
- * readX/writeX() are used to access memory mapped devices. On some
- * architectures the memory mapped IO stuff needs to be accessed
- * differently. On the m68k architecture, we just read/write the
- * memory location directly.
- */
-/* ++roman: The assignments to temp. vars avoid that gcc sometimes generates
- * two accesses to memory, which may be undesireable for some devices.
- */
-#define readb(addr) \
- ({ unsigned char __v = (*(volatile unsigned char *) (addr)); __v; })
-#define readw(addr) \
- ({ unsigned short __v = (*(volatile unsigned short *) (addr)); __v; })
-#define readl(addr) \
- ({ unsigned int __v = (*(volatile unsigned int *) (addr)); __v; })
-
-#define writeb(b,addr) ((*(volatile unsigned char *) (addr)) = (b))
-#define writew(b,addr) ((*(volatile unsigned short *) (addr)) = (b))
-#define writel(b,addr) ((*(volatile unsigned int *) (addr)) = (b))
-
-/* There is no difference between I/O and memory on 68k, these are the same */
-#define inb(addr) \
- ({ unsigned char __v = (*(volatile unsigned char *) (addr)); __v; })
-#define inw(addr) \
- ({ unsigned short __v = (*(volatile unsigned short *) (addr)); \
- _swapw(__v); })
-#define inl(addr) \
- ({ unsigned int __v = (*(volatile unsigned int *) (addr)); _swapl(__v); })
-
-#define outb(b,addr) ((*(volatile unsigned char *) (addr)) = (b))
-#define outw(b,addr) ((*(volatile unsigned short *) (addr)) = (_swapw(b)))
-#define outl(b,addr) ((*(volatile unsigned int *) (addr)) = (_swapl(b)))
-
-/* FIXME: these need to be optimized. Watch out for byte swapping, they
- * are used mostly for Intel devices... */
-#define outsw(addr,buf,len) \
- ({ unsigned short * __p = (unsigned short *)(buf); \
- unsigned short * __e = (unsigned short *)(__p) + (len); \
- while (__p < __e) { \
- *(volatile unsigned short *)(addr) = *__p++;\
- } \
- })
-
-#define insw(addr,buf,len) \
- ({ unsigned short * __p = (unsigned short *)(buf); \
- unsigned short * __e = (unsigned short *)(__p) + (len); \
- while (__p < __e) { \
- *(__p++) = *(volatile unsigned short *)(addr); \
- } \
- })
-
-
-static inline unsigned char get_user_byte_io(const char * addr)
-{
- register unsigned char _v;
-
- __asm__ __volatile__ ("moveb %1,%0":"=dm" (_v):"m" (*addr));
- return _v;
-}
-#define inb_p(addr) get_user_byte_io((char *)(addr))
-
-static inline void put_user_byte_io(char val,char *addr)
-{
- __asm__ __volatile__ ("moveb %0,%1"
- : /* no outputs */
- :"idm" (val),"m" (*addr)
- : "memory");
-}
-#define outb_p(x,addr) put_user_byte_io((x),(char *)(addr))
-
-/*
- * Change virtual addresses to physical addresses and vv.
- * These are trivial on the 1:1 Linux/i386 mapping (but if we ever
- * make the kernel segment mapped at 0, we need to do translation
- * on the i386 as well)
- */
-extern unsigned long mm_vtop(unsigned long addr);
-extern unsigned long mm_ptov(unsigned long addr);
-
-extern inline unsigned long virt_to_phys(volatile void * address)
-{
- return (unsigned long) mm_vtop((unsigned long)address);
-}
-
-extern inline void * phys_to_virt(unsigned long address)
-{
- return (void *) mm_ptov(address);
-}
-
-/*
- * IO bus memory addresses are also 1:1 with the physical address
- */
-#define virt_to_bus virt_to_phys
-#define bus_to_virt phys_to_virt
-
-
-#endif /* _M68K_IO_HW_SWAP_H */
diff --git a/include/asm-m68knommu/ipc.h b/include/asm-m68knommu/ipc.h
index d66c4b2194006..a46e3d9c2a3fc 100644
--- a/include/asm-m68knommu/ipc.h
+++ b/include/asm-m68knommu/ipc.h
@@ -1 +1 @@
-#include <asm-m68k/ipc.h>
+#include <asm-generic/ipc.h>
diff --git a/include/asm-m68knommu/kmap_types.h b/include/asm-m68knommu/kmap_types.h
index 82431edeb2a10..bfb6707575d1a 100644
--- a/include/asm-m68knommu/kmap_types.h
+++ b/include/asm-m68knommu/kmap_types.h
@@ -1,5 +1,5 @@
-#ifndef _ASM_KMAP_TYPES_H
-#define _ASM_KMAP_TYPES_H
+#ifndef __ASM_M68K_KMAP_TYPES_H
+#define __ASM_M68K_KMAP_TYPES_H
enum km_type {
KM_BOUNCE_READ,
@@ -13,6 +13,8 @@ enum km_type {
KM_PTE1,
KM_IRQ0,
KM_IRQ1,
+ KM_SOFTIRQ0,
+ KM_SOFTIRQ1,
KM_TYPE_NR
};
diff --git a/include/asm-m68knommu/mcfcache.h b/include/asm-m68knommu/mcfcache.h
index 136587b6ae60b..bdd8c53ef34ce 100644
--- a/include/asm-m68knommu/mcfcache.h
+++ b/include/asm-m68knommu/mcfcache.h
@@ -15,14 +15,14 @@
/*
* The different ColdFire families have different cache arrangments.
- * Everything from a small linstruction only cache, to configurable
+ * Everything from a small instruction only cache, to configurable
* data and/or instruction cache, to unified instruction/data, to
* harvard style separate instruction and data caches.
*/
#if defined(CONFIG_M5206) || defined(CONFIG_M5206e) || defined(CONFIG_M5272)
/*
- * Simple verion 2 core cache. These have instruction cache only,
+ * Simple version 2 core cache. These have instruction cache only,
* we just need to invalidate it and enable it.
*/
.macro CACHE_ENABLE
@@ -98,7 +98,7 @@
#if defined(CONFIG_M5407)
/*
- * Version 4 cores have a true hardvard style separate instruction
+ * Version 4 cores have a true harvard style separate instruction
* and data cache. Invalidate and enable cache, also enable write
* buffers and branch accelerator.
*/
diff --git a/include/asm-m68knommu/mmu.h b/include/asm-m68knommu/mmu.h
index 9a9c7bbca2a08..5fa6b68353bab 100644
--- a/include/asm-m68knommu/mmu.h
+++ b/include/asm-m68knommu/mmu.h
@@ -3,19 +3,8 @@
/* Copyright (C) 2002, David McCullough <davidm@snapgear.com> */
-struct mm_rblock_struct {
- int size;
- int refcount;
- void *kblock;
-};
-
-struct mm_tblock_struct {
- struct mm_rblock_struct *rblock;
- struct mm_tblock_struct *next;
-};
-
typedef struct {
- struct mm_tblock_struct tblock;
+ struct vm_list_struct *vmlist;
unsigned long end_brk;
} mm_context_t;
diff --git a/include/asm-m68knommu/page.h b/include/asm-m68knommu/page.h
index a7b5c261addf8..05e03df0ec290 100644
--- a/include/asm-m68knommu/page.h
+++ b/include/asm-m68knommu/page.h
@@ -13,12 +13,6 @@
#include <asm/setup.h>
-#if !defined(CONFIG_SMALL_TASKS) && PAGE_SHIFT < 13
-#define THREAD_SIZE (8192)
-#else
-#define THREAD_SIZE PAGE_SIZE
-#endif
-
#ifndef __ASSEMBLY__
#define get_user_page(vaddr) __get_free_page(GFP_KERNEL)
diff --git a/include/asm-m68knommu/pgtable.h b/include/asm-m68knommu/pgtable.h
index 48980c21b67b7..e2a69fffa3708 100644
--- a/include/asm-m68knommu/pgtable.h
+++ b/include/asm-m68knommu/pgtable.h
@@ -59,6 +59,13 @@ extern int is_in_rom(unsigned long);
#define io_remap_page_range(vma, vaddr, paddr, size, prot) \
remap_pfn_range(vma, vaddr, (paddr) >> PAGE_SHIFT, size, prot)
+#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
+ remap_pfn_range(vma, vaddr, pfn, size, prot)
+
+#define MK_IOSPACE_PFN(space, pfn) (pfn)
+#define GET_IOSPACE(pfn) 0
+#define GET_PFN(pfn) (pfn)
+
/*
* All 32bit addresses are effectively valid for vmalloc...
* Sort of meaningless for non-VM targets.
diff --git a/include/asm-m68knommu/semp3.h b/include/asm-m68knommu/semp3.h
deleted file mode 100644
index 3e59810c71342..0000000000000
--- a/include/asm-m68knommu/semp3.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/****************************************************************************/
-
-/*
- * semp.h -- SecureEdge MP3 hardware platform support.
- *
- * (C) Copyright 2001-2002, Greg Ungerer (gerg@snapgear.com).
- */
-
-/****************************************************************************/
-#ifndef semp3_h
-#define semp3_h
-/****************************************************************************/
-
-#include <linux/config.h>
-
-/****************************************************************************/
-#ifdef CONFIG_SECUREEDGEMP3
-/****************************************************************************/
-
-#include <asm/coldfire.h>
-#include <asm/mcfsim.h>
-
-/*
- * The ColdFire UARTs do not have any support for DTR/DCD lines.
- * We have wired them onto some of the parallel IO lines.
- */
-#define MCFPP_DCD1 0x0004
-#define MCFPP_DCD0 0x0000 /* No DCD line on port 0 */
-#define MCFPP_DTR1 0x0080
-#define MCFPP_DTR0 0x0000 /* No DTR line on port 0 */
-
-
-#ifndef __ASSEMBLY__
-
-extern volatile unsigned short ppdata;
-
-/*
- * These functions defined to give quasi generic access to the
- * PPIO bits used for DTR/DCD.
- */
-static __inline__ unsigned int mcf_getppdata(void)
-{
- volatile unsigned short *pp;
- pp = (volatile unsigned short *) (MCF_MBAR + MCFSIM_PADAT);
- return((unsigned int) *pp);
-}
-
-static __inline__ void mcf_setppdata(unsigned int mask, unsigned int bits)
-{
- volatile unsigned short *pp;
- pp = (volatile unsigned short *) (MCF_MBAR + MCFSIM_PADAT);
- ppdata = (ppdata & ~mask) | bits;
- *pp = ppdata;
-}
-#endif
-
-/****************************************************************************/
-#endif /* CONFIG_SECUREEDGEMP3 */
-/****************************************************************************/
-#endif /* semp3_h */
diff --git a/include/asm-m68knommu/system.h b/include/asm-m68knommu/system.h
index ce3f0b0226df1..c341b66c147b6 100644
--- a/include/asm-m68knommu/system.h
+++ b/include/asm-m68knommu/system.h
@@ -281,5 +281,6 @@ cmpxchg(volatile int *p, int old, int new)
})
#endif
#endif
+#define arch_align_stack(x) (x)
#endif /* _M68KNOMMU_SYSTEM_H */
diff --git a/include/asm-m68knommu/thread_info.h b/include/asm-m68knommu/thread_info.h
index cedf441d375ec..c8153b7c1f5ce 100644
--- a/include/asm-m68knommu/thread_info.h
+++ b/include/asm-m68knommu/thread_info.h
@@ -15,8 +15,21 @@
#ifndef __ASSEMBLY__
/*
+ * Size of kernel stack for each process. This must be a power of 2...
+ */
+#ifdef CONFIG_4KSTACKS
+#define THREAD_SIZE_ORDER (0)
+#else
+#define THREAD_SIZE_ORDER (1)
+#endif
+
+/*
+ * for asm files, THREAD_SIZE is now generated by asm-offsets.c
+ */
+#define THREAD_SIZE (PAGE_SIZE<<THREAD_SIZE_ORDER)
+
+/*
* low level task data.
- * If you change this, change the TI_* offsets below to match.
*/
struct thread_info {
struct task_struct *task; /* main task structure */
@@ -60,20 +73,12 @@ 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)
+ __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__ */
-/*
- * Offsets in thread_info structure, used in assembly code
- */
-#define TI_TASK 0
-#define TI_EXECDOMAIN 4
-#define TI_FLAGS 8
-#define TI_CPU 12
-
#define PREEMPT_ACTIVE 0x4000000
/*
diff --git a/include/asm-m68knommu/uaccess.h b/include/asm-m68knommu/uaccess.h
index 9bda78751138a..f0be74bb353c6 100644
--- a/include/asm-m68knommu/uaccess.h
+++ b/include/asm-m68knommu/uaccess.h
@@ -23,7 +23,8 @@ static inline int _access_ok(unsigned long addr, unsigned long size)
(is_in_rom(addr) && is_in_rom(addr+size)));
}
-extern inline int verify_area(int type, const void * addr, unsigned long size)
+/* this function will go away soon - use access_ok() instead */
+extern inline int __deprecated verify_area(int type, const void * addr, unsigned long size)
{
return access_ok(type,addr,size)?0:-EFAULT;
}
diff --git a/include/asm-m68knommu/unaligned.h b/include/asm-m68knommu/unaligned.h
index 2b047b0daf684..8876f034ea648 100644
--- a/include/asm-m68knommu/unaligned.h
+++ b/include/asm-m68knommu/unaligned.h
@@ -5,15 +5,7 @@
#ifdef CONFIG_COLDFIRE
-/* Use memmove here, so gcc does not insert a __builtin_memcpy. */
-
-#define get_unaligned(ptr) \
- ({ __typeof__(*(ptr)) __tmp; memmove(&__tmp, (ptr), sizeof(*(ptr))); __tmp; })
-
-#define put_unaligned(val, ptr) \
- ({ __typeof__(*(ptr)) __tmp = (val); \
- memmove((ptr), &__tmp, sizeof(*(ptr))); \
- (void)0; })
+#include <asm-generic/unaligned.h>
#else
/*
diff --git a/include/asm-m68knommu/unistd.h b/include/asm-m68knommu/unistd.h
index c4638b4c0b2c9..84b6fa14459f7 100644
--- a/include/asm-m68knommu/unistd.h
+++ b/include/asm-m68knommu/unistd.h
@@ -524,6 +524,6 @@ asmlinkage long sys_rt_sigaction(int sig,
* What we want is __attribute__((weak,alias("sys_ni_syscall"))),
* but it doesn't work on all toolchains, so we just do it by hand
*/
-#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
+#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
#endif /* _ASM_M68K_UNISTD_H_ */
diff --git a/include/asm-mips/cacheflush.h b/include/asm-mips/cacheflush.h
index c08c486a2f2a0..635f1bfb403ec 100644
--- a/include/asm-mips/cacheflush.h
+++ b/include/asm-mips/cacheflush.h
@@ -17,7 +17,7 @@
*
* - flush_cache_all() flushes entire cache
* - flush_cache_mm(mm) flushes the specified mm context's cache lines
- * - flush_cache_page(mm, vmaddr) flushes a single page
+ * - flush_cache_page(mm, vmaddr, pfn) flushes a single page
* - flush_cache_range(vma, start, end) flushes a range of pages
* - flush_icache_range(start, end) flush a range of instructions
* - flush_dcache_page(pg) flushes(wback&invalidates) a page for dcache
@@ -34,8 +34,7 @@ extern void (*__flush_cache_all)(void);
extern void (*flush_cache_mm)(struct mm_struct *mm);
extern void (*flush_cache_range)(struct vm_area_struct *vma,
unsigned long start, unsigned long end);
-extern void (*flush_cache_page)(struct vm_area_struct *vma,
- unsigned long page);
+extern void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page, unsigned long pfn);
extern void __flush_dcache_page(struct page *page);
static inline void flush_dcache_page(struct page *page)
diff --git a/include/asm-mips/io.h b/include/asm-mips/io.h
index 8e5ac32ae857d..039845f2e6b0a 100644
--- a/include/asm-mips/io.h
+++ b/include/asm-mips/io.h
@@ -616,4 +616,15 @@ extern void (*_dma_cache_inv)(unsigned long start, unsigned long size);
#define csr_out32(v,a) (*(volatile u32 *)((unsigned long)(a) + __CSR_32_ADJUST) = (v))
#define csr_in32(a) (*(volatile u32 *)((unsigned long)(a) + __CSR_32_ADJUST))
+/*
+ * Convert a physical pointer to a virtual kernel pointer for /dev/mem
+ * access
+ */
+#define xlate_dev_mem_ptr(p) __va(p)
+
+/*
+ * Convert a virtual cached pointer to an uncached pointer
+ */
+#define xlate_dev_kmem_ptr(p) p
+
#endif /* _ASM_IO_H */
diff --git a/include/asm-mips/ipc.h b/include/asm-mips/ipc.h
index 377bbd5ef62fc..a46e3d9c2a3fc 100644
--- a/include/asm-mips/ipc.h
+++ b/include/asm-mips/ipc.h
@@ -1,33 +1 @@
-#ifndef _ASM_IPC_H
-#define _ASM_IPC_H
-
-/*
- * These are used to wrap system calls on MIPS.
- *
- * See arch/mips/kernel/sysmips.c for ugly details..
- * FIXME: split up into ordinary syscalls ...
- */
-struct ipc_kludge {
- struct msgbuf *msgp;
- long msgtyp;
-};
-
-#define SEMOP 1
-#define SEMGET 2
-#define SEMCTL 3
-#define SEMTIMEDOP 4
-#define MSGSND 11
-#define MSGRCV 12
-#define MSGGET 13
-#define MSGCTL 14
-#define SHMAT 21
-#define SHMDT 22
-#define SHMGET 23
-#define SHMCTL 24
-
-/* Used by the DIPC package, try and avoid reusing it */
-#define DIPC 25
-
-#define IPCCALL(version,op) ((version)<<16 | (op))
-
-#endif /* _ASM_IPC_H */
+#include <asm-generic/ipc.h>
diff --git a/include/asm-mips/pci.h b/include/asm-mips/pci.h
index 987090e07a65f..c9c576b48556b 100644
--- a/include/asm-mips/pci.h
+++ b/include/asm-mips/pci.h
@@ -137,17 +137,10 @@ extern void pcibios_resource_to_bus(struct pci_dev *dev,
#define pci_domain_nr(bus) ((struct pci_controller *)(bus)->sysdata)->index
-static inline int
-pci_name_bus(char *name, struct pci_bus *bus)
+static inline int pci_proc_domain(struct pci_bus *bus)
{
struct pci_controller *hose = bus->sysdata;
-
- if (likely(hose->need_domain_info == 0)) {
- sprintf(name, "%02x", bus->number);
- } else {
- sprintf(name, "%04x:%02x", hose->index, bus->number);
- }
- return 0;
+ return hose->need_domain_info;
}
#endif /* CONFIG_PCI_DOMAINS */
diff --git a/include/asm-mips/pgtable.h b/include/asm-mips/pgtable.h
index 0461ee1d3349e..878843203d67a 100644
--- a/include/asm-mips/pgtable.h
+++ b/include/asm-mips/pgtable.h
@@ -100,14 +100,15 @@ static inline void set_pte(pte_t *ptep, pte_t pte)
buddy->pte_low |= _PAGE_GLOBAL;
}
}
+#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
-static inline void pte_clear(pte_t *ptep)
+static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
{
/* Preserve global status for the pair */
if (pte_val(*ptep_buddy(ptep)) & _PAGE_GLOBAL)
- set_pte(ptep, __pte(_PAGE_GLOBAL));
+ set_pte_at(mm, addr, ptep, __pte(_PAGE_GLOBAL));
else
- set_pte(ptep, __pte(0));
+ set_pte_at(mm, addr, ptep, __pte(0));
}
#else
/*
@@ -130,16 +131,17 @@ static inline void set_pte(pte_t *ptep, pte_t pteval)
}
#endif
}
+#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
-static inline void pte_clear(pte_t *ptep)
+static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
{
#if !defined(CONFIG_CPU_R3000) && !defined(CONFIG_CPU_TX39XX)
/* Preserve global status for the pair */
if (pte_val(*ptep_buddy(ptep)) & _PAGE_GLOBAL)
- set_pte(ptep, __pte(_PAGE_GLOBAL));
+ set_pte_at(mm, addr, ptep, __pte(_PAGE_GLOBAL));
else
#endif
- set_pte(ptep, __pte(0));
+ set_pte_at(mm, addr, ptep, __pte(0));
}
#endif
@@ -365,11 +367,27 @@ static inline int io_remap_page_range(struct vm_area_struct *vma,
phys_t phys_addr_high = fixup_bigphys_addr(paddr, size);
return remap_pfn_range(vma, vaddr, phys_addr_high >> PAGE_SHIFT, size, prot);
}
+
+static inline int io_remap_pfn_range(struct vm_area_struct *vma,
+ unsigned long vaddr,
+ unsigned long pfn,
+ unsigned long size,
+ pgprot_t prot)
+{
+ phys_t phys_addr_high = fixup_bigphys_addr(pfn << PAGE_SHIFT, size);
+ return remap_pfn_range(vma, vaddr, pfn, size, prot);
+}
#else
#define io_remap_page_range(vma, vaddr, paddr, size, prot) \
- remap_pfn_range(vma, vaddr, (paddr) >> PAGE_SHIFT, size, prot)
+ remap_pfn_range(vma, vaddr, (paddr) >> PAGE_SHIFT, size, prot)
+#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
+ remap_pfn_range(vma, vaddr, pfn, size, prot)
#endif
+#define MK_IOSPACE_PFN(space, pfn) (pfn)
+#define GET_IOSPACE(pfn) 0
+#define GET_PFN(pfn) (pfn)
+
#include <asm-generic/pgtable.h>
/*
diff --git a/include/asm-mips/resource.h b/include/asm-mips/resource.h
index 9732bb4c4b128..fd3c6d17a5f63 100644
--- a/include/asm-mips/resource.h
+++ b/include/asm-mips/resource.h
@@ -9,36 +9,26 @@
#ifndef _ASM_RESOURCE_H
#define _ASM_RESOURCE_H
+#include <linux/config.h>
+
/*
- * Resource limits
+ * These five resource limit IDs have a MIPS/Linux-specific ordering,
+ * the rest comes from the generic header:
*/
-#define RLIMIT_CPU 0 /* CPU time in ms */
-#define RLIMIT_FSIZE 1 /* Maximum filesize */
-#define RLIMIT_DATA 2 /* max data size */
-#define RLIMIT_STACK 3 /* max stack size */
-#define RLIMIT_CORE 4 /* max core file size */
-#define RLIMIT_NOFILE 5 /* max number of open files */
-#define RLIMIT_AS 6 /* mapped memory */
-#define RLIMIT_RSS 7 /* max resident set size */
-#define RLIMIT_NPROC 8 /* max number of processes */
-#define RLIMIT_MEMLOCK 9 /* max locked-in-memory address space */
-#define RLIMIT_LOCKS 10 /* maximum file locks held */
-#define RLIMIT_SIGPENDING 11 /* max number of pending signals */
-#define RLIMIT_MSGQUEUE 12 /* maximum bytes in POSIX mqueues */
-
-#define RLIM_NLIMITS 13 /* Number of limit flavors. */
-#define __ARCH_RLIMIT_ORDER
+#define RLIMIT_NOFILE 5 /* max number of open files */
+#define RLIMIT_AS 6 /* address space limit */
+#define RLIMIT_RSS 7 /* max resident set size */
+#define RLIMIT_NPROC 8 /* max number of processes */
+#define RLIMIT_MEMLOCK 9 /* max locked-in-memory address space */
/*
* SuS says limits have to be unsigned.
- * Which makes a ton more sense anyway.
+ * Which makes a ton more sense anyway,
+ * but we keep the old value on MIPS32,
+ * for compatibility:
*/
-#include <linux/config.h>
#ifdef CONFIG_MIPS32
-#define RLIM_INFINITY 0x7fffffffUL
-#endif
-#ifdef CONFIG_MIPS64
-#define RLIM_INFINITY (~0UL)
+# define RLIM_INFINITY 0x7fffffffUL
#endif
#include <asm-generic/resource.h>
diff --git a/include/asm-mips/system.h b/include/asm-mips/system.h
index a421cdb1e0da0..888fd89084672 100644
--- a/include/asm-mips/system.h
+++ b/include/asm-mips/system.h
@@ -433,4 +433,6 @@ do { \
#define finish_arch_switch(rq, prev) spin_unlock_irq(&(prev)->switch_lock)
#define task_running(rq, p) ((rq)->curr == (p) || spin_is_locked(&(p)->switch_lock))
+#define arch_align_stack(x) (x)
+
#endif /* _ASM_SYSTEM_H */
diff --git a/include/asm-mips/timex.h b/include/asm-mips/timex.h
index 3ce2630928412..98aa737b34aa7 100644
--- a/include/asm-mips/timex.h
+++ b/include/asm-mips/timex.h
@@ -45,7 +45,6 @@
*/
typedef unsigned int cycles_t;
-extern cycles_t cacheflush_time;
static inline cycles_t get_cycles (void)
{
diff --git a/include/asm-mips/uaccess.h b/include/asm-mips/uaccess.h
index 95c067a08c580..07114898e0652 100644
--- a/include/asm-mips/uaccess.h
+++ b/include/asm-mips/uaccess.h
@@ -112,7 +112,8 @@
likely(__access_ok((unsigned long)(addr), (size),__access_mask))
/*
- * verify_area: - Obsolete, use access_ok()
+ * verify_area: - Obsolete/deprecated and will go away soon,
+ * use access_ok() instead.
* @type: Type of access: %VERIFY_READ or %VERIFY_WRITE
* @addr: User space pointer to start of block to check
* @size: Size of block to check
@@ -128,7 +129,7 @@
*
* See access_ok() for more details.
*/
-static inline int verify_area(int type, const void * addr, unsigned long size)
+static inline int __deprecated verify_area(int type, const void * addr, unsigned long size)
{
return access_ok(type, addr, size) ? 0 : -EFAULT;
}
@@ -257,7 +258,8 @@ struct __large_struct { unsigned long buf[100]; };
\
might_sleep(); \
__gu_addr = (long) (ptr); \
- __gu_err = verify_area(VERIFY_READ, (void *) __gu_addr, size); \
+ __gu_err = access_ok(VERIFY_READ, (void *) __gu_addr, size) \
+ ? 0 : -EFAULT; \
\
if (likely(!__gu_err)) { \
switch (size) { \
@@ -352,7 +354,8 @@ extern void __get_user_unknown(void);
might_sleep(); \
__pu_val = (x); \
__pu_addr = (long) (ptr); \
- __pu_err = verify_area(VERIFY_WRITE, (void *) __pu_addr, size); \
+ __pu_err = access_ok(VERIFY_WRITE, (void *) __pu_addr, size) \
+ ? 0 : -EFAULT; \
\
if (likely(!__pu_err)) { \
switch (size) { \
diff --git a/include/asm-mips/unaligned.h b/include/asm-mips/unaligned.h
index 7bfeabc1de0ef..a0042563838a7 100644
--- a/include/asm-mips/unaligned.h
+++ b/include/asm-mips/unaligned.h
@@ -9,136 +9,6 @@
#ifndef _ASM_UNALIGNED_H
#define _ASM_UNALIGNED_H
-#include <linux/types.h>
-
-/*
- * get_unaligned - get value from possibly mis-aligned location
- * @ptr: pointer to value
- *
- * This macro should be used for accessing values larger in size than
- * single bytes at locations that are expected to be improperly aligned,
- * e.g. retrieving a u16 value from a location not u16-aligned.
- *
- * Note that unaligned accesses can be very expensive on some architectures.
- */
-#define get_unaligned(ptr) \
- ((__typeof__(*(ptr)))__get_unaligned((ptr), sizeof(*(ptr))))
-
-/*
- * put_unaligned - put value to a possibly mis-aligned location
- * @val: value to place
- * @ptr: pointer to location
- *
- * This macro should be used for placing values larger in size than
- * single bytes at locations that are expected to be improperly aligned,
- * e.g. writing a u16 value to a location not u16-aligned.
- *
- * Note that unaligned accesses can be very expensive on some architectures.
- */
-#define put_unaligned(x,ptr) \
- __put_unaligned((__u64)(x), (ptr), sizeof(*(ptr)))
-
-/*
- * This is a silly but good way to make sure that
- * the get/put functions are indeed always optimized,
- * and that we use the correct sizes.
- */
-extern void bad_unaligned_access_length(void);
-
-/*
- * EGCS 1.1 knows about arbitrary unaligned loads. Define some
- * packed structures to talk about such things with.
- */
-
-struct __una_u64 { __u64 x __attribute__((packed)); };
-struct __una_u32 { __u32 x __attribute__((packed)); };
-struct __una_u16 { __u16 x __attribute__((packed)); };
-
-/*
- * Elemental unaligned loads
- */
-
-static inline __u64 __uldq(const __u64 * r11)
-{
- const struct __una_u64 *ptr = (const struct __una_u64 *) r11;
- return ptr->x;
-}
-
-static inline __u32 __uldl(const __u32 * r11)
-{
- const struct __una_u32 *ptr = (const struct __una_u32 *) r11;
- return ptr->x;
-}
-
-static inline __u16 __uldw(const __u16 * r11)
-{
- const struct __una_u16 *ptr = (const struct __una_u16 *) r11;
- return ptr->x;
-}
-
-/*
- * Elemental unaligned stores
- */
-
-static inline void __ustq(__u64 r5, __u64 * r11)
-{
- struct __una_u64 *ptr = (struct __una_u64 *) r11;
- ptr->x = r5;
-}
-
-static inline void __ustl(__u32 r5, __u32 * r11)
-{
- struct __una_u32 *ptr = (struct __una_u32 *) r11;
- ptr->x = r5;
-}
-
-static inline void __ustw(__u16 r5, __u16 * r11)
-{
- struct __una_u16 *ptr = (struct __una_u16 *) r11;
- ptr->x = r5;
-}
-
-static inline __u64 __get_unaligned(const void *ptr, size_t size)
-{
- __u64 val;
-
- switch (size) {
- case 1:
- val = *(const __u8 *)ptr;
- break;
- case 2:
- val = __uldw((const __u16 *)ptr);
- break;
- case 4:
- val = __uldl((const __u32 *)ptr);
- break;
- case 8:
- val = __uldq((const __u64 *)ptr);
- break;
- default:
- bad_unaligned_access_length();
- }
- return val;
-}
-
-static inline void __put_unaligned(__u64 val, void *ptr, size_t size)
-{
- switch (size) {
- case 1:
- *(__u8 *)ptr = (val);
- break;
- case 2:
- __ustw(val, (__u16 *)ptr);
- break;
- case 4:
- __ustl(val, (__u32 *)ptr);
- break;
- case 8:
- __ustq(val, (__u64 *)ptr);
- break;
- default:
- bad_unaligned_access_length();
- }
-}
+#include <asm-generic/unaligned.h>
#endif /* _ASM_UNALIGNED_H */
diff --git a/include/asm-mips/unistd.h b/include/asm-mips/unistd.h
index 5fa411c380709..6d21cc964f76c 100644
--- a/include/asm-mips/unistd.h
+++ b/include/asm-mips/unistd.h
@@ -1180,6 +1180,6 @@ asmlinkage long sys_rt_sigaction(int sig,
* What we want is __attribute__((weak,alias("sys_ni_syscall"))),
* but it doesn't work on all toolchains, so we just do it by hand
*/
-#define cond_syscall(x) asm(".weak\t" #x "\n" #x "\t=\tsys_ni_syscall");
+#define cond_syscall(x) asm(".weak\t" #x "\n" #x "\t=\tsys_ni_syscall")
#endif /* _ASM_UNISTD_H */
diff --git a/arch/mips/vr41xx/tanbac-tb0229/tb0219.c b/include/asm-mips/vr41xx/siu.h
index a07d9fa454abf..865cc07ddd7fe 100644
--- a/arch/mips/vr41xx/tanbac-tb0229/tb0219.c
+++ b/include/asm-mips/vr41xx/siu.h
@@ -1,8 +1,7 @@
/*
- * tb0219.c, Setup for the TANBAC TB0219
+ * Include file for NEC VR4100 series Serial Interface Unit.
*
- * Copyright (C) 2003 Megasolution Inc. <matsu@megasolution.jp>
- * Copyright (C) 2004 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * Copyright (C) 2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -18,27 +17,34 @@
* 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>
+#ifndef __NEC_VR41XX_SIU_H
+#define __NEC_VR41XX_SIU_H
-#include <asm/io.h>
-#include <asm/reboot.h>
+typedef enum {
+ SIU_INTERFACE_RS232C,
+ SIU_INTERFACE_IRDA,
+} siu_interface_t;
-#define TB0219_RESET_REGS KSEG1ADDR(0x0a00000e)
+extern void vr41xx_select_siu_interface(siu_interface_t interface);
-#define tb0219_hard_reset() writew(0, TB0219_RESET_REGS)
+typedef enum {
+ SIU_USE_IRDA,
+ FIR_USE_IRDA,
+} irda_use_t;
-static void tanbac_tb0219_restart(char *command)
-{
- local_irq_disable();
- tb0219_hard_reset();
- while (1);
-}
+extern void vr41xx_use_irda(irda_use_t use);
-static int __init tanbac_tb0219_setup(void)
-{
- _machine_restart = tanbac_tb0219_restart;
+typedef enum {
+ SHARP_IRDA,
+ TEMIC_IRDA,
+ HP_IRDA,
+} irda_module_t;
- return 0;
-}
+typedef enum {
+ IRDA_TX_1_5MBPS,
+ IRDA_TX_4MBPS,
+} irda_speed_t;
-early_initcall(tanbac_tb0219_setup);
+extern void vr41xx_select_irda_module(irda_module_t module, irda_speed_t speed);
+
+#endif /* __NEC_VR41XX_SIU_H */
diff --git a/include/asm-mips/vr41xx/vr41xx.h b/include/asm-mips/vr41xx/vr41xx.h
index c57c8dca61171..caacaced32138 100644
--- a/include/asm-mips/vr41xx/vr41xx.h
+++ b/include/asm-mips/vr41xx/vr41xx.h
@@ -45,6 +45,7 @@
/*
* Bus Control Uint
*/
+extern unsigned long vr41xx_calculate_clock_frequency(void);
extern unsigned long vr41xx_get_vtclock_frequency(void);
extern unsigned long vr41xx_get_tclock_frequency(void);
@@ -83,7 +84,7 @@ extern void vr41xx_mask_clock(vr41xx_clock_t clock);
#define INT2_CASCADE_IRQ MIPS_CPU_IRQ(4)
#define INT3_CASCADE_IRQ MIPS_CPU_IRQ(5)
#define INT4_CASCADE_IRQ MIPS_CPU_IRQ(6)
-#define MIPS_COUNTER_IRQ MIPS_CPU_IRQ(7)
+#define TIMER_IRQ MIPS_CPU_IRQ(7)
/* SYINT1 Interrupt Numbers */
#define SYSINT1_IRQ_BASE 8
@@ -247,34 +248,6 @@ enum {
};
/*
- * Serial Interface Unit
- */
-extern void vr41xx_siu_init(void);
-extern int vr41xx_serial_ports;
-
-/* SIU interfaces */
-typedef enum {
- SIU_RS232C,
- SIU_IRDA
-} siu_interface_t;
-
-/* IrDA interfaces */
-typedef enum {
- IRDA_NONE,
- IRDA_SHARP,
- IRDA_TEMIC,
- IRDA_HP
-} irda_module_t;
-
-extern void vr41xx_select_siu_interface(siu_interface_t interface,
- irda_module_t module);
-
-/*
- * Debug Serial Interface Unit
- */
-extern void vr41xx_dsiu_init(void);
-
-/*
* PCI Control Unit
*/
#define PCI_MASTER_ADDRESS_MASK 0x7fffffffU
diff --git a/include/asm-mips/vr41xx/vrc4171.h b/include/asm-mips/vr41xx/vrc4171.h
deleted file mode 100644
index ff96936270055..0000000000000
--- a/include/asm-mips/vr41xx/vrc4171.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * vrc4171.h, Include file for NEC VRC4171.
- *
- * Copyright (C) 2003 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-#ifndef __NEC_VRC4171_H
-#define __NEC_VRC4171_H
-
-/*
- * Configuration 1
- */
-enum {
- SLOTB_IS_NONE,
- SLOTB_IS_PCCARD,
- SLOTB_IS_CF,
- SLOTB_IS_FLASHROM
-};
-
-extern void vrc4171_set_multifunction_pin(int config);
-
-/*
- * Interrupt Status Mask
- */
-#define IRQ_A 0x02
-#define IRQ_B 0x04
-
-extern uint16_t vrc4171_get_irq_status(void);
-
-#endif /* __NEC_VRC4171_H */
diff --git a/include/asm-parisc/assembly.h b/include/asm-parisc/assembly.h
index 56b5bd88ed474..cbc286f49b365 100644
--- a/include/asm-parisc/assembly.h
+++ b/include/asm-parisc/assembly.h
@@ -37,6 +37,7 @@
#define LDREGX ldwx,s
#define LDREGM ldwm
#define STREGM stwm
+#define SHRREG shr
#define RP_OFFSET 20
#define FRAME_SIZE 64
#define CALLEE_SAVE_FRAME_SIZE 128
@@ -44,7 +45,7 @@
#ifdef CONFIG_PA20
#define BL b,l
-# ifdef CONFIG_PARISC64
+# ifdef CONFIG_64BIT
# define LEVEL 2.0w
# else
# define LEVEL 2.0
diff --git a/include/asm-parisc/bitops.h b/include/asm-parisc/bitops.h
index 5badc617ec7cf..928e5ef850bd2 100644
--- a/include/asm-parisc/bitops.h
+++ b/include/asm-parisc/bitops.h
@@ -446,14 +446,14 @@ found_middle:
* disabling interrupts.
*/
#ifdef __LP64__
-#define ext2_set_bit(nr, addr) test_and_set_bit((nr) ^ 0x38, (unsigned long *)addr)
+#define ext2_set_bit(nr, addr) __test_and_set_bit((nr) ^ 0x38, (unsigned long *)addr)
#define ext2_set_bit_atomic(l,nr,addr) test_and_set_bit((nr) ^ 0x38, (unsigned long *)addr)
-#define ext2_clear_bit(nr, addr) test_and_clear_bit((nr) ^ 0x38, (unsigned long *)addr)
+#define ext2_clear_bit(nr, addr) __test_and_clear_bit((nr) ^ 0x38, (unsigned long *)addr)
#define ext2_clear_bit_atomic(l,nr,addr) test_and_clear_bit((nr) ^ 0x38, (unsigned long *)addr)
#else
-#define ext2_set_bit(nr, addr) test_and_set_bit((nr) ^ 0x18, (unsigned long *)addr)
+#define ext2_set_bit(nr, addr) __test_and_set_bit((nr) ^ 0x18, (unsigned long *)addr)
#define ext2_set_bit_atomic(l,nr,addr) test_and_set_bit((nr) ^ 0x18, (unsigned long *)addr)
-#define ext2_clear_bit(nr, addr) test_and_clear_bit((nr) ^ 0x18, (unsigned long *)addr)
+#define ext2_clear_bit(nr, addr) __test_and_clear_bit((nr) ^ 0x18, (unsigned long *)addr)
#define ext2_clear_bit_atomic(l,nr,addr) test_and_clear_bit((nr) ^ 0x18, (unsigned long *)addr)
#endif
diff --git a/include/asm-parisc/cacheflush.h b/include/asm-parisc/cacheflush.h
index a3132a28a8f2d..06732719d927f 100644
--- a/include/asm-parisc/cacheflush.h
+++ b/include/asm-parisc/cacheflush.h
@@ -57,9 +57,9 @@ flush_user_icache_range(unsigned long start, unsigned long end)
extern void flush_dcache_page(struct page *page);
#define flush_dcache_mmap_lock(mapping) \
- spin_lock_irq(&(mapping)->tree_lock)
+ write_lock_irq(&(mapping)->tree_lock)
#define flush_dcache_mmap_unlock(mapping) \
- spin_unlock_irq(&(mapping)->tree_lock)
+ write_unlock_irq(&(mapping)->tree_lock)
#define flush_icache_page(vma,page) do { flush_kernel_dcache_page(page_address(page)); flush_kernel_icache_page(page_address(page)); } while (0)
@@ -67,14 +67,14 @@ extern void flush_dcache_page(struct page *page);
#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
do { \
- flush_cache_page(vma, vaddr); \
+ flush_cache_page(vma, vaddr, page_to_pfn(page)); \
memcpy(dst, src, len); \
flush_kernel_dcache_range_asm((unsigned long)dst, (unsigned long)dst + len); \
} while (0)
#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
do { \
- flush_cache_page(vma, vaddr); \
+ flush_cache_page(vma, vaddr, page_to_pfn(page)); \
memcpy(dst, src, len); \
} while (0)
@@ -170,7 +170,7 @@ __flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr)
}
static inline void
-flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr)
+flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr, unsigned long pfn)
{
BUG_ON(!vma->vm_mm->context);
diff --git a/include/asm-parisc/checksum.h b/include/asm-parisc/checksum.h
index f8bfc4c722365..229cb56fdb7a0 100644
--- a/include/asm-parisc/checksum.h
+++ b/include/asm-parisc/checksum.h
@@ -30,8 +30,8 @@ extern unsigned int csum_partial_copy_nocheck(const unsigned char *, unsigned ch
* this is a new version of the above that records errors it finds in *errp,
* but continues and zeros the rest of the buffer.
*/
-extern unsigned int csum_partial_copy_from_user(const unsigned char *src, unsigned char *dst,
- int len, unsigned int sum, int *errp);
+extern unsigned int csum_partial_copy_from_user(const unsigned char __user *src,
+ unsigned char *dst, int len, unsigned int sum, int *errp);
/*
* Optimized for IP headers, which always checksum on 4 octet boundaries.
diff --git a/include/asm-parisc/compat.h b/include/asm-parisc/compat.h
index 3edb5db3eaceb..ca0eac647a05b 100644
--- a/include/asm-parisc/compat.h
+++ b/include/asm-parisc/compat.h
@@ -131,15 +131,15 @@ typedef u32 compat_sigset_word;
*/
typedef u32 compat_uptr_t;
-static inline void *compat_ptr(compat_uptr_t uptr)
+static inline void __user *compat_ptr(compat_uptr_t uptr)
{
- return (void *)(unsigned long)uptr;
+ return (void __user *)(unsigned long)uptr;
}
-static __inline__ void *compat_alloc_user_space(long len)
+static __inline__ void __user *compat_alloc_user_space(long len)
{
struct pt_regs *regs = &current->thread.regs;
- return (void *)regs->gr[30];
+ return (void __user *)regs->gr[30];
}
#endif /* _ASM_PARISC_COMPAT_H */
diff --git a/include/asm-parisc/dma-mapping.h b/include/asm-parisc/dma-mapping.h
index be4458181e389..4db84f969e9eb 100644
--- a/include/asm-parisc/dma-mapping.h
+++ b/include/asm-parisc/dma-mapping.h
@@ -1,8 +1,8 @@
#ifndef _PARISC_DMA_MAPPING_H
#define _PARISC_DMA_MAPPING_H
-#include <linux/mm.h>
#include <linux/config.h>
+#include <linux/mm.h>
#include <asm/cacheflush.h>
#include <asm/scatterlist.h>
diff --git a/include/asm-parisc/dma.h b/include/asm-parisc/dma.h
index 9b0ee7576c0e2..31fd10df43a76 100644
--- a/include/asm-parisc/dma.h
+++ b/include/asm-parisc/dma.h
@@ -38,9 +38,11 @@
** won't compile :-(
*/
#define MAX_DMA_CHANNELS 8
-#define DMA_MODE_READ 1
-#define DMA_MODE_WRITE 2
-#define DMA_AUTOINIT 0x10
+#define DMA_MODE_READ 0x44 /* I/O to memory, no autoinit, increment, single mode */
+#define DMA_MODE_WRITE 0x48 /* memory to I/O, no autoinit, increment, single mode */
+#define DMA_MODE_CASCADE 0xC0 /* pass thru DREQ->HRQ, DACK<-HLDA only */
+
+#define DMA_AUTOINIT 0x10
/* 8237 DMA controllers */
#define IO_DMA1_BASE 0x00 /* 8 bit slave DMA, channels 0..3 */
diff --git a/include/asm-parisc/eisa_eeprom.h b/include/asm-parisc/eisa_eeprom.h
index 5ba85370533e2..9c9da980402a1 100644
--- a/include/asm-parisc/eisa_eeprom.h
+++ b/include/asm-parisc/eisa_eeprom.h
@@ -13,6 +13,8 @@
#ifndef ASM_EISA_EEPROM_H
#define ASM_EISA_EEPROM_H
+extern void __iomem *eisa_eeprom_addr;
+
#define HPEE_MAX_LENGTH 0x2000 /* maximum eeprom length */
#define HPEE_SLOT_INFO(slot) (20+(48*slot))
diff --git a/include/asm-parisc/hardirq.h b/include/asm-parisc/hardirq.h
index 58d92ade386a2..ce93133d51124 100644
--- a/include/asm-parisc/hardirq.h
+++ b/include/asm-parisc/hardirq.h
@@ -15,9 +15,7 @@
#ifndef _PARISC_HARDIRQ_H
#define _PARISC_HARDIRQ_H
-#include <linux/config.h>
#include <linux/threads.h>
-#include <linux/cache.h>
#include <linux/irq.h>
typedef struct {
@@ -26,16 +24,6 @@ typedef struct {
#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */
-#define HARDIRQ_BITS 16
-
-/*
- * 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
-
void ack_bad_irq(unsigned int irq);
#endif /* _PARISC_HARDIRQ_H */
diff --git a/include/asm-parisc/hardware.h b/include/asm-parisc/hardware.h
index 8005759e16ffd..106d3f7cd8823 100644
--- a/include/asm-parisc/hardware.h
+++ b/include/asm-parisc/hardware.h
@@ -122,6 +122,7 @@ extern char *print_pci_hwpath(struct pci_dev *dev, char *path);
extern void get_pci_node_path(struct pci_dev *dev, struct hardware_path *path);
extern void init_parisc_bus(void);
extern struct device *hwpath_to_device(struct hardware_path *modpath);
+extern void device_to_hwpath(struct device *dev, struct hardware_path *path);
/* inventory.c: */
diff --git a/include/asm-parisc/ide.h b/include/asm-parisc/ide.h
index 15a9374c1c0f8..3243cf2cd2276 100644
--- a/include/asm-parisc/ide.h
+++ b/include/asm-parisc/ide.h
@@ -13,8 +13,6 @@
#ifdef __KERNEL__
-#include <linux/config.h>
-
#ifndef MAX_HWIFS
#define MAX_HWIFS 2
#endif
@@ -34,7 +32,7 @@
#define __ide_outsw outsw
#define __ide_outsl outsl
-static __inline__ void __ide_mm_insw(unsigned long port, void *addr, u32 count)
+static __inline__ void __ide_mm_insw(void __iomem *port, void *addr, u32 count)
{
while (count--) {
*(u16 *)addr = __raw_readw(port);
@@ -42,7 +40,7 @@ static __inline__ void __ide_mm_insw(unsigned long port, void *addr, u32 count)
}
}
-static __inline__ void __ide_mm_insl(unsigned long port, void *addr, u32 count)
+static __inline__ void __ide_mm_insl(void __iomem *port, void *addr, u32 count)
{
while (count--) {
*(u32 *)addr = __raw_readl(port);
@@ -50,7 +48,7 @@ static __inline__ void __ide_mm_insl(unsigned long port, void *addr, u32 count)
}
}
-static __inline__ void __ide_mm_outsw(unsigned long port, void *addr, u32 count)
+static __inline__ void __ide_mm_outsw(void __iomem *port, void *addr, u32 count)
{
while (count--) {
__raw_writew(*(u16 *)addr, port);
@@ -58,7 +56,7 @@ static __inline__ void __ide_mm_outsw(unsigned long port, void *addr, u32 count)
}
}
-static __inline__ void __ide_mm_outsl(unsigned long port, void *addr, u32 count)
+static __inline__ void __ide_mm_outsl(void __iomem *port, void *addr, u32 count)
{
while (count--) {
__raw_writel(*(u32 *)addr, port);
diff --git a/include/asm-parisc/io.h b/include/asm-parisc/io.h
index c421ac18495ab..b9bb5946ecc99 100644
--- a/include/asm-parisc/io.h
+++ b/include/asm-parisc/io.h
@@ -273,10 +273,11 @@ static inline void __raw_writeq(unsigned long long b, volatile void __iomem *add
}
#endif /* !USE_HPPA_IOREMAP */
+/* readb can never be const, so use __fswab instead of le*_to_cpu */
#define readb(addr) __raw_readb(addr)
-#define readw(addr) le16_to_cpu(__raw_readw(addr))
-#define readl(addr) le32_to_cpu(__raw_readl(addr))
-#define readq(addr) le64_to_cpu(__raw_readq(addr))
+#define readw(addr) __fswab16(__raw_readw(addr))
+#define readl(addr) __fswab32(__raw_readl(addr))
+#define readq(addr) __fswab64(__raw_readq(addr))
#define writeb(b, addr) __raw_writeb(b, addr)
#define writew(b, addr) __raw_writew(cpu_to_le16(b), addr)
#define writel(b, addr) __raw_writel(cpu_to_le32(b), addr)
@@ -403,4 +404,15 @@ extern void outsl (unsigned long port, const void *src, unsigned long count);
#include <asm-generic/iomap.h>
+/*
+ * Convert a physical pointer to a virtual kernel pointer for /dev/mem
+ * access
+ */
+#define xlate_dev_mem_ptr(p) __va(p)
+
+/*
+ * Convert a virtual cached pointer to an uncached pointer
+ */
+#define xlate_dev_kmem_ptr(p) p
+
#endif
diff --git a/include/asm-parisc/irq.h b/include/asm-parisc/irq.h
index 4e5fad213c395..75654ba933535 100644
--- a/include/asm-parisc/irq.h
+++ b/include/asm-parisc/irq.h
@@ -40,10 +40,12 @@ struct hw_interrupt_type;
void no_ack_irq(unsigned int irq);
void no_end_irq(unsigned int irq);
-extern int txn_alloc_irq(void);
+extern int txn_alloc_irq(unsigned int nbits);
extern int txn_claim_irq(int);
-extern unsigned int txn_alloc_data(int, unsigned int);
-extern unsigned long txn_alloc_addr(int);
+extern unsigned int txn_alloc_data(unsigned int);
+extern unsigned long txn_alloc_addr(unsigned int);
+
+extern int cpu_claim_irq(unsigned int irq, struct hw_interrupt_type *, void *);
extern int cpu_claim_irq(unsigned int irq, struct hw_interrupt_type *, void *);
diff --git a/include/asm-parisc/led.h b/include/asm-parisc/led.h
index 26fa9d1e0b414..1ac8ab6c580df 100644
--- a/include/asm-parisc/led.h
+++ b/include/asm-parisc/led.h
@@ -21,19 +21,23 @@
#define DISPLAY_MODEL_LASI 2 /* LASI style 8 bit LED */
#define DISPLAY_MODEL_OLD_ASP 0x7F /* faked: ASP style 8 x 1 bit LED (only very old ASP versions) */
-#define LED_CMD_REG_NONE NULL /* NULL == no addr for the cmd register */
+#define LED_CMD_REG_NONE 0 /* NULL == no addr for the cmd register */
/* led tasklet struct */
extern struct tasklet_struct led_tasklet;
/* register_led_driver() */
-int __init register_led_driver( int model, char *cmd_reg, char *data_reg );
+int __init register_led_driver(int model, unsigned long cmd_reg, unsigned long data_reg);
/* registers the LED regions for procfs */
void __init register_led_regions(void);
+#ifdef CONFIG_CHASSIS_LCD_LED
/* writes a string to the LCD display (if possible on this h/w) */
int lcd_print(char *str);
+#else
+#define lcd_print(str)
+#endif
/* main LED initialization function (uses PDC) */
int __init led_init(void);
diff --git a/include/asm-parisc/module.h b/include/asm-parisc/module.h
index 43ecd76210909..00f06885f843b 100644
--- a/include/asm-parisc/module.h
+++ b/include/asm-parisc/module.h
@@ -17,12 +17,16 @@
#define Elf_Rela Elf32_Rela
#endif
+struct unwind_table;
+
struct mod_arch_specific
{
unsigned long got_offset, got_count, got_max;
unsigned long fdesc_offset, fdesc_count, fdesc_max;
unsigned long stub_offset, stub_count, stub_max;
unsigned long init_stub_offset, init_stub_count, init_stub_max;
+ int unwind_section;
+ struct unwind_table *unwind;
};
#endif /* _ASM_PARISC_MODULE_H */
diff --git a/include/asm-parisc/numnodes.h b/include/asm-parisc/numnodes.h
index dcdd933eb60b1..6c67651efd1c8 100644
--- a/include/asm-parisc/numnodes.h
+++ b/include/asm-parisc/numnodes.h
@@ -1,8 +1,6 @@
#ifndef _ASM_MAX_NUMNODES_H
#define _ASM_MAX_NUMNODES_H
-#include <linux/config.h>
-
/* Max 8 Nodes */
#define NODES_SHIFT 3
diff --git a/include/asm-parisc/parisc-device.h b/include/asm-parisc/parisc-device.h
index 594c1d91589b6..ef69ab4b17a99 100644
--- a/include/asm-parisc/parisc-device.h
+++ b/include/asm-parisc/parisc-device.h
@@ -6,6 +6,7 @@ struct parisc_device {
struct parisc_driver *driver; /* Driver for this device */
char name[80]; /* The hardware description */
int irq;
+ int aux_irq; /* Some devices have a second IRQ */
char hw_path; /* The module number on this bus */
unsigned int num_addrs; /* some devices have additional address ranges. */
diff --git a/include/asm-parisc/pci.h b/include/asm-parisc/pci.h
index fe7c7045dc4d0..0763c2982fb08 100644
--- a/include/asm-parisc/pci.h
+++ b/include/asm-parisc/pci.h
@@ -28,7 +28,7 @@
** Data needed by pcibios layer belongs here.
*/
struct pci_hba_data {
- unsigned long base_addr; /* aka Host Physical Address */
+ void __iomem *base_addr; /* aka Host Physical Address */
const struct parisc_device *dev; /* device from PA bus walk */
struct pci_bus *hba_bus; /* primary PCI bus below HBA */
int hba_num; /* I/O port space access "key" */
@@ -69,7 +69,7 @@ struct pci_hba_data {
#define PCI_PORT_HBA(a) ((a) >> HBA_PORT_SPACE_BITS)
#define PCI_PORT_ADDR(a) ((a) & (HBA_PORT_SPACE_SIZE - 1))
-#if CONFIG_PARISC64
+#if CONFIG_64BIT
#define PCI_F_EXTEND 0xffffffff00000000UL
#define PCI_IS_LMMIO(hba,a) pci_is_lmmio(hba,a)
@@ -90,14 +90,14 @@ static __inline__ int pci_is_lmmio(struct pci_hba_data *hba, unsigned long a)
: (a)) /* GMMIO */
#define PCI_HOST_ADDR(hba,a) ((a) + hba->lmmio_space_offset)
-#else /* !CONFIG_PARISC64 */
+#else /* !CONFIG_64BIT */
#define PCI_BUS_ADDR(hba,a) (a)
#define PCI_HOST_ADDR(hba,a) (a)
#define PCI_F_EXTEND 0UL
#define PCI_IS_LMMIO(hba,a) (1) /* 32-bit doesn't support GMMIO */
-#endif /* !CONFIG_PARISC64 */
+#endif /* !CONFIG_64BIT */
/*
** KLUGE: linux/pci.h include asm/pci.h BEFORE declaring struct pci_bus
@@ -106,11 +106,28 @@ static __inline__ int pci_is_lmmio(struct pci_hba_data *hba, unsigned long a)
struct pci_bus;
struct pci_dev;
-/* The PCI address space does equal the physical memory
- * address space. The networking and block device layers use
+/*
+ * If the PCI device's view of memory is the same as the CPU's view of memory,
+ * PCI_DMA_BUS_IS_PHYS is true. The networking and block device layers use
* this boolean for bounce buffer decisions.
*/
-#define PCI_DMA_BUS_IS_PHYS (1)
+#ifdef CONFIG_PA20
+/* All PA-2.0 machines have an IOMMU. */
+#define PCI_DMA_BUS_IS_PHYS 0
+#define parisc_has_iommu() do { } while (0)
+#else
+
+#if defined(CONFIG_IOMMU_CCIO) || defined(CONFIG_IOMMU_SBA)
+extern int parisc_bus_is_phys; /* in arch/parisc/kernel/setup.c */
+#define PCI_DMA_BUS_IS_PHYS parisc_bus_is_phys
+#define parisc_has_iommu() do { parisc_bus_is_phys = 0; } while (0)
+#else
+#define PCI_DMA_BUS_IS_PHYS 1
+#define parisc_has_iommu() do { } while (0)
+#endif
+
+#endif /* !CONFIG_PA20 */
+
/*
** Most PCI devices (eg Tulip, NCR720) also export the same registers
@@ -182,16 +199,27 @@ extern inline void pcibios_register_hba(struct pci_hba_data *x)
#endif
/*
-** used by drivers/pci/pci.c:pci_do_scan_bus()
-** 0 == check if bridge is numbered before re-numbering.
-** 1 == pci_do_scan_bus() should automatically number all PCI-PCI bridges.
-**
-** REVISIT:
-** To date, only alpha sets this to one. We'll need to set this
-** to zero for legacy platforms and one for PAT platforms.
-*/
-#define pcibios_assign_all_busses() (pdc_type == PDC_TYPE_PAT)
-#define pcibios_scan_all_fns(a, b) 0
+ * pcibios_assign_all_busses() is used in drivers/pci/pci.c:pci_do_scan_bus()
+ * 0 == check if bridge is numbered before re-numbering.
+ * 1 == pci_do_scan_bus() should automatically number all PCI-PCI bridges.
+ *
+ * We *should* set this to zero for "legacy" platforms and one
+ * for PAT platforms.
+ *
+ * But legacy platforms also need to renumber the busses below a Host
+ * Bus controller. Adding a 4-port Tulip card on the first PCI root
+ * bus of a C200 resulted in the secondary bus being numbered as 1.
+ * The second PCI host bus controller's root bus had already been
+ * assigned bus number 1 by firmware and sysfs complained.
+ *
+ * Firmware isn't doing anything wrong here since each controller
+ * is its own PCI domain. It's simpler and easier for us to renumber
+ * the busses rather than treat each Dino as a separate PCI domain.
+ * Eventually, we may want to introduce PCI domains for Superdome or
+ * rp7420/8420 boxes and then revisit this issue.
+ */
+#define pcibios_assign_all_busses() (1)
+#define pcibios_scan_all_fns(a, b) (0)
#define PCIBIOS_MIN_IO 0x10
#define PCIBIOS_MIN_MEM 0x1000 /* NBPG - but pci/setup-res.c dies */
diff --git a/include/asm-parisc/pdc_chassis.h b/include/asm-parisc/pdc_chassis.h
index 7378770f02ebc..adac9ac2743f6 100644
--- a/include/asm-parisc/pdc_chassis.h
+++ b/include/asm-parisc/pdc_chassis.h
@@ -1,8 +1,8 @@
/*
- * include/asm-parisc/pdc_chassis.h
+ * include/asm-parisc/pdc_chassis.h
*
- * Copyright (C) 2002 Laurent Canet <canetl@esiee.fr>
- * Copyright (C) 2002 Thibaut Varene <varenet@esiee.fr>
+ * Copyright (C) 2002 Laurent Canet <canetl@esiee.fr>
+ * Copyright (C) 2002 Thibaut Varene <varenet@parisc-linux.org>
*
*
* This program is free software; you can redistribute it and/or modify
diff --git a/include/asm-parisc/pdcpat.h b/include/asm-parisc/pdcpat.h
index 715d94da61c79..b4b34c0e8c1a8 100644
--- a/include/asm-parisc/pdcpat.h
+++ b/include/asm-parisc/pdcpat.h
@@ -190,16 +190,16 @@
#ifndef __ASSEMBLY__
#include <linux/types.h>
-#ifdef CONFIG_PARISC64
+#ifdef CONFIG_64BIT
#define is_pdc_pat() (PDC_TYPE_PAT == pdc_type)
extern int pdc_pat_get_irt_size(unsigned long *num_entries, unsigned long cell_num);
extern int pdc_pat_get_irt(void *r_addr, unsigned long cell_num);
-#else /* ! CONFIG_PARISC64 */
+#else /* ! CONFIG_64BIT */
/* No PAT support for 32-bit kernels...sorry */
#define is_pdc_pat() (0)
#define pdc_pat_get_irt_size(num_entries, cell_numn) PDC_BAD_PROC
#define pdc_pat_get_irt(r_addr, cell_num) PDC_BAD_PROC
-#endif /* ! CONFIG_PARISC64 */
+#endif /* ! CONFIG_64BIT */
struct pdc_pat_cell_num {
diff --git a/include/asm-parisc/pgalloc.h b/include/asm-parisc/pgalloc.h
index 22b6ae6c45e03..6291d6692e5db 100644
--- a/include/asm-parisc/pgalloc.h
+++ b/include/asm-parisc/pgalloc.h
@@ -7,7 +7,6 @@
#include <asm/processor.h>
#include <asm/fixmap.h>
-#include <asm/pgtable.h>
#include <asm/cache.h>
/* Allocate the top level pgd (page directory)
diff --git a/include/asm-parisc/pgtable.h b/include/asm-parisc/pgtable.h
index ccfc070fd0557..af353a9bce211 100644
--- a/include/asm-parisc/pgtable.h
+++ b/include/asm-parisc/pgtable.h
@@ -39,6 +39,7 @@
do{ \
*(pteptr) = (pteval); \
} while(0)
+#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
#endif /* !__ASSEMBLY__ */
@@ -263,7 +264,7 @@ extern unsigned long *empty_zero_page;
#define pte_none(x) ((pte_val(x) == 0) || (pte_val(x) & _PAGE_FLUSH))
#define pte_present(x) (pte_val(x) & _PAGE_PRESENT)
-#define pte_clear(xp) do { pte_val(*(xp)) = 0; } while (0)
+#define pte_clear(mm,addr,xp) do { pte_val(*(xp)) = 0; } while (0)
#define pmd_flag(x) (pmd_val(x) & PxD_FLAG_MASK)
#define pmd_address(x) ((unsigned long)(pmd_val(x) &~ PxD_FLAG_MASK) << PxD_VALUE_SHIFT)
@@ -431,7 +432,7 @@ extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t);
#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) })
#define __swp_entry_to_pte(x) ((pte_t) { (x).val })
-static inline int ptep_test_and_clear_young(pte_t *ptep)
+static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
{
#ifdef CONFIG_SMP
if (!pte_young(*ptep))
@@ -441,12 +442,12 @@ static inline int ptep_test_and_clear_young(pte_t *ptep)
pte_t pte = *ptep;
if (!pte_young(pte))
return 0;
- set_pte(ptep, pte_mkold(pte));
+ set_pte_at(vma->vm_mm, addr, ptep, pte_mkold(pte));
return 1;
#endif
}
-static inline int ptep_test_and_clear_dirty(pte_t *ptep)
+static inline int ptep_test_and_clear_dirty(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
{
#ifdef CONFIG_SMP
if (!pte_dirty(*ptep))
@@ -456,14 +457,14 @@ static inline int ptep_test_and_clear_dirty(pte_t *ptep)
pte_t pte = *ptep;
if (!pte_dirty(pte))
return 0;
- set_pte(ptep, pte_mkclean(pte));
+ set_pte_at(vma->vm_mm, addr, ptep, pte_mkclean(pte));
return 1;
#endif
}
extern spinlock_t pa_dbit_lock;
-static inline pte_t ptep_get_and_clear(pte_t *ptep)
+static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
{
pte_t old_pte;
pte_t pte;
@@ -472,13 +473,13 @@ static inline pte_t ptep_get_and_clear(pte_t *ptep)
pte = old_pte = *ptep;
pte_val(pte) &= ~_PAGE_PRESENT;
pte_val(pte) |= _PAGE_FLUSH;
- set_pte(ptep,pte);
+ set_pte_at(mm,addr,ptep,pte);
spin_unlock(&pa_dbit_lock);
return old_pte;
}
-static inline void ptep_set_wrprotect(pte_t *ptep)
+static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
{
#ifdef CONFIG_SMP
unsigned long new, old;
@@ -489,17 +490,7 @@ static inline void ptep_set_wrprotect(pte_t *ptep)
} while (cmpxchg((unsigned long *) ptep, old, new) != old);
#else
pte_t old_pte = *ptep;
- set_pte(ptep, pte_wrprotect(old_pte));
-#endif
-}
-
-static inline void ptep_mkdirty(pte_t *ptep)
-{
-#ifdef CONFIG_SMP
- set_bit(xlate_pabit(_PAGE_DIRTY_BIT), &pte_val(*ptep));
-#else
- pte_t old_pte = *ptep;
- set_pte(ptep, pte_mkdirty(old_pte));
+ set_pte_at(mm, addr, ptep, pte_wrprotect(old_pte));
#endif
}
@@ -510,6 +501,13 @@ static inline void ptep_mkdirty(pte_t *ptep)
#define io_remap_page_range(vma, vaddr, paddr, size, prot) \
remap_pfn_range(vma, vaddr, (paddr) >> PAGE_SHIFT, size, prot)
+#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
+ remap_pfn_range(vma, vaddr, pfn, size, prot)
+
+#define MK_IOSPACE_PFN(space, pfn) (pfn)
+#define GET_IOSPACE(pfn) 0
+#define GET_PFN(pfn) (pfn)
+
/* We provide our own get_unmapped_area to provide cache coherency */
#define HAVE_ARCH_UNMAPPED_AREA
@@ -518,7 +516,6 @@ static inline void ptep_mkdirty(pte_t *ptep)
#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
#define __HAVE_ARCH_PTEP_SET_WRPROTECT
-#define __HAVE_ARCH_PTEP_MKDIRTY
#define __HAVE_ARCH_PTE_SAME
#include <asm-generic/pgtable.h>
diff --git a/include/asm-parisc/serial.h b/include/asm-parisc/serial.h
index 230644f9e28e7..239c5dcab7e6c 100644
--- a/include/asm-parisc/serial.h
+++ b/include/asm-parisc/serial.h
@@ -2,8 +2,6 @@
* include/asm-parisc/serial.h
*/
-#include <linux/config.h>
-
/*
* This assumes you have a 7.272727 MHz clock for your UART.
* The documentation implies a 40Mhz clock, and elsewhere a 7Mhz clock
diff --git a/include/asm-parisc/signal.h b/include/asm-parisc/signal.h
index cd4beefef3333..358f577c8eb8e 100644
--- a/include/asm-parisc/signal.h
+++ b/include/asm-parisc/signal.h
@@ -123,13 +123,14 @@ struct siginfo;
* compiler doesn't support code which changes or tests the address of
* the function in the little struct. This is really ugly -PB
*/
-typedef __kernel_caddr_t __sighandler_t;
+typedef char __user *__sighandler_t;
#else
-typedef void (*__sighandler_t)(int);
+typedef void __signalfn_t(int);
+typedef __signalfn_t __user *__sighandler_t;
#endif
typedef struct sigaltstack {
- void *ss_sp;
+ void __user *ss_sp;
int ss_flags;
size_t ss_size;
} stack_t;
diff --git a/include/asm-parisc/spinlock.h b/include/asm-parisc/spinlock.h
index 102a0dde9f718..679ea1c651efe 100644
--- a/include/asm-parisc/spinlock.h
+++ b/include/asm-parisc/spinlock.h
@@ -226,7 +226,7 @@ static __inline__ void _raw_write_unlock(rwlock_t *rw)
}
#ifdef CONFIG_DEBUG_RWLOCK
-extern void _dbg_write_trylock(rwlock_t * rw, const char *bfile, int bline);
+extern int _dbg_write_trylock(rwlock_t * rw, const char *bfile, int bline);
#define _raw_write_trylock(rw) _dbg_write_trylock(rw, __FILE__, __LINE__)
#else
static __inline__ int _raw_write_trylock(rwlock_t *rw)
diff --git a/include/asm-parisc/system.h b/include/asm-parisc/system.h
index 8aecb9e93fc06..81c543339036c 100644
--- a/include/asm-parisc/system.h
+++ b/include/asm-parisc/system.h
@@ -125,7 +125,7 @@ static inline void set_eiem(unsigned long val)
** The __asm__ op below simple prevents gcc/ld from reordering
** instructions across the mb() "call".
*/
-#define mb() __asm__ __volatile__("":::"memory"); /* barrier() */
+#define mb() __asm__ __volatile__("":::"memory") /* barrier() */
#define rmb() mb()
#define wmb() mb()
#define smp_mb() mb()
@@ -205,4 +205,6 @@ extern spinlock_t pa_tlb_lock;
#endif
+#define arch_align_stack(x) (x)
+
#endif
diff --git a/include/asm-parisc/thread_info.h b/include/asm-parisc/thread_info.h
index e51693dbceb42..fe9b7f8ae4c64 100644
--- a/include/asm-parisc/thread_info.h
+++ b/include/asm-parisc/thread_info.h
@@ -23,7 +23,7 @@ struct thread_info {
.flags = 0, \
.cpu = 0, \
.addr_limit = KERNEL_DS, \
- .preempt_count = 0, \
+ .preempt_count = 1, \
.restart_block = { \
.fn = do_no_restart_syscall \
} \
@@ -52,7 +52,7 @@ struct thread_info {
#endif /* !__ASSEMBLY */
-#define PREEMPT_ACTIVE 0x4000000
+#define PREEMPT_ACTIVE 0x10000000
/*
* thread information flags
diff --git a/include/asm-parisc/timex.h b/include/asm-parisc/timex.h
index a228b9167321b..3b68d77273d95 100644
--- a/include/asm-parisc/timex.h
+++ b/include/asm-parisc/timex.h
@@ -12,8 +12,6 @@
typedef unsigned long cycles_t;
-extern cycles_t cacheflush_time;
-
static inline cycles_t get_cycles (void)
{
return mfctl(16);
diff --git a/include/asm-parisc/uaccess.h b/include/asm-parisc/uaccess.h
index 4606ad9177847..8a08423b75706 100644
--- a/include/asm-parisc/uaccess.h
+++ b/include/asm-parisc/uaccess.h
@@ -34,8 +34,15 @@ extern int __get_user_bad(void);
extern int __put_kernel_bad(void);
extern int __put_user_bad(void);
-#define access_ok(type,addr,size) (1)
-#define verify_area(type,addr,size) (0)
+static inline long access_ok(int type, const void __user * addr,
+ unsigned long size)
+{
+ return 1;
+}
+
+#define verify_area(type,addr,size) (0) /* FIXME: all users should go away soon,
+ * and use access_ok instead, then this
+ * should be removed. */
#define put_user __put_user
#define get_user __get_user
@@ -142,22 +149,23 @@ struct exception_data {
#define __put_user(x,ptr) \
({ \
register long __pu_err __asm__ ("r8") = 0; \
+ __typeof__(*(ptr)) __x = (__typeof__(*(ptr)))(x); \
\
if (segment_eq(get_fs(),KERNEL_DS)) { \
switch (sizeof(*(ptr))) { \
- case 1: __put_kernel_asm("stb",x,ptr); break; \
- case 2: __put_kernel_asm("sth",x,ptr); break; \
- case 4: __put_kernel_asm("stw",x,ptr); break; \
- case 8: STD_KERNEL(x,ptr); break; \
+ case 1: __put_kernel_asm("stb",__x,ptr); break; \
+ case 2: __put_kernel_asm("sth",__x,ptr); break; \
+ case 4: __put_kernel_asm("stw",__x,ptr); break; \
+ case 8: STD_KERNEL(__x,ptr); break; \
default: __put_kernel_bad(); break; \
} \
} \
else { \
switch (sizeof(*(ptr))) { \
- case 1: __put_user_asm("stb",x,ptr); break; \
- case 2: __put_user_asm("sth",x,ptr); break; \
- case 4: __put_user_asm("stw",x,ptr); break; \
- case 8: STD_USER(x,ptr); break; \
+ case 1: __put_user_asm("stb",__x,ptr); break; \
+ case 2: __put_user_asm("sth",__x,ptr); break; \
+ case 4: __put_user_asm("stw",__x,ptr); break; \
+ case 8: STD_USER(__x,ptr); break; \
default: __put_user_bad(); break; \
} \
} \
diff --git a/include/asm-parisc/unaligned.h b/include/asm-parisc/unaligned.h
index 1527637aad360..0896a9f66529d 100644
--- a/include/asm-parisc/unaligned.h
+++ b/include/asm-parisc/unaligned.h
@@ -1,22 +1,7 @@
#ifndef _ASM_PARISC_UNALIGNED_H_
#define _ASM_PARISC_UNALIGNED_H_
-/* parisc can't handle unaligned accesses. */
-/* copied from asm-sparc/unaligned.h */
-
-#include <linux/string.h>
-
-
-/* Use memmove here, so gcc does not insert a __builtin_memcpy. */
-
-#define get_unaligned(ptr) \
- ({ __typeof__(*(ptr)) __tmp; memmove(&__tmp, (ptr), sizeof(*(ptr))); __tmp; })
-
-#define put_unaligned(val, ptr) \
- ({ __typeof__(*(ptr)) __tmp = (val); \
- memmove((ptr), &__tmp, sizeof(*(ptr))); \
- (void)0; })
-
+#include <asm-parisc/unaligned.h>
#ifdef __KERNEL__
struct pt_regs;
diff --git a/include/asm-parisc/unistd.h b/include/asm-parisc/unistd.h
index 4a9e76519ad04..6a9f0cadff589 100644
--- a/include/asm-parisc/unistd.h
+++ b/include/asm-parisc/unistd.h
@@ -1024,6 +1024,6 @@ asmlinkage long sys_rt_sigaction(int sig,
* What we want is __attribute__((weak,alias("sys_ni_syscall"))),
* but it doesn't work on all toolchains, so we just do it by hand
*/
-#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
+#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
#endif /* _ASM_PARISC_UNISTD_H_ */
diff --git a/include/asm-parisc/unwind.h b/include/asm-parisc/unwind.h
index ff9396b017295..2f7e6e50a1580 100644
--- a/include/asm-parisc/unwind.h
+++ b/include/asm-parisc/unwind.h
@@ -1,6 +1,8 @@
#ifndef _UNWIND_H_
#define _UNWIND_H_
+#include <linux/list.h>
+
/* From ABI specifications */
struct unwind_table_entry {
unsigned int region_start;
@@ -39,7 +41,7 @@ struct unwind_table_entry {
};
struct unwind_table {
- struct unwind_table *next;
+ struct list_head list;
const char *name;
unsigned long gp;
unsigned long base_addr;
@@ -55,15 +57,18 @@ struct unwind_frame_info {
available; but for now we only try to get the sp and ip for each
frame */
/* struct pt_regs regs; */
- unsigned long sp, ip, rp;
+ unsigned long sp, ip, rp, r31;
unsigned long prev_sp, prev_ip;
};
-void * unwind_table_add(const char *name, unsigned long base_addr,
- unsigned long gp,
- void *start, void *end);
+struct unwind_table *
+unwind_table_add(const char *name, unsigned long base_addr,
+ unsigned long gp, void *start, void *end);
+void
+unwind_table_remove(struct unwind_table *table);
+
void unwind_frame_init(struct unwind_frame_info *info, struct task_struct *t,
- unsigned long sp, unsigned long ip, unsigned long rp);
+ struct pt_regs *regs);
void unwind_frame_init_from_blocked_task(struct unwind_frame_info *info, struct task_struct *t);
void unwind_frame_init_running(struct unwind_frame_info *info, struct pt_regs *regs);
int unwind_once(struct unwind_frame_info *info);
diff --git a/include/asm-ppc/cache.h b/include/asm-ppc/cache.h
index 1fcf0f3e7b87c..38f2f1be4a87d 100644
--- a/include/asm-ppc/cache.h
+++ b/include/asm-ppc/cache.h
@@ -50,12 +50,12 @@ extern void flush_dcache_all(void);
/* Cache control on the MPC8xx is provided through some additional
* special purpose registers.
*/
-#define IC_CST 560 /* Instruction cache control/status */
-#define IC_ADR 561 /* Address needed for some commands */
-#define IC_DAT 562 /* Read-only data register */
-#define DC_CST 568 /* Data cache control/status */
-#define DC_ADR 569 /* Address needed for some commands */
-#define DC_DAT 570 /* Read-only data register */
+#define SPRN_IC_CST 560 /* Instruction cache control/status */
+#define SPRN_IC_ADR 561 /* Address needed for some commands */
+#define SPRN_IC_DAT 562 /* Read-only data register */
+#define SPRN_DC_CST 568 /* Data cache control/status */
+#define SPRN_DC_ADR 569 /* Address needed for some commands */
+#define SPRN_DC_DAT 570 /* Read-only data register */
/* Commands. Only the first few are available to the instruction cache.
*/
diff --git a/include/asm-ppc/cacheflush.h b/include/asm-ppc/cacheflush.h
index 7848d7130f332..6a243efb33174 100644
--- a/include/asm-ppc/cacheflush.h
+++ b/include/asm-ppc/cacheflush.h
@@ -22,7 +22,7 @@
#define flush_cache_all() do { } while (0)
#define flush_cache_mm(mm) do { } while (0)
#define flush_cache_range(vma, a, b) do { } while (0)
-#define flush_cache_page(vma, p) do { } while (0)
+#define flush_cache_page(vma, p, pfn) do { } while (0)
#define flush_icache_page(vma, page) do { } while (0)
#define flush_cache_vmap(start, end) do { } while (0)
#define flush_cache_vunmap(start, end) do { } while (0)
diff --git a/include/asm-ppc/cpm2.h b/include/asm-ppc/cpm2.h
index 2957e796b68d7..42fd1068cf2a4 100644
--- a/include/asm-ppc/cpm2.h
+++ b/include/asm-ppc/cpm2.h
@@ -69,6 +69,7 @@
#define CPM_CR_INIT_TX ((ushort)0x0002)
#define CPM_CR_HUNT_MODE ((ushort)0x0003)
#define CPM_CR_STOP_TX ((ushort)0x0004)
+#define CPM_CR_GRA_STOP_TX ((ushort)0x0005)
#define CPM_CR_RESTART_TX ((ushort)0x0006)
#define CPM_CR_SET_GADDR ((ushort)0x0008)
#define CPM_CR_START_IDMA ((ushort)0x0009)
@@ -85,7 +86,7 @@
*/
#define CPM_DATAONLY_BASE ((uint)128)
#define CPM_DP_NOSPACE ((uint)0x7fffffff)
-#ifdef CONFIG_8272
+#if defined(CONFIG_8272) || defined(CONFIG_MPC8555)
#define CPM_DATAONLY_SIZE ((uint)(8 * 1024) - CPM_DATAONLY_BASE)
#define CPM_FCC_SPECIAL_BASE ((uint)0x00009000)
#else
@@ -531,7 +532,7 @@ typedef struct scc_uart {
#define SCU_PSMR_RPM ((ushort)0x000c)
#define SCU_PSMR_REVP ((ushort)0x0008)
#define SCU_PSMR_TPM ((ushort)0x0003)
-#define SCU_PSMR_TEVP ((ushort)0x0003)
+#define SCU_PSMR_TEVP ((ushort)0x0002)
/* CPM Transparent mode SCC.
*/
diff --git a/include/asm-ppc/cputable.h b/include/asm-ppc/cputable.h
index 34f37ab613244..22de04fe1b4c1 100644
--- a/include/asm-ppc/cputable.h
+++ b/include/asm-ppc/cputable.h
@@ -61,6 +61,11 @@ struct cpu_spec {
extern struct cpu_spec cpu_specs[];
extern struct cpu_spec *cur_cpu_spec[];
+static inline unsigned int cpu_has_feature(unsigned int feature)
+{
+ return cur_cpu_spec[0]->cpu_features & feature;
+}
+
#endif /* __ASSEMBLY__ */
/* CPU kernel features */
diff --git a/include/asm-ppc/dma.h b/include/asm-ppc/dma.h
index 4cf83f9be9d92..cc8e5cd8c9d25 100644
--- a/include/asm-ppc/dma.h
+++ b/include/asm-ppc/dma.h
@@ -25,7 +25,6 @@
* with a grain of salt.
*/
-
#ifndef _ASM_DMA_H
#define _ASM_DMA_H
@@ -192,9 +191,9 @@ static __inline__ void release_dma_lock(unsigned long flags)
/* enable/disable a specific DMA channel */
static __inline__ void enable_dma(unsigned int dmanr)
{
- unsigned char ucDmaCmd=0x00;
+ unsigned char ucDmaCmd = 0x00;
- if (dmanr != 4) {
+ if (dmanr != 4) {
dma_outb(0, DMA2_MASK_REG); /* This may not be enabled */
dma_outb(ucDmaCmd, DMA2_CMD_REG); /* Enable group */
}
@@ -244,60 +243,58 @@ static __inline__ void set_dma_mode(unsigned int dmanr, char mode)
*/
static __inline__ void set_dma_page(unsigned int dmanr, int pagenr)
{
- switch(dmanr) {
- case 0:
- dma_outb(pagenr, DMA_LO_PAGE_0);
- dma_outb(pagenr >> 8, DMA_HI_PAGE_0);
- break;
- case 1:
- dma_outb(pagenr, DMA_LO_PAGE_1);
- dma_outb(pagenr >> 8, DMA_HI_PAGE_1);
- break;
- case 2:
- dma_outb(pagenr, DMA_LO_PAGE_2);
- dma_outb(pagenr >> 8, DMA_HI_PAGE_2);
- break;
- case 3:
- dma_outb(pagenr, DMA_LO_PAGE_3);
- dma_outb(pagenr >> 8, DMA_HI_PAGE_3);
- break;
- case 5:
- if (SND_DMA1 == 5 || SND_DMA2 == 5)
- dma_outb(pagenr, DMA_LO_PAGE_5);
- else
- dma_outb(pagenr & 0xfe, DMA_LO_PAGE_5);
- dma_outb(pagenr >> 8, DMA_HI_PAGE_5);
- break;
- case 6:
- if (SND_DMA1 == 6 || SND_DMA2 == 6)
- dma_outb(pagenr, DMA_LO_PAGE_6);
- else
- dma_outb(pagenr & 0xfe, DMA_LO_PAGE_6);
- dma_outb(pagenr >> 8, DMA_HI_PAGE_6);
- break;
- case 7:
- if (SND_DMA1 == 7 || SND_DMA2 == 7)
- dma_outb(pagenr, DMA_LO_PAGE_7);
- else
- dma_outb(pagenr & 0xfe, DMA_LO_PAGE_7);
- dma_outb(pagenr >> 8, DMA_HI_PAGE_7);
- break;
+ switch (dmanr) {
+ case 0:
+ dma_outb(pagenr, DMA_LO_PAGE_0);
+ dma_outb(pagenr >> 8, DMA_HI_PAGE_0);
+ break;
+ case 1:
+ dma_outb(pagenr, DMA_LO_PAGE_1);
+ dma_outb(pagenr >> 8, DMA_HI_PAGE_1);
+ break;
+ case 2:
+ dma_outb(pagenr, DMA_LO_PAGE_2);
+ dma_outb(pagenr >> 8, DMA_HI_PAGE_2);
+ break;
+ case 3:
+ dma_outb(pagenr, DMA_LO_PAGE_3);
+ dma_outb(pagenr >> 8, DMA_HI_PAGE_3);
+ break;
+ case 5:
+ if (SND_DMA1 == 5 || SND_DMA2 == 5)
+ dma_outb(pagenr, DMA_LO_PAGE_5);
+ else
+ dma_outb(pagenr & 0xfe, DMA_LO_PAGE_5);
+ dma_outb(pagenr >> 8, DMA_HI_PAGE_5);
+ break;
+ case 6:
+ if (SND_DMA1 == 6 || SND_DMA2 == 6)
+ dma_outb(pagenr, DMA_LO_PAGE_6);
+ else
+ dma_outb(pagenr & 0xfe, DMA_LO_PAGE_6);
+ dma_outb(pagenr >> 8, DMA_HI_PAGE_6);
+ break;
+ case 7:
+ if (SND_DMA1 == 7 || SND_DMA2 == 7)
+ dma_outb(pagenr, DMA_LO_PAGE_7);
+ else
+ dma_outb(pagenr & 0xfe, DMA_LO_PAGE_7);
+ dma_outb(pagenr >> 8, DMA_HI_PAGE_7);
+ break;
}
}
-
/* Set transfer address & page bits for specific DMA channel.
* Assumes dma flipflop is clear.
*/
static __inline__ void set_dma_addr(unsigned int dmanr, unsigned int phys)
{
if (dmanr <= 3) {
- dma_outb(phys & 0xff, ((dmanr & 3) << 1) + IO_DMA1_BASE );
+ dma_outb(phys & 0xff, ((dmanr & 3) << 1) + IO_DMA1_BASE);
dma_outb((phys >> 8) & 0xff, ((dmanr & 3) << 1) + IO_DMA1_BASE);
} else if (dmanr == SND_DMA1 || dmanr == SND_DMA2) {
- dma_outb(phys & 0xff, ((dmanr & 3) << 2) + IO_DMA2_BASE );
- dma_outb((phys >> 8) & 0xff, ((dmanr & 3) << 2) +
- IO_DMA2_BASE);
+ dma_outb(phys & 0xff, ((dmanr & 3) << 2) + IO_DMA2_BASE);
+ dma_outb((phys >> 8) & 0xff, ((dmanr & 3) << 2) + IO_DMA2_BASE);
dma_outb((dmanr & 3), DMA2_EXT_REG);
} else {
dma_outb((phys >> 1) & 0xff, ((dmanr & 3) << 2) + IO_DMA2_BASE);
@@ -306,7 +303,6 @@ static __inline__ void set_dma_addr(unsigned int dmanr, unsigned int phys)
set_dma_page(dmanr, phys >> 16);
}
-
/* Set transfer size (max 64k for DMA1..3, 128k for DMA5..7) for
* a specific DMA channel.
* You must ensure the parameters are valid.
@@ -321,16 +317,16 @@ static __inline__ void set_dma_count(unsigned int dmanr, unsigned int count)
if (dmanr <= 3) {
dma_outb(count & 0xff, ((dmanr & 3) << 1) + 1 + IO_DMA1_BASE);
dma_outb((count >> 8) & 0xff, ((dmanr & 3) << 1) + 1 +
- IO_DMA1_BASE);
+ IO_DMA1_BASE);
} else if (dmanr == SND_DMA1 || dmanr == SND_DMA2) {
- dma_outb( count & 0xff, ((dmanr & 3) << 2) + 2 + IO_DMA2_BASE);
- dma_outb( (count >> 8) & 0xff, ((dmanr & 3) << 2) + 2 +
- IO_DMA2_BASE);
+ dma_outb(count & 0xff, ((dmanr & 3) << 2) + 2 + IO_DMA2_BASE);
+ dma_outb((count >> 8) & 0xff, ((dmanr & 3) << 2) + 2 +
+ IO_DMA2_BASE);
} else {
dma_outb((count >> 1) & 0xff, ((dmanr & 3) << 2) + 2 +
- IO_DMA2_BASE);
+ IO_DMA2_BASE);
dma_outb((count >> 9) & 0xff, ((dmanr & 3) << 2) + 2 +
- IO_DMA2_BASE);
+ IO_DMA2_BASE);
}
}
@@ -345,8 +341,8 @@ static __inline__ void set_dma_count(unsigned int dmanr, unsigned int count)
static __inline__ int get_dma_residue(unsigned int dmanr)
{
unsigned int io_port = (dmanr <= 3) ?
- ((dmanr & 3) << 1) + 1 + IO_DMA1_BASE
- : ((dmanr & 3) << 2) + 2 + IO_DMA2_BASE;
+ ((dmanr & 3) << 1) + 1 + IO_DMA1_BASE
+ : ((dmanr & 3) << 2) + 2 + IO_DMA2_BASE;
/* using short to get 16-bit wrap around */
unsigned short count;
@@ -355,14 +351,14 @@ static __inline__ int get_dma_residue(unsigned int dmanr)
count += dma_inb(io_port) << 8;
return (dmanr <= 3 || dmanr == SND_DMA1 || dmanr == SND_DMA2)
- ? count : (count<<1);
+ ? count : (count << 1);
}
/* These are in kernel/dma.c: */
/* reserve a DMA channel */
-extern int request_dma(unsigned int dmanr, const char * device_id);
+extern int request_dma(unsigned int dmanr, const char *device_id);
/* release it again */
extern void free_dma(unsigned int dmanr);
@@ -371,5 +367,5 @@ extern int isa_dma_bridge_buggy;
#else
#define isa_dma_bridge_buggy (0)
#endif
-#endif /* _ASM_DMA_H */
-#endif /* __KERNEL__ */
+#endif /* _ASM_DMA_H */
+#endif /* __KERNEL__ */
diff --git a/include/asm-ppc/floppy.h b/include/asm-ppc/floppy.h
index 6bc36a194816a..8ccd4a276fe99 100644
--- a/include/asm-ppc/floppy.h
+++ b/include/asm-ppc/floppy.h
@@ -11,28 +11,149 @@
#ifndef __ASM_PPC_FLOPPY_H
#define __ASM_PPC_FLOPPY_H
-#define fd_inb(port) inb_p(port)
-#define fd_outb(value,port) outb_p(value,port)
-
-#define fd_enable_dma() enable_dma(FLOPPY_DMA)
-#define fd_disable_dma() disable_dma(FLOPPY_DMA)
-#define fd_request_dma() request_dma(FLOPPY_DMA,"floppy")
-#define fd_free_dma() free_dma(FLOPPY_DMA)
-#define fd_clear_dma_ff() clear_dma_ff(FLOPPY_DMA)
-#define fd_set_dma_mode(mode) set_dma_mode(FLOPPY_DMA,mode)
-#define fd_set_dma_addr(addr) set_dma_addr(FLOPPY_DMA,(unsigned int)virt_to_bus(addr))
-#define fd_set_dma_count(count) set_dma_count(FLOPPY_DMA,count)
+#define fd_inb(port) inb_p(port)
+#define fd_outb(value,port) outb_p(value,port)
+
+#define fd_disable_dma() fd_ops->_disable_dma(FLOPPY_DMA)
+#define fd_free_dma() fd_ops->_free_dma(FLOPPY_DMA)
+#define fd_get_dma_residue() fd_ops->_get_dma_residue(FLOPPY_DMA)
+#define fd_dma_setup(addr, size, mode, io) fd_ops->_dma_setup(addr, size, mode, io)
#define fd_enable_irq() enable_irq(FLOPPY_IRQ)
#define fd_disable_irq() disable_irq(FLOPPY_IRQ)
-#define fd_cacheflush(addr,size) /* nothing */
-#define fd_request_irq() request_irq(FLOPPY_IRQ, floppy_interrupt, \
- SA_INTERRUPT|SA_SAMPLE_RANDOM, \
- "floppy", NULL)
#define fd_free_irq() free_irq(FLOPPY_IRQ, NULL);
-__inline__ void virtual_dma_init(void)
+static int fd_request_dma(void);
+
+struct fd_dma_ops {
+ void (*_disable_dma)(unsigned int dmanr);
+ void (*_free_dma)(unsigned int dmanr);
+ int (*_get_dma_residue)(unsigned int dummy);
+ int (*_dma_setup)(char *addr, unsigned long size, int mode, int io);
+};
+
+static int virtual_dma_count;
+static int virtual_dma_residue;
+static char *virtual_dma_addr;
+static int virtual_dma_mode;
+static int doing_vdma;
+static struct fd_dma_ops *fd_ops;
+
+static irqreturn_t floppy_hardint(int irq, void *dev_id, struct pt_regs * regs)
+{
+ unsigned char st;
+ int lcount;
+ char *lptr;
+
+ if (!doing_vdma)
+ return floppy_interrupt(irq, dev_id, regs);
+
+
+ st = 1;
+ for (lcount=virtual_dma_count, lptr=virtual_dma_addr;
+ lcount; lcount--, lptr++) {
+ st=inb(virtual_dma_port+4) & 0xa0 ;
+ if (st != 0xa0)
+ break;
+ if (virtual_dma_mode)
+ outb_p(*lptr, virtual_dma_port+5);
+ else
+ *lptr = inb_p(virtual_dma_port+5);
+ }
+ virtual_dma_count = lcount;
+ virtual_dma_addr = lptr;
+ st = inb(virtual_dma_port+4);
+
+ if (st == 0x20)
+ return IRQ_HANDLED;
+ if (!(st & 0x20)) {
+ virtual_dma_residue += virtual_dma_count;
+ virtual_dma_count=0;
+ doing_vdma = 0;
+ floppy_interrupt(irq, dev_id, regs);
+ return IRQ_HANDLED;
+ }
+ return IRQ_HANDLED;
+}
+
+static void vdma_disable_dma(unsigned int dummy)
+{
+ doing_vdma = 0;
+ virtual_dma_residue += virtual_dma_count;
+ virtual_dma_count=0;
+}
+
+static void vdma_nop(unsigned int dummy)
+{
+}
+
+
+static int vdma_get_dma_residue(unsigned int dummy)
+{
+ return virtual_dma_count + virtual_dma_residue;
+}
+
+
+static int fd_request_irq(void)
+{
+ if (can_use_virtual_dma)
+ return request_irq(FLOPPY_IRQ, floppy_hardint,SA_INTERRUPT,
+ "floppy", NULL);
+ else
+ return request_irq(FLOPPY_IRQ, floppy_interrupt,
+ SA_INTERRUPT|SA_SAMPLE_RANDOM,
+ "floppy", NULL);
+
+}
+
+static int vdma_dma_setup(char *addr, unsigned long size, int mode, int io)
+{
+ doing_vdma = 1;
+ virtual_dma_port = io;
+ virtual_dma_mode = (mode == DMA_MODE_WRITE);
+ virtual_dma_addr = addr;
+ virtual_dma_count = size;
+ virtual_dma_residue = 0;
+ return 0;
+}
+
+static int hard_dma_setup(char *addr, unsigned long size, int mode, int io)
+{
+ /* actual, physical DMA */
+ doing_vdma = 0;
+ clear_dma_ff(FLOPPY_DMA);
+ set_dma_mode(FLOPPY_DMA,mode);
+ set_dma_addr(FLOPPY_DMA,(unsigned int)virt_to_bus(addr));
+ set_dma_count(FLOPPY_DMA,size);
+ enable_dma(FLOPPY_DMA);
+ return 0;
+}
+
+static struct fd_dma_ops real_dma_ops =
+{
+ ._disable_dma = disable_dma,
+ ._free_dma = free_dma,
+ ._get_dma_residue = get_dma_residue,
+ ._dma_setup = hard_dma_setup
+};
+
+static struct fd_dma_ops virt_dma_ops =
+{
+ ._disable_dma = vdma_disable_dma,
+ ._free_dma = vdma_nop,
+ ._get_dma_residue = vdma_get_dma_residue,
+ ._dma_setup = vdma_dma_setup
+};
+
+static int fd_request_dma()
{
- /* Nothing to do on PowerPC */
+ if (can_use_virtual_dma & 1) {
+ fd_ops = &virt_dma_ops;
+ return 0;
+ }
+ else {
+ fd_ops = &real_dma_ops;
+ return request_dma(FLOPPY_DMA, "floppy");
+ }
}
static int FDC1 = 0x3f0;
diff --git a/include/asm-ppc/highmem.h b/include/asm-ppc/highmem.h
index 7cda32eb12376..1d2c4ef81c223 100644
--- a/include/asm-ppc/highmem.h
+++ b/include/asm-ppc/highmem.h
@@ -35,8 +35,6 @@ extern pte_t *kmap_pte;
extern pgprot_t kmap_prot;
extern pte_t *pkmap_page_table;
-extern void kmap_init(void) __init;
-
/*
* Right now we initialize only a single pte table. It can be extended
* easily, subsequent pte tables have to be allocated in one physical
@@ -90,7 +88,7 @@ static inline void *kmap_atomic(struct page *page, enum km_type type)
#ifdef HIGHMEM_DEBUG
BUG_ON(!pte_none(*(kmap_pte+idx)));
#endif
- set_pte(kmap_pte+idx, mk_pte(page, kmap_prot));
+ set_pte_at(&init_mm, vaddr, kmap_pte+idx, mk_pte(page, kmap_prot));
flush_tlb_page(NULL, vaddr);
return (void*) vaddr;
@@ -114,7 +112,7 @@ static inline void kunmap_atomic(void *kvaddr, enum km_type type)
* force other mappings to Oops if they'll try to access
* this pte without first remap it
*/
- pte_clear(kmap_pte+idx);
+ pte_clear(&init_mm, vaddr, kmap_pte+idx);
flush_tlb_page(NULL, vaddr);
#endif
dec_preempt_count();
diff --git a/include/asm-ppc/io.h b/include/asm-ppc/io.h
index fb514f700e65d..7eb7cf6360bd1 100644
--- a/include/asm-ppc/io.h
+++ b/include/asm-ppc/io.h
@@ -30,6 +30,8 @@
#include <asm/mpc8xx.h>
#elif defined(CONFIG_8260)
#include <asm/mpc8260.h>
+#elif defined(CONFIG_83xx)
+#include <asm/mpc83xx.h>
#elif defined(CONFIG_85xx)
#include <asm/mpc85xx.h>
#elif defined(CONFIG_APUS)
@@ -550,4 +552,15 @@ extern void pci_iounmap(struct pci_dev *dev, void __iomem *);
#include <asm/mpc8260_pci9.h>
#endif
+/*
+ * Convert a physical pointer to a virtual kernel pointer for /dev/mem
+ * access
+ */
+#define xlate_dev_mem_ptr(p) __va(p)
+
+/*
+ * Convert a virtual cached pointer to an uncached pointer
+ */
+#define xlate_dev_kmem_ptr(p) p
+
#endif /* __KERNEL__ */
diff --git a/include/asm-ppc/ipc.h b/include/asm-ppc/ipc.h
index 512dfe962d8bb..a46e3d9c2a3fc 100644
--- a/include/asm-ppc/ipc.h
+++ b/include/asm-ppc/ipc.h
@@ -1,29 +1 @@
-#ifndef __PPC_IPC_H__
-#define __PPC_IPC_H__
-
-/*
- * These are used to wrap system calls on PowerPC.
- *
- * See arch/ppc/kernel/syscalls.c for ugly details..
- */
-struct ipc_kludge {
- struct msgbuf __user *msgp;
- long msgtyp;
-};
-
-#define SEMOP 1
-#define SEMGET 2
-#define SEMCTL 3
-#define SEMTIMEDOP 4
-#define MSGSND 11
-#define MSGRCV 12
-#define MSGGET 13
-#define MSGCTL 14
-#define SHMAT 21
-#define SHMDT 22
-#define SHMGET 23
-#define SHMCTL 24
-
-#define IPCCALL(version,op) ((version)<<16 | (op))
-
-#endif /* __PPC_IPC_H__ */
+#include <asm-generic/ipc.h>
diff --git a/include/asm-ppc/ipic.h b/include/asm-ppc/ipic.h
new file mode 100644
index 0000000000000..9092b920997a6
--- /dev/null
+++ b/include/asm-ppc/ipic.h
@@ -0,0 +1,85 @@
+/*
+ * include/asm-ppc/ipic.h
+ *
+ * IPIC external definitions and structure.
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2005 Freescale Semiconductor, Inc
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+#ifdef __KERNEL__
+#ifndef __ASM_IPIC_H__
+#define __ASM_IPIC_H__
+
+#include <linux/irq.h>
+
+/* Flags when we init the IPIC */
+#define IPIC_SPREADMODE_GRP_A 0x00000001
+#define IPIC_SPREADMODE_GRP_D 0x00000002
+#define IPIC_SPREADMODE_MIX_A 0x00000004
+#define IPIC_SPREADMODE_MIX_B 0x00000008
+#define IPIC_DISABLE_MCP_OUT 0x00000010
+#define IPIC_IRQ0_MCP 0x00000020
+
+/* IPIC registers offsets */
+#define IPIC_SICFR 0x00 /* System Global Interrupt Configuration Register */
+#define IPIC_SIVCR 0x04 /* System Global Interrupt Vector Register */
+#define IPIC_SIPNR_H 0x08 /* System Internal Interrupt Pending Register (HIGH) */
+#define IPIC_SIPNR_L 0x0C /* System Internal Interrupt Pending Register (LOW) */
+#define IPIC_SIPRR_A 0x10 /* System Internal Interrupt group A Priority Register */
+#define IPIC_SIPRR_B 0x14 /* System Internal Interrupt group B Priority Register */
+#define IPIC_SIPRR_C 0x18 /* System Internal Interrupt group C Priority Register */
+#define IPIC_SIPRR_D 0x1C /* System Internal Interrupt group D Priority Register */
+#define IPIC_SIMSR_H 0x20 /* System Internal Interrupt Mask Register (HIGH) */
+#define IPIC_SIMSR_L 0x24 /* System Internal Interrupt Mask Register (LOW) */
+#define IPIC_SICNR 0x28 /* System Internal Interrupt Control Register */
+#define IPIC_SEPNR 0x2C /* System External Interrupt Pending Register */
+#define IPIC_SMPRR_A 0x30 /* System Mixed Interrupt group A Priority Register */
+#define IPIC_SMPRR_B 0x34 /* System Mixed Interrupt group B Priority Register */
+#define IPIC_SEMSR 0x38 /* System External Interrupt Mask Register */
+#define IPIC_SECNR 0x3C /* System External Interrupt Control Register */
+#define IPIC_SERSR 0x40 /* System Error Status Register */
+#define IPIC_SERMR 0x44 /* System Error Mask Register */
+#define IPIC_SERCR 0x48 /* System Error Control Register */
+#define IPIC_SIFCR_H 0x50 /* System Internal Interrupt Force Register (HIGH) */
+#define IPIC_SIFCR_L 0x54 /* System Internal Interrupt Force Register (LOW) */
+#define IPIC_SEFCR 0x58 /* System External Interrupt Force Register */
+#define IPIC_SERFR 0x5C /* System Error Force Register */
+#define IPIC_SCVCR 0x60 /* System Critical Interrupt Vector Register */
+#define IPIC_SMVCR 0x64 /* System Management Interrupt Vector Register */
+
+enum ipic_prio_grp {
+ IPIC_INT_GRP_A = IPIC_SIPRR_A,
+ IPIC_INT_GRP_D = IPIC_SIPRR_D,
+ IPIC_MIX_GRP_A = IPIC_SMPRR_A,
+ IPIC_MIX_GRP_B = IPIC_SMPRR_B,
+};
+
+enum ipic_mcp_irq {
+ IPIC_MCP_IRQ0 = 0,
+ IPIC_MCP_WDT = 1,
+ IPIC_MCP_SBA = 2,
+ IPIC_MCP_PCI1 = 5,
+ IPIC_MCP_PCI2 = 6,
+ IPIC_MCP_MU = 7,
+};
+
+extern void ipic_init(phys_addr_t phys_addr, unsigned int flags,
+ unsigned int irq_offset,
+ unsigned char *senses, unsigned int senses_count);
+extern int ipic_set_priority(unsigned int irq, unsigned int priority);
+extern void ipic_set_highest_priority(unsigned int irq);
+extern void ipic_set_default_priority(void);
+extern void ipic_enable_mcp(enum ipic_mcp_irq mcp_irq);
+extern void ipic_disable_mcp(enum ipic_mcp_irq mcp_irq);
+extern u32 ipic_get_mcp_status(void);
+extern void ipic_clear_mcp_status(u32 mask);
+extern int ipic_get_irq(struct pt_regs *regs);
+
+#endif /* __ASM_IPIC_H__ */
+#endif /* __KERNEL__ */
diff --git a/include/asm-ppc/irq.h b/include/asm-ppc/irq.h
index 8aae5e80c1e66..06b86be61ed13 100644
--- a/include/asm-ppc/irq.h
+++ b/include/asm-ppc/irq.h
@@ -161,7 +161,17 @@ static __inline__ int irq_canonicalize(int irq)
return irq;
}
-#elif defined(CONFIG_CPM2) && defined(CONFIG_85xx)
+#elif defined(CONFIG_83xx)
+#include <asm/mpc83xx.h>
+
+static __inline__ int irq_canonicalize(int irq)
+{
+ return irq;
+}
+
+#define NR_IRQS (NR_IPIC_INTS)
+
+#elif defined(CONFIG_85xx)
/* Now include the board configuration specific associations.
*/
#include <asm/mpc85xx.h>
@@ -176,7 +186,7 @@ static __inline__ int irq_canonicalize(int irq)
#define NR_CPM_INTS 64
#define NR_EPIC_INTS 44
#ifndef NR_8259_INTS
-#define NR_8259_INTS 0
+#define NR_8259_INTS 0
#endif
#define NUM_8259_INTERRUPTS NR_8259_INTS
@@ -186,13 +196,59 @@ static __inline__ int irq_canonicalize(int irq)
#define NR_IRQS (NR_EPIC_INTS + NR_CPM_INTS + NR_8259_INTS)
-/* These values must be zero-based and map 1:1 with the EPIC configuration.
- * They are used throughout the 8560 I/O subsystem to generate
- * interrupt masks, flags, and other control patterns. This is why the
- * current kernel assumption of the 8259 as the base controller is such
- * a pain in the butt.
- */
+/* Internal IRQs on MPC85xx OpenPIC */
+
+#ifndef MPC85xx_OPENPIC_IRQ_OFFSET
+#ifdef CONFIG_CPM2
+#define MPC85xx_OPENPIC_IRQ_OFFSET (CPM_IRQ_OFFSET + NR_CPM_INTS)
+#else
+#define MPC85xx_OPENPIC_IRQ_OFFSET 0
+#endif
+#endif
+/* Not all of these exist on all MPC85xx implementations */
+#define MPC85xx_IRQ_L2CACHE ( 0 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_ECM ( 1 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_DDR ( 2 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_LBIU ( 3 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_DMA0 ( 4 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_DMA1 ( 5 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_DMA2 ( 6 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_DMA3 ( 7 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_PCI1 ( 8 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_PCI2 ( 9 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_RIO_ERROR ( 9 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_RIO_BELL (10 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_RIO_TX (11 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_RIO_RX (12 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_TSEC1_TX (13 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_TSEC1_RX (14 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_TSEC1_ERROR (18 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_TSEC2_TX (19 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_TSEC2_RX (20 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_TSEC2_ERROR (24 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_FEC (25 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_DUART (26 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_IIC1 (27 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_PERFMON (28 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_SEC2 (29 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_CPM (30 + MPC85xx_OPENPIC_IRQ_OFFSET)
+
+/* The 12 external interrupt lines */
+#define MPC85xx_IRQ_EXT0 (32 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT1 (33 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT2 (34 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT3 (35 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT4 (36 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT5 (37 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT6 (38 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT7 (39 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT8 (40 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT9 (41 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT10 (42 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT11 (43 + MPC85xx_OPENPIC_IRQ_OFFSET)
+
+/* CPM related interrupts */
#define SIU_INT_ERROR ((uint)0x00+CPM_IRQ_OFFSET)
#define SIU_INT_I2C ((uint)0x01+CPM_IRQ_OFFSET)
#define SIU_INT_SPI ((uint)0x02+CPM_IRQ_OFFSET)
@@ -257,57 +313,62 @@ static __inline__ int irq_canonicalize(int irq)
* (Document errata updates have fixed this...make sure you have up to
* date processor documentation -- Dan).
*/
-#define NR_SIU_INTS 64
-
-#define SIU_INT_ERROR ((uint)0x00)
-#define SIU_INT_I2C ((uint)0x01)
-#define SIU_INT_SPI ((uint)0x02)
-#define SIU_INT_RISC ((uint)0x03)
-#define SIU_INT_SMC1 ((uint)0x04)
-#define SIU_INT_SMC2 ((uint)0x05)
-#define SIU_INT_IDMA1 ((uint)0x06)
-#define SIU_INT_IDMA2 ((uint)0x07)
-#define SIU_INT_IDMA3 ((uint)0x08)
-#define SIU_INT_IDMA4 ((uint)0x09)
-#define SIU_INT_SDMA ((uint)0x0a)
-#define SIU_INT_TIMER1 ((uint)0x0c)
-#define SIU_INT_TIMER2 ((uint)0x0d)
-#define SIU_INT_TIMER3 ((uint)0x0e)
-#define SIU_INT_TIMER4 ((uint)0x0f)
-#define SIU_INT_TMCNT ((uint)0x10)
-#define SIU_INT_PIT ((uint)0x11)
-#define SIU_INT_IRQ1 ((uint)0x13)
-#define SIU_INT_IRQ2 ((uint)0x14)
-#define SIU_INT_IRQ3 ((uint)0x15)
-#define SIU_INT_IRQ4 ((uint)0x16)
-#define SIU_INT_IRQ5 ((uint)0x17)
-#define SIU_INT_IRQ6 ((uint)0x18)
-#define SIU_INT_IRQ7 ((uint)0x19)
-#define SIU_INT_FCC1 ((uint)0x20)
-#define SIU_INT_FCC2 ((uint)0x21)
-#define SIU_INT_FCC3 ((uint)0x22)
-#define SIU_INT_MCC1 ((uint)0x24)
-#define SIU_INT_MCC2 ((uint)0x25)
-#define SIU_INT_SCC1 ((uint)0x28)
-#define SIU_INT_SCC2 ((uint)0x29)
-#define SIU_INT_SCC3 ((uint)0x2a)
-#define SIU_INT_SCC4 ((uint)0x2b)
-#define SIU_INT_PC15 ((uint)0x30)
-#define SIU_INT_PC14 ((uint)0x31)
-#define SIU_INT_PC13 ((uint)0x32)
-#define SIU_INT_PC12 ((uint)0x33)
-#define SIU_INT_PC11 ((uint)0x34)
-#define SIU_INT_PC10 ((uint)0x35)
-#define SIU_INT_PC9 ((uint)0x36)
-#define SIU_INT_PC8 ((uint)0x37)
-#define SIU_INT_PC7 ((uint)0x38)
-#define SIU_INT_PC6 ((uint)0x39)
-#define SIU_INT_PC5 ((uint)0x3a)
-#define SIU_INT_PC4 ((uint)0x3b)
-#define SIU_INT_PC3 ((uint)0x3c)
-#define SIU_INT_PC2 ((uint)0x3d)
-#define SIU_INT_PC1 ((uint)0x3e)
-#define SIU_INT_PC0 ((uint)0x3f)
+
+#ifndef CPM_IRQ_OFFSET
+#define CPM_IRQ_OFFSET 0
+#endif
+
+#define NR_CPM_INTS 64
+
+#define SIU_INT_ERROR ((uint)0x00 + CPM_IRQ_OFFSET)
+#define SIU_INT_I2C ((uint)0x01 + CPM_IRQ_OFFSET)
+#define SIU_INT_SPI ((uint)0x02 + CPM_IRQ_OFFSET)
+#define SIU_INT_RISC ((uint)0x03 + CPM_IRQ_OFFSET)
+#define SIU_INT_SMC1 ((uint)0x04 + CPM_IRQ_OFFSET)
+#define SIU_INT_SMC2 ((uint)0x05 + CPM_IRQ_OFFSET)
+#define SIU_INT_IDMA1 ((uint)0x06 + CPM_IRQ_OFFSET)
+#define SIU_INT_IDMA2 ((uint)0x07 + CPM_IRQ_OFFSET)
+#define SIU_INT_IDMA3 ((uint)0x08 + CPM_IRQ_OFFSET)
+#define SIU_INT_IDMA4 ((uint)0x09 + CPM_IRQ_OFFSET)
+#define SIU_INT_SDMA ((uint)0x0a + CPM_IRQ_OFFSET)
+#define SIU_INT_TIMER1 ((uint)0x0c + CPM_IRQ_OFFSET)
+#define SIU_INT_TIMER2 ((uint)0x0d + CPM_IRQ_OFFSET)
+#define SIU_INT_TIMER3 ((uint)0x0e + CPM_IRQ_OFFSET)
+#define SIU_INT_TIMER4 ((uint)0x0f + CPM_IRQ_OFFSET)
+#define SIU_INT_TMCNT ((uint)0x10 + CPM_IRQ_OFFSET)
+#define SIU_INT_PIT ((uint)0x11 + CPM_IRQ_OFFSET)
+#define SIU_INT_IRQ1 ((uint)0x13 + CPM_IRQ_OFFSET)
+#define SIU_INT_IRQ2 ((uint)0x14 + CPM_IRQ_OFFSET)
+#define SIU_INT_IRQ3 ((uint)0x15 + CPM_IRQ_OFFSET)
+#define SIU_INT_IRQ4 ((uint)0x16 + CPM_IRQ_OFFSET)
+#define SIU_INT_IRQ5 ((uint)0x17 + CPM_IRQ_OFFSET)
+#define SIU_INT_IRQ6 ((uint)0x18 + CPM_IRQ_OFFSET)
+#define SIU_INT_IRQ7 ((uint)0x19 + CPM_IRQ_OFFSET)
+#define SIU_INT_FCC1 ((uint)0x20 + CPM_IRQ_OFFSET)
+#define SIU_INT_FCC2 ((uint)0x21 + CPM_IRQ_OFFSET)
+#define SIU_INT_FCC3 ((uint)0x22 + CPM_IRQ_OFFSET)
+#define SIU_INT_MCC1 ((uint)0x24 + CPM_IRQ_OFFSET)
+#define SIU_INT_MCC2 ((uint)0x25 + CPM_IRQ_OFFSET)
+#define SIU_INT_SCC1 ((uint)0x28 + CPM_IRQ_OFFSET)
+#define SIU_INT_SCC2 ((uint)0x29 + CPM_IRQ_OFFSET)
+#define SIU_INT_SCC3 ((uint)0x2a + CPM_IRQ_OFFSET)
+#define SIU_INT_SCC4 ((uint)0x2b + CPM_IRQ_OFFSET)
+#define SIU_INT_PC15 ((uint)0x30 + CPM_IRQ_OFFSET)
+#define SIU_INT_PC14 ((uint)0x31 + CPM_IRQ_OFFSET)
+#define SIU_INT_PC13 ((uint)0x32 + CPM_IRQ_OFFSET)
+#define SIU_INT_PC12 ((uint)0x33 + CPM_IRQ_OFFSET)
+#define SIU_INT_PC11 ((uint)0x34 + CPM_IRQ_OFFSET)
+#define SIU_INT_PC10 ((uint)0x35 + CPM_IRQ_OFFSET)
+#define SIU_INT_PC9 ((uint)0x36 + CPM_IRQ_OFFSET)
+#define SIU_INT_PC8 ((uint)0x37 + CPM_IRQ_OFFSET)
+#define SIU_INT_PC7 ((uint)0x38 + CPM_IRQ_OFFSET)
+#define SIU_INT_PC6 ((uint)0x39 + CPM_IRQ_OFFSET)
+#define SIU_INT_PC5 ((uint)0x3a + CPM_IRQ_OFFSET)
+#define SIU_INT_PC4 ((uint)0x3b + CPM_IRQ_OFFSET)
+#define SIU_INT_PC3 ((uint)0x3c + CPM_IRQ_OFFSET)
+#define SIU_INT_PC2 ((uint)0x3d + CPM_IRQ_OFFSET)
+#define SIU_INT_PC1 ((uint)0x3e + CPM_IRQ_OFFSET)
+#define SIU_INT_PC0 ((uint)0x3f + CPM_IRQ_OFFSET)
#endif /* CONFIG_8260 */
diff --git a/include/asm-ppc/machdep.h b/include/asm-ppc/machdep.h
index 87a5501638fc4..b78d40870c951 100644
--- a/include/asm-ppc/machdep.h
+++ b/include/asm-ppc/machdep.h
@@ -6,6 +6,7 @@
#include <linux/init.h>
#include <asm/setup.h>
+#include <asm/page.h>
#ifdef CONFIG_APUS
#include <asm-m68k/machdep.h>
@@ -15,6 +16,7 @@ struct pt_regs;
struct pci_bus;
struct pci_dev;
struct seq_file;
+struct file;
/* We export this macro for external modules like Alsa to know if
* ppc_md.feature_call is implemented or not
@@ -93,6 +95,12 @@ struct machdep_calls {
/* Called at then very end of pcibios_init() */
void (*pcibios_after_init)(void);
+ /* Get access protection for /dev/mem */
+ pgprot_t (*phys_mem_access_prot)(struct file *file,
+ unsigned long offset,
+ unsigned long size,
+ pgprot_t vma_prot);
+
/* this is for modules, since _machine can be a define -- Cort */
int ppc_machine;
@@ -121,6 +129,7 @@ typedef enum sys_ctrler_kind {
SYS_CTRLER_UNKNOWN = 0,
SYS_CTRLER_CUDA = 1,
SYS_CTRLER_PMU = 2,
+ SYS_CTRLER_SMU = 3,
} sys_ctrler_t;
extern sys_ctrler_t sys_ctrler;
diff --git a/include/asm-ppc/mmu.h b/include/asm-ppc/mmu.h
index 4d1d4fac3133e..4a0c67f672c2c 100644
--- a/include/asm-ppc/mmu.h
+++ b/include/asm-ppc/mmu.h
@@ -152,7 +152,7 @@ typedef struct _P601_BAT {
* is written, and the contents of several registers are used to
* create the entry.
*/
-#define MI_CTR 784 /* Instruction TLB control register */
+#define SPRN_MI_CTR 784 /* Instruction TLB control register */
#define MI_GPM 0x80000000 /* Set domain manager mode */
#define MI_PPM 0x40000000 /* Set subpage protection */
#define MI_CIDEF 0x20000000 /* Set cache inhibit when MMU dis */
@@ -164,7 +164,7 @@ typedef struct _P601_BAT {
/* These are the Ks and Kp from the PowerPC books. For proper operation,
* Ks = 0, Kp = 1.
*/
-#define MI_AP 786
+#define SPRN_MI_AP 786
#define MI_Ks 0x80000000 /* Should not be set */
#define MI_Kp 0x40000000 /* Should always be set */
@@ -172,7 +172,7 @@ typedef struct _P601_BAT {
* about the last instruction TLB miss. When MI_RPN is written, bits in
* this register are used to create the TLB entry.
*/
-#define MI_EPN 787
+#define SPRN_MI_EPN 787
#define MI_EPNMASK 0xfffff000 /* Effective page number for entry */
#define MI_EVALID 0x00000200 /* Entry is valid */
#define MI_ASIDMASK 0x0000000f /* ASID match value */
@@ -182,7 +182,7 @@ typedef struct _P601_BAT {
* For the instruction TLB, it contains bits that get loaded into the
* TLB entry when the MI_RPN is written.
*/
-#define MI_TWC 789
+#define SPRN_MI_TWC 789
#define MI_APG 0x000001e0 /* Access protection group (0) */
#define MI_GUARDED 0x00000010 /* Guarded storage */
#define MI_PSMASK 0x0000000c /* Mask of page size bits */
@@ -196,7 +196,7 @@ typedef struct _P601_BAT {
* causes a TLB entry to be created for the instruction TLB, using
* additional information from the MI_EPN, and MI_TWC registers.
*/
-#define MI_RPN 790
+#define SPRN_MI_RPN 790
/* Define an RPN value for mapping kernel memory to large virtual
* pages for boot initialization. This has real page number of 0,
@@ -205,7 +205,7 @@ typedef struct _P601_BAT {
*/
#define MI_BOOTINIT 0x000001fd
-#define MD_CTR 792 /* Data TLB control register */
+#define SPRN_MD_CTR 792 /* Data TLB control register */
#define MD_GPM 0x80000000 /* Set domain manager mode */
#define MD_PPM 0x40000000 /* Set subpage protection */
#define MD_CIDEF 0x20000000 /* Set cache inhibit when MMU dis */
@@ -216,14 +216,14 @@ typedef struct _P601_BAT {
#define MD_IDXMASK 0x00001f00 /* TLB index to be loaded */
#define MD_RESETVAL 0x04000000 /* Value of register at reset */
-#define M_CASID 793 /* Address space ID (context) to match */
+#define SPRN_M_CASID 793 /* Address space ID (context) to match */
#define MC_ASIDMASK 0x0000000f /* Bits used for ASID value */
/* These are the Ks and Kp from the PowerPC books. For proper operation,
* Ks = 0, Kp = 1.
*/
-#define MD_AP 794
+#define SPRN_MD_AP 794
#define MD_Ks 0x80000000 /* Should not be set */
#define MD_Kp 0x40000000 /* Should always be set */
@@ -231,7 +231,7 @@ typedef struct _P601_BAT {
* about the last instruction TLB miss. When MD_RPN is written, bits in
* this register are used to create the TLB entry.
*/
-#define MD_EPN 795
+#define SPRN_MD_EPN 795
#define MD_EPNMASK 0xfffff000 /* Effective page number for entry */
#define MD_EVALID 0x00000200 /* Entry is valid */
#define MD_ASIDMASK 0x0000000f /* ASID match value */
@@ -241,7 +241,7 @@ typedef struct _P601_BAT {
* During a software tablewalk, reading this register provides the address
* of the entry associated with MD_EPN.
*/
-#define M_TWB 796
+#define SPRN_M_TWB 796
#define M_L1TB 0xfffff000 /* Level 1 table base address */
#define M_L1INDX 0x00000ffc /* Level 1 index, when read */
/* Reset value is undefined */
@@ -251,7 +251,7 @@ typedef struct _P601_BAT {
* when the MD_RPN is written. It is also provides the hardware assist
* for finding the PTE address during software tablewalk.
*/
-#define MD_TWC 797
+#define SPRN_MD_TWC 797
#define MD_L2TB 0xfffff000 /* Level 2 table base address */
#define MD_L2INDX 0xfffffe00 /* Level 2 index (*pte), when read */
#define MD_APG 0x000001e0 /* Access protection group (0) */
@@ -269,12 +269,12 @@ typedef struct _P601_BAT {
* causes a TLB entry to be created for the data TLB, using
* additional information from the MD_EPN, and MD_TWC registers.
*/
-#define MD_RPN 798
+#define SPRN_MD_RPN 798
/* This is a temporary storage register that could be used to save
* a processor working register during a tablewalk.
*/
-#define M_TW 799
+#define SPRN_M_TW 799
/*
* At present, all PowerPC 400-class processors share a similar TLB
diff --git a/include/asm-ppc/mpc10x.h b/include/asm-ppc/mpc10x.h
index 624debe1cc540..d8e7e2d6128e7 100644
--- a/include/asm-ppc/mpc10x.h
+++ b/include/asm-ppc/mpc10x.h
@@ -115,8 +115,8 @@
#define MPC10X_CFG_MAPB_OPTIONS_CFAE 0x80 /* CPU_FD_ALIAS_EN */
#define MPC10X_CFG_MAPB_OPTIONS_PFAE 0x40 /* PCI_FD_ALIAS_EN */
#define MPC10X_CFG_MAPB_OPTIONS_DR 0x20 /* DLL_RESET */
-#define MPC10X_CFG_MAPB_OPTIONS_PCICH 0x80 /* PCI_COMPATIBILITY_HOLE */
-#define MPC10X_CFG_MAPB_OPTIONS_PROCCH 0x40 /* PROC_COMPATIBILITY_HOLE */
+#define MPC10X_CFG_MAPB_OPTIONS_PCICH 0x08 /* PCI_COMPATIBILITY_HOLE */
+#define MPC10X_CFG_MAPB_OPTIONS_PROCCH 0x04 /* PROC_COMPATIBILITY_HOLE */
/* Define offsets for the memory controller registers in the config space */
#define MPC10X_MCTLR_MEM_START_1 0x80 /* Banks 0-3 */
diff --git a/include/asm-ppc/mpc52xx.h b/include/asm-ppc/mpc52xx.h
index 76e4402f701f9..e5f80c22fbfcf 100644
--- a/include/asm-ppc/mpc52xx.h
+++ b/include/asm-ppc/mpc52xx.h
@@ -10,7 +10,7 @@
* Originally written by Dale Farnsworth <dfarnsworth@mvista.com>
* for the 2.4 kernel.
*
- * Copyright (C) 2004 Sylvain Munaut <tnt@246tNt.com>
+ * Copyright (C) 2004-2005 Sylvain Munaut <tnt@246tNt.com>
* Copyright (C) 2003 MontaVista, Software, Inc.
*
* This file is licensed under the terms of the GNU General Public License
@@ -26,53 +26,73 @@
#include <asm/types.h>
struct pt_regs;
-struct ocp_def;
#endif /* __ASSEMBLY__ */
/* ======================================================================== */
+/* PPC Sys devices definition */
+/* ======================================================================== */
+
+enum ppc_sys_devices {
+ MPC52xx_MSCAN1,
+ MPC52xx_MSCAN2,
+ MPC52xx_SPI,
+ MPC52xx_USB,
+ MPC52xx_BDLC,
+ MPC52xx_PSC1,
+ MPC52xx_PSC2,
+ MPC52xx_PSC3,
+ MPC52xx_PSC4,
+ MPC52xx_PSC5,
+ MPC52xx_PSC6,
+ MPC52xx_FEC,
+ MPC52xx_ATA,
+ MPC52xx_I2C1,
+ MPC52xx_I2C2,
+};
+
+
+/* ======================================================================== */
/* Main registers/struct addresses */
/* ======================================================================== */
-/* Theses are PHYSICAL addresses ! */
-/* TODO : There should be no static mapping, but it's not yet the case, so */
-/* we require a 1:1 mapping */
+/* MBAR position */
#define MPC52xx_MBAR 0xf0000000 /* Phys address */
-#define MPC52xx_MBAR_SIZE 0x00010000
#define MPC52xx_MBAR_VIRT 0xf0000000 /* Virt address */
+#define MPC52xx_MBAR_SIZE 0x00010000
-#define MPC52xx_MMAP_CTL (MPC52xx_MBAR + 0x0000)
-#define MPC52xx_SDRAM (MPC52xx_MBAR + 0x0100)
-#define MPC52xx_CDM (MPC52xx_MBAR + 0x0200)
-#define MPC52xx_SFTRST (MPC52xx_MBAR + 0x0220)
-#define MPC52xx_SFTRST_BIT 0x01000000
-#define MPC52xx_INTR (MPC52xx_MBAR + 0x0500)
-#define MPC52xx_GPTx(x) (MPC52xx_MBAR + 0x0600 + ((x)<<4))
-#define MPC52xx_RTC (MPC52xx_MBAR + 0x0800)
-#define MPC52xx_MSCAN1 (MPC52xx_MBAR + 0x0900)
-#define MPC52xx_MSCAN2 (MPC52xx_MBAR + 0x0980)
-#define MPC52xx_GPIO (MPC52xx_MBAR + 0x0b00)
-#define MPC52xx_GPIO_WKUP (MPC52xx_MBAR + 0x0c00)
-#define MPC52xx_PCI (MPC52xx_MBAR + 0x0d00)
-#define MPC52xx_USB_OHCI (MPC52xx_MBAR + 0x1000)
-#define MPC52xx_SDMA (MPC52xx_MBAR + 0x1200)
-#define MPC52xx_XLB (MPC52xx_MBAR + 0x1f00)
-#define MPC52xx_PSCx(x) (MPC52xx_MBAR + 0x2000 + ((x)<<9))
-#define MPC52xx_PSC1 (MPC52xx_MBAR + 0x2000)
-#define MPC52xx_PSC2 (MPC52xx_MBAR + 0x2200)
-#define MPC52xx_PSC3 (MPC52xx_MBAR + 0x2400)
-#define MPC52xx_PSC4 (MPC52xx_MBAR + 0x2600)
-#define MPC52xx_PSC5 (MPC52xx_MBAR + 0x2800)
-#define MPC52xx_PSC6 (MPC52xx_MBAR + 0x2C00)
-#define MPC52xx_FEC (MPC52xx_MBAR + 0x3000)
-#define MPC52xx_ATA (MPC52xx_MBAR + 0x3a00)
-#define MPC52xx_I2C1 (MPC52xx_MBAR + 0x3d00)
-#define MPC52xx_I2C_MICR (MPC52xx_MBAR + 0x3d20)
-#define MPC52xx_I2C2 (MPC52xx_MBAR + 0x3d40)
+#define MPC52xx_PA(x) ((phys_addr_t)(MPC52xx_MBAR + (x)))
+#define MPC52xx_VA(x) ((void __iomem *)(MPC52xx_MBAR_VIRT + (x)))
+
+/* Registers zone offset/size */
+#define MPC52xx_MMAP_CTL_OFFSET 0x0000
+#define MPC52xx_MMAP_CTL_SIZE 0x068
+#define MPC52xx_SDRAM_OFFSET 0x0100
+#define MPC52xx_SDRAM_SIZE 0x010
+#define MPC52xx_CDM_OFFSET 0x0200
+#define MPC52xx_CDM_SIZE 0x038
+#define MPC52xx_INTR_OFFSET 0x0500
+#define MPC52xx_INTR_SIZE 0x04c
+#define MPC52xx_GPTx_OFFSET(x) (0x0600 + ((x)<<4))
+#define MPC52xx_GPT_SIZE 0x010
+#define MPC52xx_RTC_OFFSET 0x0800
+#define MPC52xx_RTC_SIZE 0x024
+#define MPC52xx_GPIO_OFFSET 0x0b00
+#define MPC52xx_GPIO_SIZE 0x040
+#define MPC52xx_GPIO_WKUP_OFFSET 0x0c00
+#define MPC52xx_GPIO_WKUP_SIZE 0x028
+#define MPC52xx_PCI_OFFSET 0x0d00
+#define MPC52xx_PCI_SIZE 0x100
+#define MPC52xx_SDMA_OFFSET 0x1200
+#define MPC52xx_SDMA_SIZE 0x100
+#define MPC52xx_XLB_OFFSET 0x1f00
+#define MPC52xx_XLB_SIZE 0x100
+#define MPC52xx_PSCx_OFFSET(x) (((x)!=6)?(0x1e00+((x)<<9)):0x2c00)
+#define MPC52xx_PSC_SIZE 0x0a0
/* SRAM used for SDMA */
-#define MPC52xx_SRAM (MPC52xx_MBAR + 0x8000)
-#define MPC52xx_SRAM_SIZE (16*1024)
+#define MPC52xx_SRAM_OFFSET 0x8000
+#define MPC52xx_SRAM_SIZE 0x4000
/* ======================================================================== */
@@ -119,11 +139,12 @@ struct ocp_def;
#define MPC52xx_SPI_SPIF_IRQ (MPC52xx_PERP_IRQ_BASE + 14)
#define MPC52xx_I2C1_IRQ (MPC52xx_PERP_IRQ_BASE + 15)
#define MPC52xx_I2C2_IRQ (MPC52xx_PERP_IRQ_BASE + 16)
-#define MPC52xx_CAN1_IRQ (MPC52xx_PERP_IRQ_BASE + 17)
-#define MPC52xx_CAN2_IRQ (MPC52xx_PERP_IRQ_BASE + 18)
+#define MPC52xx_MSCAN1_IRQ (MPC52xx_PERP_IRQ_BASE + 17)
+#define MPC52xx_MSCAN2_IRQ (MPC52xx_PERP_IRQ_BASE + 18)
#define MPC52xx_IR_RX_IRQ (MPC52xx_PERP_IRQ_BASE + 19)
#define MPC52xx_IR_TX_IRQ (MPC52xx_PERP_IRQ_BASE + 20)
#define MPC52xx_XLB_ARB_IRQ (MPC52xx_PERP_IRQ_BASE + 21)
+#define MPC52xx_BDLC_IRQ (MPC52xx_PERP_IRQ_BASE + 22)
@@ -163,7 +184,7 @@ struct mpc52xx_mmap_ctl {
u32 cs6_start; /* MMAP_CTRL + 0x58 */
u32 cs6_stop; /* MMAP_CTRL + 0x5c */
u32 cs7_start; /* MMAP_CTRL + 0x60 */
- u32 cs7_stop; /* MMAP_CTRL + 0x60 */
+ u32 cs7_stop; /* MMAP_CTRL + 0x64 */
};
/* SDRAM control */
@@ -209,7 +230,7 @@ struct mpc52xx_sdma {
u16 tcr[16]; /* SDMA + 0x1c .. 0x3a */
- u8 ipr[32]; /* SDMA + 0x3c .. 5b */
+ u8 ipr[32]; /* SDMA + 0x3c .. 0x5b */
u32 cReqSelect; /* SDMA + 0x5c */
u32 task_size0; /* SDMA + 0x60 */
@@ -391,7 +412,19 @@ extern void mpc52xx_halt(void);
extern void mpc52xx_power_off(void);
extern void mpc52xx_progress(char *s, unsigned short hex);
extern void mpc52xx_calibrate_decr(void);
-extern void mpc52xx_add_board_devices(struct ocp_def board_ocp[]);
+
+extern void mpc52xx_find_bridges(void);
+
+
+ /* Matching of PSC function */
+struct mpc52xx_psc_func {
+ int id;
+ char *func;
+};
+
+extern int mpc52xx_match_psc_function(int psc_idx, const char *func);
+extern struct mpc52xx_psc_func mpc52xx_psc_functions[];
+ /* This array is to be defined in platform file */
#endif /* __ASSEMBLY__ */
diff --git a/include/asm-ppc/mpc83xx.h b/include/asm-ppc/mpc83xx.h
new file mode 100644
index 0000000000000..bb1b0576c947e
--- /dev/null
+++ b/include/asm-ppc/mpc83xx.h
@@ -0,0 +1,114 @@
+/*
+ * include/asm-ppc/mpc83xx.h
+ *
+ * MPC83xx definitions
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2005 Freescale Semiconductor, Inc
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#ifdef __KERNEL__
+#ifndef __ASM_MPC83xx_H__
+#define __ASM_MPC83xx_H__
+
+#include <linux/config.h>
+#include <asm/mmu.h>
+
+#ifdef CONFIG_83xx
+
+#ifdef CONFIG_MPC834x_SYS
+#include <platforms/83xx/mpc834x_sys.h>
+#endif
+
+#define _IO_BASE isa_io_base
+#define _ISA_MEM_BASE isa_mem_base
+#ifdef CONFIG_PCI
+#define PCI_DRAM_OFFSET pci_dram_offset
+#else
+#define PCI_DRAM_OFFSET 0
+#endif
+
+/*
+ * The "residual" board information structure the boot loader passes
+ * into the kernel.
+ */
+extern unsigned char __res[];
+
+/* Internal IRQs on MPC83xx OpenPIC */
+/* Not all of these exist on all MPC83xx implementations */
+
+#ifndef MPC83xx_IPIC_IRQ_OFFSET
+#define MPC83xx_IPIC_IRQ_OFFSET 0
+#endif
+
+#define NR_IPIC_INTS 128
+
+#define MPC83xx_IRQ_UART1 ( 9 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_UART2 (10 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_SEC2 (11 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_IIC1 (14 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_IIC2 (15 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_SPI (16 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_EXT1 (17 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_EXT2 (18 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_EXT3 (19 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_EXT4 (20 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_EXT5 (21 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_EXT6 (22 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_EXT7 (23 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_TSEC1_TX (32 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_TSEC1_RX (33 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_TSEC1_ERROR (34 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_TSEC2_TX (35 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_TSEC2_RX (36 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_TSEC2_ERROR (37 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_USB2_DR (38 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_USB2_MPH (39 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_EXT0 (48 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_RTC_SEC (64 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_PIT (65 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_PCI1 (66 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_PCI2 (67 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_RTC_ALR (68 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_MU (69 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_SBA (70 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_DMA (71 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_GTM4 (72 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_GTM8 (73 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_GPIO1 (74 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_GPIO2 (75 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_DDR (76 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_LBC (77 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_GTM2 (78 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_GTM6 (79 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_PMC (80 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_GTM3 (84 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_GTM7 (85 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_GTM1 (90 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_GTM5 (91 + MPC83xx_IPIC_IRQ_OFFSET)
+
+#define MPC83xx_CCSRBAR_SIZE (1024*1024)
+
+/* Let modules/drivers get at immrbar (physical) */
+extern phys_addr_t immrbar;
+
+enum ppc_sys_devices {
+ MPC83xx_TSEC1,
+ MPC83xx_TSEC2,
+ MPC83xx_IIC1,
+ MPC83xx_IIC2,
+ MPC83xx_DUART,
+ MPC83xx_SEC2,
+ MPC83xx_USB2_DR,
+ MPC83xx_USB2_MPH,
+};
+
+#endif /* CONFIG_83xx */
+#endif /* __ASM_MPC83xx_H__ */
+#endif /* __KERNEL__ */
diff --git a/include/asm-ppc/mpc85xx.h b/include/asm-ppc/mpc85xx.h
index 3f9e4237bf6f0..22713e331585a 100644
--- a/include/asm-ppc/mpc85xx.h
+++ b/include/asm-ppc/mpc85xx.h
@@ -52,55 +52,6 @@
*/
extern unsigned char __res[];
-/* Internal IRQs on MPC85xx OpenPIC */
-/* Not all of these exist on all MPC85xx implementations */
-
-#ifndef MPC85xx_OPENPIC_IRQ_OFFSET
-#define MPC85xx_OPENPIC_IRQ_OFFSET 64
-#endif
-
-/* The 32 internal sources */
-#define MPC85xx_IRQ_L2CACHE ( 0 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_ECM ( 1 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_DDR ( 2 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_LBIU ( 3 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_DMA0 ( 4 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_DMA1 ( 5 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_DMA2 ( 6 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_DMA3 ( 7 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_PCI1 ( 8 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_PCI2 ( 9 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_RIO_ERROR ( 9 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_RIO_BELL (10 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_RIO_TX (11 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_RIO_RX (12 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_TSEC1_TX (13 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_TSEC1_RX (14 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_TSEC1_ERROR (18 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_TSEC2_TX (19 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_TSEC2_RX (20 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_TSEC2_ERROR (24 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_FEC (25 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_DUART (26 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_IIC1 (27 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_PERFMON (28 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_SEC2 (29 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_CPM (30 + MPC85xx_OPENPIC_IRQ_OFFSET)
-
-/* The 12 external interrupt lines */
-#define MPC85xx_IRQ_EXT0 (32 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_EXT1 (33 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_EXT2 (34 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_EXT3 (35 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_EXT4 (36 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_EXT5 (37 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_EXT6 (38 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_EXT7 (39 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_EXT8 (40 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_EXT9 (41 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_EXT10 (42 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_EXT11 (43 + MPC85xx_OPENPIC_IRQ_OFFSET)
-
/* Offset from CCSRBAR */
#define MPC85xx_CPM_OFFSET (0x80000)
#define MPC85xx_CPM_SIZE (0x40000)
diff --git a/include/asm-ppc/mv64x60_defs.h b/include/asm-ppc/mv64x60_defs.h
index ebfef3f133637..2f428746c02ba 100644
--- a/include/asm-ppc/mv64x60_defs.h
+++ b/include/asm-ppc/mv64x60_defs.h
@@ -36,6 +36,8 @@
#define GT64260_WINDOW_SIZE_MIN 0x00100000
#define MV64360_WINDOW_SIZE_MIN 0x00010000
+#define MV64x60_TCLK_FREQ_MAX 133333333U
+
/* IRQ's for embedded controllers */
#define MV64x60_IRQ_DEV 1
#define MV64x60_IRQ_CPU_ERR 3
@@ -43,6 +45,11 @@
#define MV64x60_IRQ_TIMER_2_3 9
#define MV64x60_IRQ_TIMER_4_5 10
#define MV64x60_IRQ_TIMER_6_7 11
+#define MV64x60_IRQ_P1_GPP_0_7 24
+#define MV64x60_IRQ_P1_GPP_8_15 25
+#define MV64x60_IRQ_P1_GPP_16_23 26
+#define MV64x60_IRQ_P1_GPP_24_31 27
+#define MV64x60_IRQ_DOORBELL 28
#define MV64x60_IRQ_ETH_0 32
#define MV64x60_IRQ_ETH_1 33
#define MV64x60_IRQ_ETH_2 34
@@ -52,12 +59,49 @@
#define MV64x60_IRQ_MPSC_0 40
#define MV64x60_IRQ_MPSC_1 42
#define MV64x60_IRQ_COMM 43
+#define MV64x60_IRQ_P0_GPP_0_7 56
+#define MV64x60_IRQ_P0_GPP_8_15 57
+#define MV64x60_IRQ_P0_GPP_16_23 58
+#define MV64x60_IRQ_P0_GPP_24_31 59
#define MV64360_IRQ_PCI0 12
#define MV64360_IRQ_SRAM_PAR_ERR 13
#define MV64360_IRQ_PCI1 16
#define MV64360_IRQ_SDMA_1 38
+#define MV64x60_IRQ_GPP0 64
+#define MV64x60_IRQ_GPP1 65
+#define MV64x60_IRQ_GPP2 66
+#define MV64x60_IRQ_GPP3 67
+#define MV64x60_IRQ_GPP4 68
+#define MV64x60_IRQ_GPP5 69
+#define MV64x60_IRQ_GPP6 70
+#define MV64x60_IRQ_GPP7 71
+#define MV64x60_IRQ_GPP8 72
+#define MV64x60_IRQ_GPP9 73
+#define MV64x60_IRQ_GPP10 74
+#define MV64x60_IRQ_GPP11 75
+#define MV64x60_IRQ_GPP12 76
+#define MV64x60_IRQ_GPP13 77
+#define MV64x60_IRQ_GPP14 78
+#define MV64x60_IRQ_GPP15 79
+#define MV64x60_IRQ_GPP16 80
+#define MV64x60_IRQ_GPP17 81
+#define MV64x60_IRQ_GPP18 82
+#define MV64x60_IRQ_GPP19 83
+#define MV64x60_IRQ_GPP20 84
+#define MV64x60_IRQ_GPP21 85
+#define MV64x60_IRQ_GPP22 86
+#define MV64x60_IRQ_GPP23 87
+#define MV64x60_IRQ_GPP24 88
+#define MV64x60_IRQ_GPP25 89
+#define MV64x60_IRQ_GPP26 90
+#define MV64x60_IRQ_GPP27 91
+#define MV64x60_IRQ_GPP28 92
+#define MV64x60_IRQ_GPP29 93
+#define MV64x60_IRQ_GPP30 94
+#define MV64x60_IRQ_GPP31 95
+
/* Offsets for register blocks */
#define GT64260_ENET_PHY_ADDR 0x2000
#define GT64260_ENET_ESMIR 0x2010
@@ -303,7 +347,7 @@
#define MV64360_SRAM_ERR_DATA_HI 0x03a0
#define MV64360_SRAM_ERR_PARITY 0x03a8
-#define MV64360_SRAM_SIZE 0x00040000 /* 256 KB of SRAM */
+#define MV64360_SRAM_SIZE 0x00040000 /* 2Mb/256KB SRAM */
/*
*****************************************************************************
diff --git a/include/asm-ppc/page.h b/include/asm-ppc/page.h
index 57838e8e00f19..4789dc024240a 100644
--- a/include/asm-ppc/page.h
+++ b/include/asm-ppc/page.h
@@ -137,6 +137,8 @@ static inline void* ___va(unsigned long p)
#define ___va(paddr) ((paddr)+PPC_MEMOFFSET)
#endif
+extern int page_is_ram(unsigned long pfn);
+
#define __pa(x) ___pa((unsigned long)(x))
#define __va(x) ((void *)(___va((unsigned long)(x))))
diff --git a/include/asm-ppc/pci.h b/include/asm-ppc/pci.h
index 5349f5ca46978..ce5ae6d048f51 100644
--- a/include/asm-ppc/pci.h
+++ b/include/asm-ppc/pci.h
@@ -79,9 +79,8 @@ extern unsigned long pci_bus_to_phys(unsigned int ba, int busnr);
#define pci_domain_nr(bus) ((struct pci_controller *)(bus)->sysdata)->index
/* Set the name of the bus as it appears in /proc/bus/pci */
-static inline int pci_name_bus(char *name, struct pci_bus *bus)
+static inline int pci_proc_domain(struct pci_bus *bus)
{
- sprintf(name, "%02x", bus->number);
return 0;
}
@@ -98,6 +97,12 @@ pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
extern void pcibios_add_platform_entries(struct pci_dev *dev);
+struct file;
+extern pgprot_t pci_phys_mem_access_prot(struct file *file,
+ unsigned long offset,
+ unsigned long size,
+ pgprot_t prot);
+
#endif /* __KERNEL__ */
#endif /* __PPC_PCI_H */
diff --git a/include/asm-ppc/pgtable.h b/include/asm-ppc/pgtable.h
index 642c86b74121c..19dfb7abaa218 100644
--- a/include/asm-ppc/pgtable.h
+++ b/include/asm-ppc/pgtable.h
@@ -448,7 +448,7 @@ extern unsigned long empty_zero_page[1024];
#define pte_none(pte) ((pte_val(pte) & ~_PTE_NONE_MASK) == 0)
#define pte_present(pte) (pte_val(pte) & _PAGE_PRESENT)
-#define pte_clear(ptep) do { set_pte((ptep), __pte(0)); } while (0)
+#define pte_clear(mm,addr,ptep) do { set_pte_at((mm), (addr), (ptep), __pte(0)); } while (0)
#define pmd_none(pmd) (!pmd_val(pmd))
#define pmd_bad(pmd) (pmd_val(pmd) & _PMD_BAD)
@@ -512,6 +512,17 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
}
/*
+ * When flushing the tlb entry for a page, we also need to flush the hash
+ * table entry. flush_hash_pages is assembler (for speed) in hashtable.S.
+ */
+extern int flush_hash_pages(unsigned context, unsigned long va,
+ unsigned long pmdval, int count);
+
+/* Add an HPTE to the hash table */
+extern void add_hash_page(unsigned context, unsigned long va,
+ unsigned long pmdval);
+
+/*
* Atomic PTE updates.
*
* pte_update clears and sets bit atomically, and returns
@@ -542,7 +553,8 @@ static inline unsigned long pte_update(pte_t *p, unsigned long clr,
* On machines which use an MMU hash table we avoid changing the
* _PAGE_HASHPTE bit.
*/
-static inline void set_pte(pte_t *ptep, pte_t pte)
+static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
+ pte_t *ptep, pte_t pte)
{
#if _PAGE_HASHPTE != 0
pte_update(ptep, ~_PAGE_HASHPTE, pte_val(pte) & ~_PAGE_HASHPTE);
@@ -551,43 +563,47 @@ static inline void set_pte(pte_t *ptep, pte_t pte)
#endif
}
-extern void flush_hash_one_pte(pte_t *ptep);
-
/*
* 2.6 calles this without flushing the TLB entry, this is wrong
* for our hash-based implementation, we fix that up here
*/
-static inline int ptep_test_and_clear_young(pte_t *ptep)
+#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
+static inline int __ptep_test_and_clear_young(unsigned int context, unsigned long addr, pte_t *ptep)
{
unsigned long old;
old = pte_update(ptep, _PAGE_ACCESSED, 0);
#if _PAGE_HASHPTE != 0
- if (old & _PAGE_HASHPTE)
- flush_hash_one_pte(ptep);
+ if (old & _PAGE_HASHPTE) {
+ unsigned long ptephys = __pa(ptep) & PAGE_MASK;
+ flush_hash_pages(context, addr, ptephys, 1);
+ }
#endif
return (old & _PAGE_ACCESSED) != 0;
}
+#define ptep_test_and_clear_young(__vma, __addr, __ptep) \
+ __ptep_test_and_clear_young((__vma)->vm_mm->context, __addr, __ptep)
-static inline int ptep_test_and_clear_dirty(pte_t *ptep)
+#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
+static inline int ptep_test_and_clear_dirty(struct vm_area_struct *vma,
+ unsigned long addr, pte_t *ptep)
{
return (pte_update(ptep, (_PAGE_DIRTY | _PAGE_HWWRITE), 0) & _PAGE_DIRTY) != 0;
}
-static inline pte_t ptep_get_and_clear(pte_t *ptep)
+#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
+static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
+ pte_t *ptep)
{
return __pte(pte_update(ptep, ~_PAGE_HASHPTE, 0));
}
-static inline void ptep_set_wrprotect(pte_t *ptep)
+#define __HAVE_ARCH_PTEP_SET_WRPROTECT
+static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr,
+ pte_t *ptep)
{
pte_update(ptep, (_PAGE_RW | _PAGE_HWWRITE), 0);
}
-static inline void ptep_mkdirty(pte_t *ptep)
-{
- pte_update(ptep, 0, _PAGE_DIRTY);
-}
-
#define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
static inline void __ptep_set_access_flags(pte_t *ptep, pte_t entry, int dirty)
{
@@ -607,6 +623,12 @@ static inline void __ptep_set_access_flags(pte_t *ptep, pte_t entry, int dirty)
*/
#define pgprot_noncached(prot) (__pgprot(pgprot_val(prot) | _PAGE_NO_CACHE | _PAGE_GUARDED))
+struct file;
+extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long addr,
+ unsigned long size, pgprot_t vma_prot);
+#define __HAVE_PHYS_MEM_ACCESS_PROT
+
+#define __HAVE_ARCH_PTE_SAME
#define pte_same(A,B) (((pte_val(A) ^ pte_val(B)) & ~_PAGE_HASHPTE) == 0)
/*
@@ -659,17 +681,6 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
extern void paging_init(void);
/*
- * When flushing the tlb entry for a page, we also need to flush the hash
- * table entry. flush_hash_pages is assembler (for speed) in hashtable.S.
- */
-extern int flush_hash_pages(unsigned context, unsigned long va,
- unsigned long pmdval, int count);
-
-/* Add an HPTE to the hash table */
-extern void add_hash_page(unsigned context, unsigned long va,
- unsigned long pmdval);
-
-/*
* Encode and decode a swap entry.
* Note that the bits we use in a PTE for representing a swap entry
* must not include the _PAGE_PRESENT bit, the _PAGE_FILE bit, or the
@@ -729,11 +740,27 @@ static inline int io_remap_page_range(struct vm_area_struct *vma,
phys_addr_t paddr64 = fixup_bigphys_addr(paddr, size);
return remap_pfn_range(vma, vaddr, paddr64 >> PAGE_SHIFT, size, prot);
}
+
+static inline int io_remap_pfn_range(struct vm_area_struct *vma,
+ unsigned long vaddr,
+ unsigned long pfn,
+ unsigned long size,
+ pgprot_t prot)
+{
+ phys_addr_t paddr64 = fixup_bigphys_addr(pfn << PAGE_SHIFT, size);
+ return remap_pfn_range(vma, vaddr, paddr64 >> PAGE_SHIFT, size, prot);
+}
#else
#define io_remap_page_range(vma, vaddr, paddr, size, prot) \
remap_pfn_range(vma, vaddr, (paddr) >> PAGE_SHIFT, size, prot)
+#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
+ remap_pfn_range(vma, vaddr, pfn, size, prot)
#endif
+#define MK_IOSPACE_PFN(space, pfn) (pfn)
+#define GET_IOSPACE(pfn) 0
+#define GET_PFN(pfn) (pfn)
+
/*
* No page table caches to initialise
*/
@@ -741,15 +768,9 @@ static inline int io_remap_page_range(struct vm_area_struct *vma,
extern int get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep);
-#endif /* !__ASSEMBLY__ */
-
-#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
-#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
-#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
-#define __HAVE_ARCH_PTEP_SET_WRPROTECT
-#define __HAVE_ARCH_PTEP_MKDIRTY
-#define __HAVE_ARCH_PTE_SAME
#include <asm-generic/pgtable.h>
+#endif /* !__ASSEMBLY__ */
+
#endif /* _PPC_PGTABLE_H */
#endif /* __KERNEL__ */
diff --git a/include/asm-ppc/pmac_feature.h b/include/asm-ppc/pmac_feature.h
index 4945a50ce0756..98c206d8c0248 100644
--- a/include/asm-ppc/pmac_feature.h
+++ b/include/asm-ppc/pmac_feature.h
@@ -112,9 +112,13 @@
*/
#define PMAC_TYPE_UNKNOWN_INTREPID 0x11f /* Generic */
-/* MacRISC4 / G5 machines
+/* MacRISC4 / G5 machines. We don't have per-machine selection here anymore,
+ * but rather machine families
*/
-#define PMAC_TYPE_POWERMAC_G5 0x150 /* First tower */
+#define PMAC_TYPE_POWERMAC_G5 0x150 /* U3 & U3H based */
+#define PMAC_TYPE_POWERMAC_G5_U3L 0x151 /* U3L based desktop */
+#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 */
/*
diff --git a/include/asm-ppc/ppc4xx_pic.h b/include/asm-ppc/ppc4xx_pic.h
index 5141aad30621c..c16c7f81cfd8d 100644
--- a/include/asm-ppc/ppc4xx_pic.h
+++ b/include/asm-ppc/ppc4xx_pic.h
@@ -43,11 +43,11 @@
*
*/
struct ppc4xx_uic_settings {
- u32 polarity;
- u32 triggering;
- u32 ext_irq_mask;
+ u32 polarity;
+ u32 triggering;
+ u32 ext_irq_mask;
};
extern void ppc4xx_pic_init(void);
-#endif /* __PPC4XX_PIC_H__ */
+#endif /* __PPC4XX_PIC_H__ */
diff --git a/include/asm-ppc/ppc_sys.h b/include/asm-ppc/ppc_sys.h
index 6f5ab7625d6a0..24b991c427694 100644
--- a/include/asm-ppc/ppc_sys.h
+++ b/include/asm-ppc/ppc_sys.h
@@ -21,8 +21,12 @@
#include <linux/device.h>
#include <linux/types.h>
-#if defined(CONFIG_85xx)
+#if defined(CONFIG_83xx)
+#include <asm/mpc83xx.h>
+#elif defined(CONFIG_85xx)
#include <asm/mpc85xx.h>
+#elif defined(CONFIG_PPC_MPC52xx)
+#include <asm/mpc52xx.h>
#else
#error "need definition of ppc_sys_devices"
#endif
diff --git a/include/asm-ppc/ppcboot.h b/include/asm-ppc/ppcboot.h
index c2a4b94e4f1e8..fe24e4520208b 100644
--- a/include/asm-ppc/ppcboot.h
+++ b/include/asm-ppc/ppcboot.h
@@ -38,7 +38,8 @@ typedef struct bd_info {
unsigned long bi_flashoffset; /* reserved area for startup monitor */
unsigned long bi_sramstart; /* start of SRAM memory */
unsigned long bi_sramsize; /* size of SRAM memory */
-#if defined(CONFIG_8xx) || defined(CONFIG_CPM2) || defined(CONFIG_85xx)
+#if defined(CONFIG_8xx) || defined(CONFIG_CPM2) || defined(CONFIG_85xx) ||\
+ defined(CONFIG_83xx)
unsigned long bi_immr_base; /* base of IMMR register */
#endif
#if defined(CONFIG_PPC_MPC52xx)
@@ -72,7 +73,8 @@ typedef struct bd_info {
#if defined(CONFIG_HYMOD)
hymod_conf_t bi_hymod_conf; /* hymod configuration information */
#endif
-#if defined(CONFIG_EVB64260) || defined(CONFIG_44x) || defined(CONFIG_85xx)
+#if defined(CONFIG_EVB64260) || defined(CONFIG_44x) || defined(CONFIG_85xx) ||\
+ defined(CONFIG_83xx)
/* second onboard ethernet port */
unsigned char bi_enet1addr[6];
#endif
diff --git a/include/asm-ppc/reg.h b/include/asm-ppc/reg.h
index 43d865b974439..3372dee36a8cc 100644
--- a/include/asm-ppc/reg.h
+++ b/include/asm-ppc/reg.h
@@ -335,91 +335,6 @@
#define MMCR0_PMC2_LOADMISSTIME 0x5
#define MMCR0_PMXE (1 << 26)
-/* Short-hand versions for a number of the above SPRNs */
-#define CTR SPRN_CTR /* Counter Register */
-#define DAR SPRN_DAR /* Data Address Register */
-#define DABR SPRN_DABR /* Data Address Breakpoint Register */
-#define DBAT0L SPRN_DBAT0L /* Data BAT 0 Lower Register */
-#define DBAT0U SPRN_DBAT0U /* Data BAT 0 Upper Register */
-#define DBAT1L SPRN_DBAT1L /* Data BAT 1 Lower Register */
-#define DBAT1U SPRN_DBAT1U /* Data BAT 1 Upper Register */
-#define DBAT2L SPRN_DBAT2L /* Data BAT 2 Lower Register */
-#define DBAT2U SPRN_DBAT2U /* Data BAT 2 Upper Register */
-#define DBAT3L SPRN_DBAT3L /* Data BAT 3 Lower Register */
-#define DBAT3U SPRN_DBAT3U /* Data BAT 3 Upper Register */
-#define DBAT4L SPRN_DBAT4L /* Data BAT 4 Lower Register */
-#define DBAT4U SPRN_DBAT4U /* Data BAT 4 Upper Register */
-#define DBAT5L SPRN_DBAT5L /* Data BAT 5 Lower Register */
-#define DBAT5U SPRN_DBAT5U /* Data BAT 5 Upper Register */
-#define DBAT6L SPRN_DBAT6L /* Data BAT 6 Lower Register */
-#define DBAT6U SPRN_DBAT6U /* Data BAT 6 Upper Register */
-#define DBAT7L SPRN_DBAT7L /* Data BAT 7 Lower Register */
-#define DBAT7U SPRN_DBAT7U /* Data BAT 7 Upper Register */
-//#define DEC SPRN_DEC /* Decrement Register */
-#define DMISS SPRN_DMISS /* Data TLB Miss Register */
-#define DSISR SPRN_DSISR /* Data Storage Interrupt Status Register */
-#define EAR SPRN_EAR /* External Address Register */
-#define HASH1 SPRN_HASH1 /* Primary Hash Address Register */
-#define HASH2 SPRN_HASH2 /* Secondary Hash Address Register */
-#define HID0 SPRN_HID0 /* Hardware Implementation Register 0 */
-#define HID1 SPRN_HID1 /* Hardware Implementation Register 1 */
-#define IABR SPRN_IABR /* Instruction Address Breakpoint Register */
-#define IBAT0L SPRN_IBAT0L /* Instruction BAT 0 Lower Register */
-#define IBAT0U SPRN_IBAT0U /* Instruction BAT 0 Upper Register */
-#define IBAT1L SPRN_IBAT1L /* Instruction BAT 1 Lower Register */
-#define IBAT1U SPRN_IBAT1U /* Instruction BAT 1 Upper Register */
-#define IBAT2L SPRN_IBAT2L /* Instruction BAT 2 Lower Register */
-#define IBAT2U SPRN_IBAT2U /* Instruction BAT 2 Upper Register */
-#define IBAT3L SPRN_IBAT3L /* Instruction BAT 3 Lower Register */
-#define IBAT3U SPRN_IBAT3U /* Instruction BAT 3 Upper Register */
-#define IBAT4L SPRN_IBAT4L /* Instruction BAT 4 Lower Register */
-#define IBAT4U SPRN_IBAT4U /* Instruction BAT 4 Upper Register */
-#define IBAT5L SPRN_IBAT5L /* Instruction BAT 5 Lower Register */
-#define IBAT5U SPRN_IBAT5U /* Instruction BAT 5 Upper Register */
-#define IBAT6L SPRN_IBAT6L /* Instruction BAT 6 Lower Register */
-#define IBAT6U SPRN_IBAT6U /* Instruction BAT 6 Upper Register */
-#define IBAT7L SPRN_IBAT7L /* Instruction BAT 7 Lower Register */
-#define IBAT7U SPRN_IBAT7U /* Instruction BAT 7 Upper Register */
-#define ICMP SPRN_ICMP /* Instruction TLB Compare Register */
-#define IMISS SPRN_IMISS /* Instruction TLB Miss Register */
-#define IMMR SPRN_IMMR /* PPC 860/821 Internal Memory Map Register */
-#define L2CR SPRN_L2CR /* Classic PPC L2 cache control register */
-#define L3CR SPRN_L3CR /* PPC 745x L3 cache control register */
-//#define LR SPRN_LR
-#define PVR SPRN_PVR /* Processor Version */
-//#define RPA SPRN_RPA /* Required Physical Address Register */
-#define SDR1 SPRN_SDR1 /* MMU hash base register */
-#define SPR0 SPRN_SPRG0 /* Supervisor Private Registers */
-#define SPR1 SPRN_SPRG1
-#define SPR2 SPRN_SPRG2
-#define SPR3 SPRN_SPRG3
-#define SPR4 SPRN_SPRG4
-#define SPR5 SPRN_SPRG5
-#define SPR6 SPRN_SPRG6
-#define SPR7 SPRN_SPRG7
-#define SPRG0 SPRN_SPRG0
-#define SPRG1 SPRN_SPRG1
-#define SPRG2 SPRN_SPRG2
-#define SPRG3 SPRN_SPRG3
-#define SPRG4 SPRN_SPRG4
-#define SPRG5 SPRN_SPRG5
-#define SPRG6 SPRN_SPRG6
-#define SPRG7 SPRN_SPRG7
-#define SRR0 SPRN_SRR0 /* Save and Restore Register 0 */
-#define SRR1 SPRN_SRR1 /* Save and Restore Register 1 */
-#define SRR2 SPRN_SRR2 /* Save and Restore Register 2 */
-#define SRR3 SPRN_SRR3 /* Save and Restore Register 3 */
-#define SVR SPRN_SVR /* System Version Register */
-#define ICTC SPRN_ICTC /* Instruction Cache Throttling Control Reg */
-#define THRM1 SPRN_THRM1 /* Thermal Management Register 1 */
-#define THRM2 SPRN_THRM2 /* Thermal Management Register 2 */
-#define THRM3 SPRN_THRM3 /* Thermal Management Register 3 */
-#define XER SPRN_XER
-#define TBRL SPRN_TBRL /* Time Base Read Lower Register */
-#define TBRU SPRN_TBRU /* Time Base Read Upper Register */
-#define TBWL SPRN_TBWL /* Time Base Write Lower Register */
-#define TBWU SPRN_TBWU /* Time Base Write Upper Register */
-
/* Processor Version Register */
/* Processor Version Register (PVR) field extraction */
@@ -488,12 +403,6 @@
#define PVR_8245 0x80811014
#define PVR_8260 PVR_8240
-/* System Version Numbers */
-#define SVR_8540 0x80300000
-#define SVR_8541E 0x807A0000
-#define SVR_8555E 0x80790000
-#define SVR_8560 0x80700000
-
#if 0
/* Segment Registers */
#define SR0 0
diff --git a/include/asm-ppc/reg_booke.h b/include/asm-ppc/reg_booke.h
index 5c025f9b28e4c..4b03f8e26b72e 100644
--- a/include/asm-ppc/reg_booke.h
+++ b/include/asm-ppc/reg_booke.h
@@ -427,26 +427,6 @@ do { \
#define SPEFSCR_FOVFE 0x00000004 /* Embedded FP overflow enable */
#define SPEFSCR_FRMC 0x00000003 /* Embedded FP rounding mode control */
-/* Short-hand for various SPRs. */
-#ifdef CONFIG_BOOKE
-#define CSRR0 SPRN_CSRR0 /* Critical Save and Restore Register 0 */
-#define CSRR1 SPRN_CSRR1 /* Critical Save and Restore Register 1 */
-#else
-#define CSRR0 SPRN_SRR2 /* Logically and functionally equivalent. */
-#define CSRR1 SPRN_SRR3 /* Logically and functionally equivalent. */
-#endif
-#define MCSRR0 SPRN_MCSRR0 /* Machine Check Save and Restore Register 0 */
-#define MCSRR1 SPRN_MCSRR1 /* Machine Check Save and Restore Register 1 */
-#define DCMP SPRN_DCMP /* Data TLB Compare Register */
-#define SPRG4R SPRN_SPRG4R /* Supervisor Private Registers */
-#define SPRG5R SPRN_SPRG5R
-#define SPRG6R SPRN_SPRG6R
-#define SPRG7R SPRN_SPRG7R
-#define SPRG4W SPRN_SPRG4W
-#define SPRG5W SPRN_SPRG5W
-#define SPRG6W SPRN_SPRG6W
-#define SPRG7W SPRN_SPRG7W
-
/*
* The IBM-403 is an even more odd special case, as it is much
* older than the IBM-405 series. We put these down here incase someone
diff --git a/include/asm-ppc/serial.h b/include/asm-ppc/serial.h
index f4eadce930d0c..6d47438be58c2 100644
--- a/include/asm-ppc/serial.h
+++ b/include/asm-ppc/serial.h
@@ -22,6 +22,8 @@
#include <platforms/mcpn765.h>
#elif defined(CONFIG_MVME5100)
#include <platforms/mvme5100.h>
+#elif defined(CONFIG_PAL4)
+#include <platforms/pal4_serial.h>
#elif defined(CONFIG_PRPMC750)
#include <platforms/prpmc750.h>
#elif defined(CONFIG_PRPMC800)
@@ -32,8 +34,12 @@
#include <platforms/spruce.h>
#elif defined(CONFIG_4xx)
#include <asm/ibm4xx.h>
+#elif defined(CONFIG_83xx)
+#include <asm/mpc83xx.h>
#elif defined(CONFIG_85xx)
#include <asm/mpc85xx.h>
+#elif defined(CONFIG_RADSTONE_PPC7D)
+#include <platforms/radstone_ppc7d.h>
#else
/*
diff --git a/include/asm-ppc/suspend.h b/include/asm-ppc/suspend.h
new file mode 100644
index 0000000000000..3df9f32bd8349
--- /dev/null
+++ b/include/asm-ppc/suspend.h
@@ -0,0 +1,12 @@
+static inline int arch_prepare_suspend(void)
+{
+ return 0;
+}
+
+static inline void save_processor_state(void)
+{
+}
+
+static inline void restore_processor_state(void)
+{
+}
diff --git a/include/asm-ppc/system.h b/include/asm-ppc/system.h
index 5cff9a0fd84b9..82395f30004b7 100644
--- a/include/asm-ppc/system.h
+++ b/include/asm-ppc/system.h
@@ -152,9 +152,9 @@ extern inline void * xchg_ptr(void * m, void * val)
#define __HAVE_ARCH_CMPXCHG 1
static __inline__ unsigned long
-__cmpxchg_u32(volatile int *p, int old, int new)
+__cmpxchg_u32(volatile unsigned int *p, unsigned int old, unsigned int new)
{
- int prev;
+ unsigned int prev;
__asm__ __volatile__ ("\n\
1: lwarx %0,0,%2 \n\
@@ -201,5 +201,7 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
(unsigned long)_n_, sizeof(*(ptr))); \
})
+#define arch_align_stack(x) (x)
+
#endif /* __KERNEL__ */
#endif /* __PPC_SYSTEM_H */
diff --git a/include/asm-ppc/timex.h b/include/asm-ppc/timex.h
index b9bffff66edd7..cffc8712077c4 100644
--- a/include/asm-ppc/timex.h
+++ b/include/asm-ppc/timex.h
@@ -19,8 +19,6 @@ typedef unsigned long cycles_t;
* Currently only used on SMP.
*/
-extern cycles_t cacheflush_time;
-
static inline cycles_t get_cycles(void)
{
cycles_t ret = 0;
diff --git a/include/asm-ppc/todc.h b/include/asm-ppc/todc.h
index 30abf319b4257..84bae7d768145 100644
--- a/include/asm-ppc/todc.h
+++ b/include/asm-ppc/todc.h
@@ -98,6 +98,7 @@ typedef struct {
#define TODC_TYPE_PC97307 10 /* PC97307 internal RTC */
#define TODC_TYPE_DS1557 11 /* Dallas DS1557 RTC */
#define TODC_TYPE_DS17285 12 /* Dallas DS17285 RTC */
+#define TODC_TYPE_DS1553 13 /* Dallas DS1553 RTC */
#define TODC_TYPE_MC146818 100 /* Leave room for m48txx's */
/*
@@ -208,6 +209,28 @@ typedef struct {
#define TODC_TYPE_DS1501_NVRAM_ADDR_REG 0x10
#define TODC_TYPE_DS1501_NVRAM_DATA_REG 0x13
+#define TODC_TYPE_DS1553_NVRAM_SIZE 0x1ff0
+#define TODC_TYPE_DS1553_SW_FLAGS 0
+#define TODC_TYPE_DS1553_YEAR 0x1fff
+#define TODC_TYPE_DS1553_MONTH 0x1ffe
+#define TODC_TYPE_DS1553_DOM 0x1ffd /* Day of Month */
+#define TODC_TYPE_DS1553_DOW 0x1ffc /* Day of Week */
+#define TODC_TYPE_DS1553_HOURS 0x1ffb
+#define TODC_TYPE_DS1553_MINUTES 0x1ffa
+#define TODC_TYPE_DS1553_SECONDS 0x1ff9
+#define TODC_TYPE_DS1553_CNTL_B 0x1ff9
+#define TODC_TYPE_DS1553_CNTL_A 0x1ff8 /* control_a R/W regs */
+#define TODC_TYPE_DS1553_WATCHDOG 0x1ff7
+#define TODC_TYPE_DS1553_INTERRUPTS 0x1ff6
+#define TODC_TYPE_DS1553_ALARM_DATE 0x1ff5
+#define TODC_TYPE_DS1553_ALARM_HOUR 0x1ff4
+#define TODC_TYPE_DS1553_ALARM_MINUTES 0x1ff3
+#define TODC_TYPE_DS1553_ALARM_SECONDS 0x1ff2
+#define TODC_TYPE_DS1553_CENTURY 0x1ff8
+#define TODC_TYPE_DS1553_FLAGS 0x1ff0
+#define TODC_TYPE_DS1553_NVRAM_ADDR_REG 0
+#define TODC_TYPE_DS1553_NVRAM_DATA_REG 0
+
#define TODC_TYPE_DS1557_NVRAM_SIZE 0x7fff0
#define TODC_TYPE_DS1557_SW_FLAGS 0
#define TODC_TYPE_DS1557_YEAR 0x7ffff
diff --git a/include/asm-ppc/uaccess.h b/include/asm-ppc/uaccess.h
index 83c12a992cea7..b044ae03ac563 100644
--- a/include/asm-ppc/uaccess.h
+++ b/include/asm-ppc/uaccess.h
@@ -37,7 +37,8 @@
#define access_ok(type, addr, size) \
(__chk_user_ptr(addr),__access_ok((unsigned long)(addr),(size)))
-extern inline int verify_area(int type, const void __user * addr, unsigned long size)
+/* this function will go away soon - use access_ok() instead */
+extern inline int __deprecated verify_area(int type, const void __user * addr, unsigned long size)
{
return access_ok(type, addr, size) ? 0 : -EFAULT;
}
diff --git a/include/asm-ppc/uninorth.h b/include/asm-ppc/uninorth.h
index 57daf7add0227..f737732c38617 100644
--- a/include/asm-ppc/uninorth.h
+++ b/include/asm-ppc/uninorth.h
@@ -27,13 +27,18 @@
#define UNI_N_CFG_AGP_BASE 0x90
#define UNI_N_CFG_GART_CTRL 0x94
#define UNI_N_CFG_INTERNAL_STATUS 0x98
+#define UNI_N_CFG_GART_DUMMY_PAGE 0xa4
/* UNI_N_CFG_GART_CTRL bits definitions */
-/* Not U3 */
#define UNI_N_CFG_GART_INVAL 0x00000001
#define UNI_N_CFG_GART_ENABLE 0x00000100
#define UNI_N_CFG_GART_2xRESET 0x00010000
#define UNI_N_CFG_GART_DISSBADET 0x00020000
+/* The following seems to only be used only on U3 <j.glisse@gmail.com> */
+#define U3_N_CFG_GART_SYNCMODE 0x00040000
+#define U3_N_CFG_GART_PERFRD 0x00080000
+#define U3_N_CFG_GART_B2BGNT 0x00200000
+#define U3_N_CFG_GART_FASTDDR 0x00400000
/* My understanding of UniNorth AGP as of UniNorth rev 1.0x,
* revision 1.5 (x4 AGP) may need further changes.
diff --git a/include/asm-ppc/unistd.h b/include/asm-ppc/unistd.h
index 749af517d72ed..8f7e11d18adca 100644
--- a/include/asm-ppc/unistd.h
+++ b/include/asm-ppc/unistd.h
@@ -276,8 +276,9 @@
#define __NR_add_key 269
#define __NR_request_key 270
#define __NR_keyctl 271
+#define __NR_waitid 272
-#define __NR_syscalls 272
+#define __NR_syscalls 273
#define __NR(n) #n
@@ -468,7 +469,7 @@ long sys_rt_sigaction(int sig,
* but it doesn't work on all toolchains, so we just do it by hand
*/
#ifndef cond_syscall
-#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
+#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
#endif
#endif /* __KERNEL__ */
diff --git a/include/asm-ppc64/a.out.h b/include/asm-ppc64/a.out.h
index 7e2b95f3cdce9..802338efcb197 100644
--- a/include/asm-ppc64/a.out.h
+++ b/include/asm-ppc64/a.out.h
@@ -30,14 +30,11 @@ struct exec
#ifdef __KERNEL__
-#define STACK_TOP_USER64 (TASK_SIZE_USER64)
+#define STACK_TOP_USER64 TASK_SIZE_USER64
+#define STACK_TOP_USER32 TASK_SIZE_USER32
-/* Give 32-bit user space a full 4G address space to live in. */
-#define STACK_TOP_USER32 (TASK_SIZE_USER32)
-
-#define STACK_TOP ((test_thread_flag(TIF_32BIT) || \
- (ppcdebugset(PPCDBG_BINFMT_32ADDR))) ? \
- STACK_TOP_USER32 : STACK_TOP_USER64)
+#define STACK_TOP (test_thread_flag(TIF_32BIT) ? \
+ STACK_TOP_USER32 : STACK_TOP_USER64)
#endif /* __KERNEL__ */
diff --git a/include/asm-ppc64/agp.h b/include/asm-ppc64/agp.h
new file mode 100644
index 0000000000000..be27cfa8c5b0a
--- /dev/null
+++ b/include/asm-ppc64/agp.h
@@ -0,0 +1,13 @@
+#ifndef AGP_H
+#define AGP_H 1
+
+#include <asm/io.h>
+
+/* nothing much needed here */
+
+#define map_page_into_agp(page)
+#define unmap_page_from_agp(page)
+#define flush_agp_mappings()
+#define flush_agp_cache() mb()
+
+#endif
diff --git a/include/asm-ppc64/cacheflush.h b/include/asm-ppc64/cacheflush.h
index d0f0dfd263d67..ffbc08be8e520 100644
--- a/include/asm-ppc64/cacheflush.h
+++ b/include/asm-ppc64/cacheflush.h
@@ -12,7 +12,7 @@
#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)
-#define flush_cache_page(vma, vmaddr) do { } while (0)
+#define flush_cache_page(vma, vmaddr, pfn) do { } while (0)
#define flush_icache_page(vma, page) do { } while (0)
#define flush_cache_vmap(start, end) do { } while (0)
#define flush_cache_vunmap(start, end) do { } while (0)
@@ -28,6 +28,7 @@ extern void flush_icache_user_range(struct vm_area_struct *vma,
extern void flush_dcache_range(unsigned long start, unsigned long stop);
extern void flush_dcache_phys_range(unsigned long start, unsigned long stop);
+extern void flush_inval_dcache_range(unsigned long start, unsigned long stop);
#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
do { memcpy(dst, src, len); \
@@ -40,7 +41,7 @@ extern void __flush_dcache_icache(void *page_va);
static inline void flush_icache_range(unsigned long start, unsigned long stop)
{
- if (!(cur_cpu_spec->cpu_features & CPU_FTR_COHERENT_ICACHE))
+ if (!cpu_has_feature(CPU_FTR_COHERENT_ICACHE))
__flush_icache_range(start, stop);
}
diff --git a/include/asm-ppc64/cputable.h b/include/asm-ppc64/cputable.h
index 6ef442318e463..cbbfbec78b6bd 100644
--- a/include/asm-ppc64/cputable.h
+++ b/include/asm-ppc64/cputable.h
@@ -66,6 +66,11 @@ struct cpu_spec {
extern struct cpu_spec cpu_specs[];
extern struct cpu_spec *cur_cpu_spec;
+static inline unsigned long cpu_has_feature(unsigned long feature)
+{
+ return cur_cpu_spec->cpu_features & feature;
+}
+
/* firmware feature bitmask values */
#define FIRMWARE_MAX_FEATURES 63
diff --git a/include/asm-ppc64/dma-mapping.h b/include/asm-ppc64/dma-mapping.h
index 1e05f389e72b2..9ad8adee00673 100644
--- a/include/asm-ppc64/dma-mapping.h
+++ b/include/asm-ppc64/dma-mapping.h
@@ -19,7 +19,7 @@
extern int dma_supported(struct device *dev, u64 mask);
extern int dma_set_mask(struct device *dev, u64 dma_mask);
extern void *dma_alloc_coherent(struct device *dev, size_t size,
- dma_addr_t *dma_handle, int flag);
+ dma_addr_t *dma_handle, unsigned int __nocast flag);
extern void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
dma_addr_t dma_handle);
extern dma_addr_t dma_map_single(struct device *dev, void *cpu_addr,
@@ -113,4 +113,24 @@ dma_cache_sync(void *vaddr, size_t size,
/* nothing to do */
}
+/*
+ * DMA operations are abstracted for G5 vs. i/pSeries, PCI vs. VIO
+ */
+struct dma_mapping_ops {
+ void * (*alloc_coherent)(struct device *dev, size_t size,
+ dma_addr_t *dma_handle, unsigned int __nocast flag);
+ void (*free_coherent)(struct device *dev, size_t size,
+ void *vaddr, dma_addr_t dma_handle);
+ dma_addr_t (*map_single)(struct device *dev, void *ptr,
+ size_t size, enum dma_data_direction direction);
+ void (*unmap_single)(struct device *dev, dma_addr_t dma_addr,
+ size_t size, enum dma_data_direction direction);
+ int (*map_sg)(struct device *dev, struct scatterlist *sg,
+ int nents, enum dma_data_direction direction);
+ void (*unmap_sg)(struct device *dev, struct scatterlist *sg,
+ int nents, enum dma_data_direction direction);
+ int (*dma_supported)(struct device *dev, u64 mask);
+ int (*dac_dma_supported)(struct device *dev, u64 mask);
+};
+
#endif /* _ASM_DMA_MAPPING_H */
diff --git a/include/asm-ppc64/eeh.h b/include/asm-ppc64/eeh.h
index bcdb5b08cc374..94298b106a4ba 100644
--- a/include/asm-ppc64/eeh.h
+++ b/include/asm-ppc64/eeh.h
@@ -104,17 +104,30 @@ int eeh_unregister_notifier(struct notifier_block *nb);
*/
#define EEH_IO_ERROR_VALUE(size) (~0U >> ((4 - (size)) * 8))
-#else
-#define eeh_init()
-#define eeh_check_failure(token, val) (val)
-#define eeh_dn_check_failure(dn, dev) (0)
-#define pci_addr_cache_build()
-#define eeh_add_device_early(dn)
-#define eeh_add_device_late(dev)
-#define eeh_remove_device(dev)
+#else /* !CONFIG_EEH */
+static inline void eeh_init(void) { }
+
+static inline unsigned long eeh_check_failure(const volatile void __iomem *token, unsigned long val)
+{
+ return val;
+}
+
+static inline int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
+{
+ return 0;
+}
+
+static inline void pci_addr_cache_build(void) { }
+
+static inline void eeh_add_device_early(struct device_node *dn) { }
+
+static inline void eeh_add_device_late(struct pci_dev *dev) { }
+
+static inline void eeh_remove_device(struct pci_dev *dev) { }
+
#define EEH_POSSIBLE_ERROR(val, type) (0)
#define EEH_IO_ERROR_VALUE(size) (-1UL)
-#endif
+#endif /* CONFIG_EEH */
/*
* MMIO read/write operations with EEH support.
diff --git a/include/asm-ppc64/elf.h b/include/asm-ppc64/elf.h
index b7530725026ea..8457d90244fbe 100644
--- a/include/asm-ppc64/elf.h
+++ b/include/asm-ppc64/elf.h
@@ -226,6 +226,13 @@ do { \
else if (current->personality != PER_LINUX32) \
set_personality(PER_LINUX); \
} while (0)
+
+/*
+ * An executable for which elf_read_implies_exec() returns TRUE will
+ * have the READ_IMPLIES_EXEC personality flag set automatically.
+ */
+#define elf_read_implies_exec(ex, exec_stk) (exec_stk != EXSTACK_DISABLE_X)
+
#endif
/*
@@ -238,10 +245,20 @@ do { \
/* A special ignored type value for PPC, for glibc compatibility. */
#define AT_IGNOREPPC 22
+/* The vDSO location. We have to use the same value as x86 for glibc's
+ * sake :-)
+ */
+#define AT_SYSINFO_EHDR 33
+
extern int dcache_bsize;
extern int icache_bsize;
extern int ucache_bsize;
+/* We do have an arch_setup_additional_pages for vDSO matters */
+#define ARCH_HAS_SETUP_ADDITIONAL_PAGES
+struct linux_binprm;
+extern int arch_setup_additional_pages(struct linux_binprm *bprm, int executable_stack);
+
/*
* The requirements here are:
* - keep the final alignment of sp (sp & 0xf)
@@ -260,6 +277,8 @@ do { \
NEW_AUX_ENT(AT_DCACHEBSIZE, dcache_bsize); \
NEW_AUX_ENT(AT_ICACHEBSIZE, icache_bsize); \
NEW_AUX_ENT(AT_UCACHEBSIZE, ucache_bsize); \
+ /* vDSO base */ \
+ NEW_AUX_ENT(AT_SYSINFO_EHDR, current->thread.vdso_base); \
} while (0)
/* PowerPC64 relocations defined by the ABIs */
diff --git a/include/asm-ppc64/hvcall.h b/include/asm-ppc64/hvcall.h
index 6ce5ef9c1692d..4f668a4baff01 100644
--- a/include/asm-ppc64/hvcall.h
+++ b/include/asm-ppc64/hvcall.h
@@ -1,6 +1,8 @@
#ifndef _PPC64_HVCALL_H
#define _PPC64_HVCALL_H
+#define HVSC .long 0x44000022
+
#define H_Success 0
#define H_Busy 1 /* Hardware busy -- retry later */
#define H_Constrained 4 /* Resource request constrained to max allowed */
@@ -41,7 +43,7 @@
/* Flags */
#define H_LARGE_PAGE (1UL<<(63-16))
-#define H_EXACT (1UL<<(63-24)) /* Use exact PTE or return H_PTEG_FULL */
+#define H_EXACT (1UL<<(63-24)) /* Use exact PTE or return H_PTEG_FULL */
#define H_R_XLATE (1UL<<(63-25)) /* include a valid logical page num in the pte if the valid bit is set */
#define H_READ_4 (1UL<<(63-26)) /* Return 4 PTEs */
#define H_AVPN (1UL<<(63-32)) /* An avpn is provided as a sanity test */
@@ -54,8 +56,6 @@
#define H_PP1 (1UL<<(63-62))
#define H_PP2 (1UL<<(63-63))
-
-
/* pSeries hypervisor opcodes */
#define H_REMOVE 0x04
#define H_ENTER 0x08
@@ -108,6 +108,8 @@
#define H_FREE_VTERM 0x158
#define H_POLL_PENDING 0x1D8
+#ifndef __ASSEMBLY__
+
/* plpar_hcall() -- Generic call interface using above opcodes
*
* The actual call interface is a hypervisor call instruction with
@@ -125,8 +127,6 @@ long plpar_hcall(unsigned long opcode,
unsigned long *out2,
unsigned long *out3);
-#define HVSC ".long 0x44000022\n"
-
/* Same as plpar_hcall but for those opcodes that return no values
* other than status. Slightly more efficient.
*/
@@ -147,9 +147,6 @@ long plpar_hcall_8arg_2ret(unsigned long opcode,
unsigned long arg7,
unsigned long arg8,
unsigned long *out1);
-
-
-
/* plpar_hcall_4out()
*
@@ -166,4 +163,5 @@ long plpar_hcall_4out(unsigned long opcode,
unsigned long *out3,
unsigned long *out4);
+#endif /* __ASSEMBLY__ */
#endif /* _PPC64_HVCALL_H */
diff --git a/include/asm-ppc64/iSeries/iSeries_fixup.h b/include/asm-ppc64/iSeries/iSeries_fixup.h
deleted file mode 100644
index c463f79b5de15..0000000000000
--- a/include/asm-ppc64/iSeries/iSeries_fixup.h
+++ /dev/null
@@ -1,25 +0,0 @@
-
-#ifndef __ISERIES_FIXUP_H__
-#define __ISERIES_FIXUP_H__
-#include <linux/pci.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-void iSeries_fixup (void);
-void iSeries_fixup_bus (struct pci_bus*);
-unsigned int iSeries_scan_slot (struct pci_dev*, u16, u8, u8);
-
-
-/* Need to store information related to the PHB bucc and make it accessible to the hose */
-struct iSeries_hose_arch_data {
- u32 hvBusNumber;
-};
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __ISERIES_FIXUP_H__ */
diff --git a/include/asm-ppc64/io.h b/include/asm-ppc64/io.h
index 7a1194f606be8..aba1dfa388ba5 100644
--- a/include/asm-ppc64/io.h
+++ b/include/asm-ppc64/io.h
@@ -442,6 +442,17 @@ out:
extern int check_legacy_ioport(unsigned long base_port);
+/*
+ * Convert a physical pointer to a virtual kernel pointer for /dev/mem
+ * access
+ */
+#define xlate_dev_mem_ptr(p) __va(p)
+
+/*
+ * Convert a virtual cached pointer to an uncached pointer
+ */
+#define xlate_dev_kmem_ptr(p) p
+
#endif /* __KERNEL__ */
#endif /* _PPC64_IO_H */
diff --git a/include/asm-ppc64/iommu.h b/include/asm-ppc64/iommu.h
index 19f57ab596414..bd53ca4dcfa26 100644
--- a/include/asm-ppc64/iommu.h
+++ b/include/asm-ppc64/iommu.h
@@ -145,9 +145,9 @@ extern int iommu_map_sg(struct device *dev, struct iommu_table *tbl,
extern void iommu_unmap_sg(struct iommu_table *tbl, struct scatterlist *sglist,
int nelems, enum dma_data_direction direction);
-extern void *iommu_alloc_consistent(struct iommu_table *tbl, size_t size,
- dma_addr_t *dma_handle);
-extern void iommu_free_consistent(struct iommu_table *tbl, size_t size,
+extern void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size,
+ dma_addr_t *dma_handle, unsigned int __nocast flag);
+extern void iommu_free_coherent(struct iommu_table *tbl, size_t size,
void *vaddr, dma_addr_t dma_handle);
extern dma_addr_t iommu_map_single(struct iommu_table *tbl, void *vaddr,
size_t size, enum dma_data_direction direction);
diff --git a/include/asm-ppc64/ipc.h b/include/asm-ppc64/ipc.h
index f91bf5b0d092e..a46e3d9c2a3fc 100644
--- a/include/asm-ppc64/ipc.h
+++ b/include/asm-ppc64/ipc.h
@@ -1,34 +1 @@
-#ifndef __PPC64_IPC_H__
-#define __PPC64_IPC_H__
-
-/*
- * These are used to wrap system calls on PowerPC.
- *
- * See arch/ppc64/kernel/syscalls.c for ugly details..
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-struct ipc_kludge {
- struct msgbuf __user *msgp;
- long msgtyp;
-};
-
-#define SEMOP 1
-#define SEMGET 2
-#define SEMCTL 3
-#define SEMTIMEDOP 4
-#define MSGSND 11
-#define MSGRCV 12
-#define MSGGET 13
-#define MSGCTL 14
-#define SHMAT 21
-#define SHMDT 22
-#define SHMGET 23
-#define SHMCTL 24
-
-#define IPCCALL(version,op) ((version)<<16 | (op))
-
-#endif /* __PPC64_IPC_H__ */
+#include <asm-generic/ipc.h>
diff --git a/include/asm-ppc64/kprobes.h b/include/asm-ppc64/kprobes.h
index 097f0d63d1e20..19b468bed0590 100644
--- a/include/asm-ppc64/kprobes.h
+++ b/include/asm-ppc64/kprobes.h
@@ -35,6 +35,11 @@ typedef unsigned int kprobe_opcode_t;
#define BREAKPOINT_INSTRUCTION 0x7fe00008 /* trap */
#define MAX_INSN_SIZE 1
+#define IS_TW(instr) (((instr) & 0xfc0007fe) == 0x7c000008)
+#define IS_TD(instr) (((instr) & 0xfc0007fe) == 0x7c000088)
+#define IS_TDI(instr) (((instr) & 0xfc000000) == 0x08000000)
+#define IS_TWI(instr) (((instr) & 0xfc000000) == 0x0c000000)
+
#define JPROBE_ENTRY(pentry) (kprobe_opcode_t *)((func_descr_t *)pentry)
/* Architecture specific copy of original instruction */
diff --git a/include/asm-ppc64/lmb.h b/include/asm-ppc64/lmb.h
index f1c1f0a38ccdc..a6cbca21ac1d7 100644
--- a/include/asm-ppc64/lmb.h
+++ b/include/asm-ppc64/lmb.h
@@ -16,8 +16,6 @@
#include <linux/init.h>
#include <asm/prom.h>
-extern unsigned long reloc_offset(void);
-
#define MAX_LMB_REGIONS 128
#define LMB_ALLOC_ANYWHERE 0
@@ -53,6 +51,7 @@ extern unsigned long __init lmb_alloc_base(unsigned long, unsigned long,
extern unsigned long __init lmb_phys_mem_size(void);
extern unsigned long __init lmb_end_of_DRAM(void);
extern unsigned long __init lmb_abs_to_phys(unsigned long);
+extern void __init lmb_enforce_memory_limit(void);
extern void lmb_dump_all(void);
diff --git a/include/asm-ppc64/machdep.h b/include/asm-ppc64/machdep.h
index 476d2185ffd12..5d3cd9d042e29 100644
--- a/include/asm-ppc64/machdep.h
+++ b/include/asm-ppc64/machdep.h
@@ -21,6 +21,7 @@ struct pci_bus;
struct device_node;
struct iommu_table;
struct rtc_time;
+struct file;
#ifdef CONFIG_SMP
struct smp_ops_t {
@@ -30,8 +31,10 @@ struct smp_ops_t {
void (*setup_cpu)(int nr);
void (*take_timebase)(void);
void (*give_timebase)(void);
+ int (*cpu_enable)(unsigned int nr);
int (*cpu_disable)(void);
void (*cpu_die)(unsigned int nr);
+ int (*cpu_bootable)(unsigned int nr);
};
#endif
@@ -129,11 +132,34 @@ struct machdep_calls {
/* Get legacy PCI/IDE interrupt mapping */
int (*pci_get_legacy_ide_irq)(struct pci_dev *dev, int channel);
+ /* Get access protection for /dev/mem */
+ pgprot_t (*phys_mem_access_prot)(struct file *file,
+ unsigned long offset,
+ unsigned long size,
+ pgprot_t vma_prot);
+
};
extern struct machdep_calls ppc_md;
extern char cmd_line[COMMAND_LINE_SIZE];
+#ifdef CONFIG_PPC_PMAC
+/*
+ * Power macintoshes have either a CUDA, PMU or SMU controlling
+ * system reset, power, NVRAM, RTC.
+ */
+typedef enum sys_ctrler_kind {
+ SYS_CTRLER_UNKNOWN = 0,
+ SYS_CTRLER_CUDA = 1,
+ SYS_CTRLER_PMU = 2,
+ SYS_CTRLER_SMU = 3,
+} sys_ctrler_t;
+extern sys_ctrler_t sys_ctrler;
+
+#endif /* CONFIG_PPC_PMAC */
+
+
+
/* Functions to produce codes on the leds.
* The SRC code should be unique for the message category and should
* be limited to the lower 24 bits (the upper 8 are set by these funcs),
diff --git a/include/asm-ppc64/mmu_context.h b/include/asm-ppc64/mmu_context.h
index 37f6ea055bf31..c2e8e04663830 100644
--- a/include/asm-ppc64/mmu_context.h
+++ b/include/asm-ppc64/mmu_context.h
@@ -59,11 +59,11 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
return;
#ifdef CONFIG_ALTIVEC
- if (cur_cpu_spec->cpu_features & CPU_FTR_ALTIVEC)
+ if (cpu_has_feature(CPU_FTR_ALTIVEC))
asm volatile ("dssall");
#endif /* CONFIG_ALTIVEC */
- if (cur_cpu_spec->cpu_features & CPU_FTR_SLB)
+ if (cpu_has_feature(CPU_FTR_SLB))
switch_slb(tsk, next);
else
switch_stab(tsk, next);
diff --git a/include/asm-ppc64/pSeries_reconfig.h b/include/asm-ppc64/pSeries_reconfig.h
new file mode 100644
index 0000000000000..c0db1ea7f7d1b
--- /dev/null
+++ b/include/asm-ppc64/pSeries_reconfig.h
@@ -0,0 +1,25 @@
+#ifndef _PPC64_PSERIES_RECONFIG_H
+#define _PPC64_PSERIES_RECONFIG_H
+
+#include <linux/notifier.h>
+
+/*
+ * Use this API if your code needs to know about OF device nodes being
+ * added or removed on pSeries systems.
+ */
+
+#define PSERIES_RECONFIG_ADD 0x0001
+#define PSERIES_RECONFIG_REMOVE 0x0002
+
+#ifdef CONFIG_PPC_PSERIES
+extern int pSeries_reconfig_notifier_register(struct notifier_block *);
+extern void pSeries_reconfig_notifier_unregister(struct notifier_block *);
+#else /* !CONFIG_PPC_PSERIES */
+static inline int pSeries_reconfig_notifier_register(struct notifier_block *nb)
+{
+ return 0;
+}
+static inline void pSeries_reconfig_notifier_unregister(struct notifier_block *nb) { }
+#endif /* CONFIG_PPC_PSERIES */
+
+#endif /* _PPC64_PSERIES_RECONFIG_H */
diff --git a/include/asm-ppc64/paca.h b/include/asm-ppc64/paca.h
index f893406eec132..1a0223b5f3b8e 100644
--- a/include/asm-ppc64/paca.h
+++ b/include/asm-ppc64/paca.h
@@ -22,7 +22,6 @@
#include <asm/iSeries/ItLpRegSave.h>
#include <asm/mmu.h>
-extern struct paca_struct paca[];
register struct paca_struct *local_paca asm("r13");
#define get_paca() local_paca
@@ -115,4 +114,6 @@ struct paca_struct {
#endif
};
+extern struct paca_struct paca[];
+
#endif /* _PPC64_PACA_H */
diff --git a/include/asm-ppc64/page.h b/include/asm-ppc64/page.h
index ca828e5aeb8aa..20e0f19324e8a 100644
--- a/include/asm-ppc64/page.h
+++ b/include/asm-ppc64/page.h
@@ -48,8 +48,8 @@
#define ARCH_HAS_HUGEPAGE_ONLY_RANGE
#define ARCH_HAS_PREPARE_HUGEPAGE_RANGE
-#define touches_hugepage_low_range(addr, len) \
- (LOW_ESID_MASK((addr), (len)) & current->mm->context.htlb_segs)
+#define touches_hugepage_low_range(mm, addr, len) \
+ (LOW_ESID_MASK((addr), (len)) & mm->context.htlb_segs)
#define touches_hugepage_high_range(addr, len) \
(((addr) > (TASK_HPAGE_BASE-(len))) && ((addr) < TASK_HPAGE_END))
@@ -61,13 +61,13 @@
#define within_hugepage_high_range(addr, len) (((addr) >= TASK_HPAGE_BASE) \
&& ((addr)+(len) <= TASK_HPAGE_END) && ((addr)+(len) >= (addr)))
-#define is_hugepage_only_range(addr, len) \
+#define is_hugepage_only_range(mm, addr, len) \
(touches_hugepage_high_range((addr), (len)) || \
- touches_hugepage_low_range((addr), (len)))
+ touches_hugepage_low_range((mm), (addr), (len)))
#define HAVE_ARCH_HUGETLB_UNMAPPED_AREA
#define in_hugepage_area(context, addr) \
- ((cur_cpu_spec->cpu_features & CPU_FTR_16M_PAGE) && \
+ (cpu_has_feature(CPU_FTR_16M_PAGE) && \
( (((addr) >= TASK_HPAGE_BASE) && ((addr) < TASK_HPAGE_END)) || \
( ((addr) < 0x100000000L) && \
((1 << GET_ESID(addr)) & (context).htlb_segs) ) ) )
@@ -185,6 +185,9 @@ extern int page_is_ram(unsigned long pfn);
extern u64 ppc64_pft_size; /* Log 2 of page table size */
+/* We do define AT_SYSINFO_EHDR but don't use the gate mecanism */
+#define __HAVE_ARCH_GATE_AREA 1
+
#endif /* __ASSEMBLY__ */
#ifdef MODULE
@@ -232,7 +235,26 @@ extern u64 ppc64_pft_size; /* Log 2 of page table size */
#define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
-#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
+/*
+ * Unfortunately the PLT is in the BSS in the PPC32 ELF ABI,
+ * and needs to be executable. This means the whole heap ends
+ * up being executable.
+ */
+#define VM_DATA_DEFAULT_FLAGS32 (VM_READ | VM_WRITE | VM_EXEC | \
+ VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
+
+#define VM_DATA_DEFAULT_FLAGS64 (VM_READ | VM_WRITE | \
+ VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
+
+#define VM_DATA_DEFAULT_FLAGS \
+ (test_thread_flag(TIF_32BIT) ? \
+ VM_DATA_DEFAULT_FLAGS32 : VM_DATA_DEFAULT_FLAGS64)
+
+/*
+ * This is the default if a program doesn't have a PT_GNU_STACK
+ * program header entry.
+ */
+#define VM_STACK_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
#endif /* __KERNEL__ */
diff --git a/include/asm-ppc64/pci.h b/include/asm-ppc64/pci.h
index 144878b404aa5..6cd593f660a03 100644
--- a/include/asm-ppc64/pci.h
+++ b/include/asm-ppc64/pci.h
@@ -13,11 +13,14 @@
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/dma-mapping.h>
+
#include <asm/machdep.h>
#include <asm/scatterlist.h>
#include <asm/io.h>
#include <asm/prom.h>
+#include <asm-generic/pci-dma-compat.h>
+
#define PCIBIOS_MIN_IO 0x1000
#define PCIBIOS_MIN_MEM 0x10000000
@@ -63,135 +66,22 @@ static inline int pcibios_prep_mwi(struct pci_dev *dev)
extern unsigned int pcibios_assign_all_busses(void);
-/*
- * PCI DMA operations are abstracted for G5 vs. i/pSeries
- */
-struct pci_dma_ops {
- void * (*pci_alloc_consistent)(struct pci_dev *hwdev, size_t size,
- dma_addr_t *dma_handle);
- void (*pci_free_consistent)(struct pci_dev *hwdev, size_t size,
- void *vaddr, dma_addr_t dma_handle);
-
- dma_addr_t (*pci_map_single)(struct pci_dev *hwdev, void *ptr,
- size_t size, enum dma_data_direction direction);
- void (*pci_unmap_single)(struct pci_dev *hwdev, dma_addr_t dma_addr,
- size_t size, enum dma_data_direction direction);
- int (*pci_map_sg)(struct pci_dev *hwdev, struct scatterlist *sg,
- int nents, enum dma_data_direction direction);
- void (*pci_unmap_sg)(struct pci_dev *hwdev, struct scatterlist *sg,
- int nents, enum dma_data_direction direction);
- int (*pci_dma_supported)(struct pci_dev *hwdev, u64 mask);
- int (*pci_dac_dma_supported)(struct pci_dev *hwdev, u64 mask);
-};
-
-extern struct pci_dma_ops pci_dma_ops;
-
-static inline void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
- dma_addr_t *dma_handle)
-{
- return pci_dma_ops.pci_alloc_consistent(hwdev, size, dma_handle);
-}
-
-static inline void pci_free_consistent(struct pci_dev *hwdev, size_t size,
- void *vaddr, dma_addr_t dma_handle)
-{
- pci_dma_ops.pci_free_consistent(hwdev, size, vaddr, dma_handle);
-}
-
-static inline dma_addr_t pci_map_single(struct pci_dev *hwdev, void *ptr,
- size_t size, int direction)
-{
- return pci_dma_ops.pci_map_single(hwdev, ptr, size,
- (enum dma_data_direction)direction);
-}
-
-static inline void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr,
- size_t size, int direction)
-{
- pci_dma_ops.pci_unmap_single(hwdev, dma_addr, size,
- (enum dma_data_direction)direction);
-}
-
-static inline int pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg,
- int nents, int direction)
-{
- return pci_dma_ops.pci_map_sg(hwdev, sg, nents,
- (enum dma_data_direction)direction);
-}
-
-static inline void pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg,
- int nents, int direction)
-{
- pci_dma_ops.pci_unmap_sg(hwdev, sg, nents,
- (enum dma_data_direction)direction);
-}
-
-static inline void pci_dma_sync_single_for_cpu(struct pci_dev *hwdev,
- dma_addr_t dma_handle,
- size_t size, int direction)
-{
- BUG_ON(direction == PCI_DMA_NONE);
- /* nothing to do */
-}
-
-static inline void pci_dma_sync_single_for_device(struct pci_dev *hwdev,
- dma_addr_t dma_handle,
- size_t size, int direction)
-{
- BUG_ON(direction == PCI_DMA_NONE);
- /* nothing to do */
-}
-
-static inline void pci_dma_sync_sg_for_cpu(struct pci_dev *hwdev,
- struct scatterlist *sg,
- int nelems, int direction)
-{
- BUG_ON(direction == PCI_DMA_NONE);
- /* nothing to do */
-}
-
-static inline void pci_dma_sync_sg_for_device(struct pci_dev *hwdev,
- struct scatterlist *sg,
- int nelems, int direction)
-{
- BUG_ON(direction == PCI_DMA_NONE);
- /* nothing to do */
-}
-
-/* Return whether the given PCI device DMA address mask can
- * be supported properly. For example, if your device can
- * only drive the low 24-bits during PCI bus mastering, then
- * you would pass 0x00ffffff as the mask to this function.
- * We default to supporting only 32 bits DMA unless we have
- * an explicit override of this function in pci_dma_ops for
- * the platform
- */
-static inline int pci_dma_supported(struct pci_dev *hwdev, u64 mask)
-{
- if (pci_dma_ops.pci_dma_supported)
- return pci_dma_ops.pci_dma_supported(hwdev, mask);
- return (mask < 0x100000000ull);
-}
+extern struct dma_mapping_ops pci_dma_ops;
/* For DAC DMA, we currently don't support it by default, but
* we let the platform override this
*/
static inline int pci_dac_dma_supported(struct pci_dev *hwdev,u64 mask)
{
- if (pci_dma_ops.pci_dac_dma_supported)
- return pci_dma_ops.pci_dac_dma_supported(hwdev, mask);
+ if (pci_dma_ops.dac_dma_supported)
+ return pci_dma_ops.dac_dma_supported(&hwdev->dev, mask);
return 0;
}
-static inline int pci_dma_mapping_error(dma_addr_t dma_addr)
-{
- return dma_mapping_error(dma_addr);
-}
-
extern int pci_domain_nr(struct pci_bus *bus);
-/* Set the name of the bus as it appears in /proc/bus/pci */
-extern int pci_name_bus(char *name, struct pci_bus *bus);
+/* Decide whether to display the domain number in /proc */
+extern int pci_proc_domain(struct pci_bus *bus);
struct vm_area_struct;
/* Map a range of PCI memory or I/O space for a device into user space */
@@ -201,10 +91,6 @@ int pci_mmap_page_range(struct pci_dev *pdev, struct vm_area_struct *vma,
/* Tell drivers/pci/proc.c that we have pci_mmap_page_range() */
#define HAVE_PCI_MMAP 1
-#define pci_map_page(dev, page, off, size, dir) \
- pci_map_single(dev, (page_address(page) + (off)), size, dir)
-#define pci_unmap_page(dev,addr,sz,dir) pci_unmap_single(dev,addr,sz,dir)
-
/* pci_unmap_{single,page} is not a nop, thus... */
#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) \
dma_addr_t ADDR_NAME;
@@ -244,6 +130,13 @@ extern int pci_read_irq_line(struct pci_dev *dev);
extern void pcibios_add_platform_entries(struct pci_dev *dev);
+struct file;
+extern pgprot_t pci_phys_mem_access_prot(struct file *file,
+ unsigned long offset,
+ unsigned long size,
+ pgprot_t prot);
+
+
#endif /* __KERNEL__ */
#endif /* __PPC64_PCI_H */
diff --git a/include/asm-ppc64/pgalloc.h b/include/asm-ppc64/pgalloc.h
index dd717c2bb6445..16232d7401730 100644
--- a/include/asm-ppc64/pgalloc.h
+++ b/include/asm-ppc64/pgalloc.h
@@ -5,9 +5,6 @@
#include <linux/slab.h>
#include <linux/cpumask.h>
#include <linux/percpu.h>
-#include <asm/processor.h>
-#include <asm/tlb.h>
-#include <asm/page.h>
extern kmem_cache_t *zero_cache;
@@ -48,42 +45,26 @@ pmd_free(pmd_t *pmd)
#define pmd_populate(mm, pmd, pte_page) \
pmd_populate_kernel(mm, pmd, page_address(pte_page))
-static inline pte_t *
-pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
+static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
{
- pte_t *pte;
- pte = kmem_cache_alloc(zero_cache, GFP_KERNEL|__GFP_REPEAT);
- if (pte) {
- struct page *ptepage = virt_to_page(pte);
- ptepage->mapping = (void *) mm;
- ptepage->index = address & PMD_MASK;
- }
- return pte;
+ return kmem_cache_alloc(zero_cache, GFP_KERNEL|__GFP_REPEAT);
}
-static inline struct page *
-pte_alloc_one(struct mm_struct *mm, unsigned long address)
+static inline struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
{
- pte_t *pte;
- pte = kmem_cache_alloc(zero_cache, GFP_KERNEL|__GFP_REPEAT);
- if (pte) {
- struct page *ptepage = virt_to_page(pte);
- ptepage->mapping = (void *) mm;
- ptepage->index = address & PMD_MASK;
- return ptepage;
- }
+ pte_t *pte = kmem_cache_alloc(zero_cache, GFP_KERNEL|__GFP_REPEAT);
+ if (pte)
+ return virt_to_page(pte);
return NULL;
}
static inline void pte_free_kernel(pte_t *pte)
{
- virt_to_page(pte)->mapping = NULL;
kmem_cache_free(zero_cache, pte);
}
static inline void pte_free(struct page *ptepage)
{
- ptepage->mapping = NULL;
kmem_cache_free(zero_cache, page_address(ptepage));
}
diff --git a/include/asm-ppc64/pgtable.h b/include/asm-ppc64/pgtable.h
index 0f6990ad957d6..8a79ece01aa50 100644
--- a/include/asm-ppc64/pgtable.h
+++ b/include/asm-ppc64/pgtable.h
@@ -82,14 +82,14 @@
#define _PAGE_PRESENT 0x0001 /* software: pte contains a translation */
#define _PAGE_USER 0x0002 /* matches one of the PP bits */
#define _PAGE_FILE 0x0002 /* (!present only) software: pte holds file offset */
-#define _PAGE_RW 0x0004 /* software: user write access allowed */
+#define _PAGE_EXEC 0x0004 /* No execute on POWER4 and newer (we invert) */
#define _PAGE_GUARDED 0x0008
#define _PAGE_COHERENT 0x0010 /* M: enforce memory coherence (SMP systems) */
#define _PAGE_NO_CACHE 0x0020 /* I: cache inhibit */
#define _PAGE_WRITETHRU 0x0040 /* W: cache write-through */
#define _PAGE_DIRTY 0x0080 /* C: page changed */
#define _PAGE_ACCESSED 0x0100 /* R: page referenced */
-#define _PAGE_EXEC 0x0200 /* software: i-cache coherence required */
+#define _PAGE_RW 0x0200 /* software: user write access allowed */
#define _PAGE_HASHPTE 0x0400 /* software: pte has an associated HPTE */
#define _PAGE_BUSY 0x0800 /* software: PTE & hash are busy */
#define _PAGE_SECONDARY 0x8000 /* software: HPTE is in secondary group */
@@ -118,29 +118,38 @@
#define PAGE_KERNEL __pgprot(_PAGE_BASE | _PAGE_WRENABLE)
#define PAGE_KERNEL_CI __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | \
_PAGE_WRENABLE | _PAGE_NO_CACHE | _PAGE_GUARDED)
+#define PAGE_KERNEL_EXEC __pgprot(_PAGE_BASE | _PAGE_WRENABLE | _PAGE_EXEC)
/*
- * The PowerPC can only do execute protection on a segment (256MB) basis,
- * not on a page basis. So we consider execute permission the same as read.
+ * This bit in a hardware PTE indicates that the page is *not* executable.
+ */
+#define HW_NO_EXEC _PAGE_EXEC
+
+/*
+ * POWER4 and newer have per page execute protection, older chips can only
+ * do this on a segment (256MB) basis.
+ *
* Also, write permissions imply read permissions.
* This is the closest we can get..
+ *
+ * Note due to the way vm flags are laid out, the bits are XWR
*/
#define __P000 PAGE_NONE
-#define __P001 PAGE_READONLY_X
+#define __P001 PAGE_READONLY
#define __P010 PAGE_COPY
-#define __P011 PAGE_COPY_X
-#define __P100 PAGE_READONLY
+#define __P011 PAGE_COPY
+#define __P100 PAGE_READONLY_X
#define __P101 PAGE_READONLY_X
-#define __P110 PAGE_COPY
+#define __P110 PAGE_COPY_X
#define __P111 PAGE_COPY_X
#define __S000 PAGE_NONE
-#define __S001 PAGE_READONLY_X
+#define __S001 PAGE_READONLY
#define __S010 PAGE_SHARED
-#define __S011 PAGE_SHARED_X
-#define __S100 PAGE_READONLY
+#define __S011 PAGE_SHARED
+#define __S100 PAGE_READONLY_X
#define __S101 PAGE_READONLY_X
-#define __S110 PAGE_SHARED
+#define __S110 PAGE_SHARED_X
#define __S111 PAGE_SHARED_X
#ifndef __ASSEMBLY__
@@ -315,9 +324,10 @@ static inline unsigned long pte_update(pte_t *p, unsigned long clr)
* batch, doesn't actually triggers the hash flush immediately,
* you need to call flush_tlb_pending() to do that.
*/
-extern void hpte_update(pte_t *ptep, unsigned long pte, int wrprot);
+extern void hpte_update(struct mm_struct *mm, unsigned long addr, unsigned long pte,
+ int wrprot);
-static inline int ptep_test_and_clear_young(pte_t *ptep)
+static inline int __ptep_test_and_clear_young(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
{
unsigned long old;
@@ -325,18 +335,25 @@ static inline int ptep_test_and_clear_young(pte_t *ptep)
return 0;
old = pte_update(ptep, _PAGE_ACCESSED);
if (old & _PAGE_HASHPTE) {
- hpte_update(ptep, old, 0);
+ hpte_update(mm, addr, old, 0);
flush_tlb_pending();
}
return (old & _PAGE_ACCESSED) != 0;
}
+#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
+#define ptep_test_and_clear_young(__vma, __addr, __ptep) \
+({ \
+ int __r; \
+ __r = __ptep_test_and_clear_young((__vma)->vm_mm, __addr, __ptep); \
+ __r; \
+})
/*
* On RW/DIRTY bit transitions we can avoid flushing the hpte. For the
* moment we always flush but we need to fix hpte_update and test if the
* optimisation is worth it.
*/
-static inline int ptep_test_and_clear_dirty(pte_t *ptep)
+static inline int __ptep_test_and_clear_dirty(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
{
unsigned long old;
@@ -344,11 +361,19 @@ static inline int ptep_test_and_clear_dirty(pte_t *ptep)
return 0;
old = pte_update(ptep, _PAGE_DIRTY);
if (old & _PAGE_HASHPTE)
- hpte_update(ptep, old, 0);
+ hpte_update(mm, addr, old, 0);
return (old & _PAGE_DIRTY) != 0;
}
+#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
+#define ptep_test_and_clear_dirty(__vma, __addr, __ptep) \
+({ \
+ int __r; \
+ __r = __ptep_test_and_clear_dirty((__vma)->vm_mm, __addr, __ptep); \
+ __r; \
+})
-static inline void ptep_set_wrprotect(pte_t *ptep)
+#define __HAVE_ARCH_PTEP_SET_WRPROTECT
+static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
{
unsigned long old;
@@ -356,7 +381,7 @@ static inline void ptep_set_wrprotect(pte_t *ptep)
return;
old = pte_update(ptep, _PAGE_RW);
if (old & _PAGE_HASHPTE)
- hpte_update(ptep, old, 0);
+ hpte_update(mm, addr, old, 0);
}
/*
@@ -370,42 +395,46 @@ static inline void ptep_set_wrprotect(pte_t *ptep)
#define __HAVE_ARCH_PTEP_CLEAR_YOUNG_FLUSH
#define ptep_clear_flush_young(__vma, __address, __ptep) \
({ \
- int __young = ptep_test_and_clear_young(__ptep); \
+ int __young = __ptep_test_and_clear_young((__vma)->vm_mm, __address, \
+ __ptep); \
__young; \
})
#define __HAVE_ARCH_PTEP_CLEAR_DIRTY_FLUSH
#define ptep_clear_flush_dirty(__vma, __address, __ptep) \
({ \
- int __dirty = ptep_test_and_clear_dirty(__ptep); \
+ int __dirty = __ptep_test_and_clear_dirty((__vma)->vm_mm, __address, \
+ __ptep); \
flush_tlb_page(__vma, __address); \
__dirty; \
})
-static inline pte_t ptep_get_and_clear(pte_t *ptep)
+#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
+static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
{
unsigned long old = pte_update(ptep, ~0UL);
if (old & _PAGE_HASHPTE)
- hpte_update(ptep, old, 0);
+ hpte_update(mm, addr, old, 0);
return __pte(old);
}
-static inline void pte_clear(pte_t * ptep)
+static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t * ptep)
{
unsigned long old = pte_update(ptep, ~0UL);
if (old & _PAGE_HASHPTE)
- hpte_update(ptep, old, 0);
+ hpte_update(mm, addr, old, 0);
}
/*
* set_pte stores a linux PTE into the linux page table.
*/
-static inline void set_pte(pte_t *ptep, pte_t pte)
+static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
+ pte_t *ptep, pte_t pte)
{
if (pte_present(*ptep)) {
- pte_clear(ptep);
+ pte_clear(mm, addr, ptep);
flush_tlb_pending();
}
*ptep = __pte(pte_val(pte)) & ~_PAGE_HPTEFLAGS;
@@ -418,7 +447,7 @@ static inline void set_pte(pte_t *ptep, pte_t pte)
static inline void __ptep_set_access_flags(pte_t *ptep, pte_t entry, int dirty)
{
unsigned long bits = pte_val(entry) &
- (_PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_RW);
+ (_PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_RW | _PAGE_EXEC);
unsigned long old, tmp;
__asm__ __volatile__(
@@ -443,6 +472,12 @@ static inline void __ptep_set_access_flags(pte_t *ptep, pte_t entry, int dirty)
*/
#define pgprot_noncached(prot) (__pgprot(pgprot_val(prot) | _PAGE_NO_CACHE | _PAGE_GUARDED))
+struct file;
+extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long addr,
+ unsigned long size, pgprot_t vma_prot);
+#define __HAVE_PHYS_MEM_ACCESS_PROT
+
+#define __HAVE_ARCH_PTE_SAME
#define pte_same(A,B) (((pte_val(A) ^ pte_val(B)) & ~_PAGE_HPTEFLAGS) == 0)
extern unsigned long ioremap_bot, ioremap_base;
@@ -497,6 +532,13 @@ extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t);
#define io_remap_page_range(vma, vaddr, paddr, size, prot) \
remap_pfn_range(vma, vaddr, (paddr) >> PAGE_SHIFT, size, prot)
+#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
+ remap_pfn_range(vma, vaddr, pfn, size, prot)
+
+#define MK_IOSPACE_PFN(space, pfn) (pfn)
+#define GET_IOSPACE(pfn) 0
+#define GET_PFN(pfn) (pfn)
+
void pgtable_cache_init(void);
extern void hpte_init_native(void);
@@ -550,14 +592,8 @@ static inline pte_t *find_linux_pte(pgd_t *pgdir, unsigned long ea)
return pt;
}
-#endif /* __ASSEMBLY__ */
-
-#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
-#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
-#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
-#define __HAVE_ARCH_PTEP_SET_WRPROTECT
-#define __HAVE_ARCH_PTEP_MKDIRTY
-#define __HAVE_ARCH_PTE_SAME
#include <asm-generic/pgtable.h>
+#endif /* __ASSEMBLY__ */
+
#endif /* _PPC64_PGTABLE_H */
diff --git a/include/asm-ppc64/pmc.h b/include/asm-ppc64/pmc.h
new file mode 100644
index 0000000000000..c924748c0beaa
--- /dev/null
+++ b/include/asm-ppc64/pmc.h
@@ -0,0 +1,29 @@
+/*
+ * pmc.h
+ * Copyright (C) 2004 David Gibson, 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
+ */
+#ifndef _PPC64_PMC_H
+#define _PPC64_PMC_H
+
+#include <asm/ptrace.h>
+
+typedef void (*perf_irq_t)(struct pt_regs *);
+
+int reserve_pmc_hardware(perf_irq_t new_perf_irq);
+void release_pmc_hardware(void);
+
+#endif /* _PPC64_PMC_H */
diff --git a/include/asm-ppc64/processor.h b/include/asm-ppc64/processor.h
index e524e77186dbd..eb33d33cfd6d3 100644
--- a/include/asm-ppc64/processor.h
+++ b/include/asm-ppc64/processor.h
@@ -173,6 +173,11 @@
#define SPRN_DEC 0x016 /* Decrement Register */
#define SPRN_DMISS 0x3D0 /* Data TLB Miss Register */
#define SPRN_DSISR 0x012 /* Data Storage Interrupt Status Register */
+#define DSISR_NOHPTE 0x40000000 /* no translation found */
+#define DSISR_PROTFAULT 0x08000000 /* protection fault */
+#define DSISR_ISSTORE 0x02000000 /* access was a store */
+#define DSISR_DABRMATCH 0x00400000 /* hit data breakpoint */
+#define DSISR_NOSEGMENT 0x00200000 /* STAB/SLB miss */
#define SPRN_EAR 0x11A /* External Address Register */
#define SPRN_ESR 0x3D4 /* Exception Syndrome Register */
#define ESR_IMCP 0x80000000 /* Instr. Machine Check - Protection */
@@ -544,8 +549,8 @@ extern struct task_struct *last_task_used_altivec;
/* This decides where the kernel will search for a free chunk of vm
* space during mmap's.
*/
-#define TASK_UNMAPPED_BASE_USER32 (PAGE_ALIGN(STACK_TOP_USER32 / 4))
-#define TASK_UNMAPPED_BASE_USER64 (PAGE_ALIGN(STACK_TOP_USER64 / 4))
+#define TASK_UNMAPPED_BASE_USER32 (PAGE_ALIGN(TASK_SIZE_USER32 / 4))
+#define TASK_UNMAPPED_BASE_USER64 (PAGE_ALIGN(TASK_SIZE_USER64 / 4))
#define TASK_UNMAPPED_BASE ((test_thread_flag(TIF_32BIT)||(ppcdebugset(PPCDBG_BINFMT_32ADDR))) ? \
TASK_UNMAPPED_BASE_USER32 : TASK_UNMAPPED_BASE_USER64 )
@@ -562,7 +567,9 @@ struct thread_struct {
double fpr[32]; /* Complete floating point set */
unsigned long fpscr; /* Floating point status (plus pad) */
unsigned long fpexc_mode; /* Floating-point exception mode */
- unsigned long pad[3]; /* was saved_msr, saved_softe */
+ unsigned long start_tb; /* Start purr when proc switched in */
+ unsigned long accum_tb; /* Total accumilated purr for process */
+ unsigned long vdso_base; /* base of the vDSO library */
#ifdef CONFIG_ALTIVEC
/* Complete AltiVec register set */
vector128 vr[32] __attribute((aligned(16)));
diff --git a/include/asm-ppc64/prom.h b/include/asm-ppc64/prom.h
index 9b952e933fced..2440a2c90ae9a 100644
--- a/include/asm-ppc64/prom.h
+++ b/include/asm-ppc64/prom.h
@@ -137,6 +137,7 @@ struct device_node {
int devfn; /* for pci devices */
int eeh_mode; /* See eeh.h for possible EEH_MODEs */
int eeh_config_addr;
+ int pci_ext_config_space; /* for pci devices */
struct pci_controller *phb; /* for pci devices */
struct iommu_table *iommu_table; /* for phb's or bridges */
@@ -208,8 +209,8 @@ extern struct device_node *of_node_get(struct device_node *node);
extern void of_node_put(struct device_node *node);
/* For updating the device tree at runtime */
-extern int of_add_node(const char *path, struct property *proplist);
-extern int of_remove_node(struct device_node *np);
+extern void of_attach_node(struct device_node *);
+extern void of_detach_node(const struct device_node *);
/* Other Prototypes */
extern unsigned long prom_init(unsigned long, unsigned long, unsigned long,
diff --git a/include/asm-ppc64/rtas.h b/include/asm-ppc64/rtas.h
index dc2879cc49813..a8ab0e9db84a6 100644
--- a/include/asm-ppc64/rtas.h
+++ b/include/asm-ppc64/rtas.h
@@ -24,12 +24,9 @@
/* RTAS return status codes */
#define RTAS_BUSY -2 /* RTAS Busy */
-#define RTAS_NO_SUCH_INDICATOR -3 /* No such indicator implemented */
#define RTAS_EXTENDED_DELAY_MIN 9900
#define RTAS_EXTENDED_DELAY_MAX 9905
-#define RTAS_UNKNOWN_OP -1099 /* Unknown RTAS Token */
-
/*
* In general to call RTAS use rtas_token("string") to lookup
* an RTAS token for the given string (e.g. "event-scan").
diff --git a/include/asm-ppc64/seccomp.h b/include/asm-ppc64/seccomp.h
new file mode 100644
index 0000000000000..c130c334bda1c
--- /dev/null
+++ b/include/asm-ppc64/seccomp.h
@@ -0,0 +1,21 @@
+#ifndef _ASM_SECCOMP_H
+
+#include <linux/thread_info.h> /* already defines TIF_32BIT */
+
+#ifndef TIF_32BIT
+#error "unexpected TIF_32BIT on ppc64"
+#endif
+
+#include <linux/unistd.h>
+
+#define __NR_seccomp_read __NR_read
+#define __NR_seccomp_write __NR_write
+#define __NR_seccomp_exit __NR_exit
+#define __NR_seccomp_sigreturn __NR_rt_sigreturn
+
+#define __NR_seccomp_read_32 __NR_read
+#define __NR_seccomp_write_32 __NR_write
+#define __NR_seccomp_exit_32 __NR_exit
+#define __NR_seccomp_sigreturn_32 __NR_sigreturn
+
+#endif /* _ASM_SECCOMP_H */
diff --git a/include/asm-ppc64/sections.h b/include/asm-ppc64/sections.h
index 95bac41d79b80..308ca6f5ced22 100644
--- a/include/asm-ppc64/sections.h
+++ b/include/asm-ppc64/sections.h
@@ -17,4 +17,13 @@ extern char _end[];
#define __openfirmware
#define __openfirmwaredata
+
+static inline int in_kernel_text(unsigned long addr)
+{
+ if (addr >= (unsigned long)_stext && addr < (unsigned long)__init_end)
+ return 1;
+
+ return 0;
+}
+
#endif
diff --git a/include/asm-ppc64/smp.h b/include/asm-ppc64/smp.h
index 965980bbbb574..c8646fa999c2f 100644
--- a/include/asm-ppc64/smp.h
+++ b/include/asm-ppc64/smp.h
@@ -29,7 +29,7 @@
extern int boot_cpuid;
extern int boot_cpuid_phys;
-extern void cpu_die(void) __attribute__((noreturn));
+extern void cpu_die(void);
#ifdef CONFIG_SMP
@@ -37,6 +37,13 @@ extern void smp_send_debugger_break(int cpu);
struct pt_regs;
extern void smp_message_recv(int, struct pt_regs *);
+#ifdef CONFIG_HOTPLUG_CPU
+extern void fixup_irqs(cpumask_t map);
+int generic_cpu_disable(void);
+int generic_cpu_enable(unsigned int cpu);
+void generic_cpu_die(unsigned int cpu);
+void generic_mach_cpu_die(void);
+#endif
#define __smp_processor_id() (get_paca()->paca_index)
#define hard_smp_processor_id() (get_paca()->hw_cpu_id)
diff --git a/include/asm-ppc64/smu.h b/include/asm-ppc64/smu.h
new file mode 100644
index 0000000000000..10b4397af9aa4
--- /dev/null
+++ b/include/asm-ppc64/smu.h
@@ -0,0 +1,22 @@
+/*
+ * Definitions for talking to the SMU chip in newer G5 PowerMacs
+ */
+
+#include <linux/config.h>
+
+/*
+ * Basic routines for use by architecture. To be extended as
+ * we understand more of the chip
+ */
+extern int smu_init(void);
+extern int smu_present(void);
+extern void smu_shutdown(void);
+extern void smu_restart(void);
+extern int smu_get_rtc_time(struct rtc_time *time);
+extern int smu_set_rtc_time(struct rtc_time *time);
+
+/*
+ * SMU command buffer absolute address, exported by pmac_setup,
+ * this is allocated very early during boot.
+ */
+extern unsigned long smu_cmdbuf_abs;
diff --git a/include/asm-ppc64/system.h b/include/asm-ppc64/system.h
index 6785e69e8b9e4..98d120ca8a91d 100644
--- a/include/asm-ppc64/system.h
+++ b/include/asm-ppc64/system.h
@@ -300,5 +300,7 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
*/
#define NET_IP_ALIGN 0
+#define arch_align_stack(x) (x)
+
#endif /* __KERNEL__ */
#endif
diff --git a/include/asm-ppc64/systemcfg.h b/include/asm-ppc64/systemcfg.h
index 13d96bfaf46d2..9b86b53129aa8 100644
--- a/include/asm-ppc64/systemcfg.h
+++ b/include/asm-ppc64/systemcfg.h
@@ -20,10 +20,14 @@
* Minor version changes are a hint.
*/
#define SYSTEMCFG_MAJOR 1
-#define SYSTEMCFG_MINOR 0
+#define SYSTEMCFG_MINOR 1
#ifndef __ASSEMBLY__
+#include <linux/unistd.h>
+
+#define SYSCALL_MAP_SIZE ((__NR_syscalls + 31) / 32)
+
struct systemcfg {
__u8 eye_catcher[16]; /* Eyecatcher: SYSTEMCFG:PPC64 0x00 */
struct { /* Systemcfg version numbers */
@@ -47,7 +51,8 @@ struct systemcfg {
__u32 dcache_line_size; /* L1 d-cache line size 0x64 */
__u32 icache_size; /* L1 i-cache size 0x68 */
__u32 icache_line_size; /* L1 i-cache line size 0x6C */
- __u8 reserved0[3984]; /* Reserve rest of page 0x70 */
+ __u32 syscall_map_64[SYSCALL_MAP_SIZE]; /* map of available syscalls 0x70 */
+ __u32 syscall_map_32[SYSCALL_MAP_SIZE]; /* map of available syscalls */
};
#ifdef __KERNEL__
@@ -56,8 +61,4 @@ extern struct systemcfg *systemcfg;
#endif /* __ASSEMBLY__ */
-#define SYSTEMCFG_PAGE 0x5
-#define SYSTEMCFG_PHYS_ADDR (SYSTEMCFG_PAGE<<PAGE_SHIFT)
-#define SYSTEMCFG_VIRT_ADDR (KERNELBASE+SYSTEMCFG_PHYS_ADDR)
-
#endif /* _SYSTEMCFG_H */
diff --git a/include/asm-ppc64/thread_info.h b/include/asm-ppc64/thread_info.h
index d4b978c26d710..037b5e06083c0 100644
--- a/include/asm-ppc64/thread_info.h
+++ b/include/asm-ppc64/thread_info.h
@@ -101,6 +101,7 @@ static inline struct thread_info *current_thread_info(void)
#define TIF_SYSCALL_AUDIT 8 /* syscall auditing active */
#define TIF_SINGLESTEP 9 /* singlestepping active */
#define TIF_MEMDIE 10
+#define TIF_SECCOMP 11 /* secure computing */
/* as above, but as bit values */
#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
@@ -113,7 +114,8 @@ static inline struct thread_info *current_thread_info(void)
#define _TIF_ABI_PENDING (1<<TIF_ABI_PENDING)
#define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT)
#define _TIF_SINGLESTEP (1<<TIF_SINGLESTEP)
-#define _TIF_SYSCALL_T_OR_A (_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT)
+#define _TIF_SECCOMP (1<<TIF_SECCOMP)
+#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)
diff --git a/include/asm-ppc64/time.h b/include/asm-ppc64/time.h
index 362d9d90acda5..8d6e3760ee108 100644
--- a/include/asm-ppc64/time.h
+++ b/include/asm-ppc64/time.h
@@ -43,10 +43,10 @@ extern time_t last_rtc_update;
struct gettimeofday_vars {
unsigned long tb_to_xs;
unsigned long stamp_xsec;
+ unsigned long tb_orig_stamp;
};
struct gettimeofday_struct {
- unsigned long tb_orig_stamp;
unsigned long tb_ticks_per_sec;
struct gettimeofday_vars vars[2];
struct gettimeofday_vars * volatile varp;
@@ -102,5 +102,14 @@ static inline unsigned long tb_ticks_since(unsigned long tstamp)
unsigned mulhwu_scale_factor(unsigned, unsigned);
void div128_by_32( unsigned long dividend_high, unsigned long dividend_low,
unsigned divisor, struct div_result *dr );
+
+/* Used to store Processor Utilization register (purr) values */
+
+struct cpu_usage {
+ u64 current_tb; /* Holds the current purr register values */
+};
+
+DECLARE_PER_CPU(struct cpu_usage, cpu_usage_array);
+
#endif /* __KERNEL__ */
#endif /* __PPC64_TIME_H */
diff --git a/include/asm-ppc64/uaccess.h b/include/asm-ppc64/uaccess.h
index e5cdda18d1add..05b5943ab1ee5 100644
--- a/include/asm-ppc64/uaccess.h
+++ b/include/asm-ppc64/uaccess.h
@@ -56,7 +56,8 @@
#define access_ok(type,addr,size) \
__access_ok(((__force unsigned long)(addr)),(size),get_fs())
-static inline int verify_area(int type, const void __user *addr, unsigned long size)
+/* this function will go away soon - use access_ok() instead */
+static inline int __deprecated verify_area(int type, const void __user *addr, unsigned long size)
{
return access_ok(type,addr,size) ? 0 : -EFAULT;
}
@@ -119,6 +120,7 @@ extern long __put_user_bad(void);
#define __put_user_nocheck(x,ptr,size) \
({ \
long __pu_err; \
+ might_sleep(); \
__chk_user_ptr(ptr); \
__put_user_size((x),(ptr),(size),__pu_err,-EFAULT); \
__pu_err; \
@@ -128,6 +130,7 @@ extern long __put_user_bad(void);
({ \
long __pu_err = -EFAULT; \
void __user *__pu_addr = (ptr); \
+ might_sleep(); \
if (access_ok(VERIFY_WRITE,__pu_addr,size)) \
__put_user_size((x),__pu_addr,(size),__pu_err,-EFAULT); \
__pu_err; \
@@ -135,7 +138,6 @@ extern long __put_user_bad(void);
#define __put_user_size(x,ptr,size,retval,errret) \
do { \
- might_sleep(); \
retval = 0; \
switch (size) { \
case 1: __put_user_asm(x,ptr,retval,"stb",errret); break; \
@@ -170,6 +172,7 @@ do { \
#define __get_user_nocheck(x,ptr,size) \
({ \
long __gu_err, __gu_val; \
+ might_sleep(); \
__get_user_size(__gu_val,(ptr),(size),__gu_err,-EFAULT);\
(x) = (__typeof__(*(ptr)))__gu_val; \
__gu_err; \
@@ -179,6 +182,7 @@ do { \
({ \
long __gu_err = -EFAULT, __gu_val = 0; \
const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \
+ might_sleep(); \
if (access_ok(VERIFY_READ,__gu_addr,size)) \
__get_user_size(__gu_val,__gu_addr,(size),__gu_err,-EFAULT);\
(x) = (__typeof__(*(ptr)))__gu_val; \
@@ -189,7 +193,6 @@ extern long __get_user_bad(void);
#define __get_user_size(x,ptr,size,retval,errret) \
do { \
- might_sleep(); \
retval = 0; \
__chk_user_ptr(ptr); \
switch (size) { \
@@ -223,9 +226,8 @@ extern unsigned long __copy_tofrom_user(void __user *to, const void __user *from
unsigned long size);
static inline unsigned long
-__copy_from_user(void *to, const void __user *from, unsigned long n)
+__copy_from_user_inatomic(void *to, const void __user *from, unsigned long n)
{
- might_sleep();
if (__builtin_constant_p(n)) {
unsigned long ret;
@@ -248,9 +250,15 @@ __copy_from_user(void *to, const void __user *from, unsigned long n)
}
static inline unsigned long
-__copy_to_user(void __user *to, const void *from, unsigned long n)
+__copy_from_user(void *to, const void __user *from, unsigned long n)
{
might_sleep();
+ return __copy_from_user_inatomic(to, from, n);
+}
+
+static inline unsigned long
+__copy_to_user_inatomic(void __user *to, const void *from, unsigned long n)
+{
if (__builtin_constant_p(n)) {
unsigned long ret;
@@ -272,6 +280,13 @@ __copy_to_user(void __user *to, const void *from, unsigned long n)
return __copy_tofrom_user(to, (__force const void __user *) from, n);
}
+static inline unsigned long
+__copy_to_user(void __user *to, const void *from, unsigned long n)
+{
+ might_sleep();
+ return __copy_to_user_inatomic(to, from, n);
+}
+
#define __copy_in_user(to, from, size) \
__copy_tofrom_user((to), (from), (size))
@@ -284,9 +299,6 @@ extern unsigned long copy_in_user(void __user *to, const void __user *from,
extern unsigned long __clear_user(void __user *addr, unsigned long size);
-#define __copy_to_user_inatomic __copy_to_user
-#define __copy_from_user_inatomic __copy_from_user
-
static inline unsigned long
clear_user(void __user *addr, unsigned long size)
{
diff --git a/include/asm-ppc64/unistd.h b/include/asm-ppc64/unistd.h
index d20b4a3048388..605d91e011ec1 100644
--- a/include/asm-ppc64/unistd.h
+++ b/include/asm-ppc64/unistd.h
@@ -282,8 +282,9 @@
#define __NR_add_key 269
#define __NR_request_key 270
#define __NR_keyctl 271
+#define __NR_waitid 272
-#define __NR_syscalls 272
+#define __NR_syscalls 273
#ifdef __KERNEL__
#define NR_syscalls __NR_syscalls
#endif
@@ -472,7 +473,7 @@ long sys_rt_sigaction(int sig, const struct sigaction __user *act,
* What we want is __attribute__((weak,alias("sys_ni_syscall"))),
* but it doesn't work on all toolchains, so we just do it by hand
*/
-#define cond_syscall(x) asm(".weak\t." #x "\n\t.set\t." #x ",.sys_ni_syscall");
+#define cond_syscall(x) asm(".weak\t." #x "\n\t.set\t." #x ",.sys_ni_syscall")
#endif /* __KERNEL__ */
diff --git a/include/asm-ppc64/vdso.h b/include/asm-ppc64/vdso.h
new file mode 100644
index 0000000000000..b74e16c0cf010
--- /dev/null
+++ b/include/asm-ppc64/vdso.h
@@ -0,0 +1,83 @@
+#ifndef __PPC64_VDSO_H__
+#define __PPC64_VDSO_H__
+
+#ifdef __KERNEL__
+
+/* Default link addresses for the vDSOs */
+#define VDSO32_LBASE 0
+#define VDSO64_LBASE 0
+
+/* Default map addresses */
+#define VDSO32_MBASE 0x100000
+#define VDSO64_MBASE 0x100000
+
+#define VDSO_VERSION_STRING LINUX_2.6.12
+
+/* Define if 64 bits VDSO has procedure descriptors */
+#undef VDS64_HAS_DESCRIPTORS
+
+#ifndef __ASSEMBLY__
+
+extern unsigned int vdso64_pages;
+extern unsigned int vdso32_pages;
+
+/* Offsets relative to thread->vdso_base */
+extern unsigned long vdso64_rt_sigtramp;
+extern unsigned long vdso32_sigtramp;
+extern unsigned long vdso32_rt_sigtramp;
+
+extern void vdso_init(void);
+
+#else /* __ASSEMBLY__ */
+
+#ifdef __VDSO64__
+#ifdef VDS64_HAS_DESCRIPTORS
+#define V_FUNCTION_BEGIN(name) \
+ .globl name; \
+ .section ".opd","a"; \
+ .align 3; \
+ name: \
+ .quad .name,.TOC.@tocbase,0; \
+ .previous; \
+ .globl .name; \
+ .type .name,@function; \
+ .name: \
+
+#define V_FUNCTION_END(name) \
+ .size .name,.-.name;
+
+#define V_LOCAL_FUNC(name) (.name)
+
+#else /* VDS64_HAS_DESCRIPTORS */
+
+#define V_FUNCTION_BEGIN(name) \
+ .globl name; \
+ name: \
+
+#define V_FUNCTION_END(name) \
+ .size name,.-name;
+
+#define V_LOCAL_FUNC(name) (name)
+
+#endif /* VDS64_HAS_DESCRIPTORS */
+#endif /* __VDSO64__ */
+
+#ifdef __VDSO32__
+
+#define V_FUNCTION_BEGIN(name) \
+ .globl name; \
+ .type name,@function; \
+ name: \
+
+#define V_FUNCTION_END(name) \
+ .size name,.-name;
+
+#define V_LOCAL_FUNC(name) (name)
+
+#endif /* __VDSO32__ */
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __KERNEL__ */
+
+#endif /* __PPC64_VDSO_H__ */
diff --git a/include/asm-ppc64/vio.h b/include/asm-ppc64/vio.h
index 3fd465c9263d7..20cd98ee63378 100644
--- a/include/asm-ppc64/vio.h
+++ b/include/asm-ppc64/vio.h
@@ -57,32 +57,7 @@ int vio_get_irq(struct vio_dev *dev);
int vio_enable_interrupts(struct vio_dev *dev);
int vio_disable_interrupts(struct vio_dev *dev);
-dma_addr_t vio_map_single(struct vio_dev *dev, void *vaddr,
- size_t size, enum dma_data_direction direction);
-void vio_unmap_single(struct vio_dev *dev, dma_addr_t dma_handle,
- size_t size, enum dma_data_direction direction);
-int vio_map_sg(struct vio_dev *vdev, struct scatterlist *sglist,
- int nelems, enum dma_data_direction direction);
-void vio_unmap_sg(struct vio_dev *vdev, struct scatterlist *sglist,
- int nelems, enum dma_data_direction direction);
-void *vio_alloc_consistent(struct vio_dev *dev, size_t size,
- dma_addr_t *dma_handle);
-void vio_free_consistent(struct vio_dev *dev, size_t size, void *vaddr,
- dma_addr_t dma_handle);
-
-static inline int vio_dma_supported(struct vio_dev *hwdev, u64 mask)
-{
- return 1;
-}
-
-#define vio_map_page(dev, page, off, size, dir) \
- vio_map_single(dev, (page_address(page) + (off)), size, dir)
-#define vio_unmap_page(dev,addr,sz,dir) vio_unmap_single(dev,addr,sz,dir)
-
-static inline int vio_set_dma_mask(struct vio_dev *dev, u64 mask)
-{
- return -EIO;
-}
+extern struct dma_mapping_ops vio_dma_ops;
extern struct bus_type vio_bus_type;
diff --git a/include/asm-s390/atomic.h b/include/asm-s390/atomic.h
index 541b6da9d701b..d5a05cf471680 100644
--- a/include/asm-s390/atomic.h
+++ b/include/asm-s390/atomic.h
@@ -61,6 +61,10 @@ static __inline__ void atomic_sub(int i, atomic_t * v)
{
__CS_LOOP(v, i, "sr");
}
+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");
diff --git a/include/asm-s390/cacheflush.h b/include/asm-s390/cacheflush.h
index 3c613c8e62340..e399a8ba2ed76 100644
--- a/include/asm-s390/cacheflush.h
+++ b/include/asm-s390/cacheflush.h
@@ -8,7 +8,7 @@
#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)
-#define flush_cache_page(vma, vmaddr) do { } while (0)
+#define flush_cache_page(vma, vmaddr, pfn) do { } while (0)
#define flush_dcache_page(page) do { } while (0)
#define flush_dcache_mmap_lock(mapping) do { } while (0)
#define flush_dcache_mmap_unlock(mapping) do { } while (0)
diff --git a/include/asm-s390/ccwdev.h b/include/asm-s390/ccwdev.h
index fd73b5e03ce6a..3eb231af5d514 100644
--- a/include/asm-s390/ccwdev.h
+++ b/include/asm-s390/ccwdev.h
@@ -164,6 +164,8 @@ extern int ccw_device_clear(struct ccw_device *, unsigned long);
extern int read_dev_chars(struct ccw_device *cdev, void **buffer, int length);
extern int read_conf_data(struct ccw_device *cdev, void **buffer, int *length);
+extern int read_conf_data_lpm(struct ccw_device *cdev, void **buffer,
+ int *length, __u8 lpm);
extern int ccw_device_set_online(struct ccw_device *cdev);
extern int ccw_device_set_offline(struct ccw_device *cdev);
@@ -186,4 +188,5 @@ 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/cputime.h b/include/asm-s390/cputime.h
index 216d861337e6a..4b3ef7cad1158 100644
--- a/include/asm-s390/cputime.h
+++ b/include/asm-s390/cputime.h
@@ -9,6 +9,8 @@
#ifndef _S390_CPUTIME_H
#define _S390_CPUTIME_H
+#include <asm/div64.h>
+
/* We want to use micro-second resolution. */
typedef unsigned long long cputime_t;
@@ -40,6 +42,12 @@ __div(unsigned long long n, unsigned int base)
#define cputime_max ((~0UL >> 1) - 1)
#define cputime_add(__a, __b) ((__a) + (__b))
#define cputime_sub(__a, __b) ((__a) - (__b))
+#define cputime_div(__a, __n) ({ \
+ unsigned long long __div = (__a); \
+ do_div(__div,__n); \
+ __div; \
+})
+#define cputime_halve(__a) ((__a) >> 1)
#define cputime_eq(__a, __b) ((__a) == (__b))
#define cputime_gt(__a, __b) ((__a) > (__b))
#define cputime_ge(__a, __b) ((__a) >= (__b))
diff --git a/include/asm-s390/io.h b/include/asm-s390/io.h
index 60342a587a3c8..8188fdc9884f9 100644
--- a/include/asm-s390/io.h
+++ b/include/asm-s390/io.h
@@ -107,6 +107,17 @@ extern void iounmap(void *addr);
#define mmiowb()
+/*
+ * Convert a physical pointer to a virtual kernel pointer for /dev/mem
+ * access
+ */
+#define xlate_dev_mem_ptr(p) __va(p)
+
+/*
+ * Convert a virtual cached pointer to an uncached pointer
+ */
+#define xlate_dev_kmem_ptr(p) p
+
#endif /* __KERNEL__ */
#endif
diff --git a/include/asm-s390/ipc.h b/include/asm-s390/ipc.h
index d6c041e9ca9aa..a46e3d9c2a3fc 100644
--- a/include/asm-s390/ipc.h
+++ b/include/asm-s390/ipc.h
@@ -1,40 +1 @@
-/*
- * include/asm-s390/ipc.h
- *
- * S390 version
- *
- * Derived from "include/asm-i386/ipc.h"
- */
-
-#ifndef __s390_IPC_H__
-#define __s390_IPC_H__
-
-/*
- * These are used to wrap system calls on S390.
- *
- * See arch/s390/kernel/sys_s390.c for ugly details..
- */
-struct ipc_kludge {
- struct msgbuf __user *msgp;
- long msgtyp;
-};
-
-#define SEMOP 1
-#define SEMGET 2
-#define SEMCTL 3
-#define SEMTIMEDOP 4
-#define MSGSND 11
-#define MSGRCV 12
-#define MSGGET 13
-#define MSGCTL 14
-#define SHMAT 21
-#define SHMDT 22
-#define SHMGET 23
-#define SHMCTL 24
-
-/* Used by the DIPC package, try and avoid reusing it */
-#define DIPC 25
-
-#define IPCCALL(version,op) ((version)<<16 | (op))
-
-#endif
+#include <asm-generic/ipc.h>
diff --git a/include/asm-s390/pgalloc.h b/include/asm-s390/pgalloc.h
index 90308137c8e64..3417dd71ab432 100644
--- a/include/asm-s390/pgalloc.h
+++ b/include/asm-s390/pgalloc.h
@@ -14,7 +14,6 @@
#define _S390_PGALLOC_H
#include <linux/config.h>
-#include <asm/processor.h>
#include <linux/threads.h>
#include <linux/gfp.h>
#include <linux/mm.h>
@@ -130,8 +129,10 @@ pte_alloc_one_kernel(struct mm_struct *mm, unsigned long vmaddr)
pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT);
if (pte != NULL) {
- for (i=0; i < PTRS_PER_PTE; i++)
- pte_clear(pte+i);
+ for (i=0; i < PTRS_PER_PTE; i++) {
+ pte_clear(mm, vmaddr, pte+i);
+ vmaddr += PAGE_SIZE;
+ }
}
return pte;
}
diff --git a/include/asm-s390/pgtable.h b/include/asm-s390/pgtable.h
index 85f043c6d5cff..1633cb75f0577 100644
--- a/include/asm-s390/pgtable.h
+++ b/include/asm-s390/pgtable.h
@@ -322,6 +322,7 @@ extern inline void set_pte(pte_t *pteptr, pte_t pteval)
{
*pteptr = pteval;
}
+#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
/*
* pgd/pmd/pte query functions
@@ -457,7 +458,7 @@ extern inline void pmd_clear(pmd_t * pmdp)
#endif /* __s390x__ */
-extern inline void pte_clear(pte_t *ptep)
+extern inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
{
pte_val(*ptep) = _PAGE_INVALID_EMPTY;
}
@@ -521,7 +522,7 @@ extern inline pte_t pte_mkyoung(pte_t pte)
return pte;
}
-static inline int ptep_test_and_clear_young(pte_t *ptep)
+static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
{
return 0;
}
@@ -531,10 +532,10 @@ ptep_clear_flush_young(struct vm_area_struct *vma,
unsigned long address, pte_t *ptep)
{
/* No need to flush TLB; bits are in storage key */
- return ptep_test_and_clear_young(ptep);
+ return ptep_test_and_clear_young(vma, address, ptep);
}
-static inline int ptep_test_and_clear_dirty(pte_t *ptep)
+static inline int ptep_test_and_clear_dirty(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
{
return 0;
}
@@ -544,13 +545,13 @@ ptep_clear_flush_dirty(struct vm_area_struct *vma,
unsigned long address, pte_t *ptep)
{
/* No need to flush TLB; bits are in storage key */
- return ptep_test_and_clear_dirty(ptep);
+ return ptep_test_and_clear_dirty(vma, address, ptep);
}
-static inline pte_t ptep_get_and_clear(pte_t *ptep)
+static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
{
pte_t pte = *ptep;
- pte_clear(ptep);
+ pte_clear(mm, addr, ptep);
return pte;
}
@@ -573,19 +574,14 @@ ptep_clear_flush(struct vm_area_struct *vma,
: "=m" (*ptep) : "m" (*ptep),
"a" (ptep), "a" (address) );
#endif /* __s390x__ */
- pte_clear(ptep);
+ pte_val(*ptep) = _PAGE_INVALID_EMPTY;
return pte;
}
-static inline void ptep_set_wrprotect(pte_t *ptep)
+static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
{
pte_t old_pte = *ptep;
- set_pte(ptep, pte_wrprotect(old_pte));
-}
-
-static inline void ptep_mkdirty(pte_t *ptep)
-{
- pte_mkdirty(*ptep);
+ set_pte_at(mm, addr, ptep, pte_wrprotect(old_pte));
}
static inline void
@@ -756,11 +752,17 @@ extern inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address)
* 0000000000111111111122222222223333333333444444444455 5555 5 55566 66
* 0123456789012345678901234567890123456789012345678901 2345 6 78901 23
*/
+#ifndef __s390x__
+#define __SWP_OFFSET_MASK (~0UL >> 12)
+#else
+#define __SWP_OFFSET_MASK (~0UL >> 11)
+#endif
extern inline pte_t mk_swap_pte(unsigned long type, unsigned long offset)
{
pte_t pte;
+ offset &= __SWP_OFFSET_MASK;
pte_val(pte) = _PAGE_INVALID_SWAP | ((type & 0x1f) << 2) |
- ((offset & 1) << 7) | ((offset & 0xffffe) << 11);
+ ((offset & 1UL) << 7) | ((offset & ~1UL) << 11);
return pte;
}
@@ -802,7 +804,6 @@ extern inline pte_t mk_swap_pte(unsigned long type, unsigned long offset)
#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
#define __HAVE_ARCH_PTEP_CLEAR_FLUSH
#define __HAVE_ARCH_PTEP_SET_WRPROTECT
-#define __HAVE_ARCH_PTEP_MKDIRTY
#define __HAVE_ARCH_PTE_SAME
#define __HAVE_ARCH_PAGE_TEST_AND_CLEAR_DIRTY
#define __HAVE_ARCH_PAGE_TEST_AND_CLEAR_YOUNG
diff --git a/include/asm-s390/posix_types.h b/include/asm-s390/posix_types.h
index a6ac95dc95765..61788de3c0c30 100644
--- a/include/asm-s390/posix_types.h
+++ b/include/asm-s390/posix_types.h
@@ -83,16 +83,16 @@ typedef struct {
#endif
#undef __FD_SET
-#define __FD_SET(fd,fdsetp) set_bit(fd,fdsetp->fds_bits)
+#define __FD_SET(fd,fdsetp) set_bit((fd),(fdsetp)->fds_bits)
#undef __FD_CLR
-#define __FD_CLR(fd,fdsetp) clear_bit(fd,fdsetp->fds_bits)
+#define __FD_CLR(fd,fdsetp) clear_bit((fd),(fdsetp)->fds_bits)
#undef __FD_ISSET
-#define __FD_ISSET(fd,fdsetp) test_bit(fd,fdsetp->fds_bits)
+#define __FD_ISSET(fd,fdsetp) test_bit((fd),(fdsetp)->fds_bits)
#undef __FD_ZERO
-#define __FD_ZERO(fdsetp) (memset (fdsetp, 0, sizeof(*(fd_set *)fdsetp)))
+#define __FD_ZERO(fdsetp) (memset ((fdsetp), 0, sizeof(*(fd_set *)(fdsetp))))
#endif /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)*/
diff --git a/include/asm-s390/smp.h b/include/asm-s390/smp.h
index e992bd6b59de9..9473786387a34 100644
--- a/include/asm-s390/smp.h
+++ b/include/asm-s390/smp.h
@@ -18,6 +18,7 @@
#if defined(__KERNEL__) && defined(CONFIG_SMP) && !defined(__ASSEMBLY__)
#include <asm/lowcore.h>
+#include <asm/sigp.h>
/*
s390 specific smp.c headers
@@ -59,6 +60,30 @@ extern __inline__ __u16 hard_smp_processor_id(void)
return cpu_address;
}
+/*
+ * returns 1 if cpu is in stopped/check stopped state or not operational
+ * returns 0 otherwise
+ */
+static inline int
+smp_cpu_not_running(int cpu)
+{
+ __u32 status;
+
+ switch (signal_processor_ps(&status, 0, cpu, sigp_sense)) {
+ case sigp_order_code_accepted:
+ case sigp_status_stored:
+ /* Check for stopped and check stop state */
+ if (status & 0x50)
+ return 1;
+ break;
+ case sigp_not_operational:
+ return 1;
+ default:
+ break;
+ }
+ return 0;
+}
+
#define cpu_logical_map(cpu) (cpu)
extern int __cpu_disable (void);
diff --git a/include/asm-s390/system.h b/include/asm-s390/system.h
index 8565a8aee7354..81514d76edcf3 100644
--- a/include/asm-s390/system.h
+++ b/include/asm-s390/system.h
@@ -335,19 +335,23 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
__asm__ __volatile__("lpswe 0(%0)" : : "a" (&psw), "m" (psw) : "cc" );
#define __ctl_load(array, low, high) ({ \
+ typedef struct { char _[sizeof(array)]; } addrtype; \
__asm__ __volatile__ ( \
" bras 1,0f\n" \
" lctlg 0,0,0(%0)\n" \
"0: ex %1,0(1)" \
- : : "a" (&array), "a" (((low)<<4)+(high)) : "1" ); \
+ : : "a" (&array), "a" (((low)<<4)+(high)), \
+ "m" (*(addrtype *)(array)) : "1" ); \
})
#define __ctl_store(array, low, high) ({ \
+ typedef struct { char _[sizeof(array)]; } addrtype; \
__asm__ __volatile__ ( \
" bras 1,0f\n" \
" stctg 0,0,0(%1)\n" \
"0: ex %2,0(1)" \
- : "=m" (array) : "a" (&array), "a" (((low)<<4)+(high)) : "1" ); \
+ : "=m" (*(addrtype *)(array)) \
+ : "a" (&array), "a" (((low)<<4)+(high)) : "1" ); \
})
#define __ctl_set_bit(cr, bit) ({ \
@@ -390,19 +394,23 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
__asm__ __volatile__("lpsw 0(%0)" : : "a" (&psw) : "cc" );
#define __ctl_load(array, low, high) ({ \
+ typedef struct { char _[sizeof(array)]; } addrtype; \
__asm__ __volatile__ ( \
" bras 1,0f\n" \
" lctl 0,0,0(%0)\n" \
"0: ex %1,0(1)" \
- : : "a" (&array), "a" (((low)<<4)+(high)) : "1" ); \
+ : : "a" (&array), "a" (((low)<<4)+(high)), \
+ "m" (*(addrtype *)(array)) : "1" ); \
})
#define __ctl_store(array, low, high) ({ \
+ typedef struct { char _[sizeof(array)]; } addrtype; \
__asm__ __volatile__ ( \
" bras 1,0f\n" \
" stctl 0,0,0(%1)\n" \
"0: ex %2,0(1)" \
- : "=m" (array) : "a" (&array), "a" (((low)<<4)+(high)): "1" ); \
+ : "=m" (*(addrtype *)(array)) \
+ : "a" (&array), "a" (((low)<<4)+(high)): "1" ); \
})
#define __ctl_set_bit(cr, bit) ({ \
@@ -461,6 +469,8 @@ extern void (*_machine_restart)(char *command);
extern void (*_machine_halt)(void);
extern void (*_machine_power_off)(void);
+#define arch_align_stack(x) (x)
+
#endif /* __KERNEL__ */
#endif
diff --git a/include/asm-s390/timex.h b/include/asm-s390/timex.h
index c878d6ac97ab8..4848057dafe49 100644
--- a/include/asm-s390/timex.h
+++ b/include/asm-s390/timex.h
@@ -15,8 +15,6 @@
typedef unsigned long long cycles_t;
-extern cycles_t cacheflush_time;
-
static inline cycles_t get_cycles(void)
{
cycles_t cycles;
diff --git a/include/asm-s390/uaccess.h b/include/asm-s390/uaccess.h
index 5eda2c334dc7b..a7f43a251f81b 100644
--- a/include/asm-s390/uaccess.h
+++ b/include/asm-s390/uaccess.h
@@ -65,7 +65,8 @@
#define access_ok(type,addr,size) __access_ok(addr,size)
-extern inline int verify_area(int type, const void __user *addr,
+/* this function will go away soon - use access_ok() instead */
+extern inline int __deprecated verify_area(int type, const void __user *addr,
unsigned long size)
{
return access_ok(type, addr, size) ? 0 : -EFAULT;
@@ -161,7 +162,7 @@ struct exception_table_entry
__put_user_asm(__x, ptr, __pu_err); \
break; \
default: \
- __pu_err = __put_user_bad(); \
+ __put_user_bad(); \
break; \
} \
__pu_err; \
@@ -182,7 +183,7 @@ struct exception_table_entry
})
-extern int __put_user_bad(void);
+extern int __put_user_bad(void) __attribute__((noreturn));
#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)
#define __get_user_asm(x, ptr, err) \
@@ -225,8 +226,7 @@ extern int __put_user_bad(void);
__get_user_asm(__x, ptr, __gu_err); \
break; \
default: \
- __x = 0; \
- __gu_err = __get_user_bad(); \
+ __get_user_bad(); \
break; \
} \
(x) = __x; \
@@ -248,7 +248,7 @@ extern int __put_user_bad(void);
__get_user(x, ptr); \
})
-extern int __get_user_bad(void);
+extern int __get_user_bad(void) __attribute__((noreturn));
#define __put_user_unaligned __put_user
#define __get_user_unaligned __get_user
diff --git a/include/asm-s390/unistd.h b/include/asm-s390/unistd.h
index ad3063446a644..f1a204f7c0f0b 100644
--- a/include/asm-s390/unistd.h
+++ b/include/asm-s390/unistd.h
@@ -259,7 +259,7 @@
#define __NR_fadvise64_64 264
#define __NR_statfs64 265
#define __NR_fstatfs64 266
-/* Number 267 is reserved for new sys_remap_file_pages */
+#define __NR_remap_file_pages 267
/* Number 268 is reserved for new sys_mbind */
/* Number 269 is reserved for new sys_get_mempolicy */
/* Number 270 is reserved for new sys_set_mempolicy */
@@ -270,8 +270,12 @@
#define __NR_mq_notify 275
#define __NR_mq_getsetattr 276
/* Number 277 is reserved for new sys_kexec_load */
+#define __NR_add_key 278
+#define __NR_request_key 279
+#define __NR_keyctl 280
+#define __NR_waitid 281
-#define NR_syscalls 278
+#define NR_syscalls 282
/*
* There are some system calls that are not present on 64 bit, some
@@ -330,7 +334,6 @@
#undef __NR_setgid32
#undef __NR_setfsuid32
#undef __NR_setfsgid32
-#undef __NR_getdents64
#undef __NR_fcntl64
#undef __NR_sendfile64
#undef __NR_fadvise64_64
@@ -597,6 +600,6 @@ asmlinkage long sys_rt_sigaction(int sig,
* What we want is __attribute__((weak,alias("sys_ni_syscall"))),
* but it doesn't work on all toolchains, so we just do it by hand
*/
-#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
+#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
#endif /* _ASM_S390_UNISTD_H_ */
diff --git a/include/asm-sh/bitops.h b/include/asm-sh/bitops.h
index 18055347bce8a..5163d1ff2f1bd 100644
--- a/include/asm-sh/bitops.h
+++ b/include/asm-sh/bitops.h
@@ -262,9 +262,9 @@ found_middle:
#define find_first_bit(addr, size) \
find_next_bit((addr), (size), 0)
-static __inline__ int find_next_zero_bit(void *addr, int size, int offset)
+static __inline__ int find_next_zero_bit(const unsigned long *addr, int size, int offset)
{
- unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
+ const unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
unsigned long result = offset & ~31UL;
unsigned long tmp;
@@ -325,7 +325,7 @@ found_middle:
* bits is cleared.
*/
-static inline int sched_find_first_bit(unsigned long *b)
+static inline int sched_find_first_bit(const unsigned long *b)
{
if (unlikely(b[0]))
return __ffs(b[0]);
diff --git a/include/asm-sh/bug.h b/include/asm-sh/bug.h
index ea41e17bb9593..70172217140f4 100644
--- a/include/asm-sh/bug.h
+++ b/include/asm-sh/bug.h
@@ -8,7 +8,7 @@
*/
#define BUG() do { \
printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \
- asm volatile("nop"); \
+ *(volatile int *)0 = 0; \
} while (0)
#define HAVE_ARCH_BUG
diff --git a/include/asm-sh/cacheflush.h b/include/asm-sh/cacheflush.h
index beb860ae79cca..9dfb33edb0081 100644
--- a/include/asm-sh/cacheflush.h
+++ b/include/asm-sh/cacheflush.h
@@ -1,5 +1,6 @@
#ifndef __ASM_SH_CACHEFLUSH_H
#define __ASM_SH_CACHEFLUSH_H
+#ifdef __KERNEL__
#include <asm/cpu/cacheflush.h>
@@ -15,15 +16,16 @@ extern void __flush_invalidate_region(void *start, int size);
#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
do { \
- flush_cache_page(vma, vaddr); \
+ flush_cache_page(vma, vaddr, page_to_pfn(page));\
memcpy(dst, src, len); \
flush_icache_user_range(vma, page, vaddr, len); \
} while (0)
#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
do { \
- flush_cache_page(vma, vaddr); \
+ flush_cache_page(vma, vaddr, page_to_pfn(page));\
memcpy(dst, src, len); \
} while (0)
+#endif /* __KERNEL__ */
#endif /* __ASM_SH_CACHEFLUSH_H */
diff --git a/include/asm-sh/cpu-sh2/cacheflush.h b/include/asm-sh/cpu-sh2/cacheflush.h
index 98cb67f374812..f556fa80ea975 100644
--- a/include/asm-sh/cpu-sh2/cacheflush.h
+++ b/include/asm-sh/cpu-sh2/cacheflush.h
@@ -15,7 +15,7 @@
*
* - flush_cache_all() flushes entire cache
* - flush_cache_mm(mm) flushes the specified mm context's cache lines
- * - flush_cache_page(mm, vmaddr) flushes a single page
+ * - flush_cache_page(mm, vmaddr, pfn) flushes a single page
* - flush_cache_range(vma, start, end) flushes a range of pages
*
* - flush_dcache_page(pg) flushes(wback&invalidates) a page for dcache
@@ -28,7 +28,7 @@
#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)
-#define flush_cache_page(vma, vmaddr) do { } while (0)
+#define flush_cache_page(vma, vmaddr, pfn) do { } while (0)
#define flush_dcache_page(page) do { } while (0)
#define flush_dcache_mmap_lock(mapping) do { } while (0)
#define flush_dcache_mmap_unlock(mapping) do { } while (0)
diff --git a/include/asm-sh/cpu-sh3/cacheflush.h b/include/asm-sh/cpu-sh3/cacheflush.h
index ff4cc74258274..f51aed00c68f7 100644
--- a/include/asm-sh/cpu-sh3/cacheflush.h
+++ b/include/asm-sh/cpu-sh3/cacheflush.h
@@ -15,7 +15,7 @@
*
* - flush_cache_all() flushes entire cache
* - flush_cache_mm(mm) flushes the specified mm context's cache lines
- * - flush_cache_page(mm, vmaddr) flushes a single page
+ * - flush_cache_page(mm, vmaddr, pfn) flushes a single page
* - flush_cache_range(vma, start, end) flushes a range of pages
*
* - flush_dcache_page(pg) flushes(wback&invalidates) a page for dcache
@@ -43,7 +43,7 @@ extern void flush_cache_all(void);
extern void flush_cache_mm(struct mm_struct *mm);
extern void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
unsigned long end);
-extern void flush_cache_page(struct vm_area_struct *vma, unsigned long addr);
+extern void flush_cache_page(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn);
extern void flush_dcache_page(struct page *pg);
extern void flush_icache_range(unsigned long start, unsigned long end);
extern void flush_icache_page(struct vm_area_struct *vma, struct page *page);
@@ -68,7 +68,7 @@ extern void flush_icache_page(struct vm_area_struct *vma, struct page *page);
#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)
-#define flush_cache_page(vma, vmaddr) do { } while (0)
+#define flush_cache_page(vma, vmaddr, pfn) do { } while (0)
#define flush_dcache_page(page) do { } while (0)
#define flush_dcache_mmap_lock(mapping) do { } while (0)
#define flush_dcache_mmap_unlock(mapping) do { } while (0)
diff --git a/include/asm-sh/cpu-sh3/freq.h b/include/asm-sh/cpu-sh3/freq.h
index ffe798e960cf5..b61b6e331df0e 100644
--- a/include/asm-sh/cpu-sh3/freq.h
+++ b/include/asm-sh/cpu-sh3/freq.h
@@ -10,7 +10,11 @@
#ifndef __ASM_CPU_SH3_FREQ_H
#define __ASM_CPU_SH3_FREQ_H
+#if defined(CONFIG_CPU_SUBTYPE_SH7300)
+#define FRQCR 0xa415ff80
+#else
#define FRQCR 0xffffff80
+#endif
#define MIN_DIVISOR_NR 0
#define MAX_DIVISOR_NR 4
diff --git a/include/asm-sh/cpu-sh3/timer.h b/include/asm-sh/cpu-sh3/timer.h
new file mode 100644
index 0000000000000..3d8e95e8d10cc
--- /dev/null
+++ b/include/asm-sh/cpu-sh3/timer.h
@@ -0,0 +1,64 @@
+/*
+ * include/asm-sh/cpu-sh3/timer.h
+ *
+ * Copyright (C) 2004 Lineo Solutions, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#ifndef __ASM_CPU_SH3_TIMER_H
+#define __ASM_CPU_SH3_TIMER_H
+
+/*
+ * ---------------------------------------------------------------------------
+ * TMU Common definitions for SH3 processors
+ * SH7706
+ * SH7709S
+ * SH7727
+ * SH7729R
+ * SH7710
+ * SH7720
+ * SH7300
+ * ---------------------------------------------------------------------------
+ */
+
+#if defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7710)
+#define TMU_TSTR 0xa412fe92 /* Byte access */
+
+#define TMU0_TCOR 0xa412fe94 /* Long access */
+#define TMU0_TCNT 0xa412fe98 /* Long access */
+#define TMU0_TCR 0xa412fe9c /* Word access */
+
+#define TMU1_TCOR 0xa412fea0 /* Long access */
+#define TMU1_TCNT 0xa412fea4 /* Long access */
+#define TMU1_TCR 0xa412fea8 /* Word access */
+
+#define TMU2_TCOR 0xa412feac /* Long access */
+#define TMU2_TCNT 0xa412feb0 /* Long access */
+#define TMU2_TCR 0xa412feb4 /* Word access */
+
+#else
+#if !defined(CONFIG_CPU_SUBTYPE_SH7727)
+#define TMU_TOCR 0xfffffe90 /* Byte access */
+#endif
+#define TMU_TSTR 0xfffffe92 /* Byte access */
+
+#define TMU0_TCOR 0xfffffe94 /* Long access */
+#define TMU0_TCNT 0xfffffe98 /* Long access */
+#define TMU0_TCR 0xfffffe9c /* Word access */
+
+#define TMU1_TCOR 0xfffffea0 /* Long access */
+#define TMU1_TCNT 0xfffffea4 /* Long access */
+#define TMU1_TCR 0xfffffea8 /* Word access */
+
+#define TMU2_TCOR 0xfffffeac /* Long access */
+#define TMU2_TCNT 0xfffffeb0 /* Long access */
+#define TMU2_TCR 0xfffffeb4 /* Word access */
+#if !defined(CONFIG_CPU_SUBTYPE_SH7727)
+#define TMU2_TCPR2 0xfffffeb8 /* Long access */
+#endif
+#endif
+
+#endif /* __ASM_CPU_SH3_TIMER_H */
+
diff --git a/include/asm-sh/cpu-sh4/cacheflush.h b/include/asm-sh/cpu-sh4/cacheflush.h
index 9910dfaed9430..f323567e085f4 100644
--- a/include/asm-sh/cpu-sh4/cacheflush.h
+++ b/include/asm-sh/cpu-sh4/cacheflush.h
@@ -28,7 +28,7 @@ extern void flush_cache_all(void);
extern void flush_cache_mm(struct mm_struct *mm);
extern void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
unsigned long end);
-extern void flush_cache_page(struct vm_area_struct *vma, unsigned long addr);
+extern void flush_cache_page(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn);
extern void flush_dcache_page(struct page *pg);
#define flush_dcache_mmap_lock(mapping) do { } while (0)
diff --git a/include/asm-sh/cpu-sh4/timer.h b/include/asm-sh/cpu-sh4/timer.h
new file mode 100644
index 0000000000000..8a4af126c890f
--- /dev/null
+++ b/include/asm-sh/cpu-sh4/timer.h
@@ -0,0 +1,51 @@
+/*
+ * include/asm-sh/cpu-sh4/timer.h
+ *
+ * Copyright (C) 2004 Lineo Solutions, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#ifndef __ASM_CPU_SH4_TIMER_H
+#define __ASM_CPU_SH4_TIMER_H
+
+/*
+ * ---------------------------------------------------------------------------
+ * TMU Common definitions for SH4 processors
+ * SH7750S/SH7750R
+ * SH7751/SH7751R
+ * SH7760
+ * ---------------------------------------------------------------------------
+ */
+
+#if !defined(CONFIG_CPU_SUBTYPE_SH7760)
+#define TMU_TOCR 0xffd80000 /* Byte access */
+#endif
+#define TMU_TSTR 0xffd80004 /* Byte access */
+
+#define TMU0_TCOR 0xffd80008 /* Long access */
+#define TMU0_TCNT 0xffd8000c /* Long access */
+#define TMU0_TCR 0xffd80010 /* Word access */
+
+#define TMU1_TCOR 0xffd80014 /* Long access */
+#define TMU1_TCNT 0xffd80018 /* Long access */
+#define TMU1_TCR 0xffd8001c /* Word access */
+
+#define TMU2_TCOR 0xffd80020 /* Long access */
+#define TMU2_TCNT 0xffd80024 /* Long access */
+#define TMU2_TCR 0xffd80028 /* Word access */
+#define TMU2_TCPR 0xffd8002c /* Long access */
+
+#if !defined(CONFIG_CPU_SUBTYPE_SH7760)
+#define TMU3_TCOR 0xfe100008 /* Long access */
+#define TMU3_TCNT 0xfe10000c /* Long access */
+#define TMU3_TCR 0xfe100010 /* Word access */
+
+#define TMU4_TCOR 0xfe100014 /* Long access */
+#define TMU4_TCNT 0xfe100018 /* Long access */
+#define TMU4_TCR 0xfe10001c /* Word access */
+#endif
+
+#endif /* __ASM_CPU_SH4_TIMER_H */
+
diff --git a/include/asm-sh/dma-mapping.h b/include/asm-sh/dma-mapping.h
index db78317df116e..80d164c1529ef 100644
--- a/include/asm-sh/dma-mapping.h
+++ b/include/asm-sh/dma-mapping.h
@@ -3,7 +3,6 @@
#include <linux/config.h>
#include <linux/mm.h>
-#include <linux/device.h>
#include <asm/scatterlist.h>
#include <asm/io.h>
diff --git a/include/asm-sh/hardirq.h b/include/asm-sh/hardirq.h
index ee010848c3142..f2fdf0f760e59 100644
--- a/include/asm-sh/hardirq.h
+++ b/include/asm-sh/hardirq.h
@@ -12,15 +12,6 @@ typedef struct {
#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */
-#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
+extern void ack_bad_irq(unsigned int irq);
#endif /* __ASM_SH_HARDIRQ_H */
diff --git a/include/asm-sh/io.h b/include/asm-sh/io.h
index ab5f401c7e21b..6bc343fee7a02 100644
--- a/include/asm-sh/io.h
+++ b/include/asm-sh/io.h
@@ -295,6 +295,17 @@ out:
#define dma_cache_wback(_start,_size) \
__flush_wback_region(_start,_size)
+/*
+ * Convert a physical pointer to a virtual kernel pointer for /dev/mem
+ * access
+ */
+#define xlate_dev_mem_ptr(p) __va(p)
+
+/*
+ * Convert a virtual cached pointer to an uncached pointer
+ */
+#define xlate_dev_kmem_ptr(p) p
+
#endif /* __KERNEL__ */
#endif /* __ASM_SH_IO_H */
diff --git a/include/asm-sh/ipc.h b/include/asm-sh/ipc.h
index 6ced9bec6abcd..a46e3d9c2a3fc 100644
--- a/include/asm-sh/ipc.h
+++ b/include/asm-sh/ipc.h
@@ -1,32 +1 @@
-#ifndef __ASM_SH_IPC_H
-#define __ASM_SH_IPC_H
-
-/*
- * These are used to wrap system calls on x86.
- *
- * See arch/i386/kernel/sys_i386.c for ugly details..
- */
-struct ipc_kludge {
- struct msgbuf __user *msgp;
- long msgtyp;
-};
-
-#define SEMOP 1
-#define SEMGET 2
-#define SEMCTL 3
-#define SEMTIMEDOP 4
-#define MSGSND 11
-#define MSGRCV 12
-#define MSGGET 13
-#define MSGCTL 14
-#define SHMAT 21
-#define SHMDT 22
-#define SHMGET 23
-#define SHMCTL 24
-
-/* Used by the DIPC package, try and avoid reusing it */
-#define DIPC 25
-
-#define IPCCALL(version,op) ((version)<<16 | (op))
-
-#endif /* __ASM_SH_IPC_H */
+#include <asm-generic/ipc.h>
diff --git a/include/asm-sh/irq.h b/include/asm-sh/irq.h
index 87d148105183f..831e52ee45b59 100644
--- a/include/asm-sh/irq.h
+++ b/include/asm-sh/irq.h
@@ -17,7 +17,8 @@
#if defined(CONFIG_SH_HP600) || \
defined(CONFIG_SH_RTS7751R2D) || \
- defined(CONFIG_SH_HS7751RVOIP)
+ defined(CONFIG_SH_HS7751RVOIP) || \
+ defined(CONFIG_SH_SH03)
#include <asm/mach/ide.h>
#endif
diff --git a/include/asm-sh/mc146818rtc.h b/include/asm-sh/mc146818rtc.h
index 4ec4f7370ba81..1707cfb2915d0 100644
--- a/include/asm-sh/mc146818rtc.h
+++ b/include/asm-sh/mc146818rtc.h
@@ -16,6 +16,7 @@
/* FIXME:RTC Interrupt feature is not implemented yet. */
#undef RTC_IRQ
+#define RTC_IRQ 0
#if defined(CONFIG_CPU_SH3)
#define RTC_PORT(n) (R64CNT+(n)*2)
diff --git a/include/asm-sh/pgalloc.h b/include/asm-sh/pgalloc.h
index 1a998085f9619..f4f233f7a4f57 100644
--- a/include/asm-sh/pgalloc.h
+++ b/include/asm-sh/pgalloc.h
@@ -1,7 +1,6 @@
#ifndef __ASM_SH_PGALLOC_H
#define __ASM_SH_PGALLOC_H
-#include <asm/processor.h>
#include <linux/threads.h>
#include <linux/slab.h>
#include <linux/mm.h>
diff --git a/include/asm-sh/pgtable-2level.h b/include/asm-sh/pgtable-2level.h
index b7d4561d82441..b0528aa3cb1f6 100644
--- a/include/asm-sh/pgtable-2level.h
+++ b/include/asm-sh/pgtable-2level.h
@@ -41,6 +41,8 @@ static inline void pgd_clear (pgd_t * pgdp) { }
* hook is made available.
*/
#define set_pte(pteptr, pteval) (*(pteptr) = pteval)
+#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
+
/*
* (pmds are folded into pgds so this doesn't get actually called,
* but the define is needed for a generic inline function.)
diff --git a/include/asm-sh/pgtable.h b/include/asm-sh/pgtable.h
index 8853eb2485a5c..8a9689d5366f6 100644
--- a/include/asm-sh/pgtable.h
+++ b/include/asm-sh/pgtable.h
@@ -164,7 +164,7 @@ extern unsigned long empty_zero_page[1024];
#define pte_none(x) (!pte_val(x))
#define pte_present(x) (pte_val(x) & (_PAGE_PRESENT | _PAGE_PROTNONE))
-#define pte_clear(xp) do { set_pte(xp, __pte(0)); } while (0)
+#define pte_clear(mm,addr,xp) do { set_pte_at(mm, addr, xp, __pte(0)); } while (0)
#define pmd_none(x) (!pmd_val(x))
#define pmd_present(x) (pmd_val(x) & _PAGE_PRESENT)
@@ -279,6 +279,13 @@ typedef pte_t *pte_addr_t;
#define io_remap_page_range(vma, vaddr, paddr, size, prot) \
remap_pfn_range(vma, vaddr, (paddr) >> PAGE_SHIFT, size, prot)
+#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
+ remap_pfn_range(vma, vaddr, pfn, size, prot)
+
+#define MK_IOSPACE_PFN(space, pfn) (pfn)
+#define GET_IOSPACE(pfn) 0
+#define GET_PFN(pfn) (pfn)
+
/*
* No page table caches to initialise
*/
@@ -290,7 +297,7 @@ extern unsigned int kobjsize(const void *objp);
#if defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB)
#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
-extern pte_t ptep_get_and_clear(pte_t *ptep);
+extern pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep);
#endif
#include <asm-generic/pgtable.h>
diff --git a/include/asm-sh/sh03/ide.h b/include/asm-sh/sh03/ide.h
new file mode 100644
index 0000000000000..73ee92e5c79e2
--- /dev/null
+++ b/include/asm-sh/sh03/ide.h
@@ -0,0 +1,7 @@
+#ifndef __ASM_SH_SH03_IDE_H
+#define __ASM_SH_SH03_IDE_H
+
+#define IRQ_CFCARD 8
+#define IRQ_PCMCIA 8
+
+#endif /* __ASM_SH_SH03_IDE_H */
diff --git a/include/asm-sh/system.h b/include/asm-sh/system.h
index 5e67caf8885e2..28a3c2d8bcd7c 100644
--- a/include/asm-sh/system.h
+++ b/include/asm-sh/system.h
@@ -259,4 +259,6 @@ static __inline__ unsigned long __xchg(unsigned long x, volatile void * ptr, int
void disable_hlt(void);
void enable_hlt(void);
+#define arch_align_stack(x) (x)
+
#endif
diff --git a/include/asm-sh/timex.h b/include/asm-sh/timex.h
index bd2f43571fca1..a873e24113cf7 100644
--- a/include/asm-sh/timex.h
+++ b/include/asm-sh/timex.h
@@ -10,8 +10,6 @@
typedef unsigned long long cycles_t;
-extern cycles_t cacheflush_time;
-
static __inline__ cycles_t get_cycles (void)
{
return 0;
diff --git a/include/asm-sh/uaccess.h b/include/asm-sh/uaccess.h
index df9a9b28eff9a..fb9e334afa2be 100644
--- a/include/asm-sh/uaccess.h
+++ b/include/asm-sh/uaccess.h
@@ -146,7 +146,8 @@ static inline int access_ok(int type, const void __user *p, unsigned long size)
return __access_ok(addr, size);
}
-static inline int verify_area(int type, const void __user * addr, unsigned long size)
+/* this function will go away soon - use access_ok() instead */
+static inline int __deprecated verify_area(int type, const void __user * addr, unsigned long size)
{
return access_ok(type,addr,size) ? 0 : -EFAULT;
}
diff --git a/include/asm-sh/unaligned.h b/include/asm-sh/unaligned.h
index 70f94b93989c2..5250e3063b42d 100644
--- a/include/asm-sh/unaligned.h
+++ b/include/asm-sh/unaligned.h
@@ -2,18 +2,6 @@
#define __ASM_SH_UNALIGNED_H
/* SH can't handle unaligned accesses. */
-
-#include <linux/string.h>
-
-
-/* Use memmove here, so gcc does not insert a __builtin_memcpy. */
-
-#define get_unaligned(ptr) \
- ({ __typeof__(*(ptr)) __tmp; memmove(&__tmp, (ptr), sizeof(*(ptr))); __tmp; })
-
-#define put_unaligned(val, ptr) \
- ({ __typeof__(*(ptr)) __tmp = (val); \
- memmove((ptr), &__tmp, sizeof(*(ptr))); \
- (void)0; })
+#include <asm-generic/unaligned.h>
#endif /* __ASM_SH_UNALIGNED_H */
diff --git a/include/asm-sh/unistd.h b/include/asm-sh/unistd.h
index 778add873eab4..245447081f0d4 100644
--- a/include/asm-sh/unistd.h
+++ b/include/asm-sh/unistd.h
@@ -517,7 +517,7 @@ asmlinkage long sys_rt_sigaction(int sig,
* but it doesn't work on all toolchains, so we just do it by hand
*/
#ifndef cond_syscall
-#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
+#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
#endif
#endif /* __ASM_SH_UNISTD_H */
diff --git a/include/asm-sh64/bug.h b/include/asm-sh64/bug.h
index 9a81b7232f14c..3acd54d595660 100644
--- a/include/asm-sh64/bug.h
+++ b/include/asm-sh64/bug.h
@@ -1,7 +1,32 @@
#ifndef __ASM_SH64_BUG_H
#define __ASM_SH64_BUG_H
-#include <asm-sh/bug.h>
+#include <linux/config.h>
+
+/*
+ * Tell the user there is some problem, then force a segfault (in process
+ * context) or a panic (interrupt context).
+ */
+#define BUG() do { \
+ printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \
+ *(volatile int *)0 = 0; \
+} while (0)
+
+#define BUG_ON(condition) do { \
+ if (unlikely((condition)!=0)) \
+ BUG(); \
+} while(0)
+
+#define PAGE_BUG(page) do { \
+ BUG(); \
+} while (0)
+
+#define WARN_ON(condition) do { \
+ if (unlikely((condition)!=0)) { \
+ printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
+ dump_stack(); \
+ } \
+} while (0)
#endif /* __ASM_SH64_BUG_H */
diff --git a/include/asm-sh64/cacheflush.h b/include/asm-sh64/cacheflush.h
index 877c12fcd0670..55f71aa0aa6b8 100644
--- a/include/asm-sh64/cacheflush.h
+++ b/include/asm-sh64/cacheflush.h
@@ -14,7 +14,7 @@ extern void flush_cache_mm(struct mm_struct *mm);
extern void flush_cache_sigtramp(unsigned long start, unsigned long end);
extern void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
unsigned long end);
-extern void flush_cache_page(struct vm_area_struct *vma, unsigned long addr);
+extern void flush_cache_page(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn);
extern void flush_dcache_page(struct page *pg);
extern void flush_icache_range(unsigned long start, unsigned long end);
extern void flush_icache_user_range(struct vm_area_struct *vma,
@@ -31,14 +31,14 @@ extern void flush_icache_user_range(struct vm_area_struct *vma,
#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
do { \
- flush_cache_page(vma, vaddr); \
+ flush_cache_page(vma, vaddr, page_to_pfn(page));\
memcpy(dst, src, len); \
flush_icache_user_range(vma, page, vaddr, len); \
} while (0)
#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
do { \
- flush_cache_page(vma, vaddr); \
+ flush_cache_page(vma, vaddr, page_to_pfn(page));\
memcpy(dst, src, len); \
} while (0)
diff --git a/include/asm-sh64/elf.h b/include/asm-sh64/elf.h
index bc483669d2f3b..f994286e19985 100644
--- a/include/asm-sh64/elf.h
+++ b/include/asm-sh64/elf.h
@@ -53,6 +53,12 @@ typedef struct user_fpu_struct elf_fpregset_t;
#define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3)
+#define R_SH_DIR32 1
+#define R_SH_REL32 2
+#define R_SH_IMM_LOW16 246
+#define R_SH_IMM_LOW16_PCREL 247
+#define R_SH_IMM_MEDLOW16 248
+#define R_SH_IMM_MEDLOW16_PCREL 249
#define ELF_CORE_COPY_REGS(_dest,_regs) \
memcpy((char *) &_dest, (char *) _regs, \
diff --git a/include/asm-sh64/hardirq.h b/include/asm-sh64/hardirq.h
index 75bb083e65f57..ad2330e41fd5d 100644
--- a/include/asm-sh64/hardirq.h
+++ b/include/asm-sh64/hardirq.h
@@ -1,7 +1,19 @@
#ifndef __ASM_SH64_HARDIRQ_H
#define __ASM_SH64_HARDIRQ_H
-#include <asm-sh/hardirq.h>
+#include <linux/config.h>
+#include <linux/threads.h>
+#include <linux/irq.h>
+
+/* entry.S is sensitive to the offsets of these fields */
+typedef struct {
+ unsigned int __softirq_pending;
+} ____cacheline_aligned irq_cpustat_t;
+
+#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */
+
+/* arch/sh64/kernel/irq.c */
+extern void ack_bad_irq(unsigned int irq);
#endif /* __ASM_SH64_HARDIRQ_H */
diff --git a/include/asm-sh64/hardware.h b/include/asm-sh64/hardware.h
index a2e6112621d1a..931c1ad808477 100644
--- a/include/asm-sh64/hardware.h
+++ b/include/asm-sh64/hardware.h
@@ -17,29 +17,6 @@
#define PHYS_PERIPHERAL_BLOCK 0x09000000
#define PHYS_DMAC_BLOCK 0x0e000000
#define PHYS_PCI_BLOCK 0x60000000
-
-#ifndef __ASSEMBLY__
-#include <linux/types.h>
-#include <asm/io.h>
-
-struct vcr_info {
- u8 perr_flags; /* P-port Error flags */
- u8 merr_flags; /* Module Error flags */
- u16 mod_vers; /* Module Version */
- u16 mod_id; /* Module ID */
- u8 bot_mb; /* Bottom Memory block */
- u8 top_mb; /* Top Memory block */
-};
-
-static inline struct vcr_info sh64_get_vcr_info(unsigned long base)
-{
- unsigned long long tmp;
-
- tmp = sh64_in64(base);
-
- return *((struct vcr_info *)&tmp);
-}
-
-#endif /* __ASSEMBLY__ */
+#define PHYS_EMI_BLOCK 0xff000000
#endif /* __ASM_SH64_HARDWARE_H */
diff --git a/include/asm-sh64/ide.h b/include/asm-sh64/ide.h
index 900315ac40547..6fd514daa1ba3 100644
--- a/include/asm-sh64/ide.h
+++ b/include/asm-sh64/ide.h
@@ -21,7 +21,12 @@
#define MAX_HWIFS CONFIG_IDE_MAX_HWIFS
#endif
+/* Without this, the initialisation of PCI IDE cards end up calling
+ * ide_init_hwif_ports, which won't work. */
+#ifdef CONFIG_BLK_DEV_IDEPCI
+#define IDE_ARCH_OBSOLETE_INIT 1
#define ide_default_io_ctl(base) (0)
+#endif
#include <asm-generic/ide_iops.h>
diff --git a/include/asm-sh64/io.h b/include/asm-sh64/io.h
index 27032070c111f..cfafaa73b2b07 100644
--- a/include/asm-sh64/io.h
+++ b/include/asm-sh64/io.h
@@ -25,9 +25,11 @@
* onchip_remap();
*/
+#include <linux/compiler.h>
#include <asm/cache.h>
#include <asm/system.h>
#include <asm/page.h>
+#include <asm-generic/iomap.h>
#define virt_to_bus virt_to_phys
#define bus_to_virt phys_to_virt
@@ -39,75 +41,90 @@
* with an implicit size. The traditional read{b,w,l}/write{b,w,l}
* mess is wrapped to this, as are the SH-specific ctrl_in/out routines.
*/
-static inline unsigned char sh64_in8(unsigned long addr)
+static inline unsigned char sh64_in8(const volatile void __iomem *addr)
{
- return *(volatile unsigned char *)addr;
+ return *(volatile unsigned char __force *)addr;
}
-static inline unsigned short sh64_in16(unsigned long addr)
+static inline unsigned short sh64_in16(const volatile void __iomem *addr)
{
- return *(volatile unsigned short *)addr;
+ return *(volatile unsigned short __force *)addr;
}
-static inline unsigned long sh64_in32(unsigned long addr)
+static inline unsigned int sh64_in32(const volatile void __iomem *addr)
{
- return *(volatile unsigned long *)addr;
+ return *(volatile unsigned int __force *)addr;
}
-static inline unsigned long long sh64_in64(unsigned long addr)
+static inline unsigned long long sh64_in64(const volatile void __iomem *addr)
{
- return *(volatile unsigned long long *)addr;
+ return *(volatile unsigned long long __force *)addr;
}
-static inline void sh64_out8(unsigned char b, unsigned long addr)
+static inline void sh64_out8(unsigned char b, volatile void __iomem *addr)
{
- *(volatile unsigned char *)addr = b;
+ *(volatile unsigned char __force *)addr = b;
wmb();
}
-static inline void sh64_out16(unsigned short b, unsigned long addr)
+static inline void sh64_out16(unsigned short b, volatile void __iomem *addr)
{
- *(volatile unsigned short *)addr = b;
+ *(volatile unsigned short __force *)addr = b;
wmb();
}
-static inline void sh64_out32(unsigned long b, unsigned long addr)
+static inline void sh64_out32(unsigned int b, volatile void __iomem *addr)
{
- *(volatile unsigned long *)addr = b;
+ *(volatile unsigned int __force *)addr = b;
wmb();
}
-static inline void sh64_out64(unsigned long long b, unsigned long addr)
+static inline void sh64_out64(unsigned long long b, volatile void __iomem *addr)
{
- *(volatile unsigned long long *)addr = b;
+ *(volatile unsigned long long __force *)addr = b;
wmb();
}
#define readb(addr) sh64_in8(addr)
#define readw(addr) sh64_in16(addr)
#define readl(addr) sh64_in32(addr)
-#define readb_relaxed(addr) sh64_in8(addr)
-#define readw_relaxed(addr) sh64_in16(addr)
-#define readl_relaxed(addr) sh64_in32(addr)
+#define readb_relaxed(addr) sh64_in8(addr)
+#define readw_relaxed(addr) sh64_in16(addr)
+#define readl_relaxed(addr) sh64_in32(addr)
#define writeb(b, addr) sh64_out8(b, addr)
#define writew(b, addr) sh64_out16(b, addr)
#define writel(b, addr) sh64_out32(b, addr)
-#define ctrl_inb(addr) sh64_in8(addr)
-#define ctrl_inw(addr) sh64_in16(addr)
-#define ctrl_inl(addr) sh64_in32(addr)
+#define ctrl_inb(addr) sh64_in8(ioport_map(addr, 1))
+#define ctrl_inw(addr) sh64_in16(ioport_map(addr, 2))
+#define ctrl_inl(addr) sh64_in32(ioport_map(addr, 4))
-#define ctrl_outb(b, addr) sh64_out8(b, addr)
-#define ctrl_outw(b, addr) sh64_out16(b, addr)
-#define ctrl_outl(b, addr) sh64_out32(b, addr)
+#define ctrl_outb(b, addr) sh64_out8(b, ioport_map(addr, 1))
+#define ctrl_outw(b, addr) sh64_out16(b, ioport_map(addr, 2))
+#define ctrl_outl(b, addr) sh64_out32(b, ioport_map(addr, 4))
-unsigned long inb(unsigned long port);
-unsigned long inw(unsigned long port);
-unsigned long inl(unsigned long port);
-void outb(unsigned long value, unsigned long port);
-void outw(unsigned long value, unsigned long port);
-void outl(unsigned long value, unsigned long port);
+#define ioread8(addr) sh64_in8(addr)
+#define ioread16(addr) sh64_in16(addr)
+#define ioread32(addr) sh64_in32(addr)
+#define iowrite8(b, addr) sh64_out8(b, addr)
+#define iowrite16(b, addr) sh64_out16(b, addr)
+#define iowrite32(b, addr) sh64_out32(b, addr)
+
+#define inb(addr) ctrl_inb(addr)
+#define inw(addr) ctrl_inw(addr)
+#define inl(addr) ctrl_inl(addr)
+#define outb(b, addr) ctrl_outb(b, addr)
+#define outw(b, addr) ctrl_outw(b, addr)
+#define outl(b, addr) ctrl_outl(b, addr)
+
+void outsw(unsigned long port, const void *addr, unsigned long count);
+void insw(unsigned long port, void *addr, unsigned long count);
+void outsl(unsigned long port, const void *addr, unsigned long count);
+void insl(unsigned long port, void *addr, unsigned long count);
+
+void memcpy_toio(void __iomem *to, const void *from, long count);
+void memcpy_fromio(void *to, void __iomem *from, long count);
#define mmiowb()
@@ -154,7 +171,7 @@ extern void iounmap(void *addr);
unsigned long onchip_remap(unsigned long addr, unsigned long size, const char* name);
extern void onchip_unmap(unsigned long vaddr);
-static __inline__ int check_signature(unsigned long io_addr,
+static __inline__ int check_signature(volatile void __iomem *io_addr,
const unsigned char *signature, int length)
{
int retval = 0;
@@ -218,5 +235,16 @@ static __inline__ void dma_cache_wback (unsigned long start, unsigned long size)
asm volatile ("ocbwb %0, 0" : : "r" (s));
}
+/*
+ * Convert a physical pointer to a virtual kernel pointer for /dev/mem
+ * access
+ */
+#define xlate_dev_mem_ptr(p) __va(p)
+
+/*
+ * Convert a virtual cached pointer to an uncached pointer
+ */
+#define xlate_dev_kmem_ptr(p) p
+
#endif /* __KERNEL__ */
#endif /* __ASM_SH64_IO_H */
diff --git a/include/asm-sh64/ioctls.h b/include/asm-sh64/ioctls.h
index e5d55629f206a..08f3c1f2e4190 100644
--- a/include/asm-sh64/ioctls.h
+++ b/include/asm-sh64/ioctls.h
@@ -9,103 +9,108 @@
* include/asm-sh64/ioctls.h
*
* Copyright (C) 2000, 2001 Paolo Alberelli
+ * Copyright (C) 2004 Richard Curnow
*
*/
#include <asm/ioctl.h>
-#define FIOCLEX _IO('f', 1)
-#define FIONCLEX _IO('f', 2)
-#define FIOASYNC _IOW('f', 125, int)
-#define FIONBIO _IOW('f', 126, int)
-#define FIONREAD _IOR('f', 127, int)
+#define FIOCLEX 0x6601 /* _IO('f', 1) */
+#define FIONCLEX 0x6602 /* _IO('f', 2) */
+#define FIOASYNC 0x4004667d /* _IOW('f', 125, int) */
+#define FIONBIO 0x4004667e /* _IOW('f', 126, int) */
+#define FIONREAD 0x8004667f /* _IOW('f', 127, int) */
#define TIOCINQ FIONREAD
-#define FIOQSIZE _IOR('f', 128, loff_t)
+#define FIOQSIZE 0x80086680 /* _IOR('f', 128, loff_t) */
#define TCGETS 0x5401
#define TCSETS 0x5402
#define TCSETSW 0x5403
#define TCSETSF 0x5404
-#define TCGETA _IOR('t', 23, struct termio)
-#define TCSETA _IOW('t', 24, struct termio)
-#define TCSETAW _IOW('t', 25, struct termio)
-#define TCSETAF _IOW('t', 28, struct termio)
-
-#define TCSBRK _IO('t', 29)
-#define TCXONC _IO('t', 30)
-#define TCFLSH _IO('t', 31)
-
-#define TIOCSWINSZ _IOW('t', 103, struct winsize)
-#define TIOCGWINSZ _IOR('t', 104, struct winsize)
-#define TIOCSTART _IO('t', 110) /* start output, like ^Q */
-#define TIOCSTOP _IO('t', 111) /* stop output, like ^S */
-#define TIOCOUTQ _IOR('t', 115, int) /* output queue size */
-
-#define TIOCSPGRP _IOW('t', 118, int)
-#define TIOCGPGRP _IOR('t', 119, int)
-
-#define TIOCEXCL _IO('T', 12) /* 0x540C */
-#define TIOCNXCL _IO('T', 13) /* 0x540D */
-#define TIOCSCTTY _IO('T', 14) /* 0x540E */
-
-#define TIOCSTI _IOW('T', 18, char) /* 0x5412 */
-#define TIOCMGET _IOR('T', 21, unsigned int) /* 0x5415 */
-#define TIOCMBIS _IOW('T', 22, unsigned int) /* 0x5416 */
-#define TIOCMBIC _IOW('T', 23, unsigned int) /* 0x5417 */
-#define TIOCMSET _IOW('T', 24, unsigned int) /* 0x5418 */
-# define TIOCM_LE 0x001
-# define TIOCM_DTR 0x002
-# define TIOCM_RTS 0x004
-# define TIOCM_ST 0x008
-# define TIOCM_SR 0x010
-# define TIOCM_CTS 0x020
-# define TIOCM_CAR 0x040
-# define TIOCM_RNG 0x080
-# define TIOCM_DSR 0x100
-# define TIOCM_CD TIOCM_CAR
-# define TIOCM_RI TIOCM_RNG
-
-#define TIOCGSOFTCAR _IOR('T', 25, unsigned int) /* 0x5419 */
-#define TIOCSSOFTCAR _IOW('T', 26, unsigned int) /* 0x541A */
-#define TIOCLINUX _IOW('T', 28, char) /* 0x541C */
-#define TIOCCONS _IO('T', 29) /* 0x541D */
-#define TIOCGSERIAL _IOR('T', 30, struct serial_struct) /* 0x541E */
-#define TIOCSSERIAL _IOW('T', 31, struct serial_struct) /* 0x541F */
-#define TIOCPKT _IOW('T', 32, int) /* 0x5420 */
-# define TIOCPKT_DATA 0
-# define TIOCPKT_FLUSHREAD 1
-# define TIOCPKT_FLUSHWRITE 2
-# define TIOCPKT_STOP 4
-# define TIOCPKT_START 8
-# define TIOCPKT_NOSTOP 16
-# define TIOCPKT_DOSTOP 32
-
-
-#define TIOCNOTTY _IO('T', 34) /* 0x5422 */
-#define TIOCSETD _IOW('T', 35, int) /* 0x5423 */
-#define TIOCGETD _IOR('T', 36, int) /* 0x5424 */
-#define TCSBRKP _IOW('T', 37, int) /* 0x5425 */ /* Needed for POSIX tcsendbreak() */
-#define TIOCTTYGSTRUCT _IOR('T', 38, struct tty_struct) /* 0x5426 */ /* For debugging only */
-#define TIOCSBRK _IO('T', 39) /* 0x5427 */ /* BSD compatibility */
-#define TIOCCBRK _IO('T', 40) /* 0x5428 */ /* BSD compatibility */
-#define TIOCGSID _IOR('T', 41, pid_t) /* 0x5429 */ /* Return the session ID of FD */
-#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
-#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
-
-#define TIOCSERCONFIG _IO('T', 83) /* 0x5453 */
-#define TIOCSERGWILD _IOR('T', 84, int) /* 0x5454 */
-#define TIOCSERSWILD _IOW('T', 85, int) /* 0x5455 */
+#define TCGETA 0x80127417 /* _IOR('t', 23, struct termio) */
+#define TCSETA 0x40127418 /* _IOW('t', 24, struct termio) */
+#define TCSETAW 0x40127419 /* _IOW('t', 25, struct termio) */
+#define TCSETAF 0x4012741c /* _IOW('t', 28, struct termio) */
+
+#define TCSBRK 0x741d /* _IO('t', 29) */
+#define TCXONC 0x741e /* _IO('t', 30) */
+#define TCFLSH 0x741f /* _IO('t', 31) */
+
+#define TIOCSWINSZ 0x40087467 /* _IOW('t', 103, struct winsize) */
+#define TIOCGWINSZ 0x80087468 /* _IOR('t', 104, struct winsize) */
+#define TIOCSTART 0x746e /* _IO('t', 110) start output, like ^Q */
+#define TIOCSTOP 0x746f /* _IO('t', 111) stop output, like ^S */
+#define TIOCOUTQ 0x80047473 /* _IOR('t', 115, int) output queue size */
+
+#define TIOCSPGRP 0x40047476 /* _IOW('t', 118, int) */
+#define TIOCGPGRP 0x80047477 /* _IOR('t', 119, int) */
+
+#define TIOCEXCL 0x540c /* _IO('T', 12) */
+#define TIOCNXCL 0x540d /* _IO('T', 13) */
+#define TIOCSCTTY 0x540e /* _IO('T', 14) */
+
+#define TIOCSTI 0x40015412 /* _IOW('T', 18, char) 0x5412 */
+#define TIOCMGET 0x80045415 /* _IOR('T', 21, unsigned int) 0x5415 */
+#define TIOCMBIS 0x40045416 /* _IOW('T', 22, unsigned int) 0x5416 */
+#define TIOCMBIC 0x40045417 /* _IOW('T', 23, unsigned int) 0x5417 */
+#define TIOCMSET 0x40045418 /* _IOW('T', 24, unsigned int) 0x5418 */
+
+#define TIOCM_LE 0x001
+#define TIOCM_DTR 0x002
+#define TIOCM_RTS 0x004
+#define TIOCM_ST 0x008
+#define TIOCM_SR 0x010
+#define TIOCM_CTS 0x020
+#define TIOCM_CAR 0x040
+#define TIOCM_RNG 0x080
+#define TIOCM_DSR 0x100
+#define TIOCM_CD TIOCM_CAR
+#define TIOCM_RI TIOCM_RNG
+
+#define TIOCGSOFTCAR 0x80045419 /* _IOR('T', 25, unsigned int) 0x5419 */
+#define TIOCSSOFTCAR 0x4004541a /* _IOW('T', 26, unsigned int) 0x541A */
+#define TIOCLINUX 0x4004541c /* _IOW('T', 28, char) 0x541C */
+#define TIOCCONS 0x541d /* _IO('T', 29) */
+#define TIOCGSERIAL 0x803c541e /* _IOR('T', 30, struct serial_struct) 0x541E */
+#define TIOCSSERIAL 0x403c541f /* _IOW('T', 31, struct serial_struct) 0x541F */
+#define TIOCPKT 0x40045420 /* _IOW('T', 32, int) 0x5420 */
+
+#define TIOCPKT_DATA 0
+#define TIOCPKT_FLUSHREAD 1
+#define TIOCPKT_FLUSHWRITE 2
+#define TIOCPKT_STOP 4
+#define TIOCPKT_START 8
+#define TIOCPKT_NOSTOP 16
+#define TIOCPKT_DOSTOP 32
+
+
+#define TIOCNOTTY 0x5422 /* _IO('T', 34) */
+#define TIOCSETD 0x40045423 /* _IOW('T', 35, int) 0x5423 */
+#define TIOCGETD 0x80045424 /* _IOR('T', 36, int) 0x5424 */
+#define TCSBRKP 0x40045424 /* _IOW('T', 37, int) 0x5425 */ /* Needed for POSIX tcsendbreak() */
+#define TIOCTTYGSTRUCT 0x8c105426 /* _IOR('T', 38, struct tty_struct) 0x5426 */ /* For debugging only */
+#define TIOCSBRK 0x5427 /* _IO('T', 39) */ /* BSD compatibility */
+#define TIOCCBRK 0x5428 /* _IO('T', 40) */ /* BSD compatibility */
+#define TIOCGSID 0x80045429 /* _IOR('T', 41, pid_t) 0x5429 */ /* Return the session ID of FD */
+#define TIOCGPTN 0x80045430 /* _IOR('T',0x30, unsigned int) 0x5430 Get Pty Number (of pty-mux device) */
+#define TIOCSPTLCK 0x40045431 /* _IOW('T',0x31, int) Lock/unlock Pty */
+
+#define TIOCSERCONFIG 0x5453 /* _IO('T', 83) */
+#define TIOCSERGWILD 0x80045454 /* _IOR('T', 84, int) 0x5454 */
+#define TIOCSERSWILD 0x40045455 /* _IOW('T', 85, int) 0x5455 */
#define TIOCGLCKTRMIOS 0x5456
#define TIOCSLCKTRMIOS 0x5457
-#define TIOCSERGSTRUCT _IOR('T', 88, struct async_struct) /* 0x5458 */ /* For debugging only */
-#define TIOCSERGETLSR _IOR('T', 89, unsigned int) /* 0x5459 */ /* Get line status register */
- /* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
-# define TIOCSER_TEMT 0x01 /* Transmitter physically empty */
-#define TIOCSERGETMULTI _IOR('T', 90, struct serial_multiport_struct) /* 0x545A */ /* Get multiport config */
-#define TIOCSERSETMULTI _IOW('T', 91, struct serial_multiport_struct) /* 0x545B */ /* Set multiport config */
-
-#define TIOCMIWAIT _IO('T', 92) /* 0x545C */ /* wait for a change on serial input line(s) */
-#define TIOCGICOUNT _IOR('T', 93, struct async_icount) /* 0x545D */ /* read serial port inline interrupt counts */
+#define TIOCSERGSTRUCT 0x80d85458 /* _IOR('T', 88, struct async_struct) 0x5458 */ /* For debugging only */
+#define TIOCSERGETLSR 0x80045459 /* _IOR('T', 89, unsigned int) 0x5459 */ /* Get line status register */
+
+/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
+#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */
+
+#define TIOCSERGETMULTI 0x80a8545a /* _IOR('T', 90, struct serial_multiport_struct) 0x545A */ /* Get multiport config */
+#define TIOCSERSETMULTI 0x40a8545b /* _IOW('T', 91, struct serial_multiport_struct) 0x545B */ /* Set multiport config */
+
+#define TIOCMIWAIT 0x545c /* _IO('T', 92) wait for a change on serial input line(s) */
+#define TIOCGICOUNT 0x802c545d /* _IOR('T', 93, struct async_icount) 0x545D */ /* read serial port inline interrupt counts */
#endif /* __ASM_SH64_IOCTLS_H */
diff --git a/include/asm-sh64/ipc.h b/include/asm-sh64/ipc.h
index d8d9389bd3ce7..a46e3d9c2a3fc 100644
--- a/include/asm-sh64/ipc.h
+++ b/include/asm-sh64/ipc.h
@@ -1,6 +1 @@
-#ifndef __ASM_SH64_IPC_H
-#define __ASM_SH64_IPC_H
-
-#include <asm-sh/ipc.h>
-
-#endif /* __ASM_SH64_IPC_H */
+#include <asm-generic/ipc.h>
diff --git a/include/asm-sh64/irq.h b/include/asm-sh64/irq.h
index 95056a0181d0f..f815b43df845e 100644
--- a/include/asm-sh64/irq.h
+++ b/include/asm-sh64/irq.h
@@ -83,11 +83,12 @@
#define IRQ_P2INTC (START_EXT_IRQS + (3*8) + 2)
#define IRQ_P2INTD (START_EXT_IRQS + (3*8) + 3)
-#define START_EXT_IRQS 64
-
#define I8042_KBD_IRQ (START_EXT_IRQS + 2)
#define I8042_AUX_IRQ (START_EXT_IRQS + 6)
+#define IRQ_CFCARD (START_EXT_IRQS + 7)
+#define IRQ_PCMCIA (0)
+
#else
#define NR_EXT_IRQS 0
#endif
diff --git a/include/asm-sh64/module.h b/include/asm-sh64/module.h
index bf382bccf3e8f..c313650d3d932 100644
--- a/include/asm-sh64/module.h
+++ b/include/asm-sh64/module.h
@@ -4,6 +4,14 @@
* This file contains the SH architecture specific module code.
*/
+struct mod_arch_specific {
+ /* empty */
+};
+
+#define Elf_Shdr Elf32_Shdr
+#define Elf_Sym Elf32_Sym
+#define Elf_Ehdr Elf32_Ehdr
+
#define module_map(x) vmalloc(x)
#define module_unmap(x) vfree(x)
#define module_arch_init(x) (0)
diff --git a/include/asm-sh64/pgalloc.h b/include/asm-sh64/pgalloc.h
index b843ec2478b1e..b25f5df5535c0 100644
--- a/include/asm-sh64/pgalloc.h
+++ b/include/asm-sh64/pgalloc.h
@@ -14,7 +14,6 @@
*
*/
-#include <asm/processor.h>
#include <linux/threads.h>
#include <linux/mm.h>
diff --git a/include/asm-sh64/pgtable.h b/include/asm-sh64/pgtable.h
index 4b3f31ac62df3..45f70c0f4a5e6 100644
--- a/include/asm-sh64/pgtable.h
+++ b/include/asm-sh64/pgtable.h
@@ -136,6 +136,7 @@ static __inline__ void set_pte(pte_t *pteptr, pte_t pteval)
*/
*(xp) = (x & NPHYS_SIGN) ? (x | NPHYS_MASK) : x;
}
+#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
static __inline__ void pmd_set(pmd_t *pmdp,pte_t *ptep)
{
@@ -280,8 +281,6 @@ static inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address)
/* Mask which drops software flags */
#define _PAGE_FLAGS_HARDWARE_MASK 0xfffffffffffff3dbLL
-/* Flags default: 4KB, Read, Not write, Not execute, Not user */
-#define _PAGE_FLAGS_HARDWARE_DEFAULT 0x0000000000000040LL
/*
* HugeTLB support
@@ -383,7 +382,7 @@ extern void __handle_bad_pmd_kernel(pmd_t * pmd);
*/
#define _PTE_EMPTY 0x0
#define pte_present(x) (pte_val(x) & _PAGE_PRESENT)
-#define pte_clear(xp) (set_pte(xp, __pte(_PTE_EMPTY)))
+#define pte_clear(mm,addr,xp) (set_pte_at(mm, addr, xp, __pte(_PTE_EMPTY)))
#define pte_none(x) (pte_val(x) == _PTE_EMPTY)
/*
@@ -483,6 +482,14 @@ extern void update_mmu_cache(struct vm_area_struct * vma,
#define io_remap_page_range(vma, vaddr, paddr, size, prot) \
remap_pfn_range(vma, vaddr, (paddr) >> PAGE_SHIFT, size, prot)
+
+#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
+ remap_pfn_range(vma, vaddr, pfn, size, prot)
+
+#define MK_IOSPACE_PFN(space, pfn) (pfn)
+#define GET_IOSPACE(pfn) 0
+#define GET_PFN(pfn) (pfn)
+
#endif /* !__ASSEMBLY__ */
/*
diff --git a/include/asm-sh64/system.h b/include/asm-sh64/system.h
index 8b3a6f9e62fbc..42510e496eb52 100644
--- a/include/asm-sh64/system.h
+++ b/include/asm-sh64/system.h
@@ -15,7 +15,6 @@
*/
#include <linux/config.h>
-#include <linux/kernel.h>
#include <asm/registers.h>
#include <asm/processor.h>
@@ -191,4 +190,6 @@ extern void print_seg(char *file,int line);
#define PL() printk("@ <%s,%s:%d>\n",__FILE__,__FUNCTION__,__LINE__)
+#define arch_align_stack(x) (x)
+
#endif /* __ASM_SH64_SYSTEM_H */
diff --git a/include/asm-sh64/thread_info.h b/include/asm-sh64/thread_info.h
index 99e7c926f4bdd..e65f394da472a 100644
--- a/include/asm-sh64/thread_info.h
+++ b/include/asm-sh64/thread_info.h
@@ -61,13 +61,18 @@ static inline struct thread_info *current_thread_info(void)
}
/* thread information allocation */
-#define alloc_thread_info(ti) ((struct thread_info *) __get_free_pages(GFP_KERNEL,2))
+
+
+
+#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__ */
+#define THREAD_SIZE 8192
+
#define PREEMPT_ACTIVE 0x4000000
/* thread information flags */
@@ -76,7 +81,6 @@ static inline struct thread_info *current_thread_info(void)
#define TIF_NEED_RESCHED 3 /* rescheduling necessary */
#define TIF_MEMDIE 4
-#define THREAD_SIZE 16384
#endif /* __KERNEL__ */
diff --git a/include/asm-sh64/timex.h b/include/asm-sh64/timex.h
index e07fd9a7cbd55..af0b792696615 100644
--- a/include/asm-sh64/timex.h
+++ b/include/asm-sh64/timex.h
@@ -23,8 +23,6 @@
typedef unsigned long cycles_t;
-extern cycles_t cacheflush_time;
-
static __inline__ cycles_t get_cycles (void)
{
return 0;
diff --git a/include/asm-sh64/uaccess.h b/include/asm-sh64/uaccess.h
index 588065c6399f8..a33654d576a1a 100644
--- a/include/asm-sh64/uaccess.h
+++ b/include/asm-sh64/uaccess.h
@@ -60,7 +60,8 @@
#define access_ok(type,addr,size) (__range_ok(addr,size) == 0)
#define __access_ok(addr,size) (__range_ok(addr,size) == 0)
-extern inline int verify_area(int type, const void __user * addr, unsigned long size)
+/* this function will go away soon - use access_ok() instead */
+extern inline int __deprecated verify_area(int type, const void __user * addr, unsigned long size)
{
return access_ok(type,addr,size) ? 0 : -EFAULT;
}
@@ -313,6 +314,12 @@ struct exception_table_entry
sh64 at the moment). */
#define ARCH_KMALLOC_MINALIGN 8
+/*
+ * We want 8-byte alignment for the slab caches as well, otherwise we have
+ * the same BYTES_PER_WORD (sizeof(void *)) min align in kmem_cache_create().
+ */
+#define ARCH_SLAB_MINALIGN 8
+
/* Returns 0 if exception not found and fixup.unit otherwise. */
extern unsigned long search_exception_table(unsigned long addr);
extern const struct exception_table_entry *search_exception_tables (unsigned long addr);
diff --git a/include/asm-sh64/unaligned.h b/include/asm-sh64/unaligned.h
index ad22487086c4e..74481b186ae88 100644
--- a/include/asm-sh64/unaligned.h
+++ b/include/asm-sh64/unaligned.h
@@ -12,17 +12,6 @@
*
*/
-#include <linux/string.h>
-
-
-/* Use memmove here, so gcc does not insert a __builtin_memcpy. */
-
-#define get_unaligned(ptr) \
- ({ __typeof__(*(ptr)) __tmp; memmove(&__tmp, (ptr), sizeof(*(ptr))); __tmp; })
-
-#define put_unaligned(val, ptr) \
- ({ __typeof__(*(ptr)) __tmp = (val); \
- memmove((ptr), &__tmp, sizeof(*(ptr))); \
- (void)0; })
+#include <asm-generic/unaligned.h>
#endif /* __ASM_SH64_UNALIGNED_H */
diff --git a/include/asm-sh64/unistd.h b/include/asm-sh64/unistd.h
index c7d9a52983e4c..95f0b130405c4 100644
--- a/include/asm-sh64/unistd.h
+++ b/include/asm-sh64/unistd.h
@@ -333,8 +333,13 @@
#define __NR_mq_timedreceive (__NR_mq_open+3)
#define __NR_mq_notify (__NR_mq_open+4)
#define __NR_mq_getsetattr (__NR_mq_open+5)
+#define __NR_sys_kexec_load 311
+#define __NR_waitid 312
+#define __NR_add_key 313
+#define __NR_request_key 314
+#define __NR_keyctl 315
-#define NR_syscalls 311
+#define NR_syscalls 316
/* user-visible error numbers are in the range -1 - -125: see <asm-sh64/errno.h> */
@@ -549,7 +554,7 @@ static inline pid_t wait(int * wait_stat)
* but it doesn't work on all toolchains, so we just do it by hand
*/
#ifndef cond_syscall
-#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
+#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
#endif
#endif /* __ASM_SH64_UNISTD_H */
diff --git a/include/asm-sparc/cacheflush.h b/include/asm-sparc/cacheflush.h
index a91fe62b33c4b..4901217008c09 100644
--- a/include/asm-sparc/cacheflush.h
+++ b/include/asm-sparc/cacheflush.h
@@ -50,21 +50,21 @@ BTFIXUPDEF_CALL(void, flush_cache_page, struct vm_area_struct *, unsigned long)
#define flush_cache_all() BTFIXUP_CALL(flush_cache_all)()
#define flush_cache_mm(mm) BTFIXUP_CALL(flush_cache_mm)(mm)
#define flush_cache_range(vma,start,end) BTFIXUP_CALL(flush_cache_range)(vma,start,end)
-#define flush_cache_page(vma,addr) BTFIXUP_CALL(flush_cache_page)(vma,addr)
+#define flush_cache_page(vma,addr,pfn) BTFIXUP_CALL(flush_cache_page)(vma,addr)
#define flush_icache_range(start, end) do { } while (0)
#define flush_icache_page(vma, pg) do { } while (0)
#define flush_icache_user_range(vma,pg,adr,len) do { } while (0)
#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
- do { \
- flush_cache_page(vma, vaddr); \
- memcpy(dst, src, len); \
+ do { \
+ flush_cache_page(vma, vaddr, page_to_pfn(page));\
+ memcpy(dst, src, len); \
} while (0)
#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
- do { \
- flush_cache_page(vma, vaddr); \
- memcpy(dst, src, len); \
+ do { \
+ flush_cache_page(vma, vaddr, page_to_pfn(page));\
+ memcpy(dst, src, len); \
} while (0)
BTFIXUPDEF_CALL(void, __flush_page_to_ram, unsigned long)
diff --git a/include/asm-sparc/io.h b/include/asm-sparc/io.h
index f98570f54b534..a42df208d5908 100644
--- a/include/asm-sparc/io.h
+++ b/include/asm-sparc/io.h
@@ -274,4 +274,17 @@ extern void sbus_iounmap(volatile void __iomem *vaddr, unsigned long size);
#endif
+#define __ARCH_HAS_NO_PAGE_ZERO_MAPPED 1
+
+/*
+ * Convert a physical pointer to a virtual kernel pointer for /dev/mem
+ * access
+ */
+#define xlate_dev_mem_ptr(p) __va(p)
+
+/*
+ * Convert a virtual cached pointer to an uncached pointer
+ */
+#define xlate_dev_kmem_ptr(p) p
+
#endif /* !(__SPARC_IO_H) */
diff --git a/include/asm-sparc/ipc.h b/include/asm-sparc/ipc.h
index 3064aaf8fa27c..a46e3d9c2a3fc 100644
--- a/include/asm-sparc/ipc.h
+++ b/include/asm-sparc/ipc.h
@@ -1,32 +1 @@
-#ifndef __SPARC_IPC_H__
-#define __SPARC_IPC_H__
-
-/*
- * These are used to wrap system calls on the sparc.
- *
- * See arch/sparc/kernel/sys_sparc.c for ugly details..
- */
-struct ipc_kludge {
- struct msgbuf __user *msgp;
- long msgtyp;
-};
-
-#define SEMOP 1
-#define SEMGET 2
-#define SEMCTL 3
-#define SEMTIMEDOP 4
-#define MSGSND 11
-#define MSGRCV 12
-#define MSGGET 13
-#define MSGCTL 14
-#define SHMAT 21
-#define SHMDT 22
-#define SHMGET 23
-#define SHMCTL 24
-
-/* Used by the DIPC package, try and avoid reusing it */
-#define DIPC 25
-
-#define IPCCALL(version,op) ((version)<<16 | (op))
-
-#endif
+#include <asm-generic/ipc.h>
diff --git a/include/asm-sparc/mostek.h b/include/asm-sparc/mostek.h
index c6022a5d611da..59b86bc793bf9 100644
--- a/include/asm-sparc/mostek.h
+++ b/include/asm-sparc/mostek.h
@@ -128,7 +128,6 @@ struct mostek48t08 {
char offset[6*1024]; /* Magic things may be here, who knows? */
struct mostek48t02 regs; /* Here is what we are interested in. */
};
-extern struct mostek48t08 *mstk48t08_regs;
extern enum sparc_clock_type sp_clock_typ;
diff --git a/include/asm-sparc/pgtable.h b/include/asm-sparc/pgtable.h
index e62df8cbd99d1..3d2418c28ff58 100644
--- a/include/asm-sparc/pgtable.h
+++ b/include/asm-sparc/pgtable.h
@@ -157,7 +157,7 @@ extern __inline__ int pte_none(pte_t pte)
}
#define pte_present(pte) BTFIXUP_CALL(pte_present)(pte)
-#define pte_clear(pte) BTFIXUP_CALL(pte_clear)(pte)
+#define pte_clear(mm,addr,pte) BTFIXUP_CALL(pte_clear)(pte)
BTFIXUPDEF_CALL_CONST(int, pmd_bad, pmd_t)
BTFIXUPDEF_CALL_CONST(int, pmd_present, pmd_t)
@@ -339,6 +339,7 @@ extern unsigned int pg_iobits;
BTFIXUPDEF_CALL(void, set_pte, pte_t *, pte_t)
#define set_pte(ptep,pteval) BTFIXUP_CALL(set_pte)(ptep,pteval)
+#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
struct seq_file;
BTFIXUPDEF_CALL(void, mmu_info, struct seq_file *)
@@ -453,8 +454,20 @@ extern unsigned long *sparc_valid_addr_bitmap;
#define kern_addr_valid(addr) \
(test_bit(__pa((unsigned long)(addr))>>20, sparc_valid_addr_bitmap))
-extern int io_remap_page_range(struct vm_area_struct *vma, unsigned long from, unsigned long to,
+extern int io_remap_page_range(struct vm_area_struct *vma,
+ unsigned long from, unsigned long to,
unsigned long size, pgprot_t prot, int space);
+extern int io_remap_pfn_range(struct vm_area_struct *vma,
+ unsigned long from, unsigned long pfn,
+ unsigned long size, pgprot_t prot);
+
+/*
+ * For sparc32&64, the pfn in io_remap_pfn_range() carries <iospace> in
+ * its high 4 bits. These macros/functions put it there or get it from there.
+ */
+#define MK_IOSPACE_PFN(space, pfn) (pfn | (space << (BITS_PER_LONG - 4)))
+#define GET_IOSPACE(pfn) (pfn >> (BITS_PER_LONG - 4))
+#define GET_PFN(pfn) (pfn & 0x0fffffffUL)
#include <asm-generic/pgtable.h>
diff --git a/include/asm-sparc/resource.h b/include/asm-sparc/resource.h
index 432731b3844d6..0514c304e1302 100644
--- a/include/asm-sparc/resource.h
+++ b/include/asm-sparc/resource.h
@@ -8,32 +8,18 @@
#define _SPARC_RESOURCE_H
/*
- * Resource limits
+ * These two resource limit IDs have a Sparc/Linux-specific ordering,
+ * the rest comes from the generic header:
*/
-
-#define RLIMIT_CPU 0 /* CPU time in ms */
-#define RLIMIT_FSIZE 1 /* Maximum filesize */
-#define RLIMIT_DATA 2 /* max data size */
-#define RLIMIT_STACK 3 /* max stack size */
-#define RLIMIT_CORE 4 /* max core file size */
-#define RLIMIT_RSS 5 /* max resident set size */
-#define RLIMIT_NOFILE 6 /* max number of open files */
-#define RLIMIT_NPROC 7 /* max number of processes */
-#define RLIMIT_MEMLOCK 8 /* max locked-in-memory address space */
-#define RLIMIT_AS 9 /* address space limit */
-#define RLIMIT_LOCKS 10 /* maximum file locks held */
-#define RLIMIT_SIGPENDING 11 /* max number of pending signals */
-#define RLIMIT_MSGQUEUE 12 /* maximum bytes in POSIX mqueues */
-
-#define RLIM_NLIMITS 13
-#define __ARCH_RLIMIT_ORDER
+#define RLIMIT_NOFILE 6 /* max number of open files */
+#define RLIMIT_NPROC 7 /* max number of processes */
/*
* SuS says limits have to be unsigned.
* We make this unsigned, but keep the
- * old value.
+ * old value for compatibility:
*/
-#define RLIM_INFINITY 0x7fffffff
+#define RLIM_INFINITY 0x7fffffff
#include <asm-generic/resource.h>
diff --git a/include/asm-sparc/system.h b/include/asm-sparc/system.h
index a8e77ad1ea468..80cf20cfaee1c 100644
--- a/include/asm-sparc/system.h
+++ b/include/asm-sparc/system.h
@@ -257,4 +257,6 @@ extern void die_if_kernel(char *str, struct pt_regs *regs) __attribute__ ((noret
#endif /* __ASSEMBLY__ */
+#define arch_align_stack(x) (x)
+
#endif /* !(__SPARC_SYSTEM_H) */
diff --git a/include/asm-sparc/timex.h b/include/asm-sparc/timex.h
index 870a3b39c8f51..71b45c90ccae3 100644
--- a/include/asm-sparc/timex.h
+++ b/include/asm-sparc/timex.h
@@ -10,7 +10,6 @@
/* XXX Maybe do something better at some point... -DaveM */
typedef unsigned long cycles_t;
-extern cycles_t cacheflush_time;
#define get_cycles() (0)
#endif
diff --git a/include/asm-sparc/uaccess.h b/include/asm-sparc/uaccess.h
index e1fa01955a06a..3f47889883b73 100644
--- a/include/asm-sparc/uaccess.h
+++ b/include/asm-sparc/uaccess.h
@@ -46,9 +46,10 @@
#define __access_ok(addr,size) (__user_ok((addr) & get_fs().seg,(size)))
#define access_ok(type,addr,size) __access_ok((unsigned long)(addr),(size))
-static inline int verify_area(int type, const void __user * addr, unsigned long size)
+/* this function will go away soon - use access_ok() instead */
+static inline int __deprecated verify_area(int type, const void __user * addr, unsigned long size)
{
- return access_ok(type,addr,size)?0:-EFAULT;
+ return access_ok(type,addr,size) ? 0 : -EFAULT;
}
/*
diff --git a/include/asm-sparc/unaligned.h b/include/asm-sparc/unaligned.h
index 9bbc1c822644a..b6f8eddd30af2 100644
--- a/include/asm-sparc/unaligned.h
+++ b/include/asm-sparc/unaligned.h
@@ -1,19 +1,6 @@
#ifndef _ASM_SPARC_UNALIGNED_H_
#define _ASM_SPARC_UNALIGNED_H_
-/* Sparc can't handle unaligned accesses. */
-
-#include <linux/string.h>
-
-
-/* Use memmove here, so gcc does not insert a __builtin_memcpy. */
-
-#define get_unaligned(ptr) \
- ({ __typeof__(*(ptr)) __tmp; memmove(&__tmp, (ptr), sizeof(*(ptr))); __tmp; })
-
-#define put_unaligned(val, ptr) \
- ({ __typeof__(*(ptr)) __tmp = (val); \
- memmove((ptr), &__tmp, sizeof(*(ptr))); \
- (void)0; })
+#include <asm-generic/unaligned.h>
#endif /* _ASM_SPARC_UNALIGNED_H */
diff --git a/include/asm-sparc/unistd.h b/include/asm-sparc/unistd.h
index 89142ca93d443..d1f63caaa326f 100644
--- a/include/asm-sparc/unistd.h
+++ b/include/asm-sparc/unistd.h
@@ -513,6 +513,6 @@ asmlinkage long sys_rt_sigaction(int sig,
* What we want is __attribute__((weak,alias("sys_ni_syscall"))),
* but it doesn't work on all toolchains, so we just do it by hand
*/
-#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
+#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
#endif /* _SPARC_UNISTD_H */
diff --git a/include/asm-sparc64/bugs.h b/include/asm-sparc64/bugs.h
index b0af781241d97..360dd04ed8e44 100644
--- a/include/asm-sparc64/bugs.h
+++ b/include/asm-sparc64/bugs.h
@@ -8,7 +8,7 @@
extern unsigned long loops_per_jiffy;
-static void check_bugs(void)
+static void __init check_bugs(void)
{
#ifndef CONFIG_SMP
cpu_data(0).udelay_val = loops_per_jiffy;
diff --git a/include/asm-sparc64/cacheflush.h b/include/asm-sparc64/cacheflush.h
index f4b1df6a56e92..f1f8661cf83a8 100644
--- a/include/asm-sparc64/cacheflush.h
+++ b/include/asm-sparc64/cacheflush.h
@@ -11,7 +11,7 @@
do { if ((__mm) == current->mm) flushw_user(); } while(0)
#define flush_cache_range(vma, start, end) \
flush_cache_mm((vma)->vm_mm)
-#define flush_cache_page(vma, page) \
+#define flush_cache_page(vma, page, pfn) \
flush_cache_mm((vma)->vm_mm)
/*
@@ -38,15 +38,15 @@ extern void __flush_dcache_range(unsigned long start, unsigned long end);
#define flush_icache_user_range(vma,pg,adr,len) do { } while (0)
#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
- do { \
- flush_cache_page(vma, vaddr); \
- memcpy(dst, src, len); \
+ do { \
+ flush_cache_page(vma, vaddr, page_to_pfn(page));\
+ memcpy(dst, src, len); \
} while (0)
#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
- do { \
- flush_cache_page(vma, vaddr); \
- memcpy(dst, src, len); \
+ do { \
+ flush_cache_page(vma, vaddr, page_to_pfn(page));\
+ memcpy(dst, src, len); \
} while (0)
extern void flush_dcache_page(struct page *page);
diff --git a/include/asm-sparc64/io.h b/include/asm-sparc64/io.h
index 6661a23b6883a..afdcea90707a7 100644
--- a/include/asm-sparc64/io.h
+++ b/include/asm-sparc64/io.h
@@ -485,6 +485,17 @@ extern void pci_iounmap(struct pci_dev *dev, void __iomem *);
#define dma_cache_wback(_start,_size) do { } while (0)
#define dma_cache_wback_inv(_start,_size) do { } while (0)
+/*
+ * Convert a physical pointer to a virtual kernel pointer for /dev/mem
+ * access
+ */
+#define xlate_dev_mem_ptr(p) __va(p)
+
+/*
+ * Convert a virtual cached pointer to an uncached pointer
+ */
+#define xlate_dev_kmem_ptr(p) p
+
#endif
#endif /* !(__SPARC64_IO_H) */
diff --git a/include/asm-sparc64/ipc.h b/include/asm-sparc64/ipc.h
index 39261d5523ef9..a46e3d9c2a3fc 100644
--- a/include/asm-sparc64/ipc.h
+++ b/include/asm-sparc64/ipc.h
@@ -1,33 +1 @@
-#ifndef __SPARC64_IPC_H__
-#define __SPARC64_IPC_H__
-
-/*
- * These are used to wrap system calls on the sparc.
- *
- * See arch/sparc64/kernel/sys_sparc32.c for ugly details..
- */
-struct ipc_kludge {
- u32 msgp;
- s32 msgtyp;
-};
-
-#define SEMOP 1
-#define SEMGET 2
-#define SEMCTL 3
-#define SEMTIMEDOP 4
-#define MSGSND 11
-#define MSGRCV 12
-#define MSGGET 13
-#define MSGCTL 14
-#define SHMAT 21
-#define SHMDT 22
-#define SHMGET 23
-#define SHMCTL 24
-
-/* Used by the DIPC package, try and avoid reusing it */
-#define DIPC 25
-
-/* We don't need to maintain backward compatibility on 64bit, we've started fresh */
-#define IPCCALL(version,op) (op)
-
-#endif
+#include <asm-generic/ipc.h>
diff --git a/include/asm-sparc64/mostek.h b/include/asm-sparc64/mostek.h
index b000c1586b4d2..ccf2f5f82d7f5 100644
--- a/include/asm-sparc64/mostek.h
+++ b/include/asm-sparc64/mostek.h
@@ -134,13 +134,11 @@ do { u8 __val = mostek_read(regs + MOSTEK_ ## name); \
*/
#define MOSTEK_48T08_OFFSET 0x0000UL /* Lower NVRAM portions */
#define MOSTEK_48T08_48T02 0x1800UL /* Offset to 48T02 chip */
-extern unsigned long mstk48t08_regs;
/* SUN5 systems usually have 48t59 model clock chipsets. But we keep the older
* clock chip definitions around just in case.
*/
#define MOSTEK_48T59_OFFSET 0x0000UL /* Lower NVRAM portions */
#define MOSTEK_48T59_48T02 0x1800UL /* Offset to 48T02 chip */
-extern unsigned long mstk48t59_regs;
#endif /* !(_SPARC64_MOSTEK_H) */
diff --git a/include/asm-sparc64/pci.h b/include/asm-sparc64/pci.h
index 861f16533ba22..2a0c85cd1c11d 100644
--- a/include/asm-sparc64/pci.h
+++ b/include/asm-sparc64/pci.h
@@ -223,7 +223,10 @@ static inline int pci_dma_mapping_error(dma_addr_t dma_addr)
/* Return the index of the PCI controller for device PDEV. */
extern int pci_domain_nr(struct pci_bus *bus);
-extern int pci_name_bus(char *name, struct pci_bus *bus);
+static inline int pci_proc_domain(struct pci_bus *bus)
+{
+ return 1;
+}
/* Platform support for /proc/bus/pci/X/Y mmap()s. */
diff --git a/include/asm-sparc64/pgalloc.h b/include/asm-sparc64/pgalloc.h
index e1b053882ae92..167d514bdf6ee 100644
--- a/include/asm-sparc64/pgalloc.h
+++ b/include/asm-sparc64/pgalloc.h
@@ -7,9 +7,7 @@
#include <linux/sched.h>
#include <linux/mm.h>
-#include <asm/page.h>
#include <asm/spitfire.h>
-#include <asm/pgtable.h>
#include <asm/cpudata.h>
/* Page table allocation/freeing. */
@@ -191,25 +189,17 @@ extern pte_t *__pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address
static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
{
- pte_t *pte = __pte_alloc_one_kernel(mm, address);
- if (pte) {
- struct page *page = virt_to_page(pte);
- page->mapping = (void *) mm;
- page->index = address & PMD_MASK;
- }
- return pte;
+ return __pte_alloc_one_kernel(mm, address);
}
static inline struct page *
pte_alloc_one(struct mm_struct *mm, unsigned long addr)
{
pte_t *pte = __pte_alloc_one_kernel(mm, addr);
- if (pte) {
- struct page *page = virt_to_page(pte);
- page->mapping = (void *) mm;
- page->index = addr & PMD_MASK;
- return page;
- }
+
+ if (pte)
+ return virt_to_page(pte);
+
return NULL;
}
@@ -246,13 +236,11 @@ static __inline__ void free_pte_slow(pte_t *pte)
static inline void pte_free_kernel(pte_t *pte)
{
- virt_to_page(pte)->mapping = NULL;
free_pte_fast(pte);
}
static inline void pte_free(struct page *ptepage)
{
- ptepage->mapping = NULL;
free_pte_fast(page_address(ptepage));
}
diff --git a/include/asm-sparc64/pgtable.h b/include/asm-sparc64/pgtable.h
index 83adf8070928f..dfb8a88863186 100644
--- a/include/asm-sparc64/pgtable.h
+++ b/include/asm-sparc64/pgtable.h
@@ -15,6 +15,8 @@
#include <asm-generic/pgtable-nopud.h>
#include <linux/config.h>
+#include <linux/compiler.h>
+#include <asm/types.h>
#include <asm/spitfire.h>
#include <asm/asi.h>
#include <asm/system.h>
@@ -333,18 +335,23 @@ static inline pte_t pte_modify(pte_t orig_pte, pgprot_t new_prot)
#define pte_unmap_nested(pte) do { } while (0)
/* Actual page table PTE updates. */
-extern void tlb_batch_add(pte_t *ptep, pte_t orig);
+extern void tlb_batch_add(struct mm_struct *mm, unsigned long vaddr, pte_t *ptep, pte_t orig);
-static inline void set_pte(pte_t *ptep, pte_t pte)
+static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pte)
{
pte_t orig = *ptep;
*ptep = pte;
- if (pte_present(orig))
- tlb_batch_add(ptep, orig);
+
+ /* It is more efficient to let flush_tlb_kernel_range()
+ * handle init_mm tlb flushes.
+ */
+ if (likely(mm != &init_mm) && (pte_val(orig) & _PAGE_VALID))
+ tlb_batch_add(mm, addr, ptep, orig);
}
-#define pte_clear(ptep) set_pte((ptep), __pte(0UL))
+#define pte_clear(mm,addr,ptep) \
+ set_pte_at((mm), (addr), (ptep), __pte(0UL))
extern pgd_t swapper_pg_dir[1];
@@ -425,6 +432,32 @@ extern unsigned long *sparc64_valid_addr_bitmap;
extern int io_remap_page_range(struct vm_area_struct *vma, unsigned long from,
unsigned long offset,
unsigned long size, pgprot_t prot, int space);
+extern int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from,
+ unsigned long pfn,
+ unsigned long size, pgprot_t prot);
+
+/*
+ * For sparc32&64, the pfn in io_remap_pfn_range() carries <iospace> in
+ * its high 4 bits. These macros/functions put it there or get it from there.
+ */
+#define MK_IOSPACE_PFN(space, pfn) (pfn | (space << (BITS_PER_LONG - 4)))
+#define GET_IOSPACE(pfn) (pfn >> (BITS_PER_LONG - 4))
+#define GET_PFN(pfn) (pfn & 0x0fffffffffffffffUL)
+
+/* Override for {pgd,pmd}_addr_end() to deal with the virtual address
+ * space hole. We simply sign extend bit 43.
+ */
+#define pgd_addr_end(addr, end) \
+({ unsigned long __boundary = ((addr) + PGDIR_SIZE) & PGDIR_MASK; \
+ __boundary = ((long) (__boundary << 20)) >> 20; \
+ (__boundary - 1 < (end) - 1)? __boundary: (end); \
+})
+
+#define pmd_addr_end(addr, end) \
+({ unsigned long __boundary = ((addr) + PMD_SIZE) & PMD_MASK; \
+ __boundary = ((long) (__boundary << 20)) >> 20; \
+ (__boundary - 1 < (end) - 1)? __boundary: (end); \
+})
#include <asm-generic/pgtable.h>
diff --git a/include/asm-sparc64/resource.h b/include/asm-sparc64/resource.h
index 29d0e13c0eb76..aa469795a6b07 100644
--- a/include/asm-sparc64/resource.h
+++ b/include/asm-sparc64/resource.h
@@ -8,25 +8,11 @@
#define _SPARC64_RESOURCE_H
/*
- * Resource limits
+ * These two resource limit IDs have a Sparc/Linux-specific ordering,
+ * the rest comes from the generic header:
*/
-
-#define RLIMIT_CPU 0 /* CPU time in ms */
-#define RLIMIT_FSIZE 1 /* Maximum filesize */
-#define RLIMIT_DATA 2 /* max data size */
-#define RLIMIT_STACK 3 /* max stack size */
-#define RLIMIT_CORE 4 /* max core file size */
-#define RLIMIT_RSS 5 /* max resident set size */
-#define RLIMIT_NOFILE 6 /* max number of open files */
-#define RLIMIT_NPROC 7 /* max number of processes */
-#define RLIMIT_MEMLOCK 8 /* max locked-in-memory address space */
-#define RLIMIT_AS 9 /* address space limit */
-#define RLIMIT_LOCKS 10 /* maximum file locks held */
-#define RLIMIT_SIGPENDING 11 /* max number of pending signals */
-#define RLIMIT_MSGQUEUE 12 /* maximum bytes in POSIX mqueues */
-
-#define RLIM_NLIMITS 13
-#define __ARCH_RLIMIT_ORDER
+#define RLIMIT_NOFILE 6 /* max number of open files */
+#define RLIMIT_NPROC 7 /* max number of processes */
#include <asm-generic/resource.h>
diff --git a/include/asm-sparc64/siginfo.h b/include/asm-sparc64/siginfo.h
index 49952c6a23ebf..7160449e7cab1 100644
--- a/include/asm-sparc64/siginfo.h
+++ b/include/asm-sparc64/siginfo.h
@@ -4,7 +4,6 @@
#define SI_PAD_SIZE32 ((SI_MAX_SIZE/sizeof(int)) - 3)
#define SIGEV_PAD_SIZE ((SIGEV_MAX_SIZE/sizeof(int)) - 4)
-#define SIGEV_PAD_SIZE32 ((SIGEV_MAX_SIZE/sizeof(int)) - 3)
#define __ARCH_SI_PREAMBLE_SIZE (4 * sizeof(int))
#define __ARCH_SI_TRAPNO
@@ -19,11 +18,6 @@
#ifdef CONFIG_COMPAT
-typedef union sigval32 {
- int sival_int;
- u32 sival_ptr;
-} sigval_t32;
-
struct compat_siginfo;
#endif /* CONFIG_COMPAT */
@@ -38,26 +32,4 @@ struct compat_siginfo;
#define EMT_TAGOVF (__SI_FAULT|1) /* tag overflow */
#define NSIGEMT 1
-#ifdef __KERNEL__
-
-#ifdef CONFIG_COMPAT
-
-typedef struct sigevent32 {
- sigval_t32 sigev_value;
- int sigev_signo;
- int sigev_notify;
- union {
- int _pad[SIGEV_PAD_SIZE32];
-
- struct {
- u32 _function;
- u32 _attribute; /* really pthread_attr_t */
- } _sigev_thread;
- } _sigev_un;
-} sigevent_t32;
-
-#endif /* CONFIG_COMPAT */
-
-#endif /* __KERNEL__ */
-
#endif
diff --git a/include/asm-sparc64/smp.h b/include/asm-sparc64/smp.h
index 4836362c0c494..5e3e06d908feb 100644
--- a/include/asm-sparc64/smp.h
+++ b/include/asm-sparc64/smp.h
@@ -30,8 +30,6 @@
#include <asm/bitops.h>
#include <asm/atomic.h>
-extern unsigned char boot_cpu_id;
-
extern cpumask_t phys_cpu_present_map;
#define cpu_possible_map phys_cpu_present_map
diff --git a/include/asm-sparc64/system.h b/include/asm-sparc64/system.h
index ef77358abf241..e8ba9d5277e15 100644
--- a/include/asm-sparc64/system.h
+++ b/include/asm-sparc64/system.h
@@ -341,4 +341,6 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
#endif /* !(__ASSEMBLY__) */
+#define arch_align_stack(x) (x)
+
#endif /* !(__SPARC64_SYSTEM_H) */
diff --git a/include/asm-sparc64/tlb.h b/include/asm-sparc64/tlb.h
index 9ff2b61533d84..fa0ebf6786fc9 100644
--- a/include/asm-sparc64/tlb.h
+++ b/include/asm-sparc64/tlb.h
@@ -80,11 +80,11 @@ static inline void tlb_finish_mmu(struct mmu_gather *mp, unsigned long start, un
{
unsigned long freed = mp->freed;
struct mm_struct *mm = mp->mm;
- unsigned long rss = mm->rss;
+ unsigned long rss = get_mm_counter(mm, rss);
if (rss < freed)
freed = rss;
- mm->rss = rss - freed;
+ add_mm_counter(mm, rss, -freed);
tlb_flush_mmu(mp);
diff --git a/include/asm-sparc64/uaccess.h b/include/asm-sparc64/uaccess.h
index 56646813a6af6..5690142f82de3 100644
--- a/include/asm-sparc64/uaccess.h
+++ b/include/asm-sparc64/uaccess.h
@@ -49,12 +49,18 @@ do { \
__asm__ __volatile__ ("wr %%g0, %0, %%asi" : : "r" ((val).seg)); \
} while(0)
-#define __user_ok(addr,size) ((void)(addr), (void)(size), 1)
-#define __kernel_ok (segment_eq(get_fs(), KERNEL_DS))
-#define __access_ok(addr,size) ((void)(addr), (void)(size), 1)
-#define access_ok(type,addr,size) ((void)(type), (void)(addr), (void)(size), 1)
+static inline int __access_ok(const void __user * addr, unsigned long size)
+{
+ return 1;
+}
+
+static inline int access_ok(int type, const void __user * addr, unsigned long size)
+{
+ return 1;
+}
-static inline int verify_area(int type, const void __user * addr, unsigned long size)
+/* this function will go away soon - use access_ok() instead */
+static inline int __deprecated verify_area(int type, const void __user * addr, unsigned long size)
{
return 0;
}
diff --git a/include/asm-sparc64/unaligned.h b/include/asm-sparc64/unaligned.h
index 9418756d52db6..1ed3ba5377728 100644
--- a/include/asm-sparc64/unaligned.h
+++ b/include/asm-sparc64/unaligned.h
@@ -1,19 +1,6 @@
#ifndef _ASM_SPARC64_UNALIGNED_H_
#define _ASM_SPARC64_UNALIGNED_H_
-/* Sparc can't handle unaligned accesses. */
-
-#include <linux/string.h>
-
-
-/* Use memmove here, so gcc does not insert a __builtin_memcpy. */
-
-#define get_unaligned(ptr) \
- ({ __typeof__(*(ptr)) __tmp; memmove(&__tmp, (ptr), sizeof(*(ptr))); __tmp; })
-
-#define put_unaligned(val, ptr) \
- ({ __typeof__(*(ptr)) __tmp = (val); \
- memmove((ptr), &__tmp, sizeof(*(ptr))); \
- (void)0; })
+#include <asm-generic/unaligned.h>
#endif /* _ASM_SPARC64_UNALIGNED_H */
diff --git a/include/asm-sparc64/unistd.h b/include/asm-sparc64/unistd.h
index 12c151e1ff696..3c00065eea80a 100644
--- a/include/asm-sparc64/unistd.h
+++ b/include/asm-sparc64/unistd.h
@@ -509,6 +509,6 @@ asmlinkage long sys_rt_sigaction(int sig,
* What we want is __attribute__((weak,alias("sys_ni_syscall"))),
* but it doesn't work on all toolchains, so we just do it by hand
*/
-#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
+#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
#endif /* _SPARC64_UNISTD_H */
diff --git a/include/asm-um/archparam-i386.h b/include/asm-um/archparam-i386.h
index 5b5df118d9a5f..6f78de5b621b8 100644
--- a/include/asm-um/archparam-i386.h
+++ b/include/asm-um/archparam-i386.h
@@ -8,7 +8,7 @@
/********* Bits for asm-um/elf.h ************/
-#include "user.h"
+#include <asm/user.h>
extern char * elf_aux_platform;
#define ELF_PLATFORM (elf_aux_platform)
diff --git a/include/asm-um/io.h b/include/asm-um/io.h
index 62d6f2423ea6b..90674056dcef4 100644
--- a/include/asm-um/io.h
+++ b/include/asm-um/io.h
@@ -22,4 +22,15 @@ static inline void * phys_to_virt(unsigned long address)
return __va(address);
}
+/*
+ * Convert a physical pointer to a virtual kernel pointer for /dev/mem
+ * access
+ */
+#define xlate_dev_mem_ptr(p) __va(p)
+
+/*
+ * Convert a virtual cached pointer to an uncached pointer
+ */
+#define xlate_dev_kmem_ptr(p) p
+
#endif
diff --git a/include/asm-um/pgtable-2level.h b/include/asm-um/pgtable-2level.h
index f6263d11f2054..61eb247342475 100644
--- a/include/asm-um/pgtable-2level.h
+++ b/include/asm-um/pgtable-2level.h
@@ -21,7 +21,6 @@
* we don't really have any PMD directory physically.
*/
#define PTRS_PER_PTE 1024
-#define PTRS_PER_PMD 1
#define USER_PTRS_PER_PGD ((TASK_SIZE + (PGDIR_SIZE - 1)) / PGDIR_SIZE)
#define PTRS_PER_PGD 1024
#define FIRST_USER_PGD_NR 0
@@ -59,6 +58,7 @@ static inline void set_pte(pte_t *pteptr, pte_t pteval)
*pteptr = pte_mknewpage(pteval);
if(pte_present(*pteptr)) *pteptr = pte_mknewprot(*pteptr);
}
+#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
#define set_pmd(pmdptr, pmdval) (*(pmdptr) = (pmdval))
diff --git a/include/asm-um/pgtable-3level.h b/include/asm-um/pgtable-3level.h
index acebb593cfd6b..faf051c2c4189 100644
--- a/include/asm-um/pgtable-3level.h
+++ b/include/asm-um/pgtable-3level.h
@@ -84,6 +84,7 @@ static inline void set_pte(pte_t *pteptr, pte_t pteval)
*pteptr = pte_mknewpage(*pteptr);
if(pte_present(*pteptr)) *pteptr = pte_mknewprot(*pteptr);
}
+#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
#define set_pmd(pmdptr, pmdval) set_64bit((phys_t *) (pmdptr), pmd_val(pmdval))
diff --git a/include/asm-um/pgtable.h b/include/asm-um/pgtable.h
index e0a0a95639a74..71f9c0c78c0cb 100644
--- a/include/asm-um/pgtable.h
+++ b/include/asm-um/pgtable.h
@@ -142,7 +142,7 @@ extern pte_t * __bad_pagetable(void);
#define PAGE_PTR(address) \
((unsigned long)(address)>>(PAGE_SHIFT-SIZEOF_PTR_LOG2)&PTR_MASK&~PAGE_MASK)
-#define pte_clear(xp) pte_set_val(*(xp), (phys_t) 0, __pgprot(_PAGE_NEWPAGE))
+#define pte_clear(mm,addr,xp) pte_set_val(*(xp), (phys_t) 0, __pgprot(_PAGE_NEWPAGE))
#define pmd_none(x) (!(pmd_val(x) & ~_PAGE_NEWPAGE))
#define pmd_bad(x) ((pmd_val(x) & (~PAGE_MASK & ~_PAGE_USER)) != _KERNPG_TABLE)
diff --git a/include/asm-um/processor-generic.h b/include/asm-um/processor-generic.h
index ec58334fb2c78..038ba6fc88b8c 100644
--- a/include/asm-um/processor-generic.h
+++ b/include/asm-um/processor-generic.h
@@ -16,8 +16,6 @@ struct task_struct;
struct mm_struct;
-#define cpu_relax() barrier()
-
struct thread_struct {
int forking;
int nsyscalls;
diff --git a/include/asm-um/processor-i386.h b/include/asm-um/processor-i386.h
index 633cfad9cb0db..2deb8f1adbf12 100644
--- a/include/asm-um/processor-i386.h
+++ b/include/asm-um/processor-i386.h
@@ -19,6 +19,14 @@ struct arch_thread {
#include "asm/arch/user.h"
+/* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */
+static inline void rep_nop(void)
+{
+ __asm__ __volatile__("rep;nop": : :"memory");
+}
+
+#define cpu_relax() rep_nop()
+
/*
* Default implementation of macro that returns current
* instruction pointer ("program counter"). Stolen
diff --git a/include/asm-um/processor-x86_64.h b/include/asm-um/processor-x86_64.h
index 6bfd7870775e5..a1ae3a4cd9381 100644
--- a/include/asm-um/processor-x86_64.h
+++ b/include/asm-um/processor-x86_64.h
@@ -12,6 +12,14 @@
struct arch_thread {
};
+/* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */
+extern inline void rep_nop(void)
+{
+ __asm__ __volatile__("rep;nop": : :"memory");
+}
+
+#define cpu_relax() rep_nop()
+
#define INIT_ARCH_THREAD { }
#define current_text_addr() \
diff --git a/include/asm-um/setup.h b/include/asm-um/setup.h
index e5787bb80e79d..c85252e803c13 100644
--- a/include/asm-um/setup.h
+++ b/include/asm-um/setup.h
@@ -1,6 +1,9 @@
#ifndef SETUP_H_INCLUDED
#define SETUP_H_INCLUDED
-#define COMMAND_LINE_SIZE 512
+/* POSIX mandated with _POSIX_ARG_MAX that we can rely on 4096 chars in the
+ * command line, so this choice is ok.*/
+
+#define COMMAND_LINE_SIZE 4096
#endif /* SETUP_H_INCLUDED */
diff --git a/include/asm-um/signal.h b/include/asm-um/signal.h
index 211d1e8a81790..52ed92cbce4cd 100644
--- a/include/asm-um/signal.h
+++ b/include/asm-um/signal.h
@@ -11,6 +11,9 @@
#define do_signal do_signal_renamed
#include "asm/arch/signal.h"
#undef do_signal
+#undef ptrace_signal_deliver
+
+#define ptrace_signal_deliver(regs, cookie) do {} while(0)
#endif
diff --git a/include/asm-um/timex.h b/include/asm-um/timex.h
index 580581172e978..0f4ada08f7488 100644
--- a/include/asm-um/timex.h
+++ b/include/asm-um/timex.h
@@ -3,8 +3,6 @@
typedef unsigned long cycles_t;
-#define cacheflush_time (0)
-
static inline cycles_t get_cycles (void)
{
return 0;
diff --git a/include/asm-v850/cacheflush.h b/include/asm-v850/cacheflush.h
index 17d7d893424fb..e1a87f82f1a4b 100644
--- a/include/asm-v850/cacheflush.h
+++ b/include/asm-v850/cacheflush.h
@@ -25,7 +25,7 @@
#define flush_cache_all() ((void)0)
#define flush_cache_mm(mm) ((void)0)
#define flush_cache_range(vma, start, end) ((void)0)
-#define flush_cache_page(vma, vmaddr) ((void)0)
+#define flush_cache_page(vma, vmaddr, pfn) ((void)0)
#define flush_dcache_page(page) ((void)0)
#define flush_dcache_mmap_lock(mapping) ((void)0)
#define flush_dcache_mmap_unlock(mapping) ((void)0)
diff --git a/include/asm-v850/io.h b/include/asm-v850/io.h
index ad9d60703b6f7..bb5efd1b4b7d0 100644
--- a/include/asm-v850/io.h
+++ b/include/asm-v850/io.h
@@ -119,4 +119,15 @@ outsl (unsigned long port, const void *src, unsigned long count)
#define memcpy_fromio(dst, src, len) memcpy (dst, (void *)src, len)
#define memcpy_toio(dst, src, len) memcpy ((void *)dst, src, len)
+/*
+ * Convert a physical pointer to a virtual kernel pointer for /dev/mem
+ * access
+ */
+#define xlate_dev_mem_ptr(p) __va(p)
+
+/*
+ * Convert a virtual cached pointer to an uncached pointer
+ */
+#define xlate_dev_kmem_ptr(p) p
+
#endif /* __V850_IO_H__ */
diff --git a/include/asm-v850/ipc.h b/include/asm-v850/ipc.h
index 5656799cd4e85..a46e3d9c2a3fc 100644
--- a/include/asm-v850/ipc.h
+++ b/include/asm-v850/ipc.h
@@ -1,31 +1 @@
-#ifndef __V850_IPC_H__
-#define __V850_IPC_H__
-
-/*
- * These are used to wrap system calls on v850.
- *
- * See arch/v850/kernel/syscalls.c for ugly details..
- */
-struct ipc_kludge {
- struct msgbuf *msgp;
- long msgtyp;
-};
-
-#define SEMOP 1
-#define SEMGET 2
-#define SEMCTL 3
-#define MSGSND 11
-#define MSGRCV 12
-#define MSGGET 13
-#define MSGCTL 14
-#define SHMAT 21
-#define SHMDT 22
-#define SHMGET 23
-#define SHMCTL 24
-
-/* Used by the DIPC package, try and avoid reusing it */
-#define DIPC 25
-
-#define IPCCALL(version,op) ((version)<<16 | (op))
-
-#endif /* __V850_IPC_H__ */
+#include <asm-generic/ipc.h>
diff --git a/include/asm-v850/system.h b/include/asm-v850/system.h
index 072a997dc5a96..20f4c738c04ef 100644
--- a/include/asm-v850/system.h
+++ b/include/asm-v850/system.h
@@ -108,4 +108,6 @@ extern inline unsigned long __xchg (unsigned long with,
return tmp;
}
+#define arch_align_stack(x) (x)
+
#endif /* __V850_SYSTEM_H__ */
diff --git a/include/asm-v850/uaccess.h b/include/asm-v850/uaccess.h
index 7068dfcffa87d..4386cfc6a8dda 100644
--- a/include/asm-v850/uaccess.h
+++ b/include/asm-v850/uaccess.h
@@ -27,7 +27,8 @@ extern inline int access_ok (int type, const void *addr, unsigned long size)
return val >= (0x80 + NUM_CPU_IRQS*16) && val < 0xFFFFF000;
}
-extern inline int verify_area (int type, const void *addr, unsigned long size)
+/* this function will go away soon - use access_ok() instead */
+extern inline int __deprecated verify_area (int type, const void *addr, unsigned long size)
{
return access_ok (type, addr, size) ? 0 : -EFAULT;
}
diff --git a/include/asm-v850/unistd.h b/include/asm-v850/unistd.h
index 9517031d8fd1b..3b552096c0e87 100644
--- a/include/asm-v850/unistd.h
+++ b/include/asm-v850/unistd.h
@@ -466,7 +466,7 @@ asmlinkage long sys_rt_sigaction(int sig,
*/
#define cond_syscall(name) \
asm (".weak\t" C_SYMBOL_STRING(name) ";" \
- ".set\t" C_SYMBOL_STRING(name) "," C_SYMBOL_STRING(sys_ni_syscall));
+ ".set\t" C_SYMBOL_STRING(name) "," C_SYMBOL_STRING(sys_ni_syscall))
#if 0
/* This doesn't work if there's a function prototype for NAME visible,
because the argument types probably won't match. */
diff --git a/include/asm-x86_64/acpi.h b/include/asm-x86_64/acpi.h
index c5c478ab07680..a6b41b892062a 100644
--- a/include/asm-x86_64/acpi.h
+++ b/include/asm-x86_64/acpi.h
@@ -153,7 +153,6 @@ static inline int acpi_irq_balance_set(char *str) { return 0; }
/* routines for saving/restoring kernel state */
extern int acpi_save_state_mem(void);
-extern int acpi_save_state_disk(void);
extern void acpi_restore_state_mem(void);
extern unsigned long acpi_wakeup_address;
diff --git a/include/asm-x86_64/cacheflush.h b/include/asm-x86_64/cacheflush.h
index dd6d3abfd2bbc..b3189fb229d19 100644
--- a/include/asm-x86_64/cacheflush.h
+++ b/include/asm-x86_64/cacheflush.h
@@ -8,7 +8,7 @@
#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)
-#define flush_cache_page(vma, vmaddr) do { } while (0)
+#define flush_cache_page(vma, vmaddr, pfn) do { } while (0)
#define flush_dcache_page(page) do { } while (0)
#define flush_dcache_mmap_lock(mapping) do { } while (0)
#define flush_dcache_mmap_unlock(mapping) do { } while (0)
diff --git a/include/asm-x86_64/io.h b/include/asm-x86_64/io.h
index 734db492e8894..94202703fae2f 100644
--- a/include/asm-x86_64/io.h
+++ b/include/asm-x86_64/io.h
@@ -36,11 +36,7 @@
* - Arnaldo Carvalho de Melo <acme@conectiva.com.br>
*/
-#ifdef SLOW_IO_BY_JUMPING
-#define __SLOW_DOWN_IO "\njmp 1f\n1:\tjmp 1f\n1:"
-#else
#define __SLOW_DOWN_IO "\noutb %%al,$0x80"
-#endif
#ifdef REALLY_SLOW_IO
#define __FULL_SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO
@@ -329,6 +325,17 @@ out:
extern int iommu_bio_merge;
#define BIO_VMERGE_BOUNDARY iommu_bio_merge
+/*
+ * Convert a physical pointer to a virtual kernel pointer for /dev/mem
+ * access
+ */
+#define xlate_dev_mem_ptr(p) __va(p)
+
+/*
+ * Convert a virtual cached pointer to an uncached pointer
+ */
+#define xlate_dev_kmem_ptr(p) p
+
#endif /* __KERNEL__ */
#endif
diff --git a/include/asm-x86_64/ipc.h b/include/asm-x86_64/ipc.h
deleted file mode 100644
index 8736ba68c1183..0000000000000
--- a/include/asm-x86_64/ipc.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __x8664_IPC_H__
-#define __x8664_IPC_H__
-
-/* dummy */
-
-#endif
diff --git a/include/asm-x86_64/mmu_context.h b/include/asm-x86_64/mmu_context.h
index 410bd4067d346..b630d52bdfb1e 100644
--- a/include/asm-x86_64/mmu_context.h
+++ b/include/asm-x86_64/mmu_context.h
@@ -28,6 +28,11 @@ static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
}
#endif
+static inline void load_cr3(pgd_t *pgd)
+{
+ asm volatile("movq %0,%%cr3" :: "r" (__pa(pgd)) : "memory");
+}
+
static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
struct task_struct *tsk)
{
@@ -40,7 +45,8 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
write_pda(active_mm, next);
#endif
set_bit(cpu, &next->cpu_vm_mask);
- asm volatile("movq %0,%%cr3" :: "r" (__pa(next->pgd)) : "memory");
+ load_cr3(next->pgd);
+
if (unlikely(next->context.ldt != prev->context.ldt))
load_LDT_nolock(&next->context, cpu);
}
@@ -54,7 +60,7 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
* tlb flush IPI delivery. We must reload CR3
* to make sure to use no freed page tables.
*/
- asm volatile("movq %0,%%cr3" :: "r" (__pa(next->pgd)) : "memory");
+ load_cr3(next->pgd);
load_LDT_nolock(&next->context, cpu);
}
}
diff --git a/include/asm-x86_64/mpspec.h b/include/asm-x86_64/mpspec.h
index f93aa378459a6..331f6a3c72a2a 100644
--- a/include/asm-x86_64/mpspec.h
+++ b/include/asm-x86_64/mpspec.h
@@ -156,7 +156,7 @@ struct mpc_config_lintsrc
* 7 2 CPU MCA+PCI
*/
-#define MAX_MP_BUSSES 270
+#define MAX_MP_BUSSES 256
#define MAX_IRQ_SOURCES 256
enum mp_bustype {
MP_BUS_ISA = 1,
@@ -176,7 +176,6 @@ extern int apic_version [MAX_APICS];
extern int mp_irq_entries;
extern struct mpc_config_intsrc mp_irqs [MAX_IRQ_SOURCES];
extern int mpc_default_type;
-extern int mp_current_pci_id;
extern unsigned long mp_lapic_addr;
extern int pic_mode;
diff --git a/include/asm-x86_64/msr.h b/include/asm-x86_64/msr.h
index 8506956784197..66f0be191ab4f 100644
--- a/include/asm-x86_64/msr.h
+++ b/include/asm-x86_64/msr.h
@@ -28,8 +28,8 @@
#define wrmsrl(msr,val) wrmsr(msr,(__u32)((__u64)(val)),((__u64)(val))>>32)
-/* wrmsrl with exception handling */
-#define checking_wrmsrl(msr,val) ({ int ret__; \
+/* wrmsr with exception handling */
+#define wrmsr_safe(msr,a,b) ({ int ret__; \
asm volatile("2: wrmsr ; xorl %0,%0\n" \
"1:\n\t" \
".section .fixup,\"ax\"\n\t" \
@@ -40,9 +40,11 @@
" .quad 2b,3b\n\t" \
".previous" \
: "=a" (ret__) \
- : "c" (msr), "0" ((__u32)val), "d" ((val)>>32), "i" (-EFAULT));\
+ : "c" (msr), "0" (a), "d" (b), "i" (-EFAULT));\
ret__; })
+#define checking_wrmsrl(msr,val) wrmsr_safe(msr,(u32)(val),(u32)((val)>>32))
+
#define rdtsc(low,high) \
__asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high))
@@ -78,6 +80,18 @@ extern inline void cpuid(int op, unsigned int *eax, unsigned int *ebx,
: "0" (op));
}
+/* Some CPUID calls want 'count' to be placed in ecx */
+static inline void cpuid_count(int op, int count, int *eax, int *ebx, int *ecx,
+ int *edx)
+{
+ __asm__("cpuid"
+ : "=a" (*eax),
+ "=b" (*ebx),
+ "=c" (*ecx),
+ "=d" (*edx)
+ : "0" (op), "c" (count));
+}
+
/*
* CPUID functions returning a single datum
*/
diff --git a/include/asm-x86_64/page.h b/include/asm-x86_64/page.h
index 8edb69a7bc143..f43048035a033 100644
--- a/include/asm-x86_64/page.h
+++ b/include/asm-x86_64/page.h
@@ -63,10 +63,6 @@ typedef struct { unsigned long pgprot; } pgprot_t;
#define __pgd(x) ((pgd_t) { (x) } )
#define __pgprot(x) ((pgprot_t) { (x) } )
-extern unsigned long vm_stack_flags, vm_stack_flags32;
-extern unsigned long vm_data_default_flags, vm_data_default_flags32;
-extern unsigned long vm_force_exec32;
-
#define __START_KERNEL 0xffffffff80100000UL
#define __START_KERNEL_map 0xffffffff80000000UL
#define __PAGE_OFFSET 0xffff810000000000UL
diff --git a/include/asm-x86_64/pgalloc.h b/include/asm-x86_64/pgalloc.h
index cc0b2d52b1bb1..deadd146978b1 100644
--- a/include/asm-x86_64/pgalloc.h
+++ b/include/asm-x86_64/pgalloc.h
@@ -1,7 +1,6 @@
#ifndef _X86_64_PGALLOC_H
#define _X86_64_PGALLOC_H
-#include <asm/processor.h>
#include <asm/fixmap.h>
#include <asm/pda.h>
#include <linux/threads.h>
@@ -99,7 +98,8 @@ extern inline void pte_free(struct page *pte)
}
#define __pte_free_tlb(tlb,pte) tlb_remove_page((tlb),(pte))
-#define __pmd_free_tlb(tlb,x) pmd_free(x)
-#define __pud_free_tlb(tlb,x) pud_free(x)
+
+#define __pmd_free_tlb(tlb,x) tlb_remove_page((tlb),virt_to_page(x))
+#define __pud_free_tlb(tlb,x) tlb_remove_page((tlb),virt_to_page(x))
#endif /* _X86_64_PGALLOC_H */
diff --git a/include/asm-x86_64/pgtable.h b/include/asm-x86_64/pgtable.h
index 1e2cc99aebd8a..dc6b6f2604e80 100644
--- a/include/asm-x86_64/pgtable.h
+++ b/include/asm-x86_64/pgtable.h
@@ -73,6 +73,7 @@ static inline void set_pte(pte_t *dst, pte_t val)
{
pte_val(*dst) = pte_val(val);
}
+#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
static inline void set_pmd(pmd_t *dst, pmd_t val)
{
@@ -102,7 +103,7 @@ extern inline void pgd_clear (pgd_t * pgd)
#define pud_page(pud) \
((unsigned long) __va(pud_val(pud) & PHYSICAL_PAGE_MASK))
-#define ptep_get_and_clear(xp) __pte(xchg(&(xp)->pte, 0))
+#define ptep_get_and_clear(mm,addr,xp) __pte(xchg(&(xp)->pte, 0))
#define pte_same(a, b) ((a).pte == (b).pte)
#define PMD_SIZE (1UL << PMD_SHIFT)
@@ -224,7 +225,7 @@ static inline unsigned long pud_bad(pud_t pud)
#define pte_none(x) (!pte_val(x))
#define pte_present(x) (pte_val(x) & (_PAGE_PRESENT | _PAGE_PROTNONE))
-#define pte_clear(xp) do { set_pte(xp, __pte(0)); } while (0)
+#define pte_clear(mm,addr,xp) do { set_pte_at(mm, addr, xp, __pte(0)); } while (0)
#define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT)) /* FIXME: is this
right? */
@@ -263,22 +264,26 @@ extern inline pte_t pte_mkdirty(pte_t pte) { set_pte(&pte, __pte(pte_val(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; }
-static inline int ptep_test_and_clear_dirty(pte_t *ptep)
+struct vm_area_struct;
+
+static inline int ptep_test_and_clear_dirty(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
{
if (!pte_dirty(*ptep))
return 0;
return test_and_clear_bit(_PAGE_BIT_DIRTY, ptep);
}
-static inline int ptep_test_and_clear_young(pte_t *ptep)
+static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
{
if (!pte_young(*ptep))
return 0;
return test_and_clear_bit(_PAGE_BIT_ACCESSED, ptep);
}
-static inline void ptep_set_wrprotect(pte_t *ptep) { clear_bit(_PAGE_BIT_RW, ptep); }
-static inline void ptep_mkdirty(pte_t *ptep) { set_bit(_PAGE_BIT_DIRTY, ptep); }
+static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
+{
+ clear_bit(_PAGE_BIT_RW, ptep);
+}
/*
* Macro to mark a page protection value as "uncacheable".
@@ -402,6 +407,13 @@ extern int kern_addr_valid(unsigned long addr);
#define io_remap_page_range(vma, vaddr, paddr, size, prot) \
remap_pfn_range(vma, vaddr, (paddr) >> PAGE_SHIFT, size, prot)
+#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
+ remap_pfn_range(vma, vaddr, pfn, size, prot)
+
+#define MK_IOSPACE_PFN(space, pfn) (pfn)
+#define GET_IOSPACE(pfn) 0
+#define GET_PFN(pfn) (pfn)
+
#define HAVE_ARCH_UNMAPPED_AREA
#define pgtable_cache_init() do { } while (0)
@@ -419,7 +431,6 @@ extern int kern_addr_valid(unsigned long addr);
#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
#define __HAVE_ARCH_PTEP_SET_WRPROTECT
-#define __HAVE_ARCH_PTEP_MKDIRTY
#define __HAVE_ARCH_PTE_SAME
#include <asm-generic/pgtable.h>
diff --git a/include/asm-x86_64/processor.h b/include/asm-x86_64/processor.h
index 6dadc64003197..45ab74e8f1413 100644
--- a/include/asm-x86_64/processor.h
+++ b/include/asm-x86_64/processor.h
@@ -92,7 +92,6 @@ extern char ignore_irq13;
extern void identify_cpu(struct cpuinfo_x86 *);
extern void print_cpu_info(struct cpuinfo_x86 *);
extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c);
-extern void dodgy_tsc(void);
/*
* EFLAGS bits
diff --git a/include/asm-x86_64/seccomp.h b/include/asm-x86_64/seccomp.h
new file mode 100644
index 0000000000000..553af65a2287a
--- /dev/null
+++ b/include/asm-x86_64/seccomp.h
@@ -0,0 +1,24 @@
+#ifndef _ASM_SECCOMP_H
+
+#include <linux/thread_info.h>
+
+#ifdef TIF_32BIT
+#error "unexpected TIF_32BIT on x86_64"
+#else
+#define TIF_32BIT TIF_IA32
+#endif
+
+#include <linux/unistd.h>
+#include <asm/ia32_unistd.h>
+
+#define __NR_seccomp_read __NR_read
+#define __NR_seccomp_write __NR_write
+#define __NR_seccomp_exit __NR_exit
+#define __NR_seccomp_sigreturn __NR_rt_sigreturn
+
+#define __NR_seccomp_read_32 __NR_ia32_read
+#define __NR_seccomp_write_32 __NR_ia32_write
+#define __NR_seccomp_exit_32 __NR_ia32_exit
+#define __NR_seccomp_sigreturn_32 __NR_ia32_sigreturn
+
+#endif /* _ASM_SECCOMP_H */
diff --git a/include/asm-x86_64/segment.h b/include/asm-x86_64/segment.h
index 8dc82dc557fb2..44adaf18c11e3 100644
--- a/include/asm-x86_64/segment.h
+++ b/include/asm-x86_64/segment.h
@@ -24,10 +24,9 @@
#define GDT_ENTRY_TLS 1
#define GDT_ENTRY_TSS 8 /* needs two entries */
-#define GDT_ENTRY_LDT 10
-#define GDT_ENTRY_TLS_MIN 11
-#define GDT_ENTRY_TLS_MAX 13
-/* 14 free */
+#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
#define GDT_ENTRY_TLS_ENTRIES 3
diff --git a/include/asm-x86_64/suspend.h b/include/asm-x86_64/suspend.h
index 508e924b801f4..ec745807feae4 100644
--- a/include/asm-x86_64/suspend.h
+++ b/include/asm-x86_64/suspend.h
@@ -55,5 +55,4 @@ extern unsigned long saved_edi;
/* routines for saving/restoring kernel state */
extern int acpi_save_state_mem(void);
-extern int acpi_save_state_disk(void);
#endif
diff --git a/include/asm-x86_64/system.h b/include/asm-x86_64/system.h
index c1710933828f9..76165736e43a8 100644
--- a/include/asm-x86_64/system.h
+++ b/include/asm-x86_64/system.h
@@ -338,4 +338,6 @@ void enable_hlt(void);
#define HAVE_EAT_KEY
void eat_key(void);
+extern unsigned long arch_align_stack(unsigned long sp);
+
#endif
diff --git a/include/asm-x86_64/thread_info.h b/include/asm-x86_64/thread_info.h
index 255e7e66e897a..f4b3b249639c9 100644
--- a/include/asm-x86_64/thread_info.h
+++ b/include/asm-x86_64/thread_info.h
@@ -102,6 +102,7 @@ static inline struct thread_info *stack_thread_info(void)
#define TIF_SINGLESTEP 4 /* reenable singlestep on user return*/
#define TIF_IRET 5 /* force IRET */
#define TIF_SYSCALL_AUDIT 7 /* syscall auditing active */
+#define TIF_SECCOMP 8 /* secure computing */
#define TIF_POLLING_NRFLAG 16 /* true if poll_idle() is polling TIF_NEED_RESCHED */
#define TIF_IA32 17 /* 32bit process */
#define TIF_FORK 18 /* ret_from_fork */
@@ -115,6 +116,7 @@ static inline struct thread_info *stack_thread_info(void)
#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
#define _TIF_IRET (1<<TIF_IRET)
#define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT)
+#define _TIF_SECCOMP (1<<TIF_SECCOMP)
#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
#define _TIF_IA32 (1<<TIF_IA32)
#define _TIF_FORK (1<<TIF_FORK)
@@ -122,9 +124,9 @@ static inline struct thread_info *stack_thread_info(void)
/* work to do on interrupt/exception return */
#define _TIF_WORK_MASK \
- (0x0000FFFF & ~(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP))
+ (0x0000FFFF & ~(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP|_TIF_SECCOMP))
/* work to do on any return to user space */
-#define _TIF_ALLWORK_MASK 0x0000FFFF
+#define _TIF_ALLWORK_MASK (0x0000FFFF & ~_TIF_SECCOMP)
#define PREEMPT_ACTIVE 0x10000000
diff --git a/include/asm-x86_64/timex.h b/include/asm-x86_64/timex.h
index 5eb8ff3d6bbdd..34f31a18f90b5 100644
--- a/include/asm-x86_64/timex.h
+++ b/include/asm-x86_64/timex.h
@@ -16,8 +16,6 @@
typedef unsigned long long cycles_t;
-extern cycles_t cacheflush_time;
-
static inline cycles_t get_cycles (void)
{
unsigned long long ret;
diff --git a/include/asm-x86_64/uaccess.h b/include/asm-x86_64/uaccess.h
index cc37523570045..48f292752c96b 100644
--- a/include/asm-x86_64/uaccess.h
+++ b/include/asm-x86_64/uaccess.h
@@ -49,7 +49,8 @@
#define access_ok(type, addr, size) (__range_not_ok(addr,size) == 0)
-extern inline int verify_area(int type, const void __user * addr, unsigned long size)
+/* this function will go away soon - use access_ok() instead */
+extern inline int __deprecated verify_area(int type, const void __user * addr, unsigned long size)
{
return access_ok(type,addr,size) ? 0 : -EFAULT;
}
@@ -73,6 +74,7 @@ struct exception_table_entry
unsigned long insn, fixup;
};
+#define ARCH_HAS_SEARCH_EXTABLE
/*
* These are the main single-value transfer routines. They automatically
@@ -89,16 +91,11 @@ struct exception_table_entry
* accesses to the same area of user memory).
*/
-extern void __get_user_1(void);
-extern void __get_user_2(void);
-extern void __get_user_4(void);
-extern void __get_user_8(void);
-
#define __get_user_x(size,ret,x,ptr) \
__asm__ __volatile__("call __get_user_" #size \
:"=a" (ret),"=d" (x) \
- :"0" (ptr) \
- :"rbx")
+ :"c" (ptr) \
+ :"r8")
/* Careful: we have to cast the result to the type of the pointer for sign reasons */
#define get_user(x,ptr) \
@@ -120,14 +117,13 @@ extern void __put_user_1(void);
extern void __put_user_2(void);
extern void __put_user_4(void);
extern void __put_user_8(void);
-
extern void __put_user_bad(void);
#define __put_user_x(size,ret,x,ptr) \
__asm__ __volatile__("call __put_user_" #size \
:"=a" (ret) \
- :"0" (ptr),"d" (x) \
- :"rbx")
+ :"c" (ptr),"d" (x) \
+ :"r8")
#define put_user(x,ptr) \
__put_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
@@ -150,10 +146,15 @@ extern void __put_user_bad(void);
#define __put_user_check(x,ptr,size) \
({ \
- int __pu_err = -EFAULT; \
+ int __pu_err; \
__typeof__(*(ptr)) __user *__pu_addr = (ptr); \
- if (likely(access_ok(VERIFY_WRITE,__pu_addr,size))) \
- __put_user_size((x),__pu_addr,(size),__pu_err); \
+ switch (size) { \
+ case 1: __put_user_x(1,__pu_err,x,__pu_addr); break; \
+ case 2: __put_user_x(2,__pu_err,x,__pu_addr); break; \
+ case 4: __put_user_x(4,__pu_err,x,__pu_addr); break; \
+ case 8: __put_user_x(8,__pu_err,x,__pu_addr); break; \
+ default: __put_user_bad(); \
+ } \
__pu_err; \
})
@@ -204,6 +205,10 @@ struct __large_struct { unsigned long buf[100]; };
__gu_err; \
})
+extern int __get_user_1(void);
+extern int __get_user_2(void);
+extern int __get_user_4(void);
+extern int __get_user_8(void);
extern int __get_user_bad(void);
#define __get_user_size(x,ptr,size,retval) \
diff --git a/include/asm-x86_64/unistd.h b/include/asm-x86_64/unistd.h
index d0eddfd963591..a8ea0164f3ab0 100644
--- a/include/asm-x86_64/unistd.h
+++ b/include/asm-x86_64/unistd.h
@@ -774,7 +774,7 @@ asmlinkage long sys_pipe(int *fildes);
asmlinkage long sys_ptrace(long request, long pid,
unsigned long addr, long data);
-asmlinkage long sys_iopl(unsigned int level, struct pt_regs regs);
+asmlinkage long sys_iopl(unsigned int level, struct pt_regs *regs);
asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on);
struct sigaction;
asmlinkage long sys_rt_sigaction(int sig,
@@ -792,6 +792,6 @@ asmlinkage long sys_rt_sigaction(int sig,
* What we want is __attribute__((weak,alias("sys_ni_syscall"))),
* but it doesn't work on all toolchains, so we just do it by hand
*/
-#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
+#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
#endif
diff --git a/include/linux/ac97_codec.h b/include/linux/ac97_codec.h
index c3970bb88c4da..c35833824e118 100644
--- a/include/linux/ac97_codec.h
+++ b/include/linux/ac97_codec.h
@@ -323,6 +323,7 @@ struct ac97_ops
#define AC97_DELUDED_MODEM 1 /* Audio codec reports its a modem */
#define AC97_NO_PCM_VOLUME 2 /* Volume control is missing */
+#define AC97_DEFAULT_POWER_OFF 4 /* Needs warm reset to power up */
};
extern int ac97_read_proc (char *page_out, char **start, off_t off,
diff --git a/include/linux/acct.h b/include/linux/acct.h
index 39cd52f7f557a..1993a36917688 100644
--- a/include/linux/acct.h
+++ b/include/linux/acct.h
@@ -120,12 +120,12 @@ struct acct_v3
struct super_block;
extern void acct_auto_close(struct super_block *sb);
extern void acct_process(long exitcode);
-extern void acct_update_integrals(void);
+extern void acct_update_integrals(struct task_struct *tsk);
extern void acct_clear_integrals(struct task_struct *tsk);
#else
#define acct_auto_close(x) do { } while (0)
#define acct_process(x) do { } while (0)
-#define acct_update_integrals() do { } while (0)
+#define acct_update_integrals(x) do { } while (0)
#define acct_clear_integrals(task) do { } while (0)
#endif
diff --git a/include/linux/agp_backend.h b/include/linux/agp_backend.h
index 7936986c289ef..a5c8bb5d80bad 100644
--- a/include/linux/agp_backend.h
+++ b/include/linux/agp_backend.h
@@ -1,6 +1,7 @@
/*
* AGPGART backend specific includes. Not for userspace consumption.
*
+ * Copyright (C) 2004 Silicon Graphics, Inc.
* Copyright (C) 2002-2003 Dave Jones
* Copyright (C) 1999 Jeff Hartmann
* Copyright (C) 1999 Precision Insight, Inc.
@@ -54,7 +55,7 @@ struct agp_kern_info {
struct pci_dev *device;
enum chipset_type chipset;
unsigned long mode;
- off_t aper_base;
+ unsigned long aper_base;
size_t aper_size;
int max_memory; /* In pages */
int current_memory;
@@ -63,21 +64,24 @@ struct agp_kern_info {
struct vm_operations_struct *vm_ops;
};
-/*
+/*
* The agp_memory structure has information about the block of agp memory
* allocated. A caller may manipulate the next and prev pointers to link
* each allocated item into a list. These pointers are ignored by the backend.
* Everything else should never be written to, but the caller may read any of
- * the items to detrimine the status of this block of agp memory.
+ * the items to determine the status of this block of agp memory.
*/
+struct agp_bridge_data;
+
struct agp_memory {
- int key;
struct agp_memory *next;
struct agp_memory *prev;
+ struct agp_bridge_data *bridge;
+ unsigned long *memory;
size_t page_count;
+ int key;
int num_scratch_pages;
- unsigned long *memory;
off_t pg_start;
u32 type;
u32 physical;
@@ -87,14 +91,19 @@ struct agp_memory {
#define AGP_NORMAL_MEMORY 0
+extern struct agp_bridge_data *agp_bridge;
+extern struct list_head agp_bridges;
+
+extern struct agp_bridge_data *(*agp_find_bridge)(struct pci_dev *);
+
extern void agp_free_memory(struct agp_memory *);
-extern struct agp_memory *agp_allocate_memory(size_t, u32);
-extern int agp_copy_info(struct agp_kern_info *);
+extern struct agp_memory *agp_allocate_memory(struct agp_bridge_data *, size_t, u32);
+extern int agp_copy_info(struct agp_bridge_data *, struct agp_kern_info *);
extern int agp_bind_memory(struct agp_memory *, off_t);
extern int agp_unbind_memory(struct agp_memory *);
-extern void agp_enable(u32);
-extern int agp_backend_acquire(void);
-extern void agp_backend_release(void);
+extern void agp_enable(struct agp_bridge_data *, u32);
+extern struct agp_bridge_data *agp_backend_acquire(struct pci_dev *);
+extern void agp_backend_release(struct agp_bridge_data *);
#endif /* __KERNEL__ */
#endif /* _AGP_BACKEND_H */
diff --git a/include/linux/agpgart.h b/include/linux/agpgart.h
index ff4c2c058cb64..17a17c55a17f9 100644
--- a/include/linux/agpgart.h
+++ b/include/linux/agpgart.h
@@ -64,7 +64,7 @@ typedef struct _agp_info {
struct agp_version version; /* version of the driver */
__u32 bridge_id; /* bridge vendor/device */
__u32 agp_mode; /* mode info of bridge */
- off_t aper_base; /* base of aperture */
+ unsigned long aper_base;/* base of aperture */
size_t aper_size; /* size of aperture */
size_t pg_total; /* max pages (swap + system) */
size_t pg_system; /* max pages (system) */
@@ -118,7 +118,7 @@ struct agp_info {
struct agp_version version; /* version of the driver */
u32 bridge_id; /* bridge vendor/device */
u32 agp_mode; /* mode info of bridge */
- off_t aper_base; /* base of aperture */
+ unsigned long aper_base;/* base of aperture */
size_t aper_size; /* size of aperture */
size_t pg_total; /* max pages (swap + system) */
size_t pg_system; /* max pages (system) */
diff --git a/include/linux/aio_abi.h b/include/linux/aio_abi.h
index e7fc6b234efb7..30fdcc89d1421 100644
--- a/include/linux/aio_abi.h
+++ b/include/linux/aio_abi.h
@@ -2,7 +2,7 @@
*
* Copyright 2000,2001,2002 Red Hat.
*
- * Written by Benjamin LaHaise <bcrl@redhat.com>
+ * Written by Benjamin LaHaise <bcrl@kvack.org>
*
* Distribute under the terms of the GPLv2 (see ../../COPYING) or under
* the following terms.
diff --git a/include/linux/atalk.h b/include/linux/atalk.h
index 96b9dc997281d..55fcfc11fdc7b 100644
--- a/include/linux/atalk.h
+++ b/include/linux/atalk.h
@@ -1,5 +1,8 @@
#ifndef __LINUX_ATALK_H__
#define __LINUX_ATALK_H__
+
+#include <net/sock.h>
+
/*
* AppleTalk networking structures
*
@@ -63,6 +66,8 @@ struct atalk_iface {
};
struct atalk_sock {
+ /* struct sock has to be the first member of atalk_sock */
+ struct sock sk;
unsigned short dest_net;
unsigned short src_net;
unsigned char dest_node;
@@ -71,6 +76,11 @@ struct atalk_sock {
unsigned char src_port;
};
+static inline struct atalk_sock *at_sk(struct sock *sk)
+{
+ return (struct atalk_sock *)sk;
+}
+
#ifdef __KERNEL__
#include <asm/byteorder.h>
@@ -197,8 +207,6 @@ extern void aarp_proxy_remove(struct net_device *dev,
extern void aarp_cleanup_module(void);
-#define at_sk(__sk) ((struct atalk_sock *)(__sk)->sk_protinfo)
-
extern struct hlist_head atalk_sockets;
extern rwlock_t atalk_sockets_lock;
diff --git a/include/linux/atmdev.h b/include/linux/atmdev.h
index bc701ddb88e4a..9f374cfa1b05a 100644
--- a/include/linux/atmdev.h
+++ b/include/linux/atmdev.h
@@ -30,9 +30,6 @@
#define ATM_DS3_PCR (8000*12)
/* DS3: 12 cells in a 125 usec time slot */
-#define atm_sk(__sk) ((struct atm_vcc *)(__sk)->sk_protinfo)
-#define ATM_SD(s) (atm_sk((s)->sk))
-
#define __AAL_STAT_ITEMS \
__HANDLE_ITEM(tx); /* TX okay */ \
@@ -281,6 +278,8 @@ enum {
#define ATM_ATMOPT_CLP 1 /* set CLP bit */
struct atm_vcc {
+ /* struct sock has to be the first member of atm_vcc */
+ struct sock sk;
unsigned long flags; /* VCC flags (ATM_VF_*) */
short vpi; /* VPI and VCI (types must be equal */
/* with sockaddr) */
@@ -297,7 +296,6 @@ struct atm_vcc {
void *dev_data; /* per-device data */
void *proto_data; /* per-protocol data */
struct k_atm_aal_stats *stats; /* pointer to AAL stats group */
- struct sock *sk; /* socket backpointer */
/* SVC part --- may move later ------------------------------------- */
short itf; /* interface number */
struct sockaddr_atmsvc local;
@@ -310,6 +308,20 @@ struct atm_vcc {
/* by CLIP and sch_atm. */
};
+static inline struct atm_vcc *atm_sk(struct sock *sk)
+{
+ return (struct atm_vcc *)sk;
+}
+
+static inline struct atm_vcc *ATM_SD(struct socket *sock)
+{
+ return atm_sk(sock->sk);
+}
+
+static inline struct sock *sk_atm(struct atm_vcc *vcc)
+{
+ return (struct sock *)vcc;
+}
struct atm_dev_addr {
struct sockaddr_atmsvc addr; /* ATM address */
@@ -410,20 +422,20 @@ static inline int atm_guess_pdu2truesize(int size)
static inline void atm_force_charge(struct atm_vcc *vcc,int truesize)
{
- atomic_add(truesize, &vcc->sk->sk_rmem_alloc);
+ atomic_add(truesize, &sk_atm(vcc)->sk_rmem_alloc);
}
static inline void atm_return(struct atm_vcc *vcc,int truesize)
{
- atomic_sub(truesize, &vcc->sk->sk_rmem_alloc);
+ atomic_sub(truesize, &sk_atm(vcc)->sk_rmem_alloc);
}
static inline int atm_may_send(struct atm_vcc *vcc,unsigned int size)
{
- return (size + atomic_read(&vcc->sk->sk_wmem_alloc)) <
- vcc->sk->sk_sndbuf;
+ return (size + atomic_read(&sk_atm(vcc)->sk_wmem_alloc)) <
+ sk_atm(vcc)->sk_sndbuf;
}
diff --git a/include/linux/audit.h b/include/linux/audit.h
index c27b028ec3c8d..3628f7cfb1789 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -125,10 +125,9 @@ struct audit_rule { /* for AUDIT_LIST, AUDIT_ADD, and AUDIT_DEL */
#ifdef __KERNEL__
-#ifdef CONFIG_AUDIT
struct audit_buffer;
struct audit_context;
-#endif
+struct inode;
#ifdef CONFIG_AUDITSYSCALL
/* These are defined in auditsc.c */
@@ -141,7 +140,7 @@ extern void audit_syscall_entry(struct task_struct *task,
extern void audit_syscall_exit(struct task_struct *task, int return_code);
extern void audit_getname(const char *name);
extern void audit_putname(const char *name);
-extern void audit_inode(const char *name, unsigned long ino, dev_t rdev);
+extern void audit_inode(const char *name, const struct inode *inode);
/* Private API (for audit.c only) */
extern int audit_receive_filter(int type, int pid, int uid, int seq,
@@ -150,6 +149,7 @@ extern void audit_get_stamp(struct audit_context *ctx,
struct timespec *t, int *serial);
extern int audit_set_loginuid(struct audit_context *ctx, uid_t loginuid);
extern uid_t audit_get_loginuid(struct audit_context *ctx);
+extern int audit_ipc_perms(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode);
#else
#define audit_alloc(t) ({ 0; })
#define audit_free(t) do { ; } while (0)
@@ -157,8 +157,9 @@ extern uid_t audit_get_loginuid(struct audit_context *ctx);
#define audit_syscall_exit(t,r) do { ; } while (0)
#define audit_getname(n) do { ; } while (0)
#define audit_putname(n) do { ; } while (0)
-#define audit_inode(n,i,d) do { ; } while (0)
+#define audit_inode(n,i) do { ; } while (0)
#define audit_get_loginuid(c) ({ -1; })
+#define audit_ipc_perms(q,u,g,m) ({ 0; })
#endif
#ifdef CONFIG_AUDIT
@@ -173,16 +174,10 @@ extern void audit_log_format(struct audit_buffer *ab,
const char *fmt, ...)
__attribute__((format(printf,2,3)));
extern void audit_log_end(struct audit_buffer *ab);
-extern void audit_log_end_fast(struct audit_buffer *ab);
-extern void audit_log_end_irq(struct audit_buffer *ab);
extern void audit_log_d_path(struct audit_buffer *ab,
const char *prefix,
struct dentry *dentry,
struct vfsmount *vfsmnt);
-extern int audit_set_rate_limit(int limit);
-extern int audit_set_backlog_limit(int limit);
-extern int audit_set_enabled(int state);
-extern int audit_set_failure(int state);
/* Private API (for auditsc.c only) */
extern void audit_send_reply(int pid, int seq, int type,
@@ -195,13 +190,7 @@ extern void audit_log_lost(const char *message);
#define audit_log_vformat(b,f,a) do { ; } while (0)
#define audit_log_format(b,f,...) do { ; } while (0)
#define audit_log_end(b) do { ; } while (0)
-#define audit_log_end_fast(b) do { ; } while (0)
-#define audit_log_end_irq(b) do { ; } while (0)
#define audit_log_d_path(b,p,d,v) do { ; } while (0)
-#define audit_set_rate_limit(l) do { ; } while (0)
-#define audit_set_backlog_limit(l) do { ; } while (0)
-#define audit_set_enabled(s) do { ; } while (0)
-#define audit_set_failure(s) do { ; } while (0)
#endif
#endif
#endif
diff --git a/include/linux/backing-dev.h b/include/linux/backing-dev.h
index 3c369c6553e3e..f7a1390d67f5b 100644
--- a/include/linux/backing-dev.h
+++ b/include/linux/backing-dev.h
@@ -25,13 +25,39 @@ typedef int (congested_fn)(void *, int);
struct backing_dev_info {
unsigned long ra_pages; /* max readahead in PAGE_CACHE_SIZE units */
unsigned long state; /* Always use atomic bitops on this */
- int memory_backed; /* Cannot clean pages with writepage */
+ unsigned int capabilities; /* Device capabilities */
congested_fn *congested_fn; /* Function pointer if device is md/dm */
void *congested_data; /* Pointer to aux data for congested func */
void (*unplug_io_fn)(struct backing_dev_info *, struct page *);
void *unplug_io_data;
};
+
+/*
+ * Flags in backing_dev_info::capability
+ * - The first two flags control whether dirty pages will contribute to the
+ * VM's accounting and whether writepages() should be called for dirty pages
+ * (something that would not, for example, be appropriate for ramfs)
+ * - These flags let !MMU mmap() govern direct device mapping vs immediate
+ * copying more easily for MAP_PRIVATE, especially for ROM filesystems
+ */
+#define BDI_CAP_NO_ACCT_DIRTY 0x00000001 /* Dirty pages shouldn't contribute to accounting */
+#define BDI_CAP_NO_WRITEBACK 0x00000002 /* Don't write pages back */
+#define BDI_CAP_MAP_COPY 0x00000004 /* Copy can be mapped (MAP_PRIVATE) */
+#define BDI_CAP_MAP_DIRECT 0x00000008 /* Can be mapped directly (MAP_SHARED) */
+#define BDI_CAP_READ_MAP 0x00000010 /* Can be mapped for reading */
+#define BDI_CAP_WRITE_MAP 0x00000020 /* Can be mapped for writing */
+#define BDI_CAP_EXEC_MAP 0x00000040 /* Can be mapped for execution */
+#define BDI_CAP_VMFLAGS \
+ (BDI_CAP_READ_MAP | BDI_CAP_WRITE_MAP | BDI_CAP_EXEC_MAP)
+
+#if defined(VM_MAYREAD) && \
+ (BDI_CAP_READ_MAP != VM_MAYREAD || \
+ BDI_CAP_WRITE_MAP != VM_MAYWRITE || \
+ BDI_CAP_EXEC_MAP != VM_MAYEXEC)
+#error please change backing_dev_info::capabilities flags
+#endif
+
extern struct backing_dev_info default_backing_dev_info;
void default_unplug_io_fn(struct backing_dev_info *bdi, struct page *page);
@@ -62,4 +88,17 @@ static inline int bdi_rw_congested(struct backing_dev_info *bdi)
(1 << BDI_write_congested));
}
+#define bdi_cap_writeback_dirty(bdi) \
+ (!((bdi)->capabilities & BDI_CAP_NO_WRITEBACK))
+
+#define bdi_cap_account_dirty(bdi) \
+ (!((bdi)->capabilities & BDI_CAP_NO_ACCT_DIRTY))
+
+#define mapping_cap_writeback_dirty(mapping) \
+ bdi_cap_writeback_dirty((mapping)->backing_dev_info)
+
+#define mapping_cap_account_dirty(mapping) \
+ bdi_cap_account_dirty((mapping)->backing_dev_info)
+
+
#endif /* _LINUX_BACKING_DEV_H */
diff --git a/include/linux/bio.h b/include/linux/bio.h
index cd8d47bf34b48..038022763f095 100644
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
@@ -59,6 +59,7 @@ struct bio_vec {
unsigned int bv_offset;
};
+struct bio_set;
struct bio;
typedef int (bio_end_io_t) (struct bio *, unsigned int, int);
typedef void (bio_destructor_t) (struct bio *);
@@ -109,6 +110,7 @@ struct bio {
void *bi_private;
bio_destructor_t *bi_destructor; /* destructor */
+ struct bio_set *bi_set; /* memory pools set */
};
/*
@@ -258,7 +260,11 @@ extern struct bio_pair *bio_split(struct bio *bi, mempool_t *pool,
extern mempool_t *bio_split_pool;
extern void bio_pair_release(struct bio_pair *dbio);
-extern struct bio *bio_alloc(int, int);
+extern struct bio_set *bioset_create(int, int, int);
+extern void bioset_free(struct bio_set *);
+
+extern struct bio *bio_alloc(unsigned int __nocast, int);
+extern struct bio *bio_alloc_bioset(unsigned int __nocast, int, struct bio_set *);
extern void bio_put(struct bio *);
extern void bio_endio(struct bio *, unsigned int, int);
@@ -267,7 +273,7 @@ extern int bio_phys_segments(struct request_queue *, struct bio *);
extern int bio_hw_segments(struct request_queue *, struct bio *);
extern void __bio_clone(struct bio *, struct bio *);
-extern struct bio *bio_clone(struct bio *, int);
+extern struct bio *bio_clone(struct bio *, unsigned int __nocast);
extern void bio_init(struct bio *);
@@ -280,6 +286,7 @@ extern void bio_set_pages_dirty(struct bio *bio);
extern void bio_check_pages_dirty(struct bio *bio);
extern struct bio *bio_copy_user(struct request_queue *, unsigned long, unsigned int, int);
extern int bio_uncopy_user(struct bio *);
+void zero_fill_bio(struct bio *bio);
#ifdef CONFIG_HIGHMEM
/*
diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h
index 77401c15510bb..86dd5502b05c0 100644
--- a/include/linux/bitmap.h
+++ b/include/linux/bitmap.h
@@ -41,7 +41,9 @@
* bitmap_shift_right(dst, src, n, nbits) *dst = *src >> n
* bitmap_shift_left(dst, src, n, nbits) *dst = *src << n
* bitmap_scnprintf(buf, len, src, nbits) Print bitmap src to buf
- * bitmap_parse(ubuf, ulen, dst, nbits) Parse bitmap dst from buf
+ * bitmap_parse(ubuf, ulen, dst, nbits) Parse bitmap dst from user buf
+ * bitmap_scnlistprintf(buf, len, src, nbits) Print bitmap src as list to buf
+ * bitmap_parselist(buf, dst, nbits) Parse bitmap dst from list
*/
/*
@@ -98,6 +100,10 @@ extern int bitmap_scnprintf(char *buf, unsigned int len,
const unsigned long *src, int nbits);
extern int bitmap_parse(const char __user *ubuf, unsigned int ulen,
unsigned long *dst, int nbits);
+extern int bitmap_scnlistprintf(char *buf, unsigned int len,
+ const unsigned long *src, int nbits);
+extern int bitmap_parselist(const char *buf, unsigned long *maskp,
+ int nmaskbits);
extern int bitmap_find_free_region(unsigned long *bitmap, int bits, int order);
extern void bitmap_release_region(unsigned long *bitmap, int pos, int order);
extern int bitmap_allocate_region(unsigned long *bitmap, int pos, int order);
diff --git a/include/linux/bitops.h b/include/linux/bitops.h
index 48f87b979ca98..cb3c3ef50f504 100644
--- a/include/linux/bitops.h
+++ b/include/linux/bitops.h
@@ -134,4 +134,26 @@ static inline unsigned long hweight_long(unsigned long w)
return sizeof(w) == 4 ? generic_hweight32(w) : generic_hweight64(w);
}
+/*
+ * rol32 - rotate a 32-bit value left
+ *
+ * @word: value to rotate
+ * @shift: bits to roll
+ */
+static inline __u32 rol32(__u32 word, unsigned int shift)
+{
+ return (word << shift) | (word >> (32 - shift));
+}
+
+/*
+ * ror32 - rotate a 32-bit value right
+ *
+ * @word: value to rotate
+ * @shift: bits to roll
+ */
+static inline __u32 ror32(__u32 word, unsigned int shift)
+{
+ return (word >> shift) | (word << (32 - shift));
+}
+
#endif
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 5615a3c9e4104..70ac2860a6053 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -93,6 +93,9 @@ struct io_context *get_io_context(int gfp_flags);
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 *);
+
struct request_list {
int count[2];
int starved[2];
@@ -176,6 +179,12 @@ struct request {
* For Power Management requests
*/
struct request_pm_state *pm;
+
+ /*
+ * completion callback. end_io_data should be folded in with waiting
+ */
+ rq_end_io_fn *end_io;
+ void *end_io_data;
};
/*
@@ -210,6 +219,7 @@ enum rq_flag_bits {
__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_NR_BITS, /* stops here */
};
@@ -237,6 +247,7 @@ enum rq_flag_bits {
#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)
/*
* State information carried for REQ_PM_SUSPEND and REQ_PM_RESUME
@@ -266,6 +277,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 *);
enum blk_queue_state {
Queue_down,
@@ -309,6 +322,8 @@ struct request_queue
merge_bvec_fn *merge_bvec_fn;
activity_fn *activity_fn;
issue_flush_fn *issue_flush_fn;
+ prepare_flush_fn *prepare_flush_fn;
+ end_flush_fn *end_flush_fn;
/*
* Auto-unplugging state
@@ -332,7 +347,7 @@ struct request_queue
* queue needs bounce pages for pages above this limit
*/
unsigned long bounce_pfn;
- int bounce_gfp;
+ unsigned int bounce_gfp;
/*
* various queue flags, see QUEUE_* below
@@ -380,6 +395,18 @@ struct request_queue
unsigned int sg_reserved_size;
struct list_head drain_list;
+
+ /*
+ * reserved for flush operations
+ */
+ struct request *flush_rq;
+ unsigned char ordered;
+};
+
+enum {
+ QUEUE_ORDERED_NONE,
+ QUEUE_ORDERED_TAG,
+ QUEUE_ORDERED_FLUSH,
};
#define RQ_INACTIVE (-1)
@@ -396,12 +423,13 @@ struct request_queue
#define QUEUE_FLAG_DEAD 5 /* queue being torn down */
#define QUEUE_FLAG_REENTER 6 /* Re-entrancy avoidance */
#define QUEUE_FLAG_PLUGGED 7 /* queue is plugged */
-#define QUEUE_FLAG_ORDERED 8 /* supports ordered writes */
-#define QUEUE_FLAG_DRAIN 9 /* draining queue for sched switch */
+#define QUEUE_FLAG_DRAIN 8 /* draining queue for sched switch */
+#define QUEUE_FLAG_FLUSH 9 /* doing barrier flush sequence */
#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_fs_request(rq) ((rq)->flags & REQ_CMD)
#define blk_pc_request(rq) ((rq)->flags & REQ_BLOCK_PC)
@@ -509,10 +537,10 @@ 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_attempt_remerge(request_queue_t *, struct request *);
extern struct request *blk_get_request(request_queue_t *, int, int);
-extern void blk_put_request(struct request *);
extern void blk_insert_request(request_queue_t *, struct request *, int, void *, int);
extern void blk_requeue_request(request_queue_t *, struct request *);
extern void blk_plug_device(request_queue_t *);
@@ -602,6 +630,9 @@ extern struct backing_dev_info *blk_get_backing_dev_info(struct block_device *bd
extern void blk_queue_ordered(request_queue_t *, int);
extern void blk_queue_issue_flush_fn(request_queue_t *, issue_flush_fn *);
extern int blkdev_scsi_issue_flush_fn(request_queue_t *, struct gendisk *, sector_t *);
+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_rq_map_sg(request_queue_t *, struct request *, struct scatterlist *);
extern void blk_dump_rq_flags(struct request *, char *);
diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h
index f388b513df754..802c91e9b3da8 100644
--- a/include/linux/buffer_head.h
+++ b/include/linux/buffer_head.h
@@ -169,7 +169,7 @@ void __brelse(struct buffer_head *);
void __bforget(struct buffer_head *);
void __breadahead(struct block_device *, sector_t block, int size);
struct buffer_head *__bread(struct block_device *, sector_t block, int size);
-struct buffer_head *alloc_buffer_head(int gfp_flags);
+struct buffer_head *alloc_buffer_head(unsigned int __nocast gfp_flags);
void free_buffer_head(struct buffer_head * bh);
void FASTCALL(unlock_buffer(struct buffer_head *bh));
void FASTCALL(__lock_buffer(struct buffer_head *bh));
@@ -203,6 +203,9 @@ int file_fsync(struct file *, struct dentry *, int);
int nobh_prepare_write(struct page*, unsigned, unsigned, get_block_t*);
int nobh_commit_write(struct file *, struct page *, unsigned, unsigned);
int nobh_truncate_page(struct address_space *, loff_t);
+int nobh_writepage(struct page *page, get_block_t *get_block,
+ struct writeback_control *wbc);
+
/*
* inline definitions
diff --git a/include/linux/capability.h b/include/linux/capability.h
index 5df11c20ed26a..8d139f4acf23b 100644
--- a/include/linux/capability.h
+++ b/include/linux/capability.h
@@ -44,8 +44,6 @@ typedef struct __user_cap_data_struct {
#include <linux/spinlock.h>
-extern spinlock_t task_capability_lock;
-
/* #define STRICT_CAP_T_TYPECHECKS */
#ifdef STRICT_CAP_T_TYPECHECKS
diff --git a/include/linux/compat.h b/include/linux/compat.h
index f67748fda899d..b58b7d6f2fdb9 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -83,6 +83,12 @@ struct compat_rusage {
extern int put_compat_rusage(const struct rusage *, struct compat_rusage __user *);
+struct compat_siginfo;
+
+extern asmlinkage long compat_sys_waitid(int, compat_pid_t,
+ struct compat_siginfo __user *, int,
+ struct compat_rusage __user *);
+
struct compat_dirent {
u32 d_ino;
compat_off_t d_off;
@@ -95,12 +101,14 @@ typedef union compat_sigval {
compat_uptr_t sival_ptr;
} compat_sigval_t;
+#define COMPAT_SIGEV_PAD_SIZE ((SIGEV_MAX_SIZE/sizeof(int)) - 3)
+
typedef struct compat_sigevent {
compat_sigval_t sigev_value;
compat_int_t sigev_signo;
compat_int_t sigev_notify;
union {
- compat_int_t _pad[SIGEV_PAD_SIZE];
+ compat_int_t _pad[COMPAT_SIGEV_PAD_SIZE];
compat_int_t _tid;
struct {
@@ -145,8 +153,10 @@ long compat_get_bitmap(unsigned long *mask, compat_ulong_t __user *umask,
unsigned long bitmap_size);
long compat_put_bitmap(compat_ulong_t __user *umask, unsigned long *mask,
unsigned long bitmap_size);
-struct compat_siginfo;
int copy_siginfo_from_user32(siginfo_t *to, struct compat_siginfo __user *from);
int copy_siginfo_to_user32(struct compat_siginfo __user *to, siginfo_t *from);
+int get_compat_sigevent(struct sigevent *event,
+ const struct compat_sigevent __user *u_event);
+
#endif /* CONFIG_COMPAT */
#endif /* _LINUX_COMPAT_H */
diff --git a/include/linux/compat_ioctl.h b/include/linux/compat_ioctl.h
index 383275bf924ea..70a4ebb5d964e 100644
--- a/include/linux/compat_ioctl.h
+++ b/include/linux/compat_ioctl.h
@@ -16,6 +16,7 @@ COMPATIBLE_IOCTL(TCSETA)
COMPATIBLE_IOCTL(TCSETAW)
COMPATIBLE_IOCTL(TCSETAF)
COMPATIBLE_IOCTL(TCSBRK)
+ULONG_IOCTL(TCSBRKP)
COMPATIBLE_IOCTL(TCXONC)
COMPATIBLE_IOCTL(TCFLSH)
COMPATIBLE_IOCTL(TCGETS)
@@ -692,6 +693,9 @@ COMPATIBLE_IOCTL(USBDEVFS_RELEASEINTERFACE)
COMPATIBLE_IOCTL(USBDEVFS_CONNECTINFO)
COMPATIBLE_IOCTL(USBDEVFS_HUB_PORTINFO)
COMPATIBLE_IOCTL(USBDEVFS_RESET)
+COMPATIBLE_IOCTL(USBDEVFS_SUBMITURB32)
+COMPATIBLE_IOCTL(USBDEVFS_REAPURB32)
+COMPATIBLE_IOCTL(USBDEVFS_REAPURBNDELAY32)
COMPATIBLE_IOCTL(USBDEVFS_CLEAR_HALT)
/* MTD */
COMPATIBLE_IOCTL(MEMGETINFO)
diff --git a/include/linux/compiler-gcc3.h b/include/linux/compiler-gcc3.h
index eec2f88c4301b..a6fa615afab5d 100644
--- a/include/linux/compiler-gcc3.h
+++ b/include/linux/compiler-gcc3.h
@@ -10,7 +10,7 @@
#endif
#if __GNUC_MINOR__ > 0
-# define __deprecated __attribute__((deprecated))
+# define __deprecated __attribute__((deprecated))
#endif
#if __GNUC_MINOR__ >= 3
@@ -23,12 +23,10 @@
#define __attribute_const__ __attribute__((__const__))
#if __GNUC_MINOR__ >= 1
-#define noinline __attribute__((noinline))
+#define noinline __attribute__((noinline))
#endif
+
#if __GNUC_MINOR__ >= 4
-#define __must_check __attribute__((warn_unused_result))
+#define __must_check __attribute__((warn_unused_result))
#endif
-#if __GNUC_MINOR__ >= 5
-#define __compiler_offsetof(a,b) __builtin_offsetof(a,b)
-#endif
diff --git a/include/linux/compiler-gcc+.h b/include/linux/compiler-gcc4.h
index 6b9308541dcd3..53686c037a062 100644
--- a/include/linux/compiler-gcc+.h
+++ b/include/linux/compiler-gcc4.h
@@ -1,9 +1,6 @@
/* Never include this file directly. Include <linux/compiler.h> instead. */
-/*
- * These definitions are for Ueber-GCC: always newer than the latest
- * version and hence sporting everything plus a kitchen-sink.
- */
+/* These definitions are for GCC v4.x. */
#include <linux/compiler-gcc.h>
#define inline inline __attribute__((always_inline))
@@ -13,4 +10,7 @@
#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)
+
diff --git a/include/linux/compiler.h b/include/linux/compiler.h
index 0fd06b0298472..487725cf0d0d4 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -8,6 +8,7 @@
# define __kernel /* default address space */
# define __safe __attribute__((safe))
# define __force __attribute__((force))
+# define __nocast __attribute__((nocast))
# define __iomem __attribute__((noderef, address_space(2)))
# define __acquires(x) __attribute__((context(0,1)))
# define __releases(x) __attribute__((context(1,0)))
@@ -21,6 +22,7 @@ extern void __chk_io_ptr(void __iomem *);
# define __kernel
# define __safe
# define __force
+# define __nocast
# define __iomem
# define __chk_user_ptr(x) (void)0
# define __chk_io_ptr(x) (void)0
@@ -34,8 +36,10 @@ extern void __chk_io_ptr(void __iomem *);
#ifdef __KERNEL__
-#if __GNUC__ > 3
-# include <linux/compiler-gcc+.h> /* catch-all for GCC 4, 5, etc. */
+#if __GNUC__ > 4
+#error no compiler-gcc.h file for this gcc version
+#elif __GNUC__ == 4
+# include <linux/compiler-gcc4.h>
#elif __GNUC__ == 3
# include <linux/compiler-gcc3.h>
#elif __GNUC__ == 2
@@ -72,10 +76,10 @@ extern void __chk_io_ptr(void __iomem *);
(typeof(ptr)) (__ptr + (off)); })
#endif
-#endif /* __ASSEMBLY__ */
-
#endif /* __KERNEL__ */
+#endif /* __ASSEMBLY__ */
+
/*
* Allow us to mark functions as 'deprecated' and have gcc emit a nice
* warning for each use, in hopes of speeding the functions removal.
diff --git a/include/linux/console.h b/include/linux/console.h
index 99fd8e4be694a..721371382ae5f 100644
--- a/include/linux/console.h
+++ b/include/linux/console.h
@@ -59,7 +59,6 @@ struct consw {
extern const struct consw *conswitchp;
extern const struct consw dummy_con; /* dummy console buffer */
-extern const struct consw fb_con; /* frame buffer based console */
extern const struct consw vga_con; /* VGA text console */
extern const struct consw newport_con; /* SGI Newport console */
extern const struct consw prom_con; /* SPARC PROM console */
@@ -77,13 +76,17 @@ void give_up_console(const struct consw *sw);
#define CM_MOVE (3)
/*
- * The interface for a console, or any other device that
- * wants to capture console messages (printer driver?)
+ * The interface for a console, or any other device that wants to capture
+ * console messages (printer driver?)
+ *
+ * If a console driver is marked CON_BOOT then it will be auto-unregistered
+ * when the first real console is registered. This is for early-printk drivers.
*/
#define CON_PRINTBUFFER (1)
#define CON_CONSDEV (2) /* Last on the command line */
#define CON_ENABLED (4)
+#define CON_BOOT (8)
struct console
{
diff --git a/include/linux/console_struct.h b/include/linux/console_struct.h
index 062049ca5c443..725be90ef55ec 100644
--- a/include/linux/console_struct.h
+++ b/include/linux/console_struct.h
@@ -26,6 +26,7 @@ struct vc_data {
const struct consw *vc_sw;
unsigned short *vc_screenbuf; /* In-memory character/attribute buffer */
unsigned int vc_screenbuf_size;
+ unsigned char vc_mode; /* KD_TEXT, ... */
/* attributes for all characters on screen */
unsigned char vc_attr; /* Current attributes */
unsigned char vc_def_color; /* Default colors */
@@ -48,6 +49,11 @@ struct vc_data {
unsigned int vc_state; /* Escape sequence parser state */
unsigned int vc_npar,vc_par[NPAR]; /* Parameters of current escape sequence */
struct tty_struct *vc_tty; /* TTY we are attached to */
+ /* data for manual vt switching */
+ struct vt_mode vt_mode;
+ int vt_pid;
+ int vt_newvt;
+ wait_queue_head_t paste_wait;
/* mode flags */
unsigned int vc_charset : 1; /* Character set G0 / G1 */
unsigned int vc_s_charset : 1; /* Saved character set */
@@ -89,7 +95,6 @@ struct vc_data {
struct vc_data **vc_display_fg; /* [!] Ptr to var holding fg console for this display */
unsigned long vc_uni_pagedir;
unsigned long *vc_uni_pagedir_loc; /* [!] Location of uni_pagedir variable for this console */
- struct vt_struct *vc_vt;
/* additional information is in vt_kern.h */
};
diff --git a/include/linux/consolemap.h b/include/linux/consolemap.h
index dee4b654c5898..65842efc1b70f 100644
--- a/include/linux/consolemap.h
+++ b/include/linux/consolemap.h
@@ -11,5 +11,5 @@
struct vc_data;
extern unsigned char inverse_translate(struct vc_data *conp, int glyph);
-extern unsigned short *set_translate(int m,int currcons);
+extern unsigned short *set_translate(int m, struct vc_data *vc);
extern int conv_uni_to_pc(struct vc_data *conp, long ucs);
diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h
index 8ccf5487ca997..b15826f6e3a27 100644
--- a/include/linux/cpumask.h
+++ b/include/linux/cpumask.h
@@ -10,6 +10,8 @@
*
* For details of cpumask_scnprintf() and cpumask_parse(),
* see bitmap_scnprintf() and bitmap_parse() in lib/bitmap.c.
+ * For details of cpulist_scnprintf() and cpulist_parse(), see
+ * bitmap_scnlistprintf() and bitmap_parselist(), also in bitmap.c.
*
* The available cpumask operations are:
*
@@ -46,6 +48,8 @@
*
* int cpumask_scnprintf(buf, len, mask) Format cpumask for printing
* int cpumask_parse(ubuf, ulen, mask) Parse ascii string as cpumask
+ * int cpulist_scnprintf(buf, len, mask) Format cpumask as list for printing
+ * int cpulist_parse(buf, map) Parse ascii string as cpulist
*
* for_each_cpu_mask(cpu, mask) for-loop cpu over mask
*
@@ -268,14 +272,28 @@ static inline int __cpumask_scnprintf(char *buf, int len,
return bitmap_scnprintf(buf, len, srcp->bits, nbits);
}
-#define cpumask_parse(ubuf, ulen, src) \
- __cpumask_parse((ubuf), (ulen), &(src), NR_CPUS)
+#define cpumask_parse(ubuf, ulen, dst) \
+ __cpumask_parse((ubuf), (ulen), &(dst), NR_CPUS)
static inline int __cpumask_parse(const char __user *buf, int len,
cpumask_t *dstp, int nbits)
{
return bitmap_parse(buf, len, dstp->bits, nbits);
}
+#define cpulist_scnprintf(buf, len, src) \
+ __cpulist_scnprintf((buf), (len), &(src), NR_CPUS)
+static inline int __cpulist_scnprintf(char *buf, int len,
+ const cpumask_t *srcp, int nbits)
+{
+ return bitmap_scnlistprintf(buf, len, srcp->bits, nbits);
+}
+
+#define cpulist_parse(buf, dst) __cpulist_parse((buf), &(dst), NR_CPUS)
+static inline int __cpulist_parse(const char *buf, cpumask_t *dstp, int nbits)
+{
+ return bitmap_parselist(buf, dstp->bits, nbits);
+}
+
#if NR_CPUS > 1
#define for_each_cpu_mask(cpu, mask) \
for ((cpu) = first_cpu(mask); \
diff --git a/include/linux/cpuset.h b/include/linux/cpuset.h
new file mode 100644
index 0000000000000..2d9a500d994d6
--- /dev/null
+++ b/include/linux/cpuset.h
@@ -0,0 +1,64 @@
+#ifndef _LINUX_CPUSET_H
+#define _LINUX_CPUSET_H
+/*
+ * cpuset interface
+ *
+ * Copyright (C) 2003 BULL SA
+ * Copyright (C) 2004 Silicon Graphics, Inc.
+ *
+ */
+
+#include <linux/sched.h>
+#include <linux/cpumask.h>
+#include <linux/nodemask.h>
+
+#ifdef CONFIG_CPUSETS
+
+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 const cpumask_t cpuset_cpus_allowed(const 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);
+int cpuset_zonelist_valid_mems_allowed(struct zonelist *zl);
+int cpuset_zone_allowed(struct zone *z);
+extern struct file_operations proc_cpuset_operations;
+extern char *cpuset_task_status_allowed(struct task_struct *task, char *buffer);
+
+#else /* !CONFIG_CPUSETS */
+
+static inline int cpuset_init(void) { return 0; }
+static inline void cpuset_init_smp(void) {}
+static inline void cpuset_fork(struct task_struct *p) {}
+static inline void cpuset_exit(struct task_struct *p) {}
+
+static inline cpumask_t cpuset_cpus_allowed(struct task_struct *p)
+{
+ return cpu_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 int cpuset_zonelist_valid_mems_allowed(struct zonelist *zl)
+{
+ return 1;
+}
+
+static inline int cpuset_zone_allowed(struct zone *z)
+{
+ return 1;
+}
+
+static inline char *cpuset_task_status_allowed(struct task_struct *task,
+ char *buffer)
+{
+ return buffer;
+}
+
+#endif /* !CONFIG_CPUSETS */
+
+#endif /* _LINUX_CPUSET_H */
diff --git a/include/linux/cryptohash.h b/include/linux/cryptohash.h
new file mode 100644
index 0000000000000..c118b2ad98070
--- /dev/null
+++ b/include/linux/cryptohash.h
@@ -0,0 +1,12 @@
+#ifndef __CRYPTOHASH_H
+#define __CRYPTOHASH_H
+
+#define SHA_DIGEST_WORDS 5
+#define SHA_WORKSPACE_WORDS 80
+
+void sha_init(__u32 *buf);
+void sha_transform(__u32 *digest, const char *data, __u32 *W);
+
+__u32 half_md4_transform(__u32 buf[4], __u32 const in[8]);
+
+#endif
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index 2da76867183c6..50be290d24d27 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -162,17 +162,16 @@ extern spinlock_t dcache_lock;
* d_drop - drop a dentry
* @dentry: dentry to drop
*
- * d_drop() unhashes the entry from the parent
- * dentry hashes, so that it won't be found through
- * a VFS lookup any more. Note that this is different
- * from deleting the dentry - d_delete will try to
- * mark the dentry negative if possible, giving a
- * successful _negative_ lookup, while d_drop will
+ * d_drop() unhashes the entry from the parent dentry hashes, so that it won't
+ * be found through a VFS lookup any more. Note that this is different from
+ * deleting the dentry - d_delete will try to mark the dentry negative if
+ * possible, giving a successful _negative_ lookup, while d_drop will
* just make the cache lookup fail.
*
- * d_drop() is used mainly for stuff that wants
- * to invalidate a dentry for some reason (NFS
- * timeouts or autofs deletes).
+ * d_drop() is used mainly for stuff that wants to invalidate a dentry for some
+ * reason (NFS timeouts or autofs deletes).
+ *
+ * __d_drop requires dentry->d_lock.
*/
static inline void __d_drop(struct dentry *dentry)
@@ -186,7 +185,9 @@ static inline void __d_drop(struct dentry *dentry)
static inline void d_drop(struct dentry *dentry)
{
spin_lock(&dcache_lock);
+ spin_lock(&dentry->d_lock);
__d_drop(dentry);
+ spin_unlock(&dentry->d_lock);
spin_unlock(&dcache_lock);
}
diff --git a/include/linux/debugfs.h b/include/linux/debugfs.h
index 6dc7e3eca1885..f7a7b86f6eef5 100644
--- a/include/linux/debugfs.h
+++ b/include/linux/debugfs.h
@@ -15,6 +15,8 @@
#ifndef _DEBUGFS_H_
#define _DEBUGFS_H_
+#include <linux/fs.h>
+
#if defined(CONFIG_DEBUG_FS)
struct dentry *debugfs_create_file(const char *name, mode_t mode,
struct dentry *parent, void *data,
diff --git a/include/linux/device.h b/include/linux/device.h
index 786e1591102b7..cf470459fa691 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -15,7 +15,6 @@
#include <linux/ioport.h>
#include <linux/kobject.h>
#include <linux/list.h>
-#include <linux/spinlock.h>
#include <linux/types.h>
#include <linux/module.h>
#include <linux/pm.h>
@@ -102,7 +101,7 @@ struct device_driver {
char * name;
struct bus_type * bus;
- struct semaphore unload_sem;
+ struct completion unloaded;
struct kobject kobj;
struct list_head devices;
@@ -111,7 +110,7 @@ struct device_driver {
int (*probe) (struct device * dev);
int (*remove) (struct device * dev);
void (*shutdown) (struct device * dev);
- int (*suspend) (struct device * dev, u32 state, u32 level);
+ int (*suspend) (struct device * dev, pm_message_t state, u32 level);
int (*resume) (struct device * dev, u32 level);
};
@@ -148,6 +147,7 @@ struct class {
struct subsystem subsys;
struct list_head children;
struct list_head interfaces;
+ struct semaphore sem; /* locks both the children and interfaces lists */
struct class_attribute * class_attrs;
struct class_device_attribute * class_dev_attrs;
@@ -184,6 +184,7 @@ struct class_device {
struct kobject kobj;
struct class * class; /* required */
+ dev_t devt; /* dev_t, creates the sysfs "dev" */
struct device * dev; /* not necessary, but nice to have */
void * class_data; /* class-specific data */
diff --git a/include/linux/dp83840.h b/include/linux/dp83840.h
deleted file mode 100644
index 1ca8e5754608b..0000000000000
--- a/include/linux/dp83840.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * linux/dp83840.h: definitions for DP83840 MII-compatible transceivers
- *
- * Copyright (C) 1996, 1999 David S. Miller (davem@redhat.com)
- */
-#ifndef __LINUX_DP83840_H
-#define __LINUX_DP83840_H
-
-#include <linux/mii.h>
-
-/*
- * Data sheets and programming docs for the DP83840 are available at
- * from http://www.national.com/
- *
- * The DP83840 is capable of both 10 and 100Mbps ethernet, in both
- * half and full duplex mode. It also supports auto negotiation.
- *
- * But.... THIS THING IS A PAIN IN THE ASS TO PROGRAM!
- * Debugging eeprom burnt code is more fun than programming this chip!
- */
-
-/* First, the MII register numbers (actually DP83840 register numbers). */
-#define MII_CSCONFIG 0x17 /* CS configuration */
-
-/* The Carrier Sense config register. */
-#define CSCONFIG_RESV1 0x0001 /* Unused... */
-#define CSCONFIG_LED4 0x0002 /* Pin for full-dplx LED4 */
-#define CSCONFIG_LED1 0x0004 /* Pin for conn-status LED1 */
-#define CSCONFIG_RESV2 0x0008 /* Unused... */
-#define CSCONFIG_TCVDISAB 0x0010 /* Turns off the transceiver */
-#define CSCONFIG_DFBYPASS 0x0020 /* Bypass disconnect function */
-#define CSCONFIG_GLFORCE 0x0040 /* Good link force for 100mbps */
-#define CSCONFIG_CLKTRISTATE 0x0080 /* Tristate 25m clock */
-#define CSCONFIG_RESV3 0x0700 /* Unused... */
-#define CSCONFIG_ENCODE 0x0800 /* 1=MLT-3, 0=binary */
-#define CSCONFIG_RENABLE 0x1000 /* Repeater mode enable */
-#define CSCONFIG_TCDISABLE 0x2000 /* Disable timeout counter */
-#define CSCONFIG_RESV4 0x4000 /* Unused... */
-#define CSCONFIG_NDISABLE 0x8000 /* Disable NRZI */
-
-#endif /* __LINUX_DP83840_H */
diff --git a/include/linux/dqblk_xfs.h b/include/linux/dqblk_xfs.h
index bf2d657651898..cb31719ee192b 100644
--- a/include/linux/dqblk_xfs.h
+++ b/include/linux/dqblk_xfs.h
@@ -28,6 +28,12 @@
*/
#define XQM_CMD(x) (('X'<<8)+(x)) /* note: forms first QCMD argument */
+#define XQM_COMMAND(x) (((x) & (0xff<<8)) == ('X'<<8)) /* test if for XFS */
+
+#define XQM_USRQUOTA 0 /* system call user quota type */
+#define XQM_GRPQUOTA 1 /* system call group quota type */
+#define XQM_MAXQUOTAS 2
+
#define Q_XQUOTAON XQM_CMD(1) /* enable accounting/enforcement */
#define Q_XQUOTAOFF XQM_CMD(2) /* disable accounting/enforcement */
#define Q_XGETQUOTA XQM_CMD(3) /* get disk limits and usage */
diff --git a/include/linux/dvb/audio.h b/include/linux/dvb/audio.h
index 58956c3bba529..cc314443f1c4e 100644
--- a/include/linux/dvb/audio.h
+++ b/include/linux/dvb/audio.h
@@ -1,9 +1,9 @@
-/*
+/*
* audio.h
*
* Copyright (C) 2000 Ralph Metzler <ralph@convergence.de>
* & Marcus Metzler <marcus@convergence.de>
- for convergence integrated media GmbH
+ * for convergence integrated media GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Lesser Public License
@@ -32,35 +32,35 @@
typedef enum {
- AUDIO_SOURCE_DEMUX, /* Select the demux as the main source */
- AUDIO_SOURCE_MEMORY /* Select internal memory as the main source */
+ AUDIO_SOURCE_DEMUX, /* Select the demux as the main source */
+ AUDIO_SOURCE_MEMORY /* Select internal memory as the main source */
} audio_stream_source_t;
-typedef enum {
- AUDIO_STOPPED, /* Device is stopped */
- AUDIO_PLAYING, /* Device is currently playing */
- AUDIO_PAUSED /* Device is paused */
+typedef enum {
+ AUDIO_STOPPED, /* Device is stopped */
+ AUDIO_PLAYING, /* Device is currently playing */
+ AUDIO_PAUSED /* Device is paused */
} audio_play_state_t;
typedef enum {
AUDIO_STEREO,
- AUDIO_MONO_LEFT,
- AUDIO_MONO_RIGHT
+ AUDIO_MONO_LEFT,
+ AUDIO_MONO_RIGHT
} audio_channel_select_t;
-typedef struct audio_mixer {
+typedef struct audio_mixer {
unsigned int volume_left;
unsigned int volume_right;
// what else do we need? bass, pass-through, ...
} audio_mixer_t;
-typedef struct audio_status {
+typedef struct audio_status {
int AV_sync_state; /* sync audio and video? */
- int mute_state; /* audio is muted */
+ int mute_state; /* audio is muted */
audio_play_state_t play_state; /* current playback state */
audio_stream_source_t stream_source; /* current stream source */
audio_channel_select_t channel_select; /* currently selected channel */
@@ -88,7 +88,7 @@ typedef uint16_t audio_attributes_t;
/* 7- 6 Quantization / DRC (mpeg audio: 1=DRC exists)(lpcm: 0=16bit, */
/* 5- 4 Sample frequency fs (0=48kHz, 1=96kHz) */
/* 2- 0 number of audio channels (n+1 channels) */
-
+
/* for GET_CAPABILITIES and SET_FORMAT, the latter should only set one bit */
#define AUDIO_CAP_DTS 1
@@ -101,7 +101,7 @@ typedef uint16_t audio_attributes_t;
#define AUDIO_CAP_SDDS 128
#define AUDIO_CAP_AC3 256
-#define AUDIO_STOP _IO('o', 1)
+#define AUDIO_STOP _IO('o', 1)
#define AUDIO_PLAY _IO('o', 2)
#define AUDIO_PAUSE _IO('o', 3)
#define AUDIO_CONTINUE _IO('o', 4)
@@ -122,4 +122,3 @@ typedef uint16_t audio_attributes_t;
#define AUDIO_SET_KARAOKE _IOW('o', 18, audio_karaoke_t)
#endif /* _DVBAUDIO_H_ */
-
diff --git a/include/linux/dvb/ca.h b/include/linux/dvb/ca.h
index 026e5c35c0ab0..558af0cc76927 100644
--- a/include/linux/dvb/ca.h
+++ b/include/linux/dvb/ca.h
@@ -1,9 +1,9 @@
-/*
+/*
* ca.h
*
* Copyright (C) 2000 Ralph Metzler <ralph@convergence.de>
* & Marcus Metzler <marcus@convergence.de>
- for convergence integrated media GmbH
+ * for convergence integrated media GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Lesser Public License
@@ -88,4 +88,3 @@ typedef struct ca_pid {
#define CA_SET_PID _IOW('o', 135, ca_pid_t)
#endif
-
diff --git a/include/linux/dvb/dmx.h b/include/linux/dvb/dmx.h
index 147294414fcbb..ce3f829da82cf 100644
--- a/include/linux/dvb/dmx.h
+++ b/include/linux/dvb/dmx.h
@@ -3,7 +3,7 @@
*
* Copyright (C) 2000 Marcus Metzler <marcus@convergence.de>
* & Ralph Metzler <ralph@convergence.de>
- for convergence integrated media GmbH
+ * for convergence integrated media GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
@@ -31,6 +31,7 @@
#include <time.h>
#endif
+
#define DMX_FILTER_SIZE 16
typedef enum
@@ -111,10 +112,10 @@ typedef struct dmx_filter
struct dmx_sct_filter_params
{
- __u16 pid;
- dmx_filter_t filter;
- __u32 timeout;
- __u32 flags;
+ __u16 pid;
+ dmx_filter_t filter;
+ __u32 timeout;
+ __u32 flags;
#define DMX_CHECK_CRC 1
#define DMX_ONESHOT 2
#define DMX_IMMEDIATE_START 4
@@ -124,11 +125,11 @@ struct dmx_sct_filter_params
struct dmx_pes_filter_params
{
- __u16 pid;
- dmx_input_t input;
- dmx_output_t output;
- dmx_pes_type_t pes_type;
- __u32 flags;
+ __u16 pid;
+ dmx_input_t input;
+ dmx_output_t output;
+ dmx_pes_type_t pes_type;
+ __u32 flags;
};
@@ -144,7 +145,7 @@ struct dmx_event
typedef struct dmx_caps {
__u32 caps;
- int num_decoders;
+ int num_decoders;
} dmx_caps_t;
typedef enum {
@@ -165,16 +166,15 @@ struct dmx_stc {
};
-#define DMX_START _IO('o',41)
-#define DMX_STOP _IO('o',42)
-#define DMX_SET_FILTER _IOW('o',43,struct dmx_sct_filter_params)
-#define DMX_SET_PES_FILTER _IOW('o',44,struct dmx_pes_filter_params)
-#define DMX_SET_BUFFER_SIZE _IO('o',45)
-#define DMX_GET_EVENT _IOR('o',46,struct dmx_event)
+#define DMX_START _IO('o', 41)
+#define DMX_STOP _IO('o', 42)
+#define DMX_SET_FILTER _IOW('o', 43, struct dmx_sct_filter_params)
+#define DMX_SET_PES_FILTER _IOW('o', 44, struct dmx_pes_filter_params)
+#define DMX_SET_BUFFER_SIZE _IO('o', 45)
+#define DMX_GET_EVENT _IOR('o', 46, struct dmx_event)
#define DMX_GET_PES_PIDS _IOR('o', 47, __u16[5])
-#define DMX_GET_CAPS _IOR('o',48,dmx_caps_t)
-#define DMX_SET_SOURCE _IOW('o',49,dmx_source_t)
-#define DMX_GET_STC _IOWR('o',50,struct dmx_stc)
+#define DMX_GET_CAPS _IOR('o', 48, dmx_caps_t)
+#define DMX_SET_SOURCE _IOW('o', 49, dmx_source_t)
+#define DMX_GET_STC _IOWR('o', 50, struct dmx_stc)
#endif /*_DVBDMX_H_*/
-
diff --git a/include/linux/dvb/frontend.h b/include/linux/dvb/frontend.h
index f31b8fc781c70..d41df7047ed72 100644
--- a/include/linux/dvb/frontend.h
+++ b/include/linux/dvb/frontend.h
@@ -2,10 +2,10 @@
* frontend.h
*
* Copyright (C) 2000 Marcus Metzler <marcus@convergence.de>
- * Ralph Metzler <ralph@convergence.de>
- * Holger Waechtler <holger@convergence.de>
- * Andre Draszik <ad@convergence.de>
- * for convergence integrated media GmbH
+ * Ralph Metzler <ralph@convergence.de>
+ * Holger Waechtler <holger@convergence.de>
+ * Andre Draszik <ad@convergence.de>
+ * for convergence integrated media GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
@@ -30,54 +30,54 @@
typedef enum fe_type {
- FE_QPSK,
- FE_QAM,
+ FE_QPSK,
+ FE_QAM,
FE_OFDM,
FE_ATSC
} fe_type_t;
typedef enum fe_caps {
- FE_IS_STUPID = 0,
- FE_CAN_INVERSION_AUTO = 0x1,
- FE_CAN_FEC_1_2 = 0x2,
- FE_CAN_FEC_2_3 = 0x4,
- FE_CAN_FEC_3_4 = 0x8,
- FE_CAN_FEC_4_5 = 0x10,
- FE_CAN_FEC_5_6 = 0x20,
- FE_CAN_FEC_6_7 = 0x40,
- FE_CAN_FEC_7_8 = 0x80,
- FE_CAN_FEC_8_9 = 0x100,
- FE_CAN_FEC_AUTO = 0x200,
- FE_CAN_QPSK = 0x400,
- FE_CAN_QAM_16 = 0x800,
- FE_CAN_QAM_32 = 0x1000,
- FE_CAN_QAM_64 = 0x2000,
- FE_CAN_QAM_128 = 0x4000,
- FE_CAN_QAM_256 = 0x8000,
- FE_CAN_QAM_AUTO = 0x10000,
- FE_CAN_TRANSMISSION_MODE_AUTO = 0x20000,
- FE_CAN_BANDWIDTH_AUTO = 0x40000,
- FE_CAN_GUARD_INTERVAL_AUTO = 0x80000,
- FE_CAN_HIERARCHY_AUTO = 0x100000,
+ FE_IS_STUPID = 0,
+ FE_CAN_INVERSION_AUTO = 0x1,
+ FE_CAN_FEC_1_2 = 0x2,
+ FE_CAN_FEC_2_3 = 0x4,
+ FE_CAN_FEC_3_4 = 0x8,
+ FE_CAN_FEC_4_5 = 0x10,
+ FE_CAN_FEC_5_6 = 0x20,
+ FE_CAN_FEC_6_7 = 0x40,
+ FE_CAN_FEC_7_8 = 0x80,
+ FE_CAN_FEC_8_9 = 0x100,
+ FE_CAN_FEC_AUTO = 0x200,
+ FE_CAN_QPSK = 0x400,
+ FE_CAN_QAM_16 = 0x800,
+ FE_CAN_QAM_32 = 0x1000,
+ FE_CAN_QAM_64 = 0x2000,
+ FE_CAN_QAM_128 = 0x4000,
+ FE_CAN_QAM_256 = 0x8000,
+ FE_CAN_QAM_AUTO = 0x10000,
+ FE_CAN_TRANSMISSION_MODE_AUTO = 0x20000,
+ FE_CAN_BANDWIDTH_AUTO = 0x40000,
+ FE_CAN_GUARD_INTERVAL_AUTO = 0x80000,
+ FE_CAN_HIERARCHY_AUTO = 0x100000,
FE_CAN_8VSB = 0x200000,
FE_CAN_16VSB = 0x400000,
FE_NEEDS_BENDING = 0x20000000, // not supported anymore, don't use (frontend requires frequency bending)
- FE_CAN_RECOVER = 0x40000000, // frontend can recover from a cable unplug automatically
- FE_CAN_MUTE_TS = 0x80000000 // frontend can stop spurious TS data output
+ FE_CAN_RECOVER = 0x40000000, // frontend can recover from a cable unplug automatically
+ FE_CAN_MUTE_TS = 0x80000000 // frontend can stop spurious TS data output
} fe_caps_t;
struct dvb_frontend_info {
char name[128];
- fe_type_t type;
- __u32 frequency_min;
- __u32 frequency_max;
+ fe_type_t type;
+ __u32 frequency_min;
+ __u32 frequency_max;
__u32 frequency_stepsize;
__u32 frequency_tolerance;
__u32 symbol_rate_min;
- __u32 symbol_rate_max;
- __u32 symbol_rate_tolerance; /* ppm */
+ __u32 symbol_rate_max;
+ __u32 symbol_rate_tolerance; /* ppm */
__u32 notifier_delay; /* DEPRECATED */
fe_caps_t caps;
};
@@ -88,76 +88,76 @@ struct dvb_frontend_info {
* the meaning of this struct...
*/
struct dvb_diseqc_master_cmd {
- __u8 msg [6]; /* { framing, address, command, data [3] } */
- __u8 msg_len; /* valid values are 3...6 */
+ __u8 msg [6]; /* { framing, address, command, data [3] } */
+ __u8 msg_len; /* valid values are 3...6 */
};
struct dvb_diseqc_slave_reply {
- __u8 msg [4]; /* { framing, data [3] } */
- __u8 msg_len; /* valid values are 0...4, 0 means no msg */
- int timeout; /* return from ioctl after timeout ms with */
-}; /* errorcode when no message was received */
+ __u8 msg [4]; /* { framing, data [3] } */
+ __u8 msg_len; /* valid values are 0...4, 0 means no msg */
+ int timeout; /* return from ioctl after timeout ms with */
+}; /* errorcode when no message was received */
typedef enum fe_sec_voltage {
- SEC_VOLTAGE_13,
- SEC_VOLTAGE_18,
+ SEC_VOLTAGE_13,
+ SEC_VOLTAGE_18,
SEC_VOLTAGE_OFF
} fe_sec_voltage_t;
typedef enum fe_sec_tone_mode {
- SEC_TONE_ON,
- SEC_TONE_OFF
+ SEC_TONE_ON,
+ SEC_TONE_OFF
} fe_sec_tone_mode_t;
typedef enum fe_sec_mini_cmd {
- SEC_MINI_A,
- SEC_MINI_B
+ SEC_MINI_A,
+ SEC_MINI_B
} fe_sec_mini_cmd_t;
typedef enum fe_status {
- FE_HAS_SIGNAL = 0x01, /* found something above the noise level */
- FE_HAS_CARRIER = 0x02, /* found a DVB signal */
- FE_HAS_VITERBI = 0x04, /* FEC is stable */
- FE_HAS_SYNC = 0x08, /* found sync bytes */
- FE_HAS_LOCK = 0x10, /* everything's working... */
- FE_TIMEDOUT = 0x20, /* no lock within the last ~2 seconds */
- FE_REINIT = 0x40 /* frontend was reinitialized, */
-} fe_status_t; /* application is recommended to reset */
- /* DiSEqC, tone and parameters */
+ FE_HAS_SIGNAL = 0x01, /* found something above the noise level */
+ FE_HAS_CARRIER = 0x02, /* found a DVB signal */
+ FE_HAS_VITERBI = 0x04, /* FEC is stable */
+ FE_HAS_SYNC = 0x08, /* found sync bytes */
+ FE_HAS_LOCK = 0x10, /* everything's working... */
+ FE_TIMEDOUT = 0x20, /* no lock within the last ~2 seconds */
+ FE_REINIT = 0x40 /* frontend was reinitialized, */
+} fe_status_t; /* application is recommended to reset */
+ /* DiSEqC, tone and parameters */
typedef enum fe_spectral_inversion {
- INVERSION_OFF,
- INVERSION_ON,
- INVERSION_AUTO
+ INVERSION_OFF,
+ INVERSION_ON,
+ INVERSION_AUTO
} fe_spectral_inversion_t;
typedef enum fe_code_rate {
- FEC_NONE = 0,
- FEC_1_2,
- FEC_2_3,
- FEC_3_4,
- FEC_4_5,
- FEC_5_6,
- FEC_6_7,
- FEC_7_8,
- FEC_8_9,
- FEC_AUTO
+ FEC_NONE = 0,
+ FEC_1_2,
+ FEC_2_3,
+ FEC_3_4,
+ FEC_4_5,
+ FEC_5_6,
+ FEC_6_7,
+ FEC_7_8,
+ FEC_8_9,
+ FEC_AUTO
} fe_code_rate_t;
typedef enum fe_modulation {
- QPSK,
- QAM_16,
- QAM_32,
- QAM_64,
- QAM_128,
- QAM_256,
+ QPSK,
+ QAM_16,
+ QAM_32,
+ QAM_64,
+ QAM_128,
+ QAM_256,
QAM_AUTO,
VSB_8,
VSB_16
@@ -196,15 +196,14 @@ typedef enum fe_hierarchy {
struct dvb_qpsk_parameters {
- __u32 symbol_rate; /* symbol rate in Symbols per second */
- fe_code_rate_t fec_inner; /* forward error correction (see above) */
+ __u32 symbol_rate; /* symbol rate in Symbols per second */
+ fe_code_rate_t fec_inner; /* forward error correction (see above) */
};
-
struct dvb_qam_parameters {
- __u32 symbol_rate; /* symbol rate in Symbols per second */
- fe_code_rate_t fec_inner; /* forward error correction (see above) */
- fe_modulation_t modulation; /* modulation type (see above) */
+ __u32 symbol_rate; /* symbol rate in Symbols per second */
+ fe_code_rate_t fec_inner; /* forward error correction (see above) */
+ fe_modulation_t modulation; /* modulation type (see above) */
};
struct dvb_vsb_parameters {
@@ -212,19 +211,19 @@ struct dvb_vsb_parameters {
};
struct dvb_ofdm_parameters {
- fe_bandwidth_t bandwidth;
- fe_code_rate_t code_rate_HP; /* high priority stream code rate */
- fe_code_rate_t code_rate_LP; /* low priority stream code rate */
- fe_modulation_t constellation; /* modulation type (see above) */
- fe_transmit_mode_t transmission_mode;
- fe_guard_interval_t guard_interval;
- fe_hierarchy_t hierarchy_information;
+ fe_bandwidth_t bandwidth;
+ fe_code_rate_t code_rate_HP; /* high priority stream code rate */
+ fe_code_rate_t code_rate_LP; /* low priority stream code rate */
+ fe_modulation_t constellation; /* modulation type (see above) */
+ fe_transmit_mode_t transmission_mode;
+ fe_guard_interval_t guard_interval;
+ fe_hierarchy_t hierarchy_information;
};
struct dvb_frontend_parameters {
__u32 frequency; /* (absolute) frequency in Hz for QAM/OFDM/ATSC */
- /* intermediate frequency in kHz for QPSK */
+ /* intermediate frequency in kHz for QPSK */
fe_spectral_inversion_t inversion;
union {
struct dvb_qpsk_parameters qpsk;
@@ -242,29 +241,27 @@ struct dvb_frontend_event {
-#define FE_GET_INFO _IOR('o', 61, struct dvb_frontend_info)
+#define FE_GET_INFO _IOR('o', 61, struct dvb_frontend_info)
#define FE_DISEQC_RESET_OVERLOAD _IO('o', 62)
#define FE_DISEQC_SEND_MASTER_CMD _IOW('o', 63, struct dvb_diseqc_master_cmd)
#define FE_DISEQC_RECV_SLAVE_REPLY _IOR('o', 64, struct dvb_diseqc_slave_reply)
#define FE_DISEQC_SEND_BURST _IO('o', 65) /* fe_sec_mini_cmd_t */
-#define FE_SET_TONE _IO('o', 66) /* fe_sec_tone_mode_t */
-#define FE_SET_VOLTAGE _IO('o', 67) /* fe_sec_voltage_t */
+#define FE_SET_TONE _IO('o', 66) /* fe_sec_tone_mode_t */
+#define FE_SET_VOLTAGE _IO('o', 67) /* fe_sec_voltage_t */
#define FE_ENABLE_HIGH_LNB_VOLTAGE _IO('o', 68) /* int */
-#define FE_READ_STATUS _IOR('o', 69, fe_status_t)
-#define FE_READ_BER _IOR('o', 70, __u32)
+#define FE_READ_STATUS _IOR('o', 69, fe_status_t)
+#define FE_READ_BER _IOR('o', 70, __u32)
#define FE_READ_SIGNAL_STRENGTH _IOR('o', 71, __u16)
-#define FE_READ_SNR _IOR('o', 72, __u16)
+#define FE_READ_SNR _IOR('o', 72, __u16)
#define FE_READ_UNCORRECTED_BLOCKS _IOR('o', 73, __u32)
-#define FE_SET_FRONTEND _IOW('o', 76, struct dvb_frontend_parameters)
-#define FE_GET_FRONTEND _IOR('o', 77, struct dvb_frontend_parameters)
-#define FE_GET_EVENT _IOR('o', 78, 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_GET_EVENT _IOR('o', 78, struct dvb_frontend_event)
#define FE_DISHNETWORK_SEND_LEGACY_CMD _IO('o', 80) /* unsigned int */
-
#endif /*_DVBFRONTEND_H_*/
-
diff --git a/include/linux/dvb/net.h b/include/linux/dvb/net.h
index c14101491ac9e..5be474bf0d2bd 100644
--- a/include/linux/dvb/net.h
+++ b/include/linux/dvb/net.h
@@ -1,9 +1,9 @@
-/*
+/*
* net.h
*
* Copyright (C) 2000 Marcus Metzler <marcus@convergence.de>
* & Ralph Metzler <ralph@convergence.de>
- for convergence integrated media GmbH
+ * for convergence integrated media GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
@@ -30,15 +30,15 @@
struct dvb_net_if {
__u16 pid;
__u16 if_num;
- __u8 feedtype;
+ __u8 feedtype;
#define DVB_NET_FEEDTYPE_MPE 0 /* multi protocol encapsulation */
#define DVB_NET_FEEDTYPE_ULE 1 /* ultra lightweight encapsulation */
};
-#define NET_ADD_IF _IOWR('o', 52, struct dvb_net_if)
-#define NET_REMOVE_IF _IO('o', 53)
-#define NET_GET_IF _IOWR('o', 54, struct dvb_net_if)
+#define NET_ADD_IF _IOWR('o', 52, struct dvb_net_if)
+#define NET_REMOVE_IF _IO('o', 53)
+#define NET_GET_IF _IOWR('o', 54, struct dvb_net_if)
/* binary compatibility cruft: */
diff --git a/include/linux/dvb/osd.h b/include/linux/dvb/osd.h
index d236deac80f11..0e1973d54a6b1 100644
--- a/include/linux/dvb/osd.h
+++ b/include/linux/dvb/osd.h
@@ -1,9 +1,9 @@
-/*
+/*
* osd.h
*
* Copyright (C) 2001 Ralph Metzler <ralph@convergence.de>
* & Marcus Metzler <marcus@convergence.de>
- for convergence integrated media GmbH
+ * for convergence integrated media GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Lesser Public License
@@ -93,7 +93,7 @@ typedef enum {
// TODO: remove "test" in final version
OSD_Text, // (x0,y0,size,color,text)
OSD_SetWindow, // (x0) set window with number 0<x0<8 as current
- OSD_MoveWindow, // move current window to (x0, y0)
+ OSD_MoveWindow, // move current window to (x0, y0)
OSD_OpenRaw, // Open other types of OSD windows
} OSD_Command;
@@ -138,8 +138,7 @@ typedef struct osd_cap_s {
} osd_cap_t;
-#define OSD_SEND_CMD _IOW('o', 160, osd_cmd_t)
+#define OSD_SEND_CMD _IOW('o', 160, osd_cmd_t)
#define OSD_GET_CAPABILITY _IOR('o', 161, osd_cap_t)
#endif
-
diff --git a/include/linux/dvb/version.h b/include/linux/dvb/version.h
index 624c40e5df59a..6183c9c4849e2 100644
--- a/include/linux/dvb/version.h
+++ b/include/linux/dvb/version.h
@@ -27,4 +27,3 @@
#define DVB_API_VERSION_MINOR 1
#endif /*_DVBVERSION_H_*/
-
diff --git a/include/linux/dvb/video.h b/include/linux/dvb/video.h
index 2ed5d7bc4cbcf..941045e9ab891 100644
--- a/include/linux/dvb/video.h
+++ b/include/linux/dvb/video.h
@@ -1,9 +1,9 @@
-/*
+/*
* video.h
*
* Copyright (C) 2000 Marcus Metzler <marcus@convergence.de>
* & Ralph Metzler <ralph@convergence.de>
- for convergence integrated media GmbH
+ * for convergence integrated media GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
@@ -35,25 +35,25 @@
typedef enum {
- VIDEO_FORMAT_4_3, /* Select 4:3 format */
+ VIDEO_FORMAT_4_3, /* Select 4:3 format */
VIDEO_FORMAT_16_9, /* Select 16:9 format. */
VIDEO_FORMAT_221_1 /* 2.21:1 */
} video_format_t;
typedef enum {
- VIDEO_SYSTEM_PAL,
- VIDEO_SYSTEM_NTSC,
- VIDEO_SYSTEM_PALN,
- VIDEO_SYSTEM_PALNc,
- VIDEO_SYSTEM_PALM,
- VIDEO_SYSTEM_NTSC60,
+ VIDEO_SYSTEM_PAL,
+ VIDEO_SYSTEM_NTSC,
+ VIDEO_SYSTEM_PALN,
+ VIDEO_SYSTEM_PALNc,
+ VIDEO_SYSTEM_PALM,
+ VIDEO_SYSTEM_NTSC60,
VIDEO_SYSTEM_PAL60,
VIDEO_SYSTEM_PALM60
} video_system_t;
-typedef enum {
+typedef enum {
VIDEO_PAN_SCAN, /* use pan and scan format */
VIDEO_LETTER_BOX, /* use letterbox format */
VIDEO_CENTER_CUT_OUT /* use center cut out format */
@@ -66,35 +66,35 @@ typedef struct {
} video_size_t;
typedef enum {
- VIDEO_SOURCE_DEMUX, /* Select the demux as the main source */
- VIDEO_SOURCE_MEMORY /* If this source is selected, the stream
- comes from the user through the write
- system call */
+ VIDEO_SOURCE_DEMUX, /* Select the demux as the main source */
+ VIDEO_SOURCE_MEMORY /* If this source is selected, the stream
+ comes from the user through the write
+ system call */
} video_stream_source_t;
typedef enum {
- VIDEO_STOPPED, /* Video is stopped */
- VIDEO_PLAYING, /* Video is currently playing */
- VIDEO_FREEZED /* Video is freezed */
-} video_play_state_t;
+ VIDEO_STOPPED, /* Video is stopped */
+ VIDEO_PLAYING, /* Video is currently playing */
+ VIDEO_FREEZED /* Video is freezed */
+} video_play_state_t;
-struct video_event {
- int32_t type;
-#define VIDEO_EVENT_SIZE_CHANGED 1
+struct video_event {
+ int32_t type;
+#define VIDEO_EVENT_SIZE_CHANGED 1
#define VIDEO_EVENT_FRAME_RATE_CHANGED 2
time_t timestamp;
- union {
+ union {
video_size_t size;
unsigned int frame_rate; /* in frames per 1000sec */
- } u;
+ } u;
};
-struct video_status {
+struct video_status {
int video_blank; /* blank video on freeze? */
- video_play_state_t play_state; /* current state of playback */
+ video_play_state_t play_state; /* current state of playback */
video_stream_source_t stream_source; /* current source (demux/memory) */
video_format_t video_format; /* current aspect ratio of stream*/
video_displayformat_t display_format;/* selected cropping mode */
@@ -103,11 +103,11 @@ struct video_status {
struct video_still_picture {
char __user *iFrame; /* pointer to a single iframe in memory */
- int32_t size;
+ int32_t size;
};
-typedef
+typedef
struct video_highlight {
int active; /* 1=show highlight, 0=hide highlight */
uint8_t contrast1; /* 7- 4 Pattern pixel contrast */
@@ -118,7 +118,7 @@ struct video_highlight {
/* 3- 0 Background pixel color */
uint8_t color2; /* 7- 4 Emphasis pixel-2 color */
/* 3- 0 Emphasis pixel-1 color */
- uint32_t ypos; /* 23-22 auto action mode */
+ uint32_t ypos; /* 23-22 auto action mode */
/* 21-12 start y */
/* 9- 0 end y */
uint32_t xpos; /* 23-22 button color number */
@@ -160,21 +160,21 @@ typedef uint16_t video_attributes_t;
/* bit definitions for capabilities: */
/* can the hardware decode MPEG1 and/or MPEG2? */
-#define VIDEO_CAP_MPEG1 1
+#define VIDEO_CAP_MPEG1 1
#define VIDEO_CAP_MPEG2 2
/* can you send a system and/or program stream to video device?
- (you still have to open the video and the audio device but only
+ (you still have to open the video and the audio device but only
send the stream to the video device) */
#define VIDEO_CAP_SYS 4
#define VIDEO_CAP_PROG 8
-/* can the driver also handle SPU, NAVI and CSS encoded data?
+/* can the driver also handle SPU, NAVI and CSS encoded data?
(CSS API is not present yet) */
#define VIDEO_CAP_SPU 16
#define VIDEO_CAP_NAVI 32
#define VIDEO_CAP_CSS 64
-#define VIDEO_STOP _IO('o', 21)
+#define VIDEO_STOP _IO('o', 21)
#define VIDEO_PLAY _IO('o', 22)
#define VIDEO_FREEZE _IO('o', 23)
#define VIDEO_CONTINUE _IO('o', 24)
@@ -201,4 +201,3 @@ typedef uint16_t video_attributes_t;
#define VIDEO_GET_FRAME_RATE _IOR('o', 56, unsigned int)
#endif /*_DVBVIDEO_H_*/
-
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 0f461df7686c2..047e7222df7a7 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -301,7 +301,6 @@ extern u64 efi_mem_attributes (unsigned long phys_addr);
extern int __init efi_uart_console_only (void);
extern void efi_initialize_iomem_resources(struct resource *code_resource,
struct resource *data_resource);
-extern efi_status_t phys_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc);
extern unsigned long __init efi_get_time(void);
extern int __init efi_set_rtc_mmss(unsigned long nowtime);
extern struct efi_memory_map memmap;
diff --git a/include/linux/elevator.h b/include/linux/elevator.h
index 8cf0e3f290bfa..ee54f81faad50 100644
--- a/include/linux/elevator.h
+++ b/include/linux/elevator.h
@@ -20,6 +20,7 @@ typedef int (elevator_may_queue_fn) (request_queue_t *, int);
typedef int (elevator_set_req_fn) (request_queue_t *, struct request *, int);
typedef void (elevator_put_req_fn) (request_queue_t *, struct request *);
+typedef void (elevator_deactivate_req_fn) (request_queue_t *, struct request *);
typedef int (elevator_init_fn) (request_queue_t *, elevator_t *);
typedef void (elevator_exit_fn) (elevator_t *);
@@ -34,6 +35,7 @@ struct elevator_ops
elevator_add_req_fn *elevator_add_req_fn;
elevator_remove_req_fn *elevator_remove_req_fn;
elevator_requeue_req_fn *elevator_requeue_req_fn;
+ elevator_deactivate_req_fn *elevator_deactivate_req_fn;
elevator_queue_empty_fn *elevator_queue_empty_fn;
elevator_completed_req_fn *elevator_completed_req_fn;
@@ -87,6 +89,7 @@ extern void elv_merge_requests(request_queue_t *, struct request *,
extern void elv_merged_request(request_queue_t *, struct request *);
extern void elv_remove_request(request_queue_t *, struct request *);
extern void elv_requeue_request(request_queue_t *, struct request *);
+extern void elv_deactivate_request(request_queue_t *, struct request *);
extern int elv_queue_empty(request_queue_t *);
extern struct request *elv_next_request(struct request_queue *q);
extern struct request *elv_former_request(request_queue_t *, struct request *);
diff --git a/include/linux/etherdevice.h b/include/linux/etherdevice.h
index ca6a19b1479fc..396c48cbaeb14 100644
--- a/include/linux/etherdevice.h
+++ b/include/linux/etherdevice.h
@@ -47,6 +47,15 @@ static inline void eth_copy_and_sum (struct sk_buff *dest,
}
/**
+ * is_zero_ether_addr - Determine if give Ethernet address is all
+ * zeros.
+ */
+static inline int is_zero_ether_addr(const u8 *addr)
+{
+ return !(addr[0] | addr[1] | addr[2] | addr[3] | addr[4] | addr[5]);
+}
+
+/**
* is_valid_ether_addr - Determine if the given Ethernet address is valid
* @addr: Pointer to a six-byte array containing the Ethernet address
*
@@ -56,11 +65,9 @@ static inline void eth_copy_and_sum (struct sk_buff *dest,
*
* Return true if the address is valid.
*/
-static inline int is_valid_ether_addr( const u8 *addr )
+static inline int is_valid_ether_addr(const u8 *addr)
{
- const char zaddr[6] = {0,};
-
- return !(addr[0]&1) && memcmp( addr, zaddr, 6);
+ return !(addr[0]&1) && !is_zero_ether_addr(addr);
}
/**
diff --git a/include/linux/ext3_fs.h b/include/linux/ext3_fs.h
index f909e16a96456..4d478d8b2d069 100644
--- a/include/linux/ext3_fs.h
+++ b/include/linux/ext3_fs.h
@@ -357,6 +357,7 @@ struct ext3_inode {
#define EXT3_MOUNT_POSIX_ACL 0x08000 /* POSIX Access Control Lists */
#define EXT3_MOUNT_RESERVATION 0x10000 /* Preallocation */
#define EXT3_MOUNT_BARRIER 0x20000 /* Use block barriers */
+#define EXT3_MOUNT_NOBH 0x40000 /* No bufferheads */
/* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
#ifndef _LINUX_EXT2_FS_H
diff --git a/include/linux/ext3_jbd.h b/include/linux/ext3_jbd.h
index 47445f93d4f75..e8292af9033bf 100644
--- a/include/linux/ext3_jbd.h
+++ b/include/linux/ext3_jbd.h
@@ -111,9 +111,9 @@ void ext3_journal_abort_handle(const char *caller, const char *err_fn,
static inline int
__ext3_journal_get_undo_access(const char *where, handle_t *handle,
- struct buffer_head *bh, int *credits)
+ struct buffer_head *bh)
{
- int err = journal_get_undo_access(handle, bh, credits);
+ int err = journal_get_undo_access(handle, bh);
if (err)
ext3_journal_abort_handle(where, __FUNCTION__, bh, handle,err);
return err;
@@ -121,19 +121,18 @@ __ext3_journal_get_undo_access(const char *where, handle_t *handle,
static inline int
__ext3_journal_get_write_access(const char *where, handle_t *handle,
- struct buffer_head *bh, int *credits)
+ struct buffer_head *bh)
{
- int err = journal_get_write_access(handle, bh, credits);
+ int err = journal_get_write_access(handle, bh);
if (err)
ext3_journal_abort_handle(where, __FUNCTION__, bh, handle,err);
return err;
}
static inline void
-ext3_journal_release_buffer(handle_t *handle, struct buffer_head *bh,
- int credits)
+ext3_journal_release_buffer(handle_t *handle, struct buffer_head *bh)
{
- journal_release_buffer(handle, bh, credits);
+ journal_release_buffer(handle, bh);
}
static inline int
@@ -176,12 +175,10 @@ __ext3_journal_dirty_metadata(const char *where,
}
-#define ext3_journal_get_undo_access(handle, bh, credits) \
- __ext3_journal_get_undo_access(__FUNCTION__, (handle), (bh), (credits))
+#define ext3_journal_get_undo_access(handle, bh) \
+ __ext3_journal_get_undo_access(__FUNCTION__, (handle), (bh))
#define ext3_journal_get_write_access(handle, bh) \
- __ext3_journal_get_write_access(__FUNCTION__, (handle), (bh), NULL)
-#define ext3_journal_get_write_access_credits(handle, bh, credits) \
- __ext3_journal_get_write_access(__FUNCTION__, (handle), (bh), (credits))
+ __ext3_journal_get_write_access(__FUNCTION__, (handle), (bh))
#define ext3_journal_revoke(handle, blocknr, bh) \
__ext3_journal_revoke(__FUNCTION__, (handle), (blocknr), (bh))
#define ext3_journal_get_create_access(handle, bh) \
diff --git a/include/linux/fb.h b/include/linux/fb.h
index 974894b623cdb..b45d3e2d711a3 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -103,7 +103,10 @@
#define FB_ACCEL_SIS_GLAMOUR_2 40 /* SiS 315, 650, 740 */
#define FB_ACCEL_SIS_XABRE 41 /* SiS 330 ("Xabre") */
#define FB_ACCEL_I830 42 /* Intel 830M/845G/85x/865G */
-
+#define FB_ACCEL_NV_10 43 /* nVidia Arch 10 */
+#define FB_ACCEL_NV_20 44 /* nVidia Arch 20 */
+#define FB_ACCEL_NV_30 45 /* nVidia Arch 30 */
+#define FB_ACCEL_NV_40 46 /* nVidia Arch 40 */
#define FB_ACCEL_NEOMAGIC_NM2070 90 /* NeoMagic NM2070 */
#define FB_ACCEL_NEOMAGIC_NM2090 91 /* NeoMagic NM2090 */
#define FB_ACCEL_NEOMAGIC_NM2093 92 /* NeoMagic NM2093 */
@@ -490,6 +493,8 @@ struct fb_cursor_user {
#define FB_EVENT_SET_CONSOLE_MAP 0x07
/* A display blank is requested */
#define FB_EVENT_BLANK 0x08
+/* Private modelist is to be replaced */
+#define FB_EVENT_NEW_MODELIST 0x09
struct fb_event {
struct fb_info *info;
@@ -585,7 +590,7 @@ struct fb_ops {
unsigned long arg, struct fb_info *info);
/* Handle 32bit compat ioctl (optional) */
- int (*fb_compat_ioctl)(struct file *f, unsigned cmd, unsigned long arg,
+ long (*fb_compat_ioctl)(struct file *f, unsigned cmd, unsigned long arg,
struct fb_info *info);
/* perform fb specific mmap */
@@ -697,9 +702,7 @@ struct fb_tile_ops {
#define FBINFO_MISC_USEREVENT 0x10000 /* event request
from userspace */
-#define FBINFO_MISC_MODESWITCH 0x20000 /* mode switch */
-#define FBINFO_MISC_MODESWITCHLATE 0x40000 /* init hardware later */
-#define FBINFO_MISC_TILEBLITTING 0x80000 /* use tile blitting */
+#define FBINFO_MISC_TILEBLITTING 0x20000 /* use tile blitting */
struct fb_info {
int node;
@@ -712,8 +715,10 @@ struct fb_info {
struct fb_pixmap sprite; /* Cursor hardware mapper */
struct fb_cmap cmap; /* Current cmap */
struct list_head modelist; /* mode list */
+ struct fb_videomode *mode; /* current mode */
struct fb_ops *fbops;
struct device *device;
+ struct class_device *class_device; /* sysfs per device attrs */
#ifdef CONFIG_FB_TILEBLITTING
struct fb_tile_ops *tileops; /* Tile Blitting */
#endif
@@ -821,8 +826,9 @@ extern void fb_sysmove_buf_aligned(struct fb_info *info, struct fb_pixmap *buf,
u8 *dst, u32 d_pitch, u8 *src, u32 s_pitch,
u32 height);
extern void fb_set_suspend(struct fb_info *info, int state);
-extern int fb_get_color_depth(struct fb_info *info);
+extern int fb_get_color_depth(struct fb_var_screeninfo *var);
extern int fb_get_options(char *name, char **option);
+extern int fb_new_modelist(struct fb_info *info);
extern struct fb_info *registered_fb[FB_MAX];
extern int num_registered_fb;
@@ -830,6 +836,8 @@ extern int num_registered_fb;
/* drivers/video/fbsysfs.c */
extern struct fb_info *framebuffer_alloc(size_t size, struct device *dev);
extern void framebuffer_release(struct fb_info *info);
+extern int fb_init_class_device(struct fb_info *fb_info);
+extern void fb_cleanup_class_device(struct fb_info *head);
/* drivers/video/fbmon.c */
#define FB_MAXTIMINGS 0
@@ -854,10 +862,7 @@ extern int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var,
extern int fb_validate_mode(const struct fb_var_screeninfo *var,
struct fb_info *info);
extern int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var);
-extern int fb_get_monitor_limits(unsigned char *edid, struct fb_monspecs *specs);
extern void fb_edid_to_monspecs(unsigned char *edid, struct fb_monspecs *specs);
-extern int fb_get_monitor_limits(unsigned char *edid, struct fb_monspecs *specs);
-extern struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize);
extern void fb_destroy_modedb(struct fb_videomode *modedb);
/* drivers/video/modedb.c */
@@ -875,6 +880,8 @@ extern struct fb_videomode *fb_match_mode(struct fb_var_screeninfo *var,
struct list_head *head);
extern struct fb_videomode *fb_find_best_mode(struct fb_var_screeninfo *var,
struct list_head *head);
+extern struct fb_videomode *fb_find_nearest_mode(struct fb_var_screeninfo *var,
+ struct list_head *head);
extern void fb_destroy_modelist(struct list_head *head);
extern void fb_videomode_to_modelist(struct fb_videomode *modedb, int num,
struct list_head *head);
diff --git a/include/linux/fcdevice.h b/include/linux/fcdevice.h
index e42fc78f679e1..e460ef8319841 100644
--- a/include/linux/fcdevice.h
+++ b/include/linux/fcdevice.h
@@ -27,8 +27,6 @@
#include <linux/if_fc.h>
#ifdef __KERNEL__
-extern unsigned short fc_type_trans(struct sk_buff *skb, struct net_device *dev);
-
extern struct net_device *alloc_fcdev(int sizeof_priv);
#endif
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 30cb440cb6c86..723f41b51cedb 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -129,6 +129,7 @@ extern int dir_notify_enable;
#define S_DIRSYNC 64 /* Directory modifications are synchronous */
#define S_NOCMTIME 128 /* Do not update file c/mtime */
#define S_SWAPFILE 256 /* Do not truncate: swapon got its bmaps */
+#define S_PRIVATE 512 /* Inode is fs-internal */
/*
* Note that nosuid etc flags are inode-specific: setting some file-system
@@ -162,6 +163,7 @@ extern int dir_notify_enable;
#define IS_DEADDIR(inode) ((inode)->i_flags & S_DEAD)
#define IS_NOCMTIME(inode) ((inode)->i_flags & S_NOCMTIME)
#define IS_SWAPFILE(inode) ((inode)->i_flags & S_SWAPFILE)
+#define IS_PRIVATE(inode) ((inode)->i_flags & S_PRIVATE)
/* the read-only stuff doesn't really belong here, but any other place is
probably as bad and I don't want to create yet another include file. */
@@ -210,7 +212,6 @@ extern int dir_notify_enable;
#include <linux/list.h>
#include <linux/radix-tree.h>
#include <linux/prio_tree.h>
-#include <linux/audit.h>
#include <linux/init.h>
#include <asm/atomic.h>
@@ -335,7 +336,7 @@ struct backing_dev_info;
struct address_space {
struct inode *host; /* owner: inode, block_device */
struct radix_tree_root page_tree; /* radix tree of all pages */
- spinlock_t tree_lock; /* and spinlock protecting it */
+ rwlock_t tree_lock; /* and rwlock protecting it */
unsigned int i_mmap_writable;/* count VM_SHARED mappings */
struct prio_tree_root i_mmap; /* tree of private and shared mappings */
struct list_head i_mmap_nonlinear;/*list VM_NONLINEAR mappings */
@@ -647,6 +648,8 @@ struct lock_manager_operations {
void (*fl_copy_lock)(struct file_lock *, struct file_lock *);
void (*fl_release_private)(struct file_lock *);
void (*fl_break)(struct file_lock *);
+ int (*fl_mylease)(struct file_lock *, struct file_lock *);
+ int (*fl_change)(struct file_lock **, int);
};
/* that will die - we need it for nfs_lock_info */
@@ -713,7 +716,7 @@ extern int flock_lock_file_wait(struct file *filp, struct file_lock *fl);
extern int __break_lease(struct inode *inode, unsigned int flags);
extern void lease_get_mtime(struct inode *, struct timespec *time);
extern int setlease(struct file *, long, struct file_lock **);
-extern void remove_lease(struct file_lock *);
+extern int lease_modify(struct file_lock **, int);
extern int lock_may_read(struct inode *, loff_t start, unsigned long count);
extern int lock_may_write(struct inode *, loff_t start, unsigned long count);
extern void steal_locks(fl_owner_t from);
@@ -1268,13 +1271,7 @@ extern void __init vfs_caches_init(unsigned long);
#ifndef CONFIG_AUDITSYSCALL
#define putname(name) __putname(name)
#else
-#define putname(name) \
- do { \
- if (unlikely(current->audit_context)) \
- audit_putname(name); \
- else \
- __putname(name); \
- } while (0)
+extern void putname(const char *name);
#endif
extern int register_blkdev(unsigned int, const char *);
@@ -1353,11 +1350,15 @@ static inline void invalidate_remote_inode(struct inode *inode)
invalidate_inode_pages(inode->i_mapping);
}
extern int invalidate_inode_pages2(struct address_space *mapping);
+extern int invalidate_inode_pages2_range(struct address_space *mapping,
+ pgoff_t start, pgoff_t end);
extern int write_inode_now(struct inode *, int);
extern int filemap_fdatawrite(struct address_space *);
extern int filemap_flush(struct address_space *);
extern int filemap_fdatawait(struct address_space *);
extern int filemap_write_and_wait(struct address_space *mapping);
+extern int filemap_write_and_wait_range(struct address_space *mapping,
+ loff_t lstart, loff_t lend);
extern void sync_supers(void);
extern void sync_filesystems(int wait);
extern void emergency_sync(void);
diff --git a/include/linux/gameport.h b/include/linux/gameport.h
index 322a7f73297b9..b1272f822cfa1 100644
--- a/include/linux/gameport.h
+++ b/include/linux/gameport.h
@@ -10,19 +10,14 @@
*/
#include <asm/io.h>
-#include <linux/input.h>
#include <linux/list.h>
-
-struct gameport;
+#include <linux/device.h>
struct gameport {
- void *private; /* Private pointer for joystick drivers */
- void *driver; /* Private pointer for gameport drivers */
- char *name;
- char *phys;
-
- struct input_id id;
+ void *port_data; /* Private pointer for gameport drivers */
+ char name[32];
+ char phys[32];
int io;
int speed;
@@ -35,36 +30,105 @@ struct gameport {
int (*open)(struct gameport *, int);
void (*close)(struct gameport *);
- struct gameport_dev *dev;
+ struct timer_list poll_timer;
+ unsigned int poll_interval; /* in msecs */
+ spinlock_t timer_lock;
+ unsigned int poll_cnt;
+ void (*poll_handler)(struct gameport *);
+
+ struct gameport *parent, *child;
+
+ struct gameport_driver *drv;
+ struct semaphore drv_sem; /* protects serio->drv so attributes can pin driver */
+
+ struct device dev;
+ unsigned int registered; /* port has been fully registered with driver core */
struct list_head node;
};
+#define to_gameport_port(d) container_of(d, struct gameport, dev)
-struct gameport_dev {
+struct gameport_driver {
void *private;
- char *name;
+ char *description;
- void (*connect)(struct gameport *, struct gameport_dev *dev);
+ int (*connect)(struct gameport *, struct gameport_driver *drv);
+ int (*reconnect)(struct gameport *);
void (*disconnect)(struct gameport *);
- struct list_head node;
+ struct device_driver driver;
+
+ unsigned int ignore;
};
+#define to_gameport_driver(d) container_of(d, struct gameport_driver, driver)
-int gameport_open(struct gameport *gameport, struct gameport_dev *dev, int mode);
+int gameport_open(struct gameport *gameport, struct gameport_driver *drv, int mode);
void gameport_close(struct gameport *gameport);
void gameport_rescan(struct gameport *gameport);
-#if defined(CONFIG_GAMEPORT) || defined(CONFIG_GAMEPORT_MODULE)
-void gameport_register_port(struct gameport *gameport);
+void __gameport_register_port(struct gameport *gameport, struct module *owner);
+static inline void gameport_register_port(struct gameport *gameport)
+{
+ __gameport_register_port(gameport, THIS_MODULE);
+}
+
void gameport_unregister_port(struct gameport *gameport);
-#else
-static inline void gameport_register_port(struct gameport *gameport) { return; }
-static inline void gameport_unregister_port(struct gameport *gameport) { return; }
-#endif
-void gameport_register_device(struct gameport_dev *dev);
-void gameport_unregister_device(struct gameport_dev *dev);
+static inline struct gameport *gameport_allocate_port(void)
+{
+ struct gameport *gameport = kcalloc(1, sizeof(struct gameport), GFP_KERNEL);
+
+ return gameport;
+}
+
+static inline void gameport_free_port(struct gameport *gameport)
+{
+ kfree(gameport);
+}
+
+static inline void gameport_set_name(struct gameport *gameport, const char *name)
+{
+ strlcpy(gameport->name, name, sizeof(gameport->name));
+}
+
+void gameport_set_phys(struct gameport *gameport, const char *fmt, ...)
+ __attribute__ ((format (printf, 2, 3)));
+
+/*
+ * Use the following fucntions to manipulate gameport's per-port
+ * driver-specific data.
+ */
+static inline void *gameport_get_drvdata(struct gameport *gameport)
+{
+ return dev_get_drvdata(&gameport->dev);
+}
+
+static inline void gameport_set_drvdata(struct gameport *gameport, void *data)
+{
+ dev_set_drvdata(&gameport->dev, data);
+}
+
+/*
+ * Use the following fucntions to pin gameport's driver in process context
+ */
+static inline int gameport_pin_driver(struct gameport *gameport)
+{
+ return down_interruptible(&gameport->drv_sem);
+}
+
+static inline void gameport_unpin_driver(struct gameport *gameport)
+{
+ up(&gameport->drv_sem);
+}
+
+void __gameport_register_driver(struct gameport_driver *drv, struct module *owner);
+static inline void gameport_register_driver(struct gameport_driver *drv)
+{
+ __gameport_register_driver(drv, THIS_MODULE);
+}
+
+void gameport_unregister_driver(struct gameport_driver *drv);
#define GAMEPORT_MODE_DISABLED 0
#define GAMEPORT_MODE_RAW 1
@@ -81,7 +145,7 @@ void gameport_unregister_device(struct gameport_dev *dev);
#define GAMEPORT_ID_VENDOR_GRAVIS 0x0009
#define GAMEPORT_ID_VENDOR_GUILLEMOT 0x000a
-static __inline__ void gameport_trigger(struct gameport *gameport)
+static inline void gameport_trigger(struct gameport *gameport)
{
if (gameport->trigger)
gameport->trigger(gameport);
@@ -89,7 +153,7 @@ static __inline__ void gameport_trigger(struct gameport *gameport)
outb(0xff, gameport->io);
}
-static __inline__ unsigned char gameport_read(struct gameport *gameport)
+static inline unsigned char gameport_read(struct gameport *gameport)
{
if (gameport->read)
return gameport->read(gameport);
@@ -97,7 +161,7 @@ static __inline__ unsigned char gameport_read(struct gameport *gameport)
return inb(gameport->io);
}
-static __inline__ int gameport_cooked_read(struct gameport *gameport, int *axes, int *buttons)
+static inline int gameport_cooked_read(struct gameport *gameport, int *axes, int *buttons)
{
if (gameport->cooked_read)
return gameport->cooked_read(gameport, axes, buttons);
@@ -105,7 +169,7 @@ static __inline__ int gameport_cooked_read(struct gameport *gameport, int *axes,
return -1;
}
-static __inline__ int gameport_calibrate(struct gameport *gameport, int *axes, int *max)
+static inline int gameport_calibrate(struct gameport *gameport, int *axes, int *max)
{
if (gameport->calibrate)
return gameport->calibrate(gameport, axes, max);
@@ -113,9 +177,22 @@ static __inline__ int gameport_calibrate(struct gameport *gameport, int *axes, i
return -1;
}
-static __inline__ int gameport_time(struct gameport *gameport, int time)
+static inline int gameport_time(struct gameport *gameport, int time)
{
return (time * gameport->speed) / 1000;
}
+static inline void gameport_set_poll_handler(struct gameport *gameport, void (*handler)(struct gameport *))
+{
+ gameport->poll_handler = handler;
+}
+
+static inline void gameport_set_poll_interval(struct gameport *gameport, unsigned int msecs)
+{
+ gameport->poll_interval = msecs;
+}
+
+void gameport_start_polling(struct gameport *gameport);
+void gameport_stop_polling(struct gameport *gameport);
+
#endif
diff --git a/include/linux/generic_serial.h b/include/linux/generic_serial.h
index 09d2047093412..0abe9d9a0069d 100644
--- a/include/linux/generic_serial.h
+++ b/include/linux/generic_serial.h
@@ -34,7 +34,7 @@ struct gs_port {
int xmit_head;
int xmit_tail;
int xmit_cnt;
- /* struct semaphore port_write_sem; */
+ struct semaphore port_write_sem;
int flags;
wait_queue_head_t open_wait;
wait_queue_head_t close_wait;
@@ -49,6 +49,7 @@ struct gs_port {
int baud_base;
int baud;
int custom_divisor;
+ spinlock_t driver_lock;
};
@@ -70,6 +71,7 @@ struct gs_port {
#define GS_DEBUG_STUFF 0x00000008
#define GS_DEBUG_CLOSE 0x00000010
#define GS_DEBUG_FLOW 0x00000020
+#define GS_DEBUG_WRITE 0x00000040
void gs_put_char(struct tty_struct *tty, unsigned char ch);
@@ -91,6 +93,4 @@ int gs_setserial(struct gs_port *port, struct serial_struct __user *sp);
int gs_getserial(struct gs_port *port, struct serial_struct __user *sp);
void gs_got_break(struct gs_port *port);
-extern int gs_debug;
-
#endif
diff --git a/include/linux/gfp.h b/include/linux/gfp.h
index b526b21bad1c2..848a1baac0793 100644
--- a/include/linux/gfp.h
+++ b/include/linux/gfp.h
@@ -26,18 +26,18 @@ struct vm_area_struct;
*
* __GFP_NORETRY: The VM implementation must not retry indefinitely.
*/
-#define __GFP_WAIT 0x10 /* Can wait and reschedule? */
-#define __GFP_HIGH 0x20 /* Should access emergency pools? */
-#define __GFP_IO 0x40 /* Can start physical IO? */
-#define __GFP_FS 0x80 /* Can call down to low-level FS? */
-#define __GFP_COLD 0x100 /* Cache-cold page required */
-#define __GFP_NOWARN 0x200 /* Suppress page allocation failure warning */
-#define __GFP_REPEAT 0x400 /* Retry the allocation. Might fail */
-#define __GFP_NOFAIL 0x800 /* Retry for ever. Cannot fail */
-#define __GFP_NORETRY 0x1000 /* Do not retry. Might fail */
-#define __GFP_NO_GROW 0x2000 /* Slab internal usage */
-#define __GFP_COMP 0x4000 /* Add compound page metadata */
-#define __GFP_ZERO 0x8000 /* Return zeroed page on success */
+#define __GFP_WAIT 0x10u /* Can wait and reschedule? */
+#define __GFP_HIGH 0x20u /* Should access emergency pools? */
+#define __GFP_IO 0x40u /* Can start physical IO? */
+#define __GFP_FS 0x80u /* Can call down to low-level FS? */
+#define __GFP_COLD 0x100u /* Cache-cold page required */
+#define __GFP_NOWARN 0x200u /* Suppress page allocation failure warning */
+#define __GFP_REPEAT 0x400u /* Retry the allocation. Might fail */
+#define __GFP_NOFAIL 0x800u /* Retry for ever. Cannot fail */
+#define __GFP_NORETRY 0x1000u /* Do not retry. Might fail */
+#define __GFP_NO_GROW 0x2000u /* Slab internal usage */
+#define __GFP_COMP 0x4000u /* Add compound page metadata */
+#define __GFP_ZERO 0x8000u /* Return zeroed page on success */
#define __GFP_BITS_SHIFT 16 /* Room for 16 __GFP_FOO bits */
#define __GFP_BITS_MASK ((1 << __GFP_BITS_SHIFT) - 1)
@@ -82,7 +82,7 @@ static inline void arch_free_page(struct page *page, int order) { }
extern struct page *
FASTCALL(__alloc_pages(unsigned int, unsigned int, struct zonelist *));
-static inline struct page *alloc_pages_node(int nid, unsigned int gfp_mask,
+static inline struct page *alloc_pages_node(int nid, unsigned int __nocast gfp_mask,
unsigned int order)
{
if (unlikely(order >= MAX_ORDER))
@@ -93,17 +93,17 @@ static inline struct page *alloc_pages_node(int nid, unsigned int gfp_mask,
}
#ifdef CONFIG_NUMA
-extern struct page *alloc_pages_current(unsigned gfp_mask, unsigned order);
+extern struct page *alloc_pages_current(unsigned int __nocast gfp_mask, unsigned order);
static inline struct page *
-alloc_pages(unsigned int gfp_mask, unsigned int order)
+alloc_pages(unsigned int __nocast gfp_mask, unsigned int order)
{
if (unlikely(order >= MAX_ORDER))
return NULL;
return alloc_pages_current(gfp_mask, order);
}
-extern struct page *alloc_page_vma(unsigned gfp_mask,
+extern struct page *alloc_page_vma(unsigned __nocast gfp_mask,
struct vm_area_struct *vma, unsigned long addr);
#else
#define alloc_pages(gfp_mask, order) \
@@ -112,8 +112,8 @@ extern struct page *alloc_page_vma(unsigned gfp_mask,
#endif
#define alloc_page(gfp_mask) alloc_pages(gfp_mask, 0)
-extern unsigned long FASTCALL(__get_free_pages(unsigned int gfp_mask, unsigned int order));
-extern unsigned long FASTCALL(get_zeroed_page(unsigned int gfp_mask));
+extern unsigned long FASTCALL(__get_free_pages(unsigned int __nocast gfp_mask, unsigned int order));
+extern unsigned long FASTCALL(get_zeroed_page(unsigned int __nocast gfp_mask));
#define __get_free_page(gfp_mask) \
__get_free_pages((gfp_mask),0)
diff --git a/include/linux/hayesesp.h b/include/linux/hayesesp.h
index 131d71116c14d..b436be7a7fff3 100644
--- a/include/linux/hayesesp.h
+++ b/include/linux/hayesesp.h
@@ -77,6 +77,7 @@ struct hayes_esp_config {
struct esp_struct {
int magic;
+ spinlock_t lock;
int port;
int irq;
int flags; /* defined in tty.h */
diff --git a/include/linux/hdpu_features.h b/include/linux/hdpu_features.h
new file mode 100644
index 0000000000000..6a8715431ae40
--- /dev/null
+++ b/include/linux/hdpu_features.h
@@ -0,0 +1,26 @@
+#include <linux/spinlock.h>
+
+struct cpustate_t {
+ spinlock_t lock;
+ int excl;
+ int open_count;
+ unsigned char cached_val;
+ int inited;
+ unsigned long *set_addr;
+ unsigned long *clr_addr;
+};
+
+
+#define HDPU_CPUSTATE_NAME "hdpu cpustate"
+#define HDPU_NEXUS_NAME "hdpu nexus"
+
+#define CPUSTATE_KERNEL_MAJOR 0x10
+
+#define CPUSTATE_KERNEL_INIT_DRV 0 /* CPU State Driver Initialized */
+#define CPUSTATE_KERNEL_INIT_PCI 1 /* 64360 PCI Busses Init */
+#define CPUSTATE_KERNEL_INIT_REG 2 /* 64360 Bridge Init */
+#define CPUSTATE_KERNEL_CPU1_KICK 3 /* Boot cpu 1 */
+#define CPUSTATE_KERNEL_CPU1_OK 4 /* Cpu 1 has checked in */
+#define CPUSTATE_KERNEL_OK 5 /* Terminal state */
+#define CPUSTATE_KERNEL_RESET 14 /* Board reset via SW*/
+#define CPUSTATE_KERNEL_HALT 15 /* Board halted via SW*/
diff --git a/include/linux/hiddev.h b/include/linux/hiddev.h
index 695423da423e0..945ba1ad14acd 100644
--- a/include/linux/hiddev.h
+++ b/include/linux/hiddev.h
@@ -201,8 +201,8 @@ struct hiddev_usage_ref_multi {
* ioctl(fd, HIDIOCGUSAGE, &uref);
* }
* }
- * uref.report_id |= HID_REPORT_ID_NEXT;
- * ret = ioctl(fd, HIDIOCGREPORTINFO, &uref);
+ * rinfo.report_id |= HID_REPORT_ID_NEXT;
+ * ret = ioctl(fd, HIDIOCGREPORTINFO, &rinfo);
* }
*/
diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h
index 954af9d82768c..ae45676d27baf 100644
--- a/include/linux/hugetlb.h
+++ b/include/linux/hugetlb.h
@@ -36,7 +36,7 @@ extern const unsigned long hugetlb_zero, hugetlb_infinity;
extern int sysctl_hugetlb_shm_group;
#ifndef ARCH_HAS_HUGEPAGE_ONLY_RANGE
-#define is_hugepage_only_range(addr, len) 0
+#define is_hugepage_only_range(mm, addr, len) 0
#define hugetlb_free_pgtables(tlb, prev, start, end) do { } while (0)
#endif
@@ -71,7 +71,7 @@ static inline unsigned long hugetlb_total_pages(void)
#define is_aligned_hugepage_range(addr, len) 0
#define prepare_hugepage_range(addr, len) (-EINVAL)
#define pmd_huge(x) 0
-#define is_hugepage_only_range(addr, len) 0
+#define is_hugepage_only_range(mm, addr, len) 0
#define hugetlb_free_pgtables(tlb, prev, start, end) do { } while (0)
#define alloc_huge_page() ({ NULL; })
#define free_huge_page(p) ({ (void)(p); BUG(); })
diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h
index 8ac11f5c1b84d..89270ce514703 100644
--- a/include/linux/i2c-id.h
+++ b/include/linux/i2c-id.h
@@ -20,8 +20,6 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* ------------------------------------------------------------------------- */
-/* $Id: i2c-id.h,v 1.68 2003/02/25 02:55:18 mds Exp $ */
-
#ifndef LINUX_I2C_ID_H
#define LINUX_I2C_ID_H
@@ -196,11 +194,15 @@
#define I2C_ALGO_OCP 0x120000 /* IBM or otherwise On-chip I2C algorithm */
#define I2C_ALGO_BITHS 0x130000 /* enhanced bit style adapters */
#define I2C_ALGO_IOP3XX 0x140000 /* XSCALE IOP3XX On-chip I2C alg */
-#define I2C_ALGO_PCA 0x150000 /* PCA 9564 style adapters */
-
#define I2C_ALGO_SIBYTE 0x150000 /* Broadcom SiByte SOCs */
-#define I2C_ALGO_SGI 0x160000 /* SGI algorithm */
-#define I2C_ALGO_AU1550 0x170000 /* Au1550 PSC algorithm */
+#define I2C_ALGO_SGI 0x160000 /* SGI algorithm */
+
+#define I2C_ALGO_USB 0x170000 /* USB algorithm */
+#define I2C_ALGO_VIRT 0x180000 /* Virtual bus adapter */
+
+#define I2C_ALGO_MV64XXX 0x190000 /* Marvell mv64xxx i2c ctlr */
+#define I2C_ALGO_PCA 0x1a0000 /* PCA 9564 style adapters */
+#define I2C_ALGO_AU1550 0x1b0000 /* Au1550 PSC algorithm */
#define I2C_ALGO_EXP 0x800000 /* experimental */
@@ -240,6 +242,7 @@
#define I2C_HW_B_IXP4XX 0x17 /* GPIO on IXP4XX systems */
#define I2C_HW_B_S3VIA 0x18 /* S3Via ProSavage adapter */
#define I2C_HW_B_ZR36067 0x19 /* Zoran-36057/36067 based boards */
+#define I2C_HW_B_PCILYNX 0x1a /* TI PCILynx I2C adapter */
#define I2C_HW_B_CX2388x 0x1b /* connexant 2388x based tv cards */
/* --- PCF 8584 based algorithms */
@@ -310,4 +313,7 @@
/* --- MCP107 adapter */
#define I2C_HW_MPC107 0x00
+/* --- Marvell mv64xxx i2c adapter */
+#define I2C_HW_MV64XXX 0x00
+
#endif /* LINUX_I2C_ID_H */
diff --git a/include/linux/i2c.h b/include/linux/i2c.h
index 3000c102171e7..da901fd6b5908 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -55,7 +55,7 @@ extern int i2c_master_recv(struct i2c_client *,char* ,int);
/* Transfer num messages.
*/
-extern int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],int num);
+extern int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num);
/*
* Some adapter types (i.e. PCF 8584 based ones) may support slave behaviuor.
@@ -134,8 +134,6 @@ struct i2c_driver {
};
#define to_i2c_driver(d) container_of(d, struct i2c_driver, driver)
-extern struct bus_type i2c_bus_type;
-
#define I2C_NAME_SIZE 50
/*
@@ -144,7 +142,6 @@ extern struct bus_type i2c_bus_type;
* function is mainly used for lookup & other admin. functions.
*/
struct i2c_client {
- int id;
unsigned int flags; /* div., see below */
unsigned int addr; /* chip address - NOTE: 7bit */
/* addresses are stored in the */
@@ -190,11 +187,11 @@ struct i2c_algorithm {
char name[32]; /* textual description */
unsigned int id;
- /* If an adapter algorithm can't to I2C-level access, set master_xfer
+ /* If an adapter algorithm can't do I2C-level access, set master_xfer
to NULL. If an adapter algorithm can do SMBus access, set
smbus_xfer. If set to NULL, the SMBus protocol is simulated
using common I2C messages */
- int (*master_xfer)(struct i2c_adapter *adap,struct i2c_msg msgs[],
+ int (*master_xfer)(struct i2c_adapter *adap,struct i2c_msg *msgs,
int num);
int (*smbus_xfer) (struct i2c_adapter *adap, u16 addr,
unsigned short flags, char read_write,
@@ -302,8 +299,8 @@ struct i2c_client_address_data {
};
/* Internal numbers to terminate lists */
-#define I2C_CLIENT_END 0xfffe
-#define I2C_CLIENT_ISA_END 0xfffefffe
+#define I2C_CLIENT_END 0xfffeU
+#define I2C_CLIENT_ISA_END 0xfffefffeU
/* The numbers to use to set I2C bus address */
#define ANY_I2C_BUS 0xffff
@@ -423,22 +420,22 @@ struct i2c_msg {
#define I2C_FUNC_SMBUS_READ_BLOCK_DATA_PEC 0x40000000 /* SMBus 2.0 */
#define I2C_FUNC_SMBUS_WRITE_BLOCK_DATA_PEC 0x80000000 /* SMBus 2.0 */
-#define I2C_FUNC_SMBUS_BYTE I2C_FUNC_SMBUS_READ_BYTE | \
- I2C_FUNC_SMBUS_WRITE_BYTE
-#define I2C_FUNC_SMBUS_BYTE_DATA I2C_FUNC_SMBUS_READ_BYTE_DATA | \
- I2C_FUNC_SMBUS_WRITE_BYTE_DATA
-#define I2C_FUNC_SMBUS_WORD_DATA I2C_FUNC_SMBUS_READ_WORD_DATA | \
- I2C_FUNC_SMBUS_WRITE_WORD_DATA
-#define I2C_FUNC_SMBUS_BLOCK_DATA I2C_FUNC_SMBUS_READ_BLOCK_DATA | \
- I2C_FUNC_SMBUS_WRITE_BLOCK_DATA
-#define I2C_FUNC_SMBUS_I2C_BLOCK I2C_FUNC_SMBUS_READ_I2C_BLOCK | \
- I2C_FUNC_SMBUS_WRITE_I2C_BLOCK
-#define I2C_FUNC_SMBUS_I2C_BLOCK_2 I2C_FUNC_SMBUS_READ_I2C_BLOCK_2 | \
- I2C_FUNC_SMBUS_WRITE_I2C_BLOCK_2
-#define I2C_FUNC_SMBUS_BLOCK_DATA_PEC I2C_FUNC_SMBUS_READ_BLOCK_DATA_PEC | \
- I2C_FUNC_SMBUS_WRITE_BLOCK_DATA_PEC
-#define I2C_FUNC_SMBUS_WORD_DATA_PEC I2C_FUNC_SMBUS_READ_WORD_DATA_PEC | \
- I2C_FUNC_SMBUS_WRITE_WORD_DATA_PEC
+#define I2C_FUNC_SMBUS_BYTE (I2C_FUNC_SMBUS_READ_BYTE | \
+ I2C_FUNC_SMBUS_WRITE_BYTE)
+#define I2C_FUNC_SMBUS_BYTE_DATA (I2C_FUNC_SMBUS_READ_BYTE_DATA | \
+ I2C_FUNC_SMBUS_WRITE_BYTE_DATA)
+#define I2C_FUNC_SMBUS_WORD_DATA (I2C_FUNC_SMBUS_READ_WORD_DATA | \
+ I2C_FUNC_SMBUS_WRITE_WORD_DATA)
+#define I2C_FUNC_SMBUS_BLOCK_DATA (I2C_FUNC_SMBUS_READ_BLOCK_DATA | \
+ I2C_FUNC_SMBUS_WRITE_BLOCK_DATA)
+#define I2C_FUNC_SMBUS_I2C_BLOCK (I2C_FUNC_SMBUS_READ_I2C_BLOCK | \
+ I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)
+#define I2C_FUNC_SMBUS_I2C_BLOCK_2 (I2C_FUNC_SMBUS_READ_I2C_BLOCK_2 | \
+ I2C_FUNC_SMBUS_WRITE_I2C_BLOCK_2)
+#define I2C_FUNC_SMBUS_BLOCK_DATA_PEC (I2C_FUNC_SMBUS_READ_BLOCK_DATA_PEC | \
+ I2C_FUNC_SMBUS_WRITE_BLOCK_DATA_PEC)
+#define I2C_FUNC_SMBUS_WORD_DATA_PEC (I2C_FUNC_SMBUS_READ_WORD_DATA_PEC | \
+ I2C_FUNC_SMBUS_WRITE_WORD_DATA_PEC)
#define I2C_FUNC_SMBUS_READ_BYTE_PEC I2C_FUNC_SMBUS_READ_BYTE_DATA
#define I2C_FUNC_SMBUS_WRITE_BYTE_PEC I2C_FUNC_SMBUS_WRITE_BYTE_DATA
@@ -447,14 +444,14 @@ struct i2c_msg {
#define I2C_FUNC_SMBUS_BYTE_PEC I2C_FUNC_SMBUS_BYTE_DATA
#define I2C_FUNC_SMBUS_BYTE_DATA_PEC I2C_FUNC_SMBUS_WORD_DATA
-#define I2C_FUNC_SMBUS_EMUL I2C_FUNC_SMBUS_QUICK | \
- I2C_FUNC_SMBUS_BYTE | \
- I2C_FUNC_SMBUS_BYTE_DATA | \
- I2C_FUNC_SMBUS_WORD_DATA | \
- I2C_FUNC_SMBUS_PROC_CALL | \
- I2C_FUNC_SMBUS_WRITE_BLOCK_DATA | \
- I2C_FUNC_SMBUS_WRITE_BLOCK_DATA_PEC | \
- I2C_FUNC_SMBUS_I2C_BLOCK
+#define I2C_FUNC_SMBUS_EMUL (I2C_FUNC_SMBUS_QUICK | \
+ I2C_FUNC_SMBUS_BYTE | \
+ I2C_FUNC_SMBUS_BYTE_DATA | \
+ I2C_FUNC_SMBUS_WORD_DATA | \
+ I2C_FUNC_SMBUS_PROC_CALL | \
+ I2C_FUNC_SMBUS_WRITE_BLOCK_DATA | \
+ I2C_FUNC_SMBUS_WRITE_BLOCK_DATA_PEC | \
+ I2C_FUNC_SMBUS_I2C_BLOCK)
/*
* Data for SMBus Messages
diff --git a/include/linux/ibmtr.h b/include/linux/ibmtr.h
index dd8cbdc9f1a80..2ef0b21517fbd 100644
--- a/include/linux/ibmtr.h
+++ b/include/linux/ibmtr.h
@@ -169,7 +169,7 @@ typedef enum { CLOSED, OPEN } open_state;
struct tok_info {
unsigned char irq;
- void *mmio;
+ void __iomem *mmio;
unsigned char hw_address[32];
unsigned char adapter_type;
unsigned char data_rate;
@@ -192,12 +192,13 @@ struct tok_info {
/* Additions by Peter De Schrijver */
unsigned char page_mask; /* mask to select RAM page to Map*/
unsigned char mapped_ram_size; /* size of RAM page */
- __u32 sram_virt; /* Shared memory base address */
- __u32 init_srb; /* Initial System Request Block address */
- __u32 srb; /* System Request Block address */
- __u32 ssb; /* System Status Block address */
- __u32 arb; /* Adapter Request Block address */
- __u32 asb; /* Adapter Status Block address */
+ __u32 sram_phys; /* Shared memory base address */
+ void __iomem *sram_virt; /* Shared memory base address */
+ void __iomem *init_srb; /* Initial System Request Block address */
+ void __iomem *srb; /* System Request Block address */
+ void __iomem *ssb; /* System Status Block address */
+ void __iomem *arb; /* Adapter Request Block address */
+ void __iomem *asb; /* Adapter Status Block address */
__u8 init_srb_page;
__u8 srb_page;
__u8 ssb_page;
diff --git a/include/linux/ide.h b/include/linux/ide.h
index ea70213a94d3c..58d91a9d53325 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -718,6 +718,7 @@ typedef struct ide_drive_s {
*/
unsigned scsi : 1; /* 0=default, 1=ide-scsi emulation */
unsigned sleeping : 1; /* 1=sleeping & sleep field valid */
+ unsigned post_reset : 1;
u8 quirk_list; /* considered quirky, set for a specific host */
u8 init_speed; /* transfer rate set at boot */
@@ -740,7 +741,6 @@ typedef struct ide_drive_s {
u8 sect; /* "real" sectors per track */
u8 bios_head; /* BIOS/fdisk/LILO number of heads */
u8 bios_sect; /* BIOS/fdisk/LILO sectors per track */
- u8 doing_barrier; /* state, 1=currently doing flush */
unsigned int bios_cyl; /* BIOS/fdisk/LILO number of cyls */
unsigned int cyl; /* "real" number of cyls */
@@ -797,7 +797,7 @@ typedef struct hwif_s {
struct pci_dev *pci_dev; /* for pci chipsets */
struct ide_pci_device_s *cds; /* chipset device struct */
- ide_startstop_t (*rw_disk)(ide_drive_t *, struct request *, sector_t);
+ void (*rw_disk)(ide_drive_t *, struct request *);
#if 0
ide_hwif_ops_t *hwifops;
@@ -934,9 +934,9 @@ typedef struct hwgroup_s {
/* BOOL: protects all fields below */
volatile int busy;
/* BOOL: wake us up on timer expiry */
- int sleeping : 1;
+ unsigned int sleeping : 1;
/* BOOL: polling active & poll_timeout field valid */
- int polling : 1;
+ unsigned int polling : 1;
/* current drive */
ide_drive_t *drive;
/* ptr to current hwif in linked-list */
@@ -1098,15 +1098,10 @@ typedef struct ide_driver_s {
ide_startstop_t (*error)(ide_drive_t *, struct request *rq, u8, u8);
ide_startstop_t (*abort)(ide_drive_t *, struct request *rq);
int (*ioctl)(ide_drive_t *, struct inode *, struct file *, unsigned int, unsigned long);
- void (*pre_reset)(ide_drive_t *);
- sector_t (*capacity)(ide_drive_t *);
- ide_startstop_t (*special)(ide_drive_t *);
ide_proc_entry_t *proc;
int (*attach)(ide_drive_t *);
void (*ata_prebuilder)(ide_drive_t *);
void (*atapi_prebuilder)(ide_drive_t *);
- ide_startstop_t (*start_power_step)(ide_drive_t *, struct request *);
- void (*complete_power_step)(ide_drive_t *, struct request *, u8, u8);
struct device_driver gen_driver;
struct list_head drives;
struct list_head drivers;
@@ -1114,7 +1109,7 @@ typedef struct ide_driver_s {
#define DRIVER(drive) ((drive)->driver)
-extern int generic_ide_ioctl(struct file *, struct block_device *, unsigned, unsigned long);
+int generic_ide_ioctl(ide_drive_t *, struct file *, struct block_device *, unsigned, unsigned long);
/*
* ide_hwifs[] is the master data structure used to keep track
@@ -1130,6 +1125,7 @@ extern ide_hwif_t ide_hwifs[]; /* master data repository */
extern int noautodma;
extern int ide_end_request (ide_drive_t *drive, int uptodate, int nrsecs);
+extern int __ide_end_request (ide_drive_t *drive, struct request *rq, int uptodate, int nrsecs);
/*
* This is used on exit from the driver to designate the next irq handler
@@ -1318,7 +1314,6 @@ extern int set_transfer(ide_drive_t *, ide_task_t *);
extern int taskfile_lib_get_identify(ide_drive_t *drive, u8 *);
extern int ide_wait_not_busy(ide_hwif_t *hwif, unsigned long timeout);
-ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq, sector_t block);
/*
* ide_stall_queue() can be used by a drive to give excess bandwidth back
diff --git a/include/linux/if_ec.h b/include/linux/if_ec.h
index d654666f10671..e7499aa797833 100644
--- a/include/linux/if_ec.h
+++ b/include/linux/if_ec.h
@@ -47,8 +47,9 @@ struct ec_framehdr
unsigned char port;
};
-struct econet_opt
-{
+struct econet_sock {
+ /* struct sock has to be the first member of econet_sock */
+ struct sock sk;
unsigned char cb;
unsigned char port;
unsigned char station;
@@ -56,7 +57,10 @@ struct econet_opt
unsigned short num;
};
-#define ec_sk(__sk) ((struct econet_opt *)(__sk)->sk_protinfo)
+static inline struct econet_sock *ec_sk(const struct sock *sk)
+{
+ return (struct econet_sock *)sk;
+}
struct ec_device
{
diff --git a/include/linux/if_pppox.h b/include/linux/if_pppox.h
index 1030b41e22543..e677f73f13dd7 100644
--- a/include/linux/if_pppox.h
+++ b/include/linux/if_pppox.h
@@ -119,10 +119,13 @@ struct pppoe_opt {
relayed to (PPPoE relaying) */
};
-struct pppox_opt {
+#include <net/sock.h>
+
+struct pppox_sock {
+ /* struct sock must be the first member of pppox_sock */
+ struct sock sk;
struct ppp_channel chan;
- struct sock *sk;
- struct pppox_opt *next; /* for hash table */
+ struct pppox_sock *next; /* for hash table */
union {
struct pppoe_opt pppoe;
} proto;
@@ -132,7 +135,15 @@ struct pppox_opt {
#define pppoe_pa proto.pppoe.pa
#define pppoe_relay proto.pppoe.relay
-#define pppox_sk(__sk) ((struct pppox_opt *)(__sk)->sk_protinfo)
+static inline struct pppox_sock *pppox_sk(struct sock *sk)
+{
+ return (struct pppox_sock *)sk;
+}
+
+static inline struct sock *sk_pppox(struct pppox_sock *po)
+{
+ return (struct sock *)po;
+}
struct module;
diff --git a/include/linux/inetdevice.h b/include/linux/inetdevice.h
index 6fafb27877a7d..e04b71cd9e731 100644
--- a/include/linux/inetdevice.h
+++ b/include/linux/inetdevice.h
@@ -7,6 +7,7 @@
#include <linux/netdevice.h>
#include <linux/rcupdate.h>
#include <linux/timer.h>
+#include <linux/rtnetlink.h>
struct ipv4_devconf
{
@@ -131,6 +132,25 @@ static __inline__ int bad_mask(u32 mask, u32 addr)
return 0;
}
+static inline int inet_ifa_match_local_prefixlen(struct ifaddrmsg *ifm,
+ struct in_ifaddr *ifa)
+{
+ int real_prefixlen = IFA_REAL_DEL_PREFIX(ifm->ifa_prefixlen);
+
+ /*
+ * Since the prefix length hasn't been taken into account in
+ * previous kernel versions, parts of the userspace rely on the fact
+ * that the deletion of an address without specifying a prefix works.
+ * We cannot break this and thus a prefix length of 32 still represents
+ * a wildcard if no exact match is requested.
+ */
+ if (real_prefixlen != 32 || ifm->ifa_prefixlen & IFA_PREFIX_EXACT_DEL)
+ if (real_prefixlen != ifa->ifa_prefixlen)
+ return 0;
+
+ return 1;
+}
+
#define for_primary_ifa(in_dev) { struct in_ifaddr *ifa; \
for (ifa = (in_dev)->ifa_list; ifa && !(ifa->ifa_flags&IFA_F_SECONDARY); ifa = ifa->ifa_next)
diff --git a/include/linux/init_task.h b/include/linux/init_task.h
index 6498e9da9ce63..a6a8c1a38d5e4 100644
--- a/include/linux/init_task.h
+++ b/include/linux/init_task.h
@@ -51,6 +51,7 @@
.list = LIST_HEAD_INIT(sig.shared_pending.list), \
.signal = {{0}}}, \
.posix_timers = LIST_HEAD_INIT(sig.posix_timers), \
+ .cpu_timers = INIT_CPU_TIMERS(sig.cpu_timers), \
.rlim = INIT_RLIMITS, \
}
@@ -89,9 +90,6 @@ extern struct group_info init_groups;
.children = LIST_HEAD_INIT(tsk.children), \
.sibling = LIST_HEAD_INIT(tsk.sibling), \
.group_leader = &tsk, \
- .real_timer = { \
- .function = it_real_fn \
- }, \
.group_info = &init_groups, \
.cap_effective = CAP_INIT_EFF_SET, \
.cap_inheritable = CAP_INIT_INH_SET, \
@@ -112,8 +110,16 @@ extern struct group_info init_groups;
.proc_lock = SPIN_LOCK_UNLOCKED, \
.switch_lock = SPIN_LOCK_UNLOCKED, \
.journal_info = NULL, \
+ .cpu_timers = INIT_CPU_TIMERS(tsk.cpu_timers), \
}
+#define INIT_CPU_TIMERS(cpu_timers) \
+{ \
+ LIST_HEAD_INIT(cpu_timers[0]), \
+ LIST_HEAD_INIT(cpu_timers[1]), \
+ LIST_HEAD_INIT(cpu_timers[2]), \
+}
+
#endif
diff --git a/include/linux/input.h b/include/linux/input.h
index aa204097f06bf..b70df8fe60e67 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -771,7 +771,7 @@ struct ff_effect {
#include <linux/fs.h>
#include <linux/timer.h>
-#define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1)
+#define NBITS(x) (((x)/BITS_PER_LONG)+1)
#define BIT(x) (1UL<<((x)%BITS_PER_LONG))
#define LONG(x) ((x)/BITS_PER_LONG)
diff --git a/include/linux/ioc4_common.h b/include/linux/ioc4_common.h
new file mode 100644
index 0000000000000..b03bcc46df551
--- /dev/null
+++ b/include/linux/ioc4_common.h
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+#ifndef _LINUX_IOC4_COMMON_H
+#define _LINUX_IOC4_COMMON_H
+
+/* prototypes */
+
+int ioc4_serial_init(void);
+
+int ioc4_serial_attach_one(struct pci_dev *pdev, const struct
+ pci_device_id *pci_id);
+int ioc4_ide_attach_one(struct pci_dev *pdev, const struct
+ pci_device_id *pci_id);
+
+#endif /* _LINUX_IOC4_COMMON_H */
diff --git a/include/linux/ioport.h b/include/linux/ioport.h
index 62d042099e890..18d010bee635d 100644
--- a/include/linux/ioport.h
+++ b/include/linux/ioport.h
@@ -91,8 +91,6 @@ struct resource_list {
extern struct resource ioport_resource;
extern struct resource iomem_resource;
-extern int get_resource_list(struct resource *, char *buf, int size);
-
extern int request_resource(struct resource *root, struct resource *new);
extern struct resource * ____request_resource(struct resource *root, struct resource *new);
extern int release_resource(struct resource *new);
diff --git a/include/linux/ip.h b/include/linux/ip.h
index 487152a404f82..53a5afeb4e79c 100644
--- a/include/linux/ip.h
+++ b/include/linux/ip.h
@@ -121,18 +121,18 @@ struct inet_sock {
__u16 dport; /* Destination port */
__u16 num; /* Local port */
__u32 saddr; /* Sending source */
- int uc_ttl; /* Unicast TTL */
- int tos; /* TOS */
- unsigned cmsg_flags;
+ __s16 uc_ttl; /* Unicast TTL */
+ __u16 cmsg_flags;
struct ip_options *opt;
__u16 sport; /* Source port */
- unsigned char hdrincl; /* Include headers ? */
+ __u16 id; /* ID counter for DF pkts */
+ __u8 tos; /* TOS */
__u8 mc_ttl; /* Multicasting TTL */
- __u8 mc_loop; /* Loopback */
__u8 pmtudisc;
- __u16 id; /* ID counter for DF pkts */
unsigned recverr : 1,
- freebind : 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 */
@@ -152,6 +152,7 @@ struct inet_sock {
};
#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)
{
diff --git a/include/linux/ip_mp_alg.h b/include/linux/ip_mp_alg.h
new file mode 100644
index 0000000000000..e234e2008f5d3
--- /dev/null
+++ b/include/linux/ip_mp_alg.h
@@ -0,0 +1,22 @@
+/* ip_mp_alg.h: IPV4 multipath algorithm support, user-visible values.
+ *
+ * Copyright (C) 2004, 2005 Einar Lueck <elueck@de.ibm.com>
+ * Copyright (C) 2005 David S. Miller <davem@davemloft.net>
+ */
+
+#ifndef _LINUX_IP_MP_ALG_H
+#define _LINUX_IP_MP_ALG_H
+
+enum ip_mp_alg {
+ IP_MP_ALG_NONE,
+ IP_MP_ALG_RR,
+ IP_MP_ALG_DRR,
+ IP_MP_ALG_RANDOM,
+ IP_MP_ALG_WRANDOM,
+ __IP_MP_ALG_MAX
+};
+
+#define IP_MP_ALG_MAX (__IP_MP_ALG_MAX - 1)
+
+#endif /* _LINUX_IP_MP_ALG_H */
+
diff --git a/include/linux/ipmi_smi.h b/include/linux/ipmi_smi.h
index 88dd37439078b..e36ee157ad67f 100644
--- a/include/linux/ipmi_smi.h
+++ b/include/linux/ipmi_smi.h
@@ -104,13 +104,22 @@ struct ipmi_smi_handlers
/* Called to poll for work to do. This is so upper layers can
poll for operations during things like crash dumps. */
void (*poll)(void *send_info);
+
+ /* Tell the handler that we are using it/not using it. The
+ message handler get the modules that this handler belongs
+ to; this function lets the SMI claim any modules that it
+ uses. These may be NULL if this is not required. */
+ int (*inc_usecount)(void *send_info);
+ void (*dec_usecount)(void *send_info);
};
-/* Add a low-level interface to the IPMI driver. */
+/* Add a low-level interface to the IPMI driver. Note that if the
+ interface doesn't know its slave address, it should pass in zero. */
int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
void *send_info,
unsigned char version_major,
unsigned char version_minor,
+ unsigned char slave_addr,
ipmi_smi_t *intf);
/*
diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
index 939942384b788..ab0d0efbf2401 100644
--- a/include/linux/ipv6.h
+++ b/include/linux/ipv6.h
@@ -209,8 +209,8 @@ struct ipv6_pinfo {
__u32 flow_label;
__u32 frag_size;
- int hop_limit;
- int mcast_hops;
+ __s16 hop_limit;
+ __s16 mcast_hops;
int mcast_oif;
/* pktoption flags */
@@ -233,10 +233,11 @@ struct ipv6_pinfo {
pmtudisc:2,
ipv6only:1;
+ __u32 dst_cookie;
+
struct ipv6_mc_socklist *ipv6_mc_list;
struct ipv6_ac_socklist *ipv6_ac_list;
struct ipv6_fl_socklist *ipv6_fl_list;
- __u32 dst_cookie;
struct ipv6_txoptions *opt;
struct sk_buff *pktoptions;
diff --git a/include/linux/isapnp.h b/include/linux/isapnp.h
index b929eee854abc..26c64c286f421 100644
--- a/include/linux/isapnp.h
+++ b/include/linux/isapnp.h
@@ -100,16 +100,7 @@ int isapnp_present(void);
int isapnp_cfg_begin(int csn, int device);
int isapnp_cfg_end(void);
unsigned char isapnp_read_byte(unsigned char idx);
-unsigned short isapnp_read_word(unsigned char idx);
-unsigned int isapnp_read_dword(unsigned char idx);
void isapnp_write_byte(unsigned char idx, unsigned char val);
-void isapnp_write_word(unsigned char idx, unsigned short val);
-void isapnp_write_dword(unsigned char idx, unsigned int val);
-void isapnp_wake(unsigned char csn);
-void isapnp_device(unsigned char device);
-void isapnp_activate(unsigned char device);
-void isapnp_deactivate(unsigned char device);
-void *isapnp_alloc(long size);
#ifdef CONFIG_PROC_FS
int isapnp_proc_init(void);
@@ -119,9 +110,6 @@ static inline int isapnp_proc_init(void) { return 0; }
static inline int isapnp_proc_done(void) { return 0; }
#endif
-/* init/main.c */
-int isapnp_init(void);
-
/* compat */
struct pnp_card *pnp_find_card(unsigned short vendor,
unsigned short device,
@@ -138,15 +126,7 @@ static inline int isapnp_present(void) { return 0; }
static inline int isapnp_cfg_begin(int csn, int device) { return -ENODEV; }
static inline int isapnp_cfg_end(void) { return -ENODEV; }
static inline unsigned char isapnp_read_byte(unsigned char idx) { return 0xff; }
-static inline unsigned short isapnp_read_word(unsigned char idx) { return 0xffff; }
-static inline unsigned int isapnp_read_dword(unsigned char idx) { return 0xffffffff; }
static inline void isapnp_write_byte(unsigned char idx, unsigned char val) { ; }
-static inline void isapnp_write_word(unsigned char idx, unsigned short val) { ; }
-static inline void isapnp_write_dword(unsigned char idx, unsigned int val) { ; }
-static inline void isapnp_wake(unsigned char csn) { ; }
-static inline void isapnp_device(unsigned char device) { ; }
-static inline void isapnp_activate(unsigned char device) { ; }
-static inline void isapnp_deactivate(unsigned char device) { ; }
static inline struct pnp_card *pnp_find_card(unsigned short vendor,
unsigned short device,
diff --git a/include/linux/jbd.h b/include/linux/jbd.h
index f857ff09921d5..593407e865b1b 100644
--- a/include/linux/jbd.h
+++ b/include/linux/jbd.h
@@ -562,6 +562,7 @@ struct transaction_s
* @j_sb_buffer: First part of superblock buffer
* @j_superblock: Second part of superblock buffer
* @j_format_version: Version of the superblock format
+ * @j_state_lock: Protect the various scalars in the journal
* @j_barrier_count: Number of processes waiting to create a barrier lock
* @j_barrier: The barrier lock itself
* @j_running_transaction: The current running transaction..
@@ -589,6 +590,7 @@ struct transaction_s
* @j_fs_dev: Device which holds the client fs. For internal journal this will
* be equal to j_dev
* @j_maxlen: Total maximum capacity of the journal region on disk.
+ * @j_list_lock: Protects the buffer lists and internal buffer state.
* @j_inode: Optional inode where we store the journal. If present, all journal
* block numbers are mapped into this inode via bmap().
* @j_tail_sequence: Sequence number of the oldest transaction in the log
@@ -604,8 +606,11 @@ struct transaction_s
* @j_commit_interval: What is the maximum transaction lifetime before we begin
* a commit?
* @j_commit_timer: The timer used to wakeup the commit thread
+ * @j_revoke_lock: Protect the revoke table
* @j_revoke: The revoke table - maintains the list of revoked blocks in the
* current transaction.
+ * @j_revoke_table: alternate revoke tables for j_revoke
+ * @j_private: An opaque pointer to fs-private information.
*/
struct journal_s
@@ -789,6 +794,12 @@ struct journal_s
struct jbd_revoke_table_s *j_revoke_table[2];
/*
+ * array of bhs for journal_commit_transaction
+ */
+ struct buffer_head **j_wbuf;
+ int j_wbufsize;
+
+ /*
* An opaque pointer to fs-private information. ext3 puts its
* superblock pointer here
*/
@@ -811,6 +822,7 @@ struct journal_s
*/
/* Filing buffers */
+extern void __journal_temp_unlink_buffer(struct journal_head *jh);
extern void journal_unfile_buffer(journal_t *, struct journal_head *);
extern void __journal_unfile_buffer(struct journal_head *);
extern void __journal_refile_buffer(struct journal_head *);
@@ -867,15 +879,12 @@ static inline handle_t *journal_current_handle(void)
extern handle_t *journal_start(journal_t *, int nblocks);
extern int journal_restart (handle_t *, int nblocks);
extern int journal_extend (handle_t *, int nblocks);
-extern int journal_get_write_access(handle_t *, struct buffer_head *,
- int *credits);
+extern int journal_get_write_access(handle_t *, struct buffer_head *);
extern int journal_get_create_access (handle_t *, struct buffer_head *);
-extern int journal_get_undo_access(handle_t *, struct buffer_head *,
- int *credits);
+extern int journal_get_undo_access(handle_t *, struct buffer_head *);
extern int journal_dirty_data (handle_t *, struct buffer_head *);
extern int journal_dirty_metadata (handle_t *, struct buffer_head *);
-extern void journal_release_buffer (handle_t *, struct buffer_head *,
- int credits);
+extern void journal_release_buffer (handle_t *, struct buffer_head *);
extern int journal_forget (handle_t *, struct buffer_head *);
extern void journal_sync_buffer (struct buffer_head *);
extern int journal_invalidatepage(journal_t *,
@@ -926,7 +935,7 @@ void journal_put_journal_head(struct journal_head *jh);
*/
extern kmem_cache_t *jbd_handle_cache;
-static inline handle_t *jbd_alloc_handle(int gfp_flags)
+static inline handle_t *jbd_alloc_handle(unsigned int __nocast gfp_flags)
{
return kmem_cache_alloc(jbd_handle_cache, gfp_flags);
}
diff --git a/include/linux/jffs.h b/include/linux/jffs.h
index d0a98998654a1..92213215277f8 100644
--- a/include/linux/jffs.h
+++ b/include/linux/jffs.h
@@ -208,7 +208,6 @@ struct jffs_flash_status
#define JFFS_MEMORY_DEBUG 0
extern long no_jffs_node;
-extern long no_jffs_file;
#if defined(JFFS_MEMORY_DEBUG) && JFFS_MEMORY_DEBUG
extern long no_jffs_control;
extern long no_jffs_raw_inode;
diff --git a/include/linux/journal-head.h b/include/linux/journal-head.h
index 8751663d04cc9..8a62d1e84b9b4 100644
--- a/include/linux/journal-head.h
+++ b/include/linux/journal-head.h
@@ -32,6 +32,13 @@ struct journal_head {
unsigned b_jlist;
/*
+ * This flag signals the buffer has been modified by
+ * the currently running transaction
+ * [jbd_lock_bh_state()]
+ */
+ unsigned b_modified;
+
+ /*
* Copy of the buffer data frozen for writing to the log.
* [jbd_lock_bh_state()]
*/
diff --git a/include/linux/joystick.h b/include/linux/joystick.h
index 2cc4d7b56ee42..b7e0ab622cd7c 100644
--- a/include/linux/joystick.h
+++ b/include/linux/joystick.h
@@ -66,10 +66,10 @@ struct js_event {
#define JSIOCSCORR _IOW('j', 0x21, struct js_corr) /* set correction values */
#define JSIOCGCORR _IOR('j', 0x22, struct js_corr) /* get correction values */
-#define JSIOCSAXMAP _IOW('j', 0x31, __u8[ABS_MAX]) /* set axis mapping */
-#define JSIOCGAXMAP _IOR('j', 0x32, __u8[ABS_MAX]) /* get axis mapping */
-#define JSIOCSBTNMAP _IOW('j', 0x33, __u16[KEY_MAX - BTN_MISC]) /* set button mapping */
-#define JSIOCGBTNMAP _IOR('j', 0x34, __u16[KEY_MAX - BTN_MISC]) /* get button mapping */
+#define JSIOCSAXMAP _IOW('j', 0x31, __u8[ABS_MAX + 1]) /* set axis mapping */
+#define JSIOCGAXMAP _IOR('j', 0x32, __u8[ABS_MAX + 1]) /* get axis mapping */
+#define JSIOCSBTNMAP _IOW('j', 0x33, __u16[KEY_MAX - BTN_MISC + 1]) /* set button mapping */
+#define JSIOCGBTNMAP _IOR('j', 0x34, __u16[KEY_MAX - BTN_MISC + 1]) /* get button mapping */
/*
* Types and constants for get/set correction
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 806491a0ab594..7c1cba4a5278d 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -48,10 +48,20 @@ extern int console_printk[];
struct completion;
+/**
+ * might_sleep - annotation for functions that can sleep
+ *
+ * this macro will print a stack trace if it is executed in an atomic
+ * context (spinlock, irq-handler, ...).
+ *
+ * This is a useful debugging help to be able to catch problems early and not
+ * be biten later when the calling function happens to sleep when it is not
+ * supposed to.
+ */
#ifdef CONFIG_DEBUG_SPINLOCK_SLEEP
-void __might_sleep(char *file, int line);
#define might_sleep() __might_sleep(__FILE__, __LINE__)
#define might_sleep_if(cond) do { if (unlikely(cond)) might_sleep(); } while (0)
+void __might_sleep(char *file, int line);
#else
#define might_sleep() do {} while(0)
#define might_sleep_if(cond) do {} while (0)
@@ -81,17 +91,21 @@ extern unsigned long long simple_strtoull(const char *,char **,unsigned int);
extern long long simple_strtoll(const char *,char **,unsigned int);
extern int sprintf(char * buf, const char * fmt, ...)
__attribute__ ((format (printf, 2, 3)));
-extern int vsprintf(char *buf, const char *, va_list);
+extern int vsprintf(char *buf, const char *, va_list)
+ __attribute__ ((format (printf, 2, 0)));
extern int snprintf(char * buf, size_t size, const char * fmt, ...)
__attribute__ ((format (printf, 3, 4)));
-extern int vsnprintf(char *buf, size_t size, const char *fmt, va_list args);
+extern int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
+ __attribute__ ((format (printf, 3, 0)));
extern int scnprintf(char * buf, size_t size, const char * fmt, ...)
__attribute__ ((format (printf, 3, 4)));
-extern int vscnprintf(char *buf, size_t size, const char *fmt, va_list args);
+extern int vscnprintf(char *buf, size_t size, const char *fmt, va_list args)
+ __attribute__ ((format (printf, 3, 0)));
extern int sscanf(const char *, const char *, ...)
- __attribute__ ((format (scanf,2,3)));
-extern int vsscanf(const char *, const char *, va_list);
+ __attribute__ ((format (scanf, 2, 3)));
+extern int vsscanf(const char *, const char *, va_list)
+ __attribute__ ((format (scanf, 2, 0)));
extern int get_option(char **str, int *pint);
extern char *get_options(const char *str, int nints, int *ints);
@@ -101,7 +115,8 @@ extern int __kernel_text_address(unsigned long addr);
extern int kernel_text_address(unsigned long addr);
extern int session_of_pgrp(int pgrp);
-asmlinkage int vprintk(const char *fmt, va_list args);
+asmlinkage int vprintk(const char *fmt, va_list args)
+ __attribute__ ((format (printf, 1, 0)));
asmlinkage int printk(const char * fmt, ...)
__attribute__ ((format (printf, 1, 2)));
@@ -278,6 +293,12 @@ struct sysinfo {
extern void BUILD_BUG(void);
#define BUILD_BUG_ON(condition) do { if (condition) BUILD_BUG(); } while(0)
+#ifdef CONFIG_SYSCTL
+extern int randomize_va_space;
+#else
+#define randomize_va_space 1
+#endif
+
/* Trap pasters of __FUNCTION__ at compile-time */
#if __GNUC__ > 2 || __GNUC_MINOR__ >= 95
#define __FUNCTION__ (__func__)
diff --git a/include/linux/key.h b/include/linux/key.h
index 15eaba5373416..6aa46d0e812f9 100644
--- a/include/linux/key.h
+++ b/include/linux/key.h
@@ -58,6 +58,7 @@ struct key;
struct seq_file;
struct user_struct;
+struct signal_struct;
struct key_type;
struct key_owner;
@@ -258,7 +259,9 @@ extern struct key root_user_keyring, root_session_keyring;
extern int alloc_uid_keyring(struct user_struct *user);
extern void switch_uid_keyring(struct user_struct *new_user);
extern int copy_keys(unsigned long clone_flags, struct task_struct *tsk);
+extern int copy_thread_group_keys(struct task_struct *tsk);
extern void exit_keys(struct task_struct *tsk);
+extern void exit_thread_group_keys(struct signal_struct *tg);
extern int suid_keys(struct task_struct *tsk);
extern int exec_keys(struct task_struct *tsk);
extern void key_fsuid_changed(struct task_struct *tsk);
@@ -274,7 +277,9 @@ extern void key_init(void);
#define alloc_uid_keyring(u) 0
#define switch_uid_keyring(u) do { } while(0)
#define copy_keys(f,t) 0
+#define copy_thread_group_keys(t) 0
#define exit_keys(t) do { } while(0)
+#define exit_thread_group_keys(tg) do { } while(0)
#define suid_keys(t) do { } while(0)
#define exec_keys(t) do { } while(0)
#define key_fsuid_changed(t) do { } while(0)
diff --git a/include/linux/keyboard.h b/include/linux/keyboard.h
index f9c6ad75213a9..08488042d74a7 100644
--- a/include/linux/keyboard.h
+++ b/include/linux/keyboard.h
@@ -16,7 +16,7 @@
#define NR_SHIFT 9
-#define NR_KEYS 255
+#define NR_KEYS 256
#define MAX_NR_KEYMAPS 256
/* This means 128Kb if all keymaps are allocated. Only the superuser
may increase the number of keymaps beyond MAX_NR_OF_USER_KEYMAPS. */
@@ -27,7 +27,6 @@ extern const int NR_TYPES;
extern const int max_vals[];
extern unsigned short *key_maps[MAX_NR_KEYMAPS];
extern unsigned short plain_map[NR_KEYS];
-extern unsigned char keyboard_type;
#endif
#define MAX_NR_FUNC 256 /* max nr of strings assigned to keys */
diff --git a/include/linux/kfifo.h b/include/linux/kfifo.h
index 0e6e972a9f70c..c27cd428d2694 100644
--- a/include/linux/kfifo.h
+++ b/include/linux/kfifo.h
@@ -35,8 +35,8 @@ struct kfifo {
};
extern struct kfifo *kfifo_init(unsigned char *buffer, unsigned int size,
- int gfp_mask, spinlock_t *lock);
-extern struct kfifo *kfifo_alloc(unsigned int size, int gfp_mask,
+ unsigned int __nocast gfp_mask, spinlock_t *lock);
+extern struct kfifo *kfifo_alloc(unsigned int size, unsigned int __nocast gfp_mask,
spinlock_t *lock);
extern void kfifo_free(struct kfifo *fifo);
extern unsigned int __kfifo_put(struct kfifo *fifo,
@@ -44,7 +44,7 @@ extern unsigned int __kfifo_put(struct kfifo *fifo,
extern unsigned int __kfifo_get(struct kfifo *fifo,
unsigned char *buffer, unsigned int len);
-/*
+/**
* __kfifo_reset - removes the entire FIFO contents, no locking version
* @fifo: the fifo to be emptied.
*/
@@ -53,7 +53,7 @@ static inline void __kfifo_reset(struct kfifo *fifo)
fifo->in = fifo->out = 0;
}
-/*
+/**
* kfifo_reset - removes the entire FIFO contents
* @fifo: the fifo to be emptied.
*/
@@ -68,7 +68,7 @@ static inline void kfifo_reset(struct kfifo *fifo)
spin_unlock_irqrestore(fifo->lock, flags);
}
-/*
+/**
* kfifo_put - puts some data into the FIFO
* @fifo: the fifo to be used.
* @buffer: the data to be added.
@@ -93,7 +93,7 @@ static inline unsigned int kfifo_put(struct kfifo *fifo,
return ret;
}
-/*
+/**
* kfifo_get - gets some data from the FIFO
* @fifo: the fifo to be used.
* @buffer: where the data must be copied.
@@ -124,7 +124,7 @@ static inline unsigned int kfifo_get(struct kfifo *fifo,
return ret;
}
-/*
+/**
* __kfifo_len - returns the number of bytes available in the FIFO, no locking version
* @fifo: the fifo to be used.
*/
@@ -133,7 +133,7 @@ static inline unsigned int __kfifo_len(struct kfifo *fifo)
return fifo->in - fifo->out;
}
-/*
+/**
* kfifo_len - returns the number of bytes available in the FIFO
* @fifo: the fifo to be used.
*/
diff --git a/include/linux/kobj_map.h b/include/linux/kobj_map.h
index 404a945c1533f..b6cc10bf8dfca 100644
--- a/include/linux/kobj_map.h
+++ b/include/linux/kobj_map.h
@@ -7,6 +7,6 @@ int kobj_map(struct kobj_map *, dev_t, unsigned long, struct module *,
kobj_probe_t *, int (*)(dev_t, void *), void *);
void kobj_unmap(struct kobj_map *, dev_t, unsigned long);
struct kobject *kobj_lookup(struct kobj_map *, dev_t, int *);
-struct kobj_map *kobj_map_init(kobj_probe_t *, struct subsystem *);
+struct kobj_map *kobj_map_init(kobj_probe_t *, struct semaphore *);
#endif
diff --git a/include/linux/kobject.h b/include/linux/kobject.h
index dc773d4043e84..765d660d3bea4 100644
--- a/include/linux/kobject.h
+++ b/include/linux/kobject.h
@@ -20,6 +20,7 @@
#include <linux/types.h>
#include <linux/list.h>
#include <linux/sysfs.h>
+#include <linux/spinlock.h>
#include <linux/rwsem.h>
#include <linux/kref.h>
#include <linux/kobject_uevent.h>
@@ -102,6 +103,7 @@ struct kset {
struct subsystem * subsys;
struct kobj_type * ktype;
struct list_head list;
+ spinlock_t list_lock;
struct kobject kobj;
struct kset_hotplug_ops * hotplug_ops;
};
diff --git a/include/linux/kref.h b/include/linux/kref.h
index ea5948785ebfb..6fee3539893f6 100644
--- a/include/linux/kref.h
+++ b/include/linux/kref.h
@@ -26,7 +26,7 @@ struct kref {
void kref_init(struct kref *kref);
void kref_get(struct kref *kref);
-void kref_put(struct kref *kref, void (*release) (struct kref *kref));
+int kref_put(struct kref *kref, void (*release) (struct kref *kref));
#endif /* __KERNEL__ */
#endif /* _KREF_H_ */
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 5ba12aee9e92a..505160ab472b0 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -334,6 +334,8 @@ struct ata_port_operations {
void (*exec_command)(struct ata_port *ap, struct ata_taskfile *tf);
u8 (*check_status)(struct ata_port *ap);
+ u8 (*check_altstatus)(struct ata_port *ap);
+ u8 (*check_err)(struct ata_port *ap);
void (*dev_select)(struct ata_port *ap, unsigned int device);
void (*phy_reset) (struct ata_port *ap);
@@ -360,6 +362,9 @@ struct ata_port_operations {
void (*port_stop) (struct ata_port *ap);
void (*host_stop) (struct ata_host_set *host_set);
+
+ void (*bmdma_stop) (struct ata_port *ap);
+ u8 (*bmdma_status) (struct ata_port *ap);
};
struct ata_port_info {
@@ -400,6 +405,8 @@ extern void ata_tf_from_fis(u8 *fis, struct ata_taskfile *tf);
extern void ata_noop_dev_select (struct ata_port *ap, unsigned int device);
extern void ata_std_dev_select (struct ata_port *ap, unsigned int device);
extern u8 ata_check_status(struct ata_port *ap);
+extern u8 ata_altstatus(struct ata_port *ap);
+extern u8 ata_chk_err(struct ata_port *ap);
extern void ata_exec_command(struct ata_port *ap, struct ata_taskfile *tf);
extern int ata_port_start (struct ata_port *ap);
extern void ata_port_stop (struct ata_port *ap);
@@ -415,6 +422,8 @@ extern void ata_dev_id_string(u16 *id, unsigned char *s,
unsigned int ofs, unsigned int len);
extern void ata_bmdma_setup (struct ata_queued_cmd *qc);
extern void ata_bmdma_start (struct ata_queued_cmd *qc);
+extern void ata_bmdma_stop(struct ata_port *ap);
+extern u8 ata_bmdma_status(struct ata_port *ap);
extern void ata_bmdma_irq_clear(struct ata_port *ap);
extern void ata_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat);
extern void ata_eng_timeout(struct ata_port *ap);
@@ -452,26 +461,11 @@ static inline unsigned int ata_dev_present(struct ata_device *dev)
(dev->class == ATA_DEV_ATAPI));
}
-static inline u8 ata_chk_err(struct ata_port *ap)
-{
- if (ap->flags & ATA_FLAG_MMIO) {
- return readb((void __iomem *) ap->ioaddr.error_addr);
- }
- return inb(ap->ioaddr.error_addr);
-}
-
static inline u8 ata_chk_status(struct ata_port *ap)
{
return ap->ops->check_status(ap);
}
-static inline u8 ata_altstatus(struct ata_port *ap)
-{
- if (ap->flags & ATA_FLAG_MMIO)
- return readb((void __iomem *)ap->ioaddr.altstatus_addr);
- return inb(ap->ioaddr.altstatus_addr);
-}
-
static inline void ata_pause(struct ata_port *ap)
{
ata_altstatus(ap);
@@ -595,46 +589,6 @@ static inline unsigned int sata_dev_present(struct ata_port *ap)
return ((scr_read(ap, SCR_STATUS) & 0xf) == 0x3) ? 1 : 0;
}
-static inline void ata_bmdma_stop(struct ata_port *ap)
-{
- if (ap->flags & ATA_FLAG_MMIO) {
- void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
-
- /* clear start/stop bit */
- writeb(readb(mmio + ATA_DMA_CMD) & ~ATA_DMA_START,
- mmio + ATA_DMA_CMD);
- } else {
- /* clear start/stop bit */
- outb(inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD) & ~ATA_DMA_START,
- ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
- }
-
- /* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */
- ata_altstatus(ap); /* dummy read */
-}
-
-static inline void ata_bmdma_ack_irq(struct ata_port *ap)
-{
- if (ap->flags & ATA_FLAG_MMIO) {
- void __iomem *mmio = ((void __iomem *) ap->ioaddr.bmdma_addr) + ATA_DMA_STATUS;
- writeb(readb(mmio), mmio);
- } else {
- unsigned long addr = ap->ioaddr.bmdma_addr + ATA_DMA_STATUS;
- outb(inb(addr), addr);
- }
-}
-
-static inline u8 ata_bmdma_status(struct ata_port *ap)
-{
- u8 host_stat;
- if (ap->flags & ATA_FLAG_MMIO) {
- void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
- host_stat = readb(mmio + ATA_DMA_STATUS);
- } else
- host_stat = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
- return host_stat;
-}
-
static inline int ata_try_flush_cache(struct ata_device *dev)
{
return ata_id_wcache_enabled(dev->id) ||
diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h
index 5a173a673fc95..0d9d22578212c 100644
--- a/include/linux/lockd/lockd.h
+++ b/include/linux/lockd/lockd.h
@@ -42,7 +42,6 @@ struct nlm_host {
struct rpc_clnt * h_rpcclnt; /* RPC client to talk to peer */
char h_name[20]; /* remote hostname */
u32 h_version; /* interface version */
- rpc_authflavor_t h_authflavor; /* RPC authentication type */
unsigned short h_proto; /* transport proto */
unsigned short h_reclaiming : 1,
h_server : 1, /* server side, not client side */
@@ -143,8 +142,6 @@ extern unsigned long nlmsvc_timeout;
* Lockd client functions
*/
struct nlm_rqst * nlmclnt_alloc_call(void);
-int nlmclnt_call(struct nlm_rqst *, u32);
-int nlmclnt_async_call(struct nlm_rqst *, u32, rpc_action);
int nlmclnt_block(struct nlm_host *, struct file_lock *, u32 *);
int nlmclnt_cancel(struct nlm_host *, struct file_lock *);
u32 nlmclnt_grant(struct nlm_lock *);
diff --git a/include/linux/loop.h b/include/linux/loop.h
index 652124463a247..8220d9c9da007 100644
--- a/include/linux/loop.h
+++ b/include/linux/loop.h
@@ -71,7 +71,10 @@ struct loop_device {
/*
* Loop flags
*/
-#define LO_FLAGS_READ_ONLY 1
+enum {
+ LO_FLAGS_READ_ONLY = 1,
+ LO_FLAGS_USE_AOPS = 2,
+};
#include <asm/posix_types.h> /* for __kernel_old_dev_t */
#include <asm/types.h> /* for __u64 */
diff --git a/include/linux/major.h b/include/linux/major.h
index 8585730af4848..4b62c42b842c2 100644
--- a/include/linux/major.h
+++ b/include/linux/major.h
@@ -25,7 +25,6 @@
#define MISC_MAJOR 10
#define SCSI_CDROM_MAJOR 11
#define MUX_MAJOR 11 /* PA-RISC only */
-#define QIC02_TAPE_MAJOR 12
#define XT_DISK_MAJOR 13
#define INPUT_MAJOR 13
#define SOUND_MAJOR 14
diff --git a/include/linux/mempool.h b/include/linux/mempool.h
index bc77a394f25a5..4a36edf1c9743 100644
--- a/include/linux/mempool.h
+++ b/include/linux/mempool.h
@@ -6,7 +6,7 @@
#include <linux/wait.h>
-typedef void * (mempool_alloc_t)(int gfp_mask, void *pool_data);
+typedef void * (mempool_alloc_t)(unsigned int __nocast gfp_mask, void *pool_data);
typedef void (mempool_free_t)(void *element, void *pool_data);
typedef struct mempool_s {
@@ -22,16 +22,16 @@ typedef struct mempool_s {
} mempool_t;
extern mempool_t * mempool_create(int min_nr, mempool_alloc_t *alloc_fn,
mempool_free_t *free_fn, void *pool_data);
-extern int mempool_resize(mempool_t *pool, int new_min_nr, int gfp_mask);
+extern int mempool_resize(mempool_t *pool, int new_min_nr, unsigned int __nocast gfp_mask);
extern void mempool_destroy(mempool_t *pool);
-extern void * mempool_alloc(mempool_t *pool, int gfp_mask);
+extern void * mempool_alloc(mempool_t *pool, unsigned int __nocast gfp_mask);
extern void mempool_free(void *element, mempool_t *pool);
/*
* A mempool_alloc_t and mempool_free_t that get the memory from
* a slab that is passed in through pool_data.
*/
-void *mempool_alloc_slab(int gfp_mask, void *pool_data);
+void *mempool_alloc_slab(unsigned int __nocast gfp_mask, void *pool_data);
void mempool_free_slab(void *element, void *pool_data);
#endif /* _LINUX_MEMPOOL_H */
diff --git a/include/linux/mii.h b/include/linux/mii.h
index c674b2ec60036..20971fe78a8d3 100644
--- a/include/linux/mii.h
+++ b/include/linux/mii.h
@@ -20,6 +20,8 @@
#define MII_ADVERTISE 0x04 /* Advertisement control reg */
#define MII_LPA 0x05 /* Link partner ability reg */
#define MII_EXPANSION 0x06 /* Expansion register */
+#define MII_CTRL1000 0x09 /* 1000BASE-T control */
+#define MII_STAT1000 0x0a /* 1000BASE-T status */
#define MII_DCOUNTER 0x12 /* Disconnect counter */
#define MII_FCSCOUNTER 0x13 /* False carrier counter */
#define MII_NWAYTEST 0x14 /* N-way auto-neg test reg */
@@ -67,7 +69,9 @@
#define ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */
#define ADVERTISE_100FULL 0x0100 /* Try for 100mbps full-duplex */
#define ADVERTISE_100BASE4 0x0200 /* Try for 100mbps 4k packets */
-#define ADVERTISE_RESV 0x1c00 /* Unused... */
+#define ADVERTISE_PAUSE_CAP 0x0400 /* Try for pause */
+#define ADVERTISE_PAUSE_ASYM 0x0800 /* Try for asymetric pause */
+#define ADVERTISE_RESV 0x1000 /* Unused... */
#define ADVERTISE_RFAULT 0x2000 /* Say we can detect faults */
#define ADVERTISE_LPACK 0x4000 /* Ack link partners response */
#define ADVERTISE_NPAGE 0x8000 /* Next page bit */
@@ -84,7 +88,9 @@
#define LPA_100HALF 0x0080 /* Can do 100mbps half-duplex */
#define LPA_100FULL 0x0100 /* Can do 100mbps full-duplex */
#define LPA_100BASE4 0x0200 /* Can do 100mbps 4k packets */
-#define LPA_RESV 0x1c00 /* Unused... */
+#define LPA_PAUSE_CAP 0x0400 /* Can pause */
+#define LPA_PAUSE_ASYM 0x0800 /* Can pause asymetrically */
+#define LPA_RESV 0x1000 /* Unused... */
#define LPA_RFAULT 0x2000 /* Link partner faulted */
#define LPA_LPACK 0x4000 /* Link partner acked us */
#define LPA_NPAGE 0x8000 /* Next page bit */
@@ -105,6 +111,15 @@
#define NWAYTEST_LOOPBACK 0x0100 /* Enable loopback for N-way */
#define NWAYTEST_RESV2 0xfe00 /* Unused... */
+/* 1000BASE-T Control register */
+#define ADVERTISE_1000FULL 0x0200 /* Advertise 1000BASE-T full duplex */
+#define ADVERTISE_1000HALF 0x0100 /* Advertise 1000BASE-T half duplex */
+
+/* 1000BASE-T Status register */
+#define LPA_1000LOCALRXOK 0x2000 /* Link partner local receiver status */
+#define LPA_1000REMRXOK 0x1000 /* Link partner remote receiver status */
+#define LPA_1000FULL 0x0800 /* Link partner 1000BASE-T full duplex */
+#define LPA_1000HALF 0x0400 /* Link partner 1000BASE-T half duplex */
struct mii_if_info {
int phy_id;
@@ -114,6 +129,7 @@ struct mii_if_info {
unsigned int full_duplex : 1; /* is full duplex? */
unsigned int force_media : 1; /* is autoneg. disabled? */
+ unsigned int supports_gmii : 1; /* are GMII registers supported? */
struct net_device *dev;
int (*mdio_read) (struct net_device *dev, int phy_id, int location);
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 3a8c47c5dc9c1..418b928a66173 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -838,7 +838,7 @@ static inline void vm_stat_unaccount(struct vm_area_struct *vma)
}
/* update per process rss and vm hiwater data */
-extern void update_mem_hiwater(void);
+extern void update_mem_hiwater(struct task_struct *tsk);
#ifndef CONFIG_DEBUG_PAGEALLOC
static inline void
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index 44da5ac8f88f9..aefedf04b9bb2 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -75,7 +75,7 @@ struct mmc_driver {
struct device_driver drv;
int (*probe)(struct mmc_card *);
void (*remove)(struct mmc_card *);
- int (*suspend)(struct mmc_card *, u32);
+ int (*suspend)(struct mmc_card *, pm_message_t);
int (*resume)(struct mmc_card *);
};
diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h
index 8d30b2a725539..0d35d4ffb360d 100644
--- a/include/linux/mmc/mmc.h
+++ b/include/linux/mmc/mmc.h
@@ -37,6 +37,7 @@ struct mmc_command {
#define MMC_RSP_R1B (MMC_RSP_SHORT|MMC_RSP_CRC|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)
unsigned int retries; /* max number of retries */
unsigned int error; /* command error */
diff --git a/include/linux/mmc/protocol.h b/include/linux/mmc/protocol.h
index 5b79ed416e69a..7b904c5102f6b 100644
--- a/include/linux/mmc/protocol.h
+++ b/include/linux/mmc/protocol.h
@@ -76,6 +76,16 @@
#define MMC_APP_CMD 55 /* ac [31:16] RCA R1 */
#define MMC_GEN_CMD 56 /* adtc [0] RD/WR R1b */
+/* SD commands type argument response */
+ /* class 8 */
+/* This is basically the same command as for MMC with some quirks. */
+#define SD_SEND_RELATIVE_ADDR 3 /* ac R6 */
+
+ /* Application commands */
+#define SD_APP_SET_BUS_WIDTH 6 /* ac [1:0] bus width R1 */
+#define SD_APP_OP_COND 41 /* bcr [31:0] OCR R3 */
+#define SD_APP_SEND_SCR 51 /* adtc R1 */
+
/*
MMC status in R1
Type
@@ -113,7 +123,7 @@
#define R1_STATUS(x) (x & 0xFFFFE000)
#define R1_CURRENT_STATE(x) ((x & 0x00001E00) >> 9) /* sx, b (4 bits) */
#define R1_READY_FOR_DATA (1 << 8) /* sx, a */
-#define R1_APP_CMD (1 << 7) /* sr, c */
+#define R1_APP_CMD (1 << 5) /* sr, c */
/* These are unpacked versions of the actual responses */
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index a2b35dbc84f7d..e530c6c092f16 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -11,6 +11,7 @@
#include <linux/cache.h>
#include <linux/threads.h>
#include <linux/numa.h>
+#include <linux/init.h>
#include <asm/atomic.h>
/* Free memory management - zoned buddy allocator. */
@@ -278,6 +279,16 @@ void wakeup_kswapd(struct zone *zone, int order);
int zone_watermark_ok(struct zone *z, int order, unsigned long mark,
int alloc_type, int can_try_harder, int gfp_high);
+#ifdef CONFIG_HAVE_MEMORY_PRESENT
+void memory_present(int nid, unsigned long start, unsigned long end);
+#else
+static inline void memory_present(int nid, unsigned long start, unsigned long end) {}
+#endif
+
+#ifdef CONFIG_NEED_NODE_MEMMAP_SIZE
+unsigned long __init node_memmap_size_bytes(int, unsigned long, unsigned long);
+#endif
+
/*
* zone_idx() returns 0 for the ZONE_DMA zone, 1 for the ZONE_NORMAL zone, etc.
*/
diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h
index c0d7ce138d997..d6eb7b2efc043 100644
--- a/include/linux/mod_devicetable.h
+++ b/include/linux/mod_devicetable.h
@@ -165,4 +165,14 @@ struct pnp_card_device_id {
};
+#define SERIO_ANY 0xff
+
+struct serio_device_id {
+ __u8 type;
+ __u8 extra;
+ __u8 id;
+ __u8 proto;
+};
+
+
#endif /* LINUX_MOD_DEVICETABLE_H */
diff --git a/include/linux/module.h b/include/linux/module.h
index 7c66600fc66b4..0e432a0f4aee3 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -77,24 +77,14 @@ void sort_main_extable(void);
extern struct subsystem module_subsys;
#ifdef MODULE
-#define ___module_cat(a,b) __mod_ ## a ## b
-#define __module_cat(a,b) ___module_cat(a,b)
-#define __MODULE_INFO(tag, name, info) \
-static const char __module_cat(name,__LINE__)[] \
- __attribute_used__ \
- __attribute__((section(".modinfo"),unused)) = __stringify(tag) "=" info
-
#define MODULE_GENERIC_TABLE(gtype,name) \
extern const struct gtype##_id __mod_##gtype##_table \
__attribute__ ((unused, alias(__stringify(name))))
extern struct module __this_module;
#define THIS_MODULE (&__this_module)
-
#else /* !MODULE */
-
#define MODULE_GENERIC_TABLE(gtype,name)
-#define __MODULE_INFO(tag, name, info)
#define THIS_MODULE ((struct module *)0)
#endif
@@ -560,7 +550,8 @@ static inline void MODULE_PARM_(void) { }
/* DEPRECATED: Do not use. */
#define MODULE_PARM(var,type) \
struct obsolete_modparm __parm_##var __attribute__((section("__obsparm"))) = \
-{ __stringify(var), type, &MODULE_PARM_ };
+{ __stringify(var), type, &MODULE_PARM_ }; \
+__MODULE_PARM_TYPE(var, type);
#else
#define MODULE_PARM(var,type) static void __attribute__((__unused__)) *__parm_##var = &MODULE_PARM_;
#endif
@@ -572,7 +563,6 @@ struct obsolete_modparm __parm_##var __attribute__((section("__obsparm"))) = \
extern void __deprecated inter_module_register(const char *,
struct module *, const void *);
extern void __deprecated inter_module_unregister(const char *);
-extern const void * __deprecated inter_module_get(const char *);
extern const void * __deprecated inter_module_get_request(const char *,
const char *);
extern void __deprecated inter_module_put(const char *);
diff --git a/include/linux/moduleparam.h b/include/linux/moduleparam.h
index 685eab959c49a..368ec8e45bd0e 100644
--- a/include/linux/moduleparam.h
+++ b/include/linux/moduleparam.h
@@ -13,6 +13,19 @@
#define MODULE_PARAM_PREFIX __stringify(KBUILD_MODNAME) "."
#endif
+#ifdef MODULE
+#define ___module_cat(a,b) __mod_ ## a ## b
+#define __module_cat(a,b) ___module_cat(a,b)
+#define __MODULE_INFO(tag, name, info) \
+static const char __module_cat(name,__LINE__)[] \
+ __attribute_used__ \
+ __attribute__((section(".modinfo"),unused)) = __stringify(tag) "=" info
+#else /* !MODULE */
+#define __MODULE_INFO(tag, name, info)
+#endif
+#define __MODULE_PARM_TYPE(name, _type) \
+ __MODULE_INFO(parmtype, name##type, #name ":" _type)
+
struct kernel_param;
/* Returns 0, or -errno. arg is in kp->arg. */
@@ -65,7 +78,7 @@ struct kparam_array
#define module_param_named(name, value, type, perm) \
param_check_##type(name, &(value)); \
module_param_call(name, param_set_##type, param_get_##type, &value, perm); \
- __MODULE_INFO(parmtype, name##type, #name ":" #type)
+ __MODULE_PARM_TYPE(name, #type)
#define module_param(name, type, perm) \
module_param_named(name, name, type, perm)
@@ -76,7 +89,7 @@ struct kparam_array
= { len, string }; \
module_param_call(name, param_set_copystring, param_get_string, \
&__param_string_##name, perm); \
- __MODULE_INFO(parmtype, name##type, #name ":string")
+ __MODULE_PARM_TYPE(name, "string")
/* Called on module insert or kernel boot */
extern int parse_args(const char *name,
@@ -138,7 +151,7 @@ extern int param_get_invbool(char *buffer, struct kernel_param *kp);
sizeof(array[0]), array }; \
module_param_call(name, param_array_set, param_array_get, \
&__param_arr_##name, perm); \
- __MODULE_INFO(parmtype, name##type, #name ":array of " #type)
+ __MODULE_PARM_TYPE(name, "array of " #type)
#define module_param_array(name, type, nump, perm) \
module_param_array_named(name, name, type, nump, perm)
diff --git a/include/linux/mpage.h b/include/linux/mpage.h
index 86aa7b6762747..dea1b0083661c 100644
--- a/include/linux/mpage.h
+++ b/include/linux/mpage.h
@@ -11,12 +11,18 @@
*/
struct writeback_control;
+typedef int (writepage_t)(struct page *page, struct writeback_control *wbc);
int mpage_readpages(struct address_space *mapping, struct list_head *pages,
unsigned nr_pages, get_block_t get_block);
int mpage_readpage(struct page *page, get_block_t get_block);
int mpage_writepages(struct address_space *mapping,
struct writeback_control *wbc, get_block_t get_block);
+int mpage_writepage(struct page *page, get_block_t *get_block,
+ struct writeback_control *wbc);
+int __mpage_writepages(struct address_space *mapping,
+ struct writeback_control *wbc, get_block_t get_block,
+ writepage_t writepage);
static inline int
generic_writepages(struct address_space *mapping, struct writeback_control *wbc)
diff --git a/include/linux/msdos_fs.h b/include/linux/msdos_fs.h
index f40195a50ae6b..9a3d272579843 100644
--- a/include/linux/msdos_fs.h
+++ b/include/linux/msdos_fs.h
@@ -50,8 +50,6 @@
#define MSDOS_VALID_MODE (S_IFREG | S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO)
/* Convert attribute bits and a mask to the UNIX mode. */
#define MSDOS_MKMODE(a, m) (m & (a & ATTR_RO ? S_IRUGO|S_IXUGO : S_IRWXUGO))
-/* Convert the UNIX mode to MS-DOS attribute bits. */
-#define MSDOS_MKATTR(m) ((m & S_IWUGO) ? ATTR_NONE : ATTR_RO)
#define MSDOS_NAME 11 /* maximum name length */
#define MSDOS_LONGNAME 256 /* maximum name length */
@@ -78,15 +76,11 @@
#define BAD_FAT12 0xFF7
#define BAD_FAT16 0xFFF7
#define BAD_FAT32 0x0FFFFFF7
-#define BAD_FAT(s) (MSDOS_SB(s)->fat_bits == 32 ? BAD_FAT32 : \
- MSDOS_SB(s)->fat_bits == 16 ? BAD_FAT16 : BAD_FAT12)
/* standard EOF */
#define EOF_FAT12 0xFFF
#define EOF_FAT16 0xFFFF
#define EOF_FAT32 0x0FFFFFFF
-#define EOF_FAT(s) (MSDOS_SB(s)->fat_bits == 32 ? EOF_FAT32 : \
- MSDOS_SB(s)->fat_bits == 16 ? EOF_FAT16 : EOF_FAT12)
#define FAT_ENT_FREE (0)
#define FAT_ENT_BAD (BAD_FAT32)
@@ -100,8 +94,11 @@
/*
* ioctl commands
*/
-#define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct dirent [2])
-#define VFAT_IOCTL_READDIR_SHORT _IOR('r', 2, struct dirent [2])
+#define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct dirent [2])
+#define VFAT_IOCTL_READDIR_SHORT _IOR('r', 2, struct dirent [2])
+/* <linux/videotext.h> has used 0x72 ('r') in collision, so skip a few */
+#define FAT_IOCTL_GET_ATTRIBUTES _IOR('r', 0x10, __u32)
+#define FAT_IOCTL_SET_ATTRIBUTES _IOW('r', 0x11, __u32)
/*
* vfat shortname flags
@@ -152,7 +149,7 @@ struct msdos_dir_entry {
__u8 name[8],ext[3]; /* name and extension */
__u8 attr; /* attribute bits */
__u8 lcase; /* Case for base and extension */
- __u8 ctime_ms; /* Creation time, milliseconds */
+ __u8 ctime_cs; /* Creation time, centiseconds (0-199) */
__le16 ctime; /* Creation time */
__le16 cdate; /* Creation date */
__le16 adate; /* Last access date */
@@ -173,10 +170,12 @@ struct msdos_dir_slot {
__u8 name11_12[4]; /* last 2 characters in name */
};
-struct vfat_slot_info {
- int long_slots; /* number of long slots in filename */
- loff_t longname_offset; /* dir offset for longname start */
+struct fat_slot_info {
loff_t i_pos; /* on-disk position of directory entry */
+ loff_t slot_off; /* offset for slot or de start */
+ int nr_slots; /* number of slots + 1(de) in filename */
+ struct msdos_dir_entry *de;
+ struct buffer_head *bh;
};
#ifdef __KERNEL__
@@ -228,8 +227,8 @@ struct msdos_sb_info {
unsigned long root_cluster; /* first cluster of the root directory */
unsigned long fsinfo_sector; /* sector number of FAT32 fsinfo */
struct semaphore fat_lock;
- int prev_free; /* previously allocated cluster number */
- int free_clusters; /* -1 if undefined */
+ unsigned int prev_free; /* previously allocated cluster number */
+ unsigned int free_clusters; /* -1 if undefined */
struct fat_mount_options options;
struct nls_table *nls_disk; /* Codepage used on disk */
struct nls_table *nls_io; /* Charset used for input and display */
@@ -237,6 +236,9 @@ struct msdos_sb_info {
int dir_per_block; /* dir entries per block */
int dir_per_block_bits; /* log2(dir_per_block) */
+ int fatent_shift;
+ struct fatent_operations *fatent_ops;
+
spinlock_t inode_hash_lock;
struct hlist_head inode_hashtable[FAT_HASH_SIZE];
};
@@ -257,7 +259,6 @@ struct msdos_inode_info {
int i_start; /* first cluster or 0 */
int i_logstart; /* logical first cluster */
int i_attrs; /* unused attribute bits */
- int i_ctime_ms; /* unused change time in milliseconds */
loff_t i_pos; /* on-disk position of directory entry or 0 */
struct hlist_node i_fat_hash; /* hash by i_location */
struct inode vfs_inode;
@@ -273,6 +274,14 @@ static inline struct msdos_inode_info *MSDOS_I(struct inode *inode)
return container_of(inode, struct msdos_inode_info, vfs_inode);
}
+/* Return the FAT attribute byte for this inode */
+static inline u8 fat_attr(struct inode *inode)
+{
+ return ((inode->i_mode & S_IWUGO) ? ATTR_NONE : ATTR_RO) |
+ (S_ISDIR(inode->i_mode) ? ATTR_DIR : ATTR_NONE) |
+ MSDOS_I(inode)->i_attrs;
+}
+
static inline sector_t fat_clus_to_blknr(struct msdos_sb_info *sbi, int clus)
{
return ((sector_t)clus - FAT_START_ENT) * sbi->sec_per_clus
@@ -307,7 +316,6 @@ static inline void fatwchar_to16(__u8 *dst, const wchar_t *src, size_t len)
/* fat/cache.c */
extern void fat_cache_inval_inode(struct inode *inode);
-extern int fat_access(struct super_block *sb, int nr, int new_value);
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);
@@ -315,19 +323,67 @@ extern int fat_bmap(struct inode *inode, sector_t sector, sector_t *phys);
/* fat/dir.c */
extern struct file_operations fat_dir_operations;
extern int fat_search_long(struct inode *inode, const unsigned char *name,
- int name_len, int anycase,
- loff_t *spos, loff_t *lpos);
-extern int fat_add_entries(struct inode *dir, int slots,
- struct buffer_head **bh,
- struct msdos_dir_entry **de, loff_t *i_pos);
-extern int fat_new_dir(struct inode *dir, struct inode *parent, int is_vfat);
+ int name_len, struct fat_slot_info *sinfo);
extern int fat_dir_empty(struct inode *dir);
extern int fat_subdirs(struct inode *dir);
extern int fat_scan(struct inode *dir, const unsigned char *name,
- struct buffer_head **res_bh,
- struct msdos_dir_entry **res_de, loff_t *i_pos);
+ struct fat_slot_info *sinfo);
+extern int fat_get_dotdot_entry(struct inode *dir, struct buffer_head **bh,
+ struct msdos_dir_entry **de, loff_t *i_pos);
+extern int fat_alloc_new_dir(struct inode *dir, struct timespec *ts);
+extern int fat_add_entries(struct inode *dir, void *slots, int nr_slots,
+ struct fat_slot_info *sinfo);
+extern int fat_remove_entries(struct inode *dir, struct fat_slot_info *sinfo);
+
+/* fat/fatent.c */
+struct fat_entry {
+ int entry;
+ union {
+ u8 *ent12_p[2];
+ __le16 *ent16_p;
+ __le32 *ent32_p;
+ } u;
+ int nr_bhs;
+ struct buffer_head *bhs[2];
+};
+
+static inline void fatent_init(struct fat_entry *fatent)
+{
+ fatent->nr_bhs = 0;
+ fatent->entry = 0;
+ fatent->u.ent32_p = NULL;
+ fatent->bhs[0] = fatent->bhs[1] = NULL;
+}
+
+static inline void fatent_set_entry(struct fat_entry *fatent, int entry)
+{
+ fatent->entry = entry;
+ fatent->u.ent32_p = NULL;
+}
+
+static inline void fatent_brelse(struct fat_entry *fatent)
+{
+ int i;
+ fatent->u.ent32_p = NULL;
+ for (i = 0; i < fatent->nr_bhs; i++)
+ brelse(fatent->bhs[i]);
+ fatent->nr_bhs = 0;
+ fatent->bhs[0] = fatent->bhs[1] = NULL;
+}
+
+extern void fat_ent_access_init(struct super_block *sb);
+extern int fat_ent_read(struct inode *inode, struct fat_entry *fatent,
+ int entry);
+extern int fat_ent_write(struct inode *inode, struct fat_entry *fatent,
+ int new, int wait);
+extern int fat_alloc_clusters(struct inode *inode, int *cluster,
+ int nr_cluster);
+extern int fat_free_clusters(struct inode *inode, int cluster);
+extern int fat_count_free_clusters(struct super_block *sb);
/* fat/file.c */
+extern int fat_generic_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
extern struct file_operations fat_file_operations;
extern struct inode_operations fat_file_inode_operations;
extern int fat_notify_change(struct dentry * dentry, struct iattr * attr);
@@ -338,35 +394,18 @@ extern void fat_attach(struct inode *inode, loff_t i_pos);
extern void fat_detach(struct inode *inode);
extern struct inode *fat_iget(struct super_block *sb, loff_t i_pos);
extern struct inode *fat_build_inode(struct super_block *sb,
- struct msdos_dir_entry *de, loff_t i_pos, int *res);
-int fat_fill_super(struct super_block *sb, void *data, int silent,
- struct inode_operations *fs_dir_inode_ops, int isvfat);
+ struct msdos_dir_entry *de, loff_t i_pos);
+extern int fat_sync_inode(struct inode *inode);
+extern int fat_fill_super(struct super_block *sb, void *data, int silent,
+ struct inode_operations *fs_dir_inode_ops, int isvfat);
/* fat/misc.c */
extern void fat_fs_panic(struct super_block *s, const char *fmt, ...);
-extern void lock_fat(struct super_block *sb);
-extern void unlock_fat(struct super_block *sb);
extern void fat_clusters_flush(struct super_block *sb);
-extern int fat_add_cluster(struct inode *inode);
+extern int fat_chain_add(struct inode *inode, int new_dclus, int nr_cluster);
extern int date_dos2unix(unsigned short time, unsigned short date);
extern void fat_date_unix2dos(int unix_date, __le16 *time, __le16 *date);
-extern int fat__get_entry(struct inode *dir, loff_t *pos,
- struct buffer_head **bh,
- struct msdos_dir_entry **de, loff_t *i_pos);
-static __inline__ int fat_get_entry(struct inode *dir, loff_t *pos,
- struct buffer_head **bh,
- struct msdos_dir_entry **de, loff_t *i_pos)
-{
- /* Fast stuff first */
- if (*bh && *de &&
- (*de - (struct msdos_dir_entry *)(*bh)->b_data) < MSDOS_SB(dir->i_sb)->dir_per_block - 1) {
- *pos += sizeof(struct msdos_dir_entry);
- (*de)++;
- (*i_pos)++;
- return 0;
- }
- return fat__get_entry(dir, pos, bh, de, i_pos);
-}
+extern int fat_sync_bhs(struct buffer_head **bhs, int nr_bhs);
#endif /* __KERNEL__ */
diff --git a/include/linux/mtio.h b/include/linux/mtio.h
index 4f2daa83d3ad0..8c66151821e39 100644
--- a/include/linux/mtio.h
+++ b/include/linux/mtio.h
@@ -150,34 +150,6 @@ struct mtpos {
};
-/* structure for MTIOCGETCONFIG/MTIOCSETCONFIG primarily intended
- * as an interim solution for QIC-02 until DDI is fully implemented.
- */
-struct mtconfiginfo {
- long mt_type; /* drive type */
- long ifc_type; /* interface card type */
- unsigned short irqnr; /* IRQ number to use */
- unsigned short dmanr; /* DMA channel to use */
- unsigned short port; /* IO port base address */
-
- unsigned long debug; /* debugging flags */
-
- unsigned have_dens:1;
- unsigned have_bsf:1;
- unsigned have_fsr:1;
- unsigned have_bsr:1;
- unsigned have_eod:1;
- unsigned have_seek:1;
- unsigned have_tell:1;
- unsigned have_ras1:1;
- unsigned have_ras2:1;
- unsigned have_ras3:1;
- unsigned have_qfa:1;
-
- unsigned pad1:5;
- char reserved[10];
-};
-
/* structure for MTIOCVOLINFO, query information about the volume
* currently positioned at (zftape)
*/
diff --git a/include/linux/mv643xx.h b/include/linux/mv643xx.h
index ef7470732f14c..5773ea42f6e44 100644
--- a/include/linux/mv643xx.h
+++ b/include/linux/mv643xx.h
@@ -1,5 +1,5 @@
/*
- * mv64340.h - MV-64340 Internal registers definition file.
+ * mv643xx.h - MV-643XX Internal registers definition file.
*
* Copyright 2002 Momentum Computer, Inc.
* Author: Matthew Dharm <mdharm@momenco.com>
@@ -10,8 +10,8 @@
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
-#ifndef __ASM_MV64340_H
-#define __ASM_MV64340_H
+#ifndef __ASM_MV643XX_H
+#define __ASM_MV643XX_H
#ifdef __MIPS__
#include <asm/addrspace.h>
@@ -662,116 +662,119 @@
/* Ethernet Unit Registers */
/****************************************/
-#define MV64340_ETH_PHY_ADDR_REG 0x2000
-#define MV64340_ETH_SMI_REG 0x2004
-#define MV64340_ETH_UNIT_DEFAULT_ADDR_REG 0x2008
-#define MV64340_ETH_UNIT_DEFAULTID_REG 0x200c
-#define MV64340_ETH_UNIT_INTERRUPT_CAUSE_REG 0x2080
-#define MV64340_ETH_UNIT_INTERRUPT_MASK_REG 0x2084
-#define MV64340_ETH_UNIT_INTERNAL_USE_REG 0x24fc
-#define MV64340_ETH_UNIT_ERROR_ADDR_REG 0x2094
-#define MV64340_ETH_BAR_0 0x2200
-#define MV64340_ETH_BAR_1 0x2208
-#define MV64340_ETH_BAR_2 0x2210
-#define MV64340_ETH_BAR_3 0x2218
-#define MV64340_ETH_BAR_4 0x2220
-#define MV64340_ETH_BAR_5 0x2228
-#define MV64340_ETH_SIZE_REG_0 0x2204
-#define MV64340_ETH_SIZE_REG_1 0x220c
-#define MV64340_ETH_SIZE_REG_2 0x2214
-#define MV64340_ETH_SIZE_REG_3 0x221c
-#define MV64340_ETH_SIZE_REG_4 0x2224
-#define MV64340_ETH_SIZE_REG_5 0x222c
-#define MV64340_ETH_HEADERS_RETARGET_BASE_REG 0x2230
-#define MV64340_ETH_HEADERS_RETARGET_CONTROL_REG 0x2234
-#define MV64340_ETH_HIGH_ADDR_REMAP_REG_0 0x2280
-#define MV64340_ETH_HIGH_ADDR_REMAP_REG_1 0x2284
-#define MV64340_ETH_HIGH_ADDR_REMAP_REG_2 0x2288
-#define MV64340_ETH_HIGH_ADDR_REMAP_REG_3 0x228c
-#define MV64340_ETH_BASE_ADDR_ENABLE_REG 0x2290
-#define MV64340_ETH_ACCESS_PROTECTION_REG(port) (0x2294 + (port<<2))
-#define MV64340_ETH_MIB_COUNTERS_BASE(port) (0x3000 + (port<<7))
-#define MV64340_ETH_PORT_CONFIG_REG(port) (0x2400 + (port<<10))
-#define MV64340_ETH_PORT_CONFIG_EXTEND_REG(port) (0x2404 + (port<<10))
-#define MV64340_ETH_MII_SERIAL_PARAMETRS_REG(port) (0x2408 + (port<<10))
-#define MV64340_ETH_GMII_SERIAL_PARAMETRS_REG(port) (0x240c + (port<<10))
-#define MV64340_ETH_VLAN_ETHERTYPE_REG(port) (0x2410 + (port<<10))
-#define MV64340_ETH_MAC_ADDR_LOW(port) (0x2414 + (port<<10))
-#define MV64340_ETH_MAC_ADDR_HIGH(port) (0x2418 + (port<<10))
-#define MV64340_ETH_SDMA_CONFIG_REG(port) (0x241c + (port<<10))
-#define MV64340_ETH_DSCP_0(port) (0x2420 + (port<<10))
-#define MV64340_ETH_DSCP_1(port) (0x2424 + (port<<10))
-#define MV64340_ETH_DSCP_2(port) (0x2428 + (port<<10))
-#define MV64340_ETH_DSCP_3(port) (0x242c + (port<<10))
-#define MV64340_ETH_DSCP_4(port) (0x2430 + (port<<10))
-#define MV64340_ETH_DSCP_5(port) (0x2434 + (port<<10))
-#define MV64340_ETH_DSCP_6(port) (0x2438 + (port<<10))
-#define MV64340_ETH_PORT_SERIAL_CONTROL_REG(port) (0x243c + (port<<10))
-#define MV64340_ETH_VLAN_PRIORITY_TAG_TO_PRIORITY(port) (0x2440 + (port<<10))
-#define MV64340_ETH_PORT_STATUS_REG(port) (0x2444 + (port<<10))
-#define MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(port) (0x2448 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_FIXED_PRIORITY(port) (0x244c + (port<<10))
-#define MV64340_ETH_PORT_TX_TOKEN_BUCKET_RATE_CONFIG(port) (0x2450 + (port<<10))
-#define MV64340_ETH_MAXIMUM_TRANSMIT_UNIT(port) (0x2458 + (port<<10))
-#define MV64340_ETH_PORT_MAXIMUM_TOKEN_BUCKET_SIZE(port) (0x245c + (port<<10))
-#define MV64340_ETH_INTERRUPT_CAUSE_REG(port) (0x2460 + (port<<10))
-#define MV64340_ETH_INTERRUPT_CAUSE_EXTEND_REG(port) (0x2464 + (port<<10))
-#define MV64340_ETH_INTERRUPT_MASK_REG(port) (0x2468 + (port<<10))
-#define MV64340_ETH_INTERRUPT_EXTEND_MASK_REG(port) (0x246c + (port<<10))
-#define MV64340_ETH_RX_FIFO_URGENT_THRESHOLD_REG(port) (0x2470 + (port<<10))
-#define MV64340_ETH_TX_FIFO_URGENT_THRESHOLD_REG(port) (0x2474 + (port<<10))
-#define MV64340_ETH_RX_MINIMAL_FRAME_SIZE_REG(port) (0x247c + (port<<10))
-#define MV64340_ETH_RX_DISCARDED_FRAMES_COUNTER(port) (0x2484 + (port<<10)
-#define MV64340_ETH_PORT_DEBUG_0_REG(port) (0x248c + (port<<10))
-#define MV64340_ETH_PORT_DEBUG_1_REG(port) (0x2490 + (port<<10))
-#define MV64340_ETH_PORT_INTERNAL_ADDR_ERROR_REG(port) (0x2494 + (port<<10))
-#define MV64340_ETH_INTERNAL_USE_REG(port) (0x24fc + (port<<10))
-#define MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(port) (0x2680 + (port<<10))
-#define MV64340_ETH_CURRENT_SERVED_TX_DESC_PTR(port) (0x2684 + (port<<10))
-#define MV64340_ETH_RX_CURRENT_QUEUE_DESC_PTR_0(port) (0x260c + (port<<10))
-#define MV64340_ETH_RX_CURRENT_QUEUE_DESC_PTR_1(port) (0x261c + (port<<10))
-#define MV64340_ETH_RX_CURRENT_QUEUE_DESC_PTR_2(port) (0x262c + (port<<10))
-#define MV64340_ETH_RX_CURRENT_QUEUE_DESC_PTR_3(port) (0x263c + (port<<10))
-#define MV64340_ETH_RX_CURRENT_QUEUE_DESC_PTR_4(port) (0x264c + (port<<10))
-#define MV64340_ETH_RX_CURRENT_QUEUE_DESC_PTR_5(port) (0x265c + (port<<10))
-#define MV64340_ETH_RX_CURRENT_QUEUE_DESC_PTR_6(port) (0x266c + (port<<10))
-#define MV64340_ETH_RX_CURRENT_QUEUE_DESC_PTR_7(port) (0x267c + (port<<10))
-#define MV64340_ETH_TX_CURRENT_QUEUE_DESC_PTR_0(port) (0x26c0 + (port<<10))
-#define MV64340_ETH_TX_CURRENT_QUEUE_DESC_PTR_1(port) (0x26c4 + (port<<10))
-#define MV64340_ETH_TX_CURRENT_QUEUE_DESC_PTR_2(port) (0x26c8 + (port<<10))
-#define MV64340_ETH_TX_CURRENT_QUEUE_DESC_PTR_3(port) (0x26cc + (port<<10))
-#define MV64340_ETH_TX_CURRENT_QUEUE_DESC_PTR_4(port) (0x26d0 + (port<<10))
-#define MV64340_ETH_TX_CURRENT_QUEUE_DESC_PTR_5(port) (0x26d4 + (port<<10))
-#define MV64340_ETH_TX_CURRENT_QUEUE_DESC_PTR_6(port) (0x26d8 + (port<<10))
-#define MV64340_ETH_TX_CURRENT_QUEUE_DESC_PTR_7(port) (0x26dc + (port<<10))
-#define MV64340_ETH_TX_QUEUE_0_TOKEN_BUCKET_COUNT(port) (0x2700 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_1_TOKEN_BUCKET_COUNT(port) (0x2710 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_2_TOKEN_BUCKET_COUNT(port) (0x2720 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_3_TOKEN_BUCKET_COUNT(port) (0x2730 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_4_TOKEN_BUCKET_COUNT(port) (0x2740 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_5_TOKEN_BUCKET_COUNT(port) (0x2750 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_6_TOKEN_BUCKET_COUNT(port) (0x2760 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_7_TOKEN_BUCKET_COUNT(port) (0x2770 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_0_TOKEN_BUCKET_CONFIG(port) (0x2704 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_1_TOKEN_BUCKET_CONFIG(port) (0x2714 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_2_TOKEN_BUCKET_CONFIG(port) (0x2724 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_3_TOKEN_BUCKET_CONFIG(port) (0x2734 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_4_TOKEN_BUCKET_CONFIG(port) (0x2744 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_5_TOKEN_BUCKET_CONFIG(port) (0x2754 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_6_TOKEN_BUCKET_CONFIG(port) (0x2764 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_7_TOKEN_BUCKET_CONFIG(port) (0x2774 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_0_ARBITER_CONFIG(port) (0x2708 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_1_ARBITER_CONFIG(port) (0x2718 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_2_ARBITER_CONFIG(port) (0x2728 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_3_ARBITER_CONFIG(port) (0x2738 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_4_ARBITER_CONFIG(port) (0x2748 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_5_ARBITER_CONFIG(port) (0x2758 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_6_ARBITER_CONFIG(port) (0x2768 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_7_ARBITER_CONFIG(port) (0x2778 + (port<<10))
-#define MV64340_ETH_PORT_TX_TOKEN_BUCKET_COUNT(port) (0x2780 + (port<<10))
-#define MV64340_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE(port) (0x3400 + (port<<10))
-#define MV64340_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE(port) (0x3500 + (port<<10))
-#define MV64340_ETH_DA_FILTER_UNICAST_TABLE_BASE(port) (0x3600 + (port<<10))
+#define MV643XX_ETH_SHARED_REGS 0x2000
+#define MV643XX_ETH_SHARED_REGS_SIZE 0x2000
+
+#define MV643XX_ETH_PHY_ADDR_REG 0x2000
+#define MV643XX_ETH_SMI_REG 0x2004
+#define MV643XX_ETH_UNIT_DEFAULT_ADDR_REG 0x2008
+#define MV643XX_ETH_UNIT_DEFAULTID_REG 0x200c
+#define MV643XX_ETH_UNIT_INTERRUPT_CAUSE_REG 0x2080
+#define MV643XX_ETH_UNIT_INTERRUPT_MASK_REG 0x2084
+#define MV643XX_ETH_UNIT_INTERNAL_USE_REG 0x24fc
+#define MV643XX_ETH_UNIT_ERROR_ADDR_REG 0x2094
+#define MV643XX_ETH_BAR_0 0x2200
+#define MV643XX_ETH_BAR_1 0x2208
+#define MV643XX_ETH_BAR_2 0x2210
+#define MV643XX_ETH_BAR_3 0x2218
+#define MV643XX_ETH_BAR_4 0x2220
+#define MV643XX_ETH_BAR_5 0x2228
+#define MV643XX_ETH_SIZE_REG_0 0x2204
+#define MV643XX_ETH_SIZE_REG_1 0x220c
+#define MV643XX_ETH_SIZE_REG_2 0x2214
+#define MV643XX_ETH_SIZE_REG_3 0x221c
+#define MV643XX_ETH_SIZE_REG_4 0x2224
+#define MV643XX_ETH_SIZE_REG_5 0x222c
+#define MV643XX_ETH_HEADERS_RETARGET_BASE_REG 0x2230
+#define MV643XX_ETH_HEADERS_RETARGET_CONTROL_REG 0x2234
+#define MV643XX_ETH_HIGH_ADDR_REMAP_REG_0 0x2280
+#define MV643XX_ETH_HIGH_ADDR_REMAP_REG_1 0x2284
+#define MV643XX_ETH_HIGH_ADDR_REMAP_REG_2 0x2288
+#define MV643XX_ETH_HIGH_ADDR_REMAP_REG_3 0x228c
+#define MV643XX_ETH_BASE_ADDR_ENABLE_REG 0x2290
+#define MV643XX_ETH_ACCESS_PROTECTION_REG(port) (0x2294 + (port<<2))
+#define MV643XX_ETH_MIB_COUNTERS_BASE(port) (0x3000 + (port<<7))
+#define MV643XX_ETH_PORT_CONFIG_REG(port) (0x2400 + (port<<10))
+#define MV643XX_ETH_PORT_CONFIG_EXTEND_REG(port) (0x2404 + (port<<10))
+#define MV643XX_ETH_MII_SERIAL_PARAMETRS_REG(port) (0x2408 + (port<<10))
+#define MV643XX_ETH_GMII_SERIAL_PARAMETRS_REG(port) (0x240c + (port<<10))
+#define MV643XX_ETH_VLAN_ETHERTYPE_REG(port) (0x2410 + (port<<10))
+#define MV643XX_ETH_MAC_ADDR_LOW(port) (0x2414 + (port<<10))
+#define MV643XX_ETH_MAC_ADDR_HIGH(port) (0x2418 + (port<<10))
+#define MV643XX_ETH_SDMA_CONFIG_REG(port) (0x241c + (port<<10))
+#define MV643XX_ETH_DSCP_0(port) (0x2420 + (port<<10))
+#define MV643XX_ETH_DSCP_1(port) (0x2424 + (port<<10))
+#define MV643XX_ETH_DSCP_2(port) (0x2428 + (port<<10))
+#define MV643XX_ETH_DSCP_3(port) (0x242c + (port<<10))
+#define MV643XX_ETH_DSCP_4(port) (0x2430 + (port<<10))
+#define MV643XX_ETH_DSCP_5(port) (0x2434 + (port<<10))
+#define MV643XX_ETH_DSCP_6(port) (0x2438 + (port<<10))
+#define MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port) (0x243c + (port<<10))
+#define MV643XX_ETH_VLAN_PRIORITY_TAG_TO_PRIORITY(port) (0x2440 + (port<<10))
+#define MV643XX_ETH_PORT_STATUS_REG(port) (0x2444 + (port<<10))
+#define MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(port) (0x2448 + (port<<10))
+#define MV643XX_ETH_TX_QUEUE_FIXED_PRIORITY(port) (0x244c + (port<<10))
+#define MV643XX_ETH_PORT_TX_TOKEN_BUCKET_RATE_CONFIG(port) (0x2450 + (port<<10))
+#define MV643XX_ETH_MAXIMUM_TRANSMIT_UNIT(port) (0x2458 + (port<<10))
+#define MV643XX_ETH_PORT_MAXIMUM_TOKEN_BUCKET_SIZE(port) (0x245c + (port<<10))
+#define MV643XX_ETH_INTERRUPT_CAUSE_REG(port) (0x2460 + (port<<10))
+#define MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port) (0x2464 + (port<<10))
+#define MV643XX_ETH_INTERRUPT_MASK_REG(port) (0x2468 + (port<<10))
+#define MV643XX_ETH_INTERRUPT_EXTEND_MASK_REG(port) (0x246c + (port<<10))
+#define MV643XX_ETH_RX_FIFO_URGENT_THRESHOLD_REG(port) (0x2470 + (port<<10))
+#define MV643XX_ETH_TX_FIFO_URGENT_THRESHOLD_REG(port) (0x2474 + (port<<10))
+#define MV643XX_ETH_RX_MINIMAL_FRAME_SIZE_REG(port) (0x247c + (port<<10))
+#define MV643XX_ETH_RX_DISCARDED_FRAMES_COUNTER(port) (0x2484 + (port<<10)
+#define MV643XX_ETH_PORT_DEBUG_0_REG(port) (0x248c + (port<<10))
+#define MV643XX_ETH_PORT_DEBUG_1_REG(port) (0x2490 + (port<<10))
+#define MV643XX_ETH_PORT_INTERNAL_ADDR_ERROR_REG(port) (0x2494 + (port<<10))
+#define MV643XX_ETH_INTERNAL_USE_REG(port) (0x24fc + (port<<10))
+#define MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port) (0x2680 + (port<<10))
+#define MV643XX_ETH_CURRENT_SERVED_TX_DESC_PTR(port) (0x2684 + (port<<10))
+#define MV643XX_ETH_RX_CURRENT_QUEUE_DESC_PTR_0(port) (0x260c + (port<<10))
+#define MV643XX_ETH_RX_CURRENT_QUEUE_DESC_PTR_1(port) (0x261c + (port<<10))
+#define MV643XX_ETH_RX_CURRENT_QUEUE_DESC_PTR_2(port) (0x262c + (port<<10))
+#define MV643XX_ETH_RX_CURRENT_QUEUE_DESC_PTR_3(port) (0x263c + (port<<10))
+#define MV643XX_ETH_RX_CURRENT_QUEUE_DESC_PTR_4(port) (0x264c + (port<<10))
+#define MV643XX_ETH_RX_CURRENT_QUEUE_DESC_PTR_5(port) (0x265c + (port<<10))
+#define MV643XX_ETH_RX_CURRENT_QUEUE_DESC_PTR_6(port) (0x266c + (port<<10))
+#define MV643XX_ETH_RX_CURRENT_QUEUE_DESC_PTR_7(port) (0x267c + (port<<10))
+#define MV643XX_ETH_TX_CURRENT_QUEUE_DESC_PTR_0(port) (0x26c0 + (port<<10))
+#define MV643XX_ETH_TX_CURRENT_QUEUE_DESC_PTR_1(port) (0x26c4 + (port<<10))
+#define MV643XX_ETH_TX_CURRENT_QUEUE_DESC_PTR_2(port) (0x26c8 + (port<<10))
+#define MV643XX_ETH_TX_CURRENT_QUEUE_DESC_PTR_3(port) (0x26cc + (port<<10))
+#define MV643XX_ETH_TX_CURRENT_QUEUE_DESC_PTR_4(port) (0x26d0 + (port<<10))
+#define MV643XX_ETH_TX_CURRENT_QUEUE_DESC_PTR_5(port) (0x26d4 + (port<<10))
+#define MV643XX_ETH_TX_CURRENT_QUEUE_DESC_PTR_6(port) (0x26d8 + (port<<10))
+#define MV643XX_ETH_TX_CURRENT_QUEUE_DESC_PTR_7(port) (0x26dc + (port<<10))
+#define MV643XX_ETH_TX_QUEUE_0_TOKEN_BUCKET_COUNT(port) (0x2700 + (port<<10))
+#define MV643XX_ETH_TX_QUEUE_1_TOKEN_BUCKET_COUNT(port) (0x2710 + (port<<10))
+#define MV643XX_ETH_TX_QUEUE_2_TOKEN_BUCKET_COUNT(port) (0x2720 + (port<<10))
+#define MV643XX_ETH_TX_QUEUE_3_TOKEN_BUCKET_COUNT(port) (0x2730 + (port<<10))
+#define MV643XX_ETH_TX_QUEUE_4_TOKEN_BUCKET_COUNT(port) (0x2740 + (port<<10))
+#define MV643XX_ETH_TX_QUEUE_5_TOKEN_BUCKET_COUNT(port) (0x2750 + (port<<10))
+#define MV643XX_ETH_TX_QUEUE_6_TOKEN_BUCKET_COUNT(port) (0x2760 + (port<<10))
+#define MV643XX_ETH_TX_QUEUE_7_TOKEN_BUCKET_COUNT(port) (0x2770 + (port<<10))
+#define MV643XX_ETH_TX_QUEUE_0_TOKEN_BUCKET_CONFIG(port) (0x2704 + (port<<10))
+#define MV643XX_ETH_TX_QUEUE_1_TOKEN_BUCKET_CONFIG(port) (0x2714 + (port<<10))
+#define MV643XX_ETH_TX_QUEUE_2_TOKEN_BUCKET_CONFIG(port) (0x2724 + (port<<10))
+#define MV643XX_ETH_TX_QUEUE_3_TOKEN_BUCKET_CONFIG(port) (0x2734 + (port<<10))
+#define MV643XX_ETH_TX_QUEUE_4_TOKEN_BUCKET_CONFIG(port) (0x2744 + (port<<10))
+#define MV643XX_ETH_TX_QUEUE_5_TOKEN_BUCKET_CONFIG(port) (0x2754 + (port<<10))
+#define MV643XX_ETH_TX_QUEUE_6_TOKEN_BUCKET_CONFIG(port) (0x2764 + (port<<10))
+#define MV643XX_ETH_TX_QUEUE_7_TOKEN_BUCKET_CONFIG(port) (0x2774 + (port<<10))
+#define MV643XX_ETH_TX_QUEUE_0_ARBITER_CONFIG(port) (0x2708 + (port<<10))
+#define MV643XX_ETH_TX_QUEUE_1_ARBITER_CONFIG(port) (0x2718 + (port<<10))
+#define MV643XX_ETH_TX_QUEUE_2_ARBITER_CONFIG(port) (0x2728 + (port<<10))
+#define MV643XX_ETH_TX_QUEUE_3_ARBITER_CONFIG(port) (0x2738 + (port<<10))
+#define MV643XX_ETH_TX_QUEUE_4_ARBITER_CONFIG(port) (0x2748 + (port<<10))
+#define MV643XX_ETH_TX_QUEUE_5_ARBITER_CONFIG(port) (0x2758 + (port<<10))
+#define MV643XX_ETH_TX_QUEUE_6_ARBITER_CONFIG(port) (0x2768 + (port<<10))
+#define MV643XX_ETH_TX_QUEUE_7_ARBITER_CONFIG(port) (0x2778 + (port<<10))
+#define MV643XX_ETH_PORT_TX_TOKEN_BUCKET_COUNT(port) (0x2780 + (port<<10))
+#define MV643XX_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE(port) (0x3400 + (port<<10))
+#define MV643XX_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE(port) (0x3500 + (port<<10))
+#define MV643XX_ETH_DA_FILTER_UNICAST_TABLE_BASE(port) (0x3600 + (port<<10))
/*******************************************/
/* CUNIT Registers */
@@ -977,12 +980,9 @@
/* I2C Registers */
/****************************************/
-#define MV64340_I2C_SLAVE_ADDR 0xc000
-#define MV64340_I2C_EXTENDED_SLAVE_ADDR 0xc010
-#define MV64340_I2C_DATA 0xc004
-#define MV64340_I2C_CONTROL 0xc008
-#define MV64340_I2C_STATUS_BAUDE_RATE 0xc00C
-#define MV64340_I2C_SOFT_RESET 0xc01c
+#define MV64XXX_I2C_CTLR_NAME "mv64xxx i2c"
+#define MV64XXX_I2C_OFFSET 0xc000
+#define MV64XXX_I2C_REG_BLOCK_SIZE 0x0020
/****************************************/
/* GPP Interface Registers */
@@ -1085,4 +1085,229 @@ struct mpsc_pdata {
u32 brg_clk_freq;
};
-#endif /* __ASM_MV64340_H */
+/* i2c Platform Device, Driver Data */
+struct mv64xxx_i2c_pdata {
+ u32 freq_m;
+ u32 freq_n;
+ u32 timeout; /* In milliseconds */
+ u32 retries;
+};
+
+/* These macros describe Ethernet Port configuration reg (Px_cR) bits */
+#define MV643XX_ETH_UNICAST_NORMAL_MODE 0
+#define MV643XX_ETH_UNICAST_PROMISCUOUS_MODE (1<<0)
+#define MV643XX_ETH_DEFAULT_RX_QUEUE_0 0
+#define MV643XX_ETH_DEFAULT_RX_QUEUE_1 (1<<1)
+#define MV643XX_ETH_DEFAULT_RX_QUEUE_2 (1<<2)
+#define MV643XX_ETH_DEFAULT_RX_QUEUE_3 ((1<<2) | (1<<1))
+#define MV643XX_ETH_DEFAULT_RX_QUEUE_4 (1<<3)
+#define MV643XX_ETH_DEFAULT_RX_QUEUE_5 ((1<<3) | (1<<1))
+#define MV643XX_ETH_DEFAULT_RX_QUEUE_6 ((1<<3) | (1<<2))
+#define MV643XX_ETH_DEFAULT_RX_QUEUE_7 ((1<<3) | (1<<2) | (1<<1))
+#define MV643XX_ETH_DEFAULT_RX_ARP_QUEUE_0 0
+#define MV643XX_ETH_DEFAULT_RX_ARP_QUEUE_1 (1<<4)
+#define MV643XX_ETH_DEFAULT_RX_ARP_QUEUE_2 (1<<5)
+#define MV643XX_ETH_DEFAULT_RX_ARP_QUEUE_3 ((1<<5) | (1<<4))
+#define MV643XX_ETH_DEFAULT_RX_ARP_QUEUE_4 (1<<6)
+#define MV643XX_ETH_DEFAULT_RX_ARP_QUEUE_5 ((1<<6) | (1<<4))
+#define MV643XX_ETH_DEFAULT_RX_ARP_QUEUE_6 ((1<<6) | (1<<5))
+#define MV643XX_ETH_DEFAULT_RX_ARP_QUEUE_7 ((1<<6) | (1<<5) | (1<<4))
+#define MV643XX_ETH_RECEIVE_BC_IF_NOT_IP_OR_ARP 0
+#define MV643XX_ETH_REJECT_BC_IF_NOT_IP_OR_ARP (1<<7)
+#define MV643XX_ETH_RECEIVE_BC_IF_IP 0
+#define MV643XX_ETH_REJECT_BC_IF_IP (1<<8)
+#define MV643XX_ETH_RECEIVE_BC_IF_ARP 0
+#define MV643XX_ETH_REJECT_BC_IF_ARP (1<<9)
+#define MV643XX_ETH_TX_AM_NO_UPDATE_ERROR_SUMMARY (1<<12)
+#define MV643XX_ETH_CAPTURE_TCP_FRAMES_DIS 0
+#define MV643XX_ETH_CAPTURE_TCP_FRAMES_EN (1<<14)
+#define MV643XX_ETH_CAPTURE_UDP_FRAMES_DIS 0
+#define MV643XX_ETH_CAPTURE_UDP_FRAMES_EN (1<<15)
+#define MV643XX_ETH_DEFAULT_RX_TCP_QUEUE_0 0
+#define MV643XX_ETH_DEFAULT_RX_TCP_QUEUE_1 (1<<16)
+#define MV643XX_ETH_DEFAULT_RX_TCP_QUEUE_2 (1<<17)
+#define MV643XX_ETH_DEFAULT_RX_TCP_QUEUE_3 ((1<<17) | (1<<16))
+#define MV643XX_ETH_DEFAULT_RX_TCP_QUEUE_4 (1<<18)
+#define MV643XX_ETH_DEFAULT_RX_TCP_QUEUE_5 ((1<<18) | (1<<16))
+#define MV643XX_ETH_DEFAULT_RX_TCP_QUEUE_6 ((1<<18) | (1<<17))
+#define MV643XX_ETH_DEFAULT_RX_TCP_QUEUE_7 ((1<<18) | (1<<17) | (1<<16))
+#define MV643XX_ETH_DEFAULT_RX_UDP_QUEUE_0 0
+#define MV643XX_ETH_DEFAULT_RX_UDP_QUEUE_1 (1<<19)
+#define MV643XX_ETH_DEFAULT_RX_UDP_QUEUE_2 (1<<20)
+#define MV643XX_ETH_DEFAULT_RX_UDP_QUEUE_3 ((1<<20) | (1<<19))
+#define MV643XX_ETH_DEFAULT_RX_UDP_QUEUE_4 ((1<<21)
+#define MV643XX_ETH_DEFAULT_RX_UDP_QUEUE_5 ((1<<21) | (1<<19))
+#define MV643XX_ETH_DEFAULT_RX_UDP_QUEUE_6 ((1<<21) | (1<<20))
+#define MV643XX_ETH_DEFAULT_RX_UDP_QUEUE_7 ((1<<21) | (1<<20) | (1<<19))
+#define MV643XX_ETH_DEFAULT_RX_BPDU_QUEUE_0 0
+#define MV643XX_ETH_DEFAULT_RX_BPDU_QUEUE_1 (1<<22)
+#define MV643XX_ETH_DEFAULT_RX_BPDU_QUEUE_2 (1<<23)
+#define MV643XX_ETH_DEFAULT_RX_BPDU_QUEUE_3 ((1<<23) | (1<<22))
+#define MV643XX_ETH_DEFAULT_RX_BPDU_QUEUE_4 (1<<24)
+#define MV643XX_ETH_DEFAULT_RX_BPDU_QUEUE_5 ((1<<24) | (1<<22))
+#define MV643XX_ETH_DEFAULT_RX_BPDU_QUEUE_6 ((1<<24) | (1<<23))
+#define MV643XX_ETH_DEFAULT_RX_BPDU_QUEUE_7 ((1<<24) | (1<<23) | (1<<22))
+
+#define MV643XX_ETH_PORT_CONFIG_DEFAULT_VALUE \
+ MV643XX_ETH_UNICAST_NORMAL_MODE | \
+ MV643XX_ETH_DEFAULT_RX_QUEUE_0 | \
+ MV643XX_ETH_DEFAULT_RX_ARP_QUEUE_0 | \
+ MV643XX_ETH_RECEIVE_BC_IF_NOT_IP_OR_ARP | \
+ MV643XX_ETH_RECEIVE_BC_IF_IP | \
+ MV643XX_ETH_RECEIVE_BC_IF_ARP | \
+ MV643XX_ETH_CAPTURE_TCP_FRAMES_DIS | \
+ MV643XX_ETH_CAPTURE_UDP_FRAMES_DIS | \
+ MV643XX_ETH_DEFAULT_RX_TCP_QUEUE_0 | \
+ MV643XX_ETH_DEFAULT_RX_UDP_QUEUE_0 | \
+ MV643XX_ETH_DEFAULT_RX_BPDU_QUEUE_0
+
+/* These macros describe Ethernet Port configuration extend reg (Px_cXR) bits*/
+#define MV643XX_ETH_CLASSIFY_EN (1<<0)
+#define MV643XX_ETH_SPAN_BPDU_PACKETS_AS_NORMAL 0
+#define MV643XX_ETH_SPAN_BPDU_PACKETS_TO_RX_QUEUE_7 (1<<1)
+#define MV643XX_ETH_PARTITION_DISABLE 0
+#define MV643XX_ETH_PARTITION_ENABLE (1<<2)
+
+#define MV643XX_ETH_PORT_CONFIG_EXTEND_DEFAULT_VALUE \
+ MV643XX_ETH_SPAN_BPDU_PACKETS_AS_NORMAL | \
+ MV643XX_ETH_PARTITION_DISABLE
+
+/* These macros describe Ethernet Port Sdma configuration reg (SDCR) bits */
+#define MV643XX_ETH_RIFB (1<<0)
+#define MV643XX_ETH_RX_BURST_SIZE_1_64BIT 0
+#define MV643XX_ETH_RX_BURST_SIZE_2_64BIT (1<<1)
+#define MV643XX_ETH_RX_BURST_SIZE_4_64BIT (1<<2)
+#define MV643XX_ETH_RX_BURST_SIZE_8_64BIT ((1<<2) | (1<<1))
+#define MV643XX_ETH_RX_BURST_SIZE_16_64BIT (1<<3)
+#define MV643XX_ETH_BLM_RX_NO_SWAP (1<<4)
+#define MV643XX_ETH_BLM_RX_BYTE_SWAP 0
+#define MV643XX_ETH_BLM_TX_NO_SWAP (1<<5)
+#define MV643XX_ETH_BLM_TX_BYTE_SWAP 0
+#define MV643XX_ETH_DESCRIPTORS_BYTE_SWAP (1<<6)
+#define MV643XX_ETH_DESCRIPTORS_NO_SWAP 0
+#define MV643XX_ETH_TX_BURST_SIZE_1_64BIT 0
+#define MV643XX_ETH_TX_BURST_SIZE_2_64BIT (1<<22)
+#define MV643XX_ETH_TX_BURST_SIZE_4_64BIT (1<<23)
+#define MV643XX_ETH_TX_BURST_SIZE_8_64BIT ((1<<23) | (1<<22))
+#define MV643XX_ETH_TX_BURST_SIZE_16_64BIT (1<<24)
+
+#define MV643XX_ETH_IPG_INT_RX(value) ((value & 0x3fff) << 8)
+
+#define MV643XX_ETH_PORT_SDMA_CONFIG_DEFAULT_VALUE \
+ MV643XX_ETH_RX_BURST_SIZE_4_64BIT | \
+ MV643XX_ETH_IPG_INT_RX(0) | \
+ MV643XX_ETH_TX_BURST_SIZE_4_64BIT
+
+/* These macros describe Ethernet Port serial control reg (PSCR) bits */
+#define MV643XX_ETH_SERIAL_PORT_DISABLE 0
+#define MV643XX_ETH_SERIAL_PORT_ENABLE (1<<0)
+#define MV643XX_ETH_FORCE_LINK_PASS (1<<1)
+#define MV643XX_ETH_DO_NOT_FORCE_LINK_PASS 0
+#define MV643XX_ETH_ENABLE_AUTO_NEG_FOR_DUPLX 0
+#define MV643XX_ETH_DISABLE_AUTO_NEG_FOR_DUPLX (1<<2)
+#define MV643XX_ETH_ENABLE_AUTO_NEG_FOR_FLOW_CTRL 0
+#define MV643XX_ETH_DISABLE_AUTO_NEG_FOR_FLOW_CTRL (1<<3)
+#define MV643XX_ETH_ADV_NO_FLOW_CTRL 0
+#define MV643XX_ETH_ADV_SYMMETRIC_FLOW_CTRL (1<<4)
+#define MV643XX_ETH_FORCE_FC_MODE_NO_PAUSE_DIS_TX 0
+#define MV643XX_ETH_FORCE_FC_MODE_TX_PAUSE_DIS (1<<5)
+#define MV643XX_ETH_FORCE_BP_MODE_NO_JAM 0
+#define MV643XX_ETH_FORCE_BP_MODE_JAM_TX (1<<7)
+#define MV643XX_ETH_FORCE_BP_MODE_JAM_TX_ON_RX_ERR (1<<8)
+#define MV643XX_ETH_FORCE_LINK_FAIL 0
+#define MV643XX_ETH_DO_NOT_FORCE_LINK_FAIL (1<<10)
+#define MV643XX_ETH_RETRANSMIT_16_ATTEMPTS 0
+#define MV643XX_ETH_RETRANSMIT_FOREVER (1<<11)
+#define MV643XX_ETH_DISABLE_AUTO_NEG_SPEED_GMII (1<<13)
+#define MV643XX_ETH_ENABLE_AUTO_NEG_SPEED_GMII 0
+#define MV643XX_ETH_DTE_ADV_0 0
+#define MV643XX_ETH_DTE_ADV_1 (1<<14)
+#define MV643XX_ETH_DISABLE_AUTO_NEG_BYPASS 0
+#define MV643XX_ETH_ENABLE_AUTO_NEG_BYPASS (1<<15)
+#define MV643XX_ETH_AUTO_NEG_NO_CHANGE 0
+#define MV643XX_ETH_RESTART_AUTO_NEG (1<<16)
+#define MV643XX_ETH_MAX_RX_PACKET_1518BYTE 0
+#define MV643XX_ETH_MAX_RX_PACKET_1522BYTE (1<<17)
+#define MV643XX_ETH_MAX_RX_PACKET_1552BYTE (1<<18)
+#define MV643XX_ETH_MAX_RX_PACKET_9022BYTE ((1<<18) | (1<<17))
+#define MV643XX_ETH_MAX_RX_PACKET_9192BYTE (1<<19)
+#define MV643XX_ETH_MAX_RX_PACKET_9700BYTE ((1<<19) | (1<<17))
+#define MV643XX_ETH_SET_EXT_LOOPBACK (1<<20)
+#define MV643XX_ETH_CLR_EXT_LOOPBACK 0
+#define MV643XX_ETH_SET_FULL_DUPLEX_MODE (1<<21)
+#define MV643XX_ETH_SET_HALF_DUPLEX_MODE 0
+#define MV643XX_ETH_ENABLE_FLOW_CTRL_TX_RX_IN_FULL_DUPLEX (1<<22)
+#define MV643XX_ETH_DISABLE_FLOW_CTRL_TX_RX_IN_FULL_DUPLEX 0
+#define MV643XX_ETH_SET_GMII_SPEED_TO_10_100 0
+#define MV643XX_ETH_SET_GMII_SPEED_TO_1000 (1<<23)
+#define MV643XX_ETH_SET_MII_SPEED_TO_10 0
+#define MV643XX_ETH_SET_MII_SPEED_TO_100 (1<<24)
+
+#define MV643XX_ETH_PORT_SERIAL_CONTROL_DEFAULT_VALUE \
+ MV643XX_ETH_DO_NOT_FORCE_LINK_PASS | \
+ MV643XX_ETH_ENABLE_AUTO_NEG_FOR_DUPLX | \
+ MV643XX_ETH_DISABLE_AUTO_NEG_FOR_FLOW_CTRL | \
+ MV643XX_ETH_ADV_SYMMETRIC_FLOW_CTRL | \
+ MV643XX_ETH_FORCE_FC_MODE_NO_PAUSE_DIS_TX | \
+ MV643XX_ETH_FORCE_BP_MODE_NO_JAM | \
+ (1<<9) /* reserved */ | \
+ MV643XX_ETH_DO_NOT_FORCE_LINK_FAIL | \
+ MV643XX_ETH_RETRANSMIT_16_ATTEMPTS | \
+ MV643XX_ETH_ENABLE_AUTO_NEG_SPEED_GMII | \
+ MV643XX_ETH_DTE_ADV_0 | \
+ MV643XX_ETH_DISABLE_AUTO_NEG_BYPASS | \
+ MV643XX_ETH_AUTO_NEG_NO_CHANGE | \
+ MV643XX_ETH_MAX_RX_PACKET_9700BYTE | \
+ MV643XX_ETH_CLR_EXT_LOOPBACK | \
+ MV643XX_ETH_SET_FULL_DUPLEX_MODE | \
+ MV643XX_ETH_ENABLE_FLOW_CTRL_TX_RX_IN_FULL_DUPLEX
+
+/* These macros describe Ethernet Serial Status reg (PSR) bits */
+#define MV643XX_ETH_PORT_STATUS_MODE_10_BIT (1<<0)
+#define MV643XX_ETH_PORT_STATUS_LINK_UP (1<<1)
+#define MV643XX_ETH_PORT_STATUS_FULL_DUPLEX (1<<2)
+#define MV643XX_ETH_PORT_STATUS_FLOW_CONTROL (1<<3)
+#define MV643XX_ETH_PORT_STATUS_GMII_1000 (1<<4)
+#define MV643XX_ETH_PORT_STATUS_MII_100 (1<<5)
+/* PSR bit 6 is undocumented */
+#define MV643XX_ETH_PORT_STATUS_TX_IN_PROGRESS (1<<7)
+#define MV643XX_ETH_PORT_STATUS_AUTONEG_BYPASSED (1<<8)
+#define MV643XX_ETH_PORT_STATUS_PARTITION (1<<9)
+#define MV643XX_ETH_PORT_STATUS_TX_FIFO_EMPTY (1<<10)
+/* PSR bits 11-31 are reserved */
+
+#define MV643XX_ETH_PORT_DEFAULT_TRANSMIT_QUEUE_SIZE 800
+#define MV643XX_ETH_PORT_DEFAULT_RECEIVE_QUEUE_SIZE 400
+
+#define MV643XX_ETH_DESC_SIZE 64
+
+#define MV643XX_ETH_SHARED_NAME "mv643xx_eth_shared"
+#define MV643XX_ETH_NAME "mv643xx_eth"
+
+struct mv643xx_eth_platform_data {
+ /*
+ * Non-values for mac_addr, phy_addr, port_config, etc.
+ * override the default value. Setting the corresponding
+ * force_* field, causes the default value to be overridden
+ * even when zero.
+ */
+ unsigned int force_phy_addr:1;
+ unsigned int force_port_config:1;
+ unsigned int force_port_config_extend:1;
+ unsigned int force_port_sdma_config:1;
+ unsigned int force_port_serial_control:1;
+ int phy_addr;
+ char *mac_addr; /* pointer to mac address */
+ u32 port_config;
+ u32 port_config_extend;
+ u32 port_sdma_config;
+ u32 port_serial_control;
+ u32 tx_queue_size;
+ u32 rx_queue_size;
+ u32 tx_sram_addr;
+ u32 tx_sram_size;
+ u32 rx_sram_addr;
+ u32 rx_sram_size;
+};
+
+#endif /* __ASM_MV643XX_H */
diff --git a/include/linux/namei.h b/include/linux/namei.h
index 1bbfa296e11f1..7db67b008cac4 100644
--- a/include/linux/namei.h
+++ b/include/linux/namei.h
@@ -39,12 +39,14 @@ enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT, LAST_BIND};
* - ending slashes ok even for nonexistent files
* - internal "there are more path compnents" flag
* - locked when lookup done with dcache_lock held
+ * - dentry cache is untrusted; force a real lookup
*/
#define LOOKUP_FOLLOW 1
#define LOOKUP_DIRECTORY 2
#define LOOKUP_CONTINUE 4
#define LOOKUP_PARENT 16
#define LOOKUP_NOALT 32
+#define LOOKUP_REVAL 64
/*
* Intent data
*/
diff --git a/include/linux/net.h b/include/linux/net.h
index 8bfb1243f5e28..7823b34825065 100644
--- a/include/linux/net.h
+++ b/include/linux/net.h
@@ -61,6 +61,7 @@ typedef enum {
#define SOCK_ASYNC_NOSPACE 0
#define SOCK_ASYNC_WAITDATA 1
#define SOCK_NOSPACE 2
+#define SOCK_PASSCRED 3
#ifndef ARCH_HAS_SOCKET_TYPES
/** sock_type - Socket types
@@ -111,7 +112,6 @@ struct socket {
struct sock *sk;
wait_queue_head_t wait;
short type;
- unsigned char passcred;
};
struct vm_area_struct;
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index eafc8205ff9e2..8d775be67833e 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -41,7 +41,7 @@
struct divert_blk;
struct vlan_group;
struct ethtool_ops;
-
+struct netpoll;
/* source back-compat hooks */
#define SET_ETHTOOL_OPS(netdev,ops) \
( (netdev)->ethtool_ops = (ops) )
@@ -328,9 +328,7 @@ struct net_device
unsigned short flags; /* interface flags (a la BSD) */
unsigned short gflags;
unsigned short priv_flags; /* Like 'flags' but invisible to userspace. */
- unsigned short unused_alignment_fixer; /* Because we need priv_flags,
- * and we want to be 32-bit aligned.
- */
+ unsigned short padded; /* How much padding added by alloc_netdev() */
unsigned mtu; /* interface MTU value */
unsigned short type; /* interface hardware type */
@@ -469,9 +467,8 @@ struct net_device
int (*hard_header_parse)(struct sk_buff *skb,
unsigned char *haddr);
int (*neigh_setup)(struct net_device *dev, struct neigh_parms *);
- int (*accept_fastpath)(struct net_device *, struct dst_entry*);
#ifdef CONFIG_NETPOLL
- int netpoll_rx;
+ struct netpoll *np;
#endif
#ifdef CONFIG_NET_POLL_CONTROLLER
void (*poll_controller)(struct net_device *dev);
@@ -487,8 +484,6 @@ struct net_device
/* class/net/name entry */
struct class_device class_dev;
- /* how much padding had been added by alloc_netdev() */
- int padded;
};
#define NETDEV_ALIGN 32
@@ -678,6 +673,8 @@ extern unsigned dev_get_flags(const struct net_device *);
extern int dev_change_flags(struct net_device *, unsigned);
extern int dev_change_name(struct net_device *, char *);
extern int dev_set_mtu(struct net_device *, int);
+extern int dev_set_mac_address(struct net_device *,
+ struct sockaddr *);
extern void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev);
extern void dev_init(void);
@@ -921,8 +918,6 @@ extern void dev_load(const char *name);
extern void dev_mcast_init(void);
extern int netdev_max_backlog;
extern int weight_p;
-extern unsigned long netdev_fc_xoff;
-extern atomic_t netdev_dropping;
extern int netdev_set_master(struct net_device *dev, struct net_device *master);
extern int skb_checksum_help(struct sk_buff *skb, int inward);
/* rx skb timestamps */
diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h
index 0c267c89fa3e4..2e2045482cb13 100644
--- a/include/linux/netfilter.h
+++ b/include/linux/netfilter.h
@@ -18,7 +18,8 @@
#define NF_STOLEN 2
#define NF_QUEUE 3
#define NF_REPEAT 4
-#define NF_MAX_VERDICT NF_REPEAT
+#define NF_STOP 5
+#define NF_MAX_VERDICT NF_STOP
/* Generic cache responses from hook functions.
<= 0x2000 is used for protocol-flags. */
@@ -138,21 +139,32 @@ 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) \
- nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn), INT_MIN)
-#define NF_HOOK_THRESH nf_hook_slow
+#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) \
-(list_empty(&nf_hooks[(pf)][(hook)]) \
- ? (okfn)(skb) \
- : nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn), INT_MIN))
-#define NF_HOOK_THRESH(pf, hook, skb, indev, outdev, okfn, thresh) \
-(list_empty(&nf_hooks[(pf)][(hook)]) \
- ? (okfn)(skb) \
- : nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn), (thresh)))
+#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;})
+#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) \
+ __ret = (okfn)(skb); \
+__ret;})
#endif
-int nf_hook_slow(int pf, unsigned int hook, struct sk_buff *skb,
+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);
diff --git a/include/linux/netfilter_arp/arp_tables.h b/include/linux/netfilter_arp/arp_tables.h
index b16b4799e27e9..d759a637bdedb 100644
--- a/include/linux/netfilter_arp/arp_tables.h
+++ b/include/linux/netfilter_arp/arp_tables.h
@@ -154,7 +154,7 @@ struct arpt_entry
#define ARPT_CONTINUE 0xFFFFFFFF
/* For standard target */
-#define ARPT_RETURN (-NF_MAX_VERDICT - 1)
+#define ARPT_RETURN (-NF_REPEAT - 1)
/* The argument to ARPT_SO_GET_INFO */
struct arpt_getinfo
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_tcp.h b/include/linux/netfilter_ipv4/ip_conntrack_tcp.h
index 76c2a19700dcc..16da044d97a77 100644
--- a/include/linux/netfilter_ipv4/ip_conntrack_tcp.h
+++ b/include/linux/netfilter_ipv4/ip_conntrack_tcp.h
@@ -23,13 +23,16 @@ enum tcp_conntrack {
/* SACK is permitted by the sender */
#define IP_CT_TCP_FLAG_SACK_PERM 0x02
+/* This sender sent FIN first */
+#define IP_CT_TCP_FLAG_CLOSE_INIT 0x03
+
struct ip_ct_tcp_state {
u_int32_t td_end; /* max of seq + len */
u_int32_t td_maxend; /* max of ack + max(win, 1) */
u_int32_t td_maxwin; /* max(win) */
u_int8_t td_scale; /* window scale factor */
u_int8_t loose; /* used when connection picked up from the middle */
- u_int8_t flags; /* per direction state flags */
+ u_int8_t flags; /* per direction options */
};
struct ip_ct_tcp
diff --git a/include/linux/netfilter_ipv4/ip_tables.h b/include/linux/netfilter_ipv4/ip_tables.h
index 91f3594d3bfd2..12ce47808e7d2 100644
--- a/include/linux/netfilter_ipv4/ip_tables.h
+++ b/include/linux/netfilter_ipv4/ip_tables.h
@@ -166,7 +166,7 @@ struct ipt_entry
#define IPT_CONTINUE 0xFFFFFFFF
/* For standard target */
-#define IPT_RETURN (-NF_MAX_VERDICT - 1)
+#define IPT_RETURN (-NF_REPEAT - 1)
/* TCP matching stuff */
struct ipt_tcp
diff --git a/include/linux/netfilter_ipv6/ip6_tables.h b/include/linux/netfilter_ipv6/ip6_tables.h
index 8fa1bf0104eef..f1ce3b009853b 100644
--- a/include/linux/netfilter_ipv6/ip6_tables.h
+++ b/include/linux/netfilter_ipv6/ip6_tables.h
@@ -166,7 +166,7 @@ struct ip6t_entry
#define IP6T_CONTINUE 0xFFFFFFFF
/* For standard target */
-#define IP6T_RETURN (-NF_MAX_VERDICT - 1)
+#define IP6T_RETURN (-NF_REPEAT - 1)
/* TCP matching stuff */
struct ip6t_tcp
diff --git a/include/linux/netpoll.h b/include/linux/netpoll.h
index ccf1ccb80972b..c0d8b90c52025 100644
--- a/include/linux/netpoll.h
+++ b/include/linux/netpoll.h
@@ -16,11 +16,14 @@ struct netpoll;
struct netpoll {
struct net_device *dev;
char dev_name[16], *name;
+ int rx_flags;
void (*rx_hook)(struct netpoll *, int, char *, int);
+ void (*drop)(struct sk_buff *skb);
u32 local_ip, remote_ip;
u16 local_port, remote_port;
unsigned char local_mac[6], remote_mac[6];
- struct list_head rx_list;
+ spinlock_t poll_lock;
+ int poll_owner;
};
void netpoll_poll(struct netpoll *np);
@@ -30,7 +33,35 @@ int netpoll_setup(struct netpoll *np);
int netpoll_trap(void);
void netpoll_set_trap(int trap);
void netpoll_cleanup(struct netpoll *np);
-int netpoll_rx(struct sk_buff *skb);
+int __netpoll_rx(struct sk_buff *skb);
+void netpoll_queue(struct sk_buff *skb);
+#ifdef CONFIG_NETPOLL
+static inline int netpoll_rx(struct sk_buff *skb)
+{
+ return skb->dev->np && skb->dev->np->rx_flags && __netpoll_rx(skb);
+}
+
+static inline void netpoll_poll_lock(struct net_device *dev)
+{
+ if (dev->np) {
+ spin_lock(&dev->np->poll_lock);
+ dev->np->poll_owner = smp_processor_id();
+ }
+}
+
+static inline void netpoll_poll_unlock(struct net_device *dev)
+{
+ if (dev->np) {
+ spin_unlock(&dev->np->poll_lock);
+ dev->np->poll_owner = -1;
+ }
+}
+
+#else
+#define netpoll_rx(a) 0
+#define netpoll_poll_lock(a)
+#define netpoll_poll_unlock(a)
+#endif
#endif
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 12c46442cc860..dbac7f363e5d3 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -345,17 +345,14 @@ extern struct inode_operations nfs_dir_inode_operations;
extern struct file_operations nfs_dir_operations;
extern struct dentry_operations nfs_dentry_operations;
+extern int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fh, struct nfs_fattr *fattr);
+
/*
* linux/fs/nfs/symlink.c
*/
extern struct inode_operations nfs_symlink_inode_operations;
/*
- * linux/fs/nfs/locks.c
- */
-extern int nfs_lock(struct file *, int, struct file_lock *);
-
-/*
* linux/fs/nfs/unlink.c
*/
extern int nfs_async_unlink(struct dentry *);
@@ -379,11 +376,8 @@ extern void nfs_commit_done(struct rpc_task *);
* return value!)
*/
extern int nfs_sync_inode(struct inode *, unsigned long, unsigned int, int);
-extern int nfs_flush_inode(struct inode *, unsigned long, unsigned int, int);
-extern int nfs_flush_list(struct list_head *, int, int);
#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
extern int nfs_commit_inode(struct inode *, unsigned long, unsigned int, int);
-extern int nfs_commit_list(struct list_head *, int);
#else
static inline int
nfs_commit_inode(struct inode *inode, unsigned long idx_start, unsigned int npages, int how)
@@ -424,7 +418,6 @@ static inline int nfs_wb_page(struct inode *inode, struct page* page)
* Allocate and free nfs_write_data structures
*/
extern mempool_t *nfs_wdata_mempool;
-extern mempool_t *nfs_commit_mempool;
static inline struct nfs_write_data *nfs_writedata_alloc(void)
{
@@ -441,23 +434,6 @@ static inline void nfs_writedata_free(struct nfs_write_data *p)
mempool_free(p, nfs_wdata_mempool);
}
-extern void nfs_writedata_release(struct rpc_task *task);
-
-static inline struct nfs_write_data *nfs_commit_alloc(void)
-{
- struct nfs_write_data *p = mempool_alloc(nfs_commit_mempool, SLAB_NOFS);
- if (p) {
- memset(p, 0, sizeof(*p));
- INIT_LIST_HEAD(&p->pages);
- }
- return p;
-}
-
-static inline void nfs_commit_free(struct nfs_write_data *p)
-{
- mempool_free(p, nfs_commit_mempool);
-}
-
/* Hack for future NFS swap support */
#ifndef IS_SWAPFILE
# define IS_SWAPFILE(inode) (0)
@@ -469,7 +445,6 @@ static inline void nfs_commit_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 int nfs_pagein_list(struct list_head *, int);
extern void nfs_readpage_result(struct rpc_task *);
/*
@@ -610,6 +585,9 @@ struct nfs4_client {
wait_queue_head_t cl_waitq;
struct rpc_wait_queue cl_rpcwaitq;
+ /* used for the setclientid verifier */
+ struct timespec cl_boot_time;
+
/* idmapper */
struct idmap * cl_idmap;
@@ -617,6 +595,7 @@ struct nfs4_client {
* This is used to generate the clientid, and the callback address.
*/
char cl_ipaddr[16];
+ unsigned char cl_id_uniquifier;
};
/*
@@ -696,21 +675,26 @@ struct nfs4_exception {
int retry;
};
+struct nfs4_state_recovery_ops {
+ int (*recover_open)(struct nfs4_state_owner *, struct nfs4_state *);
+ int (*recover_lock)(struct nfs4_state *, struct file_lock *);
+};
+
extern struct dentry_operations nfs4_dentry_operations;
extern struct inode_operations nfs4_dir_inode_operations;
/* 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_open_reclaim(struct nfs4_state_owner *, struct nfs4_state *);
extern int nfs4_proc_async_renew(struct nfs4_client *);
extern int nfs4_proc_renew(struct nfs4_client *);
extern int nfs4_do_close(struct inode *inode, struct nfs4_state *state, mode_t mode);
-extern int nfs4_wait_clnt_recover(struct rpc_clnt *, struct nfs4_client *);
extern struct inode *nfs4_atomic_open(struct inode *, struct dentry *, struct nameidata *);
extern int nfs4_open_revalidate(struct inode *, struct dentry *, int);
-extern int nfs4_handle_exception(struct nfs_server *, int, struct nfs4_exception *);
-extern int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request);
+
+extern struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops;
+extern struct nfs4_state_recovery_ops nfs4_network_partition_recovery_ops;
/* nfs4renewd.c */
extern void nfs4_schedule_state_renewal(struct nfs4_client *);
@@ -728,6 +712,7 @@ extern u32 nfs4_alloc_lockowner_id(struct nfs4_client *);
extern struct nfs4_state_owner * nfs4_get_state_owner(struct nfs_server *, struct rpc_cred *);
extern void nfs4_put_state_owner(struct nfs4_state_owner *);
+extern void nfs4_drop_state_owner(struct nfs4_state_owner *);
extern struct nfs4_state * nfs4_get_open_state(struct inode *, struct nfs4_state_owner *);
extern void nfs4_put_open_state(struct nfs4_state *);
extern void nfs4_close_state(struct nfs4_state *, mode_t);
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
index a43a386079823..fc51645d61eec 100644
--- a/include/linux/nfs_fs_sb.h
+++ b/include/linux/nfs_fs_sb.h
@@ -53,5 +53,6 @@ struct nfs_server {
#define NFS_CAP_HARDLINKS (1U << 1)
#define NFS_CAP_SYMLINKS (1U << 2)
#define NFS_CAP_ACLS (1U << 3)
+#define NFS_CAP_ATOMIC_OPEN (1U << 4)
#endif
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index a73f8a990b24f..47037d9521cb0 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -563,6 +563,7 @@ struct nfs4_readdir_arg {
u32 count;
struct page ** pages; /* zero-copy data */
unsigned int pgbase; /* zero-copy data */
+ const u32 * bitmask;
};
struct nfs4_readdir_res {
@@ -681,7 +682,7 @@ struct nfs_rpc_ops {
int (*read) (struct nfs_read_data *);
int (*write) (struct nfs_write_data *);
int (*commit) (struct nfs_write_data *);
- struct inode * (*create) (struct inode *, struct dentry *,
+ int (*create) (struct inode *, struct dentry *,
struct iattr *, int);
int (*remove) (struct inode *, struct qstr *);
int (*unlink_setup) (struct rpc_message *,
@@ -693,13 +694,12 @@ struct nfs_rpc_ops {
int (*symlink) (struct inode *, struct qstr *, struct qstr *,
struct iattr *, struct nfs_fh *,
struct nfs_fattr *);
- int (*mkdir) (struct inode *, struct qstr *, struct iattr *,
- struct nfs_fh *, struct nfs_fattr *);
+ int (*mkdir) (struct inode *, struct dentry *, struct iattr *);
int (*rmdir) (struct inode *, struct qstr *);
int (*readdir) (struct dentry *, struct rpc_cred *,
u64, struct page *, unsigned int, int);
- int (*mknod) (struct inode *, struct qstr *, struct iattr *,
- dev_t, struct nfs_fh *, struct nfs_fattr *);
+ int (*mknod) (struct inode *, struct dentry *, struct iattr *,
+ dev_t);
int (*statfs) (struct nfs_server *, struct nfs_fh *,
struct nfs_fsstat *);
int (*fsinfo) (struct nfs_server *, struct nfs_fh *,
@@ -731,7 +731,5 @@ extern struct nfs_rpc_ops nfs_v4_clientops;
extern struct rpc_version nfs_version2;
extern struct rpc_version nfs_version3;
extern struct rpc_version nfs_version4;
-extern struct rpc_program nfs_program;
-extern struct rpc_stat nfs_rpcstat;
#endif
diff --git a/include/linux/nfsd/cache.h b/include/linux/nfsd/cache.h
index cfffc76fc1e1c..c3a3557c2a5b4 100644
--- a/include/linux/nfsd/cache.h
+++ b/include/linux/nfsd/cache.h
@@ -19,10 +19,9 @@
* be hash_next and hash_prev.
*/
struct svc_cacherep {
- struct svc_cacherep * c_hash_next;
- struct svc_cacherep * c_hash_prev;
- struct svc_cacherep * c_lru_next;
- struct svc_cacherep * c_lru_prev;
+ struct hlist_node c_hash;
+ struct list_head c_lru;
+
unsigned char c_state, /* unused, inprog, done */
c_type, /* status, buffer */
c_secure : 1; /* req came from port < 1024 */
diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h
index bf8143c8c1335..8f85d9a596075 100644
--- a/include/linux/nfsd/nfsd.h
+++ b/include/linux/nfsd/nfsd.h
@@ -96,9 +96,9 @@ int nfsd_commit(struct svc_rqst *, struct svc_fh *,
int nfsd_open(struct svc_rqst *, struct svc_fh *, int,
int, struct file **);
void nfsd_close(struct file *);
-int nfsd_read(struct svc_rqst *, struct svc_fh *,
- loff_t, struct kvec *,int, unsigned long *);
-int nfsd_write(struct svc_rqst *, struct svc_fh *,
+int nfsd_read(struct svc_rqst *, struct svc_fh *, struct file *,
+ loff_t, struct kvec *, int, unsigned long *);
+int nfsd_write(struct svc_rqst *, struct svc_fh *,struct file *,
loff_t, struct kvec *,int, unsigned long, int *);
int nfsd_readlink(struct svc_rqst *, struct svc_fh *,
char *, int *);
@@ -129,15 +129,15 @@ int nfsd_permission(struct svc_export *, struct dentry *, int);
* NFSv4 State
*/
#ifdef CONFIG_NFSD_V4
-void nfs4_state_init(void);
+int nfs4_state_init(void);
void nfs4_state_shutdown(void);
time_t nfs4_lease_time(void);
void nfs4_reset_lease(time_t leasetime);
#else
-void static inline nfs4_state_init(void){}
-void static inline nfs4_state_shutdown(void){}
-time_t static inline nfs4_lease_time(void){return 0;}
-void static inline nfs4_reset_lease(time_t leasetime){}
+static inline int nfs4_state_init(void){return 0;}
+static inline void nfs4_state_shutdown(void){}
+static inline time_t nfs4_lease_time(void){return 0;}
+static inline void nfs4_reset_lease(time_t leasetime){}
#endif
/*
@@ -209,6 +209,7 @@ void nfsd_lockd_shutdown(void);
#define nfserr_no_grace __constant_htonl(NFSERR_NO_GRACE)
#define nfserr_reclaim_bad __constant_htonl(NFSERR_RECLAIM_BAD)
#define nfserr_badname __constant_htonl(NFSERR_BADNAME)
+#define nfserr_cb_path_down __constant_htonl(NFSERR_CB_PATH_DOWN)
/* error codes for internal use */
/* if a request fails due to kmalloc failure, it gets dropped.
diff --git a/include/linux/nfsd/state.h b/include/linux/nfsd/state.h
index d08cf66f244ae..b6b2fe1e7c63f 100644
--- a/include/linux/nfsd/state.h
+++ b/include/linux/nfsd/state.h
@@ -67,12 +67,6 @@ extern stateid_t onestateid;
#define ZERO_STATEID(stateid) (!memcmp((stateid), &zerostateid, sizeof(stateid_t)))
#define ONE_STATEID(stateid) (!memcmp((stateid), &onestateid, sizeof(stateid_t)))
-/* Delegation recall states */
-#define NFS4_NO_RECALL 0x000
-#define NFS4_RECALL_IN_PROGRESS 0x001
-#define NFS4_RECALL_COMPLETE 0x002
-#define NFS4_REAP_DELEG 0x004
-
struct nfs4_cb_recall {
u32 cbr_ident;
int cbr_trunc;
@@ -86,13 +80,11 @@ struct nfs4_delegation {
struct list_head dl_del_perfile; /* nfs4_file->fi_del_perfile */
struct list_head dl_del_perclnt; /* nfs4_client->cl_del_perclnt*/
struct list_head dl_recall_lru; /* delegation recalled */
- atomic_t dl_recall_cnt; /* resend cb_recall only once */
atomic_t dl_count; /* ref count */
- atomic_t dl_state; /* recall state */
struct nfs4_client *dl_client;
struct nfs4_file *dl_file;
struct file_lock *dl_flock;
- struct nfs4_stateid *dl_stp;
+ struct file *dl_vfs_file;
u32 dl_type;
time_t dl_time;
struct nfs4_cb_recall dl_recall;
@@ -141,7 +133,6 @@ struct nfs4_client {
clientid_t cl_clientid; /* generated by server */
nfs4_verifier cl_confirm; /* generated by server */
struct nfs4_callback cl_callback; /* callback info */
- time_t cl_first_state; /* first state aquisition*/
atomic_t cl_count; /* ref count */
};
@@ -153,8 +144,6 @@ struct nfs4_client {
struct nfs4_client_reclaim {
struct list_head cr_strhash; /* hash by cr_name */
struct xdr_netobj cr_name; /* id generated by client */
- time_t cr_first_state; /* first state aquisition */
- u32 cr_expired; /* boolean: lease expired? */
};
static inline void
@@ -258,7 +247,6 @@ struct nfs4_stateid {
struct nfs4_file * st_file;
stateid_t st_stateid;
struct file * st_vfs_file;
- int st_vfs_set;
unsigned long st_access_bmap;
unsigned long st_deny_bmap;
};
@@ -282,7 +270,7 @@ struct nfs4_stateid {
extern time_t nfs4_laundromat(void);
extern int nfsd4_renew(clientid_t *clid);
extern int nfs4_preprocess_stateid_op(struct svc_fh *current_fh,
- stateid_t *stateid, int flags);
+ stateid_t *stateid, int flags, struct file **filp);
extern int nfs4_share_conflict(struct svc_fh *current_fh,
unsigned int deny_type);
extern void nfs4_lock_state(void);
@@ -292,7 +280,8 @@ extern int nfs4_check_open_reclaim(clientid_t *clid);
extern void put_nfs4_client(struct nfs4_client *clp);
extern void nfs4_free_stateowner(struct kref *kref);
extern void nfsd4_probe_callback(struct nfs4_client *clp);
-extern int nfsd4_cb_recall(struct nfs4_delegation *dp);
+extern void nfsd4_cb_recall(struct nfs4_delegation *dp);
+extern void nfs4_put_delegation(struct nfs4_delegation *dp);
static inline void
nfs4_put_stateowner(struct nfs4_stateowner *so)
diff --git a/include/linux/nfsd/xdr4.h b/include/linux/nfsd/xdr4.h
index a63238354be79..a1f5ad0be1bf0 100644
--- a/include/linux/nfsd/xdr4.h
+++ b/include/linux/nfsd/xdr4.h
@@ -241,6 +241,7 @@ struct nfsd4_read {
u32 rd_length; /* request */
struct kvec rd_iov[RPCSVC_MAXPAGES];
int rd_vlen;
+ struct file *rd_filp;
struct svc_rqst *rd_rqstp; /* response */
struct svc_fh * rd_fhp; /* response */
diff --git a/include/linux/nodemask.h b/include/linux/nodemask.h
index 5f7f8b932cf25..e96fe90625003 100644
--- a/include/linux/nodemask.h
+++ b/include/linux/nodemask.h
@@ -10,6 +10,8 @@
*
* For details of nodemask_scnprintf() and nodemask_parse(),
* see bitmap_scnprintf() and bitmap_parse() in lib/bitmap.c.
+ * For details of nodelist_scnprintf() and nodelist_parse(), see
+ * bitmap_scnlistprintf() and bitmap_parselist(), also in bitmap.c.
*
* The available nodemask operations are:
*
@@ -48,6 +50,8 @@
*
* int nodemask_scnprintf(buf, len, mask) Format nodemask for printing
* int nodemask_parse(ubuf, ulen, mask) Parse ascii string as nodemask
+ * int nodelist_scnprintf(buf, len, mask) Format nodemask as list for printing
+ * int nodelist_parse(buf, map) Parse ascii string as nodelist
*
* for_each_node_mask(node, mask) for-loop node over mask
*
@@ -281,14 +285,28 @@ static inline int __nodemask_scnprintf(char *buf, int len,
return bitmap_scnprintf(buf, len, srcp->bits, nbits);
}
-#define nodemask_parse(ubuf, ulen, src) \
- __nodemask_parse((ubuf), (ulen), &(src), MAX_NUMNODES)
+#define nodemask_parse(ubuf, ulen, dst) \
+ __nodemask_parse((ubuf), (ulen), &(dst), MAX_NUMNODES)
static inline int __nodemask_parse(const char __user *buf, int len,
nodemask_t *dstp, int nbits)
{
return bitmap_parse(buf, len, dstp->bits, nbits);
}
+#define nodelist_scnprintf(buf, len, src) \
+ __nodelist_scnprintf((buf), (len), &(src), MAX_NUMNODES)
+static inline int __nodelist_scnprintf(char *buf, int len,
+ const nodemask_t *srcp, int nbits)
+{
+ return bitmap_scnlistprintf(buf, len, srcp->bits, nbits);
+}
+
+#define nodelist_parse(buf, dst) __nodelist_parse((buf), &(dst), MAX_NUMNODES)
+static inline int __nodelist_parse(const char *buf, nodemask_t *dstp, int nbits)
+{
+ return bitmap_parselist(buf, dstp->bits, nbits);
+}
+
#if MAX_NUMNODES > 1
#define for_each_node_mask(node, mask) \
for ((node) = first_node(mask); \
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
index 6ab9cc46640fa..6b74fcf5bb638 100644
--- a/include/linux/page-flags.h
+++ b/include/linux/page-flags.h
@@ -75,7 +75,7 @@
#define PG_mappedtodisk 17 /* Has blocks allocated on-disk */
#define PG_reclaim 18 /* To be reclaimed asap */
#define PG_nosave_free 19 /* Free, should not be written */
-
+#define PG_uncached 20 /* Page has been mapped as uncached */
/*
* Global page accounting. One instance per CPU. Only unsigned longs are
@@ -301,10 +301,13 @@ extern void __mod_page_state(unsigned offset, unsigned long delta);
#define PageSwapCache(page) 0
#endif
+#define PageUncached(page) test_bit(PG_uncached, &(page)->flags)
+#define SetPageUncached(page) set_bit(PG_uncached, &(page)->flags)
+#define ClearPageUncached(page) clear_bit(PG_uncached, &(page)->flags)
+
struct page; /* forward declaration */
int test_clear_page_dirty(struct page *page);
-int __clear_page_dirty(struct page *page);
int test_clear_page_writeback(struct page *page);
int test_set_page_writeback(struct page *page);
diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h
index c394c0c8cb392..0422031161baa 100644
--- a/include/linux/pagemap.h
+++ b/include/linux/pagemap.h
@@ -19,7 +19,7 @@
#define AS_EIO (__GFP_BITS_SHIFT + 0) /* IO error on async write */
#define AS_ENOSPC (__GFP_BITS_SHIFT + 1) /* ENOSPC on async write */
-static inline int mapping_gfp_mask(struct address_space * mapping)
+static inline unsigned int __nocast mapping_gfp_mask(struct address_space * mapping)
{
return mapping->flags & __GFP_BITS_MASK;
}
diff --git a/include/linux/parport.h b/include/linux/parport.h
index fb8774633d332..d2a4d9e1e6d13 100644
--- a/include/linux/parport.h
+++ b/include/linux/parport.h
@@ -105,8 +105,6 @@ typedef enum {
#include <asm/ptrace.h>
#include <asm/semaphore.h>
-#define PARPORT_NEED_GENERIC_OPS
-
/* Define this later. */
struct parport;
struct pardevice;
@@ -520,9 +518,8 @@ extern int parport_device_proc_register(struct pardevice *device);
extern int parport_device_proc_unregister(struct pardevice *device);
/* If PC hardware is the only type supported, we can optimise a bit. */
-#if (defined(CONFIG_PARPORT_PC) || defined(CONFIG_PARPORT_PC_MODULE)) && !(defined(CONFIG_PARPORT_ARC) || defined(CONFIG_PARPORT_ARC_MODULE)) && !(defined(CONFIG_PARPORT_AMIGA) || defined(CONFIG_PARPORT_AMIGA_MODULE)) && !(defined(CONFIG_PARPORT_MFC3) || defined(CONFIG_PARPORT_MFC3_MODULE)) && !(defined(CONFIG_PARPORT_ATARI) || defined(CONFIG_PARPORT_ATARI_MODULE)) && !(defined(CONFIG_USB_USS720) || defined(CONFIG_USB_USS720_MODULE)) && !(defined(CONFIG_PARPORT_SUNBPP) || defined(CONFIG_PARPORT_SUNBPP_MODULE)) && !defined(CONFIG_PARPORT_OTHER)
+#if !defined(CONFIG_PARPORT_NOT_PC)
-#undef PARPORT_NEED_GENERIC_OPS
#include <linux/parport_pc.h>
#define parport_write_data(p,x) parport_pc_write_data(p,x)
#define parport_read_data(p) parport_pc_read_data(p)
@@ -534,9 +531,9 @@ extern int parport_device_proc_unregister(struct pardevice *device);
#define parport_disable_irq(p) parport_pc_disable_irq(p)
#define parport_data_forward(p) parport_pc_data_forward(p)
#define parport_data_reverse(p) parport_pc_data_reverse(p)
-#endif
-#ifdef PARPORT_NEED_GENERIC_OPS
+#else /* !CONFIG_PARPORT_NOT_PC */
+
/* Generic operations vector through the dispatch table. */
#define parport_write_data(p,x) (p)->ops->write_data(p,x)
#define parport_read_data(p) (p)->ops->read_data(p)
@@ -548,7 +545,8 @@ extern int parport_device_proc_unregister(struct pardevice *device);
#define parport_disable_irq(p) (p)->ops->disable_irq(p)
#define parport_data_forward(p) (p)->ops->data_forward(p)
#define parport_data_reverse(p) (p)->ops->data_reverse(p)
-#endif
+
+#endif /* !CONFIG_PARPORT_NOT_PC */
#endif /* __KERNEL__ */
#endif /* _PARPORT_H_ */
diff --git a/include/linux/pci.h b/include/linux/pci.h
index d0844ceb28105..87da80182983d 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -549,8 +549,6 @@ struct pci_dev {
unsigned int irq;
struct resource resource[DEVICE_COUNT_RESOURCE]; /* I/O and memory regions + expansion ROMs */
- char * slot_name; /* pointer to dev.bus_id */
-
/* These fields are used by common fixups */
unsigned int transparent:1; /* Transparent PCI bridge */
unsigned int multifunction:1;/* Part of multi-function device */
@@ -642,8 +640,10 @@ struct pci_ops {
};
struct pci_raw_ops {
- int (*read)(int dom, int bus, int devfn, int reg, int len, u32 *val);
- int (*write)(int dom, int bus, int devfn, int reg, int len, u32 val);
+ int (*read)(unsigned int domain, unsigned int bus, unsigned int devfn,
+ int reg, int len, u32 *val);
+ int (*write)(unsigned int domain, unsigned int bus, unsigned int devfn,
+ int reg, int len, u32 val);
};
extern struct pci_raw_ops *raw_pci_ops;
@@ -966,9 +966,8 @@ static inline int pci_enable_wake(struct pci_dev *dev, pci_power_t state, int en
*/
#ifndef CONFIG_PCI_DOMAINS
static inline int pci_domain_nr(struct pci_bus *bus) { return 0; }
-static inline int pci_name_bus(char *name, struct pci_bus *bus)
+static inline int pci_proc_domain(struct pci_bus *bus)
{
- sprintf(name, "%02x", bus->number);
return 0;
}
#endif
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 919fa9768c193..a27d42d3e6522 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -352,10 +352,21 @@
#define PCI_DEVICE_ID_ATI_RS300_133 0x5831
#define PCI_DEVICE_ID_ATI_RS300_166 0x5832
#define PCI_DEVICE_ID_ATI_RS300_200 0x5833
+#define PCI_DEVICE_ID_ATI_RS350_100 0x7830
+#define PCI_DEVICE_ID_ATI_RS350_133 0x7831
+#define PCI_DEVICE_ID_ATI_RS350_166 0x7832
+#define PCI_DEVICE_ID_ATI_RS350_200 0x7833
+#define PCI_DEVICE_ID_ATI_RS400_100 0x5a30
+#define PCI_DEVICE_ID_ATI_RS400_133 0x5a31
+#define PCI_DEVICE_ID_ATI_RS400_166 0x5a32
+#define PCI_DEVICE_ID_ATI_RS400_200 0x5a33
+#define PCI_DEVICE_ID_ATI_RS480 0x5950
/* ATI IXP Chipset */
#define PCI_DEVICE_ID_ATI_IXP200_IDE 0x4349
#define PCI_DEVICE_ID_ATI_IXP300_IDE 0x4369
+#define PCI_DEVICE_ID_ATI_IXP300_SATA 0x436e
#define PCI_DEVICE_ID_ATI_IXP400_IDE 0x4376
+#define PCI_DEVICE_ID_ATI_IXP400_SATA 0x4379
#define PCI_VENDOR_ID_VLSI 0x1004
#define PCI_DEVICE_ID_VLSI_82C592 0x0005
@@ -386,6 +397,8 @@
#define PCI_DEVICE_ID_NS_SCx200_VIDEO 0x0504
#define PCI_DEVICE_ID_NS_SCx200_XBUS 0x0505
#define PCI_DEVICE_ID_NS_SC1100_BRIDGE 0x0510
+#define PCI_DEVICE_ID_NS_SC1100_SMI 0x0511
+#define PCI_DEVICE_ID_NS_SC1100_XBUS 0x0515
#define PCI_DEVICE_ID_NS_87410 0xd001
#define PCI_VENDOR_ID_TSENG 0x100c
@@ -506,6 +519,7 @@
#define PCI_DEVICE_ID_AMD_OPUS_7449 0x7449
# define PCI_DEVICE_ID_AMD_VIPER_7449 PCI_DEVICE_ID_AMD_OPUS_7449
#define PCI_DEVICE_ID_AMD_8111_LAN 0x7462
+#define PCI_DEVICE_ID_AMD_8111_LPC 0x7468
#define PCI_DEVICE_ID_AMD_8111_IDE 0x7469
#define PCI_DEVICE_ID_AMD_8111_SMBUS2 0x746a
#define PCI_DEVICE_ID_AMD_8111_SMBUS 0x746b
@@ -695,7 +709,10 @@
#define PCI_DEVICE_ID_HP_SX1000_IOC 0x127c
#define PCI_DEVICE_ID_HP_DIVA_EVEREST 0x1282
#define PCI_DEVICE_ID_HP_DIVA_AUX 0x1290
+#define PCI_DEVICE_ID_HP_DIVA_RMP3 0x1301
#define PCI_DEVICE_ID_HP_CISSA 0x3220
+#define PCI_DEVICE_ID_HP_CISSB 0x3230
+#define PCI_DEVICE_ID_HP_ZX2_IOC 0x4031
#define PCI_VENDOR_ID_PCTECH 0x1042
#define PCI_DEVICE_ID_PCTECH_RZ1000 0x1000
@@ -753,6 +770,7 @@
#define PCI_DEVICE_ID_TI_1251B 0xac1f
#define PCI_DEVICE_ID_TI_4410 0xac41
#define PCI_DEVICE_ID_TI_4451 0xac42
+#define PCI_DEVICE_ID_TI_4510 0xac44
#define PCI_DEVICE_ID_TI_4520 0xac46
#define PCI_DEVICE_ID_TI_1410 0xac50
#define PCI_DEVICE_ID_TI_1420 0xac51
@@ -792,6 +810,7 @@
#define PCI_DEVICE_ID_MOTOROLA_HAWK 0x4803
#define PCI_DEVICE_ID_MOTOROLA_CPX8216 0x4806
#define PCI_DEVICE_ID_MOTOROLA_HARRIER 0x480b
+#define PCI_DEVICE_ID_MOTOROLA_MPC5200 0x5803
#define PCI_VENDOR_ID_PROMISE 0x105a
#define PCI_DEVICE_ID_PROMISE_20265 0x0d30
@@ -861,7 +880,13 @@
#define PCI_DEVICE_ID_APPLE_IPID_ATA100 0x003b
#define PCI_DEVICE_ID_APPLE_KEYLARGO_I 0x003e
#define PCI_DEVICE_ID_APPLE_K2_ATA100 0x0043
+#define PCI_DEVICE_ID_APPLE_U3_AGP 0x004b
#define PCI_DEVICE_ID_APPLE_K2_GMAC 0x004c
+#define PCI_DEVICE_ID_APPLE_SH_ATA 0x0050
+#define PCI_DEVICE_ID_APPLE_SH_SUNGEM 0x0051
+#define PCI_DEVICE_ID_APPLE_SH_FW 0x0052
+#define PCI_DEVICE_ID_APPLE_U3L_AGP 0x0058
+#define PCI_DEVICE_ID_APPLE_U3H_AGP 0x0059
#define PCI_DEVICE_ID_APPLE_TIGON3 0x1645
#define PCI_VENDOR_ID_YAMAHA 0x1073
@@ -1091,6 +1116,7 @@
#define PCI_DEVICE_ID_NVIDIA_TNT 0x0020
#define PCI_DEVICE_ID_NVIDIA_TNT2 0x0028
#define PCI_DEVICE_ID_NVIDIA_UTNT2 0x0029
+#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_IDE 0x0035
@@ -1098,6 +1124,12 @@
#define PCI_DEVICE_ID_NVIDIA_NVENET_10 0x0037
#define PCI_DEVICE_ID_NVIDIA_NVENET_11 0x0038
#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA2 0x003e
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6800_ULTRA 0x0040
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6800 0x0041
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6800_LE 0x0042
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6800_GT 0x0045
+#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_4000 0x004E
+#define PCI_DEVICE_ID_NVIDIA_NFORCE4_SMBUS 0x0052
#define PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE 0x0053
#define PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA 0x0054
#define PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA2 0x0055
@@ -1114,6 +1146,12 @@
#define PCI_DEVICE_ID_NVIDIA_NVENET_5 0x008c
#define PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA 0x008e
#define PCI_DEVICE_ID_NVIDIA_ITNT2 0x00A0
+#define PCI_DEVICE_ID_GEFORCE_6800A 0x00c1
+#define PCI_DEVICE_ID_GEFORCE_6800A_LE 0x00c2
+#define PCI_DEVICE_ID_GEFORCE_GO_6800 0x00c8
+#define PCI_DEVICE_ID_GEFORCE_GO_6800_ULTRA 0x00c9
+#define PCI_DEVICE_ID_QUADRO_FX_GO1400 0x00cc
+#define PCI_DEVICE_ID_QUADRO_FX_1400 0x00ce
#define PCI_DEVICE_ID_NVIDIA_NFORCE3 0x00d1
#define PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO 0x00da
#define PCI_DEVICE_ID_NVIDIA_NFORCE3_SMBUS 0x00d4
@@ -1134,21 +1172,43 @@
#define PCI_DEVICE_ID_NVIDIA_GEFORCE2_MX2 0x0111
#define PCI_DEVICE_ID_NVIDIA_GEFORCE2_GO 0x0112
#define PCI_DEVICE_ID_NVIDIA_QUADRO2_MXR 0x0113
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6600_GT 0x0140
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6600 0x0141
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6610_XL 0x0145
+#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_540 0x014E
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6200 0x014F
#define PCI_DEVICE_ID_NVIDIA_GEFORCE2_GTS 0x0150
#define PCI_DEVICE_ID_NVIDIA_GEFORCE2_GTS2 0x0151
#define PCI_DEVICE_ID_NVIDIA_GEFORCE2_ULTRA 0x0152
#define PCI_DEVICE_ID_NVIDIA_QUADRO2_PRO 0x0153
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6200_TURBOCACHE 0x0161
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_6200 0x0164
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_6250 0x0166
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_6200_1 0x0167
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_6250_1 0x0168
#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_460 0x0170
#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440 0x0171
#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_420 0x0172
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440_SE 0x0173
#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_440_GO 0x0174
#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_420_GO 0x0175
#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_420_GO_M32 0x0176
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_460_GO 0x0177
#define PCI_DEVICE_ID_NVIDIA_QUADRO4_500XGL 0x0178
#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_440_GO_M64 0x0179
#define PCI_DEVICE_ID_NVIDIA_QUADRO4_200 0x017A
#define PCI_DEVICE_ID_NVIDIA_QUADRO4_550XGL 0x017B
#define PCI_DEVICE_ID_NVIDIA_QUADRO4_500_GOGL 0x017C
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_410_GO_M16 0x017D
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440_8X 0x0181
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440SE_8X 0x0182
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_420_8X 0x0183
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_448_GO 0x0186
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_488_GO 0x0187
+#define PCI_DEVICE_ID_NVIDIA_QUADRO4_580_XGL 0x0188
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_MAC 0x0189
+#define PCI_DEVICE_ID_NVIDIA_QUADRO4_280_NVS 0x018A
+#define PCI_DEVICE_ID_NVIDIA_QUADRO4_380_XGL 0x018B
#define PCI_DEVICE_ID_NVIDIA_IGEFORCE2 0x01a0
#define PCI_DEVICE_ID_NVIDIA_NFORCE 0x01a4
#define PCI_DEVICE_ID_NVIDIA_MCP1_AUDIO 0x01b1
@@ -1160,13 +1220,61 @@
#define PCI_DEVICE_ID_NVIDIA_GEFORCE3_1 0x0201
#define PCI_DEVICE_ID_NVIDIA_GEFORCE3_2 0x0202
#define PCI_DEVICE_ID_NVIDIA_QUADRO_DDC 0x0203
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6800B 0x0211
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6800B_LE 0x0212
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6800B_GT 0x0215
#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4600 0x0250
#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4400 0x0251
#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4200 0x0253
#define PCI_DEVICE_ID_NVIDIA_QUADRO4_900XGL 0x0258
#define PCI_DEVICE_ID_NVIDIA_QUADRO4_750XGL 0x0259
#define PCI_DEVICE_ID_NVIDIA_QUADRO4_700XGL 0x025B
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO_5200 0x0329
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800 0x0280
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800_8X 0x0281
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800SE 0x0282
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_4200_GO 0x0286
+#define PCI_DEVICE_ID_NVIDIA_QUADRO4_980_XGL 0x0288
+#define PCI_DEVICE_ID_NVIDIA_QUADRO4_780_XGL 0x0289
+#define PCI_DEVICE_ID_NVIDIA_QUADRO4_700_GOGL 0x028C
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5800_ULTRA 0x0301
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5800 0x0302
+#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_2000 0x0308
+#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_1000 0x0309
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5600_ULTRA 0x0311
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5600 0x0312
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5600SE 0x0314
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5600 0x031A
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5650 0x031B
+#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_GO700 0x031C
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5200 0x0320
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5200_ULTRA 0x0321
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5200_1 0x0322
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5200SE 0x0323
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5200 0x0324
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5250 0x0325
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5500 0x0326
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5100 0x0327
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5250_32 0x0328
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO_5200 0x0329
+#define PCI_DEVICE_ID_NVIDIA_QUADRO_NVS_280_PCI 0x032A
+#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_500 0x032B
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5300 0x032C
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5100 0x032D
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5900_ULTRA 0x0330
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5900 0x0331
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5900XT 0x0332
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5950_ULTRA 0x0333
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5900ZT 0x0334
+#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_3000 0x0338
+#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_700 0x033F
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5700_ULTRA 0x0341
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5700 0x0342
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5700LE 0x0343
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5700VE 0x0344
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5700_1 0x0347
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5700_2 0x0348
+#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_GO1000 0x034C
+#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_1100 0x034E
#define PCI_VENDOR_ID_IMS 0x10e0
#define PCI_DEVICE_ID_IMS_8849 0x8849
@@ -1418,6 +1526,10 @@
#define PCI_DEVICE_ID_DIGI_DF_M_E 0x0071
#define PCI_DEVICE_ID_DIGI_DF_M_IOM2_A 0x0072
#define PCI_DEVICE_ID_DIGI_DF_M_A 0x0073
+#define PCI_DEVICE_ID_NEO_2DB9 0x00C8
+#define PCI_DEVICE_ID_NEO_2DB9PRI 0x00C9
+#define PCI_DEVICE_ID_NEO_2RJ45 0x00CA
+#define PCI_DEVICE_ID_NEO_2RJ45PRI 0x00CB
#define PCI_VENDOR_ID_MUTECH 0x1159
#define PCI_DEVICE_ID_MUTECH_MV1000 0x0001
@@ -1497,6 +1609,9 @@
#define PCI_DEVICE_ID_ARTOP_AEC7612D 0x8040
#define PCI_DEVICE_ID_ARTOP_AEC7612SUW 0x8050
#define PCI_DEVICE_ID_ARTOP_8060 0x8060
+#define PCI_DEVICE_ID_ARTOP_AEC67160 0x8080
+#define PCI_DEVICE_ID_ARTOP_AEC67160_2 0x8081
+#define PCI_DEVICE_ID_ARTOP_AEC67162 0x808a
#define PCI_VENDOR_ID_ZEITNET 0x1193
#define PCI_DEVICE_ID_ZEITNET_1221 0x0001
@@ -1609,6 +1724,10 @@
#define PCI_DEVICE_ID_PC300_TE_M_2 0x0320
#define PCI_DEVICE_ID_PC300_TE_M_1 0x0321
+/* Allied Telesyn */
+#define PCI_VENDOR_ID_AT 0x1259
+#define PCI_SUBDEVICE_ID_AT_2701FX 0x2703
+
#define PCI_VENDOR_ID_ESSENTIAL 0x120f
#define PCI_DEVICE_ID_ESSENTIAL_ROADRUNNER 0x0001
@@ -1652,6 +1771,11 @@
#define PCI_DEVICE_ID_OPTIBASE_VPLEXCC 0x2120
#define PCI_DEVICE_ID_OPTIBASE_VQUEST 0x2130
+/* Allied Telesyn */
+#define PCI_VENDOR_ID_AT 0x1259
+#define PCI_SUBDEVICE_ID_AT_2700FX 0x2701
+#define PCI_SUBDEVICE_ID_AT_2701FX 0x2703
+
#define PCI_VENDOR_ID_ESS 0x125d
#define PCI_DEVICE_ID_ESS_ESS1968 0x1968
#define PCI_DEVICE_ID_ESS_AUDIOPCI 0x1969
@@ -1789,6 +1913,7 @@
#define PCI_DEVICE_ID_SEALEVEL_UCOMM232 0x7202
#define PCI_DEVICE_ID_SEALEVEL_COMM4 0x7401
#define PCI_DEVICE_ID_SEALEVEL_COMM8 0x7801
+#define PCI_DEVICE_ID_SEALEVEL_UCOMM8 0x7804
#define PCI_VENDOR_ID_HYPERCOPE 0x1365
#define PCI_DEVICE_ID_HYPERCOPE_PLX 0x9050
@@ -1905,6 +2030,8 @@
#define PCI_DEVICE_ID_OXSEMI_16PCI954PP 0x9513
#define PCI_DEVICE_ID_OXSEMI_16PCI952 0x9521
+#define PCI_VENDOR_ID_SAMSUNG 0x144d
+
#define PCI_VENDOR_ID_AIRONET 0x14b9
#define PCI_DEVICE_ID_AIRONET_4800_1 0x0001
#define PCI_DEVICE_ID_AIRONET_4800 0x4500 // values switched? see
@@ -1972,6 +2099,9 @@
#define PCI_DEVICE_ID_BCM4401 0x4401
#define PCI_DEVICE_ID_BCM4401B0 0x4402
+#define PCI_VENDOR_ID_TOPIC 0x151f
+#define PCI_DEVICE_ID_TOPIC_TP560 0x0000
+
#define PCI_VENDOR_ID_ENE 0x1524
#define PCI_DEVICE_ID_ENE_1211 0x1211
#define PCI_DEVICE_ID_ENE_1225 0x1225
@@ -2029,13 +2159,15 @@
#define PCI_VENDOR_ID_S2IO 0x17d5
#define PCI_DEVICE_ID_S2IO_WIN 0x5731
#define PCI_DEVICE_ID_S2IO_UNI 0x5831
+#define PCI_DEVICE_ID_HERC_WIN 0x5732
+#define PCI_DEVICE_ID_HERC_UNI 0x5832
#define PCI_VENDOR_ID_INFINICON 0x1820
#define PCI_VENDOR_ID_TOPSPIN 0x1867
-#define PCI_VENDOR_ID_ARC 0x192E
-#define PCI_DEVICE_ID_ARC_EHCI 0x0101
+#define PCI_VENDOR_ID_TDI 0x192E
+#define PCI_DEVICE_ID_TDI_EHCI 0x0101
#define PCI_VENDOR_ID_SYMPHONY 0x1c1c
#define PCI_DEVICE_ID_SYMPHONY_101 0x0001
@@ -2261,7 +2393,6 @@
#define PCI_DEVICE_ID_INTEL_ICH7_1 0x27b1
#define PCI_DEVICE_ID_INTEL_ICH7_2 0x27c0
#define PCI_DEVICE_ID_INTEL_ICH7_3 0x27c1
-#define PCI_DEVICE_ID_INTEL_ICH7_4 0x27c2
#define PCI_DEVICE_ID_INTEL_ICH7_5 0x27c4
#define PCI_DEVICE_ID_INTEL_ICH7_6 0x27c5
#define PCI_DEVICE_ID_INTEL_ICH7_7 0x27c8
@@ -2393,6 +2524,7 @@
#define PCI_DEVICE_ID_ADAPTEC2_7899B 0x00c1
#define PCI_DEVICE_ID_ADAPTEC2_7899D 0x00c3
#define PCI_DEVICE_ID_ADAPTEC2_7899P 0x00cf
+#define PCI_DEVICE_ID_ADAPTEC2_SCAMP 0x0503
#define PCI_VENDOR_ID_ATRONICS 0x907f
#define PCI_DEVICE_ID_ATRONICS_2015 0x2015
@@ -2402,13 +2534,15 @@
#define PCI_VENDOR_ID_NETMOS 0x9710
#define PCI_DEVICE_ID_NETMOS_9705 0x9705
+#define PCI_DEVICE_ID_NETMOS_9715 0x9715
#define PCI_DEVICE_ID_NETMOS_9735 0x9735
+#define PCI_DEVICE_ID_NETMOS_9745 0x9745
+#define PCI_DEVICE_ID_NETMOS_9755 0x9755
#define PCI_DEVICE_ID_NETMOS_9805 0x9805
#define PCI_DEVICE_ID_NETMOS_9815 0x9815
#define PCI_DEVICE_ID_NETMOS_9835 0x9835
+#define PCI_DEVICE_ID_NETMOS_9845 0x9845
#define PCI_DEVICE_ID_NETMOS_9855 0x9855
-#define PCI_DEVICE_ID_NETMOS_9755 0x9755
-#define PCI_DEVICE_ID_NETMOS_9715 0x9715
#define PCI_SUBVENDOR_ID_EXSYS 0xd84d
#define PCI_SUBDEVICE_ID_EXSYS_4014 0x4014
diff --git a/include/linux/personality.h b/include/linux/personality.h
index 7cef4670ac05b..80d780e5a8f5a 100644
--- a/include/linux/personality.h
+++ b/include/linux/personality.h
@@ -18,6 +18,7 @@ extern int __set_personality(unsigned long);
* These occupy the top three bytes.
*/
enum {
+ ADDR_NO_RANDOMIZE = 0x0040000, /* disable randomization of VA space */
FDPIC_FUNCPTRS = 0x0080000, /* userspace function ptrs point to descriptors
* (signal handling)
*/
@@ -35,7 +36,7 @@ enum {
* Security-relevant compatibility flags that must be
* cleared upon setuid or setgid exec:
*/
-#define PER_CLEAR_ON_SETID (READ_IMPLIES_EXEC)
+#define PER_CLEAR_ON_SETID (READ_IMPLIES_EXEC|ADDR_NO_RANDOMIZE)
/*
* Personality types.
diff --git a/include/linux/pkt_cls.h b/include/linux/pkt_cls.h
index 3101ef5000adf..d2aa214d68032 100644
--- a/include/linux/pkt_cls.h
+++ b/include/linux/pkt_cls.h
@@ -80,6 +80,7 @@ enum
TCA_ACT_KIND,
TCA_ACT_OPTIONS,
TCA_ACT_INDEX,
+ TCA_ACT_STATS,
__TCA_ACT_MAX
};
@@ -221,14 +222,20 @@ struct tc_u32_sel
struct tc_u32_key keys[0];
};
-#ifdef CONFIG_CLS_U32_PERF
+struct tc_u32_mark
+{
+ __u32 val;
+ __u32 mask;
+ __u32 success;
+};
+
struct tc_u32_pcnt
{
__u64 rcnt;
__u64 rhit;
__u64 kcnts[0];
};
-#endif
+
/* Flags */
#define TC_U32_TERMINAL 1
@@ -319,4 +326,101 @@ enum
#define TCA_TCINDEX_MAX (__TCA_TCINDEX_MAX - 1)
+/* Basic filter */
+
+enum
+{
+ TCA_BASIC_UNSPEC,
+ TCA_BASIC_CLASSID,
+ TCA_BASIC_EMATCHES,
+ TCA_BASIC_ACT,
+ TCA_BASIC_POLICE,
+ __TCA_BASIC_MAX
+};
+
+#define TCA_BASIC_MAX (__TCA_BASIC_MAX - 1)
+
+/* Extended Matches */
+
+struct tcf_ematch_tree_hdr
+{
+ __u16 nmatches;
+ __u16 progid;
+};
+
+enum
+{
+ TCA_EMATCH_TREE_UNSPEC,
+ TCA_EMATCH_TREE_HDR,
+ TCA_EMATCH_TREE_LIST,
+ __TCA_EMATCH_TREE_MAX
+};
+#define TCA_EMATCH_TREE_MAX (__TCA_EMATCH_TREE_MAX - 1)
+
+struct tcf_ematch_hdr
+{
+ __u16 matchid;
+ __u16 kind;
+ __u16 flags;
+ __u16 pad; /* currently unused */
+};
+
+/* 0 1
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+ * +-----------------------+-+-+---+
+ * | Unused |S|I| R |
+ * +-----------------------+-+-+---+
+ *
+ * R(2) ::= relation to next ematch
+ * where: 0 0 END (last ematch)
+ * 0 1 AND
+ * 1 0 OR
+ * 1 1 Unused (invalid)
+ * I(1) ::= invert result
+ * S(1) ::= simple payload
+ */
+#define TCF_EM_REL_END 0
+#define TCF_EM_REL_AND (1<<0)
+#define TCF_EM_REL_OR (1<<1)
+#define TCF_EM_INVERT (1<<2)
+#define TCF_EM_SIMPLE (1<<3)
+
+#define TCF_EM_REL_MASK 3
+#define TCF_EM_REL_VALID(v) (((v) & TCF_EM_REL_MASK) != TCF_EM_REL_MASK)
+
+enum
+{
+ TCF_LAYER_LINK,
+ TCF_LAYER_NETWORK,
+ TCF_LAYER_TRANSPORT,
+ __TCF_LAYER_MAX
+};
+#define TCF_LAYER_MAX (__TCF_LAYER_MAX - 1)
+
+/* Ematch type assignments
+ * 1..32767 Reserved for ematches inside kernel tree
+ * 32768..65535 Free to use, not reliable
+ */
+enum
+{
+ TCF_EM_CONTAINER,
+ TCF_EM_CMP,
+ TCF_EM_NBYTE,
+ TCF_EM_U32,
+ TCF_EM_META,
+ __TCF_EM_MAX
+};
+
+enum
+{
+ TCF_EM_PROG_TC
+};
+
+enum
+{
+ TCF_EM_OPND_EQ,
+ TCF_EM_OPND_GT,
+ TCF_EM_OPND_LT
+};
+
#endif
diff --git a/include/linux/pm.h b/include/linux/pm.h
index 1d106a3edad56..ed2b76e751992 100644
--- a/include/linux/pm.h
+++ b/include/linux/pm.h
@@ -116,11 +116,6 @@ void __deprecated pm_unregister(struct pm_dev *dev);
void __deprecated pm_unregister_all(pm_callback callback);
/*
- * Send a request to a single device
- */
-int __deprecated pm_send(struct pm_dev *dev, pm_request_t rqst, void *data);
-
-/*
* Send a request to all devices
*/
int __deprecated pm_send_all(pm_request_t rqst, void *data);
@@ -140,11 +135,6 @@ static inline void pm_unregister(struct pm_dev *dev) {}
static inline void pm_unregister_all(pm_callback callback) {}
-static inline int pm_send(struct pm_dev *dev, pm_request_t rqst, void *data)
-{
- return 0;
-}
-
static inline int pm_send_all(pm_request_t rqst, void *data)
{
return 0;
diff --git a/include/linux/pnp.h b/include/linux/pnp.h
index b74b2b643cb23..5ec2bd0c28483 100644
--- a/include/linux/pnp.h
+++ b/include/linux/pnp.h
@@ -378,7 +378,6 @@ int pnp_register_dma_resource(struct pnp_option *option, struct pnp_dma *data);
int pnp_register_port_resource(struct pnp_option *option, struct pnp_port *data);
int pnp_register_mem_resource(struct pnp_option *option, struct pnp_mem *data);
void pnp_init_resource_table(struct pnp_resource_table *table);
-int pnp_assign_resources(struct pnp_dev *dev, int depnum);
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);
@@ -423,7 +422,6 @@ static inline int pnp_register_dma_resource(struct pnp_option *option, struct pn
static inline int pnp_register_port_resource(struct pnp_option *option, struct pnp_port *data) { return -ENODEV; }
static inline int pnp_register_mem_resource(struct pnp_option *option, struct pnp_mem *data) { return -ENODEV; }
static inline void pnp_init_resource_table(struct pnp_resource_table *table) { }
-static inline int pnp_assign_resources(struct pnp_dev *dev, int depnum) { return -ENODEV; }
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; }
diff --git a/include/linux/poll.h b/include/linux/poll.h
index 1bb33342cbbdf..f6da702088f41 100644
--- a/include/linux/poll.h
+++ b/include/linux/poll.h
@@ -71,13 +71,9 @@ static inline
int get_fd_set(unsigned long nr, void __user *ufdset, unsigned long *fdset)
{
nr = FDS_BYTES(nr);
- if (ufdset) {
- int error;
- error = verify_area(VERIFY_WRITE, ufdset, nr);
- if (!error && __copy_from_user(fdset, ufdset, nr))
- error = -EFAULT;
- return error;
- }
+ if (ufdset)
+ return copy_from_user(fdset, ufdset, nr) ? -EFAULT : 0;
+
memset(fdset, 0, nr);
return 0;
}
diff --git a/include/linux/posix-timers.h b/include/linux/posix-timers.h
index 006f3e9af4756..f942e2bad8e35 100644
--- a/include/linux/posix-timers.h
+++ b/include/linux/posix-timers.h
@@ -3,6 +3,36 @@
#include <linux/spinlock.h>
#include <linux/list.h>
+#include <linux/sched.h>
+
+union cpu_time_count {
+ cputime_t cpu;
+ unsigned long long sched;
+};
+
+struct cpu_timer_list {
+ struct list_head entry;
+ union cpu_time_count expires, incr;
+ struct task_struct *task;
+ int firing;
+};
+
+#define CPUCLOCK_PID(clock) ((pid_t) ~((clock) >> 3))
+#define CPUCLOCK_PERTHREAD(clock) \
+ (((clock) & (clockid_t) CPUCLOCK_PERTHREAD_MASK) != 0)
+#define CPUCLOCK_PID_MASK 7
+#define CPUCLOCK_PERTHREAD_MASK 4
+#define CPUCLOCK_WHICH(clock) ((clock) & (clockid_t) CPUCLOCK_CLOCK_MASK)
+#define CPUCLOCK_CLOCK_MASK 3
+#define CPUCLOCK_PROF 0
+#define CPUCLOCK_VIRT 1
+#define CPUCLOCK_SCHED 2
+#define CPUCLOCK_MAX 3
+
+#define MAKE_PROCESS_CPUCLOCK(pid, clock) \
+ ((~(clockid_t) (pid) << 3) | (clockid_t) (clock))
+#define MAKE_THREAD_CPUCLOCK(tid, clock) \
+ MAKE_PROCESS_CPUCLOCK((tid), (clock) | CPUCLOCK_PERTHREAD_MASK)
/* POSIX.1b interval timer structure. */
struct k_itimer {
@@ -13,15 +43,27 @@ struct k_itimer {
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 */
+#define REQUEUE_PENDING 1
int it_sigev_notify; /* notify word of sigevent struct */
int it_sigev_signo; /* signo word of sigevent struct */
sigval_t it_sigev_value; /* value word of sigevent struct */
- unsigned long it_incr; /* interval specified in jiffies */
struct task_struct *it_process; /* process to send signal to */
- struct timer_list it_timer;
struct sigqueue *sigq; /* signal queue entry. */
- struct list_head abs_timer_entry; /* clock abs_timer_list */
- struct timespec wall_to_prev; /* wall_to_monotonic used when set */
+ 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 */
+ } real;
+ struct cpu_timer_list cpu;
+ struct {
+ unsigned int clock;
+ unsigned int node;
+ unsigned long incr;
+ unsigned long expires;
+ } mmtimer;
+ } it;
};
struct k_clock_abs {
@@ -30,26 +72,27 @@ struct k_clock_abs {
};
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) (struct timespec * tp);
- int (*clock_get) (struct timespec * tp);
+ int (*clock_set) (clockid_t which_clock, struct timespec * tp);
+ int (*clock_get) (clockid_t which_clock, struct timespec * tp);
int (*timer_create) (struct k_itimer *timer);
- int (*nsleep) (int which_clock, int flags,
- struct timespec * t);
+ int (*nsleep) (clockid_t which_clock, int flags, struct timespec *);
int (*timer_set) (struct k_itimer * timr, int flags,
struct itimerspec * new_setting,
struct itimerspec * old_setting);
int (*timer_del) (struct k_itimer * timr);
+#define TIMER_RETRY 1
void (*timer_get) (struct k_itimer * timr,
struct itimerspec * cur_setting);
};
-void register_posix_clock(int clock_id, struct k_clock *new_clock);
+void register_posix_clock(clockid_t clock_id, struct k_clock *new_clock);
/* Error handlers for timer_create, nanosleep and settime */
int do_posix_clock_notimer_create(struct k_itimer *timer);
-int do_posix_clock_nonanosleep(int which_clock, int flags, struct timespec * t);
-int do_posix_clock_nosettime(struct timespec *tp);
+int do_posix_clock_nonanosleep(clockid_t, int flags, struct timespec *);
+int do_posix_clock_nosettime(clockid_t, struct timespec *tp);
/* function to call to trigger timer event */
int posix_timer_event(struct k_itimer *timr, int si_private);
@@ -65,12 +108,32 @@ struct now_struct {
#define posix_bump_timer(timr, now) \
do { \
long delta, orun; \
- delta = now.jiffies - (timr)->it_timer.expires; \
+ delta = now.jiffies - (timr)->it.real.timer.expires; \
if (delta >= 0) { \
- orun = 1 + (delta / (timr)->it_incr); \
- (timr)->it_timer.expires += orun * (timr)->it_incr; \
+ orun = 1 + (delta / (timr)->it.real.incr); \
+ (timr)->it.real.timer.expires += \
+ orun * (timr)->it.real.incr; \
(timr)->it_overrun += orun; \
} \
}while (0)
-#endif
+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 *);
+
+#endif
diff --git a/include/linux/posix_acl.h b/include/linux/posix_acl.h
index fc74ef3fef365..4caedddaa0337 100644
--- a/include/linux/posix_acl.h
+++ b/include/linux/posix_acl.h
@@ -71,11 +71,11 @@ posix_acl_release(struct posix_acl *acl)
/* posix_acl.c */
-extern struct posix_acl *posix_acl_alloc(int, int);
-extern struct posix_acl *posix_acl_clone(const struct posix_acl *, int);
+extern struct posix_acl *posix_acl_alloc(int, unsigned int __nocast);
+extern struct posix_acl *posix_acl_clone(const struct posix_acl *, unsigned int __nocast);
extern int posix_acl_valid(const struct posix_acl *);
extern int posix_acl_permission(struct inode *, const struct posix_acl *, int);
-extern struct posix_acl *posix_acl_from_mode(mode_t, int);
+extern struct posix_acl *posix_acl_from_mode(mode_t, unsigned int __nocast);
extern int posix_acl_equiv_mode(const struct posix_acl *, mode_t *);
extern int posix_acl_create_masq(struct posix_acl *, mode_t *);
extern int posix_acl_chmod_masq(struct posix_acl *, mode_t);
diff --git a/include/linux/qnx4_fs.h b/include/linux/qnx4_fs.h
index 53233c8fb3ef6..22ba580b0ae89 100644
--- a/include/linux/qnx4_fs.h
+++ b/include/linux/qnx4_fs.h
@@ -114,7 +114,6 @@ extern struct dentry *qnx4_lookup(struct inode *dir, struct dentry *dentry, stru
extern unsigned long qnx4_count_free_blocks(struct super_block *sb);
extern unsigned long qnx4_block_map(struct inode *inode, long iblock);
-extern struct buffer_head *qnx4_getblk(struct inode *, int, int);
extern struct buffer_head *qnx4_bread(struct inode *, int, int);
extern struct inode_operations qnx4_file_inode_operations;
@@ -130,7 +129,6 @@ extern int qnx4_unlink(struct inode *dir, struct dentry *dentry);
extern int qnx4_rmdir(struct inode *dir, struct dentry *dentry);
extern int qnx4_sync_file(struct file *file, struct dentry *dentry, int);
extern int qnx4_sync_inode(struct inode *inode);
-extern int qnx4_get_block(struct inode *inode, sector_t iblock, struct buffer_head *bh, int create);
static inline struct qnx4_sb_info *qnx4_sb(struct super_block *sb)
{
diff --git a/include/linux/random.h b/include/linux/random.h
index c6f95fc1de135..cc67034499160 100644
--- a/include/linux/random.h
+++ b/include/linux/random.h
@@ -53,16 +53,10 @@ 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_tcp_sequence_number(__u32 saddr, __u32 daddr,
__u16 sport, __u16 dport);
-extern __u32 secure_tcp_syn_cookie(__u32 saddr, __u32 daddr,
- __u16 sport, __u16 dport,
- __u32 sseq, __u32 count,
- __u32 data);
-extern __u32 check_tcp_syn_cookie(__u32 cookie, __u32 saddr,
- __u32 daddr, __u16 sport,
- __u16 dport, __u32 sseq,
- __u32 count, __u32 maxdiff);
extern __u32 secure_tcpv6_sequence_number(__u32 *saddr, __u32 *daddr,
__u16 sport, __u16 dport);
@@ -70,6 +64,9 @@ extern __u32 secure_tcpv6_sequence_number(__u32 *saddr, __u32 *daddr,
extern struct file_operations random_fops, urandom_fops;
#endif
+unsigned int get_random_int(void);
+unsigned long randomize_range(unsigned long start, unsigned long end, unsigned long len);
+
#endif /* __KERNEL___ */
#endif /* _LINUX_RANDOM_H */
diff --git a/include/linux/reiserfs_fs_i.h b/include/linux/reiserfs_fs_i.h
index e08142a75f030..e321eb050d655 100644
--- a/include/linux/reiserfs_fs_i.h
+++ b/include/linux/reiserfs_fs_i.h
@@ -23,9 +23,8 @@ typedef enum {
space on crash with some files open, but unlinked. */
i_link_saved_unlink_mask = 0x0010,
i_link_saved_truncate_mask = 0x0020,
- i_priv_object = 0x0080,
- i_has_xattr_dir = 0x0100,
- i_data_log = 0x0200,
+ i_has_xattr_dir = 0x0040,
+ i_data_log = 0x0080,
} reiserfs_inode_flags;
diff --git a/include/linux/reiserfs_xattr.h b/include/linux/reiserfs_xattr.h
index 9c40c4e9ba035..1eaa48eca8117 100644
--- a/include/linux/reiserfs_xattr.h
+++ b/include/linux/reiserfs_xattr.h
@@ -31,7 +31,7 @@ struct reiserfs_xattr_handler {
#ifdef CONFIG_REISERFS_FS_XATTR
-#define is_reiserfs_priv_object(inode) (REISERFS_I(inode)->i_flags & i_priv_object)
+#define is_reiserfs_priv_object(inode) IS_PRIVATE(inode)
#define has_xattr_dir(inode) (REISERFS_I(inode)->i_flags & i_has_xattr_dir)
ssize_t reiserfs_getxattr (struct dentry *dentry, const char *name,
void *buffer, size_t size);
@@ -103,9 +103,16 @@ reiserfs_read_unlock_xattr_i(struct inode *inode)
up_read (&REISERFS_I(inode)->xattr_sem);
}
+static inline void
+reiserfs_mark_inode_private(struct inode *inode)
+{
+ inode->i_flags |= S_PRIVATE;
+}
+
#else
#define is_reiserfs_priv_object(inode) 0
+#define reiserfs_mark_inode_private(inode)
#define reiserfs_getxattr NULL
#define reiserfs_setxattr NULL
#define reiserfs_listxattr NULL
diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
index c3d5d043a5cab..1b4e5122d697f 100644
--- a/include/linux/rtnetlink.h
+++ b/include/linux/rtnetlink.h
@@ -250,6 +250,7 @@ enum rtattr_type_t
RTA_FLOW,
RTA_CACHEINFO,
RTA_SESSION,
+ RTA_MP_ALGO,
__RTA_MAX
};
@@ -346,6 +347,7 @@ enum
#define RTAX_FEATURE_ECN 0x00000001
#define RTAX_FEATURE_SACK 0x00000002
#define RTAX_FEATURE_TIMESTAMP 0x00000004
+#define RTAX_FEATURE_ALLFRAG 0x00000008
struct rta_session
{
@@ -396,6 +398,19 @@ enum
#define IFA_MAX (__IFA_MAX - 1)
+/*
+ * Quirk for IPv4 address deletion to allow exact deletion of equal
+ * addresses varying only in prefix length. A explicit exact comparison
+ * of the prefix length will only be done if IFA_PREFIX_EXACT_DEL is
+ * ORed to ifa_prefixlen.
+ *
+ * Note: This special treatment is only understood while deleting
+ * addresses and will lead to unexpected behaviour if used
+ * otherwise.
+ */
+#define IFA_PREFIX_EXACT_DEL 0x40
+#define IFA_REAL_DEL_PREFIX(l) ((l) & 0x3f)
+
/* ifa_flags */
#define IFA_F_SECONDARY 0x01
@@ -446,6 +461,7 @@ enum
NDA_DST,
NDA_LLADDR,
NDA_CACHEINFO,
+ NDA_PROBES,
__NDA_MAX
};
@@ -699,7 +715,6 @@ enum
TCA_RATE,
TCA_FCNT,
TCA_STATS2,
- TCA_ACT_STATS,
__TCA_MAX
};
@@ -779,6 +794,11 @@ extern void __rta_fill(struct sk_buff *skb, int attrtype, int attrlen, const voi
goto rtattr_failure; \
__rta_fill(skb, attrtype, attrlen, data); })
+#define RTA_PUT_NOHDR(skb, attrlen, data) \
+({ if (unlikely(skb_tailroom(skb) < (int)(attrlen))) \
+ goto rtattr_failure; \
+ memcpy(skb_put(skb, RTA_ALIGN(attrlen)), data, attrlen); })
+
static inline struct rtattr *
__rta_reserve(struct sk_buff *skb, int attrtype, int attrlen)
{
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 1f4ccd433ce9f..a30e91f40da67 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -14,6 +14,7 @@
#include <linux/thread_info.h>
#include <linux/cpumask.h>
#include <linux/errno.h>
+#include <linux/nodemask.h>
#include <asm/system.h>
#include <asm/semaphore.h>
@@ -32,6 +33,7 @@
#include <linux/pid.h>
#include <linux/percpu.h>
#include <linux/topology.h>
+#include <linux/seccomp.h>
struct exec_domain;
@@ -173,7 +175,6 @@ extern void cpu_init (void);
extern void trap_init(void);
extern void update_process_times(int user);
extern void scheduler_tick(void);
-extern unsigned long cache_decay_ticks;
/* Attach to any functions which should be ignored in wchan output. */
#define __sched __attribute__((__section__(".sched.text")))
@@ -203,6 +204,12 @@ arch_get_unmapped_area_topdown(struct file *filp, unsigned long addr,
extern void arch_unmap_area(struct vm_area_struct *area);
extern void arch_unmap_area_topdown(struct vm_area_struct *area);
+#define set_mm_counter(mm, member, value) (mm)->_##member = (value)
+#define get_mm_counter(mm, member) ((mm)->_##member)
+#define add_mm_counter(mm, member, value) (mm)->_##member += (value)
+#define inc_mm_counter(mm, member) (mm)->_##member++
+#define dec_mm_counter(mm, member) (mm)->_##member--
+typedef unsigned long mm_counter_t;
struct mm_struct {
struct vm_area_struct * mmap; /* list of VMAs */
@@ -219,7 +226,7 @@ struct mm_struct {
atomic_t mm_count; /* How many references to "struct mm_struct" (users count as 1) */
int map_count; /* number of VMAs */
struct rw_semaphore mmap_sem;
- spinlock_t page_table_lock; /* Protects page tables, mm->rss, mm->anon_rss */
+ spinlock_t page_table_lock; /* Protects page tables and some counters */
struct list_head mmlist; /* List of maybe swapped mm's. These are globally strung
* together off init_mm.mmlist, and are protected
@@ -229,9 +236,13 @@ struct mm_struct {
unsigned long start_code, end_code, start_data, end_data;
unsigned long start_brk, brk, start_stack;
unsigned long arg_start, arg_end, env_start, env_end;
- unsigned long rss, anon_rss, total_vm, locked_vm, shared_vm;
+ unsigned long total_vm, locked_vm, shared_vm;
unsigned long exec_vm, stack_vm, reserved_vm, def_flags, nr_ptes;
+ /* Special counters protected by the page_table_lock */
+ mm_counter_t _rss;
+ mm_counter_t _anon_rss;
+
unsigned long saved_auxv[42]; /* for /proc/PID/auxv */
unsigned dumpable:1;
@@ -300,6 +311,14 @@ struct signal_struct {
/* POSIX.1b Interval Timers */
struct list_head posix_timers;
+ /* ITIMER_REAL timer for the process */
+ struct timer_list real_timer;
+ unsigned long it_real_value, it_real_incr;
+
+ /* ITIMER_PROF and ITIMER_VIRTUAL timers for the process */
+ cputime_t it_prof_expires, it_virt_expires;
+ cputime_t it_prof_incr, it_virt_incr;
+
/* job control IDs */
pid_t pgrp;
pid_t tty_old_pgrp;
@@ -320,6 +339,14 @@ struct signal_struct {
unsigned long min_flt, maj_flt, cmin_flt, cmaj_flt;
/*
+ * Cumulative ns of scheduled CPU time for dead threads in the
+ * group, not including a zombie group leader. (This only differs
+ * from jiffies_to_ns(utime + stime) if sched_clock uses something
+ * other than jiffies.)
+ */
+ unsigned long long sched_time;
+
+ /*
* We don't bother to synchronize most readers of this at all,
* because there is no reader checking a limit that actually needs
* to get both rlim_cur and rlim_max atomically, and either one
@@ -329,6 +356,15 @@ struct signal_struct {
* have no need to disable irqs.
*/
struct rlimit rlim[RLIM_NLIMITS];
+
+ struct list_head cpu_timers[3];
+
+ /* keep the process-shared keyrings here so that they do the right
+ * thing in threads created with CLONE_THREAD */
+#ifdef CONFIG_KEYS
+ struct key *session_keyring; /* keyring inherited over fork */
+ struct key *process_keyring; /* keyring private to this process */
+#endif
};
/*
@@ -462,17 +498,26 @@ struct sched_domain {
/* load_balance() stats */
unsigned long lb_cnt[MAX_IDLE_TYPES];
unsigned long lb_failed[MAX_IDLE_TYPES];
+ unsigned long lb_balanced[MAX_IDLE_TYPES];
unsigned long lb_imbalance[MAX_IDLE_TYPES];
+ unsigned long lb_gained[MAX_IDLE_TYPES];
+ unsigned long lb_hot_gained[MAX_IDLE_TYPES];
unsigned long lb_nobusyg[MAX_IDLE_TYPES];
unsigned long lb_nobusyq[MAX_IDLE_TYPES];
+ /* Active load balancing */
+ unsigned long alb_cnt;
+ unsigned long alb_failed;
+ unsigned long alb_pushed;
+
/* sched_balance_exec() stats */
unsigned long sbe_attempts;
unsigned long sbe_pushed;
/* try_to_wake_up() stats */
- unsigned long ttwu_wake_affine;
- unsigned long ttwu_wake_balance;
+ unsigned long ttwu_wake_remote;
+ unsigned long ttwu_move_affine;
+ unsigned long ttwu_move_balance;
#endif
};
@@ -488,6 +533,7 @@ extern void cpu_attach_domain(struct sched_domain *sd, int cpu);
struct io_context; /* See blkdev.h */
void exit_io_context(void);
+struct cpuset;
#define NGROUPS_SMALL 32
#define NGROUPS_PER_BLOCK ((int)(PAGE_SIZE / sizeof(gid_t)))
@@ -540,6 +586,7 @@ struct task_struct {
unsigned long sleep_avg;
unsigned long long timestamp, last_ran;
+ unsigned long long sched_time; /* sched_clock time spent running */
int activated;
unsigned long policy;
@@ -593,15 +640,16 @@ struct task_struct {
int __user *clear_child_tid; /* CLONE_CHILD_CLEARTID */
unsigned long rt_priority;
- unsigned long it_real_value, it_real_incr;
- cputime_t it_virt_value, it_virt_incr;
- cputime_t it_prof_value, it_prof_incr;
- struct timer_list real_timer;
cputime_t utime, stime;
unsigned long nvcsw, nivcsw; /* context switch counts */
struct timespec start_time;
/* mm fault and swap info: this can arguably be seen as either mm-specific or thread-specific */
unsigned long min_flt, maj_flt;
+
+ cputime_t it_prof_expires, it_virt_expires;
+ unsigned long long it_sched_expires;
+ struct list_head cpu_timers[3];
+
/* process credentials */
uid_t uid,euid,suid,fsuid;
gid_t gid,egid,sgid,fsgid;
@@ -610,8 +658,6 @@ struct task_struct {
unsigned keep_capabilities:1;
struct user_struct *user;
#ifdef CONFIG_KEYS
- struct key *session_keyring; /* keyring inherited over fork */
- struct key *process_keyring; /* keyring private to this process (CLONE_THREAD) */
struct key *thread_keyring; /* keyring private to this thread */
#endif
int oomkilladj; /* OOM kill score adjustment (bit shift). */
@@ -643,6 +689,7 @@ struct task_struct {
void *security;
struct audit_context *audit_context;
+ seccomp_t seccomp;
/* Thread group tracking */
u32 parent_exec_id;
@@ -685,6 +732,11 @@ struct task_struct {
struct mempolicy *mempolicy;
short il_next;
#endif
+#ifdef CONFIG_CPUSETS
+ struct cpuset *cpuset;
+ nodemask_t mems_allowed;
+ int cpuset_mems_generation;
+#endif
};
static inline pid_t process_group(struct task_struct *tsk)
@@ -735,6 +787,7 @@ do { if (atomic_dec_and_test(&(tsk)->usage)) __put_task_struct(tsk); } while(0)
#define PF_LESS_THROTTLE 0x00100000 /* Throttle me less: I clean memory */
#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 */
/*
* Only the _current_ task can read/write to tsk->flags, but other
@@ -773,6 +826,7 @@ static inline int set_cpus_allowed(task_t *p, cpumask_t new_mask)
#endif
extern unsigned long long sched_clock(void);
+extern unsigned long long current_sched_time(const task_t *current_task);
/* sched_exec is called by processes performing an exec */
#ifdef CONFIG_SMP
diff --git a/include/linux/scx200.h b/include/linux/scx200.h
index af7d53acad995..a22f9e173ad2d 100644
--- a/include/linux/scx200.h
+++ b/include/linux/scx200.h
@@ -7,6 +7,10 @@
/* Interesting stuff for the National Semiconductor SCx200 CPU */
+extern unsigned scx200_cb_base;
+
+#define scx200_cb_present() (scx200_cb_base!=0)
+
/* F0 PCI Header/Bridge Configuration Registers */
#define SCx200_DOCCS_BASE 0x78 /* DOCCS Base Address Register */
#define SCx200_DOCCS_CTRL 0x7c /* DOCCS Control Register */
@@ -15,7 +19,7 @@
#define SCx200_GPIO_SIZE 0x2c /* Size of GPIO register block */
/* General Configuration Block */
-#define SCx200_CB_BASE 0x9000 /* Base fixed at 0x9000 according to errata */
+#define SCx200_CB_BASE_FIXED 0x9000 /* Base fixed at 0x9000 according to errata? */
/* Watchdog Timer */
#define SCx200_WDT_OFFSET 0x00 /* offset within configuration block */
@@ -44,9 +48,7 @@
#define SCx200_IID 0x3c /* IA On a Chip Identification Number Reg */
#define SCx200_REV 0x3d /* Revision Register */
#define SCx200_CBA 0x3e /* Configuration Base Address Register */
-
-/* Verify that the configuration block really is there */
-#define scx200_cb_probe(base) (inw((base) + SCx200_CBA) == (base))
+#define SCx200_CBA_SCRATCH 0x64 /* Configuration Base Address Scratchpad */
/*
Local variables:
diff --git a/include/linux/scx200_gpio.h b/include/linux/scx200_gpio.h
index 2c6d739706b6c..30cdd648ba793 100644
--- a/include/linux/scx200_gpio.h
+++ b/include/linux/scx200_gpio.h
@@ -1,10 +1,8 @@
#include <linux/spinlock.h>
u32 scx200_gpio_configure(int index, u32 set, u32 clear);
-void scx200_gpio_dump(unsigned index);
extern unsigned scx200_gpio_base;
-extern spinlock_t scx200_gpio_lock;
extern long scx200_gpio_shadow[2];
#define scx200_gpio_present() (scx200_gpio_base!=0)
diff --git a/include/linux/seccomp.h b/include/linux/seccomp.h
new file mode 100644
index 0000000000000..3a2702bbb1d67
--- /dev/null
+++ b/include/linux/seccomp.h
@@ -0,0 +1,34 @@
+#ifndef _LINUX_SECCOMP_H
+#define _LINUX_SECCOMP_H
+
+#include <linux/config.h>
+
+#ifdef CONFIG_SECCOMP
+
+#define NR_SECCOMP_MODES 1
+
+#include <linux/thread_info.h>
+#include <asm/seccomp.h>
+
+typedef struct { int mode; } seccomp_t;
+
+extern void __secure_computing(int);
+static inline void secure_computing(int this_syscall)
+{
+ if (unlikely(test_thread_flag(TIF_SECCOMP)))
+ __secure_computing(this_syscall);
+}
+
+#else /* CONFIG_SECCOMP */
+
+#if (__GNUC__ > 2)
+ typedef struct { } seccomp_t;
+#else
+ typedef struct { int gcc_is_buggy; } seccomp_t;
+#endif
+
+#define secure_computing(x) do { } while (0)
+
+#endif /* CONFIG_SECCOMP */
+
+#endif /* _LINUX_SECCOMP_H */
diff --git a/include/linux/security.h b/include/linux/security.h
index 2b048ec62e9c1..b42095a68b1c4 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -458,13 +458,15 @@ struct swap_info_struct;
* Check permissions for a mmap operation. The @file may be NULL, e.g.
* if mapping anonymous memory.
* @file contains the file structure for file to map (may be NULL).
- * @prot contains the requested permissions.
+ * @reqprot contains the protection requested by the application.
+ * @prot contains the protection that will be applied by the kernel.
* @flags contains the operational flags.
* Return 0 if permission is granted.
* @file_mprotect:
* Check permissions before changing memory access permissions.
* @vma contains the memory region to modify.
- * @prot contains the requested permissions.
+ * @reqprot contains the protection requested by the application.
+ * @prot contains the protection that will be applied by the kernel.
* Return 0 if permission is granted.
* @file_lock:
* Check permission before performing file locking operations.
@@ -1129,8 +1131,11 @@ struct security_operations {
int (*file_ioctl) (struct file * file, unsigned int cmd,
unsigned long arg);
int (*file_mmap) (struct file * file,
+ unsigned long reqprot,
unsigned long prot, unsigned long flags);
- int (*file_mprotect) (struct vm_area_struct * vma, unsigned long prot);
+ int (*file_mprotect) (struct vm_area_struct * vma,
+ unsigned long reqprot,
+ unsigned long prot);
int (*file_lock) (struct file * file, unsigned int cmd);
int (*file_fcntl) (struct file * file, unsigned int cmd,
unsigned long arg);
@@ -1426,11 +1431,15 @@ static inline void security_sb_post_pivotroot (struct nameidata *old_nd,
static inline int security_inode_alloc (struct inode *inode)
{
+ if (unlikely (IS_PRIVATE (inode)))
+ return 0;
return security_ops->inode_alloc_security (inode);
}
static inline void security_inode_free (struct inode *inode)
{
+ if (unlikely (IS_PRIVATE (inode)))
+ return;
security_ops->inode_free_security (inode);
}
@@ -1438,6 +1447,8 @@ static inline int security_inode_create (struct inode *dir,
struct dentry *dentry,
int mode)
{
+ if (unlikely (IS_PRIVATE (dir)))
+ return 0;
return security_ops->inode_create (dir, dentry, mode);
}
@@ -1445,6 +1456,8 @@ static inline void security_inode_post_create (struct inode *dir,
struct dentry *dentry,
int mode)
{
+ if (dentry->d_inode && unlikely (IS_PRIVATE (dentry->d_inode)))
+ return;
security_ops->inode_post_create (dir, dentry, mode);
}
@@ -1452,6 +1465,8 @@ static inline int security_inode_link (struct dentry *old_dentry,
struct inode *dir,
struct dentry *new_dentry)
{
+ if (unlikely (IS_PRIVATE (old_dentry->d_inode)))
+ return 0;
return security_ops->inode_link (old_dentry, dir, new_dentry);
}
@@ -1459,12 +1474,16 @@ static inline void security_inode_post_link (struct dentry *old_dentry,
struct inode *dir,
struct dentry *new_dentry)
{
+ if (new_dentry->d_inode && unlikely (IS_PRIVATE (new_dentry->d_inode)))
+ return;
security_ops->inode_post_link (old_dentry, dir, new_dentry);
}
static inline int security_inode_unlink (struct inode *dir,
struct dentry *dentry)
{
+ if (unlikely (IS_PRIVATE (dentry->d_inode)))
+ return 0;
return security_ops->inode_unlink (dir, dentry);
}
@@ -1472,6 +1491,8 @@ static inline int security_inode_symlink (struct inode *dir,
struct dentry *dentry,
const char *old_name)
{
+ if (unlikely (IS_PRIVATE (dir)))
+ return 0;
return security_ops->inode_symlink (dir, dentry, old_name);
}
@@ -1479,6 +1500,8 @@ static inline void security_inode_post_symlink (struct inode *dir,
struct dentry *dentry,
const char *old_name)
{
+ if (dentry->d_inode && unlikely (IS_PRIVATE (dentry->d_inode)))
+ return;
security_ops->inode_post_symlink (dir, dentry, old_name);
}
@@ -1486,6 +1509,8 @@ static inline int security_inode_mkdir (struct inode *dir,
struct dentry *dentry,
int mode)
{
+ if (unlikely (IS_PRIVATE (dir)))
+ return 0;
return security_ops->inode_mkdir (dir, dentry, mode);
}
@@ -1493,12 +1518,16 @@ static inline void security_inode_post_mkdir (struct inode *dir,
struct dentry *dentry,
int mode)
{
+ if (dentry->d_inode && unlikely (IS_PRIVATE (dentry->d_inode)))
+ return;
security_ops->inode_post_mkdir (dir, dentry, mode);
}
static inline int security_inode_rmdir (struct inode *dir,
struct dentry *dentry)
{
+ if (unlikely (IS_PRIVATE (dentry->d_inode)))
+ return 0;
return security_ops->inode_rmdir (dir, dentry);
}
@@ -1506,6 +1535,8 @@ static inline int security_inode_mknod (struct inode *dir,
struct dentry *dentry,
int mode, dev_t dev)
{
+ if (unlikely (IS_PRIVATE (dir)))
+ return 0;
return security_ops->inode_mknod (dir, dentry, mode, dev);
}
@@ -1513,6 +1544,8 @@ static inline void security_inode_post_mknod (struct inode *dir,
struct dentry *dentry,
int mode, dev_t dev)
{
+ if (dentry->d_inode && unlikely (IS_PRIVATE (dentry->d_inode)))
+ return;
security_ops->inode_post_mknod (dir, dentry, mode, dev);
}
@@ -1521,6 +1554,9 @@ static inline int security_inode_rename (struct inode *old_dir,
struct inode *new_dir,
struct dentry *new_dentry)
{
+ if (unlikely (IS_PRIVATE (old_dentry->d_inode) ||
+ (new_dentry->d_inode && IS_PRIVATE (new_dentry->d_inode))))
+ return 0;
return security_ops->inode_rename (old_dir, old_dentry,
new_dir, new_dentry);
}
@@ -1530,83 +1566,114 @@ static inline void security_inode_post_rename (struct inode *old_dir,
struct inode *new_dir,
struct dentry *new_dentry)
{
+ if (unlikely (IS_PRIVATE (old_dentry->d_inode) ||
+ (new_dentry->d_inode && IS_PRIVATE (new_dentry->d_inode))))
+ return;
security_ops->inode_post_rename (old_dir, old_dentry,
new_dir, new_dentry);
}
static inline int security_inode_readlink (struct dentry *dentry)
{
+ if (unlikely (IS_PRIVATE (dentry->d_inode)))
+ return 0;
return security_ops->inode_readlink (dentry);
}
static inline int security_inode_follow_link (struct dentry *dentry,
struct nameidata *nd)
{
+ if (unlikely (IS_PRIVATE (dentry->d_inode)))
+ return 0;
return security_ops->inode_follow_link (dentry, nd);
}
static inline int security_inode_permission (struct inode *inode, int mask,
struct nameidata *nd)
{
+ if (unlikely (IS_PRIVATE (inode)))
+ return 0;
return security_ops->inode_permission (inode, mask, nd);
}
static inline int security_inode_setattr (struct dentry *dentry,
struct iattr *attr)
{
+ if (unlikely (IS_PRIVATE (dentry->d_inode)))
+ return 0;
return security_ops->inode_setattr (dentry, attr);
}
static inline int security_inode_getattr (struct vfsmount *mnt,
struct dentry *dentry)
{
+ if (unlikely (IS_PRIVATE (dentry->d_inode)))
+ return 0;
return security_ops->inode_getattr (mnt, dentry);
}
static inline void security_inode_delete (struct inode *inode)
{
+ if (unlikely (IS_PRIVATE (inode)))
+ return;
security_ops->inode_delete (inode);
}
static inline int security_inode_setxattr (struct dentry *dentry, char *name,
void *value, size_t size, int flags)
{
+ if (unlikely (IS_PRIVATE (dentry->d_inode)))
+ return 0;
return security_ops->inode_setxattr (dentry, name, value, size, flags);
}
static inline void security_inode_post_setxattr (struct dentry *dentry, char *name,
void *value, size_t size, int flags)
{
+ if (unlikely (IS_PRIVATE (dentry->d_inode)))
+ return;
security_ops->inode_post_setxattr (dentry, name, value, size, flags);
}
static inline int security_inode_getxattr (struct dentry *dentry, char *name)
{
+ if (unlikely (IS_PRIVATE (dentry->d_inode)))
+ return 0;
return security_ops->inode_getxattr (dentry, name);
}
static inline int security_inode_listxattr (struct dentry *dentry)
{
+ if (unlikely (IS_PRIVATE (dentry->d_inode)))
+ return 0;
return security_ops->inode_listxattr (dentry);
}
static inline int security_inode_removexattr (struct dentry *dentry, char *name)
{
+ if (unlikely (IS_PRIVATE (dentry->d_inode)))
+ return 0;
return security_ops->inode_removexattr (dentry, name);
}
static inline int security_inode_getsecurity(struct inode *inode, const char *name, void *buffer, size_t size)
{
+ if (unlikely (IS_PRIVATE (inode)))
+ return 0;
return security_ops->inode_getsecurity(inode, name, buffer, size);
}
static inline int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags)
{
+ if (unlikely (IS_PRIVATE (inode)))
+ return 0;
return security_ops->inode_setsecurity(inode, name, value, size, flags);
}
static inline int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size)
{
+ if (unlikely (IS_PRIVATE (inode)))
+ return 0;
return security_ops->inode_listsecurity(inode, buffer, buffer_size);
}
@@ -1631,16 +1698,18 @@ static inline int security_file_ioctl (struct file *file, unsigned int cmd,
return security_ops->file_ioctl (file, cmd, arg);
}
-static inline int security_file_mmap (struct file *file, unsigned long prot,
+static inline int security_file_mmap (struct file *file, unsigned long reqprot,
+ unsigned long prot,
unsigned long flags)
{
- return security_ops->file_mmap (file, prot, flags);
+ return security_ops->file_mmap (file, reqprot, prot, flags);
}
static inline int security_file_mprotect (struct vm_area_struct *vma,
+ unsigned long reqprot,
unsigned long prot)
{
- return security_ops->file_mprotect (vma, prot);
+ return security_ops->file_mprotect (vma, reqprot, prot);
}
static inline int security_file_lock (struct file *file, unsigned int cmd)
@@ -1883,6 +1952,8 @@ static inline int security_sem_semop (struct sem_array * sma,
static inline void security_d_instantiate (struct dentry *dentry, struct inode *inode)
{
+ if (unlikely (inode && IS_PRIVATE (inode)))
+ return;
security_ops->d_instantiate (dentry, inode);
}
@@ -2278,13 +2349,15 @@ static inline int security_file_ioctl (struct file *file, unsigned int cmd,
return 0;
}
-static inline int security_file_mmap (struct file *file, unsigned long prot,
+static inline int security_file_mmap (struct file *file, unsigned long reqprot,
+ unsigned long prot,
unsigned long flags)
{
return 0;
}
static inline int security_file_mprotect (struct vm_area_struct *vma,
+ unsigned long reqprot,
unsigned long prot)
{
return 0;
diff --git a/include/linux/seq_file.h b/include/linux/seq_file.h
index 28141af6a19a5..850a974ee505e 100644
--- a/include/linux/seq_file.h
+++ b/include/linux/seq_file.h
@@ -18,6 +18,7 @@ struct seq_file {
size_t from;
size_t count;
loff_t index;
+ loff_t version;
struct semaphore sem;
struct seq_operations *op;
void *private;
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index c45598d0a8464..c3fb5984f250a 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -106,6 +106,19 @@
/* TXX9 type number */
#define PORT_TXX9 64
+/* NEC VR4100 series SIU/DSIU */
+#define PORT_VR41XX_SIU 65
+#define PORT_VR41XX_DSIU 66
+
+/* Samsung S3C2400 SoC */
+#define PORT_S3C2400 67
+
+/* M32R SIO */
+#define PORT_M32R_SIO 68
+
+/*Digi jsm */
+#define PORT_JSM 65
+
#ifdef __KERNEL__
#include <linux/config.h>
@@ -350,6 +363,7 @@ void uart_unregister_port(struct uart_driver *reg, int line);
int uart_register_port(struct uart_driver *reg, struct uart_port *port);
int uart_add_one_port(struct uart_driver *reg, struct uart_port *port);
int uart_remove_one_port(struct uart_driver *reg, struct uart_port *port);
+int uart_match_port(struct uart_port *port1, struct uart_port *port2);
/*
* Power Management
diff --git a/include/linux/serio.h b/include/linux/serio.h
index fc387e4d8e66c..a2d3b9ae06f49 100644
--- a/include/linux/serio.h
+++ b/include/linux/serio.h
@@ -10,18 +10,18 @@
*/
#include <linux/ioctl.h>
-#include <linux/interrupt.h>
#define SPIOCSTYPE _IOW('q', 0x01, unsigned long)
#ifdef __KERNEL__
+#include <linux/interrupt.h>
#include <linux/list.h>
#include <linux/spinlock.h>
#include <linux/device.h>
+#include <linux/mod_devicetable.h>
struct serio {
- void *private;
void *port_data;
char name[32];
@@ -29,19 +29,15 @@ struct serio {
unsigned int manual_bind;
- unsigned short idbus;
- unsigned short idvendor;
- unsigned short idproduct;
- unsigned short idversion;
-
- unsigned long type;
- unsigned long event;
+ struct serio_device_id id;
spinlock_t lock; /* protects critical sections from port's interrupt handler */
int (*write)(struct serio *, unsigned char);
int (*open)(struct serio *);
void (*close)(struct serio *);
+ int (*start)(struct serio *);
+ void (*stop)(struct serio *);
struct serio *parent, *child;
@@ -49,6 +45,7 @@ struct serio {
struct semaphore drv_sem; /* protects serio->drv so attributes can pin driver */
struct device dev;
+ unsigned int registered; /* port has been fully registered with driver core */
struct list_head node;
};
@@ -58,19 +55,18 @@ struct serio_driver {
void *private;
char *description;
+ struct serio_device_id *id_table;
unsigned int manual_bind;
void (*write_wakeup)(struct serio *);
irqreturn_t (*interrupt)(struct serio *, unsigned char,
unsigned int, struct pt_regs *);
- void (*connect)(struct serio *, struct serio_driver *drv);
+ int (*connect)(struct serio *, struct serio_driver *drv);
int (*reconnect)(struct serio *);
void (*disconnect)(struct serio *);
void (*cleanup)(struct serio *);
struct device_driver driver;
-
- struct list_head node;
};
#define to_serio_driver(d) container_of(d, struct serio_driver, driver)
@@ -80,15 +76,28 @@ void serio_rescan(struct serio *serio);
void serio_reconnect(struct serio *serio);
irqreturn_t serio_interrupt(struct serio *serio, unsigned char data, unsigned int flags, struct pt_regs *regs);
-void serio_register_port(struct serio *serio);
-void serio_register_port_delayed(struct serio *serio);
+void __serio_register_port(struct serio *serio, struct module *owner);
+static inline void serio_register_port(struct serio *serio)
+{
+ __serio_register_port(serio, THIS_MODULE);
+}
+
void serio_unregister_port(struct serio *serio);
-void serio_unregister_port_delayed(struct serio *serio);
+void __serio_unregister_port_delayed(struct serio *serio, struct module *owner);
+static inline void serio_unregister_port_delayed(struct serio *serio)
+{
+ __serio_unregister_port_delayed(serio, THIS_MODULE);
+}
+
+void __serio_register_driver(struct serio_driver *drv, struct module *owner);
+static inline void serio_register_driver(struct serio_driver *drv)
+{
+ __serio_register_driver(drv, THIS_MODULE);
+}
-void serio_register_driver(struct serio_driver *drv);
void serio_unregister_driver(struct serio_driver *drv);
-static __inline__ int serio_write(struct serio *serio, unsigned char data)
+static inline int serio_write(struct serio *serio, unsigned char data)
{
if (serio->write)
return serio->write(serio, data);
@@ -96,29 +105,42 @@ static __inline__ int serio_write(struct serio *serio, unsigned char data)
return -1;
}
-static __inline__ void serio_drv_write_wakeup(struct serio *serio)
+static inline void serio_drv_write_wakeup(struct serio *serio)
{
if (serio->drv && serio->drv->write_wakeup)
serio->drv->write_wakeup(serio);
}
-static __inline__ void serio_cleanup(struct serio *serio)
+static inline void serio_cleanup(struct serio *serio)
{
if (serio->drv && serio->drv->cleanup)
serio->drv->cleanup(serio);
}
+/*
+ * Use the following fucntions to manipulate serio's per-port
+ * driver-specific data.
+ */
+static inline void *serio_get_drvdata(struct serio *serio)
+{
+ return dev_get_drvdata(&serio->dev);
+}
+
+static inline void serio_set_drvdata(struct serio *serio, void *data)
+{
+ dev_set_drvdata(&serio->dev, data);
+}
/*
* Use the following fucntions to protect critical sections in
* driver code from port's interrupt handler
*/
-static __inline__ void serio_pause_rx(struct serio *serio)
+static inline void serio_pause_rx(struct serio *serio)
{
spin_lock_irq(&serio->lock);
}
-static __inline__ void serio_continue_rx(struct serio *serio)
+static inline void serio_continue_rx(struct serio *serio)
{
spin_unlock_irq(&serio->lock);
}
@@ -126,12 +148,12 @@ static __inline__ void serio_continue_rx(struct serio *serio)
/*
* Use the following fucntions to pin serio's driver in process context
*/
-static __inline__ int serio_pin_driver(struct serio *serio)
+static inline int serio_pin_driver(struct serio *serio)
{
return down_interruptible(&serio->drv_sem);
}
-static __inline__ void serio_unpin_driver(struct serio *serio)
+static inline void serio_unpin_driver(struct serio *serio)
{
up(&serio->drv_sem);
}
@@ -146,15 +168,20 @@ static __inline__ void serio_unpin_driver(struct serio *serio)
#define SERIO_PARITY 2
#define SERIO_FRAME 4
-#define SERIO_TYPE 0xff000000UL
-#define SERIO_XT 0x00000000UL
-#define SERIO_8042 0x01000000UL
-#define SERIO_RS232 0x02000000UL
-#define SERIO_HIL_MLC 0x03000000UL
-#define SERIO_PS_PSTHRU 0x05000000UL
-#define SERIO_8042_XL 0x06000000UL
+/*
+ * Serio types
+ */
+#define SERIO_XT 0x00
+#define SERIO_8042 0x01
+#define SERIO_RS232 0x02
+#define SERIO_HIL_MLC 0x03
+#define SERIO_PS_PSTHRU 0x05
+#define SERIO_8042_XL 0x06
-#define SERIO_PROTO 0xFFUL
+/*
+ * Serio types
+ */
+#define SERIO_UNKNOWN 0x00
#define SERIO_MSC 0x01
#define SERIO_SUN 0x02
#define SERIO_MS 0x03
@@ -181,8 +208,7 @@ static __inline__ void serio_unpin_driver(struct serio *serio)
#define SERIO_SNES232 0x26
#define SERIO_SEMTECH 0x27
#define SERIO_LKKBD 0x28
-
-#define SERIO_ID 0xff00UL
-#define SERIO_EXTRA 0xff0000UL
+#define SERIO_ELO 0x29
+#define SERIO_MICROTOUCH 0x30
#endif
diff --git a/include/linux/signal.h b/include/linux/signal.h
index e5f3d83ab215e..99c97ad026c83 100644
--- a/include/linux/signal.h
+++ b/include/linux/signal.h
@@ -8,8 +8,6 @@
#ifdef __KERNEL__
-#define MAX_SIGPENDING 1024
-
/*
* Real Time signals may be queued.
*/
@@ -212,6 +210,7 @@ static inline void init_sigpending(struct sigpending *sig)
}
extern int group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p);
+extern int __group_send_sig_info(int, struct siginfo *, struct task_struct *);
extern long do_sigpending(void __user *, unsigned long);
extern int sigprocmask(int, sigset_t *, sigset_t *);
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 23e0b48b79a49..aa35797ebfbf7 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -146,6 +146,20 @@ struct skb_shared_info {
skb_frag_t frags[MAX_SKB_FRAGS];
};
+/* We divide dataref into two halves. The higher 16 bits hold references
+ * to the payload part of skb->data. The lower 16 bits hold references to
+ * the entire skb->data. It is up to the users of the skb to agree on
+ * where the payload starts.
+ *
+ * All users must obey the rule that the skb->data reference count must be
+ * greater than or equal to the payload reference count.
+ *
+ * Holding a reference to the payload part means that the user does not
+ * care about modifications to the header part of skb->data.
+ */
+#define SKB_DATAREF_SHIFT 16
+#define SKB_DATAREF_MASK ((1 << SKB_DATAREF_SHIFT) - 1)
+
/**
* struct sk_buff - socket buffer
* @next: Next buffer in list
@@ -167,6 +181,7 @@ struct skb_shared_info {
* @csum: Checksum
* @__unused: Dead field, may be reused
* @cloned: Head may be cloned (check refcnt to be sure)
+ * @nohdr: Payload reference only, must not modify header
* @pkt_type: Packet class
* @ip_summed: Driver fed us an IP checksum
* @priority: Packet queueing priority
@@ -187,6 +202,8 @@ struct skb_shared_info {
* @nf_bridge: Saved data about a bridged frame - see br_netfilter.c
* @private: Data which is private to the HIPPI implementation
* @tc_index: Traffic control index
+ * @tc_verd: traffic control verdict
+ * @tc_classid: traffic control classid
*/
struct sk_buff {
@@ -238,7 +255,8 @@ struct sk_buff {
mac_len,
csum;
unsigned char local_df,
- cloned,
+ cloned:1,
+ nohdr:1,
pkt_type,
ip_summed;
__u32 priority;
@@ -370,7 +388,42 @@ static inline void kfree_skb(struct sk_buff *skb)
*/
static inline int skb_cloned(const struct sk_buff *skb)
{
- return skb->cloned && atomic_read(&skb_shinfo(skb)->dataref) != 1;
+ return skb->cloned &&
+ (atomic_read(&skb_shinfo(skb)->dataref) & SKB_DATAREF_MASK) != 1;
+}
+
+/**
+ * skb_header_cloned - is the header a clone
+ * @skb: buffer to check
+ *
+ * Returns true if modifying the header part of the buffer requires
+ * the data to be copied.
+ */
+static inline int skb_header_cloned(const struct sk_buff *skb)
+{
+ int dataref;
+
+ if (!skb->cloned)
+ return 0;
+
+ dataref = atomic_read(&skb_shinfo(skb)->dataref);
+ dataref = (dataref & SKB_DATAREF_MASK) - (dataref >> SKB_DATAREF_SHIFT);
+ return dataref != 1;
+}
+
+/**
+ * skb_header_release - release reference to header
+ * @skb: buffer to operate on
+ *
+ * Drop a reference to the header part of the buffer. This is done
+ * by acquiring a payload reference. You must not read from the header
+ * part of skb->data after this.
+ */
+static inline void skb_header_release(struct sk_buff *skb)
+{
+ BUG_ON(skb->nohdr);
+ skb->nohdr = 1;
+ atomic_add(1 << SKB_DATAREF_SHIFT, &skb_shinfo(skb)->dataref);
}
/**
@@ -1054,6 +1107,42 @@ static inline int skb_linearize(struct sk_buff *skb, int gfp)
return __skb_linearize(skb, gfp);
}
+/**
+ * skb_postpull_rcsum - update checksum for received skb after pull
+ * @skb: buffer to update
+ * @start: start of data before pull
+ * @len: length of data pulled
+ *
+ * After doing a pull on a received packet, you need to call this to
+ * update the CHECKSUM_HW checksum, or set ip_summed to CHECKSUM_NONE
+ * so that it can be recomputed from scratch.
+ */
+
+static inline void skb_postpull_rcsum(struct sk_buff *skb,
+ const void *start, int len)
+{
+ if (skb->ip_summed == CHECKSUM_HW)
+ skb->csum = csum_sub(skb->csum, csum_partial(start, len, 0));
+}
+
+/**
+ * pskb_trim_rcsum - trim received skb and update checksum
+ * @skb: buffer to trim
+ * @len: new length
+ *
+ * This is exactly the same as pskb_trim except that it ensures the
+ * checksum of received packets are still valid after the operation.
+ */
+
+static inline int pskb_trim_rcsum(struct sk_buff *skb, unsigned int len)
+{
+ if (len >= skb->len)
+ return 0;
+ if (skb->ip_summed == CHECKSUM_HW)
+ skb->ip_summed = CHECKSUM_NONE;
+ return __pskb_trim(skb, len);
+}
+
static inline void *kmap_skb_frag(const skb_frag_t *frag)
{
#ifdef CONFIG_HIGHMEM
@@ -1118,22 +1207,6 @@ static inline void *skb_header_pointer(const struct sk_buff *skb, int offset,
extern void skb_init(void);
extern void skb_add_mtu(int mtu);
-struct skb_iter {
- /* Iteration functions set these */
- unsigned char *data;
- unsigned int len;
-
- /* Private to iteration */
- unsigned int nextfrag;
- struct sk_buff *fraglist;
-};
-
-/* Keep iterating until skb_iter_next returns false. */
-extern void skb_iter_first(const struct sk_buff *skb, struct skb_iter *i);
-extern int skb_iter_next(const struct sk_buff *skb, struct skb_iter *i);
-/* Call this if aborting loop before !skb_iter_next */
-extern void skb_iter_abort(const struct sk_buff *skb, struct skb_iter *i);
-
#ifdef CONFIG_NETFILTER
static inline void nf_conntrack_put(struct nf_conntrack *nfct)
{
diff --git a/include/linux/slab.h b/include/linux/slab.h
index 0c7ae4f678a2d..3e3c3ab8ff941 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -61,7 +61,7 @@ extern kmem_cache_t *kmem_cache_create(const char *, size_t, size_t, unsigned lo
void (*)(void *, kmem_cache_t *, unsigned long));
extern int kmem_cache_destroy(kmem_cache_t *);
extern int kmem_cache_shrink(kmem_cache_t *);
-extern void *kmem_cache_alloc(kmem_cache_t *, int);
+extern void *kmem_cache_alloc(kmem_cache_t *, unsigned int __nocast);
#ifdef CONFIG_NUMA
extern void *kmem_cache_alloc_node(kmem_cache_t *, int);
#else
@@ -80,9 +80,9 @@ struct cache_sizes {
kmem_cache_t *cs_dmacachep;
};
extern struct cache_sizes malloc_sizes[];
-extern void *__kmalloc(size_t, int);
+extern void *__kmalloc(size_t, unsigned int __nocast);
-static inline void *kmalloc(size_t size, int flags)
+static inline void *kmalloc(size_t size, unsigned int __nocast flags)
{
if (__builtin_constant_p(size)) {
int i = 0;
@@ -105,7 +105,7 @@ found:
return __kmalloc(size, flags);
}
-extern void *kcalloc(size_t, size_t, int);
+extern void *kcalloc(size_t, size_t, unsigned int __nocast);
extern void kfree(const void *);
extern unsigned int ksize(const void *);
@@ -114,7 +114,6 @@ extern int FASTCALL(kmem_ptr_validate(kmem_cache_t *cachep, void *ptr));
/* System wide caches */
extern kmem_cache_t *vm_area_cachep;
-extern kmem_cache_t *mm_cachep;
extern kmem_cache_t *names_cachep;
extern kmem_cache_t *files_cachep;
extern kmem_cache_t *filp_cachep;
diff --git a/include/linux/smp.h b/include/linux/smp.h
index c438ec9880e94..dcf1db3b35d33 100644
--- a/include/linux/smp.h
+++ b/include/linux/smp.h
@@ -71,11 +71,6 @@ static inline int on_each_cpu(void (*func) (void *info), void *info,
return ret;
}
-/*
- * True once the per process idle is forked
- */
-extern int smp_threads_ready;
-
#define MSG_ALL_BUT_SELF 0x8000 /* Assume <32768 CPU's */
#define MSG_ALL 0x8001
@@ -102,7 +97,6 @@ void smp_prepare_boot_cpu(void);
# define smp_processor_id() 0
#endif
#define hard_smp_processor_id() 0
-#define smp_threads_ready 1
#define smp_call_function(func,info,retry,wait) ({ 0; })
#define on_each_cpu(func,info,retry,wait) ({ func(info); 0; })
static inline void smp_send_reschedule(int cpu) { }
diff --git a/include/linux/sort.h b/include/linux/sort.h
new file mode 100644
index 0000000000000..d534da2b55750
--- /dev/null
+++ b/include/linux/sort.h
@@ -0,0 +1,10 @@
+#ifndef _LINUX_SORT_H
+#define _LINUX_SORT_H
+
+#include <linux/types.h>
+
+void sort(void *base, size_t num, size_t size,
+ int (*cmp)(const void *, const void *),
+ void (*swap)(void *, void *, int));
+
+#endif
diff --git a/include/linux/stallion.h b/include/linux/stallion.h
index af82bd688500c..e89b77b6505a8 100644
--- a/include/linux/stallion.h
+++ b/include/linux/stallion.h
@@ -126,7 +126,7 @@ typedef struct stlbrd {
int nrbnks;
int irq;
int irqtype;
- void (*isr)(struct stlbrd *brdp);
+ int (*isr)(struct stlbrd *brdp);
unsigned int ioaddr1;
unsigned int ioaddr2;
unsigned int iosize1;
diff --git a/include/linux/stop_machine.h b/include/linux/stop_machine.h
index 6f43cb53f21b7..151a803ed0edc 100644
--- a/include/linux/stop_machine.h
+++ b/include/linux/stop_machine.h
@@ -8,7 +8,7 @@
#include <linux/cpu.h>
#include <asm/system.h>
-#ifdef CONFIG_SMP
+#if defined(CONFIG_STOP_MACHINE) && defined(CONFIG_SMP)
/**
* stop_machine_run: freeze the machine on all CPUs and run this function
* @fn: the function to run
diff --git a/include/linux/sunrpc/auth.h b/include/linux/sunrpc/auth.h
index f6d27720962e5..04ebc24db3487 100644
--- a/include/linux/sunrpc/auth.h
+++ b/include/linux/sunrpc/auth.h
@@ -35,8 +35,7 @@ struct auth_cred {
* Client user credentials
*/
struct rpc_cred {
- struct list_head cr_hash; /* hash chain */
- struct rpc_auth * cr_auth;
+ struct hlist_node cr_hash; /* hash chain */
struct rpc_credops * cr_ops;
unsigned long cr_expire; /* when to gc */
atomic_t cr_count; /* ref count */
@@ -59,10 +58,13 @@ struct rpc_cred {
*/
#define RPC_CREDCACHE_NR 8
#define RPC_CREDCACHE_MASK (RPC_CREDCACHE_NR - 1)
+struct rpc_cred_cache {
+ struct hlist_head hashtable[RPC_CREDCACHE_NR];
+ unsigned long nextgc; /* next garbage collection */
+ unsigned long expire; /* cache expiry interval */
+};
+
struct rpc_auth {
- struct list_head au_credcache[RPC_CREDCACHE_NR];
- unsigned long au_expire; /* cache expiry interval */
- unsigned long au_nextgc; /* next garbage collection */
unsigned int au_cslack; /* call cred size estimate */
unsigned int au_rslack; /* reply verf size guess */
unsigned int au_flags; /* various flags */
@@ -73,6 +75,7 @@ struct rpc_auth {
* case) */
atomic_t au_count; /* Reference counter */
+ struct rpc_cred_cache * au_credcache;
/* per-flavor data */
};
#define RPC_AUTH_PROC_CREDS 0x0010 /* process creds (including
@@ -91,14 +94,16 @@ struct rpc_authops {
struct rpc_auth * (*create)(struct rpc_clnt *, rpc_authflavor_t);
void (*destroy)(struct rpc_auth *);
+ struct rpc_cred * (*lookup_cred)(struct rpc_auth *, struct auth_cred *, int);
struct rpc_cred * (*crcreate)(struct rpc_auth*, struct auth_cred *, int);
};
struct rpc_credops {
+ const char * cr_name; /* Name of the auth flavour */
void (*crdestroy)(struct rpc_cred *);
int (*crmatch)(struct auth_cred *, struct rpc_cred *, int);
- u32 * (*crmarshal)(struct rpc_task *, u32 *, int);
+ u32 * (*crmarshal)(struct rpc_task *, u32 *);
int (*crrefresh)(struct rpc_task *);
u32 * (*crvalidate)(struct rpc_task *, u32 *);
int (*crwrap_req)(struct rpc_task *, kxdrproc_t,
@@ -130,7 +135,7 @@ int rpcauth_unwrap_resp(struct rpc_task *task, kxdrproc_t decode, void *rqstp,
int rpcauth_refreshcred(struct rpc_task *);
void rpcauth_invalcred(struct rpc_task *);
int rpcauth_uptodatecred(struct rpc_task *);
-void rpcauth_init_credcache(struct rpc_auth *);
+int rpcauth_init_credcache(struct rpc_auth *, unsigned long);
void rpcauth_free_credcache(struct rpc_auth *);
static inline
diff --git a/include/linux/sunrpc/auth_gss.h b/include/linux/sunrpc/auth_gss.h
index 5bff5a1d45f72..03084dc4bb6a4 100644
--- a/include/linux/sunrpc/auth_gss.h
+++ b/include/linux/sunrpc/auth_gss.h
@@ -68,18 +68,21 @@ struct rpc_gss_init_res {
struct gss_cl_ctx {
atomic_t count;
- u32 gc_proc;
+ enum rpc_gss_proc gc_proc;
u32 gc_seq;
spinlock_t gc_seq_lock;
struct gss_ctx *gc_gss_ctx;
struct xdr_netobj gc_wire_ctx;
u32 gc_win;
+ unsigned long gc_expiry;
};
+struct gss_upcall_msg;
struct gss_cred {
struct rpc_cred gc_base;
- u32 gc_flavor;
+ enum rpc_gss_svc gc_service;
struct gss_cl_ctx *gc_ctx;
+ struct gss_upcall_msg *gc_upcall;
};
#define gc_uid gc_base.cr_uid
diff --git a/include/linux/sunrpc/cache.h b/include/linux/sunrpc/cache.h
index b902425d2be56..6864063d1b9f0 100644
--- a/include/linux/sunrpc/cache.h
+++ b/include/linux/sunrpc/cache.h
@@ -37,8 +37,7 @@
* Entries have a ref count and a 'hashed' flag which counts the existance
* in the hash table.
* We only expire entries when refcount is zero.
- * Existance in the cache is not measured in refcount but rather in
- * CACHE_HASHED flag.
+ * Existance in the cache is counted the refcount.
*/
/* Every cache item has a common header that is used
@@ -57,7 +56,6 @@ struct cache_head {
#define CACHE_VALID 0 /* Entry contains valid data */
#define CACHE_NEGATIVE 1 /* Negative entry - there is no match for the key */
#define CACHE_PENDING 2 /* An upcall has been sent but no reply received yet*/
-#define CACHE_HASHED 3 /* Entry is in a hash table */
#define CACHE_NEW_EXPIRY 120 /* keep new things pending confirmation for 120 seconds */
@@ -185,7 +183,6 @@ RTN *FNAME ARGS \
\
if (new) \
{INIT;} \
- cache_get(&tmp->MEMBER); \
if (set) { \
if (!INPLACE && test_bit(CACHE_VALID, &tmp->MEMBER.flags))\
{ /* need to swap in new */ \
@@ -194,8 +191,6 @@ RTN *FNAME ARGS \
new->MEMBER.next = tmp->MEMBER.next; \
*hp = &new->MEMBER; \
tmp->MEMBER.next = NULL; \
- set_bit(CACHE_HASHED, &new->MEMBER.flags); \
- clear_bit(CACHE_HASHED, &tmp->MEMBER.flags); \
t2 = tmp; tmp = new; new = t2; \
} \
if (test_bit(CACHE_NEGATIVE, &item->MEMBER.flags)) \
@@ -205,6 +200,7 @@ RTN *FNAME ARGS \
clear_bit(CACHE_NEGATIVE, &tmp->MEMBER.flags); \
} \
} \
+ cache_get(&tmp->MEMBER); \
if (set||new) write_unlock(&(DETAIL)->hash_lock); \
else read_unlock(&(DETAIL)->hash_lock); \
if (set) \
@@ -220,7 +216,7 @@ RTN *FNAME ARGS \
new->MEMBER.next = *head; \
*head = &new->MEMBER; \
(DETAIL)->entries ++; \
- set_bit(CACHE_HASHED, &new->MEMBER.flags); \
+ cache_get(&new->MEMBER); \
if (set) { \
tmp = new; \
if (test_bit(CACHE_NEGATIVE, &item->MEMBER.flags)) \
@@ -268,15 +264,10 @@ static inline struct cache_head *cache_get(struct cache_head *h)
static inline int cache_put(struct cache_head *h, struct cache_detail *cd)
{
- atomic_dec(&h->refcnt);
- if (!atomic_read(&h->refcnt) &&
+ if (atomic_read(&h->refcnt) <= 2 &&
h->expiry_time < cd->nextcheck)
cd->nextcheck = h->expiry_time;
- if (!test_bit(CACHE_HASHED, &h->flags) &&
- !atomic_read(&h->refcnt))
- return 1;
-
- return 0;
+ return atomic_dec_and_test(&h->refcnt);
}
extern void cache_init(struct cache_head *h);
diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
index 917ec29d789b9..2709caf4d1283 100644
--- a/include/linux/sunrpc/clnt.h
+++ b/include/linux/sunrpc/clnt.h
@@ -51,7 +51,6 @@ struct rpc_clnt {
cl_intr : 1,/* interruptible */
cl_chatty : 1,/* be verbose */
cl_autobind : 1,/* use getport() */
- cl_droppriv : 1,/* enable NFS suid hack */
cl_oneshot : 1,/* dispose after use */
cl_dead : 1;/* abandoned */
@@ -129,6 +128,7 @@ void rpc_restart_call(struct rpc_task *);
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 *);
static __inline__
int rpc_call(struct rpc_clnt *clnt, u32 proc, void *argp, void *resp, int flags)
diff --git a/include/linux/sunrpc/gss_api.h b/include/linux/sunrpc/gss_api.h
index 629957d710a0d..689262f630598 100644
--- a/include/linux/sunrpc/gss_api.h
+++ b/include/linux/sunrpc/gss_api.h
@@ -33,8 +33,9 @@ struct gss_ctx {
/* gss-api prototypes; note that these are somewhat simplified versions of
* the prototypes specified in RFC 2744. */
-u32 gss_import_sec_context(
- struct xdr_netobj *input_token,
+int gss_import_sec_context(
+ const void* input_token,
+ size_t bufsize,
struct gss_api_mech *mech,
struct gss_ctx **ctx_id);
u32 gss_get_mic(
@@ -50,8 +51,6 @@ u32 gss_verify_mic(
u32 gss_delete_sec_context(
struct gss_ctx **ctx_id);
-struct gss_api_mech * gss_mech_get_by_name(char *name);
-struct gss_api_mech * gss_mech_get_by_pseudoflavor(u32 pseudoflavor);
u32 gss_pseudoflavor_to_service(struct gss_api_mech *, u32 pseudoflavor);
char *gss_service_to_auth_domain_name(struct gss_api_mech *, u32 service);
@@ -80,8 +79,9 @@ struct gss_api_mech {
/* and must provide the following operations: */
struct gss_api_ops {
- u32 (*gss_import_sec_context)(
- struct xdr_netobj *input_token,
+ int (*gss_import_sec_context)(
+ const void *input_token,
+ size_t bufsize,
struct gss_ctx *ctx_id);
u32 (*gss_get_mic)(
struct gss_ctx *ctx_id,
@@ -105,7 +105,7 @@ void gss_mech_unregister(struct gss_api_mech *);
struct gss_api_mech * gss_mech_get_by_OID(struct xdr_netobj *);
/* Returns a reference to a mechanism, given a name like "krb5" etc. */
-struct gss_api_mech *gss_mech_get_by_name(char *);
+struct gss_api_mech *gss_mech_get_by_name(const char *);
/* Similar, but get by pseudoflavor. */
struct gss_api_mech *gss_mech_get_by_pseudoflavor(u32);
diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h
index 933eeb005f099..99d17ed7cebb4 100644
--- a/include/linux/sunrpc/sched.h
+++ b/include/linux/sunrpc/sched.h
@@ -53,9 +53,8 @@ struct rpc_task {
struct rpc_message tk_msg; /* RPC call info */
__u32 * tk_buffer; /* XDR buffer */
size_t tk_bufsize;
- __u8 tk_garb_retry,
- tk_cred_retry,
- tk_suid_retry;
+ __u8 tk_garb_retry;
+ __u8 tk_cred_retry;
unsigned long tk_cookie; /* Cookie for batching tasks */
@@ -118,9 +117,7 @@ typedef void (*rpc_action)(struct rpc_task *);
*/
#define RPC_TASK_ASYNC 0x0001 /* is an async task */
#define RPC_TASK_SWAPPER 0x0002 /* is swapping in/out */
-#define RPC_TASK_SETUID 0x0004 /* is setuid process */
#define RPC_TASK_CHILD 0x0008 /* is child of other task */
-#define RPC_CALL_REALUID 0x0010 /* try using real uid */
#define RPC_CALL_MAJORSEEN 0x0020 /* major timeout seen */
#define RPC_TASK_ROOTCREDS 0x0040 /* force root creds */
#define RPC_TASK_DYNAMIC 0x0080 /* task was kmalloc'ed */
@@ -129,7 +126,6 @@ typedef void (*rpc_action)(struct rpc_task *);
#define RPC_TASK_NOINTR 0x0400 /* uninterruptible task */
#define RPC_IS_ASYNC(t) ((t)->tk_flags & RPC_TASK_ASYNC)
-#define RPC_IS_SETUID(t) ((t)->tk_flags & RPC_TASK_SETUID)
#define RPC_IS_CHILD(t) ((t)->tk_flags & RPC_TASK_CHILD)
#define RPC_IS_SWAPPER(t) ((t)->tk_flags & RPC_TASK_SWAPPER)
#define RPC_DO_ROOTOVERRIDE(t) ((t)->tk_flags & RPC_TASK_ROOTCREDS)
diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
index f464260d6fdbc..37003970cf2e7 100644
--- a/include/linux/sunrpc/svc.h
+++ b/include/linux/sunrpc/svc.h
@@ -251,8 +251,7 @@ struct svc_program {
char * pg_name; /* service name */
char * pg_class; /* class name: services sharing authentication */
struct svc_stat * pg_stats; /* rpc statistics */
- /* Override authentication. NULL means use default */
- int (*pg_authenticate)(struct svc_rqst *, u32 *);
+ int (*pg_authenticate)(struct svc_rqst *);
};
/*
diff --git a/include/linux/sunrpc/svcauth.h b/include/linux/sunrpc/svcauth.h
index 5c16a7519c6ce..c119ce7cbd22a 100644
--- a/include/linux/sunrpc/svcauth.h
+++ b/include/linux/sunrpc/svcauth.h
@@ -26,21 +26,23 @@ struct svc_cred {
struct svc_rqst; /* forward decl */
/* Authentication is done in the context of a domain.
- * For a server, a domain represents a group of clients using
+ *
+ * Currently, the nfs server uses the auth_domain to stand
+ * for the "client" listed in /etc/exports.
+ *
+ * More generally, a domain might represent a group of clients using
* a common mechanism for authentication and having a common mapping
* between local identity (uid) and network identity. All clients
* in a domain have similar general access rights. Each domain can
* contain multiple principals which will have different specific right
* based on normal Discretionary Access Control.
*
- * For a client, a domain represents a number of servers which all
- * use a common authentication mechanism and network identity name space.
- *
* A domain is created by an authentication flavour module based on name
* only. Userspace then fills in detail on demand.
*
- * The creation of a domain typically implies creation of one or
- * more caches for storing domain specific information.
+ * In the case of auth_unix and auth_null, the auth_domain is also
+ * associated with entries in another cache representing the mapping
+ * of ip addresses to the given client.
*/
struct auth_domain {
struct cache_head h;
@@ -92,6 +94,7 @@ struct auth_ops {
int (*accept)(struct svc_rqst *rq, u32 *authp);
int (*release)(struct svc_rqst *rq);
void (*domain_release)(struct auth_domain *);
+ int (*set_client)(struct svc_rqst *rq);
};
#define SVC_GARBAGE 1
@@ -107,6 +110,7 @@ struct auth_ops {
extern int svc_authenticate(struct svc_rqst *rqstp, u32 *authp);
extern int svc_authorise(struct svc_rqst *rqstp);
+extern int svc_set_client(struct svc_rqst *rqstp);
extern int svc_auth_register(rpc_authflavor_t flavor, struct auth_ops *aops);
extern void svc_auth_unregister(rpc_authflavor_t flavor);
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index 78dbc7bedd7be..e618c16498140 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -140,6 +140,9 @@ struct rpc_xprt {
unsigned int rcvsize, /* socket receive buffer size */
sndsize; /* socket send buffer size */
+ size_t max_payload; /* largest RPC payload size,
+ in bytes */
+
struct rpc_wait_queue sending; /* requests waiting to send */
struct rpc_wait_queue resend; /* requests waiting to resend */
struct rpc_wait_queue pending; /* requests in flight */
diff --git a/include/linux/superhyway.h b/include/linux/superhyway.h
new file mode 100644
index 0000000000000..c906c5a0aaefa
--- /dev/null
+++ b/include/linux/superhyway.h
@@ -0,0 +1,79 @@
+/*
+ * include/linux/superhyway.h
+ *
+ * SuperHyway Bus definitions
+ *
+ * Copyright (C) 2004, 2005 Paul Mundt <lethal@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.
+ */
+#ifndef __LINUX_SUPERHYWAY_H
+#define __LINUX_SUPERHYWAY_H
+
+#include <linux/device.h>
+
+/*
+ * SuperHyway IDs
+ */
+#define SUPERHYWAY_DEVICE_ID_SH5_DMAC 0x0183
+
+struct vcr_info {
+ u8 perr_flags; /* P-port Error flags */
+ u8 merr_flags; /* Module Error flags */
+ u16 mod_vers; /* Module Version */
+ u16 mod_id; /* Module ID */
+ u8 bot_mb; /* Bottom Memory block */
+ u8 top_mb; /* Top Memory block */
+};
+
+struct superhyway_device_id {
+ unsigned int id;
+ unsigned long driver_data;
+};
+
+struct superhyway_device;
+extern struct bus_type superhyway_bus_type;
+
+struct superhyway_driver {
+ char *name;
+
+ const struct superhyway_device_id *id_table;
+ struct device_driver drv;
+
+ int (*probe)(struct superhyway_device *dev, const struct superhyway_device_id *id);
+ void (*remove)(struct superhyway_device *dev);
+};
+
+#define to_superhyway_driver(d) container_of((d), struct superhyway_driver, drv)
+
+struct superhyway_device {
+ char name[32];
+
+ struct device dev;
+
+ struct superhyway_device_id id;
+ struct superhyway_driver *drv;
+
+ struct resource resource;
+ struct vcr_info vcr;
+};
+
+#define to_superhyway_device(d) container_of((d), struct superhyway_device, dev)
+
+#define superhyway_get_drvdata(d) dev_get_drvdata(&(d)->dev)
+#define superhyway_set_drvdata(d,p) dev_set_drvdata(&(d)->dev, (p))
+
+extern int superhyway_scan_bus(void);
+
+/* drivers/sh/superhyway/superhyway.c */
+int superhyway_register_driver(struct superhyway_driver *);
+void superhyway_unregister_driver(struct superhyway_driver *);
+int superhyway_add_device(unsigned int, unsigned long, unsigned long long);
+
+/* drivers/sh/superhyway/superhyway-sysfs.c */
+extern struct device_attribute superhyway_dev_attrs[];
+
+#endif /* __LINUX_SUPERHYWAY_H */
+
diff --git a/include/linux/suspend.h b/include/linux/suspend.h
index 138f5b178f390..2bf0d5fabcdb9 100644
--- a/include/linux/suspend.h
+++ b/include/linux/suspend.h
@@ -1,7 +1,7 @@
#ifndef _LINUX_SWSUSP_H
#define _LINUX_SWSUSP_H
-#if defined(CONFIG_X86) || defined(CONFIG_FRV)
+#if defined(CONFIG_X86) || defined(CONFIG_FRV) || defined(CONFIG_PPC32)
#include <asm/suspend.h>
#endif
#include <linux/swap.h>
@@ -15,15 +15,26 @@ typedef struct pbe {
unsigned long address; /* address of the copy */
unsigned long orig_address; /* original address of page */
swp_entry_t swap_address;
- swp_entry_t dummy; /* we need scratch space at
- * end of page (see link, diskpage)
- */
+
+ struct pbe *next; /* also used as scratch space at
+ * end of page (see link, diskpage)
+ */
} suspend_pagedir_t;
+#define for_each_pbe(pbe, pblist) \
+ for (pbe = pblist ; pbe ; pbe = pbe->next)
+
+#define PBES_PER_PAGE (PAGE_SIZE/sizeof(struct pbe))
+#define PB_PAGE_SKIP (PBES_PER_PAGE-1)
+
+#define for_each_pb_page(pbe, pblist) \
+ for (pbe = pblist ; pbe ; pbe = (pbe+PB_PAGE_SKIP)->next)
+
+
#define SWAP_FILENAME_MAXLENGTH 32
-#define SUSPEND_PD_PAGES(x) (((x)*sizeof(struct pbe))/PAGE_SIZE+1)
+extern dev_t swsusp_resume_device;
/* mm/vmscan.c */
extern int shrink_mem(void);
diff --git a/include/linux/swap.h b/include/linux/swap.h
index 10eb413671046..3bbc41be9bd0c 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -148,7 +148,7 @@ struct swap_list_t {
#define vm_swap_full() (nr_swap_pages*2 < total_swap_pages)
/* linux/mm/oom_kill.c */
-extern void out_of_memory(int gfp_mask);
+extern void out_of_memory(unsigned int __nocast gfp_mask);
/* linux/mm/memory.c */
extern void swapin_readahead(swp_entry_t, unsigned long, struct vm_area_struct *);
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index 33642be4ce000..358d52b0c4455 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -135,6 +135,7 @@ enum
KERN_HZ_TIMER=65, /* int: hz timer on or off */
KERN_UNKNOWN_NMI_PANIC=66, /* int: unknown nmi panic flag */
KERN_BOOTLOADER_TYPE=67, /* int: boot loader type */
+ KERN_RANDOMIZE=68, /* int: randomize virtual address space */
};
@@ -398,6 +399,7 @@ enum
NET_IPV4_CONF_FORCE_IGMP_VERSION=17,
NET_IPV4_CONF_ARP_ANNOUNCE=18,
NET_IPV4_CONF_ARP_IGNORE=19,
+ __NET_IPV4_CONF_MAX
};
/* /proc/sys/net/ipv4/netfilter */
@@ -455,7 +457,8 @@ enum {
NET_IPV6_ROUTE_GC_INTERVAL=6,
NET_IPV6_ROUTE_GC_ELASTICITY=7,
NET_IPV6_ROUTE_MTU_EXPIRES=8,
- NET_IPV6_ROUTE_MIN_ADVMSS=9
+ NET_IPV6_ROUTE_MIN_ADVMSS=9,
+ NET_IPV6_ROUTE_GC_MIN_INTERVAL_MS=10
};
enum {
@@ -475,7 +478,8 @@ enum {
NET_IPV6_REGEN_MAX_RETRY=14,
NET_IPV6_MAX_DESYNC_FACTOR=15,
NET_IPV6_MAX_ADDRESSES=16,
- NET_IPV6_FORCE_MLD_VERSION=17
+ NET_IPV6_FORCE_MLD_VERSION=17,
+ __NET_IPV6_MAX
};
/* /proc/sys/net/ipv6/icmp */
@@ -500,7 +504,10 @@ enum {
NET_NEIGH_GC_INTERVAL=13,
NET_NEIGH_GC_THRESH1=14,
NET_NEIGH_GC_THRESH2=15,
- NET_NEIGH_GC_THRESH3=16
+ NET_NEIGH_GC_THRESH3=16,
+ NET_NEIGH_RETRANS_TIME_MS=17,
+ NET_NEIGH_REACHABLE_TIME_MS=18,
+ __NET_NEIGH_MAX
};
/* /proc/sys/net/ipx */
@@ -797,6 +804,8 @@ extern int proc_dointvec_jiffies(ctl_table *, int, struct file *,
void __user *, size_t *, loff_t *);
extern int proc_dointvec_userhz_jiffies(ctl_table *, int, struct file *,
void __user *, size_t *, loff_t *);
+extern int proc_dointvec_ms_jiffies(ctl_table *, int, struct file *,
+ void __user *, size_t *, loff_t *);
extern int proc_doulongvec_minmax(ctl_table *, int, struct file *,
void __user *, size_t *, loff_t *);
extern int proc_doulongvec_ms_jiffies_minmax(ctl_table *table, int,
@@ -814,6 +823,7 @@ extern int do_sysctl_strategy (ctl_table *table,
extern ctl_handler sysctl_string;
extern ctl_handler sysctl_intvec;
extern ctl_handler sysctl_jiffies;
+extern ctl_handler sysctl_ms_jiffies;
/*
diff --git a/include/linux/sysrq.h b/include/linux/sysrq.h
index b8415f065ef80..ea819b89c2350 100644
--- a/include/linux/sysrq.h
+++ b/include/linux/sysrq.h
@@ -16,10 +16,22 @@
struct pt_regs;
struct tty_struct;
+/* Possible values of bitmask for enabling sysrq functions */
+/* 0x0001 is reserved for enable everything */
+#define SYSRQ_ENABLE_LOG 0x0002
+#define SYSRQ_ENABLE_KEYBOARD 0x0004
+#define SYSRQ_ENABLE_DUMP 0x0008
+#define SYSRQ_ENABLE_SYNC 0x0010
+#define SYSRQ_ENABLE_REMOUNT 0x0020
+#define SYSRQ_ENABLE_SIGNAL 0x0040
+#define SYSRQ_ENABLE_BOOT 0x0080
+#define SYSRQ_ENABLE_RTNICE 0x0100
+
struct sysrq_key_op {
void (*handler)(int, struct pt_regs *, struct tty_struct *);
char *help_msg;
char *action_msg;
+ int enable_mask;
};
#ifdef CONFIG_MAGIC_SYSRQ
@@ -30,7 +42,7 @@ struct sysrq_key_op {
*/
void handle_sysrq(int, struct pt_regs *, struct tty_struct *);
-void __handle_sysrq(int, struct pt_regs *, struct tty_struct *);
+void __handle_sysrq(int, struct pt_regs *, struct tty_struct *, int check_mask);
int register_sysrq_key(int, struct sysrq_key_op *);
int unregister_sysrq_key(int, struct sysrq_key_op *);
struct sysrq_key_op *__sysrq_get_key_op(int key);
diff --git a/include/linux/tc_ematch/tc_em_cmp.h b/include/linux/tc_ematch/tc_em_cmp.h
new file mode 100644
index 0000000000000..c7f4d43618fd8
--- /dev/null
+++ b/include/linux/tc_ematch/tc_em_cmp.h
@@ -0,0 +1,26 @@
+#ifndef __LINUX_TC_EM_CMP_H
+#define __LINUX_TC_EM_CMP_H
+
+#include <linux/pkt_cls.h>
+
+struct tcf_em_cmp
+{
+ __u32 val;
+ __u32 mask;
+ __u16 off;
+ __u8 align:4;
+ __u8 flags:4;
+ __u8 layer:4;
+ __u8 opnd:4;
+};
+
+enum
+{
+ TCF_EM_ALIGN_U8 = 1,
+ TCF_EM_ALIGN_U16 = 2,
+ TCF_EM_ALIGN_U32 = 4
+};
+
+#define TCF_EM_CMP_TRANS 1
+
+#endif
diff --git a/include/linux/tc_ematch/tc_em_meta.h b/include/linux/tc_ematch/tc_em_meta.h
new file mode 100644
index 0000000000000..aa6b48bb4dcd0
--- /dev/null
+++ b/include/linux/tc_ematch/tc_em_meta.h
@@ -0,0 +1,69 @@
+#ifndef __LINUX_TC_EM_META_H
+#define __LINUX_TC_EM_META_H
+
+#include <linux/pkt_cls.h>
+
+enum
+{
+ TCA_EM_META_UNSPEC,
+ TCA_EM_META_HDR,
+ TCA_EM_META_LVALUE,
+ TCA_EM_META_RVALUE,
+ __TCA_EM_META_MAX
+};
+#define TCA_EM_META_MAX (__TCA_EM_META_MAX - 1)
+
+struct tcf_meta_val
+{
+ __u16 kind;
+ __u8 shift;
+ __u8 op;
+};
+
+#define TCF_META_TYPE_MASK (0xf << 12)
+#define TCF_META_TYPE(kind) (((kind) & TCF_META_TYPE_MASK) >> 12)
+#define TCF_META_ID_MASK 0x7ff
+#define TCF_META_ID(kind) ((kind) & TCF_META_ID_MASK)
+
+enum
+{
+ TCF_META_TYPE_VAR,
+ TCF_META_TYPE_INT,
+ __TCF_META_TYPE_MAX
+};
+#define TCF_META_TYPE_MAX (__TCF_META_TYPE_MAX - 1)
+
+enum
+{
+ TCF_META_ID_VALUE,
+ TCF_META_ID_RANDOM,
+ TCF_META_ID_LOADAVG_0,
+ TCF_META_ID_LOADAVG_1,
+ TCF_META_ID_LOADAVG_2,
+ TCF_META_ID_DEV,
+ TCF_META_ID_INDEV,
+ TCF_META_ID_REALDEV,
+ TCF_META_ID_PRIORITY,
+ TCF_META_ID_PROTOCOL,
+ TCF_META_ID_SECURITY,
+ TCF_META_ID_PKTTYPE,
+ TCF_META_ID_PKTLEN,
+ TCF_META_ID_DATALEN,
+ TCF_META_ID_MACLEN,
+ TCF_META_ID_NFMARK,
+ TCF_META_ID_TCINDEX,
+ TCF_META_ID_TCVERDICT,
+ TCF_META_ID_TCCLASSID,
+ TCF_META_ID_RTCLASSID,
+ TCF_META_ID_RTIIF,
+ __TCF_META_ID_MAX
+};
+#define TCF_META_ID_MAX (__TCF_META_ID_MAX - 1)
+
+struct tcf_meta_hdr
+{
+ struct tcf_meta_val left;
+ struct tcf_meta_val right;
+};
+
+#endif
diff --git a/include/linux/tc_ematch/tc_em_nbyte.h b/include/linux/tc_ematch/tc_em_nbyte.h
new file mode 100644
index 0000000000000..f19d1f58ec9df
--- /dev/null
+++ b/include/linux/tc_ematch/tc_em_nbyte.h
@@ -0,0 +1,13 @@
+#ifndef __LINUX_TC_EM_NBYTE_H
+#define __LINUX_TC_EM_NBYTE_H
+
+#include <linux/pkt_cls.h>
+
+struct tcf_em_nbyte
+{
+ __u16 off;
+ __u16 len:12;
+ __u8 layer:4;
+};
+
+#endif
diff --git a/include/linux/tcp.h b/include/linux/tcp.h
index f56e734c1da0b..14a55e3e3a502 100644
--- a/include/linux/tcp.h
+++ b/include/linux/tcp.h
@@ -216,17 +216,16 @@ struct tcp_options_received {
__u32 ts_recent; /* Time stamp to echo next */
__u32 rcv_tsval; /* Time stamp value */
__u32 rcv_tsecr; /* Time stamp echo reply */
- char saw_tstamp; /* Saw TIMESTAMP on last packet */
- char tstamp_ok; /* TIMESTAMP seen on SYN packet */
- char sack_ok; /* SACK seen on SYN packet */
- char wscale_ok; /* Wscale seen on SYN packet */
- __u8 snd_wscale; /* Window scaling received from sender */
- __u8 rcv_wscale; /* Window scaling to send to receiver */
+ __u16 saw_tstamp : 1, /* Saw TIMESTAMP on last packet */
+ tstamp_ok : 1, /* TIMESTAMP seen on SYN packet */
+ dsack : 1, /* D-SACK is scheduled */
+ wscale_ok : 1, /* Wscale seen on SYN packet */
+ sack_ok : 4, /* SACK seen on SYN packet */
+ snd_wscale : 4, /* Window scaling received from sender */
+ rcv_wscale : 4; /* Window scaling to send to receiver */
/* SACKs data */
- __u8 dsack; /* D-SACK is scheduled */
__u8 eff_sacks; /* Size of SACK array to send with next packet */
__u8 num_sacks; /* Number of SACK blocks */
- __u8 __pad;
__u16 user_mss; /* mss requested by user in ioctl */
__u16 mss_clamp; /* Maximal mss, negotiated at connection setup */
};
@@ -284,10 +283,13 @@ struct tcp_sock {
__u32 mss_cache; /* Cached effective mss, not including SACKS */
__u16 mss_cache_std; /* Like mss_cache, but without TSO */
__u16 ext_header_len; /* Network protocol overhead (IP/IPv6 options) */
- __u16 ext2_header_len;/* Options depending on route */
__u8 ca_state; /* State of fast-retransmit machine */
__u8 retransmits; /* Number of unrecovered RTO timeouts. */
+ __u16 advmss; /* Advertised MSS */
+ __u32 window_clamp; /* Maximal window to advertise */
+ __u32 rcv_ssthresh; /* Current window clamp */
+
__u32 frto_highmark; /* snd_nxt when RTO occurred */
__u8 reordering; /* Packet reordering metric. */
__u8 frto_counter; /* Number of new acks after RTO */
@@ -345,14 +347,9 @@ struct tcp_sock {
struct tcp_sack_block duplicate_sack[1]; /* D-SACK block */
struct tcp_sack_block selective_acks[4]; /* The SACKS themselves*/
- __u32 window_clamp; /* Maximal window to advertise */
- __u32 rcv_ssthresh; /* Current window clamp */
- __u16 advmss; /* Advertised MSS */
-
__u8 syn_retries; /* num of allowed syn retries */
__u8 ecn_flags; /* ECN status bits. */
__u16 prior_ssthresh; /* ssthresh saved at recovery start */
- __u16 __pad1;
__u32 lost_out; /* Lost packets */
__u32 sacked_out; /* SACK'd packets */
__u32 fackets_out; /* FACK'd packets */
diff --git a/include/linux/threads.h b/include/linux/threads.h
index 4243c55cce87b..b59738ac61973 100644
--- a/include/linux/threads.h
+++ b/include/linux/threads.h
@@ -7,7 +7,7 @@
* The default limit for the nr of threads is now in
* /proc/sys/kernel/threads-max.
*/
-
+
/*
* Maximum supported processors that can run under SMP. This value is
* set via configure setting. The maximum is equal to the size of the
@@ -25,11 +25,12 @@
/*
* This controls the default maximum pid allocated to a process
*/
-#define PID_MAX_DEFAULT 0x8000
+#define PID_MAX_DEFAULT (CONFIG_BASE_SMALL ? 0x1000 : 0x8000)
/*
* A maximum of 4 million PIDs should be enough for a while:
*/
-#define PID_MAX_LIMIT (sizeof(long) > 4 ? 4*1024*1024 : PID_MAX_DEFAULT)
+#define PID_MAX_LIMIT (CONFIG_BASE_SMALL ? PAGE_SIZE * 8 : \
+ (sizeof(long) > 4 ? 4 * 1024 * 1024 : PID_MAX_DEFAULT))
#endif
diff --git a/include/linux/timex.h b/include/linux/timex.h
index b54c288dd6b83..74fdd07d3792a 100644
--- a/include/linux/timex.h
+++ b/include/linux/timex.h
@@ -240,9 +240,7 @@ extern long time_precision; /* clock precision (us) */
extern long time_maxerror; /* maximum error */
extern long time_esterror; /* estimated error */
-extern long time_phase; /* phase offset (scaled us) */
extern long time_freq; /* frequency offset (scaled ppm) */
-extern long time_adj; /* tick adjust (scaled 1 / HZ) */
extern long time_reftime; /* time at last adjustment (s) */
extern long time_adjust; /* The amount of adjtime left */
diff --git a/include/linux/topology.h b/include/linux/topology.h
index 295f4c05c7f5d..d70e8972c67f5 100644
--- a/include/linux/topology.h
+++ b/include/linux/topology.h
@@ -31,9 +31,12 @@
#include <linux/bitops.h>
#include <linux/mmzone.h>
#include <linux/smp.h>
-
#include <asm/topology.h>
+#ifndef node_has_online_mem
+#define node_has_online_mem(nid) (1)
+#endif
+
#ifndef nr_cpus_node
#define nr_cpus_node(node) \
({ \
diff --git a/include/linux/tpqic02.h b/include/linux/tpqic02.h
deleted file mode 100644
index f0dfcfa562730..0000000000000
--- a/include/linux/tpqic02.h
+++ /dev/null
@@ -1,738 +0,0 @@
-/* $Id: tpqic02.h,v 1.5 1996/12/14 23:01:38 root Exp root $
- *
- * Include file for QIC-02 driver for Linux.
- *
- * Copyright (c) 1992--1995 by H. H. Bergman. All rights reserved.
- *
- * ******* USER CONFIG SECTION BELOW (Near line 70) *******
- */
-
-#ifndef _LINUX_TPQIC02_H
-#define _LINUX_TPQIC02_H
-
-#include <linux/config.h>
-
-#if defined(CONFIG_QIC02_TAPE) || defined(CONFIG_QIC02_TAPE_MODULE)
-
-/* need to have QIC02_TAPE_DRIVE and QIC02_TAPE_IFC expand to something */
-#include <linux/mtio.h>
-
-
-/* Make QIC02_TAPE_IFC expand to something.
- *
- * The only difference between WANGTEK and EVEREX is in the
- * handling of the DMA channel 3.
- * Note that the driver maps EVEREX to WANGTEK internally for speed
- * reasons. Externally WANGTEK==1, EVEREX==2, ARCHIVE==3.
- * These must correspond to the values used in qic02config(1).
- *
- * Support for Mountain controllers was added by Erik Jacobson
- * and severely hacked by me. -- hhb
- *
- * Support for Emerald controllers by Alan Bain <afrb2@chiark.chu.cam.ac.uk>
- * with more hacks by me. -- hhb
- */
-#define WANGTEK 1 /* don't know about Wangtek QIC-36 */
-#define EVEREX (WANGTEK+1) /* I heard *some* of these are identical */
-#define EVEREX_811V EVEREX /* With TEAC MT 2ST 45D */
-#define EVEREX_831V EVEREX
-#define ARCHIVE 3
-#define ARCHIVE_SC400 ARCHIVE /* rumoured to be from the pre-SMD-age */
-#define ARCHIVE_SC402 ARCHIVE /* don't know much about SC400 */
-#define ARCHIVE_SC499 ARCHIVE /* SC402 and SC499R should be identical */
-
-#define MOUNTAIN 5 /* Mountain Computer Interface */
-#define EMERALD 6 /* Emerald Interface card */
-
-
-
-#define QIC02_TAPE_PORT_RANGE 8 /* number of IO locations to reserve */
-
-
-/*********** START OF USER CONFIGURABLE SECTION ************/
-
-/* Tape configuration: Select DRIVE, IFC, PORT, IRQ and DMA below.
- * Runtime (re)configuration is not supported yet.
- *
- * Tape drive configuration: (MT_IS* constants are defined in mtio.h)
- *
- * QIC02_TAPE_DRIVE = MT_ISWT5150
- * - Wangtek 5150, format: up to QIC-150.
- * QIC02_TAPE_DRIVE = MT_ISQIC02_ALL_FEATURES
- * - Enables some optional QIC02 commands that some drives may lack.
- * It is provided so you can check which are supported by your drive.
- * Refer to tpqic02.h for others.
- *
- * Supported interface cards: QIC02_TAPE_IFC =
- * WANGTEK,
- * ARCHIVE_SC402, ARCHIVE_SC499. (both same programming interface)
- *
- * Make sure you have the I/O ports/DMA channels
- * and IRQ stuff configured properly!
- * NOTE: There may be other device drivers using the same major
- * number. This must be avoided. Check for timer.h conflicts too.
- *
- * If you have an EVEREX EV-831 card and you are using DMA channel 3,
- * you will probably have to ``#define QIC02_TAPE_DMA3_FIX'' below.
- */
-
-/* CONFIG_QIC02_DYNCONF can be defined in autoconf.h, by `make config' */
-
-/*** #undef CONFIG_QIC02_DYNCONF ***/
-
-#ifndef CONFIG_QIC02_DYNCONF
-
-#define QIC02_TAPE_DRIVE MT_ISQIC02_ALL_FEATURES /* drive type */
-/* #define QIC02_TAPE_DRIVE MT_ISWT5150 */
-/* #define QIC02_TAPE_DRIVE MT_ISARCHIVE_5945L2 */
-/* #define QIC02_TAPE_DRIVE MT_ISTEAC_MT2ST */
-/* #define QIC02_TAPE_DRIVE MT_ISARCHIVE_2150L */
-/* #define QIC02_TAPE_DRIVE MT_ISARCHIVESC499 */
-
-/* Either WANGTEK, ARCHIVE or MOUNTAIN. Not EVEREX.
- * If you have an EVEREX, use WANGTEK and try the DMA3_FIX below.
- */
-#define QIC02_TAPE_IFC WANGTEK /* interface card type */
-/* #define QIC02_TAPE_IFC ARCHIVE */
-/* #define QIC02_TAPE_IFC MOUNTAIN */
-
-#define QIC02_TAPE_PORT 0x300 /* controller port address */
-#define QIC02_TAPE_IRQ 5 /* For IRQ2, use 9 here, others normal. */
-#define QIC02_TAPE_DMA 1 /* either 1 or 3, because 2 is used by the floppy */
-
-/* If DMA3 doesn't work, but DMA1 does, and you have a
- * Wangtek/Everex card, you can try #define-ing the flag
- * below. Note that you should also change the DACK jumper
- * for Wangtek/Everex cards when changing the DMA channel.
- */
-#undef QIC02_TAPE_DMA3_FIX
-
-/************ END OF USER CONFIGURABLE SECTION *************/
-
-/* I put the stuff above in config.in, but a few recompiles, to
- * verify different configurations, and several days later I decided
- * to change it back again.
- */
-
-
-
-/* NOTE: TP_HAVE_DENS should distinguish between available densities (?)
- * NOTE: Drive select is not implemented -- I have only one tape streamer,
- * so I'm unable and unmotivated to test and implement that. ;-) ;-)
- */
-#if QIC02_TAPE_DRIVE == MT_ISWT5150
-#define TP_HAVE_DENS 1
-#define TP_HAVE_BSF 0 /* nope */
-#define TP_HAVE_FSR 0 /* nope */
-#define TP_HAVE_BSR 0 /* nope */
-#define TP_HAVE_EOD 0 /* most of the time */
-#define TP_HAVE_SEEK 0
-#define TP_HAVE_TELL 0
-#define TP_HAVE_RAS1 1
-#define TP_HAVE_RAS2 1
-
-#elif QIC02_TAPE_DRIVE == MT_ISARCHIVESC499 /* Archive SC-499 QIC-36 controller */
-#define TP_HAVE_DENS 1 /* can do set density (QIC-11 / QIC-24) */
-#define TP_HAVE_BSF 0
-#define TP_HAVE_FSR 1 /* can skip one block forwards */
-#define TP_HAVE_BSR 1 /* can skip one block backwards */
-#define TP_HAVE_EOD 1 /* can seek to end of recorded data */
-#define TP_HAVE_SEEK 0
-#define TP_HAVE_TELL 0
-#define TP_HAVE_RAS1 1 /* can run selftest 1 */
-#define TP_HAVE_RAS2 1 /* can run selftest 2 */
-/* These last two selftests shouldn't be used yet! */
-
-#elif (QIC02_TAPE_DRIVE == MT_ISARCHIVE_2060L) || (QIC02_TAPE_DRIVE == MT_ISARCHIVE_2150L)
-#define TP_HAVE_DENS 1 /* can do set density (QIC-24 / QIC-120 / QIC-150) */
-#define TP_HAVE_BSF 0
-#define TP_HAVE_FSR 1 /* can skip one block forwards */
-#define TP_HAVE_BSR 1 /* can skip one block backwards */
-#define TP_HAVE_EOD 1 /* can seek to end of recorded data */
-#define TP_HAVE_TELL 1 /* can read current block address */
-#define TP_HAVE_SEEK 1 /* can seek to block */
-#define TP_HAVE_RAS1 1 /* can run selftest 1 */
-#define TP_HAVE_RAS2 1 /* can run selftest 2 */
-/* These last two selftests shouldn't be used yet! */
-
-#elif QIC02_TAPE_DRIVE == MT_ISARCHIVE_5945L2
-/* can anyone verify this entry?? */
-#define TP_HAVE_DENS 1 /* can do set density?? (QIC-24??) */
-#define TP_HAVE_BSF 0
-#define TP_HAVE_FSR 1 /* can skip one block forwards */
-#define TP_HAVE_BSR 1 /* can skip one block backwards */
-#define TP_HAVE_EOD 1 /* can seek to end of recorded data */
-#define TP_HAVE_TELL 1 /* can read current block address */
-#define TP_HAVE_SEEK 1 /* can seek to block */
-#define TP_HAVE_RAS1 1 /* can run selftest 1 */
-#define TP_HAVE_RAS2 1 /* can run selftest 2 */
-/* These last two selftests shouldn't be used yet! */
-
-#elif QIC02_TAPE_DRIVE == MT_ISTEAC_MT2ST
-/* can anyone verify this entry?? */
-#define TP_HAVE_DENS 0 /* cannot do set density?? (QIC-150?) */
-#define TP_HAVE_BSF 0
-#define TP_HAVE_FSR 1 /* can skip one block forwards */
-#define TP_HAVE_BSR 1 /* can skip one block backwards */
-#define TP_HAVE_EOD 1 /* can seek to end of recorded data */
-#define TP_HAVE_SEEK 1 /* can seek to block */
-#define TP_HAVE_TELL 1 /* can read current block address */
-#define TP_HAVE_RAS1 1 /* can run selftest 1 */
-#define TP_HAVE_RAS2 1 /* can run selftest 2 */
-/* These last two selftests shouldn't be used yet! */
-
-#elif QIC02_TAPE_DRIVE == MT_ISQIC02_ALL_FEATURES
-#define TP_HAVE_DENS 1 /* can do set density */
-#define TP_HAVE_BSF 1 /* can search filemark backwards */
-#define TP_HAVE_FSR 1 /* can skip one block forwards */
-#define TP_HAVE_BSR 1 /* can skip one block backwards */
-#define TP_HAVE_EOD 1 /* can seek to end of recorded data */
-#define TP_HAVE_SEEK 1 /* seek to block address */
-#define TP_HAVE_TELL 1 /* tell current block address */
-#define TP_HAVE_RAS1 1 /* can run selftest 1 */
-#define TP_HAVE_RAS2 1 /* can run selftest 2 */
-/* These last two selftests shouldn't be used yet! */
-
-
-#else
-#error No QIC-02 tape drive type defined!
-/* If your drive is not listed above, first try the 'ALL_FEATURES',
- * to see what commands are supported, then create your own entry in
- * the list above. You may want to mail it to me, so that I can include
- * it in the next release.
- */
-#endif
-
-#endif /* !CONFIG_QIC02_DYNCONF */
-
-
-/* WANGTEK interface card specifics */
-#define WT_QIC02_STAT_PORT (QIC02_TAPE_PORT)
-#define WT_QIC02_CTL_PORT (QIC02_TAPE_PORT)
-#define WT_QIC02_CMD_PORT (QIC02_TAPE_PORT+1)
-#define WT_QIC02_DATA_PORT (QIC02_TAPE_PORT+1)
-
-/* status register bits (Active LOW!) */
-#define WT_QIC02_STAT_POLARITY 0
-#define WT_QIC02_STAT_READY 0x01
-#define WT_QIC02_STAT_EXCEPTION 0x02
-#define WT_QIC02_STAT_MASK (WT_QIC02_STAT_READY|WT_QIC02_STAT_EXCEPTION)
-
-#define WT_QIC02_STAT_RESETMASK 0x07
-#define WT_QIC02_STAT_RESETVAL (WT_QIC02_STAT_RESETMASK & ~WT_QIC02_STAT_EXCEPTION)
-
-/* controller register (QIC02_CTL_PORT) bits */
-#define WT_QIC02_CTL_RESET 0x02
-#define WT_QIC02_CTL_REQUEST 0x04
-#define WT_CTL_ONLINE 0x01
-#define WT_CTL_CMDOFF 0xC0
-
-#define WT_CTL_DMA3 0x10 /* enable dma chan3 */
-#define WT_CTL_DMA1 0x08 /* enable dma chan1 or chan2 */
-
-/* EMERALD interface card specifics
- * Much like Wangtek, only different polarity and bit locations
- */
-#define EMR_QIC02_STAT_PORT (QIC02_TAPE_PORT)
-#define EMR_QIC02_CTL_PORT (QIC02_TAPE_PORT)
-#define EMR_QIC02_CMD_PORT (QIC02_TAPE_PORT+1)
-#define EMR_QIC02_DATA_PORT (QIC02_TAPE_PORT+1)
-
-/* status register bits (Active High!) */
-#define EMR_QIC02_STAT_POLARITY 1
-#define EMR_QIC02_STAT_READY 0x01
-#define EMR_QIC02_STAT_EXCEPTION 0x02
-#define EMR_QIC02_STAT_MASK (EMR_QIC02_STAT_READY|EMR_QIC02_STAT_EXCEPTION)
-
-#define EMR_QIC02_STAT_RESETMASK 0x07
-#define EMR_QIC02_STAT_RESETVAL (EMR_QIC02_STAT_RESETMASK & ~EMR_QIC02_STAT_EXCEPTION)
-
-/* controller register (QIC02_CTL_PORT) bits */
-#define EMR_QIC02_CTL_RESET 0x02
-#define EMR_QIC02_CTL_REQUEST 0x04
-#define EMR_CTL_ONLINE 0x01
-#define EMR_CTL_CMDOFF 0xC0
-
-#define EMR_CTL_DMA3 0x10 /* enable dma chan3 */
-#define EMR_CTL_DMA1 0x08 /* enable dma chan1 or chan2 */
-
-
-
-/* ARCHIVE interface card specifics */
-#define AR_QIC02_STAT_PORT (QIC02_TAPE_PORT+1)
-#define AR_QIC02_CTL_PORT (QIC02_TAPE_PORT+1)
-#define AR_QIC02_CMD_PORT (QIC02_TAPE_PORT)
-#define AR_QIC02_DATA_PORT (QIC02_TAPE_PORT)
-
-#define AR_START_DMA_PORT (QIC02_TAPE_PORT+2)
-#define AR_RESET_DMA_PORT (QIC02_TAPE_PORT+3)
-
-/* STAT port bits */
-#define AR_QIC02_STAT_POLARITY 0
-#define AR_STAT_IRQF 0x80 /* active high, interrupt request flag */
-#define AR_QIC02_STAT_READY 0x40 /* active low */
-#define AR_QIC02_STAT_EXCEPTION 0x20 /* active low */
-#define AR_QIC02_STAT_MASK (AR_QIC02_STAT_READY|AR_QIC02_STAT_EXCEPTION)
-#define AR_STAT_DMADONE 0x10 /* active high, DMA done */
-#define AR_STAT_DIRC 0x08 /* active high, direction */
-
-#define AR_QIC02_STAT_RESETMASK 0x70 /* check RDY,EXC,DMADONE */
-#define AR_QIC02_STAT_RESETVAL ((AR_QIC02_STAT_RESETMASK & ~AR_STAT_IRQF & ~AR_QIC02_STAT_EXCEPTION) | AR_STAT_DMADONE)
-
-/* CTL port bits */
-#define AR_QIC02_CTL_RESET 0x80 /* drive reset */
-#define AR_QIC02_CTL_REQUEST 0x40 /* notify of new command */
-#define AR_CTL_IEN 0x20 /* interrupt enable */
-#define AR_CTL_DNIEN 0x10 /* done-interrupt enable */
- /* Note: All of these bits are cleared automatically when writing to
- * AR_RESET_DMA_PORT. So AR_CTL_IEN and AR_CTL_DNIEN must be
- * reprogrammed before the write to AR_START_DMA_PORT.
- */
-
-
-/* MOUNTAIN interface specifics */
-#define MTN_QIC02_STAT_PORT (QIC02_TAPE_PORT+1)
-#define MTN_QIC02_CTL_PORT (QIC02_TAPE_PORT+1)
-#define MTN_QIC02_CMD_PORT (QIC02_TAPE_PORT)
-#define MTN_QIC02_DATA_PORT (QIC02_TAPE_PORT)
-
-#define MTN_W_SELECT_DMA_PORT (QIC02_TAPE_PORT+2)
-#define MTN_R_DESELECT_DMA_PORT (QIC02_TAPE_PORT+2)
-#define MTN_W_DMA_WRITE_PORT (QIC02_TAPE_PORT+3)
-
-/* STAT port bits */
-#define MTN_QIC02_STAT_POLARITY 0
-#define MTN_QIC02_STAT_READY 0x02 /* active low */
-#define MTN_QIC02_STAT_EXCEPTION 0x04 /* active low */
-#define MTN_QIC02_STAT_MASK (MTN_QIC02_STAT_READY|MTN_QIC02_STAT_EXCEPTION)
-#define MTN_STAT_DMADONE 0x01 /* active high, DMA done */
-
-#define MTN_QIC02_STAT_RESETMASK 0x07 /* check RDY,EXC,DMADONE */
-#define MTN_QIC02_STAT_RESETVAL ((MTN_QIC02_STAT_RESETMASK & ~MTN_QIC02_STAT_EXCEPTION) | MTN_STAT_DMADONE)
-
-/* CTL port bits */
-#define MTN_QIC02_CTL_RESET_NOT 0x80 /* drive reset, active low */
-#define MTN_QIC02_CTL_RESET 0x80 /* Fodder #definition to keep gcc happy */
-
-#define MTN_QIC02_CTL_ONLINE 0x40 /* Put drive on line */
-#define MTN_QIC02_CTL_REQUEST 0x20 /* notify of new command */
-#define MTN_QIC02_CTL_IRQ_DRIVER 0x10 /* Enable IRQ tristate driver */
-#define MTN_QIC02_CTL_DMA_DRIVER 0x08 /* Enable DMA tristate driver */
-#define MTN_CTL_EXC_IEN 0x04 /* Exception interrupt enable */
-#define MTN_CTL_RDY_IEN 0x02 /* Ready interrupt enable */
-#define MTN_CTL_DNIEN 0x01 /* done-interrupt enable */
-
-#define MTN_CTL_ONLINE (MTN_QIC02_CTL_RESET_NOT | MTN_QIC02_CTL_IRQ_DRIVER | MTN_QIC02_CTL_DMA_DRIVER)
-
-
-#ifndef CONFIG_QIC02_DYNCONF
-
-# define QIC02_TAPE_DEBUG (qic02_tape_debug)
-
-# if QIC02_TAPE_IFC == WANGTEK
-# define QIC02_STAT_POLARITY WT_QIC02_STAT_POLARITY
-# define QIC02_STAT_PORT WT_QIC02_STAT_PORT
-# define QIC02_CTL_PORT WT_QIC02_CTL_PORT
-# define QIC02_CMD_PORT WT_QIC02_CMD_PORT
-# define QIC02_DATA_PORT WT_QIC02_DATA_PORT
-
-# define QIC02_STAT_READY WT_QIC02_STAT_READY
-# define QIC02_STAT_EXCEPTION WT_QIC02_STAT_EXCEPTION
-# define QIC02_STAT_MASK WT_QIC02_STAT_MASK
-# define QIC02_STAT_RESETMASK WT_QIC02_STAT_RESETMASK
-# define QIC02_STAT_RESETVAL WT_QIC02_STAT_RESETVAL
-
-# define QIC02_CTL_RESET WT_QIC02_CTL_RESET
-# define QIC02_CTL_REQUEST WT_QIC02_CTL_REQUEST
-
-# if QIC02_TAPE_DMA == 3
-# ifdef QIC02_TAPE_DMA3_FIX
-# define WT_CTL_DMA WT_CTL_DMA1
-# else
-# define WT_CTL_DMA WT_CTL_DMA3
-# endif
-# elif QIC02_TAPE_DMA == 1
-# define WT_CTL_DMA WT_CTL_DMA1
-# else
-# error Unsupported or incorrect DMA configuration.
-# endif
-
-# elif QIC02_TAPE_IFC == EMERALD
-# define QIC02_STAT_POLARITY EMR_QIC02_STAT_POLARITY
-# define QIC02_STAT_PORT EMR_QIC02_STAT_PORT
-# define QIC02_CTL_PORT EMR_QIC02_CTL_PORT
-# define QIC02_CMD_PORT EMR_QIC02_CMD_PORT
-# define QIC02_DATA_PORT EMR_QIC02_DATA_PORT
-
-# define QIC02_STAT_READY EMR_QIC02_STAT_READY
-# define QIC02_STAT_EXCEPTION EMR_QIC02_STAT_EXCEPTION
-# define QIC02_STAT_MASK EMR_QIC02_STAT_MASK
-# define QIC02_STAT_RESETMASK EMR_QIC02_STAT_RESETMASK
-# define QIC02_STAT_RESETVAL EMR_QIC02_STAT_RESETVAL
-
-# define QIC02_CTL_RESET EMR_QIC02_CTL_RESET
-# define QIC02_CTL_REQUEST EMR_QIC02_CTL_REQUEST
-
-# if QIC02_TAPE_DMA == 3
-# ifdef QIC02_TAPE_DMA3_FIX
-# define EMR_CTL_DMA EMR_CTL_DMA1
-# else
-# define EMR_CTL_DMA EMR_CTL_DMA3
-# endif
-# elif QIC02_TAPE_DMA == 1
-# define EMR_CTL_DMA EMR_CTL_DMA1
-# else
-# error Unsupported or incorrect DMA configuration.
-# endif
-
-# elif QIC02_TAPE_IFC == ARCHIVE
-# define QIC02_STAT_POLARITY AR_QIC02_STAT_POLARITY
-# define QIC02_STAT_PORT AR_QIC02_STAT_PORT
-# define QIC02_CTL_PORT AR_QIC02_CTL_PORT
-# define QIC02_CMD_PORT AR_QIC02_CMD_PORT
-# define QIC02_DATA_PORT AR_QIC02_DATA_PORT
-
-# define QIC02_STAT_READY AR_QIC02_STAT_READY
-# define QIC02_STAT_EXCEPTION AR_QIC02_STAT_EXCEPTION
-# define QIC02_STAT_MASK AR_QIC02_STAT_MASK
-# define QIC02_STAT_RESETMASK AR_QIC02_STAT_RESETMASK
-# define QIC02_STAT_RESETVAL AR_QIC02_STAT_RESETVAL
-
-# define QIC02_CTL_RESET AR_QIC02_CTL_RESET
-# define QIC02_CTL_REQUEST AR_QIC02_CTL_REQUEST
-
-# if QIC02_TAPE_DMA > 3 /* channel 2 is used by the floppy driver */
-# error DMA channels other than 1 and 3 are not supported.
-# endif
-
-# elif QIC02_TAPE_IFC == MOUNTAIN
-# define QIC02_STAT_POLARITY MTN_QIC02_STAT_POLARITY
-# define QIC02_STAT_PORT MTN_QIC02_STAT_PORT
-# define QIC02_CTL_PORT MTN_QIC02_CTL_PORT
-# define QIC02_CMD_PORT MTN_QIC02_CMD_PORT
-# define QIC02_DATA_PORT MTN_QIC02_DATA_PORT
-
-# define QIC02_STAT_READY MTN_QIC02_STAT_READY
-# define QIC02_STAT_EXCEPTION MTN_QIC02_STAT_EXCEPTION
-# define QIC02_STAT_MASK MTN_QIC02_STAT_MASK
-# define QIC02_STAT_RESETMASK MTN_QIC02_STAT_RESETMASK
-# define QIC02_STAT_RESETVAL MTN_QIC02_STAT_RESETVAL
-
-# define QIC02_CTL_RESET MTN_QIC02_CTL_RESET
-# define QIC02_CTL_REQUEST MTN_QIC02_CTL_REQUEST
-
-# if QIC02_TAPE_DMA > 3 /* channel 2 is used by the floppy driver */
-# error DMA channels other than 1 and 3 are not supported.
-# endif
-
-# else
-# error No valid interface card specified!
-# endif /* QIC02_TAPE_IFC */
-
-
- /* An ugly hack to make sure WT_CTL_DMA is defined even for the
- * static, non-Wangtek case. The alternative was even worse.
- */
-# ifndef WT_CTL_DMA
-# define WT_CTL_DMA WT_CTL_DMA1
-# endif
-
-/*******************/
-
-#else /* !CONFIG_QIC02_DYNCONF */
-
-/* Now the runtime config version, using variables instead of constants.
- *
- * qic02_tape_dynconf is R/O for the kernel, set from userspace.
- * qic02_tape_ccb is private to the driver, R/W.
- */
-
-# define QIC02_TAPE_DRIVE (qic02_tape_dynconf.mt_type)
-# define QIC02_TAPE_IFC (qic02_tape_ccb.ifc_type)
-# define QIC02_TAPE_IRQ (qic02_tape_dynconf.irqnr)
-# define QIC02_TAPE_DMA (qic02_tape_dynconf.dmanr)
-# define QIC02_TAPE_PORT (qic02_tape_dynconf.port)
-# define WT_CTL_DMA (qic02_tape_ccb.dma_enable_value)
-# define QIC02_TAPE_DEBUG (qic02_tape_dynconf.debug)
-
-# define QIC02_STAT_PORT (qic02_tape_ccb.port_stat)
-# define QIC02_CTL_PORT (qic02_tape_ccb.port_ctl)
-# define QIC02_CMD_PORT (qic02_tape_ccb.port_cmd)
-# define QIC02_DATA_PORT (qic02_tape_ccb.port_data)
-
-# define QIC02_STAT_POLARITY (qic02_tape_ccb.stat_polarity)
-# define QIC02_STAT_READY (qic02_tape_ccb.stat_ready)
-# define QIC02_STAT_EXCEPTION (qic02_tape_ccb.stat_exception)
-# define QIC02_STAT_MASK (qic02_tape_ccb.stat_mask)
-
-# define QIC02_STAT_RESETMASK (qic02_tape_ccb.stat_resetmask)
-# define QIC02_STAT_RESETVAL (qic02_tape_ccb.stat_resetval)
-
-# define QIC02_CTL_RESET (qic02_tape_ccb.ctl_reset)
-# define QIC02_CTL_REQUEST (qic02_tape_ccb.ctl_request)
-
-# define TP_HAVE_DENS (qic02_tape_dynconf.have_dens)
-# define TP_HAVE_BSF (qic02_tape_dynconf.have_bsf)
-# define TP_HAVE_FSR (qic02_tape_dynconf.have_fsr)
-# define TP_HAVE_BSR (qic02_tape_dynconf.have_bsr)
-# define TP_HAVE_EOD (qic02_tape_dynconf.have_eod)
-# define TP_HAVE_SEEK (qic02_tape_dynconf.have_seek)
-# define TP_HAVE_TELL (qic02_tape_dynconf.have_tell)
-# define TP_HAVE_RAS1 (qic02_tape_dynconf.have_ras1)
-# define TP_HAVE_RAS2 (qic02_tape_dynconf.have_ras2)
-
-#endif /* CONFIG_QIC02_DYNCONF */
-
-
-/* "Vendor Unique" codes */
-/* Archive seek & tell stuff */
-#define AR_QCMDV_TELL_BLK 0xAE /* read current block address */
-#define AR_QCMDV_SEEK_BLK 0xAD /* seek to specific block */
-#define AR_SEEK_BUF_SIZE 3 /* address is 3 bytes */
-
-
-
-/*
- * Misc common stuff
- */
-
-/* Standard QIC-02 commands -- rev F. All QIC-02 drives must support these */
-#define QCMD_SEL_1 0x01 /* select drive 1 */
-#define QCMD_SEL_2 0x02 /* select drive 2 */
-#define QCMD_SEL_3 0x04 /* select drive 3 */
-#define QCMD_SEL_4 0x08 /* select drive 4 */
-#define QCMD_REWIND 0x21 /* rewind tape */
-#define QCMD_ERASE 0x22 /* erase tape */
-#define QCMD_RETEN 0x24 /* retension tape */
-#define QCMD_WRT_DATA 0x40 /* write data */
-#define QCMD_WRT_FM 0x60 /* write file mark */
-#define QCMD_RD_DATA 0x80 /* read data */
-#define QCMD_RD_FM 0xA0 /* read file mark (forward direction) */
-#define QCMD_RD_STAT 0xC0 /* read status */
-
-/* Other (optional/vendor unique) commands */
- /* Density commands are only valid when TP_BOM is set! */
-#define QCMD_DENS_11 0x26 /* QIC-11 */
-#define QCMD_DENS_24 0x27 /* QIC-24: 9 track 60MB */
-#define QCMD_DENS_120 0x28 /* QIC-120: 15 track 120MB */
-#define QCMD_DENS_150 0x29 /* QIC-150: 18 track 150MB */
-#define QCMD_DENS_300 0x2A /* QIC-300/QIC-2100 */
-#define QCMD_DENS_600 0x2B /* QIC-600/QIC-2200 */
-/* don't know about QIC-1000 and QIC-1350 */
-
-#define QCMD_WRTNU_DATA 0x40 /* write data, no underruns, insert filler. */
-#define QCMD_SPACE_FWD 0x81 /* skip next block */
-#define QCMD_SPACE_BCK 0x89 /* move tape head one block back -- very useful! */
-#define QCMD_RD_FM_BCK 0xA8 /* read filemark (backwards) */
-#define QCMD_SEEK_EOD 0xA3 /* skip to EOD */
-#define QCMD_RD_STAT_X1 0xC1 /* read extended status 1 */
-#define QCMD_RD_STAT_X2 0xC4 /* read extended status 2 */
-#define QCMD_RD_STAT_X3 0xE0 /* read extended status 3 */
-#define QCMD_SELF_TST1 0xC2 /* run self test 1 (nondestructive) */
-#define QCMD_SELF_TST2 0xCA /* run self test 2 (destructive) */
-
-
-
-/* Optional, QFA (Quick File Access) commands.
- * Not all drives support this, but those that do could use these commands
- * to implement semi-non-sequential access. `mt fsf` would benefit from this.
- * QFA divides the tape into 2 partitions, a data and a directory partition,
- * causing some incompatibility problems wrt std QIC-02 data exchange.
- * It would be useful to cache the directory info, but that might be tricky
- * to do in kernel-space. [Size constraints.]
- * Refer to the QIC-02 specs, appendix A for more information.
- * I have no idea how other *nix variants implement QFA.
- * I have no idea which drives support QFA and which don't.
- */
-#define QFA_ENABLE 0x2D /* enter QFA mode, give @ BOT only */
-#define QFA_DATA 0x20 /* select data partition */
-#define QFA_DIR 0x23 /* select directory partition */
-#define QFA_RD_POS 0xCF /* read position+status bytes */
-#define QFA_SEEK_EOD 0xA1 /* seek EOD within current partition */
-#define QFA_SEEK_BLK 0xAF /* seek to a block within current partition */
-
-
-
-
-/*
- * Debugging flags
- */
-#define TPQD_SENSE_TEXT 0x0001
-#define TPQD_SENSE_CNTS 0x0002
-#define TPQD_REWIND 0x0004
-#define TPQD_TERM_CYCLE 0x0008
-#define TPQD_IOCTLS 0x0010
-#define TPQD_DMAX 0x0020
-#define TPQD_BLKSZ 0x0040
-#define TPQD_MISC 0x0080
-
-#define TPQD_DEBUG 0x0100
-
-#define TPQD_DIAGS 0x1000
-
-#define TPQD_ALWAYS 0x8000
-
-#define TPQD_DEFAULT_FLAGS 0x00fc
-
-
-#define TPQDBG(f) ((QIC02_TAPE_DEBUG) & (TPQD_##f))
-
-
-/* Minor device codes for tapes:
- * |7|6|5|4|3|2|1|0|
- * | \ | / \ | / |_____ 1=rewind on close, 0=no rewind on close
- * | \|/ |_________ Density: 000=none, 001=QIC-11, 010=24, 011=120,
- * | | 100=QIC-150, 101..111 reserved.
- * | |_______________ Reserved for unit numbers.
- * |___________________ Reserved for diagnostics during debugging.
- */
-
-#define TP_REWCLOSE(d) ((d)&1) /* rewind bit */
- /* rewind is only done if data has been transferred */
-#define TP_DENS(d) (((d) >> 1) & 0x07) /* tape density */
-#define TP_UNIT(d) (((d) >> 4) & 0x07) /* unit number */
-
-/* print excessive diagnostics */
-#define TP_DIAGS(dev) (QIC02_TAPE_DEBUG & TPQD_DIAGS)
-
-/* status codes returned by a WTS_RDSTAT call */
-struct tpstatus { /* sizeof(short)==2), LSB first */
- unsigned short exs; /* Drive exception flags */
- unsigned short dec; /* data error count: nr of blocks rewritten/soft read errors */
- unsigned short urc; /* underrun count: nr of times streaming was interrupted */
-};
-#define TPSTATSIZE sizeof(struct tpstatus)
-
-
-/* defines for tpstatus.exs -- taken from 386BSD wt driver */
-#define TP_POR 0x100 /* Power on or reset occurred */
-#define TP_EOR 0x200 /* REServed for end of RECORDED media */
-#define TP_PAR 0x400 /* REServed for bus parity */
-#define TP_BOM 0x800 /* Beginning of media */
-#define TP_MBD 0x1000 /* Marginal block detected */
-#define TP_NDT 0x2000 /* No data detected */
-#define TP_ILL 0x4000 /* Illegal command */
-#define TP_ST1 0x8000 /* Status byte 1 flag */
-#define TP_FIL 0x01 /* File mark detected */
-#define TP_BNL 0x02 /* Bad block not located */
-#define TP_UDA 0x04 /* Unrecoverable data error */
-#define TP_EOM 0x08 /* End of media */
-#define TP_WRP 0x10 /* Write protected cartridge */
-#define TP_USL 0x20 /* Unselected drive */
-#define TP_CNI 0x40 /* Cartridge not in place */
-#define TP_ST0 0x80 /* Status byte 0 flag */
-
-#define REPORT_ERR0 (TP_CNI|TP_USL|TP_WRP|TP_EOM|TP_UDA|TP_BNL|TP_FIL)
-#define REPORT_ERR1 (TP_ILL|TP_NDT|TP_MBD|TP_PAR)
-
-
-/* exception numbers */
-#define EXC_UNKNOWN 0 /* (extra) Unknown exception code */
-#define EXC_NDRV 1 /* No drive */
-#define EXC_NCART 2 /* No cartridge */
-#define EXC_WP 3 /* Write protected */
-#define EXC_EOM 4 /* EOM */
-#define EXC_RWA 5 /* read/write abort */
-#define EXC_XBAD 6 /* read error, bad block transferred */
-#define EXC_XFILLER 7 /* read error, filler block transferred */
-#define EXC_NDT 8 /* read error, no data */
-#define EXC_NDTEOM 9 /* read error, no data & EOM */
-#define EXC_NDTBOM 10 /* read error, no data & BOM */
-#define EXC_FM 11 /* Read a filemark */
-#define EXC_ILL 12 /* Illegal command */
-#define EXC_POR 13 /* Power on/reset */
-#define EXC_MARGINAL 14 /* Marginal block detected */
-#define EXC_EOR 15 /* (extra, for SEEKEOD) End Of Recorded data reached */
-#define EXC_BOM 16 /* (extra) BOM reached */
-
-
-#define TAPE_NOTIFY_TIMEOUT 1000000
-
-/* internal function return codes */
-#define TE_OK 0 /* everything is fine */
-#define TE_EX 1 /* exception detected */
-#define TE_ERR 2 /* some error */
-#define TE_NS 3 /* can't read status */
-#define TE_TIM 4 /* timed out */
-#define TE_DEAD 5 /* tape drive doesn't respond */
-#define TE_END 6 /******** Archive hack *****/
-
-/* timeout timer values -- check these! */
-#define TIM_S (4*HZ) /* 4 seconds (normal cmds) */
-#define TIM_M (30*HZ) /* 30 seconds (write FM) */
-#define TIM_R (8*60*HZ) /* 8 minutes (retensioning) */
-#define TIM_F (2*3600*HZ) /* est. 1.2hr for full tape read/write+2 retens */
-
-#define TIMERON(t) mod_timer(&tp_timer, jiffies + (t))
-#define TIMEROFF del_timer_sync(&tp_timer);
-#define TIMERCONT add_timer(&tp_timer);
-
-
-typedef char flag;
-#define NO 0 /* NO must be 0 */
-#define YES 1 /* YES must be != 0 */
-
-
-#ifdef TDEBUG
-# define TPQDEB(s) s
-# define TPQPUTS(s) tpqputs(s)
-#else
-# define TPQDEB(s)
-# define TPQPUTS(s)
-#endif
-
-
-/* NR_BLK_BUF is a `tuneable parameter'. If you're really low on
- * kernel space, you could decrease it to 1, or if you got a very
- * slow machine, you could increase it up to 127 blocks. Less kernel
- * buffer blocks result in more context-switching.
- */
-#define NR_BLK_BUF 20 /* max 127 blocks */
-#define TAPE_BLKSIZE 512 /* streamer tape block size (fixed) */
-#define TPQBUF_SIZE (TAPE_BLKSIZE*NR_BLK_BUF) /* buffer size */
-
-
-#define BLOCKS_BEYOND_EW 2 /* nr of blocks after Early Warning hole */
-#define BOGUS_IRQ 32009
-
-
-/* This is internal data, filled in based on the ifc_type field given
- * by the user. Everex is mapped to Wangtek with a different
- * `dma_enable_value', if dmanr==3.
- */
-struct qic02_ccb {
- long ifc_type;
-
- unsigned short port_stat; /* Status port address */
- unsigned short port_ctl; /* Control port address */
- unsigned short port_cmd; /* Command port address */
- unsigned short port_data; /* Data port address */
-
- /* status register bits */
- unsigned short stat_polarity; /* invert status bits or not */
- unsigned short stat_ready; /* drive ready */
- unsigned short stat_exception; /* drive signals exception */
- unsigned short stat_mask;
- unsigned short stat_resetmask;
- unsigned short stat_resetval;
-
- /* control register bits */
- unsigned short ctl_reset; /* reset drive */
- unsigned short ctl_request; /* latch command */
-
- /* This is used to change the DMA3 behaviour */
- unsigned short dma_enable_value;
-};
-
-#if MODULE
-static int qic02_tape_init(void);
-#else
-extern int qic02_tape_init(void); /* for mem.c */
-#endif
-
-
-
-#endif /* CONFIG_QIC02_TAPE */
-
-#endif /* _LINUX_TPQIC02_H */
-
diff --git a/include/linux/transport_class.h b/include/linux/transport_class.h
index 57e60203f1e00..87d98d1faefb2 100644
--- a/include/linux/transport_class.h
+++ b/include/linux/transport_class.h
@@ -48,6 +48,14 @@ struct anon_transport_class cls = { \
#define class_to_transport_class(x) \
container_of(x, struct transport_class, class)
+struct transport_container {
+ struct attribute_container ac;
+ struct attribute_group *statistics;
+};
+
+#define attribute_container_to_transport_container(x) \
+ container_of(x, struct transport_container, ac)
+
void transport_remove_device(struct device *);
void transport_add_device(struct device *);
void transport_setup_device(struct device *);
@@ -68,6 +76,16 @@ transport_unregister_device(struct device *dev)
transport_destroy_device(dev);
}
+static inline int transport_container_register(struct transport_container *tc)
+{
+ return attribute_container_register(&tc->ac);
+}
+
+static inline int transport_container_unregister(struct transport_container *tc)
+{
+ return attribute_container_unregister(&tc->ac);
+}
+
int transport_class_register(struct transport_class *);
int anon_transport_class_register(struct anon_transport_class *);
void transport_class_unregister(struct transport_class *);
diff --git a/include/linux/uinput.h b/include/linux/uinput.h
index 00bf0d29e360d..4c2c82336d103 100644
--- a/include/linux/uinput.h
+++ b/include/linux/uinput.h
@@ -22,6 +22,9 @@
* Author: Aristeu Sergio Rozanski Filho <aris@cathedrallabs.org>
*
* Changes/Revisions:
+ * 0.2 16/10/2004 (Micah Dowty <micah@navi.cx>)
+ * - added force feedback support
+ * - added UI_SET_PHYS
* 0.1 20/06/2002
* - first public version
*/
@@ -29,10 +32,25 @@
#define UINPUT_MINOR 223
#define UINPUT_NAME "uinput"
#define UINPUT_BUFFER_SIZE 16
+#define UINPUT_NUM_REQUESTS 16
/* state flags => bit index for {set|clear|test}_bit ops */
#define UIST_CREATED 0
+struct uinput_request {
+ int id;
+ int code; /* UI_FF_UPLOAD, UI_FF_ERASE */
+
+ int retval;
+ wait_queue_head_t waitq;
+ int completed;
+
+ union {
+ int effect_id;
+ struct ff_effect* effect;
+ } u;
+};
+
struct uinput_device {
struct input_dev *dev;
unsigned long state;
@@ -41,13 +59,30 @@ struct uinput_device {
head,
tail;
struct input_event buff[UINPUT_BUFFER_SIZE];
+
+ struct uinput_request *requests[UINPUT_NUM_REQUESTS];
+ wait_queue_head_t requests_waitq;
+ struct semaphore requests_sem;
};
#endif /* __KERNEL__ */
+struct uinput_ff_upload {
+ int request_id;
+ int retval;
+ struct ff_effect effect;
+};
+
+struct uinput_ff_erase {
+ int request_id;
+ int retval;
+ int effect_id;
+};
+
/* ioctl */
#define UINPUT_IOCTL_BASE 'U'
#define UI_DEV_CREATE _IO(UINPUT_IOCTL_BASE, 1)
#define UI_DEV_DESTROY _IO(UINPUT_IOCTL_BASE, 2)
+
#define UI_SET_EVBIT _IOW(UINPUT_IOCTL_BASE, 100, int)
#define UI_SET_KEYBIT _IOW(UINPUT_IOCTL_BASE, 101, int)
#define UI_SET_RELBIT _IOW(UINPUT_IOCTL_BASE, 102, int)
@@ -56,6 +91,63 @@ struct uinput_device {
#define UI_SET_LEDBIT _IOW(UINPUT_IOCTL_BASE, 105, int)
#define UI_SET_SNDBIT _IOW(UINPUT_IOCTL_BASE, 106, int)
#define UI_SET_FFBIT _IOW(UINPUT_IOCTL_BASE, 107, int)
+#define UI_SET_PHYS _IOW(UINPUT_IOCTL_BASE, 108, char*)
+
+#define UI_BEGIN_FF_UPLOAD _IOWR(UINPUT_IOCTL_BASE, 200, struct uinput_ff_upload)
+#define UI_END_FF_UPLOAD _IOW(UINPUT_IOCTL_BASE, 201, struct uinput_ff_upload)
+#define UI_BEGIN_FF_ERASE _IOWR(UINPUT_IOCTL_BASE, 202, struct uinput_ff_erase)
+#define UI_END_FF_ERASE _IOW(UINPUT_IOCTL_BASE, 203, struct uinput_ff_erase)
+
+/* To write a force-feedback-capable driver, the upload_effect
+ * and erase_effect callbacks in input_dev must be implemented.
+ * The uinput driver will generate a fake input event when one of
+ * these callbacks are invoked. The userspace code then uses
+ * ioctls to retrieve additional parameters and send the return code.
+ * The callback blocks until this return code is sent.
+ *
+ * The described callback mechanism is only used if EV_FF is set.
+ * Otherwise, default implementations of upload_effect and erase_effect
+ * are used.
+ *
+ * To implement upload_effect():
+ * 1. Wait for an event with type==EV_UINPUT and code==UI_FF_UPLOAD.
+ * A request ID will be given in 'value'.
+ * 2. Allocate a uinput_ff_upload struct, fill in request_id with
+ * the 'value' from the EV_UINPUT event.
+ * 3. Issue a UI_BEGIN_FF_UPLOAD ioctl, giving it the
+ * uinput_ff_upload struct. It will be filled in with the
+ * ff_effect passed to upload_effect().
+ * 4. Perform the effect upload, and place the modified ff_effect
+ * and a return code back into the uinput_ff_upload struct.
+ * 5. Issue a UI_END_FF_UPLOAD ioctl, also giving it the
+ * uinput_ff_upload_effect struct. This will complete execution
+ * of our upload_effect() handler.
+ *
+ * To implement erase_effect():
+ * 1. Wait for an event with type==EV_UINPUT and code==UI_FF_ERASE.
+ * A request ID will be given in 'value'.
+ * 2. Allocate a uinput_ff_erase struct, fill in request_id with
+ * the 'value' from the EV_UINPUT event.
+ * 3. Issue a UI_BEGIN_FF_ERASE ioctl, giving it the
+ * uinput_ff_erase struct. It will be filled in with the
+ * effect ID passed to erase_effect().
+ * 4. Perform the effect erasure, and place a return code back
+ * into the uinput_ff_erase struct.
+ * and a return code back into the uinput_ff_erase struct.
+ * 5. Issue a UI_END_FF_ERASE ioctl, also giving it the
+ * uinput_ff_erase_effect struct. This will complete execution
+ * of our erase_effect() handler.
+ */
+
+/* This is the new event type, used only by uinput.
+ * 'code' is UI_FF_UPLOAD or UI_FF_ERASE, and 'value'
+ * is the unique request ID. This number was picked
+ * arbitrarily, above EV_MAX (since the input system
+ * never sees it) but in the range of a 16-bit int.
+ */
+#define EV_UINPUT 0x0101
+#define UI_FF_UPLOAD 1
+#define UI_FF_ERASE 2
#ifndef NBITS
#define NBITS(x) ((((x)-1)/(sizeof(long)*8))+1)
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 7dbcc054c7dcf..c96728435935b 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -70,6 +70,7 @@ struct usb_host_interface {
*/
struct usb_host_endpoint *endpoint;
+ char *string; /* iInterface string, if present */
unsigned char *extra; /* Extra descriptors */
int extralen;
};
@@ -189,6 +190,8 @@ struct usb_interface_cache {
/**
* struct usb_host_config - representation of a device's configuration
* @desc: the device's configuration descriptor.
+ * @string: pointer to the cached version of the iConfiguration string, if
+ * present for this configuration.
* @interface: array of pointers to usb_interface structures, one for each
* interface in the configuration. The number of interfaces is stored
* in desc.bNumInterfaces. These pointers are valid only while the
@@ -225,6 +228,7 @@ struct usb_interface_cache {
struct usb_host_config {
struct usb_config_descriptor desc;
+ char *string;
/* the interfaces associated with this configuration,
* stored in no particular order */
struct usb_interface *interface[USB_MAXINTERFACES];
@@ -285,6 +289,10 @@ struct usb_bus {
struct class_device class_dev; /* class device for this bus */
void (*release)(struct usb_bus *bus); /* function to destroy this bus's memory */
+#if defined(CONFIG_USB_MON) || defined(CONFIG_USB_MON_MODULE)
+ struct mon_bus *mon_bus; /* non-null when associated */
+ int monitored; /* non-zero when monitored */
+#endif
};
#define to_usb_bus(d) container_of(d, struct usb_bus, class_dev)
@@ -338,6 +346,9 @@ struct usb_device {
int have_langid; /* whether string_langid is valid yet */
int string_langid; /* language ID for strings */
+ char *product;
+ char *manufacturer;
+ char *serial; /* static strings from the device */
struct list_head filelist;
struct dentry *usbfs_dentry; /* usbfs dentry entry for the device */
@@ -938,11 +949,11 @@ void *usb_buffer_alloc (struct usb_device *dev, size_t size,
void usb_buffer_free (struct usb_device *dev, size_t size,
void *addr, dma_addr_t dma);
-struct urb *usb_buffer_map (struct urb *urb);
#if 0
+struct urb *usb_buffer_map (struct urb *urb);
void usb_buffer_dmasync (struct urb *urb);
-#endif
void usb_buffer_unmap (struct urb *urb);
+#endif
struct scatterlist;
int usb_buffer_map_sg (struct usb_device *dev, unsigned pipe,
@@ -986,13 +997,13 @@ extern int usb_reset_configuration(struct usb_device *dev);
extern int usb_set_interface(struct usb_device *dev, int ifnum, int alternate);
/*
- * timeouts, in seconds, used for sending/receiving control messages
+ * timeouts, in milliseconds, used for sending/receiving control messages
* they typically complete within a few frames (msec) after they're issued
* USB identifies 5 second timeouts, maybe more in a few cases, and a few
* slow devices (like some MGE Ellipse UPSes) actually push that limit.
*/
-#define USB_CTRL_GET_TIMEOUT 5
-#define USB_CTRL_SET_TIMEOUT 5
+#define USB_CTRL_GET_TIMEOUT 5000
+#define USB_CTRL_SET_TIMEOUT 5000
/**
diff --git a/include/linux/usb_cdc.h b/include/linux/usb_cdc.h
new file mode 100644
index 0000000000000..1b68c122279a8
--- /dev/null
+++ b/include/linux/usb_cdc.h
@@ -0,0 +1,192 @@
+/*
+ * USB Communications Device Class (CDC) definitions
+ *
+ * CDC says how to talk to lots of different types of network adapters,
+ * notably ethernet adapters and various modems. It's used mostly with
+ * firmware based USB peripherals.
+ */
+
+#define USB_CDC_SUBCLASS_ACM 0x02
+#define USB_CDC_SUBCLASS_ETHERNET 0x06
+#define USB_CDC_SUBCLASS_WHCM 0x08
+#define USB_CDC_SUBCLASS_DMM 0x09
+#define USB_CDC_SUBCLASS_MDLM 0x0a
+#define USB_CDC_SUBCLASS_OBEX 0x0b
+
+#define USB_CDC_PROTO_NONE 0
+
+#define USB_CDC_ACM_PROTO_AT_V25TER 1
+#define USB_CDC_ACM_PROTO_AT_PCCA101 2
+#define USB_CDC_ACM_PROTO_AT_PCCA101_WAKE 3
+#define USB_CDC_ACM_PROTO_AT_GSM 4
+#define USB_CDC_ACM_PROTO_AT_3G 5
+#define USB_CDC_ACM_PROTO_AT_CDMA 6
+#define USB_CDC_ACM_PROTO_VENDOR 0xff
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * Class-Specific descriptors ... there are a couple dozen of them
+ */
+
+#define USB_CDC_HEADER_TYPE 0x00 /* header_desc */
+#define USB_CDC_CALL_MANAGEMENT_TYPE 0x01 /* call_mgmt_descriptor */
+#define USB_CDC_ACM_TYPE 0x02 /* acm_descriptor */
+#define USB_CDC_UNION_TYPE 0x06 /* union_desc */
+#define USB_CDC_COUNTRY_TYPE 0x07
+#define USB_CDC_ETHERNET_TYPE 0x0f /* ether_desc */
+#define USB_CDC_WHCM_TYPE 0x11
+#define USB_CDC_MDLM_TYPE 0x12 /* mdlm_desc */
+#define USB_CDC_MDLM_DETAIL_TYPE 0x13 /* mdlm_detail_desc */
+#define USB_CDC_DMM_TYPE 0x14
+#define USB_CDC_OBEX_TYPE 0x15
+
+/* "Header Functional Descriptor" from CDC spec 5.2.3.1 */
+struct usb_cdc_header_desc {
+ __u8 bLength;
+ __u8 bDescriptorType;
+ __u8 bDescriptorSubType;
+
+ __le16 bcdCDC;
+} __attribute__ ((packed));
+
+/* "Call Management Descriptor" from CDC spec 5.2.3.2 */
+struct usb_cdc_call_mgmt_descriptor {
+ __u8 bLength;
+ __u8 bDescriptorType;
+ __u8 bDescriptorSubType;
+
+ __u8 bmCapabilities;
+#define USB_CDC_CALL_MGMT_CAP_CALL_MGMT 0x01
+#define USB_CDC_CALL_MGMT_CAP_DATA_INTF 0x02
+
+ __u8 bDataInterface;
+} __attribute__ ((packed));
+
+/* "Abstract Control Management Descriptor" from CDC spec 5.2.3.3 */
+struct usb_cdc_acm_descriptor {
+ __u8 bLength;
+ __u8 bDescriptorType;
+ __u8 bDescriptorSubType;
+
+ __u8 bmCapabilities;
+} __attribute__ ((packed));
+
+/* "Union Functional Descriptor" from CDC spec 5.2.3.8 */
+struct usb_cdc_union_desc {
+ __u8 bLength;
+ __u8 bDescriptorType;
+ __u8 bDescriptorSubType;
+
+ __u8 bMasterInterface0;
+ __u8 bSlaveInterface0;
+ /* ... and there could be other slave interfaces */
+} __attribute__ ((packed));
+
+/* "Ethernet Networking Functional Descriptor" from CDC spec 5.2.3.16 */
+struct usb_cdc_ether_desc {
+ __u8 bLength;
+ __u8 bDescriptorType;
+ __u8 bDescriptorSubType;
+
+ __u8 iMACAddress;
+ __le32 bmEthernetStatistics;
+ __le16 wMaxSegmentSize;
+ __le16 wNumberMCFilters;
+ __u8 bNumberPowerFilters;
+} __attribute__ ((packed));
+
+/* "MDLM Functional Descriptor" from CDC WMC spec 6.7.2.3 */
+struct usb_cdc_mdlm_desc {
+ __u8 bLength;
+ __u8 bDescriptorType;
+ __u8 bDescriptorSubType;
+
+ __le16 bcdVersion;
+ __u8 bGUID[16];
+} __attribute__ ((packed));
+
+/* "MDLM Detail Functional Descriptor" from CDC WMC spec 6.7.2.4 */
+struct usb_cdc_mdlm_detail_desc {
+ __u8 bLength;
+ __u8 bDescriptorType;
+ __u8 bDescriptorSubType;
+
+ /* type is associated with mdlm_desc.bGUID */
+ __u8 bGuidDescriptorType;
+ __u8 bDetailData[];
+} __attribute__ ((packed));
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * Class-Specific Control Requests (6.2)
+ *
+ * section 3.6.2.1 table 4 has the ACM profile, for modems.
+ * section 3.8.2 table 10 has the ethernet profile.
+ *
+ * Microsoft's RNDIS stack for Ethernet is a vendor-specific CDC ACM variant,
+ * heavily dependent on the encapsulated (proprietary) command mechanism.
+ */
+
+#define USB_CDC_SEND_ENCAPSULATED_COMMAND 0x00
+#define USB_CDC_GET_ENCAPSULATED_RESPONSE 0x01
+#define USB_CDC_REQ_SET_LINE_CODING 0x20
+#define USB_CDC_REQ_GET_LINE_CODING 0x21
+#define USB_CDC_REQ_SET_CONTROL_LINE_STATE 0x22
+#define USB_CDC_REQ_SEND_BREAK 0x23
+#define USB_CDC_SET_ETHERNET_MULTICAST_FILTERS 0x40
+#define USB_CDC_SET_ETHERNET_PM_PATTERN_FILTER 0x41
+#define USB_CDC_GET_ETHERNET_PM_PATTERN_FILTER 0x42
+#define USB_CDC_SET_ETHERNET_PACKET_FILTER 0x43
+#define USB_CDC_GET_ETHERNET_STATISTIC 0x44
+
+/* Line Coding Structure from CDC spec 6.2.13 */
+struct usb_cdc_line_coding {
+ __le32 dwDTERate;
+ __u8 bCharFormat;
+#define USB_CDC_1_STOP_BITS 0
+#define USB_CDC_1_5_STOP_BITS 1
+#define USB_CDC_2_STOP_BITS 2
+
+ __u8 bParityType;
+#define USB_CDC_NO_PARITY 0
+#define USB_CDC_ODD_PARITY 1
+#define USB_CDC_EVEN_PARITY 2
+#define USB_CDC_MARK_PARITY 3
+#define USB_CDC_SPACE_PARITY 4
+
+ __u8 bDataBits;
+} __attribute__ ((packed));
+
+/* table 62; bits in multicast filter */
+#define USB_CDC_PACKET_TYPE_PROMISCUOUS (1 << 0)
+#define USB_CDC_PACKET_TYPE_ALL_MULTICAST (1 << 1) /* no filter */
+#define USB_CDC_PACKET_TYPE_DIRECTED (1 << 2)
+#define USB_CDC_PACKET_TYPE_BROADCAST (1 << 3)
+#define USB_CDC_PACKET_TYPE_MULTICAST (1 << 4) /* filtered */
+
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * Class-Specific Notifications (6.3) sent by interrupt transfers
+ *
+ * section 3.8.2 table 11 of the CDC spec lists Ethernet notifications
+ * section 3.6.2.1 table 5 specifies ACM notifications, accepted by RNDIS
+ * RNDIS also defines its own bit-incompatible notifications
+ */
+
+#define USB_CDC_NOTIFY_NETWORK_CONNECTION 0x00
+#define USB_CDC_NOTIFY_RESPONSE_AVAILABLE 0x01
+#define USB_CDC_NOTIFY_SERIAL_STATE 0x20
+#define USB_CDC_NOTIFY_SPEED_CHANGE 0x2a
+
+struct usb_cdc_notification {
+ __u8 bmRequestType;
+ __u8 bNotificationType;
+ __le16 wValue;
+ __le16 wIndex;
+ __le16 wLength;
+} __attribute__ ((packed));
+
diff --git a/include/linux/usbdevice_fs.h b/include/linux/usbdevice_fs.h
index aed8193eb4201..fb57c22174682 100644
--- a/include/linux/usbdevice_fs.h
+++ b/include/linux/usbdevice_fs.h
@@ -32,6 +32,7 @@
#define _LINUX_USBDEVICE_FS_H
#include <linux/types.h>
+#include <linux/compat.h>
/* --------------------------------------------------------------------- */
@@ -123,6 +124,24 @@ struct usbdevfs_hub_portinfo {
char port [127]; /* e.g. port 3 connects to device 27 */
};
+#ifdef CONFIG_COMPAT
+struct usbdevfs_urb32 {
+ unsigned char type;
+ unsigned char endpoint;
+ compat_int_t status;
+ compat_uint_t flags;
+ compat_caddr_t buffer;
+ compat_int_t buffer_length;
+ compat_int_t actual_length;
+ compat_int_t start_frame;
+ compat_int_t number_of_packets;
+ compat_int_t error_count;
+ compat_uint_t signr;
+ compat_caddr_t usercontext; /* unused */
+ struct usbdevfs_iso_packet_desc iso_frame_desc[0];
+};
+#endif
+
#define USBDEVFS_CONTROL _IOWR('U', 0, struct usbdevfs_ctrltransfer)
#define USBDEVFS_BULK _IOWR('U', 2, struct usbdevfs_bulktransfer)
#define USBDEVFS_RESETEP _IOR('U', 3, unsigned int)
@@ -130,9 +149,12 @@ struct usbdevfs_hub_portinfo {
#define USBDEVFS_SETCONFIGURATION _IOR('U', 5, unsigned int)
#define USBDEVFS_GETDRIVER _IOW('U', 8, struct usbdevfs_getdriver)
#define USBDEVFS_SUBMITURB _IOR('U', 10, struct usbdevfs_urb)
+#define USBDEVFS_SUBMITURB32 _IOR('U', 10, struct usbdevfs_urb32)
#define USBDEVFS_DISCARDURB _IO('U', 11)
#define USBDEVFS_REAPURB _IOW('U', 12, void *)
+#define USBDEVFS_REAPURB32 _IOW('U', 12, u32)
#define USBDEVFS_REAPURBNDELAY _IOW('U', 13, void *)
+#define USBDEVFS_REAPURBNDELAY32 _IOW('U', 13, u32)
#define USBDEVFS_DISCSIGNAL _IOR('U', 14, struct usbdevfs_disconnectsignal)
#define USBDEVFS_CLAIMINTERFACE _IOR('U', 15, unsigned int)
#define USBDEVFS_RELEASEINTERFACE _IOR('U', 16, unsigned int)
@@ -143,5 +165,4 @@ struct usbdevfs_hub_portinfo {
#define USBDEVFS_CLEAR_HALT _IOR('U', 21, unsigned int)
#define USBDEVFS_DISCONNECT _IO('U', 22)
#define USBDEVFS_CONNECT _IO('U', 23)
-
#endif /* _LINUX_USBDEVICE_FS_H */
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index 68a5ce4fcb4b7..4e0edce537601 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -268,64 +268,92 @@ struct v4l2_timecode
/* The above is based on SMPTE timecodes */
+#if 1
/*
- * C O M P R E S S I O N P A R A M E T E R S
+ * M P E G C O M P R E S S I O N P A R A M E T E R S
+ *
+ * ### WARNING: this is still work-in-progress right now, most likely
+ * ### there will be some incompatible changes.
+ *
*/
-#if 0
-/* ### generic compression settings don't work, there is too much
- * ### codec-specific stuff. Maybe reuse that for MPEG codec settings
- * ### later ... */
-struct v4l2_compression
-{
- __u32 quality;
- __u32 keyframerate;
- __u32 pframerate;
- __u32 reserved[5];
-
-/* what we'll need for MPEG, extracted from some postings on
- the v4l list (Gert Vervoort, PlasmaJohn).
-
-system stream:
- - type: elementary stream(ES), packatised elementary stream(s) (PES)
- program stream(PS), transport stream(TS)
- - system bitrate
- - PS packet size (DVD: 2048 bytes, VCD: 2324 bytes)
- - TS video PID
- - TS audio PID
- - TS PCR PID
- - TS system information tables (PAT, PMT, CAT, NIT and SIT)
- - (MPEG-1 systems stream vs. MPEG-2 program stream (TS not supported
- by MPEG-1 systems)
-
-audio:
- - type: MPEG (+Layer I,II,III), AC-3, LPCM
- - bitrate
- - sampling frequency (DVD: 48 Khz, VCD: 44.1 KHz, 32 kHz)
- - Trick Modes? (ff, rew)
- - Copyright
- - Inverse Telecine
-
-video:
- - picturesize (SIF, 1/2 D1, 2/3 D1, D1) and PAL/NTSC norm can be set
- through excisting V4L2 controls
- - noise reduction, parameters encoder specific?
- - MPEG video version: MPEG-1, MPEG-2
- - GOP (Group Of Pictures) definition:
- - N: number of frames per GOP
- - M: distance between reference (I,P) frames
- - open/closed GOP
- - quantiser matrix: inter Q matrix (64 bytes) and intra Q matrix (64 bytes)
- - quantiser scale: linear or logarithmic
- - scanning: alternate or zigzag
- - bitrate mode: CBR (constant bitrate) or VBR (variable bitrate).
- - target video bitrate for CBR
- - target video bitrate for VBR
- - maximum video bitrate for VBR - min. quantiser value for VBR
- - max. quantiser value for VBR
- - adaptive quantisation value
- - return the number of bytes per GOP or bitrate for bitrate monitoring
-
-*/
+
+
+enum v4l2_bitrate_mode {
+ V4L2_BITRATE_NONE = 0, /* not specified */
+ V4L2_BITRATE_CBR, /* constant bitrate */
+ V4L2_BITRATE_VBR, /* variable bitrate */
+};
+struct v4l2_bitrate {
+ /* rates are specified in kbit/sec */
+ enum v4l2_bitrate_mode mode;
+ __u32 min;
+ __u32 target; /* use this one for CBR */
+ __u32 max;
+};
+
+enum v4l2_mpeg_streamtype {
+ V4L2_MPEG_SS_1, /* MPEG-1 system stream */
+ V4L2_MPEG_PS_2, /* MPEG-2 program stream */
+ V4L2_MPEG_TS_2, /* MPEG-2 transport stream */
+ V4L2_MPEG_PS_DVD, /* MPEG-2 program stream with DVD header fixups */
+};
+enum v4l2_mpeg_audiotype {
+ V4L2_MPEG_AU_2_I, /* MPEG-2 layer 1 */
+ V4L2_MPEG_AU_2_II, /* MPEG-2 layer 2 */
+ V4L2_MPEG_AU_2_III, /* MPEG-2 layer 3 */
+ V4L2_MPEG_AC3, /* AC3 */
+ V4L2_MPEG_LPCM, /* LPCM */
+};
+enum v4l2_mpeg_videotype {
+ V4L2_MPEG_VI_1, /* MPEG-1 */
+ V4L2_MPEG_VI_2, /* MPEG-2 */
+};
+enum v4l2_mpeg_aspectratio {
+ V4L2_MPEG_ASPECT_SQUARE = 1, /* square pixel */
+ V4L2_MPEG_ASPECT_4_3 = 2, /* 4 : 3 */
+ V4L2_MPEG_ASPECT_16_9 = 3, /* 16 : 9 */
+ V4L2_MPEG_ASPECT_1_221 = 4, /* 1 : 2,21 */
+};
+
+struct v4l2_mpeg_compression {
+ /* general */
+ enum v4l2_mpeg_streamtype st_type;
+ struct v4l2_bitrate st_bitrate;
+
+ /* transport streams */
+ __u16 ts_pid_pmt;
+ __u16 ts_pid_audio;
+ __u16 ts_pid_video;
+ __u16 ts_pid_pcr;
+
+ /* program stream */
+ __u16 ps_size;
+ __u16 reserved_1; /* align */
+
+ /* audio */
+ enum v4l2_mpeg_audiotype au_type;
+ struct v4l2_bitrate au_bitrate;
+ __u32 au_sample_rate;
+ __u8 au_pesid;
+ __u8 reserved_2[3]; /* align */
+
+ /* video */
+ enum v4l2_mpeg_videotype vi_type;
+ enum v4l2_mpeg_aspectratio vi_aspect_ratio;
+ struct v4l2_bitrate vi_bitrate;
+ __u32 vi_frame_rate;
+ __u16 vi_frames_per_gop;
+ __u16 vi_bframes_count;
+ __u8 vi_pesid;
+ __u8 reserved_3[3]; /* align */
+
+ /* misc flags */
+ __u32 closed_gops:1;
+ __u32 pulldown:1;
+ __u32 reserved_4:30; /* align */
+
+ /* I don't expect the above being perfect yet ;) */
+ __u32 reserved_5[8];
};
#endif
@@ -841,9 +869,9 @@ struct v4l2_streamparm
#define VIDIOC_ENUM_FMT _IOWR ('V', 2, struct v4l2_fmtdesc)
#define VIDIOC_G_FMT _IOWR ('V', 4, struct v4l2_format)
#define VIDIOC_S_FMT _IOWR ('V', 5, struct v4l2_format)
-#if 0
-#define VIDIOC_G_COMP _IOR ('V', 6, struct v4l2_compression)
-#define VIDIOC_S_COMP _IOW ('V', 7, struct v4l2_compression)
+#if 1 /* experimental */
+#define VIDIOC_G_MPEGCOMP _IOR ('V', 6, struct v4l2_mpeg_compression)
+#define VIDIOC_S_MPEGCOMP _IOW ('V', 7, struct v4l2_mpeg_compression)
#endif
#define VIDIOC_REQBUFS _IOWR ('V', 8, struct v4l2_requestbuffers)
#define VIDIOC_QUERYBUF _IOWR ('V', 9, struct v4l2_buffer)
diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h
index 9af7ad38c08d6..3a358c895188f 100644
--- a/include/linux/vmalloc.h
+++ b/include/linux/vmalloc.h
@@ -26,7 +26,8 @@ struct vm_struct {
extern void *vmalloc(unsigned long size);
extern void *vmalloc_exec(unsigned long size);
extern void *vmalloc_32(unsigned long size);
-extern void *__vmalloc(unsigned long size, int gfp_mask, pgprot_t prot);
+extern void *__vmalloc(unsigned long size, unsigned int __nocast gfp_mask, pgprot_t prot);
+extern void *__vmalloc_area(struct vm_struct *area, unsigned int __nocast gfp_mask, pgprot_t prot);
extern void vfree(void *addr);
extern void *vmap(struct page **pages, unsigned int count,
diff --git a/include/linux/vt_kern.h b/include/linux/vt_kern.h
index 6dbef2f8445a8..fab5aed8ca315 100644
--- a/include/linux/vt_kern.h
+++ b/include/linux/vt_kern.h
@@ -25,15 +25,6 @@
#define BROKEN_GRAPHICS_PROGRAMS 1
#endif
-extern struct vt_struct {
- int vc_num; /* The console number */
- unsigned char vc_mode; /* KD_TEXT, ... */
- struct vt_mode vt_mode;
- int vt_pid;
- int vt_newvt;
- wait_queue_head_t paste_wait;
-} *vt_cons[MAX_NR_CONSOLES];
-
extern void kd_mksound(unsigned int hz, unsigned int ticks);
extern int kbd_rate(struct kbd_repeat *rep);
@@ -41,25 +32,20 @@ extern int kbd_rate(struct kbd_repeat *rep);
int vc_allocate(unsigned int console);
int vc_cons_allocated(unsigned int console);
-int vc_resize(int currcons, unsigned int cols, unsigned int lines);
+int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines);
void vc_disallocate(unsigned int console);
-void reset_palette(int currcons);
-void set_palette(int currcons);
+void reset_palette(struct vc_data *vc);
void do_blank_screen(int entering_gfx);
void do_unblank_screen(int leaving_gfx);
void unblank_screen(void);
void poke_blanked_console(void);
-int con_font_op(int currcons, struct console_font_op *op);
-int con_font_set(int currcons, struct console_font_op *op);
-int con_font_get(int currcons, struct console_font_op *op);
-int con_font_default(int currcons, struct console_font_op *op);
-int con_font_copy(int currcons, struct console_font_op *op);
+int con_font_op(struct vc_data *vc, struct console_font_op *op);
int con_set_cmap(unsigned char __user *cmap);
int con_get_cmap(unsigned char __user *cmap);
-void scrollback(int);
-void scrollfront(int);
-void update_region(int currcons, unsigned long start, int count);
-void redraw_screen(int new_console, int is_switch);
+void scrollback(struct vc_data *vc, int lines);
+void scrollfront(struct vc_data *vc, int lines);
+void update_region(struct vc_data *vc, unsigned long start, int count);
+void redraw_screen(struct vc_data *vc, int is_switch);
#define update_screen(x) redraw_screen(x, 0)
#define switch_screen(x) redraw_screen(x, 1)
@@ -75,25 +61,25 @@ int con_set_trans_old(unsigned char __user * table);
int con_get_trans_old(unsigned char __user * table);
int con_set_trans_new(unsigned short __user * table);
int con_get_trans_new(unsigned short __user * table);
-int con_clear_unimap(int currcons, struct unimapinit *ui);
-int con_set_unimap(int currcons, ushort ct, struct unipair __user *list);
-int con_get_unimap(int currcons, ushort ct, ushort __user *uct, struct unipair __user *list);
-int con_set_default_unimap(int currcons);
-void con_free_unimap(int currcons);
-void con_protect_unimap(int currcons, int rdonly);
-int con_copy_unimap(int dstcons, int srccons);
+int con_clear_unimap(struct vc_data *vc, struct unimapinit *ui);
+int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list);
+int con_get_unimap(struct vc_data *vc, ushort ct, ushort __user *uct, struct unipair __user *list);
+int con_set_default_unimap(struct vc_data *vc);
+void con_free_unimap(struct vc_data *vc);
+void con_protect_unimap(struct vc_data *vc, int rdonly);
+int con_copy_unimap(struct vc_data *dst_vc, struct vc_data *src_vc);
/* vt.c */
-void complete_change_console(unsigned int new_console);
int vt_waitactive(int vt);
-void change_console(unsigned int);
-void reset_vc(unsigned int new_console);
+void change_console(struct vc_data *new_vc);
+void reset_vc(struct vc_data *vc);
/*
* vc_screen.c shares this temporary buffer with the console write code so that
* we can easily avoid touching user space while holding the console spinlock.
*/
-#define CON_BUF_SIZE PAGE_SIZE
+
+#define CON_BUF_SIZE (CONFIG_BASE_SMALL ? 256 : PAGE_SIZE)
extern char con_buf[CON_BUF_SIZE];
extern struct semaphore con_buf_sem;
diff --git a/include/linux/wait.h b/include/linux/wait.h
index ddb0a16f31c91..17c874a8eb3f1 100644
--- a/include/linux/wait.h
+++ b/include/linux/wait.h
@@ -79,7 +79,7 @@ typedef struct __wait_queue_head wait_queue_head_t;
static inline void init_waitqueue_head(wait_queue_head_t *q)
{
- q->lock = SPIN_LOCK_UNLOCKED;
+ spin_lock_init(&q->lock);
INIT_LIST_HEAD(&q->task_list);
}
@@ -169,6 +169,18 @@ do { \
finish_wait(&wq, &__wait); \
} while (0)
+/**
+ * wait_event - sleep until a condition gets true
+ * @wq: the waitqueue to wait on
+ * @condition: a C expression for the event to wait for
+ *
+ * The process is put to sleep (TASK_UNINTERRUPTIBLE) until the
+ * @condition evaluates to true. The @condition is checked each time
+ * the waitqueue @wq is woken up.
+ *
+ * wake_up() has to be called after changing any variable that could
+ * change the result of the wait condition.
+ */
#define wait_event(wq, condition) \
do { \
if (condition) \
@@ -191,6 +203,22 @@ do { \
finish_wait(&wq, &__wait); \
} while (0)
+/**
+ * wait_event_timeout - sleep until a condition gets true or a timeout elapses
+ * @wq: the waitqueue to wait on
+ * @condition: a C expression for the event to wait for
+ * @timeout: timeout, in jiffies
+ *
+ * The process is put to sleep (TASK_UNINTERRUPTIBLE) until the
+ * @condition evaluates to true. The @condition is checked each time
+ * the waitqueue @wq is woken up.
+ *
+ * wake_up() has to be called after changing any variable that could
+ * change the result of the wait condition.
+ *
+ * The function returns 0 if the @timeout elapsed, and the remaining
+ * jiffies if the condition evaluated to true before the timeout elapsed.
+ */
#define wait_event_timeout(wq, condition, timeout) \
({ \
long __ret = timeout; \
@@ -217,6 +245,21 @@ do { \
finish_wait(&wq, &__wait); \
} while (0)
+/**
+ * wait_event_interruptible - sleep until a condition gets true
+ * @wq: the waitqueue to wait on
+ * @condition: a C expression for the event to wait for
+ *
+ * The process is put to sleep (TASK_INTERRUPTIBLE) until the
+ * @condition evaluates to true or a signal is received.
+ * The @condition is checked each time the waitqueue @wq is woken up.
+ *
+ * wake_up() has to be called after changing any variable that could
+ * change the result of the wait condition.
+ *
+ * The function will return -ERESTARTSYS if it was interrupted by a
+ * signal and 0 if @condition evaluated to true.
+ */
#define wait_event_interruptible(wq, condition) \
({ \
int __ret = 0; \
@@ -245,6 +288,23 @@ do { \
finish_wait(&wq, &__wait); \
} while (0)
+/**
+ * wait_event_interruptible_timeout - sleep until a condition gets true or a timeout elapses
+ * @wq: the waitqueue to wait on
+ * @condition: a C expression for the event to wait for
+ * @timeout: timeout, in jiffies
+ *
+ * The process is put to sleep (TASK_INTERRUPTIBLE) until the
+ * @condition evaluates to true or a signal is received.
+ * The @condition is checked each time the waitqueue @wq is woken up.
+ *
+ * wake_up() has to be called after changing any variable that could
+ * change the result of the wait condition.
+ *
+ * The function returns 0 if the @timeout elapsed, -ERESTARTSYS if it
+ * was interrupted by a signal, and the remaining jiffies otherwise
+ * if the condition evaluated to true before the timeout elapsed.
+ */
#define wait_event_interruptible_timeout(wq, condition, timeout) \
({ \
long __ret = timeout; \
diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h
index d37b664363b1c..ff46f537ba9b3 100644
--- a/include/linux/workqueue.h
+++ b/include/linux/workqueue.h
@@ -70,6 +70,7 @@ extern int current_is_keventd(void);
extern int keventd_up(void);
extern void init_workqueues(void);
+void cancel_rearming_delayed_work(struct work_struct *work);
/*
* Kill off a pending schedule_delayed_work(). Note that the work callback
diff --git a/include/linux/writeback.h b/include/linux/writeback.h
index 4ab519ad9f559..1262cb43c3abc 100644
--- a/include/linux/writeback.h
+++ b/include/linux/writeback.h
@@ -86,6 +86,7 @@ static inline void wait_on_inode(struct inode *inode)
int wakeup_bdflush(long nr_pages);
void laptop_io_completion(void);
void laptop_sync_completion(void);
+void throttle_vm_writeout(void);
/* These are exported to sysctl. */
extern int dirty_background_ratio;
diff --git a/include/media/ir-common.h b/include/media/ir-common.h
index bf440248477a5..62c963a52d863 100644
--- a/include/media/ir-common.h
+++ b/include/media/ir-common.h
@@ -1,5 +1,5 @@
/*
- * $Id: ir-common.h,v 1.6 2004/09/15 16:15:24 kraxel Exp $
+ * $Id: ir-common.h,v 1.8 2005/02/22 12:28:40 kraxel Exp $
*
* some common structs and functions to handle infrared remotes via
* input layer ...
@@ -47,7 +47,9 @@ struct ir_input_state {
};
extern IR_KEYTAB_TYPE ir_codes_rc5_tv[IR_KEYTAB_SIZE];
+extern IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE];
extern IR_KEYTAB_TYPE ir_codes_empty[IR_KEYTAB_SIZE];
+extern IR_KEYTAB_TYPE ir_codes_hauppauge_new[IR_KEYTAB_SIZE];
void ir_input_init(struct input_dev *dev, struct ir_input_state *ir,
int ir_type, IR_KEYTAB_TYPE *ir_codes);
@@ -55,6 +57,8 @@ void ir_input_nokey(struct input_dev *dev, struct ir_input_state *ir);
void ir_input_keydown(struct input_dev *dev, struct ir_input_state *ir,
u32 ir_key, u32 ir_raw);
u32 ir_extract_bits(u32 data, u32 mask);
+int ir_dump_samples(u32 *samples, int count);
+int ir_decode_biphase(u32 *samples, int count, int low, int high);
/*
* Local variables:
diff --git a/include/media/saa6752hs.h b/include/media/saa6752hs.h
index 135f9a6824296..791bad2b86e9b 100644
--- a/include/media/saa6752hs.h
+++ b/include/media/saa6752hs.h
@@ -18,14 +18,14 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#ifndef _SAA6752HS_H
+#if 0 /* ndef _SAA6752HS_H */
#define _SAA6752HS_H
-enum mpeg_bitrate_mode {
- MPEG_BITRATE_MODE_VBR = 0, /* Variable bitrate */
- MPEG_BITRATE_MODE_CBR = 1, /* Constant bitrate */
+enum mpeg_video_bitrate_mode {
+ MPEG_VIDEO_BITRATE_MODE_VBR = 0, /* Variable bitrate */
+ MPEG_VIDEO_BITRATE_MODE_CBR = 1, /* Constant bitrate */
- MPEG_BITRATE_MODE_MAX
+ MPEG_VIDEO_BITRATE_MODE_MAX
};
enum mpeg_audio_bitrate {
@@ -35,16 +35,33 @@ enum mpeg_audio_bitrate {
MPEG_AUDIO_BITRATE_MAX
};
+enum mpeg_video_format {
+ MPEG_VIDEO_FORMAT_D1 = 0,
+ MPEG_VIDEO_FORMAT_2_3_D1 = 1,
+ MPEG_VIDEO_FORMAT_1_2_D1 = 2,
+ MPEG_VIDEO_FORMAT_SIF = 3,
+
+ MPEG_VIDEO_FORMAT_MAX
+};
+
#define MPEG_VIDEO_TARGET_BITRATE_MAX 27000
#define MPEG_VIDEO_MAX_BITRATE_MAX 27000
#define MPEG_TOTAL_BITRATE_MAX 27000
+#define MPEG_PID_MAX ((1 << 14) - 1)
struct mpeg_params {
- enum mpeg_bitrate_mode bitrate_mode;
+ enum mpeg_video_bitrate_mode video_bitrate_mode;
unsigned int video_target_bitrate;
unsigned int video_max_bitrate; // only used for VBR
enum mpeg_audio_bitrate audio_bitrate;
unsigned int total_bitrate;
+
+ unsigned int pmt_pid;
+ unsigned int video_pid;
+ unsigned int audio_pid;
+ unsigned int pcr_pid;
+
+ enum mpeg_video_format video_format;
};
#define MPEG_SETPARAMS _IOW('6',100,struct mpeg_params)
diff --git a/include/media/saa7146.h b/include/media/saa7146.h
index 171dbb682a0ec..3dfb8d670eb78 100644
--- a/include/media/saa7146.h
+++ b/include/media/saa7146.h
@@ -65,7 +65,7 @@ struct saa7146_vv;
/* saa7146 page table */
struct saa7146_pgtable {
unsigned int size;
- u32 *cpu;
+ u32 *cpu;
dma_addr_t dma;
/* used for offsets for u,v planes for planar capture modes */
unsigned long offset;
@@ -93,20 +93,20 @@ struct saa7146_extension
#define SAA7146_USE_I2C_IRQ 0x1
#define SAA7146_I2C_SHORT_DELAY 0x2
int flags;
-
+
/* pairs of subvendor and subdevice ids for
supported devices, last entry 0xffff, 0xfff */
struct module *module;
struct pci_driver driver;
struct pci_device_id *pci_tbl;
-
+
/* extension functions */
int (*probe)(struct saa7146_dev *);
int (*attach)(struct saa7146_dev *, struct saa7146_pci_extension_data *);
int (*detach)(struct saa7146_dev*);
u32 irq_mask; /* mask to indicate, which irq-events are handled by the extension */
- void (*irq_func)(struct saa7146_dev*, u32* irq_mask);
+ void (*irq_func)(struct saa7146_dev*, u32* irq_mask);
};
struct saa7146_dma
@@ -122,18 +122,18 @@ struct saa7146_dev
struct list_head item;
/* different device locks */
- spinlock_t slock;
- struct semaphore lock;
+ spinlock_t slock;
+ struct semaphore lock;
- unsigned char __iomem *mem; /* pointer to mapped IO memory */
+ unsigned char __iomem *mem; /* pointer to mapped IO memory */
int revision; /* chip revision; needed for bug-workarounds*/
/* pci-device & irq stuff*/
char name[32];
struct pci_dev *pci;
u32 int_todo;
- spinlock_t int_slock;
-
+ spinlock_t int_slock;
+
/* extension handling */
struct saa7146_extension *ext; /* indicates if handled by extension */
void *ext_priv; /* pointer for extension private use (most likely some private data) */
@@ -149,7 +149,7 @@ struct saa7146_dev
struct saa7146_dma d_i2c; /* pointer to i2c memory */
wait_queue_head_t i2c_wq;
int i2c_op;
-
+
/* memories */
struct saa7146_dma d_rps0;
struct saa7146_dma d_rps1;
@@ -157,7 +157,7 @@ struct saa7146_dev
/* from saa7146_i2c.c */
int saa7146_i2c_adapter_prepare(struct saa7146_dev *dev, struct i2c_adapter *i2c_adapter, u32 bitrate);
-int saa7146_i2c_transfer(struct saa7146_dev *saa, const struct i2c_msg msgs[], int num, int retries);
+int saa7146_i2c_transfer(struct saa7146_dev *saa, const struct i2c_msg *msgs, int num, int retries);
/* from saa7146_core.c */
extern struct list_head saa7146_devices;
@@ -178,8 +178,8 @@ int saa7146_wait_for_debi_done(struct saa7146_dev *dev, int nobusyloop);
/* some i2c constants */
#define SAA7146_I2C_TIMEOUT 100 /* i2c-timeout-value in ms */
-#define SAA7146_I2C_RETRIES 3 /* how many times shall we retry an i2c-operation? */
-#define SAA7146_I2C_DELAY 5 /* time we wait after certain i2c-operations */
+#define SAA7146_I2C_RETRIES 3 /* how many times shall we retry an i2c-operation? */
+#define SAA7146_I2C_DELAY 5 /* time we wait after certain i2c-operations */
/* unsorted defines */
#define ME1 0x0000000800
@@ -272,7 +272,7 @@ int saa7146_wait_for_debi_done(struct saa7146_dev *dev, int nobusyloop);
#define MASK_W1 0xffff0000 /* Mask value for word 1 */
#define MASK_PA 0xfffffffc /* Mask value for physical address */
-#define MASK_PR 0xfffffffe /* Mask value for protection register */
+#define MASK_PR 0xfffffffe /* Mask value for protection register */
#define MASK_ER 0xffffffff /* Mask value for the entire register */
#define MASK_NONE 0x00000000 /* No mask */
@@ -295,7 +295,7 @@ int saa7146_wait_for_debi_done(struct saa7146_dev *dev, int nobusyloop);
#define BASE_ODD3 0x30 /* Video DMA 3 registers */
#define BASE_EVEN3 0x34
#define PROT_ADDR3 0x38
-#define PITCH3 0x3C
+#define PITCH3 0x3C
#define BASE_PAGE3 0x40 /* Video DMA 3 base page */
#define NUM_LINE_BYTE3 0x44
@@ -323,15 +323,15 @@ int saa7146_wait_for_debi_done(struct saa7146_dev *dev, int nobusyloop);
#define DEBI_CONFIG 0x7C
#define DEBI_COMMAND 0x80
#define DEBI_PAGE 0x84
-#define DEBI_AD 0x88
+#define DEBI_AD 0x88
-#define I2C_TRANSFER 0x8C
-#define I2C_STATUS 0x90
+#define I2C_TRANSFER 0x8C
+#define I2C_STATUS 0x90
#define BASE_A1_IN 0x94 /* Audio 1 input DMA */
#define PROT_A1_IN 0x98
#define PAGE_A1_IN 0x9C
-
+
#define BASE_A1_OUT 0xA0 /* Audio 1 output DMA */
#define PROT_A1_OUT 0xA4
#define PAGE_A1_OUT 0xA8
@@ -371,12 +371,12 @@ int saa7146_wait_for_debi_done(struct saa7146_dev *dev, int nobusyloop);
#define RPS_ADDR0 0x104 /* RPS task 0 address register */
#define RPS_ADDR1 0x108 /* RPS task 1 address register */
-#define ISR 0x10C /* Interrupt status register */
+#define ISR 0x10C /* Interrupt status register */
#define PSR 0x110 /* Primary status register */
#define SSR 0x114 /* Secondary status register */
#define EC1R 0x118 /* Event counter set 1 register */
-#define EC2R 0x11C /* Event counter set 2 register */
+#define EC2R 0x11C /* Event counter set 2 register */
#define PCI_VDP1 0x120 /* Video DMA pointer of FIFO 1 */
#define PCI_VDP2 0x124 /* Video DMA pointer of FIFO 2 */
@@ -450,4 +450,3 @@ int saa7146_wait_for_debi_done(struct saa7146_dev *dev, int nobusyloop);
#define SAA7146_I2C_BUS_BIT_RATE_60 (0x300)
#endif
-
diff --git a/include/media/saa7146_vv.h b/include/media/saa7146_vv.h
index eddf16aa3e8e9..f3aa24f8131ce 100644
--- a/include/media/saa7146_vv.h
+++ b/include/media/saa7146_vv.h
@@ -31,7 +31,7 @@ struct saa7146_video_dma {
struct saa7146_format {
char *name;
- u32 pixelformat;
+ u32 pixelformat;
u32 trans;
u8 depth;
u8 flags;
@@ -45,10 +45,10 @@ struct saa7146_standard
int v_offset; /* number of lines of vertical offset before processing */
int v_field; /* number of lines in a field for HPS to process */
-
+
int h_offset; /* horizontal offset of processing window */
int h_pixels; /* number of horizontal pixels to process */
-
+
int v_max_out;
int h_max_out;
};
@@ -90,7 +90,7 @@ struct saa7146_fh {
/* video overlay */
struct saa7146_overlay ov;
-
+
/* video capture */
struct videobuf_queue video_q;
struct v4l2_pix_format video_fmt;
@@ -139,11 +139,11 @@ struct saa7146_vv
all opens? currently, we do the latter, like all other
drivers do... */
struct saa7146_standard *standard;
-
+
int vflip;
- int hflip;
- int current_hps_source;
- int current_hps_sync;
+ int hflip;
+ int current_hps_source;
+ int current_hps_sync;
struct saa7146_dma d_clipping; /* pointer to clipping memory */
@@ -157,7 +157,7 @@ struct saa7146_vv
struct saa7146_extension_ioctls
{
unsigned int cmd;
- int flags;
+ int flags;
};
/* flags */
@@ -166,16 +166,16 @@ struct saa7146_extension_ioctls
struct saa7146_ext_vv
{
/* informations about the video capabilities of the device */
- int inputs;
- int audios;
+ int inputs;
+ int audios;
u32 capabilities;
- int flags;
+ int flags;
/* additionally supported transmission standards */
struct saa7146_standard *stds;
int num_stds;
int (*std_callback)(struct saa7146_dev*, struct saa7146_standard *);
-
+
struct saa7146_extension_ioctls *ioctls;
int (*ioctl)(struct saa7146_fh*, unsigned int cmd, void *arg);
};
@@ -264,7 +264,7 @@ void saa7146_res_free(struct saa7146_fh *fh, unsigned int bits);
/* misc defines */
#define SAA7146_NO_SWAP (0x0)
-#define SAA7146_TWO_BYTE_SWAP (0x1)
+#define SAA7146_TWO_BYTE_SWAP (0x1)
#define SAA7146_FOUR_BYTE_SWAP (0x2)
#endif
diff --git a/include/media/tuner.h b/include/media/tuner.h
index 3e9bac43d9b28..156a9c51ffec9 100644
--- a/include/media/tuner.h
+++ b/include/media/tuner.h
@@ -29,55 +29,74 @@
#define TUNER_PHILIPS_PAL_I 1
#define TUNER_PHILIPS_NTSC 2
#define TUNER_PHILIPS_SECAM 3 /* you must actively select B/G, L, L` */
+
#define TUNER_ABSENT 4
#define TUNER_PHILIPS_PAL 5
#define TUNER_TEMIC_NTSC 6 /* 4032 FY5 (3X 7004, 9498, 9789) */
#define TUNER_TEMIC_PAL_I 7 /* 4062 FY5 (3X 8501, 9957) */
+
#define TUNER_TEMIC_4036FY5_NTSC 8 /* 4036 FY5 (3X 1223, 1981, 7686) */
#define TUNER_ALPS_TSBH1_NTSC 9
#define TUNER_ALPS_TSBE1_PAL 10
#define TUNER_ALPS_TSBB5_PAL_I 11
+
#define TUNER_ALPS_TSBE5_PAL 12
#define TUNER_ALPS_TSBC5_PAL 13
#define TUNER_TEMIC_4006FH5_PAL 14 /* 4006 FH5 (3X 9500, 9501, 7291) */
#define TUNER_ALPS_TSHC6_NTSC 15
+
#define TUNER_TEMIC_PAL_DK 16 /* 4016 FY5 (3X 1392, 1393) */
#define TUNER_PHILIPS_NTSC_M 17
#define TUNER_TEMIC_4066FY5_PAL_I 18 /* 4066 FY5 (3X 7032, 7035) */
#define TUNER_TEMIC_4006FN5_MULTI_PAL 19 /* B/G, I and D/K autodetected (3X 7595, 7606, 7657)*/
+
#define TUNER_TEMIC_4009FR5_PAL 20 /* incl. FM radio (3X 7607, 7488, 7711)*/
#define TUNER_TEMIC_4039FR5_NTSC 21 /* incl. FM radio (3X 7246, 7578, 7732)*/
#define TUNER_TEMIC_4046FM5 22 /* you must actively select B/G, D/K, I, L, L` ! (3X 7804, 7806, 8103, 8104)*/
#define TUNER_PHILIPS_PAL_DK 23
+
#define TUNER_PHILIPS_FQ1216ME 24 /* you must actively select B/G/D/K, I, L, L` */
#define TUNER_LG_PAL_I_FM 25
#define TUNER_LG_PAL_I 26
#define TUNER_LG_NTSC_FM 27
+
#define TUNER_LG_PAL_FM 28
#define TUNER_LG_PAL 29
#define TUNER_TEMIC_4009FN5_MULTI_PAL_FM 30 /* B/G, I and D/K autodetected (3X 8155, 8160, 8163)*/
#define TUNER_SHARP_2U5JF5540_NTSC 31
+
#define TUNER_Samsung_PAL_TCPM9091PD27 32
#define TUNER_MT2032 33
#define TUNER_TEMIC_4106FH5 34 /* 4106 FH5 (3X 7808, 7865)*/
#define TUNER_TEMIC_4012FY5 35 /* 4012 FY5 (3X 0971, 1099)*/
+
#define TUNER_TEMIC_4136FY5 36 /* 4136 FY5 (3X 7708, 7746)*/
#define TUNER_LG_PAL_NEW_TAPC 37
#define TUNER_PHILIPS_FM1216ME_MK3 38
#define TUNER_LG_NTSC_NEW_TAPC 39
+
#define TUNER_HITACHI_NTSC 40
#define TUNER_PHILIPS_PAL_MK 41
#define TUNER_PHILIPS_ATSC 42
#define TUNER_PHILIPS_FM1236_MK3 43
+
#define TUNER_PHILIPS_4IN1 44 /* ATI TV Wonder Pro - Conexant */
/* Microtune mergeged with Temic 12/31/1999 partially financed by Alps - these may be similar to Temic */
#define TUNER_MICROTUNE_4049FM5 45
#define TUNER_LG_NTSC_TAPE 47
+
#define TUNER_TNF_8831BGFF 48
#define TUNER_MICROTUNE_4042FI5 49 /* FusionHDTV 3 Gold - 4042 FI5 (3X 8147) */
#define TUNER_TCL_2002N 50
#define TUNER_PHILIPS_FM1256_IH3 51
+
#define TUNER_THOMSON_DTT7610 52
+#define TUNER_PHILIPS_FQ1286 53
+#define TUNER_PHILIPS_TDA8290 54
+#define TUNER_LG_PAL_TAPE 55 /* Hauppauge PVR-150 PAL */
+
+#define TUNER_PHILIPS_FQ1216AME_MK4 56 /* Hauppauge PVR-150 PAL */
+#define TUNER_PHILIPS_FQ1236A_MK4 57 /* Hauppauge PVR-500MCE NTSC */
#define NOTUNER 0
#define PAL 1 /* PAL_BG */
@@ -102,10 +121,6 @@
#define TUNER_SET_TYPE _IOW('t',1,int) /* set tuner type */
#define TUNER_SET_TVFREQ _IOW('t',2,int) /* set tv freq */
-#if 0 /* obsolete */
-# define TUNER_SET_RADIOFREQ _IOW('t',3,int) /* set radio freq */
-# define TUNER_SET_MODE _IOW('t',4,int) /* set tuner mode */
-#endif
#define TDA9887_SET_CONFIG _IOW('t',5,int)
/* tv card specific */
@@ -123,4 +138,62 @@
# define TDA9887_DEEMPHASIS_75 (3<<16)
# define TDA9887_AUTOMUTE (1<<18)
+#ifdef __KERNEL__
+
+#define I2C_ADDR_TDA8290 0x4b
+#define I2C_ADDR_TDA8275 0x61
+
+struct tuner {
+ /* device */
+ struct i2c_client i2c;
+
+ /* state + config */
+ unsigned int initialized;
+ unsigned int type; /* chip type */
+ unsigned int freq; /* keep track of the current settings */
+ v4l2_std_id std;
+ int using_v4l2;
+
+ enum v4l2_tuner_type mode;
+ unsigned int input;
+
+ /* used by MT2032 */
+ unsigned int xogc;
+ unsigned int radio_if2;
+
+ /* used by tda8290 */
+ unsigned char i2c_easy_mode[2];
+ unsigned char i2c_set_freq[8];
+
+ /* function ptrs */
+ void (*tv_freq)(struct i2c_client *c, unsigned int freq);
+ void (*radio_freq)(struct i2c_client *c, unsigned int freq);
+ int (*has_signal)(struct i2c_client *c);
+ int (*is_stereo)(struct i2c_client *c);
+};
+
+extern unsigned int tuner_debug;
+extern unsigned const int tuner_count;
+
+extern int microtune_init(struct i2c_client *c);
+extern int tda8290_init(struct i2c_client *c);
+extern int default_tuner_init(struct i2c_client *c);
+
+#define tuner_warn(fmt, arg...) \
+ dev_printk(KERN_WARNING , &t->i2c.dev , fmt , ## arg)
+#define tuner_info(fmt, arg...) \
+ dev_printk(KERN_INFO , &t->i2c.dev , fmt , ## arg)
+#define tuner_dbg(fmt, arg...) \
+ if (tuner_debug) dev_printk(KERN_DEBUG , &t->i2c.dev , fmt , ## arg)
+
+#endif /* __KERNEL__ */
+
#endif
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/include/net/act_api.h b/include/net/act_api.h
index 12736d17d3a30..ed00a995f576f 100644
--- a/include/net/act_api.h
+++ b/include/net/act_api.h
@@ -81,7 +81,7 @@ extern struct tc_action *tcf_action_init_1(struct rtattr *rta, struct rtattr *es
extern int tcf_action_dump(struct sk_buff *skb, struct tc_action *a, int, int);
extern int tcf_action_dump_old(struct sk_buff *skb, struct tc_action *a, int, int);
extern int tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int, int);
-extern int tcf_action_copy_stats (struct sk_buff *,struct tc_action *);
+extern int tcf_action_copy_stats (struct sk_buff *,struct tc_action *, int);
#endif /* CONFIG_NET_CLS_ACT */
extern int tcf_police(struct sk_buff *skb, struct tcf_police *p);
diff --git a/include/net/addrconf.h b/include/net/addrconf.h
index bfcc02447b6ba..7af9a13cb9beb 100644
--- a/include/net/addrconf.h
+++ b/include/net/addrconf.h
@@ -49,7 +49,7 @@ struct prefix_info {
#define IN6_ADDR_HSIZE 16
-extern void addrconf_init(void);
+extern int addrconf_init(void);
extern void addrconf_cleanup(void);
extern int addrconf_add_ifaddr(void __user *arg);
@@ -102,6 +102,8 @@ extern int ipv6_is_mld(struct sk_buff *skb, int nexthdr);
extern void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len);
+extern int ipv6_get_hoplimit(struct net_device *dev);
+
/*
* anycast prototypes (anycast.c)
*/
diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
index 02bdef01cc36d..42a84c53678b1 100644
--- a/include/net/bluetooth/bluetooth.h
+++ b/include/net/bluetooth/bluetooth.h
@@ -125,7 +125,6 @@ struct bt_sock_list {
int bt_sock_register(int proto, struct net_proto_family *ops);
int bt_sock_unregister(int proto);
-struct sock *bt_sock_alloc(struct socket *sock, int proto, int pi_size, int prio);
void bt_sock_link(struct bt_sock_list *l, struct sock *s);
void bt_sock_unlink(struct bt_sock_list *l, struct sock *s);
int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len, int flags);
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index a27161a0e8d49..6d63a47c731bc 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -217,7 +217,8 @@ void hci_inquiry_cache_update(struct hci_dev *hdev, struct inquiry_data *data);
/* ----- HCI Connections ----- */
enum {
HCI_CONN_AUTH_PEND,
- HCI_CONN_ENCRYPT_PEND
+ HCI_CONN_ENCRYPT_PEND,
+ HCI_CONN_RSWITCH_PEND
};
static inline void hci_conn_hash_init(struct hci_dev *hdev)
@@ -290,6 +291,7 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *src);
int hci_conn_auth(struct hci_conn *conn);
int hci_conn_encrypt(struct hci_conn *conn);
int hci_conn_change_link_key(struct hci_conn *conn);
+int hci_conn_switch_role(struct hci_conn *conn, uint8_t role);
static inline void hci_conn_set_timer(struct hci_conn *conn, unsigned long timeout)
{
@@ -515,6 +517,8 @@ struct hci_cb {
void (*auth_cfm) (struct hci_conn *conn, __u8 status);
void (*encrypt_cfm) (struct hci_conn *conn, __u8 status, __u8 encrypt);
+ void (*key_change_cfm) (struct hci_conn *conn, __u8 status);
+ void (*role_switch_cfm) (struct hci_conn *conn, __u8 status, __u8 role);
};
static inline void hci_auth_cfm(struct hci_conn *conn, __u8 status)
@@ -547,6 +551,32 @@ static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status, __u8 encr
read_unlock_bh(&hci_cb_list_lock);
}
+static inline void hci_key_change_cfm(struct hci_conn *conn, __u8 status)
+{
+ struct list_head *p;
+
+ read_lock_bh(&hci_cb_list_lock);
+ list_for_each(p, &hci_cb_list) {
+ struct hci_cb *cb = list_entry(p, struct hci_cb, list);
+ if (cb->key_change_cfm)
+ cb->key_change_cfm(conn, status);
+ }
+ read_unlock_bh(&hci_cb_list_lock);
+}
+
+static inline void hci_role_switch_cfm(struct hci_conn *conn, __u8 status, __u8 role)
+{
+ struct list_head *p;
+
+ read_lock_bh(&hci_cb_list_lock);
+ list_for_each(p, &hci_cb_list) {
+ struct hci_cb *cb = list_entry(p, struct hci_cb, list);
+ if (cb->role_switch_cfm)
+ cb->role_switch_cfm(conn, status, role);
+ }
+ read_unlock_bh(&hci_cb_list_lock);
+}
+
int hci_register_cb(struct hci_cb *hcb);
int hci_unregister_cb(struct hci_cb *hcb);
@@ -565,8 +595,10 @@ void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data);
void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb);
/* HCI info for socket */
-#define hci_pi(sk) ((struct hci_pinfo *)sk->sk_protinfo)
+#define hci_pi(sk) ((struct hci_pinfo *) sk)
+
struct hci_pinfo {
+ struct bt_sock bt;
struct hci_dev *hdev;
struct hci_filter filter;
__u32 cmsg_mask;
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 490a656095601..8242a0ee1f586 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -201,9 +201,10 @@ struct l2cap_conn {
};
/* ----- L2CAP channel and socket info ----- */
-#define l2cap_pi(sk) ((struct l2cap_pinfo *)sk->sk_protinfo)
+#define l2cap_pi(sk) ((struct l2cap_pinfo *) sk)
struct l2cap_pinfo {
+ struct bt_sock bt;
__u16 psm;
__u16 dcid;
__u16 scid;
diff --git a/include/net/bluetooth/rfcomm.h b/include/net/bluetooth/rfcomm.h
index 31a70cee9c04e..13669bad00b37 100644
--- a/include/net/bluetooth/rfcomm.h
+++ b/include/net/bluetooth/rfcomm.h
@@ -293,9 +293,10 @@ struct rfcomm_conninfo {
#define RFCOMM_LM_RELIABLE 0x0010
#define RFCOMM_LM_SECURE 0x0020
-#define rfcomm_pi(sk) ((struct rfcomm_pinfo *)sk->sk_protinfo)
+#define rfcomm_pi(sk) ((struct rfcomm_pinfo *) sk)
struct rfcomm_pinfo {
+ struct bt_sock bt;
struct rfcomm_dlc *dlc;
u8 channel;
u32 link_mode;
diff --git a/include/net/bluetooth/sco.h b/include/net/bluetooth/sco.h
index bcd66c3feb1c5..e28a2a7714713 100644
--- a/include/net/bluetooth/sco.h
+++ b/include/net/bluetooth/sco.h
@@ -68,9 +68,10 @@ struct sco_conn {
#define sco_conn_unlock(c) spin_unlock(&c->lock);
/* ----- SCO socket info ----- */
-#define sco_pi(sk) ((struct sco_pinfo *)sk->sk_protinfo)
+#define sco_pi(sk) ((struct sco_pinfo *) sk)
struct sco_pinfo {
+ struct bt_sock bt;
__u32 flags;
struct sco_conn *conn;
};
diff --git a/include/net/checksum.h b/include/net/checksum.h
index bd570858fadaa..e3ea7cc2c7283 100644
--- a/include/net/checksum.h
+++ b/include/net/checksum.h
@@ -30,7 +30,7 @@ static inline
unsigned int csum_and_copy_from_user (const unsigned char __user *src, unsigned char *dst,
int len, int sum, int *err_ptr)
{
- if (verify_area(VERIFY_READ, src, len) == 0)
+ if (access_ok(VERIFY_READ, src, len))
return csum_partial_copy_from_user(src, dst, len, sum, err_ptr);
if (len)
diff --git a/include/net/dn.h b/include/net/dn.h
index 5e36492da13cb..5551c46db397e 100644
--- a/include/net/dn.h
+++ b/include/net/dn.h
@@ -2,6 +2,7 @@
#define _NET_DN_H
#include <linux/dn.h>
+#include <net/sock.h>
#include <asm/byteorder.h>
typedef unsigned short dn_address;
@@ -133,7 +134,10 @@ struct dn_scp /* Session Control Port */
};
-#define DN_SK(__sk) ((struct dn_scp *)(__sk)->sk_protinfo)
+static inline struct dn_scp *DN_SK(struct sock *sk)
+{
+ return (struct dn_scp *)(sk + 1);
+}
/*
* src,dst : Source and Destination DECnet addresses
diff --git a/include/net/dst.h b/include/net/dst.h
index b7e47a7ad1058..50adc91365309 100644
--- a/include/net/dst.h
+++ b/include/net/dst.h
@@ -48,6 +48,7 @@ struct dst_entry
#define DST_NOXFRM 2
#define DST_NOPOLICY 4
#define DST_NOHASH 8
+#define DST_BALANCED 0x10
unsigned long lastuse;
unsigned long expires;
@@ -109,19 +110,23 @@ dst_metric(const struct dst_entry *dst, int metric)
return dst->metrics[metric-1];
}
-static inline u32
-dst_path_metric(const struct dst_entry *dst, int metric)
+static inline u32 dst_mtu(const struct dst_entry *dst)
{
- return dst->path->metrics[metric-1];
+ u32 mtu = dst_metric(dst, RTAX_MTU);
+ /*
+ * Alexey put it here, so ask him about it :)
+ */
+ barrier();
+ return mtu;
}
static inline u32
-dst_pmtu(const struct dst_entry *dst)
+dst_allfrag(const struct dst_entry *dst)
{
- u32 mtu = dst_path_metric(dst, RTAX_MTU);
+ int ret = dst_metric(dst, RTAX_FEATURES) & RTAX_FEATURE_ALLFRAG;
/* Yes, _exactly_. This is paranoia. */
barrier();
- return mtu;
+ return ret;
}
static inline int
@@ -249,6 +254,13 @@ static inline int dst_input(struct sk_buff *skb)
}
}
+static inline struct dst_entry *dst_check(struct dst_entry *dst, u32 cookie)
+{
+ if (dst->obsolete)
+ dst = dst->ops->check(dst, cookie);
+ return dst;
+}
+
extern void dst_init(void);
struct flowi;
diff --git a/include/net/flow.h b/include/net/flow.h
index 025579ddb925a..9a5c94b1a0eca 100644
--- a/include/net/flow.h
+++ b/include/net/flow.h
@@ -51,6 +51,7 @@ struct flowi {
__u8 proto;
__u8 flags;
+#define FLOWI_FLAG_MULTIPATHOLDROUTE 0x01
union {
struct {
__u16 sport;
diff --git a/include/net/inetpeer.h b/include/net/inetpeer.h
index 5fd62eb25a041..7fda471002b6b 100644
--- a/include/net/inetpeer.h
+++ b/include/net/inetpeer.h
@@ -19,9 +19,9 @@ struct inet_peer
{
struct inet_peer *avl_left, *avl_right;
struct inet_peer *unused_next, **unused_prevp;
- atomic_t refcnt;
unsigned long dtime; /* the time of last use of not
* referenced entries */
+ atomic_t refcnt;
__u32 v4daddr; /* peer's address */
__u16 avl_height;
__u16 ip_id_count; /* IP ID for the next packet */
@@ -35,7 +35,6 @@ void inet_initpeers(void) __init;
struct inet_peer *inet_getpeer(__u32 daddr, int create);
extern spinlock_t inet_peer_unused_lock;
-extern struct inet_peer *inet_peer_unused_head;
extern struct inet_peer **inet_peer_unused_tailp;
/* can be called from BH context or outside */
static inline void inet_putpeer(struct inet_peer *p)
diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
index 9f28dfffb6c63..e5a5f6b62f880 100644
--- a/include/net/ip_fib.h
+++ b/include/net/ip_fib.h
@@ -37,6 +37,7 @@ struct kern_rta {
u32 *rta_flow;
struct rta_cacheinfo *rta_ci;
struct rta_session *rta_sess;
+ u32 *rta_mp_alg;
};
struct fib_info;
@@ -81,6 +82,9 @@ struct fib_info {
#ifdef CONFIG_IP_ROUTE_MULTIPATH
int fib_power;
#endif
+#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
+ u32 fib_mp_alg;
+#endif
struct fib_nh fib_nh[0];
#define fib_dev fib_nh[0].nh_dev
};
@@ -95,6 +99,10 @@ struct fib_result {
unsigned char nh_sel;
unsigned char type;
unsigned char scope;
+#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
+ __u32 network;
+ __u32 netmask;
+#endif
struct fib_info *fi;
#ifdef CONFIG_IP_MULTIPLE_TABLES
struct fib_rule *r;
@@ -119,6 +127,14 @@ struct fib_result {
#define FIB_RES_DEV(res) (FIB_RES_NH(res).nh_dev)
#define FIB_RES_OIF(res) (FIB_RES_NH(res).nh_oif)
+#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
+#define FIB_RES_NETWORK(res) ((res).network)
+#define FIB_RES_NETMASK(res) ((res).netmask)
+#else /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */
+#define FIB_RES_NETWORK(res) (0)
+#define FIB_RES_NETMASK(res) (0)
+#endif /* CONFIG_IP_ROUTE_MULTIPATH_WRANDOM */
+
struct fib_table {
unsigned char tb_id;
unsigned tb_stamp;
diff --git a/include/net/ip_mp_alg.h b/include/net/ip_mp_alg.h
new file mode 100644
index 0000000000000..77225735cbd4c
--- /dev/null
+++ b/include/net/ip_mp_alg.h
@@ -0,0 +1,99 @@
+/* ip_mp_alg.h: IPV4 multipath algorithm support.
+ *
+ * Copyright (C) 2004, 2005 Einar Lueck <elueck@de.ibm.com>
+ * Copyright (C) 2005 David S. Miller <davem@davemloft.net>
+ */
+
+#ifndef _NET_IP_MP_ALG_H
+#define _NET_IP_MP_ALG_H
+
+#include <linux/config.h>
+#include <linux/ip_mp_alg.h>
+#include <net/flow.h>
+#include <net/route.h>
+
+struct fib_nh;
+
+struct ip_mp_alg_ops {
+ void (*mp_alg_select_route)(const struct flowi *flp,
+ struct rtable *rth, struct rtable **rp);
+ void (*mp_alg_flush)(void);
+ void (*mp_alg_set_nhinfo)(__u32 network, __u32 netmask,
+ unsigned char prefixlen,
+ const struct fib_nh *nh);
+ void (*mp_alg_remove)(struct rtable *rth);
+};
+
+extern int multipath_alg_register(struct ip_mp_alg_ops *, enum ip_mp_alg);
+extern void multipath_alg_unregister(struct ip_mp_alg_ops *, enum ip_mp_alg);
+
+extern struct ip_mp_alg_ops *ip_mp_alg_table[];
+
+static inline int multipath_select_route(const struct flowi *flp,
+ struct rtable *rth,
+ struct rtable **rp)
+{
+#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
+ struct ip_mp_alg_ops *ops = ip_mp_alg_table[rth->rt_multipath_alg];
+
+ /* mp_alg_select_route _MUST_ be implemented */
+ if (ops && (rth->u.dst.flags & DST_BALANCED)) {
+ ops->mp_alg_select_route(flp, rth, rp);
+ return 1;
+ }
+#endif
+ return 0;
+}
+
+static inline void multipath_flush(void)
+{
+#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
+ int i;
+
+ for (i = IP_MP_ALG_NONE; i <= IP_MP_ALG_MAX; i++) {
+ struct ip_mp_alg_ops *ops = ip_mp_alg_table[i];
+
+ if (ops && ops->mp_alg_flush)
+ ops->mp_alg_flush();
+ }
+#endif
+}
+
+static inline void multipath_set_nhinfo(struct rtable *rth,
+ __u32 network, __u32 netmask,
+ unsigned char prefixlen,
+ const struct fib_nh *nh)
+{
+#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
+ struct ip_mp_alg_ops *ops = ip_mp_alg_table[rth->rt_multipath_alg];
+
+ if (ops && ops->mp_alg_set_nhinfo)
+ ops->mp_alg_set_nhinfo(network, netmask, prefixlen, nh);
+#endif
+}
+
+static inline void multipath_remove(struct rtable *rth)
+{
+#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
+ struct ip_mp_alg_ops *ops = ip_mp_alg_table[rth->rt_multipath_alg];
+
+ if (ops && ops->mp_alg_remove &&
+ (rth->u.dst.flags & DST_BALANCED))
+ ops->mp_alg_remove(rth);
+#endif
+}
+
+static inline int multipath_comparekeys(const struct flowi *flp1,
+ const struct flowi *flp2)
+{
+ return flp1->fl4_dst == flp2->fl4_dst &&
+ flp1->fl4_src == flp2->fl4_src &&
+ flp1->oif == flp2->oif &&
+#ifdef CONFIG_IP_ROUTE_FWMARK
+ flp1->fl4_fwmark == flp2->fl4_fwmark &&
+#endif
+ !((flp1->fl4_tos ^ flp2->fl4_tos) &
+ (IPTOS_RT_MASK | RTO_ONLINK));
+}
+
+#endif /* _NET_IP_MP_ALG_H */
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index dc1feea01acb8..87c45cbfbaf64 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -149,6 +149,8 @@ extern atomic_t inet6_sock_nr;
int snmp6_register_dev(struct inet6_dev *idev);
int snmp6_unregister_dev(struct inet6_dev *idev);
+int snmp6_alloc_dev(struct inet6_dev *idev);
+int snmp6_free_dev(struct inet6_dev *idev);
int snmp6_mib_init(void *ptr[2], size_t mibsize, size_t mibalign);
void snmp6_mib_free(void *ptr[2]);
@@ -303,6 +305,32 @@ static inline int ipv6_addr_equal(const struct in6_addr *a1,
a1->s6_addr32[3] == a2->s6_addr32[3]);
}
+static inline int __ipv6_prefix_equal(const u32 *a1, const u32 *a2,
+ unsigned int prefixlen)
+{
+ unsigned pdw, pbi;
+
+ /* check complete u32 in prefix */
+ pdw = prefixlen >> 5;
+ if (pdw && memcmp(a1, a2, pdw << 2))
+ return 0;
+
+ /* check incomplete u32 in prefix */
+ pbi = prefixlen & 0x1f;
+ if (pbi && ((a1[pdw] ^ a2[pdw]) & htonl((0xffffffff) << (32 - pbi))))
+ return 0;
+
+ return 1;
+}
+
+static inline int ipv6_prefix_equal(const struct in6_addr *a1,
+ const struct in6_addr *a2,
+ unsigned int prefixlen)
+{
+ return __ipv6_prefix_equal(a1->s6_addr32, a2->s6_addr32,
+ prefixlen);
+}
+
static inline int ipv6_addr_any(const struct in6_addr *a)
{
return ((a->s6_addr32[0] | a->s6_addr32[1] |
diff --git a/include/net/irda/af_irda.h b/include/net/irda/af_irda.h
index 0f6dafad4907e..7a209f61c4825 100644
--- a/include/net/irda/af_irda.h
+++ b/include/net/irda/af_irda.h
@@ -33,9 +33,12 @@
#include <net/irda/irlmp.h> /* struct lsap_cb */
#include <net/irda/irttp.h> /* struct tsap_cb */
#include <net/irda/discovery.h> /* struct discovery_t */
+#include <net/sock.h>
/* IrDA Socket */
struct irda_sock {
+ /* struct sock has to be the first member of irda_sock */
+ struct sock sk;
__u32 saddr; /* my local address */
__u32 daddr; /* peer address */
@@ -69,7 +72,6 @@ struct irda_sock {
int errno; /* status of the IAS query */
- struct sock *sk;
wait_queue_head_t query_wait; /* Wait for the answer to a query */
struct timer_list watchdog; /* Timeout for discovery */
@@ -77,6 +79,9 @@ struct irda_sock {
LOCAL_FLOW rx_flow;
};
-#define irda_sk(__sk) ((struct irda_sock *)(__sk)->sk_protinfo)
+static inline struct irda_sock *irda_sk(struct sock *sk)
+{
+ return (struct irda_sock *)sk;
+}
#endif /* AF_IRDA_H */
diff --git a/include/net/irda/irda.h b/include/net/irda/irda.h
index 497f6a3977bd5..05a840837fe7b 100644
--- a/include/net/irda/irda.h
+++ b/include/net/irda/irda.h
@@ -66,22 +66,25 @@ extern unsigned int irda_debug;
/* use 0 for production, 1 for verification, >2 for debug */
#define IRDA_DEBUG_LEVEL 0
-#define IRDA_DEBUG(n, args...) (irda_debug >= (n)) ? (printk(KERN_DEBUG args)) : 0
-#define ASSERT(expr, func) \
-if(!(expr)) { \
- printk( "Assertion failed! %s:%s:%d %s\n", \
- __FILE__,__FUNCTION__,__LINE__,(#expr)); \
- func }
+#define IRDA_DEBUG(n, args...) \
+do { if (irda_debug >= (n)) \
+ printk(KERN_DEBUG args); \
+} while (0)
+#define IRDA_ASSERT(expr, func) \
+do { if(!(expr)) { \
+ printk( "Assertion failed! %s:%s:%d %s\n", \
+ __FILE__,__FUNCTION__,__LINE__,(#expr) ); \
+ func } } while (0)
+#define IRDA_ASSERT_LABEL(label) label
#else
-#define IRDA_DEBUG(n, args...)
-#define ASSERT(expr, func) \
-if(!(expr)) do { \
- func } while (0)
+#define IRDA_DEBUG(n, args...) do { } while (0)
+#define IRDA_ASSERT(expr, func) do { (void)(expr); } while (0)
+#define IRDA_ASSERT_LABEL(label)
#endif /* CONFIG_IRDA_DEBUG */
-#define WARNING(args...) printk(KERN_WARNING args)
-#define MESSAGE(args...) printk(KERN_INFO args)
-#define ERROR(args...) printk(KERN_ERR args)
+#define IRDA_WARNING(args...) printk(KERN_WARNING args)
+#define IRDA_MESSAGE(args...) printk(KERN_INFO args)
+#define IRDA_ERROR(args...) printk(KERN_ERR args)
/*
* Magic numbers used by Linux-IrDA. Random numbers which must be unique to
diff --git a/include/net/llc_conn.h b/include/net/llc_conn.h
index bbc0af5232ed4..179e98e2aac86 100644
--- a/include/net/llc_conn.h
+++ b/include/net/llc_conn.h
@@ -13,6 +13,7 @@
*/
#include <linux/timer.h>
#include <net/llc_if.h>
+#include <net/sock.h>
#include <linux/llc.h>
#define LLC_EVENT 1
@@ -28,8 +29,9 @@ struct llc_timer {
u16 expire; /* timer expire time */
};
-struct llc_opt {
- struct sock *sk; /* sock that has this llc_opt */
+struct llc_sock {
+ /* struct sock must be the first member of llc_sock */
+ struct sock sk;
struct sockaddr_llc addr; /* address sock is bound to */
u8 state; /* state of connection */
struct llc_sap *sap; /* pointer to parent SAP */
@@ -75,7 +77,10 @@ struct llc_opt {
Used for resending FRMR */
};
-#define llc_sk(__sk) ((struct llc_opt *)(__sk)->sk_protinfo)
+static inline struct llc_sock *llc_sk(const struct sock *sk)
+{
+ return (struct llc_sock *)sk;
+}
static __inline__ void llc_set_backlog_type(struct sk_buff *skb, char type)
{
diff --git a/include/net/ndisc.h b/include/net/ndisc.h
index 8f121905ea6d7..f85d6e4b74426 100644
--- a/include/net/ndisc.h
+++ b/include/net/ndisc.h
@@ -15,11 +15,15 @@
* ndisc options
*/
-#define ND_OPT_SOURCE_LL_ADDR 1
-#define ND_OPT_TARGET_LL_ADDR 2
-#define ND_OPT_PREFIX_INFO 3
-#define ND_OPT_REDIRECT_HDR 4
-#define ND_OPT_MTU 5
+enum {
+ __ND_OPT_PREFIX_INFO_END = 0,
+ ND_OPT_SOURCE_LL_ADDR = 1, /* RFC2461 */
+ ND_OPT_TARGET_LL_ADDR = 2, /* RFC2461 */
+ ND_OPT_PREFIX_INFO = 3, /* RFC2461 */
+ ND_OPT_REDIRECT_HDR = 4, /* RFC2461 */
+ ND_OPT_MTU = 5, /* RFC2461 */
+ __ND_OPT_MAX
+};
#define MAX_RTR_SOLICITATION_DELAY HZ
diff --git a/include/net/neighbour.h b/include/net/neighbour.h
index 4c9ddae8c866f..4f33bbc21e7fd 100644
--- a/include/net/neighbour.h
+++ b/include/net/neighbour.h
@@ -274,7 +274,8 @@ extern int neigh_sysctl_register(struct net_device *dev,
struct neigh_parms *p,
int p_id, int pdev_id,
char *p_name,
- proc_handler *proc_handler);
+ proc_handler *proc_handler,
+ ctl_handler *strategy);
extern void neigh_sysctl_unregister(struct neigh_parms *p);
static inline void __neigh_parms_put(struct neigh_parms *parms)
diff --git a/include/net/netrom.h b/include/net/netrom.h
index d968252feddf3..45f2c7616d8b8 100644
--- a/include/net/netrom.h
+++ b/include/net/netrom.h
@@ -8,6 +8,7 @@
#define _NETROM_H
#include <linux/netrom.h>
#include <linux/list.h>
+#include <net/sock.h>
#define NR_NETWORK_LEN 15
#define NR_TRANSPORT_LEN 5
@@ -55,7 +56,8 @@ enum {
#define NR_MAX_WINDOW_SIZE 127 /* Maximum Window Allowable - 127 */
#define NR_MAX_PACKET_SIZE 236 /* Maximum Packet Length - 236 */
-typedef struct {
+struct nr_sock {
+ struct sock sock;
ax25_address user_addr, source_addr, dest_addr;
struct net_device *device;
unsigned char my_index, my_id;
@@ -72,10 +74,9 @@ typedef struct {
struct sk_buff_head ack_queue;
struct sk_buff_head reseq_queue;
struct sk_buff_head frag_queue;
- struct sock *sk; /* Backlink to socket */
-} nr_cb;
+};
-#define nr_sk(__sk) ((nr_cb *)(__sk)->sk_protinfo)
+#define nr_sk(sk) ((struct nr_sock *)(sk))
struct nr_neigh {
struct hlist_node neigh_node;
@@ -221,6 +222,7 @@ extern void nr_transmit_refusal(struct sk_buff *, int);
extern void nr_disconnect(struct sock *, int);
/* nr_timer.c */
+extern void nr_init_timers(struct sock *sk);
extern void nr_start_heartbeat(struct sock *);
extern void nr_start_t1timer(struct sock *);
extern void nr_start_t2timer(struct sock *);
diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h
index d12ad3831d147..4abda6aec05a8 100644
--- a/include/net/pkt_cls.h
+++ b/include/net/pkt_cls.h
@@ -148,6 +148,198 @@ extern int tcf_exts_dump(struct sk_buff *skb, struct tcf_exts *exts,
extern int tcf_exts_dump_stats(struct sk_buff *skb, struct tcf_exts *exts,
struct tcf_ext_map *map);
+/**
+ * struct tcf_pkt_info - packet information
+ */
+struct tcf_pkt_info
+{
+ unsigned char * ptr;
+ int nexthdr;
+};
+
+#ifdef CONFIG_NET_EMATCH
+
+struct tcf_ematch_ops;
+
+/**
+ * struct tcf_ematch - extended match (ematch)
+ *
+ * @matchid: identifier to allow userspace to reidentify a match
+ * @flags: flags specifying attributes and the relation to other matches
+ * @ops: the operations lookup table of the corresponding ematch module
+ * @datalen: length of the ematch specific configuration data
+ * @data: ematch specific data
+ */
+struct tcf_ematch
+{
+ struct tcf_ematch_ops * ops;
+ unsigned long data;
+ unsigned int datalen;
+ u16 matchid;
+ u16 flags;
+};
+
+static inline int tcf_em_is_container(struct tcf_ematch *em)
+{
+ return !em->ops;
+}
+
+static inline int tcf_em_is_simple(struct tcf_ematch *em)
+{
+ return em->flags & TCF_EM_SIMPLE;
+}
+
+static inline int tcf_em_is_inverted(struct tcf_ematch *em)
+{
+ return em->flags & TCF_EM_INVERT;
+}
+
+static inline int tcf_em_last_match(struct tcf_ematch *em)
+{
+ return (em->flags & TCF_EM_REL_MASK) == TCF_EM_REL_END;
+}
+
+static inline int tcf_em_early_end(struct tcf_ematch *em, int result)
+{
+ if (tcf_em_last_match(em))
+ return 1;
+
+ if (result == 0 && em->flags & TCF_EM_REL_AND)
+ return 1;
+
+ if (result != 0 && em->flags & TCF_EM_REL_OR)
+ return 1;
+
+ return 0;
+}
+
+/**
+ * struct tcf_ematch_tree - ematch tree handle
+ *
+ * @hdr: ematch tree header supplied by userspace
+ * @matches: array of ematches
+ */
+struct tcf_ematch_tree
+{
+ struct tcf_ematch_tree_hdr hdr;
+ struct tcf_ematch * matches;
+
+};
+
+/**
+ * struct tcf_ematch_ops - ematch module operations
+ *
+ * @kind: identifier (kind) of this ematch module
+ * @datalen: length of expected configuration data (optional)
+ * @change: called during validation (optional)
+ * @match: called during ematch tree evaluation, must return 1/0
+ * @destroy: called during destroyage (optional)
+ * @dump: called during dumping process (optional)
+ * @owner: owner, must be set to THIS_MODULE
+ * @link: link to previous/next ematch module (internal use)
+ */
+struct tcf_ematch_ops
+{
+ int kind;
+ int datalen;
+ int (*change)(struct tcf_proto *, void *,
+ int, struct tcf_ematch *);
+ int (*match)(struct sk_buff *, struct tcf_ematch *,
+ struct tcf_pkt_info *);
+ void (*destroy)(struct tcf_proto *,
+ struct tcf_ematch *);
+ int (*dump)(struct sk_buff *, struct tcf_ematch *);
+ struct module *owner;
+ struct list_head link;
+};
+
+extern int tcf_em_register(struct tcf_ematch_ops *);
+extern int tcf_em_unregister(struct tcf_ematch_ops *);
+extern int tcf_em_tree_validate(struct tcf_proto *, struct rtattr *,
+ struct tcf_ematch_tree *);
+extern void tcf_em_tree_destroy(struct tcf_proto *, struct tcf_ematch_tree *);
+extern int tcf_em_tree_dump(struct sk_buff *, struct tcf_ematch_tree *, int);
+extern int __tcf_em_tree_match(struct sk_buff *, struct tcf_ematch_tree *,
+ struct tcf_pkt_info *);
+
+/**
+ * tcf_em_tree_change - replace ematch tree of a running classifier
+ *
+ * @tp: classifier kind handle
+ * @dst: destination ematch tree variable
+ * @src: source ematch tree (temporary tree from tcf_em_tree_validate)
+ *
+ * This functions replaces the ematch tree in @dst with the ematch
+ * tree in @src. The classifier in charge of the ematch tree may be
+ * running.
+ */
+static inline void tcf_em_tree_change(struct tcf_proto *tp,
+ struct tcf_ematch_tree *dst,
+ struct tcf_ematch_tree *src)
+{
+ tcf_tree_lock(tp);
+ memcpy(dst, src, sizeof(*dst));
+ tcf_tree_unlock(tp);
+}
+
+/**
+ * tcf_em_tree_match - evaulate an ematch tree
+ *
+ * @skb: socket buffer of the packet in question
+ * @tree: ematch tree to be used for evaluation
+ * @info: packet information examined by classifier
+ *
+ * This function matches @skb against the ematch tree in @tree by going
+ * through all ematches respecting their logic relations returning
+ * as soon as the result is obvious.
+ *
+ * Returns 1 if the ematch tree as-one matches, no ematches are configured
+ * or ematch is not enabled in the kernel, otherwise 0 is returned.
+ */
+static inline int tcf_em_tree_match(struct sk_buff *skb,
+ struct tcf_ematch_tree *tree,
+ struct tcf_pkt_info *info)
+{
+ if (tree->hdr.nmatches)
+ return __tcf_em_tree_match(skb, tree, info);
+ else
+ return 1;
+}
+
+#else /* CONFIG_NET_EMATCH */
+
+struct tcf_ematch_tree
+{
+};
+
+#define tcf_em_tree_validate(tp, tb, t) ((void)(t), 0)
+#define tcf_em_tree_destroy(tp, t) do { (void)(t); } while(0)
+#define tcf_em_tree_dump(skb, t, tlv) (0)
+#define tcf_em_tree_change(tp, dst, src) do { } while(0)
+#define tcf_em_tree_match(skb, t, info) ((void)(info), 1)
+
+#endif /* CONFIG_NET_EMATCH */
+
+static inline unsigned char * tcf_get_base_ptr(struct sk_buff *skb, int layer)
+{
+ switch (layer) {
+ case TCF_LAYER_LINK:
+ return skb->data;
+ case TCF_LAYER_NETWORK:
+ return skb->nh.raw;
+ case TCF_LAYER_TRANSPORT:
+ return skb->h.raw;
+ }
+
+ return NULL;
+}
+
+static inline int tcf_valid_offset(struct sk_buff *skb, unsigned char *ptr,
+ int len)
+{
+ return unlikely((ptr + len) < skb->tail && ptr > skb->head);
+}
+
#ifdef CONFIG_NET_CLS_IND
static inline int
tcf_change_indev(struct tcf_proto *tp, char *indev, struct rtattr *indev_tlv)
diff --git a/include/net/rose.h b/include/net/rose.h
index 32fb79817d318..3249b979605a2 100644
--- a/include/net/rose.h
+++ b/include/net/rose.h
@@ -6,7 +6,9 @@
#ifndef _ROSE_H
#define _ROSE_H
+
#include <linux/rose.h>
+#include <net/sock.h>
#define ROSE_ADDR_LEN 5
@@ -114,7 +116,8 @@ struct rose_route {
unsigned int rand;
};
-typedef struct {
+struct rose_sock {
+ struct sock sock;
rose_address source_addr, dest_addr;
ax25_address source_call, dest_call;
unsigned char source_ndigis, dest_ndigis;
@@ -135,10 +138,9 @@ typedef struct {
struct rose_facilities_struct facilities;
struct timer_list timer;
struct timer_list idletimer;
- struct sock *sk; /* Backlink to socket */
-} rose_cb;
+};
-#define rose_sk(__sk) ((rose_cb *)(__sk)->sk_protinfo)
+#define rose_sk(sk) ((struct rose_sock *)(sk))
/* af_rose.c */
extern ax25_address rose_callsign;
diff --git a/include/net/route.h b/include/net/route.h
index 6228a91777dc4..22da7579d5de5 100644
--- a/include/net/route.h
+++ b/include/net/route.h
@@ -44,8 +44,9 @@
/* RTO_CONN is not used (being alias for 0), but preserved not to break
* some modules referring to it. */
-#define RT_CONN_FLAGS(sk) (RT_TOS(inet_sk(sk)->tos) | sk->sk_localroute)
+#define RT_CONN_FLAGS(sk) (RT_TOS(inet_sk(sk)->tos) | sock_flag(sk, SOCK_LOCALROUTE))
+struct fib_nh;
struct inet_peer;
struct rtable
{
@@ -58,7 +59,8 @@ struct rtable
struct in_device *idev;
unsigned rt_flags;
- unsigned rt_type;
+ __u16 rt_type;
+ __u16 rt_multipath_alg;
__u32 rt_dst; /* Path destination */
__u32 rt_src; /* Path source */
@@ -179,6 +181,9 @@ static inline int ip_route_newports(struct rtable **rp, u16 sport, u16 dport,
memcpy(&fl, &(*rp)->fl, sizeof(fl));
fl.fl_ip_sport = sport;
fl.fl_ip_dport = dport;
+#if defined(CONFIG_IP_ROUTE_MULTIPATH_CACHED)
+ fl.flags |= FLOWI_FLAG_MULTIPATHOLDROUTE;
+#endif
ip_rt_put(*rp);
*rp = NULL;
return ip_route_output_flow(rp, &fl, sk, 0);
diff --git a/include/net/scm.h b/include/net/scm.h
index b7ba74dbc3fda..c3fa3d5ab6067 100644
--- a/include/net/scm.h
+++ b/include/net/scm.h
@@ -51,13 +51,13 @@ static __inline__ void scm_recv(struct socket *sock, struct msghdr *msg,
{
if (!msg->msg_control)
{
- if (sock->passcred || scm->fp)
+ if (test_bit(SOCK_PASSCRED, &sock->flags) || scm->fp)
msg->msg_flags |= MSG_CTRUNC;
scm_destroy(scm);
return;
}
- if (sock->passcred)
+ if (test_bit(SOCK_PASSCRED, &sock->flags))
put_cmsg(msg, SOL_SOCKET, SCM_CREDENTIALS, sizeof(scm->creds), &scm->creds);
if (!scm->fp)
diff --git a/include/net/slhc_vj.h b/include/net/slhc_vj.h
index 0a85dc0143362..0b2c2784f3334 100644
--- a/include/net/slhc_vj.h
+++ b/include/net/slhc_vj.h
@@ -185,7 +185,4 @@ int slhc_remember __ARGS((struct slcompress *comp, unsigned char *icp,
int isize));
int slhc_toss __ARGS((struct slcompress *comp));
-void slhc_i_status __ARGS((struct slcompress *comp));
-void slhc_o_status __ARGS((struct slcompress *comp));
-
#endif /* _SLHC_H */
diff --git a/include/net/sock.h b/include/net/sock.h
index dc9a2bdf99c7e..fb789af4ab088 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -61,10 +61,10 @@
* the other protocols.
*/
-/* Define this to get the sk->sk_debug debugging facility. */
+/* Define this to get the SOCK_DBG debugging facility. */
#define SOCK_DEBUGGING
#ifdef SOCK_DEBUGGING
-#define SOCK_DEBUG(sk, msg...) do { if ((sk) && ((sk)->sk_debug)) \
+#define SOCK_DEBUG(sk, msg...) do { if ((sk) && sock_flag((sk), SOCK_DBG)) \
printk(KERN_DEBUG msg); } while (0)
#else
#define SOCK_DEBUG(sk, msg...) do { } while (0)
@@ -115,9 +115,7 @@ struct sock_common {
/**
* struct sock - network layer representation of sockets
* @__sk_common - shared layout with tcp_tw_bucket
- * @sk_zapped - ax25 & ipx means !linked
* @sk_shutdown - mask of %SEND_SHUTDOWN and/or %RCV_SHUTDOWN
- * @sk_use_write_queue - wheter to call sk->sk_write_space in sock_wfree
* @sk_userlocks - %SO_SNDBUF and %SO_RCVBUF settings
* @sk_lock - synchronizer
* @sk_rcvbuf - size of receive buffer in bytes
@@ -136,9 +134,6 @@ struct sock_common {
* @sk_sndbuf - size of send buffer in bytes
* @sk_flags - %SO_LINGER (l_onoff), %SO_BROADCAST, %SO_KEEPALIVE, %SO_OOBINLINE settings
* @sk_no_check - %SO_NO_CHECK setting, wether or not checkup packets
- * @sk_debug - %SO_DEBUG setting
- * @sk_rcvtstamp - %SO_TIMESTAMP setting
- * @sk_no_largesend - whether to sent large segments or not
* @sk_route_caps - route capabilities (e.g. %NETIF_F_TSO)
* @sk_lingertime - %SO_LINGER l_linger setting
* @sk_hashent - hash entry in several tables (e.g. tcp_ehash)
@@ -152,7 +147,6 @@ struct sock_common {
* @sk_max_ack_backlog - listen backlog set in listen()
* @sk_priority - %SO_PRIORITY setting
* @sk_type - socket type (%SOCK_STREAM, etc)
- * @sk_localroute - route locally only, %SO_DONTROUTE setting
* @sk_protocol - which protocol this socket belongs in this network family
* @sk_peercred - %SO_PEERCRED setting
* @sk_rcvlowat - %SO_RCVLOWAT setting
@@ -170,7 +164,6 @@ struct sock_common {
* @sk_sndmsg_off - cached offset for sendmsg
* @sk_send_head - front of stuff to transmit
* @sk_write_pending - a write to stream socket waits to start
- * @sk_queue_shrunk - write queue has been shrunk recently
* @sk_state_change - callback to indicate change in the state of the sock
* @sk_data_ready - callback to indicate there is data to be processed
* @sk_write_space - callback to indicate there is bf sending space available
@@ -191,33 +184,30 @@ struct sock {
#define sk_node __sk_common.skc_node
#define sk_bind_node __sk_common.skc_bind_node
#define sk_refcnt __sk_common.skc_refcnt
- volatile unsigned char sk_zapped;
- unsigned char sk_shutdown;
- unsigned char sk_use_write_queue;
- unsigned char sk_userlocks;
- socket_lock_t sk_lock;
+ unsigned char sk_shutdown : 2,
+ sk_no_check : 2,
+ sk_userlocks : 4;
+ unsigned char sk_protocol;
+ unsigned short sk_type;
int sk_rcvbuf;
+ socket_lock_t sk_lock;
wait_queue_head_t *sk_sleep;
struct dst_entry *sk_dst_cache;
- rwlock_t sk_dst_lock;
struct xfrm_policy *sk_policy[2];
+ rwlock_t sk_dst_lock;
atomic_t sk_rmem_alloc;
- struct sk_buff_head sk_receive_queue;
atomic_t sk_wmem_alloc;
- struct sk_buff_head sk_write_queue;
atomic_t sk_omem_alloc;
+ struct sk_buff_head sk_receive_queue;
+ struct sk_buff_head sk_write_queue;
int sk_wmem_queued;
int sk_forward_alloc;
unsigned int sk_allocation;
int sk_sndbuf;
- unsigned long sk_flags;
- char sk_no_check;
- unsigned char sk_debug;
- unsigned char sk_rcvtstamp;
- unsigned char sk_no_largesend;
int sk_route_caps;
- unsigned long sk_lingertime;
int sk_hashent;
+ unsigned long sk_flags;
+ unsigned long sk_lingertime;
/*
* The backlog queue is special, it is always used with
* the per-socket spinlock held and requires low latency
@@ -227,17 +217,14 @@ struct sock {
struct sk_buff *head;
struct sk_buff *tail;
} sk_backlog;
- rwlock_t sk_callback_lock;
struct sk_buff_head sk_error_queue;
struct proto *sk_prot;
+ rwlock_t sk_callback_lock;
int sk_err,
sk_err_soft;
unsigned short sk_ack_backlog;
unsigned short sk_max_ack_backlog;
__u32 sk_priority;
- unsigned short sk_type;
- unsigned char sk_localroute;
- unsigned char sk_protocol;
struct ucred sk_peercred;
int sk_rcvlowat;
long sk_rcvtimeo;
@@ -251,12 +238,10 @@ struct sock {
void *sk_user_data;
struct module *sk_owner;
struct page *sk_sndmsg_page;
- __u32 sk_sndmsg_off;
struct sk_buff *sk_send_head;
+ __u32 sk_sndmsg_off;
int sk_write_pending;
void *sk_security;
- __u8 sk_queue_shrunk;
- /* three bytes hole, try to pack */
void (*sk_state_change)(struct sock *sk);
void (*sk_data_ready)(struct sock *sk, int bytes);
void (*sk_write_space)(struct sock *sk);
@@ -391,6 +376,13 @@ enum sock_flags {
SOCK_DESTROY,
SOCK_BROADCAST,
SOCK_TIMESTAMP,
+ SOCK_ZAPPED,
+ SOCK_USE_WRITE_QUEUE, /* whether to call sk->sk_write_space in sock_wfree */
+ SOCK_DBG, /* %SO_DEBUG setting */
+ SOCK_RCVTSTAMP, /* %SO_TIMESTAMP setting */
+ SOCK_NO_LARGESEND, /* whether to sent large segments or not */
+ SOCK_LOCALROUTE, /* route locally only, %SO_DONTROUTE setting */
+ SOCK_QUEUE_SHRUNK, /* write queue has been shrunk recently */
};
static inline void sock_set_flag(struct sock *sk, enum sock_flags flag)
@@ -455,7 +447,7 @@ static inline void sk_stream_set_owner_r(struct sk_buff *skb, struct sock *sk)
static inline void sk_stream_free_skb(struct sock *sk, struct sk_buff *skb)
{
- sk->sk_queue_shrunk = 1;
+ sock_set_flag(sk, SOCK_QUEUE_SHRUNK);
sk->sk_wmem_queued -= skb->truesize;
sk->sk_forward_alloc += skb->truesize;
__kfree_skb(skb);
@@ -569,11 +561,6 @@ struct proto {
extern int sk_alloc_slab(struct proto *prot, char *name);
extern void sk_free_slab(struct proto *prot);
-static inline void sk_alloc_slab_error(struct proto *proto)
-{
- printk(KERN_CRIT "%s: Can't create sock SLAB cache!\n", proto->name);
-}
-
static __inline__ void sk_set_owner(struct sock *sk, struct module *owner)
{
/*
@@ -983,6 +970,7 @@ __sk_dst_check(struct sock *sk, u32 cookie)
if (dst && dst->obsolete && dst->ops->check(dst, cookie) == NULL) {
sk->sk_dst_cache = NULL;
+ dst_release(dst);
return NULL;
}
@@ -996,6 +984,7 @@ sk_dst_check(struct sock *sk, u32 cookie)
if (dst && dst->obsolete && dst->ops->check(dst, cookie) == NULL) {
sk_dst_reset(sk);
+ dst_release(dst);
return NULL;
}
@@ -1240,7 +1229,7 @@ static __inline__ void
sock_recv_timestamp(struct msghdr *msg, struct sock *sk, struct sk_buff *skb)
{
struct timeval *stamp = &skb->stamp;
- if (sk->sk_rcvtstamp) {
+ if (sock_flag(sk, SOCK_RCVTSTAMP)) {
/* Race occurred between timestamp enabling and packet
receiving. Fill in the current time for now. */
if (stamp->tv_sec == 0)
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 7355606725d40..503810a70e21e 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -1039,6 +1039,7 @@ static inline void tcp_reset_xmit_timer(struct sock *sk, int what, unsigned long
#ifdef TCP_DEBUG
printk(tcp_timer_bug_msg);
#endif
+ return;
};
}
@@ -1914,7 +1915,7 @@ static inline void tcp_v4_setup_caps(struct sock *sk, struct dst_entry *dst)
{
sk->sk_route_caps = dst->dev->features;
if (sk->sk_route_caps & NETIF_F_TSO) {
- if (sk->sk_no_largesend || dst->header_len)
+ if (sock_flag(sk, SOCK_NO_LARGESEND) || dst->header_len)
sk->sk_route_caps &= ~NETIF_F_TSO;
}
}
diff --git a/include/net/tcp_ecn.h b/include/net/tcp_ecn.h
index 773c00b5a89b3..dc1456389a972 100644
--- a/include/net/tcp_ecn.h
+++ b/include/net/tcp_ecn.h
@@ -33,7 +33,7 @@ static inline void TCP_ECN_send_syn(struct sock *sk, struct tcp_sock *tp,
if (sysctl_tcp_ecn && !(sk->sk_route_caps & NETIF_F_TSO)) {
TCP_SKB_CB(skb)->flags |= TCPCB_FLAG_ECE|TCPCB_FLAG_CWR;
tp->ecn_flags = TCP_ECN_OK;
- sk->sk_no_largesend = 1;
+ sock_set_flag(sk, SOCK_NO_LARGESEND);
}
}
diff --git a/include/net/x25.h b/include/net/x25.h
index 4d64a0bc2b0db..7a1ba5bbb8686 100644
--- a/include/net/x25.h
+++ b/include/net/x25.h
@@ -10,6 +10,7 @@
#ifndef _X25_H
#define _X25_H
#include <linux/x25.h>
+#include <net/sock.h>
#define X25_ADDR_LEN 16
@@ -129,7 +130,8 @@ struct x25_neigh {
atomic_t refcnt;
};
-struct x25_opt {
+struct x25_sock {
+ struct sock sk;
struct x25_address source_addr, dest_addr;
struct x25_neigh *neighbour;
unsigned int lci;
@@ -141,7 +143,6 @@ struct x25_opt {
struct sk_buff_head fragment_queue;
struct sk_buff_head interrupt_in_queue;
struct sk_buff_head interrupt_out_queue;
- struct sock *sk; /* Backlink to socket */
struct timer_list timer;
struct x25_causediag causediag;
struct x25_facilities facilities;
@@ -149,7 +150,10 @@ struct x25_opt {
unsigned long vc_facil_mask; /* inc_call facilities mask */
};
-#define x25_sk(__sk) ((struct x25_opt *)(__sk)->sk_protinfo)
+static inline struct x25_sock *x25_sk(const struct sock *sk)
+{
+ return (struct x25_sock *)sk;
+}
/* af_x25.c */
extern int sysctl_x25_restart_request_timeout;
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 40222ee714553..73e9a8ca3d3b7 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -212,7 +212,7 @@ struct xfrm_type
void (*destructor)(struct xfrm_state *);
int (*input)(struct xfrm_state *, struct xfrm_decap_state *, struct sk_buff *skb);
int (*post_input)(struct xfrm_state *, struct xfrm_decap_state *, struct sk_buff *skb);
- int (*output)(struct sk_buff *pskb);
+ int (*output)(struct xfrm_state *, struct sk_buff *pskb);
/* Estimate maximal size of result of transformation of a dgram */
u32 (*get_max_size)(struct xfrm_state *, int size);
};
@@ -511,6 +511,9 @@ struct xfrm_dst
struct rtable rt;
struct rt6_info rt6;
} u;
+ struct dst_entry *route;
+ u32 route_mtu_cached;
+ u32 child_mtu_cached;
};
/* Decapsulation state, used by the input to store data during
@@ -807,6 +810,7 @@ extern void xfrm_state_flush(u8 proto);
extern int xfrm_replay_check(struct xfrm_state *x, u32 seq);
extern void xfrm_replay_advance(struct xfrm_state *x, u32 seq);
extern int xfrm_state_check(struct xfrm_state *x, struct sk_buff *skb);
+extern int xfrm_state_mtu(struct xfrm_state *x, int mtu);
extern int xfrm4_rcv(struct sk_buff *skb);
extern int xfrm4_output(struct sk_buff *skb);
extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler);
@@ -857,6 +861,8 @@ struct xfrm_state * xfrm_find_acq(u8 mode, u32 reqid, u8 proto,
extern void xfrm_policy_flush(void);
extern int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol);
extern int xfrm_flush_bundles(void);
+extern int xfrm_bundle_ok(struct xfrm_dst *xdst, struct flowi *fl, int family);
+extern void xfrm_init_pmtu(struct dst_entry *dst);
extern wait_queue_head_t km_waitq;
extern int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, u16 sport);
diff --git a/include/pcmcia/ds.h b/include/pcmcia/ds.h
index 1a7a03d8623ab..312fd958c9014 100644
--- a/include/pcmcia/ds.h
+++ b/include/pcmcia/ds.h
@@ -169,6 +169,21 @@ struct pcmcia_device {
event_callback_args_t event_callback_args;
} client;
+ /* information about this device */
+ u8 has_manf_id:1;
+ u8 has_card_id:1;
+ u8 has_func_id:1;
+ u8 reserved:5;
+
+ u8 func_id;
+ u16 manf_id;
+ u16 card_id;
+
+ char * prod_id[4];
+
+ /* device driver wanted by cardmgr */
+ struct pcmcia_driver * cardmgr;
+
struct device dev;
};
diff --git a/include/pcmcia/ss.h b/include/pcmcia/ss.h
index 49e1213dd5440..6d3413a567081 100644
--- a/include/pcmcia/ss.h
+++ b/include/pcmcia/ss.h
@@ -203,6 +203,17 @@ struct pcmcia_socket {
u_char pci_irq;
struct pci_dev * cb_dev;
+
+ /* socket setup is done so resources should be able to be allocated. Only
+ * if set to 1, calls to find_{io,mem}_region are handled, and insertion
+ * events are actually managed by the PCMCIA layer.*/
+ u8 resource_setup_done:1;
+
+ /* is set to one if resource setup is done using adjust_resource_info() */
+ u8 resource_setup_old:1;
+
+ u8 reserved:6;
+
/* socket operations */
struct pccard_operations * ops;
struct pccard_resource_ops * resource_ops;
@@ -248,7 +259,7 @@ extern void pcmcia_unregister_socket(struct pcmcia_socket *socket);
extern struct class pcmcia_socket_class;
/* socket drivers are expected to use these callbacks in their .drv struct */
-extern int pcmcia_socket_dev_suspend(struct device *dev, u32 state);
+extern int pcmcia_socket_dev_suspend(struct device *dev, pm_message_t state);
extern int pcmcia_socket_dev_resume(struct device *dev);
#endif /* _LINUX_SS_H */
diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h
index aba6f539e1935..1d54c063ae52f 100644
--- a/include/scsi/scsi.h
+++ b/include/scsi/scsi.h
@@ -169,8 +169,10 @@ static inline int scsi_status_is_good(int status)
#define RESERVATION_CONFLICT 0x0c
#define COMMAND_TERMINATED 0x11
#define QUEUE_FULL 0x14
+#define ACA_ACTIVE 0x18
+#define TASK_ABORTED 0x20
-#define STATUS_MASK 0x3e
+#define STATUS_MASK 0xfe
/*
* SENSE KEYS
@@ -348,7 +350,7 @@ struct scsi_lun {
* host_byte = set by low-level driver to indicate status.
* driver_byte = set by mid-level.
*/
-#define status_byte(result) (((result) >> 1) & 0x1f)
+#define status_byte(result) (((result) >> 1) & 0x7f)
#define msg_byte(result) (((result) >> 8) & 0xff)
#define host_byte(result) (((result) >> 16) & 0xff)
#define driver_byte(result) (((result) >> 24) & 0xff)
diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h
index cc7cd129b9c0f..9d9871c28abdc 100644
--- a/include/scsi/scsi_cmnd.h
+++ b/include/scsi/scsi_cmnd.h
@@ -54,6 +54,7 @@ struct scsi_cmnd {
* completed and the SCSI Command structure has already being reused
* for another command, so that we can avoid incorrectly aborting or
* resetting the new command.
+ * The serial number is only unique per host.
*/
unsigned long serial_number;
unsigned long serial_number_at_timeout;
@@ -139,7 +140,7 @@ struct scsi_cmnd {
int result; /* Status code from lower level driver */
unsigned char tag; /* SCSI-II queued command tag */
- unsigned long pid; /* Process ID, starts at 0 */
+ unsigned long pid; /* Process ID, starts at 0. Unique per host. */
};
/*
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
index 53e3d08d8a995..07d974051b0c1 100644
--- a/include/scsi/scsi_device.h
+++ b/include/scsi/scsi_device.h
@@ -112,12 +112,17 @@ struct scsi_device {
unsigned no_uld_attach:1; /* disable connecting to upper level drivers */
unsigned select_no_atn:1;
unsigned fix_capacity:1; /* READ_CAPACITY is too high by 1 */
+ unsigned retry_hwerror:1; /* Retry HARDWARE_ERROR */
unsigned int device_blocked; /* Device returned QUEUE_FULL. */
unsigned int max_device_blocked; /* what device_blocked counts down from */
#define SCSI_DEFAULT_DEVICE_BLOCKED 3
+ atomic_t iorequest_cnt;
+ atomic_t iodone_cnt;
+ atomic_t ioerr_cnt;
+
int timeout;
struct device sdev_gendev;
@@ -140,7 +145,10 @@ struct scsi_device {
*/
struct scsi_target {
struct scsi_device *starget_sdev_user;
+ struct list_head siblings;
+ struct list_head devices;
struct device dev;
+ unsigned int reap_ref; /* protected by the host lock */
unsigned int channel;
unsigned int id; /* target id ... replace
* scsi_device.id eventually */
@@ -169,6 +177,10 @@ extern struct scsi_device *scsi_device_lookup(struct Scsi_Host *,
uint, uint, uint);
extern struct scsi_device *__scsi_device_lookup(struct Scsi_Host *,
uint, uint, uint);
+extern struct scsi_device *scsi_device_lookup_by_target(struct scsi_target *,
+ uint);
+extern struct scsi_device *__scsi_device_lookup_by_target(struct scsi_target *,
+ uint);
extern void starget_for_each_device(struct scsi_target *, void *,
void (*fn)(struct scsi_device *, void *));
@@ -222,6 +234,12 @@ extern int scsi_device_quiesce(struct scsi_device *sdev);
extern void scsi_device_resume(struct scsi_device *sdev);
extern void scsi_target_quiesce(struct scsi_target *);
extern void scsi_target_resume(struct scsi_target *);
+extern void scsi_scan_target(struct device *parent, unsigned int channel,
+ unsigned int id, unsigned int lun, int rescan);
+extern void scsi_target_reap(struct scsi_target *);
+extern void scsi_target_block(struct device *);
+extern void scsi_target_unblock(struct device *);
+extern void scsi_remove_target(struct device *);
extern const char *scsi_device_state_name(enum scsi_device_state);
extern int scsi_is_sdev_device(const struct device *);
extern int scsi_is_target_device(const struct device *);
diff --git a/include/scsi/scsi_devinfo.h b/include/scsi/scsi_devinfo.h
index ea263c881be82..174101b2069bb 100644
--- a/include/scsi/scsi_devinfo.h
+++ b/include/scsi/scsi_devinfo.h
@@ -27,4 +27,5 @@
#define BLIST_NOT_LOCKABLE 0x80000 /* don't use PREVENT-ALLOW commands */
#define BLIST_NO_ULD_ATTACH 0x100000 /* device is actually for RAID config */
#define BLIST_SELECT_NO_ATN 0x200000 /* select without ATN */
+#define BLIST_RETRY_HWERROR 0x400000 /* retry HARDWARE_ERROR */
#endif
diff --git a/include/scsi/scsi_driver.h b/include/scsi/scsi_driver.h
index 98c2e33f6159a..850dfa877fdab 100644
--- a/include/scsi/scsi_driver.h
+++ b/include/scsi/scsi_driver.h
@@ -14,6 +14,8 @@ struct scsi_driver {
int (*init_command)(struct scsi_cmnd *);
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 191b8fced8ac6..27f2c4e8943ac 100644
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -4,6 +4,7 @@
#include <linux/device.h>
#include <linux/list.h>
#include <linux/types.h>
+#include <linux/workqueue.h>
struct block_device;
struct module;
@@ -363,6 +364,12 @@ struct scsi_host_template {
unsigned skip_settle_delay:1;
/*
+ * ordered write support
+ */
+ unsigned ordered_flush:1;
+ unsigned ordered_tag:1;
+
+ /*
* Countdown for host blocking with no commands outstanding
*/
unsigned int max_host_blocked;
@@ -416,6 +423,7 @@ struct Scsi_Host {
* access this list directly from a driver.
*/
struct list_head __devices;
+ struct list_head __targets;
struct scsi_host_cmd_pool *cmd_pool;
spinlock_t free_list_lock;
@@ -483,7 +491,12 @@ struct Scsi_Host {
short unsigned int sg_tablesize;
short unsigned int max_sectors;
unsigned long dma_boundary;
-
+ /*
+ * Used to assign serial numbers to the cmds.
+ * Protected by the host lock.
+ */
+ unsigned long cmd_serial_number, cmd_pid;
+
unsigned unchecked_isa_dma:1;
unsigned use_clustering:1;
unsigned use_blk_tcq:1;
@@ -502,6 +515,18 @@ struct Scsi_Host {
unsigned reverse_ordering:1;
/*
+ * ordered write support
+ */
+ unsigned ordered_flush:1;
+ unsigned ordered_tag:1;
+
+ /*
+ * Optional work queue to be utilized by the transport
+ */
+ char work_q_name[KOBJ_NAME_LEN];
+ struct workqueue_struct *work_q;
+
+ /*
* Host has rejected a command because it was busy.
*/
unsigned int host_blocked;
@@ -548,11 +573,24 @@ struct Scsi_Host {
unsigned long hostdata[0] /* Used for storage of host specific stuff */
__attribute__ ((aligned (sizeof(unsigned long))));
};
-#define dev_to_shost(d) \
- container_of(d, struct Scsi_Host, shost_gendev)
+
#define class_to_shost(d) \
container_of(d, struct Scsi_Host, shost_classdev)
+int scsi_is_host_device(const struct device *);
+
+static inline struct Scsi_Host *dev_to_shost(struct device *dev)
+{
+ while (!scsi_is_host_device(dev)) {
+ if (!dev->parent)
+ return NULL;
+ dev = dev->parent;
+ }
+ return container_of(dev, struct Scsi_Host, shost_gendev);
+}
+
+extern int scsi_queue_work(struct Scsi_Host *, struct work_struct *);
+extern void scsi_flush_work(struct Scsi_Host *);
extern struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *, int);
extern int __must_check scsi_add_host(struct Scsi_Host *, struct device *);
@@ -596,8 +634,6 @@ struct class_container;
*/
extern void scsi_free_host_dev(struct scsi_device *);
extern struct scsi_device *scsi_get_host_dev(struct Scsi_Host *);
-int scsi_is_host_device(const struct device *);
-
/* legacy interfaces */
extern struct Scsi_Host *scsi_register(struct scsi_host_template *, int);
diff --git a/include/scsi/scsi_transport.h b/include/scsi/scsi_transport.h
index 889849a1f5b60..2dcee7a84752c 100644
--- a/include/scsi/scsi_transport.h
+++ b/include/scsi/scsi_transport.h
@@ -23,13 +23,10 @@
#include <linux/transport_class.h>
struct scsi_transport_template {
- /* The statistics attached to the host class only */
- struct attribute_group *host_statistics;
-
/* the attribute containers */
- struct attribute_container host_attrs;
- struct attribute_container target_attrs;
- struct attribute_container device_attrs;
+ struct transport_container host_attrs;
+ struct transport_container target_attrs;
+ struct transport_container device_attrs;
/* The size of the specific transport attribute structure (a
* space of this size will be left at the end of the
@@ -37,6 +34,11 @@ struct scsi_transport_template {
int device_size;
int target_size;
int host_size;
+
+ /*
+ * True if the transport wants to use a host-based work-queue
+ */
+ unsigned int create_work_queue : 1;
};
#define transport_class_to_shost(tc) \
diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h
index 1d4adfd6d3e9a..70ad16315a16f 100644
--- a/include/scsi/scsi_transport_fc.h
+++ b/include/scsi/scsi_transport_fc.h
@@ -16,6 +16,13 @@
* You should have received a copy of the 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) 2004-2005 James Smart, Emulex Corporation
+ * Rewrite for host, target, device, and remote port attributes,
+ * statistics, and service functions...
+ *
*/
#ifndef SCSI_TRANSPORT_FC_H
#define SCSI_TRANSPORT_FC_H
@@ -61,8 +68,10 @@ enum fc_port_type {
*/
enum fc_port_state {
FC_PORTSTATE_UNKNOWN,
+ FC_PORTSTATE_NOTPRESENT,
FC_PORTSTATE_ONLINE,
FC_PORTSTATE_OFFLINE, /* User has taken Port Offline */
+ FC_PORTSTATE_BLOCKED,
FC_PORTSTATE_BYPASSED,
FC_PORTSTATE_DIAGNOSTICS,
FC_PORTSTATE_LINKDOWN,
@@ -103,35 +112,134 @@ enum fc_port_state {
* scsi_transport_fc.c (for the ascii descriptions).
*/
enum fc_tgtid_binding_type {
+ FC_TGTID_BIND_NONE,
FC_TGTID_BIND_BY_WWPN,
FC_TGTID_BIND_BY_WWNN,
FC_TGTID_BIND_BY_ID,
};
+/*
+ * FC Remote Port Roles
+ * Note: values are not enumerated, as they can be "or'd" together
+ * for reporting (e.g. report roles). If you alter this list,
+ * you also need to alter scsi_transport_fc.c (for the ascii descriptions).
+ */
+#define FC_RPORT_ROLE_UNKNOWN 0x00
+#define FC_RPORT_ROLE_FCP_TARGET 0x01
+#define FC_RPORT_ROLE_FCP_INITIATOR 0x02
+#define FC_RPORT_ROLE_IP_PORT 0x04
+
+
+/*
+ * fc_rport_identifiers: This set of data contains all elements
+ * to uniquely identify a remote FC port. The driver uses this data
+ * to report the existence of a remote FC port in the topology. Internally,
+ * the transport uses this data for attributes and to manage consistent
+ * target id bindings.
+ */
+struct fc_rport_identifiers {
+ u64 node_name;
+ u64 port_name;
+ u32 port_id;
+ u32 roles;
+};
+
+/* Macro for use in defining Remote Port attributes */
+#define FC_RPORT_ATTR(_name,_mode,_show,_store) \
+struct class_device_attribute class_device_attr_rport_##_name = \
+ __ATTR(_name,_mode,_show,_store)
/*
- * FC Remote Port (Target) Attributes
+ * FC Remote Port Attributes
+ *
+ * This structure exists for each remote FC port that a LLDD notifies
+ * the subsystem of. A remote FC port may or may not be a SCSI Target,
+ * also be a SCSI initiator, IP endpoint, etc. As such, the remote
+ * port is considered a separate entity, independent of "role" (such
+ * as scsi target).
+ *
+ * --
+ *
+ * Attributes are based on HBAAPI V2.0 definitions. Only those
+ * attributes that are determinable by the local port (aka Host)
+ * are contained.
+ *
+ * Fixed attributes are not expected to change. The driver is
+ * expected to set these values after successfully calling
+ * fc_remote_port_add(). The transport fully manages all get functions
+ * w/o driver interaction.
+ *
+ * Dynamic attributes are expected to change. The driver participates
+ * in all get/set operations via functions provided by the driver.
+ *
+ * Private attributes are transport-managed values. They are fully
+ * managed by the transport w/o driver interaction.
+ */
+
+struct fc_rport { /* aka fc_starget_attrs */
+ /* Fixed Attributes */
+ u32 maxframe_size;
+ u32 supported_classes;
+
+ /* Dynamic Attributes */
+ u32 dev_loss_tmo; /* Remote Port loss timeout in seconds. */
+
+ /* Private (Transport-managed) Attributes */
+ u64 node_name;
+ u64 port_name;
+ u32 port_id;
+ u32 roles;
+ enum fc_port_state port_state; /* Will only be ONLINE or UNKNOWN */
+ u32 scsi_target_id;
+
+ /* exported data */
+ void *dd_data; /* Used for driver-specific storage */
+
+ /* internal data */
+ unsigned int channel;
+ u32 number;
+ struct list_head peers;
+ struct device dev;
+ struct work_struct dev_loss_work;
+ struct work_struct scan_work;
+} __attribute__((aligned(sizeof(unsigned long))));
+
+#define dev_to_rport(d) \
+ container_of(d, struct fc_rport, dev)
+#define transport_class_to_rport(classdev) \
+ dev_to_rport(classdev->dev)
+#define rport_to_shost(r) \
+ dev_to_shost(r->dev.parent)
+
+/*
+ * FC SCSI Target Attributes
+ *
+ * The SCSI Target is considered an extention of a remote port (as
+ * a remote port can be more than a SCSI Target). Within the scsi
+ * subsystem, we leave the Target as a separate entity. Doing so
+ * provides backward compatibility with prior FC transport api's,
+ * and lets remote ports be handled entirely within the FC transport
+ * and independently from the scsi subsystem. The drawback is that
+ * some data will be duplicated.
*/
struct fc_starget_attrs { /* aka fc_target_attrs */
- int port_id;
+ /* Dynamic Attributes */
u64 node_name;
u64 port_name;
- u32 dev_loss_tmo; /* Remote Port loss timeout in seconds. */
- struct work_struct dev_loss_work;
+ u32 port_id;
};
-#define fc_starget_port_id(x) \
- (((struct fc_starget_attrs *)&(x)->starget_data)->port_id)
#define fc_starget_node_name(x) \
(((struct fc_starget_attrs *)&(x)->starget_data)->node_name)
#define fc_starget_port_name(x) \
(((struct fc_starget_attrs *)&(x)->starget_data)->port_name)
-#define fc_starget_dev_loss_tmo(x) \
- (((struct fc_starget_attrs *)&(x)->starget_data)->dev_loss_tmo)
-#define fc_starget_dev_loss_work(x) \
- (((struct fc_starget_attrs *)&(x)->starget_data)->dev_loss_work)
+#define fc_starget_port_id(x) \
+ (((struct fc_starget_attrs *)&(x)->starget_data)->port_id)
+
+#define starget_to_rport(s) \
+ scsi_is_fc_rport(s->dev.parent) ? dev_to_rport(s->dev.parent) : NULL
/*
@@ -197,11 +305,7 @@ struct fc_host_attrs {
char symbolic_name[FC_SYMBOLIC_NAME_SIZE];
u32 supported_speeds;
u32 maxframe_size;
- char hardware_version[FC_VERSION_STRING_SIZE];
- char firmware_version[FC_VERSION_STRING_SIZE];
char serial_number[FC_SERIAL_NUMBER_SIZE];
- char opt_rom_version[FC_VERSION_STRING_SIZE];
- char driver_version[FC_VERSION_STRING_SIZE];
/* Dynamic Attributes */
u32 port_id;
@@ -210,13 +314,15 @@ struct fc_host_attrs {
u8 active_fc4s[FC_FC4_LIST_SIZE];
u32 speed;
u64 fabric_name;
- u32 link_down_tmo; /* Link Down timeout in seconds. */
/* Private (Transport-managed) Attributes */
enum fc_tgtid_binding_type tgtid_bind_type;
/* internal data */
- struct work_struct link_down_work;
+ struct list_head rports;
+ struct list_head rport_bindings;
+ u32 next_rport_number;
+ u32 next_target_id;
};
#define fc_host_node_name(x) \
@@ -233,16 +339,8 @@ struct fc_host_attrs {
(((struct fc_host_attrs *)(x)->shost_data)->supported_speeds)
#define fc_host_maxframe_size(x) \
(((struct fc_host_attrs *)(x)->shost_data)->maxframe_size)
-#define fc_host_hardware_version(x) \
- (((struct fc_host_attrs *)(x)->shost_data)->hardware_version)
-#define fc_host_firmware_version(x) \
- (((struct fc_host_attrs *)(x)->shost_data)->firmware_version)
#define fc_host_serial_number(x) \
(((struct fc_host_attrs *)(x)->shost_data)->serial_number)
-#define fc_host_opt_rom_version(x) \
- (((struct fc_host_attrs *)(x)->shost_data)->opt_rom_version)
-#define fc_host_driver_version(x) \
- (((struct fc_host_attrs *)(x)->shost_data)->driver_version)
#define fc_host_port_id(x) \
(((struct fc_host_attrs *)(x)->shost_data)->port_id)
#define fc_host_port_type(x) \
@@ -255,21 +353,26 @@ struct fc_host_attrs {
(((struct fc_host_attrs *)(x)->shost_data)->speed)
#define fc_host_fabric_name(x) \
(((struct fc_host_attrs *)(x)->shost_data)->fabric_name)
-#define fc_host_link_down_tmo(x) \
- (((struct fc_host_attrs *)(x)->shost_data)->link_down_tmo)
#define fc_host_tgtid_bind_type(x) \
(((struct fc_host_attrs *)(x)->shost_data)->tgtid_bind_type)
-#define fc_host_link_down_work(x) \
- (((struct fc_host_attrs *)(x)->shost_data)->link_down_work)
+#define fc_host_rports(x) \
+ (((struct fc_host_attrs *)(x)->shost_data)->rports)
+#define fc_host_rport_bindings(x) \
+ (((struct fc_host_attrs *)(x)->shost_data)->rport_bindings)
+#define fc_host_next_rport_number(x) \
+ (((struct fc_host_attrs *)(x)->shost_data)->next_rport_number)
+#define fc_host_next_target_id(x) \
+ (((struct fc_host_attrs *)(x)->shost_data)->next_target_id)
/* The functions by which the transport class and the driver communicate */
struct fc_function_template {
- void (*get_starget_port_id)(struct scsi_target *);
+ void (*get_rport_dev_loss_tmo)(struct fc_rport *);
+ void (*set_rport_dev_loss_tmo)(struct fc_rport *, u32);
+
void (*get_starget_node_name)(struct scsi_target *);
void (*get_starget_port_name)(struct scsi_target *);
- void (*get_starget_dev_loss_tmo)(struct scsi_target *);
- void (*set_starget_dev_loss_tmo)(struct scsi_target *, u32);
+ void (*get_starget_port_id)(struct scsi_target *);
void (*get_host_port_id)(struct Scsi_Host *);
void (*get_host_port_type)(struct Scsi_Host *);
@@ -277,22 +380,33 @@ struct fc_function_template {
void (*get_host_active_fc4s)(struct Scsi_Host *);
void (*get_host_speed)(struct Scsi_Host *);
void (*get_host_fabric_name)(struct Scsi_Host *);
- void (*get_host_link_down_tmo)(struct Scsi_Host *);
- void (*set_host_link_down_tmo)(struct Scsi_Host *, u32);
struct fc_host_statistics * (*get_fc_host_stats)(struct Scsi_Host *);
void (*reset_fc_host_stats)(struct Scsi_Host *);
+ /* allocation lengths for host-specific data */
+ u32 dd_fcrport_size;
+
/*
* The driver sets these to tell the transport class it
* wants the attributes displayed in sysfs. If the show_ flag
* is not set, the attribute will be private to the transport
* class
*/
- unsigned long show_starget_port_id:1;
+
+ /* remote port fixed attributes */
+ unsigned long show_rport_maxframe_size:1;
+ unsigned long show_rport_supported_classes:1;
+ unsigned long show_rport_dev_loss_tmo:1;
+
+ /*
+ * target dynamic attributes
+ * These should all be "1" if the driver uses the remote port
+ * add/delete functions (so attributes reflect rport values).
+ */
unsigned long show_starget_node_name:1;
unsigned long show_starget_port_name:1;
- unsigned long show_starget_dev_loss_tmo:1;
+ unsigned long show_starget_port_id:1;
/* host fixed attributes */
unsigned long show_host_node_name:1;
@@ -302,11 +416,7 @@ struct fc_function_template {
unsigned long show_host_symbolic_name:1;
unsigned long show_host_supported_speeds:1;
unsigned long show_host_maxframe_size:1;
- unsigned long show_host_hardware_version:1;
- unsigned long show_host_firmware_version:1;
unsigned long show_host_serial_number:1;
- unsigned long show_host_opt_rom_version:1;
- unsigned long show_host_driver_version:1;
/* host dynamic attributes */
unsigned long show_host_port_id:1;
unsigned long show_host_port_type:1;
@@ -314,15 +424,19 @@ struct fc_function_template {
unsigned long show_host_active_fc4s:1;
unsigned long show_host_speed:1;
unsigned long show_host_fabric_name:1;
- unsigned long show_host_link_down_tmo:1;
};
-struct scsi_transport_template *fc_attach_transport(struct fc_function_template *);
+struct scsi_transport_template *fc_attach_transport(
+ struct fc_function_template *);
void fc_release_transport(struct scsi_transport_template *);
-int fc_target_block(struct scsi_target *starget);
-void fc_target_unblock(struct scsi_target *starget);
-int fc_host_block(struct Scsi_Host *shost);
-void fc_host_unblock(struct Scsi_Host *shost);
+void fc_remove_host(struct Scsi_Host *);
+struct fc_rport *fc_remote_port_add(struct Scsi_Host *shost,
+ int channel, struct fc_rport_identifiers *ids);
+void fc_remote_port_delete(struct fc_rport *rport);
+void fc_remote_port_rolechg(struct fc_rport *rport, u32 roles);
+int fc_remote_port_block(struct fc_rport *rport);
+void fc_remote_port_unblock(struct fc_rport *rport);
+int scsi_is_fc_rport(const struct device *);
#endif /* SCSI_TRANSPORT_FC_H */
diff --git a/include/scsi/scsi_transport_spi.h b/include/scsi/scsi_transport_spi.h
index d18b22f427c3e..6dcf497bf46dc 100644
--- a/include/scsi/scsi_transport_spi.h
+++ b/include/scsi/scsi_transport_spi.h
@@ -130,5 +130,6 @@ struct scsi_transport_template *spi_attach_transport(struct spi_function_templat
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 *);
#endif /* SCSI_TRANSPORT_SPI_H */
diff --git a/include/sound/ac97_codec.h b/include/sound/ac97_codec.h
index d421d964cf634..2433e279e0712 100644
--- a/include/sound/ac97_codec.h
+++ b/include/sound/ac97_codec.h
@@ -356,6 +356,7 @@
#define AC97_SCAP_INDEP_SDIN (1<<6) /* independent SDIN */
#define AC97_SCAP_INV_EAPD (1<<7) /* inverted EAPD */
#define AC97_SCAP_DETECT_BY_VENDOR (1<<8) /* use vendor registers for read tests */
+#define AC97_SCAP_NO_SPDIF (1<<9) /* don't build SPDIF controls */
/* ac97->flags */
#define AC97_HAS_PC_BEEP (1<<0) /* force PC Speaker usage */
@@ -366,6 +367,13 @@
#define AC97_DOUBLE_RATE (1<<5) /* supports double rate playback */
#define AC97_HAS_NO_MASTER_VOL (1<<6) /* no Master volume */
#define AC97_HAS_NO_PCM_VOL (1<<7) /* no PCM volume */
+#define AC97_DEFAULT_POWER_OFF (1<<8) /* no RESET write */
+#define AC97_MODEM_PATCH (1<<9) /* modem patch */
+#define AC97_HAS_NO_REC_GAIN (1<<10) /* no Record gain */
+#define AC97_HAS_NO_PHONE (1<<11) /* no PHONE volume */
+#define AC97_HAS_NO_PC_BEEP (1<<12) /* no PC Beep volume */
+#define AC97_HAS_NO_VIDEO (1<<13) /* no Video volume */
+#define AC97_HAS_NO_CD (1<<14) /* no CD volume */
/* rates indexes */
#define AC97_RATES_FRONT_DAC 0
@@ -580,4 +588,11 @@ int snd_ac97_pcm_open(struct ac97_pcm *pcm, unsigned int rate,
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;
+};
#endif /* __SOUND_AC97_CODEC_H */
diff --git a/include/sound/ak4114.h b/include/sound/ak4114.h
new file mode 100644
index 0000000000000..f3f2c3e5ae516
--- /dev/null
+++ b/include/sound/ak4114.h
@@ -0,0 +1,205 @@
+#ifndef __SOUND_AK4114_H
+#define __SOUND_AK4114_H
+
+/*
+ * Routines for Asahi Kasei AK4114
+ * Copyright (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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* AK4114 registers */
+#define AK4114_REG_PWRDN 0x00 /* power down */
+#define AK4114_REG_FORMAT 0x01 /* format control */
+#define AK4114_REG_IO0 0x02 /* input/output control */
+#define AK4114_REG_IO1 0x03 /* input/output control */
+#define AK4114_REG_INT0_MASK 0x04 /* interrupt0 mask */
+#define AK4114_REG_INT1_MASK 0x05 /* interrupt1 mask */
+#define AK4114_REG_RCS0 0x06 /* receiver status 0 */
+#define AK4114_REG_RCS1 0x07 /* receiver status 1 */
+#define AK4114_REG_RXCSB0 0x08 /* RX channel status byte 0 */
+#define AK4114_REG_RXCSB1 0x09 /* RX channel status byte 1 */
+#define AK4114_REG_RXCSB2 0x0a /* RX channel status byte 2 */
+#define AK4114_REG_RXCSB3 0x0b /* RX channel status byte 3 */
+#define AK4114_REG_RXCSB4 0x0c /* RX channel status byte 4 */
+#define AK4114_REG_TXCSB0 0x0d /* TX channel status byte 0 */
+#define AK4114_REG_TXCSB1 0x0e /* TX channel status byte 1 */
+#define AK4114_REG_TXCSB2 0x0f /* TX channel status byte 2 */
+#define AK4114_REG_TXCSB3 0x10 /* TX channel status byte 3 */
+#define AK4114_REG_TXCSB4 0x11 /* TX channel status byte 4 */
+#define AK4114_REG_Pc0 0x12 /* burst preamble Pc byte 0 */
+#define AK4114_REG_Pc1 0x13 /* burst preamble Pc byte 1 */
+#define AK4114_REG_Pd0 0x14 /* burst preamble Pd byte 0 */
+#define AK4114_REG_Pd1 0x15 /* burst preamble Pd byte 1 */
+#define AK4114_REG_QSUB_ADDR 0x16 /* Q-subcode address + control */
+#define AK4114_REG_QSUB_TRACK 0x17 /* Q-subcode track */
+#define AK4114_REG_QSUB_INDEX 0x18 /* Q-subcode index */
+#define AK4114_REG_QSUB_MINUTE 0x19 /* Q-subcode minute */
+#define AK4114_REG_QSUB_SECOND 0x1a /* Q-subcode second */
+#define AK4114_REG_QSUB_FRAME 0x1b /* Q-subcode frame */
+#define AK4114_REG_QSUB_ZERO 0x1c /* Q-subcode zero */
+#define AK4114_REG_QSUB_ABSMIN 0x1d /* Q-subcode absolute minute */
+#define AK4114_REG_QSUB_ABSSEC 0x1e /* Q-subcode absolute second */
+#define AK4114_REG_QSUB_ABSFRM 0x1f /* Q-subcode absolute frame */
+
+/* sizes */
+#define AK4114_REG_RXCSB_SIZE ((AK4114_REG_RXCSB4-AK4114_REG_RXCSB0)+1)
+#define AK4114_REG_TXCSB_SIZE ((AK4114_REG_TXCSB4-AK4114_REG_TXCSB0)+1)
+#define AK4114_REG_QSUB_SIZE ((AK4114_REG_QSUB_ABSFRM-AK4114_REG_QSUB_ADDR)+1)
+
+/* AK4117_REG_PWRDN bits */
+#define AK4114_CS12 (1<<7) /* Channel Status Select */
+#define AK4114_BCU (1<<6) /* Block Start & C/U Output Mode */
+#define AK4114_CM1 (1<<5) /* Master Clock Operation Select */
+#define AK4114_CM0 (1<<4) /* Master Clock Operation Select */
+#define AK4114_OCKS1 (1<<3) /* Master Clock Frequency Select */
+#define AK4114_OCKS0 (1<<2) /* Master Clock Frequency Select */
+#define AK4114_PWN (1<<1) /* 0 = power down, 1 = normal operation */
+#define AK4114_RST (1<<0) /* 0 = reset & initialize (except this register), 1 = normal operation */
+
+/* AK4114_REQ_FORMAT bits */
+#define AK4114_MONO (1<<7) /* Double Sampling Frequency Mode: 0 = stereo, 1 = mono */
+#define AK4114_DIF2 (1<<5) /* Audio Data Control */
+#define AK4114_DIF1 (1<<5) /* Audio Data Control */
+#define AK4114_DIF0 (1<<4) /* Audio Data Control */
+#define AK4114_DIF_16R (0) /* STDO: 16-bit, right justified */
+#define AK4114_DIF_18R (AK4114_DIF0) /* STDO: 18-bit, right justified */
+#define AK4114_DIF_20R (AK4114_DIF1) /* STDO: 20-bit, right justified */
+#define AK4114_DIF_24R (AK4114_DIF1|AK4114_DIF0) /* STDO: 24-bit, right justified */
+#define AK4114_DIF_24L (AK4114_DIF2) /* STDO: 24-bit, left justified */
+#define AK4114_DIF_24I2S (AK4114_DIF2|AK4114_DIF0) /* STDO: I2S */
+#define AK4114_DIF_I24L (AK4114_DIF2|AK4114_DIF1) /* STDO: 24-bit, left justified; LRCLK, BICK = Input */
+#define AK4114_DIF_I24I2S (AK4114_DIF2|AK4114_DIF1|AK4114_DIF0) /* STDO: I2S; LRCLK, BICK = Input */
+#define AK4114_DEAU (1<<3) /* Deemphasis Autodetect Enable (1 = enable) */
+#define AK4114_DEM1 (1<<2) /* 32kHz-48kHz Deemphasis Control */
+#define AK4114_DEM0 (1<<1) /* 32kHz-48kHz Deemphasis Control */
+#define AK4114_DEM_44KHZ (0)
+#define AK4114_DEM_48KHZ (AK4114_DEM1)
+#define AK4114_DEM_32KHZ (AK4114_DEM0|AK4114_DEM1)
+#define AK4114_DEM_96KHZ (AK4114_DEM1) /* DFS must be set */
+#define AK4114_DFS (1<<0) /* 96kHz Deemphasis Control */
+
+/* AK4114_REG_IO0 */
+#define AK4114_TX1E (1<<7) /* TX1 Output Enable (1 = enable) */
+#define AK4114_OPS12 (1<<2) /* Output Though Data Selector for TX1 pin */
+#define AK4114_OPS11 (1<<1) /* Output Though Data Selector for TX1 pin */
+#define AK4114_OPS10 (1<<0) /* Output Though Data Selector for TX1 pin */
+#define AK4114_TX0E (1<<3) /* TX0 Output Enable (1 = enable) */
+#define AK4114_OPS02 (1<<2) /* Output Though Data Selector for TX0 pin */
+#define AK4114_OPS01 (1<<1) /* Output Though Data Selector for TX0 pin */
+#define AK4114_OPS00 (1<<0) /* Output Though Data Selector for TX0 pin */
+
+/* AK4114_REG_IO1 */
+#define AK4114_EFH1 (1<<7) /* Interrupt 0 pin Hold */
+#define AK4114_EFH0 (1<<6) /* Interrupt 0 pin Hold */
+#define AK4114_EFH_512 (0)
+#define AK4114_EFH_1024 (AK4114_EFH0)
+#define AK4114_EFH_2048 (AK4114_EFH1)
+#define AK4114_EFH_4096 (AK4114_EFH1|AK4114_EFH0)
+#define AK4114_UDIT (1<<5) /* U-bit Control for DIT (0 = fixed '0', 1 = recovered) */
+#define AK4114_TLR (1<<4) /* Double Sampling Frequency Select for DIT (0 = L channel, 1 = R channel) */
+#define AK4114_DIT (1<<3) /* TX1 out: 0 = Through Data (RX data), 1 = Transmit Data (DAUX data) */
+#define AK4114_IPS2 (1<<2) /* Input Recovery Data Select */
+#define AK4114_IPS1 (1<<1) /* Input Recovery Data Select */
+#define AK4114_IPS0 (1<<0) /* Input Recovery Data Select */
+#define AK4114_IPS(x) ((x)&7)
+
+/* AK4114_REG_INT0_MASK && AK4114_REG_INT1_MASK*/
+#define AK4117_MQI (1<<7) /* mask enable for QINT bit */
+#define AK4117_MAT (1<<6) /* mask enable for AUTO bit */
+#define AK4117_MCI (1<<5) /* mask enable for CINT bit */
+#define AK4117_MUL (1<<4) /* mask enable for UNLOCK bit */
+#define AK4117_MDTS (1<<3) /* mask enable for DTSCD bit */
+#define AK4117_MPE (1<<2) /* mask enable for PEM bit */
+#define AK4117_MAN (1<<1) /* mask enable for AUDN bit */
+#define AK4117_MPR (1<<0) /* mask enable for PAR bit */
+
+/* AK4114_REG_RCS0 */
+#define AK4114_QINT (1<<7) /* Q-subcode buffer interrupt, 0 = no change, 1 = changed */
+#define AK4114_AUTO (1<<6) /* Non-PCM or DTS stream auto detection, 0 = no detect, 1 = detect */
+#define AK4114_CINT (1<<5) /* channel status buffer interrupt, 0 = no change, 1 = change */
+#define AK4114_UNLCK (1<<4) /* PLL lock status, 0 = lock, 1 = unlock */
+#define AK4114_DTSCD (1<<3) /* DTS-CD Detect, 0 = No detect, 1 = Detect */
+#define AK4114_PEM (1<<2) /* Pre-emphasis Detect, 0 = OFF, 1 = ON */
+#define AK4114_AUDION (1<<1) /* audio bit output, 0 = audio, 1 = non-audio */
+#define AK4114_PAR (1<<0) /* parity error or biphase error status, 0 = no error, 1 = error */
+
+/* AK4114_REG_RCS1 */
+#define AK4114_FS3 (1<<7) /* sampling frequency detection */
+#define AK4114_FS2 (1<<6)
+#define AK4114_FS1 (1<<5)
+#define AK4114_FS0 (1<<4)
+#define AK4114_FS_44100HZ (0)
+#define AK4114_FS_48000HZ (AK4114_FS1)
+#define AK4114_FS_32000HZ (AK4114_FS1|AK4114_FS0)
+#define AK4114_FS_88200HZ (AK4114_FS3)
+#define AK4114_FS_96000HZ (AK4114_FS3|AK4114_FS1)
+#define AK4114_FS_176400HZ (AK4114_FS3|AK4114_FS2)
+#define AK4114_FS_192000HZ (AK4114_FS3|AK4114_FS2|AK4114_FS1)
+#define AK4114_V (1<<3) /* Validity of Channel Status, 0 = Valid, 1 = Invalid */
+#define AK4114_QCRC (1<<1) /* CRC for Q-subcode, 0 = no error, 1 = error */
+#define AK4114_CCRC (1<<0) /* CRC for channel status, 0 = no error, 1 = error */
+
+/* flags for snd_ak4114_check_rate_and_errors() */
+#define AK4114_CHECK_NO_STAT (1<<0) /* no statistics */
+#define AK4114_CHECK_NO_RATE (1<<1) /* no rate check */
+
+#define AK4114_CONTROLS 14
+
+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;
+ ak4114_write_t * write;
+ ak4114_read_t * read;
+ void * private_data;
+ unsigned int init: 1;
+ 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;
+ unsigned long parity_errors;
+ unsigned long v_bit_errors;
+ unsigned long qcrc_errors;
+ unsigned long ccrc_errors;
+ unsigned char rcs0;
+ unsigned char rcs1;
+ struct workqueue_struct *workqueue;
+ struct work_struct work;
+ void *change_callback_private;
+ void (*change_callback)(ak4114_t *ak4114, unsigned char c0, unsigned char c1);
+};
+
+int snd_ak4114_create(snd_card_t *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);
+
+#endif /* __SOUND_AK4114_H */
+
diff --git a/include/sound/ak4117.h b/include/sound/ak4117.h
index 3137755e66727..9e1dab17c33e5 100644
--- a/include/sound/ak4117.h
+++ b/include/sound/ak4117.h
@@ -106,7 +106,7 @@
#define AK4117_DIF_24L (AK4117_DIF2) /* STDO: 24-bit, left justified */
#define AK4117_DIF_24I2S (AK4117_DIF2|AK4117_DIF0) /* STDO: I2S */
-/* AK4117_REG_INT0_MASK & AK4117_INT1_MASK */
+/* AK4117_REG_INT0_MASK & AK4117_REG_INT1_MASK */
#define AK4117_MULK (1<<7) /* mask enable for UNLOCK bit */
#define AK4117_MPAR (1<<6) /* mask enable for PAR bit */
#define AK4117_MAUTO (1<<5) /* mask enable for AUTO bit */
@@ -181,8 +181,8 @@ struct ak4117 {
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 *chip, unsigned char reg, unsigned char mask, unsigned char val);
-void snd_ak4117_reinit(ak4117_t *chip);
+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);
diff --git a/include/sound/ak4xxx-adda.h b/include/sound/ak4xxx-adda.h
index 63fc8c703808f..e94ac02823187 100644
--- a/include/sound/ak4xxx-adda.h
+++ b/include/sound/ak4xxx-adda.h
@@ -50,7 +50,8 @@ struct snd_akm4xxx {
/* template should fill the following fields */
unsigned int idx_offset; /* control index offset */
enum {
- SND_AK4524, SND_AK4528, SND_AK4529, SND_AK4355, SND_AK4381
+ SND_AK4524, SND_AK4528, SND_AK4529,
+ SND_AK4355, SND_AK4358, SND_AK4381
} type;
struct snd_ak4xxx_ops ops;
};
diff --git a/include/sound/asound.h b/include/sound/asound.h
index b957763c32bb7..a4d149f34541e 100644
--- a/include/sound/asound.h
+++ b/include/sound/asound.h
@@ -582,6 +582,7 @@ enum sndrv_timer_slave_class {
/* global timers (device member) */
#define SNDRV_TIMER_GLOBAL_SYSTEM 0
#define SNDRV_TIMER_GLOBAL_RTC 1
+#define SNDRV_TIMER_GLOBAL_HPET 2
/* info flags */
#define SNDRV_TIMER_FLG_SLAVE (1<<0) /* cannot be controlled */
diff --git a/include/sound/asoundef.h b/include/sound/asoundef.h
index e8b8945863871..58c9ef3d18253 100644
--- a/include/sound/asoundef.h
+++ b/include/sound/asoundef.h
@@ -185,7 +185,7 @@
#define MIDI_CTL_LSB_GENERAL_PURPOSE4 0x33
#define MIDI_CTL_SUSTAIN 0x40
#define MIDI_CTL_PORTAMENTO 0x41
-#define MIDI_CTL_SUSTENUTO 0x42
+#define MIDI_CTL_SOSTENUTO 0x42
#define MIDI_CTL_SOFT_PEDAL 0x43
#define MIDI_CTL_LEGATO_FOOTSWITCH 0x44
#define MIDI_CTL_HOLD2 0x45
diff --git a/include/sound/control.h b/include/sound/control.h
index 678bcb275d881..7b9444cd02f40 100644
--- a/include/sound/control.h
+++ b/include/sound/control.h
@@ -119,6 +119,13 @@ int snd_ctl_create(snd_card_t *card);
int snd_ctl_register_ioctl(snd_kctl_ioctl_func_t fcn);
int snd_ctl_unregister_ioctl(snd_kctl_ioctl_func_t fcn);
+#ifdef CONFIG_COMPAT
+int snd_ctl_register_ioctl_compat(snd_kctl_ioctl_func_t fcn);
+int snd_ctl_unregister_ioctl_compat(snd_kctl_ioctl_func_t fcn);
+#else
+#define snd_ctl_register_ioctl_compat(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);
diff --git a/include/sound/core.h b/include/sound/core.h
index c1e64ce108308..9117c23e3a01b 100644
--- a/include/sound/core.h
+++ b/include/sound/core.h
@@ -26,6 +26,7 @@
#include <asm/semaphore.h> /* struct semaphore */
#include <linux/rwsem.h> /* struct rw_semaphore */
#include <linux/workqueue.h> /* struct workqueue_struct */
+#include <linux/pm.h> /* pm_message_t */
/* Typedef's */
typedef struct timespec snd_timestamp_t;
@@ -167,13 +168,15 @@ struct _snd_card {
struct device *dev;
#ifdef CONFIG_PM
- int (*pm_suspend)(snd_card_t *card, unsigned int state);
- int (*pm_resume)(snd_card_t *card, unsigned int state);
- struct pm_dev *pm_dev; /* for ISA */
+ 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;
+#ifdef CONFIG_SND_GENERIC_PM
+ struct snd_generic_device *pm_dev; /* for ISA */
+#endif
#endif
#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)
@@ -206,36 +209,34 @@ static inline void snd_power_change_state(snd_card_t *card, unsigned int state)
wake_up(&card->power_sleep);
}
int snd_card_set_pm_callback(snd_card_t *card,
- int (*suspend)(snd_card_t *, unsigned int),
- int (*resume)(snd_card_t *, unsigned int),
+ int (*suspend)(snd_card_t *, pm_message_t),
+ int (*resume)(snd_card_t *),
void *private_data);
-int snd_card_set_dev_pm_callback(snd_card_t *card, int type,
- int (*suspend)(snd_card_t *, unsigned int),
- int (*resume)(snd_card_t *, unsigned int),
- 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_dev_pm_callback(card, PM_ISA_DEV, suspend, resume, data)
-#ifdef CONFIG_PCI
-#ifndef SND_PCI_PM_CALLBACKS
-int snd_card_pci_suspend(struct pci_dev *dev, u32 state);
+ 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
-#endif
-#endif
-#else
+
+#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; }
#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_dev_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)
-#ifdef CONFIG_PCI
#define SND_PCI_PM_CALLBACKS
-#endif
-#endif
+
+#endif /* CONFIG_PM */
/* device.c */
@@ -489,4 +490,13 @@ static inline int snd_timestamp_null(struct timespec *tstamp)
#define SNDRV_OSS_VERSION ((3<<16)|(8<<8)|(1<<4)|(0)) /* 3.8.1a */
+/* for easier backward-porting */
+#if defined(CONFIG_GAMEPORT) || defined(CONFIG_GAMEPORT_MODULE)
+#ifndef gameport_set_dev_parent
+#define gameport_set_dev_parent(gp,xdev) ((gp)->dev.parent = (xdev))
+#define gameport_set_port_data(gp,r) ((gp)->port_data = (r))
+#define gameport_get_port_data(gp) (gp)->port_data
+#endif
+#endif
+
#endif /* __SOUND_CORE_H */
diff --git a/include/sound/cs46xx.h b/include/sound/cs46xx.h
index 1d47e20cf61ba..182dd276ee745 100644
--- a/include/sound/cs46xx.h
+++ b/include/sound/cs46xx.h
@@ -1720,7 +1720,7 @@ struct _snd_cs46xx {
snd_kcontrol_t *eapd_switch; /* for amplifier hack */
int accept_valid; /* accept mmap valid (for OSS) */
- struct snd_cs46xx_gameport *gameport;
+ struct gameport *gameport;
#ifdef CONFIG_SND_CS46XX_DEBUG_GPIO
int current_gpio;
@@ -1751,6 +1751,6 @@ int snd_cs46xx_pcm_center_lfe(cs46xx_t *chip, int device, snd_pcm_t **rpcm);
int snd_cs46xx_mixer(cs46xx_t *chip);
int snd_cs46xx_midi(cs46xx_t *chip, int device, snd_rawmidi_t **rmidi);
int snd_cs46xx_start_dsp(cs46xx_t *chip);
-void snd_cs46xx_gameport(cs46xx_t *chip);
+int snd_cs46xx_gameport(cs46xx_t *chip);
#endif /* __SOUND_CS46XX_H */
diff --git a/include/sound/emu10k1.h b/include/sound/emu10k1.h
index 29a24cbd8f656..43b6786abae52 100644
--- a/include/sound/emu10k1.h
+++ b/include/sound/emu10k1.h
@@ -51,7 +51,9 @@
#define NUM_MIDI 16
#define NUM_G 64 /* use all channels */
#define NUM_FXSENDS 4
+#define NUM_EFX_PLAYBACK 16
+/* FIXME? - according to the OSS driver the EMU10K1 needs a 29 bit DMA mask */
#define EMU10K1_DMA_MASK 0x7fffffffUL /* 31bit */
#define AUDIGY_DMA_MASK 0xffffffffUL /* 32bit */
@@ -82,10 +84,16 @@
/* Clear pending interrupts by writing a 1 to */
/* the relevant bits and zero to the other bits */
+#define IPR_GPIOMSG 0x20000000 /* GPIO message interrupt (RE'd, still not sure
+ which INTE bits enable it) */
+
/* The next two interrupts are for the midi port on the Audigy Drive (A_MPU1) */
#define IPR_A_MIDITRANSBUFEMPTY2 0x10000000 /* MIDI UART transmit buffer empty */
#define IPR_A_MIDIRECVBUFEMPTY2 0x08000000 /* MIDI UART receive buffer empty */
+#define IPR_SPDIFBUFFULL 0x04000000 /* SPDIF capture related, 10k2 only? (RE) */
+#define IPR_SPDIFBUFHALFFULL 0x02000000 /* SPDIF capture related? (RE) */
+
#define IPR_SAMPLERATETRACKER 0x01000000 /* Sample rate tracker lock status change */
#define IPR_FXDSP 0x00800000 /* Enable FX DSP interrupts */
#define IPR_FORCEINT 0x00400000 /* Force Sound Blaster interrupt */
@@ -104,12 +112,12 @@
#define IPR_INTERVALTIMER 0x00000200 /* Interval timer terminal count */
#define IPR_MIDITRANSBUFEMPTY 0x00000100 /* MIDI UART transmit buffer empty */
#define IPR_MIDIRECVBUFEMPTY 0x00000080 /* MIDI UART receive buffer empty */
-#define IPR_CHANNELLOOP 0x00000040 /* One or more channel loop interrupts pending */
+#define IPR_CHANNELLOOP 0x00000040 /* Channel (half) loop interrupt(s) pending */
#define IPR_CHANNELNUMBERMASK 0x0000003f /* When IPR_CHANNELLOOP is set, indicates the */
- /* Highest set channel in CLIPL or CLIPH. When */
- /* IP is written with CL set, the bit in CLIPL */
- /* or CLIPH corresponding to the CIN value */
- /* written will be cleared. */
+ /* highest set channel in CLIPL, CLIPH, HLIPL, */
+ /* or HLIPH. When IP is written with CL set, */
+ /* the bit in H/CLIPL or H/CLIPH corresponding */
+ /* to the CIN value written will be cleared. */
#define INTE 0x0c /* Interrupt enable register */
#define INTE_VIRTUALSB_MASK 0xc0000000 /* Virtual Soundblaster I/O port capture */
@@ -236,9 +244,27 @@
#define A_IOCFG 0x18 /* GPIO on Audigy card (16bits) */
#define A_GPINPUT_MASK 0xff00
#define A_GPOUTPUT_MASK 0x00ff
-#define A_IOCFG_GPOUT0 0x0044 /* analog/digital? */
-#define A_IOCFG_GPOUT1 0x0002 /* IR */
+
+// Audigy output/GPIO stuff taken from the kX drivers
+#define A_IOCFG_GPOUT0 0x0044 /* analog/digital */
+#define A_IOCFG_DISABLE_ANALOG 0x0040 /* = 'enable' for Audigy2 (chiprev=4) */
+#define A_IOCFG_ENABLE_DIGITAL 0x0004
+#define A_IOCFG_UNKNOWN_20 0x0020
+#define A_IOCFG_DISABLE_AC97_FRONT 0x0080 /* turn off ac97 front -> front (10k2.1) */
+#define A_IOCFG_GPOUT1 0x0002 /* IR? drive's internal bypass (?) */
#define A_IOCFG_GPOUT2 0x0001 /* IR */
+#define A_IOCFG_MULTIPURPOSE_JACK 0x2000 /* center+lfe+rear_center (a2/a2ex) */
+ /* + digital for generic 10k2 */
+#define A_IOCFG_DIGITAL_JACK 0x1000 /* digital for a2 platinum */
+#define A_IOCFG_FRONT_JACK 0x4000
+#define A_IOCFG_REAR_JACK 0x8000
+#define A_IOCFG_PHONES_JACK 0x0100 /* LiveDrive */
+
+/* outputs:
+ * for audigy2 platinum: 0xa00
+ * for a2 platinum ex: 0x1c00
+ * for a1 platinum: 0x0
+ */
#define TIMER 0x1a /* Timer terminal count register */
/* NOTE: After the rate is changed, a maximum */
@@ -254,6 +280,46 @@
#define AC97ADDRESS_READY 0x80 /* Read-only bit, reflects CODEC READY signal */
#define AC97ADDRESS_ADDRESS 0x7f /* Address of indexed AC97 register */
+/* Available on the Audigy 2 and Audigy 4 only. This is the P16V chip. */
+#define PTR2 0x20 /* Indexed register set pointer register */
+#define DATA2 0x24 /* Indexed register set data register */
+#define IPR2 0x28 /* P16V interrupt pending register */
+#define IPR2_PLAYBACK_CH_0_LOOP 0x00001000 /* Playback Channel 0 loop */
+#define IPR2_PLAYBACK_CH_0_HALF_LOOP 0x00000100 /* Playback Channel 0 half loop */
+#define IPR2_CAPTURE_CH_0_LOOP 0x00100000 /* Capture Channel 0 loop */
+#define IPR2_CAPTURE_CH_0_HALF_LOOP 0x00010000 /* Capture Channel 0 half loop */
+ /* 0x00000100 Playback. Only in once per period.
+ * 0x00110000 Capture. Int on half buffer.
+ */
+#define INTE2 0x2c /* P16V Interrupt enable register. */
+#define INTE2_PLAYBACK_CH_0_LOOP 0x00001000 /* Playback Channel 0 loop */
+#define INTE2_PLAYBACK_CH_0_HALF_LOOP 0x00000100 /* Playback Channel 0 half loop */
+#define INTE2_PLAYBACK_CH_1_LOOP 0x00002000 /* Playback Channel 1 loop */
+#define INTE2_PLAYBACK_CH_1_HALF_LOOP 0x00000200 /* Playback Channel 1 half loop */
+#define INTE2_PLAYBACK_CH_2_LOOP 0x00004000 /* Playback Channel 2 loop */
+#define INTE2_PLAYBACK_CH_2_HALF_LOOP 0x00000400 /* Playback Channel 2 half loop */
+#define INTE2_PLAYBACK_CH_3_LOOP 0x00008000 /* Playback Channel 3 loop */
+#define INTE2_PLAYBACK_CH_3_HALF_LOOP 0x00000800 /* Playback Channel 3 half loop */
+#define INTE2_CAPTURE_CH_0_LOOP 0x00100000 /* Capture Channel 0 loop */
+#define INTE2_CAPTURE_CH_0_HALF_LOOP 0x00010000 /* Caputre Channel 0 half loop */
+#define HCFG2 0x34 /* Defaults: 0, win2000 sets it to 00004201 */
+ /* 0x00000000 2-channel output. */
+ /* 0x00000200 8-channel output. */
+ /* 0x00000004 pauses stream/irq fail. */
+ /* Rest of bits no nothing to sound output */
+ /* bit 0: Enable P16V audio.
+ * bit 1: Lock P16V record memory cache.
+ * bit 2: Lock P16V playback memory cache.
+ * bit 3: Dummy record insert zero samples.
+ * bit 8: Record 8-channel in phase.
+ * bit 9: Playback 8-channel in phase.
+ * bit 11-12: Playback mixer attenuation: 0=0dB, 1=-6dB, 2=-12dB, 3=Mute.
+ * bit 13: Playback mixer enable.
+ * bit 14: Route SRC48 mixer output to fx engine.
+ * bit 15: Enable IEEE 1394 chip.
+ */
+#define IPR3 0x38 /* Cdif interrupt pending register */
+#define INTE3 0x3c /* Cdif interrupt enable register. */
/************************************************************************************************/
/* PCI function 1 registers, address = <val> + PCIBASE1 */
/************************************************************************************************/
@@ -464,6 +530,8 @@
/* NOTE: All channels contain internal variables; do */
/* not write to these locations. */
+/* 1f something */
+
#define CD0 0x20 /* Cache data 0 register */
#define CD1 0x21 /* Cache data 1 register */
#define CD2 0x22 /* Cache data 2 register */
@@ -481,6 +549,8 @@
#define CDE 0x2e /* Cache data E register */
#define CDF 0x2f /* Cache data F register */
+/* 0x30-3f seem to be the same as 0x20-2f */
+
#define PTB 0x40 /* Page table base register */
#define PTB_MASK 0xfffff000 /* Physical address of the page table in host memory */
@@ -511,7 +581,11 @@
#define FXWC 0x43 /* FX output write channels register */
/* When set, each bit enables the writing of the */
- /* corresponding FX output channel into host memory */
+ /* corresponding FX output channel (internal registers */
+ /* 0x20-0x3f) to host memory. This mode of recording */
+ /* is 16bit, 48KHz only. All 32 channels can be enabled */
+ /* simultaneously. */
+
#define FXWC_DEFAULTROUTE_C (1<<0) /* left emu out? */
#define FXWC_DEFAULTROUTE_B (1<<1) /* right emu out? */
#define FXWC_DEFAULTROUTE_A (1<<12)
@@ -546,12 +620,16 @@
#define FXBA 0x47 /* FX Buffer Address */
#define FXBA_MASK 0xfffff000 /* 20 bit base address */
+/* 0x48 something - word access, defaults to 3f */
+
#define MICBS 0x49 /* Microphone buffer size register */
#define ADCBS 0x4a /* ADC buffer size register */
#define FXBS 0x4b /* FX buffer size register */
+/* register: 0x4c..4f: ffff-ffff current amounts, per-channel */
+
/* The following mask values define the size of the ADC, MIX and FX buffers in bytes */
#define ADCBS_BUFSIZE_NONE 0x00000000
#define ADCBS_BUFSIZE_384 0x00000001
@@ -602,6 +680,7 @@
#define A_DBG_SATURATION_OCCURED 0x20000000
#define A_DBG_SATURATION_ADDR 0x0ffc0000
+// NOTE: 0x54,55,56: 64-bit
#define SPCS0 0x54 /* SPDIF output Channel Status 0 register */
#define SPCS1 0x55 /* SPDIF output Channel Status 1 register */
@@ -657,6 +736,7 @@
#define AC97SLOT_CNTR 0x10 /* Center enable */
#define AC97SLOT_LFE 0x20 /* LFE enable */
+// NOTE: 0x60,61,62: 64-bit
#define CDSRCS 0x60 /* CD-ROM Sample Rate Converter status register */
#define GPSRCS 0x61 /* General Purpose SPDIF sample rate cvt status */
@@ -693,6 +773,19 @@
#define FXIDX_MASK 0x0000ffff /* 16-bit value */
#define FXIDX_IDX 0x10000065
+/* The 32-bit HLIx and HLIPx registers all have one bit per channel control/status */
+#define HLIEL 0x66 /* Channel half loop interrupt enable low register */
+
+#define HLIEH 0x67 /* Channel half loop interrupt enable high register */
+
+#define HLIPL 0x68 /* Channel half loop interrupt pending low register */
+
+#define HLIPH 0x69 /* Channel half loop interrupt pending high register */
+
+// 0x6a,6b,6c used for some recording
+// 0x6d unused
+// 0x6e,6f - tanktable base / offset
+
/* This is the MPU port on the card (via the game port) */
#define A_MUDATA1 0x70
#define A_MUCMD1 0x71
@@ -710,10 +803,14 @@
#define A_FXWC2 0x75 /* Selects 0x9f-0x80 for FX recording */
#define A_SPDIF_SAMPLERATE 0x76 /* Set the sample rate of SPDIF output */
-#define A_SPDIF_48000 0x00000080
-#define A_SPDIF_44100 0x00000000
+#define A_SPDIF_RATE_MASK 0x000000c0
+#define A_SPDIF_48000 0x00000000
+#define A_SPDIF_44100 0x00000080
#define A_SPDIF_96000 0x00000040
+/* 0x77,0x78,0x79 "something i2s-related" - default to 0x01080000 on my audigy 2 ZS --rlrevell */
+/* 0x7a, 0x7b - lookup tables */
+
#define A_FXRT2 0x7c
#define A_FXRT_CHANNELE 0x0000003f /* Effects send bus number for channel's effects send E */
#define A_FXRT_CHANNELF 0x00003f00 /* Effects send bus number for channel's effects send F */
@@ -725,7 +822,8 @@
#define A_FXSENDAMOUNT_F_MASK 0x00FF0000
#define A_FXSENDAMOUNT_G_MASK 0x0000FF00
#define A_FXSENDAMOUNT_H_MASK 0x000000FF
-
+/* 0x7c, 0x7e "high bit is used for filtering" */
+
/* The send amounts for this one are the same as used with the emu10k1 */
#define A_FXRT1 0x7e
#define A_FXRT_CHANNELA 0x0000003f
@@ -782,6 +880,7 @@ typedef struct _snd_emu10k1_voice emu10k1_voice_t;
typedef struct _snd_emu10k1_pcm emu10k1_pcm_t;
typedef enum {
+ EMU10K1_EFX,
EMU10K1_PCM,
EMU10K1_SYNTH,
EMU10K1_MIDI
@@ -790,8 +889,9 @@ typedef enum {
struct _snd_emu10k1_voice {
emu10k1_t *emu;
int number;
- int use: 1,
+ unsigned int use: 1,
pcm: 1,
+ efx: 1,
synth: 1,
midi: 1;
void (*interrupt)(emu10k1_t *emu, emu10k1_voice_t *pvoice);
@@ -801,6 +901,7 @@ struct _snd_emu10k1_voice {
typedef enum {
PLAYBACK_EMUVOICE,
+ PLAYBACK_EFX,
CAPTURE_AC97ADC,
CAPTURE_AC97MIC,
CAPTURE_EFX
@@ -810,7 +911,7 @@ struct _snd_emu10k1_pcm {
emu10k1_t *emu;
snd_emu10k1_pcm_type_t type;
snd_pcm_substream_t *substream;
- emu10k1_voice_t *voices[2];
+ emu10k1_voice_t *voices[NUM_EFX_PLAYBACK];
emu10k1_voice_t *extra;
unsigned short running;
unsigned short first_ptr;
@@ -934,15 +1035,33 @@ typedef struct {
void (*interrupt)(emu10k1_t *emu, unsigned int status);
} emu10k1_midi_t;
+typedef struct {
+ u32 vendor;
+ u32 device;
+ u32 subsystem;
+ unsigned char emu10k1_chip; /* Original SB Live. Not SB Live 24bit. */
+ unsigned char emu10k2_chip; /* Audigy 1 or Audigy 2. */
+ unsigned char ca0102_chip; /* Audigy 1 or Audigy 2. Not SB Audigy 2 Value. */
+ unsigned char ca0108_chip; /* Audigy 2 Value */
+ unsigned char ca0151_chip; /* P16V */
+ unsigned char spk71; /* Has 7.1 speakers */
+ unsigned char spdif_bug; /* Has Spdif phasing bug */
+ unsigned char ac97_chip; /* Has an AC97 chip */
+ unsigned char ecard; /* APS EEPROM */
+ char * driver;
+ char * name;
+} emu_chip_details_t;
+
struct _snd_emu10k1 {
int irq;
unsigned long port; /* I/O port number */
- int APS: 1, /* APS flag */
+ unsigned int APS: 1, /* APS flag */
no_ac97: 1, /* no AC'97 */
tos_link: 1, /* tos link detected */
rear_ac97: 1, /* rear channels are on AC'97 */
spk71:1; /* 7.1 configuration (Audigy 2 ZS) */
+ const emu_chip_details_t *card_capabilities; /* Contains profile of card capabilities */
unsigned int audigy; /* is Audigy? */
unsigned int revision; /* chip revision */
unsigned int serial; /* serial number */
@@ -953,6 +1072,9 @@ struct _snd_emu10k1 {
int max_cache_pages; /* max memory size / PAGE_SIZE */
struct snd_dma_buffer silent_page; /* silent page */
struct snd_dma_buffer ptb_pages; /* page table pages */
+ 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 */
@@ -974,6 +1096,7 @@ struct _snd_emu10k1 {
snd_pcm_t *pcm;
snd_pcm_t *pcm_mic;
snd_pcm_t *pcm_efx;
+ snd_pcm_t *pcm_p16v;
spinlock_t synth_lock;
void *synth;
@@ -984,23 +1107,29 @@ struct _snd_emu10k1 {
spinlock_t voice_lock;
struct semaphore ptb_lock;
- emu10k1_voice_t voices[64];
+ emu10k1_voice_t voices[NUM_G];
+ emu10k1_voice_t p16v_voices[4];
+ int p16v_device_offset;
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 (*timer_interrupt)(emu10k1_t *emu);
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;
@@ -1008,6 +1137,7 @@ struct _snd_emu10k1 {
emu10k1_midi_t midi2; /* for audigy */
unsigned int efx_voices_mask[2];
+ unsigned int next_free_voice;
};
int snd_emu10k1_create(snd_card_t * card,
@@ -1021,6 +1151,10 @@ int snd_emu10k1_create(snd_card_t * card,
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 snd_emu10k1_timer(emu10k1_t * emu, int device);
@@ -1037,12 +1171,17 @@ int snd_emu10k1_fx8010_tram_setup(emu10k1_t *emu, u32 size);
/* 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);
@@ -1112,7 +1251,10 @@ int snd_emu10k1_fx8010_unregister_irq_handler(emu10k1_t *emu,
/* GPRs */
#define FXBUS(x) (0x00 + (x)) /* x = 0x00 - 0x0f */
#define EXTIN(x) (0x10 + (x)) /* x = 0x00 - 0x0f */
-#define EXTOUT(x) (0x20 + (x)) /* x = 0x00 - 0x0f */
+#define EXTOUT(x) (0x20 + (x)) /* x = 0x00 - 0x0f physical outs -> FXWC low 16 bits */
+#define FXBUS2(x) (0x30 + (x)) /* x = 0x00 - 0x0f copies of fx buses for capture -> FXWC high 16 bits */
+ /* NB: 0x31 and 0x32 are shared with Center/LFE on SB live 5.1 */
+
#define C_00000000 0x40
#define C_00000001 0x41
#define C_00000002 0x42
@@ -1154,9 +1296,13 @@ int snd_emu10k1_fx8010_unregister_irq_handler(emu10k1_t *emu,
#define A_ITRAM_CTL(x) (A_TANKMEMCTLREGBASE + 0x00 + (x)) /* x = 0x00 - 0xbf */
#define A_ETRAM_CTL(x) (A_TANKMEMCTLREGBASE + 0xc0 + (x)) /* x = 0x00 - 0x3f */
-#define A_FXBUS(x) (0x00 + (x)) /* x = 0x00 - 0x3f? */
-#define A_EXTIN(x) (0x40 + (x)) /* x = 0x00 - 0x1f? */
-#define A_EXTOUT(x) (0x60 + (x)) /* x = 0x00 - 0x1f? */
+#define A_FXBUS(x) (0x00 + (x)) /* x = 0x00 - 0x3f FX buses */
+#define A_EXTIN(x) (0x40 + (x)) /* x = 0x00 - 0x0f physical ins */
+#define A_P16VIN(x) (0x50 + (x)) /* x = 0x00 - 0x0f p16v ins (A2 only) "EMU32 inputs" */
+#define A_EXTOUT(x) (0x60 + (x)) /* x = 0x00 - 0x1f physical outs -> A_FXWC1 0x79-7f unknown */
+#define A_FXBUS2(x) (0x80 + (x)) /* x = 0x00 - 0x1f extra outs used for EFX capture -> A_FXWC2 */
+#define A_EMU32OUTH(x) (0xa0 + (x)) /* x = 0x00 - 0x0f "EMU32_OUT_10 - _1F" - ??? */
+#define A_EMU32OUTL(x) (0xb0 + (x)) /* x = 0x00 - 0x0f "EMU32_OUT_1 - _F" - ??? */
#define A_GPR(x) (A_FXGPREGBASE + (x))
/* cc_reg constants */
diff --git a/include/sound/gus.h b/include/sound/gus.h
index cac8cc070ad97..8b6287a6fff57 100644
--- a/include/sound/gus.h
+++ b/include/sound/gus.h
@@ -230,7 +230,7 @@ typedef struct {
int mode; /* operation mode */
int client; /* sequencer client number */
int port; /* sequencer port number */
- int midi_has_voices: 1;
+ unsigned int midi_has_voices: 1;
} snd_gus_port_t;
typedef struct _snd_gus_voice snd_gus_voice_t;
@@ -264,7 +264,7 @@ typedef enum {
struct _snd_gus_voice {
int number;
- int use: 1,
+ unsigned int use: 1,
pcm: 1,
synth:1,
midi: 1;
diff --git a/include/sound/hwdep.h b/include/sound/hwdep.h
index 4a4cc0167fac3..043876348fa1b 100644
--- a/include/sound/hwdep.h
+++ b/include/sound/hwdep.h
@@ -38,6 +38,7 @@ typedef struct _snd_hwdep_ops {
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);
diff --git a/include/sound/mixer_oss.h b/include/sound/mixer_oss.h
index a2fbad2b8c40b..ed75b2fb00ab5 100644
--- a/include/sound/mixer_oss.h
+++ b/include/sound/mixer_oss.h
@@ -38,7 +38,7 @@ typedef int (*snd_mixer_oss_put_recsrce_t)(snd_mixer_oss_file_t *fmixer, unsigne
struct _snd_oss_mixer_slot {
int number;
- int stereo: 1;
+ 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;
diff --git a/include/sound/mpu401.h b/include/sound/mpu401.h
index 8c5d6e0c89cce..ae39e38bf9968 100644
--- a/include/sound/mpu401.h
+++ b/include/sound/mpu401.h
@@ -86,9 +86,6 @@ struct _snd_mpu401 {
spinlock_t output_lock;
spinlock_t timer_lock;
- atomic_t rx_loop;
- atomic_t tx_loop;
-
struct timer_list timer;
void (*write) (mpu401_t * mpu, unsigned char data, unsigned long addr);
diff --git a/include/sound/rawmidi.h b/include/sound/rawmidi.h
index 3df418d4f51ea..3f9db510dee33 100644
--- a/include/sound/rawmidi.h
+++ b/include/sound/rawmidi.h
@@ -23,6 +23,7 @@
*/
#include <sound/asound.h>
+#include <linux/interrupt.h>
#include <linux/spinlock.h>
#include <linux/wait.h>
#include <asm/semaphore.h>
@@ -65,8 +66,7 @@ typedef struct _snd_rawmidi_global_ops {
} snd_rawmidi_global_ops_t;
struct _snd_rawmidi_runtime {
- unsigned int trigger: 1, /* transfer is running */
- drain: 1, /* drain stage */
+ unsigned int drain: 1, /* drain stage */
oss: 1; /* OSS compatible mode */
/* midi stream buffer */
unsigned char *buffer; /* buffer for MIDI data */
@@ -79,8 +79,10 @@ struct _snd_rawmidi_runtime {
/* misc */
spinlock_t lock;
wait_queue_head_t sleep;
- /* event handler (room [output] or new bytes [input]) */
+ /* event handler (new bytes, input only) */
void (*event)(snd_rawmidi_substream_t *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);
diff --git a/include/sound/seq_midi_emul.h b/include/sound/seq_midi_emul.h
index 32158a6070116..e58ca45bc73b3 100644
--- a/include/sound/seq_midi_emul.h
+++ b/include/sound/seq_midi_emul.h
@@ -136,7 +136,7 @@ typedef struct snd_seq_midi_op {
#define gm_sustain control[MIDI_CTL_SUSTAIN]
#define gm_hold gm_sustain
#define gm_portamento control[MIDI_CTL_PORTAMENTO]
-#define gm_sustenuto control[MIDI_CTL_SUSTENUTO]
+#define gm_sostenuto control[MIDI_CTL_SOSTENUTO]
/*
* These macros give the complete value of the controls that consist
@@ -166,7 +166,7 @@ typedef struct snd_seq_midi_op {
#define SNDRV_MIDI_NOTE_OFF 0x00
#define SNDRV_MIDI_NOTE_ON 0x01
#define SNDRV_MIDI_NOTE_RELEASED 0x02
-#define SNDRV_MIDI_NOTE_SUSTENUTO 0x04
+#define SNDRV_MIDI_NOTE_SOSTENUTO 0x04
#define SNDRV_MIDI_PARAM_TYPE_REGISTERED 0
#define SNDRV_MIDI_PARAM_TYPE_NONREGISTERED 1
diff --git a/include/sound/seq_virmidi.h b/include/sound/seq_virmidi.h
index 9bb1a80a991c8..cf4e2388103f0 100644
--- a/include/sound/seq_virmidi.h
+++ b/include/sound/seq_virmidi.h
@@ -38,7 +38,7 @@ typedef struct _snd_virmidi {
int seq_mode;
int client;
int port;
- int trigger: 1;
+ unsigned int trigger: 1;
snd_midi_event_t *parser;
snd_seq_event_t event;
snd_virmidi_dev_t *rdev;
diff --git a/include/sound/trident.h b/include/sound/trident.h
index ccb3a60d120ff..f5254ec36e6af 100644
--- a/include/sound/trident.h
+++ b/include/sound/trident.h
@@ -290,7 +290,7 @@ typedef struct {
int mode; /* operation mode */
int client; /* sequencer client number */
int port; /* sequencer port number */
- int midi_has_voices: 1;
+ unsigned int midi_has_voices: 1;
} snd_trident_port_t;
typedef struct snd_trident_memblk_arg {
@@ -308,7 +308,7 @@ typedef struct {
struct _snd_trident_voice {
unsigned int number;
- int use: 1,
+ unsigned int use: 1,
pcm: 1,
synth:1,
midi: 1;
@@ -347,7 +347,7 @@ struct _snd_trident_voice {
trident_t *trident;
snd_pcm_substream_t *substream;
snd_trident_voice_t *extra; /* extra PCM voice (acts as interrupt generator) */
- int running: 1,
+ unsigned int running: 1,
capture: 1,
spdif: 1,
foldback: 1,
@@ -448,7 +448,7 @@ struct _snd_trident {
spinlock_t reg_lock;
- struct snd_trident_gameport *gameport;
+ struct gameport *gameport;
};
int snd_trident_create(snd_card_t * card,
@@ -457,7 +457,7 @@ int snd_trident_create(snd_card_t * card,
int pcm_spdif_device,
int max_wavetable_size,
trident_t ** rtrident);
-void snd_trident_gameport(trident_t *trident);
+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);
diff --git a/include/sound/version.h b/include/sound/version.h
index a4db7e75de4d3..98b4230778ed4 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.8"
-#define CONFIG_SND_DATE " (Thu Jan 13 09:39:32 2005 UTC)"
+#define CONFIG_SND_VERSION "1.0.9rc2"
+#define CONFIG_SND_DATE " (Thu Mar 24 10:33:39 2005 UTC)"
diff --git a/include/sound/ymfpci.h b/include/sound/ymfpci.h
index b87453365f79e..4b570684a6aae 100644
--- a/include/sound/ymfpci.h
+++ b/include/sound/ymfpci.h
@@ -198,6 +198,10 @@
#define YMFPCI_LEGACY2_IMOD (1 << 15) /* legacy IRQ mode */
/* SIEN:IMOD 0:0 = legacy irq, 0:1 = INTA, 1:0 = serialized IRQ */
+#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
+#define SUPPORT_JOYSTICK
+#endif
+
/*
*
*/
@@ -262,7 +266,7 @@ typedef enum {
struct _snd_ymfpci_voice {
ymfpci_t *chip;
int number;
- int use: 1,
+ unsigned int use: 1,
pcm: 1,
synth: 1,
midi: 1;
@@ -288,9 +292,9 @@ struct _snd_ymfpci_pcm {
snd_ymfpci_pcm_type_t type;
snd_pcm_substream_t *substream;
ymfpci_voice_t *voices[2]; /* playback only */
- int running: 1;
- int output_front: 1;
- int output_rear: 1;
+ unsigned int running: 1;
+ unsigned int output_front: 1;
+ unsigned int output_rear: 1;
u32 period_size; /* cached from runtime->period_size */
u32 buffer_size; /* cached from runtime->buffer_size */
u32 period_pos;
@@ -311,9 +315,8 @@ struct _snd_ymfpci {
struct resource *mpu_res;
unsigned short old_legacy_ctrl;
-#if defined(CONFIG_GAMEPORT) || defined(CONFIG_GAMEPORT_MODULE)
- struct resource *joystick_res;
- struct gameport gameport;
+#ifdef SUPPORT_JOYSTICK
+ struct gameport *gameport;
#endif
struct snd_dma_buffer work_ptr;
@@ -381,6 +384,7 @@ int snd_ymfpci_create(snd_card_t * 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);
@@ -389,8 +393,4 @@ 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);
-#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
-#define SUPPORT_JOYSTICK
-#endif
-
#endif /* __SOUND_YMFPCI_H */
diff --git a/include/sound/yss225.h b/include/sound/yss225.h
deleted file mode 100644
index 13b2655e4a928..0000000000000
--- a/include/sound/yss225.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef __SOUND_YSS225_H
-#define __SOUND_YSS225_H
-
-extern unsigned char page_zero[256];
-extern unsigned char page_one[256];
-extern unsigned char page_two[128];
-extern unsigned char page_three[128];
-extern unsigned char page_four[128];
-extern unsigned char page_six[192];
-extern unsigned char page_seven[256];
-extern unsigned char page_zero_v2[96];
-extern unsigned char page_one_v2[96];
-extern unsigned char page_two_v2[48];
-extern unsigned char page_three_v2[48];
-extern unsigned char page_four_v2[48];
-extern unsigned char page_seven_v2[96];
-extern unsigned char mod_v2[304];
-extern unsigned char coefficients[364];
-extern unsigned char coefficients2[56];
-extern unsigned char coefficients3[404];
-
-
-#endif /* __SOUND_YSS225_H */
diff --git a/include/video/kyro.h b/include/video/kyro.h
index 6996149f3b41b..1bed37cfa68cf 100644
--- a/include/video/kyro.h
+++ b/include/video/kyro.h
@@ -49,9 +49,7 @@ extern void *kyro_dev_virtual_regs_ptr(void);
extern unsigned int kyro_dev_fb_size(void);
extern unsigned int kyro_dev_regs_size(void);
-extern int kyro_dev_overlay_create(u32 width, u32 height, int bLinear);
extern u32 kyro_dev_overlay_offset(void);
-extern int kyro_dev_overlay_viewport_set(u32 x, u32 y, u32 width, u32 height);
/*
* benedict.gaster@superh.com
diff --git a/include/video/pm3fb.h b/include/video/pm3fb.h
index 49383fd724ae3..8d3cef5d87a20 100644
--- a/include/video/pm3fb.h
+++ b/include/video/pm3fb.h
@@ -1119,34 +1119,6 @@
/* ***** pm3fb useful define and macro ***** */
/* ***************************************** */
-/* kernel -specific definitions */
-/* what kernel is this ? */
-#if ((LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)))
-#define KERNEL_2_5
-#endif
-
-#if ((LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)))
-#define KERNEL_2_4
-#endif
-
-#if ((LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)))
-#define KERNEL_2_2
-/* pci_resource_start, available in 2.2.18 */
-#include <linux/kcomp.h>
-#ifdef CONFIG_FB_OF
-#define SUPPORT_FB_OF
-#endif
-#endif
-
-#if (!defined(KERNEL_2_2)) && (!defined(KERNEL_2_4)) && (!defined(KERNEL_2_5))
-#error "Only kernel 2.2.x, kernel 2.4.y and kernel 2.5.z might work"
-#endif
-
-/* not sure if/why it's needed. doesn't work without on my PowerMac... */
-#ifdef __BIG_ENDIAN
-#define MUST_BYTESWAP
-#endif
-
/* permedia3 -specific definitions */
#define PM3_SCALE_TO_CLOCK(pr, fe, po) ((2 * PM3_REF_CLOCK * fe) / (pr * (1 << (po))))
@@ -1203,19 +1175,9 @@
/* ******************************************** */
/* ***** A bunch of register-access macro ***** */
/* ******************************************** */
-#ifdef KERNEL_2_2
-#ifdef MUST_BYTESWAP /* we are writing big_endian to big_endian through a little_endian macro */
-#define PM3_READ_REG(r) __swab32(readl((l_fb_info->vIOBase + r)))
-#define PM3_WRITE_REG(r, v) writel(__swab32(v), (l_fb_info->vIOBase + r))
-#else /* MUST_BYTESWAP */
-#define PM3_WRITE_REG(r, v) writel(v, (l_fb_info->vIOBase + r))
-#define PM3_READ_REG(r) readl((l_fb_info->vIOBase + r))
-#endif /* MUST_BYTESWAP */
-#endif /* KERNEL_2_2 */
-#if (defined KERNEL_2_4) || (defined KERNEL_2_5) /* native-endian access */
+
#define PM3_WRITE_REG(r, v) fb_writel(v, (l_fb_info->vIOBase + r))
#define PM3_READ_REG(r) fb_readl((l_fb_info->vIOBase + r))
-#endif /* KERNEL_2_4 or KERNEL_2_5 */
#define depth2bpp(d) ((d + 7L) & ~7L)
diff --git a/include/video/s1d13xxxfb.h b/include/video/s1d13xxxfb.h
new file mode 100644
index 0000000000000..f06cc88607f51
--- /dev/null
+++ b/include/video/s1d13xxxfb.h
@@ -0,0 +1,166 @@
+/* drivers/video/s1d3xxxfb.h
+ *
+ * (c) 2004 Simtec Electronics
+ * (c) 2005 Thibaut VARENE <varenet@parisc-linux.org>
+ *
+ * Header file for Epson S1D13XXX driver code
+ *
+ * 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 S1D13XXXFB_H
+#define S1D13XXXFB_H
+
+#define S1D_PALETTE_SIZE 256
+#define S1D_CHIP_REV 7 /* expected chip revision number for s1d13806 */
+#define S1D_FBID "S1D13806"
+#define S1D_DEVICENAME "s1d13806fb"
+
+/* register definitions (tested on s1d13896) */
+#define S1DREG_REV_CODE 0x0000 /* Revision Code Register */
+#define S1DREG_MISC 0x0001 /* Miscellaneous Register */
+#define S1DREG_GPIO_CNF0 0x0004 /* General IO Pins Configuration Register 0 */
+#define S1DREG_GPIO_CNF1 0x0005 /* General IO Pins Configuration Register 1 */
+#define S1DREG_GPIO_CTL0 0x0008 /* General IO Pins Control Register 0 */
+#define S1DREG_GPIO_CTL1 0x0009 /* General IO Pins Control Register 1 */
+#define S1DREG_CNF_STATUS 0x000C /* Configuration Status Readback Register */
+#define S1DREG_CLK_CNF 0x0010 /* Memory Clock Configuration Register */
+#define S1DREG_LCD_CLK_CNF 0x0014 /* LCD Pixel Clock Configuration Register */
+#define S1DREG_CRT_CLK_CNF 0x0018 /* CRT/TV Pixel Clock Configuration Register */
+#define S1DREG_MPLUG_CLK_CNF 0x001C /* MediaPlug Clock Configuration Register */
+#define S1DREG_CPU2MEM_WST_SEL 0x001E /* CPU To Memory Wait State Select Register */
+#define S1DREG_MEM_CNF 0x0020 /* Memory Configuration Register */
+#define S1DREG_SDRAM_REF_RATE 0x0021 /* SDRAM Refresh Rate Register */
+#define S1DREG_SDRAM_TC0 0x002A /* SDRAM Timing Control Register 0 */
+#define S1DREG_SDRAM_TC1 0x002B /* SDRAM Timing Control Register 1 */
+#define S1DREG_PANEL_TYPE 0x0030 /* Panel Type Register */
+#define S1DREG_MOD_RATE 0x0031 /* MOD Rate Register */
+#define S1DREG_LCD_DISP_HWIDTH 0x0032 /* LCD Horizontal Display Width Register: ((val)+1)*8)=pix/line */
+#define S1DREG_LCD_NDISP_HPER 0x0034 /* LCD Horizontal Non-Display Period Register: ((val)+1)*8)=NDpix/line */
+#define S1DREG_TFT_FPLINE_START 0x0035 /* TFT FPLINE Start Position Register */
+#define S1DREG_TFT_FPLINE_PWIDTH 0x0036 /* TFT FPLINE Pulse Width Register. */
+#define S1DREG_LCD_DISP_VHEIGHT0 0x0038 /* LCD Vertical Display Height Register 0 */
+#define S1DREG_LCD_DISP_VHEIGHT1 0x0039 /* LCD Vertical Display Height Register 1 */
+#define S1DREG_LCD_NDISP_VPER 0x003A /* LCD Vertical Non-Display Period Register: (val)+1=NDlines */
+#define S1DREG_TFT_FPFRAME_START 0x003B /* TFT FPFRAME Start Position Register */
+#define S1DREG_TFT_FPFRAME_PWIDTH 0x003C /* TFT FPFRAME Pulse Width Register */
+#define S1DREG_LCD_DISP_MODE 0x0040 /* LCD Display Mode Register */
+#define S1DREG_LCD_MISC 0x0041 /* LCD Miscellaneous Register */
+#define S1DREG_LCD_DISP_START0 0x0042 /* LCD Display Start Address Register 0 */
+#define S1DREG_LCD_DISP_START1 0x0043 /* LCD Display Start Address Register 1 */
+#define S1DREG_LCD_DISP_START2 0x0044 /* LCD Display Start Address Register 2 */
+#define S1DREG_LCD_MEM_OFF0 0x0046 /* LCD Memory Address Offset Register 0 */
+#define S1DREG_LCD_MEM_OFF1 0x0047 /* LCD Memory Address Offset Register 1 */
+#define S1DREG_LCD_PIX_PAN 0x0048 /* LCD Pixel Panning Register */
+#define S1DREG_LCD_DISP_FIFO_HTC 0x004A /* LCD Display FIFO High Threshold Control Register */
+#define S1DREG_LCD_DISP_FIFO_LTC 0x004B /* LCD Display FIFO Low Threshold Control Register */
+#define S1DREG_CRT_DISP_HWIDTH 0x0050 /* CRT/TV Horizontal Display Width Register: ((val)+1)*8)=pix/line */
+#define S1DREG_CRT_NDISP_HPER 0x0052 /* CRT/TV Horizontal Non-Display Period Register */
+#define S1DREG_CRT_HRTC_START 0x0053 /* CRT/TV HRTC Start Position Register */
+#define S1DREG_CRT_HRTC_PWIDTH 0x0054 /* CRT/TV HRTC Pulse Width Register */
+#define S1DREG_CRT_DISP_VHEIGHT0 0x0056 /* CRT/TV Vertical Display Height Register 0 */
+#define S1DREG_CRT_DISP_VHEIGHT1 0x0057 /* CRT/TV Vertical Display Height Register 1 */
+#define S1DREG_CRT_NDISP_VPER 0x0058 /* CRT/TV Vertical Non-Display Period Register */
+#define S1DREG_CRT_VRTC_START 0x0059 /* CRT/TV VRTC Start Position Register */
+#define S1DREG_CRT_VRTC_PWIDTH 0x005A /* CRT/TV VRTC Pulse Width Register */
+#define S1DREG_TV_OUT_CTL 0x005B /* TV Output Control Register */
+#define S1DREG_CRT_DISP_MODE 0x0060 /* CRT/TV Display Mode Register */
+#define S1DREG_CRT_DISP_START0 0x0062 /* CRT/TV Display Start Address Register 0 */
+#define S1DREG_CRT_DISP_START1 0x0063 /* CRT/TV Display Start Address Register 1 */
+#define S1DREG_CRT_DISP_START2 0x0064 /* CRT/TV Display Start Address Register 2 */
+#define S1DREG_CRT_MEM_OFF0 0x0066 /* CRT/TV Memory Address Offset Register 0 */
+#define S1DREG_CRT_MEM_OFF1 0x0067 /* CRT/TV Memory Address Offset Register 1 */
+#define S1DREG_CRT_PIX_PAN 0x0068 /* CRT/TV Pixel Panning Register */
+#define S1DREG_CRT_DISP_FIFO_HTC 0x006A /* CRT/TV Display FIFO High Threshold Control Register */
+#define S1DREG_CRT_DISP_FIFO_LTC 0x006B /* CRT/TV Display FIFO Low Threshold Control Register */
+#define S1DREG_LCD_CUR_CTL 0x0070 /* LCD Ink/Cursor Control Register */
+#define S1DREG_LCD_CUR_START 0x0071 /* LCD Ink/Cursor Start Address Register */
+#define S1DREG_LCD_CUR_XPOS0 0x0072 /* LCD Cursor X Position Register 0 */
+#define S1DREG_LCD_CUR_XPOS1 0x0073 /* LCD Cursor X Position Register 1 */
+#define S1DREG_LCD_CUR_YPOS0 0x0074 /* LCD Cursor Y Position Register 0 */
+#define S1DREG_LCD_CUR_YPOS1 0x0075 /* LCD Cursor Y Position Register 1 */
+#define S1DREG_LCD_CUR_BCTL0 0x0076 /* LCD Ink/Cursor Blue Color 0 Register */
+#define S1DREG_LCD_CUR_GCTL0 0x0077 /* LCD Ink/Cursor Green Color 0 Register */
+#define S1DREG_LCD_CUR_RCTL0 0x0078 /* LCD Ink/Cursor Red Color 0 Register */
+#define S1DREG_LCD_CUR_BCTL1 0x007A /* LCD Ink/Cursor Blue Color 1 Register */
+#define S1DREG_LCD_CUR_GCTL1 0x007B /* LCD Ink/Cursor Green Color 1 Register */
+#define S1DREG_LCD_CUR_RCTL1 0x007C /* LCD Ink/Cursor Red Color 1 Register */
+#define S1DREG_LCD_CUR_FIFO_HTC 0x007E /* LCD Ink/Cursor FIFO High Threshold Register */
+#define S1DREG_CRT_CUR_CTL 0x0080 /* CRT/TV Ink/Cursor Control Register */
+#define S1DREG_CRT_CUR_START 0x0081 /* CRT/TV Ink/Cursor Start Address Register */
+#define S1DREG_CRT_CUR_XPOS0 0x0082 /* CRT/TV Cursor X Position Register 0 */
+#define S1DREG_CRT_CUR_XPOS1 0x0083 /* CRT/TV Cursor X Position Register 1 */
+#define S1DREG_CRT_CUR_YPOS0 0x0084 /* CRT/TV Cursor Y Position Register 0 */
+#define S1DREG_CRT_CUR_YPOS1 0x0085 /* CRT/TV Cursor Y Position Register 1 */
+#define S1DREG_CRT_CUR_BCTL0 0x0086 /* CRT/TV Ink/Cursor Blue Color 0 Register */
+#define S1DREG_CRT_CUR_GCTL0 0x0087 /* CRT/TV Ink/Cursor Green Color 0 Register */
+#define S1DREG_CRT_CUR_RCTL0 0x0088 /* CRT/TV Ink/Cursor Red Color 0 Register */
+#define S1DREG_CRT_CUR_BCTL1 0x008A /* CRT/TV Ink/Cursor Blue Color 1 Register */
+#define S1DREG_CRT_CUR_GCTL1 0x008B /* CRT/TV Ink/Cursor Green Color 1 Register */
+#define S1DREG_CRT_CUR_RCTL1 0x008C /* CRT/TV Ink/Cursor Red Color 1 Register */
+#define S1DREG_CRT_CUR_FIFO_HTC 0x008E /* CRT/TV Ink/Cursor FIFO High Threshold Register */
+#define S1DREG_BBLT_CTL0 0x0100 /* BitBLT Control Register 0 */
+#define S1DREG_BBLT_CTL1 0x0101 /* BitBLT Control Register 1 */
+#define S1DREG_BBLT_CC_EXP 0x0102 /* BitBLT Code/Color Expansion Register */
+#define S1DREG_BBLT_OP 0x0103 /* BitBLT Operation Register */
+#define S1DREG_BBLT_SRC_START0 0x0104 /* BitBLT Source Start Address Register 0 */
+#define S1DREG_BBLT_SRC_START1 0x0105 /* BitBLT Source Start Address Register 1 */
+#define S1DREG_BBLT_SRC_START2 0x0106 /* BitBLT Source Start Address Register 2 */
+#define S1DREG_BBLT_DST_START0 0x0108 /* BitBLT Destination Start Address Register 0 */
+#define S1DREG_BBLT_DST_START1 0x0109 /* BitBLT Destination Start Address Register 1 */
+#define S1DREG_BBLT_DST_START2 0x010A /* BitBLT Destination Start Address Register 2 */
+#define S1DREG_BBLT_MEM_OFF0 0x010C /* BitBLT Memory Address Offset Register 0 */
+#define S1DREG_BBLT_MEM_OFF1 0x010D /* BitBLT Memory Address Offset Register 1 */
+#define S1DREG_BBLT_WIDTH0 0x0110 /* BitBLT Width Register 0 */
+#define S1DREG_BBLT_WIDTH1 0x0111 /* BitBLT Width Register 1 */
+#define S1DREG_BBLT_HEIGHT0 0x0112 /* BitBLT Height Register 0 */
+#define S1DREG_BBLT_HEIGHT1 0x0113 /* BitBLT Height Register 1 */
+#define S1DREG_BBLT_BGC0 0x0114 /* BitBLT Background Color Register 0 */
+#define S1DREG_BBLT_BGC1 0x0115 /* BitBLT Background Color Register 1 */
+#define S1DREG_BBLT_FGC0 0x0118 /* BitBLT Foreground Color Register 0 */
+#define S1DREG_BBLT_FGC1 0x0119 /* BitBLT Foreground Color Register 1 */
+#define S1DREG_LKUP_MODE 0x01E0 /* Look-Up Table Mode Register */
+#define S1DREG_LKUP_ADDR 0x01E2 /* Look-Up Table Address Register */
+#define S1DREG_LKUP_DATA 0x01E4 /* Look-Up Table Data Register */
+#define S1DREG_PS_CNF 0x01F0 /* Power Save Configuration Register */
+#define S1DREG_PS_STATUS 0x01F1 /* Power Save Status Register */
+#define S1DREG_CPU2MEM_WDOGT 0x01F4 /* CPU-to-Memory Access Watchdog Timer Register */
+#define S1DREG_COM_DISP_MODE 0x01FC /* Common Display Mode Register */
+
+#define S1DREG_DELAYOFF 0xFFFE
+#define S1DREG_DELAYON 0xFFFF
+
+/* Note: all above defines should go in separate header files
+ when implementing other S1D13xxx chip support. */
+
+struct s1d13xxxfb_regval {
+ u16 addr;
+ u8 value;
+};
+
+
+struct s1d13xxxfb_par {
+ void __iomem *regs;
+ unsigned char display;
+
+ unsigned int pseudo_palette[16];
+#ifdef CONFIG_PM
+ void *regs_save; /* pm saves all registers here */
+ void *disp_save; /* pm saves entire screen here */
+#endif
+};
+
+struct s1d13xxxfb_pdata {
+ const struct s1d13xxxfb_regval *initregs;
+ const unsigned int initregssize;
+ void (*platform_init_video)(void);
+#ifdef CONFIG_PM
+ int (*platform_suspend_video)(void);
+ int (*platform_resume_video)(void);
+#endif
+};
+
+#endif
+
diff --git a/include/video/trident.h b/include/video/trident.h
index abe7d67756de7..200be25516819 100644
--- a/include/video/trident.h
+++ b/include/video/trident.h
@@ -9,7 +9,7 @@
#define debug(f,a...)
#endif
-#define output(f, a...) printk("tridentfb: " f, ## a)
+#define output(f, a...) pr_info("tridentfb: " f, ## a)
#define Kb (1024)
#define Mb (Kb*Kb)
diff --git a/init/Kconfig b/init/Kconfig
index 6dd338705e0a0..abe2682a6ca68 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -55,6 +55,14 @@ config LOCK_KERNEL
depends on SMP || PREEMPT
default y
+config INIT_ENV_ARG_LIMIT
+ int
+ default 32 if !USERMODE
+ default 128 if USERMODE
+ help
+ This is the value of the two limits on the number of argument and of
+ env.var passed to init from the kernel command line.
+
endmenu
menu "General setup"
@@ -157,7 +165,6 @@ config SYSCTL
config AUDIT
bool "Auditing support"
default y if SECURITY_SELINUX
- default n
help
Enable auditing infrastructure that can be used with another
kernel subsystem, such as SELinux (which requires this for
@@ -168,29 +175,11 @@ config AUDITSYSCALL
bool "Enable system-call auditing support"
depends on AUDIT && (X86 || PPC64 || ARCH_S390 || IA64)
default y if SECURITY_SELINUX
- default n
help
Enable low-overhead system-call auditing infrastructure that
can be used independently or with another kernel subsystem,
such as SELinux.
-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 16 if X86_NUMAQ || IA64
- default 15 if SMP
- default 14
- help
- Select kernel log buffer size as a power of 2.
- Defaults and Examples:
- 17 => 128 KB for S/390
- 16 => 64 KB for x86 NUMAQ or IA-64
- 15 => 32 KB for SMP
- 14 => 16 KB for uniprocessor
- 13 => 8 KB
- 12 => 4 KB
-
config HOTPLUG
bool "Support for hot-pluggable devices" if !ARCH_S390
default ARCH_S390
@@ -237,6 +226,16 @@ config IKCONFIG_PROC
This option enables access to the kernel configuration file
through /proc/config.gz.
+config CPUSETS
+ bool "Cpuset support"
+ depends on SMP
+ help
+ This options will let you create and manage CPUSET's which
+ allow dynamically partitioning a system into sets of CPUs and
+ Memory Nodes and assigning tasks to run only within those sets.
+ This is primarily useful on large SMP or NUMA systems.
+
+ Say N if unsure.
menuconfig EMBEDDED
bool "Configure standard kernel features (for small systems)"
@@ -276,6 +275,14 @@ config KALLSYMS_EXTRA_PASS
reported. KALLSYMS_EXTRA_PASS is only a temporary workaround while
you wait for kallsyms to be fixed.
+config BASE_FULL
+ default y
+ bool "Enable full-sized data structures for core" if EMBEDDED
+ help
+ Disabling this option reduces the size of miscellaneous core
+ kernel data structures. This saves memory on small machines,
+ but may reduce performance.
+
config FUTEX
bool "Enable futex support" if EMBEDDED
default y
@@ -294,7 +301,6 @@ config EPOLL
config CC_OPTIMIZE_FOR_SIZE
bool "Optimize for size" if EMBEDDED
default y if ARM || H8300
- default n
help
Enabling this option will pass "-Os" instead of "-O2" to gcc
resulting in a smaller kernel.
@@ -358,6 +364,11 @@ config TINY_SHMEM
default !SHMEM
bool
+config BASE_SMALL
+ int
+ default 0 if BASE_FULL
+ default 1 if !BASE_FULL
+
menu "Loadable module support"
config MODULES
@@ -410,7 +421,7 @@ config OBSOLETE_MODPARM
config MODVERSIONS
bool "Module versioning support (EXPERIMENTAL)"
- depends on MODULES && EXPERIMENTAL && !USERMODE
+ depends on MODULES && EXPERIMENTAL && !UML
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.c b/init/do_mounts.c
index 185794fcd01ce..b7570c074d0fe 100644
--- a/init/do_mounts.c
+++ b/init/do_mounts.c
@@ -53,7 +53,7 @@ static int __init readwrite(char *str)
__setup("ro", readonly);
__setup("rw", readwrite);
-static dev_t __init try_name(char *name, int part)
+static dev_t try_name(char *name, int part)
{
char path[64];
char buf[32];
@@ -135,7 +135,7 @@ fail:
* is mounted on rootfs /sys.
*/
-dev_t __init name_to_dev_t(char *name)
+dev_t name_to_dev_t(char *name)
{
char s[32];
char *p;
diff --git a/init/main.c b/init/main.c
index 6849397dd475f..40bf367ffdf19 100644
--- a/init/main.c
+++ b/init/main.c
@@ -41,6 +41,7 @@
#include <linux/kallsyms.h>
#include <linux/writeback.h>
#include <linux/cpu.h>
+#include <linux/cpuset.h>
#include <linux/efi.h>
#include <linux/unistd.h>
#include <linux/rmap.h>
@@ -109,8 +110,8 @@ EXPORT_SYMBOL(system_state);
/*
* Boot command-line arguments
*/
-#define MAX_INIT_ARGS 32
-#define MAX_INIT_ENVS 32
+#define MAX_INIT_ARGS CONFIG_INIT_ENV_ARG_LIMIT
+#define MAX_INIT_ENVS CONFIG_INIT_ENV_ARG_LIMIT
extern void time_init(void);
/* Default late time init is NULL. archs can override this later. */
@@ -209,6 +210,14 @@ static int __init quiet_kernel(char *str)
__setup("debug", debug_kernel);
__setup("quiet", quiet_kernel);
+static int __init loglevel(char *str)
+{
+ get_option(&str, &console_loglevel);
+ return 1;
+}
+
+__setup("loglevel=", loglevel);
+
/*
* Unknown boot options get handed to init, unless they look like
* failed parameters
@@ -347,12 +356,11 @@ static void __init smp_init(void)
}
/* Any cleanup work */
- printk("Brought up %ld CPUs\n", (long)num_online_cpus());
+ printk(KERN_INFO "Brought up %ld CPUs\n", (long)num_online_cpus());
smp_cpus_done(max_cpus);
#if 0
/* Get other processors into their bootup holding patterns. */
- smp_threads_ready=1;
smp_commence();
#endif
}
@@ -423,6 +431,7 @@ asmlinkage void __init start_kernel(void)
*/
lock_kernel();
page_address_init();
+ printk(KERN_NOTICE);
printk(linux_banner);
setup_arch(&command_line);
setup_per_cpu_areas();
@@ -446,7 +455,7 @@ asmlinkage void __init start_kernel(void)
preempt_disable();
build_all_zonelists();
page_alloc_init();
- printk("Kernel command line: %s\n", saved_command_line);
+ printk(KERN_NOTICE "Kernel command line: %s\n", saved_command_line);
parse_early_param();
parse_args("Booting kernel", command_line, __start___param,
__stop___param - __start___param,
@@ -497,6 +506,7 @@ asmlinkage void __init start_kernel(void)
proc_caches_init();
buffer_init();
unnamed_dev_init();
+ key_init();
security_init();
vfs_caches_init(num_physpages);
radix_tree_init();
@@ -506,6 +516,8 @@ asmlinkage void __init start_kernel(void)
#ifdef CONFIG_PROC_FS
proc_root_init();
#endif
+ cpuset_init();
+
check_bugs();
acpi_early_init(); /* before LAPIC and SMP init */
@@ -553,7 +565,7 @@ static void __init do_initcalls(void)
local_irq_enable();
}
if (msg) {
- printk("error in initcall at 0x%p: "
+ printk(KERN_WARNING "error in initcall at 0x%p: "
"returned with %s\n", *call, msg);
}
}
@@ -574,7 +586,6 @@ static void __init do_basic_setup(void)
/* drivers will send hotplug events */
init_workqueues();
usermodehelper_init();
- key_init();
driver_init();
#ifdef CONFIG_SYSCTL
@@ -626,6 +637,10 @@ static int init(void * unused)
{
lock_kernel();
/*
+ * init can run on any cpu.
+ */
+ set_cpus_allowed(current, CPU_MASK_ALL);
+ /*
* Tell the world that we're going to be the grim
* reaper of innocent orphaned children.
*
@@ -644,6 +659,8 @@ static int init(void * unused)
smp_init();
sched_init_smp();
+ cpuset_init_smp();
+
/*
* Do this before initcalls, because some drivers want to access
* firmware files.
@@ -672,7 +689,7 @@ static int init(void * unused)
numa_default_policy();
if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)
- printk("Warning: unable to open an initial console.\n");
+ printk(KERN_WARNING "Warning: unable to open an initial console.\n");
(void) sys_dup(0);
(void) sys_dup(0);
diff --git a/ipc/compat_mq.c b/ipc/compat_mq.c
index 034d5d73ccf2b..d8d1e9ff4e886 100644
--- a/ipc/compat_mq.c
+++ b/ipc/compat_mq.c
@@ -25,7 +25,7 @@ struct compat_mq_attr {
static inline int get_compat_mq_attr(struct mq_attr *attr,
const struct compat_mq_attr __user *uattr)
{
- if (verify_area(VERIFY_READ, uattr, sizeof *uattr))
+ if (!access_ok(VERIFY_READ, uattr, sizeof *uattr))
return -EFAULT;
return __get_user(attr->mq_flags, &uattr->mq_flags)
@@ -102,20 +102,6 @@ asmlinkage ssize_t compat_sys_mq_timedreceive(mqd_t mqdes,
u_msg_prio, u_ts);
}
-static int get_compat_sigevent(struct sigevent *event,
- const struct compat_sigevent __user *u_event)
-{
- if (verify_area(VERIFY_READ, u_event, sizeof(*u_event)))
- return -EFAULT;
-
- return __get_user(event->sigev_value.sival_int,
- &u_event->sigev_value.sival_int)
- | __get_user(event->sigev_signo, &u_event->sigev_signo)
- | __get_user(event->sigev_notify, &u_event->sigev_notify)
- | __get_user(event->sigev_notify_thread_id,
- &u_event->sigev_notify_thread_id);
-}
-
asmlinkage long compat_sys_mq_notify(mqd_t mqdes,
const struct compat_sigevent __user *u_notification)
{
diff --git a/ipc/msg.c b/ipc/msg.c
index 7d7470c8d2c25..27e516f96cdc7 100644
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -25,6 +25,7 @@
#include <linux/security.h>
#include <linux/sched.h>
#include <linux/syscalls.h>
+#include <linux/audit.h>
#include <asm/current.h>
#include <asm/uaccess.h>
#include "util.h"
@@ -425,6 +426,8 @@ asmlinkage long sys_msgctl (int msqid, int cmd, struct msqid_ds __user *buf)
return -EFAULT;
if (copy_msqid_from_user (&setbuf, buf, version))
return -EFAULT;
+ if ((err = audit_ipc_perms(setbuf.qbytes, setbuf.uid, setbuf.gid, setbuf.mode)))
+ return err;
break;
case IPC_RMID:
break;
diff --git a/ipc/sem.c b/ipc/sem.c
index f0efedb8d4c30..5ad7ac0ed60d0 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -72,6 +72,7 @@
#include <linux/smp_lock.h>
#include <linux/security.h>
#include <linux/syscalls.h>
+#include <linux/audit.h>
#include <asm/uaccess.h>
#include "util.h"
@@ -803,6 +804,8 @@ static int semctl_down(int semid, int semnum, int cmd, int version, union semun
if(cmd == IPC_SET) {
if(copy_semid_from_user (&setbuf, arg.buf, version))
return -EFAULT;
+ if ((err = audit_ipc_perms(0, setbuf.uid, setbuf.gid, setbuf.mode)))
+ return err;
}
sma = sem_lock(semid);
if(sma==NULL)
diff --git a/ipc/shm.c b/ipc/shm.c
index dcdc6d5e22bcb..06cd5c91056f5 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -27,6 +27,7 @@
#include <linux/shmem_fs.h>
#include <linux/security.h>
#include <linux/syscalls.h>
+#include <linux/audit.h>
#include <asm/uaccess.h>
#include "util.h"
@@ -600,6 +601,8 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf)
err = -EFAULT;
goto out;
}
+ if ((err = audit_ipc_perms(0, setbuf.uid, setbuf.gid, setbuf.mode)))
+ return err;
down(&shm_ids.sem);
shp = shm_lock(shmid);
err=-EINVAL;
diff --git a/kernel/Makefile b/kernel/Makefile
index db7281f1f087a..eb88b446c2cca 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -7,7 +7,7 @@ obj-y = sched.o fork.o exec_domain.o panic.o printk.o profile.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
+ kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o
obj-$(CONFIG_FUTEX) += futex.o
obj-$(CONFIG_GENERIC_ISA_DMA) += dma.o
@@ -18,6 +18,7 @@ obj-$(CONFIG_KALLSYMS) += kallsyms.o
obj-$(CONFIG_PM) += power/
obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o
obj-$(CONFIG_COMPAT) += compat.o
+obj-$(CONFIG_CPUSETS) += cpuset.o
obj-$(CONFIG_IKCONFIG) += configs.o
obj-$(CONFIG_IKCONFIG_PROC) += configs.o
obj-$(CONFIG_STOP_MACHINE) += stop_machine.o
@@ -26,6 +27,7 @@ obj-$(CONFIG_AUDITSYSCALL) += auditsc.o
obj-$(CONFIG_KPROBES) += kprobes.o
obj-$(CONFIG_SYSFS) += ksysfs.o
obj-$(CONFIG_GENERIC_HARDIRQS) += irq/
+obj-$(CONFIG_SECCOMP) += seccomp.o
ifneq ($(CONFIG_IA64),y)
# According to Alan Modra <alan@linuxcare.com.au>, the -fno-omit-frame-pointer is
@@ -45,7 +47,7 @@ $(obj)/config_data.gz: .config FORCE
$(call if_changed,gzip)
quiet_cmd_ikconfiggz = IKCFG $@
- cmd_ikconfiggz = (echo "const char kernel_config_data[] = MAGIC_START"; cat $< | scripts/bin2c; echo "MAGIC_END;") > $@
+ cmd_ikconfiggz = (echo "static const char kernel_config_data[] = MAGIC_START"; cat $< | scripts/bin2c; echo "MAGIC_END;") > $@
targets += config_data.h
$(obj)/config_data.h: $(obj)/config_data.gz FORCE
$(call if_changed,ikconfiggz)
diff --git a/kernel/acct.c b/kernel/acct.c
index 32e39accbb86c..4168f631868e1 100644
--- a/kernel/acct.c
+++ b/kernel/acct.c
@@ -170,7 +170,7 @@ out:
*
* NOTE: acct_globals.lock MUST be held on entry and exit.
*/
-void acct_file_reopen(struct file *file)
+static void acct_file_reopen(struct file *file)
{
struct file *old_acct = NULL;
@@ -534,17 +534,15 @@ void acct_process(long exitcode)
* acct_update_integrals
* - update mm integral fields in task_struct
*/
-void acct_update_integrals(void)
+void acct_update_integrals(struct task_struct *tsk)
{
- struct task_struct *tsk = current;
-
if (likely(tsk->mm)) {
long delta = tsk->stime - tsk->acct_stimexpd;
if (delta == 0)
return;
tsk->acct_stimexpd = tsk->stime;
- tsk->acct_rss_mem1 += delta * tsk->mm->rss;
+ tsk->acct_rss_mem1 += delta * get_mm_counter(tsk->mm, rss);
tsk->acct_vm_mem1 += delta * tsk->mm->total_vm;
}
}
diff --git a/kernel/audit.c b/kernel/audit.c
index 9b48512a4cf57..0f84dd7af2c8d 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -155,6 +155,9 @@ struct audit_entry {
struct audit_rule rule;
};
+static void audit_log_end_irq(struct audit_buffer *ab);
+static void audit_log_end_fast(struct audit_buffer *ab);
+
static void audit_panic(const char *message)
{
switch (audit_failure)
@@ -236,7 +239,7 @@ void audit_log_lost(const char *message)
}
-int audit_set_rate_limit(int limit)
+static int audit_set_rate_limit(int limit)
{
int old = audit_rate_limit;
audit_rate_limit = limit;
@@ -245,7 +248,7 @@ int audit_set_rate_limit(int limit)
return old;
}
-int audit_set_backlog_limit(int limit)
+static int audit_set_backlog_limit(int limit)
{
int old = audit_backlog_limit;
audit_backlog_limit = limit;
@@ -254,7 +257,7 @@ int audit_set_backlog_limit(int limit)
return old;
}
-int audit_set_enabled(int state)
+static int audit_set_enabled(int state)
{
int old = audit_enabled;
if (state != 0 && state != 1)
@@ -265,7 +268,7 @@ int audit_set_enabled(int state)
return old;
}
-int audit_set_failure(int state)
+static int audit_set_failure(int state)
{
int old = audit_failure;
if (state != AUDIT_FAIL_SILENT
@@ -360,7 +363,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
status_set.backlog_limit = audit_backlog_limit;
status_set.lost = atomic_read(&audit_lost);
status_set.backlog = atomic_read(&audit_backlog);
- audit_send_reply(pid, seq, AUDIT_GET, 0, 0,
+ audit_send_reply(NETLINK_CB(skb).pid, seq, AUDIT_GET, 0, 0,
&status_set, sizeof(status_set));
break;
case AUDIT_SET:
@@ -407,8 +410,8 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
/* fallthrough */
case AUDIT_LIST:
#ifdef CONFIG_AUDITSYSCALL
- err = audit_receive_filter(nlh->nlmsg_type, pid, uid, seq,
- data);
+ err = audit_receive_filter(nlh->nlmsg_type, NETLINK_CB(skb).pid,
+ uid, seq, data);
#else
err = -EOPNOTSUPP;
#endif
@@ -547,7 +550,7 @@ static inline int audit_log_drain(struct audit_buffer *ab)
}
/* Initialize audit support at boot time. */
-int __init audit_init(void)
+static int __init audit_init(void)
{
printk(KERN_INFO "audit: initializing netlink socket (%s)\n",
audit_default ? "enabled" : "disabled");
@@ -768,7 +771,7 @@ static DECLARE_TASKLET(audit_tasklet, audit_tasklet_handler, 0);
* the audit buffer is places on a queue and a tasklet is scheduled to
* remove them from the queue outside the irq context. May be called in
* any context. */
-void audit_log_end_irq(struct audit_buffer *ab)
+static void audit_log_end_irq(struct audit_buffer *ab)
{
unsigned long flags;
@@ -783,7 +786,7 @@ void audit_log_end_irq(struct audit_buffer *ab)
/* Send the message in the audit buffer directly to user space. May not
* be called in an irq context. */
-void audit_log_end_fast(struct audit_buffer *ab)
+static void audit_log_end_fast(struct audit_buffer *ab)
{
unsigned long flags;
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index c412d6779733a..8c454852d6a52 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -89,9 +89,30 @@ enum audit_state {
struct audit_names {
const char *name;
unsigned long ino;
+ dev_t dev;
+ umode_t mode;
+ uid_t uid;
+ gid_t gid;
dev_t rdev;
};
+struct audit_aux_data {
+ struct audit_aux_data *next;
+ int type;
+};
+
+#define AUDIT_AUX_IPCPERM 0
+
+struct audit_aux_data_ipcctl {
+ struct audit_aux_data d;
+ struct ipc_perm p;
+ unsigned long qbytes;
+ uid_t uid;
+ gid_t gid;
+ mode_t mode;
+};
+
+
/* The per-task audit context. */
struct audit_context {
int in_syscall; /* 1 if task is in a syscall */
@@ -107,6 +128,7 @@ struct audit_context {
int name_count;
struct audit_names names[AUDIT_NAMES];
struct audit_context *previous; /* For nested syscalls */
+ struct audit_aux_data *aux;
/* Save things to print about task_struct */
pid_t pid;
@@ -338,7 +360,7 @@ static int audit_filter_rules(struct task_struct *tsk,
case AUDIT_DEVMAJOR:
if (ctx) {
for (j = 0; j < ctx->name_count; j++) {
- if (MAJOR(ctx->names[j].rdev)==value) {
+ if (MAJOR(ctx->names[j].dev)==value) {
++result;
break;
}
@@ -348,7 +370,7 @@ static int audit_filter_rules(struct task_struct *tsk,
case AUDIT_DEVMINOR:
if (ctx) {
for (j = 0; j < ctx->name_count; j++) {
- if (MINOR(ctx->names[j].rdev)==value) {
+ if (MINOR(ctx->names[j].dev)==value) {
++result;
break;
}
@@ -358,7 +380,7 @@ static int audit_filter_rules(struct task_struct *tsk,
case AUDIT_INODE:
if (ctx) {
for (j = 0; j < ctx->name_count; j++) {
- if (MINOR(ctx->names[j].ino)==value) {
+ if (ctx->names[j].ino == value) {
++result;
break;
}
@@ -504,6 +526,16 @@ static inline void audit_free_names(struct audit_context *context)
context->name_count = 0;
}
+static inline void audit_free_aux(struct audit_context *context)
+{
+ struct audit_aux_data *aux;
+
+ while ((aux = context->aux)) {
+ context->aux = aux->next;
+ kfree(aux);
+ }
+}
+
static inline void audit_zero_context(struct audit_context *context,
enum audit_state state)
{
@@ -570,6 +602,7 @@ static inline void audit_free_context(struct audit_context *context)
context->name_count, count);
}
audit_free_names(context);
+ audit_free_aux(context);
kfree(context);
context = previous;
} while (context);
@@ -607,6 +640,29 @@ static void audit_log_exit(struct audit_context *context)
context->euid, context->suid, context->fsuid,
context->egid, context->sgid, context->fsgid);
audit_log_end(ab);
+ while (context->aux) {
+ struct audit_aux_data *aux;
+
+ ab = audit_log_start(context);
+ if (!ab)
+ continue; /* audit_panic has been called */
+
+ aux = context->aux;
+ context->aux = aux->next;
+
+ audit_log_format(ab, "auxitem=%d", aux->type);
+ switch (aux->type) {
+ case AUDIT_AUX_IPCPERM: {
+ struct audit_aux_data_ipcctl *axi = (void *)aux;
+ audit_log_format(ab,
+ " qbytes=%lx uid=%d gid=%d mode=%x",
+ axi->qbytes, axi->uid, axi->gid, axi->mode);
+ }
+ }
+ audit_log_end(ab);
+ kfree(aux);
+ }
+
for (i = 0; i < context->name_count; i++) {
ab = audit_log_start(context);
if (!ab)
@@ -616,12 +672,14 @@ static void audit_log_exit(struct audit_context *context)
audit_log_format(ab, " name=%s",
context->names[i].name);
if (context->names[i].ino != (unsigned long)-1)
- audit_log_format(ab, " inode=%lu",
- context->names[i].ino);
- /* FIXME: should use format_dev_t, but ab structure is
- * opaque. */
- if (context->names[i].rdev != -1)
- audit_log_format(ab, " dev=%02x:%02x",
+ audit_log_format(ab, " inode=%lu dev=%02x:%02x mode=%#o"
+ " uid=%d gid=%d rdev=%02x:%02x",
+ context->names[i].ino,
+ MAJOR(context->names[i].dev),
+ MINOR(context->names[i].dev),
+ context->names[i].mode,
+ context->names[i].uid,
+ context->names[i].gid,
MAJOR(context->names[i].rdev),
MINOR(context->names[i].rdev));
audit_log_end(ab);
@@ -789,6 +847,7 @@ void audit_syscall_exit(struct task_struct *tsk, int return_code)
tsk->audit_context = new_context;
} else {
audit_free_names(context);
+ audit_free_aux(context);
audit_zero_context(context, context->state);
tsk->audit_context = context;
}
@@ -800,7 +859,9 @@ void audit_getname(const char *name)
{
struct audit_context *context = current->audit_context;
- BUG_ON(!context);
+ if (!context || IS_ERR(name) || !name)
+ return;
+
if (!context->in_syscall) {
#if AUDIT_DEBUG == 2
printk(KERN_ERR "%s:%d(:%d): ignoring getname(%p)\n",
@@ -812,7 +873,6 @@ void audit_getname(const char *name)
BUG_ON(context->name_count >= AUDIT_NAMES);
context->names[context->name_count].name = name;
context->names[context->name_count].ino = (unsigned long)-1;
- context->names[context->name_count].rdev = -1;
++context->name_count;
}
@@ -855,11 +915,10 @@ void audit_putname(const char *name)
}
#endif
}
-EXPORT_SYMBOL(audit_putname);
/* Store the inode and device from a lookup. Called from
* fs/namei.c:path_lookup(). */
-void audit_inode(const char *name, unsigned long ino, dev_t rdev)
+void audit_inode(const char *name, const struct inode *inode)
{
int idx;
struct audit_context *context = current->audit_context;
@@ -885,8 +944,12 @@ void audit_inode(const char *name, unsigned long ino, dev_t rdev)
++context->ino_count;
#endif
}
- context->names[idx].ino = ino;
- context->names[idx].rdev = rdev;
+ context->names[idx].ino = inode->i_ino;
+ context->names[idx].dev = inode->i_sb->s_dev;
+ context->names[idx].mode = inode->i_mode;
+ context->names[idx].uid = inode->i_uid;
+ context->names[idx].gid = inode->i_gid;
+ context->names[idx].rdev = inode->i_rdev;
}
void audit_get_stamp(struct audit_context *ctx,
@@ -927,3 +990,26 @@ uid_t audit_get_loginuid(struct audit_context *ctx)
{
return ctx ? ctx->loginuid : -1;
}
+
+int audit_ipc_perms(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode)
+{
+ struct audit_aux_data_ipcctl *ax;
+ struct audit_context *context = current->audit_context;
+
+ if (likely(!context))
+ return 0;
+
+ ax = kmalloc(sizeof(*ax), GFP_KERNEL);
+ if (!ax)
+ return -ENOMEM;
+
+ ax->qbytes = qbytes;
+ ax->uid = uid;
+ ax->gid = gid;
+ ax->mode = mode;
+
+ ax->d.type = AUDIT_AUX_IPCPERM;
+ ax->d.next = context->aux;
+ context->aux = (void *)ax;
+ return 0;
+}
diff --git a/kernel/capability.c b/kernel/capability.c
index b828d545a97b7..64db1ee820c2d 100644
--- a/kernel/capability.c
+++ b/kernel/capability.c
@@ -20,10 +20,10 @@ EXPORT_SYMBOL(securebits);
EXPORT_SYMBOL(cap_bset);
/*
- * This global lock protects task->cap_* for all tasks including current.
+ * This lock protects task->cap_* for all tasks including current.
* Locking rule: acquire this prior to tasklist_lock.
*/
-DEFINE_SPINLOCK(task_capability_lock);
+static DEFINE_SPINLOCK(task_capability_lock);
/*
* For sys_getproccap() and sys_setproccap(), any of the three
diff --git a/kernel/compat.c b/kernel/compat.c
index f14fbde52bb39..dad10656bf144 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -23,17 +23,18 @@
#include <linux/security.h>
#include <asm/uaccess.h>
+#include <asm/bug.h>
int get_compat_timespec(struct timespec *ts, const struct compat_timespec __user *cts)
{
- return (verify_area(VERIFY_READ, cts, sizeof(*cts)) ||
+ return (!access_ok(VERIFY_READ, cts, sizeof(*cts)) ||
__get_user(ts->tv_sec, &cts->tv_sec) ||
__get_user(ts->tv_nsec, &cts->tv_nsec)) ? -EFAULT : 0;
}
int put_compat_timespec(const struct timespec *ts, struct compat_timespec __user *cts)
{
- return (verify_area(VERIFY_WRITE, cts, sizeof(*cts)) ||
+ return (!access_ok(VERIFY_WRITE, cts, sizeof(*cts)) ||
__put_user(ts->tv_sec, &cts->tv_sec) ||
__put_user(ts->tv_nsec, &cts->tv_nsec)) ? -EFAULT : 0;
}
@@ -413,6 +414,36 @@ compat_sys_wait4(compat_pid_t pid, compat_uint_t __user *stat_addr, int options,
}
}
+asmlinkage long compat_sys_waitid(int which, compat_pid_t pid,
+ struct compat_siginfo __user *uinfo, int options,
+ struct compat_rusage __user *uru)
+{
+ siginfo_t info;
+ struct rusage ru;
+ long ret;
+ mm_segment_t old_fs = get_fs();
+
+ memset(&info, 0, sizeof(info));
+
+ set_fs(KERNEL_DS);
+ ret = sys_waitid(which, pid, (siginfo_t __user *)&info, options,
+ uru ? (struct rusage __user *)&ru : NULL);
+ set_fs(old_fs);
+
+ if ((ret < 0) || (info.si_signo == 0))
+ return ret;
+
+ if (uru) {
+ ret = put_compat_rusage(&ru, uru);
+ if (ret)
+ return ret;
+ }
+
+ BUG_ON(info.si_code & __SI_MASK);
+ info.si_code |= __SI_CHLD;
+ return copy_siginfo_to_user32(uinfo, &info);
+}
+
static int compat_get_user_cpu_mask(compat_ulong_t __user *user_mask_ptr,
unsigned len, cpumask_t *new_mask)
{
@@ -599,6 +630,27 @@ long compat_sys_clock_nanosleep(clockid_t which_clock, int flags,
return err;
}
+/*
+ * We currently only need the following fields from the sigevent
+ * structure: sigev_value, sigev_signo, sig_notify and (sometimes
+ * sigev_notify_thread_id). The others are handled in user mode.
+ * We also assume that copying sigev_value.sival_int is sufficient
+ * to keep all the bits of sigev_value.sival_ptr intact.
+ */
+int get_compat_sigevent(struct sigevent *event,
+ const struct compat_sigevent __user *u_event)
+{
+ memset(&event, 0, sizeof(*event));
+ return (!access_ok(VERIFY_READ, u_event, sizeof(*u_event)) ||
+ __get_user(event->sigev_value.sival_int,
+ &u_event->sigev_value.sival_int) ||
+ __get_user(event->sigev_signo, &u_event->sigev_signo) ||
+ __get_user(event->sigev_notify, &u_event->sigev_notify) ||
+ __get_user(event->sigev_notify_thread_id,
+ &u_event->sigev_notify_thread_id))
+ ? -EFAULT : 0;
+}
+
/* timer_create is architecture specific because it needs sigevent conversion */
long compat_get_bitmap(unsigned long *mask, compat_ulong_t __user *umask,
@@ -612,7 +664,7 @@ long compat_get_bitmap(unsigned long *mask, compat_ulong_t __user *umask,
/* align bitmap up to nearest compat_long_t boundary */
bitmap_size = ALIGN(bitmap_size, BITS_PER_COMPAT_LONG);
- if (verify_area(VERIFY_READ, umask, bitmap_size / 8))
+ if (!access_ok(VERIFY_READ, umask, bitmap_size / 8))
return -EFAULT;
nr_compat_longs = BITS_TO_COMPAT_LONGS(bitmap_size);
@@ -653,7 +705,7 @@ long compat_put_bitmap(compat_ulong_t __user *umask, unsigned long *mask,
/* align bitmap up to nearest compat_long_t boundary */
bitmap_size = ALIGN(bitmap_size, BITS_PER_COMPAT_LONG);
- if (verify_area(VERIFY_WRITE, umask, bitmap_size / 8))
+ if (!access_ok(VERIFY_WRITE, umask, bitmap_size / 8))
return -EFAULT;
nr_compat_longs = BITS_TO_COMPAT_LONGS(bitmap_size);
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
new file mode 100644
index 0000000000000..a6584d9099d32
--- /dev/null
+++ b/kernel/cpuset.c
@@ -0,0 +1,1564 @@
+/*
+ * kernel/cpuset.c
+ *
+ * Processor and Memory placement constraints for sets of tasks.
+ *
+ * Copyright (C) 2003 BULL SA.
+ * Copyright (C) 2004 Silicon Graphics, Inc.
+ *
+ * Portions derived from Patrick Mochel's sysfs code.
+ * sysfs is Copyright (c) 2001-3 Patrick Mochel
+ * Portions Copyright (c) 2004 Silicon Graphics, Inc.
+ *
+ * 2003-10-10 Written by Simon Derr <simon.derr@bull.net>
+ * 2003-10-22 Updates by Stephen Hemminger.
+ * 2004 May-July Rework by Paul Jackson <pj@sgi.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 the Linux
+ * distribution for more details.
+ */
+
+#include <linux/config.h>
+#include <linux/cpu.h>
+#include <linux/cpumask.h>
+#include <linux/cpuset.h>
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/kmod.h>
+#include <linux/list.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/mount.h>
+#include <linux/namei.h>
+#include <linux/pagemap.h>
+#include <linux/proc_fs.h>
+#include <linux/sched.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+#include <linux/smp_lock.h>
+#include <linux/spinlock.h>
+#include <linux/stat.h>
+#include <linux/string.h>
+#include <linux/time.h>
+#include <linux/backing-dev.h>
+#include <linux/sort.h>
+
+#include <asm/uaccess.h>
+#include <asm/atomic.h>
+#include <asm/semaphore.h>
+
+#define CPUSET_SUPER_MAGIC 0x27e0eb
+
+struct cpuset {
+ unsigned long flags; /* "unsigned long" so bitops work */
+ cpumask_t cpus_allowed; /* CPUs allowed to tasks in cpuset */
+ nodemask_t mems_allowed; /* Memory Nodes allowed to tasks */
+
+ atomic_t count; /* count tasks using this cpuset */
+
+ /*
+ * We link our 'sibling' struct into our parents 'children'.
+ * Our children link their 'sibling' into our 'children'.
+ */
+ struct list_head sibling; /* my parents children */
+ struct list_head children; /* my children */
+
+ struct cpuset *parent; /* my parent */
+ struct dentry *dentry; /* cpuset fs entry */
+
+ /*
+ * Copy of global cpuset_mems_generation as of the most
+ * recent time this cpuset changed its mems_allowed.
+ */
+ int mems_generation;
+};
+
+/* bits in struct cpuset flags field */
+typedef enum {
+ CS_CPU_EXCLUSIVE,
+ CS_MEM_EXCLUSIVE,
+ CS_REMOVED,
+ CS_NOTIFY_ON_RELEASE
+} cpuset_flagbits_t;
+
+/* convenient tests for these bits */
+static inline int is_cpu_exclusive(const struct cpuset *cs)
+{
+ return !!test_bit(CS_CPU_EXCLUSIVE, &cs->flags);
+}
+
+static inline int is_mem_exclusive(const struct cpuset *cs)
+{
+ return !!test_bit(CS_MEM_EXCLUSIVE, &cs->flags);
+}
+
+static inline int is_removed(const struct cpuset *cs)
+{
+ return !!test_bit(CS_REMOVED, &cs->flags);
+}
+
+static inline int notify_on_release(const struct cpuset *cs)
+{
+ return !!test_bit(CS_NOTIFY_ON_RELEASE, &cs->flags);
+}
+
+/*
+ * Increment this atomic integer everytime any cpuset changes its
+ * mems_allowed value. Users of cpusets can track this generation
+ * number, and avoid having to lock and reload mems_allowed unless
+ * the cpuset they're using changes generation.
+ *
+ * A single, global generation is needed because attach_task() could
+ * reattach a task to a different cpuset, which must not have its
+ * generation numbers aliased with those of that tasks previous cpuset.
+ *
+ * Generations are needed for mems_allowed because one task cannot
+ * modify anothers memory placement. So we must enable every task,
+ * on every visit to __alloc_pages(), to efficiently check whether
+ * its current->cpuset->mems_allowed has changed, requiring an update
+ * of its current->mems_allowed.
+ */
+static atomic_t cpuset_mems_generation = ATOMIC_INIT(1);
+
+static struct cpuset top_cpuset = {
+ .flags = ((1 << CS_CPU_EXCLUSIVE) | (1 << CS_MEM_EXCLUSIVE)),
+ .cpus_allowed = CPU_MASK_ALL,
+ .mems_allowed = NODE_MASK_ALL,
+ .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;
+
+/*
+ * cpuset_sem should be held by anyone who is depending on the children
+ * or sibling lists of any cpuset, or performing non-atomic operations
+ * on the flags or *_allowed values of a cpuset, such as raising the
+ * CS_REMOVED flag bit iff it is not already raised, or reading and
+ * conditionally modifying the *_allowed values. One kernel global
+ * cpuset semaphore should be sufficient - these things don't change
+ * that much.
+ *
+ * The code that modifies cpusets holds cpuset_sem across the entire
+ * operation, from cpuset_common_file_write() down, single threading
+ * all cpuset modifications (except for counter manipulations from
+ * fork and exit) across the system. This presumes that cpuset
+ * modifications are rare - better kept simple and safe, even if slow.
+ *
+ * The code that reads cpusets, such as in cpuset_common_file_read()
+ * and below, only holds cpuset_sem across small pieces of code, such
+ * as when reading out possibly multi-word cpumasks and nodemasks, as
+ * the risks are less, and the desire for performance a little greater.
+ * The proc_cpuset_show() routine needs to hold cpuset_sem to insure
+ * that no cs->dentry is NULL, as it walks up the cpuset tree to root.
+ *
+ * The hooks from fork and exit, cpuset_fork() and cpuset_exit(), don't
+ * (usually) grab cpuset_sem. These are the two most performance
+ * critical pieces of code here. The exception occurs on exit(),
+ * if the last task using a cpuset exits, and the cpuset was marked
+ * notify_on_release. In that case, the cpuset_sem is taken, the
+ * path to the released cpuset calculated, and a usermode call made
+ * to /sbin/cpuset_release_agent with the name of the cpuset (path
+ * relative to the root of cpuset file system) as the argument.
+ *
+ * A cpuset can only be deleted if both its 'count' of using tasks is
+ * zero, and its list of 'children' cpusets is empty. Since all tasks
+ * in the system use _some_ cpuset, and since there is always at least
+ * one task in the system (init, pid == 1), therefore, top_cpuset
+ * always has either children cpusets and/or using tasks. So no need
+ * for any special hack to ensure that top_cpuset cannot be deleted.
+ */
+
+static DECLARE_MUTEX(cpuset_sem);
+
+/*
+ * A couple of forward declarations required, due to cyclic reference loop:
+ * cpuset_mkdir -> cpuset_create -> cpuset_populate_dir -> cpuset_add_file
+ * -> cpuset_create_file -> cpuset_dir_inode_operations -> cpuset_mkdir.
+ */
+
+static int cpuset_mkdir(struct inode *dir, struct dentry *dentry, int mode);
+static int cpuset_rmdir(struct inode *unused_dir, struct dentry *dentry);
+
+static struct backing_dev_info cpuset_backing_dev_info = {
+ .ra_pages = 0, /* No readahead */
+ .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK,
+};
+
+static struct inode *cpuset_new_inode(mode_t mode)
+{
+ struct inode *inode = new_inode(cpuset_sb);
+
+ if (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_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+ inode->i_mapping->backing_dev_info = &cpuset_backing_dev_info;
+ }
+ return inode;
+}
+
+static void cpuset_diput(struct dentry *dentry, struct inode *inode)
+{
+ /* is dentry a directory ? if so, kfree() associated cpuset */
+ if (S_ISDIR(inode->i_mode)) {
+ struct cpuset *cs = dentry->d_fsdata;
+ BUG_ON(!(is_removed(cs)));
+ kfree(cs);
+ }
+ iput(inode);
+}
+
+static struct dentry_operations cpuset_dops = {
+ .d_iput = cpuset_diput,
+};
+
+static struct dentry *cpuset_get_dentry(struct dentry *parent, const char *name)
+{
+ struct qstr qstr;
+ struct dentry *d;
+
+ qstr.name = name;
+ qstr.len = strlen(name);
+ qstr.hash = full_name_hash(name, qstr.len);
+ d = lookup_hash(&qstr, parent);
+ if (!IS_ERR(d))
+ d->d_op = &cpuset_dops;
+ return d;
+}
+
+static void remove_dir(struct dentry *d)
+{
+ struct dentry *parent = dget(d->d_parent);
+
+ d_delete(d);
+ simple_rmdir(parent->d_inode, d);
+ dput(parent);
+}
+
+/*
+ * NOTE : the dentry must have been dget()'ed
+ */
+static void cpuset_d_remove_dir(struct dentry *dentry)
+{
+ struct list_head *node;
+
+ spin_lock(&dcache_lock);
+ node = dentry->d_subdirs.next;
+ while (node != &dentry->d_subdirs) {
+ struct dentry *d = list_entry(node, struct dentry, d_child);
+ list_del_init(node);
+ if (d->d_inode) {
+ d = dget_locked(d);
+ spin_unlock(&dcache_lock);
+ d_delete(d);
+ simple_unlink(dentry->d_inode, d);
+ dput(d);
+ spin_lock(&dcache_lock);
+ }
+ node = dentry->d_subdirs.next;
+ }
+ list_del_init(&dentry->d_child);
+ spin_unlock(&dcache_lock);
+ remove_dir(dentry);
+}
+
+static struct super_operations cpuset_ops = {
+ .statfs = simple_statfs,
+ .drop_inode = generic_delete_inode,
+};
+
+static int cpuset_fill_super(struct super_block *sb, void *unused_data,
+ int unused_silent)
+{
+ struct inode *inode;
+ struct dentry *root;
+
+ sb->s_blocksize = PAGE_CACHE_SIZE;
+ sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
+ sb->s_magic = CPUSET_SUPER_MAGIC;
+ sb->s_op = &cpuset_ops;
+ cpuset_sb = sb;
+
+ inode = cpuset_new_inode(S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR);
+ if (inode) {
+ inode->i_op = &simple_dir_inode_operations;
+ inode->i_fop = &simple_dir_operations;
+ /* directories start off with i_nlink == 2 (for "." entry) */
+ inode->i_nlink++;
+ } else {
+ return -ENOMEM;
+ }
+
+ root = d_alloc_root(inode);
+ if (!root) {
+ iput(inode);
+ return -ENOMEM;
+ }
+ sb->s_root = root;
+ return 0;
+}
+
+static struct super_block *cpuset_get_sb(struct file_system_type *fs_type,
+ int flags, const char *unused_dev_name,
+ void *data)
+{
+ return get_sb_single(fs_type, flags, data, cpuset_fill_super);
+}
+
+static struct file_system_type cpuset_fs_type = {
+ .name = "cpuset",
+ .get_sb = cpuset_get_sb,
+ .kill_sb = kill_litter_super,
+};
+
+/* struct cftype:
+ *
+ * The files in the cpuset filesystem mostly have a very simple read/write
+ * handling, some common function will take care of it. Nevertheless some cases
+ * (read tasks) are special and therefore I define this structure for every
+ * kind of file.
+ *
+ *
+ * When reading/writing to a file:
+ * - the cpuset to use in file->f_dentry->d_parent->d_fsdata
+ * - the 'cftype' of the file is file->f_dentry->d_fsdata
+ */
+
+struct cftype {
+ char *name;
+ int private;
+ int (*open) (struct inode *inode, struct file *file);
+ ssize_t (*read) (struct file *file, char __user *buf, size_t nbytes,
+ loff_t *ppos);
+ int (*write) (struct file *file, const char *buf, size_t nbytes,
+ loff_t *ppos);
+ int (*release) (struct inode *inode, struct file *file);
+};
+
+static inline struct cpuset *__d_cs(struct dentry *dentry)
+{
+ return dentry->d_fsdata;
+}
+
+static inline struct cftype *__d_cft(struct dentry *dentry)
+{
+ return dentry->d_fsdata;
+}
+
+/*
+ * Call with cpuset_sem held. Writes path of cpuset into buf.
+ * Returns 0 on success, -errno on error.
+ */
+
+static int cpuset_path(const struct cpuset *cs, char *buf, int buflen)
+{
+ char *start;
+
+ start = buf + buflen;
+
+ *--start = '\0';
+ for (;;) {
+ int len = cs->dentry->d_name.len;
+ if ((start -= len) < buf)
+ return -ENAMETOOLONG;
+ memcpy(start, cs->dentry->d_name.name, len);
+ cs = cs->parent;
+ if (!cs)
+ break;
+ if (!cs->parent)
+ continue;
+ if (--start < buf)
+ return -ENAMETOOLONG;
+ *start = '/';
+ }
+ memmove(buf, start, buf + buflen - start);
+ return 0;
+}
+
+/*
+ * Notify userspace when a cpuset is released, by running
+ * /sbin/cpuset_release_agent with the name of the cpuset (path
+ * relative to the root of cpuset file system) as the argument.
+ *
+ * Most likely, this user command will try to rmdir this cpuset.
+ *
+ * This races with the possibility that some other task will be
+ * attached to this cpuset before it is removed, or that some other
+ * user task will 'mkdir' a child cpuset of this cpuset. That's ok.
+ * The presumed 'rmdir' will fail quietly if this cpuset is no longer
+ * unused, and this cpuset will be reprieved from its death sentence,
+ * to continue to serve a useful existence. Next time it's released,
+ * we will get notified again, if it still has 'notify_on_release' set.
+ *
+ * Note final arg to call_usermodehelper() is 0 - that means
+ * don't wait. Since we are holding the global cpuset_sem here,
+ * and we are asking another thread (started from keventd) to rmdir a
+ * cpuset, we can't wait - or we'd deadlock with the removing thread
+ * on cpuset_sem.
+ */
+
+static int cpuset_release_agent(char *cpuset_str)
+{
+ char *argv[3], *envp[3];
+ int i;
+
+ i = 0;
+ argv[i++] = "/sbin/cpuset_release_agent";
+ argv[i++] = cpuset_str;
+ argv[i] = NULL;
+
+ i = 0;
+ /* minimal command environment */
+ envp[i++] = "HOME=/";
+ envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
+ envp[i] = NULL;
+
+ return call_usermodehelper(argv[0], argv, envp, 0);
+}
+
+/*
+ * Either cs->count of using tasks transitioned to zero, or the
+ * cs->children list of child cpusets just became empty. If this
+ * cs is notify_on_release() and now both the user count is zero and
+ * the list of children is empty, send notice to user land.
+ */
+
+static void check_for_release(struct cpuset *cs)
+{
+ if (notify_on_release(cs) && atomic_read(&cs->count) == 0 &&
+ list_empty(&cs->children)) {
+ char *buf;
+
+ buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+ if (!buf)
+ return;
+ if (cpuset_path(cs, buf, PAGE_SIZE) < 0)
+ goto out;
+ cpuset_release_agent(buf);
+out:
+ kfree(buf);
+ }
+}
+
+/*
+ * Return in *pmask the portion of a cpusets's cpus_allowed that
+ * are online. If none are online, walk up the cpuset hierarchy
+ * until we find one that does have some online cpus. If we get
+ * all the way to the top and still haven't found any online cpus,
+ * return cpu_online_map. Or if passed a NULL cs from an exit'ing
+ * task, return cpu_online_map.
+ *
+ * One way or another, we guarantee to return some non-empty subset
+ * of cpu_online_map.
+ *
+ * Call with cpuset_sem held.
+ */
+
+static void guarantee_online_cpus(const struct cpuset *cs, cpumask_t *pmask)
+{
+ while (cs && !cpus_intersects(cs->cpus_allowed, cpu_online_map))
+ cs = cs->parent;
+ if (cs)
+ cpus_and(*pmask, cs->cpus_allowed, cpu_online_map);
+ else
+ *pmask = cpu_online_map;
+ BUG_ON(!cpus_intersects(*pmask, cpu_online_map));
+}
+
+/*
+ * Return in *pmask the portion of a cpusets's mems_allowed that
+ * are online. If none are online, walk up the cpuset hierarchy
+ * until we find one that does have some online mems. If we get
+ * all the way to the top and still haven't found any online mems,
+ * return node_online_map.
+ *
+ * One way or another, we guarantee to return some non-empty subset
+ * of node_online_map.
+ *
+ * Call with cpuset_sem held.
+ */
+
+static void guarantee_online_mems(const struct cpuset *cs, nodemask_t *pmask)
+{
+ while (cs && !nodes_intersects(cs->mems_allowed, node_online_map))
+ cs = cs->parent;
+ if (cs)
+ nodes_and(*pmask, cs->mems_allowed, node_online_map);
+ else
+ *pmask = node_online_map;
+ BUG_ON(!nodes_intersects(*pmask, node_online_map));
+}
+
+/*
+ * Refresh current tasks mems_allowed and mems_generation from
+ * current tasks cpuset. Call with cpuset_sem held.
+ *
+ * Be sure to call refresh_mems() on any cpuset operation which
+ * (1) holds cpuset_sem, and (2) might possibly alloc memory.
+ * Call after obtaining cpuset_sem lock, before any possible
+ * allocation. Otherwise one risks trying to allocate memory
+ * while the task cpuset_mems_generation is not the same as
+ * the mems_generation in its cpuset, which would deadlock on
+ * cpuset_sem in cpuset_update_current_mems_allowed().
+ *
+ * Since we hold cpuset_sem, once refresh_mems() is called, the
+ * test (current->cpuset_mems_generation != cs->mems_generation)
+ * in cpuset_update_current_mems_allowed() will remain false,
+ * until we drop cpuset_sem. Anyone else who would change our
+ * cpusets mems_generation needs to lock cpuset_sem first.
+ */
+
+static void refresh_mems(void)
+{
+ struct cpuset *cs = current->cpuset;
+
+ if (current->cpuset_mems_generation != cs->mems_generation) {
+ guarantee_online_mems(cs, &current->mems_allowed);
+ current->cpuset_mems_generation = cs->mems_generation;
+ }
+}
+
+/*
+ * is_cpuset_subset(p, q) - Is cpuset p a subset of cpuset q?
+ *
+ * One cpuset is a subset of another if all its allowed CPUs and
+ * Memory Nodes are a subset of the other, and its exclusive flags
+ * are only set if the other's are set.
+ */
+
+static int is_cpuset_subset(const struct cpuset *p, const struct cpuset *q)
+{
+ return cpus_subset(p->cpus_allowed, q->cpus_allowed) &&
+ nodes_subset(p->mems_allowed, q->mems_allowed) &&
+ is_cpu_exclusive(p) <= is_cpu_exclusive(q) &&
+ is_mem_exclusive(p) <= is_mem_exclusive(q);
+}
+
+/*
+ * validate_change() - Used to validate that any proposed cpuset change
+ * follows the structural rules for cpusets.
+ *
+ * If we replaced the flag and mask values of the current cpuset
+ * (cur) with those values in the trial cpuset (trial), would
+ * our various subset and exclusive rules still be valid? Presumes
+ * cpuset_sem held.
+ *
+ * 'cur' is the address of an actual, in-use cpuset. Operations
+ * such as list traversal that depend on the actual address of the
+ * cpuset in the list must use cur below, not trial.
+ *
+ * 'trial' is the address of bulk structure copy of cur, with
+ * perhaps one or more of the fields cpus_allowed, mems_allowed,
+ * or flags changed to new, trial values.
+ *
+ * Return 0 if valid, -errno if not.
+ */
+
+static int validate_change(const struct cpuset *cur, const struct cpuset *trial)
+{
+ struct cpuset *c, *par;
+
+ /* Each of our child cpusets must be a subset of us */
+ list_for_each_entry(c, &cur->children, sibling) {
+ if (!is_cpuset_subset(c, trial))
+ return -EBUSY;
+ }
+
+ /* Remaining checks don't apply to root cpuset */
+ if ((par = cur->parent) == NULL)
+ return 0;
+
+ /* We must be a subset of our parent cpuset */
+ if (!is_cpuset_subset(trial, par))
+ return -EACCES;
+
+ /* If either I or some sibling (!= me) is exclusive, we can't overlap */
+ list_for_each_entry(c, &par->children, sibling) {
+ if ((is_cpu_exclusive(trial) || is_cpu_exclusive(c)) &&
+ c != cur &&
+ cpus_intersects(trial->cpus_allowed, c->cpus_allowed))
+ return -EINVAL;
+ if ((is_mem_exclusive(trial) || is_mem_exclusive(c)) &&
+ c != cur &&
+ nodes_intersects(trial->mems_allowed, c->mems_allowed))
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int update_cpumask(struct cpuset *cs, char *buf)
+{
+ struct cpuset trialcs;
+ int retval;
+
+ trialcs = *cs;
+ retval = cpulist_parse(buf, trialcs.cpus_allowed);
+ if (retval < 0)
+ return retval;
+ cpus_and(trialcs.cpus_allowed, trialcs.cpus_allowed, cpu_online_map);
+ if (cpus_empty(trialcs.cpus_allowed))
+ return -ENOSPC;
+ retval = validate_change(cs, &trialcs);
+ if (retval == 0)
+ cs->cpus_allowed = trialcs.cpus_allowed;
+ return retval;
+}
+
+static int update_nodemask(struct cpuset *cs, char *buf)
+{
+ struct cpuset trialcs;
+ int retval;
+
+ trialcs = *cs;
+ retval = nodelist_parse(buf, trialcs.mems_allowed);
+ if (retval < 0)
+ return retval;
+ nodes_and(trialcs.mems_allowed, trialcs.mems_allowed, node_online_map);
+ if (nodes_empty(trialcs.mems_allowed))
+ return -ENOSPC;
+ retval = validate_change(cs, &trialcs);
+ if (retval == 0) {
+ cs->mems_allowed = trialcs.mems_allowed;
+ atomic_inc(&cpuset_mems_generation);
+ cs->mems_generation = atomic_read(&cpuset_mems_generation);
+ }
+ return retval;
+}
+
+/*
+ * 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: the cpuset to update
+ * buf: the buffer where we read the 0 or 1
+ */
+
+static int update_flag(cpuset_flagbits_t bit, struct cpuset *cs, char *buf)
+{
+ int turning_on;
+ struct cpuset trialcs;
+ int err;
+
+ turning_on = (simple_strtoul(buf, NULL, 10) != 0);
+
+ trialcs = *cs;
+ if (turning_on)
+ set_bit(bit, &trialcs.flags);
+ else
+ clear_bit(bit, &trialcs.flags);
+
+ err = validate_change(cs, &trialcs);
+ if (err == 0) {
+ if (turning_on)
+ set_bit(bit, &cs->flags);
+ else
+ clear_bit(bit, &cs->flags);
+ }
+ return err;
+}
+
+static int attach_task(struct cpuset *cs, char *buf)
+{
+ pid_t pid;
+ struct task_struct *tsk;
+ struct cpuset *oldcs;
+ cpumask_t cpus;
+
+ if (sscanf(buf, "%d", &pid) != 1)
+ return -EIO;
+ if (cpus_empty(cs->cpus_allowed) || nodes_empty(cs->mems_allowed))
+ return -ENOSPC;
+
+ if (pid) {
+ read_lock(&tasklist_lock);
+
+ tsk = find_task_by_pid(pid);
+ if (!tsk) {
+ read_unlock(&tasklist_lock);
+ return -ESRCH;
+ }
+
+ get_task_struct(tsk);
+ read_unlock(&tasklist_lock);
+
+ if ((current->euid) && (current->euid != tsk->uid)
+ && (current->euid != tsk->suid)) {
+ put_task_struct(tsk);
+ return -EACCES;
+ }
+ } else {
+ tsk = current;
+ get_task_struct(tsk);
+ }
+
+ task_lock(tsk);
+ oldcs = tsk->cpuset;
+ if (!oldcs) {
+ task_unlock(tsk);
+ put_task_struct(tsk);
+ return -ESRCH;
+ }
+ atomic_inc(&cs->count);
+ tsk->cpuset = cs;
+ task_unlock(tsk);
+
+ guarantee_online_cpus(cs, &cpus);
+ set_cpus_allowed(tsk, cpus);
+
+ put_task_struct(tsk);
+ if (atomic_dec_and_test(&oldcs->count))
+ check_for_release(oldcs);
+ return 0;
+}
+
+/* The various types of files and directories in a cpuset file system */
+
+typedef enum {
+ FILE_ROOT,
+ FILE_DIR,
+ FILE_CPULIST,
+ FILE_MEMLIST,
+ FILE_CPU_EXCLUSIVE,
+ FILE_MEM_EXCLUSIVE,
+ FILE_NOTIFY_ON_RELEASE,
+ FILE_TASKLIST,
+} cpuset_filetype_t;
+
+static ssize_t cpuset_common_file_write(struct file *file, const char *userbuf,
+ size_t nbytes, loff_t *unused_ppos)
+{
+ struct cpuset *cs = __d_cs(file->f_dentry->d_parent);
+ struct cftype *cft = __d_cft(file->f_dentry);
+ cpuset_filetype_t type = cft->private;
+ char *buffer;
+ int retval = 0;
+
+ /* Crude upper limit on largest legitimate cpulist user might write. */
+ if (nbytes > 100 + 6 * NR_CPUS)
+ return -E2BIG;
+
+ /* +1 for nul-terminator */
+ if ((buffer = kmalloc(nbytes + 1, GFP_KERNEL)) == 0)
+ return -ENOMEM;
+
+ if (copy_from_user(buffer, userbuf, nbytes)) {
+ retval = -EFAULT;
+ goto out1;
+ }
+ buffer[nbytes] = 0; /* nul-terminate */
+
+ down(&cpuset_sem);
+
+ if (is_removed(cs)) {
+ retval = -ENODEV;
+ goto out2;
+ }
+
+ switch (type) {
+ case FILE_CPULIST:
+ retval = update_cpumask(cs, buffer);
+ break;
+ case FILE_MEMLIST:
+ retval = update_nodemask(cs, buffer);
+ break;
+ case FILE_CPU_EXCLUSIVE:
+ retval = update_flag(CS_CPU_EXCLUSIVE, cs, buffer);
+ break;
+ case FILE_MEM_EXCLUSIVE:
+ retval = update_flag(CS_MEM_EXCLUSIVE, cs, buffer);
+ break;
+ case FILE_NOTIFY_ON_RELEASE:
+ retval = update_flag(CS_NOTIFY_ON_RELEASE, cs, buffer);
+ break;
+ case FILE_TASKLIST:
+ retval = attach_task(cs, buffer);
+ break;
+ default:
+ retval = -EINVAL;
+ goto out2;
+ }
+
+ if (retval == 0)
+ retval = nbytes;
+out2:
+ up(&cpuset_sem);
+out1:
+ kfree(buffer);
+ return retval;
+}
+
+static ssize_t cpuset_file_write(struct file *file, const char *buf,
+ size_t nbytes, loff_t *ppos)
+{
+ ssize_t retval = 0;
+ struct cftype *cft = __d_cft(file->f_dentry);
+ if (!cft)
+ return -ENODEV;
+
+ /* special function ? */
+ if (cft->write)
+ retval = cft->write(file, buf, nbytes, ppos);
+ else
+ retval = cpuset_common_file_write(file, buf, nbytes, ppos);
+
+ return retval;
+}
+
+/*
+ * These ascii lists should be read in a single call, by using a user
+ * buffer large enough to hold the entire map. If read in smaller
+ * chunks, there is no guarantee of atomicity. Since the display format
+ * used, list of ranges of sequential numbers, is variable length,
+ * and since these maps can change value dynamically, one could read
+ * gibberish by doing partial reads while a list was changing.
+ * A single large read to a buffer that crosses a page boundary is
+ * ok, because the result being copied to user land is not recomputed
+ * across a page fault.
+ */
+
+static int cpuset_sprintf_cpulist(char *page, struct cpuset *cs)
+{
+ cpumask_t mask;
+
+ down(&cpuset_sem);
+ mask = cs->cpus_allowed;
+ up(&cpuset_sem);
+
+ return cpulist_scnprintf(page, PAGE_SIZE, mask);
+}
+
+static int cpuset_sprintf_memlist(char *page, struct cpuset *cs)
+{
+ nodemask_t mask;
+
+ down(&cpuset_sem);
+ mask = cs->mems_allowed;
+ up(&cpuset_sem);
+
+ return nodelist_scnprintf(page, PAGE_SIZE, mask);
+}
+
+static ssize_t cpuset_common_file_read(struct file *file, char __user *buf,
+ size_t nbytes, loff_t *ppos)
+{
+ struct cftype *cft = __d_cft(file->f_dentry);
+ struct cpuset *cs = __d_cs(file->f_dentry->d_parent);
+ cpuset_filetype_t type = cft->private;
+ char *page;
+ ssize_t retval = 0;
+ char *s;
+ char *start;
+ size_t n;
+
+ if (!(page = (char *)__get_free_page(GFP_KERNEL)))
+ return -ENOMEM;
+
+ s = page;
+
+ switch (type) {
+ case FILE_CPULIST:
+ s += cpuset_sprintf_cpulist(s, cs);
+ break;
+ case FILE_MEMLIST:
+ s += cpuset_sprintf_memlist(s, cs);
+ break;
+ case FILE_CPU_EXCLUSIVE:
+ *s++ = is_cpu_exclusive(cs) ? '1' : '0';
+ break;
+ case FILE_MEM_EXCLUSIVE:
+ *s++ = is_mem_exclusive(cs) ? '1' : '0';
+ break;
+ case FILE_NOTIFY_ON_RELEASE:
+ *s++ = notify_on_release(cs) ? '1' : '0';
+ break;
+ default:
+ retval = -EINVAL;
+ goto out;
+ }
+ *s++ = '\n';
+ *s = '\0';
+
+ start = page + *ppos;
+ n = s - start;
+ retval = n - copy_to_user(buf, start, min(n, nbytes));
+ *ppos += retval;
+out:
+ free_page((unsigned long)page);
+ return retval;
+}
+
+static ssize_t cpuset_file_read(struct file *file, char *buf, size_t nbytes,
+ loff_t *ppos)
+{
+ ssize_t retval = 0;
+ struct cftype *cft = __d_cft(file->f_dentry);
+ if (!cft)
+ return -ENODEV;
+
+ /* special function ? */
+ if (cft->read)
+ retval = cft->read(file, buf, nbytes, ppos);
+ else
+ retval = cpuset_common_file_read(file, buf, nbytes, ppos);
+
+ return retval;
+}
+
+static int cpuset_file_open(struct inode *inode, struct file *file)
+{
+ int err;
+ struct cftype *cft;
+
+ err = generic_file_open(inode, file);
+ if (err)
+ return err;
+
+ cft = __d_cft(file->f_dentry);
+ if (!cft)
+ return -ENODEV;
+ if (cft->open)
+ err = cft->open(inode, file);
+ else
+ err = 0;
+
+ return err;
+}
+
+static int cpuset_file_release(struct inode *inode, struct file *file)
+{
+ struct cftype *cft = __d_cft(file->f_dentry);
+ if (cft->release)
+ return cft->release(inode, file);
+ return 0;
+}
+
+static struct file_operations cpuset_file_operations = {
+ .read = cpuset_file_read,
+ .write = cpuset_file_write,
+ .llseek = generic_file_llseek,
+ .open = cpuset_file_open,
+ .release = cpuset_file_release,
+};
+
+static struct inode_operations cpuset_dir_inode_operations = {
+ .lookup = simple_lookup,
+ .mkdir = cpuset_mkdir,
+ .rmdir = cpuset_rmdir,
+};
+
+static int cpuset_create_file(struct dentry *dentry, int mode)
+{
+ struct inode *inode;
+
+ if (!dentry)
+ return -ENOENT;
+ if (dentry->d_inode)
+ return -EEXIST;
+
+ inode = cpuset_new_inode(mode);
+ if (!inode)
+ return -ENOMEM;
+
+ if (S_ISDIR(mode)) {
+ inode->i_op = &cpuset_dir_inode_operations;
+ inode->i_fop = &simple_dir_operations;
+
+ /* start off with i_nlink == 2 (for "." entry) */
+ inode->i_nlink++;
+ } else if (S_ISREG(mode)) {
+ inode->i_size = 0;
+ inode->i_fop = &cpuset_file_operations;
+ }
+
+ d_instantiate(dentry, inode);
+ dget(dentry); /* Extra count - pin the dentry in core */
+ return 0;
+}
+
+/*
+ * cpuset_create_dir - create a directory for an object.
+ * 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.
+ * mode: mode to set on new directory.
+ */
+
+static int cpuset_create_dir(struct cpuset *cs, const char *name, int mode)
+{
+ struct dentry *dentry = NULL;
+ struct dentry *parent;
+ int error = 0;
+
+ parent = cs->parent->dentry;
+ dentry = cpuset_get_dentry(parent, name);
+ if (IS_ERR(dentry))
+ return PTR_ERR(dentry);
+ error = cpuset_create_file(dentry, S_IFDIR | mode);
+ if (!error) {
+ dentry->d_fsdata = cs;
+ parent->d_inode->i_nlink++;
+ cs->dentry = dentry;
+ }
+ dput(dentry);
+
+ return error;
+}
+
+static int cpuset_add_file(struct dentry *dir, const struct cftype *cft)
+{
+ struct dentry *dentry;
+ int error;
+
+ down(&dir->d_inode->i_sem);
+ dentry = cpuset_get_dentry(dir, cft->name);
+ if (!IS_ERR(dentry)) {
+ error = cpuset_create_file(dentry, 0644 | S_IFREG);
+ if (!error)
+ dentry->d_fsdata = (void *)cft;
+ dput(dentry);
+ } else
+ error = PTR_ERR(dentry);
+ up(&dir->d_inode->i_sem);
+ return error;
+}
+
+/*
+ * Stuff for reading the 'tasks' file.
+ *
+ * Reading this file can return large amounts of data if a cpuset has
+ * *lots* of attached tasks. So it may need several calls to read(),
+ * but we cannot guarantee that the information we produce is correct
+ * unless we produce it entirely atomically.
+ *
+ * Upon tasks file open(), a struct ctr_struct is allocated, that
+ * will have a pointer to an array (also allocated here). The struct
+ * ctr_struct * is stored in file->private_data. Its resources will
+ * be freed by release() when the file is closed. The array is used
+ * to sprintf the PIDs and then used by read().
+ */
+
+/* cpusets_tasks_read array */
+
+struct ctr_struct {
+ char *buf;
+ int bufsz;
+};
+
+/*
+ * Load into 'pidarray' up to 'npids' of the tasks using cpuset 'cs'.
+ * Return actual number of pids loaded.
+ */
+static inline int pid_array_load(pid_t *pidarray, int npids, struct cpuset *cs)
+{
+ int n = 0;
+ struct task_struct *g, *p;
+
+ read_lock(&tasklist_lock);
+
+ do_each_thread(g, p) {
+ if (p->cpuset == cs) {
+ pidarray[n++] = p->pid;
+ if (unlikely(n == npids))
+ goto array_full;
+ }
+ } while_each_thread(g, p);
+
+array_full:
+ read_unlock(&tasklist_lock);
+ return n;
+}
+
+static int cmppid(const void *a, const void *b)
+{
+ return *(pid_t *)a - *(pid_t *)b;
+}
+
+/*
+ * Convert array 'a' of 'npids' pid_t's to a string of newline separated
+ * decimal pids in 'buf'. Don't write more than 'sz' chars, but return
+ * count 'cnt' of how many chars would be written if buf were large enough.
+ */
+static int pid_array_to_buf(char *buf, int sz, pid_t *a, int npids)
+{
+ int cnt = 0;
+ int i;
+
+ for (i = 0; i < npids; i++)
+ cnt += snprintf(buf + cnt, max(sz - cnt, 0), "%d\n", a[i]);
+ return cnt;
+}
+
+static int cpuset_tasks_open(struct inode *unused, struct file *file)
+{
+ struct cpuset *cs = __d_cs(file->f_dentry->d_parent);
+ struct ctr_struct *ctr;
+ pid_t *pidarray;
+ int npids;
+ char c;
+
+ if (!(file->f_mode & FMODE_READ))
+ return 0;
+
+ ctr = kmalloc(sizeof(*ctr), GFP_KERNEL);
+ if (!ctr)
+ goto err0;
+
+ /*
+ * If cpuset gets more users after we read count, we won't have
+ * enough space - tough. This race is indistinguishable to the
+ * caller from the case that the additional cpuset users didn't
+ * show up until sometime later on.
+ */
+ npids = atomic_read(&cs->count);
+ pidarray = kmalloc(npids * sizeof(pid_t), GFP_KERNEL);
+ if (!pidarray)
+ goto err1;
+
+ npids = pid_array_load(pidarray, npids, cs);
+ sort(pidarray, npids, sizeof(pid_t), cmppid, NULL);
+
+ /* Call pid_array_to_buf() twice, first just to get bufsz */
+ ctr->bufsz = pid_array_to_buf(&c, sizeof(c), pidarray, npids) + 1;
+ ctr->buf = kmalloc(ctr->bufsz, GFP_KERNEL);
+ if (!ctr->buf)
+ goto err2;
+ ctr->bufsz = pid_array_to_buf(ctr->buf, ctr->bufsz, pidarray, npids);
+
+ kfree(pidarray);
+ file->private_data = ctr;
+ return 0;
+
+err2:
+ kfree(pidarray);
+err1:
+ kfree(ctr);
+err0:
+ return -ENOMEM;
+}
+
+static ssize_t cpuset_tasks_read(struct file *file, char __user *buf,
+ size_t nbytes, loff_t *ppos)
+{
+ struct ctr_struct *ctr = file->private_data;
+
+ if (*ppos + nbytes > ctr->bufsz)
+ nbytes = ctr->bufsz - *ppos;
+ if (copy_to_user(buf, ctr->buf + *ppos, nbytes))
+ return -EFAULT;
+ *ppos += nbytes;
+ return nbytes;
+}
+
+static int cpuset_tasks_release(struct inode *unused_inode, struct file *file)
+{
+ struct ctr_struct *ctr;
+
+ if (file->f_mode & FMODE_READ) {
+ ctr = file->private_data;
+ kfree(ctr->buf);
+ kfree(ctr);
+ }
+ return 0;
+}
+
+/*
+ * for the common functions, 'private' gives the type of file
+ */
+
+static struct cftype cft_tasks = {
+ .name = "tasks",
+ .open = cpuset_tasks_open,
+ .read = cpuset_tasks_read,
+ .release = cpuset_tasks_release,
+ .private = FILE_TASKLIST,
+};
+
+static struct cftype cft_cpus = {
+ .name = "cpus",
+ .private = FILE_CPULIST,
+};
+
+static struct cftype cft_mems = {
+ .name = "mems",
+ .private = FILE_MEMLIST,
+};
+
+static struct cftype cft_cpu_exclusive = {
+ .name = "cpu_exclusive",
+ .private = FILE_CPU_EXCLUSIVE,
+};
+
+static struct cftype cft_mem_exclusive = {
+ .name = "mem_exclusive",
+ .private = FILE_MEM_EXCLUSIVE,
+};
+
+static struct cftype cft_notify_on_release = {
+ .name = "notify_on_release",
+ .private = FILE_NOTIFY_ON_RELEASE,
+};
+
+static int cpuset_populate_dir(struct dentry *cs_dentry)
+{
+ int err;
+
+ if ((err = cpuset_add_file(cs_dentry, &cft_cpus)) < 0)
+ return err;
+ if ((err = cpuset_add_file(cs_dentry, &cft_mems)) < 0)
+ return err;
+ if ((err = cpuset_add_file(cs_dentry, &cft_cpu_exclusive)) < 0)
+ return err;
+ if ((err = cpuset_add_file(cs_dentry, &cft_mem_exclusive)) < 0)
+ return err;
+ if ((err = cpuset_add_file(cs_dentry, &cft_notify_on_release)) < 0)
+ return err;
+ if ((err = cpuset_add_file(cs_dentry, &cft_tasks)) < 0)
+ return err;
+ return 0;
+}
+
+/*
+ * cpuset_create - create a cpuset
+ * parent: cpuset that will be parent of the new cpuset.
+ * name: name of the new cpuset. Will be strcpy'ed.
+ * mode: mode to set on new inode
+ *
+ * Must be called with the semaphore on the parent inode held
+ */
+
+static long cpuset_create(struct cpuset *parent, const char *name, int mode)
+{
+ struct cpuset *cs;
+ int err;
+
+ cs = kmalloc(sizeof(*cs), GFP_KERNEL);
+ if (!cs)
+ return -ENOMEM;
+
+ down(&cpuset_sem);
+ refresh_mems();
+ cs->flags = 0;
+ if (notify_on_release(parent))
+ set_bit(CS_NOTIFY_ON_RELEASE, &cs->flags);
+ cs->cpus_allowed = CPU_MASK_NONE;
+ cs->mems_allowed = NODE_MASK_NONE;
+ atomic_set(&cs->count, 0);
+ INIT_LIST_HEAD(&cs->sibling);
+ INIT_LIST_HEAD(&cs->children);
+ atomic_inc(&cpuset_mems_generation);
+ cs->mems_generation = atomic_read(&cpuset_mems_generation);
+
+ cs->parent = parent;
+
+ list_add(&cs->sibling, &cs->parent->children);
+
+ err = cpuset_create_dir(cs, name, mode);
+ if (err < 0)
+ goto err;
+
+ /*
+ * Release cpuset_sem before cpuset_populate_dir() because it
+ * will down() this new directory's i_sem and if we race with
+ * another mkdir, we might deadlock.
+ */
+ up(&cpuset_sem);
+
+ err = cpuset_populate_dir(cs->dentry);
+ /* If err < 0, we have a half-filled directory - oh well ;) */
+ return 0;
+err:
+ list_del(&cs->sibling);
+ up(&cpuset_sem);
+ kfree(cs);
+ return err;
+}
+
+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 */
+ return cpuset_create(c_parent, dentry->d_name.name, mode | S_IFDIR);
+}
+
+static int cpuset_rmdir(struct inode *unused_dir, struct dentry *dentry)
+{
+ struct cpuset *cs = dentry->d_fsdata;
+ struct dentry *d;
+ struct cpuset *parent;
+
+ /* the vfs holds both inode->i_sem already */
+
+ down(&cpuset_sem);
+ refresh_mems();
+ if (atomic_read(&cs->count) > 0) {
+ up(&cpuset_sem);
+ return -EBUSY;
+ }
+ if (!list_empty(&cs->children)) {
+ up(&cpuset_sem);
+ return -EBUSY;
+ }
+ spin_lock(&cs->dentry->d_lock);
+ parent = cs->parent;
+ set_bit(CS_REMOVED, &cs->flags);
+ list_del(&cs->sibling); /* delete my sibling from parent->children */
+ if (list_empty(&parent->children))
+ check_for_release(parent);
+ d = dget(cs->dentry);
+ cs->dentry = NULL;
+ spin_unlock(&d->d_lock);
+ cpuset_d_remove_dir(d);
+ dput(d);
+ up(&cpuset_sem);
+ return 0;
+}
+
+/**
+ * cpuset_init - initialize cpusets at system boot
+ *
+ * Description: Initialize top_cpuset and the cpuset internal file system,
+ **/
+
+int __init cpuset_init(void)
+{
+ struct dentry *root;
+ int err;
+
+ top_cpuset.cpus_allowed = CPU_MASK_ALL;
+ top_cpuset.mems_allowed = NODE_MASK_ALL;
+
+ atomic_inc(&cpuset_mems_generation);
+ top_cpuset.mems_generation = atomic_read(&cpuset_mems_generation);
+
+ init_task.cpuset = &top_cpuset;
+
+ err = register_filesystem(&cpuset_fs_type);
+ if (err < 0)
+ goto out;
+ cpuset_mount = kern_mount(&cpuset_fs_type);
+ if (IS_ERR(cpuset_mount)) {
+ printk(KERN_ERR "cpuset: could not mount!\n");
+ err = PTR_ERR(cpuset_mount);
+ cpuset_mount = NULL;
+ goto out;
+ }
+ root = cpuset_mount->mnt_sb->s_root;
+ root->d_fsdata = &top_cpuset;
+ root->d_inode->i_nlink++;
+ top_cpuset.dentry = root;
+ root->d_inode->i_op = &cpuset_dir_inode_operations;
+ err = cpuset_populate_dir(root);
+out:
+ return err;
+}
+
+/**
+ * cpuset_init_smp - initialize cpus_allowed
+ *
+ * Description: Finish top cpuset after cpu, node maps are initialized
+ **/
+
+void __init cpuset_init_smp(void)
+{
+ top_cpuset.cpus_allowed = cpu_online_map;
+ top_cpuset.mems_allowed = node_online_map;
+}
+
+/**
+ * cpuset_fork - attach newly forked task to its parents cpuset.
+ * @p: pointer to task_struct of forking parent process.
+ *
+ * Description: By default, on fork, a task inherits its
+ * parents cpuset. The pointer to the shared cpuset is
+ * automatically copied in fork.c by dup_task_struct().
+ * This cpuset_fork() routine need only increment the usage
+ * counter in that cpuset.
+ **/
+
+void cpuset_fork(struct task_struct *tsk)
+{
+ atomic_inc(&tsk->cpuset->count);
+}
+
+/**
+ * cpuset_exit - detach cpuset from exiting task
+ * @tsk: pointer to task_struct of exiting process
+ *
+ * Description: Detach cpuset from @tsk and release it.
+ *
+ **/
+
+void cpuset_exit(struct task_struct *tsk)
+{
+ struct cpuset *cs;
+
+ task_lock(tsk);
+ cs = tsk->cpuset;
+ tsk->cpuset = NULL;
+ task_unlock(tsk);
+
+ if (atomic_dec_and_test(&cs->count)) {
+ down(&cpuset_sem);
+ check_for_release(cs);
+ up(&cpuset_sem);
+ }
+}
+
+/**
+ * cpuset_cpus_allowed - return cpus_allowed mask from a tasks cpuset.
+ * @tsk: pointer to task_struct from which to obtain cpuset->cpus_allowed.
+ *
+ * Description: Returns the cpumask_t cpus_allowed of the cpuset
+ * attached to the specified @tsk. Guaranteed to return some non-empty
+ * subset of cpu_online_map, even if this means going outside the
+ * tasks cpuset.
+ **/
+
+const cpumask_t cpuset_cpus_allowed(const struct task_struct *tsk)
+{
+ cpumask_t mask;
+
+ down(&cpuset_sem);
+ task_lock((struct task_struct *)tsk);
+ guarantee_online_cpus(tsk->cpuset, &mask);
+ task_unlock((struct task_struct *)tsk);
+ up(&cpuset_sem);
+
+ return mask;
+}
+
+void cpuset_init_current_mems_allowed(void)
+{
+ current->mems_allowed = NODE_MASK_ALL;
+}
+
+/*
+ * 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().
+ */
+
+void cpuset_update_current_mems_allowed(void)
+{
+ struct cpuset *cs = current->cpuset;
+
+ if (!cs)
+ return; /* task is exiting */
+ if (current->cpuset_mems_generation != cs->mems_generation) {
+ down(&cpuset_sem);
+ refresh_mems();
+ up(&cpuset_sem);
+ }
+}
+
+void cpuset_restrict_to_mems_allowed(unsigned long *nodes)
+{
+ bitmap_and(nodes, nodes, nodes_addr(current->mems_allowed),
+ MAX_NUMNODES);
+}
+
+/*
+ * Are any of the nodes on zonelist zl allowed in current->mems_allowed?
+ */
+int cpuset_zonelist_valid_mems_allowed(struct zonelist *zl)
+{
+ int i;
+
+ for (i = 0; zl->zones[i]; i++) {
+ int nid = zl->zones[i]->zone_pgdat->node_id;
+
+ if (node_isset(nid, current->mems_allowed))
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * Is 'current' valid, and is zone z allowed in current->mems_allowed?
+ */
+int cpuset_zone_allowed(struct zone *z)
+{
+ return in_interrupt() ||
+ node_isset(z->zone_pgdat->node_id, current->mems_allowed);
+}
+
+/*
+ * proc_cpuset_show()
+ * - Print tasks cpuset path into seq_file.
+ * - Used for /proc/<pid>/cpuset.
+ */
+
+static int proc_cpuset_show(struct seq_file *m, void *v)
+{
+ struct cpuset *cs;
+ struct task_struct *tsk;
+ char *buf;
+ int retval = 0;
+
+ buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ tsk = m->private;
+ down(&cpuset_sem);
+ task_lock(tsk);
+ cs = tsk->cpuset;
+ task_unlock(tsk);
+ if (!cs) {
+ retval = -EINVAL;
+ goto out;
+ }
+
+ retval = cpuset_path(cs, buf, PAGE_SIZE);
+ if (retval < 0)
+ goto out;
+ seq_puts(m, buf);
+ seq_putc(m, '\n');
+out:
+ up(&cpuset_sem);
+ kfree(buf);
+ return retval;
+}
+
+static int cpuset_open(struct inode *inode, struct file *file)
+{
+ struct task_struct *tsk = PROC_I(inode)->task;
+ return single_open(file, proc_cpuset_show, tsk);
+}
+
+struct file_operations proc_cpuset_operations = {
+ .open = cpuset_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+/* Display task cpus_allowed, mems_allowed in /proc/<pid>/status file. */
+char *cpuset_task_status_allowed(struct task_struct *task, char *buffer)
+{
+ buffer += sprintf(buffer, "Cpus_allowed:\t");
+ buffer += cpumask_scnprintf(buffer, PAGE_SIZE, task->cpus_allowed);
+ buffer += sprintf(buffer, "\n");
+ buffer += sprintf(buffer, "Mems_allowed:\t");
+ buffer += nodemask_scnprintf(buffer, PAGE_SIZE, task->mems_allowed);
+ buffer += sprintf(buffer, "\n");
+ return buffer;
+}
diff --git a/kernel/exit.c b/kernel/exit.c
index f40a50f698508..6dd4ebe1dd903 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -25,6 +25,7 @@
#include <linux/mount.h>
#include <linux/proc_fs.h>
#include <linux/mempolicy.h>
+#include <linux/cpuset.h>
#include <linux/syscalls.h>
#include <asm/uaccess.h>
@@ -753,13 +754,6 @@ static void exit_notify(struct task_struct *tsk)
state = EXIT_DEAD;
tsk->exit_state = state;
- /*
- * Clear these here so that update_process_times() won't try to deliver
- * itimer, profile or rlimit signals to this task while it is in late exit.
- */
- tsk->it_virt_value = cputime_zero;
- tsk->it_prof_value = cputime_zero;
-
write_unlock_irq(&tasklist_lock);
list_for_each_safe(_p, _n, &ptrace_dead) {
@@ -799,18 +793,27 @@ fastcall NORET_TYPE void do_exit(long code)
}
tsk->flags |= PF_EXITING;
- del_timer_sync(&tsk->real_timer);
+
+ /*
+ * Make sure we don't try to process any timer firings
+ * while we are already exiting.
+ */
+ tsk->it_virt_expires = cputime_zero;
+ tsk->it_prof_expires = cputime_zero;
+ tsk->it_sched_expires = 0;
if (unlikely(in_atomic()))
printk(KERN_INFO "note: %s[%d] exited with preempt_count %d\n",
current->comm, current->pid,
preempt_count());
- acct_update_integrals();
- update_mem_hiwater();
+ acct_update_integrals(tsk);
+ update_mem_hiwater(tsk);
group_dead = atomic_dec_and_test(&tsk->signal->live);
- if (group_dead)
+ if (group_dead) {
+ del_timer_sync(&tsk->signal->real_timer);
acct_process(code);
+ }
exit_mm(tsk);
exit_sem(tsk);
@@ -818,6 +821,7 @@ fastcall NORET_TYPE void do_exit(long code)
__exit_fs(tsk);
exit_namespace(tsk);
exit_thread();
+ cpuset_exit(tsk);
exit_keys(tsk);
if (group_dead && tsk->signal->leader)
diff --git a/kernel/fork.c b/kernel/fork.c
index f6b929e69f5be..f42a17f88699b 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -29,6 +29,7 @@
#include <linux/mman.h>
#include <linux/fs.h>
#include <linux/cpu.h>
+#include <linux/cpuset.h>
#include <linux/security.h>
#include <linux/swap.h>
#include <linux/syscalls.h>
@@ -79,6 +80,24 @@ int nr_processes(void)
static kmem_cache_t *task_struct_cachep;
#endif
+/* SLAB cache for signal_struct structures (tsk->signal) */
+kmem_cache_t *signal_cachep;
+
+/* SLAB cache for sighand_struct structures (tsk->sighand) */
+kmem_cache_t *sighand_cachep;
+
+/* SLAB cache for files_struct structures (tsk->files) */
+kmem_cache_t *files_cachep;
+
+/* SLAB cache for fs_struct structures (tsk->fs) */
+kmem_cache_t *fs_cachep;
+
+/* SLAB cache for vm_area_struct structures */
+kmem_cache_t *vm_area_cachep;
+
+/* SLAB cache for mm_struct structures (tsk->mm) */
+static kmem_cache_t *mm_cachep;
+
void free_task(struct task_struct *tsk)
{
free_thread_info(tsk->thread_info);
@@ -129,6 +148,8 @@ void __init fork_init(unsigned long mempages)
init_task.signal->rlim[RLIMIT_NPROC].rlim_cur = max_threads/2;
init_task.signal->rlim[RLIMIT_NPROC].rlim_max = max_threads/2;
+ init_task.signal->rlim[RLIMIT_SIGPENDING] =
+ init_task.signal->rlim[RLIMIT_NPROC];
}
static struct task_struct *dup_task_struct(struct task_struct *orig)
@@ -174,8 +195,8 @@ static inline int dup_mmap(struct mm_struct * mm, struct mm_struct * oldmm)
mm->mmap_cache = NULL;
mm->free_area_cache = oldmm->mmap_base;
mm->map_count = 0;
- mm->rss = 0;
- mm->anon_rss = 0;
+ set_mm_counter(mm, rss, 0);
+ set_mm_counter(mm, anon_rss, 0);
cpus_clear(mm->cpu_vm_mask);
mm->mm_rb = RB_ROOT;
rb_link = &mm->mm_rb.rb_node;
@@ -471,7 +492,7 @@ static int copy_mm(unsigned long clone_flags, struct task_struct * tsk)
if (retval)
goto free_pt;
- mm->hiwater_rss = mm->rss;
+ mm->hiwater_rss = get_mm_counter(mm,rss);
mm->hiwater_vm = mm->total_vm;
good_mm:
@@ -719,6 +740,7 @@ static inline int copy_sighand(unsigned long clone_flags, struct task_struct * t
static inline int copy_signal(unsigned long clone_flags, struct task_struct * tsk)
{
struct signal_struct *sig;
+ int ret;
if (clone_flags & CLONE_THREAD) {
atomic_inc(&current->signal->count);
@@ -729,6 +751,13 @@ static inline int copy_signal(unsigned long clone_flags, struct task_struct * ts
tsk->signal = sig;
if (!sig)
return -ENOMEM;
+
+ ret = copy_thread_group_keys(tsk);
+ if (ret < 0) {
+ kmem_cache_free(signal_cachep, sig);
+ return ret;
+ }
+
atomic_set(&sig->count, 1);
atomic_set(&sig->live, 1);
init_waitqueue_head(&sig->wait_chldexit);
@@ -740,6 +769,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;
+ sig->real_timer.function = it_real_fn;
+ sig->real_timer.data = (unsigned long) tsk;
+ init_timer(&sig->real_timer);
+
+ 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;
@@ -749,11 +788,24 @@ static inline int copy_signal(unsigned long clone_flags, struct task_struct * ts
sig->utime = sig->stime = sig->cutime = sig->cstime = cputime_zero;
sig->nvcsw = sig->nivcsw = sig->cnvcsw = sig->cnivcsw = 0;
sig->min_flt = sig->maj_flt = sig->cmin_flt = sig->cmaj_flt = 0;
+ sig->sched_time = 0;
+ INIT_LIST_HEAD(&sig->cpu_timers[0]);
+ INIT_LIST_HEAD(&sig->cpu_timers[1]);
+ INIT_LIST_HEAD(&sig->cpu_timers[2]);
task_lock(current->group_leader);
memcpy(sig->rlim, current->signal->rlim, sizeof sig->rlim);
task_unlock(current->group_leader);
+ if (sig->rlim[RLIMIT_CPU].rlim_cur != RLIM_INFINITY) {
+ /*
+ * New sole thread in the process gets an expiry time
+ * of the whole CPU time limit.
+ */
+ tsk->it_prof_expires =
+ secs_to_cputime(sig->rlim[RLIMIT_CPU].rlim_cur);
+ }
+
return 0;
}
@@ -866,23 +918,22 @@ static task_t *copy_process(unsigned long clone_flags,
clear_tsk_thread_flag(p, TIF_SIGPENDING);
init_sigpending(&p->pending);
- p->it_real_value = 0;
- p->it_real_incr = 0;
- p->it_virt_value = cputime_zero;
- p->it_virt_incr = cputime_zero;
- p->it_prof_value = cputime_zero;
- p->it_prof_incr = cputime_zero;
- init_timer(&p->real_timer);
- p->real_timer.data = (unsigned long) p;
-
p->utime = cputime_zero;
p->stime = cputime_zero;
+ p->sched_time = 0;
p->rchar = 0; /* I/O counter: bytes read */
p->wchar = 0; /* I/O counter: bytes written */
p->syscr = 0; /* I/O counter: read syscalls */
p->syscw = 0; /* I/O counter: write syscalls */
acct_clear_integrals(p);
+ p->it_virt_expires = cputime_zero;
+ p->it_prof_expires = cputime_zero;
+ p->it_sched_expires = 0;
+ INIT_LIST_HEAD(&p->cpu_timers[0]);
+ INIT_LIST_HEAD(&p->cpu_timers[1]);
+ INIT_LIST_HEAD(&p->cpu_timers[2]);
+
p->lock_depth = -1; /* -1 = no lock */
do_posix_clock_monotonic_gettime(&p->start_time);
p->security = NULL;
@@ -1015,6 +1066,21 @@ static task_t *copy_process(unsigned long clone_flags,
set_tsk_thread_flag(p, TIF_SIGPENDING);
}
+ if (!cputime_eq(current->signal->it_virt_expires,
+ cputime_zero) ||
+ !cputime_eq(current->signal->it_prof_expires,
+ cputime_zero) ||
+ current->signal->rlim[RLIMIT_CPU].rlim_cur != RLIM_INFINITY ||
+ !list_empty(&current->signal->cpu_timers[0]) ||
+ !list_empty(&current->signal->cpu_timers[1]) ||
+ !list_empty(&current->signal->cpu_timers[2])) {
+ /*
+ * Have child wake up on its first tick to check
+ * for process CPU timers.
+ */
+ p->it_prof_expires = jiffies_to_cputime(1);
+ }
+
spin_unlock(&current->sighand->siglock);
}
@@ -1022,6 +1088,8 @@ static task_t *copy_process(unsigned long clone_flags,
if (unlikely(p->ptrace & PT_PTRACED))
__ptrace_link(p, current->parent);
+ cpuset_fork(p);
+
attach_pid(p, PIDTYPE_PID, p->pid);
attach_pid(p, PIDTYPE_TGID, p->tgid);
if (thread_group_leader(p)) {
@@ -1183,24 +1251,6 @@ long do_fork(unsigned long clone_flags,
return pid;
}
-/* SLAB cache for signal_struct structures (tsk->signal) */
-kmem_cache_t *signal_cachep;
-
-/* SLAB cache for sighand_struct structures (tsk->sighand) */
-kmem_cache_t *sighand_cachep;
-
-/* SLAB cache for files_struct structures (tsk->files) */
-kmem_cache_t *files_cachep;
-
-/* SLAB cache for fs_struct structures (tsk->fs) */
-kmem_cache_t *fs_cachep;
-
-/* SLAB cache for vm_area_struct structures */
-kmem_cache_t *vm_area_cachep;
-
-/* SLAB cache for mm_struct structures (tsk->mm) */
-kmem_cache_t *mm_cachep;
-
void __init proc_caches_init(void)
{
sighand_cachep = kmem_cache_create("sighand_cache",
diff --git a/kernel/futex.c b/kernel/futex.c
index 645a4301f1e60..7b54a672d0add 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -40,7 +40,7 @@
#include <linux/pagemap.h>
#include <linux/syscalls.h>
-#define FUTEX_HASHBITS 8
+#define FUTEX_HASHBITS (CONFIG_BASE_SMALL ? 4 : 8)
/*
* Futexes are matched on equal values of this key.
@@ -97,7 +97,6 @@ struct futex_q {
*/
struct futex_hash_bucket {
spinlock_t lock;
- unsigned int nqueued;
struct list_head chain;
};
@@ -258,6 +257,17 @@ static void drop_key_refs(union futex_key *key)
}
}
+static inline int get_futex_value_locked(int *dest, int __user *from)
+{
+ int ret;
+
+ inc_preempt_count();
+ ret = __copy_from_user_inatomic(dest, from, sizeof(int));
+ dec_preempt_count();
+
+ return ret ? -EFAULT : 0;
+}
+
/*
* The hash bucket lock must be held when this is called.
* Afterwards, the futex_q must not be accessed.
@@ -327,8 +337,8 @@ static int futex_requeue(unsigned long uaddr1, unsigned long uaddr2,
struct list_head *head1;
struct futex_q *this, *next;
int ret, drop_count = 0;
- unsigned int nqueued;
+ retry:
down_read(&current->mm->mmap_sem);
ret = get_futex_key(uaddr1, &key1);
@@ -341,41 +351,40 @@ static int futex_requeue(unsigned long uaddr1, unsigned long uaddr2,
bh1 = hash_futex(&key1);
bh2 = hash_futex(&key2);
- nqueued = bh1->nqueued;
+ if (bh1 < bh2)
+ spin_lock(&bh1->lock);
+ spin_lock(&bh2->lock);
+ if (bh1 > bh2)
+ spin_lock(&bh1->lock);
+
if (likely(valp != NULL)) {
int curval;
- /* In order to avoid doing get_user while
- holding bh1->lock and bh2->lock, nqueued
- (monotonically increasing field) must be first
- read, then *uaddr1 fetched from userland and
- after acquiring lock nqueued field compared with
- the stored value. The smp_mb () below
- makes sure that bh1->nqueued is read from memory
- before *uaddr1. */
- smp_mb();
-
- if (get_user(curval, (int __user *)uaddr1) != 0) {
- ret = -EFAULT;
- goto out;
+ ret = get_futex_value_locked(&curval, (int __user *)uaddr1);
+
+ if (unlikely(ret)) {
+ spin_unlock(&bh1->lock);
+ if (bh1 != bh2)
+ spin_unlock(&bh2->lock);
+
+ /* If we would have faulted, release mmap_sem, fault
+ * it in and start all over again.
+ */
+ up_read(&current->mm->mmap_sem);
+
+ ret = get_user(curval, (int __user *)uaddr1);
+
+ if (!ret)
+ goto retry;
+
+ return ret;
}
if (curval != *valp) {
ret = -EAGAIN;
- goto out;
+ goto out_unlock;
}
}
- if (bh1 < bh2)
- spin_lock(&bh1->lock);
- spin_lock(&bh2->lock);
- if (bh1 > bh2)
- spin_lock(&bh1->lock);
-
- if (unlikely(nqueued != bh1->nqueued && valp != NULL)) {
- ret = -EAGAIN;
- goto out_unlock;
- }
-
head1 = &bh1->chain;
list_for_each_entry_safe(this, next, head1, list) {
if (!match_futex (&this->key, &key1))
@@ -411,13 +420,9 @@ out:
return ret;
}
-/*
- * queue_me and unqueue_me must be called as a pair, each
- * exactly once. They are called with the hashed spinlock held.
- */
-
/* The key must be already stored in q->key. */
-static void queue_me(struct futex_q *q, int fd, struct file *filp)
+static inline struct futex_hash_bucket *
+queue_lock(struct futex_q *q, int fd, struct file *filp)
{
struct futex_hash_bucket *bh;
@@ -431,11 +436,35 @@ static void queue_me(struct futex_q *q, int fd, struct file *filp)
q->lock_ptr = &bh->lock;
spin_lock(&bh->lock);
- bh->nqueued++;
+ return bh;
+}
+
+static inline void __queue_me(struct futex_q *q, struct futex_hash_bucket *bh)
+{
list_add_tail(&q->list, &bh->chain);
spin_unlock(&bh->lock);
}
+static inline void
+queue_unlock(struct futex_q *q, struct futex_hash_bucket *bh)
+{
+ spin_unlock(&bh->lock);
+ drop_key_refs(&q->key);
+}
+
+/*
+ * queue_me and unqueue_me must be called as a pair, each
+ * exactly once. They are called with the hashed spinlock held.
+ */
+
+/* The key must be already stored in q->key. */
+static void queue_me(struct futex_q *q, int fd, struct file *filp)
+{
+ struct futex_hash_bucket *bh;
+ bh = queue_lock(q, fd, filp);
+ __queue_me(q, bh);
+}
+
/* Return 1 if we were still queued (ie. 0 means we were woken) */
static int unqueue_me(struct futex_q *q)
{
@@ -479,14 +508,16 @@ static int futex_wait(unsigned long uaddr, int val, unsigned long time)
DECLARE_WAITQUEUE(wait, current);
int ret, curval;
struct futex_q q;
+ struct futex_hash_bucket *bh;
+ retry:
down_read(&current->mm->mmap_sem);
ret = get_futex_key(uaddr, &q.key);
if (unlikely(ret != 0))
goto out_release_sem;
- queue_me(&q, -1, NULL);
+ bh = queue_lock(&q, -1, NULL);
/*
* Access the page AFTER the futex is queued.
@@ -508,15 +539,32 @@ static int futex_wait(unsigned long uaddr, int val, unsigned long time)
* We hold the mmap semaphore, so the mapping cannot have changed
* since we looked it up in get_futex_key.
*/
- if (get_user(curval, (int __user *)uaddr) != 0) {
- ret = -EFAULT;
- goto out_unqueue;
+
+ ret = get_futex_value_locked(&curval, (int __user *)uaddr);
+
+ if (unlikely(ret)) {
+ queue_unlock(&q, bh);
+
+ /* If we would have faulted, release mmap_sem, fault it in and
+ * start all over again.
+ */
+ up_read(&current->mm->mmap_sem);
+
+ ret = get_user(curval, (int __user *)uaddr);
+
+ if (!ret)
+ goto retry;
+ return ret;
}
if (curval != val) {
ret = -EWOULDBLOCK;
- goto out_unqueue;
+ queue_unlock(&q, bh);
+ goto out_release_sem;
}
+ /* Only actually queue if *uaddr contained val. */
+ __queue_me(&q, bh);
+
/*
* Now the futex is queued and we have checked the data, we
* don't want to hold mmap_sem while we sleep.
@@ -557,10 +605,6 @@ static int futex_wait(unsigned long uaddr, int val, unsigned long time)
* have handled it for us already. */
return -EINTR;
- out_unqueue:
- /* If we were woken (and unqueued), we succeeded, whatever. */
- if (!unqueue_me(&q))
- ret = 0;
out_release_sem:
up_read(&current->mm->mmap_sem);
return ret;
diff --git a/kernel/intermodule.c b/kernel/intermodule.c
index 9078649382cfe..388977f3e9b7d 100644
--- a/kernel/intermodule.c
+++ b/kernel/intermodule.c
@@ -113,7 +113,7 @@ void inter_module_unregister(const char *im_name)
* Try to increment the use count on the owning module, if that fails
* then return NULL. Otherwise return the userdata.
*/
-const void *inter_module_get(const char *im_name)
+static const void *inter_module_get(const char *im_name)
{
struct list_head *tmp;
struct inter_module_entry *ime;
@@ -178,6 +178,5 @@ void inter_module_put(const char *im_name)
EXPORT_SYMBOL(inter_module_register);
EXPORT_SYMBOL(inter_module_unregister);
-EXPORT_SYMBOL(inter_module_get);
EXPORT_SYMBOL(inter_module_get_request);
EXPORT_SYMBOL(inter_module_put);
diff --git a/kernel/irq/proc.c b/kernel/irq/proc.c
index 33fe32e114cb4..85d08daa6600e 100644
--- a/kernel/irq/proc.c
+++ b/kernel/irq/proc.c
@@ -19,6 +19,13 @@ static struct proc_dir_entry *root_irq_dir, *irq_dir[NR_IRQS];
*/
static struct proc_dir_entry *smp_affinity_entry[NR_IRQS];
+void __attribute__((weak))
+proc_set_irq_affinity(unsigned int irq, cpumask_t mask_val)
+{
+ irq_affinity[irq] = mask_val;
+ irq_desc[irq].handler->set_affinity(irq, mask_val);
+}
+
static int irq_affinity_read_proc(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
@@ -53,8 +60,7 @@ static int irq_affinity_write_proc(struct file *file, const char __user *buffer,
if (cpus_empty(tmp))
return -EINVAL;
- irq_affinity[irq] = new_value;
- irq_desc[irq].handler->set_affinity(irq, new_value);
+ proc_set_irq_affinity(irq, new_value);
return full_count;
}
diff --git a/kernel/itimer.c b/kernel/itimer.c
index e1743c5632062..e9a40e947e079 100644
--- a/kernel/itimer.c
+++ b/kernel/itimer.c
@@ -11,36 +11,86 @@
#include <linux/interrupt.h>
#include <linux/syscalls.h>
#include <linux/time.h>
+#include <linux/posix-timers.h>
#include <asm/uaccess.h>
+static unsigned long it_real_value(struct signal_struct *sig)
+{
+ unsigned long val = 0;
+ if (timer_pending(&sig->real_timer)) {
+ val = sig->real_timer.expires - jiffies;
+
+ /* look out for negative/zero itimer.. */
+ if ((long) val <= 0)
+ val = 1;
+ }
+ return val;
+}
+
int do_getitimer(int which, struct itimerval *value)
{
- register unsigned long val;
+ struct task_struct *tsk = current;
+ unsigned long interval, val;
+ cputime_t cinterval, cval;
switch (which) {
case ITIMER_REAL:
- val = 0;
- /*
- * FIXME! This needs to be atomic, in case the kernel timer happens!
- */
- if (timer_pending(&current->real_timer)) {
- val = current->real_timer.expires - jiffies;
-
- /* look out for negative/zero itimer.. */
- if ((long) val <= 0)
- val = 1;
- }
+ 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(current->it_real_incr, &value->it_interval);
+ jiffies_to_timeval(interval, &value->it_interval);
break;
case ITIMER_VIRTUAL:
- cputime_to_timeval(current->it_virt_value, &value->it_value);
- cputime_to_timeval(current->it_virt_incr, &value->it_interval);
+ read_lock(&tasklist_lock);
+ spin_lock_irq(&tsk->sighand->siglock);
+ cval = tsk->signal->it_virt_expires;
+ cinterval = tsk->signal->it_virt_incr;
+ if (!cputime_eq(cval, cputime_zero)) {
+ struct task_struct *t = tsk;
+ cputime_t utime = tsk->signal->utime;
+ do {
+ utime = cputime_add(utime, t->utime);
+ t = next_thread(t);
+ } while (t != tsk);
+ if (cputime_le(cval, utime)) { /* about to fire */
+ cval = jiffies_to_cputime(1);
+ } else {
+ cval = cputime_sub(cval, utime);
+ }
+ }
+ spin_unlock_irq(&tsk->sighand->siglock);
+ read_unlock(&tasklist_lock);
+ cputime_to_timeval(cval, &value->it_value);
+ cputime_to_timeval(cinterval, &value->it_interval);
break;
case ITIMER_PROF:
- cputime_to_timeval(current->it_prof_value, &value->it_value);
- cputime_to_timeval(current->it_prof_incr, &value->it_interval);
+ read_lock(&tasklist_lock);
+ spin_lock_irq(&tsk->sighand->siglock);
+ cval = tsk->signal->it_prof_expires;
+ cinterval = tsk->signal->it_prof_incr;
+ if (!cputime_eq(cval, cputime_zero)) {
+ struct task_struct *t = tsk;
+ cputime_t ptime = cputime_add(tsk->signal->utime,
+ tsk->signal->stime);
+ do {
+ ptime = cputime_add(ptime,
+ cputime_add(t->utime,
+ t->stime));
+ t = next_thread(t);
+ } while (t != tsk);
+ if (cputime_le(cval, ptime)) { /* about to fire */
+ cval = jiffies_to_cputime(1);
+ } else {
+ cval = cputime_sub(cval, ptime);
+ }
+ }
+ spin_unlock_irq(&tsk->sighand->siglock);
+ read_unlock(&tasklist_lock);
+ cputime_to_timeval(cval, &value->it_value);
+ cputime_to_timeval(cinterval, &value->it_interval);
break;
default:
return(-EINVAL);
@@ -48,7 +98,6 @@ int do_getitimer(int which, struct itimerval *value)
return 0;
}
-/* SMP: Only we modify our itimer values. */
asmlinkage long sys_getitimer(int which, struct itimerval __user *value)
{
int error = -EFAULT;
@@ -63,70 +112,112 @@ asmlinkage long sys_getitimer(int which, struct itimerval __user *value)
return error;
}
+/*
+ * Called with P->sighand->siglock held and P->signal->real_timer inactive.
+ * If interval is nonzero, arm the timer for interval ticks from now.
+ */
+static inline void it_real_arm(struct task_struct *p, unsigned long interval)
+{
+ p->signal->it_real_value = interval; /* XXX unnecessary field?? */
+ if (interval == 0)
+ return;
+ if (interval > (unsigned long) LONG_MAX)
+ interval = LONG_MAX;
+ p->signal->real_timer.expires = jiffies + interval;
+ add_timer(&p->signal->real_timer);
+}
+
void it_real_fn(unsigned long __data)
{
struct task_struct * p = (struct task_struct *) __data;
- unsigned long interval;
send_group_sig_info(SIGALRM, SEND_SIG_PRIV, p);
- interval = p->it_real_incr;
- if (interval) {
- if (interval > (unsigned long) LONG_MAX)
- interval = LONG_MAX;
- p->real_timer.expires = jiffies + interval;
- add_timer(&p->real_timer);
- }
+
+ /*
+ * 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.
+ */
+ it_real_arm(p, p->signal->it_real_incr);
}
int do_setitimer(int which, struct itimerval *value, struct itimerval *ovalue)
{
- unsigned long expire;
- cputime_t cputime;
- int k;
+ struct task_struct *tsk = current;
+ unsigned long val, interval;
+ cputime_t cval, cinterval, nval, ninterval;
- if (ovalue && (k = do_getitimer(which, ovalue)) < 0)
- return k;
switch (which) {
- case ITIMER_REAL:
- del_timer_sync(&current->real_timer);
- expire = timeval_to_jiffies(&value->it_value);
- current->it_real_value = expire;
- current->it_real_incr =
- timeval_to_jiffies(&value->it_interval);
- if (!expire)
- break;
- if (expire > (unsigned long) LONG_MAX)
- expire = LONG_MAX;
- current->real_timer.expires = jiffies + expire;
- add_timer(&current->real_timer);
- break;
- case ITIMER_VIRTUAL:
- cputime = timeval_to_cputime(&value->it_value);
- if (cputime_gt(cputime, cputime_zero))
- cputime = cputime_add(cputime,
- jiffies_to_cputime(1));
- current->it_virt_value = cputime;
- cputime = timeval_to_cputime(&value->it_interval);
- current->it_virt_incr = cputime;
- break;
- case ITIMER_PROF:
- cputime = timeval_to_cputime(&value->it_value);
- if (cputime_gt(cputime, cputime_zero))
- cputime = cputime_add(cputime,
- jiffies_to_cputime(1));
- current->it_prof_value = cputime;
- cputime = timeval_to_cputime(&value->it_interval);
- current->it_prof_incr = cputime;
- break;
- default:
- return -EINVAL;
+ case ITIMER_REAL:
+ spin_lock_irq(&tsk->sighand->siglock);
+ interval = tsk->signal->it_real_incr;
+ val = it_real_value(tsk->signal);
+ if (val)
+ del_timer_sync(&tsk->signal->real_timer);
+ tsk->signal->it_real_incr =
+ timeval_to_jiffies(&value->it_interval);
+ it_real_arm(tsk, timeval_to_jiffies(&value->it_value));
+ spin_unlock_irq(&tsk->sighand->siglock);
+ if (ovalue) {
+ jiffies_to_timeval(val, &ovalue->it_value);
+ jiffies_to_timeval(interval,
+ &ovalue->it_interval);
+ }
+ break;
+ case ITIMER_VIRTUAL:
+ nval = timeval_to_cputime(&value->it_value);
+ ninterval = timeval_to_cputime(&value->it_interval);
+ read_lock(&tasklist_lock);
+ spin_lock_irq(&tsk->sighand->siglock);
+ cval = tsk->signal->it_virt_expires;
+ cinterval = tsk->signal->it_virt_incr;
+ if (!cputime_eq(cval, cputime_zero) ||
+ !cputime_eq(nval, cputime_zero)) {
+ if (cputime_gt(nval, cputime_zero))
+ nval = cputime_add(nval,
+ jiffies_to_cputime(1));
+ set_process_cpu_timer(tsk, CPUCLOCK_VIRT,
+ &nval, &cval);
+ }
+ tsk->signal->it_virt_expires = nval;
+ tsk->signal->it_virt_incr = ninterval;
+ spin_unlock_irq(&tsk->sighand->siglock);
+ read_unlock(&tasklist_lock);
+ if (ovalue) {
+ cputime_to_timeval(cval, &ovalue->it_value);
+ cputime_to_timeval(cinterval, &ovalue->it_interval);
+ }
+ break;
+ case ITIMER_PROF:
+ nval = timeval_to_cputime(&value->it_value);
+ ninterval = timeval_to_cputime(&value->it_interval);
+ read_lock(&tasklist_lock);
+ spin_lock_irq(&tsk->sighand->siglock);
+ cval = tsk->signal->it_prof_expires;
+ cinterval = tsk->signal->it_prof_incr;
+ if (!cputime_eq(cval, cputime_zero) ||
+ !cputime_eq(nval, cputime_zero)) {
+ if (cputime_gt(nval, cputime_zero))
+ nval = cputime_add(nval,
+ jiffies_to_cputime(1));
+ set_process_cpu_timer(tsk, CPUCLOCK_PROF,
+ &nval, &cval);
+ }
+ tsk->signal->it_prof_expires = nval;
+ tsk->signal->it_prof_incr = ninterval;
+ spin_unlock_irq(&tsk->sighand->siglock);
+ read_unlock(&tasklist_lock);
+ if (ovalue) {
+ cputime_to_timeval(cval, &ovalue->it_value);
+ cputime_to_timeval(cinterval, &ovalue->it_interval);
+ }
+ break;
+ default:
+ return -EINVAL;
}
return 0;
}
-/* SMP: Again, only we play with our itimers, and signals are SMP safe
- * now so that is not an issue at all anymore.
- */
asmlinkage long sys_setitimer(int which,
struct itimerval __user *value,
struct itimerval __user *ovalue)
diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c
index bd765adaacd64..1627f8d6e0cdd 100644
--- a/kernel/kallsyms.c
+++ b/kernel/kallsyms.c
@@ -145,14 +145,22 @@ unsigned long kallsyms_lookup_name(const char *name)
}
return module_kallsyms_lookup_name(name);
}
+EXPORT_SYMBOL_GPL(kallsyms_lookup_name);
-/* Lookup an address. modname is set to NULL if it's in the kernel. */
+/*
+ * Lookup an address
+ * - modname is set to NULL if it's in the kernel
+ * - we guarantee that the returned name is valid until we reschedule even if
+ * it resides in a module
+ * - we also guarantee that modname will be valid until rescheduled
+ */
const char *kallsyms_lookup(unsigned long addr,
unsigned long *symbolsize,
unsigned long *offset,
char **modname, char *namebuf)
{
unsigned long i, low, high, mid;
+ const char *msym;
/* This kernel should never had been booted. */
BUG_ON(!kallsyms_addresses);
@@ -204,7 +212,12 @@ const char *kallsyms_lookup(unsigned long addr,
return namebuf;
}
- return module_address_lookup(addr, symbolsize, offset, modname);
+ /* see if it's in a module */
+ msym = module_address_lookup(addr, symbolsize, offset, modname);
+ if (msym)
+ return strncpy(namebuf, msym, KSYM_NAME_LEN);
+
+ return NULL;
}
/* Replace "%s" in format with address, or returns -errno. */
@@ -342,7 +355,7 @@ static int s_show(struct seq_file *m, void *p)
return 0;
}
-struct seq_operations kallsyms_op = {
+static struct seq_operations kallsyms_op = {
.start = s_start,
.next = s_next,
.stop = s_stop,
@@ -384,7 +397,7 @@ static struct file_operations kallsyms_operations = {
.release = kallsyms_release,
};
-int __init kallsyms_init(void)
+static int __init kallsyms_init(void)
{
struct proc_dir_entry *entry;
diff --git a/kernel/kfifo.c b/kernel/kfifo.c
index 2fbe06a4a6eb8..179baafcdd96d 100644
--- a/kernel/kfifo.c
+++ b/kernel/kfifo.c
@@ -25,7 +25,7 @@
#include <linux/err.h>
#include <linux/kfifo.h>
-/*
+/**
* kfifo_init - allocates a new FIFO using a preallocated buffer
* @buffer: the preallocated buffer to be used.
* @size: the size of the internal buffer, this have to be a power of 2.
@@ -36,7 +36,7 @@
* struct kfifo with kfree().
*/
struct kfifo *kfifo_init(unsigned char *buffer, unsigned int size,
- int gfp_mask, spinlock_t *lock)
+ unsigned int __nocast gfp_mask, spinlock_t *lock)
{
struct kfifo *fifo;
@@ -56,7 +56,7 @@ struct kfifo *kfifo_init(unsigned char *buffer, unsigned int size,
}
EXPORT_SYMBOL(kfifo_init);
-/*
+/**
* kfifo_alloc - allocates a new FIFO and its internal buffer
* @size: the size of the internal buffer to be allocated.
* @gfp_mask: get_free_pages mask, passed to kmalloc()
@@ -64,7 +64,7 @@ EXPORT_SYMBOL(kfifo_init);
*
* The size will be rounded-up to a power of 2.
*/
-struct kfifo *kfifo_alloc(unsigned int size, int gfp_mask, spinlock_t *lock)
+struct kfifo *kfifo_alloc(unsigned int size, unsigned int __nocast gfp_mask, spinlock_t *lock)
{
unsigned char *buffer;
struct kfifo *ret;
@@ -91,7 +91,7 @@ struct kfifo *kfifo_alloc(unsigned int size, int gfp_mask, spinlock_t *lock)
}
EXPORT_SYMBOL(kfifo_alloc);
-/*
+/**
* kfifo_free - frees the FIFO
* @fifo: the fifo to be freed.
*/
@@ -102,7 +102,7 @@ void kfifo_free(struct kfifo *fifo)
}
EXPORT_SYMBOL(kfifo_free);
-/*
+/**
* __kfifo_put - puts some data into the FIFO, no locking version
* @fifo: the fifo to be used.
* @buffer: the data to be added.
@@ -135,7 +135,7 @@ unsigned int __kfifo_put(struct kfifo *fifo,
}
EXPORT_SYMBOL(__kfifo_put);
-/*
+/**
* __kfifo_get - gets some data from the FIFO, no locking version
* @fifo: the fifo to be used.
* @buffer: where the data must be copied.
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 4a331aed08660..1d5dd1337bd1c 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -79,7 +79,7 @@ int register_kprobe(struct kprobe *p)
unsigned long flags = 0;
if ((ret = arch_prepare_kprobe(p)) != 0) {
- goto out;
+ goto rm_kprobe;
}
spin_lock_irqsave(&kprobe_lock, flags);
INIT_HLIST_NODE(&p->hlist);
@@ -96,8 +96,9 @@ int register_kprobe(struct kprobe *p)
*p->addr = BREAKPOINT_INSTRUCTION;
flush_icache_range((unsigned long) p->addr,
(unsigned long) p->addr + sizeof(kprobe_opcode_t));
- out:
+out:
spin_unlock_irqrestore(&kprobe_lock, flags);
+rm_kprobe:
if (ret == -EEXIST)
arch_remove_kprobe(p);
return ret;
diff --git a/kernel/module.c b/kernel/module.c
index ce427b675b98f..2dbfa0773faf3 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -472,7 +472,7 @@ struct stopref
};
/* Whole machine is stopped with interrupts off when this runs. */
-static inline int __try_stop_module(void *_sref)
+static int __try_stop_module(void *_sref)
{
struct stopref *sref = _sref;
@@ -1072,14 +1072,22 @@ static void mod_kobject_remove(struct module *mod)
kobject_unregister(&mod->mkobj.kobj);
}
+/*
+ * unlink the module with the whole machine is stopped with interrupts off
+ * - this defends against kallsyms not taking locks
+ */
+static int __unlink_module(void *_mod)
+{
+ struct module *mod = _mod;
+ list_del(&mod->list);
+ return 0;
+}
+
/* Free a module, remove from lists, etc (must hold module mutex). */
static void free_module(struct module *mod)
{
/* Delete from various lists */
- spin_lock_irq(&modlist_lock);
- list_del(&mod->list);
- spin_unlock_irq(&modlist_lock);
-
+ stop_machine_run(__unlink_module, mod, NR_CPUS);
remove_sect_attrs(mod);
mod_kobject_remove(mod);
@@ -1732,6 +1740,17 @@ static struct module *load_module(void __user *umod,
goto free_hdr;
}
+/*
+ * link the module with the whole machine is stopped with interrupts off
+ * - this defends against kallsyms not taking locks
+ */
+static int __link_module(void *_mod)
+{
+ struct module *mod = _mod;
+ list_add(&mod->list, &modules);
+ return 0;
+}
+
/* This is where the real work happens */
asmlinkage long
sys_init_module(void __user *umod,
@@ -1766,9 +1785,7 @@ sys_init_module(void __user *umod,
/* Now sew it into the lists. They won't access us, since
strong_try_module_get() will fail. */
- spin_lock_irq(&modlist_lock);
- list_add(&mod->list, &modules);
- spin_unlock_irq(&modlist_lock);
+ stop_machine_run(__link_module, mod, NR_CPUS);
/* Drop lock so they can recurse */
up(&module_mutex);
diff --git a/kernel/panic.c b/kernel/panic.c
index 3f93784a42073..0fa3f3a66fb6a 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -49,8 +49,7 @@ EXPORT_SYMBOL(panic_blink);
* panic - halt the system
* @fmt: The text string to print
*
- * Display a message, then perform cleanups. Functions in the panic
- * notifier list are called after the filesystem cache is flushed (when possible).
+ * Display a message, then perform cleanups.
*
* This function never returns.
*/
diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c
new file mode 100644
index 0000000000000..ad85d3f0dcc45
--- /dev/null
+++ b/kernel/posix-cpu-timers.c
@@ -0,0 +1,1559 @@
+/*
+ * Implement CPU time clocks for the POSIX clock interface.
+ */
+
+#include <linux/sched.h>
+#include <linux/posix-timers.h>
+#include <asm/uaccess.h>
+#include <linux/errno.h>
+
+static int check_clock(clockid_t which_clock)
+{
+ int error = 0;
+ struct task_struct *p;
+ const pid_t pid = CPUCLOCK_PID(which_clock);
+
+ if (CPUCLOCK_WHICH(which_clock) >= CPUCLOCK_MAX)
+ return -EINVAL;
+
+ if (pid == 0)
+ return 0;
+
+ read_lock(&tasklist_lock);
+ p = find_task_by_pid(pid);
+ if (!p || (CPUCLOCK_PERTHREAD(which_clock) ?
+ p->tgid != current->tgid : p->tgid != pid)) {
+ error = -EINVAL;
+ }
+ read_unlock(&tasklist_lock);
+
+ return error;
+}
+
+static inline union cpu_time_count
+timespec_to_sample(clockid_t which_clock, const struct timespec *tp)
+{
+ union cpu_time_count ret;
+ ret.sched = 0; /* high half always zero when .cpu used */
+ if (CPUCLOCK_WHICH(which_clock) == CPUCLOCK_SCHED) {
+ ret.sched = tp->tv_sec * NSEC_PER_SEC + tp->tv_nsec;
+ } else {
+ ret.cpu = timespec_to_cputime(tp);
+ }
+ return ret;
+}
+
+static void sample_to_timespec(clockid_t which_clock,
+ union cpu_time_count cpu,
+ struct timespec *tp)
+{
+ if (CPUCLOCK_WHICH(which_clock) == CPUCLOCK_SCHED) {
+ tp->tv_sec = div_long_long_rem(cpu.sched,
+ NSEC_PER_SEC, &tp->tv_nsec);
+ } else {
+ cputime_to_timespec(cpu.cpu, tp);
+ }
+}
+
+static inline int cpu_time_before(clockid_t which_clock,
+ union cpu_time_count now,
+ union cpu_time_count then)
+{
+ if (CPUCLOCK_WHICH(which_clock) == CPUCLOCK_SCHED) {
+ return now.sched < then.sched;
+ } else {
+ return cputime_lt(now.cpu, then.cpu);
+ }
+}
+static inline void cpu_time_add(clockid_t which_clock,
+ union cpu_time_count *acc,
+ union cpu_time_count val)
+{
+ if (CPUCLOCK_WHICH(which_clock) == CPUCLOCK_SCHED) {
+ acc->sched += val.sched;
+ } else {
+ acc->cpu = cputime_add(acc->cpu, val.cpu);
+ }
+}
+static inline union cpu_time_count cpu_time_sub(clockid_t which_clock,
+ union cpu_time_count a,
+ union cpu_time_count b)
+{
+ if (CPUCLOCK_WHICH(which_clock) == CPUCLOCK_SCHED) {
+ a.sched -= b.sched;
+ } else {
+ a.cpu = cputime_sub(a.cpu, b.cpu);
+ }
+ return a;
+}
+
+/*
+ * Update expiry time from increment, and increase overrun count,
+ * given the current clock sample.
+ */
+static inline void bump_cpu_timer(struct k_itimer *timer,
+ union cpu_time_count now)
+{
+ int i;
+
+ if (timer->it.cpu.incr.sched == 0)
+ return;
+
+ if (CPUCLOCK_WHICH(timer->it_clock) == CPUCLOCK_SCHED) {
+ unsigned long long delta, incr;
+
+ if (now.sched < timer->it.cpu.expires.sched)
+ return;
+ incr = timer->it.cpu.incr.sched;
+ delta = now.sched + incr - timer->it.cpu.expires.sched;
+ /* Don't use (incr*2 < delta), incr*2 might overflow. */
+ for (i = 0; incr < delta - incr; i++)
+ incr = incr << 1;
+ for (; i >= 0; incr >>= 1, i--) {
+ if (delta <= incr)
+ continue;
+ timer->it.cpu.expires.sched += incr;
+ timer->it_overrun += 1 << i;
+ delta -= incr;
+ }
+ } else {
+ cputime_t delta, incr;
+
+ if (cputime_lt(now.cpu, timer->it.cpu.expires.cpu))
+ return;
+ incr = timer->it.cpu.incr.cpu;
+ delta = cputime_sub(cputime_add(now.cpu, incr),
+ timer->it.cpu.expires.cpu);
+ /* Don't use (incr*2 < delta), incr*2 might overflow. */
+ for (i = 0; cputime_lt(incr, cputime_sub(delta, incr)); i++)
+ incr = cputime_add(incr, incr);
+ for (; i >= 0; incr = cputime_halve(incr), i--) {
+ if (cputime_le(delta, incr))
+ continue;
+ timer->it.cpu.expires.cpu =
+ cputime_add(timer->it.cpu.expires.cpu, incr);
+ timer->it_overrun += 1 << i;
+ delta = cputime_sub(delta, incr);
+ }
+ }
+}
+
+static inline cputime_t prof_ticks(struct task_struct *p)
+{
+ return cputime_add(p->utime, p->stime);
+}
+static inline cputime_t virt_ticks(struct task_struct *p)
+{
+ return p->utime;
+}
+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 error = check_clock(which_clock);
+ if (!error) {
+ tp->tv_sec = 0;
+ tp->tv_nsec = ((NSEC_PER_SEC + HZ - 1) / HZ);
+ if (CPUCLOCK_WHICH(which_clock) == CPUCLOCK_SCHED) {
+ /*
+ * If sched_clock is using a cycle counter, we
+ * don't have any idea of its true resolution
+ * exported, but it is much more than 1s/HZ.
+ */
+ tp->tv_nsec = 1;
+ }
+ }
+ return error;
+}
+
+int posix_cpu_clock_set(clockid_t which_clock, const struct timespec *tp)
+{
+ /*
+ * You can never reset a CPU clock, but we check for other errors
+ * in the call before failing with EPERM.
+ */
+ int error = check_clock(which_clock);
+ if (error == 0) {
+ error = -EPERM;
+ }
+ return error;
+}
+
+
+/*
+ * Sample a per-thread clock for the given task.
+ */
+static int cpu_clock_sample(clockid_t which_clock, struct task_struct *p,
+ union cpu_time_count *cpu)
+{
+ switch (CPUCLOCK_WHICH(which_clock)) {
+ default:
+ return -EINVAL;
+ case CPUCLOCK_PROF:
+ cpu->cpu = prof_ticks(p);
+ break;
+ case CPUCLOCK_VIRT:
+ cpu->cpu = virt_ticks(p);
+ break;
+ case CPUCLOCK_SCHED:
+ cpu->sched = sched_ns(p);
+ break;
+ }
+ return 0;
+}
+
+/*
+ * Sample a process (thread group) clock for the given group_leader task.
+ * Must be called with tasklist_lock held for reading.
+ * Must be called with tasklist_lock held for reading, and p->sighand->siglock.
+ */
+static int cpu_clock_sample_group_locked(unsigned int clock_idx,
+ struct task_struct *p,
+ union cpu_time_count *cpu)
+{
+ struct task_struct *t = p;
+ switch (clock_idx) {
+ default:
+ return -EINVAL;
+ case CPUCLOCK_PROF:
+ cpu->cpu = cputime_add(p->signal->utime, p->signal->stime);
+ do {
+ cpu->cpu = cputime_add(cpu->cpu, prof_ticks(t));
+ t = next_thread(t);
+ } while (t != p);
+ break;
+ case CPUCLOCK_VIRT:
+ cpu->cpu = p->signal->utime;
+ do {
+ cpu->cpu = cputime_add(cpu->cpu, virt_ticks(t));
+ t = next_thread(t);
+ } while (t != p);
+ break;
+ case CPUCLOCK_SCHED:
+ cpu->sched = p->signal->sched_time;
+ /* Add in each other live thread. */
+ 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;
+ }
+ break;
+ }
+ return 0;
+}
+
+/*
+ * 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,
+ struct task_struct *p,
+ union cpu_time_count *cpu)
+{
+ int ret;
+ unsigned long flags;
+ spin_lock_irqsave(&p->sighand->siglock, flags);
+ ret = cpu_clock_sample_group_locked(CPUCLOCK_WHICH(which_clock), p,
+ cpu);
+ spin_unlock_irqrestore(&p->sighand->siglock, flags);
+ return ret;
+}
+
+
+int posix_cpu_clock_get(clockid_t which_clock, struct timespec *tp)
+{
+ const pid_t pid = CPUCLOCK_PID(which_clock);
+ int error = -EINVAL;
+ union cpu_time_count rtn;
+
+ if (pid == 0) {
+ /*
+ * Special case constant value for our own clocks.
+ * We don't have to do any lookup to find ourselves.
+ */
+ if (CPUCLOCK_PERTHREAD(which_clock)) {
+ /*
+ * Sampling just ourselves we can do with no locking.
+ */
+ error = cpu_clock_sample(which_clock,
+ current, &rtn);
+ } else {
+ read_lock(&tasklist_lock);
+ error = cpu_clock_sample_group(which_clock,
+ current, &rtn);
+ read_unlock(&tasklist_lock);
+ }
+ } else {
+ /*
+ * Find the given PID, and validate that the caller
+ * should be able to see it.
+ */
+ struct task_struct *p;
+ read_lock(&tasklist_lock);
+ p = find_task_by_pid(pid);
+ if (p) {
+ if (CPUCLOCK_PERTHREAD(which_clock)) {
+ if (p->tgid == current->tgid) {
+ error = cpu_clock_sample(which_clock,
+ p, &rtn);
+ }
+ } else if (p->tgid == pid && p->signal) {
+ error = cpu_clock_sample_group(which_clock,
+ p, &rtn);
+ }
+ }
+ read_unlock(&tasklist_lock);
+ }
+
+ if (error)
+ return error;
+ sample_to_timespec(which_clock, rtn, tp);
+ return 0;
+}
+
+
+/*
+ * Validate the clockid_t for a new CPU-clock timer, and initialize the timer.
+ * This is called from sys_timer_create with the new timer already locked.
+ */
+int posix_cpu_timer_create(struct k_itimer *new_timer)
+{
+ int ret = 0;
+ const pid_t pid = CPUCLOCK_PID(new_timer->it_clock);
+ struct task_struct *p;
+
+ if (CPUCLOCK_WHICH(new_timer->it_clock) >= CPUCLOCK_MAX)
+ return -EINVAL;
+
+ INIT_LIST_HEAD(&new_timer->it.cpu.entry);
+ new_timer->it.cpu.incr.sched = 0;
+ new_timer->it.cpu.expires.sched = 0;
+
+ read_lock(&tasklist_lock);
+ if (CPUCLOCK_PERTHREAD(new_timer->it_clock)) {
+ if (pid == 0) {
+ p = current;
+ } else {
+ p = find_task_by_pid(pid);
+ if (p && p->tgid != current->tgid)
+ p = NULL;
+ }
+ } else {
+ if (pid == 0) {
+ p = current->group_leader;
+ } else {
+ p = find_task_by_pid(pid);
+ if (p && p->tgid != pid)
+ p = NULL;
+ }
+ }
+ new_timer->it.cpu.task = p;
+ if (p) {
+ get_task_struct(p);
+ } else {
+ ret = -EINVAL;
+ }
+ read_unlock(&tasklist_lock);
+
+ return ret;
+}
+
+/*
+ * Clean up a CPU-clock timer that is about to be destroyed.
+ * This is called from timer deletion with the timer already locked.
+ * If we return TIMER_RETRY, it's necessary to release the timer's lock
+ * and try again. (This happens when the timer is in the middle of firing.)
+ */
+int posix_cpu_timer_del(struct k_itimer *timer)
+{
+ struct task_struct *p = timer->it.cpu.task;
+
+ if (timer->it.cpu.firing)
+ return TIMER_RETRY;
+
+ if (unlikely(p == NULL))
+ return 0;
+
+ if (!list_empty(&timer->it.cpu.entry)) {
+ read_lock(&tasklist_lock);
+ if (unlikely(p->signal == NULL)) {
+ /*
+ * We raced with the reaping of the task.
+ * The deletion should have cleared us off the list.
+ */
+ BUG_ON(!list_empty(&timer->it.cpu.entry));
+ } else {
+ /*
+ * Take us off the task's timer list.
+ */
+ spin_lock(&p->sighand->siglock);
+ list_del(&timer->it.cpu.entry);
+ spin_unlock(&p->sighand->siglock);
+ }
+ read_unlock(&tasklist_lock);
+ }
+ put_task_struct(p);
+
+ return 0;
+}
+
+/*
+ * Clean out CPU timers still ticking when a thread exited. The task
+ * pointer is cleared, and the expiry time is replaced with the residual
+ * time for later timer_gettime calls to return.
+ * This must be called with the siglock held.
+ */
+static void cleanup_timers(struct list_head *head,
+ cputime_t utime, cputime_t stime,
+ unsigned long long sched_time)
+{
+ struct cpu_timer_list *timer, *next;
+ cputime_t ptime = cputime_add(utime, stime);
+
+ list_for_each_entry_safe(timer, next, head, entry) {
+ timer->task = NULL;
+ list_del_init(&timer->entry);
+ if (cputime_lt(timer->expires.cpu, ptime)) {
+ timer->expires.cpu = cputime_zero;
+ } else {
+ timer->expires.cpu = cputime_sub(timer->expires.cpu,
+ ptime);
+ }
+ }
+
+ ++head;
+ list_for_each_entry_safe(timer, next, head, entry) {
+ timer->task = NULL;
+ list_del_init(&timer->entry);
+ if (cputime_lt(timer->expires.cpu, utime)) {
+ timer->expires.cpu = cputime_zero;
+ } else {
+ timer->expires.cpu = cputime_sub(timer->expires.cpu,
+ utime);
+ }
+ }
+
+ ++head;
+ list_for_each_entry_safe(timer, next, head, entry) {
+ timer->task = NULL;
+ list_del_init(&timer->entry);
+ if (timer->expires.sched < sched_time) {
+ timer->expires.sched = 0;
+ } else {
+ timer->expires.sched -= sched_time;
+ }
+ }
+}
+
+/*
+ * These are both called with the siglock held, when the current thread
+ * is being reaped. When the final (leader) thread in the group is reaped,
+ * posix_cpu_timers_exit_group will be called after posix_cpu_timers_exit.
+ */
+void posix_cpu_timers_exit(struct task_struct *tsk)
+{
+ cleanup_timers(tsk->cpu_timers,
+ tsk->utime, tsk->stime, tsk->sched_time);
+
+}
+void posix_cpu_timers_exit_group(struct task_struct *tsk)
+{
+ cleanup_timers(tsk->signal->cpu_timers,
+ cputime_add(tsk->utime, tsk->signal->utime),
+ cputime_add(tsk->stime, tsk->signal->stime),
+ tsk->sched_time + tsk->signal->sched_time);
+}
+
+
+/*
+ * Set the expiry times of all the threads in the process so one of them
+ * will go off before the process cumulative expiry total is reached.
+ */
+static void process_timer_rebalance(struct task_struct *p,
+ unsigned int clock_idx,
+ union cpu_time_count expires,
+ union cpu_time_count val)
+{
+ cputime_t ticks, left;
+ unsigned long long ns, nsleft;
+ struct task_struct *t = p;
+ unsigned int nthreads = atomic_read(&p->signal->live);
+
+ switch (clock_idx) {
+ default:
+ BUG();
+ break;
+ case CPUCLOCK_PROF:
+ left = cputime_div(cputime_sub(expires.cpu, val.cpu),
+ nthreads);
+ do {
+ if (!unlikely(t->exit_state)) {
+ ticks = cputime_add(prof_ticks(t), left);
+ if (cputime_eq(t->it_prof_expires,
+ cputime_zero) ||
+ cputime_gt(t->it_prof_expires, ticks)) {
+ t->it_prof_expires = ticks;
+ }
+ }
+ t = next_thread(t);
+ } while (t != p);
+ break;
+ case CPUCLOCK_VIRT:
+ left = cputime_div(cputime_sub(expires.cpu, val.cpu),
+ nthreads);
+ do {
+ if (!unlikely(t->exit_state)) {
+ ticks = cputime_add(virt_ticks(t), left);
+ if (cputime_eq(t->it_virt_expires,
+ cputime_zero) ||
+ cputime_gt(t->it_virt_expires, ticks)) {
+ t->it_virt_expires = ticks;
+ }
+ }
+ t = next_thread(t);
+ } while (t != p);
+ break;
+ case CPUCLOCK_SCHED:
+ nsleft = expires.sched - val.sched;
+ do_div(nsleft, nthreads);
+ do {
+ if (!unlikely(t->exit_state)) {
+ ns = t->sched_time + nsleft;
+ if (t->it_sched_expires == 0 ||
+ t->it_sched_expires > ns) {
+ t->it_sched_expires = ns;
+ }
+ }
+ t = next_thread(t);
+ } while (t != p);
+ break;
+ }
+}
+
+static void clear_dead_task(struct k_itimer *timer, union cpu_time_count now)
+{
+ /*
+ * That's all for this thread or process.
+ * We leave our residual in expires to be reported.
+ */
+ put_task_struct(timer->it.cpu.task);
+ timer->it.cpu.task = NULL;
+ timer->it.cpu.expires = cpu_time_sub(timer->it_clock,
+ timer->it.cpu.expires,
+ now);
+}
+
+/*
+ * Insert the timer on the appropriate list before any timers that
+ * expire later. This must be called with the tasklist_lock held
+ * for reading, and interrupts disabled.
+ */
+static void arm_timer(struct k_itimer *timer, union cpu_time_count now)
+{
+ struct task_struct *p = timer->it.cpu.task;
+ struct list_head *head, *listpos;
+ struct cpu_timer_list *const nt = &timer->it.cpu;
+ struct cpu_timer_list *next;
+ unsigned long i;
+
+ head = (CPUCLOCK_PERTHREAD(timer->it_clock) ?
+ p->cpu_timers : p->signal->cpu_timers);
+ head += CPUCLOCK_WHICH(timer->it_clock);
+
+ BUG_ON(!irqs_disabled());
+ spin_lock(&p->sighand->siglock);
+
+ listpos = head;
+ if (CPUCLOCK_WHICH(timer->it_clock) == CPUCLOCK_SCHED) {
+ list_for_each_entry(next, head, entry) {
+ if (next->expires.sched > nt->expires.sched) {
+ listpos = &next->entry;
+ break;
+ }
+ }
+ } else {
+ list_for_each_entry(next, head, entry) {
+ if (cputime_gt(next->expires.cpu, nt->expires.cpu)) {
+ listpos = &next->entry;
+ break;
+ }
+ }
+ }
+ list_add(&nt->entry, listpos);
+
+ if (listpos == head) {
+ /*
+ * We are the new earliest-expiring timer.
+ * If we are a thread timer, there can always
+ * be a process timer telling us to stop earlier.
+ */
+
+ if (CPUCLOCK_PERTHREAD(timer->it_clock)) {
+ switch (CPUCLOCK_WHICH(timer->it_clock)) {
+ default:
+ BUG();
+ case CPUCLOCK_PROF:
+ if (cputime_eq(p->it_prof_expires,
+ cputime_zero) ||
+ cputime_gt(p->it_prof_expires,
+ nt->expires.cpu))
+ p->it_prof_expires = nt->expires.cpu;
+ break;
+ case CPUCLOCK_VIRT:
+ if (cputime_eq(p->it_virt_expires,
+ cputime_zero) ||
+ cputime_gt(p->it_virt_expires,
+ nt->expires.cpu))
+ p->it_virt_expires = nt->expires.cpu;
+ break;
+ case CPUCLOCK_SCHED:
+ if (p->it_sched_expires == 0 ||
+ p->it_sched_expires > nt->expires.sched)
+ p->it_sched_expires = nt->expires.sched;
+ break;
+ }
+ } else {
+ /*
+ * For a process timer, we must balance
+ * all the live threads' expirations.
+ */
+ switch (CPUCLOCK_WHICH(timer->it_clock)) {
+ default:
+ BUG();
+ case CPUCLOCK_VIRT:
+ if (!cputime_eq(p->signal->it_virt_expires,
+ cputime_zero) &&
+ cputime_lt(p->signal->it_virt_expires,
+ timer->it.cpu.expires.cpu))
+ break;
+ goto rebalance;
+ case CPUCLOCK_PROF:
+ if (!cputime_eq(p->signal->it_prof_expires,
+ cputime_zero) &&
+ cputime_lt(p->signal->it_prof_expires,
+ timer->it.cpu.expires.cpu))
+ break;
+ i = p->signal->rlim[RLIMIT_CPU].rlim_cur;
+ if (i != RLIM_INFINITY &&
+ i <= cputime_to_secs(timer->it.cpu.expires.cpu))
+ break;
+ goto rebalance;
+ case CPUCLOCK_SCHED:
+ rebalance:
+ process_timer_rebalance(
+ timer->it.cpu.task,
+ CPUCLOCK_WHICH(timer->it_clock),
+ timer->it.cpu.expires, now);
+ break;
+ }
+ }
+ }
+
+ spin_unlock(&p->sighand->siglock);
+}
+
+/*
+ * The timer is locked, fire it and arrange for its reload.
+ */
+static void cpu_timer_fire(struct k_itimer *timer)
+{
+ if (unlikely(timer->sigq == NULL)) {
+ /*
+ * This a special case for clock_nanosleep,
+ * not a normal timer from sys_timer_create.
+ */
+ wake_up_process(timer->it_process);
+ timer->it.cpu.expires.sched = 0;
+ } else if (timer->it.cpu.incr.sched == 0) {
+ /*
+ * One-shot timer. Clear it as soon as it's fired.
+ */
+ posix_timer_event(timer, 0);
+ timer->it.cpu.expires.sched = 0;
+ } else if (posix_timer_event(timer, ++timer->it_requeue_pending)) {
+ /*
+ * The signal did not get queued because the signal
+ * was ignored, so we won't get any callback to
+ * reload the timer. But we need to keep it
+ * ticking in case the signal is deliverable next time.
+ */
+ posix_cpu_timer_schedule(timer);
+ }
+}
+
+/*
+ * Guts of sys_timer_settime for CPU timers.
+ * This is called with the timer locked and interrupts disabled.
+ * If we return TIMER_RETRY, it's necessary to release the timer's lock
+ * and try again. (This happens when the timer is in the middle of firing.)
+ */
+int posix_cpu_timer_set(struct k_itimer *timer, int flags,
+ struct itimerspec *new, struct itimerspec *old)
+{
+ struct task_struct *p = timer->it.cpu.task;
+ union cpu_time_count old_expires, new_expires, val;
+ int ret;
+
+ if (unlikely(p == NULL)) {
+ /*
+ * Timer refers to a dead task's clock.
+ */
+ return -ESRCH;
+ }
+
+ new_expires = timespec_to_sample(timer->it_clock, &new->it_value);
+
+ read_lock(&tasklist_lock);
+ /*
+ * We need the tasklist_lock to protect against reaping that
+ * clears p->signal. If p has just been reaped, we can no
+ * longer get any information about it at all.
+ */
+ if (unlikely(p->signal == NULL)) {
+ read_unlock(&tasklist_lock);
+ put_task_struct(p);
+ timer->it.cpu.task = NULL;
+ return -ESRCH;
+ }
+
+ /*
+ * Disarm any old timer after extracting its expiry time.
+ */
+ BUG_ON(!irqs_disabled());
+ spin_lock(&p->sighand->siglock);
+ old_expires = timer->it.cpu.expires;
+ list_del_init(&timer->it.cpu.entry);
+ spin_unlock(&p->sighand->siglock);
+
+ /*
+ * We need to sample the current value to convert the new
+ * value from to relative and absolute, and to convert the
+ * old value from absolute to relative. To set a process
+ * timer, we need a sample to balance the thread expiry
+ * times (in arm_timer). With an absolute time, we must
+ * check if it's already passed. In short, we need a sample.
+ */
+ if (CPUCLOCK_PERTHREAD(timer->it_clock)) {
+ cpu_clock_sample(timer->it_clock, p, &val);
+ } else {
+ cpu_clock_sample_group(timer->it_clock, p, &val);
+ }
+
+ if (old) {
+ if (old_expires.sched == 0) {
+ old->it_value.tv_sec = 0;
+ old->it_value.tv_nsec = 0;
+ } else {
+ /*
+ * Update the timer in case it has
+ * overrun already. If it has,
+ * we'll report it as having overrun
+ * and with the next reloaded timer
+ * already ticking, though we are
+ * swallowing that pending
+ * notification here to install the
+ * new setting.
+ */
+ bump_cpu_timer(timer, val);
+ if (cpu_time_before(timer->it_clock, val,
+ timer->it.cpu.expires)) {
+ old_expires = cpu_time_sub(
+ timer->it_clock,
+ timer->it.cpu.expires, val);
+ sample_to_timespec(timer->it_clock,
+ old_expires,
+ &old->it_value);
+ } else {
+ old->it_value.tv_nsec = 1;
+ old->it_value.tv_sec = 0;
+ }
+ }
+ }
+
+ if (unlikely(timer->it.cpu.firing)) {
+ /*
+ * We are colliding with the timer actually firing.
+ * Punt after filling in the timer's old value, and
+ * disable this firing since we are already reporting
+ * it as an overrun (thanks to bump_cpu_timer above).
+ */
+ read_unlock(&tasklist_lock);
+ timer->it.cpu.firing = -1;
+ ret = TIMER_RETRY;
+ goto out;
+ }
+
+ if (new_expires.sched != 0 && !(flags & TIMER_ABSTIME)) {
+ cpu_time_add(timer->it_clock, &new_expires, val);
+ }
+
+ /*
+ * Install the new expiry time (or zero).
+ * For a timer with no notification action, we don't actually
+ * arm the timer (we'll just fake it for timer_gettime).
+ */
+ timer->it.cpu.expires = new_expires;
+ if (new_expires.sched != 0 &&
+ (timer->it_sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE &&
+ cpu_time_before(timer->it_clock, val, new_expires)) {
+ arm_timer(timer, val);
+ }
+
+ read_unlock(&tasklist_lock);
+
+ /*
+ * Install the new reload setting, and
+ * set up the signal and overrun bookkeeping.
+ */
+ timer->it.cpu.incr = timespec_to_sample(timer->it_clock,
+ &new->it_interval);
+
+ /*
+ * This acts as a modification timestamp for the timer,
+ * so any automatic reload attempt will punt on seeing
+ * that we have reset the timer manually.
+ */
+ timer->it_requeue_pending = (timer->it_requeue_pending + 2) &
+ ~REQUEUE_PENDING;
+ timer->it_overrun_last = 0;
+ timer->it_overrun = -1;
+
+ if (new_expires.sched != 0 &&
+ (timer->it_sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE &&
+ !cpu_time_before(timer->it_clock, val, new_expires)) {
+ /*
+ * The designated time already passed, so we notify
+ * immediately, even if the thread never runs to
+ * accumulate more time on this clock.
+ */
+ cpu_timer_fire(timer);
+ }
+
+ ret = 0;
+ out:
+ if (old) {
+ sample_to_timespec(timer->it_clock,
+ timer->it.cpu.incr, &old->it_interval);
+ }
+ return ret;
+}
+
+void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec *itp)
+{
+ union cpu_time_count now;
+ struct task_struct *p = timer->it.cpu.task;
+ int clear_dead;
+
+ /*
+ * Easy part: convert the reload time.
+ */
+ sample_to_timespec(timer->it_clock,
+ timer->it.cpu.incr, &itp->it_interval);
+
+ if (timer->it.cpu.expires.sched == 0) { /* Timer not armed at all. */
+ itp->it_value.tv_sec = itp->it_value.tv_nsec = 0;
+ return;
+ }
+
+ if (unlikely(p == NULL)) {
+ /*
+ * This task already died and the timer will never fire.
+ * In this case, expires is actually the dead value.
+ */
+ dead:
+ sample_to_timespec(timer->it_clock, timer->it.cpu.expires,
+ &itp->it_value);
+ return;
+ }
+
+ /*
+ * Sample the clock to take the difference with the expiry time.
+ */
+ if (CPUCLOCK_PERTHREAD(timer->it_clock)) {
+ cpu_clock_sample(timer->it_clock, p, &now);
+ clear_dead = p->exit_state;
+ } else {
+ read_lock(&tasklist_lock);
+ if (unlikely(p->signal == NULL)) {
+ /*
+ * The process has been reaped.
+ * We can't even collect a sample any more.
+ * Call the timer disarmed, nothing else to do.
+ */
+ put_task_struct(p);
+ timer->it.cpu.task = NULL;
+ timer->it.cpu.expires.sched = 0;
+ read_unlock(&tasklist_lock);
+ goto dead;
+ } else {
+ cpu_clock_sample_group(timer->it_clock, p, &now);
+ clear_dead = (unlikely(p->exit_state) &&
+ thread_group_empty(p));
+ }
+ read_unlock(&tasklist_lock);
+ }
+
+ if ((timer->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE) {
+ if (timer->it.cpu.incr.sched == 0 &&
+ cpu_time_before(timer->it_clock,
+ timer->it.cpu.expires, now)) {
+ /*
+ * Do-nothing timer expired and has no reload,
+ * so it's as if it was never set.
+ */
+ timer->it.cpu.expires.sched = 0;
+ itp->it_value.tv_sec = itp->it_value.tv_nsec = 0;
+ return;
+ }
+ /*
+ * Account for any expirations and reloads that should
+ * have happened.
+ */
+ bump_cpu_timer(timer, now);
+ }
+
+ if (unlikely(clear_dead)) {
+ /*
+ * We've noticed that the thread is dead, but
+ * not yet reaped. Take this opportunity to
+ * drop our task ref.
+ */
+ clear_dead_task(timer, now);
+ goto dead;
+ }
+
+ if (cpu_time_before(timer->it_clock, now, timer->it.cpu.expires)) {
+ sample_to_timespec(timer->it_clock,
+ cpu_time_sub(timer->it_clock,
+ timer->it.cpu.expires, now),
+ &itp->it_value);
+ } else {
+ /*
+ * The timer should have expired already, but the firing
+ * hasn't taken place yet. Say it's just about to expire.
+ */
+ itp->it_value.tv_nsec = 1;
+ itp->it_value.tv_sec = 0;
+ }
+}
+
+/*
+ * Check for any per-thread CPU timers that have fired and move them off
+ * the tsk->cpu_timers[N] list onto the firing list. Here we update the
+ * tsk->it_*_expires values to reflect the remaining thread CPU timers.
+ */
+static void check_thread_timers(struct task_struct *tsk,
+ struct list_head *firing)
+{
+ struct list_head *timers = tsk->cpu_timers;
+
+ tsk->it_prof_expires = cputime_zero;
+ while (!list_empty(timers)) {
+ struct cpu_timer_list *t = list_entry(timers->next,
+ struct cpu_timer_list,
+ entry);
+ if (cputime_lt(prof_ticks(tsk), t->expires.cpu)) {
+ tsk->it_prof_expires = t->expires.cpu;
+ break;
+ }
+ t->firing = 1;
+ list_move_tail(&t->entry, firing);
+ }
+
+ ++timers;
+ tsk->it_virt_expires = cputime_zero;
+ while (!list_empty(timers)) {
+ struct cpu_timer_list *t = list_entry(timers->next,
+ struct cpu_timer_list,
+ entry);
+ if (cputime_lt(virt_ticks(tsk), t->expires.cpu)) {
+ tsk->it_virt_expires = t->expires.cpu;
+ break;
+ }
+ t->firing = 1;
+ list_move_tail(&t->entry, firing);
+ }
+
+ ++timers;
+ tsk->it_sched_expires = 0;
+ while (!list_empty(timers)) {
+ struct cpu_timer_list *t = list_entry(timers->next,
+ struct cpu_timer_list,
+ entry);
+ if (tsk->sched_time < t->expires.sched) {
+ tsk->it_sched_expires = t->expires.sched;
+ break;
+ }
+ t->firing = 1;
+ list_move_tail(&t->entry, firing);
+ }
+}
+
+/*
+ * Check for any per-thread CPU timers that have fired and move them
+ * off the tsk->*_timers list onto the firing list. Per-thread timers
+ * have already been taken off.
+ */
+static void check_process_timers(struct task_struct *tsk,
+ struct list_head *firing)
+{
+ struct signal_struct *const sig = tsk->signal;
+ cputime_t utime, stime, ptime, virt_expires, prof_expires;
+ unsigned long long sched_time, sched_expires;
+ struct task_struct *t;
+ struct list_head *timers = sig->cpu_timers;
+
+ /*
+ * Don't sample the current process CPU clocks if there are no timers.
+ */
+ if (list_empty(&timers[CPUCLOCK_PROF]) &&
+ cputime_eq(sig->it_prof_expires, cputime_zero) &&
+ sig->rlim[RLIMIT_CPU].rlim_cur == RLIM_INFINITY &&
+ list_empty(&timers[CPUCLOCK_VIRT]) &&
+ cputime_eq(sig->it_virt_expires, cputime_zero) &&
+ list_empty(&timers[CPUCLOCK_SCHED]))
+ return;
+
+ /*
+ * Collect the current process totals.
+ */
+ utime = sig->utime;
+ stime = sig->stime;
+ sched_time = sig->sched_time;
+ t = tsk;
+ do {
+ utime = cputime_add(utime, t->utime);
+ stime = cputime_add(stime, t->stime);
+ sched_time += t->sched_time;
+ t = next_thread(t);
+ } while (t != tsk);
+ ptime = cputime_add(utime, stime);
+
+ prof_expires = cputime_zero;
+ while (!list_empty(timers)) {
+ struct cpu_timer_list *t = list_entry(timers->next,
+ struct cpu_timer_list,
+ entry);
+ if (cputime_lt(ptime, t->expires.cpu)) {
+ prof_expires = t->expires.cpu;
+ break;
+ }
+ t->firing = 1;
+ list_move_tail(&t->entry, firing);
+ }
+
+ ++timers;
+ virt_expires = cputime_zero;
+ while (!list_empty(timers)) {
+ struct cpu_timer_list *t = list_entry(timers->next,
+ struct cpu_timer_list,
+ entry);
+ if (cputime_lt(utime, t->expires.cpu)) {
+ virt_expires = t->expires.cpu;
+ break;
+ }
+ t->firing = 1;
+ list_move_tail(&t->entry, firing);
+ }
+
+ ++timers;
+ sched_expires = 0;
+ while (!list_empty(timers)) {
+ struct cpu_timer_list *t = list_entry(timers->next,
+ struct cpu_timer_list,
+ entry);
+ if (sched_time < t->expires.sched) {
+ sched_expires = t->expires.sched;
+ break;
+ }
+ t->firing = 1;
+ list_move_tail(&t->entry, firing);
+ }
+
+ /*
+ * Check for the special case process timers.
+ */
+ if (!cputime_eq(sig->it_prof_expires, cputime_zero)) {
+ if (cputime_ge(ptime, sig->it_prof_expires)) {
+ /* ITIMER_PROF fires and reloads. */
+ sig->it_prof_expires = sig->it_prof_incr;
+ if (!cputime_eq(sig->it_prof_expires, cputime_zero)) {
+ sig->it_prof_expires = cputime_add(
+ sig->it_prof_expires, ptime);
+ }
+ __group_send_sig_info(SIGPROF, SEND_SIG_PRIV, tsk);
+ }
+ if (!cputime_eq(sig->it_prof_expires, cputime_zero) &&
+ (cputime_eq(prof_expires, cputime_zero) ||
+ cputime_lt(sig->it_prof_expires, prof_expires))) {
+ prof_expires = sig->it_prof_expires;
+ }
+ }
+ if (!cputime_eq(sig->it_virt_expires, cputime_zero)) {
+ if (cputime_ge(utime, sig->it_virt_expires)) {
+ /* ITIMER_VIRTUAL fires and reloads. */
+ sig->it_virt_expires = sig->it_virt_incr;
+ if (!cputime_eq(sig->it_virt_expires, cputime_zero)) {
+ sig->it_virt_expires = cputime_add(
+ sig->it_virt_expires, utime);
+ }
+ __group_send_sig_info(SIGVTALRM, SEND_SIG_PRIV, tsk);
+ }
+ if (!cputime_eq(sig->it_virt_expires, cputime_zero) &&
+ (cputime_eq(virt_expires, cputime_zero) ||
+ cputime_lt(sig->it_virt_expires, virt_expires))) {
+ virt_expires = sig->it_virt_expires;
+ }
+ }
+ if (sig->rlim[RLIMIT_CPU].rlim_cur != RLIM_INFINITY) {
+ unsigned long psecs = cputime_to_secs(ptime);
+ cputime_t x;
+ if (psecs >= sig->rlim[RLIMIT_CPU].rlim_max) {
+ /*
+ * At the hard limit, we just die.
+ * No need to calculate anything else now.
+ */
+ __group_send_sig_info(SIGKILL, SEND_SIG_PRIV, tsk);
+ return;
+ }
+ if (psecs >= sig->rlim[RLIMIT_CPU].rlim_cur) {
+ /*
+ * At the soft limit, send a SIGXCPU every second.
+ */
+ __group_send_sig_info(SIGXCPU, SEND_SIG_PRIV, tsk);
+ if (sig->rlim[RLIMIT_CPU].rlim_cur
+ < sig->rlim[RLIMIT_CPU].rlim_max) {
+ sig->rlim[RLIMIT_CPU].rlim_cur++;
+ }
+ }
+ x = secs_to_cputime(sig->rlim[RLIMIT_CPU].rlim_cur);
+ if (cputime_eq(prof_expires, cputime_zero) ||
+ cputime_lt(x, prof_expires)) {
+ prof_expires = x;
+ }
+ }
+
+ if (!cputime_eq(prof_expires, cputime_zero) ||
+ !cputime_eq(virt_expires, cputime_zero) ||
+ sched_expires != 0) {
+ /*
+ * Rebalance the threads' expiry times for the remaining
+ * process CPU timers.
+ */
+
+ cputime_t prof_left, virt_left, ticks;
+ unsigned long long sched_left, sched;
+ const unsigned int nthreads = atomic_read(&sig->live);
+
+ prof_left = cputime_sub(prof_expires, utime);
+ prof_left = cputime_sub(prof_left, stime);
+ prof_left = cputime_div(prof_left, nthreads);
+ virt_left = cputime_sub(virt_expires, utime);
+ virt_left = cputime_div(virt_left, nthreads);
+ if (sched_expires) {
+ sched_left = sched_expires - sched_time;
+ do_div(sched_left, nthreads);
+ } else {
+ sched_left = 0;
+ }
+ t = tsk;
+ do {
+ ticks = cputime_add(cputime_add(t->utime, t->stime),
+ prof_left);
+ if (!cputime_eq(prof_expires, cputime_zero) &&
+ (cputime_eq(t->it_prof_expires, cputime_zero) ||
+ cputime_gt(t->it_prof_expires, ticks))) {
+ t->it_prof_expires = ticks;
+ }
+
+ ticks = cputime_add(t->utime, virt_left);
+ if (!cputime_eq(virt_expires, cputime_zero) &&
+ (cputime_eq(t->it_virt_expires, cputime_zero) ||
+ cputime_gt(t->it_virt_expires, ticks))) {
+ t->it_virt_expires = ticks;
+ }
+
+ sched = t->sched_time + sched_left;
+ if (sched_expires && (t->it_sched_expires == 0 ||
+ t->it_sched_expires > sched)) {
+ t->it_sched_expires = sched;
+ }
+
+ do {
+ t = next_thread(t);
+ } while (unlikely(t->exit_state));
+ } while (t != tsk);
+ }
+}
+
+/*
+ * This is called from the signal code (via do_schedule_next_timer)
+ * when the last timer signal was delivered and we have to reload the timer.
+ */
+void posix_cpu_timer_schedule(struct k_itimer *timer)
+{
+ struct task_struct *p = timer->it.cpu.task;
+ union cpu_time_count now;
+
+ if (unlikely(p == NULL))
+ /*
+ * The task was cleaned up already, no future firings.
+ */
+ return;
+
+ /*
+ * Fetch the current sample and update the timer's expiry time.
+ */
+ if (CPUCLOCK_PERTHREAD(timer->it_clock)) {
+ cpu_clock_sample(timer->it_clock, p, &now);
+ bump_cpu_timer(timer, now);
+ if (unlikely(p->exit_state)) {
+ clear_dead_task(timer, now);
+ return;
+ }
+ read_lock(&tasklist_lock); /* arm_timer needs it. */
+ } else {
+ read_lock(&tasklist_lock);
+ if (unlikely(p->signal == NULL)) {
+ /*
+ * The process has been reaped.
+ * We can't even collect a sample any more.
+ */
+ put_task_struct(p);
+ timer->it.cpu.task = p = NULL;
+ timer->it.cpu.expires.sched = 0;
+ read_unlock(&tasklist_lock);
+ return;
+ } else if (unlikely(p->exit_state) && thread_group_empty(p)) {
+ /*
+ * We've noticed that the thread is dead, but
+ * not yet reaped. Take this opportunity to
+ * drop our task ref.
+ */
+ clear_dead_task(timer, now);
+ read_unlock(&tasklist_lock);
+ return;
+ }
+ cpu_clock_sample_group(timer->it_clock, p, &now);
+ bump_cpu_timer(timer, now);
+ /* Leave the tasklist_lock locked for the call below. */
+ }
+
+ /*
+ * Now re-arm for the new expiry time.
+ */
+ arm_timer(timer, now);
+
+ read_unlock(&tasklist_lock);
+}
+
+/*
+ * This is called from the timer interrupt handler. The irq handler has
+ * already updated our counts. We need to check if any timers fire now.
+ * Interrupts are disabled.
+ */
+void run_posix_cpu_timers(struct task_struct *tsk)
+{
+ LIST_HEAD(firing);
+ struct k_itimer *timer, *next;
+
+ BUG_ON(!irqs_disabled());
+
+#define UNEXPIRED(clock) \
+ (cputime_eq(tsk->it_##clock##_expires, cputime_zero) || \
+ cputime_lt(clock##_ticks(tsk), tsk->it_##clock##_expires))
+
+ if (UNEXPIRED(prof) && UNEXPIRED(virt) &&
+ (tsk->it_sched_expires == 0 ||
+ tsk->sched_time < tsk->it_sched_expires))
+ return;
+
+#undef UNEXPIRED
+
+ BUG_ON(tsk->exit_state);
+
+ /*
+ * Double-check with locks held.
+ */
+ read_lock(&tasklist_lock);
+ spin_lock(&tsk->sighand->siglock);
+
+ /*
+ * Here we take off tsk->cpu_timers[N] and tsk->signal->cpu_timers[N]
+ * all the timers that are firing, and put them on the firing list.
+ */
+ check_thread_timers(tsk, &firing);
+ check_process_timers(tsk, &firing);
+
+ /*
+ * We must release these locks before taking any timer's lock.
+ * There is a potential race with timer deletion here, as the
+ * siglock now protects our private firing list. We have set
+ * the firing flag in each timer, so that a deletion attempt
+ * that gets the timer lock before we do will give it up and
+ * spin until we've taken care of that timer below.
+ */
+ spin_unlock(&tsk->sighand->siglock);
+ read_unlock(&tasklist_lock);
+
+ /*
+ * Now that all the timers on our list have the firing flag,
+ * noone will touch their list entries but us. We'll take
+ * each timer's lock before clearing its firing flag, so no
+ * timer call will interfere.
+ */
+ list_for_each_entry_safe(timer, next, &firing, it.cpu.entry) {
+ int firing;
+ spin_lock(&timer->it_lock);
+ list_del_init(&timer->it.cpu.entry);
+ firing = timer->it.cpu.firing;
+ timer->it.cpu.firing = 0;
+ /*
+ * The firing flag is -1 if we collided with a reset
+ * of the timer, which already reported this
+ * almost-firing as an overrun. So don't generate an event.
+ */
+ if (likely(firing >= 0)) {
+ cpu_timer_fire(timer);
+ }
+ spin_unlock(&timer->it_lock);
+ }
+}
+
+/*
+ * Set one of the process-wide special case CPU timers.
+ * The tasklist_lock and tsk->sighand->siglock must be held by the caller.
+ * The oldval argument is null for the RLIMIT_CPU timer, where *newval is
+ * absolute; non-null for ITIMER_*, where *newval is relative and we update
+ * it to be absolute, *oldval is absolute and we update it to be relative.
+ */
+void set_process_cpu_timer(struct task_struct *tsk, unsigned int clock_idx,
+ cputime_t *newval, cputime_t *oldval)
+{
+ union cpu_time_count now;
+ struct list_head *head;
+
+ BUG_ON(clock_idx == CPUCLOCK_SCHED);
+ cpu_clock_sample_group_locked(clock_idx, tsk, &now);
+
+ if (oldval) {
+ if (!cputime_eq(*oldval, cputime_zero)) {
+ if (cputime_le(*oldval, now.cpu)) {
+ /* Just about to fire. */
+ *oldval = jiffies_to_cputime(1);
+ } else {
+ *oldval = cputime_sub(*oldval, now.cpu);
+ }
+ }
+
+ if (cputime_eq(*newval, cputime_zero))
+ return;
+ *newval = cputime_add(*newval, now.cpu);
+
+ /*
+ * If the RLIMIT_CPU timer will expire before the
+ * ITIMER_PROF timer, we have nothing else to do.
+ */
+ if (tsk->signal->rlim[RLIMIT_CPU].rlim_cur
+ < cputime_to_secs(*newval))
+ return;
+ }
+
+ /*
+ * Check whether there are any process timers already set to fire
+ * before this one. If so, we don't have anything more to do.
+ */
+ head = &tsk->signal->cpu_timers[clock_idx];
+ if (list_empty(head) ||
+ cputime_ge(list_entry(head->next,
+ struct cpu_timer_list, entry)->expires.cpu,
+ *newval)) {
+ /*
+ * Rejigger each thread's expiry time so that one will
+ * notice before we hit the process-cumulative expiry time.
+ */
+ union cpu_time_count expires = { .sched = 0 };
+ expires.cpu = *newval;
+ process_timer_rebalance(tsk, clock_idx, expires, now);
+ }
+}
+
+static long posix_cpu_clock_nanosleep_restart(struct restart_block *);
+
+int posix_cpu_nsleep(clockid_t which_clock, int flags,
+ struct timespec *rqtp)
+{
+ struct restart_block *restart_block =
+ &current_thread_info()->restart_block;
+ struct k_itimer timer;
+ int error;
+
+ /*
+ * Diagnose required errors first.
+ */
+ if (CPUCLOCK_PERTHREAD(which_clock) &&
+ (CPUCLOCK_PID(which_clock) == 0 ||
+ CPUCLOCK_PID(which_clock) == current->pid))
+ return -EINVAL;
+
+ /*
+ * Set up a temporary timer and then wait for it to go off.
+ */
+ memset(&timer, 0, sizeof timer);
+ spin_lock_init(&timer.it_lock);
+ timer.it_clock = which_clock;
+ timer.it_overrun = -1;
+ 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 = {} };
+
+ spin_lock_irq(&timer.it_lock);
+ error = posix_cpu_timer_set(&timer, flags, &it, NULL);
+ if (error) {
+ spin_unlock_irq(&timer.it_lock);
+ return error;
+ }
+
+ while (!signal_pending(current)) {
+ if (timer.it.cpu.expires.sched == 0) {
+ /*
+ * Our timer fired and was reset.
+ */
+ spin_unlock_irq(&timer.it_lock);
+ return 0;
+ }
+
+ /*
+ * Block until cpu_timer_fire (or a signal) wakes us.
+ */
+ __set_current_state(TASK_INTERRUPTIBLE);
+ spin_unlock_irq(&timer.it_lock);
+ schedule();
+ spin_lock_irq(&timer.it_lock);
+ }
+
+ /*
+ * We were interrupted by a signal.
+ */
+ sample_to_timespec(which_clock, timer.it.cpu.expires, rqtp);
+ posix_cpu_timer_set(&timer, 0, &zero_it, &it);
+ spin_unlock_irq(&timer.it_lock);
+
+ if ((it.it_value.tv_sec | it.it_value.tv_nsec) == 0) {
+ /*
+ * It actually did fire already.
+ */
+ return 0;
+ }
+
+ /*
+ * 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;
+
+ restart_block->fn = posix_cpu_clock_nanosleep_restart;
+ /* Caller already set restart_block->arg1 */
+ restart_block->arg0 = which_clock;
+ restart_block->arg2 = rqtp->tv_sec;
+ restart_block->arg3 = rqtp->tv_nsec;
+
+ error = -ERESTART_RESTARTBLOCK;
+ }
+
+ return error;
+}
+
+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 };
+ restart_block->fn = do_no_restart_syscall;
+ return posix_cpu_nsleep(which_clock, TIMER_ABSTIME, &t);
+}
+
+
+#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)
+{
+ return posix_cpu_clock_getres(PROCESS_CLOCK, tp);
+}
+static int process_cpu_clock_get(clockid_t which_clock, struct timespec *tp)
+{
+ return posix_cpu_clock_get(PROCESS_CLOCK, tp);
+}
+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)
+{
+ return posix_cpu_nsleep(PROCESS_CLOCK, flags, rqtp);
+}
+static int thread_cpu_clock_getres(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)
+{
+ return posix_cpu_clock_get(THREAD_CLOCK, tp);
+}
+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)
+{
+ return -EINVAL;
+}
+
+static __init int init_posix_cpu_timers(void)
+{
+ struct k_clock process = {
+ .clock_getres = process_cpu_clock_getres,
+ .clock_get = process_cpu_clock_get,
+ .clock_set = do_posix_clock_nosettime,
+ .timer_create = process_cpu_timer_create,
+ .nsleep = process_cpu_nsleep,
+ };
+ struct k_clock thread = {
+ .clock_getres = thread_cpu_clock_getres,
+ .clock_get = thread_cpu_clock_get,
+ .clock_set = do_posix_clock_nosettime,
+ .timer_create = thread_cpu_timer_create,
+ .nsleep = thread_cpu_nsleep,
+ };
+
+ register_posix_clock(CLOCK_PROCESS_CPUTIME_ID, &process);
+ register_posix_clock(CLOCK_THREAD_CPUTIME_ID, &thread);
+
+ return 0;
+}
+__initcall(init_posix_cpu_timers);
diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c
index 9e79eca513ca7..fd316c2722604 100644
--- a/kernel/posix-timers.c
+++ b/kernel/posix-timers.c
@@ -46,6 +46,7 @@
#include <linux/syscalls.h>
#include <linux/wait.h>
#include <linux/workqueue.h>
+#include <linux/module.h>
#ifndef div_long_long_rem
#include <asm/div64.h>
@@ -92,14 +93,13 @@ static DEFINE_SPINLOCK(idr_lock);
* inactive. It could be in the "fire" routine getting a new expire time.
*/
#define TIMER_INACTIVE 1
-#define TIMER_RETRY 1
#ifdef CONFIG_SMP
# define timer_active(tmr) \
- ((tmr)->it_timer.entry.prev != (void *)TIMER_INACTIVE)
+ ((tmr)->it.real.timer.entry.prev != (void *)TIMER_INACTIVE)
# define set_timer_inactive(tmr) \
do { \
- (tmr)->it_timer.entry.prev = (void *)TIMER_INACTIVE; \
+ (tmr)->it.real.timer.entry.prev = (void *)TIMER_INACTIVE; \
} while (0)
#else
# define timer_active(tmr) BARFY // error to use outside of SMP
@@ -115,7 +115,6 @@ static DEFINE_SPINLOCK(idr_lock);
#endif
-#define REQUEUE_PENDING 1
/*
* The timer ID is turned into a timer address by idr_find().
* Verifying a valid ID consists of:
@@ -173,22 +172,12 @@ static struct k_clock posix_clocks[MAX_CLOCKS];
static struct k_clock_abs abs_list = {.list = LIST_HEAD_INIT(abs_list.list),
.lock = SPIN_LOCK_UNLOCKED};
-#define if_clock_do(clock_fun,alt_fun,parms) \
- (!clock_fun) ? alt_fun parms : clock_fun parms
-
-#define p_timer_get(clock,a,b) \
- if_clock_do((clock)->timer_get,do_timer_gettime, (a,b))
-
-#define p_nsleep(clock,a,b,c) \
- if_clock_do((clock)->nsleep, do_nsleep, (a,b,c))
-
-#define p_timer_del(clock,a) \
- if_clock_do((clock)->timer_del, do_timer_delete, (a))
-
-static int do_posix_gettime(struct k_clock *clock, struct timespec *tp);
+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 struct k_itimer *lock_timer(timer_t timer_id, unsigned long *flags);
static inline void unlock_timer(struct k_itimer *timr, unsigned long flags)
@@ -197,6 +186,79 @@ static inline void unlock_timer(struct k_itimer *timr, unsigned long flags)
}
/*
+ * Call the k_clock hook function if non-null, or the default function.
+ */
+#define CLOCK_DISPATCH(clock, call, arglist) \
+ ((clock) < 0 ? posix_cpu_##call arglist : \
+ (posix_clocks[clock].call != NULL \
+ ? (*posix_clocks[clock].call) arglist : common_##call arglist))
+
+/*
+ * Default clock hook functions when the struct k_clock passed
+ * to register_posix_clock leaves a function pointer null.
+ *
+ * The function common_CALL is the default implementation for
+ * the function pointer CALL in struct k_clock.
+ */
+
+static inline int common_clock_getres(clockid_t which_clock,
+ struct timespec *tp)
+{
+ tp->tv_sec = 0;
+ tp->tv_nsec = posix_clocks[which_clock].res;
+ return 0;
+}
+
+static inline int common_clock_get(clockid_t which_clock, struct timespec *tp)
+{
+ getnstimeofday(tp);
+ return 0;
+}
+
+static inline int common_clock_set(clockid_t which_clock, struct timespec *tp)
+{
+ return do_sys_settimeofday(tp, NULL);
+}
+
+static inline 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;
+ new_timer->it.real.timer.function = posix_timer_fn;
+ set_timer_inactive(new_timer);
+ 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.
+ */
+static inline int invalid_clockid(clockid_t which_clock)
+{
+ if (which_clock < 0) /* CPU clock, posix_cpu_* will check it */
+ return 0;
+ if ((unsigned) which_clock >= MAX_CLOCKS)
+ 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;
+}
+
+
+/*
* Initialize everything, well, just everything in Posix clocks/timers ;)
*/
static __init int init_posix_timers(void)
@@ -206,7 +268,7 @@ static __init int init_posix_timers(void)
};
struct k_clock clock_monotonic = {.res = CLOCK_REALTIME_RES,
.abs_struct = NULL,
- .clock_get = do_posix_clock_monotonic_gettime,
+ .clock_get = do_posix_clock_monotonic_get,
.clock_set = do_posix_clock_nosettime
};
@@ -263,9 +325,9 @@ static long add_clockset_delta(struct k_itimer *timr,
set_normalized_timespec(&delta,
new_wall_to->tv_sec -
- timr->wall_to_prev.tv_sec,
+ timr->it.real.wall_to_prev.tv_sec,
new_wall_to->tv_nsec -
- timr->wall_to_prev.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) {
@@ -276,16 +338,16 @@ static long add_clockset_delta(struct k_itimer *timr,
sign++;
}
tstojiffie(&delta, posix_clocks[timr->it_clock].res, &exp);
- timr->wall_to_prev = *new_wall_to;
- timr->it_timer.expires += (sign ? -exp : 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->abs_timer_entry)) {
+ if (!list_empty(&timr->it.real.abs_timer_entry)) {
spin_lock(&abs_list.lock);
- list_del_init(&timr->abs_timer_entry);
+ list_del_init(&timr->it.real.abs_timer_entry);
spin_unlock(&abs_list.lock);
}
}
@@ -299,7 +361,7 @@ static void schedule_next_timer(struct k_itimer *timr)
/*
* Set up the timer for the next interval (if there is one).
* Note: this code uses the abs_timer_lock to protect
- * wall_to_prev and must hold it until exp is set, not exactly
+ * it.real.wall_to_prev and must hold it until exp is set, not exactly
* obvious...
* This function is used for CLOCK_REALTIME* and
@@ -309,7 +371,7 @@ static void schedule_next_timer(struct k_itimer *timr)
* "other" CLOCKs "next timer" code (which, I suppose should
* also be added to the k_clock structure).
*/
- if (!timr->it_incr)
+ if (!timr->it.real.incr)
return;
do {
@@ -318,7 +380,7 @@ static void schedule_next_timer(struct k_itimer *timr)
posix_get_now(&now);
} while (read_seqretry(&xtime_lock, seq));
- if (!list_empty(&timr->abs_timer_entry)) {
+ if (!list_empty(&timr->it.real.abs_timer_entry)) {
spin_lock(&abs_list.lock);
add_clockset_delta(timr, &new_wall_to);
@@ -331,7 +393,7 @@ static void schedule_next_timer(struct k_itimer *timr)
timr->it_overrun_last = timr->it_overrun;
timr->it_overrun = -1;
++timr->it_requeue_pending;
- add_timer(&timr->it_timer);
+ add_timer(&timr->it.real.timer);
}
/*
@@ -355,7 +417,10 @@ void do_schedule_next_timer(struct siginfo *info)
if (!timr || timr->it_requeue_pending != info->si_sys_private)
goto exit;
- 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)
@@ -396,6 +461,7 @@ int posix_timer_event(struct k_itimer *timr,int si_private)
timr->it_process);
}
}
+EXPORT_SYMBOL_GPL(posix_timer_event);
/*
* This function gets called when a POSIX.1b interval timer expires. It
@@ -415,7 +481,7 @@ static void posix_timer_fn(unsigned long __data)
spin_lock_irqsave(&timr->it_lock, flags);
set_timer_inactive(timr);
- if (!list_empty(&timr->abs_timer_entry)) {
+ if (!list_empty(&timr->it.real.abs_timer_entry)) {
spin_lock(&abs_list.lock);
do {
seq = read_seqbegin(&xtime_lock);
@@ -423,9 +489,9 @@ static void posix_timer_fn(unsigned long __data)
} while (read_seqretry(&xtime_lock, seq));
set_normalized_timespec(&delta,
new_wall_to.tv_sec -
- timr->wall_to_prev.tv_sec,
+ timr->it.real.wall_to_prev.tv_sec,
new_wall_to.tv_nsec -
- timr->wall_to_prev.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) {
@@ -435,9 +501,9 @@ static void posix_timer_fn(unsigned long __data)
tstojiffie(&delta,
posix_clocks[timr->it_clock].res,
&exp);
- timr->wall_to_prev = new_wall_to;
- timr->it_timer.expires += exp;
- add_timer(&timr->it_timer);
+ 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);
@@ -446,7 +512,7 @@ static void posix_timer_fn(unsigned long __data)
if (do_notify) {
int si_private=0;
- if (timr->it_incr)
+ if (timr->it.real.incr)
si_private = ++timr->it_requeue_pending;
else {
remove_from_abslist(timr);
@@ -481,15 +547,17 @@ static inline struct task_struct * good_sigevent(sigevent_t * event)
return rtn;
}
-void register_posix_clock(int clock_id, struct k_clock *new_clock)
+void register_posix_clock(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",
clock_id);
return;
}
+
posix_clocks[clock_id] = *new_clock;
}
+EXPORT_SYMBOL_GPL(register_posix_clock);
static struct k_itimer * alloc_posix_timer(void)
{
@@ -498,7 +566,6 @@ static struct k_itimer * alloc_posix_timer(void)
if (!tmr)
return tmr;
memset(tmr, 0, sizeof (struct k_itimer));
- INIT_LIST_HEAD(&tmr->abs_timer_entry);
if (unlikely(!(tmr->sigq = sigqueue_alloc()))) {
kmem_cache_free(posix_timers_cache, tmr);
tmr = NULL;
@@ -538,8 +605,7 @@ sys_timer_create(clockid_t which_clock,
sigevent_t event;
int it_id_set = IT_ID_NOT_SET;
- if ((unsigned) which_clock >= MAX_CLOCKS ||
- !posix_clocks[which_clock].res)
+ if (invalid_clockid(which_clock))
return -EINVAL;
new_timer = alloc_posix_timer();
@@ -571,19 +637,10 @@ sys_timer_create(clockid_t which_clock,
it_id_set = IT_ID_SET;
new_timer->it_id = (timer_t) new_timer_id;
new_timer->it_clock = which_clock;
- new_timer->it_incr = 0;
new_timer->it_overrun = -1;
- if (posix_clocks[which_clock].timer_create) {
- error = posix_clocks[which_clock].timer_create(new_timer);
- if (error)
- goto out;
- } else {
- init_timer(&new_timer->it_timer);
- new_timer->it_timer.expires = 0;
- new_timer->it_timer.data = (unsigned long) new_timer;
- new_timer->it_timer.function = posix_timer_fn;
- set_timer_inactive(new_timer);
- }
+ error = CLOCK_DISPATCH(which_clock, timer_create, (new_timer));
+ if (error)
+ goto out;
/*
* return the timer_id now. The next step is hard to
@@ -734,36 +791,36 @@ static struct k_itimer * lock_timer(timer_t timer_id, unsigned long *flags)
* report.
*/
static void
-do_timer_gettime(struct k_itimer *timr, struct itimerspec *cur_setting)
+common_timer_get(struct k_itimer *timr, struct itimerspec *cur_setting)
{
unsigned long expires;
struct now_struct now;
do
- expires = timr->it_timer.expires;
- while ((volatile long) (timr->it_timer.expires) != expires);
+ 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_incr &&
- posix_time_before(&timr->it_timer, &now))
- timr->it_timer.expires = expires = 0;
+ !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_timer.expires;
+ expires = timr->it.real.timer.expires;
}
else
- if (!timer_pending(&timr->it_timer))
+ 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_incr, &cur_setting->it_interval);
+ jiffies_to_timespec(timr->it.real.incr, &cur_setting->it_interval);
if (cur_setting->it_value.tv_sec < 0) {
cur_setting->it_value.tv_nsec = 1;
@@ -783,7 +840,7 @@ sys_timer_gettime(timer_t timer_id, struct itimerspec __user *setting)
if (!timr)
return -EINVAL;
- p_timer_get(&posix_clocks[timr->it_clock], timr, &cur_setting);
+ CLOCK_DISPATCH(timr->it_clock, timer_get, (timr, &cur_setting));
unlock_timer(timr, flags);
@@ -854,7 +911,7 @@ static int adjust_abs_time(struct k_clock *clock, struct timespec *tp,
/*
* Not one of the basic clocks
*/
- do_posix_gettime(clock, &now);
+ clock->clock_get(clock - posix_clocks, &now);
jiffies_64_f = get_jiffies_64();
}
/*
@@ -881,6 +938,10 @@ static int adjust_abs_time(struct k_clock *clock, struct timespec *tp,
*/
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);
/*
@@ -907,23 +968,23 @@ static int adjust_abs_time(struct k_clock *clock, struct timespec *tp,
/* Set a POSIX.1b interval timer. */
/* timr->it_lock is taken. */
static inline int
-do_timer_settime(struct k_itimer *timr, int flags,
+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;
if (old_setting)
- do_timer_gettime(timr, old_setting);
+ common_timer_get(timr, old_setting);
/* disable the timer */
- timr->it_incr = 0;
+ timr->it.real.incr = 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.
*/
#ifdef CONFIG_SMP
- if (timer_active(timr) && !del_timer(&timr->it_timer))
+ if (timer_active(timr) && !del_timer(&timr->it.real.timer))
/*
* It can only be active if on an other cpu. Since
* we have cleared the interval stuff above, it should
@@ -936,7 +997,7 @@ do_timer_settime(struct k_itimer *timr, int flags,
set_timer_inactive(timr);
#else
- del_timer(&timr->it_timer);
+ del_timer(&timr->it.real.timer);
#endif
remove_from_abslist(timr);
@@ -948,29 +1009,29 @@ do_timer_settime(struct k_itimer *timr, int flags,
*switch off the timer when it_value is zero
*/
if (!new_setting->it_value.tv_sec && !new_setting->it_value.tv_nsec) {
- timr->it_timer.expires = 0;
+ timr->it.real.timer.expires = 0;
return 0;
}
if (adjust_abs_time(clock,
&new_setting->it_value, flags & TIMER_ABSTIME,
- &expire_64, &(timr->wall_to_prev))) {
+ &expire_64, &(timr->it.real.wall_to_prev))) {
return -EINVAL;
}
- timr->it_timer.expires = (unsigned long)expire_64;
+ timr->it.real.timer.expires = (unsigned long)expire_64;
tstojiffie(&new_setting->it_interval, clock->res, &expire_64);
- timr->it_incr = (unsigned long)expire_64;
+ timr->it.real.incr = (unsigned long)expire_64;
/*
* We do not even queue SIGEV_NONE timers! But we do put them
* in the abs list so we can do that right.
*/
if (((timr->it_sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE))
- add_timer(&timr->it_timer);
+ add_timer(&timr->it.real.timer);
if (flags & TIMER_ABSTIME && clock->abs_struct) {
spin_lock(&clock->abs_struct->lock);
- list_add_tail(&(timr->abs_timer_entry),
+ list_add_tail(&(timr->it.real.abs_timer_entry),
&(clock->abs_struct->list));
spin_unlock(&clock->abs_struct->lock);
}
@@ -1003,12 +1064,9 @@ retry:
if (!timr)
return -EINVAL;
- if (!posix_clocks[timr->it_clock].timer_set)
- error = do_timer_settime(timr, flags, &new_spec, rtn);
- else
- error = posix_clocks[timr->it_clock].timer_set(timr,
- flags,
- &new_spec, rtn);
+ error = CLOCK_DISPATCH(timr->it_clock, timer_set,
+ (timr, flags, &new_spec, rtn));
+
unlock_timer(timr, flag);
if (error == TIMER_RETRY) {
rtn = NULL; // We already got the old time...
@@ -1022,11 +1080,11 @@ retry:
return error;
}
-static inline int do_timer_delete(struct k_itimer *timer)
+static inline int common_timer_del(struct k_itimer *timer)
{
- timer->it_incr = 0;
+ timer->it.real.incr = 0;
#ifdef CONFIG_SMP
- if (timer_active(timer) && !del_timer(&timer->it_timer))
+ if (timer_active(timer) && !del_timer(&timer->it.real.timer))
/*
* It can only be active if on an other cpu. Since
* we have cleared the interval stuff above, it should
@@ -1037,13 +1095,18 @@ static inline int do_timer_delete(struct k_itimer *timer)
*/
return TIMER_RETRY;
#else
- del_timer(&timer->it_timer);
+ del_timer(&timer->it.real.timer);
#endif
remove_from_abslist(timer);
return 0;
}
+static inline int timer_delete_hook(struct k_itimer *timer)
+{
+ return CLOCK_DISPATCH(timer->it_clock, timer_del, (timer));
+}
+
/* Delete a POSIX.1b interval timer. */
asmlinkage long
sys_timer_delete(timer_t timer_id)
@@ -1060,14 +1123,14 @@ retry_delete:
return -EINVAL;
#ifdef CONFIG_SMP
- error = p_timer_del(&posix_clocks[timer->it_clock], timer);
+ error = timer_delete_hook(timer);
if (error == TIMER_RETRY) {
unlock_timer(timer, flags);
goto retry_delete;
}
#else
- p_timer_del(&posix_clocks[timer->it_clock], timer);
+ timer_delete_hook(timer);
#endif
spin_lock(&current->sighand->siglock);
list_del(&timer->list);
@@ -1099,14 +1162,14 @@ retry_delete:
spin_lock_irqsave(&timer->it_lock, flags);
#ifdef CONFIG_SMP
- error = p_timer_del(&posix_clocks[timer->it_clock], timer);
+ error = timer_delete_hook(timer);
if (error == TIMER_RETRY) {
unlock_timer(timer, flags);
goto retry_delete;
}
#else
- p_timer_del(&posix_clocks[timer->it_clock], timer);
+ timer_delete_hook(timer);
#endif
list_del(&timer->list);
/*
@@ -1143,14 +1206,6 @@ void exit_itimers(struct signal_struct *sig)
* spin_lock_irq() held and from clock calls with no locking. They must
* use the save flags versions of locks.
*/
-static int do_posix_gettime(struct k_clock *clock, struct timespec *tp)
-{
- if (clock->clock_get)
- return clock->clock_get(tp);
-
- getnstimeofday(tp);
- return 0;
-}
/*
* We do ticks here to avoid the irq lock ( they take sooo long).
@@ -1177,7 +1232,7 @@ static u64 do_posix_clock_monotonic_gettime_parts(
return jiff;
}
-int do_posix_clock_monotonic_gettime(struct timespec *tp)
+static int do_posix_clock_monotonic_get(clockid_t clock, struct timespec *tp)
{
struct timespec wall_to_mono;
@@ -1193,17 +1248,24 @@ int do_posix_clock_monotonic_gettime(struct timespec *tp)
return 0;
}
-int do_posix_clock_nosettime(struct timespec *tp)
+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)
{
return -EINVAL;
}
+EXPORT_SYMBOL_GPL(do_posix_clock_nosettime);
int do_posix_clock_notimer_create(struct k_itimer *timer)
{
return -EINVAL;
}
+EXPORT_SYMBOL_GPL(do_posix_clock_notimer_create);
-int do_posix_clock_nonanosleep(int which_clock, int flags, struct timespec *t)
+int do_posix_clock_nonanosleep(clockid_t clock, int flags, struct timespec *t)
{
#ifndef ENOTSUP
return -EOPNOTSUPP; /* aka ENOTSUP in userland for POSIX */
@@ -1211,30 +1273,19 @@ int do_posix_clock_nonanosleep(int which_clock, int flags, struct timespec *t)
return -ENOTSUP;
#endif
}
+EXPORT_SYMBOL_GPL(do_posix_clock_nonanosleep);
asmlinkage long
sys_clock_settime(clockid_t which_clock, const struct timespec __user *tp)
{
struct timespec new_tp;
- if ((unsigned) which_clock >= MAX_CLOCKS ||
- !posix_clocks[which_clock].res)
+ if (invalid_clockid(which_clock))
return -EINVAL;
if (copy_from_user(&new_tp, tp, sizeof (*tp)))
return -EFAULT;
- if (posix_clocks[which_clock].clock_set)
- return posix_clocks[which_clock].clock_set(&new_tp);
-
- return do_sys_settimeofday(&new_tp, NULL);
-}
-static int do_clock_gettime(clockid_t which_clock, struct timespec *tp)
-{
- if ((unsigned) which_clock >= MAX_CLOCKS ||
- !posix_clocks[which_clock].res)
- return -EINVAL;
-
- return do_posix_gettime(&posix_clocks[which_clock], tp);
+ return CLOCK_DISPATCH(which_clock, clock_set, (which_clock, &new_tp));
}
asmlinkage long
@@ -1243,7 +1294,10 @@ sys_clock_gettime(clockid_t which_clock, struct timespec __user *tp)
struct timespec kernel_tp;
int error;
- error = do_clock_gettime(which_clock, &kernel_tp);
+ if (invalid_clockid(which_clock))
+ return -EINVAL;
+ error = CLOCK_DISPATCH(which_clock, clock_get,
+ (which_clock, &kernel_tp));
if (!error && copy_to_user(tp, &kernel_tp, sizeof (kernel_tp)))
error = -EFAULT;
@@ -1255,18 +1309,19 @@ asmlinkage long
sys_clock_getres(clockid_t which_clock, struct timespec __user *tp)
{
struct timespec rtn_tp;
+ int error;
- if ((unsigned) which_clock >= MAX_CLOCKS ||
- !posix_clocks[which_clock].res)
+ if (invalid_clockid(which_clock))
return -EINVAL;
- rtn_tp.tv_sec = 0;
- rtn_tp.tv_nsec = posix_clocks[which_clock].res;
- if (tp && copy_to_user(tp, &rtn_tp, sizeof (rtn_tp)))
- return -EFAULT;
+ error = CLOCK_DISPATCH(which_clock, clock_getres,
+ (which_clock, &rtn_tp));
- return 0;
+ if (!error && tp && copy_to_user(tp, &rtn_tp, sizeof (rtn_tp))) {
+ error = -EFAULT;
+ }
+ return error;
}
static void nanosleep_wake_up(unsigned long __data)
@@ -1364,13 +1419,13 @@ void clock_was_set(void)
break;
}
timr = list_entry(cws_list.next, struct k_itimer,
- abs_timer_entry);
+ it.real.abs_timer_entry);
- list_del_init(&timr->abs_timer_entry);
+ list_del_init(&timr->it.real.abs_timer_entry);
if (add_clockset_delta(timr, &new_wall_to) &&
- del_timer(&timr->it_timer)) /* timer run yet? */
- add_timer(&timr->it_timer);
- list_add(&timr->abs_timer_entry, &abs_list.list);
+ 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);
@@ -1379,9 +1434,6 @@ void clock_was_set(void)
long clock_nanosleep_restart(struct restart_block *restart_block);
-extern long do_clock_nanosleep(clockid_t which_clock, int flags,
- struct timespec *t);
-
asmlinkage long
sys_clock_nanosleep(clockid_t which_clock, int flags,
const struct timespec __user *rqtp,
@@ -1392,8 +1444,7 @@ sys_clock_nanosleep(clockid_t which_clock, int flags,
&(current_thread_info()->restart_block);
int ret;
- if ((unsigned) which_clock >= MAX_CLOCKS ||
- !posix_clocks[which_clock].res)
+ if (invalid_clockid(which_clock))
return -EINVAL;
if (copy_from_user(&t, rqtp, sizeof (struct timespec)))
@@ -1402,23 +1453,22 @@ sys_clock_nanosleep(clockid_t which_clock, int flags,
if ((unsigned) t.tv_nsec >= NSEC_PER_SEC || t.tv_sec < 0)
return -EINVAL;
- if (posix_clocks[which_clock].nsleep)
- ret = posix_clocks[which_clock].nsleep(which_clock, flags, &t);
- else
- ret = do_clock_nanosleep(which_clock, flags, &t);
/*
- * Do this here as do_clock_nanosleep does not have the real address
+ * 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;
}
-long
-do_clock_nanosleep(clockid_t which_clock, int flags, struct timespec *tsave)
+
+static int common_nsleep(clockid_t which_clock,
+ int flags, struct timespec *tsave)
{
struct timespec t, dum;
struct timer_list new_timer;
@@ -1461,7 +1511,6 @@ do_clock_nanosleep(clockid_t which_clock, int flags, struct timespec *tsave)
if (abs || !rq_time) {
adjust_abs_time(&posix_clocks[which_clock], &t, abs,
&rq_time, &dum);
- rq_time += (t.tv_sec || t.tv_nsec);
}
left = rq_time - get_jiffies_64();
@@ -1525,7 +1574,7 @@ long
clock_nanosleep_restart(struct restart_block *restart_block)
{
struct timespec t;
- int ret = do_clock_nanosleep(restart_block->arg0, 0, &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,
diff --git a/kernel/power/disk.c b/kernel/power/disk.c
index b9b3f58816779..02b6764034dcb 100644
--- a/kernel/power/disk.c
+++ b/kernel/power/disk.c
@@ -16,7 +16,6 @@
#include <linux/device.h>
#include <linux/delay.h>
#include <linux/fs.h>
-#include <linux/device.h>
#include "power.h"
@@ -25,13 +24,16 @@ extern struct pm_ops * pm_ops;
extern int swsusp_suspend(void);
extern int swsusp_write(void);
+extern int swsusp_check(void);
extern int swsusp_read(void);
+extern void swsusp_close(void);
extern int swsusp_resume(void);
extern int swsusp_free(void);
static int noresume = 0;
char resume_file[256] = CONFIG_PM_STD_PARTITION;
+dev_t swsusp_resume_device;
/**
* power_down - Shut machine down for hibernate.
@@ -51,7 +53,7 @@ static void power_down(suspend_disk_method_t mode)
local_irq_save(flags);
switch(mode) {
case PM_DISK_PLATFORM:
- device_power_down(PMSG_SUSPEND);
+ device_shutdown();
error = pm_ops->enter(PM_SUSPEND_DISK);
break;
case PM_DISK_SHUTDOWN:
@@ -121,45 +123,54 @@ static void finish(void)
}
-static int prepare(void)
+static int prepare_processes(void)
{
int error;
pm_prepare_console();
sys_sync();
+
if (freeze_processes()) {
error = -EBUSY;
- goto Thaw;
+ return error;
}
if (pm_disk_mode == PM_DISK_PLATFORM) {
if (pm_ops && pm_ops->prepare) {
if ((error = pm_ops->prepare(PM_SUSPEND_DISK)))
- goto Thaw;
+ return error;
}
}
/* Free memory before shutting down devices. */
free_some_memory();
+ return 0;
+}
+
+static void unprepare_processes(void)
+{
+ enable_nonboot_cpus();
+ thaw_processes();
+ pm_restore_console();
+}
+
+static int prepare_devices(void)
+{
+ int error;
+
disable_nonboot_cpus();
if ((error = device_suspend(PMSG_FREEZE))) {
printk("Some devices failed to suspend\n");
- goto Finish;
+ platform_finish();
+ enable_nonboot_cpus();
+ return error;
}
return 0;
- Finish:
- platform_finish();
- Thaw:
- enable_nonboot_cpus();
- thaw_processes();
- pm_restore_console();
- return error;
}
-
/**
* pm_suspend_disk - The granpappy of power management.
*
@@ -173,8 +184,15 @@ int pm_suspend_disk(void)
{
int error;
- if ((error = prepare()))
+ error = prepare_processes();
+ if (!error) {
+ error = prepare_devices();
+ }
+
+ if (error) {
+ unprepare_processes();
return error;
+ }
pr_debug("PM: Attempting to suspend to disk.\n");
if (pm_disk_mode == PM_DISK_FIRMWARE)
@@ -223,17 +241,28 @@ static int software_resume(void)
return 0;
}
+ pr_debug("PM: Checking swsusp image.\n");
+
+ if ((error = swsusp_check()))
+ goto Done;
+
+ pr_debug("PM: Preparing processes for restore.\n");
+
+ if ((error = prepare_processes())) {
+ swsusp_close();
+ goto Cleanup;
+ }
+
pr_debug("PM: Reading swsusp image.\n");
if ((error = swsusp_read()))
- goto Done;
+ goto Cleanup;
- pr_debug("PM: Preparing system for restore.\n");
+ pr_debug("PM: Preparing devices for restore.\n");
- if ((error = prepare()))
+ if ((error = prepare_devices()))
goto Free;
- barrier();
mb();
pr_debug("PM: Restoring saved image.\n");
@@ -242,6 +271,8 @@ static int software_resume(void)
finish();
Free:
swsusp_free();
+ Cleanup:
+ unprepare_processes();
Done:
pr_debug("PM: Resume from disk failed.\n");
return 0;
@@ -329,8 +360,41 @@ static ssize_t disk_store(struct subsystem * s, const char * buf, size_t n)
power_attr(disk);
+static ssize_t resume_show(struct subsystem * subsys, char *buf)
+{
+ return sprintf(buf,"%d:%d\n", MAJOR(swsusp_resume_device),
+ MINOR(swsusp_resume_device));
+}
+
+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;
+
+ p = memchr(buf, '\n', n);
+ len = p ? p - buf : n;
+
+ if (sscanf(buf, "%u:%u", &maj, &min) == 2) {
+ res = MKDEV(maj,min);
+ if (maj == MAJOR(res) && min == MINOR(res)) {
+ swsusp_resume_device = res;
+ printk("Attempting manual resume\n");
+ noresume = 0;
+ software_resume();
+ }
+ }
+
+ return error >= 0 ? n : error;
+}
+
+power_attr(resume);
+
static struct attribute * g[] = {
&disk_attr.attr,
+ &resume_attr.attr,
NULL,
};
diff --git a/kernel/power/main.c b/kernel/power/main.c
index 0f78207cfb573..7960ddf04a57f 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -65,8 +65,10 @@ static int suspend_prepare(suspend_state_t state)
goto Thaw;
}
- if ((error = device_suspend(PMSG_SUSPEND)))
+ if ((error = device_suspend(PMSG_SUSPEND))) {
+ printk(KERN_ERR "Some devices failed to suspend\n");
goto Finish;
+ }
return 0;
Finish:
if (pm_ops->finish)
@@ -85,8 +87,10 @@ static int suspend_enter(suspend_state_t state)
local_irq_save(flags);
- if ((error = device_power_down(PMSG_SUSPEND)))
+ if ((error = device_power_down(PMSG_SUSPEND))) {
+ printk(KERN_ERR "Some devices failed to power down\n");
goto Done;
+ }
error = pm_ops->enter(state);
device_power_up();
Done:
@@ -115,7 +119,7 @@ static void suspend_finish(suspend_state_t state)
-char * pm_states[] = {
+static char * pm_states[] = {
[PM_SUSPEND_STANDBY] = "standby",
[PM_SUSPEND_MEM] = "mem",
[PM_SUSPEND_DISK] = "disk",
diff --git a/kernel/power/pm.c b/kernel/power/pm.c
index 8fca5822a8077..61deda04e39e2 100644
--- a/kernel/power/pm.c
+++ b/kernel/power/pm.c
@@ -151,7 +151,7 @@ void pm_unregister_all(pm_callback callback)
* execution and unload yourself.
*/
-int pm_send(struct pm_dev *dev, pm_request_t rqst, void *data)
+static int pm_send(struct pm_dev *dev, pm_request_t rqst, void *data)
{
int status = 0;
unsigned long prev_state, next_state;
diff --git a/kernel/power/poweroff.c b/kernel/power/poweroff.c
index 73cabf6f47819..715081b2d8290 100644
--- a/kernel/power/poweroff.c
+++ b/kernel/power/poweroff.c
@@ -32,7 +32,8 @@ static void handle_poweroff(int key, struct pt_regs *pt_regs,
static struct sysrq_key_op sysrq_poweroff_op = {
.handler = handle_poweroff,
.help_msg = "powerOff",
- .action_msg = "Power Off"
+ .action_msg = "Power Off",
+ .enable_mask = SYSRQ_ENABLE_BOOT,
};
static int pm_sysrq_init(void)
diff --git a/kernel/power/smp.c b/kernel/power/smp.c
index cda77cdfb8c1c..7fa7f6e2b7fb6 100644
--- a/kernel/power/smp.c
+++ b/kernel/power/smp.c
@@ -42,7 +42,7 @@ static void smp_pause(void * data)
__restore_processor_state(&ctxt);
}
-cpumask_t oldmask;
+static cpumask_t oldmask;
void disable_nonboot_cpus(void)
{
diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c
index 9ca3b1c38b469..ae5bebc3b18fa 100644
--- a/kernel/power/swsusp.c
+++ b/kernel/power/swsusp.c
@@ -76,11 +76,10 @@
extern const void __nosave_begin, __nosave_end;
/* Variables to be preserved over suspend */
-static int pagedir_order_check;
static int nr_copy_pages_check;
extern char resume_file[];
-static dev_t resume_device;
+
/* Local variables that should not be affected by save */
unsigned int nr_copy_pages __nosavedata = 0;
@@ -99,7 +98,6 @@ unsigned int nr_copy_pages __nosavedata = 0;
*/
suspend_pagedir_t *pagedir_nosave __nosavedata = NULL;
static suspend_pagedir_t *pagedir_save;
-static int pagedir_order __nosavedata = 0;
#define SWSUSP_SIG "S1SUSPEND"
@@ -170,7 +168,7 @@ static int is_resume_device(const struct swap_info_struct *swap_info)
struct inode *inode = file->f_dentry->d_inode;
return S_ISBLK(inode->i_mode) &&
- resume_device == MKDEV(imajor(inode), iminor(inode));
+ swsusp_resume_device == MKDEV(imajor(inode), iminor(inode));
}
static int swsusp_swap_check(void) /* This is called before saving image */
@@ -225,8 +223,6 @@ static void lock_swapdevices(void)
swap_list_unlock();
}
-
-
/**
* write_swap_page - Write one page to a fresh swap location.
* @addr: Address we're writing.
@@ -239,7 +235,6 @@ static void lock_swapdevices(void)
* This is a partial improvement, since we will at least return other
* errors, though we need to eventually fix the damn code.
*/
-
static int write_page(unsigned long addr, swp_entry_t * loc)
{
swp_entry_t entry;
@@ -259,14 +254,12 @@ static int write_page(unsigned long addr, swp_entry_t * loc)
return error;
}
-
/**
* data_free - Free the swap entries used by the saved image.
*
* Walk the list of used swap entries and free each one.
* This is only used for cleanup when suspend fails.
*/
-
static void data_free(void)
{
swp_entry_t entry;
@@ -282,28 +275,27 @@ static void data_free(void)
}
}
-
/**
* data_write - Write saved image to swap.
*
* Walk the list of pages in the image and sync each one to swap.
*/
-
static int data_write(void)
{
- int error = 0;
- int i;
+ int error = 0, i = 0;
unsigned int mod = nr_copy_pages / 100;
+ struct pbe *p;
if (!mod)
mod = 1;
printk( "Writing data to swap (%d pages)... ", nr_copy_pages );
- for (i = 0; i < nr_copy_pages && !error; i++) {
+ for_each_pbe(p, pagedir_nosave) {
if (!(i%mod))
printk( "\b\b\b\b%3d%%", i / mod );
- error = write_page((pagedir_nosave+i)->address,
- &((pagedir_nosave+i)->swap_address));
+ if ((error = write_page(p->address, &(p->swap_address))))
+ return error;
+ i++;
}
printk("\b\b\b\bdone\n");
return error;
@@ -326,15 +318,14 @@ static void dump_info(void)
static void init_header(void)
{
- memset(&swsusp_info,0,sizeof(swsusp_info));
+ 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));
+ 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;
- dump_info();
}
static int close_swap(void)
@@ -342,7 +333,8 @@ static int close_swap(void)
swp_entry_t entry;
int error;
- error = write_page((unsigned long)&swsusp_info,&entry);
+ dump_info();
+ error = write_page((unsigned long)&swsusp_info, &entry);
if (!error) {
printk( "S" );
error = mark_swapfiles(entry);
@@ -373,15 +365,18 @@ static void free_pagedir_entries(void)
static int write_pagedir(void)
{
- unsigned long addr = (unsigned long)pagedir_nosave;
int error = 0;
- int n = SUSPEND_PD_PAGES(nr_copy_pages);
- int i;
+ unsigned n = 0;
+ struct pbe * pbe;
+
+ printk( "Writing pagedir...");
+ for_each_pb_page(pbe, pagedir_nosave) {
+ if ((error = write_page((unsigned long)pbe, &swsusp_info.pagedir[n++])))
+ return error;
+ }
swsusp_info.pagedir_pages = n;
- printk( "Writing pagedir (%d pages)\n", n);
- for (i = 0; i < n && !error; i++, addr += PAGE_SIZE)
- error = write_page(addr, &swsusp_info.pagedir[i]);
+ printk("done (%u pages)\n", n);
return error;
}
@@ -567,8 +562,8 @@ static void copy_data_pages(void)
struct zone *zone;
unsigned long zone_pfn;
struct pbe * pbe = pagedir_nosave;
- int to_copy = nr_copy_pages;
+ pr_debug("copy_data_pages(): pages to copy: %d\n", nr_copy_pages);
for_each_zone(zone) {
if (is_highmem(zone))
continue;
@@ -577,78 +572,126 @@ static void copy_data_pages(void)
if (saveable(zone, &zone_pfn)) {
struct page * page;
page = pfn_to_page(zone_pfn + zone->zone_start_pfn);
+ BUG_ON(!pbe);
pbe->orig_address = (long) page_address(page);
/* copy_page is not usable for copying task structs. */
memcpy((void *)pbe->address, (void *)pbe->orig_address, PAGE_SIZE);
- pbe++;
- to_copy--;
+ pbe = pbe->next;
}
}
}
- BUG_ON(to_copy);
+ BUG_ON(pbe);
}
/**
- * calc_order - Determine the order of allocation needed for pagedir_save.
- *
- * This looks tricky, but is just subtle. Please fix it some time.
- * Since there are %nr_copy_pages worth of pages in the snapshot, we need
- * to allocate enough contiguous space to hold
- * (%nr_copy_pages * sizeof(struct pbe)),
- * which has the saved/orig locations of the page..
- *
- * SUSPEND_PD_PAGES() tells us how many pages we need to hold those
- * structures, then we call get_bitmask_order(), which will tell us the
- * last bit set in the number, starting with 1. (If we need 30 pages, that
- * is 0x0000001e in hex. The last bit is the 5th, which is the order we
- * would use to allocate 32 contiguous pages).
- *
- * Since we also need to save those pages, we add the number of pages that
- * we need to nr_copy_pages, and in case of an overflow, do the
- * calculation again to update the number of pages needed.
- *
- * With this model, we will tend to waste a lot of memory if we just cross
- * an order boundary. Plus, the higher the order of allocation that we try
- * to do, the more likely we are to fail in a low-memory situtation
- * (though we're unlikely to get this far in such a case, since swsusp
- * requires half of memory to be free anyway).
+ * calc_nr - Determine the number of pages needed for a pbe list.
*/
-
-static void calc_order(void)
+static int calc_nr(int nr_copy)
{
- int diff = 0;
- int order = 0;
+ int extra = 0;
+ int mod = !!(nr_copy % PBES_PER_PAGE);
+ int diff = (nr_copy / PBES_PER_PAGE) + mod;
do {
- diff = get_bitmask_order(SUSPEND_PD_PAGES(nr_copy_pages)) - order;
- if (diff) {
- order += diff;
- nr_copy_pages += 1 << diff;
- }
- } while(diff);
- pagedir_order = order;
+ extra += diff;
+ nr_copy += diff;
+ mod = !!(nr_copy % PBES_PER_PAGE);
+ diff = (nr_copy / PBES_PER_PAGE) + mod - extra;
+ } while (diff > 0);
+
+ return nr_copy;
+}
+
+/**
+ * free_pagedir - free pages allocated with alloc_pagedir()
+ */
+
+static inline void free_pagedir(struct pbe *pblist)
+{
+ struct pbe *pbe;
+
+ while (pblist) {
+ pbe = (pblist + PB_PAGE_SKIP)->next;
+ free_page((unsigned long)pblist);
+ pblist = pbe;
+ }
}
+/**
+ * fill_pb_page - Create a list of PBEs on a given memory page
+ */
+
+static inline void fill_pb_page(struct pbe *pbpage)
+{
+ struct pbe *p;
+
+ p = pbpage;
+ pbpage += PB_PAGE_SKIP;
+ do
+ p->next = p + 1;
+ while (++p < pbpage);
+}
+
+/**
+ * create_pbe_list - Create a list of PBEs on top of a given chain
+ * of memory pages allocated with alloc_pagedir()
+ */
+
+static void create_pbe_list(struct pbe *pblist, unsigned nr_pages)
+{
+ struct pbe *pbpage, *p;
+ unsigned num = PBES_PER_PAGE;
+
+ for_each_pb_page (pbpage, pblist) {
+ if (num >= nr_pages)
+ break;
+
+ fill_pb_page(pbpage);
+ num += PBES_PER_PAGE;
+ }
+ if (pbpage) {
+ for (num -= PBES_PER_PAGE - 1, p = pbpage; num < nr_pages; p++, num++)
+ p->next = p + 1;
+ p->next = NULL;
+ }
+ pr_debug("create_pbe_list(): initialized %d PBEs\n", num);
+}
/**
* alloc_pagedir - Allocate the page directory.
*
- * First, determine exactly how many contiguous pages we need and
+ * First, determine exactly how many pages we need and
* allocate them.
+ *
+ * We arrange the pages in a chain: each page is an array of PBES_PER_PAGE
+ * struct pbe elements (pbes) and the last element in the page points
+ * to the next page.
+ *
+ * On each page we set up a list of struct_pbe elements.
*/
-static int alloc_pagedir(void)
+static struct pbe * alloc_pagedir(unsigned nr_pages)
{
- calc_order();
- pagedir_save = (suspend_pagedir_t *)__get_free_pages(GFP_ATOMIC | __GFP_COLD,
- pagedir_order);
- if (!pagedir_save)
- return -ENOMEM;
- memset(pagedir_save, 0, (1 << pagedir_order) * PAGE_SIZE);
- pagedir_nosave = pagedir_save;
- return 0;
+ unsigned num;
+ struct pbe *pblist, *pbe;
+
+ if (!nr_pages)
+ return NULL;
+
+ pr_debug("alloc_pagedir(): nr_pages = %d\n", nr_pages);
+ pblist = (struct pbe *)get_zeroed_page(GFP_ATOMIC | __GFP_COLD);
+ for (pbe = pblist, num = PBES_PER_PAGE; pbe && num < nr_pages;
+ pbe = pbe->next, num += PBES_PER_PAGE) {
+ pbe += PB_PAGE_SKIP;
+ pbe->next = (struct pbe *)get_zeroed_page(GFP_ATOMIC | __GFP_COLD);
+ }
+ if (!pbe) { /* get_zeroed_page() failed */
+ free_pagedir(pblist);
+ pblist = NULL;
+ }
+ return pblist;
}
/**
@@ -658,10 +701,8 @@ static int alloc_pagedir(void)
static void free_image_pages(void)
{
struct pbe * p;
- int i;
- p = pagedir_save;
- for (i = 0, p = pagedir_save; i < nr_copy_pages; i++, p++) {
+ for_each_pbe(p, pagedir_save) {
if (p->address) {
ClearPageNosave(virt_to_page(p->address));
free_page(p->address);
@@ -672,15 +713,13 @@ static void free_image_pages(void)
/**
* alloc_image_pages - Allocate pages for the snapshot.
- *
*/
static int alloc_image_pages(void)
{
struct pbe * p;
- int i;
- for (i = 0, p = pagedir_save; i < nr_copy_pages; i++, p++) {
+ for_each_pbe(p, pagedir_save) {
p->address = get_zeroed_page(GFP_ATOMIC | __GFP_COLD);
if (!p->address)
return -ENOMEM;
@@ -694,7 +733,7 @@ void swsusp_free(void)
BUG_ON(PageNosave(virt_to_page(pagedir_save)));
BUG_ON(PageNosaveFree(virt_to_page(pagedir_save)));
free_image_pages();
- free_pages((unsigned long) pagedir_save, pagedir_order);
+ free_pagedir(pagedir_save);
}
@@ -752,10 +791,14 @@ static int swsusp_alloc(void)
if (!enough_swap())
return -ENOSPC;
- if ((error = alloc_pagedir())) {
+ nr_copy_pages = calc_nr(nr_copy_pages);
+
+ if (!(pagedir_save = alloc_pagedir(nr_copy_pages))) {
printk(KERN_ERR "suspend: Allocating pagedir failed.\n");
- return error;
+ return -ENOMEM;
}
+ create_pbe_list(pagedir_save, nr_copy_pages);
+ pagedir_nosave = pagedir_save;
if ((error = alloc_image_pages())) {
printk(KERN_ERR "suspend: Allocating image pages failed.\n");
swsusp_free();
@@ -763,7 +806,6 @@ static int swsusp_alloc(void)
}
nr_copy_pages_check = nr_copy_pages;
- pagedir_order_check = pagedir_order;
return 0;
}
@@ -780,7 +822,7 @@ static int suspend_prepare_image(void)
drain_local_pages();
count_data_pages();
- printk("swsusp: Need to copy %u pages\n",nr_copy_pages);
+ printk("swsusp: Need to copy %u pages\n", nr_copy_pages);
error = swsusp_alloc();
if (error)
@@ -850,35 +892,29 @@ int swsusp_suspend(void)
* at resume time, and evil weirdness ensues.
*/
if ((error = device_power_down(PMSG_FREEZE))) {
+ printk(KERN_ERR "Some devices failed to power down, aborting suspend\n");
local_irq_enable();
+ swsusp_free();
return error;
}
save_processor_state();
- error = swsusp_arch_suspend();
+ if ((error = swsusp_arch_suspend()))
+ swsusp_free();
/* Restore control flow magically appears here */
restore_processor_state();
+ BUG_ON (nr_copy_pages_check != nr_copy_pages);
restore_highmem();
device_power_up();
local_irq_enable();
return error;
}
-
-asmlinkage int swsusp_restore(void)
-{
- BUG_ON (nr_copy_pages_check != nr_copy_pages);
- BUG_ON (pagedir_order_check != pagedir_order);
-
- /* Even mappings of "global" things (vmalloc) need to be fixed */
- __flush_tlb_global();
- return 0;
-}
-
int swsusp_resume(void)
{
int error;
local_irq_disable();
- device_power_down(PMSG_FREEZE);
+ if (device_power_down(PMSG_FREEZE))
+ printk(KERN_ERR "Some devices failed to power down, very bad\n");
/* We'll ignore saved state, but this gets preempt count (etc) right */
save_processor_state();
error = swsusp_arch_resume();
@@ -898,7 +934,7 @@ int swsusp_resume(void)
/*
* Returns true if given address/order collides with any orig_address
*/
-static int __init does_collide_order(unsigned long addr, int order)
+static int does_collide_order(unsigned long addr, int order)
{
int i;
@@ -908,44 +944,104 @@ static int __init does_collide_order(unsigned long addr, int order)
return 0;
}
-/*
- * We check here that pagedir & pages it points to won't collide with pages
- * where we're going to restore from the loaded pages later
+/**
+ * On resume, for storing the PBE list and the image,
+ * we can only use memory pages that do not conflict with the pages
+ * which had been used before suspend.
+ *
+ * We don't know which pages are usable until we allocate them.
+ *
+ * Allocated but unusable (ie eaten) memory pages are linked together
+ * to create a list, so that we can free them easily
+ *
+ * We could have used a type other than (void *)
+ * for this purpose, but ...
*/
-static int __init check_pagedir(void)
+static void **eaten_memory = NULL;
+
+static inline void eat_page(void *page)
{
- int i;
+ void **c;
- for(i=0; i < nr_copy_pages; i++) {
- unsigned long addr;
+ c = eaten_memory;
+ eaten_memory = page;
+ *eaten_memory = c;
+}
- do {
- addr = get_zeroed_page(GFP_ATOMIC);
- if(!addr)
- return -ENOMEM;
- } while (does_collide_order(addr, 0));
+static unsigned long get_usable_page(unsigned gfp_mask)
+{
+ unsigned long m;
- (pagedir_nosave+i)->address = addr;
+ m = get_zeroed_page(gfp_mask);
+ while (does_collide_order(m, 0)) {
+ eat_page((void *)m);
+ m = get_zeroed_page(gfp_mask);
+ if (!m)
+ break;
}
- return 0;
+ return m;
}
-static int __init swsusp_pagedir_relocate(void)
+static void free_eaten_memory(void)
{
- /*
- * We have to avoid recursion (not to overflow kernel stack),
- * and that's why code looks pretty cryptic
+ unsigned long m;
+ void **c;
+ int i = 0;
+
+ c = eaten_memory;
+ while (c) {
+ m = (unsigned long)c;
+ c = *c;
+ free_page(m);
+ i++;
+ }
+ eaten_memory = NULL;
+ pr_debug("swsusp: %d unused pages freed\n", i);
+}
+
+/**
+ * check_pagedir - We ensure here that pages that the PBEs point to
+ * won't collide with pages where we're going to restore from the loaded
+ * pages later
+ */
+
+static int check_pagedir(struct pbe *pblist)
+{
+ struct pbe *p;
+
+ /* This is necessary, so that we can free allocated pages
+ * in case of failure
*/
- suspend_pagedir_t *old_pagedir = pagedir_nosave;
- void **eaten_memory = NULL;
- void **c = eaten_memory, *m, *f;
- int ret = 0;
+ for_each_pbe (p, pblist)
+ p->address = 0UL;
+
+ for_each_pbe (p, pblist) {
+ p->address = get_usable_page(GFP_ATOMIC);
+ if (!p->address)
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+/**
+ * swsusp_pagedir_relocate - It is possible, that some memory pages
+ * occupied by the list of PBEs collide with pages where we're going to
+ * restore from the loaded pages later. We relocate them here.
+ */
+
+static struct pbe * swsusp_pagedir_relocate(struct pbe *pblist)
+{
struct zone *zone;
- int i;
- struct pbe *p;
unsigned long zone_pfn;
+ struct pbe *pbpage, *tail, *p;
+ void *m;
+ int rel = 0, error = 0;
+
+ if (!pblist) /* a sanity check */
+ return NULL;
- printk("Relocating pagedir ");
+ pr_debug("swsusp: Relocating pagedir (%lu pages to check)\n",
+ swsusp_info.pagedir_pages);
/* Set page flags */
@@ -955,45 +1051,52 @@ static int __init swsusp_pagedir_relocate(void)
zone->zone_start_pfn));
}
- /* Clear orig address */
+ /* Clear orig addresses */
- for(i = 0, p = pagedir_nosave; i < nr_copy_pages; i++, p++) {
+ for_each_pbe (p, pblist)
ClearPageNosaveFree(virt_to_page(p->orig_address));
- }
- if (!does_collide_order((unsigned long)old_pagedir, pagedir_order)) {
- printk("not necessary\n");
- return check_pagedir();
- }
+ tail = pblist + PB_PAGE_SKIP;
- while ((m = (void *) __get_free_pages(GFP_ATOMIC, pagedir_order)) != NULL) {
- if (!does_collide_order((unsigned long)m, pagedir_order))
- break;
- eaten_memory = m;
- printk( "." );
- *eaten_memory = c;
- c = eaten_memory;
- }
+ /* Relocate colliding pages */
- if (!m) {
- printk("out of memory\n");
- ret = -ENOMEM;
- } else {
- pagedir_nosave =
- memcpy(m, old_pagedir, PAGE_SIZE << pagedir_order);
+ for_each_pb_page (pbpage, pblist) {
+ if (does_collide_order((unsigned long)pbpage, 0)) {
+ m = (void *)get_usable_page(GFP_ATOMIC | __GFP_COLD);
+ if (!m) {
+ error = -ENOMEM;
+ break;
+ }
+ memcpy(m, (void *)pbpage, PAGE_SIZE);
+ if (pbpage == pblist)
+ pblist = (struct pbe *)m;
+ else
+ tail->next = (struct pbe *)m;
+
+ eat_page((void *)pbpage);
+ pbpage = (struct pbe *)m;
+
+ /* We have to link the PBEs again */
+
+ for (p = pbpage; p < pbpage + PB_PAGE_SKIP; p++)
+ if (p->next) /* needed to save the end */
+ p->next = p + 1;
+
+ rel++;
+ }
+ tail = pbpage + PB_PAGE_SKIP;
}
- c = eaten_memory;
- while (c) {
- printk(":");
- f = c;
- c = *c;
- free_pages((unsigned long)f, pagedir_order);
+ if (error) {
+ printk("\nswsusp: Out of memory\n\n");
+ free_pagedir(pblist);
+ free_eaten_memory();
+ pblist = NULL;
}
- if (ret)
- return ret;
- printk("|\n");
- return check_pagedir();
+ else
+ printk("swsusp: Relocated %d pages\n", rel);
+
+ return pblist;
}
/**
@@ -1075,7 +1178,7 @@ static int bio_write_page(pgoff_t page_off, void * page)
* I really don't think that it's foolproof but more than nothing..
*/
-static const char * __init sanity_check(void)
+static const char * sanity_check(void)
{
dump_info();
if(swsusp_info.version_code != LINUX_VERSION_CODE)
@@ -1096,7 +1199,7 @@ static const char * __init sanity_check(void)
}
-static int __init check_header(void)
+static int check_header(void)
{
const char * reason = NULL;
int error;
@@ -1110,11 +1213,10 @@ static int __init check_header(void)
return -EPERM;
}
nr_copy_pages = swsusp_info.image_pages;
- pagedir_order = get_bitmask_order(SUSPEND_PD_PAGES(nr_copy_pages));
return error;
}
-static int __init check_sig(void)
+static int check_sig(void)
{
int error;
@@ -1129,7 +1231,7 @@ static int __init check_sig(void)
*/
error = bio_write_page(0, &swsusp_header);
} else {
- pr_debug(KERN_ERR "swsusp: Suspend partition has wrong signature?\n");
+ printk(KERN_ERR "swsusp: Suspend partition has wrong signature?\n");
return -EINVAL;
}
if (!error)
@@ -1138,104 +1240,194 @@ static int __init check_sig(void)
}
/**
- * swsusp_read_data - Read image pages from swap.
+ * data_read - Read image pages from swap.
*
* You do not need to check for overlaps, check_pagedir()
* already did that.
*/
-static int __init data_read(void)
+static int data_read(struct pbe *pblist)
{
struct pbe * p;
- int error;
- int i;
- int mod = nr_copy_pages / 100;
+ int error = 0;
+ int i = 0;
+ int mod = swsusp_info.image_pages / 100;
if (!mod)
mod = 1;
- if ((error = swsusp_pagedir_relocate()))
- return error;
+ 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);
- printk( "Reading image data (%d pages): ", nr_copy_pages );
- for(i = 0, p = pagedir_nosave; i < nr_copy_pages && !error; i++, p++) {
- if (!(i%mod))
- printk( "\b\b\b\b%3d%%", i / mod );
error = bio_read_page(swp_offset(p->swap_address),
(void *)p->address);
+ if (error)
+ return error;
+
+ i++;
}
- printk(" %d done.\n",i);
+ printk("\b\b\b\bdone\n");
return error;
-
}
-extern dev_t __init name_to_dev_t(const char *line);
+extern dev_t name_to_dev_t(const char *line);
-static int __init read_pagedir(void)
+/**
+ * read_pagedir - Read page backup list pages from swap
+ */
+
+static int read_pagedir(struct pbe *pblist)
{
- unsigned long addr;
- int i, n = swsusp_info.pagedir_pages;
- int error = 0;
+ struct pbe *pbpage, *p;
+ unsigned i = 0;
+ int error;
- addr = __get_free_pages(GFP_ATOMIC, pagedir_order);
- if (!addr)
- return -ENOMEM;
- pagedir_nosave = (struct pbe *)addr;
+ if (!pblist)
+ return -EFAULT;
- pr_debug("swsusp: Reading pagedir (%d Pages)\n",n);
+ printk("swsusp: Reading pagedir (%lu pages)\n",
+ swsusp_info.pagedir_pages);
- for (i = 0; i < n && !error; i++, addr += PAGE_SIZE) {
- unsigned long offset = swp_offset(swsusp_info.pagedir[i]);
- if (offset)
- error = bio_read_page(offset, (void *)addr);
- else
- error = -EFAULT;
+ 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;
+ }
+ if (error)
+ break;
}
+
if (error)
- free_pages((unsigned long)pagedir_nosave, pagedir_order);
+ free_page((unsigned long)pblist);
+
+ BUG_ON(i != swsusp_info.pagedir_pages);
+
return error;
}
-static int __init read_suspend_image(void)
+
+static int check_suspend_image(void)
{
int error = 0;
if ((error = check_sig()))
return error;
+
if ((error = check_header()))
return error;
- if ((error = read_pagedir()))
+
+ return 0;
+}
+
+static int read_suspend_image(void)
+{
+ int error = 0;
+ struct pbe *p;
+
+ if (!(p = alloc_pagedir(nr_copy_pages)))
+ return -ENOMEM;
+
+ if ((error = read_pagedir(p)))
return error;
- if ((error = data_read()))
- free_pages((unsigned long)pagedir_nosave, pagedir_order);
+
+ create_pbe_list(p, nr_copy_pages);
+
+ if (!(pagedir_nosave = swsusp_pagedir_relocate(p)))
+ return -ENOMEM;
+
+ /* Allocate memory for the image and read the data from swap */
+
+ error = check_pagedir(pagedir_nosave);
+ free_eaten_memory();
+ if (!error)
+ error = data_read(pagedir_nosave);
+
+ if (error) { /* We fail cleanly */
+ for_each_pbe (p, pagedir_nosave)
+ if (p->address) {
+ free_page(p->address);
+ p->address = 0UL;
+ }
+ free_pagedir(pagedir_nosave);
+ }
return error;
}
/**
- * swsusp_read - Read saved image from swap.
+ * swsusp_check - Check for saved image in swap
*/
-int __init swsusp_read(void)
+int swsusp_check(void)
{
int error;
- if (!strlen(resume_file))
- return -ENOENT;
-
- resume_device = name_to_dev_t(resume_file);
- pr_debug("swsusp: Resume From Partition: %s\n", resume_file);
+ if (!swsusp_resume_device) {
+ if (!strlen(resume_file))
+ return -ENOENT;
+ swsusp_resume_device = name_to_dev_t(resume_file);
+ pr_debug("swsusp: Resume From Partition %s\n", resume_file);
+ } else {
+ pr_debug("swsusp: Resume From Partition %d:%d\n",
+ MAJOR(swsusp_resume_device), MINOR(swsusp_resume_device));
+ }
- resume_bdev = open_by_devnum(resume_device, FMODE_READ);
+ resume_bdev = open_by_devnum(swsusp_resume_device, FMODE_READ);
if (!IS_ERR(resume_bdev)) {
set_blocksize(resume_bdev, PAGE_SIZE);
- error = read_suspend_image();
- blkdev_put(resume_bdev);
+ error = check_suspend_image();
+ if (error)
+ blkdev_put(resume_bdev);
} else
error = PTR_ERR(resume_bdev);
if (!error)
- pr_debug("Reading resume file was successful\n");
+ 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);
+
+ if (!error)
+ pr_debug("swsusp: Reading resume file was successful\n");
else
pr_debug("swsusp: Error %d resuming\n", error);
return error;
}
+
+/**
+ * swsusp_close - close swap device.
+ */
+
+void swsusp_close(void)
+{
+ if (IS_ERR(resume_bdev)) {
+ pr_debug("swsusp: block device not initialised\n");
+ return;
+ }
+
+ blkdev_put(resume_bdev);
+}
diff --git a/kernel/printk.c b/kernel/printk.c
index d981e7e4153a8..1498689548d1e 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -54,7 +54,12 @@ int console_printk[4] = {
EXPORT_SYMBOL(console_printk);
+/*
+ * Low lever drivers may need that to know if they can schedule in
+ * their unblank() callback or not. So let's export it.
+ */
int oops_in_progress;
+EXPORT_SYMBOL(oops_in_progress);
/*
* console_sem protects the console_drivers list, and also
@@ -269,9 +274,10 @@ int do_syslog(int type, char __user * buf, int len)
error = 0;
if (!len)
goto out;
- error = verify_area(VERIFY_WRITE,buf,len);
- if (error)
+ if (!access_ok(VERIFY_WRITE, buf, len)) {
+ error = -EFAULT;
goto out;
+ }
error = wait_event_interruptible(log_wait, (log_start - log_end));
if (error)
goto out;
@@ -301,9 +307,10 @@ int do_syslog(int type, char __user * buf, int len)
error = 0;
if (!len)
goto out;
- error = verify_area(VERIFY_WRITE,buf,len);
- if (error)
+ if (!access_ok(VERIFY_WRITE, buf, len)) {
+ error = -EFAULT;
goto out;
+ }
count = len;
if (count > log_buf_len)
count = log_buf_len;
@@ -499,6 +506,22 @@ static void zap_locks(void)
init_MUTEX(&console_sem);
}
+#if defined(CONFIG_PRINTK_TIME)
+static int printk_time = 1;
+#else
+static int printk_time = 0;
+#endif
+
+static int __init printk_time_setup(char *str)
+{
+ if (*str)
+ return 0;
+ printk_time = 1;
+ return 1;
+}
+
+__setup("time", printk_time_setup);
+
/*
* This is printk. It can be called from any context. We want it to work.
*
@@ -547,12 +570,51 @@ asmlinkage int vprintk(const char *fmt, va_list args)
*/
for (p = printk_buf; *p; p++) {
if (log_level_unknown) {
- if (p[0] != '<' || p[1] < '0' || p[1] > '7' || p[2] != '>') {
- emit_log_char('<');
- emit_log_char(default_message_loglevel + '0');
- emit_log_char('>');
+ /* log_level_unknown signals the start of a new line */
+ if (printk_time) {
+ int loglev_char;
+ char tbuf[50], *tp;
+ unsigned tlen;
+ unsigned long long t;
+ unsigned long nanosec_rem;
+
+ /*
+ * force the log level token to be
+ * before the time output.
+ */
+ if (p[0] == '<' && p[1] >='0' &&
+ p[1] <= '7' && p[2] == '>') {
+ loglev_char = p[1];
+ p += 3;
+ printed_len += 3;
+ } else {
+ loglev_char = default_message_loglevel
+ + '0';
+ }
+ t = sched_clock();
+ nanosec_rem = do_div(t, 1000000000);
+ tlen = sprintf(tbuf,
+ "<%c>[%5lu.%06lu] ",
+ loglev_char,
+ (unsigned long)t,
+ nanosec_rem/1000);
+
+ for (tp = tbuf; tp < tbuf + tlen; tp++)
+ emit_log_char(*tp);
+ printed_len += tlen - 3;
+ } else {
+ if (p[0] != '<' || p[1] < '0' ||
+ p[1] > '7' || p[2] != '>') {
+ emit_log_char('<');
+ emit_log_char(default_message_loglevel
+ + '0');
+ emit_log_char('>');
+ }
+ printed_len += 3;
}
log_level_unknown = 0;
+ if (!*p)
+ break;
}
emit_log_char(*p);
if (*p == '\n')
@@ -694,12 +756,15 @@ void console_unblank(void)
struct console *c;
/*
- * Try to get the console semaphore. If someone else owns it
- * we have to return without unblanking because console_unblank
- * may be called in interrupt context.
+ * console_unblank can no longer be called in interrupt context unless
+ * oops_in_progress is set to 1..
*/
- if (down_trylock(&console_sem) != 0)
- return;
+ if (oops_in_progress) {
+ if (down_trylock(&console_sem) != 0)
+ return;
+ } else
+ acquire_console_sem();
+
console_locked = 1;
console_may_schedule = 0;
for (c = console_drivers; c != NULL; c = c->next)
@@ -804,6 +869,11 @@ void register_console(struct console * console)
if (!(console->flags & CON_ENABLED))
return;
+ if (console_drivers && (console_drivers->flags & CON_BOOT)) {
+ unregister_console(console_drivers);
+ console->flags &= ~CON_PRINTBUFFER;
+ }
+
/*
* Put this console in the list - keep the
* preferred driver at the head of the list.
diff --git a/kernel/rcupdate.c b/kernel/rcupdate.c
index f0ae3c3c013eb..d00eded75d71f 100644
--- a/kernel/rcupdate.c
+++ b/kernel/rcupdate.c
@@ -465,6 +465,6 @@ void synchronize_kernel(void)
}
module_param(maxbatch, int, 0);
-EXPORT_SYMBOL(call_rcu);
-EXPORT_SYMBOL(call_rcu_bh);
-EXPORT_SYMBOL(synchronize_kernel);
+EXPORT_SYMBOL_GPL(call_rcu);
+EXPORT_SYMBOL_GPL(call_rcu_bh);
+EXPORT_SYMBOL_GPL(synchronize_kernel);
diff --git a/kernel/resource.c b/kernel/resource.c
index 72596bc6fdafb..35c99ac02c7cf 100644
--- a/kernel/resource.c
+++ b/kernel/resource.c
@@ -91,7 +91,7 @@ static int r_show(struct seq_file *m, void *v)
return 0;
}
-struct seq_operations resource_op = {
+static struct seq_operations resource_op = {
.start = r_start,
.next = r_next,
.stop = r_stop,
diff --git a/kernel/sched.c b/kernel/sched.c
index 95042b27d30ce..f69c4a5361e3b 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -40,11 +40,13 @@
#include <linux/timer.h>
#include <linux/rcupdate.h>
#include <linux/cpu.h>
+#include <linux/cpuset.h>
#include <linux/percpu.h>
#include <linux/kthread.h>
#include <linux/seq_file.h>
#include <linux/syscalls.h>
#include <linux/times.h>
+#include <linux/acct.h>
#include <asm/tlb.h>
#include <asm/unistd.h>
@@ -164,7 +166,7 @@
#define SCALE_PRIO(x, prio) \
max(x * (MAX_PRIO - prio) / (MAX_USER_PRIO/2), MIN_TIMESLICE)
-static unsigned int task_timeslice(task_t *p)
+static inline unsigned int task_timeslice(task_t *p)
{
if (p->static_prio < NICE_TO_PRIO(0))
return SCALE_PRIO(DEF_TIMESLICE*4, p->static_prio);
@@ -246,35 +248,13 @@ struct runqueue {
unsigned long yld_cnt;
/* schedule() stats */
- unsigned long sched_noswitch;
unsigned long sched_switch;
unsigned long sched_cnt;
unsigned long sched_goidle;
- /* pull_task() stats */
- unsigned long pt_gained[MAX_IDLE_TYPES];
- unsigned long pt_lost[MAX_IDLE_TYPES];
-
- /* active_load_balance() stats */
- unsigned long alb_cnt;
- unsigned long alb_lost;
- unsigned long alb_gained;
- unsigned long alb_failed;
-
/* try_to_wake_up() stats */
unsigned long ttwu_cnt;
- unsigned long ttwu_attempts;
- unsigned long ttwu_moved;
-
- /* wake_up_new_task() stats */
- unsigned long wunt_cnt;
- unsigned long wunt_moved;
-
- /* sched_migrate_task() stats */
- unsigned long smt_cnt;
-
- /* sched_balance_exec() stats */
- unsigned long sbe_cnt;
+ unsigned long ttwu_local;
#endif
};
@@ -302,7 +282,7 @@ static DEFINE_PER_CPU(struct runqueue, runqueues);
* interrupts. Note the ordering: we can safely lookup the task_rq without
* explicitly disabling preemption.
*/
-static runqueue_t *task_rq_lock(task_t *p, unsigned long *flags)
+static inline runqueue_t *task_rq_lock(task_t *p, unsigned long *flags)
__acquires(rq->lock)
{
struct runqueue *rq;
@@ -329,12 +309,11 @@ static inline void task_rq_unlock(runqueue_t *rq, unsigned long *flags)
* bump this up when changing the output format or the meaning of an existing
* format, so that tools can adapt (or abort)
*/
-#define SCHEDSTAT_VERSION 10
+#define SCHEDSTAT_VERSION 11
static int show_schedstat(struct seq_file *seq, void *v)
{
int cpu;
- enum idle_type itype;
seq_printf(seq, "version %d\n", SCHEDSTAT_VERSION);
seq_printf(seq, "timestamp %lu\n", jiffies);
@@ -347,43 +326,40 @@ static int show_schedstat(struct seq_file *seq, void *v)
/* runqueue-specific stats */
seq_printf(seq,
- "cpu%d %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu "
- "%lu %lu %lu %lu %lu %lu %lu %lu %lu %lu",
+ "cpu%d %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu",
cpu, rq->yld_both_empty,
- rq->yld_act_empty, rq->yld_exp_empty,
- rq->yld_cnt, rq->sched_noswitch,
+ rq->yld_act_empty, rq->yld_exp_empty, rq->yld_cnt,
rq->sched_switch, rq->sched_cnt, rq->sched_goidle,
- rq->alb_cnt, rq->alb_gained, rq->alb_lost,
- rq->alb_failed,
- rq->ttwu_cnt, rq->ttwu_moved, rq->ttwu_attempts,
- rq->wunt_cnt, rq->wunt_moved,
- rq->smt_cnt, rq->sbe_cnt, rq->rq_sched_info.cpu_time,
+ rq->ttwu_cnt, rq->ttwu_local,
+ rq->rq_sched_info.cpu_time,
rq->rq_sched_info.run_delay, rq->rq_sched_info.pcnt);
- for (itype = SCHED_IDLE; itype < MAX_IDLE_TYPES; itype++)
- seq_printf(seq, " %lu %lu", rq->pt_gained[itype],
- rq->pt_lost[itype]);
seq_printf(seq, "\n");
#ifdef CONFIG_SMP
/* domain-specific stats */
for_each_domain(cpu, sd) {
+ enum idle_type itype;
char mask_str[NR_CPUS];
cpumask_scnprintf(mask_str, NR_CPUS, sd->span);
seq_printf(seq, "domain%d %s", dcnt++, mask_str);
for (itype = SCHED_IDLE; itype < MAX_IDLE_TYPES;
- itype++) {
- seq_printf(seq, " %lu %lu %lu %lu %lu",
+ itype++) {
+ seq_printf(seq, " %lu %lu %lu %lu %lu %lu %lu %lu",
sd->lb_cnt[itype],
+ sd->lb_balanced[itype],
sd->lb_failed[itype],
sd->lb_imbalance[itype],
+ sd->lb_gained[itype],
+ sd->lb_hot_gained[itype],
sd->lb_nobusyq[itype],
sd->lb_nobusyg[itype]);
}
- seq_printf(seq, " %lu %lu %lu %lu\n",
+ seq_printf(seq, " %lu %lu %lu %lu %lu %lu %lu %lu\n",
+ sd->alb_cnt, sd->alb_failed, sd->alb_pushed,
sd->sbe_pushed, sd->sbe_attempts,
- sd->ttwu_wake_affine, sd->ttwu_wake_balance);
+ sd->ttwu_wake_remote, sd->ttwu_move_affine, sd->ttwu_move_balance);
}
#endif
}
@@ -426,7 +402,7 @@ struct file_operations proc_schedstat_operations = {
/*
* rq_lock - lock a given runqueue and disable interrupts.
*/
-static runqueue_t *this_rq_lock(void)
+static inline runqueue_t *this_rq_lock(void)
__acquires(rq->lock)
{
runqueue_t *rq;
@@ -648,6 +624,7 @@ static inline void __activate_idle_task(task_t *p, runqueue_t *rq)
static void recalc_task_prio(task_t *p, unsigned long long now)
{
+ /* Caller must always ensure 'now >= p->timestamp' */
unsigned long long __sleep_time = now - p->timestamp;
unsigned long sleep_time;
@@ -995,7 +972,6 @@ static int try_to_wake_up(task_t * p, unsigned int state, int sync)
#endif
rq = task_rq_lock(p, &flags);
- schedstat_inc(rq, ttwu_cnt);
old_state = p->state;
if (!(old_state & state))
goto out;
@@ -1010,8 +986,21 @@ static int try_to_wake_up(task_t * p, unsigned int state, int sync)
if (unlikely(task_running(rq, p)))
goto out_activate;
- new_cpu = cpu;
+#ifdef CONFIG_SCHEDSTATS
+ schedstat_inc(rq, ttwu_cnt);
+ if (cpu == this_cpu) {
+ schedstat_inc(rq, ttwu_local);
+ } else {
+ for_each_domain(this_cpu, sd) {
+ if (cpu_isset(cpu, sd->span)) {
+ schedstat_inc(sd, ttwu_wake_remote);
+ break;
+ }
+ }
+ }
+#endif
+ new_cpu = cpu;
if (cpu == this_cpu || unlikely(!cpu_isset(this_cpu, p->cpus_allowed)))
goto out_set_cpu;
@@ -1050,7 +1039,7 @@ static int try_to_wake_up(task_t * p, unsigned int state, int sync)
* in this domain.
*/
if (cpu_isset(cpu, sd->span)) {
- schedstat_inc(sd, ttwu_wake_affine);
+ schedstat_inc(sd, ttwu_move_affine);
goto out_set_cpu;
}
} else if ((sd->flags & SD_WAKE_BALANCE) &&
@@ -1060,7 +1049,7 @@ static int try_to_wake_up(task_t * p, unsigned int state, int sync)
* an imbalance.
*/
if (cpu_isset(cpu, sd->span)) {
- schedstat_inc(sd, ttwu_wake_balance);
+ schedstat_inc(sd, ttwu_move_balance);
goto out_set_cpu;
}
}
@@ -1068,10 +1057,8 @@ static int try_to_wake_up(task_t * p, unsigned int state, int sync)
new_cpu = cpu; /* Could not wake to this_cpu. Wake to cpu instead */
out_set_cpu:
- schedstat_inc(rq, ttwu_attempts);
new_cpu = wake_idle(new_cpu, p);
if (new_cpu != cpu) {
- schedstat_inc(rq, ttwu_moved);
set_task_cpu(p, new_cpu);
task_rq_unlock(rq, &flags);
/* might preempt at this point */
@@ -1214,7 +1201,6 @@ void fastcall wake_up_new_task(task_t * p, unsigned long clone_flags)
BUG_ON(p->state != TASK_RUNNING);
- schedstat_inc(rq, wunt_cnt);
/*
* We decrease the sleep average of forking parents
* and children as well, to keep max-interactive tasks
@@ -1266,7 +1252,6 @@ void fastcall wake_up_new_task(task_t * p, unsigned long clone_flags)
if (TASK_PREEMPTS_CURR(p, rq))
resched_task(rq->curr);
- schedstat_inc(rq, wunt_moved);
/*
* Parent and child are on different CPUs, now get the
* parent runqueue to update the parent's ->sleep_avg:
@@ -1323,7 +1308,7 @@ void fastcall sched_exit(task_t * p)
* with the lock held can cause deadlocks; see schedule() for
* details.)
*/
-static void finish_task_switch(task_t *prev)
+static inline void finish_task_switch(task_t *prev)
__releases(rq->lock)
{
runqueue_t *rq = this_rq();
@@ -1570,7 +1555,6 @@ static void sched_migrate_task(task_t *p, int dest_cpu)
|| unlikely(cpu_is_offline(dest_cpu)))
goto out;
- schedstat_inc(rq, smt_cnt);
/* force the process onto the specified CPU */
if (migrate_task(p, dest_cpu, &req)) {
/* Need to wait for migration thread (might exit: take ref). */
@@ -1598,7 +1582,6 @@ void sched_exec(void)
struct sched_domain *tmp, *sd = NULL;
int new_cpu, this_cpu = get_cpu();
- schedstat_inc(this_rq(), sbe_cnt);
/* Prefer the current CPU if there's only this task running */
if (this_rq()->nr_running <= 1)
goto out;
@@ -1741,13 +1724,10 @@ skip_queue:
goto skip_bitmap;
}
- /*
- * Right now, this is the only place pull_task() is called,
- * so we can safely collect pull_task() stats here rather than
- * inside pull_task().
- */
- schedstat_inc(this_rq, pt_gained[idle]);
- schedstat_inc(busiest, pt_lost[idle]);
+#ifdef CONFIG_SCHEDSTATS
+ if (task_hot(tmp, busiest->timestamp_last_tick, sd))
+ schedstat_inc(sd, lb_hot_gained[idle]);
+#endif
pull_task(busiest, array, tmp, this_rq, dst_array, this_cpu);
pulled++;
@@ -1760,6 +1740,12 @@ skip_queue:
goto skip_bitmap;
}
out:
+ /*
+ * Right now, this is the only place pull_task() is called,
+ * so we can safely collect pull_task() stats here rather than
+ * inside pull_task().
+ */
+ schedstat_add(sd, lb_gained[idle], pulled);
return pulled;
}
@@ -1780,7 +1766,7 @@ find_busiest_group(struct sched_domain *sd, int this_cpu,
do {
unsigned long load;
int local_group;
- int i, nr_cpus = 0;
+ int i;
local_group = cpu_isset(this_cpu, group->cpumask);
@@ -1794,13 +1780,9 @@ find_busiest_group(struct sched_domain *sd, int this_cpu,
else
load = source_load(i);
- nr_cpus++;
avg_load += load;
}
- if (!nr_cpus)
- goto nextgroup;
-
total_load += avg_load;
total_pwr += group->cpu_power;
@@ -1839,13 +1821,12 @@ nextgroup:
* by pulling tasks to us. Be careful of negative numbers as they'll
* appear as very large values with unsigned longs.
*/
- *imbalance = min(max_load - avg_load, avg_load - this_load);
-
/* How much load to actually move to equalise the imbalance */
- *imbalance = (*imbalance * min(busiest->cpu_power, this->cpu_power))
- / SCHED_LOAD_SCALE;
+ *imbalance = min((max_load - avg_load) * busiest->cpu_power,
+ (avg_load - this_load) * this->cpu_power)
+ / SCHED_LOAD_SCALE;
- if (*imbalance < SCHED_LOAD_SCALE - 1) {
+ if (*imbalance < SCHED_LOAD_SCALE) {
unsigned long pwr_now = 0, pwr_move = 0;
unsigned long tmp;
@@ -1871,14 +1852,16 @@ nextgroup:
max_load - tmp);
/* Amount of load we'd add */
- tmp = SCHED_LOAD_SCALE*SCHED_LOAD_SCALE/this->cpu_power;
- if (max_load < tmp)
- tmp = max_load;
+ if (max_load*busiest->cpu_power <
+ SCHED_LOAD_SCALE*SCHED_LOAD_SCALE)
+ tmp = max_load*busiest->cpu_power/this->cpu_power;
+ else
+ tmp = SCHED_LOAD_SCALE*SCHED_LOAD_SCALE/this->cpu_power;
pwr_move += this->cpu_power*min(SCHED_LOAD_SCALE, this_load + tmp);
pwr_move /= SCHED_LOAD_SCALE;
- /* Move if we gain another 8th of a CPU worth of throughput */
- if (pwr_move < pwr_now + SCHED_LOAD_SCALE / 8)
+ /* Move if we gain throughput */
+ if (pwr_move <= pwr_now)
goto out_balanced;
*imbalance = 1;
@@ -1886,7 +1869,7 @@ nextgroup:
}
/* Get rid of the scaling factor, rounding down as we divide */
- *imbalance = (*imbalance + 1) / SCHED_LOAD_SCALE;
+ *imbalance = *imbalance / SCHED_LOAD_SCALE;
return busiest;
@@ -2020,6 +2003,8 @@ static int load_balance(int this_cpu, runqueue_t *this_rq,
out_balanced:
spin_unlock(&this_rq->lock);
+ schedstat_inc(sd, lb_balanced[idle]);
+
/* tune up the balancing interval */
if (sd->balance_interval < sd->max_interval)
sd->balance_interval *= 2;
@@ -2045,12 +2030,14 @@ static int load_balance_newidle(int this_cpu, runqueue_t *this_rq,
schedstat_inc(sd, lb_cnt[NEWLY_IDLE]);
group = find_busiest_group(sd, this_cpu, &imbalance, NEWLY_IDLE);
if (!group) {
+ schedstat_inc(sd, lb_balanced[NEWLY_IDLE]);
schedstat_inc(sd, lb_nobusyg[NEWLY_IDLE]);
goto out;
}
busiest = find_busiest_queue(group);
if (!busiest || busiest == this_rq) {
+ schedstat_inc(sd, lb_balanced[NEWLY_IDLE]);
schedstat_inc(sd, lb_nobusyq[NEWLY_IDLE]);
goto out;
}
@@ -2104,7 +2091,6 @@ static void active_load_balance(runqueue_t *busiest_rq, int busiest_cpu)
cpumask_t visited_cpus;
int cpu;
- schedstat_inc(busiest_rq, alb_cnt);
/*
* Search for suitable CPUs to push tasks to in successively higher
* domains with SD_LOAD_BALANCE set.
@@ -2115,6 +2101,8 @@ static void active_load_balance(runqueue_t *busiest_rq, int busiest_cpu)
/* no more domains to search */
break;
+ schedstat_inc(sd, alb_cnt);
+
cpu_group = sd->groups;
do {
for_each_cpu_mask(cpu, cpu_group->cpumask) {
@@ -2139,10 +2127,9 @@ static void active_load_balance(runqueue_t *busiest_rq, int busiest_cpu)
double_lock_balance(busiest_rq, target_rq);
if (move_tasks(target_rq, cpu, busiest_rq,
1, sd, SCHED_IDLE)) {
- schedstat_inc(busiest_rq, alb_lost);
- schedstat_inc(target_rq, alb_gained);
+ schedstat_inc(sd, alb_pushed);
} else {
- schedstat_inc(busiest_rq, alb_failed);
+ schedstat_inc(sd, alb_failed);
}
spin_unlock(&target_rq->lock);
}
@@ -2241,6 +2228,32 @@ DEFINE_PER_CPU(struct kernel_stat, kstat);
EXPORT_PER_CPU_SYMBOL(kstat);
/*
+ * This is called on clock ticks and on context switches.
+ * Bank in p->sched_time the ns elapsed since the last tick or switch.
+ */
+static inline void update_cpu_clock(task_t *p, runqueue_t *rq,
+ unsigned long long now)
+{
+ unsigned long long last = max(p->timestamp, rq->timestamp_last_tick);
+ p->sched_time += now - last;
+}
+
+/*
+ * Return current->sched_time plus any more ns on the sched_clock
+ * that have not yet been banked.
+ */
+unsigned long long current_sched_time(const task_t *tsk)
+{
+ unsigned long long ns;
+ unsigned long flags;
+ local_irq_save(flags);
+ ns = max(tsk->timestamp, task_rq(tsk)->timestamp_last_tick);
+ ns = tsk->sched_time + (sched_clock() - ns);
+ local_irq_restore(flags);
+ return ns;
+}
+
+/*
* We place interactive tasks back into the active array, if possible.
*
* To guarantee that this does not starve expired tasks we ignore the
@@ -2257,70 +2270,6 @@ EXPORT_PER_CPU_SYMBOL(kstat);
((rq)->curr->static_prio > (rq)->best_expired_prio))
/*
- * Do the virtual cpu time signal calculations.
- * @p: the process that the cpu time gets accounted to
- * @cputime: the cpu time spent in user space since the last update
- */
-static inline void account_it_virt(struct task_struct * p, cputime_t cputime)
-{
- cputime_t it_virt = p->it_virt_value;
-
- if (cputime_gt(it_virt, cputime_zero) &&
- cputime_gt(cputime, cputime_zero)) {
- if (cputime_ge(cputime, it_virt)) {
- it_virt = cputime_add(it_virt, p->it_virt_incr);
- send_sig(SIGVTALRM, p, 1);
- }
- it_virt = cputime_sub(it_virt, cputime);
- p->it_virt_value = it_virt;
- }
-}
-
-/*
- * Do the virtual profiling signal calculations.
- * @p: the process that the cpu time gets accounted to
- * @cputime: the cpu time spent in user and kernel space since the last update
- */
-static void account_it_prof(struct task_struct *p, cputime_t cputime)
-{
- cputime_t it_prof = p->it_prof_value;
-
- if (cputime_gt(it_prof, cputime_zero) &&
- cputime_gt(cputime, cputime_zero)) {
- if (cputime_ge(cputime, it_prof)) {
- it_prof = cputime_add(it_prof, p->it_prof_incr);
- send_sig(SIGPROF, p, 1);
- }
- it_prof = cputime_sub(it_prof, cputime);
- p->it_prof_value = it_prof;
- }
-}
-
-/*
- * Check if the process went over its cputime resource limit after
- * some cpu time got added to utime/stime.
- * @p: the process that the cpu time gets accounted to
- * @cputime: the cpu time spent in user and kernel space since the last update
- */
-static void check_rlimit(struct task_struct *p, cputime_t cputime)
-{
- cputime_t total, tmp;
- unsigned long secs;
-
- total = cputime_add(p->utime, p->stime);
- secs = cputime_to_secs(total);
- if (unlikely(secs >= p->signal->rlim[RLIMIT_CPU].rlim_cur)) {
- /* Send SIGXCPU every second. */
- tmp = cputime_sub(total, cputime);
- if (cputime_to_secs(tmp) < secs)
- send_sig(SIGXCPU, p, 1);
- /* and SIGKILL when we go over max.. */
- if (secs >= p->signal->rlim[RLIMIT_CPU].rlim_max)
- send_sig(SIGKILL, p, 1);
- }
-}
-
-/*
* Account user cpu time to a process.
* @p: the process that the cpu time gets accounted to
* @hardirq_offset: the offset to subtract from hardirq_count()
@@ -2333,11 +2282,6 @@ void account_user_time(struct task_struct *p, cputime_t cputime)
p->utime = cputime_add(p->utime, cputime);
- /* Check for signals (SIGVTALRM, SIGPROF, SIGXCPU & SIGKILL). */
- check_rlimit(p, cputime);
- account_it_virt(p, cputime);
- account_it_prof(p, cputime);
-
/* Add user time to cpustat. */
tmp = cputime_to_cputime64(cputime);
if (TASK_NICE(p) > 0)
@@ -2361,12 +2305,6 @@ void account_system_time(struct task_struct *p, int hardirq_offset,
p->stime = cputime_add(p->stime, cputime);
- /* Check for signals (SIGPROF, SIGXCPU & SIGKILL). */
- if (likely(p->signal && p->exit_state < EXIT_ZOMBIE)) {
- check_rlimit(p, cputime);
- account_it_prof(p, cputime);
- }
-
/* Add system time to cpustat. */
tmp = cputime_to_cputime64(cputime);
if (hardirq_count() - hardirq_offset)
@@ -2379,6 +2317,10 @@ void account_system_time(struct task_struct *p, int hardirq_offset,
cpustat->iowait = cputime64_add(cpustat->iowait, tmp);
else
cpustat->idle = cputime64_add(cpustat->idle, tmp);
+ /* Account for system time used */
+ acct_update_integrals(p);
+ /* Update rss highwater mark */
+ update_mem_hiwater(p);
}
/*
@@ -2414,8 +2356,11 @@ void scheduler_tick(void)
int cpu = smp_processor_id();
runqueue_t *rq = this_rq();
task_t *p = current;
+ unsigned long long now = sched_clock();
- rq->timestamp_last_tick = sched_clock();
+ update_cpu_clock(p, rq, now);
+
+ rq->timestamp_last_tick = now;
if (p == rq->idle) {
if (wake_priority_sleeper(rq))
@@ -2703,9 +2648,11 @@ need_resched_nonpreemptible:
schedstat_inc(rq, sched_cnt);
now = sched_clock();
- if (likely(now - prev->timestamp < NS_MAX_SLEEP_AVG))
+ if (likely((long long)now - prev->timestamp < NS_MAX_SLEEP_AVG)) {
run_time = now - prev->timestamp;
- else
+ if (unlikely((long long)now - prev->timestamp < 0))
+ run_time = 0;
+ } else
run_time = NS_MAX_SLEEP_AVG;
/*
@@ -2773,8 +2720,7 @@ go_idle:
array = rq->active;
rq->expired_timestamp = 0;
rq->best_expired_prio = MAX_PRIO;
- } else
- schedstat_inc(rq, sched_noswitch);
+ }
idx = sched_find_first_bit(array->bitmap);
queue = array->queue + idx;
@@ -2782,6 +2728,8 @@ go_idle:
if (!rt_task(next) && next->activated > 0) {
unsigned long long delta = now - next->timestamp;
+ if (unlikely((long long)now - next->timestamp < 0))
+ delta = 0;
if (next->activated == 1)
delta = delta * (ON_RUNQUEUE_WEIGHT * 128 / 100) / 128;
@@ -2799,6 +2747,8 @@ switch_tasks:
clear_tsk_need_resched(prev);
rcu_qsctr_inc(task_cpu(prev));
+ update_cpu_clock(prev, rq, now);
+
prev->sleep_avg -= run_time;
if ((long)prev->sleep_avg <= 0)
prev->sleep_avg = 0;
@@ -3578,6 +3528,7 @@ long sched_setaffinity(pid_t pid, cpumask_t new_mask)
{
task_t *p;
int retval;
+ cpumask_t cpus_allowed;
lock_cpu_hotplug();
read_lock(&tasklist_lock);
@@ -3602,6 +3553,8 @@ long sched_setaffinity(pid_t pid, cpumask_t new_mask)
!capable(CAP_SYS_NICE))
goto out_unlock;
+ cpus_allowed = cpuset_cpus_allowed(p);
+ cpus_and(new_mask, new_mask, cpus_allowed);
retval = set_cpus_allowed(p, new_mask);
out_unlock:
@@ -3788,14 +3741,11 @@ EXPORT_SYMBOL(cond_resched);
*/
int cond_resched_lock(spinlock_t * lock)
{
-#if defined(CONFIG_SMP) && defined(CONFIG_PREEMPT)
- if (lock->break_lock) {
- lock->break_lock = 0;
+ if (need_lockbreak(lock)) {
spin_unlock(lock);
cpu_relax();
spin_lock(lock);
}
-#endif
if (need_resched()) {
_raw_spin_unlock(lock);
preempt_enable_no_resched();
@@ -4058,6 +4008,7 @@ void __devinit init_idle(task_t *idle, int cpu)
idle->array = NULL;
idle->prio = MAX_PRIO;
idle->state = TASK_RUNNING;
+ idle->cpus_allowed = cpumask_of_cpu(cpu);
set_task_cpu(idle, cpu);
spin_lock_irqsave(&rq->lock, flags);
@@ -4278,7 +4229,7 @@ static void move_task_off_dead_cpu(int dead_cpu, struct task_struct *tsk)
/* No more Mr. Nice Guy. */
if (dest_cpu == NR_CPUS) {
- cpus_setall(tsk->cpus_allowed);
+ tsk->cpus_allowed = cpuset_cpus_allowed(tsk);
dest_cpu = any_online_cpu(tsk->cpus_allowed);
/*
diff --git a/kernel/seccomp.c b/kernel/seccomp.c
new file mode 100644
index 0000000000000..c3391b6020e85
--- /dev/null
+++ b/kernel/seccomp.c
@@ -0,0 +1,56 @@
+/*
+ * linux/kernel/seccomp.c
+ *
+ * Copyright 2004-2005 Andrea Arcangeli <andrea@cpushare.com>
+ *
+ * This defines a simple but solid secure-computing mode.
+ */
+
+#include <linux/seccomp.h>
+#include <linux/sched.h>
+
+/* #define SECCOMP_DEBUG 1 */
+
+/*
+ * Secure computing mode 1 allows only read/write/exit/sigreturn.
+ * To be fully secure this must be combined with rlimit
+ * to limit the stack allocations too.
+ */
+static int mode1_syscalls[] = {
+ __NR_seccomp_read, __NR_seccomp_write, __NR_seccomp_exit, __NR_seccomp_sigreturn,
+ 0, /* null terminated */
+};
+
+#ifdef TIF_32BIT
+static int mode1_syscalls_32[] = {
+ __NR_seccomp_read_32, __NR_seccomp_write_32, __NR_seccomp_exit_32, __NR_seccomp_sigreturn_32,
+ 0, /* null terminated */
+};
+#endif
+
+void __secure_computing(int this_syscall)
+{
+ int mode = current->seccomp.mode;
+ int * syscall;
+
+ switch (mode) {
+ case 1:
+ syscall = mode1_syscalls;
+#ifdef TIF_32BIT
+ if (test_thread_flag(TIF_32BIT))
+ syscall = mode1_syscalls_32;
+#endif
+ do {
+ if (*syscall == this_syscall)
+ return;
+ } while (*++syscall);
+ break;
+ default:
+ BUG();
+ }
+
+#ifdef SECCOMP_DEBUG
+ dump_stack();
+#endif
+ do_exit(SIGKILL);
+}
diff --git a/kernel/signal.c b/kernel/signal.c
index 9e87ab3f8f21f..f00a1d610f0bb 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -22,13 +22,12 @@
#include <linux/security.h>
#include <linux/syscalls.h>
#include <linux/ptrace.h>
+#include <linux/posix-timers.h>
#include <asm/param.h>
#include <asm/uaccess.h>
#include <asm/unistd.h>
#include <asm/siginfo.h>
-extern void k_getrusage(struct task_struct *, int, struct rusage *);
-
/*
* SLAB caches for signal bits.
*/
@@ -260,19 +259,23 @@ next_signal(struct sigpending *pending, sigset_t *mask)
return sig;
}
-static struct sigqueue *__sigqueue_alloc(struct task_struct *t, int flags)
+static struct sigqueue *__sigqueue_alloc(struct task_struct *t, unsigned int __nocast flags,
+ int override_rlimit)
{
struct sigqueue *q = NULL;
- if (atomic_read(&t->user->sigpending) <
+ atomic_inc(&t->user->sigpending);
+ if (override_rlimit ||
+ atomic_read(&t->user->sigpending) <=
t->signal->rlim[RLIMIT_SIGPENDING].rlim_cur)
q = kmem_cache_alloc(sigqueue_cachep, flags);
- if (q) {
+ if (unlikely(q == NULL)) {
+ atomic_dec(&t->user->sigpending);
+ } else {
INIT_LIST_HEAD(&q->list);
q->flags = 0;
q->lock = NULL;
q->user = get_uid(t->user);
- atomic_inc(&q->user->sigpending);
}
return(q);
}
@@ -347,7 +350,9 @@ void __exit_signal(struct task_struct *tsk)
if (!atomic_read(&sig->count))
BUG();
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;
@@ -381,6 +386,7 @@ void __exit_signal(struct task_struct *tsk)
sig->maj_flt += tsk->maj_flt;
sig->nvcsw += tsk->nvcsw;
sig->nivcsw += tsk->nivcsw;
+ sig->sched_time += tsk->sched_time;
spin_unlock(&sighand->siglock);
sig = NULL; /* Marker for below. */
}
@@ -402,6 +408,7 @@ void __exit_signal(struct task_struct *tsk)
* signals are constrained to threads inside the group.
*/
exit_itimers(sig);
+ exit_thread_group_keys(sig);
kmem_cache_free(signal_cachep, sig);
}
}
@@ -564,7 +571,15 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info)
if ( signr &&
((info->si_code & __SI_MASK) == __SI_TIMER) &&
info->si_sys_private){
+ /*
+ * Release the siglock to ensure proper locking order
+ * of timer locks outside of siglocks. Note, we leave
+ * irqs disabled here, since the posix-timers code is
+ * about to disable them again anyway.
+ */
+ spin_unlock(&tsk->sighand->siglock);
do_schedule_next_timer(info);
+ spin_lock(&tsk->sighand->siglock);
}
return signr;
}
@@ -793,7 +808,9 @@ static int send_signal(int sig, struct siginfo *info, struct task_struct *t,
make sure at least one signal gets delivered and don't
pass on the info struct. */
- q = __sigqueue_alloc(t, GFP_ATOMIC);
+ q = __sigqueue_alloc(t, GFP_ATOMIC, (sig < SIGRTMIN &&
+ ((unsigned long) info < 2 ||
+ info->si_code >= 0)));
if (q) {
list_add_tail(&q->list, &signals->list);
switch ((unsigned long) info) {
@@ -1036,7 +1053,7 @@ __group_complete_signal(int sig, struct task_struct *p)
return;
}
-static int
+int
__group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p)
{
int ret = 0;
@@ -1316,7 +1333,7 @@ struct sigqueue *sigqueue_alloc(void)
{
struct sigqueue *q;
- if ((q = __sigqueue_alloc(current, GFP_KERNEL)))
+ if ((q = __sigqueue_alloc(current, GFP_KERNEL, 0)))
q->flags |= SIGQUEUE_PREALLOC;
return(q);
}
@@ -1728,6 +1745,7 @@ do_signal_stop(int signr)
* with another processor delivering a stop signal,
* then the SIGCONT that wakes us up should clear it.
*/
+ read_unlock(&tasklist_lock);
return 0;
}
@@ -2201,6 +2219,8 @@ sys_rt_sigtimedwait(const sigset_t __user *uthese,
current->state = TASK_INTERRUPTIBLE;
timeout = schedule_timeout(timeout);
+ if (current->flags & PF_FREEZE)
+ refrigerator(PF_FREEZE);
spin_lock_irq(&current->sighand->siglock);
sig = dequeue_signal(current, &these, &info);
current->blocked = current->real_blocked;
@@ -2432,7 +2452,7 @@ do_sigaltstack (const stack_t __user *uss, stack_t __user *uoss, unsigned long s
int ss_flags;
error = -EFAULT;
- if (verify_area(VERIFY_READ, uss, sizeof(*uss))
+ if (!access_ok(VERIFY_READ, uss, sizeof(*uss))
|| __get_user(ss_sp, &uss->ss_sp)
|| __get_user(ss_flags, &uss->ss_flags)
|| __get_user(ss_size, &uss->ss_size))
diff --git a/kernel/softirq.c b/kernel/softirq.c
index 582a1e8091bc6..b4ab6af1dea85 100644
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
@@ -355,8 +355,12 @@ static int ksoftirqd(void * __bind_cpu)
set_current_state(TASK_INTERRUPTIBLE);
while (!kthread_should_stop()) {
- if (!local_softirq_pending())
+ preempt_disable();
+ if (!local_softirq_pending()) {
+ preempt_enable_no_resched();
schedule();
+ preempt_disable();
+ }
__set_current_state(TASK_RUNNING);
@@ -364,14 +368,14 @@ static int ksoftirqd(void * __bind_cpu)
/* Preempt disable stops cpu going offline.
If already offline, we'll be on wrong CPU:
don't process */
- preempt_disable();
if (cpu_is_offline((long)__bind_cpu))
goto wait_to_die;
do_softirq();
- preempt_enable();
+ preempt_enable_no_resched();
cond_resched();
+ preempt_disable();
}
-
+ preempt_enable();
set_current_state(TASK_INTERRUPTIBLE);
}
__set_current_state(TASK_RUNNING);
diff --git a/kernel/spinlock.c b/kernel/spinlock.c
index b8e76ca8a001f..e15ed17863f16 100644
--- a/kernel/spinlock.c
+++ b/kernel/spinlock.c
@@ -187,6 +187,7 @@ void __lockfunc _##op##_lock(locktype##_t *lock) \
cpu_relax(); \
preempt_disable(); \
} \
+ (lock)->break_lock = 0; \
} \
\
EXPORT_SYMBOL(_##op##_lock); \
@@ -209,6 +210,7 @@ unsigned long __lockfunc _##op##_lock_irqsave(locktype##_t *lock) \
cpu_relax(); \
preempt_disable(); \
} \
+ (lock)->break_lock = 0; \
return flags; \
} \
\
diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
index e31b1cb8e5030..c39ed70af1740 100644
--- a/kernel/stop_machine.c
+++ b/kernel/stop_machine.c
@@ -6,6 +6,7 @@
#include <linux/syscalls.h>
#include <asm/atomic.h>
#include <asm/semaphore.h>
+#include <asm/uaccess.h>
/* Since we effect priority and affinity (both of which are visible
* to, and settable by outside processes) we do indirection via a
@@ -86,9 +87,13 @@ 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. */
- sys_sched_setscheduler(current->pid, SCHED_FIFO, &param);
+ set_fs(KERNEL_DS);
+ sys_sched_setscheduler(current->pid, SCHED_FIFO,
+ (struct sched_param __user *)&param);
+ set_fs(old_fs);
atomic_set(&stopmachine_thread_ack, 0);
stopmachine_num_threads = 0;
diff --git a/kernel/sys.c b/kernel/sys.c
index 6e354fd380e7a..462d78d558951 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -20,6 +20,7 @@
#include <linux/device.h>
#include <linux/key.h>
#include <linux/times.h>
+#include <linux/posix-timers.h>
#include <linux/security.h>
#include <linux/dcookies.h>
#include <linux/suspend.h>
@@ -89,7 +90,7 @@ int cad_pid = 1;
*/
static struct notifier_block *reboot_notifier_list;
-DEFINE_RWLOCK(notifier_lock);
+static DEFINE_RWLOCK(notifier_lock);
/**
* notifier_chain_register - Add notifier to a notifier chain
@@ -216,12 +217,13 @@ int unregister_reboot_notifier(struct notifier_block * nb)
}
EXPORT_SYMBOL(unregister_reboot_notifier);
+
static int set_one_prio(struct task_struct *p, int niceval, int error)
{
int no_nice;
if (p->uid != current->euid &&
- p->uid != current->uid && !capable(CAP_SYS_NICE)) {
+ p->euid != current->euid && !capable(CAP_SYS_NICE)) {
error = -EPERM;
goto out;
}
@@ -1501,6 +1503,20 @@ asmlinkage long sys_setrlimit(unsigned int resource, struct rlimit __user *rlim)
task_lock(current->group_leader);
*old_rlim = new_rlim;
task_unlock(current->group_leader);
+
+ if (resource == RLIMIT_CPU && new_rlim.rlim_cur != RLIM_INFINITY &&
+ (cputime_eq(current->signal->it_prof_expires, cputime_zero) ||
+ new_rlim.rlim_cur <= cputime_to_secs(
+ current->signal->it_prof_expires))) {
+ cputime_t cputime = secs_to_cputime(new_rlim.rlim_cur);
+ read_lock(&tasklist_lock);
+ spin_lock_irq(&current->sighand->siglock);
+ set_process_cpu_timer(current, CPUCLOCK_PROF,
+ &cputime, NULL);
+ spin_unlock_irq(&current->sighand->siglock);
+ read_unlock(&tasklist_lock);
+ }
+
return 0;
}
@@ -1524,7 +1540,7 @@ asmlinkage long sys_setrlimit(unsigned int resource, struct rlimit __user *rlim)
* given child after it's reaped, or none so this sample is before reaping.
*/
-void k_getrusage(struct task_struct *p, int who, struct rusage *r)
+static void k_getrusage(struct task_struct *p, int who, struct rusage *r)
{
struct task_struct *t;
unsigned long flags;
diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
index 1bb70036fd728..1802a311dd3f8 100644
--- a/kernel/sys_ni.c
+++ b/kernel/sys_ni.c
@@ -12,74 +12,75 @@ asmlinkage long sys_ni_syscall(void)
return -ENOSYS;
}
-cond_syscall(sys_nfsservctl)
-cond_syscall(sys_quotactl)
-cond_syscall(sys_acct)
-cond_syscall(sys_lookup_dcookie)
-cond_syscall(sys_swapon)
-cond_syscall(sys_swapoff)
-cond_syscall(sys_init_module)
-cond_syscall(sys_delete_module)
-cond_syscall(sys_socketpair)
-cond_syscall(sys_bind)
-cond_syscall(sys_listen)
-cond_syscall(sys_accept)
-cond_syscall(sys_connect)
-cond_syscall(sys_getsockname)
-cond_syscall(sys_getpeername)
-cond_syscall(sys_sendto)
-cond_syscall(sys_send)
-cond_syscall(sys_recvfrom)
-cond_syscall(sys_recv)
-cond_syscall(sys_socket)
-cond_syscall(sys_setsockopt)
-cond_syscall(sys_getsockopt)
-cond_syscall(sys_shutdown)
-cond_syscall(sys_sendmsg)
-cond_syscall(sys_recvmsg)
-cond_syscall(sys_socketcall)
-cond_syscall(sys_futex)
-cond_syscall(compat_sys_futex)
-cond_syscall(sys_epoll_create)
-cond_syscall(sys_epoll_ctl)
-cond_syscall(sys_epoll_wait)
-cond_syscall(sys_semget)
-cond_syscall(sys_semop)
-cond_syscall(sys_semtimedop)
-cond_syscall(sys_semctl)
-cond_syscall(sys_msgget)
-cond_syscall(sys_msgsnd)
-cond_syscall(sys_msgrcv)
-cond_syscall(sys_msgctl)
-cond_syscall(sys_shmget)
-cond_syscall(sys_shmdt)
-cond_syscall(sys_shmctl)
-cond_syscall(sys_mq_open)
-cond_syscall(sys_mq_unlink)
-cond_syscall(sys_mq_timedsend)
-cond_syscall(sys_mq_timedreceive)
-cond_syscall(sys_mq_notify)
-cond_syscall(sys_mq_getsetattr)
-cond_syscall(compat_sys_mq_open)
-cond_syscall(compat_sys_mq_timedsend)
-cond_syscall(compat_sys_mq_timedreceive)
-cond_syscall(compat_sys_mq_notify)
-cond_syscall(compat_sys_mq_getsetattr)
-cond_syscall(sys_mbind)
-cond_syscall(sys_get_mempolicy)
-cond_syscall(sys_set_mempolicy)
-cond_syscall(compat_sys_mbind)
-cond_syscall(compat_sys_get_mempolicy)
-cond_syscall(compat_sys_set_mempolicy)
-cond_syscall(sys_add_key)
-cond_syscall(sys_request_key)
-cond_syscall(sys_keyctl)
-cond_syscall(compat_sys_keyctl)
-cond_syscall(compat_sys_socketcall)
+cond_syscall(sys_nfsservctl);
+cond_syscall(sys_quotactl);
+cond_syscall(sys_acct);
+cond_syscall(sys_lookup_dcookie);
+cond_syscall(sys_swapon);
+cond_syscall(sys_swapoff);
+cond_syscall(sys_init_module);
+cond_syscall(sys_delete_module);
+cond_syscall(sys_socketpair);
+cond_syscall(sys_bind);
+cond_syscall(sys_listen);
+cond_syscall(sys_accept);
+cond_syscall(sys_connect);
+cond_syscall(sys_getsockname);
+cond_syscall(sys_getpeername);
+cond_syscall(sys_sendto);
+cond_syscall(sys_send);
+cond_syscall(sys_recvfrom);
+cond_syscall(sys_recv);
+cond_syscall(sys_socket);
+cond_syscall(sys_setsockopt);
+cond_syscall(sys_getsockopt);
+cond_syscall(sys_shutdown);
+cond_syscall(sys_sendmsg);
+cond_syscall(sys_recvmsg);
+cond_syscall(sys_socketcall);
+cond_syscall(sys_futex);
+cond_syscall(compat_sys_futex);
+cond_syscall(sys_epoll_create);
+cond_syscall(sys_epoll_ctl);
+cond_syscall(sys_epoll_wait);
+cond_syscall(sys_semget);
+cond_syscall(sys_semop);
+cond_syscall(sys_semtimedop);
+cond_syscall(sys_semctl);
+cond_syscall(sys_msgget);
+cond_syscall(sys_msgsnd);
+cond_syscall(sys_msgrcv);
+cond_syscall(sys_msgctl);
+cond_syscall(sys_shmget);
+cond_syscall(sys_shmdt);
+cond_syscall(sys_shmctl);
+cond_syscall(sys_mq_open);
+cond_syscall(sys_mq_unlink);
+cond_syscall(sys_mq_timedsend);
+cond_syscall(sys_mq_timedreceive);
+cond_syscall(sys_mq_notify);
+cond_syscall(sys_mq_getsetattr);
+cond_syscall(compat_sys_mq_open);
+cond_syscall(compat_sys_mq_timedsend);
+cond_syscall(compat_sys_mq_timedreceive);
+cond_syscall(compat_sys_mq_notify);
+cond_syscall(compat_sys_mq_getsetattr);
+cond_syscall(sys_mbind);
+cond_syscall(sys_get_mempolicy);
+cond_syscall(sys_set_mempolicy);
+cond_syscall(compat_sys_mbind);
+cond_syscall(compat_sys_get_mempolicy);
+cond_syscall(compat_sys_set_mempolicy);
+cond_syscall(sys_add_key);
+cond_syscall(sys_request_key);
+cond_syscall(sys_keyctl);
+cond_syscall(compat_sys_keyctl);
+cond_syscall(compat_sys_socketcall);
/* arch-specific weak syscall entries */
-cond_syscall(sys_pciconfig_read)
-cond_syscall(sys_pciconfig_write)
-cond_syscall(sys_pciconfig_iobase)
-cond_syscall(sys32_ipc)
-cond_syscall(sys32_sysctl)
+cond_syscall(sys_pciconfig_read);
+cond_syscall(sys_pciconfig_write);
+cond_syscall(sys_pciconfig_iobase);
+cond_syscall(sys32_ipc);
+cond_syscall(sys32_sysctl);
+cond_syscall(ppc_rtas);
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index ec430d0e5b01d..79dbd93bd697c 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -121,6 +121,8 @@ extern int sysctl_hz_timer;
extern int acct_parm[];
#endif
+int randomize_va_space = 1;
+
static int parse_table(int __user *, int, void __user *, size_t __user *, void __user *, size_t,
ctl_table *, void **);
static int proc_doutsstring(ctl_table *table, int write, struct file *filp,
@@ -632,6 +634,15 @@ static ctl_table kern_table[] = {
.proc_handler = &proc_dointvec,
},
#endif
+ {
+ .ctl_name = KERN_RANDOMIZE,
+ .procname = "randomize_va_space",
+ .data = &randomize_va_space,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec,
+ },
+
{ .ctl_name = 0 }
};
@@ -1366,6 +1377,7 @@ static ssize_t proc_writesys(struct file * file, const char __user * buf,
* @filp: the file structure
* @buffer: the user buffer
* @lenp: the size of the user buffer
+ * @ppos: file position
*
* Reads/writes a string from/to the user buffer. If the kernel
* buffer provided is not large enough to hold the string, the
@@ -1582,6 +1594,7 @@ static int do_proc_dointvec(ctl_table *table, int write, struct file *filp,
* @filp: the file structure
* @buffer: the user buffer
* @lenp: the size of the user buffer
+ * @ppos: file position
*
* Reads/writes up to table->maxlen/sizeof(unsigned int) integer
* values from/to the user buffer, treated as an ASCII string.
@@ -1686,6 +1699,7 @@ static int do_proc_dointvec_minmax_conv(int *negp, unsigned long *lvalp,
* @filp: the file structure
* @buffer: the user buffer
* @lenp: the size of the user buffer
+ * @ppos: file position
*
* Reads/writes up to table->maxlen/sizeof(unsigned int) integer
* values from/to the user buffer, treated as an ASCII string.
@@ -1818,6 +1832,7 @@ static int do_proc_doulongvec_minmax(ctl_table *table, int write,
* @filp: the file structure
* @buffer: the user buffer
* @lenp: the size of the user buffer
+ * @ppos: file position
*
* Reads/writes up to table->maxlen/sizeof(unsigned long) unsigned long
* values from/to the user buffer, treated as an ASCII string.
@@ -1840,6 +1855,7 @@ int proc_doulongvec_minmax(ctl_table *table, int write, struct file *filp,
* @filp: the file structure
* @buffer: the user buffer
* @lenp: the size of the user buffer
+ * @ppos: file position
*
* Reads/writes up to table->maxlen/sizeof(unsigned long) unsigned long
* values from/to the user buffer, treated as an ASCII string. The values
@@ -1902,6 +1918,27 @@ static int do_proc_dointvec_userhz_jiffies_conv(int *negp, unsigned long *lvalp,
return 0;
}
+static int do_proc_dointvec_ms_jiffies_conv(int *negp, unsigned long *lvalp,
+ int *valp,
+ int write, void *data)
+{
+ if (write) {
+ *valp = msecs_to_jiffies(*negp ? -*lvalp : *lvalp);
+ } else {
+ int val = *valp;
+ unsigned long lval;
+ if (val < 0) {
+ *negp = -1;
+ lval = (unsigned long)-val;
+ } else {
+ *negp = 0;
+ lval = (unsigned long)val;
+ }
+ *lvalp = jiffies_to_msecs(lval);
+ }
+ return 0;
+}
+
/**
* proc_dointvec_jiffies - read a vector of integers as seconds
* @table: the sysctl table
@@ -1909,6 +1946,7 @@ static int do_proc_dointvec_userhz_jiffies_conv(int *negp, unsigned long *lvalp,
* @filp: the file structure
* @buffer: the user buffer
* @lenp: the size of the user buffer
+ * @ppos: file position
*
* Reads/writes up to table->maxlen/sizeof(unsigned int) integer
* values from/to the user buffer, treated as an ASCII string.
@@ -1946,6 +1984,28 @@ int proc_dointvec_userhz_jiffies(ctl_table *table, int write, struct file *filp,
do_proc_dointvec_userhz_jiffies_conv,NULL);
}
+/**
+ * proc_dointvec_ms_jiffies - read a vector of integers as 1 milliseconds
+ * @table: the sysctl table
+ * @write: %TRUE if this is a write to the sysctl file
+ * @filp: the file structure
+ * @buffer: the user buffer
+ * @lenp: the size of the user buffer
+ *
+ * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
+ * values from/to the user buffer, treated as an ASCII string.
+ * The values read are assumed to be in 1/1000 seconds, and
+ * are converted into jiffies.
+ *
+ * Returns 0 on success.
+ */
+int proc_dointvec_ms_jiffies(ctl_table *table, int write, struct file *filp,
+ void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+ return do_proc_dointvec(table, write, filp, buffer, lenp, ppos,
+ do_proc_dointvec_ms_jiffies_conv, NULL);
+}
+
#else /* CONFIG_PROC_FS */
int proc_dostring(ctl_table *table, int write, struct file *filp,
@@ -1990,6 +2050,12 @@ int proc_dointvec_userhz_jiffies(ctl_table *table, int write, struct file *filp,
return -ENOSYS;
}
+int proc_dointvec_ms_jiffies(ctl_table *table, int write, struct file *filp,
+ void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+ return -ENOSYS;
+}
+
int proc_doulongvec_minmax(ctl_table *table, int write, struct file *filp,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
@@ -2119,6 +2185,33 @@ int sysctl_jiffies(ctl_table *table, int __user *name, int nlen,
return 1;
}
+/* Strategy function to convert jiffies to seconds */
+int sysctl_ms_jiffies(ctl_table *table, int __user *name, int nlen,
+ void __user *oldval, size_t __user *oldlenp,
+ void __user *newval, size_t newlen, void **context)
+{
+ if (oldval) {
+ size_t olen;
+ if (oldlenp) {
+ if (get_user(olen, oldlenp))
+ return -EFAULT;
+ if (olen!=sizeof(int))
+ return -EINVAL;
+ }
+ if (put_user(jiffies_to_msecs(*(int *)(table->data)), (int __user *)oldval) ||
+ (oldlenp && put_user(sizeof(int),oldlenp)))
+ return -EFAULT;
+ }
+ if (newval && newlen) {
+ int new;
+ if (newlen != sizeof(int))
+ return -EINVAL;
+ if (get_user(new, (int __user *)newval))
+ return -EFAULT;
+ *(int *)(table->data) = msecs_to_jiffies(new);
+ }
+ return 1;
+}
#else /* CONFIG_SYSCTL */
@@ -2149,6 +2242,13 @@ int sysctl_jiffies(ctl_table *table, int __user *name, int nlen,
return -ENOSYS;
}
+int sysctl_ms_jiffies(ctl_table *table, int __user *name, int nlen,
+ void __user *oldval, size_t __user *oldlenp,
+ void __user *newval, size_t newlen, void **context)
+{
+ return -ENOSYS;
+}
+
int proc_dostring(ctl_table *table, int write, struct file *filp,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
@@ -2185,6 +2285,12 @@ int proc_dointvec_userhz_jiffies(ctl_table *table, int write, struct file *filp,
return -ENOSYS;
}
+int proc_dointvec_ms_jiffies(ctl_table *table, int write, struct file *filp,
+ void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+ return -ENOSYS;
+}
+
int proc_doulongvec_minmax(ctl_table *table, int write, struct file *filp,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
@@ -2219,11 +2325,13 @@ EXPORT_SYMBOL(proc_dointvec);
EXPORT_SYMBOL(proc_dointvec_jiffies);
EXPORT_SYMBOL(proc_dointvec_minmax);
EXPORT_SYMBOL(proc_dointvec_userhz_jiffies);
+EXPORT_SYMBOL(proc_dointvec_ms_jiffies);
EXPORT_SYMBOL(proc_dostring);
EXPORT_SYMBOL(proc_doulongvec_minmax);
EXPORT_SYMBOL(proc_doulongvec_ms_jiffies_minmax);
EXPORT_SYMBOL(register_sysctl_table);
EXPORT_SYMBOL(sysctl_intvec);
EXPORT_SYMBOL(sysctl_jiffies);
+EXPORT_SYMBOL(sysctl_ms_jiffies);
EXPORT_SYMBOL(sysctl_string);
EXPORT_SYMBOL(unregister_sysctl_table);
diff --git a/kernel/time.c b/kernel/time.c
index d5400f6af052d..96fd0f499631d 100644
--- a/kernel/time.c
+++ b/kernel/time.c
@@ -34,6 +34,7 @@
#include <linux/syscalls.h>
#include <linux/security.h>
#include <linux/fs.h>
+#include <linux/module.h>
#include <asm/uaccess.h>
#include <asm/unistd.h>
@@ -215,6 +216,14 @@ long pps_stbcnt; /* stability limit exceeded */
/* hook for a loadable hardpps kernel module */
void (*hardpps_ptr)(struct timeval *);
+/* we call this to notify the arch when the clock is being
+ * controlled. If no such arch routine, do nothing.
+ */
+void __attribute__ ((weak)) notify_arch_cmos_timer(void)
+{
+ return;
+}
+
/* adjtimex mainly allows reading (and writing, if superuser) of
* kernel time-keeping variables. used by xntpd.
*/
@@ -398,6 +407,7 @@ leave: if ((time_status & (STA_UNSYNC|STA_CLOCKERR)) != 0
txc->stbcnt = pps_stbcnt;
write_sequnlock_irq(&xtime_lock);
do_gettimeofday(&txc->time);
+ notify_arch_cmos_timer();
return(result);
}
@@ -494,6 +504,7 @@ void getnstimeofday (struct timespec *tv)
tv->tv_sec = sec;
tv->tv_nsec = nsec;
}
+EXPORT_SYMBOL_GPL(getnstimeofday);
int do_settimeofday (struct timespec *tv)
{
diff --git a/kernel/timer.c b/kernel/timer.c
index f764f0c2334b2..ecb3d67c0e149 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -30,6 +30,7 @@
#include <linux/thread_info.h>
#include <linux/time.h>
#include <linux/jiffies.h>
+#include <linux/posix-timers.h>
#include <linux/cpu.h>
#include <linux/syscalls.h>
@@ -48,8 +49,9 @@ static void time_interpolator_update(long delta_nsec);
/*
* per-CPU timer vector definitions:
*/
-#define TVN_BITS 6
-#define TVR_BITS 8
+
+#define TVN_BITS (CONFIG_BASE_SMALL ? 4 : 6)
+#define TVR_BITS (CONFIG_BASE_SMALL ? 6 : 8)
#define TVN_SIZE (1 << TVN_BITS)
#define TVR_SIZE (1 << TVR_BITS)
#define TVN_MASK (TVN_SIZE - 1)
@@ -587,10 +589,10 @@ long time_tolerance = MAXFREQ; /* frequency tolerance (ppm) */
long time_precision = 1; /* clock precision (us) */
long time_maxerror = NTP_PHASE_LIMIT; /* maximum error (us) */
long time_esterror = NTP_PHASE_LIMIT; /* estimated error (us) */
-long time_phase; /* phase offset (scaled us) */
+static long time_phase; /* phase offset (scaled us) */
long time_freq = (((NSEC_PER_SEC + HZ/2) % HZ - HZ/2) << SHIFT_USEC) / NSEC_PER_USEC;
/* frequency offset (scaled ppm)*/
-long time_adj; /* tick adjust (scaled 1 / HZ) */
+static long time_adj; /* tick adjust (scaled 1 / HZ) */
long time_reftime; /* time at last adjustment (s) */
long time_adjust;
long time_next_adjust;
@@ -824,6 +826,7 @@ void update_process_times(int user_tick)
if (rcu_pending(cpu))
rcu_check_callbacks(cpu, user_tick);
scheduler_tick();
+ run_posix_cpu_timers(p);
}
/*
@@ -844,6 +847,8 @@ static unsigned long count_active_tasks(void)
*/
unsigned long avenrun[3];
+EXPORT_SYMBOL(avenrun);
+
/*
* calc_load - given tick count, update the avenrun load estimates.
* This is called while holding a write_lock on xtime_lock.
diff --git a/kernel/user.c b/kernel/user.c
index 18f63146602a1..734575d55769b 100644
--- a/kernel/user.c
+++ b/kernel/user.c
@@ -18,7 +18,8 @@
* UID task count cache, to get fast user lookup in "alloc_uid"
* when changing user ID's (ie setuid() and friends).
*/
-#define UIDHASH_BITS 8
+
+#define UIDHASH_BITS (CONFIG_BASE_SMALL ? 3 : 8)
#define UIDHASH_SZ (1 << UIDHASH_BITS)
#define UIDHASH_MASK (UIDHASH_SZ - 1)
#define __uidhashfn(uid) (((uid >> UIDHASH_BITS) + uid) & UIDHASH_MASK)
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 5301935f609b7..52ef419d27479 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -423,6 +423,30 @@ void flush_scheduled_work(void)
flush_workqueue(keventd_wq);
}
+/**
+ * cancel_rearming_delayed_workqueue - reliably kill off a delayed
+ * work whose handler rearms the delayed work.
+ * @wq: the controlling workqueue structure
+ * @work: the delayed work struct
+ */
+static void cancel_rearming_delayed_workqueue(struct workqueue_struct *wq,
+ struct work_struct *work)
+{
+ while (!cancel_delayed_work(work))
+ flush_workqueue(wq);
+}
+
+/**
+ * cancel_rearming_delayed_work - reliably kill off a delayed keventd
+ * work whose handler rearms the delayed work.
+ * @work: the delayed work struct
+ */
+void cancel_rearming_delayed_work(struct work_struct *work)
+{
+ cancel_rearming_delayed_workqueue(keventd_wq, work);
+}
+EXPORT_SYMBOL(cancel_rearming_delayed_work);
+
int keventd_up(void)
{
return keventd_wq != NULL;
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 388af7c979271..426a0cf7b11c6 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -1,14 +1,23 @@
+config PRINTK_TIME
+ bool "Show timing information on printks"
+ help
+ Selecting this option causes timing information to be
+ included in printk output. This allows you to measure
+ the interval between kernel operations, including bootup
+ operations. This is useful for identifying long delays
+ in kernel startup.
+
+
config DEBUG_KERNEL
bool "Kernel debugging"
- depends on (ALPHA || ARM || CRIS || H8300 || X86 || IA64 || M32R || M68K || M68KNOMMU || MIPS || PARISC || PPC32 || PPC64 || ARCH_S390 || SUPERH || SUPERH64 || SPARC32 || SPARC64 || USERMODE || V850 || X86_64)
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 && (ALPHA || ARM || X86 || IA64 || M32R || M68K || MIPS || PARISC || PPC32 || PPC64 || ARCH_S390 || SUPERH || SUPERH64 || SPARC32 || SPARC64 || X86_64 || USERMODE)
+ depends on DEBUG_KERNEL && !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
@@ -20,12 +29,22 @@ config MAGIC_SYSRQ
keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
unless you really know what this hack does.
-config MAGIC_SYSRQ
- bool "Magic SysRq key"
- depends on DEBUG_KERNEL && (H8300 || M68KNOMMU || V850)
- help
- Enables console device to interpret special characters as
- commands to dump state information.
+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 16 if X86_NUMAQ || IA64
+ default 15 if SMP
+ default 14
+ help
+ Select kernel log buffer size as a power of 2.
+ Defaults and Examples:
+ 17 => 128 KB for S/390
+ 16 => 64 KB for x86 NUMAQ or IA-64
+ 15 => 32 KB for SMP
+ 14 => 16 KB for uniprocessor
+ 13 => 8 KB
+ 12 => 4 KB
config SCHEDSTATS
bool "Collect scheduler statistics"
@@ -41,7 +60,7 @@ config SCHEDSTATS
config DEBUG_SLAB
bool "Debug memory allocations"
- depends on DEBUG_KERNEL && (ALPHA || ARM || X86 || IA64 || M32R || M68K || MIPS || PARISC || PPC32 || PPC64 || ARCH_S390 || SPARC32 || SPARC64 || USERMODE || X86_64)
+ depends on DEBUG_KERNEL
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
@@ -49,7 +68,7 @@ config DEBUG_SLAB
config DEBUG_PREEMPT
bool "Debug preemptible kernel"
- depends on PREEMPT
+ depends on DEBUG_KERNEL && PREEMPT
default y
help
If you say Y here then the kernel will use a debug variant of the
@@ -59,7 +78,7 @@ config DEBUG_PREEMPT
config DEBUG_SPINLOCK
bool "Spinlock debugging"
- depends on DEBUG_KERNEL && (ALPHA || ARM || X86 || IA64 || M32R || MIPS || PARISC || PPC32 || (SUPERH && !SUPERH64) || SPARC32 || SPARC64 || USERMODE || X86_64)
+ depends on DEBUG_KERNEL
help
Say Y here and build SMP to catch missing spinlock initialization
and certain other kinds of spinlock errors commonly made. This is
@@ -68,7 +87,7 @@ config DEBUG_SPINLOCK
config DEBUG_SPINLOCK_SLEEP
bool "Sleep-inside-spinlock checking"
- depends on DEBUG_KERNEL && (X86 || IA64 || M32R || MIPS || PPC32 || PPC64 || ARCH_S390 || SPARC32 || SPARC64 || USERMODE)
+ depends on DEBUG_KERNEL
help
If you say Y here, various routines which may sleep will become very
noisy if they are called with a spinlock held.
@@ -82,14 +101,14 @@ config DEBUG_KOBJECT
config DEBUG_HIGHMEM
bool "Highmem debugging"
- depends on DEBUG_KERNEL && HIGHMEM && (X86 || PPC32 || MIPS || SPARC32)
+ depends on DEBUG_KERNEL && HIGHMEM
help
This options enables addition error checking for high memory systems.
Disable for production systems.
config DEBUG_BUGVERBOSE
bool "Verbose BUG() reporting (adds 70K)" if DEBUG_KERNEL && EMBEDDED
- depends on ARM || ARM26 || M32R || M68K || SPARC32 || SPARC64 || (X86 && !X86_64)
+ depends on ARM || ARM26 || M32R || M68K || SPARC32 || SPARC64 || (X86 && !X86_64) || FRV
default !EMBEDDED
help
Say Y here to make BUG() panics output the file name and line number
@@ -98,24 +117,13 @@ config DEBUG_BUGVERBOSE
config DEBUG_INFO
bool "Compile the kernel with debug info"
- depends on DEBUG_KERNEL && (ALPHA || CRIS || X86 || IA64 || M32R || M68K || MIPS || PARISC || PPC32 || PPC64 || ARCH_S390 || (SUPERH && !SUPERH64) || SPARC64 || V850 || X86_64)
+ depends on DEBUG_KERNEL
help
If you say Y here the resulting kernel image will include
debugging info resulting in a larger kernel image.
- Say Y here only if you plan to use gdb to debug the kernel.
- If you don't debug the kernel, you can say N.
+ Say Y here only if you plan to debug the kernel.
-config DEBUG_INFO
- bool "Enable kernel debugging symbols"
- depends on DEBUG_KERNEL && USERMODE
- help
- When this is enabled, the User-Mode Linux binary will include
- debugging symbols. This enlarges the binary by a few megabytes,
- but aids in tracking down kernel problems in UML. It is required
- if you intend to do any kernel development.
-
- If you're truly short on disk space or don't expect to report any
- bugs back to the UML developers, say N, otherwise say Y.
+ If unsure, say N.
config DEBUG_IOREMAP
bool "Enable ioremap() debugging"
@@ -140,13 +148,12 @@ config DEBUG_FS
If unsure, say N.
-if !X86_64
config FRAME_POINTER
bool "Compile the kernel with frame pointers"
- depends on X86 || CRIS || M68KNOMMU
+ depends on DEBUG_KERNEL && ((X86 && !X86_64) || CRIS || M68K || M68KNOMMU || FRV)
help
If you say Y here the resulting kernel image will be slightly larger
and slower, but it will give very useful debugging information.
If you don't debug the kernel, you can say N, but we may not be able
to solve problems without frame pointers.
-endif
+
diff --git a/lib/Makefile b/lib/Makefile
index 8cb331ab0c3f2..7c70db79c0e09 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -4,8 +4,11 @@
lib-y := errno.o ctype.o string.o vsprintf.o cmdline.o \
bust_spinlocks.o rbtree.o radix-tree.o dump_stack.o \
- kobject.o kref.o idr.o div64.o parser.o int_sqrt.o \
- bitmap.o extable.o kobject_uevent.o prio_tree.o
+ kobject.o kref.o idr.o div64.o int_sqrt.o \
+ bitmap.o extable.o kobject_uevent.o prio_tree.o sha1.o \
+ halfmd4.o
+
+obj-y += sort.o parser.o
ifeq ($(CONFIG_DEBUG_KOBJECT),y)
CFLAGS_kobject.o += -DDEBUG
diff --git a/lib/bitmap.c b/lib/bitmap.c
index f7414e7fd0461..d1388a5ce89c3 100644
--- a/lib/bitmap.c
+++ b/lib/bitmap.c
@@ -291,6 +291,7 @@ EXPORT_SYMBOL(__bitmap_weight);
#define nbits_to_hold_value(val) fls(val)
#define roundup_power2(val,modulus) (((val) + (modulus) - 1) & ~((modulus) - 1))
#define unhex(c) (isdigit(c) ? (c - '0') : (toupper(c) - 'A' + 10))
+#define BASEDEC 10 /* fancier cpuset lists input in decimal */
/**
* bitmap_scnprintf - convert bitmap to an ASCII hex string.
@@ -409,6 +410,108 @@ int bitmap_parse(const char __user *ubuf, unsigned int ubuflen,
}
EXPORT_SYMBOL(bitmap_parse);
+/*
+ * bscnl_emit(buf, buflen, rbot, rtop, bp)
+ *
+ * Helper routine for bitmap_scnlistprintf(). Write decimal number
+ * or range to buf, suppressing output past buf+buflen, with optional
+ * comma-prefix. Return len of what would be written to buf, if it
+ * all fit.
+ */
+static inline int bscnl_emit(char *buf, int buflen, int rbot, int rtop, int len)
+{
+ if (len > 0)
+ len += scnprintf(buf + len, buflen - len, ",");
+ if (rbot == rtop)
+ len += scnprintf(buf + len, buflen - len, "%d", rbot);
+ else
+ len += scnprintf(buf + len, buflen - len, "%d-%d", rbot, rtop);
+ return len;
+}
+
+/**
+ * bitmap_scnlistprintf - convert bitmap to list format ASCII string
+ * @buf: byte buffer into which string is placed
+ * @buflen: reserved size of @buf, in bytes
+ * @maskp: pointer to bitmap to convert
+ * @nmaskbits: size of bitmap, in bits
+ *
+ * Output format is a comma-separated list of decimal numbers and
+ * ranges. Consecutively set bits are shown as two hyphen-separated
+ * decimal numbers, the smallest and largest bit numbers set in
+ * the range. Output format is compatible with the format
+ * accepted as input by bitmap_parselist().
+ *
+ * The return value is the number of characters which would be
+ * generated for the given input, excluding the trailing '\0', as
+ * per ISO C99.
+ */
+int bitmap_scnlistprintf(char *buf, unsigned int buflen,
+ const unsigned long *maskp, int nmaskbits)
+{
+ int len = 0;
+ /* current bit is 'cur', most recently seen range is [rbot, rtop] */
+ int cur, rbot, rtop;
+
+ rbot = cur = find_first_bit(maskp, nmaskbits);
+ while (cur < nmaskbits) {
+ rtop = cur;
+ cur = find_next_bit(maskp, nmaskbits, cur+1);
+ if (cur >= nmaskbits || cur > rtop + 1) {
+ len = bscnl_emit(buf, buflen, rbot, rtop, len);
+ rbot = cur;
+ }
+ }
+ return len;
+}
+EXPORT_SYMBOL(bitmap_scnlistprintf);
+
+/**
+ * bitmap_parselist - convert list format ASCII string to bitmap
+ * @buf: read nul-terminated user string from this buffer
+ * @mask: write resulting mask here
+ * @nmaskbits: number of bits in mask to be written
+ *
+ * Input format is a comma-separated list of decimal numbers and
+ * ranges. Consecutively set bits are shown as two hyphen-separated
+ * decimal numbers, the smallest and largest bit numbers set in
+ * the range.
+ *
+ * Returns 0 on success, -errno on invalid input strings:
+ * -EINVAL: second number in range smaller than first
+ * -EINVAL: invalid character in string
+ * -ERANGE: bit number specified too large for mask
+ */
+int bitmap_parselist(const char *bp, unsigned long *maskp, int nmaskbits)
+{
+ unsigned a, b;
+
+ bitmap_zero(maskp, nmaskbits);
+ do {
+ if (!isdigit(*bp))
+ return -EINVAL;
+ b = a = simple_strtoul(bp, (char **)&bp, BASEDEC);
+ if (*bp == '-') {
+ bp++;
+ if (!isdigit(*bp))
+ return -EINVAL;
+ b = simple_strtoul(bp, (char **)&bp, BASEDEC);
+ }
+ if (!(a <= b))
+ return -EINVAL;
+ if (b >= nmaskbits)
+ return -ERANGE;
+ while (a <= b) {
+ set_bit(a, maskp);
+ a++;
+ }
+ if (*bp == ',')
+ bp++;
+ } while (*bp != '\0' && *bp != '\n');
+ return 0;
+}
+EXPORT_SYMBOL(bitmap_parselist);
+
/**
* bitmap_find_free_region - find a contiguous aligned mem region
* @bitmap: an array of unsigned longs corresponding to the bitmap
diff --git a/lib/extable.c b/lib/extable.c
index 57dc4333e217a..3f677a8f0c3c1 100644
--- a/lib/extable.c
+++ b/lib/extable.c
@@ -13,6 +13,7 @@
#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
+#include <linux/sort.h>
#include <asm/uaccess.h>
extern struct exception_table_entry __start___ex_table[];
@@ -25,26 +26,23 @@ extern struct exception_table_entry __stop___ex_table[];
* This is used both for the kernel exception table and for
* the exception tables of modules that get loaded.
*/
+static int cmp_ex(const void *a, const void *b)
+{
+ const struct exception_table_entry *x = a, *y = b;
+
+ /* avoid overflow */
+ if (x->insn > y->insn)
+ return 1;
+ if (x->insn < y->insn)
+ return -1;
+ return 0;
+}
+
void sort_extable(struct exception_table_entry *start,
struct exception_table_entry *finish)
{
- struct exception_table_entry el, *p, *q;
-
- /* insertion sort */
- for (p = start + 1; p < finish; ++p) {
- /* start .. p-1 is sorted */
- if (p[0].insn < p[-1].insn) {
- /* move element p down to its right place */
- el = *p;
- q = p;
- do {
- /* el comes before q[-1], move q[-1] up one */
- q[0] = q[-1];
- --q;
- } while (q > start && el.insn < q[-1].insn);
- *q = el;
- }
- }
+ sort(start, finish - start, sizeof(struct exception_table_entry),
+ cmp_ex, NULL);
}
#endif
diff --git a/lib/halfmd4.c b/lib/halfmd4.c
new file mode 100644
index 0000000000000..e11db26f8ae58
--- /dev/null
+++ b/lib/halfmd4.c
@@ -0,0 +1,66 @@
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/cryptohash.h>
+
+/* F, G and H are basic MD4 functions: selection, majority, parity */
+#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
+#define G(x, y, z) (((x) & (y)) + (((x) ^ (y)) & (z)))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+
+/*
+ * The generic round function. The application is so specific that
+ * we don't bother protecting all the arguments with parens, as is generally
+ * good macro practice, in favor of extra legibility.
+ * Rotation is separate from addition to prevent recomputation
+ */
+#define ROUND(f, a, b, c, d, x, s) \
+ (a += f(b, c, d) + x, a = (a << s) | (a >> (32 - s)))
+#define K1 0
+#define K2 013240474631UL
+#define K3 015666365641UL
+
+/*
+ * Basic cut-down MD4 transform. Returns only 32 bits of result.
+ */
+__u32 half_md4_transform(__u32 buf[4], __u32 const in[8])
+{
+ __u32 a = buf[0], b = buf[1], c = buf[2], d = buf[3];
+
+ /* Round 1 */
+ ROUND(F, a, b, c, d, in[0] + K1, 3);
+ ROUND(F, d, a, b, c, in[1] + K1, 7);
+ ROUND(F, c, d, a, b, in[2] + K1, 11);
+ ROUND(F, b, c, d, a, in[3] + K1, 19);
+ ROUND(F, a, b, c, d, in[4] + K1, 3);
+ ROUND(F, d, a, b, c, in[5] + K1, 7);
+ ROUND(F, c, d, a, b, in[6] + K1, 11);
+ ROUND(F, b, c, d, a, in[7] + K1, 19);
+
+ /* Round 2 */
+ ROUND(G, a, b, c, d, in[1] + K2, 3);
+ ROUND(G, d, a, b, c, in[3] + K2, 5);
+ ROUND(G, c, d, a, b, in[5] + K2, 9);
+ ROUND(G, b, c, d, a, in[7] + K2, 13);
+ ROUND(G, a, b, c, d, in[0] + K2, 3);
+ ROUND(G, d, a, b, c, in[2] + K2, 5);
+ ROUND(G, c, d, a, b, in[4] + K2, 9);
+ ROUND(G, b, c, d, a, in[6] + K2, 13);
+
+ /* Round 3 */
+ ROUND(H, a, b, c, d, in[3] + K3, 3);
+ ROUND(H, d, a, b, c, in[7] + K3, 9);
+ ROUND(H, c, d, a, b, in[2] + K3, 11);
+ ROUND(H, b, c, d, a, in[6] + K3, 15);
+ ROUND(H, a, b, c, d, in[1] + K3, 3);
+ ROUND(H, d, a, b, c, in[5] + K3, 9);
+ ROUND(H, c, d, a, b, in[0] + K3, 11);
+ ROUND(H, b, c, d, a, in[4] + K3, 15);
+
+ buf[0] += a;
+ buf[1] += b;
+ buf[2] += c;
+ buf[3] += d;
+
+ return buf[1]; /* "most hashed" word */
+}
+EXPORT_SYMBOL(half_md4_transform);
diff --git a/lib/kernel_lock.c b/lib/kernel_lock.c
index c739bfcad6595..99b0ae3d51dde 100644
--- a/lib/kernel_lock.c
+++ b/lib/kernel_lock.c
@@ -79,7 +79,7 @@ EXPORT_SYMBOL(smp_processor_id);
*
* Don't use in new code.
*/
-DECLARE_MUTEX(kernel_sem);
+static DECLARE_MUTEX(kernel_sem);
/*
* Re-acquire the kernel semaphore.
diff --git a/lib/kobject.c b/lib/kobject.c
index 8737dfd72d360..ff9491986b381 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -140,9 +140,9 @@ void kobject_init(struct kobject * kobj)
static void unlink(struct kobject * kobj)
{
if (kobj->kset) {
- down_write(&kobj->kset->subsys->rwsem);
+ spin_lock(&kobj->kset->list_lock);
list_del_init(&kobj->entry);
- up_write(&kobj->kset->subsys->rwsem);
+ spin_unlock(&kobj->kset->list_lock);
}
kobject_put(kobj);
}
@@ -168,13 +168,13 @@ int kobject_add(struct kobject * kobj)
kobj->kset ? kobj->kset->kobj.name : "<NULL>" );
if (kobj->kset) {
- down_write(&kobj->kset->subsys->rwsem);
+ spin_lock(&kobj->kset->list_lock);
if (!parent)
parent = kobject_get(&kobj->kset->kobj);
list_add_tail(&kobj->entry,&kobj->kset->list);
- up_write(&kobj->kset->subsys->rwsem);
+ spin_unlock(&kobj->kset->list_lock);
}
kobj->parent = parent;
@@ -380,6 +380,7 @@ void kset_init(struct kset * k)
{
kobject_init(&k->kobj);
INIT_LIST_HEAD(&k->list);
+ spin_lock_init(&k->list_lock);
}
@@ -444,7 +445,7 @@ struct kobject * kset_find_obj(struct kset * kset, const char * name)
struct list_head * entry;
struct kobject * ret = NULL;
- down_read(&kset->subsys->rwsem);
+ spin_lock(&kset->list_lock);
list_for_each(entry,&kset->list) {
struct kobject * k = to_kobj(entry);
if (kobject_name(k) && !strcmp(kobject_name(k),name)) {
@@ -452,7 +453,7 @@ struct kobject * kset_find_obj(struct kset * kset, const char * name)
break;
}
}
- up_read(&kset->subsys->rwsem);
+ spin_unlock(&kset->list_lock);
return ret;
}
@@ -524,7 +525,6 @@ void subsys_remove_file(struct subsystem * s, struct subsys_attribute * a)
}
}
-EXPORT_SYMBOL(kobject_get_path);
EXPORT_SYMBOL(kobject_init);
EXPORT_SYMBOL(kobject_register);
EXPORT_SYMBOL(kobject_unregister);
@@ -532,7 +532,6 @@ EXPORT_SYMBOL(kobject_get);
EXPORT_SYMBOL(kobject_put);
EXPORT_SYMBOL(kobject_add);
EXPORT_SYMBOL(kobject_del);
-EXPORT_SYMBOL(kobject_rename);
EXPORT_SYMBOL(kset_register);
EXPORT_SYMBOL(kset_unregister);
diff --git a/lib/kref.c b/lib/kref.c
index 2218b7ae7db6f..0d07cc31c8181 100644
--- a/lib/kref.c
+++ b/lib/kref.c
@@ -42,14 +42,21 @@ void kref_get(struct kref *kref)
* in as this function.
*
* Decrement the refcount, and if 0, call release().
+ * Return 1 if the object was removed, otherwise return 0. Beware, if this
+ * function returns 0, you still can not count on the kref from remaining in
+ * memory. Only use the return value if you want to see if the kref is now
+ * gone, not present.
*/
-void kref_put(struct kref *kref, void (*release) (struct kref *kref))
+int kref_put(struct kref *kref, void (*release)(struct kref *kref))
{
WARN_ON(release == NULL);
WARN_ON(release == (void (*)(struct kref *))kfree);
- if (atomic_dec_and_test(&kref->refcount))
+ if (atomic_dec_and_test(&kref->refcount)) {
release(kref);
+ return 1;
+ }
+ return 0;
}
EXPORT_SYMBOL(kref_init);
diff --git a/lib/rwsem-spinlock.c b/lib/rwsem-spinlock.c
index 96255f47b1f85..21f0db2c97113 100644
--- a/lib/rwsem-spinlock.c
+++ b/lib/rwsem-spinlock.c
@@ -140,12 +140,12 @@ void fastcall __sched __down_read(struct rw_semaphore *sem)
rwsemtrace(sem, "Entering __down_read");
- spin_lock(&sem->wait_lock);
+ spin_lock_irq(&sem->wait_lock);
if (sem->activity >= 0 && list_empty(&sem->wait_list)) {
/* granted */
sem->activity++;
- spin_unlock(&sem->wait_lock);
+ spin_unlock_irq(&sem->wait_lock);
goto out;
}
@@ -160,7 +160,7 @@ void fastcall __sched __down_read(struct rw_semaphore *sem)
list_add_tail(&waiter.list, &sem->wait_list);
/* we don't need to touch the semaphore struct anymore */
- spin_unlock(&sem->wait_lock);
+ spin_unlock_irq(&sem->wait_lock);
/* wait to be given the lock */
for (;;) {
@@ -181,10 +181,12 @@ void fastcall __sched __down_read(struct rw_semaphore *sem)
*/
int fastcall __down_read_trylock(struct rw_semaphore *sem)
{
+ unsigned long flags;
int ret = 0;
+
rwsemtrace(sem, "Entering __down_read_trylock");
- spin_lock(&sem->wait_lock);
+ spin_lock_irqsave(&sem->wait_lock, flags);
if (sem->activity >= 0 && list_empty(&sem->wait_list)) {
/* granted */
@@ -192,7 +194,7 @@ int fastcall __down_read_trylock(struct rw_semaphore *sem)
ret = 1;
}
- spin_unlock(&sem->wait_lock);
+ spin_unlock_irqrestore(&sem->wait_lock, flags);
rwsemtrace(sem, "Leaving __down_read_trylock");
return ret;
@@ -209,12 +211,12 @@ void fastcall __sched __down_write(struct rw_semaphore *sem)
rwsemtrace(sem, "Entering __down_write");
- spin_lock(&sem->wait_lock);
+ spin_lock_irq(&sem->wait_lock);
if (sem->activity == 0 && list_empty(&sem->wait_list)) {
/* granted */
sem->activity = -1;
- spin_unlock(&sem->wait_lock);
+ spin_unlock_irq(&sem->wait_lock);
goto out;
}
@@ -229,7 +231,7 @@ void fastcall __sched __down_write(struct rw_semaphore *sem)
list_add_tail(&waiter.list, &sem->wait_list);
/* we don't need to touch the semaphore struct anymore */
- spin_unlock(&sem->wait_lock);
+ spin_unlock_irq(&sem->wait_lock);
/* wait to be given the lock */
for (;;) {
@@ -250,10 +252,12 @@ void fastcall __sched __down_write(struct rw_semaphore *sem)
*/
int fastcall __down_write_trylock(struct rw_semaphore *sem)
{
+ unsigned long flags;
int ret = 0;
+
rwsemtrace(sem, "Entering __down_write_trylock");
- spin_lock(&sem->wait_lock);
+ spin_lock_irqsave(&sem->wait_lock, flags);
if (sem->activity == 0 && list_empty(&sem->wait_list)) {
/* granted */
@@ -261,7 +265,7 @@ int fastcall __down_write_trylock(struct rw_semaphore *sem)
ret = 1;
}
- spin_unlock(&sem->wait_lock);
+ spin_unlock_irqrestore(&sem->wait_lock, flags);
rwsemtrace(sem, "Leaving __down_write_trylock");
return ret;
@@ -272,14 +276,16 @@ int fastcall __down_write_trylock(struct rw_semaphore *sem)
*/
void fastcall __up_read(struct rw_semaphore *sem)
{
+ unsigned long flags;
+
rwsemtrace(sem, "Entering __up_read");
- spin_lock(&sem->wait_lock);
+ spin_lock_irqsave(&sem->wait_lock, flags);
if (--sem->activity == 0 && !list_empty(&sem->wait_list))
sem = __rwsem_wake_one_writer(sem);
- spin_unlock(&sem->wait_lock);
+ spin_unlock_irqrestore(&sem->wait_lock, flags);
rwsemtrace(sem, "Leaving __up_read");
}
@@ -289,15 +295,17 @@ void fastcall __up_read(struct rw_semaphore *sem)
*/
void fastcall __up_write(struct rw_semaphore *sem)
{
+ unsigned long flags;
+
rwsemtrace(sem, "Entering __up_write");
- spin_lock(&sem->wait_lock);
+ spin_lock_irqsave(&sem->wait_lock, flags);
sem->activity = 0;
if (!list_empty(&sem->wait_list))
sem = __rwsem_do_wake(sem, 1);
- spin_unlock(&sem->wait_lock);
+ spin_unlock_irqrestore(&sem->wait_lock, flags);
rwsemtrace(sem, "Leaving __up_write");
}
@@ -308,15 +316,17 @@ void fastcall __up_write(struct rw_semaphore *sem)
*/
void fastcall __downgrade_write(struct rw_semaphore *sem)
{
+ unsigned long flags;
+
rwsemtrace(sem, "Entering __downgrade_write");
- spin_lock(&sem->wait_lock);
+ spin_lock_irqsave(&sem->wait_lock, flags);
sem->activity = 1;
if (!list_empty(&sem->wait_list))
sem = __rwsem_do_wake(sem, 0);
- spin_unlock(&sem->wait_lock);
+ spin_unlock_irqrestore(&sem->wait_lock, flags);
rwsemtrace(sem, "Leaving __downgrade_write");
}
diff --git a/lib/rwsem.c b/lib/rwsem.c
index 924c14e0bfdef..7644089ec8fa0 100644
--- a/lib/rwsem.c
+++ b/lib/rwsem.c
@@ -150,7 +150,7 @@ rwsem_down_failed_common(struct rw_semaphore *sem,
set_task_state(tsk, TASK_UNINTERRUPTIBLE);
/* set up my own style of waitqueue */
- spin_lock(&sem->wait_lock);
+ spin_lock_irq(&sem->wait_lock);
waiter->task = tsk;
get_task_struct(tsk);
@@ -163,7 +163,7 @@ rwsem_down_failed_common(struct rw_semaphore *sem,
if (!(count & RWSEM_ACTIVE_MASK))
sem = __rwsem_do_wake(sem, 0);
- spin_unlock(&sem->wait_lock);
+ spin_unlock_irq(&sem->wait_lock);
/* wait to be given the lock */
for (;;) {
@@ -219,15 +219,17 @@ rwsem_down_write_failed(struct rw_semaphore *sem)
*/
struct rw_semaphore fastcall *rwsem_wake(struct rw_semaphore *sem)
{
+ unsigned long flags;
+
rwsemtrace(sem, "Entering rwsem_wake");
- spin_lock(&sem->wait_lock);
+ spin_lock_irqsave(&sem->wait_lock, flags);
/* do nothing if list empty */
if (!list_empty(&sem->wait_list))
sem = __rwsem_do_wake(sem, 0);
- spin_unlock(&sem->wait_lock);
+ spin_unlock_irqrestore(&sem->wait_lock, flags);
rwsemtrace(sem, "Leaving rwsem_wake");
@@ -241,15 +243,17 @@ struct rw_semaphore fastcall *rwsem_wake(struct rw_semaphore *sem)
*/
struct rw_semaphore fastcall *rwsem_downgrade_wake(struct rw_semaphore *sem)
{
+ unsigned long flags;
+
rwsemtrace(sem, "Entering rwsem_downgrade_wake");
- spin_lock(&sem->wait_lock);
+ spin_lock_irqsave(&sem->wait_lock, flags);
/* do nothing if list empty */
if (!list_empty(&sem->wait_list))
sem = __rwsem_do_wake(sem, 1);
- spin_unlock(&sem->wait_lock);
+ spin_unlock_irqrestore(&sem->wait_lock, flags);
rwsemtrace(sem, "Leaving rwsem_downgrade_wake");
return sem;
diff --git a/lib/sha1.c b/lib/sha1.c
new file mode 100644
index 0000000000000..2f7f1148dfde3
--- /dev/null
+++ b/lib/sha1.c
@@ -0,0 +1,96 @@
+/*
+ * SHA transform algorithm, originally taken from code written by
+ * Peter Gutmann, and placed in the public domain.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/cryptohash.h>
+
+/* The SHA f()-functions. */
+
+#define f1(x,y,z) (z ^ (x & (y ^ z))) /* x ? y : z */
+#define f2(x,y,z) (x ^ y ^ z) /* XOR */
+#define f3(x,y,z) ((x & y) + (z & (x ^ y))) /* majority */
+
+/* The SHA Mysterious Constants */
+
+#define K1 0x5A827999L /* Rounds 0-19: sqrt(2) * 2^30 */
+#define K2 0x6ED9EBA1L /* Rounds 20-39: sqrt(3) * 2^30 */
+#define K3 0x8F1BBCDCL /* Rounds 40-59: sqrt(5) * 2^30 */
+#define K4 0xCA62C1D6L /* Rounds 60-79: sqrt(10) * 2^30 */
+
+/*
+ * sha_transform: single block SHA1 transform
+ *
+ * @digest: 160 bit digest to update
+ * @data: 512 bits of data to hash
+ * @W: 80 words of workspace (see note)
+ *
+ * This function generates a SHA1 digest for a single 512-bit block.
+ * Be warned, it does not handle padding and message digest, do not
+ * confuse it with the full FIPS 180-1 digest algorithm for variable
+ * length messages.
+ *
+ * Note: If the hash is security sensitive, the caller should be sure
+ * to clear the workspace. This is left to the caller to avoid
+ * unnecessary clears between chained hashing operations.
+ */
+void sha_transform(__u32 *digest, const char *in, __u32 *W)
+{
+ __u32 a, b, c, d, e, t, i;
+
+ for (i = 0; i < 16; i++)
+ W[i] = be32_to_cpu(((const __u32 *)in)[i]);
+
+ for (i = 0; i < 64; i++)
+ W[i+16] = rol32(W[i+13] ^ W[i+8] ^ W[i+2] ^ W[i], 1);
+
+ a = digest[0];
+ b = digest[1];
+ c = digest[2];
+ d = digest[3];
+ e = digest[4];
+
+ for (i = 0; i < 20; i++) {
+ t = f1(b, c, d) + K1 + rol32(a, 5) + e + W[i];
+ e = d; d = c; c = rol32(b, 30); b = a; a = t;
+ }
+
+ for (; i < 40; i ++) {
+ t = f2(b, c, d) + K2 + rol32(a, 5) + e + W[i];
+ e = d; d = c; c = rol32(b, 30); b = a; a = t;
+ }
+
+ for (; i < 60; i ++) {
+ t = f3(b, c, d) + K3 + rol32(a, 5) + e + W[i];
+ e = d; d = c; c = rol32(b, 30); b = a; a = t;
+ }
+
+ for (; i < 80; i ++) {
+ t = f2(b, c, d) + K4 + rol32(a, 5) + e + W[i];
+ e = d; d = c; c = rol32(b, 30); b = a; a = t;
+ }
+
+ digest[0] += a;
+ digest[1] += b;
+ digest[2] += c;
+ digest[3] += d;
+ digest[4] += e;
+}
+EXPORT_SYMBOL(sha_transform);
+
+/*
+ * sha_init: initialize the vectors for a SHA1 digest
+ *
+ * @buf: vector to initialize
+ */
+void sha_init(__u32 *buf)
+{
+ buf[0] = 0x67452301;
+ buf[1] = 0xefcdab89;
+ buf[2] = 0x98badcfe;
+ buf[3] = 0x10325476;
+ buf[4] = 0xc3d2e1f0;
+}
+
diff --git a/lib/sort.c b/lib/sort.c
new file mode 100644
index 0000000000000..ea3caedeabdb6
--- /dev/null
+++ b/lib/sort.c
@@ -0,0 +1,119 @@
+/*
+ * A fast, small, non-recursive O(nlog n) sort for the Linux kernel
+ *
+ * Jan 23 2005 Matt Mackall <mpm@selenic.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+void u32_swap(void *a, void *b, int size)
+{
+ u32 t = *(u32 *)a;
+ *(u32 *)a = *(u32 *)b;
+ *(u32 *)b = t;
+}
+
+void generic_swap(void *a, void *b, int size)
+{
+ char t;
+
+ do {
+ t = *(char *)a;
+ *(char *)a++ = *(char *)b;
+ *(char *)b++ = t;
+ } while (--size > 0);
+}
+
+/*
+ * sort - sort an array of elements
+ * @base: pointer to data to sort
+ * @num: number of elements
+ * @size: size of each element
+ * @cmp: pointer to comparison function
+ * @swap: pointer to swap function or NULL
+ *
+ * This function does a heapsort on the given array. You may provide a
+ * swap function optimized to your element type.
+ *
+ * Sorting time is O(n log n) both on average and worst-case. While
+ * qsort is about 20% faster on average, it suffers from exploitable
+ * O(n*n) worst-case behavior and extra memory requirements that make
+ * it less suitable for kernel use.
+ */
+
+void sort(void *base, size_t num, size_t size,
+ int (*cmp)(const void *, const void *),
+ void (*swap)(void *, void *, int size))
+{
+ /* pre-scale counters for performance */
+ int i = (num/2) * size, n = num * size, c, r;
+
+ if (!swap)
+ swap = (size == 4 ? u32_swap : generic_swap);
+
+ /* heapify */
+ for ( ; i >= 0; i -= size) {
+ for (r = i; r * 2 < n; r = c) {
+ c = r * 2;
+ if (c < n - size && cmp(base + c, base + c + size) < 0)
+ c += size;
+ if (cmp(base + r, base + c) >= 0)
+ break;
+ swap(base + r, base + c, size);
+ }
+ }
+
+ /* sort */
+ for (i = n - size; i >= 0; i -= size) {
+ swap(base, base + i, size);
+ for (r = 0; r * 2 < i; r = c) {
+ c = r * 2;
+ if (c < i - size && cmp(base + c, base + c + size) < 0)
+ c += size;
+ if (cmp(base + r, base + c) >= 0)
+ break;
+ swap(base + r, base + c, size);
+ }
+ }
+}
+
+EXPORT_SYMBOL(sort);
+
+#if 0
+/* a simple boot-time regression test */
+
+int cmpint(const void *a, const void *b)
+{
+ return *(int *)a - *(int *)b;
+}
+
+static int sort_test(void)
+{
+ int *a, i, r = 0;
+
+ a = kmalloc(1000 * sizeof(int), GFP_KERNEL);
+ BUG_ON(!a);
+
+ printk("testing sort()\n");
+
+ for (i = 0; i < 1000; i++) {
+ r = (r * 725861) % 6599;
+ a[i] = r;
+ }
+
+ sort(a, 1000, sizeof(int), cmpint, NULL);
+
+ for (i = 0; i < 999; i++)
+ if (a[i] > a[i+1]) {
+ printk("sort() failed!\n");
+ break;
+ }
+
+ kfree(a);
+
+ return 0;
+}
+
+module_init(sort_test);
+#endif
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 0b0935915066a..a9bda0a361f39 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -580,7 +580,7 @@ EXPORT_SYMBOL(scnprintf);
*/
int vsprintf(char *buf, const char *fmt, va_list args)
{
- return vsnprintf(buf, (~0U)>>1, fmt, args);
+ return vsnprintf(buf, INT_MAX, fmt, args);
}
EXPORT_SYMBOL(vsprintf);
@@ -601,7 +601,7 @@ int sprintf(char * buf, const char *fmt, ...)
int i;
va_start(args, fmt);
- i=vsprintf(buf,fmt,args);
+ i=vsnprintf(buf, INT_MAX, fmt, args);
va_end(args);
return i;
}
diff --git a/mm/filemap.c b/mm/filemap.c
index 4f2fb2c40f788..439b2bea8e342 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -126,9 +126,9 @@ void remove_from_page_cache(struct page *page)
if (unlikely(!PageLocked(page)))
PAGE_BUG(page);
- spin_lock_irq(&mapping->tree_lock);
+ write_lock_irq(&mapping->tree_lock);
__remove_from_page_cache(page);
- spin_unlock_irq(&mapping->tree_lock);
+ write_unlock_irq(&mapping->tree_lock);
}
static int sync_page(void *word)
@@ -172,7 +172,7 @@ static int __filemap_fdatawrite_range(struct address_space *mapping,
.end = end,
};
- if (mapping->backing_dev_info->memory_backed)
+ if (!mapping_cap_writeback_dirty(mapping))
return 0;
ret = do_writepages(mapping, &wbc);
@@ -269,7 +269,7 @@ int sync_page_range(struct inode *inode, struct address_space *mapping,
pgoff_t end = (pos + count - 1) >> PAGE_CACHE_SHIFT;
int ret;
- if (mapping->backing_dev_info->memory_backed || !count)
+ if (!mapping_cap_writeback_dirty(mapping) || !count)
return 0;
ret = filemap_fdatawrite_range(mapping, pos, pos + count - 1);
if (ret == 0) {
@@ -295,7 +295,7 @@ int sync_page_range_nolock(struct inode *inode, struct address_space *mapping,
pgoff_t end = (pos + count - 1) >> PAGE_CACHE_SHIFT;
int ret;
- if (mapping->backing_dev_info->memory_backed || !count)
+ if (!mapping_cap_writeback_dirty(mapping) || !count)
return 0;
ret = filemap_fdatawrite_range(mapping, pos, pos + count - 1);
if (ret == 0)
@@ -336,6 +336,22 @@ int filemap_write_and_wait(struct address_space *mapping)
return retval;
}
+int filemap_write_and_wait_range(struct address_space *mapping,
+ loff_t lstart, loff_t lend)
+{
+ int retval = 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);
+ }
+ return retval;
+}
+
/*
* This function is used to add newly allocated pagecache pages:
* the page is new, so we can just run SetPageLocked() against it.
@@ -349,7 +365,7 @@ int add_to_page_cache(struct page *page, struct address_space *mapping,
int error = radix_tree_preload(gfp_mask & ~__GFP_HIGHMEM);
if (error == 0) {
- spin_lock_irq(&mapping->tree_lock);
+ write_lock_irq(&mapping->tree_lock);
error = radix_tree_insert(&mapping->page_tree, offset, page);
if (!error) {
page_cache_get(page);
@@ -359,7 +375,7 @@ int add_to_page_cache(struct page *page, struct address_space *mapping,
mapping->nrpages++;
pagecache_acct(1);
}
- spin_unlock_irq(&mapping->tree_lock);
+ write_unlock_irq(&mapping->tree_lock);
radix_tree_preload_end();
}
return error;
@@ -472,11 +488,11 @@ struct page * find_get_page(struct address_space *mapping, unsigned long offset)
{
struct page *page;
- spin_lock_irq(&mapping->tree_lock);
+ read_lock_irq(&mapping->tree_lock);
page = radix_tree_lookup(&mapping->page_tree, offset);
if (page)
page_cache_get(page);
- spin_unlock_irq(&mapping->tree_lock);
+ read_unlock_irq(&mapping->tree_lock);
return page;
}
@@ -489,11 +505,11 @@ struct page *find_trylock_page(struct address_space *mapping, unsigned long offs
{
struct page *page;
- spin_lock_irq(&mapping->tree_lock);
+ read_lock_irq(&mapping->tree_lock);
page = radix_tree_lookup(&mapping->page_tree, offset);
if (page && TestSetPageLocked(page))
page = NULL;
- spin_unlock_irq(&mapping->tree_lock);
+ read_unlock_irq(&mapping->tree_lock);
return page;
}
@@ -515,15 +531,15 @@ struct page *find_lock_page(struct address_space *mapping,
{
struct page *page;
- spin_lock_irq(&mapping->tree_lock);
+ read_lock_irq(&mapping->tree_lock);
repeat:
page = radix_tree_lookup(&mapping->page_tree, offset);
if (page) {
page_cache_get(page);
if (TestSetPageLocked(page)) {
- spin_unlock_irq(&mapping->tree_lock);
+ read_unlock_irq(&mapping->tree_lock);
lock_page(page);
- spin_lock_irq(&mapping->tree_lock);
+ read_lock_irq(&mapping->tree_lock);
/* Has the page been truncated while we slept? */
if (page->mapping != mapping || page->index != offset) {
@@ -533,7 +549,7 @@ repeat:
}
}
}
- spin_unlock_irq(&mapping->tree_lock);
+ read_unlock_irq(&mapping->tree_lock);
return page;
}
@@ -607,12 +623,12 @@ unsigned find_get_pages(struct address_space *mapping, pgoff_t start,
unsigned int i;
unsigned int ret;
- spin_lock_irq(&mapping->tree_lock);
+ read_lock_irq(&mapping->tree_lock);
ret = radix_tree_gang_lookup(&mapping->page_tree,
(void **)pages, start, nr_pages);
for (i = 0; i < ret; i++)
page_cache_get(pages[i]);
- spin_unlock_irq(&mapping->tree_lock);
+ read_unlock_irq(&mapping->tree_lock);
return ret;
}
@@ -626,14 +642,14 @@ unsigned find_get_pages_tag(struct address_space *mapping, pgoff_t *index,
unsigned int i;
unsigned int ret;
- spin_lock_irq(&mapping->tree_lock);
+ read_lock_irq(&mapping->tree_lock);
ret = radix_tree_gang_lookup_tag(&mapping->page_tree,
(void **)pages, *index, nr_pages, tag);
for (i = 0; i < ret; i++)
page_cache_get(pages[i]);
if (ret)
*index = pages[ret - 1]->index + 1;
- spin_unlock_irq(&mapping->tree_lock);
+ read_unlock_irq(&mapping->tree_lock);
return ret;
}
@@ -650,7 +666,7 @@ struct page *
grab_cache_page_nowait(struct address_space *mapping, unsigned long index)
{
struct page *page = find_get_page(mapping, index);
- int gfp_mask;
+ unsigned int gfp_mask;
if (page) {
if (!TestSetPageLocked(page))
@@ -691,7 +707,7 @@ void do_generic_mapping_read(struct address_space *mapping,
unsigned long index;
unsigned long end_index;
unsigned long offset;
- unsigned long req_size;
+ unsigned long last_index;
unsigned long next_index;
unsigned long prev_index;
loff_t isize;
@@ -703,7 +719,7 @@ void do_generic_mapping_read(struct address_space *mapping,
index = *ppos >> PAGE_CACHE_SHIFT;
next_index = index;
prev_index = ra.prev_page;
- req_size = (desc->count + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
+ last_index = (*ppos + desc->count + PAGE_CACHE_SIZE-1) >> PAGE_CACHE_SHIFT;
offset = *ppos & ~PAGE_CACHE_MASK;
isize = i_size_read(inode);
@@ -713,7 +729,7 @@ void do_generic_mapping_read(struct address_space *mapping,
end_index = (isize - 1) >> PAGE_CACHE_SHIFT;
for (;;) {
struct page *page;
- unsigned long ret_size, nr, ret;
+ unsigned long nr, ret;
/* nr is the maximum number of bytes to copy from this page */
nr = PAGE_CACHE_SIZE;
@@ -728,12 +744,9 @@ void do_generic_mapping_read(struct address_space *mapping,
nr = nr - offset;
cond_resched();
- if (index == next_index && req_size) {
- ret_size = page_cache_readahead(mapping, &ra,
- filp, index, req_size);
- next_index += ret_size;
- req_size -= ret_size;
- }
+ if (index == next_index)
+ next_index = page_cache_readahead(mapping, &ra, filp,
+ index, last_index - index);
find_page:
page = find_get_page(mapping, index);
@@ -1154,7 +1167,8 @@ static int fastcall page_cache_read(struct file * file, unsigned long offset)
* it in the page cache, and handles the special cases reasonably without
* having a lot of duplicated code.
*/
-struct page * filemap_nopage(struct vm_area_struct * area, unsigned long address, int *type)
+struct page *filemap_nopage(struct vm_area_struct *area,
+ unsigned long address, int *type)
{
int error;
struct file *file = area->vm_file;
@@ -1162,11 +1176,10 @@ struct page * filemap_nopage(struct vm_area_struct * area, unsigned long address
struct file_ra_state *ra = &file->f_ra;
struct inode *inode = mapping->host;
struct page *page;
- unsigned long size, pgoff, endoff;
+ unsigned long size, pgoff;
int did_readaround = 0, majmin = VM_FAULT_MINOR;
- pgoff = ((address - area->vm_start) >> PAGE_CACHE_SHIFT) + area->vm_pgoff;
- endoff = ((area->vm_end - area->vm_start) >> PAGE_CACHE_SHIFT) + area->vm_pgoff;
+ pgoff = ((address-area->vm_start) >> PAGE_CACHE_SHIFT) + area->vm_pgoff;
retry_all:
size = (i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
@@ -1178,13 +1191,6 @@ retry_all:
goto no_cached_page;
/*
- * The "size" of the file, as far as mmap is concerned, isn't bigger
- * than the mapping
- */
- if (size > endoff)
- size = endoff;
-
- /*
* The readahead code wants to be told about each and every page
* so it can build and shrink its windows appropriately
*
@@ -2269,21 +2275,28 @@ generic_file_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
struct file *file = iocb->ki_filp;
struct address_space *mapping = file->f_mapping;
ssize_t retval;
+ size_t write_len = 0;
/*
* If it's a write, unmap all mmappings of the file up-front. This
* will cause any pte dirty bits to be propagated into the pageframes
* for the subsequent filemap_write_and_wait().
*/
- if (rw == WRITE && mapping_mapped(mapping))
- unmap_mapping_range(mapping, 0, -1, 0);
+ if (rw == WRITE) {
+ write_len = iov_length(iov, nr_segs);
+ if (mapping_mapped(mapping))
+ unmap_mapping_range(mapping, offset, write_len, 0);
+ }
retval = filemap_write_and_wait(mapping);
if (retval == 0) {
retval = mapping->a_ops->direct_IO(rw, iocb, iov,
offset, nr_segs);
if (rw == WRITE && mapping->nrpages) {
- int err = invalidate_inode_pages2(mapping);
+ pgoff_t end = (offset + write_len - 1)
+ >> PAGE_CACHE_SHIFT;
+ int err = invalidate_inode_pages2_range(mapping,
+ offset >> PAGE_CACHE_SHIFT, end);
if (err)
retval = err;
}
diff --git a/mm/fremap.c b/mm/fremap.c
index bab48f238623a..3235fb77c1331 100644
--- a/mm/fremap.c
+++ b/mm/fremap.c
@@ -30,7 +30,7 @@ static inline void zap_pte(struct mm_struct *mm, struct vm_area_struct *vma,
if (pte_present(pte)) {
unsigned long pfn = pte_pfn(pte);
- flush_cache_page(vma, addr);
+ flush_cache_page(vma, addr, pfn);
pte = ptep_clear_flush(vma, addr, ptep);
if (pfn_valid(pfn)) {
struct page *page = pfn_to_page(pfn);
@@ -39,13 +39,13 @@ static inline void zap_pte(struct mm_struct *mm, struct vm_area_struct *vma,
set_page_dirty(page);
page_remove_rmap(page);
page_cache_release(page);
- mm->rss--;
+ dec_mm_counter(mm, rss);
}
}
} else {
if (!pte_file(pte))
free_swap_and_cache(pte_to_swp_entry(pte));
- pte_clear(ptep);
+ pte_clear(mm, addr, ptep);
}
}
@@ -92,9 +92,9 @@ int install_page(struct mm_struct *mm, struct vm_area_struct *vma,
zap_pte(mm, vma, addr, pte);
- mm->rss++;
+ inc_mm_counter(mm,rss);
flush_icache_page(vma, page);
- set_pte(pte, mk_pte(page, prot));
+ set_pte_at(mm, addr, pte, mk_pte(page, prot));
page_add_file_rmap(page);
pte_val = *pte;
pte_unmap(pte);
@@ -139,7 +139,7 @@ int install_file_pte(struct mm_struct *mm, struct vm_area_struct *vma,
zap_pte(mm, vma, addr, pte);
- set_pte(pte, pgoff_to_pte(pgoff));
+ set_pte_at(mm, addr, pte, pgoff_to_pte(pgoff));
pte_val = *pte;
pte_unmap(pte);
update_mmu_cache(vma, addr, pte_val);
diff --git a/mm/highmem.c b/mm/highmem.c
index c37d66cb1af12..d01276506b004 100644
--- a/mm/highmem.c
+++ b/mm/highmem.c
@@ -30,9 +30,9 @@
static mempool_t *page_pool, *isa_page_pool;
-static void *page_pool_alloc(int gfp_mask, void *data)
+static void *page_pool_alloc(unsigned int __nocast gfp_mask, void *data)
{
- int gfp = gfp_mask | (int) (long) data;
+ unsigned int gfp = gfp_mask | (unsigned int) (long) data;
return alloc_page(gfp);
}
@@ -90,7 +90,8 @@ static void flush_all_zero_pkmaps(void)
* So no dangers, even with speculative execution.
*/
page = pte_page(pkmap_page_table[i]);
- pte_clear(&pkmap_page_table[i]);
+ pte_clear(&init_mm, (unsigned long)page_address(page),
+ &pkmap_page_table[i]);
set_page_address(page, NULL);
}
@@ -138,7 +139,8 @@ start:
}
}
vaddr = PKMAP_ADDR(last_pkmap_nr);
- set_pte(&(pkmap_page_table[last_pkmap_nr]), mk_pte(page, kmap_prot));
+ set_pte_at(&init_mm, vaddr,
+ &(pkmap_page_table[last_pkmap_nr]), mk_pte(page, kmap_prot));
pkmap_count[last_pkmap_nr] = 1;
set_page_address(page, (void *)vaddr);
@@ -425,7 +427,7 @@ static void __blk_queue_bounce(request_queue_t *q, struct bio **bio_orig,
* at least one page was bounced, fill in possible non-highmem
* pages
*/
- bio_for_each_segment(from, *bio_orig, i) {
+ __bio_for_each_segment(from, *bio_orig, i, 0) {
to = bio_iovec_idx(bio, i);
if (!to->bv_page) {
to->bv_page = from->bv_page;
diff --git a/mm/memory.c b/mm/memory.c
index 48cbd6b7b98b6..fb6e5deb873a8 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -46,7 +46,6 @@
#include <linux/highmem.h>
#include <linux/pagemap.h>
#include <linux/rmap.h>
-#include <linux/acct.h>
#include <linux/module.h>
#include <linux/init.h>
@@ -84,23 +83,39 @@ EXPORT_SYMBOL(high_memory);
EXPORT_SYMBOL(vmalloc_earlyreserve);
/*
+ * If a p?d_bad entry is found while walking page tables, report
+ * the error, before resetting entry to p?d_none. Usually (but
+ * very seldom) called out from the p?d_none_or_clear_bad macros.
+ */
+
+void pgd_clear_bad(pgd_t *pgd)
+{
+ pgd_ERROR(*pgd);
+ pgd_clear(pgd);
+}
+
+void pud_clear_bad(pud_t *pud)
+{
+ pud_ERROR(*pud);
+ pud_clear(pud);
+}
+
+void pmd_clear_bad(pmd_t *pmd)
+{
+ pmd_ERROR(*pmd);
+ pmd_clear(pmd);
+}
+
+/*
* Note: this doesn't free the actual pages themselves. That
* has been handled earlier when unmapping all the memory regions.
*/
-static inline void clear_pmd_range(struct mmu_gather *tlb, pmd_t *pmd, unsigned long start, unsigned long end)
+static inline void clear_pte_range(struct mmu_gather *tlb, pmd_t *pmd,
+ unsigned long addr, unsigned long end)
{
- struct page *page;
-
- if (pmd_none(*pmd))
- return;
- if (unlikely(pmd_bad(*pmd))) {
- pmd_ERROR(*pmd);
- pmd_clear(pmd);
- return;
- }
- if (!((start | end) & ~PMD_MASK)) {
- /* Only clear full, aligned ranges */
- page = pmd_page(*pmd);
+ if (!((addr | end) & ~PMD_MASK)) {
+ /* Only free fully aligned ranges */
+ struct page *page = pmd_page(*pmd);
pmd_clear(pmd);
dec_page_state(nr_page_table_pages);
tlb->mm->nr_ptes--;
@@ -108,89 +123,74 @@ static inline void clear_pmd_range(struct mmu_gather *tlb, pmd_t *pmd, unsigned
}
}
-static inline void clear_pud_range(struct mmu_gather *tlb, pud_t *pud, unsigned long start, unsigned long end)
+static inline void clear_pmd_range(struct mmu_gather *tlb, pud_t *pud,
+ unsigned long addr, unsigned long end)
{
- unsigned long addr = start, next;
- pmd_t *pmd, *__pmd;
+ pmd_t *pmd;
+ unsigned long next;
+ pmd_t *empty_pmd = NULL;
- if (pud_none(*pud))
- return;
- if (unlikely(pud_bad(*pud))) {
- pud_ERROR(*pud);
- pud_clear(pud);
- return;
- }
+ pmd = pmd_offset(pud, addr);
- pmd = __pmd = pmd_offset(pud, start);
+ /* Only free fully aligned ranges */
+ if (!((addr | end) & ~PUD_MASK))
+ empty_pmd = pmd;
do {
- next = (addr + PMD_SIZE) & PMD_MASK;
- if (next > end || next <= addr)
- next = end;
-
- clear_pmd_range(tlb, pmd, addr, next);
- pmd++;
- addr = next;
- } while (addr && (addr < end));
+ next = pmd_addr_end(addr, end);
+ if (pmd_none_or_clear_bad(pmd))
+ continue;
+ clear_pte_range(tlb, pmd, addr, next);
+ } while (pmd++, addr = next, addr != end);
- if (!((start | end) & ~PUD_MASK)) {
- /* Only clear full, aligned ranges */
+ if (empty_pmd) {
pud_clear(pud);
- pmd_free_tlb(tlb, __pmd);
+ pmd_free_tlb(tlb, empty_pmd);
}
}
-
-static inline void clear_pgd_range(struct mmu_gather *tlb, pgd_t *pgd, unsigned long start, unsigned long end)
+static inline void clear_pud_range(struct mmu_gather *tlb, pgd_t *pgd,
+ unsigned long addr, unsigned long end)
{
- unsigned long addr = start, next;
- pud_t *pud, *__pud;
+ pud_t *pud;
+ unsigned long next;
+ pud_t *empty_pud = NULL;
- if (pgd_none(*pgd))
- return;
- if (unlikely(pgd_bad(*pgd))) {
- pgd_ERROR(*pgd);
- pgd_clear(pgd);
- return;
- }
+ pud = pud_offset(pgd, addr);
- pud = __pud = pud_offset(pgd, start);
+ /* Only free fully aligned ranges */
+ if (!((addr | end) & ~PGDIR_MASK))
+ empty_pud = pud;
do {
- next = (addr + PUD_SIZE) & PUD_MASK;
- if (next > end || next <= addr)
- next = end;
-
- clear_pud_range(tlb, pud, addr, next);
- pud++;
- addr = next;
- } while (addr && (addr < end));
+ next = pud_addr_end(addr, end);
+ if (pud_none_or_clear_bad(pud))
+ continue;
+ clear_pmd_range(tlb, pud, addr, next);
+ } while (pud++, addr = next, addr != end);
- if (!((start | end) & ~PGDIR_MASK)) {
- /* Only clear full, aligned ranges */
+ if (empty_pud) {
pgd_clear(pgd);
- pud_free_tlb(tlb, __pud);
+ pud_free_tlb(tlb, empty_pud);
}
}
/*
* This function clears user-level page tables of a process.
- *
+ * Unlike other pagetable walks, some memory layouts might give end 0.
* Must be called with pagetable lock held.
*/
-void clear_page_range(struct mmu_gather *tlb, unsigned long start, unsigned long end)
+void clear_page_range(struct mmu_gather *tlb,
+ unsigned long addr, unsigned long end)
{
- unsigned long addr = start, next;
- pgd_t * pgd = pgd_offset(tlb->mm, start);
- unsigned long i;
-
- for (i = pgd_index(start); i <= pgd_index(end-1); i++) {
- next = (addr + PGDIR_SIZE) & PGDIR_MASK;
- if (next > end || next <= addr)
- next = end;
-
- clear_pgd_range(tlb, pgd, addr, next);
- pgd++;
- addr = next;
- }
+ pgd_t *pgd;
+ unsigned long next;
+
+ pgd = pgd_offset(tlb->mm, addr);
+ do {
+ next = pgd_addr_end(addr, end);
+ if (pgd_none_or_clear_bad(pgd))
+ continue;
+ clear_pud_range(tlb, pgd, addr, next);
+ } while (pgd++, addr = next, addr != end);
}
pte_t fastcall * pte_alloc_map(struct mm_struct *mm, pmd_t *pmd, unsigned long address)
@@ -254,20 +254,7 @@ out:
*/
static inline void
-copy_swap_pte(struct mm_struct *dst_mm, struct mm_struct *src_mm, pte_t pte)
-{
- if (pte_file(pte))
- return;
- swap_duplicate(pte_to_swp_entry(pte));
- if (list_empty(&dst_mm->mmlist)) {
- spin_lock(&mmlist_lock);
- list_add(&dst_mm->mmlist, &src_mm->mmlist);
- spin_unlock(&mmlist_lock);
- }
-}
-
-static inline void
-copy_one_pte(struct mm_struct *dst_mm, struct mm_struct *src_mm,
+copy_one_pte(struct mm_struct *dst_mm, struct mm_struct *src_mm,
pte_t *dst_pte, pte_t *src_pte, unsigned long vm_flags,
unsigned long addr)
{
@@ -275,12 +262,21 @@ copy_one_pte(struct mm_struct *dst_mm, struct mm_struct *src_mm,
struct page *page;
unsigned long pfn;
- /* pte contains position in swap, so copy. */
- if (!pte_present(pte)) {
- copy_swap_pte(dst_mm, src_mm, pte);
- set_pte(dst_pte, pte);
+ /* pte contains position in swap or file, so copy. */
+ if (unlikely(!pte_present(pte))) {
+ if (!pte_file(pte)) {
+ swap_duplicate(pte_to_swp_entry(pte));
+ /* make sure dst_mm is on swapoff's mmlist. */
+ if (unlikely(list_empty(&dst_mm->mmlist))) {
+ spin_lock(&mmlist_lock);
+ list_add(&dst_mm->mmlist, &src_mm->mmlist);
+ spin_unlock(&mmlist_lock);
+ }
+ }
+ set_pte_at(dst_mm, addr, dst_pte, pte);
return;
}
+
pfn = pte_pfn(pte);
/* the pte points outside of valid memory, the
* mapping is assumed to be good, meaningful
@@ -292,7 +288,7 @@ copy_one_pte(struct mm_struct *dst_mm, struct mm_struct *src_mm,
page = pfn_to_page(pfn);
if (!page || PageReserved(page)) {
- set_pte(dst_pte, pte);
+ set_pte_at(dst_mm, addr, dst_pte, pte);
return;
}
@@ -301,7 +297,7 @@ copy_one_pte(struct mm_struct *dst_mm, struct mm_struct *src_mm,
* in the parent and the child
*/
if ((vm_flags & (VM_SHARED | VM_MAYWRITE)) == VM_MAYWRITE) {
- ptep_set_wrprotect(src_pte);
+ ptep_set_wrprotect(src_mm, addr, src_pte);
pte = *src_pte;
}
@@ -313,172 +309,137 @@ copy_one_pte(struct mm_struct *dst_mm, struct mm_struct *src_mm,
pte = pte_mkclean(pte);
pte = pte_mkold(pte);
get_page(page);
- dst_mm->rss++;
+ inc_mm_counter(dst_mm, rss);
if (PageAnon(page))
- dst_mm->anon_rss++;
- set_pte(dst_pte, pte);
+ inc_mm_counter(dst_mm, anon_rss);
+ set_pte_at(dst_mm, addr, dst_pte, pte);
page_dup_rmap(page);
}
-static int copy_pte_range(struct mm_struct *dst_mm, struct mm_struct *src_mm,
+static int copy_pte_range(struct mm_struct *dst_mm, struct mm_struct *src_mm,
pmd_t *dst_pmd, pmd_t *src_pmd, struct vm_area_struct *vma,
unsigned long addr, unsigned long end)
{
pte_t *src_pte, *dst_pte;
- pte_t *s, *d;
unsigned long vm_flags = vma->vm_flags;
+ int progress;
- d = dst_pte = pte_alloc_map(dst_mm, dst_pmd, addr);
+again:
+ dst_pte = pte_alloc_map(dst_mm, dst_pmd, addr);
if (!dst_pte)
return -ENOMEM;
+ src_pte = pte_offset_map_nested(src_pmd, addr);
+ progress = 0;
spin_lock(&src_mm->page_table_lock);
- s = src_pte = pte_offset_map_nested(src_pmd, addr);
- for (; addr < end; addr += PAGE_SIZE, s++, d++) {
- if (pte_none(*s))
+ do {
+ /*
+ * We are holding two locks at this point - either of them
+ * could generate latencies in another task on another CPU.
+ */
+ if (progress >= 32 && (need_resched() ||
+ need_lockbreak(&src_mm->page_table_lock) ||
+ need_lockbreak(&dst_mm->page_table_lock)))
+ break;
+ if (pte_none(*src_pte)) {
+ progress++;
continue;
- copy_one_pte(dst_mm, src_mm, d, s, vm_flags, addr);
- }
- pte_unmap_nested(src_pte);
- pte_unmap(dst_pte);
+ }
+ copy_one_pte(dst_mm, src_mm, dst_pte, src_pte, vm_flags, addr);
+ progress += 8;
+ } while (dst_pte++, src_pte++, addr += PAGE_SIZE, addr != end);
spin_unlock(&src_mm->page_table_lock);
+
+ pte_unmap_nested(src_pte - 1);
+ pte_unmap(dst_pte - 1);
cond_resched_lock(&dst_mm->page_table_lock);
+ if (addr != end)
+ goto again;
return 0;
}
-static int copy_pmd_range(struct mm_struct *dst_mm, struct mm_struct *src_mm,
+static inline int copy_pmd_range(struct mm_struct *dst_mm, struct mm_struct *src_mm,
pud_t *dst_pud, pud_t *src_pud, struct vm_area_struct *vma,
unsigned long addr, unsigned long end)
{
pmd_t *src_pmd, *dst_pmd;
- int err = 0;
unsigned long next;
- src_pmd = pmd_offset(src_pud, addr);
dst_pmd = pmd_alloc(dst_mm, dst_pud, addr);
if (!dst_pmd)
return -ENOMEM;
-
- for (; addr < end; addr = next, src_pmd++, dst_pmd++) {
- next = (addr + PMD_SIZE) & PMD_MASK;
- if (next > end || next <= addr)
- next = end;
- if (pmd_none(*src_pmd))
- continue;
- if (pmd_bad(*src_pmd)) {
- pmd_ERROR(*src_pmd);
- pmd_clear(src_pmd);
+ src_pmd = pmd_offset(src_pud, addr);
+ do {
+ next = pmd_addr_end(addr, end);
+ if (pmd_none_or_clear_bad(src_pmd))
continue;
- }
- err = copy_pte_range(dst_mm, src_mm, dst_pmd, src_pmd,
- vma, addr, next);
- if (err)
- break;
- }
- return err;
+ if (copy_pte_range(dst_mm, src_mm, dst_pmd, src_pmd,
+ vma, addr, next))
+ return -ENOMEM;
+ } while (dst_pmd++, src_pmd++, addr = next, addr != end);
+ return 0;
}
-static int copy_pud_range(struct mm_struct *dst_mm, struct mm_struct *src_mm,
+static inline int copy_pud_range(struct mm_struct *dst_mm, struct mm_struct *src_mm,
pgd_t *dst_pgd, pgd_t *src_pgd, struct vm_area_struct *vma,
unsigned long addr, unsigned long end)
{
pud_t *src_pud, *dst_pud;
- int err = 0;
unsigned long next;
- src_pud = pud_offset(src_pgd, addr);
dst_pud = pud_alloc(dst_mm, dst_pgd, addr);
if (!dst_pud)
return -ENOMEM;
-
- for (; addr < end; addr = next, src_pud++, dst_pud++) {
- next = (addr + PUD_SIZE) & PUD_MASK;
- if (next > end || next <= addr)
- next = end;
- if (pud_none(*src_pud))
- continue;
- if (pud_bad(*src_pud)) {
- pud_ERROR(*src_pud);
- pud_clear(src_pud);
+ src_pud = pud_offset(src_pgd, addr);
+ do {
+ next = pud_addr_end(addr, end);
+ if (pud_none_or_clear_bad(src_pud))
continue;
- }
- err = copy_pmd_range(dst_mm, src_mm, dst_pud, src_pud,
- vma, addr, next);
- if (err)
- break;
- }
- return err;
+ if (copy_pmd_range(dst_mm, src_mm, dst_pud, src_pud,
+ vma, addr, next))
+ return -ENOMEM;
+ } while (dst_pud++, src_pud++, addr = next, addr != end);
+ return 0;
}
-int copy_page_range(struct mm_struct *dst, struct mm_struct *src,
+int copy_page_range(struct mm_struct *dst_mm, struct mm_struct *src_mm,
struct vm_area_struct *vma)
{
pgd_t *src_pgd, *dst_pgd;
- unsigned long addr, start, end, next;
- int err = 0;
+ unsigned long next;
+ unsigned long addr = vma->vm_start;
+ unsigned long end = vma->vm_end;
if (is_vm_hugetlb_page(vma))
- return copy_hugetlb_page_range(dst, src, vma);
-
- start = vma->vm_start;
- src_pgd = pgd_offset(src, start);
- dst_pgd = pgd_offset(dst, start);
-
- end = vma->vm_end;
- addr = start;
- while (addr && (addr < end-1)) {
- next = (addr + PGDIR_SIZE) & PGDIR_MASK;
- if (next > end || next <= addr)
- next = end;
- if (pgd_none(*src_pgd))
- goto next_pgd;
- if (pgd_bad(*src_pgd)) {
- pgd_ERROR(*src_pgd);
- pgd_clear(src_pgd);
- goto next_pgd;
- }
- err = copy_pud_range(dst, src, dst_pgd, src_pgd,
- vma, addr, next);
- if (err)
- break;
+ return copy_hugetlb_page_range(dst_mm, src_mm, vma);
-next_pgd:
- src_pgd++;
- dst_pgd++;
- addr = next;
- }
-
- return err;
+ dst_pgd = pgd_offset(dst_mm, addr);
+ src_pgd = pgd_offset(src_mm, addr);
+ do {
+ next = pgd_addr_end(addr, end);
+ if (pgd_none_or_clear_bad(src_pgd))
+ continue;
+ if (copy_pud_range(dst_mm, src_mm, dst_pgd, src_pgd,
+ vma, addr, next))
+ return -ENOMEM;
+ } while (dst_pgd++, src_pgd++, addr = next, addr != end);
+ return 0;
}
-static void zap_pte_range(struct mmu_gather *tlb,
- pmd_t *pmd, unsigned long address,
- unsigned long size, struct zap_details *details)
+static void zap_pte_range(struct mmu_gather *tlb, pmd_t *pmd,
+ unsigned long addr, unsigned long end,
+ struct zap_details *details)
{
- unsigned long offset;
- pte_t *ptep;
+ pte_t *pte;
- if (pmd_none(*pmd))
- return;
- if (unlikely(pmd_bad(*pmd))) {
- pmd_ERROR(*pmd);
- pmd_clear(pmd);
- return;
- }
- ptep = pte_offset_map(pmd, address);
- offset = address & ~PMD_MASK;
- if (offset + size > PMD_SIZE)
- size = PMD_SIZE - offset;
- size &= PAGE_MASK;
- if (details && !details->check_mapping && !details->nonlinear_vma)
- details = NULL;
- for (offset=0; offset < size; ptep++, offset += PAGE_SIZE) {
- pte_t pte = *ptep;
- if (pte_none(pte))
+ pte = pte_offset_map(pmd, addr);
+ do {
+ pte_t ptent = *pte;
+ if (pte_none(ptent))
continue;
- if (pte_present(pte)) {
+ if (pte_present(ptent)) {
struct page *page = NULL;
- unsigned long pfn = pte_pfn(pte);
+ unsigned long pfn = pte_pfn(ptent);
if (pfn_valid(pfn)) {
page = pfn_to_page(pfn);
if (PageReserved(page))
@@ -502,19 +463,20 @@ static void zap_pte_range(struct mmu_gather *tlb,
page->index > details->last_index))
continue;
}
- pte = ptep_get_and_clear(ptep);
- tlb_remove_tlb_entry(tlb, ptep, address+offset);
+ ptent = ptep_get_and_clear(tlb->mm, addr, pte);
+ tlb_remove_tlb_entry(tlb, pte, addr);
if (unlikely(!page))
continue;
if (unlikely(details) && details->nonlinear_vma
&& linear_page_index(details->nonlinear_vma,
- address+offset) != page->index)
- set_pte(ptep, pgoff_to_pte(page->index));
- if (pte_dirty(pte))
+ addr) != page->index)
+ set_pte_at(tlb->mm, addr, pte,
+ pgoff_to_pte(page->index));
+ if (pte_dirty(ptent))
set_page_dirty(page);
if (PageAnon(page))
- tlb->mm->anon_rss--;
- else if (pte_young(pte))
+ dec_mm_counter(tlb->mm, anon_rss);
+ else if (pte_young(ptent))
mark_page_accessed(page);
tlb->freed++;
page_remove_rmap(page);
@@ -527,78 +489,64 @@ static void zap_pte_range(struct mmu_gather *tlb,
*/
if (unlikely(details))
continue;
- if (!pte_file(pte))
- free_swap_and_cache(pte_to_swp_entry(pte));
- pte_clear(ptep);
- }
- pte_unmap(ptep-1);
+ if (!pte_file(ptent))
+ free_swap_and_cache(pte_to_swp_entry(ptent));
+ pte_clear(tlb->mm, addr, pte);
+ } while (pte++, addr += PAGE_SIZE, addr != end);
+ pte_unmap(pte - 1);
}
-static void zap_pmd_range(struct mmu_gather *tlb,
- pud_t *pud, unsigned long address,
- unsigned long size, struct zap_details *details)
+static inline void zap_pmd_range(struct mmu_gather *tlb, pud_t *pud,
+ unsigned long addr, unsigned long end,
+ struct zap_details *details)
{
- pmd_t * pmd;
- unsigned long end;
+ pmd_t *pmd;
+ unsigned long next;
- if (pud_none(*pud))
- return;
- if (unlikely(pud_bad(*pud))) {
- pud_ERROR(*pud);
- pud_clear(pud);
- return;
- }
- pmd = pmd_offset(pud, address);
- end = address + size;
- if (end > ((address + PUD_SIZE) & PUD_MASK))
- end = ((address + PUD_SIZE) & PUD_MASK);
+ pmd = pmd_offset(pud, addr);
do {
- zap_pte_range(tlb, pmd, address, end - address, details);
- address = (address + PMD_SIZE) & PMD_MASK;
- pmd++;
- } while (address && (address < end));
+ next = pmd_addr_end(addr, end);
+ if (pmd_none_or_clear_bad(pmd))
+ continue;
+ zap_pte_range(tlb, pmd, addr, next, details);
+ } while (pmd++, addr = next, addr != end);
}
-static void zap_pud_range(struct mmu_gather *tlb,
- pgd_t * pgd, unsigned long address,
- unsigned long end, struct zap_details *details)
+static inline void zap_pud_range(struct mmu_gather *tlb, pgd_t *pgd,
+ unsigned long addr, unsigned long end,
+ struct zap_details *details)
{
- pud_t * pud;
+ pud_t *pud;
+ unsigned long next;
- if (pgd_none(*pgd))
- return;
- if (unlikely(pgd_bad(*pgd))) {
- pgd_ERROR(*pgd);
- pgd_clear(pgd);
- return;
- }
- pud = pud_offset(pgd, address);
+ pud = pud_offset(pgd, addr);
do {
- zap_pmd_range(tlb, pud, address, end - address, details);
- address = (address + PUD_SIZE) & PUD_MASK;
- pud++;
- } while (address && (address < end));
+ next = pud_addr_end(addr, end);
+ if (pud_none_or_clear_bad(pud))
+ continue;
+ zap_pmd_range(tlb, pud, addr, next, details);
+ } while (pud++, addr = next, addr != end);
}
-static void unmap_page_range(struct mmu_gather *tlb,
- struct vm_area_struct *vma, unsigned long address,
- unsigned long end, struct zap_details *details)
+static void unmap_page_range(struct mmu_gather *tlb, struct vm_area_struct *vma,
+ unsigned long addr, unsigned long end,
+ struct zap_details *details)
{
- unsigned long next;
pgd_t *pgd;
- int i;
+ unsigned long next;
+
+ if (details && !details->check_mapping && !details->nonlinear_vma)
+ details = NULL;
- BUG_ON(address >= end);
- pgd = pgd_offset(vma->vm_mm, address);
+ BUG_ON(addr >= end);
tlb_start_vma(tlb, vma);
- for (i = pgd_index(address); i <= pgd_index(end-1); i++) {
- next = (address + PGDIR_SIZE) & PGDIR_MASK;
- if (next <= address || next > end)
- next = end;
- zap_pud_range(tlb, pgd, address, next, details);
- address = next;
- pgd++;
- }
+ pgd = pgd_offset(vma->vm_mm, addr);
+ do {
+ next = pgd_addr_end(addr, end);
+ if (pgd_none_or_clear_bad(pgd))
+ continue;
+ zap_pud_range(tlb, pgd, addr, next, details);
+ } while (pgd++, addr = next, addr != end);
tlb_end_vma(tlb, vma);
}
@@ -735,7 +683,6 @@ void zap_page_range(struct vm_area_struct *vma, unsigned long address,
tlb = tlb_gather_mmu(mm, 0);
unmap_vmas(&tlb, mm, vma, address, end, &nr_accounted, details);
tlb_finish_mmu(tlb, address, end);
- acct_update_integrals();
spin_unlock(&mm->page_table_lock);
}
@@ -987,111 +934,78 @@ out:
EXPORT_SYMBOL(get_user_pages);
-static void zeromap_pte_range(pte_t * pte, unsigned long address,
- unsigned long size, pgprot_t prot)
+static int zeromap_pte_range(struct mm_struct *mm, pmd_t *pmd,
+ unsigned long addr, unsigned long end, pgprot_t prot)
{
- unsigned long end;
+ pte_t *pte;
- address &= ~PMD_MASK;
- end = address + size;
- if (end > PMD_SIZE)
- end = PMD_SIZE;
+ pte = pte_alloc_map(mm, pmd, addr);
+ if (!pte)
+ return -ENOMEM;
do {
- pte_t zero_pte = pte_wrprotect(mk_pte(ZERO_PAGE(address), prot));
+ pte_t zero_pte = pte_wrprotect(mk_pte(ZERO_PAGE(addr), prot));
BUG_ON(!pte_none(*pte));
- set_pte(pte, zero_pte);
- address += PAGE_SIZE;
- pte++;
- } while (address && (address < end));
+ set_pte_at(mm, addr, pte, zero_pte);
+ } while (pte++, addr += PAGE_SIZE, addr != end);
+ pte_unmap(pte - 1);
+ return 0;
}
-static inline int zeromap_pmd_range(struct mm_struct *mm, pmd_t * pmd,
- unsigned long address, unsigned long size, pgprot_t prot)
+static inline int zeromap_pmd_range(struct mm_struct *mm, pud_t *pud,
+ unsigned long addr, unsigned long end, pgprot_t prot)
{
- unsigned long base, end;
+ pmd_t *pmd;
+ unsigned long next;
- base = address & PUD_MASK;
- address &= ~PUD_MASK;
- end = address + size;
- if (end > PUD_SIZE)
- end = PUD_SIZE;
+ pmd = pmd_alloc(mm, pud, addr);
+ if (!pmd)
+ return -ENOMEM;
do {
- pte_t * pte = pte_alloc_map(mm, pmd, base + address);
- if (!pte)
+ next = pmd_addr_end(addr, end);
+ if (zeromap_pte_range(mm, pmd, addr, next, prot))
return -ENOMEM;
- zeromap_pte_range(pte, base + address, end - address, prot);
- pte_unmap(pte);
- address = (address + PMD_SIZE) & PMD_MASK;
- pmd++;
- } while (address && (address < end));
+ } while (pmd++, addr = next, addr != end);
return 0;
}
-static inline int zeromap_pud_range(struct mm_struct *mm, pud_t * pud,
- unsigned long address,
- unsigned long size, pgprot_t prot)
+static inline int zeromap_pud_range(struct mm_struct *mm, pgd_t *pgd,
+ unsigned long addr, unsigned long end, pgprot_t prot)
{
- unsigned long base, end;
- int error = 0;
-
- base = address & PGDIR_MASK;
- address &= ~PGDIR_MASK;
- end = address + size;
- if (end > PGDIR_SIZE)
- end = PGDIR_SIZE;
+ pud_t *pud;
+ unsigned long next;
+
+ pud = pud_alloc(mm, pgd, addr);
+ if (!pud)
+ return -ENOMEM;
do {
- pmd_t * pmd = pmd_alloc(mm, pud, base + address);
- error = -ENOMEM;
- if (!pmd)
- break;
- error = zeromap_pmd_range(mm, pmd, base + address,
- end - address, prot);
- if (error)
- break;
- address = (address + PUD_SIZE) & PUD_MASK;
- pud++;
- } while (address && (address < end));
+ next = pud_addr_end(addr, end);
+ if (zeromap_pmd_range(mm, pud, addr, next, prot))
+ return -ENOMEM;
+ } while (pud++, addr = next, addr != end);
return 0;
}
-int zeromap_page_range(struct vm_area_struct *vma, unsigned long address,
- unsigned long size, pgprot_t prot)
+int zeromap_page_range(struct vm_area_struct *vma,
+ unsigned long addr, unsigned long size, pgprot_t prot)
{
- int i;
- int error = 0;
- pgd_t * pgd;
- unsigned long beg = address;
- unsigned long end = address + size;
+ pgd_t *pgd;
unsigned long next;
+ unsigned long end = addr + size;
struct mm_struct *mm = vma->vm_mm;
+ int err;
- pgd = pgd_offset(mm, address);
- flush_cache_range(vma, beg, end);
- BUG_ON(address >= end);
- BUG_ON(end > vma->vm_end);
-
+ BUG_ON(addr >= end);
+ pgd = pgd_offset(mm, addr);
+ flush_cache_range(vma, addr, end);
spin_lock(&mm->page_table_lock);
- for (i = pgd_index(address); i <= pgd_index(end-1); i++) {
- pud_t *pud = pud_alloc(mm, pgd, address);
- error = -ENOMEM;
- if (!pud)
- break;
- next = (address + PGDIR_SIZE) & PGDIR_MASK;
- if (next <= beg || next > end)
- next = end;
- error = zeromap_pud_range(mm, pud, address,
- next - address, prot);
- if (error)
+ do {
+ next = pgd_addr_end(addr, end);
+ err = zeromap_pud_range(mm, pgd, addr, next, prot);
+ if (err)
break;
- address = next;
- pgd++;
- }
- /*
- * Why flush? zeromap_pte_range has a BUG_ON for !pte_none()
- */
- flush_tlb_range(vma, beg, end);
+ } while (pgd++, addr = next, addr != end);
spin_unlock(&mm->page_table_lock);
- return error;
+ return err;
}
/*
@@ -1099,95 +1013,74 @@ int zeromap_page_range(struct vm_area_struct *vma, unsigned long address,
* mappings are removed. any references to nonexistent pages results
* in null mappings (currently treated as "copy-on-access")
*/
-static inline void
-remap_pte_range(pte_t * pte, unsigned long address, unsigned long size,
- unsigned long pfn, pgprot_t prot)
+static int remap_pte_range(struct mm_struct *mm, pmd_t *pmd,
+ unsigned long addr, unsigned long end,
+ unsigned long pfn, pgprot_t prot)
{
- unsigned long end;
+ pte_t *pte;
- address &= ~PMD_MASK;
- end = address + size;
- if (end > PMD_SIZE)
- end = PMD_SIZE;
+ pte = pte_alloc_map(mm, pmd, addr);
+ if (!pte)
+ return -ENOMEM;
do {
BUG_ON(!pte_none(*pte));
if (!pfn_valid(pfn) || PageReserved(pfn_to_page(pfn)))
- set_pte(pte, pfn_pte(pfn, prot));
- address += PAGE_SIZE;
+ set_pte_at(mm, addr, pte, pfn_pte(pfn, prot));
pfn++;
- pte++;
- } while (address && (address < end));
+ } while (pte++, addr += PAGE_SIZE, addr != end);
+ pte_unmap(pte - 1);
+ return 0;
}
-static inline int
-remap_pmd_range(struct mm_struct *mm, pmd_t * pmd, unsigned long address,
- unsigned long size, unsigned long pfn, pgprot_t prot)
+static inline int remap_pmd_range(struct mm_struct *mm, pud_t *pud,
+ unsigned long addr, unsigned long end,
+ unsigned long pfn, pgprot_t prot)
{
- unsigned long base, end;
-
- base = address & PUD_MASK;
- address &= ~PUD_MASK;
- end = address + size;
- if (end > PUD_SIZE)
- end = PUD_SIZE;
- pfn -= (address >> PAGE_SHIFT);
+ pmd_t *pmd;
+ unsigned long next;
+
+ pfn -= addr >> PAGE_SHIFT;
+ pmd = pmd_alloc(mm, pud, addr);
+ if (!pmd)
+ return -ENOMEM;
do {
- pte_t * pte = pte_alloc_map(mm, pmd, base + address);
- if (!pte)
+ next = pmd_addr_end(addr, end);
+ if (remap_pte_range(mm, pmd, addr, next,
+ pfn + (addr >> PAGE_SHIFT), prot))
return -ENOMEM;
- remap_pte_range(pte, base + address, end - address,
- (address >> PAGE_SHIFT) + pfn, prot);
- pte_unmap(pte);
- address = (address + PMD_SIZE) & PMD_MASK;
- pmd++;
- } while (address && (address < end));
+ } while (pmd++, addr = next, addr != end);
return 0;
}
-static inline int remap_pud_range(struct mm_struct *mm, pud_t * pud,
- unsigned long address, unsigned long size,
- unsigned long pfn, pgprot_t prot)
+static inline int remap_pud_range(struct mm_struct *mm, pgd_t *pgd,
+ unsigned long addr, unsigned long end,
+ unsigned long pfn, pgprot_t prot)
{
- unsigned long base, end;
- int error;
-
- base = address & PGDIR_MASK;
- address &= ~PGDIR_MASK;
- end = address + size;
- if (end > PGDIR_SIZE)
- end = PGDIR_SIZE;
- pfn -= address >> PAGE_SHIFT;
+ pud_t *pud;
+ unsigned long next;
+
+ pfn -= addr >> PAGE_SHIFT;
+ pud = pud_alloc(mm, pgd, addr);
+ if (!pud)
+ return -ENOMEM;
do {
- pmd_t *pmd = pmd_alloc(mm, pud, base+address);
- error = -ENOMEM;
- if (!pmd)
- break;
- error = remap_pmd_range(mm, pmd, base + address, end - address,
- (address >> PAGE_SHIFT) + pfn, prot);
- if (error)
- break;
- address = (address + PUD_SIZE) & PUD_MASK;
- pud++;
- } while (address && (address < end));
- return error;
+ next = pud_addr_end(addr, end);
+ if (remap_pmd_range(mm, pud, addr, next,
+ pfn + (addr >> PAGE_SHIFT), prot))
+ return -ENOMEM;
+ } while (pud++, addr = next, addr != end);
+ return 0;
}
/* Note: this is only safe if the mm semaphore is held when called. */
-int remap_pfn_range(struct vm_area_struct *vma, unsigned long from,
+int remap_pfn_range(struct vm_area_struct *vma, unsigned long addr,
unsigned long pfn, unsigned long size, pgprot_t prot)
{
- int error = 0;
pgd_t *pgd;
- unsigned long beg = from;
- unsigned long end = from + size;
unsigned long next;
+ unsigned long end = addr + size;
struct mm_struct *mm = vma->vm_mm;
- int i;
-
- pfn -= from >> PAGE_SHIFT;
- pgd = pgd_offset(mm, from);
- flush_cache_range(vma, beg, end);
- BUG_ON(from >= end);
+ int err;
/*
* Physically remapped pages are special. Tell the
@@ -1199,31 +1092,21 @@ int remap_pfn_range(struct vm_area_struct *vma, unsigned long from,
*/
vma->vm_flags |= VM_IO | VM_RESERVED;
+ BUG_ON(addr >= end);
+ pfn -= addr >> PAGE_SHIFT;
+ pgd = pgd_offset(mm, addr);
+ flush_cache_range(vma, addr, end);
spin_lock(&mm->page_table_lock);
- for (i = pgd_index(beg); i <= pgd_index(end-1); i++) {
- pud_t *pud = pud_alloc(mm, pgd, from);
- error = -ENOMEM;
- if (!pud)
- break;
- next = (from + PGDIR_SIZE) & PGDIR_MASK;
- if (next > end || next <= from)
- next = end;
- error = remap_pud_range(mm, pud, from, end - from,
- pfn + (from >> PAGE_SHIFT), prot);
- if (error)
+ do {
+ next = pgd_addr_end(addr, end);
+ err = remap_pud_range(mm, pgd, addr, next,
+ pfn + (addr >> PAGE_SHIFT), prot);
+ if (err)
break;
- from = next;
- pgd++;
- }
- /*
- * Why flush? remap_pte_range has a BUG_ON for !pte_none()
- */
- flush_tlb_range(vma, beg, end);
+ } while (pgd++, addr = next, addr != end);
spin_unlock(&mm->page_table_lock);
-
- return error;
+ return err;
}
-
EXPORT_SYMBOL(remap_pfn_range);
/*
@@ -1247,11 +1130,11 @@ static inline void break_cow(struct vm_area_struct * vma, struct page * new_page
{
pte_t entry;
- flush_cache_page(vma, address);
entry = maybe_mkwrite(pte_mkdirty(mk_pte(new_page, vma->vm_page_prot)),
vma);
ptep_establish(vma, address, page_table, entry);
update_mmu_cache(vma, address, entry);
+ lazy_mmu_prot_update(entry);
}
/*
@@ -1299,11 +1182,12 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct * vma,
int reuse = can_share_swap_page(old_page);
unlock_page(old_page);
if (reuse) {
- flush_cache_page(vma, address);
+ flush_cache_page(vma, address, pfn);
entry = maybe_mkwrite(pte_mkyoung(pte_mkdirty(pte)),
vma);
ptep_set_access_flags(vma, address, page_table, entry, 1);
update_mmu_cache(vma, address, entry);
+ lazy_mmu_prot_update(entry);
pte_unmap(page_table);
spin_unlock(&mm->page_table_lock);
return VM_FAULT_MINOR;
@@ -1337,13 +1221,12 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct * vma,
page_table = pte_offset_map(pmd, address);
if (likely(pte_same(*page_table, pte))) {
if (PageAnon(old_page))
- mm->anon_rss--;
- if (PageReserved(old_page)) {
- ++mm->rss;
- acct_update_integrals();
- update_mem_hiwater();
- } else
+ dec_mm_counter(mm, anon_rss);
+ if (PageReserved(old_page))
+ inc_mm_counter(mm, rss);
+ else
page_remove_rmap(old_page);
+ flush_cache_page(vma, address, pfn);
break_cow(vma, new_page, address, page_table);
lru_cache_add_active(new_page);
page_add_anon_rmap(new_page, vma, address);
@@ -1746,10 +1629,7 @@ static int do_swap_page(struct mm_struct * mm,
if (vm_swap_full())
remove_exclusive_swap_page(page);
- mm->rss++;
- acct_update_integrals();
- update_mem_hiwater();
-
+ inc_mm_counter(mm, rss);
pte = mk_pte(page, vma->vm_page_prot);
if (write_access && can_share_swap_page(page)) {
pte = maybe_mkwrite(pte_mkdirty(pte), vma);
@@ -1758,7 +1638,7 @@ static int do_swap_page(struct mm_struct * mm,
unlock_page(page);
flush_icache_page(vma, page);
- set_pte(page_table, pte);
+ set_pte_at(mm, address, page_table, pte);
page_add_anon_rmap(page, vma, address);
if (write_access) {
@@ -1770,6 +1650,7 @@ static int do_swap_page(struct mm_struct * mm,
/* No need to invalidate - it was non-present before */
update_mmu_cache(vma, address, pte);
+ lazy_mmu_prot_update(pte);
pte_unmap(page_table);
spin_unlock(&mm->page_table_lock);
out:
@@ -1813,9 +1694,7 @@ do_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma,
spin_unlock(&mm->page_table_lock);
goto out;
}
- mm->rss++;
- acct_update_integrals();
- update_mem_hiwater();
+ inc_mm_counter(mm, rss);
entry = maybe_mkwrite(pte_mkdirty(mk_pte(page,
vma->vm_page_prot)),
vma);
@@ -1824,11 +1703,12 @@ do_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma,
page_add_anon_rmap(page, vma, addr);
}
- set_pte(page_table, entry);
+ set_pte_at(mm, addr, page_table, entry);
pte_unmap(page_table);
/* No need to invalidate - it was non-present before */
update_mmu_cache(vma, addr, entry);
+ lazy_mmu_prot_update(entry);
spin_unlock(&mm->page_table_lock);
out:
return VM_FAULT_MINOR;
@@ -1931,15 +1811,13 @@ retry:
/* Only go through if we didn't race with anybody else... */
if (pte_none(*page_table)) {
if (!PageReserved(new_page))
- ++mm->rss;
- acct_update_integrals();
- update_mem_hiwater();
+ inc_mm_counter(mm, rss);
flush_icache_page(vma, new_page);
entry = mk_pte(new_page, vma->vm_page_prot);
if (write_access)
entry = maybe_mkwrite(pte_mkdirty(entry), vma);
- set_pte(page_table, entry);
+ set_pte_at(mm, address, page_table, entry);
if (anon) {
lru_cache_add_active(new_page);
page_add_anon_rmap(new_page, vma, address);
@@ -1956,6 +1834,7 @@ retry:
/* no need to invalidate: a not-present page shouldn't be cached */
update_mmu_cache(vma, address, entry);
+ lazy_mmu_prot_update(entry);
spin_unlock(&mm->page_table_lock);
out:
return ret;
@@ -1983,7 +1862,7 @@ static int do_file_page(struct mm_struct * mm, struct vm_area_struct * vma,
*/
if (!vma->vm_ops || !vma->vm_ops->populate ||
(write_access && !(vma->vm_flags & VM_SHARED))) {
- pte_clear(pte);
+ pte_clear(mm, address, pte);
return do_no_page(mm, vma, address, write_access, pte, pmd);
}
@@ -2050,6 +1929,7 @@ static inline int handle_pte_fault(struct mm_struct *mm,
entry = pte_mkyoung(entry);
ptep_set_access_flags(vma, address, pte, entry, write_access);
update_mmu_cache(vma, address, entry);
+ lazy_mmu_prot_update(entry);
pte_unmap(pte);
spin_unlock(&mm->page_table_lock);
return VM_FAULT_MINOR;
@@ -2099,15 +1979,12 @@ int handle_mm_fault(struct mm_struct *mm, struct vm_area_struct * vma,
return VM_FAULT_OOM;
}
-#ifndef __ARCH_HAS_4LEVEL_HACK
+#ifndef __PAGETABLE_PUD_FOLDED
/*
* Allocate page upper directory.
*
* We've already handled the fast-path in-line, and we own the
* page table lock.
- *
- * On a two-level or three-level page table, this ends up actually being
- * entirely optimized away.
*/
pud_t fastcall *__pud_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long address)
{
@@ -2131,15 +2008,14 @@ pud_t fastcall *__pud_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long addr
out:
return pud_offset(pgd, address);
}
+#endif /* __PAGETABLE_PUD_FOLDED */
+#ifndef __PAGETABLE_PMD_FOLDED
/*
* Allocate page middle directory.
*
* We've already handled the fast-path in-line, and we own the
* page table lock.
- *
- * On a two-level page table, this ends up actually being entirely
- * optimized away.
*/
pmd_t fastcall *__pmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long address)
{
@@ -2155,38 +2031,24 @@ pmd_t fastcall *__pmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long addr
* Because we dropped the lock, we should re-check the
* entry, as somebody else could have populated it..
*/
+#ifndef __ARCH_HAS_4LEVEL_HACK
if (pud_present(*pud)) {
pmd_free(new);
goto out;
}
pud_populate(mm, pud, new);
- out:
- return pmd_offset(pud, address);
-}
#else
-pmd_t fastcall *__pmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long address)
-{
- pmd_t *new;
-
- spin_unlock(&mm->page_table_lock);
- new = pmd_alloc_one(mm, address);
- spin_lock(&mm->page_table_lock);
- if (!new)
- return NULL;
-
- /*
- * Because we dropped the lock, we should re-check the
- * entry, as somebody else could have populated it..
- */
if (pgd_present(*pud)) {
pmd_free(new);
goto out;
}
pgd_populate(mm, pud, new);
-out:
+#endif /* __ARCH_HAS_4LEVEL_HACK */
+
+ out:
return pmd_offset(pud, address);
}
-#endif
+#endif /* __PAGETABLE_PMD_FOLDED */
int make_pages_present(unsigned long addr, unsigned long end)
{
@@ -2253,13 +2115,13 @@ EXPORT_SYMBOL(vmalloc_to_pfn);
* update_mem_hiwater
* - update per process rss and vm high water data
*/
-void update_mem_hiwater(void)
+void update_mem_hiwater(struct task_struct *tsk)
{
- struct task_struct *tsk = current;
-
if (tsk->mm) {
- if (tsk->mm->hiwater_rss < tsk->mm->rss)
- tsk->mm->hiwater_rss = tsk->mm->rss;
+ unsigned long rss = get_mm_counter(tsk->mm, rss);
+
+ if (tsk->mm->hiwater_rss < rss)
+ tsk->mm->hiwater_rss = rss;
if (tsk->mm->hiwater_vm < tsk->mm->total_vm)
tsk->mm->hiwater_vm = tsk->mm->total_vm;
}
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index c50402632c6d3..a3b44a671cec2 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -67,6 +67,7 @@
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/nodemask.h>
+#include <linux/cpuset.h>
#include <linux/gfp.h>
#include <linux/slab.h>
#include <linux/string.h>
@@ -167,6 +168,10 @@ static int get_nodes(unsigned long *nodes, unsigned long __user *nmask,
if (copy_from_user(nodes, nmask, nlongs*sizeof(unsigned long)))
return -EFAULT;
nodes[nlongs-1] &= endmask;
+ /* Update current mems_allowed */
+ cpuset_update_current_mems_allowed();
+ /* Ignore nodes not set in current->mems_allowed */
+ cpuset_restrict_to_mems_allowed(nodes);
return mpol_check_policy(mode, nodes);
}
@@ -524,9 +529,13 @@ asmlinkage long sys_get_mempolicy(int __user *policy,
} else
pval = pol->policy;
- err = -EFAULT;
+ if (vma) {
+ up_read(&current->mm->mmap_sem);
+ vma = NULL;
+ }
+
if (policy && put_user(pval, policy))
- goto out;
+ return -EFAULT;
err = 0;
if (nmask) {
@@ -639,7 +648,7 @@ get_vma_policy(struct vm_area_struct *vma, unsigned long addr)
}
/* Return a zonelist representing a mempolicy */
-static struct zonelist *zonelist_policy(unsigned gfp, struct mempolicy *policy)
+static struct zonelist *zonelist_policy(unsigned int __nocast gfp, struct mempolicy *policy)
{
int nd;
@@ -651,8 +660,10 @@ static struct zonelist *zonelist_policy(unsigned gfp, struct mempolicy *policy)
break;
case MPOL_BIND:
/* Lower zones don't get a policy applied */
+ /* Careful: current->mems_allowed might have moved */
if (gfp >= policy_zone)
- return policy->v.zonelist;
+ if (cpuset_zonelist_valid_mems_allowed(policy->v.zonelist))
+ return policy->v.zonelist;
/*FALL THROUGH*/
case MPOL_INTERLEAVE: /* should not happen */
case MPOL_DEFAULT:
@@ -701,7 +712,7 @@ static unsigned offset_il_node(struct mempolicy *pol,
/* Allocate a page in interleaved policy.
Own path because it needs to do special accounting. */
-static struct page *alloc_page_interleave(unsigned gfp, unsigned order, unsigned nid)
+static struct page *alloc_page_interleave(unsigned int __nocast gfp, unsigned order, unsigned nid)
{
struct zonelist *zl;
struct page *page;
@@ -739,10 +750,12 @@ static struct page *alloc_page_interleave(unsigned gfp, unsigned order, unsigned
* Should be called with the mm_sem of the vma hold.
*/
struct page *
-alloc_page_vma(unsigned gfp, struct vm_area_struct *vma, unsigned long addr)
+alloc_page_vma(unsigned int __nocast gfp, struct vm_area_struct *vma, unsigned long addr)
{
struct mempolicy *pol = get_vma_policy(vma, addr);
+ cpuset_update_current_mems_allowed();
+
if (unlikely(pol->policy == MPOL_INTERLEAVE)) {
unsigned nid;
if (vma) {
@@ -775,11 +788,17 @@ alloc_page_vma(unsigned gfp, struct vm_area_struct *vma, unsigned long addr)
* Allocate a page from the kernel page pool. When not in
* 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
+ * 1) it's ok to take cpuset_sem (can WAIT), and
+ * 2) allocating for current task (not interrupt).
*/
-struct page *alloc_pages_current(unsigned gfp, unsigned order)
+struct page *alloc_pages_current(unsigned int __nocast gfp, unsigned order)
{
struct mempolicy *pol = current->mempolicy;
+ if ((gfp & __GFP_WAIT) && !in_interrupt())
+ cpuset_update_current_mems_allowed();
if (!pol || in_interrupt())
pol = &default_policy;
if (pol->policy == MPOL_INTERLEAVE)
diff --git a/mm/mempool.c b/mm/mempool.c
index 8dec8779e28f0..b014ffeaa4137 100644
--- a/mm/mempool.c
+++ b/mm/mempool.c
@@ -105,7 +105,7 @@ EXPORT_SYMBOL(mempool_create);
* while this function is running. mempool_alloc() & mempool_free()
* might be called (eg. from IRQ contexts) while this function executes.
*/
-int mempool_resize(mempool_t *pool, int new_min_nr, int gfp_mask)
+int mempool_resize(mempool_t *pool, int new_min_nr, unsigned int __nocast gfp_mask)
{
void *element;
void **new_elements;
@@ -114,8 +114,8 @@ int mempool_resize(mempool_t *pool, int new_min_nr, int gfp_mask)
BUG_ON(new_min_nr <= 0);
spin_lock_irqsave(&pool->lock, flags);
- if (new_min_nr < pool->min_nr) {
- while (pool->curr_nr > new_min_nr) {
+ if (new_min_nr <= pool->min_nr) {
+ while (new_min_nr < pool->curr_nr) {
element = remove_element(pool);
spin_unlock_irqrestore(&pool->lock, flags);
pool->free(element, pool->pool_data);
@@ -132,6 +132,12 @@ int mempool_resize(mempool_t *pool, int new_min_nr, int gfp_mask)
return -ENOMEM;
spin_lock_irqsave(&pool->lock, flags);
+ if (unlikely(new_min_nr <= pool->min_nr)) {
+ /* Raced, other resize will do our work */
+ spin_unlock_irqrestore(&pool->lock, flags);
+ kfree(new_elements);
+ goto out;
+ }
memcpy(new_elements, pool->elements,
pool->curr_nr * sizeof(*new_elements));
kfree(pool->elements);
@@ -149,7 +155,7 @@ int mempool_resize(mempool_t *pool, int new_min_nr, int gfp_mask)
} else {
spin_unlock_irqrestore(&pool->lock, flags);
pool->free(element, pool->pool_data); /* Raced */
- spin_lock_irqsave(&pool->lock, flags);
+ goto out;
}
}
out_unlock:
@@ -187,7 +193,7 @@ EXPORT_SYMBOL(mempool_destroy);
* *never* fails when called from process contexts. (it might
* fail if called from an IRQ context.)
*/
-void * mempool_alloc(mempool_t *pool, int gfp_mask)
+void * mempool_alloc(mempool_t *pool, unsigned int __nocast gfp_mask)
{
void *element;
unsigned long flags;
@@ -269,7 +275,7 @@ EXPORT_SYMBOL(mempool_free);
/*
* A commonly used alloc and free fn.
*/
-void *mempool_alloc_slab(int gfp_mask, void *pool_data)
+void *mempool_alloc_slab(unsigned int __nocast gfp_mask, void *pool_data)
{
kmem_cache_t *mem = (kmem_cache_t *) pool_data;
return kmem_cache_alloc(mem, gfp_mask);
diff --git a/mm/mincore.c b/mm/mincore.c
index c47fff50053df..07833dc5829df 100644
--- a/mm/mincore.c
+++ b/mm/mincore.c
@@ -97,8 +97,7 @@ static long mincore_vma(struct vm_area_struct * vma,
* return values:
* zero - success
* -EFAULT - vec points to an illegal address
- * -EINVAL - addr is not a multiple of PAGE_CACHE_SIZE,
- * or len has a nonpositive value
+ * -EINVAL - addr is not a multiple of PAGE_CACHE_SIZE
* -ENOMEM - Addresses in the range [addr, addr + len] are
* invalid for the address space of this process, or
* specify one or more pages which are not currently
@@ -126,10 +125,13 @@ asmlinkage long sys_mincore(unsigned long start, size_t len,
if (start >= limit)
goto enomem;
+ if (!len)
+ return 0;
+
max = limit - start;
len = PAGE_CACHE_ALIGN(len);
- if (len > max)
- goto einval;
+ if (len > max || !len)
+ goto enomem;
end = start + len;
diff --git a/mm/mlock.c b/mm/mlock.c
index 5c722ce45cd8f..4ae3a46ff7688 100644
--- a/mm/mlock.c
+++ b/mm/mlock.c
@@ -7,18 +7,32 @@
#include <linux/mman.h>
#include <linux/mm.h>
+#include <linux/mempolicy.h>
#include <linux/syscalls.h>
-static int mlock_fixup(struct vm_area_struct * vma,
+static int mlock_fixup(struct vm_area_struct *vma, struct vm_area_struct **prev,
unsigned long start, unsigned long end, unsigned int newflags)
{
struct mm_struct * mm = vma->vm_mm;
+ pgoff_t pgoff;
int pages;
int ret = 0;
- if (newflags == vma->vm_flags)
+ if (newflags == vma->vm_flags) {
+ *prev = vma;
goto out;
+ }
+
+ pgoff = vma->vm_pgoff + ((start - vma->vm_start) >> PAGE_SHIFT);
+ *prev = vma_merge(mm, *prev, start, end, newflags, vma->anon_vma,
+ vma->vm_file, pgoff, vma_policy(vma));
+ if (*prev) {
+ vma = *prev;
+ goto success;
+ }
+
+ *prev = vma;
if (start != vma->vm_start) {
ret = split_vma(mm, vma, start, 1);
@@ -32,6 +46,7 @@ static int mlock_fixup(struct vm_area_struct * vma,
goto out;
}
+success:
/*
* vm_flags is protected by the mmap_sem held in write mode.
* It's okay if try_to_unmap_one unmaps a page just after we
@@ -59,7 +74,7 @@ out:
static int do_mlock(unsigned long start, size_t len, int on)
{
unsigned long nstart, end, tmp;
- struct vm_area_struct * vma, * next;
+ struct vm_area_struct * vma, * prev;
int error;
len = PAGE_ALIGN(len);
@@ -68,10 +83,13 @@ static int do_mlock(unsigned long start, size_t len, int on)
return -EINVAL;
if (end == start)
return 0;
- vma = find_vma(current->mm, start);
+ vma = find_vma_prev(current->mm, start, &prev);
if (!vma || vma->vm_start > start)
return -ENOMEM;
+ if (start > vma->vm_start)
+ prev = vma;
+
for (nstart = start ; ; ) {
unsigned int newflags;
@@ -81,18 +99,19 @@ static int do_mlock(unsigned long start, size_t len, int on)
if (!on)
newflags &= ~VM_LOCKED;
- if (vma->vm_end >= end) {
- error = mlock_fixup(vma, nstart, end, newflags);
- break;
- }
-
tmp = vma->vm_end;
- next = vma->vm_next;
- error = mlock_fixup(vma, nstart, tmp, newflags);
+ if (tmp > end)
+ tmp = end;
+ error = mlock_fixup(vma, &prev, nstart, tmp, newflags);
if (error)
break;
nstart = tmp;
- vma = next;
+ if (nstart < prev->vm_end)
+ nstart = prev->vm_end;
+ if (nstart >= end)
+ break;
+
+ vma = prev->vm_next;
if (!vma || vma->vm_start != nstart) {
error = -ENOMEM;
break;
@@ -141,7 +160,7 @@ asmlinkage long sys_munlock(unsigned long start, size_t len)
static int do_mlockall(int flags)
{
- struct vm_area_struct * vma;
+ struct vm_area_struct * vma, * prev = NULL;
unsigned int def_flags = 0;
if (flags & MCL_FUTURE)
@@ -150,7 +169,7 @@ static int do_mlockall(int flags)
if (flags == MCL_FUTURE)
goto out;
- for (vma = current->mm->mmap; vma ; vma = vma->vm_next) {
+ for (vma = current->mm->mmap; vma ; vma = prev->vm_next) {
unsigned int newflags;
newflags = vma->vm_flags | VM_LOCKED;
@@ -158,7 +177,7 @@ static int do_mlockall(int flags)
newflags &= ~VM_LOCKED;
/* Ignore errors */
- mlock_fixup(vma, vma->vm_start, vma->vm_end, newflags);
+ mlock_fixup(vma, &prev, vma->vm_start, vma->vm_end, newflags);
}
out:
return 0;
diff --git a/mm/mmap.c b/mm/mmap.c
index b8af0c8db48d6..a95ebda274462 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -21,7 +21,6 @@
#include <linux/hugetlb.h>
#include <linux/profile.h>
#include <linux/module.h>
-#include <linux/acct.h>
#include <linux/mount.h>
#include <linux/mempolicy.h>
#include <linux/rmap.h>
@@ -873,7 +872,7 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr,
int error;
struct rb_node ** rb_link, * rb_parent;
int accountable = 1;
- unsigned long charged = 0;
+ unsigned long charged = 0, reqprot = prot;
if (file) {
if (is_file_hugepages(file))
@@ -897,16 +896,16 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr,
prot |= PROT_EXEC;
if (!len)
- return addr;
+ return -EINVAL;
/* Careful about overflows.. */
len = PAGE_ALIGN(len);
if (!len || len > TASK_SIZE)
- return -EINVAL;
+ return -ENOMEM;
/* offset overflow? */
if ((pgoff + (len >> PAGE_SHIFT)) < pgoff)
- return -EINVAL;
+ return -EOVERFLOW;
/* Too many mappings? */
if (mm->map_count > sysctl_max_map_count)
@@ -991,7 +990,7 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr,
}
}
- error = security_file_mmap(file, prot, flags);
+ error = security_file_mmap(file, reqprot, prot, flags);
if (error)
return error;
@@ -1121,8 +1120,6 @@ out:
pgoff, flags & MAP_NONBLOCK);
down_write(&mm->mmap_sem);
}
- acct_update_integrals();
- update_mem_hiwater();
return addr;
unmap_and_free_vma:
@@ -1221,19 +1218,14 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
const unsigned long len, const unsigned long pgoff,
const unsigned long flags)
{
- struct vm_area_struct *vma, *prev_vma;
+ struct vm_area_struct *vma;
struct mm_struct *mm = current->mm;
- unsigned long base = mm->mmap_base, addr = addr0;
- int first_time = 1;
+ unsigned long addr = addr0;
/* requested length too big for entire address space */
if (len > TASK_SIZE)
return -ENOMEM;
- /* dont allow allocations above current base */
- if (mm->free_area_cache > base)
- mm->free_area_cache = base;
-
/* requesting a specific address */
if (addr) {
addr = PAGE_ALIGN(addr);
@@ -1243,48 +1235,34 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
return addr;
}
-try_again:
+ /* either no address requested or can't fit in requested address hole */
+ addr = mm->free_area_cache;
+
/* make sure it can fit in the remaining address space */
- if (mm->free_area_cache < len)
- goto fail;
+ if (addr >= len) {
+ vma = find_vma(mm, addr-len);
+ if (!vma || addr <= vma->vm_start)
+ /* remember the address as a hint for next time */
+ return (mm->free_area_cache = addr-len);
+ }
+
+ addr = mm->mmap_base-len;
- /* either no address requested or cant fit in requested address hole */
- addr = (mm->free_area_cache - len) & PAGE_MASK;
do {
/*
* Lookup failure means no vma is above this address,
- * i.e. return with success:
+ * else if new region fits below vma->vm_start,
+ * return with success:
*/
- if (!(vma = find_vma_prev(mm, addr, &prev_vma)))
- return addr;
-
- /*
- * new region fits between prev_vma->vm_end and
- * vma->vm_start, use it:
- */
- if (addr+len <= vma->vm_start &&
- (!prev_vma || (addr >= prev_vma->vm_end)))
+ vma = find_vma(mm, addr);
+ if (!vma || addr+len <= vma->vm_start)
/* remember the address as a hint for next time */
return (mm->free_area_cache = addr);
- else
- /* pull free_area_cache down to the first hole */
- if (mm->free_area_cache == vma->vm_end)
- mm->free_area_cache = vma->vm_start;
/* try just below the current vma->vm_start */
addr = vma->vm_start-len;
} while (len <= vma->vm_start);
-fail:
- /*
- * if hint left us with no space for the requested
- * mapping then try again:
- */
- if (first_time) {
- mm->free_area_cache = base;
- first_time = 0;
- goto try_again;
- }
/*
* A failed mmap() very likely causes application failure,
* so fall back to the bottom-up function here. This scenario
@@ -1296,7 +1274,7 @@ fail:
/*
* Restore the topdown base:
*/
- mm->free_area_cache = base;
+ mm->free_area_cache = mm->mmap_base;
return addr;
}
@@ -1309,6 +1287,10 @@ void arch_unmap_area_topdown(struct vm_area_struct *area)
*/
if (area->vm_end > area->vm_mm->free_area_cache)
area->vm_mm->free_area_cache = area->vm_end;
+
+ /* dont allow allocations above current base */
+ if (area->vm_mm->free_area_cache > area->vm_mm->mmap_base)
+ area->vm_mm->free_area_cache = area->vm_mm->mmap_base;
}
unsigned long
@@ -1334,7 +1316,7 @@ get_unmapped_area(struct file *file, unsigned long addr, unsigned long len,
* reserved hugepage range. For some archs like IA-64,
* there is a separate region for hugepages.
*/
- ret = is_hugepage_only_range(addr, len);
+ ret = is_hugepage_only_range(current->mm, addr, len);
}
if (ret)
return -EINVAL;
@@ -1463,8 +1445,6 @@ static int acct_stack_growth(struct vm_area_struct * vma, unsigned long size, un
if (vma->vm_flags & VM_LOCKED)
mm->locked_vm += grow;
__vm_stat_account(mm, vma->vm_flags, vma->vm_file, grow);
- acct_update_integrals();
- update_mem_hiwater();
return 0;
}
@@ -1707,7 +1687,7 @@ static void unmap_region(struct mm_struct *mm,
unmap_vmas(&tlb, mm, vma, start, end, &nr_accounted, NULL);
vm_unacct_memory(nr_accounted);
- if (is_hugepage_only_range(start, end - start))
+ if (is_hugepage_only_range(mm, start, end - start))
hugetlb_free_pgtables(tlb, prev, start, end);
else
free_pgtables(tlb, prev, start, end);
@@ -1968,8 +1948,6 @@ out:
mm->locked_vm += len >> PAGE_SHIFT;
make_pages_present(addr, addr + len);
}
- acct_update_integrals();
- update_mem_hiwater();
return addr;
}
@@ -2000,7 +1978,7 @@ void exit_mmap(struct mm_struct *mm)
vma = mm->mmap;
mm->mmap = mm->mmap_cache = NULL;
mm->mm_rb = RB_ROOT;
- mm->rss = 0;
+ set_mm_counter(mm, rss, 0);
mm->total_vm = 0;
mm->locked_vm = 0;
diff --git a/mm/mprotect.c b/mm/mprotect.c
index 0427711ec10ba..e9fbd013ad9af 100644
--- a/mm/mprotect.c
+++ b/mm/mprotect.c
@@ -25,116 +25,77 @@
#include <asm/cacheflush.h>
#include <asm/tlbflush.h>
-static inline void
-change_pte_range(pmd_t *pmd, unsigned long address,
- unsigned long size, pgprot_t newprot)
+static void change_pte_range(struct mm_struct *mm, pmd_t *pmd,
+ unsigned long addr, unsigned long end, pgprot_t newprot)
{
- pte_t * pte;
- unsigned long end;
-
- if (pmd_none(*pmd))
- return;
- if (pmd_bad(*pmd)) {
- pmd_ERROR(*pmd);
- pmd_clear(pmd);
- return;
- }
- pte = pte_offset_map(pmd, address);
- address &= ~PMD_MASK;
- end = address + size;
- if (end > PMD_SIZE)
- end = PMD_SIZE;
+ pte_t *pte;
+
+ pte = pte_offset_map(pmd, addr);
do {
if (pte_present(*pte)) {
- pte_t entry;
+ pte_t ptent;
/* Avoid an SMP race with hardware updated dirty/clean
* bits by wiping the pte and then setting the new pte
* into place.
*/
- entry = ptep_get_and_clear(pte);
- set_pte(pte, pte_modify(entry, newprot));
+ ptent = pte_modify(ptep_get_and_clear(mm, addr, pte), newprot);
+ set_pte_at(mm, addr, pte, ptent);
+ lazy_mmu_prot_update(ptent);
}
- address += PAGE_SIZE;
- pte++;
- } while (address && (address < end));
+ } while (pte++, addr += PAGE_SIZE, addr != end);
pte_unmap(pte - 1);
}
-static inline void
-change_pmd_range(pud_t *pud, unsigned long address,
- unsigned long size, pgprot_t newprot)
+static inline void change_pmd_range(struct mm_struct *mm, pud_t *pud,
+ unsigned long addr, unsigned long end, pgprot_t newprot)
{
- pmd_t * pmd;
- unsigned long end;
-
- if (pud_none(*pud))
- return;
- if (pud_bad(*pud)) {
- pud_ERROR(*pud);
- pud_clear(pud);
- return;
- }
- pmd = pmd_offset(pud, address);
- address &= ~PUD_MASK;
- end = address + size;
- if (end > PUD_SIZE)
- end = PUD_SIZE;
+ pmd_t *pmd;
+ unsigned long next;
+
+ pmd = pmd_offset(pud, addr);
do {
- change_pte_range(pmd, address, end - address, newprot);
- address = (address + PMD_SIZE) & PMD_MASK;
- pmd++;
- } while (address && (address < end));
+ next = pmd_addr_end(addr, end);
+ if (pmd_none_or_clear_bad(pmd))
+ continue;
+ change_pte_range(mm, pmd, addr, next, newprot);
+ } while (pmd++, addr = next, addr != end);
}
-static inline void
-change_pud_range(pgd_t *pgd, unsigned long address,
- unsigned long size, pgprot_t newprot)
+static inline void change_pud_range(struct mm_struct *mm, pgd_t *pgd,
+ unsigned long addr, unsigned long end, pgprot_t newprot)
{
- pud_t * pud;
- unsigned long end;
-
- if (pgd_none(*pgd))
- return;
- if (pgd_bad(*pgd)) {
- pgd_ERROR(*pgd);
- pgd_clear(pgd);
- return;
- }
- pud = pud_offset(pgd, address);
- address &= ~PGDIR_MASK;
- end = address + size;
- if (end > PGDIR_SIZE)
- end = PGDIR_SIZE;
+ pud_t *pud;
+ unsigned long next;
+
+ pud = pud_offset(pgd, addr);
do {
- change_pmd_range(pud, address, end - address, newprot);
- address = (address + PUD_SIZE) & PUD_MASK;
- pud++;
- } while (address && (address < end));
+ next = pud_addr_end(addr, end);
+ if (pud_none_or_clear_bad(pud))
+ continue;
+ change_pmd_range(mm, pud, addr, next, newprot);
+ } while (pud++, addr = next, addr != end);
}
-static void
-change_protection(struct vm_area_struct *vma, unsigned long start,
- unsigned long end, pgprot_t newprot)
+static void change_protection(struct vm_area_struct *vma,
+ unsigned long addr, unsigned long end, pgprot_t newprot)
{
- struct mm_struct *mm = current->mm;
+ struct mm_struct *mm = vma->vm_mm;
pgd_t *pgd;
- unsigned long beg = start, next;
- int i;
+ unsigned long next;
+ unsigned long start = addr;
- pgd = pgd_offset(mm, start);
- flush_cache_range(vma, beg, end);
- BUG_ON(start >= end);
+ BUG_ON(addr >= end);
+ pgd = pgd_offset(mm, addr);
+ flush_cache_range(vma, addr, end);
spin_lock(&mm->page_table_lock);
- for (i = pgd_index(start); i <= pgd_index(end-1); i++) {
- next = (start + PGDIR_SIZE) & PGDIR_MASK;
- if (next <= start || next > end)
- next = end;
- change_pud_range(pgd, start, next - start, newprot);
- start = next;
- pgd++;
- }
- flush_tlb_range(vma, beg, end);
+ do {
+ next = pgd_addr_end(addr, end);
+ if (pgd_none_or_clear_bad(pgd))
+ continue;
+ change_pud_range(mm, pgd, addr, next, newprot);
+ } while (pgd++, addr = next, addr != end);
+ flush_tlb_range(vma, start, end);
spin_unlock(&mm->page_table_lock);
}
@@ -142,7 +103,7 @@ static int
mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev,
unsigned long start, unsigned long end, unsigned long newflags)
{
- struct mm_struct * mm = vma->vm_mm;
+ struct mm_struct *mm = vma->vm_mm;
unsigned long oldflags = vma->vm_flags;
long nrpages = (end - start) >> PAGE_SHIFT;
unsigned long charged = 0;
@@ -185,16 +146,13 @@ mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev,
goto success;
}
+ *pprev = vma;
+
if (start != vma->vm_start) {
error = split_vma(mm, vma, start, 1);
if (error)
goto fail;
}
- /*
- * Unless it returns an error, this function always sets *pprev to
- * the first vma for which vma->vm_end >= end.
- */
- *pprev = vma;
if (end != vma->vm_end) {
error = split_vma(mm, vma, end, 0);
@@ -222,7 +180,7 @@ fail:
asmlinkage long
sys_mprotect(unsigned long start, size_t len, unsigned long prot)
{
- unsigned long vm_flags, nstart, end, tmp;
+ unsigned long vm_flags, nstart, end, tmp, reqprot;
struct vm_area_struct *vma, *prev;
int error = -EINVAL;
const int grows = prot & (PROT_GROWSDOWN|PROT_GROWSUP);
@@ -232,14 +190,16 @@ sys_mprotect(unsigned long start, size_t len, unsigned long prot)
if (start & ~PAGE_MASK)
return -EINVAL;
+ if (!len)
+ return 0;
len = PAGE_ALIGN(len);
end = start + len;
- if (end < start)
+ if (end <= start)
return -ENOMEM;
if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC | PROT_SEM))
return -EINVAL;
- if (end == start)
- return 0;
+
+ reqprot = prot;
/*
* Does the application expect PROT_READ to imply PROT_EXEC:
*/
@@ -293,7 +253,7 @@ sys_mprotect(unsigned long start, size_t len, unsigned long prot)
goto out;
}
- error = security_file_mprotect(vma, prot);
+ error = security_file_mprotect(vma, reqprot, prot);
if (error)
goto out;
diff --git a/mm/mremap.c b/mm/mremap.c
index ebdf621984ac4..0d1c1b9c7a0a3 100644
--- a/mm/mremap.c
+++ b/mm/mremap.c
@@ -16,7 +16,6 @@
#include <linux/fs.h>
#include <linux/highmem.h>
#include <linux/security.h>
-#include <linux/acct.h>
#include <linux/syscalls.h>
#include <asm/uaccess.h>
@@ -31,26 +30,16 @@ static pte_t *get_one_pte_map_nested(struct mm_struct *mm, unsigned long addr)
pte_t *pte = NULL;
pgd = pgd_offset(mm, addr);
- if (pgd_none(*pgd))
+ if (pgd_none_or_clear_bad(pgd))
goto end;
pud = pud_offset(pgd, addr);
- if (pud_none(*pud))
+ if (pud_none_or_clear_bad(pud))
goto end;
- if (pud_bad(*pud)) {
- pud_ERROR(*pud);
- pud_clear(pud);
- goto end;
- }
pmd = pmd_offset(pud, addr);
- if (pmd_none(*pmd))
+ if (pmd_none_or_clear_bad(pmd))
goto end;
- if (pmd_bad(*pmd)) {
- pmd_ERROR(*pmd);
- pmd_clear(pmd);
- goto end;
- }
pte = pte_offset_map_nested(pmd, addr);
if (pte_none(*pte)) {
@@ -68,15 +57,17 @@ static pte_t *get_one_pte_map(struct mm_struct *mm, unsigned long addr)
pmd_t *pmd;
pgd = pgd_offset(mm, addr);
- if (pgd_none(*pgd))
+ if (pgd_none_or_clear_bad(pgd))
return NULL;
pud = pud_offset(pgd, addr);
- if (pud_none(*pud))
+ if (pud_none_or_clear_bad(pud))
return NULL;
+
pmd = pmd_offset(pud, addr);
- if (!pmd_present(*pmd))
+ if (pmd_none_or_clear_bad(pmd))
return NULL;
+
return pte_offset_map(pmd, addr);
}
@@ -150,7 +141,7 @@ move_one_page(struct vm_area_struct *vma, unsigned long old_addr,
if (dst) {
pte_t pte;
pte = ptep_clear_flush(vma, old_addr, src);
- set_pte(dst, pte);
+ set_pte_at(mm, new_addr, dst, pte);
} else
error = -ENOMEM;
pte_unmap_nested(src);
@@ -255,9 +246,6 @@ static unsigned long move_vma(struct vm_area_struct *vma,
new_addr + new_len);
}
- acct_update_integrals();
- update_mem_hiwater();
-
return new_addr;
}
@@ -394,8 +382,6 @@ unsigned long do_mremap(unsigned long addr,
make_pages_present(addr + old_len,
addr + new_len);
}
- acct_update_integrals();
- update_mem_hiwater();
ret = addr;
goto out;
}
diff --git a/mm/msync.c b/mm/msync.c
index b387bac348f94..090f426bca7d5 100644
--- a/mm/msync.c
+++ b/mm/msync.c
@@ -21,170 +21,109 @@
* Called with mm->page_table_lock held to protect against other
* threads/the swapper from ripping pte's out from under us.
*/
-static int filemap_sync_pte(pte_t *ptep, struct vm_area_struct *vma,
- unsigned long address, unsigned int flags)
-{
- pte_t pte = *ptep;
- unsigned long pfn = pte_pfn(pte);
- struct page *page;
-
- if (pte_present(pte) && pfn_valid(pfn)) {
- page = pfn_to_page(pfn);
- if (!PageReserved(page) &&
- (ptep_clear_flush_dirty(vma, address, ptep) ||
- page_test_and_clear_dirty(page)))
- set_page_dirty(page);
- }
- return 0;
-}
-static int filemap_sync_pte_range(pmd_t * pmd,
- unsigned long address, unsigned long end,
- struct vm_area_struct *vma, unsigned int flags)
+static void sync_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
+ unsigned long addr, unsigned long end)
{
pte_t *pte;
- int error;
- if (pmd_none(*pmd))
- return 0;
- if (pmd_bad(*pmd)) {
- pmd_ERROR(*pmd);
- pmd_clear(pmd);
- return 0;
- }
- pte = pte_offset_map(pmd, address);
- if ((address & PMD_MASK) != (end & PMD_MASK))
- end = (address & PMD_MASK) + PMD_SIZE;
- error = 0;
+ pte = pte_offset_map(pmd, addr);
do {
- error |= filemap_sync_pte(pte, vma, address, flags);
- address += PAGE_SIZE;
- pte++;
- } while (address && (address < end));
+ unsigned long pfn;
+ struct page *page;
+
+ if (!pte_present(*pte))
+ continue;
+ pfn = pte_pfn(*pte);
+ if (!pfn_valid(pfn))
+ continue;
+ page = pfn_to_page(pfn);
+ if (PageReserved(page))
+ continue;
+ if (ptep_clear_flush_dirty(vma, addr, pte) ||
+ page_test_and_clear_dirty(page))
+ set_page_dirty(page);
+ } while (pte++, addr += PAGE_SIZE, addr != end);
pte_unmap(pte - 1);
-
- return error;
}
-static inline int filemap_sync_pmd_range(pud_t * pud,
- unsigned long address, unsigned long end,
- struct vm_area_struct *vma, unsigned int flags)
+static inline void sync_pmd_range(struct vm_area_struct *vma, pud_t *pud,
+ unsigned long addr, unsigned long end)
{
- pmd_t * pmd;
- int error;
+ pmd_t *pmd;
+ unsigned long next;
- if (pud_none(*pud))
- return 0;
- if (pud_bad(*pud)) {
- pud_ERROR(*pud);
- pud_clear(pud);
- return 0;
- }
- pmd = pmd_offset(pud, address);
- if ((address & PUD_MASK) != (end & PUD_MASK))
- end = (address & PUD_MASK) + PUD_SIZE;
- error = 0;
+ pmd = pmd_offset(pud, addr);
do {
- error |= filemap_sync_pte_range(pmd, address, end, vma, flags);
- address = (address + PMD_SIZE) & PMD_MASK;
- pmd++;
- } while (address && (address < end));
- return error;
+ next = pmd_addr_end(addr, end);
+ if (pmd_none_or_clear_bad(pmd))
+ continue;
+ sync_pte_range(vma, pmd, addr, next);
+ } while (pmd++, addr = next, addr != end);
}
-static inline int filemap_sync_pud_range(pgd_t *pgd,
- unsigned long address, unsigned long end,
- struct vm_area_struct *vma, unsigned int flags)
+static inline void sync_pud_range(struct vm_area_struct *vma, pgd_t *pgd,
+ unsigned long addr, unsigned long end)
{
pud_t *pud;
- int error;
+ unsigned long next;
- if (pgd_none(*pgd))
- return 0;
- if (pgd_bad(*pgd)) {
- pgd_ERROR(*pgd);
- pgd_clear(pgd);
- return 0;
- }
- pud = pud_offset(pgd, address);
- if ((address & PGDIR_MASK) != (end & PGDIR_MASK))
- end = (address & PGDIR_MASK) + PGDIR_SIZE;
- error = 0;
+ pud = pud_offset(pgd, addr);
do {
- error |= filemap_sync_pmd_range(pud, address, end, vma, flags);
- address = (address + PUD_SIZE) & PUD_MASK;
- pud++;
- } while (address && (address < end));
- return error;
+ next = pud_addr_end(addr, end);
+ if (pud_none_or_clear_bad(pud))
+ continue;
+ sync_pmd_range(vma, pud, addr, next);
+ } while (pud++, addr = next, addr != end);
}
-static int __filemap_sync(struct vm_area_struct *vma, unsigned long address,
- size_t size, unsigned int flags)
+static void sync_page_range(struct vm_area_struct *vma,
+ unsigned long addr, unsigned long end)
{
+ struct mm_struct *mm = vma->vm_mm;
pgd_t *pgd;
- unsigned long end = address + size;
unsigned long next;
- int i;
- int error = 0;
-
- /* Aquire the lock early; it may be possible to avoid dropping
- * and reaquiring it repeatedly.
- */
- spin_lock(&vma->vm_mm->page_table_lock);
-
- pgd = pgd_offset(vma->vm_mm, address);
- flush_cache_range(vma, address, end);
/* For hugepages we can't go walking the page table normally,
* but that's ok, hugetlbfs is memory based, so we don't need
* to do anything more on an msync() */
if (is_vm_hugetlb_page(vma))
- goto out;
-
- if (address >= end)
- BUG();
- for (i = pgd_index(address); i <= pgd_index(end-1); i++) {
- next = (address + PGDIR_SIZE) & PGDIR_MASK;
- if (next <= address || next > end)
- next = end;
- error |= filemap_sync_pud_range(pgd, address, next, vma, flags);
- address = next;
- pgd++;
- }
- /*
- * Why flush ? filemap_sync_pte already flushed the tlbs with the
- * dirty bits.
- */
- flush_tlb_range(vma, end - size, end);
- out:
- spin_unlock(&vma->vm_mm->page_table_lock);
+ return;
- return error;
+ BUG_ON(addr >= end);
+ pgd = pgd_offset(mm, addr);
+ flush_cache_range(vma, addr, end);
+ spin_lock(&mm->page_table_lock);
+ do {
+ next = pgd_addr_end(addr, end);
+ if (pgd_none_or_clear_bad(pgd))
+ continue;
+ sync_pud_range(vma, pgd, addr, next);
+ } while (pgd++, addr = next, addr != end);
+ spin_unlock(&mm->page_table_lock);
}
#ifdef CONFIG_PREEMPT
-static int filemap_sync(struct vm_area_struct *vma, unsigned long address,
- size_t size, unsigned int flags)
+static inline void filemap_sync(struct vm_area_struct *vma,
+ unsigned long addr, unsigned long end)
{
const size_t chunk = 64 * 1024; /* bytes */
- int error = 0;
-
- while (size) {
- size_t sz = min(size, chunk);
+ unsigned long next;
- error |= __filemap_sync(vma, address, sz, flags);
+ do {
+ next = addr + chunk;
+ if (next > end || next < addr)
+ next = end;
+ sync_page_range(vma, addr, next);
cond_resched();
- address += sz;
- size -= sz;
- }
- return error;
+ } while (addr = next, addr != end);
}
#else
-static int filemap_sync(struct vm_area_struct *vma, unsigned long address,
- size_t size, unsigned int flags)
+static inline void filemap_sync(struct vm_area_struct *vma,
+ unsigned long addr, unsigned long end)
{
- return __filemap_sync(vma, address, size, flags);
+ sync_page_range(vma, addr, end);
}
#endif
@@ -199,19 +138,19 @@ static int filemap_sync(struct vm_area_struct *vma, unsigned long address,
* So my _not_ starting I/O in MS_ASYNC we provide complete flexibility to
* applications.
*/
-static int msync_interval(struct vm_area_struct * vma,
- unsigned long start, unsigned long end, int flags)
+static int msync_interval(struct vm_area_struct *vma,
+ unsigned long addr, unsigned long end, int flags)
{
int ret = 0;
- struct file * file = vma->vm_file;
+ struct file *file = vma->vm_file;
if ((flags & MS_INVALIDATE) && (vma->vm_flags & VM_LOCKED))
return -EBUSY;
if (file && (vma->vm_flags & VM_SHARED)) {
- ret = filemap_sync(vma, start, end-start, flags);
+ filemap_sync(vma, addr, end);
- if (!ret && (flags & MS_SYNC)) {
+ if (flags & MS_SYNC) {
struct address_space *mapping = file->f_mapping;
int err;
@@ -236,7 +175,7 @@ static int msync_interval(struct vm_area_struct * vma,
asmlinkage long sys_msync(unsigned long start, size_t len, int flags)
{
unsigned long end;
- struct vm_area_struct * vma;
+ struct vm_area_struct *vma;
int unmapped_error, error = -EINVAL;
if (flags & MS_SYNC)
diff --git a/mm/nommu.c b/mm/nommu.c
index 8e70b95a8d9fe..f613db39e8474 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -396,6 +396,7 @@ unsigned long do_mmap_pgoff(struct file *file,
unsigned int vm_flags;
void *result;
int ret, membacked;
+ unsigned long reqprot = prot;
/* do the simple checks first */
if (flags & MAP_FIXED || addr) {
@@ -506,7 +507,7 @@ unsigned long do_mmap_pgoff(struct file *file,
}
/* allow the security API to have its say */
- ret = security_file_mmap(file, prot, flags);
+ ret = security_file_mmap(file, reqprot, prot, flags);
if (ret)
return ret;
@@ -959,13 +960,13 @@ void arch_unmap_area(struct vm_area_struct *area)
{
}
-void update_mem_hiwater(void)
+void update_mem_hiwater(struct task_struct *tsk)
{
- struct task_struct *tsk = current;
+ unsigned long rss = get_mm_counter(tsk->mm, rss);
if (likely(tsk->mm)) {
- if (tsk->mm->hiwater_rss < tsk->mm->rss)
- tsk->mm->hiwater_rss = tsk->mm->rss;
+ if (tsk->mm->hiwater_rss < rss)
+ tsk->mm->hiwater_rss = rss;
if (tsk->mm->hiwater_vm < tsk->mm->total_vm)
tsk->mm->hiwater_vm = tsk->mm->total_vm;
}
@@ -1063,3 +1064,7 @@ int __vm_enough_memory(long pages, int cap_sys_admin)
return -ENOMEM;
}
+int in_gate_area_no_task(unsigned long addr)
+{
+ return 0;
+}
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index 728094668603f..9595a0f6c4b88 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -253,7 +253,7 @@ static struct mm_struct *oom_kill_process(struct task_struct *p)
* OR try to be smart about which process to kill. Note that we
* don't have to be perfect here, we just have to be good.
*/
-void out_of_memory(int gfp_mask)
+void out_of_memory(unsigned int __nocast gfp_mask)
{
struct mm_struct *mm = NULL;
task_t * p;
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index 624ce500fb169..6ddd6a29c73b2 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -289,6 +289,28 @@ void balance_dirty_pages_ratelimited(struct address_space *mapping)
}
EXPORT_SYMBOL(balance_dirty_pages_ratelimited);
+void throttle_vm_writeout(void)
+{
+ struct writeback_state wbs;
+ long background_thresh;
+ long dirty_thresh;
+
+ for ( ; ; ) {
+ get_dirty_limits(&wbs, &background_thresh, &dirty_thresh, NULL);
+
+ /*
+ * Boost the allowable dirty threshold a bit for page
+ * allocators so they don't get DoS'ed by heavy writers
+ */
+ dirty_thresh += dirty_thresh / 10; /* wheeee... */
+
+ if (wbs.nr_unstable + wbs.nr_writeback <= dirty_thresh)
+ break;
+ blk_congestion_wait(WRITE, HZ/10);
+ }
+}
+
+
/*
* writeback at least _min_pages, and keep writing until the amount of dirty
* memory is less than the background threshold, or until we're all clean.
@@ -601,16 +623,16 @@ int __set_page_dirty_nobuffers(struct page *page)
struct address_space *mapping2;
if (mapping) {
- spin_lock_irq(&mapping->tree_lock);
+ write_lock_irq(&mapping->tree_lock);
mapping2 = page_mapping(page);
if (mapping2) { /* Race with truncate? */
BUG_ON(mapping2 != mapping);
- if (!mapping->backing_dev_info->memory_backed)
+ if (mapping_cap_account_dirty(mapping))
inc_page_state(nr_dirty);
radix_tree_tag_set(&mapping->page_tree,
page_index(page), PAGECACHE_TAG_DIRTY);
}
- spin_unlock_irq(&mapping->tree_lock);
+ write_unlock_irq(&mapping->tree_lock);
if (mapping->host) {
/* !PageAnon && !swapper_space */
__mark_inode_dirty(mapping->host,
@@ -685,17 +707,17 @@ int test_clear_page_dirty(struct page *page)
unsigned long flags;
if (mapping) {
- spin_lock_irqsave(&mapping->tree_lock, flags);
+ write_lock_irqsave(&mapping->tree_lock, flags);
if (TestClearPageDirty(page)) {
radix_tree_tag_clear(&mapping->page_tree,
page_index(page),
PAGECACHE_TAG_DIRTY);
- spin_unlock_irqrestore(&mapping->tree_lock, flags);
- if (!mapping->backing_dev_info->memory_backed)
+ write_unlock_irqrestore(&mapping->tree_lock, flags);
+ if (mapping_cap_account_dirty(mapping))
dec_page_state(nr_dirty);
return 1;
}
- spin_unlock_irqrestore(&mapping->tree_lock, flags);
+ write_unlock_irqrestore(&mapping->tree_lock, flags);
return 0;
}
return TestClearPageDirty(page);
@@ -722,7 +744,7 @@ int clear_page_dirty_for_io(struct page *page)
if (mapping) {
if (TestClearPageDirty(page)) {
- if (!mapping->backing_dev_info->memory_backed)
+ if (mapping_cap_account_dirty(mapping))
dec_page_state(nr_dirty);
return 1;
}
@@ -732,30 +754,6 @@ int clear_page_dirty_for_io(struct page *page)
}
EXPORT_SYMBOL(clear_page_dirty_for_io);
-/*
- * Clear a page's dirty flag while ignoring dirty memory accounting
- */
-int __clear_page_dirty(struct page *page)
-{
- struct address_space *mapping = page_mapping(page);
-
- if (mapping) {
- unsigned long flags;
-
- spin_lock_irqsave(&mapping->tree_lock, flags);
- if (TestClearPageDirty(page)) {
- radix_tree_tag_clear(&mapping->page_tree,
- page_index(page),
- PAGECACHE_TAG_DIRTY);
- spin_unlock_irqrestore(&mapping->tree_lock, flags);
- return 1;
- }
- spin_unlock_irqrestore(&mapping->tree_lock, flags);
- return 0;
- }
- return TestClearPageDirty(page);
-}
-
int test_clear_page_writeback(struct page *page)
{
struct address_space *mapping = page_mapping(page);
@@ -764,13 +762,13 @@ int test_clear_page_writeback(struct page *page)
if (mapping) {
unsigned long flags;
- spin_lock_irqsave(&mapping->tree_lock, flags);
+ write_lock_irqsave(&mapping->tree_lock, flags);
ret = TestClearPageWriteback(page);
if (ret)
radix_tree_tag_clear(&mapping->page_tree,
page_index(page),
PAGECACHE_TAG_WRITEBACK);
- spin_unlock_irqrestore(&mapping->tree_lock, flags);
+ write_unlock_irqrestore(&mapping->tree_lock, flags);
} else {
ret = TestClearPageWriteback(page);
}
@@ -785,7 +783,7 @@ int test_set_page_writeback(struct page *page)
if (mapping) {
unsigned long flags;
- spin_lock_irqsave(&mapping->tree_lock, flags);
+ write_lock_irqsave(&mapping->tree_lock, flags);
ret = TestSetPageWriteback(page);
if (!ret)
radix_tree_tag_set(&mapping->page_tree,
@@ -795,7 +793,7 @@ int test_set_page_writeback(struct page *page)
radix_tree_tag_clear(&mapping->page_tree,
page_index(page),
PAGECACHE_TAG_DIRTY);
- spin_unlock_irqrestore(&mapping->tree_lock, flags);
+ write_unlock_irqrestore(&mapping->tree_lock, flags);
} else {
ret = TestSetPageWriteback(page);
}
@@ -813,9 +811,9 @@ int mapping_tagged(struct address_space *mapping, int tag)
unsigned long flags;
int ret;
- spin_lock_irqsave(&mapping->tree_lock, flags);
+ read_lock_irqsave(&mapping->tree_lock, flags);
ret = radix_tree_tagged(&mapping->page_tree, tag);
- spin_unlock_irqrestore(&mapping->tree_lock, flags);
+ read_unlock_irqrestore(&mapping->tree_lock, flags);
return ret;
}
EXPORT_SYMBOL(mapping_tagged);
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 6a8191942c8e7..c73dbbc1cd8f5 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -31,19 +31,24 @@
#include <linux/topology.h>
#include <linux/sysctl.h>
#include <linux/cpu.h>
+#include <linux/cpuset.h>
#include <linux/nodemask.h>
#include <linux/vmalloc.h>
#include <asm/tlbflush.h>
#include "internal.h"
-/* MCD - HACK: Find somewhere to initialize this EARLY, or make this initializer cleaner */
+/*
+ * MCD - HACK: Find somewhere to initialize this EARLY, or make this
+ * initializer cleaner
+ */
nodemask_t node_online_map = { { [0] = 1UL } };
nodemask_t node_possible_map = NODE_MASK_ALL;
struct pglist_data *pgdat_list;
unsigned long totalram_pages;
unsigned long totalhigh_pages;
long nr_swap_pages;
+
/*
* results with 256, 32 in the lowmem_reserve sysctl:
* 1G machine -> (16M dma, 800M-16M normal, 1G-800M high)
@@ -191,6 +196,37 @@ static inline void rmv_page_order(struct page *page)
}
/*
+ * Locate the struct page for both the matching buddy in our
+ * pair (buddy1) and the combined O(n+1) page they form (page).
+ *
+ * 1) Any buddy B1 will have an order O twin B2 which satisfies
+ * the following equation:
+ * B2 = B1 ^ (1 << O)
+ * For example, if the starting buddy (buddy2) is #8 its order
+ * 1 buddy is #10:
+ * B2 = 8 ^ (1 << 1) = 8 ^ 2 = 10
+ *
+ * 2) Any buddy B will have an order O+1 parent P which
+ * satisfies the following equation:
+ * P = B & ~(1 << O)
+ *
+ * Assumption: *_mem_map is contigious at least up to MAX_ORDER
+ */
+static inline struct page *
+__page_find_buddy(struct page *page, unsigned long page_idx, unsigned int order)
+{
+ unsigned long buddy_idx = page_idx ^ (1 << order);
+
+ return page + (buddy_idx - page_idx);
+}
+
+static inline unsigned long
+__find_combined_index(unsigned long page_idx, unsigned int order)
+{
+ return (page_idx & ~(1 << 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 &&
@@ -233,50 +269,49 @@ static inline int page_is_buddy(struct page *page, int order)
* -- wli
*/
-static inline void __free_pages_bulk (struct page *page, struct page *base,
+static inline void __free_pages_bulk (struct page *page,
struct zone *zone, unsigned int order)
{
unsigned long page_idx;
- struct page *coalesced;
int order_size = 1 << order;
if (unlikely(order))
destroy_compound_page(page, order);
- page_idx = page - base;
+ page_idx = page_to_pfn(page) & ((1 << MAX_ORDER) - 1);
BUG_ON(page_idx & (order_size - 1));
BUG_ON(bad_range(zone, page));
zone->free_pages += order_size;
while (order < MAX_ORDER-1) {
+ unsigned long combined_idx;
struct free_area *area;
struct page *buddy;
- int buddy_idx;
- buddy_idx = (page_idx ^ (1 << order));
- buddy = base + buddy_idx;
+ 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. */
+ break; /* Move the buddy up one level. */
list_del(&buddy->lru);
area = zone->free_area + order;
area->nr_free--;
rmv_page_order(buddy);
- page_idx &= buddy_idx;
+ page = page + (combined_idx - page_idx);
+ page_idx = combined_idx;
order++;
}
- coalesced = base + page_idx;
- set_page_order(coalesced, order);
- list_add(&coalesced->lru, &zone->free_area[order].free_list);
+ set_page_order(page, order);
+ list_add(&page->lru, &zone->free_area[order].free_list);
zone->free_area[order].nr_free++;
}
static inline void free_pages_check(const char *function, struct page *page)
{
- if ( page_mapped(page) ||
+ if ( page_mapcount(page) ||
page->mapping != NULL ||
page_count(page) != 0 ||
(page->flags & (
@@ -309,10 +344,9 @@ free_pages_bulk(struct zone *zone, int count,
struct list_head *list, unsigned int order)
{
unsigned long flags;
- struct page *base, *page = NULL;
+ struct page *page = NULL;
int ret = 0;
- base = zone->zone_mem_map;
spin_lock_irqsave(&zone->lock, flags);
zone->all_unreclaimable = 0;
zone->pages_scanned = 0;
@@ -320,7 +354,7 @@ free_pages_bulk(struct zone *zone, int count,
page = list_entry(list->prev, struct page, lru);
/* have to delete it as __free_pages_bulk list manipulates */
list_del(&page->lru);
- __free_pages_bulk(page, base, zone, order);
+ __free_pages_bulk(page, zone, order);
ret++;
}
spin_unlock_irqrestore(&zone->lock, flags);
@@ -404,7 +438,7 @@ void set_page_refs(struct page *page, int order)
*/
static void prep_new_page(struct page *page, int order)
{
- if (page->mapping || page_mapped(page) ||
+ if (page->mapping || page_mapcount(page) ||
(page->flags & (
1 << PG_private |
1 << PG_locked |
@@ -599,7 +633,7 @@ void fastcall free_cold_page(struct page *page)
free_hot_cold_page(page, 1);
}
-static inline void prep_zero_page(struct page *page, int order, int gfp_flags)
+static inline void prep_zero_page(struct page *page, int order, unsigned int __nocast gfp_flags)
{
int i;
@@ -614,7 +648,7 @@ static inline void prep_zero_page(struct page *page, int order, int gfp_flags)
* or two.
*/
static struct page *
-buffered_rmqueue(struct zone *zone, int order, int gfp_flags)
+buffered_rmqueue(struct zone *zone, int order, unsigned int __nocast gfp_flags)
{
unsigned long flags;
struct page *page = NULL;
@@ -692,7 +726,7 @@ int zone_watermark_ok(struct zone *z, int order, unsigned long mark,
* This is the 'heart' of the zoned buddy allocator.
*/
struct page * fastcall
-__alloc_pages(unsigned int gfp_mask, unsigned int order,
+__alloc_pages(unsigned int __nocast gfp_mask, unsigned int order,
struct zonelist *zonelist)
{
const int wait = gfp_mask & __GFP_WAIT;
@@ -732,6 +766,9 @@ __alloc_pages(unsigned int gfp_mask, unsigned int order,
classzone_idx, 0, 0))
continue;
+ if (!cpuset_zone_allowed(z))
+ continue;
+
page = buffered_rmqueue(z, order, gfp_mask);
if (page)
goto got_pg;
@@ -743,6 +780,9 @@ __alloc_pages(unsigned int gfp_mask, unsigned int order,
/*
* Go through the zonelist again. Let __GFP_HIGH and allocations
* coming from realtime tasks to go deeper into reserves
+ *
+ * This is the last chance, in general, before the goto nopage.
+ * Ignore cpuset if GFP_ATOMIC (!wait) rather than fail alloc.
*/
for (i = 0; (z = zones[i]) != NULL; i++) {
if (!zone_watermark_ok(z, order, z->pages_min,
@@ -750,6 +790,9 @@ __alloc_pages(unsigned int gfp_mask, unsigned int order,
gfp_mask & __GFP_HIGH))
continue;
+ if (wait && !cpuset_zone_allowed(z))
+ continue;
+
page = buffered_rmqueue(z, order, gfp_mask);
if (page)
goto got_pg;
@@ -759,6 +802,8 @@ __alloc_pages(unsigned int gfp_mask, unsigned int order,
if (((p->flags & PF_MEMALLOC) || unlikely(test_thread_flag(TIF_MEMDIE))) && !in_interrupt()) {
/* go through the zonelist yet again, ignoring mins */
for (i = 0; (z = zones[i]) != NULL; i++) {
+ if (!cpuset_zone_allowed(z))
+ continue;
page = buffered_rmqueue(z, order, gfp_mask);
if (page)
goto got_pg;
@@ -798,6 +843,9 @@ rebalance:
gfp_mask & __GFP_HIGH))
continue;
+ if (!cpuset_zone_allowed(z))
+ continue;
+
page = buffered_rmqueue(z, order, gfp_mask);
if (page)
goto got_pg;
@@ -814,6 +862,9 @@ rebalance:
classzone_idx, 0, 0))
continue;
+ if (!cpuset_zone_allowed(z))
+ continue;
+
page = buffered_rmqueue(z, order, gfp_mask);
if (page)
goto got_pg;
@@ -860,7 +911,7 @@ EXPORT_SYMBOL(__alloc_pages);
/*
* Common helper functions.
*/
-fastcall unsigned long __get_free_pages(unsigned int gfp_mask, unsigned int order)
+fastcall unsigned long __get_free_pages(unsigned int __nocast gfp_mask, unsigned int order)
{
struct page * page;
page = alloc_pages(gfp_mask, order);
@@ -871,7 +922,7 @@ fastcall unsigned long __get_free_pages(unsigned int gfp_mask, unsigned int orde
EXPORT_SYMBOL(__get_free_pages);
-fastcall unsigned long get_zeroed_page(unsigned int gfp_mask)
+fastcall unsigned long get_zeroed_page(unsigned int __nocast gfp_mask)
{
struct page * page;
@@ -1370,7 +1421,6 @@ static void __init build_zonelists(pg_data_t *pgdat)
/* initialize zonelists */
for (i = 0; i < GFP_ZONETYPES; i++) {
zonelist = pgdat->node_zonelists + i;
- memset(zonelist, 0, sizeof(*zonelist));
zonelist->zones[0] = NULL;
}
@@ -1417,7 +1467,6 @@ static void __init build_zonelists(pg_data_t *pgdat)
struct zonelist *zonelist;
zonelist = pgdat->node_zonelists + i;
- memset(zonelist, 0, sizeof(*zonelist));
j = 0;
k = ZONE_NORMAL;
@@ -1459,6 +1508,7 @@ void __init build_all_zonelists(void)
for_each_online_node(i)
build_zonelists(NODE_DATA(i));
printk("Built %i zonelists\n", num_online_nodes());
+ cpuset_init_current_mems_allowed();
}
/*
@@ -1679,14 +1729,25 @@ static void __init free_area_init_core(struct pglist_data *pgdat,
}
}
-void __init node_alloc_mem_map(struct pglist_data *pgdat)
+static void __init alloc_node_mem_map(struct pglist_data *pgdat)
{
unsigned long size;
- size = (pgdat->node_spanned_pages + 1) * sizeof(struct page);
- pgdat->node_mem_map = alloc_bootmem_node(pgdat, size);
+ /* Skip empty nodes */
+ if (!pgdat->node_spanned_pages)
+ return;
+
+ /* ia64 gets its own node_mem_map, before this, without bootmem */
+ if (!pgdat->node_mem_map) {
+ size = (pgdat->node_spanned_pages + 1) * sizeof(struct page);
+ pgdat->node_mem_map = alloc_bootmem_node(pgdat, size);
+ }
#ifndef CONFIG_DISCONTIGMEM
- mem_map = contig_page_data.node_mem_map;
+ /*
+ * With no DISCONTIG, the global mem_map is just set as node 0's
+ */
+ if (pgdat == NODE_DATA(0))
+ mem_map = NODE_DATA(0)->node_mem_map;
#endif
}
@@ -1698,8 +1759,7 @@ void __init free_area_init_node(int nid, struct pglist_data *pgdat,
pgdat->node_start_pfn = node_start_pfn;
calculate_zone_totalpages(pgdat, zones_size, zholes_size);
- if (!pfn_to_page(node_start_pfn))
- node_alloc_mem_map(pgdat);
+ alloc_node_mem_map(pgdat);
free_area_init_core(pgdat, zones_size, zholes_size);
}
@@ -1924,15 +1984,20 @@ static void setup_per_zone_lowmem_reserve(void)
for_each_pgdat(pgdat) {
for (j = 0; j < MAX_NR_ZONES; j++) {
- struct zone * zone = pgdat->node_zones + j;
+ struct zone *zone = pgdat->node_zones + j;
unsigned long present_pages = zone->present_pages;
zone->lowmem_reserve[j] = 0;
for (idx = j-1; idx >= 0; idx--) {
- struct zone * lower_zone = pgdat->node_zones + idx;
+ struct zone *lower_zone;
+
+ if (sysctl_lowmem_reserve_ratio[idx] < 1)
+ sysctl_lowmem_reserve_ratio[idx] = 1;
- lower_zone->lowmem_reserve[j] = present_pages / sysctl_lowmem_reserve_ratio[idx];
+ lower_zone = pgdat->node_zones + idx;
+ lower_zone->lowmem_reserve[j] = present_pages /
+ sysctl_lowmem_reserve_ratio[idx];
present_pages += lower_zone->present_pages;
}
}
@@ -2039,7 +2104,7 @@ module_init(init_per_zone_pages_min)
* changes.
*/
int min_free_kbytes_sysctl_handler(ctl_table *table, int write,
- struct file *file, void __user *buffer, size_t *length, loff_t *ppos)
+ struct file *file, void __user *buffer, size_t *length, loff_t *ppos)
{
proc_dointvec(table, write, file, buffer, length, ppos);
setup_per_zone_pages_min();
@@ -2056,7 +2121,7 @@ int min_free_kbytes_sysctl_handler(ctl_table *table, int write,
* if in function of the boot time zone sizes.
*/
int lowmem_reserve_ratio_sysctl_handler(ctl_table *table, int write,
- struct file *file, void __user *buffer, size_t *length, loff_t *ppos)
+ struct file *file, void __user *buffer, size_t *length, loff_t *ppos)
{
proc_dointvec_minmax(table, write, file, buffer, length, ppos);
setup_per_zone_lowmem_reserve();
diff --git a/mm/page_io.c b/mm/page_io.c
index 5f1b672c66ac5..667c76df1ec24 100644
--- a/mm/page_io.c
+++ b/mm/page_io.c
@@ -19,7 +19,7 @@
#include <linux/writeback.h>
#include <asm/pgtable.h>
-static struct bio *get_swap_bio(int gfp_flags, pgoff_t index,
+static struct bio *get_swap_bio(unsigned int __nocast gfp_flags, pgoff_t index,
struct page *page, bio_end_io_t end_io)
{
struct bio *bio;
diff --git a/mm/readahead.c b/mm/readahead.c
index b7c3b746de679..b840e7c6ea740 100644
--- a/mm/readahead.c
+++ b/mm/readahead.c
@@ -23,6 +23,7 @@ EXPORT_SYMBOL(default_unplug_io_fn);
struct backing_dev_info default_backing_dev_info = {
.ra_pages = (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE,
.state = 0,
+ .capabilities = BDI_CAP_MAP_COPY,
.unplug_io_fn = default_unplug_io_fn,
};
EXPORT_SYMBOL_GPL(default_backing_dev_info);
@@ -55,7 +56,7 @@ static inline void ra_off(struct file_ra_state *ra)
{
ra->start = 0;
ra->flags = 0;
- ra->size = -1;
+ ra->size = 0;
ra->ahead_start = 0;
ra->ahead_size = 0;
return;
@@ -85,14 +86,16 @@ static unsigned long get_init_ra_size(unsigned long size, unsigned long max)
* not for each call to readahead. If a cache miss occured, reduce next I/O
* size, else increase depending on how close to max we are.
*/
-static unsigned long get_next_ra_size(unsigned long cur, unsigned long max,
- unsigned long min, unsigned long * flags)
+static inline unsigned long get_next_ra_size(struct file_ra_state *ra)
{
+ unsigned long max = get_max_readahead(ra);
+ unsigned long min = get_min_readahead(ra);
+ unsigned long cur = ra->size;
unsigned long newsize;
- if (*flags & RA_FLAG_MISS) {
+ if (ra->flags & RA_FLAG_MISS) {
+ ra->flags &= ~RA_FLAG_MISS;
newsize = max((cur - 2), min);
- *flags &= ~RA_FLAG_MISS;
} else if (cur < max / 16) {
newsize = 4 * cur;
} else {
@@ -190,18 +193,16 @@ out:
* size: Number of pages in that read
* Together, these form the "current window".
* Together, start and size represent the `readahead window'.
- * next_size: The number of pages to read on the next readahead miss.
- * Has the magical value -1UL if readahead has been disabled.
* prev_page: The page which the readahead algorithm most-recently inspected.
- * prev_page is mainly an optimisation: if page_cache_readahead
- * sees that it is again being called for a page which it just
- * looked at, it can return immediately without making any state
- * changes.
+ * It is mainly used to detect sequential file reading.
+ * If page_cache_readahead sees that it is again being called for
+ * a page which it just looked at, it can return immediately without
+ * making any state changes.
* ahead_start,
* ahead_size: Together, these form the "ahead window".
* ra_pages: The externally controlled max readahead for this fd.
*
- * When readahead is in the off state (size == -1UL), readahead is disabled.
+ * When readahead is in the off state (size == 0), readahead is disabled.
* In this state, prev_page is used to detect the resumption of sequential I/O.
*
* The readahead code manages two windows - the "current" and the "ahead"
@@ -222,7 +223,7 @@ out:
* ahead window.
*
* A `readahead hit' occurs when a read request is made against a page which is
- * the next sequential page. Ahead windowe calculations are done only when it
+ * the next sequential page. Ahead window calculations are done only when it
* is time to submit a new IO. The code ramps up the size agressively at first,
* but slow down as it approaches max_readhead.
*
@@ -233,12 +234,9 @@ out:
* read happens to be the first page of the file, it is assumed that a linear
* read is about to happen and the window is immediately set to the initial size
* based on I/O request size and the max_readahead.
- *
- * A page request at (start + size) is not a miss at all - it's just a part of
- * sequential file reading.
*
* This function is to be called for every read request, rather than when
- * it is time to perform readahead. It is called only oce for the entire I/O
+ * it is time to perform readahead. It is called only once for the entire I/O
* regardless of size unless readahead is unable to start enough I/O to satisfy
* the request (I/O request > max_readahead).
*/
@@ -274,7 +272,7 @@ __do_page_cache_readahead(struct address_space *mapping, struct file *filp,
/*
* Preallocate as many pages as we will need.
*/
- spin_lock_irq(&mapping->tree_lock);
+ read_lock_irq(&mapping->tree_lock);
for (page_idx = 0; page_idx < nr_to_read; page_idx++) {
unsigned long page_offset = offset + page_idx;
@@ -285,16 +283,16 @@ __do_page_cache_readahead(struct address_space *mapping, struct file *filp,
if (page)
continue;
- spin_unlock_irq(&mapping->tree_lock);
+ read_unlock_irq(&mapping->tree_lock);
page = page_cache_alloc_cold(mapping);
- spin_lock_irq(&mapping->tree_lock);
+ read_lock_irq(&mapping->tree_lock);
if (!page)
break;
page->index = page_offset;
list_add(&page->lru, &page_pool);
ret++;
}
- spin_unlock_irq(&mapping->tree_lock);
+ read_unlock_irq(&mapping->tree_lock);
/*
* Now start the IO. We ignore I/O errors - if the page is not
@@ -346,8 +344,8 @@ int force_page_cache_readahead(struct address_space *mapping, struct file *filp,
* readahead isn't helping.
*
*/
-int check_ra_success(struct file_ra_state *ra, unsigned long nr_to_read,
- unsigned long actual)
+static inline int check_ra_success(struct file_ra_state *ra,
+ unsigned long nr_to_read, unsigned long actual)
{
if (actual == 0) {
ra->cache_hit += nr_to_read;
@@ -392,18 +390,46 @@ blockable_page_cache_readahead(struct address_space *mapping, struct file *filp,
{
int actual;
- if (block) {
- actual = __do_page_cache_readahead(mapping, filp,
- offset, nr_to_read);
- } else {
- actual = do_page_cache_readahead(mapping, filp,
- offset, nr_to_read);
- if (actual == -1)
- return 0;
- }
+ if (!block && bdi_read_congested(mapping->backing_dev_info))
+ return 0;
+
+ actual = __do_page_cache_readahead(mapping, filp, offset, nr_to_read);
+
return check_ra_success(ra, nr_to_read, actual);
}
+static int make_ahead_window(struct address_space *mapping, struct file *filp,
+ struct file_ra_state *ra, int force)
+{
+ int block, ret;
+
+ ra->ahead_size = get_next_ra_size(ra);
+ ra->ahead_start = ra->start + ra->size;
+
+ block = force || (ra->prev_page >= ra->ahead_start);
+ ret = blockable_page_cache_readahead(mapping, filp,
+ ra->ahead_start, ra->ahead_size, ra, block);
+
+ if (!ret && !force) {
+ /* A read failure in blocking mode, implies pages are
+ * all cached. So we can safely assume we have taken
+ * care of all the pages requested in this call.
+ * A read failure in non-blocking mode, implies we are
+ * reading more pages than requested in this call. So
+ * we safely assume we have taken care of all the pages
+ * requested in this call.
+ *
+ * Just reset the ahead window in case we failed due to
+ * congestion. The ahead window will any way be closed
+ * in case we failed due to excessive page cache hits.
+ */
+ ra->ahead_start = 0;
+ ra->ahead_size = 0;
+ }
+
+ return ret;
+}
+
/*
* page_cache_readahead is the main function. If performs the adaptive
* readahead window size management and submits the readahead I/O.
@@ -413,37 +439,35 @@ page_cache_readahead(struct address_space *mapping, struct file_ra_state *ra,
struct file *filp, unsigned long offset,
unsigned long req_size)
{
- unsigned long max, min;
- unsigned long newsize = req_size;
- unsigned long block;
+ unsigned long max, newsize;
+ int sequential;
/*
- * Here we detect the case where the application is performing
- * sub-page sized reads. We avoid doing extra work and bogusly
- * perturbing the readahead window expansion logic.
- * If size is zero, there is no read ahead window so we need one
+ * We avoid doing extra work and bogusly perturbing the readahead
+ * window expansion logic.
*/
- if (offset == ra->prev_page && req_size == 1 && ra->size != 0)
- goto out;
+ if (offset == ra->prev_page && --req_size)
+ ++offset;
+
+ /* Note that prev_page == -1 if it is a first read */
+ sequential = (offset == ra->prev_page + 1);
+ ra->prev_page = offset;
max = get_max_readahead(ra);
- min = get_min_readahead(ra);
newsize = min(req_size, max);
- if (newsize == 0 || (ra->flags & RA_FLAG_INCACHE)) {
- newsize = 1;
- ra->prev_page = offset;
- goto out; /* No readahead or file already in cache */
- }
+ /* No readahead or sub-page sized read or file already in cache */
+ if (newsize == 0 || (ra->flags & RA_FLAG_INCACHE))
+ goto out;
+
+ ra->prev_page += newsize - 1;
+
/*
- * Special case - first read. We'll assume it's a whole-file read if
- * at start of file, and grow the window fast. Or detect first
+ * Special case - first read at start of file. We'll assume it's
+ * a whole-file read and grow the window fast. Or detect first
* sequential access
*/
- if ((ra->size == 0 && offset == 0) /* first io and start of file */
- || (ra->size == -1 && ra->prev_page == offset - 1)) {
- /* First sequential */
- ra->prev_page = offset + newsize - 1;
+ if (sequential && ra->size == 0) {
ra->size = get_init_ra_size(newsize, max);
ra->start = offset;
if (!blockable_page_cache_readahead(mapping, filp, offset,
@@ -458,13 +482,9 @@ page_cache_readahead(struct address_space *mapping, struct file_ra_state *ra,
* IOs,* thus preventing stalls. so issue the ahead window
* immediately.
*/
- if (req_size >= max) {
- ra->ahead_size = get_next_ra_size(ra->size, max, min,
- &ra->flags);
- ra->ahead_start = ra->start + ra->size;
- blockable_page_cache_readahead(mapping, filp,
- ra->ahead_start, ra->ahead_size, ra, 1);
- }
+ if (req_size >= max)
+ make_ahead_window(mapping, filp, ra, 1);
+
goto out;
}
@@ -473,9 +493,8 @@ page_cache_readahead(struct address_space *mapping, struct file_ra_state *ra,
* partial page reads and first access were handled above,
* so this must be the next page otherwise it is random
*/
- if ((offset != (ra->prev_page+1) || (ra->size == 0))) {
+ if (!sequential) {
ra_off(ra);
- ra->prev_page = offset + newsize - 1;
blockable_page_cache_readahead(mapping, filp, offset,
newsize, ra, 1);
goto out;
@@ -487,28 +506,8 @@ page_cache_readahead(struct address_space *mapping, struct file_ra_state *ra,
*/
if (ra->ahead_start == 0) { /* no ahead window yet */
- ra->ahead_size = get_next_ra_size(ra->size, max, min,
- &ra->flags);
- ra->ahead_start = ra->start + ra->size;
- block = ((offset + newsize -1) >= ra->ahead_start);
- if (!blockable_page_cache_readahead(mapping, filp,
- ra->ahead_start, ra->ahead_size, ra, block)) {
- /* A read failure in blocking mode, implies pages are
- * all cached. So we can safely assume we have taken
- * care of all the pages requested in this call. A read
- * failure in non-blocking mode, implies we are reading
- * more pages than requested in this call. So we safely
- * assume we have taken care of all the pages requested
- * in this call.
- *
- * Just reset the ahead window in case we failed due to
- * congestion. The ahead window will any way be closed
- * in case we failed due to exessive page cache hits.
- */
- ra->ahead_start = 0;
- ra->ahead_size = 0;
+ if (!make_ahead_window(mapping, filp, ra, 0))
goto out;
- }
}
/*
* Already have an ahead window, check if we crossed into it.
@@ -517,35 +516,14 @@ page_cache_readahead(struct address_space *mapping, struct file_ra_state *ra,
* we get called back on the first page of the ahead window which
* will allow us to submit more IO.
*/
- if ((offset + newsize - 1) >= ra->ahead_start) {
+ if (ra->prev_page >= ra->ahead_start) {
ra->start = ra->ahead_start;
ra->size = ra->ahead_size;
- ra->ahead_start = ra->ahead_start + ra->ahead_size;
- ra->ahead_size = get_next_ra_size(ra->ahead_size,
- max, min, &ra->flags);
- block = ((offset + newsize - 1) >= ra->ahead_start);
- if (!blockable_page_cache_readahead(mapping, filp,
- ra->ahead_start, ra->ahead_size, ra, block)) {
- /* A read failure in blocking mode, implies pages are
- * all cached. So we can safely assume we have taken
- * care of all the pages requested in this call.
- * A read failure in non-blocking mode, implies we are
- * reading more pages than requested in this call. So
- * we safely assume we have taken care of all the pages
- * requested in this call.
- *
- * Just reset the ahead window in case we failed due to
- * congestion. The ahead window will any way be closed
- * in case we failed due to excessive page cache hits.
- */
- ra->ahead_start = 0;
- ra->ahead_size = 0;
- }
+ make_ahead_window(mapping, filp, ra, 0);
}
out:
- ra->prev_page = offset + newsize - 1;
- return(newsize);
+ return ra->prev_page + 1;
}
/*
diff --git a/mm/rmap.c b/mm/rmap.c
index 4ff8183fa18e9..884d6d1928bce 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -51,7 +51,6 @@
#include <linux/swapops.h>
#include <linux/slab.h>
#include <linux/init.h>
-#include <linux/acct.h>
#include <linux/rmap.h>
#include <linux/rcupdate.h>
@@ -258,7 +257,7 @@ static int page_referenced_one(struct page *page,
pte_t *pte;
int referenced = 0;
- if (!mm->rss)
+ if (!get_mm_counter(mm, rss))
goto out;
address = vma_address(page, vma);
if (address == -EFAULT)
@@ -437,7 +436,7 @@ void page_add_anon_rmap(struct page *page,
BUG_ON(PageReserved(page));
BUG_ON(!anon_vma);
- vma->vm_mm->anon_rss++;
+ inc_mm_counter(vma->vm_mm, anon_rss);
anon_vma = (void *) anon_vma + PAGE_MAPPING_ANON;
index = (address - vma->vm_start) >> PAGE_SHIFT;
@@ -510,7 +509,7 @@ static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma)
pte_t pteval;
int ret = SWAP_AGAIN;
- if (!mm->rss)
+ if (!get_mm_counter(mm, rss))
goto out;
address = vma_address(page, vma);
if (address == -EFAULT)
@@ -574,7 +573,7 @@ static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma)
}
/* Nuke the page table entry. */
- flush_cache_page(vma, address);
+ flush_cache_page(vma, address, page_to_pfn(page));
pteval = ptep_clear_flush(vma, address, pte);
/* Move the dirty bit to the physical page now the pte is gone. */
@@ -594,13 +593,12 @@ static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma)
list_add(&mm->mmlist, &init_mm.mmlist);
spin_unlock(&mmlist_lock);
}
- set_pte(pte, swp_entry_to_pte(entry));
+ set_pte_at(mm, address, pte, swp_entry_to_pte(entry));
BUG_ON(pte_file(*pte));
- mm->anon_rss--;
+ dec_mm_counter(mm, anon_rss);
}
- mm->rss--;
- acct_update_integrals();
+ inc_mm_counter(mm, rss);
page_remove_rmap(page);
page_cache_release(page);
@@ -692,12 +690,12 @@ static void try_to_unmap_cluster(unsigned long cursor,
continue;
/* Nuke the page table entry. */
- flush_cache_page(vma, address);
+ flush_cache_page(vma, address, pfn);
pteval = ptep_clear_flush(vma, address, pte);
/* If nonlinear, store the file page offset in the pte. */
if (page->index != linear_page_index(vma, address))
- set_pte(pte, pgoff_to_pte(page->index));
+ set_pte_at(mm, address, pte, pgoff_to_pte(page->index));
/* Move the dirty bit to the physical page now the pte is gone. */
if (pte_dirty(pteval))
@@ -705,8 +703,7 @@ static void try_to_unmap_cluster(unsigned long cursor,
page_remove_rmap(page);
page_cache_release(page);
- acct_update_integrals();
- mm->rss--;
+ dec_mm_counter(mm, rss);
(*mapcount)--;
}
@@ -805,7 +802,7 @@ static int try_to_unmap_file(struct page *page)
if (vma->vm_flags & (VM_LOCKED|VM_RESERVED))
continue;
cursor = (unsigned long) vma->vm_private_data;
- while (vma->vm_mm->rss &&
+ while (get_mm_counter(vma->vm_mm, rss) &&
cursor < max_nl_cursor &&
cursor < vma->vm_end - vma->vm_start) {
try_to_unmap_cluster(cursor, &mapcount, vma);
diff --git a/mm/shmem.c b/mm/shmem.c
index c8fa573e030d9..61574b81d979f 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -184,8 +184,8 @@ static struct vm_operations_struct shmem_vm_ops;
static struct backing_dev_info shmem_backing_dev_info = {
.ra_pages = 0, /* No readahead */
- .memory_backed = 1, /* Does not contribute to dirty memory */
- .unplug_io_fn = default_unplug_io_fn,
+ .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK,
+ .unplug_io_fn = default_unplug_io_fn,
};
static LIST_HEAD(shmem_swaplist);
@@ -922,7 +922,7 @@ shmem_swapin(struct shmem_inode_info *info,swp_entry_t entry,unsigned long idx)
}
static inline struct page *
-shmem_alloc_page(unsigned long gfp,struct shmem_inode_info *info,
+shmem_alloc_page(unsigned int __nocast gfp,struct shmem_inode_info *info,
unsigned long idx)
{
return alloc_page(gfp | __GFP_ZERO);
@@ -2172,7 +2172,7 @@ static int shmem_xattr_security_set(struct inode *inode, const char *name, const
return security_inode_setsecurity(inode, name, value, size, flags);
}
-struct xattr_handler shmem_xattr_security_handler = {
+static struct xattr_handler shmem_xattr_security_handler = {
.prefix = XATTR_SECURITY_PREFIX,
.list = shmem_xattr_security_list,
.get = shmem_xattr_security_get,
diff --git a/mm/slab.c b/mm/slab.c
index 30cd4d0ced229..ec660d85ddd76 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -507,10 +507,9 @@ static int slab_break_gfp_order = BREAK_GFP_ORDER_LO;
struct cache_sizes malloc_sizes[] = {
#define CACHE(x) { .cs_size = (x) },
#include <linux/kmalloc_sizes.h>
- { 0, }
+ CACHE(ULONG_MAX)
#undef CACHE
};
-
EXPORT_SYMBOL(malloc_sizes);
/* Must match cache_sizes above. Out of line to keep cache footprint low. */
@@ -574,7 +573,7 @@ static void free_block(kmem_cache_t* cachep, void** objpp, int len);
static void enable_cpucache (kmem_cache_t *cachep);
static void cache_reap (void *unused);
-static inline void ** ac_entry(struct array_cache *ac)
+static inline void **ac_entry(struct array_cache *ac)
{
return (void**)(ac+1);
}
@@ -584,24 +583,32 @@ static inline struct array_cache *ac_data(kmem_cache_t *cachep)
return cachep->array[smp_processor_id()];
}
-static kmem_cache_t * kmem_find_general_cachep (size_t size, int gfpflags)
+static inline kmem_cache_t *kmem_find_general_cachep(size_t size, int gfpflags)
{
struct cache_sizes *csizep = malloc_sizes;
- /* This function could be moved to the header file, and
- * made inline so consumers can quickly determine what
- * cache pointer they require.
+#if DEBUG
+ /* This happens if someone tries to call
+ * kmem_cache_create(), or __kmalloc(), before
+ * the generic caches are initialized.
+ */
+ BUG_ON(csizep->cs_cachep == NULL);
+#endif
+ while (size > csizep->cs_size)
+ csizep++;
+
+ /*
+ * Really subtile: The last entry with cs->cs_size==ULONG_MAX
+ * has cs_{dma,}cachep==NULL. Thus no special case
+ * for large kmalloc calls required.
*/
- for ( ; csizep->cs_size; csizep++) {
- if (size > csizep->cs_size)
- continue;
- break;
- }
- return (gfpflags & GFP_DMA) ? csizep->cs_dmacachep : csizep->cs_cachep;
+ if (unlikely(gfpflags & GFP_DMA))
+ return csizep->cs_dmacachep;
+ return csizep->cs_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,
+static void cache_estimate(unsigned long gfporder, size_t size, size_t align,
int flags, size_t *left_over, unsigned int *num)
{
int i;
@@ -659,14 +666,17 @@ static void __devinit start_cpu_timer(int cpu)
}
}
-static struct array_cache *alloc_arraycache(int cpu, int entries, int batchcount)
+static struct array_cache *alloc_arraycache(int cpu, int entries,
+ int batchcount)
{
int memsize = sizeof(void*)*entries+sizeof(struct array_cache);
struct array_cache *nc = NULL;
if (cpu != -1) {
- nc = kmem_cache_alloc_node(kmem_find_general_cachep(memsize,
- GFP_KERNEL), cpu_to_node(cpu));
+ kmem_cache_t *cachep;
+ cachep = kmem_find_general_cachep(memsize, GFP_KERNEL);
+ if (cachep)
+ nc = kmem_cache_alloc_node(cachep, cpu_to_node(cpu));
}
if (!nc)
nc = kmalloc(memsize, GFP_KERNEL);
@@ -680,8 +690,7 @@ static struct array_cache *alloc_arraycache(int cpu, int entries, int batchcount
}
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;
@@ -794,7 +803,7 @@ void __init kmem_cache_init(void)
sizes = malloc_sizes;
names = cache_names;
- while (sizes->cs_size) {
+ while (sizes->cs_size != ULONG_MAX) {
/* For performance, all the general caches are L1 aligned.
* This should be particularly beneficial on SMP boxes, as it
* eliminates "false sharing".
@@ -886,7 +895,7 @@ __initcall(cpucache_init);
* did not request dmaable memory, we might get it, but that
* would be relatively rare and ignorable.
*/
-static void *kmem_getpages(kmem_cache_t *cachep, int flags, int nodeid)
+static void *kmem_getpages(kmem_cache_t *cachep, unsigned int __nocast flags, int nodeid)
{
struct page *page;
void *addr;
@@ -948,7 +957,8 @@ static void kmem_rcu_free(struct rcu_head *head)
#if DEBUG
#ifdef CONFIG_DEBUG_PAGEALLOC
-static void store_stackinfo(kmem_cache_t *cachep, unsigned long *addr, unsigned long caller)
+static void store_stackinfo(kmem_cache_t *cachep, unsigned long *addr,
+ unsigned long caller)
{
int size = obj_reallen(cachep);
@@ -1606,7 +1616,6 @@ int kmem_cache_shrink(kmem_cache_t *cachep)
return __cache_shrink(cachep);
}
-
EXPORT_SYMBOL(kmem_cache_shrink);
/**
@@ -1626,7 +1635,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;
@@ -1671,12 +1680,11 @@ int kmem_cache_destroy (kmem_cache_t * cachep)
return 0;
}
-
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, int local_flags)
+static struct slab* alloc_slabmgmt(kmem_cache_t *cachep,
+ void *objp, int colour_off, unsigned int __nocast local_flags)
{
struct slab *slabp;
@@ -1701,8 +1709,8 @@ static inline kmem_bufctl_t *slab_bufctl(struct slab *slabp)
return (kmem_bufctl_t *)(slabp+1);
}
-static void cache_init_objs (kmem_cache_t * cachep,
- struct slab * slabp, unsigned long ctor_flags)
+static void cache_init_objs(kmem_cache_t *cachep,
+ struct slab *slabp, unsigned long ctor_flags)
{
int i;
@@ -1747,7 +1755,7 @@ static void cache_init_objs (kmem_cache_t * cachep,
slabp->free = 0;
}
-static void kmem_flagcheck(kmem_cache_t *cachep, int flags)
+static void kmem_flagcheck(kmem_cache_t *cachep, unsigned int flags)
{
if (flags & SLAB_DMA) {
if (!(cachep->gfpflags & GFP_DMA))
@@ -1777,12 +1785,12 @@ static void set_slab_attr(kmem_cache_t *cachep, struct slab *slabp, void *objp)
* Grow (by 1) the number of slabs within a cache. This is called by
* kmem_cache_alloc() when there are no active objs left in a cache.
*/
-static int cache_grow (kmem_cache_t * cachep, int flags, int nodeid)
+static int cache_grow(kmem_cache_t *cachep, unsigned int __nocast flags, int nodeid)
{
struct slab *slabp;
void *objp;
size_t offset;
- int local_flags;
+ unsigned int local_flags;
unsigned long ctor_flags;
/* Be lazy and only check for valid flags here,
@@ -1882,7 +1890,8 @@ static void kfree_debugcheck(const void *objp)
}
}
-static void *cache_free_debugcheck (kmem_cache_t * cachep, void * objp, void *caller)
+static void *cache_free_debugcheck(kmem_cache_t *cachep, void *objp,
+ void *caller)
{
struct page *page;
unsigned int objnr;
@@ -1950,18 +1959,17 @@ static void *cache_free_debugcheck (kmem_cache_t * cachep, void * objp, void *ca
static void check_slabp(kmem_cache_t *cachep, struct slab *slabp)
{
- int i;
+ kmem_bufctl_t i;
int entries = 0;
check_spinlock_acquired(cachep);
/* Check slab's freelist to see if this obj is there. */
for (i = slabp->free; i != BUFCTL_END; i = slab_bufctl(slabp)[i]) {
entries++;
- if (entries > cachep->num || i < 0 || i >= cachep->num)
+ if (entries > cachep->num || i >= cachep->num)
goto bad;
}
if (entries != cachep->num - slabp->inuse) {
- int i;
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);
@@ -1980,7 +1988,7 @@ bad:
#define check_slabp(x,y) do { } while(0)
#endif
-static void* cache_alloc_refill(kmem_cache_t* cachep, int flags)
+static void *cache_alloc_refill(kmem_cache_t *cachep, unsigned int __nocast flags)
{
int batchcount;
struct kmem_list3 *l3;
@@ -2077,7 +2085,7 @@ alloc_done:
}
static inline void
-cache_alloc_debugcheck_before(kmem_cache_t *cachep, int flags)
+cache_alloc_debugcheck_before(kmem_cache_t *cachep, unsigned int __nocast flags)
{
might_sleep_if(flags & __GFP_WAIT);
#if DEBUG
@@ -2132,7 +2140,7 @@ cache_alloc_debugcheck_after(kmem_cache_t *cachep,
#endif
-static inline void * __cache_alloc (kmem_cache_t *cachep, int flags)
+static inline void *__cache_alloc(kmem_cache_t *cachep, unsigned int __nocast flags)
{
unsigned long save_flags;
void* objp;
@@ -2211,7 +2219,7 @@ static void free_block(kmem_cache_t *cachep, void **objpp, int nr_objects)
}
}
-static void cache_flusharray (kmem_cache_t* cachep, struct array_cache *ac)
+static void cache_flusharray(kmem_cache_t *cachep, struct array_cache *ac)
{
int batchcount;
@@ -2268,7 +2276,7 @@ free_done:
*
* Called with disabled ints.
*/
-static inline void __cache_free (kmem_cache_t *cachep, void* objp)
+static inline void __cache_free(kmem_cache_t *cachep, void *objp)
{
struct array_cache *ac = ac_data(cachep);
@@ -2294,11 +2302,10 @@ static inline void __cache_free (kmem_cache_t *cachep, void* objp)
* Allocate an object from this cache. The flags are only relevant
* if the cache has no available objects.
*/
-void * kmem_cache_alloc (kmem_cache_t *cachep, int flags)
+void *kmem_cache_alloc(kmem_cache_t *cachep, unsigned int __nocast flags)
{
return __cache_alloc(cachep, flags);
}
-
EXPORT_SYMBOL(kmem_cache_alloc);
/**
@@ -2451,26 +2458,15 @@ EXPORT_SYMBOL(kmem_cache_alloc_node);
* platforms. For example, on i386, it means that the memory must come
* from the first 16MB.
*/
-void * __kmalloc (size_t size, int flags)
+void *__kmalloc(size_t size, unsigned int __nocast flags)
{
- struct cache_sizes *csizep = malloc_sizes;
+ kmem_cache_t *cachep;
- for (; csizep->cs_size; csizep++) {
- if (size > csizep->cs_size)
- continue;
-#if DEBUG
- /* This happens if someone tries to call
- * kmem_cache_create(), or kmalloc(), before
- * the generic caches are initialized.
- */
- BUG_ON(csizep->cs_cachep == NULL);
-#endif
- return __cache_alloc(flags & GFP_DMA ?
- csizep->cs_dmacachep : csizep->cs_cachep, flags);
- }
- return NULL;
+ cachep = kmem_find_general_cachep(size, flags);
+ if (unlikely(cachep == NULL))
+ return NULL;
+ return __cache_alloc(cachep, flags);
}
-
EXPORT_SYMBOL(__kmalloc);
#ifdef CONFIG_SMP
@@ -2514,7 +2510,6 @@ unwind_oom:
kfree(pdata);
return NULL;
}
-
EXPORT_SYMBOL(__alloc_percpu);
#endif
@@ -2526,7 +2521,7 @@ EXPORT_SYMBOL(__alloc_percpu);
* Free an object which was previously allocated from this
* cache.
*/
-void kmem_cache_free (kmem_cache_t *cachep, void *objp)
+void kmem_cache_free(kmem_cache_t *cachep, void *objp)
{
unsigned long flags;
@@ -2534,7 +2529,6 @@ void kmem_cache_free (kmem_cache_t *cachep, void *objp)
__cache_free(cachep, objp);
local_irq_restore(flags);
}
-
EXPORT_SYMBOL(kmem_cache_free);
/**
@@ -2543,7 +2537,7 @@ EXPORT_SYMBOL(kmem_cache_free);
* @size: element size.
* @flags: the type of memory to allocate.
*/
-void *kcalloc(size_t n, size_t size, int flags)
+void *kcalloc(size_t n, size_t size, unsigned int __nocast flags)
{
void *ret = NULL;
@@ -2555,7 +2549,6 @@ void *kcalloc(size_t n, size_t size, int flags)
memset(ret, 0, n * size);
return ret;
}
-
EXPORT_SYMBOL(kcalloc);
/**
@@ -2565,12 +2558,12 @@ EXPORT_SYMBOL(kcalloc);
* Don't free memory not originally allocated by kmalloc()
* or you will run into trouble.
*/
-void kfree (const void *objp)
+void kfree(const void *objp)
{
kmem_cache_t *c;
unsigned long flags;
- if (!objp)
+ if (unlikely(!objp))
return;
local_irq_save(flags);
kfree_debugcheck(objp);
@@ -2578,7 +2571,6 @@ void kfree (const void *objp)
__cache_free(c, (void*)objp);
local_irq_restore(flags);
}
-
EXPORT_SYMBOL(kfree);
#ifdef CONFIG_SMP
@@ -2602,7 +2594,6 @@ free_percpu(const void *objp)
}
kfree(p);
}
-
EXPORT_SYMBOL(free_percpu);
#endif
@@ -2610,7 +2601,6 @@ unsigned int kmem_cache_size(kmem_cache_t *cachep)
{
return obj_reallen(cachep);
}
-
EXPORT_SYMBOL(kmem_cache_size);
struct ccupdate_struct {
@@ -2631,7 +2621,8 @@ static void do_ccupdate_local(void *info)
}
-static int do_tune_cpucache (kmem_cache_t* cachep, int limit, int batchcount, int shared)
+static int do_tune_cpucache(kmem_cache_t *cachep, int limit, int batchcount,
+ int shared)
{
struct ccupdate_struct new;
struct array_cache *new_shared;
@@ -2686,7 +2677,7 @@ static int do_tune_cpucache (kmem_cache_t* cachep, int limit, int batchcount, in
}
-static void enable_cpucache (kmem_cache_t *cachep)
+static void enable_cpucache(kmem_cache_t *cachep)
{
int err;
int limit, shared;
diff --git a/mm/swap_state.c b/mm/swap_state.c
index 7a8f03f211690..a063a902ed034 100644
--- a/mm/swap_state.c
+++ b/mm/swap_state.c
@@ -29,13 +29,13 @@ static struct address_space_operations swap_aops = {
};
static struct backing_dev_info swap_backing_dev_info = {
- .memory_backed = 1, /* Does not contribute to dirty memory */
+ .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK,
.unplug_io_fn = swap_unplug_io_fn,
};
struct address_space swapper_space = {
.page_tree = RADIX_TREE_INIT(GFP_ATOMIC|__GFP_NOWARN),
- .tree_lock = SPIN_LOCK_UNLOCKED,
+ .tree_lock = RW_LOCK_UNLOCKED,
.a_ops = &swap_aops,
.i_mmap_nonlinear = LIST_HEAD_INIT(swapper_space.i_mmap_nonlinear),
.backing_dev_info = &swap_backing_dev_info,
@@ -76,7 +76,7 @@ static int __add_to_swap_cache(struct page *page,
BUG_ON(PagePrivate(page));
error = radix_tree_preload(gfp_mask);
if (!error) {
- spin_lock_irq(&swapper_space.tree_lock);
+ write_lock_irq(&swapper_space.tree_lock);
error = radix_tree_insert(&swapper_space.page_tree,
entry.val, page);
if (!error) {
@@ -87,7 +87,7 @@ static int __add_to_swap_cache(struct page *page,
total_swapcache_pages++;
pagecache_acct(1);
}
- spin_unlock_irq(&swapper_space.tree_lock);
+ write_unlock_irq(&swapper_space.tree_lock);
radix_tree_preload_end();
}
return error;
@@ -214,9 +214,9 @@ void delete_from_swap_cache(struct page *page)
entry.val = page->private;
- spin_lock_irq(&swapper_space.tree_lock);
+ write_lock_irq(&swapper_space.tree_lock);
__delete_from_swap_cache(page);
- spin_unlock_irq(&swapper_space.tree_lock);
+ write_unlock_irq(&swapper_space.tree_lock);
swap_free(entry);
page_cache_release(page);
@@ -315,13 +315,11 @@ struct page * lookup_swap_cache(swp_entry_t entry)
{
struct page *page;
- spin_lock_irq(&swapper_space.tree_lock);
- page = radix_tree_lookup(&swapper_space.page_tree, entry.val);
- if (page) {
- page_cache_get(page);
+ page = find_get_page(&swapper_space, entry.val);
+
+ if (page)
INC_CACHE_INFO(find_success);
- }
- spin_unlock_irq(&swapper_space.tree_lock);
+
INC_CACHE_INFO(find_total);
return page;
}
@@ -344,12 +342,7 @@ struct page *read_swap_cache_async(swp_entry_t entry,
* called after lookup_swap_cache() failed, re-calling
* that would confuse statistics.
*/
- spin_lock_irq(&swapper_space.tree_lock);
- found_page = radix_tree_lookup(&swapper_space.page_tree,
- entry.val);
- if (found_page)
- page_cache_get(found_page);
- spin_unlock_irq(&swapper_space.tree_lock);
+ found_page = find_get_page(&swapper_space, entry.val);
if (found_page)
break;
diff --git a/mm/swapfile.c b/mm/swapfile.c
index 547ecd9c060d5..a60e0075d55bd 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -24,7 +24,6 @@
#include <linux/module.h>
#include <linux/rmap.h>
#include <linux/security.h>
-#include <linux/acct.h>
#include <linux/backing-dev.h>
#include <linux/syscalls.h>
@@ -292,10 +291,10 @@ static int exclusive_swap_page(struct page *page)
/* Is the only swap cache user the cache itself? */
if (p->swap_map[swp_offset(entry)] == 1) {
/* Recheck the page count with the swapcache lock held.. */
- spin_lock_irq(&swapper_space.tree_lock);
+ write_lock_irq(&swapper_space.tree_lock);
if (page_count(page) == 2)
retval = 1;
- spin_unlock_irq(&swapper_space.tree_lock);
+ write_unlock_irq(&swapper_space.tree_lock);
}
swap_info_put(p);
}
@@ -363,13 +362,13 @@ int remove_exclusive_swap_page(struct page *page)
retval = 0;
if (p->swap_map[swp_offset(entry)] == 1) {
/* Recheck the page count with the swapcache lock held.. */
- spin_lock_irq(&swapper_space.tree_lock);
+ write_lock_irq(&swapper_space.tree_lock);
if ((page_count(page) == 2) && !PageWriteback(page)) {
__delete_from_swap_cache(page);
SetPageDirty(page);
retval = 1;
}
- spin_unlock_irq(&swapper_space.tree_lock);
+ write_unlock_irq(&swapper_space.tree_lock);
}
swap_info_put(p);
@@ -392,14 +391,8 @@ void free_swap_and_cache(swp_entry_t entry)
p = swap_info_get(entry);
if (p) {
- if (swap_entry_free(p, swp_offset(entry)) == 1) {
- spin_lock_irq(&swapper_space.tree_lock);
- page = radix_tree_lookup(&swapper_space.page_tree,
- entry.val);
- if (page && TestSetPageLocked(page))
- page = NULL;
- spin_unlock_irq(&swapper_space.tree_lock);
- }
+ if (swap_entry_free(p, swp_offset(entry)) == 1)
+ page = find_trylock_page(&swapper_space, entry.val);
swap_info_put(p);
}
if (page) {
@@ -419,170 +412,121 @@ void free_swap_and_cache(swp_entry_t entry)
}
/*
- * The swap entry has been read in advance, and we return 1 to indicate
- * that the page has been used or is no longer needed.
- *
* Always set the resulting pte to be nowrite (the same as COW pages
* after one process has exited). We don't know just how many PTEs will
* share this swap entry, so be cautious and let do_wp_page work out
* what to do if a write is requested later.
+ *
+ * vma->vm_mm->page_table_lock is held.
*/
-/* vma->vm_mm->page_table_lock is held */
-static void
-unuse_pte(struct vm_area_struct *vma, unsigned long address, pte_t *dir,
- swp_entry_t entry, struct page *page)
+static void unuse_pte(struct vm_area_struct *vma, pte_t *pte,
+ unsigned long addr, swp_entry_t entry, struct page *page)
{
- vma->vm_mm->rss++;
+ inc_mm_counter(vma->vm_mm, rss);
get_page(page);
- set_pte(dir, pte_mkold(mk_pte(page, vma->vm_page_prot)));
- page_add_anon_rmap(page, vma, address);
+ set_pte_at(vma->vm_mm, addr, pte,
+ pte_mkold(mk_pte(page, vma->vm_page_prot)));
+ page_add_anon_rmap(page, vma, addr);
swap_free(entry);
- acct_update_integrals();
- update_mem_hiwater();
+ /*
+ * Move the page to the active list so it is not
+ * immediately swapped out again after swapon.
+ */
+ activate_page(page);
}
-/* vma->vm_mm->page_table_lock is held */
-static unsigned long unuse_pmd(struct vm_area_struct *vma, pmd_t *dir,
- unsigned long address, unsigned long end,
- swp_entry_t entry, struct page *page)
+static int unuse_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
+ unsigned long addr, unsigned long end,
+ swp_entry_t entry, struct page *page)
{
pte_t *pte;
pte_t swp_pte = swp_entry_to_pte(entry);
- if (pmd_none(*dir))
- return 0;
- if (pmd_bad(*dir)) {
- pmd_ERROR(*dir);
- pmd_clear(dir);
- return 0;
- }
- pte = pte_offset_map(dir, address);
+ pte = pte_offset_map(pmd, addr);
do {
/*
* swapoff spends a _lot_ of time in this loop!
* Test inline before going to call unuse_pte.
*/
if (unlikely(pte_same(*pte, swp_pte))) {
- unuse_pte(vma, address, pte, entry, page);
+ unuse_pte(vma, pte, addr, entry, page);
pte_unmap(pte);
-
- /*
- * Move the page to the active list so it is not
- * immediately swapped out again after swapon.
- */
- activate_page(page);
-
- /* add 1 since address may be 0 */
- return 1 + address;
+ return 1;
}
- address += PAGE_SIZE;
- pte++;
- } while (address < end);
+ } while (pte++, addr += PAGE_SIZE, addr != end);
pte_unmap(pte - 1);
return 0;
}
-/* vma->vm_mm->page_table_lock is held */
-static unsigned long unuse_pud(struct vm_area_struct *vma, pud_t *pud,
- unsigned long address, unsigned long end,
- swp_entry_t entry, struct page *page)
+static inline int unuse_pmd_range(struct vm_area_struct *vma, pud_t *pud,
+ unsigned long addr, unsigned long end,
+ swp_entry_t entry, struct page *page)
{
pmd_t *pmd;
unsigned long next;
- unsigned long foundaddr;
- if (pud_none(*pud))
- return 0;
- if (pud_bad(*pud)) {
- pud_ERROR(*pud);
- pud_clear(pud);
- return 0;
- }
- pmd = pmd_offset(pud, address);
+ pmd = pmd_offset(pud, addr);
do {
- next = (address + PMD_SIZE) & PMD_MASK;
- if (next > end || !next)
- next = end;
- foundaddr = unuse_pmd(vma, pmd, address, next, entry, page);
- if (foundaddr)
- return foundaddr;
- address = next;
- pmd++;
- } while (address < end);
+ next = pmd_addr_end(addr, end);
+ if (pmd_none_or_clear_bad(pmd))
+ continue;
+ if (unuse_pte_range(vma, pmd, addr, next, entry, page))
+ return 1;
+ } while (pmd++, addr = next, addr != end);
return 0;
}
-/* vma->vm_mm->page_table_lock is held */
-static unsigned long unuse_pgd(struct vm_area_struct *vma, pgd_t *pgd,
- unsigned long address, unsigned long end,
- swp_entry_t entry, struct page *page)
+static inline int unuse_pud_range(struct vm_area_struct *vma, pgd_t *pgd,
+ unsigned long addr, unsigned long end,
+ swp_entry_t entry, struct page *page)
{
pud_t *pud;
unsigned long next;
- unsigned long foundaddr;
- if (pgd_none(*pgd))
- return 0;
- if (pgd_bad(*pgd)) {
- pgd_ERROR(*pgd);
- pgd_clear(pgd);
- return 0;
- }
- pud = pud_offset(pgd, address);
+ pud = pud_offset(pgd, addr);
do {
- next = (address + PUD_SIZE) & PUD_MASK;
- if (next > end || !next)
- next = end;
- foundaddr = unuse_pud(vma, pud, address, next, entry, page);
- if (foundaddr)
- return foundaddr;
- address = next;
- pud++;
- } while (address < end);
+ next = pud_addr_end(addr, end);
+ if (pud_none_or_clear_bad(pud))
+ continue;
+ if (unuse_pmd_range(vma, pud, addr, next, entry, page))
+ return 1;
+ } while (pud++, addr = next, addr != end);
return 0;
}
-/* vma->vm_mm->page_table_lock is held */
-static unsigned long unuse_vma(struct vm_area_struct *vma,
- swp_entry_t entry, struct page *page)
+static int unuse_vma(struct vm_area_struct *vma,
+ swp_entry_t entry, struct page *page)
{
pgd_t *pgd;
- unsigned long address, next, end;
- unsigned long foundaddr;
+ unsigned long addr, end, next;
if (page->mapping) {
- address = page_address_in_vma(page, vma);
- if (address == -EFAULT)
+ addr = page_address_in_vma(page, vma);
+ if (addr == -EFAULT)
return 0;
else
- end = address + PAGE_SIZE;
+ end = addr + PAGE_SIZE;
} else {
- address = vma->vm_start;
+ addr = vma->vm_start;
end = vma->vm_end;
}
- pgd = pgd_offset(vma->vm_mm, address);
+
+ pgd = pgd_offset(vma->vm_mm, addr);
do {
- next = (address + PGDIR_SIZE) & PGDIR_MASK;
- if (next > end || !next)
- next = end;
- foundaddr = unuse_pgd(vma, pgd, address, next, entry, page);
- if (foundaddr)
- return foundaddr;
- address = next;
- pgd++;
- } while (address < end);
+ next = pgd_addr_end(addr, end);
+ if (pgd_none_or_clear_bad(pgd))
+ continue;
+ if (unuse_pud_range(vma, pgd, addr, next, entry, page))
+ return 1;
+ } while (pgd++, addr = next, addr != end);
return 0;
}
-static int unuse_process(struct mm_struct * mm,
- swp_entry_t entry, struct page* page)
+static int unuse_mm(struct mm_struct *mm,
+ swp_entry_t entry, struct page *page)
{
- struct vm_area_struct* vma;
- unsigned long foundaddr = 0;
+ struct vm_area_struct *vma;
- /*
- * Go through process' page directory.
- */
if (!down_read_trylock(&mm->mmap_sem)) {
/*
* Our reference to the page stops try_to_unmap_one from
@@ -594,16 +538,13 @@ static int unuse_process(struct mm_struct * mm,
}
spin_lock(&mm->page_table_lock);
for (vma = mm->mmap; vma; vma = vma->vm_next) {
- if (vma->anon_vma) {
- foundaddr = unuse_vma(vma, entry, page);
- if (foundaddr)
- break;
- }
+ if (vma->anon_vma && unuse_vma(vma, entry, page))
+ break;
}
spin_unlock(&mm->page_table_lock);
up_read(&mm->mmap_sem);
/*
- * Currently unuse_process cannot fail, but leave error handling
+ * Currently unuse_mm cannot fail, but leave error handling
* at call sites for now, since we change it from time to time.
*/
return 0;
@@ -747,7 +688,7 @@ static int try_to_unuse(unsigned int type)
if (start_mm == &init_mm)
shmem = shmem_unuse(entry, page);
else
- retval = unuse_process(start_mm, entry, page);
+ retval = unuse_mm(start_mm, entry, page);
}
if (*swap_map > 1) {
int set_start_mm = (*swap_map >= swcount);
@@ -779,7 +720,7 @@ static int try_to_unuse(unsigned int type)
set_start_mm = 1;
shmem = shmem_unuse(entry, page);
} else
- retval = unuse_process(mm, entry, page);
+ retval = unuse_mm(mm, entry, page);
if (set_start_mm && *swap_map < swcount) {
mmput(new_start_mm);
atomic_inc(&mm->mm_users);
diff --git a/mm/thrash.c b/mm/thrash.c
index 735a91baa6ff3..11461f7ad8302 100644
--- a/mm/thrash.c
+++ b/mm/thrash.c
@@ -15,7 +15,7 @@
static DEFINE_SPINLOCK(swap_token_lock);
static unsigned long swap_token_timeout;
-unsigned long swap_token_check;
+static unsigned long swap_token_check;
struct mm_struct * swap_token_mm = &init_mm;
#define SWAP_TOKEN_CHECK_INTERVAL (HZ * 2)
diff --git a/mm/truncate.c b/mm/truncate.c
index 9645008bd2f6b..c9a63f0b69a2b 100644
--- a/mm/truncate.c
+++ b/mm/truncate.c
@@ -76,15 +76,15 @@ invalidate_complete_page(struct address_space *mapping, struct page *page)
if (PagePrivate(page) && !try_to_release_page(page, 0))
return 0;
- spin_lock_irq(&mapping->tree_lock);
+ write_lock_irq(&mapping->tree_lock);
if (PageDirty(page)) {
- spin_unlock_irq(&mapping->tree_lock);
+ write_unlock_irq(&mapping->tree_lock);
return 0;
}
BUG_ON(PagePrivate(page));
__remove_from_page_cache(page);
- spin_unlock_irq(&mapping->tree_lock);
+ write_unlock_irq(&mapping->tree_lock);
ClearPageUptodate(page);
page_cache_release(page); /* pagecache ref */
return 1;
@@ -241,54 +241,68 @@ unsigned long invalidate_inode_pages(struct address_space *mapping)
EXPORT_SYMBOL(invalidate_inode_pages);
/**
- * invalidate_inode_pages2 - remove all pages from an address_space
+ * invalidate_inode_pages2_range - remove range of pages from an address_space
* @mapping - the address_space
+ * @start: the page offset 'from' which to invalidate
+ * @end: the page offset 'to' which to invalidate (inclusive)
*
* Any pages which are found to be mapped into pagetables are unmapped prior to
* invalidation.
*
* Returns -EIO if any pages could not be invalidated.
*/
-int invalidate_inode_pages2(struct address_space *mapping)
+int invalidate_inode_pages2_range(struct address_space *mapping,
+ pgoff_t start, pgoff_t end)
{
struct pagevec pvec;
- pgoff_t next = 0;
+ pgoff_t next;
int i;
int ret = 0;
- int did_full_unmap = 0;
+ int did_range_unmap = 0;
+ int wrapped = 0;
pagevec_init(&pvec, 0);
- while (!ret && pagevec_lookup(&pvec, mapping, next, PAGEVEC_SIZE)) {
+ next = start;
+ while (next <= end && !ret && !wrapped &&
+ pagevec_lookup(&pvec, mapping, next,
+ min(end - next, (pgoff_t)PAGEVEC_SIZE - 1) + 1)) {
for (i = 0; !ret && i < pagevec_count(&pvec); i++) {
struct page *page = pvec.pages[i];
+ pgoff_t page_index;
int was_dirty;
lock_page(page);
- if (page->mapping != mapping) { /* truncate race? */
+ if (page->mapping != mapping) {
unlock_page(page);
continue;
}
+ page_index = page->index;
+ next = page_index + 1;
+ if (next == 0)
+ wrapped = 1;
+ if (page_index > end) {
+ unlock_page(page);
+ break;
+ }
wait_on_page_writeback(page);
- next = page->index + 1;
while (page_mapped(page)) {
- if (!did_full_unmap) {
+ if (!did_range_unmap) {
/*
* Zap the rest of the file in one hit.
- * FIXME: invalidate_inode_pages2()
- * should take start/end offsets.
*/
unmap_mapping_range(mapping,
- page->index << PAGE_CACHE_SHIFT,
- -1, 0);
- did_full_unmap = 1;
+ page_index << PAGE_CACHE_SHIFT,
+ (end - page_index + 1)
+ << PAGE_CACHE_SHIFT,
+ 0);
+ did_range_unmap = 1;
} else {
/*
* Just zap this page
*/
unmap_mapping_range(mapping,
- page->index << PAGE_CACHE_SHIFT,
- (page->index << PAGE_CACHE_SHIFT)+1,
- 0);
+ page_index << PAGE_CACHE_SHIFT,
+ PAGE_CACHE_SIZE, 0);
}
}
was_dirty = test_clear_page_dirty(page);
@@ -304,4 +318,19 @@ int invalidate_inode_pages2(struct address_space *mapping)
}
return ret;
}
+EXPORT_SYMBOL_GPL(invalidate_inode_pages2_range);
+
+/**
+ * invalidate_inode_pages2 - remove all pages from an address_space
+ * @mapping - the address_space
+ *
+ * Any pages which are found to be mapped into pagetables are unmapped prior to
+ * invalidation.
+ *
+ * Returns -EIO if any pages could not be invalidated.
+ */
+int invalidate_inode_pages2(struct address_space *mapping)
+{
+ return invalidate_inode_pages2_range(mapping, 0, -1);
+}
EXPORT_SYMBOL_GPL(invalidate_inode_pages2);
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index e6516c208d623..c6182f6f13058 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -23,210 +23,136 @@
DEFINE_RWLOCK(vmlist_lock);
struct vm_struct *vmlist;
-static void unmap_area_pte(pmd_t *pmd, unsigned long address,
- unsigned long size)
+static void vunmap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end)
{
- unsigned long end;
pte_t *pte;
- if (pmd_none(*pmd))
- return;
- if (pmd_bad(*pmd)) {
- pmd_ERROR(*pmd);
- pmd_clear(pmd);
- return;
- }
-
- pte = pte_offset_kernel(pmd, address);
- address &= ~PMD_MASK;
- end = address + size;
- if (end > PMD_SIZE)
- end = PMD_SIZE;
-
+ pte = pte_offset_kernel(pmd, addr);
do {
- pte_t page;
- page = ptep_get_and_clear(pte);
- address += PAGE_SIZE;
- pte++;
- if (pte_none(page))
- continue;
- if (pte_present(page))
- continue;
- printk(KERN_CRIT "Whee.. Swapped out page in kernel page table\n");
- } while (address < end);
+ pte_t ptent = ptep_get_and_clear(&init_mm, addr, pte);
+ WARN_ON(!pte_none(ptent) && !pte_present(ptent));
+ } while (pte++, addr += PAGE_SIZE, addr != end);
}
-static void unmap_area_pmd(pud_t *pud, unsigned long address,
- unsigned long size)
+static inline void vunmap_pmd_range(pud_t *pud, unsigned long addr,
+ unsigned long end)
{
- unsigned long end;
pmd_t *pmd;
+ unsigned long next;
- if (pud_none(*pud))
- return;
- if (pud_bad(*pud)) {
- pud_ERROR(*pud);
- pud_clear(pud);
- return;
- }
-
- pmd = pmd_offset(pud, address);
- address &= ~PUD_MASK;
- end = address + size;
- if (end > PUD_SIZE)
- end = PUD_SIZE;
-
+ pmd = pmd_offset(pud, addr);
do {
- unmap_area_pte(pmd, address, end - address);
- address = (address + PMD_SIZE) & PMD_MASK;
- pmd++;
- } while (address < end);
+ next = pmd_addr_end(addr, end);
+ if (pmd_none_or_clear_bad(pmd))
+ continue;
+ vunmap_pte_range(pmd, addr, next);
+ } while (pmd++, addr = next, addr != end);
}
-static void unmap_area_pud(pgd_t *pgd, unsigned long address,
- unsigned long size)
+static inline void vunmap_pud_range(pgd_t *pgd, unsigned long addr,
+ unsigned long end)
{
pud_t *pud;
- unsigned long end;
+ unsigned long next;
- if (pgd_none(*pgd))
- return;
- if (pgd_bad(*pgd)) {
- pgd_ERROR(*pgd);
- pgd_clear(pgd);
- return;
- }
+ pud = pud_offset(pgd, addr);
+ do {
+ next = pud_addr_end(addr, end);
+ if (pud_none_or_clear_bad(pud))
+ continue;
+ vunmap_pmd_range(pud, addr, next);
+ } while (pud++, addr = next, addr != end);
+}
- pud = pud_offset(pgd, address);
- address &= ~PGDIR_MASK;
- end = address + size;
- if (end > PGDIR_SIZE)
- end = PGDIR_SIZE;
+void unmap_vm_area(struct vm_struct *area)
+{
+ pgd_t *pgd;
+ unsigned long next;
+ unsigned long addr = (unsigned long) area->addr;
+ unsigned long end = addr + area->size;
+ BUG_ON(addr >= end);
+ pgd = pgd_offset_k(addr);
+ flush_cache_vunmap(addr, end);
do {
- unmap_area_pmd(pud, address, end - address);
- address = (address + PUD_SIZE) & PUD_MASK;
- pud++;
- } while (address && (address < end));
+ next = pgd_addr_end(addr, end);
+ if (pgd_none_or_clear_bad(pgd))
+ continue;
+ vunmap_pud_range(pgd, addr, next);
+ } while (pgd++, addr = next, addr != end);
+ flush_tlb_kernel_range((unsigned long) area->addr, end);
}
-static int map_area_pte(pte_t *pte, unsigned long address,
- unsigned long size, pgprot_t prot,
- struct page ***pages)
+static int vmap_pte_range(pmd_t *pmd, unsigned long addr,
+ unsigned long end, pgprot_t prot, struct page ***pages)
{
- unsigned long end;
-
- address &= ~PMD_MASK;
- end = address + size;
- if (end > PMD_SIZE)
- end = PMD_SIZE;
+ pte_t *pte;
+ pte = pte_alloc_kernel(&init_mm, pmd, addr);
+ if (!pte)
+ return -ENOMEM;
do {
struct page *page = **pages;
WARN_ON(!pte_none(*pte));
if (!page)
return -ENOMEM;
-
- set_pte(pte, mk_pte(page, prot));
- address += PAGE_SIZE;
- pte++;
+ set_pte_at(&init_mm, addr, pte, mk_pte(page, prot));
(*pages)++;
- } while (address < end);
+ } while (pte++, addr += PAGE_SIZE, addr != end);
return 0;
}
-static int map_area_pmd(pmd_t *pmd, unsigned long address,
- unsigned long size, pgprot_t prot,
- struct page ***pages)
+static inline int vmap_pmd_range(pud_t *pud, unsigned long addr,
+ unsigned long end, pgprot_t prot, struct page ***pages)
{
- unsigned long base, end;
-
- base = address & PUD_MASK;
- address &= ~PUD_MASK;
- end = address + size;
- if (end > PUD_SIZE)
- end = PUD_SIZE;
+ pmd_t *pmd;
+ unsigned long next;
+ pmd = pmd_alloc(&init_mm, pud, addr);
+ if (!pmd)
+ return -ENOMEM;
do {
- pte_t * pte = pte_alloc_kernel(&init_mm, pmd, base + address);
- if (!pte)
+ next = pmd_addr_end(addr, end);
+ if (vmap_pte_range(pmd, addr, next, prot, pages))
return -ENOMEM;
- if (map_area_pte(pte, address, end - address, prot, pages))
- return -ENOMEM;
- address = (address + PMD_SIZE) & PMD_MASK;
- pmd++;
- } while (address < end);
-
+ } while (pmd++, addr = next, addr != end);
return 0;
}
-static int map_area_pud(pud_t *pud, unsigned long address,
- unsigned long end, pgprot_t prot,
- struct page ***pages)
+static inline int vmap_pud_range(pgd_t *pgd, unsigned long addr,
+ unsigned long end, pgprot_t prot, struct page ***pages)
{
+ pud_t *pud;
+ unsigned long next;
+
+ pud = pud_alloc(&init_mm, pgd, addr);
+ if (!pud)
+ return -ENOMEM;
do {
- pmd_t *pmd = pmd_alloc(&init_mm, pud, address);
- if (!pmd)
- return -ENOMEM;
- if (map_area_pmd(pmd, address, end - address, prot, pages))
+ next = pud_addr_end(addr, end);
+ if (vmap_pmd_range(pud, addr, next, prot, pages))
return -ENOMEM;
- address = (address + PUD_SIZE) & PUD_MASK;
- pud++;
- } while (address && address < end);
-
+ } while (pud++, addr = next, addr != end);
return 0;
}
-void unmap_vm_area(struct vm_struct *area)
-{
- unsigned long address = (unsigned long) area->addr;
- unsigned long end = (address + area->size);
- unsigned long next;
- pgd_t *pgd;
- int i;
-
- pgd = pgd_offset_k(address);
- flush_cache_vunmap(address, end);
- for (i = pgd_index(address); i <= pgd_index(end-1); i++) {
- next = (address + PGDIR_SIZE) & PGDIR_MASK;
- if (next <= address || next > end)
- next = end;
- unmap_area_pud(pgd, address, next - address);
- address = next;
- pgd++;
- }
- flush_tlb_kernel_range((unsigned long) area->addr, end);
-}
-
int map_vm_area(struct vm_struct *area, pgprot_t prot, struct page ***pages)
{
- unsigned long address = (unsigned long) area->addr;
- unsigned long end = address + (area->size-PAGE_SIZE);
- unsigned long next;
pgd_t *pgd;
- int err = 0;
- int i;
+ unsigned long next;
+ unsigned long addr = (unsigned long) area->addr;
+ unsigned long end = addr + area->size - PAGE_SIZE;
+ int err;
- pgd = pgd_offset_k(address);
+ BUG_ON(addr >= end);
+ pgd = pgd_offset_k(addr);
spin_lock(&init_mm.page_table_lock);
- for (i = pgd_index(address); i <= pgd_index(end-1); i++) {
- pud_t *pud = pud_alloc(&init_mm, pgd, address);
- if (!pud) {
- err = -ENOMEM;
- break;
- }
- next = (address + PGDIR_SIZE) & PGDIR_MASK;
- if (next < address || next > end)
- next = end;
- if (map_area_pud(pud, address, next, prot, pages)) {
- err = -ENOMEM;
+ do {
+ next = pgd_addr_end(addr, end);
+ err = vmap_pud_range(pgd, addr, next, prot, pages);
+ if (err)
break;
- }
-
- address = next;
- pgd++;
- }
-
+ } while (pgd++, addr = next, addr != end);
spin_unlock(&init_mm.page_table_lock);
flush_cache_vmap((unsigned long) area->addr, end);
return err;
@@ -252,20 +178,22 @@ struct vm_struct *__get_vm_area(unsigned long size, unsigned long flags,
align = 1ul << bit;
}
addr = ALIGN(start, align);
+ size = PAGE_ALIGN(size);
area = kmalloc(sizeof(*area), GFP_KERNEL);
if (unlikely(!area))
return NULL;
- /*
- * We always allocate a guard page.
- */
- size += PAGE_SIZE;
if (unlikely(!size)) {
kfree (area);
return NULL;
}
+ /*
+ * We always allocate a guard page.
+ */
+ size += PAGE_SIZE;
+
write_lock(&vmlist_lock);
for (p = &vmlist; (tmp = *p) != NULL ;p = &tmp->next) {
if ((unsigned long)tmp->addr < addr) {
@@ -345,6 +273,11 @@ found:
unmap_vm_area(tmp);
*p = tmp->next;
write_unlock(&vmlist_lock);
+
+ /*
+ * Remove the guard page.
+ */
+ tmp->size -= PAGE_SIZE;
return tmp;
}
@@ -368,7 +301,7 @@ void __vunmap(void *addr, int deallocate_pages)
WARN_ON(1);
return;
}
-
+
if (deallocate_pages) {
int i;
@@ -456,32 +389,12 @@ void *vmap(struct page **pages, unsigned int count,
EXPORT_SYMBOL(vmap);
-/**
- * __vmalloc - allocate virtually contiguous memory
- *
- * @size: allocation size
- * @gfp_mask: flags for the page level allocator
- * @prot: protection mask for the allocated pages
- *
- * Allocate enough pages to cover @size from the page level
- * allocator with @gfp_mask flags. Map them into contiguous
- * kernel virtual space, using a pagetable protection of @prot.
- */
-void *__vmalloc(unsigned long size, int gfp_mask, pgprot_t prot)
+void *__vmalloc_area(struct vm_struct *area, unsigned int __nocast gfp_mask, pgprot_t prot)
{
- struct vm_struct *area;
struct page **pages;
unsigned int nr_pages, array_size, i;
- size = PAGE_ALIGN(size);
- if (!size || (size >> PAGE_SHIFT) > num_physpages)
- return NULL;
-
- area = get_vm_area(size, VM_ALLOC);
- if (!area)
- return NULL;
-
- nr_pages = size >> PAGE_SHIFT;
+ nr_pages = (area->size - PAGE_SIZE) >> PAGE_SHIFT;
array_size = (nr_pages * sizeof(struct page *));
area->nr_pages = nr_pages;
@@ -506,7 +419,7 @@ void *__vmalloc(unsigned long size, int gfp_mask, pgprot_t prot)
goto fail;
}
}
-
+
if (map_vm_area(area, prot, &pages))
goto fail;
return area->addr;
@@ -516,6 +429,32 @@ fail:
return NULL;
}
+/**
+ * __vmalloc - allocate virtually contiguous memory
+ *
+ * @size: allocation size
+ * @gfp_mask: flags for the page level allocator
+ * @prot: protection mask for the allocated pages
+ *
+ * Allocate enough pages to cover @size from the page level
+ * allocator with @gfp_mask flags. Map them into contiguous
+ * kernel virtual space, using a pagetable protection of @prot.
+ */
+void *__vmalloc(unsigned long size, unsigned int __nocast gfp_mask, pgprot_t prot)
+{
+ struct vm_struct *area;
+
+ size = PAGE_ALIGN(size);
+ if (!size || (size >> PAGE_SHIFT) > num_physpages)
+ return NULL;
+
+ area = get_vm_area(size, VM_ALLOC);
+ if (!area)
+ return NULL;
+
+ return __vmalloc_area(area, gfp_mask, prot);
+}
+
EXPORT_SYMBOL(__vmalloc);
/**
diff --git a/mm/vmscan.c b/mm/vmscan.c
index f8417ff769c49..4003c0518d28e 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -30,6 +30,7 @@
#include <linux/rmap.h>
#include <linux/topology.h>
#include <linux/cpu.h>
+#include <linux/cpuset.h>
#include <linux/notifier.h>
#include <linux/rwsem.h>
@@ -72,6 +73,12 @@ struct scan_control {
unsigned int gfp_mask;
int may_writepage;
+
+ /* This context's SWAP_CLUSTER_MAX. If freeing memory for
+ * suspend, we effectively ignore SWAP_CLUSTER_MAX.
+ * In this context, it doesn't matter that we scan the
+ * whole list at once. */
+ int swap_cluster_max;
};
/*
@@ -137,7 +144,7 @@ struct shrinker *set_shrinker(int seeks, shrinker_t theshrinker)
shrinker->seeks = seeks;
shrinker->nr = 0;
down_write(&shrinker_rwsem);
- list_add(&shrinker->list, &shrinker_list);
+ list_add_tail(&shrinker->list, &shrinker_list);
up_write(&shrinker_rwsem);
}
return shrinker;
@@ -306,8 +313,20 @@ static pageout_t pageout(struct page *page, struct address_space *mapping)
*/
if (!is_page_cache_freeable(page))
return PAGE_KEEP;
- if (!mapping)
+ if (!mapping) {
+ /*
+ * Some data journaling orphaned pages can have
+ * page->mapping == NULL while being dirty with clean buffers.
+ */
+ if (PageDirty(page) && PagePrivate(page)) {
+ if (try_to_free_buffers(page)) {
+ ClearPageDirty(page);
+ printk("%s: orphaned page\n", __FUNCTION__);
+ return PAGE_CLEAN;
+ }
+ }
return PAGE_KEEP;
+ }
if (mapping->a_ops->writepage == NULL)
return PAGE_ACTIVATE;
if (!may_write_to_queue(mapping->backing_dev_info))
@@ -475,7 +494,7 @@ static int shrink_list(struct list_head *page_list, struct scan_control *sc)
if (!mapping)
goto keep_locked; /* truncate got there first */
- spin_lock_irq(&mapping->tree_lock);
+ write_lock_irq(&mapping->tree_lock);
/*
* The non-racy check for busy page. It is critical to check
@@ -483,7 +502,7 @@ static int shrink_list(struct list_head *page_list, struct scan_control *sc)
* not in use by anybody. (pagecache + us == 2)
*/
if (page_count(page) != 2 || PageDirty(page)) {
- spin_unlock_irq(&mapping->tree_lock);
+ write_unlock_irq(&mapping->tree_lock);
goto keep_locked;
}
@@ -491,7 +510,7 @@ static int shrink_list(struct list_head *page_list, struct scan_control *sc)
if (PageSwapCache(page)) {
swp_entry_t swap = { .val = page->private };
__delete_from_swap_cache(page);
- spin_unlock_irq(&mapping->tree_lock);
+ write_unlock_irq(&mapping->tree_lock);
swap_free(swap);
__put_page(page); /* The pagecache ref */
goto free_it;
@@ -499,7 +518,7 @@ static int shrink_list(struct list_head *page_list, struct scan_control *sc)
#endif /* CONFIG_SWAP */
__remove_from_page_cache(page);
- spin_unlock_irq(&mapping->tree_lock);
+ write_unlock_irq(&mapping->tree_lock);
__put_page(page);
free_it:
@@ -527,14 +546,56 @@ keep:
}
/*
- * zone->lru_lock is heavily contented. We relieve it by quickly privatising
- * a batch of pages and working on them outside the lock. Any pages which were
- * not freed will be added back to the LRU.
+ * zone->lru_lock is heavily contended. Some of the functions that
+ * shrink the lists perform better by taking out a batch of pages
+ * and working on them outside the LRU lock.
*
- * shrink_cache() adds the number of pages reclaimed to sc->nr_reclaimed
+ * For pagecache intensive workloads, this function is the hottest
+ * spot in the kernel (apart from copy_*_user functions).
+ *
+ * Appropriate locks must be held before calling this function.
*
- * For pagecache intensive workloads, the first loop here is the hottest spot
- * in the kernel (apart from the copy_*_user functions).
+ * @nr_to_scan: The number of pages to look through on the list.
+ * @src: The LRU list to pull pages off.
+ * @dst: The temp list to put pages on to.
+ * @scanned: The number of pages that were scanned.
+ *
+ * returns how many pages were moved onto *@dst.
+ */
+static int isolate_lru_pages(int nr_to_scan, struct list_head *src,
+ struct list_head *dst, int *scanned)
+{
+ int nr_taken = 0;
+ struct page *page;
+ int scan = 0;
+
+ while (scan++ < nr_to_scan && !list_empty(src)) {
+ page = lru_to_page(src);
+ prefetchw_prev_lru_page(page, src, flags);
+
+ if (!TestClearPageLRU(page))
+ BUG();
+ list_del(&page->lru);
+ if (get_page_testone(page)) {
+ /*
+ * It is being freed elsewhere
+ */
+ __put_page(page);
+ SetPageLRU(page);
+ list_add(&page->lru, src);
+ continue;
+ } else {
+ list_add(&page->lru, dst);
+ nr_taken++;
+ }
+ }
+
+ *scanned = scan;
+ return nr_taken;
+}
+
+/*
+ * shrink_cache() adds the number of pages reclaimed to sc->nr_reclaimed
*/
static void shrink_cache(struct zone *zone, struct scan_control *sc)
{
@@ -548,32 +609,13 @@ static void shrink_cache(struct zone *zone, struct scan_control *sc)
spin_lock_irq(&zone->lru_lock);
while (max_scan > 0) {
struct page *page;
- int nr_taken = 0;
- int nr_scan = 0;
+ int nr_taken;
+ int nr_scan;
int nr_freed;
- while (nr_scan++ < SWAP_CLUSTER_MAX &&
- !list_empty(&zone->inactive_list)) {
- page = lru_to_page(&zone->inactive_list);
-
- prefetchw_prev_lru_page(page,
- &zone->inactive_list, flags);
-
- if (!TestClearPageLRU(page))
- BUG();
- list_del(&page->lru);
- if (get_page_testone(page)) {
- /*
- * It is being freed elsewhere
- */
- __put_page(page);
- SetPageLRU(page);
- list_add(&page->lru, &zone->inactive_list);
- continue;
- }
- list_add(&page->lru, &page_list);
- nr_taken++;
- }
+ nr_taken = isolate_lru_pages(sc->swap_cluster_max,
+ &zone->inactive_list,
+ &page_list, &nr_scan);
zone->nr_inactive -= nr_taken;
zone->pages_scanned += nr_scan;
spin_unlock_irq(&zone->lru_lock);
@@ -639,7 +681,7 @@ refill_inactive_zone(struct zone *zone, struct scan_control *sc)
{
int pgmoved;
int pgdeactivate = 0;
- int pgscanned = 0;
+ int pgscanned;
int nr_pages = sc->nr_to_scan;
LIST_HEAD(l_hold); /* The pages which were snipped off */
LIST_HEAD(l_inactive); /* Pages to go onto the inactive_list */
@@ -652,30 +694,9 @@ refill_inactive_zone(struct zone *zone, struct scan_control *sc)
long swap_tendency;
lru_add_drain();
- pgmoved = 0;
spin_lock_irq(&zone->lru_lock);
- while (pgscanned < nr_pages && !list_empty(&zone->active_list)) {
- page = lru_to_page(&zone->active_list);
- prefetchw_prev_lru_page(page, &zone->active_list, flags);
- if (!TestClearPageLRU(page))
- BUG();
- list_del(&page->lru);
- if (get_page_testone(page)) {
- /*
- * It was already free! release_pages() or put_page()
- * are about to remove it from the LRU and free it. So
- * put the refcount back and put the page back on the
- * LRU
- */
- __put_page(page);
- SetPageLRU(page);
- list_add(&page->lru, &zone->active_list);
- } else {
- list_add(&page->lru, &l_hold);
- pgmoved++;
- }
- pgscanned++;
- }
+ pgmoved = isolate_lru_pages(nr_pages, &zone->active_list,
+ &l_hold, &pgscanned);
zone->pages_scanned += pgscanned;
zone->nr_active -= pgmoved;
spin_unlock_irq(&zone->lru_lock);
@@ -797,37 +818,39 @@ shrink_zone(struct zone *zone, struct scan_control *sc)
*/
zone->nr_scan_active += (zone->nr_active >> sc->priority) + 1;
nr_active = zone->nr_scan_active;
- if (nr_active >= SWAP_CLUSTER_MAX)
+ if (nr_active >= sc->swap_cluster_max)
zone->nr_scan_active = 0;
else
nr_active = 0;
zone->nr_scan_inactive += (zone->nr_inactive >> sc->priority) + 1;
nr_inactive = zone->nr_scan_inactive;
- if (nr_inactive >= SWAP_CLUSTER_MAX)
+ if (nr_inactive >= sc->swap_cluster_max)
zone->nr_scan_inactive = 0;
else
nr_inactive = 0;
- sc->nr_to_reclaim = SWAP_CLUSTER_MAX;
+ sc->nr_to_reclaim = sc->swap_cluster_max;
while (nr_active || nr_inactive) {
if (nr_active) {
sc->nr_to_scan = min(nr_active,
- (unsigned long)SWAP_CLUSTER_MAX);
+ (unsigned long)sc->swap_cluster_max);
nr_active -= sc->nr_to_scan;
refill_inactive_zone(zone, sc);
}
if (nr_inactive) {
sc->nr_to_scan = min(nr_inactive,
- (unsigned long)SWAP_CLUSTER_MAX);
+ (unsigned long)sc->swap_cluster_max);
nr_inactive -= sc->nr_to_scan;
shrink_cache(zone, sc);
if (sc->nr_to_reclaim <= 0)
break;
}
}
+
+ throttle_vm_writeout();
}
/*
@@ -857,6 +880,9 @@ shrink_caches(struct zone **zones, struct scan_control *sc)
if (zone->present_pages == 0)
continue;
+ if (!cpuset_zone_allowed(zone))
+ continue;
+
zone->temp_priority = sc->priority;
if (zone->prev_priority > sc->priority)
zone->prev_priority = sc->priority;
@@ -900,6 +926,9 @@ int try_to_free_pages(struct zone **zones,
for (i = 0; zones[i] != NULL; i++) {
struct zone *zone = zones[i];
+ if (!cpuset_zone_allowed(zone))
+ continue;
+
zone->temp_priority = DEF_PRIORITY;
lru_pages += zone->nr_active + zone->nr_inactive;
}
@@ -909,18 +938,19 @@ int try_to_free_pages(struct zone **zones,
sc.nr_scanned = 0;
sc.nr_reclaimed = 0;
sc.priority = priority;
+ sc.swap_cluster_max = SWAP_CLUSTER_MAX;
shrink_caches(zones, &sc);
shrink_slab(sc.nr_scanned, gfp_mask, lru_pages);
if (reclaim_state) {
sc.nr_reclaimed += reclaim_state->reclaimed_slab;
reclaim_state->reclaimed_slab = 0;
}
- if (sc.nr_reclaimed >= SWAP_CLUSTER_MAX) {
+ total_scanned += sc.nr_scanned;
+ total_reclaimed += sc.nr_reclaimed;
+ if (total_reclaimed >= sc.swap_cluster_max) {
ret = 1;
goto out;
}
- total_scanned += sc.nr_scanned;
- total_reclaimed += sc.nr_reclaimed;
/*
* Try to write back as many pages as we just scanned. This
@@ -929,7 +959,7 @@ int try_to_free_pages(struct zone **zones,
* that's undesirable in laptop mode, where we *want* lumpy
* writeout. So in laptop mode, write out the whole world.
*/
- if (total_scanned > SWAP_CLUSTER_MAX + SWAP_CLUSTER_MAX/2) {
+ if (total_scanned > sc.swap_cluster_max + sc.swap_cluster_max/2) {
wakeup_bdflush(laptop_mode ? 0 : total_scanned);
sc.may_writepage = 1;
}
@@ -939,8 +969,14 @@ int try_to_free_pages(struct zone **zones,
blk_congestion_wait(WRITE, HZ/10);
}
out:
- for (i = 0; zones[i] != 0; i++)
- zones[i]->prev_priority = zones[i]->temp_priority;
+ for (i = 0; zones[i] != 0; i++) {
+ struct zone *zone = zones[i];
+
+ if (!cpuset_zone_allowed(zone))
+ continue;
+
+ zone->prev_priority = zone->temp_priority;
+ }
return ret;
}
@@ -1061,6 +1097,7 @@ scan:
sc.nr_scanned = 0;
sc.nr_reclaimed = 0;
sc.priority = priority;
+ sc.swap_cluster_max = nr_pages? nr_pages : SWAP_CLUSTER_MAX;
shrink_zone(zone, &sc);
reclaim_state->reclaimed_slab = 0;
shrink_slab(sc.nr_scanned, GFP_KERNEL, lru_pages);
@@ -1098,7 +1135,7 @@ scan:
* matches the direct reclaim path behaviour in terms of impact
* on zone->*_priority.
*/
- if (total_reclaimed >= SWAP_CLUSTER_MAX)
+ if ((total_reclaimed >= SWAP_CLUSTER_MAX) && (!nr_pages))
break;
}
out:
@@ -1200,6 +1237,8 @@ void wakeup_kswapd(struct zone *zone, int order)
return;
if (pgdat->kswapd_max_order < order)
pgdat->kswapd_max_order = order;
+ if (!cpuset_zone_allowed(zone))
+ return;
if (!waitqueue_active(&zone->zone_pgdat->kswapd_wait))
return;
wake_up_interruptible(&zone->zone_pgdat->kswapd_wait);
diff --git a/net/802/fc.c b/net/802/fc.c
index 16702377958e7..640d34e026c2e 100644
--- a/net/802/fc.c
+++ b/net/802/fc.c
@@ -97,40 +97,6 @@ static int fc_rebuild_header(struct sk_buff *skb)
#endif
}
-unsigned short
-fc_type_trans(struct sk_buff *skb, struct net_device *dev)
-{
- struct fch_hdr *fch = (struct fch_hdr *)skb->data;
- struct fcllc *fcllc;
-
- skb->mac.raw = skb->data;
- fcllc = (struct fcllc *)(skb->data + sizeof (struct fch_hdr) + 2);
- skb_pull(skb, sizeof (struct fch_hdr) + 2);
-
- if (*fch->daddr & 1) {
- if (!memcmp(fch->daddr, dev->broadcast, FC_ALEN))
- skb->pkt_type = PACKET_BROADCAST;
- else
- skb->pkt_type = PACKET_MULTICAST;
- } else if (dev->flags & IFF_PROMISC) {
- if (memcmp(fch->daddr, dev->dev_addr, FC_ALEN))
- skb->pkt_type = PACKET_OTHERHOST;
- }
-
- /*
- * Strip the SNAP header from ARP packets since we don't pass
- * them through to the 802.2/SNAP layers.
- */
- if (fcllc->dsap == EXTENDED_SAP &&
- (fcllc->ethertype == ntohs(ETH_P_IP) ||
- fcllc->ethertype == ntohs(ETH_P_ARP))) {
- skb_pull(skb, sizeof (struct fcllc));
- return fcllc->ethertype;
- }
-
- return ntohs(ETH_P_802_2);
-}
-
static void fc_setup(struct net_device *dev)
{
dev->hard_header = fc_header;
diff --git a/net/Kconfig b/net/Kconfig
index 435e535ead8c1..9251b28e8d5d0 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -45,15 +45,6 @@ config PACKET_MMAP
If unsure, say N.
-config NETLINK_DEV
- tristate "Netlink device emulation"
- help
- This option will be removed soon. Any programs that want to use
- character special nodes like /dev/tap0 or /dev/route (all with major
- number 36) need this option, and need to be rewritten soon to use
- the real netlink socket.
- This is a backward compatibility option, choose Y for now.
-
config UNIX
tristate "Unix domain sockets"
---help---
@@ -107,28 +98,24 @@ source "net/ipv4/Kconfig"
# IPv6 as module will cause a CRASH if you try to unload it
config IPV6
- tristate "The IPv6 protocol (EXPERIMENTAL)"
- depends on INET && EXPERIMENTAL
+ tristate "The IPv6 protocol"
+ depends on INET
+ default m
select CRYPTO if IPV6_PRIVACY
select CRYPTO_MD5 if IPV6_PRIVACY
---help---
- This is experimental support for the IP version 6 (formerly called
- IPng "IP next generation"). You will still be able to do
- regular IPv4 networking as well.
-
- Features of this new protocol include: expanded address space,
- authentication and privacy, and seamless interoperability with the
- current version of IP (IP version 4). For general information about
- IPv6, see <http://playground.sun.com/pub/ipng/html/ipng-main.html>;
- for specific information about IPv6 under Linux read the HOWTO at
- <http://www.bieringer.de/linux/IPv6/> and the file net/ipv6/README
- in the kernel source.
+ This is complemental support for the IP version 6.
+ You will still be able to do traditional IPv4 networking as well.
+
+ For general information about IPv6, see
+ <http://playground.sun.com/pub/ipng/html/ipng-main.html>.
+ For Linux IPv6 development information, see <http://www.linux-ipv6.org>.
+ For specific information about IPv6 under Linux, read the HOWTO at
+ <http://www.bieringer.de/linux/IPv6/>.
To compile this protocol support as a module, choose M here: the
module will be called ipv6.
- It is safe to say N here for now.
-
source "net/ipv6/Kconfig"
menuconfig NETFILTER
diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c
index 123d928183b87..8c55dbce87582 100644
--- a/net/appletalk/ddp.c
+++ b/net/appletalk/ddp.c
@@ -1022,7 +1022,6 @@ static unsigned short atalk_checksum(const struct sk_buff *skb, int len)
static int atalk_create(struct socket *sock, int protocol)
{
struct sock *sk;
- struct atalk_sock *at;
int rc = -ESOCKTNOSUPPORT;
/*
@@ -1032,25 +1031,19 @@ static int atalk_create(struct socket *sock, int protocol)
if (sock->type != SOCK_RAW && sock->type != SOCK_DGRAM)
goto out;
rc = -ENOMEM;
- sk = sk_alloc(PF_APPLETALK, GFP_KERNEL, 1, NULL);
+ sk = sk_alloc(PF_APPLETALK, GFP_KERNEL,
+ sizeof(struct atalk_sock), NULL);
if (!sk)
goto out;
- at = sk->sk_protinfo = kmalloc(sizeof(*at), GFP_KERNEL);
- if (!at)
- goto outsk;
- memset(at, 0, sizeof(*at));
rc = 0;
sock->ops = &atalk_dgram_ops;
sock_init_data(sock, sk);
sk_set_owner(sk, THIS_MODULE);
/* Checksums on by default */
- sk->sk_zapped = 1;
+ sock_set_flag(sk, SOCK_ZAPPED);
out:
return rc;
-outsk:
- sk_free(sk);
- goto out;
}
/* Free a socket. No work needed */
@@ -1127,7 +1120,7 @@ static int atalk_autobind(struct sock *sk)
n = atalk_pick_and_bind_port(sk, &sat);
if (!n)
- sk->sk_zapped = 0;
+ sock_reset_flag(sk, SOCK_ZAPPED);
out:
return n;
}
@@ -1139,7 +1132,8 @@ static int atalk_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
struct sock *sk = sock->sk;
struct atalk_sock *at = at_sk(sk);
- if (!sk->sk_zapped || addr_len != sizeof(struct sockaddr_at))
+ if (!sock_flag(sk, SOCK_ZAPPED) ||
+ addr_len != sizeof(struct sockaddr_at))
return -EINVAL;
if (addr->sat_family != AF_APPLETALK)
@@ -1174,7 +1168,7 @@ static int atalk_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
return -EADDRINUSE;
}
- sk->sk_zapped = 0;
+ sock_reset_flag(sk, SOCK_ZAPPED);
return 0;
}
@@ -1209,7 +1203,7 @@ static int atalk_connect(struct socket *sock, struct sockaddr *uaddr,
#endif
}
- if (sk->sk_zapped)
+ if (sock_flag(sk, SOCK_ZAPPED))
if (atalk_autobind(sk) < 0)
return -EBUSY;
@@ -1236,7 +1230,7 @@ static int atalk_getname(struct socket *sock, struct sockaddr *uaddr,
struct sock *sk = sock->sk;
struct atalk_sock *at = at_sk(sk);
- if (sk->sk_zapped)
+ if (sock_flag(sk, SOCK_ZAPPED))
if (atalk_autobind(sk) < 0)
return -ENOBUFS;
@@ -1558,7 +1552,7 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
return -EMSGSIZE;
if (usat) {
- if (sk->sk_zapped)
+ if (sock_flag(sk, SOCK_ZAPPED))
if (atalk_autobind(sk) < 0)
return -EBUSY;
diff --git a/net/atm/atm_misc.c b/net/atm/atm_misc.c
index d842ecd4bfd1c..b2113c3454ae6 100644
--- a/net/atm/atm_misc.c
+++ b/net/atm/atm_misc.c
@@ -16,7 +16,7 @@
int atm_charge(struct atm_vcc *vcc,int truesize)
{
atm_force_charge(vcc,truesize);
- if (atomic_read(&vcc->sk->sk_rmem_alloc) <= vcc->sk->sk_rcvbuf)
+ if (atomic_read(&sk_atm(vcc)->sk_rmem_alloc) <= sk_atm(vcc)->sk_rcvbuf)
return 1;
atm_return(vcc,truesize);
atomic_inc(&vcc->stats->rx_drop);
@@ -27,15 +27,16 @@ int atm_charge(struct atm_vcc *vcc,int truesize)
struct sk_buff *atm_alloc_charge(struct atm_vcc *vcc,int pdu_size,
int gfp_flags)
{
+ struct sock *sk = sk_atm(vcc);
int guess = atm_guess_pdu2truesize(pdu_size);
atm_force_charge(vcc,guess);
- if (atomic_read(&vcc->sk->sk_rmem_alloc) <= vcc->sk->sk_rcvbuf) {
+ if (atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf) {
struct sk_buff *skb = alloc_skb(pdu_size,gfp_flags);
if (skb) {
atomic_add(skb->truesize-guess,
- &vcc->sk->sk_rmem_alloc);
+ &sk->sk_rmem_alloc);
return skb;
}
}
diff --git a/net/atm/br2684.c b/net/atm/br2684.c
index 02b2556f194d5..e6954cf1459d1 100644
--- a/net/atm/br2684.c
+++ b/net/atm/br2684.c
@@ -190,7 +190,7 @@ static int br2684_xmit_vcc(struct sk_buff *skb, struct br2684_dev *brdev,
dev_kfree_skb(skb);
return 0;
}
- atomic_add(skb->truesize, &atmvcc->sk->sk_wmem_alloc);
+ atomic_add(skb->truesize, &sk_atm(atmvcc)->sk_wmem_alloc);
ATM_SKB(skb)->atm_options = atmvcc->atm_options;
brdev->stats.tx_packets++;
brdev->stats.tx_bytes += skb->len;
@@ -557,7 +557,7 @@ Note: we do not have explicit unassign, but look at _push()
barrier();
atmvcc->push = br2684_push;
skb_queue_head_init(&copy);
- skb_migrate(&atmvcc->sk->sk_receive_queue, &copy);
+ skb_migrate(&sk_atm(atmvcc)->sk_receive_queue, &copy);
while ((skb = skb_dequeue(&copy)) != NULL) {
BRPRIV(skb->dev)->stats.rx_bytes -= skb->len;
BRPRIV(skb->dev)->stats.rx_packets--;
diff --git a/net/atm/clip.c b/net/atm/clip.c
index 8db42d467af32..28dab55a4387c 100644
--- a/net/atm/clip.c
+++ b/net/atm/clip.c
@@ -58,6 +58,7 @@ static int start_timer = 1;
static int to_atmarpd(enum atmarp_ctrl_type type,int itf,unsigned long ip)
{
+ struct sock *sk;
struct atmarp_ctrl *ctrl;
struct sk_buff *skb;
@@ -70,8 +71,10 @@ static int to_atmarpd(enum atmarp_ctrl_type type,int itf,unsigned long ip)
ctrl->itf_num = itf;
ctrl->ip = ip;
atm_force_charge(atmarpd,skb->truesize);
- skb_queue_tail(&atmarpd->sk->sk_receive_queue, skb);
- atmarpd->sk->sk_data_ready(atmarpd->sk, skb->len);
+
+ sk = sk_atm(atmarpd);
+ skb_queue_tail(&sk->sk_receive_queue, skb);
+ sk->sk_data_ready(sk, skb->len);
return 0;
}
@@ -434,7 +437,7 @@ static int clip_start_xmit(struct sk_buff *skb,struct net_device *dev)
memcpy(here,llc_oui,sizeof(llc_oui));
((u16 *) here)[3] = skb->protocol;
}
- atomic_add(skb->truesize, &vcc->sk->sk_wmem_alloc);
+ atomic_add(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc);
ATM_SKB(skb)->atm_options = vcc->atm_options;
entry->vccs->last_use = jiffies;
DPRINTK("atm_skb(%p)->vcc(%p)->dev(%p)\n",skb,vcc,vcc->dev);
@@ -493,7 +496,7 @@ static int clip_mkip(struct atm_vcc *vcc,int timeout)
vcc->push = clip_push;
vcc->pop = clip_pop;
skb_queue_head_init(&copy);
- skb_migrate(&vcc->sk->sk_receive_queue, &copy);
+ skb_migrate(&sk_atm(vcc)->sk_receive_queue, &copy);
/* re-process everything received between connection setup and MKIP */
while ((skb = skb_dequeue(&copy)) != NULL)
if (!clip_devs) {
@@ -686,10 +689,10 @@ static void atmarpd_close(struct atm_vcc *vcc)
barrier();
unregister_inetaddr_notifier(&clip_inet_notifier);
unregister_netdevice_notifier(&clip_dev_notifier);
- if (skb_peek(&vcc->sk->sk_receive_queue))
+ if (skb_peek(&sk_atm(vcc)->sk_receive_queue))
printk(KERN_ERR "atmarpd_close: closing with requests "
"pending\n");
- skb_queue_purge(&vcc->sk->sk_receive_queue);
+ skb_queue_purge(&sk_atm(vcc)->sk_receive_queue);
DPRINTK("(done)\n");
module_put(THIS_MODULE);
}
@@ -723,7 +726,7 @@ static int atm_init_atmarp(struct atm_vcc *vcc)
set_bit(ATM_VF_READY,&vcc->flags);
/* allow replies and avoid getting closed if signaling dies */
vcc->dev = &atmarpd_dev;
- vcc_insert_socket(vcc->sk);
+ vcc_insert_socket(sk_atm(vcc));
vcc->push = NULL;
vcc->pop = NULL; /* crash */
vcc->push_oam = NULL; /* crash */
@@ -822,7 +825,7 @@ static void atmarp_info(struct seq_file *seq, struct net_device *dev,
int svc, llc, off;
svc = ((clip_vcc == SEQ_NO_VCC_TOKEN) ||
- (clip_vcc->vcc->sk->sk_family == AF_ATMSVC));
+ (sk_atm(clip_vcc->vcc)->sk_family == AF_ATMSVC));
llc = ((clip_vcc == SEQ_NO_VCC_TOKEN) ||
clip_vcc->encap);
diff --git a/net/atm/common.c b/net/atm/common.c
index 85556b1af5c0a..30a6a75325605 100644
--- a/net/atm/common.c
+++ b/net/atm/common.c
@@ -41,7 +41,7 @@
struct hlist_head vcc_hash[VCC_HTABLE_SIZE];
DEFINE_RWLOCK(vcc_sklist_lock);
-void __vcc_insert_socket(struct sock *sk)
+static void __vcc_insert_socket(struct sock *sk)
{
struct atm_vcc *vcc = atm_sk(sk);
struct hlist_head *head = &vcc_hash[vcc->vci &
@@ -68,17 +68,18 @@ static void vcc_remove_socket(struct sock *sk)
static struct sk_buff *alloc_tx(struct atm_vcc *vcc,unsigned int size)
{
struct sk_buff *skb;
+ struct sock *sk = sk_atm(vcc);
- if (atomic_read(&vcc->sk->sk_wmem_alloc) && !atm_may_send(vcc, size)) {
+ if (atomic_read(&sk->sk_wmem_alloc) && !atm_may_send(vcc, size)) {
DPRINTK("Sorry: wmem_alloc = %d, size = %d, sndbuf = %d\n",
- atomic_read(&vcc->sk->sk_wmem_alloc), size,
- vcc->sk->sk_sndbuf);
+ atomic_read(&sk->sk_wmem_alloc), size,
+ sk->sk_sndbuf);
return NULL;
}
while (!(skb = alloc_skb(size,GFP_KERNEL))) schedule();
- DPRINTK("AlTx %d += %d\n", atomic_read(&vcc->sk->sk_wmem_alloc),
+ DPRINTK("AlTx %d += %d\n", atomic_read(&sk->sk_wmem_alloc),
skb->truesize);
- atomic_add(skb->truesize, &vcc->sk->sk_wmem_alloc);
+ atomic_add(skb->truesize, &sk->sk_wmem_alloc);
return skb;
}
@@ -89,15 +90,11 @@ EXPORT_SYMBOL(vcc_insert_socket);
static void vcc_sock_destruct(struct sock *sk)
{
- struct atm_vcc *vcc = atm_sk(sk);
-
- if (atomic_read(&vcc->sk->sk_rmem_alloc))
+ if (atomic_read(&sk->sk_rmem_alloc))
printk(KERN_DEBUG "vcc_sock_destruct: rmem leakage (%d bytes) detected.\n", atomic_read(&sk->sk_rmem_alloc));
- if (atomic_read(&vcc->sk->sk_wmem_alloc))
+ if (atomic_read(&sk->sk_wmem_alloc))
printk(KERN_DEBUG "vcc_sock_destruct: wmem leakage (%d bytes) detected.\n", atomic_read(&sk->sk_wmem_alloc));
-
- kfree(sk->sk_protinfo);
}
static void vcc_def_wakeup(struct sock *sk)
@@ -139,7 +136,7 @@ int vcc_create(struct socket *sock, int protocol, int family)
sock->sk = NULL;
if (sock->type == SOCK_STREAM)
return -EINVAL;
- sk = sk_alloc(family, GFP_KERNEL, 1, NULL);
+ sk = sk_alloc(family, GFP_KERNEL, sizeof(struct atm_vcc), NULL);
if (!sk)
return -ENOMEM;
sock_init_data(sock, sk);
@@ -147,20 +144,13 @@ int vcc_create(struct socket *sock, int protocol, int family)
sk->sk_state_change = vcc_def_wakeup;
sk->sk_write_space = vcc_write_space;
- vcc = sk->sk_protinfo = kmalloc(sizeof(*vcc), GFP_KERNEL);
- if (!vcc) {
- sk_free(sk);
- return -ENOMEM;
- }
-
- memset(vcc, 0, sizeof(*vcc));
- vcc->sk = sk;
+ vcc = atm_sk(sk);
vcc->dev = NULL;
memset(&vcc->local,0,sizeof(struct sockaddr_atmsvc));
memset(&vcc->remote,0,sizeof(struct sockaddr_atmsvc));
vcc->qos.txtp.max_sdu = 1 << 16; /* for meta VCs */
- atomic_set(&vcc->sk->sk_wmem_alloc, 0);
- atomic_set(&vcc->sk->sk_rmem_alloc, 0);
+ atomic_set(&sk->sk_wmem_alloc, 0);
+ atomic_set(&sk->sk_rmem_alloc, 0);
vcc->push = NULL;
vcc->pop = NULL;
vcc->push_oam = NULL;
@@ -187,7 +177,7 @@ static void vcc_destroy_socket(struct sock *sk)
vcc_remove_socket(sk); /* no more receive */
- while ((skb = skb_dequeue(&vcc->sk->sk_receive_queue)) != NULL) {
+ while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
atm_return(vcc,skb->truesize);
kfree_skb(skb);
}
@@ -215,11 +205,13 @@ int vcc_release(struct socket *sock)
void vcc_release_async(struct atm_vcc *vcc, int reply)
{
+ struct sock *sk = sk_atm(vcc);
+
set_bit(ATM_VF_CLOSE, &vcc->flags);
- vcc->sk->sk_shutdown |= RCV_SHUTDOWN;
- vcc->sk->sk_err = -reply;
+ sk->sk_shutdown |= RCV_SHUTDOWN;
+ sk->sk_err = -reply;
clear_bit(ATM_VF_WAITING, &vcc->flags);
- vcc->sk->sk_state_change(vcc->sk);
+ sk->sk_state_change(sk);
}
@@ -328,6 +320,7 @@ static int find_ci(struct atm_vcc *vcc, short *vpi, int *vci)
static int __vcc_connect(struct atm_vcc *vcc, struct atm_dev *dev, short vpi,
int vci)
{
+ struct sock *sk = sk_atm(vcc);
int error;
if ((vpi != ATM_VPI_UNSPEC && vpi != ATM_VPI_ANY &&
@@ -347,7 +340,7 @@ static int __vcc_connect(struct atm_vcc *vcc, struct atm_dev *dev, short vpi,
}
vcc->vpi = vpi;
vcc->vci = vci;
- __vcc_insert_socket(vcc->sk);
+ __vcc_insert_socket(sk);
write_unlock_irq(&vcc_sklist_lock);
switch (vcc->qos.aal) {
case ATM_AAL0:
@@ -386,7 +379,7 @@ static int __vcc_connect(struct atm_vcc *vcc, struct atm_dev *dev, short vpi,
return 0;
fail:
- vcc_remove_socket(vcc->sk);
+ vcc_remove_socket(sk);
fail_module_put:
module_put(dev->ops->owner);
/* ensure we get dev module ref count correct */
@@ -495,7 +488,7 @@ int vcc_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
if (error)
return error;
sock_recv_timestamp(msg, sk, skb);
- DPRINTK("RcvM %d -= %d\n", atomic_read(&vcc->sk->rmem_alloc), skb->truesize);
+ DPRINTK("RcvM %d -= %d\n", atomic_read(&sk->rmem_alloc), skb->truesize);
atm_return(vcc, skb->truesize);
skb_free_datagram(sk, skb);
return copied;
@@ -615,7 +608,7 @@ unsigned int vcc_poll(struct file *file, struct socket *sock, poll_table *wait)
return mask;
if (vcc->qos.txtp.traffic_class != ATM_NONE &&
- vcc_writable(vcc->sk))
+ vcc_writable(sk))
mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
return mask;
@@ -638,7 +631,7 @@ static int atm_change_qos(struct atm_vcc *vcc,struct atm_qos *qos)
if (!error) error = adjust_tp(&qos->rxtp,qos->aal);
if (error) return error;
if (!vcc->dev->ops->change_qos) return -EOPNOTSUPP;
- if (vcc->sk->sk_family == AF_ATMPVC)
+ if (sk_atm(vcc)->sk_family == AF_ATMPVC)
return vcc->dev->ops->change_qos(vcc,qos,ATM_MF_SET);
return svc_change_qos(vcc,qos);
}
@@ -762,21 +755,6 @@ int vcc_getsockopt(struct socket *sock, int level, int optname,
return vcc->dev->ops->getsockopt(vcc, level, optname, optval, len);
}
-
-#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
-#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
-struct net_bridge;
-struct net_bridge_fdb_entry *(*br_fdb_get_hook)(struct net_bridge *br,
- unsigned char *addr) = NULL;
-void (*br_fdb_put_hook)(struct net_bridge_fdb_entry *ent) = NULL;
-#if defined(CONFIG_ATM_LANE_MODULE) || defined(CONFIG_BRIDGE_MODULE)
-EXPORT_SYMBOL(br_fdb_get_hook);
-EXPORT_SYMBOL(br_fdb_put_hook);
-#endif /* defined(CONFIG_ATM_LANE_MODULE) || defined(CONFIG_BRIDGE_MODULE) */
-#endif /* defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) */
-#endif /* defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE) */
-
-
static int __init atm_init(void)
{
int error;
diff --git a/net/atm/ioctl.c b/net/atm/ioctl.c
index b15e724f8f96f..4dbb5af34a5ed 100644
--- a/net/atm/ioctl.c
+++ b/net/atm/ioctl.c
@@ -46,6 +46,7 @@ EXPORT_SYMBOL(deregister_atm_ioctl);
int vcc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
{
+ struct sock *sk = sock->sk;
struct atm_vcc *vcc;
int error;
struct list_head * pos;
@@ -59,8 +60,8 @@ int vcc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
error = -EINVAL;
goto done;
}
- error = put_user(vcc->sk->sk_sndbuf -
- atomic_read(&vcc->sk->sk_wmem_alloc),
+ error = put_user(sk->sk_sndbuf -
+ atomic_read(&sk->sk_wmem_alloc),
(int __user *) argp) ? -EFAULT : 0;
goto done;
case SIOCINQ:
@@ -71,13 +72,13 @@ int vcc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
error = -EINVAL;
goto done;
}
- skb = skb_peek(&vcc->sk->sk_receive_queue);
+ skb = skb_peek(&sk->sk_receive_queue);
error = put_user(skb ? skb->len : 0,
(int __user *)argp) ? -EFAULT : 0;
goto done;
}
case SIOCGSTAMP: /* borrowed from IP */
- error = sock_get_timestamp(vcc->sk, argp);
+ error = sock_get_timestamp(sk, argp);
goto done;
case ATM_SETSC:
printk(KERN_WARNING "ATM_SETSC is obsolete\n");
diff --git a/net/atm/lec.c b/net/atm/lec.c
index c243b191ad4fc..a0752487026d5 100644
--- a/net/atm/lec.c
+++ b/net/atm/lec.c
@@ -37,11 +37,8 @@
#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
#include <linux/if_bridge.h>
#include "../bridge/br_private.h"
-static unsigned char bridge_ula_lec[] = {0x01, 0x80, 0xc2, 0x00, 0x00};
-extern struct net_bridge_fdb_entry *(*br_fdb_get_hook)(struct net_bridge *br,
- unsigned char *addr);
-extern void (*br_fdb_put_hook)(struct net_bridge_fdb_entry *ent);
+static unsigned char bridge_ula_lec[] = {0x01, 0x80, 0xc2, 0x00, 0x00};
#endif
/* Modular too */
@@ -83,6 +80,29 @@ static int lane2_resolve(struct net_device *dev, u8 *dst_mac, int force,
static int lane2_associate_req (struct net_device *dev, u8 *lan_dst,
u8 *tlvs, u32 sizeoftlvs);
+static int lec_addr_delete(struct lec_priv *priv, unsigned char *atm_addr,
+ unsigned long permanent);
+static void lec_arp_check_empties(struct lec_priv *priv,
+ struct atm_vcc *vcc, struct sk_buff *skb);
+static void lec_arp_destroy(struct lec_priv *priv);
+static void lec_arp_init(struct lec_priv *priv);
+static struct atm_vcc* lec_arp_resolve(struct lec_priv *priv,
+ unsigned char *mac_to_find,
+ int is_rdesc,
+ struct lec_arp_table **ret_entry);
+static void lec_arp_update(struct lec_priv *priv, unsigned char *mac_addr,
+ unsigned char *atm_addr, unsigned long remoteflag,
+ unsigned int targetless_le_arp);
+static void lec_flush_complete(struct lec_priv *priv, unsigned long tran_id);
+static int lec_mcast_make(struct lec_priv *priv, struct atm_vcc *vcc);
+static void lec_set_flush_tran_id(struct lec_priv *priv,
+ unsigned char *atm_addr,
+ unsigned long tran_id);
+static void lec_vcc_added(struct lec_priv *priv, struct atmlec_ioc *ioc_data,
+ struct atm_vcc *vcc,
+ void (*old_push)(struct atm_vcc *vcc, struct sk_buff *skb));
+static void lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc);
+
static struct lane2_ops lane2_ops = {
lane2_resolve, /* resolve, spec 3.1.3 */
lane2_associate_req, /* associate_req, spec 3.1.4 */
@@ -94,21 +114,6 @@ static unsigned char bus_mac[ETH_ALEN] = {0xff,0xff,0xff,0xff,0xff,0xff};
/* Device structures */
static struct net_device *dev_lec[MAX_LEC_ITF];
-/* This will be called from proc.c via function pointer */
-struct net_device *get_dev_lec(int itf)
-{
- struct net_device *dev;
-
- if (itf >= MAX_LEC_ITF)
- return NULL;
- rtnl_lock();
- dev = dev_lec[itf];
- if (dev)
- dev_hold(dev);
- rtnl_unlock();
- return dev;
-}
-
#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
static void lec_handle_bridge(struct sk_buff *skb, struct net_device *dev)
{
@@ -122,6 +127,7 @@ static void lec_handle_bridge(struct sk_buff *skb, struct net_device *dev)
eth = (struct ethhdr *)skb->data;
buff = skb->data + skb->dev->hard_header_len;
if (*buff++ == 0x42 && *buff++ == 0x42 && *buff++ == 0x03) {
+ struct sock *sk;
struct sk_buff *skb2;
struct atmlec_msg *mesg;
@@ -135,8 +141,9 @@ static void lec_handle_bridge(struct sk_buff *skb, struct net_device *dev)
priv = (struct lec_priv *)dev->priv;
atm_force_charge(priv->lecd, skb2->truesize);
- skb_queue_tail(&priv->lecd->sk->sk_receive_queue, skb2);
- priv->lecd->sk->sk_data_ready(priv->lecd->sk, skb2->len);
+ sk = sk_atm(priv->lecd);
+ skb_queue_tail(&sk->sk_receive_queue, skb2);
+ sk->sk_data_ready(sk, skb2->len);
}
return;
@@ -153,7 +160,7 @@ static void lec_handle_bridge(struct sk_buff *skb, struct net_device *dev)
* and returns NULL.
*/
#ifdef CONFIG_TR
-unsigned char *get_tr_dst(unsigned char *packet, unsigned char *rdesc)
+static unsigned char *get_tr_dst(unsigned char *packet, unsigned char *rdesc)
{
struct trh_hdr *trh;
int riflen, num_rdsc;
@@ -214,7 +221,7 @@ lec_send(struct atm_vcc *vcc, struct sk_buff *skb, struct lec_priv *priv)
ATM_SKB(skb)->vcc = vcc;
ATM_SKB(skb)->atm_options = vcc->atm_options;
- atomic_add(skb->truesize, &vcc->sk->sk_wmem_alloc);
+ atomic_add(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc);
if (vcc->send(vcc, skb) < 0) {
priv->stats.tx_dropped++;
return;
@@ -430,7 +437,7 @@ lec_atm_send(struct atm_vcc *vcc, struct sk_buff *skb)
int i;
char *tmp; /* FIXME */
- atomic_sub(skb->truesize, &vcc->sk->sk_wmem_alloc);
+ atomic_sub(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc);
mesg = (struct atmlec_msg *)skb->data;
tmp = skb->data;
tmp += sizeof(struct atmlec_msg);
@@ -528,6 +535,7 @@ lec_atm_send(struct atm_vcc *vcc, struct sk_buff *skb)
f->dst->state == BR_STATE_FORWARDING) {
/* hit from bridge table, send LE_ARP_RESPONSE */
struct sk_buff *skb2;
+ struct sock *sk;
DPRINTK("%s: entry found, responding to zeppelin\n", dev->name);
skb2 = alloc_skb(sizeof(struct atmlec_msg), GFP_ATOMIC);
@@ -538,8 +546,9 @@ lec_atm_send(struct atm_vcc *vcc, struct sk_buff *skb)
skb2->len = sizeof(struct atmlec_msg);
memcpy(skb2->data, mesg, sizeof(struct atmlec_msg));
atm_force_charge(priv->lecd, skb2->truesize);
- skb_queue_tail(&priv->lecd->sk->sk_receive_queue, skb2);
- priv->lecd->sk->sk_data_ready(priv->lecd->sk, skb2->len);
+ sk = sk_atm(priv->lecd);
+ skb_queue_tail(&sk->sk_receive_queue, skb2);
+ sk->sk_data_ready(sk, skb2->len);
}
if (f != NULL) br_fdb_put_hook(f);
#endif /* defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) */
@@ -567,10 +576,10 @@ lec_atm_close(struct atm_vcc *vcc)
netif_stop_queue(dev);
lec_arp_destroy(priv);
- if (skb_peek(&vcc->sk->sk_receive_queue))
+ if (skb_peek(&sk_atm(vcc)->sk_receive_queue))
printk("%s lec_atm_close: closing with messages pending\n",
dev->name);
- while ((skb = skb_dequeue(&vcc->sk->sk_receive_queue)) != NULL) {
+ while ((skb = skb_dequeue(&sk_atm(vcc)->sk_receive_queue)) != NULL) {
atm_return(vcc, skb->truesize);
dev_kfree_skb(skb);
}
@@ -595,11 +604,12 @@ static struct atm_dev lecatm_dev = {
* LANE2: new argument struct sk_buff *data contains
* the LE_ARP based TLVs introduced in the LANE2 spec
*/
-int
+static int
send_to_lecd(struct lec_priv *priv, atmlec_msg_type type,
unsigned char *mac_addr, unsigned char *atm_addr,
struct sk_buff *data)
{
+ struct sock *sk;
struct sk_buff *skb;
struct atmlec_msg *mesg;
@@ -623,14 +633,15 @@ send_to_lecd(struct lec_priv *priv, atmlec_msg_type type,
memcpy(&mesg->content.normal.atm_addr, atm_addr, ATM_ESA_LEN);
atm_force_charge(priv->lecd, skb->truesize);
- skb_queue_tail(&priv->lecd->sk->sk_receive_queue, skb);
- priv->lecd->sk->sk_data_ready(priv->lecd->sk, skb->len);
+ sk = sk_atm(priv->lecd);
+ skb_queue_tail(&sk->sk_receive_queue, skb);
+ sk->sk_data_ready(sk, skb->len);
if (data != NULL) {
DPRINTK("lec: about to send %d bytes of data\n", data->len);
atm_force_charge(priv->lecd, data->truesize);
- skb_queue_tail(&priv->lecd->sk->sk_receive_queue, data);
- priv->lecd->sk->sk_data_ready(priv->lecd->sk, skb->len);
+ skb_queue_tail(&sk->sk_receive_queue, data);
+ sk->sk_data_ready(sk, skb->len);
}
return 0;
@@ -675,7 +686,7 @@ static unsigned char lec_ctrl_magic[] = {
0x01,
0x01 };
-void
+static void
lec_push(struct atm_vcc *vcc, struct sk_buff *skb)
{
struct net_device *dev = (struct net_device *)vcc->proto_data;
@@ -711,9 +722,11 @@ lec_push(struct atm_vcc *vcc, struct sk_buff *skb)
printk("%s...\n",buf);
#endif /* DUMP_PACKETS > 0 */
if (memcmp(skb->data, lec_ctrl_magic, 4) ==0) { /* Control frame, to daemon*/
+ struct sock *sk = sk_atm(vcc);
+
DPRINTK("%s: To daemon\n",dev->name);
- skb_queue_tail(&vcc->sk->sk_receive_queue, skb);
- vcc->sk->sk_data_ready(vcc->sk, skb->len);
+ skb_queue_tail(&sk->sk_receive_queue, skb);
+ sk->sk_data_ready(sk, skb->len);
} else { /* Data frame, queue to protocol handlers */
unsigned char *dst;
@@ -756,7 +769,7 @@ lec_push(struct atm_vcc *vcc, struct sk_buff *skb)
}
}
-void
+static void
lec_pop(struct atm_vcc *vcc, struct sk_buff *skb)
{
struct lec_vcc_priv *vpriv = LEC_VCC_PRIV(vcc);
@@ -776,7 +789,7 @@ lec_pop(struct atm_vcc *vcc, struct sk_buff *skb)
}
}
-int
+static int
lec_vcc_attach(struct atm_vcc *vcc, void __user *arg)
{
struct lec_vcc_priv *vpriv;
@@ -805,7 +818,7 @@ lec_vcc_attach(struct atm_vcc *vcc, void __user *arg)
return 0;
}
-int
+static int
lec_mcast_attach(struct atm_vcc *vcc, int arg)
{
if (arg <0 || arg >= MAX_LEC_ITF || !dev_lec[arg])
@@ -815,7 +828,7 @@ lec_mcast_attach(struct atm_vcc *vcc, int arg)
}
/* Initialize device. */
-int
+static int
lecd_attach(struct atm_vcc *vcc, int arg)
{
int i;
@@ -866,7 +879,7 @@ lecd_attach(struct atm_vcc *vcc, int arg)
priv->itfnum = i; /* LANE2 addition */
priv->lecd = vcc;
vcc->dev = &lecatm_dev;
- vcc_insert_socket(vcc->sk);
+ vcc_insert_socket(sk_atm(vcc));
vcc->proto_data = dev_lec[i];
set_bit(ATM_VF_META,&vcc->flags);
@@ -1375,7 +1388,6 @@ static void lane2_associate_ind (struct net_device *dev, u8 *mac_addr,
static void lec_arp_check_expire(unsigned long data);
static void lec_arp_expire_arp(unsigned long data);
-void dump_arp_table(struct lec_priv *priv);
/*
* Arp table funcs
@@ -1386,7 +1398,7 @@ void dump_arp_table(struct lec_priv *priv);
/*
* Initialization of arp-cache
*/
-void
+static void
lec_arp_init(struct lec_priv *priv)
{
unsigned short i;
@@ -1402,7 +1414,7 @@ lec_arp_init(struct lec_priv *priv)
add_timer(&priv->lec_arp_timer);
}
-void
+static void
lec_arp_clear_vccs(struct lec_arp_table *entry)
{
if (entry->vcc) {
@@ -1531,7 +1543,7 @@ get_status_string(unsigned char st)
}
#endif
-void
+static void
dump_arp_table(struct lec_priv *priv)
{
#if DEBUG_ARP_TABLE
@@ -1683,7 +1695,7 @@ dump_arp_table(struct lec_priv *priv)
/*
* Destruction of arp-cache
*/
-void
+static void
lec_arp_destroy(struct lec_priv *priv)
{
unsigned long flags;
@@ -1945,9 +1957,9 @@ lec_arp_check_expire(unsigned long data)
* Try to find vcc where mac_address is attached.
*
*/
-struct atm_vcc*
-lec_arp_resolve(struct lec_priv *priv, unsigned char *mac_to_find, int is_rdesc,
- struct lec_arp_table **ret_entry)
+static struct atm_vcc*
+lec_arp_resolve(struct lec_priv *priv, unsigned char *mac_to_find,
+ int is_rdesc, struct lec_arp_table **ret_entry)
{
unsigned long flags;
struct lec_arp_table *entry;
@@ -2026,7 +2038,7 @@ out:
return found;
}
-int
+static int
lec_addr_delete(struct lec_priv *priv, unsigned char *atm_addr,
unsigned long permanent)
{
@@ -2056,7 +2068,7 @@ lec_addr_delete(struct lec_priv *priv, unsigned char *atm_addr,
/*
* Notifies: Response to arp_request (atm_addr != NULL)
*/
-void
+static void
lec_arp_update(struct lec_priv *priv, unsigned char *mac_addr,
unsigned char *atm_addr, unsigned long remoteflag,
unsigned int targetless_le_arp)
@@ -2168,7 +2180,7 @@ out:
/*
* Notifies: Vcc setup ready
*/
-void
+static void
lec_vcc_added(struct lec_priv *priv, struct atmlec_ioc *ioc_data,
struct atm_vcc *vcc,
void (*old_push)(struct atm_vcc *vcc, struct sk_buff *skb))
@@ -2312,7 +2324,7 @@ out:
spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
}
-void
+static void
lec_flush_complete(struct lec_priv *priv, unsigned long tran_id)
{
unsigned long flags;
@@ -2338,7 +2350,7 @@ lec_flush_complete(struct lec_priv *priv, unsigned long tran_id)
dump_arp_table(priv);
}
-void
+static void
lec_set_flush_tran_id(struct lec_priv *priv,
unsigned char *atm_addr, unsigned long tran_id)
{
@@ -2356,7 +2368,7 @@ lec_set_flush_tran_id(struct lec_priv *priv,
spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
}
-int
+static int
lec_mcast_make(struct lec_priv *priv, struct atm_vcc *vcc)
{
unsigned long flags;
@@ -2393,7 +2405,7 @@ out:
return err;
}
-void
+static void
lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc)
{
unsigned long flags;
@@ -2468,7 +2480,7 @@ lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc)
dump_arp_table(priv);
}
-void
+static void
lec_arp_check_empties(struct lec_priv *priv,
struct atm_vcc *vcc, struct sk_buff *skb)
{
diff --git a/net/atm/lec.h b/net/atm/lec.h
index 34a64f4b63e3c..6606082b29a87 100644
--- a/net/atm/lec.h
+++ b/net/atm/lec.h
@@ -14,14 +14,6 @@
#include <linux/netdevice.h>
#include <linux/atmlec.h>
-#if defined (CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
-#include <linux/if_bridge.h>
-struct net_bridge;
-extern struct net_bridge_fdb_entry *(*br_fdb_get_hook)(struct net_bridge *br,
- unsigned char *addr);
-extern void (*br_fdb_put_hook)(struct net_bridge_fdb_entry *ent);
-#endif /* defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) */
-
#define LEC_HEADER_LEN 16
struct lecdatahdr_8023 {
@@ -146,14 +138,5 @@ struct lec_vcc_priv {
#define LEC_VCC_PRIV(vcc) ((struct lec_vcc_priv *)((vcc)->user_back))
-int lecd_attach(struct atm_vcc *vcc, int arg);
-int lec_vcc_attach(struct atm_vcc *vcc, void __user *arg);
-int lec_mcast_attach(struct atm_vcc *vcc, int arg);
-struct net_device *get_dev_lec(int itf);
-int send_to_lecd(struct lec_priv *priv,
- atmlec_msg_type type, unsigned char *mac_addr,
- unsigned char *atm_addr, struct sk_buff *data);
-void lec_push(struct atm_vcc *vcc, struct sk_buff *skb);
-
#endif /* _LEC_H_ */
diff --git a/net/atm/lec_arpc.h b/net/atm/lec_arpc.h
index d07fc6a0a2c3f..397448094648e 100644
--- a/net/atm/lec_arpc.h
+++ b/net/atm/lec_arpc.h
@@ -89,28 +89,4 @@ struct tlv { /* LANE2: Template tlv struct for accessing */
#define LEC_REMOTE_FLAG 0x0001
#define LEC_PERMANENT_FLAG 0x0002
-/* Protos */
-void lec_arp_init(struct lec_priv *priv);
-int lec_mcast_make(struct lec_priv *priv, struct atm_vcc *vcc);
-void lec_arp_destroy(struct lec_priv *priv);
-void lec_vcc_close(struct lec_priv *priv, struct atm_vcc *vcc);
-
-struct atm_vcc *lec_arp_resolve(struct lec_priv *priv,
- unsigned char *mac_to_addr,
- int is_rdesc,
- struct lec_arp_table **ret_entry);
-void lec_vcc_added(struct lec_priv *dev,
- struct atmlec_ioc *ioc_data, struct atm_vcc *vcc,
- void (*old_push)(struct atm_vcc *vcc, struct sk_buff *skb));
-void lec_arp_check_empties(struct lec_priv *priv,
- struct atm_vcc *vcc, struct sk_buff *skb);
-int lec_addr_delete(struct lec_priv *priv,
- unsigned char *mac_addr, unsigned long permanent);
-void lec_flush_complete(struct lec_priv *priv, unsigned long tran_id);
-void lec_arp_update(struct lec_priv *priv,
- unsigned char *mac_addr, unsigned char *atm_addr,
- unsigned long remoteflag, unsigned int targetless_le_arp);
-void lec_set_flush_tran_id(struct lec_priv *priv,
- unsigned char *mac_addr, unsigned long tran_id);
-
#endif
diff --git a/net/atm/mpc.c b/net/atm/mpc.c
index a28db2d2d0c0a..17a81ebe7e6eb 100644
--- a/net/atm/mpc.c
+++ b/net/atm/mpc.c
@@ -522,7 +522,7 @@ static int send_via_shortcut(struct sk_buff *skb, struct mpoa_client *mpc)
memcpy(skb->data, &llc_snap_mpoa_data, sizeof(struct llc_snap_hdr));
}
- atomic_add(skb->truesize, &entry->shortcut->sk->sk_wmem_alloc);
+ atomic_add(skb->truesize, &sk_atm(entry->shortcut)->sk_wmem_alloc);
ATM_SKB(skb)->atm_options = entry->shortcut->atm_options;
entry->shortcut->send(entry->shortcut, skb);
entry->packets_fwded++;
@@ -564,7 +564,7 @@ static int mpc_send_packet(struct sk_buff *skb, struct net_device *dev)
return retval;
}
-int atm_mpoa_vcc_attach(struct atm_vcc *vcc, void __user *arg)
+static int atm_mpoa_vcc_attach(struct atm_vcc *vcc, void __user *arg)
{
int bytes_left;
struct mpoa_client *mpc;
@@ -665,10 +665,12 @@ static void mpc_push(struct atm_vcc *vcc, struct sk_buff *skb)
skb->dev = dev;
if (memcmp(skb->data, &llc_snap_mpoa_ctrl, sizeof(struct llc_snap_hdr)) == 0) {
+ struct sock *sk = sk_atm(vcc);
+
dprintk("mpoa: (%s) mpc_push: control packet arrived\n", dev->name);
/* Pass control packets to daemon */
- skb_queue_tail(&vcc->sk->sk_receive_queue, skb);
- vcc->sk->sk_data_ready(vcc->sk, skb->len);
+ skb_queue_tail(&sk->sk_receive_queue, skb);
+ sk->sk_data_ready(sk, skb->len);
return;
}
@@ -751,7 +753,7 @@ static struct atm_dev mpc_dev = {
/* members not explicitly initialised will be 0 */
};
-int atm_mpoa_mpoad_attach (struct atm_vcc *vcc, int arg)
+static int atm_mpoa_mpoad_attach (struct atm_vcc *vcc, int arg)
{
struct mpoa_client *mpc;
struct lec_priv *priv;
@@ -794,7 +796,7 @@ int atm_mpoa_mpoad_attach (struct atm_vcc *vcc, int arg)
mpc->mpoad_vcc = vcc;
vcc->dev = &mpc_dev;
- vcc_insert_socket(vcc->sk);
+ vcc_insert_socket(sk_atm(vcc));
set_bit(ATM_VF_META,&vcc->flags);
set_bit(ATM_VF_READY,&vcc->flags);
@@ -853,7 +855,7 @@ static void mpoad_close(struct atm_vcc *vcc)
mpc->in_ops->destroy_cache(mpc);
mpc->eg_ops->destroy_cache(mpc);
- while ((skb = skb_dequeue(&vcc->sk->sk_receive_queue))) {
+ while ((skb = skb_dequeue(&sk_atm(vcc)->sk_receive_queue))) {
atm_return(vcc, skb->truesize);
kfree_skb(skb);
}
@@ -873,7 +875,7 @@ static int msg_from_mpoad(struct atm_vcc *vcc, struct sk_buff *skb)
struct mpoa_client *mpc = find_mpc_by_vcc(vcc);
struct k_message *mesg = (struct k_message*)skb->data;
- atomic_sub(skb->truesize, &vcc->sk->sk_wmem_alloc);
+ atomic_sub(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc);
if (mpc == NULL) {
printk("mpoa: msg_from_mpoad: no mpc found\n");
@@ -938,6 +940,7 @@ static int msg_from_mpoad(struct atm_vcc *vcc, struct sk_buff *skb)
int msg_to_mpoad(struct k_message *mesg, struct mpoa_client *mpc)
{
struct sk_buff *skb;
+ struct sock *sk;
if (mpc == NULL || !mpc->mpoad_vcc) {
printk("mpoa: msg_to_mpoad: mesg %d to a non-existent mpoad\n", mesg->type);
@@ -950,8 +953,10 @@ int msg_to_mpoad(struct k_message *mesg, struct mpoa_client *mpc)
skb_put(skb, sizeof(struct k_message));
memcpy(skb->data, mesg, sizeof(struct k_message));
atm_force_charge(mpc->mpoad_vcc, skb->truesize);
- skb_queue_tail(&mpc->mpoad_vcc->sk->sk_receive_queue, skb);
- mpc->mpoad_vcc->sk->sk_data_ready(mpc->mpoad_vcc->sk, skb->len);
+
+ sk = sk_atm(mpc->mpoad_vcc);
+ skb_queue_tail(&sk->sk_receive_queue, skb);
+ sk->sk_data_ready(sk, skb->len);
return 0;
}
@@ -1206,6 +1211,7 @@ static void egress_purge_rcvd(struct k_message *msg, struct mpoa_client *mpc)
static void purge_egress_shortcut(struct atm_vcc *vcc, eg_cache_entry *entry)
{
+ struct sock *sk;
struct k_message *purge_msg;
struct sk_buff *skb;
@@ -1229,8 +1235,10 @@ static void purge_egress_shortcut(struct atm_vcc *vcc, eg_cache_entry *entry)
purge_msg->content.eg_info = entry->ctrl_info;
atm_force_charge(vcc, skb->truesize);
- skb_queue_tail(&vcc->sk->sk_receive_queue, skb);
- vcc->sk->sk_data_ready(vcc->sk, skb->len);
+
+ sk = sk_atm(vcc);
+ skb_queue_tail(&sk->sk_receive_queue, skb);
+ sk->sk_data_ready(sk, skb->len);
dprintk("mpoa: purge_egress_shortcut: exiting:\n");
return;
@@ -1452,7 +1460,7 @@ static __init int atm_mpoa_init(void)
return 0;
}
-void __exit atm_mpoa_cleanup(void)
+static void __exit atm_mpoa_cleanup(void)
{
struct mpoa_client *mpc, *tmp;
struct atm_mpoa_qos *qos, *nextqos;
diff --git a/net/atm/mpc.h b/net/atm/mpc.h
index cb6cbdd2294bd..863ddf6079e15 100644
--- a/net/atm/mpc.h
+++ b/net/atm/mpc.h
@@ -11,10 +11,6 @@
/* kernel -> mpc-daemon */
int msg_to_mpoad(struct k_message *msg, struct mpoa_client *mpc);
-/* Functions for ioctl(ATMMPC_*) operations */
-int atm_mpoa_mpoad_attach(struct atm_vcc *vcc, int arg);
-int atm_mpoa_vcc_attach(struct atm_vcc *vcc, void __user *arg);
-
struct mpoa_client {
struct mpoa_client *next;
struct net_device *dev; /* lec in question */
diff --git a/net/atm/pppoatm.c b/net/atm/pppoatm.c
index bea4da1cf1abf..58f4a2b5aebe4 100644
--- a/net/atm/pppoatm.c
+++ b/net/atm/pppoatm.c
@@ -233,7 +233,8 @@ static int pppoatm_send(struct ppp_channel *chan, struct sk_buff *skb)
kfree_skb(skb);
return 1;
}
- atomic_add(skb->truesize, &ATM_SKB(skb)->vcc->sk->sk_wmem_alloc);
+
+ atomic_add(skb->truesize, &sk_atm(ATM_SKB(skb)->vcc)->sk_wmem_alloc);
ATM_SKB(skb)->atm_options = ATM_SKB(skb)->vcc->atm_options;
DPRINTK("(unit %d): atm_skb(%p)->vcc(%p)->dev(%p)\n",
pvcc->chan.unit, skb, ATM_SKB(skb)->vcc,
@@ -344,7 +345,7 @@ static int pppoatm_ioctl(struct socket *sock, unsigned int cmd,
return -ENOIOCTLCMD;
}
-struct atm_ioctl pppoatm_ioctl_ops = {
+static struct atm_ioctl pppoatm_ioctl_ops = {
.owner = THIS_MODULE,
.ioctl = pppoatm_ioctl,
};
diff --git a/net/atm/proc.c b/net/atm/proc.c
index 12f49fe94c8f3..4041054e52825 100644
--- a/net/atm/proc.c
+++ b/net/atm/proc.c
@@ -71,9 +71,7 @@ struct vcc_state {
static inline int compare_family(struct sock *sk, int family)
{
- struct atm_vcc *vcc = atm_sk(sk);
-
- return !family || (vcc->sk->sk_family == family);
+ return !family || (sk->sk_family == family);
}
static int __vcc_walk(struct sock **sock, int family, int *bucket, loff_t l)
@@ -203,13 +201,15 @@ static const char *vcc_state(struct atm_vcc *vcc)
static void vcc_info(struct seq_file *seq, struct atm_vcc *vcc)
{
+ struct sock *sk = sk_atm(vcc);
+
seq_printf(seq, "%p ", vcc);
if (!vcc->dev)
seq_printf(seq, "Unassigned ");
else
seq_printf(seq, "%3d %3d %5d ", vcc->dev->number, vcc->vpi,
vcc->vci);
- switch (vcc->sk->sk_family) {
+ switch (sk->sk_family) {
case AF_ATMPVC:
seq_printf(seq, "PVC");
break;
@@ -217,12 +217,12 @@ static void vcc_info(struct seq_file *seq, struct atm_vcc *vcc)
seq_printf(seq, "SVC");
break;
default:
- seq_printf(seq, "%3d", vcc->sk->sk_family);
+ seq_printf(seq, "%3d", sk->sk_family);
}
- seq_printf(seq, " %04lx %5d %7d/%7d %7d/%7d [%d]\n", vcc->flags, vcc->sk->sk_err,
- atomic_read(&vcc->sk->sk_wmem_alloc),vcc->sk->sk_sndbuf,
- atomic_read(&vcc->sk->sk_rmem_alloc),vcc->sk->sk_rcvbuf,
- atomic_read(&vcc->sk->sk_refcnt));
+ seq_printf(seq, " %04lx %5d %7d/%7d %7d/%7d [%d]\n", vcc->flags, sk->sk_err,
+ atomic_read(&sk->sk_wmem_alloc), sk->sk_sndbuf,
+ atomic_read(&sk->sk_rmem_alloc), sk->sk_rcvbuf,
+ atomic_read(&sk->sk_refcnt));
}
static void svc_info(struct seq_file *seq, struct atm_vcc *vcc)
diff --git a/net/atm/protocols.h b/net/atm/protocols.h
index 0d658fa8a611c..acdfc856222db 100644
--- a/net/atm/protocols.h
+++ b/net/atm/protocols.h
@@ -6,8 +6,6 @@
#ifndef NET_ATM_PROTOCOLS_H
#define NET_ATM_PROTOCOLS_H
-void atm_push_raw(struct atm_vcc *vcc,struct sk_buff *skb);
-
int atm_init_aal0(struct atm_vcc *vcc); /* "raw" AAL0 */
int atm_init_aal34(struct atm_vcc *vcc);/* "raw" AAL3/4 transport */
int atm_init_aal5(struct atm_vcc *vcc); /* "raw" AAL5 transport */
diff --git a/net/atm/raw.c b/net/atm/raw.c
index 5d75ec1aafb03..4a0466e91aa67 100644
--- a/net/atm/raw.c
+++ b/net/atm/raw.c
@@ -25,22 +25,26 @@
* SKB == NULL indicates that the link is being closed
*/
-void atm_push_raw(struct atm_vcc *vcc,struct sk_buff *skb)
+static void atm_push_raw(struct atm_vcc *vcc,struct sk_buff *skb)
{
if (skb) {
- skb_queue_tail(&vcc->sk->sk_receive_queue, skb);
- vcc->sk->sk_data_ready(vcc->sk, skb->len);
+ struct sock *sk = sk_atm(vcc);
+
+ skb_queue_tail(&sk->sk_receive_queue, skb);
+ sk->sk_data_ready(sk, skb->len);
}
}
static void atm_pop_raw(struct atm_vcc *vcc,struct sk_buff *skb)
{
- DPRINTK("APopR (%d) %d -= %d\n", vcc->vci, vcc->sk->sk_wmem_alloc,
+ struct sock *sk = sk_atm(vcc);
+
+ DPRINTK("APopR (%d) %d -= %d\n", vcc->vci, sk->sk_wmem_alloc,
skb->truesize);
- atomic_sub(skb->truesize, &vcc->sk->sk_wmem_alloc);
+ atomic_sub(skb->truesize, &sk->sk_wmem_alloc);
dev_kfree_skb_any(skb);
- vcc->sk->sk_write_space(vcc->sk);
+ sk->sk_write_space(sk);
}
diff --git a/net/atm/signaling.c b/net/atm/signaling.c
index 0ecb4a4f66d0e..6ff803154c046 100644
--- a/net/atm/signaling.c
+++ b/net/atm/signaling.c
@@ -62,8 +62,8 @@ static void sigd_put_skb(struct sk_buff *skb)
}
#endif
atm_force_charge(sigd,skb->truesize);
- skb_queue_tail(&sigd->sk->sk_receive_queue,skb);
- sigd->sk->sk_data_ready(sigd->sk, skb->len);
+ skb_queue_tail(&sk_atm(sigd)->sk_receive_queue,skb);
+ sk_atm(sigd)->sk_data_ready(sk_atm(sigd), skb->len);
}
@@ -97,15 +97,18 @@ static int sigd_send(struct atm_vcc *vcc,struct sk_buff *skb)
{
struct atmsvc_msg *msg;
struct atm_vcc *session_vcc;
+ struct sock *sk;
msg = (struct atmsvc_msg *) skb->data;
- atomic_sub(skb->truesize, &vcc->sk->sk_wmem_alloc);
+ atomic_sub(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc);
DPRINTK("sigd_send %d (0x%lx)\n",(int) msg->type,
(unsigned long) msg->vcc);
vcc = *(struct atm_vcc **) &msg->vcc;
+ sk = sk_atm(vcc);
+
switch (msg->type) {
case as_okay:
- vcc->sk->sk_err = -msg->reply;
+ sk->sk_err = -msg->reply;
clear_bit(ATM_VF_WAITING, &vcc->flags);
if (!*vcc->local.sas_addr.prv &&
!*vcc->local.sas_addr.pub) {
@@ -126,25 +129,24 @@ static int sigd_send(struct atm_vcc *vcc,struct sk_buff *skb)
case as_error:
clear_bit(ATM_VF_REGIS,&vcc->flags);
clear_bit(ATM_VF_READY,&vcc->flags);
- vcc->sk->sk_err = -msg->reply;
+ sk->sk_err = -msg->reply;
clear_bit(ATM_VF_WAITING, &vcc->flags);
break;
case as_indicate:
vcc = *(struct atm_vcc **) &msg->listen_vcc;
DPRINTK("as_indicate!!!\n");
- lock_sock(vcc->sk);
- if (vcc->sk->sk_ack_backlog ==
- vcc->sk->sk_max_ack_backlog) {
+ lock_sock(sk);
+ if (sk_acceptq_is_full(sk)) {
sigd_enq(NULL,as_reject,vcc,NULL,NULL);
dev_kfree_skb(skb);
goto as_indicate_complete;
}
- vcc->sk->sk_ack_backlog++;
- skb_queue_tail(&vcc->sk->sk_receive_queue, skb);
- DPRINTK("waking vcc->sk->sk_sleep 0x%p\n", vcc->sk->sk_sleep);
- vcc->sk->sk_state_change(vcc->sk);
+ sk->sk_ack_backlog++;
+ skb_queue_tail(&sk->sk_receive_queue, skb);
+ DPRINTK("waking sk->sk_sleep 0x%p\n", sk->sk_sleep);
+ sk->sk_state_change(sk);
as_indicate_complete:
- release_sock(vcc->sk);
+ release_sock(sk);
return 0;
case as_close:
set_bit(ATM_VF_RELEASED,&vcc->flags);
@@ -155,7 +157,7 @@ as_indicate_complete:
break;
case as_addparty:
case as_dropparty:
- vcc->sk->sk_err_soft = msg->reply; /* < 0 failure, otherwise ep_ref */
+ sk->sk_err_soft = msg->reply; /* < 0 failure, otherwise ep_ref */
clear_bit(ATM_VF_WAITING, &vcc->flags);
break;
default:
@@ -163,7 +165,7 @@ as_indicate_complete:
(int) msg->type);
return -EINVAL;
}
- vcc->sk->sk_state_change(vcc->sk);
+ sk->sk_state_change(sk);
out:
dev_kfree_skb(skb);
return 0;
@@ -213,7 +215,7 @@ void sigd_enq(struct atm_vcc *vcc,enum atmsvc_msg_type type,
static void purge_vcc(struct atm_vcc *vcc)
{
- if (vcc->sk->sk_family == PF_ATMSVC &&
+ if (sk_atm(vcc)->sk_family == PF_ATMSVC &&
!test_bit(ATM_VF_META,&vcc->flags)) {
set_bit(ATM_VF_RELEASED,&vcc->flags);
vcc_release_async(vcc, -EUNATCH);
@@ -229,9 +231,9 @@ static void sigd_close(struct atm_vcc *vcc)
DPRINTK("sigd_close\n");
sigd = NULL;
- if (skb_peek(&vcc->sk->sk_receive_queue))
+ if (skb_peek(&sk_atm(vcc)->sk_receive_queue))
printk(KERN_ERR "sigd_close: closing with requests pending\n");
- skb_queue_purge(&vcc->sk->sk_receive_queue);
+ skb_queue_purge(&sk_atm(vcc)->sk_receive_queue);
read_lock(&vcc_sklist_lock);
for(i = 0; i < VCC_HTABLE_SIZE; ++i) {
@@ -268,7 +270,7 @@ int sigd_attach(struct atm_vcc *vcc)
DPRINTK("sigd_attach\n");
sigd = vcc;
vcc->dev = &sigd_dev;
- vcc_insert_socket(vcc->sk);
+ vcc_insert_socket(sk_atm(vcc));
set_bit(ATM_VF_META,&vcc->flags);
set_bit(ATM_VF_READY,&vcc->flags);
#ifdef WAIT_FOR_DEMON
diff --git a/net/atm/svc.c b/net/atm/svc.c
index d5314246e0ad2..02f5374a51f2a 100644
--- a/net/atm/svc.c
+++ b/net/atm/svc.c
@@ -53,20 +53,21 @@ static void svc_disconnect(struct atm_vcc *vcc)
{
DEFINE_WAIT(wait);
struct sk_buff *skb;
+ struct sock *sk = sk_atm(vcc);
DPRINTK("svc_disconnect %p\n",vcc);
if (test_bit(ATM_VF_REGIS,&vcc->flags)) {
- prepare_to_wait(vcc->sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE);
+ prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE);
sigd_enq(vcc,as_close,NULL,NULL,NULL);
while (!test_bit(ATM_VF_RELEASED,&vcc->flags) && sigd) {
schedule();
- prepare_to_wait(vcc->sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE);
+ prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE);
}
- finish_wait(vcc->sk->sk_sleep, &wait);
+ finish_wait(sk->sk_sleep, &wait);
}
/* beware - socket is still in use by atmsigd until the last
as_indicate has been answered */
- while ((skb = skb_dequeue(&vcc->sk->sk_receive_queue)) != NULL) {
+ while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
atm_return(vcc, skb->truesize);
DPRINTK("LISTEN REL\n");
sigd_enq2(NULL,as_reject,vcc,NULL,NULL,&vcc->qos,0);
@@ -318,8 +319,7 @@ static int svc_listen(struct socket *sock,int backlog)
goto out;
}
set_bit(ATM_VF_LISTEN,&vcc->flags);
- vcc->sk->sk_max_ack_backlog = backlog > 0 ? backlog :
- ATM_BACKLOG_DEFAULT;
+ sk->sk_max_ack_backlog = backlog > 0 ? backlog : ATM_BACKLOG_DEFAULT;
error = -sk->sk_err;
out:
release_sock(sk);
@@ -348,8 +348,8 @@ static int svc_accept(struct socket *sock,struct socket *newsock,int flags)
while (1) {
DEFINE_WAIT(wait);
- prepare_to_wait(old_vcc->sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
- while (!(skb = skb_dequeue(&old_vcc->sk->sk_receive_queue)) &&
+ prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
+ while (!(skb = skb_dequeue(&sk->sk_receive_queue)) &&
sigd) {
if (test_bit(ATM_VF_RELEASED,&old_vcc->flags)) break;
if (test_bit(ATM_VF_CLOSE,&old_vcc->flags)) {
@@ -367,9 +367,9 @@ static int svc_accept(struct socket *sock,struct socket *newsock,int flags)
error = -ERESTARTSYS;
break;
}
- prepare_to_wait(old_vcc->sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
+ prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
}
- finish_wait(old_vcc->sk->sk_sleep, &wait);
+ finish_wait(sk->sk_sleep, &wait);
if (error)
goto out;
if (!skb) {
@@ -385,7 +385,7 @@ static int svc_accept(struct socket *sock,struct socket *newsock,int flags)
error = vcc_connect(newsock, msg->pvc.sap_addr.itf,
msg->pvc.sap_addr.vpi, msg->pvc.sap_addr.vci);
dev_kfree_skb(skb);
- old_vcc->sk->sk_ack_backlog--;
+ sk->sk_ack_backlog--;
if (error) {
sigd_enq2(NULL,as_reject,old_vcc,NULL,NULL,
&old_vcc->qos,error);
@@ -394,23 +394,23 @@ static int svc_accept(struct socket *sock,struct socket *newsock,int flags)
}
/* wait should be short, so we ignore the non-blocking flag */
set_bit(ATM_VF_WAITING, &new_vcc->flags);
- prepare_to_wait(new_vcc->sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE);
+ prepare_to_wait(sk_atm(new_vcc)->sk_sleep, &wait, TASK_UNINTERRUPTIBLE);
sigd_enq(new_vcc,as_accept,old_vcc,NULL,NULL);
while (test_bit(ATM_VF_WAITING, &new_vcc->flags) && sigd) {
release_sock(sk);
schedule();
lock_sock(sk);
- prepare_to_wait(new_vcc->sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE);
+ prepare_to_wait(sk_atm(new_vcc)->sk_sleep, &wait, TASK_UNINTERRUPTIBLE);
}
- finish_wait(new_vcc->sk->sk_sleep, &wait);
+ finish_wait(sk_atm(new_vcc)->sk_sleep, &wait);
if (!sigd) {
error = -EUNATCH;
goto out;
}
- if (!new_vcc->sk->sk_err)
+ if (!sk_atm(new_vcc)->sk_err)
break;
- if (new_vcc->sk->sk_err != ERESTARTSYS) {
- error = -new_vcc->sk->sk_err;
+ if (sk_atm(new_vcc)->sk_err != ERESTARTSYS) {
+ error = -sk_atm(new_vcc)->sk_err;
goto out;
}
}
@@ -436,19 +436,20 @@ static int svc_getname(struct socket *sock,struct sockaddr *sockaddr,
int svc_change_qos(struct atm_vcc *vcc,struct atm_qos *qos)
{
+ struct sock *sk = sk_atm(vcc);
DEFINE_WAIT(wait);
set_bit(ATM_VF_WAITING, &vcc->flags);
- prepare_to_wait(vcc->sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE);
+ prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE);
sigd_enq2(vcc,as_modify,NULL,NULL,&vcc->local,qos,0);
while (test_bit(ATM_VF_WAITING, &vcc->flags) &&
!test_bit(ATM_VF_RELEASED, &vcc->flags) && sigd) {
schedule();
- prepare_to_wait(vcc->sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE);
+ prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE);
}
- finish_wait(vcc->sk->sk_sleep, &wait);
+ finish_wait(sk->sk_sleep, &wait);
if (!sigd) return -EUNATCH;
- return -vcc->sk->sk_err;
+ return -sk->sk_err;
}
@@ -533,28 +534,29 @@ static int svc_addparty(struct socket *sock, struct sockaddr *sockaddr,
int sockaddr_len, int flags)
{
DEFINE_WAIT(wait);
+ struct sock *sk = sock->sk;
struct atm_vcc *vcc = ATM_SD(sock);
int error;
- lock_sock(vcc->sk);
+ lock_sock(sk);
set_bit(ATM_VF_WAITING, &vcc->flags);
- prepare_to_wait(vcc->sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
+ prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
sigd_enq(vcc, as_addparty, NULL, NULL,
(struct sockaddr_atmsvc *) sockaddr);
if (flags & O_NONBLOCK) {
- finish_wait(vcc->sk->sk_sleep, &wait);
+ finish_wait(sk->sk_sleep, &wait);
error = -EINPROGRESS;
goto out;
}
DPRINTK("svc_addparty added wait queue\n");
while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) {
schedule();
- prepare_to_wait(vcc->sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
+ prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
}
- finish_wait(vcc->sk->sk_sleep, &wait);
- error = xchg(&vcc->sk->sk_err_soft, 0);
+ finish_wait(sk->sk_sleep, &wait);
+ error = xchg(&sk->sk_err_soft, 0);
out:
- release_sock(vcc->sk);
+ release_sock(sk);
return error;
}
@@ -562,25 +564,26 @@ out:
static int svc_dropparty(struct socket *sock, int ep_ref)
{
DEFINE_WAIT(wait);
+ struct sock *sk = sock->sk;
struct atm_vcc *vcc = ATM_SD(sock);
int error;
- lock_sock(vcc->sk);
+ lock_sock(sk);
set_bit(ATM_VF_WAITING, &vcc->flags);
- prepare_to_wait(vcc->sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
+ prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
sigd_enq2(vcc, as_dropparty, NULL, NULL, NULL, NULL, ep_ref);
while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) {
schedule();
- prepare_to_wait(vcc->sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
+ prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
}
- finish_wait(vcc->sk->sk_sleep, &wait);
+ finish_wait(sk->sk_sleep, &wait);
if (!sigd) {
error = -EUNATCH;
goto out;
}
- error = xchg(&vcc->sk->sk_err_soft, 0);
+ error = xchg(&sk->sk_err_soft, 0);
out:
- release_sock(vcc->sk);
+ release_sock(sk);
return error;
}
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
index 974d029f46e2d..fbef221c2f657 100644
--- a/net/ax25/af_ax25.c
+++ b/net/ax25/af_ax25.c
@@ -180,8 +180,7 @@ struct sock *ax25_get_socket(ax25_address *my_addr, ax25_address *dest_addr,
!ax25cmp(&s->dest_addr, dest_addr) &&
s->sk->sk_type == type) {
sk = s->sk;
- /* XXX Sleeps with spinlock held, use refcounts instead. XXX */
- lock_sock(sk);
+ sock_hold(sk);
break;
}
}
@@ -307,9 +306,7 @@ void ax25_destroy_socket(ax25_cb *ax25)
kfree_skb(skb);
}
- while ((skb = skb_dequeue(&ax25->sk->sk_write_queue)) != NULL) {
- kfree_skb(skb);
- }
+ skb_queue_purge(&ax25->sk->sk_write_queue);
}
if (ax25->sk != NULL) {
@@ -868,10 +865,14 @@ struct sock *ax25_make_new(struct sock *osk, struct ax25_dev *ax25_dev)
sk->sk_protocol = osk->sk_protocol;
sk->sk_rcvbuf = osk->sk_rcvbuf;
sk->sk_sndbuf = osk->sk_sndbuf;
- sk->sk_debug = osk->sk_debug;
sk->sk_state = TCP_ESTABLISHED;
sk->sk_sleep = osk->sk_sleep;
- sk->sk_zapped = osk->sk_zapped;
+
+ if (sock_flag(osk, SOCK_DBG))
+ sock_set_flag(sk, SOCK_DBG);
+
+ if (sock_flag(osk, SOCK_ZAPPED))
+ sock_set_flag(sk, SOCK_ZAPPED);
oax25 = ax25_sk(osk);
@@ -1025,7 +1026,7 @@ static int ax25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
lock_sock(sk);
ax25 = ax25_sk(sk);
- if (!sk->sk_zapped) {
+ if (!sock_flag(sk, SOCK_ZAPPED)) {
err = -EINVAL;
goto out;
}
@@ -1059,7 +1060,7 @@ static int ax25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
done:
ax25_cb_add(ax25);
- sk->sk_zapped = 0;
+ sock_reset_flag(sk, SOCK_ZAPPED);
out:
release_sock(sk);
@@ -1172,7 +1173,7 @@ static int ax25_connect(struct socket *sock, struct sockaddr *uaddr,
* the socket is already bound, check to see if the device has
* been filled in, error if it hasn't.
*/
- if (sk->sk_zapped) {
+ if (sock_flag(sk, SOCK_ZAPPED)) {
/* check if we can remove this feature. It is broken. */
printk(KERN_WARNING "ax25_connect(): %s uses autobind, please contact jreuter@yaina.de\n",
current->comm);
@@ -1420,7 +1421,7 @@ static int ax25_sendmsg(struct kiocb *iocb, struct socket *sock,
lock_sock(sk);
ax25 = ax25_sk(sk);
- if (sk->sk_zapped) {
+ if (sock_flag(sk, SOCK_ZAPPED)) {
err = -EADDRNOTAVAIL;
goto out;
}
diff --git a/net/ax25/ax25_in.c b/net/ax25/ax25_in.c
index 01a2c865a36ad..3dc808fde33ff 100644
--- a/net/ax25/ax25_in.c
+++ b/net/ax25/ax25_in.c
@@ -275,6 +275,7 @@ static int ax25_rcv(struct sk_buff *skb, struct net_device *dev,
/* Now find a suitable dgram socket */
sk = ax25_get_socket(&dest, &src, SOCK_DGRAM);
if (sk != NULL) {
+ bh_lock_sock(sk);
if (atomic_read(&sk->sk_rmem_alloc) >=
sk->sk_rcvbuf) {
kfree_skb(skb);
@@ -286,7 +287,8 @@ static int ax25_rcv(struct sk_buff *skb, struct net_device *dev,
if (sock_queue_rcv_skb(sk, skb) != 0)
kfree_skb(skb);
}
- release_sock(sk);
+ bh_unlock_sock(sk);
+ sock_put(sk);
} else {
kfree_skb(skb);
}
@@ -356,7 +358,7 @@ static int ax25_rcv(struct sk_buff *skb, struct net_device *dev,
if (sk != NULL) {
bh_lock_sock(sk);
- if (sk->sk_ack_backlog == sk->sk_max_ack_backlog ||
+ if (sk_acceptq_is_full(sk) ||
(make = ax25_make_new(sk, ax25_dev)) == NULL) {
if (mine)
ax25_return_dm(dev, &src, &dest, &dp);
diff --git a/net/ax25/ax25_route.c b/net/ax25/ax25_route.c
index 706e729f6859c..44b99b1ff9f8c 100644
--- a/net/ax25/ax25_route.c
+++ b/net/ax25/ax25_route.c
@@ -455,7 +455,7 @@ int ax25_rt_autobind(ax25_cb *ax25, ax25_address *addr)
if (ax25->sk != NULL) {
bh_lock_sock(ax25->sk);
- ax25->sk->sk_zapped = 0;
+ sock_reset_flag(ax25->sk, SOCK_ZAPPED);
bh_unlock_sock(ax25->sk);
}
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c
index 8ff58bc2bf275..1650c6bf6997e 100644
--- a/net/bluetooth/af_bluetooth.c
+++ b/net/bluetooth/af_bluetooth.c
@@ -60,11 +60,9 @@ EXPORT_SYMBOL(proc_bt);
#define BT_MAX_PROTO 8
static struct net_proto_family *bt_proto[BT_MAX_PROTO];
-static kmem_cache_t *bt_sock_cache;
-
int bt_sock_register(int proto, struct net_proto_family *ops)
{
- if (proto >= BT_MAX_PROTO)
+ if (proto < 0 || proto >= BT_MAX_PROTO)
return -EINVAL;
if (bt_proto[proto])
@@ -77,7 +75,7 @@ EXPORT_SYMBOL(bt_sock_register);
int bt_sock_unregister(int proto)
{
- if (proto >= BT_MAX_PROTO)
+ if (proto < 0 || proto >= BT_MAX_PROTO)
return -EINVAL;
if (!bt_proto[proto])
@@ -92,7 +90,7 @@ static int bt_sock_create(struct socket *sock, int proto)
{
int err = 0;
- if (proto >= BT_MAX_PROTO)
+ if (proto < 0 || proto >= BT_MAX_PROTO)
return -EINVAL;
#if defined(CONFIG_KMOD)
@@ -108,36 +106,6 @@ static int bt_sock_create(struct socket *sock, int proto)
return err;
}
-struct sock *bt_sock_alloc(struct socket *sock, int proto, int pi_size, int prio)
-{
- struct sock *sk;
- void *pi;
-
- sk = sk_alloc(PF_BLUETOOTH, prio, sizeof(struct bt_sock), bt_sock_cache);
- if (!sk)
- return NULL;
-
- if (pi_size) {
- pi = kmalloc(pi_size, prio);
- if (!pi) {
- sk_free(sk);
- return NULL;
- }
- memset(pi, 0, pi_size);
- sk->sk_protinfo = pi;
- }
-
- sock_init_data(sock, sk);
- INIT_LIST_HEAD(&bt_sk(sk)->accept_q);
-
- sk->sk_zapped = 0;
- sk->sk_protocol = proto;
- sk->sk_state = BT_OPEN;
-
- return sk;
-}
-EXPORT_SYMBOL(bt_sock_alloc);
-
void bt_sock_link(struct bt_sock_list *l, struct sock *sk)
{
write_lock_bh(&l->lock);
@@ -355,16 +323,6 @@ static int __init bt_init(void)
if (proc_bt)
proc_bt->owner = THIS_MODULE;
- /* Init socket cache */
- bt_sock_cache = kmem_cache_create("bt_sock",
- sizeof(struct bt_sock), 0,
- SLAB_HWCACHE_ALIGN, NULL, NULL);
-
- if (!bt_sock_cache) {
- BT_ERR("Socket cache creation failed");
- return -ENOMEM;
- }
-
sock_register(&bt_sock_family_ops);
BT_INFO("HCI device and connection manager initialized");
@@ -383,7 +341,6 @@ static void __exit bt_exit(void)
bt_sysfs_cleanup();
sock_unregister(PF_BLUETOOTH);
- kmem_cache_destroy(bt_sock_cache);
remove_proc_entry("bluetooth", NULL);
}
diff --git a/net/bluetooth/bnep/sock.c b/net/bluetooth/bnep/sock.c
index 990e503a1ff15..b17a39ee8161f 100644
--- a/net/bluetooth/bnep/sock.c
+++ b/net/bluetooth/bnep/sock.c
@@ -176,17 +176,22 @@ static int bnep_sock_create(struct socket *sock, int protocol)
if (sock->type != SOCK_RAW)
return -ESOCKTNOSUPPORT;
- if (!(sk = bt_sock_alloc(sock, PF_BLUETOOTH, 0, GFP_KERNEL)))
+ if (!(sk = sk_alloc(PF_BLUETOOTH, GFP_KERNEL, sizeof(struct bt_sock), NULL)))
return -ENOMEM;
+ sock_init_data(sock, sk);
+
sk_set_owner(sk, THIS_MODULE);
sock->ops = &bnep_sock_ops;
- sock->state = SS_UNCONNECTED;
+ sock->state = SS_UNCONNECTED;
+
+ sock_reset_flag(sk, SOCK_ZAPPED);
- sk->sk_destruct = NULL;
sk->sk_protocol = protocol;
+ sk->sk_state = BT_OPEN;
+
return 0;
}
diff --git a/net/bluetooth/cmtp/sock.c b/net/bluetooth/cmtp/sock.c
index bf4e7d7840228..e4beaad22adf6 100644
--- a/net/bluetooth/cmtp/sock.c
+++ b/net/bluetooth/cmtp/sock.c
@@ -167,17 +167,21 @@ static int cmtp_sock_create(struct socket *sock, int protocol)
if (sock->type != SOCK_RAW)
return -ESOCKTNOSUPPORT;
- if (!(sk = bt_sock_alloc(sock, PF_BLUETOOTH, 0, GFP_KERNEL)))
+ if (!(sk = sk_alloc(PF_BLUETOOTH, GFP_KERNEL, sizeof(struct bt_sock), NULL)))
return -ENOMEM;
+ sock_init_data(sock, sk);
+
sk_set_owner(sk, THIS_MODULE);
sock->ops = &cmtp_sock_ops;
sock->state = SS_UNCONNECTED;
- sk->sk_destruct = NULL;
+ sock_reset_flag(sk, SOCK_ZAPPED);
+
sk->sk_protocol = protocol;
+ sk->sk_state = BT_OPEN;
return 0;
}
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index a2bd4b1c19da3..71762d7e99701 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -348,6 +348,24 @@ int hci_conn_change_link_key(struct hci_conn *conn)
}
EXPORT_SYMBOL(hci_conn_change_link_key);
+/* Switch role */
+int hci_conn_switch_role(struct hci_conn *conn, uint8_t role)
+{
+ BT_DBG("conn %p", conn);
+
+ if (!role && conn->link_mode & HCI_LM_MASTER)
+ return 1;
+
+ if (!test_and_set_bit(HCI_CONN_RSWITCH_PEND, &conn->pend)) {
+ struct hci_cp_switch_role cp;
+ bacpy(&cp.bdaddr, &conn->dst);
+ cp.role = role;
+ hci_send_cmd(conn->hdev, OGF_LINK_POLICY, OCF_SWITCH_ROLE, sizeof(cp), &cp);
+ }
+ return 0;
+}
+EXPORT_SYMBOL(hci_conn_switch_role);
+
/* Drop all connection on the device */
void hci_conn_hash_flush(struct hci_dev *hdev)
{
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 47a1e90add303..8ccba8ee99795 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -718,17 +718,20 @@ static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb
BT_DBG("%s status %d", hdev->name, ev->status);
- if (ev->status)
- return;
-
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
if (conn) {
- if (ev->role)
- conn->link_mode &= ~HCI_LM_MASTER;
- else
- conn->link_mode |= HCI_LM_MASTER;
+ if (!ev->status) {
+ if (ev->role)
+ conn->link_mode &= ~HCI_LM_MASTER;
+ else
+ conn->link_mode |= HCI_LM_MASTER;
+ }
+
+ clear_bit(HCI_CONN_RSWITCH_PEND, &conn->pend);
+
+ hci_role_switch_cfm(conn, ev->status, ev->role);
}
hci_dev_unlock(hdev);
@@ -749,6 +752,7 @@ static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *s
if (conn) {
if (!ev->status)
conn->link_mode |= HCI_LM_AUTH;
+
clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
hci_auth_cfm(conn, ev->status);
@@ -790,6 +794,7 @@ static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *
else
conn->link_mode &= ~HCI_LM_ENCRYPT;
}
+
clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
hci_encrypt_cfm(conn, ev->status, ev->encrypt);
@@ -801,6 +806,25 @@ static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *
/* Change Connection Link Key Complete */
static inline void hci_change_conn_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
+ struct hci_ev_change_conn_link_key_complete *ev = (struct hci_ev_change_conn_link_key_complete *) skb->data;
+ struct hci_conn *conn = NULL;
+ __u16 handle = __le16_to_cpu(ev->handle);
+
+ BT_DBG("%s status %d", hdev->name, ev->status);
+
+ hci_dev_lock(hdev);
+
+ conn = hci_conn_hash_lookup_handle(hdev, handle);
+ if (conn) {
+ if (!ev->status)
+ conn->link_mode |= HCI_LM_SECURE;
+
+ clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
+
+ hci_key_change_cfm(conn, ev->status);
+ }
+
+ hci_dev_unlock(hdev);
}
/* Pin Code Request*/
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
index 7fe6b9ff9408b..841bdba0b877a 100644
--- a/net/bluetooth/hci_sock.c
+++ b/net/bluetooth/hci_sock.c
@@ -601,10 +601,16 @@ static int hci_sock_create(struct socket *sock, int protocol)
sock->ops = &hci_sock_ops;
- sk = bt_sock_alloc(sock, protocol, sizeof(struct hci_pinfo), GFP_KERNEL);
+ sk = sk_alloc(PF_BLUETOOTH, GFP_KERNEL, sizeof(struct hci_pinfo), NULL);
if (!sk)
return -ENOMEM;
+ sock_init_data(sock, sk);
+
+ sock_reset_flag(sk, SOCK_ZAPPED);
+
+ sk->sk_protocol = protocol;
+
sk_set_owner(sk, THIS_MODULE);
sock->state = SS_UNCONNECTED;
diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c
index 0fc90e3ebc78f..7856bc26accb2 100644
--- a/net/bluetooth/hci_sysfs.c
+++ b/net/bluetooth/hci_sysfs.c
@@ -55,7 +55,7 @@ static ssize_t show_inquiry_cache(struct class_device *cdev, char *buf)
batostr(&bdaddr),
data->pscan_rep_mode, data->pscan_period_mode, data->pscan_mode,
data->dev_class[2], data->dev_class[1], data->dev_class[0],
- data->clock_offset, data->rssi, e->timestamp);
+ __le16_to_cpu(data->clock_offset), data->rssi, e->timestamp);
}
hci_dev_unlock_bh(hdev);
diff --git a/net/bluetooth/hidp/sock.c b/net/bluetooth/hidp/sock.c
index 315f4354f052a..dc642f667eea5 100644
--- a/net/bluetooth/hidp/sock.c
+++ b/net/bluetooth/hidp/sock.c
@@ -173,17 +173,21 @@ static int hidp_sock_create(struct socket *sock, int protocol)
if (sock->type != SOCK_RAW)
return -ESOCKTNOSUPPORT;
- if (!(sk = bt_sock_alloc(sock, PF_BLUETOOTH, 0, GFP_KERNEL)))
+ if (!(sk = sk_alloc(PF_BLUETOOTH, GFP_KERNEL, sizeof(struct bt_sock), NULL)))
return -ENOMEM;
+ sock_init_data(sock, sk);
+
sk_set_owner(sk, THIS_MODULE);
sock->ops = &hidp_sock_ops;
sock->state = SS_UNCONNECTED;
- sk->sk_destruct = NULL;
+ sock_reset_flag(sk, SOCK_ZAPPED);
+
sk->sk_protocol = protocol;
+ sk->sk_state = BT_OPEN;
return 0;
}
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index ff8d31015211d..59b58661c1a82 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -264,9 +264,6 @@ static void l2cap_sock_destruct(struct sock *sk)
skb_queue_purge(&sk->sk_receive_queue);
skb_queue_purge(&sk->sk_write_queue);
-
- if (sk->sk_protinfo)
- kfree(sk->sk_protinfo);
}
static void l2cap_sock_cleanup_listen(struct sock *parent)
@@ -280,7 +277,7 @@ static void l2cap_sock_cleanup_listen(struct sock *parent)
l2cap_sock_close(sk);
parent->sk_state = BT_CLOSED;
- parent->sk_zapped = 1;
+ sock_set_flag(parent, SOCK_ZAPPED);
}
/* Kill socket (only if zapped and orphan)
@@ -288,7 +285,7 @@ static void l2cap_sock_cleanup_listen(struct sock *parent)
*/
static void l2cap_sock_kill(struct sock *sk)
{
- if (!sk->sk_zapped || sk->sk_socket)
+ if (!sock_flag(sk, SOCK_ZAPPED) || sk->sk_socket)
return;
BT_DBG("sk %p state %d", sk, sk->sk_state);
@@ -333,7 +330,7 @@ static void __l2cap_sock_close(struct sock *sk, int reason)
break;
default:
- sk->sk_zapped = 1;
+ sock_set_flag(sk, SOCK_ZAPPED);
break;
}
}
@@ -374,15 +371,20 @@ static struct sock *l2cap_sock_alloc(struct socket *sock, int proto, int prio)
{
struct sock *sk;
- sk = bt_sock_alloc(sock, proto, sizeof(struct l2cap_pinfo), prio);
+ sk = sk_alloc(PF_BLUETOOTH, prio, sizeof(struct l2cap_pinfo), NULL);
if (!sk)
return NULL;
+ sock_init_data(sock, sk);
+ INIT_LIST_HEAD(&bt_sk(sk)->accept_q);
+
sk_set_owner(sk, THIS_MODULE);
sk->sk_destruct = l2cap_sock_destruct;
sk->sk_sndtimeo = L2CAP_CONN_TIMEOUT;
+ sock_reset_flag(sk, SOCK_ZAPPED);
+
sk->sk_protocol = proto;
sk->sk_state = BT_OPEN;
@@ -1062,7 +1064,7 @@ static void l2cap_chan_del(struct sock *sk, int err)
}
sk->sk_state = BT_CLOSED;
- sk->sk_zapped = 1;
+ sock_set_flag(sk, SOCK_ZAPPED);
if (err)
sk->sk_err = err;
@@ -1410,7 +1412,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
result = L2CAP_CR_NO_MEM;
/* Check for backlog size */
- if (parent->sk_ack_backlog > parent->sk_max_ack_backlog) {
+ if (sk_acceptq_is_full(parent)) {
BT_DBG("backlog full %d", parent->sk_ack_backlog);
goto response;
}
@@ -1424,7 +1426,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
/* Check if we already have channel with that dcid */
if (__l2cap_get_chan_by_dcid(list, scid)) {
write_unlock(&list->lock);
- sk->sk_zapped = 1;
+ sock_set_flag(sk, SOCK_ZAPPED);
l2cap_sock_kill(sk);
goto response;
}
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
index 061677e9cba08..e9e6fda66f1a3 100644
--- a/net/bluetooth/rfcomm/core.c
+++ b/net/bluetooth/rfcomm/core.c
@@ -68,7 +68,7 @@ static DECLARE_MUTEX(rfcomm_sem);
#define rfcomm_lock() down(&rfcomm_sem);
#define rfcomm_unlock() up(&rfcomm_sem);
-unsigned long rfcomm_event;
+static unsigned long rfcomm_event;
static LIST_HEAD(session_list);
static atomic_t terminate, running;
@@ -389,6 +389,8 @@ static int __rfcomm_dlc_close(struct rfcomm_dlc *d, int err)
rfcomm_dlc_unlock(d);
skb_queue_purge(&d->tx_queue);
+ rfcomm_session_put(s);
+
rfcomm_dlc_unlink(d);
}
@@ -598,6 +600,8 @@ static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src, bdaddr_t *dst
goto failed;
}
+ rfcomm_session_hold(s);
+
s->initiator = 1;
bacpy(&addr.l2_bdaddr, dst);
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
index a4cd20072daa0..097e007cd9b0d 100644
--- a/net/bluetooth/rfcomm/sock.c
+++ b/net/bluetooth/rfcomm/sock.c
@@ -105,7 +105,7 @@ static void rfcomm_sk_state_change(struct rfcomm_dlc *d, int err)
parent = bt_sk(sk)->parent;
if (parent) {
if (d->state == BT_CLOSED) {
- sk->sk_zapped = 1;
+ sock_set_flag(sk, SOCK_ZAPPED);
bt_accept_unlink(sk);
}
parent->sk_data_ready(parent, 0);
@@ -117,7 +117,7 @@ static void rfcomm_sk_state_change(struct rfcomm_dlc *d, int err)
bh_unlock_sock(sk);
- if (parent && sk->sk_zapped) {
+ if (parent && sock_flag(sk, SOCK_ZAPPED)) {
/* We have to drop DLC lock here, otherwise
* rfcomm_sock_destruct() will dead lock. */
rfcomm_dlc_unlock(d);
@@ -196,9 +196,6 @@ static void rfcomm_sock_destruct(struct sock *sk)
rfcomm_dlc_unlock(d);
rfcomm_dlc_put(d);
-
- if (sk->sk_protinfo)
- kfree(sk->sk_protinfo);
}
static void rfcomm_sock_cleanup_listen(struct sock *parent)
@@ -214,7 +211,7 @@ static void rfcomm_sock_cleanup_listen(struct sock *parent)
}
parent->sk_state = BT_CLOSED;
- parent->sk_zapped = 1;
+ sock_set_flag(parent, SOCK_ZAPPED);
}
/* Kill socket (only if zapped and orphan)
@@ -222,7 +219,7 @@ static void rfcomm_sock_cleanup_listen(struct sock *parent)
*/
static void rfcomm_sock_kill(struct sock *sk)
{
- if (!sk->sk_zapped || sk->sk_socket)
+ if (!sock_flag(sk, SOCK_ZAPPED) || sk->sk_socket)
return;
BT_DBG("sk %p state %d refcnt %d", sk, sk->sk_state, atomic_read(&sk->sk_refcnt));
@@ -251,7 +248,7 @@ static void __rfcomm_sock_close(struct sock *sk)
rfcomm_dlc_close(d, 0);
default:
- sk->sk_zapped = 1;
+ sock_set_flag(sk, SOCK_ZAPPED);
break;
}
}
@@ -287,10 +284,13 @@ static struct sock *rfcomm_sock_alloc(struct socket *sock, int proto, int prio)
struct rfcomm_dlc *d;
struct sock *sk;
- sk = bt_sock_alloc(sock, BTPROTO_RFCOMM, sizeof(struct rfcomm_pinfo), prio);
+ sk = sk_alloc(PF_BLUETOOTH, prio, sizeof(struct rfcomm_pinfo), NULL);
if (!sk)
return NULL;
+ sock_init_data(sock, sk);
+ INIT_LIST_HEAD(&bt_sk(sk)->accept_q);
+
sk_set_owner(sk, THIS_MODULE);
d = rfcomm_dlc_alloc(prio);
@@ -298,6 +298,7 @@ static struct sock *rfcomm_sock_alloc(struct socket *sock, int proto, int prio)
sk_free(sk);
return NULL;
}
+
d->data_ready = rfcomm_sk_data_ready;
d->state_change = rfcomm_sk_state_change;
@@ -310,8 +311,10 @@ static struct sock *rfcomm_sock_alloc(struct socket *sock, int proto, int prio)
sk->sk_sndbuf = RFCOMM_MAX_CREDITS * RFCOMM_DEFAULT_MTU * 10;
sk->sk_rcvbuf = RFCOMM_MAX_CREDITS * RFCOMM_DEFAULT_MTU * 10;
+ sock_reset_flag(sk, SOCK_ZAPPED);
+
sk->sk_protocol = proto;
- sk->sk_state = BT_OPEN;
+ sk->sk_state = BT_OPEN;
bt_sock_link(&rfcomm_sk_list, sk);
@@ -832,7 +835,7 @@ int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc *
return 0;
/* Check for backlog size */
- if (parent->sk_ack_backlog > parent->sk_max_ack_backlog) {
+ if (sk_acceptq_is_full(parent)) {
BT_DBG("backlog full %d", parent->sk_ack_backlog);
goto done;
}
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index ac01c408238e5..d1361367d7495 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -334,9 +334,6 @@ static void sco_sock_destruct(struct sock *sk)
skb_queue_purge(&sk->sk_receive_queue);
skb_queue_purge(&sk->sk_write_queue);
-
- if (sk->sk_protinfo)
- kfree(sk->sk_protinfo);
}
static void sco_sock_cleanup_listen(struct sock *parent)
@@ -352,7 +349,7 @@ static void sco_sock_cleanup_listen(struct sock *parent)
}
parent->sk_state = BT_CLOSED;
- parent->sk_zapped = 1;
+ sock_set_flag(sk, SOCK_ZAPPED);
}
/* Kill socket (only if zapped and orphan)
@@ -360,7 +357,7 @@ static void sco_sock_cleanup_listen(struct sock *parent)
*/
static void sco_sock_kill(struct sock *sk)
{
- if (!sk->sk_zapped || sk->sk_socket)
+ if (!sock_flag(sk, SOCK_ZAPPED) || sk->sk_socket)
return;
BT_DBG("sk %p state %d", sk, sk->sk_state);
@@ -399,7 +396,7 @@ static void sco_sock_close(struct sock *sk)
break;
default:
- sk->sk_zapped = 1;
+ sock_set_flag(sk, SOCK_ZAPPED);
break;
};
@@ -420,14 +417,21 @@ static struct sock *sco_sock_alloc(struct socket *sock, int proto, int prio)
{
struct sock *sk;
- sk = bt_sock_alloc(sock, proto, sizeof(struct sco_pinfo), prio);
+ sk = sk_alloc(PF_BLUETOOTH, prio, sizeof(struct sco_pinfo), NULL);
if (!sk)
return NULL;
+ sock_init_data(sock, sk);
+ INIT_LIST_HEAD(&bt_sk(sk)->accept_q);
+
sk_set_owner(sk, THIS_MODULE);
sk->sk_destruct = sco_sock_destruct;
sk->sk_sndtimeo = SCO_CONN_TIMEOUT;
+
+ sock_reset_flag(sk, SOCK_ZAPPED);
+
+ sk->sk_protocol = proto;
sk->sk_state = BT_OPEN;
sco_sock_init_timer(sk);
@@ -778,7 +782,7 @@ static void sco_chan_del(struct sock *sk, int err)
sk->sk_err = err;
sk->sk_state_change(sk);
- sk->sk_zapped = 1;
+ sock_set_flag(sk, SOCK_ZAPPED);
}
static void sco_conn_ready(struct sco_conn *conn)
diff --git a/net/bridge/br.c b/net/bridge/br.c
index 675d0709a0691..f8f184942aaf4 100644
--- a/net/bridge/br.c
+++ b/net/bridge/br.c
@@ -16,17 +16,12 @@
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
-#include <linux/miscdevice.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/init.h>
#include "br_private.h"
-#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
-#include "../atm/lec.h"
-#endif
-
int (*br_should_route_hook) (struct sk_buff **pskb) = NULL;
static int __init br_init(void)
@@ -40,10 +35,9 @@ static int __init br_init(void)
brioctl_set(br_ioctl_deviceless_stub);
br_handle_frame_hook = br_handle_frame;
-#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
br_fdb_get_hook = br_fdb_get;
br_fdb_put_hook = br_fdb_put;
-#endif
+
register_netdevice_notifier(&br_device_notifier);
return 0;
@@ -61,10 +55,8 @@ static void __exit br_deinit(void)
synchronize_net();
-#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
br_fdb_get_hook = NULL;
br_fdb_put_hook = NULL;
-#endif
br_handle_frame_hook = NULL;
br_fdb_fini();
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index 44a976221318f..d9b72fde433c4 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -83,11 +83,6 @@ static int br_change_mtu(struct net_device *dev, int new_mtu)
return 0;
}
-static int br_dev_accept_fastpath(struct net_device *dev, struct dst_entry *dst)
-{
- return -1;
-}
-
void br_dev_setup(struct net_device *dev)
{
memset(dev->dev_addr, 0, ETH_ALEN);
@@ -103,7 +98,6 @@ void br_dev_setup(struct net_device *dev)
dev->destructor = free_netdev;
SET_MODULE_OWNER(dev);
dev->stop = br_dev_stop;
- dev->accept_fastpath = br_dev_accept_fastpath;
dev->tx_queue_len = 0;
dev->set_mac_address = NULL;
dev->priv_flags = IFF_EBRIDGE;
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
index 940699997793d..e6c2200b7ca3f 100644
--- a/net/bridge/br_fdb.c
+++ b/net/bridge/br_fdb.c
@@ -19,12 +19,13 @@
#include <linux/times.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
+#include <linux/jhash.h>
#include <asm/atomic.h>
#include "br_private.h"
static kmem_cache_t *br_fdb_cache;
static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source,
- const unsigned char *addr, int is_local);
+ const unsigned char *addr);
void __init br_fdb_init(void)
{
@@ -57,26 +58,12 @@ static __inline__ int has_expired(const struct net_bridge *br,
static __inline__ int br_mac_hash(const unsigned char *mac)
{
- unsigned long x;
-
- x = mac[0];
- x = (x << 2) ^ mac[1];
- x = (x << 2) ^ mac[2];
- x = (x << 2) ^ mac[3];
- x = (x << 2) ^ mac[4];
- x = (x << 2) ^ mac[5];
-
- x ^= x >> 8;
-
- return x & (BR_HASH_SIZE - 1);
+ return jhash(mac, ETH_ALEN, 0) & (BR_HASH_SIZE - 1);
}
static __inline__ void fdb_delete(struct net_bridge_fdb_entry *f)
{
hlist_del_rcu(&f->hlist);
- if (!f->is_static)
- list_del(&f->u.age_list);
-
br_fdb_put(f);
}
@@ -114,8 +101,7 @@ void br_fdb_changeaddr(struct net_bridge_port *p, const unsigned char *newaddr)
}
insert:
/* insert new address, may fail if invalid address or dup. */
- fdb_insert(br, p, newaddr, 1);
-
+ fdb_insert(br, p, newaddr);
spin_unlock_bh(&br->hash_lock);
}
@@ -123,30 +109,23 @@ void br_fdb_changeaddr(struct net_bridge_port *p, const unsigned char *newaddr)
void br_fdb_cleanup(unsigned long _data)
{
struct net_bridge *br = (struct net_bridge *)_data;
- struct list_head *l, *n;
- unsigned long delay;
+ unsigned long delay = hold_time(br);
+ int i;
spin_lock_bh(&br->hash_lock);
- delay = hold_time(br);
-
- list_for_each_safe(l, n, &br->age_list) {
+ for (i = 0; i < BR_HASH_SIZE; i++) {
struct net_bridge_fdb_entry *f;
- unsigned long expires;
-
- f = list_entry(l, struct net_bridge_fdb_entry, u.age_list);
- expires = f->ageing_timer + delay;
+ struct hlist_node *h, *n;
- if (time_before_eq(expires, jiffies)) {
- WARN_ON(f->is_static);
- pr_debug("expire age %lu jiffies %lu\n",
- f->ageing_timer, jiffies);
- fdb_delete(f);
- } else {
- mod_timer(&br->gc_timer, expires);
- break;
+ hlist_for_each_entry_safe(f, h, n, &br->hash[i], hlist) {
+ if (!f->is_static &&
+ time_before_eq(f->ageing_timer + delay, jiffies))
+ fdb_delete(f);
}
}
spin_unlock_bh(&br->hash_lock);
+
+ mod_timer(&br->gc_timer, jiffies + HZ/10);
}
void br_fdb_delete_by_port(struct net_bridge *br, struct net_bridge_port *p)
@@ -222,7 +201,7 @@ struct net_bridge_fdb_entry *br_fdb_get(struct net_bridge *br,
static void fdb_rcu_free(struct rcu_head *head)
{
struct net_bridge_fdb_entry *ent
- = container_of(head, struct net_bridge_fdb_entry, u.rcu);
+ = container_of(head, struct net_bridge_fdb_entry, rcu);
kmem_cache_free(br_fdb_cache, ent);
}
@@ -230,7 +209,7 @@ static void fdb_rcu_free(struct rcu_head *head)
void br_fdb_put(struct net_bridge_fdb_entry *ent)
{
if (atomic_dec_and_test(&ent->use_count))
- call_rcu(&ent->u.rcu, fdb_rcu_free);
+ call_rcu(&ent->rcu, fdb_rcu_free);
}
/*
@@ -278,80 +257,112 @@ int br_fdb_fillbuf(struct net_bridge *br, void *buf,
return num;
}
-static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source,
- const unsigned char *addr, int is_local)
+static inline struct net_bridge_fdb_entry *fdb_find(struct hlist_head *head,
+ const unsigned char *addr)
{
struct hlist_node *h;
struct net_bridge_fdb_entry *fdb;
- int hash = br_mac_hash(addr);
-
- if (!is_valid_ether_addr(addr))
- return -EADDRNOTAVAIL;
-
- hlist_for_each_entry(fdb, h, &br->hash[hash], hlist) {
- if (!memcmp(fdb->addr.addr, addr, ETH_ALEN)) {
- /* attempt to update an entry for a local interface */
- if (fdb->is_local) {
- /* it is okay to have multiple ports with same
- * address, just don't allow to be spoofed.
- */
- if (is_local)
- return 0;
-
- if (net_ratelimit())
- printk(KERN_WARNING "%s: received packet with "
- " own address as source address\n",
- source->dev->name);
- return -EEXIST;
- }
- if (is_local) {
- printk(KERN_WARNING "%s adding interface with same address "
- "as a received packet\n",
- source->dev->name);
- goto update;
- }
+ hlist_for_each_entry_rcu(fdb, h, head, hlist) {
+ if (!memcmp(fdb->addr.addr, addr, ETH_ALEN))
+ return fdb;
+ }
+ return NULL;
+}
- if (fdb->is_static)
- return 0;
+static struct net_bridge_fdb_entry *fdb_create(struct hlist_head *head,
+ struct net_bridge_port *source,
+ const unsigned char *addr,
+ int is_local)
+{
+ struct net_bridge_fdb_entry *fdb;
- /* move to end of age list */
- list_del(&fdb->u.age_list);
- goto update;
- }
+ fdb = kmem_cache_alloc(br_fdb_cache, GFP_ATOMIC);
+ if (fdb) {
+ memcpy(fdb->addr.addr, addr, ETH_ALEN);
+ atomic_set(&fdb->use_count, 1);
+ hlist_add_head_rcu(&fdb->hlist, head);
+
+ fdb->dst = source;
+ fdb->is_local = is_local;
+ fdb->is_static = is_local;
+ fdb->ageing_timer = jiffies;
}
+ return fdb;
+}
- fdb = kmem_cache_alloc(br_fdb_cache, GFP_ATOMIC);
- if (!fdb)
- return ENOMEM;
+static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source,
+ const unsigned char *addr)
+{
+ struct hlist_head *head = &br->hash[br_mac_hash(addr)];
+ struct net_bridge_fdb_entry *fdb;
- memcpy(fdb->addr.addr, addr, ETH_ALEN);
- atomic_set(&fdb->use_count, 1);
- hlist_add_head_rcu(&fdb->hlist, &br->hash[hash]);
+ if (!is_valid_ether_addr(addr))
+ return -EINVAL;
- if (!timer_pending(&br->gc_timer)) {
- br->gc_timer.expires = jiffies + hold_time(br);
- add_timer(&br->gc_timer);
- }
+ fdb = fdb_find(head, addr);
+ if (fdb) {
+ /* it is okay to have multiple ports with same
+ * address, just use the first one.
+ */
+ if (fdb->is_local)
+ return 0;
+
+ printk(KERN_WARNING "%s adding interface with same address "
+ "as a received packet\n",
+ source->dev->name);
+ fdb_delete(fdb);
+ }
- update:
- fdb->dst = source;
- fdb->is_local = is_local;
- fdb->is_static = is_local;
- fdb->ageing_timer = jiffies;
- if (!is_local)
- list_add_tail(&fdb->u.age_list, &br->age_list);
+ if (!fdb_create(head, source, addr, 1))
+ return -ENOMEM;
return 0;
}
int br_fdb_insert(struct net_bridge *br, struct net_bridge_port *source,
- const unsigned char *addr, int is_local)
+ const unsigned char *addr)
{
int ret;
spin_lock_bh(&br->hash_lock);
- ret = fdb_insert(br, source, addr, is_local);
+ ret = fdb_insert(br, source, addr);
spin_unlock_bh(&br->hash_lock);
return ret;
}
+
+void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source,
+ const unsigned char *addr)
+{
+ struct hlist_head *head = &br->hash[br_mac_hash(addr)];
+ struct net_bridge_fdb_entry *fdb;
+
+ /* some users want to always flood. */
+ if (hold_time(br) == 0)
+ return;
+
+ rcu_read_lock();
+ fdb = fdb_find(head, addr);
+ if (likely(fdb)) {
+ /* attempt to update an entry for a local interface */
+ if (unlikely(fdb->is_local)) {
+ if (net_ratelimit())
+ printk(KERN_WARNING "%s: received packet with "
+ " own address as source address\n",
+ source->dev->name);
+ } else {
+ /* fastpath: update of existing entry */
+ fdb->dst = source;
+ fdb->ageing_timer = jiffies;
+ }
+ } else {
+ spin_lock_bh(&br->hash_lock);
+ if (!fdb_find(head, addr))
+ fdb_create(head, source, addr, 0);
+ /* else we lose race and someone else inserts
+ * it first, don't bother updating
+ */
+ spin_unlock_bh(&br->hash_lock);
+ }
+ rcu_read_unlock();
+}
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index 080277bac10da..69872bf3b87e9 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -332,7 +332,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
if (IS_ERR(p = new_nbp(br, dev, br_initial_port_cost(dev))))
return PTR_ERR(p);
- if ((err = br_fdb_insert(br, p, dev->dev_addr, 1)))
+ if ((err = br_fdb_insert(br, p, dev->dev_addr)))
destroy_nbp(p);
else if ((err = br_sysfs_addif(p)))
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index 943d5ddc5f26e..2b1cce46cab42 100644
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -105,12 +105,12 @@ int br_handle_frame(struct net_bridge_port *p, struct sk_buff **pskb)
if (p->state == BR_STATE_DISABLED)
goto err;
- if (eth_hdr(skb)->h_source[0] & 1)
+ if (!is_valid_ether_addr(eth_hdr(skb)->h_source))
goto err;
if (p->state == BR_STATE_LEARNING ||
p->state == BR_STATE_FORWARDING)
- br_fdb_insert(p->br, p, eth_hdr(skb)->h_source, 0);
+ br_fdb_update(p->br, p, eth_hdr(skb)->h_source);
if (p->br->stp_enabled &&
!memcmp(dest, bridge_ula, 5) &&
diff --git a/net/bridge/br_ioctl.c b/net/bridge/br_ioctl.c
index 363c73f28b9b0..b8ce14b221816 100644
--- a/net/bridge/br_ioctl.c
+++ b/net/bridge/br_ioctl.c
@@ -324,6 +324,8 @@ static int old_deviceless(void __user *uarg)
int *indices;
int ret = 0;
+ if (args[2] >= 2048)
+ return -ENOMEM;
indices = kmalloc(args[2]*sizeof(int), GFP_KERNEL);
if (indices == NULL)
return -ENOMEM;
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index 3c34d7d2bd2da..be03d3ad26484 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -829,8 +829,7 @@ static unsigned int ip_sabotage_in(unsigned int hook, struct sk_buff **pskb,
{
if ((*pskb)->nf_bridge &&
!((*pskb)->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING)) {
- okfn(*pskb);
- return NF_STOLEN;
+ return NF_STOP;
}
return NF_ACCEPT;
@@ -891,8 +890,7 @@ static unsigned int ip_sabotage_out(unsigned int hook, struct sk_buff **pskb,
if (out->priv_flags & IFF_802_1Q_VLAN)
nf_bridge->netoutdev = (struct net_device *)out;
#endif
- okfn(skb);
- return NF_STOLEN;
+ return NF_STOP;
}
return NF_ACCEPT;
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index cecdba777dd9e..54d63f1372a0a 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -46,10 +46,8 @@ struct net_bridge_fdb_entry
{
struct hlist_node hlist;
struct net_bridge_port *dst;
- union {
- struct list_head age_list;
- struct rcu_head rcu;
- } u;
+
+ struct rcu_head rcu;
atomic_t use_count;
unsigned long ageing_timer;
mac_addr addr;
@@ -148,8 +146,10 @@ extern int br_fdb_fillbuf(struct net_bridge *br, void *buf,
unsigned long count, unsigned long off);
extern int br_fdb_insert(struct net_bridge *br,
struct net_bridge_port *source,
- const unsigned char *addr,
- int is_local);
+ const unsigned char *addr);
+extern void br_fdb_update(struct net_bridge *br,
+ struct net_bridge_port *source,
+ const unsigned char *addr);
/* br_forward.c */
extern void br_deliver(const struct net_bridge_port *to,
@@ -216,6 +216,12 @@ extern void br_stp_timer_init(struct net_bridge *br);
extern void br_stp_port_timer_init(struct net_bridge_port *p);
extern unsigned long br_timer_value(const struct timer_list *timer);
+/* br.c */
+extern struct net_bridge_fdb_entry *(*br_fdb_get_hook)(struct net_bridge *br,
+ unsigned char *addr);
+extern void (*br_fdb_put_hook)(struct net_bridge_fdb_entry *ent);
+
+
#ifdef CONFIG_SYSFS
/* br_sysfs_if.c */
extern int br_sysfs_addif(struct net_bridge_port *p);
diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c
index 6c08fefcc75d5..0da11ff05fa3a 100644
--- a/net/bridge/br_stp_if.c
+++ b/net/bridge/br_stp_if.c
@@ -49,6 +49,8 @@ void br_stp_enable_bridge(struct net_bridge *br)
spin_lock_bh(&br->lock);
mod_timer(&br->hello_timer, jiffies + br->hello_time);
+ mod_timer(&br->gc_timer, jiffies + HZ/10);
+
br_config_bpdu_generation(br);
list_for_each_entry(p, &br->port_list, list) {
@@ -78,6 +80,7 @@ void br_stp_disable_bridge(struct net_bridge *br)
del_timer_sync(&br->hello_timer);
del_timer_sync(&br->topology_change_timer);
del_timer_sync(&br->tcn_timer);
+ del_timer_sync(&br->gc_timer);
}
/* called under bridge lock */
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index 33dde2be31ba3..18ebc664769b1 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -179,9 +179,10 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff **pskb,
struct ebt_chainstack *cs;
struct ebt_entries *chaininfo;
char *base;
- struct ebt_table_info *private = table->private;
+ struct ebt_table_info *private;
read_lock_bh(&table->lock);
+ private = table->private;
cb_base = COUNTER_BASE(private->counters, private->nentries,
smp_processor_id());
if (private->chainstack)
@@ -822,10 +823,10 @@ static int translate_table(struct ebt_replace *repl,
/* this will get free'd in do_replace()/ebt_register_table()
if an error occurs */
newinfo->chainstack = (struct ebt_chainstack **)
- vmalloc(NR_CPUS * sizeof(struct ebt_chainstack));
+ vmalloc(num_possible_cpus() * sizeof(struct ebt_chainstack));
if (!newinfo->chainstack)
return -ENOMEM;
- for (i = 0; i < NR_CPUS; i++) {
+ for (i = 0; i < num_possible_cpus(); i++) {
newinfo->chainstack[i] =
vmalloc(udc_cnt * sizeof(struct ebt_chainstack));
if (!newinfo->chainstack[i]) {
@@ -898,7 +899,7 @@ static void get_counters(struct ebt_counter *oldcounters,
memcpy(counters, oldcounters,
sizeof(struct ebt_counter) * nentries);
/* add other counters to those of cpu 0 */
- for (cpu = 1; cpu < NR_CPUS; cpu++) {
+ for (cpu = 1; cpu < num_possible_cpus(); cpu++) {
counter_base = COUNTER_BASE(oldcounters, nentries, cpu);
for (i = 0; i < nentries; i++) {
counters[i].pcnt += counter_base[i].pcnt;
@@ -930,7 +931,7 @@ static int do_replace(void __user *user, unsigned int len)
BUGPRINT("Entries_size never zero\n");
return -EINVAL;
}
- countersize = COUNTER_OFFSET(tmp.nentries) * NR_CPUS;
+ countersize = COUNTER_OFFSET(tmp.nentries) * num_possible_cpus();
newinfo = (struct ebt_table_info *)
vmalloc(sizeof(struct ebt_table_info) + countersize);
if (!newinfo)
@@ -1023,7 +1024,7 @@ static int do_replace(void __user *user, unsigned int len)
vfree(table->entries);
if (table->chainstack) {
- for (i = 0; i < NR_CPUS; i++)
+ for (i = 0; i < num_possible_cpus(); i++)
vfree(table->chainstack[i]);
vfree(table->chainstack);
}
@@ -1043,7 +1044,7 @@ free_counterstmp:
vfree(counterstmp);
/* can be initialized in translate_table() */
if (newinfo->chainstack) {
- for (i = 0; i < NR_CPUS; i++)
+ for (i = 0; i < num_possible_cpus(); i++)
vfree(newinfo->chainstack[i]);
vfree(newinfo->chainstack);
}
@@ -1137,7 +1138,7 @@ int ebt_register_table(struct ebt_table *table)
return -EINVAL;
}
- countersize = COUNTER_OFFSET(table->table->nentries) * NR_CPUS;
+ countersize = COUNTER_OFFSET(table->table->nentries) * num_possible_cpus();
newinfo = (struct ebt_table_info *)
vmalloc(sizeof(struct ebt_table_info) + countersize);
ret = -ENOMEM;
@@ -1191,7 +1192,7 @@ free_unlock:
up(&ebt_mutex);
free_chainstack:
if (newinfo->chainstack) {
- for (i = 0; i < NR_CPUS; i++)
+ for (i = 0; i < num_possible_cpus(); i++)
vfree(newinfo->chainstack[i]);
vfree(newinfo->chainstack);
}
@@ -1215,7 +1216,7 @@ void ebt_unregister_table(struct ebt_table *table)
if (table->private->entries)
vfree(table->private->entries);
if (table->private->chainstack) {
- for (i = 0; i < NR_CPUS; i++)
+ for (i = 0; i < num_possible_cpus(); i++)
vfree(table->private->chainstack[i]);
vfree(table->private->chainstack);
}
diff --git a/net/core/dev.c b/net/core/dev.c
index 5d4abaa853510..42344d903692f 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1427,13 +1427,10 @@ int netif_rx(struct sk_buff *skb)
struct softnet_data *queue;
unsigned long flags;
-#ifdef CONFIG_NETPOLL
- if (skb->dev->netpoll_rx && netpoll_rx(skb)) {
- kfree_skb(skb);
+ /* if netpoll wants it, pretend we never saw it */
+ if (netpoll_rx(skb))
return NET_RX_DROP;
- }
-#endif
-
+
if (!skb->stamp.tv_sec)
net_timestamp(&skb->stamp);
@@ -1561,6 +1558,10 @@ static __inline__ int deliver_skb(struct sk_buff *skb,
#if defined(CONFIG_BRIDGE) || defined (CONFIG_BRIDGE_MODULE)
int (*br_handle_frame_hook)(struct net_bridge_port *p, struct sk_buff **pskb);
+struct net_bridge;
+struct net_bridge_fdb_entry *(*br_fdb_get_hook)(struct net_bridge *br,
+ unsigned char *addr);
+void (*br_fdb_put_hook)(struct net_bridge_fdb_entry *ent);
static __inline__ int handle_bridge(struct sk_buff **pskb,
struct packet_type **pt_prev, int *ret)
@@ -1629,12 +1630,9 @@ int netif_receive_skb(struct sk_buff *skb)
int ret = NET_RX_DROP;
unsigned short type;
-#ifdef CONFIG_NETPOLL
- if (skb->dev->netpoll_rx && skb->dev->poll && netpoll_rx(skb)) {
- kfree_skb(skb);
+ /* if we've gotten here through NAPI, check netpoll */
+ if (skb->dev->poll && netpoll_rx(skb))
return NET_RX_DROP;
- }
-#endif
if (!skb->stamp.tv_sec)
net_timestamp(&skb->stamp);
@@ -1781,8 +1779,10 @@ static void net_rx_action(struct softirq_action *h)
dev = list_entry(queue->poll_list.next,
struct net_device, poll_list);
+ netpoll_poll_lock(dev);
if (dev->quota <= 0 || dev->poll(dev, &budget)) {
+ netpoll_poll_unlock(dev);
local_irq_disable();
list_del(&dev->poll_list);
list_add_tail(&dev->poll_list, &queue->poll_list);
@@ -1791,6 +1791,7 @@ static void net_rx_action(struct softirq_action *h)
else
dev->quota = dev->weight;
} else {
+ netpoll_poll_unlock(dev);
dev_put(dev);
local_irq_disable();
}
@@ -2300,6 +2301,21 @@ int dev_set_mtu(struct net_device *dev, int new_mtu)
return err;
}
+int dev_set_mac_address(struct net_device *dev, struct sockaddr *sa)
+{
+ int err;
+
+ if (!dev->set_mac_address)
+ return -EOPNOTSUPP;
+ if (sa->sa_family != dev->type)
+ return -EINVAL;
+ if (!netif_device_present(dev))
+ return -ENODEV;
+ err = dev->set_mac_address(dev, sa);
+ if (!err)
+ notifier_call_chain(&netdev_chain, NETDEV_CHANGEADDR, dev);
+ return err;
+}
/*
* Perform the SIOCxIFxxx calls.
@@ -2346,17 +2362,7 @@ static int dev_ifsioc(struct ifreq *ifr, unsigned int cmd)
return 0;
case SIOCSIFHWADDR:
- if (!dev->set_mac_address)
- return -EOPNOTSUPP;
- if (ifr->ifr_hwaddr.sa_family != dev->type)
- return -EINVAL;
- if (!netif_device_present(dev))
- return -ENODEV;
- err = dev->set_mac_address(dev, &ifr->ifr_hwaddr);
- if (!err)
- notifier_call_chain(&netdev_chain,
- NETDEV_CHANGEADDR, dev);
- return err;
+ return dev_set_mac_address(dev, &ifr->ifr_hwaddr);
case SIOCSIFHWBROADCAST:
if (ifr->ifr_hwaddr.sa_family != dev->type)
@@ -3322,6 +3328,7 @@ EXPORT_SYMBOL(dev_set_allmulti);
EXPORT_SYMBOL(dev_set_promiscuity);
EXPORT_SYMBOL(dev_change_flags);
EXPORT_SYMBOL(dev_set_mtu);
+EXPORT_SYMBOL(dev_set_mac_address);
EXPORT_SYMBOL(free_netdev);
EXPORT_SYMBOL(netdev_boot_setup_check);
EXPORT_SYMBOL(netdev_set_master);
@@ -3337,9 +3344,12 @@ EXPORT_SYMBOL(unregister_netdevice);
EXPORT_SYMBOL(unregister_netdevice_notifier);
EXPORT_SYMBOL(net_enable_timestamp);
EXPORT_SYMBOL(net_disable_timestamp);
+EXPORT_SYMBOL(dev_get_flags);
#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
EXPORT_SYMBOL(br_handle_frame_hook);
+EXPORT_SYMBOL(br_fdb_get_hook);
+EXPORT_SYMBOL(br_fdb_put_hook);
#endif
#ifdef CONFIG_KMOD
diff --git a/net/core/gen_stats.c b/net/core/gen_stats.c
index 86cd889d0e2bf..ebb86fbd23ab6 100644
--- a/net/core/gen_stats.c
+++ b/net/core/gen_stats.c
@@ -26,7 +26,9 @@
static inline int
gnet_stats_copy(struct gnet_dump *d, int type, void *buf, int size)
{
- RTA_PUT(d->skb, type, size, buf);
+ if (type)
+ RTA_PUT(d->skb, type, size, buf);
+
return 0;
rtattr_failure:
@@ -58,7 +60,8 @@ gnet_stats_start_copy_compat(struct sk_buff *skb, int type, int tc_stats_type,
{
spin_lock_bh(lock);
d->lock = lock;
- d->tail = (struct rtattr *) skb->tail;
+ if (type)
+ d->tail = (struct rtattr *) skb->tail;
d->skb = skb;
d->compat_tc_stats = tc_stats_type;
d->compat_xstats = xstats_type;
@@ -194,7 +197,8 @@ gnet_stats_copy_app(struct gnet_dump *d, void *st, int len)
int
gnet_stats_finish_copy(struct gnet_dump *d)
{
- d->tail->rta_len = d->skb->tail - (u8 *) d->tail;
+ if (d->tail)
+ d->tail->rta_len = d->skb->tail - (u8 *) d->tail;
if (d->compat_tc_stats)
if (gnet_stats_copy(d, d->compat_tc_stats, &d->tc_stats,
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index b697893dfb407..0a2f67bbef2ec 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -1430,6 +1430,7 @@ int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
read_lock(&neigh_tbl_lock);
for (tbl = neigh_tables; tbl; tbl = tbl->next) {
+ struct rtattr *dst_attr = nda[NDA_DST - 1];
struct neighbour *n;
if (tbl->family != ndm->ndm_family)
@@ -1437,20 +1438,18 @@ int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
read_unlock(&neigh_tbl_lock);
err = -EINVAL;
- if (!nda[NDA_DST - 1] ||
- nda[NDA_DST - 1]->rta_len != RTA_LENGTH(tbl->key_len))
+ if (!dst_attr || RTA_PAYLOAD(dst_attr) < tbl->key_len)
goto out_dev_put;
if (ndm->ndm_flags & NTF_PROXY) {
- err = pneigh_delete(tbl,
- RTA_DATA(nda[NDA_DST - 1]), dev);
+ err = pneigh_delete(tbl, RTA_DATA(dst_attr), dev);
goto out_dev_put;
}
if (!dev)
goto out;
- n = neigh_lookup(tbl, RTA_DATA(nda[NDA_DST - 1]), dev);
+ n = neigh_lookup(tbl, RTA_DATA(dst_attr), dev);
if (n) {
err = neigh_update(n, NULL, NUD_FAILED,
NEIGH_UPDATE_F_OVERRIDE|
@@ -1482,6 +1481,8 @@ int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
read_lock(&neigh_tbl_lock);
for (tbl = neigh_tables; tbl; tbl = tbl->next) {
+ struct rtattr *lladdr_attr = nda[NDA_LLADDR - 1];
+ struct rtattr *dst_attr = nda[NDA_DST - 1];
int override = 1;
struct neighbour *n;
@@ -1490,48 +1491,49 @@ int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
read_unlock(&neigh_tbl_lock);
err = -EINVAL;
- if (!nda[NDA_DST - 1] ||
- nda[NDA_DST - 1]->rta_len != RTA_LENGTH(tbl->key_len))
+ if (!dst_attr || RTA_PAYLOAD(dst_attr) < tbl->key_len)
goto out_dev_put;
+
if (ndm->ndm_flags & NTF_PROXY) {
err = -ENOBUFS;
- if (pneigh_lookup(tbl,
- RTA_DATA(nda[NDA_DST - 1]), dev, 1))
+ if (pneigh_lookup(tbl, RTA_DATA(dst_attr), dev, 1))
err = 0;
goto out_dev_put;
}
+
err = -EINVAL;
if (!dev)
goto out;
- if (nda[NDA_LLADDR - 1] &&
- nda[NDA_LLADDR - 1]->rta_len != RTA_LENGTH(dev->addr_len))
+ if (lladdr_attr && RTA_PAYLOAD(lladdr_attr) < dev->addr_len)
goto out_dev_put;
- err = 0;
- n = neigh_lookup(tbl, RTA_DATA(nda[NDA_DST - 1]), dev);
+
+ n = neigh_lookup(tbl, RTA_DATA(dst_attr), dev);
if (n) {
- if (nlh->nlmsg_flags & NLM_F_EXCL)
+ if (nlh->nlmsg_flags & NLM_F_EXCL) {
err = -EEXIST;
+ neigh_release(n);
+ goto out_dev_put;
+ }
+
override = nlh->nlmsg_flags & NLM_F_REPLACE;
- } else if (!(nlh->nlmsg_flags & NLM_F_CREATE))
+ } else if (!(nlh->nlmsg_flags & NLM_F_CREATE)) {
err = -ENOENT;
- else {
- n = __neigh_lookup_errno(tbl, RTA_DATA(nda[NDA_DST - 1]),
- dev);
+ goto out_dev_put;
+ } else {
+ n = __neigh_lookup_errno(tbl, RTA_DATA(dst_attr), dev);
if (IS_ERR(n)) {
err = PTR_ERR(n);
- n = NULL;
+ goto out_dev_put;
}
}
- if (!err) {
- err = neigh_update(n, nda[NDA_LLADDR - 1] ?
- RTA_DATA(nda[NDA_LLADDR - 1]) :
- NULL,
- ndm->ndm_state,
- (override ? NEIGH_UPDATE_F_OVERRIDE : 0) |
- NEIGH_UPDATE_F_ADMIN);
- }
- if (n)
- neigh_release(n);
+
+ err = neigh_update(n,
+ lladdr_attr ? RTA_DATA(lladdr_attr) : NULL,
+ ndm->ndm_state,
+ (override ? NEIGH_UPDATE_F_OVERRIDE : 0) |
+ NEIGH_UPDATE_F_ADMIN);
+
+ neigh_release(n);
goto out_dev_put;
}
@@ -1552,6 +1554,7 @@ static int neigh_fill_info(struct sk_buff *skb, struct neighbour *n,
unsigned char *b = skb->tail;
struct nda_cacheinfo ci;
int locked = 0;
+ u32 probes;
struct nlmsghdr *nlh = NLMSG_PUT(skb, pid, seq, event,
sizeof(struct ndmsg));
struct ndmsg *ndm = NLMSG_DATA(nlh);
@@ -1571,9 +1574,11 @@ static int neigh_fill_info(struct sk_buff *skb, struct neighbour *n,
ci.ndm_confirmed = now - n->confirmed;
ci.ndm_updated = now - n->updated;
ci.ndm_refcnt = atomic_read(&n->refcnt) - 1;
+ probes = atomic_read(&n->probes);
read_unlock_bh(&n->lock);
locked = 0;
RTA_PUT(skb, NDA_CACHEINFO, sizeof(ci), &ci);
+ RTA_PUT(skb, NDA_PROBES, sizeof(probes), &probes);
nlh->nlmsg_len = skb->tail - b;
return skb->len;
@@ -2047,7 +2052,7 @@ static void neigh_app_notify(struct neighbour *n)
static struct neigh_sysctl_table {
struct ctl_table_header *sysctl_header;
- ctl_table neigh_vars[17];
+ ctl_table neigh_vars[__NET_NEIGH_MAX];
ctl_table neigh_dev[2];
ctl_table neigh_neigh_dir[2];
ctl_table neigh_proto_dir[2];
@@ -2170,6 +2175,22 @@ static struct neigh_sysctl_table {
.mode = 0644,
.proc_handler = &proc_dointvec,
},
+ {
+ .ctl_name = NET_NEIGH_RETRANS_TIME_MS,
+ .procname = "retrans_time_ms",
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_ms_jiffies,
+ .strategy = &sysctl_ms_jiffies,
+ },
+ {
+ .ctl_name = NET_NEIGH_REACHABLE_TIME_MS,
+ .procname = "base_reachable_time_ms",
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_ms_jiffies,
+ .strategy = &sysctl_ms_jiffies,
+ },
},
.neigh_dev = {
{
@@ -2200,7 +2221,7 @@ static struct neigh_sysctl_table {
int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p,
int p_id, int pdev_id, char *p_name,
- proc_handler *handler)
+ proc_handler *handler, ctl_handler *strategy)
{
struct neigh_sysctl_table *t = kmalloc(sizeof(*t), GFP_KERNEL);
const char *dev_name_source = NULL;
@@ -2214,10 +2235,6 @@ int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p,
t->neigh_vars[1].data = &p->ucast_probes;
t->neigh_vars[2].data = &p->app_probes;
t->neigh_vars[3].data = &p->retrans_time;
- if (handler) {
- t->neigh_vars[3].proc_handler = handler;
- t->neigh_vars[3].extra1 = dev;
- }
t->neigh_vars[4].data = &p->base_reachable_time;
t->neigh_vars[5].data = &p->delay_probe_time;
t->neigh_vars[6].data = &p->gc_staletime;
@@ -2227,18 +2244,43 @@ int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p,
t->neigh_vars[10].data = &p->proxy_delay;
t->neigh_vars[11].data = &p->locktime;
- dev_name_source = t->neigh_dev[0].procname;
if (dev) {
dev_name_source = dev->name;
t->neigh_dev[0].ctl_name = dev->ifindex;
- memset(&t->neigh_vars[12], 0, sizeof(ctl_table));
+ t->neigh_vars[12].procname = NULL;
+ t->neigh_vars[13].procname = NULL;
+ t->neigh_vars[14].procname = NULL;
+ t->neigh_vars[15].procname = NULL;
} else {
+ dev_name_source = t->neigh_dev[0].procname;
t->neigh_vars[12].data = (int *)(p + 1);
t->neigh_vars[13].data = (int *)(p + 1) + 1;
t->neigh_vars[14].data = (int *)(p + 1) + 2;
t->neigh_vars[15].data = (int *)(p + 1) + 3;
}
+ t->neigh_vars[16].data = &p->retrans_time;
+ t->neigh_vars[17].data = &p->base_reachable_time;
+
+ if (handler || strategy) {
+ /* RetransTime */
+ t->neigh_vars[3].proc_handler = handler;
+ t->neigh_vars[3].strategy = strategy;
+ t->neigh_vars[3].extra1 = dev;
+ /* ReachableTime */
+ t->neigh_vars[4].proc_handler = handler;
+ t->neigh_vars[4].strategy = strategy;
+ t->neigh_vars[4].extra1 = dev;
+ /* RetransTime (in milliseconds)*/
+ t->neigh_vars[16].proc_handler = handler;
+ t->neigh_vars[16].strategy = strategy;
+ t->neigh_vars[16].extra1 = dev;
+ /* ReachableTime (in milliseconds) */
+ t->neigh_vars[17].proc_handler = handler;
+ t->neigh_vars[17].strategy = strategy;
+ t->neigh_vars[17].extra1 = dev;
+ }
+
dev_name = net_sysctl_strdup(dev_name_source);
if (!dev_name) {
err = -ENOBUFS;
diff --git a/net/core/netfilter.c b/net/core/netfilter.c
index 0416161a2ed71..e51cfa46950cf 100644
--- a/net/core/netfilter.c
+++ b/net/core/netfilter.c
@@ -349,6 +349,8 @@ static unsigned int nf_iterate(struct list_head *head,
int (*okfn)(struct sk_buff *),
int hook_thresh)
{
+ unsigned int verdict;
+
/*
* The caller must not block between calls to this
* function because of risk of continuing from deleted element.
@@ -361,28 +363,18 @@ static unsigned int nf_iterate(struct list_head *head,
/* Optimization: we don't need to hold module
reference here, since function can't sleep. --RR */
- switch (elem->hook(hook, skb, indev, outdev, okfn)) {
- case NF_QUEUE:
- return NF_QUEUE;
-
- case NF_STOLEN:
- return NF_STOLEN;
-
- case NF_DROP:
- return NF_DROP;
-
- case NF_REPEAT:
- *i = (*i)->prev;
- break;
-
+ verdict = elem->hook(hook, skb, indev, outdev, okfn);
+ if (verdict != NF_ACCEPT) {
#ifdef CONFIG_NETFILTER_DEBUG
- case NF_ACCEPT:
- break;
-
- default:
- NFDEBUG("Evil return from %p(%u).\n",
- elem->hook, hook);
+ if (unlikely(verdict > NF_MAX_VERDICT)) {
+ NFDEBUG("Evil return from %p(%u).\n",
+ elem->hook, hook);
+ continue;
+ }
#endif
+ if (verdict != NF_REPEAT)
+ return verdict;
+ *i = (*i)->prev;
}
}
return NF_ACCEPT;
@@ -494,7 +486,9 @@ static int nf_queue(struct sk_buff *skb,
return 1;
}
-int nf_hook_slow(int pf, unsigned int hook, struct sk_buff *skb,
+/* Returns 1 if okfn() needs to be executed by the caller,
+ * -EPERM for NF_DROP, 0 otherwise. */
+int nf_hook_slow(int pf, unsigned int hook, struct sk_buff **pskb,
struct net_device *indev,
struct net_device *outdev,
int (*okfn)(struct sk_buff *),
@@ -508,34 +502,29 @@ int nf_hook_slow(int pf, unsigned int hook, struct sk_buff *skb,
rcu_read_lock();
#ifdef CONFIG_NETFILTER_DEBUG
- if (skb->nf_debug & (1 << hook)) {
+ if (unlikely((*pskb)->nf_debug & (1 << hook))) {
printk("nf_hook: hook %i already set.\n", hook);
- nf_dump_skb(pf, skb);
+ nf_dump_skb(pf, *pskb);
}
- skb->nf_debug |= (1 << hook);
+ (*pskb)->nf_debug |= (1 << hook);
#endif
elem = &nf_hooks[pf][hook];
- next_hook:
- verdict = nf_iterate(&nf_hooks[pf][hook], &skb, hook, indev,
+next_hook:
+ verdict = nf_iterate(&nf_hooks[pf][hook], pskb, hook, indev,
outdev, &elem, okfn, hook_thresh);
- if (verdict == NF_QUEUE) {
+ if (verdict == NF_ACCEPT || verdict == NF_STOP) {
+ ret = 1;
+ goto unlock;
+ } else if (verdict == NF_DROP) {
+ kfree_skb(*pskb);
+ ret = -EPERM;
+ } else if (verdict == NF_QUEUE) {
NFDEBUG("nf_hook: Verdict = QUEUE.\n");
- if (!nf_queue(skb, elem, pf, hook, indev, outdev, okfn))
+ if (!nf_queue(*pskb, elem, pf, hook, indev, outdev, okfn))
goto next_hook;
}
-
- switch (verdict) {
- case NF_ACCEPT:
- ret = okfn(skb);
- break;
-
- case NF_DROP:
- kfree_skb(skb);
- ret = -EPERM;
- break;
- }
-
+unlock:
rcu_read_unlock();
return ret;
}
@@ -678,7 +667,6 @@ EXPORT_SYMBOL(ip_route_me_harder);
int skb_ip_make_writable(struct sk_buff **pskb, unsigned int writable_len)
{
struct sk_buff *nskb;
- unsigned int iplen;
if (writable_len > (*pskb)->len)
return 0;
@@ -687,35 +675,7 @@ int skb_ip_make_writable(struct sk_buff **pskb, unsigned int writable_len)
if (skb_shared(*pskb) || skb_cloned(*pskb))
goto copy_skb;
- /* Alexey says IP hdr is always modifiable and linear, so ok. */
- if (writable_len <= (*pskb)->nh.iph->ihl*4)
- return 1;
-
- iplen = writable_len - (*pskb)->nh.iph->ihl*4;
-
- /* DaveM says protocol headers are also modifiable. */
- switch ((*pskb)->nh.iph->protocol) {
- case IPPROTO_TCP: {
- struct tcphdr _hdr, *hp;
- hp = skb_header_pointer(*pskb, (*pskb)->nh.iph->ihl*4,
- sizeof(_hdr), &_hdr);
- if (hp == NULL)
- goto copy_skb;
- if (writable_len <= (*pskb)->nh.iph->ihl*4 + hp->doff*4)
- goto pull_skb;
- goto copy_skb;
- }
- case IPPROTO_UDP:
- if (writable_len<=(*pskb)->nh.iph->ihl*4+sizeof(struct udphdr))
- goto pull_skb;
- goto copy_skb;
- case IPPROTO_ICMP:
- if (writable_len
- <= (*pskb)->nh.iph->ihl*4 + sizeof(struct icmphdr))
- goto pull_skb;
- goto copy_skb;
- /* Insert other cases here as desired */
- }
+ return pskb_may_pull(*pskb, writable_len);
copy_skb:
nskb = skb_copy(*pskb, GFP_ATOMIC);
@@ -730,9 +690,6 @@ copy_skb:
kfree_skb(*pskb);
*pskb = nskb;
return 1;
-
-pull_skb:
- return pskb_may_pull(*pskb, writable_len);
}
EXPORT_SYMBOL(skb_ip_make_writable);
#endif /*CONFIG_INET*/
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index 0860e08271346..a119696d55212 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -18,7 +18,9 @@
#include <linux/interrupt.h>
#include <linux/netpoll.h>
#include <linux/sched.h>
+#include <linux/delay.h>
#include <linux/rcupdate.h>
+#include <linux/workqueue.h>
#include <net/tcp.h>
#include <net/udp.h>
#include <asm/unaligned.h>
@@ -28,18 +30,19 @@
* message gets out even in extreme OOM situations.
*/
-#define MAX_SKBS 32
#define MAX_UDP_CHUNK 1460
+#define MAX_SKBS 32
+#define MAX_QUEUE_DEPTH (MAX_SKBS / 2)
static DEFINE_SPINLOCK(skb_list_lock);
static int nr_skbs;
static struct sk_buff *skbs;
-static DEFINE_SPINLOCK(rx_list_lock);
-static LIST_HEAD(rx_list);
+static DEFINE_SPINLOCK(queue_lock);
+static int queue_depth;
+static struct sk_buff *queue_head, *queue_tail;
static atomic_t trapped;
-static DEFINE_SPINLOCK(netpoll_poll_lock);
#define NETPOLL_RX_ENABLED 1
#define NETPOLL_RX_DROP 2
@@ -50,6 +53,50 @@ static DEFINE_SPINLOCK(netpoll_poll_lock);
static void zap_completion_queue(void);
+static void queue_process(void *p)
+{
+ unsigned long flags;
+ struct sk_buff *skb;
+
+ while (queue_head) {
+ spin_lock_irqsave(&queue_lock, flags);
+
+ skb = queue_head;
+ queue_head = skb->next;
+ if (skb == queue_tail)
+ queue_head = NULL;
+
+ queue_depth--;
+
+ spin_unlock_irqrestore(&queue_lock, flags);
+
+ dev_queue_xmit(skb);
+ }
+}
+
+static DECLARE_WORK(send_queue, queue_process, NULL);
+
+void netpoll_queue(struct sk_buff *skb)
+{
+ unsigned long flags;
+
+ if (queue_depth == MAX_QUEUE_DEPTH) {
+ __kfree_skb(skb);
+ return;
+ }
+
+ spin_lock_irqsave(&queue_lock, flags);
+ if (!queue_head)
+ queue_head = skb;
+ else
+ queue_tail->next = skb;
+ queue_tail = skb;
+ queue_depth++;
+ spin_unlock_irqrestore(&queue_lock, flags);
+
+ schedule_work(&send_queue);
+}
+
static int checksum_udp(struct sk_buff *skb, struct udphdr *uh,
unsigned short ulen, u32 saddr, u32 daddr)
{
@@ -66,8 +113,15 @@ static int checksum_udp(struct sk_buff *skb, struct udphdr *uh,
}
/*
- * Check whether delayed processing was scheduled for our current CPU,
- * and then manually invoke NAPI polling to pump data off the card.
+ * Check whether delayed processing was scheduled for our NIC. If so,
+ * we attempt to grab the poll lock and use ->poll() to pump the card.
+ * If this fails, either we've recursed in ->poll() or it's already
+ * running on another CPU.
+ *
+ * Note: we don't mask interrupts with this lock because we're using
+ * trylock here and interrupts are already disabled in the softirq
+ * case. Further, we test the poll_owner to avoid recursion on UP
+ * systems where the lock doesn't exist.
*
* In cases where there is bi-directional communications, reading only
* one message at a time can lead to packets being dropped by the
@@ -77,22 +131,19 @@ static int checksum_udp(struct sk_buff *skb, struct udphdr *uh,
static void poll_napi(struct netpoll *np)
{
int budget = 16;
- unsigned long flags;
- struct softnet_data *queue;
- spin_lock_irqsave(&netpoll_poll_lock, flags);
- queue = &__get_cpu_var(softnet_data);
if (test_bit(__LINK_STATE_RX_SCHED, &np->dev->state) &&
- !list_empty(&queue->poll_list)) {
- np->dev->netpoll_rx |= NETPOLL_RX_DROP;
+ np->poll_owner != smp_processor_id() &&
+ spin_trylock(&np->poll_lock)) {
+ np->rx_flags |= NETPOLL_RX_DROP;
atomic_inc(&trapped);
np->dev->poll(np->dev, &budget);
atomic_dec(&trapped);
- np->dev->netpoll_rx &= ~NETPOLL_RX_DROP;
+ np->rx_flags &= ~NETPOLL_RX_DROP;
+ spin_unlock(&np->poll_lock);
}
- spin_unlock_irqrestore(&netpoll_poll_lock, flags);
}
void netpoll_poll(struct netpoll *np)
@@ -142,7 +193,10 @@ static void zap_completion_queue(void)
while (clist != NULL) {
struct sk_buff *skb = clist;
clist = clist->next;
- __kfree_skb(skb);
+ if(skb->destructor)
+ dev_kfree_skb_any(skb); /* put this one back */
+ else
+ __kfree_skb(skb);
}
}
@@ -165,10 +219,11 @@ repeat:
if (!skb) {
spin_lock_irqsave(&skb_list_lock, flags);
skb = skbs;
- if (skb)
+ if (skb) {
skbs = skb->next;
- skb->next = NULL;
- nr_skbs--;
+ skb->next = NULL;
+ nr_skbs--;
+ }
spin_unlock_irqrestore(&skb_list_lock, flags);
}
@@ -197,6 +252,16 @@ repeat:
return;
}
+ /* avoid recursion */
+ if(np->poll_owner == smp_processor_id() ||
+ np->dev->xmit_lock_owner == smp_processor_id()) {
+ if (np->drop)
+ np->drop(skb);
+ else
+ __kfree_skb(skb);
+ return;
+ }
+
spin_lock(&np->dev->xmit_lock);
np->dev->xmit_lock_owner = smp_processor_id();
@@ -233,7 +298,7 @@ void netpoll_send_udp(struct netpoll *np, const char *msg, int len)
udp_len = len + sizeof(*udph);
ip_len = eth_len = udp_len + sizeof(*iph);
- total_len = eth_len + ETH_HLEN;
+ total_len = eth_len + ETH_HLEN + NET_IP_ALIGN;
skb = find_skb(np, total_len, total_len - len);
if (!skb)
@@ -269,6 +334,8 @@ void netpoll_send_udp(struct netpoll *np, const char *msg, int len)
memcpy(eth->h_source, np->local_mac, 6);
memcpy(eth->h_dest, np->remote_mac, 6);
+ skb->dev = np->dev;
+
netpoll_send_skb(np, skb);
}
@@ -279,18 +346,7 @@ static void arp_reply(struct sk_buff *skb)
int size, type = ARPOP_REPLY, ptype = ETH_P_ARP;
u32 sip, tip;
struct sk_buff *send_skb;
- unsigned long flags;
- struct list_head *p;
- struct netpoll *np = NULL;
-
- spin_lock_irqsave(&rx_list_lock, flags);
- list_for_each(p, &rx_list) {
- np = list_entry(p, struct netpoll, rx_list);
- if ( np->dev == skb->dev )
- break;
- np = NULL;
- }
- spin_unlock_irqrestore(&rx_list_lock, flags);
+ struct netpoll *np = skb->dev->np;
if (!np) return;
@@ -368,15 +424,15 @@ static void arp_reply(struct sk_buff *skb)
netpoll_send_skb(np, send_skb);
}
-int netpoll_rx(struct sk_buff *skb)
+int __netpoll_rx(struct sk_buff *skb)
{
int proto, len, ulen;
struct iphdr *iph;
struct udphdr *uh;
- struct netpoll *np;
- struct list_head *p;
- unsigned long flags;
+ struct netpoll *np = skb->dev->np;
+ if (!np->rx_hook)
+ goto out;
if (skb->dev->type != ARPHRD_ETHER)
goto out;
@@ -420,32 +476,27 @@ int netpoll_rx(struct sk_buff *skb)
goto out;
if (checksum_udp(skb, uh, ulen, iph->saddr, iph->daddr) < 0)
goto out;
+ if (np->local_ip && np->local_ip != ntohl(iph->daddr))
+ goto out;
+ if (np->remote_ip && np->remote_ip != ntohl(iph->saddr))
+ goto out;
+ if (np->local_port && np->local_port != ntohs(uh->dest))
+ goto out;
+
+ np->rx_hook(np, ntohs(uh->source),
+ (char *)(uh+1),
+ ulen - sizeof(struct udphdr));
- spin_lock_irqsave(&rx_list_lock, flags);
- list_for_each(p, &rx_list) {
- np = list_entry(p, struct netpoll, rx_list);
- if (np->dev && np->dev != skb->dev)
- continue;
- if (np->local_ip && np->local_ip != ntohl(iph->daddr))
- continue;
- if (np->remote_ip && np->remote_ip != ntohl(iph->saddr))
- continue;
- if (np->local_port && np->local_port != ntohs(uh->dest))
- continue;
-
- spin_unlock_irqrestore(&rx_list_lock, flags);
-
- if (np->rx_hook)
- np->rx_hook(np, ntohs(uh->source),
- (char *)(uh+1),
- ulen - sizeof(struct udphdr));
+ kfree_skb(skb);
+ return 1;
+out:
+ if (atomic_read(&trapped)) {
+ kfree_skb(skb);
return 1;
}
- spin_unlock_irqrestore(&rx_list_lock, flags);
-out:
- return atomic_read(&trapped);
+ return 0;
}
int netpoll_parse_options(struct netpoll *np, char *opt)
@@ -561,6 +612,9 @@ int netpoll_setup(struct netpoll *np)
struct net_device *ndev = NULL;
struct in_device *in_dev;
+ np->poll_lock = SPIN_LOCK_UNLOCKED;
+ np->poll_owner = -1;
+
if (np->dev_name)
ndev = dev_get_by_name(np->dev_name);
if (!ndev) {
@@ -568,6 +622,10 @@ int netpoll_setup(struct netpoll *np)
np->name, np->dev_name);
return -1;
}
+
+ np->dev = ndev;
+ ndev->np = np;
+
if (!ndev->poll_controller) {
printk(KERN_ERR "%s: %s doesn't support polling, aborting.\n",
np->name, np->dev_name);
@@ -575,16 +633,13 @@ int netpoll_setup(struct netpoll *np)
}
if (!netif_running(ndev)) {
- unsigned short oflags;
unsigned long atmost, atleast;
printk(KERN_INFO "%s: device %s not up yet, forcing it\n",
np->name, np->dev_name);
- oflags = ndev->flags;
-
rtnl_shlock();
- if (dev_change_flags(ndev, oflags | IFF_UP) < 0) {
+ if (dev_change_flags(ndev, ndev->flags | IFF_UP) < 0) {
printk(KERN_ERR "%s: failed to open %s\n",
np->name, np->dev_name);
rtnl_shunlock();
@@ -593,7 +648,7 @@ int netpoll_setup(struct netpoll *np)
rtnl_shunlock();
atleast = jiffies + HZ/10;
- atmost = jiffies + 10*HZ;
+ atmost = jiffies + 4*HZ;
while (!netif_carrier_ok(ndev)) {
if (time_after(jiffies, atmost)) {
printk(KERN_NOTICE
@@ -604,12 +659,16 @@ int netpoll_setup(struct netpoll *np)
cond_resched();
}
+ /* If carrier appears to come up instantly, we don't
+ * trust it and pause so that we don't pump all our
+ * queued console messages into the bitbucket.
+ */
+
if (time_before(jiffies, atleast)) {
- printk(KERN_NOTICE "%s: carrier detect appears flaky,"
- " waiting 10 seconds\n",
+ printk(KERN_NOTICE "%s: carrier detect appears"
+ " untrustworthy, waiting 4 seconds\n",
np->name);
- while (time_before(jiffies, atmost))
- cond_resched();
+ msleep(4000);
}
}
@@ -633,36 +692,22 @@ int netpoll_setup(struct netpoll *np)
np->name, HIPQUAD(np->local_ip));
}
- np->dev = ndev;
-
- if(np->rx_hook) {
- unsigned long flags;
-
- np->dev->netpoll_rx = NETPOLL_RX_ENABLED;
-
- spin_lock_irqsave(&rx_list_lock, flags);
- list_add(&np->rx_list, &rx_list);
- spin_unlock_irqrestore(&rx_list_lock, flags);
- }
+ if(np->rx_hook)
+ np->rx_flags = NETPOLL_RX_ENABLED;
return 0;
+
release:
+ ndev->np = NULL;
+ np->dev = NULL;
dev_put(ndev);
return -1;
}
void netpoll_cleanup(struct netpoll *np)
{
- if (np->rx_hook) {
- unsigned long flags;
-
- spin_lock_irqsave(&rx_list_lock, flags);
- list_del(&np->rx_list);
- spin_unlock_irqrestore(&rx_list_lock, flags);
- }
-
if (np->dev)
- np->dev->netpoll_rx = 0;
+ np->dev->np = NULL;
dev_put(np->dev);
np->dev = NULL;
}
@@ -687,3 +732,4 @@ EXPORT_SYMBOL(netpoll_setup);
EXPORT_SYMBOL(netpoll_cleanup);
EXPORT_SYMBOL(netpoll_send_udp);
EXPORT_SYMBOL(netpoll_poll);
+EXPORT_SYMBOL(netpoll_queue);
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index 689db7d8df9b0..c57b06bc79f37 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -104,6 +104,8 @@
* Corrections from Nikolai Malykh (nmalykh@bilim.com)
* Removed unused flags F_SET_SRCMAC & F_SET_SRCIP 041230
*
+ * interruptible_sleep_on_timeout() replaced Nishanth Aravamudan <nacc@us.ibm.com>
+ * 050103
*/
#include <linux/sys.h>
#include <linux/types.h>
@@ -135,6 +137,7 @@
#include <linux/ipv6.h>
#include <linux/udp.h>
#include <linux/proc_fs.h>
+#include <linux/wait.h>
#include <net/checksum.h>
#include <net/ipv6.h>
#include <net/addrconf.h>
@@ -148,7 +151,7 @@
#include <asm/timex.h>
-#define VERSION "pktgen v2.56: Packet Generator for packet performance testing.\n"
+#define VERSION "pktgen v2.61: Packet Generator for packet performance testing.\n"
/* #define PG_DEBUG(a) a */
#define PG_DEBUG(a)
@@ -808,6 +811,7 @@ static int proc_if_write(struct file *file, const char __user *user_buffer,
struct pktgen_dev *pkt_dev = (struct pktgen_dev*)(data);
char* pg_result = NULL;
int tmp = 0;
+ char buf[128];
pg_result = &(pkt_dev->result[0]);
@@ -1068,7 +1072,6 @@ static int proc_if_write(struct file *file, const char __user *user_buffer,
return count;
}
if (!strcmp(name, "dst_min") || !strcmp(name, "dst")) {
- char buf[IP_NAME_SZ];
len = strn_len(&user_buffer[i], sizeof(pkt_dev->dst_min) - 1);
if (len < 0) { return len; }
@@ -1088,7 +1091,6 @@ static int proc_if_write(struct file *file, const char __user *user_buffer,
return count;
}
if (!strcmp(name, "dst_max")) {
- char buf[IP_NAME_SZ];
len = strn_len(&user_buffer[i], sizeof(pkt_dev->dst_max) - 1);
if (len < 0) { return len; }
@@ -1109,9 +1111,7 @@ static int proc_if_write(struct file *file, const char __user *user_buffer,
return count;
}
if (!strcmp(name, "dst6")) {
- char buf[128];
-
- len = strn_len(&user_buffer[i], 128 - 1);
+ len = strn_len(&user_buffer[i], sizeof(buf) - 1);
if (len < 0) return len;
pkt_dev->flags |= F_IPV6;
@@ -1133,9 +1133,7 @@ static int proc_if_write(struct file *file, const char __user *user_buffer,
return count;
}
if (!strcmp(name, "dst6_min")) {
- char buf[128];
-
- len = strn_len(&user_buffer[i], 128 - 1);
+ len = strn_len(&user_buffer[i], sizeof(buf) - 1);
if (len < 0) return len;
pkt_dev->flags |= F_IPV6;
@@ -1156,9 +1154,7 @@ static int proc_if_write(struct file *file, const char __user *user_buffer,
return count;
}
if (!strcmp(name, "dst6_max")) {
- char buf[128];
-
- len = strn_len(&user_buffer[i], 128 - 1);
+ len = strn_len(&user_buffer[i], sizeof(buf) - 1);
if (len < 0) return len;
pkt_dev->flags |= F_IPV6;
@@ -1178,9 +1174,7 @@ static int proc_if_write(struct file *file, const char __user *user_buffer,
return count;
}
if (!strcmp(name, "src6")) {
- char buf[128];
-
- len = strn_len(&user_buffer[i], 128 - 1);
+ len = strn_len(&user_buffer[i], sizeof(buf) - 1);
if (len < 0) return len;
pkt_dev->flags |= F_IPV6;
@@ -1202,7 +1196,6 @@ static int proc_if_write(struct file *file, const char __user *user_buffer,
return count;
}
if (!strcmp(name, "src_min")) {
- char buf[IP_NAME_SZ];
len = strn_len(&user_buffer[i], sizeof(pkt_dev->src_min) - 1);
if (len < 0) { return len; }
if (copy_from_user(buf, &user_buffer[i], len))
@@ -1221,7 +1214,6 @@ static int proc_if_write(struct file *file, const char __user *user_buffer,
return count;
}
if (!strcmp(name, "src_max")) {
- char buf[IP_NAME_SZ];
len = strn_len(&user_buffer[i], sizeof(pkt_dev->src_max) - 1);
if (len < 0) { return len; }
if (copy_from_user(buf, &user_buffer[i], len))
@@ -1427,7 +1419,6 @@ static int proc_thread_write(struct file *file, const char __user *user_buffer,
if (debug)
printk("pktgen: t=%s, count=%lu\n", name, count);
- thread_lock();
t = (struct pktgen_thread*)(data);
if(!t) {
@@ -1449,14 +1440,18 @@ static int proc_thread_write(struct file *file, const char __user *user_buffer,
if( copy_from_user(f, &user_buffer[i], len) )
return -EFAULT;
i += len;
+ thread_lock();
pktgen_add_device(t, f);
+ thread_unlock();
ret = count;
sprintf(pg_result, "OK: add_device=%s", f);
goto out;
}
if (!strcmp(name, "rem_device_all")) {
+ thread_lock();
t->control |= T_REMDEV;
+ thread_unlock();
current->state = TASK_INTERRUPTIBLE;
schedule_timeout(HZ/8); /* Propagate thread->control */
ret = count;
@@ -1464,10 +1459,11 @@ static int proc_thread_write(struct file *file, const char __user *user_buffer,
goto out;
}
-
if (!strcmp(name, "max_before_softirq")) {
len = num_arg(&user_buffer[i], 10, &value);
+ thread_lock();
t->max_before_softirq = value;
+ thread_unlock();
ret = count;
sprintf(pg_result, "OK: max_before_softirq=%lu", value);
goto out;
@@ -1475,7 +1471,6 @@ static int proc_thread_write(struct file *file, const char __user *user_buffer,
ret = -EINVAL;
out:
- thread_unlock();
return ret;
}
@@ -1690,7 +1685,7 @@ static void pktgen_setup_inject(struct pktgen_dev *pkt_dev)
pkt_dev->saddr_min = in_dev->ifa_list->ifa_address;
pkt_dev->saddr_max = pkt_dev->saddr_min;
}
- in_dev_put(in_dev);
+ __in_dev_put(in_dev);
}
rcu_read_unlock();
}
@@ -2402,16 +2397,14 @@ static int thread_is_running(struct pktgen_thread *t )
static int pktgen_wait_thread_run(struct pktgen_thread *t )
{
- wait_queue_head_t queue;
-
- init_waitqueue_head(&queue);
-
if_lock(t);
while(thread_is_running(t)) {
+
if_unlock(t);
-
- interruptible_sleep_on_timeout(&queue, HZ/10);
+
+ msleep_interruptible(100);
+
if (signal_pending(current))
goto signal;
if_lock(t);
@@ -2597,7 +2590,7 @@ static void pktgen_rem_thread(struct pktgen_thread *t)
thread_unlock();
}
-__inline__ void pktgen_xmit(struct pktgen_dev *pkt_dev)
+static __inline__ void pktgen_xmit(struct pktgen_dev *pkt_dev)
{
struct net_device *odev = NULL;
__u64 idle_start = 0;
@@ -2661,7 +2654,6 @@ __inline__ void pktgen_xmit(struct pktgen_dev *pkt_dev)
spin_lock_bh(&odev->xmit_lock);
if (!netif_queue_stopped(odev)) {
- u64 now;
atomic_inc(&(pkt_dev->skb->users));
retry_now:
@@ -2685,24 +2677,18 @@ retry_now:
pkt_dev->errors++;
pkt_dev->last_ok = 0;
- pkt_dev->next_tx_us = getCurUs(); /* TODO */
- pkt_dev->next_tx_ns = 0;
}
+ pkt_dev->next_tx_us = getCurUs();
+ pkt_dev->next_tx_ns = 0;
+
pkt_dev->next_tx_us += pkt_dev->delay_us;
pkt_dev->next_tx_ns += pkt_dev->delay_ns;
+
if (pkt_dev->next_tx_ns > 1000) {
pkt_dev->next_tx_us++;
pkt_dev->next_tx_ns -= 1000;
}
-
- now = getCurUs();
- if (now > pkt_dev->next_tx_us) {
- /* TODO: this code is slightly wonky. */
- pkt_dev->errors++;
- pkt_dev->next_tx_us = now - pkt_dev->delay_us;
- pkt_dev->next_tx_ns = 0;
- }
}
else { /* Retry it next time */
@@ -2738,6 +2724,7 @@ retry_now:
static void pktgen_thread_worker(struct pktgen_thread *t)
{
+ DEFINE_WAIT(wait);
struct pktgen_dev *pkt_dev = NULL;
int cpu = t->cpu;
sigset_t tmpsig;
@@ -2805,9 +2792,11 @@ static void pktgen_thread_worker(struct pktgen_thread *t)
do_softirq();
tx_since_softirq = 0;
}
+ } else {
+ prepare_to_wait(&(t->queue), &wait, TASK_INTERRUPTIBLE);
+ schedule_timeout(HZ/10);
+ finish_wait(&(t->queue), &wait);
}
- else
- interruptible_sleep_on_timeout(&(t->queue), HZ/10);
/*
* Back from sleep, either due to the timeout or signal.
@@ -3117,8 +3106,7 @@ static void __exit pg_cleanup(void)
struct pktgen_thread *t = pktgen_threads;
pktgen_threads->control |= (T_TERMINATE);
- while( t == pktgen_threads)
- interruptible_sleep_on_timeout(&queue, HZ);
+ wait_event_interruptible_timeout(queue, (t != pktgen_threads), HZ);
}
/* Un-register us from receiving netdevice events */
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index c83dd4c9b0573..bf02ca9f80ac1 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -241,7 +241,8 @@ static void skb_clone_fraglist(struct sk_buff *skb)
void skb_release_data(struct sk_buff *skb)
{
if (!skb->cloned ||
- atomic_dec_and_test(&(skb_shinfo(skb)->dataref))) {
+ !atomic_sub_return(skb->nohdr ? (1 << SKB_DATAREF_SHIFT) + 1 : 1,
+ &skb_shinfo(skb)->dataref)) {
if (skb_shinfo(skb)->nr_frags) {
int i;
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
@@ -353,6 +354,7 @@ struct sk_buff *skb_clone(struct sk_buff *skb, int gfp_mask)
C(csum);
C(local_df);
n->cloned = 1;
+ n->nohdr = 0;
C(pkt_type);
C(ip_summed);
C(priority);
@@ -604,6 +606,7 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail, int gfp_mask)
skb->h.raw += off;
skb->nh.raw += off;
skb->cloned = 0;
+ skb->nohdr = 0;
atomic_set(&skb_shinfo(skb)->dataref, 1);
return 0;
@@ -982,70 +985,6 @@ fault:
return -EFAULT;
}
-/* Keep iterating until skb_iter_next returns false. */
-void skb_iter_first(const struct sk_buff *skb, struct skb_iter *i)
-{
- i->len = skb_headlen(skb);
- i->data = (unsigned char *)skb->data;
- i->nextfrag = 0;
- i->fraglist = NULL;
-}
-
-int skb_iter_next(const struct sk_buff *skb, struct skb_iter *i)
-{
- /* Unmap previous, if not head fragment. */
- if (i->nextfrag)
- kunmap_skb_frag(i->data);
-
- if (i->fraglist) {
- fraglist:
- /* We're iterating through fraglist. */
- if (i->nextfrag < skb_shinfo(i->fraglist)->nr_frags) {
- i->data = kmap_skb_frag(&skb_shinfo(i->fraglist)
- ->frags[i->nextfrag]);
- i->len = skb_shinfo(i->fraglist)->frags[i->nextfrag]
- .size;
- i->nextfrag++;
- return 1;
- }
- /* Fragments with fragments? Too hard! */
- BUG_ON(skb_shinfo(i->fraglist)->frag_list);
- i->fraglist = i->fraglist->next;
- if (!i->fraglist)
- goto end;
-
- i->len = skb_headlen(i->fraglist);
- i->data = i->fraglist->data;
- i->nextfrag = 0;
- return 1;
- }
-
- if (i->nextfrag < skb_shinfo(skb)->nr_frags) {
- i->data = kmap_skb_frag(&skb_shinfo(skb)->frags[i->nextfrag]);
- i->len = skb_shinfo(skb)->frags[i->nextfrag].size;
- i->nextfrag++;
- return 1;
- }
-
- i->fraglist = skb_shinfo(skb)->frag_list;
- if (i->fraglist)
- goto fraglist;
-
-end:
- /* Bug trap for callers */
- i->data = NULL;
- return 0;
-}
-
-void skb_iter_abort(const struct sk_buff *skb, struct skb_iter *i)
-{
- /* Unmap previous, if not head fragment. */
- if (i->data && i->nextfrag)
- kunmap_skb_frag(i->data);
- /* Bug trap for callers */
- i->data = NULL;
-}
-
/* Checksum skb data. */
unsigned int skb_checksum(const struct sk_buff *skb, int offset,
@@ -1444,7 +1383,7 @@ static inline void skb_split_no_header(struct sk_buff *skb,
if (pos < len) {
/* Split frag.
- * We have to variants in this case:
+ * We have two variants in this case:
* 1. Move all the frag to the second
* part, if it is possible. F.e.
* this approach is mandatory for TUX,
@@ -1467,6 +1406,9 @@ static inline void skb_split_no_header(struct sk_buff *skb,
/**
* skb_split - Split fragmented skb to two parts at length len.
+ * @skb: the buffer to split
+ * @skb1: the buffer to receive the second part
+ * @len: new length for skb
*/
void skb_split(struct sk_buff *skb, struct sk_buff *skb1, const u32 len)
{
@@ -1516,6 +1458,3 @@ EXPORT_SYMBOL(skb_queue_tail);
EXPORT_SYMBOL(skb_unlink);
EXPORT_SYMBOL(skb_append);
EXPORT_SYMBOL(skb_split);
-EXPORT_SYMBOL(skb_iter_first);
-EXPORT_SYMBOL(skb_iter_next);
-EXPORT_SYMBOL(skb_iter_abort);
diff --git a/net/core/sock.c b/net/core/sock.c
index 8d77617f0fcbe..18365fb8853f9 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -228,8 +228,10 @@ int sock_setsockopt(struct socket *sock, int level, int optname,
{
ret = -EACCES;
}
+ else if (valbool)
+ sock_set_flag(sk, SOCK_DBG);
else
- sk->sk_debug = valbool;
+ sock_reset_flag(sk, SOCK_DBG);
break;
case SO_REUSEADDR:
sk->sk_reuse = valbool;
@@ -239,7 +241,10 @@ int sock_setsockopt(struct socket *sock, int level, int optname,
ret = -ENOPROTOOPT;
break;
case SO_DONTROUTE:
- sk->sk_localroute = valbool;
+ if (valbool)
+ sock_set_flag(sk, SOCK_LOCALROUTE);
+ else
+ sock_reset_flag(sk, SOCK_LOCALROUTE);
break;
case SO_BROADCAST:
sock_valbool_flag(sk, SOCK_BROADCAST, valbool);
@@ -333,13 +338,18 @@ int sock_setsockopt(struct socket *sock, int level, int optname,
break;
case SO_PASSCRED:
- sock->passcred = valbool;
+ if (valbool)
+ set_bit(SOCK_PASSCRED, &sock->flags);
+ else
+ clear_bit(SOCK_PASSCRED, &sock->flags);
break;
case SO_TIMESTAMP:
- sk->sk_rcvtstamp = valbool;
- if (valbool)
+ if (valbool) {
+ sock_set_flag(sk, SOCK_RCVTSTAMP);
sock_enable_timestamp(sk);
+ } else
+ sock_reset_flag(sk, SOCK_RCVTSTAMP);
break;
case SO_RCVLOWAT:
@@ -463,11 +473,11 @@ int sock_getsockopt(struct socket *sock, int level, int optname,
switch(optname)
{
case SO_DEBUG:
- v.val = sk->sk_debug;
+ v.val = sock_flag(sk, SOCK_DBG);
break;
case SO_DONTROUTE:
- v.val = sk->sk_localroute;
+ v.val = sock_flag(sk, SOCK_LOCALROUTE);
break;
case SO_BROADCAST:
@@ -523,7 +533,7 @@ int sock_getsockopt(struct socket *sock, int level, int optname,
break;
case SO_TIMESTAMP:
- v.val = sk->sk_rcvtstamp;
+ v.val = sock_flag(sk, SOCK_RCVTSTAMP);
break;
case SO_RCVTIMEO:
@@ -557,7 +567,7 @@ int sock_getsockopt(struct socket *sock, int level, int optname,
break;
case SO_PASSCRED:
- v.val = sock->passcred;
+ v.val = test_bit(SOCK_PASSCRED, &sock->flags) ? 1 : 0;
break;
case SO_PEERCRED:
@@ -621,9 +631,17 @@ struct sock *sk_alloc(int family, int priority, int zero_it, kmem_cache_t *slab)
{
struct sock *sk = NULL;
- if (!slab)
+ /*
+ * Transitional, this test will be removed when sk_cachep is killed
+ */
+ if (slab == NULL && zero_it == 1)
slab = sk_cachep;
- sk = kmem_cache_alloc(slab, priority);
+
+ if (slab != NULL)
+ sk = kmem_cache_alloc(slab, priority);
+ else
+ sk = kmalloc(zero_it, priority);
+
if (sk) {
if (zero_it) {
memset(sk, 0,
@@ -662,7 +680,10 @@ void sk_free(struct sock *sk)
__FUNCTION__, atomic_read(&sk->sk_omem_alloc));
security_sk_free(sk);
- kmem_cache_free(sk->sk_slab, sk);
+ if (sk->sk_slab != NULL)
+ kmem_cache_free(sk->sk_slab, sk);
+ else
+ kfree(sk);
module_put(owner);
}
@@ -698,7 +719,7 @@ void sock_wfree(struct sk_buff *skb)
/* In case it might be waiting for more memory. */
atomic_sub(skb->truesize, &sk->sk_wmem_alloc);
- if (!sk->sk_use_write_queue)
+ if (!sock_flag(sk, SOCK_USE_WRITE_QUEUE))
sk->sk_write_space(sk);
sock_put(sk);
}
@@ -1175,9 +1196,10 @@ void sock_init_data(struct socket *sock, struct sock *sk)
sk->sk_rcvbuf = sysctl_rmem_default;
sk->sk_sndbuf = sysctl_wmem_default;
sk->sk_state = TCP_CLOSE;
- sk->sk_zapped = 1;
sk->sk_socket = sock;
+ sock_set_flag(sk, SOCK_ZAPPED);
+
if(sock)
{
sk->sk_type = sock->type;
@@ -1352,7 +1374,13 @@ int sk_alloc_slab(struct proto *prot, char *name)
prot->slab_obj_size, 0,
SLAB_HWCACHE_ALIGN, NULL, NULL);
- return prot->slab != NULL ? 0 : -ENOBUFS;
+ if (prot->slab == NULL) {
+ printk(KERN_CRIT "%s: Can't create sock SLAB cache!\n",
+ prot->name);
+ return -ENOBUFS;
+ }
+
+ return 0;
}
EXPORT_SYMBOL(sk_alloc_slab);
diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c
index 056bac657275f..442075a7eaec0 100644
--- a/net/decnet/af_decnet.c
+++ b/net/decnet/af_decnet.c
@@ -456,8 +456,6 @@ static struct sock *dn_alloc_sock(struct socket *sock, int gfp)
if (!sk)
goto out;
- sk->sk_protinfo = scp = (struct dn_scp *)(sk + 1);
-
if (sock)
sock->ops = &dn_proto_ops;
sock_init_data(sock, sk);
@@ -471,6 +469,7 @@ static struct sock *dn_alloc_sock(struct socket *sock, int gfp)
sk->sk_allocation = gfp;
/* Initialization of DECnet Session Control Port */
+ scp = DN_SK(sk);
scp->state = DN_O; /* Open */
scp->numdat = 1; /* Next data seg to tx */
scp->numoth = 1; /* Next oth data to tx */
@@ -751,14 +750,13 @@ static int dn_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
rv = -EINVAL;
lock_sock(sk);
- if (sk->sk_zapped) {
+ if (sock_flag(sk, SOCK_ZAPPED)) {
memcpy(&scp->addr, saddr, addr_len);
- sk->sk_zapped = 0;
+ sock_reset_flag(sk, SOCK_ZAPPED);
rv = dn_hash_sock(sk);
- if (rv) {
- sk->sk_zapped = 1;
- }
+ if (rv)
+ sock_set_flag(sk, SOCK_ZAPPED);
}
release_sock(sk);
@@ -772,7 +770,7 @@ static int dn_auto_bind(struct socket *sock)
struct dn_scp *scp = DN_SK(sk);
int rv;
- sk->sk_zapped = 0;
+ sock_reset_flag(sk, SOCK_ZAPPED);
scp->addr.sdn_flags = 0;
scp->addr.sdn_objnum = 0;
@@ -796,9 +794,8 @@ static int dn_auto_bind(struct socket *sock)
rv = dn_dev_bind_default((dn_address *)scp->addr.sdn_add.a_addr);
if (rv == 0) {
rv = dn_hash_sock(sk);
- if (rv) {
- sk->sk_zapped = 1;
- }
+ if (rv)
+ sock_set_flag(sk, SOCK_ZAPPED);
}
return rv;
@@ -814,7 +811,7 @@ static int dn_confirm_accept(struct sock *sk, long *timeo, int allocation)
return -EINVAL;
scp->state = DN_CC;
- scp->segsize_loc = dst_path_metric(__sk_dst_get(sk), RTAX_ADVMSS);
+ scp->segsize_loc = dst_metric(__sk_dst_get(sk), RTAX_ADVMSS);
dn_send_conn_conf(sk, allocation);
prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
@@ -923,7 +920,7 @@ static int __dn_connect(struct sock *sk, struct sockaddr_dn *addr, int addrlen,
if (addr->sdn_flags & SDF_WILD)
goto out;
- if (sk->sk_zapped) {
+ if (sock_flag(sk, SOCK_ZAPPED)) {
err = dn_auto_bind(sk->sk_socket);
if (err)
goto out;
@@ -943,7 +940,7 @@ static int __dn_connect(struct sock *sk, struct sockaddr_dn *addr, int addrlen,
sk->sk_route_caps = sk->sk_dst_cache->dev->features;
sock->state = SS_CONNECTING;
scp->state = DN_CI;
- scp->segsize_loc = dst_path_metric(sk->sk_dst_cache, RTAX_ADVMSS);
+ scp->segsize_loc = dst_metric(sk->sk_dst_cache, RTAX_ADVMSS);
dn_nsp_send_conninit(sk, NSP_CI);
err = -EINPROGRESS;
@@ -1142,7 +1139,7 @@ static int dn_accept(struct socket *sock, struct socket *newsock, int flags)
lock_sock(newsk);
err = dn_hash_sock(newsk);
if (err == 0) {
- newsk->sk_zapped = 0;
+ sock_reset_flag(newsk, SOCK_ZAPPED);
dn_send_conn_ack(newsk);
/*
@@ -1260,7 +1257,7 @@ static int dn_listen(struct socket *sock, int backlog)
lock_sock(sk);
- if (sk->sk_zapped)
+ if (sock_flag(sk, SOCK_ZAPPED))
goto out;
if ((DN_SK(sk)->state != DN_O) || (sk->sk_state == TCP_LISTEN))
@@ -1672,7 +1669,7 @@ static int dn_recvmsg(struct kiocb *iocb, struct socket *sock,
lock_sock(sk);
- if (sk->sk_zapped) {
+ if (sock_flag(sk, SOCK_ZAPPED)) {
rv = -EADDRNOTAVAIL;
goto out;
}
@@ -1869,7 +1866,7 @@ static inline unsigned int dn_current_mss(struct sock *sk, int flags)
/* This works out the maximum size of segment we can send out */
if (dst) {
- u32 mtu = dst_pmtu(dst);
+ u32 mtu = dst_mtu(dst);
mss_now = min_t(int, dn_mss_from_pmtu(dst->dev, mtu), mss_now);
}
diff --git a/net/decnet/dn_nsp_in.c b/net/decnet/dn_nsp_in.c
index d8e24d47d044a..202dbde9850d4 100644
--- a/net/decnet/dn_nsp_in.c
+++ b/net/decnet/dn_nsp_in.c
@@ -324,7 +324,7 @@ err_out:
static void dn_nsp_conn_init(struct sock *sk, struct sk_buff *skb)
{
- if (sk->sk_ack_backlog >= sk->sk_max_ack_backlog) {
+ if (sk_acceptq_is_full(sk)) {
kfree_skb(skb);
return;
}
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c
index 309a8b317a9ed..1e7b5c3ea2154 100644
--- a/net/decnet/dn_route.c
+++ b/net/decnet/dn_route.c
@@ -253,7 +253,6 @@ static void dn_dst_update_pmtu(struct dst_entry *dst, u32 mtu)
*/
static struct dst_entry *dn_dst_check(struct dst_entry *dst, __u32 cookie)
{
- dst_release(dst);
return NULL;
}
@@ -818,7 +817,7 @@ static int dn_rt_set_next_hop(struct dn_route *rt, struct dn_fib_res *res)
if (rt->u.dst.metrics[RTAX_MTU-1] == 0 ||
rt->u.dst.metrics[RTAX_MTU-1] > rt->u.dst.dev->mtu)
rt->u.dst.metrics[RTAX_MTU-1] = rt->u.dst.dev->mtu;
- mss = dn_mss_from_pmtu(dev, dst_pmtu(&rt->u.dst));
+ mss = dn_mss_from_pmtu(dev, dst_mtu(&rt->u.dst));
if (rt->u.dst.metrics[RTAX_ADVMSS-1] == 0 ||
rt->u.dst.metrics[RTAX_ADVMSS-1] > mss)
rt->u.dst.metrics[RTAX_ADVMSS-1] = mss;
diff --git a/net/econet/af_econet.c b/net/econet/af_econet.c
index 06f5460516e0f..70f01713d89b0 100644
--- a/net/econet/af_econet.c
+++ b/net/econet/af_econet.c
@@ -184,7 +184,7 @@ static int econet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len
{
struct sockaddr_ec *sec = (struct sockaddr_ec *)uaddr;
struct sock *sk=sock->sk;
- struct econet_opt *eo = ec_sk(sk);
+ struct econet_sock *eo = ec_sk(sk);
/*
* Check legality
@@ -284,7 +284,7 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
*/
if (saddr == NULL) {
- struct econet_opt *eo = ec_sk(sk);
+ struct econet_sock *eo = ec_sk(sk);
addr.station = eo->station;
addr.net = eo->net;
@@ -437,8 +437,8 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
void __user *base = msg->msg_iov[i].iov_base;
size_t len = msg->msg_iov[i].iov_len;
/* Check it now since we switch to KERNEL_DS later. */
- if ((err = verify_area(VERIFY_READ, base, len)) < 0)
- return err;
+ if (!access_ok(VERIFY_READ, base, len))
+ return -EFAULT;
iov[i+1].iov_base = base;
iov[i+1].iov_len = len;
size += len;
@@ -485,7 +485,7 @@ static int econet_getname(struct socket *sock, struct sockaddr *uaddr,
int *uaddr_len, int peer)
{
struct sock *sk = sock->sk;
- struct econet_opt *eo = ec_sk(sk);
+ struct econet_sock *eo = ec_sk(sk);
struct sockaddr_ec *sec = (struct sockaddr_ec *)uaddr;
if (peer)
@@ -562,7 +562,7 @@ static int econet_release(struct socket *sock)
static int econet_create(struct socket *sock, int protocol)
{
struct sock *sk;
- struct econet_opt *eo;
+ struct econet_sock *eo;
int err;
/* Econet only provides datagram services. */
@@ -572,7 +572,8 @@ static int econet_create(struct socket *sock, int protocol)
sock->state = SS_UNCONNECTED;
err = -ENOBUFS;
- sk = sk_alloc(PF_ECONET, GFP_KERNEL, 1, NULL);
+ sk = sk_alloc(PF_ECONET, GFP_KERNEL,
+ sizeof(struct econet_sock), NULL);
if (sk == NULL)
goto out;
@@ -581,19 +582,13 @@ static int econet_create(struct socket *sock, int protocol)
sock_init_data(sock,sk);
sk_set_owner(sk, THIS_MODULE);
- eo = sk->sk_protinfo = kmalloc(sizeof(*eo), GFP_KERNEL);
- if (!eo)
- goto out_free;
- memset(eo, 0, sizeof(*eo));
- sk->sk_zapped = 0;
+ eo = ec_sk(sk);
+ sock_reset_flag(sk, SOCK_ZAPPED);
sk->sk_family = PF_ECONET;
eo->num = protocol;
econet_insert_socket(&econet_sklist, sk);
return(0);
-
-out_free:
- sk_free(sk);
out:
return err;
}
@@ -735,7 +730,7 @@ static struct sock *ec_listening_socket(unsigned char port, unsigned char
struct hlist_node *node;
sk_for_each(sk, node, &econet_sklist) {
- struct econet_opt *opt = ec_sk(sk);
+ struct econet_sock *opt = ec_sk(sk);
if ((opt->port == port || opt->port == 0) &&
(opt->station == station || opt->station == 0) &&
(opt->net == net || opt->net == 0))
diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig
index 8fe95800fe837..6d3e8b1bd1f20 100644
--- a/net/ipv4/Kconfig
+++ b/net/ipv4/Kconfig
@@ -90,6 +90,48 @@ config IP_ROUTE_MULTIPATH
equal "cost" and chooses one of them in a non-deterministic fashion
if a matching packet arrives.
+config IP_ROUTE_MULTIPATH_CACHED
+ bool "IP: equal cost multipath with caching support (EXPERIMENTAL)"
+ depends on: IP_ROUTE_MULTIPATH
+ help
+ Normally, equal cost multipath routing is not supported by the
+ routing cache. If you say Y here, alternative routes are cached
+ and on cache lookup a route is chosen in a configurable fashion.
+
+ If unsure, say N.
+
+config IP_ROUTE_MULTIPATH_RR
+ tristate "MULTIPATH: round robin algorithm"
+ depends on IP_ROUTE_MULTIPATH_CACHED
+ help
+ Mulitpath routes are chosen according to Round Robin
+
+config IP_ROUTE_MULTIPATH_RANDOM
+ tristate "MULTIPATH: random algorithm"
+ depends on IP_ROUTE_MULTIPATH_CACHED
+ help
+ Multipath routes are chosen in a random fashion. Actually,
+ there is no weight for a route. The advantage of this policy
+ is that it is implemented stateless and therefore introduces only
+ a very small delay.
+
+config IP_ROUTE_MULTIPATH_WRANDOM
+ tristate "MULTIPATH: weighted random algorithm"
+ depends on IP_ROUTE_MULTIPATH_CACHED
+ help
+ Multipath routes are chosen in a weighted random fashion.
+ The per route weights are the weights visible via ip route 2. As the
+ corresponding state management introduces some overhead routing delay
+ is increased.
+
+config IP_ROUTE_MULTIPATH_DRR
+ tristate "MULTIPATH: interface round robin algorithm"
+ depends on IP_ROUTE_MULTIPATH_CACHED
+ help
+ Connections are distributed in a round robin fashion over the
+ available interfaces. This policy makes sense if the connections
+ should be primarily distributed on interfaces and not on routes.
+
config IP_ROUTE_VERBOSE
bool "IP: verbose route monitoring"
depends on IP_ADVANCED_ROUTER
diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile
index e0f24f50ed3e6..8b379627ebb66 100644
--- a/net/ipv4/Makefile
+++ b/net/ipv4/Makefile
@@ -20,9 +20,14 @@ obj-$(CONFIG_INET_ESP) += esp4.o
obj-$(CONFIG_INET_IPCOMP) += ipcomp.o
obj-$(CONFIG_INET_TUNNEL) += xfrm4_tunnel.o
obj-$(CONFIG_IP_PNP) += ipconfig.o
+obj-$(CONFIG_IP_ROUTE_MULTIPATH_RR) += multipath_rr.o
+obj-$(CONFIG_IP_ROUTE_MULTIPATH_RANDOM) += multipath_random.o
+obj-$(CONFIG_IP_ROUTE_MULTIPATH_WRANDOM) += multipath_wrandom.o
+obj-$(CONFIG_IP_ROUTE_MULTIPATH_DRR) += multipath_drr.o
obj-$(CONFIG_NETFILTER) += netfilter/
obj-$(CONFIG_IP_VS) += ipvs/
obj-$(CONFIG_IP_TCPDIAG) += tcp_diag.o
+obj-$(CONFIG_IP_ROUTE_MULTIPATH_CACHED) += multipath.o
obj-$(CONFIG_XFRM) += xfrm4_policy.o xfrm4_state.o xfrm4_input.o \
xfrm4_output.o
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 859f67245932d..aa4fb251c54c7 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -1027,20 +1027,16 @@ static int __init inet_init(void)
}
rc = sk_alloc_slab(&tcp_prot, "tcp_sock");
- if (rc) {
- sk_alloc_slab_error(&tcp_prot);
+ if (rc)
goto out;
- }
+
rc = sk_alloc_slab(&udp_prot, "udp_sock");
- if (rc) {
- sk_alloc_slab_error(&udp_prot);
+ if (rc)
goto out_tcp_free_slab;
- }
+
rc = sk_alloc_slab(&raw_prot, "raw_sock");
- if (rc) {
- sk_alloc_slab_error(&raw_prot);
+ if (rc)
goto out_udp_free_slab;
- }
/*
* Tell SOCKET that we are alive...
diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c
index f7199e997bd54..0e98f2235b6e1 100644
--- a/net/ipv4/ah4.c
+++ b/net/ipv4/ah4.c
@@ -53,11 +53,9 @@ static int ip_clear_mutable_options(struct iphdr *iph, u32 *daddr)
return 0;
}
-static int ah_output(struct sk_buff *skb)
+static int ah_output(struct xfrm_state *x, struct sk_buff *skb)
{
int err;
- struct dst_entry *dst = skb->dst;
- struct xfrm_state *x = dst->xfrm;
struct iphdr *iph, *top_iph;
struct ip_auth_hdr *ah;
struct ah_data *ahp;
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index 9b4b933641640..a642fd6128533 100644
--- a/net/ipv4/arp.c
+++ b/net/ipv4/arp.c
@@ -1243,7 +1243,7 @@ void __init arp_init(void)
arp_proc_init();
#ifdef CONFIG_SYSCTL
neigh_sysctl_register(NULL, &arp_tbl.parms, NET_IPV4,
- NET_IPV4_NEIGH, "ipv4", NULL);
+ NET_IPV4_NEIGH, "ipv4", NULL, NULL);
#endif
register_netdevice_notifier(&arp_netdev_notifier);
}
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index d9559e8ed00ae..25b94e0be09ee 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -153,7 +153,7 @@ struct in_device *inetdev_init(struct net_device *dev)
dev_hold(dev);
#ifdef CONFIG_SYSCTL
neigh_sysctl_register(dev, in_dev->arp_parms, NET_IPV4,
- NET_IPV4_NEIGH, "ipv4", NULL);
+ NET_IPV4_NEIGH, "ipv4", NULL, NULL);
#endif
/* Account for reference dev->ip_ptr */
@@ -187,6 +187,10 @@ static void inetdev_destroy(struct in_device *in_dev)
ASSERT_RTNL();
+ dev = in_dev->dev;
+ if (dev == &loopback_dev)
+ return;
+
in_dev->dead = 1;
ip_mc_destroy_dev(in_dev);
@@ -200,7 +204,6 @@ static void inetdev_destroy(struct in_device *in_dev)
devinet_sysctl_unregister(&in_dev->cnf);
#endif
- dev = in_dev->dev;
dev->ip_ptr = NULL;
#ifdef CONFIG_SYSCTL
@@ -386,6 +389,7 @@ static int inet_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg
struct in_device *in_dev;
struct ifaddrmsg *ifm = NLMSG_DATA(nlh);
struct in_ifaddr *ifa, **ifap;
+ int real_prefixlen = IFA_REAL_DEL_PREFIX(ifm->ifa_prefixlen);
ASSERT_RTNL();
@@ -396,12 +400,13 @@ static int inet_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg
for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL;
ifap = &ifa->ifa_next) {
if ((rta[IFA_LOCAL - 1] &&
+ (!inet_ifa_match_local_prefixlen(ifm, ifa) ||
memcmp(RTA_DATA(rta[IFA_LOCAL - 1]),
- &ifa->ifa_local, 4)) ||
+ &ifa->ifa_local, 4))) ||
(rta[IFA_LABEL - 1] &&
rtattr_strcmp(rta[IFA_LABEL - 1], ifa->ifa_label)) ||
(rta[IFA_ADDRESS - 1] &&
- (ifm->ifa_prefixlen != ifa->ifa_prefixlen ||
+ (real_prefixlen != ifa->ifa_prefixlen ||
!inet_ifa_match(*(u32*)RTA_DATA(rta[IFA_ADDRESS - 1]),
ifa))))
continue;
@@ -943,8 +948,16 @@ static int inetdev_event(struct notifier_block *this, unsigned long event,
ASSERT_RTNL();
- if (!in_dev)
+ if (!in_dev) {
+ if (event == NETDEV_REGISTER && dev == &loopback_dev) {
+ in_dev = inetdev_init(dev);
+ if (!in_dev)
+ panic("devinet: Failed to create loopback\n");
+ in_dev->cnf.no_xfrm = 1;
+ in_dev->cnf.no_policy = 1;
+ }
goto out;
+ }
switch (event) {
case NETDEV_REGISTER:
@@ -967,8 +980,6 @@ static int inetdev_event(struct notifier_block *this, unsigned long event,
memcpy(ifa->ifa_label, dev->name, IFNAMSIZ);
inet_insert_ifa(ifa);
}
- in_dev->cnf.no_xfrm = 1;
- in_dev->cnf.no_policy = 1;
}
ip_mc_up(in_dev);
break;
@@ -992,7 +1003,7 @@ static int inetdev_event(struct notifier_block *this, unsigned long event,
devinet_sysctl_unregister(&in_dev->cnf);
neigh_sysctl_unregister(in_dev->arp_parms);
neigh_sysctl_register(dev, in_dev->arp_parms, NET_IPV4,
- NET_IPV4_NEIGH, "ipv4", NULL);
+ NET_IPV4_NEIGH, "ipv4", NULL, NULL);
devinet_sysctl_register(in_dev, &in_dev->cnf);
#endif
break;
@@ -1212,7 +1223,7 @@ int ipv4_doint_and_flush_strategy(ctl_table *table, int __user *name, int nlen,
static struct devinet_sysctl_table {
struct ctl_table_header *sysctl_header;
- ctl_table devinet_vars[20];
+ ctl_table devinet_vars[__NET_IPV4_CONF_MAX];
ctl_table devinet_dev[2];
ctl_table devinet_conf_dir[2];
ctl_table devinet_proto_dir[2];
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index 49d3cee6ded77..053a883247ba6 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -17,11 +17,9 @@ struct esp_decap_data {
__u8 proto;
};
-static int esp_output(struct sk_buff *skb)
+static int esp_output(struct xfrm_state *x, struct sk_buff *skb)
{
int err;
- struct dst_entry *dst = skb->dst;
- struct xfrm_state *x = dst->xfrm;
struct iphdr *top_iph;
struct ip_esp_hdr *esph;
struct crypto_tfm *tfm;
diff --git a/net/ipv4/fib_hash.c b/net/ipv4/fib_hash.c
index 688e551cc5aff..6506dcc01b460 100644
--- a/net/ipv4/fib_hash.c
+++ b/net/ipv4/fib_hash.c
@@ -93,6 +93,7 @@ static inline u32 fz_key(u32 dst, struct fn_zone *fz)
}
static DEFINE_RWLOCK(fib_hash_lock);
+static unsigned int fib_hash_genid;
#define FZ_MAX_DIVISOR ((PAGE_SIZE<<MAX_ORDER) / sizeof(struct hlist_head))
@@ -181,6 +182,7 @@ static void fn_rehash_zone(struct fn_zone *fz)
fz->fz_hashmask = new_hashmask;
fz->fz_divisor = new_divisor;
fn_rebuild_zone(fz, old_ht, old_divisor);
+ fib_hash_genid++;
write_unlock_bh(&fib_hash_lock);
fz_hash_free(old_ht, old_divisor);
@@ -236,6 +238,7 @@ fn_new_zone(struct fn_hash *table, int z)
table->fn_zones[i]->fz_next = fz;
}
table->fn_zones[z] = fz;
+ fib_hash_genid++;
write_unlock_bh(&fib_hash_lock);
return fz;
}
@@ -261,6 +264,7 @@ fn_hash_lookup(struct fib_table *tb, const struct flowi *flp, struct fib_result
err = fib_semantic_match(&f->fn_alias,
flp, res,
+ f->fn_key, fz->fz_mask,
fz->fz_order);
if (err <= 0)
goto out;
@@ -451,6 +455,7 @@ fn_hash_insert(struct fib_table *tb, struct rtmsg *r, struct kern_rta *rta,
fa->fa_scope = r->rtm_scope;
state = fa->fa_state;
fa->fa_state &= ~FA_S_ACCESSED;
+ fib_hash_genid++;
write_unlock_bh(&fib_hash_lock);
fib_release_info(fi_drop);
@@ -515,6 +520,7 @@ fn_hash_insert(struct fib_table *tb, struct rtmsg *r, struct kern_rta *rta,
fib_insert_node(fz, new_f);
list_add_tail(&new_fa->fa_list,
(fa ? &fa->fa_list : &f->fn_alias));
+ fib_hash_genid++;
write_unlock_bh(&fib_hash_lock);
if (new_f)
@@ -600,6 +606,7 @@ fn_hash_delete(struct fib_table *tb, struct rtmsg *r, struct kern_rta *rta,
hlist_del(&f->fn_hash);
kill_fn = 1;
}
+ fib_hash_genid++;
write_unlock_bh(&fib_hash_lock);
if (fa->fa_state & FA_S_ACCESSED)
@@ -637,6 +644,7 @@ static int fn_flush_list(struct fn_zone *fz, int idx)
hlist_del(&f->fn_hash);
kill_f = 1;
}
+ fib_hash_genid++;
write_unlock_bh(&fib_hash_lock);
fn_free_alias(fa);
@@ -684,7 +692,7 @@ fn_hash_dump_bucket(struct sk_buff *skb, struct netlink_callback *cb,
list_for_each_entry(fa, &f->fn_alias, fa_list) {
if (i < s_i)
- continue;
+ goto next;
if (fib_dump_info(skb, NETLINK_CB(cb->skb).pid,
cb->nlh->nlmsg_seq,
@@ -699,7 +707,7 @@ fn_hash_dump_bucket(struct sk_buff *skb, struct netlink_callback *cb,
cb->args[3] = i;
return -1;
}
-
+ next:
i++;
}
}
@@ -801,6 +809,9 @@ struct fib_iter_state {
struct hlist_head *hash_head;
struct fib_node *fn;
struct fib_alias *fa;
+ loff_t pos;
+ unsigned int genid;
+ int valid;
};
static struct fib_alias *fib_get_first(struct seq_file *seq)
@@ -812,6 +823,9 @@ static struct fib_alias *fib_get_first(struct seq_file *seq)
iter->hash_head = NULL;
iter->fn = NULL;
iter->fa = NULL;
+ iter->pos = 0;
+ iter->genid = fib_hash_genid;
+ iter->valid = 1;
for (iter->zone = table->fn_zone_list; iter->zone;
iter->zone = iter->zone->fz_next) {
@@ -916,16 +930,34 @@ static struct fib_alias *fib_get_next(struct seq_file *seq)
}
}
out:
+ iter->pos++;
return fa;
}
+static struct fib_alias *fib_get_idx(struct seq_file *seq, loff_t pos)
+{
+ struct fib_iter_state *iter = seq->private;
+ struct fib_alias *fa;
+
+ if (iter->valid && pos >= iter->pos && iter->genid == fib_hash_genid) {
+ fa = iter->fa;
+ pos -= iter->pos;
+ } else
+ fa = fib_get_first(seq);
+
+ if (fa)
+ while (pos && (fa = fib_get_next(seq)))
+ --pos;
+ return pos ? NULL : fa;
+}
+
static void *fib_seq_start(struct seq_file *seq, loff_t *pos)
{
void *v = NULL;
read_lock(&fib_hash_lock);
if (ip_fib_main_table)
- v = *pos ? fib_get_next(seq) : SEQ_START_TOKEN;
+ v = *pos ? fib_get_idx(seq, *pos - 1) : SEQ_START_TOKEN;
return v;
}
diff --git a/net/ipv4/fib_lookup.h b/net/ipv4/fib_lookup.h
index 56debc86eab02..ac4485f75e975 100644
--- a/net/ipv4/fib_lookup.h
+++ b/net/ipv4/fib_lookup.h
@@ -19,7 +19,8 @@ struct fib_alias {
/* Exported by fib_semantics.c */
extern int fib_semantic_match(struct list_head *head,
const struct flowi *flp,
- struct fib_result *res, int prefixlen);
+ struct fib_result *res, __u32 zone, __u32 mask,
+ int prefixlen);
extern void fib_release_info(struct fib_info *);
extern struct fib_info *fib_create_info(const struct rtmsg *r,
struct kern_rta *rta,
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index edf74c31e2cd8..029362d661351 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -42,6 +42,7 @@
#include <net/tcp.h>
#include <net/sock.h>
#include <net/ip_fib.h>
+#include <net/ip_mp_alg.h>
#include "fib_lookup.h"
@@ -649,6 +650,9 @@ fib_create_info(const struct rtmsg *r, struct kern_rta *rta,
#else
const int nhs = 1;
#endif
+#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
+ u32 mp_alg = IP_MP_ALG_NONE;
+#endif
/* Fast check to catch the most weird cases */
if (fib_props[r->rtm_type].scope > r->rtm_scope)
@@ -661,6 +665,15 @@ fib_create_info(const struct rtmsg *r, struct kern_rta *rta,
goto err_inval;
}
#endif
+#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
+ if (rta->rta_mp_alg) {
+ mp_alg = *rta->rta_mp_alg;
+
+ if (mp_alg < IP_MP_ALG_NONE ||
+ mp_alg > IP_MP_ALG_MAX)
+ goto err_inval;
+ }
+#endif
err = -ENOBUFS;
if (fib_info_cnt >= fib_hash_size) {
@@ -752,6 +765,10 @@ fib_create_info(const struct rtmsg *r, struct kern_rta *rta,
#endif
}
+#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
+ fi->fib_mp_alg = mp_alg;
+#endif
+
if (fib_props[r->rtm_type].error) {
if (rta->rta_gw || rta->rta_oif || rta->rta_mp)
goto err_inval;
@@ -831,7 +848,8 @@ failure:
}
int fib_semantic_match(struct list_head *head, const struct flowi *flp,
- struct fib_result *res, int prefixlen)
+ struct fib_result *res, __u32 zone, __u32 mask,
+ int prefixlen)
{
struct fib_alias *fa;
int nh_sel = 0;
@@ -895,6 +913,11 @@ out_fill_res:
res->type = fa->fa_type;
res->scope = fa->fa_scope;
res->fi = fa->fa_info;
+#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
+ res->netmask = mask;
+ res->network = zone &
+ (0xFFFFFFFF >> (32 - prefixlen));
+#endif
atomic_inc(&res->fi->fib_clntref);
return 0;
}
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index dc2e14faedb8e..85bf0d3e294b2 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -518,14 +518,6 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, u32 info)
IPTOS_PREC_INTERNETCONTROL) :
iph->tos;
- {
- struct flowi fl = { .nl_u = { .ip4_u = { .daddr = iph->saddr,
- .saddr = saddr,
- .tos = RT_TOS(tos) } },
- .proto = IPPROTO_ICMP };
- if (ip_route_output_key(&rt, &fl))
- goto out_unlock;
- }
if (ip_options_echo(&icmp_param.replyopts, skb_in))
goto ende;
@@ -544,13 +536,26 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, u32 info)
inet_sk(icmp_socket->sk)->tos = tos;
ipc.addr = iph->saddr;
ipc.opt = &icmp_param.replyopts;
- if (icmp_param.replyopts.srr) {
- struct flowi fl = { .nl_u = { .ip4_u =
- { .daddr = icmp_param.replyopts.faddr,
- .saddr = saddr,
- .tos = RT_TOS(tos) } },
- .proto = IPPROTO_ICMP };
- ip_rt_put(rt);
+
+ {
+ struct flowi fl = {
+ .nl_u = {
+ .ip4_u = {
+ .daddr = icmp_param.replyopts.srr ?
+ icmp_param.replyopts.faddr :
+ iph->saddr,
+ .saddr = saddr,
+ .tos = RT_TOS(tos)
+ }
+ },
+ .proto = IPPROTO_ICMP,
+ .uli_u = {
+ .icmpt = {
+ .type = type,
+ .code = code
+ }
+ }
+ };
if (ip_route_output_key(&rt, &fl))
goto out_unlock;
}
@@ -560,7 +565,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, u32 info)
/* RFC says return as much as we can without exceeding 576 bytes. */
- room = dst_pmtu(&rt->u.dst);
+ room = dst_mtu(&rt->u.dst);
if (room > 576)
room = 576;
room -= sizeof(struct iphdr) + icmp_param.replyopts.optlen;
diff --git a/net/ipv4/inetpeer.c b/net/ipv4/inetpeer.c
index 9942d1146828a..95473953c406e 100644
--- a/net/ipv4/inetpeer.c
+++ b/net/ipv4/inetpeer.c
@@ -92,9 +92,9 @@ int inet_peer_threshold = 65536 + 128; /* start to throw entries more
int inet_peer_minttl = 120 * HZ; /* TTL under high load: 120 sec */
int inet_peer_maxttl = 10 * 60 * HZ; /* usual time to live: 10 min */
+static struct inet_peer *inet_peer_unused_head;
/* Exported for inet_putpeer inline function. */
-struct inet_peer *inet_peer_unused_head,
- **inet_peer_unused_tailp = &inet_peer_unused_head;
+struct inet_peer **inet_peer_unused_tailp = &inet_peer_unused_head;
DEFINE_SPINLOCK(inet_peer_unused_lock);
#define PEER_MAX_CLEANUP_WORK 30
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index 1404a96ae350e..8848355222241 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -511,7 +511,7 @@ out:
/* change mtu on this route */
if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) {
- if (rel_info > dst_pmtu(skb2->dst)) {
+ if (rel_info > dst_mtu(skb2->dst)) {
kfree_skb(skb2);
return;
}
@@ -618,10 +618,8 @@ static int ipgre_rcv(struct sk_buff *skb)
skb->mac.raw = skb->nh.raw;
skb->nh.raw = __pskb_pull(skb, offset);
+ skb_postpull_rcsum(skb, skb->mac.raw, offset);
memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
- if (skb->ip_summed == CHECKSUM_HW)
- skb->csum = csum_sub(skb->csum,
- csum_partial(skb->mac.raw, skb->nh.raw-skb->mac.raw, 0));
skb->pkt_type = PACKET_HOST;
#ifdef CONFIG_NET_IPGRE_BROADCAST
if (MULTICAST(iph->daddr)) {
@@ -766,9 +764,9 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
df = tiph->frag_off;
if (df)
- mtu = dst_pmtu(&rt->u.dst) - tunnel->hlen;
+ mtu = dst_mtu(&rt->u.dst) - tunnel->hlen;
else
- mtu = skb->dst ? dst_pmtu(skb->dst) : dev->mtu;
+ mtu = skb->dst ? dst_mtu(skb->dst) : dev->mtu;
if (skb->dst)
skb->dst->ops->update_pmtu(skb->dst, mtu);
@@ -787,7 +785,7 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
else if (skb->protocol == htons(ETH_P_IPV6)) {
struct rt6_info *rt6 = (struct rt6_info*)skb->dst;
- if (rt6 && mtu < dst_pmtu(skb->dst) && mtu >= IPV6_MIN_MTU) {
+ if (rt6 && mtu < dst_mtu(skb->dst) && mtu >= IPV6_MIN_MTU) {
if ((tunnel->parms.iph.daddr && !MULTICAST(tunnel->parms.iph.daddr)) ||
rt6->rt6i_dst.plen == 128) {
rt6->rt6i_flags |= RTF_MODIFIED;
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
index 51069c0b57eb4..a0d0833034be7 100644
--- a/net/ipv4/ip_input.c
+++ b/net/ipv4/ip_input.c
@@ -410,10 +410,9 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
* is IP we can trim to the true length of the frame.
* Note this now means skb->len holds ntohs(iph->tot_len).
*/
- if (skb->len > len) {
- __pskb_trim(skb, len);
- if (skb->ip_summed == CHECKSUM_HW)
- skb->ip_summed = CHECKSUM_NONE;
+ if (pskb_trim_rcsum(skb, len)) {
+ IP_INC_STATS_BH(IPSTATS_MIB_INDISCARDS);
+ goto drop;
}
}
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 47054f8a3a33f..30ab7b6ab7618 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -278,7 +278,7 @@ int ip_mc_output(struct sk_buff *skb)
newskb->dev, ip_dev_loopback_xmit);
}
- if (skb->len > dst_pmtu(&rt->u.dst))
+ if (skb->len > dst_mtu(&rt->u.dst))
return ip_fragment(skb, ip_finish_output);
else
return ip_finish_output(skb);
@@ -288,7 +288,7 @@ int ip_output(struct sk_buff *skb)
{
IP_INC_STATS(IPSTATS_MIB_OUTREQUESTS);
- if (skb->len > dst_pmtu(skb->dst) && !skb_shinfo(skb)->tso_size)
+ if (skb->len > dst_mtu(skb->dst) && !skb_shinfo(skb)->tso_size)
return ip_fragment(skb, ip_finish_output);
else
return ip_finish_output(skb);
@@ -448,7 +448,7 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*))
if (unlikely((iph->frag_off & htons(IP_DF)) && !skb->local_df)) {
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED,
- htonl(dst_pmtu(&rt->u.dst)));
+ htonl(dst_mtu(&rt->u.dst)));
kfree_skb(skb);
return -EMSGSIZE;
}
@@ -458,7 +458,7 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*))
*/
hlen = iph->ihl * 4;
- mtu = dst_pmtu(&rt->u.dst) - hlen; /* Size of data space */
+ mtu = dst_mtu(&rt->u.dst) - hlen; /* Size of data space */
/* When frag_list is given, use it. First, check its validity:
* some transformers could create wrong frag_list or break existing
@@ -498,7 +498,7 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*))
skb->data_len = first_len - skb_headlen(skb);
skb->len = first_len;
iph->tot_len = htons(first_len);
- iph->frag_off |= htons(IP_MF);
+ iph->frag_off = htons(IP_MF);
ip_send_check(iph);
for (;;) {
@@ -746,7 +746,7 @@ int ip_append_data(struct sock *sk,
inet->cork.addr = ipc->addr;
}
dst_hold(&rt->u.dst);
- inet->cork.fragsize = mtu = dst_pmtu(&rt->u.dst);
+ inet->cork.fragsize = mtu = dst_mtu(rt->u.dst.path);
inet->cork.rt = rt;
inet->cork.length = 0;
sk->sk_sndmsg_page = NULL;
@@ -1152,7 +1152,8 @@ int ip_push_pending_frames(struct sock *sk)
* If local_df is set too, we still allow to fragment this frame
* locally. */
if (inet->pmtudisc == IP_PMTUDISC_DO ||
- (!skb_shinfo(skb)->frag_list && ip_dont_fragment(sk, &rt->u.dst)))
+ (skb->len <= dst_mtu(&rt->u.dst) &&
+ ip_dont_fragment(sk, &rt->u.dst)))
df = htons(IP_DF);
if (inet->cork.flags & IPCORK_OPT)
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index 48f9cfbcc6a51..47012b93cad2e 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -955,7 +955,7 @@ int ip_getsockopt(struct sock *sk, int level, int optname, char __user *optval,
val = 0;
dst = sk_dst_get(sk);
if (dst) {
- val = dst_pmtu(dst) - dst->header_len;
+ val = dst_mtu(dst);
dst_release(dst);
}
if (!val) {
diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c
index 89e320d5270ee..49eef7b3ec40e 100644
--- a/net/ipv4/ipcomp.c
+++ b/net/ipv4/ipcomp.c
@@ -154,11 +154,9 @@ out:
return err;
}
-static int ipcomp_output(struct sk_buff *skb)
+static int ipcomp_output(struct xfrm_state *x, struct sk_buff *skb)
{
int err;
- struct dst_entry *dst = skb->dst;
- struct xfrm_state *x = dst->xfrm;
struct iphdr *iph;
struct ip_comp_hdr *ipch;
struct ipcomp_data *ipcd = x->data;
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
index f91663c399ac8..68a78731f7224 100644
--- a/net/ipv4/ipip.c
+++ b/net/ipv4/ipip.c
@@ -436,7 +436,7 @@ out:
/* change mtu on this route */
if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) {
- if (rel_info > dst_pmtu(skb2->dst)) {
+ if (rel_info > dst_mtu(skb2->dst)) {
kfree_skb(skb2);
return;
}
@@ -569,9 +569,9 @@ static int ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
}
if (tiph->frag_off)
- mtu = dst_pmtu(&rt->u.dst) - sizeof(struct iphdr);
+ mtu = dst_mtu(&rt->u.dst) - sizeof(struct iphdr);
else
- mtu = skb->dst ? dst_pmtu(skb->dst) : dev->mtu;
+ mtu = skb->dst ? dst_mtu(skb->dst) : dev->mtu;
if (mtu < 68) {
tunnel->stat.collisions++;
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index 2568fe28dcd55..e21c049ec62ae 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -1171,7 +1171,7 @@ static void ipmr_queue_xmit(struct sk_buff *skb, struct mfc_cache *c, int vifi)
dev = rt->u.dst.dev;
- if (skb->len+encap > dst_pmtu(&rt->u.dst) && (ntohs(iph->frag_off) & IP_DF)) {
+ if (skb->len+encap > dst_mtu(&rt->u.dst) && (ntohs(iph->frag_off) & IP_DF)) {
/* Do not fragment multicasts. Alas, IPv4 does not
allow to send ICMP, so that packets will disappear
to blackhole.
diff --git a/net/ipv4/ipvs/ip_vs_core.c b/net/ipv4/ipvs/ip_vs_core.c
index a8ccdb7976536..5fb257dd07cb3 100644
--- a/net/ipv4/ipvs/ip_vs_core.c
+++ b/net/ipv4/ipvs/ip_vs_core.c
@@ -1003,7 +1003,7 @@ ip_vs_in(unsigned int hooknum, struct sk_buff **pskb,
/* Check the server status */
if (cp->dest && !(cp->dest->flags & IP_VS_DEST_F_AVAILABLE)) {
- /* the destination server is not availabe */
+ /* the destination server is not available */
if (sysctl_ip_vs_expire_nodest_conn) {
/* try to expire the connection immediately */
diff --git a/net/ipv4/ipvs/ip_vs_ctl.c b/net/ipv4/ipvs/ip_vs_ctl.c
index 102154138dbf9..218d9701036e4 100644
--- a/net/ipv4/ipvs/ip_vs_ctl.c
+++ b/net/ipv4/ipvs/ip_vs_ctl.c
@@ -26,7 +26,7 @@
#include <linux/fs.h>
#include <linux/sysctl.h>
#include <linux/proc_fs.h>
-#include <linux/timer.h>
+#include <linux/workqueue.h>
#include <linux/swap.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
@@ -90,7 +90,7 @@ int ip_vs_get_debug_level(void)
#endif
/*
- * update_defense_level is called from timer bh and from sysctl.
+ * update_defense_level is called from keventd and from sysctl.
*/
static void update_defense_level(void)
{
@@ -212,19 +212,19 @@ static void update_defense_level(void)
/*
* Timer for checking the defense
*/
-static struct timer_list defense_timer;
#define DEFENSE_TIMER_PERIOD 1*HZ
+static void defense_work_handler(void *data);
+static DECLARE_WORK(defense_work, defense_work_handler, NULL);
-static void defense_timer_handler(unsigned long data)
+static void defense_work_handler(void *data)
{
update_defense_level();
if (atomic_read(&ip_vs_dropentry))
ip_vs_random_dropentry();
- mod_timer(&defense_timer, jiffies + DEFENSE_TIMER_PERIOD);
+ schedule_delayed_work(&defense_work, DEFENSE_TIMER_PERIOD);
}
-
int
ip_vs_use_count_inc(void)
{
@@ -2370,10 +2370,7 @@ int ip_vs_control_init(void)
ip_vs_new_estimator(&ip_vs_stats);
/* Hook the defense timer */
- init_timer(&defense_timer);
- defense_timer.function = defense_timer_handler;
- defense_timer.expires = jiffies + DEFENSE_TIMER_PERIOD;
- add_timer(&defense_timer);
+ schedule_delayed_work(&defense_work, DEFENSE_TIMER_PERIOD);
LeaveFunction(2);
return 0;
@@ -2384,7 +2381,7 @@ void ip_vs_control_cleanup(void)
{
EnterFunction(2);
ip_vs_trash_cleanup();
- del_timer_sync(&defense_timer);
+ cancel_rearming_delayed_work(&defense_work);
ip_vs_kill_estimator(&ip_vs_stats);
unregister_sysctl_table(sysctl_header);
proc_net_remove("ip_vs_stats");
diff --git a/net/ipv4/ipvs/ip_vs_wrr.c b/net/ipv4/ipvs/ip_vs_wrr.c
index 5e02c8c698282..749fa044eca53 100644
--- a/net/ipv4/ipvs/ip_vs_wrr.c
+++ b/net/ipv4/ipvs/ip_vs_wrr.c
@@ -126,6 +126,8 @@ static int ip_vs_wrr_update_svc(struct ip_vs_service *svc)
mark->cl = &svc->destinations;
mark->mw = ip_vs_wrr_max_weight(svc);
mark->di = ip_vs_wrr_gcd_weight(svc);
+ if (mark->cw > mark->mw)
+ mark->cw = 0;
return 0;
}
@@ -163,7 +165,7 @@ ip_vs_wrr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
if (mark->cw <= 0) {
mark->cw = mark->mw;
/*
- * Still zero, which means no availabe servers.
+ * Still zero, which means no available servers.
*/
if (mark->cw == 0) {
mark->cl = &svc->destinations;
@@ -186,7 +188,7 @@ ip_vs_wrr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
}
}
- if (mark->cl == p) {
+ if (mark->cl == p && mark->cw == mark->di) {
/* back to the start, and no dest is found.
It is only possible when all dests are OVERLOADED */
dest = NULL;
diff --git a/net/ipv4/ipvs/ip_vs_xmit.c b/net/ipv4/ipvs/ip_vs_xmit.c
index 58db69d128168..faa6176bbeb19 100644
--- a/net/ipv4/ipvs/ip_vs_xmit.c
+++ b/net/ipv4/ipvs/ip_vs_xmit.c
@@ -52,6 +52,7 @@ __ip_vs_dst_check(struct ip_vs_dest *dest, u32 rtos, u32 cookie)
if ((dst->obsolete || rtos != dest->dst_rtos) &&
dst->ops->check(dst, cookie) == NULL) {
dest->dst_cache = NULL;
+ dst_release(dst);
return NULL;
}
dst_hold(dst);
@@ -177,7 +178,7 @@ ip_vs_bypass_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
}
/* MTU checking */
- mtu = dst_pmtu(&rt->u.dst);
+ mtu = dst_mtu(&rt->u.dst);
if ((skb->len > mtu) && (iph->frag_off&__constant_htons(IP_DF))) {
ip_rt_put(rt);
icmp_send(skb, ICMP_DEST_UNREACH,ICMP_FRAG_NEEDED, htonl(mtu));
@@ -244,7 +245,7 @@ ip_vs_nat_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
goto tx_error_icmp;
/* MTU checking */
- mtu = dst_pmtu(&rt->u.dst);
+ mtu = dst_mtu(&rt->u.dst);
if ((skb->len > mtu) && (iph->frag_off&__constant_htons(IP_DF))) {
ip_rt_put(rt);
icmp_send(skb, ICMP_DEST_UNREACH,ICMP_FRAG_NEEDED, htonl(mtu));
@@ -341,7 +342,7 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
tdev = rt->u.dst.dev;
- mtu = dst_pmtu(&rt->u.dst) - sizeof(struct iphdr);
+ mtu = dst_mtu(&rt->u.dst) - sizeof(struct iphdr);
if (mtu < 68) {
ip_rt_put(rt);
IP_VS_DBG_RL("ip_vs_tunnel_xmit(): mtu less than 68\n");
@@ -444,7 +445,7 @@ ip_vs_dr_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
goto tx_error_icmp;
/* MTU checking */
- mtu = dst_pmtu(&rt->u.dst);
+ mtu = dst_mtu(&rt->u.dst);
if ((iph->frag_off&__constant_htons(IP_DF)) && skb->len > mtu) {
icmp_send(skb, ICMP_DEST_UNREACH,ICMP_FRAG_NEEDED, htonl(mtu));
ip_rt_put(rt);
@@ -519,7 +520,7 @@ ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
goto tx_error_icmp;
/* MTU checking */
- mtu = dst_pmtu(&rt->u.dst);
+ mtu = dst_mtu(&rt->u.dst);
if ((skb->len > mtu) && (skb->nh.iph->frag_off&__constant_htons(IP_DF))) {
ip_rt_put(rt);
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu));
diff --git a/net/ipv4/multipath.c b/net/ipv4/multipath.c
new file mode 100644
index 0000000000000..4e9ca7c76407d
--- /dev/null
+++ b/net/ipv4/multipath.c
@@ -0,0 +1,55 @@
+/* multipath.c: IPV4 multipath algorithm support.
+ *
+ * Copyright (C) 2004, 2005 Einar Lueck <elueck@de.ibm.com>
+ * Copyright (C) 2005 David S. Miller <davem@davemloft.net>
+ */
+
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/netdevice.h>
+#include <linux/spinlock.h>
+
+#include <net/ip_mp_alg.h>
+
+static DEFINE_SPINLOCK(alg_table_lock);
+struct ip_mp_alg_ops *ip_mp_alg_table[IP_MP_ALG_MAX + 1];
+
+int multipath_alg_register(struct ip_mp_alg_ops *ops, enum ip_mp_alg n)
+{
+ struct ip_mp_alg_ops **slot;
+ int err;
+
+ if (n < IP_MP_ALG_NONE || n > IP_MP_ALG_MAX ||
+ !ops->mp_alg_select_route)
+ return -EINVAL;
+
+ spin_lock(&alg_table_lock);
+ slot = &ip_mp_alg_table[n];
+ if (*slot != NULL) {
+ err = -EBUSY;
+ } else {
+ *slot = ops;
+ err = 0;
+ }
+ spin_unlock(&alg_table_lock);
+
+ return err;
+}
+EXPORT_SYMBOL(multipath_alg_register);
+
+void multipath_alg_unregister(struct ip_mp_alg_ops *ops, enum ip_mp_alg n)
+{
+ struct ip_mp_alg_ops **slot;
+
+ if (n < IP_MP_ALG_NONE || n > IP_MP_ALG_MAX)
+ return;
+
+ spin_lock(&alg_table_lock);
+ slot = &ip_mp_alg_table[n];
+ if (*slot == ops)
+ *slot = NULL;
+ spin_unlock(&alg_table_lock);
+
+ synchronize_net();
+}
+EXPORT_SYMBOL(multipath_alg_unregister);
diff --git a/net/ipv4/multipath_drr.c b/net/ipv4/multipath_drr.c
new file mode 100644
index 0000000000000..9349686131fcf
--- /dev/null
+++ b/net/ipv4/multipath_drr.c
@@ -0,0 +1,265 @@
+/*
+ * Device round robin policy for multipath.
+ *
+ *
+ * Version: $Id: multipath_drr.c,v 1.1.2.1 2004/09/16 07:42:34 elueck Exp $
+ *
+ * Authors: Einar Lueck <elueck@de.ibm.com><lkml@einar-lueck.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/config.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/kernel.h>
+#include <linux/fcntl.h>
+#include <linux/stat.h>
+#include <linux/socket.h>
+#include <linux/in.h>
+#include <linux/inet.h>
+#include <linux/netdevice.h>
+#include <linux/inetdevice.h>
+#include <linux/igmp.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/mroute.h>
+#include <linux/init.h>
+#include <net/ip.h>
+#include <net/protocol.h>
+#include <linux/skbuff.h>
+#include <net/sock.h>
+#include <net/icmp.h>
+#include <net/udp.h>
+#include <net/raw.h>
+#include <linux/notifier.h>
+#include <linux/if_arp.h>
+#include <linux/netfilter_ipv4.h>
+#include <net/ipip.h>
+#include <net/checksum.h>
+#include <net/ip_mp_alg.h>
+
+struct multipath_device {
+ int ifi; /* interface index of device */
+ atomic_t usecount;
+ int allocated;
+};
+
+#define MULTIPATH_MAX_DEVICECANDIDATES 10
+
+static struct multipath_device state[MULTIPATH_MAX_DEVICECANDIDATES];
+static DEFINE_SPINLOCK(state_lock);
+static struct rtable *last_selection = NULL;
+
+static int inline __multipath_findslot(void)
+{
+ int i;
+
+ for (i = 0; i < MULTIPATH_MAX_DEVICECANDIDATES; i++) {
+ if (state[i].allocated == 0)
+ return i;
+ }
+ return -1;
+}
+
+static int inline __multipath_finddev(int ifindex)
+{
+ int i;
+
+ for (i = 0; i < MULTIPATH_MAX_DEVICECANDIDATES; i++) {
+ if (state[i].allocated != 0 &&
+ state[i].ifi == ifindex)
+ return i;
+ }
+ return -1;
+}
+
+static int drr_dev_event(struct notifier_block *this,
+ unsigned long event, void *ptr)
+{
+ struct net_device *dev = ptr;
+ int devidx;
+
+ switch (event) {
+ case NETDEV_UNREGISTER:
+ case NETDEV_DOWN:
+ spin_lock_bh(&state_lock);
+
+ devidx = __multipath_finddev(dev->ifindex);
+ if (devidx != -1) {
+ state[devidx].allocated = 0;
+ state[devidx].ifi = 0;
+ atomic_set(&state[devidx].usecount, 0);
+ }
+
+ spin_unlock_bh(&state_lock);
+ break;
+ };
+
+ return NOTIFY_DONE;
+}
+
+struct notifier_block drr_dev_notifier = {
+ .notifier_call = drr_dev_event,
+};
+
+static void drr_remove(struct rtable *rt)
+{
+ if (last_selection == rt)
+ last_selection = NULL;
+}
+
+static void drr_safe_inc(atomic_t *usecount)
+{
+ int n;
+
+ atomic_inc(usecount);
+
+ n = atomic_read(usecount);
+ if (n <= 0) {
+ int i;
+
+ spin_lock_bh(&state_lock);
+
+ for (i = 0; i < MULTIPATH_MAX_DEVICECANDIDATES; i++)
+ atomic_set(&state[i].usecount, 0);
+
+ spin_unlock_bh(&state_lock);
+ }
+}
+
+static void drr_select_route(const struct flowi *flp,
+ struct rtable *first, struct rtable **rp)
+{
+ struct rtable *nh, *result, *cur_min;
+ int min_usecount = -1;
+ int devidx = -1;
+ int cur_min_devidx = -1;
+
+ /* if necessary and possible utilize the old alternative */
+ if ((flp->flags & FLOWI_FLAG_MULTIPATHOLDROUTE) != 0 &&
+ last_selection != NULL) {
+ result = last_selection;
+ *rp = result;
+ return;
+ }
+
+ /* 1. make sure all alt. nexthops have the same GC related data */
+ /* 2. determine the new candidate to be returned */
+ result = NULL;
+ cur_min = NULL;
+ for (nh = rcu_dereference(first); nh;
+ nh = rcu_dereference(nh->u.rt_next)) {
+ if ((nh->u.dst.flags & DST_BALANCED) != 0 &&
+ multipath_comparekeys(&nh->fl, flp)) {
+ int nh_ifidx = nh->u.dst.dev->ifindex;
+
+ nh->u.dst.lastuse = jiffies;
+ nh->u.dst.__use++;
+ if (result != NULL)
+ continue;
+
+ /* search for the output interface */
+
+ /* this is not SMP safe, only add/remove are
+ * SMP safe as wrong usecount updates have no big
+ * impact
+ */
+ devidx = __multipath_finddev(nh_ifidx);
+ if (devidx == -1) {
+ /* add the interface to the array
+ * SMP safe
+ */
+ spin_lock_bh(&state_lock);
+
+ /* due to SMP: search again */
+ devidx = __multipath_finddev(nh_ifidx);
+ if (devidx == -1) {
+ /* add entry for device */
+ devidx = __multipath_findslot();
+ if (devidx == -1) {
+ /* unlikely but possible */
+ continue;
+ }
+
+ state[devidx].allocated = 1;
+ state[devidx].ifi = nh_ifidx;
+ atomic_set(&state[devidx].usecount, 0);
+ min_usecount = 0;
+ }
+
+ spin_unlock_bh(&state_lock);
+ }
+
+ if (min_usecount == 0) {
+ /* if the device has not been used it is
+ * the primary target
+ */
+ drr_safe_inc(&state[devidx].usecount);
+ result = nh;
+ } else {
+ int count =
+ atomic_read(&state[devidx].usecount);
+
+ if (min_usecount == -1 ||
+ count < min_usecount) {
+ cur_min = nh;
+ cur_min_devidx = devidx;
+ min_usecount = count;
+ }
+ }
+ }
+ }
+
+ if (!result) {
+ if (cur_min) {
+ drr_safe_inc(&state[cur_min_devidx].usecount);
+ result = cur_min;
+ } else {
+ result = first;
+ }
+ }
+
+ *rp = result;
+ last_selection = result;
+}
+
+static struct ip_mp_alg_ops drr_ops = {
+ .mp_alg_select_route = drr_select_route,
+ .mp_alg_remove = drr_remove,
+};
+
+static int __init drr_init(void)
+{
+ int err = register_netdevice_notifier(&drr_dev_notifier);
+
+ if (err)
+ return err;
+
+ err = multipath_alg_register(&drr_ops, IP_MP_ALG_RR);
+ if (err)
+ goto fail;
+
+ return 0;
+
+fail:
+ unregister_netdevice_notifier(&drr_dev_notifier);
+ return err;
+}
+
+static void __exit drr_exit(void)
+{
+ unregister_netdevice_notifier(&drr_dev_notifier);
+ multipath_alg_unregister(&drr_ops, IP_MP_ALG_DRR);
+}
+
+module_init(drr_init);
+module_exit(drr_exit);
diff --git a/net/ipv4/multipath_random.c b/net/ipv4/multipath_random.c
new file mode 100644
index 0000000000000..805a16e47de5f
--- /dev/null
+++ b/net/ipv4/multipath_random.c
@@ -0,0 +1,128 @@
+/*
+ * Random policy for multipath.
+ *
+ *
+ * Version: $Id: multipath_random.c,v 1.1.2.3 2004/09/21 08:42:11 elueck Exp $
+ *
+ * Authors: Einar Lueck <elueck@de.ibm.com><lkml@einar-lueck.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/config.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/kernel.h>
+#include <linux/fcntl.h>
+#include <linux/stat.h>
+#include <linux/socket.h>
+#include <linux/in.h>
+#include <linux/inet.h>
+#include <linux/netdevice.h>
+#include <linux/inetdevice.h>
+#include <linux/igmp.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/mroute.h>
+#include <linux/init.h>
+#include <net/ip.h>
+#include <net/protocol.h>
+#include <linux/skbuff.h>
+#include <net/sock.h>
+#include <net/icmp.h>
+#include <net/udp.h>
+#include <net/raw.h>
+#include <linux/notifier.h>
+#include <linux/if_arp.h>
+#include <linux/netfilter_ipv4.h>
+#include <net/ipip.h>
+#include <net/checksum.h>
+#include <net/ip_mp_alg.h>
+
+#define MULTIPATH_MAX_CANDIDATES 40
+
+/* interface to random number generation */
+static unsigned int RANDOM_SEED = 93186752;
+
+static inline unsigned int random(unsigned int ubound)
+{
+ static unsigned int a = 1588635695,
+ q = 2,
+ r = 1117695901;
+
+ RANDOM_SEED = a*(RANDOM_SEED % q) - r*(RANDOM_SEED / q);
+
+ return RANDOM_SEED % ubound;
+}
+
+
+static void random_select_route(const struct flowi *flp,
+ struct rtable *first,
+ struct rtable **rp)
+{
+ struct rtable *rt;
+ struct rtable *decision;
+ unsigned char candidate_count = 0;
+
+ /* count all candidate */
+ for (rt = rcu_dereference(first); rt;
+ rt = rcu_dereference(rt->u.rt_next)) {
+ if ((rt->u.dst.flags & DST_BALANCED) != 0 &&
+ multipath_comparekeys(&rt->fl, flp))
+ ++candidate_count;
+ }
+
+ /* choose a random candidate */
+ decision = first;
+ if (candidate_count > 1) {
+ unsigned char i = 0;
+ unsigned char candidate_no = (unsigned char)
+ random(candidate_count);
+
+ /* find chosen candidate and adjust GC data for all candidates
+ * to ensure they stay in cache
+ */
+ for (rt = first; rt; rt = rt->u.rt_next) {
+ if ((rt->u.dst.flags & DST_BALANCED) != 0 &&
+ multipath_comparekeys(&rt->fl, flp)) {
+ rt->u.dst.lastuse = jiffies;
+
+ if (i == candidate_no)
+ decision = rt;
+
+ if (i >= candidate_count)
+ break;
+
+ i++;
+ }
+ }
+ }
+
+ decision->u.dst.__use++;
+ *rp = decision;
+}
+
+static struct ip_mp_alg_ops random_ops = {
+ .mp_alg_select_route = random_select_route,
+};
+
+static int __init random_init(void)
+{
+ return multipath_alg_register(&random_ops, IP_MP_ALG_RANDOM);
+}
+
+static void __exit random_exit(void)
+{
+ multipath_alg_unregister(&random_ops, IP_MP_ALG_RANDOM);
+}
+
+module_init(random_init);
+module_exit(random_exit);
diff --git a/net/ipv4/multipath_rr.c b/net/ipv4/multipath_rr.c
new file mode 100644
index 0000000000000..554a825681602
--- /dev/null
+++ b/net/ipv4/multipath_rr.c
@@ -0,0 +1,115 @@
+/*
+ * Round robin policy for multipath.
+ *
+ *
+ * Version: $Id: multipath_rr.c,v 1.1.2.2 2004/09/16 07:42:34 elueck Exp $
+ *
+ * Authors: Einar Lueck <elueck@de.ibm.com><lkml@einar-lueck.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/config.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/kernel.h>
+#include <linux/fcntl.h>
+#include <linux/stat.h>
+#include <linux/socket.h>
+#include <linux/in.h>
+#include <linux/inet.h>
+#include <linux/netdevice.h>
+#include <linux/inetdevice.h>
+#include <linux/igmp.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/mroute.h>
+#include <linux/init.h>
+#include <net/ip.h>
+#include <net/protocol.h>
+#include <linux/skbuff.h>
+#include <net/sock.h>
+#include <net/icmp.h>
+#include <net/udp.h>
+#include <net/raw.h>
+#include <linux/notifier.h>
+#include <linux/if_arp.h>
+#include <linux/netfilter_ipv4.h>
+#include <net/ipip.h>
+#include <net/checksum.h>
+#include <net/ip_mp_alg.h>
+
+#define MULTIPATH_MAX_CANDIDATES 40
+
+static struct rtable* last_used = NULL;
+
+static void rr_remove(struct rtable *rt)
+{
+ if (last_used == rt)
+ last_used = NULL;
+}
+
+static void rr_select_route(const struct flowi *flp,
+ struct rtable *first, struct rtable **rp)
+{
+ struct rtable *nh, *result, *min_use_cand = NULL;
+ int min_use = -1;
+
+ /* if necessary and possible utilize the old alternative */
+ if ((flp->flags & FLOWI_FLAG_MULTIPATHOLDROUTE) != 0 &&
+ last_used != NULL) {
+ result = last_used;
+ goto out;
+ }
+
+ /* 1. make sure all alt. nexthops have the same GC related data
+ * 2. determine the new candidate to be returned
+ */
+ result = NULL;
+ for (nh = rcu_dereference(first); nh;
+ nh = rcu_dereference(nh->u.rt_next)) {
+ if ((nh->u.dst.flags & DST_BALANCED) != 0 &&
+ multipath_comparekeys(&nh->fl, flp)) {
+ nh->u.dst.lastuse = jiffies;
+
+ if (min_use == -1 || nh->u.dst.__use < min_use) {
+ min_use = nh->u.dst.__use;
+ min_use_cand = nh;
+ }
+ }
+ }
+ result = min_use_cand;
+ if (!result)
+ result = first;
+
+out:
+ last_used = result;
+ result->u.dst.__use++;
+ *rp = result;
+}
+
+static struct ip_mp_alg_ops rr_ops = {
+ .mp_alg_select_route = rr_select_route,
+ .mp_alg_remove = rr_remove,
+};
+
+static int __init rr_init(void)
+{
+ return multipath_alg_register(&rr_ops, IP_MP_ALG_RR);
+}
+
+static void __exit rr_exit(void)
+{
+ multipath_alg_unregister(&rr_ops, IP_MP_ALG_RR);
+}
+
+module_init(rr_init);
+module_exit(rr_exit);
diff --git a/net/ipv4/multipath_wrandom.c b/net/ipv4/multipath_wrandom.c
new file mode 100644
index 0000000000000..10b23e1bece66
--- /dev/null
+++ b/net/ipv4/multipath_wrandom.c
@@ -0,0 +1,344 @@
+/*
+ * Weighted random policy for multipath.
+ *
+ *
+ * Version: $Id: multipath_wrandom.c,v 1.1.2.3 2004/09/22 07:51:40 elueck Exp $
+ *
+ * Authors: Einar Lueck <elueck@de.ibm.com><lkml@einar-lueck.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/config.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/kernel.h>
+#include <linux/fcntl.h>
+#include <linux/stat.h>
+#include <linux/socket.h>
+#include <linux/in.h>
+#include <linux/inet.h>
+#include <linux/netdevice.h>
+#include <linux/inetdevice.h>
+#include <linux/igmp.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/mroute.h>
+#include <linux/init.h>
+#include <net/ip.h>
+#include <net/protocol.h>
+#include <linux/skbuff.h>
+#include <net/sock.h>
+#include <net/icmp.h>
+#include <net/udp.h>
+#include <net/raw.h>
+#include <linux/notifier.h>
+#include <linux/if_arp.h>
+#include <linux/netfilter_ipv4.h>
+#include <net/ipip.h>
+#include <net/checksum.h>
+#include <net/ip_fib.h>
+#include <net/ip_mp_alg.h>
+
+#define MULTIPATH_STATE_SIZE 15
+
+struct multipath_candidate {
+ struct multipath_candidate *next;
+ int power;
+ struct rtable *rt;
+};
+
+struct multipath_dest {
+ struct list_head list;
+
+ const struct fib_nh *nh_info;
+ __u32 netmask;
+ __u32 network;
+ unsigned char prefixlen;
+
+ struct rcu_head rcu;
+};
+
+struct multipath_bucket {
+ struct list_head head;
+ spinlock_t lock;
+};
+
+struct multipath_route {
+ struct list_head list;
+
+ int oif;
+ __u32 gw;
+ struct list_head dests;
+
+ struct rcu_head rcu;
+};
+
+/* state: primarily weight per route information */
+static struct multipath_bucket state[MULTIPATH_STATE_SIZE];
+
+/* interface to random number generation */
+static unsigned int RANDOM_SEED = 93186752;
+
+static inline unsigned int random(unsigned int ubound)
+{
+ static unsigned int a = 1588635695,
+ q = 2,
+ r = 1117695901;
+ RANDOM_SEED = a*(RANDOM_SEED % q) - r*(RANDOM_SEED / q);
+ return RANDOM_SEED % ubound;
+}
+
+static unsigned char __multipath_lookup_weight(const struct flowi *fl,
+ const struct rtable *rt)
+{
+ const int state_idx = rt->idev->dev->ifindex % MULTIPATH_STATE_SIZE;
+ struct multipath_route *r;
+ struct multipath_route *target_route = NULL;
+ struct multipath_dest *d;
+ int weight = 1;
+
+ /* lookup the weight information for a certain route */
+ rcu_read_lock();
+
+ /* find state entry for gateway or add one if necessary */
+ list_for_each_entry_rcu(r, &state[state_idx].head, list) {
+ if (r->gw == rt->rt_gateway &&
+ r->oif == rt->idev->dev->ifindex) {
+ target_route = r;
+ break;
+ }
+ }
+
+ if (!target_route) {
+ /* this should not happen... but we are prepared */
+ printk( KERN_CRIT"%s: missing state for gateway: %u and " \
+ "device %d\n", __FUNCTION__, rt->rt_gateway,
+ rt->idev->dev->ifindex);
+ goto out;
+ }
+
+ /* find state entry for destination */
+ list_for_each_entry_rcu(d, &target_route->dests, list) {
+ __u32 targetnetwork = fl->fl4_dst &
+ (0xFFFFFFFF >> (32 - d->prefixlen));
+
+ if ((targetnetwork & d->netmask) == d->network) {
+ weight = d->nh_info->nh_weight;
+ goto out;
+ }
+ }
+
+out:
+ rcu_read_unlock();
+ return weight;
+}
+
+static void wrandom_init_state(void)
+{
+ int i;
+
+ for (i = 0; i < MULTIPATH_STATE_SIZE; ++i) {
+ INIT_LIST_HEAD(&state[i].head);
+ spin_lock_init(&state[i].lock);
+ }
+}
+
+static void wrandom_select_route(const struct flowi *flp,
+ struct rtable *first,
+ struct rtable **rp)
+{
+ struct rtable *rt;
+ struct rtable *decision;
+ struct multipath_candidate *first_mpc = NULL;
+ struct multipath_candidate *mpc, *last_mpc = NULL;
+ int power = 0;
+ int last_power;
+ int selector;
+ const size_t size_mpc = sizeof(struct multipath_candidate);
+
+ /* collect all candidates and identify their weights */
+ for (rt = rcu_dereference(first); rt;
+ rt = rcu_dereference(rt->u.rt_next)) {
+ if ((rt->u.dst.flags & DST_BALANCED) != 0 &&
+ multipath_comparekeys(&rt->fl, flp)) {
+ struct multipath_candidate* mpc =
+ (struct multipath_candidate*)
+ kmalloc(size_mpc, GFP_KERNEL);
+
+ if (!mpc)
+ return;
+
+ power += __multipath_lookup_weight(flp, rt) * 10000;
+
+ mpc->power = power;
+ mpc->rt = rt;
+ mpc->next = NULL;
+
+ if (!first_mpc)
+ first_mpc = mpc;
+ else
+ last_mpc->next = mpc;
+
+ last_mpc = mpc;
+ }
+ }
+
+ /* choose a weighted random candidate */
+ decision = first;
+ selector = random(power);
+ last_power = 0;
+
+ /* select candidate, adjust GC data and cleanup local state */
+ decision = first;
+ last_mpc = NULL;
+ for (mpc = first_mpc; mpc; mpc = mpc->next) {
+ mpc->rt->u.dst.lastuse = jiffies;
+ if (last_power <= selector && selector < mpc->power)
+ decision = mpc->rt;
+
+ last_power = mpc->power;
+ if (last_mpc)
+ kfree(last_mpc);
+
+ last_mpc = mpc;
+ }
+
+ if (last_mpc) {
+ /* concurrent __multipath_flush may lead to !last_mpc */
+ kfree(last_mpc);
+ }
+
+ decision->u.dst.__use++;
+ *rp = decision;
+}
+
+static void wrandom_set_nhinfo(__u32 network,
+ __u32 netmask,
+ unsigned char prefixlen,
+ const struct fib_nh *nh)
+{
+ const int state_idx = nh->nh_oif % MULTIPATH_STATE_SIZE;
+ struct multipath_route *r, *target_route = NULL;
+ struct multipath_dest *d, *target_dest = NULL;
+
+ /* store the weight information for a certain route */
+ spin_lock(&state[state_idx].lock);
+
+ /* find state entry for gateway or add one if necessary */
+ list_for_each_entry_rcu(r, &state[state_idx].head, list) {
+ if (r->gw == nh->nh_gw && r->oif == nh->nh_oif) {
+ target_route = r;
+ break;
+ }
+ }
+
+ if (!target_route) {
+ const size_t size_rt = sizeof(struct multipath_route);
+ target_route = (struct multipath_route *)
+ kmalloc(size_rt, GFP_KERNEL);
+
+ target_route->gw = nh->nh_gw;
+ target_route->oif = nh->nh_oif;
+ memset(&target_route->rcu, 0, sizeof(struct rcu_head));
+ INIT_LIST_HEAD(&target_route->dests);
+
+ list_add_rcu(&target_route->list, &state[state_idx].head);
+ }
+
+ /* find state entry for destination or add one if necessary */
+ list_for_each_entry_rcu(d, &target_route->dests, list) {
+ if (d->nh_info == nh) {
+ target_dest = d;
+ break;
+ }
+ }
+
+ if (!target_dest) {
+ const size_t size_dst = sizeof(struct multipath_dest);
+ target_dest = (struct multipath_dest*)
+ kmalloc(size_dst, GFP_KERNEL);
+
+ target_dest->nh_info = nh;
+ target_dest->network = network;
+ target_dest->netmask = netmask;
+ target_dest->prefixlen = prefixlen;
+ memset(&target_dest->rcu, 0, sizeof(struct rcu_head));
+
+ list_add_rcu(&target_dest->list, &target_route->dests);
+ }
+ /* else: we already stored this info for another destination =>
+ * we are finished
+ */
+
+ spin_unlock(&state[state_idx].lock);
+}
+
+static void __multipath_free(struct rcu_head *head)
+{
+ struct multipath_route *rt = container_of(head, struct multipath_route,
+ rcu);
+ kfree(rt);
+}
+
+static void __multipath_free_dst(struct rcu_head *head)
+{
+ struct multipath_dest *dst = container_of(head,
+ struct multipath_dest,
+ rcu);
+ kfree(dst);
+}
+
+static void wrandom_flush(void)
+{
+ int i;
+
+ /* defere delete to all entries */
+ for (i = 0; i < MULTIPATH_STATE_SIZE; ++i) {
+ struct multipath_route *r;
+
+ spin_lock(&state[i].lock);
+ list_for_each_entry_rcu(r, &state[i].head, list) {
+ struct multipath_dest *d;
+ list_for_each_entry_rcu(d, &r->dests, list) {
+ list_del_rcu(&d->list);
+ call_rcu(&d->rcu,
+ __multipath_free_dst);
+ }
+ list_del_rcu(&r->list);
+ call_rcu(&r->rcu,
+ __multipath_free);
+ }
+
+ spin_unlock(&state[i].lock);
+ }
+}
+
+static struct ip_mp_alg_ops wrandom_ops = {
+ .mp_alg_select_route = wrandom_select_route,
+ .mp_alg_flush = wrandom_flush,
+ .mp_alg_set_nhinfo = wrandom_set_nhinfo,
+};
+
+static int __init wrandom_init(void)
+{
+ wrandom_init_state();
+
+ return multipath_alg_register(&wrandom_ops, IP_MP_ALG_WRANDOM);
+}
+
+static void __exit wrandom_exit(void)
+{
+ multipath_alg_unregister(&wrandom_ops, IP_MP_ALG_WRANDOM);
+}
+
+module_init(wrandom_init);
+module_exit(wrandom_exit);
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index bc5fc5f76937d..df79f5ed6a0a3 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -717,7 +717,7 @@ static int translate_table(const char *name,
}
/* And one copy for every other CPU */
- for (i = 1; i < NR_CPUS; i++) {
+ for (i = 1; i < num_possible_cpus(); i++) {
memcpy(newinfo->entries + SMP_ALIGN(newinfo->size)*i,
newinfo->entries,
SMP_ALIGN(newinfo->size));
@@ -768,7 +768,7 @@ static void get_counters(const struct arpt_table_info *t,
unsigned int cpu;
unsigned int i;
- for (cpu = 0; cpu < NR_CPUS; cpu++) {
+ for (cpu = 0; cpu < num_possible_cpus(); cpu++) {
i = 0;
ARPT_ENTRY_ITERATE(t->entries + TABLE_OFFSET(t, cpu),
t->size,
@@ -886,7 +886,7 @@ static int do_replace(void __user *user, unsigned int len)
return -ENOMEM;
newinfo = vmalloc(sizeof(struct arpt_table_info)
- + SMP_ALIGN(tmp.size) * NR_CPUS);
+ + SMP_ALIGN(tmp.size) * num_possible_cpus());
if (!newinfo)
return -ENOMEM;
@@ -1159,7 +1159,7 @@ int arpt_register_table(struct arpt_table *table,
= { 0, 0, 0, { 0 }, { 0 }, { } };
newinfo = vmalloc(sizeof(struct arpt_table_info)
- + SMP_ALIGN(repl->size) * NR_CPUS);
+ + SMP_ALIGN(repl->size) * num_possible_cpus());
if (!newinfo) {
ret = -ENOMEM;
return ret;
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_sctp.c b/net/ipv4/netfilter/ip_conntrack_proto_sctp.c
index 7d9f8ea14a5e3..ff8c34a860ff2 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_sctp.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_sctp.c
@@ -400,8 +400,8 @@ static int sctp_packet(struct ip_conntrack *conntrack,
return -1;
}
DEBUGP("Setting vtag %x for dir %d\n",
- ih->init_tag, CTINFO2DIR(ctinfo));
- conntrack->proto.sctp.vtag[IP_CT_DIR_ORIGINAL] = ih->init_tag;
+ ih->init_tag, !CTINFO2DIR(ctinfo));
+ conntrack->proto.sctp.vtag[!CTINFO2DIR(ctinfo)] = ih->init_tag;
}
conntrack->proto.sctp.state = newconntrack;
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
index 939931c338d6c..e800b16fc9209 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
@@ -254,7 +254,7 @@ static enum tcp_conntrack tcp_conntracks[2][6][TCP_CONNTRACK_MAX] = {
* sSS -> sSR Standard open.
* sSR -> sSR Retransmitted SYN/ACK.
* sES -> sIG Late retransmitted SYN/ACK?
- * sFW -> sIG
+ * sFW -> sIG Might be SYN/ACK answering ignored SYN
* sCW -> sIG
* sLA -> sIG
* sTW -> sIG
@@ -273,10 +273,10 @@ static enum tcp_conntrack tcp_conntracks[2][6][TCP_CONNTRACK_MAX] = {
* sCL -> sCL
*/
/* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI */
-/*ack*/ { sIV, sIG, sIV, sES, sCW, sCW, sTW, sTW, sCL, sIV },
+/*ack*/ { sIV, sIV, sSR, sES, sCW, sCW, sTW, sTW, sCL, sIV },
/*
- * sSS -> sIG Might be a half-open connection.
- * sSR -> sIV Simultaneous open.
+ * sSS -> sIV Might be a half-open connection.
+ * sSR -> sSR Might answer late resent SYN.
* sES -> sES :-)
* sFW -> sCW Normal close request answered by ACK.
* sCW -> sCW
@@ -352,14 +352,19 @@ static unsigned int get_conntrack_index(const struct tcphdr *tcph)
http://www.nluug.nl/events/sane2000/papers.html
http://www.iae.nl/users/guido/papers/tcp_filtering.ps.gz
- The boundaries and the conditions are slightly changed:
-
+ The boundaries and the conditions are changed according to RFC793:
+ the packet must intersect the window (i.e. segments may be
+ after the right or before the left edge) and thus receivers may ACK
+ segments after the right edge of the window.
+
td_maxend = max(sack + max(win,1)) seen in reply packets
td_maxwin = max(max(win, 1)) + (sack - ack) seen in sent packets
+ td_maxwin += seq + len - sender.td_maxend
+ if seq + len > sender.td_maxend
td_end = max(seq + len) seen in sent packets
- I. Upper bound for valid data: seq + len <= sender.td_maxend
- II. Lower bound for valid data: seq >= sender.td_end - receiver.td_maxwin
+ I. Upper bound for valid data: seq <= sender.td_maxend
+ II. Lower bound for valid data: seq + len >= sender.td_end - receiver.td_maxwin
III. Upper bound for valid ack: sack <= receiver.td_end
IV. Lower bound for valid ack: ack >= receiver.td_end - MAXACKWINDOW
@@ -373,7 +378,7 @@ static inline __u32 segment_seq_plus_len(__u32 seq,
size_t len,
struct iphdr *iph,
struct tcphdr *tcph)
- {
+{
return (seq + len - (iph->ihl + tcph->doff)*4
+ (tcph->syn ? 1 : 0) + (tcph->fin ? 1 : 0));
}
@@ -444,22 +449,33 @@ static void tcp_options(const struct sk_buff *skb,
}
}
-static void tcp_sack(struct tcphdr *tcph, __u32 *sack)
+static void tcp_sack(const struct sk_buff *skb,
+ struct iphdr *iph,
+ struct tcphdr *tcph,
+ __u32 *sack)
{
- __u32 tmp;
+ unsigned char buff[(15 * 4) - sizeof(struct tcphdr)];
unsigned char *ptr;
int length = (tcph->doff*4) - sizeof(struct tcphdr);
-
+ __u32 tmp;
+
+ if (!length)
+ return;
+
+ ptr = skb_header_pointer(skb,
+ (iph->ihl * 4) + sizeof(struct tcphdr),
+ length, buff);
+ BUG_ON(ptr == NULL);
+
/* Fast path for timestamp-only option */
if (length == TCPOLEN_TSTAMP_ALIGNED*4
- && *(__u32 *)(tcph + 1) ==
+ && *(__u32 *)ptr ==
__constant_ntohl((TCPOPT_NOP << 24)
| (TCPOPT_NOP << 16)
| (TCPOPT_TIMESTAMP << 8)
| TCPOLEN_TIMESTAMP))
return;
- ptr = (unsigned char *)(tcph + 1);
while (length > 0) {
int opcode=*ptr++;
int opsize, i;
@@ -500,7 +516,7 @@ static void tcp_sack(struct tcphdr *tcph, __u32 *sack)
static int tcp_in_window(struct ip_ct_tcp *state,
enum ip_conntrack_dir dir,
- unsigned int *index,
+ unsigned int index,
const struct sk_buff *skb,
struct iphdr *iph,
struct tcphdr *tcph)
@@ -519,7 +535,7 @@ static int tcp_in_window(struct ip_ct_tcp *state,
end = segment_seq_plus_len(seq, skb->len, iph, tcph);
if (receiver->flags & IP_CT_TCP_FLAG_SACK_PERM)
- tcp_sack(tcph, &sack);
+ tcp_sack(skb, iph, tcph, &sack);
DEBUGP("tcp_in_window: START\n");
DEBUGP("tcp_in_window: src=%u.%u.%u.%u:%hu dst=%u.%u.%u.%u:%hu "
@@ -598,20 +614,23 @@ static int tcp_in_window(struct ip_ct_tcp *state,
ack = sack = receiver->td_end;
}
- if (seq == end)
+ if (seq == end
+ && (!tcph->rst
+ || (seq == 0 && state->state == TCP_CONNTRACK_SYN_SENT)))
/*
* Packets contains no data: we assume it is valid
* and check the ack value only.
+ * However RST segments are always validated by their
+ * SEQ number, except when seq == 0 (reset sent answering
+ * SYN.
*/
seq = end = sender->td_end;
DEBUGP("tcp_in_window: src=%u.%u.%u.%u:%hu dst=%u.%u.%u.%u:%hu "
- "seq=%u ack=%u sack =%u win=%u end=%u trim=%u\n",
+ "seq=%u ack=%u sack =%u win=%u end=%u\n",
NIPQUAD(iph->saddr), ntohs(tcph->source),
NIPQUAD(iph->daddr), ntohs(tcph->dest),
- seq, ack, sack, win, end,
- after(end, sender->td_maxend) && before(seq, sender->td_maxend)
- ? sender->td_maxend : end);
+ seq, ack, sack, win, end);
DEBUGP("tcp_in_window: sender end=%u maxend=%u maxwin=%u scale=%i "
"receiver end=%u maxend=%u maxwin=%u scale=%i\n",
sender->td_end, sender->td_maxend, sender->td_maxwin,
@@ -619,24 +638,15 @@ static int tcp_in_window(struct ip_ct_tcp *state,
receiver->td_end, receiver->td_maxend, receiver->td_maxwin,
receiver->td_scale);
- /* Ignore data over the right edge of the receiver's window. */
- if (after(end, sender->td_maxend) &&
- before(seq, sender->td_maxend)) {
- end = sender->td_maxend;
- if (*index == TCP_FIN_SET)
- *index = TCP_ACK_SET;
- }
DEBUGP("tcp_in_window: I=%i II=%i III=%i IV=%i\n",
- before(end, sender->td_maxend + 1)
- || before(seq, sender->td_maxend + 1),
- after(seq, sender->td_end - receiver->td_maxwin - 1)
- || after(end, sender->td_end - receiver->td_maxwin - 1),
+ before(seq, sender->td_maxend + 1),
+ after(end, sender->td_end - receiver->td_maxwin - 1),
before(sack, receiver->td_end + 1),
after(ack, receiver->td_end - MAXACKWINDOW(sender)));
if (sender->loose || receiver->loose ||
- (before(end, sender->td_maxend + 1) &&
- after(seq, sender->td_end - receiver->td_maxwin - 1) &&
+ (before(seq, sender->td_maxend + 1) &&
+ after(end, sender->td_end - receiver->td_maxwin - 1) &&
before(sack, receiver->td_end + 1) &&
after(ack, receiver->td_end - MAXACKWINDOW(sender)))) {
/*
@@ -653,6 +663,11 @@ static int tcp_in_window(struct ip_ct_tcp *state,
sender->td_maxwin = swin;
if (after(end, sender->td_end))
sender->td_end = end;
+ /*
+ * Update receiver data.
+ */
+ if (after(end, sender->td_maxend))
+ receiver->td_maxwin += end - sender->td_maxend;
if (after(sack + win, receiver->td_maxend - 1)) {
receiver->td_maxend = sack + win;
if (win == 0)
@@ -662,7 +677,7 @@ static int tcp_in_window(struct ip_ct_tcp *state,
/*
* Check retransmissions.
*/
- if (*index == TCP_ACK_SET) {
+ if (index == TCP_ACK_SET) {
if (state->last_dir == dir
&& state->last_seq == seq
&& state->last_ack == ack
@@ -687,16 +702,16 @@ static int tcp_in_window(struct ip_ct_tcp *state,
if (LOG_INVALID(IPPROTO_TCP))
nf_log_packet(PF_INET, 0, skb, NULL, NULL,
"ip_ct_tcp: %s ",
- before(end, sender->td_maxend + 1) ?
- after(seq, sender->td_end - receiver->td_maxwin - 1) ?
+ before(seq, sender->td_maxend + 1) ?
+ after(end, sender->td_end - receiver->td_maxwin - 1) ?
before(sack, receiver->td_end + 1) ?
after(ack, receiver->td_end - MAXACKWINDOW(sender)) ? "BUG"
- : "ACK is under the lower bound (possibly overly delayed ACK)"
- : "ACK is over the upper bound (ACKed data has never seen yet)"
- : "SEQ is under the lower bound (retransmitted already ACKed data)"
+ : "ACK is under the lower bound (possible overly delayed ACK)"
+ : "ACK is over the upper bound (ACKed data not seen yet)"
+ : "SEQ is under the lower bound (already ACKed data retransmitted)"
: "SEQ is over the upper bound (over the window of the receiver)");
- res = ip_ct_tcp_be_liberal && !tcph->rst;
+ res = ip_ct_tcp_be_liberal;
}
DEBUGP("tcp_in_window: res=%i sender end=%u maxend=%u maxwin=%u "
@@ -849,13 +864,12 @@ static int tcp_packet(struct ip_conntrack *conntrack,
switch (new_state) {
case TCP_CONNTRACK_IGNORE:
/* Either SYN in ORIGINAL
- * or SYN/ACK in REPLY
- * or ACK in REPLY direction (half-open connection). */
+ * or SYN/ACK in REPLY. */
if (index == TCP_SYNACK_SET
&& conntrack->proto.tcp.last_index == TCP_SYN_SET
&& conntrack->proto.tcp.last_dir != dir
- && after(ntohl(th->ack_seq),
- conntrack->proto.tcp.last_seq)) {
+ && ntohl(th->ack_seq) ==
+ conntrack->proto.tcp.last_end) {
/* This SYN/ACK acknowledges a SYN that we earlier
* ignored as invalid. This means that the client and
* the server are both in sync, while the firewall is
@@ -875,6 +889,8 @@ static int tcp_packet(struct ip_conntrack *conntrack,
conntrack->proto.tcp.last_index = index;
conntrack->proto.tcp.last_dir = dir;
conntrack->proto.tcp.last_seq = ntohl(th->seq);
+ conntrack->proto.tcp.last_end =
+ segment_seq_plus_len(ntohl(th->seq), skb->len, iph, th);
WRITE_UNLOCK(&tcp_lock);
if (LOG_INVALID(IPPROTO_TCP))
@@ -892,7 +908,12 @@ static int tcp_packet(struct ip_conntrack *conntrack,
"ip_ct_tcp: invalid state ");
return -NF_ACCEPT;
case TCP_CONNTRACK_SYN_SENT:
- if (old_state >= TCP_CONNTRACK_TIME_WAIT) {
+ if (old_state < TCP_CONNTRACK_TIME_WAIT)
+ break;
+ if ((conntrack->proto.tcp.seen[dir].flags &
+ IP_CT_TCP_FLAG_CLOSE_INIT)
+ || after(ntohl(th->seq),
+ conntrack->proto.tcp.seen[dir].td_end)) {
/* Attempt to reopen a closed connection.
* Delete this connection and look up again. */
WRITE_UNLOCK(&tcp_lock);
@@ -900,23 +921,23 @@ static int tcp_packet(struct ip_conntrack *conntrack,
conntrack->timeout.function((unsigned long)
conntrack);
return -NF_REPEAT;
+ } else {
+ WRITE_UNLOCK(&tcp_lock);
+ if (LOG_INVALID(IPPROTO_TCP))
+ nf_log_packet(PF_INET, 0, skb, NULL, NULL,
+ "ip_ct_tcp: invalid SYN");
+ return -NF_ACCEPT;
}
- break;
case TCP_CONNTRACK_CLOSE:
if (index == TCP_RST_SET
- && ((test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)
- && conntrack->proto.tcp.last_index <= TCP_SYNACK_SET)
- || (!test_bit(IPS_ASSURED_BIT, &conntrack->status)
- && conntrack->proto.tcp.last_index == TCP_ACK_SET))
- && after(ntohl(th->ack_seq),
- conntrack->proto.tcp.last_seq)) {
- /* Ignore RST closing down invalid SYN or ACK
- we had let trough. */
- WRITE_UNLOCK(&tcp_lock);
- if (LOG_INVALID(IPPROTO_TCP))
- nf_log_packet(PF_INET, 0, skb, NULL, NULL,
- "ip_ct_tcp: invalid RST (ignored) ");
- return NF_ACCEPT;
+ && test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)
+ && conntrack->proto.tcp.last_index == TCP_SYN_SET
+ && ntohl(th->ack_seq) == conntrack->proto.tcp.last_end) {
+ /* RST sent to invalid SYN we had let trough
+ * SYN was in window then, tear down connection.
+ * We skip window checking, because packet might ACK
+ * segments we ignored in the SYN. */
+ goto in_window;
}
/* Just fall trough */
default:
@@ -924,16 +945,14 @@ static int tcp_packet(struct ip_conntrack *conntrack,
break;
}
- if (!tcp_in_window(&conntrack->proto.tcp, dir, &index,
+ if (!tcp_in_window(&conntrack->proto.tcp, dir, index,
skb, iph, th)) {
WRITE_UNLOCK(&tcp_lock);
return -NF_ACCEPT;
}
- /* From now on we have got in-window packets */
-
- /* If FIN was trimmed off, we don't change state. */
+ in_window:
+ /* From now on we have got in-window packets */
conntrack->proto.tcp.last_index = index;
- new_state = tcp_conntracks[dir][index][old_state];
DEBUGP("tcp_conntracks: src=%u.%u.%u.%u:%hu dst=%u.%u.%u.%u:%hu "
"syn=%i ack=%i fin=%i rst=%i old=%i new=%i\n",
@@ -944,6 +963,10 @@ static int tcp_packet(struct ip_conntrack *conntrack,
old_state, new_state);
conntrack->proto.tcp.state = new_state;
+ if (old_state != new_state
+ && (new_state == TCP_CONNTRACK_FIN_WAIT
+ || new_state == TCP_CONNTRACK_CLOSE))
+ conntrack->proto.tcp.seen[dir].flags |= IP_CT_TCP_FLAG_CLOSE_INIT;
timeout = conntrack->proto.tcp.retrans >= ip_ct_tcp_max_retrans
&& *tcp_timeouts[new_state] > ip_ct_tcp_timeout_max_retrans
? ip_ct_tcp_timeout_max_retrans : *tcp_timeouts[new_state];
@@ -974,7 +997,7 @@ static int tcp_packet(struct ip_conntrack *conntrack,
return NF_ACCEPT;
}
- /* Called when a new connection for this protocol found. */
+/* Called when a new connection for this protocol found. */
static int tcp_new(struct ip_conntrack *conntrack,
const struct sk_buff *skb)
{
diff --git a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c
index dd9f125ff6508..80a7bde2a57a7 100644
--- a/net/ipv4/netfilter/ip_conntrack_standalone.c
+++ b/net/ipv4/netfilter/ip_conntrack_standalone.c
@@ -77,34 +77,70 @@ seq_print_counters(struct seq_file *s,
#define seq_print_counters(x, y) 0
#endif
-static void *ct_seq_start(struct seq_file *s, loff_t *pos)
+struct ct_iter_state {
+ unsigned int bucket;
+};
+
+static struct list_head *ct_get_first(struct seq_file *seq)
{
- if (*pos >= ip_conntrack_htable_size)
- return NULL;
- return &ip_conntrack_hash[*pos];
+ struct ct_iter_state *st = seq->private;
+
+ for (st->bucket = 0;
+ st->bucket < ip_conntrack_htable_size;
+ st->bucket++) {
+ if (!list_empty(&ip_conntrack_hash[st->bucket]))
+ return ip_conntrack_hash[st->bucket].next;
+ }
+ return NULL;
}
-
-static void ct_seq_stop(struct seq_file *s, void *v)
+
+static struct list_head *ct_get_next(struct seq_file *seq, struct list_head *head)
{
+ struct ct_iter_state *st = seq->private;
+
+ head = head->next;
+ while (head == &ip_conntrack_hash[st->bucket]) {
+ if (++st->bucket >= ip_conntrack_htable_size)
+ return NULL;
+ head = ip_conntrack_hash[st->bucket].next;
+ }
+ return head;
+}
+
+static struct list_head *ct_get_idx(struct seq_file *seq, loff_t pos)
+{
+ struct list_head *head = ct_get_first(seq);
+
+ if (head)
+ while (pos && (head = ct_get_next(seq, head)))
+ pos--;
+ return pos ? NULL : head;
+}
+
+static void *ct_seq_start(struct seq_file *seq, loff_t *pos)
+{
+ READ_LOCK(&ip_conntrack_lock);
+ return ct_get_idx(seq, *pos);
}
static void *ct_seq_next(struct seq_file *s, void *v, loff_t *pos)
{
(*pos)++;
- if (*pos >= ip_conntrack_htable_size)
- return NULL;
- return &ip_conntrack_hash[*pos];
+ return ct_get_next(s, v);
}
-/* return 0 on success, 1 in case of error */
-static int ct_seq_real_show(const struct ip_conntrack_tuple_hash *hash,
- struct seq_file *s)
+static void ct_seq_stop(struct seq_file *s, void *v)
+{
+ READ_UNLOCK(&ip_conntrack_lock);
+}
+
+static int ct_seq_show(struct seq_file *s, void *v)
{
+ const struct ip_conntrack_tuple_hash *hash = v;
const struct ip_conntrack *conntrack = tuplehash_to_ctrack(hash);
struct ip_conntrack_protocol *proto;
MUST_BE_READ_LOCKED(&ip_conntrack_lock);
-
IP_NF_ASSERT(conntrack);
/* we only want to print DIR_ORIGINAL */
@@ -115,63 +151,50 @@ static int ct_seq_real_show(const struct ip_conntrack_tuple_hash *hash,
.tuple.dst.protonum);
IP_NF_ASSERT(proto);
- if (seq_printf(s, "%-8s %u %lu ",
+ if (seq_printf(s, "%-8s %u %ld ",
proto->name,
conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum,
timer_pending(&conntrack->timeout)
- ? (conntrack->timeout.expires - jiffies)/HZ : 0) != 0)
- return 1;
+ ? (long)(conntrack->timeout.expires - jiffies)/HZ
+ : 0) != 0)
+ return -ENOSPC;
if (proto->print_conntrack(s, conntrack))
- return 1;
+ return -ENOSPC;
if (print_tuple(s, &conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
proto))
- return 1;
+ return -ENOSPC;
if (seq_print_counters(s, &conntrack->counters[IP_CT_DIR_ORIGINAL]))
- return 1;
+ return -ENOSPC;
if (!(test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)))
if (seq_printf(s, "[UNREPLIED] "))
- return 1;
+ return -ENOSPC;
if (print_tuple(s, &conntrack->tuplehash[IP_CT_DIR_REPLY].tuple,
proto))
- return 1;
+ return -ENOSPC;
if (seq_print_counters(s, &conntrack->counters[IP_CT_DIR_REPLY]))
- return 1;
+ return -ENOSPC;
if (test_bit(IPS_ASSURED_BIT, &conntrack->status))
if (seq_printf(s, "[ASSURED] "))
- return 1;
+ return -ENOSPC;
#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
- if (seq_printf(s, "mark=%ld ", conntrack->mark))
- return 1;
+ if (seq_printf(s, "mark=%lu ", conntrack->mark))
+ return -ENOSPC;
#endif
if (seq_printf(s, "use=%u\n", atomic_read(&conntrack->ct_general.use)))
- return 1;
+ return -ENOSPC;
return 0;
}
-static int ct_seq_show(struct seq_file *s, void *v)
-{
- struct list_head *list = v;
- int ret = 0;
-
- /* FIXME: Simply truncates if hash chain too long. */
- READ_LOCK(&ip_conntrack_lock);
- if (LIST_FIND(list, ct_seq_real_show,
- struct ip_conntrack_tuple_hash *, s))
- ret = -ENOSPC;
- READ_UNLOCK(&ip_conntrack_lock);
- return ret;
-}
-
static struct seq_operations ct_seq_ops = {
.start = ct_seq_start,
.next = ct_seq_next,
@@ -181,7 +204,23 @@ static struct seq_operations ct_seq_ops = {
static int ct_open(struct inode *inode, struct file *file)
{
- return seq_open(file, &ct_seq_ops);
+ struct seq_file *seq;
+ struct ct_iter_state *st;
+ int ret;
+
+ st = kmalloc(sizeof(struct ct_iter_state), GFP_KERNEL);
+ if (st == NULL)
+ return -ENOMEM;
+ ret = seq_open(file, &ct_seq_ops);
+ if (ret)
+ goto out_free;
+ seq = file->private_data;
+ seq->private = st;
+ memset(st, 0, sizeof(struct ct_iter_state));
+ return ret;
+out_free:
+ kfree(st);
+ return ret;
}
static struct file_operations ct_file_ops = {
@@ -189,7 +228,7 @@ static struct file_operations ct_file_ops = {
.open = ct_open,
.read = seq_read,
.llseek = seq_lseek,
- .release = seq_release
+ .release = seq_release_private,
};
/* expects */
@@ -235,8 +274,8 @@ static int exp_seq_show(struct seq_file *s, void *v)
struct ip_conntrack_expect *expect = v;
if (expect->timeout.function)
- seq_printf(s, "%lu ", timer_pending(&expect->timeout)
- ? (expect->timeout.expires - jiffies)/HZ : 0);
+ seq_printf(s, "%ld ", timer_pending(&expect->timeout)
+ ? (long)(expect->timeout.expires - jiffies)/HZ : 0);
else
seq_printf(s, "- ");
@@ -384,10 +423,12 @@ static unsigned int ip_conntrack_defrag(unsigned int hooknum,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
+#if !defined(CONFIG_IP_NF_NAT) && !defined(CONFIG_IP_NF_NAT_MODULE)
/* Previously seen (loopback)? Ignore. Do this before
fragment check. */
if ((*pskb)->nfct)
return NF_ACCEPT;
+#endif
/* Gather fragments. */
if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
@@ -416,7 +457,7 @@ static unsigned int ip_refrag(unsigned int hooknum,
/* 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_pmtu(&rt->u.dst) &&
+ 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);
diff --git a/net/ipv4/netfilter/ip_nat_ftp.c b/net/ipv4/netfilter/ip_nat_ftp.c
index e4799f2da77a9..c6000e794ad67 100644
--- a/net/ipv4/netfilter/ip_nat_ftp.c
+++ b/net/ipv4/netfilter/ip_nat_ftp.c
@@ -170,5 +170,14 @@ static int __init init(void)
return 0;
}
+/* 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)
+ ": kernel >= 2.6.10 only uses 'ports' for conntrack modules\n");
+ return 0;
+}
+module_param_call(ports, warn_set, NULL, NULL, 0);
+
module_init(init);
module_exit(fini);
diff --git a/net/ipv4/netfilter/ip_nat_irc.c b/net/ipv4/netfilter/ip_nat_irc.c
index e618b6c7e3015..9c1ca3381d561 100644
--- a/net/ipv4/netfilter/ip_nat_irc.c
+++ b/net/ipv4/netfilter/ip_nat_irc.c
@@ -112,5 +112,14 @@ static int __init init(void)
return 0;
}
+/* 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)
+ ": kernel >= 2.6.10 only uses 'ports' for conntrack modules\n");
+ return 0;
+}
+module_param_call(ports, warn_set, NULL, NULL, 0);
+
module_init(init);
module_exit(fini);
diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c
index a9aa12cc83bb4..9e40dffc204f3 100644
--- a/net/ipv4/netfilter/ip_queue.c
+++ b/net/ipv4/netfilter/ip_queue.c
@@ -14,6 +14,9 @@
* Zander).
* 2000-08-01: Added Nick Williams' MAC support.
* 2002-06-25: Code cleanup.
+ * 2005-01-10: Added /proc counter for dropped packets; fixed so
+ * packets aren't delivered to user space if they're going
+ * to be dropped.
*
*/
#include <linux/module.h>
@@ -59,6 +62,8 @@ static DEFINE_RWLOCK(queue_lock);
static int peer_pid;
static unsigned int copy_range;
static unsigned int queue_total;
+static unsigned int queue_dropped = 0;
+static unsigned int queue_user_dropped = 0;
static struct sock *ipqnl;
static LIST_HEAD(queue_list);
static DECLARE_MUTEX(ipqnl_sem);
@@ -70,18 +75,11 @@ ipq_issue_verdict(struct ipq_queue_entry *entry, int verdict)
kfree(entry);
}
-static inline int
+static inline void
__ipq_enqueue_entry(struct ipq_queue_entry *entry)
{
- if (queue_total >= queue_maxlen) {
- if (net_ratelimit())
- printk(KERN_WARNING "ip_queue: full at %d entries, "
- "dropping packet(s).\n", queue_total);
- return -ENOSPC;
- }
list_add(&entry->list, &queue_list);
queue_total++;
- return 0;
}
/*
@@ -308,14 +306,24 @@ ipq_enqueue_packet(struct sk_buff *skb, struct nf_info *info, void *data)
if (!peer_pid)
goto err_out_free_nskb;
+ if (queue_total >= queue_maxlen) {
+ queue_dropped++;
+ status = -ENOSPC;
+ if (net_ratelimit())
+ printk (KERN_WARNING "ip_queue: full at %d entries, "
+ "dropping packets(s). Dropped: %d\n", queue_total,
+ queue_dropped);
+ goto err_out_free_nskb;
+ }
+
/* netlink_unicast will either free the nskb or attach it to a socket */
status = netlink_unicast(ipqnl, nskb, peer_pid, MSG_DONTWAIT);
- if (status < 0)
- goto err_out_unlock;
-
- status = __ipq_enqueue_entry(entry);
- if (status < 0)
+ if (status < 0) {
+ queue_user_dropped++;
goto err_out_unlock;
+ }
+
+ __ipq_enqueue_entry(entry);
write_unlock_bh(&queue_lock);
return status;
@@ -637,12 +645,16 @@ ipq_get_info(char *buffer, char **start, off_t offset, int length)
"Copy mode : %hu\n"
"Copy range : %u\n"
"Queue length : %u\n"
- "Queue max. length : %u\n",
+ "Queue max. length : %u\n"
+ "Queue dropped : %u\n"
+ "Netlink dropped : %u\n",
peer_pid,
copy_mode,
copy_range,
queue_total,
- queue_maxlen);
+ queue_maxlen,
+ queue_dropped,
+ queue_user_dropped);
read_unlock_bh(&queue_lock);
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 3d13400af58d5..8a54f92b8496a 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -923,7 +923,7 @@ translate_table(const char *name,
}
/* And one copy for every other CPU */
- for (i = 1; i < NR_CPUS; i++) {
+ for (i = 1; i < num_possible_cpus(); i++) {
memcpy(newinfo->entries + SMP_ALIGN(newinfo->size)*i,
newinfo->entries,
SMP_ALIGN(newinfo->size));
@@ -945,7 +945,7 @@ replace_table(struct ipt_table *table,
struct ipt_entry *table_base;
unsigned int i;
- for (i = 0; i < NR_CPUS; i++) {
+ for (i = 0; i < num_possible_cpus(); i++) {
table_base =
(void *)newinfo->entries
+ TABLE_OFFSET(newinfo, i);
@@ -992,7 +992,7 @@ get_counters(const struct ipt_table_info *t,
unsigned int cpu;
unsigned int i;
- for (cpu = 0; cpu < NR_CPUS; cpu++) {
+ for (cpu = 0; cpu < num_possible_cpus(); cpu++) {
i = 0;
IPT_ENTRY_ITERATE(t->entries + TABLE_OFFSET(t, cpu),
t->size,
@@ -1130,7 +1130,7 @@ do_replace(void __user *user, unsigned int len)
return -ENOMEM;
newinfo = vmalloc(sizeof(struct ipt_table_info)
- + SMP_ALIGN(tmp.size) * NR_CPUS);
+ + SMP_ALIGN(tmp.size) * num_possible_cpus());
if (!newinfo)
return -ENOMEM;
@@ -1460,7 +1460,7 @@ int ipt_register_table(struct ipt_table *table, const struct ipt_replace *repl)
= { 0, 0, 0, { 0 }, { 0 }, { } };
newinfo = vmalloc(sizeof(struct ipt_table_info)
- + SMP_ALIGN(repl->size) * NR_CPUS);
+ + SMP_ALIGN(repl->size) * num_possible_cpus());
if (!newinfo)
return -ENOMEM;
diff --git a/net/ipv4/netfilter/ipt_LOG.c b/net/ipv4/netfilter/ipt_LOG.c
index 3713b5b4dd99d..ef08733d26da2 100644
--- a/net/ipv4/netfilter/ipt_LOG.c
+++ b/net/ipv4/netfilter/ipt_LOG.c
@@ -198,16 +198,16 @@ static void dump_packet(const struct ipt_log_info *info,
static size_t required_len[NR_ICMP_TYPES+1]
= { [ICMP_ECHOREPLY] = 4,
[ICMP_DEST_UNREACH]
- = 8 + sizeof(struct iphdr) + 8,
+ = 8 + sizeof(struct iphdr),
[ICMP_SOURCE_QUENCH]
- = 8 + sizeof(struct iphdr) + 8,
+ = 8 + sizeof(struct iphdr),
[ICMP_REDIRECT]
- = 8 + sizeof(struct iphdr) + 8,
+ = 8 + sizeof(struct iphdr),
[ICMP_ECHO] = 4,
[ICMP_TIME_EXCEEDED]
- = 8 + sizeof(struct iphdr) + 8,
+ = 8 + sizeof(struct iphdr),
[ICMP_PARAMETERPROB]
- = 8 + sizeof(struct iphdr) + 8,
+ = 8 + sizeof(struct iphdr),
[ICMP_TIMESTAMP] = 20,
[ICMP_TIMESTAMPREPLY] = 20,
[ICMP_ADDRESS] = 12,
diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c
index 7593090ee2224..266d64979286d 100644
--- a/net/ipv4/netfilter/ipt_REJECT.c
+++ b/net/ipv4/netfilter/ipt_REJECT.c
@@ -207,163 +207,22 @@ static void send_reset(struct sk_buff *oldskb, int hook)
nskb->nh.iph->ihl);
/* "Never happens" */
- if (nskb->len > dst_pmtu(nskb->dst))
+ if (nskb->len > dst_mtu(nskb->dst))
goto free_nskb;
nf_ct_attach(nskb, oldskb);
NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
- ip_finish_output);
+ dst_output);
return;
free_nskb:
kfree_skb(nskb);
}
-static void send_unreach(struct sk_buff *skb_in, int code)
+static inline void send_unreach(struct sk_buff *skb_in, int code)
{
- struct iphdr *iph;
- struct icmphdr *icmph;
- struct sk_buff *nskb;
- u32 saddr;
- u8 tos;
- int hh_len, length;
- struct rtable *rt = (struct rtable*)skb_in->dst;
- unsigned char *data;
-
- if (!rt)
- return;
-
- /* FIXME: Use sysctl number. --RR */
- if (!xrlim_allow(&rt->u.dst, 1*HZ))
- return;
-
- iph = skb_in->nh.iph;
-
- /* No replies to physical multicast/broadcast */
- if (skb_in->pkt_type!=PACKET_HOST)
- return;
-
- /* Now check at the protocol level */
- if (rt->rt_flags&(RTCF_BROADCAST|RTCF_MULTICAST))
- return;
-
- /* Only reply to fragment 0. */
- if (iph->frag_off&htons(IP_OFFSET))
- return;
-
- /* Ensure we have at least 8 bytes of proto header. */
- if (skb_in->len < skb_in->nh.iph->ihl*4 + 8)
- return;
-
- /* If we send an ICMP error to an ICMP error a mess would result.. */
- if (iph->protocol == IPPROTO_ICMP) {
- struct icmphdr ihdr;
-
- icmph = skb_header_pointer(skb_in, skb_in->nh.iph->ihl*4,
- sizeof(ihdr), &ihdr);
- if (!icmph)
- return;
-
- /* Between echo-reply (0) and timestamp (13),
- everything except echo-request (8) is an error.
- Also, anything greater than NR_ICMP_TYPES is
- unknown, and hence should be treated as an error... */
- if ((icmph->type < ICMP_TIMESTAMP
- && icmph->type != ICMP_ECHOREPLY
- && icmph->type != ICMP_ECHO)
- || icmph->type > NR_ICMP_TYPES)
- return;
- }
-
- saddr = iph->daddr;
- if (!(rt->rt_flags & RTCF_LOCAL))
- saddr = 0;
-
- tos = (iph->tos & IPTOS_TOS_MASK) | IPTOS_PREC_INTERNETCONTROL;
-
- {
- struct flowi fl = {
- .nl_u = {
- .ip4_u = {
- .daddr = skb_in->nh.iph->saddr,
- .saddr = saddr,
- .tos = RT_TOS(tos)
- }
- },
- .proto = IPPROTO_ICMP,
- .uli_u = {
- .icmpt = {
- .type = ICMP_DEST_UNREACH,
- .code = code
- }
- }
- };
-
- if (ip_route_output_key(&rt, &fl))
- return;
- }
- /* RFC says return as much as we can without exceeding 576 bytes. */
- length = skb_in->len + sizeof(struct iphdr) + sizeof(struct icmphdr);
-
- if (length > dst_pmtu(&rt->u.dst))
- length = dst_pmtu(&rt->u.dst);
- if (length > 576)
- length = 576;
-
- hh_len = LL_RESERVED_SPACE(rt->u.dst.dev);
-
- nskb = alloc_skb(hh_len + length, GFP_ATOMIC);
- if (!nskb) {
- ip_rt_put(rt);
- return;
- }
-
- nskb->priority = 0;
- nskb->dst = &rt->u.dst;
- skb_reserve(nskb, hh_len);
-
- /* Set up IP header */
- iph = nskb->nh.iph
- = (struct iphdr *)skb_put(nskb, sizeof(struct iphdr));
- iph->version=4;
- iph->ihl=5;
- iph->tos=tos;
- iph->tot_len = htons(length);
-
- /* PMTU discovery never applies to ICMP packets. */
- iph->frag_off = 0;
-
- iph->ttl = MAXTTL;
- ip_select_ident(iph, &rt->u.dst, NULL);
- iph->protocol=IPPROTO_ICMP;
- iph->saddr=rt->rt_src;
- iph->daddr=rt->rt_dst;
- iph->check=0;
- iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
-
- /* Set up ICMP header. */
- icmph = nskb->h.icmph
- = (struct icmphdr *)skb_put(nskb, sizeof(struct icmphdr));
- icmph->type = ICMP_DEST_UNREACH;
- icmph->code = code;
- icmph->un.gateway = 0;
- icmph->checksum = 0;
-
- /* Copy as much of original packet as will fit */
- data = skb_put(nskb,
- length - sizeof(struct iphdr) - sizeof(struct icmphdr));
-
- skb_copy_bits(skb_in, 0, data,
- length - sizeof(struct iphdr) - sizeof(struct icmphdr));
-
- icmph->checksum = ip_compute_csum((unsigned char *)icmph,
- length - sizeof(struct iphdr));
-
- nf_ct_attach(nskb, skb_in);
-
- NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
- ip_finish_output);
+ icmp_send(skb_in, ICMP_DEST_UNREACH, code, 0);
}
static unsigned int reject(struct sk_buff **pskb,
diff --git a/net/ipv4/netfilter/ipt_TCPMSS.c b/net/ipv4/netfilter/ipt_TCPMSS.c
index 4ef4782c9c4c4..1049050b2bfbc 100644
--- a/net/ipv4/netfilter/ipt_TCPMSS.c
+++ b/net/ipv4/netfilter/ipt_TCPMSS.c
@@ -87,14 +87,14 @@ ipt_tcpmss_target(struct sk_buff **pskb,
return NF_DROP; /* or IPT_CONTINUE ?? */
}
- if(dst_pmtu((*pskb)->dst) <= (sizeof(struct iphdr) + sizeof(struct tcphdr))) {
+ if(dst_mtu((*pskb)->dst) <= (sizeof(struct iphdr) + sizeof(struct tcphdr))) {
if (net_ratelimit())
printk(KERN_ERR
- "ipt_tcpmss_target: unknown or invalid path-MTU (%d)\n", dst_pmtu((*pskb)->dst));
+ "ipt_tcpmss_target: unknown or invalid path-MTU (%d)\n", dst_mtu((*pskb)->dst));
return NF_DROP; /* or IPT_CONTINUE ?? */
}
- newmss = dst_pmtu((*pskb)->dst) - sizeof(struct iphdr) - sizeof(struct tcphdr);
+ newmss = dst_mtu((*pskb)->dst) - sizeof(struct iphdr) - sizeof(struct tcphdr);
} else
newmss = tcpmssinfo->mss;
diff --git a/net/ipv4/netfilter/ipt_hashlimit.c b/net/ipv4/netfilter/ipt_hashlimit.c
index 9d80cac77089f..7b923d40861e1 100644
--- a/net/ipv4/netfilter/ipt_hashlimit.c
+++ b/net/ipv4/netfilter/ipt_hashlimit.c
@@ -33,14 +33,11 @@
#include <linux/sctp.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
-
-#define ASSERT_READ_LOCK(x)
-#define ASSERT_WRITE_LOCK(x)
-#include <linux/netfilter_ipv4/lockhelp.h>
-#include <linux/netfilter_ipv4/listhelp.h>
+#include <linux/list.h>
#include <linux/netfilter_ipv4/ip_tables.h>
#include <linux/netfilter_ipv4/ipt_hashlimit.h>
+#include <linux/netfilter_ipv4/lockhelp.h>
/* FIXME: this is just for IP_NF_ASSERRT */
#include <linux/netfilter_ipv4/ip_conntrack.h>
@@ -67,7 +64,7 @@ struct dsthash_dst {
struct dsthash_ent {
/* static / read-only parts in the beginning */
- struct list_head list;
+ struct hlist_node node;
struct dsthash_dst dst;
/* modified structure members in the end */
@@ -80,7 +77,7 @@ struct dsthash_ent {
};
struct ipt_hashlimit_htable {
- struct list_head list; /* global list of all htables */
+ struct hlist_node node; /* global list of all htables */
atomic_t use;
struct hashlimit_cfg cfg; /* config */
@@ -94,11 +91,12 @@ struct ipt_hashlimit_htable {
/* seq_file stuff */
struct proc_dir_entry *pde;
- struct list_head hash[0]; /* hashtable itself */
+ struct hlist_head hash[0]; /* hashtable itself */
};
-static DECLARE_RWLOCK(hashlimit_lock); /* protects htables list */
-static LIST_HEAD(hashlimit_htables);
+static DECLARE_LOCK(hashlimit_lock); /* protects htables list */
+static DECLARE_MUTEX(hlimit_mutex); /* additional checkentry protection */
+static HLIST_HEAD(hashlimit_htables);
static kmem_cache_t *hashlimit_cachep;
static inline int dst_cmp(const struct dsthash_ent *ent, struct dsthash_dst *b)
@@ -112,16 +110,24 @@ static inline int dst_cmp(const struct dsthash_ent *ent, struct dsthash_dst *b)
static inline u_int32_t
hash_dst(const struct ipt_hashlimit_htable *ht, const struct dsthash_dst *dst)
{
- return (jhash_3words(dst->dst_ip, (dst->dst_port<<16 & dst->src_port),
+ return (jhash_3words(dst->dst_ip, (dst->dst_port<<16 | dst->src_port),
dst->src_ip, ht->rnd) % ht->cfg.size);
}
static inline struct dsthash_ent *
__dsthash_find(const struct ipt_hashlimit_htable *ht, struct dsthash_dst *dst)
{
- struct dsthash_ent *ent;
+ struct dsthash_ent *ent = NULL;
+ struct hlist_node *pos;
u_int32_t hash = hash_dst(ht, dst);
- ent = LIST_FIND(&ht->hash[hash], dst_cmp, struct dsthash_ent *, dst);
+
+ if (!hlist_empty(&ht->hash[hash]))
+ hlist_for_each_entry(ent, pos, &ht->hash[hash], node) {
+ if (dst_cmp(ent, dst)) {
+ break;
+ }
+ }
+
return ent;
}
@@ -161,7 +167,7 @@ __dsthash_alloc_init(struct ipt_hashlimit_htable *ht, struct dsthash_dst *dst)
ent->dst.src_ip = dst->src_ip;
ent->dst.src_port = dst->src_port;
- list_add(&ent->list, &ht->hash[hash_dst(ht, dst)]);
+ hlist_add_head(&ent->node, &ht->hash[hash_dst(ht, dst)]);
return ent;
}
@@ -169,7 +175,7 @@ __dsthash_alloc_init(struct ipt_hashlimit_htable *ht, struct dsthash_dst *dst)
static inline void
__dsthash_free(struct ipt_hashlimit_htable *ht, struct dsthash_ent *ent)
{
- list_del(&ent->list);
+ hlist_del(&ent->node);
kmem_cache_free(hashlimit_cachep, ent);
atomic_dec(&ht->count);
}
@@ -209,7 +215,7 @@ static int htable_create(struct ipt_hashlimit_info *minfo)
hinfo->cfg.max = hinfo->cfg.size;
for (i = 0; i < hinfo->cfg.size; i++)
- INIT_LIST_HEAD(&hinfo->hash[i]);
+ INIT_HLIST_HEAD(&hinfo->hash[i]);
atomic_set(&hinfo->count, 0);
atomic_set(&hinfo->use, 1);
@@ -229,9 +235,9 @@ static int htable_create(struct ipt_hashlimit_info *minfo)
hinfo->timer.function = htable_gc;
add_timer(&hinfo->timer);
- WRITE_LOCK(&hashlimit_lock);
- list_add(&hinfo->list, &hashlimit_htables);
- WRITE_UNLOCK(&hashlimit_lock);
+ LOCK_BH(&hashlimit_lock);
+ hlist_add_head(&hinfo->node, &hashlimit_htables);
+ UNLOCK_BH(&hashlimit_lock);
return 0;
}
@@ -257,8 +263,9 @@ static void htable_selective_cleanup(struct ipt_hashlimit_htable *ht,
/* lock hash table and iterate over it */
spin_lock_bh(&ht->lock);
for (i = 0; i < ht->cfg.size; i++) {
- struct dsthash_ent *dh, *n;
- list_for_each_entry_safe(dh, n, &ht->hash[i], list) {
+ struct dsthash_ent *dh;
+ struct hlist_node *pos, *n;
+ hlist_for_each_entry_safe(dh, pos, n, &ht->hash[i], node) {
if ((*select)(ht, dh))
__dsthash_free(ht, dh);
}
@@ -294,16 +301,17 @@ static void htable_destroy(struct ipt_hashlimit_htable *hinfo)
static struct ipt_hashlimit_htable *htable_find_get(char *name)
{
struct ipt_hashlimit_htable *hinfo;
+ struct hlist_node *pos;
- READ_LOCK(&hashlimit_lock);
- list_for_each_entry(hinfo, &hashlimit_htables, list) {
+ LOCK_BH(&hashlimit_lock);
+ hlist_for_each_entry(hinfo, pos, &hashlimit_htables, node) {
if (!strcmp(name, hinfo->pde->name)) {
atomic_inc(&hinfo->use);
- READ_UNLOCK(&hashlimit_lock);
+ UNLOCK_BH(&hashlimit_lock);
return hinfo;
}
}
- READ_UNLOCK(&hashlimit_lock);
+ UNLOCK_BH(&hashlimit_lock);
return NULL;
}
@@ -311,9 +319,9 @@ static struct ipt_hashlimit_htable *htable_find_get(char *name)
static void htable_put(struct ipt_hashlimit_htable *hinfo)
{
if (atomic_dec_and_test(&hinfo->use)) {
- WRITE_LOCK(&hashlimit_lock);
- list_del(&hinfo->list);
- WRITE_UNLOCK(&hashlimit_lock);
+ LOCK_BH(&hashlimit_lock);
+ hlist_del(&hinfo->node);
+ UNLOCK_BH(&hashlimit_lock);
htable_destroy(hinfo);
}
}
@@ -531,10 +539,19 @@ hashlimit_checkentry(const char *tablename,
if (!r->cfg.expire)
return 0;
+ /* This is the best we've got: We cannot release and re-grab lock,
+ * since checkentry() is called before ip_tables.c grabs ipt_mutex.
+ * We also cannot grab the hashtable spinlock, since htable_create will
+ * call vmalloc, and that can sleep. And we cannot just re-search
+ * the list of htable's in htable_create(), since then we would
+ * create duplicate proc files. -HW */
+ down(&hlimit_mutex);
r->hinfo = htable_find_get(r->name);
if (!r->hinfo && (htable_create(r) != 0)) {
+ up(&hlimit_mutex);
return 0;
}
+ up(&hlimit_mutex);
/* Ugly hack: For SMP, we only want to use one set */
r->u.master = r;
@@ -609,7 +626,7 @@ static inline int dl_seq_real_show(struct dsthash_ent *ent, struct seq_file *s)
rateinfo_recalc(ent, jiffies);
return seq_printf(s, "%ld %u.%u.%u.%u:%u->%u.%u.%u.%u:%u %u %u %u\n",
- (ent->expires - jiffies)/HZ,
+ (long)(ent->expires - jiffies)/HZ,
NIPQUAD(ent->dst.src_ip), ntohs(ent->dst.src_port),
NIPQUAD(ent->dst.dst_ip), ntohs(ent->dst.dst_port),
ent->rateinfo.credit, ent->rateinfo.credit_cap,
@@ -621,12 +638,17 @@ static int dl_seq_show(struct seq_file *s, void *v)
struct proc_dir_entry *pde = s->private;
struct ipt_hashlimit_htable *htable = pde->data;
unsigned int *bucket = (unsigned int *)v;
-
- if (LIST_FIND_W(&htable->hash[*bucket], dl_seq_real_show,
- struct dsthash_ent *, s)) {
- /* buffer was filled and unable to print that tuple */
- return 1;
- }
+ struct dsthash_ent *ent;
+ struct hlist_node *pos;
+
+ if (!hlist_empty(&htable->hash[*bucket]))
+ hlist_for_each_entry(ent, pos, &htable->hash[*bucket], node) {
+ if (dl_seq_real_show(ent, s)) {
+ /* buffer was filled and unable to print that tuple */
+ return 1;
+ }
+ }
+
return 0;
}
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index eaf475a066c24..1e71ed6507fd4 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -457,7 +457,7 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
daddr = ipc.opt->faddr;
}
}
- tos = RT_TOS(inet->tos) | sk->sk_localroute;
+ tos = RT_CONN_FLAGS(sk);
if (msg->msg_flags & MSG_DONTROUTE)
tos |= RTO_ONLINK;
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 24e7f12f19727..9f91a116d9192 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -100,10 +100,14 @@
#include <net/tcp.h>
#include <net/icmp.h>
#include <net/xfrm.h>
+#include <net/ip_mp_alg.h>
#ifdef CONFIG_SYSCTL
#include <linux/sysctl.h>
#endif
+#define RT_FL_TOS(oldflp) \
+ ((u32)(oldflp->fl4_tos & (IPTOS_RT_MASK | RTO_ONLINK)))
+
#define IP_MAX_MTU 0xFFF0
#define RT_GC_TIMEOUT (300*HZ)
@@ -447,11 +451,13 @@ static struct file_operations rt_cpu_seq_fops = {
static __inline__ void rt_free(struct rtable *rt)
{
+ multipath_remove(rt);
call_rcu_bh(&rt->u.dst.rcu_head, dst_rcu_free);
}
static __inline__ void rt_drop(struct rtable *rt)
{
+ multipath_remove(rt);
ip_rt_put(rt);
call_rcu_bh(&rt->u.dst.rcu_head, dst_rcu_free);
}
@@ -513,6 +519,59 @@ static inline u32 rt_score(struct rtable *rt)
return score;
}
+static inline int compare_keys(struct flowi *fl1, struct flowi *fl2)
+{
+ return memcmp(&fl1->nl_u.ip4_u, &fl2->nl_u.ip4_u, sizeof(fl1->nl_u.ip4_u)) == 0 &&
+ fl1->oif == fl2->oif &&
+ fl1->iif == fl2->iif;
+}
+
+#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
+static struct rtable **rt_remove_balanced_route(struct rtable **chain_head,
+ struct rtable *expentry,
+ int *removed_count)
+{
+ int passedexpired = 0;
+ struct rtable **nextstep = NULL;
+ struct rtable **rthp = chain_head;
+ struct rtable *rth;
+
+ if (removed_count)
+ *removed_count = 0;
+
+ while ((rth = *rthp) != NULL) {
+ if (rth == expentry)
+ passedexpired = 1;
+
+ if (((*rthp)->u.dst.flags & DST_BALANCED) != 0 &&
+ compare_keys(&(*rthp)->fl, &expentry->fl)) {
+ if (*rthp == expentry) {
+ *rthp = rth->u.rt_next;
+ continue;
+ } else {
+ *rthp = rth->u.rt_next;
+ rt_free(rth);
+ if (removed_count)
+ ++(*removed_count);
+ }
+ } else {
+ if (!((*rthp)->u.dst.flags & DST_BALANCED) &&
+ passedexpired && !nextstep)
+ nextstep = &rth->u.rt_next;
+
+ rthp = &rth->u.rt_next;
+ }
+ }
+
+ rt_free(expentry);
+ if (removed_count)
+ ++(*removed_count);
+
+ return nextstep;
+}
+#endif /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */
+
+
/* This runs via a timer and thus is always in BH context. */
static void rt_check_expire(unsigned long dummy)
{
@@ -544,8 +603,22 @@ static void rt_check_expire(unsigned long dummy)
}
/* Cleanup aged off entries. */
- *rthp = rth->u.rt_next;
- rt_free(rth);
+#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
+ /* remove all related balanced entries if necessary */
+ if (rth->u.dst.flags & DST_BALANCED) {
+ rthp = rt_remove_balanced_route(
+ &rt_hash_table[i].chain,
+ rth, NULL);
+ if (!rthp)
+ break;
+ } else {
+ *rthp = rth->u.rt_next;
+ rt_free(rth);
+ }
+#else /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */
+ *rthp = rth->u.rt_next;
+ rt_free(rth);
+#endif /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */
}
spin_unlock(&rt_hash_table[i].lock);
@@ -593,6 +666,9 @@ void rt_cache_flush(int delay)
if (delay < 0)
delay = ip_rt_min_delay;
+ /* flush existing multipath state*/
+ multipath_flush();
+
spin_lock_bh(&rt_flush_lock);
if (del_timer(&rt_flush_timer) && delay > 0 && rt_deadline) {
@@ -711,9 +787,30 @@ static int rt_garbage_collect(void)
rthp = &rth->u.rt_next;
continue;
}
+#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
+ /* remove all related balanced entries
+ * if necessary
+ */
+ if (rth->u.dst.flags & DST_BALANCED) {
+ int r;
+
+ rthp = rt_remove_balanced_route(
+ &rt_hash_table[i].chain,
+ rth,
+ &r);
+ goal -= r;
+ if (!rthp)
+ break;
+ } else {
+ *rthp = rth->u.rt_next;
+ rt_free(rth);
+ goal--;
+ }
+#else /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */
*rthp = rth->u.rt_next;
rt_free(rth);
goal--;
+#endif /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */
}
spin_unlock_bh(&rt_hash_table[k].lock);
if (goal <= 0)
@@ -767,13 +864,6 @@ work_done:
out: return 0;
}
-static inline int compare_keys(struct flowi *fl1, struct flowi *fl2)
-{
- return memcmp(&fl1->nl_u.ip4_u, &fl2->nl_u.ip4_u, sizeof(fl1->nl_u.ip4_u)) == 0 &&
- fl1->oif == fl2->oif &&
- fl1->iif == fl2->iif;
-}
-
static int rt_intern_hash(unsigned hash, struct rtable *rt, struct rtable **rp)
{
struct rtable *rth, **rthp;
@@ -794,7 +884,12 @@ restart:
spin_lock_bh(&rt_hash_table[hash].lock);
while ((rth = *rthp) != NULL) {
+#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
+ if (!(rth->u.dst.flags & DST_BALANCED) &&
+ compare_keys(&rth->fl, &rt->fl)) {
+#else
if (compare_keys(&rth->fl, &rt->fl)) {
+#endif
/* Put it first */
*rthp = rth->u.rt_next;
/*
@@ -1322,7 +1417,6 @@ static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu)
static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie)
{
- dst_release(dst);
return NULL;
}
@@ -1535,6 +1629,223 @@ e_inval:
return -EINVAL;
}
+
+static void ip_handle_martian_source(struct net_device *dev,
+ struct in_device *in_dev,
+ struct sk_buff *skb,
+ u32 daddr,
+ u32 saddr)
+{
+ RT_CACHE_STAT_INC(in_martian_src);
+#ifdef CONFIG_IP_ROUTE_VERBOSE
+ if (IN_DEV_LOG_MARTIANS(in_dev) && net_ratelimit()) {
+ /*
+ * RFC1812 recommendation, if source is martian,
+ * the only hint is MAC header.
+ */
+ printk(KERN_WARNING "martian source %u.%u.%u.%u from "
+ "%u.%u.%u.%u, on dev %s\n",
+ NIPQUAD(daddr), NIPQUAD(saddr), dev->name);
+ if (dev->hard_header_len) {
+ int i;
+ unsigned char *p = skb->mac.raw;
+ printk(KERN_WARNING "ll header: ");
+ for (i = 0; i < dev->hard_header_len; i++, p++) {
+ printk("%02x", *p);
+ if (i < (dev->hard_header_len - 1))
+ printk(":");
+ }
+ printk("\n");
+ }
+ }
+#endif
+}
+
+static inline int __mkroute_input(struct sk_buff *skb,
+ struct fib_result* res,
+ struct in_device *in_dev,
+ u32 daddr, u32 saddr, u32 tos,
+ struct rtable **result)
+{
+
+ struct rtable *rth;
+ int err;
+ struct in_device *out_dev;
+ unsigned flags = 0;
+ u32 spec_dst, itag;
+
+ /* get a working reference to the output device */
+ out_dev = in_dev_get(FIB_RES_DEV(*res));
+ if (out_dev == NULL) {
+ if (net_ratelimit())
+ printk(KERN_CRIT "Bug in ip_route_input" \
+ "_slow(). Please, report\n");
+ return -EINVAL;
+ }
+
+
+ err = fib_validate_source(saddr, daddr, tos, FIB_RES_OIF(*res),
+ in_dev->dev, &spec_dst, &itag);
+ if (err < 0) {
+ ip_handle_martian_source(in_dev->dev, in_dev, skb, daddr,
+ saddr);
+
+ err = -EINVAL;
+ goto cleanup;
+ }
+
+ if (err)
+ flags |= RTCF_DIRECTSRC;
+
+ if (out_dev == in_dev && err && !(flags & (RTCF_NAT | RTCF_MASQ)) &&
+ (IN_DEV_SHARED_MEDIA(out_dev) ||
+ inet_addr_onlink(out_dev, saddr, FIB_RES_GW(*res))))
+ flags |= RTCF_DOREDIRECT;
+
+ if (skb->protocol != htons(ETH_P_IP)) {
+ /* Not IP (i.e. ARP). Do not create route, if it is
+ * invalid for proxy arp. DNAT routes are always valid.
+ */
+ if (out_dev == in_dev && !(flags & RTCF_DNAT)) {
+ err = -EINVAL;
+ goto cleanup;
+ }
+ }
+
+
+ rth = dst_alloc(&ipv4_dst_ops);
+ if (!rth) {
+ err = -ENOBUFS;
+ goto cleanup;
+ }
+
+ rth->u.dst.flags= DST_HOST;
+#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
+ if (res->fi->fib_nhs > 1)
+ rth->u.dst.flags |= DST_BALANCED;
+#endif
+ if (in_dev->cnf.no_policy)
+ rth->u.dst.flags |= DST_NOPOLICY;
+ if (in_dev->cnf.no_xfrm)
+ rth->u.dst.flags |= DST_NOXFRM;
+ rth->fl.fl4_dst = daddr;
+ rth->rt_dst = daddr;
+ rth->fl.fl4_tos = tos;
+#ifdef CONFIG_IP_ROUTE_FWMARK
+ rth->fl.fl4_fwmark= skb->nfmark;
+#endif
+ rth->fl.fl4_src = saddr;
+ rth->rt_src = saddr;
+ rth->rt_gateway = daddr;
+ rth->rt_iif =
+ rth->fl.iif = in_dev->dev->ifindex;
+ rth->u.dst.dev = (out_dev)->dev;
+ dev_hold(rth->u.dst.dev);
+ rth->idev = in_dev_get(rth->u.dst.dev);
+ rth->fl.oif = 0;
+ rth->rt_spec_dst= spec_dst;
+
+ rth->u.dst.input = ip_forward;
+ rth->u.dst.output = ip_output;
+
+ rt_set_nexthop(rth, res, itag);
+
+ rth->rt_flags = flags;
+
+ *result = rth;
+ err = 0;
+ cleanup:
+ /* release the working reference to the output device */
+ in_dev_put(out_dev);
+ return err;
+}
+
+static inline int ip_mkroute_input_def(struct sk_buff *skb,
+ struct fib_result* res,
+ const struct flowi *fl,
+ struct in_device *in_dev,
+ u32 daddr, u32 saddr, u32 tos)
+{
+ struct rtable* rth;
+ int err;
+ unsigned hash;
+
+#ifdef CONFIG_IP_ROUTE_MULTIPATH
+ if (res->fi && res->fi->fib_nhs > 1 && fl->oif == 0)
+ fib_select_multipath(fl, res);
+#endif
+
+ /* create a routing cache entry */
+ err = __mkroute_input(skb, res, in_dev, daddr, saddr, tos, &rth);
+ if (err)
+ return err;
+ atomic_set(&rth->u.dst.__refcnt, 1);
+
+ /* put it into the cache */
+ hash = rt_hash_code(daddr, saddr ^ (fl->iif << 5), tos);
+ return rt_intern_hash(hash, rth, (struct rtable**)&skb->dst);
+}
+
+static inline int ip_mkroute_input(struct sk_buff *skb,
+ struct fib_result* res,
+ const struct flowi *fl,
+ struct in_device *in_dev,
+ u32 daddr, u32 saddr, u32 tos)
+{
+#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
+ struct rtable* rth;
+ unsigned char hop, hopcount, lasthop;
+ int err = -EINVAL;
+ unsigned int hash;
+
+ if (res->fi)
+ hopcount = res->fi->fib_nhs;
+ else
+ hopcount = 1;
+
+ lasthop = hopcount - 1;
+
+ /* distinguish between multipath and singlepath */
+ if (hopcount < 2)
+ return ip_mkroute_input_def(skb, res, fl, in_dev, daddr,
+ saddr, tos);
+
+ /* add all alternatives to the routing cache */
+ for (hop = 0; hop < hopcount; hop++) {
+ res->nh_sel = hop;
+
+ /* create a routing cache entry */
+ err = __mkroute_input(skb, res, in_dev, daddr, saddr, tos,
+ &rth);
+ if (err)
+ return err;
+
+ /* put it into the cache */
+ hash = rt_hash_code(daddr, saddr ^ (fl->iif << 5), tos);
+ err = rt_intern_hash(hash, rth, (struct rtable**)&skb->dst);
+ if (err)
+ return err;
+
+ /* forward hop information to multipath impl. */
+ multipath_set_nhinfo(rth,
+ FIB_RES_NETWORK(*res),
+ FIB_RES_NETMASK(*res),
+ res->prefixlen,
+ &FIB_RES_NH(*res));
+
+ /* only for the last hop the reference count is handled
+ * outside
+ */
+ if (hop == lasthop)
+ atomic_set(&(skb->dst->__refcnt), 1);
+ }
+ return err;
+#else /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */
+ return ip_mkroute_input_def(skb, res, fl, in_dev, daddr, saddr, tos);
+#endif /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */
+}
+
+
/*
* NOTE. We drop all the packets that has local source
* addresses, because every properly looped back packet
@@ -1546,11 +1857,10 @@ e_inval:
*/
static int ip_route_input_slow(struct sk_buff *skb, u32 daddr, u32 saddr,
- u8 tos, struct net_device *dev)
+ u8 tos, struct net_device *dev)
{
struct fib_result res;
struct in_device *in_dev = in_dev_get(dev);
- struct in_device *out_dev = NULL;
struct flowi fl = { .nl_u = { .ip4_u =
{ .daddr = daddr,
.saddr = saddr,
@@ -1574,8 +1884,6 @@ static int ip_route_input_slow(struct sk_buff *skb, u32 daddr, u32 saddr,
if (!in_dev)
goto out;
- hash = rt_hash_code(daddr, saddr ^ (fl.iif << 5), tos);
-
/* Check for the most weird martians, which can be not detected
by fib_lookup.
*/
@@ -1628,79 +1936,14 @@ static int ip_route_input_slow(struct sk_buff *skb, u32 daddr, u32 saddr,
if (res.type != RTN_UNICAST)
goto martian_destination;
-#ifdef CONFIG_IP_ROUTE_MULTIPATH
- if (res.fi->fib_nhs > 1 && fl.oif == 0)
- fib_select_multipath(&fl, &res);
-#endif
- out_dev = in_dev_get(FIB_RES_DEV(res));
- if (out_dev == NULL) {
- if (net_ratelimit())
- printk(KERN_CRIT "Bug in ip_route_input_slow(). "
- "Please, report\n");
- goto e_inval;
- }
-
- err = fib_validate_source(saddr, daddr, tos, FIB_RES_OIF(res), dev,
- &spec_dst, &itag);
- if (err < 0)
- goto martian_source;
-
- if (err)
- flags |= RTCF_DIRECTSRC;
-
- if (out_dev == in_dev && err && !(flags & (RTCF_NAT | RTCF_MASQ)) &&
- (IN_DEV_SHARED_MEDIA(out_dev) ||
- inet_addr_onlink(out_dev, saddr, FIB_RES_GW(res))))
- flags |= RTCF_DOREDIRECT;
-
- if (skb->protocol != htons(ETH_P_IP)) {
- /* Not IP (i.e. ARP). Do not create route, if it is
- * invalid for proxy arp. DNAT routes are always valid.
- */
- if (out_dev == in_dev && !(flags & RTCF_DNAT))
- goto e_inval;
- }
-
- rth = dst_alloc(&ipv4_dst_ops);
- if (!rth)
+ err = ip_mkroute_input(skb, &res, &fl, in_dev, daddr, saddr, tos);
+ if (err == -ENOBUFS)
goto e_nobufs;
-
- atomic_set(&rth->u.dst.__refcnt, 1);
- rth->u.dst.flags= DST_HOST;
- if (in_dev->cnf.no_policy)
- rth->u.dst.flags |= DST_NOPOLICY;
- if (in_dev->cnf.no_xfrm)
- rth->u.dst.flags |= DST_NOXFRM;
- rth->fl.fl4_dst = daddr;
- rth->rt_dst = daddr;
- rth->fl.fl4_tos = tos;
-#ifdef CONFIG_IP_ROUTE_FWMARK
- rth->fl.fl4_fwmark= skb->nfmark;
-#endif
- rth->fl.fl4_src = saddr;
- rth->rt_src = saddr;
- rth->rt_gateway = daddr;
- rth->rt_iif =
- rth->fl.iif = dev->ifindex;
- rth->u.dst.dev = out_dev->dev;
- dev_hold(rth->u.dst.dev);
- rth->idev = in_dev_get(rth->u.dst.dev);
- rth->fl.oif = 0;
- rth->rt_spec_dst= spec_dst;
-
- rth->u.dst.input = ip_forward;
- rth->u.dst.output = ip_output;
-
- rt_set_nexthop(rth, &res, itag);
-
- rth->rt_flags = flags;
-
-intern:
- err = rt_intern_hash(hash, rth, (struct rtable**)&skb->dst);
+ if (err == -EINVAL)
+ goto e_inval;
+
done:
in_dev_put(in_dev);
- if (out_dev)
- in_dev_put(out_dev);
if (free_res)
fib_res_put(&res);
out: return err;
@@ -1760,7 +2003,9 @@ local_input:
rth->rt_flags &= ~RTCF_LOCAL;
}
rth->rt_type = res.type;
- goto intern;
+ hash = rt_hash_code(daddr, saddr ^ (fl.iif << 5), tos);
+ err = rt_intern_hash(hash, rth, (struct rtable**)&skb->dst);
+ goto done;
no_route:
RT_CACHE_STAT_INC(in_no_route);
@@ -1788,30 +2033,7 @@ e_nobufs:
goto done;
martian_source:
-
- RT_CACHE_STAT_INC(in_martian_src);
-#ifdef CONFIG_IP_ROUTE_VERBOSE
- if (IN_DEV_LOG_MARTIANS(in_dev) && net_ratelimit()) {
- /*
- * RFC1812 recommendation, if source is martian,
- * the only hint is MAC header.
- */
- printk(KERN_WARNING "martian source %u.%u.%u.%u from "
- "%u.%u.%u.%u, on dev %s\n",
- NIPQUAD(daddr), NIPQUAD(saddr), dev->name);
- if (dev->hard_header_len) {
- int i;
- unsigned char *p = skb->mac.raw;
- printk(KERN_WARNING "ll header: ");
- for (i = 0; i < dev->hard_header_len; i++, p++) {
- printk("%02x", *p);
- if (i < (dev->hard_header_len - 1))
- printk(":");
- }
- printk("\n");
- }
- }
-#endif
+ ip_handle_martian_source(dev, in_dev, skb, daddr, saddr);
goto e_inval;
}
@@ -1882,13 +2104,224 @@ int ip_route_input(struct sk_buff *skb, u32 daddr, u32 saddr,
return ip_route_input_slow(skb, daddr, saddr, tos, dev);
}
+static inline int __mkroute_output(struct rtable **result,
+ struct fib_result* res,
+ const struct flowi *fl,
+ const struct flowi *oldflp,
+ struct net_device *dev_out,
+ unsigned flags)
+{
+ struct rtable *rth;
+ struct in_device *in_dev;
+ u32 tos = RT_FL_TOS(oldflp);
+ int err = 0;
+
+ if (LOOPBACK(fl->fl4_src) && !(dev_out->flags&IFF_LOOPBACK))
+ return -EINVAL;
+
+ if (fl->fl4_dst == 0xFFFFFFFF)
+ res->type = RTN_BROADCAST;
+ else if (MULTICAST(fl->fl4_dst))
+ res->type = RTN_MULTICAST;
+ else if (BADCLASS(fl->fl4_dst) || ZERONET(fl->fl4_dst))
+ return -EINVAL;
+
+ if (dev_out->flags & IFF_LOOPBACK)
+ flags |= RTCF_LOCAL;
+
+ /* get work reference to inet device */
+ in_dev = in_dev_get(dev_out);
+ if (!in_dev)
+ return -EINVAL;
+
+ if (res->type == RTN_BROADCAST) {
+ flags |= RTCF_BROADCAST | RTCF_LOCAL;
+ if (res->fi) {
+ fib_info_put(res->fi);
+ res->fi = NULL;
+ }
+ } else if (res->type == RTN_MULTICAST) {
+ flags |= RTCF_MULTICAST|RTCF_LOCAL;
+ if (!ip_check_mc(in_dev, oldflp->fl4_dst, oldflp->fl4_src,
+ oldflp->proto))
+ flags &= ~RTCF_LOCAL;
+ /* If multicast route do not exist use
+ default one, but do not gateway in this case.
+ Yes, it is hack.
+ */
+ if (res->fi && res->prefixlen < 4) {
+ fib_info_put(res->fi);
+ res->fi = NULL;
+ }
+ }
+
+
+ rth = dst_alloc(&ipv4_dst_ops);
+ if (!rth) {
+ err = -ENOBUFS;
+ goto cleanup;
+ }
+
+ rth->u.dst.flags= DST_HOST;
+#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
+ if (res->fi) {
+ rth->rt_multipath_alg = res->fi->fib_mp_alg;
+ if (res->fi->fib_nhs > 1)
+ rth->u.dst.flags |= DST_BALANCED;
+ }
+#endif
+ if (in_dev->cnf.no_xfrm)
+ rth->u.dst.flags |= DST_NOXFRM;
+ if (in_dev->cnf.no_policy)
+ rth->u.dst.flags |= DST_NOPOLICY;
+
+ rth->fl.fl4_dst = oldflp->fl4_dst;
+ rth->fl.fl4_tos = tos;
+ rth->fl.fl4_src = oldflp->fl4_src;
+ rth->fl.oif = oldflp->oif;
+#ifdef CONFIG_IP_ROUTE_FWMARK
+ rth->fl.fl4_fwmark= oldflp->fl4_fwmark;
+#endif
+ rth->rt_dst = fl->fl4_dst;
+ rth->rt_src = fl->fl4_src;
+ rth->rt_iif = oldflp->oif ? : dev_out->ifindex;
+ /* get references to the devices that are to be hold by the routing
+ cache entry */
+ rth->u.dst.dev = dev_out;
+ dev_hold(dev_out);
+ rth->idev = in_dev_get(dev_out);
+ rth->rt_gateway = fl->fl4_dst;
+ rth->rt_spec_dst= fl->fl4_src;
+
+ rth->u.dst.output=ip_output;
+
+ RT_CACHE_STAT_INC(out_slow_tot);
+
+ if (flags & RTCF_LOCAL) {
+ rth->u.dst.input = ip_local_deliver;
+ rth->rt_spec_dst = fl->fl4_dst;
+ }
+ if (flags & (RTCF_BROADCAST | RTCF_MULTICAST)) {
+ rth->rt_spec_dst = fl->fl4_src;
+ if (flags & RTCF_LOCAL &&
+ !(dev_out->flags & IFF_LOOPBACK)) {
+ rth->u.dst.output = ip_mc_output;
+ RT_CACHE_STAT_INC(out_slow_mc);
+ }
+#ifdef CONFIG_IP_MROUTE
+ if (res->type == RTN_MULTICAST) {
+ if (IN_DEV_MFORWARD(in_dev) &&
+ !LOCAL_MCAST(oldflp->fl4_dst)) {
+ rth->u.dst.input = ip_mr_input;
+ rth->u.dst.output = ip_mc_output;
+ }
+ }
+#endif
+ }
+
+ rt_set_nexthop(rth, res, 0);
+
+ rth->rt_flags = flags;
+
+ *result = rth;
+ cleanup:
+ /* release work reference to inet device */
+ in_dev_put(in_dev);
+
+ return err;
+}
+
+static inline int ip_mkroute_output_def(struct rtable **rp,
+ struct fib_result* res,
+ const struct flowi *fl,
+ const struct flowi *oldflp,
+ struct net_device *dev_out,
+ unsigned flags)
+{
+ struct rtable *rth;
+ int err = __mkroute_output(&rth, res, fl, oldflp, dev_out, flags);
+ unsigned hash;
+ if (err == 0) {
+ u32 tos = RT_FL_TOS(oldflp);
+
+ atomic_set(&rth->u.dst.__refcnt, 1);
+
+ hash = rt_hash_code(oldflp->fl4_dst,
+ oldflp->fl4_src ^ (oldflp->oif << 5), tos);
+ err = rt_intern_hash(hash, rth, rp);
+ }
+
+ return err;
+}
+
+static inline int ip_mkroute_output(struct rtable** rp,
+ struct fib_result* res,
+ const struct flowi *fl,
+ const struct flowi *oldflp,
+ struct net_device *dev_out,
+ unsigned flags)
+{
+#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
+ u32 tos = RT_FL_TOS(oldflp);
+ unsigned char hop;
+ unsigned hash;
+ int err = -EINVAL;
+ struct rtable *rth;
+
+ if (res->fi && res->fi->fib_nhs > 1) {
+ unsigned char hopcount = res->fi->fib_nhs;
+
+ for (hop = 0; hop < hopcount; hop++) {
+ struct net_device *dev2nexthop;
+
+ res->nh_sel = hop;
+
+ /* hold a work reference to the output device */
+ dev2nexthop = FIB_RES_DEV(*res);
+ dev_hold(dev2nexthop);
+
+ err = __mkroute_output(&rth, res, fl, oldflp,
+ dev2nexthop, flags);
+
+ if (err != 0)
+ goto cleanup;
+
+ hash = rt_hash_code(oldflp->fl4_dst,
+ oldflp->fl4_src ^
+ (oldflp->oif << 5), tos);
+ err = rt_intern_hash(hash, rth, rp);
+
+ /* forward hop information to multipath impl. */
+ multipath_set_nhinfo(rth,
+ FIB_RES_NETWORK(*res),
+ FIB_RES_NETMASK(*res),
+ res->prefixlen,
+ &FIB_RES_NH(*res));
+ cleanup:
+ /* release work reference to output device */
+ dev_put(dev2nexthop);
+
+ if (err != 0)
+ return err;
+ }
+ atomic_set(&(*rp)->u.dst.__refcnt, 1);
+ return err;
+ } else {
+ return ip_mkroute_output_def(rp, res, fl, oldflp, dev_out,
+ flags);
+ }
+#else /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */
+ return ip_mkroute_output_def(rp, res, fl, oldflp, dev_out, flags);
+#endif
+}
+
/*
* Major route resolver routine.
*/
static int ip_route_output_slow(struct rtable **rp, const struct flowi *oldflp)
{
- u32 tos = oldflp->fl4_tos & (IPTOS_RT_MASK | RTO_ONLINK);
+ u32 tos = RT_FL_TOS(oldflp);
struct flowi fl = { .nl_u = { .ip4_u =
{ .daddr = oldflp->fl4_dst,
.saddr = oldflp->fl4_src,
@@ -1904,13 +2337,11 @@ static int ip_route_output_slow(struct rtable **rp, const struct flowi *oldflp)
.oif = oldflp->oif };
struct fib_result res;
unsigned flags = 0;
- struct rtable *rth;
struct net_device *dev_out = NULL;
- struct in_device *in_dev = NULL;
- unsigned hash;
int free_res = 0;
int err;
+
res.fi = NULL;
#ifdef CONFIG_IP_MULTIPLE_TABLES
res.r = NULL;
@@ -1960,6 +2391,8 @@ static int ip_route_output_slow(struct rtable **rp, const struct flowi *oldflp)
dev_put(dev_out);
dev_out = NULL;
}
+
+
if (oldflp->oif) {
dev_out = dev_get_by_index(oldflp->oif);
err = -ENODEV;
@@ -2066,117 +2499,16 @@ static int ip_route_output_slow(struct rtable **rp, const struct flowi *oldflp)
dev_hold(dev_out);
fl.oif = dev_out->ifindex;
-make_route:
- if (LOOPBACK(fl.fl4_src) && !(dev_out->flags&IFF_LOOPBACK))
- goto e_inval;
-
- if (fl.fl4_dst == 0xFFFFFFFF)
- res.type = RTN_BROADCAST;
- else if (MULTICAST(fl.fl4_dst))
- res.type = RTN_MULTICAST;
- else if (BADCLASS(fl.fl4_dst) || ZERONET(fl.fl4_dst))
- goto e_inval;
-
- if (dev_out->flags & IFF_LOOPBACK)
- flags |= RTCF_LOCAL;
-
- in_dev = in_dev_get(dev_out);
- if (!in_dev)
- goto e_inval;
-
- if (res.type == RTN_BROADCAST) {
- flags |= RTCF_BROADCAST | RTCF_LOCAL;
- if (res.fi) {
- fib_info_put(res.fi);
- res.fi = NULL;
- }
- } else if (res.type == RTN_MULTICAST) {
- flags |= RTCF_MULTICAST|RTCF_LOCAL;
- if (!ip_check_mc(in_dev, oldflp->fl4_dst, oldflp->fl4_src, oldflp->proto))
- flags &= ~RTCF_LOCAL;
- /* If multicast route do not exist use
- default one, but do not gateway in this case.
- Yes, it is hack.
- */
- if (res.fi && res.prefixlen < 4) {
- fib_info_put(res.fi);
- res.fi = NULL;
- }
- }
-
- rth = dst_alloc(&ipv4_dst_ops);
- if (!rth)
- goto e_nobufs;
-
- atomic_set(&rth->u.dst.__refcnt, 1);
- rth->u.dst.flags= DST_HOST;
- if (in_dev->cnf.no_xfrm)
- rth->u.dst.flags |= DST_NOXFRM;
- if (in_dev->cnf.no_policy)
- rth->u.dst.flags |= DST_NOPOLICY;
- rth->fl.fl4_dst = oldflp->fl4_dst;
- rth->fl.fl4_tos = tos;
- rth->fl.fl4_src = oldflp->fl4_src;
- rth->fl.oif = oldflp->oif;
-#ifdef CONFIG_IP_ROUTE_FWMARK
- rth->fl.fl4_fwmark= oldflp->fl4_fwmark;
-#endif
- rth->rt_dst = fl.fl4_dst;
- rth->rt_src = fl.fl4_src;
- rth->rt_iif = oldflp->oif ? : dev_out->ifindex;
- rth->u.dst.dev = dev_out;
- dev_hold(dev_out);
- rth->idev = in_dev_get(dev_out);
- rth->rt_gateway = fl.fl4_dst;
- rth->rt_spec_dst= fl.fl4_src;
-
- rth->u.dst.output=ip_output;
-
- RT_CACHE_STAT_INC(out_slow_tot);
-
- if (flags & RTCF_LOCAL) {
- rth->u.dst.input = ip_local_deliver;
- rth->rt_spec_dst = fl.fl4_dst;
- }
- if (flags & (RTCF_BROADCAST | RTCF_MULTICAST)) {
- rth->rt_spec_dst = fl.fl4_src;
- if (flags & RTCF_LOCAL && !(dev_out->flags & IFF_LOOPBACK)) {
- rth->u.dst.output = ip_mc_output;
- RT_CACHE_STAT_INC(out_slow_mc);
- }
-#ifdef CONFIG_IP_MROUTE
- if (res.type == RTN_MULTICAST) {
- if (IN_DEV_MFORWARD(in_dev) &&
- !LOCAL_MCAST(oldflp->fl4_dst)) {
- rth->u.dst.input = ip_mr_input;
- rth->u.dst.output = ip_mc_output;
- }
- }
-#endif
- }
- rt_set_nexthop(rth, &res, 0);
-
+make_route:
+ err = ip_mkroute_output(rp, &res, &fl, oldflp, dev_out, flags);
- rth->rt_flags = flags;
- hash = rt_hash_code(oldflp->fl4_dst, oldflp->fl4_src ^ (oldflp->oif << 5), tos);
- err = rt_intern_hash(hash, rth, rp);
-done:
if (free_res)
fib_res_put(&res);
if (dev_out)
dev_put(dev_out);
- if (in_dev)
- in_dev_put(in_dev);
out: return err;
-
-e_inval:
- err = -EINVAL;
- goto done;
-e_nobufs:
- err = -ENOBUFS;
- goto done;
}
int __ip_route_output_key(struct rtable **rp, const struct flowi *flp)
@@ -2198,6 +2530,17 @@ int __ip_route_output_key(struct rtable **rp, const struct flowi *flp)
#endif
!((rth->fl.fl4_tos ^ flp->fl4_tos) &
(IPTOS_RT_MASK | RTO_ONLINK))) {
+
+ /* check for multipath routes and choose one if
+ * necessary
+ */
+ if (multipath_select_route(flp, rth, rp)) {
+ dst_hold(&(*rp)->u.dst);
+ RT_CACHE_STAT_INC(out_hit);
+ rcu_read_unlock_bh();
+ return 0;
+ }
+
rth->u.dst.lastuse = jiffies;
dst_hold(&rth->u.dst);
rth->u.dst.__use++;
@@ -2272,6 +2615,13 @@ static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
if (rt->u.dst.tclassid)
RTA_PUT(skb, RTA_FLOW, 4, &rt->u.dst.tclassid);
#endif
+#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
+ if (rt->rt_multipath_alg != IP_MP_ALG_NONE) {
+ __u32 alg = rt->rt_multipath_alg;
+
+ RTA_PUT(skb, RTA_MP_ALGO, 4, &alg);
+ }
+#endif
if (rt->fl.iif)
RTA_PUT(skb, RTA_PREFSRC, 4, &rt->rt_spec_dst);
else if (rt->rt_src != rt->fl.fl4_src)
@@ -2545,10 +2895,10 @@ ctl_table ipv4_route_table[] = {
.ctl_name = NET_IPV4_ROUTE_GC_MIN_INTERVAL_MS,
.procname = "gc_min_interval_ms",
.data = &ip_rt_gc_min_interval,
- .maxlen = sizeof(unsigned long),
+ .maxlen = sizeof(int),
.mode = 0644,
- .proc_handler = &proc_doulongvec_ms_jiffies_minmax,
- .strategy = &sysctl_jiffies,
+ .proc_handler = &proc_dointvec_ms_jiffies,
+ .strategy = &sysctl_ms_jiffies,
},
{
.ctl_name = NET_IPV4_ROUTE_GC_TIMEOUT,
diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c
index 5d6d2138ac91a..4b87a4f11f465 100644
--- a/net/ipv4/syncookies.c
+++ b/net/ipv4/syncookies.c
@@ -17,11 +17,88 @@
#include <linux/tcp.h>
#include <linux/slab.h>
#include <linux/random.h>
+#include <linux/cryptohash.h>
#include <linux/kernel.h>
#include <net/tcp.h>
extern int sysctl_tcp_syncookies;
+static __u32 syncookie_secret[2][16-3+SHA_DIGEST_WORDS];
+
+static __init int init_syncookies(void)
+{
+ get_random_bytes(syncookie_secret, sizeof(syncookie_secret));
+ return 0;
+}
+module_init(init_syncookies);
+
+#define COOKIEBITS 24 /* Upper bits store count */
+#define COOKIEMASK (((__u32)1 << COOKIEBITS) - 1)
+
+static u32 cookie_hash(u32 saddr, u32 daddr, u32 sport, u32 dport,
+ u32 count, int c)
+{
+ __u32 tmp[16 + 5 + SHA_WORKSPACE_WORDS];
+
+ memcpy(tmp + 3, syncookie_secret[c], sizeof(syncookie_secret[c]));
+ tmp[0] = saddr;
+ tmp[1] = daddr;
+ tmp[2] = (sport << 16) + dport;
+ tmp[3] = count;
+ sha_transform(tmp + 16, (__u8 *)tmp, tmp + 16 + 5);
+
+ return tmp[17];
+}
+
+static __u32 secure_tcp_syn_cookie(__u32 saddr, __u32 daddr, __u16 sport,
+ __u16 dport, __u32 sseq, __u32 count,
+ __u32 data)
+{
+ /*
+ * Compute the secure sequence number.
+ * The output should be:
+ * HASH(sec1,saddr,sport,daddr,dport,sec1) + sseq + (count * 2^24)
+ * + (HASH(sec2,saddr,sport,daddr,dport,count,sec2) % 2^24).
+ * Where sseq is their sequence number and count increases every
+ * minute by 1.
+ * As an extra hack, we add a small "data" value that encodes the
+ * MSS into the second hash value.
+ */
+
+ return (cookie_hash(saddr, daddr, sport, dport, 0, 0) +
+ sseq + (count << COOKIEBITS) +
+ ((cookie_hash(saddr, daddr, sport, dport, count, 1) + data)
+ & COOKIEMASK));
+}
+
+/*
+ * This retrieves the small "data" value from the syncookie.
+ * If the syncookie is bad, the data returned will be out of
+ * range. This must be checked by the caller.
+ *
+ * The count value used to generate the cookie must be within
+ * "maxdiff" if the current (passed-in) "count". The return value
+ * is (__u32)-1 if this test fails.
+ */
+static __u32 check_tcp_syn_cookie(__u32 cookie, __u32 saddr, __u32 daddr,
+ __u16 sport, __u16 dport, __u32 sseq,
+ __u32 count, __u32 maxdiff)
+{
+ __u32 diff;
+
+ /* Strip away the layers from the cookie */
+ cookie -= cookie_hash(saddr, daddr, sport, dport, 0, 0) + sseq;
+
+ /* Cookie is now reduced to (count * 2^24) ^ (hash % 2^24) */
+ diff = (count - (cookie >> COOKIEBITS)) & ((__u32) - 1 >> COOKIEBITS);
+ if (diff >= maxdiff)
+ return (__u32)-1;
+
+ return (cookie -
+ cookie_hash(saddr, daddr, sport, dport, count - diff, 1))
+ & COOKIEMASK; /* Leaving the data behind */
+}
+
/*
* This table has to be sorted and terminated with (__u16)-1.
* XXX generate a better table.
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 0903d6ece86f2..5cff56af78551 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -598,6 +598,7 @@ static inline void skb_entail(struct sock *sk, struct tcp_sock *tp,
TCP_SKB_CB(skb)->end_seq = tp->write_seq;
TCP_SKB_CB(skb)->flags = TCPCB_FLAG_ACK;
TCP_SKB_CB(skb)->sacked = 0;
+ skb_header_release(skb);
__skb_queue_tail(&sk->sk_write_queue, skb);
sk_charge_skb(sk, skb);
if (!sk->sk_send_head)
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 8a71e824e17e1..2504927359024 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -71,6 +71,7 @@
#include <net/tcp.h>
#include <net/inet_common.h>
#include <linux/ipsec.h>
+#include <asm/unaligned.h>
int sysctl_tcp_timestamps = 1;
int sysctl_tcp_window_scaling = 1;
@@ -977,7 +978,7 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_
* Not good, but alternative is to resegment the queue. */
if (sk->sk_route_caps & NETIF_F_TSO) {
sk->sk_route_caps &= ~NETIF_F_TSO;
- sk->sk_no_largesend = 1;
+ sock_set_flag(sk, SOCK_NO_LARGESEND);
tp->mss_cache = tp->mss_cache_std;
}
@@ -1653,7 +1654,10 @@ static void DBGUNDO(struct sock *sk, struct tcp_sock *tp, const char *msg)
static void tcp_undo_cwr(struct tcp_sock *tp, int undo)
{
if (tp->prior_ssthresh) {
- tp->snd_cwnd = max(tp->snd_cwnd, tp->snd_ssthresh<<1);
+ if (tcp_is_bic(tp))
+ tp->snd_cwnd = max(tp->snd_cwnd, tp->bictcp.last_max_cwnd);
+ else
+ tp->snd_cwnd = max(tp->snd_cwnd, tp->snd_ssthresh<<1);
if (undo && tp->prior_ssthresh > tp->snd_ssthresh) {
tp->snd_ssthresh = tp->prior_ssthresh;
@@ -3007,7 +3011,7 @@ void tcp_parse_options(struct sk_buff *skb, struct tcp_options_received *opt_rx,
switch(opcode) {
case TCPOPT_MSS:
if(opsize==TCPOLEN_MSS && th->syn && !estab) {
- u16 in_mss = ntohs(*(__u16 *)ptr);
+ u16 in_mss = ntohs(get_unaligned((__u16 *)ptr));
if (in_mss) {
if (opt_rx->user_mss && opt_rx->user_mss < in_mss)
in_mss = opt_rx->user_mss;
@@ -3018,15 +3022,16 @@ void tcp_parse_options(struct sk_buff *skb, struct tcp_options_received *opt_rx,
case TCPOPT_WINDOW:
if(opsize==TCPOLEN_WINDOW && th->syn && !estab)
if (sysctl_tcp_window_scaling) {
+ __u8 snd_wscale = *(__u8 *) ptr;
opt_rx->wscale_ok = 1;
- opt_rx->snd_wscale = *(__u8 *)ptr;
- if(opt_rx->snd_wscale > 14) {
+ if (snd_wscale > 14) {
if(net_ratelimit())
printk(KERN_INFO "tcp_parse_options: Illegal window "
"scaling value %d >14 received.\n",
- opt_rx->snd_wscale);
- opt_rx->snd_wscale = 14;
+ snd_wscale);
+ snd_wscale = 14;
}
+ opt_rx->snd_wscale = snd_wscale;
}
break;
case TCPOPT_TIMESTAMP:
@@ -3034,8 +3039,8 @@ void tcp_parse_options(struct sk_buff *skb, struct tcp_options_received *opt_rx,
if ((estab && opt_rx->tstamp_ok) ||
(!estab && sysctl_tcp_timestamps)) {
opt_rx->saw_tstamp = 1;
- opt_rx->rcv_tsval = ntohl(*(__u32 *)ptr);
- opt_rx->rcv_tsecr = ntohl(*(__u32 *)(ptr+4));
+ opt_rx->rcv_tsval = ntohl(get_unaligned((__u32 *)ptr));
+ opt_rx->rcv_tsecr = ntohl(get_unaligned((__u32 *)(ptr+4)));
}
}
break;
@@ -3935,7 +3940,7 @@ void tcp_cwnd_application_limited(struct sock *sk)
/* When incoming ACK allowed to free some skb from write_queue,
- * we remember this event in flag sk->sk_queue_shrunk and wake up socket
+ * we remember this event in flag SOCK_QUEUE_SHRUNK and wake up socket
* on the exit from tcp input handler.
*
* PROBLEM: sndbuf expansion does not work well with largesend.
@@ -3963,8 +3968,8 @@ static void tcp_new_space(struct sock *sk)
static inline void tcp_check_space(struct sock *sk)
{
- if (sk->sk_queue_shrunk) {
- sk->sk_queue_shrunk = 0;
+ if (sock_flag(sk, SOCK_QUEUE_SHRUNK)) {
+ sock_reset_flag(sk, SOCK_QUEUE_SHRUNK);
if (sk->sk_socket &&
test_bit(SOCK_NOSPACE, &sk->sk_socket->flags))
tcp_new_space(sk);
@@ -4507,7 +4512,7 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
TCP_ECN_rcv_synack(tp, th);
if (tp->ecn_flags&TCP_ECN_OK)
- sk->sk_no_largesend = 1;
+ sock_set_flag(sk, SOCK_NO_LARGESEND);
tp->snd_wl1 = TCP_SKB_CB(skb)->seq;
tcp_ack(sk, skb, FLAG_SLOWPATH);
@@ -4645,7 +4650,7 @@ discard:
TCP_ECN_rcv_syn(tp, th);
if (tp->ecn_flags&TCP_ECN_OK)
- sk->sk_no_largesend = 1;
+ sock_set_flag(sk, SOCK_NO_LARGESEND);
tcp_sync_mss(sk, tp->pmtu_cookie);
tcp_initialize_rcv_mss(sk);
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 37d4ef7b58faa..fa30d1d83d037 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -831,7 +831,6 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
/* OK, now commit destination to socket. */
__sk_dst_set(sk, &rt->u.dst);
tcp_v4_setup_caps(sk, &rt->u.dst);
- tp->ext2_header_len = rt->u.dst.header_len;
if (!tp->write_seq)
tp->write_seq = secure_tcp_sequence_number(inet->saddr,
@@ -941,10 +940,10 @@ static inline void do_pmtu_discovery(struct sock *sk, struct iphdr *iph,
/* Something is about to be wrong... Remember soft error
* for the case, if this connection will not able to recover.
*/
- if (mtu < dst_pmtu(dst) && ip_dont_fragment(sk, dst))
+ if (mtu < dst_mtu(dst) && ip_dont_fragment(sk, dst))
sk->sk_err_soft = EMSGSIZE;
- mtu = dst_pmtu(dst);
+ mtu = dst_mtu(dst);
if (inet->pmtudisc != IP_PMTUDISC_DONT &&
tp->pmtu_cookie > mtu) {
@@ -1578,10 +1577,9 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
newtp->ext_header_len = 0;
if (newinet->opt)
newtp->ext_header_len = newinet->opt->optlen;
- newtp->ext2_header_len = dst->header_len;
newinet->id = newtp->write_seq ^ jiffies;
- tcp_sync_mss(newsk, dst_pmtu(dst));
+ tcp_sync_mss(newsk, dst_mtu(dst));
newtp->advmss = dst_metric(dst, RTAX_ADVMSS);
tcp_initialize_rcv_mss(newsk);
@@ -1868,7 +1866,7 @@ static int tcp_v4_reselect_saddr(struct sock *sk)
/* Query new route. */
err = ip_route_connect(&rt, daddr, 0,
- RT_TOS(inet->tos) | sk->sk_localroute,
+ RT_CONN_FLAGS(sk),
sk->sk_bound_dev_if,
IPPROTO_TCP,
inet->sport, inet->dport, sk);
@@ -1877,7 +1875,6 @@ static int tcp_v4_reselect_saddr(struct sock *sk)
__sk_dst_set(sk, &rt->u.dst);
tcp_v4_setup_caps(sk, &rt->u.dst);
- tcp_sk(sk)->ext2_header_len = rt->u.dst.header_len;
new_saddr = rt->rt_src;
@@ -1937,7 +1934,6 @@ int tcp_v4_rebuild_header(struct sock *sk)
if (!err) {
__sk_dst_set(sk, &rt->u.dst);
tcp_v4_setup_caps(sk, &rt->u.dst);
- tcp_sk(sk)->ext2_header_len = rt->u.dst.header_len;
return 0;
}
@@ -2068,7 +2064,7 @@ static int tcp_v4_init_sock(struct sock *sk)
sk->sk_state = TCP_CLOSE;
sk->sk_write_space = sk_stream_write_space;
- sk->sk_use_write_queue = 1;
+ sock_set_flag(sk, SOCK_USE_WRITE_QUEUE);
tp->af_specific = &ipv4_specific;
@@ -2663,4 +2659,5 @@ EXPORT_SYMBOL(tcp_proc_unregister);
EXPORT_SYMBOL(sysctl_local_port_range);
EXPORT_SYMBOL(sysctl_max_syn_backlog);
EXPORT_SYMBOL(sysctl_tcp_low_latency);
+EXPORT_SYMBOL(sysctl_tcp_tw_reuse);
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
index 1e2265c086bab..2faf1a9c3eba2 100644
--- a/net/ipv4/tcp_minisocks.c
+++ b/net/ipv4/tcp_minisocks.c
@@ -841,7 +841,7 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct open_request *req,
newtp->rx_opt.mss_clamp = req->mss;
TCP_ECN_openreq_child(newtp, req);
if (newtp->ecn_flags&TCP_ECN_OK)
- newsk->sk_no_largesend = 1;
+ sock_set_flag(newsk, SOCK_NO_LARGESEND);
tcp_ca_init(newtp);
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index a29ac27636008..13c14cb6dee45 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -400,6 +400,7 @@ static void tcp_queue_skb(struct sock *sk, struct sk_buff *skb)
/* Advance write_seq and place onto the write_queue. */
tp->write_seq = TCP_SKB_CB(skb)->end_seq;
+ skb_header_release(skb);
__skb_queue_tail(&sk->sk_write_queue, skb);
sk_charge_skb(sk, skb);
@@ -592,9 +593,9 @@ int tcp_trim_head(struct sock *sk, struct sk_buff *skb, u32 len)
skb->ip_summed = CHECKSUM_HW;
skb->truesize -= len;
- sk->sk_queue_shrunk = 1;
sk->sk_wmem_queued -= len;
sk->sk_forward_alloc += len;
+ sock_set_flag(sk, SOCK_QUEUE_SHRUNK);
/* Any change of skb->len requires recalculation of tso
* factor and mss.
@@ -631,12 +632,8 @@ int tcp_trim_head(struct sock *sk, struct sk_buff *skb, u32 len)
unsigned int tcp_sync_mss(struct sock *sk, u32 pmtu)
{
struct tcp_sock *tp = tcp_sk(sk);
- struct dst_entry *dst = __sk_dst_get(sk);
int mss_now;
- if (dst && dst->ops->get_mss)
- pmtu = dst->ops->get_mss(dst, pmtu);
-
/* Calculate base mss without TCP options:
It is MMS_S - sizeof(tcphdr) of rfc1122
*/
@@ -647,7 +644,7 @@ unsigned int tcp_sync_mss(struct sock *sk, u32 pmtu)
mss_now = tp->rx_opt.mss_clamp;
/* Now subtract optional transport overhead */
- mss_now -= tp->ext_header_len + tp->ext2_header_len;
+ mss_now -= tp->ext_header_len;
/* Then reserve room for full set of TCP options and 8 bytes of data */
if (mss_now < 48)
@@ -683,9 +680,8 @@ unsigned int tcp_current_mss(struct sock *sk, int large)
mss_now = tp->mss_cache_std;
if (dst) {
- u32 mtu = dst_pmtu(dst);
- if (mtu != tp->pmtu_cookie ||
- tp->ext2_header_len != dst->header_len)
+ u32 mtu = dst_mtu(dst);
+ if (mtu != tp->pmtu_cookie)
mss_now = tcp_sync_mss(sk, mtu);
}
@@ -697,8 +693,7 @@ unsigned int tcp_current_mss(struct sock *sk, int large)
unsigned int large_mss, factor, limit;
large_mss = 65535 - tp->af_specific->net_header_len -
- tp->ext_header_len - tp->ext2_header_len -
- tp->tcp_header_len;
+ tp->ext_header_len - tp->tcp_header_len;
if (tp->max_window && large_mss > (tp->max_window>>1))
large_mss = max((tp->max_window>>1),
@@ -1045,7 +1040,7 @@ int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
if (sk->sk_route_caps & NETIF_F_TSO) {
sk->sk_route_caps &= ~NETIF_F_TSO;
- sk->sk_no_largesend = 1;
+ sock_set_flag(sk, SOCK_NO_LARGESEND);
tp->mss_cache = tp->mss_cache_std;
}
@@ -1340,6 +1335,7 @@ int tcp_send_synack(struct sock *sk)
if (nskb == NULL)
return -ENOMEM;
__skb_unlink(skb, &sk->sk_write_queue);
+ skb_header_release(nskb);
__skb_queue_head(&sk->sk_write_queue, nskb);
sk_stream_free_skb(sk, skb);
sk_charge_skb(sk, nskb);
@@ -1431,6 +1427,7 @@ static inline void tcp_connect_init(struct sock *sk)
{
struct dst_entry *dst = __sk_dst_get(sk);
struct tcp_sock *tp = tcp_sk(sk);
+ __u8 rcv_wscale;
/* We'll fix this up when we get a response from the other end.
* See tcp_input.c:tcp_rcv_state_process case TCP_SYN_SENT.
@@ -1442,7 +1439,7 @@ static inline void tcp_connect_init(struct sock *sk)
if (tp->rx_opt.user_mss)
tp->rx_opt.mss_clamp = tp->rx_opt.user_mss;
tp->max_window = 0;
- tcp_sync_mss(sk, dst_pmtu(dst));
+ tcp_sync_mss(sk, dst_mtu(dst));
if (!tp->window_clamp)
tp->window_clamp = dst_metric(dst, RTAX_WINDOW);
@@ -1455,8 +1452,9 @@ static inline void tcp_connect_init(struct sock *sk)
&tp->rcv_wnd,
&tp->window_clamp,
sysctl_tcp_window_scaling,
- &tp->rx_opt.rcv_wscale);
+ &rcv_wscale);
+ tp->rx_opt.rcv_wscale = rcv_wscale;
tp->rcv_ssthresh = tp->rcv_wnd;
sk->sk_err = 0;
@@ -1506,6 +1504,7 @@ int tcp_connect(struct sock *sk)
/* Send it off. */
TCP_SKB_CB(buff)->when = tcp_time_stamp;
tp->retrans_stamp = TCP_SKB_CB(buff)->when;
+ skb_header_release(buff);
__skb_queue_tail(&sk->sk_write_queue, buff);
sk_charge_skb(sk, buff);
tp->packets_out += tcp_skb_pcount(buff);
@@ -1672,7 +1671,7 @@ int tcp_write_wakeup(struct sock *sk)
/* SWS override triggered forced fragmentation.
* Disable TSO, the connection is too sick. */
if (sk->sk_route_caps & NETIF_F_TSO) {
- sk->sk_no_largesend = 1;
+ sock_set_flag(sk, SOCK_NO_LARGESEND);
sk->sk_route_caps &= ~NETIF_F_TSO;
tp->mss_cache = tp->mss_cache_std;
}
diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c
index 84844eeeb654f..85b279f1e935b 100644
--- a/net/ipv4/tcp_timer.c
+++ b/net/ipv4/tcp_timer.c
@@ -38,6 +38,7 @@ static void tcp_keepalive_timer (unsigned long data);
#ifdef TCP_DEBUG
const char tcp_timer_bug_msg[] = KERN_DEBUG "tcpbug: unknown timer value\n";
+EXPORT_SYMBOL(tcp_timer_bug_msg);
#endif
/*
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 12cd0e690cb02..eac0bd84d7a67 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -574,7 +574,8 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
connected = 0;
}
tos = RT_TOS(inet->tos);
- if (sk->sk_localroute || (msg->msg_flags & MSG_DONTROUTE) ||
+ if (sock_flag(sk, SOCK_LOCALROUTE) ||
+ (msg->msg_flags & MSG_DONTROUTE) ||
(ipc.opt && ipc.opt->is_strictroute)) {
tos |= RTO_ONLINK;
connected = 0;
diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c
index 3c70b08f908c0..af2392ae57696 100644
--- a/net/ipv4/xfrm4_output.c
+++ b/net/ipv4/xfrm4_output.c
@@ -58,7 +58,7 @@ static void xfrm4_encap(struct sk_buff *skb)
if (!top_iph->frag_off)
__ip_select_ident(top_iph, dst, 0);
- top_iph->ttl = dst_path_metric(dst, RTAX_HOPLIMIT);
+ top_iph->ttl = dst_metric(dst->child, RTAX_HOPLIMIT);
top_iph->saddr = x->props.saddr.a4;
top_iph->daddr = x->id.daddr.a4;
@@ -78,11 +78,11 @@ static int xfrm4_tunnel_check_size(struct sk_buff *skb)
IPCB(skb)->flags |= IPSKB_XFRM_TUNNEL_SIZE;
- if (!(iph->frag_off & htons(IP_DF)))
+ if (!(iph->frag_off & htons(IP_DF)) || skb->local_df)
goto out;
dst = skb->dst;
- mtu = dst_pmtu(dst) - dst->header_len - dst->trailer_len;
+ mtu = dst_mtu(dst);
if (skb->len > mtu) {
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu));
ret = -EMSGSIZE;
@@ -103,20 +103,20 @@ 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;
-
if (x->props.mode) {
err = xfrm4_tunnel_check_size(skb);
if (err)
- goto error;
+ goto error_nolock;
}
+ spin_lock_bh(&x->lock);
+ err = xfrm_state_check(x, skb);
+ if (err)
+ goto error;
+
xfrm4_encap(skb);
- err = x->type->output(skb);
+ err = x->type->output(x, skb);
if (err)
goto error;
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
index 012ef304ce63c..7fe2afd2e6695 100644
--- a/net/ipv4/xfrm4_policy.c
+++ b/net/ipv4/xfrm4_policy.c
@@ -22,26 +22,6 @@ static int xfrm4_dst_lookup(struct xfrm_dst **dst, struct flowi *fl)
return __ip_route_output_key((struct rtable**)dst, fl);
}
-/* Check that the bundle accepts the flow and its components are
- * still valid.
- */
-
-static int __xfrm4_bundle_ok(struct xfrm_dst *xdst, struct flowi *fl)
-{
- do {
- if (xdst->u.dst.ops != &xfrm4_dst_ops)
- return 1;
-
- if (!xfrm_selector_match(&xdst->u.dst.xfrm->sel, fl, AF_INET))
- return 0;
- if (xdst->u.dst.xfrm->km.state != XFRM_STATE_VALID ||
- xdst->u.dst.path->obsolete > 0)
- return 0;
- xdst = (struct xfrm_dst*)xdst->u.dst.child;
- } while (xdst);
- return 0;
-}
-
static struct dst_entry *
__xfrm4_find_bundle(struct flowi *fl, struct xfrm_policy *policy)
{
@@ -53,7 +33,7 @@ __xfrm4_find_bundle(struct flowi *fl, struct xfrm_policy *policy)
if (xdst->u.rt.fl.oif == fl->oif && /*XXX*/
xdst->u.rt.fl.fl4_dst == fl->fl4_dst &&
xdst->u.rt.fl.fl4_src == fl->fl4_src &&
- __xfrm4_bundle_ok(xdst, fl)) {
+ xfrm_bundle_ok(xdst, fl, AF_INET)) {
dst_clone(dst);
break;
}
@@ -75,18 +55,30 @@ __xfrm4_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int
struct rtable *rt = rt0;
u32 remote = fl->fl4_dst;
u32 local = fl->fl4_src;
+ struct flowi fl_tunnel = {
+ .nl_u = {
+ .ip4_u = {
+ .saddr = local,
+ .daddr = remote
+ }
+ }
+ };
int i;
int err;
int header_len = 0;
int trailer_len = 0;
dst = dst_prev = NULL;
+ dst_hold(&rt->u.dst);
for (i = 0; i < nx; i++) {
struct dst_entry *dst1 = dst_alloc(&xfrm4_dst_ops);
+ struct xfrm_dst *xdst;
+ int tunnel = 0;
if (unlikely(dst1 == NULL)) {
err = -ENOBUFS;
+ dst_release(&rt->u.dst);
goto error;
}
@@ -97,30 +89,40 @@ __xfrm4_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int
dst1->flags |= DST_NOHASH;
dst_clone(dst1);
}
+
+ xdst = (struct xfrm_dst *)dst1;
+ xdst->route = &rt->u.dst;
+
+ dst1->next = dst_prev;
dst_prev = dst1;
if (xfrm[i]->props.mode) {
remote = xfrm[i]->id.daddr.a4;
local = xfrm[i]->props.saddr.a4;
+ tunnel = 1;
}
header_len += xfrm[i]->props.header_len;
trailer_len += xfrm[i]->props.trailer_len;
- }
- if (remote != fl->fl4_dst) {
- struct flowi fl_tunnel = { .nl_u = { .ip4_u =
- { .daddr = remote,
- .saddr = local }
- }
- };
- err = xfrm_dst_lookup((struct xfrm_dst**)&rt, &fl_tunnel, AF_INET);
- if (err)
- goto error;
- } else {
- dst_hold(&rt->u.dst);
+ if (tunnel) {
+ fl_tunnel.fl4_src = local;
+ fl_tunnel.fl4_dst = remote;
+ err = xfrm_dst_lookup((struct xfrm_dst **)&rt,
+ &fl_tunnel, AF_INET);
+ if (err)
+ goto error;
+ } else
+ dst_hold(&rt->u.dst);
}
+
dst_prev->child = &rt->u.dst;
+ dst->path = &rt->u.dst;
+
+ *dst_p = dst;
+ dst = dst_prev;
+
+ dst_prev = *dst_p;
i = 0;
- for (dst_prev = dst; dst_prev != &rt->u.dst; dst_prev = dst_prev->child) {
+ for (; dst_prev != &rt->u.dst; dst_prev = dst_prev->child) {
struct xfrm_dst *x = (struct xfrm_dst*)dst_prev;
x->u.rt.fl = *fl;
@@ -133,8 +135,7 @@ __xfrm4_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int
dst_prev->lastuse = jiffies;
dst_prev->header_len = header_len;
dst_prev->trailer_len = trailer_len;
- memcpy(&dst_prev->metrics, &rt->u.dst.metrics, sizeof(dst_prev->metrics));
- dst_prev->path = &rt->u.dst;
+ memcpy(&dst_prev->metrics, &x->route->metrics, sizeof(dst_prev->metrics));
/* Copy neighbout for reachability confirmation */
dst_prev->neighbour = neigh_clone(rt->u.dst.neighbour);
@@ -154,7 +155,8 @@ __xfrm4_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int
header_len -= x->u.dst.xfrm->props.header_len;
trailer_len -= x->u.dst.xfrm->props.trailer_len;
}
- *dst_p = dst;
+
+ xfrm_init_pmtu(dst);
return 0;
error:
@@ -235,10 +237,8 @@ static inline int xfrm4_garbage_collect(void)
static void xfrm4_update_pmtu(struct dst_entry *dst, u32 mtu)
{
- struct dst_entry *path = dst->path;
-
- if (mtu < 68 + dst->header_len)
- return;
+ struct xfrm_dst *xdst = (struct xfrm_dst *)dst;
+ struct dst_entry *path = xdst->route;
path->ops->update_pmtu(path, mtu);
}
diff --git a/net/ipv4/xfrm4_state.c b/net/ipv4/xfrm4_state.c
index b28a3881378ae..223a2e83853f9 100644
--- a/net/ipv4/xfrm4_state.c
+++ b/net/ipv4/xfrm4_state.c
@@ -20,9 +20,9 @@ __xfrm4_init_tempsel(struct xfrm_state *x, struct flowi *fl,
{
x->sel.daddr.a4 = fl->fl4_dst;
x->sel.saddr.a4 = fl->fl4_src;
- x->sel.dport = fl->fl_ip_dport;
+ x->sel.dport = xfrm_flowi_dport(fl);
x->sel.dport_mask = ~0;
- x->sel.sport = fl->fl_ip_sport;
+ x->sel.sport = xfrm_flowi_sport(fl);
x->sel.sport_mask = ~0;
x->sel.prefixlen_d = 32;
x->sel.prefixlen_s = 32;
diff --git a/net/ipv4/xfrm4_tunnel.c b/net/ipv4/xfrm4_tunnel.c
index dcc04644cceca..413191f585f6a 100644
--- a/net/ipv4/xfrm4_tunnel.c
+++ b/net/ipv4/xfrm4_tunnel.c
@@ -9,7 +9,7 @@
#include <net/ip.h>
#include <net/protocol.h>
-static int ipip_output(struct sk_buff *skb)
+static int ipip_output(struct xfrm_state *x, struct sk_buff *skb)
{
struct iphdr *iph;
diff --git a/net/ipv6/README b/net/ipv6/README
deleted file mode 100644
index a3f3f575a5514..0000000000000
--- a/net/ipv6/README
+++ /dev/null
@@ -1,8 +0,0 @@
-To join in the work on Linux IPv6 send mail to:
-
- majordomo@oss.sgi.com
-
-and in the body of the message include:
-
-subscribe netdev
-
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index f4eeb8629a0e6..5ffde14ddc095 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -308,7 +308,7 @@ void in6_dev_finish_destroy(struct inet6_dev *idev)
printk("Freeing alive inet6 device %p\n", idev);
return;
}
- snmp6_unregister_dev(idev);
+ snmp6_free_dev(idev);
kfree(idev);
}
@@ -339,6 +339,16 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev)
/* We refer to the device */
dev_hold(dev);
+ if (snmp6_alloc_dev(ndev) < 0) {
+ ADBG((KERN_WARNING
+ "%s(): cannot allocate memory for statistics; dev=%s.\n",
+ __FUNCTION__, dev->name));
+ neigh_parms_release(&nd_tbl, ndev->nd_parms);
+ ndev->dead = 1;
+ in6_dev_finish_destroy(ndev);
+ return NULL;
+ }
+
if (snmp6_register_dev(ndev) < 0) {
ADBG((KERN_WARNING
"%s(): cannot create /proc/net/dev_snmp6/%s\n",
@@ -381,7 +391,9 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev)
ndev->tstamp = jiffies;
#ifdef CONFIG_SYSCTL
neigh_sysctl_register(dev, ndev->nd_parms, NET_IPV6,
- NET_IPV6_NEIGH, "ipv6", &ndisc_ifinfo_sysctl_change);
+ NET_IPV6_NEIGH, "ipv6",
+ &ndisc_ifinfo_sysctl_change,
+ NULL);
addrconf_sysctl_register(ndev, &ndev->cnf);
#endif
}
@@ -579,6 +591,8 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp)
struct inet6_ifaddr *ifa, **ifap;
struct inet6_dev *idev = ifp->idev;
int hash;
+ int deleted = 0, onlink = 0;
+ unsigned long expires = jiffies;
hash = ipv6_addr_hash(&ifp->addr);
@@ -621,7 +635,31 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp)
*ifap = ifa->if_next;
__in6_ifa_put(ifp);
ifa->if_next = NULL;
- break;
+ if (!(ifp->flags & IFA_F_PERMANENT) || onlink > 0)
+ break;
+ deleted = 1;
+ } else if (ifp->flags & IFA_F_PERMANENT) {
+ if (ipv6_prefix_equal(&ifa->addr, &ifp->addr,
+ ifp->prefix_len)) {
+ if (ifa->flags & IFA_F_PERMANENT) {
+ onlink = 1;
+ if (deleted)
+ break;
+ } else {
+ unsigned long lifetime;
+
+ if (!onlink)
+ onlink = -1;
+
+ spin_lock(&ifa->lock);
+ lifetime = min_t(unsigned long,
+ ifa->valid_lft, 0x7fffffffUL/HZ);
+ if (time_before(expires,
+ ifa->tstamp + lifetime * HZ))
+ expires = ifa->tstamp + lifetime * HZ;
+ spin_unlock(&ifa->lock);
+ }
+ }
}
}
write_unlock_bh(&idev->lock);
@@ -632,6 +670,40 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp)
addrconf_del_timer(ifp);
+ /*
+ * Purge or update corresponding prefix
+ *
+ * 1) we don't purge prefix here if address was not permanent.
+ * prefix is managed by its own lifetime.
+ * 2) if there're no addresses, delete prefix.
+ * 3) if there're still other permanent address(es),
+ * corresponding prefix is still permanent.
+ * 4) otherwise, update prefix lifetime to the
+ * longest valid lifetime among the corresponding
+ * addresses on the device.
+ * Note: subsequent RA will update lifetime.
+ *
+ * --yoshfuji
+ */
+ if ((ifp->flags & IFA_F_PERMANENT) && onlink < 1) {
+ struct in6_addr prefix;
+ struct rt6_info *rt;
+
+ ipv6_addr_prefix(&prefix, &ifp->addr, ifp->prefix_len);
+ rt = rt6_lookup(&prefix, NULL, ifp->idev->dev->ifindex, 1);
+
+ if (rt && ((rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0)) {
+ if (onlink == 0) {
+ ip6_del_rt(rt, NULL, NULL);
+ rt = NULL;
+ } else if (!(rt->rt6i_flags & RTF_EXPIRES)) {
+ rt->rt6i_expires = expires;
+ rt->rt6i_flags |= RTF_EXPIRES;
+ }
+ }
+ dst_release(&rt->u.dst);
+ }
+
in6_ifa_put(ifp);
}
@@ -870,7 +942,7 @@ out:
int ipv6_get_saddr(struct dst_entry *dst,
struct in6_addr *daddr, struct in6_addr *saddr)
{
- return ipv6_dev_get_saddr(dst ? dst->dev : NULL, daddr, saddr);
+ return ipv6_dev_get_saddr(dst ? ((struct rt6_info *)dst)->rt6i_idev->dev : NULL, daddr, saddr);
}
@@ -1972,7 +2044,10 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
if (idev) {
addrconf_sysctl_unregister(&idev->cnf);
neigh_sysctl_unregister(idev->nd_parms);
- neigh_sysctl_register(dev, idev->nd_parms, NET_IPV6, NET_IPV6_NEIGH, "ipv6", &ndisc_ifinfo_sysctl_change);
+ neigh_sysctl_register(dev, idev->nd_parms,
+ NET_IPV6, NET_IPV6_NEIGH, "ipv6",
+ &ndisc_ifinfo_sysctl_change,
+ NULL);
addrconf_sysctl_register(idev, &idev->cnf);
}
#endif
@@ -1998,6 +2073,9 @@ static int addrconf_ifdown(struct net_device *dev, int how)
ASSERT_RTNL();
+ if (dev == &loopback_dev && how == 1)
+ how = 0;
+
rt6_ifdown(dev);
neigh_ifdown(&nd_tbl, dev);
@@ -2013,6 +2091,10 @@ static int addrconf_ifdown(struct net_device *dev, int how)
dev->ip6_ptr = NULL;
idev->dead = 1;
write_unlock_bh(&addrconf_lock);
+
+ /* Step 1.5: remove snmp6 entry */
+ snmp6_unregister_dev(idev);
+
}
/* Step 2: clear hash table */
@@ -2841,12 +2923,8 @@ static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev,
r->ifi_family = AF_INET6;
r->ifi_type = dev->type;
r->ifi_index = dev->ifindex;
- r->ifi_flags = dev->flags;
+ r->ifi_flags = dev_get_flags(dev);
r->ifi_change = 0;
- if (!netif_running(dev) || !netif_carrier_ok(dev))
- r->ifi_flags &= ~IFF_RUNNING;
- else
- r->ifi_flags |= IFF_RUNNING;
RTA_PUT(skb, IFLA_IFNAME, strlen(dev->name)+1, dev->name);
@@ -3133,7 +3211,7 @@ static int addrconf_sysctl_forward_strategy(ctl_table *table,
static struct addrconf_sysctl_table
{
struct ctl_table_header *sysctl_header;
- ctl_table addrconf_vars[18];
+ ctl_table addrconf_vars[__NET_IPV6_MAX];
ctl_table addrconf_dev[2];
ctl_table addrconf_conf_dir[2];
ctl_table addrconf_proto_dir[2];
@@ -3424,8 +3502,10 @@ int unregister_inet6addr_notifier(struct notifier_block *nb)
* Init / cleanup code
*/
-void __init addrconf_init(void)
+int __init addrconf_init(void)
{
+ int err = 0;
+
/* The addrconf netdev notifier requires that loopback_dev
* has it's ipv6 private information allocated and setup
* before it can bring up and give link-local addresses
@@ -3439,15 +3519,17 @@ void __init addrconf_init(void)
* first, then loopback_dev, which cases all the non-loopback_dev
* devices to fail to get a link-local address.
*
- * So, as a temporary fix, register loopback_dev first by hand.
+ * So, as a temporary fix, allocate the ipv6 structure for
+ * loopback_dev first by hand.
* Longer term, all of the dependencies ipv6 has upon the loopback
* device and it being up should be removed.
*/
rtnl_lock();
- addrconf_notify(&ipv6_dev_notf, NETDEV_REGISTER, &loopback_dev);
- if (loopback_dev.flags & IFF_UP)
- addrconf_notify(&ipv6_dev_notf, NETDEV_UP, &loopback_dev);
+ if (!ipv6_add_dev(&loopback_dev))
+ err = -ENOMEM;
rtnl_unlock();
+ if (err)
+ return err;
register_netdevice_notifier(&ipv6_dev_notf);
@@ -3465,6 +3547,8 @@ void __init addrconf_init(void)
register_sysctl_table(addrconf_sysctl.addrconf_root_dir, 0);
addrconf_sysctl_register(NULL, &ipv6_devconf_dflt);
#endif
+
+ return 0;
}
void __exit addrconf_cleanup(void)
@@ -3493,6 +3577,7 @@ void __exit addrconf_cleanup(void)
continue;
addrconf_ifdown(dev, 1);
}
+ addrconf_ifdown(&loopback_dev, 2);
/*
* Check hash table.
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index d5d1d83416fe8..2f1e7b439e2f4 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -652,8 +652,10 @@ snmp6_mib_free(void *ptr[2])
{
if (ptr == NULL)
return;
- free_percpu(ptr[0]);
- free_percpu(ptr[1]);
+ if (ptr[0])
+ free_percpu(ptr[0]);
+ if (ptr[1])
+ free_percpu(ptr[1]);
ptr[0] = ptr[1] = NULL;
}
@@ -709,20 +711,17 @@ static int __init inet6_init(void)
}
err = sk_alloc_slab(&tcpv6_prot, "tcpv6_sock");
- if (err) {
- sk_alloc_slab_error(&tcpv6_prot);
+ if (err)
goto out;
- }
+
err = sk_alloc_slab(&udpv6_prot, "udpv6_sock");
- if (err) {
- sk_alloc_slab_error(&udpv6_prot);
+ if (err)
goto out_tcp_free_slab;
- }
+
err = sk_alloc_slab(&rawv6_prot, "rawv6_sock");
- if (err) {
- sk_alloc_slab_error(&rawv6_prot);
+ if (err)
goto out_udp_free_slab;
- }
+
/* Register the socket-side information for inet6_create. */
for(r = &inetsw6[0]; r < &inetsw6[SOCK_MAX]; ++r)
@@ -782,7 +781,9 @@ static int __init inet6_init(void)
ipv6_packet_init();
ip6_route_init();
ip6_flowlabel_init();
- addrconf_init();
+ err = addrconf_init();
+ if (err)
+ goto addrconf_fail;
sit_init();
/* Init v6 extension headers. */
@@ -798,7 +799,12 @@ static int __init inet6_init(void)
out:
return err;
+addrconf_fail:
+ ip6_flowlabel_cleanup();
+ ip6_route_cleanup();
+ ipv6_packet_cleanup();
#ifdef CONFIG_PROC_FS
+ if6_proc_exit();
proc_if6_fail:
ac6_proc_exit();
proc_anycast6_fail:
@@ -810,8 +816,8 @@ proc_udp6_fail:
proc_tcp6_fail:
raw6_proc_exit();
proc_raw6_fail:
- igmp6_cleanup();
#endif
+ igmp6_cleanup();
igmp_fail:
ndisc_cleanup();
ndisc_fail:
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c
index ed6b36eafc36d..e3ecf626cbf79 100644
--- a/net/ipv6/ah6.c
+++ b/net/ipv6/ah6.c
@@ -154,12 +154,10 @@ static int ipv6_clear_mutable_options(struct ipv6hdr *iph, int len)
return 0;
}
-static int ah6_output(struct sk_buff *skb)
+static int ah6_output(struct xfrm_state *x, struct sk_buff *skb)
{
int err;
int extlen;
- struct dst_entry *dst = skb->dst;
- struct xfrm_state *x = dst->xfrm;
struct ipv6hdr *top_iph;
struct ip_auth_hdr *ah;
struct ah_data *ahp;
diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c
index 410a1ab9c698b..5d22ca3cca2eb 100644
--- a/net/ipv6/anycast.c
+++ b/net/ipv6/anycast.c
@@ -48,32 +48,6 @@ static int ipv6_dev_ac_dec(struct net_device *dev, struct in6_addr *addr);
/* Big ac list lock for all the sockets */
static DEFINE_RWLOCK(ipv6_sk_ac_lock);
-/* XXX ip6_addr_match() and ip6_onlink() really belong in net/core.c */
-
-static int
-ip6_addr_match(struct in6_addr *addr1, struct in6_addr *addr2, int prefix)
-{
- __u32 mask;
- int i;
-
- if (prefix > 128 || prefix < 0)
- return 0;
- if (prefix == 0)
- return 1;
- for (i=0; i<4; ++i) {
- if (prefix >= 32)
- mask = ~0;
- else
- mask = htonl(~0 << (32 - prefix));
- if ((addr1->s6_addr32[i] ^ addr2->s6_addr32[i]) & mask)
- return 0;
- prefix -= 32;
- if (prefix <= 0)
- break;
- }
- return 1;
-}
-
static int
ip6_onlink(struct in6_addr *addr, struct net_device *dev)
{
@@ -87,8 +61,8 @@ ip6_onlink(struct in6_addr *addr, struct net_device *dev)
if (idev) {
read_lock_bh(&idev->lock);
for (ifa=idev->addr_list; ifa; ifa=ifa->if_next) {
- onlink = ip6_addr_match(addr, &ifa->addr,
- ifa->prefix_len);
+ onlink = ipv6_prefix_equal(addr, &ifa->addr,
+ ifa->prefix_len);
if (onlink)
break;
}
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index dd5dc189d5413..be7095d6babef 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -37,12 +37,10 @@
#include <net/ipv6.h>
#include <linux/icmpv6.h>
-static int esp6_output(struct sk_buff *skb)
+static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)
{
int err;
int hdr_len;
- struct dst_entry *dst = skb->dst;
- struct xfrm_state *x = dst->xfrm;
struct ipv6hdr *top_iph;
struct ipv6_esp_hdr *esph;
struct crypto_tfm *tfm;
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index 18637221a7506..87b9082ceab27 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -381,6 +381,8 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info,
hlimit = np->hop_limit;
if (hlimit < 0)
hlimit = dst_metric(dst, RTAX_HOPLIMIT);
+ if (hlimit < 0)
+ hlimit = ipv6_get_hoplimit(dst->dev);
msg.skb = skb;
msg.offset = skb->nh.raw - skb->data;
@@ -467,6 +469,8 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
hlimit = np->hop_limit;
if (hlimit < 0)
hlimit = dst_metric(dst, RTAX_HOPLIMIT);
+ if (hlimit < 0)
+ hlimit = ipv6_get_hoplimit(dst->dev);
idev = in6_dev_get(skb->dev);
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index b131090deb4c7..405740b75abb7 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -117,36 +117,6 @@ static __inline__ u32 fib6_new_sernum(void)
*/
/*
- * compare "prefix length" bits of an address
- */
-
-static __inline__ int addr_match(void *token1, void *token2, int prefixlen)
-{
- __u32 *a1 = token1;
- __u32 *a2 = token2;
- int pdw;
- int pbi;
-
- pdw = prefixlen >> 5; /* num of whole __u32 in prefix */
- pbi = prefixlen & 0x1f; /* num of bits in incomplete u32 in prefix */
-
- if (pdw)
- if (memcmp(a1, a2, pdw << 2))
- return 0;
-
- if (pbi) {
- __u32 mask;
-
- mask = htonl((0xffffffff) << (32 - pbi));
-
- if ((a1[pdw] ^ a2[pdw]) & mask)
- return 0;
- }
-
- return 1;
-}
-
-/*
* test bit
*/
@@ -261,7 +231,7 @@ static struct fib6_node * fib6_add_1(struct fib6_node *root, void *addr,
* Prefix match
*/
if (plen < fn->fn_bit ||
- !addr_match(&key->addr, addr, fn->fn_bit))
+ !ipv6_prefix_equal(&key->addr, addr, fn->fn_bit))
goto insert_above;
/*
@@ -667,7 +637,7 @@ static struct fib6_node * fib6_lookup_1(struct fib6_node *root,
key = (struct rt6key *) ((u8 *) fn->leaf +
args->offset);
- if (addr_match(&key->addr, args->addr, key->plen))
+ if (ipv6_prefix_equal(&key->addr, args->addr, key->plen))
return fn;
}
@@ -718,7 +688,7 @@ static struct fib6_node * fib6_locate_1(struct fib6_node *root,
* Prefix match
*/
if (plen < fn->fn_bit ||
- !addr_match(&key->addr, addr, fn->fn_bit))
+ !ipv6_prefix_equal(&key->addr, addr, fn->fn_bit))
return NULL;
if (plen == fn->fn_bit)
@@ -1211,7 +1181,7 @@ void fib6_run_gc(unsigned long dummy)
{
if (dummy != ~0UL) {
spin_lock_bh(&fib6_gc_lock);
- gc_args.timeout = (int)dummy;
+ gc_args.timeout = dummy ? (int)dummy : ip6_rt_gc_interval;
} else {
local_bh_disable();
if (!spin_trylock(&fib6_gc_lock)) {
@@ -1248,7 +1218,7 @@ void __init fib6_init(void)
panic("cannot create fib6_nodes cache");
}
-void __exit fib6_gc_cleanup(void)
+void fib6_gc_cleanup(void)
{
del_timer(&ip6_fib_timer);
kmem_cache_destroy(fib6_node_kmem);
diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c
index a3340f2b47144..a93f6dc51979f 100644
--- a/net/ipv6/ip6_flowlabel.c
+++ b/net/ipv6/ip6_flowlabel.c
@@ -87,7 +87,7 @@ static struct ip6_flowlabel * fl_lookup(u32 label)
static void fl_free(struct ip6_flowlabel *fl)
{
- if (fl->opt)
+ if (fl)
kfree(fl->opt);
kfree(fl);
}
@@ -351,8 +351,7 @@ fl_create(struct in6_flowlabel_req *freq, char __user *optval, int optlen, int *
return fl;
done:
- if (fl)
- fl_free(fl);
+ fl_free(fl);
*err_p = err;
return NULL;
}
@@ -551,10 +550,8 @@ release:
}
done:
- if (fl)
- fl_free(fl);
- if (sfl1)
- kfree(sfl1);
+ fl_free(fl);
+ kfree(sfl1);
return err;
}
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
index 99436a59e4ceb..866f10726c583 100644
--- a/net/ipv6/ip6_input.c
+++ b/net/ipv6/ip6_input.c
@@ -71,10 +71,18 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
goto out;
}
- /* Store incoming device index. When the packet will
- be queued, we cannot refer to skb->dev anymore.
+ /*
+ * Store incoming device index. When the packet will
+ * be queued, we cannot refer to skb->dev anymore.
+ *
+ * BTW, when we send a packet for our own local address on a
+ * non-loopback interface (e.g. ethX), it is being delivered
+ * via the loopback interface (lo) here; skb->dev = &loopback_dev.
+ * It, however, should be considered as if it is being
+ * arrived via the sending interface (ethX), because of the
+ * nature of scoping architecture. --yoshfuji
*/
- IP6CB(skb)->iif = dev->ifindex;
+ IP6CB(skb)->iif = skb->dst ? ((struct rt6_info *)skb->dst)->rt6i_idev->dev->ifindex : dev->ifindex;
if (skb->len < sizeof(struct ipv6hdr))
goto err;
@@ -95,15 +103,11 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
if (pkt_len || hdr->nexthdr != NEXTHDR_HOP) {
if (pkt_len + sizeof(struct ipv6hdr) > skb->len)
goto truncated;
- if (pkt_len + sizeof(struct ipv6hdr) < skb->len) {
- if (__pskb_trim(skb, pkt_len + sizeof(struct ipv6hdr))){
- IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
- goto drop;
- }
- hdr = skb->nh.ipv6h;
- if (skb->ip_summed == CHECKSUM_HW)
- skb->ip_summed = CHECKSUM_NONE;
+ if (pskb_trim_rcsum(skb, pkt_len + sizeof(struct ipv6hdr))) {
+ IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
+ goto drop;
}
+ hdr = skb->nh.ipv6h;
}
if (hdr->nexthdr == NEXTHDR_HOP) {
@@ -138,7 +142,6 @@ static inline int ip6_input_finish(struct sk_buff *skb)
unsigned int nhoff;
int nexthdr;
u8 hash;
- int cksum_sub = 0;
skb->h.raw = skb->nh.raw + sizeof(struct ipv6hdr);
@@ -173,11 +176,8 @@ resubmit:
if (ipprot->flags & INET6_PROTO_FINAL) {
struct ipv6hdr *hdr;
- if (!cksum_sub && skb->ip_summed == CHECKSUM_HW) {
- skb->csum = csum_sub(skb->csum,
- csum_partial(skb->nh.raw, skb->h.raw-skb->nh.raw, 0));
- cksum_sub++;
- }
+ skb_postpull_rcsum(skb, skb->nh.raw,
+ skb->h.raw - skb->nh.raw);
hdr = skb->nh.ipv6h;
if (ipv6_addr_is_multicast(&hdr->daddr) &&
!ipv6_chk_mcast_addr(skb->dev, &hdr->daddr,
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index fce2a87e9e4a6..49208ba75094a 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -147,7 +147,7 @@ static int ip6_output2(struct sk_buff *skb)
int ip6_output(struct sk_buff *skb)
{
- if (skb->len > dst_pmtu(skb->dst))
+ if (skb->len > dst_mtu(skb->dst) || dst_allfrag(skb->dst))
return ip6_fragment(skb, ip6_output2);
else
return ip6_output2(skb);
@@ -253,6 +253,8 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
hlimit = np->hop_limit;
if (hlimit < 0)
hlimit = dst_metric(dst, RTAX_HOPLIMIT);
+ if (hlimit < 0)
+ hlimit = ipv6_get_hoplimit(dst->dev);
hdr->payload_len = htons(seg_len);
hdr->nexthdr = proto;
@@ -261,7 +263,7 @@ 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);
- mtu = dst_pmtu(dst);
+ mtu = dst_mtu(dst);
if ((skb->len <= mtu) || ipfragok) {
IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS);
return NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, ip6_maybe_reroute);
@@ -395,6 +397,7 @@ int ip6_forward(struct sk_buff *skb)
IP6_INC_STATS(IPSTATS_MIB_INDISCARDS);
goto drop;
}
+ dst = skb->dst;
/* IPv6 specs say nothing about it, but it is clear that we cannot
send redirects to source routed frames.
@@ -426,10 +429,10 @@ int ip6_forward(struct sk_buff *skb)
goto error;
}
- if (skb->len > dst_pmtu(dst)) {
+ if (skb->len > dst_mtu(dst)) {
/* Again, force OUTPUT device used as source address */
skb->dev = dst->dev;
- icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, dst_pmtu(dst), skb->dev);
+ icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, dst_mtu(dst), skb->dev);
IP6_INC_STATS_BH(IPSTATS_MIB_INTOOBIGERRORS);
IP6_INC_STATS_BH(IPSTATS_MIB_FRAGFAILS);
kfree_skb(skb);
@@ -532,7 +535,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
hlen = ip6_find_1stfragopt(skb, &prevhdr);
nexthdr = *prevhdr;
- mtu = dst_pmtu(&rt->u.dst) - hlen - sizeof(struct frag_hdr);
+ mtu = dst_mtu(&rt->u.dst) - hlen - sizeof(struct frag_hdr);
if (skb_shinfo(skb)->frag_list) {
int first_len = skb_pagelen(skb);
@@ -847,7 +850,9 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, int offse
np->cork.rt = rt;
inet->cork.fl = *fl;
np->cork.hop_limit = hlimit;
- inet->cork.fragsize = mtu = dst_pmtu(&rt->u.dst);
+ inet->cork.fragsize = mtu = dst_mtu(rt->u.dst.path);
+ if (dst_allfrag(rt->u.dst.path))
+ inet->cork.flags |= IPCORK_ALLFRAG;
inet->cork.length = 0;
sk->sk_sndmsg_page = NULL;
sk->sk_sndmsg_off = 0;
@@ -899,7 +904,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, int offse
while (length > 0) {
/* Check if the remaining data fits into current packet. */
- copy = mtu - skb->len;
+ copy = (inet->cork.length <= mtu && !(inet->cork.flags & IPCORK_ALLFRAG) ? mtu : maxfraglen) - skb->len;
if (copy < length)
copy = maxfraglen - skb->len;
@@ -924,7 +929,7 @@ alloc_new_skb:
* we know we need more fragment(s).
*/
datalen = length + fraggap;
- if (datalen > mtu - fragheaderlen)
+ if (datalen > (inet->cork.length <= mtu && !(inet->cork.flags & IPCORK_ALLFRAG) ? mtu : maxfraglen) - fragheaderlen)
datalen = maxfraglen - fragheaderlen;
fraglen = datalen + fragheaderlen;
@@ -1158,6 +1163,7 @@ out:
if (np->cork.rt) {
dst_release(&np->cork.rt->u.dst);
np->cork.rt = NULL;
+ inet->cork.flags &= ~IPCORK_ALLFRAG;
}
memset(&inet->cork.fl, 0, sizeof(inet->cork.fl));
return err;
@@ -1185,6 +1191,7 @@ void ip6_flush_pending_frames(struct sock *sk)
if (np->cork.rt) {
dst_release(&np->cork.rt->u.dst);
np->cork.rt = NULL;
+ inet->cork.flags &= ~IPCORK_ALLFRAG;
}
memset(&inet->cork.fl, 0, sizeof(inet->cork.fl));
}
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index ef6245f1474e4..3b1c9fa184ae6 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -94,6 +94,7 @@ static inline struct dst_entry *ip6_tnl_dst_check(struct ip6_tnl *t)
if (dst && dst->obsolete &&
dst->ops->check(dst, t->dst_cookie) == NULL) {
t->dst_cache = NULL;
+ dst_release(dst);
return NULL;
}
@@ -688,14 +689,14 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
t->parms.name);
goto tx_err_dst_release;
}
- mtu = dst_pmtu(dst) - sizeof (*ipv6h);
+ mtu = dst_mtu(dst) - sizeof (*ipv6h);
if (opt) {
max_headroom += 8;
mtu -= 8;
}
if (mtu < IPV6_MIN_MTU)
mtu = IPV6_MIN_MTU;
- if (skb->dst && mtu < dst_pmtu(skb->dst)) {
+ if (skb->dst && mtu < dst_mtu(skb->dst)) {
struct rt6_info *rt = (struct rt6_info *) skb->dst;
rt->rt6i_flags |= RTF_MODIFIED;
rt->u.dst.metrics[RTAX_MTU-1] = mtu;
diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c
index 6604e6f25223c..ecea6cf66055a 100644
--- a/net/ipv6/ipcomp6.c
+++ b/net/ipv6/ipcomp6.c
@@ -139,11 +139,9 @@ error_out:
return err;
}
-static int ipcomp6_output(struct sk_buff *skb)
+static int ipcomp6_output(struct xfrm_state *x, struct sk_buff *skb)
{
int err;
- struct dst_entry *dst = skb->dst;
- struct xfrm_state *x = dst->xfrm;
struct ipv6hdr *top_iph;
int hdr_len;
struct ipv6_comp_hdr *ipch;
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index e2d848ab01b0e..279ab86be6620 100644
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -607,7 +607,7 @@ int ipv6_getsockopt(struct sock *sk, int level, int optname,
lock_sock(sk);
dst = sk_dst_get(sk);
if (dst) {
- val = dst_pmtu(dst) - dst->header_len;
+ val = dst_mtu(dst);
dst_release(dst);
}
release_sock(sk);
@@ -698,7 +698,7 @@ void __init ipv6_packet_init(void)
dev_add_pack(&ipv6_packet_type);
}
-void __exit ipv6_packet_cleanup(void)
+void ipv6_packet_cleanup(void)
{
dev_remove_pack(&ipv6_packet_type);
}
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 0b45f8da29505..7c291f4e9edce 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -156,14 +156,13 @@ struct neigh_table nd_tbl = {
/* ND options */
struct ndisc_options {
- struct nd_opt_hdr *nd_opt_array[7];
- struct nd_opt_hdr *nd_opt_piend;
+ struct nd_opt_hdr *nd_opt_array[__ND_OPT_MAX];
};
#define nd_opts_src_lladdr nd_opt_array[ND_OPT_SOURCE_LL_ADDR]
#define nd_opts_tgt_lladdr nd_opt_array[ND_OPT_TARGET_LL_ADDR]
#define nd_opts_pi nd_opt_array[ND_OPT_PREFIX_INFO]
-#define nd_opts_pi_end nd_opt_piend
+#define nd_opts_pi_end nd_opt_array[__ND_OPT_PREFIX_INFO_END]
#define nd_opts_rh nd_opt_array[ND_OPT_REDIRECT_HDR]
#define nd_opts_mtu nd_opt_array[ND_OPT_MTU]
@@ -183,6 +182,11 @@ static int ndisc_addr_option_pad(unsigned short type)
}
}
+static inline int ndisc_opt_addr_space(struct net_device *dev)
+{
+ return NDISC_OPT_SPACE(dev->addr_len + ndisc_addr_option_pad(dev->type));
+}
+
static u8 *ndisc_fill_addr_option(u8 *opt, int type, void *data, int data_len,
unsigned short addr_type)
{
@@ -267,6 +271,17 @@ static struct ndisc_options *ndisc_parse_options(u8 *opt, int opt_len,
return ndopts;
}
+static inline u8 *ndisc_opt_addr_data(struct nd_opt_hdr *p,
+ struct net_device *dev)
+{
+ u8 *lladdr = (u8 *)(p + 1);
+ int lladdrlen = p->nd_opt_len << 3;
+ int prepad = ndisc_addr_option_pad(dev->type);
+ if (lladdrlen != NDISC_OPT_SPACE(dev->addr_len + prepad))
+ return NULL;
+ return (lladdr + prepad);
+}
+
int ndisc_mc_map(struct in6_addr *addr, char *buf, struct net_device *dev, int dir)
{
switch (dev->type) {
@@ -439,7 +454,7 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
if (inc_opt) {
if (dev->addr_len)
- len += NDISC_OPT_SPACE(dev->addr_len);
+ len += ndisc_opt_addr_space(dev);
else
inc_opt = 0;
}
@@ -532,7 +547,7 @@ void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh,
len = sizeof(struct icmp6hdr) + sizeof(struct in6_addr);
send_llinfo = dev->addr_len && !ipv6_addr_any(saddr);
if (send_llinfo)
- len += NDISC_OPT_SPACE(dev->addr_len);
+ len += ndisc_opt_addr_space(dev);
skb = sock_alloc_send_skb(sk, MAX_HEADER + len + LL_RESERVED_SPACE(dev),
1, &err);
@@ -608,7 +623,7 @@ void ndisc_send_rs(struct net_device *dev, struct in6_addr *saddr,
len = sizeof(struct icmp6hdr);
if (dev->addr_len)
- len += NDISC_OPT_SPACE(dev->addr_len);
+ len += ndisc_opt_addr_space(dev);
skb = sock_alloc_send_skb(sk, MAX_HEADER + len + LL_RESERVED_SPACE(dev),
1, &err);
@@ -704,7 +719,6 @@ static void ndisc_recv_ns(struct sk_buff *skb)
struct in6_addr *saddr = &skb->nh.ipv6h->saddr;
struct in6_addr *daddr = &skb->nh.ipv6h->daddr;
u8 *lladdr = NULL;
- int lladdrlen = 0;
u32 ndoptlen = skb->tail - msg->opt;
struct ndisc_options ndopts;
struct net_device *dev = skb->dev;
@@ -741,10 +755,8 @@ static void ndisc_recv_ns(struct sk_buff *skb)
}
if (ndopts.nd_opts_src_lladdr) {
- lladdr = (u8*)(ndopts.nd_opts_src_lladdr + 1) +
- ndisc_addr_option_pad(dev->type);
- lladdrlen = ndopts.nd_opts_src_lladdr->nd_opt_len << 3;
- if (lladdrlen != NDISC_OPT_SPACE(dev->addr_len)) {
+ lladdr = ndisc_opt_addr_data(ndopts.nd_opts_src_lladdr, dev);
+ if (!lladdr) {
ND_PRINTK2(KERN_WARNING
"ICMPv6 NS: invalid link-layer address length\n");
return;
@@ -867,7 +879,6 @@ static void ndisc_recv_na(struct sk_buff *skb)
struct in6_addr *saddr = &skb->nh.ipv6h->saddr;
struct in6_addr *daddr = &skb->nh.ipv6h->daddr;
u8 *lladdr = NULL;
- int lladdrlen = 0;
u32 ndoptlen = skb->tail - msg->opt;
struct ndisc_options ndopts;
struct net_device *dev = skb->dev;
@@ -899,10 +910,8 @@ static void ndisc_recv_na(struct sk_buff *skb)
return;
}
if (ndopts.nd_opts_tgt_lladdr) {
- lladdr = (u8*)(ndopts.nd_opts_tgt_lladdr + 1) +
- ndisc_addr_option_pad(dev->type);
- lladdrlen = ndopts.nd_opts_tgt_lladdr->nd_opt_len << 3;
- if (lladdrlen != NDISC_OPT_SPACE(dev->addr_len)) {
+ lladdr = ndisc_opt_addr_data(ndopts.nd_opts_tgt_lladdr, dev);
+ if (!lladdr) {
ND_PRINTK2(KERN_WARNING
"ICMPv6 NA: invalid link-layer address length\n");
return;
@@ -963,7 +972,6 @@ static void ndisc_recv_rs(struct sk_buff *skb)
struct in6_addr *saddr = &skb->nh.ipv6h->saddr;
struct ndisc_options ndopts;
u8 *lladdr = NULL;
- int lladdrlen = 0;
if (skb->len < sizeof(*rs_msg))
return;
@@ -994,10 +1002,9 @@ static void ndisc_recv_rs(struct sk_buff *skb)
}
if (ndopts.nd_opts_src_lladdr) {
- lladdr = (u8 *)(ndopts.nd_opts_src_lladdr + 1) +
- ndisc_addr_option_pad(skb->dev->type);
- lladdrlen = ndopts.nd_opts_src_lladdr->nd_opt_len << 3;
- if (lladdrlen != NDISC_OPT_SPACE(skb->dev->addr_len))
+ lladdr = ndisc_opt_addr_data(ndopts.nd_opts_src_lladdr,
+ skb->dev);
+ if (!lladdr)
goto out;
}
@@ -1121,8 +1128,11 @@ static void ndisc_router_discovery(struct sk_buff *skb)
if (rt)
rt->rt6i_expires = jiffies + (HZ * lifetime);
- if (ra_msg->icmph.icmp6_hop_limit)
+ if (ra_msg->icmph.icmp6_hop_limit) {
in6_dev->cnf.hop_limit = ra_msg->icmph.icmp6_hop_limit;
+ if (rt)
+ rt->u.dst.metrics[RTAX_HOPLIMIT-1] = ra_msg->icmph.icmp6_hop_limit;
+ }
/*
* Update Reachable Time and Retrans Timer
@@ -1166,12 +1176,10 @@ static void ndisc_router_discovery(struct sk_buff *skb)
skb->dev, 1);
if (neigh) {
u8 *lladdr = NULL;
- int lladdrlen;
if (ndopts.nd_opts_src_lladdr) {
- lladdr = (u8*)((ndopts.nd_opts_src_lladdr)+1) +
- ndisc_addr_option_pad(skb->dev->type);
- lladdrlen = ndopts.nd_opts_src_lladdr->nd_opt_len << 3;
- if (lladdrlen != NDISC_OPT_SPACE(skb->dev->addr_len)) {
+ lladdr = ndisc_opt_addr_data(ndopts.nd_opts_src_lladdr,
+ skb->dev);
+ if (!lladdr) {
ND_PRINTK2(KERN_WARNING
"ICMPv6 RA: invalid link-layer address length\n");
goto out;
@@ -1236,7 +1244,6 @@ static void ndisc_redirect_rcv(struct sk_buff *skb)
struct ndisc_options ndopts;
int optlen;
u8 *lladdr = NULL;
- int lladdrlen;
if (!(ipv6_addr_type(&skb->nh.ipv6h->saddr) & IPV6_ADDR_LINKLOCAL)) {
ND_PRINTK2(KERN_WARNING
@@ -1291,10 +1298,9 @@ static void ndisc_redirect_rcv(struct sk_buff *skb)
return;
}
if (ndopts.nd_opts_tgt_lladdr) {
- lladdr = (u8*)(ndopts.nd_opts_tgt_lladdr + 1) +
- ndisc_addr_option_pad(skb->dev->type);
- lladdrlen = ndopts.nd_opts_tgt_lladdr->nd_opt_len << 3;
- if (lladdrlen != NDISC_OPT_SPACE(skb->dev->addr_len)) {
+ lladdr = ndisc_opt_addr_data(ndopts.nd_opts_tgt_lladdr,
+ skb->dev);
+ if (!lladdr) {
ND_PRINTK2(KERN_WARNING
"ICMPv6 Redirect: invalid link-layer address length\n");
in6_dev_put(in6_dev);
@@ -1329,6 +1335,7 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
int rd_len;
int err;
int hlen;
+ u8 ha_buf[MAX_ADDR_LEN], *ha = NULL;
dev = skb->dev;
@@ -1341,10 +1348,9 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
ndisc_flow_init(&fl, NDISC_REDIRECT, &saddr_buf, &skb->nh.ipv6h->saddr);
- rt = rt6_lookup(&skb->nh.ipv6h->saddr, NULL, dev->ifindex, 1);
- if (rt == NULL)
+ dst = ip6_route_output(NULL, &fl);
+ if (dst == NULL)
return;
- dst = &rt->u.dst;
err = xfrm_lookup(&dst, &fl, NULL, 0);
if (err) {
@@ -1366,16 +1372,14 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
}
if (dev->addr_len) {
- if (neigh->nud_state&NUD_VALID) {
- len += NDISC_OPT_SPACE(dev->addr_len);
- } else {
- /* If nexthop is not valid, do not redirect!
- We will make it later, when will be sure,
- that it is alive.
- */
- dst_release(dst);
- return;
- }
+ read_lock_bh(&neigh->lock);
+ if (neigh->nud_state & NUD_VALID) {
+ memcpy(ha_buf, neigh->ha, dev->addr_len);
+ read_unlock_bh(&neigh->lock);
+ ha = ha_buf;
+ len += ndisc_opt_addr_space(dev);
+ } else
+ read_unlock_bh(&neigh->lock);
}
rd_len = min_t(unsigned int,
@@ -1420,8 +1424,8 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
* include target_address option
*/
- if (dev->addr_len)
- opt = ndisc_fill_addr_option(opt, ND_OPT_TARGET_LL_ADDR, neigh->ha,
+ if (ha)
+ opt = ndisc_fill_addr_option(opt, ND_OPT_TARGET_LL_ADDR, ha,
dev->addr_len, dev->type);
/*
@@ -1515,11 +1519,11 @@ static int ndisc_netdev_event(struct notifier_block *this, unsigned long event,
switch (event) {
case NETDEV_CHANGEADDR:
neigh_changeaddr(&nd_tbl, dev);
- fib6_run_gc(0);
+ fib6_run_gc(~0UL);
break;
case NETDEV_DOWN:
neigh_ifdown(&nd_tbl, dev);
- fib6_run_gc(0);
+ fib6_run_gc(~0UL);
break;
default:
break;
@@ -1533,18 +1537,106 @@ static struct notifier_block ndisc_netdev_notifier = {
};
#ifdef CONFIG_SYSCTL
+static void ndisc_warn_deprecated_sysctl(struct ctl_table *ctl,
+ const char *func, const char *dev_name)
+{
+ static char warncomm[TASK_COMM_LEN];
+ static int warned;
+ if (strcmp(warncomm, current->comm) && warned < 5) {
+ strcpy(warncomm, current->comm);
+ printk(KERN_WARNING
+ "process `%s' is using deprecated sysctl (%s) "
+ "net.ipv6.neigh.%s.%s; "
+ "Use net.ipv6.neigh.%s.%s_ms "
+ "instead.\n",
+ warncomm, func,
+ dev_name, ctl->procname,
+ dev_name, ctl->procname);
+ warned++;
+ }
+}
+
int ndisc_ifinfo_sysctl_change(struct ctl_table *ctl, int write, struct file * filp, void __user *buffer, size_t *lenp, loff_t *ppos)
{
struct net_device *dev = ctl->extra1;
struct inet6_dev *idev;
+ int ret;
+
+ if (ctl->ctl_name == NET_NEIGH_RETRANS_TIME ||
+ ctl->ctl_name == NET_NEIGH_REACHABLE_TIME)
+ ndisc_warn_deprecated_sysctl(ctl, "syscall", dev ? dev->name : "default");
- if (write && dev && (idev = in6_dev_get(dev)) != NULL) {
+ switch (ctl->ctl_name) {
+ case NET_NEIGH_RETRANS_TIME:
+ ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos);
+ break;
+ case NET_NEIGH_REACHABLE_TIME:
+ ret = proc_dointvec_jiffies(ctl, write,
+ filp, buffer, lenp, ppos);
+ break;
+ case NET_NEIGH_RETRANS_TIME_MS:
+ case NET_NEIGH_REACHABLE_TIME_MS:
+ ret = proc_dointvec_ms_jiffies(ctl, write,
+ filp, buffer, lenp, ppos);
+ break;
+ default:
+ ret = -1;
+ }
+
+ if (write && ret == 0 && dev && (idev = in6_dev_get(dev)) != NULL) {
+ if (ctl->ctl_name == NET_NEIGH_REACHABLE_TIME ||
+ ctl->ctl_name == NET_NEIGH_REACHABLE_TIME_MS)
+ idev->nd_parms->reachable_time = neigh_rand_reach_time(idev->nd_parms->base_reachable_time);
+ idev->tstamp = jiffies;
+ inet6_ifinfo_notify(RTM_NEWLINK, idev);
+ in6_dev_put(idev);
+ }
+ return ret;
+}
+
+static int ndisc_ifinfo_sysctl_strategy(ctl_table *ctl, int __user *name,
+ int nlen, void __user *oldval,
+ size_t __user *oldlenp,
+ void __user *newval, size_t newlen,
+ void **context)
+{
+ struct net_device *dev = ctl->extra1;
+ struct inet6_dev *idev;
+ int ret;
+
+ if (ctl->ctl_name == NET_NEIGH_RETRANS_TIME ||
+ ctl->ctl_name == NET_NEIGH_REACHABLE_TIME)
+ ndisc_warn_deprecated_sysctl(ctl, "procfs", dev ? dev->name : "default");
+
+ switch (ctl->ctl_name) {
+ case NET_NEIGH_REACHABLE_TIME:
+ ret = sysctl_jiffies(ctl, name, nlen,
+ oldval, oldlenp, newval, newlen,
+ context);
+ break;
+ case NET_NEIGH_RETRANS_TIME_MS:
+ case NET_NEIGH_REACHABLE_TIME_MS:
+ ret = sysctl_ms_jiffies(ctl, name, nlen,
+ oldval, oldlenp, newval, newlen,
+ context);
+ break;
+ default:
+ ret = 0;
+ }
+
+ if (newval && newlen && ret > 0 &&
+ dev && (idev = in6_dev_get(dev)) != NULL) {
+ if (ctl->ctl_name == NET_NEIGH_REACHABLE_TIME ||
+ ctl->ctl_name == NET_NEIGH_REACHABLE_TIME_MS)
+ idev->nd_parms->reachable_time = neigh_rand_reach_time(idev->nd_parms->base_reachable_time);
idev->tstamp = jiffies;
inet6_ifinfo_notify(RTM_NEWLINK, idev);
in6_dev_put(idev);
}
- return proc_dointvec(ctl, write, filp, buffer, lenp, ppos);
+
+ return ret;
}
+
#endif
int __init ndisc_init(struct net_proto_family *ops)
@@ -1578,7 +1670,9 @@ int __init ndisc_init(struct net_proto_family *ops)
#ifdef CONFIG_SYSCTL
neigh_sysctl_register(NULL, &nd_tbl.parms, NET_IPV6, NET_IPV6_NEIGH,
- "ipv6", &ndisc_ifinfo_sysctl_change);
+ "ipv6",
+ &ndisc_ifinfo_sysctl_change,
+ &ndisc_ifinfo_sysctl_strategy);
#endif
register_netdevice_notifier(&ndisc_netdev_notifier);
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig
index 325d91edfa969..77ec704c9ee34 100644
--- a/net/ipv6/netfilter/Kconfig
+++ b/net/ipv6/netfilter/Kconfig
@@ -2,8 +2,8 @@
# IP netfilter configuration
#
-menu "IPv6: Netfilter Configuration"
- depends on INET && IPV6 && NETFILTER
+menu "IPv6: Netfilter Configuration (EXPERIMENTAL)"
+ depends on INET && IPV6 && NETFILTER && EXPERIMENTAL
#tristate 'Connection tracking (required for masq/NAT)' CONFIG_IP6_NF_CONNTRACK
#if [ "$CONFIG_IP6_NF_CONNTRACK" != "n" ]; then
diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c
index 6795b4179933b..c54830b895939 100644
--- a/net/ipv6/netfilter/ip6_queue.c
+++ b/net/ipv6/netfilter/ip6_queue.c
@@ -20,6 +20,9 @@
* Few changes needed, mainly the hard_routing code and
* the netlink socket protocol (we're NETLINK_IP6_FW).
* 2002-06-25: Code cleanup. [JM: ported cleanup over from ip_queue.c]
+ * 2005-02-04: Added /proc counter for dropped packets; fixed so
+ * packets aren't delivered to user space if they're going
+ * to be dropped.
*/
#include <linux/module.h>
#include <linux/skbuff.h>
@@ -64,6 +67,8 @@ static DEFINE_RWLOCK(queue_lock);
static int peer_pid;
static unsigned int copy_range;
static unsigned int queue_total;
+static unsigned int queue_dropped = 0;
+static unsigned int queue_user_dropped = 0;
static struct sock *ipqnl;
static LIST_HEAD(queue_list);
static DECLARE_MUTEX(ipqnl_sem);
@@ -75,18 +80,11 @@ ipq_issue_verdict(struct ipq_queue_entry *entry, int verdict)
kfree(entry);
}
-static inline int
+static inline void
__ipq_enqueue_entry(struct ipq_queue_entry *entry)
{
- if (queue_total >= queue_maxlen) {
- if (net_ratelimit())
- printk(KERN_WARNING "ip6_queue: full at %d entries, "
- "dropping packet(s).\n", queue_total);
- return -ENOSPC;
- }
list_add(&entry->list, &queue_list);
queue_total++;
- return 0;
}
/*
@@ -312,14 +310,24 @@ ipq_enqueue_packet(struct sk_buff *skb, struct nf_info *info, void *data)
if (!peer_pid)
goto err_out_free_nskb;
+ if (queue_total >= queue_maxlen) {
+ queue_dropped++;
+ status = -ENOSPC;
+ if (net_ratelimit())
+ printk (KERN_WARNING "ip6_queue: fill at %d entries, "
+ "dropping packet(s). Dropped: %d\n", queue_total,
+ queue_dropped);
+ goto err_out_free_nskb;
+ }
+
/* netlink_unicast will either free the nskb or attach it to a socket */
status = netlink_unicast(ipqnl, nskb, peer_pid, MSG_DONTWAIT);
- if (status < 0)
+ if (status < 0) {
+ queue_user_dropped++;
goto err_out_unlock;
+ }
- status = __ipq_enqueue_entry(entry);
- if (status < 0)
- goto err_out_unlock;
+ __ipq_enqueue_entry(entry);
write_unlock_bh(&queue_lock);
return status;
@@ -639,12 +647,16 @@ ipq_get_info(char *buffer, char **start, off_t offset, int length)
"Copy mode : %hu\n"
"Copy range : %u\n"
"Queue length : %u\n"
- "Queue max. length : %u\n",
+ "Queue max. length : %u\n"
+ "Queue dropped : %u\n"
+ "Netfilter dropped : %u\n",
peer_pid,
copy_mode,
copy_range,
queue_total,
- queue_maxlen);
+ queue_maxlen,
+ queue_dropped,
+ queue_user_dropped);
read_unlock_bh(&queue_lock);
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 6a06de74a30f1..c735276fdd5fb 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -952,7 +952,7 @@ translate_table(const char *name,
}
/* And one copy for every other CPU */
- for (i = 1; i < NR_CPUS; i++) {
+ for (i = 1; i < num_possible_cpus(); i++) {
memcpy(newinfo->entries + SMP_ALIGN(newinfo->size)*i,
newinfo->entries,
SMP_ALIGN(newinfo->size));
@@ -974,7 +974,7 @@ replace_table(struct ip6t_table *table,
struct ip6t_entry *table_base;
unsigned int i;
- for (i = 0; i < NR_CPUS; i++) {
+ for (i = 0; i < num_possible_cpus(); i++) {
table_base =
(void *)newinfo->entries
+ TABLE_OFFSET(newinfo, i);
@@ -1021,7 +1021,7 @@ get_counters(const struct ip6t_table_info *t,
unsigned int cpu;
unsigned int i;
- for (cpu = 0; cpu < NR_CPUS; cpu++) {
+ for (cpu = 0; cpu < num_possible_cpus(); cpu++) {
i = 0;
IP6T_ENTRY_ITERATE(t->entries + TABLE_OFFSET(t, cpu),
t->size,
@@ -1155,7 +1155,7 @@ do_replace(void __user *user, unsigned int len)
return -ENOMEM;
newinfo = vmalloc(sizeof(struct ip6t_table_info)
- + SMP_ALIGN(tmp.size) * NR_CPUS);
+ + SMP_ALIGN(tmp.size) * num_possible_cpus());
if (!newinfo)
return -ENOMEM;
@@ -1469,7 +1469,7 @@ int ip6t_register_table(struct ip6t_table *table,
= { 0, 0, 0, { 0 }, { 0 }, { } };
newinfo = vmalloc(sizeof(struct ip6t_table_info)
- + SMP_ALIGN(repl->size) * NR_CPUS);
+ + SMP_ALIGN(repl->size) * num_possible_cpus());
if (!newinfo)
return -ENOMEM;
diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c
index 3330ba6cf5385..334a5967831e0 100644
--- a/net/ipv6/proc.c
+++ b/net/ipv6/proc.c
@@ -201,33 +201,23 @@ static struct file_operations snmp6_seq_fops = {
int snmp6_register_dev(struct inet6_dev *idev)
{
- int err = -ENOMEM;
struct proc_dir_entry *p;
if (!idev || !idev->dev)
return -EINVAL;
- if (snmp6_mib_init((void **)idev->stats.icmpv6, sizeof(struct icmpv6_mib),
- __alignof__(struct icmpv6_mib)) < 0)
- goto err_icmp;
+ if (!proc_net_devsnmp6)
+ return -ENOENT;
- if (!proc_net_devsnmp6) {
- err = -ENOENT;
- goto err_proc;
- }
p = create_proc_entry(idev->dev->name, S_IRUGO, proc_net_devsnmp6);
if (!p)
- goto err_proc;
+ return -ENOMEM;
+
p->data = idev;
p->proc_fops = &snmp6_seq_fops;
idev->stats.proc_dir_entry = p;
return 0;
-
-err_proc:
- snmp6_mib_free((void **)idev->stats.icmpv6);
-err_icmp:
- return err;
}
int snmp6_unregister_dev(struct inet6_dev *idev)
@@ -238,8 +228,6 @@ int snmp6_unregister_dev(struct inet6_dev *idev)
return -EINVAL;
remove_proc_entry(idev->stats.proc_dir_entry->name,
proc_net_devsnmp6);
- snmp6_mib_free((void **)idev->stats.icmpv6);
-
return 0;
}
@@ -280,6 +268,17 @@ void ipv6_misc_proc_exit(void)
int snmp6_register_dev(struct inet6_dev *idev)
{
+ return 0;
+}
+
+int snmp6_unregister_dev(struct inet6_dev *idev)
+{
+ return 0;
+}
+#endif /* CONFIG_PROC_FS */
+
+int snmp6_alloc_dev(struct inet6_dev *idev)
+{
int err = -ENOMEM;
if (!idev || !idev->dev)
@@ -295,11 +294,10 @@ err_icmp:
return err;
}
-int snmp6_unregister_dev(struct inet6_dev *idev)
+int snmp6_free_dev(struct inet6_dev *idev)
{
snmp6_mib_free((void **)idev->stats.icmpv6);
return 0;
}
-#endif
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index be23939b8f8e7..a8b4acfab951b 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -756,6 +756,8 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
hlimit = np->hop_limit;
if (hlimit < 0)
hlimit = dst_metric(dst, RTAX_HOPLIMIT);
+ if (hlimit < 0)
+ hlimit = ipv6_get_hoplimit(dst->dev);
}
if (msg->msg_flags&MSG_CONFIRM)
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index dd1703a09aa9d..183802902c023 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -589,7 +589,6 @@ static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie)
if (rt && rt->rt6i_node && (rt->rt6i_node->fn_sernum == cookie))
return dst;
- dst_release(dst);
return NULL;
}
@@ -626,10 +625,12 @@ static void ip6_rt_update_pmtu(struct dst_entry *dst, u32 mtu)
{
struct rt6_info *rt6 = (struct rt6_info*)dst;
- if (mtu < dst_pmtu(dst) && rt6->rt6i_dst.plen == 128) {
+ if (mtu < dst_mtu(dst) && rt6->rt6i_dst.plen == 128) {
rt6->rt6i_flags |= RTF_MODIFIED;
- if (mtu < IPV6_MIN_MTU)
+ if (mtu < IPV6_MIN_MTU) {
mtu = IPV6_MIN_MTU;
+ dst->metrics[RTAX_FEATURES-1] |= RTAX_FEATURE_ALLFRAG;
+ }
dst->metrics[RTAX_MTU-1] = mtu;
}
}
@@ -685,7 +686,7 @@ struct dst_entry *ndisc_dst_alloc(struct net_device *dev,
atomic_set(&rt->u.dst.__refcnt, 1);
rt->u.dst.metrics[RTAX_HOPLIMIT-1] = 255;
rt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(rt->rt6i_dev);
- rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_pmtu(&rt->u.dst));
+ rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_mtu(&rt->u.dst));
rt->u.dst.output = output;
#if 0 /* there's no chance to use these for ndisc */
@@ -769,7 +770,7 @@ static int ipv6_get_mtu(struct net_device *dev)
return mtu;
}
-static int ipv6_get_hoplimit(struct net_device *dev)
+int ipv6_get_hoplimit(struct net_device *dev)
{
int hoplimit = ipv6_devconf.hop_limit;
struct inet6_dev *idev;
@@ -965,19 +966,12 @@ install_route:
}
}
- if (rt->u.dst.metrics[RTAX_HOPLIMIT-1] == 0) {
- if (ipv6_addr_is_multicast(&rt->rt6i_dst.addr))
- rt->u.dst.metrics[RTAX_HOPLIMIT-1] =
- IPV6_DEFAULT_MCASTHOPS;
- else
- rt->u.dst.metrics[RTAX_HOPLIMIT-1] =
- ipv6_get_hoplimit(dev);
- }
-
+ if (rt->u.dst.metrics[RTAX_HOPLIMIT-1] == 0)
+ rt->u.dst.metrics[RTAX_HOPLIMIT-1] = -1;
if (!rt->u.dst.metrics[RTAX_MTU-1])
rt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(dev);
if (!rt->u.dst.metrics[RTAX_ADVMSS-1])
- rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_pmtu(&rt->u.dst));
+ rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_mtu(&rt->u.dst));
rt->u.dst.dev = dev;
rt->rt6i_idev = idev;
return ip6_ins_rt(rt, nlh, _rtattr);
@@ -1140,7 +1134,7 @@ source_ok:
nrt->rt6i_nexthop = neigh_clone(neigh);
/* Reset pmtu, it may be better */
nrt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(neigh->dev);
- nrt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_pmtu(&nrt->u.dst));
+ nrt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_mtu(&nrt->u.dst));
if (ip6_ins_rt(nrt, NULL, NULL))
goto out;
@@ -1164,26 +1158,26 @@ void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr,
struct net_device *dev, u32 pmtu)
{
struct rt6_info *rt, *nrt;
-
- if (pmtu < IPV6_MIN_MTU) {
- if (net_ratelimit())
- printk(KERN_DEBUG "rt6_pmtu_discovery: invalid MTU value %d\n",
- pmtu);
- /* According to RFC1981, the PMTU is set to the IPv6 minimum
- link MTU if the node receives a Packet Too Big message
- reporting next-hop MTU that is less than the IPv6 minimum MTU.
- */
- pmtu = IPV6_MIN_MTU;
- }
+ int allfrag = 0;
rt = rt6_lookup(daddr, saddr, dev->ifindex, 0);
-
if (rt == NULL)
return;
- if (pmtu >= dst_pmtu(&rt->u.dst))
+ if (pmtu >= dst_mtu(&rt->u.dst))
goto out;
+ if (pmtu < IPV6_MIN_MTU) {
+ /*
+ * According to RFC2460, PMTU is set to the IPv6 Minimum Link
+ * MTU (1280) and a fragment header should always be included
+ * after a node receiving Too Big message reporting PMTU is
+ * less than the IPv6 Minimum Link MTU.
+ */
+ pmtu = IPV6_MIN_MTU;
+ allfrag = 1;
+ }
+
/* New mtu received -> path was valid.
They are sent only in response to data packets,
so that this nexthop apparently is reachable. --ANK
@@ -1197,6 +1191,8 @@ void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr,
*/
if (rt->rt6i_flags & RTF_CACHE) {
rt->u.dst.metrics[RTAX_MTU-1] = pmtu;
+ if (allfrag)
+ rt->u.dst.metrics[RTAX_FEATURES-1] |= RTAX_FEATURE_ALLFRAG;
dst_set_expires(&rt->u.dst, ip6_rt_mtu_expires);
rt->rt6i_flags |= RTF_MODIFIED|RTF_EXPIRES;
goto out;
@@ -1211,6 +1207,8 @@ void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr,
nrt = rt6_cow(rt, daddr, saddr);
if (!nrt->u.dst.error) {
nrt->u.dst.metrics[RTAX_MTU-1] = pmtu;
+ if (allfrag)
+ nrt->u.dst.metrics[RTAX_FEATURES-1] |= RTAX_FEATURE_ALLFRAG;
/* According to RFC 1981, detecting PMTU increase shouldn't be
happened within 5 mins, the recommended timer is 10 mins.
Here this route expiration time is set to ip6_rt_mtu_expires
@@ -1232,6 +1230,8 @@ void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr,
dst_set_expires(&nrt->u.dst, ip6_rt_mtu_expires);
nrt->rt6i_flags |= RTF_DYNAMIC|RTF_CACHE|RTF_EXPIRES;
nrt->u.dst.metrics[RTAX_MTU-1] = pmtu;
+ if (allfrag)
+ nrt->u.dst.metrics[RTAX_FEATURES-1] |= RTAX_FEATURE_ALLFRAG;
ip6_ins_rt(nrt, NULL, NULL);
}
@@ -1405,8 +1405,8 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
rt->rt6i_dev = &loopback_dev;
rt->rt6i_idev = idev;
rt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(rt->rt6i_dev);
- rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_pmtu(&rt->u.dst));
- rt->u.dst.metrics[RTAX_HOPLIMIT-1] = ipv6_get_hoplimit(rt->rt6i_dev);
+ rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_mtu(&rt->u.dst));
+ rt->u.dst.metrics[RTAX_HOPLIMIT-1] = -1;
rt->u.dst.obsolete = -1;
rt->rt6i_flags = RTF_UP | RTF_NONEXTHOP;
@@ -1480,9 +1480,9 @@ static int rt6_mtu_change_route(struct rt6_info *rt, void *p_arg)
*/
if (rt->rt6i_dev == arg->dev &&
!dst_metric_locked(&rt->u.dst, RTAX_MTU) &&
- (dst_pmtu(&rt->u.dst) > arg->mtu ||
- (dst_pmtu(&rt->u.dst) < arg->mtu &&
- dst_pmtu(&rt->u.dst) == idev->cnf.mtu6)))
+ (dst_mtu(&rt->u.dst) > arg->mtu ||
+ (dst_mtu(&rt->u.dst) < arg->mtu &&
+ dst_mtu(&rt->u.dst) == idev->cnf.mtu6)))
rt->u.dst.metrics[RTAX_MTU-1] = arg->mtu;
rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(arg->mtu);
return 0;
@@ -1993,9 +1993,7 @@ int ipv6_sysctl_rtcache_flush(ctl_table *ctl, int write, struct file * filp,
{
if (write) {
proc_dointvec(ctl, write, filp, buffer, lenp, ppos);
- if (flush_delay < 0)
- flush_delay = 0;
- fib6_run_gc((unsigned long)flush_delay);
+ fib6_run_gc(flush_delay <= 0 ? ~0UL : (unsigned long)flush_delay);
return 0;
} else
return -EINVAL;
@@ -2080,6 +2078,15 @@ ctl_table ipv6_route_table[] = {
.proc_handler = &proc_dointvec_jiffies,
.strategy = &sysctl_jiffies,
},
+ {
+ .ctl_name = NET_IPV6_ROUTE_GC_MIN_INTERVAL_MS,
+ .procname = "gc_min_interval_ms",
+ .data = &ip6_rt_gc_min_interval,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_ms_jiffies,
+ .strategy = &sysctl_ms_jiffies,
+ },
{ .ctl_name = 0 }
};
@@ -2109,7 +2116,7 @@ void __init ip6_route_init(void)
#endif
}
-void __exit ip6_route_cleanup(void)
+void ip6_route_cleanup(void)
{
#ifdef CONFIG_PROC_FS
proc_net_remove("ipv6_route");
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index b517fa50f01b1..b788f55e139b8 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -500,9 +500,9 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
}
if (tiph->frag_off)
- mtu = dst_pmtu(&rt->u.dst) - sizeof(struct iphdr);
+ mtu = dst_mtu(&rt->u.dst) - sizeof(struct iphdr);
else
- mtu = skb->dst ? dst_pmtu(skb->dst) : dev->mtu;
+ mtu = skb->dst ? dst_mtu(skb->dst) : dev->mtu;
if (mtu < 68) {
tunnel->stat.collisions++;
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 5167758946659..40a50e82ed55a 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -441,21 +441,22 @@ static __u32 tcp_v6_init_sequence(struct sock *sk, struct sk_buff *skb)
}
}
-static int tcp_v6_check_established(struct sock *sk)
+static int __tcp_v6_check_established(struct sock *sk, __u16 lport,
+ struct tcp_tw_bucket **twp)
{
struct inet_sock *inet = inet_sk(sk);
struct ipv6_pinfo *np = inet6_sk(sk);
struct in6_addr *daddr = &np->rcv_saddr;
struct in6_addr *saddr = &np->daddr;
int dif = sk->sk_bound_dev_if;
- u32 ports = TCP_COMBINED_PORTS(inet->dport, inet->num);
+ u32 ports = TCP_COMBINED_PORTS(inet->dport, lport);
int hash = tcp_v6_hashfn(daddr, inet->num, saddr, inet->dport);
struct tcp_ehash_bucket *head = &tcp_ehash[hash];
struct sock *sk2;
struct hlist_node *node;
struct tcp_tw_bucket *tw;
- write_lock_bh(&head->lock);
+ write_lock(&head->lock);
/* Check TIME-WAIT sockets first. */
sk_for_each(sk2, node, &(head + tcp_ehash_size)->chain) {
@@ -468,7 +469,10 @@ static int tcp_v6_check_established(struct sock *sk)
sk2->sk_bound_dev_if == sk->sk_bound_dev_if) {
struct tcp_sock *tp = tcp_sk(sk);
- if (tw->tw_ts_recent_stamp) {
+ if (tw->tw_ts_recent_stamp &&
+ (!twp || (sysctl_tcp_tw_reuse &&
+ xtime.tv_sec -
+ tw->tw_ts_recent_stamp > 1))) {
/* See comment in tcp_ipv4.c */
tp->write_seq = tw->tw_snd_nxt + 65535 + 2;
if (!tp->write_seq)
@@ -494,40 +498,113 @@ unique:
__sk_add_node(sk, &head->chain);
sk->sk_hashent = hash;
sock_prot_inc_use(sk->sk_prot);
- write_unlock_bh(&head->lock);
+ write_unlock(&head->lock);
- if (tw) {
+ if (twp) {
+ *twp = tw;
+ NET_INC_STATS_BH(LINUX_MIB_TIMEWAITRECYCLED);
+ } else if (tw) {
/* Silly. Should hash-dance instead... */
- local_bh_disable();
tcp_tw_deschedule(tw);
NET_INC_STATS_BH(LINUX_MIB_TIMEWAITRECYCLED);
- local_bh_enable();
tcp_tw_put(tw);
}
return 0;
not_unique:
- write_unlock_bh(&head->lock);
+ write_unlock(&head->lock);
return -EADDRNOTAVAIL;
}
-static int tcp_v6_hash_connect(struct sock *sk)
+static inline u32 tcpv6_port_offset(const struct sock *sk)
{
- struct tcp_bind_hashbucket *head;
- struct tcp_bind_bucket *tb;
+ const struct inet_sock *inet = inet_sk(sk);
+ const struct ipv6_pinfo *np = inet6_sk(sk);
- /* XXX */
- if (inet_sk(sk)->num == 0) {
- int err = tcp_v6_get_port(sk, inet_sk(sk)->num);
- if (err)
- return err;
- inet_sk(sk)->sport = htons(inet_sk(sk)->num);
- }
+ return secure_tcpv6_port_ephemeral(np->rcv_saddr.s6_addr32,
+ np->daddr.s6_addr32,
+ inet->dport);
+}
- head = &tcp_bhash[tcp_bhashfn(inet_sk(sk)->num)];
- tb = tb_head(head);
+static int tcp_v6_hash_connect(struct sock *sk)
+{
+ unsigned short snum = inet_sk(sk)->num;
+ struct tcp_bind_hashbucket *head;
+ struct tcp_bind_bucket *tb;
+ 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 tcp_tw_bucket *tw = NULL;
+
+ local_bh_disable();
+ for (i = 1; i <= range; i++) {
+ port = low + (i + offset) % range;
+ head = &tcp_bhash[tcp_bhashfn(port)];
+ spin_lock(&head->lock);
+
+ /* Does not bother with rcv_saddr checks,
+ * because the established check is already
+ * unique enough.
+ */
+ tb_for_each(tb, node, &head->chain) {
+ 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 = tcp_bucket_create(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 */
+ tcp_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) {
+ tcp_tw_deschedule(tw);
+ tcp_tw_put(tw);
+ }
+
+ ret = 0;
+ goto out;
+ }
+
+ head = &tcp_bhash[tcp_bhashfn(snum)];
+ tb = tcp_sk(sk)->bind_hash;
spin_lock_bh(&head->lock);
if (sk_head(&tb->owners) == sk && !sk->sk_bind_node.next) {
@@ -535,8 +612,12 @@ static int tcp_v6_hash_connect(struct sock *sk)
spin_unlock_bh(&head->lock);
return 0;
} else {
- spin_unlock_bh(&head->lock);
- return tcp_v6_check_established(sk);
+ 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;
}
}
@@ -701,7 +782,6 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
tp->ext_header_len = 0;
if (np->opt)
tp->ext_header_len = np->opt->opt_flen + np->opt->opt_nflen;
- tp->ext2_header_len = dst->header_len;
tp->rx_opt.mss_clamp = IPV6_MIN_MTU - sizeof(struct tcphdr) - sizeof(struct ipv6hdr);
@@ -813,8 +893,8 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
} else
dst_hold(dst);
- if (tp->pmtu_cookie > dst_pmtu(dst)) {
- tcp_sync_mss(sk, dst_pmtu(dst));
+ if (tp->pmtu_cookie > dst_mtu(dst)) {
+ tcp_sync_mss(sk, dst_mtu(dst));
tcp_simple_retransmit(sk);
} /* else let the usual retransmit timer handle it */
dst_release(dst);
@@ -1443,9 +1523,8 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
if (newnp->opt)
newtp->ext_header_len = newnp->opt->opt_nflen +
newnp->opt->opt_flen;
- newtp->ext2_header_len = dst->header_len;
- tcp_sync_mss(newsk, dst_pmtu(dst));
+ tcp_sync_mss(newsk, dst_mtu(dst));
newtp->advmss = dst_metric(dst, RTAX_ADVMSS);
tcp_initialize_rcv_mss(newsk);
@@ -1792,7 +1871,6 @@ static int tcp_v6_rebuild_header(struct sock *sk)
ip6_dst_store(sk, dst, NULL);
sk->sk_route_caps = dst->dev->features &
~(NETIF_F_IP_CSUM | NETIF_F_TSO);
- tcp_sk(sk)->ext2_header_len = dst->header_len;
}
return 0;
@@ -1846,7 +1924,6 @@ static int tcp_v6_xmit(struct sk_buff *skb, int ipfragok)
ip6_dst_store(sk, dst, NULL);
sk->sk_route_caps = dst->dev->features &
~(NETIF_F_IP_CSUM | NETIF_F_TSO);
- tcp_sk(sk)->ext2_header_len = dst->header_len;
}
skb->dst = dst_clone(dst);
@@ -1950,7 +2027,7 @@ static int tcp_v6_init_sock(struct sock *sk)
tp->af_specific = &ipv6_specific;
sk->sk_write_space = sk_stream_write_space;
- sk->sk_use_write_queue = 1;
+ sock_set_flag(sk, SOCK_USE_WRITE_QUEUE);
sk->sk_sndbuf = sysctl_tcp_wmem[1];
sk->sk_rcvbuf = sysctl_tcp_rmem[1];
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 00db112f6e459..badbcc26c338a 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -811,6 +811,8 @@ do_udp_sendmsg:
hlimit = np->hop_limit;
if (hlimit < 0)
hlimit = dst_metric(dst, RTAX_HOPLIMIT);
+ if (hlimit < 0)
+ hlimit = ipv6_get_hoplimit(dst->dev);
}
if (msg->msg_flags&MSG_CONFIRM)
diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c
index b06b11c960bbc..601a148f60f39 100644
--- a/net/ipv6/xfrm6_output.c
+++ b/net/ipv6/xfrm6_output.c
@@ -69,7 +69,7 @@ static void xfrm6_encap(struct sk_buff *skb)
dsfield &= ~INET_ECN_MASK;
ipv6_change_dsfield(top_iph, 0, dsfield);
top_iph->nexthdr = IPPROTO_IPV6;
- top_iph->hop_limit = dst_path_metric(dst, RTAX_HOPLIMIT);
+ top_iph->hop_limit = dst_metric(dst->child, RTAX_HOPLIMIT);
ipv6_addr_copy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr);
ipv6_addr_copy(&top_iph->daddr, (struct in6_addr *)&x->id.daddr);
}
@@ -79,7 +79,7 @@ static int xfrm6_tunnel_check_size(struct sk_buff *skb)
int mtu, ret = 0;
struct dst_entry *dst = skb->dst;
- mtu = dst_pmtu(dst) - dst->header_len - dst->trailer_len;
+ mtu = dst_mtu(dst);
if (mtu < IPV6_MIN_MTU)
mtu = IPV6_MIN_MTU;
@@ -103,20 +103,20 @@ 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;
-
if (x->props.mode) {
err = xfrm6_tunnel_check_size(skb);
if (err)
- goto error;
+ goto error_nolock;
}
+ spin_lock_bh(&x->lock);
+ err = xfrm_state_check(x, skb);
+ if (err)
+ goto error;
+
xfrm6_encap(skb);
- err = x->type->output(skb);
+ err = x->type->output(x, skb);
if (err)
goto error;
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
index f17e340a90feb..8a4f37de4d2da 100644
--- a/net/ipv6/xfrm6_policy.c
+++ b/net/ipv6/xfrm6_policy.c
@@ -31,26 +31,6 @@ static int xfrm6_dst_lookup(struct xfrm_dst **dst, struct flowi *fl)
return err;
}
-/* Check that the bundle accepts the flow and its components are
- * still valid.
- */
-
-static int __xfrm6_bundle_ok(struct xfrm_dst *xdst, struct flowi *fl)
-{
- do {
- if (xdst->u.dst.ops != &xfrm6_dst_ops)
- return 1;
-
- if (!xfrm_selector_match(&xdst->u.dst.xfrm->sel, fl, AF_INET6))
- return 0;
- if (xdst->u.dst.xfrm->km.state != XFRM_STATE_VALID ||
- xdst->u.dst.path->obsolete > 0)
- return 0;
- xdst = (struct xfrm_dst*)xdst->u.dst.child;
- } while (xdst);
- return 0;
-}
-
static struct dst_entry *
__xfrm6_find_bundle(struct flowi *fl, struct xfrm_policy *policy)
{
@@ -70,7 +50,7 @@ __xfrm6_find_bundle(struct flowi *fl, struct xfrm_policy *policy)
xdst->u.rt6.rt6i_src.plen);
if (ipv6_addr_equal(&xdst->u.rt6.rt6i_dst.addr, &fl_dst_prefix) &&
ipv6_addr_equal(&xdst->u.rt6.rt6i_src.addr, &fl_src_prefix) &&
- __xfrm6_bundle_ok(xdst, fl)) {
+ xfrm_bundle_ok(xdst, fl, AF_INET6)) {
dst_clone(dst);
break;
}
@@ -92,18 +72,30 @@ __xfrm6_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int
struct rt6_info *rt = rt0;
struct in6_addr *remote = &fl->fl6_dst;
struct in6_addr *local = &fl->fl6_src;
+ struct flowi fl_tunnel = {
+ .nl_u = {
+ .ip6_u = {
+ .saddr = *local,
+ .daddr = *remote
+ }
+ }
+ };
int i;
int err = 0;
int header_len = 0;
int trailer_len = 0;
dst = dst_prev = NULL;
+ dst_hold(&rt->u.dst);
for (i = 0; i < nx; i++) {
struct dst_entry *dst1 = dst_alloc(&xfrm6_dst_ops);
+ struct xfrm_dst *xdst;
+ int tunnel = 0;
if (unlikely(dst1 == NULL)) {
err = -ENOBUFS;
+ dst_release(&rt->u.dst);
goto error;
}
@@ -114,32 +106,40 @@ __xfrm6_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int
dst1->flags |= DST_NOHASH;
dst_clone(dst1);
}
+
+ xdst = (struct xfrm_dst *)dst1;
+ xdst->route = &rt->u.dst;
+
+ dst1->next = dst_prev;
dst_prev = dst1;
if (xfrm[i]->props.mode) {
remote = (struct in6_addr*)&xfrm[i]->id.daddr;
local = (struct in6_addr*)&xfrm[i]->props.saddr;
+ tunnel = 1;
}
header_len += xfrm[i]->props.header_len;
trailer_len += xfrm[i]->props.trailer_len;
+
+ if (tunnel) {
+ ipv6_addr_copy(&fl_tunnel.fl6_dst, remote);
+ ipv6_addr_copy(&fl_tunnel.fl6_src, local);
+ err = xfrm_dst_lookup((struct xfrm_dst **) &rt,
+ &fl_tunnel, AF_INET6);
+ if (err)
+ goto error;
+ } else
+ dst_hold(&rt->u.dst);
}
- if (!ipv6_addr_equal(remote, &fl->fl6_dst)) {
- struct flowi fl_tunnel;
+ dst_prev->child = &rt->u.dst;
+ dst->path = &rt->u.dst;
- memset(&fl_tunnel, 0, sizeof(fl_tunnel));
- ipv6_addr_copy(&fl_tunnel.fl6_dst, remote);
- ipv6_addr_copy(&fl_tunnel.fl6_src, local);
+ *dst_p = dst;
+ dst = dst_prev;
- err = xfrm_dst_lookup((struct xfrm_dst **) &rt,
- &fl_tunnel, AF_INET6);
- if (err)
- goto error;
- } else {
- dst_hold(&rt->u.dst);
- }
- dst_prev->child = &rt->u.dst;
+ dst_prev = *dst_p;
i = 0;
- for (dst_prev = dst; dst_prev != &rt->u.dst; dst_prev = dst_prev->child) {
+ for (; dst_prev != &rt->u.dst; dst_prev = dst_prev->child) {
struct xfrm_dst *x = (struct xfrm_dst*)dst_prev;
dst_prev->xfrm = xfrm[i++];
@@ -151,8 +151,7 @@ __xfrm6_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int
dst_prev->lastuse = jiffies;
dst_prev->header_len = header_len;
dst_prev->trailer_len = trailer_len;
- memcpy(&dst_prev->metrics, &rt->u.dst.metrics, sizeof(dst_prev->metrics));
- dst_prev->path = &rt->u.dst;
+ memcpy(&dst_prev->metrics, &x->route->metrics, sizeof(dst_prev->metrics));
/* Copy neighbour for reachability confirmation */
dst_prev->neighbour = neigh_clone(rt->u.dst.neighbour);
@@ -170,7 +169,8 @@ __xfrm6_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int
header_len -= x->u.dst.xfrm->props.header_len;
trailer_len -= x->u.dst.xfrm->props.trailer_len;
}
- *dst_p = dst;
+
+ xfrm_init_pmtu(dst);
return 0;
error:
@@ -245,12 +245,10 @@ static inline int xfrm6_garbage_collect(void)
static void xfrm6_update_pmtu(struct dst_entry *dst, u32 mtu)
{
- struct dst_entry *path = dst->path;
+ struct xfrm_dst *xdst = (struct xfrm_dst *)dst;
+ struct dst_entry *path = xdst->route;
- if (mtu >= IPV6_MIN_MTU && mtu < dst_pmtu(dst))
- path->ops->update_pmtu(path, mtu);
-
- return;
+ path->ops->update_pmtu(path, mtu);
}
static struct dst_ops xfrm6_dst_ops = {
@@ -278,7 +276,7 @@ static void __init xfrm6_policy_init(void)
xfrm_policy_register_afinfo(&xfrm6_policy_afinfo);
}
-static void __exit xfrm6_policy_fini(void)
+static void xfrm6_policy_fini(void)
{
xfrm_policy_unregister_afinfo(&xfrm6_policy_afinfo);
}
@@ -289,7 +287,7 @@ void __init xfrm6_init(void)
xfrm6_state_init();
}
-void __exit xfrm6_fini(void)
+void xfrm6_fini(void)
{
//xfrm6_input_fini();
xfrm6_policy_fini();
diff --git a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c
index 6024a1c3cc15e..bf0d0abc3871b 100644
--- a/net/ipv6/xfrm6_state.c
+++ b/net/ipv6/xfrm6_state.c
@@ -27,9 +27,9 @@ __xfrm6_init_tempsel(struct xfrm_state *x, struct flowi *fl,
* to current session. */
ipv6_addr_copy((struct in6_addr *)&x->sel.daddr, &fl->fl6_dst);
ipv6_addr_copy((struct in6_addr *)&x->sel.saddr, &fl->fl6_src);
- x->sel.dport = fl->fl_ip_dport;
+ x->sel.dport = xfrm_flowi_dport(fl);
x->sel.dport_mask = ~0;
- x->sel.sport = fl->fl_ip_sport;
+ x->sel.sport = xfrm_flowi_sport(fl);
x->sel.sport_mask = ~0;
x->sel.prefixlen_d = 128;
x->sel.prefixlen_s = 128;
@@ -129,7 +129,7 @@ void __init xfrm6_state_init(void)
xfrm_state_register_afinfo(&xfrm6_state_afinfo);
}
-void __exit xfrm6_state_fini(void)
+void xfrm6_state_fini(void)
{
xfrm_state_unregister_afinfo(&xfrm6_state_afinfo);
}
diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c
index 1df30ba70200a..ffcadd68b951d 100644
--- a/net/ipv6/xfrm6_tunnel.c
+++ b/net/ipv6/xfrm6_tunnel.c
@@ -343,7 +343,7 @@ void xfrm6_tunnel_free_spi(xfrm_address_t *saddr)
EXPORT_SYMBOL(xfrm6_tunnel_free_spi);
-static int xfrm6_tunnel_output(struct sk_buff *skb)
+static int xfrm6_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
{
struct ipv6hdr *top_iph;
diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c
index 344be7e9ea40d..65309f9d9e532 100644
--- a/net/ipx/af_ipx.c
+++ b/net/ipx/af_ipx.c
@@ -310,7 +310,7 @@ static void __ipxitf_down(struct ipx_interface *intrfc)
s->sk_error_report(s);
ipxs->intrfc = NULL;
ipxs->port = 0;
- s->sk_zapped = 1; /* Indicates it is no longer bound */
+ sock_set_flag(s, SOCK_ZAPPED); /* Indicates it is no longer bound */
sk_del_node_init(s);
}
INIT_HLIST_HEAD(&intrfc->if_sklist);
@@ -1427,7 +1427,7 @@ static int ipx_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
struct sockaddr_ipx *addr = (struct sockaddr_ipx *)uaddr;
int rc = -EINVAL;
- if (!sk->sk_zapped || addr_len != sizeof(struct sockaddr_ipx))
+ if (!sock_flag(sk, SOCK_ZAPPED) || addr_len != sizeof(struct sockaddr_ipx))
goto out;
intrfc = ipxitf_find_using_net(addr->sipx_network);
@@ -1505,7 +1505,7 @@ static int ipx_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
#endif /* CONFIG_IPX_INTERN */
ipxitf_insert_socket(intrfc, sk);
- sk->sk_zapped = 0;
+ sock_reset_flag(sk, SOCK_ZAPPED);
rc = 0;
out_put:
@@ -1774,7 +1774,7 @@ static int ipx_recvmsg(struct kiocb *iocb, struct socket *sock,
}
rc = -ENOTCONN;
- if (sk->sk_zapped)
+ if (sock_flag(sk, SOCK_ZAPPED))
goto out;
skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT,
diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c
index 5dd00fe097b65..a6f32b96d3b56 100644
--- a/net/irda/af_irda.c
+++ b/net/irda/af_irda.c
@@ -87,11 +87,9 @@ static int irda_data_indication(void *instance, void *sap, struct sk_buff *skb)
IRDA_DEBUG(3, "%s()\n", __FUNCTION__);
- self = (struct irda_sock *) instance;
- ASSERT(self != NULL, return -1;);
-
- sk = self->sk;
- ASSERT(sk != NULL, return -1;);
+ self = instance;
+ sk = instance;
+ IRDA_ASSERT(sk != NULL, return -1;);
err = sock_queue_rcv_skb(sk, skb);
if (err) {
@@ -117,7 +115,7 @@ static void irda_disconnect_indication(void *instance, void *sap,
struct irda_sock *self;
struct sock *sk;
- self = (struct irda_sock *) instance;
+ self = instance;
IRDA_DEBUG(2, "%s(%p)\n", __FUNCTION__, self);
@@ -125,7 +123,7 @@ static void irda_disconnect_indication(void *instance, void *sap,
if(skb)
dev_kfree_skb(skb);
- sk = self->sk;
+ sk = instance;
if (sk == NULL) {
IRDA_DEBUG(0, "%s(%p) : BUG : sk is NULL\n",
__FUNCTION__, self);
@@ -183,11 +181,11 @@ static void irda_connect_confirm(void *instance, void *sap,
struct irda_sock *self;
struct sock *sk;
- self = (struct irda_sock *) instance;
+ self = instance;
IRDA_DEBUG(2, "%s(%p)\n", __FUNCTION__, self);
- sk = self->sk;
+ sk = instance;
if (sk == NULL) {
dev_kfree_skb(skb);
return;
@@ -206,14 +204,16 @@ static void irda_connect_confirm(void *instance, void *sap,
switch (sk->sk_type) {
case SOCK_STREAM:
if (max_sdu_size != 0) {
- ERROR("%s: max_sdu_size must be 0\n", __FUNCTION__);
+ IRDA_ERROR("%s: max_sdu_size must be 0\n",
+ __FUNCTION__);
return;
}
self->max_data_size = irttp_get_max_seg_size(self->tsap);
break;
case SOCK_SEQPACKET:
if (max_sdu_size == 0) {
- ERROR("%s: max_sdu_size cannot be 0\n", __FUNCTION__);
+ IRDA_ERROR("%s: max_sdu_size cannot be 0\n",
+ __FUNCTION__);
return;
}
self->max_data_size = max_sdu_size;
@@ -245,11 +245,11 @@ static void irda_connect_indication(void *instance, void *sap,
struct irda_sock *self;
struct sock *sk;
- self = (struct irda_sock *) instance;
+ self = instance;
IRDA_DEBUG(2, "%s(%p)\n", __FUNCTION__, self);
- sk = self->sk;
+ sk = instance;
if (sk == NULL) {
dev_kfree_skb(skb);
return;
@@ -265,7 +265,8 @@ static void irda_connect_indication(void *instance, void *sap,
switch (sk->sk_type) {
case SOCK_STREAM:
if (max_sdu_size != 0) {
- ERROR("%s: max_sdu_size must be 0\n", __FUNCTION__);
+ IRDA_ERROR("%s: max_sdu_size must be 0\n",
+ __FUNCTION__);
kfree_skb(skb);
return;
}
@@ -273,7 +274,8 @@ static void irda_connect_indication(void *instance, void *sap,
break;
case SOCK_SEQPACKET:
if (max_sdu_size == 0) {
- ERROR("%s: max_sdu_size cannot be 0\n", __FUNCTION__);
+ IRDA_ERROR("%s: max_sdu_size cannot be 0\n",
+ __FUNCTION__);
kfree_skb(skb);
return;
}
@@ -304,7 +306,7 @@ static void irda_connect_response(struct irda_sock *self)
IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
- ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self != NULL, return;);
skb = dev_alloc_skb(64);
if (skb == NULL) {
@@ -332,11 +334,9 @@ static void irda_flow_indication(void *instance, void *sap, LOCAL_FLOW flow)
IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
- self = (struct irda_sock *) instance;
- ASSERT(self != NULL, return;);
-
- sk = self->sk;
- ASSERT(sk != NULL, return;);
+ self = instance;
+ sk = instance;
+ IRDA_ASSERT(sk != NULL, return;);
switch (flow) {
case FLOW_STOP:
@@ -373,7 +373,7 @@ static void irda_getvalue_confirm(int result, __u16 obj_id,
self = (struct irda_sock *) priv;
if (!self) {
- WARNING("%s: lost myself!\n", __FUNCTION__);
+ IRDA_WARNING("%s: lost myself!\n", __FUNCTION__);
return;
}
@@ -422,7 +422,7 @@ static void irda_selective_discovery_indication(discinfo_t *discovery,
self = (struct irda_sock *) priv;
if (!self) {
- WARNING("%s: lost myself!\n", __FUNCTION__);
+ IRDA_WARNING("%s: lost myself!\n", __FUNCTION__);
return;
}
@@ -448,7 +448,7 @@ static void irda_discovery_timeout(u_long priv)
IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
self = (struct irda_sock *) priv;
- ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self != NULL, return;);
/* Nothing for the caller */
self->cachelog = NULL;
@@ -470,7 +470,7 @@ static int irda_open_tsap(struct irda_sock *self, __u8 tsap_sel, char *name)
notify_t notify;
if (self->tsap) {
- WARNING("%s: busy!\n", __FUNCTION__);
+ IRDA_WARNING("%s: busy!\n", __FUNCTION__);
return -EBUSY;
}
@@ -510,7 +510,7 @@ static int irda_open_lsap(struct irda_sock *self, int pid)
notify_t notify;
if (self->lsap) {
- WARNING("%s(), busy!\n", __FUNCTION__);
+ IRDA_WARNING("%s(), busy!\n", __FUNCTION__);
return -EBUSY;
}
@@ -545,10 +545,11 @@ static int irda_find_lsap_sel(struct irda_sock *self, char *name)
{
IRDA_DEBUG(2, "%s(%p, %s)\n", __FUNCTION__, self, name);
- ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
if (self->iriap) {
- WARNING("%s(): busy with a previous query\n", __FUNCTION__);
+ IRDA_WARNING("%s(): busy with a previous query\n",
+ __FUNCTION__);
return -EBUSY;
}
@@ -633,7 +634,7 @@ static int irda_discover_daddr_and_lsap_sel(struct irda_sock *self, char *name)
IRDA_DEBUG(2, "%s(), name=%s\n", __FUNCTION__, name);
- ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
/* Ask lmp for the current discovery log
* Note : we have to use irlmp_get_discoveries(), as opposed
@@ -782,7 +783,7 @@ static int irda_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
struct irda_sock *self = irda_sk(sk);
int err;
- ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
IRDA_DEBUG(2, "%s(%p)\n", __FUNCTION__, self);
@@ -839,7 +840,7 @@ static int irda_accept(struct socket *sock, struct socket *newsock, int flags)
IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
- ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
err = irda_create(newsock, sk->sk_protocol);
if (err)
@@ -908,7 +909,7 @@ static int irda_accept(struct socket *sock, struct socket *newsock, int flags)
newsk->sk_state = TCP_ESTABLISHED;
new = irda_sk(newsk);
- ASSERT(new != NULL, return -1;);
+ IRDA_ASSERT(new != NULL, return -1;);
/* Now attach up the new socket */
new->tsap = irttp_dup(self->tsap, new);
@@ -1012,11 +1013,23 @@ static int irda_connect(struct socket *sock, struct sockaddr *uaddr,
self->daddr = addr->sir_addr;
IRDA_DEBUG(1, "%s(), daddr = %08x\n", __FUNCTION__, self->daddr);
- /* Query remote LM-IAS */
- err = irda_find_lsap_sel(self, addr->sir_name);
- if (err) {
- IRDA_DEBUG(0, "%s(), connect failed!\n", __FUNCTION__);
- return err;
+ /* If we don't have a valid service name, we assume the
+ * user want to connect on a specific LSAP. Prevent
+ * the use of invalid LSAPs (IrLMP 1.1 p10). Jean II */
+ if((addr->sir_name[0] != '\0') ||
+ (addr->sir_lsap_sel >= 0x70)) {
+ /* Query remote LM-IAS using service name */
+ err = irda_find_lsap_sel(self, addr->sir_name);
+ if (err) {
+ IRDA_DEBUG(0, "%s(), connect failed!\n", __FUNCTION__);
+ return err;
+ }
+ } else {
+ /* Directly connect to the remote LSAP
+ * specified by the sir_lsap field.
+ * Please use with caution, in IrDA LSAPs are
+ * dynamic and there is no "well-known" LSAP. */
+ self->dtsap_sel = addr->sir_lsap_sel;
}
}
@@ -1082,17 +1095,12 @@ static int irda_create(struct socket *sock, int protocol)
}
/* Allocate networking socket */
- if ((sk = sk_alloc(PF_IRDA, GFP_ATOMIC, 1, NULL)) == NULL)
- return -ENOMEM;
-
- /* Allocate IrDA socket */
- self = sk->sk_protinfo = kmalloc(sizeof(struct irda_sock), GFP_ATOMIC);
- if (self == NULL) {
- sk_free(sk);
+ sk = sk_alloc(PF_IRDA, GFP_ATOMIC,
+ sizeof(struct irda_sock), NULL);
+ if (sk == NULL)
return -ENOMEM;
- }
- memset(self, 0, sizeof(struct irda_sock));
+ self = irda_sk(sk);
IRDA_DEBUG(2, "%s() : self is %p\n", __FUNCTION__, self);
init_waitqueue_head(&self->query_wait);
@@ -1102,8 +1110,6 @@ static int irda_create(struct socket *sock, int protocol)
sk_set_owner(sk, THIS_MODULE);
sk->sk_family = PF_IRDA;
sk->sk_protocol = protocol;
- /* Link networking socket and IrDA socket structs together */
- self->sk = sk;
switch (sock->type) {
case SOCK_STREAM:
@@ -1131,7 +1137,8 @@ static int irda_create(struct socket *sock, int protocol)
self->max_sdu_size_rx = TTP_SAR_UNBOUND;
break;
default:
- ERROR("%s: protocol not supported!\n", __FUNCTION__);
+ IRDA_ERROR("%s: protocol not supported!\n",
+ __FUNCTION__);
return -ESOCKTNOSUPPORT;
}
break;
@@ -1159,7 +1166,7 @@ static void irda_destroy_socket(struct irda_sock *self)
{
IRDA_DEBUG(2, "%s(%p)\n", __FUNCTION__, self);
- ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self != NULL, return;);
/* Unregister with IrLMP */
irlmp_unregister_client(self->ckey);
@@ -1187,7 +1194,6 @@ static void irda_destroy_socket(struct irda_sock *self)
self->lsap = NULL;
}
#endif /* CONFIG_IRDA_ULTRA */
- kfree(self);
}
/*
@@ -1208,8 +1214,6 @@ static int irda_release(struct socket *sock)
/* Destroy IrDA socket */
irda_destroy_socket(irda_sk(sk));
- /* Prevent sock_def_destruct() to create havoc */
- sk->sk_protinfo = NULL;
sock_orphan(sk);
sock->sk = NULL;
@@ -1281,7 +1285,7 @@ static int irda_sendmsg(struct kiocb *iocb, struct socket *sock,
return -ENOTCONN;
self = irda_sk(sk);
- ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
/* Check if IrTTP is wants us to slow down */
@@ -1344,7 +1348,7 @@ static int irda_recvmsg_dgram(struct kiocb *iocb, struct socket *sock,
IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
- ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT,
flags & MSG_DONTWAIT, &err);
@@ -1396,7 +1400,7 @@ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock,
IRDA_DEBUG(3, "%s()\n", __FUNCTION__);
- ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
if (sock->flags & __SO_ACCEPTCON)
return(-EINVAL);
@@ -1533,7 +1537,7 @@ static int irda_sendmsg_dgram(struct kiocb *iocb, struct socket *sock,
return -ENOTCONN;
self = irda_sk(sk);
- ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
/*
* Check that we don't send out to big frames. This is an unreliable
@@ -1602,7 +1606,7 @@ static int irda_sendmsg_ultra(struct kiocb *iocb, struct socket *sock,
}
self = irda_sk(sk);
- ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
/* Check if an address was specified with sendto. Jean II */
if (msg->msg_name) {
@@ -1675,7 +1679,7 @@ static int irda_shutdown(struct socket *sock, int how)
struct sock *sk = sock->sk;
struct irda_sock *self = irda_sk(sk);
- ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
IRDA_DEBUG(1, "%s(%p)\n", __FUNCTION__, self);
@@ -1836,7 +1840,7 @@ static int irda_setsockopt(struct socket *sock, int level, int optname,
struct ias_attrib * ias_attr; /* Attribute in IAS object */
int opt;
- ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
IRDA_DEBUG(2, "%s(%p)\n", __FUNCTION__, self);
@@ -2021,8 +2025,8 @@ static int irda_setsockopt(struct socket *sock, int level, int optname,
__FUNCTION__, opt);
self->max_sdu_size_rx = opt;
} else {
- WARNING("%s: not allowed to set MAXSDUSIZE for this socket type!\n",
- __FUNCTION__);
+ IRDA_WARNING("%s: not allowed to set MAXSDUSIZE for this socket type!\n",
+ __FUNCTION__);
return -ENOPROTOOPT;
}
break;
@@ -2296,8 +2300,8 @@ bed:
/* Check that we can proceed with IAP */
if (self->iriap) {
- WARNING("%s: busy with a previous query\n",
- __FUNCTION__);
+ IRDA_WARNING("%s: busy with a previous query\n",
+ __FUNCTION__);
kfree(ias_opt);
return -EBUSY;
}
diff --git a/net/irda/discovery.c b/net/irda/discovery.c
index d16ef81552cf1..c4ba5fa1446a4 100644
--- a/net/irda/discovery.c
+++ b/net/irda/discovery.c
@@ -155,7 +155,7 @@ void irlmp_expire_discoveries(hashbin_t *log, __u32 saddr, int force)
int n; /* Size of the full log */
int i = 0; /* How many we expired */
- ASSERT(log != NULL, return;);
+ IRDA_ASSERT(log != NULL, return;);
IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
spin_lock_irqsave(&log->hb_spinlock, flags);
@@ -226,7 +226,7 @@ void irlmp_dump_discoveries(hashbin_t *log)
{
discovery_t *discovery;
- ASSERT(log != NULL, return;);
+ IRDA_ASSERT(log != NULL, return;);
discovery = (discovery_t *) hashbin_get_first(log);
while (discovery != NULL) {
@@ -270,8 +270,8 @@ struct irda_device_info *irlmp_copy_discoveries(hashbin_t *log, int *pn,
int n; /* Size of the full log */
int i = 0; /* How many we picked */
- ASSERT(pn != NULL, return NULL;);
- ASSERT(log != NULL, return NULL;);
+ IRDA_ASSERT(pn != NULL, return NULL;);
+ IRDA_ASSERT(log != NULL, return NULL;);
/* Save spin lock */
spin_lock_irqsave(&log->hb_spinlock, flags);
@@ -404,7 +404,7 @@ static struct seq_operations discovery_seq_ops = {
static int discovery_seq_open(struct inode *inode, struct file *file)
{
- ASSERT(irlmp != NULL, return -EINVAL;);
+ IRDA_ASSERT(irlmp != NULL, return -EINVAL;);
return seq_open(file, &discovery_seq_ops);
}
diff --git a/net/irda/ircomm/ircomm_core.c b/net/irda/ircomm/ircomm_core.c
index 36b75261d0caa..286881978858e 100644
--- a/net/irda/ircomm/ircomm_core.c
+++ b/net/irda/ircomm/ircomm_core.c
@@ -72,7 +72,7 @@ static int __init ircomm_init(void)
{
ircomm = hashbin_new(HB_LOCK);
if (ircomm == NULL) {
- ERROR("%s(), can't allocate hashbin!\n", __FUNCTION__);
+ IRDA_ERROR("%s(), can't allocate hashbin!\n", __FUNCTION__);
return -ENOMEM;
}
@@ -84,7 +84,7 @@ static int __init ircomm_init(void)
}
#endif /* CONFIG_PROC_FS */
- MESSAGE("IrCOMM protocol (Dag Brattli)\n");
+ IRDA_MESSAGE("IrCOMM protocol (Dag Brattli)\n");
return 0;
}
@@ -114,7 +114,7 @@ struct ircomm_cb *ircomm_open(notify_t *notify, __u8 service_type, int line)
IRDA_DEBUG(2, "%s(), service_type=0x%02x\n", __FUNCTION__ ,
service_type);
- ASSERT(ircomm != NULL, return NULL;);
+ IRDA_ASSERT(ircomm != NULL, return NULL;);
self = kmalloc(sizeof(struct ircomm_cb), GFP_ATOMIC);
if (self == NULL)
@@ -190,14 +190,14 @@ int ircomm_close(struct ircomm_cb *self)
{
struct ircomm_cb *entry;
- ASSERT(self != NULL, return -EIO;);
- ASSERT(self->magic == IRCOMM_MAGIC, return -EIO;);
+ IRDA_ASSERT(self != NULL, return -EIO;);
+ IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return -EIO;);
IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
entry = hashbin_remove(ircomm, self->line, NULL);
- ASSERT(entry == self, return -1;);
+ IRDA_ASSERT(entry == self, return -1;);
return __ircomm_close(self);
}
@@ -220,8 +220,8 @@ int ircomm_connect_request(struct ircomm_cb *self, __u8 dlsap_sel,
IRDA_DEBUG(2 , "%s()\n", __FUNCTION__ );
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == IRCOMM_MAGIC, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return -1;);
self->service_type= service_type;
@@ -277,8 +277,8 @@ int ircomm_connect_response(struct ircomm_cb *self, struct sk_buff *userdata)
{
int ret;
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == IRCOMM_MAGIC, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return -1;);
IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
@@ -322,9 +322,9 @@ int ircomm_data_request(struct ircomm_cb *self, struct sk_buff *skb)
IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
- ASSERT(self != NULL, return -EFAULT;);
- ASSERT(self->magic == IRCOMM_MAGIC, return -EFAULT;);
- ASSERT(skb != NULL, return -EFAULT;);
+ IRDA_ASSERT(self != NULL, return -EFAULT;);
+ IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return -EFAULT;);
+ IRDA_ASSERT(skb != NULL, return -EFAULT;);
ret = ircomm_do_event(self, IRCOMM_DATA_REQUEST, skb, NULL);
@@ -343,7 +343,7 @@ void ircomm_data_indication(struct ircomm_cb *self, struct sk_buff *skb)
{
IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
- ASSERT(skb->len > 0, return;);
+ IRDA_ASSERT(skb->len > 0, return;);
if (self->notify.data_indication)
self->notify.data_indication(self->notify.instance, self, skb);
@@ -362,7 +362,7 @@ void ircomm_process_data(struct ircomm_cb *self, struct sk_buff *skb)
{
int clen;
- ASSERT(skb->len > 0, return;);
+ IRDA_ASSERT(skb->len > 0, return;);
clen = skb->data[0];
@@ -397,9 +397,9 @@ int ircomm_control_request(struct ircomm_cb *self, struct sk_buff *skb)
IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
- ASSERT(self != NULL, return -EFAULT;);
- ASSERT(self->magic == IRCOMM_MAGIC, return -EFAULT;);
- ASSERT(skb != NULL, return -EFAULT;);
+ IRDA_ASSERT(self != NULL, return -EFAULT;);
+ IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return -EFAULT;);
+ IRDA_ASSERT(skb != NULL, return -EFAULT;);
ret = ircomm_do_event(self, IRCOMM_CONTROL_REQUEST, skb, NULL);
@@ -455,8 +455,8 @@ int ircomm_disconnect_request(struct ircomm_cb *self, struct sk_buff *userdata)
IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == IRCOMM_MAGIC, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return -1;);
ret = ircomm_do_event(self, IRCOMM_DISCONNECT_REQUEST, userdata,
&info);
@@ -476,7 +476,7 @@ void ircomm_disconnect_indication(struct ircomm_cb *self, struct sk_buff *skb,
{
IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
- ASSERT(info != NULL, return;);
+ IRDA_ASSERT(info != NULL, return;);
if (self->notify.disconnect_indication) {
self->notify.disconnect_indication(self->notify.instance, self,
@@ -496,8 +496,8 @@ void ircomm_flow_request(struct ircomm_cb *self, LOCAL_FLOW flow)
{
IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IRCOMM_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return;);
if (self->service_type == IRCOMM_3_WIRE_RAW)
return;
@@ -541,7 +541,7 @@ static int ircomm_seq_show(struct seq_file *seq, void *v)
{
const struct ircomm_cb *self = v;
- ASSERT(self->magic == IRCOMM_MAGIC, return -EINVAL; );
+ IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return -EINVAL; );
if(self->line < 0x10)
seq_printf(seq, "ircomm%d", self->line);
diff --git a/net/irda/ircomm/ircomm_lmp.c b/net/irda/ircomm/ircomm_lmp.c
index 3a0dc925a4aa4..d9097207aed3c 100644
--- a/net/irda/ircomm/ircomm_lmp.c
+++ b/net/irda/ircomm/ircomm_lmp.c
@@ -92,7 +92,8 @@ static int ircomm_lmp_connect_response(struct ircomm_cb *self,
* Check that the client has reserved enough space for
* headers
*/
- ASSERT(skb_headroom(userdata) >= LMP_MAX_HEADER, return -1;);
+ IRDA_ASSERT(skb_headroom(userdata) >= LMP_MAX_HEADER,
+ return -1;);
/* Don't forget to refcount it - should be NULL anyway */
skb_get(userdata);
@@ -144,7 +145,7 @@ static void ircomm_lmp_flow_control(struct sk_buff *skb)
struct ircomm_cb *self;
int line;
- ASSERT(skb != NULL, return;);
+ IRDA_ASSERT(skb != NULL, return;);
cb = (struct irda_skb_cb *) skb->cb;
@@ -158,8 +159,8 @@ static void ircomm_lmp_flow_control(struct sk_buff *skb)
return;
}
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IRCOMM_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return;);
self->pkt_count--;
@@ -185,7 +186,7 @@ static int ircomm_lmp_data_request(struct ircomm_cb *self,
struct irda_skb_cb *cb;
int ret;
- ASSERT(skb != NULL, return -1;);
+ IRDA_ASSERT(skb != NULL, return -1;);
cb = (struct irda_skb_cb *) skb->cb;
@@ -207,7 +208,7 @@ static int ircomm_lmp_data_request(struct ircomm_cb *self,
}
ret = irlmp_data_request(self->lsap, skb);
if (ret) {
- ERROR("%s(), failed\n", __FUNCTION__);
+ IRDA_ERROR("%s(), failed\n", __FUNCTION__);
/* irlmp_data_request already free the packet */
}
@@ -227,9 +228,9 @@ static int ircomm_lmp_data_indication(void *instance, void *sap,
IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == IRCOMM_MAGIC, return -1;);
- ASSERT(skb != NULL, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return -1;);
+ IRDA_ASSERT(skb != NULL, return -1;);
ircomm_do_event(self, IRCOMM_LMP_DATA_INDICATION, skb, NULL);
@@ -257,10 +258,10 @@ static void ircomm_lmp_connect_confirm(void *instance, void *sap,
IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IRCOMM_MAGIC, return;);
- ASSERT(skb != NULL, return;);
- ASSERT(qos != NULL, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return;);
+ IRDA_ASSERT(skb != NULL, return;);
+ IRDA_ASSERT(qos != NULL, return;);
info.max_data_size = max_seg_size;
info.max_header_size = max_header_size;
@@ -290,10 +291,10 @@ static void ircomm_lmp_connect_indication(void *instance, void *sap,
IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IRCOMM_MAGIC, return;);
- ASSERT(skb != NULL, return;);
- ASSERT(qos != NULL, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return;);
+ IRDA_ASSERT(skb != NULL, return;);
+ IRDA_ASSERT(qos != NULL, return;);
info.max_data_size = max_seg_size;
info.max_header_size = max_header_size;
@@ -320,8 +321,8 @@ static void ircomm_lmp_disconnect_indication(void *instance, void *sap,
IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IRCOMM_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return;);
info.reason = reason;
diff --git a/net/irda/ircomm/ircomm_param.c b/net/irda/ircomm/ircomm_param.c
index 703e8aa31c758..6009bab050913 100644
--- a/net/irda/ircomm/ircomm_param.c
+++ b/net/irda/ircomm/ircomm_param.c
@@ -106,8 +106,8 @@ int ircomm_param_request(struct ircomm_tty_cb *self, __u8 pi, int flush)
IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
tty = self->tty;
if (!tty)
@@ -137,7 +137,7 @@ int ircomm_param_request(struct ircomm_tty_cb *self, __u8 pi, int flush)
count = irda_param_insert(self, pi, skb->tail, skb_tailroom(skb),
&ircomm_param_info);
if (count < 0) {
- WARNING("%s(), no room for parameter!\n", __FUNCTION__);
+ IRDA_WARNING("%s(), no room for parameter!\n", __FUNCTION__);
spin_unlock_irqrestore(&self->spinlock, flags);
return -1;
}
@@ -168,8 +168,8 @@ static int ircomm_param_service_type(void *instance, irda_param_t *param,
struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
__u8 service_type = (__u8) param->pv.i;
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
if (get) {
param->pv.i = self->settings.service_type;
@@ -233,8 +233,8 @@ static int ircomm_param_port_type(void *instance, irda_param_t *param, int get)
{
struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
if (get)
param->pv.i = IRCOMM_SERIAL;
@@ -257,8 +257,8 @@ static int ircomm_param_port_name(void *instance, irda_param_t *param, int get)
{
struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
if (get) {
IRDA_DEBUG(0, "%s(), not imp!\n", __FUNCTION__ );
@@ -280,8 +280,8 @@ static int ircomm_param_data_rate(void *instance, irda_param_t *param, int get)
{
struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
if (get)
param->pv.i = self->settings.data_rate;
@@ -304,8 +304,8 @@ static int ircomm_param_data_format(void *instance, irda_param_t *param,
{
struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
if (get)
param->pv.i = self->settings.data_format;
@@ -326,8 +326,8 @@ static int ircomm_param_flow_control(void *instance, irda_param_t *param,
{
struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
if (get)
param->pv.i = self->settings.flow_control;
@@ -349,8 +349,8 @@ static int ircomm_param_xon_xoff(void *instance, irda_param_t *param, int get)
{
struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
if (get) {
param->pv.i = self->settings.xonxoff[0];
@@ -376,8 +376,8 @@ static int ircomm_param_enq_ack(void *instance, irda_param_t *param, int get)
{
struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
if (get) {
param->pv.i = self->settings.enqack[0];
@@ -418,8 +418,8 @@ static int ircomm_param_dte(void *instance, irda_param_t *param, int get)
struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
__u8 dte;
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
if (get)
param->pv.i = self->settings.dte;
@@ -467,8 +467,8 @@ static int ircomm_param_dce(void *instance, irda_param_t *param, int get)
dce = (__u8) param->pv.i;
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
self->settings.dce = dce;
@@ -494,8 +494,8 @@ static int ircomm_param_poll(void *instance, irda_param_t *param, int get)
{
struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
/* Poll parameters are always of lenght 0 (just a signal) */
if (!get) {
diff --git a/net/irda/ircomm/ircomm_ttp.c b/net/irda/ircomm/ircomm_ttp.c
index 6dafe0b0f628a..d98bf3570d290 100644
--- a/net/irda/ircomm/ircomm_ttp.c
+++ b/net/irda/ircomm/ircomm_ttp.c
@@ -172,7 +172,7 @@ static int ircomm_ttp_data_request(struct ircomm_cb *self,
{
int ret;
- ASSERT(skb != NULL, return -1;);
+ IRDA_ASSERT(skb != NULL, return -1;);
IRDA_DEBUG(2, "%s(), clen=%d\n", __FUNCTION__ , clen);
@@ -180,7 +180,7 @@ static int ircomm_ttp_data_request(struct ircomm_cb *self,
* Insert clen field, currently we either send data only, or control
* only frames, to make things easier and avoid queueing
*/
- ASSERT(skb_headroom(skb) >= IRCOMM_HEADER_SIZE, return -1;);
+ IRDA_ASSERT(skb_headroom(skb) >= IRCOMM_HEADER_SIZE, return -1;);
/* Don't forget to refcount it - see ircomm_tty_do_softint() */
skb_get(skb);
@@ -191,7 +191,7 @@ static int ircomm_ttp_data_request(struct ircomm_cb *self,
ret = irttp_data_request(self->tsap, skb);
if (ret) {
- ERROR("%s(), failed\n", __FUNCTION__);
+ IRDA_ERROR("%s(), failed\n", __FUNCTION__);
/* irttp_data_request already free the packet */
}
@@ -211,9 +211,9 @@ static int ircomm_ttp_data_indication(void *instance, void *sap,
IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == IRCOMM_MAGIC, return -1;);
- ASSERT(skb != NULL, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return -1;);
+ IRDA_ASSERT(skb != NULL, return -1;);
ircomm_do_event(self, IRCOMM_TTP_DATA_INDICATION, skb, NULL);
@@ -234,13 +234,14 @@ static void ircomm_ttp_connect_confirm(void *instance, void *sap,
IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IRCOMM_MAGIC, return;);
- ASSERT(skb != NULL, return;);
- ASSERT(qos != NULL, goto out;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return;);
+ IRDA_ASSERT(skb != NULL, return;);
+ IRDA_ASSERT(qos != NULL, goto out;);
if (max_sdu_size != TTP_SAR_DISABLE) {
- ERROR("%s(), SAR not allowed for IrCOMM!\n", __FUNCTION__);
+ IRDA_ERROR("%s(), SAR not allowed for IrCOMM!\n",
+ __FUNCTION__);
goto out;
}
@@ -274,13 +275,14 @@ static void ircomm_ttp_connect_indication(void *instance, void *sap,
IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IRCOMM_MAGIC, return;);
- ASSERT(skb != NULL, return;);
- ASSERT(qos != NULL, goto out;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return;);
+ IRDA_ASSERT(skb != NULL, return;);
+ IRDA_ASSERT(qos != NULL, goto out;);
if (max_sdu_size != TTP_SAR_DISABLE) {
- ERROR("%s(), SAR not allowed for IrCOMM!\n", __FUNCTION__);
+ IRDA_ERROR("%s(), SAR not allowed for IrCOMM!\n",
+ __FUNCTION__);
goto out;
}
@@ -332,8 +334,8 @@ static void ircomm_ttp_disconnect_indication(void *instance, void *sap,
IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IRCOMM_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return;);
info.reason = reason;
@@ -357,8 +359,8 @@ static void ircomm_ttp_flow_indication(void *instance, void *sap,
IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IRCOMM_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return;);
if (self->notify.flow_indication)
self->notify.flow_indication(self->notify.instance, self, cmd);
diff --git a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c
index f75949d277bb7..5d1e61168eb72 100644
--- a/net/irda/ircomm/ircomm_tty.c
+++ b/net/irda/ircomm/ircomm_tty.c
@@ -116,7 +116,7 @@ static int __init ircomm_tty_init(void)
return -ENOMEM;
ircomm_tty = hashbin_new(HB_LOCK);
if (ircomm_tty == NULL) {
- ERROR("%s(), can't allocate hashbin!\n", __FUNCTION__);
+ IRDA_ERROR("%s(), can't allocate hashbin!\n", __FUNCTION__);
put_tty_driver(driver);
return -ENOMEM;
}
@@ -134,7 +134,8 @@ static int __init ircomm_tty_init(void)
driver->flags = TTY_DRIVER_REAL_RAW;
tty_set_operations(driver, &ops);
if (tty_register_driver(driver)) {
- ERROR("%s(): Couldn't register serial driver\n", __FUNCTION__);
+ IRDA_ERROR("%s(): Couldn't register serial driver\n",
+ __FUNCTION__);
put_tty_driver(driver);
return -1;
}
@@ -145,8 +146,8 @@ static void __exit __ircomm_tty_cleanup(struct ircomm_tty_cb *self)
{
IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
ircomm_tty_shutdown(self);
@@ -168,7 +169,8 @@ static void __exit ircomm_tty_cleanup(void)
ret = tty_unregister_driver(driver);
if (ret) {
- ERROR("%s(), failed to unregister driver\n", __FUNCTION__);
+ IRDA_ERROR("%s(), failed to unregister driver\n",
+ __FUNCTION__);
return;
}
@@ -189,8 +191,8 @@ static int ircomm_tty_startup(struct ircomm_tty_cb *self)
IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
/* Check if already open */
if (test_and_set_bit(ASYNC_B_INITIALIZED, &self->flags)) {
@@ -224,7 +226,7 @@ static int ircomm_tty_startup(struct ircomm_tty_cb *self)
/* Connect IrCOMM link with remote device */
ret = ircomm_tty_attach_cable(self);
if (ret < 0) {
- ERROR("%s(), error attaching cable!\n", __FUNCTION__);
+ IRDA_ERROR("%s(), error attaching cable!\n", __FUNCTION__);
goto err;
}
@@ -381,7 +383,7 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp)
/* No, so make new instance */
self = kmalloc(sizeof(struct ircomm_tty_cb), GFP_KERNEL);
if (self == NULL) {
- ERROR("%s(), kmalloc failed!\n", __FUNCTION__);
+ IRDA_ERROR("%s(), kmalloc failed!\n", __FUNCTION__);
return -ENOMEM;
}
memset(self, 0, sizeof(struct ircomm_tty_cb));
@@ -442,8 +444,8 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp)
*/
if (wait_event_interruptible(self->close_wait, !test_bit(ASYNC_B_CLOSING, &self->flags))) {
- WARNING("%s - got signal while blocking on ASYNC_CLOSING!\n",
- __FUNCTION__);
+ IRDA_WARNING("%s - got signal while blocking on ASYNC_CLOSING!\n",
+ __FUNCTION__);
return -ERESTARTSYS;
}
@@ -499,8 +501,8 @@ static void ircomm_tty_close(struct tty_struct *tty, struct file *filp)
if (!tty)
return;
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
spin_lock_irqsave(&self->spinlock, flags);
@@ -526,8 +528,8 @@ static void ircomm_tty_close(struct tty_struct *tty, struct file *filp)
}
if (--self->open_count < 0) {
- ERROR("%s(), bad serial port count for ttys%d: %d\n",
- __FUNCTION__, self->line, self->open_count);
+ IRDA_ERROR("%s(), bad serial port count for ttys%d: %d\n",
+ __FUNCTION__, self->line, self->open_count);
self->open_count = 0;
}
if (self->open_count) {
@@ -586,8 +588,8 @@ static void ircomm_tty_flush_buffer(struct tty_struct *tty)
{
struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
/*
* Let do_softint() do this to avoid race condition with
@@ -671,10 +673,9 @@ static void ircomm_tty_do_softint(void *private_)
* accepted for writing. This routine is mandatory.
*/
static int ircomm_tty_write(struct tty_struct *tty,
- const unsigned char *ubuf, int count)
+ const unsigned char *buf, int count)
{
struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
- unsigned char *kbuf; /* Buffer in kernel space */
unsigned long flags;
struct sk_buff *skb;
int tailroom = 0;
@@ -684,8 +685,8 @@ static int ircomm_tty_write(struct tty_struct *tty,
IRDA_DEBUG(2, "%s(), count=%d, hw_stopped=%d\n", __FUNCTION__ , count,
tty->hw_stopped);
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
/* We may receive packets from the TTY even before we have finished
* our setup. Not cool.
@@ -714,9 +715,6 @@ static int ircomm_tty_write(struct tty_struct *tty,
if (count < 1)
return 0;
- /* The buffer is already in kernel space */
- kbuf = (unsigned char *) ubuf;
-
/* Protect our manipulation of self->tx_skb and related */
spin_lock_irqsave(&self->spinlock, flags);
@@ -779,7 +777,7 @@ static int ircomm_tty_write(struct tty_struct *tty,
}
/* Copy data */
- memcpy(skb_put(skb,size), kbuf + len, size);
+ memcpy(skb_put(skb,size), buf + len, size);
count -= size;
len += size;
@@ -812,8 +810,8 @@ static int ircomm_tty_write_room(struct tty_struct *tty)
unsigned long flags;
int ret;
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
#ifdef IRCOMM_NO_TX_BEFORE_INIT
/* max_header_size tells us if the channel is initialised or not. */
@@ -854,8 +852,8 @@ static void ircomm_tty_wait_until_sent(struct tty_struct *tty, int timeout)
IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
orig_jiffies = jiffies;
@@ -890,8 +888,8 @@ static void ircomm_tty_throttle(struct tty_struct *tty)
IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
/* Software flow control? */
if (I_IXOFF(tty))
@@ -921,8 +919,8 @@ static void ircomm_tty_unthrottle(struct tty_struct *tty)
IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
/* Using software flow control? */
if (I_IXOFF(tty)) {
@@ -951,8 +949,8 @@ static int ircomm_tty_chars_in_buffer(struct tty_struct *tty)
unsigned long flags;
int len = 0;
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
spin_lock_irqsave(&self->spinlock, flags);
@@ -968,8 +966,8 @@ static void ircomm_tty_shutdown(struct ircomm_tty_cb *self)
{
unsigned long flags;
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
@@ -1016,8 +1014,8 @@ static void ircomm_tty_hangup(struct tty_struct *tty)
IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
if (!tty)
return;
@@ -1069,8 +1067,8 @@ static void ircomm_tty_stop(struct tty_struct *tty)
{
struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
ircomm_flow_request(self->ircomm, FLOW_STOP);
}
@@ -1089,8 +1087,8 @@ void ircomm_tty_check_modem_status(struct ircomm_tty_cb *self)
IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
tty = self->tty;
@@ -1152,9 +1150,9 @@ static int ircomm_tty_data_indication(void *instance, void *sap,
IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
- ASSERT(skb != NULL, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+ IRDA_ASSERT(skb != NULL, return -1;);
if (!self->tty) {
IRDA_DEBUG(0, "%s(), no tty!\n", __FUNCTION__ );
@@ -1202,9 +1200,9 @@ static int ircomm_tty_control_indication(void *instance, void *sap,
IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
- ASSERT(skb != NULL, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+ IRDA_ASSERT(skb != NULL, return -1;);
clen = skb->data[0];
@@ -1229,8 +1227,8 @@ static void ircomm_tty_flow_indication(void *instance, void *sap,
struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
struct tty_struct *tty;
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
tty = self->tty;
diff --git a/net/irda/ircomm/ircomm_tty_attach.c b/net/irda/ircomm/ircomm_tty_attach.c
index e01be889abed8..99f5eddbb4b78 100644
--- a/net/irda/ircomm/ircomm_tty_attach.c
+++ b/net/irda/ircomm/ircomm_tty_attach.c
@@ -132,8 +132,8 @@ int ircomm_tty_attach_cable(struct ircomm_tty_cb *self)
{
IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
/* Check if somebody has already connected to us */
if (ircomm_is_connected(self->ircomm)) {
@@ -161,8 +161,8 @@ void ircomm_tty_detach_cable(struct ircomm_tty_cb *self)
{
IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
del_timer(&self->watchdog_timer);
@@ -210,8 +210,8 @@ static void ircomm_tty_ias_register(struct ircomm_tty_cb *self)
IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
/* Compute hint bits based on service */
hints = irlmp_service_to_hint(S_COMM);
@@ -299,8 +299,8 @@ static void ircomm_tty_ias_unregister(struct ircomm_tty_cb *self)
*/
int ircomm_tty_send_initial_parameters(struct ircomm_tty_cb *self)
{
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
if (self->service_type & IRCOMM_3_WIRE_RAW)
return 0;
@@ -387,7 +387,7 @@ static void ircomm_tty_discovery_indication(discinfo_t *discovery,
* need to ensure that "line" is unique. - Jean II */
self = (struct ircomm_tty_cb *) hashbin_get_first(ircomm_tty);
while (self != NULL) {
- ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+ IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
ircomm_tty_do_event(self, IRCOMM_TTY_DISCOVERY_INDICATION,
NULL, &info);
@@ -410,8 +410,8 @@ void ircomm_tty_disconnect_indication(void *instance, void *sap,
IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
if (!self->tty)
return;
@@ -440,8 +440,8 @@ static void ircomm_tty_getvalue_confirm(int result, __u16 obj_id,
IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
/* We probably don't need to make any more queries */
iriap_close(self->iriap);
@@ -501,8 +501,8 @@ void ircomm_tty_connect_confirm(void *instance, void *sap,
IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
self->client = TRUE;
self->max_data_size = max_data_size;
@@ -532,8 +532,8 @@ void ircomm_tty_connect_indication(void *instance, void *sap,
IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
self->client = FALSE;
self->max_data_size = max_data_size;
@@ -561,8 +561,8 @@ void ircomm_tty_link_established(struct ircomm_tty_cb *self)
{
IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
if (!self->tty)
return;
@@ -600,8 +600,8 @@ void ircomm_tty_link_established(struct ircomm_tty_cb *self)
static void ircomm_tty_start_watchdog_timer(struct ircomm_tty_cb *self,
int timeout)
{
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
irda_start_timer(&self->watchdog_timer, timeout, (void *) self,
ircomm_tty_watchdog_timer_expired);
@@ -619,8 +619,8 @@ static void ircomm_tty_watchdog_timer_expired(void *data)
IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
ircomm_tty_do_event(self, IRCOMM_TTY_WD_TIMER_EXPIRED, NULL, NULL);
}
@@ -635,8 +635,8 @@ static void ircomm_tty_watchdog_timer_expired(void *data)
int ircomm_tty_do_event(struct ircomm_tty_cb *self, IRCOMM_TTY_EVENT event,
struct sk_buff *skb, struct ircomm_tty_info *info)
{
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
IRDA_DEBUG(2, "%s: state=%s, event=%s\n", __FUNCTION__ ,
ircomm_tty_state[self->state], ircomm_tty_event[event]);
@@ -653,8 +653,8 @@ int ircomm_tty_do_event(struct ircomm_tty_cb *self, IRCOMM_TTY_EVENT event,
static inline void ircomm_tty_next_state(struct ircomm_tty_cb *self, IRCOMM_TTY_STATE state)
{
/*
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
IRDA_DEBUG(2, "%s: next state=%s, service type=%d\n", __FUNCTION__ ,
ircomm_tty_state[self->state], self->service_type);
@@ -690,7 +690,8 @@ static int ircomm_tty_state_idle(struct ircomm_tty_cb *self,
self->saddr = info->saddr;
if (self->iriap) {
- WARNING("%s(), busy with a previous query\n", __FUNCTION__);
+ IRDA_WARNING("%s(), busy with a previous query\n",
+ __FUNCTION__);
return -EBUSY;
}
@@ -747,7 +748,8 @@ static int ircomm_tty_state_search(struct ircomm_tty_cb *self,
self->saddr = info->saddr;
if (self->iriap) {
- WARNING("%s(), busy with a previous query\n", __FUNCTION__);
+ IRDA_WARNING("%s(), busy with a previous query\n",
+ __FUNCTION__);
return -EBUSY;
}
@@ -816,7 +818,8 @@ static int ircomm_tty_state_query_parameters(struct ircomm_tty_cb *self,
switch (event) {
case IRCOMM_TTY_GOT_PARAMETERS:
if (self->iriap) {
- WARNING("%s(), busy with a previous query\n", __FUNCTION__);
+ IRDA_WARNING("%s(), busy with a previous query\n",
+ __FUNCTION__);
return -EBUSY;
}
diff --git a/net/irda/ircomm/ircomm_tty_ioctl.c b/net/irda/ircomm/ircomm_tty_ioctl.c
index 001611d3302ed..197e3e7ed7e2d 100644
--- a/net/irda/ircomm/ircomm_tty_ioctl.c
+++ b/net/irda/ircomm/ircomm_tty_ioctl.c
@@ -95,7 +95,7 @@ static void ircomm_tty_change_speed(struct ircomm_tty_cb *self)
self->settings.flow_control |= IRCOMM_RTS_CTS_IN;
/* This got me. Bummer. Jean II */
if (self->service_type == IRCOMM_3_WIRE_RAW)
- WARNING("%s(), enabling RTS/CTS on link that doesn't support it (3-wire-raw)\n", __FUNCTION__);
+ IRDA_WARNING("%s(), enabling RTS/CTS on link that doesn't support it (3-wire-raw)\n", __FUNCTION__);
} else {
self->flags &= ~ASYNC_CTS_FLOW;
self->settings.flow_control &= ~IRCOMM_RTS_CTS_IN;
@@ -230,8 +230,8 @@ int ircomm_tty_tiocmset(struct tty_struct *tty, struct file *file,
if (tty->flags & (1 << TTY_IO_ERROR))
return -EIO;
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
if (set & TIOCM_RTS)
self->settings.dte |= IRCOMM_RTS;
diff --git a/net/irda/irda_device.c b/net/irda/irda_device.c
index cf5a849bf4c01..fda299e300c08 100644
--- a/net/irda/irda_device.c
+++ b/net/irda/irda_device.c
@@ -77,14 +77,14 @@ int __init irda_device_init( void)
{
dongles = hashbin_new(HB_NOLOCK);
if (dongles == NULL) {
- printk(KERN_WARNING "IrDA: Can't allocate dongles hashbin!\n");
+ IRDA_WARNING("IrDA: Can't allocate dongles hashbin!\n");
return -ENOMEM;
}
spin_lock_init(&dongles->hb_spinlock);
tasks = hashbin_new(HB_LOCK);
if (tasks == NULL) {
- printk(KERN_WARNING "IrDA: Can't allocate tasks hashbin!\n");
+ IRDA_WARNING("IrDA: Can't allocate tasks hashbin!\n");
hashbin_delete(dongles, NULL);
return -ENOMEM;
}
@@ -98,8 +98,8 @@ int __init irda_device_init( void)
static void __exit leftover_dongle(void *arg)
{
struct dongle_reg *reg = arg;
- printk(KERN_WARNING "IrDA: Dongle type %x not unregistered\n",
- reg->type);
+ IRDA_WARNING("IrDA: Dongle type %x not unregistered\n",
+ reg->type);
}
void __exit irda_device_cleanup(void)
@@ -125,8 +125,8 @@ void irda_device_set_media_busy(struct net_device *dev, int status)
self = (struct irlap_cb *) dev->atalk_ptr;
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LAP_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
if (status) {
self->media_busy = TRUE;
@@ -157,8 +157,8 @@ int irda_device_is_receiving(struct net_device *dev)
IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
if (!dev->do_ioctl) {
- ERROR("%s: do_ioctl not impl. by device driver\n",
- __FUNCTION__);
+ IRDA_ERROR("%s: do_ioctl not impl. by device driver\n",
+ __FUNCTION__);
return -1;
}
@@ -209,21 +209,22 @@ static int irda_task_kick(struct irda_task *task)
IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
- ASSERT(task != NULL, return -1;);
- ASSERT(task->magic == IRDA_TASK_MAGIC, return -1;);
+ IRDA_ASSERT(task != NULL, return -1;);
+ IRDA_ASSERT(task->magic == IRDA_TASK_MAGIC, return -1;);
/* Execute task until it's finished, or askes for a timeout */
do {
timeout = task->function(task);
if (count++ > 100) {
- ERROR("%s: error in task handler!\n", __FUNCTION__);
+ IRDA_ERROR("%s: error in task handler!\n",
+ __FUNCTION__);
irda_task_delete(task);
return TRUE;
}
} while ((timeout == 0) && (task->state != IRDA_TASK_DONE));
if (timeout < 0) {
- ERROR("%s: Error executing task!\n", __FUNCTION__);
+ IRDA_ERROR("%s: Error executing task!\n", __FUNCTION__);
irda_task_delete(task);
return TRUE;
}
@@ -387,7 +388,8 @@ dongle_t *irda_device_dongle_init(struct net_device *dev, int type)
#endif
if (!reg || !try_module_get(reg->owner) ) {
- ERROR("IrDA: Unable to find requested dongle type %x\n", type);
+ IRDA_ERROR("IrDA: Unable to find requested dongle type %x\n",
+ type);
goto out;
}
@@ -413,7 +415,7 @@ EXPORT_SYMBOL(irda_device_dongle_init);
*/
int irda_device_dongle_cleanup(dongle_t *dongle)
{
- ASSERT(dongle != NULL, return -1;);
+ IRDA_ASSERT(dongle != NULL, return -1;);
dongle->issue->close(dongle);
module_put(dongle->issue->owner);
@@ -431,8 +433,8 @@ int irda_device_register_dongle(struct dongle_reg *new)
spin_lock(&dongles->hb_spinlock);
/* Check if this dongle has been registered before */
if (hashbin_find(dongles, new->type, NULL)) {
- MESSAGE("%s: Dongle type %x already registered\n",
- __FUNCTION__, new->type);
+ IRDA_MESSAGE("%s: Dongle type %x already registered\n",
+ __FUNCTION__, new->type);
} else {
/* Insert IrDA dongle into hashbin */
hashbin_insert(dongles, (irda_queue_t *) new, new->type, NULL);
@@ -456,7 +458,7 @@ void irda_device_unregister_dongle(struct dongle_reg *dongle)
spin_lock(&dongles->hb_spinlock);
node = hashbin_remove(dongles, dongle->type, NULL);
if (!node)
- ERROR("%s: dongle not found!\n", __FUNCTION__);
+ IRDA_ERROR("%s: dongle not found!\n", __FUNCTION__);
spin_unlock(&dongles->hb_spinlock);
}
EXPORT_SYMBOL(irda_device_unregister_dongle);
diff --git a/net/irda/iriap.c b/net/irda/iriap.c
index f22993c24ea86..b8bb78af8b8a2 100644
--- a/net/irda/iriap.c
+++ b/net/irda/iriap.c
@@ -107,8 +107,8 @@ int __init iriap_init(void)
/* Object repository - defined in irias_object.c */
irias_objects = hashbin_new(HB_LOCK);
if (!irias_objects) {
- WARNING("%s: Can't allocate irias_objects hashbin!\n",
- __FUNCTION__);
+ IRDA_WARNING("%s: Can't allocate irias_objects hashbin!\n",
+ __FUNCTION__);
hashbin_delete(iriap, NULL);
return -ENOMEM;
}
@@ -175,7 +175,7 @@ struct iriap_cb *iriap_open(__u8 slsap_sel, int mode, void *priv,
self = kmalloc(sizeof(struct iriap_cb), GFP_ATOMIC);
if (!self) {
- WARNING("%s: Unable to kmalloc!\n", __FUNCTION__);
+ IRDA_WARNING("%s: Unable to kmalloc!\n", __FUNCTION__);
return NULL;
}
@@ -220,8 +220,8 @@ static void __iriap_close(struct iriap_cb *self)
{
IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IAS_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
del_timer(&self->watchdog_timer);
@@ -244,8 +244,8 @@ void iriap_close(struct iriap_cb *self)
IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IAS_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
if (self->lsap) {
irlmp_close_lsap(self->lsap);
@@ -253,7 +253,7 @@ void iriap_close(struct iriap_cb *self)
}
entry = (struct iriap_cb *) hashbin_remove(iriap, (long) self, NULL);
- ASSERT(entry == self, return;);
+ IRDA_ASSERT(entry == self, return;);
__iriap_close(self);
}
@@ -278,7 +278,7 @@ static int iriap_register_lsap(struct iriap_cb *self, __u8 slsap_sel, int mode)
self->lsap = irlmp_open_lsap(slsap_sel, &notify, 0);
if (self->lsap == NULL) {
- ERROR("%s: Unable to allocated LSAP!\n", __FUNCTION__);
+ IRDA_ERROR("%s: Unable to allocated LSAP!\n", __FUNCTION__);
return -1;
}
self->slsap_sel = self->lsap->slsap_sel;
@@ -302,10 +302,10 @@ static void iriap_disconnect_indication(void *instance, void *sap,
self = (struct iriap_cb *) instance;
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IAS_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
- ASSERT(iriap != NULL, return;);
+ IRDA_ASSERT(iriap != NULL, return;);
del_timer(&self->watchdog_timer);
@@ -343,8 +343,8 @@ static void iriap_disconnect_request(struct iriap_cb *self)
IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IAS_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
tx_skb = dev_alloc_skb(64);
if (tx_skb == NULL) {
@@ -375,8 +375,8 @@ int iriap_getvaluebyclass_request(struct iriap_cb *self,
int name_len, attr_len, skb_len;
__u8 *frame;
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == IAS_MAGIC, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == IAS_MAGIC, return -1;);
/* Client must supply the destination device address */
if (!daddr)
@@ -442,9 +442,9 @@ static void iriap_getvaluebyclass_confirm(struct iriap_cb *self,
__u8 *fp;
int n;
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IAS_MAGIC, return;);
- ASSERT(skb != NULL, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
+ IRDA_ASSERT(skb != NULL, return;);
/* Initialize variables */
fp = skb->data;
@@ -549,10 +549,10 @@ static void iriap_getvaluebyclass_response(struct iriap_cb *self,
IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IAS_MAGIC, return;);
- ASSERT(value != NULL, return;);
- ASSERT(value->len <= 1024, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
+ IRDA_ASSERT(value != NULL, return;);
+ IRDA_ASSERT(value->len <= 1024, return;);
/* Initialize variables */
n = 0;
@@ -642,9 +642,9 @@ static void iriap_getvaluebyclass_indication(struct iriap_cb *self,
IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IAS_MAGIC, return;);
- ASSERT(skb != NULL, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
+ IRDA_ASSERT(skb != NULL, return;);
fp = skb->data;
n = 1;
@@ -697,8 +697,8 @@ void iriap_send_ack(struct iriap_cb *self)
IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IAS_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
tx_skb = dev_alloc_skb(64);
if (!tx_skb)
@@ -719,8 +719,8 @@ void iriap_connect_request(struct iriap_cb *self)
{
int ret;
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IAS_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
ret = irlmp_connect_request(self->lsap, LSAP_IAS,
self->saddr, self->daddr,
@@ -746,9 +746,9 @@ static void iriap_connect_confirm(void *instance, void *sap,
self = (struct iriap_cb *) instance;
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IAS_MAGIC, return;);
- ASSERT(skb != NULL, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
+ IRDA_ASSERT(skb != NULL, return;);
self->max_data_size = max_seg_size;
self->max_header_size = max_header_size;
@@ -778,9 +778,9 @@ static void iriap_connect_indication(void *instance, void *sap,
self = (struct iriap_cb *) instance;
- ASSERT(skb != NULL, return;);
- ASSERT(self != NULL, goto out;);
- ASSERT(self->magic == IAS_MAGIC, goto out;);
+ IRDA_ASSERT(skb != NULL, return;);
+ IRDA_ASSERT(self != NULL, goto out;);
+ IRDA_ASSERT(self->magic == IAS_MAGIC, goto out;);
/* Start new server */
new = iriap_open(LSAP_IAS, IAS_SERVER, NULL, NULL);
@@ -826,9 +826,9 @@ static int iriap_data_indication(void *instance, void *sap,
self = (struct iriap_cb *) instance;
- ASSERT(skb != NULL, return 0;);
- ASSERT(self != NULL, goto out;);
- ASSERT(self->magic == IAS_MAGIC, goto out;);
+ IRDA_ASSERT(skb != NULL, return 0;);
+ IRDA_ASSERT(self != NULL, goto out;);
+ IRDA_ASSERT(self->magic == IAS_MAGIC, goto out;);
frame = skb->data;
@@ -840,8 +840,9 @@ static int iriap_data_indication(void *instance, void *sap,
}
opcode = frame[0];
if (~opcode & IAP_LST) {
- WARNING("%s:, IrIAS multiframe commands or "
- "results is not implemented yet!\n", __FUNCTION__);
+ IRDA_WARNING("%s:, IrIAS multiframe commands or "
+ "results is not implemented yet!\n",
+ __FUNCTION__);
goto out;
}
@@ -917,24 +918,24 @@ void iriap_call_indication(struct iriap_cb *self, struct sk_buff *skb)
IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IAS_MAGIC, return;);
- ASSERT(skb != NULL, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
+ IRDA_ASSERT(skb != NULL, return;);
fp = skb->data;
opcode = fp[0];
if (~opcode & 0x80) {
- WARNING("%s: IrIAS multiframe commands or results"
- "is not implemented yet!\n", __FUNCTION__);
+ IRDA_WARNING("%s: IrIAS multiframe commands or results"
+ "is not implemented yet!\n", __FUNCTION__);
return;
}
opcode &= 0x7f; /* Mask away LST bit */
switch (opcode) {
case GET_INFO_BASE:
- WARNING("%s: GetInfoBaseDetails not implemented yet!\n",
- __FUNCTION__);
+ IRDA_WARNING("%s: GetInfoBaseDetails not implemented yet!\n",
+ __FUNCTION__);
break;
case GET_VALUE_BY_CLASS:
iriap_getvaluebyclass_indication(self, skb);
@@ -953,8 +954,8 @@ static void iriap_watchdog_timer_expired(void *data)
{
struct iriap_cb *self = (struct iriap_cb *) data;
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IAS_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
/* iriap_close(self); */
}
@@ -1010,7 +1011,7 @@ static int irias_seq_show(struct seq_file *seq, void *v)
struct ias_object *obj = v;
struct ias_attrib *attrib;
- ASSERT(obj->magic == IAS_OBJECT_MAGIC, return -EINVAL;);
+ IRDA_ASSERT(obj->magic == IAS_OBJECT_MAGIC, return -EINVAL;);
seq_printf(seq, "name: %s, id=%d\n",
obj->name, obj->id);
@@ -1025,7 +1026,8 @@ static int irias_seq_show(struct seq_file *seq, void *v)
attrib != NULL;
attrib = (struct ias_attrib *) hashbin_get_next(obj->attribs)) {
- ASSERT(attrib->magic == IAS_ATTRIB_MAGIC, break; );
+ IRDA_ASSERT(attrib->magic == IAS_ATTRIB_MAGIC,
+ goto outloop; );
seq_printf(seq, " - Attribute name: \"%s\", ",
attrib->name);
@@ -1055,6 +1057,7 @@ static int irias_seq_show(struct seq_file *seq, void *v)
seq_putc(seq, '\n');
}
+ IRDA_ASSERT_LABEL(outloop:)
spin_unlock(&obj->attribs->hb_spinlock);
}
@@ -1070,7 +1073,7 @@ static struct seq_operations irias_seq_ops = {
static int irias_seq_open(struct inode *inode, struct file *file)
{
- ASSERT( irias_objects != NULL, return -EINVAL;);
+ IRDA_ASSERT( irias_objects != NULL, return -EINVAL;);
return seq_open(file, &irias_seq_ops);
}
diff --git a/net/irda/iriap_event.c b/net/irda/iriap_event.c
index ce209ad44eafd..a73607450de1b 100644
--- a/net/irda/iriap_event.c
+++ b/net/irda/iriap_event.c
@@ -93,32 +93,32 @@ static void (*iriap_state[])(struct iriap_cb *self, IRIAP_EVENT event,
void iriap_next_client_state(struct iriap_cb *self, IRIAP_STATE state)
{
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IAS_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
self->client_state = state;
}
void iriap_next_call_state(struct iriap_cb *self, IRIAP_STATE state)
{
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IAS_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
self->call_state = state;
}
void iriap_next_server_state(struct iriap_cb *self, IRIAP_STATE state)
{
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IAS_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
self->server_state = state;
}
void iriap_next_r_connect_state(struct iriap_cb *self, IRIAP_STATE state)
{
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IAS_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
self->r_connect_state = state;
}
@@ -126,8 +126,8 @@ void iriap_next_r_connect_state(struct iriap_cb *self, IRIAP_STATE state)
void iriap_do_client_event(struct iriap_cb *self, IRIAP_EVENT event,
struct sk_buff *skb)
{
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IAS_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
(*iriap_state[ self->client_state]) (self, event, skb);
}
@@ -135,8 +135,8 @@ void iriap_do_client_event(struct iriap_cb *self, IRIAP_EVENT event,
void iriap_do_call_event(struct iriap_cb *self, IRIAP_EVENT event,
struct sk_buff *skb)
{
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IAS_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
(*iriap_state[ self->call_state]) (self, event, skb);
}
@@ -144,8 +144,8 @@ void iriap_do_call_event(struct iriap_cb *self, IRIAP_EVENT event,
void iriap_do_server_event(struct iriap_cb *self, IRIAP_EVENT event,
struct sk_buff *skb)
{
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IAS_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
(*iriap_state[ self->server_state]) (self, event, skb);
}
@@ -153,8 +153,8 @@ void iriap_do_server_event(struct iriap_cb *self, IRIAP_EVENT event,
void iriap_do_r_connect_event(struct iriap_cb *self, IRIAP_EVENT event,
struct sk_buff *skb)
{
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IAS_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
(*iriap_state[ self->r_connect_state]) (self, event, skb);
}
@@ -169,13 +169,13 @@ void iriap_do_r_connect_event(struct iriap_cb *self, IRIAP_EVENT event,
static void state_s_disconnect(struct iriap_cb *self, IRIAP_EVENT event,
struct sk_buff *skb)
{
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IAS_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
switch (event) {
case IAP_CALL_REQUEST_GVBC:
iriap_next_client_state(self, S_CONNECTING);
- ASSERT(self->request_skb == NULL, return;);
+ IRDA_ASSERT(self->request_skb == NULL, return;);
/* Don't forget to refcount it -
* see iriap_getvaluebyclass_request(). */
skb_get(skb);
@@ -199,8 +199,8 @@ static void state_s_disconnect(struct iriap_cb *self, IRIAP_EVENT event,
static void state_s_connecting(struct iriap_cb *self, IRIAP_EVENT event,
struct sk_buff *skb)
{
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IAS_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
switch (event) {
case IAP_LM_CONNECT_CONFIRM:
@@ -232,7 +232,7 @@ static void state_s_connecting(struct iriap_cb *self, IRIAP_EVENT event,
static void state_s_call(struct iriap_cb *self, IRIAP_EVENT event,
struct sk_buff *skb)
{
- ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self != NULL, return;);
switch (event) {
case IAP_LM_DISCONNECT_INDICATION:
@@ -257,7 +257,7 @@ static void state_s_make_call(struct iriap_cb *self, IRIAP_EVENT event,
{
struct sk_buff *tx_skb;
- ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self != NULL, return;);
switch (event) {
case IAP_CALL_REQUEST:
@@ -295,7 +295,7 @@ static void state_s_calling(struct iriap_cb *self, IRIAP_EVENT event,
static void state_s_outstanding(struct iriap_cb *self, IRIAP_EVENT event,
struct sk_buff *skb)
{
- ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self != NULL, return;);
switch (event) {
case IAP_RECV_F_LST:
@@ -367,7 +367,7 @@ static void state_r_disconnect(struct iriap_cb *self, IRIAP_EVENT event,
case IAP_LM_CONNECT_INDICATION:
tx_skb = dev_alloc_skb(64);
if (tx_skb == NULL) {
- WARNING("%s: unable to malloc!\n", __FUNCTION__);
+ IRDA_WARNING("%s: unable to malloc!\n", __FUNCTION__);
return;
}
@@ -464,9 +464,9 @@ static void state_r_execute(struct iriap_cb *self, IRIAP_EVENT event,
{
IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
- ASSERT(skb != NULL, return;);
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IAS_MAGIC, return;);
+ IRDA_ASSERT(skb != NULL, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
switch (event) {
case IAP_CALL_RESPONSE:
diff --git a/net/irda/irias_object.c b/net/irda/irias_object.c
index 98c9e1517a2f1..6fec428b45123 100644
--- a/net/irda/irias_object.c
+++ b/net/irda/irias_object.c
@@ -59,7 +59,7 @@ static char *strndup(char *str, int max)
/* Allocate new string */
new_str = kmalloc(len + 1, GFP_ATOMIC);
if (new_str == NULL) {
- WARNING("%s: Unable to kmalloc!\n", __FUNCTION__);
+ IRDA_WARNING("%s: Unable to kmalloc!\n", __FUNCTION__);
return NULL;
}
@@ -85,8 +85,8 @@ struct ias_object *irias_new_object( char *name, int id)
obj = (struct ias_object *) kmalloc(sizeof(struct ias_object),
GFP_ATOMIC);
if (obj == NULL) {
- WARNING("%s(), Unable to allocate object!\n",
- __FUNCTION__);
+ IRDA_WARNING("%s(), Unable to allocate object!\n",
+ __FUNCTION__);
return NULL;
}
memset(obj, 0, sizeof( struct ias_object));
@@ -101,7 +101,8 @@ struct ias_object *irias_new_object( char *name, int id)
obj->attribs = hashbin_new(HB_LOCK);
if (obj->attribs == NULL) {
- WARNING("%s(), Unable to allocate attribs!\n", __FUNCTION__);
+ IRDA_WARNING("%s(), Unable to allocate attribs!\n",
+ __FUNCTION__);
kfree(obj);
return NULL;
}
@@ -118,8 +119,8 @@ EXPORT_SYMBOL(irias_new_object);
*/
static void __irias_delete_attrib(struct ias_attrib *attrib)
{
- ASSERT(attrib != NULL, return;);
- ASSERT(attrib->magic == IAS_ATTRIB_MAGIC, return;);
+ IRDA_ASSERT(attrib != NULL, return;);
+ IRDA_ASSERT(attrib->magic == IAS_ATTRIB_MAGIC, return;);
if (attrib->name)
kfree(attrib->name);
@@ -132,8 +133,8 @@ static void __irias_delete_attrib(struct ias_attrib *attrib)
void __irias_delete_object(struct ias_object *obj)
{
- ASSERT(obj != NULL, return;);
- ASSERT(obj->magic == IAS_OBJECT_MAGIC, return;);
+ IRDA_ASSERT(obj != NULL, return;);
+ IRDA_ASSERT(obj->magic == IAS_OBJECT_MAGIC, return;);
if (obj->name)
kfree(obj->name);
@@ -156,8 +157,8 @@ int irias_delete_object(struct ias_object *obj)
{
struct ias_object *node;
- ASSERT(obj != NULL, return -1;);
- ASSERT(obj->magic == IAS_OBJECT_MAGIC, return -1;);
+ IRDA_ASSERT(obj != NULL, return -1;);
+ IRDA_ASSERT(obj->magic == IAS_OBJECT_MAGIC, return -1;);
/* Remove from list */
node = hashbin_remove_this(irias_objects, (irda_queue_t *) obj);
@@ -184,9 +185,9 @@ int irias_delete_attrib(struct ias_object *obj, struct ias_attrib *attrib,
{
struct ias_attrib *node;
- ASSERT(obj != NULL, return -1;);
- ASSERT(obj->magic == IAS_OBJECT_MAGIC, return -1;);
- ASSERT(attrib != NULL, return -1;);
+ IRDA_ASSERT(obj != NULL, return -1;);
+ IRDA_ASSERT(obj->magic == IAS_OBJECT_MAGIC, return -1;);
+ IRDA_ASSERT(attrib != NULL, return -1;);
/* Remove attribute from object */
node = hashbin_remove_this(obj->attribs, (irda_queue_t *) attrib);
@@ -216,8 +217,8 @@ int irias_delete_attrib(struct ias_object *obj, struct ias_attrib *attrib,
*/
void irias_insert_object(struct ias_object *obj)
{
- ASSERT(obj != NULL, return;);
- ASSERT(obj->magic == IAS_OBJECT_MAGIC, return;);
+ IRDA_ASSERT(obj != NULL, return;);
+ IRDA_ASSERT(obj->magic == IAS_OBJECT_MAGIC, return;);
hashbin_insert(irias_objects, (irda_queue_t *) obj, 0, obj->name);
}
@@ -231,7 +232,7 @@ EXPORT_SYMBOL(irias_insert_object);
*/
struct ias_object *irias_find_object(char *name)
{
- ASSERT(name != NULL, return NULL;);
+ IRDA_ASSERT(name != NULL, return NULL;);
/* Unsafe (locking), object might change */
return hashbin_lock_find(irias_objects, 0, name);
@@ -248,9 +249,9 @@ struct ias_attrib *irias_find_attrib(struct ias_object *obj, char *name)
{
struct ias_attrib *attrib;
- ASSERT(obj != NULL, return NULL;);
- ASSERT(obj->magic == IAS_OBJECT_MAGIC, return NULL;);
- ASSERT(name != NULL, return NULL;);
+ IRDA_ASSERT(obj != NULL, return NULL;);
+ IRDA_ASSERT(obj->magic == IAS_OBJECT_MAGIC, return NULL;);
+ IRDA_ASSERT(name != NULL, return NULL;);
attrib = hashbin_lock_find(obj->attribs, 0, name);
if (attrib == NULL)
@@ -270,11 +271,11 @@ EXPORT_SYMBOL(irias_find_attrib);
static void irias_add_attrib(struct ias_object *obj, struct ias_attrib *attrib,
int owner)
{
- ASSERT(obj != NULL, return;);
- ASSERT(obj->magic == IAS_OBJECT_MAGIC, return;);
+ IRDA_ASSERT(obj != NULL, return;);
+ IRDA_ASSERT(obj->magic == IAS_OBJECT_MAGIC, return;);
- ASSERT(attrib != NULL, return;);
- ASSERT(attrib->magic == IAS_ATTRIB_MAGIC, return;);
+ IRDA_ASSERT(attrib != NULL, return;);
+ IRDA_ASSERT(attrib->magic == IAS_ATTRIB_MAGIC, return;);
/* Set if attrib is owned by kernel or user space */
attrib->value->owner = owner;
@@ -298,8 +299,8 @@ int irias_object_change_attribute(char *obj_name, char *attrib_name,
/* Find object */
obj = hashbin_lock_find(irias_objects, 0, obj_name);
if (obj == NULL) {
- WARNING("%s: Unable to find object: %s\n", __FUNCTION__,
- obj_name);
+ IRDA_WARNING("%s: Unable to find object: %s\n", __FUNCTION__,
+ obj_name);
return -1;
}
@@ -309,8 +310,8 @@ int irias_object_change_attribute(char *obj_name, char *attrib_name,
/* Find attribute */
attrib = hashbin_find(obj->attribs, 0, attrib_name);
if (attrib == NULL) {
- WARNING("%s: Unable to find attribute: %s\n", __FUNCTION__,
- attrib_name);
+ IRDA_WARNING("%s: Unable to find attribute: %s\n",
+ __FUNCTION__, attrib_name);
spin_unlock_irqrestore(&obj->attribs->hb_spinlock, flags);
return -1;
}
@@ -345,14 +346,15 @@ void irias_add_integer_attrib(struct ias_object *obj, char *name, int value,
{
struct ias_attrib *attrib;
- ASSERT(obj != NULL, return;);
- ASSERT(obj->magic == IAS_OBJECT_MAGIC, return;);
- ASSERT(name != NULL, return;);
+ IRDA_ASSERT(obj != NULL, return;);
+ IRDA_ASSERT(obj->magic == IAS_OBJECT_MAGIC, return;);
+ IRDA_ASSERT(name != NULL, return;);
attrib = (struct ias_attrib *) kmalloc(sizeof(struct ias_attrib),
GFP_ATOMIC);
if (attrib == NULL) {
- WARNING("%s: Unable to allocate attribute!\n", __FUNCTION__);
+ IRDA_WARNING("%s: Unable to allocate attribute!\n",
+ __FUNCTION__);
return;
}
memset(attrib, 0, sizeof( struct ias_attrib));
@@ -379,16 +381,17 @@ void irias_add_octseq_attrib(struct ias_object *obj, char *name, __u8 *octets,
{
struct ias_attrib *attrib;
- ASSERT(obj != NULL, return;);
- ASSERT(obj->magic == IAS_OBJECT_MAGIC, return;);
+ IRDA_ASSERT(obj != NULL, return;);
+ IRDA_ASSERT(obj->magic == IAS_OBJECT_MAGIC, return;);
- ASSERT(name != NULL, return;);
- ASSERT(octets != NULL, return;);
+ IRDA_ASSERT(name != NULL, return;);
+ IRDA_ASSERT(octets != NULL, return;);
attrib = (struct ias_attrib *) kmalloc(sizeof(struct ias_attrib),
GFP_ATOMIC);
if (attrib == NULL) {
- WARNING("%s: Unable to allocate attribute!\n", __FUNCTION__);
+ IRDA_WARNING("%s: Unable to allocate attribute!\n",
+ __FUNCTION__);
return;
}
memset(attrib, 0, sizeof( struct ias_attrib));
@@ -413,16 +416,17 @@ void irias_add_string_attrib(struct ias_object *obj, char *name, char *value,
{
struct ias_attrib *attrib;
- ASSERT(obj != NULL, return;);
- ASSERT(obj->magic == IAS_OBJECT_MAGIC, return;);
+ IRDA_ASSERT(obj != NULL, return;);
+ IRDA_ASSERT(obj->magic == IAS_OBJECT_MAGIC, return;);
- ASSERT(name != NULL, return;);
- ASSERT(value != NULL, return;);
+ IRDA_ASSERT(name != NULL, return;);
+ IRDA_ASSERT(value != NULL, return;);
attrib = (struct ias_attrib *) kmalloc(sizeof( struct ias_attrib),
GFP_ATOMIC);
if (attrib == NULL) {
- WARNING("%s: Unable to allocate attribute!\n", __FUNCTION__);
+ IRDA_WARNING("%s: Unable to allocate attribute!\n",
+ __FUNCTION__);
return;
}
memset(attrib, 0, sizeof( struct ias_attrib));
@@ -448,7 +452,7 @@ struct ias_value *irias_new_integer_value(int integer)
value = kmalloc(sizeof(struct ias_value), GFP_ATOMIC);
if (value == NULL) {
- WARNING("%s: Unable to kmalloc!\n", __FUNCTION__);
+ IRDA_WARNING("%s: Unable to kmalloc!\n", __FUNCTION__);
return NULL;
}
memset(value, 0, sizeof(struct ias_value));
@@ -474,7 +478,7 @@ struct ias_value *irias_new_string_value(char *string)
value = kmalloc(sizeof(struct ias_value), GFP_ATOMIC);
if (value == NULL) {
- WARNING("%s: Unable to kmalloc!\n", __FUNCTION__);
+ IRDA_WARNING("%s: Unable to kmalloc!\n", __FUNCTION__);
return NULL;
}
memset( value, 0, sizeof( struct ias_value));
@@ -501,7 +505,7 @@ struct ias_value *irias_new_octseq_value(__u8 *octseq , int len)
value = kmalloc(sizeof(struct ias_value), GFP_ATOMIC);
if (value == NULL) {
- WARNING("%s: Unable to kmalloc!\n", __FUNCTION__);
+ IRDA_WARNING("%s: Unable to kmalloc!\n", __FUNCTION__);
return NULL;
}
memset(value, 0, sizeof(struct ias_value));
@@ -514,7 +518,7 @@ struct ias_value *irias_new_octseq_value(__u8 *octseq , int len)
value->t.oct_seq = kmalloc(len, GFP_ATOMIC);
if (value->t.oct_seq == NULL){
- WARNING("%s: Unable to kmalloc!\n", __FUNCTION__);
+ IRDA_WARNING("%s: Unable to kmalloc!\n", __FUNCTION__);
kfree(value);
return NULL;
}
@@ -529,7 +533,7 @@ struct ias_value *irias_new_missing_value(void)
value = kmalloc(sizeof(struct ias_value), GFP_ATOMIC);
if (value == NULL) {
- WARNING("%s: Unable to kmalloc!\n", __FUNCTION__);
+ IRDA_WARNING("%s: Unable to kmalloc!\n", __FUNCTION__);
return NULL;
}
memset(value, 0, sizeof(struct ias_value));
@@ -550,7 +554,7 @@ void irias_delete_value(struct ias_value *value)
{
IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
- ASSERT(value != NULL, return;);
+ IRDA_ASSERT(value != NULL, return;);
switch (value->type) {
case IAS_INTEGER: /* Fallthrough */
diff --git a/net/irda/irlan/irlan_client.c b/net/irda/irlan/irlan_client.c
index 92dbe620340e4..f8e6cb0db04bc 100644
--- a/net/irda/irlan/irlan_client.c
+++ b/net/irda/irlan/irlan_client.c
@@ -74,8 +74,8 @@ static void irlan_client_kick_timer_expired(void *data)
IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IRLAN_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
/*
* If we are in peer mode, the client may not have got the discovery
@@ -107,8 +107,8 @@ void irlan_client_wakeup(struct irlan_cb *self, __u32 saddr, __u32 daddr)
{
IRDA_DEBUG(1, "%s()\n", __FUNCTION__ );
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IRLAN_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
/*
* Check if we are already awake, or if we are a provider in direct
@@ -155,7 +155,7 @@ void irlan_client_discovery_indication(discinfo_t *discovery,
IRDA_DEBUG(1, "%s()\n", __FUNCTION__ );
- ASSERT(discovery != NULL, return;);
+ IRDA_ASSERT(discovery != NULL, return;);
/*
* I didn't check it, but I bet that IrLAN suffer from the same
@@ -173,7 +173,7 @@ void irlan_client_discovery_indication(discinfo_t *discovery,
rcu_read_lock();
self = irlan_get_any();
if (self) {
- ASSERT(self->magic == IRLAN_MAGIC, return;);
+ IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
IRDA_DEBUG(1, "%s(), Found instance (%08x)!\n", __FUNCTION__ ,
daddr);
@@ -198,9 +198,9 @@ static int irlan_client_ctrl_data_indication(void *instance, void *sap,
self = (struct irlan_cb *) instance;
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == IRLAN_MAGIC, return -1;);
- ASSERT(skb != NULL, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == IRLAN_MAGIC, return -1;);
+ IRDA_ASSERT(skb != NULL, return -1;);
irlan_do_client_event(self, IRLAN_DATA_INDICATION, skb);
@@ -227,12 +227,12 @@ static void irlan_client_ctrl_disconnect_indication(void *instance, void *sap,
self = (struct irlan_cb *) instance;
tsap = (struct tsap_cb *) sap;
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IRLAN_MAGIC, return;);
- ASSERT(tsap != NULL, return;);
- ASSERT(tsap->magic == TTP_TSAP_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
+ IRDA_ASSERT(tsap != NULL, return;);
+ IRDA_ASSERT(tsap->magic == TTP_TSAP_MAGIC, return;);
- ASSERT(tsap == self->client.tsap_ctrl, return;);
+ IRDA_ASSERT(tsap == self->client.tsap_ctrl, return;);
/* Remove frames queued on the control channel */
while ((skb = skb_dequeue(&self->client.txq)) != NULL) {
@@ -256,8 +256,8 @@ static void irlan_client_open_ctrl_tsap(struct irlan_cb *self)
IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IRLAN_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
/* Check if already open */
if (self->client.tsap_ctrl)
@@ -298,8 +298,8 @@ static void irlan_client_ctrl_connect_confirm(void *instance, void *sap,
self = (struct irlan_cb *) instance;
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IRLAN_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
self->client.max_sdu_size = max_sdu_size;
self->client.max_header_size = max_header_size;
@@ -322,34 +322,34 @@ static void print_ret_code(__u8 code)
printk(KERN_INFO "Success\n");
break;
case 1:
- WARNING("IrLAN: Insufficient resources\n");
+ IRDA_WARNING("IrLAN: Insufficient resources\n");
break;
case 2:
- WARNING("IrLAN: Invalid command format\n");
+ IRDA_WARNING("IrLAN: Invalid command format\n");
break;
case 3:
- WARNING("IrLAN: Command not supported\n");
+ IRDA_WARNING("IrLAN: Command not supported\n");
break;
case 4:
- WARNING("IrLAN: Parameter not supported\n");
+ IRDA_WARNING("IrLAN: Parameter not supported\n");
break;
case 5:
- WARNING("IrLAN: Value not supported\n");
+ IRDA_WARNING("IrLAN: Value not supported\n");
break;
case 6:
- WARNING("IrLAN: Not open\n");
+ IRDA_WARNING("IrLAN: Not open\n");
break;
case 7:
- WARNING("IrLAN: Authentication required\n");
+ IRDA_WARNING("IrLAN: Authentication required\n");
break;
case 8:
- WARNING("IrLAN: Invalid password\n");
+ IRDA_WARNING("IrLAN: Invalid password\n");
break;
case 9:
- WARNING("IrLAN: Protocol error\n");
+ IRDA_WARNING("IrLAN: Protocol error\n");
break;
case 255:
- WARNING("IrLAN: Asynchronous status\n");
+ IRDA_WARNING("IrLAN: Asynchronous status\n");
break;
}
}
@@ -371,15 +371,15 @@ void irlan_client_parse_response(struct irlan_cb *self, struct sk_buff *skb)
char *name;
char *value;
- ASSERT(skb != NULL, return;);
+ IRDA_ASSERT(skb != NULL, return;);
IRDA_DEBUG(4, "%s() skb->len=%d\n", __FUNCTION__ , (int) skb->len);
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IRLAN_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
if (!skb) {
- ERROR("%s(), Got NULL skb!\n", __FUNCTION__);
+ IRDA_ERROR("%s(), Got NULL skb!\n", __FUNCTION__);
return;
}
frame = skb->data;
@@ -438,8 +438,8 @@ static void irlan_check_response_param(struct irlan_cb *self, char *param,
IRDA_DEBUG(4, "%s(), parm=%s\n", __FUNCTION__ , param);
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IRLAN_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
/* Media type */
if (strcmp(param, "MEDIA") == 0) {
@@ -540,10 +540,10 @@ void irlan_client_get_value_confirm(int result, __u16 obj_id,
IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
- ASSERT(priv != NULL, return;);
+ IRDA_ASSERT(priv != NULL, return;);
self = (struct irlan_cb *) priv;
- ASSERT(self->magic == IRLAN_MAGIC, return;);
+ IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
/* We probably don't need to make any more queries */
iriap_close(self->client.iriap);
diff --git a/net/irda/irlan/irlan_client_event.c b/net/irda/irlan/irlan_client_event.c
index 0484ca24ad94d..ce943b69e9961 100644
--- a/net/irda/irlan/irlan_client_event.c
+++ b/net/irda/irlan/irlan_client_event.c
@@ -77,8 +77,8 @@ static int (*state[])(struct irlan_cb *, IRLAN_EVENT event, struct sk_buff *) =
void irlan_do_client_event(struct irlan_cb *self, IRLAN_EVENT event,
struct sk_buff *skb)
{
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IRLAN_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
(*state[ self->client.state]) (self, event, skb);
}
@@ -94,13 +94,14 @@ static int irlan_client_state_idle(struct irlan_cb *self, IRLAN_EVENT event,
{
IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == IRLAN_MAGIC, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == IRLAN_MAGIC, return -1;);
switch (event) {
case IRLAN_DISCOVERY_INDICATION:
if (self->client.iriap) {
- WARNING("%s(), busy with a previous query\n", __FUNCTION__);
+ IRDA_WARNING("%s(), busy with a previous query\n",
+ __FUNCTION__);
return -EBUSY;
}
@@ -137,12 +138,12 @@ static int irlan_client_state_query(struct irlan_cb *self, IRLAN_EVENT event,
{
IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == IRLAN_MAGIC, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == IRLAN_MAGIC, return -1;);
switch(event) {
case IRLAN_IAS_PROVIDER_AVAIL:
- ASSERT(self->dtsap_sel_ctrl != 0, return -1;);
+ IRDA_ASSERT(self->dtsap_sel_ctrl != 0, return -1;);
self->client.open_retries = 0;
@@ -190,7 +191,7 @@ static int irlan_client_state_conn(struct irlan_cb *self, IRLAN_EVENT event,
{
IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
- ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
switch (event) {
case IRLAN_CONNECT_COMPLETE:
@@ -225,11 +226,11 @@ static int irlan_client_state_info(struct irlan_cb *self, IRLAN_EVENT event,
{
IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
- ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
switch (event) {
case IRLAN_DATA_INDICATION:
- ASSERT(skb != NULL, return -1;);
+ IRDA_ASSERT(skb != NULL, return -1;);
irlan_client_parse_response(self, skb);
@@ -267,7 +268,7 @@ static int irlan_client_state_media(struct irlan_cb *self, IRLAN_EVENT event,
{
IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
- ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
switch(event) {
case IRLAN_DATA_INDICATION:
@@ -306,7 +307,7 @@ static int irlan_client_state_open(struct irlan_cb *self, IRLAN_EVENT event,
IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
- ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
switch(event) {
case IRLAN_DATA_INDICATION:
@@ -316,7 +317,7 @@ static int irlan_client_state_open(struct irlan_cb *self, IRLAN_EVENT event,
* Check if we have got the remote TSAP for data
* communications
*/
- ASSERT(self->dtsap_sel_data != 0, return -1;);
+ IRDA_ASSERT(self->dtsap_sel_data != 0, return -1;);
/* Check which access type we are dealing with */
switch (self->client.access_type) {
@@ -377,7 +378,7 @@ static int irlan_client_state_wait(struct irlan_cb *self, IRLAN_EVENT event,
{
IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
- ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
switch(event) {
case IRLAN_PROVIDER_SIGNAL:
@@ -408,7 +409,7 @@ static int irlan_client_state_arb(struct irlan_cb *self, IRLAN_EVENT event,
IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
- ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
switch(event) {
case IRLAN_CHECK_CON_ARB:
@@ -463,8 +464,8 @@ static int irlan_client_state_data(struct irlan_cb *self, IRLAN_EVENT event,
{
IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == IRLAN_MAGIC, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == IRLAN_MAGIC, return -1;);
switch(event) {
case IRLAN_DATA_INDICATION:
diff --git a/net/irda/irlan/irlan_common.c b/net/irda/irlan/irlan_common.c
index fd9f3043119b1..657d12210578e 100644
--- a/net/irda/irlan/irlan_common.c
+++ b/net/irda/irlan/irlan_common.c
@@ -261,8 +261,8 @@ static void __irlan_close(struct irlan_cb *self)
IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
ASSERT_RTNL();
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IRLAN_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
del_timer_sync(&self->watchdog_timer);
del_timer_sync(&self->client.kick_timer);
@@ -311,9 +311,9 @@ static void irlan_connect_indication(void *instance, void *sap,
self = (struct irlan_cb *) instance;
tsap = (struct tsap_cb *) sap;
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IRLAN_MAGIC, return;);
- ASSERT(tsap == self->tsap_data,return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
+ IRDA_ASSERT(tsap == self->tsap_data,return;);
self->max_sdu_size = max_sdu_size;
self->max_header_size = max_header_size;
@@ -354,8 +354,8 @@ static void irlan_connect_confirm(void *instance, void *sap,
self = (struct irlan_cb *) instance;
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IRLAN_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
self->max_sdu_size = max_sdu_size;
self->max_header_size = max_header_size;
@@ -403,12 +403,12 @@ static void irlan_disconnect_indication(void *instance,
self = (struct irlan_cb *) instance;
tsap = (struct tsap_cb *) sap;
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IRLAN_MAGIC, return;);
- ASSERT(tsap != NULL, return;);
- ASSERT(tsap->magic == TTP_TSAP_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
+ IRDA_ASSERT(tsap != NULL, return;);
+ IRDA_ASSERT(tsap->magic == TTP_TSAP_MAGIC, return;);
- ASSERT(tsap == self->tsap_data, return;);
+ IRDA_ASSERT(tsap == self->tsap_data, return;);
IRDA_DEBUG(2, "IrLAN, data channel disconnected by peer!\n");
@@ -432,7 +432,7 @@ static void irlan_disconnect_indication(void *instance,
IRDA_DEBUG(2, "%s(), IrLMP connect failed\n", __FUNCTION__ );
break;
default:
- ERROR("%s(), Unknown disconnect reason\n", __FUNCTION__);
+ IRDA_ERROR("%s(), Unknown disconnect reason\n", __FUNCTION__);
break;
}
@@ -456,8 +456,8 @@ void irlan_open_data_tsap(struct irlan_cb *self)
IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IRLAN_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
/* Check if already open */
if (self->tsap_data)
@@ -492,8 +492,8 @@ void irlan_close_tsaps(struct irlan_cb *self)
{
IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IRLAN_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
/* Disconnect and close all open TSAP connections */
if (self->tsap_data) {
@@ -527,8 +527,8 @@ void irlan_ias_register(struct irlan_cb *self, __u8 tsap_sel)
struct ias_object *obj;
struct ias_value *new_value;
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IRLAN_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
/*
* Check if object has already been registered by a previous provider.
@@ -634,8 +634,8 @@ void irlan_get_provider_info(struct irlan_cb *self)
IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IRLAN_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
skb = dev_alloc_skb(64);
if (!skb)
@@ -666,8 +666,8 @@ void irlan_open_data_channel(struct irlan_cb *self)
IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IRLAN_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
skb = dev_alloc_skb(64);
if (!skb)
@@ -698,8 +698,8 @@ void irlan_close_data_channel(struct irlan_cb *self)
IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IRLAN_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
/* Check if the TSAP is still there */
if (self->client.tsap_ctrl == NULL)
@@ -737,8 +737,8 @@ static void irlan_open_unicast_addr(struct irlan_cb *self)
IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IRLAN_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
skb = dev_alloc_skb(128);
if (!skb)
@@ -775,8 +775,8 @@ void irlan_set_broadcast_filter(struct irlan_cb *self, int status)
IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IRLAN_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
skb = dev_alloc_skb(128);
if (!skb)
@@ -814,8 +814,8 @@ void irlan_set_multicast_filter(struct irlan_cb *self, int status)
IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IRLAN_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
skb = dev_alloc_skb(128);
if (!skb)
@@ -854,8 +854,8 @@ static void irlan_get_unicast_addr(struct irlan_cb *self)
IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IRLAN_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
skb = dev_alloc_skb(128);
if (!skb)
@@ -889,8 +889,8 @@ void irlan_get_media_char(struct irlan_cb *self)
IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IRLAN_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
skb = dev_alloc_skb(64);
if (!skb)
@@ -985,8 +985,8 @@ static int __irlan_insert_param(struct sk_buff *skb, char *param, int type,
value_len = 2;
break;
case IRLAN_ARRAY:
- ASSERT(value_array != NULL, return 0;);
- ASSERT(value_len > 0, return 0;);
+ IRDA_ASSERT(value_array != NULL, return 0;);
+ IRDA_ASSERT(value_len > 0, return 0;);
break;
default:
IRDA_DEBUG(2, "%s(), Unknown parameter type!\n", __FUNCTION__ );
@@ -1029,7 +1029,7 @@ static int __irlan_insert_param(struct sk_buff *skb, char *param, int type,
default:
break;
}
- ASSERT(n == (param_len+value_len+3), return 0;);
+ IRDA_ASSERT(n == (param_len+value_len+3), return 0;);
return param_len+value_len+3;
}
@@ -1142,8 +1142,8 @@ static int irlan_seq_show(struct seq_file *seq, void *v)
else {
struct irlan_cb *self = v;
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == IRLAN_MAGIC, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == IRLAN_MAGIC, return -1;);
seq_printf(seq,"ifname: %s,\n",
self->dev->name);
diff --git a/net/irda/irlan/irlan_eth.c b/net/irda/irlan/irlan_eth.c
index 04bb8925ac046..071cd2cefd8a2 100644
--- a/net/irda/irlan/irlan_eth.c
+++ b/net/irda/irlan/irlan_eth.c
@@ -222,7 +222,13 @@ int irlan_eth_receive(void *instance, void *sap, struct sk_buff *skb)
++self->stats.rx_dropped;
return 0;
}
- ASSERT(skb->len > 1, return 0;);
+ if (skb->len < ETH_HLEN) {
+ IRDA_DEBUG(0, "%s() : IrLAN frame too short (%d)\n",
+ __FUNCTION__, skb->len);
+ ++self->stats.rx_dropped;
+ dev_kfree_skb(skb);
+ return 0;
+ }
/*
* Adopt this frame! Important to set all these fields since they
@@ -261,12 +267,12 @@ void irlan_eth_flow_indication(void *instance, void *sap, LOCAL_FLOW flow)
self = (struct irlan_cb *) instance;
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IRLAN_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
dev = self->dev;
- ASSERT(dev != NULL, return;);
+ IRDA_ASSERT(dev != NULL, return;);
IRDA_DEBUG(0, "%s() : flow %s ; running %d\n", __FUNCTION__,
flow == FLOW_STOP ? "FLOW_STOP" : "FLOW_START",
@@ -340,7 +346,7 @@ static void irlan_eth_set_multicast_list(struct net_device *dev)
if (dev->flags & IFF_PROMISC) {
/* Enable promiscuous mode */
- WARNING("Promiscous mode not implemented by IrLAN!\n");
+ IRDA_WARNING("Promiscous mode not implemented by IrLAN!\n");
}
else if ((dev->flags & IFF_ALLMULTI) || dev->mc_count > HW_MAX_ADDRS) {
/* Disable promiscuous mode, use normal mode. */
diff --git a/net/irda/irlan/irlan_event.c b/net/irda/irlan/irlan_event.c
index daea4d7dc1936..2778d8c6aa311 100644
--- a/net/irda/irlan/irlan_event.c
+++ b/net/irda/irlan/irlan_event.c
@@ -42,8 +42,8 @@ void irlan_next_client_state(struct irlan_cb *self, IRLAN_STATE state)
{
IRDA_DEBUG(2, "%s(), %s\n", __FUNCTION__ , irlan_state[state]);
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IRLAN_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
self->client.state = state;
}
@@ -52,8 +52,8 @@ void irlan_next_provider_state(struct irlan_cb *self, IRLAN_STATE state)
{
IRDA_DEBUG(2, "%s(), %s\n", __FUNCTION__ , irlan_state[state]);
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IRLAN_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
self->provider.state = state;
}
diff --git a/net/irda/irlan/irlan_filter.c b/net/irda/irlan/irlan_filter.c
index aa1e13a57099e..343c5d4a1a1de 100644
--- a/net/irda/irlan/irlan_filter.c
+++ b/net/irda/irlan/irlan_filter.c
@@ -36,8 +36,8 @@
*/
void irlan_filter_request(struct irlan_cb *self, struct sk_buff *skb)
{
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IRLAN_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
if ((self->provider.filter_type == IRLAN_DIRECTED) &&
(self->provider.filter_operation == DYNAMIC))
@@ -148,8 +148,8 @@ void irlan_check_command_param(struct irlan_cb *self, char *param, char *value)
bytes = value;
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IRLAN_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
IRDA_DEBUG(4, "%s, %s\n", param, value);
diff --git a/net/irda/irlan/irlan_provider.c b/net/irda/irlan/irlan_provider.c
index 406d78a5f6592..39c202d1c3747 100644
--- a/net/irda/irlan/irlan_provider.c
+++ b/net/irda/irlan/irlan_provider.c
@@ -74,10 +74,10 @@ static int irlan_provider_data_indication(void *instance, void *sap,
self = (struct irlan_cb *) instance;
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == IRLAN_MAGIC, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == IRLAN_MAGIC, return -1;);
- ASSERT(skb != NULL, return -1;);
+ IRDA_ASSERT(skb != NULL, return -1;);
code = skb->data[0];
switch(code) {
@@ -134,11 +134,11 @@ static void irlan_provider_connect_indication(void *instance, void *sap,
self = (struct irlan_cb *) instance;
tsap = (struct tsap_cb *) sap;
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IRLAN_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
- ASSERT(tsap == self->provider.tsap_ctrl,return;);
- ASSERT(self->provider.state == IRLAN_IDLE, return;);
+ IRDA_ASSERT(tsap == self->provider.tsap_ctrl,return;);
+ IRDA_ASSERT(self->provider.state == IRLAN_IDLE, return;);
daddr = irttp_get_daddr(tsap);
saddr = irttp_get_saddr(tsap);
@@ -168,8 +168,8 @@ static void irlan_provider_connect_indication(void *instance, void *sap,
void irlan_provider_connect_response(struct irlan_cb *self,
struct tsap_cb *tsap)
{
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IRLAN_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
/* Just accept */
irttp_connect_response(tsap, IRLAN_MTU, NULL);
@@ -187,12 +187,12 @@ static void irlan_provider_disconnect_indication(void *instance, void *sap,
self = (struct irlan_cb *) instance;
tsap = (struct tsap_cb *) sap;
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IRLAN_MAGIC, return;);
- ASSERT(tsap != NULL, return;);
- ASSERT(tsap->magic == TTP_TSAP_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
+ IRDA_ASSERT(tsap != NULL, return;);
+ IRDA_ASSERT(tsap->magic == TTP_TSAP_MAGIC, return;);
- ASSERT(tsap == self->provider.tsap_ctrl, return;);
+ IRDA_ASSERT(tsap == self->provider.tsap_ctrl, return;);
irlan_do_provider_event(self, IRLAN_LMP_DISCONNECT, NULL);
}
@@ -234,12 +234,12 @@ int irlan_provider_parse_command(struct irlan_cb *self, int cmd,
char *value;
int ret = RSP_SUCCESS;
- ASSERT(skb != NULL, return -RSP_PROTOCOL_ERROR;);
+ IRDA_ASSERT(skb != NULL, return -RSP_PROTOCOL_ERROR;);
IRDA_DEBUG(4, "%s(), skb->len=%d\n", __FUNCTION__ , (int)skb->len);
- ASSERT(self != NULL, return -RSP_PROTOCOL_ERROR;);
- ASSERT(self->magic == IRLAN_MAGIC, return -RSP_PROTOCOL_ERROR;);
+ IRDA_ASSERT(self != NULL, return -RSP_PROTOCOL_ERROR;);
+ IRDA_ASSERT(self->magic == IRLAN_MAGIC, return -RSP_PROTOCOL_ERROR;);
if (!skb)
return -RSP_PROTOCOL_ERROR;
@@ -293,8 +293,8 @@ void irlan_provider_send_reply(struct irlan_cb *self, int command,
IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IRLAN_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
skb = dev_alloc_skb(128);
if (!skb)
@@ -381,8 +381,8 @@ int irlan_provider_open_ctrl_tsap(struct irlan_cb *self)
IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == IRLAN_MAGIC, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == IRLAN_MAGIC, return -1;);
/* Check if already open */
if (self->provider.tsap_ctrl)
diff --git a/net/irda/irlan/irlan_provider_event.c b/net/irda/irlan/irlan_provider_event.c
index 691b7c1a570c8..5a086f9827ed0 100644
--- a/net/irda/irlan/irlan_provider_event.c
+++ b/net/irda/irlan/irlan_provider_event.c
@@ -58,7 +58,7 @@ static int (*state[])(struct irlan_cb *self, IRLAN_EVENT event,
void irlan_do_provider_event(struct irlan_cb *self, IRLAN_EVENT event,
struct sk_buff *skb)
{
- ASSERT(*state[ self->provider.state] != NULL, return;);
+ IRDA_ASSERT(*state[ self->provider.state] != NULL, return;);
(*state[self->provider.state]) (self, event, skb);
}
@@ -74,7 +74,7 @@ static int irlan_provider_state_idle(struct irlan_cb *self, IRLAN_EVENT event,
{
IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
- ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
switch(event) {
case IRLAN_CONNECT_INDICATION:
@@ -103,7 +103,7 @@ static int irlan_provider_state_info(struct irlan_cb *self, IRLAN_EVENT event,
IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
- ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
switch(event) {
case IRLAN_GET_INFO_CMD:
@@ -168,7 +168,7 @@ static int irlan_provider_state_open(struct irlan_cb *self, IRLAN_EVENT event,
{
IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
- ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
switch(event) {
case IRLAN_FILTER_CONFIG_CMD:
@@ -207,8 +207,8 @@ static int irlan_provider_state_data(struct irlan_cb *self, IRLAN_EVENT event,
{
IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == IRLAN_MAGIC, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == IRLAN_MAGIC, return -1;);
switch(event) {
case IRLAN_FILTER_CONFIG_CMD:
diff --git a/net/irda/irlap.c b/net/irda/irlap.c
index 44fd6aa431714..046ad0750e48d 100644
--- a/net/irda/irlap.c
+++ b/net/irda/irlap.c
@@ -80,15 +80,16 @@ int __init irlap_init(void)
{
/* Check if the compiler did its job properly.
* May happen on some ARM configuration, check with Russell King. */
- ASSERT(sizeof(struct xid_frame) == 14, ;);
- ASSERT(sizeof(struct test_frame) == 10, ;);
- ASSERT(sizeof(struct ua_frame) == 10, ;);
- ASSERT(sizeof(struct snrm_frame) == 11, ;);
+ IRDA_ASSERT(sizeof(struct xid_frame) == 14, ;);
+ IRDA_ASSERT(sizeof(struct test_frame) == 10, ;);
+ IRDA_ASSERT(sizeof(struct ua_frame) == 10, ;);
+ IRDA_ASSERT(sizeof(struct snrm_frame) == 11, ;);
/* Allocate master array */
irlap = hashbin_new(HB_LOCK);
if (irlap == NULL) {
- ERROR("%s: can't allocate irlap hashbin!\n", __FUNCTION__);
+ IRDA_ERROR("%s: can't allocate irlap hashbin!\n",
+ __FUNCTION__);
return -ENOMEM;
}
@@ -97,7 +98,7 @@ int __init irlap_init(void)
void __exit irlap_cleanup(void)
{
- ASSERT(irlap != NULL, return;);
+ IRDA_ASSERT(irlap != NULL, return;);
hashbin_delete(irlap, (FREE_FUNC) __irlap_close);
}
@@ -186,8 +187,8 @@ EXPORT_SYMBOL(irlap_open);
*/
static void __irlap_close(struct irlap_cb *self)
{
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LAP_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
/* Stop timers */
del_timer(&self->slot_timer);
@@ -218,8 +219,8 @@ void irlap_close(struct irlap_cb *self)
IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LAP_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
/* We used to send a LAP_DISC_INDICATION here, but this was
* racy. This has been move within irlmp_unregister_link()
@@ -249,8 +250,8 @@ void irlap_connect_indication(struct irlap_cb *self, struct sk_buff *skb)
{
IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LAP_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
irlap_init_qos_capabilities(self, NULL); /* No user QoS! */
@@ -283,8 +284,8 @@ void irlap_connect_request(struct irlap_cb *self, __u32 daddr,
{
IRDA_DEBUG(3, "%s(), daddr=0x%08x\n", __FUNCTION__, daddr);
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LAP_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
self->daddr = daddr;
@@ -310,8 +311,8 @@ void irlap_connect_confirm(struct irlap_cb *self, struct sk_buff *skb)
{
IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LAP_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
irlmp_link_connect_confirm(self->notify.instance, &self->qos_tx, skb);
}
@@ -342,13 +343,13 @@ void irlap_data_indication(struct irlap_cb *self, struct sk_buff *skb,
void irlap_data_request(struct irlap_cb *self, struct sk_buff *skb,
int unreliable)
{
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LAP_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
IRDA_DEBUG(3, "%s()\n", __FUNCTION__);
- ASSERT(skb_headroom(skb) >= (LAP_ADDR_HEADER+LAP_CTRL_HEADER),
- return;);
+ IRDA_ASSERT(skb_headroom(skb) >= (LAP_ADDR_HEADER+LAP_CTRL_HEADER),
+ return;);
skb_push(skb, LAP_ADDR_HEADER+LAP_CTRL_HEADER);
/*
@@ -389,12 +390,12 @@ void irlap_data_request(struct irlap_cb *self, struct sk_buff *skb,
#ifdef CONFIG_IRDA_ULTRA
void irlap_unitdata_request(struct irlap_cb *self, struct sk_buff *skb)
{
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LAP_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
IRDA_DEBUG(3, "%s()\n", __FUNCTION__);
- ASSERT(skb_headroom(skb) >= (LAP_ADDR_HEADER+LAP_CTRL_HEADER),
+ IRDA_ASSERT(skb_headroom(skb) >= (LAP_ADDR_HEADER+LAP_CTRL_HEADER),
return;);
skb_push(skb, LAP_ADDR_HEADER+LAP_CTRL_HEADER);
@@ -420,9 +421,9 @@ void irlap_unitdata_indication(struct irlap_cb *self, struct sk_buff *skb)
{
IRDA_DEBUG(1, "%s()\n", __FUNCTION__);
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LAP_MAGIC, return;);
- ASSERT(skb != NULL, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
+ IRDA_ASSERT(skb != NULL, return;);
/* Hide LAP header from IrLMP layer */
skb_pull(skb, LAP_ADDR_HEADER+LAP_CTRL_HEADER);
@@ -440,8 +441,8 @@ void irlap_disconnect_request(struct irlap_cb *self)
{
IRDA_DEBUG(3, "%s()\n", __FUNCTION__);
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LAP_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
/* Don't disconnect until all data frames are successfully sent */
if (skb_queue_len(&self->txq) > 0) {
@@ -476,8 +477,8 @@ void irlap_disconnect_indication(struct irlap_cb *self, LAP_REASON reason)
{
IRDA_DEBUG(1, "%s(), reason=%s\n", __FUNCTION__, lap_reasons[reason]);
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LAP_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
/* Flush queues */
irlap_flush_all_queues(self);
@@ -495,7 +496,7 @@ void irlap_disconnect_indication(struct irlap_cb *self, LAP_REASON reason)
reason, NULL);
break;
default:
- ERROR("%s: Unknown reason %d\n", __FUNCTION__, reason);
+ IRDA_ERROR("%s: Unknown reason %d\n", __FUNCTION__, reason);
}
}
@@ -509,15 +510,15 @@ void irlap_discovery_request(struct irlap_cb *self, discovery_t *discovery)
{
struct irlap_info info;
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LAP_MAGIC, return;);
- ASSERT(discovery != NULL, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
+ IRDA_ASSERT(discovery != NULL, return;);
IRDA_DEBUG(4, "%s(), nslots = %d\n", __FUNCTION__, discovery->nslots);
- ASSERT((discovery->nslots == 1) || (discovery->nslots == 6) ||
- (discovery->nslots == 8) || (discovery->nslots == 16),
- return;);
+ IRDA_ASSERT((discovery->nslots == 1) || (discovery->nslots == 6) ||
+ (discovery->nslots == 8) || (discovery->nslots == 16),
+ return;);
/* Discovery is only possible in NDM mode */
if (self->state != LAP_NDM) {
@@ -544,8 +545,8 @@ void irlap_discovery_request(struct irlap_cb *self, discovery_t *discovery)
self->discovery_log = hashbin_new(HB_NOLOCK);
if (self->discovery_log == NULL) {
- WARNING("%s(), Unable to allocate discovery log!\n",
- __FUNCTION__);
+ IRDA_WARNING("%s(), Unable to allocate discovery log!\n",
+ __FUNCTION__);
return;
}
@@ -569,10 +570,10 @@ void irlap_discovery_request(struct irlap_cb *self, discovery_t *discovery)
*/
void irlap_discovery_confirm(struct irlap_cb *self, hashbin_t *discovery_log)
{
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LAP_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
- ASSERT(self->notify.instance != NULL, return;);
+ IRDA_ASSERT(self->notify.instance != NULL, return;);
/*
* Check for successful discovery, since we are then allowed to clear
@@ -602,11 +603,11 @@ void irlap_discovery_indication(struct irlap_cb *self, discovery_t *discovery)
{
IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LAP_MAGIC, return;);
- ASSERT(discovery != NULL, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
+ IRDA_ASSERT(discovery != NULL, return;);
- ASSERT(self->notify.instance != NULL, return;);
+ IRDA_ASSERT(self->notify.instance != NULL, return;);
/* A device is very likely to connect immediately after it performs
* a successful discovery. This means that in our case, we are much
@@ -629,10 +630,10 @@ void irlap_status_indication(struct irlap_cb *self, int quality_of_link)
{
switch (quality_of_link) {
case STATUS_NO_ACTIVITY:
- MESSAGE("IrLAP, no activity on link!\n");
+ IRDA_MESSAGE("IrLAP, no activity on link!\n");
break;
case STATUS_NOISY:
- MESSAGE("IrLAP, noisy link!\n");
+ IRDA_MESSAGE("IrLAP, noisy link!\n");
break;
default:
break;
@@ -648,8 +649,8 @@ void irlap_reset_indication(struct irlap_cb *self)
{
IRDA_DEBUG(1, "%s()\n", __FUNCTION__);
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LAP_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
if (self->state == LAP_RESET_WAIT)
irlap_do_event(self, RESET_REQUEST, NULL, NULL);
@@ -677,7 +678,7 @@ int irlap_generate_rand_time_slot(int S, int s)
static int rand;
int slot;
- ASSERT((S - s) > 0, return 0;);
+ IRDA_ASSERT((S - s) > 0, return 0;);
rand += jiffies;
rand ^= (rand << 12);
@@ -685,7 +686,7 @@ int irlap_generate_rand_time_slot(int S, int s)
slot = s + rand % (S-s);
- ASSERT((slot >= s) || (slot < S), return 0;);
+ IRDA_ASSERT((slot >= s) || (slot < S), return 0;);
return slot;
}
@@ -792,8 +793,8 @@ void irlap_initiate_connection_state(struct irlap_cb *self)
{
IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LAP_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
/* Next to send and next to receive */
self->vs = self->vr = 0;
@@ -848,8 +849,8 @@ void irlap_flush_all_queues(struct irlap_cb *self)
{
struct sk_buff* skb;
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LAP_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
/* Free transmission queue */
while ((skb = skb_dequeue(&self->txq)) != NULL)
@@ -875,8 +876,8 @@ static void irlap_change_speed(struct irlap_cb *self, __u32 speed, int now)
IRDA_DEBUG(0, "%s(), setting speed to %d\n", __FUNCTION__, speed);
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LAP_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
self->speed = speed;
@@ -899,9 +900,9 @@ static void irlap_change_speed(struct irlap_cb *self, __u32 speed, int now)
static void irlap_init_qos_capabilities(struct irlap_cb *self,
struct qos_info *qos_user)
{
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LAP_MAGIC, return;);
- ASSERT(self->netdev != NULL, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
+ IRDA_ASSERT(self->netdev != NULL, return;);
/* Start out with the maximum QoS support possible */
irda_init_max_qos_capabilies(&self->qos_rx);
@@ -947,8 +948,8 @@ void irlap_apply_default_connection_parameters(struct irlap_cb *self)
{
IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LAP_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
/* xbofs : Default value in NDM */
self->next_bofs = 12;
@@ -1010,8 +1011,8 @@ void irlap_apply_connection_parameters(struct irlap_cb *self, int now)
{
IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LAP_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
/* Set the negotiated xbofs value */
self->next_bofs = self->qos_tx.additional_bofs.value;
@@ -1040,8 +1041,8 @@ void irlap_apply_connection_parameters(struct irlap_cb *self, int now)
* Initialize timeout values, some of the rules are listed on
* page 92 in IrLAP.
*/
- ASSERT(self->qos_tx.max_turn_time.value != 0, return;);
- ASSERT(self->qos_rx.max_turn_time.value != 0, return;);
+ IRDA_ASSERT(self->qos_tx.max_turn_time.value != 0, return;);
+ IRDA_ASSERT(self->qos_rx.max_turn_time.value != 0, return;);
/* The poll timeout applies only to the primary station.
* It defines the maximum time the primary stay in XMIT mode
* before timeout and turning the link around (sending a RR).
@@ -1139,7 +1140,7 @@ static int irlap_seq_show(struct seq_file *seq, void *v)
const struct irlap_iter_state *iter = seq->private;
const struct irlap_cb *self = v;
- ASSERT(self->magic == LAP_MAGIC, return -EINVAL;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return -EINVAL;);
seq_printf(seq, "irlap%d ", iter->id);
seq_printf(seq, "state: %s\n",
diff --git a/net/irda/irlap_event.c b/net/irda/irlap_event.c
index 570a296c85307..1cd89f5f3b759 100644
--- a/net/irda/irlap_event.c
+++ b/net/irda/irlap_event.c
@@ -169,8 +169,8 @@ static void irlap_poll_timer_expired(void *data)
{
struct irlap_cb *self = (struct irlap_cb *) data;
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LAP_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
irlap_do_event(self, POLL_TIMER_EXPIRED, NULL, NULL);
}
@@ -183,8 +183,8 @@ static void irlap_poll_timer_expired(void *data)
*/
static void irlap_start_poll_timer(struct irlap_cb *self, int timeout)
{
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LAP_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
#ifdef CONFIG_IRDA_FAST_RR
/*
@@ -346,12 +346,12 @@ static int irlap_state_ndm(struct irlap_cb *self, IRLAP_EVENT event,
discovery_t *discovery_rsp;
int ret = 0;
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == LAP_MAGIC, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return -1;);
switch (event) {
case CONNECT_REQUEST:
- ASSERT(self->netdev != NULL, return -1;);
+ IRDA_ASSERT(self->netdev != NULL, return -1;);
if (self->media_busy) {
/* Note : this will never happen, because we test
@@ -389,10 +389,11 @@ static int irlap_state_ndm(struct irlap_cb *self, IRLAP_EVENT event,
}
break;
case DISCOVERY_REQUEST:
- ASSERT(info != NULL, return -1;);
+ IRDA_ASSERT(info != NULL, return -1;);
if (self->media_busy) {
- IRDA_DEBUG(0, "%s(), media busy!\n", __FUNCTION__);
+ IRDA_DEBUG(1, "%s(), DISCOVERY_REQUEST: media busy!\n",
+ __FUNCTION__);
/* irlap->log.condition = MEDIA_BUSY; */
/* This will make IrLMP try again */
@@ -414,7 +415,7 @@ static int irlap_state_ndm(struct irlap_cb *self, IRLAP_EVENT event,
irlap_next_state(self, LAP_QUERY);
break;
case RECV_DISCOVERY_XID_CMD:
- ASSERT(info != NULL, return -1;);
+ IRDA_ASSERT(info != NULL, return -1;);
/* Assert that this is not the final slot */
if (info->s <= info->S) {
@@ -576,21 +577,21 @@ static int irlap_state_query(struct irlap_cb *self, IRLAP_EVENT event,
{
int ret = 0;
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == LAP_MAGIC, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return -1;);
switch (event) {
case RECV_DISCOVERY_XID_RSP:
- ASSERT(info != NULL, return -1;);
- ASSERT(info->discovery != NULL, return -1;);
+ IRDA_ASSERT(info != NULL, return -1;);
+ IRDA_ASSERT(info->discovery != NULL, return -1;);
IRDA_DEBUG(4, "%s(), daddr=%08x\n", __FUNCTION__,
info->discovery->data.daddr);
if (!self->discovery_log) {
- WARNING("%s: discovery log is gone! "
- "maybe the discovery timeout has been set to "
- "short?\n", __FUNCTION__);
+ IRDA_WARNING("%s: discovery log is gone! "
+ "maybe the discovery timeout has been set"
+ " to short?\n", __FUNCTION__);
break;
}
hashbin_insert(self->discovery_log,
@@ -613,7 +614,7 @@ static int irlap_state_query(struct irlap_cb *self, IRLAP_EVENT event,
* Jean II
*/
- ASSERT(info != NULL, return -1;);
+ IRDA_ASSERT(info != NULL, return -1;);
IRDA_DEBUG(1, "%s(), Receiving discovery request (s = %d) while performing discovery :-(\n", __FUNCTION__, info->s);
@@ -690,8 +691,8 @@ static int irlap_state_reply(struct irlap_cb *self, IRLAP_EVENT event,
IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == LAP_MAGIC, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return -1;);
switch (event) {
case QUERY_TIMER_EXPIRED:
@@ -700,7 +701,7 @@ static int irlap_state_reply(struct irlap_cb *self, IRLAP_EVENT event,
irlap_next_state(self, LAP_NDM);
break;
case RECV_DISCOVERY_XID_CMD:
- ASSERT(info != NULL, return -1;);
+ IRDA_ASSERT(info != NULL, return -1;);
/* Last frame? */
if (info->s == 0xff) {
del_timer(&self->query_timer);
@@ -757,14 +758,14 @@ static int irlap_state_conn(struct irlap_cb *self, IRLAP_EVENT event,
IRDA_DEBUG(4, "%s(), event=%s\n", __FUNCTION__, irlap_event[ event]);
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == LAP_MAGIC, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return -1;);
switch (event) {
case CONNECT_RESPONSE:
skb_pull(skb, sizeof(struct snrm_frame));
- ASSERT(self->netdev != NULL, return -1;);
+ IRDA_ASSERT(self->netdev != NULL, return -1;);
irlap_qos_negotiate(self, skb);
@@ -851,8 +852,8 @@ static int irlap_state_setup(struct irlap_cb *self, IRLAP_EVENT event,
IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == LAP_MAGIC, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return -1;);
switch (event) {
case FINAL_TIMER_EXPIRED:
@@ -880,8 +881,8 @@ static int irlap_state_setup(struct irlap_cb *self, IRLAP_EVENT event,
case RECV_SNRM_CMD:
IRDA_DEBUG(4, "%s(), SNRM battle!\n", __FUNCTION__);
- ASSERT(skb != NULL, return 0;);
- ASSERT(info != NULL, return 0;);
+ IRDA_ASSERT(skb != NULL, return 0;);
+ IRDA_ASSERT(info != NULL, return 0;);
/*
* The device with the largest device address wins the battle
@@ -891,7 +892,7 @@ static int irlap_state_setup(struct irlap_cb *self, IRLAP_EVENT event,
del_timer(&self->final_timer);
irlap_initiate_connection_state(self);
- ASSERT(self->netdev != NULL, return -1;);
+ IRDA_ASSERT(self->netdev != NULL, return -1;);
skb_pull(skb, sizeof(struct snrm_frame));
@@ -923,11 +924,11 @@ static int irlap_state_setup(struct irlap_cb *self, IRLAP_EVENT event,
irlap_initiate_connection_state(self);
/* Negotiate connection parameters */
- ASSERT(skb->len > 10, return -1;);
+ IRDA_ASSERT(skb->len > 10, return -1;);
skb_pull(skb, sizeof(struct ua_frame));
- ASSERT(self->netdev != NULL, return -1;);
+ IRDA_ASSERT(self->netdev != NULL, return -1;);
irlap_qos_negotiate(self, skb);
@@ -1158,8 +1159,8 @@ static int irlap_state_pclose(struct irlap_cb *self, IRLAP_EVENT event,
IRDA_DEBUG(1, "%s()\n", __FUNCTION__);
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == LAP_MAGIC, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return -1;);
switch (event) {
case RECV_UA_RSP: /* FALLTHROUGH */
@@ -1226,7 +1227,7 @@ static int irlap_state_nrm_p(struct irlap_cb *self, IRLAP_EVENT event,
*/
self->fast_RR = FALSE;
#endif /* CONFIG_IRDA_FAST_RR */
- ASSERT( info != NULL, return -1;);
+ IRDA_ASSERT( info != NULL, return -1;);
ns_status = irlap_validate_ns_received(self, info->ns);
nr_status = irlap_validate_nr_received(self, info->nr);
@@ -1460,7 +1461,7 @@ static int irlap_state_nrm_p(struct irlap_cb *self, IRLAP_EVENT event,
/* Start poll timer */
irlap_start_poll_timer(self, self->poll_timeout);
} else if (ret == NR_UNEXPECTED) {
- ASSERT(info != NULL, return -1;);
+ IRDA_ASSERT(info != NULL, return -1;);
/*
* Unexpected nr!
*/
@@ -1491,7 +1492,7 @@ static int irlap_state_nrm_p(struct irlap_cb *self, IRLAP_EVENT event,
}
break;
case RECV_RNR_RSP:
- ASSERT(info != NULL, return -1;);
+ IRDA_ASSERT(info != NULL, return -1;);
/* Stop final timer */
del_timer(&self->final_timer);
@@ -1612,8 +1613,8 @@ static int irlap_state_reset_wait(struct irlap_cb *self, IRLAP_EVENT event,
IRDA_DEBUG(3, "%s(), event = %s\n", __FUNCTION__, irlap_event[event]);
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == LAP_MAGIC, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return -1;);
switch (event) {
case RESET_REQUEST:
@@ -1659,8 +1660,8 @@ static int irlap_state_reset(struct irlap_cb *self, IRLAP_EVENT event,
IRDA_DEBUG(3, "%s(), event = %s\n", __FUNCTION__, irlap_event[event]);
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == LAP_MAGIC, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return -1;);
switch (event) {
case RECV_DISC_CMD:
@@ -1693,7 +1694,7 @@ static int irlap_state_reset(struct irlap_cb *self, IRLAP_EVENT event,
if (self->retry_count < 3) {
irlap_wait_min_turn_around(self, &self->qos_tx);
- ASSERT(self->netdev != NULL, return -1;);
+ IRDA_ASSERT(self->netdev != NULL, return -1;);
irlap_send_snrm_frame(self, self->qos_dev);
self->retry_count++; /* Experimental!! */
@@ -1752,8 +1753,8 @@ static int irlap_state_xmit_s(struct irlap_cb *self, IRLAP_EVENT event,
IRDA_DEBUG(4, "%s(), event=%s\n", __FUNCTION__, irlap_event[event]);
- ASSERT(self != NULL, return -ENODEV;);
- ASSERT(self->magic == LAP_MAGIC, return -EBADR;);
+ IRDA_ASSERT(self != NULL, return -ENODEV;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return -EBADR;);
switch (event) {
case SEND_I_CMD:
@@ -1874,8 +1875,8 @@ static int irlap_state_nrm_s(struct irlap_cb *self, IRLAP_EVENT event,
IRDA_DEBUG(4, "%s(), event=%s\n", __FUNCTION__, irlap_event[ event]);
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == LAP_MAGIC, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return -1;);
switch (event) {
case RECV_I_CMD: /* Optimize for the common case */
@@ -2231,8 +2232,8 @@ static int irlap_state_sclose(struct irlap_cb *self, IRLAP_EVENT event,
IRDA_DEBUG(1, "%s()\n", __FUNCTION__);
- ASSERT(self != NULL, return -ENODEV;);
- ASSERT(self->magic == LAP_MAGIC, return -EBADR;);
+ IRDA_ASSERT(self != NULL, return -ENODEV;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return -EBADR;);
switch (event) {
case RECV_DISC_CMD:
@@ -2304,8 +2305,8 @@ static int irlap_state_reset_check( struct irlap_cb *self, IRLAP_EVENT event,
IRDA_DEBUG(1, "%s(), event=%s\n", __FUNCTION__, irlap_event[event]);
- ASSERT(self != NULL, return -ENODEV;);
- ASSERT(self->magic == LAP_MAGIC, return -EBADR;);
+ IRDA_ASSERT(self != NULL, return -ENODEV;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return -EBADR;);
switch (event) {
case RESET_RESPONSE:
diff --git a/net/irda/irlap_frame.c b/net/irda/irlap_frame.c
index 346c95eb46dd3..040abe714aa35 100644
--- a/net/irda/irlap_frame.c
+++ b/net/irda/irlap_frame.c
@@ -113,8 +113,8 @@ void irlap_send_snrm_frame(struct irlap_cb *self, struct qos_info *qos)
struct snrm_frame *frame;
int ret;
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LAP_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
/* Allocate frame */
tx_skb = dev_alloc_skb(64);
@@ -206,8 +206,8 @@ void irlap_send_ua_response_frame(struct irlap_cb *self, struct qos_info *qos)
IRDA_DEBUG(2, "%s() <%ld>\n", __FUNCTION__, jiffies);
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LAP_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
/* Allocate frame */
tx_skb = dev_alloc_skb(64);
@@ -247,8 +247,8 @@ void irlap_send_dm_frame( struct irlap_cb *self)
struct sk_buff *tx_skb = NULL;
__u8 *frame;
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LAP_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
tx_skb = dev_alloc_skb(32);
if (!tx_skb)
@@ -279,8 +279,8 @@ void irlap_send_disc_frame(struct irlap_cb *self)
IRDA_DEBUG(3, "%s()\n", __FUNCTION__);
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LAP_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
tx_skb = dev_alloc_skb(16);
if (!tx_skb)
@@ -311,9 +311,9 @@ void irlap_send_discovery_xid_frame(struct irlap_cb *self, int S, __u8 s,
IRDA_DEBUG(4, "%s(), s=%d, S=%d, command=%d\n", __FUNCTION__,
s, S, command);
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LAP_MAGIC, return;);
- ASSERT(discovery != NULL, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
+ IRDA_ASSERT(discovery != NULL, return;);
tx_skb = dev_alloc_skb(64);
if (!tx_skb)
@@ -402,11 +402,11 @@ static void irlap_recv_discovery_xid_rsp(struct irlap_cb *self,
IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LAP_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
if (!pskb_may_pull(skb, sizeof(struct xid_frame))) {
- ERROR("%s: frame to short!\n", __FUNCTION__);
+ IRDA_ERROR("%s: frame to short!\n", __FUNCTION__);
return;
}
@@ -423,7 +423,7 @@ static void irlap_recv_discovery_xid_rsp(struct irlap_cb *self,
}
if ((discovery = kmalloc(sizeof(discovery_t), GFP_ATOMIC)) == NULL) {
- WARNING("%s: kmalloc failed!\n", __FUNCTION__);
+ IRDA_WARNING("%s: kmalloc failed!\n", __FUNCTION__);
return;
}
memset(discovery, 0, sizeof(discovery_t));
@@ -478,7 +478,7 @@ static void irlap_recv_discovery_xid_cmd(struct irlap_cb *self,
char *text;
if (!pskb_may_pull(skb, sizeof(struct xid_frame))) {
- ERROR("%s: frame to short!\n", __FUNCTION__);
+ IRDA_ERROR("%s: frame to short!\n", __FUNCTION__);
return;
}
@@ -522,7 +522,8 @@ static void irlap_recv_discovery_xid_cmd(struct irlap_cb *self,
/* Check if things are sane at this point... */
if((discovery_info == NULL) ||
!pskb_may_pull(skb, 3)) {
- ERROR("%s: discovery frame to short!\n", __FUNCTION__);
+ IRDA_ERROR("%s: discovery frame to short!\n",
+ __FUNCTION__);
return;
}
@@ -531,7 +532,7 @@ static void irlap_recv_discovery_xid_cmd(struct irlap_cb *self,
*/
discovery = kmalloc(sizeof(discovery_t), GFP_ATOMIC);
if (!discovery) {
- WARNING("%s: unable to malloc!\n", __FUNCTION__);
+ IRDA_WARNING("%s: unable to malloc!\n", __FUNCTION__);
return;
}
@@ -861,9 +862,9 @@ void irlap_send_data_secondary_final(struct irlap_cb *self,
{
struct sk_buff *tx_skb = NULL;
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LAP_MAGIC, return;);
- ASSERT(skb != NULL, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
+ IRDA_ASSERT(skb != NULL, return;);
/* Is this reliable or unreliable data? */
if (skb->data[1] == I_FRAME) {
@@ -967,8 +968,8 @@ void irlap_resend_rejected_frames(struct irlap_cb *self, int command)
struct sk_buff *skb;
int count;
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LAP_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
/* Initialize variables */
count = skb_queue_len(&self->wx_list);
@@ -1023,7 +1024,7 @@ void irlap_resend_rejected_frames(struct irlap_cb *self, int command)
if ((skb_queue_len( &self->txq) > 0) &&
(self->window > 0)) {
skb = skb_dequeue( &self->txq);
- ASSERT(skb != NULL, return;);
+ IRDA_ASSERT(skb != NULL, return;);
/*
* If send window > 1 then send frame with pf
@@ -1047,8 +1048,8 @@ void irlap_resend_rejected_frame(struct irlap_cb *self, int command)
struct sk_buff *tx_skb;
struct sk_buff *skb;
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LAP_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
/* Resend unacknowledged frame(s) */
skb = skb_peek(&self->wx_list);
@@ -1089,9 +1090,9 @@ void irlap_send_ui_frame(struct irlap_cb *self, struct sk_buff *skb,
{
IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LAP_MAGIC, return;);
- ASSERT(skb != NULL, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
+ IRDA_ASSERT(skb != NULL, return;);
/* Insert connection address */
skb->data[0] = caddr | ((command) ? CMD_FRAME : 0);
@@ -1168,13 +1169,13 @@ static void irlap_recv_frmr_frame(struct irlap_cb *self, struct sk_buff *skb,
IRDA_DEBUG(0, "%s()\n", __FUNCTION__);
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LAP_MAGIC, return;);
- ASSERT(skb != NULL, return;);
- ASSERT(info != NULL, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
+ IRDA_ASSERT(skb != NULL, return;);
+ IRDA_ASSERT(info != NULL, return;);
if (!pskb_may_pull(skb, 4)) {
- ERROR("%s: frame to short!\n", __FUNCTION__);
+ IRDA_ERROR("%s: frame to short!\n", __FUNCTION__);
return;
}
@@ -1263,7 +1264,7 @@ static void irlap_recv_test_frame(struct irlap_cb *self, struct sk_buff *skb,
IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
if (!pskb_may_pull(skb, sizeof(*frame))) {
- ERROR("%s: frame to short!\n", __FUNCTION__);
+ IRDA_ERROR("%s: frame to short!\n", __FUNCTION__);
return;
}
frame = (struct test_frame *) skb->data;
@@ -1330,14 +1331,14 @@ int irlap_driver_rcv(struct sk_buff *skb, struct net_device *dev,
* share and non linear skbs. This should never happen, so
* we don't need to be clever about it. Jean II */
if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) {
- ERROR("%s: can't clone shared skb!\n", __FUNCTION__);
+ IRDA_ERROR("%s: can't clone shared skb!\n", __FUNCTION__);
dev_kfree_skb(skb);
return -1;
}
/* Check if frame is large enough for parsing */
if (!pskb_may_pull(skb, 2)) {
- ERROR("%s: frame to short!\n", __FUNCTION__);
+ IRDA_ERROR("%s: frame to short!\n", __FUNCTION__);
dev_kfree_skb(skb);
return -1;
}
@@ -1387,7 +1388,7 @@ int irlap_driver_rcv(struct sk_buff *skb, struct net_device *dev,
irlap_recv_srej_frame(self, skb, &info, command);
break;
default:
- WARNING("%s: Unknown S-frame %02x received!\n",
+ IRDA_WARNING("%s: Unknown S-frame %02x received!\n",
__FUNCTION__, info.control);
break;
}
@@ -1425,7 +1426,7 @@ int irlap_driver_rcv(struct sk_buff *skb, struct net_device *dev,
irlap_recv_ui_frame(self, skb, &info);
break;
default:
- WARNING("%s: Unknown frame %02x received!\n",
+ IRDA_WARNING("%s: Unknown frame %02x received!\n",
__FUNCTION__, info.control);
break;
}
diff --git a/net/irda/irlmp.c b/net/irda/irlmp.c
index 26b22f49076bc..7a4a4d7fbe66b 100644
--- a/net/irda/irlmp.c
+++ b/net/irda/irlmp.c
@@ -121,8 +121,8 @@ int __init irlmp_init(void)
void __exit irlmp_cleanup(void)
{
/* Check for main structure */
- ASSERT(irlmp != NULL, return;);
- ASSERT(irlmp->magic == LMP_MAGIC, return;);
+ IRDA_ASSERT(irlmp != NULL, return;);
+ IRDA_ASSERT(irlmp->magic == LMP_MAGIC, return;);
del_timer(&irlmp->discovery_timer);
@@ -147,10 +147,10 @@ struct lsap_cb *irlmp_open_lsap(__u8 slsap_sel, notify_t *notify, __u8 pid)
{
struct lsap_cb *self;
- ASSERT(notify != NULL, return NULL;);
- ASSERT(irlmp != NULL, return NULL;);
- ASSERT(irlmp->magic == LMP_MAGIC, return NULL;);
- ASSERT(notify->instance != NULL, return NULL;);
+ IRDA_ASSERT(notify != NULL, return NULL;);
+ IRDA_ASSERT(irlmp != NULL, return NULL;);
+ IRDA_ASSERT(irlmp->magic == LMP_MAGIC, return NULL;);
+ IRDA_ASSERT(notify->instance != NULL, return NULL;);
/* Does the client care which Source LSAP selector it gets? */
if (slsap_sel == LSAP_ANY) {
@@ -163,7 +163,7 @@ struct lsap_cb *irlmp_open_lsap(__u8 slsap_sel, notify_t *notify, __u8 pid)
/* Allocate new instance of a LSAP connection */
self = kmalloc(sizeof(struct lsap_cb), GFP_ATOMIC);
if (self == NULL) {
- ERROR("%s: can't allocate memory\n", __FUNCTION__);
+ IRDA_ERROR("%s: can't allocate memory\n", __FUNCTION__);
return NULL;
}
memset(self, 0, sizeof(struct lsap_cb));
@@ -204,8 +204,8 @@ static void __irlmp_close_lsap(struct lsap_cb *self)
{
IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
/*
* Set some of the variables to preset values
@@ -230,8 +230,8 @@ void irlmp_close_lsap(struct lsap_cb *self)
struct lap_cb *lap;
struct lsap_cb *lsap = NULL;
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
/*
* Find out if we should remove this LSAP from a link or from the
@@ -239,7 +239,7 @@ void irlmp_close_lsap(struct lsap_cb *self)
*/
lap = self->lap;
if (lap) {
- ASSERT(lap->magic == LMP_LAP_MAGIC, return;);
+ IRDA_ASSERT(lap->magic == LMP_LAP_MAGIC, return;);
/* We might close a LSAP before it has completed the
* connection setup. In those case, higher layers won't
* send a proper disconnect request. Harmless, except
@@ -282,16 +282,16 @@ void irlmp_register_link(struct irlap_cb *irlap, __u32 saddr, notify_t *notify)
{
struct lap_cb *lap;
- ASSERT(irlmp != NULL, return;);
- ASSERT(irlmp->magic == LMP_MAGIC, return;);
- ASSERT(notify != NULL, return;);
+ IRDA_ASSERT(irlmp != NULL, return;);
+ IRDA_ASSERT(irlmp->magic == LMP_MAGIC, return;);
+ IRDA_ASSERT(notify != NULL, return;);
/*
* Allocate new instance of a LSAP connection
*/
lap = kmalloc(sizeof(struct lap_cb), GFP_KERNEL);
if (lap == NULL) {
- ERROR("%s: unable to kmalloc\n", __FUNCTION__);
+ IRDA_ERROR("%s: unable to kmalloc\n", __FUNCTION__);
return;
}
memset(lap, 0, sizeof(struct lap_cb));
@@ -305,7 +305,7 @@ void irlmp_register_link(struct irlap_cb *irlap, __u32 saddr, notify_t *notify)
#endif
lap->lsaps = hashbin_new(HB_LOCK);
if (lap->lsaps == NULL) {
- WARNING("%s(), unable to kmalloc lsaps\n", __FUNCTION__);
+ IRDA_WARNING("%s(), unable to kmalloc lsaps\n", __FUNCTION__);
kfree(lap);
return;
}
@@ -344,7 +344,7 @@ void irlmp_unregister_link(__u32 saddr)
* will be triggered anymore. Jean II */
link = hashbin_remove(irlmp->links, saddr, NULL);
if (link) {
- ASSERT(link->magic == LMP_LAP_MAGIC, return;);
+ IRDA_ASSERT(link->magic == LMP_LAP_MAGIC, return;);
/* Kill all the LSAPs on this link. Jean II */
link->reason = LAP_DISC_INDICATION;
@@ -376,8 +376,8 @@ int irlmp_connect_request(struct lsap_cb *self, __u8 dlsap_sel,
struct lsap_cb *lsap;
int ret;
- ASSERT(self != NULL, return -EBADR;);
- ASSERT(self->magic == LMP_LSAP_MAGIC, return -EBADR;);
+ IRDA_ASSERT(self != NULL, return -EBADR;);
+ IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -EBADR;);
IRDA_DEBUG(2,
"%s(), slsap_sel=%02x, dlsap_sel=%02x, saddr=%08x, daddr=%08x\n",
@@ -404,7 +404,7 @@ int irlmp_connect_request(struct lsap_cb *self, __u8 dlsap_sel,
}
/* Make room for MUX control header (3 bytes) */
- ASSERT(skb_headroom(tx_skb) >= LMP_CONTROL_HEADER, return -1;);
+ IRDA_ASSERT(skb_headroom(tx_skb) >= LMP_CONTROL_HEADER, return -1;);
skb_push(tx_skb, LMP_CONTROL_HEADER);
self->dlsap_sel = dlsap_sel;
@@ -473,10 +473,10 @@ int irlmp_connect_request(struct lsap_cb *self, __u8 dlsap_sel,
*/
lsap = hashbin_remove(irlmp->unconnected_lsaps, (long) self, NULL);
- ASSERT(lsap != NULL, return -1;);
- ASSERT(lsap->magic == LMP_LSAP_MAGIC, return -1;);
- ASSERT(lsap->lap != NULL, return -1;);
- ASSERT(lsap->lap->magic == LMP_LAP_MAGIC, return -1;);
+ IRDA_ASSERT(lsap != NULL, return -1;);
+ IRDA_ASSERT(lsap->magic == LMP_LSAP_MAGIC, return -1;);
+ IRDA_ASSERT(lsap->lap != NULL, return -1;);
+ IRDA_ASSERT(lsap->lap->magic == LMP_LAP_MAGIC, return -1;);
hashbin_insert(self->lap->lsaps, (irda_queue_t *) self, (long) self,
NULL);
@@ -516,10 +516,10 @@ void irlmp_connect_indication(struct lsap_cb *self, struct sk_buff *skb)
int lap_header_size;
int max_header_size;
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
- ASSERT(skb != NULL, return;);
- ASSERT(self->lap != NULL, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
+ IRDA_ASSERT(skb != NULL, return;);
+ IRDA_ASSERT(self->lap != NULL, return;);
IRDA_DEBUG(2, "%s(), slsap_sel=%02x, dlsap_sel=%02x\n",
__FUNCTION__, self->slsap_sel, self->dlsap_sel);
@@ -555,9 +555,9 @@ void irlmp_connect_indication(struct lsap_cb *self, struct sk_buff *skb)
*/
int irlmp_connect_response(struct lsap_cb *self, struct sk_buff *userdata)
{
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
- ASSERT(userdata != NULL, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
+ IRDA_ASSERT(userdata != NULL, return -1;);
/* We set the connected bit and move the lsap to the connected list
* in the state machine itself. Jean II */
@@ -566,7 +566,7 @@ int irlmp_connect_response(struct lsap_cb *self, struct sk_buff *userdata)
__FUNCTION__, self->slsap_sel, self->dlsap_sel);
/* Make room for MUX control header (3 bytes) */
- ASSERT(skb_headroom(userdata) >= LMP_CONTROL_HEADER, return -1;);
+ IRDA_ASSERT(skb_headroom(userdata) >= LMP_CONTROL_HEADER, return -1;);
skb_push(userdata, LMP_CONTROL_HEADER);
irlmp_do_lsap_event(self, LM_CONNECT_RESPONSE, userdata);
@@ -591,10 +591,10 @@ void irlmp_connect_confirm(struct lsap_cb *self, struct sk_buff *skb)
IRDA_DEBUG(3, "%s()\n", __FUNCTION__);
- ASSERT(skb != NULL, return;);
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
- ASSERT(self->lap != NULL, return;);
+ IRDA_ASSERT(skb != NULL, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
+ IRDA_ASSERT(self->lap != NULL, return;);
self->qos = *self->lap->qos;
@@ -687,9 +687,9 @@ int irlmp_disconnect_request(struct lsap_cb *self, struct sk_buff *userdata)
{
struct lsap_cb *lsap;
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
- ASSERT(userdata != NULL, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
+ IRDA_ASSERT(userdata != NULL, return -1;);
/* Already disconnected ?
* There is a race condition between irlmp_disconnect_indication()
@@ -716,18 +716,18 @@ int irlmp_disconnect_request(struct lsap_cb *self, struct sk_buff *userdata)
* Remove LSAP from list of connected LSAPs for the particular link
* and insert it into the list of unconnected LSAPs
*/
- ASSERT(self->lap != NULL, return -1;);
- ASSERT(self->lap->magic == LMP_LAP_MAGIC, return -1;);
- ASSERT(self->lap->lsaps != NULL, return -1;);
+ IRDA_ASSERT(self->lap != NULL, return -1;);
+ IRDA_ASSERT(self->lap->magic == LMP_LAP_MAGIC, return -1;);
+ IRDA_ASSERT(self->lap->lsaps != NULL, return -1;);
lsap = hashbin_remove(self->lap->lsaps, (long) self, NULL);
#ifdef CONFIG_IRDA_CACHE_LAST_LSAP
self->lap->cache.valid = FALSE;
#endif
- ASSERT(lsap != NULL, return -1;);
- ASSERT(lsap->magic == LMP_LSAP_MAGIC, return -1;);
- ASSERT(lsap == self, return -1;);
+ IRDA_ASSERT(lsap != NULL, return -1;);
+ IRDA_ASSERT(lsap->magic == LMP_LSAP_MAGIC, return -1;);
+ IRDA_ASSERT(lsap == self, return -1;);
hashbin_insert(irlmp->unconnected_lsaps, (irda_queue_t *) self,
(long) self, NULL);
@@ -751,8 +751,8 @@ void irlmp_disconnect_indication(struct lsap_cb *self, LM_REASON reason,
struct lsap_cb *lsap;
IRDA_DEBUG(1, "%s(), reason=%s\n", __FUNCTION__, irlmp_reasons[reason]);
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
IRDA_DEBUG(3, "%s(), slsap_sel=%02x, dlsap_sel=%02x\n",
__FUNCTION__, self->slsap_sel, self->dlsap_sel);
@@ -769,16 +769,16 @@ void irlmp_disconnect_indication(struct lsap_cb *self, LM_REASON reason,
/*
* Remove association between this LSAP and the link it used
*/
- ASSERT(self->lap != NULL, return;);
- ASSERT(self->lap->lsaps != NULL, return;);
+ IRDA_ASSERT(self->lap != NULL, return;);
+ IRDA_ASSERT(self->lap->lsaps != NULL, return;);
lsap = hashbin_remove(self->lap->lsaps, (long) self, NULL);
#ifdef CONFIG_IRDA_CACHE_LAST_LSAP
self->lap->cache.valid = FALSE;
#endif
- ASSERT(lsap != NULL, return;);
- ASSERT(lsap == self, return;);
+ IRDA_ASSERT(lsap != NULL, return;);
+ IRDA_ASSERT(lsap == self, return;);
hashbin_insert(irlmp->unconnected_lsaps, (irda_queue_t *) lsap,
(long) lsap, NULL);
@@ -822,7 +822,7 @@ void irlmp_do_expiry(void)
*/
lap = (struct lap_cb *) hashbin_get_first(irlmp->links);
while (lap != NULL) {
- ASSERT(lap->magic == LMP_LAP_MAGIC, return;);
+ IRDA_ASSERT(lap->magic == LMP_LAP_MAGIC, return;);
if (lap->lap_state == LAP_STANDBY) {
/* Expire discoveries discovered on this link */
@@ -846,8 +846,8 @@ void irlmp_do_discovery(int nslots)
/* Make sure the value is sane */
if ((nslots != 1) && (nslots != 6) && (nslots != 8) && (nslots != 16)){
- WARNING("%s: invalid value for number of slots!\n",
- __FUNCTION__);
+ IRDA_WARNING("%s: invalid value for number of slots!\n",
+ __FUNCTION__);
nslots = sysctl_discovery_slots = 8;
}
@@ -870,7 +870,7 @@ void irlmp_do_discovery(int nslots)
*/
lap = (struct lap_cb *) hashbin_get_first(irlmp->links);
while (lap != NULL) {
- ASSERT(lap->magic == LMP_LAP_MAGIC, return;);
+ IRDA_ASSERT(lap->magic == LMP_LAP_MAGIC, return;);
if (lap->lap_state == LAP_STANDBY) {
/* Try to discover */
@@ -1017,7 +1017,7 @@ void irlmp_discovery_confirm(hashbin_t *log, DISCOVERY_MODE mode)
IRDA_DEBUG(3, "%s()\n", __FUNCTION__);
- ASSERT(log != NULL, return;);
+ IRDA_ASSERT(log != NULL, return;);
if (!(HASHBIN_GET_SIZE(log)))
return;
@@ -1052,7 +1052,7 @@ void irlmp_discovery_expiry(discinfo_t *expiries, int number)
IRDA_DEBUG(3, "%s()\n", __FUNCTION__);
- ASSERT(expiries != NULL, return;);
+ IRDA_ASSERT(expiries != NULL, return;);
/* For each client - notify callback may touch client list */
client = (irlmp_client_t *) hashbin_get_first(irlmp->clients);
@@ -1085,7 +1085,7 @@ discovery_t *irlmp_get_discovery_response(void)
{
IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
- ASSERT(irlmp != NULL, return NULL;);
+ IRDA_ASSERT(irlmp != NULL, return NULL;);
u16ho(irlmp->discovery_rsp.data.hints) = irlmp->hints.word;
@@ -1120,11 +1120,11 @@ int irlmp_data_request(struct lsap_cb *self, struct sk_buff *userdata)
{
int ret;
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
/* Make room for MUX header */
- ASSERT(skb_headroom(userdata) >= LMP_HEADER, return -1;);
+ IRDA_ASSERT(skb_headroom(userdata) >= LMP_HEADER, return -1;);
skb_push(userdata, LMP_HEADER);
ret = irlmp_do_lsap_event(self, LM_DATA_REQUEST, userdata);
@@ -1163,10 +1163,10 @@ int irlmp_udata_request(struct lsap_cb *self, struct sk_buff *userdata)
IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
- ASSERT(userdata != NULL, return -1;);
+ IRDA_ASSERT(userdata != NULL, return -1;);
/* Make room for MUX header */
- ASSERT(skb_headroom(userdata) >= LMP_HEADER, return -1;);
+ IRDA_ASSERT(skb_headroom(userdata) >= LMP_HEADER, return -1;);
skb_push(userdata, LMP_HEADER);
ret = irlmp_do_lsap_event(self, LM_UDATA_REQUEST, userdata);
@@ -1187,9 +1187,9 @@ void irlmp_udata_indication(struct lsap_cb *self, struct sk_buff *skb)
{
IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
- ASSERT(skb != NULL, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
+ IRDA_ASSERT(skb != NULL, return;);
/* Hide LMP header from layer above */
skb_pull(skb, LMP_HEADER);
@@ -1214,11 +1214,11 @@ int irlmp_connless_data_request(struct lsap_cb *self, struct sk_buff *userdata,
IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
- ASSERT(userdata != NULL, return -1;);
+ IRDA_ASSERT(userdata != NULL, return -1;);
/* Make room for MUX and PID header */
- ASSERT(skb_headroom(userdata) >= LMP_HEADER+LMP_PID_HEADER,
- return -1;);
+ IRDA_ASSERT(skb_headroom(userdata) >= LMP_HEADER+LMP_PID_HEADER,
+ return -1;);
/* Insert protocol identifier */
skb_push(userdata, LMP_PID_HEADER);
@@ -1234,7 +1234,7 @@ int irlmp_connless_data_request(struct lsap_cb *self, struct sk_buff *userdata,
/* Try to send Connectionless packets out on all links */
lap = (struct lap_cb *) hashbin_get_first(irlmp->links);
while (lap != NULL) {
- ASSERT(lap->magic == LMP_LAP_MAGIC, return -1;);
+ IRDA_ASSERT(lap->magic == LMP_LAP_MAGIC, return -1;);
clone_skb = skb_clone(userdata, GFP_ATOMIC);
if (!clone_skb) {
@@ -1265,9 +1265,9 @@ void irlmp_connless_data_indication(struct lsap_cb *self, struct sk_buff *skb)
{
IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
- ASSERT(skb != NULL, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
+ IRDA_ASSERT(skb != NULL, return;);
/* Hide LMP and PID header from layer above */
skb_pull(skb, LMP_HEADER+LMP_PID_HEADER);
@@ -1298,7 +1298,7 @@ void irlmp_status_indication(struct lap_cb *self,
curr = (struct lsap_cb *) hashbin_get_first( self->lsaps);
while (NULL != hashbin_find_next(self->lsaps, (long) curr, NULL,
(void *) &next) ) {
- ASSERT(curr->magic == LMP_LSAP_MAGIC, return;);
+ IRDA_ASSERT(curr->magic == LMP_LSAP_MAGIC, return;);
/*
* Inform service user if he has requested it
*/
@@ -1328,8 +1328,8 @@ void irlmp_flow_indication(struct lap_cb *self, LOCAL_FLOW flow)
struct lsap_cb *curr;
int lsap_todo;
- ASSERT(self->magic == LMP_LAP_MAGIC, return;);
- ASSERT(flow == FLOW_START, return;);
+ IRDA_ASSERT(self->magic == LMP_LAP_MAGIC, return;);
+ IRDA_ASSERT(flow == FLOW_START, return;);
/* Get the number of lsap. That's the only safe way to know
* that we have looped around... - Jean II */
@@ -1559,7 +1559,7 @@ void *irlmp_register_client(__u16 hint_mask, DISCOVERY_CALLBACK1 disco_clb,
irlmp_client_t *client;
IRDA_DEBUG(1, "%s()\n", __FUNCTION__);
- ASSERT(irlmp != NULL, return NULL;);
+ IRDA_ASSERT(irlmp != NULL, return NULL;);
/* Make a new registration */
client = kmalloc(sizeof(irlmp_client_t), GFP_ATOMIC);
@@ -1660,9 +1660,9 @@ static int irlmp_slsap_inuse(__u8 slsap_sel)
struct lap_cb *lap;
unsigned long flags;
- ASSERT(irlmp != NULL, return TRUE;);
- ASSERT(irlmp->magic == LMP_MAGIC, return TRUE;);
- ASSERT(slsap_sel != LSAP_ANY, return TRUE;);
+ IRDA_ASSERT(irlmp != NULL, return TRUE;);
+ IRDA_ASSERT(irlmp->magic == LMP_MAGIC, return TRUE;);
+ IRDA_ASSERT(slsap_sel != LSAP_ANY, return TRUE;);
IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
@@ -1684,7 +1684,7 @@ static int irlmp_slsap_inuse(__u8 slsap_sel)
spin_lock_irqsave(&irlmp->links->hb_spinlock, flags);
lap = (struct lap_cb *) hashbin_get_first(irlmp->links);
while (lap != NULL) {
- ASSERT(lap->magic == LMP_LAP_MAGIC, goto errlap;);
+ IRDA_ASSERT(lap->magic == LMP_LAP_MAGIC, goto errlap;);
/* Careful for priority inversions here !
* irlmp->links is never taken while another IrDA
@@ -1694,7 +1694,8 @@ static int irlmp_slsap_inuse(__u8 slsap_sel)
/* For this IrLAP, check all the LSAPs */
self = (struct lsap_cb *) hashbin_get_first(lap->lsaps);
while (self != NULL) {
- ASSERT(self->magic == LMP_LSAP_MAGIC, goto errlsap;);
+ IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC,
+ goto errlsap;);
if ((self->slsap_sel == slsap_sel)) {
IRDA_DEBUG(4, "Source LSAP selector=%02x in use\n",
@@ -1720,7 +1721,7 @@ static int irlmp_slsap_inuse(__u8 slsap_sel)
self = (struct lsap_cb *) hashbin_get_first(irlmp->unconnected_lsaps);
while (self != NULL) {
- ASSERT(self->magic == LMP_LSAP_MAGIC, goto erruncon;);
+ IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, goto erruncon;);
if ((self->slsap_sel == slsap_sel)) {
IRDA_DEBUG(4, "Source LSAP selector=%02x in use (unconnected)\n",
self->slsap_sel);
@@ -1737,7 +1738,7 @@ static int irlmp_slsap_inuse(__u8 slsap_sel)
* Jean II */
errlsap:
spin_unlock(&lap->lsaps->hb_spinlock);
-errlap:
+IRDA_ASSERT_LABEL(errlap:)
spin_unlock_irqrestore(&irlmp->links->hb_spinlock, flags);
return TRUE;
@@ -1759,8 +1760,8 @@ static __u8 irlmp_find_free_slsap(void)
__u8 lsap_sel;
int wrapped = 0;
- ASSERT(irlmp != NULL, return -1;);
- ASSERT(irlmp->magic == LMP_MAGIC, return -1;);
+ IRDA_ASSERT(irlmp != NULL, return -1;);
+ IRDA_ASSERT(irlmp->magic == LMP_MAGIC, return -1;);
/* Most users don't really care which LSAPs they are given,
* and therefore we automatically give them a free LSAP.
@@ -1788,8 +1789,8 @@ static __u8 irlmp_find_free_slsap(void)
/* Make sure we terminate the loop */
if (wrapped++) {
- ERROR("%s: no more free LSAPs !\n",
- __FUNCTION__);
+ IRDA_ERROR("%s: no more free LSAPs !\n",
+ __FUNCTION__);
return 0;
}
}
@@ -1948,7 +1949,7 @@ static int irlmp_seq_show(struct seq_file *seq, void *v)
seq_puts(seq, "\nRegistered Link Layers:\n");
else if (iter->hashbin == irlmp->unconnected_lsaps) {
self = v;
- ASSERT(self->magic == LMP_LSAP_MAGIC, return -EINVAL; );
+ IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -EINVAL; );
seq_printf(seq, "lsap state: %s, ",
irlsap_state[ self->lsap_state]);
seq_printf(seq,
@@ -1977,7 +1978,8 @@ static int irlmp_seq_show(struct seq_file *seq, void *v)
for (self = (struct lsap_cb *) hashbin_get_first(lap->lsaps);
self != NULL;
self = (struct lsap_cb *)hashbin_get_next(lap->lsaps)) {
- ASSERT(self->magic == LMP_LSAP_MAGIC, break;);
+ IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC,
+ goto outloop;);
seq_printf(seq, " lsap state: %s, ",
irlsap_state[ self->lsap_state]);
seq_printf(seq,
@@ -1987,6 +1989,7 @@ static int irlmp_seq_show(struct seq_file *seq, void *v)
seq_putc(seq, '\n');
}
+ IRDA_ASSERT_LABEL(outloop:)
spin_unlock(&lap->lsaps->hb_spinlock);
seq_putc(seq, '\n');
} else
@@ -2008,7 +2011,7 @@ static int irlmp_seq_open(struct inode *inode, struct file *file)
int rc = -ENOMEM;
struct irlmp_iter_state *s;
- ASSERT(irlmp != NULL, return -EINVAL;);
+ IRDA_ASSERT(irlmp != NULL, return -EINVAL;);
s = kmalloc(sizeof(*s), GFP_KERNEL);
if (!s)
diff --git a/net/irda/irlmp_event.c b/net/irda/irlmp_event.c
index d6e551226e5b7..26649f6528e6c 100644
--- a/net/irda/irlmp_event.c
+++ b/net/irda/irlmp_event.c
@@ -130,7 +130,7 @@ static inline void irlmp_next_lsap_state(struct lsap_cb *self,
LSAP_STATE state)
{
/*
- ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self != NULL, return;);
IRDA_DEBUG(4, "%s(), LMP LSAP = %s\n", __FUNCTION__, irlsap_state[state]);
*/
self->lsap_state = state;
@@ -140,8 +140,8 @@ static inline void irlmp_next_lsap_state(struct lsap_cb *self,
int irlmp_do_lsap_event(struct lsap_cb *self, IRLMP_EVENT event,
struct sk_buff *skb)
{
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
IRDA_DEBUG(4, "%s(), EVENT = %s, STATE = %s\n",
__FUNCTION__, irlmp_event[event], irlsap_state[ self->lsap_state]);
@@ -158,8 +158,8 @@ int irlmp_do_lsap_event(struct lsap_cb *self, IRLMP_EVENT event,
void irlmp_do_lap_event(struct lap_cb *self, IRLMP_EVENT event,
struct sk_buff *skb)
{
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LMP_LAP_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LMP_LAP_MAGIC, return;);
IRDA_DEBUG(4, "%s(), EVENT = %s, STATE = %s\n", __FUNCTION__,
irlmp_event[event],
@@ -189,8 +189,8 @@ void irlmp_watchdog_timer_expired(void *data)
IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
irlmp_do_lsap_event(self, LM_WATCHDOG_TIMEOUT, NULL);
}
@@ -201,8 +201,8 @@ void irlmp_idle_timer_expired(void *data)
IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LMP_LAP_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LMP_LAP_MAGIC, return;);
irlmp_do_lap_event(self, LM_LAP_IDLE_TIMEOUT, NULL);
}
@@ -260,7 +260,7 @@ static void irlmp_state_standby(struct lap_cb *self, IRLMP_EVENT event,
struct sk_buff *skb)
{
IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
- ASSERT(self->irlap != NULL, return;);
+ IRDA_ASSERT(self->irlap != NULL, return;);
switch (event) {
case LM_LAP_DISCOVERY_REQUEST:
@@ -495,8 +495,8 @@ static int irlmp_state_disconnected(struct lsap_cb *self, IRLMP_EVENT event,
IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
switch (event) {
#ifdef CONFIG_IRDA_ULTRA
@@ -511,8 +511,8 @@ static int irlmp_state_disconnected(struct lsap_cb *self, IRLMP_EVENT event,
IRDA_DEBUG(4, "%s(), LM_CONNECT_REQUEST\n", __FUNCTION__);
if (self->conn_skb) {
- WARNING("%s: busy with another request!\n",
- __FUNCTION__);
+ IRDA_WARNING("%s: busy with another request!\n",
+ __FUNCTION__);
return -EBUSY;
}
/* Don't forget to refcount it (see irlmp_connect_request()) */
@@ -528,8 +528,8 @@ static int irlmp_state_disconnected(struct lsap_cb *self, IRLMP_EVENT event,
break;
case LM_CONNECT_INDICATION:
if (self->conn_skb) {
- WARNING("%s: busy with another request!\n",
- __FUNCTION__);
+ IRDA_WARNING("%s: busy with another request!\n",
+ __FUNCTION__);
return -EBUSY;
}
/* Don't forget to refcount it (see irlap_driver_rcv()) */
@@ -575,8 +575,8 @@ static int irlmp_state_connect(struct lsap_cb *self, IRLMP_EVENT event,
IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
switch (event) {
case LM_CONNECT_RESPONSE:
@@ -587,9 +587,9 @@ static int irlmp_state_connect(struct lsap_cb *self, IRLMP_EVENT event,
lsap = hashbin_remove(irlmp->unconnected_lsaps, (long) self,
NULL);
- ASSERT(lsap == self, return -1;);
- ASSERT(self->lap != NULL, return -1;);
- ASSERT(self->lap->lsaps != NULL, return -1;);
+ IRDA_ASSERT(lsap == self, return -1;);
+ IRDA_ASSERT(self->lap != NULL, return -1;);
+ IRDA_ASSERT(self->lap->lsaps != NULL, return -1;);
hashbin_insert(self->lap->lsaps, (irda_queue_t *) self,
(long) self, NULL);
@@ -637,8 +637,8 @@ static int irlmp_state_connect_pend(struct lsap_cb *self, IRLMP_EVENT event,
IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
switch (event) {
case LM_CONNECT_REQUEST:
@@ -703,9 +703,9 @@ static int irlmp_state_dtr(struct lsap_cb *self, IRLMP_EVENT event,
IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
- ASSERT(self->lap != NULL, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
+ IRDA_ASSERT(self->lap != NULL, return -1;);
switch (event) {
case LM_DATA_REQUEST: /* Optimize for the common case */
@@ -716,7 +716,7 @@ static int irlmp_state_dtr(struct lsap_cb *self, IRLMP_EVENT event,
irlmp_data_indication(self, skb);
break;
case LM_UDATA_REQUEST:
- ASSERT(skb != NULL, return -1;);
+ IRDA_ASSERT(skb != NULL, return -1;);
irlmp_send_data_pdu(self->lap, self->dlsap_sel,
self->slsap_sel, TRUE, skb);
break;
@@ -759,11 +759,11 @@ static int irlmp_state_dtr(struct lsap_cb *self, IRLMP_EVENT event,
case LM_DISCONNECT_INDICATION:
irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
- ASSERT(self->lap != NULL, return -1;);
- ASSERT(self->lap->magic == LMP_LAP_MAGIC, return -1;);
+ IRDA_ASSERT(self->lap != NULL, return -1;);
+ IRDA_ASSERT(self->lap->magic == LMP_LAP_MAGIC, return -1;);
- ASSERT(skb != NULL, return -1;);
- ASSERT(skb->len > 3, return -1;);
+ IRDA_ASSERT(skb != NULL, return -1;);
+ IRDA_ASSERT(skb->len > 3, return -1;);
reason = skb->data[3];
/* Try to close the LAP connection */
@@ -793,8 +793,8 @@ static int irlmp_state_setup(struct lsap_cb *self, IRLMP_EVENT event,
LM_REASON reason;
int ret = 0;
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
@@ -809,11 +809,11 @@ static int irlmp_state_setup(struct lsap_cb *self, IRLMP_EVENT event,
case LM_DISCONNECT_INDICATION:
irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
- ASSERT(self->lap != NULL, return -1;);
- ASSERT(self->lap->magic == LMP_LAP_MAGIC, return -1;);
+ IRDA_ASSERT(self->lap != NULL, return -1;);
+ IRDA_ASSERT(self->lap->magic == LMP_LAP_MAGIC, return -1;);
- ASSERT(skb != NULL, return -1;);
- ASSERT(skb->len > 3, return -1;);
+ IRDA_ASSERT(skb != NULL, return -1;);
+ IRDA_ASSERT(skb->len > 3, return -1;);
reason = skb->data[3];
/* Try to close the LAP connection */
@@ -827,8 +827,8 @@ static int irlmp_state_setup(struct lsap_cb *self, IRLMP_EVENT event,
del_timer(&self->watchdog_timer);
- ASSERT(self->lap != NULL, return -1;);
- ASSERT(self->lap->magic == LMP_LAP_MAGIC, return -1;);
+ IRDA_ASSERT(self->lap != NULL, return -1;);
+ IRDA_ASSERT(self->lap->magic == LMP_LAP_MAGIC, return -1;);
reason = irlmp_convert_lap_reason(self->lap->reason);
@@ -837,7 +837,7 @@ static int irlmp_state_setup(struct lsap_cb *self, IRLMP_EVENT event,
case LM_WATCHDOG_TIMEOUT:
IRDA_DEBUG(0, "%s() WATCHDOG_TIMEOUT!\n", __FUNCTION__);
- ASSERT(self->lap != NULL, return -1;);
+ IRDA_ASSERT(self->lap != NULL, return -1;);
irlmp_do_lap_event(self->lap, LM_LAP_DISCONNECT_REQUEST, NULL);
irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
@@ -868,12 +868,12 @@ static int irlmp_state_setup_pend(struct lsap_cb *self, IRLMP_EVENT event,
IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
- ASSERT(self != NULL, return -1;);
- ASSERT(irlmp != NULL, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(irlmp != NULL, return -1;);
switch (event) {
case LM_LAP_CONNECT_CONFIRM:
- ASSERT(self->conn_skb != NULL, return -1;);
+ IRDA_ASSERT(self->conn_skb != NULL, return -1;);
tx_skb = self->conn_skb;
self->conn_skb = NULL;
@@ -888,7 +888,7 @@ static int irlmp_state_setup_pend(struct lsap_cb *self, IRLMP_EVENT event,
case LM_WATCHDOG_TIMEOUT:
IRDA_DEBUG(0, "%s() : WATCHDOG_TIMEOUT !\n", __FUNCTION__);
- ASSERT(self->lap != NULL, return -1;);
+ IRDA_ASSERT(self->lap != NULL, return -1;);
irlmp_do_lap_event(self->lap, LM_LAP_DISCONNECT_REQUEST, NULL);
irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
diff --git a/net/irda/irlmp_frame.c b/net/irda/irlmp_frame.c
index c00ccfd31022a..91cd268172fa0 100644
--- a/net/irda/irlmp_frame.c
+++ b/net/irda/irlmp_frame.c
@@ -63,9 +63,9 @@ void irlmp_send_lcf_pdu(struct lap_cb *self, __u8 dlsap, __u8 slsap,
IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LMP_LAP_MAGIC, return;);
- ASSERT(skb != NULL, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LMP_LAP_MAGIC, return;);
+ IRDA_ASSERT(skb != NULL, return;);
frame = skb->data;
@@ -98,9 +98,9 @@ void irlmp_link_data_indication(struct lap_cb *self, struct sk_buff *skb,
IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LMP_LAP_MAGIC, return;);
- ASSERT(skb->len > 2, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LMP_LAP_MAGIC, return;);
+ IRDA_ASSERT(skb->len > 2, return;);
fp = skb->data;
@@ -209,9 +209,9 @@ void irlmp_link_unitdata_indication(struct lap_cb *self, struct sk_buff *skb)
IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LMP_LAP_MAGIC, return;);
- ASSERT(skb->len > 2, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LMP_LAP_MAGIC, return;);
+ IRDA_ASSERT(skb->len > 2, return;);
fp = skb->data;
@@ -273,8 +273,8 @@ void irlmp_link_disconnect_indication(struct lap_cb *lap,
{
IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
- ASSERT(lap != NULL, return;);
- ASSERT(lap->magic == LMP_LAP_MAGIC, return;);
+ IRDA_ASSERT(lap != NULL, return;);
+ IRDA_ASSERT(lap->magic == LMP_LAP_MAGIC, return;);
lap->reason = reason;
lap->daddr = DEV_ADDR_ANY;
@@ -304,7 +304,7 @@ void irlmp_link_connect_indication(struct lap_cb *self, __u32 saddr,
/* Update destination device address */
self->daddr = daddr;
- ASSERT(self->saddr == saddr, return;);
+ IRDA_ASSERT(self->saddr == saddr, return;);
irlmp_do_lap_event(self, LM_LAP_CONNECT_INDICATION, skb);
}
@@ -320,9 +320,9 @@ void irlmp_link_connect_confirm(struct lap_cb *self, struct qos_info *qos,
{
IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LMP_LAP_MAGIC, return;);
- ASSERT(qos != NULL, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LMP_LAP_MAGIC, return;);
+ IRDA_ASSERT(qos != NULL, return;);
/* Don't need use the skb for now */
@@ -363,8 +363,8 @@ void irlmp_link_connect_confirm(struct lap_cb *self, struct qos_info *qos,
void irlmp_link_discovery_indication(struct lap_cb *self,
discovery_t *discovery)
{
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LMP_LAP_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LMP_LAP_MAGIC, return;);
/* Add to main log, cleanup */
irlmp_add_discovery(irlmp->cachelog, discovery);
@@ -386,8 +386,8 @@ void irlmp_link_discovery_confirm(struct lap_cb *self, hashbin_t *log)
{
IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LMP_LAP_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LMP_LAP_MAGIC, return;);
/* Add to main log, cleanup */
irlmp_add_discovery_log(irlmp->cachelog, log);
diff --git a/net/irda/irnet/irnet_irda.c b/net/irda/irnet/irnet_irda.c
index 307025519802b..07ec326c71f5b 100644
--- a/net/irda/irnet/irnet_irda.c
+++ b/net/irda/irnet/irnet_irda.c
@@ -632,7 +632,7 @@ irda_irnet_destroy(irnet_socket * self)
self->iriap = NULL;
}
- /* Cleanup eventual discoveries from connection attempt */
+ /* Cleanup eventual discoveries from connection attempt or control channel */
if(self->discoveries != NULL)
{
/* Cleanup our copy of the discovery log */
diff --git a/net/irda/irnet/irnet_ppp.c b/net/irda/irnet/irnet_ppp.c
index 123f92fb63a67..f8f984bb99225 100644
--- a/net/irda/irnet/irnet_ppp.c
+++ b/net/irda/irnet/irnet_ppp.c
@@ -171,18 +171,44 @@ irnet_ctrl_write(irnet_socket * ap,
#ifdef INITIAL_DISCOVERY
/*------------------------------------------------------------------*/
/*
- * Function irnet_read_discovery_log (self)
+ * Function irnet_get_discovery_log (self)
+ *
+ * Query the content on the discovery log if not done
+ *
+ * This function query the current content of the discovery log
+ * at the startup of the event channel and save it in the internal struct.
+ */
+static void
+irnet_get_discovery_log(irnet_socket * ap)
+{
+ __u16 mask = irlmp_service_to_hint(S_LAN);
+
+ /* Ask IrLMP for the current discovery log */
+ ap->discoveries = irlmp_get_discoveries(&ap->disco_number, mask,
+ DISCOVERY_DEFAULT_SLOTS);
+
+ /* Check if the we got some results */
+ if(ap->discoveries == NULL)
+ ap->disco_number = -1;
+
+ DEBUG(CTRL_INFO, "Got the log (0x%p), size is %d\n",
+ ap->discoveries, ap->disco_number);
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Function irnet_read_discovery_log (self, event)
*
* Read the content on the discovery log
*
* This function dump the current content of the discovery log
* at the startup of the event channel.
- * Return 1 if written on the control channel...
+ * Return 1 if wrote an event on the control channel...
*
* State of the ap->disco_XXX variables :
- * at socket creation : disco_index = 0 ; disco_number = 0
- * while reading : disco_index = X ; disco_number = Y
- * After reading : disco_index = Y ; disco_number = -1
+ * Socket creation : discoveries = NULL ; disco_index = 0 ; disco_number = 0
+ * While reading : discoveries = ptr ; disco_index = X ; disco_number = Y
+ * After reading : discoveries = NULL ; disco_index = Y ; disco_number = -1
*/
static inline int
irnet_read_discovery_log(irnet_socket * ap,
@@ -201,19 +227,8 @@ irnet_read_discovery_log(irnet_socket * ap,
}
/* Test if it's the first time and therefore we need to get the log */
- if(ap->disco_index == 0)
- {
- __u16 mask = irlmp_service_to_hint(S_LAN);
-
- /* Ask IrLMP for the current discovery log */
- ap->discoveries = irlmp_get_discoveries(&ap->disco_number, mask,
- DISCOVERY_DEFAULT_SLOTS);
- /* Check if the we got some results */
- if(ap->discoveries == NULL)
- ap->disco_number = -1;
- DEBUG(CTRL_INFO, "Got the log (0x%p), size is %d\n",
- ap->discoveries, ap->disco_number);
- }
+ if(ap->discoveries == NULL)
+ irnet_get_discovery_log(ap);
/* Check if we have more item to dump */
if(ap->disco_index < ap->disco_number)
@@ -417,7 +432,14 @@ irnet_ctrl_poll(irnet_socket * ap,
mask |= POLLIN | POLLRDNORM;
#ifdef INITIAL_DISCOVERY
if(ap->disco_number != -1)
- mask |= POLLIN | POLLRDNORM;
+ {
+ /* Test if it's the first time and therefore we need to get the log */
+ if(ap->discoveries == NULL)
+ irnet_get_discovery_log(ap);
+ /* Recheck */
+ if(ap->disco_number != -1)
+ mask |= POLLIN | POLLRDNORM;
+ }
#endif /* INITIAL_DISCOVERY */
DEXIT(CTRL_TRACE, " - mask=0x%X\n", mask);
diff --git a/net/irda/irqueue.c b/net/irda/irqueue.c
index ca948a000ad22..b0dd3ea359996 100644
--- a/net/irda/irqueue.c
+++ b/net/irda/irqueue.c
@@ -391,8 +391,8 @@ int hashbin_delete( hashbin_t* hashbin, FREE_FUNC free_func)
unsigned long flags = 0;
int i;
- ASSERT(hashbin != NULL, return -1;);
- ASSERT(hashbin->magic == HB_MAGIC, return -1;);
+ IRDA_ASSERT(hashbin != NULL, return -1;);
+ IRDA_ASSERT(hashbin->magic == HB_MAGIC, return -1;);
/* Synchronize */
if ( hashbin->hb_type & HB_LOCK ) {
@@ -447,8 +447,8 @@ void hashbin_insert(hashbin_t* hashbin, irda_queue_t* entry, long hashv,
IRDA_DEBUG( 4, "%s()\n", __FUNCTION__);
- ASSERT( hashbin != NULL, return;);
- ASSERT( hashbin->magic == HB_MAGIC, return;);
+ IRDA_ASSERT( hashbin != NULL, return;);
+ IRDA_ASSERT( hashbin->magic == HB_MAGIC, return;);
/*
* Locate hashbin
@@ -560,8 +560,8 @@ void* hashbin_remove( hashbin_t* hashbin, long hashv, const char* name)
IRDA_DEBUG( 4, "%s()\n", __FUNCTION__);
- ASSERT( hashbin != NULL, return NULL;);
- ASSERT( hashbin->magic == HB_MAGIC, return NULL;);
+ IRDA_ASSERT( hashbin != NULL, return NULL;);
+ IRDA_ASSERT( hashbin->magic == HB_MAGIC, return NULL;);
/*
* Locate hashbin
@@ -653,9 +653,9 @@ void* hashbin_remove_this( hashbin_t* hashbin, irda_queue_t* entry)
IRDA_DEBUG( 4, "%s()\n", __FUNCTION__);
- ASSERT( hashbin != NULL, return NULL;);
- ASSERT( hashbin->magic == HB_MAGIC, return NULL;);
- ASSERT( entry != NULL, return NULL;);
+ IRDA_ASSERT( hashbin != NULL, return NULL;);
+ IRDA_ASSERT( hashbin->magic == HB_MAGIC, return NULL;);
+ IRDA_ASSERT( entry != NULL, return NULL;);
/* Synchronize */
if ( hashbin->hb_type & HB_LOCK ) {
@@ -714,8 +714,8 @@ void* hashbin_find( hashbin_t* hashbin, long hashv, const char* name )
IRDA_DEBUG( 4, "hashbin_find()\n");
- ASSERT( hashbin != NULL, return NULL;);
- ASSERT( hashbin->magic == HB_MAGIC, return NULL;);
+ IRDA_ASSERT( hashbin != NULL, return NULL;);
+ IRDA_ASSERT( hashbin->magic == HB_MAGIC, return NULL;);
/*
* Locate hashbin
@@ -836,8 +836,8 @@ irda_queue_t *hashbin_get_first( hashbin_t* hashbin)
irda_queue_t *entry;
int i;
- ASSERT( hashbin != NULL, return NULL;);
- ASSERT( hashbin->magic == HB_MAGIC, return NULL;);
+ IRDA_ASSERT( hashbin != NULL, return NULL;);
+ IRDA_ASSERT( hashbin->magic == HB_MAGIC, return NULL;);
if ( hashbin == NULL)
return NULL;
@@ -872,11 +872,11 @@ irda_queue_t *hashbin_get_next( hashbin_t *hashbin)
int bin;
int i;
- ASSERT( hashbin != NULL, return NULL;);
- ASSERT( hashbin->magic == HB_MAGIC, return NULL;);
+ IRDA_ASSERT( hashbin != NULL, return NULL;);
+ IRDA_ASSERT( hashbin->magic == HB_MAGIC, return NULL;);
if ( hashbin->hb_current == NULL) {
- ASSERT( hashbin->hb_current != NULL, return NULL;);
+ IRDA_ASSERT( hashbin->hb_current != NULL, return NULL;);
return NULL;
}
entry = hashbin->hb_current->q_next;
diff --git a/net/irda/irttp.c b/net/irda/irttp.c
index 1a8d3b17aee26..d091ccf773b3d 100644
--- a/net/irda/irttp.c
+++ b/net/irda/irttp.c
@@ -98,7 +98,8 @@ int __init irttp_init(void)
irttp->tsaps = hashbin_new(HB_LOCK);
if (!irttp->tsaps) {
- ERROR("%s: can't allocate IrTTP hashbin!\n", __FUNCTION__);
+ IRDA_ERROR("%s: can't allocate IrTTP hashbin!\n",
+ __FUNCTION__);
return -ENOMEM;
}
@@ -114,8 +115,8 @@ int __init irttp_init(void)
void __exit irttp_cleanup(void)
{
/* Check for main structure */
- ASSERT(irttp != NULL, return;);
- ASSERT(irttp->magic == TTP_MAGIC, return;);
+ IRDA_ASSERT(irttp != NULL, return;);
+ IRDA_ASSERT(irttp->magic == TTP_MAGIC, return;);
/*
* Delete hashbin and close all TSAP instances in it
@@ -210,8 +211,8 @@ void irttp_flush_queues(struct tsap_cb *self)
IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
/* Deallocate frames waiting to be sent */
while ((skb = skb_dequeue(&self->tx_queue)) != NULL)
@@ -238,8 +239,8 @@ static struct sk_buff *irttp_reassemble_skb(struct tsap_cb *self)
struct sk_buff *skb, *frag;
int n = 0; /* Fragment index */
- ASSERT(self != NULL, return NULL;);
- ASSERT(self->magic == TTP_TSAP_MAGIC, return NULL;);
+ IRDA_ASSERT(self != NULL, return NULL;);
+ IRDA_ASSERT(self->magic == TTP_TSAP_MAGIC, return NULL;);
IRDA_DEBUG(2, "%s(), self->rx_sdu_size=%d\n", __FUNCTION__,
self->rx_sdu_size);
@@ -274,7 +275,7 @@ static struct sk_buff *irttp_reassemble_skb(struct tsap_cb *self)
* droped the last fragment (when self->rx_sdu_size exceed
* self->rx_max_sdu_size), where n < self->rx_sdu_size.
* Jean II */
- ASSERT(n <= self->rx_sdu_size, n = self->rx_sdu_size;);
+ IRDA_ASSERT(n <= self->rx_sdu_size, n = self->rx_sdu_size;);
/* Set the new length */
skb_trim(skb, n);
@@ -298,9 +299,9 @@ static inline void irttp_fragment_skb(struct tsap_cb *self,
IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
- ASSERT(skb != NULL, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
+ IRDA_ASSERT(skb != NULL, return;);
/*
* Split frame into a number of segments
@@ -353,8 +354,8 @@ static int irttp_param_max_sdu_size(void *instance, irda_param_t *param,
self = (struct tsap_cb *) instance;
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
if (get)
param->pv.i = self->tx_max_sdu_size;
@@ -381,8 +382,8 @@ struct tsap_cb *irttp_open_tsap(__u8 stsap_sel, int credit, notify_t *notify)
struct lsap_cb *lsap;
notify_t ttp_notify;
- ASSERT(irttp != NULL, return NULL;);
- ASSERT(irttp->magic == TTP_MAGIC, return NULL;);
+ IRDA_ASSERT(irttp != NULL, return NULL;);
+ IRDA_ASSERT(irttp->magic == TTP_MAGIC, return NULL;);
/* The IrLMP spec (IrLMP 1.1 p10) says that we have the right to
* use only 0x01-0x6F. Of course, we can use LSAP_ANY as well.
@@ -430,7 +431,7 @@ struct tsap_cb *irttp_open_tsap(__u8 stsap_sel, int credit, notify_t *notify)
*/
lsap = irlmp_open_lsap(stsap_sel, &ttp_notify, 0);
if (lsap == NULL) {
- WARNING("%s: unable to allocate LSAP!!\n", __FUNCTION__);
+ IRDA_WARNING("%s: unable to allocate LSAP!!\n", __FUNCTION__);
return NULL;
}
@@ -466,8 +467,8 @@ EXPORT_SYMBOL(irttp_open_tsap);
static void __irttp_close_tsap(struct tsap_cb *self)
{
/* First make sure we're connected. */
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
irttp_flush_queues(self);
@@ -500,14 +501,15 @@ int irttp_close_tsap(struct tsap_cb *self)
IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
/* Make sure tsap has been disconnected */
if (self->connected) {
/* Check if disconnect is not pending */
if (!test_bit(0, &self->disconnect_pend)) {
- WARNING("%s: TSAP still connected!\n", __FUNCTION__);
+ IRDA_WARNING("%s: TSAP still connected!\n",
+ __FUNCTION__);
irttp_disconnect_request(self, NULL, P_NORMAL);
}
self->close_pend = TRUE;
@@ -518,7 +520,7 @@ int irttp_close_tsap(struct tsap_cb *self)
tsap = hashbin_remove(irttp->tsaps, (long) self, NULL);
- ASSERT(tsap == self, return -1;);
+ IRDA_ASSERT(tsap == self, return -1;);
/* Close corresponding LSAP */
if (self->lsap) {
@@ -540,9 +542,9 @@ EXPORT_SYMBOL(irttp_close_tsap);
*/
int irttp_udata_request(struct tsap_cb *self, struct sk_buff *skb)
{
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
- ASSERT(skb != NULL, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
+ IRDA_ASSERT(skb != NULL, return -1;);
IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
@@ -582,16 +584,16 @@ int irttp_data_request(struct tsap_cb *self, struct sk_buff *skb)
__u8 *frame;
int ret;
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
- ASSERT(skb != NULL, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
+ IRDA_ASSERT(skb != NULL, return -1;);
IRDA_DEBUG(2, "%s() : queue len = %d\n", __FUNCTION__,
skb_queue_len(&self->tx_queue));
/* Check that nothing bad happens */
if ((skb->len == 0) || (!self->connected)) {
- WARNING("%s: No data, or not connected\n", __FUNCTION__);
+ IRDA_WARNING("%s: No data, or not connected\n", __FUNCTION__);
ret = -ENOTCONN;
goto err;
}
@@ -601,8 +603,8 @@ int irttp_data_request(struct tsap_cb *self, struct sk_buff *skb)
* inside an IrLAP frame
*/
if ((self->tx_max_sdu_size == 0) && (skb->len > self->max_seg_size)) {
- ERROR("%s: SAR disabled, and data is to large for IrLAP!\n",
- __FUNCTION__);
+ IRDA_ERROR("%s: SAR disabled, and data is to large for IrLAP!\n",
+ __FUNCTION__);
ret = -EMSGSIZE;
goto err;
}
@@ -615,8 +617,8 @@ int irttp_data_request(struct tsap_cb *self, struct sk_buff *skb)
(self->tx_max_sdu_size != TTP_SAR_UNBOUND) &&
(skb->len > self->tx_max_sdu_size))
{
- ERROR("%s: SAR enabled, but data is larger than TxMaxSduSize!\n",
- __FUNCTION__);
+ IRDA_ERROR("%s: SAR enabled, but data is larger than TxMaxSduSize!\n",
+ __FUNCTION__);
ret = -EMSGSIZE;
goto err;
}
@@ -638,7 +640,7 @@ int irttp_data_request(struct tsap_cb *self, struct sk_buff *skb)
/* Queue frame, or queue frame segments */
if ((self->tx_max_sdu_size == 0) || (skb->len < self->max_seg_size)) {
/* Queue frame */
- ASSERT(skb_headroom(skb) >= TTP_HEADER, return -1;);
+ IRDA_ASSERT(skb_headroom(skb) >= TTP_HEADER, return -1;);
frame = skb_push(skb, TTP_HEADER);
frame[0] = 0x00; /* Clear more bit */
@@ -800,8 +802,8 @@ static inline void irttp_give_credit(struct tsap_cb *self)
unsigned long flags;
int n;
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
IRDA_DEBUG(4, "%s() send=%d,avail=%d,remote=%d\n",
__FUNCTION__,
@@ -857,9 +859,9 @@ static int irttp_udata_indication(void *instance, void *sap,
self = (struct tsap_cb *) instance;
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
- ASSERT(skb != NULL, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
+ IRDA_ASSERT(skb != NULL, return -1;);
self->stats.rx_packets++;
@@ -974,8 +976,8 @@ static void irttp_status_indication(void *instance,
self = (struct tsap_cb *) instance;
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
/* Check if client has already closed the TSAP and gone away */
if (self->close_pend)
@@ -1003,8 +1005,8 @@ static void irttp_flow_indication(void *instance, void *sap, LOCAL_FLOW flow)
self = (struct tsap_cb *) instance;
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
IRDA_DEBUG(4, "%s(instance=%p)\n", __FUNCTION__, self);
@@ -1046,8 +1048,8 @@ void irttp_flow_request(struct tsap_cb *self, LOCAL_FLOW flow)
{
IRDA_DEBUG(1, "%s()\n", __FUNCTION__);
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
switch (flow) {
case FLOW_STOP:
@@ -1086,8 +1088,8 @@ int irttp_connect_request(struct tsap_cb *self, __u8 dtsap_sel,
IRDA_DEBUG(4, "%s(), max_sdu_size=%d\n", __FUNCTION__, max_sdu_size);
- ASSERT(self != NULL, return -EBADR;);
- ASSERT(self->magic == TTP_TSAP_MAGIC, return -EBADR;);
+ IRDA_ASSERT(self != NULL, return -EBADR;);
+ IRDA_ASSERT(self->magic == TTP_TSAP_MAGIC, return -EBADR;);
if (self->connected) {
if(userdata)
@@ -1109,8 +1111,8 @@ int irttp_connect_request(struct tsap_cb *self, __u8 dtsap_sel,
* Check that the client has reserved enough space for
* headers
*/
- ASSERT(skb_headroom(userdata) >= TTP_MAX_HEADER,
- { dev_kfree_skb(userdata); return -1; } );
+ IRDA_ASSERT(skb_headroom(userdata) >= TTP_MAX_HEADER,
+ { dev_kfree_skb(userdata); return -1; } );
}
/* Initialize connection parameters */
@@ -1138,8 +1140,8 @@ int irttp_connect_request(struct tsap_cb *self, __u8 dtsap_sel,
/* SAR enabled? */
if (max_sdu_size > 0) {
- ASSERT(skb_headroom(tx_skb) >= (TTP_MAX_HEADER + TTP_SAR_HEADER),
- { dev_kfree_skb(tx_skb); return -1; } );
+ IRDA_ASSERT(skb_headroom(tx_skb) >= (TTP_MAX_HEADER + TTP_SAR_HEADER),
+ { dev_kfree_skb(tx_skb); return -1; } );
/* Insert SAR parameters */
frame = skb_push(tx_skb, TTP_HEADER+TTP_SAR_HEADER);
@@ -1185,9 +1187,9 @@ static void irttp_connect_confirm(void *instance, void *sap,
self = (struct tsap_cb *) instance;
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
- ASSERT(skb != NULL, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
+ IRDA_ASSERT(skb != NULL, return;);
self->max_seg_size = max_seg_size - TTP_HEADER;
self->max_header_size = max_header_size + TTP_HEADER;
@@ -1213,7 +1215,7 @@ static void irttp_connect_confirm(void *instance, void *sap,
parameters = skb->data[0] & 0x80;
- ASSERT(skb->len >= TTP_HEADER, return;);
+ IRDA_ASSERT(skb->len >= TTP_HEADER, return;);
skb_pull(skb, TTP_HEADER);
if (parameters) {
@@ -1225,8 +1227,8 @@ static void irttp_connect_confirm(void *instance, void *sap,
/* Any errors in the parameter list? */
if (ret < 0) {
- WARNING("%s: error extracting parameters\n",
- __FUNCTION__);
+ IRDA_WARNING("%s: error extracting parameters\n",
+ __FUNCTION__);
dev_kfree_skb(skb);
/* Do not accept this connection attempt */
@@ -1269,9 +1271,9 @@ void irttp_connect_indication(void *instance, void *sap, struct qos_info *qos,
self = (struct tsap_cb *) instance;
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
- ASSERT(skb != NULL, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
+ IRDA_ASSERT(skb != NULL, return;);
lsap = (struct lsap_cb *) sap;
@@ -1290,7 +1292,7 @@ void irttp_connect_indication(void *instance, void *sap, struct qos_info *qos,
parameters = skb->data[0] & 0x80;
- ASSERT(skb->len >= TTP_HEADER, return;);
+ IRDA_ASSERT(skb->len >= TTP_HEADER, return;);
skb_pull(skb, TTP_HEADER);
if (parameters) {
@@ -1302,8 +1304,8 @@ void irttp_connect_indication(void *instance, void *sap, struct qos_info *qos,
/* Any errors in the parameter list? */
if (ret < 0) {
- WARNING("%s: error extracting parameters\n",
- __FUNCTION__);
+ IRDA_WARNING("%s: error extracting parameters\n",
+ __FUNCTION__);
dev_kfree_skb(skb);
/* Do not accept this connection attempt */
@@ -1337,8 +1339,8 @@ int irttp_connect_response(struct tsap_cb *self, __u32 max_sdu_size,
int ret;
__u8 n;
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
IRDA_DEBUG(4, "%s(), Source TSAP selector=%02x\n", __FUNCTION__,
self->stsap_sel);
@@ -1357,8 +1359,8 @@ int irttp_connect_response(struct tsap_cb *self, __u32 max_sdu_size,
* Check that the client has reserved enough space for
* headers
*/
- ASSERT(skb_headroom(userdata) >= TTP_MAX_HEADER,
- { dev_kfree_skb(userdata); return -1; } );
+ IRDA_ASSERT(skb_headroom(userdata) >= TTP_MAX_HEADER,
+ { dev_kfree_skb(userdata); return -1; } );
}
self->avail_credit = 0;
@@ -1380,8 +1382,8 @@ int irttp_connect_response(struct tsap_cb *self, __u32 max_sdu_size,
/* SAR enabled? */
if (max_sdu_size > 0) {
- ASSERT(skb_headroom(tx_skb) >= (TTP_MAX_HEADER + TTP_SAR_HEADER),
- { dev_kfree_skb(tx_skb); return -1; } );
+ IRDA_ASSERT(skb_headroom(tx_skb) >= (TTP_MAX_HEADER + TTP_SAR_HEADER),
+ { dev_kfree_skb(tx_skb); return -1; } );
/* Insert TTP header with SAR parameters */
frame = skb_push(tx_skb, TTP_HEADER+TTP_SAR_HEADER);
@@ -1481,8 +1483,8 @@ int irttp_disconnect_request(struct tsap_cb *self, struct sk_buff *userdata,
{
int ret;
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
/* Already disconnected? */
if (!self->connected) {
@@ -1579,8 +1581,8 @@ void irttp_disconnect_indication(void *instance, void *sap, LM_REASON reason,
self = (struct tsap_cb *) instance;
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
/* Prevent higher layer to send more data */
self->connected = FALSE;
@@ -1879,7 +1881,7 @@ static int irttp_seq_open(struct inode *inode, struct file *file)
int rc = -ENOMEM;
struct irttp_iter_state *s;
- ASSERT(irttp != NULL, return -EINVAL;);
+ IRDA_ASSERT(irttp != NULL, return -EINVAL;);
s = kmalloc(sizeof(*s), GFP_KERNEL);
if (!s)
diff --git a/net/irda/parameters.c b/net/irda/parameters.c
index 9d26cba2c3eb9..1324942f976c2 100644
--- a/net/irda/parameters.c
+++ b/net/irda/parameters.c
@@ -160,7 +160,8 @@ static int irda_insert_integer(void *self, __u8 *buf, int len, __u8 pi,
}
/* Check if buffer is long enough for insertion */
if (len < (2+p.pl)) {
- WARNING("%s: buffer to short for insertion!\n", __FUNCTION__);
+ IRDA_WARNING("%s: buffer to short for insertion!\n",
+ __FUNCTION__);
return -1;
}
IRDA_DEBUG(2, "%s(), pi=%#x, pl=%d, pi=%d\n", __FUNCTION__,
@@ -185,7 +186,8 @@ static int irda_insert_integer(void *self, __u8 *buf, int len, __u8 pi,
break;
default:
- WARNING("%s: length %d not supported\n", __FUNCTION__, p.pl);
+ IRDA_WARNING("%s: length %d not supported\n",
+ __FUNCTION__, p.pl);
/* Skip parameter */
return -1;
}
@@ -214,9 +216,9 @@ static int irda_extract_integer(void *self, __u8 *buf, int len, __u8 pi,
/* Check if buffer is long enough for parsing */
if (len < (2+p.pl)) {
- WARNING("%s: buffer to short for parsing! "
- "Need %d bytes, but len is only %d\n",
- __FUNCTION__, p.pl, len);
+ IRDA_WARNING("%s: buffer to short for parsing! "
+ "Need %d bytes, but len is only %d\n",
+ __FUNCTION__, p.pl, len);
return -1;
}
@@ -226,9 +228,9 @@ static int irda_extract_integer(void *self, __u8 *buf, int len, __u8 pi,
* PV_INTEGER means that the handler is flexible.
*/
if (((type & PV_MASK) != PV_INTEGER) && ((type & PV_MASK) != p.pl)) {
- ERROR("%s: invalid parameter length! "
- "Expected %d bytes, but value had %d bytes!\n",
- __FUNCTION__, type & PV_MASK, p.pl);
+ IRDA_ERROR("%s: invalid parameter length! "
+ "Expected %d bytes, but value had %d bytes!\n",
+ __FUNCTION__, type & PV_MASK, p.pl);
/* Most parameters are bit/byte fields or little endian,
* so it's ok to only extract a subset of it (the subset
@@ -265,7 +267,8 @@ static int irda_extract_integer(void *self, __u8 *buf, int len, __u8 pi,
le32_to_cpus(&p.pv.i);
break;
default:
- WARNING("%s: length %d not supported\n", __FUNCTION__, p.pl);
+ IRDA_WARNING("%s: length %d not supported\n",
+ __FUNCTION__, p.pl);
/* Skip parameter */
return p.pl+2;
@@ -301,9 +304,9 @@ static int irda_extract_string(void *self, __u8 *buf, int len, __u8 pi,
/* Check if buffer is long enough for parsing */
if (len < (2+p.pl)) {
- WARNING("%s: buffer to short for parsing! "
- "Need %d bytes, but len is only %d\n",
- __FUNCTION__, p.pl, len);
+ IRDA_WARNING("%s: buffer to short for parsing! "
+ "Need %d bytes, but len is only %d\n",
+ __FUNCTION__, p.pl, len);
return -1;
}
@@ -340,9 +343,9 @@ static int irda_extract_octseq(void *self, __u8 *buf, int len, __u8 pi,
/* Check if buffer is long enough for parsing */
if (len < (2+p.pl)) {
- WARNING("%s: buffer to short for parsing! "
- "Need %d bytes, but len is only %d\n",
- __FUNCTION__, p.pl, len);
+ IRDA_WARNING("%s: buffer to short for parsing! "
+ "Need %d bytes, but len is only %d\n",
+ __FUNCTION__, p.pl, len);
return -1;
}
@@ -459,8 +462,8 @@ int irda_param_insert(void *self, __u8 pi, __u8 *buf, int len,
int ret = -1;
int n = 0;
- ASSERT(buf != NULL, return ret;);
- ASSERT(info != 0, return ret;);
+ IRDA_ASSERT(buf != NULL, return ret;);
+ IRDA_ASSERT(info != 0, return ret;);
pi_minor = pi & info->pi_mask;
pi_major = pi >> info->pi_major_offset;
@@ -484,7 +487,7 @@ int irda_param_insert(void *self, __u8 pi, __u8 *buf, int len,
/* Check if handler has been implemented */
if (!pi_minor_info->func) {
- MESSAGE("%s: no handler for pi=%#x\n", __FUNCTION__, pi);
+ IRDA_MESSAGE("%s: no handler for pi=%#x\n", __FUNCTION__, pi);
/* Skip this parameter */
return -1;
}
@@ -513,8 +516,8 @@ static int irda_param_extract(void *self, __u8 *buf, int len,
int ret = -1;
int n = 0;
- ASSERT(buf != NULL, return ret;);
- ASSERT(info != 0, return ret;);
+ IRDA_ASSERT(buf != NULL, return ret;);
+ IRDA_ASSERT(info != 0, return ret;);
pi_minor = buf[n] & info->pi_mask;
pi_major = buf[n] >> info->pi_major_offset;
@@ -541,7 +544,8 @@ static int irda_param_extract(void *self, __u8 *buf, int len,
/* Check if handler has been implemented */
if (!pi_minor_info->func) {
- MESSAGE("%s: no handler for pi=%#x\n", __FUNCTION__, buf[n]);
+ IRDA_MESSAGE("%s: no handler for pi=%#x\n",
+ __FUNCTION__, buf[n]);
/* Skip this parameter */
return 2 + buf[n + 1]; /* Continue */
}
@@ -565,8 +569,8 @@ int irda_param_extract_all(void *self, __u8 *buf, int len,
int ret = -1;
int n = 0;
- ASSERT(buf != NULL, return ret;);
- ASSERT(info != 0, return ret;);
+ IRDA_ASSERT(buf != NULL, return ret;);
+ IRDA_ASSERT(info != 0, return ret;);
/*
* Parse all parameters. Each parameter must be at least two bytes
diff --git a/net/irda/qos.c b/net/irda/qos.c
index 288d468a8fca7..df732d56cc577 100644
--- a/net/irda/qos.c
+++ b/net/irda/qos.c
@@ -200,7 +200,7 @@ static int msb_index (__u16 word)
* able to check precisely what's going on. If a end user sees this,
* it's very likely the peer. - Jean II */
if (word == 0) {
- WARNING("%s(), Detected buggy peer, adjust null PV to 0x1!\n",
+ IRDA_WARNING("%s(), Detected buggy peer, adjust null PV to 0x1!\n",
__FUNCTION__);
/* The only safe choice (we don't know the array size) */
word = 0x1;
@@ -278,8 +278,8 @@ static inline int value_highest_bit(__u32 value, __u32 *array, int size, __u16 *
*/
void irda_qos_compute_intersection(struct qos_info *qos, struct qos_info *new)
{
- ASSERT(qos != NULL, return;);
- ASSERT(new != NULL, return;);
+ IRDA_ASSERT(qos != NULL, return;);
+ IRDA_ASSERT(new != NULL, return;);
/* Apply */
qos->baud_rate.bits &= new->baud_rate.bits;
@@ -351,7 +351,7 @@ static void irlap_adjust_qos_settings(struct qos_info *qos)
if (sysctl_min_tx_turn_time > qos->min_turn_time.value) {
int i;
- WARNING("%s(), Detected buggy peer, adjust mtt to %dus!\n",
+ IRDA_WARNING("%s(), Detected buggy peer, adjust mtt to %dus!\n",
__FUNCTION__, sysctl_min_tx_turn_time);
/* We don't really need bits, but easier this way */
@@ -390,7 +390,7 @@ static void irlap_adjust_qos_settings(struct qos_info *qos)
}
#else /* Use method described in section 6.6.11 of IrLAP */
while (irlap_requested_line_capacity(qos) > line_capacity) {
- ASSERT(index != 0, return;);
+ IRDA_ASSERT(index != 0, return;);
/* Must be able to send at least one frame */
if (qos->window_size.value > 1) {
@@ -402,8 +402,8 @@ static void irlap_adjust_qos_settings(struct qos_info *qos)
IRDA_DEBUG(2, "%s(), reducing data size to %d\n",
__FUNCTION__, qos->data_size.value);
} else {
- WARNING("%s(), nothing more we can do!\n",
- __FUNCTION__);
+ IRDA_WARNING("%s(), nothing more we can do!\n",
+ __FUNCTION__);
}
}
#endif /* CONFIG_IRDA_DYNAMIC_WINDOW */
@@ -532,8 +532,8 @@ static int irlap_param_baud_rate(void *instance, irda_param_t *param, int get)
struct irlap_cb *self = (struct irlap_cb *) instance;
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == LAP_MAGIC, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return -1;);
if (get) {
param->pv.i = self->qos_rx.baud_rate.bits;
@@ -568,8 +568,8 @@ static int irlap_param_link_disconnect(void *instance, irda_param_t *param,
struct irlap_cb *self = (struct irlap_cb *) instance;
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == LAP_MAGIC, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return -1;);
if (get)
param->pv.i = self->qos_rx.link_disc_time.bits;
@@ -600,8 +600,8 @@ static int irlap_param_max_turn_time(void *instance, irda_param_t *param,
{
struct irlap_cb *self = (struct irlap_cb *) instance;
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == LAP_MAGIC, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return -1;);
if (get)
param->pv.i = self->qos_rx.max_turn_time.bits;
@@ -622,8 +622,8 @@ static int irlap_param_data_size(void *instance, irda_param_t *param, int get)
{
struct irlap_cb *self = (struct irlap_cb *) instance;
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == LAP_MAGIC, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return -1;);
if (get)
param->pv.i = self->qos_rx.data_size.bits;
@@ -645,8 +645,8 @@ static int irlap_param_window_size(void *instance, irda_param_t *param,
{
struct irlap_cb *self = (struct irlap_cb *) instance;
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == LAP_MAGIC, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return -1;);
if (get)
param->pv.i = self->qos_rx.window_size.bits;
@@ -666,8 +666,8 @@ static int irlap_param_additional_bofs(void *instance, irda_param_t *param, int
{
struct irlap_cb *self = (struct irlap_cb *) instance;
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == LAP_MAGIC, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return -1;);
if (get)
param->pv.i = self->qos_rx.additional_bofs.bits;
@@ -688,8 +688,8 @@ static int irlap_param_min_turn_time(void *instance, irda_param_t *param,
{
struct irlap_cb *self = (struct irlap_cb *) instance;
- ASSERT(self != NULL, return -1;);
- ASSERT(self->magic == LAP_MAGIC, return -1;);
+ IRDA_ASSERT(self != NULL, return -1;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return -1;);
if (get)
param->pv.i = self->qos_rx.min_turn_time.bits;
@@ -716,8 +716,8 @@ __u32 irlap_max_line_capacity(__u32 speed, __u32 max_turn_time)
i = value_index(speed, baud_rates, 10);
j = value_index(max_turn_time, max_turn_times, 4);
- ASSERT(((i >=0) && (i <10)), return 0;);
- ASSERT(((j >=0) && (j <4)), return 0;);
+ IRDA_ASSERT(((i >=0) && (i <10)), return 0;);
+ IRDA_ASSERT(((j >=0) && (j <4)), return 0;);
line_capacity = max_line_capacities[i][j];
@@ -748,7 +748,7 @@ void irda_qos_bits_to_value(struct qos_info *qos)
{
int index;
- ASSERT(qos != NULL, return;);
+ IRDA_ASSERT(qos != NULL, return;);
index = msb_index(qos->baud_rate.bits);
qos->baud_rate.value = baud_rates[index];
diff --git a/net/irda/timer.c b/net/irda/timer.c
index 0b2811834fa33..0e17f976add69 100644
--- a/net/irda/timer.c
+++ b/net/irda/timer.c
@@ -144,8 +144,8 @@ static void irlap_slot_timer_expired(void *data)
{
struct irlap_cb *self = (struct irlap_cb *) data;
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LAP_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
irlap_do_event(self, SLOT_TIMER_EXPIRED, NULL, NULL);
}
@@ -160,8 +160,8 @@ static void irlap_query_timer_expired(void *data)
{
struct irlap_cb *self = (struct irlap_cb *) data;
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LAP_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
irlap_do_event(self, QUERY_TIMER_EXPIRED, NULL, NULL);
}
@@ -176,8 +176,8 @@ static void irlap_final_timer_expired(void *data)
{
struct irlap_cb *self = (struct irlap_cb *) data;
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LAP_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
irlap_do_event(self, FINAL_TIMER_EXPIRED, NULL, NULL);
}
@@ -192,8 +192,8 @@ static void irlap_wd_timer_expired(void *data)
{
struct irlap_cb *self = (struct irlap_cb *) data;
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LAP_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
irlap_do_event(self, WD_TIMER_EXPIRED, NULL, NULL);
}
@@ -208,8 +208,8 @@ static void irlap_backoff_timer_expired(void *data)
{
struct irlap_cb *self = (struct irlap_cb *) data;
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == LAP_MAGIC, return;);
+ IRDA_ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self->magic == LAP_MAGIC, return;);
irlap_do_event(self, BACKOFF_TIMER_EXPIRED, NULL, NULL);
}
@@ -224,7 +224,7 @@ void irlap_media_busy_expired(void* data)
{
struct irlap_cb *self = (struct irlap_cb *) data;
- ASSERT(self != NULL, return;);
+ IRDA_ASSERT(self != NULL, return;);
irda_device_set_media_busy(self->netdev, FALSE);
/* Note : the LAP event will be send in irlap_stop_mbusy_timer(),
diff --git a/net/irda/wrapper.c b/net/irda/wrapper.c
index c96074d325ac0..87130c1c8693a 100644
--- a/net/irda/wrapper.c
+++ b/net/irda/wrapper.c
@@ -133,7 +133,11 @@ int async_wrap_skb(struct sk_buff *skb, __u8 *tx_buff, int buffsize)
* bufsize-5 since the maximum number of bytes that can be
* transmitted after this point is 5.
*/
- ASSERT(n < (buffsize-5), return n;);
+ if(n >= (buffsize-5)) {
+ IRDA_ERROR("%s(), tx buffer overflow (n=%d)\n",
+ __FUNCTION__, n);
+ return n;
+ }
n += stuff_byte(skb->data[i], tx_buff+n);
fcs.value = irda_fcs(fcs.value, skb->data[i]);
@@ -381,7 +385,7 @@ async_unwrap_ce(struct net_device *dev,
break;
case LINK_ESCAPE:
- WARNING("%s: state not defined\n", __FUNCTION__);
+ IRDA_WARNING("%s: state not defined\n", __FUNCTION__);
break;
case BEGIN_FRAME:
diff --git a/net/key/af_key.c b/net/key/af_key.c
index c05649430be31..6682c7e261acb 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -42,11 +42,17 @@ static atomic_t pfkey_table_users = ATOMIC_INIT(0);
static atomic_t pfkey_socks_nr = ATOMIC_INIT(0);
-struct pfkey_opt {
- int registered;
- int promisc;
+struct pfkey_sock {
+ /* struct sock must be the first member of struct pfkey_sock */
+ struct sock sk;
+ int registered;
+ int promisc;
};
-#define pfkey_sk(__sk) ((struct pfkey_opt *)(__sk)->sk_protinfo)
+
+static inline struct pfkey_sock *pfkey_sk(struct sock *sk)
+{
+ return (struct pfkey_sock *)sk;
+}
static void pfkey_sock_destruct(struct sock *sk)
{
@@ -60,8 +66,6 @@ static void pfkey_sock_destruct(struct sock *sk)
BUG_TRAP(!atomic_read(&sk->sk_rmem_alloc));
BUG_TRAP(!atomic_read(&sk->sk_wmem_alloc));
- kfree(pfkey_sk(sk));
-
atomic_dec(&pfkey_socks_nr);
}
@@ -128,7 +132,6 @@ static void pfkey_remove(struct sock *sk)
static int pfkey_create(struct socket *sock, int protocol)
{
struct sock *sk;
- struct pfkey_opt *pfk;
int err;
if (!capable(CAP_NET_ADMIN))
@@ -139,7 +142,7 @@ static int pfkey_create(struct socket *sock, int protocol)
return -EPROTONOSUPPORT;
err = -ENOMEM;
- sk = sk_alloc(PF_KEY, GFP_KERNEL, 1, NULL);
+ sk = sk_alloc(PF_KEY, GFP_KERNEL, sizeof(struct pfkey_sock), NULL);
if (sk == NULL)
goto out;
@@ -147,14 +150,6 @@ static int pfkey_create(struct socket *sock, int protocol)
sock_init_data(sock, sk);
sk_set_owner(sk, THIS_MODULE);
- err = -ENOMEM;
- pfk = sk->sk_protinfo = kmalloc(sizeof(*pfk), GFP_KERNEL);
- if (!pfk) {
- sk_free(sk);
- goto out;
- }
- memset(pfk, 0, sizeof(*pfk));
-
sk->sk_family = PF_KEY;
sk->sk_destruct = pfkey_sock_destruct;
@@ -233,7 +228,7 @@ static int pfkey_broadcast(struct sk_buff *skb, int allocation,
pfkey_lock_table();
sk_for_each(sk, node, &pfkey_table) {
- struct pfkey_opt *pfk = pfkey_sk(sk);
+ struct pfkey_sock *pfk = pfkey_sk(sk);
int err2;
/* Yes, it means that if you are meant to receive this
@@ -598,7 +593,7 @@ static struct sk_buff * pfkey_xfrm_state2msg(struct xfrm_state *x, int add_keys,
/* address family check */
sockaddr_size = pfkey_sockaddr_size(x->props.family);
if (!sockaddr_size)
- ERR_PTR(-EINVAL);
+ return ERR_PTR(-EINVAL);
/* base, SA, (lifetime (HSC),) address(SD), (address(P),)
key(AE), (identity(SD),) (sensitivity)> */
@@ -1418,7 +1413,7 @@ out_put_algs:
static int pfkey_register(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)
{
- struct pfkey_opt *pfk = pfkey_sk(sk);
+ struct pfkey_sock *pfk = pfkey_sk(sk);
struct sk_buff *supp_skb;
if (hdr->sadb_msg_satype > SADB_SATYPE_MAX)
@@ -1514,7 +1509,7 @@ static int pfkey_dump(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr
static int pfkey_promisc(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)
{
- struct pfkey_opt *pfk = pfkey_sk(sk);
+ struct pfkey_sock *pfk = pfkey_sk(sk);
int satype = hdr->sadb_msg_satype;
if (hdr->sadb_msg_len == (sizeof(*hdr) / sizeof(uint64_t))) {
diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c
index 357a1f0455a09..2e11283e5062e 100644
--- a/net/llc/af_llc.c
+++ b/net/llc/af_llc.c
@@ -113,7 +113,7 @@ static __inline__ u8 llc_ui_header_len(struct sock *sk,
*/
static int llc_ui_send_data(struct sock* sk, struct sk_buff *skb, int noblock)
{
- struct llc_opt* llc = llc_sk(sk);
+ struct llc_sock* llc = llc_sk(sk);
int rc = 0;
if (llc_data_accept_state(llc->state) || llc->p_flag) {
@@ -169,7 +169,7 @@ static int llc_ui_create(struct socket *sock, int protocol)
static int llc_ui_release(struct socket *sock)
{
struct sock *sk = sock->sk;
- struct llc_opt *llc;
+ struct llc_sock *llc;
if (!sk)
goto out;
@@ -180,7 +180,7 @@ static int llc_ui_release(struct socket *sock)
llc->laddr.lsap, llc->daddr.lsap);
if (!llc_send_disc(sk))
llc_ui_wait_for_disc(sk, sk->sk_rcvtimeo);
- if (!sk->sk_zapped)
+ if (!sock_flag(sk, SOCK_ZAPPED))
llc_sap_remove_socket(llc->sap, sk);
release_sock(sk);
if (llc->sap && hlist_empty(&llc->sap->sk_list.list)) {
@@ -244,11 +244,11 @@ out:
static int llc_ui_autobind(struct socket *sock, struct sockaddr_llc *addr)
{
struct sock *sk = sock->sk;
- struct llc_opt *llc = llc_sk(sk);
+ struct llc_sock *llc = llc_sk(sk);
struct llc_sap *sap;
int rc = -EINVAL;
- if (!sk->sk_zapped)
+ if (!sock_flag(sk, SOCK_ZAPPED))
goto out;
rc = -ENODEV;
llc->dev = dev_getfirstbyhwtype(addr->sllc_arphrd);
@@ -266,7 +266,8 @@ static int llc_ui_autobind(struct socket *sock, struct sockaddr_llc *addr)
memcpy(&llc->addr, addr, sizeof(llc->addr));
/* assign new connection to its SAP */
llc_sap_add_socket(sap, sk);
- rc = sk->sk_zapped = 0;
+ sock_reset_flag(sk, SOCK_ZAPPED);
+ rc = 0;
out:
return rc;
}
@@ -293,12 +294,12 @@ static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen)
{
struct sockaddr_llc *addr = (struct sockaddr_llc *)uaddr;
struct sock *sk = sock->sk;
- struct llc_opt *llc = llc_sk(sk);
+ struct llc_sock *llc = llc_sk(sk);
struct llc_sap *sap;
int rc = -EINVAL;
dprintk("%s: binding %02X\n", __FUNCTION__, addr->sllc_sap);
- if (!sk->sk_zapped || addrlen != sizeof(*addr))
+ if (!sock_flag(sk, SOCK_ZAPPED) || addrlen != sizeof(*addr))
goto out;
rc = -EAFNOSUPPORT;
if (addr->sllc_family != AF_LLC)
@@ -339,7 +340,8 @@ static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen)
memcpy(&llc->addr, addr, sizeof(llc->addr));
/* assign new connection to its SAP */
llc_sap_add_socket(sap, sk);
- rc = sk->sk_zapped = 0;
+ sock_reset_flag(sk, SOCK_ZAPPED);
+ rc = 0;
out:
return rc;
}
@@ -394,7 +396,7 @@ static int llc_ui_connect(struct socket *sock, struct sockaddr *uaddr,
int addrlen, int flags)
{
struct sock *sk = sock->sk;
- struct llc_opt *llc = llc_sk(sk);
+ struct llc_sock *llc = llc_sk(sk);
struct sockaddr_llc *addr = (struct sockaddr_llc *)uaddr;
struct net_device *dev;
int rc = -EINVAL;
@@ -406,7 +408,7 @@ static int llc_ui_connect(struct socket *sock, struct sockaddr *uaddr,
if (addr->sllc_family != AF_LLC)
goto out;
/* bind connection to sap if user hasn't done it. */
- if (sk->sk_zapped) {
+ if (sock_flag(sk, SOCK_ZAPPED)) {
/* bind to sap with null dev, exclusive */
rc = llc_ui_autobind(sock, addr);
if (rc)
@@ -459,7 +461,7 @@ static int llc_ui_listen(struct socket *sock, int backlog)
if (sk->sk_type != SOCK_STREAM)
goto out;
rc = -EAGAIN;
- if (sk->sk_zapped)
+ if (sock_flag(sk, SOCK_ZAPPED))
goto out;
rc = 0;
if (!(unsigned)backlog) /* BSDism */
@@ -571,7 +573,7 @@ static int llc_ui_wait_for_data(struct sock *sk, int timeout)
static int llc_ui_wait_for_busy_core(struct sock *sk, int timeout)
{
DECLARE_WAITQUEUE(wait, current);
- struct llc_opt *llc = llc_sk(sk);
+ struct llc_sock *llc = llc_sk(sk);
int rc;
add_wait_queue_exclusive(sk->sk_sleep, &wait);
@@ -612,7 +614,7 @@ static int llc_ui_wait_for_busy_core(struct sock *sk, int timeout)
static int llc_ui_accept(struct socket *sock, struct socket *newsock, int flags)
{
struct sock *sk = sock->sk, *newsk;
- struct llc_opt *llc, *newllc;
+ struct llc_sock *llc, *newllc;
struct sk_buff *skb;
int rc = -EOPNOTSUPP;
@@ -638,7 +640,7 @@ static int llc_ui_accept(struct socket *sock, struct socket *newsock, int flags)
newsk = skb->sk;
/* attach connection to a new socket. */
llc_ui_sk_init(newsock, newsk);
- newsk->sk_zapped = 0;
+ sock_reset_flag(newsk, SOCK_ZAPPED);
newsk->sk_state = TCP_ESTABLISHED;
newsock->state = SS_CONNECTED;
llc = llc_sk(sk);
@@ -728,7 +730,7 @@ static int llc_ui_sendmsg(struct kiocb *iocb, struct socket *sock,
struct msghdr *msg, size_t len)
{
struct sock *sk = sock->sk;
- struct llc_opt *llc = llc_sk(sk);
+ struct llc_sock *llc = llc_sk(sk);
struct sockaddr_llc *addr = (struct sockaddr_llc *)msg->msg_name;
int flags = msg->msg_flags;
int noblock = flags & MSG_DONTWAIT;
@@ -749,7 +751,7 @@ static int llc_ui_sendmsg(struct kiocb *iocb, struct socket *sock,
addr = &llc->addr;
}
/* must bind connection to sap if user hasn't done it. */
- if (sk->sk_zapped) {
+ if (sock_flag(sk, SOCK_ZAPPED)) {
/* bind to sap with null dev, exclusive. */
rc = llc_ui_autobind(sock, addr);
if (rc)
@@ -819,11 +821,11 @@ static int llc_ui_getname(struct socket *sock, struct sockaddr *uaddr,
{
struct sockaddr_llc sllc;
struct sock *sk = sock->sk;
- struct llc_opt *llc = llc_sk(sk);
+ struct llc_sock *llc = llc_sk(sk);
int rc = 0;
lock_sock(sk);
- if (sk->sk_zapped)
+ if (sock_flag(sk, SOCK_ZAPPED))
goto out;
*uaddrlen = sizeof(sllc);
memset(uaddr, 0, *uaddrlen);
@@ -883,7 +885,7 @@ static int llc_ui_setsockopt(struct socket *sock, int level, int optname,
char __user *optval, int optlen)
{
struct sock *sk = sock->sk;
- struct llc_opt *llc = llc_sk(sk);
+ struct llc_sock *llc = llc_sk(sk);
int rc = -EINVAL, opt;
lock_sock(sk);
@@ -958,7 +960,7 @@ static int llc_ui_getsockopt(struct socket *sock, int level, int optname,
char __user *optval, int __user *optlen)
{
struct sock *sk = sock->sk;
- struct llc_opt *llc = llc_sk(sk);
+ struct llc_sock *llc = llc_sk(sk);
int val = 0, len = 0, rc = -EINVAL;
lock_sock(sk);
diff --git a/net/llc/llc_c_ac.c b/net/llc/llc_c_ac.c
index 6d1eefaa10da0..b218be4c10ec4 100644
--- a/net/llc/llc_c_ac.c
+++ b/net/llc/llc_c_ac.c
@@ -44,7 +44,7 @@ static int llc_conn_ac_set_p_flag_1(struct sock *sk, struct sk_buff *skb);
int llc_conn_ac_clear_remote_busy(struct sock *sk, struct sk_buff *skb)
{
- struct llc_opt *llc = llc_sk(sk);
+ struct llc_sock *llc = llc_sk(sk);
if (llc->remote_busy_flag) {
u8 nr;
@@ -68,7 +68,7 @@ int llc_conn_ac_conn_ind(struct sock *sk, struct sk_buff *skb)
sap = llc_sap_find(dsap);
if (sap) {
struct llc_conn_state_ev *ev = llc_conn_ev(skb);
- struct llc_opt *llc = llc_sk(sk);
+ struct llc_sock *llc = llc_sk(sk);
llc_pdu_decode_sa(skb, llc->daddr.mac);
llc_pdu_decode_da(skb, llc->laddr.mac);
@@ -146,7 +146,7 @@ int llc_conn_ac_rst_ind(struct sock *sk, struct sk_buff *skb)
int rc = 1;
struct llc_conn_state_ev *ev = llc_conn_ev(skb);
struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
- struct llc_opt *llc = llc_sk(sk);
+ struct llc_sock *llc = llc_sk(sk);
switch (ev->type) {
case LLC_CONN_EV_TYPE_PDU:
@@ -207,7 +207,7 @@ int llc_conn_ac_clear_remote_busy_if_f_eq_1(struct sock *sk,
int llc_conn_ac_stop_rej_tmr_if_data_flag_eq_2(struct sock *sk,
struct sk_buff *skb)
{
- struct llc_opt *llc = llc_sk(sk);
+ struct llc_sock *llc = llc_sk(sk);
if (llc->data_flag == 2)
del_timer(&llc->rej_sent_timer.timer);
@@ -220,7 +220,7 @@ int llc_conn_ac_send_disc_cmd_p_set_x(struct sock *sk, struct sk_buff *skb)
struct sk_buff *nskb = llc_alloc_frame();
if (nskb) {
- struct llc_opt *llc = llc_sk(sk);
+ struct llc_sock *llc = llc_sk(sk);
struct llc_sap *sap = llc->sap;
nskb->dev = llc->dev;
@@ -246,7 +246,7 @@ int llc_conn_ac_send_dm_rsp_f_set_p(struct sock *sk, struct sk_buff *skb)
struct sk_buff *nskb = llc_alloc_frame();
if (nskb) {
- struct llc_opt *llc = llc_sk(sk);
+ struct llc_sock *llc = llc_sk(sk);
struct llc_sap *sap = llc->sap;
u8 f_bit;
@@ -273,7 +273,7 @@ int llc_conn_ac_send_dm_rsp_f_set_1(struct sock *sk, struct sk_buff *skb)
struct sk_buff *nskb = llc_alloc_frame();
if (nskb) {
- struct llc_opt *llc = llc_sk(sk);
+ struct llc_sock *llc = llc_sk(sk);
struct llc_sap *sap = llc->sap;
u8 f_bit = 1;
@@ -299,7 +299,7 @@ int llc_conn_ac_send_frmr_rsp_f_set_x(struct sock *sk, struct sk_buff *skb)
int rc = -ENOBUFS;
struct sk_buff *nskb;
struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
- struct llc_opt *llc = llc_sk(sk);
+ struct llc_sock *llc = llc_sk(sk);
llc->rx_pdu_hdr = *((u32 *)pdu);
if (LLC_PDU_IS_CMD(pdu))
@@ -334,7 +334,7 @@ int llc_conn_ac_resend_frmr_rsp_f_set_0(struct sock *sk, struct sk_buff *skb)
if (nskb) {
u8 f_bit = 0;
- struct llc_opt *llc = llc_sk(sk);
+ struct llc_sock *llc = llc_sk(sk);
struct llc_sap *sap = llc->sap;
struct llc_pdu_sn *pdu = (struct llc_pdu_sn *)&llc->rx_pdu_hdr;
@@ -364,7 +364,7 @@ int llc_conn_ac_resend_frmr_rsp_f_set_p(struct sock *sk, struct sk_buff *skb)
llc_pdu_decode_pf_bit(skb, &f_bit);
nskb = llc_alloc_frame();
if (nskb) {
- struct llc_opt *llc = llc_sk(sk);
+ struct llc_sock *llc = llc_sk(sk);
struct llc_sap *sap = llc->sap;
struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
@@ -388,7 +388,7 @@ free:
int llc_conn_ac_send_i_cmd_p_set_1(struct sock *sk, struct sk_buff *skb)
{
int rc;
- struct llc_opt *llc = llc_sk(sk);
+ struct llc_sock *llc = llc_sk(sk);
struct llc_sap *sap = llc->sap;
llc_pdu_header_init(skb, LLC_PDU_TYPE_I, sap->laddr.lsap,
@@ -405,7 +405,7 @@ int llc_conn_ac_send_i_cmd_p_set_1(struct sock *sk, struct sk_buff *skb)
static int llc_conn_ac_send_i_cmd_p_set_0(struct sock *sk, struct sk_buff *skb)
{
int rc;
- struct llc_opt *llc = llc_sk(sk);
+ struct llc_sock *llc = llc_sk(sk);
struct llc_sap *sap = llc->sap;
llc_pdu_header_init(skb, LLC_PDU_TYPE_I, sap->laddr.lsap,
@@ -422,7 +422,7 @@ static int llc_conn_ac_send_i_cmd_p_set_0(struct sock *sk, struct sk_buff *skb)
int llc_conn_ac_send_i_xxx_x_set_0(struct sock *sk, struct sk_buff *skb)
{
int rc;
- struct llc_opt *llc = llc_sk(sk);
+ struct llc_sock *llc = llc_sk(sk);
struct llc_sap *sap = llc->sap;
llc_pdu_header_init(skb, LLC_PDU_TYPE_I, sap->laddr.lsap,
@@ -454,7 +454,7 @@ int llc_conn_ac_resend_i_xxx_x_set_0_or_send_rr(struct sock *sk,
struct sk_buff *nskb = llc_alloc_frame();
if (nskb) {
- struct llc_opt *llc = llc_sk(sk);
+ struct llc_sock *llc = llc_sk(sk);
struct llc_sap *sap = llc->sap;
nskb->dev = llc->dev;
@@ -490,7 +490,7 @@ int llc_conn_ac_send_rej_cmd_p_set_1(struct sock *sk, struct sk_buff *skb)
struct sk_buff *nskb = llc_alloc_frame();
if (nskb) {
- struct llc_opt *llc = llc_sk(sk);
+ struct llc_sock *llc = llc_sk(sk);
struct llc_sap *sap = llc->sap;
nskb->dev = llc->dev;
@@ -516,7 +516,7 @@ int llc_conn_ac_send_rej_rsp_f_set_1(struct sock *sk, struct sk_buff *skb)
if (nskb) {
u8 f_bit = 1;
- struct llc_opt *llc = llc_sk(sk);
+ struct llc_sock *llc = llc_sk(sk);
struct llc_sap *sap = llc->sap;
nskb->dev = llc->dev;
@@ -541,7 +541,7 @@ int llc_conn_ac_send_rej_xxx_x_set_0(struct sock *sk, struct sk_buff *skb)
struct sk_buff *nskb = llc_alloc_frame();
if (nskb) {
- struct llc_opt *llc = llc_sk(sk);
+ struct llc_sock *llc = llc_sk(sk);
struct llc_sap *sap = llc->sap;
u8 f_bit = 0;
@@ -567,7 +567,7 @@ int llc_conn_ac_send_rnr_cmd_p_set_1(struct sock *sk, struct sk_buff *skb)
struct sk_buff *nskb = llc_alloc_frame();
if (nskb) {
- struct llc_opt *llc = llc_sk(sk);
+ struct llc_sock *llc = llc_sk(sk);
struct llc_sap *sap = llc->sap;
nskb->dev = llc->dev;
@@ -592,7 +592,7 @@ int llc_conn_ac_send_rnr_rsp_f_set_1(struct sock *sk, struct sk_buff *skb)
struct sk_buff *nskb = llc_alloc_frame();
if (nskb) {
- struct llc_opt *llc = llc_sk(sk);
+ struct llc_sock *llc = llc_sk(sk);
struct llc_sap *sap = llc->sap;
u8 f_bit = 1;
@@ -619,7 +619,7 @@ int llc_conn_ac_send_rnr_xxx_x_set_0(struct sock *sk, struct sk_buff *skb)
if (nskb) {
u8 f_bit = 0;
- struct llc_opt *llc = llc_sk(sk);
+ struct llc_sock *llc = llc_sk(sk);
struct llc_sap *sap = llc->sap;
nskb->dev = llc->dev;
@@ -640,7 +640,7 @@ free:
int llc_conn_ac_set_remote_busy(struct sock *sk, struct sk_buff *skb)
{
- struct llc_opt *llc = llc_sk(sk);
+ struct llc_sock *llc = llc_sk(sk);
if (!llc->remote_busy_flag) {
llc->remote_busy_flag = 1;
@@ -656,7 +656,7 @@ int llc_conn_ac_opt_send_rnr_xxx_x_set_0(struct sock *sk, struct sk_buff *skb)
struct sk_buff *nskb = llc_alloc_frame();
if (nskb) {
- struct llc_opt *llc = llc_sk(sk);
+ struct llc_sock *llc = llc_sk(sk);
struct llc_sap *sap = llc->sap;
nskb->dev = llc->dev;
@@ -681,7 +681,7 @@ int llc_conn_ac_send_rr_cmd_p_set_1(struct sock *sk, struct sk_buff *skb)
struct sk_buff *nskb = llc_alloc_frame();
if (nskb) {
- struct llc_opt *llc = llc_sk(sk);
+ struct llc_sock *llc = llc_sk(sk);
struct llc_sap *sap = llc->sap;
nskb->dev = llc->dev;
@@ -706,7 +706,7 @@ int llc_conn_ac_send_rr_rsp_f_set_1(struct sock *sk, struct sk_buff *skb)
struct sk_buff *nskb = llc_alloc_frame();
if (nskb) {
- struct llc_opt *llc = llc_sk(sk);
+ struct llc_sock *llc = llc_sk(sk);
struct llc_sap *sap = llc->sap;
u8 f_bit = 1;
@@ -732,7 +732,7 @@ int llc_conn_ac_send_ack_rsp_f_set_1(struct sock *sk, struct sk_buff *skb)
struct sk_buff *nskb = llc_alloc_frame();
if (nskb) {
- struct llc_opt *llc = llc_sk(sk);
+ struct llc_sock *llc = llc_sk(sk);
struct llc_sap *sap = llc->sap;
u8 f_bit = 1;
@@ -758,7 +758,7 @@ int llc_conn_ac_send_rr_xxx_x_set_0(struct sock *sk, struct sk_buff *skb)
struct sk_buff *nskb = llc_alloc_frame();
if (nskb) {
- struct llc_opt *llc = llc_sk(sk);
+ struct llc_sock *llc = llc_sk(sk);
struct llc_sap *sap = llc->sap;
nskb->dev = llc->dev;
@@ -783,7 +783,7 @@ int llc_conn_ac_send_ack_xxx_x_set_0(struct sock *sk, struct sk_buff *skb)
struct sk_buff *nskb = llc_alloc_frame();
if (nskb) {
- struct llc_opt *llc = llc_sk(sk);
+ struct llc_sock *llc = llc_sk(sk);
struct llc_sap *sap = llc->sap;
nskb->dev = llc->dev;
@@ -816,7 +816,7 @@ int llc_conn_ac_send_sabme_cmd_p_set_x(struct sock *sk, struct sk_buff *skb)
{
int rc = -ENOBUFS;
struct sk_buff *nskb = llc_alloc_frame();
- struct llc_opt *llc = llc_sk(sk);
+ struct llc_sock *llc = llc_sk(sk);
if (nskb) {
struct llc_sap *sap = llc->sap;
@@ -849,7 +849,7 @@ int llc_conn_ac_send_ua_rsp_f_set_p(struct sock *sk, struct sk_buff *skb)
llc_pdu_decode_pf_bit(skb, &f_bit);
if (nskb) {
- struct llc_opt *llc = llc_sk(sk);
+ struct llc_sock *llc = llc_sk(sk);
struct llc_sap *sap = llc->sap;
nskb->dev = llc->dev;
@@ -882,7 +882,7 @@ int llc_conn_ac_set_s_flag_1(struct sock *sk, struct sk_buff *skb)
int llc_conn_ac_start_p_timer(struct sock *sk, struct sk_buff *skb)
{
- struct llc_opt *llc = llc_sk(sk);
+ struct llc_sock *llc = llc_sk(sk);
llc_conn_set_p_flag(sk, 1);
mod_timer(&llc->pf_cycle_timer.timer,
@@ -903,7 +903,7 @@ int llc_conn_ac_start_p_timer(struct sock *sk, struct sk_buff *skb)
int llc_conn_ac_send_ack_if_needed(struct sock *sk, struct sk_buff *skb)
{
u8 pf_bit;
- struct llc_opt *llc = llc_sk(sk);
+ struct llc_sock *llc = llc_sk(sk);
llc_pdu_decode_pf_bit(skb, &pf_bit);
llc->ack_pf |= pf_bit & 1;
@@ -950,7 +950,7 @@ static int llc_conn_ac_send_i_rsp_f_set_ackpf(struct sock *sk,
struct sk_buff *skb)
{
int rc;
- struct llc_opt *llc = llc_sk(sk);
+ struct llc_sock *llc = llc_sk(sk);
struct llc_sap *sap = llc->sap;
llc_pdu_header_init(skb, LLC_PDU_TYPE_I, sap->laddr.lsap,
@@ -976,7 +976,7 @@ static int llc_conn_ac_send_i_rsp_f_set_ackpf(struct sock *sk,
*/
int llc_conn_ac_send_i_as_ack(struct sock *sk, struct sk_buff *skb)
{
- struct llc_opt *llc = llc_sk(sk);
+ struct llc_sock *llc = llc_sk(sk);
if (llc->ack_must_be_send) {
llc_conn_ac_send_i_rsp_f_set_ackpf(sk, skb);
@@ -1004,7 +1004,7 @@ static int llc_conn_ac_send_rr_rsp_f_set_ackpf(struct sock *sk,
struct sk_buff *nskb = llc_alloc_frame();
if (nskb) {
- struct llc_opt *llc = llc_sk(sk);
+ struct llc_sock *llc = llc_sk(sk);
struct llc_sap *sap = llc->sap;
nskb->dev = llc->dev;
@@ -1035,7 +1035,7 @@ free:
*/
static int llc_conn_ac_inc_npta_value(struct sock *sk, struct sk_buff *skb)
{
- struct llc_opt *llc = llc_sk(sk);
+ struct llc_sock *llc = llc_sk(sk);
if (!llc->inc_cntr) {
llc->dec_step = 0;
@@ -1058,7 +1058,7 @@ static int llc_conn_ac_inc_npta_value(struct sock *sk, struct sk_buff *skb)
*/
int llc_conn_ac_adjust_npta_by_rr(struct sock *sk, struct sk_buff *skb)
{
- struct llc_opt *llc = llc_sk(sk);
+ struct llc_sock *llc = llc_sk(sk);
if (!llc->connect_step && !llc->remote_busy_flag) {
if (!llc->dec_step) {
@@ -1084,7 +1084,7 @@ int llc_conn_ac_adjust_npta_by_rr(struct sock *sk, struct sk_buff *skb)
*/
int llc_conn_ac_adjust_npta_by_rnr(struct sock *sk, struct sk_buff *skb)
{
- struct llc_opt *llc = llc_sk(sk);
+ struct llc_sock *llc = llc_sk(sk);
if (llc->remote_busy_flag)
if (!llc->dec_step) {
@@ -1109,7 +1109,7 @@ int llc_conn_ac_adjust_npta_by_rnr(struct sock *sk, struct sk_buff *skb)
*/
int llc_conn_ac_dec_tx_win_size(struct sock *sk, struct sk_buff *skb)
{
- struct llc_opt *llc = llc_sk(sk);
+ struct llc_sock *llc = llc_sk(sk);
u8 unacked_pdu = skb_queue_len(&llc->pdu_unack_q);
llc->k -= unacked_pdu;
@@ -1128,7 +1128,7 @@ int llc_conn_ac_dec_tx_win_size(struct sock *sk, struct sk_buff *skb)
*/
int llc_conn_ac_inc_tx_win_size(struct sock *sk, struct sk_buff *skb)
{
- struct llc_opt *llc = llc_sk(sk);
+ struct llc_sock *llc = llc_sk(sk);
llc->k += 1;
if (llc->k > 128)
@@ -1138,7 +1138,7 @@ int llc_conn_ac_inc_tx_win_size(struct sock *sk, struct sk_buff *skb)
int llc_conn_ac_stop_all_timers(struct sock *sk, struct sk_buff *skb)
{
- struct llc_opt *llc = llc_sk(sk);
+ struct llc_sock *llc = llc_sk(sk);
del_timer(&llc->pf_cycle_timer.timer);
del_timer(&llc->ack_timer.timer);
@@ -1151,7 +1151,7 @@ int llc_conn_ac_stop_all_timers(struct sock *sk, struct sk_buff *skb)
int llc_conn_ac_stop_other_timers(struct sock *sk, struct sk_buff *skb)
{
- struct llc_opt *llc = llc_sk(sk);
+ struct llc_sock *llc = llc_sk(sk);
del_timer(&llc->rej_sent_timer.timer);
del_timer(&llc->pf_cycle_timer.timer);
@@ -1163,7 +1163,7 @@ int llc_conn_ac_stop_other_timers(struct sock *sk, struct sk_buff *skb)
int llc_conn_ac_start_ack_timer(struct sock *sk, struct sk_buff *skb)
{
- struct llc_opt *llc = llc_sk(sk);
+ struct llc_sock *llc = llc_sk(sk);
mod_timer(&llc->ack_timer.timer, jiffies + llc->ack_timer.expire * HZ);
return 0;
@@ -1171,7 +1171,7 @@ int llc_conn_ac_start_ack_timer(struct sock *sk, struct sk_buff *skb)
int llc_conn_ac_start_rej_timer(struct sock *sk, struct sk_buff *skb)
{
- struct llc_opt *llc = llc_sk(sk);
+ struct llc_sock *llc = llc_sk(sk);
mod_timer(&llc->rej_sent_timer.timer,
jiffies + llc->rej_sent_timer.expire * HZ);
@@ -1181,7 +1181,7 @@ int llc_conn_ac_start_rej_timer(struct sock *sk, struct sk_buff *skb)
int llc_conn_ac_start_ack_tmr_if_not_running(struct sock *sk,
struct sk_buff *skb)
{
- struct llc_opt *llc = llc_sk(sk);
+ struct llc_sock *llc = llc_sk(sk);
if (!timer_pending(&llc->ack_timer.timer))
mod_timer(&llc->ack_timer.timer,
@@ -1197,7 +1197,7 @@ int llc_conn_ac_stop_ack_timer(struct sock *sk, struct sk_buff *skb)
int llc_conn_ac_stop_p_timer(struct sock *sk, struct sk_buff *skb)
{
- struct llc_opt *llc = llc_sk(sk);
+ struct llc_sock *llc = llc_sk(sk);
del_timer(&llc->pf_cycle_timer.timer);
llc_conn_set_p_flag(sk, 0);
@@ -1215,7 +1215,7 @@ int llc_conn_ac_upd_nr_received(struct sock *sk, struct sk_buff *skb)
int acked;
u16 unacked = 0;
struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
- struct llc_opt *llc = llc_sk(sk);
+ struct llc_sock *llc = llc_sk(sk);
llc->last_nr = PDU_SUPV_GET_Nr(pdu);
acked = llc_conn_remove_acked_pdus(sk, llc->last_nr, &unacked);
diff --git a/net/llc/llc_c_ev.c b/net/llc/llc_c_ev.c
index c7ed6c76cef3a..cd130c3b72bc4 100644
--- a/net/llc/llc_c_ev.c
+++ b/net/llc/llc_c_ev.c
@@ -78,7 +78,7 @@ static u16 llc_util_nr_inside_tx_window(struct sock *sk, u8 nr)
u8 nr1, nr2;
struct sk_buff *skb;
struct llc_pdu_sn *pdu;
- struct llc_opt *llc = llc_sk(sk);
+ struct llc_sock *llc = llc_sk(sk);
int rc = 0;
if (llc->dev->flags & IFF_LOOPBACK)
diff --git a/net/llc/llc_conn.c b/net/llc/llc_conn.c
index 9dd0f26a1534d..cc587ebf42c15 100644
--- a/net/llc/llc_conn.c
+++ b/net/llc/llc_conn.c
@@ -53,7 +53,7 @@ static int llc_offset_table[NBR_CONN_STATES][NBR_CONN_EV];
int llc_conn_state_process(struct sock *sk, struct sk_buff *skb)
{
int rc;
- struct llc_opt *llc = llc_sk(sk);
+ struct llc_sock *llc = llc_sk(sk);
struct llc_conn_state_ev *ev = llc_conn_ev(skb);
/*
@@ -221,7 +221,7 @@ void llc_conn_resend_i_pdu_as_cmd(struct sock *sk, u8 nr, u8 first_p_bit)
struct sk_buff *skb;
struct llc_pdu_sn *pdu;
u16 nbr_unack_pdus;
- struct llc_opt *llc;
+ struct llc_sock *llc;
u8 howmany_resend = 0;
llc_conn_remove_acked_pdus(sk, nr, &nbr_unack_pdus);
@@ -263,7 +263,7 @@ void llc_conn_resend_i_pdu_as_rsp(struct sock *sk, u8 nr, u8 first_f_bit)
{
struct sk_buff *skb;
u16 nbr_unack_pdus;
- struct llc_opt *llc = llc_sk(sk);
+ struct llc_sock *llc = llc_sk(sk);
u8 howmany_resend = 0;
llc_conn_remove_acked_pdus(sk, nr, &nbr_unack_pdus);
@@ -305,7 +305,7 @@ int llc_conn_remove_acked_pdus(struct sock *sk, u8 nr, u16 *how_many_unacked)
struct sk_buff *skb;
struct llc_pdu_sn *pdu;
int nbr_acked = 0;
- struct llc_opt *llc = llc_sk(sk);
+ struct llc_sock *llc = llc_sk(sk);
int q_len = skb_queue_len(&llc->pdu_unack_q);
if (!q_len)
@@ -366,7 +366,7 @@ static void llc_conn_send_pdus(struct sock *sk)
static int llc_conn_service(struct sock *sk, struct sk_buff *skb)
{
int rc = 1;
- struct llc_opt *llc = llc_sk(sk);
+ struct llc_sock *llc = llc_sk(sk);
struct llc_conn_state_trans *trans;
if (llc->state > NBR_CONN_STATES)
@@ -399,7 +399,7 @@ static struct llc_conn_state_trans *llc_qualify_conn_ev(struct sock *sk,
struct llc_conn_state_trans **next_trans;
llc_conn_ev_qfyr_t *next_qualifier;
struct llc_conn_state_ev *ev = llc_conn_ev(skb);
- struct llc_opt *llc = llc_sk(sk);
+ struct llc_sock *llc = llc_sk(sk);
struct llc_conn_state *curr_state =
&llc_conn_state_table[llc->state - 1];
@@ -478,7 +478,7 @@ struct sock *llc_lookup_established(struct llc_sap *sap, struct llc_addr *daddr,
read_lock_bh(&sap->sk_list.lock);
sk_for_each(rc, node, &sap->sk_list.list) {
- struct llc_opt *llc = llc_sk(rc);
+ struct llc_sock *llc = llc_sk(rc);
if (llc->laddr.lsap == laddr->lsap &&
llc->daddr.lsap == daddr->lsap &&
@@ -511,7 +511,7 @@ static struct sock *llc_lookup_listener(struct llc_sap *sap,
read_lock_bh(&sap->sk_list.lock);
sk_for_each(rc, node, &sap->sk_list.list) {
- struct llc_opt *llc = llc_sk(rc);
+ struct llc_sock *llc = llc_sk(rc);
if (rc->sk_type == SOCK_STREAM && rc->sk_state == TCP_LISTEN &&
llc->laddr.lsap == laddr->lsap &&
@@ -650,7 +650,7 @@ void llc_sap_remove_socket(struct llc_sap *sap, struct sock *sk)
static int llc_conn_rcv(struct sock* sk, struct sk_buff *skb)
{
struct llc_conn_state_ev *ev = llc_conn_ev(skb);
- struct llc_opt *llc = llc_sk(sk);
+ struct llc_sock *llc = llc_sk(sk);
if (!llc->dev)
llc->dev = skb->dev;
@@ -675,7 +675,7 @@ void llc_conn_handler(struct llc_sap *sap, struct sk_buff *skb)
* Didn't find an active connection; verify if there
* is a listening socket for this llc addr
*/
- struct llc_opt *llc;
+ struct llc_sock *llc;
struct sock *parent = llc_lookup_listener(sap, &daddr);
if (!parent) {
@@ -756,7 +756,7 @@ int llc_release_sockets(struct llc_sap *sap)
static int llc_backlog_rcv(struct sock *sk, struct sk_buff *skb)
{
int rc = 0;
- struct llc_opt *llc = llc_sk(sk);
+ struct llc_sock *llc = llc_sk(sk);
if (llc_backlog_type(skb) == LLC_PACKET) {
if (llc->state > 1) /* not closed */
@@ -786,17 +786,10 @@ out_kfree_skb:
*
* Initializes a socket with default llc values.
*/
-static int llc_sk_init(struct sock* sk)
+static void llc_sk_init(struct sock* sk)
{
- struct llc_opt *llc = kmalloc(sizeof(*llc), GFP_ATOMIC);
- int rc = -ENOMEM;
+ struct llc_sock *llc = llc_sk(sk);
- if (!llc)
- goto out;
- memset(llc, 0, sizeof(*llc));
- rc = 0;
-
- llc->sk = sk;
llc->state = LLC_CONN_STATE_ADM;
llc->inc_cntr = llc->dec_cntr = 2;
llc->dec_step = llc->connect_step = 1;
@@ -827,9 +820,6 @@ static int llc_sk_init(struct sock* sk)
* tx_win of remote LLC) */
skb_queue_head_init(&llc->pdu_unack_q);
sk->sk_backlog_rcv = llc_backlog_rcv;
- sk->sk_protinfo = llc;
-out:
- return rc;
}
/**
@@ -842,12 +832,12 @@ out:
*/
struct sock *llc_sk_alloc(int family, int priority)
{
- struct sock *sk = sk_alloc(family, priority, 1, NULL);
+ struct sock *sk = sk_alloc(family, priority,
+ sizeof(struct llc_sock), NULL);
if (!sk)
goto out;
- if (llc_sk_init(sk))
- goto outsk;
+ llc_sk_init(sk);
sock_init_data(NULL, sk);
sk_set_owner(sk, THIS_MODULE);
#ifdef LLC_REFCNT_DEBUG
@@ -857,10 +847,6 @@ struct sock *llc_sk_alloc(int family, int priority)
#endif
out:
return sk;
-outsk:
- sk_free(sk);
- sk = NULL;
- goto out;
}
/**
@@ -871,7 +857,7 @@ outsk:
*/
void llc_sk_free(struct sock *sk)
{
- struct llc_opt *llc = llc_sk(sk);
+ struct llc_sock *llc = llc_sk(sk);
llc->state = LLC_CONN_OUT_OF_SVC;
/* Stop all (possibly) running timers */
@@ -908,7 +894,7 @@ void llc_sk_free(struct sock *sk)
*/
void llc_sk_reset(struct sock *sk)
{
- struct llc_opt *llc = llc_sk(sk);
+ struct llc_sock *llc = llc_sk(sk);
llc_conn_ac_stop_all_timers(sk, NULL);
skb_queue_purge(&sk->sk_write_queue);
diff --git a/net/llc/llc_if.c b/net/llc/llc_if.c
index 5949147018afa..0f9fc48aeaf91 100644
--- a/net/llc/llc_if.c
+++ b/net/llc/llc_if.c
@@ -45,7 +45,7 @@ int llc_build_and_send_pkt(struct sock *sk, struct sk_buff *skb)
{
struct llc_conn_state_ev *ev;
int rc = -ECONNABORTED;
- struct llc_opt *llc = llc_sk(sk);
+ struct llc_sock *llc = llc_sk(sk);
if (llc->state == LLC_CONN_STATE_ADM)
goto out;
@@ -86,7 +86,7 @@ int llc_establish_connection(struct sock *sk, u8 *lmac, u8 *dmac, u8 dsap)
int rc = -EISCONN;
struct llc_addr laddr, daddr;
struct sk_buff *skb;
- struct llc_opt *llc = llc_sk(sk);
+ struct llc_sock *llc = llc_sk(sk);
struct sock *existing;
laddr.lsap = llc->sap->laddr.lsap;
diff --git a/net/llc/llc_proc.c b/net/llc/llc_proc.c
index c7de46e5cea4a..36e8db3fa1a2a 100644
--- a/net/llc/llc_proc.c
+++ b/net/llc/llc_proc.c
@@ -65,7 +65,7 @@ static void *llc_seq_start(struct seq_file *seq, loff_t *pos)
static void *llc_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
struct sock* sk, *next;
- struct llc_opt *llc;
+ struct llc_sock *llc;
struct llc_sap *sap;
++*pos;
@@ -102,7 +102,7 @@ static void llc_seq_stop(struct seq_file *seq, void *v)
{
if (v && v != SEQ_START_TOKEN) {
struct sock *sk = v;
- struct llc_opt *llc = llc_sk(sk);
+ struct llc_sock *llc = llc_sk(sk);
struct llc_sap *sap = llc->sap;
read_unlock_bh(&sap->sk_list.lock);
@@ -113,7 +113,7 @@ static void llc_seq_stop(struct seq_file *seq, void *v)
static int llc_seq_socket_show(struct seq_file *seq, void *v)
{
struct sock* sk;
- struct llc_opt *llc;
+ struct llc_sock *llc;
if (v == SEQ_START_TOKEN) {
seq_puts(seq, "SKt Mc local_mac_sap remote_mac_sap "
@@ -160,7 +160,7 @@ static char *llc_conn_state_names[] = {
static int llc_seq_core_show(struct seq_file *seq, void *v)
{
struct sock* sk;
- struct llc_opt *llc;
+ struct llc_sock *llc;
if (v == SEQ_START_TOKEN) {
seq_puts(seq, "Connection list:\n"
diff --git a/net/llc/llc_sap.c b/net/llc/llc_sap.c
index 89ca222cfba5e..965c94eb4bbc7 100644
--- a/net/llc/llc_sap.c
+++ b/net/llc/llc_sap.c
@@ -283,7 +283,7 @@ static struct sock *llc_lookup_dgram(struct llc_sap *sap,
read_lock_bh(&sap->sk_list.lock);
sk_for_each(rc, node, &sap->sk_list.list) {
- struct llc_opt *llc = llc_sk(rc);
+ struct llc_sock *llc = llc_sk(rc);
if (rc->sk_type == SOCK_DGRAM &&
llc->laddr.lsap == laddr->lsap &&
diff --git a/net/netlink/Makefile b/net/netlink/Makefile
index b81a514ecfd8f..39d9c2dcd03cf 100644
--- a/net/netlink/Makefile
+++ b/net/netlink/Makefile
@@ -3,4 +3,3 @@
#
obj-y := af_netlink.o
-obj-$(CONFIG_NETLINK_DEV) += netlink_dev.o
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index a209998165243..65f1a89ac6dea 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -55,25 +55,24 @@
#define Nprintk(a...)
-#if defined(CONFIG_NETLINK_DEV) || defined(CONFIG_NETLINK_DEV_MODULE)
-#define NL_EMULATE_DEV
-#endif
-
-struct netlink_opt
-{
+struct netlink_sock {
+ /* struct sock has to be the first member of netlink_sock */
+ struct sock sk;
u32 pid;
unsigned int groups;
u32 dst_pid;
unsigned int dst_groups;
unsigned long state;
- int (*handler)(int unit, struct sk_buff *skb);
wait_queue_head_t wait;
struct netlink_callback *cb;
spinlock_t cb_lock;
void (*data_ready)(struct sock *sk, int bytes);
};
-#define nlk_sk(__sk) ((struct netlink_opt *)(__sk)->sk_protinfo)
+static inline struct netlink_sock *nlk_sk(struct sock *sk)
+{
+ return (struct netlink_sock *)sk;
+}
struct nl_pid_hash {
struct hlist_head *table;
@@ -122,8 +121,6 @@ static void netlink_sock_destruct(struct sock *sk)
BUG_TRAP(!atomic_read(&sk->sk_rmem_alloc));
BUG_TRAP(!atomic_read(&sk->sk_wmem_alloc));
BUG_TRAP(!nlk_sk(sk)->cb);
-
- kfree(nlk_sk(sk));
}
/* This lock without WQ_FLAG_EXCLUSIVE is good on UP and it is _very_ bad on SMP.
@@ -327,7 +324,7 @@ static void netlink_remove(struct sock *sk)
static int netlink_create(struct socket *sock, int protocol)
{
struct sock *sk;
- struct netlink_opt *nlk;
+ struct netlink_sock *nlk;
sock->state = SS_UNCONNECTED;
@@ -339,19 +336,15 @@ static int netlink_create(struct socket *sock, int protocol)
sock->ops = &netlink_ops;
- sk = sk_alloc(PF_NETLINK, GFP_KERNEL, 1, NULL);
+ sk = sk_alloc(PF_NETLINK, GFP_KERNEL,
+ sizeof(struct netlink_sock), NULL);
if (!sk)
return -ENOMEM;
sock_init_data(sock,sk);
sk_set_owner(sk, THIS_MODULE);
- nlk = sk->sk_protinfo = kmalloc(sizeof(*nlk), GFP_KERNEL);
- if (!nlk) {
- sk_free(sk);
- return -ENOMEM;
- }
- memset(nlk, 0, sizeof(*nlk));
+ nlk = nlk_sk(sk);
spin_lock_init(&nlk->cb_lock);
init_waitqueue_head(&nlk->wait);
@@ -364,7 +357,7 @@ static int netlink_create(struct socket *sock, int protocol)
static int netlink_release(struct socket *sock)
{
struct sock *sk = sock->sk;
- struct netlink_opt *nlk;
+ struct netlink_sock *nlk;
if (!sk)
return 0;
@@ -432,7 +425,6 @@ retry:
err = netlink_insert(sk, pid);
if (err == -EADDRINUSE)
goto retry;
- nlk_sk(sk)->groups = 0;
return 0;
}
@@ -445,7 +437,7 @@ static inline int netlink_capable(struct socket *sock, unsigned int flag)
static int netlink_bind(struct socket *sock, struct sockaddr *addr, int addr_len)
{
struct sock *sk = sock->sk;
- struct netlink_opt *nlk = nlk_sk(sk);
+ struct netlink_sock *nlk = nlk_sk(sk);
struct sockaddr_nl *nladdr = (struct sockaddr_nl *)addr;
int err;
@@ -486,7 +478,7 @@ static int netlink_connect(struct socket *sock, struct sockaddr *addr,
{
int err = 0;
struct sock *sk = sock->sk;
- struct netlink_opt *nlk = nlk_sk(sk);
+ struct netlink_sock *nlk = nlk_sk(sk);
struct sockaddr_nl *nladdr=(struct sockaddr_nl*)addr;
if (addr->sa_family == AF_UNSPEC) {
@@ -517,7 +509,7 @@ static int netlink_connect(struct socket *sock, struct sockaddr *addr,
static int netlink_getname(struct socket *sock, struct sockaddr *addr, int *addr_len, int peer)
{
struct sock *sk = sock->sk;
- struct netlink_opt *nlk = nlk_sk(sk);
+ struct netlink_sock *nlk = nlk_sk(sk);
struct sockaddr_nl *nladdr=(struct sockaddr_nl *)addr;
nladdr->nl_family = AF_NETLINK;
@@ -546,7 +538,7 @@ static struct sock *netlink_getsockbypid(struct sock *ssk, u32 pid)
{
int protocol = ssk->sk_protocol;
struct sock *sock;
- struct netlink_opt *nlk;
+ struct netlink_sock *nlk;
sock = netlink_lookup(protocol, pid);
if (!sock)
@@ -592,14 +584,10 @@ struct sock *netlink_getsockbyfilp(struct file *filp)
*/
int netlink_attachskb(struct sock *sk, struct sk_buff *skb, int nonblock, long timeo)
{
- struct netlink_opt *nlk;
+ struct netlink_sock *nlk;
nlk = nlk_sk(sk);
-#ifdef NL_EMULATE_DEV
- if (nlk->handler)
- return 0;
-#endif
if (atomic_read(&sk->sk_rmem_alloc) > sk->sk_rcvbuf ||
test_bit(0, &nlk->state)) {
DECLARE_WAITQUEUE(wait, current);
@@ -635,18 +623,10 @@ int netlink_attachskb(struct sock *sk, struct sk_buff *skb, int nonblock, long t
int netlink_sendskb(struct sock *sk, struct sk_buff *skb, int protocol)
{
- struct netlink_opt *nlk;
+ struct netlink_sock *nlk;
int len = skb->len;
nlk = nlk_sk(sk);
-#ifdef NL_EMULATE_DEV
- if (nlk->handler) {
- skb_orphan(skb);
- len = nlk->handler(protocol, skb);
- sock_put(sk);
- return len;
- }
-#endif
skb_queue_tail(&sk->sk_receive_queue, skb);
sk->sk_data_ready(sk, len);
@@ -710,13 +690,8 @@ retry:
static __inline__ int netlink_broadcast_deliver(struct sock *sk, struct sk_buff *skb)
{
- struct netlink_opt *nlk = nlk_sk(sk);
-#ifdef NL_EMULATE_DEV
- if (nlk->handler) {
- nlk->handler(sk->sk_protocol, skb);
- return 0;
- } else
-#endif
+ struct netlink_sock *nlk = nlk_sk(sk);
+
if (atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf &&
!test_bit(0, &nlk->state)) {
skb_set_owner_r(skb, sk);
@@ -741,7 +716,7 @@ struct netlink_broadcast_data {
static inline int do_one_broadcast(struct sock *sk,
struct netlink_broadcast_data *p)
{
- struct netlink_opt *nlk = nlk_sk(sk);
+ struct netlink_sock *nlk = nlk_sk(sk);
int val;
if (p->exclude_sk == sk)
@@ -833,7 +808,7 @@ struct netlink_set_err_data {
static inline int do_one_set_err(struct sock *sk,
struct netlink_set_err_data *p)
{
- struct netlink_opt *nlk = nlk_sk(sk);
+ struct netlink_sock *nlk = nlk_sk(sk);
if (sk == p->exclude_sk)
goto out;
@@ -868,7 +843,7 @@ void netlink_set_err(struct sock *ssk, u32 pid, u32 group, int code)
static inline void netlink_rcv_wake(struct sock *sk)
{
- struct netlink_opt *nlk = nlk_sk(sk);
+ struct netlink_sock *nlk = nlk_sk(sk);
if (!skb_queue_len(&sk->sk_receive_queue))
clear_bit(0, &nlk->state);
@@ -881,7 +856,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
{
struct sock_iocb *siocb = kiocb_to_siocb(kiocb);
struct sock *sk = sock->sk;
- struct netlink_opt *nlk = nlk_sk(sk);
+ struct netlink_sock *nlk = nlk_sk(sk);
struct sockaddr_nl *addr=msg->msg_name;
u32 dst_pid;
u32 dst_groups;
@@ -965,7 +940,7 @@ static int netlink_recvmsg(struct kiocb *kiocb, struct socket *sock,
struct sock_iocb *siocb = kiocb_to_siocb(kiocb);
struct scm_cookie scm;
struct sock *sk = sock->sk;
- struct netlink_opt *nlk = nlk_sk(sk);
+ struct netlink_sock *nlk = nlk_sk(sk);
int noblock = flags&MSG_DONTWAIT;
size_t copied;
struct sk_buff *skb;
@@ -1019,7 +994,7 @@ out:
static void netlink_data_ready(struct sock *sk, int len)
{
- struct netlink_opt *nlk = nlk_sk(sk);
+ struct netlink_sock *nlk = nlk_sk(sk);
if (nlk->data_ready)
nlk->data_ready(sk, len);
@@ -1083,7 +1058,7 @@ static void netlink_destroy_callback(struct netlink_callback *cb)
static int netlink_dump(struct sock *sk)
{
- struct netlink_opt *nlk = nlk_sk(sk);
+ struct netlink_sock *nlk = nlk_sk(sk);
struct netlink_callback *cb;
struct sk_buff *skb;
struct nlmsghdr *nlh;
@@ -1105,9 +1080,11 @@ static int netlink_dump(struct sock *sk)
len = cb->dump(skb, cb);
if (len > 0) {
+ sock_hold(sk);
spin_unlock(&nlk->cb_lock);
skb_queue_tail(&sk->sk_receive_queue, skb);
sk->sk_data_ready(sk, len);
+ sock_put(sk);
return 0;
}
@@ -1133,7 +1110,7 @@ int netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
{
struct netlink_callback *cb;
struct sock *sk;
- struct netlink_opt *nlk;
+ struct netlink_sock *nlk;
cb = kmalloc(sizeof(*cb), GFP_KERNEL);
if (cb == NULL)
@@ -1290,7 +1267,7 @@ static int netlink_seq_show(struct seq_file *seq, void *v)
"Rmem Wmem Dump Locks\n");
else {
struct sock *s = v;
- struct netlink_opt *nlk = nlk_sk(s);
+ struct netlink_sock *nlk = nlk_sk(s);
seq_printf(seq, "%p %-3d %-6d %08x %-8d %-8d %p %d\n",
s,
diff --git a/net/netlink/netlink_dev.c b/net/netlink/netlink_dev.c
deleted file mode 100644
index 59f53de4b86bf..0000000000000
--- a/net/netlink/netlink_dev.c
+++ /dev/null
@@ -1,278 +0,0 @@
-/*
- * NETLINK An implementation of a loadable kernel mode driver providing
- * multiple kernel/user space bidirectional communications links.
- *
- * Author: Alan Cox <alan@redhat.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- *
- * Now netlink devices are emulated on the top of netlink sockets
- * by compatibility reasons. Remove this file after a period. --ANK
- *
- */
-
-#include <linux/module.h>
-
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/major.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/skbuff.h>
-#include <linux/netlink.h>
-#include <linux/poll.h>
-#include <linux/init.h>
-#include <linux/devfs_fs_kernel.h>
-#include <linux/smp_lock.h>
-#include <linux/device.h>
-#include <linux/bitops.h>
-
-#include <asm/system.h>
-#include <asm/uaccess.h>
-
-static long open_map;
-static struct socket *netlink_user[MAX_LINKS];
-static struct class_simple *netlink_class;
-
-/*
- * Device operations
- */
-
-static unsigned int netlink_poll(struct file *file, poll_table * wait)
-{
- struct socket *sock = netlink_user[iminor(file->f_dentry->d_inode)];
-
- if (sock->ops->poll==NULL)
- return 0;
- return sock->ops->poll(file, sock, wait);
-}
-
-/*
- * Write a message to the kernel side of a communication link
- */
-
-static ssize_t netlink_write(struct file * file, const char __user * buf,
- size_t count, loff_t *pos)
-{
- struct inode *inode = file->f_dentry->d_inode;
- struct socket *sock = netlink_user[iminor(inode)];
- struct msghdr msg;
- struct iovec iov;
-
- iov.iov_base = (void __user*)buf;
- iov.iov_len = count;
- msg.msg_name=NULL;
- msg.msg_namelen=0;
- msg.msg_controllen=0;
- msg.msg_flags=0;
- msg.msg_iov=&iov;
- msg.msg_iovlen=1;
-
- return sock_sendmsg(sock, &msg, count);
-}
-
-/*
- * Read a message from the kernel side of the communication link
- */
-
-static ssize_t netlink_read(struct file * file, char __user * buf,
- size_t count, loff_t *pos)
-{
- struct inode *inode = file->f_dentry->d_inode;
- struct socket *sock = netlink_user[iminor(inode)];
- struct msghdr msg;
- struct iovec iov;
-
- iov.iov_base = buf;
- iov.iov_len = count;
- msg.msg_name=NULL;
- msg.msg_namelen=0;
- msg.msg_controllen=0;
- msg.msg_flags=0;
- msg.msg_iov=&iov;
- msg.msg_iovlen=1;
- if (file->f_flags&O_NONBLOCK)
- msg.msg_flags=MSG_DONTWAIT;
-
- return sock_recvmsg(sock, &msg, count, msg.msg_flags);
-}
-
-static int netlink_open(struct inode * inode, struct file * file)
-{
- unsigned int minor = iminor(inode);
- struct socket *sock;
- struct sockaddr_nl nladdr;
- int err;
-
- if (minor>=MAX_LINKS)
- return -ENODEV;
- if (test_and_set_bit(minor, &open_map))
- return -EBUSY;
-
- err = sock_create_kern(PF_NETLINK, SOCK_RAW, minor, &sock);
- if (err < 0)
- goto out;
-
- memset(&nladdr, 0, sizeof(nladdr));
- nladdr.nl_family = AF_NETLINK;
- nladdr.nl_groups = ~0;
- if ((err = sock->ops->bind(sock, (struct sockaddr*)&nladdr, sizeof(nladdr))) < 0) {
- sock_release(sock);
- goto out;
- }
-
- netlink_user[minor] = sock;
- return 0;
-
-out:
- clear_bit(minor, &open_map);
- return err;
-}
-
-static int netlink_release(struct inode * inode, struct file * file)
-{
- unsigned int minor = iminor(inode);
- struct socket *sock;
-
- sock = netlink_user[minor];
- netlink_user[minor] = NULL;
- clear_bit(minor, &open_map);
- sock_release(sock);
- return 0;
-}
-
-
-static int netlink_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- unsigned int minor = iminor(inode);
- int retval = 0;
-
- if (minor >= MAX_LINKS)
- return -ENODEV;
- switch ( cmd ) {
- default:
- retval = -EINVAL;
- }
- return retval;
-}
-
-
-static struct file_operations netlink_fops = {
- .owner = THIS_MODULE,
- .llseek = no_llseek,
- .read = netlink_read,
- .write = netlink_write,
- .poll = netlink_poll,
- .ioctl = netlink_ioctl,
- .open = netlink_open,
- .release = netlink_release,
-};
-
-static struct {
- char *name;
- int minor;
-} entries[] = {
- {
- .name = "route",
- .minor = NETLINK_ROUTE,
- },
- {
- .name = "skip",
- .minor = NETLINK_SKIP,
- },
- {
- .name = "usersock",
- .minor = NETLINK_USERSOCK,
- },
- {
- .name = "fwmonitor",
- .minor = NETLINK_FIREWALL,
- },
- {
- .name = "tcpdiag",
- .minor = NETLINK_TCPDIAG,
- },
- {
- .name = "nflog",
- .minor = NETLINK_NFLOG,
- },
- {
- .name = "xfrm",
- .minor = NETLINK_XFRM,
- },
- {
- .name = "arpd",
- .minor = NETLINK_ARPD,
- },
- {
- .name = "route6",
- .minor = NETLINK_ROUTE6,
- },
- {
- .name = "ip6_fw",
- .minor = NETLINK_IP6_FW,
- },
- {
- .name = "dnrtmsg",
- .minor = NETLINK_DNRTMSG,
- },
-};
-
-static int __init init_netlink(void)
-{
- int i;
-
- if (register_chrdev(NETLINK_MAJOR,"netlink", &netlink_fops)) {
- printk(KERN_ERR "netlink: unable to get major %d\n", NETLINK_MAJOR);
- return -EIO;
- }
-
- netlink_class = class_simple_create(THIS_MODULE, "netlink");
- if (IS_ERR(netlink_class)) {
- printk (KERN_ERR "Error creating netlink class.\n");
- unregister_chrdev(NETLINK_MAJOR, "netlink");
- return PTR_ERR(netlink_class);
- }
-
- devfs_mk_dir("netlink");
-
- /* Someone tell me the official names for the uppercase ones */
- for (i = 0; i < ARRAY_SIZE(entries); i++) {
- devfs_mk_cdev(MKDEV(NETLINK_MAJOR, entries[i].minor),
- S_IFCHR|S_IRUSR|S_IWUSR, "netlink/%s", entries[i].name);
- class_simple_device_add(netlink_class, MKDEV(NETLINK_MAJOR, entries[i].minor), NULL, "%s", entries[i].name);
- }
-
- for (i = 0; i < 16; i++) {
- devfs_mk_cdev(MKDEV(NETLINK_MAJOR, i + 16),
- S_IFCHR|S_IRUSR|S_IWUSR, "netlink/tap%d", i);
- class_simple_device_add(netlink_class, MKDEV(NETLINK_MAJOR, i + 16), NULL, "tap%d", i);
- }
-
- return 0;
-}
-
-static void __exit cleanup_netlink(void)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(entries); i++) {
- devfs_remove("netlink/%s", entries[i].name);
- class_simple_device_remove(MKDEV(NETLINK_MAJOR, entries[i].minor));
- }
- for (i = 0; i < 16; i++) {
- devfs_remove("netlink/tap%d", i);
- class_simple_device_remove(MKDEV(NETLINK_MAJOR, i + 16));
- }
- devfs_remove("netlink");
- class_simple_destroy(netlink_class);
- unregister_chrdev(NETLINK_MAJOR, "netlink");
-}
-
-MODULE_LICENSE("GPL");
-module_init(init_netlink);
-module_exit(cleanup_netlink);
diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c
index 39223bbf19382..024217b2f9e58 100644
--- a/net/netrom/af_netrom.c
+++ b/net/netrom/af_netrom.c
@@ -63,28 +63,10 @@ static HLIST_HEAD(nr_list);
static DEFINE_SPINLOCK(nr_list_lock);
static struct proto_ops nr_proto_ops;
-void nr_init_timers(struct sock *sk);
static struct sock *nr_alloc_sock(void)
{
- nr_cb *nr;
- struct sock *sk = sk_alloc(PF_NETROM, GFP_ATOMIC, 1, NULL);
-
- if (!sk)
- goto out;
-
- nr = sk->sk_protinfo = kmalloc(sizeof(*nr), GFP_ATOMIC);
- if (!nr)
- goto frees;
-
- memset(nr, 0x00, sizeof(*nr));
- nr->sk = sk;
-out:
- return sk;
-frees:
- sk_free(sk);
- sk = NULL;
- goto out;
+ return sk_alloc(PF_NETROM, GFP_ATOMIC, sizeof(struct nr_sock), NULL);
}
/*
@@ -170,7 +152,7 @@ static struct sock *nr_find_socket(unsigned char index, unsigned char id)
spin_lock_bh(&nr_list_lock);
sk_for_each(s, node, &nr_list) {
- nr_cb *nr = nr_sk(s);
+ struct nr_sock *nr = nr_sk(s);
if (nr->my_index == index && nr->my_id == id) {
bh_lock_sock(s);
@@ -194,7 +176,7 @@ static struct sock *nr_find_peer(unsigned char index, unsigned char id,
spin_lock_bh(&nr_list_lock);
sk_for_each(s, node, &nr_list) {
- nr_cb *nr = nr_sk(s);
+ struct nr_sock *nr = nr_sk(s);
if (nr->your_index == index && nr->your_id == id &&
!ax25cmp(&nr->dest_addr, dest)) {
@@ -301,7 +283,7 @@ static int nr_setsockopt(struct socket *sock, int level, int optname,
char __user *optval, int optlen)
{
struct sock *sk = sock->sk;
- nr_cb *nr = nr_sk(sk);
+ struct nr_sock *nr = nr_sk(sk);
int opt;
if (level != SOL_NETROM)
@@ -353,7 +335,7 @@ static int nr_getsockopt(struct socket *sock, int level, int optname,
char __user *optval, int __user *optlen)
{
struct sock *sk = sock->sk;
- nr_cb *nr = nr_sk(sk);
+ struct nr_sock *nr = nr_sk(sk);
int val = 0;
int len;
@@ -419,7 +401,7 @@ static int nr_listen(struct socket *sock, int backlog)
static int nr_create(struct socket *sock, int protocol)
{
struct sock *sk;
- nr_cb *nr;
+ struct nr_sock *nr;
if (sock->type != SOCK_SEQPACKET || protocol != 0)
return -ESOCKTNOSUPPORT;
@@ -457,7 +439,7 @@ static int nr_create(struct socket *sock, int protocol)
static struct sock *nr_make_new(struct sock *osk)
{
struct sock *sk;
- nr_cb *nr, *onr;
+ struct nr_sock *nr, *onr;
if (osk->sk_type != SOCK_SEQPACKET)
return NULL;
@@ -476,10 +458,14 @@ static struct sock *nr_make_new(struct sock *osk)
sk->sk_protocol = osk->sk_protocol;
sk->sk_rcvbuf = osk->sk_rcvbuf;
sk->sk_sndbuf = osk->sk_sndbuf;
- sk->sk_debug = osk->sk_debug;
sk->sk_state = TCP_ESTABLISHED;
sk->sk_sleep = osk->sk_sleep;
- sk->sk_zapped = osk->sk_zapped;
+
+ if (sock_flag(osk, SOCK_ZAPPED))
+ sock_set_flag(sk, SOCK_ZAPPED);
+
+ if (sock_flag(osk, SOCK_DBG))
+ sock_set_flag(sk, SOCK_DBG);
skb_queue_head_init(&nr->ack_queue);
skb_queue_head_init(&nr->reseq_queue);
@@ -505,7 +491,7 @@ static struct sock *nr_make_new(struct sock *osk)
static int nr_release(struct socket *sock)
{
struct sock *sk = sock->sk;
- nr_cb *nr;
+ struct nr_sock *nr;
if (sk == NULL) return 0;
@@ -553,13 +539,13 @@ static int nr_release(struct socket *sock)
static int nr_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
{
struct sock *sk = sock->sk;
- nr_cb *nr = nr_sk(sk);
+ struct nr_sock *nr = nr_sk(sk);
struct full_sockaddr_ax25 *addr = (struct full_sockaddr_ax25 *)uaddr;
struct net_device *dev;
ax25_address *user, *source;
lock_sock(sk);
- if (!sk->sk_zapped) {
+ if (!sock_flag(sk, SOCK_ZAPPED)) {
release_sock(sk);
return -EINVAL;
}
@@ -611,7 +597,7 @@ static int nr_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
nr->device = dev;
nr_insert_socket(sk);
- sk->sk_zapped = 0;
+ sock_reset_flag(sk, SOCK_ZAPPED);
dev_put(dev);
release_sock(sk);
SOCK_DEBUG(sk, "NET/ROM: socket is bound\n");
@@ -622,7 +608,7 @@ static int nr_connect(struct socket *sock, struct sockaddr *uaddr,
int addr_len, int flags)
{
struct sock *sk = sock->sk;
- nr_cb *nr = nr_sk(sk);
+ struct nr_sock *nr = nr_sk(sk);
struct sockaddr_ax25 *addr = (struct sockaddr_ax25 *)uaddr;
ax25_address *user, *source = NULL;
struct net_device *dev;
@@ -656,8 +642,8 @@ static int nr_connect(struct socket *sock, struct sockaddr *uaddr,
release_sock(sk);
return -EINVAL;
}
- if (sk->sk_zapped) { /* Must bind first - autobinding in this may or may not work */
- sk->sk_zapped = 0;
+ if (sock_flag(sk, SOCK_ZAPPED)) { /* Must bind first - autobinding in this may or may not work */
+ sock_reset_flag(sk, SOCK_ZAPPED);
if ((dev = nr_dev_first()) == NULL) {
release_sock(sk);
@@ -819,7 +805,7 @@ static int nr_getname(struct socket *sock, struct sockaddr *uaddr,
{
struct full_sockaddr_ax25 *sax = (struct full_sockaddr_ax25 *)uaddr;
struct sock *sk = sock->sk;
- nr_cb *nr = nr_sk(sk);
+ struct nr_sock *nr = nr_sk(sk);
lock_sock(sk);
if (peer != 0) {
@@ -847,7 +833,7 @@ int nr_rx_frame(struct sk_buff *skb, struct net_device *dev)
{
struct sock *sk;
struct sock *make;
- nr_cb *nr_make;
+ struct nr_sock *nr_make;
ax25_address *src, *dest, *user;
unsigned short circuit_index, circuit_id;
unsigned short peer_circuit_index, peer_circuit_id;
@@ -939,7 +925,7 @@ int nr_rx_frame(struct sk_buff *skb, struct net_device *dev)
user = (ax25_address *)(skb->data + 21);
- if (!sk || sk->sk_ack_backlog == sk->sk_max_ack_backlog ||
+ if (sk == NULL || sk_acceptq_is_full(sk) ||
(make = nr_make_new(sk)) == NULL) {
nr_transmit_refusal(skb, 0);
if (sk)
@@ -1012,7 +998,7 @@ static int nr_sendmsg(struct kiocb *iocb, struct socket *sock,
struct msghdr *msg, size_t len)
{
struct sock *sk = sock->sk;
- nr_cb *nr = nr_sk(sk);
+ struct nr_sock *nr = nr_sk(sk);
struct sockaddr_ax25 *usax = (struct sockaddr_ax25 *)msg->msg_name;
int err;
struct sockaddr_ax25 sax;
@@ -1024,7 +1010,7 @@ static int nr_sendmsg(struct kiocb *iocb, struct socket *sock,
return -EINVAL;
lock_sock(sk);
- if (sk->sk_zapped) {
+ if (sock_flag(sk, SOCK_ZAPPED)) {
err = -EADDRNOTAVAIL;
goto out;
}
@@ -1272,7 +1258,7 @@ static int nr_info_show(struct seq_file *seq, void *v)
{
struct sock *s = v;
struct net_device *dev;
- nr_cb *nr;
+ struct nr_sock *nr;
const char *devname;
if (v == SEQ_START_TOKEN)
diff --git a/net/netrom/nr_in.c b/net/netrom/nr_in.c
index e272aff648bd5..9c44b37941263 100644
--- a/net/netrom/nr_in.c
+++ b/net/netrom/nr_in.c
@@ -34,7 +34,7 @@
static int nr_queue_rx_frame(struct sock *sk, struct sk_buff *skb, int more)
{
struct sk_buff *skbo, *skbn = skb;
- nr_cb *nr = nr_sk(sk);
+ struct nr_sock *nr = nr_sk(sk);
skb_pull(skb, NR_NETWORK_LEN + NR_TRANSPORT_LEN);
@@ -74,10 +74,9 @@ static int nr_queue_rx_frame(struct sock *sk, struct sk_buff *skb, int more)
static int nr_state1_machine(struct sock *sk, struct sk_buff *skb,
int frametype)
{
- bh_lock_sock(sk);
switch (frametype) {
case NR_CONNACK: {
- nr_cb *nr = nr_sk(sk);
+ struct nr_sock *nr = nr_sk(sk);
nr_stop_t1timer(sk);
nr_start_idletimer(sk);
@@ -103,8 +102,6 @@ static int nr_state1_machine(struct sock *sk, struct sk_buff *skb,
default:
break;
}
- bh_unlock_sock(sk);
-
return 0;
}
@@ -116,7 +113,6 @@ static int nr_state1_machine(struct sock *sk, struct sk_buff *skb,
static int nr_state2_machine(struct sock *sk, struct sk_buff *skb,
int frametype)
{
- bh_lock_sock(sk);
switch (frametype) {
case NR_CONNACK | NR_CHOKE_FLAG:
nr_disconnect(sk, ECONNRESET);
@@ -132,8 +128,6 @@ static int nr_state2_machine(struct sock *sk, struct sk_buff *skb,
default:
break;
}
- bh_unlock_sock(sk);
-
return 0;
}
@@ -144,7 +138,7 @@ static int nr_state2_machine(struct sock *sk, struct sk_buff *skb,
*/
static int nr_state3_machine(struct sock *sk, struct sk_buff *skb, int frametype)
{
- nr_cb *nrom = nr_sk(sk);
+ struct nr_sock *nrom = nr_sk(sk);
struct sk_buff_head temp_queue;
struct sk_buff *skbn;
unsigned short save_vr;
@@ -154,7 +148,6 @@ static int nr_state3_machine(struct sock *sk, struct sk_buff *skb, int frametype
nr = skb->data[18];
ns = skb->data[17];
- bh_lock_sock(sk);
switch (frametype) {
case NR_CONNREQ:
nr_write_internal(sk, NR_CONNACK);
@@ -265,15 +258,13 @@ static int nr_state3_machine(struct sock *sk, struct sk_buff *skb, int frametype
default:
break;
}
- bh_unlock_sock(sk);
-
return queued;
}
-/* Higher level upcall for a LAPB frame */
+/* Higher level upcall for a LAPB frame - called with sk locked */
int nr_process_rx_frame(struct sock *sk, struct sk_buff *skb)
{
- nr_cb *nr = nr_sk(sk);
+ struct nr_sock *nr = nr_sk(sk);
int queued = 0, frametype;
if (nr->state == NR_STATE_0)
diff --git a/net/netrom/nr_out.c b/net/netrom/nr_out.c
index d36393da58257..7939ded9c98cc 100644
--- a/net/netrom/nr_out.c
+++ b/net/netrom/nr_out.c
@@ -82,7 +82,7 @@ void nr_output(struct sock *sk, struct sk_buff *skb)
*/
static void nr_send_iframe(struct sock *sk, struct sk_buff *skb)
{
- nr_cb *nr = nr_sk(sk);
+ struct nr_sock *nr = nr_sk(sk);
if (skb == NULL)
return;
@@ -101,7 +101,7 @@ static void nr_send_iframe(struct sock *sk, struct sk_buff *skb)
void nr_send_nak_frame(struct sock *sk)
{
struct sk_buff *skb, *skbn;
- nr_cb *nr = nr_sk(sk);
+ struct nr_sock *nr = nr_sk(sk);
if ((skb = skb_peek(&nr->ack_queue)) == NULL)
return;
@@ -125,7 +125,7 @@ void nr_send_nak_frame(struct sock *sk)
void nr_kick(struct sock *sk)
{
- nr_cb *nr = nr_sk(sk);
+ struct nr_sock *nr = nr_sk(sk);
struct sk_buff *skb, *skbn;
unsigned short start, end;
@@ -188,7 +188,7 @@ void nr_kick(struct sock *sk)
void nr_transmit_buffer(struct sock *sk, struct sk_buff *skb)
{
- nr_cb *nr = nr_sk(sk);
+ struct nr_sock *nr = nr_sk(sk);
unsigned char *dptr;
/*
@@ -223,7 +223,7 @@ void nr_transmit_buffer(struct sock *sk, struct sk_buff *skb)
void nr_establish_data_link(struct sock *sk)
{
- nr_cb *nr = nr_sk(sk);
+ struct nr_sock *nr = nr_sk(sk);
nr->condition = 0x00;
nr->n2count = 0;
@@ -241,7 +241,7 @@ void nr_establish_data_link(struct sock *sk)
*/
void nr_enquiry_response(struct sock *sk)
{
- nr_cb *nr = nr_sk(sk);
+ struct nr_sock *nr = nr_sk(sk);
int frametype = NR_INFOACK;
if (nr->condition & NR_COND_OWN_RX_BUSY) {
@@ -259,7 +259,7 @@ void nr_enquiry_response(struct sock *sk)
void nr_check_iframes_acked(struct sock *sk, unsigned short nr)
{
- nr_cb *nrom = nr_sk(sk);
+ struct nr_sock *nrom = nr_sk(sk);
if (nrom->vs == nr) {
nr_frames_acked(sk, nr);
diff --git a/net/netrom/nr_subr.c b/net/netrom/nr_subr.c
index 474ff6309f109..0627347b14b88 100644
--- a/net/netrom/nr_subr.c
+++ b/net/netrom/nr_subr.c
@@ -34,7 +34,7 @@
*/
void nr_clear_queues(struct sock *sk)
{
- nr_cb *nr = nr_sk(sk);
+ struct nr_sock *nr = nr_sk(sk);
skb_queue_purge(&sk->sk_write_queue);
skb_queue_purge(&nr->ack_queue);
@@ -49,7 +49,7 @@ void nr_clear_queues(struct sock *sk)
*/
void nr_frames_acked(struct sock *sk, unsigned short nr)
{
- nr_cb *nrom = nr_sk(sk);
+ struct nr_sock *nrom = nr_sk(sk);
struct sk_buff *skb;
/*
@@ -88,7 +88,7 @@ void nr_requeue_frames(struct sock *sk)
*/
int nr_validate_nr(struct sock *sk, unsigned short nr)
{
- nr_cb *nrom = nr_sk(sk);
+ struct nr_sock *nrom = nr_sk(sk);
unsigned short vc = nrom->va;
while (vc != nrom->vs) {
@@ -104,7 +104,7 @@ int nr_validate_nr(struct sock *sk, unsigned short nr)
*/
int nr_in_rx_window(struct sock *sk, unsigned short ns)
{
- nr_cb *nr = nr_sk(sk);
+ struct nr_sock *nr = nr_sk(sk);
unsigned short vc = nr->vr;
unsigned short vt = (nr->vl + nr->window) % NR_MODULUS;
@@ -122,7 +122,7 @@ int nr_in_rx_window(struct sock *sk, unsigned short ns)
*/
void nr_write_internal(struct sock *sk, int frametype)
{
- nr_cb *nr = nr_sk(sk);
+ struct nr_sock *nr = nr_sk(sk);
struct sk_buff *skb;
unsigned char *dptr;
int len, timeout;
diff --git a/net/netrom/nr_timer.c b/net/netrom/nr_timer.c
index 213d0b4007095..faabda8088be5 100644
--- a/net/netrom/nr_timer.c
+++ b/net/netrom/nr_timer.c
@@ -38,7 +38,7 @@ static void nr_idletimer_expiry(unsigned long);
void nr_init_timers(struct sock *sk)
{
- nr_cb *nr = nr_sk(sk);
+ struct nr_sock *nr = nr_sk(sk);
init_timer(&nr->t1timer);
nr->t1timer.data = (unsigned long)sk;
@@ -63,28 +63,28 @@ void nr_init_timers(struct sock *sk)
void nr_start_t1timer(struct sock *sk)
{
- nr_cb *nr = nr_sk(sk);
+ struct nr_sock *nr = nr_sk(sk);
mod_timer(&nr->t1timer, jiffies + nr->t1);
}
void nr_start_t2timer(struct sock *sk)
{
- nr_cb *nr = nr_sk(sk);
+ struct nr_sock *nr = nr_sk(sk);
mod_timer(&nr->t2timer, jiffies + nr->t2);
}
void nr_start_t4timer(struct sock *sk)
{
- nr_cb *nr = nr_sk(sk);
+ struct nr_sock *nr = nr_sk(sk);
mod_timer(&nr->t4timer, jiffies + nr->t4);
}
void nr_start_idletimer(struct sock *sk)
{
- nr_cb *nr = nr_sk(sk);
+ struct nr_sock *nr = nr_sk(sk);
if (nr->idle > 0)
mod_timer(&nr->idletimer, jiffies + nr->idle);
@@ -128,7 +128,7 @@ int nr_t1timer_running(struct sock *sk)
static void nr_heartbeat_expiry(unsigned long param)
{
struct sock *sk = (struct sock *)param;
- nr_cb *nr = nr_sk(sk);
+ struct nr_sock *nr = nr_sk(sk);
bh_lock_sock(sk);
switch (nr->state) {
@@ -167,7 +167,7 @@ static void nr_heartbeat_expiry(unsigned long param)
static void nr_t2timer_expiry(unsigned long param)
{
struct sock *sk = (struct sock *)param;
- nr_cb *nr = nr_sk(sk);
+ struct nr_sock *nr = nr_sk(sk);
bh_lock_sock(sk);
if (nr->condition & NR_COND_ACK_PENDING) {
@@ -189,7 +189,7 @@ static void nr_t4timer_expiry(unsigned long param)
static void nr_idletimer_expiry(unsigned long param)
{
struct sock *sk = (struct sock *)param;
- nr_cb *nr = nr_sk(sk);
+ struct nr_sock *nr = nr_sk(sk);
bh_lock_sock(sk);
@@ -217,7 +217,7 @@ static void nr_idletimer_expiry(unsigned long param)
static void nr_t1timer_expiry(unsigned long param)
{
struct sock *sk = (struct sock *)param;
- nr_cb *nr = nr_sk(sk);
+ struct nr_sock *nr = nr_sk(sk);
bh_lock_sock(sk);
switch (nr->state) {
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index a996d9c43f9e4..1c994ed5cf356 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -170,8 +170,9 @@ static int packet_set_ring(struct sock *sk, struct tpacket_req *req, int closing
static void packet_flush_mclist(struct sock *sk);
-struct packet_opt
-{
+struct packet_sock {
+ /* struct sock has to be the first member of packet_sock */
+ struct sock sk;
struct tpacket_stats stats;
#ifdef CONFIG_PACKET_MMAP
char * *pg_vec;
@@ -199,7 +200,7 @@ struct packet_opt
#ifdef CONFIG_PACKET_MMAP
-static inline char *packet_lookup_frame(struct packet_opt *po, unsigned int position)
+static inline char *packet_lookup_frame(struct packet_sock *po, unsigned int position)
{
unsigned int pg_vec_pos, frame_offset;
char *frame;
@@ -213,7 +214,10 @@ static inline char *packet_lookup_frame(struct packet_opt *po, unsigned int posi
}
#endif
-#define pkt_sk(__sk) ((struct packet_opt *)(__sk)->sk_protinfo)
+static inline struct packet_sock *pkt_sk(struct sock *sk)
+{
+ return (struct packet_sock *)sk;
+}
static void packet_sock_destruct(struct sock *sk)
{
@@ -225,8 +229,6 @@ static void packet_sock_destruct(struct sock *sk)
return;
}
- if (pkt_sk(sk))
- kfree(pkt_sk(sk));
atomic_dec(&packet_socks_nr);
#ifdef PACKET_REFCNT_DEBUG
printk(KERN_DEBUG "PACKET socket %p is free, %d are alive\n", sk, atomic_read(&packet_socks_nr));
@@ -440,7 +442,7 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev, struct packe
{
struct sock *sk;
struct sockaddr_ll *sll;
- struct packet_opt *po;
+ struct packet_sock *po;
u8 * skb_head = skb->data;
int skb_len = skb->len;
unsigned snaplen;
@@ -541,7 +543,7 @@ drop:
static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
{
struct sock *sk;
- struct packet_opt *po;
+ struct packet_sock *po;
struct sockaddr_ll *sll;
struct tpacket_hdr *h;
u8 * skb_head = skb->data;
@@ -699,7 +701,7 @@ static int packet_sendmsg(struct kiocb *iocb, struct socket *sock,
*/
if (saddr == NULL) {
- struct packet_opt *po = pkt_sk(sk);
+ struct packet_sock *po = pkt_sk(sk);
ifindex = po->ifindex;
proto = po->num;
@@ -786,7 +788,7 @@ out:
static int packet_release(struct socket *sock)
{
struct sock *sk = sock->sk;
- struct packet_opt *po;
+ struct packet_sock *po;
if (!sk)
return 0;
@@ -844,7 +846,7 @@ static int packet_release(struct socket *sock)
static int packet_do_bind(struct sock *sk, struct net_device *dev, int protocol)
{
- struct packet_opt *po = pkt_sk(sk);
+ struct packet_sock *po = pkt_sk(sk);
/*
* Detach an existing hook if present.
*/
@@ -961,7 +963,7 @@ out:
static int packet_create(struct socket *sock, int protocol)
{
struct sock *sk;
- struct packet_opt *po;
+ struct packet_sock *po;
int err;
if (!capable(CAP_NET_RAW))
@@ -976,7 +978,8 @@ static int packet_create(struct socket *sock, int protocol)
sock->state = SS_UNCONNECTED;
err = -ENOBUFS;
- sk = sk_alloc(PF_PACKET, GFP_KERNEL, 1, NULL);
+ sk = sk_alloc(PF_PACKET, GFP_KERNEL,
+ sizeof(struct packet_sock), NULL);
if (sk == NULL)
goto out;
@@ -988,10 +991,7 @@ static int packet_create(struct socket *sock, int protocol)
sock_init_data(sock,sk);
sk_set_owner(sk, THIS_MODULE);
- po = sk->sk_protinfo = kmalloc(sizeof(*po), GFP_KERNEL);
- if (!po)
- goto out_free;
- memset(po, 0, sizeof(*po));
+ po = pkt_sk(sk);
sk->sk_family = PF_PACKET;
po->num = protocol;
@@ -1021,9 +1021,6 @@ static int packet_create(struct socket *sock, int protocol)
sk_add_node(sk, &packet_sklist);
write_unlock_bh(&packet_sklist_lock);
return(0);
-
-out_free:
- sk_free(sk);
out:
return err;
}
@@ -1141,7 +1138,7 @@ static int packet_getname(struct socket *sock, struct sockaddr *uaddr,
{
struct net_device *dev;
struct sock *sk = sock->sk;
- struct packet_opt *po = pkt_sk(sk);
+ struct packet_sock *po = pkt_sk(sk);
struct sockaddr_ll *sll = (struct sockaddr_ll*)uaddr;
if (peer)
@@ -1195,7 +1192,7 @@ static void packet_dev_mclist(struct net_device *dev, struct packet_mclist *i, i
static int packet_mc_add(struct sock *sk, struct packet_mreq *mreq)
{
- struct packet_opt *po = pkt_sk(sk);
+ struct packet_sock *po = pkt_sk(sk);
struct packet_mclist *ml, *i;
struct net_device *dev;
int err;
@@ -1274,7 +1271,7 @@ static int packet_mc_drop(struct sock *sk, struct packet_mreq *mreq)
static void packet_flush_mclist(struct sock *sk)
{
- struct packet_opt *po = pkt_sk(sk);
+ struct packet_sock *po = pkt_sk(sk);
struct packet_mclist *ml;
if (!po->mclist)
@@ -1355,7 +1352,7 @@ static int packet_getsockopt(struct socket *sock, int level, int optname,
{
int len;
struct sock *sk = sock->sk;
- struct packet_opt *po = pkt_sk(sk);
+ struct packet_sock *po = pkt_sk(sk);
if (level != SOL_PACKET)
return -ENOPROTOOPT;
@@ -1401,7 +1398,7 @@ static int packet_notifier(struct notifier_block *this, unsigned long msg, void
read_lock(&packet_sklist_lock);
sk_for_each(sk, node, &packet_sklist) {
- struct packet_opt *po = pkt_sk(sk);
+ struct packet_sock *po = pkt_sk(sk);
switch (msg) {
case NETDEV_UNREGISTER:
@@ -1504,7 +1501,7 @@ static unsigned int packet_poll(struct file * file, struct socket *sock,
poll_table *wait)
{
struct sock *sk = sock->sk;
- struct packet_opt *po = pkt_sk(sk);
+ struct packet_sock *po = pkt_sk(sk);
unsigned int mask = datagram_poll(file, sock, wait);
spin_lock_bh(&sk->sk_receive_queue.lock);
@@ -1579,7 +1576,7 @@ static void free_pg_vec(char **pg_vec, unsigned order, unsigned len)
static int packet_set_ring(struct sock *sk, struct tpacket_req *req, int closing)
{
char **pg_vec = NULL;
- struct packet_opt *po = pkt_sk(sk);
+ struct packet_sock *po = pkt_sk(sk);
int was_running, num, order = 0;
int err = 0;
@@ -1709,7 +1706,7 @@ out:
static int packet_mmap(struct file *file, struct socket *sock, struct vm_area_struct *vma)
{
struct sock *sk = sock->sk;
- struct packet_opt *po = pkt_sk(sk);
+ struct packet_sock *po = pkt_sk(sk);
unsigned long size;
unsigned long start;
int err = -EINVAL;
@@ -1839,7 +1836,7 @@ static int packet_seq_show(struct seq_file *seq, void *v)
seq_puts(seq, "sk RefCnt Type Proto Iface R Rmem User Inode\n");
else {
struct sock *s = v;
- const struct packet_opt *po = pkt_sk(s);
+ const struct packet_sock *po = pkt_sk(s);
seq_printf(seq,
"%p %-6d %-4d %04x %-5d %1d %-6u %-6u %-6lu\n",
diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c
index e02d7eb6cbd04..68da687c9142a 100644
--- a/net/rose/af_rose.c
+++ b/net/rose/af_rose.c
@@ -128,24 +128,7 @@ int rosecmpm(rose_address *addr1, rose_address *addr2, unsigned short mask)
static struct sock *rose_alloc_sock(void)
{
- rose_cb *rose;
- struct sock *sk = sk_alloc(PF_ROSE, GFP_ATOMIC, 1, NULL);
-
- if (!sk)
- goto out;
-
- rose = sk->sk_protinfo = kmalloc(sizeof(*rose), GFP_ATOMIC);
- if (!rose)
- goto frees;
-
- memset(rose, 0x00, sizeof(*rose));
- rose->sk = sk;
-out:
- return sk;
-frees:
- sk_free(sk);
- sk = NULL;
- goto out;
+ return sk_alloc(PF_ROSE, GFP_ATOMIC, sizeof(struct rose_sock), NULL);
}
/*
@@ -169,7 +152,7 @@ void rose_kill_by_neigh(struct rose_neigh *neigh)
spin_lock_bh(&rose_list_lock);
sk_for_each(s, node, &rose_list) {
- rose_cb *rose = rose_sk(s);
+ struct rose_sock *rose = rose_sk(s);
if (rose->neighbour == neigh) {
rose_disconnect(s, ENETUNREACH, ROSE_OUT_OF_ORDER, 0);
@@ -190,7 +173,7 @@ static void rose_kill_by_device(struct net_device *dev)
spin_lock_bh(&rose_list_lock);
sk_for_each(s, node, &rose_list) {
- rose_cb *rose = rose_sk(s);
+ struct rose_sock *rose = rose_sk(s);
if (rose->device == dev) {
rose_disconnect(s, ENETUNREACH, ROSE_OUT_OF_ORDER, 0);
@@ -247,7 +230,7 @@ static struct sock *rose_find_listener(rose_address *addr, ax25_address *call)
spin_lock_bh(&rose_list_lock);
sk_for_each(s, node, &rose_list) {
- rose_cb *rose = rose_sk(s);
+ struct rose_sock *rose = rose_sk(s);
if (!rosecmp(&rose->source_addr, addr) &&
!ax25cmp(&rose->source_call, call) &&
@@ -256,7 +239,7 @@ static struct sock *rose_find_listener(rose_address *addr, ax25_address *call)
}
sk_for_each(s, node, &rose_list) {
- rose_cb *rose = rose_sk(s);
+ struct rose_sock *rose = rose_sk(s);
if (!rosecmp(&rose->source_addr, addr) &&
!ax25cmp(&rose->source_call, &null_ax25_address) &&
@@ -279,7 +262,7 @@ struct sock *rose_find_socket(unsigned int lci, struct rose_neigh *neigh)
spin_lock_bh(&rose_list_lock);
sk_for_each(s, node, &rose_list) {
- rose_cb *rose = rose_sk(s);
+ struct rose_sock *rose = rose_sk(s);
if (rose->lci == lci && rose->neighbour == neigh)
goto found;
@@ -372,7 +355,7 @@ static int rose_setsockopt(struct socket *sock, int level, int optname,
char __user *optval, int optlen)
{
struct sock *sk = sock->sk;
- rose_cb *rose = rose_sk(sk);
+ struct rose_sock *rose = rose_sk(sk);
int opt;
if (level != SOL_ROSE)
@@ -432,7 +415,7 @@ static int rose_getsockopt(struct socket *sock, int level, int optname,
char __user *optval, int __user *optlen)
{
struct sock *sk = sock->sk;
- rose_cb *rose = rose_sk(sk);
+ struct rose_sock *rose = rose_sk(sk);
int val = 0;
int len;
@@ -491,7 +474,7 @@ static int rose_listen(struct socket *sock, int backlog)
struct sock *sk = sock->sk;
if (sk->sk_state != TCP_LISTEN) {
- rose_cb *rose = rose_sk(sk);
+ struct rose_sock *rose = rose_sk(sk);
rose->dest_ndigis = 0;
memset(&rose->dest_addr, 0, ROSE_ADDR_LEN);
@@ -508,7 +491,7 @@ static int rose_listen(struct socket *sock, int backlog)
static int rose_create(struct socket *sock, int protocol)
{
struct sock *sk;
- rose_cb *rose;
+ struct rose_sock *rose;
if (sock->type != SOCK_SEQPACKET || protocol != 0)
return -ESOCKTNOSUPPORT;
@@ -547,7 +530,7 @@ static int rose_create(struct socket *sock, int protocol)
static struct sock *rose_make_new(struct sock *osk)
{
struct sock *sk;
- rose_cb *rose, *orose;
+ struct rose_sock *rose, *orose;
if (osk->sk_type != SOCK_SEQPACKET)
return NULL;
@@ -572,10 +555,14 @@ static struct sock *rose_make_new(struct sock *osk)
sk->sk_protocol = osk->sk_protocol;
sk->sk_rcvbuf = osk->sk_rcvbuf;
sk->sk_sndbuf = osk->sk_sndbuf;
- sk->sk_debug = osk->sk_debug;
sk->sk_state = TCP_ESTABLISHED;
sk->sk_sleep = osk->sk_sleep;
- sk->sk_zapped = osk->sk_zapped;
+
+ if (sock_flag(osk, SOCK_ZAPPED))
+ sock_set_flag(sk, SOCK_ZAPPED);
+
+ if (sock_flag(osk, SOCK_DBG))
+ sock_set_flag(sk, SOCK_DBG);
init_timer(&rose->timer);
init_timer(&rose->idletimer);
@@ -596,7 +583,7 @@ static struct sock *rose_make_new(struct sock *osk)
static int rose_release(struct socket *sock)
{
struct sock *sk = sock->sk;
- rose_cb *rose;
+ struct rose_sock *rose;
if (sk == NULL) return 0;
@@ -642,13 +629,13 @@ static int rose_release(struct socket *sock)
static int rose_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
{
struct sock *sk = sock->sk;
- rose_cb *rose = rose_sk(sk);
+ struct rose_sock *rose = rose_sk(sk);
struct sockaddr_rose *addr = (struct sockaddr_rose *)uaddr;
struct net_device *dev;
ax25_address *user, *source;
int n;
- if (!sk->sk_zapped)
+ if (!sock_flag(sk, SOCK_ZAPPED))
return -EINVAL;
if (addr_len != sizeof(struct sockaddr_rose) && addr_len != sizeof(struct full_sockaddr_rose))
@@ -693,7 +680,7 @@ static int rose_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
rose_insert_socket(sk);
- sk->sk_zapped = 0;
+ sock_reset_flag(sk, SOCK_ZAPPED);
SOCK_DEBUG(sk, "ROSE: socket is bound\n");
return 0;
}
@@ -701,7 +688,7 @@ static int rose_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
static int rose_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len, int flags)
{
struct sock *sk = sock->sk;
- rose_cb *rose = rose_sk(sk);
+ struct rose_sock *rose = rose_sk(sk);
struct sockaddr_rose *addr = (struct sockaddr_rose *)uaddr;
unsigned char cause, diagnostic;
ax25_address *user;
@@ -749,8 +736,8 @@ static int rose_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le
if (!rose->lci)
return -ENETUNREACH;
- if (sk->sk_zapped) { /* Must bind first - autobinding in this may or may not work */
- sk->sk_zapped = 0;
+ if (sock_flag(sk, SOCK_ZAPPED)) { /* Must bind first - autobinding in this may or may not work */
+ sock_reset_flag(sk, SOCK_ZAPPED);
if ((dev = rose_dev_first()) == NULL)
return -ENETUNREACH;
@@ -902,7 +889,7 @@ static int rose_getname(struct socket *sock, struct sockaddr *uaddr,
{
struct full_sockaddr_rose *srose = (struct full_sockaddr_rose *)uaddr;
struct sock *sk = sock->sk;
- rose_cb *rose = rose_sk(sk);
+ struct rose_sock *rose = rose_sk(sk);
int n;
if (peer != 0) {
@@ -931,7 +918,7 @@ int rose_rx_call_request(struct sk_buff *skb, struct net_device *dev, struct ros
{
struct sock *sk;
struct sock *make;
- rose_cb *make_rose;
+ struct rose_sock *make_rose;
struct rose_facilities_struct facilities;
int n, len;
@@ -954,7 +941,7 @@ int rose_rx_call_request(struct sk_buff *skb, struct net_device *dev, struct ros
/*
* We can't accept the Call Request.
*/
- if (!sk || sk->sk_ack_backlog == sk->sk_max_ack_backlog ||
+ if (sk == NULL || sk_acceptq_is_full(sk) ||
(make = rose_make_new(sk)) == NULL) {
rose_transmit_clear_request(neigh, lci, ROSE_NETWORK_CONGESTION, 120);
return 0;
@@ -1012,7 +999,7 @@ static int rose_sendmsg(struct kiocb *iocb, struct socket *sock,
struct msghdr *msg, size_t len)
{
struct sock *sk = sock->sk;
- rose_cb *rose = rose_sk(sk);
+ struct rose_sock *rose = rose_sk(sk);
struct sockaddr_rose *usrose = (struct sockaddr_rose *)msg->msg_name;
int err;
struct full_sockaddr_rose srose;
@@ -1023,7 +1010,7 @@ static int rose_sendmsg(struct kiocb *iocb, struct socket *sock,
if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_EOR|MSG_CMSG_COMPAT))
return -EINVAL;
- if (sk->sk_zapped)
+ if (sock_flag(sk, SOCK_ZAPPED))
return -EADDRNOTAVAIL;
if (sk->sk_shutdown & SEND_SHUTDOWN) {
@@ -1182,7 +1169,7 @@ static int rose_recvmsg(struct kiocb *iocb, struct socket *sock,
struct msghdr *msg, size_t size, int flags)
{
struct sock *sk = sock->sk;
- rose_cb *rose = rose_sk(sk);
+ struct rose_sock *rose = rose_sk(sk);
struct sockaddr_rose *srose = (struct sockaddr_rose *)msg->msg_name;
size_t copied;
unsigned char *asmptr;
@@ -1247,7 +1234,7 @@ static int rose_recvmsg(struct kiocb *iocb, struct socket *sock,
static int rose_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
{
struct sock *sk = sock->sk;
- rose_cb *rose = rose_sk(sk);
+ struct rose_sock *rose = rose_sk(sk);
void __user *argp = (void __user *)arg;
switch (cmd) {
@@ -1382,7 +1369,7 @@ static int rose_info_show(struct seq_file *seq, void *v)
else {
struct sock *s = v;
- rose_cb *rose = rose_sk(s);
+ struct rose_sock *rose = rose_sk(s);
const char *devname, *callsign;
const struct net_device *dev = rose->device;
diff --git a/net/rose/rose_in.c b/net/rose/rose_in.c
index c6aa8fba6a38b..ef475a1bb1ba6 100644
--- a/net/rose/rose_in.c
+++ b/net/rose/rose_in.c
@@ -41,7 +41,7 @@
*/
static int rose_state1_machine(struct sock *sk, struct sk_buff *skb, int frametype)
{
- rose_cb *rose = rose_sk(sk);
+ struct rose_sock *rose = rose_sk(sk);
switch (frametype) {
case ROSE_CALL_ACCEPTED:
@@ -78,7 +78,7 @@ static int rose_state1_machine(struct sock *sk, struct sk_buff *skb, int framety
*/
static int rose_state2_machine(struct sock *sk, struct sk_buff *skb, int frametype)
{
- rose_cb *rose = rose_sk(sk);
+ struct rose_sock *rose = rose_sk(sk);
switch (frametype) {
case ROSE_CLEAR_REQUEST:
@@ -106,7 +106,7 @@ static int rose_state2_machine(struct sock *sk, struct sk_buff *skb, int framety
*/
static int rose_state3_machine(struct sock *sk, struct sk_buff *skb, int frametype, int ns, int nr, int q, int d, int m)
{
- rose_cb *rose = rose_sk(sk);
+ struct rose_sock *rose = rose_sk(sk);
int queued = 0;
switch (frametype) {
@@ -216,7 +216,7 @@ static int rose_state3_machine(struct sock *sk, struct sk_buff *skb, int framety
*/
static int rose_state4_machine(struct sock *sk, struct sk_buff *skb, int frametype)
{
- rose_cb *rose = rose_sk(sk);
+ struct rose_sock *rose = rose_sk(sk);
switch (frametype) {
case ROSE_RESET_REQUEST:
@@ -265,7 +265,7 @@ static int rose_state5_machine(struct sock *sk, struct sk_buff *skb, int framety
/* Higher level upcall for a LAPB frame */
int rose_process_rx_frame(struct sock *sk, struct sk_buff *skb)
{
- rose_cb *rose = rose_sk(sk);
+ struct rose_sock *rose = rose_sk(sk);
int queued = 0, frametype, ns, nr, q, d, m;
if (rose->state == ROSE_STATE_0)
diff --git a/net/rose/rose_out.c b/net/rose/rose_out.c
index 5e5d4c4b459cd..2965ffc83b9b7 100644
--- a/net/rose/rose_out.c
+++ b/net/rose/rose_out.c
@@ -33,7 +33,7 @@
*/
static void rose_send_iframe(struct sock *sk, struct sk_buff *skb)
{
- rose_cb *rose = rose_sk(sk);
+ struct rose_sock *rose = rose_sk(sk);
if (skb == NULL)
return;
@@ -48,7 +48,7 @@ static void rose_send_iframe(struct sock *sk, struct sk_buff *skb)
void rose_kick(struct sock *sk)
{
- rose_cb *rose = rose_sk(sk);
+ struct rose_sock *rose = rose_sk(sk);
struct sk_buff *skb, *skbn;
unsigned short start, end;
@@ -112,7 +112,7 @@ void rose_kick(struct sock *sk)
void rose_enquiry_response(struct sock *sk)
{
- rose_cb *rose = rose_sk(sk);
+ struct rose_sock *rose = rose_sk(sk);
if (rose->condition & ROSE_COND_OWN_RX_BUSY)
rose_write_internal(sk, ROSE_RNR);
diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c
index 92674a1cc49ea..ff73ebb912b8e 100644
--- a/net/rose/rose_route.c
+++ b/net/rose/rose_route.c
@@ -727,7 +727,8 @@ int rose_rt_ioctl(unsigned int cmd, void __user *arg)
}
if (rose_route.mask > 10) /* Mask can't be more than 10 digits */
return -EINVAL;
-
+ if (rose_route.ndigis > 8) /* No more than 8 digipeats */
+ return -EINVAL;
err = rose_add_node(&rose_route, dev);
dev_put(dev);
return err;
@@ -898,7 +899,8 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25)
*/
if ((sk = rose_find_socket(lci, rose_neigh)) != NULL) {
if (frametype == ROSE_CALL_REQUEST) {
- rose_cb *rose = rose_sk(sk);
+ struct rose_sock *rose = rose_sk(sk);
+
/* Remove an existing unused socket */
rose_clear_queues(sk);
rose->cause = ROSE_NETWORK_CONGESTION;
diff --git a/net/rose/rose_subr.c b/net/rose/rose_subr.c
index e2cd9d8c9b5b8..7db7e1cedc3ae 100644
--- a/net/rose/rose_subr.c
+++ b/net/rose/rose_subr.c
@@ -28,7 +28,7 @@
#include <linux/interrupt.h>
#include <net/rose.h>
-static int rose_create_facilities(unsigned char *buffer, rose_cb *rose);
+static int rose_create_facilities(unsigned char *buffer, struct rose_sock *rose);
/*
* This routine purges all of the queues of frames.
@@ -47,7 +47,7 @@ void rose_clear_queues(struct sock *sk)
void rose_frames_acked(struct sock *sk, unsigned short nr)
{
struct sk_buff *skb;
- rose_cb *rose = rose_sk(sk);
+ struct rose_sock *rose = rose_sk(sk);
/*
* Remove all the ack-ed frames from the ack queue.
@@ -85,7 +85,7 @@ void rose_requeue_frames(struct sock *sk)
*/
int rose_validate_nr(struct sock *sk, unsigned short nr)
{
- rose_cb *rose = rose_sk(sk);
+ struct rose_sock *rose = rose_sk(sk);
unsigned short vc = rose->va;
while (vc != rose->vs) {
@@ -102,7 +102,7 @@ int rose_validate_nr(struct sock *sk, unsigned short nr)
*/
void rose_write_internal(struct sock *sk, int frametype)
{
- rose_cb *rose = rose_sk(sk);
+ struct rose_sock *rose = rose_sk(sk);
struct sk_buff *skb;
unsigned char *dptr;
unsigned char lci1, lci2;
@@ -396,7 +396,7 @@ int rose_parse_facilities(unsigned char *p,
return 1;
}
-static int rose_create_facilities(unsigned char *buffer, rose_cb *rose)
+static int rose_create_facilities(unsigned char *buffer, struct rose_sock *rose)
{
unsigned char *p = buffer + 1;
char *callsign;
@@ -492,7 +492,7 @@ static int rose_create_facilities(unsigned char *buffer, rose_cb *rose)
void rose_disconnect(struct sock *sk, int reason, int cause, int diagnostic)
{
- rose_cb *rose = rose_sk(sk);
+ struct rose_sock *rose = rose_sk(sk);
rose_stop_timer(sk);
rose_stop_idletimer(sk);
diff --git a/net/rose/rose_timer.c b/net/rose/rose_timer.c
index 638bb1f585609..84dd4403f792d 100644
--- a/net/rose/rose_timer.c
+++ b/net/rose/rose_timer.c
@@ -46,7 +46,7 @@ void rose_start_heartbeat(struct sock *sk)
void rose_start_t1timer(struct sock *sk)
{
- rose_cb *rose = rose_sk(sk);
+ struct rose_sock *rose = rose_sk(sk);
del_timer(&rose->timer);
@@ -59,7 +59,7 @@ void rose_start_t1timer(struct sock *sk)
void rose_start_t2timer(struct sock *sk)
{
- rose_cb *rose = rose_sk(sk);
+ struct rose_sock *rose = rose_sk(sk);
del_timer(&rose->timer);
@@ -72,7 +72,7 @@ void rose_start_t2timer(struct sock *sk)
void rose_start_t3timer(struct sock *sk)
{
- rose_cb *rose = rose_sk(sk);
+ struct rose_sock *rose = rose_sk(sk);
del_timer(&rose->timer);
@@ -85,7 +85,7 @@ void rose_start_t3timer(struct sock *sk)
void rose_start_hbtimer(struct sock *sk)
{
- rose_cb *rose = rose_sk(sk);
+ struct rose_sock *rose = rose_sk(sk);
del_timer(&rose->timer);
@@ -98,7 +98,7 @@ void rose_start_hbtimer(struct sock *sk)
void rose_start_idletimer(struct sock *sk)
{
- rose_cb *rose = rose_sk(sk);
+ struct rose_sock *rose = rose_sk(sk);
del_timer(&rose->idletimer);
@@ -129,7 +129,7 @@ void rose_stop_idletimer(struct sock *sk)
static void rose_heartbeat_expiry(unsigned long param)
{
struct sock *sk = (struct sock *)param;
- rose_cb *rose = rose_sk(sk);
+ struct rose_sock *rose = rose_sk(sk);
bh_lock_sock(sk);
switch (rose->state) {
@@ -166,7 +166,7 @@ static void rose_heartbeat_expiry(unsigned long param)
static void rose_timer_expiry(unsigned long param)
{
struct sock *sk = (struct sock *)param;
- rose_cb *rose = rose_sk(sk);
+ struct rose_sock *rose = rose_sk(sk);
bh_lock_sock(sk);
switch (rose->state) {
diff --git a/net/rxrpc/krxiod.c b/net/rxrpc/krxiod.c
index c987395e57838..2b537f425a17d 100644
--- a/net/rxrpc/krxiod.c
+++ b/net/rxrpc/krxiod.c
@@ -138,6 +138,8 @@ static int rxrpc_krxiod(void *arg)
_debug("### End Work");
+ try_to_freeze(PF_FREEZE);
+
/* discard pending signals */
rxrpc_discard_my_signals();
diff --git a/net/rxrpc/krxsecd.c b/net/rxrpc/krxsecd.c
index 117aa91537a1b..6020c89d92288 100644
--- a/net/rxrpc/krxsecd.c
+++ b/net/rxrpc/krxsecd.c
@@ -107,6 +107,8 @@ static int rxrpc_krxsecd(void *arg)
_debug("### End Inbound Calls");
+ try_to_freeze(PF_FREEZE);
+
/* discard pending signals */
rxrpc_discard_my_signals();
diff --git a/net/rxrpc/krxtimod.c b/net/rxrpc/krxtimod.c
index 0d9e9d2f8eed6..249c2b0290bbf 100644
--- a/net/rxrpc/krxtimod.c
+++ b/net/rxrpc/krxtimod.c
@@ -90,6 +90,8 @@ static int krxtimod(void *arg)
complete_and_exit(&krxtimod_dead, 0);
}
+ try_to_freeze(PF_FREEZE);
+
/* discard pending signals */
rxrpc_discard_my_signals();
diff --git a/net/rxrpc/main.c b/net/rxrpc/main.c
index 966667ff67226..36fdcbcd80d1f 100644
--- a/net/rxrpc/main.c
+++ b/net/rxrpc/main.c
@@ -22,12 +22,6 @@
#include <rxrpc/message.h>
#include "internal.h"
-static int rxrpc_initialise(void);
-static void rxrpc_cleanup(void);
-
-module_init(rxrpc_initialise);
-module_exit(rxrpc_cleanup);
-
MODULE_DESCRIPTION("Rx RPC implementation");
MODULE_AUTHOR("Red Hat, Inc.");
MODULE_LICENSE("GPL");
@@ -38,7 +32,7 @@ __be32 rxrpc_epoch;
/*
* initialise the Rx module
*/
-static int rxrpc_initialise(void)
+static int __init rxrpc_initialise(void)
{
int ret;
@@ -93,6 +87,8 @@ static int rxrpc_initialise(void)
return ret;
} /* end rxrpc_initialise() */
+module_init(rxrpc_initialise);
+
/*****************************************************************************/
/*
* clean up the Rx module
@@ -136,6 +132,8 @@ static void __exit rxrpc_cleanup(void)
kleave("");
} /* end rxrpc_cleanup() */
+module_exit(rxrpc_cleanup);
+
/*****************************************************************************/
/*
* clear the dead space between task_struct and kernel stack
diff --git a/net/sched/Kconfig b/net/sched/Kconfig
index b0fb5d7f42b79..3d1d902dd1a1a 100644
--- a/net/sched/Kconfig
+++ b/net/sched/Kconfig
@@ -269,6 +269,16 @@ config NET_CLS
Documentation and software is at
<http://diffserv.sourceforge.net/>.
+config NET_CLS_BASIC
+ tristate "Basic classifier"
+ depends on NET_CLS
+ ---help---
+ Say Y here if you want to be able to classify packets using
+ only extended matches and actions.
+
+ To compile this code as a module, choose M here: the
+ module will be called cls_basic.
+
config NET_CLS_TCINDEX
tristate "TC index classifier"
depends on NET_CLS
@@ -375,6 +385,70 @@ config NET_CLS_RSVP6
To compile this code as a module, choose M here: the
module will be called cls_rsvp6.
+config NET_EMATCH
+ bool "Extended Matches"
+ depends on NET_CLS
+ ---help---
+ Say Y here if you want to use extended matches on top of classifiers
+ and select the extended matches below.
+
+ Extended matches are small classification helpers not worth writing
+ a separate classifier.
+
+ You must have a recent version of the iproute2 tools in order to use
+ extended matches.
+
+config NET_EMATCH_STACK
+ int "Stack size"
+ depends on NET_EMATCH
+ default "32"
+ ---help---
+ Size of the local stack variable used while evaluating the tree of
+ ematches. Limits the depth of the tree, i.e. the number of
+ encapsulated precedences. Every level requires 4 bytes of addtional
+ stack space.
+
+config NET_EMATCH_CMP
+ tristate "Simple packet data comparison"
+ depends on NET_EMATCH
+ ---help---
+ Say Y here if you want to be able to classify packets based on
+ simple packet data comparisons for 8, 16, and 32bit values.
+
+ To compile this code as a module, choose M here: the
+ module will be called em_cmp.
+
+config NET_EMATCH_NBYTE
+ tristate "Multi byte comparison"
+ depends on NET_EMATCH
+ ---help---
+ Say Y here if you want to be able to classify packets based on
+ multiple byte comparisons mainly useful for IPv6 address comparisons.
+
+ To compile this code as a module, choose M here: the
+ module will be called em_nbyte.
+
+config NET_EMATCH_U32
+ tristate "U32 hashing key"
+ depends on NET_EMATCH
+ ---help---
+ Say Y here if you want to be able to classify packets using
+ the famous u32 key in combination with logic relations.
+
+ To compile this code as a module, choose M here: the
+ module will be called em_u32.
+
+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
+ metadata such as load average, netfilter attributes, socket
+ attributes and routing decisions.
+
+ To compile this code as a module, choose M here: the
+ module will be called em_meta.
+
config NET_CLS_ACT
bool "Packet ACTION"
depends on EXPERIMENTAL && NET_CLS && NET_QOS
diff --git a/net/sched/Makefile b/net/sched/Makefile
index 0bd324914cfe2..431e55786efd1 100644
--- a/net/sched/Makefile
+++ b/net/sched/Makefile
@@ -33,3 +33,9 @@ obj-$(CONFIG_NET_CLS_FW) += cls_fw.o
obj-$(CONFIG_NET_CLS_RSVP) += cls_rsvp.o
obj-$(CONFIG_NET_CLS_TCINDEX) += cls_tcindex.o
obj-$(CONFIG_NET_CLS_RSVP6) += cls_rsvp6.o
+obj-$(CONFIG_NET_CLS_BASIC) += cls_basic.o
+obj-$(CONFIG_NET_EMATCH) += ematch.o
+obj-$(CONFIG_NET_EMATCH_CMP) += em_cmp.o
+obj-$(CONFIG_NET_EMATCH_NBYTE) += em_nbyte.o
+obj-$(CONFIG_NET_EMATCH_U32) += em_u32.o
+obj-$(CONFIG_NET_EMATCH_META) += em_meta.o
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index eebef4e16a2f9..88962fa33199f 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -228,7 +228,7 @@ tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
return err;
RTA_PUT(skb, TCA_KIND, IFNAMSIZ, a->ops->kind);
- if (tcf_action_copy_stats(skb, a))
+ if (tcf_action_copy_stats(skb, a, 0))
goto rtattr_failure;
r = (struct rtattr*) skb->tail;
RTA_PUT(skb, TCA_OPTIONS, 0, NULL);
@@ -380,19 +380,24 @@ err:
return NULL;
}
-int tcf_action_copy_stats(struct sk_buff *skb, struct tc_action *a)
+int tcf_action_copy_stats(struct sk_buff *skb, struct tc_action *a,
+ int compat_mode)
{
- int err;
+ int err = 0;
struct gnet_dump d;
struct tcf_act_hdr *h = a->priv;
if (h == NULL)
goto errout;
- if (a->type == TCA_OLD_COMPAT)
- err = gnet_stats_start_copy_compat(skb, TCA_ACT_STATS,
- TCA_STATS, TCA_XSTATS, h->stats_lock, &d);
- else
+ /* compat_mode being true specifies a call that is supposed
+ * to add additional backward compatiblity statistic TLVs.
+ */
+ if (compat_mode) {
+ if (a->type == TCA_OLD_COMPAT)
+ err = gnet_stats_start_copy_compat(skb, 0,
+ TCA_STATS, TCA_XSTATS, h->stats_lock, &d);
+ } else
err = gnet_stats_start_copy(skb, TCA_ACT_STATS,
h->stats_lock, &d);
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index fe85d5588b46e..56e66c3fe0fa0 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -602,7 +602,7 @@ tcf_exts_dump_stats(struct sk_buff *skb, struct tcf_exts *exts,
{
#ifdef CONFIG_NET_CLS_ACT
if (exts->action)
- if (tcf_action_copy_stats(skb, exts->action) < 0)
+ if (tcf_action_copy_stats(skb, exts->action, 1) < 0)
goto rtattr_failure;
#elif defined CONFIG_NET_CLS_POLICE
if (exts->police)
diff --git a/net/sched/cls_basic.c b/net/sched/cls_basic.c
new file mode 100644
index 0000000000000..0d2d4415f3348
--- /dev/null
+++ b/net/sched/cls_basic.c
@@ -0,0 +1,303 @@
+/*
+ * net/sched/cls_basic.c Basic Packet Classifier.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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: Thomas Graf <tgraf@suug.ch>
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/errno.h>
+#include <linux/rtnetlink.h>
+#include <linux/skbuff.h>
+#include <net/act_api.h>
+#include <net/pkt_cls.h>
+
+struct basic_head
+{
+ u32 hgenerator;
+ struct list_head flist;
+};
+
+struct basic_filter
+{
+ u32 handle;
+ struct tcf_exts exts;
+ struct tcf_ematch_tree ematches;
+ struct tcf_result res;
+ struct list_head link;
+};
+
+static struct tcf_ext_map basic_ext_map = {
+ .action = TCA_BASIC_ACT,
+ .police = TCA_BASIC_POLICE
+};
+
+static int basic_classify(struct sk_buff *skb, struct tcf_proto *tp,
+ struct tcf_result *res)
+{
+ int r;
+ struct basic_head *head = (struct basic_head *) tp->root;
+ struct basic_filter *f;
+
+ list_for_each_entry(f, &head->flist, link) {
+ if (!tcf_em_tree_match(skb, &f->ematches, NULL))
+ continue;
+ *res = f->res;
+ r = tcf_exts_exec(skb, &f->exts, res);
+ if (r < 0)
+ continue;
+ return r;
+ }
+ return -1;
+}
+
+static unsigned long basic_get(struct tcf_proto *tp, u32 handle)
+{
+ unsigned long l = 0UL;
+ struct basic_head *head = (struct basic_head *) tp->root;
+ struct basic_filter *f;
+
+ if (head == NULL)
+ return 0UL;
+
+ list_for_each_entry(f, &head->flist, link)
+ if (f->handle == handle)
+ l = (unsigned long) f;
+
+ return l;
+}
+
+static void basic_put(struct tcf_proto *tp, unsigned long f)
+{
+}
+
+static int basic_init(struct tcf_proto *tp)
+{
+ return 0;
+}
+
+static inline void basic_delete_filter(struct tcf_proto *tp,
+ struct basic_filter *f)
+{
+ tcf_unbind_filter(tp, &f->res);
+ tcf_exts_destroy(tp, &f->exts);
+ tcf_em_tree_destroy(tp, &f->ematches);
+ kfree(f);
+}
+
+static void basic_destroy(struct tcf_proto *tp)
+{
+ struct basic_head *head = (struct basic_head *) xchg(&tp->root, NULL);
+ struct basic_filter *f, *n;
+
+ list_for_each_entry_safe(f, n, &head->flist, link) {
+ list_del(&f->link);
+ basic_delete_filter(tp, f);
+ }
+}
+
+static int basic_delete(struct tcf_proto *tp, unsigned long arg)
+{
+ struct basic_head *head = (struct basic_head *) tp->root;
+ struct basic_filter *t, *f = (struct basic_filter *) arg;
+
+ list_for_each_entry(t, &head->flist, link)
+ if (t == f) {
+ tcf_tree_lock(tp);
+ list_del(&t->link);
+ tcf_tree_unlock(tp);
+ basic_delete_filter(tp, t);
+ return 0;
+ }
+
+ return -ENOENT;
+}
+
+static inline int basic_set_parms(struct tcf_proto *tp, struct basic_filter *f,
+ unsigned long base, struct rtattr **tb,
+ struct rtattr *est)
+{
+ int err = -EINVAL;
+ struct tcf_exts e;
+ struct tcf_ematch_tree t;
+
+ if (tb[TCA_BASIC_CLASSID-1])
+ if (RTA_PAYLOAD(tb[TCA_BASIC_CLASSID-1]) < sizeof(u32))
+ return err;
+
+ err = tcf_exts_validate(tp, tb, est, &e, &basic_ext_map);
+ if (err < 0)
+ return err;
+
+ err = tcf_em_tree_validate(tp, tb[TCA_BASIC_EMATCHES-1], &t);
+ if (err < 0)
+ goto errout;
+
+ if (tb[TCA_BASIC_CLASSID-1]) {
+ f->res.classid = *(u32*)RTA_DATA(tb[TCA_BASIC_CLASSID-1]);
+ tcf_bind_filter(tp, &f->res, base);
+ }
+
+ tcf_exts_change(tp, &f->exts, &e);
+ tcf_em_tree_change(tp, &f->ematches, &t);
+
+ return 0;
+errout:
+ tcf_exts_destroy(tp, &e);
+ return err;
+}
+
+static int basic_change(struct tcf_proto *tp, unsigned long base, u32 handle,
+ struct rtattr **tca, unsigned long *arg)
+{
+ int err = -EINVAL;
+ struct basic_head *head = (struct basic_head *) tp->root;
+ struct rtattr *tb[TCA_BASIC_MAX];
+ struct basic_filter *f = (struct basic_filter *) *arg;
+
+ if (tca[TCA_OPTIONS-1] == NULL)
+ return -EINVAL;
+
+ if (rtattr_parse_nested(tb, TCA_BASIC_MAX, tca[TCA_OPTIONS-1]) < 0)
+ return -EINVAL;
+
+ if (f != NULL) {
+ if (handle && f->handle != handle)
+ return -EINVAL;
+ return basic_set_parms(tp, f, base, tb, tca[TCA_RATE-1]);
+ }
+
+ err = -ENOBUFS;
+ if (head == NULL) {
+ head = kmalloc(sizeof(*head), GFP_KERNEL);
+ if (head == NULL)
+ goto errout;
+
+ memset(head, 0, sizeof(*head));
+ INIT_LIST_HEAD(&head->flist);
+ tp->root = head;
+ }
+
+ f = kmalloc(sizeof(*f), GFP_KERNEL);
+ if (f == NULL)
+ goto errout;
+ memset(f, 0, sizeof(*f));
+
+ err = -EINVAL;
+ if (handle)
+ f->handle = handle;
+ else {
+ int i = 0x80000000;
+ do {
+ if (++head->hgenerator == 0x7FFFFFFF)
+ head->hgenerator = 1;
+ } while (--i > 0 && basic_get(tp, head->hgenerator));
+
+ if (i <= 0) {
+ printk(KERN_ERR "Insufficient number of handles\n");
+ goto errout;
+ }
+
+ f->handle = head->hgenerator;
+ }
+
+ err = basic_set_parms(tp, f, base, tb, tca[TCA_RATE-1]);
+ if (err < 0)
+ goto errout;
+
+ tcf_tree_lock(tp);
+ list_add(&f->link, &head->flist);
+ tcf_tree_unlock(tp);
+ *arg = (unsigned long) f;
+
+ return 0;
+errout:
+ if (*arg == 0UL && f)
+ kfree(f);
+
+ return err;
+}
+
+static void basic_walk(struct tcf_proto *tp, struct tcf_walker *arg)
+{
+ struct basic_head *head = (struct basic_head *) tp->root;
+ struct basic_filter *f;
+
+ list_for_each_entry(f, &head->flist, link) {
+ if (arg->count < arg->skip)
+ goto skip;
+
+ if (arg->fn(tp, (unsigned long) f, arg) < 0) {
+ arg->stop = 1;
+ break;
+ }
+skip:
+ arg->count++;
+ }
+}
+
+static int basic_dump(struct tcf_proto *tp, unsigned long fh,
+ struct sk_buff *skb, struct tcmsg *t)
+{
+ struct basic_filter *f = (struct basic_filter *) fh;
+ unsigned char *b = skb->tail;
+ struct rtattr *rta;
+
+ if (f == NULL)
+ return skb->len;
+
+ t->tcm_handle = f->handle;
+
+ rta = (struct rtattr *) b;
+ RTA_PUT(skb, TCA_OPTIONS, 0, NULL);
+
+ if (tcf_exts_dump(skb, &f->exts, &basic_ext_map) < 0 ||
+ tcf_em_tree_dump(skb, &f->ematches, TCA_BASIC_EMATCHES) < 0)
+ goto rtattr_failure;
+
+ rta->rta_len = (skb->tail - b);
+ return skb->len;
+
+rtattr_failure:
+ skb_trim(skb, b - skb->data);
+ return -1;
+}
+
+static struct tcf_proto_ops cls_basic_ops = {
+ .kind = "basic",
+ .classify = basic_classify,
+ .init = basic_init,
+ .destroy = basic_destroy,
+ .get = basic_get,
+ .put = basic_put,
+ .change = basic_change,
+ .delete = basic_delete,
+ .walk = basic_walk,
+ .dump = basic_dump,
+ .owner = THIS_MODULE,
+};
+
+static int __init init_basic(void)
+{
+ return register_tcf_proto_ops(&cls_basic_ops);
+}
+
+static void __exit exit_basic(void)
+{
+ unregister_tcf_proto_ops(&cls_basic_ops);
+}
+
+module_init(init_basic)
+module_exit(exit_basic)
+MODULE_LICENSE("GPL");
+
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index 821d3b9c5c55b..364b87d86455d 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -58,14 +58,6 @@
#include <net/act_api.h>
#include <net/pkt_cls.h>
-
-struct tc_u32_mark
-{
- u32 val;
- u32 mask;
- u32 success;
-};
-
struct tc_u_knode
{
struct tc_u_knode *next;
diff --git a/net/sched/em_cmp.c b/net/sched/em_cmp.c
new file mode 100644
index 0000000000000..bf1f00f8b1bf7
--- /dev/null
+++ b/net/sched/em_cmp.c
@@ -0,0 +1,101 @@
+/*
+ * net/sched/em_cmp.c Simple packet data comparison ematch
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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: Thomas Graf <tgraf@suug.ch>
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/skbuff.h>
+#include <linux/tc_ematch/tc_em_cmp.h>
+#include <net/pkt_cls.h>
+
+static inline int cmp_needs_transformation(struct tcf_em_cmp *cmp)
+{
+ return unlikely(cmp->flags & TCF_EM_CMP_TRANS);
+}
+
+static int em_cmp_match(struct sk_buff *skb, struct tcf_ematch *em,
+ struct tcf_pkt_info *info)
+{
+ struct tcf_em_cmp *cmp = (struct tcf_em_cmp *) em->data;
+ unsigned char *ptr = tcf_get_base_ptr(skb, cmp->layer) + cmp->off;
+ u32 val = 0;
+
+ if (!tcf_valid_offset(skb, ptr, cmp->align))
+ return 0;
+
+ switch (cmp->align) {
+ case TCF_EM_ALIGN_U8:
+ val = *ptr;
+ break;
+
+ case TCF_EM_ALIGN_U16:
+ val = *ptr << 8;
+ val |= *(ptr+1);
+
+ if (cmp_needs_transformation(cmp))
+ val = be16_to_cpu(val);
+ break;
+
+ case TCF_EM_ALIGN_U32:
+ /* Worth checking boundries? The branching seems
+ * to get worse. Visit again. */
+ val = *ptr << 24;
+ val |= *(ptr+1) << 16;
+ val |= *(ptr+2) << 8;
+ val |= *(ptr+3);
+
+ if (cmp_needs_transformation(cmp))
+ val = be32_to_cpu(val);
+ break;
+
+ default:
+ return 0;
+ }
+
+ if (cmp->mask)
+ val &= cmp->mask;
+
+ switch (cmp->opnd) {
+ case TCF_EM_OPND_EQ:
+ return val == cmp->val;
+ case TCF_EM_OPND_LT:
+ return val < cmp->val;
+ case TCF_EM_OPND_GT:
+ return val > cmp->val;
+ }
+
+ return 0;
+}
+
+static struct tcf_ematch_ops em_cmp_ops = {
+ .kind = TCF_EM_CMP,
+ .datalen = sizeof(struct tcf_em_cmp),
+ .match = em_cmp_match,
+ .owner = THIS_MODULE,
+ .link = LIST_HEAD_INIT(em_cmp_ops.link)
+};
+
+static int __init init_em_cmp(void)
+{
+ return tcf_em_register(&em_cmp_ops);
+}
+
+static void __exit exit_em_cmp(void)
+{
+ tcf_em_unregister(&em_cmp_ops);
+}
+
+MODULE_LICENSE("GPL");
+
+module_init(init_em_cmp);
+module_exit(exit_em_cmp);
+
diff --git a/net/sched/em_meta.c b/net/sched/em_meta.c
new file mode 100644
index 0000000000000..f1eeaf65cee5f
--- /dev/null
+++ b/net/sched/em_meta.c
@@ -0,0 +1,661 @@
+/*
+ * net/sched/em_meta.c Metadata ematch
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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: Thomas Graf <tgraf@suug.ch>
+ *
+ * ==========================================================================
+ *
+ * The metadata ematch compares two meta objects where each object
+ * represents either a meta value stored in the kernel or a static
+ * value provided by userspace. The objects are not provided by
+ * userspace itself but rather a definition providing the information
+ * to build them. Every object is of a certain type which must be
+ * equal to the object it is being compared to.
+ *
+ * The definition of a objects conists of the type (meta type), a
+ * identifier (meta id) and additional type specific information.
+ * The meta id is either TCF_META_TYPE_VALUE for values provided by
+ * userspace or a index to the meta operations table consisting of
+ * function pointers to type specific meta data collectors returning
+ * the value of the requested meta value.
+ *
+ * lvalue rvalue
+ * +-----------+ +-----------+
+ * | type: INT | | type: INT |
+ * def | id: INDEV | | id: VALUE |
+ * | data: | | data: 3 |
+ * +-----------+ +-----------+
+ * | |
+ * ---> meta_ops[INT][INDEV](...) |
+ * | |
+ * ----------- |
+ * V V
+ * +-----------+ +-----------+
+ * | type: INT | | type: INT |
+ * obj | id: INDEV | | id: VALUE |
+ * | data: 2 |<--data got filled out | data: 3 |
+ * +-----------+ +-----------+
+ * | |
+ * --------------> 2 equals 3 <--------------
+ *
+ * This is a simplified schema, the complexity varies depending
+ * on the meta type. Obviously, the length of the data must also
+ * be provided for non-numeric types.
+ *
+ * Additionaly, type dependant modifiers such as shift operators
+ * or mask may be applied to extend the functionaliy. As of now,
+ * the variable length type supports shifting the byte string to
+ * the right, eating up any number of octets and thus supporting
+ * wildcard interface name comparisons such as "ppp%" matching
+ * ppp0..9.
+ *
+ * NOTE: Certain meta values depend on other subsystems and are
+ * only available if that subsytem is enabled in the kernel.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/skbuff.h>
+#include <linux/random.h>
+#include <linux/tc_ematch/tc_em_meta.h>
+#include <net/dst.h>
+#include <net/route.h>
+#include <net/pkt_cls.h>
+
+struct meta_obj
+{
+ unsigned long value;
+ unsigned int len;
+};
+
+struct meta_value
+{
+ struct tcf_meta_val hdr;
+ unsigned long val;
+ unsigned int len;
+};
+
+struct meta_match
+{
+ struct meta_value lvalue;
+ struct meta_value rvalue;
+};
+
+static inline int meta_id(struct meta_value *v)
+{
+ return TCF_META_ID(v->hdr.kind);
+}
+
+static inline int meta_type(struct meta_value *v)
+{
+ return TCF_META_TYPE(v->hdr.kind);
+}
+
+#define META_COLLECTOR(FUNC) static void meta_##FUNC(struct sk_buff *skb, \
+ struct tcf_pkt_info *info, struct meta_value *v, \
+ struct meta_obj *dst, int *err)
+
+/**************************************************************************
+ * System status & misc
+ **************************************************************************/
+
+META_COLLECTOR(int_random)
+{
+ get_random_bytes(&dst->value, sizeof(dst->value));
+}
+
+static inline unsigned long fixed_loadavg(int load)
+{
+ int rnd_load = load + (FIXED_1/200);
+ int rnd_frac = ((rnd_load & (FIXED_1-1)) * 100) >> FSHIFT;
+
+ return ((rnd_load >> FSHIFT) * 100) + rnd_frac;
+}
+
+META_COLLECTOR(int_loadavg_0)
+{
+ dst->value = fixed_loadavg(avenrun[0]);
+}
+
+META_COLLECTOR(int_loadavg_1)
+{
+ dst->value = fixed_loadavg(avenrun[1]);
+}
+
+META_COLLECTOR(int_loadavg_2)
+{
+ dst->value = fixed_loadavg(avenrun[2]);
+}
+
+/**************************************************************************
+ * Device names & indices
+ **************************************************************************/
+
+static inline int int_dev(struct net_device *dev, struct meta_obj *dst)
+{
+ if (unlikely(dev == NULL))
+ return -1;
+
+ dst->value = dev->ifindex;
+ return 0;
+}
+
+static inline int var_dev(struct net_device *dev, struct meta_obj *dst)
+{
+ if (unlikely(dev == NULL))
+ return -1;
+
+ dst->value = (unsigned long) dev->name;
+ dst->len = strlen(dev->name);
+ return 0;
+}
+
+META_COLLECTOR(int_dev)
+{
+ *err = int_dev(skb->dev, dst);
+}
+
+META_COLLECTOR(var_dev)
+{
+ *err = var_dev(skb->dev, dst);
+}
+
+META_COLLECTOR(int_indev)
+{
+ *err = int_dev(skb->input_dev, dst);
+}
+
+META_COLLECTOR(var_indev)
+{
+ *err = var_dev(skb->input_dev, dst);
+}
+
+META_COLLECTOR(int_realdev)
+{
+ *err = int_dev(skb->real_dev, dst);
+}
+
+META_COLLECTOR(var_realdev)
+{
+ *err = var_dev(skb->real_dev, dst);
+}
+
+/**************************************************************************
+ * skb attributes
+ **************************************************************************/
+
+META_COLLECTOR(int_priority)
+{
+ dst->value = skb->priority;
+}
+
+META_COLLECTOR(int_protocol)
+{
+ /* Let userspace take care of the byte ordering */
+ dst->value = skb->protocol;
+}
+
+META_COLLECTOR(int_security)
+{
+ dst->value = skb->security;
+}
+
+META_COLLECTOR(int_pkttype)
+{
+ dst->value = skb->pkt_type;
+}
+
+META_COLLECTOR(int_pktlen)
+{
+ dst->value = skb->len;
+}
+
+META_COLLECTOR(int_datalen)
+{
+ dst->value = skb->data_len;
+}
+
+META_COLLECTOR(int_maclen)
+{
+ dst->value = skb->mac_len;
+}
+
+/**************************************************************************
+ * Netfilter
+ **************************************************************************/
+
+#ifdef CONFIG_NETFILTER
+META_COLLECTOR(int_nfmark)
+{
+ dst->value = skb->nfmark;
+}
+#endif
+
+/**************************************************************************
+ * Traffic Control
+ **************************************************************************/
+
+META_COLLECTOR(int_tcindex)
+{
+ dst->value = skb->tc_index;
+}
+
+#ifdef CONFIG_NET_CLS_ACT
+META_COLLECTOR(int_tcverd)
+{
+ dst->value = skb->tc_verd;
+}
+
+META_COLLECTOR(int_tcclassid)
+{
+ dst->value = skb->tc_classid;
+}
+#endif
+
+/**************************************************************************
+ * Routing
+ **************************************************************************/
+
+#ifdef CONFIG_NET_CLS_ROUTE
+META_COLLECTOR(int_rtclassid)
+{
+ if (unlikely(skb->dst == NULL))
+ *err = -1;
+ else
+ dst->value = skb->dst->tclassid;
+}
+#endif
+
+META_COLLECTOR(int_rtiif)
+{
+ if (unlikely(skb->dst == NULL))
+ *err = -1;
+ else
+ dst->value = ((struct rtable*) skb->dst)->fl.iif;
+}
+
+/**************************************************************************
+ * Meta value collectors assignment table
+ **************************************************************************/
+
+struct meta_ops
+{
+ void (*get)(struct sk_buff *, struct tcf_pkt_info *,
+ struct meta_value *, struct meta_obj *, int *);
+};
+
+/* Meta value operations table listing all meta value collectors and
+ * assigns them to a type and meta id. */
+static struct meta_ops __meta_ops[TCF_META_TYPE_MAX+1][TCF_META_ID_MAX+1] = {
+ [TCF_META_TYPE_VAR] = {
+ [TCF_META_ID_DEV] = { .get = meta_var_dev },
+ [TCF_META_ID_INDEV] = { .get = meta_var_indev },
+ [TCF_META_ID_REALDEV] = { .get = meta_var_realdev }
+ },
+ [TCF_META_TYPE_INT] = {
+ [TCF_META_ID_RANDOM] = { .get = meta_int_random },
+ [TCF_META_ID_LOADAVG_0] = { .get = meta_int_loadavg_0 },
+ [TCF_META_ID_LOADAVG_1] = { .get = meta_int_loadavg_1 },
+ [TCF_META_ID_LOADAVG_2] = { .get = meta_int_loadavg_2 },
+ [TCF_META_ID_DEV] = { .get = meta_int_dev },
+ [TCF_META_ID_INDEV] = { .get = meta_int_indev },
+ [TCF_META_ID_REALDEV] = { .get = meta_int_realdev },
+ [TCF_META_ID_PRIORITY] = { .get = meta_int_priority },
+ [TCF_META_ID_PROTOCOL] = { .get = meta_int_protocol },
+ [TCF_META_ID_SECURITY] = { .get = meta_int_security },
+ [TCF_META_ID_PKTTYPE] = { .get = meta_int_pkttype },
+ [TCF_META_ID_PKTLEN] = { .get = meta_int_pktlen },
+ [TCF_META_ID_DATALEN] = { .get = meta_int_datalen },
+ [TCF_META_ID_MACLEN] = { .get = meta_int_maclen },
+#ifdef CONFIG_NETFILTER
+ [TCF_META_ID_NFMARK] = { .get = meta_int_nfmark },
+#endif
+ [TCF_META_ID_TCINDEX] = { .get = meta_int_tcindex },
+#ifdef CONFIG_NET_CLS_ACT
+ [TCF_META_ID_TCVERDICT] = { .get = meta_int_tcverd },
+ [TCF_META_ID_TCCLASSID] = { .get = meta_int_tcclassid },
+#endif
+#ifdef CONFIG_NET_CLS_ROUTE
+ [TCF_META_ID_RTCLASSID] = { .get = meta_int_rtclassid },
+#endif
+ [TCF_META_ID_RTIIF] = { .get = meta_int_rtiif }
+ }
+};
+
+static inline struct meta_ops * meta_ops(struct meta_value *val)
+{
+ return &__meta_ops[meta_type(val)][meta_id(val)];
+}
+
+/**************************************************************************
+ * Type specific operations for TCF_META_TYPE_VAR
+ **************************************************************************/
+
+static int meta_var_compare(struct meta_obj *a, struct meta_obj *b)
+{
+ int r = a->len - b->len;
+
+ if (r == 0)
+ r = memcmp((void *) a->value, (void *) b->value, a->len);
+
+ return r;
+}
+
+static int meta_var_change(struct meta_value *dst, struct rtattr *rta)
+{
+ int len = RTA_PAYLOAD(rta);
+
+ dst->val = (unsigned long) kmalloc(len, GFP_KERNEL);
+ if (dst->val == 0UL)
+ return -ENOMEM;
+ memcpy((void *) dst->val, RTA_DATA(rta), len);
+ dst->len = len;
+ return 0;
+}
+
+static void meta_var_destroy(struct meta_value *v)
+{
+ if (v->val)
+ kfree((void *) v->val);
+}
+
+static void meta_var_apply_extras(struct meta_value *v,
+ struct meta_obj *dst)
+{
+ int shift = v->hdr.shift;
+
+ if (shift && shift < dst->len)
+ dst->len -= shift;
+}
+
+static int meta_var_dump(struct sk_buff *skb, struct meta_value *v, int tlv)
+{
+ if (v->val && v->len)
+ RTA_PUT(skb, tlv, v->len, (void *) v->val);
+ return 0;
+
+rtattr_failure:
+ return -1;
+}
+
+/**************************************************************************
+ * Type specific operations for TCF_META_TYPE_INT
+ **************************************************************************/
+
+static int meta_int_compare(struct meta_obj *a, struct meta_obj *b)
+{
+ /* Let gcc optimize it, the unlikely is not really based on
+ * some numbers but jump free code for mismatches seems
+ * more logical. */
+ if (unlikely(a == b))
+ return 0;
+ else if (a < b)
+ return -1;
+ else
+ return 1;
+}
+
+static int meta_int_change(struct meta_value *dst, struct rtattr *rta)
+{
+ if (RTA_PAYLOAD(rta) >= sizeof(unsigned long)) {
+ dst->val = *(unsigned long *) RTA_DATA(rta);
+ dst->len = sizeof(unsigned long);
+ } else if (RTA_PAYLOAD(rta) == sizeof(u32)) {
+ dst->val = *(u32 *) RTA_DATA(rta);
+ dst->len = sizeof(u32);
+ } else
+ return -EINVAL;
+
+ return 0;
+}
+
+static void meta_int_apply_extras(struct meta_value *v,
+ struct meta_obj *dst)
+{
+ if (v->hdr.shift)
+ dst->value >>= v->hdr.shift;
+
+ if (v->val)
+ dst->value &= v->val;
+}
+
+static int meta_int_dump(struct sk_buff *skb, struct meta_value *v, int tlv)
+{
+ if (v->len == sizeof(unsigned long))
+ RTA_PUT(skb, tlv, sizeof(unsigned long), &v->val);
+ else if (v->len == sizeof(u32)) {
+ u32 d = v->val;
+ RTA_PUT(skb, tlv, sizeof(d), &d);
+ }
+
+ return 0;
+
+rtattr_failure:
+ return -1;
+}
+
+/**************************************************************************
+ * Type specific operations table
+ **************************************************************************/
+
+struct meta_type_ops
+{
+ void (*destroy)(struct meta_value *);
+ int (*compare)(struct meta_obj *, struct meta_obj *);
+ int (*change)(struct meta_value *, struct rtattr *);
+ void (*apply_extras)(struct meta_value *, struct meta_obj *);
+ int (*dump)(struct sk_buff *, struct meta_value *, int);
+};
+
+static struct meta_type_ops __meta_type_ops[TCF_META_TYPE_MAX+1] = {
+ [TCF_META_TYPE_VAR] = {
+ .destroy = meta_var_destroy,
+ .compare = meta_var_compare,
+ .change = meta_var_change,
+ .apply_extras = meta_var_apply_extras,
+ .dump = meta_var_dump
+ },
+ [TCF_META_TYPE_INT] = {
+ .compare = meta_int_compare,
+ .change = meta_int_change,
+ .apply_extras = meta_int_apply_extras,
+ .dump = meta_int_dump
+ }
+};
+
+static inline struct meta_type_ops * meta_type_ops(struct meta_value *v)
+{
+ return &__meta_type_ops[meta_type(v)];
+}
+
+/**************************************************************************
+ * Core
+ **************************************************************************/
+
+static inline int meta_get(struct sk_buff *skb, struct tcf_pkt_info *info,
+ struct meta_value *v, struct meta_obj *dst)
+{
+ int err = 0;
+
+ if (meta_id(v) == TCF_META_ID_VALUE) {
+ dst->value = v->val;
+ dst->len = v->len;
+ return 0;
+ }
+
+ meta_ops(v)->get(skb, info, v, dst, &err);
+ if (err < 0)
+ return err;
+
+ if (meta_type_ops(v)->apply_extras)
+ meta_type_ops(v)->apply_extras(v, dst);
+
+ return 0;
+}
+
+static int em_meta_match(struct sk_buff *skb, struct tcf_ematch *m,
+ struct tcf_pkt_info *info)
+{
+ int r;
+ struct meta_match *meta = (struct meta_match *) m->data;
+ struct meta_obj l_value, r_value;
+
+ if (meta_get(skb, info, &meta->lvalue, &l_value) < 0 ||
+ meta_get(skb, info, &meta->rvalue, &r_value) < 0)
+ return 0;
+
+ r = meta_type_ops(&meta->lvalue)->compare(&l_value, &r_value);
+
+ switch (meta->lvalue.hdr.op) {
+ case TCF_EM_OPND_EQ:
+ return !r;
+ case TCF_EM_OPND_LT:
+ return r < 0;
+ case TCF_EM_OPND_GT:
+ return r > 0;
+ }
+
+ return 0;
+}
+
+static inline void meta_delete(struct meta_match *meta)
+{
+ struct meta_type_ops *ops = meta_type_ops(&meta->lvalue);
+
+ if (ops && ops->destroy) {
+ ops->destroy(&meta->lvalue);
+ ops->destroy(&meta->rvalue);
+ }
+
+ kfree(meta);
+}
+
+static inline int meta_change_data(struct meta_value *dst, struct rtattr *rta)
+{
+ if (rta) {
+ if (RTA_PAYLOAD(rta) == 0)
+ return -EINVAL;
+
+ return meta_type_ops(dst)->change(dst, rta);
+ }
+
+ return 0;
+}
+
+static inline int meta_is_supported(struct meta_value *val)
+{
+ return (!meta_id(val) || meta_ops(val)->get);
+}
+
+static int em_meta_change(struct tcf_proto *tp, void *data, int len,
+ struct tcf_ematch *m)
+{
+ int err = -EINVAL;
+ struct rtattr *tb[TCA_EM_META_MAX];
+ struct tcf_meta_hdr *hdr;
+ struct meta_match *meta = NULL;
+
+ if (rtattr_parse(tb, TCA_EM_META_MAX, data, len) < 0)
+ goto errout;
+
+ if (tb[TCA_EM_META_HDR-1] == NULL ||
+ RTA_PAYLOAD(tb[TCA_EM_META_HDR-1]) < sizeof(*hdr))
+ goto errout;
+ hdr = RTA_DATA(tb[TCA_EM_META_HDR-1]);
+
+ if (TCF_META_TYPE(hdr->left.kind) != TCF_META_TYPE(hdr->right.kind) ||
+ TCF_META_TYPE(hdr->left.kind) > TCF_META_TYPE_MAX ||
+ TCF_META_ID(hdr->left.kind) > TCF_META_ID_MAX ||
+ TCF_META_ID(hdr->right.kind) > TCF_META_ID_MAX)
+ goto errout;
+
+ meta = kmalloc(sizeof(*meta), GFP_KERNEL);
+ if (meta == NULL)
+ goto errout;
+ memset(meta, 0, sizeof(*meta));
+
+ memcpy(&meta->lvalue.hdr, &hdr->left, sizeof(hdr->left));
+ memcpy(&meta->rvalue.hdr, &hdr->right, sizeof(hdr->right));
+
+ if (!meta_is_supported(&meta->lvalue) ||
+ !meta_is_supported(&meta->rvalue)) {
+ err = -EOPNOTSUPP;
+ goto errout;
+ }
+
+ if (meta_change_data(&meta->lvalue, tb[TCA_EM_META_LVALUE-1]) < 0 ||
+ meta_change_data(&meta->rvalue, tb[TCA_EM_META_RVALUE-1]) < 0)
+ goto errout;
+
+ m->datalen = sizeof(*meta);
+ m->data = (unsigned long) meta;
+
+ err = 0;
+errout:
+ if (err && meta)
+ meta_delete(meta);
+ return err;
+}
+
+static void em_meta_destroy(struct tcf_proto *tp, struct tcf_ematch *m)
+{
+ if (m)
+ meta_delete((struct meta_match *) m->data);
+}
+
+static int em_meta_dump(struct sk_buff *skb, struct tcf_ematch *em)
+{
+ struct meta_match *meta = (struct meta_match *) em->data;
+ struct tcf_meta_hdr hdr;
+ struct meta_type_ops *ops;
+
+ memset(&hdr, 0, sizeof(hdr));
+ memcpy(&hdr.left, &meta->lvalue.hdr, sizeof(hdr.left));
+ memcpy(&hdr.right, &meta->rvalue.hdr, sizeof(hdr.right));
+
+ RTA_PUT(skb, TCA_EM_META_HDR, sizeof(hdr), &hdr);
+
+ ops = meta_type_ops(&meta->lvalue);
+ if (ops->dump(skb, &meta->lvalue, TCA_EM_META_LVALUE) < 0 ||
+ ops->dump(skb, &meta->rvalue, TCA_EM_META_RVALUE) < 0)
+ goto rtattr_failure;
+
+ return 0;
+
+rtattr_failure:
+ return -1;
+}
+
+static struct tcf_ematch_ops em_meta_ops = {
+ .kind = TCF_EM_META,
+ .change = em_meta_change,
+ .match = em_meta_match,
+ .destroy = em_meta_destroy,
+ .dump = em_meta_dump,
+ .owner = THIS_MODULE,
+ .link = LIST_HEAD_INIT(em_meta_ops.link)
+};
+
+static int __init init_em_meta(void)
+{
+ return tcf_em_register(&em_meta_ops);
+}
+
+static void __exit exit_em_meta(void)
+{
+ tcf_em_unregister(&em_meta_ops);
+}
+
+MODULE_LICENSE("GPL");
+
+module_init(init_em_meta);
+module_exit(exit_em_meta);
diff --git a/net/sched/em_nbyte.c b/net/sched/em_nbyte.c
new file mode 100644
index 0000000000000..71ea926a9f092
--- /dev/null
+++ b/net/sched/em_nbyte.c
@@ -0,0 +1,82 @@
+/*
+ * net/sched/em_nbyte.c N-Byte ematch
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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: Thomas Graf <tgraf@suug.ch>
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/skbuff.h>
+#include <linux/tc_ematch/tc_em_nbyte.h>
+#include <net/pkt_cls.h>
+
+struct nbyte_data
+{
+ struct tcf_em_nbyte hdr;
+ char pattern[0];
+};
+
+static int em_nbyte_change(struct tcf_proto *tp, void *data, int data_len,
+ struct tcf_ematch *em)
+{
+ struct tcf_em_nbyte *nbyte = data;
+
+ if (data_len < sizeof(*nbyte) ||
+ data_len < (sizeof(*nbyte) + nbyte->len))
+ return -EINVAL;
+
+ em->datalen = sizeof(*nbyte) + nbyte->len;
+ em->data = (unsigned long) kmalloc(em->datalen, GFP_KERNEL);
+ if (em->data == 0UL)
+ return -ENOBUFS;
+
+ memcpy((void *) em->data, data, em->datalen);
+
+ return 0;
+}
+
+static int em_nbyte_match(struct sk_buff *skb, struct tcf_ematch *em,
+ struct tcf_pkt_info *info)
+{
+ struct nbyte_data *nbyte = (struct nbyte_data *) em->data;
+ unsigned char *ptr = tcf_get_base_ptr(skb, nbyte->hdr.layer);
+
+ ptr += nbyte->hdr.off;
+
+ if (!tcf_valid_offset(skb, ptr, nbyte->hdr.len))
+ return 0;
+
+ return !memcmp(ptr + nbyte->hdr.off, nbyte->pattern, nbyte->hdr.len);
+}
+
+static struct tcf_ematch_ops em_nbyte_ops = {
+ .kind = TCF_EM_NBYTE,
+ .change = em_nbyte_change,
+ .match = em_nbyte_match,
+ .owner = THIS_MODULE,
+ .link = LIST_HEAD_INIT(em_nbyte_ops.link)
+};
+
+static int __init init_em_nbyte(void)
+{
+ return tcf_em_register(&em_nbyte_ops);
+}
+
+static void __exit exit_em_nbyte(void)
+{
+ tcf_em_unregister(&em_nbyte_ops);
+}
+
+MODULE_LICENSE("GPL");
+
+module_init(init_em_nbyte);
+module_exit(exit_em_nbyte);
diff --git a/net/sched/em_u32.c b/net/sched/em_u32.c
new file mode 100644
index 0000000000000..34e7e51e601e0
--- /dev/null
+++ b/net/sched/em_u32.c
@@ -0,0 +1,63 @@
+/*
+ * net/sched/em_u32.c U32 Ematch
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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: Thomas Graf <tgraf@suug.ch>
+ * Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
+ *
+ * Based on net/sched/cls_u32.c
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/skbuff.h>
+#include <net/pkt_cls.h>
+
+static int em_u32_match(struct sk_buff *skb, struct tcf_ematch *em,
+ struct tcf_pkt_info *info)
+{
+ struct tc_u32_key *key = (struct tc_u32_key *) em->data;
+ unsigned char *ptr = skb->nh.raw;
+
+ if (info) {
+ if (info->ptr)
+ ptr = info->ptr;
+ ptr += (info->nexthdr & key->offmask);
+ }
+
+ ptr += key->off;
+
+ if (!tcf_valid_offset(skb, ptr, sizeof(u32)))
+ return 0;
+
+ return !(((*(u32*) ptr) ^ key->val) & key->mask);
+}
+
+static struct tcf_ematch_ops em_u32_ops = {
+ .kind = TCF_EM_U32,
+ .datalen = sizeof(struct tc_u32_key),
+ .match = em_u32_match,
+ .owner = THIS_MODULE,
+ .link = LIST_HEAD_INIT(em_u32_ops.link)
+};
+
+static int __init init_em_u32(void)
+{
+ return tcf_em_register(&em_u32_ops);
+}
+
+static void __exit exit_em_u32(void)
+{
+ tcf_em_unregister(&em_u32_ops);
+}
+
+MODULE_LICENSE("GPL");
+
+module_init(init_em_u32);
+module_exit(exit_em_u32);
diff --git a/net/sched/ematch.c b/net/sched/ematch.c
new file mode 100644
index 0000000000000..ebfe2e7d21bdf
--- /dev/null
+++ b/net/sched/ematch.c
@@ -0,0 +1,524 @@
+/*
+ * net/sched/ematch.c Extended Match API
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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: Thomas Graf <tgraf@suug.ch>
+ *
+ * ==========================================================================
+ *
+ * An extended match (ematch) is a small classification tool not worth
+ * writing a full classifier for. Ematches can be interconnected to form
+ * a logic expression and get attached to classifiers to extend their
+ * functionatlity.
+ *
+ * The userspace part transforms the logic expressions into an array
+ * consisting of multiple sequences of interconnected ematches separated
+ * by markers. Precedence is implemented by a special ematch kind
+ * referencing a sequence beyond the marker of the current sequence
+ * causing the current position in the sequence to be pushed onto a stack
+ * to allow the current position to be overwritten by the position referenced
+ * in the special ematch. Matching continues in the new sequence until a
+ * marker is reached causing the position to be restored from the stack.
+ *
+ * Example:
+ * A AND (B1 OR B2) AND C AND D
+ *
+ * ------->-PUSH-------
+ * -->-- / -->-- \ -->--
+ * / \ / / \ \ / \
+ * +-------+-------+-------+-------+-------+--------+
+ * | A AND | B AND | C AND | D END | B1 OR | B2 END |
+ * +-------+-------+-------+-------+-------+--------+
+ * \ /
+ * --------<-POP---------
+ *
+ * where B is a virtual ematch referencing to sequence starting with B1.
+ *
+ * ==========================================================================
+ *
+ * How to write an ematch in 60 seconds
+ * ------------------------------------
+ *
+ * 1) Provide a matcher function:
+ * static int my_match(struct sk_buff *skb, struct tcf_ematch *m,
+ * struct tcf_pkt_info *info)
+ * {
+ * struct mydata *d = (struct mydata *) m->data;
+ *
+ * if (...matching goes here...)
+ * return 1;
+ * else
+ * return 0;
+ * }
+ *
+ * 2) Fill out a struct tcf_ematch_ops:
+ * static struct tcf_ematch_ops my_ops = {
+ * .kind = unique id,
+ * .datalen = sizeof(struct mydata),
+ * .match = my_match,
+ * .owner = THIS_MODULE,
+ * };
+ *
+ * 3) Register/Unregister your ematch:
+ * static int __init init_my_ematch(void)
+ * {
+ * return tcf_em_register(&my_ops);
+ * }
+ *
+ * static void __exit exit_my_ematch(void)
+ * {
+ * return tcf_em_unregister(&my_ops);
+ * }
+ *
+ * module_init(init_my_ematch);
+ * module_exit(exit_my_ematch);
+ *
+ * 4) By now you should have two more seconds left, barely enough to
+ * open up a beer to watch the compilation going.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#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);
+
+static inline struct tcf_ematch_ops * tcf_em_lookup(u16 kind)
+{
+ struct tcf_ematch_ops *e = NULL;
+
+ read_lock(&ematch_mod_lock);
+ list_for_each_entry(e, &ematch_ops, link) {
+ if (kind == e->kind) {
+ if (!try_module_get(e->owner))
+ e = NULL;
+ read_unlock(&ematch_mod_lock);
+ return e;
+ }
+ }
+ read_unlock(&ematch_mod_lock);
+
+ return NULL;
+}
+
+/**
+ * tcf_em_register - register an extended match
+ *
+ * @ops: ematch operations lookup table
+ *
+ * This function must be called by ematches to announce their presence.
+ * The given @ops must have kind set to a unique identifier and the
+ * callback match() must be implemented. All other callbacks are optional
+ * and a fallback implementation is used instead.
+ *
+ * Returns -EEXISTS if an ematch of the same kind has already registered.
+ */
+int tcf_em_register(struct tcf_ematch_ops *ops)
+{
+ int err = -EEXIST;
+ struct tcf_ematch_ops *e;
+
+ if (ops->match == NULL)
+ return -EINVAL;
+
+ write_lock(&ematch_mod_lock);
+ list_for_each_entry(e, &ematch_ops, link)
+ if (ops->kind == e->kind)
+ goto errout;
+
+ list_add_tail(&ops->link, &ematch_ops);
+ err = 0;
+errout:
+ write_unlock(&ematch_mod_lock);
+ return err;
+}
+
+/**
+ * tcf_em_unregister - unregster and extended match
+ *
+ * @ops: ematch operations lookup table
+ *
+ * This function must be called by ematches to announce their disappearance
+ * for examples when the module gets unloaded. The @ops parameter must be
+ * the same as the one used for registration.
+ *
+ * Returns -ENOENT if no matching ematch was found.
+ */
+int tcf_em_unregister(struct tcf_ematch_ops *ops)
+{
+ int err = 0;
+ struct tcf_ematch_ops *e;
+
+ write_lock(&ematch_mod_lock);
+ list_for_each_entry(e, &ematch_ops, link) {
+ if (e == ops) {
+ list_del(&e->link);
+ goto out;
+ }
+ }
+
+ err = -ENOENT;
+out:
+ write_unlock(&ematch_mod_lock);
+ return err;
+}
+
+static inline struct tcf_ematch * tcf_em_get_match(struct tcf_ematch_tree *tree,
+ int index)
+{
+ return &tree->matches[index];
+}
+
+
+static int tcf_em_validate(struct tcf_proto *tp,
+ struct tcf_ematch_tree_hdr *tree_hdr,
+ struct tcf_ematch *em, struct rtattr *rta, int idx)
+{
+ int err = -EINVAL;
+ struct tcf_ematch_hdr *em_hdr = RTA_DATA(rta);
+ int data_len = RTA_PAYLOAD(rta) - sizeof(*em_hdr);
+ void *data = (void *) em_hdr + sizeof(*em_hdr);
+
+ if (!TCF_EM_REL_VALID(em_hdr->flags))
+ goto errout;
+
+ if (em_hdr->kind == TCF_EM_CONTAINER) {
+ /* Special ematch called "container", carries an index
+ * referencing an external ematch sequence. */
+ u32 ref;
+
+ if (data_len < sizeof(ref))
+ goto errout;
+ ref = *(u32 *) data;
+
+ if (ref >= tree_hdr->nmatches)
+ goto errout;
+
+ /* We do not allow backward jumps to avoid loops and jumps
+ * to our own position are of course illegal. */
+ if (ref <= idx)
+ goto errout;
+
+
+ em->data = ref;
+ } else {
+ /* Note: This lookup will increase the module refcnt
+ * of the ematch module referenced. In case of a failure,
+ * a destroy function is called by the underlying layer
+ * which automatically releases the reference again, therefore
+ * the module MUST not be given back under any circumstances
+ * here. Be aware, the destroy function assumes that the
+ * module is held if the ops field is non zero. */
+ em->ops = tcf_em_lookup(em_hdr->kind);
+
+ if (em->ops == NULL) {
+ err = -ENOENT;
+ goto errout;
+ }
+
+ /* ematch module provides expected length of data, so we
+ * can do a basic sanity check. */
+ if (em->ops->datalen && data_len < em->ops->datalen)
+ goto errout;
+
+ if (em->ops->change) {
+ err = em->ops->change(tp, data, data_len, em);
+ if (err < 0)
+ goto errout;
+ } else if (data_len > 0) {
+ /* ematch module doesn't provide an own change
+ * procedure and expects us to allocate and copy
+ * the ematch data.
+ *
+ * TCF_EM_SIMPLE may be specified stating that the
+ * data only consists of a u32 integer and the module
+ * does not expected a memory reference but rather
+ * the value carried. */
+ if (em_hdr->flags & TCF_EM_SIMPLE) {
+ if (data_len < sizeof(u32))
+ goto errout;
+ em->data = *(u32 *) data;
+ } else {
+ void *v = kmalloc(data_len, GFP_KERNEL);
+ if (v == NULL) {
+ err = -ENOBUFS;
+ goto errout;
+ }
+ memcpy(v, data, data_len);
+ em->data = (unsigned long) v;
+ }
+ }
+ }
+
+ em->matchid = em_hdr->matchid;
+ em->flags = em_hdr->flags;
+ em->datalen = data_len;
+
+ err = 0;
+errout:
+ return err;
+}
+
+/**
+ * tcf_em_tree_validate - validate ematch config TLV and build ematch tree
+ *
+ * @tp: classifier kind handle
+ * @rta: ematch tree configuration TLV
+ * @tree: destination ematch tree variable to store the resulting
+ * ematch tree.
+ *
+ * This function validates the given configuration TLV @rta and builds an
+ * ematch tree in @tree. The resulting tree must later be copied into
+ * the private classifier data using tcf_em_tree_change(). You MUST NOT
+ * provide the ematch tree variable of the private classifier data directly,
+ * the changes would not be locked properly.
+ *
+ * Returns a negative error code if the configuration TLV contains errors.
+ */
+int tcf_em_tree_validate(struct tcf_proto *tp, struct rtattr *rta,
+ struct tcf_ematch_tree *tree)
+{
+ int idx, list_len, matches_len, err = -EINVAL;
+ struct rtattr *tb[TCA_EMATCH_TREE_MAX];
+ struct rtattr *rt_match, *rt_hdr, *rt_list;
+ struct tcf_ematch_tree_hdr *tree_hdr;
+ struct tcf_ematch *em;
+
+ if (rtattr_parse_nested(tb, TCA_EMATCH_TREE_MAX, rta) < 0)
+ goto errout;
+
+ rt_hdr = tb[TCA_EMATCH_TREE_HDR-1];
+ rt_list = tb[TCA_EMATCH_TREE_LIST-1];
+
+ if (rt_hdr == NULL || rt_list == NULL)
+ goto errout;
+
+ if (RTA_PAYLOAD(rt_hdr) < sizeof(*tree_hdr) ||
+ RTA_PAYLOAD(rt_list) < sizeof(*rt_match))
+ goto errout;
+
+ tree_hdr = RTA_DATA(rt_hdr);
+ memcpy(&tree->hdr, tree_hdr, sizeof(*tree_hdr));
+
+ rt_match = RTA_DATA(rt_list);
+ list_len = RTA_PAYLOAD(rt_list);
+ matches_len = tree_hdr->nmatches * sizeof(*em);
+
+ tree->matches = kmalloc(matches_len, GFP_KERNEL);
+ if (tree->matches == NULL)
+ goto errout;
+ memset(tree->matches, 0, matches_len);
+
+ /* We do not use rtattr_parse_nested here because the maximum
+ * number of attributes is unknown. This saves us the allocation
+ * for a tb buffer which would serve no purpose at all.
+ *
+ * The array of rt attributes is parsed in the order as they are
+ * provided, their type must be incremental from 1 to n. Even
+ * if it does not serve any real purpose, a failure of sticking
+ * to this policy will result in parsing failure. */
+ for (idx = 0; RTA_OK(rt_match, list_len); idx++) {
+ err = -EINVAL;
+
+ if (rt_match->rta_type != (idx + 1))
+ goto errout_abort;
+
+ if (idx >= tree_hdr->nmatches)
+ goto errout_abort;
+
+ if (RTA_PAYLOAD(rt_match) < sizeof(struct tcf_ematch_hdr))
+ goto errout_abort;
+
+ em = tcf_em_get_match(tree, idx);
+
+ err = tcf_em_validate(tp, tree_hdr, em, rt_match, idx);
+ if (err < 0)
+ goto errout_abort;
+
+ rt_match = RTA_NEXT(rt_match, list_len);
+ }
+
+ /* Check if the number of matches provided by userspace actually
+ * complies with the array of matches. The number was used for
+ * the validation of references and a mismatch could lead to
+ * undefined references during the matching process. */
+ if (idx != tree_hdr->nmatches) {
+ err = -EINVAL;
+ goto errout_abort;
+ }
+
+ err = 0;
+errout:
+ return err;
+
+errout_abort:
+ tcf_em_tree_destroy(tp, tree);
+ return err;
+}
+
+/**
+ * tcf_em_tree_destroy - destroy an ematch tree
+ *
+ * @tp: classifier kind handle
+ * @tree: ematch tree to be deleted
+ *
+ * This functions destroys an ematch tree previously created by
+ * tcf_em_tree_validate()/tcf_em_tree_change(). You must ensure that
+ * the ematch tree is not in use before calling this function.
+ */
+void tcf_em_tree_destroy(struct tcf_proto *tp, struct tcf_ematch_tree *tree)
+{
+ int i;
+
+ if (tree->matches == NULL)
+ return;
+
+ for (i = 0; i < tree->hdr.nmatches; i++) {
+ struct tcf_ematch *em = tcf_em_get_match(tree, i);
+
+ if (em->ops) {
+ if (em->ops->destroy)
+ em->ops->destroy(tp, em);
+ else if (!tcf_em_is_simple(em) && em->data)
+ kfree((void *) em->data);
+ module_put(em->ops->owner);
+ }
+ }
+
+ tree->hdr.nmatches = 0;
+ kfree(tree->matches);
+}
+
+/**
+ * tcf_em_tree_dump - dump ematch tree into a rtnl message
+ *
+ * @skb: skb holding the rtnl message
+ * @t: ematch tree to be dumped
+ * @tlv: TLV type to be used to encapsulate the tree
+ *
+ * This function dumps a ematch tree into a rtnl message. It is valid to
+ * call this function while the ematch tree is in use.
+ *
+ * Returns -1 if the skb tailroom is insufficient.
+ */
+int tcf_em_tree_dump(struct sk_buff *skb, struct tcf_ematch_tree *tree, int tlv)
+{
+ int i;
+ struct rtattr * top_start = (struct rtattr*) skb->tail;
+ struct rtattr * list_start;
+
+ RTA_PUT(skb, tlv, 0, NULL);
+ RTA_PUT(skb, TCA_EMATCH_TREE_HDR, sizeof(tree->hdr), &tree->hdr);
+
+ list_start = (struct rtattr *) skb->tail;
+ RTA_PUT(skb, TCA_EMATCH_TREE_LIST, 0, NULL);
+
+ for (i = 0; i < tree->hdr.nmatches; i++) {
+ struct rtattr *match_start = (struct rtattr*) skb->tail;
+ struct tcf_ematch *em = tcf_em_get_match(tree, i);
+ struct tcf_ematch_hdr em_hdr = {
+ .kind = em->ops ? em->ops->kind : TCF_EM_CONTAINER,
+ .matchid = em->matchid,
+ .flags = em->flags
+ };
+
+ RTA_PUT(skb, i+1, sizeof(em_hdr), &em_hdr);
+
+ if (em->ops && em->ops->dump) {
+ if (em->ops->dump(skb, em) < 0)
+ goto rtattr_failure;
+ } else if (tcf_em_is_container(em) || tcf_em_is_simple(em)) {
+ u32 u = em->data;
+ RTA_PUT_NOHDR(skb, sizeof(u), &u);
+ } else if (em->datalen > 0)
+ RTA_PUT_NOHDR(skb, em->datalen, (void *) em->data);
+
+ match_start->rta_len = skb->tail - (u8*) match_start;
+ }
+
+ list_start->rta_len = skb->tail - (u8 *) list_start;
+ top_start->rta_len = skb->tail - (u8 *) top_start;
+
+ return 0;
+
+rtattr_failure:
+ return -1;
+}
+
+static inline int tcf_em_match(struct sk_buff *skb, struct tcf_ematch *em,
+ struct tcf_pkt_info *info)
+{
+ int r = em->ops->match(skb, em, info);
+ return tcf_em_is_inverted(em) ? !r : r;
+}
+
+/* Do not use this function directly, use tcf_em_tree_match instead */
+int __tcf_em_tree_match(struct sk_buff *skb, struct tcf_ematch_tree *tree,
+ struct tcf_pkt_info *info)
+{
+ int stackp = 0, match_idx = 0, res = 0;
+ struct tcf_ematch *cur_match;
+ int stack[CONFIG_NET_EMATCH_STACK];
+
+proceed:
+ while (match_idx < tree->hdr.nmatches) {
+ cur_match = tcf_em_get_match(tree, match_idx);
+
+ if (tcf_em_is_container(cur_match)) {
+ if (unlikely(stackp >= CONFIG_NET_EMATCH_STACK))
+ goto stack_overflow;
+
+ stack[stackp++] = match_idx;
+ match_idx = cur_match->data;
+ goto proceed;
+ }
+
+ res = tcf_em_match(skb, cur_match, info);
+
+ if (tcf_em_early_end(cur_match, res))
+ break;
+
+ match_idx++;
+ }
+
+pop_stack:
+ if (stackp > 0) {
+ match_idx = stack[--stackp];
+ cur_match = tcf_em_get_match(tree, match_idx);
+
+ if (tcf_em_early_end(cur_match, res))
+ goto pop_stack;
+ else {
+ match_idx++;
+ goto proceed;
+ }
+ }
+
+ return res;
+
+stack_overflow:
+ if (net_ratelimit())
+ printk("Local stack overflow, increase NET_EMATCH_STACK\n");
+ return -1;
+}
+
+EXPORT_SYMBOL(tcf_em_register);
+EXPORT_SYMBOL(tcf_em_unregister);
+EXPORT_SYMBOL(tcf_em_tree_validate);
+EXPORT_SYMBOL(tcf_em_tree_destroy);
+EXPORT_SYMBOL(tcf_em_tree_dump);
+EXPORT_SYMBOL(__tcf_em_tree_match);
diff --git a/net/sched/ipt.c b/net/sched/ipt.c
index 886f46393abc4..b114d994d5236 100644
--- a/net/sched/ipt.c
+++ b/net/sched/ipt.c
@@ -284,10 +284,12 @@ tcf_ipt_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
tm.lastuse = jiffies_to_clock_t(jiffies - p->tm.lastuse);
tm.expires = jiffies_to_clock_t(p->tm.expires);
RTA_PUT(skb, TCA_IPT_TM, sizeof (tm), &tm);
+ kfree(t);
return skb->len;
rtattr_failure:
skb_trim(skb, b - skb->data);
+ kfree(t);
return -1;
}
diff --git a/net/sched/sch_atm.c b/net/sched/sch_atm.c
index 427b6fe7bfac0..93ebce40acac6 100644
--- a/net/sched/sch_atm.c
+++ b/net/sched/sch_atm.c
@@ -519,7 +519,7 @@ static void sch_atm_dequeue(unsigned long data)
memcpy(skb_push(skb,flow->hdr_len),flow->hdr,
flow->hdr_len);
atomic_add(skb->truesize,
- &flow->vcc->sk->sk_wmem_alloc);
+ &sk_atm(flow->vcc)->sk_wmem_alloc);
/* atm.atm_options are already set by atm_tc_enqueue */
(void) flow->vcc->send(flow->vcc,skb);
}
diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c
index b4631b3001a3d..544b75077dbdd 100644
--- a/net/sctp/endpointola.c
+++ b/net/sctp/endpointola.c
@@ -126,7 +126,7 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep,
/* Use SCTP specific send buffer space queues. */
sk->sk_write_space = sctp_write_space;
- sk->sk_use_write_queue = 1;
+ sock_set_flag(sk, SOCK_USE_WRITE_QUEUE);
/* Initialize the secret key used with cookie. */
get_random_bytes(&ep->secret_key[0], SCTP_SECRET_SIZE);
diff --git a/net/sctp/input.c b/net/sctp/input.c
index 688e714f909ff..b719a77d66b47 100644
--- a/net/sctp/input.c
+++ b/net/sctp/input.c
@@ -100,6 +100,21 @@ static inline int sctp_rcv_checksum(struct sk_buff *skb)
return 0;
}
+/* The free routine for skbuffs that sctp receives */
+static void sctp_rfree(struct sk_buff *skb)
+{
+ atomic_sub(sizeof(struct sctp_chunk),&skb->sk->sk_rmem_alloc);
+ sock_rfree(skb);
+}
+
+/* The ownership wrapper routine to do receive buffer accounting */
+static void sctp_rcv_set_owner_r(struct sk_buff *skb, struct sock *sk)
+{
+ skb_set_owner_r(skb,sk);
+ skb->destructor = sctp_rfree;
+ atomic_add(sizeof(struct sctp_chunk),&sk->sk_rmem_alloc);
+}
+
/*
* This is the routine which IP calls when receiving an SCTP packet.
*/
@@ -183,6 +198,11 @@ int sctp_rcv(struct sk_buff *skb)
rcvr = asoc ? &asoc->base : &ep->base;
sk = rcvr->sk;
+ if ((sk) && (atomic_read(&sk->sk_rmem_alloc) >= sk->sk_rcvbuf)) {
+ goto discard_release;
+ }
+
+
/* SCTP seems to always need a timestamp right now (FIXME) */
if (skb->stamp.tv_sec == 0) {
do_gettimeofday(&skb->stamp);
@@ -203,6 +223,8 @@ int sctp_rcv(struct sk_buff *skb)
goto discard_release;
}
+ sctp_rcv_set_owner_r(skb,sk);
+
/* Remember what endpoint is to handle this packet. */
chunk->rcvr = rcvr;
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index efe44d19d2c45..ee1be46dd5709 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c
@@ -609,11 +609,11 @@ static struct sock *sctp_v6_create_accept_sk(struct sock *sk,
newsk->sk_reuse = sk->sk_reuse;
newsk->sk_destruct = inet_sock_destruct;
- newsk->sk_zapped = 0;
newsk->sk_family = PF_INET6;
newsk->sk_protocol = IPPROTO_SCTP;
newsk->sk_backlog_rcv = sk->sk_prot->backlog_rcv;
newsk->sk_shutdown = sk->sk_shutdown;
+ sock_reset_flag(sk, SOCK_ZAPPED);
newsctp6sk = (struct sctp6_sock *)newsk;
inet_sk(newsk)->pinet6 = &newsctp6sk->inet6;
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index c1ee92a662b7d..49214c3b45f43 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -570,10 +570,10 @@ static struct sock *sctp_v4_create_accept_sk(struct sock *sk,
newsk->sk_shutdown = sk->sk_shutdown;
newsk->sk_destruct = inet_sock_destruct;
- newsk->sk_zapped = 0;
newsk->sk_family = PF_INET;
newsk->sk_protocol = IPPROTO_SCTP;
newsk->sk_backlog_rcv = sk->sk_prot->backlog_rcv;
+ sock_reset_flag(newsk, SOCK_ZAPPED);
newinet = inet_sk(newsk);
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index 9b1b95939b62a..278c56a2d0765 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -268,7 +268,7 @@ sctp_disposition_t sctp_sf_do_5_1B_init(const struct sctp_endpoint *ep,
*/
if (!sctp_sstate(sk, LISTENING) ||
(sctp_style(sk, TCP) &&
- (sk->sk_ack_backlog >= sk->sk_max_ack_backlog)))
+ sk_acceptq_is_full(sk)))
return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands);
/* 3.1 A packet containing an INIT chunk MUST have a zero Verification
diff --git a/net/sctp/transport.c b/net/sctp/transport.c
index 0e0c0f8f19118..f30882e1e96ac 100644
--- a/net/sctp/transport.c
+++ b/net/sctp/transport.c
@@ -227,7 +227,7 @@ void sctp_transport_pmtu(struct sctp_transport *transport)
dst = transport->af_specific->get_dst(NULL, &transport->ipaddr, NULL);
if (dst) {
- transport->pmtu = dst_pmtu(dst);
+ transport->pmtu = dst_mtu(dst);
dst_release(dst);
} else
transport->pmtu = SCTP_DEFAULT_MAXSEGMENT;
@@ -253,7 +253,7 @@ void sctp_transport_route(struct sctp_transport *transport,
transport->dst = dst;
if (dst) {
- transport->pmtu = dst_pmtu(dst);
+ transport->pmtu = dst_mtu(dst);
/* Initialize sk->sk_rcv_saddr, if the transport is the
* association's active path for getsockname().
diff --git a/net/socket.c b/net/socket.c
index 7bc2e08115831..f2391d68fad3b 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -287,7 +287,7 @@ static struct inode *sock_alloc_inode(struct super_block *sb)
ei->socket.ops = NULL;
ei->socket.sk = NULL;
ei->socket.file = NULL;
- ei->socket.passcred = 0;
+ ei->socket.flags = 0;
return &ei->vfs_inode;
}
@@ -993,8 +993,7 @@ static int sock_fasync(int fd, struct file *filp, int on)
sock = SOCKET_I(filp->f_dentry->d_inode);
if ((sk=sock->sk) == NULL) {
- if (fna)
- kfree(fna);
+ kfree(fna);
return -EINVAL;
}
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c
index 7176c6d371900..9bcec9b927b9b 100644
--- a/net/sunrpc/auth.c
+++ b/net/sunrpc/auth.c
@@ -67,12 +67,9 @@ rpcauth_create(rpc_authflavor_t pseudoflavor, struct rpc_clnt *clnt)
if (flavor >= RPC_AUTH_MAXFLAVOR || !(ops = auth_flavors[flavor]))
return NULL;
- if (!try_module_get(ops->owner))
- return NULL;
auth = ops->create(clnt, pseudoflavor);
if (!auth)
return NULL;
- atomic_set(&auth->au_count, 1);
if (clnt->cl_auth)
rpcauth_destroy(clnt->cl_auth);
clnt->cl_auth = auth;
@@ -85,8 +82,6 @@ rpcauth_destroy(struct rpc_auth *auth)
if (!atomic_dec_and_test(&auth->au_count))
return;
auth->au_ops->destroy(auth);
- module_put(auth->au_ops->owner);
- kfree(auth);
}
static DEFINE_SPINLOCK(rpc_credcache_lock);
@@ -94,42 +89,35 @@ static DEFINE_SPINLOCK(rpc_credcache_lock);
/*
* Initialize RPC credential cache
*/
-void
-rpcauth_init_credcache(struct rpc_auth *auth)
+int
+rpcauth_init_credcache(struct rpc_auth *auth, unsigned long expire)
{
+ struct rpc_cred_cache *new;
int i;
- for (i = 0; i < RPC_CREDCACHE_NR; i++)
- INIT_LIST_HEAD(&auth->au_credcache[i]);
- auth->au_nextgc = jiffies + (auth->au_expire >> 1);
-}
-/*
- * Destroy an unreferenced credential
- */
-static inline void
-rpcauth_crdestroy(struct rpc_cred *cred)
-{
-#ifdef RPC_DEBUG
- BUG_ON(cred->cr_magic != RPCAUTH_CRED_MAGIC ||
- atomic_read(&cred->cr_count) ||
- !list_empty(&cred->cr_hash));
- cred->cr_magic = 0;
-#endif
- cred->cr_ops->crdestroy(cred);
+ new = (struct rpc_cred_cache *)kmalloc(sizeof(*new), GFP_KERNEL);
+ if (!new)
+ return -ENOMEM;
+ for (i = 0; i < RPC_CREDCACHE_NR; i++)
+ INIT_HLIST_HEAD(&new->hashtable[i]);
+ new->expire = expire;
+ new->nextgc = jiffies + (expire >> 1);
+ auth->au_credcache = new;
+ return 0;
}
/*
* Destroy a list of credentials
*/
static inline
-void rpcauth_destroy_credlist(struct list_head *head)
+void rpcauth_destroy_credlist(struct hlist_head *head)
{
struct rpc_cred *cred;
- while (!list_empty(head)) {
- cred = list_entry(head->next, struct rpc_cred, cr_hash);
- list_del_init(&cred->cr_hash);
- rpcauth_crdestroy(cred);
+ while (!hlist_empty(head)) {
+ cred = hlist_entry(head->first, struct rpc_cred, cr_hash);
+ hlist_del_init(&cred->cr_hash);
+ put_rpccred(cred);
}
}
@@ -140,56 +128,56 @@ void rpcauth_destroy_credlist(struct list_head *head)
void
rpcauth_free_credcache(struct rpc_auth *auth)
{
- LIST_HEAD(free);
- struct list_head *pos, *next;
+ struct rpc_cred_cache *cache = auth->au_credcache;
+ HLIST_HEAD(free);
+ struct hlist_node *pos, *next;
struct rpc_cred *cred;
int i;
spin_lock(&rpc_credcache_lock);
for (i = 0; i < RPC_CREDCACHE_NR; i++) {
- list_for_each_safe(pos, next, &auth->au_credcache[i]) {
- cred = list_entry(pos, struct rpc_cred, cr_hash);
- cred->cr_auth = NULL;
- list_del_init(&cred->cr_hash);
- if (atomic_read(&cred->cr_count) == 0)
- list_add(&cred->cr_hash, &free);
+ hlist_for_each_safe(pos, next, &cache->hashtable[i]) {
+ cred = hlist_entry(pos, struct rpc_cred, cr_hash);
+ __hlist_del(&cred->cr_hash);
+ hlist_add_head(&cred->cr_hash, &free);
}
}
spin_unlock(&rpc_credcache_lock);
rpcauth_destroy_credlist(&free);
}
-static inline int
-rpcauth_prune_expired(struct rpc_cred *cred, struct list_head *free)
+static void
+rpcauth_prune_expired(struct rpc_auth *auth, struct rpc_cred *cred, struct hlist_head *free)
{
- if (atomic_read(&cred->cr_count) != 0)
- return 0;
- if (time_before(jiffies, cred->cr_expire))
- return 0;
- cred->cr_auth = NULL;
- list_del(&cred->cr_hash);
- list_add(&cred->cr_hash, free);
- return 1;
+ if (atomic_read(&cred->cr_count) != 1)
+ return;
+ if (time_after(jiffies, cred->cr_expire + auth->au_credcache->expire))
+ cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
+ if (!(cred->cr_flags & RPCAUTH_CRED_UPTODATE)) {
+ __hlist_del(&cred->cr_hash);
+ hlist_add_head(&cred->cr_hash, free);
+ }
}
/*
* Remove stale credentials. Avoid sleeping inside the loop.
*/
static void
-rpcauth_gc_credcache(struct rpc_auth *auth, struct list_head *free)
+rpcauth_gc_credcache(struct rpc_auth *auth, struct hlist_head *free)
{
- struct list_head *pos, *next;
+ struct rpc_cred_cache *cache = auth->au_credcache;
+ struct hlist_node *pos, *next;
struct rpc_cred *cred;
int i;
dprintk("RPC: gc'ing RPC credentials for auth %p\n", auth);
for (i = 0; i < RPC_CREDCACHE_NR; i++) {
- list_for_each_safe(pos, next, &auth->au_credcache[i]) {
- cred = list_entry(pos, struct rpc_cred, cr_hash);
- rpcauth_prune_expired(cred, free);
+ hlist_for_each_safe(pos, next, &cache->hashtable[i]) {
+ cred = hlist_entry(pos, struct rpc_cred, cr_hash);
+ rpcauth_prune_expired(auth, cred, free);
}
}
- auth->au_nextgc = jiffies + auth->au_expire;
+ cache->nextgc = jiffies + cache->expire;
}
/*
@@ -199,8 +187,9 @@ struct rpc_cred *
rpcauth_lookup_credcache(struct rpc_auth *auth, struct auth_cred * acred,
int taskflags)
{
- LIST_HEAD(free);
- struct list_head *pos, *next;
+ struct rpc_cred_cache *cache = auth->au_credcache;
+ HLIST_HEAD(free);
+ struct hlist_node *pos, *next;
struct rpc_cred *new = NULL,
*cred = NULL;
int nr = 0;
@@ -209,28 +198,26 @@ rpcauth_lookup_credcache(struct rpc_auth *auth, struct auth_cred * acred,
nr = acred->uid & RPC_CREDCACHE_MASK;
retry:
spin_lock(&rpc_credcache_lock);
- if (time_before(auth->au_nextgc, jiffies))
+ if (time_before(cache->nextgc, jiffies))
rpcauth_gc_credcache(auth, &free);
- list_for_each_safe(pos, next, &auth->au_credcache[nr]) {
+ hlist_for_each_safe(pos, next, &cache->hashtable[nr]) {
struct rpc_cred *entry;
- entry = list_entry(pos, struct rpc_cred, cr_hash);
- if (rpcauth_prune_expired(entry, &free))
- continue;
+ entry = hlist_entry(pos, struct rpc_cred, cr_hash);
if (entry->cr_ops->crmatch(acred, entry, taskflags)) {
- list_del(&entry->cr_hash);
+ hlist_del(&entry->cr_hash);
cred = entry;
break;
}
+ rpcauth_prune_expired(auth, entry, &free);
}
if (new) {
if (cred)
- list_add(&new->cr_hash, &free);
+ hlist_add_head(&new->cr_hash, &free);
else
cred = new;
}
if (cred) {
- list_add(&cred->cr_hash, &auth->au_credcache[nr]);
- cred->cr_auth = auth;
+ hlist_add_head(&cred->cr_hash, &cache->hashtable[nr]);
get_rpccred(cred);
}
spin_unlock(&rpc_credcache_lock);
@@ -239,12 +226,13 @@ retry:
if (!cred) {
new = auth->au_ops->crcreate(auth, acred, taskflags);
- if (new) {
+ if (!IS_ERR(new)) {
#ifdef RPC_DEBUG
new->cr_magic = RPCAUTH_CRED_MAGIC;
#endif
goto retry;
- }
+ } else
+ cred = new;
}
return (struct rpc_cred *) cred;
@@ -253,18 +241,18 @@ retry:
struct rpc_cred *
rpcauth_lookupcred(struct rpc_auth *auth, int taskflags)
{
- struct auth_cred acred;
+ struct auth_cred acred = {
+ .uid = current->fsuid,
+ .gid = current->fsgid,
+ .group_info = current->group_info,
+ };
struct rpc_cred *ret;
- get_group_info(current->group_info);
- acred.uid = current->fsuid;
- acred.gid = current->fsgid;
- acred.group_info = current->group_info;
-
dprintk("RPC: looking up %s cred\n",
auth->au_ops->au_name);
- ret = rpcauth_lookup_credcache(auth, &acred, taskflags);
- put_group_info(current->group_info);
+ get_group_info(acred.group_info);
+ ret = auth->au_ops->lookup_cred(auth, &acred, taskflags);
+ put_group_info(acred.group_info);
return ret;
}
@@ -272,21 +260,22 @@ struct rpc_cred *
rpcauth_bindcred(struct rpc_task *task)
{
struct rpc_auth *auth = task->tk_auth;
- struct auth_cred acred;
+ struct auth_cred acred = {
+ .uid = current->fsuid,
+ .gid = current->fsgid,
+ .group_info = current->group_info,
+ };
struct rpc_cred *ret;
- get_group_info(current->group_info);
- acred.uid = current->fsuid;
- acred.gid = current->fsgid;
- acred.group_info = current->group_info;
-
dprintk("RPC: %4d looking up %s cred\n",
task->tk_pid, task->tk_auth->au_ops->au_name);
- task->tk_msg.rpc_cred = rpcauth_lookup_credcache(auth, &acred, task->tk_flags);
- if (task->tk_msg.rpc_cred == 0)
- task->tk_status = -ENOMEM;
- ret = task->tk_msg.rpc_cred;
- put_group_info(current->group_info);
+ get_group_info(acred.group_info);
+ ret = auth->au_ops->lookup_cred(auth, &acred, task->tk_flags);
+ if (!IS_ERR(ret))
+ task->tk_msg.rpc_cred = ret;
+ else
+ task->tk_status = PTR_ERR(ret);
+ put_group_info(acred.group_info);
return ret;
}
@@ -302,16 +291,10 @@ rpcauth_holdcred(struct rpc_task *task)
void
put_rpccred(struct rpc_cred *cred)
{
- if (!atomic_dec_and_lock(&cred->cr_count, &rpc_credcache_lock))
- return;
-
- if (list_empty(&cred->cr_hash)) {
- spin_unlock(&rpc_credcache_lock);
- rpcauth_crdestroy(cred);
+ cred->cr_expire = jiffies;
+ if (!atomic_dec_and_test(&cred->cr_count))
return;
- }
- cred->cr_expire = jiffies + cred->cr_auth->au_expire;
- spin_unlock(&rpc_credcache_lock);
+ cred->cr_ops->crdestroy(cred);
}
void
@@ -335,8 +318,7 @@ rpcauth_marshcred(struct rpc_task *task, u32 *p)
dprintk("RPC: %4d marshaling %s cred %p\n",
task->tk_pid, auth->au_ops->au_name, cred);
- return cred->cr_ops->crmarshal(task, p,
- task->tk_flags & RPC_CALL_REALUID);
+ return cred->cr_ops->crmarshal(task, p);
}
u32 *
@@ -357,7 +339,7 @@ rpcauth_wrap_req(struct rpc_task *task, kxdrproc_t encode, void *rqstp,
struct rpc_cred *cred = task->tk_msg.rpc_cred;
dprintk("RPC: %4d using %s cred %p to wrap rpc data\n",
- task->tk_pid, cred->cr_auth->au_ops->au_name, cred);
+ task->tk_pid, cred->cr_ops->cr_name, cred);
if (cred->cr_ops->crwrap_req)
return cred->cr_ops->crwrap_req(task, encode, rqstp, data, obj);
/* By default, we encode the arguments normally. */
@@ -371,7 +353,7 @@ rpcauth_unwrap_resp(struct rpc_task *task, kxdrproc_t decode, void *rqstp,
struct rpc_cred *cred = task->tk_msg.rpc_cred;
dprintk("RPC: %4d using %s cred %p to unwrap rpc data\n",
- task->tk_pid, cred->cr_auth->au_ops->au_name, cred);
+ task->tk_pid, cred->cr_ops->cr_name, cred);
if (cred->cr_ops->crunwrap_resp)
return cred->cr_ops->crunwrap_resp(task, decode, rqstp,
data, obj);
@@ -384,11 +366,14 @@ rpcauth_refreshcred(struct rpc_task *task)
{
struct rpc_auth *auth = task->tk_auth;
struct rpc_cred *cred = task->tk_msg.rpc_cred;
+ int err;
dprintk("RPC: %4d refreshing %s cred %p\n",
task->tk_pid, auth->au_ops->au_name, cred);
- task->tk_status = cred->cr_ops->crrefresh(task);
- return task->tk_status;
+ err = cred->cr_ops->crrefresh(task);
+ if (err < 0)
+ task->tk_status = err;
+ return err;
}
void
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index 62960a5603e84..a33b627cbef4b 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -85,7 +85,9 @@ static DEFINE_RWLOCK(gss_ctx_lock);
struct gss_auth {
struct rpc_auth rpc_auth;
struct gss_api_mech *mech;
+ enum rpc_gss_svc service;
struct list_head upcalls;
+ struct rpc_clnt *client;
struct dentry *dentry;
char path[48];
spinlock_t lock;
@@ -175,42 +177,34 @@ gss_cred_is_uptodate_ctx(struct rpc_cred *cred)
return res;
}
-static inline int
-simple_get_bytes(char **ptr, const char *end, void *res, int len)
+static const void *
+simple_get_bytes(const void *p, const void *end, void *res, size_t len)
{
- char *p, *q;
- p = *ptr;
- q = p + len;
- if (q > end || q < p)
- return -1;
+ const void *q = (const void *)((const char *)p + len);
+ if (unlikely(q > end || q < p))
+ return ERR_PTR(-EFAULT);
memcpy(res, p, len);
- *ptr = q;
- return 0;
-}
-
-static inline int
-simple_get_netobj(char **ptr, const char *end, struct xdr_netobj *res)
-{
- char *p, *q;
- p = *ptr;
- if (simple_get_bytes(&p, end, &res->len, sizeof(res->len)))
- return -1;
- q = p + res->len;
- if (q > end || q < p)
- return -1;
- res->data = p;
- *ptr = q;
- return 0;
+ return q;
}
-static int
-dup_netobj(struct xdr_netobj *source, struct xdr_netobj *dest)
+static inline const void *
+simple_get_netobj(const void *p, const void *end, struct xdr_netobj *dest)
{
- dest->len = source->len;
- if (!(dest->data = kmalloc(dest->len, GFP_KERNEL)))
- return -1;
- memcpy(dest->data, source->data, dest->len);
- return 0;
+ const void *q;
+ unsigned int len;
+
+ p = simple_get_bytes(p, end, &len, sizeof(len));
+ if (IS_ERR(p))
+ return p;
+ q = (const void *)((const char *)p + len);
+ if (unlikely(q > end || q < p))
+ return ERR_PTR(-EFAULT);
+ dest->data = kmalloc(len, GFP_KERNEL);
+ if (unlikely(dest->data == NULL))
+ return ERR_PTR(-ENOMEM);
+ dest->len = len;
+ memcpy(dest->data, p, len);
+ return q;
}
static struct gss_cl_ctx *
@@ -226,74 +220,84 @@ gss_cred_get_ctx(struct rpc_cred *cred)
return ctx;
}
-static int
-gss_parse_init_downcall(struct gss_api_mech *gm, struct xdr_netobj *buf,
- struct gss_cl_ctx **gc, uid_t *uid, int *gss_err)
+static struct gss_cl_ctx *
+gss_alloc_context(void)
{
- char *end = buf->data + buf->len;
- char *p = buf->data;
struct gss_cl_ctx *ctx;
- struct xdr_netobj tmp_buf;
+
+ ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
+ if (ctx != NULL) {
+ memset(ctx, 0, sizeof(*ctx));
+ ctx->gc_proc = RPC_GSS_PROC_DATA;
+ ctx->gc_seq = 1; /* NetApp 6.4R1 doesn't accept seq. no. 0 */
+ spin_lock_init(&ctx->gc_seq_lock);
+ atomic_set(&ctx->count,1);
+ }
+ return ctx;
+}
+
+#define GSSD_MIN_TIMEOUT (60 * 60)
+static const void *
+gss_fill_context(const void *p, const void *end, struct gss_cl_ctx *ctx, struct gss_api_mech *gm)
+{
+ const void *q;
+ unsigned int seclen;
unsigned int timeout;
- int err = -EIO;
+ u32 window_size;
+ int ret;
- if (!(ctx = kmalloc(sizeof(*ctx), GFP_KERNEL))) {
- err = -ENOMEM;
+ /* First unsigned int gives the lifetime (in seconds) of the cred */
+ p = simple_get_bytes(p, end, &timeout, sizeof(timeout));
+ if (IS_ERR(p))
goto err;
- }
- ctx->gc_proc = RPC_GSS_PROC_DATA;
- ctx->gc_seq = 1; /* NetApp 6.4R1 doesn't accept seq. no. 0 */
- spin_lock_init(&ctx->gc_seq_lock);
- atomic_set(&ctx->count,1);
-
- if (simple_get_bytes(&p, end, uid, sizeof(*uid)))
- goto err_free_ctx;
- /* FIXME: discarded timeout for now */
- if (simple_get_bytes(&p, end, &timeout, sizeof(timeout)))
- goto err_free_ctx;
- *gss_err = 0;
- if (simple_get_bytes(&p, end, &ctx->gc_win, sizeof(ctx->gc_win)))
- goto err_free_ctx;
+ if (timeout == 0)
+ timeout = GSSD_MIN_TIMEOUT;
+ ctx->gc_expiry = jiffies + (unsigned long)timeout * HZ * 3 / 4;
+ /* Sequence number window. Determines the maximum number of simultaneous requests */
+ p = simple_get_bytes(p, end, &window_size, sizeof(window_size));
+ if (IS_ERR(p))
+ goto err;
+ ctx->gc_win = window_size;
/* gssd signals an error by passing ctx->gc_win = 0: */
- if (!ctx->gc_win) {
- /* in which case the next int is an error code: */
- if (simple_get_bytes(&p, end, gss_err, sizeof(*gss_err)))
- goto err_free_ctx;
- err = 0;
- goto err_free_ctx;
+ if (ctx->gc_win == 0) {
+ /* in which case, p points to an error code which we ignore */
+ p = ERR_PTR(-EACCES);
+ goto err;
}
- if (simple_get_netobj(&p, end, &tmp_buf))
- goto err_free_ctx;
- if (dup_netobj(&tmp_buf, &ctx->gc_wire_ctx)) {
- err = -ENOMEM;
- goto err_free_ctx;
+ /* copy the opaque wire context */
+ p = simple_get_netobj(p, end, &ctx->gc_wire_ctx);
+ if (IS_ERR(p))
+ goto err;
+ /* import the opaque security context */
+ p = simple_get_bytes(p, end, &seclen, sizeof(seclen));
+ if (IS_ERR(p))
+ goto err;
+ q = (const void *)((const char *)p + seclen);
+ if (unlikely(q > end || q < p)) {
+ p = ERR_PTR(-EFAULT);
+ goto err;
}
- if (simple_get_netobj(&p, end, &tmp_buf))
- goto err_free_wire_ctx;
- if (p != end)
- goto err_free_wire_ctx;
- if (gss_import_sec_context(&tmp_buf, gm, &ctx->gc_gss_ctx))
- goto err_free_wire_ctx;
- *gc = ctx;
- return 0;
-err_free_wire_ctx:
- kfree(ctx->gc_wire_ctx.data);
-err_free_ctx:
- kfree(ctx);
+ ret = gss_import_sec_context(p, seclen, gm, &ctx->gc_gss_ctx);
+ if (ret < 0) {
+ p = ERR_PTR(ret);
+ goto err;
+ }
+ return q;
err:
- *gc = NULL;
- dprintk("RPC: gss_parse_init_downcall returning %d\n", err);
- return err;
+ dprintk("RPC: gss_fill_context returning %ld\n", -PTR_ERR(p));
+ return p;
}
struct gss_upcall_msg {
+ atomic_t count;
+ uid_t uid;
struct rpc_pipe_msg msg;
struct list_head list;
struct gss_auth *auth;
- struct rpc_wait_queue waitq;
- uid_t uid;
- atomic_t count;
+ struct rpc_wait_queue rpc_waitqueue;
+ wait_queue_head_t waitqueue;
+ struct gss_cl_ctx *ctx;
};
static void
@@ -302,6 +306,8 @@ gss_release_msg(struct gss_upcall_msg *gss_msg)
if (!atomic_dec_and_test(&gss_msg->count))
return;
BUG_ON(!list_empty(&gss_msg->list));
+ if (gss_msg->ctx != NULL)
+ gss_put_ctx(gss_msg->ctx);
kfree(gss_msg);
}
@@ -320,16 +326,34 @@ __gss_find_upcall(struct gss_auth *gss_auth, uid_t uid)
return NULL;
}
+/* Try to add a upcall to the pipefs queue.
+ * If an upcall owned by our uid already exists, then we return a reference
+ * to that upcall instead of adding the new upcall.
+ */
+static inline struct gss_upcall_msg *
+gss_add_msg(struct gss_auth *gss_auth, struct gss_upcall_msg *gss_msg)
+{
+ struct gss_upcall_msg *old;
+
+ spin_lock(&gss_auth->lock);
+ old = __gss_find_upcall(gss_auth, gss_msg->uid);
+ if (old == NULL) {
+ atomic_inc(&gss_msg->count);
+ list_add(&gss_msg->list, &gss_auth->upcalls);
+ } else
+ gss_msg = old;
+ spin_unlock(&gss_auth->lock);
+ return gss_msg;
+}
+
static void
__gss_unhash_msg(struct gss_upcall_msg *gss_msg)
{
if (list_empty(&gss_msg->list))
return;
list_del_init(&gss_msg->list);
- if (gss_msg->msg.errno < 0)
- rpc_wake_up_status(&gss_msg->waitq, gss_msg->msg.errno);
- else
- rpc_wake_up(&gss_msg->waitq);
+ rpc_wake_up_status(&gss_msg->rpc_waitqueue, gss_msg->msg.errno);
+ wake_up_all(&gss_msg->waitqueue);
atomic_dec(&gss_msg->count);
}
@@ -343,76 +367,139 @@ gss_unhash_msg(struct gss_upcall_msg *gss_msg)
spin_unlock(&gss_auth->lock);
}
-static int
-gss_upcall(struct rpc_clnt *clnt, struct rpc_task *task, struct rpc_cred *cred)
+static void
+gss_upcall_callback(struct rpc_task *task)
{
- struct gss_auth *gss_auth = container_of(clnt->cl_auth,
- struct gss_auth, rpc_auth);
- struct gss_upcall_msg *gss_msg, *gss_new = NULL;
- struct rpc_pipe_msg *msg;
- struct dentry *dentry = gss_auth->dentry;
- uid_t uid = cred->cr_uid;
- int res = 0;
+ struct gss_cred *gss_cred = container_of(task->tk_msg.rpc_cred,
+ struct gss_cred, gc_base);
+ struct gss_upcall_msg *gss_msg = gss_cred->gc_upcall;
- dprintk("RPC: %4u gss_upcall for uid %u\n", task->tk_pid, uid);
+ BUG_ON(gss_msg == NULL);
+ if (gss_msg->ctx)
+ gss_cred_set_ctx(task->tk_msg.rpc_cred, gss_get_ctx(gss_msg->ctx));
+ else
+ task->tk_status = gss_msg->msg.errno;
+ spin_lock(&gss_msg->auth->lock);
+ gss_cred->gc_upcall = NULL;
+ rpc_wake_up_status(&gss_msg->rpc_waitqueue, gss_msg->msg.errno);
+ spin_unlock(&gss_msg->auth->lock);
+ gss_release_msg(gss_msg);
+}
-retry:
- spin_lock(&gss_auth->lock);
- gss_msg = __gss_find_upcall(gss_auth, uid);
- if (gss_msg)
- goto out_sleep;
- if (gss_new == NULL) {
- spin_unlock(&gss_auth->lock);
- gss_new = kmalloc(sizeof(*gss_new), GFP_KERNEL);
- if (!gss_new) {
- dprintk("RPC: %4u gss_upcall -ENOMEM\n", task->tk_pid);
- return -ENOMEM;
+static inline struct gss_upcall_msg *
+gss_alloc_msg(struct gss_auth *gss_auth, uid_t uid)
+{
+ struct gss_upcall_msg *gss_msg;
+
+ gss_msg = kmalloc(sizeof(*gss_msg), GFP_KERNEL);
+ if (gss_msg != NULL) {
+ memset(gss_msg, 0, sizeof(*gss_msg));
+ INIT_LIST_HEAD(&gss_msg->list);
+ rpc_init_wait_queue(&gss_msg->rpc_waitqueue, "RPCSEC_GSS upcall waitq");
+ init_waitqueue_head(&gss_msg->waitqueue);
+ atomic_set(&gss_msg->count, 1);
+ gss_msg->msg.data = &gss_msg->uid;
+ gss_msg->msg.len = sizeof(gss_msg->uid);
+ gss_msg->uid = uid;
+ gss_msg->auth = gss_auth;
+ }
+ return gss_msg;
+}
+
+static struct gss_upcall_msg *
+gss_setup_upcall(struct rpc_clnt *clnt, struct gss_auth *gss_auth, struct rpc_cred *cred)
+{
+ struct gss_upcall_msg *gss_new, *gss_msg;
+
+ gss_new = gss_alloc_msg(gss_auth, cred->cr_uid);
+ if (gss_new == NULL)
+ return ERR_PTR(-ENOMEM);
+ gss_msg = gss_add_msg(gss_auth, gss_new);
+ if (gss_msg == gss_new) {
+ int res = rpc_queue_upcall(gss_auth->dentry->d_inode, &gss_new->msg);
+ if (res) {
+ gss_unhash_msg(gss_new);
+ gss_msg = ERR_PTR(res);
}
- goto retry;
+ } else
+ gss_release_msg(gss_new);
+ return gss_msg;
+}
+
+static inline int
+gss_refresh_upcall(struct rpc_task *task)
+{
+ struct rpc_cred *cred = task->tk_msg.rpc_cred;
+ struct gss_auth *gss_auth = container_of(task->tk_client->cl_auth,
+ struct gss_auth, rpc_auth);
+ struct gss_cred *gss_cred = container_of(cred,
+ struct gss_cred, gc_base);
+ struct gss_upcall_msg *gss_msg;
+ int err = 0;
+
+ dprintk("RPC: %4u gss_refresh_upcall for uid %u\n", task->tk_pid, cred->cr_uid);
+ gss_msg = gss_setup_upcall(task->tk_client, gss_auth, cred);
+ if (IS_ERR(gss_msg)) {
+ err = PTR_ERR(gss_msg);
+ goto out;
}
- gss_msg = gss_new;
- memset(gss_new, 0, sizeof(*gss_new));
- INIT_LIST_HEAD(&gss_new->list);
- rpc_init_wait_queue(&gss_new->waitq, "RPCSEC_GSS upcall waitq");
- atomic_set(&gss_new->count, 2);
- msg = &gss_new->msg;
- msg->data = &gss_new->uid;
- msg->len = sizeof(gss_new->uid);
- gss_new->uid = uid;
- gss_new->auth = gss_auth;
- list_add(&gss_new->list, &gss_auth->upcalls);
- gss_new = NULL;
- /* Has someone updated the credential behind our back? */
- if (!gss_cred_is_uptodate_ctx(cred)) {
- /* No, so do upcall and sleep */
+ spin_lock(&gss_auth->lock);
+ if (gss_cred->gc_upcall != NULL)
+ rpc_sleep_on(&gss_cred->gc_upcall->rpc_waitqueue, task, NULL, NULL);
+ else if (gss_msg->ctx == NULL && gss_msg->msg.errno >= 0) {
task->tk_timeout = 0;
- rpc_sleep_on(&gss_msg->waitq, task, NULL, NULL);
- spin_unlock(&gss_auth->lock);
- res = rpc_queue_upcall(dentry->d_inode, msg);
- if (res)
- gss_unhash_msg(gss_msg);
- } else {
- /* Yes, so cancel upcall */
- __gss_unhash_msg(gss_msg);
+ gss_cred->gc_upcall = gss_msg;
+ /* gss_upcall_callback will release the reference to gss_upcall_msg */
+ atomic_inc(&gss_msg->count);
+ rpc_sleep_on(&gss_msg->rpc_waitqueue, task, gss_upcall_callback, NULL);
+ } else
+ err = gss_msg->msg.errno;
+ spin_unlock(&gss_auth->lock);
+ gss_release_msg(gss_msg);
+out:
+ dprintk("RPC: %4u gss_refresh_upcall for uid %u result %d\n", task->tk_pid,
+ cred->cr_uid, err);
+ return err;
+}
+
+static inline int
+gss_create_upcall(struct gss_auth *gss_auth, struct gss_cred *gss_cred)
+{
+ struct rpc_cred *cred = &gss_cred->gc_base;
+ struct gss_upcall_msg *gss_msg;
+ DEFINE_WAIT(wait);
+ int err = 0;
+
+ dprintk("RPC: gss_upcall for uid %u\n", cred->cr_uid);
+ gss_msg = gss_setup_upcall(gss_auth->client, gss_auth, cred);
+ if (IS_ERR(gss_msg)) {
+ err = PTR_ERR(gss_msg);
+ goto out;
+ }
+ for (;;) {
+ prepare_to_wait(&gss_msg->waitqueue, &wait, TASK_INTERRUPTIBLE);
+ spin_lock(&gss_auth->lock);
+ if (gss_msg->ctx != NULL || gss_msg->msg.errno < 0) {
+ spin_unlock(&gss_auth->lock);
+ break;
+ }
spin_unlock(&gss_auth->lock);
+ if (signalled()) {
+ err = -ERESTARTSYS;
+ goto out_intr;
+ }
+ schedule();
}
+ if (gss_msg->ctx)
+ gss_cred_set_ctx(cred, gss_get_ctx(gss_msg->ctx));
+ else
+ err = gss_msg->msg.errno;
+out_intr:
+ finish_wait(&gss_msg->waitqueue, &wait);
gss_release_msg(gss_msg);
- dprintk("RPC: %4u gss_upcall for uid %u result %d\n", task->tk_pid,
- uid, res);
- return res;
-out_sleep:
- task->tk_timeout = 0;
- rpc_sleep_on(&gss_msg->waitq, task, NULL, NULL);
- spin_unlock(&gss_auth->lock);
- dprintk("RPC: %4u gss_upcall sleeping\n", task->tk_pid);
- if (gss_new)
- kfree(gss_new);
- /* Note: we drop the reference here: we are automatically removed
- * from the queue when we're woken up, and we should in any case
- * have no further responsabilities w.r.t. the upcall.
- */
- gss_release_msg(gss_msg);
- return 0;
+out:
+ dprintk("RPC: gss_create_upcall for uid %u result %d\n", cred->cr_uid, err);
+ return err;
}
static ssize_t
@@ -441,68 +528,75 @@ gss_pipe_upcall(struct file *filp, struct rpc_pipe_msg *msg,
static ssize_t
gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
{
- struct xdr_netobj obj = {
- .len = mlen,
- };
- struct inode *inode = filp->f_dentry->d_inode;
- struct rpc_inode *rpci = RPC_I(inode);
+ const void *p, *end;
+ void *buf;
struct rpc_clnt *clnt;
- struct rpc_auth *auth;
struct gss_auth *gss_auth;
- struct gss_api_mech *mech;
- struct auth_cred acred = { 0 };
struct rpc_cred *cred;
struct gss_upcall_msg *gss_msg;
- struct gss_cl_ctx *ctx = NULL;
- ssize_t left;
- int err;
- int gss_err;
+ struct gss_cl_ctx *ctx;
+ uid_t uid;
+ int err = -EFBIG;
if (mlen > MSG_BUF_MAXSIZE)
- return -EFBIG;
- obj.data = kmalloc(mlen, GFP_KERNEL);
- if (!obj.data)
- return -ENOMEM;
- left = copy_from_user(obj.data, src, mlen);
- if (left) {
- err = -EFAULT;
goto out;
- }
- clnt = rpci->private;
- atomic_inc(&clnt->cl_users);
- auth = clnt->cl_auth;
- gss_auth = container_of(auth, struct gss_auth, rpc_auth);
- mech = gss_auth->mech;
- err = gss_parse_init_downcall(mech, &obj, &ctx, &acred.uid, &gss_err);
- if (err)
+ err = -ENOMEM;
+ buf = kmalloc(mlen, GFP_KERNEL);
+ if (!buf)
+ goto out;
+
+ clnt = RPC_I(filp->f_dentry->d_inode)->private;
+ err = -EFAULT;
+ if (copy_from_user(buf, src, mlen))
goto err;
- cred = rpcauth_lookup_credcache(auth, &acred, 0);
- if (!cred)
+
+ end = (const void *)((char *)buf + mlen);
+ p = simple_get_bytes(buf, end, &uid, sizeof(uid));
+ if (IS_ERR(p)) {
+ err = PTR_ERR(p);
goto err;
- if (gss_err)
- cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
- else
- gss_cred_set_ctx(cred, ctx);
+ }
+
+ err = -ENOMEM;
+ ctx = gss_alloc_context();
+ if (ctx == NULL)
+ goto err;
+ err = 0;
+ gss_auth = container_of(clnt->cl_auth, struct gss_auth, rpc_auth);
+ p = gss_fill_context(p, end, ctx, gss_auth->mech);
+ if (IS_ERR(p)) {
+ err = PTR_ERR(p);
+ if (err != -EACCES)
+ goto err_put_ctx;
+ }
spin_lock(&gss_auth->lock);
- gss_msg = __gss_find_upcall(gss_auth, acred.uid);
+ gss_msg = __gss_find_upcall(gss_auth, uid);
if (gss_msg) {
- if (gss_err)
- gss_msg->msg.errno = -EACCES;
+ if (err == 0 && gss_msg->ctx == NULL)
+ gss_msg->ctx = gss_get_ctx(ctx);
+ gss_msg->msg.errno = err;
__gss_unhash_msg(gss_msg);
spin_unlock(&gss_auth->lock);
gss_release_msg(gss_msg);
- } else
+ } else {
+ struct auth_cred acred = { .uid = uid };
spin_unlock(&gss_auth->lock);
- rpc_release_client(clnt);
- kfree(obj.data);
+ cred = rpcauth_lookup_credcache(clnt->cl_auth, &acred, 0);
+ if (IS_ERR(cred)) {
+ err = PTR_ERR(cred);
+ goto err_put_ctx;
+ }
+ gss_cred_set_ctx(cred, gss_get_ctx(ctx));
+ }
+ gss_put_ctx(ctx);
+ kfree(buf);
dprintk("RPC: gss_pipe_downcall returning length %Zu\n", mlen);
return mlen;
+err_put_ctx:
+ gss_put_ctx(ctx);
err:
- if (ctx)
- gss_destroy_ctx(ctx);
- rpc_release_client(clnt);
+ kfree(buf);
out:
- kfree(obj.data);
dprintk("RPC: gss_pipe_downcall returning %d\n", err);
return err;
}
@@ -569,24 +663,32 @@ gss_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor)
dprintk("RPC: creating GSS authenticator for client %p\n",clnt);
+ if (!try_module_get(THIS_MODULE))
+ return NULL;
if (!(gss_auth = kmalloc(sizeof(*gss_auth), GFP_KERNEL)))
goto out_dec;
+ gss_auth->client = clnt;
gss_auth->mech = gss_mech_get_by_pseudoflavor(flavor);
if (!gss_auth->mech) {
printk(KERN_WARNING "%s: Pseudoflavor %d not found!",
__FUNCTION__, flavor);
goto err_free;
}
+ gss_auth->service = gss_pseudoflavor_to_service(gss_auth->mech, flavor);
+ /* FIXME: Will go away once privacy support is merged in */
+ if (gss_auth->service == RPC_GSS_SVC_PRIVACY)
+ gss_auth->service = RPC_GSS_SVC_INTEGRITY;
INIT_LIST_HEAD(&gss_auth->upcalls);
spin_lock_init(&gss_auth->lock);
auth = &gss_auth->rpc_auth;
auth->au_cslack = GSS_CRED_SLACK >> 2;
auth->au_rslack = GSS_VERF_SLACK >> 2;
- auth->au_expire = GSS_CRED_EXPIRE;
auth->au_ops = &authgss_ops;
auth->au_flavor = flavor;
+ atomic_set(&auth->au_count, 1);
- rpcauth_init_credcache(auth);
+ if (rpcauth_init_credcache(auth, GSS_CRED_EXPIRE) < 0)
+ goto err_put_mech;
snprintf(gss_auth->path, sizeof(gss_auth->path), "%s/%s",
clnt->cl_pathname,
@@ -601,6 +703,7 @@ err_put_mech:
err_free:
kfree(gss_auth);
out_dec:
+ module_put(THIS_MODULE);
return NULL;
}
@@ -617,6 +720,8 @@ gss_destroy(struct rpc_auth *auth)
gss_mech_put(gss_auth->mech);
rpcauth_free_credcache(auth);
+ kfree(gss_auth);
+ module_put(THIS_MODULE);
}
/* gss_destroy_cred (and gss_destroy_ctx) are used to clean up after failure
@@ -630,19 +735,14 @@ gss_destroy_ctx(struct gss_cl_ctx *ctx)
if (ctx->gc_gss_ctx)
gss_delete_sec_context(&ctx->gc_gss_ctx);
- if (ctx->gc_wire_ctx.len > 0) {
- kfree(ctx->gc_wire_ctx.data);
- ctx->gc_wire_ctx.len = 0;
- }
-
+ kfree(ctx->gc_wire_ctx.data);
kfree(ctx);
-
}
static void
gss_destroy_cred(struct rpc_cred *rc)
{
- struct gss_cred *cred = (struct gss_cred *)rc;
+ struct gss_cred *cred = container_of(rc, struct gss_cred, gc_base);
dprintk("RPC: gss_destroy_cred \n");
@@ -651,10 +751,21 @@ gss_destroy_cred(struct rpc_cred *rc)
kfree(cred);
}
+/*
+ * Lookup RPCSEC_GSS cred for the current process
+ */
+static struct rpc_cred *
+gss_lookup_cred(struct rpc_auth *auth, struct auth_cred *acred, int taskflags)
+{
+ return rpcauth_lookup_credcache(auth, acred, taskflags);
+}
+
static struct rpc_cred *
gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int taskflags)
{
+ struct gss_auth *gss_auth = container_of(auth, struct gss_auth, rpc_auth);
struct gss_cred *cred = NULL;
+ int err = -ENOMEM;
dprintk("RPC: gss_create_cred for uid %d, flavor %d\n",
acred->uid, auth->au_flavor);
@@ -663,7 +774,7 @@ gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int taskflags)
goto out_err;
memset(cred, 0, sizeof(*cred));
- atomic_set(&cred->gc_count, 0);
+ atomic_set(&cred->gc_count, 1);
cred->gc_uid = acred->uid;
/*
* Note: in order to force a call to call_refresh(), we deliberately
@@ -671,19 +782,27 @@ gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int taskflags)
*/
cred->gc_flags = 0;
cred->gc_base.cr_ops = &gss_credops;
- cred->gc_flavor = auth->au_flavor;
+ cred->gc_service = gss_auth->service;
+ err = gss_create_upcall(gss_auth, cred);
+ if (err < 0)
+ goto out_err;
- return (struct rpc_cred *) cred;
+ return &cred->gc_base;
out_err:
- dprintk("RPC: gss_create_cred failed\n");
- if (cred) gss_destroy_cred((struct rpc_cred *)cred);
- return NULL;
+ dprintk("RPC: gss_create_cred failed with error %d\n", err);
+ if (cred) gss_destroy_cred(&cred->gc_base);
+ return ERR_PTR(err);
}
static int
gss_match(struct auth_cred *acred, struct rpc_cred *rc, int taskflags)
{
+ struct gss_cred *gss_cred = container_of(rc, struct gss_cred, gc_base);
+
+ /* Don't match with creds that have expired. */
+ if (gss_cred->gc_ctx && time_after(jiffies, gss_cred->gc_ctx->gc_expiry))
+ return 0;
return (rc->cr_uid == acred->uid);
}
@@ -692,7 +811,7 @@ gss_match(struct auth_cred *acred, struct rpc_cred *rc, int taskflags)
* Maybe we should keep a cached credential for performance reasons.
*/
static u32 *
-gss_marshal(struct rpc_task *task, u32 *p, int ruid)
+gss_marshal(struct rpc_task *task, u32 *p)
{
struct rpc_cred *cred = task->tk_msg.rpc_cred;
struct gss_cred *gss_cred = container_of(cred, struct gss_cred,
@@ -704,20 +823,12 @@ gss_marshal(struct rpc_task *task, u32 *p, int ruid)
struct xdr_netobj mic;
struct kvec iov;
struct xdr_buf verf_buf;
- u32 service;
dprintk("RPC: %4u gss_marshal\n", task->tk_pid);
*p++ = htonl(RPC_AUTH_GSS);
cred_len = p++;
- service = gss_pseudoflavor_to_service(ctx->gc_gss_ctx->mech_type,
- gss_cred->gc_flavor);
- if (service == 0) {
- dprintk("RPC: %4u Bad pseudoflavor %d in gss_marshal\n",
- task->tk_pid, gss_cred->gc_flavor);
- goto out_put_ctx;
- }
spin_lock(&ctx->gc_seq_lock);
req->rq_seqno = ctx->gc_seq++;
spin_unlock(&ctx->gc_seq_lock);
@@ -725,7 +836,7 @@ gss_marshal(struct rpc_task *task, u32 *p, int ruid)
*p++ = htonl((u32) RPC_GSS_VERSION);
*p++ = htonl((u32) ctx->gc_proc);
*p++ = htonl((u32) req->rq_seqno);
- *p++ = htonl((u32) service);
+ *p++ = htonl((u32) gss_cred->gc_service);
p = xdr_encode_netobj(p, &ctx->gc_wire_ctx);
*cred_len = htonl((p - (cred_len + 1)) << 2);
@@ -765,11 +876,9 @@ out_put_ctx:
static int
gss_refresh(struct rpc_task *task)
{
- struct rpc_clnt *clnt = task->tk_client;
- struct rpc_cred *cred = task->tk_msg.rpc_cred;
- if (!gss_cred_is_uptodate_ctx(cred))
- return gss_upcall(clnt, task, cred);
+ if (!gss_cred_is_uptodate_ctx(task->tk_msg.rpc_cred))
+ return gss_refresh_upcall(task);
return 0;
}
@@ -785,7 +894,6 @@ gss_validate(struct rpc_task *task, u32 *p)
struct xdr_buf verf_buf;
struct xdr_netobj mic;
u32 flav,len;
- u32 service;
u32 maj_stat;
dprintk("RPC: %4u gss_validate\n", task->tk_pid);
@@ -807,9 +915,7 @@ gss_validate(struct rpc_task *task, u32 *p)
cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
if (maj_stat)
goto out_bad;
- service = gss_pseudoflavor_to_service(ctx->gc_gss_ctx->mech_type,
- gss_cred->gc_flavor);
- switch (service) {
+ switch (gss_cred->gc_service) {
case RPC_GSS_SVC_NONE:
/* verifier data, flavor, length: */
task->tk_auth->au_rslack = XDR_QUADLEN(len) + 2;
@@ -818,7 +924,7 @@ gss_validate(struct rpc_task *task, u32 *p)
/* verifier data, flavor, length, length, sequence number: */
task->tk_auth->au_rslack = XDR_QUADLEN(len) + 4;
break;
- default:
+ case RPC_GSS_SVC_PRIVACY:
goto out_bad;
}
gss_put_ctx(ctx);
@@ -889,7 +995,6 @@ gss_wrap_req(struct rpc_task *task,
gc_base);
struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred);
int status = -EIO;
- u32 service;
dprintk("RPC: %4u gss_wrap_req\n", task->tk_pid);
if (ctx->gc_proc != RPC_GSS_PROC_DATA) {
@@ -899,19 +1004,16 @@ gss_wrap_req(struct rpc_task *task,
status = encode(rqstp, p, obj);
goto out;
}
- service = gss_pseudoflavor_to_service(ctx->gc_gss_ctx->mech_type,
- gss_cred->gc_flavor);
- switch (service) {
+ switch (gss_cred->gc_service) {
case RPC_GSS_SVC_NONE:
status = encode(rqstp, p, obj);
- goto out;
+ break;
case RPC_GSS_SVC_INTEGRITY:
status = gss_wrap_req_integ(cred, ctx, encode,
rqstp, p, obj);
- goto out;
- case RPC_GSS_SVC_PRIVACY:
- default:
- goto out;
+ break;
+ case RPC_GSS_SVC_PRIVACY:
+ break;
}
out:
gss_put_ctx(ctx);
@@ -966,23 +1068,19 @@ gss_unwrap_resp(struct rpc_task *task,
gc_base);
struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred);
int status = -EIO;
- u32 service;
if (ctx->gc_proc != RPC_GSS_PROC_DATA)
goto out_decode;
- service = gss_pseudoflavor_to_service(ctx->gc_gss_ctx->mech_type,
- gss_cred->gc_flavor);
- switch (service) {
+ switch (gss_cred->gc_service) {
case RPC_GSS_SVC_NONE:
- goto out_decode;
+ break;
case RPC_GSS_SVC_INTEGRITY:
status = gss_unwrap_resp_integ(cred, ctx, rqstp, &p);
if (status)
goto out;
break;
- case RPC_GSS_SVC_PRIVACY:
- default:
- goto out;
+ case RPC_GSS_SVC_PRIVACY:
+ break;
}
out_decode:
status = decode(rqstp, p, obj);
@@ -1001,10 +1099,12 @@ static struct rpc_authops authgss_ops = {
#endif
.create = gss_create,
.destroy = gss_destroy,
+ .lookup_cred = gss_lookup_cred,
.crcreate = gss_create_cred
};
static struct rpc_credops gss_credops = {
+ .cr_name = "AUTH_GSS",
.crdestroy = gss_destroy_cred,
.crmatch = gss_match,
.crmarshal = gss_marshal,
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
index a734dd8695183..cf726510df8e5 100644
--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
+++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
@@ -48,46 +48,48 @@
# define RPCDBG_FACILITY RPCDBG_AUTH
#endif
-static inline int
-get_bytes(char **ptr, const char *end, void *res, int len)
+static const void *
+simple_get_bytes(const void *p, const void *end, void *res, int len)
{
- char *p, *q;
- p = *ptr;
- q = p + len;
- if (q > end || q < p)
- return -1;
+ const void *q = (const void *)((const char *)p + len);
+ if (unlikely(q > end || q < p))
+ return ERR_PTR(-EFAULT);
memcpy(res, p, len);
- *ptr = q;
- return 0;
+ return q;
}
-static inline int
-get_netobj(char **ptr, const char *end, struct xdr_netobj *res)
+static const void *
+simple_get_netobj(const void *p, const void *end, struct xdr_netobj *res)
{
- char *p, *q;
- p = *ptr;
- if (get_bytes(&p, end, &res->len, sizeof(res->len)))
- return -1;
- q = p + res->len;
- if (q > end || q < p)
- return -1;
- if (!(res->data = kmalloc(res->len, GFP_KERNEL)))
- return -1;
- memcpy(res->data, p, res->len);
- *ptr = q;
- return 0;
+ const void *q;
+ unsigned int len;
+
+ p = simple_get_bytes(p, end, &len, sizeof(len));
+ if (IS_ERR(p))
+ return p;
+ q = (const void *)((const char *)p + len);
+ if (unlikely(q > end || q < p))
+ return ERR_PTR(-EFAULT);
+ res->data = kmalloc(len, GFP_KERNEL);
+ if (unlikely(res->data == NULL))
+ return ERR_PTR(-ENOMEM);
+ memcpy(res->data, p, len);
+ res->len = len;
+ return q;
}
-static inline int
-get_key(char **p, char *end, struct crypto_tfm **res)
+static inline const void *
+get_key(const void *p, const void *end, struct crypto_tfm **res)
{
struct xdr_netobj key;
int alg, alg_mode;
char *alg_name;
- if (get_bytes(p, end, &alg, sizeof(alg)))
+ p = simple_get_bytes(p, end, &alg, sizeof(alg));
+ if (IS_ERR(p))
goto out_err;
- if ((get_netobj(p, end, &key)))
+ p = simple_get_netobj(p, end, &key);
+ if (IS_ERR(p))
goto out_err;
switch (alg) {
@@ -105,50 +107,63 @@ get_key(char **p, char *end, struct crypto_tfm **res)
goto out_err_free_tfm;
kfree(key.data);
- return 0;
+ return p;
out_err_free_tfm:
crypto_free_tfm(*res);
out_err_free_key:
kfree(key.data);
+ p = ERR_PTR(-EINVAL);
out_err:
- return -1;
+ return p;
}
-static u32
-gss_import_sec_context_kerberos(struct xdr_netobj *inbuf,
+static int
+gss_import_sec_context_kerberos(const void *p,
+ size_t len,
struct gss_ctx *ctx_id)
{
- char *p = inbuf->data;
- char *end = inbuf->data + inbuf->len;
+ const void *end = (const void *)((const char *)p + len);
struct krb5_ctx *ctx;
if (!(ctx = kmalloc(sizeof(*ctx), GFP_KERNEL)))
goto out_err;
memset(ctx, 0, sizeof(*ctx));
- if (get_bytes(&p, end, &ctx->initiate, sizeof(ctx->initiate)))
+ p = simple_get_bytes(p, end, &ctx->initiate, sizeof(ctx->initiate));
+ if (IS_ERR(p))
goto out_err_free_ctx;
- if (get_bytes(&p, end, &ctx->seed_init, sizeof(ctx->seed_init)))
+ p = simple_get_bytes(p, end, &ctx->seed_init, sizeof(ctx->seed_init));
+ if (IS_ERR(p))
goto out_err_free_ctx;
- if (get_bytes(&p, end, ctx->seed, sizeof(ctx->seed)))
+ p = simple_get_bytes(p, end, ctx->seed, sizeof(ctx->seed));
+ if (IS_ERR(p))
goto out_err_free_ctx;
- if (get_bytes(&p, end, &ctx->signalg, sizeof(ctx->signalg)))
+ p = simple_get_bytes(p, end, &ctx->signalg, sizeof(ctx->signalg));
+ if (IS_ERR(p))
goto out_err_free_ctx;
- if (get_bytes(&p, end, &ctx->sealalg, sizeof(ctx->sealalg)))
+ p = simple_get_bytes(p, end, &ctx->sealalg, sizeof(ctx->sealalg));
+ if (IS_ERR(p))
goto out_err_free_ctx;
- if (get_bytes(&p, end, &ctx->endtime, sizeof(ctx->endtime)))
+ p = simple_get_bytes(p, end, &ctx->endtime, sizeof(ctx->endtime));
+ if (IS_ERR(p))
goto out_err_free_ctx;
- if (get_bytes(&p, end, &ctx->seq_send, sizeof(ctx->seq_send)))
+ p = simple_get_bytes(p, end, &ctx->seq_send, sizeof(ctx->seq_send));
+ if (IS_ERR(p))
goto out_err_free_ctx;
- if (get_netobj(&p, end, &ctx->mech_used))
+ p = simple_get_netobj(p, end, &ctx->mech_used);
+ if (IS_ERR(p))
goto out_err_free_ctx;
- if (get_key(&p, end, &ctx->enc))
+ p = get_key(p, end, &ctx->enc);
+ if (IS_ERR(p))
goto out_err_free_mech;
- if (get_key(&p, end, &ctx->seq))
+ p = get_key(p, end, &ctx->seq);
+ if (IS_ERR(p))
goto out_err_free_key1;
- if (p != end)
+ if (p != end) {
+ p = ERR_PTR(-EFAULT);
goto out_err_free_key2;
+ }
ctx_id->internal_ctx_id = ctx;
dprintk("RPC: Succesfully imported new context.\n");
@@ -163,7 +178,7 @@ out_err_free_mech:
out_err_free_ctx:
kfree(ctx);
out_err:
- return GSS_S_FAILURE;
+ return PTR_ERR(p);
}
static void
diff --git a/net/sunrpc/auth_gss/gss_mech_switch.c b/net/sunrpc/auth_gss/gss_mech_switch.c
index a0db9f5004f10..9dfb68377d694 100644
--- a/net/sunrpc/auth_gss/gss_mech_switch.c
+++ b/net/sunrpc/auth_gss/gss_mech_switch.c
@@ -143,7 +143,7 @@ gss_mech_get(struct gss_api_mech *gm)
EXPORT_SYMBOL(gss_mech_get);
struct gss_api_mech *
-gss_mech_get_by_name(char *name)
+gss_mech_get_by_name(const char *name)
{
struct gss_api_mech *pos, *gm = NULL;
@@ -233,8 +233,8 @@ EXPORT_SYMBOL(gss_mech_put);
/* The mech could probably be determined from the token instead, but it's just
* as easy for now to pass it in. */
-u32
-gss_import_sec_context(struct xdr_netobj *input_token,
+int
+gss_import_sec_context(const void *input_token, size_t bufsize,
struct gss_api_mech *mech,
struct gss_ctx **ctx_id)
{
@@ -244,7 +244,7 @@ gss_import_sec_context(struct xdr_netobj *input_token,
(*ctx_id)->mech_type = gss_mech_get(mech);
return mech->gm_ops
- ->gss_import_sec_context(input_token, *ctx_id);
+ ->gss_import_sec_context(input_token, bufsize, *ctx_id);
}
/* gss_get_mic: compute a mic over message and return mic_token. */
diff --git a/net/sunrpc/auth_gss/gss_spkm3_mech.c b/net/sunrpc/auth_gss/gss_spkm3_mech.c
index fd213dc360939..dad05994c3eb3 100644
--- a/net/sunrpc/auth_gss/gss_spkm3_mech.c
+++ b/net/sunrpc/auth_gss/gss_spkm3_mech.c
@@ -49,52 +49,51 @@
# define RPCDBG_FACILITY RPCDBG_AUTH
#endif
-static inline int
-get_bytes(char **ptr, const char *end, void *res, int len)
+static const void *
+simple_get_bytes(const void *p, const void *end, void *res, int len)
{
- char *p, *q;
- p = *ptr;
- q = p + len;
- if (q > end || q < p)
- return -1;
+ const void *q = (const void *)((const char *)p + len);
+ if (unlikely(q > end || q < p))
+ return ERR_PTR(-EFAULT);
memcpy(res, p, len);
- *ptr = q;
- return 0;
+ return q;
}
-static inline int
-get_netobj(char **ptr, const char *end, struct xdr_netobj *res)
+static const void *
+simple_get_netobj(const void *p, const void *end, struct xdr_netobj *res)
{
- char *p, *q;
- p = *ptr;
- if (get_bytes(&p, end, &res->len, sizeof(res->len)))
- return -1;
- q = p + res->len;
- if(res->len == 0)
- goto out_nocopy;
- if (q > end || q < p)
- return -1;
- if (!(res->data = kmalloc(res->len, GFP_KERNEL)))
- return -1;
- memcpy(res->data, p, res->len);
-out_nocopy:
- *ptr = q;
- return 0;
+ const void *q;
+ unsigned int len;
+ p = simple_get_bytes(p, end, &len, sizeof(len));
+ if (IS_ERR(p))
+ return p;
+ res->len = len;
+ if (len == 0) {
+ res->data = NULL;
+ return p;
+ }
+ q = (const void *)((const char *)p + len);
+ if (unlikely(q > end || q < p))
+ return ERR_PTR(-EFAULT);
+ res->data = kmalloc(len, GFP_KERNEL);
+ if (unlikely(res->data == NULL))
+ return ERR_PTR(-ENOMEM);
+ memcpy(res->data, p, len);
+ return q;
}
-static inline int
-get_key(char **p, char *end, struct crypto_tfm **res, int *resalg)
+static inline const void *
+get_key(const void *p, const void *end, struct crypto_tfm **res, int *resalg)
{
- struct xdr_netobj key = {
- .len = 0,
- .data = NULL,
- };
+ struct xdr_netobj key = { 0 };
int alg_mode,setkey = 0;
char *alg_name;
- if (get_bytes(p, end, resalg, sizeof(int)))
+ p = simple_get_bytes(p, end, resalg, sizeof(*resalg));
+ if (IS_ERR(p))
goto out_err;
- if ((get_netobj(p, end, &key)))
+ p = simple_get_netobj(p, end, &key);
+ if (IS_ERR(p))
goto out_err;
switch (*resalg) {
@@ -111,10 +110,6 @@ get_key(char **p, char *end, struct crypto_tfm **res, int *resalg)
alg_mode = 0;
setkey = 0;
break;
- case NID_cast5_cbc:
- dprintk("RPC: SPKM3 get_key: case cast5_cbc, UNSUPPORTED \n");
- goto out_err;
- break;
default:
dprintk("RPC: SPKM3 get_key: unsupported algorithm %d", *resalg);
goto out_err_free_key;
@@ -128,69 +123,81 @@ get_key(char **p, char *end, struct crypto_tfm **res, int *resalg)
if(key.len > 0)
kfree(key.data);
- return 0;
+ return p;
out_err_free_tfm:
crypto_free_tfm(*res);
out_err_free_key:
if(key.len > 0)
kfree(key.data);
+ p = ERR_PTR(-EINVAL);
out_err:
- return -1;
+ return p;
}
-static u32
-gss_import_sec_context_spkm3(struct xdr_netobj *inbuf,
+static int
+gss_import_sec_context_spkm3(const void *p, size_t len,
struct gss_ctx *ctx_id)
{
- char *p = inbuf->data;
- char *end = inbuf->data + inbuf->len;
+ const void *end = (const void *)((const char *)p + len);
struct spkm3_ctx *ctx;
if (!(ctx = kmalloc(sizeof(*ctx), GFP_KERNEL)))
goto out_err;
memset(ctx, 0, sizeof(*ctx));
- if (get_netobj(&p, end, &ctx->ctx_id))
+ p = simple_get_netobj(p, end, &ctx->ctx_id);
+ if (IS_ERR(p))
goto out_err_free_ctx;
- if (get_bytes(&p, end, &ctx->qop, sizeof(ctx->qop)))
+ p = simple_get_bytes(p, end, &ctx->qop, sizeof(ctx->qop));
+ if (IS_ERR(p))
goto out_err_free_ctx_id;
- if (get_netobj(&p, end, &ctx->mech_used))
+ p = simple_get_netobj(p, end, &ctx->mech_used);
+ if (IS_ERR(p))
goto out_err_free_mech;
- if (get_bytes(&p, end, &ctx->ret_flags, sizeof(ctx->ret_flags)))
+ p = simple_get_bytes(p, end, &ctx->ret_flags, sizeof(ctx->ret_flags));
+ if (IS_ERR(p))
goto out_err_free_mech;
- if (get_bytes(&p, end, &ctx->req_flags, sizeof(ctx->req_flags)))
+ p = simple_get_bytes(p, end, &ctx->req_flags, sizeof(ctx->req_flags));
+ if (IS_ERR(p))
goto out_err_free_mech;
- if (get_netobj(&p, end, &ctx->share_key))
+ p = simple_get_netobj(p, end, &ctx->share_key);
+ if (IS_ERR(p))
goto out_err_free_s_key;
- if (get_key(&p, end, &ctx->derived_conf_key, &ctx->conf_alg)) {
- dprintk("RPC: SPKM3 confidentiality key will be NULL\n");
- }
+ p = get_key(p, end, &ctx->derived_conf_key, &ctx->conf_alg);
+ if (IS_ERR(p))
+ goto out_err_free_s_key;
- if (get_key(&p, end, &ctx->derived_integ_key, &ctx->intg_alg)) {
- dprintk("RPC: SPKM3 integrity key will be NULL\n");
- }
+ p = get_key(p, end, &ctx->derived_integ_key, &ctx->intg_alg);
+ if (IS_ERR(p))
+ goto out_err_free_key1;
- if (get_bytes(&p, end, &ctx->owf_alg, sizeof(ctx->owf_alg)))
- goto out_err_free_s_key;
+ p = simple_get_bytes(p, end, &ctx->keyestb_alg, sizeof(ctx->keyestb_alg));
+ if (IS_ERR(p))
+ goto out_err_free_key2;
- if (get_bytes(&p, end, &ctx->owf_alg, sizeof(ctx->owf_alg)))
- goto out_err_free_s_key;
+ p = simple_get_bytes(p, end, &ctx->owf_alg, sizeof(ctx->owf_alg));
+ if (IS_ERR(p))
+ goto out_err_free_key2;
if (p != end)
- goto out_err_free_s_key;
+ goto out_err_free_key2;
ctx_id->internal_ctx_id = ctx;
dprintk("Succesfully imported new spkm context.\n");
return 0;
+out_err_free_key2:
+ crypto_free_tfm(ctx->derived_integ_key);
+out_err_free_key1:
+ crypto_free_tfm(ctx->derived_conf_key);
out_err_free_s_key:
kfree(ctx->share_key.data);
out_err_free_mech:
@@ -200,7 +207,7 @@ out_err_free_ctx_id:
out_err_free_ctx:
kfree(ctx);
out_err:
- return GSS_S_FAILURE;
+ return PTR_ERR(p);
}
static void
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
index 1b4a111142e00..5c8fe3bfc4941 100644
--- a/net/sunrpc/auth_gss/svcauth_gss.c
+++ b/net/sunrpc/auth_gss/svcauth_gss.c
@@ -381,7 +381,6 @@ static int rsc_parse(struct cache_detail *cd,
else {
int N, i;
struct gss_api_mech *gm;
- struct xdr_netobj tmp_buf;
/* gid */
if (get_int(&mesg, &rsci.cred.cr_gid))
@@ -420,9 +419,7 @@ static int rsc_parse(struct cache_detail *cd,
gss_mech_put(gm);
goto out;
}
- tmp_buf.len = len;
- tmp_buf.data = buf;
- if (gss_import_sec_context(&tmp_buf, gm, &rsci.mechctx)) {
+ if (gss_import_sec_context(buf, len, gm, &rsci.mechctx)) {
gss_mech_put(gm);
goto out;
}
@@ -730,6 +727,19 @@ struct gss_svc_data {
struct rsc *rsci;
};
+static int
+svcauth_gss_set_client(struct svc_rqst *rqstp)
+{
+ struct gss_svc_data *svcdata = rqstp->rq_auth_data;
+ struct rsc *rsci = svcdata->rsci;
+ struct rpc_gss_wire_cred *gc = &svcdata->clcred;
+
+ rqstp->rq_client = find_gss_auth_domain(rsci->mechctx, gc->gc_svc);
+ if (rqstp->rq_client == NULL)
+ return SVC_DENIED;
+ return SVC_OK;
+}
+
/*
* Accept an rpcsec packet.
* If context establishment, punt to user space
@@ -893,11 +903,6 @@ svcauth_gss_accept(struct svc_rqst *rqstp, u32 *authp)
svc_putu32(resv, rpc_success);
goto complete;
case RPC_GSS_PROC_DATA:
- *authp = rpc_autherr_badcred;
- rqstp->rq_client =
- find_gss_auth_domain(rsci->mechctx, gc->gc_svc);
- if (rqstp->rq_client == NULL)
- goto auth_err;
*authp = rpcsec_gsserr_ctxproblem;
if (gss_write_verf(rqstp, rsci->mechctx, gc->gc_seq))
goto auth_err;
@@ -911,8 +916,6 @@ svcauth_gss_accept(struct svc_rqst *rqstp, u32 *authp)
if (unwrap_integ_data(&rqstp->rq_arg,
gc->gc_seq, rsci->mechctx))
goto auth_err;
- svcdata->rsci = rsci;
- cache_get(&rsci->h);
/* placeholders for length and seq. number: */
svcdata->body_start = resv->iov_base + resv->iov_len;
svc_putu32(resv, 0);
@@ -923,6 +926,8 @@ svcauth_gss_accept(struct svc_rqst *rqstp, u32 *authp)
default:
goto auth_err;
}
+ svcdata->rsci = rsci;
+ cache_get(&rsci->h);
ret = SVC_OK;
goto out;
}
@@ -1052,6 +1057,7 @@ static struct auth_ops svcauthops_gss = {
.accept = svcauth_gss_accept,
.release = svcauth_gss_release,
.domain_release = svcauth_gss_domain_release,
+ .set_client = svcauth_gss_set_client,
};
int
diff --git a/net/sunrpc/auth_null.c b/net/sunrpc/auth_null.c
index f112f63e3705e..9b72d3abf823b 100644
--- a/net/sunrpc/auth_null.c
+++ b/net/sunrpc/auth_null.c
@@ -18,48 +18,28 @@
# define RPCDBG_FACILITY RPCDBG_AUTH
#endif
-static struct rpc_credops null_credops;
+static struct rpc_auth null_auth;
+static struct rpc_cred null_cred;
static struct rpc_auth *
nul_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor)
{
- struct rpc_auth *auth;
-
- dprintk("RPC: creating NULL authenticator for client %p\n", clnt);
- if (!(auth = (struct rpc_auth *) kmalloc(sizeof(*auth),GFP_KERNEL)))
- return NULL;
- auth->au_cslack = 4;
- auth->au_rslack = 2;
- auth->au_ops = &authnull_ops;
- auth->au_expire = 1800 * HZ;
- rpcauth_init_credcache(auth);
-
- return (struct rpc_auth *) auth;
+ atomic_inc(&null_auth.au_count);
+ return &null_auth;
}
static void
nul_destroy(struct rpc_auth *auth)
{
- dprintk("RPC: destroying NULL authenticator %p\n", auth);
- rpcauth_free_credcache(auth);
}
/*
- * Create NULL creds for current process
+ * Lookup NULL creds for current process
*/
static struct rpc_cred *
-nul_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
+nul_lookup_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
{
- struct rpc_cred *cred;
-
- if (!(cred = (struct rpc_cred *) kmalloc(sizeof(*cred),GFP_KERNEL)))
- return NULL;
- atomic_set(&cred->cr_count, 0);
- cred->cr_flags = RPCAUTH_CRED_UPTODATE;
- cred->cr_uid = acred->uid;
- cred->cr_ops = &null_credops;
-
- return cred;
+ return get_rpccred(&null_cred);
}
/*
@@ -68,7 +48,6 @@ nul_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
static void
nul_destroy_cred(struct rpc_cred *cred)
{
- kfree(cred);
}
/*
@@ -84,7 +63,7 @@ nul_match(struct auth_cred *acred, struct rpc_cred *cred, int taskflags)
* Marshal credential.
*/
static u32 *
-nul_marshal(struct rpc_task *task, u32 *p, int ruid)
+nul_marshal(struct rpc_task *task, u32 *p)
{
*p++ = htonl(RPC_AUTH_NULL);
*p++ = 0;
@@ -125,7 +104,7 @@ nul_validate(struct rpc_task *task, u32 *p)
return p;
}
-struct rpc_authops authnull_ops = {
+struct rpc_authops authnull_ops = {
.owner = THIS_MODULE,
.au_flavor = RPC_AUTH_NULL,
#ifdef RPC_DEBUG
@@ -133,14 +112,32 @@ struct rpc_authops authnull_ops = {
#endif
.create = nul_create,
.destroy = nul_destroy,
- .crcreate = nul_create_cred,
+ .lookup_cred = nul_lookup_cred,
+};
+
+static
+struct rpc_auth null_auth = {
+ .au_cslack = 4,
+ .au_rslack = 2,
+ .au_ops = &authnull_ops,
};
static
struct rpc_credops null_credops = {
+ .cr_name = "AUTH_NULL",
.crdestroy = nul_destroy_cred,
.crmatch = nul_match,
.crmarshal = nul_marshal,
.crrefresh = nul_refresh,
.crvalidate = nul_validate,
};
+
+static
+struct rpc_cred null_cred = {
+ .cr_ops = &null_credops,
+ .cr_count = ATOMIC_INIT(1),
+ .cr_flags = RPCAUTH_CRED_UPTODATE,
+#ifdef RPC_DEBUG
+ .cr_magic = RPCAUTH_CRED_MAGIC,
+#endif
+};
diff --git a/net/sunrpc/auth_unix.c b/net/sunrpc/auth_unix.c
index f49ed17fe3fbf..4ff297a9b15bb 100644
--- a/net/sunrpc/auth_unix.c
+++ b/net/sunrpc/auth_unix.c
@@ -19,8 +19,6 @@
struct unx_cred {
struct rpc_cred uc_base;
gid_t uc_gid;
- uid_t uc_puid; /* process uid */
- gid_t uc_pgid; /* process gid */
gid_t uc_gids[NFS_NGROUPS];
};
#define uc_uid uc_base.cr_uid
@@ -36,24 +34,17 @@ struct unx_cred {
# define RPCDBG_FACILITY RPCDBG_AUTH
#endif
+static struct rpc_auth unix_auth;
+static struct rpc_cred_cache unix_cred_cache;
static struct rpc_credops unix_credops;
static struct rpc_auth *
unx_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor)
{
- struct rpc_auth *auth;
-
dprintk("RPC: creating UNIX authenticator for client %p\n", clnt);
- if (!(auth = (struct rpc_auth *) kmalloc(sizeof(*auth), GFP_KERNEL)))
- return NULL;
- auth->au_cslack = UNX_WRITESLACK;
- auth->au_rslack = 2; /* assume AUTH_NULL verf */
- auth->au_expire = UNX_CRED_EXPIRE;
- auth->au_ops = &authunix_ops;
-
- rpcauth_init_credcache(auth);
-
- return auth;
+ if (atomic_inc_return(&unix_auth.au_count) == 0)
+ unix_cred_cache.nextgc = jiffies + (unix_cred_cache.expire >> 1);
+ return &unix_auth;
}
static void
@@ -63,6 +54,15 @@ unx_destroy(struct rpc_auth *auth)
rpcauth_free_credcache(auth);
}
+/*
+ * Lookup AUTH_UNIX creds for current process
+ */
+static struct rpc_cred *
+unx_lookup_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
+{
+ return rpcauth_lookup_credcache(auth, acred, flags);
+}
+
static struct rpc_cred *
unx_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
{
@@ -73,13 +73,13 @@ unx_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
acred->uid, acred->gid);
if (!(cred = (struct unx_cred *) kmalloc(sizeof(*cred), GFP_KERNEL)))
- return NULL;
+ return ERR_PTR(-ENOMEM);
- atomic_set(&cred->uc_count, 0);
+ atomic_set(&cred->uc_count, 1);
cred->uc_flags = RPCAUTH_CRED_UPTODATE;
if (flags & RPC_TASK_ROOTCREDS) {
- cred->uc_uid = cred->uc_puid = 0;
- cred->uc_gid = cred->uc_pgid = 0;
+ cred->uc_uid = 0;
+ cred->uc_gid = 0;
cred->uc_gids[0] = NOGROUP;
} else {
int groups = acred->group_info->ngroups;
@@ -88,8 +88,6 @@ unx_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
cred->uc_uid = acred->uid;
cred->uc_gid = acred->gid;
- cred->uc_puid = current->uid;
- cred->uc_pgid = current->gid;
for (i = 0; i < groups; i++)
cred->uc_gids[i] = GROUP_AT(acred->group_info, i);
if (i < NFS_NGROUPS)
@@ -121,9 +119,7 @@ unx_match(struct auth_cred *acred, struct rpc_cred *rcred, int taskflags)
int groups;
if (cred->uc_uid != acred->uid
- || cred->uc_gid != acred->gid
- || cred->uc_puid != current->uid
- || cred->uc_pgid != current->gid)
+ || cred->uc_gid != acred->gid)
return 0;
groups = acred->group_info->ngroups;
@@ -134,8 +130,8 @@ unx_match(struct auth_cred *acred, struct rpc_cred *rcred, int taskflags)
return 0;
return 1;
}
- return (cred->uc_uid == 0 && cred->uc_puid == 0
- && cred->uc_gid == 0 && cred->uc_pgid == 0
+ return (cred->uc_uid == 0
+ && cred->uc_gid == 0
&& cred->uc_gids[0] == (gid_t) NOGROUP);
}
@@ -144,7 +140,7 @@ unx_match(struct auth_cred *acred, struct rpc_cred *rcred, int taskflags)
* Maybe we should keep a cached credential for performance reasons.
*/
static u32 *
-unx_marshal(struct rpc_task *task, u32 *p, int ruid)
+unx_marshal(struct rpc_task *task, u32 *p)
{
struct rpc_clnt *clnt = task->tk_client;
struct unx_cred *cred = (struct unx_cred *) task->tk_msg.rpc_cred;
@@ -160,14 +156,8 @@ unx_marshal(struct rpc_task *task, u32 *p, int ruid)
*/
p = xdr_encode_array(p, clnt->cl_nodename, clnt->cl_nodelen);
- /* Note: we don't use real uid if it involves raising privilege */
- if (ruid && cred->uc_puid != 0 && cred->uc_pgid != 0) {
- *p++ = htonl((u32) cred->uc_puid);
- *p++ = htonl((u32) cred->uc_pgid);
- } else {
- *p++ = htonl((u32) cred->uc_uid);
- *p++ = htonl((u32) cred->uc_gid);
- }
+ *p++ = htonl((u32) cred->uc_uid);
+ *p++ = htonl((u32) cred->uc_gid);
hold = p++;
for (i = 0; i < 16 && cred->uc_gids[i] != (gid_t) NOGROUP; i++)
*p++ = htonl((u32) cred->uc_gids[i]);
@@ -223,11 +213,27 @@ struct rpc_authops authunix_ops = {
#endif
.create = unx_create,
.destroy = unx_destroy,
+ .lookup_cred = unx_lookup_cred,
.crcreate = unx_create_cred,
};
static
+struct rpc_cred_cache unix_cred_cache = {
+ .expire = UNX_CRED_EXPIRE,
+};
+
+static
+struct rpc_auth unix_auth = {
+ .au_cslack = UNX_WRITESLACK,
+ .au_rslack = 2, /* assume AUTH_NULL verf */
+ .au_ops = &authunix_ops,
+ .au_count = ATOMIC_INIT(0),
+ .au_credcache = &unix_cred_cache,
+};
+
+static
struct rpc_credops unix_credops = {
+ .cr_name = "AUTH_UNIX",
.crdestroy = unx_destroy_cred,
.crmatch = unx_match,
.crmarshal = unx_marshal,
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c
index bf5a2dee88000..900f5bc7e3366 100644
--- a/net/sunrpc/cache.c
+++ b/net/sunrpc/cache.c
@@ -321,12 +321,10 @@ static int cache_clean(void)
if (test_and_clear_bit(CACHE_PENDING, &ch->flags))
queue_loose(current_detail, ch);
- if (!atomic_read(&ch->refcnt))
+ if (atomic_read(&ch->refcnt) == 1)
break;
}
if (ch) {
- cache_get(ch);
- clear_bit(CACHE_HASHED, &ch->flags);
*cp = ch->next;
ch->next = NULL;
current_detail->entries--;
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 50d58e877b9a4..02bc029d46fe7 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -23,6 +23,7 @@
#include <asm/system.h>
+#include <linux/module.h>
#include <linux/types.h>
#include <linux/mm.h>
#include <linux/slab.h>
@@ -406,12 +407,11 @@ rpc_call_async(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 = rpc_execute(task);
- else {
- status = task->tk_status;
+ status = task->tk_status;
+ if (status == 0)
+ rpc_execute(task);
+ else
rpc_release_task(task);
- }
out:
rpc_clnt_sigunmask(clnt, &oldset);
@@ -426,9 +426,9 @@ rpc_call_setup(struct rpc_task *task, struct rpc_message *msg, int flags)
task->tk_msg = *msg;
task->tk_flags |= flags;
/* Bind the user cred */
- if (task->tk_msg.rpc_cred != NULL) {
+ if (task->tk_msg.rpc_cred != NULL)
rpcauth_holdcred(task);
- } else
+ else
rpcauth_bindcred(task);
if (task->tk_status == 0)
@@ -453,6 +453,20 @@ rpc_setbufsize(struct rpc_clnt *clnt, unsigned int sndsize, unsigned int rcvsize
}
/*
+ * Return size of largest payload RPC client can support, in bytes
+ *
+ * For stream transports, this is one RPC record fragment (see RFC
+ * 1831), as we don't support multi-record requests yet. For datagram
+ * transports, this is the size of an IP packet minus the IP, UDP, and
+ * RPC header sizes.
+ */
+size_t rpc_max_payload(struct rpc_clnt *clnt)
+{
+ return clnt->cl_xprt->max_payload;
+}
+EXPORT_SYMBOL(rpc_max_payload);
+
+/*
* Restart an (async) RPC call. Usually called from within the
* exit handler.
*/
@@ -871,21 +885,6 @@ call_decode(struct rpc_task *task)
goto out_retry;
}
- /*
- * The following is an NFS-specific hack to cater for setuid
- * processes whose uid is mapped to nobody on the server.
- */
- if (task->tk_client->cl_droppriv &&
- (ntohl(*p) == NFSERR_ACCES || ntohl(*p) == NFSERR_PERM)) {
- if (RPC_IS_SETUID(task) && task->tk_suid_retry) {
- dprintk("RPC: %4d retry squashed uid\n", task->tk_pid);
- task->tk_flags ^= RPC_CALL_REALUID;
- task->tk_action = call_bind;
- task->tk_suid_retry--;
- goto out_retry;
- }
- }
-
task->tk_action = NULL;
if (decode)
diff --git a/net/sunrpc/pmap_clnt.c b/net/sunrpc/pmap_clnt.c
index 2a5d319eda092..d0b1d2c34a4db 100644
--- a/net/sunrpc/pmap_clnt.c
+++ b/net/sunrpc/pmap_clnt.c
@@ -3,9 +3,6 @@
*
* Portmapper client.
*
- * FIXME: In a secure environment, we may want to use an authentication
- * flavor other than AUTH_NULL.
- *
* Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
*/
@@ -212,7 +209,7 @@ pmap_create(char *hostname, struct sockaddr_in *srvaddr, int proto)
/* printk("pmap: create clnt\n"); */
clnt = rpc_create_client(xprt, hostname,
&pmap_program, RPC_PMAP_VERSION,
- RPC_AUTH_NULL);
+ RPC_AUTH_UNIX);
if (IS_ERR(clnt)) {
xprt_destroy(xprt);
} else {
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
index be26e4c5b1a72..c06614d0e31de 100644
--- a/net/sunrpc/sched.c
+++ b/net/sunrpc/sched.c
@@ -132,9 +132,11 @@ __rpc_add_timer(struct rpc_task *task, rpc_action timer)
* Delete any timer for the current task. Because we use del_timer_sync(),
* this function should never be called while holding queue->lock.
*/
-static inline void
+static void
rpc_delete_timer(struct rpc_task *task)
{
+ if (RPC_IS_QUEUED(task))
+ return;
if (test_and_clear_bit(RPC_TASK_HAS_TIMER, &task->tk_runstate)) {
del_singleshot_timer_sync(&task->tk_timer);
dprintk("RPC: %4d deleting timer\n", task->tk_pid);
@@ -747,13 +749,10 @@ void rpc_init_task(struct rpc_task *task, struct rpc_clnt *clnt, rpc_action call
task->tk_client = clnt;
task->tk_flags = flags;
task->tk_exit = callback;
- if (current->uid != current->fsuid || current->gid != current->fsgid)
- task->tk_flags |= RPC_TASK_SETUID;
/* Initialize retry counters */
task->tk_garb_retry = 2;
task->tk_cred_retry = 2;
- task->tk_suid_retry = 1;
task->tk_priority = RPC_PRIORITY_NORMAL;
task->tk_cookie = (unsigned long)current;
diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c
index 1876751172be3..d4f26bf9e7320 100644
--- a/net/sunrpc/sunrpc_syms.c
+++ b/net/sunrpc/sunrpc_syms.c
@@ -90,6 +90,7 @@ EXPORT_SYMBOL(svc_reserve);
EXPORT_SYMBOL(svc_auth_register);
EXPORT_SYMBOL(auth_domain_lookup);
EXPORT_SYMBOL(svc_authenticate);
+EXPORT_SYMBOL(svc_set_client);
/* RPC statistics */
#ifdef CONFIG_PROC_FS
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
index 8c5b0517db7fe..bb2d99f33315f 100644
--- a/net/sunrpc/svc.c
+++ b/net/sunrpc/svc.c
@@ -264,6 +264,7 @@ svc_process(struct svc_serv *serv, struct svc_rqst *rqstp)
u32 dir, prog, vers, proc,
auth_stat, rpc_stat;
int auth_res;
+ u32 *accept_statp;
rpc_stat = rpc_success;
@@ -299,6 +300,9 @@ svc_process(struct svc_serv *serv, struct svc_rqst *rqstp)
if (vers != 2) /* RPC version number */
goto err_bad_rpc;
+ /* Save position in case we later decide to reject: */
+ accept_statp = resv->iov_base + resv->iov_len;
+
svc_putu32(resv, xdr_zero); /* ACCEPT */
rqstp->rq_prog = prog = ntohl(svc_getu32(argv)); /* program number */
@@ -311,10 +315,12 @@ svc_process(struct svc_serv *serv, struct svc_rqst *rqstp)
* We do this before anything else in order to get a decent
* auth verifier.
*/
- if (progp->pg_authenticate != NULL)
- auth_res = progp->pg_authenticate(rqstp, &auth_stat);
- else
- auth_res = svc_authenticate(rqstp, &auth_stat);
+ auth_res = svc_authenticate(rqstp, &auth_stat);
+ /* Also give the program a chance to reject this call: */
+ if (auth_res == SVC_OK) {
+ auth_stat = rpc_autherr_badcred;
+ auth_res = progp->pg_authenticate(rqstp);
+ }
switch (auth_res) {
case SVC_OK:
break;
@@ -437,7 +443,8 @@ err_bad_rpc:
err_bad_auth:
dprintk("svc: authentication failed (%d)\n", ntohl(auth_stat));
serv->sv_stats->rpcbadauth++;
- resv->iov_len -= 4;
+ /* Restore write pointer to location of accept status: */
+ xdr_ressize_check(rqstp, accept_statp);
svc_putu32(resv, xdr_one); /* REJECT */
svc_putu32(resv, xdr_one); /* AUTH_ERROR */
svc_putu32(resv, auth_stat); /* status */
diff --git a/net/sunrpc/svcauth.c b/net/sunrpc/svcauth.c
index 0148c3310157d..bde8147ef2db5 100644
--- a/net/sunrpc/svcauth.c
+++ b/net/sunrpc/svcauth.c
@@ -59,6 +59,11 @@ svc_authenticate(struct svc_rqst *rqstp, u32 *authp)
return aops->accept(rqstp, authp);
}
+int svc_set_client(struct svc_rqst *rqstp)
+{
+ return rqstp->rq_authop->set_client(rqstp);
+}
+
/* A request, which was authenticated, has now executed.
* Time to finalise the the credentials and verifier
* and release and resources
@@ -173,12 +178,12 @@ auth_domain_lookup(struct auth_domain *item, int set)
tmp = container_of(*hp, struct auth_domain, h);
if (!auth_domain_match(tmp, item))
continue;
- cache_get(&tmp->h);
- if (!set)
+ if (!set) {
+ cache_get(&tmp->h);
goto out_noset;
+ }
*hp = tmp->h.next;
tmp->h.next = NULL;
- clear_bit(CACHE_HASHED, &tmp->h.flags);
auth_domain_drop(&tmp->h, &auth_domain_cache);
goto out_set;
}
@@ -187,9 +192,9 @@ auth_domain_lookup(struct auth_domain *item, int set)
goto out_nada;
auth_domain_cache.entries++;
out_set:
- set_bit(CACHE_HASHED, &item->h.flags);
item->h.next = *head;
*head = &item->h;
+ cache_get(&item->h);
write_unlock(&auth_domain_cache.hash_lock);
cache_fresh(&auth_domain_cache, &item->h, item->h.expiry_time);
cache_get(&item->h);
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c
index 580eb7596d6cf..2b99b4028d31d 100644
--- a/net/sunrpc/svcauth_unix.c
+++ b/net/sunrpc/svcauth_unix.c
@@ -368,7 +368,6 @@ svcauth_null_accept(struct svc_rqst *rqstp, u32 *authp)
struct kvec *argv = &rqstp->rq_arg.head[0];
struct kvec *resv = &rqstp->rq_res.head[0];
struct svc_cred *cred = &rqstp->rq_cred;
- int rv=0;
cred->cr_group_info = NULL;
rqstp->rq_client = NULL;
@@ -394,19 +393,11 @@ svcauth_null_accept(struct svc_rqst *rqstp, u32 *authp)
if (cred->cr_group_info == NULL)
return SVC_DROP; /* kmalloc failure - client must retry */
- rv = svcauth_unix_set_client(rqstp);
- if (rv == SVC_DENIED)
- goto badcred;
-
/* Put NULL verifier */
svc_putu32(resv, RPC_AUTH_NULL);
svc_putu32(resv, 0);
- return rv;
-
-badcred:
- *authp = rpc_autherr_badcred;
- return SVC_DENIED;
+ return SVC_OK;
}
static int
@@ -429,6 +420,7 @@ struct auth_ops svcauth_null = {
.flavour = RPC_AUTH_NULL,
.accept = svcauth_null_accept,
.release = svcauth_null_release,
+ .set_client = svcauth_unix_set_client,
};
@@ -440,7 +432,6 @@ svcauth_unix_accept(struct svc_rqst *rqstp, u32 *authp)
struct svc_cred *cred = &rqstp->rq_cred;
u32 slen, i;
int len = argv->iov_len;
- int rv=0;
cred->cr_group_info = NULL;
rqstp->rq_client = NULL;
@@ -472,15 +463,11 @@ svcauth_unix_accept(struct svc_rqst *rqstp, u32 *authp)
return SVC_DENIED;
}
- rv = svcauth_unix_set_client(rqstp);
- if (rv == SVC_DENIED)
- goto badcred;
-
/* Put NULL verifier */
svc_putu32(resv, RPC_AUTH_NULL);
svc_putu32(resv, 0);
- return rv;
+ return SVC_OK;
badcred:
*authp = rpc_autherr_badcred;
@@ -510,5 +497,6 @@ struct auth_ops svcauth_unix = {
.accept = svcauth_unix_accept,
.release = svcauth_unix_release,
.domain_release = svcauth_unix_domain_release,
+ .set_client = svcauth_unix_set_client,
};
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index 7794c16d84bb2..05907035bc961 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -1186,6 +1186,7 @@ svc_recv(struct svc_serv *serv, struct svc_rqst *rqstp, long timeout)
arg->len = (pages-1)*PAGE_SIZE;
arg->tail[0].iov_len = 0;
+ try_to_freeze(PF_FREEZE);
if (signalled())
return -EINTR;
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index ed2a19c762e02..c74a6bb940742 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -1044,7 +1044,8 @@ tcp_state_change(struct sock *sk)
dprintk("RPC: tcp_state_change client %p...\n", xprt);
dprintk("RPC: state %x conn %d dead %d zapped %d\n",
sk->sk_state, xprt_connected(xprt),
- sock_flag(sk, SOCK_DEAD), sk->sk_zapped);
+ sock_flag(sk, SOCK_DEAD),
+ sock_flag(sk, SOCK_ZAPPED));
switch (sk->sk_state) {
case TCP_ESTABLISHED:
@@ -1460,8 +1461,11 @@ xprt_setup(int proto, struct sockaddr_in *ap, struct rpc_timeout *to)
if (xprt->stream) {
xprt->cwnd = RPC_MAXCWND(xprt);
xprt->nocong = 1;
- } else
+ xprt->max_payload = (1U << 31) - 1;
+ } else {
xprt->cwnd = RPC_INITCWND;
+ xprt->max_payload = (1U << 16) - (MAX_HEADER << 3);
+ }
spin_lock_init(&xprt->sock_lock);
spin_lock_init(&xprt->xprt_lock);
init_waitqueue_head(&xprt->cong_wait);
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 062bcc2080a70..20165335e27b8 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -188,6 +188,13 @@ static int unix_mkname(struct sockaddr_un * sunaddr, int len, unsigned *hashp)
if (!sunaddr || sunaddr->sun_family != AF_UNIX)
return -EINVAL;
if (sunaddr->sun_path[0]) {
+ /*
+ * This may look like an off by one error but it is a bit more
+ * subtle. 108 is the longest valid AF_UNIX path for a binding.
+ * sun_path[108] doesnt as such exist. However in kernel space
+ * we are guaranteed that it is a valid memory location in our
+ * kernel address buffer.
+ */
((char *)sunaddr)[len]=0;
len = strlen(sunaddr->sun_path)+1+sizeof(short);
return len;
@@ -861,8 +868,8 @@ static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr,
goto out;
alen = err;
- if (sock->passcred && !unix_sk(sk)->addr &&
- (err = unix_autobind(sock)) != 0)
+ if (test_bit(SOCK_PASSCRED, &sock->flags) &&
+ !unix_sk(sk)->addr && (err = unix_autobind(sock)) != 0)
goto out;
other=unix_find_other(sunaddr, alen, sock->type, hash, &err);
@@ -952,7 +959,8 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,
goto out;
addr_len = err;
- if (sock->passcred && !u->addr && (err = unix_autobind(sock)) != 0)
+ if (test_bit(SOCK_PASSCRED, &sock->flags)
+ && !u->addr && (err = unix_autobind(sock)) != 0)
goto out;
timeo = sock_sndtimeo(sk, flags & O_NONBLOCK);
@@ -1286,7 +1294,8 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,
goto out;
}
- if (sock->passcred && !u->addr && (err = unix_autobind(sock)) != 0)
+ if (test_bit(SOCK_PASSCRED, &sock->flags)
+ && !u->addr && (err = unix_autobind(sock)) != 0)
goto out;
err = -EMSGSIZE;
@@ -1850,15 +1859,22 @@ static int unix_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
case SIOCINQ:
{
struct sk_buff *skb;
+
if (sk->sk_state == TCP_LISTEN) {
err = -EINVAL;
break;
}
spin_lock(&sk->sk_receive_queue.lock);
- skb = skb_peek(&sk->sk_receive_queue);
- if (skb)
- amount=skb->len;
+ if (sk->sk_type == SOCK_STREAM ||
+ sk->sk_type == SOCK_SEQPACKET) {
+ skb_queue_walk(&sk->sk_receive_queue, skb)
+ amount += skb->len;
+ } else {
+ skb = skb_peek(&sk->sk_receive_queue);
+ if (skb)
+ amount=skb->len;
+ }
spin_unlock(&sk->sk_receive_queue.lock);
err = put_user(amount, (int __user *)arg);
break;
diff --git a/net/wanrouter/af_wanpipe.c b/net/wanrouter/af_wanpipe.c
index d0d92336d5c2c..6698c872c96b9 100644
--- a/net/wanrouter/af_wanpipe.c
+++ b/net/wanrouter/af_wanpipe.c
@@ -394,7 +394,7 @@ static int wanpipe_listen_rcv (struct sk_buff *skb, struct sock *sk)
chan->lcn = mbox_ptr->cmd.lcn;
card->u.x.svc_to_dev_map[(chan->lcn%MAX_X25_LCN)] = dev;
- newsk->sk_zapped = 0;
+ sock_reset_flag(newsk, SOCK_ZAPPED);
newwp->num = htons(X25_PROT);
if (wanpipe_do_bind(newsk, dev, newwp->num)) {
@@ -468,10 +468,12 @@ static struct sock *wanpipe_make_new(struct sock *osk)
wp_sk(sk)->num = wp_sk(osk)->num;
sk->sk_rcvbuf = osk->sk_rcvbuf;
sk->sk_sndbuf = osk->sk_sndbuf;
- sk->sk_debug = osk->sk_debug;
sk->sk_state = WANSOCK_CONNECTING;
sk->sk_sleep = osk->sk_sleep;
+ if (sock_flag(osk, SOCK_DBG))
+ sock_set_flag(sk, SOCK_DBG);
+
return sk;
}
@@ -546,7 +548,7 @@ static int wanpipe_sendmsg(struct kiocb *iocb, struct socket *sock,
int ifindex, err, reserve = 0;
- if (!sk->sk_zapped)
+ if (!sock_flag(sk, SOCK_ZAPPED))
return -ENETDOWN;
if (sk->sk_state != WANSOCK_CONNECTED)
@@ -672,7 +674,7 @@ static void wanpipe_delayed_transmit (unsigned long data)
return;
}
- if (sk->sk_state != WANSOCK_CONNECTED || !sk->sk_zapped) {
+ if (sk->sk_state != WANSOCK_CONNECTED || !sock_flag(sk, SOCK_ZAPPED)) {
clear_bit(0, &wp->timer);
DBG_PRINTK(KERN_INFO "wansock: Tx Timer, State not CONNECTED\n");
return;
@@ -865,7 +867,7 @@ static void wanpipe_unlink_driver (struct sock *sk)
struct net_device *dev;
wanpipe_common_t *chan=NULL;
- sk->sk_zapped = 0;
+ sock_reset_flag(sk, SOCK_ZAPPED);
sk->sk_state = WANSOCK_DISCONNECTED;
wp_sk(sk)->dev = NULL;
@@ -914,7 +916,7 @@ static void wanpipe_link_driver(struct net_device *dev, struct sock *sk)
chan->mbox = wp->mbox;
chan->tx_timer = &wp->tx_timer;
wp->dev = dev;
- sk->sk_zapped = 1;
+ sock_set_flag(sk, SOCK_ZAPPED);
clear_bit(0,&chan->common_critical);
}
@@ -964,7 +966,7 @@ static int wanpipe_release(struct socket *sock)
*/
if (wp->num == htons(X25_PROT) &&
- sk->sk_state != WANSOCK_DISCONNECTED && sk->sk_zapped) {
+ sk->sk_state != WANSOCK_DISCONNECTED && sock_flag(sk, SOCK_ZAPPED)) {
struct net_device *dev = dev_get_by_index(sk->sk_bound_dev_if);
wanpipe_common_t *chan;
if (dev){
@@ -1075,15 +1077,15 @@ static void release_driver(struct sock *sk)
}
kfree_skb(skb);
}
- if (sk->sk_zapped)
+ if (sock_flag(sk, SOCK_ZAPPED))
wanpipe_unlink_card(sk);
}else{
- if (sk->sk_zapped)
+ if (sock_flag(sk, SOCK_ZAPPED))
wanpipe_unlink_driver(sk);
}
sk->sk_state = WANSOCK_DISCONNECTED;
sk->sk_bound_dev_if = 0;
- sk->sk_zapped = 0;
+ sock_reset_flag(sk, SOCK_ZAPPED);
wp = wp_sk(sk);
if (wp && wp->mbox) {
@@ -1261,7 +1263,7 @@ static int wanpipe_do_bind(struct sock *sk, struct net_device *dev,
wanpipe_common_t *chan=NULL;
int err=0;
- if (sk->sk_zapped) {
+ if (sock_flag(sk, SOCK_ZAPPED)) {
err = -EALREADY;
goto bind_unlock_exit;
}
@@ -1515,7 +1517,7 @@ static int wanpipe_create(struct socket *sock, int protocol)
sock->ops = &wanpipe_ops;
sock_init_data(sock,sk);
- sk->sk_zapped = 0;
+ sock_reset_flag(sk, SOCK_ZAPPED);
sk->sk_family = PF_WANPIPE;
wp_sk(sk)->num = protocol;
sk->sk_state = WANSOCK_DISCONNECTED;
@@ -1721,7 +1723,7 @@ static int wanpipe_notifier(struct notifier_block *this, unsigned long msg, void
case NETDEV_UNREGISTER:
if (dev->ifindex == sk->sk_bound_dev_if) {
printk(KERN_INFO "wansock: Device down %s\n",dev->name);
- if (sk->sk_zapped) {
+ if (sock_flag(sk, SOCK_ZAPPED)) {
wanpipe_unlink_driver(sk);
sk->sk_err = ENETDOWN;
sk->sk_error_report(sk);
@@ -1737,7 +1739,7 @@ static int wanpipe_notifier(struct notifier_block *this, unsigned long msg, void
break;
case NETDEV_UP:
if (dev->ifindex == sk->sk_bound_dev_if &&
- po->num && !sk->sk_zapped) {
+ po->num && !sock_flag(sk, SOCK_ZAPPED)) {
printk(KERN_INFO "wansock: Registering Device: %s\n",
dev->name);
wanpipe_link_driver(dev,sk);
@@ -2160,7 +2162,7 @@ static int wanpipe_link_card (struct sock *sk)
card->sk=sk;
card->func=wanpipe_listen_rcv;
- sk->sk_zapped = 1;
+ sock_set_flag(sk, SOCK_ZAPPED);
return 0;
}
@@ -2504,7 +2506,7 @@ static int wanpipe_connect(struct socket *sock, struct sockaddr *uaddr, int addr
dev_put(dev);
- if (!sk->sk_zapped) /* Must bind first - autobinding does not work */
+ if (!sock_flag(sk, SOCK_ZAPPED)) /* Must bind first - autobinding does not work */
return -EINVAL;
sock->state = SS_CONNECTING;
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c
index bbac184a94012..e05189a7f85fd 100644
--- a/net/x25/af_x25.c
+++ b/net/x25/af_x25.c
@@ -444,33 +444,23 @@ static int x25_listen(struct socket *sock, int backlog)
static struct sock *x25_alloc_socket(void)
{
- struct x25_opt *x25;
- struct sock *sk = sk_alloc(AF_X25, GFP_ATOMIC, 1, NULL);
+ struct x25_sock *x25;
+ struct sock *sk = sk_alloc(AF_X25, GFP_ATOMIC,
+ sizeof(struct x25_sock), NULL);
if (!sk)
goto out;
- x25 = sk->sk_protinfo = kmalloc(sizeof(*x25), GFP_ATOMIC);
- if (!x25)
- goto frees;
-
- memset(x25, 0, sizeof(*x25));
-
- x25->sk = sk;
-
sock_init_data(NULL, sk);
sk_set_owner(sk, THIS_MODULE);
+ x25 = x25_sk(sk);
skb_queue_head_init(&x25->ack_queue);
skb_queue_head_init(&x25->fragment_queue);
skb_queue_head_init(&x25->interrupt_in_queue);
skb_queue_head_init(&x25->interrupt_out_queue);
out:
return sk;
-frees:
- sk_free(sk);
- sk = NULL;
- goto out;
}
void x25_init_timers(struct sock *sk);
@@ -478,7 +468,7 @@ void x25_init_timers(struct sock *sk);
static int x25_create(struct socket *sock, int protocol)
{
struct sock *sk;
- struct x25_opt *x25;
+ struct x25_sock *x25;
int rc = -ESOCKTNOSUPPORT;
if (sock->type != SOCK_SEQPACKET || protocol)
@@ -519,7 +509,7 @@ out:
static struct sock *x25_make_new(struct sock *osk)
{
struct sock *sk = NULL;
- struct x25_opt *x25, *ox25;
+ struct x25_sock *x25, *ox25;
if (osk->sk_type != SOCK_SEQPACKET)
goto out;
@@ -535,12 +525,16 @@ static struct sock *x25_make_new(struct sock *osk)
sk->sk_protocol = osk->sk_protocol;
sk->sk_rcvbuf = osk->sk_rcvbuf;
sk->sk_sndbuf = osk->sk_sndbuf;
- sk->sk_debug = osk->sk_debug;
sk->sk_state = TCP_ESTABLISHED;
sk->sk_sleep = osk->sk_sleep;
- sk->sk_zapped = osk->sk_zapped;
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);
+
ox25 = x25_sk(osk);
x25->t21 = ox25->t21;
x25->t22 = ox25->t22;
@@ -557,7 +551,7 @@ out:
static int x25_release(struct socket *sock)
{
struct sock *sk = sock->sk;
- struct x25_opt *x25;
+ struct x25_sock *x25;
if (!sk)
goto out;
@@ -598,14 +592,14 @@ static int x25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
struct sock *sk = sock->sk;
struct sockaddr_x25 *addr = (struct sockaddr_x25 *)uaddr;
- if (!sk->sk_zapped ||
+ if (!sock_flag(sk, SOCK_ZAPPED) ||
addr_len != sizeof(struct sockaddr_x25) ||
addr->sx25_family != AF_X25)
return -EINVAL;
x25_sk(sk)->source_addr = addr->sx25_addr;
x25_insert_socket(sk);
- sk->sk_zapped = 0;
+ sock_reset_flag(sk, SOCK_ZAPPED);
SOCK_DEBUG(sk, "x25_bind: socket is bound\n");
return 0;
@@ -644,7 +638,7 @@ static int x25_connect(struct socket *sock, struct sockaddr *uaddr,
int addr_len, int flags)
{
struct sock *sk = sock->sk;
- struct x25_opt *x25 = x25_sk(sk);
+ struct x25_sock *x25 = x25_sk(sk);
struct sockaddr_x25 *addr = (struct sockaddr_x25 *)uaddr;
struct x25_route *rt;
int rc = 0;
@@ -689,7 +683,7 @@ static int x25_connect(struct socket *sock, struct sockaddr *uaddr,
goto out_put_neigh;
rc = -EINVAL;
- if (sk->sk_zapped) /* Must bind first - autobinding does not work */
+ if (sock_flag(sk, SOCK_ZAPPED)) /* Must bind first - autobinding does not work */
goto out_put_neigh;
if (!strcmp(x25->source_addr.x25_addr, null_x25_address.x25_addr))
@@ -802,7 +796,7 @@ static int x25_getname(struct socket *sock, struct sockaddr *uaddr,
{
struct sockaddr_x25 *sx25 = (struct sockaddr_x25 *)uaddr;
struct sock *sk = sock->sk;
- struct x25_opt *x25 = x25_sk(sk);
+ struct x25_sock *x25 = x25_sk(sk);
if (peer) {
if (sk->sk_state != TCP_ESTABLISHED)
@@ -822,7 +816,7 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb,
{
struct sock *sk;
struct sock *make;
- struct x25_opt *makex25;
+ struct x25_sock *makex25;
struct x25_address source_addr, dest_addr;
struct x25_facilities facilities;
struct x25_calluserdata calluserdata;
@@ -865,7 +859,7 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb,
/*
* We can't accept the Call Request.
*/
- if (!sk || sk->sk_ack_backlog == sk->sk_max_ack_backlog)
+ if (sk == NULL || sk_acceptq_is_full(sk))
goto out_clear_request;
/*
@@ -935,7 +929,7 @@ static int x25_sendmsg(struct kiocb *iocb, struct socket *sock,
struct msghdr *msg, size_t len)
{
struct sock *sk = sock->sk;
- struct x25_opt *x25 = x25_sk(sk);
+ struct x25_sock *x25 = x25_sk(sk);
struct sockaddr_x25 *usx25 = (struct sockaddr_x25 *)msg->msg_name;
struct sockaddr_x25 sx25;
struct sk_buff *skb;
@@ -952,7 +946,7 @@ static int x25_sendmsg(struct kiocb *iocb, struct socket *sock,
goto out;
rc = -EADDRNOTAVAIL;
- if (sk->sk_zapped)
+ if (sock_flag(sk, SOCK_ZAPPED))
goto out;
rc = -EPIPE;
@@ -1112,7 +1106,7 @@ static int x25_recvmsg(struct kiocb *iocb, struct socket *sock,
int flags)
{
struct sock *sk = sock->sk;
- struct x25_opt *x25 = x25_sk(sk);
+ struct x25_sock *x25 = x25_sk(sk);
struct sockaddr_x25 *sx25 = (struct sockaddr_x25 *)msg->msg_name;
size_t copied;
int qbit;
@@ -1201,7 +1195,7 @@ out:
static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
{
struct sock *sk = sock->sk;
- struct x25_opt *x25 = x25_sk(sk);
+ struct x25_sock *x25 = x25_sk(sk);
void __user *argp = (void __user *)arg;
int rc;
diff --git a/net/x25/x25_facilities.c b/net/x25/x25_facilities.c
index 1a25f40e93d2c..a21bdb95f9a8b 100644
--- a/net/x25/x25_facilities.c
+++ b/net/x25/x25_facilities.c
@@ -158,7 +158,7 @@ int x25_create_facilities(unsigned char *buffer,
int x25_negotiate_facilities(struct sk_buff *skb, struct sock *sk,
struct x25_facilities *new)
{
- struct x25_opt *x25 = x25_sk(sk);
+ struct x25_sock *x25 = x25_sk(sk);
struct x25_facilities *ours = &x25->facilities;
struct x25_facilities theirs;
int len;
diff --git a/net/x25/x25_in.c b/net/x25/x25_in.c
index 7b7697c4b0ef2..b0197c70a9fc5 100644
--- a/net/x25/x25_in.c
+++ b/net/x25/x25_in.c
@@ -34,7 +34,7 @@
static int x25_queue_rx_frame(struct sock *sk, struct sk_buff *skb, int more)
{
struct sk_buff *skbo, *skbn = skb;
- struct x25_opt *x25 = x25_sk(sk);
+ struct x25_sock *x25 = x25_sk(sk);
if (more) {
x25->fraglen += skb->len;
@@ -89,7 +89,7 @@ static int x25_state1_machine(struct sock *sk, struct sk_buff *skb, int frametyp
switch (frametype) {
case X25_CALL_ACCEPTED: {
- struct x25_opt *x25 = x25_sk(sk);
+ struct x25_sock *x25 = x25_sk(sk);
x25_stop_timer(sk);
x25->condition = 0x00;
@@ -165,7 +165,7 @@ static int x25_state3_machine(struct sock *sk, struct sk_buff *skb, int frametyp
{
int queued = 0;
int modulus;
- struct x25_opt *x25 = x25_sk(sk);
+ struct x25_sock *x25 = x25_sk(sk);
modulus = (x25->neighbour->extended) ? X25_EMODULUS : X25_SMODULUS;
@@ -295,7 +295,7 @@ static int x25_state4_machine(struct sock *sk, struct sk_buff *skb, int frametyp
case X25_RESET_REQUEST:
x25_write_internal(sk, X25_RESET_CONFIRMATION);
case X25_RESET_CONFIRMATION: {
- struct x25_opt *x25 = x25_sk(sk);
+ struct x25_sock *x25 = x25_sk(sk);
x25_stop_timer(sk);
x25->condition = 0x00;
@@ -322,7 +322,7 @@ static int x25_state4_machine(struct sock *sk, struct sk_buff *skb, int frametyp
/* Higher level upcall for a LAPB frame */
int x25_process_rx_frame(struct sock *sk, struct sk_buff *skb)
{
- struct x25_opt *x25 = x25_sk(sk);
+ struct x25_sock *x25 = x25_sk(sk);
int queued = 0, frametype, ns, nr, q, d, m;
if (x25->state == X25_STATE_0)
diff --git a/net/x25/x25_out.c b/net/x25/x25_out.c
index 1a0d3e46974d6..a2e62cea819a0 100644
--- a/net/x25/x25_out.c
+++ b/net/x25/x25_out.c
@@ -54,7 +54,7 @@ int x25_output(struct sock *sk, struct sk_buff *skb)
unsigned char header[X25_EXT_MIN_LEN];
int err, frontlen, len;
int sent=0, noblock = X25_SKB_CB(skb)->flags & MSG_DONTWAIT;
- struct x25_opt *x25 = x25_sk(sk);
+ struct x25_sock *x25 = x25_sk(sk);
int header_len = x25->neighbour->extended ? X25_EXT_MIN_LEN :
X25_STD_MIN_LEN;
int max_len = x25_pacsize_to_bytes(x25->facilities.pacsize_out);
@@ -116,7 +116,7 @@ int x25_output(struct sock *sk, struct sk_buff *skb)
*/
static void x25_send_iframe(struct sock *sk, struct sk_buff *skb)
{
- struct x25_opt *x25 = x25_sk(sk);
+ struct x25_sock *x25 = x25_sk(sk);
if (!skb)
return;
@@ -139,7 +139,7 @@ void x25_kick(struct sock *sk)
struct sk_buff *skb, *skbn;
unsigned short start, end;
int modulus;
- struct x25_opt *x25 = x25_sk(sk);
+ struct x25_sock *x25 = x25_sk(sk);
if (x25->state != X25_STATE_3)
return;
@@ -212,7 +212,7 @@ void x25_kick(struct sock *sk)
void x25_enquiry_response(struct sock *sk)
{
- struct x25_opt *x25 = x25_sk(sk);
+ struct x25_sock *x25 = x25_sk(sk);
if (x25->condition & X25_COND_OWN_RX_BUSY)
x25_write_internal(sk, X25_RNR);
diff --git a/net/x25/x25_proc.c b/net/x25/x25_proc.c
index 37c9447e589bd..dfb80116c59f5 100644
--- a/net/x25/x25_proc.c
+++ b/net/x25/x25_proc.c
@@ -134,7 +134,7 @@ static void x25_seq_socket_stop(struct seq_file *seq, void *v)
static int x25_seq_socket_show(struct seq_file *seq, void *v)
{
struct sock *s;
- struct x25_opt *x25;
+ struct x25_sock *x25;
struct net_device *dev;
const char *devname;
diff --git a/net/x25/x25_subr.c b/net/x25/x25_subr.c
index fd9b13029642a..183fea3bba676 100644
--- a/net/x25/x25_subr.c
+++ b/net/x25/x25_subr.c
@@ -33,7 +33,7 @@
*/
void x25_clear_queues(struct sock *sk)
{
- struct x25_opt *x25 = x25_sk(sk);
+ struct x25_sock *x25 = x25_sk(sk);
skb_queue_purge(&sk->sk_write_queue);
skb_queue_purge(&x25->ack_queue);
@@ -51,7 +51,7 @@ void x25_clear_queues(struct sock *sk)
void x25_frames_acked(struct sock *sk, unsigned short nr)
{
struct sk_buff *skb;
- struct x25_opt *x25 = x25_sk(sk);
+ struct x25_sock *x25 = x25_sk(sk);
int modulus = x25->neighbour->extended ? X25_EMODULUS : X25_SMODULUS;
/*
@@ -89,7 +89,7 @@ void x25_requeue_frames(struct sock *sk)
*/
int x25_validate_nr(struct sock *sk, unsigned short nr)
{
- struct x25_opt *x25 = x25_sk(sk);
+ struct x25_sock *x25 = x25_sk(sk);
unsigned short vc = x25->va;
int modulus = x25->neighbour->extended ? X25_EMODULUS : X25_SMODULUS;
@@ -108,7 +108,7 @@ int x25_validate_nr(struct sock *sk, unsigned short nr)
*/
void x25_write_internal(struct sock *sk, int frametype)
{
- struct x25_opt *x25 = x25_sk(sk);
+ struct x25_sock *x25 = x25_sk(sk);
struct sk_buff *skb;
unsigned char *dptr;
unsigned char facilities[X25_MAX_FAC_LEN];
@@ -248,7 +248,7 @@ void x25_write_internal(struct sock *sk, int frametype)
int x25_decode(struct sock *sk, struct sk_buff *skb, int *ns, int *nr, int *q,
int *d, int *m)
{
- struct x25_opt *x25 = x25_sk(sk);
+ struct x25_sock *x25 = x25_sk(sk);
unsigned char *frame = skb->data;
*ns = *nr = *q = *d = *m = 0;
@@ -315,7 +315,7 @@ int x25_decode(struct sock *sk, struct sk_buff *skb, int *ns, int *nr, int *q,
void x25_disconnect(struct sock *sk, int reason, unsigned char cause,
unsigned char diagnostic)
{
- struct x25_opt *x25 = x25_sk(sk);
+ struct x25_sock *x25 = x25_sk(sk);
x25_clear_queues(sk);
x25_stop_timer(sk);
@@ -342,7 +342,7 @@ void x25_disconnect(struct sock *sk, int reason, unsigned char cause,
*/
void x25_check_rbuf(struct sock *sk)
{
- struct x25_opt *x25 = x25_sk(sk);
+ struct x25_sock *x25 = x25_sk(sk);
if (atomic_read(&sk->sk_rmem_alloc) < (sk->sk_rcvbuf / 2) &&
(x25->condition & X25_COND_OWN_RX_BUSY)) {
diff --git a/net/x25/x25_timer.c b/net/x25/x25_timer.c
index 949faa7f6b92f..d6a21a3ad80e7 100644
--- a/net/x25/x25_timer.c
+++ b/net/x25/x25_timer.c
@@ -31,7 +31,7 @@ static void x25_timer_expiry(unsigned long);
void x25_init_timers(struct sock *sk)
{
- struct x25_opt *x25 = x25_sk(sk);
+ struct x25_sock *x25 = x25_sk(sk);
init_timer(&x25->timer);
x25->timer.data = (unsigned long)sk;
@@ -54,28 +54,28 @@ void x25_stop_heartbeat(struct sock *sk)
void x25_start_t2timer(struct sock *sk)
{
- struct x25_opt *x25 = x25_sk(sk);
+ struct x25_sock *x25 = x25_sk(sk);
mod_timer(&x25->timer, jiffies + x25->t2);
}
void x25_start_t21timer(struct sock *sk)
{
- struct x25_opt *x25 = x25_sk(sk);
+ struct x25_sock *x25 = x25_sk(sk);
mod_timer(&x25->timer, jiffies + x25->t21);
}
void x25_start_t22timer(struct sock *sk)
{
- struct x25_opt *x25 = x25_sk(sk);
+ struct x25_sock *x25 = x25_sk(sk);
mod_timer(&x25->timer, jiffies + x25->t22);
}
void x25_start_t23timer(struct sock *sk)
{
- struct x25_opt *x25 = x25_sk(sk);
+ struct x25_sock *x25 = x25_sk(sk);
mod_timer(&x25->timer, jiffies + x25->t23);
}
@@ -87,7 +87,7 @@ void x25_stop_timer(struct sock *sk)
unsigned long x25_display_timer(struct sock *sk)
{
- struct x25_opt *x25 = x25_sk(sk);
+ struct x25_sock *x25 = x25_sk(sk);
if (!timer_pending(&x25->timer))
return 0;
@@ -138,7 +138,7 @@ unlock:
*/
static inline void x25_do_timer_expiry(struct sock * sk)
{
- struct x25_opt *x25 = x25_sk(sk);
+ struct x25_sock *x25 = x25_sk(sk);
switch (x25->state) {
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 450b0a6f55dd3..fbf8270619255 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -301,18 +301,22 @@ static void xfrm_policy_gc_task(void *data)
static void xfrm_policy_kill(struct xfrm_policy *policy)
{
write_lock_bh(&policy->lock);
- if (policy->dead)
- goto out;
-
+ if (policy->dead) {
+ write_unlock_bh(&policy->lock);
+ return;
+ }
policy->dead = 1;
spin_lock(&xfrm_policy_gc_lock);
list_add(&policy->list, &xfrm_policy_gc_list);
+ /*
+ * Unlock the policy (out of order unlocking), to make sure
+ * the GC context does not free it with an active lock:
+ */
+ write_unlock_bh(&policy->lock);
spin_unlock(&xfrm_policy_gc_lock);
- schedule_work(&xfrm_policy_gc_work);
-out:
- write_unlock_bh(&policy->lock);
+ schedule_work(&xfrm_policy_gc_work);
}
/* Generate new index... KAME seems to generate them ordered by cost
@@ -1015,28 +1019,20 @@ static struct dst_entry *xfrm_dst_check(struct dst_entry *dst, u32 cookie)
if (!stale_bundle(dst))
return dst;
- dst_release(dst);
return NULL;
}
static int stale_bundle(struct dst_entry *dst)
{
- struct dst_entry *child = dst;
-
- while (child) {
- if (child->obsolete > 0 ||
- (child->dev && !netif_running(child->dev)) ||
- (child->xfrm && child->xfrm->km.state != XFRM_STATE_VALID)) {
- return 1;
- }
- child = child->child;
- }
-
- return 0;
+ return !xfrm_bundle_ok((struct xfrm_dst *)dst, NULL, AF_UNSPEC);
}
static void xfrm_dst_destroy(struct dst_entry *dst)
{
+ struct xfrm_dst *xdst = (struct xfrm_dst *)dst;
+
+ dst_release(xdst->route);
+
if (!dst->xfrm)
return;
xfrm_state_put(dst->xfrm);
@@ -1121,6 +1117,94 @@ int xfrm_flush_bundles(void)
return 0;
}
+void xfrm_init_pmtu(struct dst_entry *dst)
+{
+ do {
+ struct xfrm_dst *xdst = (struct xfrm_dst *)dst;
+ u32 pmtu, route_mtu_cached;
+
+ pmtu = dst_mtu(dst->child);
+ xdst->child_mtu_cached = pmtu;
+
+ pmtu = xfrm_state_mtu(dst->xfrm, pmtu);
+
+ route_mtu_cached = dst_mtu(xdst->route);
+ xdst->route_mtu_cached = route_mtu_cached;
+
+ if (pmtu > route_mtu_cached)
+ pmtu = route_mtu_cached;
+
+ dst->metrics[RTAX_MTU-1] = pmtu;
+ } while ((dst = dst->next));
+}
+
+EXPORT_SYMBOL(xfrm_init_pmtu);
+
+/* Check that the bundle accepts the flow and its components are
+ * still valid.
+ */
+
+int xfrm_bundle_ok(struct xfrm_dst *first, struct flowi *fl, int family)
+{
+ struct dst_entry *dst = &first->u.dst;
+ struct xfrm_dst *last;
+ u32 mtu;
+
+ if (!dst_check(dst->path, 0) ||
+ (dst->dev && !netif_running(dst->dev)))
+ return 0;
+
+ last = NULL;
+
+ do {
+ struct xfrm_dst *xdst = (struct xfrm_dst *)dst;
+
+ if (fl && !xfrm_selector_match(&dst->xfrm->sel, fl, family))
+ return 0;
+ if (dst->xfrm->km.state != XFRM_STATE_VALID)
+ return 0;
+
+ mtu = dst_mtu(dst->child);
+ if (xdst->child_mtu_cached != mtu) {
+ last = xdst;
+ xdst->child_mtu_cached = mtu;
+ }
+
+ if (!dst_check(xdst->route, 0))
+ return 0;
+ mtu = dst_mtu(xdst->route);
+ if (xdst->route_mtu_cached != mtu) {
+ last = xdst;
+ xdst->route_mtu_cached = mtu;
+ }
+
+ dst = dst->child;
+ } while (dst->xfrm);
+
+ if (likely(!last))
+ return 1;
+
+ mtu = last->child_mtu_cached;
+ for (;;) {
+ dst = &last->u.dst;
+
+ mtu = xfrm_state_mtu(dst->xfrm, mtu);
+ if (mtu > last->route_mtu_cached)
+ mtu = last->route_mtu_cached;
+ dst->metrics[RTAX_MTU-1] = mtu;
+
+ if (last == first)
+ break;
+
+ last = last->u.next;
+ last->child_mtu_cached = mtu;
+ }
+
+ return 1;
+}
+
+EXPORT_SYMBOL(xfrm_bundle_ok);
+
/* Well... that's _TASK_. We need to scan through transformation
* list and figure out what mss tcp should generate in order to
* final datagram fit to mtu. Mama mia... :-)
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index e43aa8c274836..78d6c52a65ccb 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -609,7 +609,7 @@ static struct xfrm_state *__xfrm_find_acq_byseq(u32 seq)
for (i = 0; i < XFRM_DST_HSIZE; i++) {
list_for_each_entry(x, xfrm_state_bydst+i, bydst) {
- if (x->km.seq == seq) {
+ if (x->km.seq == seq && x->km.state == XFRM_STATE_ACQ) {
xfrm_state_hold(x);
return x;
}
@@ -966,6 +966,36 @@ void xfrm_state_delete_tunnel(struct xfrm_state *x)
}
EXPORT_SYMBOL(xfrm_state_delete_tunnel);
+int xfrm_state_mtu(struct xfrm_state *x, int mtu)
+{
+ int res = mtu;
+
+ res -= x->props.header_len;
+
+ for (;;) {
+ int m = res;
+
+ if (m < 68)
+ return 68;
+
+ spin_lock_bh(&x->lock);
+ if (x->km.state == XFRM_STATE_VALID &&
+ x->type && x->type->get_max_size)
+ m = x->type->get_max_size(x, m);
+ else
+ m += x->props.header_len;
+ spin_unlock_bh(&x->lock);
+
+ if (m <= mtu)
+ break;
+ res -= (m - mtu);
+ }
+
+ return res;
+}
+
+EXPORT_SYMBOL(xfrm_state_mtu);
+
void __init xfrm_state_init(void)
{
int i;
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 6e75ced8b583a..7cf75cc4f849d 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -183,15 +183,24 @@ cmd_gzip = gzip -f -9 < $< > $@
# Generic stuff
# ===========================================================================
+ifneq ($(KBUILD_NOCMDDEP),1)
+# Check if both arguments has same arguments. Result in empty string if equal
+# User may override this check using make KBUILD_NOCMDDEP=1
+arg-check = $(strip $(filter-out $(1), $(2)) $(filter-out $(2), $(1)) )
+
+endif
+
+# echo command. Short version is $(quiet) equals quiet, otherwise full command
+echo-cmd = $(if $($(quiet)cmd_$(1)), \
+ echo ' $(subst ','\'',$($(quiet)cmd_$(1)))';)
+
# function to only execute the passed command if necessary
# >'< substitution is for echo to work, >$< substitution to preserve $ when reloading .cmd file
# note: when using inline perl scripts [perl -e '...$$t=1;...'] in $(cmd_xxx) double $$ your perl vars
-
-if_changed = $(if $(strip $? \
- $(filter-out $(cmd_$(1)),$(cmd_$@))\
- $(filter-out $(cmd_$@),$(cmd_$(1)))),\
+#
+if_changed = $(if $(strip $? $(call arg-check, $(cmd_$(1)), $(cmd_$@)) ), \
@set -e; \
- $(if $($(quiet)cmd_$(1)),echo ' $(subst ','\'',$($(quiet)cmd_$(1)))';) \
+ $(echo-cmd) \
$(cmd_$(1)); \
echo 'cmd_$@ := $(subst $$,$$$$,$(subst ','\'',$(cmd_$(1))))' > $(@D)/.$(@F).cmd)
@@ -200,10 +209,9 @@ if_changed = $(if $(strip $? \
# file
if_changed_dep = $(if $(strip $? $(filter-out FORCE $(wildcard $^),$^)\
- $(filter-out $(cmd_$(1)),$(cmd_$@))\
- $(filter-out $(cmd_$@),$(cmd_$(1)))),\
+ $(call arg-check, $(cmd_$(1)), $(cmd_$@)) ), \
@set -e; \
- $(if $($(quiet)cmd_$(1)),echo ' $(subst ','\'',$($(quiet)cmd_$(1)))';) \
+ $(echo-cmd) \
$(cmd_$(1)); \
scripts/basic/fixdep $(depfile) $@ '$(subst $$,$$$$,$(subst ','\'',$(cmd_$(1))))' > $(@D)/.$(@F).tmp; \
rm -f $(depfile); \
@@ -213,9 +221,7 @@ if_changed_dep = $(if $(strip $? $(filter-out FORCE $(wildcard $^),$^)\
# will check if $(cmd_foo) changed, or any of the prequisites changed,
# and if so will execute $(rule_foo)
-if_changed_rule = $(if $(strip $? \
- $(filter-out $(cmd_$(1)),$(cmd_$@))\
- $(filter-out $(cmd_$@),$(cmd_$(1)))),\
+if_changed_rule = $(if $(strip $? $(call arg-check, $(cmd_$(1)), $(cmd_$@)) ),\
@set -e; \
$(rule_$(1)))
diff --git a/scripts/Makefile.modinst b/scripts/Makefile.modinst
index ba47b7fcb1404..85d6494e3c24a 100644
--- a/scripts/Makefile.modinst
+++ b/scripts/Makefile.modinst
@@ -21,8 +21,9 @@ quiet_cmd_modules_install = INSTALL $@
# Modules built outside the kernel source tree go into extra by default
INSTALL_MOD_DIR ?= extra
+ext-mod-dir = $(INSTALL_MOD_DIR)$(subst $(KBUILD_EXTMOD),,$(@D))
-modinst_dir = $(MODLIB)/$(if $(filter ../% /%,$@),$(INSTALL_MOD_DIR)/,kernel/$(@D))
+modinst_dir = $(if $(KBUILD_EXTMOD),$(ext-mod-dir),kernel/$(@D))
$(modules):
- $(call cmd,modules_install,$(modinst_dir))
+ $(call cmd,modules_install,$(MODLIB)/$(modinst_dir))
diff --git a/scripts/checkstack.pl b/scripts/checkstack.pl
index dd2db95d466db..dadfa20ffec01 100644
--- a/scripts/checkstack.pl
+++ b/scripts/checkstack.pl
@@ -9,6 +9,7 @@
# Mips port by Juan Quintela <quintela@mandrakesoft.com>
# IA64 port via Andreas Dilger
# Arm port by Holger Schurig
+# sh64 port by Paul Mundt
# Random bits by Matt Mackall <mpm@selenic.com>
# M68k port by Geert Uytterhoeven and Andreas Schwab
#
@@ -64,6 +65,12 @@ my (@stack, $re, $x, $xs);
} elsif ($arch =~ /^s390x?$/) {
# 11160: a7 fb ff 60 aghi %r15,-160
$re = qr/.*ag?hi.*\%r15,-(([0-9]{2}|[3-9])[0-9]{2})/o;
+ } elsif ($arch =~ /^sh64$/) {
+ #XXX: we only check for the immediate case presently,
+ # though we will want to check for the movi/sub
+ # pair for larger users. -- PFM.
+ #a00048e0: d4fc40f0 addi.l r15,-240,r15
+ $re = qr/.*addi\.l.*r15,-(([0-9]{2}|[3-9])[0-9]{2}),r15/o;
} else {
print("wrong or unknown architecture\n");
exit
@@ -72,8 +79,8 @@ my (@stack, $re, $x, $xs);
sub bysize($) {
my ($asize, $bsize);
- ($asize = $a) =~ s/.* +(.*)$/$1/;
- ($bsize = $b) =~ s/.* +(.*)$/$1/;
+ ($asize = $a) =~ s/.*: *(.*)$/$1/;
+ ($bsize = $b) =~ s/.*: *(.*)$/$1/;
$bsize <=> $asize
}
@@ -90,11 +97,12 @@ while (my $line = <STDIN>) {
my $size = $1;
$size = hex($size) if ($size =~ /^0x/);
- if ($size > 0x80000000) {
+ if ($size > 0xf0000000) {
$size = - $size;
$size += 0x80000000;
$size += 0x80000000;
}
+ next if ($size > 0x10000000);
next if $line !~ m/^($xs*)/;
my $addr = $1;
diff --git a/scripts/genksyms/genksyms.h b/scripts/genksyms/genksyms.h
index 7b711731abf27..f09af47ab2814 100644
--- a/scripts/genksyms/genksyms.h
+++ b/scripts/genksyms/genksyms.h
@@ -25,7 +25,6 @@
#define MODUTILS_GENKSYMS_H 1
#include <stdio.h>
-#include <assert.h>
enum symbol_type
@@ -89,8 +88,17 @@ void error_with_pos(const char *, ...);
#define MODUTILS_VERSION "<in-kernel>"
-#define xmalloc(size) ({ void *__ptr = malloc(size); assert(__ptr || size == 0); __ptr; })
-#define xstrdup(str) ({ char *__str = strdup(str); assert(__str); __str; })
-
+#define xmalloc(size) ({ void *__ptr = malloc(size); \
+ if(!__ptr && size != 0) { \
+ fprintf(stderr, "out of memory\n"); \
+ exit(1); \
+ } \
+ __ptr; })
+#define xstrdup(str) ({ char *__str = strdup(str); \
+ if (!__str) { \
+ fprintf(stderr, "out of memory\n"); \
+ exit(1); \
+ } \
+ __str; })
#endif /* genksyms.h */
diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile
index 51492ba6fbcd2..5a5ddc40f36ce 100644
--- a/scripts/kconfig/Makefile
+++ b/scripts/kconfig/Makefile
@@ -50,10 +50,12 @@ endif
# Help text used by make help
help:
- @echo ' oldconfig - Update current config utilising a line-oriented program'
+ @echo ' config - Update current config utilising a line-oriented program'
@echo ' menuconfig - Update current config utilising a menu based program'
@echo ' xconfig - Update current config utilising a QT based front-end'
@echo ' gconfig - Update current config utilising a GTK based front-end'
+ @echo ' oldconfig - Update current config utilising a provided .config as base'
+ @echo ' randconfig - New config with random answer to all options'
@echo ' defconfig - New config with default answer to all options'
@echo ' allmodconfig - New config selecting modules when possible'
@echo ' allyesconfig - New config where all options are accepted with yes'
@@ -107,6 +109,10 @@ HOSTCFLAGS_gconf.o = `pkg-config gtk+-2.0 gmodule-2.0 libglade-2.0 --cflags` \
$(obj)/conf.o $(obj)/mconf.o $(obj)/qconf.o $(obj)/gconf.o: $(obj)/zconf.tab.h
+$(obj)/zconf.tab.h: $(src)/zconf.tab.h_shipped
+$(obj)/zconf.tab.c: $(src)/zconf.tab.c_shipped
+$(obj)/lex.zconf.c: $(src)/lex.zconf.c_shipped
+
$(obj)/qconf.o: $(obj)/.tmp_qtcheck
ifeq ($(qconf-target),1)
diff --git a/scripts/kconfig/gconf.c b/scripts/kconfig/gconf.c
index ed4afa063fb6e..6fdbe6e3ce0dc 100644
--- a/scripts/kconfig/gconf.c
+++ b/scripts/kconfig/gconf.c
@@ -187,6 +187,8 @@ void init_main_window(const gchar * glade_file)
GtkWidget *widget;
GtkTextBuffer *txtbuf;
char title[256];
+ GdkPixmap *pixmap;
+ GdkBitmap *mask;
GtkStyle *style;
xml = glade_xml_new(glade_file, "window1", NULL);
@@ -219,18 +221,48 @@ void init_main_window(const gchar * glade_file)
style = gtk_widget_get_style(main_wnd);
widget = glade_xml_get_widget(xml, "toolbar1");
+ pixmap = gdk_pixmap_create_from_xpm_d(main_wnd->window, &mask,
+ &style->bg[GTK_STATE_NORMAL],
+ (gchar **) xpm_single_view);
+ gtk_image_set_from_pixmap(GTK_IMAGE
+ (((GtkToolbarChild
+ *) (g_list_nth(GTK_TOOLBAR(widget)->
+ children,
+ 5)->data))->icon),
+ pixmap, mask);
+ pixmap =
+ gdk_pixmap_create_from_xpm_d(main_wnd->window, &mask,
+ &style->bg[GTK_STATE_NORMAL],
+ (gchar **) xpm_split_view);
+ gtk_image_set_from_pixmap(GTK_IMAGE
+ (((GtkToolbarChild
+ *) (g_list_nth(GTK_TOOLBAR(widget)->
+ children,
+ 6)->data))->icon),
+ pixmap, mask);
+ pixmap =
+ gdk_pixmap_create_from_xpm_d(main_wnd->window, &mask,
+ &style->bg[GTK_STATE_NORMAL],
+ (gchar **) xpm_tree_view);
+ gtk_image_set_from_pixmap(GTK_IMAGE
+ (((GtkToolbarChild
+ *) (g_list_nth(GTK_TOOLBAR(widget)->
+ children,
+ 7)->data))->icon),
+ pixmap, mask);
+
switch (view_mode) {
case SINGLE_VIEW:
widget = glade_xml_get_widget(xml, "button4");
- gtk_button_clicked(GTK_BUTTON(widget));
+ g_signal_emit_by_name(widget, "clicked");
break;
case SPLIT_VIEW:
widget = glade_xml_get_widget(xml, "button5");
- gtk_button_clicked(GTK_BUTTON(widget));
+ g_signal_emit_by_name(widget, "clicked");
break;
case FULL_VIEW:
widget = glade_xml_get_widget(xml, "button6");
- gtk_button_clicked(GTK_BUTTON(widget));
+ g_signal_emit_by_name(widget, "clicked");
break;
}
@@ -1140,9 +1172,6 @@ on_treeview1_button_press_event(GtkWidget * widget,
}
-/* Conf management */
-
-
/* Fill a row of strings */
static gchar **fill_row(struct menu *menu)
{
diff --git a/scripts/kconfig/gconf.glade b/scripts/kconfig/gconf.glade
index 5ed75a7aeece8..1e1736d81ee95 100644
--- a/scripts/kconfig/gconf.glade
+++ b/scripts/kconfig/gconf.glade
@@ -310,13 +310,13 @@
<property name="tooltips">True</property>
<child>
- <widget class="GtkToolButton" id="button1">
+ <widget class="button" id="button1">
<property name="visible">True</property>
<property name="tooltip" translatable="yes">Goes up of one level (single view)</property>
<property name="label" translatable="yes">Back</property>
<property name="use_underline">True</property>
- <property name="stock-id">gtk-undo</property>
- <signal name="clicked" handler="on_back_pressed"/>
+ <property name="stock_pixmap">gtk-undo</property>
+ <signal name="pressed" handler="on_back_pressed"/>
</widget>
</child>
@@ -327,24 +327,24 @@
</child>
<child>
- <widget class="GtkToolButton" id="button2">
+ <widget class="button" id="button2">
<property name="visible">True</property>
<property name="tooltip" translatable="yes">Load a config file</property>
<property name="label" translatable="yes">Load</property>
<property name="use_underline">True</property>
- <property name="stock-id">gtk-open</property>
- <signal name="clicked" handler="on_load_pressed"/>
+ <property name="stock_pixmap">gtk-open</property>
+ <signal name="pressed" handler="on_load_pressed"/>
</widget>
</child>
<child>
- <widget class="GtkToolButton" id="button3">
+ <widget class="button" id="button3">
<property name="visible">True</property>
<property name="tooltip" translatable="yes">Save a config file</property>
<property name="label" translatable="yes">Save</property>
<property name="use_underline">True</property>
- <property name="stock-id">gtk-save</property>
- <signal name="clicked" handler="on_save_pressed"/>
+ <property name="stock_pixmap">gtk-save</property>
+ <signal name="pressed" handler="on_save_pressed"/>
</widget>
</child>
@@ -355,34 +355,34 @@
</child>
<child>
- <widget class="GtkToolButton" id="button4">
+ <widget class="button" id="button4">
<property name="visible">True</property>
<property name="tooltip" translatable="yes">Single view</property>
<property name="label" translatable="yes">Single</property>
<property name="use_underline">True</property>
- <property name="stock-id">gtk-indent</property>
+ <property name="stock_pixmap">gtk-missing-image</property>
<signal name="clicked" handler="on_single_clicked" last_modification_time="Sun, 12 Jan 2003 14:28:39 GMT"/>
</widget>
</child>
<child>
- <widget class="GtkToolButton" id="button5">
+ <widget class="button" id="button5">
<property name="visible">True</property>
<property name="tooltip" translatable="yes">Split view</property>
<property name="label" translatable="yes">Split</property>
<property name="use_underline">True</property>
- <property name="stock-id">gtk-copy</property>
+ <property name="stock_pixmap">gtk-missing-image</property>
<signal name="clicked" handler="on_split_clicked" last_modification_time="Sun, 12 Jan 2003 14:28:45 GMT"/>
</widget>
</child>
<child>
- <widget class="GtkToolButton" id="button6">
+ <widget class="button" id="button6">
<property name="visible">True</property>
<property name="tooltip" translatable="yes">Full view</property>
<property name="label" translatable="yes">Full</property>
<property name="use_underline">True</property>
- <property name="stock-id">gtk-justify-left</property>
+ <property name="stock_pixmap">gtk-missing-image</property>
<signal name="clicked" handler="on_full_clicked" last_modification_time="Sun, 12 Jan 2003 14:28:50 GMT"/>
</widget>
</child>
@@ -394,24 +394,22 @@
</child>
<child>
- <widget class="GtkToolButton" id="button7">
+ <widget class="button" id="button7">
<property name="visible">True</property>
<property name="tooltip" translatable="yes">Collapse the whole tree in the right frame</property>
<property name="label" translatable="yes">Collapse</property>
<property name="use_underline">True</property>
- <property name="stock-id">gtk-zoom-out</property>
- <signal name="clicked" handler="on_collapse_pressed"/>
+ <signal name="pressed" handler="on_collapse_pressed"/>
</widget>
</child>
<child>
- <widget class="GtkToolButton" id="button8">
+ <widget class="button" id="button8">
<property name="visible">True</property>
<property name="tooltip" translatable="yes">Expand the whole tree in the right frame</property>
<property name="label" translatable="yes">Expand</property>
<property name="use_underline">True</property>
- <property name="stock-id">gtk-zoom-in</property>
- <signal name="clicked" handler="on_expand_pressed"/>
+ <signal name="pressed" handler="on_expand_pressed"/>
</widget>
</child>
</widget>
diff --git a/scripts/kernel-doc b/scripts/kernel-doc
index a2eaf382aa485..8b1dab63f11ca 100755
--- a/scripts/kernel-doc
+++ b/scripts/kernel-doc
@@ -170,14 +170,14 @@ my %highlights_html = ( $type_constant, "<i>\$1</i>",
$type_param, "<tt><b>\$1</b></tt>" );
my $blankline_html = "<p>";
-# sgml, docbook format
-my %highlights_sgml = ( "([^=])\\\"([^\\\"<]+)\\\"", "\$1<quote>\$2</quote>",
+# XML, docbook format
+my %highlights_xml = ( "([^=])\\\"([^\\\"<]+)\\\"", "\$1<quote>\$2</quote>",
$type_constant, "<constant>\$1</constant>",
$type_func, "<function>\$1</function>",
$type_struct, "<structname>\$1</structname>",
$type_env, "<envar>\$1</envar>",
$type_param, "<parameter>\$1</parameter>" );
-my $blankline_sgml = "</para><para>\n";
+my $blankline_xml = "</para><para>\n";
# gnome, docbook format
my %highlights_gnome = ( $type_constant, "<replaceable class=\"option\">\$1</replaceable>",
@@ -297,14 +297,14 @@ while ($ARGV[0] =~ m/^-(.*)/) {
%highlights = %highlights_text;
$blankline = $blankline_text;
} elsif ($cmd eq "-docbook") {
- $output_mode = "sgml";
- %highlights = %highlights_sgml;
- $blankline = $blankline_sgml;
+ $output_mode = "xml";
+ %highlights = %highlights_xml;
+ $blankline = $blankline_xml;
} elsif ($cmd eq "-gnome") {
$output_mode = "gnome";
%highlights = %highlights_gnome;
$blankline = $blankline_gnome;
- } elsif ($cmd eq "-module") { # not needed for sgml, inherits from calling document
+ } elsif ($cmd eq "-module") { # not needed for XML, inherits from calling document
$modulename = shift @ARGV;
} elsif ($cmd eq "-function") { # to only output specific functions
$function_only = 1;
@@ -547,7 +547,7 @@ sub output_intro_html(%) {
print "<hr>\n";
}
-sub output_section_sgml(%) {
+sub output_section_xml(%) {
my %args = %{$_[0]};
my $section;
# print out each section
@@ -565,8 +565,8 @@ sub output_section_sgml(%) {
}
}
-# output function in sgml DocBook
-sub output_function_sgml(%) {
+# output function in XML DocBook
+sub output_function_xml(%) {
my %args = %{$_[0]};
my ($parameter, $section);
my $count;
@@ -632,12 +632,12 @@ sub output_function_sgml(%) {
}
print "</refsect1>\n";
- output_section_sgml(@_);
+ output_section_xml(@_);
print "</refentry>\n\n";
}
-# output struct in sgml DocBook
-sub output_struct_sgml(%) {
+# output struct in XML DocBook
+sub output_struct_xml(%) {
my %args = %{$_[0]};
my ($parameter, $section);
my $id;
@@ -708,13 +708,13 @@ sub output_struct_sgml(%) {
print " </variablelist>\n";
print " </refsect1>\n";
- output_section_sgml(@_);
+ output_section_xml(@_);
print "</refentry>\n\n";
}
-# output enum in sgml DocBook
-sub output_enum_sgml(%) {
+# output enum in XML DocBook
+sub output_enum_xml(%) {
my %args = %{$_[0]};
my ($parameter, $section);
my $count;
@@ -769,13 +769,13 @@ sub output_enum_sgml(%) {
print " </variablelist>\n";
print "</refsect1>\n";
- output_section_sgml(@_);
+ output_section_xml(@_);
print "</refentry>\n\n";
}
-# output typedef in sgml DocBook
-sub output_typedef_sgml(%) {
+# output typedef in XML DocBook
+sub output_typedef_xml(%) {
my %args = %{$_[0]};
my ($parameter, $section);
my $id;
@@ -800,13 +800,13 @@ sub output_typedef_sgml(%) {
print " <synopsis>typedef ".$args{'typedef'}.";</synopsis>\n";
print "</refsynopsisdiv>\n";
- output_section_sgml(@_);
+ output_section_xml(@_);
print "</refentry>\n\n";
}
-# output in sgml DocBook
-sub output_intro_sgml(%) {
+# output in XML DocBook
+sub output_intro_xml(%) {
my %args = %{$_[0]};
my ($parameter, $section);
my $count;
@@ -831,7 +831,7 @@ sub output_intro_sgml(%) {
print "\n\n";
}
-# output in sgml DocBook
+# output in XML DocBook
sub output_function_gnome {
my %args = %{$_[0]};
my ($parameter, $section);
@@ -1578,13 +1578,13 @@ sub process_state3_function($$) {
my $x = shift;
my $file = shift;
- if ($x =~ m#\s*/\*\s+MACDOC\s*#io) {
+ if ($x =~ m#\s*/\*\s+MACDOC\s*#io || ($x =~ /^#/ && $x !~ /^#define/)) {
# do nothing
}
elsif ($x =~ /([^\{]*)/) {
$prototype .= $1;
}
- if (($x =~ /\{/) || ($x =~ /\#/) || ($x =~ /;/)) {
+ if (($x =~ /\{/) || ($x =~ /\#define/) || ($x =~ /;/)) {
$prototype =~ s@/\*.*?\*/@@gos; # strip comments.
$prototype =~ s@[\r\n]+@ @gos; # strip newlines/cr's.
$prototype =~ s@^\s+@@gos; # strip leading spaces
@@ -1624,6 +1624,15 @@ sub process_state3_type($$) {
}
}
+# replace <, >, and &
+sub xml_escape($) {
+ my $text = shift;
+ $text =~ s/\&/\\\\\\amp;/g;
+ $text =~ s/\</\\\\\\lt;/g;
+ $text =~ s/\>/\\\\\\gt;/g;
+ return $text;
+}
+
sub process_file($) {
my ($file) = "$ENV{'SRCTREE'}@_";
my $identifier;
@@ -1664,7 +1673,7 @@ sub process_file($) {
$state = 2;
if (/-(.*)/) {
- $declaration_purpose = $1;
+ $declaration_purpose = xml_escape($1);
} else {
$declaration_purpose = "";
}
@@ -1695,10 +1704,7 @@ sub process_file($) {
$newcontents = $2;
if ($contents ne "") {
- $contents =~ s/\&/\\\\\\amp;/g;
- $contents =~ s/\</\\\\\\lt;/g;
- $contents =~ s/\>/\\\\\\gt;/g;
- dump_section($section, $contents);
+ dump_section($section, xml_escape($contents));
$section = $section_default;
}
@@ -1710,10 +1716,7 @@ sub process_file($) {
} elsif (/$doc_end/) {
if ($contents ne "") {
- $contents =~ s/\&/\\\\\\amp;/g;
- $contents =~ s/\</\\\\\\lt;/g;
- $contents =~ s/\>/\\\\\\gt;/g;
- dump_section($section, $contents);
+ dump_section($section, xml_escape($contents));
$section = $section_default;
$contents = "";
}
@@ -1727,10 +1730,7 @@ sub process_file($) {
# @parameter line to signify start of description
if ($1 eq "" &&
($section =~ m/^@/ || $section eq $section_context)) {
- $contents =~ s/\&/\\\\\\amp;/g;
- $contents =~ s/\</\\\\\\lt;/g;
- $contents =~ s/\>/\\\\\\gt;/g;
- dump_section($section, $contents);
+ dump_section($section, xml_escape($contents));
$section = $section_default;
$contents = "";
} else {
@@ -1799,7 +1799,7 @@ sub process_file($) {
}
if ($initial_section_counter == $section_counter) {
print STDERR "Warning(${file}): no structured comments found\n";
- if ($output_mode eq "sgml") {
+ if ($output_mode eq "xml") {
# The template wants at least one RefEntry here; make one.
print "<refentry>\n";
print " <refnamediv>\n";
diff --git a/scripts/lxdialog/checklist.c b/scripts/lxdialog/checklist.c
index 99705fe65bf14..7aba17c72e64a 100644
--- a/scripts/lxdialog/checklist.c
+++ b/scripts/lxdialog/checklist.c
@@ -269,7 +269,7 @@ dialog_checklist (const char *title, const char *prompt, int height, int width,
status[scroll + max_choice - 1],
max_choice - 1, FALSE);
scrollok (list, TRUE);
- scroll (list);
+ wscrl (list, 1);
scrollok (list, FALSE);
}
scroll++;
diff --git a/scripts/lxdialog/colors.h b/scripts/lxdialog/colors.h
index d34dd37c6f745..25c59528a2510 100644
--- a/scripts/lxdialog/colors.h
+++ b/scripts/lxdialog/colors.h
@@ -152,10 +152,4 @@
* Global variables
*/
-typedef struct {
- char name[COLOR_NAME_LEN];
- int value;
-} color_names_st;
-
-extern color_names_st color_names[];
extern int color_table[][3];
diff --git a/scripts/lxdialog/lxdialog.c b/scripts/lxdialog/lxdialog.c
index 6f4c1fd4eba5f..f283a8545426c 100644
--- a/scripts/lxdialog/lxdialog.c
+++ b/scripts/lxdialog/lxdialog.c
@@ -56,7 +56,7 @@ static struct Mode *modePtr;
int
main (int argc, const char * const * argv)
{
- int offset = 0, clear_screen = 0, end_common_opts = 0, retval;
+ int offset = 0, opt_clear = 0, end_common_opts = 0, retval;
const char *title = NULL;
#ifdef LOCALE
@@ -89,7 +89,7 @@ main (int argc, const char * const * argv)
offset += 2;
}
} else if (!strcmp (argv[offset + 1], "--clear")) {
- if (clear_screen) { /* Hey, "--clear" can't appear twice! */
+ 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 */
@@ -98,7 +98,7 @@ main (int argc, const char * const * argv)
end_dialog ();
return 0;
} else {
- clear_screen = 1;
+ opt_clear = 1;
offset++;
}
} else /* no more common options */
@@ -127,7 +127,7 @@ main (int argc, const char * const * argv)
init_dialog ();
retval = (*(modePtr->jumper)) (title, argc - offset, argv + offset);
- if (clear_screen) { /* clear screen before exit */
+ if (opt_clear) { /* clear screen before exit */
attr_clear (stdscr, LINES, COLS, screen_attr);
refresh ();
}
diff --git a/scripts/lxdialog/menubox.c b/scripts/lxdialog/menubox.c
index ce2a990594314..91d82ba17f8d0 100644
--- a/scripts/lxdialog/menubox.c
+++ b/scripts/lxdialog/menubox.c
@@ -327,7 +327,7 @@ dialog_menu (const char *title, const char *prompt, int height, int width,
) {
/* Scroll menu up */
scrollok (menu, TRUE);
- scroll (menu);
+ wscrl (menu, 1);
scrollok (menu, FALSE);
scroll++;
@@ -357,7 +357,7 @@ dialog_menu (const char *title, const char *prompt, int height, int width,
for (i=0; (i < max_choice); i++) {
if (scroll+max_choice < item_no) {
scrollok (menu, TRUE);
- scroll(menu);
+ wscrl (menu, 1);
scrollok (menu, FALSE);
scroll++;
print_item (menu, items[(scroll+max_choice-1)*2+1],
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index 7c8f064f03bbe..d54b52d3bb6fe 100644
--- a/scripts/mod/file2alias.c
+++ b/scripts/mod/file2alias.c
@@ -4,7 +4,7 @@
*
* Copyright 2002-2003 Rusty Russell, IBM Corporation
* 2003 Kai Germaschewski
- *
+ *
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
@@ -181,6 +181,24 @@ static int do_ccw_entry(const char *filename,
return 1;
}
+/* Looks like: "serio:tyNprNidNexN" */
+static int do_serio_entry(const char *filename,
+ struct serio_device_id *id, char *alias)
+{
+ id->type = TO_NATIVE(id->type);
+ id->proto = TO_NATIVE(id->proto);
+ id->id = TO_NATIVE(id->id);
+ id->extra = TO_NATIVE(id->extra);
+
+ strcpy(alias, "serio:");
+ ADD(alias, "ty", id->type != SERIO_ANY, id->type);
+ ADD(alias, "pr", id->proto != SERIO_ANY, id->proto);
+ ADD(alias, "id", id->id != SERIO_ANY, id->id);
+ ADD(alias, "ex", id->extra != SERIO_ANY, id->extra);
+
+ return 1;
+}
+
/* looks like: "pnp:dD" */
static int do_pnp_entry(const char *filename,
struct pnp_device_id *id, char *alias)
@@ -270,6 +288,9 @@ void handle_moddevtable(struct module *mod, struct elf_info *info,
else if (sym_is(symname, "__mod_ccw_device_table"))
do_table(symval, sym->st_size, sizeof(struct ccw_device_id),
do_ccw_entry, mod);
+ else if (sym_is(symname, "__mod_serio_device_table"))
+ do_table(symval, sym->st_size, sizeof(struct serio_device_id),
+ do_serio_entry, mod);
else if (sym_is(symname, "__mod_pnp_device_table"))
do_table(symval, sym->st_size, sizeof(struct pnp_device_id),
do_pnp_entry, mod);
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 347549c35d6c2..9b9f94c915d23 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -47,11 +47,10 @@ warn(const char *fmt, ...)
va_end(arglist);
}
-void *do_nofail(void *ptr, const char *file, int line, const char *expr)
+void *do_nofail(void *ptr, const char *expr)
{
if (!ptr) {
- fatal("Memory allocation failure %s line %d: %s.\n",
- file, line, expr);
+ fatal("modpost: Memory allocation failure: %s.\n", expr);
}
return ptr;
}
diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h
index eb8815ae209e5..7334d839145de 100644
--- a/scripts/mod/modpost.h
+++ b/scripts/mod/modpost.h
@@ -53,8 +53,8 @@ static inline void __endian(const void *src, void *dest, unsigned int size)
#endif
-#define NOFAIL(ptr) do_nofail((ptr), __FILE__, __LINE__, #ptr)
-void *do_nofail(void *ptr, const char *file, int line, const char *expr);
+#define NOFAIL(ptr) do_nofail((ptr), #ptr)
+void *do_nofail(void *ptr, const char *expr);
struct buffer {
char *p;
diff --git a/scripts/mod/sumversion.c b/scripts/mod/sumversion.c
index 6fe63c60c16cd..1112347245c02 100644
--- a/scripts/mod/sumversion.c
+++ b/scripts/mod/sumversion.c
@@ -419,7 +419,9 @@ void get_src_version(const char *modname, char sum[], unsigned sumlen)
*end = '\0';
md4_init(&md);
- for (fname = strtok(sources, " "); fname; fname = strtok(NULL, " ")) {
+ while ((fname = strsep(&sources, " ")) != NULL) {
+ if (!*fname)
+ continue;
if (!parse_source_files(fname, &md))
goto release;
}
diff --git a/scripts/namespace.pl b/scripts/namespace.pl
index 399c831e5d12b..88e30e82f1ca9 100644
--- a/scripts/namespace.pl
+++ b/scripts/namespace.pl
@@ -406,6 +406,11 @@ sub resolve_external_references
&& $name !~ /^__.*per_cpu_end/
&& $name !~ /^__alt_instructions/
&& $name !~ /^__setup_/
+ && $name !~ /^jiffies/
+ && $name !~ /^__mod_timer/
+ && $name !~ /^__mod_page_state/
+ && $name !~ /^init_module/
+ && $name !~ /^cleanup_module/
) {
printf "Cannot resolve ";
printf "weak " if ($type eq "w");
diff --git a/scripts/show_delta b/scripts/show_delta
new file mode 100644
index 0000000000000..48a706ab3d0c3
--- /dev/null
+++ b/scripts/show_delta
@@ -0,0 +1,129 @@
+#!/usr/bin/env python
+#
+# show_deltas: Read list of printk messages instrumented with
+# time data, and format with time deltas.
+#
+# Also, you can show the times relative to a fixed point.
+#
+# Copyright 2003 Sony Corporation
+#
+# GPL 2.0 applies.
+
+import sys
+import string
+
+def usage():
+ print """usage: show_delta [<options>] <filename>
+
+This program parses the output from a set of printk message lines which
+have time data prefixed because the CONFIG_PRINTK_TIME option is set, or
+the kernel command line option "time" is specified. When run with no
+options, the time information is converted to show the time delta between
+each printk line and the next. When run with the '-b' option, all times
+are relative to a single (base) point in time.
+
+Options:
+ -h Show this usage help.
+ -b <base> Specify a base for time references.
+ <base> can be a number or a string.
+ If it is a string, the first message line
+ which matches (at the beginning of the
+ line) is used as the time reference.
+
+ex: $ dmesg >timefile
+ $ show_delta -b NET4 timefile
+
+will show times relative to the line in the kernel output
+starting with "NET4".
+"""
+ sys.exit(1)
+
+# returns a tuple containing the seconds and text for each message line
+# seconds is returned as a float
+# raise an exception if no timing data was found
+def get_time(line):
+ if line[0]!="[":
+ raise ValueError
+
+ # split on closing bracket
+ (time_str, rest) = string.split(line[1:],']',1)
+ time = string.atof(time_str)
+
+ #print "time=", time
+ return (time, rest)
+
+
+# average line looks like:
+# [ 0.084282] VFS: Mounted root (romfs filesystem) readonly
+# time data is expressed in seconds.useconds,
+# convert_line adds a delta for each line
+last_time = 0.0
+def convert_line(line, base_time):
+ global last_time
+
+ try:
+ (time, rest) = get_time(line)
+ except:
+ # if any problem parsing time, don't convert anything
+ return line
+
+ if base_time:
+ # show time from base
+ delta = time - base_time
+ else:
+ # just show time from last line
+ delta = time - last_time
+ last_time = time
+
+ return ("[%5.6f < %5.6f >]" % (time, delta)) + rest
+
+def main():
+ base_str = ""
+ filein = ""
+ for arg in sys.argv[1:]:
+ if arg=="-b":
+ base_str = sys.argv[sys.argv.index("-b")+1]
+ elif arg=="-h":
+ usage()
+ else:
+ filein = arg
+
+ if not filein:
+ usage()
+
+ try:
+ lines = open(filein,"r").readlines()
+ except:
+ print "Problem opening file: %s" % filein
+ sys.exit(1)
+
+ if base_str:
+ print 'base= "%s"' % base_str
+ # assume a numeric base. If that fails, try searching
+ # for a matching line.
+ try:
+ base_time = float(base_str)
+ except:
+ # search for line matching <base> string
+ found = 0
+ for line in lines:
+ try:
+ (time, rest) = get_time(line)
+ except:
+ continue
+ if string.find(rest, base_str)==1:
+ base_time = time
+ found = 1
+ # stop at first match
+ break
+ if not found:
+ print 'Couldn\'t find line matching base pattern "%s"' % base_str
+ sys.exit(1)
+ else:
+ base_time = 0.0
+
+ for line in lines:
+ print convert_line(line, base_time),
+
+main()
+
diff --git a/security/dummy.c b/security/dummy.c
index acbfa5b60cde9..b32eff1465471 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -446,13 +446,16 @@ static int dummy_file_ioctl (struct file *file, unsigned int command,
return 0;
}
-static int dummy_file_mmap (struct file *file, unsigned long prot,
+static int dummy_file_mmap (struct file *file, unsigned long reqprot,
+ unsigned long prot,
unsigned long flags)
{
return 0;
}
-static int dummy_file_mprotect (struct vm_area_struct *vma, unsigned long prot)
+static int dummy_file_mprotect (struct vm_area_struct *vma,
+ unsigned long reqprot,
+ unsigned long prot)
{
return 0;
}
diff --git a/security/keys/compat.c b/security/keys/compat.c
index 17c038c241ea7..aff8b22dcb5c7 100644
--- a/security/keys/compat.c
+++ b/security/keys/compat.c
@@ -31,7 +31,7 @@ asmlinkage long compat_sys_keyctl(u32 option,
return keyctl_get_keyring_ID(arg2, arg3);
case KEYCTL_JOIN_SESSION_KEYRING:
- return keyctl_join_session_keyring(compat_ptr(arg3));
+ return keyctl_join_session_keyring(compat_ptr(arg2));
case KEYCTL_UPDATE:
return keyctl_update_key(arg2, compat_ptr(arg3), arg4);
diff --git a/security/keys/key.c b/security/keys/key.c
index e3d0359f5f7e1..59402c8432031 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -57,9 +57,10 @@ struct key_user *key_user_lookup(uid_t uid)
{
struct key_user *candidate = NULL, *user;
struct rb_node *parent = NULL;
- struct rb_node **p = &key_user_tree.rb_node;
+ struct rb_node **p;
try_again:
+ p = &key_user_tree.rb_node;
spin_lock(&key_user_lock);
/* search the tree for a user record with a matching UID */
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index 4d95fdb75bce4..dc0011b3fac92 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -923,7 +923,7 @@ asmlinkage long sys_keyctl(int option, unsigned long arg2, unsigned long arg3,
(int) arg3);
case KEYCTL_JOIN_SESSION_KEYRING:
- return keyctl_join_session_keyring((const char __user *) arg3);
+ return keyctl_join_session_keyring((const char __user *) arg2);
case KEYCTL_UPDATE:
return keyctl_update_key((key_serial_t) arg2,
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index e5bd7b940550a..2eb0e471cd408 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -165,30 +165,36 @@ int install_thread_keyring(struct task_struct *tsk)
/*****************************************************************************/
/*
- * install a fresh process keyring, discarding the old one
+ * make sure a process keyring is installed
*/
static int install_process_keyring(struct task_struct *tsk)
{
- struct key *keyring, *old;
+ unsigned long flags;
+ struct key *keyring;
char buf[20];
int ret;
- sprintf(buf, "_pid.%u", tsk->tgid);
+ if (!tsk->signal->process_keyring) {
+ sprintf(buf, "_pid.%u", tsk->tgid);
- keyring = keyring_alloc(buf, tsk->uid, tsk->gid, 1, NULL);
- if (IS_ERR(keyring)) {
- ret = PTR_ERR(keyring);
- goto error;
- }
+ keyring = keyring_alloc(buf, tsk->uid, tsk->gid, 1, NULL);
+ if (IS_ERR(keyring)) {
+ ret = PTR_ERR(keyring);
+ goto error;
+ }
- task_lock(tsk);
- old = tsk->process_keyring;
- tsk->process_keyring = keyring;
- task_unlock(tsk);
+ /* attach or swap keyrings */
+ spin_lock_irqsave(&tsk->sighand->siglock, flags);
+ if (!tsk->signal->process_keyring) {
+ tsk->signal->process_keyring = keyring;
+ keyring = NULL;
+ }
+ spin_unlock_irqrestore(&tsk->sighand->siglock, flags);
- ret = 0;
+ key_put(keyring);
+ }
- key_put(old);
+ ret = 0;
error:
return ret;
@@ -202,6 +208,7 @@ static int install_process_keyring(struct task_struct *tsk)
static int install_session_keyring(struct task_struct *tsk,
struct key *keyring)
{
+ unsigned long flags;
struct key *old;
char buf[20];
int ret;
@@ -221,10 +228,10 @@ static int install_session_keyring(struct task_struct *tsk,
}
/* install the keyring */
- task_lock(tsk);
- old = tsk->session_keyring;
- tsk->session_keyring = keyring;
- task_unlock(tsk);
+ spin_lock_irqsave(&tsk->sighand->siglock, flags);
+ old = tsk->signal->session_keyring;
+ tsk->signal->session_keyring = keyring;
+ spin_unlock_irqrestore(&tsk->sighand->siglock, flags);
ret = 0;
@@ -236,42 +243,59 @@ static int install_session_keyring(struct task_struct *tsk,
/*****************************************************************************/
/*
- * copy the keys for fork
+ * copy the keys in a thread group for fork without CLONE_THREAD
*/
-int copy_keys(unsigned long clone_flags, struct task_struct *tsk)
+int copy_thread_group_keys(struct task_struct *tsk)
{
- int ret = 0;
+ unsigned long flags;
- key_check(tsk->session_keyring);
- key_check(tsk->process_keyring);
- key_check(tsk->thread_keyring);
+ key_check(current->thread_group->session_keyring);
+ key_check(current->thread_group->process_keyring);
- if (tsk->session_keyring)
- atomic_inc(&tsk->session_keyring->usage);
+ /* no process keyring yet */
+ tsk->signal->process_keyring = NULL;
- if (tsk->process_keyring) {
- if (clone_flags & CLONE_THREAD) {
- atomic_inc(&tsk->process_keyring->usage);
- }
- else {
- tsk->process_keyring = NULL;
- ret = install_process_keyring(tsk);
- }
- }
+ /* same session keyring */
+ spin_lock_irqsave(&current->sighand->siglock, flags);
+ tsk->signal->session_keyring =
+ key_get(current->signal->session_keyring);
+ spin_unlock_irqrestore(&current->sighand->siglock, flags);
+
+ return 0;
+} /* end copy_thread_group_keys() */
+
+/*****************************************************************************/
+/*
+ * copy the keys for fork
+ */
+int copy_keys(unsigned long clone_flags, struct task_struct *tsk)
+{
+ key_check(tsk->thread_keyring);
+
+ /* no thread keyring yet */
tsk->thread_keyring = NULL;
- return ret;
+ return 0;
} /* end copy_keys() */
/*****************************************************************************/
/*
- * dispose of keys upon exit
+ * dispose of thread group keys upon thread group destruction
+ */
+void exit_thread_group_keys(struct signal_struct *tg)
+{
+ key_put(tg->session_keyring);
+ key_put(tg->process_keyring);
+
+} /* end exit_thread_group_keys() */
+
+/*****************************************************************************/
+/*
+ * dispose of keys upon thread exit
*/
void exit_keys(struct task_struct *tsk)
{
- key_put(tsk->session_keyring);
- key_put(tsk->process_keyring);
key_put(tsk->thread_keyring);
} /* end exit_keys() */
@@ -282,6 +306,7 @@ void exit_keys(struct task_struct *tsk)
*/
int exec_keys(struct task_struct *tsk)
{
+ unsigned long flags;
struct key *old;
/* newly exec'd tasks don't get a thread keyring */
@@ -292,8 +317,15 @@ int exec_keys(struct task_struct *tsk)
key_put(old);
- /* newly exec'd tasks get a fresh process keyring */
- return install_process_keyring(tsk);
+ /* discard the process keyring from a newly exec'd task */
+ spin_lock_irqsave(&tsk->sighand->siglock, flags);
+ old = tsk->signal->process_keyring;
+ tsk->signal->process_keyring = NULL;
+ spin_unlock_irqrestore(&tsk->sighand->siglock, flags);
+
+ key_put(old);
+
+ return 0;
} /* end exec_keys() */
@@ -314,15 +346,6 @@ int suid_keys(struct task_struct *tsk)
*/
void key_fsuid_changed(struct task_struct *tsk)
{
- /* update the ownership of the process keyring */
- if (tsk->process_keyring) {
- down_write(&tsk->process_keyring->sem);
- write_lock(&tsk->process_keyring->lock);
- tsk->process_keyring->uid = tsk->fsuid;
- write_unlock(&tsk->process_keyring->lock);
- up_write(&tsk->process_keyring->sem);
- }
-
/* update the ownership of the thread keyring */
if (tsk->thread_keyring) {
down_write(&tsk->thread_keyring->sem);
@@ -340,15 +363,6 @@ void key_fsuid_changed(struct task_struct *tsk)
*/
void key_fsgid_changed(struct task_struct *tsk)
{
- /* update the ownership of the process keyring */
- if (tsk->process_keyring) {
- down_write(&tsk->process_keyring->sem);
- write_lock(&tsk->process_keyring->lock);
- tsk->process_keyring->gid = tsk->fsgid;
- write_unlock(&tsk->process_keyring->lock);
- up_write(&tsk->process_keyring->sem);
- }
-
/* update the ownership of the thread keyring */
if (tsk->thread_keyring) {
down_write(&tsk->thread_keyring->sem);
@@ -373,7 +387,8 @@ struct key *search_process_keyrings_aux(struct key_type *type,
key_match_func_t match)
{
struct task_struct *tsk = current;
- struct key *key, *ret, *err, *session;
+ unsigned long flags;
+ struct key *key, *ret, *err, *tmp;
/* 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;
@@ -407,9 +422,9 @@ struct key *search_process_keyrings_aux(struct key_type *type,
}
/* search the process keyring second */
- if (tsk->process_keyring) {
- key = keyring_search_aux(tsk->process_keyring, type,
- description, match);
+ if (tsk->signal->process_keyring) {
+ key = keyring_search_aux(tsk->signal->process_keyring,
+ type, description, match);
if (!IS_ERR(key))
goto found;
@@ -427,12 +442,17 @@ struct key *search_process_keyrings_aux(struct key_type *type,
}
/* search the session keyring last */
- session = tsk->session_keyring;
- if (!session)
- session = tsk->user->session_keyring;
+ spin_lock_irqsave(&tsk->sighand->siglock, flags);
- key = keyring_search_aux(session, type,
- description, match);
+ tmp = tsk->signal->session_keyring;
+ if (!tmp)
+ tmp = tsk->user->session_keyring;
+ atomic_inc(&tmp->usage);
+
+ spin_unlock_irqrestore(&tsk->sighand->siglock, flags);
+
+ key = keyring_search_aux(tmp, type, description, match);
+ key_put(tmp);
if (!IS_ERR(key))
goto found;
@@ -479,6 +499,7 @@ struct key *lookup_user_key(key_serial_t id, int create, int partial,
key_perm_t perm)
{
struct task_struct *tsk = current;
+ unsigned long flags;
struct key *key;
int ret;
@@ -502,7 +523,7 @@ struct key *lookup_user_key(key_serial_t id, int create, int partial,
break;
case KEY_SPEC_PROCESS_KEYRING:
- if (!tsk->process_keyring) {
+ if (!tsk->signal->process_keyring) {
if (!create)
goto error;
@@ -513,12 +534,12 @@ struct key *lookup_user_key(key_serial_t id, int create, int partial,
}
}
- key = tsk->process_keyring;
+ key = tsk->signal->process_keyring;
atomic_inc(&key->usage);
break;
case KEY_SPEC_SESSION_KEYRING:
- if (!tsk->session_keyring) {
+ if (!tsk->signal->session_keyring) {
/* always install a session keyring upon access if one
* doesn't exist yet */
ret = install_session_keyring(
@@ -527,8 +548,10 @@ struct key *lookup_user_key(key_serial_t id, int create, int partial,
goto error;
}
- key = tsk->session_keyring;
+ spin_lock_irqsave(&tsk->sighand->siglock, flags);
+ key = tsk->signal->session_keyring;
atomic_inc(&key->usage);
+ spin_unlock_irqrestore(&tsk->sighand->siglock, flags);
break;
case KEY_SPEC_USER_KEYRING:
@@ -592,6 +615,7 @@ struct key *lookup_user_key(key_serial_t id, int create, int partial,
long join_session_keyring(const char *name)
{
struct task_struct *tsk = current;
+ unsigned long flags;
struct key *keyring;
long ret;
@@ -601,7 +625,9 @@ long join_session_keyring(const char *name)
if (ret < 0)
goto error;
- ret = tsk->session_keyring->serial;
+ spin_lock_irqsave(&tsk->sighand->siglock, flags);
+ ret = tsk->signal->session_keyring->serial;
+ spin_unlock_irqrestore(&tsk->sighand->siglock, flags);
goto error;
}
@@ -628,10 +654,9 @@ long join_session_keyring(const char *name)
if (ret < 0)
goto error2;
+ ret = keyring->serial;
key_put(keyring);
- ret = tsk->session_keyring->serial;
-
error2:
up(&key_session_sem);
error:
diff --git a/security/keys/request_key.c b/security/keys/request_key.c
index fd6ba06f25035..9705b1aeba5de 100644
--- a/security/keys/request_key.c
+++ b/security/keys/request_key.c
@@ -34,6 +34,8 @@ static int call_request_key(struct key *key,
const char *callout_info)
{
struct task_struct *tsk = current;
+ unsigned long flags;
+ key_serial_t prkey, sskey;
char *argv[10], *envp[3], uid_str[12], gid_str[12];
char key_str[12], keyring_str[3][12];
int i;
@@ -46,16 +48,25 @@ static int call_request_key(struct key *key,
sprintf(key_str, "%d", key->serial);
/* we specify the process's default keyrings */
- task_lock(current);
sprintf(keyring_str[0], "%d",
tsk->thread_keyring ? tsk->thread_keyring->serial : 0);
- sprintf(keyring_str[1], "%d",
- tsk->process_keyring ? tsk->process_keyring->serial : 0);
- sprintf(keyring_str[2], "%d",
- (tsk->session_keyring ?
- tsk->session_keyring->serial :
- tsk->user->session_keyring->serial));
- task_unlock(tsk);
+
+ prkey = 0;
+ if (tsk->signal->process_keyring)
+ prkey = tsk->signal->process_keyring->serial;
+
+ sskey = 0;
+ spin_lock_irqsave(&tsk->sighand->siglock, flags);
+ if (tsk->signal->session_keyring)
+ sskey = tsk->signal->session_keyring->serial;
+ spin_unlock_irqrestore(&tsk->sighand->siglock, flags);
+
+
+ if (!sskey)
+ sskey = tsk->user->session_keyring->serial;
+
+ sprintf(keyring_str[1], "%d", prkey);
+ sprintf(keyring_str[2], "%d", sskey);
/* set up a minimal environment */
i = 0;
@@ -166,8 +177,19 @@ static struct key *__request_key_construction(struct key_type *type,
now = current_kernel_time();
key->expiry = now.tv_sec + key_negative_timeout;
- if (current->session_keyring)
- key_link(current->session_keyring, key);
+ if (current->signal->session_keyring) {
+ unsigned long flags;
+ struct key *keyring;
+
+ spin_lock_irqsave(&current->sighand->siglock, flags);
+ keyring = current->signal->session_keyring;
+ atomic_inc(&keyring->usage);
+ spin_unlock_irqrestore(&current->sighand->siglock, flags);
+
+ key_link(keyring, key);
+ key_put(keyring);
+ }
+
key_put(key);
/* notify anyone who was waiting */
@@ -274,8 +296,8 @@ struct key *request_key(struct key_type *type,
/* - get hold of the user's construction queue */
user = key_user_lookup(current->fsuid);
- if (IS_ERR(user)) {
- key = ERR_PTR(PTR_ERR(user));
+ if (!user) {
+ key = ERR_PTR(-ENOMEM);
goto error;
}
diff --git a/security/seclvl.c b/security/seclvl.c
index 6a06bb224fe82..8a0ab0d7949e0 100644
--- a/security/seclvl.c
+++ b/security/seclvl.c
@@ -170,7 +170,7 @@ seclvl_attr_show(struct kobject *kobj, struct attribute *attr, char *buf)
/**
* Callback function pointers for show and store
*/
-struct sysfs_ops seclvlfs_sysfs_ops = {
+static struct sysfs_ops seclvlfs_sysfs_ops = {
.show = seclvl_attr_show,
.store = seclvl_attr_store,
};
@@ -275,7 +275,7 @@ seclvl_write_file(struct seclvl_obj *obj, const char *buff, size_t count)
}
/* Generate sysfs_attr_seclvl */
-struct seclvl_attribute sysfs_attr_seclvl =
+static struct seclvl_attribute sysfs_attr_seclvl =
__ATTR(seclvl, (S_IFREG | S_IRUGO | S_IWUSR), seclvl_read_file,
seclvl_write_file);
@@ -386,7 +386,7 @@ seclvl_write_passwd(struct seclvl_obj *obj, const char *buff, size_t count)
}
/* Generate sysfs_attr_passwd */
-struct seclvl_attribute sysfs_attr_passwd =
+static struct seclvl_attribute sysfs_attr_passwd =
__ATTR(passwd, (S_IFREG | S_IRUGO | S_IWUSR), seclvl_read_passwd,
seclvl_write_passwd);
diff --git a/security/selinux/Kconfig b/security/selinux/Kconfig
index ea459b9aba148..b59582b92283e 100644
--- a/security/selinux/Kconfig
+++ b/security/selinux/Kconfig
@@ -1,6 +1,6 @@
config SECURITY_SELINUX
bool "NSA SELinux Support"
- depends on SECURITY && NET
+ depends on SECURITY && NET && INET
default n
help
This selects NSA Security-Enhanced Linux (SELinux).
@@ -76,12 +76,22 @@ config SECURITY_SELINUX_AVC_STATS
/selinux/avc/cache_stats, which may be monitored via
tools such as avcstat.
-config SECURITY_SELINUX_MLS
- bool "NSA SELinux MLS policy (EXPERIMENTAL)"
- depends on SECURITY_SELINUX && EXPERIMENTAL
- default n
+config SECURITY_SELINUX_CHECKREQPROT_VALUE
+ int "NSA SELinux checkreqprot default value"
+ depends on SECURITY_SELINUX
+ range 0 1
+ default 1
help
- This enables the NSA SELinux Multi-Level Security (MLS) policy in
- addition to the default RBAC/TE policy. This policy is
- experimental and has not been configured for use. Unless you
- specifically want to experiment with MLS, say N.
+ This option sets the default value for the 'checkreqprot' flag
+ that determines whether SELinux checks the protection requested
+ by the application or the protection that will be applied by the
+ kernel (including any implied execute for read-implies-exec) for
+ mmap and mprotect calls. If this option is set to 0 (zero),
+ SELinux will default to checking the protection that will be applied
+ by the kernel. If this option is set to 1 (one), SELinux will
+ default to checking the protection requested by the application.
+ The checkreqprot flag may be changed from the default via the
+ 'checkreqprot=' boot parameter. It may also be changed at runtime
+ via /selinux/checkreqprot if authorized by policy.
+
+ If you are unsure how to answer this question, answer 1.
diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index fc683fadae5ff..fe6285e5c68f8 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -139,7 +139,7 @@ static inline int avc_hash(u32 ssid, u32 tsid, u16 tclass)
* @tclass: target security class
* @av: access vector
*/
-void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av)
+static void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av)
{
const char **common_pts = NULL;
u32 common_base = 0;
@@ -199,7 +199,7 @@ void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av)
* @tsid: target security identifier
* @tclass: target security class
*/
-void avc_dump_query(struct audit_buffer *ab, u32 ssid, u32 tsid, u16 tclass)
+static void avc_dump_query(struct audit_buffer *ab, u32 ssid, u32 tsid, u16 tclass)
{
int rc;
char *scontext;
@@ -828,136 +828,6 @@ out:
return rc;
}
-static int avc_update_cache(u32 event, u32 ssid, u32 tsid,
- u16 tclass, u32 perms)
-{
- struct avc_node *node;
- int i;
-
- rcu_read_lock();
-
- if (ssid == SECSID_WILD || tsid == SECSID_WILD) {
- /* apply to all matching nodes */
- for (i = 0; i < AVC_CACHE_SLOTS; i++) {
- list_for_each_entry_rcu(node, &avc_cache.slots[i], list) {
- if (avc_sidcmp(ssid, node->ae.ssid) &&
- avc_sidcmp(tsid, node->ae.tsid) &&
- tclass == node->ae.tclass ) {
- avc_update_node(event, perms, node->ae.ssid,
- node->ae.tsid, node->ae.tclass);
- }
- }
- }
- } else {
- /* apply to one node */
- avc_update_node(event, perms, ssid, tsid, tclass);
- }
-
- rcu_read_unlock();
-
- return 0;
-}
-
-static int avc_control(u32 event, u32 ssid, u32 tsid,
- u16 tclass, u32 perms,
- u32 seqno, u32 *out_retained)
-{
- struct avc_callback_node *c;
- u32 tretained = 0, cretained = 0;
- int rc = 0;
-
- /*
- * try_revoke only removes permissions from the cache
- * state if they are not retained by the object manager.
- * Hence, try_revoke must wait until after the callbacks have
- * been invoked to update the cache state.
- */
- if (event != AVC_CALLBACK_TRY_REVOKE)
- avc_update_cache(event,ssid,tsid,tclass,perms);
-
- for (c = avc_callbacks; c; c = c->next)
- {
- if ((c->events & event) &&
- avc_sidcmp(c->ssid, ssid) &&
- avc_sidcmp(c->tsid, tsid) &&
- c->tclass == tclass &&
- (c->perms & perms)) {
- cretained = 0;
- rc = c->callback(event, ssid, tsid, tclass,
- (c->perms & perms),
- &cretained);
- if (rc)
- goto out;
- tretained |= cretained;
- }
- }
-
- if (event == AVC_CALLBACK_TRY_REVOKE) {
- /* revoke any unretained permissions */
- perms &= ~tretained;
- avc_update_cache(event,ssid,tsid,tclass,perms);
- *out_retained = tretained;
- }
-
- avc_latest_notif_update(seqno, 0);
-
-out:
- return rc;
-}
-
-/**
- * avc_ss_grant - Grant previously denied permissions.
- * @ssid: source security identifier or %SECSID_WILD
- * @tsid: target security identifier or %SECSID_WILD
- * @tclass: target security class
- * @perms: permissions to grant
- * @seqno: policy sequence number
- */
-int avc_ss_grant(u32 ssid, u32 tsid, u16 tclass,
- u32 perms, u32 seqno)
-{
- return avc_control(AVC_CALLBACK_GRANT,
- ssid, tsid, tclass, perms, seqno, NULL);
-}
-
-/**
- * avc_ss_try_revoke - Try to revoke previously granted permissions.
- * @ssid: source security identifier or %SECSID_WILD
- * @tsid: target security identifier or %SECSID_WILD
- * @tclass: target security class
- * @perms: permissions to grant
- * @seqno: policy sequence number
- * @out_retained: subset of @perms that are retained
- *
- * Try to revoke previously granted permissions, but
- * only if they are not retained as migrated permissions.
- * Return the subset of permissions that are retained via @out_retained.
- */
-int avc_ss_try_revoke(u32 ssid, u32 tsid, u16 tclass,
- u32 perms, u32 seqno, u32 *out_retained)
-{
- return avc_control(AVC_CALLBACK_TRY_REVOKE,
- ssid, tsid, tclass, perms, seqno, out_retained);
-}
-
-/**
- * avc_ss_revoke - Revoke previously granted permissions.
- * @ssid: source security identifier or %SECSID_WILD
- * @tsid: target security identifier or %SECSID_WILD
- * @tclass: target security class
- * @perms: permissions to grant
- * @seqno: policy sequence number
- *
- * Revoke previously granted permissions, even if
- * they are retained as migrated permissions.
- */
-int avc_ss_revoke(u32 ssid, u32 tsid, u16 tclass,
- u32 perms, u32 seqno)
-{
- return avc_control(AVC_CALLBACK_REVOKE,
- ssid, tsid, tclass, perms, seqno, NULL);
-}
-
/**
* avc_ss_reset - Flush the cache and revalidate migrated permissions.
* @seqno: policy sequence number
@@ -991,46 +861,6 @@ out:
}
/**
- * avc_ss_set_auditallow - Enable or disable auditing of granted permissions.
- * @ssid: source security identifier or %SECSID_WILD
- * @tsid: target security identifier or %SECSID_WILD
- * @tclass: target security class
- * @perms: permissions to grant
- * @seqno: policy sequence number
- * @enable: enable flag.
- */
-int avc_ss_set_auditallow(u32 ssid, u32 tsid, u16 tclass,
- u32 perms, u32 seqno, u32 enable)
-{
- if (enable)
- return avc_control(AVC_CALLBACK_AUDITALLOW_ENABLE,
- ssid, tsid, tclass, perms, seqno, NULL);
- else
- return avc_control(AVC_CALLBACK_AUDITALLOW_DISABLE,
- ssid, tsid, tclass, perms, seqno, NULL);
-}
-
-/**
- * avc_ss_set_auditdeny - Enable or disable auditing of denied permissions.
- * @ssid: source security identifier or %SECSID_WILD
- * @tsid: target security identifier or %SECSID_WILD
- * @tclass: target security class
- * @perms: permissions to grant
- * @seqno: policy sequence number
- * @enable: enable flag.
- */
-int avc_ss_set_auditdeny(u32 ssid, u32 tsid, u16 tclass,
- u32 perms, u32 seqno, u32 enable)
-{
- if (enable)
- return avc_control(AVC_CALLBACK_AUDITDENY_ENABLE,
- ssid, tsid, tclass, perms, seqno, NULL);
- else
- return avc_control(AVC_CALLBACK_AUDITDENY_DISABLE,
- ssid, tsid, tclass, perms, seqno, NULL);
-}
-
-/**
* avc_has_perm_noaudit - Check permissions but perform no auditing.
* @ssid: source security identifier
* @tsid: target security identifier
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index d9d22ce4a4f1c..8c5dd09a89b40 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -10,6 +10,8 @@
*
* Copyright (C) 2001,2002 Networks Associates Technology, Inc.
* Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com>
+ * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
+ * <dgoeddel@trustedcs.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,
@@ -65,6 +67,7 @@
#include <linux/hugetlb.h>
#include <linux/personality.h>
#include <linux/sysctl.h>
+#include <linux/audit.h>
#include "avc.h"
#include "objsec.h"
@@ -589,7 +592,8 @@ next_inode:
spin_unlock(&sbsec->isec_lock);
inode = igrab(inode);
if (inode) {
- inode_doinit(inode);
+ if (!IS_PRIVATE (inode))
+ inode_doinit(inode);
iput(inode);
}
spin_lock(&sbsec->isec_lock);
@@ -826,7 +830,9 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
__FUNCTION__, context, -rc,
inode->i_sb->s_id, inode->i_ino);
kfree(context);
- goto out;
+ /* Leave with the unlabeled SID */
+ rc = 0;
+ break;
}
}
kfree(context);
@@ -918,9 +924,9 @@ static inline u32 signal_to_av(int sig)
/* Check permission betweeen a pair of tasks, e.g. signal checks,
fork check, ptrace check, etc. */
-int task_has_perm(struct task_struct *tsk1,
- struct task_struct *tsk2,
- u32 perms)
+static int task_has_perm(struct task_struct *tsk1,
+ struct task_struct *tsk2,
+ u32 perms)
{
struct task_security_struct *tsec1, *tsec2;
@@ -931,8 +937,8 @@ int task_has_perm(struct task_struct *tsk1,
}
/* Check whether a task is allowed to use a capability. */
-int task_has_capability(struct task_struct *tsk,
- int cap)
+static int task_has_capability(struct task_struct *tsk,
+ int cap)
{
struct task_security_struct *tsec;
struct avc_audit_data ad;
@@ -948,8 +954,8 @@ int task_has_capability(struct task_struct *tsk,
}
/* Check whether a task is allowed to use a system operation. */
-int task_has_system(struct task_struct *tsk,
- u32 perms)
+static int task_has_system(struct task_struct *tsk,
+ u32 perms)
{
struct task_security_struct *tsec;
@@ -962,10 +968,10 @@ int task_has_system(struct task_struct *tsk,
/* Check whether a task has a particular permission to an inode.
The 'adp' parameter is optional and allows other audit
data to be passed (e.g. the dentry). */
-int inode_has_perm(struct task_struct *tsk,
- struct inode *inode,
- u32 perms,
- struct avc_audit_data *adp)
+static int inode_has_perm(struct task_struct *tsk,
+ struct inode *inode,
+ u32 perms,
+ struct avc_audit_data *adp)
{
struct task_security_struct *tsec;
struct inode_security_struct *isec;
@@ -1187,10 +1193,10 @@ static inline int may_rename(struct inode *old_dir,
}
/* Check whether a task can perform a filesystem operation. */
-int superblock_has_perm(struct task_struct *tsk,
- struct super_block *sb,
- u32 perms,
- struct avc_audit_data *ad)
+static int superblock_has_perm(struct task_struct *tsk,
+ struct super_block *sb,
+ u32 perms,
+ struct avc_audit_data *ad)
{
struct task_security_struct *tsec;
struct superblock_security_struct *sbsec;
@@ -1247,7 +1253,7 @@ static inline u32 file_to_av(struct file *file)
}
/* Set an inode's SID to a specified value. */
-int inode_security_set_sid(struct inode *inode, u32 sid)
+static int inode_security_set_sid(struct inode *inode, u32 sid)
{
struct inode_security_struct *isec = inode->i_security;
struct superblock_security_struct *sbsec = inode->i_sb->s_security;
@@ -1855,6 +1861,13 @@ static void selinux_bprm_post_apply_creds(struct linux_binprm *bprm)
initrlim = init_task.signal->rlim+i;
rlim->rlim_cur = min(rlim->rlim_max,initrlim->rlim_cur);
}
+ if (current->signal->rlim[RLIMIT_CPU].rlim_cur != RLIM_INFINITY) {
+ /*
+ * This will cause RLIMIT_CPU calculations
+ * to be refigured.
+ */
+ current->it_prof_expires = jiffies_to_cputime(1);
+ }
}
/* Wake up the parent if it is waiting so that it can
@@ -2203,6 +2216,11 @@ static int selinux_inode_setxattr(struct dentry *dentry, char *name, void *value
if (rc)
return rc;
+ rc = security_validate_transition(isec->sid, newsid, tsec->sid,
+ isec->sclass);
+ if (rc)
+ return rc;
+
return avc_has_perm(newsid,
sbsec->sid,
SECCLASS_FILESYSTEM,
@@ -2407,6 +2425,7 @@ static int selinux_file_ioctl(struct file *file, unsigned int cmd,
static int file_map_prot_check(struct file *file, unsigned long prot, int shared)
{
+#ifndef CONFIG_PPC32
if ((prot & PROT_EXEC) && (!file || (!shared && (prot & PROT_WRITE)))) {
/*
* We are making executable an anonymous mapping or a
@@ -2417,6 +2436,7 @@ static int file_map_prot_check(struct file *file, unsigned long prot, int shared
if (rc)
return rc;
}
+#endif
if (file) {
/* read access is always possible with a mapping */
@@ -2434,27 +2454,36 @@ static int file_map_prot_check(struct file *file, unsigned long prot, int shared
return 0;
}
-static int selinux_file_mmap(struct file *file, unsigned long prot, unsigned long flags)
+static int selinux_file_mmap(struct file *file, unsigned long reqprot,
+ unsigned long prot, unsigned long flags)
{
int rc;
- rc = secondary_ops->file_mmap(file, prot, flags);
+ rc = secondary_ops->file_mmap(file, reqprot, prot, flags);
if (rc)
return rc;
+ if (selinux_checkreqprot)
+ prot = reqprot;
+
return file_map_prot_check(file, prot,
(flags & MAP_TYPE) == MAP_SHARED);
}
static int selinux_file_mprotect(struct vm_area_struct *vma,
+ unsigned long reqprot,
unsigned long prot)
{
int rc;
- rc = secondary_ops->file_mprotect(vma, prot);
+ rc = secondary_ops->file_mprotect(vma, reqprot, prot);
if (rc)
return rc;
+ if (selinux_checkreqprot)
+ prot = reqprot;
+
+#ifndef CONFIG_PPC32
if (vma->vm_file != NULL && vma->anon_vma != NULL && (prot & PROT_EXEC)) {
/*
* We are making executable a file mapping that has
@@ -2466,6 +2495,7 @@ static int selinux_file_mprotect(struct vm_area_struct *vma,
if (rc)
return rc;
}
+#endif
return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED);
}
@@ -3064,7 +3094,53 @@ out:
static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen)
{
- return socket_has_perm(current, sock, SOCKET__CONNECT);
+ struct inode_security_struct *isec;
+ int err;
+
+ err = socket_has_perm(current, sock, SOCKET__CONNECT);
+ if (err)
+ return err;
+
+ /*
+ * If a TCP socket, check name_connect permission for the port.
+ */
+ isec = SOCK_INODE(sock)->i_security;
+ if (isec->sclass == SECCLASS_TCP_SOCKET) {
+ struct sock *sk = sock->sk;
+ struct avc_audit_data ad;
+ struct sockaddr_in *addr4 = NULL;
+ struct sockaddr_in6 *addr6 = NULL;
+ unsigned short snum;
+ u32 sid;
+
+ if (sk->sk_family == PF_INET) {
+ addr4 = (struct sockaddr_in *)address;
+ if (addrlen != sizeof(struct sockaddr_in))
+ return -EINVAL;
+ snum = ntohs(addr4->sin_port);
+ } else {
+ addr6 = (struct sockaddr_in6 *)address;
+ if (addrlen != sizeof(struct sockaddr_in6))
+ return -EINVAL;
+ snum = ntohs(addr6->sin6_port);
+ }
+
+ err = security_port_sid(sk->sk_family, sk->sk_type,
+ sk->sk_protocol, snum, &sid);
+ if (err)
+ goto out;
+
+ AVC_AUDIT_DATA_INIT(&ad,NET);
+ ad.u.net.dport = htons(snum);
+ ad.u.net.family = sk->sk_family;
+ err = avc_has_perm(isec->sid, sid, isec->sclass,
+ TCP_SOCKET__NAME_CONNECT, &ad);
+ if (err)
+ goto out;
+ }
+
+out:
+ return err;
}
static int selinux_socket_listen(struct socket *sock, int backlog)
@@ -3356,6 +3432,15 @@ static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
err = selinux_nlmsg_lookup(isec->sclass, nlh->nlmsg_type, &perm);
if (err) {
+ if (err == -EINVAL) {
+ audit_log(current->audit_context,
+ "SELinux: unrecognized netlink message"
+ " type=%hu for sclass=%hu\n",
+ nlh->nlmsg_type, isec->sclass);
+ if (!selinux_enforcing)
+ err = 0;
+ }
+
/* Ignore */
if (err == -ENOENT)
err = 0;
@@ -3992,7 +4077,7 @@ static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
}
/* module stacking operations */
-int selinux_register_security (const char *name, struct security_operations *ops)
+static int selinux_register_security (const char *name, struct security_operations *ops)
{
if (secondary_ops != original_ops) {
printk(KERN_INFO "%s: There is already a secondary security "
@@ -4009,7 +4094,7 @@ int selinux_register_security (const char *name, struct security_operations *ops
return 0;
}
-int selinux_unregister_security (const char *name, struct security_operations *ops)
+static int selinux_unregister_security (const char *name, struct security_operations *ops)
{
if (ops != secondary_ops) {
printk (KERN_INFO "%s: trying to unregister a security module "
@@ -4079,6 +4164,7 @@ static int selinux_setprocattr(struct task_struct *p,
struct task_security_struct *tsec;
u32 sid = 0;
int error;
+ char *str = value;
if (current != p) {
/* SELinux only allows a process to change its own
@@ -4103,8 +4189,11 @@ static int selinux_setprocattr(struct task_struct *p,
return error;
/* Obtain a SID for the context, if one was specified. */
- if (size) {
- int error;
+ if (size && str[1] && str[1] != '\n') {
+ if (str[size-1] == '\n') {
+ str[size-1] = 0;
+ size--;
+ }
error = security_context_to_sid(value, size, &sid);
if (error)
return error;
@@ -4172,7 +4261,7 @@ static int selinux_setprocattr(struct task_struct *p,
return size;
}
-struct security_operations selinux_ops = {
+static struct security_operations selinux_ops = {
.ptrace = selinux_ptrace,
.capget = selinux_capget,
.capset_check = selinux_capset_check,
@@ -4321,7 +4410,7 @@ struct security_operations selinux_ops = {
#endif
};
-__init int selinux_init(void)
+static __init int selinux_init(void)
{
struct task_security_struct *tsec;
diff --git a/security/selinux/include/av_perm_to_string.h b/security/selinux/include/av_perm_to_string.h
index e1e084ca71d73..903e8b3cc2e9d 100644
--- a/security/selinux/include/av_perm_to_string.h
+++ b/security/selinux/include/av_perm_to_string.h
@@ -25,6 +25,7 @@
S_(SECCLASS_TCP_SOCKET, TCP_SOCKET__NEWCONN, "newconn")
S_(SECCLASS_TCP_SOCKET, TCP_SOCKET__ACCEPTFROM, "acceptfrom")
S_(SECCLASS_TCP_SOCKET, TCP_SOCKET__NODE_BIND, "node_bind")
+ S_(SECCLASS_TCP_SOCKET, TCP_SOCKET__NAME_CONNECT, "name_connect")
S_(SECCLASS_UDP_SOCKET, UDP_SOCKET__NODE_BIND, "node_bind")
S_(SECCLASS_RAWIP_SOCKET, RAWIP_SOCKET__NODE_BIND, "node_bind")
S_(SECCLASS_NODE, NODE__TCP_RECV, "tcp_recv")
@@ -83,6 +84,7 @@
S_(SECCLASS_SECURITY, SECURITY__SETENFORCE, "setenforce")
S_(SECCLASS_SECURITY, SECURITY__SETBOOL, "setbool")
S_(SECCLASS_SECURITY, SECURITY__SETSECPARAM, "setsecparam")
+ S_(SECCLASS_SECURITY, SECURITY__SETCHECKREQPROT, "setcheckreqprot")
S_(SECCLASS_SYSTEM, SYSTEM__IPC_INFO, "ipc_info")
S_(SECCLASS_SYSTEM, SYSTEM__SYSLOG_READ, "syslog_read")
S_(SECCLASS_SYSTEM, SYSTEM__SYSLOG_MOD, "syslog_mod")
diff --git a/security/selinux/include/av_permissions.h b/security/selinux/include/av_permissions.h
index 4f77cc53d722a..b0a12ac8f7eeb 100644
--- a/security/selinux/include/av_permissions.h
+++ b/security/selinux/include/av_permissions.h
@@ -253,6 +253,7 @@
#define TCP_SOCKET__NEWCONN 0x00800000UL
#define TCP_SOCKET__ACCEPTFROM 0x01000000UL
#define TCP_SOCKET__NODE_BIND 0x02000000UL
+#define TCP_SOCKET__NAME_CONNECT 0x04000000UL
#define UDP_SOCKET__IOCTL 0x00000001UL
#define UDP_SOCKET__READ 0x00000002UL
@@ -522,6 +523,7 @@
#define SECURITY__SETENFORCE 0x00000080UL
#define SECURITY__SETBOOL 0x00000100UL
#define SECURITY__SETSECPARAM 0x00000200UL
+#define SECURITY__SETCHECKREQPROT 0x00000400UL
#define SYSTEM__IPC_INFO 0x00000001UL
#define SYSTEM__SYSLOG_READ 0x00000002UL
diff --git a/security/selinux/include/avc.h b/security/selinux/include/avc.h
index ca2fdf557b222..960ef18ddc411 100644
--- a/security/selinux/include/avc.h
+++ b/security/selinux/include/avc.h
@@ -93,13 +93,6 @@ struct avc_cache_stats
};
/*
- * AVC display support
- */
-struct audit_buffer;
-void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av);
-void avc_dump_query(struct audit_buffer *ab, u32 ssid, u32 tsid, u16 tclass);
-
-/*
* AVC operations
*/
diff --git a/security/selinux/include/avc_ss.h b/security/selinux/include/avc_ss.h
index 8fc999745e24e..450a2831e2e32 100644
--- a/security/selinux/include/avc_ss.h
+++ b/security/selinux/include/avc_ss.h
@@ -8,20 +8,7 @@
#include "flask.h"
-int avc_ss_grant(u32 ssid, u32 tsid, u16 tclass, u32 perms, u32 seqno);
-
-int avc_ss_try_revoke(u32 ssid, u32 tsid, u16 tclass, u32 perms, u32 seqno,
- u32 *out_retained);
-
-int avc_ss_revoke(u32 ssid, u32 tsid, u16 tclass, u32 perms, u32 seqno);
-
int avc_ss_reset(u32 seqno);
-int avc_ss_set_auditallow(u32 ssid, u32 tsid, u16 tclass, u32 perms,
- u32 seqno, u32 enable);
-
-int avc_ss_set_auditdeny(u32 ssid, u32 tsid, u16 tclass, u32 perms,
- u32 seqno, u32 enable);
-
#endif /* _SELINUX_AVC_SS_H_ */
diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h
index 30a0abc9c7782..887937c8134a4 100644
--- a/security/selinux/include/objsec.h
+++ b/security/selinux/include/objsec.h
@@ -107,6 +107,6 @@ struct sk_security_struct {
u32 peer_sid; /* SID of peer */
};
-extern int inode_security_set_sid(struct inode *inode, u32 sid);
+extern unsigned int selinux_checkreqprot;
#endif /* _SELINUX_OBJSEC_H_ */
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
index 5931e46d44e56..fa187c9a351db 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -21,10 +21,12 @@
#define POLICYDB_VERSION_BOOL 16
#define POLICYDB_VERSION_IPV6 17
#define POLICYDB_VERSION_NLCLASS 18
+#define POLICYDB_VERSION_VALIDATETRANS 19
+#define POLICYDB_VERSION_MLS 19
/* Range of policy versions we understand*/
#define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE
-#define POLICYDB_VERSION_MAX POLICYDB_VERSION_NLCLASS
+#define POLICYDB_VERSION_MAX POLICYDB_VERSION_MLS
#ifdef CONFIG_SECURITY_SELINUX_BOOTPARAM
extern int selinux_enabled;
@@ -32,11 +34,7 @@ extern int selinux_enabled;
#define selinux_enabled 1
#endif
-#ifdef CONFIG_SECURITY_SELINUX_MLS
-#define selinux_mls_enabled 1
-#else
-#define selinux_mls_enabled 0
-#endif
+extern int selinux_mls_enabled;
int security_load_policy(void * data, size_t len);
@@ -79,6 +77,9 @@ int security_netif_sid(char *name, u32 *if_sid,
int security_node_sid(u16 domain, void *addr, u32 addrlen,
u32 *out_sid);
+int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid,
+ u16 tclass);
+
#define SECURITY_FS_USE_XATTR 1 /* use xattr */
#define SECURITY_FS_USE_TRANS 2 /* use transition SIDs, e.g. devpts/tmpfs */
#define SECURITY_FS_USE_TASK 3 /* use task SIDs, e.g. pipefs/sockfs */
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index 66adccd1c789d..07221568b5059 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -34,6 +34,16 @@
#include "objsec.h"
#include "conditional.h"
+unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE;
+
+static int __init checkreqprot_setup(char *str)
+{
+ selinux_checkreqprot = simple_strtoul(str,NULL,0) ? 1 : 0;
+ return 1;
+}
+__setup("checkreqprot=", checkreqprot_setup);
+
+
static DECLARE_MUTEX(sel_sem);
/* global data for booleans */
@@ -44,8 +54,8 @@ static int *bool_pending_values = NULL;
extern void selnl_notify_setenforce(int val);
/* Check whether a task is allowed to use a security operation. */
-int task_has_security(struct task_struct *tsk,
- u32 perms)
+static int task_has_security(struct task_struct *tsk,
+ u32 perms)
{
struct task_security_struct *tsec;
@@ -72,6 +82,7 @@ enum sel_inos {
SEL_DISABLE, /* disable SELinux until next reboot */
SEL_AVC, /* AVC management directory */
SEL_MEMBER, /* compute polyinstantiation membership decision */
+ SEL_CHECKREQPROT, /* check requested protection, not kernel-applied one */
};
#define TMPBUFLEN 12
@@ -300,6 +311,54 @@ static struct file_operations sel_context_ops = {
.write = sel_write_context,
};
+static ssize_t sel_read_checkreqprot(struct file *filp, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ char tmpbuf[TMPBUFLEN];
+ ssize_t length;
+
+ length = scnprintf(tmpbuf, TMPBUFLEN, "%u", selinux_checkreqprot);
+ return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
+}
+
+static ssize_t sel_write_checkreqprot(struct file * file, const char __user * buf,
+ size_t count, loff_t *ppos)
+{
+ char *page;
+ ssize_t length;
+ unsigned int new_value;
+
+ length = task_has_security(current, SECURITY__SETCHECKREQPROT);
+ if (length)
+ return length;
+
+ if (count < 0 || count >= PAGE_SIZE)
+ return -ENOMEM;
+ if (*ppos != 0) {
+ /* No partial writes. */
+ return -EINVAL;
+ }
+ page = (char*)get_zeroed_page(GFP_KERNEL);
+ if (!page)
+ return -ENOMEM;
+ length = -EFAULT;
+ if (copy_from_user(page, buf, count))
+ goto out;
+
+ length = -EINVAL;
+ if (sscanf(page, "%u", &new_value) != 1)
+ goto out;
+
+ selinux_checkreqprot = new_value ? 1 : 0;
+ length = count;
+out:
+ free_page((unsigned long) page);
+ return length;
+}
+static struct file_operations sel_checkreqprot_ops = {
+ .read = sel_read_checkreqprot,
+ .write = sel_write_checkreqprot,
+};
/*
* Remaining nodes use transaction based IO methods like nfsd/nfsctl.c
@@ -1182,6 +1241,7 @@ static int sel_fill_super(struct super_block * sb, void * data, int silent)
[SEL_MLS] = {"mls", &sel_mls_ops, S_IRUGO},
[SEL_DISABLE] = {"disable", &sel_disable_ops, S_IWUSR},
[SEL_MEMBER] = {"member", &transaction_ops, S_IRUGO|S_IWUGO},
+ [SEL_CHECKREQPROT] = {"checkreqprot", &sel_checkreqprot_ops, S_IRUGO|S_IWUSR},
/* last one */ {""}
};
ret = simple_fill_super(sb, SELINUX_MAGIC, selinux_files);
diff --git a/security/selinux/ss/Makefile b/security/selinux/ss/Makefile
index 70153a0aee67f..bad78779b9b0f 100644
--- a/security/selinux/ss/Makefile
+++ b/security/selinux/ss/Makefile
@@ -5,7 +5,5 @@
EXTRA_CFLAGS += -Isecurity/selinux/include
obj-y := ss.o
-ss-y := ebitmap.o hashtab.o symtab.o sidtab.o avtab.o policydb.o services.o conditional.o
-
-ss-$(CONFIG_SECURITY_SELINUX_MLS) += mls.o
+ss-y := ebitmap.o hashtab.o symtab.o sidtab.o avtab.o policydb.o services.o conditional.o mls.o
diff --git a/security/selinux/ss/avtab.c b/security/selinux/ss/avtab.c
index 609ca16be799f..f238c034c44e2 100644
--- a/security/selinux/ss/avtab.c
+++ b/security/selinux/ss/avtab.c
@@ -31,7 +31,8 @@
static kmem_cache_t *avtab_node_cachep;
static struct avtab_node*
-avtab_insert_node(struct avtab *h, int hvalue, struct avtab_node * prev, struct avtab_node * cur,
+avtab_insert_node(struct avtab *h, int hvalue,
+ struct avtab_node * prev, struct avtab_node * cur,
struct avtab_key *key, struct avtab_datum *datum)
{
struct avtab_node * newnode;
@@ -53,7 +54,7 @@ avtab_insert_node(struct avtab *h, int hvalue, struct avtab_node * prev, struct
return newnode;
}
-int avtab_insert(struct avtab *h, struct avtab_key *key, struct avtab_datum *datum)
+static int avtab_insert(struct avtab *h, struct avtab_key *key, struct avtab_datum *datum)
{
int hvalue;
struct avtab_node *prev, *cur, *newnode;
@@ -237,30 +238,6 @@ void avtab_destroy(struct avtab *h)
}
-int avtab_map(struct avtab *h,
- int (*apply) (struct avtab_key *k,
- struct avtab_datum *d,
- void *args),
- void *args)
-{
- int i, ret;
- struct avtab_node *cur;
-
- if (!h)
- return 0;
-
- for (i = 0; i < AVTAB_SIZE; i++) {
- cur = h->htable[i];
- while (cur != NULL) {
- ret = apply(&cur->key, &cur->datum, args);
- if (ret)
- return ret;
- cur = cur->next;
- }
- }
- return 0;
-}
-
int avtab_init(struct avtab *h)
{
int i;
diff --git a/security/selinux/ss/avtab.h b/security/selinux/ss/avtab.h
index f636ac844a485..519d4f6dc655e 100644
--- a/security/selinux/ss/avtab.h
+++ b/security/selinux/ss/avtab.h
@@ -58,14 +58,8 @@ struct avtab {
};
int avtab_init(struct avtab *);
-int avtab_insert(struct avtab *h, struct avtab_key *k, struct avtab_datum *d);
struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *k, int specified);
void avtab_destroy(struct avtab *h);
-int avtab_map(struct avtab *h,
- int (*apply) (struct avtab_key *k,
- struct avtab_datum *d,
- void *args),
- void *args);
void avtab_hash_eval(struct avtab *h, char *tag);
int avtab_read_item(void *fp, struct avtab_datum *avdatum, struct avtab_key *avkey);
diff --git a/security/selinux/ss/conditional.c b/security/selinux/ss/conditional.c
index 90f5fbd5fad52..b53441184aca7 100644
--- a/security/selinux/ss/conditional.c
+++ b/security/selinux/ss/conditional.c
@@ -208,7 +208,7 @@ int cond_index_bool(void *key, void *datum, void *datap)
return 0;
}
-int bool_isvalid(struct cond_bool_datum *b)
+static int bool_isvalid(struct cond_bool_datum *b)
{
if (!(b->state == 0 || b->state == 1))
return 0;
@@ -401,8 +401,10 @@ static int cond_read_node(struct policydb *p, struct cond_node *node, void *fp)
expr->expr_type = le32_to_cpu(buf[0]);
expr->bool = le32_to_cpu(buf[1]);
- if (!expr_isvalid(p, expr))
+ if (!expr_isvalid(p, expr)) {
+ kfree(expr);
goto err;
+ }
if (i == 0) {
node->expr = expr;
diff --git a/security/selinux/ss/constraint.h b/security/selinux/ss/constraint.h
index e394fc9dfb971..149dda731fd3f 100644
--- a/security/selinux/ss/constraint.h
+++ b/security/selinux/ss/constraint.h
@@ -31,6 +31,13 @@ struct constraint_expr {
#define CEXPR_ROLE 2 /* role */
#define CEXPR_TYPE 4 /* type */
#define CEXPR_TARGET 8 /* target if set, source otherwise */
+#define CEXPR_XTARGET 16 /* special 3rd target for validatetrans rule */
+#define CEXPR_L1L2 32 /* low level 1 vs. low level 2 */
+#define CEXPR_L1H2 64 /* low level 1 vs. high level 2 */
+#define CEXPR_H1L2 128 /* high level 1 vs. low level 2 */
+#define CEXPR_H1H2 256 /* high level 1 vs. high level 2 */
+#define CEXPR_L1H1 512 /* low level 1 vs. high level 1 */
+#define CEXPR_L2H2 1024 /* low level 2 vs. high level 2 */
u32 attr; /* attribute */
#define CEXPR_EQ 1 /* == or eq */
diff --git a/security/selinux/ss/context.h b/security/selinux/ss/context.h
index 581409f6fed0a..0562bacb7b996 100644
--- a/security/selinux/ss/context.h
+++ b/security/selinux/ss/context.h
@@ -17,6 +17,7 @@
#include "ebitmap.h"
#include "mls_types.h"
+#include "security.h"
/*
* A security context consists of an authenticated user
@@ -26,13 +27,9 @@ struct context {
u32 user;
u32 role;
u32 type;
-#ifdef CONFIG_SECURITY_SELINUX_MLS
struct mls_range range;
-#endif
};
-#ifdef CONFIG_SECURITY_SELINUX_MLS
-
static inline void mls_context_init(struct context *c)
{
memset(&c->range, 0, sizeof(c->range));
@@ -42,6 +39,9 @@ static inline int mls_context_cpy(struct context *dst, struct context *src)
{
int rc;
+ if (!selinux_mls_enabled)
+ return 0;
+
dst->range.level[0].sens = src->range.level[0].sens;
rc = ebitmap_cpy(&dst->range.level[0].cat, &src->range.level[0].cat);
if (rc)
@@ -57,6 +57,9 @@ out:
static inline int mls_context_cmp(struct context *c1, struct context *c2)
{
+ if (!selinux_mls_enabled)
+ return 1;
+
return ((c1->range.level[0].sens == c2->range.level[0].sens) &&
ebitmap_cmp(&c1->range.level[0].cat,&c2->range.level[0].cat) &&
(c1->range.level[1].sens == c2->range.level[1].sens) &&
@@ -65,27 +68,14 @@ static inline int mls_context_cmp(struct context *c1, struct context *c2)
static inline void mls_context_destroy(struct context *c)
{
+ if (!selinux_mls_enabled)
+ return;
+
ebitmap_destroy(&c->range.level[0].cat);
ebitmap_destroy(&c->range.level[1].cat);
mls_context_init(c);
}
-#else
-
-static inline void mls_context_init(struct context *c)
-{ }
-
-static inline int mls_context_cpy(struct context *dst, struct context *src)
-{ return 0; }
-
-static inline int mls_context_cmp(struct context *c1, struct context *c2)
-{ return 1; }
-
-static inline void mls_context_destroy(struct context *c)
-{ }
-
-#endif
-
static inline void context_init(struct context *c)
{
memset(c, 0, sizeof(*c));
diff --git a/security/selinux/ss/ebitmap.c b/security/selinux/ss/ebitmap.c
index ad34294aa368a..d8ce9cc0b9f15 100644
--- a/security/selinux/ss/ebitmap.c
+++ b/security/selinux/ss/ebitmap.c
@@ -9,49 +9,6 @@
#include "ebitmap.h"
#include "policydb.h"
-int ebitmap_or(struct ebitmap *dst, struct ebitmap *e1, struct ebitmap *e2)
-{
- struct ebitmap_node *n1, *n2, *new, *prev;
-
- ebitmap_init(dst);
-
- n1 = e1->node;
- n2 = e2->node;
- prev = NULL;
- while (n1 || n2) {
- new = kmalloc(sizeof(*new), GFP_ATOMIC);
- if (!new) {
- ebitmap_destroy(dst);
- return -ENOMEM;
- }
- memset(new, 0, sizeof(*new));
- if (n1 && n2 && n1->startbit == n2->startbit) {
- new->startbit = n1->startbit;
- new->map = n1->map | n2->map;
- n1 = n1->next;
- n2 = n2->next;
- } else if (!n2 || (n1 && n1->startbit < n2->startbit)) {
- new->startbit = n1->startbit;
- new->map = n1->map;
- n1 = n1->next;
- } else {
- new->startbit = n2->startbit;
- new->map = n2->map;
- n2 = n2->next;
- }
-
- new->next = NULL;
- if (prev)
- prev->next = new;
- else
- dst->node = new;
- prev = new;
- }
-
- dst->highbit = (e1->highbit > e2->highbit) ? e1->highbit : e2->highbit;
- return 0;
-}
-
int ebitmap_cmp(struct ebitmap *e1, struct ebitmap *e2)
{
struct ebitmap_node *n1, *n2;
diff --git a/security/selinux/ss/ebitmap.h b/security/selinux/ss/ebitmap.h
index 321764c23cf58..471370233fd9e 100644
--- a/security/selinux/ss/ebitmap.h
+++ b/security/selinux/ss/ebitmap.h
@@ -38,7 +38,6 @@ static inline void ebitmap_init(struct ebitmap *e)
}
int ebitmap_cmp(struct ebitmap *e1, struct ebitmap *e2);
-int ebitmap_or(struct ebitmap *dst, struct ebitmap *e1, struct ebitmap *e2);
int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src);
int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2);
int ebitmap_get_bit(struct ebitmap *e, unsigned long bit);
diff --git a/security/selinux/ss/hashtab.c b/security/selinux/ss/hashtab.c
index 2a6752a8d016b..26661fcc00ce3 100644
--- a/security/selinux/ss/hashtab.c
+++ b/security/selinux/ss/hashtab.c
@@ -73,81 +73,6 @@ int hashtab_insert(struct hashtab *h, void *key, void *datum)
return 0;
}
-int hashtab_remove(struct hashtab *h, void *key,
- void (*destroy)(void *k, void *d, void *args),
- void *args)
-{
- u32 hvalue;
- struct hashtab_node *cur, *last;
-
- if (!h)
- return -EINVAL;
-
- hvalue = h->hash_value(h, key);
- last = NULL;
- cur = h->htable[hvalue];
- while (cur != NULL && h->keycmp(h, key, cur->key) > 0) {
- last = cur;
- cur = cur->next;
- }
-
- if (cur == NULL || (h->keycmp(h, key, cur->key) != 0))
- return -ENOENT;
-
- if (last == NULL)
- h->htable[hvalue] = cur->next;
- else
- last->next = cur->next;
-
- if (destroy)
- destroy(cur->key, cur->datum, args);
- kfree(cur);
- h->nel--;
- return 0;
-}
-
-int hashtab_replace(struct hashtab *h, void *key, void *datum,
- void (*destroy)(void *k, void *d, void *args),
- void *args)
-{
- u32 hvalue;
- struct hashtab_node *prev, *cur, *newnode;
-
- if (!h)
- return -EINVAL;
-
- hvalue = h->hash_value(h, key);
- prev = NULL;
- cur = h->htable[hvalue];
- while (cur != NULL && h->keycmp(h, key, cur->key) > 0) {
- prev = cur;
- cur = cur->next;
- }
-
- if (cur && (h->keycmp(h, key, cur->key) == 0)) {
- if (destroy)
- destroy(cur->key, cur->datum, args);
- cur->key = key;
- cur->datum = datum;
- } else {
- newnode = kmalloc(sizeof(*newnode), GFP_KERNEL);
- if (newnode == NULL)
- return -ENOMEM;
- memset(newnode, 0, sizeof(*newnode));
- newnode->key = key;
- newnode->datum = datum;
- if (prev) {
- newnode->next = prev->next;
- prev->next = newnode;
- } else {
- newnode->next = h->htable[hvalue];
- h->htable[hvalue] = newnode;
- }
- }
-
- return 0;
-}
-
void *hashtab_search(struct hashtab *h, void *key)
{
u32 hvalue;
@@ -215,44 +140,6 @@ int hashtab_map(struct hashtab *h,
}
-void hashtab_map_remove_on_error(struct hashtab *h,
- int (*apply)(void *k, void *d, void *args),
- void (*destroy)(void *k, void *d, void *args),
- void *args)
-{
- u32 i;
- int ret;
- struct hashtab_node *last, *cur, *temp;
-
- if (!h)
- return;
-
- for (i = 0; i < h->size; i++) {
- last = NULL;
- cur = h->htable[i];
- while (cur != NULL) {
- ret = apply(cur->key, cur->datum, args);
- if (ret) {
- if (last)
- last->next = cur->next;
- else
- h->htable[i] = cur->next;
-
- temp = cur;
- cur = cur->next;
- if (destroy)
- destroy(temp->key, temp->datum, args);
- kfree(temp);
- h->nel--;
- } else {
- last = cur;
- cur = cur->next;
- }
- }
- }
- return;
-}
-
void hashtab_stat(struct hashtab *h, struct hashtab_info *info)
{
u32 i, chain_len, slots_used, max_chain_len;
diff --git a/security/selinux/ss/hashtab.h b/security/selinux/ss/hashtab.h
index 10c3be19605fd..4cc85816a718a 100644
--- a/security/selinux/ss/hashtab.h
+++ b/security/selinux/ss/hashtab.h
@@ -54,33 +54,6 @@ struct hashtab *hashtab_create(u32 (*hash_value)(struct hashtab *h, void *key),
int hashtab_insert(struct hashtab *h, void *k, void *d);
/*
- * Removes the entry with the specified key from the hash table.
- * Applies the specified destroy function to (key,datum,args) for
- * the entry.
- *
- * Returns -ENOENT if no entry has the specified key,
- * -EINVAL for general errors or
- *0 otherwise.
- */
-int hashtab_remove(struct hashtab *h, void *k,
- void (*destroy)(void *k, void *d, void *args),
- void *args);
-
-/*
- * Insert or replace the specified (key, datum) pair in the specified
- * hash table. If an entry for the specified key already exists,
- * then the specified destroy function is applied to (key,datum,args)
- * for the entry prior to replacing the entry's contents.
- *
- * Returns -ENOMEM if insufficient space is available,
- * -EINVAL for general errors or
- * 0 otherwise.
- */
-int hashtab_replace(struct hashtab *h, void *k, void *d,
- void (*destroy)(void *k, void *d, void *args),
- void *args);
-
-/*
* Searches for the entry with the specified key in the hash table.
*
* Returns NULL if no entry has the specified key or
@@ -108,17 +81,6 @@ int hashtab_map(struct hashtab *h,
int (*apply)(void *k, void *d, void *args),
void *args);
-/*
- * Same as hashtab_map, except that if apply returns a non-zero status,
- * then the (key,datum) pair will be removed from the hashtab and the
- * destroy function will be applied to (key,datum,args).
- */
-void hashtab_map_remove_on_error(struct hashtab *h,
- int (*apply)(void *k, void *d, void *args),
- void (*destroy)(void *k, void *d, void *args),
- void *args);
-
-
/* Fill info with some hash table statistics */
void hashtab_stat(struct hashtab *h, struct hashtab_info *info);
diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c
index 5ef5bd5bcc1c4..756036bcc2431 100644
--- a/security/selinux/ss/mls.c
+++ b/security/selinux/ss/mls.c
@@ -3,6 +3,14 @@
*
* Author : Stephen Smalley, <sds@epoch.ncsc.mil>
*/
+/*
+ * Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com>
+ *
+ * Support for enhanced MLS infrastructure.
+ *
+ * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
+ */
+
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/string.h>
@@ -12,79 +20,47 @@
#include "services.h"
/*
- * Remove any permissions from `allowed' that are
- * denied by the MLS policy.
- */
-void mls_compute_av(struct context *scontext,
- struct context *tcontext,
- struct class_datum *tclass,
- u32 *allowed)
-{
- unsigned int rel[2];
- int l;
-
- for (l = 0; l < 2; l++)
- rel[l] = mls_level_relation(scontext->range.level[l],
- tcontext->range.level[l]);
-
- if (rel[1] != MLS_RELATION_EQ) {
- if (rel[1] != MLS_RELATION_DOM &&
- !ebitmap_get_bit(&policydb.trustedreaders, scontext->type - 1) &&
- !ebitmap_get_bit(&policydb.trustedobjects, tcontext->type - 1)) {
- /* read(s,t) = (s.high >= t.high) = False */
- *allowed = (*allowed) & ~(tclass->mlsperms.read);
- }
- if (rel[1] != MLS_RELATION_DOMBY &&
- !ebitmap_get_bit(&policydb.trustedreaders, tcontext->type - 1) &&
- !ebitmap_get_bit(&policydb.trustedobjects, scontext->type - 1)) {
- /* readby(s,t) = read(t,s) = False */
- *allowed = (*allowed) & ~(tclass->mlsperms.readby);
- }
- }
- if (((rel[0] != MLS_RELATION_DOMBY && rel[0] != MLS_RELATION_EQ) ||
- ((!mls_level_eq(tcontext->range.level[0],
- tcontext->range.level[1])) &&
- (rel[1] != MLS_RELATION_DOM && rel[1] != MLS_RELATION_EQ))) &&
- !ebitmap_get_bit(&policydb.trustedwriters, scontext->type - 1) &&
- !ebitmap_get_bit(&policydb.trustedobjects, tcontext->type - 1)) {
- /*
- * write(s,t) = ((s.low <= t.low = t.high) or (s.low
- * <= t.low <= t.high <= s.high)) = False
- */
- *allowed = (*allowed) & ~(tclass->mlsperms.write);
- }
-
- if (((rel[0] != MLS_RELATION_DOM && rel[0] != MLS_RELATION_EQ) ||
- ((!mls_level_eq(scontext->range.level[0],
- scontext->range.level[1])) &&
- (rel[1] != MLS_RELATION_DOMBY && rel[1] != MLS_RELATION_EQ))) &&
- !ebitmap_get_bit(&policydb.trustedwriters, tcontext->type - 1) &&
- !ebitmap_get_bit(&policydb.trustedobjects, scontext->type - 1)) {
- /* writeby(s,t) = write(t,s) = False */
- *allowed = (*allowed) & ~(tclass->mlsperms.writeby);
- }
-}
-
-/*
* Return the length in bytes for the MLS fields of the
* security context string representation of `context'.
*/
int mls_compute_context_len(struct context * context)
{
- int i, l, len;
+ int i, l, len, range;
+ if (!selinux_mls_enabled)
+ return 0;
- len = 0;
+ len = 1; /* for the beginning ":" */
for (l = 0; l < 2; l++) {
- len += strlen(policydb.p_sens_val_to_name[context->range.level[l].sens - 1]) + 1;
+ range = 0;
+ len += strlen(policydb.p_sens_val_to_name[context->range.level[l].sens - 1]);
- for (i = 1; i <= ebitmap_length(&context->range.level[l].cat); i++)
- if (ebitmap_get_bit(&context->range.level[l].cat, i - 1))
- len += strlen(policydb.p_cat_val_to_name[i - 1]) + 1;
+ for (i = 1; i <= ebitmap_length(&context->range.level[l].cat); i++) {
+ if (ebitmap_get_bit(&context->range.level[l].cat, i - 1)) {
+ if (range) {
+ range++;
+ continue;
+ }
- if (mls_level_relation(context->range.level[0], context->range.level[1])
- == MLS_RELATION_EQ)
- break;
+ len += strlen(policydb.p_cat_val_to_name[i - 1]) + 1;
+ range++;
+ } else {
+ if (range > 1)
+ len += strlen(policydb.p_cat_val_to_name[i - 2]) + 1;
+ range = 0;
+ }
+ }
+ /* Handle case where last category is the end of range */
+ if (range > 1)
+ len += strlen(policydb.p_cat_val_to_name[i - 2]) + 1;
+
+ if (l == 0) {
+ if (mls_level_eq(&context->range.level[0],
+ &context->range.level[1]))
+ break;
+ else
+ len++;
+ }
}
return len;
@@ -95,40 +71,81 @@ int mls_compute_context_len(struct context * context)
* the MLS fields of `context' into the string `*scontext'.
* Update `*scontext' to point to the end of the MLS fields.
*/
-int mls_sid_to_context(struct context *context,
- char **scontext)
+void mls_sid_to_context(struct context *context,
+ char **scontext)
{
char *scontextp;
- int i, l;
+ int i, l, range, wrote_sep;
+
+ if (!selinux_mls_enabled)
+ return;
scontextp = *scontext;
+ *scontextp = ':';
+ scontextp++;
+
for (l = 0; l < 2; l++) {
+ range = 0;
+ wrote_sep = 0;
strcpy(scontextp,
policydb.p_sens_val_to_name[context->range.level[l].sens - 1]);
scontextp += strlen(policydb.p_sens_val_to_name[context->range.level[l].sens - 1]);
- *scontextp = ':';
- scontextp++;
- for (i = 1; i <= ebitmap_length(&context->range.level[l].cat); i++)
+
+ /* categories */
+ for (i = 1; i <= ebitmap_length(&context->range.level[l].cat); i++) {
if (ebitmap_get_bit(&context->range.level[l].cat, i - 1)) {
+ if (range) {
+ range++;
+ continue;
+ }
+
+ if (!wrote_sep) {
+ *scontextp++ = ':';
+ wrote_sep = 1;
+ } else
+ *scontextp++ = ',';
strcpy(scontextp, policydb.p_cat_val_to_name[i - 1]);
scontextp += strlen(policydb.p_cat_val_to_name[i - 1]);
- *scontextp = ',';
- scontextp++;
+ range++;
+ } else {
+ if (range > 1) {
+ if (range > 2)
+ *scontextp++ = '.';
+ else
+ *scontextp++ = ',';
+
+ strcpy(scontextp, policydb.p_cat_val_to_name[i - 2]);
+ scontextp += strlen(policydb.p_cat_val_to_name[i - 2]);
+ }
+ range = 0;
}
- if (mls_level_relation(context->range.level[0], context->range.level[1])
- != MLS_RELATION_EQ) {
- scontextp--;
- sprintf(scontextp, "-");
- scontextp++;
+ }
- } else {
- break;
+ /* Handle case where last category is the end of range */
+ if (range > 1) {
+ if (range > 2)
+ *scontextp++ = '.';
+ else
+ *scontextp++ = ',';
+
+ strcpy(scontextp, policydb.p_cat_val_to_name[i - 2]);
+ scontextp += strlen(policydb.p_cat_val_to_name[i - 2]);
+ }
+
+ if (l == 0) {
+ if (mls_level_eq(&context->range.level[0],
+ &context->range.level[1]))
+ break;
+ else {
+ *scontextp = '-';
+ scontextp++;
+ }
}
}
*scontext = scontextp;
- return 0;
+ return;
}
/*
@@ -137,20 +154,19 @@ int mls_sid_to_context(struct context *context,
*/
int mls_context_isvalid(struct policydb *p, struct context *c)
{
- unsigned int relation;
struct level_datum *levdatum;
struct user_datum *usrdatum;
- struct mls_range_list *rnode;
int i, l;
+ if (!selinux_mls_enabled)
+ return 1;
+
/*
* MLS range validity checks: high must dominate low, low level must
* be valid (category set <-> sensitivity check), and high level must
* be valid (category set <-> sensitivity check)
*/
- relation = mls_level_relation(c->range.level[1],
- c->range.level[0]);
- if (!(relation & (MLS_RELATION_DOM | MLS_RELATION_EQ)))
+ if (!mls_level_dom(&c->range.level[1], &c->range.level[0]))
/* High does not dominate low. */
return 0;
@@ -185,18 +201,12 @@ int mls_context_isvalid(struct policydb *p, struct context *c)
if (!c->user || c->user > p->p_users.nprim)
return 0;
usrdatum = p->user_val_to_struct[c->user - 1];
- for (rnode = usrdatum->ranges; rnode; rnode = rnode->next) {
- if (mls_range_contains(rnode->range, c->range))
- break;
- }
- if (!rnode)
- /* user may not be associated with range */
- return 0;
+ if (!mls_range_contains(usrdatum->range, c->range))
+ return 0; /* user may not be associated with range */
return 1;
}
-
/*
* Set the MLS fields in the security context structure
* `context' based on the string representation in
@@ -213,23 +223,17 @@ int mls_context_to_sid(char oldc,
{
char delim;
- char *scontextp, *p;
+ char *scontextp, *p, *rngptr;
struct level_datum *levdatum;
- struct cat_datum *catdatum;
+ struct cat_datum *catdatum, *rngdatum;
int l, rc = -EINVAL;
- if (!oldc) {
- /* No MLS component to the security context. Try
- to use a default 'unclassified' value. */
- levdatum = hashtab_search(policydb.p_levels.table,
- "unclassified");
- if (!levdatum)
- goto out;
- context->range.level[0].sens = levdatum->level->sens;
- context->range.level[1].sens = context->range.level[0].sens;
- rc = 0;
+ if (!selinux_mls_enabled)
+ return 0;
+
+ /* No MLS component to the security context. */
+ if (!oldc)
goto out;
- }
/* Extract low sensitivity. */
scontextp = p = *scontext;
@@ -242,13 +246,15 @@ int mls_context_to_sid(char oldc,
for (l = 0; l < 2; l++) {
levdatum = hashtab_search(policydb.p_levels.table, scontextp);
- if (!levdatum)
+ if (!levdatum) {
+ rc = -EINVAL;
goto out;
+ }
context->range.level[l].sens = levdatum->level->sens;
if (delim == ':') {
- /* Extract low category set. */
+ /* Extract category set. */
while (1) {
scontextp = p;
while (*p && *p != ',' && *p != '-')
@@ -257,15 +263,46 @@ int mls_context_to_sid(char oldc,
if (delim != 0)
*p++ = 0;
+ /* Separate into range if exists */
+ if ((rngptr = strchr(scontextp, '.')) != NULL) {
+ /* Remove '.' */
+ *rngptr++ = 0;
+ }
+
catdatum = hashtab_search(policydb.p_cats.table,
scontextp);
- if (!catdatum)
+ if (!catdatum) {
+ rc = -EINVAL;
goto out;
+ }
rc = ebitmap_set_bit(&context->range.level[l].cat,
catdatum->value - 1, 1);
if (rc)
goto out;
+
+ /* If range, set all categories in range */
+ if (rngptr) {
+ int i;
+
+ rngdatum = hashtab_search(policydb.p_cats.table, rngptr);
+ if (!rngdatum) {
+ rc = -EINVAL;
+ goto out;
+ }
+
+ if (catdatum->value >= rngdatum->value) {
+ rc = -EINVAL;
+ goto out;
+ }
+
+ for (i = catdatum->value; i < rngdatum->value; i++) {
+ rc = ebitmap_set_bit(&context->range.level[l].cat, i, 1);
+ if (rc)
+ goto out;
+ }
+ }
+
if (delim != ',')
break;
}
@@ -306,7 +343,6 @@ static inline int mls_copy_context(struct context *dst,
/* Copy the MLS range from the source context */
for (l = 0; l < 2; l++) {
-
dst->range.level[l].sens = src->range.level[l].sens;
rc = ebitmap_cpy(&dst->range.level[l].cat,
&src->range.level[l].cat);
@@ -318,6 +354,84 @@ static inline int mls_copy_context(struct context *dst,
}
/*
+ * Copies the effective MLS range from `src' into `dst'.
+ */
+static inline int mls_scopy_context(struct context *dst,
+ struct context *src)
+{
+ int l, rc = 0;
+
+ /* Copy the MLS range from the source context */
+ for (l = 0; l < 2; l++) {
+ dst->range.level[l].sens = src->range.level[0].sens;
+ rc = ebitmap_cpy(&dst->range.level[l].cat,
+ &src->range.level[0].cat);
+ if (rc)
+ break;
+ }
+
+ return rc;
+}
+
+/*
+ * Copies the MLS range `range' into `context'.
+ */
+static inline int mls_range_set(struct context *context,
+ struct mls_range *range)
+{
+ int l, rc = 0;
+
+ /* Copy the MLS range into the context */
+ for (l = 0; l < 2; l++) {
+ context->range.level[l].sens = range->level[l].sens;
+ rc = ebitmap_cpy(&context->range.level[l].cat,
+ &range->level[l].cat);
+ if (rc)
+ break;
+ }
+
+ return rc;
+}
+
+int mls_setup_user_range(struct context *fromcon, struct user_datum *user,
+ struct context *usercon)
+{
+ if (selinux_mls_enabled) {
+ struct mls_level *fromcon_sen = &(fromcon->range.level[0]);
+ struct mls_level *fromcon_clr = &(fromcon->range.level[1]);
+ struct mls_level *user_low = &(user->range.level[0]);
+ struct mls_level *user_clr = &(user->range.level[1]);
+ struct mls_level *user_def = &(user->dfltlevel);
+ struct mls_level *usercon_sen = &(usercon->range.level[0]);
+ struct mls_level *usercon_clr = &(usercon->range.level[1]);
+
+ /* Honor the user's default level if we can */
+ if (mls_level_between(user_def, fromcon_sen, fromcon_clr)) {
+ *usercon_sen = *user_def;
+ } else if (mls_level_between(fromcon_sen, user_def, user_clr)) {
+ *usercon_sen = *fromcon_sen;
+ } else if (mls_level_between(fromcon_clr, user_low, user_def)) {
+ *usercon_sen = *user_low;
+ } else
+ return -EINVAL;
+
+ /* Lower the clearance of available contexts
+ if the clearance of "fromcon" is lower than
+ that of the user's default clearance (but
+ only if the "fromcon" clearance dominates
+ the user's computed sensitivity level) */
+ if (mls_level_dom(user_clr, fromcon_clr)) {
+ *usercon_clr = *fromcon_clr;
+ } else if (mls_level_dom(fromcon_clr, user_clr)) {
+ *usercon_clr = *user_clr;
+ } else
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/*
* Convert the MLS fields in the security context
* structure `c' from the values specified in the
* policy `oldp' to the values specified in the policy `newp'.
@@ -331,6 +445,9 @@ int mls_convert_context(struct policydb *oldp,
struct ebitmap bitmap;
int l, i;
+ if (!selinux_mls_enabled)
+ return 0;
+
for (l = 0; l < 2; l++) {
levdatum = hashtab_search(newp->p_levels.table,
oldp->p_sens_val_to_name[c->range.level[l].sens - 1]);
@@ -366,17 +483,38 @@ int mls_compute_sid(struct context *scontext,
u32 specified,
struct context *newcontext)
{
+ if (!selinux_mls_enabled)
+ return 0;
+
switch (specified) {
case AVTAB_TRANSITION:
+ if (tclass == SECCLASS_PROCESS) {
+ struct range_trans *rangetr;
+ /* Look for a range transition rule. */
+ for (rangetr = policydb.range_tr; rangetr;
+ rangetr = rangetr->next) {
+ if (rangetr->dom == scontext->type &&
+ rangetr->type == tcontext->type) {
+ /* Set the range from the rule */
+ return mls_range_set(newcontext,
+ &rangetr->range);
+ }
+ }
+ }
+ /* Fallthrough */
case AVTAB_CHANGE:
- /* Use the process MLS attributes. */
- return mls_copy_context(newcontext, scontext);
+ if (tclass == SECCLASS_PROCESS)
+ /* Use the process MLS attributes. */
+ return mls_copy_context(newcontext, scontext);
+ else
+ /* Use the process effective MLS attributes. */
+ return mls_scopy_context(newcontext, scontext);
case AVTAB_MEMBER:
/* Only polyinstantiate the MLS attributes if
the type is being polyinstantiated */
if (newcontext->type != tcontext->type) {
- /* Use the process MLS attributes. */
- return mls_copy_context(newcontext, scontext);
+ /* Use the process effective MLS attributes. */
+ return mls_scopy_context(newcontext, scontext);
} else {
/* Use the related object MLS attributes. */
return mls_copy_context(newcontext, tcontext);
@@ -387,365 +525,3 @@ int mls_compute_sid(struct context *scontext,
return -EINVAL;
}
-void mls_user_destroy(struct user_datum *usrdatum)
-{
- struct mls_range_list *rnode, *rtmp;
- rnode = usrdatum->ranges;
- while (rnode) {
- rtmp = rnode;
- rnode = rnode->next;
- ebitmap_destroy(&rtmp->range.level[0].cat);
- ebitmap_destroy(&rtmp->range.level[1].cat);
- kfree(rtmp);
- }
-}
-
-int mls_read_perm(struct perm_datum *perdatum, void *fp)
-{
- u32 buf[1];
- int rc;
-
- rc = next_entry(buf, fp, sizeof buf);
- if (rc < 0)
- return -EINVAL;
- perdatum->base_perms = le32_to_cpu(buf[0]);
- return 0;
-}
-
-/*
- * Read a MLS level structure from a policydb binary
- * representation file.
- */
-struct mls_level *mls_read_level(void *fp)
-{
- struct mls_level *l;
- u32 buf[1];
- int rc;
-
- l = kmalloc(sizeof(*l), GFP_ATOMIC);
- if (!l) {
- printk(KERN_ERR "security: mls: out of memory\n");
- return NULL;
- }
- memset(l, 0, sizeof(*l));
-
- rc = next_entry(buf, fp, sizeof buf);
- if (rc < 0) {
- printk(KERN_ERR "security: mls: truncated level\n");
- goto bad;
- }
- l->sens = cpu_to_le32(buf[0]);
-
- if (ebitmap_read(&l->cat, fp)) {
- printk(KERN_ERR "security: mls: error reading level "
- "categories\n");
- goto bad;
- }
- return l;
-
-bad:
- kfree(l);
- return NULL;
-}
-
-
-/*
- * Read a MLS range structure from a policydb binary
- * representation file.
- */
-static int mls_read_range_helper(struct mls_range *r, void *fp)
-{
- u32 buf[2], items;
- int rc;
-
- rc = next_entry(buf, fp, sizeof(u32));
- if (rc < 0)
- goto out;
-
- items = le32_to_cpu(buf[0]);
- if (items > ARRAY_SIZE(buf)) {
- printk(KERN_ERR "security: mls: range overflow\n");
- rc = -EINVAL;
- goto out;
- }
- rc = next_entry(buf, fp, sizeof(u32) * items);
- if (rc < 0) {
- printk(KERN_ERR "security: mls: truncated range\n");
- goto out;
- }
- r->level[0].sens = le32_to_cpu(buf[0]);
- if (items > 1) {
- r->level[1].sens = le32_to_cpu(buf[1]);
- } else {
- r->level[1].sens = r->level[0].sens;
- }
-
- rc = ebitmap_read(&r->level[0].cat, fp);
- if (rc) {
- printk(KERN_ERR "security: mls: error reading low "
- "categories\n");
- goto out;
- }
- if (items > 1) {
- rc = ebitmap_read(&r->level[1].cat, fp);
- if (rc) {
- printk(KERN_ERR "security: mls: error reading high "
- "categories\n");
- goto bad_high;
- }
- } else {
- rc = ebitmap_cpy(&r->level[1].cat, &r->level[0].cat);
- if (rc) {
- printk(KERN_ERR "security: mls: out of memory\n");
- goto bad_high;
- }
- }
-
- rc = 0;
-out:
- return rc;
-bad_high:
- ebitmap_destroy(&r->level[0].cat);
- goto out;
-}
-
-int mls_read_range(struct context *c, void *fp)
-{
- return mls_read_range_helper(&c->range, fp);
-}
-
-
-/*
- * Read a MLS perms structure from a policydb binary
- * representation file.
- */
-int mls_read_class(struct class_datum *cladatum, void *fp)
-{
- struct mls_perms *p = &cladatum->mlsperms;
- u32 buf[4];
- int rc;
-
- rc = next_entry(buf, fp, sizeof buf);
- if (rc < 0) {
- printk(KERN_ERR "security: mls: truncated mls permissions\n");
- return -EINVAL;
- }
- p->read = le32_to_cpu(buf[0]);
- p->readby = le32_to_cpu(buf[1]);
- p->write = le32_to_cpu(buf[2]);
- p->writeby = le32_to_cpu(buf[3]);
- return 0;
-}
-
-int mls_read_user(struct user_datum *usrdatum, void *fp)
-{
- struct mls_range_list *r, *l;
- int rc;
- u32 nel, i;
- u32 buf[1];
-
- rc = next_entry(buf, fp, sizeof buf);
- if (rc < 0)
- goto out;
- nel = le32_to_cpu(buf[0]);
- l = NULL;
- for (i = 0; i < nel; i++) {
- r = kmalloc(sizeof(*r), GFP_ATOMIC);
- if (!r) {
- rc = -ENOMEM;
- goto out;
- }
- memset(r, 0, sizeof(*r));
-
- rc = mls_read_range_helper(&r->range, fp);
- if (rc) {
- kfree(r);
- goto out;
- }
-
- if (l)
- l->next = r;
- else
- usrdatum->ranges = r;
- l = r;
- }
-out:
- return rc;
-}
-
-int mls_read_nlevels(struct policydb *p, void *fp)
-{
- u32 buf[1];
- int rc;
-
- rc = next_entry(buf, fp, sizeof buf);
- if (rc < 0)
- return -EINVAL;
- p->nlevels = le32_to_cpu(buf[0]);
- return 0;
-}
-
-int mls_read_trusted(struct policydb *p, void *fp)
-{
- int rc = 0;
-
- rc = ebitmap_read(&p->trustedreaders, fp);
- if (rc)
- goto out;
- rc = ebitmap_read(&p->trustedwriters, fp);
- if (rc)
- goto bad;
- rc = ebitmap_read(&p->trustedobjects, fp);
- if (rc)
- goto bad2;
-out:
- return rc;
-bad2:
- ebitmap_destroy(&p->trustedwriters);
-bad:
- ebitmap_destroy(&p->trustedreaders);
- goto out;
-}
-
-int sens_index(void *key, void *datum, void *datap)
-{
- struct policydb *p;
- struct level_datum *levdatum;
-
-
- levdatum = datum;
- p = datap;
-
- if (!levdatum->isalias)
- p->p_sens_val_to_name[levdatum->level->sens - 1] = key;
-
- return 0;
-}
-
-int cat_index(void *key, void *datum, void *datap)
-{
- struct policydb *p;
- struct cat_datum *catdatum;
-
-
- catdatum = datum;
- p = datap;
-
-
- if (!catdatum->isalias)
- p->p_cat_val_to_name[catdatum->value - 1] = key;
-
- return 0;
-}
-
-int sens_destroy(void *key, void *datum, void *p)
-{
- struct level_datum *levdatum;
-
- kfree(key);
- levdatum = datum;
- if (!levdatum->isalias) {
- ebitmap_destroy(&levdatum->level->cat);
- kfree(levdatum->level);
- }
- kfree(datum);
- return 0;
-}
-
-int cat_destroy(void *key, void *datum, void *p)
-{
- kfree(key);
- kfree(datum);
- return 0;
-}
-
-int sens_read(struct policydb *p, struct hashtab *h, void *fp)
-{
- char *key = NULL;
- struct level_datum *levdatum;
- int rc;
- u32 buf[2], len;
-
- levdatum = kmalloc(sizeof(*levdatum), GFP_ATOMIC);
- if (!levdatum) {
- rc = -ENOMEM;
- goto out;
- }
- memset(levdatum, 0, sizeof(*levdatum));
-
- rc = next_entry(buf, fp, sizeof buf);
- if (rc < 0)
- goto bad;
-
- len = le32_to_cpu(buf[0]);
- levdatum->isalias = le32_to_cpu(buf[1]);
-
- key = kmalloc(len + 1,GFP_ATOMIC);
- if (!key) {
- rc = -ENOMEM;
- goto bad;
- }
- rc = next_entry(key, fp, len);
- if (rc < 0)
- goto bad;
- key[len] = 0;
-
- levdatum->level = mls_read_level(fp);
- if (!levdatum->level) {
- rc = -EINVAL;
- goto bad;
- }
-
- rc = hashtab_insert(h, key, levdatum);
- if (rc)
- goto bad;
-out:
- return rc;
-bad:
- sens_destroy(key, levdatum, NULL);
- goto out;
-}
-
-
-int cat_read(struct policydb *p, struct hashtab *h, void *fp)
-{
- char *key = NULL;
- struct cat_datum *catdatum;
- int rc;
- u32 buf[3], len;
-
- catdatum = kmalloc(sizeof(*catdatum), GFP_ATOMIC);
- if (!catdatum) {
- rc = -ENOMEM;
- goto out;
- }
- memset(catdatum, 0, sizeof(*catdatum));
-
- rc = next_entry(buf, fp, sizeof buf);
- if (rc < 0)
- goto bad;
-
- len = le32_to_cpu(buf[0]);
- catdatum->value = le32_to_cpu(buf[1]);
- catdatum->isalias = le32_to_cpu(buf[2]);
-
- key = kmalloc(len + 1,GFP_ATOMIC);
- if (!key) {
- rc = -ENOMEM;
- goto bad;
- }
- rc = next_entry(key, fp, len);
- if (rc < 0)
- goto bad;
- key[len] = 0;
-
- rc = hashtab_insert(h, key, catdatum);
- if (rc)
- goto bad;
-out:
- return rc;
-
-bad:
- cat_destroy(key, catdatum, NULL);
- goto out;
-}
diff --git a/security/selinux/ss/mls.h b/security/selinux/ss/mls.h
index 01c3fc81fc3d4..0d37beaa85e2f 100644
--- a/security/selinux/ss/mls.h
+++ b/security/selinux/ss/mls.h
@@ -3,21 +3,22 @@
*
* Author : Stephen Smalley, <sds@epoch.ncsc.mil>
*/
+/*
+ * Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com>
+ *
+ * Support for enhanced MLS infrastructure.
+ *
+ * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
+ */
+
#ifndef _SS_MLS_H_
#define _SS_MLS_H_
#include "context.h"
#include "policydb.h"
-#ifdef CONFIG_SECURITY_SELINUX_MLS
-
-void mls_compute_av(struct context *scontext,
- struct context *tcontext,
- struct class_datum *tclass,
- u32 *allowed);
-
int mls_compute_context_len(struct context *context);
-int mls_sid_to_context(struct context *context, char **scontext);
+void mls_sid_to_context(struct context *context, char **scontext);
int mls_context_isvalid(struct policydb *p, struct context *c);
int mls_context_to_sid(char oldc,
@@ -34,66 +35,8 @@ int mls_compute_sid(struct context *scontext,
u32 specified,
struct context *newcontext);
-int sens_index(void *key, void *datum, void *datap);
-int cat_index(void *key, void *datum, void *datap);
-int sens_destroy(void *key, void *datum, void *p);
-int cat_destroy(void *key, void *datum, void *p);
-int sens_read(struct policydb *p, struct hashtab *h, void *fp);
-int cat_read(struct policydb *p, struct hashtab *h, void *fp);
-
-#define mls_for_user_ranges(user, usercon) { \
-struct mls_range_list *__ranges; \
-for (__ranges = user->ranges; __ranges; __ranges = __ranges->next) { \
-usercon.range = __ranges->range;
-
-#define mls_end_user_ranges } }
-
-#define mls_symtab_names "levels", "categories",
-#define mls_symtab_sizes 16, 16,
-#define mls_index_f sens_index, cat_index,
-#define mls_destroy_f sens_destroy, cat_destroy,
-#define mls_read_f sens_read, cat_read,
-#define mls_write_f sens_write, cat_write,
-#define mls_policydb_index_others(p) printk(", %d levels", p->nlevels);
-
-#define mls_set_config(config) config |= POLICYDB_CONFIG_MLS
-
-void mls_user_destroy(struct user_datum *usrdatum);
-int mls_read_range(struct context *c, void *fp);
-int mls_read_perm(struct perm_datum *perdatum, void *fp);
-int mls_read_class(struct class_datum *cladatum, void *fp);
-int mls_read_user(struct user_datum *usrdatum, void *fp);
-int mls_read_nlevels(struct policydb *p, void *fp);
-int mls_read_trusted(struct policydb *p, void *fp);
-
-#else
-
-#define mls_compute_av(scontext, tcontext, tclass_datum, allowed)
-#define mls_compute_context_len(context) 0
-#define mls_sid_to_context(context, scontextpp)
-#define mls_context_isvalid(p, c) 1
-#define mls_context_to_sid(oldc, context_str, context) 0
-#define mls_convert_context(oldp, newp, c) 0
-#define mls_compute_sid(scontext, tcontext, tclass, specified, newcontextp) 0
-#define mls_for_user_ranges(user, usercon)
-#define mls_end_user_ranges
-#define mls_symtab_names
-#define mls_symtab_sizes
-#define mls_index_f
-#define mls_destroy_f
-#define mls_read_f
-#define mls_write_f
-#define mls_policydb_index_others(p)
-#define mls_set_config(config)
-#define mls_user_destroy(usrdatum)
-#define mls_read_range(c, fp) 0
-#define mls_read_perm(p, fp) 0
-#define mls_read_class(c, fp) 0
-#define mls_read_user(u, fp) 0
-#define mls_read_nlevels(p, fp) 0
-#define mls_read_trusted(p, fp) 0
-
-#endif
+int mls_setup_user_range(struct context *fromcon, struct user_datum *user,
+ struct context *usercon);
#endif /* _SS_MLS_H */
diff --git a/security/selinux/ss/mls_types.h b/security/selinux/ss/mls_types.h
index 9f454a1ecd0d0..0c692d58d489f 100644
--- a/security/selinux/ss/mls_types.h
+++ b/security/selinux/ss/mls_types.h
@@ -3,9 +3,19 @@
*
* Author : Stephen Smalley, <sds@epoch.ncsc.mil>
*/
+/*
+ * Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com>
+ *
+ * Support for enhanced MLS infrastructure.
+ *
+ * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
+ */
+
#ifndef _SS_MLS_TYPES_H_
#define _SS_MLS_TYPES_H_
+#include "security.h"
+
struct mls_level {
u32 sens; /* sensitivity */
struct ebitmap cat; /* category set */
@@ -15,44 +25,32 @@ struct mls_range {
struct mls_level level[2]; /* low == level[0], high == level[1] */
};
-struct mls_range_list {
- struct mls_range range;
- struct mls_range_list *next;
-};
+static inline int mls_level_eq(struct mls_level *l1, struct mls_level *l2)
+{
+ if (!selinux_mls_enabled)
+ return 1;
-#define MLS_RELATION_DOM 1 /* source dominates */
-#define MLS_RELATION_DOMBY 2 /* target dominates */
-#define MLS_RELATION_EQ 4 /* source and target are equivalent */
-#define MLS_RELATION_INCOMP 8 /* source and target are incomparable */
-
-#define mls_level_eq(l1,l2) \
-(((l1).sens == (l2).sens) && ebitmap_cmp(&(l1).cat,&(l2).cat))
-
-#define mls_level_relation(l1,l2) ( \
-(((l1).sens == (l2).sens) && ebitmap_cmp(&(l1).cat,&(l2).cat)) ? \
- MLS_RELATION_EQ : \
-(((l1).sens >= (l2).sens) && ebitmap_contains(&(l1).cat, &(l2).cat)) ? \
- MLS_RELATION_DOM : \
-(((l2).sens >= (l1).sens) && ebitmap_contains(&(l2).cat, &(l1).cat)) ? \
- MLS_RELATION_DOMBY : \
- MLS_RELATION_INCOMP )
-
-#define mls_range_contains(r1,r2) \
-((mls_level_relation((r1).level[0], (r2).level[0]) & \
- (MLS_RELATION_EQ | MLS_RELATION_DOMBY)) && \
- (mls_level_relation((r1).level[1], (r2).level[1]) & \
- (MLS_RELATION_EQ | MLS_RELATION_DOM)))
+ return ((l1->sens == l2->sens) &&
+ ebitmap_cmp(&l1->cat, &l2->cat));
+}
-/*
- * Every access vector permission is mapped to a set of MLS base
- * permissions, based on the flow properties of the corresponding
- * operation.
- */
-struct mls_perms {
- u32 read; /* permissions that map to `read' */
- u32 readby; /* permissions that map to `readby' */
- u32 write; /* permissions that map to `write' */
- u32 writeby; /* permissions that map to `writeby' */
-};
+static inline int mls_level_dom(struct mls_level *l1, struct mls_level *l2)
+{
+ if (!selinux_mls_enabled)
+ return 1;
+
+ return ((l1->sens >= l2->sens) &&
+ ebitmap_contains(&l1->cat, &l2->cat));
+}
+
+#define mls_level_incomp(l1, l2) \
+(!mls_level_dom((l1), (l2)) && !mls_level_dom((l2), (l1)))
+
+#define mls_level_between(l1, l2, l3) \
+(mls_level_dom((l1), (l2)) && mls_level_dom((l3), (l1)))
+
+#define mls_range_contains(r1, r2) \
+(mls_level_dom(&(r2).level[0], &(r1).level[0]) && \
+ mls_level_dom(&(r1).level[1], &(r2).level[1]))
#endif /* _SS_MLS_TYPES_H_ */
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index 7fc245f3ac320..14190efbf333b 100644
--- a/security/selinux/ss/policydb.c
+++ b/security/selinux/ss/policydb.c
@@ -4,10 +4,16 @@
* Author : Stephen Smalley, <sds@epoch.ncsc.mil>
*/
-/* Updated: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com>
+/*
+ * Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com>
+ *
+ * Support for enhanced MLS infrastructure.
+ *
+ * Updated: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com>
*
* Added conditional policy language extensions
*
+ * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
* Copyright (C) 2003 - 2004 Tresys Technology, LLC
* This 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,19 +39,23 @@ static char *symtab_name[SYM_NUM] = {
"roles",
"types",
"users",
- mls_symtab_names
- "bools"
+ "bools",
+ "levels",
+ "categories",
};
#endif
+int selinux_mls_enabled = 0;
+
static unsigned int symtab_sizes[SYM_NUM] = {
2,
32,
16,
512,
128,
- mls_symtab_sizes
- 16
+ 16,
+ 16,
+ 16,
};
struct policydb_compat_info {
@@ -58,21 +68,26 @@ struct policydb_compat_info {
static struct policydb_compat_info policydb_compat[] = {
{
.version = POLICYDB_VERSION_BASE,
- .sym_num = SYM_NUM - 1,
+ .sym_num = SYM_NUM - 3,
.ocon_num = OCON_NUM - 1,
},
{
.version = POLICYDB_VERSION_BOOL,
- .sym_num = SYM_NUM,
+ .sym_num = SYM_NUM - 2,
.ocon_num = OCON_NUM - 1,
},
{
.version = POLICYDB_VERSION_IPV6,
- .sym_num = SYM_NUM,
+ .sym_num = SYM_NUM - 2,
.ocon_num = OCON_NUM,
},
{
.version = POLICYDB_VERSION_NLCLASS,
+ .sym_num = SYM_NUM - 2,
+ .ocon_num = OCON_NUM,
+ },
+ {
+ .version = POLICYDB_VERSION_MLS,
.sym_num = SYM_NUM,
.ocon_num = OCON_NUM,
},
@@ -95,7 +110,7 @@ static struct policydb_compat_info *policydb_lookup_compat(int version)
/*
* Initialize the role table.
*/
-int roles_init(struct policydb *p)
+static int roles_init(struct policydb *p)
{
char *key = NULL;
int rc;
@@ -134,7 +149,7 @@ out_free_role:
/*
* Initialize a policy database structure.
*/
-int policydb_init(struct policydb *p)
+static int policydb_init(struct policydb *p)
{
int i, rc;
@@ -252,6 +267,41 @@ static int user_index(void *key, void *datum, void *datap)
return 0;
}
+static int sens_index(void *key, void *datum, void *datap)
+{
+ struct policydb *p;
+ struct level_datum *levdatum;
+
+ levdatum = datum;
+ p = datap;
+
+ if (!levdatum->isalias) {
+ if (!levdatum->level->sens ||
+ levdatum->level->sens > p->p_levels.nprim)
+ return -EINVAL;
+ p->p_sens_val_to_name[levdatum->level->sens - 1] = key;
+ }
+
+ return 0;
+}
+
+static int cat_index(void *key, void *datum, void *datap)
+{
+ struct policydb *p;
+ struct cat_datum *catdatum;
+
+ catdatum = datum;
+ p = datap;
+
+ if (!catdatum->isalias) {
+ if (!catdatum->value || catdatum->value > p->p_cats.nprim)
+ return -EINVAL;
+ p->p_cat_val_to_name[catdatum->value - 1] = key;
+ }
+
+ return 0;
+}
+
static int (*index_f[SYM_NUM]) (void *key, void *datum, void *datap) =
{
common_index,
@@ -259,8 +309,9 @@ static int (*index_f[SYM_NUM]) (void *key, void *datum, void *datap) =
role_index,
type_index,
user_index,
- mls_index_f
- cond_index_bool
+ cond_index_bool,
+ sens_index,
+ cat_index,
};
/*
@@ -270,7 +321,7 @@ static int (*index_f[SYM_NUM]) (void *key, void *datum, void *datap) =
*
* Caller must clean up upon failure.
*/
-int policydb_index_classes(struct policydb *p)
+static int policydb_index_classes(struct policydb *p)
{
int rc;
@@ -327,13 +378,15 @@ static void symtab_hash_eval(struct symtab *s)
*
* Caller must clean up on failure.
*/
-int policydb_index_others(struct policydb *p)
+static int policydb_index_others(struct policydb *p)
{
int i, rc = 0;
printk(KERN_INFO "security: %d users, %d roles, %d types, %d bools",
p->p_users.nprim, p->p_roles.nprim, p->p_types.nprim, p->p_bools.nprim);
- mls_policydb_index_others(p);
+ if (selinux_mls_enabled)
+ printk(", %d sens, %d cats", p->p_levels.nprim,
+ p->p_cats.nprim);
printk("\n");
printk(KERN_INFO "security: %d classes, %d rules\n",
@@ -429,6 +482,21 @@ static int class_destroy(void *key, void *datum, void *p)
constraint = constraint->next;
kfree(ctemp);
}
+
+ constraint = cladatum->validatetrans;
+ while (constraint) {
+ e = constraint->expr;
+ while (e) {
+ ebitmap_destroy(&e->names);
+ etmp = e;
+ e = e->next;
+ kfree(etmp);
+ }
+ ctemp = constraint;
+ constraint = constraint->next;
+ kfree(ctemp);
+ }
+
kfree(cladatum->comkey);
kfree(datum);
return 0;
@@ -460,7 +528,28 @@ static int user_destroy(void *key, void *datum, void *p)
kfree(key);
usrdatum = datum;
ebitmap_destroy(&usrdatum->roles);
- mls_user_destroy(usrdatum);
+ ebitmap_destroy(&usrdatum->range.level[0].cat);
+ ebitmap_destroy(&usrdatum->range.level[1].cat);
+ ebitmap_destroy(&usrdatum->dfltlevel.cat);
+ kfree(datum);
+ return 0;
+}
+
+static int sens_destroy(void *key, void *datum, void *p)
+{
+ struct level_datum *levdatum;
+
+ kfree(key);
+ levdatum = datum;
+ ebitmap_destroy(&levdatum->level->cat);
+ kfree(levdatum->level);
+ kfree(datum);
+ return 0;
+}
+
+static int cat_destroy(void *key, void *datum, void *p)
+{
+ kfree(key);
kfree(datum);
return 0;
}
@@ -472,11 +561,12 @@ static int (*destroy_f[SYM_NUM]) (void *key, void *datum, void *datap) =
role_destroy,
type_destroy,
user_destroy,
- mls_destroy_f
- cond_destroy_bool
+ cond_destroy_bool,
+ sens_destroy,
+ cat_destroy,
};
-void ocontext_destroy(struct ocontext *c, int i)
+static void ocontext_destroy(struct ocontext *c, int i)
{
context_destroy(&c->context[0]);
context_destroy(&c->context[1]);
@@ -624,6 +714,65 @@ int policydb_context_isvalid(struct policydb *p, struct context *c)
}
/*
+ * Read a MLS range structure from a policydb binary
+ * representation file.
+ */
+static int mls_read_range_helper(struct mls_range *r, void *fp)
+{
+ u32 buf[2], items;
+ int rc;
+
+ rc = next_entry(buf, fp, sizeof(u32));
+ if (rc < 0)
+ goto out;
+
+ items = le32_to_cpu(buf[0]);
+ if (items > ARRAY_SIZE(buf)) {
+ printk(KERN_ERR "security: mls: range overflow\n");
+ rc = -EINVAL;
+ goto out;
+ }
+ rc = next_entry(buf, fp, sizeof(u32) * items);
+ if (rc < 0) {
+ printk(KERN_ERR "security: mls: truncated range\n");
+ goto out;
+ }
+ r->level[0].sens = le32_to_cpu(buf[0]);
+ if (items > 1)
+ r->level[1].sens = le32_to_cpu(buf[1]);
+ else
+ r->level[1].sens = r->level[0].sens;
+
+ rc = ebitmap_read(&r->level[0].cat, fp);
+ if (rc) {
+ printk(KERN_ERR "security: mls: error reading low "
+ "categories\n");
+ goto out;
+ }
+ if (items > 1) {
+ rc = ebitmap_read(&r->level[1].cat, fp);
+ if (rc) {
+ printk(KERN_ERR "security: mls: error reading high "
+ "categories\n");
+ goto bad_high;
+ }
+ } else {
+ rc = ebitmap_cpy(&r->level[1].cat, &r->level[0].cat);
+ if (rc) {
+ printk(KERN_ERR "security: mls: out of memory\n");
+ goto bad_high;
+ }
+ }
+
+ rc = 0;
+out:
+ return rc;
+bad_high:
+ ebitmap_destroy(&r->level[0].cat);
+ goto out;
+}
+
+/*
* Read and validate a security context structure
* from a policydb binary representation file.
*/
@@ -642,11 +791,13 @@ static int context_read_and_validate(struct context *c,
c->user = le32_to_cpu(buf[0]);
c->role = le32_to_cpu(buf[1]);
c->type = le32_to_cpu(buf[2]);
- if (mls_read_range(c, fp)) {
- printk(KERN_ERR "security: error reading MLS range of "
- "context\n");
- rc = -EINVAL;
- goto out;
+ if (p->policyvers >= POLICYDB_VERSION_MLS) {
+ if (mls_read_range_helper(&c->range, fp)) {
+ printk(KERN_ERR "security: error reading MLS range of "
+ "context\n");
+ rc = -EINVAL;
+ goto out;
+ }
}
if (!policydb_context_isvalid(p, c)) {
@@ -684,9 +835,6 @@ static int perm_read(struct policydb *p, struct hashtab *h, void *fp)
len = le32_to_cpu(buf[0]);
perdatum->value = le32_to_cpu(buf[1]);
- rc = mls_read_perm(perdatum, fp);
- if (rc)
- goto bad;
key = kmalloc(len + 1,GFP_KERNEL);
if (!key) {
@@ -761,19 +909,102 @@ bad:
goto out;
}
+static int read_cons_helper(struct constraint_node **nodep, int ncons,
+ int allowxtarget, void *fp)
+{
+ struct constraint_node *c, *lc;
+ struct constraint_expr *e, *le;
+ u32 buf[3], nexpr;
+ int rc, i, j, depth;
+
+ lc = NULL;
+ for (i = 0; i < ncons; i++) {
+ c = kmalloc(sizeof(*c), GFP_KERNEL);
+ if (!c)
+ return -ENOMEM;
+ memset(c, 0, sizeof(*c));
+
+ if (lc) {
+ lc->next = c;
+ } else {
+ *nodep = c;
+ }
+
+ rc = next_entry(buf, fp, (sizeof(u32) * 2));
+ if (rc < 0)
+ return rc;
+ c->permissions = le32_to_cpu(buf[0]);
+ nexpr = le32_to_cpu(buf[1]);
+ le = NULL;
+ depth = -1;
+ for (j = 0; j < nexpr; j++) {
+ e = kmalloc(sizeof(*e), GFP_KERNEL);
+ if (!e)
+ return -ENOMEM;
+ memset(e, 0, sizeof(*e));
+
+ if (le) {
+ le->next = e;
+ } else {
+ c->expr = e;
+ }
+
+ rc = next_entry(buf, fp, (sizeof(u32) * 3));
+ if (rc < 0)
+ return rc;
+ e->expr_type = le32_to_cpu(buf[0]);
+ e->attr = le32_to_cpu(buf[1]);
+ e->op = le32_to_cpu(buf[2]);
+
+ switch (e->expr_type) {
+ case CEXPR_NOT:
+ if (depth < 0)
+ return -EINVAL;
+ break;
+ case CEXPR_AND:
+ case CEXPR_OR:
+ if (depth < 1)
+ return -EINVAL;
+ depth--;
+ break;
+ case CEXPR_ATTR:
+ if (depth == (CEXPR_MAXDEPTH - 1))
+ return -EINVAL;
+ depth++;
+ break;
+ case CEXPR_NAMES:
+ if (!allowxtarget && (e->attr & CEXPR_XTARGET))
+ return -EINVAL;
+ if (depth == (CEXPR_MAXDEPTH - 1))
+ return -EINVAL;
+ depth++;
+ if (ebitmap_read(&e->names, fp))
+ return -EINVAL;
+ break;
+ default:
+ return -EINVAL;
+ }
+ le = e;
+ }
+ if (depth != 0)
+ return -EINVAL;
+ lc = c;
+ }
+
+ return 0;
+}
+
static int class_read(struct policydb *p, struct hashtab *h, void *fp)
{
char *key = NULL;
struct class_datum *cladatum;
- struct constraint_node *c, *lc;
- struct constraint_expr *e, *le;
- u32 buf[6], len, len2, ncons, nexpr, nel;
- int i, j, depth, rc;
+ u32 buf[6], len, len2, ncons, nel;
+ int i, rc;
cladatum = kmalloc(sizeof(*cladatum), GFP_KERNEL);
if (!cladatum) {
rc = -ENOMEM;
- goto bad;
+ goto out;
}
memset(cladatum, 0, sizeof(*cladatum));
@@ -829,87 +1060,21 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp)
goto bad;
}
- lc = NULL;
- for (i = 0; i < ncons; i++) {
- c = kmalloc(sizeof(*c), GFP_KERNEL);
- if (!c) {
- rc = -ENOMEM;
- goto bad;
- }
- memset(c, 0, sizeof(*c));
-
- if (lc) {
- lc->next = c;
- } else {
- cladatum->constraints = c;
- }
+ rc = read_cons_helper(&cladatum->constraints, ncons, 0, fp);
+ if (rc)
+ goto bad;
- rc = next_entry(buf, fp, sizeof(u32)*2);
+ if (p->policyvers >= POLICYDB_VERSION_VALIDATETRANS) {
+ /* grab the validatetrans rules */
+ rc = next_entry(buf, fp, sizeof(u32));
if (rc < 0)
goto bad;
- c->permissions = le32_to_cpu(buf[0]);
- nexpr = le32_to_cpu(buf[1]);
- le = NULL;
- depth = -1;
- for (j = 0; j < nexpr; j++) {
- e = kmalloc(sizeof(*e), GFP_KERNEL);
- if (!e) {
- rc = -ENOMEM;
- goto bad;
- }
- memset(e, 0, sizeof(*e));
-
- if (le) {
- le->next = e;
- } else {
- c->expr = e;
- }
-
- rc = next_entry(buf, fp, sizeof(u32)*3);
- if (rc < 0)
- goto bad;
- e->expr_type = le32_to_cpu(buf[0]);
- e->attr = le32_to_cpu(buf[1]);
- e->op = le32_to_cpu(buf[2]);
-
- rc = -EINVAL;
- switch (e->expr_type) {
- case CEXPR_NOT:
- if (depth < 0)
- goto bad;
- break;
- case CEXPR_AND:
- case CEXPR_OR:
- if (depth < 1)
- goto bad;
- depth--;
- break;
- case CEXPR_ATTR:
- if (depth == (CEXPR_MAXDEPTH-1))
- goto bad;
- depth++;
- break;
- case CEXPR_NAMES:
- if (depth == (CEXPR_MAXDEPTH-1))
- goto bad;
- depth++;
- if (ebitmap_read(&e->names, fp))
- goto bad;
- break;
- default:
- goto bad;
- }
- le = e;
- }
- if (depth != 0)
+ ncons = le32_to_cpu(buf[0]);
+ rc = read_cons_helper(&cladatum->validatetrans, ncons, 1, fp);
+ if (rc)
goto bad;
- lc = c;
}
- rc = mls_read_class(cladatum, fp);
- if (rc)
- goto bad;
-
rc = hashtab_insert(h, key, cladatum);
if (rc)
goto bad;
@@ -1024,6 +1189,36 @@ bad:
goto out;
}
+
+/*
+ * Read a MLS level structure from a policydb binary
+ * representation file.
+ */
+static int mls_read_level(struct mls_level *lp, void *fp)
+{
+ u32 buf[1];
+ int rc;
+
+ memset(lp, 0, sizeof(*lp));
+
+ rc = next_entry(buf, fp, sizeof buf);
+ if (rc < 0) {
+ printk(KERN_ERR "security: mls: truncated level\n");
+ goto bad;
+ }
+ lp->sens = le32_to_cpu(buf[0]);
+
+ if (ebitmap_read(&lp->cat, fp)) {
+ printk(KERN_ERR "security: mls: error reading level "
+ "categories\n");
+ goto bad;
+ }
+ return 0;
+
+bad:
+ return -EINVAL;
+}
+
static int user_read(struct policydb *p, struct hashtab *h, void *fp)
{
char *key = NULL;
@@ -1031,7 +1226,6 @@ static int user_read(struct policydb *p, struct hashtab *h, void *fp)
int rc;
u32 buf[2], len;
-
usrdatum = kmalloc(sizeof(*usrdatum), GFP_KERNEL);
if (!usrdatum) {
rc = -ENOMEM;
@@ -1060,9 +1254,14 @@ static int user_read(struct policydb *p, struct hashtab *h, void *fp)
if (rc)
goto bad;
- rc = mls_read_user(usrdatum, fp);
- if (rc)
- goto bad;
+ if (p->policyvers >= POLICYDB_VERSION_MLS) {
+ rc = mls_read_range_helper(&usrdatum->range, fp);
+ if (rc)
+ goto bad;
+ rc = mls_read_level(&usrdatum->dfltlevel, fp);
+ if (rc)
+ goto bad;
+ }
rc = hashtab_insert(h, key, usrdatum);
if (rc)
@@ -1074,6 +1273,100 @@ bad:
goto out;
}
+static int sens_read(struct policydb *p, struct hashtab *h, void *fp)
+{
+ char *key = NULL;
+ struct level_datum *levdatum;
+ int rc;
+ u32 buf[2], len;
+
+ levdatum = kmalloc(sizeof(*levdatum), GFP_ATOMIC);
+ if (!levdatum) {
+ rc = -ENOMEM;
+ goto out;
+ }
+ memset(levdatum, 0, sizeof(*levdatum));
+
+ rc = next_entry(buf, fp, sizeof buf);
+ if (rc < 0)
+ goto bad;
+
+ len = le32_to_cpu(buf[0]);
+ levdatum->isalias = le32_to_cpu(buf[1]);
+
+ key = kmalloc(len + 1,GFP_ATOMIC);
+ if (!key) {
+ rc = -ENOMEM;
+ goto bad;
+ }
+ rc = next_entry(key, fp, len);
+ if (rc < 0)
+ goto bad;
+ key[len] = 0;
+
+ levdatum->level = kmalloc(sizeof(struct mls_level), GFP_ATOMIC);
+ if (!levdatum->level) {
+ rc = -ENOMEM;
+ goto bad;
+ }
+ if (mls_read_level(levdatum->level, fp)) {
+ rc = -EINVAL;
+ goto bad;
+ }
+
+ rc = hashtab_insert(h, key, levdatum);
+ if (rc)
+ goto bad;
+out:
+ return rc;
+bad:
+ sens_destroy(key, levdatum, NULL);
+ goto out;
+}
+
+static int cat_read(struct policydb *p, struct hashtab *h, void *fp)
+{
+ char *key = NULL;
+ struct cat_datum *catdatum;
+ int rc;
+ u32 buf[3], len;
+
+ catdatum = kmalloc(sizeof(*catdatum), GFP_ATOMIC);
+ if (!catdatum) {
+ rc = -ENOMEM;
+ goto out;
+ }
+ memset(catdatum, 0, sizeof(*catdatum));
+
+ rc = next_entry(buf, fp, sizeof buf);
+ if (rc < 0)
+ goto bad;
+
+ len = le32_to_cpu(buf[0]);
+ catdatum->value = le32_to_cpu(buf[1]);
+ catdatum->isalias = le32_to_cpu(buf[2]);
+
+ key = kmalloc(len + 1,GFP_ATOMIC);
+ if (!key) {
+ rc = -ENOMEM;
+ goto bad;
+ }
+ rc = next_entry(key, fp, len);
+ if (rc < 0)
+ goto bad;
+ key[len] = 0;
+
+ rc = hashtab_insert(h, key, catdatum);
+ if (rc)
+ goto bad;
+out:
+ return rc;
+
+bad:
+ cat_destroy(key, catdatum, NULL);
+ goto out;
+}
+
static int (*read_f[SYM_NUM]) (struct policydb *p, struct hashtab *h, void *fp) =
{
common_read,
@@ -1081,12 +1374,12 @@ static int (*read_f[SYM_NUM]) (struct policydb *p, struct hashtab *h, void *fp)
role_read,
type_read,
user_read,
- mls_read_f
- cond_read_bool
+ cond_read_bool,
+ sens_read,
+ cat_read,
};
-#define mls_config(x) \
- ((x) & POLICYDB_CONFIG_MLS) ? "mls" : "no_mls"
+extern int ss_initialized;
/*
* Read the configuration data from a policy database binary
@@ -1102,9 +1395,9 @@ int policydb_read(struct policydb *p, void *fp)
u32 buf[8], len, len2, config, nprim, nel, nel2;
char *policydb_str;
struct policydb_compat_info *info;
+ struct range_trans *rt, *lrt;
config = 0;
- mls_set_config(config);
rc = policydb_init(p);
if (rc)
@@ -1172,14 +1465,27 @@ int policydb_read(struct policydb *p, void *fp)
goto bad;
}
- if (buf[1] != config) {
- printk(KERN_ERR "security: policydb configuration (%s) does "
- "not match my configuration (%s)\n",
- mls_config(buf[1]),
- mls_config(config));
- goto bad;
- }
+ if ((buf[1] & POLICYDB_CONFIG_MLS)) {
+ if (ss_initialized && !selinux_mls_enabled) {
+ printk(KERN_ERR "Cannot switch between non-MLS and MLS "
+ "policies\n");
+ goto bad;
+ }
+ selinux_mls_enabled = 1;
+ config |= POLICYDB_CONFIG_MLS;
+ if (p->policyvers < POLICYDB_VERSION_MLS) {
+ printk(KERN_ERR "security policydb version %d (MLS) "
+ "not backwards compatible\n", p->policyvers);
+ goto bad;
+ }
+ } else {
+ if (ss_initialized && selinux_mls_enabled) {
+ printk(KERN_ERR "Cannot switch between MLS and non-MLS "
+ "policies\n");
+ goto bad;
+ }
+ }
info = policydb_lookup_compat(p->policyvers);
if (!info) {
@@ -1195,10 +1501,6 @@ int policydb_read(struct policydb *p, void *fp)
goto bad;
}
- rc = mls_read_nlevels(p, fp);
- if (rc)
- goto bad;
-
for (i = 0; i < info->sym_num; i++) {
rc = next_entry(buf, fp, sizeof(u32)*2);
if (rc < 0)
@@ -1499,9 +1801,34 @@ int policydb_read(struct policydb *p, void *fp)
}
}
- rc = mls_read_trusted(p, fp);
- if (rc)
- goto bad;
+ if (p->policyvers >= POLICYDB_VERSION_MLS) {
+ rc = next_entry(buf, fp, sizeof(u32));
+ if (rc < 0)
+ goto bad;
+ nel = le32_to_cpu(buf[0]);
+ lrt = NULL;
+ for (i = 0; i < nel; i++) {
+ rt = kmalloc(sizeof(*rt), GFP_KERNEL);
+ if (!rt) {
+ rc = -ENOMEM;
+ goto bad;
+ }
+ memset(rt, 0, sizeof(*rt));
+ if (lrt)
+ lrt->next = rt;
+ else
+ p->range_tr = rt;
+ rc = next_entry(buf, fp, (sizeof(u32) * 2));
+ if (rc < 0)
+ goto bad;
+ rt->dom = le32_to_cpu(buf[0]);
+ rt->type = le32_to_cpu(buf[1]);
+ rc = mls_read_range_helper(&rt->range, fp);
+ if (rc)
+ goto bad;
+ lrt = rt;
+ }
+ }
rc = 0;
out:
diff --git a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h
index e660e85f2e569..2470e2a1a1c3c 100644
--- a/security/selinux/ss/policydb.h
+++ b/security/selinux/ss/policydb.h
@@ -5,10 +5,16 @@
* Author : Stephen Smalley, <sds@epoch.ncsc.mil>
*/
-/* Updated: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com>
+/*
+ * Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com>
+ *
+ * Support for enhanced MLS infrastructure.
+ *
+ * Updated: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com>
*
* Added conditional policy language extensions
*
+ * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
* Copyright (C) 2003 - 2004 Tresys Technology, LLC
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -34,13 +40,6 @@
/* Permission attributes */
struct perm_datum {
u32 value; /* permission bit + 1 */
-#ifdef CONFIG_SECURITY_SELINUX_MLS
-#define MLS_BASE_READ 1 /* MLS base permission `read' */
-#define MLS_BASE_WRITE 2 /* MLS base permission `write' */
-#define MLS_BASE_READBY 4 /* MLS base permission `readby' */
-#define MLS_BASE_WRITEBY 8 /* MLS base permission `writeby' */
- u32 base_perms; /* MLS base permission mask */
-#endif
};
/* Attributes of a common prefix for access vectors */
@@ -56,9 +55,7 @@ struct class_datum {
struct common_datum *comdatum; /* common datum */
struct symtab permissions; /* class-specific permission symbol table */
struct constraint_node *constraints; /* constraints on class permissions */
-#ifdef CONFIG_SECURITY_SELINUX_MLS
- struct mls_perms mlsperms; /* MLS base permission masks */
-#endif
+ struct constraint_node *validatetrans; /* special transition rules */
};
/* Role attributes */
@@ -91,13 +88,11 @@ struct type_datum {
struct user_datum {
u32 value; /* internal user value */
struct ebitmap roles; /* set of authorized roles for user */
-#ifdef CONFIG_SECURITY_SELINUX_MLS
- struct mls_range_list *ranges; /* list of authorized MLS ranges for user */
-#endif
+ struct mls_range range; /* MLS range (min - max) for user */
+ struct mls_level dfltlevel; /* default login MLS level for user */
};
-#ifdef CONFIG_SECURITY_SELINUX_MLS
/* Sensitivity attributes */
struct level_datum {
struct mls_level *level; /* sensitivity and associated categories */
@@ -109,7 +104,13 @@ struct cat_datum {
u32 value; /* internal category bit + 1 */
unsigned char isalias; /* is this category an alias for another? */
};
-#endif
+
+struct range_trans {
+ u32 dom; /* current process domain */
+ u32 type; /* program executable type */
+ struct mls_range range; /* new range */
+ struct range_trans *next;
+};
/* Boolean data type */
struct cond_bool_datum {
@@ -164,15 +165,10 @@ struct genfs {
#define SYM_ROLES 2
#define SYM_TYPES 3
#define SYM_USERS 4
-#ifdef CONFIG_SECURITY_SELINUX_MLS
-#define SYM_LEVELS 5
-#define SYM_CATS 6
-#define SYM_BOOLS 7
-#define SYM_NUM 8
-#else
#define SYM_BOOLS 5
-#define SYM_NUM 6
-#endif
+#define SYM_LEVELS 6
+#define SYM_CATS 7
+#define SYM_NUM 8
/* object context array indices */
#define OCON_ISID 0 /* initial SIDs */
@@ -193,9 +189,9 @@ struct policydb {
#define p_roles symtab[SYM_ROLES]
#define p_types symtab[SYM_TYPES]
#define p_users symtab[SYM_USERS]
+#define p_bools symtab[SYM_BOOLS]
#define p_levels symtab[SYM_LEVELS]
#define p_cats symtab[SYM_CATS]
-#define p_bools symtab[SYM_BOOLS]
/* symbol names indexed by (value - 1) */
char **sym_val_to_name[SYM_NUM];
@@ -204,9 +200,9 @@ struct policydb {
#define p_role_val_to_name sym_val_to_name[SYM_ROLES]
#define p_type_val_to_name sym_val_to_name[SYM_TYPES]
#define p_user_val_to_name sym_val_to_name[SYM_USERS]
+#define p_bool_val_to_name sym_val_to_name[SYM_BOOLS]
#define p_sens_val_to_name sym_val_to_name[SYM_LEVELS]
#define p_cat_val_to_name sym_val_to_name[SYM_CATS]
-#define p_bool_val_to_name sym_val_to_name[SYM_BOOLS]
/* class, role, and user attributes indexed by (value - 1) */
struct class_datum **class_val_to_struct;
@@ -238,21 +234,12 @@ struct policydb {
fixed labeling behavior. */
struct genfs *genfs;
-#ifdef CONFIG_SECURITY_SELINUX_MLS
- /* number of legitimate MLS levels */
- u32 nlevels;
-
- struct ebitmap trustedreaders;
- struct ebitmap trustedwriters;
- struct ebitmap trustedobjects;
-#endif
+ /* range transitions */
+ struct range_trans *range_tr;
unsigned int policyvers;
};
-extern int policydb_init(struct policydb *p);
-extern int policydb_index_classes(struct policydb *p);
-extern int policydb_index_others(struct policydb *p);
extern void policydb_destroy(struct policydb *p);
extern int policydb_load_isids(struct policydb *p, struct sidtab *s);
extern int policydb_context_isvalid(struct policydb *p, struct context *c);
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 11545e0f83076..5a820cf88c9c9 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -4,17 +4,17 @@
* Authors : Stephen Smalley, <sds@epoch.ncsc.mil>
* James Morris <jmorris@redhat.com>
*
- * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com>
+ * Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com>
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2,
- * as published by the Free Software Foundation.
+ * Support for enhanced MLS infrastructure.
*
* Updated: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com>
*
* Added conditional policy language extensions
*
+ * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
* Copyright (C) 2003 - 2004 Tresys Technology, LLC
+ * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com>
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 2.
@@ -52,7 +52,7 @@ static DECLARE_MUTEX(load_sem);
#define LOAD_LOCK down(&load_sem)
#define LOAD_UNLOCK up(&load_sem)
-struct sidtab sidtab;
+static struct sidtab sidtab;
struct policydb policydb;
int ss_initialized = 0;
@@ -64,18 +64,30 @@ int ss_initialized = 0;
*/
static u32 latest_granting = 0;
+/* Forward declaration. */
+static int context_struct_to_string(struct context *context, char **scontext,
+ u32 *scontext_len);
+
/*
* Return the boolean value of a constraint expression
* when it is applied to the specified source and target
* security contexts.
+ *
+ * xcontext is a special beast... It is used by the validatetrans rules
+ * only. For these rules, scontext is the context before the transition,
+ * tcontext is the context after the transition, and xcontext is the context
+ * of the process performing the transition. All other callers of
+ * constraint_expr_eval should pass in NULL for xcontext.
*/
static int constraint_expr_eval(struct context *scontext,
struct context *tcontext,
+ struct context *xcontext,
struct constraint_expr *cexpr)
{
u32 val1, val2;
struct context *c;
struct role_datum *r1, *r2;
+ struct mls_level *l1, *l2;
struct constraint_expr *e;
int s[CEXPR_MAXDEPTH];
int sp = -1;
@@ -132,6 +144,52 @@ static int constraint_expr_eval(struct context *scontext,
break;
}
break;
+ case CEXPR_L1L2:
+ l1 = &(scontext->range.level[0]);
+ l2 = &(tcontext->range.level[0]);
+ goto mls_ops;
+ case CEXPR_L1H2:
+ l1 = &(scontext->range.level[0]);
+ l2 = &(tcontext->range.level[1]);
+ goto mls_ops;
+ case CEXPR_H1L2:
+ l1 = &(scontext->range.level[1]);
+ l2 = &(tcontext->range.level[0]);
+ goto mls_ops;
+ case CEXPR_H1H2:
+ l1 = &(scontext->range.level[1]);
+ l2 = &(tcontext->range.level[1]);
+ goto mls_ops;
+ case CEXPR_L1H1:
+ l1 = &(scontext->range.level[0]);
+ l2 = &(scontext->range.level[1]);
+ goto mls_ops;
+ case CEXPR_L2H2:
+ l1 = &(tcontext->range.level[0]);
+ l2 = &(tcontext->range.level[1]);
+ goto mls_ops;
+mls_ops:
+ switch (e->op) {
+ case CEXPR_EQ:
+ s[++sp] = mls_level_eq(l1, l2);
+ continue;
+ case CEXPR_NEQ:
+ s[++sp] = !mls_level_eq(l1, l2);
+ continue;
+ case CEXPR_DOM:
+ s[++sp] = mls_level_dom(l1, l2);
+ continue;
+ case CEXPR_DOMBY:
+ s[++sp] = mls_level_dom(l2, l1);
+ continue;
+ case CEXPR_INCOMP:
+ s[++sp] = mls_level_incomp(l2, l1);
+ continue;
+ default:
+ BUG();
+ return 0;
+ }
+ break;
default:
BUG();
return 0;
@@ -155,6 +213,13 @@ static int constraint_expr_eval(struct context *scontext,
c = scontext;
if (e->attr & CEXPR_TARGET)
c = tcontext;
+ else if (e->attr & CEXPR_XTARGET) {
+ c = xcontext;
+ if (!c) {
+ BUG();
+ return 0;
+ }
+ }
if (e->attr & CEXPR_USER)
val1 = c->user;
else if (e->attr & CEXPR_ROLE)
@@ -252,17 +317,13 @@ static int context_struct_compute_av(struct context *scontext,
cond_compute_av(&policydb.te_cond_avtab, &avkey, avd);
/*
- * Remove any permissions prohibited by the MLS policy.
- */
- mls_compute_av(scontext, tcontext, tclass_datum, &avd->allowed);
-
- /*
- * Remove any permissions prohibited by a constraint.
+ * Remove any permissions prohibited by a constraint (this includes
+ * the MLS policy).
*/
constraint = tclass_datum->constraints;
while (constraint) {
if ((constraint->permissions & (avd->allowed)) &&
- !constraint_expr_eval(scontext, tcontext,
+ !constraint_expr_eval(scontext, tcontext, NULL,
constraint->expr)) {
avd->allowed = (avd->allowed) & ~(constraint->permissions);
}
@@ -290,6 +351,108 @@ static int context_struct_compute_av(struct context *scontext,
return 0;
}
+static int security_validtrans_handle_fail(struct context *ocontext,
+ struct context *ncontext,
+ struct context *tcontext,
+ u16 tclass)
+{
+ char *o = NULL, *n = NULL, *t = NULL;
+ u32 olen, nlen, tlen;
+
+ if (context_struct_to_string(ocontext, &o, &olen) < 0)
+ goto out;
+ if (context_struct_to_string(ncontext, &n, &nlen) < 0)
+ goto out;
+ if (context_struct_to_string(tcontext, &t, &tlen) < 0)
+ goto out;
+ audit_log(current->audit_context,
+ "security_validate_transition: denied for"
+ " oldcontext=%s newcontext=%s taskcontext=%s tclass=%s",
+ o, n, t, policydb.p_class_val_to_name[tclass-1]);
+out:
+ kfree(o);
+ kfree(n);
+ kfree(t);
+
+ if (!selinux_enforcing)
+ return 0;
+ return -EPERM;
+}
+
+int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid,
+ u16 tclass)
+{
+ struct context *ocontext;
+ struct context *ncontext;
+ struct context *tcontext;
+ struct class_datum *tclass_datum;
+ struct constraint_node *constraint;
+ int rc = 0;
+
+ if (!ss_initialized)
+ return 0;
+
+ POLICY_RDLOCK;
+
+ /*
+ * Remap extended Netlink classes for old policy versions.
+ * Do this here rather than socket_type_to_security_class()
+ * in case a newer policy version is loaded, allowing sockets
+ * to remain in the correct class.
+ */
+ if (policydb_loaded_version < POLICYDB_VERSION_NLCLASS)
+ if (tclass >= SECCLASS_NETLINK_ROUTE_SOCKET &&
+ tclass <= SECCLASS_NETLINK_DNRT_SOCKET)
+ tclass = SECCLASS_NETLINK_SOCKET;
+
+ if (!tclass || tclass > policydb.p_classes.nprim) {
+ printk(KERN_ERR "security_validate_transition: "
+ "unrecognized class %d\n", tclass);
+ rc = -EINVAL;
+ goto out;
+ }
+ tclass_datum = policydb.class_val_to_struct[tclass - 1];
+
+ ocontext = sidtab_search(&sidtab, oldsid);
+ if (!ocontext) {
+ printk(KERN_ERR "security_validate_transition: "
+ " unrecognized SID %d\n", oldsid);
+ rc = -EINVAL;
+ goto out;
+ }
+
+ ncontext = sidtab_search(&sidtab, newsid);
+ if (!ncontext) {
+ printk(KERN_ERR "security_validate_transition: "
+ " unrecognized SID %d\n", newsid);
+ rc = -EINVAL;
+ goto out;
+ }
+
+ tcontext = sidtab_search(&sidtab, tasksid);
+ if (!tcontext) {
+ printk(KERN_ERR "security_validate_transition: "
+ " unrecognized SID %d\n", tasksid);
+ rc = -EINVAL;
+ goto out;
+ }
+
+ constraint = tclass_datum->validatetrans;
+ while (constraint) {
+ if (!constraint_expr_eval(ocontext, ncontext, tcontext,
+ constraint->expr)) {
+ rc = security_validtrans_handle_fail(ocontext, ncontext,
+ tcontext, tclass);
+ goto out;
+ }
+ constraint = constraint->next;
+ }
+
+out:
+ POLICY_RDUNLOCK;
+ return rc;
+}
+
/**
* security_compute_av - Compute access vector decisions.
* @ssid: source security identifier
@@ -352,7 +515,7 @@ out:
* to point to this string and set `*scontext_len' to
* the length of the string.
*/
-int context_struct_to_string(struct context *context, char **scontext, u32 *scontext_len)
+static int context_struct_to_string(struct context *context, char **scontext, u32 *scontext_len)
{
char *scontextp;
@@ -366,7 +529,7 @@ int context_struct_to_string(struct context *context, char **scontext, u32 *scon
*scontext_len += mls_compute_context_len(context);
/* Allocate space for the context; caller must free this space. */
- scontextp = kmalloc(*scontext_len+1,GFP_ATOMIC);
+ scontextp = kmalloc(*scontext_len, GFP_ATOMIC);
if (!scontextp) {
return -ENOMEM;
}
@@ -375,17 +538,16 @@ int context_struct_to_string(struct context *context, char **scontext, u32 *scon
/*
* Copy the user name, role name and type name into the context.
*/
- sprintf(scontextp, "%s:%s:%s:",
+ sprintf(scontextp, "%s:%s:%s",
policydb.p_user_val_to_name[context->user - 1],
policydb.p_role_val_to_name[context->role - 1],
policydb.p_type_val_to_name[context->type - 1]);
scontextp += strlen(policydb.p_user_val_to_name[context->user - 1]) +
1 + strlen(policydb.p_role_val_to_name[context->role - 1]) +
- 1 + strlen(policydb.p_type_val_to_name[context->type - 1]) + 1;
+ 1 + strlen(policydb.p_type_val_to_name[context->type - 1]);
mls_sid_to_context(context, &scontextp);
- scontextp--;
*scontextp = 0;
return 0;
@@ -715,23 +877,8 @@ static int security_compute_sid(u32 ssid,
}
}
}
-
- if (!type_change && !roletr) {
- /* No change in process role or type. */
- *out_sid = ssid;
- goto out_unlock;
-
- }
break;
default:
- if (!type_change &&
- (newcontext.user == tcontext->user) &&
- mls_context_cmp(scontext, tcontext)) {
- /* No change in object type, owner,
- or MLS attributes. */
- *out_sid = tsid;
- goto out_unlock;
- }
break;
}
@@ -1363,36 +1510,37 @@ int security_get_user_sids(u32 fromsid,
if (!ebitmap_get_bit(&role->types, j))
continue;
usercon.type = j+1;
- mls_for_user_ranges(user,usercon) {
- rc = context_struct_compute_av(fromcon, &usercon,
- SECCLASS_PROCESS,
- PROCESS__TRANSITION,
- &avd);
- if (rc || !(avd.allowed & PROCESS__TRANSITION))
- continue;
- rc = sidtab_context_to_sid(&sidtab, &usercon, &sid);
- if (rc) {
+
+ if (mls_setup_user_range(fromcon, user, &usercon))
+ continue;
+
+ rc = context_struct_compute_av(fromcon, &usercon,
+ SECCLASS_PROCESS,
+ PROCESS__TRANSITION,
+ &avd);
+ if (rc || !(avd.allowed & PROCESS__TRANSITION))
+ continue;
+ rc = sidtab_context_to_sid(&sidtab, &usercon, &sid);
+ if (rc) {
+ kfree(mysids);
+ goto out_unlock;
+ }
+ if (mynel < maxnel) {
+ mysids[mynel++] = sid;
+ } else {
+ maxnel += SIDS_NEL;
+ mysids2 = kmalloc(maxnel*sizeof(*mysids2), GFP_ATOMIC);
+ if (!mysids2) {
+ rc = -ENOMEM;
kfree(mysids);
goto out_unlock;
}
- if (mynel < maxnel) {
- mysids[mynel++] = sid;
- } else {
- maxnel += SIDS_NEL;
- mysids2 = kmalloc(maxnel*sizeof(*mysids2), GFP_ATOMIC);
- if (!mysids2) {
- rc = -ENOMEM;
- kfree(mysids);
- goto out_unlock;
- }
- memset(mysids2, 0, maxnel*sizeof(*mysids2));
- memcpy(mysids2, mysids, mynel * sizeof(*mysids2));
- kfree(mysids);
- mysids = mysids2;
- mysids[mynel++] = sid;
- }
+ memset(mysids2, 0, maxnel*sizeof(*mysids2));
+ memcpy(mysids2, mysids, mynel * sizeof(*mysids2));
+ kfree(mysids);
+ mysids = mysids2;
+ mysids[mynel++] = sid;
}
- mls_end_user_ranges;
}
}
diff --git a/security/selinux/ss/services.h b/security/selinux/ss/services.h
index c7030aee83d33..e8d907e903cdb 100644
--- a/security/selinux/ss/services.h
+++ b/security/selinux/ss/services.h
@@ -9,12 +9,6 @@
#include "policydb.h"
#include "sidtab.h"
-/*
- * The security server uses two global data structures
- * when providing its services: the SID table (sidtab)
- * and the policy database (policydb).
- */
-extern struct sidtab sidtab;
extern struct policydb policydb;
#endif /* _SS_SERVICES_H_ */
diff --git a/security/selinux/ss/sidtab.c b/security/selinux/ss/sidtab.c
index 77d000246f137..871c33bd07413 100644
--- a/security/selinux/ss/sidtab.c
+++ b/security/selinux/ss/sidtab.c
@@ -87,42 +87,6 @@ out:
return rc;
}
-int sidtab_remove(struct sidtab *s, u32 sid)
-{
- int hvalue, rc = 0;
- struct sidtab_node *cur, *last;
-
- if (!s) {
- rc = -ENOENT;
- goto out;
- }
-
- hvalue = SIDTAB_HASH(sid);
- last = NULL;
- cur = s->htable[hvalue];
- while (cur != NULL && sid > cur->sid) {
- last = cur;
- cur = cur->next;
- }
-
- if (cur == NULL || sid != cur->sid) {
- rc = -ENOENT;
- goto out;
- }
-
- if (last == NULL)
- s->htable[hvalue] = cur->next;
- else
- last->next = cur->next;
-
- context_destroy(&cur->context);
-
- kfree(cur);
- s->nel--;
-out:
- return rc;
-}
-
struct context *sidtab_search(struct sidtab *s, u32 sid)
{
int hvalue;
diff --git a/sound/arm/sa11xx-uda1341.c b/sound/arm/sa11xx-uda1341.c
index 21103c7aed5aa..174bc032d1ad5 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.19 2004/12/15 15:26:10 tiwai Exp $ */
+/* $Id: sa11xx-uda1341.c,v 1.21 2005/01/28 19:34:04 tiwai Exp $ */
/***************************************************************************************************
*
@@ -862,7 +862,7 @@ 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, unsigned int state)
+static int snd_sa11xx_uda1341_suspend(snd_card_t *card, pm_message_t state)
{
sa11xx_uda1341_t *chip = card->pm_private_data;
@@ -878,7 +878,7 @@ static int snd_sa11xx_uda1341_suspend(snd_card_t *card, unsigned int state)
return 0;
}
-static int snd_sa11xx_uda1341_resume(snd_card_t *card, unsigned int state)
+static int snd_sa11xx_uda1341_resume(snd_card_t *card)
{
sa11xx_uda1341_t *chip = card->pm_private_data;
@@ -938,7 +938,7 @@ static int __init sa11xx_uda1341_init(void)
if ((err = snd_card_sa11xx_uda1341_pcm(sa11xx_uda1341, 0)) < 0)
goto nodev;
- snd_card_set_dev_pm_callback(card, PM_SYS_DEV,
+ snd_card_set_generic_pm_callback(card,
snd_sa11xx_uda1341_suspend, snd_sa11_uda1341_resume,
sa11xx_uda1341);
diff --git a/sound/core/Kconfig b/sound/core/Kconfig
index e0dd38a084423..d1e800b9866df 100644
--- a/sound/core/Kconfig
+++ b/sound/core/Kconfig
@@ -1,16 +1,20 @@
# ALSA soundcard-configuration
config SND_TIMER
tristate
+ depends on SND
config SND_PCM
tristate
select SND_TIMER
+ depends on SND
config SND_HWDEP
tristate
+ depends on SND
config SND_RAWMIDI
tristate
+ depends on SND
config SND_SEQUENCER
tristate "Sequencer support"
@@ -40,6 +44,7 @@ config SND_SEQ_DUMMY
config SND_OSSEMUL
bool
+ depends on SND
config SND_MIXER_OSS
tristate "OSS Mixer API"
@@ -70,7 +75,7 @@ config SND_PCM_OSS
config SND_SEQUENCER_OSS
bool "OSS Sequencer API"
- depends on SND_SEQUENCER
+ depends on SND && SND_SEQUENCER
select SND_OSSEMUL
help
Say Y here to enable OSS sequencer emulation (both
@@ -81,20 +86,6 @@ config SND_SEQUENCER_OSS
To compile this driver as a module, choose M here: the module
will be called snd-seq-oss.
-config SND_BIT32_EMUL
- tristate "Emulation for 32-bit applications"
- depends on SND && COMPAT
- select SND_PCM
- select SND_RAWMIDI
- select SND_TIMER
- select SND_HWDEP
- help
- Say Y here to enable the emulation for 32-bit ALSA-native
- applications.
-
- To compile this driver as a module, choose M here: the module
- will be called snd-ioctl32.
-
config SND_RTCTIMER
tristate "RTC Timer support"
depends on SND && RTC
@@ -137,3 +128,6 @@ config SND_DEBUG_DETECT
Say Y here to enable extra-verbose log messages printed when
detecting devices.
+config SND_GENERIC_PM
+ bool
+ depends on SND
diff --git a/sound/core/Makefile b/sound/core/Makefile
index 37e2fe6f4eda6..764ac184b2232 100644
--- a/sound/core/Makefile
+++ b/sound/core/Makefile
@@ -31,4 +31,3 @@ obj-$(CONFIG_SND_RAWMIDI) += snd-rawmidi.o
obj-$(CONFIG_SND_OSSEMUL) += oss/
obj-$(CONFIG_SND_SEQUENCER) += seq/
-obj-$(CONFIG_SND_BIT32_EMUL) += ioctl32/
diff --git a/sound/core/control.c b/sound/core/control.c
index 91ecc3fbd3576..f4ea6bff1dd3b 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -43,6 +43,9 @@ typedef struct _snd_kctl_ioctl {
static DECLARE_RWSEM(snd_ioctl_rwsem);
static LIST_HEAD(snd_control_ioctls);
+#ifdef CONFIG_COMPAT
+static LIST_HEAD(snd_control_compat_ioctls);
+#endif
static int snd_ctl_open(struct inode *inode, struct file *file)
{
@@ -516,20 +519,25 @@ snd_kcontrol_t *snd_ctl_find_id(snd_card_t * card, snd_ctl_elem_id_t *id)
static int snd_ctl_card_info(snd_card_t * card, snd_ctl_file_t * ctl,
unsigned int cmd, void __user *arg)
{
- snd_ctl_card_info_t info;
+ snd_ctl_card_info_t *info;
- memset(&info, 0, sizeof(info));
+ info = kcalloc(1, sizeof(*info), GFP_KERNEL);
+ if (! info)
+ return -ENOMEM;
down_read(&snd_ioctl_rwsem);
- info.card = card->number;
- strlcpy(info.id, card->id, sizeof(info.id));
- strlcpy(info.driver, card->driver, sizeof(info.driver));
- strlcpy(info.name, card->shortname, sizeof(info.name));
- strlcpy(info.longname, card->longname, sizeof(info.longname));
- strlcpy(info.mixername, card->mixername, sizeof(info.mixername));
- strlcpy(info.components, card->components, sizeof(info.components));
+ info->card = card->number;
+ strlcpy(info->id, card->id, sizeof(info->id));
+ strlcpy(info->driver, card->driver, sizeof(info->driver));
+ strlcpy(info->name, card->shortname, sizeof(info->name));
+ strlcpy(info->longname, card->longname, sizeof(info->longname));
+ 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(snd_ctl_card_info_t))) {
+ kfree(info);
return -EFAULT;
+ }
+ kfree(info);
return 0;
}
@@ -595,43 +603,51 @@ 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 __user *_info)
+static int snd_ctl_elem_info(snd_ctl_file_t *ctl, snd_ctl_elem_info_t *info)
{
snd_card_t *card = ctl->card;
- snd_ctl_elem_info_t info;
snd_kcontrol_t *kctl;
snd_kcontrol_volatile_t *vd;
unsigned int index_offset;
int result;
- if (copy_from_user(&info, _info, sizeof(info)))
- return -EFAULT;
down_read(&card->controls_rwsem);
- kctl = snd_ctl_find_id(card, &info.id);
+ kctl = snd_ctl_find_id(card, &info->id);
if (kctl == NULL) {
up_read(&card->controls_rwsem);
return -ENOENT;
}
#ifdef CONFIG_SND_DEBUG
- info.access = 0;
+ info->access = 0;
#endif
- result = kctl->info(kctl, &info);
+ result = kctl->info(kctl, info);
if (result >= 0) {
- snd_assert(info.access == 0, );
- index_offset = snd_ctl_get_ioff(kctl, &info.id);
+ snd_assert(info->access == 0, );
+ index_offset = snd_ctl_get_ioff(kctl, &info->id);
vd = &kctl->vd[index_offset];
- snd_ctl_build_ioff(&info.id, kctl, index_offset);
- info.access = vd->access;
+ snd_ctl_build_ioff(&info->id, kctl, index_offset);
+ info->access = vd->access;
if (vd->owner) {
- info.access |= SNDRV_CTL_ELEM_ACCESS_LOCK;
+ info->access |= SNDRV_CTL_ELEM_ACCESS_LOCK;
if (vd->owner == ctl)
- info.access |= SNDRV_CTL_ELEM_ACCESS_OWNER;
- info.owner = vd->owner_pid;
+ info->access |= SNDRV_CTL_ELEM_ACCESS_OWNER;
+ info->owner = vd->owner_pid;
} else {
- info.owner = -1;
+ info->owner = -1;
}
}
up_read(&card->controls_rwsem);
+ return result;
+}
+
+static int snd_ctl_elem_info_user(snd_ctl_file_t *ctl, snd_ctl_elem_info_t __user *_info)
+{
+ snd_ctl_elem_info_t info;
+ int result;
+
+ if (copy_from_user(&info, _info, sizeof(info)))
+ return -EFAULT;
+ result = snd_ctl_elem_info(ctl, &info);
if (result >= 0)
if (copy_to_user(_info, &info, sizeof(info)))
return -EFAULT;
@@ -816,14 +832,6 @@ static int snd_ctl_elem_user_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
struct user_element *ue = kcontrol->private_data;
*uinfo = ue->info;
- if (ue->info.type == SNDRV_CTL_ELEM_TYPE_ENUMERATED) {
- uinfo->value.enumerated.items = ue->info.value.enumerated.items;
- if (uinfo->value.enumerated.item >= ue->info.value.enumerated.items)
- uinfo->value.enumerated.item = 0;
- strlcpy(uinfo->value.enumerated.name,
- (char *)ue->priv_data + uinfo->value.enumerated.item * 64,
- 64);
- }
return 0;
}
@@ -851,28 +859,25 @@ static void snd_ctl_elem_user_free(snd_kcontrol_t * kcontrol)
kfree(kcontrol->private_data);
}
-static int snd_ctl_elem_add(snd_ctl_file_t *file, snd_ctl_elem_info_t __user *_info, int replace)
+static int snd_ctl_elem_add(snd_ctl_file_t *file, snd_ctl_elem_info_t *info, int replace)
{
snd_card_t *card = file->card;
- snd_ctl_elem_info_t info;
snd_kcontrol_t kctl, *_kctl;
unsigned int access;
- long private_size, extra_size;
+ long private_size;
struct user_element *ue;
int idx, err;
if (card->user_ctl_count >= MAX_USER_CONTROLS)
return -ENOMEM;
- if (copy_from_user(&info, _info, sizeof(info)))
- return -EFAULT;
- if (info.count > 1024)
+ 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.id.numid = 0;
+ access = info->access == 0 ? SNDRV_CTL_ELEM_ACCESS_READWRITE :
+ (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);
- _kctl = snd_ctl_find_id(card, &info.id);
+ _kctl = snd_ctl_find_id(card, &info->id);
err = 0;
if (_kctl) {
if (replace)
@@ -886,67 +891,50 @@ static int snd_ctl_elem_add(snd_ctl_file_t *file, snd_ctl_elem_info_t __user *_i
up_write(&card->controls_rwsem);
if (err < 0)
return err;
- memcpy(&kctl.id, &info.id, sizeof(info.id));
- kctl.count = info.owner ? info.owner : 1;
+ memcpy(&kctl.id, &info->id, sizeof(info->id));
+ kctl.count = info->owner ? info->owner : 1;
access |= SNDRV_CTL_ELEM_ACCESS_USER;
kctl.info = snd_ctl_elem_user_info;
if (access & SNDRV_CTL_ELEM_ACCESS_READ)
kctl.get = snd_ctl_elem_user_get;
if (access & SNDRV_CTL_ELEM_ACCESS_WRITE)
kctl.put = snd_ctl_elem_user_put;
- extra_size = 0;
- switch (info.type) {
+ switch (info->type) {
case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
private_size = sizeof(char);
- if (info.count > 128)
+ if (info->count > 128)
return -EINVAL;
break;
case SNDRV_CTL_ELEM_TYPE_INTEGER:
private_size = sizeof(long);
- if (info.count > 128)
+ if (info->count > 128)
return -EINVAL;
break;
case SNDRV_CTL_ELEM_TYPE_INTEGER64:
private_size = sizeof(long long);
- if (info.count > 64)
+ if (info->count > 64)
return -EINVAL;
break;
- case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
- private_size = sizeof(unsigned int);
- if (info.count > 128)
- return -EINVAL;
- if (info.value.enumerated.items > 128)
- return -EINVAL;
- extra_size = info.value.enumerated.items * 64;
- break;
case SNDRV_CTL_ELEM_TYPE_BYTES:
private_size = sizeof(unsigned char);
- if (info.count > 512)
+ if (info->count > 512)
return -EINVAL;
break;
case SNDRV_CTL_ELEM_TYPE_IEC958:
private_size = sizeof(struct sndrv_aes_iec958);
- if (info.count != 1)
+ if (info->count != 1)
return -EINVAL;
break;
default:
return -EINVAL;
}
- private_size *= info.count;
- ue = kcalloc(1, sizeof(struct user_element) + private_size + extra_size, GFP_KERNEL);
+ private_size *= info->count;
+ ue = kcalloc(1, sizeof(struct user_element) + private_size, GFP_KERNEL);
if (ue == NULL)
return -ENOMEM;
- ue->info = info;
- ue->elem_data = (char *)ue + sizeof(ue);
+ ue->info = *info;
+ ue->elem_data = (char *)ue + sizeof(*ue);
ue->elem_data_size = private_size;
- if (extra_size) {
- ue->priv_data = (char *)ue + sizeof(ue) + private_size;
- ue->priv_data_size = extra_size;
- if (ue->info.type == SNDRV_CTL_ELEM_TYPE_ENUMERATED) {
- if (copy_from_user(ue->priv_data, *(char __user **)info.value.enumerated.name, extra_size))
- return -EFAULT;
- }
- }
kctl.private_free = snd_ctl_elem_user_free;
_kctl = snd_ctl_new(&kctl, access);
if (_kctl == NULL) {
@@ -969,6 +957,14 @@ static int snd_ctl_elem_add(snd_ctl_file_t *file, snd_ctl_elem_info_t __user *_i
return 0;
}
+static int snd_ctl_elem_add_user(snd_ctl_file_t *file, snd_ctl_elem_info_t __user *_info, int replace)
+{
+ snd_ctl_elem_info_t 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)
{
snd_ctl_elem_id_t id;
@@ -1016,15 +1012,13 @@ 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) {
- /* FIXME: pass the correct state value */
- card->pm_resume(card, 0);
+ card->pm_resume(card);
snd_power_change_state(card, power_state);
}
break;
case SNDRV_CTL_POWER_D3hot:
if (card->power_state != power_state) {
- /* FIXME: pass the correct state value */
- card->pm_suspend(card, 0);
+ card->pm_suspend(card, PMSG_SUSPEND);
snd_power_change_state(card, power_state);
}
break;
@@ -1039,8 +1033,7 @@ static int snd_ctl_set_power_state(snd_card_t *card, unsigned int power_state)
}
#endif
-static inline int _snd_ctl_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
+static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
snd_ctl_file_t *ctl;
snd_card_t *card;
@@ -1061,7 +1054,7 @@ static inline int _snd_ctl_ioctl(struct inode *inode, struct file *file,
case SNDRV_CTL_IOCTL_ELEM_LIST:
return snd_ctl_elem_list(ctl->card, argp);
case SNDRV_CTL_IOCTL_ELEM_INFO:
- return snd_ctl_elem_info(ctl, argp);
+ return snd_ctl_elem_info_user(ctl, argp);
case SNDRV_CTL_IOCTL_ELEM_READ:
return snd_ctl_elem_read_user(ctl->card, argp);
case SNDRV_CTL_IOCTL_ELEM_WRITE:
@@ -1071,9 +1064,9 @@ static inline int _snd_ctl_ioctl(struct inode *inode, struct file *file,
case SNDRV_CTL_IOCTL_ELEM_UNLOCK:
return snd_ctl_elem_unlock(ctl, argp);
case SNDRV_CTL_IOCTL_ELEM_ADD:
- return snd_ctl_elem_add(ctl, argp, 0);
+ return snd_ctl_elem_add_user(ctl, argp, 0);
case SNDRV_CTL_IOCTL_ELEM_REPLACE:
- return snd_ctl_elem_add(ctl, argp, 1);
+ return snd_ctl_elem_add_user(ctl, argp, 1);
case SNDRV_CTL_IOCTL_ELEM_REMOVE:
return snd_ctl_elem_remove(ctl, argp);
case SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS:
@@ -1113,17 +1106,6 @@ static inline int _snd_ctl_ioctl(struct inode *inode, struct file *file,
return -ENOTTY;
}
-/* FIXME: need to unlock BKL to allow preemption */
-static int snd_ctl_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- int err;
- unlock_kernel();
- err = _snd_ctl_ioctl(inode, file, cmd, arg);
- lock_kernel();
- return err;
-}
-
static ssize_t snd_ctl_read(struct file *file, char __user *buffer, size_t count, loff_t * offset)
{
snd_ctl_file_t *ctl;
@@ -1199,7 +1181,7 @@ static unsigned int snd_ctl_poll(struct file *file, poll_table * wait)
* register the device-specific control-ioctls.
* called from each device manager like pcm.c, hwdep.c, etc.
*/
-int snd_ctl_register_ioctl(snd_kctl_ioctl_func_t fcn)
+static int _snd_ctl_register_ioctl(snd_kctl_ioctl_func_t fcn, struct list_head *lists)
{
snd_kctl_ioctl_t *pn;
@@ -1208,22 +1190,34 @@ int snd_ctl_register_ioctl(snd_kctl_ioctl_func_t fcn)
return -ENOMEM;
pn->fioctl = fcn;
down_write(&snd_ioctl_rwsem);
- list_add_tail(&pn->list, &snd_control_ioctls);
+ list_add_tail(&pn->list, lists);
up_write(&snd_ioctl_rwsem);
return 0;
}
+int snd_ctl_register_ioctl(snd_kctl_ioctl_func_t fcn)
+{
+ return _snd_ctl_register_ioctl(fcn, &snd_control_ioctls);
+}
+
+#ifdef CONFIG_COMPAT
+int snd_ctl_register_ioctl_compat(snd_kctl_ioctl_func_t fcn)
+{
+ return _snd_ctl_register_ioctl(fcn, &snd_control_compat_ioctls);
+}
+#endif
+
/*
* de-register the device-specific control-ioctls.
*/
-int snd_ctl_unregister_ioctl(snd_kctl_ioctl_func_t fcn)
+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;
snd_runtime_check(fcn != NULL, return -EINVAL);
down_write(&snd_ioctl_rwsem);
- list_for_each(list, &snd_control_ioctls) {
+ list_for_each(list, lists) {
p = list_entry(list, snd_kctl_ioctl_t, list);
if (p->fioctl == fcn) {
list_del(&p->list);
@@ -1237,6 +1231,19 @@ int snd_ctl_unregister_ioctl(snd_kctl_ioctl_func_t fcn)
return -EINVAL;
}
+int snd_ctl_unregister_ioctl(snd_kctl_ioctl_func_t fcn)
+{
+ return _snd_ctl_unregister_ioctl(fcn, &snd_control_ioctls);
+}
+
+#ifdef CONFIG_COMPAT
+int snd_ctl_unregister_ioctl_compat(snd_kctl_ioctl_func_t fcn)
+{
+ return _snd_ctl_unregister_ioctl(fcn, &snd_control_compat_ioctls);
+}
+
+#endif
+
static int snd_ctl_fasync(int fd, struct file * file, int on)
{
snd_ctl_file_t *ctl;
@@ -1249,6 +1256,15 @@ static int snd_ctl_fasync(int fd, struct file * file, int on)
}
/*
+ * ioctl32 compat
+ */
+#ifdef CONFIG_COMPAT
+#include "control_compat.c"
+#else
+#define snd_ctl_ioctl_compat NULL
+#endif
+
+/*
* INIT PART
*/
@@ -1259,7 +1275,8 @@ static struct file_operations snd_ctl_f_ops =
.open = snd_ctl_open,
.release = snd_ctl_release,
.poll = snd_ctl_poll,
- .ioctl = snd_ctl_ioctl,
+ .unlocked_ioctl = snd_ctl_ioctl,
+ .compat_ioctl = snd_ctl_ioctl_compat,
.fasync = snd_ctl_fasync,
};
diff --git a/sound/core/control_compat.c b/sound/core/control_compat.c
new file mode 100644
index 0000000000000..7fdabea4bfc8b
--- /dev/null
+++ b/sound/core/control_compat.c
@@ -0,0 +1,412 @@
+/*
+ * compat ioctls for control API
+ *
+ * Copyright (c) by Takashi Iwai <tiwai@suse.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/* this file included from control.c */
+
+#include <linux/compat.h>
+
+struct sndrv_ctl_elem_list32 {
+ u32 offset;
+ u32 space;
+ u32 used;
+ u32 count;
+ u32 pids;
+ 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)
+{
+ struct sndrv_ctl_elem_list __user *data;
+ compat_caddr_t ptr;
+ int err;
+
+ data = compat_alloc_user_space(sizeof(*data));
+
+ /* offset, space, used, count */
+ if (copy_in_user(data, data32, 4 * sizeof(u32)))
+ return -EFAULT;
+ /* pids */
+ if (get_user(ptr, &data32->pids) ||
+ put_user(compat_ptr(ptr), &data->pids))
+ return -EFAULT;
+ err = snd_ctl_elem_list(card, data);
+ if (err < 0)
+ return err;
+ /* copy the result */
+ if (copy_in_user(data32, data, 4 * sizeof(u32)))
+ return -EFAULT;
+ return 0;
+}
+
+/*
+ * control element info
+ * 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
+ s32 type;
+ u32 access;
+ u32 count;
+ s32 owner;
+ union {
+ struct {
+ s32 min;
+ s32 max;
+ s32 step;
+ } integer;
+ struct {
+ u64 min;
+ u64 max;
+ u64 step;
+ } integer64;
+ struct {
+ u32 items;
+ u32 item;
+ char name[64];
+ } enumerated;
+ unsigned char reserved[128];
+ } value;
+ 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)
+{
+ struct sndrv_ctl_elem_info *data;
+ int err;
+
+ data = kcalloc(1, sizeof(*data), GFP_KERNEL);
+ if (! data)
+ return -ENOMEM;
+
+ err = -EFAULT;
+ /* copy id */
+ if (copy_from_user(&data->id, &data32->id, sizeof(data->id)))
+ goto error;
+ /* we need to copy the item index.
+ * hope this doesn't break anything..
+ */
+ if (get_user(data->value.enumerated.item, &data32->value.enumerated.item))
+ goto error;
+ err = snd_ctl_elem_info(ctl, data);
+ if (err < 0)
+ goto error;
+ /* restore info to 32bit */
+ err = -EFAULT;
+ /* id, type, access, count */
+ if (copy_to_user(&data32->id, &data->id, sizeof(data->id)) ||
+ copy_to_user(&data32->type, &data->type, 3 * sizeof(u32)))
+ goto error;
+ if (put_user(data->owner, &data32->owner))
+ goto error;
+ switch (data->type) {
+ case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
+ case SNDRV_CTL_ELEM_TYPE_INTEGER:
+ if (put_user(data->value.integer.min, &data32->value.integer.min) ||
+ put_user(data->value.integer.max, &data32->value.integer.max) ||
+ put_user(data->value.integer.step, &data32->value.integer.step))
+ goto error;
+ break;
+ case SNDRV_CTL_ELEM_TYPE_INTEGER64:
+ if (copy_to_user(&data32->value.integer64,
+ &data->value.integer64,
+ sizeof(data->value.integer64)))
+ goto error;
+ break;
+ case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
+ if (copy_to_user(&data32->value.enumerated,
+ &data->value.enumerated,
+ sizeof(data->value.enumerated)))
+ goto error;
+ break;
+ default:
+ break;
+ }
+ err = 0;
+ error:
+ kfree(data);
+ return err;
+}
+
+/* read / write */
+struct sndrv_ctl_elem_value32 {
+ struct sndrv_ctl_elem_id id;
+ unsigned int indirect; /* bit-field causes misalignment */
+ union {
+ s32 integer[128];
+ unsigned char data[512];
+#ifndef CONFIG_X86_64
+ s64 integer64[64];
+#endif
+ } value;
+ unsigned char reserved[128];
+};
+
+
+/* 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)
+{
+ snd_kcontrol_t *kctl;
+ snd_ctl_elem_info_t info;
+ int err;
+
+ down_read(&card->controls_rwsem);
+ kctl = snd_ctl_find_id(card, id);
+ if (! kctl) {
+ up_read(&card->controls_rwsem);
+ return -ENXIO;
+ }
+ info.id = *id;
+ err = kctl->info(kctl, &info);
+ up_read(&card->controls_rwsem);
+ if (err >= 0) {
+ err = info.type;
+ *countp = info.count;
+ }
+ return err;
+}
+
+static int get_elem_size(int type, int count)
+{
+ switch (type) {
+ case SNDRV_CTL_ELEM_TYPE_INTEGER64:
+ return sizeof(s64) * count;
+ case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
+ return sizeof(int) * count;
+ case SNDRV_CTL_ELEM_TYPE_BYTES:
+ return 512;
+ case SNDRV_CTL_ELEM_TYPE_IEC958:
+ return sizeof(struct sndrv_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,
+ int *typep, int *countp)
+{
+ int i, type, count, size;
+ unsigned int indirect;
+
+ if (copy_from_user(&data->id, &data32->id, sizeof(data->id)))
+ return -EFAULT;
+ if (get_user(indirect, &data32->indirect))
+ return -EFAULT;
+ if (indirect)
+ return -EINVAL;
+ type = get_ctl_type(card, &data->id, &count);
+ if (type < 0)
+ return type;
+
+ if (type == SNDRV_CTL_ELEM_TYPE_BOOLEAN ||
+ type == SNDRV_CTL_ELEM_TYPE_INTEGER) {
+ for (i = 0; i < count; i++) {
+ int val;
+ if (get_user(val, &data32->value.integer[i]))
+ return -EFAULT;
+ data->value.integer.value[i] = val;
+ }
+ } else {
+ size = get_elem_size(type, count);
+ if (size < 0) {
+ printk(KERN_ERR "snd_ioctl32_ctl_elem_value: unknown type %d\n", type);
+ return -EINVAL;
+ }
+ if (copy_from_user(data->value.bytes.data,
+ data32->value.data, size))
+ return -EFAULT;
+ }
+
+ *typep = type;
+ *countp = count;
+ return 0;
+}
+
+/* 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,
+ int type, int count)
+{
+ int i, size;
+
+ if (type == SNDRV_CTL_ELEM_TYPE_BOOLEAN ||
+ type == SNDRV_CTL_ELEM_TYPE_INTEGER) {
+ for (i = 0; i < count; i++) {
+ int val;
+ val = data->value.integer.value[i];
+ if (put_user(val, &data32->value.integer[i]))
+ return -EFAULT;
+ }
+ } else {
+ size = get_elem_size(type, count);
+ if (copy_to_user(data32->value.data,
+ data->value.bytes.data, size))
+ return -EFAULT;
+ }
+ return 0;
+}
+
+static int snd_ctl_elem_read_user_compat(snd_card_t *card,
+ struct sndrv_ctl_elem_value32 __user *data32)
+{
+ struct sndrv_ctl_elem_value *data;
+ int err, type, count;
+
+ data = kcalloc(1, sizeof(*data), GFP_KERNEL);
+ if (data == NULL)
+ return -ENOMEM;
+
+ if ((err = copy_ctl_value_from_user(card, data, data32, &type, &count)) < 0)
+ goto error;
+ if ((err = snd_ctl_elem_read(card, data)) < 0)
+ goto error;
+ err = copy_ctl_value_to_user(data32, data, type, count);
+ error:
+ kfree(data);
+ return err;
+}
+
+static int snd_ctl_elem_write_user_compat(snd_ctl_file_t *file,
+ struct sndrv_ctl_elem_value32 __user *data32)
+{
+ struct sndrv_ctl_elem_value *data;
+ int err, type, count;
+
+ data = kcalloc(1, sizeof(*data), GFP_KERNEL);
+ if (data == NULL)
+ return -ENOMEM;
+
+ if ((err = copy_ctl_value_from_user(file->card, data, data32, &type, &count)) < 0)
+ goto error;
+ if ((err = snd_ctl_elem_write(file->card, file, data)) < 0)
+ goto error;
+ err = copy_ctl_value_to_user(data32, data, type, count);
+ error:
+ kfree(data);
+ return err;
+}
+
+/* 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,
+ int replace)
+{
+ struct sndrv_ctl_elem_info *data;
+ int err;
+
+ data = kcalloc(1, sizeof(*data), GFP_KERNEL);
+ if (! data)
+ return -ENOMEM;
+
+ err = -EFAULT;
+ /* id, type, access, count */ \
+ if (copy_from_user(&data->id, &data32->id, sizeof(data->id)) ||
+ copy_from_user(&data->type, &data32->type, 3 * sizeof(u32)))
+ goto error;
+ if (get_user(data->owner, &data32->owner) ||
+ get_user(data->type, &data32->type))
+ goto error;
+ switch (data->type) {
+ case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
+ case SNDRV_CTL_ELEM_TYPE_INTEGER:
+ if (get_user(data->value.integer.min, &data32->value.integer.min) ||
+ get_user(data->value.integer.max, &data32->value.integer.max) ||
+ get_user(data->value.integer.step, &data32->value.integer.step))
+ goto error;
+ break;
+ case SNDRV_CTL_ELEM_TYPE_INTEGER64:
+ if (copy_from_user(&data->value.integer64,
+ &data32->value.integer64,
+ sizeof(data->value.integer64)))
+ goto error;
+ break;
+ case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
+ if (copy_from_user(&data->value.enumerated,
+ &data32->value.enumerated,
+ sizeof(data->value.enumerated)))
+ goto error;
+ break;
+ default:
+ break;
+ }
+ err = snd_ctl_elem_add(file, data, replace);
+ error:
+ kfree(data);
+ return err;
+}
+
+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),
+};
+
+static inline long snd_ctl_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ snd_ctl_file_t *ctl;
+ struct list_head *list;
+ void __user *argp = compat_ptr(arg);
+ int err;
+
+ ctl = file->private_data;
+ snd_assert(ctl && ctl->card, return -ENXIO);
+
+ switch (cmd) {
+ case SNDRV_CTL_IOCTL_PVERSION:
+ case SNDRV_CTL_IOCTL_CARD_INFO:
+ case SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS:
+ case SNDRV_CTL_IOCTL_POWER:
+ case SNDRV_CTL_IOCTL_POWER_STATE:
+ case SNDRV_CTL_IOCTL_ELEM_LOCK:
+ case SNDRV_CTL_IOCTL_ELEM_UNLOCK:
+ return snd_ctl_ioctl(file, cmd, (unsigned long)argp);
+ case SNDRV_CTL_IOCTL_ELEM_LIST32:
+ return snd_ctl_elem_list_compat(ctl->card, argp);
+ case SNDRV_CTL_IOCTL_ELEM_INFO32:
+ return snd_ctl_elem_info_compat(ctl, argp);
+ case SNDRV_CTL_IOCTL_ELEM_READ32:
+ return snd_ctl_elem_read_user_compat(ctl->card, argp);
+ case SNDRV_CTL_IOCTL_ELEM_WRITE32:
+ return snd_ctl_elem_write_user_compat(ctl, argp);
+ case SNDRV_CTL_IOCTL_ELEM_ADD32:
+ return snd_ctl_elem_add_compat(ctl, argp, 0);
+ case SNDRV_CTL_IOCTL_ELEM_REPLACE32:
+ return snd_ctl_elem_add_compat(ctl, argp, 1);
+ }
+
+ 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);
+ if (p->fioctl) {
+ err = p->fioctl(ctl->card, ctl, cmd, arg);
+ if (err != -ENOIOCTLCMD) {
+ up_read(&snd_ioctl_rwsem);
+ return err;
+ }
+ }
+ }
+ up_read(&snd_ioctl_rwsem);
+ return -ENOIOCTLCMD;
+}
diff --git a/sound/core/hwdep.c b/sound/core/hwdep.c
index cbd8eba6a35ae..997dd41c584e6 100644
--- a/sound/core/hwdep.c
+++ b/sound/core/hwdep.c
@@ -223,7 +223,7 @@ static int snd_hwdep_dsp_load(snd_hwdep_t *hw, snd_hwdep_dsp_image_t __user *_in
/* check whether the dsp was already loaded */
if (hw->dsp_loaded & (1 << info.index))
return -EBUSY;
- if (verify_area(VERIFY_READ, info.image, info.length))
+ if (!access_ok(VERIFY_READ, info.image, info.length))
return -EFAULT;
err = hw->ops.dsp_load(hw, &info);
if (err < 0)
@@ -232,8 +232,7 @@ static int snd_hwdep_dsp_load(snd_hwdep_t *hw, snd_hwdep_dsp_image_t __user *_in
return 0;
}
-static inline int _snd_hwdep_ioctl(struct inode *inode, 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;
void __user *argp = (void __user *)arg;
@@ -252,17 +251,6 @@ static inline int _snd_hwdep_ioctl(struct inode *inode, struct file * file,
return -ENOTTY;
}
-/* FIXME: need to unlock BKL to allow preemption */
-static int snd_hwdep_ioctl(struct inode *inode, struct file * file,
- unsigned int cmd, unsigned long arg)
-{
- int err;
- unlock_kernel();
- err = _snd_hwdep_ioctl(inode, file, cmd, arg);
- lock_kernel();
- return err;
-}
-
static int snd_hwdep_mmap(struct file * file, struct vm_area_struct * vma)
{
snd_hwdep_t *hw = file->private_data;
@@ -315,6 +303,12 @@ static int snd_hwdep_control_ioctl(snd_card_t * card, snd_ctl_file_t * control,
return -ENOIOCTLCMD;
}
+#ifdef CONFIG_COMPAT
+#include "hwdep_compat.c"
+#else
+#define snd_hwdep_ioctl_compat NULL
+#endif
+
/*
*/
@@ -328,7 +322,8 @@ static struct file_operations snd_hwdep_f_ops =
.open = snd_hwdep_open,
.release = snd_hwdep_release,
.poll = snd_hwdep_poll,
- .ioctl = snd_hwdep_ioctl,
+ .unlocked_ioctl = snd_hwdep_ioctl,
+ .compat_ioctl = snd_hwdep_ioctl_compat,
.mmap = snd_hwdep_mmap,
};
@@ -509,12 +504,14 @@ static int __init alsa_hwdep_init(void)
}
snd_hwdep_proc_entry = entry;
snd_ctl_register_ioctl(snd_hwdep_control_ioctl);
+ snd_ctl_register_ioctl_compat(snd_hwdep_control_ioctl);
return 0;
}
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;
diff --git a/sound/core/ioctl32/hwdep32.c b/sound/core/hwdep_compat.c
index d3fd14c6a43fb..6866f423d4b9c 100644
--- a/sound/core/ioctl32/hwdep32.c
+++ b/sound/core/hwdep_compat.c
@@ -18,13 +18,9 @@
*
*/
-#include <sound/driver.h>
-#include <linux/time.h>
-#include <linux/fs.h>
-#include <sound/core.h>
-#include <sound/hwdep.h>
-#include <asm/uaccess.h>
-#include "ioctl32.h"
+/* This file is included from hwdep.c */
+
+#include <linux/compat.h>
struct sndrv_hwdep_dsp_image32 {
u32 index;
@@ -34,40 +30,48 @@ struct sndrv_hwdep_dsp_image32 {
u32 driver_data;
} /* don't set packed attribute here */;
-static inline int _snd_ioctl32_hwdep_dsp_image(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)
+static int snd_hwdep_dsp_load_compat(snd_hwdep_t *hw,
+ struct sndrv_hwdep_dsp_image32 __user *src)
{
- struct sndrv_hwdep_dsp_image __user *data, *dst;
- struct sndrv_hwdep_dsp_image32 __user *data32, *src;
+ struct sndrv_hwdep_dsp_image *dst;
compat_caddr_t ptr;
+ u32 val;
- data32 = compat_ptr(arg);
- data = compat_alloc_user_space(sizeof(*data));
+ dst = compat_alloc_user_space(sizeof(*dst));
/* index and name */
- if (copy_in_user(data, data32, 4 + 64))
+ if (copy_in_user(dst, src, 4 + 64))
return -EFAULT;
- if (__get_user(ptr, &data32->image) ||
- __put_user(compat_ptr(ptr), &data->image))
+ if (get_user(ptr, &src->image) ||
+ put_user(compat_ptr(ptr), &dst->image))
+ return -EFAULT;
+ if (get_user(val, &src->length) ||
+ put_user(val, &dst->length))
+ return -EFAULT;
+ if (get_user(val, &src->driver_data) ||
+ put_user(val, &dst->driver_data))
return -EFAULT;
- src = data32;
- dst = data;
- COPY_CVT(length);
- COPY_CVT(driver_data);
- return file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)data);
-}
-
-DEFINE_ALSA_IOCTL_ENTRY(hwdep_dsp_image, hwdep_dsp_image, SNDRV_HWDEP_IOCTL_DSP_LOAD);
-#define AP(x) snd_ioctl32_##x
+ return snd_hwdep_dsp_load(hw, dst);
+}
enum {
SNDRV_HWDEP_IOCTL_DSP_LOAD32 = _IOW('H', 0x03, struct sndrv_hwdep_dsp_image32)
};
-struct ioctl32_mapper hwdep_mappers[] = {
- MAP_COMPAT(SNDRV_HWDEP_IOCTL_PVERSION),
- MAP_COMPAT(SNDRV_HWDEP_IOCTL_INFO),
- MAP_COMPAT(SNDRV_HWDEP_IOCTL_DSP_STATUS),
- { SNDRV_HWDEP_IOCTL_DSP_LOAD32, AP(hwdep_dsp_image) },
- { 0 },
-};
+static long snd_hwdep_ioctl_compat(struct file * file, unsigned int cmd, unsigned long arg)
+{
+ snd_hwdep_t *hw = file->private_data;
+ void __user *argp = compat_ptr(arg);
+ switch (cmd) {
+ case SNDRV_HWDEP_IOCTL_PVERSION:
+ case SNDRV_HWDEP_IOCTL_INFO:
+ case SNDRV_HWDEP_IOCTL_DSP_STATUS:
+ return snd_hwdep_ioctl(file, cmd, (unsigned long)argp);
+ case SNDRV_HWDEP_IOCTL_DSP_LOAD32:
+ return snd_hwdep_dsp_load_compat(hw, argp);
+ }
+ if (hw->ops.ioctl_compat)
+ return hw->ops.ioctl_compat(hw, file, cmd, arg);
+ return -ENOIOCTLCMD;
+}
diff --git a/sound/core/info.c b/sound/core/info.c
index de9879b3b3867..31faffe01cb0f 100644
--- a/sound/core/info.c
+++ b/sound/core/info.c
@@ -92,19 +92,18 @@ static int snd_info_version_done(void);
int snd_iprintf(snd_info_buffer_t * buffer, char *fmt,...)
{
va_list args;
- int res;
- char sbuffer[512];
+ int len, res;
if (buffer->stop || buffer->error)
return 0;
+ len = buffer->len - buffer->size;
va_start(args, fmt);
- res = vscnprintf(sbuffer, sizeof(sbuffer), fmt, args);
+ res = vsnprintf(buffer->curr, len, fmt, args);
va_end(args);
- if (buffer->size + res >= buffer->len) {
+ if (res >= len) {
buffer->stop = 1;
return 0;
}
- strcpy(buffer->curr, sbuffer);
buffer->curr += res;
buffer->size += res;
return res;
diff --git a/sound/core/init.c b/sound/core/init.c
index 127f70e33b80e..3f1fa8eabb728 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -39,7 +39,7 @@ 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};
-rwlock_t snd_card_rwlock = RW_LOCK_UNLOCKED;
+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);
@@ -84,16 +84,13 @@ snd_card_t *snd_card_new(int idx, const char *xid,
write_lock(&snd_card_rwlock);
if (idx < 0) {
int idx2;
- for (idx2 = 0; idx2 < snd_ecards_limit; idx2++)
- if (!(snd_cards_lock & (1 << idx2))) {
+ for (idx2 = 0; idx2 < SNDRV_CARDS; idx2++)
+ if (~snd_cards_lock & idx & 1<<idx2) {
idx = idx2;
+ if (idx >= snd_ecards_limit)
+ snd_ecards_limit = idx + 1;
break;
}
- if (idx < 0 && snd_ecards_limit < SNDRV_CARDS)
- /* for dynamically additional devices like hotplug:
- * increment the limit if still free slot exists.
- */
- idx = snd_ecards_limit++;
} else if (idx < snd_ecards_limit) {
if (snd_cards_lock & (1 << idx))
err = -ENODEV; /* invalid */
@@ -229,6 +226,10 @@ int snd_card_disconnect(snd_card_t * card)
return 0;
}
+#if defined(CONFIG_PM) && defined(CONFIG_SND_GENERIC_PM)
+static void snd_generic_device_unregister(struct snd_generic_device *dev);
+#endif
+
/**
* snd_card_free - frees given soundcard structure
* @card: soundcard structure
@@ -252,9 +253,9 @@ int snd_card_free(snd_card_t * card)
#ifdef CONFIG_PM
wake_up(&card->power_sleep);
-#ifdef CONFIG_ISA
+#ifdef CONFIG_SND_GENERIC_PM
if (card->pm_dev) {
- pm_unregister(card->pm_dev);
+ snd_generic_device_unregister(card->pm_dev);
card->pm_dev = NULL;
}
#endif
@@ -374,7 +375,7 @@ static void choose_default_id(snd_card_t * card)
while (1) {
if (loops-- == 0) {
- snd_printk(KERN_ERR "unable to choose default card id (%s)", id);
+ snd_printk(KERN_ERR "unable to choose default card id (%s)\n", id);
strcpy(card->id, card->proc_root->name);
return;
}
@@ -719,8 +720,8 @@ int snd_power_wait(snd_card_t *card, unsigned int power_state, struct file *file
* handler and from the control API.
*/
int snd_card_set_pm_callback(snd_card_t *card,
- int (*suspend)(snd_card_t *, unsigned int),
- int (*resume)(snd_card_t *, unsigned int),
+ int (*suspend)(snd_card_t *, pm_message_t),
+ int (*resume)(snd_card_t *),
void *private_data)
{
card->pm_suspend = suspend;
@@ -729,56 +730,132 @@ int snd_card_set_pm_callback(snd_card_t *card,
return 0;
}
-static int snd_generic_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data)
+#ifdef CONFIG_SND_GENERIC_PM
+/*
+ * use platform_device for generic power-management without a proper bus
+ * (e.g. ISA)
+ */
+struct snd_generic_device {
+ struct platform_device pdev;
+ snd_card_t *card;
+};
+
+#define get_snd_generic_card(dev) container_of(to_platform_device(dev), struct snd_generic_device, pdev)->card
+
+#define SND_GENERIC_NAME "snd_generic_pm"
+
+static int snd_generic_suspend(struct device *dev, u32 state, u32 level);
+static int snd_generic_resume(struct device *dev, u32 level);
+
+static struct device_driver snd_generic_driver = {
+ .name = SND_GENERIC_NAME,
+ .bus = &platform_bus_type,
+ .suspend = snd_generic_suspend,
+ .resume = snd_generic_resume,
+};
+
+static int generic_driver_registered;
+
+static void generic_driver_unregister(void)
+{
+ if (generic_driver_registered) {
+ generic_driver_registered--;
+ if (! generic_driver_registered)
+ driver_unregister(&snd_generic_driver);
+ }
+}
+
+static struct snd_generic_device *snd_generic_device_register(snd_card_t *card)
{
- snd_card_t *card = dev->data;
+ struct snd_generic_device *dev;
- switch (rqst) {
- case PM_SUSPEND:
- if (card->power_state == SNDRV_CTL_POWER_D3hot)
- break;
- /* FIXME: the correct state value? */
- card->pm_suspend(card, 0);
- snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
- break;
- case PM_RESUME:
- if (card->power_state == SNDRV_CTL_POWER_D0)
- break;
- /* FIXME: the correct state value? */
- card->pm_resume(card, 0);
- snd_power_change_state(card, SNDRV_CTL_POWER_D0);
- break;
+ if (! generic_driver_registered) {
+ if (driver_register(&snd_generic_driver) < 0)
+ return NULL;
+ }
+ generic_driver_registered++;
+
+ dev = kcalloc(1, sizeof(*dev), GFP_KERNEL);
+ if (! dev) {
+ generic_driver_unregister();
+ return NULL;
}
+
+ dev->pdev.name = SND_GENERIC_NAME;
+ dev->pdev.id = card->number;
+ dev->card = card;
+ if (platform_device_register(&dev->pdev) < 0) {
+ kfree(dev);
+ generic_driver_unregister();
+ return NULL;
+ }
+ return dev;
+}
+
+static void snd_generic_device_unregister(struct snd_generic_device *dev)
+{
+ platform_device_unregister(&dev->pdev);
+ kfree(dev);
+ generic_driver_unregister();
+}
+
+/* suspend/resume callbacks for snd_generic platform device */
+static int snd_generic_suspend(struct device *dev, u32 state, u32 level)
+{
+ snd_card_t *card;
+
+ if (level != SUSPEND_DISABLE)
+ return 0;
+
+ card = get_snd_generic_card(dev);
+ if (card->power_state == SNDRV_CTL_POWER_D3hot)
+ return 0;
+ card->pm_suspend(card, PMSG_SUSPEND);
+ snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
+ return 0;
+}
+
+static int snd_generic_resume(struct device *dev, u32 level)
+{
+ snd_card_t *card;
+
+ if (level != RESUME_ENABLE)
+ return 0;
+
+ card = get_snd_generic_card(dev);
+ if (card->power_state == SNDRV_CTL_POWER_D0)
+ return 0;
+ card->pm_resume(card);
+ snd_power_change_state(card, SNDRV_CTL_POWER_D0);
return 0;
}
/**
- * snd_card_set_dev_pm_callback - set the generic power-management callbacks
+ * snd_card_set_generic_pm_callback - set the generic power-management callbacks
* @card: soundcard structure
- * @type: PM device type (PM_XXX)
* @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 with the given PM type. These callbacks are called
- * from the ALSA's common PM handler and from the control API.
+ * the given card. These callbacks are called from the ALSA's common
+ * PM handler and from the control API.
*/
-int snd_card_set_dev_pm_callback(snd_card_t *card, int type,
- int (*suspend)(snd_card_t *, unsigned int),
- int (*resume)(snd_card_t *, unsigned int),
+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)
{
- card->pm_dev = pm_register(type, 0, snd_generic_pm_callback);
+ card->pm_dev = snd_generic_device_register(card);
if (! card->pm_dev)
return -ENOMEM;
- card->pm_dev->data = card;
snd_card_set_pm_callback(card, suspend, resume, private_data);
return 0;
}
+#endif /* CONFIG_SND_GENERIC_PM */
#ifdef CONFIG_PCI
-int snd_card_pci_suspend(struct pci_dev *dev, u32 state)
+int snd_card_pci_suspend(struct pci_dev *dev, pm_message_t state)
{
snd_card_t *card = pci_get_drvdata(dev);
int err;
@@ -786,8 +863,7 @@ int snd_card_pci_suspend(struct pci_dev *dev, u32 state)
return 0;
if (card->power_state == SNDRV_CTL_POWER_D3hot)
return 0;
- /* FIXME: correct state value? */
- err = card->pm_suspend(card, 0);
+ err = card->pm_suspend(card, PMSG_SUSPEND);
pci_save_state(dev);
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
return err;
@@ -802,8 +878,7 @@ int snd_card_pci_resume(struct pci_dev *dev)
return 0;
/* restore the PCI config space */
pci_restore_state(dev);
- /* FIXME: correct state value? */
- card->pm_resume(card, 0);
+ card->pm_resume(card);
snd_power_change_state(card, SNDRV_CTL_POWER_D0);
return 0;
}
diff --git a/sound/core/ioctl32/Makefile b/sound/core/ioctl32/Makefile
deleted file mode 100644
index 0d0eacd42380b..0000000000000
--- a/sound/core/ioctl32/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-#
-# Makefile for ALSA
-# Copyright (c) 1999 by Jaroslav Kysela <perex@suse.cz>
-#
-
-snd-ioctl32-objs := ioctl32.o pcm32.o rawmidi32.o timer32.o hwdep32.o
-ifneq ($(CONFIG_SND_SEQUENCER),n)
- snd-ioctl32-objs += seq32.o
-endif
-
-obj-$(CONFIG_SND_BIT32_EMUL) += snd-ioctl32.o
diff --git a/sound/core/ioctl32/ioctl32.c b/sound/core/ioctl32/ioctl32.c
deleted file mode 100644
index bf48c51080a59..0000000000000
--- a/sound/core/ioctl32/ioctl32.c
+++ /dev/null
@@ -1,433 +0,0 @@
-/*
- * 32bit -> 64bit ioctl wrapper for control API
- * Copyright (c) by Takashi Iwai <tiwai@suse.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include <sound/driver.h>
-#include <linux/sched.h>
-#include <linux/smp_lock.h>
-#include <linux/init.h>
-#include <linux/time.h>
-#include <linux/slab.h>
-#include <linux/fs.h>
-#include <sound/core.h>
-#include <sound/control.h>
-#include <sound/minors.h>
-#include <asm/uaccess.h>
-#include "ioctl32.h"
-
-
-/*
- * register/unregister mappers
- * exported for other modules
- */
-
-MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
-MODULE_DESCRIPTION("ioctl32 wrapper for ALSA");
-MODULE_LICENSE("GPL");
-
-int register_ioctl32_conversion(unsigned int cmd, int (*handler)(unsigned int, unsigned int, unsigned long, struct file *));
-int unregister_ioctl32_conversion(unsigned int cmd);
-
-
-int snd_ioctl32_register(struct ioctl32_mapper *mappers)
-{
- int err;
- struct ioctl32_mapper *m;
-
- for (m = mappers; m->cmd; m++) {
- err = register_ioctl32_conversion(m->cmd, m->handler);
- if (err >= 0)
- m->registered++;
- }
- return 0;
-}
-
-void snd_ioctl32_unregister(struct ioctl32_mapper *mappers)
-{
- struct ioctl32_mapper *m;
-
- for (m = mappers; m->cmd; m++) {
- if (m->registered) {
- unregister_ioctl32_conversion(m->cmd);
- m->registered = 0;
- }
- }
-}
-
-
-/*
- * compatible wrapper
- */
-int snd_ioctl32_compat(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *filp)
-{
- if (! filp->f_op || ! filp->f_op->ioctl)
- return -ENOTTY;
- return filp->f_op->ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
-}
-
-
-/*
- * Controls
- */
-
-struct sndrv_ctl_elem_list32 {
- u32 offset;
- u32 space;
- u32 used;
- u32 count;
- u32 pids;
- unsigned char reserved[50];
-} /* don't set packed attribute here */;
-
-static inline int _snd_ioctl32_ctl_elem_list(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)
-{
- struct sndrv_ctl_elem_list32 __user *data32;
- struct sndrv_ctl_elem_list __user *data;
- compat_caddr_t ptr;
- int err;
-
- data32 = compat_ptr(arg);
- data = compat_alloc_user_space(sizeof(*data));
-
- /* offset, space, used, count */
- if (copy_in_user(data, data32, 4 * sizeof(u32)))
- return -EFAULT;
- /* pids */
- if (__get_user(ptr, &data32->pids) ||
- __put_user(compat_ptr(ptr), &data->pids))
- return -EFAULT;
- err = file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)data);
- if (err < 0)
- return err;
- /* copy the result */
- if (copy_in_user(data32, data, 4 * sizeof(u32)))
- return -EFAULT;
- return 0;
-}
-
-DEFINE_ALSA_IOCTL_ENTRY(ctl_elem_list, ctl_elem_list, SNDRV_CTL_IOCTL_ELEM_LIST);
-
-/*
- * control element info
- * 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
- s32 type;
- u32 access;
- u32 count;
- s32 owner;
- union {
- struct {
- s32 min;
- s32 max;
- s32 step;
- } integer;
- struct {
- u64 min;
- u64 max;
- u64 step;
- } integer64;
- struct {
- u32 items;
- u32 item;
- char name[64];
- } enumerated;
- unsigned char reserved[128];
- } value;
- unsigned char reserved[64];
-} __attribute__((packed));
-
-static inline int _snd_ioctl32_ctl_elem_info(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)
-{
- struct sndrv_ctl_elem_info __user *data, *src;
- struct sndrv_ctl_elem_info32 __user *data32, *dst;
- unsigned int type;
- int err;
-
- data32 = compat_ptr(arg);
- data = compat_alloc_user_space(sizeof(*data));
-
- /* copy id */
- if (copy_in_user(&data->id, &data32->id, sizeof(data->id)))
- return -EFAULT;
- /* we need to copy the item index.
- * hope this doesn't break anything..
- */
- if (copy_in_user(&data->value.enumerated.item,
- &data32->value.enumerated.item,
- sizeof(data->value.enumerated.item)))
- return -EFAULT;
- err = file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)data);
- if (err < 0)
- return err;
- /* restore info to 32bit */
- /* for COPY_CVT macro */
- src = data;
- dst = data32;
- /* id, type, access, count */
- if (copy_in_user(&data32->id, &data->id, sizeof(data->id)) ||
- copy_in_user(&data32->type, &data->type, 3 * sizeof(u32)))
- return -EFAULT;
- COPY_CVT(owner);
- __get_user(type, &data->type);
- switch (type) {
- case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
- case SNDRV_CTL_ELEM_TYPE_INTEGER:
- COPY_CVT(value.integer.min);
- COPY_CVT(value.integer.max);
- COPY_CVT(value.integer.step);
- break;
- case SNDRV_CTL_ELEM_TYPE_INTEGER64:
- if (copy_in_user(&data32->value.integer64,
- &data->value.integer64,
- sizeof(data->value.integer64)))
- return -EFAULT;
- break;
- case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
- if (copy_in_user(&data32->value.enumerated,
- &data->value.enumerated,
- sizeof(data->value.enumerated)))
- return -EFAULT;
- break;
- default:
- break;
- }
- return 0;
-}
-
-DEFINE_ALSA_IOCTL_ENTRY(ctl_elem_info, ctl_elem_info, SNDRV_CTL_IOCTL_ELEM_INFO);
-
-struct sndrv_ctl_elem_value32 {
- struct sndrv_ctl_elem_id id;
- unsigned int indirect; /* bit-field causes misalignment */
- union {
- s32 integer[128]; /* integer and boolean need conversion */
-#ifndef CONFIG_X86_64
- s64 integer64[64]; /* for alignment */
-#endif
- unsigned char data[512]; /* others should be compatible */
- } value;
- unsigned char reserved[128]; /* not used */
-};
-
-
-/* hmm, it's so hard to retrieve the value type from the control id.. */
-static int get_ctl_type(snd_card_t *card, snd_ctl_elem_id_t *id)
-{
- snd_kcontrol_t *kctl;
- snd_ctl_elem_info_t info;
- int err;
-
- down_read(&card->controls_rwsem);
- kctl = snd_ctl_find_id(card, id);
- if (! kctl) {
- up_read(&card->controls_rwsem);
- return -ENXIO;
- }
- info.id = *id;
- err = kctl->info(kctl, &info);
- up_read(&card->controls_rwsem);
- if (err >= 0)
- err = info.type;
- return err;
-}
-
-extern int snd_major;
-
-static inline int _snd_ioctl32_ctl_elem_value(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)
-{
- struct sndrv_ctl_elem_value *data;
- struct sndrv_ctl_elem_value32 __user *data32;
- snd_ctl_file_t *ctl;
- int err, i, indirect;
- int type;
-
- /* sanity check */
- if (imajor(file->f_dentry->d_inode) != snd_major ||
- SNDRV_MINOR_DEVICE(iminor(file->f_dentry->d_inode)) != SNDRV_MINOR_CONTROL)
- return -ENOTTY;
-
- if ((ctl = file->private_data) == NULL)
- return -ENOTTY;
-
- data32 = compat_ptr(arg);
- data = kcalloc(1, sizeof(*data), GFP_KERNEL);
- if (data == NULL)
- return -ENOMEM;
-
- if (copy_from_user(&data->id, &data32->id, sizeof(data->id))) {
- err = -EFAULT;
- goto __end;
- }
- if (__get_user(indirect, &data32->indirect)) {
- err = -EFAULT;
- goto __end;
- }
- /* FIXME: indirect access is not supported */
- if (indirect) {
- err = -EINVAL;
- goto __end;
- }
- type = get_ctl_type(ctl->card, &data->id);
- if (type < 0) {
- err = type;
- goto __end;
- }
-
- switch (type) {
- case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
- case SNDRV_CTL_ELEM_TYPE_INTEGER:
- for (i = 0; i < 128; i++) {
- int val;
- if (__get_user(val, &data32->value.integer[i])) {
- err = -EFAULT;
- goto __end;
- }
- data->value.integer.value[i] = val;
- }
- break;
- case SNDRV_CTL_ELEM_TYPE_INTEGER64:
- case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
- case SNDRV_CTL_ELEM_TYPE_BYTES:
- case SNDRV_CTL_ELEM_TYPE_IEC958:
- if (__copy_from_user(data->value.bytes.data,
- data32->value.data,
- sizeof(data32->value.data))) {
- err = -EFAULT;
- goto __end;
- }
- break;
- default:
- printk(KERN_ERR "snd_ioctl32_ctl_elem_value: unknown type %d\n", type);
- err = -EINVAL;
- goto __end;
- }
-
- if (native_ctl == SNDRV_CTL_IOCTL_ELEM_READ)
- err = snd_ctl_elem_read(ctl->card, data);
- else
- err = snd_ctl_elem_write(ctl->card, ctl, data);
- if (err < 0)
- goto __end;
- /* restore info to 32bit */
- switch (type) {
- case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
- case SNDRV_CTL_ELEM_TYPE_INTEGER:
- for (i = 0; i < 128; i++) {
- int val;
- val = data->value.integer.value[i];
- if (__put_user(val, &data32->value.integer[i])) {
- err = -EFAULT;
- goto __end;
- }
- }
- break;
- default:
- if (__copy_to_user(data32->value.data,
- data->value.bytes.data,
- sizeof(data32->value.data))) {
- err = -EFAULT;
- goto __end;
- }
- break;
- break;
- }
- err = 0;
- __end:
- kfree(data);
- return err;
-}
-
-DEFINE_ALSA_IOCTL_ENTRY(ctl_elem_read, ctl_elem_value, SNDRV_CTL_IOCTL_ELEM_READ);
-DEFINE_ALSA_IOCTL_ENTRY(ctl_elem_write, ctl_elem_value, SNDRV_CTL_IOCTL_ELEM_WRITE);
-
-/*
- */
-
-#define AP(x) snd_ioctl32_##x
-
-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),
-};
-
-static struct ioctl32_mapper control_mappers[] = {
- /* controls (without rawmidi, hwdep, timer releated ones) */
- MAP_COMPAT(SNDRV_CTL_IOCTL_PVERSION),
- MAP_COMPAT(SNDRV_CTL_IOCTL_CARD_INFO),
- { SNDRV_CTL_IOCTL_ELEM_LIST32, AP(ctl_elem_list) },
- { SNDRV_CTL_IOCTL_ELEM_INFO32, AP(ctl_elem_info) },
- { SNDRV_CTL_IOCTL_ELEM_READ32, AP(ctl_elem_read) },
- { SNDRV_CTL_IOCTL_ELEM_WRITE32, AP(ctl_elem_write) },
- MAP_COMPAT(SNDRV_CTL_IOCTL_ELEM_LOCK),
- MAP_COMPAT(SNDRV_CTL_IOCTL_ELEM_UNLOCK),
- MAP_COMPAT(SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS),
- MAP_COMPAT(SNDRV_CTL_IOCTL_HWDEP_INFO),
- MAP_COMPAT(SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE),
- MAP_COMPAT(SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE),
- MAP_COMPAT(SNDRV_CTL_IOCTL_PCM_INFO),
- MAP_COMPAT(SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE),
- MAP_COMPAT(SNDRV_CTL_IOCTL_POWER),
- MAP_COMPAT(SNDRV_CTL_IOCTL_POWER_STATE),
- { 0 }
-};
-
-
-/*
- */
-
-extern struct ioctl32_mapper pcm_mappers[];
-extern struct ioctl32_mapper rawmidi_mappers[];
-extern struct ioctl32_mapper timer_mappers[];
-extern struct ioctl32_mapper hwdep_mappers[];
-#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
-extern struct ioctl32_mapper seq_mappers[];
-#endif
-
-static void snd_ioctl32_done(void)
-{
-#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
- snd_ioctl32_unregister(seq_mappers);
-#endif
- snd_ioctl32_unregister(hwdep_mappers);
- snd_ioctl32_unregister(timer_mappers);
- snd_ioctl32_unregister(rawmidi_mappers);
- snd_ioctl32_unregister(pcm_mappers);
- snd_ioctl32_unregister(control_mappers);
-}
-
-static int __init snd_ioctl32_init(void)
-{
- snd_ioctl32_register(control_mappers);
- snd_ioctl32_register(pcm_mappers);
- snd_ioctl32_register(rawmidi_mappers);
- snd_ioctl32_register(timer_mappers);
- snd_ioctl32_register(hwdep_mappers);
-#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
- snd_ioctl32_register(seq_mappers);
-#endif
- return 0;
-}
-
-module_init(snd_ioctl32_init)
-module_exit(snd_ioctl32_done)
diff --git a/sound/core/ioctl32/ioctl32.h b/sound/core/ioctl32/ioctl32.h
deleted file mode 100644
index a8825a87a9761..0000000000000
--- a/sound/core/ioctl32/ioctl32.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * 32bit -> 64bit ioctl helpers
- * Copyright (c) by Takashi Iwai <tiwai@suse.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- *
- * This file registers the converters from 32-bit ioctls to 64-bit ones.
- * The converter assumes that a 32-bit user-pointer can be casted by compat_ptr(x)
- * macro to a valid 64-bit pointer which is accessible via copy_from/to_user.
- *
- */
-
-#ifndef __ALSA_IOCTL32_H
-#define __ALSA_IOCTL32_H
-
-#include <linux/compat.h>
-
-#define COPY(x) \
- do { \
- if (copy_in_user(&dst->x, &src->x, sizeof(dst->x))) \
- return -EFAULT; \
- } while (0)
-
-#define COPY_ARRAY(x) \
- do { \
- if (copy_in_user(dst->x, src->x, sizeof(dst->x))) \
- return -EFAULT; \
- } while (0)
-
-#define COPY_CVT(x) \
- do { \
- __typeof__(src->x) __val_tmp; \
- if (get_user(__val_tmp, &src->x) || \
- put_user(__val_tmp, &dst->x))\
- return -EFAULT; \
- } while (0)
-
-#define convert_from_32(type, dstp, srcp)\
-{\
- struct sndrv_##type __user *dst = dstp;\
- struct sndrv_##type##32 __user *src = srcp;\
- CVT_##sndrv_##type();\
-}
-
-#define convert_to_32(type, dstp, srcp)\
-{\
- struct sndrv_##type __user *src = srcp;\
- struct sndrv_##type##32 __user *dst = dstp;\
- CVT_##sndrv_##type();\
-}
-
-
-#define DEFINE_ALSA_IOCTL(type) \
-static inline int _snd_ioctl32_##type(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)\
-{\
- struct sndrv_##type##32 __user *data32;\
- struct sndrv_##type __user *data;\
- int err;\
- data32 = compat_ptr(arg);\
- data = compat_alloc_user_space(sizeof(*data));\
- convert_from_32(type, data, data32);\
- err = file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)data);\
- if (err < 0) \
- return err;\
- if (native_ctl & (_IOC_READ << _IOC_DIRSHIFT)) {\
- convert_to_32(type, data32, data);\
- }\
- return 0;\
-}
-
-#define DEFINE_ALSA_IOCTL_ENTRY(name,type,native_ctl) \
-static int snd_ioctl32_##name(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file) {\
- return _snd_ioctl32_##type(fd, cmd, arg, file, native_ctl);\
-}
-
-#define MAP_COMPAT(ctl) { ctl, snd_ioctl32_compat }
-
-struct ioctl32_mapper {
- unsigned int cmd;
- int (*handler)(unsigned int, unsigned int, unsigned long, struct file * filp);
- int registered;
-};
-
-int snd_ioctl32_compat(unsigned int, unsigned int, unsigned long, struct file *);
-
-int snd_ioctl32_register(struct ioctl32_mapper *mappers);
-void snd_ioctl32_unregister(struct ioctl32_mapper *mappers);
-
-#endif /* __ALSA_IOCTL32_H */
diff --git a/sound/core/ioctl32/pcm32.c b/sound/core/ioctl32/pcm32.c
deleted file mode 100644
index 1e37cda343d24..0000000000000
--- a/sound/core/ioctl32/pcm32.c
+++ /dev/null
@@ -1,464 +0,0 @@
-/*
- * 32bit -> 64bit ioctl wrapper for PCM API
- * Copyright (c) by Takashi Iwai <tiwai@suse.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to 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/slab.h>
-#include <linux/compat.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/minors.h>
-#include "ioctl32.h"
-
-
-/* wrapper for sndrv_pcm_[us]frames */
-struct sndrv_pcm_sframes_str {
- sndrv_pcm_sframes_t val;
-};
-struct sndrv_pcm_sframes_str32 {
- s32 val;
-};
-struct sndrv_pcm_uframes_str {
- sndrv_pcm_uframes_t val;
-};
-struct sndrv_pcm_uframes_str32 {
- u32 val;
-};
-
-#define CVT_sndrv_pcm_sframes_str() { COPY_CVT(val); }
-#define CVT_sndrv_pcm_uframes_str() { COPY_CVT(val); }
-
-
-struct sndrv_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 */
- u32 rmask;
- u32 cmask;
- u32 info;
- u32 msbits;
- u32 rate_num;
- u32 rate_den;
- u32 fifo_size;
- unsigned char reserved[64];
-} __attribute__((packed));
-
-struct sndrv_pcm_sw_params32 {
- s32 tstamp_mode;
- u32 period_step;
- u32 sleep_min;
- u32 avail_min;
- u32 xfer_align;
- u32 start_threshold;
- u32 stop_threshold;
- u32 silence_threshold;
- u32 silence_size;
- u32 boundary;
- unsigned char reserved[64];
-} __attribute__((packed));
-
-#define CVT_sndrv_pcm_sw_params()\
-{\
- COPY(tstamp_mode);\
- COPY(period_step);\
- COPY(sleep_min);\
- COPY_CVT(avail_min);\
- COPY_CVT(xfer_align);\
- COPY_CVT(start_threshold);\
- COPY_CVT(stop_threshold);\
- COPY_CVT(silence_threshold);\
- COPY_CVT(silence_size);\
- COPY_CVT(boundary);\
-}
-
-struct sndrv_pcm_channel_info32 {
- u32 channel;
- u32 offset;
- u32 first;
- u32 step;
-} __attribute__((packed));
-
-#define CVT_sndrv_pcm_channel_info()\
-{\
- COPY(channel);\
- COPY_CVT(offset);\
- COPY(first);\
- COPY(step);\
-}
-
-struct sndrv_pcm_status32 {
- s32 state;
- struct compat_timespec trigger_tstamp;
- struct compat_timespec tstamp;
- u32 appl_ptr;
- u32 hw_ptr;
- s32 delay;
- u32 avail;
- u32 avail_max;
- u32 overrange;
- s32 suspended_state;
- unsigned char reserved[60];
-} __attribute__((packed));
-
-#define CVT_sndrv_pcm_status()\
-{\
- COPY(state);\
- COPY_CVT(trigger_tstamp.tv_sec);\
- COPY_CVT(trigger_tstamp.tv_nsec);\
- COPY_CVT(tstamp.tv_sec);\
- COPY_CVT(tstamp.tv_nsec);\
- COPY_CVT(appl_ptr);\
- COPY_CVT(hw_ptr);\
- COPY_CVT(delay);\
- COPY_CVT(avail);\
- COPY_CVT(avail_max);\
- COPY_CVT(overrange);\
- COPY(suspended_state);\
-}
-
-DEFINE_ALSA_IOCTL(pcm_uframes_str);
-DEFINE_ALSA_IOCTL(pcm_sframes_str);
-DEFINE_ALSA_IOCTL(pcm_sw_params);
-DEFINE_ALSA_IOCTL(pcm_channel_info);
-DEFINE_ALSA_IOCTL(pcm_status);
-
-/* sanity device check */
-extern int snd_major;
-static int sanity_check_pcm(struct file *file)
-{
- unsigned short minor;
- if (imajor(file->f_dentry->d_inode) != snd_major)
- return -ENOTTY;
- minor = iminor(file->f_dentry->d_inode);
- if (minor >= 256 ||
- minor % SNDRV_MINOR_DEVICES < SNDRV_MINOR_PCM_PLAYBACK)
- return -ENOTTY;
- return 0;
-}
-
-/* recalcuate the boundary within 32bit */
-static void recalculate_boundary(snd_pcm_runtime_t *runtime)
-{
- if (! runtime->buffer_size)
- return;
- runtime->boundary = runtime->buffer_size;
- while (runtime->boundary * 2 <= 0x7fffffffUL - runtime->buffer_size)
- runtime->boundary *= 2;
-}
-
-/* both for HW_PARAMS and HW_REFINE */
-static int _snd_ioctl32_pcm_hw_params(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)
-{
- struct sndrv_pcm_hw_params32 __user *data32;
- struct sndrv_pcm_hw_params *data;
- snd_pcm_file_t *pcm_file;
- snd_pcm_substream_t *substream;
- snd_pcm_runtime_t *runtime;
- int err;
-
- if (sanity_check_pcm(file))
- return -ENOTTY;
- if (! (pcm_file = file->private_data))
- return -ENOTTY;
- if (! (substream = pcm_file->substream))
- return -ENOTTY;
- if (! (runtime = substream->runtime))
- return -ENOTTY;
-
- data32 = compat_ptr(arg);
- data = kmalloc(sizeof(*data), GFP_KERNEL);
- if (data == NULL)
- return -ENOMEM;
- if (copy_from_user(data, data32, sizeof(*data32))) {
- err = -EFAULT;
- goto error;
- }
- if (native_ctl == SNDRV_PCM_IOCTL_HW_REFINE)
- err = snd_pcm_hw_refine(substream, data);
- else
- err = snd_pcm_hw_params(substream, data);
- if (err < 0)
- goto error;
- if (copy_to_user(data32, data, sizeof(*data32)) ||
- __put_user((u32)data->fifo_size, &data32->fifo_size)) {
- err = -EFAULT;
- goto error;
- }
-
- if (native_ctl == SNDRV_PCM_IOCTL_HW_PARAMS)
- recalculate_boundary(runtime);
- error:
- kfree(data);
- return err;
-}
-
-
-/*
- */
-struct sndrv_xferi32 {
- s32 result;
- u32 buf;
- u32 frames;
-} __attribute__((packed));
-
-static int _snd_ioctl32_xferi(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)
-{
- struct sndrv_xferi32 data32;
- struct sndrv_xferi __user *data;
- snd_pcm_sframes_t result;
- int err;
-
- if (copy_from_user(&data32, (void __user *)arg, sizeof(data32)))
- return -EFAULT;
- data = compat_alloc_user_space(sizeof(*data));
- if (put_user((snd_pcm_sframes_t)data32.result, &data->result) ||
- __put_user(compat_ptr(data32.buf), &data->buf) ||
- __put_user((snd_pcm_uframes_t)data32.frames, &data->frames))
- return -EFAULT;
- err = file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)data);
- if (err < 0)
- return err;
- /* copy the result */
- if (__get_user(result, &data->result))
- return -EFAULT;
- data32.result = result;
- if (copy_to_user((void __user *)arg, &data32, sizeof(data32)))
- return -EFAULT;
- return 0;
-}
-
-
-/* snd_xfern needs remapping of bufs */
-struct sndrv_xfern32 {
- s32 result;
- u32 bufs; /* this is void **; */
- u32 frames;
-} __attribute__((packed));
-
-/*
- * xfern ioctl nees to copy (up to) 128 pointers on stack.
- * although we may pass the copied pointers through f_op->ioctl, but the ioctl
- * 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_ioctl32_xfern(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)
-{
- snd_pcm_file_t *pcm_file;
- snd_pcm_substream_t *substream;
- struct sndrv_xfern32 __user *srcptr = compat_ptr(arg);
- struct sndrv_xfern32 data32;
- void __user **bufs;
- int err = 0, ch, i;
- u32 __user *bufptr;
-
- if (sanity_check_pcm(file))
- return -ENOTTY;
- if (! (pcm_file = file->private_data))
- return -ENOTTY;
- if (! (substream = pcm_file->substream))
- return -ENOTTY;
- if (! substream->runtime)
- return -ENOTTY;
-
- /* check validty of the command */
- switch (native_ctl) {
- case SNDRV_PCM_IOCTL_WRITEN_FRAMES:
- if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
- return -EINVAL;
- if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN)
- return -EBADFD;
- break;
- case SNDRV_PCM_IOCTL_READN_FRAMES:
- if (substream->stream != SNDRV_PCM_STREAM_CAPTURE)
- return -EINVAL;
- break;
- }
- if ((ch = substream->runtime->channels) > 128)
- return -EINVAL;
- if (copy_from_user(&data32, (void __user *)arg, sizeof(data32)))
- return -EFAULT;
- bufptr = compat_ptr(data32.bufs);
- bufs = kmalloc(sizeof(void __user *) * ch, GFP_KERNEL);
- if (bufs == NULL)
- return -ENOMEM;
- for (i = 0; i < ch; i++) {
- u32 ptr;
- if (get_user(ptr, bufptr)) {
- kfree(bufs);
- return -EFAULT;
- }
- bufs[ch] = compat_ptr(ptr);
- bufptr++;
- }
- switch (native_ctl) {
- case SNDRV_PCM_IOCTL_WRITEN_FRAMES:
- err = snd_pcm_lib_writev(substream, bufs, data32.frames);
- break;
- case SNDRV_PCM_IOCTL_READN_FRAMES:
- err = snd_pcm_lib_readv(substream, bufs, data32.frames);
- break;
- }
- if (err >= 0) {
- if (put_user(err, &srcptr->result))
- err = -EFAULT;
- }
- kfree(bufs);
- return err;
-}
-
-
-struct sndrv_pcm_mmap_status32 {
- s32 state;
- s32 pad1;
- u32 hw_ptr;
- struct compat_timespec tstamp;
- s32 suspended_state;
-} __attribute__((packed));
-
-struct sndrv_pcm_mmap_control32 {
- u32 appl_ptr;
- u32 avail_min;
-} __attribute__((packed));
-
-struct sndrv_pcm_sync_ptr32 {
- u32 flags;
- union {
- struct sndrv_pcm_mmap_status32 status;
- unsigned char reserved[64];
- } s;
- union {
- struct sndrv_pcm_mmap_control32 control;
- unsigned char reserved[64];
- } c;
-} __attribute__((packed));
-
-#define CVT_sndrv_pcm_sync_ptr()\
-{\
- COPY(flags);\
- COPY(s.status.state);\
- COPY(s.status.pad1);\
- COPY_CVT(s.status.hw_ptr);\
- COPY_CVT(s.status.tstamp.tv_sec);\
- COPY_CVT(s.status.tstamp.tv_nsec);\
- COPY(s.status.suspended_state);\
- COPY_CVT(c.control.appl_ptr);\
- COPY_CVT(c.control.avail_min);\
-}
-
-DEFINE_ALSA_IOCTL(pcm_sync_ptr);
-
-/*
- */
-
-DEFINE_ALSA_IOCTL_ENTRY(pcm_hw_refine, pcm_hw_params, SNDRV_PCM_IOCTL_HW_REFINE);
-DEFINE_ALSA_IOCTL_ENTRY(pcm_hw_params, pcm_hw_params, SNDRV_PCM_IOCTL_HW_PARAMS);
-DEFINE_ALSA_IOCTL_ENTRY(pcm_sw_params, pcm_sw_params, SNDRV_PCM_IOCTL_SW_PARAMS);
-DEFINE_ALSA_IOCTL_ENTRY(pcm_status, pcm_status, SNDRV_PCM_IOCTL_STATUS);
-DEFINE_ALSA_IOCTL_ENTRY(pcm_delay, pcm_sframes_str, SNDRV_PCM_IOCTL_DELAY);
-DEFINE_ALSA_IOCTL_ENTRY(pcm_channel_info, pcm_channel_info, SNDRV_PCM_IOCTL_CHANNEL_INFO);
-DEFINE_ALSA_IOCTL_ENTRY(pcm_rewind, pcm_uframes_str, SNDRV_PCM_IOCTL_REWIND);
-DEFINE_ALSA_IOCTL_ENTRY(pcm_forward, pcm_uframes_str, SNDRV_PCM_IOCTL_FORWARD);
-DEFINE_ALSA_IOCTL_ENTRY(pcm_readi, xferi, SNDRV_PCM_IOCTL_READI_FRAMES);
-DEFINE_ALSA_IOCTL_ENTRY(pcm_writei, xferi, SNDRV_PCM_IOCTL_WRITEI_FRAMES);
-DEFINE_ALSA_IOCTL_ENTRY(pcm_readn, xfern, SNDRV_PCM_IOCTL_READN_FRAMES);
-DEFINE_ALSA_IOCTL_ENTRY(pcm_writen, xfern, SNDRV_PCM_IOCTL_WRITEN_FRAMES);
-DEFINE_ALSA_IOCTL_ENTRY(pcm_sync_ptr, pcm_sync_ptr, SNDRV_PCM_IOCTL_SYNC_PTR);
-
-
-/*
- * When PCM is used on 32bit mode, we need to disable
- * mmap of PCM status/control records because of the size
- * incompatibility.
- *
- * Since INFO ioctl is always called at first, we mark the
- * mmap-disabling in this ioctl wrapper.
- */
-static int snd_pcm_info_ioctl32(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *filp)
-{
- snd_pcm_file_t *pcm_file;
- snd_pcm_substream_t *substream;
- if (! filp->f_op || ! filp->f_op->ioctl)
- return -ENOTTY;
- pcm_file = filp->private_data;
- if (! pcm_file)
- return -ENOTTY;
- substream = pcm_file->substream;
- if (! substream)
- return -ENOTTY;
- substream->no_mmap_ctrl = 1;
- return filp->f_op->ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
-}
-
-/*
- */
-#define AP(x) snd_ioctl32_##x
-
-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_DELAY32 = _IOR('A', 0x21, s32),
- SNDRV_PCM_IOCTL_CHANNEL_INFO32 = _IOR('A', 0x32, struct sndrv_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),
-
-};
-
-struct ioctl32_mapper pcm_mappers[] = {
- MAP_COMPAT(SNDRV_PCM_IOCTL_PVERSION),
- /* MAP_COMPAT(SNDRV_PCM_IOCTL_INFO), */
- { SNDRV_PCM_IOCTL_INFO, snd_pcm_info_ioctl32 },
- MAP_COMPAT(SNDRV_PCM_IOCTL_TSTAMP),
- { SNDRV_PCM_IOCTL_HW_REFINE32, AP(pcm_hw_refine) },
- { SNDRV_PCM_IOCTL_HW_PARAMS32, AP(pcm_hw_params) },
- MAP_COMPAT(SNDRV_PCM_IOCTL_HW_FREE),
- { SNDRV_PCM_IOCTL_SW_PARAMS32, AP(pcm_sw_params) },
- { SNDRV_PCM_IOCTL_STATUS32, AP(pcm_status) },
- { SNDRV_PCM_IOCTL_DELAY32, AP(pcm_delay) },
- MAP_COMPAT(SNDRV_PCM_IOCTL_HWSYNC),
- { SNDRV_PCM_IOCTL_SYNC_PTR32, AP(pcm_sync_ptr) },
- { SNDRV_PCM_IOCTL_CHANNEL_INFO32, AP(pcm_channel_info) },
- MAP_COMPAT(SNDRV_PCM_IOCTL_PREPARE),
- MAP_COMPAT(SNDRV_PCM_IOCTL_RESET),
- MAP_COMPAT(SNDRV_PCM_IOCTL_START),
- MAP_COMPAT(SNDRV_PCM_IOCTL_DROP),
- MAP_COMPAT(SNDRV_PCM_IOCTL_DRAIN),
- MAP_COMPAT(SNDRV_PCM_IOCTL_PAUSE),
- { SNDRV_PCM_IOCTL_REWIND32, AP(pcm_rewind) },
- MAP_COMPAT(SNDRV_PCM_IOCTL_RESUME),
- MAP_COMPAT(SNDRV_PCM_IOCTL_XRUN),
- { SNDRV_PCM_IOCTL_FORWARD32, AP(pcm_forward) },
- { SNDRV_PCM_IOCTL_WRITEI_FRAMES32, AP(pcm_writei) },
- { SNDRV_PCM_IOCTL_READI_FRAMES32, AP(pcm_readi) },
- { SNDRV_PCM_IOCTL_WRITEN_FRAMES32, AP(pcm_writen) },
- { SNDRV_PCM_IOCTL_READN_FRAMES32, AP(pcm_readn) },
- MAP_COMPAT(SNDRV_PCM_IOCTL_LINK),
- MAP_COMPAT(SNDRV_PCM_IOCTL_UNLINK),
-
- { 0 },
-};
diff --git a/sound/core/ioctl32/rawmidi32.c b/sound/core/ioctl32/rawmidi32.c
deleted file mode 100644
index c1d89488618c6..0000000000000
--- a/sound/core/ioctl32/rawmidi32.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * 32bit -> 64bit ioctl wrapper for raw MIDI API
- * Copyright (c) by Takashi Iwai <tiwai@suse.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to 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/fs.h>
-#include <linux/compat.h>
-#include <sound/core.h>
-#include <sound/rawmidi.h>
-#include <asm/uaccess.h>
-#include "ioctl32.h"
-
-struct sndrv_rawmidi_params32 {
- s32 stream;
- u32 buffer_size;
- u32 avail_min;
- unsigned int no_active_sensing; /* avoid bit-field */
- unsigned char reserved[16];
-} __attribute__((packed));
-
-#define CVT_sndrv_rawmidi_params()\
-{\
- COPY(stream);\
- COPY_CVT(buffer_size);\
- COPY_CVT(avail_min);\
- if (copy_in_user(((size_t __user *)&dst->avail_min + 1),\
- ((size_t __user *)&src->avail_min + 1), 4)) \
- return -EFAULT;\
-}
-
-struct sndrv_rawmidi_status32 {
- s32 stream;
- struct compat_timespec tstamp;
- u32 avail;
- u32 xruns;
- unsigned char reserved[16];
-} __attribute__((packed));
-
-#define CVT_sndrv_rawmidi_status()\
-{\
- COPY(stream);\
- COPY_CVT(tstamp.tv_sec);\
- COPY_CVT(tstamp.tv_nsec);\
- COPY_CVT(avail);\
- COPY_CVT(xruns);\
-}
-
-DEFINE_ALSA_IOCTL(rawmidi_params);
-DEFINE_ALSA_IOCTL(rawmidi_status);
-
-DEFINE_ALSA_IOCTL_ENTRY(rawmidi_params, rawmidi_params, SNDRV_RAWMIDI_IOCTL_PARAMS);
-DEFINE_ALSA_IOCTL_ENTRY(rawmidi_status, rawmidi_status, SNDRV_RAWMIDI_IOCTL_STATUS);
-
-#define AP(x) snd_ioctl32_##x
-
-enum {
- SNDRV_RAWMIDI_IOCTL_PARAMS32 = _IOWR('W', 0x10, struct sndrv_rawmidi_params32),
- SNDRV_RAWMIDI_IOCTL_STATUS32 = _IOWR('W', 0x20, struct sndrv_rawmidi_status32),
-};
-
-struct ioctl32_mapper rawmidi_mappers[] = {
- MAP_COMPAT(SNDRV_RAWMIDI_IOCTL_PVERSION),
- MAP_COMPAT(SNDRV_RAWMIDI_IOCTL_INFO),
- { SNDRV_RAWMIDI_IOCTL_PARAMS32, AP(rawmidi_params) },
- { SNDRV_RAWMIDI_IOCTL_STATUS32, AP(rawmidi_status) },
- MAP_COMPAT(SNDRV_RAWMIDI_IOCTL_DROP),
- MAP_COMPAT(SNDRV_RAWMIDI_IOCTL_DRAIN),
-
- MAP_COMPAT(SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE),
- MAP_COMPAT(SNDRV_CTL_IOCTL_RAWMIDI_INFO),
- MAP_COMPAT(SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE),
-
- { 0 },
-};
diff --git a/sound/core/ioctl32/seq32.c b/sound/core/ioctl32/seq32.c
deleted file mode 100644
index c349feaf3add4..0000000000000
--- a/sound/core/ioctl32/seq32.c
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * 32bit -> 64bit ioctl wrapper for sequencer API
- * Copyright (c) by Takashi Iwai <tiwai@suse.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to 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/fs.h>
-#include <sound/core.h>
-#include <sound/timer.h>
-#include <asm/uaccess.h>
-#include <sound/asequencer.h>
-#include "ioctl32.h"
-
-struct sndrv_seq_port_info32 {
- struct sndrv_seq_addr addr; /* client/port numbers */
- char name[64]; /* port name */
-
- u32 capability; /* port capability bits */
- u32 type; /* port type bits */
- s32 midi_channels; /* channels per MIDI port */
- s32 midi_voices; /* voices per MIDI port */
- s32 synth_voices; /* voices per SYNTH port */
-
- s32 read_use; /* R/O: subscribers for output (from this port) */
- s32 write_use; /* R/O: subscribers for input (to this port) */
-
- u32 kernel; /* reserved for kernel use (must be NULL) */
- u32 flags; /* misc. conditioning */
- unsigned char time_queue; /* queue # for timestamping */
- char reserved[59]; /* for future use */
-};
-
-#define CVT_sndrv_seq_port_info()\
-{\
- COPY(addr);\
- COPY_ARRAY(name);\
- COPY(capability);\
- COPY(type);\
- COPY(midi_channels);\
- COPY(midi_voices);\
- COPY(synth_voices);\
- COPY(read_use);\
- COPY(write_use);\
- COPY(flags);\
- COPY(time_queue);\
-}
-
-DEFINE_ALSA_IOCTL(seq_port_info);
-DEFINE_ALSA_IOCTL_ENTRY(create_port, seq_port_info, SNDRV_SEQ_IOCTL_CREATE_PORT);
-DEFINE_ALSA_IOCTL_ENTRY(delete_port, seq_port_info, SNDRV_SEQ_IOCTL_DELETE_PORT);
-DEFINE_ALSA_IOCTL_ENTRY(get_port_info, seq_port_info, SNDRV_SEQ_IOCTL_GET_PORT_INFO);
-DEFINE_ALSA_IOCTL_ENTRY(set_port_info, seq_port_info, SNDRV_SEQ_IOCTL_SET_PORT_INFO);
-DEFINE_ALSA_IOCTL_ENTRY(query_next_port, seq_port_info, SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT);
-
-/*
- */
-#define AP(x) snd_ioctl32_##x
-
-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),
-};
-
-struct ioctl32_mapper seq_mappers[] = {
- MAP_COMPAT(SNDRV_SEQ_IOCTL_PVERSION),
- MAP_COMPAT(SNDRV_SEQ_IOCTL_CLIENT_ID),
- MAP_COMPAT(SNDRV_SEQ_IOCTL_SYSTEM_INFO),
- MAP_COMPAT(SNDRV_SEQ_IOCTL_GET_CLIENT_INFO),
- MAP_COMPAT(SNDRV_SEQ_IOCTL_SET_CLIENT_INFO),
- { SNDRV_SEQ_IOCTL_CREATE_PORT32, AP(create_port) },
- { SNDRV_SEQ_IOCTL_DELETE_PORT32, AP(delete_port) },
- { SNDRV_SEQ_IOCTL_GET_PORT_INFO32, AP(get_port_info) },
- { SNDRV_SEQ_IOCTL_SET_PORT_INFO32, AP(set_port_info) },
- MAP_COMPAT(SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT),
- MAP_COMPAT(SNDRV_SEQ_IOCTL_UNSUBSCRIBE_PORT),
- MAP_COMPAT(SNDRV_SEQ_IOCTL_CREATE_QUEUE),
- MAP_COMPAT(SNDRV_SEQ_IOCTL_DELETE_QUEUE),
- MAP_COMPAT(SNDRV_SEQ_IOCTL_GET_QUEUE_INFO),
- MAP_COMPAT(SNDRV_SEQ_IOCTL_SET_QUEUE_INFO),
- MAP_COMPAT(SNDRV_SEQ_IOCTL_GET_NAMED_QUEUE),
- MAP_COMPAT(SNDRV_SEQ_IOCTL_GET_QUEUE_STATUS),
- MAP_COMPAT(SNDRV_SEQ_IOCTL_GET_QUEUE_TEMPO),
- MAP_COMPAT(SNDRV_SEQ_IOCTL_SET_QUEUE_TEMPO),
- MAP_COMPAT(SNDRV_SEQ_IOCTL_GET_QUEUE_TIMER),
- MAP_COMPAT(SNDRV_SEQ_IOCTL_SET_QUEUE_TIMER),
- MAP_COMPAT(SNDRV_SEQ_IOCTL_GET_QUEUE_CLIENT),
- MAP_COMPAT(SNDRV_SEQ_IOCTL_SET_QUEUE_CLIENT),
- MAP_COMPAT(SNDRV_SEQ_IOCTL_GET_CLIENT_POOL),
- MAP_COMPAT(SNDRV_SEQ_IOCTL_SET_CLIENT_POOL),
- MAP_COMPAT(SNDRV_SEQ_IOCTL_REMOVE_EVENTS),
- MAP_COMPAT(SNDRV_SEQ_IOCTL_QUERY_SUBS),
- MAP_COMPAT(SNDRV_SEQ_IOCTL_GET_SUBSCRIPTION),
- MAP_COMPAT(SNDRV_SEQ_IOCTL_QUERY_NEXT_CLIENT),
- { SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT32, AP(query_next_port) },
- MAP_COMPAT(SNDRV_SEQ_IOCTL_RUNNING_MODE),
- { 0 },
-};
diff --git a/sound/core/ioctl32/timer32.c b/sound/core/ioctl32/timer32.c
deleted file mode 100644
index 5f1a2d97a873a..0000000000000
--- a/sound/core/ioctl32/timer32.c
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * 32bit -> 64bit ioctl wrapper for timer API
- * Copyright (c) by Takashi Iwai <tiwai@suse.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to 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/fs.h>
-#include <linux/compat.h>
-#include <sound/core.h>
-#include <sound/timer.h>
-#include <asm/uaccess.h>
-#include "ioctl32.h"
-
-struct sndrv_timer_info32 {
- u32 flags;
- s32 card;
- unsigned char id[64];
- unsigned char name[80];
- u32 reserved0;
- u32 resolution;
- unsigned char reserved[64];
-};
-
-#define CVT_sndrv_timer_info()\
-{\
- COPY(flags);\
- COPY(card);\
- COPY_ARRAY(id);\
- COPY_ARRAY(name);\
- COPY_CVT(resolution);\
-}
-
-struct sndrv_timer_status32 {
- struct compat_timespec tstamp;
- u32 resolution;
- u32 lost;
- u32 overrun;
- u32 queue;
- unsigned char reserved[64];
-};
-
-#define CVT_sndrv_timer_status()\
-{\
- COPY_CVT(tstamp.tv_sec);\
- COPY_CVT(tstamp.tv_nsec);\
- COPY(resolution);\
- COPY(lost);\
- COPY(overrun);\
- COPY(queue);\
-}
-
-DEFINE_ALSA_IOCTL(timer_info);
-DEFINE_ALSA_IOCTL(timer_status);
-
-DEFINE_ALSA_IOCTL_ENTRY(timer_info, timer_info, SNDRV_TIMER_IOCTL_INFO);
-DEFINE_ALSA_IOCTL_ENTRY(timer_status, timer_status, SNDRV_TIMER_IOCTL_STATUS);
-
-/*
- */
-
-#define AP(x) snd_ioctl32_##x
-
-enum {
- SNDRV_TIMER_IOCTL_INFO32 = _IOR('T', 0x11, struct sndrv_timer_info32),
- SNDRV_TIMER_IOCTL_STATUS32 = _IOW('T', 0x14, struct sndrv_timer_status32),
-};
-
-struct ioctl32_mapper timer_mappers[] = {
- MAP_COMPAT(SNDRV_TIMER_IOCTL_PVERSION),
- MAP_COMPAT(SNDRV_TIMER_IOCTL_NEXT_DEVICE),
- MAP_COMPAT(SNDRV_TIMER_IOCTL_SELECT),
- { SNDRV_TIMER_IOCTL_INFO32, AP(timer_info) },
- MAP_COMPAT(SNDRV_TIMER_IOCTL_PARAMS),
- { SNDRV_TIMER_IOCTL_STATUS32, AP(timer_status) },
-#if 0
- /* ** FIXME **
- * The following four entries are disabled because they conflict
- * with the TCOC* definitions.
- * Unfortunately, the current ioctl32 wrapper uses a single
- * hash table for all devices. Once when the wrapper is fixed
- * with the table based on devices, they'll be back again.
- */
- MAP_COMPAT(SNDRV_TIMER_IOCTL_START),
- MAP_COMPAT(SNDRV_TIMER_IOCTL_STOP),
- MAP_COMPAT(SNDRV_TIMER_IOCTL_CONTINUE),
- MAP_COMPAT(SNDRV_TIMER_IOCTL_PAUSE),
-#endif
- { 0 },
-};
diff --git a/sound/core/memory.c b/sound/core/memory.c
index eff0de0c49196..20860fec93644 100644
--- a/sound/core/memory.c
+++ b/sound/core/memory.c
@@ -50,8 +50,8 @@ static long snd_alloc_kmalloc;
static long snd_alloc_vmalloc;
static LIST_HEAD(snd_alloc_kmalloc_list);
static LIST_HEAD(snd_alloc_vmalloc_list);
-static spinlock_t snd_alloc_kmalloc_lock = SPIN_LOCK_UNLOCKED;
-static spinlock_t snd_alloc_vmalloc_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(snd_alloc_kmalloc_lock);
+static DEFINE_SPINLOCK(snd_alloc_vmalloc_lock);
#define KMALLOC_MAGIC 0x87654321
#define VMALLOC_MAGIC 0x87654320
static snd_info_entry_t *snd_memory_info_entry;
diff --git a/sound/core/misc.c b/sound/core/misc.c
index 4ec82aad54fb7..1a81fe4df218b 100644
--- a/sound/core/misc.c
+++ b/sound/core/misc.c
@@ -40,7 +40,6 @@ int snd_task_name(struct task_struct *task, char *name, size_t size)
void snd_verbose_printk(const char *file, int line, const char *format, ...)
{
va_list args;
- char tmpbuf[512];
if (format[0] == '<' && format[1] >= '0' && format[1] <= '9' && format[2] == '>') {
char tmp[] = "<0>";
@@ -51,9 +50,8 @@ void snd_verbose_printk(const char *file, int line, const char *format, ...)
printk("ALSA %s:%d: ", file, line);
}
va_start(args, format);
- vsnprintf(tmpbuf, sizeof(tmpbuf), format, args);
+ vprintk(format, args);
va_end(args);
- printk(tmpbuf);
}
#endif
@@ -61,7 +59,6 @@ void snd_verbose_printk(const char *file, int line, const char *format, ...)
void snd_verbose_printd(const char *file, int line, const char *format, ...)
{
va_list args;
- char tmpbuf[512];
if (format[0] == '<' && format[1] >= '0' && format[1] <= '9' && format[2] == '>') {
char tmp[] = "<0>";
@@ -72,9 +69,8 @@ void snd_verbose_printd(const char *file, int line, const char *format, ...)
printk(KERN_DEBUG "ALSA %s:%d: ", file, line);
}
va_start(args, format);
- vsnprintf(tmpbuf, sizeof(tmpbuf), format, args);
+ vprintk(format, args);
va_end(args);
- printk(tmpbuf);
}
#endif
diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c
index b9901566a1d66..98ed9a9f0da65 100644
--- a/sound/core/oss/mixer_oss.c
+++ b/sound/core/oss/mixer_oss.c
@@ -359,16 +359,9 @@ static int snd_mixer_oss_ioctl1(snd_mixer_oss_file_t *fmixer, unsigned int cmd,
return -ENXIO;
}
-/* FIXME: need to unlock BKL to allow preemption */
-static int snd_mixer_oss_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
+static long snd_mixer_oss_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
- int err;
- /* FIXME: need to unlock BKL to allow preemption */
- unlock_kernel();
- err = snd_mixer_oss_ioctl1((snd_mixer_oss_file_t *) file->private_data, cmd, arg);
- lock_kernel();
- return err;
+ return snd_mixer_oss_ioctl1((snd_mixer_oss_file_t *) file->private_data, cmd, arg);
}
int snd_mixer_oss_ioctl_card(snd_card_t *card, unsigned int cmd, unsigned long arg)
@@ -384,6 +377,13 @@ int snd_mixer_oss_ioctl_card(snd_card_t *card, unsigned int cmd, unsigned long a
return snd_mixer_oss_ioctl1(&fmixer, cmd, arg);
}
+#ifdef CONFIG_COMPAT
+/* all compatible */
+#define snd_mixer_oss_ioctl_compat snd_mixer_oss_ioctl
+#else
+#define snd_mixer_oss_ioctl_compat NULL
+#endif
+
/*
* REGISTRATION PART
*/
@@ -393,7 +393,8 @@ static struct file_operations snd_mixer_oss_f_ops =
.owner = THIS_MODULE,
.open = snd_mixer_oss_open,
.release = snd_mixer_oss_release,
- .ioctl = snd_mixer_oss_ioctl,
+ .unlocked_ioctl = snd_mixer_oss_ioctl,
+ .compat_ioctl = snd_mixer_oss_ioctl_compat,
};
static snd_minor_t snd_mixer_oss_reg =
@@ -521,7 +522,7 @@ static void snd_mixer_oss_get_volume1_vol(snd_mixer_oss_file_t *fmixer,
goto __unalloc;
snd_runtime_check(!kctl->info(kctl, uinfo), goto __unalloc);
snd_runtime_check(!kctl->get(kctl, uctl), goto __unalloc);
- snd_runtime_check(uinfo->type != SNDRV_CTL_ELEM_TYPE_BOOLEAN || uinfo->value.integer.min != 0 || uinfo->value.integer.max != 1, return);
+ snd_runtime_check(uinfo->type != SNDRV_CTL_ELEM_TYPE_BOOLEAN || uinfo->value.integer.min != 0 || uinfo->value.integer.max != 1, goto __unalloc);
*left = snd_mixer_oss_conv1(uctl->value.integer.value[0], uinfo->value.integer.min, uinfo->value.integer.max, &pslot->volume[0]);
if (uinfo->count > 1)
*right = snd_mixer_oss_conv1(uctl->value.integer.value[1], uinfo->value.integer.min, uinfo->value.integer.max, &pslot->volume[1]);
@@ -615,7 +616,7 @@ static void snd_mixer_oss_put_volume1_vol(snd_mixer_oss_file_t *fmixer,
if (uinfo == NULL || uctl == NULL)
goto __unalloc;
snd_runtime_check(!kctl->info(kctl, uinfo), goto __unalloc);
- snd_runtime_check(uinfo->type != SNDRV_CTL_ELEM_TYPE_BOOLEAN || uinfo->value.integer.min != 0 || uinfo->value.integer.max != 1, return);
+ snd_runtime_check(uinfo->type != SNDRV_CTL_ELEM_TYPE_BOOLEAN || uinfo->value.integer.min != 0 || uinfo->value.integer.max != 1, goto __unalloc);
uctl->value.integer.value[0] = snd_mixer_oss_conv2(left, uinfo->value.integer.min, uinfo->value.integer.max);
if (uinfo->count > 1)
uctl->value.integer.value[1] = snd_mixer_oss_conv2(right, uinfo->value.integer.min, uinfo->value.integer.max);
@@ -856,7 +857,7 @@ struct snd_mixer_oss_assign_table {
static int snd_mixer_oss_build_test(snd_mixer_oss_t *mixer, struct slot *slot, const char *name, int index, int item)
{
- snd_ctl_elem_info_t info;
+ snd_ctl_elem_info_t *info;
snd_kcontrol_t *kcontrol;
snd_card_t *card = mixer->card;
int err;
@@ -867,15 +868,22 @@ static int snd_mixer_oss_build_test(snd_mixer_oss_t *mixer, struct slot *slot, c
up_read(&card->controls_rwsem);
return 0;
}
- if ((err = kcontrol->info(kcontrol, &info)) < 0) {
+ info = kmalloc(sizeof(*info), GFP_KERNEL);
+ if (! info) {
+ up_read(&card->controls_rwsem);
+ return -ENOMEM;
+ }
+ if ((err = kcontrol->info(kcontrol, info)) < 0) {
up_read(&card->controls_rwsem);
+ kfree(info);
return err;
}
slot->numid[item] = kcontrol->id.numid;
up_read(&card->controls_rwsem);
- if (info.count > slot->channels)
- slot->channels = info.count;
+ if (info->count > slot->channels)
+ slot->channels = info->count;
slot->present |= 1 << item;
+ kfree(info);
return 0;
}
@@ -960,10 +968,16 @@ 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;
+ snd_ctl_elem_info_t *uinfo;
- memset(&uinfo, 0, sizeof(uinfo));
- if (kctl->info(kctl, &uinfo)) {
+ uinfo = kmalloc(sizeof(*uinfo), GFP_KERNEL);
+ if (! uinfo) {
+ up_read(&mixer->card->controls_rwsem);
+ return -ENOMEM;
+ }
+
+ memset(uinfo, 0, sizeof(*uinfo));
+ if (kctl->info(kctl, uinfo)) {
up_read(&mixer->card->controls_rwsem);
return 0;
}
@@ -973,21 +987,22 @@ static int snd_mixer_oss_build_input(snd_mixer_oss_t *mixer, struct snd_mixer_os
if (!strcmp(str, "Master Mono"))
strcpy(str, "Mix Mono");
slot.capture_item = 0;
- if (!strcmp(uinfo.value.enumerated.name, str)) {
+ if (!strcmp(uinfo->value.enumerated.name, str)) {
slot.present |= SNDRV_MIXER_OSS_PRESENT_CAPTURE;
} else {
- for (slot.capture_item = 1; slot.capture_item < uinfo.value.enumerated.items; slot.capture_item++) {
- uinfo.value.enumerated.item = slot.capture_item;
- if (kctl->info(kctl, &uinfo)) {
+ for (slot.capture_item = 1; slot.capture_item < uinfo->value.enumerated.items; slot.capture_item++) {
+ uinfo->value.enumerated.item = slot.capture_item;
+ if (kctl->info(kctl, uinfo)) {
up_read(&mixer->card->controls_rwsem);
return 0;
}
- if (!strcmp(uinfo.value.enumerated.name, str)) {
+ if (!strcmp(uinfo->value.enumerated.name, str)) {
slot.present |= SNDRV_MIXER_OSS_PRESENT_CAPTURE;
break;
}
}
}
+ kfree(uinfo);
}
up_read(&mixer->card->controls_rwsem);
if (slot.present != 0) {
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index cc76a98d4c202..1a805020f57a5 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -636,10 +636,10 @@ snd_pcm_sframes_t snd_pcm_oss_write3(snd_pcm_substream_t *substream, const char
if (in_kernel) {
mm_segment_t fs;
fs = snd_enter_user();
- ret = snd_pcm_lib_write(substream, ptr, frames);
+ ret = snd_pcm_lib_write(substream, (void __user *)ptr, frames);
snd_leave_user(fs);
} else {
- ret = snd_pcm_lib_write(substream, ptr, frames);
+ ret = snd_pcm_lib_write(substream, (void __user *)ptr, frames);
}
if (ret != -EPIPE && ret != -ESTRPIPE)
break;
@@ -679,10 +679,10 @@ snd_pcm_sframes_t snd_pcm_oss_read3(snd_pcm_substream_t *substream, char *ptr, s
if (in_kernel) {
mm_segment_t fs;
fs = snd_enter_user();
- ret = snd_pcm_lib_read(substream, ptr, frames);
+ ret = snd_pcm_lib_read(substream, (void __user *)ptr, frames);
snd_leave_user(fs);
} else {
- ret = snd_pcm_lib_read(substream, ptr, frames);
+ ret = snd_pcm_lib_read(substream, (void __user *)ptr, frames);
}
if (ret == -EPIPE) {
if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
@@ -718,10 +718,10 @@ snd_pcm_sframes_t snd_pcm_oss_writev3(snd_pcm_substream_t *substream, void **buf
if (in_kernel) {
mm_segment_t fs;
fs = snd_enter_user();
- ret = snd_pcm_lib_writev(substream, bufs, frames);
+ ret = snd_pcm_lib_writev(substream, (void __user **)bufs, frames);
snd_leave_user(fs);
} else {
- ret = snd_pcm_lib_writev(substream, bufs, frames);
+ ret = snd_pcm_lib_writev(substream, (void __user **)bufs, frames);
}
if (ret != -EPIPE && ret != -ESTRPIPE)
break;
@@ -758,10 +758,10 @@ snd_pcm_sframes_t snd_pcm_oss_readv3(snd_pcm_substream_t *substream, void **bufs
if (in_kernel) {
mm_segment_t fs;
fs = snd_enter_user();
- ret = snd_pcm_lib_readv(substream, bufs, frames);
+ ret = snd_pcm_lib_readv(substream, (void __user **)bufs, frames);
snd_leave_user(fs);
} else {
- ret = snd_pcm_lib_readv(substream, bufs, frames);
+ ret = snd_pcm_lib_readv(substream, (void __user **)bufs, frames);
}
if (ret != -EPIPE && ret != -ESTRPIPE)
break;
@@ -777,7 +777,7 @@ static ssize_t snd_pcm_oss_write2(snd_pcm_substream_t *substream, const char *bu
snd_pcm_plugin_channel_t *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, buf, bytes))
+ if (copy_from_user(runtime->oss.buffer, (const char __user *)buf, bytes))
return -EFAULT;
buf = runtime->oss.buffer;
}
@@ -839,7 +839,7 @@ static ssize_t snd_pcm_oss_write1(snd_pcm_substream_t *substream, const char __u
return xfer > 0 ? xfer : -EAGAIN;
}
} else {
- tmp = snd_pcm_oss_write2(substream, (char *)buf, runtime->oss.period_bytes, 0);
+ tmp = snd_pcm_oss_write2(substream, (const char *)buf, runtime->oss.period_bytes, 0);
if (tmp <= 0)
return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp;
runtime->oss.bytes += tmp;
@@ -858,7 +858,7 @@ static ssize_t snd_pcm_oss_read2(snd_pcm_substream_t *substream, char *buf, size
{
snd_pcm_runtime_t *runtime = substream->runtime;
snd_pcm_sframes_t frames, frames1;
- char *final_dst = buf;
+ char __user *final_dst = (char __user *)buf;
if (runtime->oss.plugin_first) {
snd_pcm_plugin_channel_t *channels;
size_t oss_frame_bytes = (runtime->oss.plugin_last->dst_width * runtime->oss.plugin_last->dst_format.channels) / 8;
@@ -1058,6 +1058,7 @@ static int snd_pcm_oss_sync(snd_pcm_oss_file_t *pcm_oss_file)
if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED) {
size = (runtime->frame_bits * size) / 8;
while (size > 0) {
+ mm_segment_t fs;
size_t size1 = size < runtime->oss.period_bytes ? size : runtime->oss.period_bytes;
size -= size1;
size1 *= 8;
@@ -1065,7 +1066,9 @@ static int snd_pcm_oss_sync(snd_pcm_oss_file_t *pcm_oss_file)
snd_pcm_format_set_silence(runtime->format,
runtime->oss.buffer,
size1);
- snd_pcm_lib_write(substream, runtime->oss.buffer, size1);
+ fs = snd_enter_user();
+ snd_pcm_lib_write(substream, (void __user *)runtime->oss.buffer, size1);
+ snd_leave_user(fs);
}
} else if (runtime->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) {
void __user *buffers[runtime->channels];
@@ -1913,8 +1916,7 @@ static int snd_pcm_oss_release(struct inode *inode, struct file *file)
return 0;
}
-static inline int _snd_pcm_oss_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
+static long snd_pcm_oss_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
snd_pcm_oss_file_t *pcm_oss_file;
int __user *p = (int __user *)arg;
@@ -2073,16 +2075,12 @@ static inline int _snd_pcm_oss_ioctl(struct inode *inode, struct file *file,
return -EINVAL;
}
-/* FIXME: need to unlock BKL to allow preemption */
-static int snd_pcm_oss_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- int err;
- unlock_kernel();
- err = _snd_pcm_oss_ioctl(inode, file, cmd, arg);
- lock_kernel();
- return err;
-}
+#ifdef CONFIG_COMPAT
+/* all compatible */
+#define snd_pcm_oss_ioctl_compat snd_pcm_oss_ioctl
+#else
+#define snd_pcm_oss_ioctl_compat NULL
+#endif
static ssize_t snd_pcm_oss_read(struct file *file, char __user *buf, size_t count, loff_t *offset)
{
@@ -2296,7 +2294,7 @@ static void snd_pcm_oss_proc_write(snd_info_entry_t *entry,
snd_info_buffer_t * buffer)
{
snd_pcm_str_t *pstr = (snd_pcm_str_t *)entry->private_data;
- char line[256], str[32], task_name[32], *ptr;
+ char line[128], str[32], task_name[32], *ptr;
int idx1;
snd_pcm_oss_setup_t *setup, *setup1, template;
@@ -2410,7 +2408,8 @@ static struct file_operations snd_pcm_oss_f_reg =
.open = snd_pcm_oss_open,
.release = snd_pcm_oss_release,
.poll = snd_pcm_oss_poll,
- .ioctl = snd_pcm_oss_ioctl,
+ .unlocked_ioctl = snd_pcm_oss_ioctl,
+ .compat_ioctl = snd_pcm_oss_ioctl_compat,
.mmap = snd_pcm_oss_mmap,
};
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
index 559c66c55754c..8d94325529a87 100644
--- a/sound/core/pcm.c
+++ b/sound/core/pcm.c
@@ -270,25 +270,35 @@ static const char *snd_pcm_oss_format_name(int format)
#ifdef CONFIG_PROC_FS
static void snd_pcm_proc_info_read(snd_pcm_substream_t *substream, snd_info_buffer_t *buffer)
{
- snd_pcm_info_t info;
+ snd_pcm_info_t *info;
int err;
+
snd_runtime_check(substream, return);
- err = snd_pcm_info(substream, &info);
+
+ info = kmalloc(sizeof(*info), GFP_KERNEL);
+ if (! info) {
+ printk(KERN_DEBUG "snd_pcm_proc_info_read: cannot malloc\n");
+ return;
+ }
+
+ err = snd_pcm_info(substream, info);
if (err < 0) {
snd_iprintf(buffer, "error %d\n", err);
+ kfree(info);
return;
}
- snd_iprintf(buffer, "card: %d\n", info.card);
- snd_iprintf(buffer, "device: %d\n", info.device);
- snd_iprintf(buffer, "subdevice: %d\n", info.subdevice);
- snd_iprintf(buffer, "stream: %s\n", snd_pcm_stream_name(info.stream));
- snd_iprintf(buffer, "id: %s\n", info.id);
- snd_iprintf(buffer, "name: %s\n", info.name);
- snd_iprintf(buffer, "subname: %s\n", info.subname);
- snd_iprintf(buffer, "class: %d\n", info.dev_class);
- snd_iprintf(buffer, "subclass: %d\n", info.dev_subclass);
- snd_iprintf(buffer, "subdevices_count: %d\n", info.subdevices_count);
- snd_iprintf(buffer, "subdevices_avail: %d\n", info.subdevices_avail);
+ snd_iprintf(buffer, "card: %d\n", info->card);
+ snd_iprintf(buffer, "device: %d\n", info->device);
+ snd_iprintf(buffer, "subdevice: %d\n", info->subdevice);
+ snd_iprintf(buffer, "stream: %s\n", snd_pcm_stream_name(info->stream));
+ snd_iprintf(buffer, "id: %s\n", info->id);
+ snd_iprintf(buffer, "name: %s\n", info->name);
+ snd_iprintf(buffer, "subname: %s\n", info->subname);
+ snd_iprintf(buffer, "class: %d\n", info->dev_class);
+ snd_iprintf(buffer, "subclass: %d\n", info->dev_subclass);
+ snd_iprintf(buffer, "subdevices_count: %d\n", info->subdevices_count);
+ snd_iprintf(buffer, "subdevices_avail: %d\n", info->subdevices_avail);
+ kfree(info);
}
static void snd_pcm_stream_proc_info_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
@@ -1004,6 +1014,7 @@ static int __init alsa_pcm_init(void)
snd_info_entry_t *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);
if (snd_info_register(entry) < 0) {
@@ -1018,6 +1029,7 @@ static int __init alsa_pcm_init(void)
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;
diff --git a/sound/core/pcm_compat.c b/sound/core/pcm_compat.c
new file mode 100644
index 0000000000000..3920bf0eebbf2
--- /dev/null
+++ b/sound/core/pcm_compat.c
@@ -0,0 +1,513 @@
+/*
+ * 32bit -> 64bit ioctl wrapper for PCM API
+ * Copyright (c) by Takashi Iwai <tiwai@suse.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* This file included from pcm_native.c */
+
+#include <linux/compat.h>
+
+static int snd_pcm_ioctl_delay_compat(snd_pcm_substream_t *substream,
+ s32 __user *src)
+{
+ snd_pcm_sframes_t delay;
+ mm_segment_t fs;
+ int err;
+
+ fs = snd_enter_user();
+ err = snd_pcm_delay(substream, &delay);
+ snd_leave_user(fs);
+ if (err < 0)
+ return err;
+ if (put_user(delay, src))
+ return -EFAULT;
+ return err;
+}
+
+static int snd_pcm_ioctl_rewind_compat(snd_pcm_substream_t *substream,
+ u32 __user *src)
+{
+ snd_pcm_uframes_t frames;
+ int err;
+
+ if (get_user(frames, src))
+ return -EFAULT;
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ err = snd_pcm_playback_rewind(substream, frames);
+ else
+ err = snd_pcm_capture_rewind(substream, frames);
+ if (put_user(err, src))
+ return -EFAULT;
+ return err < 0 ? err : 0;
+}
+
+static int snd_pcm_ioctl_forward_compat(snd_pcm_substream_t *substream,
+ u32 __user *src)
+{
+ snd_pcm_uframes_t frames;
+ int err;
+
+ if (get_user(frames, src))
+ return -EFAULT;
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ err = snd_pcm_playback_forward(substream, frames);
+ else
+ err = snd_pcm_capture_forward(substream, frames);
+ if (put_user(err, src))
+ return -EFAULT;
+ return err < 0 ? err : 0;
+}
+
+struct sndrv_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 */
+ u32 rmask;
+ u32 cmask;
+ u32 info;
+ u32 msbits;
+ u32 rate_num;
+ u32 rate_den;
+ u32 fifo_size;
+ unsigned char reserved[64];
+};
+
+struct sndrv_pcm_sw_params32 {
+ s32 tstamp_mode;
+ u32 period_step;
+ u32 sleep_min;
+ u32 avail_min;
+ u32 xfer_align;
+ u32 start_threshold;
+ u32 stop_threshold;
+ u32 silence_threshold;
+ u32 silence_size;
+ u32 boundary;
+ unsigned char reserved[64];
+};
+
+static int snd_pcm_ioctl_sw_params_compat(snd_pcm_substream_t *substream,
+ struct sndrv_pcm_sw_params32 __user *src)
+{
+ snd_pcm_sw_params_t params;
+ int err;
+
+ memset(&params, 0, sizeof(params));
+ if (get_user(params.tstamp_mode, &src->tstamp_mode) ||
+ get_user(params.period_step, &src->period_step) ||
+ get_user(params.sleep_min, &src->sleep_min) ||
+ get_user(params.avail_min, &src->avail_min) ||
+ get_user(params.xfer_align, &src->xfer_align) ||
+ get_user(params.start_threshold, &src->start_threshold) ||
+ get_user(params.stop_threshold, &src->stop_threshold) ||
+ get_user(params.silence_threshold, &src->silence_threshold) ||
+ get_user(params.silence_size, &src->silence_size))
+ return -EFAULT;
+ err = snd_pcm_sw_params(substream, &params);
+ if (err < 0)
+ return err;
+ if (put_user(params.boundary, &src->boundary))
+ return -EFAULT;
+ return err;
+}
+
+struct sndrv_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)
+{
+ snd_pcm_channel_info_t info;
+ int err;
+
+ if (get_user(info.channel, &src->channel) ||
+ get_user(info.offset, &src->offset) ||
+ get_user(info.first, &src->first) ||
+ get_user(info.step, &src->step))
+ return -EFAULT;
+ err = snd_pcm_channel_info(substream, &info);
+ if (err < 0)
+ return err;
+ if (put_user(info.channel, &src->channel) ||
+ put_user(info.offset, &src->offset) ||
+ put_user(info.first, &src->first) ||
+ put_user(info.step, &src->step))
+ return -EFAULT;
+ return err;
+}
+
+struct sndrv_pcm_status32 {
+ s32 state;
+ struct compat_timespec trigger_tstamp;
+ struct compat_timespec tstamp;
+ u32 appl_ptr;
+ u32 hw_ptr;
+ s32 delay;
+ u32 avail;
+ u32 avail_max;
+ u32 overrange;
+ s32 suspended_state;
+ unsigned char reserved[60];
+} __attribute__((packed));
+
+
+static int snd_pcm_status_user_compat(snd_pcm_substream_t *substream,
+ struct sndrv_pcm_status32 __user *src)
+{
+ snd_pcm_status_t status;
+ int err;
+
+ err = snd_pcm_status(substream, &status);
+ if (err < 0)
+ return err;
+
+ if (put_user(status.state, &src->state) ||
+ put_user(status.trigger_tstamp.tv_sec, &src->trigger_tstamp.tv_sec) ||
+ put_user(status.trigger_tstamp.tv_nsec, &src->trigger_tstamp.tv_nsec) ||
+ put_user(status.tstamp.tv_sec, &src->tstamp.tv_sec) ||
+ put_user(status.tstamp.tv_nsec, &src->tstamp.tv_nsec) ||
+ put_user(status.appl_ptr, &src->appl_ptr) ||
+ put_user(status.hw_ptr, &src->hw_ptr) ||
+ put_user(status.delay, &src->delay) ||
+ put_user(status.avail, &src->avail) ||
+ put_user(status.avail_max, &src->avail_max) ||
+ put_user(status.overrange, &src->overrange) ||
+ put_user(status.suspended_state, &src->suspended_state))
+ return -EFAULT;
+
+ return err;
+}
+
+/* recalcuate the boundary within 32bit */
+static void recalculate_boundary(snd_pcm_runtime_t *runtime)
+{
+ if (! runtime->buffer_size)
+ return;
+ runtime->boundary = runtime->buffer_size;
+ while (runtime->boundary * 2 <= 0x7fffffffUL - runtime->buffer_size)
+ runtime->boundary *= 2;
+}
+
+/* both for HW_PARAMS and HW_REFINE */
+static int snd_pcm_ioctl_hw_params_compat(snd_pcm_substream_t *substream,
+ int refine,
+ struct sndrv_pcm_hw_params32 __user *data32)
+{
+ struct sndrv_pcm_hw_params *data;
+ snd_pcm_runtime_t *runtime;
+ int err;
+
+ if (! (runtime = substream->runtime))
+ return -ENOTTY;
+
+ data = kmalloc(sizeof(*data), GFP_KERNEL);
+ if (data == NULL)
+ return -ENOMEM;
+ /* only fifo_size is different, so just copy all */
+ if (copy_from_user(data, data32, sizeof(*data32))) {
+ err = -EFAULT;
+ goto error;
+ }
+ if (refine)
+ err = snd_pcm_hw_refine(substream, data);
+ else
+ err = snd_pcm_hw_params(substream, data);
+ if (err < 0)
+ goto error;
+ if (copy_to_user(data32, data, sizeof(*data32)) ||
+ put_user(data->fifo_size, &data32->fifo_size)) {
+ err = -EFAULT;
+ goto error;
+ }
+
+ if (! refine)
+ recalculate_boundary(runtime);
+ error:
+ kfree(data);
+ return err;
+}
+
+
+/*
+ */
+struct sndrv_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)
+{
+ compat_caddr_t buf;
+ u32 frames;
+ int err;
+
+ if (! substream->runtime)
+ return -ENOTTY;
+ if (substream->stream != dir)
+ return -EINVAL;
+ if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN)
+ return -EBADFD;
+
+ if (get_user(buf, &data32->buf) ||
+ get_user(frames, &data32->frames))
+ return -EFAULT;
+
+ if (dir == SNDRV_PCM_STREAM_PLAYBACK)
+ err = snd_pcm_lib_write(substream, compat_ptr(buf), frames);
+ else
+ err = snd_pcm_lib_read(substream, compat_ptr(buf), frames);
+ if (err < 0)
+ return err;
+ /* copy the result */
+ if (put_user(err, &data32->result))
+ return -EFAULT;
+ return 0;
+}
+
+
+/* snd_xfern needs remapping of bufs */
+struct sndrv_xfern32 {
+ s32 result;
+ u32 bufs; /* this is void **; */
+ u32 frames;
+};
+
+/*
+ * xfern ioctl nees to copy (up to) 128 pointers on stack.
+ * although we may pass the copied pointers through f_op->ioctl, but the ioctl
+ * 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)
+{
+ compat_caddr_t buf;
+ compat_caddr_t __user *bufptr;
+ u32 frames;
+ void __user **bufs;
+ int err, ch, i;
+
+ if (! substream->runtime)
+ return -ENOTTY;
+ if (substream->stream != dir)
+ return -EINVAL;
+
+ if ((ch = substream->runtime->channels) > 128)
+ return -EINVAL;
+ if (get_user(buf, &data32->bufs) ||
+ get_user(frames, &data32->frames))
+ return -EFAULT;
+ bufptr = compat_ptr(buf);
+ bufs = kmalloc(sizeof(void __user *) * ch, GFP_KERNEL);
+ if (bufs == NULL)
+ return -ENOMEM;
+ for (i = 0; i < ch; i++) {
+ u32 ptr;
+ if (get_user(ptr, bufptr)) {
+ kfree(bufs);
+ return -EFAULT;
+ }
+ bufs[ch] = compat_ptr(ptr);
+ bufptr++;
+ }
+ if (dir == SNDRV_PCM_STREAM_PLAYBACK)
+ err = snd_pcm_lib_writev(substream, bufs, frames);
+ else
+ err = snd_pcm_lib_readv(substream, bufs, frames);
+ if (err >= 0) {
+ if (put_user(err, &data32->result))
+ err = -EFAULT;
+ }
+ kfree(bufs);
+ return err;
+}
+
+
+struct sndrv_pcm_mmap_status32 {
+ s32 state;
+ s32 pad1;
+ u32 hw_ptr;
+ struct compat_timespec tstamp;
+ s32 suspended_state;
+} __attribute__((packed));
+
+struct sndrv_pcm_mmap_control32 {
+ u32 appl_ptr;
+ u32 avail_min;
+};
+
+struct sndrv_pcm_sync_ptr32 {
+ u32 flags;
+ union {
+ struct sndrv_pcm_mmap_status32 status;
+ unsigned char reserved[64];
+ } s;
+ union {
+ struct sndrv_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)
+{
+ snd_pcm_runtime_t *runtime = substream->runtime;
+ volatile struct sndrv_pcm_mmap_status *status;
+ volatile struct sndrv_pcm_mmap_control *control;
+ u32 sflags;
+ struct sndrv_pcm_mmap_control scontrol;
+ struct sndrv_pcm_mmap_status sstatus;
+ int err;
+
+ snd_assert(runtime, return -EINVAL);
+
+ if (get_user(sflags, &src->flags) ||
+ get_user(scontrol.appl_ptr, &src->c.control.appl_ptr) ||
+ get_user(scontrol.avail_min, &src->c.control.avail_min))
+ return -EFAULT;
+ if (sflags & SNDRV_PCM_SYNC_PTR_HWSYNC) {
+ err = snd_pcm_hwsync(substream);
+ if (err < 0)
+ return err;
+ }
+ status = runtime->status;
+ control = runtime->control;
+ snd_pcm_stream_lock_irq(substream);
+ if (!(sflags & SNDRV_PCM_SYNC_PTR_APPL))
+ control->appl_ptr = scontrol.appl_ptr;
+ else
+ scontrol.appl_ptr = control->appl_ptr;
+ if (!(sflags & SNDRV_PCM_SYNC_PTR_AVAIL_MIN))
+ control->avail_min = scontrol.avail_min;
+ else
+ scontrol.avail_min = control->avail_min;
+ sstatus.state = status->state;
+ sstatus.hw_ptr = status->hw_ptr;
+ sstatus.tstamp = status->tstamp;
+ sstatus.suspended_state = status->suspended_state;
+ snd_pcm_stream_unlock_irq(substream);
+ if (put_user(sstatus.state, &src->s.status.state) ||
+ put_user(sstatus.hw_ptr, &src->s.status.hw_ptr) ||
+ put_user(sstatus.tstamp.tv_sec, &src->s.status.tstamp.tv_sec) ||
+ put_user(sstatus.tstamp.tv_nsec, &src->s.status.tstamp.tv_nsec) ||
+ put_user(sstatus.suspended_state, &src->s.status.suspended_state) ||
+ put_user(scontrol.appl_ptr, &src->c.control.appl_ptr) ||
+ put_user(scontrol.avail_min, &src->c.control.avail_min))
+ return -EFAULT;
+
+ return 0;
+}
+
+
+/*
+ */
+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_DELAY32 = _IOR('A', 0x21, s32),
+ SNDRV_PCM_IOCTL_CHANNEL_INFO32 = _IOR('A', 0x32, struct sndrv_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),
+
+};
+
+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;
+ void __user *argp = compat_ptr(arg);
+
+ pcm_file = file->private_data;
+ if (! pcm_file)
+ return -ENOTTY;
+ substream = pcm_file->substream;
+ if (! substream)
+ return -ENOTTY;
+
+ /*
+ * When PCM is used on 32bit mode, we need to disable
+ * mmap of PCM status/control records because of the size
+ * incompatibility.
+ */
+ substream->no_mmap_ctrl = 1;
+
+ switch (cmd) {
+ case SNDRV_PCM_IOCTL_PVERSION:
+ case SNDRV_PCM_IOCTL_INFO:
+ case SNDRV_PCM_IOCTL_TSTAMP:
+ case SNDRV_PCM_IOCTL_HWSYNC:
+ case SNDRV_PCM_IOCTL_PREPARE:
+ case SNDRV_PCM_IOCTL_RESET:
+ case SNDRV_PCM_IOCTL_START:
+ case SNDRV_PCM_IOCTL_DROP:
+ case SNDRV_PCM_IOCTL_DRAIN:
+ case SNDRV_PCM_IOCTL_PAUSE:
+ case SNDRV_PCM_IOCTL_HW_FREE:
+ case SNDRV_PCM_IOCTL_RESUME:
+ case SNDRV_PCM_IOCTL_XRUN:
+ case SNDRV_PCM_IOCTL_LINK:
+ case SNDRV_PCM_IOCTL_UNLINK:
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ return snd_pcm_playback_ioctl1(substream, cmd, argp);
+ else
+ return snd_pcm_capture_ioctl1(substream, cmd, argp);
+ case SNDRV_PCM_IOCTL_HW_REFINE32:
+ return snd_pcm_ioctl_hw_params_compat(substream, 1, argp);
+ case SNDRV_PCM_IOCTL_HW_PARAMS32:
+ return snd_pcm_ioctl_hw_params_compat(substream, 0, argp);
+ case SNDRV_PCM_IOCTL_SW_PARAMS32:
+ return snd_pcm_ioctl_sw_params_compat(substream, argp);
+ case SNDRV_PCM_IOCTL_STATUS32:
+ return snd_pcm_status_user_compat(substream, argp);
+ case SNDRV_PCM_IOCTL_SYNC_PTR32:
+ return snd_pcm_ioctl_sync_ptr_compat(substream, argp);
+ case SNDRV_PCM_IOCTL_CHANNEL_INFO32:
+ return snd_pcm_ioctl_channel_info_compat(substream, argp);
+ case SNDRV_PCM_IOCTL_WRITEI_FRAMES32:
+ return snd_pcm_ioctl_xferi_compat(substream, SNDRV_PCM_STREAM_PLAYBACK, argp);
+ case SNDRV_PCM_IOCTL_READI_FRAMES32:
+ return snd_pcm_ioctl_xferi_compat(substream, SNDRV_PCM_STREAM_CAPTURE, argp);
+ case SNDRV_PCM_IOCTL_WRITEN_FRAMES32:
+ return snd_pcm_ioctl_xfern_compat(substream, SNDRV_PCM_STREAM_PLAYBACK, argp);
+ case SNDRV_PCM_IOCTL_READN_FRAMES32:
+ return snd_pcm_ioctl_xfern_compat(substream, SNDRV_PCM_STREAM_CAPTURE, argp);
+ case SNDRV_PCM_IOCTL_DELAY32:
+ return snd_pcm_ioctl_delay_compat(substream, argp);
+ case SNDRV_PCM_IOCTL_REWIND32:
+ return snd_pcm_ioctl_rewind_compat(substream, argp);
+ case SNDRV_PCM_IOCTL_FORWARD32:
+ return snd_pcm_ioctl_forward_compat(substream, argp);
+ }
+
+ return -ENOIOCTLCMD;
+}
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index fc05089ca3484..151fd99ca2c9b 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -1863,9 +1863,8 @@ static void snd_pcm_system_tick_set(snd_pcm_substream_t *substream,
if (ticks == 0)
del_timer(&runtime->tick_timer);
else {
+ ticks += (1000000 / HZ) - 1;
ticks /= (1000000 / HZ);
- if (ticks % (1000000 / HZ))
- ticks++;
mod_timer(&runtime->tick_timer, jiffies + ticks);
}
}
@@ -2142,11 +2141,9 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(snd_pcm_substream_t *substream,
break;
}
appl_ptr += frames;
- if (appl_ptr >= runtime->boundary) {
- runtime->control->appl_ptr = 0;
- } else {
- runtime->control->appl_ptr = appl_ptr;
- }
+ if (appl_ptr >= runtime->boundary)
+ appl_ptr -= runtime->boundary;
+ runtime->control->appl_ptr = appl_ptr;
if (substream->ops->ack)
substream->ops->ack(substream);
@@ -2441,11 +2438,9 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(snd_pcm_substream_t *substream,
break;
}
appl_ptr += frames;
- if (appl_ptr >= runtime->boundary) {
- runtime->control->appl_ptr = 0;
- } else {
- runtime->control->appl_ptr = appl_ptr;
- }
+ if (appl_ptr >= runtime->boundary)
+ appl_ptr -= runtime->boundary;
+ runtime->control->appl_ptr = appl_ptr;
if (substream->ops->ack)
substream->ops->ack(substream);
diff --git a/sound/core/pcm_memory.c b/sound/core/pcm_memory.c
index e165fee4891c1..f1d5f7a6ee0c6 100644
--- a/sound/core/pcm_memory.c
+++ b/sound/core/pcm_memory.c
@@ -291,7 +291,7 @@ struct page *snd_pcm_sgbuf_ops_page(snd_pcm_substream_t *substream, unsigned lon
* @substream: the substream to allocate the DMA buffer to
* @size: the requested buffer size in bytes
*
- * Allocates the DMA buffer on the BUS type given by
+ * Allocates the DMA buffer on the BUS type given earlier to
* snd_pcm_lib_preallocate_xxx_pages().
*
* Returns 1 if the buffer is changed, 0 if not changed, or a negative
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index d0519469c52a1..cad9bbde99868 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -65,7 +65,7 @@ static int snd_pcm_hw_params_old_user(snd_pcm_substream_t * substream, struct sn
*
*/
-rwlock_t snd_pcm_link_rwlock = RW_LOCK_UNLOCKED;
+DEFINE_RWLOCK(snd_pcm_link_rwlock);
static DECLARE_RWSEM(snd_pcm_link_rwsem);
@@ -113,10 +113,18 @@ 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)
{
- snd_pcm_info_t info;
- int err = snd_pcm_info(substream, &info);
- if (copy_to_user(_info, &info, sizeof(info)))
- return -EFAULT;
+ snd_pcm_info_t *info;
+ int err;
+
+ info = kmalloc(sizeof(*info), GFP_KERNEL);
+ if (! info)
+ return -ENOMEM;
+ err = snd_pcm_info(substream, info);
+ if (err >= 0) {
+ if (copy_to_user(_info, info, sizeof(*info)))
+ err = -EFAULT;
+ }
+ kfree(info);
return err;
}
@@ -602,17 +610,13 @@ 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 __user * _info)
+static int snd_pcm_channel_info(snd_pcm_substream_t * substream, snd_pcm_channel_info_t * info)
{
- snd_pcm_channel_info_t info;
snd_pcm_runtime_t *runtime;
- int res;
unsigned int channel;
snd_assert(substream != NULL, return -ENXIO);
- if (copy_from_user(&info, _info, sizeof(info)))
- return -EFAULT;
- channel = info.channel;
+ channel = info->channel;
runtime = substream->runtime;
snd_pcm_stream_lock_irq(substream);
if (runtime->status->state == SNDRV_PCM_STATE_OPEN) {
@@ -622,9 +626,19 @@ static int snd_pcm_channel_info(snd_pcm_substream_t * substream, snd_pcm_channel
snd_pcm_stream_unlock_irq(substream);
if (channel >= runtime->channels)
return -EINVAL;
- memset(&info, 0, sizeof(info));
- info.channel = channel;
- res = substream->ops->ioctl(substream, SNDRV_PCM_IOCTL1_CHANNEL_INFO, &info);
+ memset(info, 0, sizeof(*info));
+ info->channel = 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)
+{
+ snd_pcm_channel_info_t info;
+ int res;
+
+ if (copy_from_user(&info, _info, sizeof(info)))
+ return -EFAULT;
+ res = snd_pcm_channel_info(substream, &info);
if (res < 0)
return res;
if (copy_to_user(_info, &info, sizeof(info)))
@@ -1032,7 +1046,13 @@ static struct action_ops snd_pcm_action_suspend = {
*/
int snd_pcm_suspend(snd_pcm_substream_t *substream)
{
- return snd_pcm_action(&snd_pcm_action_suspend, substream, 0);
+ int err;
+ unsigned long flags;
+
+ snd_pcm_stream_lock_irqsave(substream, flags);
+ err = snd_pcm_action(&snd_pcm_action_suspend, substream, 0);
+ snd_pcm_stream_unlock_irqrestore(substream, flags);
+ return err;
}
/**
@@ -1051,11 +1071,8 @@ int snd_pcm_suspend_all(snd_pcm_t *pcm)
/* FIXME: the open/close code should lock this as well */
if (substream->runtime == NULL)
continue;
- snd_pcm_stream_lock(substream);
- if (substream->runtime->status->state != SNDRV_PCM_STATE_SUSPENDED)
- err = snd_pcm_suspend(substream);
- snd_pcm_stream_unlock(substream);
- if (err < 0)
+ err = snd_pcm_suspend(substream);
+ if (err < 0 && err != -EBUSY)
return err;
}
}
@@ -2440,7 +2457,7 @@ static int snd_pcm_common_ioctl1(snd_pcm_substream_t *substream,
case SNDRV_PCM_IOCTL_STATUS:
return snd_pcm_status_user(substream, arg);
case SNDRV_PCM_IOCTL_CHANNEL_INFO:
- return snd_pcm_channel_info(substream, arg);
+ return snd_pcm_channel_info_user(substream, arg);
case SNDRV_PCM_IOCTL_PREPARE:
return snd_pcm_prepare(substream);
case SNDRV_PCM_IOCTL_RESET:
@@ -2640,40 +2657,28 @@ static int snd_pcm_capture_ioctl1(snd_pcm_substream_t *substream,
return snd_pcm_common_ioctl1(substream, cmd, arg);
}
-static int snd_pcm_playback_ioctl(struct inode *inode, 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;
- int err;
pcm_file = file->private_data;
if (((cmd >> 8) & 0xff) != 'A')
return -ENOTTY;
- /* FIXME: need to unlock BKL to allow preemption */
- unlock_kernel();
- err = snd_pcm_playback_ioctl1(pcm_file->substream, cmd, (void __user *)arg);
- lock_kernel();
- return err;
+ return snd_pcm_playback_ioctl1(pcm_file->substream, cmd, (void __user *)arg);
}
-static int snd_pcm_capture_ioctl(struct inode *inode, 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;
- int err;
pcm_file = file->private_data;
if (((cmd >> 8) & 0xff) != 'A')
return -ENOTTY;
- /* FIXME: need to unlock BKL to allow preemption */
- unlock_kernel();
- err = snd_pcm_capture_ioctl1(pcm_file->substream, cmd, (void __user *)arg);
- lock_kernel();
- return err;
+ return snd_pcm_capture_ioctl1(pcm_file->substream, cmd, (void __user *)arg);
}
int snd_pcm_kernel_playback_ioctl(snd_pcm_substream_t *substream,
@@ -2683,7 +2688,7 @@ int snd_pcm_kernel_playback_ioctl(snd_pcm_substream_t *substream,
int result;
fs = snd_enter_user();
- result = snd_pcm_playback_ioctl1(substream, cmd, arg);
+ result = snd_pcm_playback_ioctl1(substream, cmd, (void __user *)arg);
snd_leave_user(fs);
return result;
}
@@ -2695,7 +2700,7 @@ int snd_pcm_kernel_capture_ioctl(snd_pcm_substream_t *substream,
int result;
fs = snd_enter_user();
- result = snd_pcm_capture_ioctl1(substream, cmd, arg);
+ result = snd_pcm_capture_ioctl1(substream, cmd, (void __user *)arg);
snd_leave_user(fs);
return result;
}
@@ -3103,8 +3108,8 @@ int snd_pcm_lib_mmap_iomem(snd_pcm_substream_t *substream, struct vm_area_struct
area->vm_flags |= VM_IO;
size = area->vm_end - area->vm_start;
offset = area->vm_pgoff << PAGE_SHIFT;
- if (io_remap_page_range(area, area->vm_start,
- substream->runtime->dma_addr + offset,
+ if (io_remap_pfn_range(area, area->vm_start,
+ (substream->runtime->dma_addr + offset) >> PAGE_SHIFT,
size, area->vm_page_prot))
return -EAGAIN;
atomic_inc(&substream->runtime->mmap_count);
@@ -3198,6 +3203,15 @@ static int snd_pcm_fasync(int fd, struct file * file, int on)
}
/*
+ * ioctl32 compat
+ */
+#ifdef CONFIG_COMPAT
+#include "pcm_compat.c"
+#else
+#define snd_pcm_ioctl_compat NULL
+#endif
+
+/*
* To be removed helpers to keep binary compatibility
*/
@@ -3318,7 +3332,8 @@ static struct file_operations snd_pcm_f_ops_playback = {
.open = snd_pcm_open,
.release = snd_pcm_release,
.poll = snd_pcm_playback_poll,
- .ioctl = snd_pcm_playback_ioctl,
+ .unlocked_ioctl = snd_pcm_playback_ioctl,
+ .compat_ioctl = snd_pcm_ioctl_compat,
.mmap = snd_pcm_mmap,
.fasync = snd_pcm_fasync,
};
@@ -3330,7 +3345,8 @@ static struct file_operations snd_pcm_f_ops_capture = {
.open = snd_pcm_open,
.release = snd_pcm_release,
.poll = snd_pcm_capture_poll,
- .ioctl = snd_pcm_capture_ioctl,
+ .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/rawmidi.c b/sound/core/rawmidi.c
index 0624ff970cb8c..edba4118271c7 100644
--- a/sound/core/rawmidi.c
+++ b/sound/core/rawmidi.c
@@ -29,6 +29,8 @@
#include <linux/time.h>
#include <linux/wait.h>
#include <linux/moduleparam.h>
+#include <linux/delay.h>
+#include <linux/wait.h>
#include <sound/rawmidi.h>
#include <sound/info.h>
#include <sound/control.h>
@@ -83,11 +85,34 @@ static inline int snd_rawmidi_ready_append(snd_rawmidi_substream_t * substream,
(!substream->append || runtime->avail >= count);
}
-static int snd_rawmidi_init(snd_rawmidi_substream_t *substream)
+static void snd_rawmidi_input_event_tasklet(unsigned long data)
{
- snd_rawmidi_runtime_t *runtime = substream->runtime;
+ snd_rawmidi_substream_t *substream = (snd_rawmidi_substream_t *)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;
+ substream->ops->trigger(substream, 1);
+}
+
+static int snd_rawmidi_runtime_create(snd_rawmidi_substream_t * substream)
+{
+ snd_rawmidi_runtime_t *runtime;
+
+ if ((runtime = kcalloc(1, sizeof(*runtime), GFP_KERNEL)) == NULL)
+ return -ENOMEM;
spin_lock_init(&runtime->lock);
init_waitqueue_head(&runtime->sleep);
+ if (substream->stream == SNDRV_RAWMIDI_STREAM_INPUT)
+ tasklet_init(&runtime->tasklet,
+ snd_rawmidi_input_event_tasklet,
+ (unsigned long)substream);
+ else
+ tasklet_init(&runtime->tasklet,
+ snd_rawmidi_output_trigger_tasklet,
+ (unsigned long)substream);
runtime->event = NULL;
runtime->buffer_size = PAGE_SIZE;
runtime->avail_min = 1;
@@ -95,32 +120,53 @@ static int snd_rawmidi_init(snd_rawmidi_substream_t *substream)
runtime->avail = 0;
else
runtime->avail = runtime->buffer_size;
- if ((runtime->buffer = kmalloc(runtime->buffer_size, GFP_KERNEL)) == NULL)
+ if ((runtime->buffer = kmalloc(runtime->buffer_size, GFP_KERNEL)) == NULL) {
+ kfree(runtime);
return -ENOMEM;
+ }
runtime->appl_ptr = runtime->hw_ptr = 0;
+ substream->runtime = runtime;
return 0;
}
-static int snd_rawmidi_done_buffer(snd_rawmidi_runtime_t *runtime)
+static int snd_rawmidi_runtime_free(snd_rawmidi_substream_t * substream)
{
- if (runtime->buffer) {
- kfree(runtime->buffer);
- runtime->buffer = NULL;
- }
+ snd_rawmidi_runtime_t *runtime = substream->runtime;
+
+ kfree(runtime->buffer);
+ kfree(runtime);
+ substream->runtime = NULL;
return 0;
}
+static inline void snd_rawmidi_output_trigger(snd_rawmidi_substream_t * substream, int up)
+{
+ if (up) {
+ tasklet_hi_schedule(&substream->runtime->tasklet);
+ } else {
+ tasklet_kill(&substream->runtime->tasklet);
+ substream->ops->trigger(substream, 0);
+ }
+}
+
+static void snd_rawmidi_input_trigger(snd_rawmidi_substream_t * 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)
{
+ unsigned long flags;
snd_rawmidi_runtime_t *runtime = substream->runtime;
- substream->ops->trigger(substream, 0);
- runtime->trigger = 0;
+ snd_rawmidi_output_trigger(substream, 0);
runtime->drain = 0;
- /* interrupts are not enabled at this moment,
- so spinlock is not required */
+ spin_lock_irqsave(&runtime->lock, flags);
runtime->appl_ptr = runtime->hw_ptr = 0;
runtime->avail = runtime->buffer_size;
+ spin_unlock_irqrestore(&runtime->lock, flags);
return 0;
}
@@ -132,27 +178,22 @@ int snd_rawmidi_drain_output(snd_rawmidi_substream_t * substream)
err = 0;
runtime->drain = 1;
- while (runtime->avail < runtime->buffer_size) {
- timeout = interruptible_sleep_on_timeout(&runtime->sleep, 10 * HZ);
- if (signal_pending(current)) {
- err = -ERESTARTSYS;
- break;
- }
- if (runtime->avail < runtime->buffer_size && !timeout) {
- snd_printk(KERN_WARNING "rawmidi drain error (avail = %li, buffer_size = %li)\n", (long)runtime->avail, (long)runtime->buffer_size);
- err = -EIO;
- break;
- }
+ timeout = wait_event_interruptible_timeout(runtime->sleep,
+ (runtime->avail >= runtime->buffer_size),
+ 10*HZ);
+ if (signal_pending(current))
+ err = -ERESTARTSYS;
+ if (runtime->avail < runtime->buffer_size && !timeout) {
+ snd_printk(KERN_WARNING "rawmidi drain error (avail = %li, buffer_size = %li)\n", (long)runtime->avail, (long)runtime->buffer_size);
+ err = -EIO;
}
runtime->drain = 0;
if (err != -ERESTARTSYS) {
/* we need wait a while to make sure that Tx FIFOs are empty */
if (substream->ops->drain)
substream->ops->drain(substream);
- else {
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(HZ / 20);
- }
+ else
+ msleep(50);
snd_rawmidi_drop_output(substream);
}
return err;
@@ -160,14 +201,15 @@ int snd_rawmidi_drain_output(snd_rawmidi_substream_t * substream)
int snd_rawmidi_drain_input(snd_rawmidi_substream_t * substream)
{
+ unsigned long flags;
snd_rawmidi_runtime_t *runtime = substream->runtime;
- substream->ops->trigger(substream, 0);
- runtime->trigger = 0;
+ snd_rawmidi_input_trigger(substream, 0);
runtime->drain = 0;
- /* interrupts aren't enabled at this moment, so spinlock isn't needed */
+ spin_lock_irqsave(&runtime->lock, flags);
runtime->appl_ptr = runtime->hw_ptr = 0;
runtime->avail = 0;
+ spin_unlock_irqrestore(&runtime->lock, flags);
return 0;
}
@@ -176,7 +218,7 @@ int snd_rawmidi_kernel_open(int cardnum, int device, int subdevice,
{
snd_rawmidi_t *rmidi;
struct list_head *list1, *list2;
- snd_rawmidi_substream_t *sinput, *soutput;
+ snd_rawmidi_substream_t *sinput = NULL, *soutput = NULL;
snd_rawmidi_runtime_t *input = NULL, *output = NULL;
int err;
@@ -267,20 +309,11 @@ int snd_rawmidi_kernel_open(int cardnum, int device, int subdevice,
list2 = list2->next;
}
if (mode & SNDRV_RAWMIDI_LFLG_INPUT) {
- input = kcalloc(1, sizeof(*input), GFP_KERNEL);
- if (input == NULL) {
- err = -ENOMEM;
- goto __error;
- }
- sinput->runtime = input;
- if (snd_rawmidi_init(sinput) < 0) {
- err = -ENOMEM;
+ if ((err = snd_rawmidi_runtime_create(sinput)) < 0)
goto __error;
- }
- if ((err = sinput->ops->open(sinput)) < 0) {
- sinput->runtime = NULL;
+ input = sinput->runtime;
+ if ((err = sinput->ops->open(sinput)) < 0)
goto __error;
- }
sinput->opened = 1;
rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substream_opened++;
} else {
@@ -289,26 +322,15 @@ int snd_rawmidi_kernel_open(int cardnum, int device, int subdevice,
if (mode & SNDRV_RAWMIDI_LFLG_OUTPUT) {
if (soutput->opened)
goto __skip_output;
- output = kcalloc(1, sizeof(*output), GFP_KERNEL);
- if (output == NULL) {
- err = -ENOMEM;
- goto __error;
- }
- soutput->runtime = output;
- if (snd_rawmidi_init(soutput) < 0) {
- if (mode & SNDRV_RAWMIDI_LFLG_INPUT) {
+ if ((err = snd_rawmidi_runtime_create(soutput)) < 0) {
+ if (mode & SNDRV_RAWMIDI_LFLG_INPUT)
sinput->ops->close(sinput);
- sinput->runtime = NULL;
- }
- err = -ENOMEM;
goto __error;
}
+ output = soutput->runtime;
if ((err = soutput->ops->open(soutput)) < 0) {
- if (mode & SNDRV_RAWMIDI_LFLG_INPUT) {
+ if (mode & SNDRV_RAWMIDI_LFLG_INPUT)
sinput->ops->close(sinput);
- sinput->runtime = NULL;
- }
- soutput->runtime = NULL;
goto __error;
}
__skip_output:
@@ -331,14 +353,10 @@ int snd_rawmidi_kernel_open(int cardnum, int device, int subdevice,
return 0;
__error:
- if (input != NULL) {
- snd_rawmidi_done_buffer(input);
- kfree(input);
- }
- if (output != NULL) {
- snd_rawmidi_done_buffer(output);
- kfree(output);
- }
+ if (input != NULL)
+ snd_rawmidi_runtime_free(sinput);
+ if (output != NULL)
+ snd_rawmidi_runtime_free(soutput);
module_put(rmidi->card->module);
if (!(mode & SNDRV_RAWMIDI_LFLG_NOOPENLOCK))
up(&rmidi->open_mutex);
@@ -465,14 +483,11 @@ int snd_rawmidi_kernel_release(snd_rawmidi_file_t * rfile)
substream = rfile->input;
rfile->input = NULL;
runtime = substream->runtime;
- runtime->trigger = 0;
- substream->ops->trigger(substream, 0);
+ snd_rawmidi_input_trigger(substream, 0);
substream->ops->close(substream);
- snd_rawmidi_done_buffer(runtime);
if (runtime->private_free != NULL)
runtime->private_free(substream);
- kfree(runtime);
- substream->runtime = NULL;
+ snd_rawmidi_runtime_free(substream);
substream->opened = 0;
rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substream_opened--;
}
@@ -487,13 +502,11 @@ int snd_rawmidi_kernel_release(snd_rawmidi_file_t * rfile)
snd_rawmidi_kernel_write(substream, &buf, 1);
}
if (snd_rawmidi_drain_output(substream) == -ERESTARTSYS)
- substream->ops->trigger(substream, 0);
+ snd_rawmidi_output_trigger(substream, 0);
substream->ops->close(substream);
- snd_rawmidi_done_buffer(runtime);
if (runtime->private_free != NULL)
runtime->private_free(substream);
- kfree(runtime);
- substream->runtime = NULL;
+ snd_rawmidi_runtime_free(substream);
substream->opened = 0;
substream->append = 0;
}
@@ -673,8 +686,7 @@ static int snd_rawmidi_input_status(snd_rawmidi_substream_t * substream,
return 0;
}
-static inline int _snd_rawmidi_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
+static long snd_rawmidi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
snd_rawmidi_file_t *rfile;
void __user *argp = (void __user *)arg;
@@ -784,17 +796,6 @@ static inline int _snd_rawmidi_ioctl(struct inode *inode, struct file *file,
return -ENOTTY;
}
-/* FIXME: need to unlock BKL to allow preemption */
-static int snd_rawmidi_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- int err;
- unlock_kernel();
- err = _snd_rawmidi_ioctl(inode, file, cmd, arg);
- lock_kernel();
- return err;
-}
-
static int snd_rawmidi_control_ioctl(snd_card_t * card,
snd_ctl_file_t * control,
unsigned int cmd,
@@ -887,7 +888,7 @@ int snd_rawmidi_receive(snd_rawmidi_substream_t * substream, const unsigned char
count1 = count;
if (count1 > (int)(runtime->buffer_size - runtime->avail)) {
count1 = runtime->buffer_size - runtime->avail;
- runtime->xruns = count - count1;
+ runtime->xruns += count - count1;
}
if (count1 > 0) {
memcpy(runtime->buffer, buffer, count1);
@@ -897,13 +898,13 @@ int snd_rawmidi_receive(snd_rawmidi_substream_t * substream, const unsigned char
}
}
}
- if (result > 0 && runtime->event == NULL) {
- if (snd_rawmidi_ready(substream))
+ if (result > 0) {
+ if (runtime->event)
+ tasklet_hi_schedule(&runtime->tasklet);
+ else if (snd_rawmidi_ready(substream))
wake_up(&runtime->sleep);
}
spin_unlock_irqrestore(&runtime->lock, flags);
- if (result > 0 && runtime->event)
- runtime->event(substream);
return result;
}
@@ -925,7 +926,8 @@ static long snd_rawmidi_kernel_read1(snd_rawmidi_substream_t *substream,
memcpy(buf + result, runtime->buffer + runtime->appl_ptr, count1);
} else {
spin_unlock_irqrestore(&runtime->lock, flags);
- if (copy_to_user(buf + result, runtime->buffer + runtime->appl_ptr, count1)) {
+ if (copy_to_user((char __user *)buf + result,
+ runtime->buffer + runtime->appl_ptr, count1)) {
return result > 0 ? result : -EFAULT;
}
spin_lock_irqsave(&runtime->lock, flags);
@@ -942,8 +944,7 @@ static long snd_rawmidi_kernel_read1(snd_rawmidi_substream_t *substream,
long snd_rawmidi_kernel_read(snd_rawmidi_substream_t *substream, unsigned char *buf, long count)
{
- substream->runtime->trigger = 1;
- substream->ops->trigger(substream, 1);
+ snd_rawmidi_input_trigger(substream, 1);
return snd_rawmidi_kernel_read1(substream, buf, count, 1);
}
@@ -960,8 +961,7 @@ static ssize_t snd_rawmidi_read(struct file *file, char __user *buf, size_t coun
if (substream == NULL)
return -EIO;
runtime = substream->runtime;
- runtime->trigger = 1;
- substream->ops->trigger(substream, 1);
+ snd_rawmidi_input_trigger(substream, 1);
result = 0;
while (count > 0) {
spin_lock_irq(&runtime->lock);
@@ -984,7 +984,7 @@ static ssize_t snd_rawmidi_read(struct file *file, char __user *buf, size_t coun
spin_lock_irq(&runtime->lock);
}
spin_unlock_irq(&runtime->lock);
- count1 = snd_rawmidi_kernel_read1(substream, buf, count, 0);
+ count1 = snd_rawmidi_kernel_read1(substream, (unsigned char *)buf, count, 0);
if (count1 < 0)
return result > 0 ? result : count1;
result += count1;
@@ -1012,8 +1012,6 @@ int snd_rawmidi_transmit_empty(snd_rawmidi_substream_t * substream)
}
spin_lock_irqsave(&runtime->lock, flags);
result = runtime->avail >= runtime->buffer_size;
- if (result)
- runtime->trigger = 1;
spin_unlock_irqrestore(&runtime->lock, flags);
return result;
}
@@ -1046,7 +1044,6 @@ int snd_rawmidi_transmit_peek(snd_rawmidi_substream_t * substream, unsigned char
spin_lock_irqsave(&runtime->lock, flags);
if (runtime->avail >= runtime->buffer_size) {
/* warning: lowlevel layer MUST trigger down the hardware */
- runtime->trigger = 0;
goto __skip;
}
if (count == 1) { /* special case, faster code */
@@ -1061,8 +1058,12 @@ int snd_rawmidi_transmit_peek(snd_rawmidi_substream_t * substream, unsigned char
memcpy(buffer, runtime->buffer + runtime->hw_ptr, count1);
count -= count1;
result += count1;
- if (count > 0)
+ if (count > 0) {
+ if (count > (int)(runtime->buffer_size - runtime->avail - count1))
+ count = runtime->buffer_size - runtime->avail - count1;
memcpy(buffer + count1, runtime->buffer, count);
+ result += count;
+ }
}
__skip:
spin_unlock_irqrestore(&runtime->lock, flags);
@@ -1095,15 +1096,11 @@ int snd_rawmidi_transmit_ack(snd_rawmidi_substream_t * substream, int count)
runtime->hw_ptr %= runtime->buffer_size;
runtime->avail += count;
substream->bytes += count;
- if (runtime->drain)
- wake_up(&runtime->sleep);
- else
- if (count > 0 && runtime->event == NULL)
- if (snd_rawmidi_ready(substream))
- wake_up(&runtime->sleep);
+ if (count > 0) {
+ if (runtime->drain || snd_rawmidi_ready(substream))
+ wake_up(&runtime->sleep);
+ }
spin_unlock_irqrestore(&runtime->lock, flags);
- if (count > 0 && runtime->event)
- runtime->event(substream);
return count;
}
@@ -1152,7 +1149,8 @@ static long snd_rawmidi_kernel_write1(snd_rawmidi_substream_t * substream, const
memcpy(runtime->buffer + runtime->appl_ptr, buf, count1);
} else {
spin_unlock_irqrestore(&runtime->lock, flags);
- if (copy_from_user(runtime->buffer + runtime->appl_ptr, buf, count1)) {
+ if (copy_from_user(runtime->buffer + runtime->appl_ptr,
+ (char __user *)buf, count1)) {
spin_lock_irqsave(&runtime->lock, flags);
result = result > 0 ? result : -EFAULT;
goto __end;
@@ -1167,12 +1165,10 @@ static long snd_rawmidi_kernel_write1(snd_rawmidi_substream_t * substream, const
count -= count1;
}
__end:
- if (result > 0)
- runtime->trigger = 1;
count1 = runtime->avail < runtime->buffer_size;
spin_unlock_irqrestore(&runtime->lock, flags);
if (count1)
- substream->ops->trigger(substream, 1);
+ snd_rawmidi_output_trigger(substream, 1);
return result;
}
@@ -1217,7 +1213,7 @@ static ssize_t snd_rawmidi_write(struct file *file, const char __user *buf, size
spin_lock_irq(&runtime->lock);
}
spin_unlock_irq(&runtime->lock);
- count1 = snd_rawmidi_kernel_write1(substream, buf, count, 0);
+ count1 = snd_rawmidi_kernel_write1(substream, (unsigned char *)buf, count, 0);
if (count1 < 0)
return result > 0 ? result : count1;
result += count1;
@@ -1257,8 +1253,7 @@ static unsigned int snd_rawmidi_poll(struct file *file, poll_table * wait)
rfile = file->private_data;
if (rfile->input != NULL) {
runtime = rfile->input->runtime;
- runtime->trigger = 1;
- rfile->input->ops->trigger(rfile->input, 1);
+ snd_rawmidi_input_trigger(rfile->input, 1);
poll_wait(file, &runtime->sleep, wait);
}
if (rfile->output != NULL) {
@@ -1278,6 +1273,14 @@ static unsigned int snd_rawmidi_poll(struct file *file, poll_table * wait)
}
/*
+ */
+#ifdef CONFIG_COMPAT
+#include "rawmidi_compat.c"
+#else
+#define snd_rawmidi_ioctl_compat NULL
+#endif
+
+/*
*/
@@ -1347,7 +1350,8 @@ static struct file_operations snd_rawmidi_f_ops =
.open = snd_rawmidi_open,
.release = snd_rawmidi_release,
.poll = snd_rawmidi_poll,
- .ioctl = snd_rawmidi_ioctl,
+ .unlocked_ioctl = snd_rawmidi_ioctl,
+ .compat_ioctl = snd_rawmidi_ioctl_compat,
};
static snd_minor_t snd_rawmidi_reg =
@@ -1628,6 +1632,7 @@ static int __init alsa_rawmidi_init(void)
{
snd_ctl_register_ioctl(snd_rawmidi_control_ioctl);
+ snd_ctl_register_ioctl_compat(snd_rawmidi_control_ioctl);
#ifdef CONFIG_SND_OSSEMUL
{ int i;
/* check device map table */
@@ -1649,6 +1654,7 @@ static int __init alsa_rawmidi_init(void)
static void __exit alsa_rawmidi_exit(void)
{
snd_ctl_unregister_ioctl(snd_rawmidi_control_ioctl);
+ snd_ctl_unregister_ioctl_compat(snd_rawmidi_control_ioctl);
}
module_init(alsa_rawmidi_init)
diff --git a/sound/core/rawmidi_compat.c b/sound/core/rawmidi_compat.c
new file mode 100644
index 0000000000000..d97631c3f3ad1
--- /dev/null
+++ b/sound/core/rawmidi_compat.c
@@ -0,0 +1,120 @@
+/*
+ * 32bit -> 64bit ioctl wrapper for raw MIDI API
+ * Copyright (c) by Takashi Iwai <tiwai@suse.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* This file included from rawmidi.c */
+
+#include <linux/compat.h>
+
+struct sndrv_rawmidi_params32 {
+ s32 stream;
+ u32 buffer_size;
+ u32 avail_min;
+ unsigned int no_active_sensing; /* avoid bit-field */
+ unsigned char reserved[16];
+} __attribute__((packed));
+
+static int snd_rawmidi_ioctl_params_compat(snd_rawmidi_file_t *rfile,
+ struct sndrv_rawmidi_params32 __user *src)
+{
+ snd_rawmidi_params_t params;
+ unsigned int val;
+
+ if (rfile->output == NULL)
+ return -EINVAL;
+ if (get_user(params.stream, &src->stream) ||
+ get_user(params.buffer_size, &src->buffer_size) ||
+ get_user(params.avail_min, &src->avail_min) ||
+ get_user(val, &src->no_active_sensing))
+ return -EFAULT;
+ params.no_active_sensing = val;
+ switch (params.stream) {
+ case SNDRV_RAWMIDI_STREAM_OUTPUT:
+ return snd_rawmidi_output_params(rfile->output, &params);
+ case SNDRV_RAWMIDI_STREAM_INPUT:
+ return snd_rawmidi_input_params(rfile->input, &params);
+ }
+ return -EINVAL;
+}
+
+struct sndrv_rawmidi_status32 {
+ s32 stream;
+ struct compat_timespec tstamp;
+ u32 avail;
+ u32 xruns;
+ unsigned char reserved[16];
+} __attribute__((packed));
+
+static int snd_rawmidi_ioctl_status_compat(snd_rawmidi_file_t *rfile,
+ struct sndrv_rawmidi_status32 __user *src)
+{
+ int err;
+ snd_rawmidi_status_t status;
+
+ if (rfile->output == NULL)
+ return -EINVAL;
+ if (get_user(status.stream, &src->stream))
+ return -EFAULT;
+
+ switch (status.stream) {
+ case SNDRV_RAWMIDI_STREAM_OUTPUT:
+ err = snd_rawmidi_output_status(rfile->output, &status);
+ break;
+ case SNDRV_RAWMIDI_STREAM_INPUT:
+ err = snd_rawmidi_input_status(rfile->input, &status);
+ break;
+ default:
+ return -EINVAL;
+ }
+ if (err < 0)
+ return err;
+
+ if (put_user(status.tstamp.tv_sec, &src->tstamp.tv_sec) ||
+ put_user(status.tstamp.tv_nsec, &src->tstamp.tv_nsec) ||
+ put_user(status.avail, &src->avail) ||
+ put_user(status.xruns, &src->xruns))
+ return -EFAULT;
+
+ return 0;
+}
+
+enum {
+ SNDRV_RAWMIDI_IOCTL_PARAMS32 = _IOWR('W', 0x10, struct sndrv_rawmidi_params32),
+ SNDRV_RAWMIDI_IOCTL_STATUS32 = _IOWR('W', 0x20, struct sndrv_rawmidi_status32),
+};
+
+static long snd_rawmidi_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ snd_rawmidi_file_t *rfile;
+ void __user *argp = compat_ptr(arg);
+
+ rfile = file->private_data;
+ switch (cmd) {
+ case SNDRV_RAWMIDI_IOCTL_PVERSION:
+ case SNDRV_RAWMIDI_IOCTL_INFO:
+ case SNDRV_RAWMIDI_IOCTL_DROP:
+ case SNDRV_RAWMIDI_IOCTL_DRAIN:
+ return snd_rawmidi_ioctl(file, cmd, (unsigned long)argp);
+ case SNDRV_RAWMIDI_IOCTL_PARAMS32:
+ return snd_rawmidi_ioctl_params_compat(rfile, argp);
+ case SNDRV_RAWMIDI_IOCTL_STATUS32:
+ return snd_rawmidi_ioctl_status_compat(rfile, argp);
+ }
+ return -ENOIOCTLCMD;
+}
diff --git a/sound/core/rtctimer.c b/sound/core/rtctimer.c
index e957b13960f37..bd5d584d284d5 100644
--- a/sound/core/rtctimer.c
+++ b/sound/core/rtctimer.c
@@ -183,4 +183,6 @@ MODULE_PARM_DESC(rtctimer_freq, "timer frequency in Hz");
MODULE_LICENSE("GPL");
+MODULE_ALIAS("snd-timer-" __stringify(SNDRV_TIMER_GLOBAL_RTC));
+
#endif /* CONFIG_RTC || CONFIG_RTC_MODULE */
diff --git a/sound/core/seq/oss/seq_oss.c b/sound/core/seq/oss/seq_oss.c
index 53eb754897069..4c0558c0a8b4e 100644
--- a/sound/core/seq/oss/seq_oss.c
+++ b/sound/core/seq/oss/seq_oss.c
@@ -59,7 +59,7 @@ static int odev_open(struct inode *inode, struct file *file);
static int 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);
static ssize_t odev_write(struct file *file, const char __user *buf, size_t count, loff_t *offset);
-static int odev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);
+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);
@@ -177,20 +177,20 @@ odev_write(struct file *file, const char __user *buf, size_t count, loff_t *offs
return snd_seq_oss_write(dp, buf, count, file);
}
-static int
-odev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+static long
+odev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
seq_oss_devinfo_t *dp;
- int err;
dp = file->private_data;
snd_assert(dp != NULL, return -EIO);
- /* FIXME: need to unlock BKL to allow preemption */
- unlock_kernel();
- err = snd_seq_oss_ioctl(dp, cmd, arg);
- lock_kernel();
- return err;
+ return snd_seq_oss_ioctl(dp, cmd, arg);
}
+#ifdef CONFIG_COMPAT
+#define odev_ioctl_compat odev_ioctl
+#else
+#define odev_ioctl_compat NULL
+#endif
static unsigned int
odev_poll(struct file *file, poll_table * wait)
@@ -213,7 +213,8 @@ static struct file_operations seq_oss_f_ops =
.open = odev_open,
.release = odev_release,
.poll = odev_poll,
- .ioctl = odev_ioctl,
+ .unlocked_ioctl = odev_ioctl,
+ .compat_ioctl = odev_ioctl_compat,
};
static snd_minor_t seq_oss_reg = {
diff --git a/sound/core/seq/oss/seq_oss_init.c b/sound/core/seq/oss/seq_oss_init.c
index 9f245c9994187..bac4b4f1a94ec 100644
--- a/sound/core/seq/oss/seq_oss_init.c
+++ b/sound/core/seq/oss/seq_oss_init.c
@@ -66,10 +66,17 @@ 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_client_info_t *info;
+ snd_seq_port_info_t *port;
snd_seq_port_callback_t port_callback;
+ info = kmalloc(sizeof(*info), GFP_KERNEL);
+ port = kmalloc(sizeof(*port), GFP_KERNEL);
+ if (!info || !port) {
+ rc = -ENOMEM;
+ goto __error;
+ }
+
/* create ALSA client */
memset(&callback, 0, sizeof(callback));
@@ -79,38 +86,38 @@ snd_seq_oss_create_client(void)
rc = snd_seq_create_kernel_client(NULL, SNDRV_SEQ_CLIENT_OSS, &callback);
if (rc < 0)
- return rc;
+ 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");
+ 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);
+ rc = call_ctl(SNDRV_SEQ_IOCTL_SET_CLIENT_INFO, info);
/* look up midi devices */
snd_seq_oss_midi_lookup_ports(system_client);
/* create annoucement receiver port */
- memset(&port, 0, sizeof(port));
- strcpy(port.name, "Receiver");
- port.addr.client = system_client;
- port.capability = SNDRV_SEQ_PORT_CAP_WRITE; /* receive only */
- port.type = 0;
+ memset(port, 0, sizeof(*port));
+ strcpy(port->name, "Receiver");
+ port->addr.client = system_client;
+ port->capability = SNDRV_SEQ_PORT_CAP_WRITE; /* receive only */
+ port->type = 0;
memset(&port_callback, 0, sizeof(port_callback));
/* don't set port_callback.owner here. otherwise the module counter
* is incremented and we can no longer release the module..
*/
port_callback.event_input = receive_announce;
- port.kernel = &port_callback;
+ port->kernel = &port_callback;
- call_ctl(SNDRV_SEQ_IOCTL_CREATE_PORT, &port);
- if ((system_port = port.addr.port) >= 0) {
+ call_ctl(SNDRV_SEQ_IOCTL_CREATE_PORT, port);
+ if ((system_port = port->addr.port) >= 0) {
snd_seq_port_subscribe_t subs;
memset(&subs, 0, sizeof(subs));
@@ -120,9 +127,12 @@ snd_seq_oss_create_client(void)
subs.dest.port = system_port;
call_ctl(SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT, &subs);
}
+ rc = 0;
-
- return 0;
+ __error:
+ kfree(port);
+ kfree(info);
+ return rc;
}
diff --git a/sound/core/seq/oss/seq_oss_midi.c b/sound/core/seq/oss/seq_oss_midi.c
index 60fb5fb2793af..9aece6c65dbc8 100644
--- a/sound/core/seq/oss/seq_oss_midi.c
+++ b/sound/core/seq/oss/seq_oss_midi.c
@@ -56,7 +56,7 @@ struct seq_oss_midi_t {
static int max_midi_devs;
static seq_oss_midi_t *midi_devs[SNDRV_SEQ_OSS_MAX_MIDI_DEVS];
-static spinlock_t register_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(register_lock);
/*
* prototypes
@@ -73,26 +73,27 @@ 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_system_info_t sysinfo;
- snd_seq_client_info_t clinfo;
- snd_seq_port_info_t pinfo;
- int rc;
-
- rc = snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_SYSTEM_INFO, &sysinfo);
- if (rc < 0)
- return rc;
-
- memset(&clinfo, 0, sizeof(clinfo));
- memset(&pinfo, 0, sizeof(pinfo));
- clinfo.client = -1;
- while (snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_QUERY_NEXT_CLIENT, &clinfo) == 0) {
- if (clinfo.client == client)
+ snd_seq_client_info_t *clinfo;
+ snd_seq_port_info_t *pinfo;
+
+ clinfo = kcalloc(1, sizeof(*clinfo), GFP_KERNEL);
+ pinfo = kcalloc(1, sizeof(*pinfo), GFP_KERNEL);
+ if (! clinfo || ! pinfo) {
+ kfree(clinfo);
+ kfree(pinfo);
+ return -ENOMEM;
+ }
+ clinfo->client = -1;
+ while (snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_QUERY_NEXT_CLIENT, clinfo) == 0) {
+ if (clinfo->client == client)
continue; /* ignore myself */
- pinfo.addr.client = clinfo.client;
- pinfo.addr.port = -1;
- while (snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT, &pinfo) == 0)
- snd_seq_oss_midi_check_new_port(&pinfo);
+ pinfo->addr.client = clinfo->client;
+ pinfo->addr.port = -1;
+ while (snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT, pinfo) == 0)
+ snd_seq_oss_midi_check_new_port(pinfo);
}
+ kfree(clinfo);
+ kfree(pinfo);
return 0;
}
diff --git a/sound/core/seq/oss/seq_oss_readq.c b/sound/core/seq/oss/seq_oss_readq.c
index 6d87b637759f5..0a6f2a64f6923 100644
--- a/sound/core/seq/oss/seq_oss_readq.c
+++ b/sound/core/seq/oss/seq_oss_readq.c
@@ -24,6 +24,7 @@
#include "seq_oss_event.h"
#include <sound/seq_oss_legacy.h>
#include "../seq_lock.h"
+#include <linux/wait.h>
/*
* constants
@@ -165,7 +166,9 @@ snd_seq_oss_readq_pick(seq_oss_readq_t *q, evrec_t *rec)
void
snd_seq_oss_readq_wait(seq_oss_readq_t *q)
{
- interruptible_sleep_on_timeout(&q->midi_sleep, q->pre_event_timeout);
+ wait_event_interruptible_timeout(q->midi_sleep,
+ (q->qlen > 0 || q->head == q->tail),
+ q->pre_event_timeout);
}
/*
diff --git a/sound/core/seq/oss/seq_oss_synth.c b/sound/core/seq/oss/seq_oss_synth.c
index dc44e665d2a26..638cc148706dc 100644
--- a/sound/core/seq/oss/seq_oss_synth.c
+++ b/sound/core/seq/oss/seq_oss_synth.c
@@ -75,7 +75,7 @@ static seq_oss_synth_t midi_synth_dev = {
"MIDI", /* name */
};
-static spinlock_t register_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(register_lock);
/*
* prototypes
diff --git a/sound/core/seq/oss/seq_oss_writeq.c b/sound/core/seq/oss/seq_oss_writeq.c
index 138203864e894..87f85f7ee8146 100644
--- a/sound/core/seq/oss/seq_oss_writeq.c
+++ b/sound/core/seq/oss/seq_oss_writeq.c
@@ -26,6 +26,7 @@
#include <sound/seq_oss_legacy.h>
#include "../seq_lock.h"
#include "../seq_clientmgr.h"
+#include <linux/wait.h>
/*
@@ -91,7 +92,6 @@ snd_seq_oss_writeq_sync(seq_oss_writeq_t *q)
{
seq_oss_devinfo_t *dp = q->dp;
abstime_t time;
- unsigned long flags;
time = snd_seq_oss_timer_cur_tick(dp->timer);
if (q->sync_time >= time)
@@ -115,27 +115,13 @@ snd_seq_oss_writeq_sync(seq_oss_writeq_t *q)
snd_seq_kernel_client_enqueue_blocking(dp->cseq, &ev, NULL, 0, 0);
}
- spin_lock_irqsave(&q->sync_lock, flags);
- if (! q->sync_event_put) { /* echoback event has been received */
- spin_unlock_irqrestore(&q->sync_lock, flags);
- return 0;
- }
-
- /* wait for echo event */
- spin_unlock(&q->sync_lock);
- interruptible_sleep_on_timeout(&q->sync_sleep, HZ);
- spin_lock(&q->sync_lock);
- if (signal_pending(current)) {
+ wait_event_interruptible_timeout(q->sync_sleep, ! q->sync_event_put, HZ);
+ if (signal_pending(current))
/* interrupted - return 0 to finish sync */
q->sync_event_put = 0;
- spin_unlock_irqrestore(&q->sync_lock, flags);
- return 0;
- }
- spin_unlock_irqrestore(&q->sync_lock, flags);
- if (q->sync_time >= time)
+ if (! q->sync_event_put || q->sync_time >= time)
return 0;
- else
- return 1;
+ return 1;
}
/*
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c
index 4b24a1fbc9897..d8f76afd284bc 100644
--- a/sound/core/seq/seq_clientmgr.c
+++ b/sound/core/seq/seq_clientmgr.c
@@ -37,8 +37,8 @@
#include "seq_info.h"
#include "seq_system.h"
#include <sound/seq_device.h>
-#if defined(CONFIG_SND_BIT32_EMUL) || defined(CONFIG_SND_BIT32_EMUL_MODULE)
-#include "../ioctl32/ioctl32.h"
+#ifdef CONFIG_COMPAT
+#include <linux/compat.h>
#endif
/* Client Manager
@@ -51,7 +51,7 @@
#define SNDRV_SEQ_LFLG_OUTPUT 0x0002
#define SNDRV_SEQ_LFLG_OPEN (SNDRV_SEQ_LFLG_INPUT|SNDRV_SEQ_LFLG_OUTPUT)
-static spinlock_t clients_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(clients_lock);
static DECLARE_MUTEX(register_mutex);
/*
@@ -375,7 +375,7 @@ static ssize_t snd_seq_read(struct file *file, char __user *buf, size_t count, l
if (!(snd_seq_file_flags(file) & SNDRV_SEQ_LFLG_INPUT))
return -ENXIO;
- if (verify_area(VERIFY_WRITE, buf, count))
+ if (!access_ok(VERIFY_WRITE, buf, count))
return -EFAULT;
/* check client structures are in place */
@@ -413,7 +413,7 @@ static ssize_t snd_seq_read(struct file *file, char __user *buf, size_t count, l
}
count -= sizeof(snd_seq_event_t);
buf += sizeof(snd_seq_event_t);
- err = snd_seq_expand_var_event(&cell->event, count, buf, 0, sizeof(snd_seq_event_t));
+ err = snd_seq_expand_var_event(&cell->event, count, (char *)buf, 0, sizeof(snd_seq_event_t));
if (err < 0)
break;
result += err;
@@ -1012,7 +1012,7 @@ static ssize_t snd_seq_write(struct file *file, const char __user *buf, size_t c
event.data.ext.ptr = (char*)buf + sizeof(snd_seq_event_t);
len += extlen; /* increment data length */
} else {
-#if defined(CONFIG_SND_BIT32_EMUL) || defined(CONFIG_SND_BIT32_EMUL_MODULE)
+#ifdef CONFIG_COMPAT
if (client->convert32 && snd_seq_ev_is_varusr(&event)) {
void *ptr = compat_ptr(event.data.raw32.d[1]);
event.data.ext.ptr = ptr;
@@ -2131,21 +2131,20 @@ static int snd_seq_do_ioctl(client_t *client, unsigned int cmd, void __user *arg
}
-static int snd_seq_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
+static long snd_seq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
client_t *client = (client_t *) file->private_data;
- int err;
snd_assert(client != NULL, return -ENXIO);
- /* FIXME: need to unlock BKL to allow preemption */
- unlock_kernel();
- err = snd_seq_do_ioctl(client, cmd, (void __user *) arg);
- lock_kernel();
- return err;
+ return snd_seq_do_ioctl(client, cmd, (void __user *) arg);
}
+#ifdef CONFIG_COMPAT
+#include "seq_compat.c"
+#else
+#define snd_seq_ioctl_compat NULL
+#endif
/* -------------------------------------------------------- */
@@ -2321,7 +2320,7 @@ int snd_seq_kernel_client_ctl(int clientid, unsigned int cmd, void *arg)
if (client == NULL)
return -ENXIO;
fs = snd_enter_user();
- result = snd_seq_do_ioctl(client, cmd, arg);
+ result = snd_seq_do_ioctl(client, cmd, (void __user *)arg);
snd_leave_user(fs);
return result;
}
@@ -2462,7 +2461,8 @@ static struct file_operations snd_seq_f_ops =
.open = snd_seq_open,
.release = snd_seq_release,
.poll = snd_seq_poll,
- .ioctl = snd_seq_ioctl,
+ .unlocked_ioctl = snd_seq_ioctl,
+ .compat_ioctl = snd_seq_ioctl_compat,
};
static snd_minor_t snd_seq_reg =
diff --git a/sound/core/seq/seq_compat.c b/sound/core/seq/seq_compat.c
new file mode 100644
index 0000000000000..902ad8b0c3551
--- /dev/null
+++ b/sound/core/seq/seq_compat.c
@@ -0,0 +1,137 @@
+/*
+ * 32bit -> 64bit ioctl wrapper for sequencer API
+ * Copyright (c) by Takashi Iwai <tiwai@suse.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* This file included from seq.c */
+
+#include <linux/compat.h>
+
+struct sndrv_seq_port_info32 {
+ struct sndrv_seq_addr addr; /* client/port numbers */
+ char name[64]; /* port name */
+
+ u32 capability; /* port capability bits */
+ u32 type; /* port type bits */
+ s32 midi_channels; /* channels per MIDI port */
+ s32 midi_voices; /* voices per MIDI port */
+ s32 synth_voices; /* voices per SYNTH port */
+
+ s32 read_use; /* R/O: subscribers for output (from this port) */
+ s32 write_use; /* R/O: subscribers for input (to this port) */
+
+ u32 kernel; /* reserved for kernel use (must be NULL) */
+ u32 flags; /* misc. conditioning */
+ unsigned char time_queue; /* queue # for timestamping */
+ 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)
+{
+ int err = -EFAULT;
+ snd_seq_port_info_t *data;
+ mm_segment_t fs;
+
+ data = kmalloc(sizeof(*data), GFP_KERNEL);
+ if (! data)
+ return -ENOMEM;
+
+ if (copy_from_user(data, data32, sizeof(*data32)) ||
+ get_user(data->flags, &data32->flags) ||
+ get_user(data->time_queue, &data32->time_queue))
+ goto error;
+ data->kernel = NULL;
+
+ fs = snd_enter_user();
+ err = snd_seq_do_ioctl(client, cmd, data);
+ snd_leave_user(fs);
+ if (err < 0)
+ goto error;
+
+ if (copy_to_user(data32, data, sizeof(*data32)) ||
+ put_user(data->flags, &data32->flags) ||
+ put_user(data->time_queue, &data32->time_queue))
+ err = -EFAULT;
+
+ error:
+ kfree(data);
+ return err;
+}
+
+
+
+/*
+ */
+
+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),
+};
+
+static long snd_seq_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ client_t *client = (client_t *) file->private_data;
+ void __user *argp = compat_ptr(arg);
+
+ snd_assert(client != NULL, return -ENXIO);
+
+ switch (cmd) {
+ case SNDRV_SEQ_IOCTL_PVERSION:
+ case SNDRV_SEQ_IOCTL_CLIENT_ID:
+ case SNDRV_SEQ_IOCTL_SYSTEM_INFO:
+ case SNDRV_SEQ_IOCTL_GET_CLIENT_INFO:
+ case SNDRV_SEQ_IOCTL_SET_CLIENT_INFO:
+ case SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT:
+ case SNDRV_SEQ_IOCTL_UNSUBSCRIBE_PORT:
+ case SNDRV_SEQ_IOCTL_CREATE_QUEUE:
+ case SNDRV_SEQ_IOCTL_DELETE_QUEUE:
+ case SNDRV_SEQ_IOCTL_GET_QUEUE_INFO:
+ case SNDRV_SEQ_IOCTL_SET_QUEUE_INFO:
+ case SNDRV_SEQ_IOCTL_GET_NAMED_QUEUE:
+ case SNDRV_SEQ_IOCTL_GET_QUEUE_STATUS:
+ case SNDRV_SEQ_IOCTL_GET_QUEUE_TEMPO:
+ case SNDRV_SEQ_IOCTL_SET_QUEUE_TEMPO:
+ case SNDRV_SEQ_IOCTL_GET_QUEUE_TIMER:
+ case SNDRV_SEQ_IOCTL_SET_QUEUE_TIMER:
+ case SNDRV_SEQ_IOCTL_GET_QUEUE_CLIENT:
+ case SNDRV_SEQ_IOCTL_SET_QUEUE_CLIENT:
+ case SNDRV_SEQ_IOCTL_GET_CLIENT_POOL:
+ case SNDRV_SEQ_IOCTL_SET_CLIENT_POOL:
+ case SNDRV_SEQ_IOCTL_REMOVE_EVENTS:
+ case SNDRV_SEQ_IOCTL_QUERY_SUBS:
+ case SNDRV_SEQ_IOCTL_GET_SUBSCRIPTION:
+ case SNDRV_SEQ_IOCTL_QUERY_NEXT_CLIENT:
+ case SNDRV_SEQ_IOCTL_RUNNING_MODE:
+ return snd_seq_do_ioctl(client, cmd, argp);
+ case SNDRV_SEQ_IOCTL_CREATE_PORT32:
+ return snd_seq_call_port_info_ioctl(client, SNDRV_SEQ_IOCTL_CREATE_PORT, argp);
+ case SNDRV_SEQ_IOCTL_DELETE_PORT32:
+ return snd_seq_call_port_info_ioctl(client, SNDRV_SEQ_IOCTL_DELETE_PORT, argp);
+ case SNDRV_SEQ_IOCTL_GET_PORT_INFO32:
+ return snd_seq_call_port_info_ioctl(client, SNDRV_SEQ_IOCTL_GET_PORT_INFO, argp);
+ case SNDRV_SEQ_IOCTL_SET_PORT_INFO32:
+ return snd_seq_call_port_info_ioctl(client, SNDRV_SEQ_IOCTL_SET_PORT_INFO, argp);
+ case SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT32:
+ return snd_seq_call_port_info_ioctl(client, SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT, argp);
+ }
+ return -ENOIOCTLCMD;
+}
diff --git a/sound/core/seq/seq_dummy.c b/sound/core/seq/seq_dummy.c
index 6380acfe663d7..e88967c5b93d1 100644
--- a/sound/core/seq/seq_dummy.c
+++ b/sound/core/seq/seq_dummy.c
@@ -63,6 +63,7 @@
MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
MODULE_DESCRIPTION("ALSA sequencer MIDI-through client");
MODULE_LICENSE("GPL");
+MODULE_ALIAS("snd-seq-client-" __stringify(SNDRV_SEQ_CLIENT_DUMMY));
static int ports = 1;
static int duplex = 0;
diff --git a/sound/core/seq/seq_instr.c b/sound/core/seq/seq_instr.c
index 315196768f9cc..5b40ea2ba8f4f 100644
--- a/sound/core/seq/seq_instr.c
+++ b/sound/core/seq/seq_instr.c
@@ -430,7 +430,7 @@ static int instr_put(snd_seq_kinstr_ops_t *ops,
if (ev->data.ext.len < sizeof(snd_seq_instr_header_t))
goto __return;
- if (copy_from_user(&put, ev->data.ext.ptr, sizeof(snd_seq_instr_header_t))) {
+ if (copy_from_user(&put, (void __user *)ev->data.ext.ptr, sizeof(snd_seq_instr_header_t))) {
result = -EFAULT;
goto __return;
}
@@ -466,7 +466,7 @@ 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,
- ev->data.ext.ptr + sizeof(snd_seq_instr_header_t),
+ (void __user *)ev->data.ext.ptr + sizeof(snd_seq_instr_header_t),
ev->data.ext.len - sizeof(snd_seq_instr_header_t),
atomic,
put.cmd);
@@ -513,7 +513,7 @@ static int instr_free(snd_seq_kinstr_ops_t *ops,
if (ev->data.ext.len < sizeof(snd_seq_instr_header_t))
goto __return;
- if (copy_from_user(&ifree, ev->data.ext.ptr, sizeof(snd_seq_instr_header_t))) {
+ if (copy_from_user(&ifree, (void __user *)ev->data.ext.ptr, sizeof(snd_seq_instr_header_t))) {
result = -EFAULT;
goto __return;
}
diff --git a/sound/core/seq/seq_memory.c b/sound/core/seq/seq_memory.c
index b668fbca45a94..00d841e82fbc0 100644
--- a/sound/core/seq/seq_memory.c
+++ b/sound/core/seq/seq_memory.c
@@ -90,7 +90,7 @@ int snd_seq_dump_var_event(const snd_seq_event_t *event, snd_seq_dump_func_t fun
if (event->data.ext.len & SNDRV_SEQ_EXT_USRPTR) {
char buf[32];
- char __user *curptr = event->data.ext.ptr;
+ char __user *curptr = (char __user *)event->data.ext.ptr;
while (len > 0) {
int size = sizeof(buf);
if (len < size)
@@ -134,7 +134,7 @@ static int seq_copy_in_kernel(char **bufptr, const void *src, int size)
return 0;
}
-static int seq_copy_in_user(char **bufptr, const void *src, int size)
+static int seq_copy_in_user(char __user **bufptr, const void *src, int size)
{
if (copy_to_user(*bufptr, src, size))
return -EFAULT;
@@ -158,7 +158,7 @@ int snd_seq_expand_var_event(const snd_seq_event_t *event, int count, char *buf,
if (event->data.ext.len & SNDRV_SEQ_EXT_USRPTR) {
if (! in_kernel)
return -EINVAL;
- if (copy_from_user(buf, event->data.ext.ptr, len))
+ if (copy_from_user(buf, (void __user *)event->data.ext.ptr, len))
return -EFAULT;
return newlen;
}
@@ -336,7 +336,7 @@ int snd_seq_event_dup(pool_t *pool, snd_seq_event_t *event, snd_seq_event_cell_t
tmp->event = src->event;
src = src->next;
} else if (is_usrptr) {
- if (copy_from_user(&tmp->event, buf, size)) {
+ if (copy_from_user(&tmp->event, (char __user *)buf, size)) {
err = -EFAULT;
goto __error;
}
diff --git a/sound/core/seq/seq_midi.c b/sound/core/seq/seq_midi.c
index a9957aeadc284..18247db45db65 100644
--- a/sound/core/seq/seq_midi.c
+++ b/sound/core/seq/seq_midi.c
@@ -289,8 +289,8 @@ snd_seq_midisynth_register_port(snd_seq_device_t *dev)
{
seq_midisynth_client_t *client;
seq_midisynth_t *msynth, *ms;
- snd_seq_port_info_t port;
- snd_rawmidi_info_t info;
+ snd_seq_port_info_t *port;
+ snd_rawmidi_info_t *info;
int newclient = 0;
unsigned int p, ports;
snd_seq_client_callback_t callbacks;
@@ -300,20 +300,25 @@ snd_seq_midisynth_register_port(snd_seq_device_t *dev)
unsigned int input_count = 0, output_count = 0;
snd_assert(card != NULL && device >= 0 && device < SNDRV_RAWMIDI_DEVICES, return -EINVAL);
- info.device = device;
- info.stream = SNDRV_RAWMIDI_STREAM_OUTPUT;
- info.subdevice = 0;
- if (snd_rawmidi_info_select(card, &info) >= 0)
- output_count = info.subdevices_count;
- info.stream = SNDRV_RAWMIDI_STREAM_INPUT;
- if (snd_rawmidi_info_select(card, &info) >= 0) {
- input_count = info.subdevices_count;
+ info = kmalloc(sizeof(*info), GFP_KERNEL);
+ if (! info)
+ return -ENOMEM;
+ info->device = device;
+ info->stream = SNDRV_RAWMIDI_STREAM_OUTPUT;
+ info->subdevice = 0;
+ if (snd_rawmidi_info_select(card, info) >= 0)
+ output_count = info->subdevices_count;
+ info->stream = SNDRV_RAWMIDI_STREAM_INPUT;
+ if (snd_rawmidi_info_select(card, info) >= 0) {
+ input_count = info->subdevices_count;
}
ports = output_count;
if (ports < input_count)
ports = input_count;
- if (ports == 0)
+ if (ports == 0) {
+ kfree(info);
return -ENODEV;
+ }
if (ports > (256 / SNDRV_RAWMIDI_DEVICES))
ports = 256 / SNDRV_RAWMIDI_DEVICES;
@@ -324,6 +329,7 @@ snd_seq_midisynth_register_port(snd_seq_device_t *dev)
client = kcalloc(1, sizeof(*client), GFP_KERNEL);
if (client == NULL) {
up(&register_mutex);
+ kfree(info);
return -ENOMEM;
}
memset(&callbacks, 0, sizeof(callbacks));
@@ -333,14 +339,16 @@ snd_seq_midisynth_register_port(snd_seq_device_t *dev)
if (client->seq_client < 0) {
kfree(client);
up(&register_mutex);
+ kfree(info);
return -ENOMEM;
}
- set_client_name(client, card, &info);
+ set_client_name(client, card, info);
} else if (device == 0)
- set_client_name(client, card, &info); /* use the first device's name */
+ set_client_name(client, card, info); /* use the first device's name */
msynth = kcalloc(ports, sizeof(seq_midisynth_t), GFP_KERNEL);
- if (msynth == NULL)
+ port = kmalloc(sizeof(*port), GFP_KERNEL);
+ if (msynth == NULL || port == NULL)
goto __nomem;
for (p = 0; p < ports; p++) {
@@ -350,42 +358,42 @@ snd_seq_midisynth_register_port(snd_seq_device_t *dev)
goto __nomem;
/* declare port */
- memset(&port, 0, sizeof(port));
- port.addr.client = client->seq_client;
- port.addr.port = device * (256 / SNDRV_RAWMIDI_DEVICES) + p;
- port.flags = SNDRV_SEQ_PORT_FLG_GIVEN_PORT;
- memset(&info, 0, sizeof(info));
- info.device = device;
+ memset(port, 0, sizeof(*port));
+ port->addr.client = client->seq_client;
+ port->addr.port = device * (256 / SNDRV_RAWMIDI_DEVICES) + p;
+ port->flags = SNDRV_SEQ_PORT_FLG_GIVEN_PORT;
+ memset(info, 0, sizeof(*info));
+ info->device = device;
if (p < output_count)
- info.stream = SNDRV_RAWMIDI_STREAM_OUTPUT;
+ info->stream = SNDRV_RAWMIDI_STREAM_OUTPUT;
else
- info.stream = SNDRV_RAWMIDI_STREAM_INPUT;
- info.subdevice = p;
- if (snd_rawmidi_info_select(card, &info) >= 0)
- strcpy(port.name, info.subname);
- if (! port.name[0]) {
- if (info.name[0]) {
+ info->stream = SNDRV_RAWMIDI_STREAM_INPUT;
+ info->subdevice = p;
+ if (snd_rawmidi_info_select(card, info) >= 0)
+ strcpy(port->name, info->subname);
+ if (! port->name[0]) {
+ if (info->name[0]) {
if (ports > 1)
- snprintf(port.name, sizeof(port.name), "%s-%d", info.name, p);
+ snprintf(port->name, sizeof(port->name), "%s-%d", info->name, p);
else
- snprintf(port.name, sizeof(port.name), "%s", info.name);
+ snprintf(port->name, sizeof(port->name), "%s", info->name);
} else {
/* last resort */
if (ports > 1)
- sprintf(port.name, "MIDI %d-%d-%d", card->number, device, p);
+ sprintf(port->name, "MIDI %d-%d-%d", card->number, device, p);
else
- sprintf(port.name, "MIDI %d-%d", card->number, device);
+ sprintf(port->name, "MIDI %d-%d", card->number, device);
}
}
- if ((info.flags & SNDRV_RAWMIDI_INFO_OUTPUT) && p < output_count)
- port.capability |= SNDRV_SEQ_PORT_CAP_WRITE | SNDRV_SEQ_PORT_CAP_SYNC_WRITE | SNDRV_SEQ_PORT_CAP_SUBS_WRITE;
- if ((info.flags & SNDRV_RAWMIDI_INFO_INPUT) && p < input_count)
- port.capability |= SNDRV_SEQ_PORT_CAP_READ | SNDRV_SEQ_PORT_CAP_SYNC_READ | SNDRV_SEQ_PORT_CAP_SUBS_READ;
- if ((port.capability & (SNDRV_SEQ_PORT_CAP_WRITE|SNDRV_SEQ_PORT_CAP_READ)) == (SNDRV_SEQ_PORT_CAP_WRITE|SNDRV_SEQ_PORT_CAP_READ) &&
- info.flags & SNDRV_RAWMIDI_INFO_DUPLEX)
- port.capability |= SNDRV_SEQ_PORT_CAP_DUPLEX;
- port.type = SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC;
- port.midi_channels = 16;
+ if ((info->flags & SNDRV_RAWMIDI_INFO_OUTPUT) && p < output_count)
+ port->capability |= SNDRV_SEQ_PORT_CAP_WRITE | SNDRV_SEQ_PORT_CAP_SYNC_WRITE | SNDRV_SEQ_PORT_CAP_SUBS_WRITE;
+ if ((info->flags & SNDRV_RAWMIDI_INFO_INPUT) && p < input_count)
+ port->capability |= SNDRV_SEQ_PORT_CAP_READ | SNDRV_SEQ_PORT_CAP_SYNC_READ | SNDRV_SEQ_PORT_CAP_SUBS_READ;
+ if ((port->capability & (SNDRV_SEQ_PORT_CAP_WRITE|SNDRV_SEQ_PORT_CAP_READ)) == (SNDRV_SEQ_PORT_CAP_WRITE|SNDRV_SEQ_PORT_CAP_READ) &&
+ info->flags & SNDRV_RAWMIDI_INFO_DUPLEX)
+ port->capability |= SNDRV_SEQ_PORT_CAP_DUPLEX;
+ port->type = SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC;
+ port->midi_channels = 16;
memset(&pcallbacks, 0, sizeof(pcallbacks));
pcallbacks.owner = THIS_MODULE;
pcallbacks.private_data = ms;
@@ -394,11 +402,11 @@ snd_seq_midisynth_register_port(snd_seq_device_t *dev)
pcallbacks.use = midisynth_use;
pcallbacks.unuse = midisynth_unuse;
pcallbacks.event_input = event_process_midi;
- port.kernel = &pcallbacks;
- if (snd_seq_kernel_client_ctl(client->seq_client, SNDRV_SEQ_IOCTL_CREATE_PORT, &port)<0)
+ port->kernel = &pcallbacks;
+ if (snd_seq_kernel_client_ctl(client->seq_client, SNDRV_SEQ_IOCTL_CREATE_PORT, port)<0)
goto __nomem;
ms->seq_client = client->seq_client;
- ms->seq_port = port.addr.port;
+ ms->seq_port = port->addr.port;
}
client->ports_per_device[device] = ports;
client->ports[device] = msynth;
@@ -418,6 +426,8 @@ snd_seq_midisynth_register_port(snd_seq_device_t *dev)
snd_seq_delete_kernel_client(client->seq_client);
kfree(client);
}
+ kfree(info);
+ kfree(port);
up(&register_mutex);
return -ENOMEM;
}
diff --git a/sound/core/seq/seq_midi_emul.c b/sound/core/seq/seq_midi_emul.c
index 5b2e2ed977b7b..35fe8a7e34bf9 100644
--- a/sound/core/seq/seq_midi_emul.c
+++ b/sound/core/seq/seq_midi_emul.c
@@ -244,8 +244,8 @@ note_off(snd_midi_op_t *ops, void *drv, snd_midi_channel_t *chan, int note, int
if (chan->gm_hold) {
/* Hold this note until pedal is turned off */
chan->note[note] |= SNDRV_MIDI_NOTE_RELEASED;
- } else if (chan->note[note] & SNDRV_MIDI_NOTE_SUSTENUTO) {
- /* Mark this note as release; it will be turned off when sustenuto
+ } else if (chan->note[note] & SNDRV_MIDI_NOTE_SOSTENUTO) {
+ /* Mark this note as release; it will be turned off when sostenuto
* is turned off */
chan->note[note] |= SNDRV_MIDI_NOTE_RELEASED;
} else {
@@ -287,18 +287,18 @@ do_control(snd_midi_op_t *ops, void *drv, snd_midi_channel_set_t *chset,
break;
case MIDI_CTL_PORTAMENTO:
break;
- case MIDI_CTL_SUSTENUTO:
+ case MIDI_CTL_SOSTENUTO:
if (value) {
/* Mark each note that is currently held down */
for (i = 0; i < 128; i++) {
if (chan->note[i] & SNDRV_MIDI_NOTE_ON)
- chan->note[i] |= SNDRV_MIDI_NOTE_SUSTENUTO;
+ chan->note[i] |= SNDRV_MIDI_NOTE_SOSTENUTO;
}
} else {
/* release all notes that were held */
for (i = 0; i < 128; i++) {
- if (chan->note[i] & SNDRV_MIDI_NOTE_SUSTENUTO) {
- chan->note[i] &= ~SNDRV_MIDI_NOTE_SUSTENUTO;
+ if (chan->note[i] & SNDRV_MIDI_NOTE_SOSTENUTO) {
+ chan->note[i] &= ~SNDRV_MIDI_NOTE_SOSTENUTO;
if (chan->note[i] & SNDRV_MIDI_NOTE_RELEASED) {
chan->note[i] = SNDRV_MIDI_NOTE_OFF;
if (ops->note_off)
diff --git a/sound/core/seq/seq_midi_event.c b/sound/core/seq/seq_midi_event.c
index 042ae7b81d335..21e569062bc38 100644
--- a/sound/core/seq/seq_midi_event.c
+++ b/sound/core/seq/seq_midi_event.c
@@ -525,3 +525,15 @@ EXPORT_SYMBOL(snd_midi_event_no_status);
EXPORT_SYMBOL(snd_midi_event_encode);
EXPORT_SYMBOL(snd_midi_event_encode_byte);
EXPORT_SYMBOL(snd_midi_event_decode);
+
+static int __init alsa_seq_midi_event_init(void)
+{
+ return 0;
+}
+
+static void __exit alsa_seq_midi_event_exit(void)
+{
+}
+
+module_init(alsa_seq_midi_event_init)
+module_exit(alsa_seq_midi_event_exit)
diff --git a/sound/core/seq/seq_queue.c b/sound/core/seq/seq_queue.c
index afb14604e0b4c..3afc7cc0c9a79 100644
--- a/sound/core/seq/seq_queue.c
+++ b/sound/core/seq/seq_queue.c
@@ -49,7 +49,7 @@
/* list of allocated queues */
static queue_t *queue_list[SNDRV_SEQ_MAX_QUEUES];
-static spinlock_t queue_list_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(queue_list_lock);
/* number of queues allocated */
static int num_queues;
@@ -650,7 +650,7 @@ 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 from_timer_port, int atomic, int hop)
+static void queue_broadcast_event(queue_t *q, snd_seq_event_t *ev, int atomic, int hop)
{
snd_seq_event_t sev;
@@ -661,60 +661,58 @@ static void queue_broadcast_event(queue_t *q, snd_seq_event_t *ev, int from_time
sev.queue = q->queue;
sev.data.queue.queue = q->queue;
- if (from_timer_port) {
- /* broadcast events from Timer port */
- sev.source.client = SNDRV_SEQ_CLIENT_SYSTEM;
- sev.source.port = SNDRV_SEQ_PORT_SYSTEM_TIMER;
- sev.dest.client = SNDRV_SEQ_ADDRESS_SUBSCRIBERS;
- snd_seq_kernel_client_dispatch(SNDRV_SEQ_CLIENT_SYSTEM, &sev, atomic, hop);
- }
+ /* broadcast events from Timer port */
+ sev.source.client = SNDRV_SEQ_CLIENT_SYSTEM;
+ sev.source.port = SNDRV_SEQ_PORT_SYSTEM_TIMER;
+ sev.dest.client = SNDRV_SEQ_ADDRESS_SUBSCRIBERS;
+ snd_seq_kernel_client_dispatch(SNDRV_SEQ_CLIENT_SYSTEM, &sev, atomic, hop);
}
/*
* process a received queue-control event.
* this function is exported for seq_sync.c.
*/
-void snd_seq_queue_process_event(queue_t *q, snd_seq_event_t *ev, int from_timer_port, int atomic, int hop)
+void snd_seq_queue_process_event(queue_t *q, snd_seq_event_t *ev, int atomic, int hop)
{
switch (ev->type) {
case SNDRV_SEQ_EVENT_START:
snd_seq_prioq_leave(q->tickq, ev->source.client, 1);
snd_seq_prioq_leave(q->timeq, ev->source.client, 1);
if (! snd_seq_timer_start(q->timer))
- queue_broadcast_event(q, ev, from_timer_port, atomic, hop);
+ queue_broadcast_event(q, ev, atomic, hop);
break;
case SNDRV_SEQ_EVENT_CONTINUE:
if (! snd_seq_timer_continue(q->timer))
- queue_broadcast_event(q, ev, from_timer_port, atomic, hop);
+ queue_broadcast_event(q, ev, atomic, hop);
break;
case SNDRV_SEQ_EVENT_STOP:
snd_seq_timer_stop(q->timer);
- queue_broadcast_event(q, ev, from_timer_port, atomic, hop);
+ queue_broadcast_event(q, ev, atomic, hop);
break;
case SNDRV_SEQ_EVENT_TEMPO:
snd_seq_timer_set_tempo(q->timer, ev->data.queue.param.value);
- queue_broadcast_event(q, ev, from_timer_port, atomic, hop);
+ queue_broadcast_event(q, ev, atomic, hop);
break;
case SNDRV_SEQ_EVENT_SETPOS_TICK:
if (snd_seq_timer_set_position_tick(q->timer, ev->data.queue.param.time.tick) == 0) {
- queue_broadcast_event(q, ev, from_timer_port, atomic, hop);
+ queue_broadcast_event(q, ev, atomic, hop);
}
break;
case SNDRV_SEQ_EVENT_SETPOS_TIME:
if (snd_seq_timer_set_position_time(q->timer, ev->data.queue.param.time.time) == 0) {
- queue_broadcast_event(q, ev, from_timer_port, atomic, hop);
+ queue_broadcast_event(q, ev, atomic, hop);
}
break;
case SNDRV_SEQ_EVENT_QUEUE_SKEW:
if (snd_seq_timer_set_skew(q->timer,
ev->data.queue.param.skew.value,
ev->data.queue.param.skew.base) == 0) {
- queue_broadcast_event(q, ev, from_timer_port, atomic, hop);
+ queue_broadcast_event(q, ev, atomic, hop);
}
break;
}
@@ -740,7 +738,7 @@ int snd_seq_control_queue(snd_seq_event_t *ev, int atomic, int hop)
return -EPERM;
}
- snd_seq_queue_process_event(q, ev, 1, atomic, hop);
+ snd_seq_queue_process_event(q, ev, atomic, hop);
queue_access_unlock(q);
queuefree(q);
diff --git a/sound/core/seq/seq_queue.h b/sound/core/seq/seq_queue.h
index 6e0113acea26f..b1bf5519fb3b0 100644
--- a/sound/core/seq/seq_queue.h
+++ b/sound/core/seq/seq_queue.h
@@ -111,7 +111,7 @@ 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);
-void snd_seq_queue_process_event(queue_t *q, snd_seq_event_t *ev, int from_timer_port, int atomic, int hop);
+void snd_seq_queue_process_event(queue_t *q, snd_seq_event_t *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 ceecd72ee3751..e8f0a6683d50b 100644
--- a/sound/core/seq/seq_system.c
+++ b/sound/core/seq/seq_system.c
@@ -123,13 +123,19 @@ int __init snd_seq_system_client_init(void)
snd_seq_client_callback_t callbacks;
snd_seq_port_callback_t pcallbacks;
- snd_seq_client_info_t inf;
- snd_seq_port_info_t port;
+ snd_seq_client_info_t *inf;
+ snd_seq_port_info_t *port;
+
+ inf = kcalloc(1, sizeof(*inf), GFP_KERNEL);
+ port = kcalloc(1, sizeof(*port), GFP_KERNEL);
+ if (! inf || ! port) {
+ kfree(inf);
+ kfree(port);
+ return -ENOMEM;
+ }
memset(&callbacks, 0, sizeof(callbacks));
memset(&pcallbacks, 0, sizeof(pcallbacks));
- memset(&inf, 0, sizeof(inf));
- memset(&port, 0, sizeof(port));
pcallbacks.owner = THIS_MODULE;
pcallbacks.event_input = event_input_timer;
@@ -138,33 +144,35 @@ int __init snd_seq_system_client_init(void)
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);
+ inf->client = 0;
+ inf->type = KERNEL_CLIENT;
+ strcpy(inf->name, "System");
+ snd_seq_kernel_client_ctl(sysclient, SNDRV_SEQ_IOCTL_SET_CLIENT_INFO, inf);
/* register timer */
- strcpy(port.name, "Timer");
- port.capability = SNDRV_SEQ_PORT_CAP_WRITE; /* accept queue control */
- port.capability |= SNDRV_SEQ_PORT_CAP_READ|SNDRV_SEQ_PORT_CAP_SUBS_READ; /* for broadcast */
- port.kernel = &pcallbacks;
- port.type = 0;
- port.flags = SNDRV_SEQ_PORT_FLG_GIVEN_PORT;
- port.addr.client = sysclient;
- port.addr.port = SNDRV_SEQ_PORT_SYSTEM_TIMER;
- snd_seq_kernel_client_ctl(sysclient, SNDRV_SEQ_IOCTL_CREATE_PORT, &port);
+ strcpy(port->name, "Timer");
+ port->capability = SNDRV_SEQ_PORT_CAP_WRITE; /* accept queue control */
+ port->capability |= SNDRV_SEQ_PORT_CAP_READ|SNDRV_SEQ_PORT_CAP_SUBS_READ; /* for broadcast */
+ port->kernel = &pcallbacks;
+ port->type = 0;
+ port->flags = SNDRV_SEQ_PORT_FLG_GIVEN_PORT;
+ port->addr.client = sysclient;
+ port->addr.port = SNDRV_SEQ_PORT_SYSTEM_TIMER;
+ snd_seq_kernel_client_ctl(sysclient, SNDRV_SEQ_IOCTL_CREATE_PORT, port);
/* register announcement port */
- strcpy(port.name, "Announce");
- port.capability = SNDRV_SEQ_PORT_CAP_READ|SNDRV_SEQ_PORT_CAP_SUBS_READ; /* for broadcast only */
- port.kernel = NULL;
- port.type = 0;
- port.flags = SNDRV_SEQ_PORT_FLG_GIVEN_PORT;
- port.addr.client = sysclient;
- port.addr.port = SNDRV_SEQ_PORT_SYSTEM_ANNOUNCE;
- snd_seq_kernel_client_ctl(sysclient, SNDRV_SEQ_IOCTL_CREATE_PORT, &port);
- announce_port = port.addr.port;
-
+ strcpy(port->name, "Announce");
+ port->capability = SNDRV_SEQ_PORT_CAP_READ|SNDRV_SEQ_PORT_CAP_SUBS_READ; /* for broadcast only */
+ port->kernel = NULL;
+ port->type = 0;
+ port->flags = SNDRV_SEQ_PORT_FLG_GIVEN_PORT;
+ port->addr.client = sysclient;
+ port->addr.port = SNDRV_SEQ_PORT_SYSTEM_ANNOUNCE;
+ 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_virmidi.c b/sound/core/seq/seq_virmidi.c
index 2785486292254..6b4e630ace541 100644
--- a/sound/core/seq/seq_virmidi.c
+++ b/sound/core/seq/seq_virmidi.c
@@ -354,39 +354,48 @@ static int snd_virmidi_dev_attach_seq(snd_virmidi_dev_t *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;
+ snd_seq_client_info_t *info;
+ snd_seq_port_info_t *pinfo;
int err;
if (rdev->client >= 0)
return 0;
+ info = kmalloc(sizeof(*info), GFP_KERNEL);
+ pinfo = kmalloc(sizeof(*pinfo), GFP_KERNEL);
+ if (! info || ! 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);
- if (client < 0)
- return client;
+ 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);
+ 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;
- sprintf(pinfo.name, "VirMIDI %d-%d", rdev->card->number, rdev->device);
+ memset(pinfo, 0, sizeof(*pinfo));
+ pinfo->addr.client = client;
+ sprintf(pinfo->name, "VirMIDI %d-%d", rdev->card->number, rdev->device);
/* set all capabilities */
- pinfo.capability |= SNDRV_SEQ_PORT_CAP_WRITE | SNDRV_SEQ_PORT_CAP_SYNC_WRITE | SNDRV_SEQ_PORT_CAP_SUBS_WRITE;
- pinfo.capability |= SNDRV_SEQ_PORT_CAP_READ | SNDRV_SEQ_PORT_CAP_SYNC_READ | SNDRV_SEQ_PORT_CAP_SUBS_READ;
- pinfo.capability |= SNDRV_SEQ_PORT_CAP_DUPLEX;
- pinfo.type = SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC;
- pinfo.midi_channels = 16;
+ pinfo->capability |= SNDRV_SEQ_PORT_CAP_WRITE | SNDRV_SEQ_PORT_CAP_SYNC_WRITE | SNDRV_SEQ_PORT_CAP_SUBS_WRITE;
+ pinfo->capability |= SNDRV_SEQ_PORT_CAP_READ | SNDRV_SEQ_PORT_CAP_SYNC_READ | SNDRV_SEQ_PORT_CAP_SUBS_READ;
+ pinfo->capability |= SNDRV_SEQ_PORT_CAP_DUPLEX;
+ pinfo->type = SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC;
+ pinfo->midi_channels = 16;
memset(&pcallbacks, 0, sizeof(pcallbacks));
pcallbacks.owner = THIS_MODULE;
pcallbacks.private_data = rdev;
@@ -395,16 +404,21 @@ static int snd_virmidi_dev_attach_seq(snd_virmidi_dev_t *rdev)
pcallbacks.use = snd_virmidi_use;
pcallbacks.unuse = snd_virmidi_unuse;
pcallbacks.event_input = snd_virmidi_event_input;
- pinfo.kernel = &pcallbacks;
+ pinfo->kernel = &pcallbacks;
err = snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_CREATE_PORT, &pinfo);
if (err < 0) {
snd_seq_delete_kernel_client(client);
rdev->client = -1;
- return err;
+ goto __error;
}
- rdev->port = pinfo.addr.port;
- return 0; /* success */
+ rdev->port = pinfo->addr.port;
+ err = 0; /* success */
+
+ __error:
+ kfree(info);
+ kfree(pinfo);
+ return err;
}
diff --git a/sound/core/sound.c b/sound/core/sound.c
index 31bc97e74a41b..88e052079f852 100644
--- a/sound/core/sound.c
+++ b/sound/core/sound.c
@@ -48,7 +48,6 @@ module_param(major, int, 0444);
MODULE_PARM_DESC(major, "Major # for sound driver.");
module_param(cards_limit, int, 0444);
MODULE_PARM_DESC(cards_limit, "Count of auto-loadable soundcards.");
-MODULE_ALIAS_CHARDEV_MAJOR(CONFIG_SND_MAJOR);
#ifdef CONFIG_DEVFS_FS
module_param(device_mode, int, 0444);
MODULE_PARM_DESC(device_mode, "Device file permission mask for devfs.");
@@ -420,7 +419,9 @@ EXPORT_SYMBOL(snd_card_file_remove);
#ifdef CONFIG_PM
EXPORT_SYMBOL(snd_power_wait);
EXPORT_SYMBOL(snd_card_set_pm_callback);
-EXPORT_SYMBOL(snd_card_set_dev_pm_callback);
+#if defined(CONFIG_PM) && defined(CONFIG_SND_GENERIC_PM)
+EXPORT_SYMBOL(snd_card_set_generic_pm_callback);
+#endif
#ifdef CONFIG_PCI
EXPORT_SYMBOL(snd_card_pci_suspend);
EXPORT_SYMBOL(snd_card_pci_resume);
@@ -467,6 +468,10 @@ EXPORT_SYMBOL(snd_ctl_find_id);
EXPORT_SYMBOL(snd_ctl_notify);
EXPORT_SYMBOL(snd_ctl_register_ioctl);
EXPORT_SYMBOL(snd_ctl_unregister_ioctl);
+#ifdef CONFIG_COMPAT
+EXPORT_SYMBOL(snd_ctl_register_ioctl_compat);
+EXPORT_SYMBOL(snd_ctl_unregister_ioctl_compat);
+#endif
EXPORT_SYMBOL(snd_ctl_elem_read);
EXPORT_SYMBOL(snd_ctl_elem_write);
/* misc.c */
diff --git a/sound/core/timer.c b/sound/core/timer.c
index f5ef7f5be53ae..fa762ca439be4 100644
--- a/sound/core/timer.c
+++ b/sound/core/timer.c
@@ -37,10 +37,12 @@
#include <linux/kerneld.h>
#endif
-#if !defined(CONFIG_SND_RTCTIMER) && !defined(CONFIG_SND_RTCTIMER_MODULE)
-#define DEFAULT_TIMER_LIMIT 1
-#else
+#if defined(CONFIG_SND_HPET) || defined(CONFIG_SND_HPET_MODULE)
+#define DEFAULT_TIMER_LIMIT 3
+#elif defined(CONFIG_SND_RTCTIMER) || defined(CONFIG_SND_RTCTIMER_MODULE)
#define DEFAULT_TIMER_LIMIT 2
+#else
+#define DEFAULT_TIMER_LIMIT 1
#endif
static int timer_limit = DEFAULT_TIMER_LIMIT;
@@ -76,7 +78,7 @@ static LIST_HEAD(snd_timer_list);
static LIST_HEAD(snd_timer_slave_list);
/* lock for slave active lists */
-static spinlock_t slave_active_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(slave_active_lock);
static DECLARE_MUTEX(register_mutex);
@@ -1117,7 +1119,8 @@ static void snd_timer_user_append_to_tqueue(snd_timer_user_t *tu, snd_timer_trea
if (tu->qused >= tu->queue_size) {
tu->overrun++;
} else {
- memcpy(&tu->queue[tu->qtail++], tread, sizeof(*tread));
+ memcpy(&tu->tqueue[tu->qtail++], tread, sizeof(*tread));
+ tu->qtail %= tu->queue_size;
tu->qused++;
}
}
@@ -1140,6 +1143,8 @@ static void snd_timer_user_ccallback(snd_timer_instance_t *timeri,
spin_lock(&tu->qlock);
snd_timer_user_append_to_tqueue(tu, &r1);
spin_unlock(&tu->qlock);
+ kill_fasync(&tu->fasync, SIGIO, POLL_IN);
+ wake_up(&tu->qchange_sleep);
}
static void snd_timer_user_tinterrupt(snd_timer_instance_t *timeri,
@@ -1342,39 +1347,45 @@ 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)
{
- snd_timer_ginfo_t ginfo;
+ snd_timer_ginfo_t *ginfo;
snd_timer_id_t tid;
snd_timer_t *t;
struct list_head *p;
int err = 0;
- if (copy_from_user(&ginfo, _ginfo, sizeof(ginfo)))
+ ginfo = kmalloc(sizeof(*ginfo), GFP_KERNEL);
+ if (! ginfo)
+ return -ENOMEM;
+ if (copy_from_user(ginfo, _ginfo, sizeof(*ginfo))) {
+ kfree(ginfo);
return -EFAULT;
- tid = ginfo.tid;
- memset(&ginfo, 0, sizeof(ginfo));
- ginfo.tid = tid;
+ }
+ tid = ginfo->tid;
+ memset(ginfo, 0, sizeof(*ginfo));
+ ginfo->tid = tid;
down(&register_mutex);
t = snd_timer_find(&tid);
if (t != NULL) {
- ginfo.card = t->card ? t->card->number : -1;
+ ginfo->card = t->card ? t->card->number : -1;
if (t->hw.flags & SNDRV_TIMER_HW_SLAVE)
- ginfo.flags |= SNDRV_TIMER_FLG_SLAVE;
- strlcpy(ginfo.id, t->id, sizeof(ginfo.id));
- strlcpy(ginfo.name, t->name, sizeof(ginfo.name));
- ginfo.resolution = t->hw.resolution;
+ ginfo->flags |= SNDRV_TIMER_FLG_SLAVE;
+ strlcpy(ginfo->id, t->id, sizeof(ginfo->id));
+ strlcpy(ginfo->name, t->name, sizeof(ginfo->name));
+ ginfo->resolution = t->hw.resolution;
if (t->hw.resolution_min > 0) {
- ginfo.resolution_min = t->hw.resolution_min;
- ginfo.resolution_max = t->hw.resolution_max;
+ ginfo->resolution_min = t->hw.resolution_min;
+ ginfo->resolution_max = t->hw.resolution_max;
}
list_for_each(p, &t->open_list_head) {
- ginfo.clients++;
+ ginfo->clients++;
}
} else {
err = -ENODEV;
}
up(&register_mutex);
- if (err >= 0 && copy_to_user(_ginfo, &ginfo, sizeof(ginfo)))
+ if (err >= 0 && copy_to_user(_ginfo, ginfo, sizeof(*ginfo)))
err = -EFAULT;
+ kfree(ginfo);
return err;
}
@@ -1488,23 +1499,28 @@ static int snd_timer_user_tselect(struct file *file, snd_timer_select_t __user *
static int snd_timer_user_info(struct file *file, snd_timer_info_t __user *_info)
{
snd_timer_user_t *tu;
- snd_timer_info_t info;
+ snd_timer_info_t *info;
snd_timer_t *t;
+ int err = 0;
tu = file->private_data;
snd_assert(tu->timeri != NULL, return -ENXIO);
t = tu->timeri->timer;
snd_assert(t != NULL, return -ENXIO);
- memset(&info, 0, sizeof(info));
- info.card = t->card ? t->card->number : -1;
+
+ info = kcalloc(1, sizeof(*info), GFP_KERNEL);
+ if (! info)
+ return -ENOMEM;
+ info->card = t->card ? t->card->number : -1;
if (t->hw.flags & SNDRV_TIMER_HW_SLAVE)
- info.flags |= SNDRV_TIMER_FLG_SLAVE;
- strlcpy(info.id, t->id, sizeof(info.id));
- strlcpy(info.name, t->name, sizeof(info.name));
- info.resolution = t->hw.resolution;
- if (copy_to_user(_info, &info, sizeof(*_info)))
- return -EFAULT;
- return 0;
+ info->flags |= SNDRV_TIMER_FLG_SLAVE;
+ strlcpy(info->id, t->id, sizeof(info->id));
+ strlcpy(info->name, t->name, sizeof(info->name));
+ info->resolution = t->hw.resolution;
+ if (copy_to_user(_info, info, sizeof(*_info)))
+ err = -EFAULT;
+ kfree(info);
+ return err;
}
static int snd_timer_user_params(struct file *file, snd_timer_params_t __user *_params)
@@ -1653,8 +1669,7 @@ static int snd_timer_user_continue(struct file *file)
return (err = snd_timer_continue(tu->timeri)) < 0 ? err : 0;
}
-static inline int _snd_timer_user_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
+static long snd_timer_user_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
snd_timer_user_t *tu;
void __user *argp = (void __user *)arg;
@@ -1701,17 +1716,6 @@ static inline int _snd_timer_user_ioctl(struct inode *inode, struct file *file,
return -ENOTTY;
}
-/* FIXME: need to unlock BKL to allow preemption */
-static int snd_timer_user_ioctl(struct inode *inode, struct file * file,
- unsigned int cmd, unsigned long arg)
-{
- int err;
- unlock_kernel();
- err = _snd_timer_user_ioctl(inode, file, cmd, arg);
- lock_kernel();
- return err;
-}
-
static int snd_timer_user_fasync(int fd, struct file * file, int on)
{
snd_timer_user_t *tu;
@@ -1803,6 +1807,12 @@ static unsigned int snd_timer_user_poll(struct file *file, poll_table * wait)
return mask;
}
+#ifdef CONFIG_COMPAT
+#include "timer_compat.c"
+#else
+#define snd_timer_user_ioctl_compat NULL
+#endif
+
static struct file_operations snd_timer_f_ops =
{
.owner = THIS_MODULE,
@@ -1810,7 +1820,8 @@ static struct file_operations snd_timer_f_ops =
.open = snd_timer_user_open,
.release = snd_timer_user_release,
.poll = snd_timer_user_poll,
- .ioctl = snd_timer_user_ioctl,
+ .unlocked_ioctl = snd_timer_user_ioctl,
+ .compat_ioctl = snd_timer_user_ioctl_compat,
.fasync = snd_timer_user_fasync,
};
diff --git a/sound/core/timer_compat.c b/sound/core/timer_compat.c
new file mode 100644
index 0000000000000..9fbc3957a22df
--- /dev/null
+++ b/sound/core/timer_compat.c
@@ -0,0 +1,119 @@
+/*
+ * 32bit -> 64bit ioctl wrapper for timer API
+ * Copyright (c) by Takashi Iwai <tiwai@suse.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* This file included from timer.c */
+
+#include <linux/compat.h>
+
+struct sndrv_timer_info32 {
+ u32 flags;
+ s32 card;
+ unsigned char id[64];
+ unsigned char name[80];
+ u32 reserved0;
+ u32 resolution;
+ unsigned char reserved[64];
+};
+
+static int snd_timer_user_info_compat(struct file *file,
+ struct sndrv_timer_info32 __user *_info)
+{
+ snd_timer_user_t *tu;
+ struct sndrv_timer_info32 info;
+ snd_timer_t *t;
+
+ tu = file->private_data;
+ snd_assert(tu->timeri != NULL, return -ENXIO);
+ t = tu->timeri->timer;
+ snd_assert(t != NULL, return -ENXIO);
+ memset(&info, 0, sizeof(info));
+ info.card = t->card ? t->card->number : -1;
+ if (t->hw.flags & SNDRV_TIMER_HW_SLAVE)
+ info.flags |= SNDRV_TIMER_FLG_SLAVE;
+ strlcpy(info.id, t->id, sizeof(info.id));
+ strlcpy(info.name, t->name, sizeof(info.name));
+ info.resolution = t->hw.resolution;
+ if (copy_to_user(_info, &info, sizeof(*_info)))
+ return -EFAULT;
+ return 0;
+}
+
+struct sndrv_timer_status32 {
+ struct compat_timespec tstamp;
+ u32 resolution;
+ u32 lost;
+ u32 overrun;
+ u32 queue;
+ unsigned char reserved[64];
+};
+
+static int snd_timer_user_status_compat(struct file *file,
+ struct sndrv_timer_status32 __user *_status)
+{
+ snd_timer_user_t *tu;
+ snd_timer_status_t status;
+
+ tu = file->private_data;
+ snd_assert(tu->timeri != NULL, return -ENXIO);
+ memset(&status, 0, sizeof(status));
+ status.tstamp = tu->tstamp;
+ status.resolution = snd_timer_resolution(tu->timeri);
+ status.lost = tu->timeri->lost;
+ status.overrun = tu->overrun;
+ spin_lock_irq(&tu->qlock);
+ status.queue = tu->qused;
+ spin_unlock_irq(&tu->qlock);
+ if (copy_to_user(_status, &status, sizeof(status)))
+ return -EFAULT;
+ return 0;
+}
+
+/*
+ */
+
+enum {
+ SNDRV_TIMER_IOCTL_INFO32 = _IOR('T', 0x11, struct sndrv_timer_info32),
+ SNDRV_TIMER_IOCTL_STATUS32 = _IOW('T', 0x14, struct sndrv_timer_status32),
+};
+
+static long snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ void __user *argp = compat_ptr(arg);
+
+ switch (cmd) {
+ case SNDRV_TIMER_IOCTL_PVERSION:
+ case SNDRV_TIMER_IOCTL_TREAD:
+ case SNDRV_TIMER_IOCTL_GINFO:
+ case SNDRV_TIMER_IOCTL_GPARAMS:
+ case SNDRV_TIMER_IOCTL_GSTATUS:
+ case SNDRV_TIMER_IOCTL_SELECT:
+ case SNDRV_TIMER_IOCTL_PARAMS:
+ case SNDRV_TIMER_IOCTL_START:
+ case SNDRV_TIMER_IOCTL_STOP:
+ case SNDRV_TIMER_IOCTL_CONTINUE:
+ case SNDRV_TIMER_IOCTL_NEXT_DEVICE:
+ return snd_timer_user_ioctl(file, cmd, (unsigned long)argp);
+ case SNDRV_TIMER_IOCTL_INFO32:
+ return snd_timer_user_info_compat(file, argp);
+ case SNDRV_TIMER_IOCTL_STATUS32:
+ return snd_timer_user_status_compat(file, argp);
+ }
+ return -ENOIOCTLCMD;
+}
diff --git a/sound/drivers/mpu401/mpu401.c b/sound/drivers/mpu401/mpu401.c
index 6b22d2e08bc74..cb36ecb78697b 100644
--- a/sound/drivers/mpu401/mpu401.c
+++ b/sound/drivers/mpu401/mpu401.c
@@ -1,12 +1,7 @@
/*
* Driver for generic MPU-401 boards (UART mode only)
* Copyright (c) by Jaroslav Kysela <perex@suse.cz>
- *
- * ACPI PnP Copyright (c) 2004 by Clemens Ladisch <clemens@ladisch.de>
- * based on 8250_acpi.c
- * Copyright (c) 2002-2003 Matthew Wilcox for Hewlett-Packard
- * Copyright (C) 2004 Hewlett-Packard Co
- * Bjorn Helgaas <bjorn.helgaas@hp.com>
+ * Copyright (c) 2004 by Castet Matthieu <castet.matthieu@free.fr>
*
*
* This program is free software; you can redistribute it and/or modify
@@ -27,27 +22,21 @@
#include <sound/driver.h>
#include <linux/init.h>
-#ifdef CONFIG_ACPI_BUS
-#include <linux/acpi.h>
-#endif
+#include <linux/pnp.h>
#include <linux/moduleparam.h>
#include <sound/core.h>
#include <sound/mpu401.h>
#include <sound/initval.h>
-#ifdef CONFIG_ACPI_BUS
-#define USE_ACPI_PNP
-#endif
-
MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
MODULE_DESCRIPTION("MPU-401 UART");
MODULE_LICENSE("GPL");
-static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
+static int index[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = -2}; /* exclude the first card */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */
-#ifdef USE_ACPI_PNP
-static int acpipnp[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = 1 };
+#ifdef CONFIG_PNP
+static int pnp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1};
#endif
static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* MPU-401 port number */
static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* MPU-401 IRQ */
@@ -58,115 +47,36 @@ module_param_array(id, charp, NULL, 0444);
MODULE_PARM_DESC(id, "ID string for MPU-401 device.");
module_param_array(enable, bool, NULL, 0444);
MODULE_PARM_DESC(enable, "Enable MPU-401 device.");
-#ifdef USE_ACPI_PNP
-module_param_array(acpipnp, bool, NULL, 0444);
-MODULE_PARM_DESC(acpipnp, "ACPI PnP detection for MPU-401 device.");
+#ifdef CONFIG_PNP
+module_param_array(pnp, bool, NULL, 0444);
+MODULE_PARM_DESC(pnp, "PnP detection for MPU-401 device.");
#endif
module_param_array(port, long, NULL, 0444);
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.");
-#ifndef CONFIG_ACPI_BUS
-struct acpi_device;
-#endif
-
static snd_card_t *snd_mpu401_legacy_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
-static int cards;
-
-#ifdef USE_ACPI_PNP
-
-static int acpi_driver_registered;
-
-struct mpu401_resources {
- unsigned long port;
- int irq;
-};
+static int pnp_registered = 0;
-static acpi_status __devinit snd_mpu401_acpi_resource(struct acpi_resource *res,
- void *data)
-{
- struct mpu401_resources *resources = (struct mpu401_resources *)data;
-
- if (res->id == ACPI_RSTYPE_IRQ) {
- if (res->data.irq.number_of_interrupts > 0) {
- resources->irq = acpi_register_gsi(res->data.irq.interrupts[0],
- res->data.irq.edge_level,
- res->data.irq.active_high_low);
- }
- } else if (res->id == ACPI_RSTYPE_IO) {
- if (res->data.io.range_length >= 2) {
- resources->port = res->data.io.min_base_address;
- }
- }
- return AE_OK;
-}
-
-static int __devinit snd_mpu401_acpi_pnp(int dev, struct acpi_device *device)
-{
- struct mpu401_resources res;
- acpi_status status;
-
- res.port = SNDRV_AUTO_PORT;
- res.irq = SNDRV_AUTO_IRQ;
- status = acpi_walk_resources(device->handle, METHOD_NAME__CRS,
- snd_mpu401_acpi_resource, &res);
- if (ACPI_FAILURE(status))
- return -ENODEV;
- if (res.port == SNDRV_AUTO_PORT || res.irq == SNDRV_AUTO_IRQ) {
- snd_printk(KERN_ERR "no port or irq in %s _CRS\n",
- acpi_device_bid(device));
- return -ENODEV;
- }
- port[dev] = res.port;
- irq[dev] = res.irq;
- return 0;
-}
-
-#endif /* USE_ACPI_PNP */
-
-static int __devinit snd_card_mpu401_probe(int dev, struct acpi_device *device)
+static int snd_mpu401_create(int dev, snd_card_t **rcard)
{
snd_card_t *card;
int err;
-#ifdef USE_ACPI_PNP
- if (!device) {
-#endif
- if (port[dev] == SNDRV_AUTO_PORT) {
- snd_printk(KERN_ERR "specify port\n");
- return -EINVAL;
- }
- if (irq[dev] == SNDRV_AUTO_IRQ) {
- snd_printk(KERN_ERR "specify or disable IRQ port\n");
- return -EINVAL;
- }
-#ifdef USE_ACPI_PNP
- }
-#endif
-
-#ifdef USE_ACPI_PNP
- if (device && (err = snd_mpu401_acpi_pnp(dev, device)) < 0)
- return err;
-#endif
-
+ *rcard = NULL;
card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
if (card == NULL)
return -ENOMEM;
strcpy(card->driver, "MPU-401 UART");
strcpy(card->shortname, card->driver);
- sprintf(card->longname, "%s at 0x%lx, ", card->shortname, port[dev]);
+ sprintf(card->longname, "%s at %#lx, ", card->shortname, port[dev]);
if (irq[dev] >= 0) {
- sprintf(card->longname + strlen(card->longname), "IRQ %d", irq[dev]);
+ sprintf(card->longname + strlen(card->longname), "irq %d", irq[dev]);
} else {
strcat(card->longname, "polled");
}
-#ifdef USE_ACPI_PNP
- if (device) {
- strcat(card->longname, ", ACPI id ");
- strlcat(card->longname, acpi_device_bid(device), sizeof(card->longname));
- }
-#endif
+
if (snd_mpu401_uart_new(card, 0,
MPU401_HW_MPU401,
port[dev], 0,
@@ -179,89 +89,127 @@ static int __devinit snd_card_mpu401_probe(int dev, struct acpi_device *device)
snd_card_free(card);
return err;
}
-#ifdef USE_ACPI_PNP
- if (device)
- acpi_driver_data(device) = card;
- else
-#endif
- snd_mpu401_legacy_cards[dev] = card;
- ++cards;
+ *rcard = card;
return 0;
}
-#ifdef USE_ACPI_PNP
+static int __devinit snd_mpu401_probe(int dev)
+{
+ if (port[dev] == SNDRV_AUTO_PORT) {
+ snd_printk(KERN_ERR "specify port\n");
+ return -EINVAL;
+ }
+ if (irq[dev] == SNDRV_AUTO_IRQ) {
+ snd_printk(KERN_ERR "specify or disable IRQ\n");
+ return -EINVAL;
+ }
+ return snd_mpu401_create(dev, &snd_mpu401_legacy_cards[dev]);
+}
+
+#ifdef CONFIG_PNP
+
+#define IO_EXTENT 2
+
+static struct pnp_device_id snd_mpu401_pnpids[] = {
+ { .id = "PNPb006" },
+ { .id = "" }
+};
+
+MODULE_DEVICE_TABLE(pnp, snd_mpu401_pnpids);
+
+static int __init snd_mpu401_pnp(int dev, struct pnp_dev *device,
+ const struct pnp_device_id *id)
+{
+ if (!pnp_port_valid(device, 0) ||
+ pnp_port_flags(device, 0) & IORESOURCE_DISABLED) {
+ snd_printk(KERN_ERR "no PnP port\n");
+ return -ENODEV;
+ }
+ if (pnp_port_len(device, 0) < IO_EXTENT) {
+ snd_printk(KERN_ERR "PnP port length is %ld, expected %d\n",
+ pnp_port_len(device, 0), IO_EXTENT);
+ return -ENODEV;
+ }
+ port[dev] = pnp_port_start(device, 0);
+
+ if (!pnp_irq_valid(device, 0) ||
+ pnp_irq_flags(device, 0) & IORESOURCE_DISABLED) {
+ snd_printk(KERN_WARNING "no PnP irq, using polling\n");
+ irq[dev] = -1;
+ } else {
+ irq[dev] = pnp_irq(device, 0);
+ }
+ return 0;
+}
-static int __devinit snd_mpu401_acpi_add(struct acpi_device *device)
+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;
int err;
for ( ; dev < SNDRV_CARDS; ++dev) {
- if (!enable[dev] || !acpipnp[dev])
+ if (!enable[dev] || !pnp[dev])
continue;
- err = snd_card_mpu401_probe(dev, device);
+ err = snd_mpu401_pnp(dev, pnp_dev, id);
+ if (err < 0)
+ return err;
+ err = snd_mpu401_create(dev, &card);
if (err < 0)
return err;
+ snd_card_set_dev(card, &pnp_dev->dev);
+ pnp_set_drvdata(pnp_dev, card);
++dev;
return 0;
}
return -ENODEV;
}
-static int __devexit snd_mpu401_acpi_remove(struct acpi_device *device,
- int type)
+static void __devexit snd_mpu401_pnp_remove(struct pnp_dev *dev)
{
- snd_card_t *card;
-
- if (!device)
- return -EINVAL;
- card = (snd_card_t *)acpi_driver_data(device);
- if (!card)
- return -EINVAL;
+ snd_card_t *card = (snd_card_t *) pnp_get_drvdata(dev);
snd_card_disconnect(card);
snd_card_free_in_thread(card);
- acpi_driver_data(device) = NULL;
- return 0;
}
-static struct acpi_driver snd_mpu401_acpi_driver = {
- .name = "MPU-401 Driver",
- .class = "mpu401",
- .ids = "PNPB006",
- .ops = {
- .add = snd_mpu401_acpi_add,
- .remove = __devexit_p(snd_mpu401_acpi_remove),
- },
+static struct pnp_driver snd_mpu401_pnp_driver = {
+ .name = "mpu401",
+ .id_table = snd_mpu401_pnpids,
+ .probe = snd_mpu401_pnp_probe,
+ .remove = __devexit_p(snd_mpu401_pnp_remove),
};
-
-#endif /* USE_ACPI_PNP */
+#else
+static struct pnp_driver snd_mpu401_pnp_driver;
+#endif
static int __init alsa_card_mpu401_init(void)
{
- int dev;
+ int dev, devices = 0;
+ int err;
-#ifdef USE_ACPI_PNP
- if (acpi_bus_register_driver(&snd_mpu401_acpi_driver) >= 0)
- acpi_driver_registered = 1;
-#endif
for (dev = 0; dev < SNDRV_CARDS; dev++) {
if (!enable[dev])
continue;
-#ifdef USE_ACPI_PNP
- if (acpipnp[dev] && acpi_driver_registered)
+#ifdef CONFIG_PNP
+ if (pnp[dev])
continue;
#endif
- snd_card_mpu401_probe(dev, NULL);
+ if (snd_mpu401_probe(dev) >= 0)
+ devices++;
}
- if (!cards) {
+ if ((err = pnp_register_driver(&snd_mpu401_pnp_driver)) >= 0) {
+ pnp_registered = 1;
+ devices += err;
+ }
+
+ if (!devices) {
#ifdef MODULE
printk(KERN_ERR "MPU-401 device not found or device busy\n");
#endif
-#ifdef USE_ACPI_PNP
- if (acpi_driver_registered)
- acpi_bus_unregister_driver(&snd_mpu401_acpi_driver);
-#endif
+ if (pnp_registered)
+ pnp_unregister_driver(&snd_mpu401_pnp_driver);
return -ENODEV;
}
return 0;
@@ -271,10 +219,8 @@ static void __exit alsa_card_mpu401_exit(void)
{
int idx;
-#ifdef USE_ACPI_PNP
- if (acpi_driver_registered)
- acpi_bus_unregister_driver(&snd_mpu401_acpi_driver);
-#endif
+ 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]);
}
diff --git a/sound/drivers/mpu401/mpu401_uart.c b/sound/drivers/mpu401/mpu401_uart.c
index ef36d9e661470..0f83c5241b6be 100644
--- a/sound/drivers/mpu401/mpu401_uart.c
+++ b/sound/drivers/mpu401/mpu401_uart.c
@@ -94,9 +94,7 @@ static void _snd_mpu401_uart_interrupt(mpu401_t *mpu)
{
spin_lock(&mpu->input_lock);
if (test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode)) {
- atomic_dec(&mpu->rx_loop);
snd_mpu401_uart_input_read(mpu);
- atomic_inc(&mpu->rx_loop);
} else {
snd_mpu401_uart_clear_rx(mpu);
}
@@ -104,12 +102,9 @@ static void _snd_mpu401_uart_interrupt(mpu401_t *mpu)
/* ok. for better Tx performance try do some output when input is done */
if (test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode) &&
test_bit(MPU401_MODE_BIT_OUTPUT_TRIGGER, &mpu->mode)) {
- if (spin_trylock(&mpu->output_lock)) {
- atomic_dec(&mpu->tx_loop);
- snd_mpu401_uart_output_write(mpu);
- atomic_inc(&mpu->tx_loop);
- spin_unlock(&mpu->output_lock);
- }
+ spin_lock(&mpu->output_lock);
+ snd_mpu401_uart_output_write(mpu);
+ spin_unlock(&mpu->output_lock);
}
}
@@ -243,7 +238,6 @@ static int snd_mpu401_uart_input_open(snd_rawmidi_substream_t * substream)
snd_mpu401_uart_cmd(mpu, MPU401_ENTER_UART, 1);
}
mpu->substream_input = substream;
- atomic_set(&mpu->rx_loop, 1);
set_bit(MPU401_MODE_BIT_INPUT, &mpu->mode);
return 0;
}
@@ -261,7 +255,6 @@ static int snd_mpu401_uart_output_open(snd_rawmidi_substream_t * substream)
snd_mpu401_uart_cmd(mpu, MPU401_ENTER_UART, 1);
}
mpu->substream_output = substream;
- atomic_set(&mpu->tx_loop, 1);
set_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode);
return 0;
}
@@ -314,16 +307,9 @@ static void snd_mpu401_uart_input_trigger(snd_rawmidi_substream_t * substream, i
}
/* read data in advance */
- /* prevent double enter via rawmidi->event callback */
- if (atomic_dec_and_test(&mpu->rx_loop)) {
- local_irq_save(flags);
- if (spin_trylock(&mpu->input_lock)) {
- snd_mpu401_uart_input_read(mpu);
- spin_unlock(&mpu->input_lock);
- }
- local_irq_restore(flags);
- }
- atomic_inc(&mpu->rx_loop);
+ spin_lock_irqsave(&mpu->input_lock, flags);
+ snd_mpu401_uart_input_read(mpu);
+ spin_unlock_irqrestore(&mpu->input_lock, flags);
} else {
if (mpu->irq < 0)
snd_mpu401_uart_remove_timer(mpu, 1);
@@ -405,16 +391,9 @@ static void snd_mpu401_uart_output_trigger(snd_rawmidi_substream_t * substream,
snd_mpu401_uart_add_timer(mpu, 0);
/* output pending data */
- /* prevent double enter via rawmidi->event callback */
- if (atomic_dec_and_test(&mpu->tx_loop)) {
- local_irq_save(flags);
- if (spin_trylock(&mpu->output_lock)) {
- snd_mpu401_uart_output_write(mpu);
- spin_unlock(&mpu->output_lock);
- }
- local_irq_restore(flags);
- }
- atomic_inc(&mpu->tx_loop);
+ spin_lock_irqsave(&mpu->output_lock, flags);
+ snd_mpu401_uart_output_write(mpu);
+ spin_unlock_irqrestore(&mpu->output_lock, flags);
} else {
snd_mpu401_uart_remove_timer(mpu, 0);
clear_bit(MPU401_MODE_BIT_OUTPUT_TRIGGER, &mpu->mode);
diff --git a/sound/drivers/mtpav.c b/sound/drivers/mtpav.c
index 2c572345c90bf..1280a57c49eb8 100644
--- a/sound/drivers/mtpav.c
+++ b/sound/drivers/mtpav.c
@@ -413,10 +413,11 @@ 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;
int p;
- spin_lock(&chip->spinlock);
+ spin_lock_irqsave(&chip->spinlock, flags);
/* reprogram timer */
chip->timer.expires = 1 + jiffies;
add_timer(&chip->timer);
@@ -426,7 +427,7 @@ static void snd_mtpav_output_timer(unsigned long data)
if ((portp->mode & MTPAV_MODE_OUTPUT_TRIGGERED) && portp->output)
snd_mtpav_output_port_write(portp, portp->output);
}
- spin_unlock(&chip->spinlock);
+ spin_unlock_irqrestore(&chip->spinlock, flags);
}
/* spinlock held! */
@@ -514,9 +515,7 @@ static void snd_mtpav_inmidi_process(mtpav_t *mcrd, u8 inbyte)
portp = &mcrd->ports[mcrd->inmidiport];
if (portp->mode & MTPAV_MODE_INPUT_TRIGGERED) {
- spin_unlock(&mcrd->spinlock);
snd_rawmidi_receive(portp->input, &inbyte, 1);
- spin_lock(&mcrd->spinlock);
}
}
diff --git a/sound/drivers/serial-u16550.c b/sound/drivers/serial-u16550.c
index 1dac18638a99d..964b97e70c846 100644
--- a/sound/drivers/serial-u16550.c
+++ b/sound/drivers/serial-u16550.c
@@ -232,7 +232,7 @@ static void snd_uart16550_io_loop(snd_uart16550_t * uart)
}
else if ((uart->filemode & SERIAL_MODE_INPUT_OPEN) && (uart->midi_input[substream] != NULL)) {
snd_rawmidi_receive(uart->midi_input[substream], &c, 1);
- }
+ }
} else if ((uart->filemode & SERIAL_MODE_INPUT_OPEN) && (uart->midi_input[substream] != NULL)) {
snd_rawmidi_receive(uart->midi_input[substream], &c, 1);
}
@@ -309,13 +309,14 @@ static irqreturn_t snd_uart16550_interrupt(int irq, void *dev_id, struct pt_regs
/* When the polling mode, this function calls snd_uart16550_io_loop. */
static void snd_uart16550_buffer_timer(unsigned long data)
{
+ unsigned long flags;
snd_uart16550_t *uart;
uart = (snd_uart16550_t *)data;
- spin_lock(&uart->open_lock);
+ spin_lock_irqsave(&uart->open_lock, flags);
snd_uart16550_del_timer(uart);
snd_uart16550_io_loop(uart);
- spin_unlock(&uart->open_lock);
+ spin_unlock_irqrestore(&uart->open_lock, flags);
}
/*
@@ -840,6 +841,16 @@ static int __init snd_uart16550_create(snd_card_t * card,
return 0;
}
+static void __init snd_uart16550_substreams(snd_rawmidi_str_t *stream)
+{
+ struct list_head *list;
+
+ list_for_each(list, &stream->substreams) {
+ snd_rawmidi_substream_t *substream = list_entry(list, snd_rawmidi_substream_t, 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)
{
snd_rawmidi_t *rrawmidi;
@@ -849,7 +860,9 @@ static int __init snd_uart16550_rmidi(snd_uart16550_t *uart, int device, int out
return err;
snd_rawmidi_set_ops(rrawmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_uart16550_input);
snd_rawmidi_set_ops(rrawmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_uart16550_output);
- sprintf(rrawmidi->name, "uart16550 MIDI #%d", device);
+ strcpy(rrawmidi->name, "Serial MIDI");
+ snd_uart16550_substreams(&rrawmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT]);
+ snd_uart16550_substreams(&rrawmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT]);
rrawmidi->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT |
SNDRV_RAWMIDI_INFO_INPUT |
SNDRV_RAWMIDI_INFO_DUPLEX;
@@ -906,7 +919,7 @@ static int __init snd_serial_probe(int dev)
return -ENOMEM;
strcpy(card->driver, "Serial");
- strcpy(card->shortname, "Serial midi (uart16550A)");
+ strcpy(card->shortname, "Serial MIDI (UART16550A)");
if ((err = snd_uart16550_create(card,
port[dev],
diff --git a/sound/drivers/vx/vx_core.c b/sound/drivers/vx/vx_core.c
index 806bf78458594..c6fa5afa3e9ae 100644
--- a/sound/drivers/vx/vx_core.c
+++ b/sound/drivers/vx/vx_core.c
@@ -25,6 +25,7 @@
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/init.h>
+#include <linux/device.h>
#include <linux/firmware.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -45,12 +46,10 @@ MODULE_LICENSE("GPL");
*/
void snd_vx_delay(vx_core_t *chip, int xmsec)
{
- if (! in_interrupt() && xmsec >= 1000 / HZ) {
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout((xmsec * HZ + 999) / 1000);
- } else {
+ if (! in_interrupt() && xmsec >= 1000 / HZ)
+ msleep(xmsec);
+ else
mdelay(xmsec);
- }
}
/*
@@ -610,6 +609,10 @@ static void vx_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
static char *uer_type[] = { "Consumer", "Professional", "Not Present" };
snd_iprintf(buffer, "%s\n", chip->card->longname);
+ snd_iprintf(buffer, "Xilinx Firmware: %s\n",
+ chip->chip_status & VX_STAT_XILINX_LOADED ? "Loaded" : "No");
+ snd_iprintf(buffer, "Device Initialized: %s\n",
+ chip->chip_status & VX_STAT_DEVICE_INIT ? "Yes" : "No");
snd_iprintf(buffer, "DSP audio info:");
if (chip->audio_info & VX_AUDIO_INFO_REAL_TIME)
snd_iprintf(buffer, " realtime");
@@ -718,7 +721,7 @@ int snd_vx_dsp_load(vx_core_t *chip, const struct firmware *dsp)
/*
* suspend
*/
-static int snd_vx_suspend(snd_card_t *card, unsigned int state)
+static int snd_vx_suspend(snd_card_t *card, pm_message_t state)
{
vx_core_t *chip = card->pm_private_data;
unsigned int i;
@@ -735,7 +738,7 @@ static int snd_vx_suspend(snd_card_t *card, unsigned int state)
/*
* resume
*/
-static int snd_vx_resume(snd_card_t *card, unsigned int state)
+static int snd_vx_resume(snd_card_t *card)
{
vx_core_t *chip = card->pm_private_data;
int i, err;
diff --git a/sound/drivers/vx/vx_hwdep.c b/sound/drivers/vx/vx_hwdep.c
index ad290fa057064..9a3dc3c3b3de3 100644
--- a/sound/drivers/vx/vx_hwdep.c
+++ b/sound/drivers/vx/vx_hwdep.c
@@ -21,6 +21,7 @@
*/
#include <sound/driver.h>
+#include <linux/device.h>
#include <linux/firmware.h>
#include <sound/core.h>
#include <sound/hwdep.h>
diff --git a/sound/i2c/other/Makefile b/sound/i2c/other/Makefile
index c2377d0e9a68f..2fe023ef00a7d 100644
--- a/sound/i2c/other/Makefile
+++ b/sound/i2c/other/Makefile
@@ -3,6 +3,7 @@
# Copyright (c) 2003 by Jaroslav Kysela <perex@suse.cz>
#
+snd-ak4114-objs := ak4114.o
snd-ak4117-objs := ak4117.o
snd-ak4xxx-adda-objs := ak4xxx-adda.o
snd-tea575x-tuner-objs := tea575x-tuner.o
@@ -11,4 +12,5 @@ snd-tea575x-tuner-objs := tea575x-tuner.o
obj-$(CONFIG_SND_PDAUDIOCF) += snd-ak4117.o
obj-$(CONFIG_SND_ICE1712) += snd-ak4xxx-adda.o
obj-$(CONFIG_SND_ICE1724) += snd-ak4xxx-adda.o
+obj-$(CONFIG_SND_ICE1724) += snd-ak4114.o
obj-$(CONFIG_SND_FM801_TEA575X) += snd-tea575x-tuner.o
diff --git a/sound/i2c/other/ak4114.c b/sound/i2c/other/ak4114.c
new file mode 100644
index 0000000000000..f5e6018ea3f47
--- /dev/null
+++ b/sound/i2c/other/ak4114.c
@@ -0,0 +1,580 @@
+/*
+ * Routines for control of the AK4114 via I2C and 4-wire serial interface
+ * IEC958 (S/PDIF) receiver by Asahi Kasei
+ * Copyright (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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <sound/driver.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <sound/core.h>
+#include <sound/control.h>
+#include <sound/pcm.h>
+#include <sound/ak4114.h>
+#include <sound/asoundef.h>
+
+MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
+MODULE_DESCRIPTION("AK4114 IEC958 (S/PDIF) receiver by Asahi Kasei");
+MODULE_LICENSE("GPL");
+
+#define AK4114_ADDR 0x00 /* fixed address */
+
+static void ak4114_stats(void *);
+
+static void reg_write(ak4114_t *ak4114, unsigned char reg, unsigned char val)
+{
+ ak4114->write(ak4114->private_data, reg, val);
+ if (reg <= AK4114_REG_INT1_MASK)
+ ak4114->regmap[reg] = val;
+ else if (reg >= AK4114_REG_RXCSB0 && reg <= AK4114_REG_TXCSB4)
+ ak4114->txcsb[reg-AK4114_REG_RXCSB0] = val;
+}
+
+static inline unsigned char reg_read(ak4114_t *ak4114, unsigned char reg)
+{
+ return ak4114->read(ak4114->private_data, reg);
+}
+
+#if 0
+static void reg_dump(ak4114_t *ak4114)
+{
+ int i;
+
+ printk("AK4114 REG DUMP:\n");
+ for (i = 0; i < 0x20; i++)
+ printk("reg[%02x] = %02x (%02x)\n", i, reg_read(ak4114, i), i < sizeof(ak4114->regmap) ? ak4114->regmap[i] : 0);
+}
+#endif
+
+static void snd_ak4114_free(ak4114_t *chip)
+{
+ chip->init = 1; /* don't schedule new work */
+ mb();
+ if (chip->workqueue != NULL) {
+ flush_workqueue(chip->workqueue);
+ destroy_workqueue(chip->workqueue);
+ }
+ kfree(chip);
+}
+
+static int snd_ak4114_dev_free(snd_device_t *device)
+{
+ ak4114_t *chip = device->device_data;
+ snd_ak4114_free(chip);
+ return 0;
+}
+
+int snd_ak4114_create(snd_card_t *card,
+ ak4114_read_t *read, ak4114_write_t *write,
+ unsigned char pgm[7], unsigned char txcsb[5],
+ void *private_data, ak4114_t **r_ak4114)
+{
+ ak4114_t *chip;
+ int err = 0;
+ unsigned char reg;
+ static snd_device_ops_t ops = {
+ .dev_free = snd_ak4114_dev_free,
+ };
+
+ chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+ if (chip == NULL)
+ return -ENOMEM;
+ spin_lock_init(&chip->lock);
+ chip->card = card;
+ chip->read = read;
+ chip->write = write;
+ chip->private_data = private_data;
+
+ for (reg = 0; reg < 7; reg++)
+ chip->regmap[reg] = pgm[reg];
+ for (reg = 0; reg < 5; reg++)
+ chip->txcsb[reg] = txcsb[reg];
+
+ chip->workqueue = create_workqueue("snd-ak4114");
+ if (chip->workqueue == NULL) {
+ kfree(chip);
+ return -ENOMEM;
+ }
+
+ snd_ak4114_reinit(chip);
+
+ chip->rcs0 = reg_read(chip, AK4114_REG_RCS0) & ~(AK4114_QINT | AK4114_CINT);
+ chip->rcs1 = reg_read(chip, AK4114_REG_RCS1);
+
+ if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0)
+ goto __fail;
+
+ if (r_ak4114)
+ *r_ak4114 = chip;
+ return 0;
+
+ __fail:
+ snd_ak4114_free(chip);
+ return err < 0 ? err : -EIO;
+}
+
+void snd_ak4114_reg_write(ak4114_t *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);
+ else if (reg >= AK4114_REG_TXCSB0 && reg <= AK4114_REG_TXCSB4)
+ reg_write(chip, reg, (chip->txcsb[reg] & ~mask) | val);
+}
+
+void snd_ak4114_reinit(ak4114_t *chip)
+{
+ unsigned char old = chip->regmap[AK4114_REG_PWRDN], reg;
+
+ chip->init = 1;
+ mb();
+ flush_workqueue(chip->workqueue);
+ /* bring the chip to reset state and powerdown state */
+ reg_write(chip, AK4114_REG_PWRDN, old & ~(AK4114_RST|AK4114_PWN));
+ udelay(200);
+ /* release reset, but leave powerdown */
+ reg_write(chip, AK4114_REG_PWRDN, (old | AK4114_RST) & ~AK4114_PWN);
+ udelay(200);
+ for (reg = 1; reg < 7; reg++)
+ reg_write(chip, reg, chip->regmap[reg]);
+ for (reg = 0; reg < 5; reg++)
+ reg_write(chip, reg + AK4114_REG_TXCSB0, chip->txcsb[reg]);
+ /* release powerdown, everything is initialized now */
+ reg_write(chip, AK4114_REG_PWRDN, old | AK4114_RST | AK4114_PWN);
+ /* bring up statistics / event queing */
+ chip->init = 0;
+ INIT_WORK(&chip->work, ak4114_stats, chip);
+ queue_delayed_work(chip->workqueue, &chip->work, HZ / 10);
+}
+
+static unsigned int external_rate(unsigned char rcs1)
+{
+ switch (rcs1 & (AK4114_FS0|AK4114_FS1|AK4114_FS2|AK4114_FS3)) {
+ case AK4114_FS_32000HZ: return 32000;
+ case AK4114_FS_44100HZ: return 44100;
+ case AK4114_FS_48000HZ: return 48000;
+ case AK4114_FS_88200HZ: return 88200;
+ case AK4114_FS_96000HZ: return 96000;
+ case AK4114_FS_176400HZ: return 176400;
+ case AK4114_FS_192000HZ: return 192000;
+ default: return 0;
+ }
+}
+
+static int snd_ak4114_in_error_info(snd_kcontrol_t *kcontrol,
+ snd_ctl_elem_info_t *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = 1;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = LONG_MAX;
+ return 0;
+}
+
+static int snd_ak4114_in_error_get(snd_kcontrol_t *kcontrol,
+ snd_ctl_elem_value_t *ucontrol)
+{
+ ak4114_t *chip = snd_kcontrol_chip(kcontrol);
+ long *ptr;
+
+ spin_lock_irq(&chip->lock);
+ ptr = (long *)(((char *)chip) + kcontrol->private_value);
+ ucontrol->value.integer.value[0] = *ptr;
+ *ptr = 0;
+ spin_unlock_irq(&chip->lock);
+ return 0;
+}
+
+static int snd_ak4114_in_bit_info(snd_kcontrol_t *kcontrol,
+ snd_ctl_elem_info_t *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+ uinfo->count = 1;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 1;
+ return 0;
+}
+
+static int snd_ak4114_in_bit_get(snd_kcontrol_t *kcontrol,
+ snd_ctl_elem_value_t *ucontrol)
+{
+ ak4114_t *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;
+
+ ucontrol->value.integer.value[0] = ((reg_read(chip, reg) & (1 << bit)) ? 1 : 0) ^ inv;
+ return 0;
+}
+
+static int snd_ak4114_rate_info(snd_kcontrol_t *kcontrol,
+ snd_ctl_elem_info_t *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = 1;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 192000;
+ return 0;
+}
+
+static int snd_ak4114_rate_get(snd_kcontrol_t *kcontrol,
+ snd_ctl_elem_value_t *ucontrol)
+{
+ ak4114_t *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)
+{
+ 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)
+{
+ ak4114_t *chip = snd_kcontrol_chip(kcontrol);
+ unsigned i;
+
+ for (i = 0; i < AK4114_REG_RXCSB_SIZE; i++)
+ ucontrol->value.iec958.status[i] = reg_read(chip, AK4114_REG_RXCSB0 + i);
+ return 0;
+}
+
+static int snd_ak4114_spdif_playback_get(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t * ucontrol)
+{
+ ak4114_t *chip = snd_kcontrol_chip(kcontrol);
+ unsigned i;
+
+ for (i = 0; i < AK4114_REG_TXCSB_SIZE; i++)
+ ucontrol->value.iec958.status[i] = chip->txcsb[i];
+ return 0;
+}
+
+static int snd_ak4114_spdif_playback_put(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t * ucontrol)
+{
+ ak4114_t *chip = snd_kcontrol_chip(kcontrol);
+ unsigned i;
+
+ for (i = 0; i < AK4114_REG_TXCSB_SIZE; i++)
+ reg_write(chip, AK4114_REG_TXCSB0 + i, ucontrol->value.iec958.status[i]);
+ return 0;
+}
+
+static int snd_ak4114_spdif_mask_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * 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)
+{
+ 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)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 0xffff;
+ uinfo->count = 4;
+ return 0;
+}
+
+static int snd_ak4114_spdif_pget(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t * ucontrol)
+{
+ ak4114_t *chip = snd_kcontrol_chip(kcontrol);
+ unsigned short tmp;
+
+ ucontrol->value.integer.value[0] = 0xf8f2;
+ ucontrol->value.integer.value[1] = 0x4e1f;
+ tmp = reg_read(chip, AK4114_REG_Pc0) | (reg_read(chip, AK4114_REG_Pc1) << 8);
+ ucontrol->value.integer.value[2] = tmp;
+ tmp = reg_read(chip, AK4114_REG_Pd0) | (reg_read(chip, AK4114_REG_Pd1) << 8);
+ ucontrol->value.integer.value[3] = tmp;
+ return 0;
+}
+
+static int snd_ak4114_spdif_qinfo(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * 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)
+{
+ ak4114_t *chip = snd_kcontrol_chip(kcontrol);
+ unsigned i;
+
+ for (i = 0; i < AK4114_REG_QSUB_SIZE; i++)
+ ucontrol->value.bytes.data[i] = reg_read(chip, AK4114_REG_QSUB_ADDR + i);
+ return 0;
+}
+
+/* Don't forget to change AK4114_CONTROLS define!!! */
+static snd_kcontrol_new_t 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),
+},
+{
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = "IEC958 V-Bit 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, v_bit_errors),
+},
+{
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = "IEC958 C-CRC 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, ccrc_errors),
+},
+{
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = "IEC958 Q-CRC 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, qcrc_errors),
+},
+{
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = "IEC958 External Rate",
+ .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
+ .info = snd_ak4114_rate_info,
+ .get = snd_ak4114_rate_get,
+},
+{
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK),
+ .access = SNDRV_CTL_ELEM_ACCESS_READ,
+ .info = snd_ak4114_spdif_mask_info,
+ .get = snd_ak4114_spdif_mask_get,
+},
+{
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
+ .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
+ .info = snd_ak4114_spdif_info,
+ .get = snd_ak4114_spdif_playback_get,
+ .put = snd_ak4114_spdif_playback_put,
+},
+{
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,MASK),
+ .access = SNDRV_CTL_ELEM_ACCESS_READ,
+ .info = snd_ak4114_spdif_mask_info,
+ .get = snd_ak4114_spdif_mask_get,
+},
+{
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,DEFAULT),
+ .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
+ .info = snd_ak4114_spdif_info,
+ .get = snd_ak4114_spdif_get,
+},
+{
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = "IEC958 Preample Capture Default",
+ .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
+ .info = snd_ak4114_spdif_pinfo,
+ .get = snd_ak4114_spdif_pget,
+},
+{
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = "IEC958 Q-subcode Capture Default",
+ .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
+ .info = snd_ak4114_spdif_qinfo,
+ .get = snd_ak4114_spdif_qget,
+},
+{
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = "IEC958 Audio",
+ .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
+ .info = snd_ak4114_in_bit_info,
+ .get = snd_ak4114_in_bit_get,
+ .private_value = (1<<31) | (1<<8) | AK4114_REG_RCS0,
+},
+{
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = "IEC958 Non-PCM Bitstream",
+ .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
+ .info = snd_ak4114_in_bit_info,
+ .get = snd_ak4114_in_bit_get,
+ .private_value = (6<<8) | AK4114_REG_RCS1,
+},
+{
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = "IEC958 DTS Bitstream",
+ .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
+ .info = snd_ak4114_in_bit_info,
+ .get = snd_ak4114_in_bit_get,
+ .private_value = (3<<8) | AK4114_REG_RCS1,
+}
+};
+
+int snd_ak4114_build(ak4114_t *ak4114,
+ snd_pcm_substream_t *ply_substream,
+ snd_pcm_substream_t *cap_substream)
+{
+ snd_kcontrol_t *kctl;
+ unsigned int idx;
+ int err;
+
+ snd_assert(cap_substream, return -EINVAL);
+ ak4114->playback_substream = ply_substream;
+ ak4114->capture_substream = cap_substream;
+ for (idx = 0; idx < AK4114_CONTROLS; idx++) {
+ kctl = snd_ctl_new1(&snd_ak4114_iec958_controls[idx], ak4114);
+ if (kctl == NULL)
+ return -ENOMEM;
+ if (!strstr(kctl->id.name, "Playback")) {
+ if (ply_substream == NULL) {
+ snd_ctl_free_one(kctl);
+ ak4114->kctls[idx] = NULL;
+ continue;
+ }
+ kctl->id.device = ply_substream->pcm->device;
+ kctl->id.subdevice = ply_substream->number;
+ } else {
+ kctl->id.device = cap_substream->pcm->device;
+ kctl->id.subdevice = cap_substream->number;
+ }
+ err = snd_ctl_add(ak4114->card, kctl);
+ if (err < 0)
+ return err;
+ ak4114->kctls[idx] = kctl;
+ }
+ return 0;
+}
+
+int snd_ak4114_external_rate(ak4114_t *ak4114)
+{
+ unsigned char rcs1;
+
+ rcs1 = reg_read(ak4114, AK4114_REG_RCS1);
+ return external_rate(rcs1);
+}
+
+int snd_ak4114_check_rate_and_errors(ak4114_t *ak4114, unsigned int flags)
+{
+ snd_pcm_runtime_t *runtime = ak4114->capture_substream ? ak4114->capture_substream->runtime : NULL;
+ unsigned long _flags;
+ int res = 0;
+ unsigned char rcs0, rcs1;
+ unsigned char c0, c1;
+
+ rcs1 = reg_read(ak4114, AK4114_REG_RCS1);
+ if (flags & AK4114_CHECK_NO_STAT)
+ goto __rate;
+ rcs0 = reg_read(ak4114, AK4114_REG_RCS0);
+ spin_lock_irqsave(&ak4114->lock, _flags);
+ if (rcs0 & AK4114_PAR)
+ ak4114->parity_errors++;
+ if (rcs1 & AK4114_V)
+ ak4114->v_bit_errors++;
+ if (rcs1 & AK4114_CCRC)
+ ak4114->ccrc_errors++;
+ if (rcs1 & AK4114_QCRC)
+ ak4114->qcrc_errors++;
+ c0 = (ak4114->rcs0 & (AK4114_QINT | AK4114_CINT | AK4114_PEM | AK4114_AUDION | AK4114_AUTO | AK4114_UNLCK)) ^
+ (rcs0 & (AK4114_QINT | AK4114_CINT | AK4114_PEM | AK4114_AUDION | AK4114_AUTO | AK4114_UNLCK));
+ c1 = (ak4114->rcs1 & 0xf0) ^ (rcs1 & 0xf0);
+ ak4114->rcs0 = rcs0 & ~(AK4114_QINT | AK4114_CINT);
+ ak4114->rcs1 = rcs1;
+ spin_unlock_irqrestore(&ak4114->lock, _flags);
+
+ if (rcs0 & AK4114_PAR)
+ snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4114->kctls[0]->id);
+ if (rcs0 & AK4114_V)
+ snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4114->kctls[1]->id);
+ if (rcs1 & AK4114_CCRC)
+ snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4114->kctls[2]->id);
+ if (rcs1 & AK4114_QCRC)
+ snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4114->kctls[3]->id);
+
+ /* rate change */
+ if (c1 & 0xf0)
+ snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4114->kctls[4]->id);
+
+ if ((c0 & AK4114_PEM) | (c0 & AK4114_CINT))
+ snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4114->kctls[9]->id);
+ if (c0 & AK4114_QINT)
+ snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4114->kctls[10]->id);
+
+ if (c0 & AK4114_AUDION)
+ snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4114->kctls[11]->id);
+ if (c0 & AK4114_AUTO)
+ snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4114->kctls[12]->id);
+ if (c0 & AK4114_DTSCD)
+ snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4114->kctls[13]->id);
+
+ if (ak4114->change_callback && (c0 | c1) != 0)
+ ak4114->change_callback(ak4114, c0, c1);
+
+ __rate:
+ /* compare rate */
+ res = external_rate(rcs1);
+ if (!(flags & AK4114_CHECK_NO_RATE) && runtime && runtime->rate != res) {
+ snd_pcm_stream_lock_irqsave(ak4114->capture_substream, _flags);
+ if (snd_pcm_running(ak4114->capture_substream)) {
+ // printk("rate changed (%i <- %i)\n", runtime->rate, res);
+ snd_pcm_stop(ak4114->capture_substream, SNDRV_PCM_STATE_DRAINING);
+ wake_up(&runtime->sleep);
+ res = 1;
+ }
+ snd_pcm_stream_unlock_irqrestore(ak4114->capture_substream, _flags);
+ }
+ return res;
+}
+
+static void ak4114_stats(void *data)
+{
+ ak4114_t *chip = (ak4114_t *)data;
+
+ if (chip->init)
+ return;
+ snd_ak4114_check_rate_and_errors(chip, 0);
+ queue_delayed_work(chip->workqueue, &chip->work, HZ / 10);
+}
+
+EXPORT_SYMBOL(snd_ak4114_create);
+EXPORT_SYMBOL(snd_ak4114_reg_write);
+EXPORT_SYMBOL(snd_ak4114_reinit);
+EXPORT_SYMBOL(snd_ak4114_build);
+EXPORT_SYMBOL(snd_ak4114_external_rate);
+EXPORT_SYMBOL(snd_ak4114_check_rate_and_errors);
diff --git a/sound/i2c/other/ak4xxx-adda.c b/sound/i2c/other/ak4xxx-adda.c
index abd82625bfd82..db2b7274a9d6e 100644
--- a/sound/i2c/other/ak4xxx-adda.c
+++ b/sound/i2c/other/ak4xxx-adda.c
@@ -1,8 +1,8 @@
/*
- * ALSA driver for AK4524 / AK4528 / AK4529 / AK4355 / AK4381
+ * ALSA driver for AK4524 / AK4528 / AK4529 / AK4355 / AK4358 / AK4381
* AD and DA converters
*
- * Copyright (c) 2000-2003 Jaroslav Kysela <perex@suse.cz>,
+ * Copyright (c) 2000-2004 Jaroslav Kysela <perex@suse.cz>,
* Takashi Iwai <tiwai@suse.de>
*
* This program is free software; you can redistribute it and/or modify
@@ -84,6 +84,7 @@ void snd_akm4xxx_reset(akm4xxx_t *ak, int state)
/* FIXME: needed for ak4529? */
break;
case SND_AK4355:
+ case SND_AK4358:
if (state) {
snd_akm4xxx_write(ak, 0, 0x01, 0x02); /* reset and soft-mute */
return;
@@ -166,6 +167,24 @@ void snd_akm4xxx_init(akm4xxx_t *ak)
0x01, 0x01, /* 1: un-reset, unmute */
0xff, 0xff
};
+ static unsigned char inits_ak4358[] = {
+ 0x01, 0x02, /* 1: reset and soft-mute */
+ 0x00, 0x06, /* 0: mode3(i2s), disable auto-clock detect, disable DZF, sharp roll-off, RSTN#=0 */
+ 0x02, 0x0e, /* 2: DA's power up, normal speed, RSTN#=0 */
+ // 0x02, 0x2e, /* quad speed */
+ 0x03, 0x01, /* 3: de-emphasis off */
+ 0x04, 0x00, /* 4: LOUT1 volume muted */
+ 0x05, 0x00, /* 5: ROUT1 volume muted */
+ 0x06, 0x00, /* 6: LOUT2 volume muted */
+ 0x07, 0x00, /* 7: ROUT2 volume muted */
+ 0x08, 0x00, /* 8: LOUT3 volume muted */
+ 0x09, 0x00, /* 9: ROUT3 volume muted */
+ 0x0b, 0x00, /* b: LOUT4 volume muted */
+ 0x0c, 0x00, /* c: ROUT4 volume muted */
+ 0x0a, 0x00, /* a: DATT speed=0, ignore DZF */
+ 0x01, 0x01, /* 1: un-reset, unmute */
+ 0xff, 0xff
+ };
static unsigned char inits_ak4381[] = {
0x00, 0x0c, /* 0: mode3(i2s), disable auto-clock detect */
0x01, 0x02, /* 1: de-emphasis off, normal speed, sharp roll-off, DZF off */
@@ -197,6 +216,10 @@ void snd_akm4xxx_init(akm4xxx_t *ak)
inits = inits_ak4355;
num_chips = 1;
break;
+ case SND_AK4358:
+ inits = inits_ak4358;
+ num_chips = 1;
+ break;
case SND_AK4381:
inits = inits_ak4381;
num_chips = ak->num_dacs / 2;
@@ -343,106 +366,121 @@ static int snd_akm4xxx_deemphasis_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_val
int snd_akm4xxx_build_controls(akm4xxx_t *ak)
{
unsigned int idx, num_emphs;
+ snd_kcontrol_t *ctl;
int err;
+ ctl = kmalloc(sizeof(*ctl), GFP_KERNEL);
+ if (! ctl)
+ return -ENOMEM;
+
for (idx = 0; idx < ak->num_dacs; ++idx) {
- snd_kcontrol_t ctl;
- memset(&ctl, 0, sizeof(ctl));
- strcpy(ctl.id.name, "DAC Volume");
- ctl.id.index = idx + ak->idx_offset * 2;
- ctl.id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
- ctl.count = 1;
- ctl.info = snd_akm4xxx_volume_info;
- ctl.get = snd_akm4xxx_volume_get;
- ctl.put = snd_akm4xxx_volume_put;
+ memset(ctl, 0, sizeof(*ctl));
+ strcpy(ctl->id.name, "DAC Volume");
+ ctl->id.index = idx + ak->idx_offset * 2;
+ ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+ ctl->count = 1;
+ ctl->info = snd_akm4xxx_volume_info;
+ ctl->get = snd_akm4xxx_volume_get;
+ ctl->put = snd_akm4xxx_volume_put;
switch (ak->type) {
case SND_AK4524:
- ctl.private_value = AK_COMPOSE(idx/2, (idx%2) + 6, 0, 127); /* register 6 & 7 */
+ ctl->private_value = AK_COMPOSE(idx/2, (idx%2) + 6, 0, 127); /* register 6 & 7 */
break;
case SND_AK4528:
- ctl.private_value = AK_COMPOSE(idx/2, (idx%2) + 4, 0, 127); /* register 4 & 5 */
+ ctl->private_value = AK_COMPOSE(idx/2, (idx%2) + 4, 0, 127); /* register 4 & 5 */
break;
case SND_AK4529: {
int val = idx < 6 ? idx + 2 : (idx - 6) + 0xb; /* registers 2-7 and b,c */
- ctl.private_value = AK_COMPOSE(0, val, 0, 255) | AK_INVERT;
+ ctl->private_value = AK_COMPOSE(0, val, 0, 255) | AK_INVERT;
break;
}
case SND_AK4355:
- ctl.private_value = AK_COMPOSE(0, idx + 4, 0, 255); /* register 4-9, chip #0 only */
+ ctl->private_value = AK_COMPOSE(0, idx + 4, 0, 255); /* register 4-9, chip #0 only */
+ break;
+ case SND_AK4358:
+ if (idx >= 6)
+ ctl->private_value = AK_COMPOSE(0, idx + 5, 0, 255); /* register 4-9, chip #0 only */
+ else
+ ctl->private_value = AK_COMPOSE(0, idx + 4, 0, 255); /* register 4-9, chip #0 only */
break;
case SND_AK4381:
- ctl.private_value = AK_COMPOSE(idx/2, (idx%2) + 3, 0, 255); /* register 3 & 4 */
+ ctl->private_value = AK_COMPOSE(idx/2, (idx%2) + 3, 0, 255); /* register 3 & 4 */
break;
default:
- return -EINVAL;
- }
- ctl.private_data = ak;
- if ((err = snd_ctl_add(ak->card, snd_ctl_new(&ctl, SNDRV_CTL_ELEM_ACCESS_READ|SNDRV_CTL_ELEM_ACCESS_WRITE))) < 0)
- return err;
+ err = -EINVAL;
+ goto __error;
+ }
+ ctl->private_data = ak;
+ if ((err = snd_ctl_add(ak->card, snd_ctl_new(ctl, SNDRV_CTL_ELEM_ACCESS_READ|SNDRV_CTL_ELEM_ACCESS_WRITE))) < 0)
+ goto __error;
}
for (idx = 0; idx < ak->num_adcs && ak->type == SND_AK4524; ++idx) {
- snd_kcontrol_t ctl;
- memset(&ctl, 0, sizeof(ctl));
- strcpy(ctl.id.name, "ADC Volume");
- ctl.id.index = idx + ak->idx_offset * 2;
- ctl.id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
- ctl.count = 1;
- ctl.info = snd_akm4xxx_volume_info;
- ctl.get = snd_akm4xxx_volume_get;
- ctl.put = snd_akm4xxx_volume_put;
- ctl.private_value = AK_COMPOSE(idx/2, (idx%2) + 4, 0, 127); /* register 4 & 5 */
- ctl.private_data = ak;
- if ((err = snd_ctl_add(ak->card, snd_ctl_new(&ctl, SNDRV_CTL_ELEM_ACCESS_READ|SNDRV_CTL_ELEM_ACCESS_WRITE))) < 0)
- return err;
- memset(&ctl, 0, sizeof(ctl));
- strcpy(ctl.id.name, "IPGA Analog Capture Volume");
- ctl.id.index = idx + ak->idx_offset * 2;
- ctl.id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
- ctl.count = 1;
- ctl.info = snd_akm4xxx_ipga_gain_info;
- ctl.get = snd_akm4xxx_ipga_gain_get;
- ctl.put = snd_akm4xxx_ipga_gain_put;
- ctl.private_value = AK_COMPOSE(idx/2, (idx%2) + 4, 0, 0); /* register 4 & 5 */
- ctl.private_data = ak;
- if ((err = snd_ctl_add(ak->card, snd_ctl_new(&ctl, SNDRV_CTL_ELEM_ACCESS_READ|SNDRV_CTL_ELEM_ACCESS_WRITE))) < 0)
- return err;
+ memset(ctl, 0, sizeof(*ctl));
+ strcpy(ctl->id.name, "ADC Volume");
+ ctl->id.index = idx + ak->idx_offset * 2;
+ ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+ ctl->count = 1;
+ ctl->info = snd_akm4xxx_volume_info;
+ ctl->get = snd_akm4xxx_volume_get;
+ ctl->put = snd_akm4xxx_volume_put;
+ ctl->private_value = AK_COMPOSE(idx/2, (idx%2) + 4, 0, 127); /* register 4 & 5 */
+ ctl->private_data = ak;
+ if ((err = snd_ctl_add(ak->card, snd_ctl_new(ctl, SNDRV_CTL_ELEM_ACCESS_READ|SNDRV_CTL_ELEM_ACCESS_WRITE))) < 0)
+ goto __error;
+
+ memset(ctl, 0, sizeof(*ctl));
+ strcpy(ctl->id.name, "IPGA Analog Capture Volume");
+ ctl->id.index = idx + ak->idx_offset * 2;
+ ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+ ctl->count = 1;
+ ctl->info = snd_akm4xxx_ipga_gain_info;
+ ctl->get = snd_akm4xxx_ipga_gain_get;
+ ctl->put = snd_akm4xxx_ipga_gain_put;
+ ctl->private_value = AK_COMPOSE(idx/2, (idx%2) + 4, 0, 0); /* register 4 & 5 */
+ ctl->private_data = ak;
+ if ((err = snd_ctl_add(ak->card, snd_ctl_new(ctl, SNDRV_CTL_ELEM_ACCESS_READ|SNDRV_CTL_ELEM_ACCESS_WRITE))) < 0)
+ goto __error;
}
- if (ak->type == SND_AK4355)
+ if (ak->type == SND_AK4355 || ak->type == SND_AK4358)
num_emphs = 1;
else
num_emphs = ak->num_dacs / 2;
for (idx = 0; idx < num_emphs; idx++) {
- snd_kcontrol_t ctl;
- memset(&ctl, 0, sizeof(ctl));
- strcpy(ctl.id.name, "Deemphasis");
- ctl.id.index = idx + ak->idx_offset;
- ctl.id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
- ctl.count = 1;
- ctl.info = snd_akm4xxx_deemphasis_info;
- ctl.get = snd_akm4xxx_deemphasis_get;
- ctl.put = snd_akm4xxx_deemphasis_put;
+ memset(ctl, 0, sizeof(*ctl));
+ strcpy(ctl->id.name, "Deemphasis");
+ ctl->id.index = idx + ak->idx_offset;
+ ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+ ctl->count = 1;
+ ctl->info = snd_akm4xxx_deemphasis_info;
+ ctl->get = snd_akm4xxx_deemphasis_get;
+ ctl->put = snd_akm4xxx_deemphasis_put;
switch (ak->type) {
case SND_AK4524:
case SND_AK4528:
- ctl.private_value = AK_COMPOSE(idx, 3, 0, 0); /* register 3 */
+ ctl->private_value = AK_COMPOSE(idx, 3, 0, 0); /* register 3 */
break;
case SND_AK4529: {
int shift = idx == 3 ? 6 : (2 - idx) * 2;
- ctl.private_value = AK_COMPOSE(0, 8, shift, 0); /* register 8 with shift */
+ ctl->private_value = AK_COMPOSE(0, 8, shift, 0); /* register 8 with shift */
break;
}
case SND_AK4355:
- ctl.private_value = AK_COMPOSE(idx, 3, 0, 0);
+ case SND_AK4358:
+ ctl->private_value = AK_COMPOSE(idx, 3, 0, 0);
break;
case SND_AK4381:
- ctl.private_value = AK_COMPOSE(idx, 1, 1, 0);
+ ctl->private_value = AK_COMPOSE(idx, 1, 1, 0);
break;
}
- ctl.private_data = ak;
- if ((err = snd_ctl_add(ak->card, snd_ctl_new(&ctl, SNDRV_CTL_ELEM_ACCESS_READ|SNDRV_CTL_ELEM_ACCESS_WRITE))) < 0)
- return err;
+ ctl->private_data = ak;
+ if ((err = snd_ctl_add(ak->card, snd_ctl_new(ctl, SNDRV_CTL_ELEM_ACCESS_READ|SNDRV_CTL_ELEM_ACCESS_WRITE))) < 0)
+ goto __error;
}
- return 0;
+ err = 0;
+
+ __error:
+ kfree(ctl);
+ return err;
}
static int __init alsa_akm4xxx_module_init(void)
diff --git a/sound/i2c/other/tea575x-tuner.c b/sound/i2c/other/tea575x-tuner.c
index 38dbacf90a92d..0f05a2b9a3702 100644
--- a/sound/i2c/other/tea575x-tuner.c
+++ b/sound/i2c/other/tea575x-tuner.c
@@ -168,6 +168,10 @@ static int snd_tea575x_ioctl(struct inode *inode, struct file *file,
}
}
+static void snd_tea575x_release(struct video_device *vfd)
+{
+}
+
/*
* initialize all the tea575x chips
*/
@@ -186,6 +190,7 @@ void snd_tea575x_init(tea575x_t *tea)
strcpy(tea->vd.name, tea->tea5759 ? "TEA5759 radio" : "TEA5757 radio");
tea->vd.type = VID_TYPE_TUNER;
tea->vd.hardware = VID_HARDWARE_RTRACK; /* FIXME: assign new number */
+ tea->vd.release = snd_tea575x_release;
video_set_drvdata(&tea->vd, tea);
tea->vd.fops = &tea->fops;
tea->fops.owner = tea->card->module;
diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig
index 7e6cedb413f97..4a6be966bd9ff 100644
--- a/sound/isa/Kconfig
+++ b/sound/isa/Kconfig
@@ -3,6 +3,16 @@
menu "ISA devices"
depends on SND!=n && ISA
+config SND_AD1848_LIB
+ tristate
+ select SND_PCM
+ select SND_GENERIC_PM
+
+config SND_CS4231_LIB
+ tristate
+ select SND_PCM
+ select SND_GENERIC_PM
+
config SND_AD1816A
tristate "Analog Devices SoundPort AD1816A"
depends on SND && ISAPNP
@@ -19,7 +29,7 @@ config SND_AD1816A
config SND_AD1848
tristate "Generic AD1848/CS4248 driver"
depends on SND
- select SND_PCM
+ select SND_AD1848_LIB
help
Say Y here to include support for AD1848 (Analog Devices) or
CS4248 (Cirrus Logic - Crystal Semiconductors) chips.
@@ -34,7 +44,7 @@ config SND_CS4231
tristate "Generic Cirrus Logic CS4231 driver"
depends on SND
select SND_MPU401_UART
- select SND_PCM
+ select SND_CS4231_LIB
help
Say Y here to include support for CS4231 chips from Cirrus
Logic - Crystal Semiconductors.
@@ -47,7 +57,7 @@ config SND_CS4232
depends on SND
select SND_OPL3_LIB
select SND_MPU401_UART
- select SND_PCM
+ select SND_CS4231_LIB
help
Say Y here to include support for CS4232 chips from Cirrus
Logic - Crystal Semiconductors.
@@ -60,7 +70,7 @@ config SND_CS4236
depends on SND
select SND_OPL3_LIB
select SND_MPU401_UART
- select SND_PCM
+ select SND_CS4231_LIB
help
Say Y to include support for CS4235,CS4236,CS4237B,CS4238B,
CS4239 chips from Cirrus Logic - Crystal Semiconductors.
@@ -98,6 +108,7 @@ config SND_ES18XX
select SND_OPL3_LIB
select SND_MPU401_UART
select SND_PCM
+ select SND_GENERIC_PM
help
Say Y here to include support for ESS AudioDrive ES18xx chips.
@@ -138,7 +149,7 @@ config SND_GUSMAX
tristate "Gravis UltraSound MAX"
depends on SND
select SND_RAWMIDI
- select SND_PCM
+ select SND_CS4231_LIB
select SND_GUS_SYNTH
help
Say Y here to include support for Gravis UltraSound MAX
@@ -151,7 +162,7 @@ config SND_INTERWAVE
tristate "AMD InterWave, Gravis UltraSound PnP"
depends on SND
select SND_RAWMIDI
- select SND_PCM
+ select SND_CS4231_LIB
select SND_GUS_SYNTH
help
Say Y here to include support for AMD InterWave based
@@ -165,7 +176,7 @@ config SND_INTERWAVE_STB
tristate "AMD InterWave + TEA6330T (UltraSound 32-Pro)"
depends on SND
select SND_RAWMIDI
- select SND_PCM
+ select SND_CS4231_LIB
select SND_GUS_SYNTH
help
Say Y here to include support for AMD InterWave based
@@ -181,7 +192,7 @@ config SND_OPTI92X_AD1848
select SND_OPL3_LIB
select SND_OPL4_LIB
select SND_MPU401_UART
- select SND_PCM
+ select SND_AD1848_LIB
help
Say Y here to include support for soundcards based on Opti
82C92x or OTI-601 chips and using an AD1848 codec.
@@ -195,7 +206,7 @@ config SND_OPTI92X_CS4231
select SND_OPL3_LIB
select SND_OPL4_LIB
select SND_MPU401_UART
- select SND_PCM
+ select SND_CS4231_LIB
help
Say Y here to include support for soundcards based on Opti
82C92x chips and using a CS4231 codec.
@@ -268,7 +279,7 @@ config SND_WAVEFRONT
depends on SND
select SND_OPL3_LIB
select SND_MPU401_UART
- select SND_PCM
+ select SND_CS4231_LIB
help
Say Y here to include support for Turtle Beach Maui, Tropez
and Tropez+ soundcards based on the Wavefront chip.
@@ -294,7 +305,7 @@ config SND_AZT2320
depends on SND && ISAPNP
select SND_OPL3_LIB
select SND_MPU401_UART
- select SND_PCM
+ select SND_CS4231_LIB
help
Say Y here to include support for soundcards based on the
Aztech Systems AZT2320 chip.
@@ -305,7 +316,7 @@ config SND_AZT2320
config SND_CMI8330
tristate "C-Media CMI8330"
depends on SND
- select SND_PCM
+ select SND_AD1848_LIB
help
Say Y here to include support for soundcards based on the
C-Media CMI8330 chip.
@@ -331,7 +342,7 @@ config SND_OPL3SA2
depends on SND
select SND_OPL3_LIB
select SND_MPU401_UART
- select SND_PCM
+ select SND_CS4231_LIB
help
Say Y here to include support for Yamaha OPL3-SA2 and OPL3-SA3
chips.
@@ -342,7 +353,7 @@ config SND_OPL3SA2
config SND_SGALAXY
tristate "Aztech Sound Galaxy"
depends on SND
- select SND_PCM
+ select SND_AD1848_LIB
help
Say Y here to include support for Aztech Sound Galaxy
soundcards.
@@ -355,7 +366,7 @@ config SND_SSCAPE
depends on SND
select SND_HWDEP
select SND_MPU401_UART
- select SND_PCM
+ select SND_CS4231_LIB
help
Say Y here to include support for Ensoniq SoundScape PnP
soundcards.
diff --git a/sound/isa/ad1848/ad1848_lib.c b/sound/isa/ad1848/ad1848_lib.c
index 97b8f87108020..8fb3db103e485 100644
--- a/sound/isa/ad1848/ad1848_lib.c
+++ b/sound/isa/ad1848/ad1848_lib.c
@@ -644,7 +644,7 @@ static void snd_ad1848_thinkpad_twiddle(ad1848_t *chip, int on) {
}
#ifdef CONFIG_PM
-static int snd_ad1848_suspend(snd_card_t *card, unsigned int state)
+static int snd_ad1848_suspend(snd_card_t *card, pm_message_t state)
{
ad1848_t *chip = card->pm_private_data;
@@ -657,7 +657,7 @@ static int snd_ad1848_suspend(snd_card_t *card, unsigned int state)
return 0;
}
-static int snd_ad1848_resume(snd_card_t *card, unsigned int state)
+static int snd_ad1848_resume(snd_card_t *card)
{
ad1848_t *chip = card->pm_private_data;
diff --git a/sound/isa/als100.c b/sound/isa/als100.c
index 3fa1f5c532abb..ac8f136649832 100644
--- a/sound/isa/als100.c
+++ b/sound/isa/als100.c
@@ -121,7 +121,7 @@ static int __devinit snd_card_als100_pnp(int dev, struct snd_card_als100 *acard,
return -ENODEV;
}
acard->devmpu = pnp_request_card_device(card, id->devs[1].id, acard->dev);
- acard->devopl = pnp_request_card_device(card, id->devs[2].id, acard->devmpu);
+ acard->devopl = pnp_request_card_device(card, id->devs[2].id, acard->dev);
pdev = acard->dev;
diff --git a/sound/isa/cs423x/cs4231_lib.c b/sound/isa/cs423x/cs4231_lib.c
index 888e2b00f9d96..3e7a2a33a5cad 100644
--- a/sound/isa/cs423x/cs4231_lib.c
+++ b/sound/isa/cs423x/cs4231_lib.c
@@ -1394,7 +1394,7 @@ static void snd_cs4231_resume(cs4231_t *chip)
#endif
}
-static int snd_cs4231_pm_suspend(snd_card_t *card, unsigned int state)
+static int snd_cs4231_pm_suspend(snd_card_t *card, pm_message_t state)
{
cs4231_t *chip = card->pm_private_data;
if (chip->suspend)
@@ -1402,7 +1402,7 @@ static int snd_cs4231_pm_suspend(snd_card_t *card, unsigned int state)
return 0;
}
-static int snd_cs4231_pm_resume(snd_card_t *card, unsigned int state)
+static int snd_cs4231_pm_resume(snd_card_t *card)
{
cs4231_t *chip = card->pm_private_data;
if (chip->resume)
diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c
index 4939aad0aebbf..1d832b2adb7ca 100644
--- a/sound/isa/es18xx.c
+++ b/sound/isa/es18xx.c
@@ -1612,7 +1612,7 @@ 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, unsigned int state)
+static int snd_es18xx_suspend(snd_card_t *card, pm_message_t state)
{
es18xx_t *chip = card->pm_private_data;
@@ -1627,7 +1627,7 @@ static int snd_es18xx_suspend(snd_card_t *card, unsigned int state)
return 0;
}
-static int snd_es18xx_resume(snd_card_t *card, unsigned int state)
+static int snd_es18xx_resume(snd_card_t *card)
{
es18xx_t *chip = card->pm_private_data;
diff --git a/sound/isa/gus/gus_lfo.c b/sound/isa/gus/gus_lfo.c
deleted file mode 100644
index 94d0688502051..0000000000000
--- a/sound/isa/gus/gus_lfo.c
+++ /dev/null
@@ -1,429 +0,0 @@
-/*
- * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
- * Routines for control of LFO generators (tremolo & vibrato) for
- * GF1/InterWave chips...
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include <sound/driver.h>
-#include <sound/core.h>
-#include <sound/gus.h>
-
-/*
- * called by engine routines
- */
-
-static signed char snd_gf1_lfo_compute_value(snd_gus_card_t * gus,
- unsigned char *ptr)
-{
- unsigned int twaveinc, depth_delta;
- signed int result;
- unsigned short control, twave, depth, depth_final;
- unsigned char *ptr1;
-
- control = *(unsigned short *) (ptr + 0x00);
- ptr1 = ptr + ((control & 0x4000) >> 12);
- /* 1. add TWAVEINC to TWAVE and write the result back */
- /* LFO update rate is 689Hz, effect timer is in ms */
- if (gus->gf1.timer_slave)
- twaveinc = (689 * gus->gf1.timer_master_gus->gf1.effect_timer) / 1000;
- else
- twaveinc = (689 * gus->gf1.effect_timer) / 1000;
- if (!twaveinc)
- twaveinc++;
-#if 0
- printk("twaveinc = 0x%x, effect_timer = %i\n", twaveinc, gus->gf1.effect_timer);
-#endif
-
- depth = *(unsigned short *) (ptr1 + 0x0a);
- depth_final = *(unsigned char *) (ptr + 0x02) << 5;
- if (depth != depth_final) {
- depth_delta = ((twaveinc * *(ptr + 0x03)) + *(unsigned short *) (ptr + 0x04));
- *(unsigned short *) (ptr + 0x04) = depth_delta % 8000;
- depth_delta /= 8000;
- if (depth < depth_final) {
- if (depth + depth_delta > depth_final)
- depth = depth_final;
- else
- depth += depth_delta;
- }
- if (depth > depth_final) {
- if (depth - depth_delta < depth_final)
- depth = depth_final;
- else
- depth -= depth_delta;
- }
- *(unsigned short *) (ptr1 + 0x0a) = depth;
- }
- twaveinc *= (unsigned int) control & 0x7ff;
- twaveinc += *(unsigned short *) (ptr + 0x06);
- *(unsigned short *) (ptr + 0x06) = twaveinc % 1000;
-
- twave = *(unsigned short *) (ptr1 + 0x08);
- twave += (unsigned short) (twaveinc / (unsigned int) 1000);
- *(unsigned short *) (ptr1 + 0x08) = twave;
-
- if (!(control & 0x2000)) {
- /* 2. if shift is low */
- if (twave & 0x4000) { /* bit 14 high -> invert TWAVE 13-0 */
- twave ^= 0x3fff;
- twave &= ~0x4000;
- }
- /* TWAVE bit 15 is exclusive or'd with the invert bit (12) */
- twave ^= (control & 0x1000) << 3;
- } else {
- /* 2. if shift is high */
- if (twave & 0x8000) /* bit 15 high -> invert TWAVE 14-0 */
- twave ^= 0x7fff;
- /* the invert bit (12) is used as sign bit */
- if (control & 0x1000)
- twave |= 0x8000;
- else
- twave &= ~0x8000;
- }
- /* 3. multiply the 14-bit LFO waveform magnitude by 13-bit DEPTH */
-#if 0
- printk("c=0x%x,tw=0x%x,to=0x%x,d=0x%x,df=0x%x,di=0x%x,r=0x%x,r1=%i\n",
- control, twave,
- *(unsigned short *) (ptr1 + 0x08),
- depth, depth_final, *(ptr + 0x03),
- (twave & 0x7fff) * depth, ((twave & 0x7fff) * depth) >> 21);
-#endif
- result = (twave & 0x7fff) * depth;
- if (result) {
- /* shift */
- result >>= 21;
- result &= 0x3f;
- }
- /* add sign */
- if (twave & 0x8000)
- result = -result;
-#if 0
- printk("lfo final value = %i\n", result);
-#endif
- return result;
-}
-
-static void snd_gf1_lfo_register_setup(snd_gus_card_t * gus,
- snd_gf1_voice_t * voice,
- int lfo_type)
-{
- unsigned long flags;
-
- if (gus->gf1.enh_mode) {
- CLI(&flags);
- gf1_select_voice(gus, voice->number);
- if (lfo_type & 1) {
- snd_gf1_write8(gus, GF1_VB_FREQUENCY_LFO, voice->lfo_fc);
- voice->lfo_fc = 0;
- }
- if (lfo_type & 2) {
- snd_gf1_write8(gus, GF1_VB_VOLUME_LFO, voice->lfo_volume);
- voice->lfo_volume = 0;
- }
- STI(&flags);
- } else {
- /*
- * ok.. with old GF1 chip can be only vibrato emulated...
- * volume register can be in volume ramp state, so tremolo isn't simple..
- */
- if (!(lfo_type & 1))
- return;
-#if 0
- if (voice->lfo_fc)
- printk("setup - %i = %i\n", voice->number, voice->lfo_fc);
-#endif
- CLI(&flags);
- gf1_select_voice(gus, voice->number);
- snd_gf1_write16(gus, GF1_VW_FREQUENCY, voice->fc_register + voice->lfo_fc);
- STI(&flags);
- }
-}
-
-void snd_gf1_lfo_effect_interrupt(snd_gus_card_t * gus, snd_gf1_voice_t * voice)
-{
- unsigned char *ptr;
-
-#if 0
- if (voice->number != 0)
- return;
-#endif
- ptr = gus->gf1.lfos + ((voice->number) << 5);
- /* 1. vibrato */
- if (*(unsigned short *) (ptr + 0x00) & 0x8000)
- voice->lfo_fc = snd_gf1_lfo_compute_value(gus, ptr);
- /* 2. tremolo */
- ptr += 16;
- if (*(unsigned short *) (ptr + 0x00) & 0x8000)
- voice->lfo_volume = snd_gf1_lfo_compute_value(gus, ptr);
- /* 3. register setup */
- snd_gf1_lfo_register_setup(gus, voice, 3);
-}
-
-/*
-
- */
-
-void snd_gf1_lfo_init(snd_gus_card_t * gus)
-{
- if (gus->gf1.hw_lfo) {
- snd_gf1_i_write16(gus, GF1_GW_LFO_BASE, 0x0000);
- snd_gf1_dram_setmem(gus, 0, 0x0000, 1024);
- /* now enable LFO */
- snd_gf1_i_write8(gus, GF1_GB_GLOBAL_MODE, snd_gf1_i_look8(gus, GF1_GB_GLOBAL_MODE) | 0x02);
- }
- if (gus->gf1.sw_lfo) {
-#if 1
- gus->gf1.lfos = snd_calloc(1024);
- if (!gus->gf1.lfos)
-#endif
- gus->gf1.sw_lfo = 0;
- }
-}
-
-void snd_gf1_lfo_done(snd_gus_card_t * gus)
-{
- if (gus->gf1.sw_lfo) {
- if (gus->gf1.lfos) {
- snd_gf1_free(gus->gf1.lfos, 1024);
- gus->gf1.lfos = NULL;
- }
- }
-}
-
-void snd_gf1_lfo_program(snd_gus_card_t * gus, int voice, int lfo_type,
- struct ULTRA_STRU_IW_LFO_PROGRAM *program)
-{
- unsigned int lfo_addr, wave_select;
-
- wave_select = (program->freq_and_control & 0x4000) >> 12;
- lfo_addr = (voice << 5) | (lfo_type << 4);
- if (gus->gf1.hw_lfo) {
-#if 0
- printk("LMCI = 0x%x\n", snd_gf1_i_look8(gus, 0x53));
- printk("lfo_program: lfo_addr=0x%x,wave_sel=0x%x,fac=0x%x,df=0x%x,di=0x%x,twave=0x%x,depth=0x%x\n",
- lfo_addr, wave_select,
- program->freq_and_control,
- program->depth_final,
- program->depth_inc,
- program->twave,
- program->depth);
-#endif
- snd_gf1_poke(gus, lfo_addr + 0x02, program->depth_final);
- snd_gf1_poke(gus, lfo_addr + 0x03, program->depth_inc);
- snd_gf1_pokew(gus, lfo_addr + 0x08 + wave_select, program->twave);
- snd_gf1_pokew(gus, lfo_addr + 0x0a + wave_select, program->depth);
- snd_gf1_pokew(gus, lfo_addr + 0x00, program->freq_and_control);
-#if 0
- {
- int i = 0;
- for (i = 0; i < 16; i++)
- printk("%02x:", snd_gf1_peek(gus, lfo_addr + i));
- printk("\n");
- }
-#endif
- }
- if (gus->gf1.sw_lfo) {
- unsigned char *ptr = gus->gf1.lfos + lfo_addr;
-
- *(ptr + 0x02) = program->depth_final;
- *(ptr + 0x03) = program->depth_inc;
- *(unsigned short *) (ptr + 0x08 + wave_select) = program->twave;
- *(unsigned short *) (ptr + 0x0a + wave_select) = program->depth;
- *(unsigned short *) (ptr + 0x00) = program->freq_and_control;
- }
-}
-
-void snd_gf1_lfo_enable(snd_gus_card_t * gus, int voice, int lfo_type)
-{
- unsigned int lfo_addr;
-
- lfo_addr = (voice << 5) | (lfo_type << 4);
- if (gus->gf1.hw_lfo)
- snd_gf1_pokew(gus, lfo_addr + 0x00, snd_gf1_peekw(gus, lfo_addr + 0x00) | 0x8000);
- if (gus->gf1.sw_lfo) {
- unsigned char *ptr = gus->gf1.lfos + lfo_addr;
-
- *(unsigned short *) (ptr + 0x00) |= 0x8000;
- }
-}
-
-void snd_gf1_lfo_disable(snd_gus_card_t * gus, int voice, int lfo_type)
-{
- unsigned int lfo_addr;
-
- lfo_addr = (voice << 5) | (lfo_type << 4);
- if (gus->gf1.hw_lfo)
- snd_gf1_pokew(gus, lfo_addr + 0x00,
- snd_gf1_peekw(gus, lfo_addr + 0x00) & ~0x8000);
- if (gus->gf1.sw_lfo) {
- unsigned char *ptr = gus->gf1.lfos + lfo_addr;
-
- *(unsigned short *) (ptr + 0x00) &= ~0x8000;
- }
-}
-
-void snd_gf1_lfo_change_freq(snd_gus_card_t * gus, int voice,
- int lfo_type, int freq)
-{
- unsigned int lfo_addr;
-
- lfo_addr = (voice << 5) | (lfo_type << 4);
- if (gus->gf1.hw_lfo)
- snd_gf1_pokew(gus, lfo_addr + 0x00,
- (snd_gf1_peekw(gus, lfo_addr + 0x00) & ~0x7ff) | (freq & 0x7ff));
- if (gus->gf1.sw_lfo) {
- unsigned long flags;
- unsigned char *ptr = gus->gf1.lfos + lfo_addr;
-
- CLI(&flags);
- *(unsigned short *) (ptr + 0x00) &= ~0x7ff;
- *(unsigned short *) (ptr + 0x00) |= freq & 0x7ff;
- STI(&flags);
- }
-}
-
-void snd_gf1_lfo_change_depth(snd_gus_card_t * gus, int voice,
- int lfo_type, int depth)
-{
- unsigned long flags;
- unsigned int lfo_addr;
- unsigned short control = 0;
- unsigned char *ptr;
-
- lfo_addr = (voice << 5) | (lfo_type << 4);
- ptr = gus->gf1.lfos + lfo_addr;
- if (gus->gf1.hw_lfo)
- control = snd_gf1_peekw(gus, lfo_addr + 0x00);
- if (gus->gf1.sw_lfo)
- control = *(unsigned short *) (ptr + 0x00);
- if (depth < 0) {
- control |= 0x1000;
- depth = -depth;
- } else
- control &= ~0x1000;
- if (gus->gf1.hw_lfo) {
- CLI(&flags);
- snd_gf1_poke(gus, lfo_addr + 0x02, (unsigned char) depth);
- snd_gf1_pokew(gus, lfo_addr + 0x0a + ((control & 0x4000) >> 12), depth << 5);
- snd_gf1_pokew(gus, lfo_addr + 0x00, control);
- STI(&flags);
- }
- if (gus->gf1.sw_lfo) {
- unsigned char *ptr = gus->gf1.lfos + lfo_addr;
-
- CLI(&flags);
- *(ptr + 0x02) = (unsigned char) depth;
- *(unsigned short *) (ptr + 0x0a + ((control & 0x4000) >> 12)) = depth << 5;
- *(unsigned short *) (ptr + 0x00) = control;
- STI(&flags);
- }
-}
-
-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)
-{
- struct ULTRA_STRU_IW_LFO_PROGRAM program;
-
- program.freq_and_control = 0x8000 | (freq & 0x7ff);
- if (shape & ULTRA_STRU_IW_LFO_SHAPE_POSTRIANGLE)
- program.freq_and_control |= 0x2000;
- if (depth < 0) {
- program.freq_and_control |= 0x1000;
- depth = -depth;
- }
- program.twave = 0;
- program.depth = current_depth;
- program.depth_final = depth;
- if (sweep) {
- program.depth_inc = (unsigned char) (((int) ((depth << 5) - current_depth) << 9) / (sweep * 4410L));
- if (!program.depth_inc)
- program.depth_inc++;
- } else
- program.depth = (unsigned short) (depth << 5);
- snd_gf1_lfo_program(gus, voice, lfo_type, &program);
-}
-
-void snd_gf1_lfo_shutdown(snd_gus_card_t * gus, int voice, int lfo_type)
-{
- unsigned long flags;
- unsigned int lfo_addr;
-
- lfo_addr = (voice << 5) | (lfo_type << 4);
- if (gus->gf1.hw_lfo) {
- snd_gf1_pokew(gus, lfo_addr + 0x00, 0x0000);
- CLI(&flags);
- gf1_select_voice(gus, voice);
- snd_gf1_write8(gus, lfo_type == ULTRA_LFO_VIBRATO ? GF1_VB_FREQUENCY_LFO : GF1_VB_VOLUME_LFO, 0);
- STI(&flags);
- }
- if (gus->gf1.sw_lfo) {
- unsigned char *ptr = gus->gf1.lfos + lfo_addr;
- snd_gf1_voice_t *pvoice;
-
- *(unsigned short *) (ptr + 0x00) = 0;
- *(unsigned short *) (ptr + 0x04) = 0;
- *(unsigned short *) (ptr + 0x06) = 0;
- if (gus->gf1.syn_voices) {
- pvoice = gus->gf1.syn_voices + voice;
- if (lfo_type == ULTRA_LFO_VIBRATO)
- pvoice->lfo_fc = 0;
- else
- pvoice->lfo_volume = 0;
- snd_gf1_lfo_register_setup(gus, pvoice, lfo_type == ULTRA_LFO_VIBRATO ? 1 : 2);
- } else if (gus->gf1.enh_mode) {
- CLI(&flags);
- gf1_select_voice(gus, voice);
- snd_gf1_write8(gus, lfo_type == ULTRA_LFO_VIBRATO ? GF1_VB_FREQUENCY_LFO : GF1_VB_VOLUME_LFO, 0);
- STI(&flags);
- }
- }
-}
-
-void snd_gf1_lfo_command(snd_gus_card_t * gus, int voice, unsigned char *data)
-{
- int lfo_type;
- int lfo_command;
- int temp1, temp2;
-
- lfo_type = *data >> 7;
- lfo_command = *data & 0x7f;
- switch (lfo_command) {
- case ULTRA_LFO_SETUP: /* setup */
- temp1 = snd_gf1_get_word(data, 2);
- temp2 = snd_gf1_get_word(data, 4);
- snd_gf1_lfo_setup(gus, voice, lfo_type, temp1 & 0x7ff, 0, temp2 > 255 ? 255 : temp2, snd_gf1_get_byte(data, 1), (temp1 & 0x2000) >> 13);
- break;
- case ULTRA_LFO_FREQ: /* freq */
- snd_gf1_lfo_change_depth(gus, voice, lfo_type, snd_gf1_get_word(data, 2));
- break;
- case ULTRA_LFO_DEPTH: /* depth */
- snd_gf1_lfo_change_freq(gus, voice, lfo_type, snd_gf1_get_word(data, 2));
- break;
- case ULTRA_LFO_ENABLE: /* enable */
- snd_gf1_lfo_enable(gus, voice, lfo_type);
- break;
- case ULTRA_LFO_DISABLE: /* disable */
- snd_gf1_lfo_disable(gus, voice, lfo_type);
- break;
- case ULTRA_LFO_SHUTDOWN: /* shutdown */
- snd_gf1_lfo_shutdown(gus, voice, lfo_type);
- break;
- }
-}
diff --git a/sound/isa/gus/gus_pcm.c b/sound/isa/gus/gus_pcm.c
index aca7f3ad38b8d..8995ad9c516d0 100644
--- a/sound/isa/gus/gus_pcm.c
+++ b/sound/isa/gus/gus_pcm.c
@@ -333,6 +333,7 @@ static int snd_gf1_pcm_poke_block(snd_gus_card_t *gus, unsigned char *buf,
}
}
if (count > 0 && !in_interrupt()) {
+ set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(1);
if (signal_pending(current))
return -EAGAIN;
@@ -696,16 +697,10 @@ static int snd_gf1_pcm_playback_close(snd_pcm_substream_t * 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;
- unsigned long jiffies_old;
-
- jiffies_old = jiffies;
- while (atomic_read(&pcmp->dma_count) > 0) {
- interruptible_sleep_on_timeout(&pcmp->sleep, 1);
- if ((signed long)(jiffies - jiffies_old) > 2*HZ) {
- snd_printk("gf1 pcm - serious DMA problem\n");
- break;
- }
- }
+
+ if (!wait_event_timeout(pcmp->sleep, (atomic_read(&pcmp->dma_count) <= 0), 2*HZ))
+ snd_printk("gf1 pcm - serious DMA problem\n");
+
snd_gf1_dma_done(gus);
return 0;
}
diff --git a/sound/isa/gus/gus_reset.c b/sound/isa/gus/gus_reset.c
index 10182383a7a1c..b4e66f6a10aee 100644
--- a/sound/isa/gus/gus_reset.c
+++ b/sound/isa/gus/gus_reset.c
@@ -207,7 +207,6 @@ void snd_gf1_stop_voices(snd_gus_card_t * gus, unsigned short v_min, unsigned sh
unsigned long flags;
short i, ramp_ok;
unsigned short ramp_end;
- long time;
if (!in_interrupt()) { /* this can't be done in interrupt */
for (i = v_min, ramp_ok = 0; i <= v_max; i++) {
@@ -227,11 +226,7 @@ void snd_gf1_stop_voices(snd_gus_card_t * gus, unsigned short v_min, unsigned sh
}
spin_unlock_irqrestore(&gus->reg_lock, flags);
}
- time = HZ / 20;
- while (time > 0 && !signal_pending(current)) {
- set_current_state(TASK_INTERRUPTIBLE);
- time = schedule_timeout(time);
- }
+ msleep_interruptible(50);
}
snd_gf1_clear_voices(gus, v_min, v_max);
}
diff --git a/sound/isa/gus/gus_synth.c b/sound/isa/gus/gus_synth.c
index c7ff304433e9f..66552e6013a4b 100644
--- a/sound/isa/gus/gus_synth.c
+++ b/sound/isa/gus/gus_synth.c
@@ -214,7 +214,7 @@ static int snd_gus_synth_new_device(snd_seq_device_t *dev)
snd_gus_card_t *gus;
int client, i;
snd_seq_client_callback_t callbacks;
- snd_seq_client_info_t cinfo;
+ snd_seq_client_info_t *cinfo;
snd_seq_port_subscribe_t sub;
snd_iwffff_ops_t *iwops;
snd_gf1_ops_t *gf1ops;
@@ -227,21 +227,28 @@ static int snd_gus_synth_new_device(snd_seq_device_t *dev)
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)
+ if (client < 0) {
+ kfree(cinfo);
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);
+ 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);
diff --git a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c
index c3f2c6b5cf064..46e867daba6af 100644
--- a/sound/isa/gus/interwave.c
+++ b/sound/isa/gus/interwave.c
@@ -79,8 +79,10 @@ module_param_array(id, charp, NULL, 0444);
MODULE_PARM_DESC(id, "ID string for InterWave soundcard.");
module_param_array(enable, bool, NULL, 0444);
MODULE_PARM_DESC(enable, "Enable InterWave soundcard.");
+#ifdef CONFIG_PNP
module_param_array(isapnp, bool, NULL, 0444);
MODULE_PARM_DESC(isapnp, "ISA PnP detection for specified soundcard.");
+#endif
module_param_array(port, long, NULL, 0444);
MODULE_PARM_DESC(port, "Port # for InterWave driver.");
#ifdef SNDRV_STB
diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c
index ea71f581962b7..95c7b3e53407f 100644
--- a/sound/isa/opl3sa2.c
+++ b/sound/isa/opl3sa2.c
@@ -529,7 +529,7 @@ 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, unsigned int state)
+static int snd_opl3sa2_suspend(snd_card_t *card, pm_message_t state)
{
opl3sa2_t *chip = card->pm_private_data;
@@ -542,7 +542,7 @@ static int snd_opl3sa2_suspend(snd_card_t *card, unsigned int state)
return 0;
}
-static int snd_opl3sa2_resume(snd_card_t *card, unsigned int state)
+static int snd_opl3sa2_resume(snd_card_t *card)
{
opl3sa2_t *chip = card->pm_private_data;
int i;
@@ -787,7 +787,7 @@ static int __devinit snd_opl3sa2_pnp_detect(struct pnp_card_link *card,
int res;
for ( ; dev < SNDRV_CARDS; dev++) {
- if (!enable[dev] && !isapnp[dev])
+ if (!enable[dev] || !isapnp[dev])
continue;
res = snd_opl3sa2_probe(dev, card, id);
if (res < 0)
diff --git a/sound/isa/sb/emu8000.c b/sound/isa/sb/emu8000.c
index 9a668dac4b2f4..028af4066595f 100644
--- a/sound/isa/sb/emu8000.c
+++ b/sound/isa/sb/emu8000.c
@@ -25,6 +25,7 @@
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/ioport.h>
+#include <linux/delay.h>
#include <sound/core.h>
#include <sound/emu8000.h>
#include <sound/emu8000_reg.h>
@@ -355,8 +356,7 @@ init_arrays(emu8000_t *emu)
{
send_array(emu, init1, ARRAY_SIZE(init1)/4);
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout((HZ * (44099 + 1024)) / 44100); /* wait for 1024 clocks */
+ msleep((1024 * 1000) / 44100); /* wait for 1024 clocks */
send_array(emu, init2, ARRAY_SIZE(init2)/4);
send_array(emu, init3, ARRAY_SIZE(init3)/4);
diff --git a/sound/isa/sb/emu8000_patch.c b/sound/isa/sb/emu8000_patch.c
index cea56e0167084..4afc4a1bc140e 100644
--- a/sound/isa/sb/emu8000_patch.c
+++ b/sound/isa/sb/emu8000_patch.c
@@ -183,10 +183,10 @@ snd_emu8000_sample_new(snd_emux_t *rec, snd_sf_sample_t *sp,
}
if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS) {
- if (verify_area(VERIFY_READ, data, sp->v.size))
+ if (!access_ok(VERIFY_READ, data, sp->v.size))
return -EFAULT;
} else {
- if (verify_area(VERIFY_READ, data, sp->v.size * 2))
+ if (!access_ok(VERIFY_READ, data, sp->v.size * 2))
return -EFAULT;
}
diff --git a/sound/isa/sb/sb8_midi.c b/sound/isa/sb/sb8_midi.c
index 90b01e79879dc..d2c633a40e743 100644
--- a/sound/isa/sb/sb8_midi.c
+++ b/sound/isa/sb/sb8_midi.c
@@ -46,20 +46,16 @@ irqreturn_t snd_sb8dsp_midi_interrupt(sb_t * chip)
inb(SBP(chip, DATA_AVAIL)); /* ack interrupt */
return IRQ_NONE;
}
+ spin_lock(&chip->midi_input_lock);
while (max-- > 0) {
- spin_lock(&chip->midi_input_lock);
if (inb(SBP(chip, DATA_AVAIL)) & 0x80) {
byte = inb(SBP(chip, READ));
if (chip->open & SB_OPEN_MIDI_INPUT_TRIGGER) {
- spin_unlock(&chip->midi_input_lock);
snd_rawmidi_receive(chip->midi_substream_input, &byte, 1);
- } else {
- spin_unlock(&chip->midi_input_lock);
}
- } else {
- spin_unlock(&chip->midi_input_lock);
}
}
+ spin_unlock(&chip->midi_input_lock);
return IRQ_HANDLED;
}
diff --git a/sound/isa/wavefront/wavefront_midi.c b/sound/isa/wavefront/wavefront_midi.c
index 3918fbcdeb2d0..6f51d64fb5655 100644
--- a/sound/isa/wavefront/wavefront_midi.c
+++ b/sound/isa/wavefront/wavefront_midi.c
@@ -413,8 +413,8 @@ snd_wavefront_midi_interrupt (snd_wavefront_card_t *card)
return;
}
+ spin_lock_irqsave (&midi->virtual, flags);
while (--max) {
- spin_lock_irqsave (&midi->virtual, flags);
if (input_avail (midi)) {
byte = read_data (midi);
@@ -433,21 +433,17 @@ snd_wavefront_midi_interrupt (snd_wavefront_card_t *card)
}
if (substream == NULL) {
- spin_unlock_irqrestore (&midi->virtual, flags);
continue;
}
if (midi->mode[mpu] & MPU401_MODE_INPUT_TRIGGER) {
- spin_unlock_irqrestore (&midi->virtual, flags);
snd_rawmidi_receive(substream, &byte, 1);
- } else {
- spin_unlock_irqrestore (&midi->virtual, flags);
}
} else {
- spin_unlock_irqrestore (&midi->virtual, flags);
break;
}
}
+ spin_unlock_irqrestore (&midi->virtual, flags);
snd_wavefront_midi_output_write(card);
}
diff --git a/sound/isa/wavefront/wavefront_synth.c b/sound/isa/wavefront/wavefront_synth.c
index b17b505f200eb..0c3c951009d85 100644
--- a/sound/isa/wavefront/wavefront_synth.c
+++ b/sound/isa/wavefront/wavefront_synth.c
@@ -1201,7 +1201,11 @@ wavefront_send_multisample (snd_wavefront_t *dev, wavefront_patch_info *header)
{
int i;
int num_samples;
- unsigned char msample_hdr[WF_MSAMPLE_BYTES];
+ unsigned char *msample_hdr;
+
+ msample_hdr = kmalloc(sizeof(WF_MSAMPLE_BYTES), GFP_KERNEL);
+ if (! msample_hdr)
+ return -ENOMEM;
munge_int32 (header->number, &msample_hdr[0], 2);
@@ -1234,11 +1238,13 @@ wavefront_send_multisample (snd_wavefront_t *dev, wavefront_patch_info *header)
(unsigned char *) (long) ((num_samples*2)+3),
msample_hdr)) {
snd_printk ("download of multisample failed.\n");
+ kfree(msample_hdr);
return -(EIO);
}
dev->sample_status[header->number] = (WF_SLOT_FILLED|WF_ST_MULTISAMPLE);
+ kfree(msample_hdr);
return (0);
}
@@ -1356,78 +1362,103 @@ wavefront_find_free_patch (snd_wavefront_t *dev)
static int
wavefront_load_patch (snd_wavefront_t *dev, const char __user *addr)
-
{
- wavefront_patch_info header;
+ wavefront_patch_info *header;
+ int err;
- if (copy_from_user (&header, addr, sizeof(wavefront_patch_info) -
+ header = kmalloc(sizeof(*header), GFP_KERNEL);
+ if (! header)
+ return -ENOMEM;
+
+ if (copy_from_user (header, addr, sizeof(wavefront_patch_info) -
sizeof(wavefront_any))) {
snd_printk ("bad address for load patch.\n");
- return -(EFAULT);
+ err = -EFAULT;
+ goto __error;
}
DPRINT (WF_DEBUG_LOAD_PATCH, "download "
"Sample type: %d "
"Sample number: %d "
"Sample size: %d\n",
- header.subkey,
- header.number,
- header.size);
+ header->subkey,
+ header->number,
+ header->size);
- switch (header.subkey) {
+ switch (header->subkey) {
case WF_ST_SAMPLE: /* sample or sample_header, based on patch->size */
- if (copy_from_user (&header.hdr.s, header.hdrptr,
- sizeof (wavefront_sample)))
- return -EFAULT;
+ if (copy_from_user (&header->hdr.s, header->hdrptr,
+ sizeof (wavefront_sample))) {
+ err = -EFAULT;
+ break;
+ }
- return wavefront_send_sample (dev, &header, header.dataptr, 0);
+ err = wavefront_send_sample (dev, header, header->dataptr, 0);
+ break;
case WF_ST_MULTISAMPLE:
- if (copy_from_user (&header.hdr.s, header.hdrptr,
- sizeof (wavefront_multisample)))
- return -EFAULT;
-
- return wavefront_send_multisample (dev, &header);
+ if (copy_from_user (&header->hdr.s, header->hdrptr,
+ sizeof (wavefront_multisample))) {
+ err = -EFAULT;
+ break;
+ }
+ err = wavefront_send_multisample (dev, header);
+ break;
case WF_ST_ALIAS:
- if (copy_from_user (&header.hdr.a, header.hdrptr,
- sizeof (wavefront_alias)))
- return -EFAULT;
+ if (copy_from_user (&header->hdr.a, header->hdrptr,
+ sizeof (wavefront_alias))) {
+ err = -EFAULT;
+ break;
+ }
- return wavefront_send_alias (dev, &header);
+ err = wavefront_send_alias (dev, header);
+ break;
case WF_ST_DRUM:
- if (copy_from_user (&header.hdr.d, header.hdrptr,
- sizeof (wavefront_drum)))
- return -EFAULT;
+ if (copy_from_user (&header->hdr.d, header->hdrptr,
+ sizeof (wavefront_drum))) {
+ err = -EFAULT;
+ break;
+ }
- return wavefront_send_drum (dev, &header);
+ err = wavefront_send_drum (dev, header);
+ break;
case WF_ST_PATCH:
- if (copy_from_user (&header.hdr.p, header.hdrptr,
- sizeof (wavefront_patch)))
- return -EFAULT;
-
- return wavefront_send_patch (dev, &header);
+ if (copy_from_user (&header->hdr.p, header->hdrptr,
+ sizeof (wavefront_patch))) {
+ err = -EFAULT;
+ break;
+ }
+
+ err = wavefront_send_patch (dev, header);
+ break;
case WF_ST_PROGRAM:
- if (copy_from_user (&header.hdr.pr, header.hdrptr,
- sizeof (wavefront_program)))
- return -EFAULT;
+ if (copy_from_user (&header->hdr.pr, header->hdrptr,
+ sizeof (wavefront_program))) {
+ err = -EFAULT;
+ break;
+ }
- return wavefront_send_program (dev, &header);
+ err = wavefront_send_program (dev, header);
+ break;
default:
snd_printk ("unknown patch type %d.\n",
- header.subkey);
- return -(EINVAL);
+ header->subkey);
+ err = -EINVAL;
+ break;
}
- return 0;
+ __error:
+ kfree(header);
+ return err;
}
/***********************************************************************
@@ -1620,8 +1651,9 @@ snd_wavefront_synth_ioctl (snd_hwdep_t *hw, struct file *file,
snd_card_t *card;
snd_wavefront_t *dev;
snd_wavefront_card_t *acard;
- wavefront_control wc;
+ wavefront_control *wc;
void __user *argp = (void __user *)arg;
+ int err;
card = (snd_card_t *) hw->card;
@@ -1640,14 +1672,19 @@ snd_wavefront_synth_ioctl (snd_hwdep_t *hw, struct file *file,
break;
case WFCTL_WFCMD:
- if (copy_from_user (&wc, argp, sizeof (wc)))
- return -EFAULT;
- if (wavefront_synth_control (acard, &wc) < 0) {
- return -EIO;
- }
- if (copy_to_user (argp, &wc, sizeof (wc)))
- return -EFAULT;
- break;
+ wc = kmalloc(sizeof(*wc), GFP_KERNEL);
+ if (! wc)
+ return -ENOMEM;
+ if (copy_from_user (wc, argp, sizeof (*wc)))
+ err = -EFAULT;
+ else if (wavefront_synth_control (acard, wc) < 0)
+ err = -EIO;
+ else if (copy_to_user (argp, wc, sizeof (*wc)))
+ err = -EFAULT;
+ else
+ err = 0;
+ kfree(wc);
+ return err;
default:
return -EINVAL;
@@ -1751,6 +1788,7 @@ wavefront_should_cause_interrupt (snd_wavefront_t *dev,
outb (val,port);
spin_unlock_irq(&dev->irq_lock);
while (1) {
+ set_current_state(TASK_INTERRUPTIBLE);
if ((timeout = schedule_timeout(timeout)) == 0)
return;
if (dev->irq_ok)
@@ -1942,7 +1980,7 @@ wavefront_download_firmware (snd_wavefront_t *dev, char *path)
fs = get_fs();
set_fs (get_ds());
- if ((fd = sys_open (path, 0, 0)) < 0) {
+ if ((fd = sys_open ((char __user *) path, 0, 0)) < 0) {
snd_printk ("Unable to load \"%s\".\n",
path);
return 1;
@@ -1951,7 +1989,7 @@ wavefront_download_firmware (snd_wavefront_t *dev, char *path)
while (1) {
int x;
- if ((x = sys_read (fd, &section_length, sizeof (section_length))) !=
+ if ((x = sys_read (fd, (char __user *) &section_length, sizeof (section_length))) !=
sizeof (section_length)) {
snd_printk ("firmware read error.\n");
goto failure;
@@ -1967,7 +2005,7 @@ wavefront_download_firmware (snd_wavefront_t *dev, char *path)
goto failure;
}
- if (sys_read (fd, section, section_length) != section_length) {
+ if (sys_read (fd, (char __user *) section, section_length) != section_length) {
snd_printk ("firmware section "
"read error.\n");
goto failure;
diff --git a/sound/oss/ac97_codec.c b/sound/oss/ac97_codec.c
index 20a09424a48a4..124b1e10a13d9 100644
--- a/sound/oss/ac97_codec.c
+++ b/sound/oss/ac97_codec.c
@@ -71,6 +71,7 @@ static int wolfson_init03(struct ac97_codec * codec);
static int wolfson_init04(struct ac97_codec * codec);
static int wolfson_init05(struct ac97_codec * codec);
static int wolfson_init11(struct ac97_codec * codec);
+static int wolfson_init13(struct ac97_codec * codec);
static int tritech_init(struct ac97_codec * codec);
static int tritech_maestro_init(struct ac97_codec * codec);
static int sigmatel_9708_init(struct ac97_codec *codec);
@@ -107,6 +108,7 @@ static struct ac97_ops wolfson_ops03 = { wolfson_init03, NULL, NULL };
static struct ac97_ops wolfson_ops04 = { wolfson_init04, NULL, NULL };
static struct ac97_ops wolfson_ops05 = { wolfson_init05, NULL, NULL };
static struct ac97_ops wolfson_ops11 = { wolfson_init11, NULL, NULL };
+static struct ac97_ops wolfson_ops13 = { wolfson_init13, NULL, NULL };
static struct ac97_ops tritech_ops = { tritech_init, NULL, NULL };
static struct ac97_ops tritech_m_ops = { tritech_maestro_init, NULL, NULL };
static struct ac97_ops sigmatel_9708_ops = { sigmatel_9708_init, NULL, NULL };
@@ -171,6 +173,7 @@ static const struct {
{0x574D4C05, "Wolfson WM9705/WM9710", &wolfson_ops05},
{0x574D4C09, "Wolfson WM9709", &null_ops},
{0x574D4C12, "Wolfson WM9711/9712", &wolfson_ops11},
+ {0x574D4C13, "Wolfson WM9713", &wolfson_ops13, AC97_DEFAULT_POWER_OFF},
{0x83847600, "SigmaTel STAC????", &null_ops},
{0x83847604, "SigmaTel STAC9701/3/4/5", &null_ops},
{0x83847605, "SigmaTel STAC9704", &null_ops},
@@ -798,6 +801,9 @@ EXPORT_SYMBOL(ac97_release_codec);
* Currently codec_wait is used to wait for AC97 codec
* reset to complete.
*
+ * Some codecs will power down when a register reset is
+ * performed. We now check for such codecs.
+ *
* Returns 1 (true) on success, or 0 (false) on failure.
*/
@@ -811,34 +817,17 @@ int ac97_probe_codec(struct ac97_codec *codec)
struct list_head *l;
struct ac97_driver *d;
- /* probing AC97 codec, AC97 2.0 says that bit 15 of register 0x00 (reset) should
- * be read zero.
- *
- * FIXME: is the following comment outdated? -jgarzik
- * Probing of AC97 in this way is not reliable, it is not even SAFE !!
- */
- codec->codec_write(codec, AC97_RESET, 0L);
-
- /* also according to spec, we wait for codec-ready state */
+ /* wait for codec-ready state */
if (codec->codec_wait)
codec->codec_wait(codec);
else
udelay(10);
- if ((audio = codec->codec_read(codec, AC97_RESET)) & 0x8000) {
- printk(KERN_ERR "ac97_codec: %s ac97 codec not present\n",
- (codec->id & 0x2) ? (codec->id&1 ? "4th" : "Tertiary")
- : (codec->id&1 ? "Secondary": "Primary"));
- return 0;
- }
-
- /* probe for Modem Codec */
- codec->modem = ac97_check_modem(codec);
- codec->name = NULL;
- codec->codec_ops = &default_ops;
-
+ /* will the codec power down if register reset ? */
id1 = codec->codec_read(codec, AC97_VENDOR_ID1);
id2 = codec->codec_read(codec, AC97_VENDOR_ID2);
+ codec->name = NULL;
+ codec->codec_ops = &null_ops;
for (i = 0; i < ARRAY_SIZE(ac97_codec_ids); i++) {
if (ac97_codec_ids[i].id == ((id1 << 16) | id2)) {
codec->type = ac97_codec_ids[i].id;
@@ -850,9 +839,34 @@ int ac97_probe_codec(struct ac97_codec *codec)
}
codec->model = (id1 << 16) | id2;
+ if ((codec->flags & AC97_DEFAULT_POWER_OFF) == 0) {
+ /* reset codec and wait for the ready bit before we continue */
+ codec->codec_write(codec, AC97_RESET, 0L);
+ if (codec->codec_wait)
+ codec->codec_wait(codec);
+ else
+ udelay(10);
+ }
+
+ /* probing AC97 codec, AC97 2.0 says that bit 15 of register 0x00 (reset) should
+ * be read zero.
+ *
+ * FIXME: is the following comment outdated? -jgarzik
+ * Probing of AC97 in this way is not reliable, it is not even SAFE !!
+ */
+ if ((audio = codec->codec_read(codec, AC97_RESET)) & 0x8000) {
+ printk(KERN_ERR "ac97_codec: %s ac97 codec not present\n",
+ (codec->id & 0x2) ? (codec->id&1 ? "4th" : "Tertiary")
+ : (codec->id&1 ? "Secondary": "Primary"));
+ return 0;
+ }
+ /* probe for Modem Codec */
+ codec->modem = ac97_check_modem(codec);
+
+ /* enable SPDIF */
f = codec->codec_read(codec, AC97_EXTENDED_STATUS);
- if(f & 4)
+ if((codec->codec_ops == &null_ops) && (f & 4))
codec->codec_ops = &default_digital_ops;
/* A device which thinks its a modem but isnt */
@@ -921,11 +935,6 @@ static int ac97_init_mixer(struct ac97_codec *codec)
codec->recmask_io = ac97_recmask_io;
codec->mixer_ioctl = ac97_mixer_ioctl;
- /* codec specific initialization for 4-6 channel output or secondary codec stuff */
- if (codec->codec_ops->init != NULL) {
- codec->codec_ops->init(codec);
- }
-
/* initialize mixer channel volumes */
for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
struct mixer_defaults *md = &mixer_defaults[i];
@@ -936,6 +945,11 @@ static int ac97_init_mixer(struct ac97_codec *codec)
ac97_set_mixer(codec, md->mixer, md->value);
}
+ /* codec specific initialization for 4-6 channel output or secondary codec stuff */
+ if (codec->codec_ops->init != NULL) {
+ codec->codec_ops->init(codec);
+ }
+
/*
* Volume is MUTE only on this device. We have to initialise
* it but its useless beyond that.
@@ -1091,6 +1105,19 @@ static int wolfson_init11(struct ac97_codec * codec)
return 0;
}
+/* WM9713 */
+static int wolfson_init13(struct ac97_codec * codec)
+{
+ codec->codec_write(codec, AC97_RECORD_GAIN, 0x00a0);
+ codec->codec_write(codec, AC97_POWER_CONTROL, 0x0000);
+ codec->codec_write(codec, AC97_EXTENDED_MODEM_ID, 0xDA00);
+ codec->codec_write(codec, AC97_EXTEND_MODEM_STAT, 0x3810);
+ codec->codec_write(codec, AC97_PHONE_VOL, 0x0808);
+ codec->codec_write(codec, AC97_PCBEEP_VOL, 0x0808);
+
+ return 0;
+}
+
static int tritech_init(struct ac97_codec * codec)
{
codec->codec_write(codec, 0x26, 0x0300);
diff --git a/sound/oss/aedsp16.c b/sound/oss/aedsp16.c
index a246289d4dd77..b556263a57f55 100644
--- a/sound/oss/aedsp16.c
+++ b/sound/oss/aedsp16.c
@@ -489,7 +489,7 @@ static struct orVals orDMA[] __initdata = {
{0x00, 0x00}
};
-static struct aedsp16_info ae_config __initdata = {
+static struct aedsp16_info ae_config = {
DEF_AEDSP16_IOB,
DEF_AEDSP16_IRQ,
DEF_AEDSP16_MRQ,
@@ -1155,7 +1155,7 @@ static int __init init_aedsp16_sb(void)
return TRUE;
}
-static void __init uninit_aedsp16_sb(void)
+static void uninit_aedsp16_sb(void)
{
DBG(("uninit_aedsp16_sb: "));
@@ -1196,7 +1196,7 @@ static int __init init_aedsp16_mss(void)
return TRUE;
}
-static void __init uninit_aedsp16_mss(void)
+static void uninit_aedsp16_mss(void)
{
DBG(("uninit_aedsp16_mss: "));
@@ -1237,7 +1237,7 @@ static int __init init_aedsp16_mpu(void)
return TRUE;
}
-static void __init uninit_aedsp16_mpu(void)
+static void uninit_aedsp16_mpu(void)
{
DBG(("uninit_aedsp16_mpu: "));
@@ -1294,7 +1294,7 @@ static int __init init_aedsp16(void)
return initialized;
}
-static void __init uninit_aedsp16(void)
+static void __exit uninit_aedsp16(void)
{
if (ae_config.mss_base != -1)
uninit_aedsp16_mss();
diff --git a/sound/oss/ali5455.c b/sound/oss/ali5455.c
index a48be23dabfc1..9c9e6c0410f26 100644
--- a/sound/oss/ali5455.c
+++ b/sound/oss/ali5455.c
@@ -3528,7 +3528,7 @@ static void __devexit ali_remove(struct pci_dev *pci_dev)
}
#ifdef CONFIG_PM
-static int ali_pm_suspend(struct pci_dev *dev, u32 pm_state)
+static int ali_pm_suspend(struct pci_dev *dev, pm_message_t pm_state)
{
struct ali_card *card = pci_get_drvdata(dev);
struct ali_state *state;
diff --git a/sound/oss/btaudio.c b/sound/oss/btaudio.c
index 7f9a30a9e8d42..a85093fec7bed 100644
--- a/sound/oss/btaudio.c
+++ b/sound/oss/btaudio.c
@@ -558,7 +558,7 @@ static ssize_t btaudio_dsp_read(struct file *file, char __user *buffer,
__s16 __user *dst = (__s16 __user *)(buffer + ret);
__s16 avg;
int n = ndst>>1;
- if (0 != verify_area(VERIFY_WRITE,dst,ndst)) {
+ if (!access_ok(VERIFY_WRITE, dst, ndst)) {
if (0 == ret)
ret = -EFAULT;
break;
@@ -574,7 +574,7 @@ static ssize_t btaudio_dsp_read(struct file *file, char __user *buffer,
__u8 *src = bta->buf_cpu + bta->read_offset;
__u8 __user *dst = buffer + ret;
int n = ndst;
- if (0 != verify_area(VERIFY_WRITE,dst,ndst)) {
+ if (!access_ok(VERIFY_WRITE, dst, ndst)) {
if (0 == ret)
ret = -EFAULT;
break;
@@ -587,7 +587,7 @@ static ssize_t btaudio_dsp_read(struct file *file, char __user *buffer,
__u16 *src = (__u16*)(bta->buf_cpu + bta->read_offset);
__u16 __user *dst = (__u16 __user *)(buffer + ret);
int n = ndst>>1;
- if (0 != verify_area(VERIFY_WRITE,dst,ndst)) {
+ if (!access_ok(VERIFY_WRITE,dst,ndst)) {
if (0 == ret)
ret = -EFAULT;
break;
diff --git a/sound/oss/cmpci.c b/sound/oss/cmpci.c
index 72e1a6fd02726..34720e66dae1b 100644
--- a/sound/oss/cmpci.c
+++ b/sound/oss/cmpci.c
@@ -426,7 +426,7 @@ struct cm_state {
struct address_info mpu_data;
#endif
#ifdef CONFIG_SOUND_CMPCI_JOYSTICK
- struct gameport gameport;
+ struct gameport *gameport;
#endif
int chip_version;
@@ -468,17 +468,17 @@ struct cm_state {
static LIST_HEAD(devs);
-static int mpuio = 0;
-static int fmio = 0;
-static int joystick = 0;
-static int spdif_inverse = 0;
-static int spdif_loop = 0;
-static int spdif_out = 0;
-static int use_line_as_rear = 0;
-static int use_line_as_bass = 0;
-static int use_mic_as_bass = 0;
-static int mic_boost = 0;
-static int hw_copy = 0;
+static int mpuio;
+static int fmio;
+static int joystick;
+static int spdif_inverse;
+static int spdif_loop;
+static int spdif_out;
+static int use_line_as_rear;
+static int use_line_as_bass;
+static int use_mic_as_bass;
+static int mic_boost;
+static int hw_copy;
module_param(mpuio, int, 0);
module_param(fmio, int, 0);
module_param(joystick, bool, 0);
@@ -2925,7 +2925,7 @@ static /*const*/ struct file_operations cm_audio_fops = {
static struct initvol {
int mixch;
int vol;
-} initvol[] __initdata = {
+} initvol[] __devinitdata = {
{ SOUND_MIXER_WRITE_CD, 0x4f4f },
{ SOUND_MIXER_WRITE_LINE, 0x4f4f },
{ SOUND_MIXER_WRITE_MIC, 0x4f4f },
@@ -2984,6 +2984,51 @@ static int query_chip(struct cm_state *s)
return ChipVersion;
}
+#ifdef CONFIG_SOUND_CMPCI_JOYSTICK
+static int __devinit cm_create_gameport(struct cm_state *s, int io_port)
+{
+ struct gameport *gp;
+
+ if (!request_region(io_port, CM_EXTENT_GAME, "cmpci GAME")) {
+ printk(KERN_ERR "cmpci: gameport io ports 0x%#x in use\n", io_port);
+ return -EBUSY;
+ }
+
+ if (!(s->gameport = gp = gameport_allocate_port())) {
+ printk(KERN_ERR "cmpci: can not allocate memory for gameport\n");
+ release_region(io_port, CM_EXTENT_GAME);
+ return -ENOMEM;
+ }
+
+ gameport_set_name(gp, "C-Media GP");
+ gameport_set_phys(gp, "pci%s/gameport0", pci_name(s->dev));
+ gp->dev.parent = &s->dev->dev;
+ gp->io = io_port;
+
+ /* enable joystick */
+ maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~0, 0x02);
+
+ gameport_register_port(gp);
+
+ return 0;
+}
+
+static void __devexit cm_free_gameport(struct cm_state *s)
+{
+ if (s->gameport) {
+ int gpio = s->gameport->io;
+
+ gameport_unregister_port(s->gameport);
+ s->gameport = NULL;
+ maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~0x02, 0);
+ release_region(gpio, CM_EXTENT_GAME);
+ }
+}
+#else
+static inline int cm_create_gameport(struct cm_state *s, int io_port) { return -ENOSYS; }
+static inline void cm_free_gameport(struct cm_state *s) { }
+#endif
+
#define echo_option(x)\
if (x) strcat(options, "" #x " ")
@@ -3229,22 +3274,11 @@ static int __devinit cm_probe(struct pci_dev *pcidev, const struct pci_device_id
}
skip_mpu:
#endif
-#ifdef CONFIG_SOUND_CMPCI_JOYSTICK
- /* enable joystick */
- if (joystick) {
- s->gameport.io = 0x200;
- if (!request_region(s->gameport.io, CM_EXTENT_GAME, "cmpci GAME")) {
- printk(KERN_ERR "cmpci: gameport io ports in use\n");
- s->gameport.io = 0;
- } else {
- maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~0, 0x02);
- gameport_register_port(&s->gameport);
- }
- } else {
- maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~0x02, 0);
- s->gameport.io = 0;
- }
-#endif
+ /* disable joystick port */
+ maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~0x02, 0);
+ if (joystick)
+ cm_create_gameport(s, 0x200);
+
/* store it in the driver field */
pci_set_drvdata(pcidev, s);
/* put it into driver list */
@@ -3278,13 +3312,9 @@ static void __devexit cm_remove(struct pci_dev *dev)
if (!s)
return;
-#ifdef CONFIG_SOUND_CMPCI_JOYSTICK
- if (s->gameport.io) {
- gameport_unregister_port(&s->gameport);
- release_region(s->gameport.io, CM_EXTENT_GAME);
- maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~0x02, 0);
- }
-#endif
+
+ cm_free_gameport(s);
+
#ifdef CONFIG_SOUND_CMPCI_FM
if (s->iosynth) {
/* disable FM */
diff --git a/sound/oss/cs4281/cs4281_wrapper-24.c b/sound/oss/cs4281/cs4281_wrapper-24.c
index bd61a45983dd1..4559f02c99694 100644
--- a/sound/oss/cs4281/cs4281_wrapper-24.c
+++ b/sound/oss/cs4281/cs4281_wrapper-24.c
@@ -27,7 +27,7 @@
#include <linux/spinlock.h>
static int cs4281_resume_null(struct pci_dev *pcidev) { return 0; }
-static int cs4281_suspend_null(struct pci_dev *pcidev, u32 state) { return 0; }
+static int cs4281_suspend_null(struct pci_dev *pcidev, pm_message_t state) { return 0; }
#define free_dmabuf(state, dmabuf) \
pci_free_consistent(state->pcidev, \
diff --git a/sound/oss/cs4281/cs4281m.c b/sound/oss/cs4281/cs4281m.c
index 5fff9c331f548..d0d3963e1b83f 100644
--- a/sound/oss/cs4281/cs4281m.c
+++ b/sound/oss/cs4281/cs4281m.c
@@ -4096,7 +4096,7 @@ static /*const */ struct file_operations cs4281_midi_fops = {
static struct initvol {
int mixch;
int vol;
-} initvol[] __initdata = {
+} initvol[] __devinitdata = {
{
SOUND_MIXER_WRITE_VOLUME, 0x4040}, {
diff --git a/sound/oss/cs46xx.c b/sound/oss/cs46xx.c
index bc4941cb8b11f..8ce6b48f1881b 100644
--- a/sound/oss/cs46xx.c
+++ b/sound/oss/cs46xx.c
@@ -388,7 +388,7 @@ static int cs_hardware_init(struct cs_card *card);
static int cs46xx_powerup(struct cs_card *card, unsigned int type);
static int cs461x_powerdown(struct cs_card *card, unsigned int type, int suspendflag);
static void cs461x_clear_serial_FIFOs(struct cs_card *card, int type);
-static int cs46xx_suspend_tbl(struct pci_dev *pcidev, u32 state);
+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
@@ -5774,7 +5774,7 @@ static int cs46xx_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data)
#endif
#if CS46XX_ACPI_SUPPORT
-static int cs46xx_suspend_tbl(struct pci_dev *pcidev, u32 state)
+static int cs46xx_suspend_tbl(struct pci_dev *pcidev, pm_message_t state)
{
struct cs_card *s = PCI_GET_DRIVER_DATA(pcidev);
CS_DBGOUT(CS_PM | CS_FUNCTION, 2,
diff --git a/sound/oss/cs46xxpm-24.h b/sound/oss/cs46xxpm-24.h
index 7402cb76e43a8..e220bd7240f14 100644
--- a/sound/oss/cs46xxpm-24.h
+++ b/sound/oss/cs46xxpm-24.h
@@ -36,7 +36,7 @@
* for now (12/22/00) only enable the pm_register PM support.
* allow these table entries to be null.
*/
-static int cs46xx_suspend_tbl(struct pci_dev *pcidev, u32 state);
+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)
diff --git a/sound/oss/dmasound/dac3550a.c b/sound/oss/dmasound/dac3550a.c
index fadf33e5963cb..533895eba0ebc 100644
--- a/sound/oss/dmasound/dac3550a.c
+++ b/sound/oss/dmasound/dac3550a.c
@@ -40,9 +40,6 @@ static int daca_attach_adapter(struct i2c_adapter *adapter);
static int daca_detect_client(struct i2c_adapter *adapter, int address);
static int daca_detach_client(struct i2c_client *client);
-/* Unique ID allocation */
-static int daca_id;
-
struct i2c_driver daca_driver = {
.owner = THIS_MODULE,
.name = "DAC3550A driver V " DACA_VERSION,
@@ -176,7 +173,6 @@ static int daca_detect_client(struct i2c_adapter *adapter, int address)
new_client->driver = &daca_driver;
new_client->flags = 0;
strcpy(new_client->name, client_name);
- new_client->id = daca_id++; /* racy... */
if (daca_init_client(new_client))
goto bail;
diff --git a/sound/oss/dmasound/dmasound_awacs.c b/sound/oss/dmasound/dmasound_awacs.c
index 89f52a7d466a1..5281b88987f35 100644
--- a/sound/oss/dmasound/dmasound_awacs.c
+++ b/sound/oss/dmasound/dmasound_awacs.c
@@ -2987,10 +2987,13 @@ printk("dmasound_pmac: Awacs/Screamer Codec Mfct: %d Rev %d\n", mfg, rev);
set_hw_byteswap(io) ; /* figure out if the h/w can do it */
- /* get default volume from nvram
- * vol = (~nvram_read_byte(0x1308) & 7) << 1;
- */
+#ifdef CONFIG_NVRAM
+ /* get default volume from nvram */
vol = ((pmac_xpram_read( 8 ) & 7 ) << 1 );
+#else
+ vol = 0;
+#endif
+
/* set up tracking values */
spk_vol = vol * 100 ;
spk_vol /= 7 ; /* get set value to a percentage */
diff --git a/sound/oss/es1370.c b/sound/oss/es1370.c
index 52cc8bf5abf56..056091cff2663 100644
--- a/sound/oss/es1370.c
+++ b/sound/oss/es1370.c
@@ -384,7 +384,7 @@ struct es1370_state {
unsigned char obuf[MIDIOUTBUF];
} midi;
- struct gameport gameport;
+ struct gameport *gameport;
struct semaphore sem;
};
@@ -2540,7 +2540,7 @@ MODULE_LICENSE("GPL");
static struct initvol {
int mixch;
int vol;
-} initvol[] __initdata = {
+} initvol[] __devinitdata = {
{ SOUND_MIXER_WRITE_VOLUME, 0x4040 },
{ SOUND_MIXER_WRITE_PCM, 0x4040 },
{ SOUND_MIXER_WRITE_SYNTH, 0x4040 },
@@ -2556,6 +2556,7 @@ static struct initvol {
static int __devinit es1370_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid)
{
struct es1370_state *s;
+ struct gameport *gp = NULL;
mm_segment_t fs;
int i, val, ret;
@@ -2604,12 +2605,17 @@ static int __devinit es1370_probe(struct pci_dev *pcidev, const struct pci_devic
/* note: setting CTRL_SERR_DIS is reported to break
* mic bias setting (by Kim.Berts@fisub.mail.abb.com) */
s->ctrl = CTRL_CDC_EN | (DAC2_SRTODIV(8000) << CTRL_SH_PCLKDIV) | (1 << CTRL_SH_WTSRSEL);
- s->gameport.io = 0;
- if (!request_region(0x200, JOY_EXTENT, "es1370"))
+ if (!request_region(0x200, JOY_EXTENT, "es1370")) {
printk(KERN_ERR "es1370: joystick io port 0x200 in use\n");
- else {
+ } else if (!(s->gameport = gp = gameport_allocate_port())) {
+ printk(KERN_ERR "es1370: can not allocate memory for gameport\n");
+ release_region(0x200, JOY_EXTENT);
+ } else {
+ gameport_set_name(gp, "ESS1370");
+ gameport_set_phys(gp, "pci%s/gameport0", pci_name(s->dev));
+ gp->dev.parent = &s->dev->dev;
+ gp->io = 0x200;
s->ctrl |= CTRL_JYSTK_EN;
- s->gameport.io = 0x200;
}
if (lineout[devindex])
s->ctrl |= CTRL_XCTL0;
@@ -2665,9 +2671,10 @@ static int __devinit es1370_probe(struct pci_dev *pcidev, const struct pci_devic
mixer_ioctl(s, initvol[i].mixch, (unsigned long)&val);
}
set_fs(fs);
+
/* register gameport */
- if (s->gameport.io)
- gameport_register_port(&s->gameport);
+ if (gp)
+ gameport_register_port(gp);
/* store it in the driver field */
pci_set_drvdata(pcidev, s);
@@ -2689,8 +2696,10 @@ static int __devinit es1370_probe(struct pci_dev *pcidev, const struct pci_devic
err_dev1:
printk(KERN_ERR "es1370: cannot register misc device\n");
free_irq(s->irq, s);
- if (s->gameport.io)
- release_region(s->gameport.io, JOY_EXTENT);
+ if (s->gameport) {
+ release_region(s->gameport->io, JOY_EXTENT);
+ gameport_free_port(s->gameport);
+ }
err_irq:
release_region(s->io, ES1370_EXTENT);
err_region:
@@ -2709,9 +2718,10 @@ static void __devexit es1370_remove(struct pci_dev *dev)
outl(0, s->io+ES1370_REG_SERIAL_CONTROL); /* clear serial interrupts */
synchronize_irq(s->irq);
free_irq(s->irq, s);
- if (s->gameport.io) {
- gameport_unregister_port(&s->gameport);
- release_region(s->gameport.io, JOY_EXTENT);
+ if (s->gameport) {
+ int gpio = s->gameport->io;
+ gameport_unregister_port(s->gameport);
+ release_region(gpio, JOY_EXTENT);
}
release_region(s->io, ES1370_EXTENT);
unregister_sound_dsp(s->dev_audio);
diff --git a/sound/oss/es1371.c b/sound/oss/es1371.c
index 0fc6334d4f637..a50fddaeea216 100644
--- a/sound/oss/es1371.c
+++ b/sound/oss/es1371.c
@@ -453,7 +453,7 @@ struct es1371_state {
unsigned char obuf[MIDIOUTBUF];
} midi;
- struct gameport gameport;
+ struct gameport *gameport;
struct semaphore sem;
};
@@ -2786,12 +2786,12 @@ static struct
{ PCI_ANY_ID, PCI_ANY_ID }
};
-
static int __devinit es1371_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid)
{
struct es1371_state *s;
+ struct gameport *gp;
mm_segment_t fs;
- int i, val, res = -1;
+ int i, gpio, val, res = -1;
int idx;
unsigned long tmo;
signed long tmo2;
@@ -2849,8 +2849,8 @@ static int __devinit es1371_probe(struct pci_dev *pcidev, const struct pci_devic
printk(KERN_ERR PFX "irq %u in use\n", s->irq);
goto err_irq;
}
- printk(KERN_INFO PFX "found es1371 rev %d at io %#lx irq %u joystick %#x\n",
- s->rev, s->io, s->irq, s->gameport.io);
+ printk(KERN_INFO PFX "found es1371 rev %d at io %#lx irq %u\n",
+ s->rev, s->io, s->irq);
/* register devices */
if ((res=(s->dev_audio = register_sound_dsp(&es1371_audio_fops,-1)))<0)
goto err_dev1;
@@ -2881,16 +2881,23 @@ static int __devinit es1371_probe(struct pci_dev *pcidev, const struct pci_devic
printk(KERN_INFO PFX "Enabling internal amplifier.\n");
}
}
- s->gameport.io = 0;
- for (i = 0x218; i >= 0x200; i -= 0x08) {
- if (request_region(i, JOY_EXTENT, "es1371")) {
- s->ctrl |= CTRL_JYSTK_EN | (((i >> 3) & CTRL_JOY_MASK) << CTRL_JOY_SHIFT);
- s->gameport.io = i;
+
+ for (gpio = 0x218; gpio >= 0x200; gpio -= 0x08)
+ if (request_region(gpio, JOY_EXTENT, "es1371"))
break;
- }
- }
- if (!s->gameport.io)
+
+ if (gpio < 0x200) {
printk(KERN_ERR PFX "no free joystick address found\n");
+ } else if (!(s->gameport = gp = gameport_allocate_port())) {
+ printk(KERN_ERR PFX "can not allocate memory for gameport\n");
+ release_region(gpio, JOY_EXTENT);
+ } else {
+ gameport_set_name(gp, "ESS1371 Gameport");
+ gameport_set_phys(gp, "isa%04x/gameport0", gpio);
+ gp->dev.parent = &s->dev->dev;
+ gp->io = gpio;
+ s->ctrl |= CTRL_JYSTK_EN | (((gpio >> 3) & CTRL_JOY_MASK) << CTRL_JOY_SHIFT);
+ }
s->sctrl = 0;
cssr = 0;
@@ -2960,9 +2967,11 @@ static int __devinit es1371_probe(struct pci_dev *pcidev, const struct pci_devic
set_fs(fs);
/* turn on S/PDIF output driver if requested */
outl(cssr, s->io+ES1371_REG_STATUS);
+
/* register gameport */
- if (s->gameport.io)
- gameport_register_port(&s->gameport);
+ if (s->gameport)
+ gameport_register_port(s->gameport);
+
/* store it in the driver field */
pci_set_drvdata(pcidev, s);
/* put it into driver list */
@@ -2973,8 +2982,10 @@ static int __devinit es1371_probe(struct pci_dev *pcidev, const struct pci_devic
return 0;
err_gp:
- if (s->gameport.io)
- release_region(s->gameport.io, JOY_EXTENT);
+ if (s->gameport) {
+ release_region(s->gameport->io, JOY_EXTENT);
+ gameport_free_port(s->gameport);
+ }
#ifdef ES1371_DEBUG
if (s->ps)
remove_proc_entry("es1371", NULL);
@@ -3013,9 +3024,10 @@ static void __devexit es1371_remove(struct pci_dev *dev)
outl(0, s->io+ES1371_REG_SERIAL_CONTROL); /* clear serial interrupts */
synchronize_irq(s->irq);
free_irq(s->irq, s);
- if (s->gameport.io) {
- gameport_unregister_port(&s->gameport);
- release_region(s->gameport.io, JOY_EXTENT);
+ if (s->gameport) {
+ int gpio = s->gameport->io;
+ gameport_unregister_port(s->gameport);
+ release_region(gpio, JOY_EXTENT);
}
release_region(s->io, ES1371_EXTENT);
unregister_sound_dsp(s->dev_audio);
diff --git a/sound/oss/esssolo1.c b/sound/oss/esssolo1.c
index 3e73405b3d45e..6b3b9a99579db 100644
--- a/sound/oss/esssolo1.c
+++ b/sound/oss/esssolo1.c
@@ -226,7 +226,7 @@ struct solo1_state {
unsigned char obuf[MIDIOUTBUF];
} midi;
- struct gameport gameport;
+ struct gameport *gameport;
};
/* --------------------------------------------------------------------- */
@@ -2193,7 +2193,7 @@ static /*const*/ struct file_operations solo1_dmfm_fops = {
static struct initvol {
int mixch;
int vol;
-} initvol[] __initdata = {
+} initvol[] __devinitdata = {
{ SOUND_MIXER_WRITE_VOLUME, 0x4040 },
{ SOUND_MIXER_WRITE_PCM, 0x4040 },
{ SOUND_MIXER_WRITE_SYNTH, 0x4040 },
@@ -2257,7 +2257,7 @@ static int setup_solo1(struct solo1_state *s)
}
static int
-solo1_suspend(struct pci_dev *pci_dev, u32 state) {
+solo1_suspend(struct pci_dev *pci_dev, pm_message_t state) {
struct solo1_state *s = (struct solo1_state*)pci_get_drvdata(pci_dev);
if (!s)
return 1;
@@ -2280,9 +2280,36 @@ solo1_resume(struct pci_dev *pci_dev) {
return 0;
}
+static int __devinit solo1_register_gameport(struct solo1_state *s, int io_port)
+{
+ struct gameport *gp;
+
+ if (!request_region(io_port, GAMEPORT_EXTENT, "ESS Solo1")) {
+ printk(KERN_ERR "solo1: gameport io ports are in use\n");
+ return -EBUSY;
+ }
+
+ s->gameport = gp = gameport_allocate_port();
+ if (!gp) {
+ printk(KERN_ERR "solo1: can not allocate memory for gameport\n");
+ release_region(io_port, GAMEPORT_EXTENT);
+ return -ENOMEM;
+ }
+
+ gameport_set_name(gp, "ESS Solo1 Gameport");
+ gameport_set_phys(gp, "isa%04x/gameport0", io_port);
+ gp->dev.parent = &s->dev->dev;
+ gp->io = io_port;
+
+ gameport_register_port(gp);
+
+ return 0;
+}
+
static int __devinit solo1_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid)
{
struct solo1_state *s;
+ int gpio;
int ret;
if ((ret=pci_enable_device(pcidev)))
@@ -2323,7 +2350,7 @@ static int __devinit solo1_probe(struct pci_dev *pcidev, const struct pci_device
s->vcbase = pci_resource_start(pcidev, 2);
s->ddmabase = s->vcbase + DDMABASE_OFFSET;
s->mpubase = pci_resource_start(pcidev, 3);
- s->gameport.io = pci_resource_start(pcidev, 4);
+ gpio = pci_resource_start(pcidev, 4);
s->irq = pcidev->irq;
ret = -EBUSY;
if (!request_region(s->iobase, IOBASE_EXTENT, "ESS Solo1")) {
@@ -2342,15 +2369,10 @@ static int __devinit solo1_probe(struct pci_dev *pcidev, const struct pci_device
printk(KERN_ERR "solo1: io ports in use\n");
goto err_region4;
}
- if (s->gameport.io && !request_region(s->gameport.io, GAMEPORT_EXTENT, "ESS Solo1")) {
- printk(KERN_ERR "solo1: gameport io ports in use\n");
- s->gameport.io = 0;
- }
if ((ret=request_irq(s->irq,solo1_interrupt,SA_SHIRQ,"ESS Solo1",s))) {
printk(KERN_ERR "solo1: irq %u in use\n", s->irq);
goto err_irq;
}
- printk(KERN_INFO "solo1: joystick port at %#x\n", s->gameport.io+1);
/* register devices */
if ((s->dev_audio = register_sound_dsp(&solo1_audio_fops, -1)) < 0) {
ret = s->dev_audio;
@@ -2373,7 +2395,7 @@ static int __devinit solo1_probe(struct pci_dev *pcidev, const struct pci_device
goto err;
}
/* register gameport */
- gameport_register_port(&s->gameport);
+ solo1_register_gameport(s, gpio);
/* store it in the driver field */
pci_set_drvdata(pcidev, s);
return 0;
@@ -2390,8 +2412,6 @@ static int __devinit solo1_probe(struct pci_dev *pcidev, const struct pci_device
printk(KERN_ERR "solo1: initialisation error\n");
free_irq(s->irq, s);
err_irq:
- if (s->gameport.io)
- release_region(s->gameport.io, GAMEPORT_EXTENT);
release_region(s->mpubase, MPUBASE_EXTENT);
err_region4:
release_region(s->ddmabase, DDMABASE_EXTENT);
@@ -2417,9 +2437,10 @@ static void __devexit solo1_remove(struct pci_dev *dev)
synchronize_irq(s->irq);
pci_write_config_word(s->dev, 0x60, 0); /* turn off DDMA controller address space */
free_irq(s->irq, s);
- if (s->gameport.io) {
- gameport_unregister_port(&s->gameport);
- release_region(s->gameport.io, GAMEPORT_EXTENT);
+ if (s->gameport) {
+ int gpio = s->gameport->io;
+ gameport_unregister_port(s->gameport);
+ release_region(gpio, GAMEPORT_EXTENT);
}
release_region(s->iobase, IOBASE_EXTENT);
release_region(s->sbbase+FMSYNTH_EXTENT, SBBASE_EXTENT-FMSYNTH_EXTENT);
diff --git a/sound/oss/gus_wave.c b/sound/oss/gus_wave.c
index b1f5c8c9f69dd..942d5186580dc 100644
--- a/sound/oss/gus_wave.c
+++ b/sound/oss/gus_wave.c
@@ -3126,8 +3126,7 @@ void __exit gus_wave_unload(struct address_info *hw_config)
if (hw_config->slots[5] != -1)
sound_unload_mixerdev(hw_config->slots[5]);
- if(samples)
- vfree(samples);
+ vfree(samples);
samples=NULL;
}
/* called in interrupt context */
diff --git a/sound/oss/harmony.c b/sound/oss/harmony.c
index 2f83ac8a4cee4..bee9d344cd265 100644
--- a/sound/oss/harmony.c
+++ b/sound/oss/harmony.c
@@ -310,7 +310,7 @@ static int harmony_detect_rate(int *freq)
case 32000: newrate = HARMONY_SR_32KHZ; break;
case 48000: newrate = HARMONY_SR_48KHZ; break;
case 9600: newrate = HARMONY_SR_9KHZ; break;
- case 5125: newrate = HARMONY_SR_5KHZ; break;
+ case 5512: newrate = HARMONY_SR_5KHZ; break;
case 11025: newrate = HARMONY_SR_11KHZ; break;
case 18900: newrate = HARMONY_SR_18KHZ; break;
case 22050: newrate = HARMONY_SR_22KHZ; break;
diff --git a/sound/oss/i810_audio.c b/sound/oss/i810_audio.c
index a4b959ae9bbf5..7e9f667cf7a71 100644
--- a/sound/oss/i810_audio.c
+++ b/sound/oss/i810_audio.c
@@ -3470,7 +3470,7 @@ static void __devexit i810_remove(struct pci_dev *pci_dev)
}
#ifdef CONFIG_PM
-static int i810_pm_suspend(struct pci_dev *dev, u32 pm_state)
+static int i810_pm_suspend(struct pci_dev *dev, pm_message_t pm_state)
{
struct i810_card *card = pci_get_drvdata(dev);
struct i810_state *state;
diff --git a/sound/oss/mad16.c b/sound/oss/mad16.c
index f53970a602ecb..a7067f169919c 100644
--- a/sound/oss/mad16.c
+++ b/sound/oss/mad16.c
@@ -52,7 +52,7 @@
static int mad16_conf;
static int mad16_cdsel;
-static struct gameport gameport;
+static struct gameport *gameport;
static DEFINE_SPINLOCK(lock);
#define C928 1
@@ -902,7 +902,30 @@ static int __initdata irq_map[16] =
-1, -1, -1, -1
};
-static int __init init_mad16(void)
+static int __devinit mad16_register_gameport(int io_port)
+{
+ if (!request_region(io_port, 1, "mad16 gameport")) {
+ printk(KERN_ERR "mad16: gameport address 0x%#x already in use\n", io_port);
+ return -EBUSY;
+ }
+
+ gameport = gameport_allocate_port();
+ if (!gameport) {
+ printk(KERN_ERR "mad16: can not allocate memory for gameport\n");
+ release_region(io_port, 1);
+ return -ENOMEM;
+ }
+
+ gameport_set_name(gameport, "MAD16 Gameport");
+ gameport_set_phys(gameport, "isa%04x/gameport0", io_port);
+ gameport->io = io_port;
+
+ gameport_register_port(gameport);
+
+ return 0;
+}
+
+static int __devinit init_mad16(void)
{
int dmatype = 0;
@@ -1027,17 +1050,9 @@ static int __init init_mad16(void)
found_mpu = probe_mad16_mpu(&cfg_mpu);
- if (joystick == 1) {
- /* register gameport */
- if (!request_region(0x201, 1, "mad16 gameport"))
- printk(KERN_ERR "mad16: gameport address 0x201 already in use\n");
- else {
- printk(KERN_ERR "mad16: gameport enabled at 0x201\n");
- gameport.io = 0x201;
- gameport_register_port(&gameport);
- }
- }
- else printk(KERN_ERR "mad16: gameport disabled.\n");
+ if (joystick)
+ mad16_register_gameport(0x201);
+
return 0;
}
@@ -1045,10 +1060,10 @@ static void __exit cleanup_mad16(void)
{
if (found_mpu)
unload_mad16_mpu(&cfg_mpu);
- if (gameport.io) {
+ if (gameport) {
/* the gameport was initialized so we must free it up */
- gameport_unregister_port(&gameport);
- gameport.io = 0;
+ gameport_unregister_port(gameport);
+ gameport = NULL;
release_region(0x201, 1);
}
unload_mad16(&cfg);
diff --git a/sound/oss/maestro3.c b/sound/oss/maestro3.c
index 17d4f0792d382..f3dec70fcb9b2 100644
--- a/sound/oss/maestro3.c
+++ b/sound/oss/maestro3.c
@@ -375,7 +375,7 @@ static struct m3_card *devs;
* I'm not very good at laying out functions in a file :)
*/
static int m3_notifier(struct notifier_block *nb, unsigned long event, void *buf);
-static int m3_suspend(struct pci_dev *pci_dev, u32 state);
+static int m3_suspend(struct pci_dev *pci_dev, pm_message_t state);
static void check_suspend(struct m3_card *card);
static struct notifier_block m3_reboot_nb = {
@@ -2777,12 +2777,12 @@ static int m3_notifier(struct notifier_block *nb, unsigned long event, void *buf
for(card = devs; card != NULL; card = card->next) {
if(!card->in_suspend)
- m3_suspend(card->pcidev, 3); /* XXX legal? */
+ m3_suspend(card->pcidev, PMSG_SUSPEND); /* XXX legal? */
}
return 0;
}
-static int m3_suspend(struct pci_dev *pci_dev, u32 state)
+static int m3_suspend(struct pci_dev *pci_dev, pm_message_t state)
{
unsigned long flags;
int i;
diff --git a/sound/oss/maestro_tables.h b/sound/oss/maestro_tables.h
deleted file mode 100644
index 1edf1850a5f25..0000000000000
--- a/sound/oss/maestro_tables.h
+++ /dev/null
@@ -1,333 +0,0 @@
-/*
- * Set up data block for the ESS soundblaster emulation. This is like
- * the example code from ftp.esstech.com.tw (104T31.ZIP)
- */
-
-u16 asp_block_0[]= {
- 0x7980, 0x003a, 0x7980, 0x007d, 0xbe3a, 0x8b00, 0xbe3a, 0x8b00,
- 0xbe3a, 0x8b00, 0xbe3a, 0x8b00, 0xbe3a, 0x8b00, 0xbe3a, 0x8b00,
- 0x7980, 0x0be6, 0x7980, 0x0069, 0xbe3a, 0x8b00, 0x8048, 0x6945,
- 0xb801, 0x9045, 0x6941, 0xe388, 0x0031, 0x6944, 0xba50, 0xe38c,
- 0x0031, 0x8b88, 0x6942, 0x304a, 0xe308, 0x0028, 0x6949, 0x9042,
- 0x0042, 0xafa0, 0x8000, 0xafa0, 0x8000, 0x8042, 0x6944, 0xb801,
- 0x9044, 0x0048, 0xbe3a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0xbe41, 0xbf80, 0x0101, 0x8806, 0x8804, 0xb912,
- 0x8807, 0xbc26, 0xbe40, 0xb92f, 0x9001, 0x9002, 0x003b, 0x0122,
- 0x7a88, 0x0055, 0x003a, 0x013c, 0x7a88, 0x0055, 0x4902, 0xe100,
- 0x0800, 0x0c02, 0xa000, 0x7980, 0x004e, 0xb908, 0x8809, 0xbec6,
- 0x0067, 0x4a80, 0xe200, 0x0065, 0x4880, 0xe200, 0x0063, 0xb97f,
- 0x6e80, 0x7980, 0x0066, 0x1089, 0x9088, 0xb900, 0x90a9, 0x8ba8,
- 0xef00, 0x803d, 0x0003, 0x1007, 0x881f, 0x8b88, 0xbb0f, 0xada0,
- 0x0810, 0x9003, 0x4903, 0xe200, 0x007b, 0x9002, 0x6a05, 0x6d04,
- 0x9803, 0x9804, 0x9005, 0x003d, 0xbe3a, 0xaf06, 0x0000, 0x803d,
- 0x8b88, 0x6906, 0x8810, 0xaf06, 0x0001, 0xbfb0, 0x00ff, 0xbaf5,
- 0xe3cc, 0x009a, 0x5e06, 0x003f, 0xbf80, 0x0080, 0x4a06, 0xe200,
- 0x0095, 0x6e80, 0x6d06, 0x7980, 0x009b, 0x9080, 0x0810, 0xba46,
- 0x8810, 0x8b00, 0x1006, 0x9080, 0x003d, 0xbe3a, 0x1024, 0x2009,
- 0x8810, 0x8b88, 0x8b00, 0x1089, 0xbfb0, 0x000e, 0xbe0a, 0x880d,
- 0x903e, 0x1038, 0x2008, 0x8810, 0x1037, 0x2008, 0x8811, 0x5f3e,
- 0x0000, 0x8b00, 0xf500, 0x5e80, 0xfffe, 0x1039, 0x2008, 0x8815,
- 0x8b8d, 0x0231, 0x0333, 0x108a, 0x90ad, 0x1025, 0x200a, 0x8815,
- 0x0605, 0xb91f, 0x8809, 0x4f16, 0x1080, 0xf600, 0xbfb0,
- 0x0003, 0xbfb0, 0x0007, 0x9089, 0xbe47, 0xbe43, 0xbec6,
- 0x00f6, 0x4f8b, 0x14a8, 0xe500, 0x6380, 0x8b89, 0x4e8a,
- 0xbfe3, 0xe500, 0x2480, 0xbe46, 0x8b9d, 0xbfe7, 0xbfb0,
- 0x00ff, 0x288c, 0x2026, 0x8814, 0xbe47, 0x8b00, 0x738f,
- 0x54aa, 0xbe03, 0xbe0a, 0x2fa8, 0x988a, 0x8da9, 0xbe03,
- 0x4d8e, 0xbfe1, 0xf500, 0x6180, 0x9880, 0x8ba9, 0xbe03,
- 0x4c8e, 0xbfe1, 0xf500, 0x6180, 0x9880, 0x8ba9, 0xbe42,
- 0x1039, 0x2008, 0x8815, 0x8b8d, 0x8b00, 0x8d8a, 0x7980,
- 0x0bcf};
-
-u16 asp_block_1[]={
- 0x0005, 0xb900, 0x9008, 0x9009, 0x900a, 0xbb3f, 0x90a0,
- 0x001a, 0x011b, 0x021c, 0x0323, 0x1089, 0x9015, 0x108a,
- 0x9016, 0x108b, 0x9017, 0x1088, 0x9018, 0x0137, 0x0524,
- 0x8b8d, 0x4f16, 0xe200, 0x0827, 0x4f15, 0xe200, 0x0827,
- 0x7a80, 0x08e6, 0x102c, 0xb802, 0x8813, 0x8b8b, 0xb900,
- 0x90a0, 0x908d, 0x7980, 0x0833, 0x7a80, 0x0913, 0x7803,
- 0x7a80, 0x0913, 0x102c, 0xb802, 0x8813, 0x8b8b, 0xb903,
- 0x90a0, 0x908d, 0x7c02, 0x4f16, 0xe200, 0x0845, 0x4e15,
- 0xe200, 0x0845, 0x7a80, 0x08e6, 0x102c, 0xb806, 0x8813,
- 0x8b8b, 0xb901, 0x90a0, 0x908d, 0x7980, 0x0851, 0x7a80,
- 0x0913, 0x7803, 0x7a80, 0x0913, 0x102c, 0xb806, 0x8813,
- 0x8b8b, 0xb904, 0x90a0, 0x908d, 0x7c02, 0x4f16, 0xe200,
- 0x0863, 0x4d15, 0xe200, 0x0863, 0x7a80, 0x08e6, 0x102c,
- 0xb80a, 0x8813, 0x8b8b, 0xb902, 0x90a0, 0x908d, 0x7980,
- 0x086f, 0x7a80, 0x0913, 0x7803, 0x7a80, 0x0913, 0x102c,
- 0xb80a, 0x8813, 0x8b8b, 0xb905, 0x90a0, 0x908d, 0x7801,
- 0x7a80, 0x0913, 0x7801, 0x7a80, 0x0913, 0x7801, 0x7a80,
- 0x0913, 0x1024, 0xbf90, 0x0100, 0x8815, 0x4f16, 0xe200,
- 0x088e, 0x4c15, 0xe200, 0x088e, 0x7a80, 0x08e6, 0x102c,
- 0xb814, 0x8813, 0x8b8b, 0xbf80, 0x0100, 0x90a0, 0x908d,
- 0x7980, 0x089b, 0x7a80, 0x0913, 0x7803, 0x7a80, 0x0913,
- 0x102c, 0xb814, 0x8813, 0x8b8b, 0xbf80, 0x0103, 0x90a0,
- 0x908d, 0x7c02, 0x4f16, 0xe200, 0x08ae, 0x4b15, 0xe200,
- 0x08ae, 0x7a80, 0x08e6, 0x102c, 0xb818, 0x8813, 0x8b8b,
- 0xbf80, 0x0101, 0x90a0, 0x908d, 0x7980, 0x08bb, 0x7a80,
- 0x0913, 0x7803, 0x7a80, 0x0913, 0x102c, 0xb818, 0x8813,
- 0x8b8b, 0xbf80, 0x0104, 0x90a0, 0x908d, 0x7c02, 0x4f16,
- 0xe200, 0x08ce, 0x4a15, 0xe200, 0x08ce, 0x7a80, 0x08e6,
- 0x102c, 0xb81c, 0x8813, 0x8b8b, 0xbf80, 0x0102, 0x90a0,
- 0x908d, 0x7980, 0x08db, 0x7a80, 0x0913, 0x7803, 0x7a80,
- 0x0913, 0x102c, 0xb81c, 0x8813, 0x8b8b, 0xbf80, 0x0105,
- 0x90a0, 0x908d, 0x7801, 0x7a80, 0x0913, 0x7801, 0x7a80,
- 0x0913, 0x7801, 0x7a80, 0x0913, 0x7980, 0x0920, 0x4f80,
- 0x7803, 0xe100, 0x08fe, 0x4f89, 0xe100, 0x08f5, 0xb901,
- 0x90a0, 0xb902, 0x90a0, 0x90a0, 0xb906, 0x90ad, 0xef00,
- 0xb901, 0x90a0, 0xb906, 0x90a0, 0xb900, 0x90a0, 0xb906,
- 0x90ad, 0xef00, 0x4f89, 0xe100, 0x090a, 0xb905, 0x90a0,
- 0xb900, 0x90a0, 0xb902, 0x90a0, 0xb906, 0x90ad, 0xef00,
- 0xb905, 0x90a0, 0xb900, 0x90a0, 0xb906, 0x90a0, 0xb904,
- 0x90ad, 0xef00, 0x4f89, 0xe100, 0x091b, 0xb901, 0x90a0,
- 0xb906, 0x90ad, 0xef00, 0xb905, 0x90a0, 0xb904, 0x90ad,
- 0xef00, 0xb91f, 0x8809, 0x0034, 0x8b88, 0xbec6, 0x0932,
- 0x1313, 0xbe1e, 0x1014, 0xbe1a, 0xbe01, 0xbfe8, 0xbe17,
- 0x6a13, 0x6214, 0xbe14, 0x9813, 0x9014, 0x98a0, 0xbe47,
- 0x5f0f, 0x002e, 0xe200, 0x093d, 0xbf80, 0xffd2, 0x900f,
- 0x7980, 0x0940, 0x100f, 0xb801, 0x900f, 0x400f, 0x8b00,
- 0xe500, 0xbe01, 0xbe09, 0x9010, 0xbe46, 0x5f11, 0x003f,
- 0xe200, 0x094f, 0xb900, 0x9011, 0x7980, 0x0952, 0x1011,
- 0xb801, 0x9011, 0x1001, 0xe388, 0x0bcf, 0x1021, 0x2009,
- 0x8813, 0x8b8b, 0x8b00, 0x1080, 0xbfe6, 0x7810, 0x8b00,
- 0x8b00, 0x2180, 0xbfb0, 0x0007, 0x4c11, 0x8b00, 0xe100,
- 0x096c, 0x4b11, 0x8b00, 0xe600, 0xb900, 0x7980, 0x096d,
- 0xbe0a, 0x4a11, 0x8b00, 0xe500, 0xbe01, 0x9012, 0x1037,
- 0x2008, 0x8811, 0x102e, 0x2008, 0x8812, 0x4a89, 0xb901,
- 0xe500, 0x9019, 0xe100, 0x09c9, 0xb900, 0x9019, 0x4a18,
- 0xe200, 0x09c9, 0x5f0a, 0x0010, 0xe200, 0x098d, 0x4b18,
- 0xb901, 0xe500, 0x9019, 0x7980, 0x09c9, 0x5f0a, 0x0013,
- 0xe200, 0x0997, 0x4b18, 0xb901, 0xe500, 0x9019, 0x7980,
- 0x09c9, 0x5f0a, 0x0011, 0xe200, 0x09a4, 0x4f18, 0xb905,
- 0xe500, 0x9080, 0xb901, 0xe500, 0x9019, 0x7980, 0x09c9,
- 0x5f0a, 0x0014, 0xe200, 0x09b1, 0x4c18, 0xb904, 0xe500,
- 0x9080, 0xb901, 0xe500, 0x9019, 0x7980, 0x09c9, 0x5f0a,
- 0x0012, 0xe200, 0x09be, 0x4d18, 0xb905, 0xe500, 0x9080,
- 0xb901, 0xe500, 0x9019, 0x7980, 0x09c9, 0x5f0a, 0x0015,
- 0xe200, 0x09c9, 0x4e18, 0xb904, 0xe500, 0x9080, 0xb901,
- 0xe500, 0x9019, 0x8b8a, 0x4f19, 0xe200, 0x09d4, 0x4b80,
- 0xe200, 0x09d6, 0x5d80, 0x0020, 0x7980, 0x09d9, 0x5d80,
- 0x0010, 0x4a80, 0xe200, 0x0bca, 0x1001, 0xba01, 0x9001,
- 0x1024, 0x2009, 0x8815, 0x8b89, 0x4d8d, 0xe200, 0x09f8,
- 0x4f16, 0xe100, 0x09ed, 0x8b89, 0x1080, 0xbfc0, 0x000c,
- 0x908c, 0x7980, 0x09f8, 0x4b89, 0x108d, 0xf600, 0xbfb0,
- 0x0003, 0x4a89, 0x8b00, 0xf500, 0xbfc0, 0x0008, 0x908c,
- 0x1022, 0x2009, 0x8811, 0x102e, 0x2008, 0x8812, 0x102f,
- 0x2008, 0x8813, 0x1020, 0x200a, 0x8814, 0x101d, 0x200a,
- 0x8815, 0x8b8a, 0x4f19, 0xe100, 0x0a11, 0x5e80, 0x0020,
- 0x5d80, 0x0018, 0x7980, 0x0a3e, 0x4f80, 0xe200, 0x0a1e,
- 0x8b8b, 0x108a, 0xbfa0, 0x7fc0, 0x8b00, 0xf704, 0x5c80,
- 0x0003, 0x7980, 0x0a3e, 0x4e80, 0xe200, 0x0a36, 0x8b8c,
- 0x178b, 0xbe01, 0xbfb7, 0x00f0, 0x308a, 0xe344, 0x0a3e,
- 0x8b8d, 0x4a8a, 0x8b00, 0xe200, 0x0a32, 0x5c80, 0x0006,
- 0x7980, 0x0a3e, 0x5c80, 0x000a, 0x7980, 0x0a3e, 0x4c80,
- 0xe200, 0x0a3e, 0x4b80, 0x8b00, 0xf500, 0x5c80, 0x0019,
- 0x4f80, 0xe200, 0x0a4d, 0x101f, 0x200a, 0x8816, 0x8b00,
- 0x8b00, 0x8b8e, 0x1780, 0xbfb7, 0x00f0, 0x900b, 0x7980,
- 0x0a64, 0x4e80, 0xe200, 0x0a5c, 0x101f, 0x200a, 0x8816,
- 0x8b00, 0x8b00, 0x8b8e, 0x1b80, 0xbfbb, 0x000f, 0x900b,
- 0x7980, 0x0a64, 0x4c80, 0xe200, 0x0a64, 0x8b8c, 0x1b80,
- 0xbfbb, 0x000f, 0x900b, 0x8b89, 0x1880, 0xbfb8, 0x001c,
- 0x4917, 0xe100, 0x0a6e, 0x4f80, 0x7980, 0x0a70, 0x4e80,
- 0x8b00, 0xf500, 0xbf98, 0x0002, 0x8b8d, 0x4b89, 0x8b00,
- 0xe600, 0xbfe1, 0x903e, 0xbe43, 0x6a0b, 0x613e, 0xbfe8,
- 0x980c, 0xbe42, 0x7c10, 0x1080, 0xbfe5, 0xbe1e, 0x7810,
- 0x1280, 0xbfb2, 0x001f, 0xbe11, 0x2027, 0x8811, 0x101e,
- 0x200a, 0x8816, 0x8b00, 0x128e, 0x4980, 0xe100, 0x0a9b,
- 0x4880, 0xe100, 0x0a98, 0xb900, 0x7980, 0x0a9f, 0xbe0a,
- 0x7980, 0x0a9f, 0x4880, 0xe200, 0x0a9f, 0xbe09, 0xbe1e,
- 0x158d, 0xbfb5, 0x003f, 0xbe11, 0x4889, 0xe200, 0x0aae,
- 0xbe1e, 0x1010, 0x4818, 0x8b00, 0xe600, 0xbfe1, 0xbe11,
- 0xbfe1, 0x8811, 0xbe1e, 0xb9ff, 0x8819, 0x8b00, 0x8b00,
- 0xbf46, 0x8b00, 0xe600, 0xbe1f, 0xbe01, 0xbfb0, 0x00ff,
- 0x202a, 0x8811, 0x8b00, 0x8b00, 0x108a, 0x900d, 0xb91f,
- 0x8809, 0x0732, 0x730d, 0x4f80, 0xe200, 0x0ad8, 0x1028,
- 0x200c, 0x8815, 0xbe43, 0x8b8b, 0x6a8d, 0xbec6, 0x0ad4,
- 0x618b, 0x9880, 0x548f, 0x8dad, 0xbe42, 0x7980, 0x0b24,
- 0x4e80, 0xe200, 0x0af9, 0x8b8c, 0x178b, 0xbe01, 0xbfb7,
- 0x00f0, 0x903e, 0x1029, 0x200c, 0x8815, 0x108d, 0xbec6,
- 0x0af6, 0x308b, 0xbe1e, 0x303e, 0x903f, 0x403f, 0xbe1f,
- 0xe500, 0x103e, 0x9080, 0xbfe6, 0x202a, 0x8811, 0x8b00,
- 0x1089, 0x548f, 0x8dad, 0x7980, 0x0b24, 0x4c8b, 0xe200,
- 0x0b1b, 0x1029, 0x200c, 0x8815, 0xbf80, 0x007f, 0x903e,
- 0x108d, 0xbec6, 0x0b14, 0x308b, 0xbe1e, 0x303e, 0x903f,
- 0x403f, 0xbe1f, 0xe500, 0xb900, 0x9080, 0xbfe6, 0x202a,
- 0x8811, 0x8b00, 0x1089, 0x548f, 0x8dad, 0x8b8a, 0xf500,
- 0x5e80, 0xffdf, 0x7980, 0x0b24, 0x1089, 0xbfe6, 0x202a,
- 0x8811, 0x8b00, 0x8b00, 0x548f, 0xbb1f, 0x8da0, 0x8b8f,
- 0x0732, 0x1021, 0x2009, 0x8811, 0x8b89, 0x101d, 0x200a,
- 0x8812, 0x1080, 0x7810, 0x8b00, 0xbe47, 0x288a, 0xbfb0,
- 0x03ff, 0x4989, 0xe200, 0x0b3e, 0xbe1e, 0x1012, 0x4918,
- 0x8b00, 0xe600, 0xbe0a, 0xbe11, 0x900e, 0xbe46, 0x108a,
- 0xbfb0, 0x001c, 0xbfe1, 0x880d, 0x8b00, 0x6b0e, 0xbe0a,
- 0x880c, 0x108c, 0xbfb0, 0x000f, 0x202d, 0x8814, 0x8b00,
- 0x8b00, 0x5589, 0xbf03, 0x8c0e, 0xbf00, 0x1030, 0x2008,
- 0x8811, 0xb91f, 0x8809, 0x108b, 0x0333, 0xbec6, 0x0b5f,
- 0x200e, 0x90a0, 0x8b00, 0x8b89, 0x9080, 0x4a18, 0xe200,
- 0x0b7a, 0x5f0a, 0x0011, 0xe200, 0x0b6c, 0x4f18, 0xe900,
- 0x0b7c, 0x5f0a, 0x0014, 0xe200, 0x0b73, 0x4c18, 0xe900,
- 0x0b9b, 0x5f0a, 0x0015, 0xe200, 0x0b7a, 0x4e18, 0xe900,
- 0x0bb2, 0x7980, 0x009e, 0x0034, 0xb91f, 0x8809, 0x0333,
- 0x8b8b, 0xbec6, 0x0b99, 0x1280, 0x6c80, 0xbfea, 0xbe1e,
- 0x1580, 0x6c88, 0xbfec, 0xbe13, 0x903e, 0x6cab, 0x903f,
- 0x4f3e, 0xb900, 0xf500, 0xbf80, 0x8000, 0x4f3f, 0xbf90,
- 0x0d00, 0xf500, 0xbf90, 0x2700, 0x90a0, 0xef00, 0x0034,
- 0xb91f, 0x8809, 0x0333, 0x8b88, 0xbec6, 0x0bb0, 0x1eab,
- 0x6c80, 0xbfed, 0x903e, 0x4180, 0xb900, 0xf500, 0xbf80,
- 0x8000, 0x4f3e, 0x8b00, 0xf500, 0xbf90, 0x4000, 0x90a8,
- 0xef00, 0x0034, 0xb91f, 0x8809, 0x0333, 0x8b8b, 0xbec6,
- 0x0bc8, 0x1280, 0x6c8b, 0xbfea, 0xbe1e, 0x1580, 0x6c80,
- 0xbfec, 0xbe13, 0x903e, 0x4f3e, 0xbf80, 0x4000, 0xf500,
- 0xbf90, 0x8000, 0x90a0, 0xef00, 0x0231, 0x8b8a, 0xb900,
- 0xbb20, 0x90a0, 0x5f08, 0x0023, 0xe100, 0x0043, 0x1008,
- 0xb801, 0x9008, 0x102b, 0x2008, 0x8812, 0x8b00, 0x8b00,
- 0x1080, 0x900a, 0x102c, 0x2008, 0x8812, 0x8b00, 0x8b00,
- 0x1080, 0x9009, 0x7980, 0x0952, 0x8148, 0x6946, 0xb801,
- 0x9046, 0xb901, 0x9041, 0x6944, 0xba08, 0xe344, 0x0bfe,
- 0x9044, 0x8b89, 0x0143, 0x694b, 0x881f, 0xbb0f, 0xada0,
- 0x8143, 0x0811, 0x304a, 0xe308, 0x0bfe, 0x6949, 0x9043,
- 0x0148, 0xbe3a
-};
-
-u16 asp_block_2[]={
- 0x0000, 0x0000, 0x0003, 0x0003, 0x0001, 0x0001,
- 0x0004, 0x0004, 0x0002, 0x0002, 0x0005, 0x0005,
- 0x0006, 0x0006, 0x0007, 0x0007, 0x0008, 0x0008,
- 0x0100, 0x0100, 0x0103, 0x0103, 0x0101, 0x0101,
- 0x0104, 0x0104, 0x0102, 0x0102, 0x0105, 0x0105,
- 0x0106, 0x0106, 0x0107, 0x0107, 0x0108, 0x0108
-};
-
-u16 asp_block_3[]={
- 0x0000, 0x0000, 0x0000, 0x1200, 0x1200, 0x1280, 0x0000, 0x05d0,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x1104, 0x1105, 0x1008, 0x1020, 0x1040, 0x1060,
- 0x1080, 0x10a0, 0x10b0, 0x100d, 0x1010, 0x10e0, 0x2000, 0x2980,
- 0x2b00, 0x2b40, 0x2a00, 0x2b90, 0x13dc, 0x2b80, 0x11bc, 0x134c,
- 0x1370, 0x12e0, 0x1240, 0x1260, 0x12c0, 0x009e, 0x0045, 0x10bc,
- 0x1394, 0x13b8, 0x11f6, 0x10f6, 0x11b0, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0815, 0x0956, 0x09df, 0x0be5, 0x0a19, 0x0a48, 0x0b37,
- 0x0b5d, 0x0a8b, 0x0aae, 0x0ad2 };
-
-
-u16 asp_block_4[] = {
- 0x0192, 0x04b6, 0x07d9, 0x0afb, 0x0e1c, 0x113a, 0x1455, 0x176e,
- 0x1a83, 0x1d93, 0x209f, 0x23a7, 0x26a8, 0x29a4, 0x2c99, 0x2f87,
- 0x326e, 0x354e, 0x3825, 0x3af3, 0x3db8, 0x4074, 0x4326, 0x45cd,
- 0x486a, 0x4afb, 0x4d81, 0x4ffb, 0x5269, 0x54ca, 0x571e, 0x5964,
- 0x5b9d, 0x5dc8, 0x5fe4, 0x61f1, 0x63ef, 0x65de, 0x67bd, 0x698c,
- 0x6b4b, 0x6cf9, 0x6e97, 0x7023, 0x719e, 0x7308, 0x7460, 0x75a6,
- 0x76d9, 0x77fb, 0x790a, 0x7a06, 0x7aef, 0x7bc6, 0x7c89, 0x7d3a,
- 0x7dd6, 0x7e60, 0x7ed6, 0x7f38, 0x7f87, 0x7fc2, 0x7fea, 0x7ffe,
- 0x7ffe, 0x7fea, 0x7fc2, 0x7f87, 0x7f38, 0x7ed6, 0x7e60, 0x7dd6,
- 0x7d3a, 0x7c89, 0x7bc6, 0x7aef, 0x7a06, 0x790a, 0x77fb, 0x76d9,
- 0x75a6, 0x7460, 0x7308, 0x719e, 0x7023, 0x6e97, 0x6cf9, 0x6b4b,
- 0x698c, 0x67bd, 0x65de, 0x63ef, 0x61f1, 0x5fe4, 0x5dc8, 0x5b9d,
- 0x5964, 0x571e, 0x54ca, 0x5269, 0x4ffb, 0x4d81, 0x4afb, 0x486a,
- 0x45cd, 0x4326, 0x4074, 0x3db8, 0x3af3, 0x3825, 0x354e, 0x326e,
- 0x2f87, 0x2c99, 0x29a4, 0x26a8, 0x23a7, 0x209f, 0x1d93, 0x1a83,
- 0x176e, 0x1455, 0x113a, 0x0e1c, 0x0afb, 0x07d9, 0x04b6, 0x0192,
- 0xfe6f, 0xfb4b, 0xf828, 0xf506, 0xf1e5, 0xeec7, 0xebac, 0xe893,
- 0xe57e, 0xe26e, 0xdf62, 0xdc5a, 0xd959, 0xd65d, 0xd368, 0xd07a,
- 0xcd93, 0xcab3, 0xc7dc, 0xc50e, 0xc249, 0xbf8d, 0xbcdb, 0xba34,
- 0xb797, 0xb506, 0xb280, 0xb006, 0xad98, 0xab37, 0xa8e3, 0xa69d,
- 0xa464, 0xa239, 0xa01d, 0x9e10, 0x9c12, 0x9a23, 0x9844, 0x9675,
- 0x94b6, 0x9308, 0x916a, 0x8fde, 0x8e63, 0x8cf9, 0x8ba1, 0x8a5b,
- 0x8928, 0x8806, 0x86f7, 0x85fb, 0x8512, 0x843b, 0x8378, 0x82c7,
- 0x822b, 0x81a1, 0x812b, 0x80c9, 0x807a, 0x803f, 0x8017, 0x8003,
- 0x8003, 0x8017, 0x803f, 0x807a, 0x80c9, 0x812b, 0x81a1, 0x822b,
- 0x82c7, 0x8378, 0x843b, 0x8512, 0x85fb, 0x86f7, 0x8806, 0x8928,
- 0x8a5b, 0x8ba1, 0x8cf9, 0x8e63, 0x8fde, 0x916a, 0x9308, 0x94b6,
- 0x9675, 0x9844, 0x9a23, 0x9c12, 0x9e10, 0xa01d, 0xa239, 0xa464,
- 0xa69d, 0xa8e3, 0xab37, 0xad98, 0xb006, 0xb280, 0xb506, 0xb797,
- 0xba34, 0xbcdb, 0xbf8d, 0xc249, 0xc50e, 0xc7dc, 0xcab3, 0xcd93,
- 0xd07a, 0xd368, 0xd65d, 0xd959, 0xdc5a, 0xdf62, 0xe26e, 0xe57e,
- 0xe893, 0xebac, 0xeec7, 0xf1e5, 0xf506, 0xf828, 0xfb4b, 0xfe6f,
- 0x7cc3, 0x725e, 0x68d5, 0x6017, 0x5813, 0x50b9, 0x49fb, 0x43cd,
- 0x3e22, 0x38ef, 0x342b, 0x2fcc, 0x2bc9, 0x281c, 0x24be, 0x21a6,
- 0x1ed1, 0x1c37, 0x19d5, 0x17a6, 0x15a5, 0x13ce, 0x121f, 0x1093,
- 0x0f28, 0x0ddc, 0x0cab, 0x0b93, 0x0a92, 0x09a7, 0x08cf, 0x080a,
- 0x0754, 0x06ae, 0x0615, 0x0589, 0x0509, 0x0494, 0x0428, 0x03c5,
- 0x036a, 0x0317, 0x02cb, 0x0285, 0x0245, 0x020a, 0x01d4, 0x01a2,
- 0x0175, 0x014b, 0x0125, 0x0102, 0x00e2, 0x00c5, 0x00aa, 0x0091,
- 0x007b, 0x0066, 0x0053, 0x0041, 0x0031, 0x0022, 0x0015, 0x0009,
- 0xfffe, 0xfff2, 0xffe5, 0xffd7, 0xffc8, 0xffb7, 0xffa5, 0xff91,
- 0xff7b, 0xff64, 0xff4a, 0xff2e, 0xff0f, 0xfeee, 0xfec9, 0xfea1,
- 0xfe76, 0xfe46, 0xfe13, 0xfdda, 0xfd9d, 0xfd5a, 0xfd11, 0xfcc1,
- 0xfc6b, 0xfc0c, 0xfba5, 0xfb34, 0xfab9, 0xfa33, 0xf9a1, 0xf902,
- 0xf854, 0xf797, 0xf6c8, 0xf5e7, 0xf4f1, 0xf3e5, 0xf2c1, 0xf183,
- 0xf027, 0xeeac, 0xed0f, 0xeb4d, 0xe961, 0xe74a, 0xe501, 0xe284,
- 0xdfcd, 0xdcd8, 0xd99d, 0xd618, 0xd242, 0xce12, 0xc982, 0xc487,
- 0xbf1a, 0xb92e, 0xb2ba, 0xabaf, 0xa402, 0x9ba3, 0x9282, 0x888d,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0004, 0x0006, 0x0008, 0x000a, 0x000c, 0x000e, 0x0010,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0006, 0x000a, 0x000e,
- 0x0010, 0x0014, 0x0016, 0x0018, 0x001a, 0x001c, 0x001e, 0x0020,
- 0x0000, 0x0000, 0x0000, 0x000a, 0x0010, 0x0016, 0x001a, 0x001e,
- 0x0020, 0x0024, 0x0026, 0x0028, 0x002a, 0x002c, 0x002e, 0x0030,
- 0x0000, 0x0000, 0x0010, 0x001a, 0x0020, 0x0026, 0x002a, 0x002e,
- 0x0030, 0x0034, 0x0036, 0x0038, 0x003a, 0x003c, 0x003e, 0x0040,
- 0x0000, 0x0010, 0x0020, 0x002a, 0x0030, 0x0036, 0x003a, 0x003e,
- 0x0040, 0x0044, 0x0046, 0x0048, 0x004a, 0x004c, 0x004e, 0x0050,
- 0x0000, 0x0020, 0x0030, 0x003a, 0x0040, 0x0046, 0x004a, 0x004e,
- 0x0050, 0x0054, 0x0056, 0x0058, 0x005a, 0x005c, 0x005e, 0x0060,
- 0x0000, 0x0030, 0x0040, 0x004a, 0x0050, 0x0056, 0x005a, 0x005e,
- 0x0060, 0x0064, 0x0066, 0x0068, 0x006a, 0x006c, 0x006e, 0x0070,
- 0x0008, 0x0021, 0x0042, 0x0064, 0x0086, 0x00a8, 0x00cb, 0x00ee,
- 0x0111, 0x0135, 0x0158, 0x017d, 0x01a1, 0x01c6, 0x01eb, 0x0211,
- 0x0236, 0x025d, 0x0283, 0x02aa, 0x02d1, 0x02f9, 0x0321, 0x0349,
- 0x0372, 0x039b, 0x03c4, 0x03ee, 0x0418, 0x0442, 0x046d, 0x0499,
- 0x04c4, 0x04f0, 0x051d, 0x054a, 0x0577, 0x05a5, 0x05d3, 0x0601,
- 0x0630, 0x0660, 0x0690, 0x06c0, 0x06f1, 0x0722, 0x0753, 0x0785,
- 0x07b8, 0x07eb, 0x081e, 0x0852, 0x0886, 0x08bb, 0x08f0, 0x0926,
- 0x095c, 0x0993, 0x09ca, 0x0a02, 0x0a3a, 0x0a73, 0x0aac, 0x0ae6,
- 0x0b20, 0x0b5b, 0x0b96, 0x0bd2, 0x0c0e, 0x0c4b, 0x0c89, 0x0cc7,
- 0x0d05, 0x0d44, 0x0d84, 0x0dc5, 0x0e05, 0x0e47, 0x0e89, 0x0ecc,
- 0x0f0f, 0x0f53, 0x0f97, 0x0fdd, 0x1022, 0x1069, 0x10b0, 0x10f7,
- 0x1140, 0x1189, 0x11d2, 0x121c, 0x1267, 0x12b3, 0x12ff, 0x134c,
- 0x139a, 0x13e8, 0x1438, 0x1487, 0x14d8, 0x1529, 0x157b, 0x15ce,
- 0x1621, 0x1676, 0x16cb, 0x1720, 0x1777, 0x17ce, 0x1826, 0x187f,
- 0x18d9, 0x1934, 0x198f, 0x19eb, 0x1a48, 0x1aa6, 0x1b05, 0x1b64,
- 0x1bc5, 0x1c26, 0x1c88, 0x1ceb, 0x1d4f, 0x1db4, 0x1e1a, 0x1e80,
- 0x1ee8, 0x1f51, 0x1fba, 0x2025, 0x2090, 0x20fc, 0x216a, 0x21d8,
- 0x2247, 0x22b8, 0x2329, 0x239b, 0x240f, 0x2483, 0x24f9, 0x256f,
- 0x25e7, 0x2660, 0x26da, 0x2755, 0x27d1, 0x284e, 0x28cc, 0x294b,
- 0x29cc, 0x2a4e, 0x2ad1, 0x2b55, 0x2bda, 0x2c61, 0x2ce8, 0x2d71,
- 0x2dfb, 0x2e87, 0x2f13, 0x2fa1, 0x3031, 0x30c1, 0x3153, 0x31e6,
- 0x327b, 0x3310, 0x33a8, 0x3440, 0x34da, 0x3575, 0x3612, 0x36b0,
- 0x3750, 0x37f1, 0x3893, 0x3937, 0x39dc, 0x3a83, 0x3b2c, 0x3bd6,
- 0x3c81, 0x3d2e, 0x3ddd, 0x3e8d, 0x3f3f, 0x3ff2, 0x40a7, 0x415d,
- 0x4216, 0x42d0, 0x438b, 0x4448, 0x4507, 0x45c8, 0x468b, 0x474f,
- 0x4815, 0x48dd, 0x49a6, 0x4a72, 0x4b3f, 0x4c0e, 0x4cdf, 0x4db2,
- 0x4e87, 0x4f5d, 0x5036, 0x5111, 0x51ed, 0x52cc, 0x53ac, 0x548f,
- 0x5573, 0x565a, 0x5743, 0x582e, 0x591b, 0x5a0a, 0x5afb, 0x5bef,
- 0x5ce4, 0x5ddc, 0x5ed7, 0x5fd3, 0x60d2, 0x61d3, 0x62d6, 0x63dc,
- 0x64e4, 0x65ee, 0x66fb, 0x680a, 0x691c, 0x6a30, 0x6b47, 0x6c60,
- 0x6d7c, 0x6e9a, 0x6fbb, 0x70de, 0x7204, 0x732d, 0x7459, 0x7587,
- 0x76b8, 0x77eb, 0x7922, 0x7a5b, 0x7b97, 0x7cd6, 0x7e18, 0x7f5d,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0002, 0x0002, 0x0002, 0x0003,
- 0x0003, 0x0004, 0x0004, 0x0005, 0x0006, 0x0008, 0x0009, 0x000a,
- 0x000c, 0x0010, 0x0012, 0x0015, 0x0019, 0x0022, 0x0024, 0x002a,
- 0x0031, 0x003e, 0x0049, 0x0055, 0x0062, 0x007c, 0x0092, 0x00a9,
- 0x00c4, 0x00fc, 0x0125, 0x0152, 0x0187, 0x01f2, 0x024a, 0x02a4,
- 0x030d, 0x03e3, 0x0492, 0x0547, 0x061b, 0x07c7, 0x0923, 0x0a8d,
- 0x0c19, 0x0eb3, 0x1228, 0x14c1, 0x17fb, 0x1d17, 0x22f2, 0x2835,
- 0x2dd4, 0x3cd0, 0x4cf5, 0x51cc, 0x7fff, 0x7fff, 0x7fff, 0x7fff,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001,
- 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0002, 0x0002,
- 0x0002, 0x0003, 0x0004, 0x0005, 0x0005, 0x0007, 0x0008, 0x000a,
- 0x000b, 0x000e, 0x0011, 0x0014, 0x0017, 0x001c, 0x0022, 0x0028,
- 0x002e, 0x0039, 0x0045, 0x0050, 0x005c, 0x0073, 0x008a, 0x00a0,
- 0x00b9, 0x00e7, 0x0114, 0x0141, 0x0172, 0x01ce, 0x0228, 0x0283,
- 0x02e3, 0x039b, 0x0454, 0x0501, 0x05bf, 0x072a, 0x0899, 0x0a18,
- 0x0b7e, 0x0e55, 0x10d3, 0x1404, 0x16c3, 0x16c3, 0x16c3, 0x16c3,
- 0x0012, 0x0024, 0x0048, 0x006c, 0x0090, 0x00b4, 0x00d8, 0x00fc,
- 0x0120, 0x0144, 0x0168, 0x0168, 0x01b0, 0x01b0, 0x021c, 0x021c,
- 0x0000, 0x0003, 0x0008, 0x000b, 0x0001, 0x0004, 0x0009, 0x000c,
- 0x0002, 0x0005, 0x000a, 0x000d, 0x0010, 0x0013, 0x0011, 0x0014,
- 0x0012, 0x0015, 0x0100, 0x0103, 0x0108, 0x010b, 0x0101, 0x0104,
- 0x0109, 0x010c, 0x0102, 0x0105, 0x010a, 0x010d, 0x0110, 0x0113,
- 0x0111, 0x0114, 0x0112, 0x0115 };
diff --git a/sound/oss/nm256_audio.c b/sound/oss/nm256_audio.c
index b70e3a137315c..f9166e1351920 100644
--- a/sound/oss/nm256_audio.c
+++ b/sound/oss/nm256_audio.c
@@ -1047,7 +1047,7 @@ nm256_peek_for_sig (struct nm256_info *card)
* VERSTR is a human-readable version string.
*/
-static int __init
+static int __devinit
nm256_install(struct pci_dev *pcidev, enum nm256rev rev, char *verstr)
{
struct nm256_info *card;
diff --git a/sound/oss/opl3sa2.c b/sound/oss/opl3sa2.c
index cb1019e6e5a85..7b4996e71576c 100644
--- a/sound/oss/opl3sa2.c
+++ b/sound/oss/opl3sa2.c
@@ -711,7 +711,7 @@ static void __init attach_opl3sa2_mixer(struct address_info *hw_config, int card
}
-static void __init opl3sa2_clear_slots(struct address_info* hw_config)
+static void opl3sa2_clear_slots(struct address_info* hw_config)
{
int i;
diff --git a/sound/oss/pss.c b/sound/oss/pss.c
index c5d2ab0ffa66a..3ed38765dcc43 100644
--- a/sound/oss/pss.c
+++ b/sound/oss/pss.c
@@ -1149,7 +1149,7 @@ static int mss_irq __initdata = -1;
static int mss_dma __initdata = -1;
static int mpu_io __initdata = -1;
static int mpu_irq __initdata = -1;
-static int pss_no_sound __initdata = 0; /* Just configure non-sound components */
+static int pss_no_sound = 0; /* Just configure non-sound components */
static int pss_keep_settings = 1; /* Keep hardware settings at module exit */
static char *pss_firmware = "/etc/sound/pss_synth";
diff --git a/sound/oss/sb_card.c b/sound/oss/sb_card.c
index de3fd492d0b0b..680b82e152986 100644
--- a/sound/oss/sb_card.c
+++ b/sound/oss/sb_card.c
@@ -26,9 +26,6 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
-#ifdef CONFIG_MCA
-#include <linux/mca.h>
-#endif /* CONFIG_MCA */
#include "sound_config.h"
#include "sb_mixer.h"
#include "sb.h"
@@ -289,6 +286,7 @@ static struct pnp_card_driver sb_pnp_driver = {
.probe = sb_pnp_probe,
.remove = sb_pnp_remove,
};
+MODULE_DEVICE_TABLE(pnp_card, sb_pnp_card_table);
#endif /* CONFIG_PNP */
static int __init sb_init(void)
diff --git a/sound/oss/sonicvibes.c b/sound/oss/sonicvibes.c
index 432bf4965b413..e1d69611a2573 100644
--- a/sound/oss/sonicvibes.c
+++ b/sound/oss/sonicvibes.c
@@ -365,7 +365,7 @@ struct sv_state {
unsigned char obuf[MIDIOUTBUF];
} midi;
- struct gameport gameport;
+ struct gameport *gameport;
};
/* --------------------------------------------------------------------- */
@@ -2470,7 +2470,7 @@ MODULE_LICENSE("GPL");
static struct initvol {
int mixch;
int vol;
-} initvol[] __initdata = {
+} initvol[] __devinitdata = {
{ SOUND_MIXER_WRITE_RECLEV, 0x4040 },
{ SOUND_MIXER_WRITE_LINE1, 0x4040 },
{ SOUND_MIXER_WRITE_CD, 0x4040 },
@@ -2485,12 +2485,39 @@ static struct initvol {
#define RSRCISIOREGION(dev,num) (pci_resource_start((dev), (num)) != 0 && \
(pci_resource_flags((dev), (num)) & IORESOURCE_IO))
+static int __devinit sv_register_gameport(struct sv_state *s, int io_port)
+{
+ struct gameport *gp;
+
+ if (!request_region(io_port, SV_EXTENT_GAME, "S3 SonicVibes Gameport")) {
+ printk(KERN_ERR "sv: gameport io ports are in use\n");
+ return -EBUSY;
+ }
+
+ s->gameport = gp = gameport_allocate_port();
+ if (!gp) {
+ printk(KERN_ERR "sv: can not allocate memory for gameport\n");
+ release_region(io_port, SV_EXTENT_GAME);
+ return -ENOMEM;
+ }
+
+ gameport_set_name(gp, "S3 SonicVibes Gameport");
+ gameport_set_phys(gp, "isa%04x/gameport0", io_port);
+ gp->dev.parent = &s->dev->dev;
+ gp->io = io_port;
+
+ gameport_register_port(gp);
+
+ return 0;
+}
+
static int __devinit sv_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid)
{
- static char __initdata sv_ddma_name[] = "S3 Inc. SonicVibes DDMA Controller";
+ static char __devinitdata sv_ddma_name[] = "S3 Inc. SonicVibes DDMA Controller";
struct sv_state *s;
mm_segment_t fs;
int i, val, ret;
+ int gpio;
char *ddmaname;
unsigned ddmanamelen;
@@ -2546,11 +2573,11 @@ static int __devinit sv_probe(struct pci_dev *pcidev, const struct pci_device_id
s->iomidi = pci_resource_start(pcidev, RESOURCE_MIDI);
s->iodmaa = pci_resource_start(pcidev, RESOURCE_DDMA);
s->iodmac = pci_resource_start(pcidev, RESOURCE_DDMA) + SV_EXTENT_DMA;
- s->gameport.io = pci_resource_start(pcidev, RESOURCE_GAME);
+ gpio = pci_resource_start(pcidev, RESOURCE_GAME);
pci_write_config_dword(pcidev, 0x40, s->iodmaa | 9); /* enable and use extended mode */
pci_write_config_dword(pcidev, 0x48, s->iodmac | 9); /* enable */
printk(KERN_DEBUG "sv: io ports: %#lx %#lx %#lx %#lx %#x %#x %#x\n",
- s->iosb, s->ioenh, s->iosynth, s->iomidi, s->gameport.io, s->iodmaa, s->iodmac);
+ s->iosb, s->ioenh, s->iosynth, s->iomidi, gpio, s->iodmaa, s->iodmac);
s->irq = pcidev->irq;
/* hack */
@@ -2577,10 +2604,7 @@ static int __devinit sv_probe(struct pci_dev *pcidev, const struct pci_device_id
printk(KERN_ERR "sv: io ports %#lx-%#lx in use\n", s->iosynth, s->iosynth+SV_EXTENT_SYNTH-1);
goto err_region1;
}
- if (s->gameport.io && !request_region(s->gameport.io, SV_EXTENT_GAME, "ESS Solo1")) {
- printk(KERN_ERR "sv: gameport io ports in use\n");
- s->gameport.io = 0;
- }
+
/* initialize codec registers */
outb(0x80, s->ioenh + SV_CODEC_CONTROL); /* assert reset */
udelay(50);
@@ -2639,7 +2663,7 @@ static int __devinit sv_probe(struct pci_dev *pcidev, const struct pci_device_id
}
set_fs(fs);
/* register gameport */
- gameport_register_port(&s->gameport);
+ sv_register_gameport(s, gpio);
/* store it in the driver field */
pci_set_drvdata(pcidev, s);
/* put it into driver list */
@@ -2659,8 +2683,6 @@ static int __devinit sv_probe(struct pci_dev *pcidev, const struct pci_device_id
printk(KERN_ERR "sv: cannot register misc device\n");
free_irq(s->irq, s);
err_irq:
- if (s->gameport.io)
- release_region(s->gameport.io, SV_EXTENT_GAME);
release_region(s->iosynth, SV_EXTENT_SYNTH);
err_region1:
release_region(s->iomidi, SV_EXTENT_MIDI);
@@ -2689,9 +2711,10 @@ static void __devexit sv_remove(struct pci_dev *dev)
/*outb(0, s->iodmaa + SV_DMA_RESET);*/
/*outb(0, s->iodmac + SV_DMA_RESET);*/
free_irq(s->irq, s);
- if (s->gameport.io) {
- gameport_unregister_port(&s->gameport);
- release_region(s->gameport.io, SV_EXTENT_GAME);
+ if (s->gameport) {
+ int gpio = s->gameport->io;
+ gameport_unregister_port(s->gameport);
+ release_region(gpio, SV_EXTENT_GAME);
}
release_region(s->iodmac, SV_EXTENT_DMA);
release_region(s->iodmaa, SV_EXTENT_DMA);
diff --git a/sound/oss/soundcard.c b/sound/oss/soundcard.c
index e878a971251b9..de91c90a01121 100644
--- a/sound/oss/soundcard.c
+++ b/sound/oss/soundcard.c
@@ -329,7 +329,7 @@ static int sound_mixer_ioctl(int mixdev, unsigned int cmd, void __user *arg)
static int sound_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
- int err, len = 0, dtype;
+ int len = 0, dtype;
int dev = iminor(inode);
void __user *p = (void __user *)arg;
@@ -341,11 +341,11 @@ static int sound_ioctl(struct inode *inode, struct file *file,
if (len < 1 || len > 65536 || !p)
return -EFAULT;
if (_SIOC_DIR(cmd) & _SIOC_WRITE)
- if ((err = verify_area(VERIFY_READ, p, len)) < 0)
- return err;
+ if (!access_ok(VERIFY_READ, p, len))
+ return -EFAULT;
if (_SIOC_DIR(cmd) & _SIOC_READ)
- if ((err = verify_area(VERIFY_WRITE, p, len)) < 0)
- return err;
+ if (!access_ok(VERIFY_WRITE, p, len))
+ return -EFAULT;
}
DEB(printk("sound_ioctl(dev=%d, cmd=0x%x, arg=0x%x)\n", dev, cmd, arg));
if (cmd == OSS_GETVERSION)
diff --git a/sound/oss/sscape.c b/sound/oss/sscape.c
index 08b52658012e7..50ca646294502 100644
--- a/sound/oss/sscape.c
+++ b/sound/oss/sscape.c
@@ -1393,7 +1393,7 @@ static struct address_info cfg;
static struct address_info cfg_mpu;
static int __initdata spea = -1;
-static int __initdata mss = 0;
+static int mss = 0;
static int __initdata dma = -1;
static int __initdata irq = -1;
static int __initdata io = -1;
diff --git a/sound/oss/trident.c b/sound/oss/trident.c
index 8395501af2ae1..47537f0a5b058 100644
--- a/sound/oss/trident.c
+++ b/sound/oss/trident.c
@@ -441,7 +441,7 @@ struct trident_card {
struct timer_list timer;
/* Game port support */
- struct gameport gameport;
+ struct gameport *gameport;
};
enum dmabuf_mode {
@@ -487,7 +487,7 @@ static struct trident_channel *ali_alloc_rec_pcm_channel(struct trident_card *ca
static struct trident_channel *ali_alloc_pcm_channel(struct trident_card *card);
static void ali_restore_regs(struct trident_card *card);
static void ali_save_regs(struct trident_card *card);
-static int trident_suspend(struct pci_dev *dev, u32 unused);
+static int trident_suspend(struct pci_dev *dev, pm_message_t unused);
static int trident_resume(struct pci_dev *dev);
static void ali_free_pcm_channel(struct trident_card *card, unsigned int channel);
static int ali_setup_multi_channels(struct trident_card *card, int chan_nums);
@@ -3723,7 +3723,7 @@ ali_restore_regs(struct trident_card *card)
}
static int
-trident_suspend(struct pci_dev *dev, u32 unused)
+trident_suspend(struct pci_dev *dev, pm_message_t unused)
{
struct trident_card *card = pci_get_drvdata(dev);
@@ -4257,21 +4257,21 @@ trident_ac97_init(struct trident_card *card)
static unsigned char
trident_game_read(struct gameport *gameport)
{
- struct trident_card *card = gameport->driver;
+ struct trident_card *card = gameport->port_data;
return inb(TRID_REG(card, T4D_GAME_LEG));
}
static void
trident_game_trigger(struct gameport *gameport)
{
- struct trident_card *card = gameport->driver;
+ struct trident_card *card = gameport->port_data;
outb(0xff, TRID_REG(card, T4D_GAME_LEG));
}
static int
trident_game_cooked_read(struct gameport *gameport, int *axes, int *buttons)
{
- struct trident_card *card = gameport->driver;
+ struct trident_card *card = gameport->port_data;
int i;
*buttons = (~inb(TRID_REG(card, T4D_GAME_LEG)) >> 4) & 0xf;
@@ -4288,7 +4288,7 @@ trident_game_cooked_read(struct gameport *gameport, int *axes, int *buttons)
static int
trident_game_open(struct gameport *gameport, int mode)
{
- struct trident_card *card = gameport->driver;
+ struct trident_card *card = gameport->port_data;
switch (mode) {
case GAMEPORT_MODE_COOKED:
@@ -4305,6 +4305,31 @@ trident_game_open(struct gameport *gameport, int mode)
return 0;
}
+static int __devinit
+trident_register_gameport(struct trident_card *card)
+{
+ struct gameport *gp;
+
+ card->gameport = gp = gameport_allocate_port();
+ if (!gp) {
+ printk(KERN_ERR "trident: can not allocate memory for gameport\n");
+ return -ENOMEM;
+ }
+
+ gameport_set_name(gp, "Trident 4DWave");
+ gameport_set_phys(gp, "pci%s/gameport0", pci_name(card->pci_dev));
+ gp->read = trident_game_read;
+ gp->trigger = trident_game_trigger;
+ gp->cooked_read = trident_game_cooked_read;
+ gp->open = trident_game_open;
+ gp->fuzz = 64;
+ gp->port_data = card;
+
+ gameport_register_port(gp);
+
+ return 0;
+}
+
/* install the driver, we do not allocate hardware channel nor DMA buffer */
/* now, they are defered until "ACCESS" time (in prog_dmabuf called by */
/* open/read/write/ioctl/mmap) */
@@ -4368,13 +4393,6 @@ trident_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_id)
card->banks[BANK_B].addresses = &bank_b_addrs;
card->banks[BANK_B].bitmap = 0UL;
- card->gameport.driver = card;
- card->gameport.fuzz = 64;
- card->gameport.read = trident_game_read;
- card->gameport.trigger = trident_game_trigger;
- card->gameport.cooked_read = trident_game_cooked_read;
- card->gameport.open = trident_game_open;
-
init_MUTEX(&card->open_sem);
spin_lock_init(&card->lock);
init_timer(&card->timer);
@@ -4508,7 +4526,7 @@ trident_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_id)
trident_enable_loop_interrupts(card);
/* Register gameport */
- gameport_register_port(&card->gameport);
+ trident_register_gameport(card);
out:
return rc;
@@ -4551,7 +4569,8 @@ trident_remove(struct pci_dev *pci_dev)
}
/* Unregister gameport */
- gameport_unregister_port(&card->gameport);
+ if (card->gameport)
+ gameport_unregister_port(card->gameport);
/* Kill interrupts, and SP/DIF */
trident_disable_loop_interrupts(card);
diff --git a/sound/oss/wavfront.c b/sound/oss/wavfront.c
index 9057edaaab16f..cce1278dc487c 100644
--- a/sound/oss/wavfront.c
+++ b/sound/oss/wavfront.c
@@ -1518,45 +1518,56 @@ wavefront_load_gus_patch (int devno, int format, const char __user *addr,
int offs, int count, int pmgr_flag)
{
struct patch_info guspatch;
- wavefront_patch_info samp, pat, prog;
+ wavefront_patch_info *samp, *pat, *prog;
wavefront_patch *patp;
wavefront_sample *sampp;
wavefront_program *progp;
int i,base_note;
long sizeof_patch;
+ int rc = -ENOMEM;
+
+ samp = kmalloc(3 * sizeof(wavefront_patch_info), GFP_KERNEL);
+ if (!samp)
+ goto free_fail;
+ pat = samp + 1;
+ prog = pat + 1;
/* Copy in the header of the GUS patch */
sizeof_patch = (long) &guspatch.data[0] - (long) &guspatch;
if (copy_from_user(&((char *) &guspatch)[offs],
- &(addr)[offs], sizeof_patch - offs))
- return -EFAULT;
+ &(addr)[offs], sizeof_patch - offs)) {
+ rc = -EFAULT;
+ goto free_fail;
+ }
if ((i = wavefront_find_free_patch ()) == -1) {
- return -EBUSY;
+ rc = -EBUSY;
+ goto free_fail;
}
- pat.number = i;
- pat.subkey = WF_ST_PATCH;
- patp = &pat.hdr.p;
+ pat->number = i;
+ pat->subkey = WF_ST_PATCH;
+ patp = &pat->hdr.p;
if ((i = wavefront_find_free_sample ()) == -1) {
- return -EBUSY;
+ rc = -EBUSY;
+ goto free_fail;
}
- samp.number = i;
- samp.subkey = WF_ST_SAMPLE;
- samp.size = guspatch.len;
- sampp = &samp.hdr.s;
+ samp->number = i;
+ samp->subkey = WF_ST_SAMPLE;
+ samp->size = guspatch.len;
+ sampp = &samp->hdr.s;
- prog.number = guspatch.instr_no;
- progp = &prog.hdr.pr;
+ prog->number = guspatch.instr_no;
+ progp = &prog->hdr.pr;
/* Setup the patch structure */
patp->amplitude_bias=guspatch.volume;
patp->portamento=0;
- patp->sample_number= samp.number & 0xff;
- patp->sample_msb= samp.number>>8;
+ patp->sample_number= samp->number & 0xff;
+ patp->sample_msb= samp->number >> 8;
patp->pitch_bend= /*12*/ 0;
patp->mono=1;
patp->retrigger=1;
@@ -1589,7 +1600,7 @@ wavefront_load_gus_patch (int devno, int format, const char __user *addr,
/* Program for this patch */
- progp->layer[0].patch_number= pat.number; /* XXX is this right ? */
+ progp->layer[0].patch_number= pat->number; /* XXX is this right ? */
progp->layer[0].mute=1;
progp->layer[0].pan_or_mod=1;
progp->layer[0].pan=7;
@@ -1637,11 +1648,11 @@ wavefront_load_gus_patch (int devno, int format, const char __user *addr,
/* Now ship it down */
- wavefront_send_sample (&samp,
+ wavefront_send_sample (samp,
(unsigned short __user *) &(addr)[sizeof_patch],
(guspatch.mode & WAVE_UNSIGNED) ? 1:0);
- wavefront_send_patch (&pat);
- wavefront_send_program (&prog);
+ wavefront_send_patch (pat);
+ wavefront_send_program (prog);
/* Now pan as best we can ... use the slave/internal MIDI device
number if it exists (since it talks to the WaveFront), or the
@@ -1653,8 +1664,11 @@ wavefront_load_gus_patch (int devno, int format, const char __user *addr,
((guspatch.panning << 4) > 127) ?
127 : (guspatch.panning << 4));
}
+ rc = 0;
- return(0);
+free_fail:
+ kfree(samp);
+ return rc;
}
static int
diff --git a/sound/oss/ymfpci.c b/sound/oss/ymfpci.c
index 3bbe819ed3f72..05203ad523f7a 100644
--- a/sound/oss/ymfpci.c
+++ b/sound/oss/ymfpci.c
@@ -2074,7 +2074,7 @@ static /*const*/ struct file_operations ymf_mixer_fops = {
/*
*/
-static int ymf_suspend(struct pci_dev *pcidev, u32 unused)
+static int ymf_suspend(struct pci_dev *pcidev, pm_message_t unused)
{
struct ymf_unit *unit = pci_get_drvdata(pcidev);
unsigned long flags;
diff --git a/sound/parisc/Kconfig b/sound/parisc/Kconfig
index 01cc80db26c04..a5a7f9d75d051 100644
--- a/sound/parisc/Kconfig
+++ b/sound/parisc/Kconfig
@@ -1,6 +1,6 @@
# ALSA PA-RISC drivers
-menu "ALSA GSC devices"
+menu "GSC devices"
depends on SND!=n && GSC
config SND_HARMONY
diff --git a/sound/parisc/harmony.c b/sound/parisc/harmony.c
index 3b9a8bd4f6308..d7a8f9f5896fc 100644
--- a/sound/parisc/harmony.c
+++ b/sound/parisc/harmony.c
@@ -1,264 +1,88 @@
-/*
- * Harmony chipset driver
+/* Hewlett-Packard Harmony audio driver
*
- * This is a sound driver for ASP's and Lasi's Harmony sound chip
- * and is unlikely to be used for anything other than on a HP PA-RISC.
+ * This is a driver for the Harmony audio chipset found
+ * on the LASI ASIC of various early HP PA-RISC workstations.
*
- * Harmony is found in HP 712s, 715/new and many other GSC based machines.
- * On older 715 machines you'll find the technically identical chip
- * called 'Vivace'. Both Harmony and Vivace are supported by this driver.
+ * Copyright (C) 2004, Kyle McMartin <kyle@{debian.org,parisc-linux.org}>
*
- * this ALSA driver is based on OSS driver by:
- * Copyright 2000 (c) Linuxcare Canada, Alex deVries <alex@linuxcare.com>
- * Copyright 2000-2002 (c) Helge Deller <deller@gmx.de>
- * Copyright 2001 (c) Matthieu Delahaye <delahaym@esiee.fr>
+ * Based on the previous Harmony incarnations by,
+ * Copyright 2000 (c) Linuxcare Canada, Alex deVries
+ * Copyright 2000-2003 (c) Helge Deller
+ * Copyright 2001 (c) Matthieu Delahaye
+ * Copyright 2001 (c) Jean-Christophe Vaugeois
+ * Copyright 2003 (c) Laurent Canet
+ * Copyright 2004 (c) Stuart Brady
*
- * TODO:
- * - use generic DMA interface and ioremap()/iounmap()
- * - capture is still untested (and probaby non-working)
- * - spin locks
- * - implement non-consistent DMA pages
- * - implement gain meter
- * - module parameters
- * - correct cleaning sequence
- * - better error checking
- * - try to have a better quality.
- *
- */
-
-/*
- * Harmony chipset 'modus operandi'.
- * - This chipset is found in some HP 32bit workstations, like 712, or B132 class.
- * most of controls are done through registers. Register are found at a fixed offset
- * from the hard physical adress, given in struct dev by register_parisc_driver.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
*
- * Playback and recording use 4kb pages (dma or not, depending on the machine).
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*
- * Most of PCM playback & capture is done through interrupt. When harmony needs
- * a new buffer to put recorded data or read played PCM, it sends an interrupt.
- * Bits 2 and 10 of DSTATUS register are '1' when harmony needs respectively
- * a new page for recording and playing.
- * Interrupt are disabled/enabled by writing to bit 32 of DSTATUS.
- * Adresses of next page to be played is put in PNXTADD register, next page
- * to be recorded is put in RNXTADD. There is 2 read-only registers, PCURADD and
- * RCURADD that provides adress of current page.
- *
- * Harmony has no way to control full duplex or half duplex mode. It means
- * that we always need to provide adresses of playback and capture data, even
- * when this is not needed. That's why we statically alloc one graveyard
- * buffer (to put recorded data in play-only mode) and a silence buffer.
- *
- * Bitrate, number of channels and data format are controlled with
- * the CNTL register.
+ * You 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.
*
- * Mixer work is done through one register (GAINCTL). Only input gain,
- * output attenuation and general attenuation control is provided. There is
- * also controls for enabling/disabling internal speaker and line
- * input.
+ * Notes:
+ * - graveyard and silence buffers last for lifetime of
+ * the driver. playback and capture buffers are allocated
+ * per _open()/_close().
+ *
+ * TODO:
*
- * Buffers used by this driver are all DMA consistent.
*/
-#include <linux/delay.h>
-#include <sound/driver.h>
#include <linux/init.h>
-#include <linux/interrupt.h>
#include <linux/slab.h>
#include <linux/time.h>
#include <linux/wait.h>
-#include <linux/moduleparam.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/dma-mapping.h>
+
+#include <sound/driver.h>
#include <sound/core.h>
-#include <sound/control.h>
#include <sound/pcm.h>
+#include <sound/control.h>
#include <sound/rawmidi.h>
#include <sound/initval.h>
#include <sound/info.h>
-#include <asm/hardware.h>
+
#include <asm/io.h>
+#include <asm/hardware.h>
#include <asm/parisc-device.h>
-MODULE_AUTHOR("Laurent Canet <canetl@esiee.fr>");
-MODULE_DESCRIPTION("ALSA Harmony sound driver");
-MODULE_LICENSE("GPL");
-MODULE_SUPPORTED_DEVICE("{{ALSA,Harmony soundcard}}");
-
-#undef DEBUG
-#ifdef DEBUG
-# define DPRINTK printk
-#else
-# define DPRINTK(x,...)
-#endif
-
-#define PFX "harmony: "
-
-#define MAX_PCM_DEVICES 1
-#define MAX_PCM_SUBSTREAMS 4
-#define MAX_MIDI_DEVICES 0
-
-#define HARMONY_BUF_SIZE 4096
-#define MAX_BUFS 10
-#define MAX_BUFFER_SIZE (MAX_BUFS * HARMONY_BUF_SIZE)
-
-/* number of silence & graveyard buffers */
-#define GRAVEYARD_BUFS 3
-#define SILENCE_BUFS 3
-
-#define HARMONY_CNTL_C 0x80000000
-
-#define HARMONY_DSTATUS_PN 0x00000200
-#define HARMONY_DSTATUS_RN 0x00000002
-#define HARMONY_DSTATUS_IE 0x80000000
-
-#define HARMONY_DF_16BIT_LINEAR 0x00000000
-#define HARMONY_DF_8BIT_ULAW 0x00000001
-#define HARMONY_DF_8BIT_ALAW 0x00000002
-
-#define HARMONY_SS_MONO 0x00000000
-#define HARMONY_SS_STEREO 0x00000001
-
-/*
- * Channels Mask in mixer register
- * try some "reasonable" default gain values
- */
-
-#define HARMONY_GAIN_TOTAL_SILENCE 0x00F00FFF
-
-/* the following should be enough (mixer is
- * very sensible on harmony)
- */
-#define HARMONY_GAIN_DEFAULT 0x0F2FF082
-
-
-/* useless since only one card is supported ATM */
-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;
-
-module_param_array(index, int, NULL, 0444);
-MODULE_PARM_DESC(index, "Index value for Harmony device.");
-module_param_array(id, charp, NULL, 0444);
-MODULE_PARM_DESC(id, "ID string for Harmony device.");
-module_param_array(enable, bool, NULL, 0444);
-MODULE_PARM_DESC(enable, "Enable Harmony device.");
-
-/* Register offset (from base hpa) */
-#define REG_ID 0x00
-#define REG_RESET 0x04
-#define REG_CNTL 0x08
-#define REG_GAINCTL 0x0C
-#define REG_PNXTADD 0x10
-#define REG_PCURADD 0x14
-#define REG_RNXTADD 0x18
-#define REG_RCURADD 0x1C
-#define REG_DSTATUS 0x20
-#define REG_OV 0x24
-#define REG_PIO 0x28
-#define REG_DIAG 0x3C
-
-/*
- * main harmony structure
- */
-
-typedef struct snd_card_harmony {
-
- /* spinlocks (To be done) */
- spinlock_t mixer_lock;
- spinlock_t control_lock;
-
- /* parameters */
- int irq;
- unsigned long hpa;
- int id;
- int rev;
-
- u32 current_gain;
- int data_format; /* HARMONY_DF_xx_BIT_xxx */
- int sample_rate; /* HARMONY_SR_xx_KHZ */
- int stereo_select; /* HARMONY_SS_MONO or HARMONY_SS_STEREO */
- int format_initialized;
-
- unsigned long ply_buffer;
- int ply_buf;
- int ply_count;
- int ply_size;
- int ply_stopped;
- int ply_total;
-
- unsigned long cap_buffer;
- int cap_buf;
- int cap_count;
- int cap_size;
- int cap_stopped;
- int cap_total;
-
- struct parisc_device *pa_dev;
-
- struct snd_dma_device dma_dev;
-
- /* the graveyard buffer is used as recording buffer when playback,
- * because harmony always want a buffer to put recorded data */
- struct snd_dma_buffer graveyard_dma;
- int graveyard_count;
-
- /* same thing for silence buffer */
- struct snd_dma_buffer silence_dma;
- int silence_count;
-
- /* alsa stuff */
- snd_card_t *card;
- snd_pcm_t *pcm;
- snd_pcm_substream_t *playback_substream;
- snd_pcm_substream_t *capture_substream;
- snd_info_entry_t *proc_entry;
-} snd_card_harmony_t;
-
-static snd_card_t *snd_harmony_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
-
-/* wait to be out of control mode */
-static inline void snd_harmony_wait_cntl(snd_card_harmony_t *harmony)
-{
- int timeout = 5000;
+#include "harmony.h"
+
+static struct parisc_device_id snd_harmony_devtable[] = {
+ /* bushmaster / flounder */
+ { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0007A },
+ /* 712 / 715 */
+ { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0007B },
+ /* pace */
+ { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0007E },
+ /* outfield / coral II */
+ { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0007F },
+ { 0, }
+};
- while ( (gsc_readl(harmony->hpa+REG_CNTL) & HARMONY_CNTL_C) && --timeout)
- {
- /* Wait */ ;
- }
- if (timeout == 0) DPRINTK(KERN_DEBUG PFX "Error: wait cntl timeouted\n");
-}
+MODULE_DEVICE_TABLE(parisc, snd_harmony_devtable);
+#define NAME "harmony"
+#define PFX NAME ": "
-/*
- * sample rate routines
- */
-static unsigned int snd_card_harmony_rates[] = {
- 5125, 6615, 8000, 9600,
+static unsigned int snd_harmony_rates[] = {
+ 5512, 6615, 8000, 9600,
11025, 16000, 18900, 22050,
27428, 32000, 33075, 37800,
44100, 48000
};
-static snd_pcm_hw_constraint_list_t hw_constraint_rates = {
- .count = ARRAY_SIZE(snd_card_harmony_rates),
- .list = snd_card_harmony_rates,
- .mask = 0,
-};
-
-#define HARMONY_SR_8KHZ 0x08
-#define HARMONY_SR_16KHZ 0x09
-#define HARMONY_SR_27KHZ 0x0A
-#define HARMONY_SR_32KHZ 0x0B
-#define HARMONY_SR_48KHZ 0x0E
-#define HARMONY_SR_9KHZ 0x0F
-#define HARMONY_SR_5KHZ 0x10
-#define HARMONY_SR_11KHZ 0x11
-#define HARMONY_SR_18KHZ 0x12
-#define HARMONY_SR_22KHZ 0x13
-#define HARMONY_SR_37KHZ 0x14
-#define HARMONY_SR_44KHZ 0x15
-#define HARMONY_SR_33KHZ 0x16
-#define HARMONY_SR_6KHZ 0x17
-
-/* bits corresponding to the entries of snd_card_harmony_rates */
static unsigned int rate_bits[14] = {
HARMONY_SR_5KHZ, HARMONY_SR_6KHZ, HARMONY_SR_8KHZ,
HARMONY_SR_9KHZ, HARMONY_SR_11KHZ, HARMONY_SR_16KHZ,
@@ -267,642 +91,627 @@ static unsigned int rate_bits[14] = {
HARMONY_SR_44KHZ, HARMONY_SR_48KHZ
};
-/* snd_card_harmony_rate_bits
- * @rate: index of current data rate in list
- * returns: harmony hex code for registers
- */
-static unsigned int snd_card_harmony_rate_bits(int rate)
+static snd_pcm_hw_constraint_list_t 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)
{
- unsigned int idx;
-
- for (idx = 0; idx < ARRAY_SIZE(snd_card_harmony_rates); idx++)
- if (snd_card_harmony_rates[idx] == rate)
- return rate_bits[idx];
- return HARMONY_SR_44KHZ; /* fallback */
+ return __raw_readl(h->iobase + r);
}
-/*
- * update controls (data format, sample rate, number of channels)
- * according to value supplied in data structure
- */
-void snd_harmony_update_control(snd_card_harmony_t *harmony)
+inline void
+harmony_write(harmony_t *h, unsigned r, unsigned long v)
{
- u32 default_cntl;
-
- /* Set CNTL */
- default_cntl = (HARMONY_CNTL_C | /* The C bit */
- (harmony->data_format << 6) | /* Set the data format */
- (harmony->stereo_select << 5) | /* Stereo select */
- (harmony->sample_rate)); /* Set sample rate */
-
- /* initialize CNTL */
- snd_harmony_wait_cntl(harmony);
-
- gsc_writel(default_cntl, harmony->hpa+REG_CNTL);
-
+ __raw_writel(v, h->iobase + r);
}
-/*
- * interruption controls routines
- */
+static void
+harmony_wait_for_control(harmony_t *h)
+{
+ while (harmony_read(h, HARMONY_CNTL) & HARMONY_CNTL_C) ;
+}
-static void snd_harmony_disable_interrupts(snd_card_harmony_t *chip)
+inline void
+harmony_reset(harmony_t *h)
{
- snd_harmony_wait_cntl(chip);
- gsc_writel(0, chip->hpa+REG_DSTATUS);
+ harmony_write(h, HARMONY_RESET, 1);
+ mdelay(50);
+ harmony_write(h, HARMONY_RESET, 0);
}
-static void snd_harmony_enable_interrupts(snd_card_harmony_t *chip)
+static void
+harmony_disable_interrupts(harmony_t *h)
{
- snd_harmony_wait_cntl(chip);
- gsc_writel(HARMONY_DSTATUS_IE, chip->hpa+REG_DSTATUS);
+ u32 dstatus;
+ harmony_wait_for_control(h);
+ dstatus = harmony_read(h, HARMONY_DSTATUS);
+ dstatus &= ~HARMONY_DSTATUS_IE;
+ harmony_write(h, HARMONY_DSTATUS, dstatus);
}
-/*
- * interruption routine:
- * The interrupt routine must provide adresse of next physical pages
- * used by harmony
- */
-static int snd_card_harmony_interrupt(int irq, void *dev, struct pt_regs *regs)
+static void
+harmony_enable_interrupts(harmony_t *h)
{
- snd_card_harmony_t *harmony = (snd_card_harmony_t *)dev;
- u32 dstatus = 0;
- unsigned long hpa = harmony->hpa;
-
- /* Turn off interrupts */
- snd_harmony_disable_interrupts(harmony);
-
- /* wait for control to free */
- snd_harmony_wait_cntl(harmony);
-
- /* Read dstatus and pcuradd (the current address) */
- dstatus = gsc_readl(hpa+REG_DSTATUS);
-
- /* Check if this is a request to get the next play buffer */
+ u32 dstatus;
+ harmony_wait_for_control(h);
+ dstatus = harmony_read(h, HARMONY_DSTATUS);
+ dstatus |= HARMONY_DSTATUS_IE;
+ harmony_write(h, HARMONY_DSTATUS, dstatus);
+}
+
+static void
+harmony_mute(harmony_t *h)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&h->mixer_lock, flags);
+ harmony_wait_for_control(h);
+ harmony_write(h, HARMONY_GAINCTL, HARMONY_GAIN_SILENCE);
+ spin_unlock_irqrestore(&h->mixer_lock, flags);
+}
+
+static void
+harmony_unmute(harmony_t *h)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&h->mixer_lock, flags);
+ harmony_wait_for_control(h);
+ harmony_write(h, HARMONY_GAINCTL, h->st.gain);
+ spin_unlock_irqrestore(&h->mixer_lock, flags);
+}
+
+static void
+harmony_set_control(harmony_t *h)
+{
+ u32 ctrl;
+ unsigned long flags;
+
+ spin_lock_irqsave(&h->lock, flags);
+
+ ctrl = (HARMONY_CNTL_C |
+ (h->st.format << 6) |
+ (h->st.stereo << 5) |
+ (h->st.rate));
+
+ harmony_wait_for_control(h);
+ harmony_write(h, HARMONY_CNTL, ctrl);
+
+ spin_unlock_irqrestore(&h->lock, flags);
+}
+
+static irqreturn_t
+snd_harmony_interrupt(int irq, void *dev, struct pt_regs *regs)
+{
+ u32 dstatus;
+ harmony_t *h = dev;
+
+ spin_lock(&h->lock);
+ harmony_disable_interrupts(h);
+ harmony_wait_for_control(h);
+ dstatus = harmony_read(h, HARMONY_DSTATUS);
+ spin_unlock(&h->lock);
+
if (dstatus & HARMONY_DSTATUS_PN) {
- if (harmony->playback_substream) {
- harmony->ply_buf += harmony->ply_count;
- harmony->ply_buf %= harmony->ply_size;
-
- gsc_writel(harmony->ply_buffer + harmony->ply_buf,
- hpa+REG_PNXTADD);
-
- snd_pcm_period_elapsed(harmony->playback_substream);
- harmony->ply_total++;
+ if (h->psubs) {
+ spin_lock(&h->lock);
+ h->pbuf.buf += h->pbuf.count; /* PAGE_SIZE */
+ h->pbuf.buf %= h->pbuf.size; /* MAX_BUFS*PAGE_SIZE */
+
+ harmony_write(h, HARMONY_PNXTADD,
+ h->pbuf.addr + h->pbuf.buf);
+ h->stats.play_intr++;
+ spin_unlock(&h->lock);
+ snd_pcm_period_elapsed(h->psubs);
} else {
- gsc_writel(harmony->silence_dma.addr +
- (HARMONY_BUF_SIZE*harmony->silence_count),
- hpa+REG_PNXTADD);
- harmony->silence_count++;
- harmony->silence_count %= SILENCE_BUFS;
+ spin_lock(&h->lock);
+ harmony_write(h, HARMONY_PNXTADD, h->sdma.addr);
+ h->stats.silence_intr++;
+ spin_unlock(&h->lock);
}
}
-
- /* Check if we're being asked to fill in a recording buffer */
+
if (dstatus & HARMONY_DSTATUS_RN) {
- if (harmony->capture_substream) {
- harmony->cap_buf += harmony->cap_count;
- harmony->cap_buf %= harmony->cap_size;
-
- gsc_writel(harmony->cap_buffer + harmony->cap_buf,
- hpa+REG_RNXTADD);
-
- snd_pcm_period_elapsed(harmony->capture_substream);
- harmony->cap_total++;
+ if (h->csubs) {
+ spin_lock(&h->lock);
+ h->cbuf.buf += h->cbuf.count;
+ h->cbuf.buf %= h->cbuf.size;
+
+ harmony_write(h, HARMONY_RNXTADD,
+ h->cbuf.addr + h->cbuf.buf);
+ h->stats.rec_intr++;
+ spin_unlock(&h->lock);
+ snd_pcm_period_elapsed(h->csubs);
} else {
- /* graveyard buffer */
- gsc_writel(harmony->graveyard_dma.addr +
- (HARMONY_BUF_SIZE*harmony->graveyard_count),
- hpa+REG_RNXTADD);
- harmony->graveyard_count++;
- harmony->graveyard_count %= GRAVEYARD_BUFS;
+ spin_lock(&h->lock);
+ harmony_write(h, HARMONY_RNXTADD, h->gdma.addr);
+ h->stats.graveyard_intr++;
+ spin_unlock(&h->lock);
}
}
- snd_harmony_enable_interrupts(harmony);
+
+ spin_lock(&h->lock);
+ harmony_enable_interrupts(h);
+ spin_unlock(&h->lock);
return IRQ_HANDLED;
}
-/*
- * proc entry
- * this proc file will give some debugging info
- */
-
-static void snd_harmony_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
+static unsigned int
+snd_harmony_rate_bits(int rate)
{
- snd_card_harmony_t *harmony = (snd_card_harmony_t *)entry->private_data;
-
- snd_iprintf(buffer, "LASI Harmony driver\nLaurent Canet <canetl@esiee.fr>\n\n");
- snd_iprintf(buffer, "IRQ %d, hpa %lx, id %d rev %d\n",
- harmony->irq, harmony->hpa,
- harmony->id, harmony->rev);
- snd_iprintf(buffer, "Current gain %lx\n", (unsigned long) harmony->current_gain);
- snd_iprintf(buffer, "\tsample rate=%d\n", harmony->sample_rate);
- snd_iprintf(buffer, "\tstereo select=%d\n", harmony->stereo_select);
- snd_iprintf(buffer, "\tbitperchan=%d\n\n", harmony->data_format);
+ unsigned int i;
- snd_iprintf(buffer, "Play status:\n");
- snd_iprintf(buffer, "\tstopped %d\n", harmony->ply_stopped);
- snd_iprintf(buffer, "\tbuffer %lx, count %d\n", harmony->ply_buffer, harmony->ply_count);
- snd_iprintf(buffer, "\tbuf %d size %d\n\n", harmony->ply_buf, harmony->ply_size);
-
- snd_iprintf(buffer, "Capture status:\n");
- snd_iprintf(buffer, "\tstopped %d\n", harmony->cap_stopped);
- snd_iprintf(buffer, "\tbuffer %lx, count %d\n", harmony->cap_buffer, harmony->cap_count);
- snd_iprintf(buffer, "\tbuf %d, size %d\n\n", harmony->cap_buf, harmony->cap_size);
+ for (i = 0; i < ARRAY_SIZE(snd_harmony_rates); i++)
+ if (snd_harmony_rates[i] == rate)
+ return rate_bits[i];
- snd_iprintf(buffer, "Funny stats: total played=%d, recorded=%d\n\n", harmony->ply_total, harmony->cap_total);
-
- snd_iprintf(buffer, "Register:\n");
- snd_iprintf(buffer, "\tgainctl: %lx\n", (unsigned long) gsc_readl(harmony->hpa+REG_GAINCTL));
- snd_iprintf(buffer, "\tcntl: %lx\n", (unsigned long) gsc_readl(harmony->hpa+REG_CNTL));
- snd_iprintf(buffer, "\tid: %lx\n", (unsigned long) gsc_readl(harmony->hpa+REG_ID));
- snd_iprintf(buffer, "\tpcuradd: %lx\n", (unsigned long) gsc_readl(harmony->hpa+REG_PCURADD));
- snd_iprintf(buffer, "\trcuradd: %lx\n", (unsigned long) gsc_readl(harmony->hpa+REG_RCURADD));
- snd_iprintf(buffer, "\tpnxtadd: %lx\n", (unsigned long) gsc_readl(harmony->hpa+REG_PNXTADD));
- snd_iprintf(buffer, "\trnxtadd: %lx\n", (unsigned long) gsc_readl(harmony->hpa+REG_RNXTADD));
- snd_iprintf(buffer, "\tdstatus: %lx\n", (unsigned long) gsc_readl(harmony->hpa+REG_DSTATUS));
- snd_iprintf(buffer, "\tov: %lx\n\n", (unsigned long) gsc_readl(harmony->hpa+REG_OV));
-
+ return HARMONY_SR_44KHZ;
}
-static void __devinit snd_harmony_proc_init(snd_card_harmony_t *harmony)
+static snd_pcm_hardware_t snd_harmony_playback =
{
- snd_info_entry_t *entry;
-
- if (! snd_card_proc_new(harmony->card, "harmony", &entry))
- snd_info_set_text_ops(entry, harmony, 2048, snd_harmony_proc_read);
-}
+ .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_JOINT_DUPLEX | SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_BLOCK_TRANSFER),
+ .formats = (SNDRV_PCM_FMTBIT_S16_BE | SNDRV_PCM_FMTBIT_MU_LAW |
+ SNDRV_PCM_FMTBIT_A_LAW),
+ .rates = (SNDRV_PCM_RATE_5512 | SNDRV_PCM_RATE_8000_48000 |
+ SNDRV_PCM_RATE_KNOT),
+ .rate_min = 5512,
+ .rate_max = 48000,
+ .channels_min = 1,
+ .channels_max = 2,
+ .buffer_bytes_max = MAX_BUF_SIZE,
+ .period_bytes_min = BUF_SIZE,
+ .period_bytes_max = BUF_SIZE,
+ .periods_min = 1,
+ .periods_max = MAX_BUFS,
+ .fifo_size = 0,
+};
-/*
- * PCM Stuff
- */
+static snd_pcm_hardware_t snd_harmony_capture =
+{
+ .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_JOINT_DUPLEX | SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_BLOCK_TRANSFER),
+ .formats = (SNDRV_PCM_FMTBIT_S16_BE | SNDRV_PCM_FMTBIT_MU_LAW |
+ SNDRV_PCM_FMTBIT_A_LAW),
+ .rates = (SNDRV_PCM_RATE_5512 | SNDRV_PCM_RATE_8000_48000 |
+ SNDRV_PCM_RATE_KNOT),
+ .rate_min = 5512,
+ .rate_max = 48000,
+ .channels_min = 1,
+ .channels_max = 2,
+ .buffer_bytes_max = MAX_BUF_SIZE,
+ .period_bytes_min = BUF_SIZE,
+ .period_bytes_max = BUF_SIZE,
+ .periods_min = 1,
+ .periods_max = MAX_BUFS,
+ .fifo_size = 0,
+};
-static int snd_card_harmony_playback_ioctl(snd_pcm_substream_t * substream,
- unsigned int cmd,
- void *arg)
+static int
+snd_harmony_playback_trigger(snd_pcm_substream_t *ss, int cmd)
{
- return snd_pcm_lib_ioctl(substream, cmd, arg);
-}
+ harmony_t *h = snd_pcm_substream_chip(ss);
+ unsigned long flags;
-static int snd_card_harmony_capture_ioctl(snd_pcm_substream_t * substream,
- unsigned int cmd,
- void *arg)
-{
- return snd_pcm_lib_ioctl(substream, cmd, arg);
-}
+ if (h->st.capturing)
+ return -EBUSY;
-static int snd_card_harmony_playback_trigger(snd_pcm_substream_t * substream,
- int cmd)
-{
- snd_card_harmony_t *harmony = snd_pcm_substream_chip(substream);
-
+ spin_lock_irqsave(&h->lock, flags);
switch (cmd) {
- case SNDRV_PCM_TRIGGER_STOP:
- if (harmony->ply_stopped)
- return -EBUSY;
- harmony->ply_stopped = 1;
- snd_harmony_disable_interrupts(harmony);
- break;
- case SNDRV_PCM_TRIGGER_START:
- if (!harmony->ply_stopped)
- return -EBUSY;
- harmony->ply_stopped = 0;
- /* write the location of the first buffer to play */
- gsc_writel(harmony->ply_buffer, harmony->hpa+REG_PNXTADD);
- snd_harmony_enable_interrupts(harmony);
- break;
- case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- case SNDRV_PCM_TRIGGER_SUSPEND:
- DPRINTK(KERN_INFO PFX "received unimplemented trigger: %d\n", cmd);
- default:
- return -EINVAL;
+ case SNDRV_PCM_TRIGGER_START:
+ h->st.playing = 1;
+ harmony_write(h, HARMONY_PNXTADD, h->pbuf.addr);
+ harmony_write(h, HARMONY_RNXTADD, h->gdma.addr);
+ harmony_unmute(h);
+ harmony_enable_interrupts(h);
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ h->st.playing = 0;
+ harmony_mute(h);
+ harmony_disable_interrupts(h);
+ break;
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ default:
+ spin_unlock_irqrestore(&h->lock, flags);
+ snd_BUG();
+ return -EINVAL;
}
+ spin_unlock_irqrestore(&h->lock, flags);
+
return 0;
}
-static int snd_card_harmony_capture_trigger(snd_pcm_substream_t * substream,
- int cmd)
+static int
+snd_harmony_capture_trigger(snd_pcm_substream_t *ss, int cmd)
{
- snd_card_harmony_t *harmony = snd_pcm_substream_chip(substream);
-
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_STOP:
- if (harmony->cap_stopped)
- return -EBUSY;
- harmony->cap_stopped = 1;
- snd_harmony_disable_interrupts(harmony);
- break;
- case SNDRV_PCM_TRIGGER_START:
- if (!harmony->cap_stopped)
- return -EBUSY;
- harmony->cap_stopped = 0;
- snd_harmony_enable_interrupts(harmony);
- break;
- case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- case SNDRV_PCM_TRIGGER_SUSPEND:
- DPRINTK(KERN_INFO PFX "Received unimplemented trigger: %d\n", cmd);
- default:
- return -EINVAL;
- }
- return 0;
+ harmony_t *h = snd_pcm_substream_chip(ss);
+ unsigned long flags;
+
+ if (h->st.playing)
+ return -EBUSY;
+
+ spin_lock_irqsave(&h->lock, flags);
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ h->st.capturing = 1;
+ harmony_write(h, HARMONY_PNXTADD, h->sdma.addr);
+ harmony_write(h, HARMONY_RNXTADD, h->cbuf.addr);
+ harmony_unmute(h);
+ harmony_enable_interrupts(h);
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ h->st.capturing = 0;
+ harmony_mute(h);
+ harmony_disable_interrupts(h);
+ break;
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ default:
+ spin_unlock_irqrestore(&h->lock, flags);
+ snd_BUG();
+ return -EINVAL;
+ }
+ spin_unlock_irqrestore(&h->lock, flags);
+
+ return 0;
}
-/* set data format */
-static int snd_harmony_set_data_format(snd_card_harmony_t *harmony, int pcm_format)
+static int
+snd_harmony_set_data_format(harmony_t *h, int fmt, int force)
{
- int old_format = harmony->data_format;
- int new_format = old_format;
- switch (pcm_format) {
+ int o = h->st.format;
+ int n;
+
+ switch(fmt) {
case SNDRV_PCM_FORMAT_S16_BE:
- new_format = HARMONY_DF_16BIT_LINEAR;
+ n = HARMONY_DF_16BIT_LINEAR;
break;
case SNDRV_PCM_FORMAT_A_LAW:
- new_format = HARMONY_DF_8BIT_ALAW;
+ n = HARMONY_DF_8BIT_ALAW;
break;
case SNDRV_PCM_FORMAT_MU_LAW:
- new_format = HARMONY_DF_8BIT_ULAW;
+ n = HARMONY_DF_8BIT_ULAW;
break;
+ default:
+ n = HARMONY_DF_16BIT_LINEAR;
+ break;
+ }
+
+ if (force || o != n) {
+ snd_pcm_format_set_silence(fmt, h->sdma.area, SILENCE_BUFSZ /
+ (snd_pcm_format_physical_width(fmt)
+ / 8));
}
- /* re-initialize silence buffer if needed */
- if (old_format != new_format)
- snd_pcm_format_set_silence(pcm_format, harmony->silence_dma.area,
- (HARMONY_BUF_SIZE * SILENCE_BUFS * 8) / snd_pcm_format_width(pcm_format));
- return new_format;
+ return n;
}
-static int snd_card_harmony_playback_prepare(snd_pcm_substream_t * substream)
+static int
+snd_harmony_playback_prepare(snd_pcm_substream_t *ss)
{
- snd_card_harmony_t *harmony = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ harmony_t *h = snd_pcm_substream_chip(ss);
+ snd_pcm_runtime_t *rt = ss->runtime;
- harmony->ply_size = snd_pcm_lib_buffer_bytes(substream);
- harmony->ply_count = snd_pcm_lib_period_bytes(substream);
- harmony->ply_buf = 0;
- harmony->ply_stopped = 1;
+ if (h->st.capturing)
+ return -EBUSY;
- /* initialize given sample rate */
- harmony->sample_rate = snd_card_harmony_rate_bits(runtime->rate);
-
- /* data format */
- harmony->data_format = snd_harmony_set_data_format(harmony, runtime->format);
+ h->pbuf.size = snd_pcm_lib_buffer_bytes(ss);
+ h->pbuf.count = snd_pcm_lib_period_bytes(ss);
+ h->pbuf.buf = 0;
+ h->st.playing = 0;
- /* number of channels */
- if (runtime->channels == 2)
- harmony->stereo_select = HARMONY_SS_STEREO;
- else
- harmony->stereo_select = HARMONY_SS_MONO;
-
- DPRINTK(KERN_INFO PFX "Playback_prepare, sr=%d(%x), df=%x, ss=%x hpa=%lx\n", runtime->rate,
- harmony->sample_rate, harmony->data_format, harmony->stereo_select, harmony->hpa);
- snd_harmony_update_control(harmony);
- harmony->format_initialized = 1;
- harmony->ply_buffer = runtime->dma_addr;
+ h->st.rate = snd_harmony_rate_bits(rt->rate);
+ h->st.format = snd_harmony_set_data_format(h, rt->format, 0);
- return 0;
-}
+ if (rt->channels == 2)
+ h->st.stereo = HARMONY_SS_STEREO;
+ else
+ h->st.stereo = HARMONY_SS_MONO;
-static int snd_card_harmony_capture_prepare(snd_pcm_substream_t * substream)
-{
- snd_pcm_runtime_t *runtime = substream->runtime;
- snd_card_harmony_t *harmony = snd_pcm_substream_chip(substream);
-
- harmony->cap_size = snd_pcm_lib_buffer_bytes(substream);
- harmony->cap_count = snd_pcm_lib_period_bytes(substream);
- harmony->cap_count = 0;
- harmony->cap_stopped = 1;
+ harmony_set_control(h);
- /* initialize given sample rate */
- harmony->sample_rate = snd_card_harmony_rate_bits(runtime->rate);
-
- /* data format */
- harmony->data_format = snd_harmony_set_data_format(harmony, runtime->format);
-
- /* number of channels */
- if (runtime->channels == 1)
- harmony->stereo_select = HARMONY_SS_MONO;
- else if (runtime->channels == 2)
- harmony->stereo_select = HARMONY_SS_STEREO;
-
- snd_harmony_update_control(harmony);
- harmony->format_initialized = 1;
-
- harmony->cap_buffer = runtime->dma_addr;
+ h->pbuf.addr = rt->dma_addr;
return 0;
}
-static snd_pcm_uframes_t snd_card_harmony_capture_pointer(snd_pcm_substream_t * substream)
+static int
+snd_harmony_capture_prepare(snd_pcm_substream_t *ss)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
- snd_card_harmony_t *harmony = snd_pcm_substream_chip(substream);
- unsigned long rcuradd;
- int recorded;
-
- if (harmony->cap_stopped) return 0;
- if (harmony->capture_substream == NULL) return 0;
+ harmony_t *h = snd_pcm_substream_chip(ss);
+ snd_pcm_runtime_t *rt = ss->runtime;
- rcuradd = gsc_readl(harmony->hpa+REG_RCURADD);
- recorded = (rcuradd - harmony->cap_buffer);
- recorded %= harmony->cap_size;
-
- return bytes_to_frames(runtime, recorded);
-}
+ if (h->st.playing)
+ return -EBUSY;
-/*
- */
+ h->cbuf.size = snd_pcm_lib_buffer_bytes(ss);
+ h->cbuf.count = snd_pcm_lib_period_bytes(ss);
+ h->cbuf.buf = 0;
+ h->st.capturing = 0;
+
+ h->st.rate = snd_harmony_rate_bits(rt->rate);
+ h->st.format = snd_harmony_set_data_format(h, rt->format, 0);
+
+ if (rt->channels == 2)
+ h->st.stereo = HARMONY_SS_STEREO;
+ else
+ h->st.stereo = HARMONY_SS_MONO;
+
+ harmony_set_control(h);
-static snd_pcm_uframes_t snd_card_harmony_playback_pointer(snd_pcm_substream_t * substream)
+ h->cbuf.addr = rt->dma_addr;
+
+ return 0;
+}
+
+static snd_pcm_uframes_t
+snd_harmony_playback_pointer(snd_pcm_substream_t *ss)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
- snd_card_harmony_t *harmony = snd_pcm_substream_chip(substream);
- int played;
- long int pcuradd = gsc_readl(harmony->hpa+REG_PCURADD);
-
- if ((harmony->ply_stopped) || (harmony->playback_substream == NULL)) return 0;
- if ((harmony->ply_buffer == 0) || (harmony->ply_size == 0)) return 0;
-
- played = (pcuradd - harmony->ply_buffer);
-
- printk(KERN_DEBUG PFX "Pointer is %lx-%lx = %d\n", pcuradd, harmony->ply_buffer, played);
+ snd_pcm_runtime_t *rt = ss->runtime;
+ harmony_t *h = snd_pcm_substream_chip(ss);
+ unsigned long pcuradd;
+ unsigned long played;
+
+ if (!(h->st.playing) || (h->psubs == NULL))
+ return 0;
- if (pcuradd > harmony->ply_buffer + harmony->ply_size) return 0;
+ if ((h->pbuf.addr == 0) || (h->pbuf.size == 0))
+ return 0;
- return bytes_to_frames(runtime, played);
+ pcuradd = harmony_read(h, HARMONY_PCURADD);
+ played = pcuradd - h->pbuf.addr;
+
+#ifdef HARMONY_DEBUG
+ printk(KERN_DEBUG PFX "playback_pointer is 0x%lx-0x%lx = %d bytes\n",
+ pcuradd, h->pbuf.addr, played);
+#endif
+
+ if (pcuradd > h->pbuf.addr + h->pbuf.size) {
+ return 0;
+ }
+
+ return bytes_to_frames(rt, played);
}
-static snd_pcm_hardware_t snd_card_harmony_playback =
+static snd_pcm_uframes_t
+snd_harmony_capture_pointer(snd_pcm_substream_t *ss)
{
- .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
- SNDRV_PCM_INFO_JOINT_DUPLEX |
- SNDRV_PCM_INFO_MMAP_VALID |
- SNDRV_PCM_INFO_BLOCK_TRANSFER),
- .formats = (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_BE |
- SNDRV_PCM_FMTBIT_A_LAW | SNDRV_PCM_FMTBIT_MU_LAW),
- .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
- .rate_min = 5500,
- .rate_max = 48000,
- .channels_min = 1,
- .channels_max = 2,
- .buffer_bytes_max = MAX_BUFFER_SIZE,
- .period_bytes_min = HARMONY_BUF_SIZE,
- .period_bytes_max = HARMONY_BUF_SIZE,
- .periods_min = 1,
- .periods_max = MAX_BUFS,
- .fifo_size = 0,
-};
+ snd_pcm_runtime_t *rt = ss->runtime;
+ harmony_t *h = snd_pcm_substream_chip(ss);
+ unsigned long rcuradd;
+ unsigned long caught;
-static snd_pcm_hardware_t snd_card_harmony_capture =
-{
- .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
- SNDRV_PCM_INFO_JOINT_DUPLEX |
- SNDRV_PCM_INFO_MMAP_VALID |
- SNDRV_PCM_INFO_BLOCK_TRANSFER),
- .formats = (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_BE |
- SNDRV_PCM_FMTBIT_A_LAW | SNDRV_PCM_FMTBIT_MU_LAW),
- .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
- .rate_min = 5500,
- .rate_max = 48000,
- .channels_min = 1,
- .channels_max = 2,
- .buffer_bytes_max = MAX_BUFFER_SIZE,
- .period_bytes_min = HARMONY_BUF_SIZE,
- .period_bytes_max = HARMONY_BUF_SIZE,
- .periods_min = 1,
- .periods_max = MAX_BUFS,
- .fifo_size = 0,
-};
+ if (!(h->st.capturing) || (h->csubs == NULL))
+ return 0;
-static int snd_card_harmony_playback_open(snd_pcm_substream_t * substream)
+ if ((h->cbuf.addr == 0) || (h->cbuf.size == 0))
+ return 0;
+
+ rcuradd = harmony_read(h, HARMONY_RCURADD);
+ caught = rcuradd - h->cbuf.addr;
+
+#ifdef HARMONY_DEBUG
+ printk(KERN_DEBUG PFX "capture_pointer is 0x%lx-0x%lx = %d bytes\n",
+ rcuradd, h->cbuf.addr, caught);
+#endif
+
+ if (rcuradd > h->cbuf.addr + h->cbuf.size) {
+ return 0;
+ }
+
+ return bytes_to_frames(rt, caught);
+}
+
+static int
+snd_harmony_playback_open(snd_pcm_substream_t *ss)
{
- snd_card_harmony_t *harmony = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ harmony_t *h = snd_pcm_substream_chip(ss);
+ snd_pcm_runtime_t *rt = ss->runtime;
int err;
- harmony->playback_substream = substream;
- runtime->hw = snd_card_harmony_playback;
- snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraint_rates);
+ h->psubs = ss;
+ rt->hw = snd_harmony_playback;
+ snd_pcm_hw_constraint_list(rt, 0, SNDRV_PCM_HW_PARAM_RATE,
+ &hw_constraint_rates);
- if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
+ err = snd_pcm_hw_constraint_integer(rt, SNDRV_PCM_HW_PARAM_PERIODS);
+ if (err < 0)
return err;
return 0;
}
-static int snd_card_harmony_capture_open(snd_pcm_substream_t * substream)
+static int
+snd_harmony_capture_open(snd_pcm_substream_t *ss)
{
- snd_card_harmony_t *harmony = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- int err;
-
- harmony->capture_substream = substream;
- runtime->hw = snd_card_harmony_capture;
- snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraint_rates);
- if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
- return err;
- return 0;
+ harmony_t *h = snd_pcm_substream_chip(ss);
+ snd_pcm_runtime_t *rt = ss->runtime;
+ int err;
+
+ h->csubs = ss;
+ rt->hw = snd_harmony_capture;
+ snd_pcm_hw_constraint_list(rt, 0, SNDRV_PCM_HW_PARAM_RATE,
+ &hw_constraint_rates);
+
+ err = snd_pcm_hw_constraint_integer(rt, SNDRV_PCM_HW_PARAM_PERIODS);
+ if (err < 0)
+ return err;
+ return 0;
}
-static int snd_card_harmony_playback_close(snd_pcm_substream_t * substream)
+static int
+snd_harmony_playback_close(snd_pcm_substream_t *ss)
{
- snd_card_harmony_t *harmony = snd_pcm_substream_chip(substream);
-
- harmony->playback_substream = NULL;
- harmony->ply_size = 0;
- harmony->ply_buf = 0;
- harmony->ply_buffer = 0;
- harmony->ply_count = 0;
- harmony->ply_stopped = 1;
- harmony->format_initialized = 0;
-
+ harmony_t *h = snd_pcm_substream_chip(ss);
+ h->psubs = NULL;
return 0;
}
-static int snd_card_harmony_capture_close(snd_pcm_substream_t * substream)
+static int
+snd_harmony_capture_close(snd_pcm_substream_t *ss)
{
- snd_card_harmony_t *harmony = snd_pcm_substream_chip(substream);
-
- harmony->capture_substream = NULL;
- harmony->cap_size = 0;
- harmony->cap_buf = 0;
- harmony->cap_buffer = 0;
- harmony->cap_count = 0;
- harmony->cap_stopped = 1;
- harmony->format_initialized = 0;
-
- return 0;
+ harmony_t *h = snd_pcm_substream_chip(ss);
+ h->csubs = NULL;
+ return 0;
}
-static int snd_card_harmony_hw_params(snd_pcm_substream_t *substream,
- snd_pcm_hw_params_t * hw_params)
+static int
+snd_harmony_hw_params(snd_pcm_substream_t *ss,
+ snd_pcm_hw_params_t *hw)
{
int err;
- snd_card_harmony_t *harmony = snd_pcm_substream_chip(substream);
+ harmony_t *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)
+ ss->runtime->dma_addr = __pa(ss->runtime->dma_area);
- err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
- if (err > 0 && harmony->dma_dev.type == SNDRV_DMA_TYPE_CONTINUOUS)
- substream->runtime->dma_addr = __pa(substream->runtime->dma_area);
- DPRINTK(KERN_INFO PFX "HW Params returned %d, dma_addr %lx\n", err,
- (unsigned long)substream->runtime->dma_addr);
return err;
}
-static int snd_card_harmony_hw_free(snd_pcm_substream_t *substream)
+static int
+snd_harmony_hw_free(snd_pcm_substream_t *ss)
{
- snd_pcm_lib_free_pages(substream);
- return 0;
+ return snd_pcm_lib_free_pages(ss);
}
-static snd_pcm_ops_t snd_card_harmony_playback_ops = {
- .open = snd_card_harmony_playback_open,
- .close = snd_card_harmony_playback_close,
- .ioctl = snd_card_harmony_playback_ioctl,
- .hw_params = snd_card_harmony_hw_params,
- .hw_free = snd_card_harmony_hw_free,
- .prepare = snd_card_harmony_playback_prepare,
- .trigger = snd_card_harmony_playback_trigger,
- .pointer = snd_card_harmony_playback_pointer,
+static snd_pcm_ops_t snd_harmony_playback_ops = {
+ .open = snd_harmony_playback_open,
+ .close = snd_harmony_playback_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = snd_harmony_hw_params,
+ .hw_free = snd_harmony_hw_free,
+ .prepare = snd_harmony_playback_prepare,
+ .trigger = snd_harmony_playback_trigger,
+ .pointer = snd_harmony_playback_pointer,
};
-static snd_pcm_ops_t snd_card_harmony_capture_ops = {
- .open = snd_card_harmony_capture_open,
- .close = snd_card_harmony_capture_close,
- .ioctl = snd_card_harmony_capture_ioctl,
- .hw_params = snd_card_harmony_hw_params,
- .hw_free = snd_card_harmony_hw_free,
- .prepare = snd_card_harmony_capture_prepare,
- .trigger = snd_card_harmony_capture_trigger,
- .pointer = snd_card_harmony_capture_pointer,
+static snd_pcm_ops_t snd_harmony_capture_ops = {
+ .open = snd_harmony_capture_open,
+ .close = snd_harmony_capture_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = snd_harmony_hw_params,
+ .hw_free = snd_harmony_hw_free,
+ .prepare = snd_harmony_capture_prepare,
+ .trigger = snd_harmony_capture_trigger,
+ .pointer = snd_harmony_capture_pointer,
};
-static int snd_card_harmony_pcm_init(snd_card_harmony_t *harmony)
+static int
+snd_harmony_pcm_init(harmony_t *h)
{
snd_pcm_t *pcm;
int err;
- /* Request that IRQ */
- if (request_irq(harmony->irq, snd_card_harmony_interrupt, 0 ,"harmony", harmony)) {
- printk(KERN_ERR PFX "Error requesting irq %d.\n", harmony->irq);
- return -EFAULT;
- }
+ harmony_disable_interrupts(h);
- snd_harmony_disable_interrupts(harmony);
-
- if ((err = snd_pcm_new(harmony->card, "Harmony", 0, 1, 1, &pcm)) < 0)
+ err = snd_pcm_new(h->card, "harmony", 0, 1, 1, &pcm);
+ if (err < 0)
return err;
- snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_card_harmony_playback_ops);
- snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_card_harmony_capture_ops);
-
- pcm->private_data = harmony;
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
+ &snd_harmony_playback_ops);
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
+ &snd_harmony_capture_ops);
+
+ pcm->private_data = h;
pcm->info_flags = 0;
- strcpy(pcm->name, "Harmony");
- harmony->pcm = pcm;
+ strcpy(pcm->name, "harmony");
+ h->pcm = pcm;
+
+ h->psubs = NULL;
+ h->csubs = NULL;
/* initialize graveyard buffer */
- harmony->dma_dev.type = SNDRV_DMA_TYPE_DEV;
- harmony->dma_dev.dev = &harmony->pa_dev->dev;
- err = snd_dma_alloc_pages(harmony->dma_dev.type,
- harmony->dma_dev.dev,
- HARMONY_BUF_SIZE*GRAVEYARD_BUFS,
- &harmony->graveyard_dma);
- if (err == -ENOMEM) {
- /* use continuous buffers */
- harmony->dma_dev.type = SNDRV_DMA_TYPE_CONTINUOUS;
- harmony->dma_dev.dev = snd_dma_continuous_data(GFP_KERNEL);
- err = snd_dma_alloc_pages(harmony->dma_dev.type,
- harmony->dma_dev.dev,
- HARMONY_BUF_SIZE*GRAVEYARD_BUFS,
- &harmony->graveyard_dma);
- }
+ h->dma.type = SNDRV_DMA_TYPE_DEV;
+ h->dma.dev = &h->dev->dev;
+ err = snd_dma_alloc_pages(h->dma.type,
+ h->dma.dev,
+ BUF_SIZE*GRAVEYARD_BUFS,
+ &h->gdma);
if (err < 0) {
- printk(KERN_ERR PFX "can't allocate graveyard buffer\n");
+ printk(KERN_ERR PFX "cannot allocate graveyard buffer!\n");
return err;
}
- harmony->graveyard_count = 0;
/* initialize silence buffers */
- err = snd_dma_alloc_pages(harmony->dma_dev.type,
- harmony->dma_dev.dev,
- HARMONY_BUF_SIZE*SILENCE_BUFS,
- &harmony->silence_dma);
+ err = snd_dma_alloc_pages(h->dma.type,
+ h->dma.dev,
+ BUF_SIZE*SILENCE_BUFS,
+ &h->sdma);
if (err < 0) {
- printk(KERN_ERR PFX "can't allocate silence buffer\n");
+ printk(KERN_ERR PFX "cannot allocate silence buffer!\n");
return err;
}
- harmony->silence_count = 0;
-
- if (harmony->dma_dev.type == SNDRV_DMA_TYPE_CONTINUOUS) {
- harmony->graveyard_dma.addr = __pa(harmony->graveyard_dma.area);
- harmony->silence_dma.addr = __pa(harmony->silence_dma.area);
- }
- harmony->ply_stopped = harmony->cap_stopped = 1;
-
- harmony->playback_substream = NULL;
- harmony->capture_substream = NULL;
- harmony->graveyard_count = 0;
-
- err = snd_pcm_lib_preallocate_pages_for_all(pcm, harmony->dma_dev.type,
- harmony->dma_dev.dev,
- MAX_BUFFER_SIZE, MAX_BUFFER_SIZE);
+ /* pre-allocate space for DMA */
+ err = snd_pcm_lib_preallocate_pages_for_all(pcm, h->dma.type,
+ h->dma.dev,
+ MAX_BUF_SIZE,
+ MAX_BUF_SIZE);
if (err < 0) {
- printk(KERN_ERR PFX "buffer allocation error %d\n", err);
- // return err;
+ printk(KERN_ERR PFX "buffer allocation error: %d\n", err);
+ return err;
}
+ h->st.format = snd_harmony_set_data_format(h,
+ SNDRV_PCM_FORMAT_S16_BE, 1);
+
return 0;
}
-/*
- * mixer routines
- */
-
-static void snd_harmony_set_new_gain(snd_card_harmony_t *harmony)
+static void
+snd_harmony_set_new_gain(harmony_t *h)
{
- DPRINTK(KERN_INFO PFX "Setting new gain %x at %lx\n", harmony->current_gain, harmony->hpa+REG_GAINCTL);
- /* Wait until we're out of control mode */
- snd_harmony_wait_cntl(harmony);
-
- gsc_writel(harmony->current_gain, harmony->hpa+REG_GAINCTL);
+ harmony_wait_for_control(h);
+ harmony_write(h, HARMONY_GAINCTL, h->st.gain);
}
-#define HARMONY_VOLUME(xname, left_shift, right_shift, mask, invert) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
- .info = snd_harmony_mixercontrol_info, \
- .get = snd_harmony_volume_get, .put = snd_harmony_volume_put, \
- .private_value = ((left_shift) | ((right_shift) << 8) | ((mask) << 16) | ((invert) << 24)) }
-
-static int snd_harmony_mixercontrol_info(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo)
+static int
+snd_harmony_mixercontrol_info(snd_kcontrol_t *kc,
+ snd_ctl_elem_info_t *uinfo)
{
- int mask = (kcontrol->private_value >> 16) & 0xff;
- int left_shift = (kcontrol->private_value) & 0xff;
- int right_shift = (kcontrol->private_value >> 8) & 0xff;
+ int mask = (kc->private_value >> 16) & 0xff;
+ int left_shift = (kc->private_value) & 0xff;
+ int right_shift = (kc->private_value >> 8) & 0xff;
- uinfo->type = (mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER);
- uinfo->count = (left_shift == right_shift) ? 1 : 2;
+ uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN :
+ SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = left_shift == right_shift ? 1 : 2;
uinfo->value.integer.min = 0;
uinfo->value.integer.max = mask;
+
return 0;
}
-
-static int snd_harmony_volume_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+
+static int
+snd_harmony_volume_get(snd_kcontrol_t *kc,
+ snd_ctl_elem_value_t *ucontrol)
{
- snd_card_harmony_t *harmony = snd_kcontrol_chip(kcontrol);
- int shift_left = (kcontrol->private_value) & 0xff;
- int shift_right = (kcontrol->private_value >> 8) & 0xff;
- int mask = (kcontrol->private_value >> 16) & 0xff;
- int invert = (kcontrol->private_value >> 24) & 0xff;
- unsigned long flags;
+ harmony_t *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(&harmony->mixer_lock, flags);
- left = (harmony->current_gain >> shift_left) & mask;
- right = (harmony->current_gain >> shift_right) & mask;
+ spin_lock_irqsave(&h->mixer_lock, flags);
+
+ left = (h->st.gain >> shift_left) & mask;
+ right = (h->st.gain >> shift_right) & mask;
if (invert) {
left = mask - left;
@@ -910,21 +719,24 @@ static int snd_harmony_volume_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_
}
ucontrol->value.integer.value[0] = left;
ucontrol->value.integer.value[1] = right;
- spin_unlock_irqrestore(&harmony->mixer_lock, flags);
+
+ spin_unlock_irqrestore(&h->mixer_lock, flags);
return 0;
}
-static int snd_harmony_volume_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int
+snd_harmony_volume_put(snd_kcontrol_t *kc,
+ snd_ctl_elem_value_t *ucontrol)
{
- snd_card_harmony_t *harmony = snd_kcontrol_chip(kcontrol);
- int shift_left = (kcontrol->private_value) & 0xff;
- int shift_right = (kcontrol->private_value >> 8) & 0xff;
- int mask = (kcontrol->private_value >> 16) & 0xff;
- int invert = (kcontrol->private_value >> 24) & 0xff;
- unsigned long flags;
+ harmony_t *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 = harmony->current_gain;
+ int old_gain = h->st.gain;
+ unsigned long flags;
left = ucontrol->value.integer.value[0] & mask;
right = ucontrol->value.integer.value[1] & mask;
@@ -933,213 +745,249 @@ static int snd_harmony_volume_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_
right = mask - right;
}
- spin_lock_irqsave(&harmony->mixer_lock, flags);
- harmony->current_gain = harmony->current_gain & ~( (mask << shift_right) | (mask << shift_left));
- harmony->current_gain = harmony->current_gain | ((left << shift_left) | (right << shift_right) );
- snd_harmony_set_new_gain(harmony);
- spin_unlock_irqrestore(&harmony->mixer_lock, flags);
+ spin_lock_irqsave(&h->mixer_lock, flags);
+
+ h->st.gain &= ~( (mask << shift_right) | (mask << shift_left) );
+ h->st.gain |= ( (left << shift_left) | (right << shift_right) );
+ snd_harmony_set_new_gain(h);
+
+ spin_unlock_irqrestore(&h->mixer_lock, flags);
- return (old_gain - harmony->current_gain);
+ return (old_gain - h->st.gain);
}
-#define HARMONY_CONTROLS (sizeof(snd_harmony_controls)/sizeof(snd_kcontrol_new_t))
+#define HARMONY_CONTROLS (sizeof(snd_harmony_controls)/ \
+ sizeof(snd_kcontrol_new_t))
+
+#define HARMONY_VOLUME(xname, left_shift, right_shift, mask, invert) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
+ .info = snd_harmony_mixercontrol_info, \
+ .get = snd_harmony_volume_get, .put = snd_harmony_volume_put, \
+ .private_value = ((left_shift) | ((right_shift) << 8) | \
+ ((mask) << 16) | ((invert) << 24)) }
static snd_kcontrol_new_t snd_harmony_controls[] = {
-HARMONY_VOLUME("PCM Capture Volume", 12, 16, 0x0f, 0),
-HARMONY_VOLUME("Master Volume", 20, 20, 0x0f, 1),
-HARMONY_VOLUME("PCM Playback Volume", 6, 0, 0x3f, 1),
+ HARMONY_VOLUME("Playback Volume", HARMONY_GAIN_LO_SHIFT,
+ HARMONY_GAIN_RO_SHIFT, HARMONY_GAIN_OUT, 1),
+ HARMONY_VOLUME("Capture Volume", HARMONY_GAIN_LI_SHIFT,
+ HARMONY_GAIN_RI_SHIFT, HARMONY_GAIN_IN, 0),
};
-static void __init snd_harmony_reset_codec(snd_card_harmony_t *harmony)
+static void __init
+snd_harmony_mixer_reset(harmony_t *h)
{
- snd_harmony_wait_cntl(harmony);
- gsc_writel(1, harmony->hpa+REG_RESET);
- mdelay(50); /* wait 50 ms */
- gsc_writel(0, harmony->hpa+REG_RESET);
+ harmony_mute(h);
+ harmony_reset(h);
+ h->st.gain = HARMONY_GAIN_DEFAULT;
+ harmony_unmute(h);
}
-/*
- * Mute all the output and reset Harmony.
- */
-
-static void __init snd_harmony_mixer_reset(snd_card_harmony_t *harmony)
+static int __init
+snd_harmony_mixer_init(harmony_t *h)
{
- harmony->current_gain = HARMONY_GAIN_TOTAL_SILENCE;
- snd_harmony_set_new_gain(harmony);
- snd_harmony_reset_codec(harmony);
- harmony->current_gain = HARMONY_GAIN_DEFAULT;
- snd_harmony_set_new_gain(harmony);
-}
-
-
-static int __init snd_card_harmony_mixer_init(snd_card_harmony_t *harmony)
-{
- snd_card_t *card = harmony->card;
+ snd_card_t *card = h->card;
int idx, err;
- snd_assert(harmony != NULL, return -EINVAL);
+ snd_assert(h != NULL, return -EINVAL);
strcpy(card->mixername, "Harmony Gain control interface");
for (idx = 0; idx < HARMONY_CONTROLS; idx++) {
- if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_harmony_controls[idx], harmony))) < 0)
+ err = snd_ctl_add(card,
+ snd_ctl_new1(&snd_harmony_controls[idx], h));
+ if (err < 0)
return err;
}
- snd_harmony_mixer_reset(harmony);
+ snd_harmony_mixer_reset(h);
return 0;
}
-static int snd_card_harmony_create(snd_card_t *card, struct parisc_device *pa_dev, snd_card_harmony_t *harmony)
+static int
+snd_harmony_free(harmony_t *h)
{
- u32 cntl;
-
- harmony->card = card;
-
- harmony->pa_dev = pa_dev;
+ if (h->gdma.addr)
+ snd_dma_free_pages(&h->gdma);
+ if (h->sdma.addr)
+ snd_dma_free_pages(&h->sdma);
- /* Set the HPA of harmony */
- harmony->hpa = pa_dev->hpa;
-
- harmony->irq = pa_dev->irq;
- if (!harmony->irq) {
- printk(KERN_ERR PFX "no irq found\n");
- return -ENODEV;
- }
+ if (h->irq >= 0)
+ free_irq(h->irq, h);
- /* Grab the ID and revision from the device */
- harmony->id = (gsc_readl(harmony->hpa+REG_ID)&0x00ff0000) >> 16;
- if ((harmony->id | 1) != 0x15) {
- printk(KERN_WARNING PFX "wrong harmony id 0x%02x\n", harmony->id);
- return -EBUSY;
- }
- cntl = gsc_readl(harmony->hpa+REG_CNTL);
- harmony->rev = (cntl>>20) & 0xff;
+ if (h->iobase)
+ iounmap(h->iobase);
- printk(KERN_INFO "Lasi Harmony Audio driver h/w id %i, rev. %i at 0x%lx, IRQ %i\n", harmony->id, harmony->rev, pa_dev->hpa, harmony->irq);
-
- /* Make sure the control bit isn't set, although I don't think it
- ever is. */
- if (cntl & HARMONY_CNTL_C) {
- printk(KERN_WARNING PFX "CNTL busy\n");
- harmony->hpa = 0;
- return -EBUSY;
+ parisc_set_drvdata(h->dev, NULL);
+
+ kfree(h);
+ return 0;
+}
+
+static int
+snd_harmony_dev_free(snd_device_t *dev)
+{
+ harmony_t *h = dev->device_data;
+ return snd_harmony_free(h);
+}
+
+static int __devinit
+snd_harmony_create(snd_card_t *card,
+ struct parisc_device *padev,
+ harmony_t **rchip)
+{
+ int err;
+ harmony_t *h;
+ static snd_device_ops_t ops = {
+ .dev_free = snd_harmony_dev_free,
+ };
+
+ *rchip = NULL;
+
+ h = kmalloc(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;
+ h->card = card;
+ h->dev = padev;
+ h->irq = padev->irq;
+ h->iobase = ioremap_nocache(padev->hpa, HARMONY_SIZE);
+ if (h->iobase == NULL) {
+ printk(KERN_ERR PFX "unable to remap hpa 0x%lx\n",
+ padev->hpa);
+ err = -EBUSY;
+ goto free_and_ret;
}
-
+
+ err = request_irq(h->irq, snd_harmony_interrupt, 0,
+ "harmony", h);
+ if (err) {
+ printk(KERN_ERR PFX "could not obtain interrupt %d",
+ h->irq);
+ goto free_and_ret;
+ }
+
+ spin_lock_init(&h->mixer_lock);
+ spin_lock_init(&h->lock);
+
+ if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL,
+ h, &ops)) < 0) {
+ goto free_and_ret;
+ }
+
+ *rchip = h;
+
return 0;
+
+free_and_ret:
+ snd_harmony_free(h);
+ return err;
}
-
-static int __init snd_card_harmony_probe(struct parisc_device *pa_dev)
+
+static int __devinit
+snd_harmony_probe(struct parisc_device *padev)
{
+ int err;
static int dev;
- snd_card_harmony_t *chip;
snd_card_t *card;
- int err;
-
- if (dev >= SNDRV_CARDS)
+ 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;
- if (!enable[dev]) {
- dev++;
- return -ENOENT;
}
-
- snd_harmony_cards[dev] = snd_card_new(index[dev], id[dev], THIS_MODULE,
- sizeof(snd_card_harmony_t));
- card = snd_harmony_cards[dev];
-
+
+ card = snd_card_new(index, id, THIS_MODULE, 0);
if (card == NULL)
return -ENOMEM;
- chip = (struct snd_card_harmony *)card->private_data;
- spin_lock_init(&chip->control_lock);
- spin_lock_init(&chip->mixer_lock);
-
- if ((err = snd_card_harmony_create(card, pa_dev, chip)) < 0) {
- printk(KERN_ERR PFX "Creation failed\n");
- snd_card_free(card);
- return err;
+
+ err = snd_harmony_create(card, padev, &h);
+ if (err < 0) {
+ goto free_and_ret;
}
- if ((err = snd_card_harmony_pcm_init(chip)) < 0) {
- printk(KERN_ERR PFX "PCM Init failed\n");
- snd_card_free(card);
- return err;
+
+ err = snd_harmony_pcm_init(h);
+ if (err < 0) {
+ goto free_and_ret;
}
- if ((err = snd_card_harmony_mixer_init(chip)) < 0) {
- printk(KERN_ERR PFX "Mixer init failed\n");
- snd_card_free(card);
- return err;
+
+ err = snd_harmony_mixer_init(h);
+ if (err < 0) {
+ goto free_and_ret;
}
-
- snd_harmony_proc_init(chip);
-
- strcpy(card->driver, "Harmony");
- strcpy(card->shortname, "ALSA driver for LASI Harmony");
- sprintf(card->longname, "%s at h/w, id %i, rev. %i hpa 0x%lx, IRQ %i\n",card->shortname, chip->id, chip->rev, pa_dev->hpa, chip->irq);
- if ((err = snd_card_register(card)) < 0) {
- snd_card_free(card);
- return err;
+ strcpy(card->driver, "harmony");
+ strcpy(card->shortname, "Harmony");
+ sprintf(card->longname, "%s at 0x%lx, irq %i",
+ card->shortname, h->hpa, h->irq);
+
+ err = snd_card_register(card);
+ if (err < 0) {
+ goto free_and_ret;
}
- printk(KERN_DEBUG PFX "Successfully registered harmony pcm backend & mixer %d\n", dev);
dev++;
- return 0;
-}
+ parisc_set_drvdata(padev, h);
-static struct parisc_device_id snd_card_harmony_devicetbl[] = {
- { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0007A }, /* Bushmaster/Flounder */
- { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0007B }, /* 712/715 Audio */
- { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0007E }, /* Pace Audio */
- { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0007F }, /* Outfield / Coral II */
- { 0, }
-};
+ return 0;
-MODULE_DEVICE_TABLE(parisc, snd_card_harmony_devicetbl);
+free_and_ret:
+ snd_card_free(card);
+ return err;
+}
-/*
- * bloc device parisc. c'est une structure qui definit un device
- * que l'on trouve sur parisc.
- * On y trouve les differents numeros HVERSION correspondant au device
- * en question (ce qui permet a l'inventory de l'identifier) et la fonction
- * d'initialisation du chose
- */
+static int __devexit
+snd_harmony_remove(struct parisc_device *padev)
+{
+ harmony_t *h = parisc_get_drvdata(padev);
+ snd_card_free(h->card);
+ return 0;
+}
-static struct parisc_driver snd_card_harmony_driver = {
- .name = "Lasi ALSA Harmony",
- .id_table = snd_card_harmony_devicetbl,
- .probe = snd_card_harmony_probe,
+static struct parisc_driver snd_harmony_driver = {
+ .name = "harmony",
+ .id_table = snd_harmony_devtable,
+ .probe = snd_harmony_probe,
+ .remove = snd_harmony_remove,
};
-static int __init alsa_card_harmony_init(void)
+static int __init
+alsa_harmony_init(void)
{
int err;
-
- if ((err = register_parisc_driver(&snd_card_harmony_driver)) < 0) {
- printk(KERN_ERR "Harmony soundcard not found or device busy\n");
+
+ err = register_parisc_driver(&snd_harmony_driver);
+ if (err < 0) {
+ printk(KERN_ERR PFX "device not found\n");
return err;
}
return 0;
}
-static void __exit alsa_card_harmony_exit(void)
+static void __exit
+alsa_harmony_fini(void)
{
- int idx;
- snd_card_harmony_t *harmony;
+ int err;
+
+ err = unregister_parisc_driver(&snd_harmony_driver);
+ if (err < 0) {
+ printk(KERN_ERR PFX "failed to unregister\n");
+ }
- for (idx = 0; idx < SNDRV_CARDS; idx++)
- {
- if (snd_harmony_cards[idx] != NULL)
- {
- DPRINTK(KERN_INFO PFX "Freeing card %d\n", idx);
- harmony = snd_harmony_cards[idx]->private_data;
- free_irq(harmony->irq, harmony);
- printk(KERN_INFO PFX "Card unloaded %d, irq=%d\n", idx, harmony->irq);
- snd_card_free(snd_harmony_cards[idx]);
- }
- }
- if (unregister_parisc_driver(&snd_card_harmony_driver) < 0)
- printk(KERN_ERR PFX "Failed to unregister Harmony driver\n");
+ return;
}
-module_init(alsa_card_harmony_init)
-module_exit(alsa_card_harmony_exit)
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Kyle McMartin <kyle@parisc-linux.org>");
+MODULE_DESCRIPTION("Harmony sound driver");
+
+module_init(alsa_harmony_init);
+module_exit(alsa_harmony_fini);
diff --git a/sound/parisc/harmony.h b/sound/parisc/harmony.h
new file mode 100644
index 0000000000000..ef77f9a577d53
--- /dev/null
+++ b/sound/parisc/harmony.h
@@ -0,0 +1,151 @@
+/* Hewlett-Packard Harmony audio driver
+ * Copyright (C) 2004, Kyle McMartin <kyle@parisc-linux.org>
+ */
+
+#ifndef __HARMONY_H__
+#define __HARMONY_H__
+
+struct harmony_buffer {
+ unsigned long addr;
+ int buf;
+ int count;
+ int size;
+ int coherent;
+};
+
+typedef struct snd_card_harmony {
+ int irq;
+
+ unsigned long hpa; /* hard physical address */
+ void __iomem *iobase; /* remapped io address */
+
+ struct parisc_device *dev;
+
+ struct {
+ u32 gain;
+ u32 rate;
+ u32 format;
+ u32 stereo;
+ int playing;
+ int capturing;
+ } st;
+
+ struct snd_dma_device dma; /* playback/capture */
+ struct harmony_buffer pbuf;
+ struct harmony_buffer cbuf;
+
+ struct snd_dma_buffer gdma; /* graveyard */
+ struct snd_dma_buffer sdma; /* silence */
+
+ struct {
+ unsigned long play_intr;
+ unsigned long rec_intr;
+ unsigned long graveyard_intr;
+ 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;
+
+ spinlock_t lock;
+ spinlock_t mixer_lock;
+} harmony_t;
+
+#define MAX_PCM_DEVICES 1
+#define MAX_PCM_SUBSTREAMS 4
+#define MAX_MIDI_DEVICES 0
+
+#define HARMONY_SIZE 64
+
+#define BUF_SIZE PAGE_SIZE
+#define MAX_BUFS 10
+#define MAX_BUF_SIZE (MAX_BUFS * BUF_SIZE)
+
+#define PLAYBACK_BUFS MAX_BUFS
+#define RECORD_BUFS MAX_BUFS
+#define GRAVEYARD_BUFS 1
+#define GRAVEYARD_BUFSZ (GRAVEYARD_BUFS*BUF_SIZE)
+#define SILENCE_BUFS 1
+#define SILENCE_BUFSZ (SILENCE_BUFS*BUF_SIZE)
+
+#define HARMONY_ID 0x000
+#define HARMONY_RESET 0x004
+#define HARMONY_CNTL 0x008
+#define HARMONY_GAINCTL 0x00c
+#define HARMONY_PNXTADD 0x010
+#define HARMONY_PCURADD 0x014
+#define HARMONY_RNXTADD 0x018
+#define HARMONY_RCURADD 0x01c
+#define HARMONY_DSTATUS 0x020
+#define HARMONY_OV 0x024
+#define HARMONY_PIO 0x028
+#define HARMONY_DIAG 0x03c
+
+#define HARMONY_CNTL_C 0x80000000
+#define HARMONY_CNTL_ST 0x00000020
+#define HARMONY_CNTL_44100 0x00000015 /* HARMONY_SR_44KHZ */
+#define HARMONY_CNTL_8000 0x00000008 /* HARMONY_SR_8KHZ */
+
+#define HARMONY_DSTATUS_ID 0x00000000 /* interrupts off */
+#define HARMONY_DSTATUS_PN 0x00000200 /* playback fill */
+#define HARMONY_DSTATUS_RN 0x00000002 /* record fill */
+#define HARMONY_DSTATUS_IE 0x80000000 /* interrupts on */
+
+#define HARMONY_DF_16BIT_LINEAR 0x00000000
+#define HARMONY_DF_8BIT_ULAW 0x00000001
+#define HARMONY_DF_8BIT_ALAW 0x00000002
+
+#define HARMONY_SS_MONO 0x00000000
+#define HARMONY_SS_STEREO 0x00000001
+
+#define HARMONY_GAIN_SILENCE 0x00F00FFF
+#define HARMONY_GAIN_DEFAULT 0x0FF00000
+
+#define HARMONY_GAIN_HE_SHIFT 27
+#define HARMONY_GAIN_HE_MASK (1 << HARMONY_GAIN_HE_SHIFT)
+#define HARMONY_GAIN_LE_SHIFT 26
+#define HARMONY_GAIN_LE_MASK (1 << HARMONY_GAIN_LE_SHIFT)
+#define HARMONY_GAIN_SE_SHIFT 25
+#define HARMONY_GAIN_SE_MASK (1 << HARMONY_GAIN_SE_SHIFT)
+#define HARMONY_GAIN_IS_SHIFT 24
+#define HARMONY_GAIN_IS_MASK (1 << HARMONY_GAIN_IS_SHIFT)
+
+#define HARMONY_GAIN_MA 0x0f
+#define HARMONY_GAIN_MA_SHIFT 20
+#define HARMONY_GAIN_MA_MASK (HARMONY_GAIN_MA << HARMONY_GAIN_MA_SHIFT)
+
+#define HARMONY_GAIN_IN 0x0f
+#define HARMONY_GAIN_LI_SHIFT 16
+#define HARMONY_GAIN_LI_MASK (HARMONY_GAIN_IN << HARMONY_GAIN_LI_SHIFT)
+#define HARMONY_GAIN_RI_SHIFT 12
+#define HARMONY_GAIN_RI_MASK (HARMONY_GAIN_IN << HARMONY_GAIN_RI_SHIFT)
+
+#define HARMONY_GAIN_OUT 0x3f
+#define HARMONY_GAIN_LO_SHIFT 6
+#define HARMONY_GAIN_LO_MASK (HARMONY_GAIN_OUT << HARMONY_GAIN_LO_SHIFT)
+#define HARMONY_GAIN_RO_SHIFT 0
+#define HARMONY_GAIN_RO_MASK (HARMONY_GAIN_OUT << HARMONY_GAIN_RO_SHIFT)
+
+#define HARMONY_MAX_OUT (HARMONY_GAIN_RO_MASK >> HARMONY_GAIN_RO_SHIFT)
+#define HARMONY_MAX_IN (HARMONY_GAIN_RI_MASK >> HARMONY_GAIN_RI_SHIFT)
+#define HARMONY_MAX_MON (HARMONY_GAIN_MA_MASK >> HARMONY_GAIN_MA_SHIFT)
+
+#define HARMONY_SR_8KHZ 0x08
+#define HARMONY_SR_16KHZ 0x09
+#define HARMONY_SR_27KHZ 0x0A
+#define HARMONY_SR_32KHZ 0x0B
+#define HARMONY_SR_48KHZ 0x0E
+#define HARMONY_SR_9KHZ 0x0F
+#define HARMONY_SR_5KHZ 0x10
+#define HARMONY_SR_11KHZ 0x11
+#define HARMONY_SR_18KHZ 0x12
+#define HARMONY_SR_22KHZ 0x13
+#define HARMONY_SR_37KHZ 0x14
+#define HARMONY_SR_44KHZ 0x15
+#define HARMONY_SR_33KHZ 0x16
+#define HARMONY_SR_6KHZ 0x17
+
+#endif /* __HARMONY_H__ */
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig
index 2acb2f7939e94..428efdbd70a12 100644
--- a/sound/pci/Kconfig
+++ b/sound/pci/Kconfig
@@ -514,5 +514,15 @@ config SND_VX222
To compile this driver as a module, choose M here: the module
will be called snd-vx222.
-endmenu
+config SND_HDA_INTEL
+ tristate "Intel HD Audio"
+ depends on SND
+ select SND_PCM
+ help
+ 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-hda-intel.
+
+endmenu
diff --git a/sound/pci/Makefile b/sound/pci/Makefile
index 9cba3cdadd432..b40575c3349ad 100644
--- a/sound/pci/Makefile
+++ b/sound/pci/Makefile
@@ -53,6 +53,7 @@ obj-$(CONFIG_SND) += \
ca0106/ \
cs46xx/ \
emu10k1/ \
+ hda/ \
ice1712/ \
korg1212/ \
mixart/ \
diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c
index 171bf668a3ff9..0b024ec1f7096 100644
--- a/sound/pci/ac97/ac97_codec.c
+++ b/sound/pci/ac97/ac97_codec.c
@@ -56,6 +56,7 @@ typedef struct {
const char *name;
int (*patch)(ac97_t *ac97);
int (*mpatch)(ac97_t *ac97);
+ unsigned int flags;
} ac97_codec_id_t;
static const ac97_codec_id_t snd_ac97_codec_id_vendors[] = {
@@ -103,8 +104,9 @@ static const ac97_codec_id_t snd_ac97_codec_ids[] = {
{ 0x41445372, 0xffffffff, "AD1981A", patch_ad1981a, NULL },
{ 0x41445374, 0xffffffff, "AD1981B", patch_ad1981b, NULL },
{ 0x41445375, 0xffffffff, "AD1985", patch_ad1985, NULL },
-{ 0x414c4300, 0xffffff00, "ALC100/100P", NULL, NULL },
-{ 0x414c4710, 0xfffffff0, "ALC200/200P", NULL, NULL },
+{ 0x41445378, 0xffffffff, "AD1986", patch_ad1985, NULL },
+{ 0x414c4300, 0xffffff00, "ALC100,100P", NULL, NULL },
+{ 0x414c4710, 0xfffffff0, "ALC200,200P", NULL, NULL },
{ 0x414c4721, 0xffffffff, "ALC650D", NULL, NULL }, /* already patched */
{ 0x414c4722, 0xffffffff, "ALC650E", NULL, NULL }, /* already patched */
{ 0x414c4723, 0xffffffff, "ALC650F", NULL, NULL }, /* already patched */
@@ -143,11 +145,11 @@ static const ac97_codec_id_t snd_ac97_codec_ids[] = {
{ 0x49434552, 0xffffffff, "VT1616i", patch_vt1616, NULL }, // VT1616 compatible (chipset integrated)
{ 0x49544520, 0xffffffff, "IT2226E", NULL, NULL },
{ 0x49544561, 0xffffffff, "IT2646E", patch_it2646, NULL },
-{ 0x4e534300, 0xffffffff, "LM4540/43/45/46/48", NULL, NULL }, // only guess --jk
+{ 0x4e534300, 0xffffffff, "LM4540,43,45,46,48", NULL, NULL }, // only guess --jk
{ 0x4e534331, 0xffffffff, "LM4549", NULL, NULL },
{ 0x4e534350, 0xffffffff, "LM4550", NULL, NULL },
{ 0x50534304, 0xffffffff, "UCB1400", NULL, NULL },
-{ 0x53494c20, 0xffffffe0, "Si3036/8", NULL, mpatch_si3036 },
+{ 0x53494c20, 0xffffffe0, "Si3036,8", NULL, mpatch_si3036 },
{ 0x54524102, 0xffffffff, "TR28022", NULL, NULL },
{ 0x54524106, 0xffffffff, "TR28026", NULL, NULL },
{ 0x54524108, 0xffffffff, "TR28028", patch_tritech_tr28028, NULL }, // added by xin jin [07/09/99]
@@ -156,25 +158,26 @@ static const ac97_codec_id_t snd_ac97_codec_ids[] = {
{ 0x56494161, 0xffffffff, "VIA1612A", NULL, NULL }, // modified ICE1232 with S/PDIF
{ 0x57454301, 0xffffffff, "W83971D", NULL, NULL },
{ 0x574d4c00, 0xffffffff, "WM9701A", NULL, NULL },
-{ 0x574d4C03, 0xffffffff, "WM9703/WM9707/WM9708/WM9717", patch_wolfson03, NULL},
-{ 0x574d4C04, 0xffffffff, "WM9704M/WM9704Q", patch_wolfson04, NULL},
-{ 0x574d4C05, 0xffffffff, "WM9705/WM9710", patch_wolfson05, NULL},
+{ 0x574d4C03, 0xffffffff, "WM9703,WM9707,WM9708,WM9717", patch_wolfson03, NULL},
+{ 0x574d4C04, 0xffffffff, "WM9704M,WM9704Q", patch_wolfson04, NULL},
+{ 0x574d4C05, 0xffffffff, "WM9705,WM9710", patch_wolfson05, NULL},
{ 0x574d4C09, 0xffffffff, "WM9709", NULL, NULL},
-{ 0x574d4C12, 0xffffffff, "WM9711/WM9712", patch_wolfson11, NULL},
+{ 0x574d4C12, 0xffffffff, "WM9711,WM9712", patch_wolfson11, NULL},
+{ 0x574d4c13, 0xffffffff, "WM9713,WM9714", patch_wolfson13, NULL, AC97_DEFAULT_POWER_OFF},
{ 0x594d4800, 0xffffffff, "YMF743", NULL, NULL },
{ 0x594d4802, 0xffffffff, "YMF752", NULL, NULL },
{ 0x594d4803, 0xffffffff, "YMF753", patch_yamaha_ymf753, NULL },
-{ 0x83847600, 0xffffffff, "STAC9700/83/84", patch_sigmatel_stac9700, NULL },
-{ 0x83847604, 0xffffffff, "STAC9701/3/4/5", NULL, NULL },
+{ 0x83847600, 0xffffffff, "STAC9700,83,84", patch_sigmatel_stac9700, NULL },
+{ 0x83847604, 0xffffffff, "STAC9701,3,4,5", NULL, NULL },
{ 0x83847605, 0xffffffff, "STAC9704", NULL, NULL },
-{ 0x83847608, 0xffffffff, "STAC9708/11", patch_sigmatel_stac9708, NULL },
-{ 0x83847609, 0xffffffff, "STAC9721/23", patch_sigmatel_stac9721, NULL },
+{ 0x83847608, 0xffffffff, "STAC9708,11", patch_sigmatel_stac9708, NULL },
+{ 0x83847609, 0xffffffff, "STAC9721,23", patch_sigmatel_stac9721, NULL },
{ 0x83847644, 0xffffffff, "STAC9744", patch_sigmatel_stac9744, NULL },
-{ 0x83847650, 0xffffffff, "STAC9750/51", NULL, NULL }, // patch?
-{ 0x83847652, 0xffffffff, "STAC9752/53", NULL, NULL }, // patch?
-{ 0x83847656, 0xffffffff, "STAC9756/57", patch_sigmatel_stac9756, NULL },
-{ 0x83847658, 0xffffffff, "STAC9758/59", patch_sigmatel_stac9758, NULL },
-{ 0x83847666, 0xffffffff, "STAC9766/67", NULL, NULL }, // patch?
+{ 0x83847650, 0xffffffff, "STAC9750,51", NULL, NULL }, // patch?
+{ 0x83847652, 0xffffffff, "STAC9752,53", NULL, NULL }, // patch?
+{ 0x83847656, 0xffffffff, "STAC9756,57", patch_sigmatel_stac9756, NULL },
+{ 0x83847658, 0xffffffff, "STAC9758,59", patch_sigmatel_stac9758, NULL },
+{ 0x83847666, 0xffffffff, "STAC9766,67", NULL, NULL }, // patch?
{ 0, 0, NULL, NULL, NULL }
};
@@ -438,111 +441,81 @@ static int snd_ac97_ad18xx_update_pcm_bits(ac97_t *ac97, int codec, unsigned sho
}
/*
- *
+ * Controls
*/
-static int snd_ac97_info_mux(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+int snd_ac97_info_enum_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
{
- static char *texts[8] = {
- "Mic", "CD", "Video", "Aux", "Line",
- "Mix", "Mix Mono", "Phone"
- };
-
+ struct ac97_enum *e = (struct ac97_enum *)kcontrol->private_value;
+
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
- uinfo->count = 2;
- uinfo->value.enumerated.items = 8;
- if (uinfo->value.enumerated.item > 7)
- uinfo->value.enumerated.item = 7;
- strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
+ uinfo->count = e->shift_l == e->shift_r ? 1 : 2;
+ uinfo->value.enumerated.items = e->mask;
+
+ if (uinfo->value.enumerated.item > e->mask - 1)
+ uinfo->value.enumerated.item = e->mask - 1;
+ strcpy(uinfo->value.enumerated.name, e->texts[uinfo->value.enumerated.item]);
return 0;
}
-static int snd_ac97_get_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+int snd_ac97_get_enum_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ struct ac97_enum *e = (struct ac97_enum *)kcontrol->private_value;
unsigned short val;
- val = snd_ac97_read_cache(ac97, AC97_REC_SEL);
- ucontrol->value.enumerated.item[0] = (val >> 8) & 7;
- ucontrol->value.enumerated.item[1] = (val >> 0) & 7;
+ val = snd_ac97_read_cache(ac97, e->reg);
+ ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & (e->mask - 1);
+ if (e->shift_l != e->shift_r)
+ ucontrol->value.enumerated.item[1] = (val >> e->shift_r) & (e->mask - 1);
+
return 0;
}
-static int snd_ac97_put_mux(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)
{
ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ struct ac97_enum *e = (struct ac97_enum *)kcontrol->private_value;
unsigned short val;
+ unsigned short mask;
- if (ucontrol->value.enumerated.item[0] > 7 ||
- ucontrol->value.enumerated.item[1] > 7)
+ if (ucontrol->value.enumerated.item[0] > e->mask - 1)
return -EINVAL;
- val = (ucontrol->value.enumerated.item[0] << 8) |
- (ucontrol->value.enumerated.item[1] << 0);
- return snd_ac97_update(ac97, AC97_REC_SEL, val);
-}
-
-#define AC97_ENUM_DOUBLE(xname, reg, shift, invert) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_ac97_info_enum_double, \
- .get = snd_ac97_get_enum_double, .put = snd_ac97_put_enum_double, \
- .private_value = reg | (shift << 8) | (invert << 24) }
-
-static int snd_ac97_info_enum_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
-{
- static char *texts1[2] = { "pre 3D", "post 3D" };
- static char *texts2[2] = { "Mix", "Mic" };
- static char *texts3[2] = { "Mic1", "Mic2" };
- char **texts = NULL;
- int reg = kcontrol->private_value & 0xff;
- int shift = (kcontrol->private_value >> 8) & 0xff;
-
- switch (reg) {
- case AC97_GENERAL_PURPOSE:
- switch (shift) {
- case 15: texts = texts1; break;
- case 9: texts = texts2; break;
- case 8: texts = texts3; break;
- }
+ val = ucontrol->value.enumerated.item[0] << e->shift_l;
+ mask = (e->mask - 1) << e->shift_l;
+ if (e->shift_l != e->shift_r) {
+ if (ucontrol->value.enumerated.item[1] > e->mask - 1)
+ return -EINVAL;
+ val |= ucontrol->value.enumerated.item[1] << e->shift_r;
+ mask |= (e->mask - 1) << e->shift_r;
}
- uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
- uinfo->count = 1;
- uinfo->value.enumerated.items = 2;
- if (uinfo->value.enumerated.item > 1)
- uinfo->value.enumerated.item = 1;
- strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
- return 0;
+ return snd_ac97_update_bits(ac97, e->reg, mask, val);
}
-static int snd_ac97_get_enum_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+/* save/restore ac97 v2.3 paging */
+static int snd_ac97_page_save(ac97_t *ac97, int reg, snd_kcontrol_t *kcontrol)
{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
- unsigned short val;
- int reg = kcontrol->private_value & 0xff;
- int shift = (kcontrol->private_value >> 8) & 0xff;
- int invert = (kcontrol->private_value >> 24) & 0xff;
-
- val = (snd_ac97_read_cache(ac97, reg) >> shift) & 1;
- if (invert)
- val ^= 1;
- ucontrol->value.enumerated.item[0] = val;
- return 0;
+ int page_save = -1;
+ if ((kcontrol->private_value & (1<<25)) &&
+ (ac97->ext_id & AC97_EI_REV_MASK) >= AC97_EI_REV_23 &&
+ (reg >= 0x60 && reg < 0x70)) {
+ unsigned short page = (kcontrol->private_value >> 26) & 0x0f;
+ down(&ac97->page_mutex); /* lock paging */
+ page_save = snd_ac97_read(ac97, AC97_INT_PAGING) & AC97_PAGE_MASK;
+ snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page);
+ }
+ return page_save;
}
-static int snd_ac97_put_enum_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static void snd_ac97_page_restore(ac97_t *ac97, int page_save)
{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
- unsigned short val;
- int reg = kcontrol->private_value & 0xff;
- int shift = (kcontrol->private_value >> 8) & 0xff;
- int invert = (kcontrol->private_value >> 24) & 0xff;
-
- if (ucontrol->value.enumerated.item[0] > 1)
- return -EINVAL;
- val = !!ucontrol->value.enumerated.item[0];
- if (invert)
- val = !val;
- return snd_ac97_update_bits(ac97, reg, 1 << shift, val << shift);
+ if (page_save >= 0) {
+ snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page_save);
+ up(&ac97->page_mutex); /* unlock paging */
+ }
}
+/* volume and switch controls */
int snd_ac97_info_volsw(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
{
int mask = (kcontrol->private_value >> 16) & 0xff;
@@ -564,7 +537,9 @@ int snd_ac97_get_volsw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontro
int rshift = (kcontrol->private_value >> 12) & 0x0f;
int mask = (kcontrol->private_value >> 16) & 0xff;
int invert = (kcontrol->private_value >> 24) & 0x01;
-
+ int page_save;
+
+ page_save = snd_ac97_page_save(ac97, reg, kcontrol);
ucontrol->value.integer.value[0] = (snd_ac97_read_cache(ac97, reg) >> shift) & mask;
if (shift != rshift)
ucontrol->value.integer.value[1] = (snd_ac97_read_cache(ac97, reg) >> rshift) & mask;
@@ -573,6 +548,7 @@ int snd_ac97_get_volsw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontro
if (shift != rshift)
ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1];
}
+ snd_ac97_page_restore(ac97, page_save);
return 0;
}
@@ -584,8 +560,10 @@ int snd_ac97_put_volsw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontro
int rshift = (kcontrol->private_value >> 12) & 0x0f;
int mask = (kcontrol->private_value >> 16) & 0xff;
int invert = (kcontrol->private_value >> 24) & 0x01;
+ int err, page_save;
unsigned short val, val2, val_mask;
+ page_save = snd_ac97_page_save(ac97, reg, kcontrol);
val = (ucontrol->value.integer.value[0] & mask);
if (invert)
val = mask - val;
@@ -598,48 +576,11 @@ int snd_ac97_put_volsw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontro
val_mask |= mask << rshift;
val |= val2 << rshift;
}
- return snd_ac97_update_bits(ac97, reg, val_mask, val);
-}
-
-#define AC97_DOUBLE(xname, reg, shift_left, shift_right, mask, invert) \
-{ .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) }
-
-static int snd_ac97_getput_page(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol,
- int (*func)(snd_kcontrol_t *, snd_ctl_elem_value_t *))
-{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
- int reg = kcontrol->private_value & 0xff;
- int err;
-
- if ((ac97->ext_id & AC97_EI_REV_MASK) >= AC97_EI_REV_23 &&
- (reg >= 0x60 && reg < 0x70)) {
- unsigned short page_save;
- unsigned short page = (kcontrol->private_value >> 25) & 0x0f;
- down(&ac97->page_mutex); /* lock paging */
- page_save = snd_ac97_read(ac97, AC97_INT_PAGING) & AC97_PAGE_MASK;
- snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page);
- err = func(kcontrol, ucontrol);
- snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page_save);
- up(&ac97->page_mutex); /* unlock paging */
- } else
- err = func(kcontrol, ucontrol);
+ err = snd_ac97_update_bits(ac97, reg, val_mask, val);
+ snd_ac97_page_restore(ac97, page_save);
return err;
}
-/* for rev2.3 paging */
-int snd_ac97_page_get_volsw(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
-{
- return snd_ac97_getput_page(kcontrol, ucontrol, snd_ac97_get_volsw);
-}
-
-/* for rev2.3 paging */
-int snd_ac97_page_put_volsw(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
-{
- return snd_ac97_getput_page(kcontrol, ucontrol, snd_ac97_put_volsw);
-}
-
static const snd_kcontrol_new_t 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)
@@ -659,14 +600,21 @@ static const snd_kcontrol_new_t snd_ac97_controls_mic_boost =
AC97_SINGLE("Mic Boost (+20dB)", AC97_MIC, 6, 1, 0);
-static const snd_kcontrol_new_t snd_ac97_control_capture_src = {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Capture Source",
- .info = snd_ac97_info_mux,
- .get = snd_ac97_get_mux,
- .put = snd_ac97_put_mux,
+static const char* std_rec_sel[] = {"Mic", "CD", "Video", "Aux", "Line", "Mix", "Mix Mono", "Phone"};
+static const char* std_3d_path[] = {"pre 3D", "post 3D"};
+static const char* std_mix[] = {"Mix", "Mic"};
+static const char* std_mic[] = {"Mic1", "Mic2"};
+
+static const struct ac97_enum std_enum[] = {
+AC97_ENUM_DOUBLE(AC97_REC_SEL, 8, 0, 8, std_rec_sel),
+AC97_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 15, 2, std_3d_path),
+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 =
+AC97_ENUM("Capture Source", std_enum[0]);
+
static const snd_kcontrol_new_t snd_ac97_control_capture_vol =
AC97_DOUBLE("Capture Volume", AC97_REC_GAIN, 8, 0, 15, 0);
@@ -686,12 +634,12 @@ typedef enum {
} ac97_general_index_t;
static const snd_kcontrol_new_t snd_ac97_controls_general[7] = {
-AC97_ENUM_DOUBLE("PCM Out Path & Mute", AC97_GENERAL_PURPOSE, 15, 0),
+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),
AC97_SINGLE("Loudness (bass boost)", AC97_GENERAL_PURPOSE, 12, 1, 0),
-AC97_ENUM_DOUBLE("Mono Output Select", AC97_GENERAL_PURPOSE, 9, 0),
-AC97_ENUM_DOUBLE("Mic Select", AC97_GENERAL_PURPOSE, 8, 0),
+AC97_ENUM("Mono Output Select", std_enum[2]),
+AC97_ENUM("Mic Select", std_enum[3]),
AC97_SINGLE("ADC/DAC Loopback", AC97_GENERAL_PURPOSE, 7, 1, 0)
};
@@ -1185,7 +1133,7 @@ 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(snd_card_t *card, char *name, int reg, ac97_t *ac97)
+static int snd_ac97_cmute_new_stereo(snd_card_t *card, char *name, int reg, int check_stereo, ac97_t *ac97)
{
snd_kcontrol_t *kctl;
int err;
@@ -1196,7 +1144,7 @@ static int snd_ac97_cmute_new(snd_card_t *card, char *name, int reg, ac97_t *ac9
mute_mask = 0x8000;
val = snd_ac97_read(ac97, reg);
- if (ac97->flags & AC97_STEREO_MUTES) {
+ if (check_stereo || (ac97->flags & AC97_STEREO_MUTES)) {
/* check whether both mute bits work */
val1 = val | 0x8080;
snd_ac97_write(ac97, reg, val1);
@@ -1254,7 +1202,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(snd_card_t *card, const char *pfx, int reg, ac97_t *ac97)
+static int snd_ac97_cmix_new_stereo(snd_card_t *card, const char *pfx, int reg, int check_stereo, ac97_t *ac97)
{
int err;
char name[44];
@@ -1265,7 +1213,7 @@ static int snd_ac97_cmix_new(snd_card_t *card, const char *pfx, int reg, ac97_t
if (snd_ac97_try_bit(ac97, reg, 15)) {
sprintf(name, "%s Switch", pfx);
- if ((err = snd_ac97_cmute_new(card, name, reg, ac97)) < 0)
+ if ((err = snd_ac97_cmute_new_stereo(card, name, reg, check_stereo, ac97)) < 0)
return err;
}
check_volume_resolution(ac97, reg, &lo_max, &hi_max);
@@ -1277,6 +1225,8 @@ static int snd_ac97_cmix_new(snd_card_t *card, const char *pfx, int reg, ac97_t
return 0;
}
+#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);
@@ -1327,7 +1277,8 @@ static int snd_ac97_mixer_build(ac97_t * ac97)
/* build surround controls */
if (snd_ac97_try_volume_mix(ac97, AC97_SURROUND_MASTER)) {
- if ((err = snd_ac97_cmix_new(card, "Surround Playback", AC97_SURROUND_MASTER, ac97)) < 0)
+ /* Surround Master (0x38) is with stereo mutes */
+ if ((err = snd_ac97_cmix_new_stereo(card, "Surround Playback", AC97_SURROUND_MASTER, 1, ac97)) < 0)
return err;
}
@@ -1357,8 +1308,9 @@ static int snd_ac97_mixer_build(ac97_t * ac97)
}
/* build PC Speaker controls */
- if ((ac97->flags & AC97_HAS_PC_BEEP) ||
- snd_ac97_try_volume_mix(ac97, AC97_PC_BEEP)) {
+ if (!(ac97->flags & AC97_HAS_NO_PC_BEEP) &&
+ ((ac97->flags & AC97_HAS_PC_BEEP) ||
+ snd_ac97_try_volume_mix(ac97, AC97_PC_BEEP))) {
for (idx = 0; idx < 2; idx++)
if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_pc_beep[idx], ac97))) < 0)
return err;
@@ -1367,9 +1319,11 @@ static int snd_ac97_mixer_build(ac97_t * ac97)
}
/* build Phone controls */
- if (snd_ac97_try_volume_mix(ac97, AC97_PHONE)) {
- if ((err = snd_ac97_cmix_new(card, "Phone Playback", AC97_PHONE, ac97)) < 0)
- return err;
+ if (!(ac97->flags & AC97_HAS_NO_PHONE)) {
+ if (snd_ac97_try_volume_mix(ac97, AC97_PHONE)) {
+ if ((err = snd_ac97_cmix_new(card, "Phone Playback", AC97_PHONE, ac97)) < 0)
+ return err;
+ }
}
/* build MIC controls */
@@ -1387,15 +1341,19 @@ static int snd_ac97_mixer_build(ac97_t * ac97)
}
/* build CD controls */
- if (snd_ac97_try_volume_mix(ac97, AC97_CD)) {
- if ((err = snd_ac97_cmix_new(card, "CD Playback", AC97_CD, ac97)) < 0)
- return err;
+ if (!(ac97->flags & AC97_HAS_NO_CD)) {
+ if (snd_ac97_try_volume_mix(ac97, AC97_CD)) {
+ if ((err = snd_ac97_cmix_new(card, "CD Playback", AC97_CD, ac97)) < 0)
+ return err;
+ }
}
/* build Video controls */
- if (snd_ac97_try_volume_mix(ac97, AC97_VIDEO)) {
- if ((err = snd_ac97_cmix_new(card, "Video Playback", AC97_VIDEO, ac97)) < 0)
- return err;
+ if (!(ac97->flags & AC97_HAS_NO_VIDEO)) {
+ if (snd_ac97_try_volume_mix(ac97, AC97_VIDEO)) {
+ if ((err = snd_ac97_cmix_new(card, "Video Playback", AC97_VIDEO, ac97)) < 0)
+ return err;
+ }
}
/* build Aux controls */
@@ -1441,17 +1399,18 @@ static int snd_ac97_mixer_build(ac97_t * ac97)
}
/* build Capture controls */
- if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_control_capture_src, ac97))) < 0)
- return err;
- if (snd_ac97_try_bit(ac97, AC97_REC_GAIN, 15)) {
- if ((err = snd_ac97_cmute_new(card, "Capture Switch", AC97_REC_GAIN, ac97)) < 0)
+ if (!(ac97->flags & AC97_HAS_NO_REC_GAIN)) {
+ if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_control_capture_src, ac97))) < 0)
+ return err;
+ if (snd_ac97_try_bit(ac97, AC97_REC_GAIN, 15)) {
+ if ((err = snd_ac97_cmute_new(card, "Capture Switch", AC97_REC_GAIN, ac97)) < 0)
+ return err;
+ }
+ if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_control_capture_vol, ac97))) < 0)
return err;
+ snd_ac97_write_cache(ac97, AC97_REC_SEL, 0x0000);
+ snd_ac97_write_cache(ac97, AC97_REC_GAIN, 0x0000);
}
- if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_control_capture_vol, ac97))) < 0)
- return err;
- snd_ac97_write_cache(ac97, AC97_REC_SEL, 0x0000);
- snd_ac97_write_cache(ac97, AC97_REC_GAIN, 0x0000);
-
/* build MIC Capture controls */
if (snd_ac97_try_volume_mix(ac97, AC97_REC_GAIN_MIC)) {
for (idx = 0; idx < 2; idx++)
@@ -1527,7 +1486,7 @@ static int snd_ac97_mixer_build(ac97_t * ac97)
}
/* build S/PDIF controls */
- if (ac97->ext_id & AC97_EI_SPDIF) {
+ if ((ac97->ext_id & AC97_EI_SPDIF) && !(ac97->scaps & AC97_SCAP_NO_SPDIF)) {
if (ac97->build_ops->build_spdif) {
if ((err = ac97->build_ops->build_spdif(ac97)) < 0)
return err;
@@ -1593,6 +1552,7 @@ static int snd_ac97_test_rate(ac97_t *ac97, int reg, int shadow_reg, int rate)
static void snd_ac97_determine_rates(ac97_t *ac97, int reg, int shadow_reg, unsigned int *r_result)
{
unsigned int result = 0;
+ unsigned short saved;
if (ac97->bus->no_vra) {
*r_result = SNDRV_PCM_RATE_48000;
@@ -1602,6 +1562,7 @@ static void snd_ac97_determine_rates(ac97_t *ac97, int reg, int shadow_reg, unsi
return;
}
+ saved = snd_ac97_read(ac97, reg);
if ((ac97->ext_id & AC97_EI_DRA) && reg == AC97_PCM_FRONT_DAC_RATE)
snd_ac97_update_bits(ac97, AC97_EXTENDED_STATUS,
AC97_EA_DRA, 0);
@@ -1640,6 +1601,10 @@ static void snd_ac97_determine_rates(ac97_t *ac97, int reg, int shadow_reg, unsi
snd_ac97_update_bits(ac97, AC97_EXTENDED_STATUS,
AC97_EA_DRA, 0);
}
+ /* restore the default value */
+ snd_ac97_write_cache(ac97, reg, saved);
+ if (shadow_reg)
+ snd_ac97_write_cache(ac97, shadow_reg, saved);
*r_result = result;
}
@@ -1663,6 +1628,18 @@ static unsigned int snd_ac97_determine_spdif_rates(ac97_t *ac97)
return result;
}
+/* 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)
+{
+ const ac97_codec_id_t *pid;
+
+ for (pid = table; pid->id; pid++)
+ if (pid->id == (id & pid->mask))
+ return pid;
+ return NULL;
+}
+
void snd_ac97_get_name(ac97_t *ac97, unsigned int id, char *name, int modem)
{
const ac97_codec_id_t *pid;
@@ -1671,35 +1648,30 @@ void snd_ac97_get_name(ac97_t *ac97, unsigned int id, char *name, int modem)
printable(id >> 24),
printable(id >> 16),
printable(id >> 8));
- for (pid = snd_ac97_codec_id_vendors; pid->id; pid++)
- if (pid->id == (id & pid->mask)) {
- strcpy(name, pid->name);
- if (ac97) {
- if (!modem && pid->patch)
- pid->patch(ac97);
- else if (modem && pid->mpatch)
- pid->mpatch(ac97);
- }
- goto __vendor_ok;
- }
- return;
+ pid = look_for_codec_id(snd_ac97_codec_id_vendors, id);
+ if (! pid)
+ return;
- __vendor_ok:
- for (pid = snd_ac97_codec_ids; pid->id; pid++)
- if (pid->id == (id & pid->mask)) {
- strcat(name, " ");
- strcat(name, pid->name);
- if (pid->mask != 0xffffffff)
- sprintf(name + strlen(name), " rev %d", id & ~pid->mask);
- if (ac97) {
- if (!modem && pid->patch)
- pid->patch(ac97);
- else if (modem && pid->mpatch)
- pid->mpatch(ac97);
- }
- return;
+ strcpy(name, pid->name);
+ if (ac97 && pid->patch) {
+ if ((modem && (pid->flags & AC97_MODEM_PATCH)) ||
+ (! modem && ! (pid->flags & AC97_MODEM_PATCH)))
+ pid->patch(ac97);
+ }
+
+ pid = look_for_codec_id(snd_ac97_codec_ids, id);
+ if (pid) {
+ strcat(name, " ");
+ strcat(name, pid->name);
+ if (pid->mask != 0xffffffff)
+ sprintf(name + strlen(name), " rev %d", id & ~pid->mask);
+ if (ac97 && pid->patch) {
+ if ((modem && (pid->flags & AC97_MODEM_PATCH)) ||
+ (! modem && ! (pid->flags & AC97_MODEM_PATCH)))
+ pid->patch(ac97);
}
- sprintf(name + strlen(name), " id %x", id & 0xff);
+ } else
+ sprintf(name + strlen(name), " id %x", id & 0xff);
}
/**
@@ -1841,6 +1813,7 @@ int snd_ac97_mixer(ac97_bus_t *bus, ac97_template_t *template, ac97_t **rac97)
char name[64];
unsigned long end_time;
unsigned int reg;
+ const ac97_codec_id_t *pid;
static snd_device_ops_t ops = {
.dev_free = snd_ac97_dev_free,
};
@@ -1891,6 +1864,14 @@ int snd_ac97_mixer(ac97_bus_t *bus, ac97_template_t *template, ac97_t **rac97)
goto __access_ok;
}
+ ac97->id = snd_ac97_read(ac97, AC97_VENDOR_ID1) << 16;
+ ac97->id |= snd_ac97_read(ac97, AC97_VENDOR_ID2);
+ if (ac97->id && ac97->id != (unsigned int)-1) {
+ pid = look_for_codec_id(snd_ac97_codec_ids, ac97->id);
+ if (pid && (pid->flags & AC97_DEFAULT_POWER_OFF))
+ goto __access_ok;
+ }
+
snd_ac97_write(ac97, AC97_RESET, 0); /* reset to defaults */
if (bus->ops->wait)
bus->ops->wait(ac97);
@@ -1917,6 +1898,9 @@ int snd_ac97_mixer(ac97_bus_t *bus, ac97_template_t *template, ac97_t **rac97)
snd_ac97_free(ac97);
return -EIO;
}
+ pid = look_for_codec_id(snd_ac97_codec_ids, ac97->id);
+ if (pid)
+ ac97->flags |= pid->flags;
/* test for AC'97 */
if (!(ac97->scaps & AC97_SCAP_SKIP_AUDIO) && !(ac97->scaps & AC97_SCAP_AUDIO)) {
@@ -1955,10 +1939,12 @@ int snd_ac97_mixer(ac97_bus_t *bus, ac97_template_t *template, ac97_t **rac97)
if (ac97_is_audio(ac97)) {
/* nothing should be in powerdown mode */
snd_ac97_write_cache(ac97, AC97_POWERDOWN, 0);
- snd_ac97_write_cache(ac97, AC97_RESET, 0); /* reset to defaults */
- udelay(100);
+ if (! (ac97->flags & AC97_DEFAULT_POWER_OFF)) {
+ snd_ac97_write_cache(ac97, AC97_RESET, 0); /* reset to defaults */
+ udelay(100);
+ snd_ac97_write_cache(ac97, AC97_POWERDOWN, 0);
+ }
/* nothing should be in powerdown mode */
- snd_ac97_write_cache(ac97, AC97_POWERDOWN, 0);
snd_ac97_write_cache(ac97, AC97_GENERAL_PURPOSE, 0);
end_time = jiffies + (HZ / 10);
do {
@@ -2225,9 +2211,11 @@ void snd_ac97_resume(ac97_t *ac97)
}
snd_ac97_write(ac97, AC97_POWERDOWN, 0);
- snd_ac97_write(ac97, AC97_RESET, 0);
- udelay(100);
- snd_ac97_write(ac97, AC97_POWERDOWN, 0);
+ if (! (ac97->flags & AC97_DEFAULT_POWER_OFF)) {
+ snd_ac97_write(ac97, AC97_RESET, 0);
+ udelay(100);
+ snd_ac97_write(ac97, AC97_POWERDOWN, 0);
+ }
snd_ac97_write(ac97, AC97_GENERAL_PURPOSE, 0);
snd_ac97_write(ac97, AC97_POWERDOWN, ac97->regs[AC97_POWERDOWN]);
@@ -2331,6 +2319,35 @@ int snd_ac97_swap_ctl(ac97_t *ac97, const char *s1, const char *s2, const char *
return -ENOENT;
}
+#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)
+{
+ int err = snd_ac97_put_volsw(kcontrol, ucontrol);
+ if (err > 0) {
+ unsigned long priv_saved = kcontrol->private_value;
+ kcontrol->private_value = (kcontrol->private_value & ~0xff) | AC97_HEADPHONE;
+ snd_ac97_put_volsw(kcontrol, ucontrol);
+ kcontrol->private_value = priv_saved;
+ }
+ return err;
+}
+
+/* ac97 tune: bind Master and Headphone controls */
+static int tune_hp_only(ac97_t *ac97)
+{
+ snd_kcontrol_t *msw = ctl_find(ac97, "Master Playback Switch", NULL);
+ snd_kcontrol_t *mvol = ctl_find(ac97, "Master Playback Volume", NULL);
+ if (! msw || ! mvol)
+ return -ENOENT;
+ msw->put = bind_hp_volsw_put;
+ mvol->put = bind_hp_volsw_put;
+ snd_ac97_remove_ctl(ac97, "Headphone Playback", "Switch");
+ snd_ac97_remove_ctl(ac97, "Headphone Playback", "Volume");
+ return 0;
+}
+
+#else
/* ac97 tune: use Headphone control as master */
static int tune_hp_only(ac97_t *ac97)
{
@@ -2341,6 +2358,7 @@ static int tune_hp_only(ac97_t *ac97)
snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", "Master Playback");
return 0;
}
+#endif
/* ac97 tune: swap Headphone and Master controls */
static int tune_swap_hp(ac97_t *ac97)
@@ -2472,7 +2490,7 @@ static int apply_quirk_str(ac97_t *ac97, const char *typestr)
}
/* for compatibility, accept the numbers, too */
if (*typestr >= '0' && *typestr <= '9')
- return apply_quirk(ac97, (int)simple_strtol(typestr, NULL, 10));
+ return apply_quirk(ac97, (int)simple_strtoul(typestr, NULL, 10));
return -EINVAL;
}
diff --git a/sound/pci/ac97/ac97_local.h b/sound/pci/ac97/ac97_local.h
index 14a40606349c7..536a4d4793af4 100644
--- a/sound/pci/ac97/ac97_local.h
+++ b/sound/pci/ac97/ac97_local.h
@@ -23,15 +23,28 @@
*/
#define AC97_SINGLE_VALUE(reg,shift,mask,invert) ((reg) | ((shift) << 8) | ((shift) << 12) | ((mask) << 16) | ((invert) << 24))
-#define AC97_PAGE_SINGLE_VALUE(reg,shift,mask,invert,page) (AC97_SINGLE_VALUE(reg,shift,mask,invert) | ((page) << 25))
+#define AC97_PAGE_SINGLE_VALUE(reg,shift,mask,invert,page) (AC97_SINGLE_VALUE(reg,shift,mask,invert) | (1<<25) | ((page) << 26))
#define AC97_SINGLE(xname, reg, shift, mask, invert) \
{ .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 = AC97_SINGLE_VALUE(reg, shift, mask, invert) }
#define AC97_PAGE_SINGLE(xname, reg, shift, mask, invert, page) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_ac97_info_volsw, \
- .get = snd_ac97_page_get_volsw, .put = snd_ac97_page_put_volsw, \
+ .get = snd_ac97_get_volsw, .put = snd_ac97_put_volsw, \
.private_value = AC97_PAGE_SINGLE_VALUE(reg, shift, mask, invert, page) }
+#define AC97_DOUBLE(xname, reg, shift_left, shift_right, mask, invert) \
+{ .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) }
+#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 }
+#define AC97_ENUM_SINGLE(xreg, xshift, xmask, xtexts) \
+ AC97_ENUM_DOUBLE(xreg, xshift, xshift, xmask, xtexts)
+#define AC97_ENUM(xname, xenum) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_ac97_info_enum_double, \
+ .get = snd_ac97_get_enum_double, .put = snd_ac97_put_enum_double, \
+ .private_value = (unsigned long)&xenum }
/* ac97_codec.c */
extern const char *snd_ac97_stereo_enhancements[];
@@ -42,8 +55,6 @@ 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_page_get_volsw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol);
-int snd_ac97_page_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);
@@ -51,6 +62,9 @@ int snd_ac97_swap_ctl(ac97_t *ac97, const char *s1, const char *s2, const char *
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);
int snd_ac97_update_bits_nolock(ac97_t *ac97, unsigned short reg,
unsigned short mask, unsigned short value);
diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c
index 5bb7f24f4acf4..13c34a5d8206d 100644
--- a/sound/pci/ac97/ac97_patch.c
+++ b/sound/pci/ac97/ac97_patch.c
@@ -305,6 +305,136 @@ int patch_wolfson11(ac97_t * ac97)
return 0;
}
+static const char* wm9713_mic_mixer[] = {"Stereo", "Mic1", "Mic2", "Mute"};
+static const char* wm9713_rec_mux[] = {"Stereo", "Left", "Right", "Mute"};
+static const char* wm9713_rec_src_l[] = {"Mic1", "Mic2", "Line L", "Mono In", "HP Mix L", "Spk Mix", "Mono Mix", "Zh"};
+static const char* wm9713_rec_src_r[] = {"Mic1", "Mic2", "Line R", "Mono In", "HP Mix R", "Spk Mix", "Mono Mix", "Zh"};
+
+static const struct ac97_enum wm9713_enum[] = {
+AC97_ENUM_SINGLE(AC97_LINE, 3, 4, wm9713_mic_mixer),
+AC97_ENUM_SINGLE(AC97_VIDEO, 14, 4, wm9713_rec_mux),
+AC97_ENUM_SINGLE(AC97_VIDEO, 9, 4, wm9713_rec_mux),
+AC97_ENUM_SINGLE(AC97_VIDEO, 3, 8, wm9713_rec_src_l),
+AC97_ENUM_SINGLE(AC97_VIDEO, 0, 8, wm9713_rec_src_r),
+};
+
+static const snd_kcontrol_new_t wm13_snd_ac97_controls_line_in[] = {
+AC97_DOUBLE("Line In Volume", AC97_PC_BEEP, 8, 0, 31, 1),
+AC97_SINGLE("Line In to Headphone Mute", AC97_PC_BEEP, 15, 1, 1),
+AC97_SINGLE("Line In to Speaker Mute", AC97_PC_BEEP, 14, 1, 1),
+AC97_SINGLE("Line In to Mono Mute", AC97_PC_BEEP, 13, 1, 1),
+};
+
+static const snd_kcontrol_new_t wm13_snd_ac97_controls_dac[] = {
+AC97_DOUBLE("DAC Volume", AC97_PHONE, 8, 0, 31, 1),
+AC97_SINGLE("DAC to Headphone Mute", AC97_PHONE, 15, 1, 1),
+AC97_SINGLE("DAC to Speaker Mute", AC97_PHONE, 14, 1, 1),
+AC97_SINGLE("DAC to Mono Mute", AC97_PHONE, 13, 1, 1),
+};
+
+static const snd_kcontrol_new_t wm13_snd_ac97_controls_mic[] = {
+AC97_SINGLE("MICA Volume", AC97_MIC, 8, 31, 1),
+AC97_SINGLE("MICB Volume", AC97_MIC, 0, 31, 1),
+AC97_SINGLE("MICA to Mono Mute", AC97_LINE, 7, 1, 1),
+AC97_SINGLE("MICB to Mono Mute", AC97_LINE, 6, 1, 1),
+AC97_SINGLE("MIC Boost (+20dB)", AC97_LINE, 5, 1, 1),
+AC97_ENUM("MIC Headphone Routing", wm9713_enum[0]),
+AC97_SINGLE("MIC Headphone Mixer Volume", AC97_LINE, 0, 7, 1)
+};
+
+static const snd_kcontrol_new_t wm13_snd_ac97_controls_adc[] = {
+AC97_SINGLE("ADC Mute", AC97_CD, 15, 1, 1),
+AC97_DOUBLE("Gain Step Size (1.5dB/0.75dB)", AC97_CD, 14, 6, 1, 1),
+AC97_DOUBLE("ADC Volume",AC97_CD, 8, 0, 15, 0),
+AC97_SINGLE("ADC Zero Cross", AC97_CD, 7, 1, 1),
+};
+
+static const snd_kcontrol_new_t wm13_snd_ac97_controls_recsel[] = {
+AC97_ENUM("Record to Headphone Path", wm9713_enum[1]),
+AC97_SINGLE("Record to Headphone Volume", AC97_VIDEO, 11, 7, 0),
+AC97_ENUM("Record to Mono Path", wm9713_enum[2]),
+AC97_SINGLE("Record to Mono Boost (+20dB)", AC97_VIDEO, 8, 1, 0),
+AC97_SINGLE("Record ADC Boost (+20dB)", AC97_VIDEO, 6, 1, 0),
+AC97_ENUM("Record Select Left", wm9713_enum[3]),
+AC97_ENUM("Record Select Right", wm9713_enum[4]),
+};
+
+static int patch_wolfson_wm9713_specific(ac97_t * ac97)
+{
+ int err, i;
+
+ for (i = 0; i < ARRAY_SIZE(wm13_snd_ac97_controls_line_in); i++) {
+ if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm13_snd_ac97_controls_line_in[i], ac97))) < 0)
+ return err;
+ }
+ snd_ac97_write_cache(ac97, AC97_PC_BEEP, 0x0808);
+
+ for (i = 0; i < ARRAY_SIZE(wm13_snd_ac97_controls_dac); i++) {
+ if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm13_snd_ac97_controls_dac[i], ac97))) < 0)
+ return err;
+ }
+ snd_ac97_write_cache(ac97, AC97_PHONE, 0x0808);
+
+ for (i = 0; i < ARRAY_SIZE(wm13_snd_ac97_controls_mic); i++) {
+ if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm13_snd_ac97_controls_mic[i], ac97))) < 0)
+ return err;
+ }
+ snd_ac97_write_cache(ac97, AC97_MIC, 0x0808);
+ snd_ac97_write_cache(ac97, AC97_LINE, 0x00da);
+
+ for (i = 0; i < ARRAY_SIZE(wm13_snd_ac97_controls_adc); i++) {
+ if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm13_snd_ac97_controls_adc[i], ac97))) < 0)
+ return err;
+ }
+ snd_ac97_write_cache(ac97, AC97_CD, 0x0808);
+
+ for (i = 0; i < ARRAY_SIZE(wm13_snd_ac97_controls_recsel); i++) {
+ if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm13_snd_ac97_controls_recsel[i], ac97))) < 0)
+ return err;
+ }
+ snd_ac97_write_cache(ac97, AC97_VIDEO, 0xd612);
+ snd_ac97_write_cache(ac97, AC97_REC_GAIN, 0x1ba0);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static void patch_wolfson_wm9713_suspend (ac97_t * 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)
+{
+ snd_ac97_write_cache(ac97, AC97_EXTENDED_MID, 0xda00);
+ snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0x3810);
+ snd_ac97_write_cache(ac97, AC97_POWERDOWN, 0x0);
+}
+#endif
+
+static struct snd_ac97_build_ops patch_wolfson_wm9713_ops = {
+ .build_specific = patch_wolfson_wm9713_specific,
+#ifdef CONFIG_PM
+ .suspend = patch_wolfson_wm9713_suspend,
+ .resume = patch_wolfson_wm9713_resume
+#endif
+};
+
+int patch_wolfson13(ac97_t * ac97)
+{
+ ac97->build_ops = &patch_wolfson_wm9713_ops;
+
+ ac97->flags |= AC97_HAS_NO_REC_GAIN | AC97_STEREO_MUTES | AC97_HAS_NO_PHONE |
+ AC97_HAS_NO_PC_BEEP | AC97_HAS_NO_VIDEO | AC97_HAS_NO_CD;
+
+ snd_ac97_write_cache(ac97, AC97_EXTENDED_MID, 0xda00);
+ snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0x3810);
+ snd_ac97_write_cache(ac97, AC97_POWERDOWN, 0x0);
+
+ return 0;
+}
+
/*
* Tritech codec
*/
@@ -392,9 +522,36 @@ int patch_sigmatel_stac9700(ac97_t * ac97)
return 0;
}
+static int snd_ac97_stac9708_put_bias(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+ ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ int err;
+
+ down(&ac97->page_mutex);
+ snd_ac97_write(ac97, AC97_SIGMATEL_BIAS1, 0xabba);
+ err = snd_ac97_update_bits(ac97, AC97_SIGMATEL_BIAS2, 0x0010,
+ (ucontrol->value.integer.value[0] & 1) << 4);
+ snd_ac97_write(ac97, AC97_SIGMATEL_BIAS1, 0);
+ up(&ac97->page_mutex);
+ return err;
+}
+
+static const snd_kcontrol_new_t snd_ac97_stac9708_bias_control = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Sigmatel Output Bias Switch",
+ .info = snd_ac97_info_volsw,
+ .get = snd_ac97_get_volsw,
+ .put = snd_ac97_stac9708_put_bias,
+ .private_value = AC97_SINGLE_VALUE(AC97_SIGMATEL_BIAS2, 4, 1, 0),
+};
+
static int patch_sigmatel_stac9708_specific(ac97_t *ac97)
{
+ int err;
+
snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", "Sigmatel Surround Playback");
+ if ((err = patch_build_controls(ac97, &snd_ac97_stac9708_bias_control, 1)) < 0)
+ return err;
return patch_sigmatel_stac97xx_specific(ac97);
}
@@ -1571,7 +1728,7 @@ static int alc655_iec958_route_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_
ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
return ac97_update_bits_page(ac97, AC97_ALC650_MULTICH, 3 << 12,
- (unsigned short)ucontrol->value.enumerated.item[0],
+ (unsigned short)ucontrol->value.enumerated.item[0] << 12,
0);
}
@@ -2009,10 +2166,13 @@ int patch_cm9761(ac97_t *ac97)
{
unsigned short val;
- /* CM9761 has no Master and PCM volume although the register reacts */
- ac97->flags |= AC97_HAS_NO_MASTER_VOL | AC97_HAS_NO_PCM_VOL;
- snd_ac97_write_cache(ac97, AC97_MASTER, 0x8000);
- snd_ac97_write_cache(ac97, AC97_PCM, 0x8000);
+ /* CM9761 has no PCM volume although the register reacts */
+ /* Master volume seems to have _some_ influence on the analog
+ * input sounds
+ */
+ ac97->flags |= /*AC97_HAS_NO_MASTER_VOL |*/ AC97_HAS_NO_PCM_VOL;
+ snd_ac97_write_cache(ac97, AC97_MASTER, 0x8808);
+ snd_ac97_write_cache(ac97, AC97_PCM, 0x8808);
ac97->spec.dev_flags = 0; /* 1 = model 82 revision B */
if (ac97->id == AC97_ID_CM9761_82) {
@@ -2032,7 +2192,8 @@ int patch_cm9761(ac97_t *ac97)
ac97->ext_id |= AC97_EI_SPDIF;
/* to be sure: we overwrite the ext status bits */
snd_ac97_write_cache(ac97, AC97_EXTENDED_STATUS, 0x05c0);
- snd_ac97_write_cache(ac97, AC97_CM9761_SPDIF_CTRL, 0x0209);
+ /* Don't set 0x0200 here. This results in the silent analog output */
+ snd_ac97_write_cache(ac97, AC97_CM9761_SPDIF_CTRL, 0x0009);
ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000; /* 48k only */
/* set-up multi channel */
@@ -2057,8 +2218,10 @@ int patch_cm9761(ac97_t *ac97)
val = 0x0214;
else
val = 0x321c;
- snd_ac97_write_cache(ac97, AC97_CM9761_MULTI_CHAN, val);
#endif
+ val = snd_ac97_read(ac97, AC97_CM9761_MULTI_CHAN);
+ val |= (1 << 4); /* front on */
+ snd_ac97_write_cache(ac97, AC97_CM9761_MULTI_CHAN, val);
/* FIXME: set up GPIO */
snd_ac97_write_cache(ac97, 0x70, 0x0100);
diff --git a/sound/pci/ac97/ac97_patch.h b/sound/pci/ac97/ac97_patch.h
index 641b0be889ead..6db51c96f5d01 100644
--- a/sound/pci/ac97/ac97_patch.h
+++ b/sound/pci/ac97/ac97_patch.h
@@ -28,6 +28,7 @@ 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);
diff --git a/sound/pci/ac97/ac97_pcm.c b/sound/pci/ac97/ac97_pcm.c
index d8cf2c5d79919..dd289b9512e13 100644
--- a/sound/pci/ac97/ac97_pcm.c
+++ b/sound/pci/ac97/ac97_pcm.c
@@ -553,7 +553,7 @@ int snd_ac97_pcm_open(struct ac97_pcm *pcm, unsigned int rate,
{
ac97_bus_t *bus;
int i, cidx, r, ok_flag;
- unsigned int reg_ok = 0;
+ unsigned int reg_ok[4] = {0,0,0,0};
unsigned char reg;
int err = 0;
@@ -602,14 +602,14 @@ int snd_ac97_pcm_open(struct ac97_pcm *pcm, unsigned int rate,
snd_printk(KERN_ERR "invalid AC97 slot %i?\n", i);
continue;
}
- if (reg_ok & (1 << (reg - AC97_PCM_FRONT_DAC_RATE)))
+ if (reg_ok[cidx] & (1 << (reg - AC97_PCM_FRONT_DAC_RATE)))
continue;
//printk(KERN_DEBUG "setting ac97 reg 0x%x to rate %d\n", reg, rate);
err = snd_ac97_set_rate(pcm->r[r].codec[cidx], reg, rate);
if (err < 0)
snd_printk(KERN_ERR "error in snd_ac97_set_rate: cidx=%d, reg=0x%x, rate=%d, err=%d\n", cidx, reg, rate, err);
else
- reg_ok |= (1 << (reg - AC97_PCM_FRONT_DAC_RATE));
+ reg_ok[cidx] |= (1 << (reg - AC97_PCM_FRONT_DAC_RATE));
}
}
}
diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c
index b58de44409047..984d5d4ba4e15 100644
--- a/sound/pci/ali5451/ali5451.c
+++ b/sound/pci/ali5451/ali5451.c
@@ -188,7 +188,7 @@ typedef struct snd_ali_channel_control {
struct snd_ali_stru_voice {
unsigned int number;
- int use: 1,
+ unsigned int use: 1,
pcm: 1,
midi: 1,
mode: 1,
@@ -199,7 +199,7 @@ struct snd_ali_stru_voice {
snd_pcm_substream_t *substream;
snd_ali_voice_t *extra;
- int running: 1;
+ unsigned int running: 1;
int eso; /* final ESO value for channel */
int count; /* runtime->period_size */
@@ -1894,7 +1894,7 @@ static int __devinit snd_ali_mixer(ali_t * codec)
}
#ifdef CONFIG_PM
-static int ali_suspend(snd_card_t *card, unsigned int state)
+static int ali_suspend(snd_card_t *card, pm_message_t state)
{
ali_t *chip = card->pm_private_data;
ali_image_t *im;
@@ -1936,7 +1936,7 @@ static int ali_suspend(snd_card_t *card, unsigned int state)
return 0;
}
-static int ali_resume(snd_card_t *card, unsigned int state)
+static int ali_resume(snd_card_t *card)
{
ali_t *chip = card->pm_private_data;
ali_image_t *im;
diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c
index 7be0f0d6d0689..f1a5f5723ee6b 100644
--- a/sound/pci/als4000.c
+++ b/sound/pci/als4000.c
@@ -104,8 +104,7 @@ typedef struct {
struct pci_dev *pci;
unsigned long gcr;
#ifdef SUPPORT_JOYSTICK
- struct gameport gameport;
- struct resource *res_joystick;
+ struct gameport *gameport;
#endif
} snd_card_als4000_t;
@@ -566,21 +565,80 @@ static void __devinit snd_als4000_configure(sb_t *chip)
spin_unlock_irq(&chip->reg_lock);
}
+#ifdef SUPPORT_JOYSTICK
+static int __devinit snd_als4000_create_gameport(snd_card_als4000_t *acard, int dev)
+{
+ struct gameport *gp;
+ struct resource *r;
+ int io_port;
+
+ if (joystick_port[dev] == 0)
+ return -ENODEV;
+
+ if (joystick_port[dev] == 1) { /* auto-detect */
+ for (io_port = 0x200; io_port <= 0x218; io_port += 8) {
+ r = request_region(io_port, 8, "ALS4000 gameport");
+ if (r)
+ break;
+ }
+ } else {
+ io_port = joystick_port[dev];
+ r = request_region(io_port, 8, "ALS4000 gameport");
+ }
+
+ if (!r) {
+ printk(KERN_WARNING "als4000: cannot reserve joystick ports\n");
+ return -EBUSY;
+ }
+
+ acard->gameport = gp = gameport_allocate_port();
+ if (!gp) {
+ printk(KERN_ERR "als4000: cannot allocate memory for gameport\n");
+ release_resource(r);
+ kfree_nocheck(r);
+ return -ENOMEM;
+ }
+
+ gameport_set_name(gp, "ALS4000 Gameport");
+ gameport_set_phys(gp, "pci%s/gameport0", pci_name(acard->pci));
+ gameport_set_dev_parent(gp, &acard->pci->dev);
+ gp->io = io_port;
+ gameport_set_port_data(gp, r);
+
+ /* Enable legacy joystick port */
+ snd_als4000_set_addr(acard->gcr, 0, 0, 0, 1);
+
+ gameport_register_port(acard->gameport);
+
+ return 0;
+}
+
+static void snd_als4000_free_gameport(snd_card_als4000_t *acard)
+{
+ if (acard->gameport) {
+ struct resource *r = gameport_get_port_data(acard->gameport);
+
+ gameport_unregister_port(acard->gameport);
+ acard->gameport = NULL;
+
+ snd_als4000_set_addr(acard->gcr, 0, 0, 0, 0); /* disable joystick */
+ release_resource(r);
+ kfree_nocheck(r);
+ }
+}
+#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) { }
+#endif
+
static void snd_card_als4000_free( snd_card_t *card )
{
snd_card_als4000_t * acard = (snd_card_als4000_t *)card->private_data;
+
/* make sure that interrupts are disabled */
snd_als4000_gcr_write_addr( acard->gcr, 0x8c, 0);
/* free resources */
-#ifdef SUPPORT_JOYSTICK
- if (acard->res_joystick) {
- if (acard->gameport.io)
- gameport_unregister_port(&acard->gameport);
- snd_als4000_set_addr(acard->gcr, 0, 0, 0, 0); /* disable joystick */
- release_resource(acard->res_joystick);
- kfree_nocheck(acard->res_joystick);
- }
-#endif
+ snd_als4000_free_gameport(acard);
pci_release_regions(acard->pci);
pci_disable_device(acard->pci);
}
@@ -596,7 +654,6 @@ static int __devinit snd_card_als4000_probe(struct pci_dev *pci,
opl3_t *opl3;
unsigned short word;
int err;
- int joystick = 0;
if (dev >= SNDRV_CARDS)
return -ENODEV;
@@ -640,26 +697,9 @@ static int __devinit snd_card_als4000_probe(struct pci_dev *pci,
acard->gcr = gcr;
card->private_free = snd_card_als4000_free;
- /* disable all legacy ISA stuff except for joystick */
-#ifdef SUPPORT_JOYSTICK
- if (joystick_port[dev] == 1) {
- /* auto-detect */
- long p;
- for (p = 0x200; p <= 0x218; p += 8) {
- if ((acard->res_joystick = request_region(p, 8, "ALS4000 gameport")) != NULL) {
- joystick_port[dev] = p;
- break;
- }
- }
- } else if (joystick_port[dev] > 0)
- acard->res_joystick = request_region(joystick_port[dev], 8, "ALS4000 gameport");
- if (acard->res_joystick)
- joystick = joystick_port[dev];
- else
- joystick = 0;
-#endif
- snd_als4000_set_addr(gcr, 0, 0, 0, joystick);
-
+ /* disable all legacy ISA stuff */
+ snd_als4000_set_addr(acard->gcr, 0, 0, 0, 0);
+
if ((err = snd_sbdsp_create(card,
gcr + 0x10,
pci->irq,
@@ -711,12 +751,7 @@ static int __devinit snd_card_als4000_probe(struct pci_dev *pci,
}
}
-#ifdef SUPPORT_JOYSTICK
- if (acard->res_joystick) {
- acard->gameport.io = joystick;
- gameport_register_port(&acard->gameport);
- }
-#endif
+ snd_als4000_create_gameport(acard, dev);
if ((err = snd_card_register(card)) < 0) {
snd_card_free(card);
diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c
index 758bc99c34909..6b04c0acc6f72 100644
--- a/sound/pci/atiixp.c
+++ b/sound/pci/atiixp.c
@@ -250,6 +250,7 @@ struct snd_atiixp_dma {
int running;
int pcm_open_flag;
int ac97_pcm_type; /* index # of ac97_pcm to access, -1 = not used */
+ unsigned int saved_curptr;
};
/*
@@ -1375,6 +1376,8 @@ static int __devinit snd_atiixp_mixer_new(atiixp_t *chip, int clock, const char
ac97.pci = chip->pci;
ac97.num = i;
ac97.scaps = AC97_SCAP_SKIP_MODEM;
+ if (! chip->spdif_over_aclink)
+ ac97.scaps |= AC97_SCAP_NO_SPDIF;
if ((err = snd_ac97_mixer(pbus, &ac97, &chip->ac97[i])) < 0) {
chip->ac97[i] = NULL; /* to be sure */
snd_printdd("atiixp: codec %d not available for audio\n", i);
@@ -1398,14 +1401,18 @@ 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, unsigned int state)
+static int snd_atiixp_suspend(snd_card_t *card, pm_message_t state)
{
atiixp_t *chip = card->pm_private_data;
int i;
for (i = 0; i < NUM_ATI_PCMDEVS; i++)
- if (chip->pcmdevs[i])
+ if (chip->pcmdevs[i]) {
+ atiixp_dma_t *dma = &chip->dmas[i];
+ if (dma->substream && dma->running)
+ 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]);
@@ -1417,7 +1424,7 @@ static int snd_atiixp_suspend(snd_card_t *card, unsigned int state)
return 0;
}
-static int snd_atiixp_resume(snd_card_t *card, unsigned int state)
+static int snd_atiixp_resume(snd_card_t *card)
{
atiixp_t *chip = card->pm_private_data;
int i;
@@ -1433,6 +1440,17 @@ static int snd_atiixp_resume(snd_card_t *card, unsigned int state)
if (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];
+ if (dma->substream && dma->running) {
+ dma->ops->enable_dma(chip, 1);
+ 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);
+ }
+ }
+
return 0;
}
#endif /* CONFIG_PM */
diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c
index e55a7c6bdde95..5d3e537339f9c 100644
--- a/sound/pci/atiixp_modem.c
+++ b/sound/pci/atiixp_modem.c
@@ -39,7 +39,7 @@ MODULE_DESCRIPTION("ATI IXP MC97 controller");
MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("{{ATI,IXP150/200/250}}");
-static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
+static int index[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = -2}; /* Exclude the first card */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
static int ac97_clock[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 48000};
@@ -606,21 +606,20 @@ static snd_pcm_uframes_t snd_atiixp_pcm_pointer(snd_pcm_substream_t *substream)
snd_pcm_runtime_t *runtime = substream->runtime;
atiixp_dma_t *dma = (atiixp_dma_t *)runtime->private_data;
unsigned int curptr;
+ int timeout = 1000;
- spin_lock(&chip->reg_lock);
- curptr = readl(chip->remap_addr + dma->ops->dt_cur);
- if (curptr < dma->buf_addr) {
- snd_printdd("curptr = %x, base = %x\n", curptr, dma->buf_addr);
- curptr = 0;
- } else {
+ while (timeout--) {
+ curptr = readl(chip->remap_addr + dma->ops->dt_cur);
+ if (curptr < dma->buf_addr)
+ continue;
curptr -= dma->buf_addr;
- if (curptr >= dma->buf_bytes) {
- snd_printdd("curptr = %x, size = %x\n", curptr, dma->buf_bytes);
- curptr = 0;
- }
+ if (curptr >= dma->buf_bytes)
+ continue;
+ return bytes_to_frames(runtime, curptr);
}
- spin_unlock(&chip->reg_lock);
- return bytes_to_frames(runtime, curptr);
+ snd_printd("atiixp-modem: invalid DMA pointer read 0x%x (buf=%x)\n",
+ readl(chip->remap_addr + dma->ops->dt_cur), dma->buf_addr);
+ return 0;
}
/*
@@ -1108,7 +1107,7 @@ static int __devinit snd_atiixp_mixer_new(atiixp_t *chip, int clock)
/*
* power management
*/
-static int snd_atiixp_suspend(snd_card_t *card, unsigned int state)
+static int snd_atiixp_suspend(snd_card_t *card, pm_message_t state)
{
atiixp_t *chip = card->pm_private_data;
int i;
@@ -1127,7 +1126,7 @@ static int snd_atiixp_suspend(snd_card_t *card, unsigned int state)
return 0;
}
-static int snd_atiixp_resume(snd_card_t *card, unsigned int state)
+static int snd_atiixp_resume(snd_card_t *card)
{
atiixp_t *chip = card->pm_private_data;
int i;
diff --git a/sound/pci/au88x0/au88x0.c b/sound/pci/au88x0/au88x0.c
index 7ce2e7631217e..889b4a1a51a1a 100644
--- a/sound/pci/au88x0/au88x0.c
+++ b/sound/pci/au88x0/au88x0.c
@@ -290,10 +290,9 @@ snd_vortex_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
snd_card_free(card);
return err;
}
- if ((err = vortex_gameport_register(chip)) < 0) {
- snd_card_free(card);
- return err;
- }
+
+ vortex_gameport_register(chip);
+
#if 0
if (snd_seq_device_new(card, 1, SNDRV_SEQ_DEV_ID_VORTEX_SYNTH,
sizeof(snd_vortex_synth_arg_t), &wave) < 0
diff --git a/sound/pci/au88x0/au88x0.h b/sound/pci/au88x0/au88x0.h
index d573d9c171b1e..ee1ede1979f63 100644
--- a/sound/pci/au88x0/au88x0.h
+++ b/sound/pci/au88x0/au88x0.h
@@ -272,7 +272,7 @@ static void vortex_Vort3D_InitializeSource(a3dsrc_t * a, int en);
/* Driver stuff. */
static int __devinit vortex_gameport_register(vortex_t * card);
-static int __devexit vortex_gameport_unregister(vortex_t * card);
+static void vortex_gameport_unregister(vortex_t * card);
#ifndef CHIP_AU8820
static int __devinit vortex_eq_init(vortex_t * vortex);
static int __devexit vortex_eq_free(vortex_t * vortex);
diff --git a/sound/pci/au88x0/au88x0_core.c b/sound/pci/au88x0/au88x0_core.c
index 772bc61246503..f0eda4bbbb395 100644
--- a/sound/pci/au88x0/au88x0_core.c
+++ b/sound/pci/au88x0/au88x0_core.c
@@ -2480,7 +2480,8 @@ static void vortex_codec_init(vortex_t * vortex)
int i;
for (i = 0; i < 32; i++) {
- hwwrite(vortex->mmio, (VORTEX_CODEC_CHN + (i << 2)), 0);
+ /* the windows driver writes -i, so we write -i */
+ hwwrite(vortex->mmio, (VORTEX_CODEC_CHN + (i << 2)), -i);
msleep(2);
}
if (0) {
@@ -2502,7 +2503,7 @@ static void vortex_codec_init(vortex_t * vortex)
hwwrite(vortex->mmio, VORTEX_CODEC_CTRL, 0x00e8);
}
for (i = 0; i < 32; i++) {
- hwwrite(vortex->mmio, (VORTEX_CODEC_CHN + (i << 2)), 0);
+ hwwrite(vortex->mmio, (VORTEX_CODEC_CHN + (i << 2)), -i);
msleep(5);
}
hwwrite(vortex->mmio, VORTEX_CODEC_CTRL, 0xe8);
diff --git a/sound/pci/au88x0/au88x0_game.c b/sound/pci/au88x0/au88x0_game.c
index d47bff1eb88c0..a07d1deba3227 100644
--- a/sound/pci/au88x0/au88x0_game.c
+++ b/sound/pci/au88x0/au88x0_game.c
@@ -44,20 +44,20 @@
static unsigned char vortex_game_read(struct gameport *gameport)
{
- vortex_t *vortex = gameport->driver;
+ vortex_t *vortex = gameport_get_port_data(gameport);
return hwread(vortex->mmio, VORTEX_GAME_LEGACY);
}
static void vortex_game_trigger(struct gameport *gameport)
{
- vortex_t *vortex = gameport->driver;
+ vortex_t *vortex = gameport_get_port_data(gameport);
hwwrite(vortex->mmio, VORTEX_GAME_LEGACY, 0xff);
}
static int
vortex_game_cooked_read(struct gameport *gameport, int *axes, int *buttons)
{
- vortex_t *vortex = gameport->driver;
+ vortex_t *vortex = gameport_get_port_data(gameport);
int i;
*buttons = (~hwread(vortex->mmio, VORTEX_GAME_LEGACY) >> 4) & 0xf;
@@ -73,7 +73,7 @@ vortex_game_cooked_read(struct gameport *gameport, int *axes, int *buttons)
static int vortex_game_open(struct gameport *gameport, int mode)
{
- vortex_t *vortex = gameport->driver;
+ vortex_t *vortex = gameport_get_port_data(gameport);
switch (mode) {
case GAMEPORT_MODE_COOKED:
@@ -94,40 +94,42 @@ static int vortex_game_open(struct gameport *gameport, int mode)
return 0;
}
-static int vortex_gameport_register(vortex_t * vortex)
+static int __devinit vortex_gameport_register(vortex_t * vortex)
{
- if ((vortex->gameport = kcalloc(1, sizeof(struct gameport), GFP_KERNEL)) == NULL) {
- return -1;
+ struct gameport *gp;
+
+ vortex->gameport = gp = gameport_allocate_port();
+ if (!gp) {
+ printk(KERN_ERR "vortex: cannot allocate memory for gameport\n");
+ return -ENOMEM;
};
-
- vortex->gameport->driver = vortex;
- vortex->gameport->fuzz = 64;
- vortex->gameport->read = vortex_game_read;
- vortex->gameport->trigger = vortex_game_trigger;
- vortex->gameport->cooked_read = vortex_game_cooked_read;
- vortex->gameport->open = vortex_game_open;
+ gameport_set_name(gp, "AU88x0 Gameport");
+ gameport_set_phys(gp, "pci%s/gameport0", pci_name(vortex->pci_dev));
+ gameport_set_dev_parent(gp, &vortex->pci_dev->dev);
+
+ gp->read = vortex_game_read;
+ gp->trigger = vortex_game_trigger;
+ gp->cooked_read = vortex_game_cooked_read;
+ gp->open = vortex_game_open;
+
+ gameport_set_port_data(gp, vortex);
+ gp->fuzz = 64;
- gameport_register_port((struct gameport *)vortex->gameport);
+ gameport_register_port(gp);
-/* printk(KERN_INFO "gameport%d: %s at speed %d kHz\n",
- vortex->gameport->number, vortex->pci_dev->name, vortex->gameport->speed);
-*/
return 0;
}
-static int vortex_gameport_unregister(vortex_t * vortex)
+static void vortex_gameport_unregister(vortex_t * vortex)
{
- if (vortex->gameport != NULL) {
+ if (vortex->gameport) {
gameport_unregister_port(vortex->gameport);
- kfree(vortex->gameport);
+ vortex->gameport = NULL;
}
- return 0;
}
#else
-
-static inline int vortex_gameport_register(vortex_t * vortex) { return 0; }
-static inline int vortex_gameport_unregister(vortex_t * vortex) { return 0; }
-
+static inline int vortex_gameport_register(vortex_t * vortex) { return -ENOSYS; }
+static inline void vortex_gameport_unregister(vortex_t * vortex) { }
#endif
diff --git a/sound/pci/au88x0/au88x0_mixer.c b/sound/pci/au88x0/au88x0_mixer.c
index 95ed26ead5c51..86e27d695c375 100644
--- a/sound/pci/au88x0/au88x0_mixer.c
+++ b/sound/pci/au88x0/au88x0_mixer.c
@@ -26,6 +26,7 @@ static int __devinit snd_vortex_mixer(vortex_t * vortex)
memset(&ac97, 0, sizeof(ac97));
// Intialize AC97 codec stuff.
ac97.private_data = vortex;
+ ac97.scaps = AC97_SCAP_NO_SPDIF;
err = snd_ac97_mixer(pbus, &ac97, &vortex->codec);
vortex->isquad = ((vortex->codec == NULL) ? 0 : (vortex->codec->ext_id&0x80));
return err;
diff --git a/sound/pci/au88x0/au88x0_pcm.c b/sound/pci/au88x0/au88x0_pcm.c
index 066e6c698a721..04dcefd8b8ff0 100644
--- a/sound/pci/au88x0/au88x0_pcm.c
+++ b/sound/pci/au88x0/au88x0_pcm.c
@@ -20,7 +20,7 @@
* Supports ADB and WT DMA. Unfortunately, WT channels do not run yet.
* It remains stuck,and DMA transfers do not happen.
*/
-
+#include <sound/asoundef.h>
#include <sound/driver.h>
#include <linux/time.h>
#include <sound/core.h>
@@ -431,61 +431,77 @@ 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 char *texts[] = { "32000", "44100", "48000" };
- uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+static int snd_vortex_spdif_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
uinfo->count = 1;
- uinfo->value.enumerated.items = 3;
- if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
- uinfo->value.enumerated.item =
- uinfo->value.enumerated.items - 1;
- strcpy(uinfo->value.enumerated.name,
- texts[uinfo->value.enumerated.item]);
return 0;
}
-static int
-snd_vortex_spdif_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
-{
- vortex_t *vortex = snd_kcontrol_chip(kcontrol);
- if (vortex->spdif_sr == 32000)
- ucontrol->value.enumerated.item[0] = 0;
- if (vortex->spdif_sr == 44100)
- ucontrol->value.enumerated.item[0] = 1;
- if (vortex->spdif_sr == 48000)
- ucontrol->value.enumerated.item[0] = 2;
+static int snd_vortex_spdif_mask_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+ ucontrol->value.iec958.status[0] = 0xff;
+ ucontrol->value.iec958.status[1] = 0xff;
+ ucontrol->value.iec958.status[2] = 0xff;
+ ucontrol->value.iec958.status[3] = IEC958_AES3_CON_FS;
return 0;
}
-static int
-snd_vortex_spdif_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+
+static int snd_vortex_spdif_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
vortex_t *vortex = snd_kcontrol_chip(kcontrol);
- static unsigned int sr[3] = { 32000, 44100, 48000 };
+ ucontrol->value.iec958.status[0] = 0x00;
+ ucontrol->value.iec958.status[1] = IEC958_AES1_CON_ORIGINAL|IEC958_AES1_CON_DIGDIGCONV_ID;
+ ucontrol->value.iec958.status[2] = 0x00;
+ switch (vortex->spdif_sr) {
+ case 32000: ucontrol->value.iec958.status[3] = IEC958_AES3_CON_FS_32000; break;
+ case 44100: ucontrol->value.iec958.status[3] = IEC958_AES3_CON_FS_44100; break;
+ case 48000: ucontrol->value.iec958.status[3] = IEC958_AES3_CON_FS_48000; break;
+ }
+ return 0;
+}
- //printk("vortex: spdif sr = %d\n", ucontrol->value.enumerated.item[0]);
- vortex->spdif_sr = sr[ucontrol->value.enumerated.item[0] % 3];
- vortex_spdif_init(vortex,
- sr[ucontrol->value.enumerated.item[0] % 3], 1);
+static int snd_vortex_spdif_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+ vortex_t *vortex = snd_kcontrol_chip(kcontrol);
+ int spdif_sr = 48000;
+ switch (ucontrol->value.iec958.status[3] & IEC958_AES3_CON_FS) {
+ case IEC958_AES3_CON_FS_32000: spdif_sr = 32000; break;
+ case IEC958_AES3_CON_FS_44100: spdif_sr = 44100; break;
+ case IEC958_AES3_CON_FS_48000: spdif_sr = 48000; break;
+ }
+ if (spdif_sr == vortex->spdif_sr)
+ return 0;
+ vortex->spdif_sr = spdif_sr;
+ vortex_spdif_init(vortex, vortex->spdif_sr, 1);
return 1;
}
-static snd_kcontrol_new_t vortex_spdif_kcontrol __devinitdata = {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "SPDIF SR",
- .index = 0,
- .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
- .private_value = 0,
- .info = snd_vortex_spdif_info,
- .get = snd_vortex_spdif_get,
- .put = snd_vortex_spdif_put
+
+/* spdif controls */
+static snd_kcontrol_new_t snd_vortex_mixer_spdif[] __devinitdata = {
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
+ .info = snd_vortex_spdif_info,
+ .get = snd_vortex_spdif_get,
+ .put = snd_vortex_spdif_put,
+ },
+ {
+ .access = SNDRV_CTL_ELEM_ACCESS_READ,
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK),
+ .info = snd_vortex_spdif_info,
+ .get = snd_vortex_spdif_mask_get
+ },
};
/* 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;
+ int i;
int err, nr_capt;
if ((chip == 0) || (idx < 0) || (idx > VORTEX_PCM_LAST))
@@ -520,13 +536,13 @@ static int __devinit snd_vortex_new_pcm(vortex_t * chip, int idx, int nr)
0x10000, 0x10000);
if (VORTEX_PCM_TYPE(pcm) == VORTEX_PCM_SPDIF) {
- snd_kcontrol_t *kcontrol;
-
- if ((kcontrol =
- snd_ctl_new1(&vortex_spdif_kcontrol, chip)) == NULL)
- return -ENOMEM;
- if ((err = snd_ctl_add(chip->card, kcontrol)) < 0)
- return err;
+ for (i = 0; i < ARRAY_SIZE(snd_vortex_mixer_spdif); i++) {
+ kctl = snd_ctl_new1(&snd_vortex_mixer_spdif[i], chip);
+ if (!kctl)
+ return -ENOMEM;
+ if ((err = snd_ctl_add(chip->card, kctl)) < 0)
+ return err;
+ }
}
return 0;
}
diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c
index 612794256ea4b..b8ae534125c1e 100644
--- a/sound/pci/azt3328.c
+++ b/sound/pci/azt3328.c
@@ -160,19 +160,19 @@ MODULE_SUPPORTED_DEVICE("{{Aztech,AZF3328}}");
#endif
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
-static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
-#ifdef SUPPORT_JOYSTICK
-static int joystick[SNDRV_CARDS];
-#endif
-
module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for AZF3328 soundcard.");
+
+static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
module_param_array(id, charp, NULL, 0444);
MODULE_PARM_DESC(id, "ID string for AZF3328 soundcard.");
+
+static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
module_param_array(enable, bool, NULL, 0444);
MODULE_PARM_DESC(enable, "Enable AZF3328 soundcard.");
+
#ifdef SUPPORT_JOYSTICK
+static int joystick[SNDRV_CARDS];
module_param_array(joystick, bool, NULL, 0444);
MODULE_PARM_DESC(joystick, "Enable joystick for AZF3328 soundcard.");
#endif
@@ -189,8 +189,7 @@ struct _snd_azf3328 {
unsigned long mixer_port;
#ifdef SUPPORT_JOYSTICK
- struct gameport gameport;
- struct resource *res_joystick;
+ struct gameport *gameport;
#endif
struct pci_dev *pci;
@@ -1222,6 +1221,63 @@ static int __devinit snd_azf3328_pcm(azf3328_t *chip, int device)
/******************************************************************/
+#ifdef SUPPORT_JOYSTICK
+static int __devinit snd_azf3328_config_joystick(azf3328_t *chip, int dev)
+{
+ struct gameport *gp;
+ struct resource *r;
+
+ if (!joystick[dev])
+ return -ENODEV;
+
+ if (!(r = request_region(0x200, 8, "AZF3328 gameport"))) {
+ printk(KERN_WARNING "azt3328: cannot reserve joystick ports\n");
+ return -EBUSY;
+ }
+
+ chip->gameport = gp = gameport_allocate_port();
+ if (!gp) {
+ printk(KERN_ERR "azt3328: cannot allocate memory for gameport\n");
+ release_resource(r);
+ kfree_nocheck(r);
+ return -ENOMEM;
+ }
+
+ gameport_set_name(gp, "AZF3328 Gameport");
+ gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci));
+ gameport_set_dev_parent(gp, &chip->pci->dev);
+ gp->io = 0x200;
+ gameport_set_port_data(gp, r);
+
+ snd_azf3328_io2_write(chip, IDX_IO2_LEGACY_ADDR,
+ snd_azf3328_io2_read(chip, IDX_IO2_LEGACY_ADDR) | LEGACY_JOY);
+
+ gameport_register_port(chip->gameport);
+
+ return 0;
+}
+
+static void snd_azf3328_free_joystick(azf3328_t *chip)
+{
+ if (chip->gameport) {
+ struct resource *r = gameport_get_port_data(chip->gameport);
+
+ gameport_unregister_port(chip->gameport);
+ chip->gameport = NULL;
+ /* disable gameport */
+ snd_azf3328_io2_write(chip, IDX_IO2_LEGACY_ADDR,
+ snd_azf3328_io2_read(chip, IDX_IO2_LEGACY_ADDR) & ~LEGACY_JOY);
+ release_resource(r);
+ kfree_nocheck(r);
+ }
+}
+#else
+static inline int snd_azf3328_config_joystick(azf3328_t *chip, int dev) { return -ENOSYS; }
+static inline void snd_azf3328_free_joystick(azf3328_t *chip) { }
+#endif
+
+/******************************************************************/
+
static int snd_azf3328_free(azf3328_t *chip)
{
if (chip->irq < 0)
@@ -1236,16 +1292,7 @@ static int snd_azf3328_free(azf3328_t *chip)
synchronize_irq(chip->irq);
__end_hw:
-#ifdef SUPPORT_JOYSTICK
- if (chip->res_joystick) {
- gameport_unregister_port(&chip->gameport);
- /* disable gameport */
- snd_azf3328_io2_write(chip, IDX_IO2_LEGACY_ADDR,
- snd_azf3328_io2_read(chip, IDX_IO2_LEGACY_ADDR) & ~LEGACY_JOY);
- release_resource(chip->res_joystick);
- kfree_nocheck(chip->res_joystick);
- }
-#endif
+ snd_azf3328_free_joystick(chip);
if (chip->irq >= 0)
free_irq(chip->irq, (void *)chip);
pci_release_regions(chip->pci);
@@ -1373,28 +1420,6 @@ static int __devinit snd_azf3328_create(snd_card_t * card,
return 0;
}
-#ifdef SUPPORT_JOYSTICK
-static void __devinit snd_azf3328_config_joystick(azf3328_t *chip, int joystick)
-{
- unsigned char val;
-
- if (joystick == 1) {
- if ((chip->res_joystick = request_region(0x200, 8, "AZF3328 gameport")) != NULL)
- chip->gameport.io = 0x200;
- }
-
- val = inb(chip->io2_port + IDX_IO2_LEGACY_ADDR);
- if (chip->res_joystick)
- val |= LEGACY_JOY;
- else
- val &= ~LEGACY_JOY;
-
- outb(val, chip->io2_port + IDX_IO2_LEGACY_ADDR);
- if (chip->res_joystick)
- gameport_register_port(&chip->gameport);
-}
-#endif
-
static int __devinit snd_azf3328_probe(struct pci_dev *pci,
const struct pci_device_id *pci_id)
{
@@ -1465,9 +1490,9 @@ static int __devinit snd_azf3328_probe(struct pci_dev *pci,
"azt3328: Feel free to contact hw7oshyuv3001@sneakemail.com for bug reports etc.!\n");
#endif
-#ifdef SUPPORT_JOYSTICK
- snd_azf3328_config_joystick(chip, joystick[dev]);
-#endif
+ if (snd_azf3328_config_joystick(chip, dev) < 0)
+ snd_azf3328_io2_write(chip, IDX_IO2_LEGACY_ADDR,
+ snd_azf3328_io2_read(chip, IDX_IO2_LEGACY_ADDR) & ~LEGACY_JOY);
pci_set_drvdata(pci, card);
dev++;
diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c
index 3b7a31f3665b3..89a7ffe5e7d77 100644
--- a/sound/pci/bt87x.c
+++ b/sound/pci/bt87x.c
@@ -41,7 +41,7 @@ MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("{{Brooktree,Bt878},"
"{Brooktree,Bt879}}");
-static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
+static int index[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = -2}; /* Exclude the first card */
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 digital_rate[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = 0 }; /* digital input rate */
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c
index a6f3fa5dc12b5..82533b45bc8cd 100644
--- a/sound/pci/ca0106/ca0106_main.c
+++ b/sound/pci/ca0106/ca0106_main.c
@@ -1,7 +1,7 @@
/*
* Copyright (c) 2004 James Courtier-Dutton <James@superbug.demon.co.uk>
* Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit
- * Version: 0.0.21
+ * Version: 0.0.22
*
* FEATURES currently supported:
* Front, Rear and Center/LFE.
@@ -75,6 +75,8 @@
* 0.0.21
* Add 4 capture channels. (SPDIF only comes in on channel 0. )
* Add SPDIF capture using optional digital I/O module for SB Live 24bit. (Analog capture does not yet work.)
+ * 0.0.22
+ * Add support for MSI K8N Diamond Motherboard with onboard SB Live 24bit without AC97. From kiksen, bug #901
*
* BUGS:
* Some stability problems when unloading the snd-ca0106 kernel module.
@@ -169,6 +171,7 @@ static ca0106_names_t ca0106_chip_names[] = {
{ 0x10051102, "AudigyLS [SB0310b]"} , /* Unknown AudigyLS that also says SB0310 on it */
{ 0x10061102, "Live! 7.1 24bit [SB0410]"} , /* New Sound Blaster Live! 7.1 24bit. This does not have an AC97. 53SB041000001 */
{ 0x10071102, "Live! 7.1 24bit [SB0413]"} , /* New Dell Sound Blaster Live! 7.1 24bit. This does not have an AC97. */
+ { 0x10091462, "MSI K8N Diamond MB [SB0438]"}, /* MSI K8N Diamond Motherboard with onboard SB Live 24bit without AC97 */
{ 0, "AudigyLS [Unknown]" }
};
@@ -184,9 +187,9 @@ static snd_pcm_hardware_t snd_ca0106_playback_hw = {
.rate_max = 192000,
.channels_min = 2, //1,
.channels_max = 2, //6,
- .buffer_bytes_max = (32*1024),
+ .buffer_bytes_max = ((65536 - 64) * 8),
.period_bytes_min = 64,
- .period_bytes_max = (16*1024),
+ .period_bytes_max = (65536 - 64),
.periods_min = 2,
.periods_max = 8,
.fifo_size = 0,
@@ -203,9 +206,9 @@ static snd_pcm_hardware_t snd_ca0106_capture_hw = {
.rate_max = 48000,
.channels_min = 2,
.channels_max = 2,
- .buffer_bytes_max = (32*1024),
+ .buffer_bytes_max = ((65536 - 64) * 8),
.period_bytes_min = 64,
- .period_bytes_max = (16*1024),
+ .period_bytes_max = (65536 - 64),
.periods_min = 2,
.periods_max = 2,
.fifo_size = 0,
@@ -510,6 +513,8 @@ static int snd_ca0106_pcm_prepare_playback(snd_pcm_substream_t *substream)
snd_ca0106_ptr_write(emu, PLAYBACK_LIST_PTR, channel, 0);
snd_ca0106_ptr_write(emu, PLAYBACK_DMA_ADDR, channel, runtime->dma_addr);
snd_ca0106_ptr_write(emu, PLAYBACK_PERIOD_SIZE, channel, frames_to_bytes(runtime, runtime->period_size)<<16); // buffer size in bytes
+ /* FIXME test what 0 bytes does. */
+ snd_ca0106_ptr_write(emu, PLAYBACK_PERIOD_SIZE, channel, 0); // buffer size in bytes
snd_ca0106_ptr_write(emu, PLAYBACK_POINTER, channel, 0);
snd_ca0106_ptr_write(emu, 0x07, channel, 0x0);
snd_ca0106_ptr_write(emu, 0x08, channel, 0);
@@ -1133,7 +1138,9 @@ static int __devinit snd_ca0106_create(snd_card_t *card,
snd_ca0106_ptr_write(chip, CAPTURE_SOURCE, 0x0, 0x333300e4); /* Select MIC, Line in, TAD in, AUX in */
chip->capture_source = 3; /* Set CAPTURE_SOURCE */
- if ((chip->serial == 0x10061102) || (chip->serial == 0x10071102) ) { /* The SB0410 and SB0413 use GPIO differently. */
+ if ((chip->serial == 0x10061102) ||
+ (chip->serial == 0x10071102) ||
+ (chip->serial == 0x10091462)) { /* The SB0410 and SB0413 use GPIO differently. */
/* FIXME: Still need to find out what the other GPIO bits do. E.g. For digital spdif out. */
outl(0x0, chip->port+GPIO);
//outl(0x00f0e000, chip->port+GPIO); /* Analog */
@@ -1200,7 +1207,9 @@ static int __devinit snd_ca0106_probe(struct pci_dev *pci,
snd_card_free(card);
return err;
}
- if ((chip->serial != 0x10061102) && (chip->serial != 0x10071102) ) { /* The SB0410 and SB0413 do not have an ac97 chip. */
+ if ((chip->serial != 0x10061102) &&
+ (chip->serial != 0x10071102) &&
+ (chip->serial != 0x10091462) ) { /* The SB0410 and SB0413 do not have an ac97 chip. */
if ((err = snd_ca0106_ac97(chip)) < 0) {
snd_card_free(card);
return err;
diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c
index 17fbed0f06419..113208fbde1bc 100644
--- a/sound/pci/cmipci.c
+++ b/sound/pci/cmipci.c
@@ -156,6 +156,8 @@ MODULE_PARM_DESC(joystick_port, "Joystick port address.");
#define CM_CHIP_MASK2 0xff000000
#define CM_CHIP_039 0x04000000
#define CM_CHIP_039_6CH 0x01000000
+#define CM_CHIP_055 0x08000000
+#define CM_CHIP_8768 0x20000000
#define CM_TDMA_INT_EN 0x00040000
#define CM_CH1_INT_EN 0x00020000
#define CM_CH0_INT_EN 0x00010000
@@ -328,6 +330,13 @@ 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_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 */
+#define CM_ADC2SPDIF 0x08 /* ADC output to SPDIF/OUT */
+#define CM_SHAREADC 0x04 /* DAC in ADC as Center/LFE */
+#define CM_REALTCMP 0x02 /* monitor the CMPL/CMPR of ADC */
+#define CM_INVLRCK 0x01 /* invert ZVPORT's LRCK */
/*
* size of i/o region
@@ -458,7 +467,7 @@ struct snd_stru_cmipci {
int opened[2]; /* open mode */
struct semaphore open_mutex;
- int mixer_insensitive: 1;
+ unsigned int mixer_insensitive: 1;
snd_kcontrol_t *mixer_res_ctl[CM_SAVED_MIXERS];
int mixer_res_status[CM_SAVED_MIXERS];
@@ -471,8 +480,7 @@ struct snd_stru_cmipci {
snd_rawmidi_t *rmidi;
#ifdef SUPPORT_JOYSTICK
- struct gameport gameport;
- struct resource *res_joystick;
+ struct gameport *gameport;
#endif
spinlock_t reg_lock;
@@ -674,7 +682,7 @@ static int snd_cmipci_hw_free(snd_pcm_substream_t * substream)
/*
*/
-static unsigned int hw_channels[] = {1, 2, 4, 5, 6};
+static unsigned int hw_channels[] = {1, 2, 4, 5, 6, 8};
static snd_pcm_hw_constraint_list_t hw_constraints_channels_4 = {
.count = 3,
.list = hw_channels,
@@ -685,6 +693,11 @@ static snd_pcm_hw_constraint_list_t hw_constraints_channels_6 = {
.list = hw_channels,
.mask = 0,
};
+static snd_pcm_hw_constraint_list_t 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)
{
@@ -704,13 +717,20 @@ static int set_dac_channels(cmipci_t *cm, cmipci_pcm_t *rec, int channels)
snd_cmipci_clear_bit(cm, CM_REG_CHFORMAT, CM_CHB3D5C);
snd_cmipci_set_bit(cm, CM_REG_CHFORMAT, CM_CHB3D);
}
- if (channels == 6) {
+ if (channels >= 6) {
snd_cmipci_set_bit(cm, CM_REG_LEGACY_CTRL, CM_CHB3D6C);
snd_cmipci_set_bit(cm, CM_REG_MISC_CTRL, CM_ENCENTER);
} else {
snd_cmipci_clear_bit(cm, CM_REG_LEGACY_CTRL, CM_CHB3D6C);
snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_ENCENTER);
}
+ if (cm->chip_version == 68) {
+ if (channels == 8) {
+ snd_cmipci_set_bit(cm, CM_REG_MISC_CTRL_8768, CM_CHB3D8C);
+ } else {
+ snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL_8768, CM_CHB3D8C);
+ }
+ }
spin_unlock_irq(&cm->reg_lock);
} else {
@@ -1504,6 +1524,7 @@ static int snd_cmipci_playback_open(snd_pcm_substream_t *substream)
if ((err = open_device_check(cm, CM_OPEN_PLAYBACK, substream)) < 0)
return err;
runtime->hw = snd_cmipci_playback;
+ runtime->hw.channels_max = cm->max_channels;
snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 0x10000);
cm->dig_pcm_status = cm->dig_status;
return 0;
@@ -1518,6 +1539,10 @@ static int snd_cmipci_capture_open(snd_pcm_substream_t *substream)
if ((err = open_device_check(cm, CM_OPEN_CAPTURE, substream)) < 0)
return err;
runtime->hw = snd_cmipci_capture;
+ if (cm->chip_version == 68) { // 8768 only supports 44k/48k recording
+ runtime->hw.rate_min = 41000;
+ runtime->hw.rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000;
+ }
snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 0x10000);
return 0;
}
@@ -1537,8 +1562,10 @@ static int snd_cmipci_playback2_open(snd_pcm_substream_t *substream)
runtime->hw.channels_max = cm->max_channels;
if (cm->max_channels == 4)
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, &hw_constraints_channels_4);
- else
+ else if (cm->max_channels == 6)
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, &hw_constraints_channels_6);
+ else if (cm->max_channels == 8)
+ snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, &hw_constraints_channels_8);
}
snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 0x10000);
}
@@ -2108,8 +2135,8 @@ typedef struct snd_cmipci_switch_args {
int reg; /* register index */
unsigned int mask; /* mask bits */
unsigned int mask_on; /* mask bits to turn on */
- int is_byte: 1; /* byte access? */
- int ac3_sensitive: 1; /* access forbidden during non-audio operation? */
+ unsigned int is_byte: 1; /* byte access? */
+ unsigned int ac3_sensitive: 1; /* access forbidden during non-audio operation? */
} snd_cmipci_switch_args_t;
static int snd_cmipci_uswitch_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
@@ -2346,6 +2373,11 @@ static int __devinit snd_cmipci_mixer_new(cmipci_t *cm, int pcm_spdif_device)
spin_unlock_irq(&cm->reg_lock);
for (idx = 0; idx < ARRAY_SIZE(snd_cmipci_mixers); idx++) {
+ if (cm->chip_version == 68) { // 8768 has no PCM volume
+ if (!strcmp(snd_cmipci_mixers[idx].name,
+ "PCM Playback Volume"))
+ continue;
+ }
if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_cmipci_mixers[idx], cm))) < 0)
return err;
}
@@ -2496,32 +2528,98 @@ static void __devinit query_chip(cmipci_t *cm)
}
} else {
/* check reg 0Ch, bit 26 */
- if (detect & CM_CHIP_039) {
+ if (detect & CM_CHIP_8768) {
+ cm->chip_version = 68;
+ cm->max_channels = 8;
+ cm->can_ac3_hw = 1;
+ cm->has_dual_dac = 1;
+ cm->can_multi_ch = 1;
+ } else if (detect & CM_CHIP_055) {
+ cm->chip_version = 55;
+ cm->max_channels = 6;
+ cm->can_ac3_hw = 1;
+ cm->has_dual_dac = 1;
+ cm->can_multi_ch = 1;
+ } else if (detect & CM_CHIP_039) {
cm->chip_version = 39;
- if (detect & CM_CHIP_039_6CH)
- cm->max_channels = 6;
+ if (detect & CM_CHIP_039_6CH) /* 4 or 6 channels */
+ cm->max_channels = 6;
else
cm->max_channels = 4;
cm->can_ac3_hw = 1;
cm->has_dual_dac = 1;
cm->can_multi_ch = 1;
} else {
- cm->chip_version = 55; /* 4 or 6 channels */
- cm->max_channels = 6;
- cm->can_ac3_hw = 1;
- cm->has_dual_dac = 1;
- cm->can_multi_ch = 1;
+ printk(KERN_ERR "chip %x version not supported\n", detect);
}
}
+}
- /* added -MCx suffix for chip supporting multi-channels */
- if (cm->can_multi_ch)
- sprintf(cm->card->driver + strlen(cm->card->driver),
- "-MC%d", cm->max_channels);
- else if (cm->can_ac3_sw)
- strcpy(cm->card->driver + strlen(cm->card->driver), "-SWIEC");
+#ifdef SUPPORT_JOYSTICK
+static int __devinit snd_cmipci_create_gameport(cmipci_t *cm, int dev)
+{
+ static int ports[] = { 0x201, 0x200, 0 }; /* FIXME: majority is 0x201? */
+ struct gameport *gp;
+ struct resource *r = NULL;
+ int i, io_port = 0;
+
+ if (joystick_port[dev] == 0)
+ return -ENODEV;
+
+ if (joystick_port[dev] == 1) { /* auto-detect */
+ for (i = 0; ports[i]; i++) {
+ io_port = ports[i];
+ r = request_region(io_port, 1, "CMIPCI gameport");
+ if (r)
+ break;
+ }
+ } else {
+ io_port = joystick_port[dev];
+ r = request_region(io_port, 1, "CMIPCI gameport");
+ }
+
+ if (!r) {
+ printk(KERN_WARNING "cmipci: cannot reserve joystick ports\n");
+ return -EBUSY;
+ }
+
+ cm->gameport = gp = gameport_allocate_port();
+ if (!gp) {
+ printk(KERN_ERR "cmipci: cannot allocate memory for gameport\n");
+ release_resource(r);
+ kfree_nocheck(r);
+ return -ENOMEM;
+ }
+ gameport_set_name(gp, "C-Media Gameport");
+ gameport_set_phys(gp, "pci%s/gameport0", pci_name(cm->pci));
+ gameport_set_dev_parent(gp, &cm->pci->dev);
+ gp->io = io_port;
+ gameport_set_port_data(gp, r);
+
+ snd_cmipci_set_bit(cm, CM_REG_FUNCTRL1, CM_JYSTK_EN);
+
+ gameport_register_port(cm->gameport);
+
+ return 0;
}
+static void snd_cmipci_free_gameport(cmipci_t *cm)
+{
+ if (cm->gameport) {
+ struct resource *r = gameport_get_port_data(cm->gameport);
+
+ gameport_unregister_port(cm->gameport);
+ cm->gameport = NULL;
+
+ snd_cmipci_clear_bit(cm, CM_REG_FUNCTRL1, CM_JYSTK_EN);
+ release_resource(r);
+ kfree_nocheck(r);
+ }
+}
+#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) { }
+#endif
static int snd_cmipci_free(cmipci_t *cm)
{
@@ -2541,14 +2639,8 @@ static int snd_cmipci_free(cmipci_t *cm)
free_irq(cm->irq, (void *)cm);
}
-#ifdef SUPPORT_JOYSTICK
- if (cm->res_joystick) {
- gameport_unregister_port(&cm->gameport);
- snd_cmipci_clear_bit(cm, CM_REG_FUNCTRL1, CM_JYSTK_EN);
- release_resource(cm->res_joystick);
- kfree_nocheck(cm->res_joystick);
- }
-#endif
+
+ snd_cmipci_free_gameport(cm);
pci_release_regions(cm->pci);
pci_disable_device(cm->pci);
kfree(cm);
@@ -2623,7 +2715,15 @@ static int __devinit snd_cmipci_create(snd_card_t *card, struct pci_dev *pci,
cm->max_channels = 2;
cm->do_soft_ac3 = soft_ac3[dev];
- query_chip(cm);
+ if (pci->device != PCI_DEVICE_ID_CMEDIA_CM8338A &&
+ pci->device != PCI_DEVICE_ID_CMEDIA_CM8338B)
+ query_chip(cm);
+ /* added -MCx suffix for chip supporting multi-channels */
+ if (cm->can_multi_ch)
+ sprintf(cm->card->driver + strlen(cm->card->driver),
+ "-MC%d", cm->max_channels);
+ else if (cm->can_ac3_sw)
+ strcpy(cm->card->driver + strlen(cm->card->driver), "-SWIEC");
cm->dig_status = SNDRV_PCM_DEFAULT_CON_SPDIF;
cm->dig_pcm_status = SNDRV_PCM_DEFAULT_CON_SPDIF;
@@ -2757,31 +2857,9 @@ static int __devinit snd_cmipci_create(snd_card_t *card, struct pci_dev *pci,
snd_cmipci_set_bit(cm, CM_REG_MISC_CTRL, CM_SPDIF48K|CM_SPDF_AC97);
#endif /* USE_VAR48KRATE */
-#ifdef SUPPORT_JOYSTICK
- if (joystick_port[dev] > 0) {
- if (joystick_port[dev] == 1) { /* auto-detect */
- static int ports[] = { 0x201, 0x200, 0 }; /* FIXME: majority is 0x201? */
- int i;
- for (i = 0; ports[i]; i++) {
- joystick_port[dev] = ports[i];
- cm->res_joystick = request_region(ports[i], 1, "CMIPCI gameport");
- if (cm->res_joystick)
- break;
- }
- } else {
- cm->res_joystick = request_region(joystick_port[dev], 1, "CMIPCI gameport");
- }
- }
- if (cm->res_joystick) {
- cm->gameport.io = joystick_port[dev];
- snd_cmipci_set_bit(cm, CM_REG_FUNCTRL1, CM_JYSTK_EN);
- gameport_register_port(&cm->gameport);
- } else {
- if (joystick_port[dev] > 0)
- printk(KERN_WARNING "cmipci: cannot reserve joystick ports\n");
+ if (snd_cmipci_create_gameport(cm, dev) < 0)
snd_cmipci_clear_bit(cm, CM_REG_FUNCTRL1, CM_JYSTK_EN);
- }
-#endif
+
snd_card_set_dev(card, &pci->dev);
*rcmipci = cm;
diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c
index 72831d064e406..d7e06b3caf973 100644
--- a/sound/pci/cs4281.c
+++ b/sound/pci/cs4281.c
@@ -495,7 +495,7 @@ struct snd_cs4281 {
unsigned int midcr;
unsigned int uartm;
- struct snd_cs4281_gameport *gameport;
+ struct gameport *gameport;
#ifdef CONFIG_PM
u32 suspend_regs[SUSPEND_REGISTERS];
@@ -1238,38 +1238,29 @@ static void __devinit snd_cs4281_proc_init(cs4281_t * chip)
#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
-typedef struct snd_cs4281_gameport {
- struct gameport info;
- cs4281_t *chip;
-} cs4281_gameport_t;
-
static void snd_cs4281_gameport_trigger(struct gameport *gameport)
{
- cs4281_gameport_t *gp = (cs4281_gameport_t *)gameport;
- cs4281_t *chip;
- snd_assert(gp, return);
- chip = gp->chip;
+ cs4281_t *chip = gameport_get_port_data(gameport);
+
+ snd_assert(chip, return);
snd_cs4281_pokeBA0(chip, BA0_JSPT, 0xff);
}
static unsigned char snd_cs4281_gameport_read(struct gameport *gameport)
{
- cs4281_gameport_t *gp = (cs4281_gameport_t *)gameport;
- cs4281_t *chip;
- snd_assert(gp, return 0);
- chip = gp->chip;
+ cs4281_t *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)
{
- cs4281_gameport_t *gp = (cs4281_gameport_t *)gameport;
- cs4281_t *chip;
+ cs4281_t *chip = gameport_get_port_data(gameport);
unsigned js1, js2, jst;
- snd_assert(gp, return 0);
- chip = gp->chip;
+ snd_assert(chip, return 0);
js1 = snd_cs4281_peekBA0(chip, BA0_JSC1);
js2 = snd_cs4281_peekBA0(chip, BA0_JSC2);
@@ -1282,10 +1273,12 @@ static int snd_cs4281_gameport_cooked_read(struct gameport *gameport, int *axes,
axes[2] = ((js2 & JSC2_Y2V_MASK) >> JSC2_Y2V_SHIFT) & 0xFFFF;
axes[3] = ((js2 & JSC2_X2V_MASK) >> JSC2_X2V_SHIFT) & 0xFFFF;
- for(jst=0;jst<4;++jst)
- if(axes[jst]==0xFFFF) axes[jst] = -1;
+ for (jst = 0; jst < 4; ++jst)
+ if (axes[jst] == 0xFFFF) axes[jst] = -1;
return 0;
}
+#else
+#define snd_cs4281_gameport_cooked_read NULL
#endif
static int snd_cs4281_gameport_open(struct gameport *gameport, int mode)
@@ -1303,31 +1296,43 @@ static int snd_cs4281_gameport_open(struct gameport *gameport, int mode)
return 0;
}
-static void __devinit snd_cs4281_gameport(cs4281_t *chip)
+static int __devinit snd_cs4281_create_gameport(cs4281_t *chip)
{
- cs4281_gameport_t *gp;
- gp = kmalloc(sizeof(*gp), GFP_KERNEL);
- if (! gp) {
- snd_printk(KERN_ERR "cannot allocate gameport area\n");
- return;
+ struct gameport *gp;
+
+ chip->gameport = gp = gameport_allocate_port();
+ if (!gp) {
+ printk(KERN_ERR "cs4281: cannot allocate memory for gameport\n");
+ return -ENOMEM;
}
- memset(gp, 0, sizeof(*gp));
- gp->info.open = snd_cs4281_gameport_open;
- gp->info.read = snd_cs4281_gameport_read;
- gp->info.trigger = snd_cs4281_gameport_trigger;
-#ifdef COOKED_MODE
- gp->info.cooked_read = snd_cs4281_gameport_cooked_read;
-#endif
- gp->chip = chip;
- chip->gameport = gp;
+
+ gameport_set_name(gp, "CS4281 Gameport");
+ gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci));
+ gameport_set_dev_parent(gp, &chip->pci->dev);
+ gp->open = snd_cs4281_gameport_open;
+ gp->read = snd_cs4281_gameport_read;
+ gp->trigger = snd_cs4281_gameport_trigger;
+ gp->cooked_read = snd_cs4281_gameport_cooked_read;
+ gameport_set_port_data(gp, chip);
snd_cs4281_pokeBA0(chip, BA0_JSIO, 0xFF); // ?
snd_cs4281_pokeBA0(chip, BA0_JSCTL, JSCTL_SP_MEDIUM_SLOW);
- gameport_register_port(&gp->info);
+
+ gameport_register_port(gp);
+
+ return 0;
}
+static void snd_cs4281_free_gameport(cs4281_t *chip)
+{
+ if (chip->gameport) {
+ gameport_unregister_port(chip->gameport);
+ chip->gameport = NULL;
+ }
+}
#else
-#define snd_cs4281_gameport(chip) /*NOP*/
+static inline int snd_cs4281_create_gameport(cs4281_t *chip) { return -ENOSYS; }
+static inline void snd_cs4281_free_gameport(cs4281_t *chip) { }
#endif /* CONFIG_GAMEPORT || (MODULE && CONFIG_GAMEPORT_MODULE) */
@@ -1337,12 +1342,8 @@ static void __devinit snd_cs4281_gameport(cs4281_t *chip)
static int snd_cs4281_free(cs4281_t *chip)
{
-#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
- if (chip->gameport) {
- gameport_unregister_port(&chip->gameport->info);
- kfree(chip->gameport);
- }
-#endif
+ snd_cs4281_free_gameport(chip);
+
if (chip->irq >= 0)
synchronize_irq(chip->irq);
@@ -1376,8 +1377,8 @@ static int snd_cs4281_dev_free(snd_device_t *device)
static int snd_cs4281_chip_init(cs4281_t *chip); /* defined below */
#ifdef CONFIG_PM
-static int cs4281_suspend(snd_card_t *card, unsigned int state);
-static int cs4281_resume(snd_card_t *card, unsigned int state);
+static int cs4281_suspend(snd_card_t *card, pm_message_t state);
+static int cs4281_resume(snd_card_t *card);
#endif
static int __devinit snd_cs4281_create(snd_card_t * card,
@@ -1893,9 +1894,7 @@ static irqreturn_t snd_cs4281_interrupt(int irq, void *dev_id, struct pt_regs *r
c = snd_cs4281_peekBA0(chip, BA0_MIDRP);
if ((chip->midcr & BA0_MIDCR_RIE) == 0)
continue;
- spin_unlock(&chip->reg_lock);
snd_rawmidi_receive(chip->midi_input, &c, 1);
- spin_lock(&chip->reg_lock);
}
while ((snd_cs4281_peekBA0(chip, BA0_MIDSR) & BA0_MIDSR_TBF) == 0) {
if ((chip->midcr & BA0_MIDCR_TIE) == 0)
@@ -1990,7 +1989,7 @@ static int __devinit snd_cs4281_probe(struct pci_dev *pci,
snd_card_free(card);
return err;
}
- snd_cs4281_gameport(chip);
+ snd_cs4281_create_gameport(chip);
strcpy(card->driver, "CS4281");
strcpy(card->shortname, "Cirrus Logic CS4281");
sprintf(card->longname, "%s at 0x%lx, irq %d",
@@ -2037,7 +2036,7 @@ static int saved_regs[SUSPEND_REGISTERS] = {
#define CLKCR1_CKRA 0x00010000L
-static int cs4281_suspend(snd_card_t *card, unsigned int state)
+static int cs4281_suspend(snd_card_t *card, pm_message_t state)
{
cs4281_t *chip = card->pm_private_data;
u32 ulCLK;
@@ -2082,7 +2081,7 @@ static int cs4281_suspend(snd_card_t *card, unsigned int state)
return 0;
}
-static int cs4281_resume(snd_card_t *card, unsigned int state)
+static int cs4281_resume(snd_card_t *card)
{
cs4281_t *chip = card->pm_private_data;
unsigned int i;
diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c
index 0dcfee8015978..5f2ffb7efa061 100644
--- a/sound/pci/cs46xx/cs46xx_lib.c
+++ b/sound/pci/cs46xx/cs46xx_lib.c
@@ -1217,9 +1217,7 @@ static irqreturn_t snd_cs46xx_interrupt(int irq, void *dev_id, struct pt_regs *r
c = snd_cs46xx_peekBA0(chip, BA0_MIDRP);
if ((chip->midcr & MIDCR_RIE) == 0)
continue;
- spin_unlock(&chip->reg_lock);
snd_rawmidi_receive(chip->midi_input, &c, 1);
- spin_lock(&chip->reg_lock);
}
while ((snd_cs46xx_peekBA0(chip, BA0_MIDSR) & MIDSR_TBF) == 0) {
if ((chip->midcr & MIDCR_TIE) == 0)
@@ -2690,37 +2688,28 @@ int __devinit snd_cs46xx_midi(cs46xx_t *chip, int device, snd_rawmidi_t **rrawmi
#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
-typedef struct snd_cs46xx_gameport {
- struct gameport info;
- cs46xx_t *chip;
-} cs46xx_gameport_t;
-
static void snd_cs46xx_gameport_trigger(struct gameport *gameport)
{
- cs46xx_gameport_t *gp = (cs46xx_gameport_t *)gameport;
- cs46xx_t *chip;
- snd_assert(gp, return);
- chip = gp->chip;
+ cs46xx_t *chip = gameport_get_port_data(gameport);
+
+ snd_assert(chip, return);
snd_cs46xx_pokeBA0(chip, BA0_JSPT, 0xFF); //outb(gameport->io, 0xFF);
}
static unsigned char snd_cs46xx_gameport_read(struct gameport *gameport)
{
- cs46xx_gameport_t *gp = (cs46xx_gameport_t *)gameport;
- cs46xx_t *chip;
- snd_assert(gp, return 0);
- chip = gp->chip;
+ cs46xx_t *chip = gameport_get_port_data(gameport);
+
+ snd_assert(chip, return 0);
return snd_cs46xx_peekBA0(chip, BA0_JSPT); //inb(gameport->io);
}
static int snd_cs46xx_gameport_cooked_read(struct gameport *gameport, int *axes, int *buttons)
{
- cs46xx_gameport_t *gp = (cs46xx_gameport_t *)gameport;
- cs46xx_t *chip;
+ cs46xx_t *chip = gameport_get_port_data(gameport);
unsigned js1, js2, jst;
-
- snd_assert(gp, return 0);
- chip = gp->chip;
+
+ snd_assert(chip, return 0);
js1 = snd_cs46xx_peekBA0(chip, BA0_JSC1);
js2 = snd_cs46xx_peekBA0(chip, BA0_JSC2);
@@ -2751,33 +2740,44 @@ static int snd_cs46xx_gameport_open(struct gameport *gameport, int mode)
return 0;
}
-void __devinit snd_cs46xx_gameport(cs46xx_t *chip)
+int __devinit snd_cs46xx_gameport(cs46xx_t *chip)
{
- cs46xx_gameport_t *gp;
- gp = kmalloc(sizeof(*gp), GFP_KERNEL);
- if (! gp) {
- snd_printk("cannot allocate gameport area\n");
- return;
+ struct gameport *gp;
+
+ chip->gameport = gp = gameport_allocate_port();
+ if (!gp) {
+ printk(KERN_ERR "cs46xx: cannot allocate memory for gameport\n");
+ return -ENOMEM;
}
- memset(gp, 0, sizeof(*gp));
- gp->info.open = snd_cs46xx_gameport_open;
- gp->info.read = snd_cs46xx_gameport_read;
- gp->info.trigger = snd_cs46xx_gameport_trigger;
- gp->info.cooked_read = snd_cs46xx_gameport_cooked_read;
- gp->chip = chip;
- chip->gameport = gp;
+
+ gameport_set_name(gp, "CS46xx Gameport");
+ gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci));
+ gameport_set_dev_parent(gp, &chip->pci->dev);
+ gameport_set_port_data(gp, chip);
+
+ gp->open = snd_cs46xx_gameport_open;
+ gp->read = snd_cs46xx_gameport_read;
+ gp->trigger = snd_cs46xx_gameport_trigger;
+ gp->cooked_read = snd_cs46xx_gameport_cooked_read;
snd_cs46xx_pokeBA0(chip, BA0_JSIO, 0xFF); // ?
snd_cs46xx_pokeBA0(chip, BA0_JSCTL, JSCTL_SP_MEDIUM_SLOW);
- gameport_register_port(&gp->info);
-}
-#else
+ gameport_register_port(gp);
-void __devinit snd_cs46xx_gameport(cs46xx_t *chip)
-{
+ return 0;
}
+static inline void snd_cs46xx_remove_gameport(cs46xx_t *chip)
+{
+ if (chip->gameport) {
+ gameport_unregister_port(chip->gameport);
+ chip->gameport = NULL;
+ }
+}
+#else
+int __devinit snd_cs46xx_gameport(cs46xx_t *chip) { return -ENOSYS; }
+static inline void snd_cs46xx_remove_gameport(cs46xx_t *chip) { }
#endif /* CONFIG_GAMEPORT */
/*
@@ -2893,12 +2893,7 @@ static int snd_cs46xx_free(cs46xx_t *chip)
if (chip->active_ctrl)
chip->active_ctrl(chip, 1);
-#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
- if (chip->gameport) {
- gameport_unregister_port(&chip->gameport->info);
- kfree(chip->gameport);
- }
-#endif
+ snd_cs46xx_remove_gameport(chip);
if (chip->amplifier_ctrl)
chip->amplifier_ctrl(chip, -chip->amplifier); /* force to off */
@@ -3704,7 +3699,7 @@ static struct cs_card_type __devinitdata cards[] = {
* APM support
*/
#ifdef CONFIG_PM
-static int snd_cs46xx_suspend(snd_card_t *card, unsigned int state)
+static int snd_cs46xx_suspend(snd_card_t *card, pm_message_t state)
{
cs46xx_t *chip = card->pm_private_data;
int amp_saved;
@@ -3728,7 +3723,7 @@ static int snd_cs46xx_suspend(snd_card_t *card, unsigned int state)
return 0;
}
-static int snd_cs46xx_resume(snd_card_t *card, unsigned int state)
+static int snd_cs46xx_resume(snd_card_t *card)
{
cs46xx_t *chip = card->pm_private_data;
int amp_saved;
diff --git a/sound/pci/emu10k1/Makefile b/sound/pci/emu10k1/Makefile
index 460504e49b5ad..e521c38cef455 100644
--- a/sound/pci/emu10k1/Makefile
+++ b/sound/pci/emu10k1/Makefile
@@ -5,7 +5,7 @@
snd-emu10k1-objs := emu10k1.o emu10k1_main.o \
irq.o memory.o voice.o emumpu401.o emupcm.o io.o \
- emuproc.o emumixer.o emufx.o timer.o
+ emuproc.o emumixer.o emufx.o timer.o p16v.o
snd-emu10k1-synth-objs := emu10k1_synth.o emu10k1_callback.o emu10k1_patch.o
snd-emu10k1x-objs := emu10k1x.o
diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c
index 20165abbf7ebd..6446afe19d80c 100644
--- a/sound/pci/emu10k1/emu10k1.c
+++ b/sound/pci/emu10k1/emu10k1.c
@@ -138,7 +138,15 @@ static int __devinit snd_card_emu10k1_probe(struct pci_dev *pci,
if ((err = snd_emu10k1_pcm_efx(emu, 2, NULL)) < 0) {
snd_card_free(card);
return err;
- }
+ }
+ /* This stores the periods table. */
+ if (emu->audigy && emu->revision == 4) { /* 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_emu10k1_mixer(emu)) < 0) {
snd_card_free(card);
return err;
@@ -149,6 +157,16 @@ static int __devinit snd_card_emu10k1_probe(struct pci_dev *pci,
return err;
}
+ if ((err = snd_emu10k1_pcm_multi(emu, 3, NULL)) < 0) {
+ snd_card_free(card);
+ return err;
+ }
+ if (emu->audigy && emu->revision == 4) { /* P16V */
+ if ((err = snd_p16v_pcm(emu, 4, NULL)) < 0) {
+ snd_card_free(card);
+ return err;
+ }
+ }
if (emu->audigy) {
if ((err = snd_emu10k1_audigy_midi(emu)) < 0) {
snd_card_free(card);
@@ -180,23 +198,11 @@ static int __devinit snd_card_emu10k1_probe(struct pci_dev *pci,
}
#endif
- if (emu->audigy && (emu->serial == 0x10011102) ) {
- strcpy(card->driver, "Audigy2");
- strcpy(card->shortname, "Sound Blaster Audigy2_Value");
- } else if (emu->audigy && (emu->revision == 4) ) {
- strcpy(card->driver, "Audigy2");
- strcpy(card->shortname, "Sound Blaster Audigy2");
- } else if (emu->audigy) {
- strcpy(card->driver, "Audigy");
- strcpy(card->shortname, "Sound Blaster Audigy");
- } else if (emu->APS) {
- strcpy(card->driver, "E-mu APS");
- strcpy(card->shortname, "E-mu APS");
- } else {
- strcpy(card->driver, "EMU10K1");
- strcpy(card->shortname, "Sound Blaster Live!");
- }
- sprintf(card->longname, "%s (rev.%d, serial:0x%x) at 0x%lx, irq %i", card->shortname, emu->revision, emu->serial, emu->port, emu->irq);
+ strcpy(card->driver, emu->card_capabilities->driver);
+ strcpy(card->shortname, emu->card_capabilities->name);
+ snprintf(card->longname, sizeof(card->longname),
+ "%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);
diff --git a/sound/pci/emu10k1/emu10k1_callback.c b/sound/pci/emu10k1/emu10k1_callback.c
index 580701e9042c1..7cf2f908eed9a 100644
--- a/sound/pci/emu10k1/emu10k1_callback.c
+++ b/sound/pci/emu10k1/emu10k1_callback.c
@@ -291,7 +291,7 @@ get_voice(snd_emux_t *emu, snd_emux_port_t *port)
if (vp->ch < 0) {
/* allocate a voice */
emu10k1_voice_t *hwvoice;
- if (snd_emu10k1_voice_alloc(hw, EMU10K1_SYNTH, 0, &hwvoice) < 0 || hwvoice == NULL)
+ if (snd_emu10k1_voice_alloc(hw, EMU10K1_SYNTH, 1, &hwvoice) < 0 || hwvoice == NULL)
continue;
vp->ch = hwvoice->number;
emu->num_voices++;
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c
index 7710bfaac84ca..c3c96f9f2c7fe 100644
--- a/sound/pci/emu10k1/emu10k1_main.c
+++ b/sound/pci/emu10k1/emu10k1_main.c
@@ -39,6 +39,7 @@
#include <sound/core.h>
#include <sound/emu10k1.h>
+#include "p16v.h"
#if 0
MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>, Creative Labs, Inc.");
@@ -178,14 +179,17 @@ static int __devinit snd_emu10k1_init(emu10k1_t * emu, int enable_ir)
tmp &= 0xfffff1ff;
tmp |= (0x2<<9);
snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, 0, tmp);
-
+
/* Setup SRCSel (Enable Spdif,I2S SRCMulti) */
- outl(0x600000, emu->port + 0x20);
- outl(0x14, emu->port + 0x24);
-
+ snd_emu10k1_ptr20_write(emu, SRCSel, 0, 0x14);
/* Setup SRCMulti Input Audio Enable */
- outl(0x6E0000, emu->port + 0x20);
- outl(0xFF00FF00, emu->port + 0x24);
+ /* Use 0xFFFFFFFF to enable P16V sounds. */
+ snd_emu10k1_ptr20_write(emu, SRCMULTI_ENABLE, 0, 0xFFFFFFFF);
+
+ /* Enabled Phased (8-channel) P16V playback */
+ outl(0x0201, emu->port + HCFG2);
+ /* Set playback routing. */
+ snd_emu10k1_ptr_write(emu, CAPTURE_P16V_SOURCE, 0, 78e4);
}
if (emu->audigy && (emu->serial == 0x10011102) ) { /* audigy2 Value */
/* Hacks for Alice3 to work independent of haP16V driver */
@@ -205,6 +209,15 @@ static int __devinit snd_emu10k1_init(emu10k1_t * emu, int enable_ir)
/* Setup SRCMulti Input Audio Enable */
outl(0x7b0000, emu->port + 0x20);
outl(0xFF000000, emu->port + 0x24);
+
+ /* Setup SPDIF Out Audio Enable */
+ /* The Audigy 2 Value has a separate SPDIF out,
+ * so no need for a mixer switch
+ */
+ outl(0x7a0000, emu->port + 0x20);
+ outl(0xFF000000, emu->port + 0x24);
+ tmp = inl(emu->port + A_IOCFG) & ~0x8; /* Clear bit 3 */
+ outl(tmp, emu->port + A_IOCFG);
}
@@ -587,6 +600,8 @@ static int snd_emu10k1_free(emu10k1_t *emu)
if (emu->port)
pci_release_regions(emu->pci);
pci_disable_device(emu->pci);
+ if (emu->audigy && emu->revision == 4) /* P16V */
+ snd_p16v_free(emu);
kfree(emu);
return 0;
}
@@ -597,6 +612,85 @@ static int snd_emu10k1_dev_free(snd_device_t *device)
return snd_emu10k1_free(emu);
}
+/* vendor, device, subsystem, emu10k1_chip, emu10k2_chip, ca0102_chip, ca0108_chip, ca0151_chip, spk71, spdif_bug, ac97_chip, ecard, driver, name */
+
+static emu_chip_details_t emu_chip_details[] = {
+ /* Audigy 2 Value AC3 out does not work yet. Need to find out how to turn off interpolators.*/
+ {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x10011102,
+ .driver = "Audigy2", .name = "Audigy 2 Value [SB0400]",
+ .emu10k2_chip = 1,
+ .ca0108_chip = 1,
+ .spk71 = 1} ,
+ {.vendor = 0x1102, .device = 0x0008,
+ .driver = "Audigy2", .name = "Audigy 2 Value [Unknown]",
+ .emu10k2_chip = 1,
+ .ca0108_chip = 1} ,
+ {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20071102,
+ .driver = "Audigy2", .name = "Audigy 4 PRO [SB0380]",
+ .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]",
+ .emu10k2_chip = 1,
+ .ca0102_chip = 1,
+ .ca0151_chip = 1,
+ .spk71 = 1,
+ .spdif_bug = 1,
+ .ac97_chip = 1} ,
+ {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20011102,
+ .driver = "Audigy2", .name = "Audigy 2 ZS [2001]",
+ .emu10k2_chip = 1,
+ .ca0102_chip = 1,
+ .ca0151_chip = 1,
+ .spk71 = 1,
+ .spdif_bug = 1,
+ .ac97_chip = 1} ,
+ {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10071102,
+ .driver = "Audigy2", .name = "Audigy 2 [SB0240]",
+ .emu10k2_chip = 1,
+ .ca0102_chip = 1,
+ .ca0151_chip = 1,
+ .spk71 = 1,
+ .spdif_bug = 1,
+ .ac97_chip = 1} ,
+ {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10051102,
+ .driver = "Audigy2", .name = "Audigy 2 EX [1005]",
+ .emu10k2_chip = 1,
+ .ca0102_chip = 1,
+ .ca0151_chip = 1,
+ .spdif_bug = 1} ,
+ {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10021102,
+ .driver = "Audigy2", .name = "Audigy 2 Platinum [SB0240P]",
+ .emu10k2_chip = 1,
+ .ca0102_chip = 1,
+ .ca0151_chip = 1,
+ .spk71 = 1,
+ .spdif_bug = 1,
+ .ac97_chip = 1} ,
+ {.vendor = 0x1102, .device = 0x0004,
+ .driver = "Audigy", .name = "Audigy 1 or 2 [Unknown]",
+ .emu10k2_chip = 1,
+ .ca0102_chip = 1,
+ .spdif_bug = 1} ,
+ {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x40011102,
+ .driver = "EMU10K1", .name = "E-mu APS [4001]",
+ .emu10k1_chip = 1,
+ .ecard = 1} ,
+ {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80641102,
+ .driver = "EMU10K1", .name = "SB Live 5.1",
+ .emu10k1_chip = 1,
+ .ac97_chip = 1} ,
+ {.vendor = 0x1102, .device = 0x0002,
+ .driver = "EMU10K1", .name = "SB Live [Unknown]",
+ .emu10k1_chip = 1,
+ .ac97_chip = 1} ,
+ { } /* terminator */
+};
+
int __devinit snd_emu10k1_create(snd_card_t * card,
struct pci_dev * pci,
unsigned short extin_mask,
@@ -608,15 +702,14 @@ int __devinit snd_emu10k1_create(snd_card_t * card,
emu10k1_t *emu;
int err;
int is_audigy;
+ unsigned char revision;
+ const emu_chip_details_t *c;
static snd_device_ops_t ops = {
.dev_free = snd_emu10k1_dev_free,
};
*remu = NULL;
- // is_audigy = (int)pci->driver_data;
- is_audigy = (pci->device == 0x0004) || ( (pci->device == 0x0008) );
-
/* enable PCI device */
if ((err = pci_enable_device(pci)) < 0)
return err;
@@ -626,15 +719,6 @@ int __devinit snd_emu10k1_create(snd_card_t * card,
pci_disable_device(pci);
return -ENOMEM;
}
- /* set the DMA transfer mask */
- emu->dma_mask = is_audigy ? AUDIGY_DMA_MASK : EMU10K1_DMA_MASK;
- if (pci_set_dma_mask(pci, emu->dma_mask) < 0 ||
- pci_set_consistent_dma_mask(pci, emu->dma_mask) < 0) {
- snd_printk(KERN_ERR "architecture does not support PCI busmaster DMA with mask 0x%lx\n", emu->dma_mask);
- kfree(emu);
- pci_disable_device(pci);
- return -ENXIO;
- }
emu->card = card;
spin_lock_init(&emu->reg_lock);
spin_lock_init(&emu->emu_lock);
@@ -649,8 +733,43 @@ int __devinit snd_emu10k1_create(snd_card_t * card,
emu->irq = -1;
emu->synth = NULL;
emu->get_synth_voice = NULL;
+ /* read revision & serial */
+ pci_read_config_byte(pci, PCI_REVISION_ID, &revision);
+ emu->revision = revision;
+ pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &emu->serial);
+ pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &emu->model);
+ emu->card_type = EMU10K1_CARD_CREATIVE;
+ snd_printdd("vendor=0x%x, device=0x%x, subsystem_vendor_id=0x%x, subsystem_id=0x%x\n",pci->vendor, pci->device, emu->serial, emu->model);
+
+ for (c = emu_chip_details; c->vendor; c++) {
+ if (c->vendor == pci->vendor && c->device == pci->device) {
+ if (c->subsystem == emu->serial) break;
+ if (c->subsystem == 0) break;
+ }
+ }
+ if (c->vendor == 0) {
+ snd_printk(KERN_ERR "emu10k1: Card not recognised\n");
+ kfree(emu);
+ pci_disable_device(pci);
+ return -ENOENT;
+ }
+ emu->card_capabilities = c;
+ if (c->subsystem != 0)
+ snd_printdd("Sound card name=%s\n", c->name);
+ else
+ snd_printdd("Sound card name=%s, vendor=0x%x, device=0x%x, subsystem=0x%x\n", c->name, pci->vendor, pci->device, emu->serial);
+
+ is_audigy = emu->audigy = c->emu10k2_chip;
- emu->audigy = is_audigy;
+ /* set the DMA transfer mask */
+ emu->dma_mask = is_audigy ? AUDIGY_DMA_MASK : EMU10K1_DMA_MASK;
+ if (pci_set_dma_mask(pci, emu->dma_mask) < 0 ||
+ pci_set_consistent_dma_mask(pci, emu->dma_mask) < 0) {
+ snd_printk(KERN_ERR "architecture does not support PCI busmaster DMA with mask 0x%lx\n", emu->dma_mask);
+ kfree(emu);
+ pci_disable_device(pci);
+ return -ENXIO;
+ }
if (is_audigy)
emu->gpr_base = A_FXGPREGBASE;
else
@@ -696,30 +815,15 @@ int __devinit snd_emu10k1_create(snd_card_t * card,
emu->memhdr->block_extra_size = sizeof(emu10k1_memblk_t) - sizeof(snd_util_memblk_t);
pci_set_master(pci);
- /* read revision & serial */
- pci_read_config_byte(pci, PCI_REVISION_ID, (char *)&emu->revision);
- pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &emu->serial);
- pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &emu->model);
- emu->card_type = EMU10K1_CARD_CREATIVE;
- if (emu->serial == 0x40011102) {
+
+ if (c->ecard) {
emu->card_type = EMU10K1_CARD_EMUAPS;
emu->APS = 1;
- emu->no_ac97 = 1; /* APS has no AC97 chip */
- }
- else if (emu->revision == 4 && emu->serial == 0x10051102) {
- /* Audigy 2 EX has apparently no effective AC97 controls
- * (for both input and output), so we skip the AC97 detections
- */
- snd_printdd(KERN_INFO "Audigy2 EX is detected. skipping ac97.\n");
- emu->no_ac97 = 1;
- }
-
- if (emu->revision == 4 && (emu->model == 0x2001 || emu->model == 0x2002)) {
- /* Audigy 2 ZS */
- snd_printdd(KERN_INFO "Audigy2 ZS is detected. setting 7.1 mode.\n");
- emu->spk71 = 1;
}
+ if (! c->ac97_chip)
+ emu->no_ac97 = 1;
+ emu->spk71 = c->spk71;
emu->fx8010.fxbus_mask = 0x303f;
if (extin_mask == 0)
diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c
index e60d58158a137..27dfd8ddddf48 100644
--- a/sound/pci/emu10k1/emu10k1x.c
+++ b/sound/pci/emu10k1/emu10k1x.c
@@ -749,6 +749,7 @@ static int snd_emu10k1x_ac97(emu10k1x_t *chip)
memset(&ac97, 0, sizeof(ac97));
ac97.private_data = chip;
+ ac97.scaps = AC97_SCAP_NO_SPDIF;
return snd_ac97_mixer(pbus, &ac97, &chip->ac97);
}
@@ -1278,10 +1279,8 @@ static void do_emu10k1x_midi_interrupt(emu10k1x_t *emu, emu10k1x_midi_t *midi, u
mpu401_clear_rx(emu, midi);
} else {
byte = mpu401_read_data(emu, midi);
- spin_unlock(&midi->input_lock);
if (midi->substream_input)
snd_rawmidi_receive(midi->substream_input, &byte, 1);
- spin_lock(&midi->input_lock);
}
}
spin_unlock(&midi->input_lock);
diff --git a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c
index 06d27926602ff..b9fa2e887fee3 100644
--- a/sound/pci/emu10k1/emufx.c
+++ b/sound/pci/emu10k1/emufx.c
@@ -468,10 +468,13 @@ int snd_emu10k1_fx8010_unregister_irq_handler(emu10k1_t *emu,
static void snd_emu10k1_write_op(emu10k1_fx8010_code_t *icode, unsigned int *ptr,
u32 op, u32 r, u32 a, u32 x, u32 y)
{
+ u_int32_t *code;
snd_assert(*ptr < 512, return);
+ code = (u_int32_t *)icode->code + (*ptr) * 2;
set_bit(*ptr, icode->code_valid);
- icode->code[(*ptr) * 2 + 0] = ((x & 0x3ff) << 10) | (y & 0x3ff);
- icode->code[(*ptr)++ * 2 + 1] = ((op & 0x0f) << 20) | ((r & 0x3ff) << 10) | (a & 0x3ff);
+ code[0] = ((x & 0x3ff) << 10) | (y & 0x3ff);
+ code[1] = ((op & 0x0f) << 20) | ((r & 0x3ff) << 10) | (a & 0x3ff);
+ (*ptr)++;
}
#define OP(icode, ptr, op, r, a, x, y) \
@@ -480,10 +483,13 @@ static void snd_emu10k1_write_op(emu10k1_fx8010_code_t *icode, unsigned int *ptr
static void snd_emu10k1_audigy_write_op(emu10k1_fx8010_code_t *icode, unsigned int *ptr,
u32 op, u32 r, u32 a, u32 x, u32 y)
{
+ u_int32_t *code;
snd_assert(*ptr < 1024, return);
+ code = (u_int32_t *)icode->code + (*ptr) * 2;
set_bit(*ptr, icode->code_valid);
- icode->code[(*ptr) * 2 + 0] = ((x & 0x7ff) << 12) | (y & 0x7ff);
- icode->code[(*ptr)++ * 2 + 1] = ((op & 0x0f) << 24) | ((r & 0x7ff) << 12) | (a & 0x7ff);
+ code[0] = ((x & 0x7ff) << 12) | (y & 0x7ff);
+ code[1] = ((op & 0x0f) << 24) | ((r & 0x7ff) << 12) | (a & 0x7ff);
+ (*ptr)++;
}
#define A_OP(icode, ptr, op, r, a, x, y) \
@@ -628,7 +634,8 @@ static int snd_emu10k1_verify_controls(emu10k1_t *emu, emu10k1_fx8010_code_t *ic
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;
+ emu10k1_fx8010_control_gpr_t *gctl;
+ int err;
for (i = 0, _id = icode->gpr_del_controls;
i < icode->gpr_del_control_count; i++, _id++) {
@@ -637,29 +644,42 @@ static int snd_emu10k1_verify_controls(emu10k1_t *emu, emu10k1_fx8010_code_t *ic
if (snd_emu10k1_look_for_ctl(emu, &id) == NULL)
return -ENOENT;
}
+ gctl = kmalloc(sizeof(*gctl), GFP_KERNEL);
+ if (! gctl)
+ return -ENOMEM;
+ err = 0;
for (i = 0, _gctl = icode->gpr_add_controls;
i < icode->gpr_add_control_count; i++, _gctl++) {
- if (copy_from_user(&gctl, _gctl, sizeof(gctl)))
- return -EFAULT;
- if (snd_emu10k1_look_for_ctl(emu, &gctl.id))
+ if (copy_from_user(gctl, _gctl, sizeof(*gctl))) {
+ err = -EFAULT;
+ goto __error;
+ }
+ if (snd_emu10k1_look_for_ctl(emu, &gctl->id))
continue;
down_read(&emu->card->controls_rwsem);
- if (snd_ctl_find_id(emu->card, &gctl.id) != NULL) {
+ if (snd_ctl_find_id(emu->card, &gctl->id) != NULL) {
up_read(&emu->card->controls_rwsem);
- return -EEXIST;
+ err = -EEXIST;
+ goto __error;
}
up_read(&emu->card->controls_rwsem);
- if (gctl.id.iface != SNDRV_CTL_ELEM_IFACE_MIXER &&
- gctl.id.iface != SNDRV_CTL_ELEM_IFACE_PCM)
- return -EINVAL;
+ if (gctl->id.iface != SNDRV_CTL_ELEM_IFACE_MIXER &&
+ gctl->id.iface != SNDRV_CTL_ELEM_IFACE_PCM) {
+ err = -EINVAL;
+ goto __error;
+ }
}
for (i = 0, _gctl = icode->gpr_list_controls;
i < icode->gpr_list_control_count; i++, _gctl++) {
/* FIXME: we need to check the WRITE access */
- if (copy_from_user(&gctl, _gctl, sizeof(gctl)))
- return -EFAULT;
+ if (copy_from_user(gctl, _gctl, sizeof(*gctl))) {
+ err = -EFAULT;
+ goto __error;
+ }
}
- return 0;
+ __error:
+ kfree(gctl);
+ return err;
}
static void snd_emu10k1_ctl_private_free(snd_kcontrol_t *kctl)
@@ -676,52 +696,59 @@ static int snd_emu10k1_add_controls(emu10k1_t *emu, emu10k1_fx8010_code_t *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;
+ 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;
int err = 0;
val = (snd_ctl_elem_value_t *)kmalloc(sizeof(*val), GFP_KERNEL);
- if (!val)
- return -ENOMEM;
+ gctl = kmalloc(sizeof(*gctl), GFP_KERNEL);
+ nctl = kmalloc(sizeof(*nctl), GFP_KERNEL);
+ if (!val || !gctl || !nctl) {
+ err = -ENOMEM;
+ goto __error;
+ }
+
for (i = 0, _gctl = icode->gpr_add_controls;
i < icode->gpr_add_control_count; i++, _gctl++) {
- if (copy_from_user(&gctl, _gctl, sizeof(gctl))) {
+ if (copy_from_user(gctl, _gctl, sizeof(*gctl))) {
err = -EFAULT;
goto __error;
}
- snd_runtime_check(gctl.id.iface == SNDRV_CTL_ELEM_IFACE_MIXER ||
- gctl.id.iface == SNDRV_CTL_ELEM_IFACE_PCM, err = -EINVAL; goto __error);
- snd_runtime_check(gctl.id.name[0] != '\0', err = -EINVAL; goto __error);
- ctl = snd_emu10k1_look_for_ctl(emu, &gctl.id);
+ snd_runtime_check(gctl->id.iface == SNDRV_CTL_ELEM_IFACE_MIXER ||
+ gctl->id.iface == SNDRV_CTL_ELEM_IFACE_PCM, err = -EINVAL; goto __error);
+ snd_runtime_check(gctl->id.name[0] != '\0', err = -EINVAL; goto __error);
+ ctl = snd_emu10k1_look_for_ctl(emu, &gctl->id);
memset(&knew, 0, sizeof(knew));
- knew.iface = gctl.id.iface;
- knew.name = gctl.id.name;
- knew.index = gctl.id.index;
- knew.device = gctl.id.device;
- knew.subdevice = gctl.id.subdevice;
+ knew.iface = gctl->id.iface;
+ knew.name = gctl->id.name;
+ knew.index = gctl->id.index;
+ knew.device = gctl->id.device;
+ knew.subdevice = gctl->id.subdevice;
knew.info = snd_emu10k1_gpr_ctl_info;
knew.get = snd_emu10k1_gpr_ctl_get;
knew.put = snd_emu10k1_gpr_ctl_put;
- memset(&nctl, 0, sizeof(nctl));
- nctl.vcount = gctl.vcount;
- nctl.count = gctl.count;
+ memset(nctl, 0, sizeof(*nctl));
+ nctl->vcount = gctl->vcount;
+ nctl->count = gctl->count;
for (j = 0; j < 32; j++) {
- nctl.gpr[j] = gctl.gpr[j];
- nctl.value[j] = ~gctl.value[j]; /* inverted, we want to write new value in gpr_ctl_put() */
- val->value.integer.value[j] = gctl.value[j];
+ nctl->gpr[j] = gctl->gpr[j];
+ nctl->value[j] = ~gctl->value[j]; /* inverted, we want to write new value in gpr_ctl_put() */
+ val->value.integer.value[j] = gctl->value[j];
}
- nctl.min = gctl.min;
- nctl.max = gctl.max;
- nctl.translation = gctl.translation;
+ nctl->min = gctl->min;
+ nctl->max = gctl->max;
+ nctl->translation = gctl->translation;
if (ctl == NULL) {
ctl = (snd_emu10k1_fx8010_ctl_t *)kmalloc(sizeof(*ctl), GFP_KERNEL);
- if (ctl == NULL)
- continue;
+ if (ctl == NULL) {
+ err = -ENOMEM;
+ goto __error;
+ }
knew.private_value = (unsigned long)ctl;
- memcpy(ctl, &nctl, sizeof(nctl));
+ *ctl = *nctl;
if ((err = snd_ctl_add(emu->card, kctl = snd_ctl_new1(&knew, emu))) < 0) {
kfree(ctl);
goto __error;
@@ -731,15 +758,17 @@ static int snd_emu10k1_add_controls(emu10k1_t *emu, emu10k1_fx8010_code_t *icode
list_add_tail(&ctl->list, &emu->fx8010.gpr_ctl);
} else {
/* overwrite */
- nctl.list = ctl->list;
- nctl.kcontrol = ctl->kcontrol;
- memcpy(ctl, &nctl, sizeof(nctl));
+ nctl->list = ctl->list;
+ nctl->kcontrol = ctl->kcontrol;
+ *ctl = *nctl;
snd_ctl_notify(emu->card, SNDRV_CTL_EVENT_MASK_VALUE |
SNDRV_CTL_EVENT_MASK_INFO, &ctl->kcontrol->id);
}
snd_emu10k1_gpr_ctl_put(ctl->kcontrol, val);
}
__error:
+ kfree(nctl);
+ kfree(gctl);
kfree(val);
return err;
}
@@ -768,40 +797,47 @@ static int snd_emu10k1_list_controls(emu10k1_t *emu, emu10k1_fx8010_code_t *icod
{
unsigned int i = 0, j;
unsigned int total = 0;
- emu10k1_fx8010_control_gpr_t gctl;
+ 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 list_head *list;
+ gctl = kmalloc(sizeof(*gctl), GFP_KERNEL);
+ if (! gctl)
+ return -ENOMEM;
+
_gctl = icode->gpr_list_controls;
list_for_each(list, &emu->fx8010.gpr_ctl) {
ctl = emu10k1_gpr_ctl(list);
total++;
if (_gctl && i < icode->gpr_list_control_count) {
- memset(&gctl, 0, sizeof(gctl));
+ memset(gctl, 0, sizeof(*gctl));
id = &ctl->kcontrol->id;
- gctl.id.iface = id->iface;
- strlcpy(gctl.id.name, id->name, sizeof(gctl.id.name));
- gctl.id.index = id->index;
- gctl.id.device = id->device;
- gctl.id.subdevice = id->subdevice;
- gctl.vcount = ctl->vcount;
- gctl.count = ctl->count;
+ gctl->id.iface = id->iface;
+ strlcpy(gctl->id.name, id->name, sizeof(gctl->id.name));
+ gctl->id.index = id->index;
+ gctl->id.device = id->device;
+ gctl->id.subdevice = id->subdevice;
+ gctl->vcount = ctl->vcount;
+ gctl->count = ctl->count;
for (j = 0; j < 32; j++) {
- gctl.gpr[j] = ctl->gpr[j];
- gctl.value[j] = ctl->value[j];
+ gctl->gpr[j] = ctl->gpr[j];
+ gctl->value[j] = ctl->value[j];
}
- gctl.min = ctl->min;
- gctl.max = ctl->max;
- gctl.translation = ctl->translation;
- if (copy_to_user(_gctl, &gctl, sizeof(gctl)))
+ gctl->min = ctl->min;
+ gctl->max = ctl->max;
+ gctl->translation = ctl->translation;
+ if (copy_to_user(_gctl, gctl, sizeof(*gctl))) {
+ kfree(gctl);
return -EFAULT;
+ }
_gctl++;
i++;
}
}
icode->gpr_list_control_total = total;
+ kfree(gctl);
return 0;
}
@@ -994,17 +1030,19 @@ static int __devinit _snd_emu10k1_audigy_init_efx(emu10k1_t *emu)
u32 ptr;
emu10k1_fx8010_code_t *icode = NULL;
emu10k1_fx8010_control_gpr_t *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 = kcalloc(1, sizeof(*icode), GFP_KERNEL)) == NULL ||
- (icode->gpr_map = kcalloc(512 + 256 + 256 + 2 * 1024, sizeof(u_int32_t), GFP_KERNEL)) == NULL ||
+ (icode->gpr_map = (u_int32_t __user *)kcalloc(512 + 256 + 256 + 2 * 1024, sizeof(u_int32_t), GFP_KERNEL)) == NULL ||
(controls = kcalloc(SND_EMU10K1_GPR_CONTROLS, sizeof(*controls), GFP_KERNEL)) == NULL) {
err = -ENOMEM;
goto __err;
}
+ gpr_map = (u32 *)icode->gpr_map;
icode->tram_data_map = icode->gpr_map + 512;
icode->tram_addr_map = icode->tram_data_map + 256;
@@ -1065,10 +1103,10 @@ static int __devinit _snd_emu10k1_audigy_init_efx(emu10k1_t *emu)
snd_emu10k1_init_stereo_control(&controls[nctl++], "Wave Playback Volume", gpr, 100);
gpr += 2;
- /* Music Playback */
+ /* Synth Playback */
A_OP(icode, &ptr, iMAC0, A_GPR(stereo_mix+0), A_GPR(stereo_mix+0), A_GPR(gpr), A_FXBUS(FXBUS_MIDI_LEFT));
A_OP(icode, &ptr, iMAC0, A_GPR(stereo_mix+1), A_GPR(stereo_mix+1), A_GPR(gpr+1), A_FXBUS(FXBUS_MIDI_RIGHT));
- snd_emu10k1_init_stereo_control(&controls[nctl++], "Music Playback Volume", gpr, 100);
+ snd_emu10k1_init_stereo_control(&controls[nctl++], "Synth Playback Volume", gpr, 100);
gpr += 2;
/* Wave (PCM) Capture */
@@ -1077,10 +1115,10 @@ static int __devinit _snd_emu10k1_audigy_init_efx(emu10k1_t *emu)
snd_emu10k1_init_stereo_control(&controls[nctl++], "PCM Capture Volume", gpr, 0);
gpr += 2;
- /* Music Capture */
+ /* Synth Capture */
A_OP(icode, &ptr, iMAC0, A_GPR(capture+0), A_GPR(capture+0), A_GPR(gpr), A_FXBUS(FXBUS_MIDI_LEFT));
A_OP(icode, &ptr, iMAC0, A_GPR(capture+1), A_GPR(capture+1), A_GPR(gpr+1), A_FXBUS(FXBUS_MIDI_RIGHT));
- snd_emu10k1_init_stereo_control(&controls[nctl++], "Music Capture Volume", gpr, 0);
+ snd_emu10k1_init_stereo_control(&controls[nctl++], "Synth Capture Volume", gpr, 0);
gpr += 2;
/*
@@ -1331,8 +1369,9 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
/* A_PUT_STEREO_OUTPUT(A_EXTOUT_FRONT_L, A_EXTOUT_FRONT_R, playback + SND_EMU10K1_PLAYBACK_CHANNELS); */
/* IEC958 Optical Raw Playback Switch */
- icode->gpr_map[gpr++] = 0x1008;
- icode->gpr_map[gpr++] = 0xffff0000;
+ gpr_map[gpr++] = 0;
+ gpr_map[gpr++] = 0x1008;
+ gpr_map[gpr++] = 0xffff0000;
for (z = 0; z < 2; z++) {
A_OP(icode, &ptr, iMAC0, A_GPR(tmp + 2), A_FXBUS(FXBUS_PT_LEFT + z), A_C_00000000, A_C_00000000);
A_OP(icode, &ptr, iSKIP, A_GPR_COND, A_GPR_COND, A_GPR(gpr - 2), A_C_00000001);
@@ -1341,7 +1380,14 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
A_SWITCH(icode, &ptr, tmp + 0, tmp + 2, gpr + z);
A_SWITCH_NEG(icode, &ptr, tmp + 1, gpr + z);
A_SWITCH(icode, &ptr, tmp + 1, playback + SND_EMU10K1_PLAYBACK_CHANNELS + z, tmp + 1);
- A_OP(icode, &ptr, iACC3, A_EXTOUT(A_EXTOUT_FRONT_L + z), A_GPR(tmp + 0), A_GPR(tmp + 1), A_C_00000000);
+ if ((z==1) && (emu->card_capabilities->spdif_bug)) {
+ /* Due to a SPDIF output bug on some Audigy cards, this code delays the Right channel by 1 sample */
+ snd_printk("Installing spdif_bug patch: %s\n", emu->card_capabilities->name);
+ A_OP(icode, &ptr, iACC3, A_EXTOUT(A_EXTOUT_FRONT_L + z), A_GPR(gpr - 3), A_C_00000000, A_C_00000000);
+ A_OP(icode, &ptr, iACC3, A_GPR(gpr - 3), A_GPR(tmp + 0), A_GPR(tmp + 1), A_C_00000000);
+ } else {
+ A_OP(icode, &ptr, iACC3, A_EXTOUT(A_EXTOUT_FRONT_L + z), A_GPR(tmp + 0), A_GPR(tmp + 1), A_C_00000000);
+ }
}
snd_emu10k1_init_stereo_onoff_control(controls + nctl++, "IEC958 Optical Raw Playback Switch", gpr, 0);
gpr += 2;
@@ -1358,6 +1404,11 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
A_PUT_OUTPUT(A_EXTOUT_ADC_CAP_R, capture+1);
#endif
+ /* EFX capture - capture the 16 EXTINs */
+ for (z = 0; z < 16; z++) {
+ A_OP(icode, &ptr, iACC3, A_FXBUS2(z), A_C_00000000, A_C_00000000, A_EXTIN(z));
+ }
+
/*
* ok, set up done..
*/
@@ -1373,16 +1424,14 @@ 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 = controls;
+ icode->gpr_add_controls = (emu10k1_fx8010_control_gpr_t __user *)controls;
err = snd_emu10k1_icode_poke(emu, icode);
snd_leave_user(seg);
__err:
- if (controls != NULL)
- kfree(controls);
+ kfree(controls);
if (icode != NULL) {
- if (icode->gpr_map != NULL)
- kfree(icode->gpr_map);
+ kfree((void *)icode->gpr_map);
kfree(icode);
}
return err;
@@ -1448,6 +1497,7 @@ static int __devinit _snd_emu10k1_init_efx(emu10k1_t *emu)
emu10k1_fx8010_code_t *icode;
emu10k1_fx8010_pcm_t *ipcm = NULL;
emu10k1_fx8010_control_gpr_t *controls = NULL, *ctl;
+ u32 *gpr_map;
mm_segment_t seg;
spin_lock_init(&emu->fx8010.irq_lock);
@@ -1455,12 +1505,13 @@ static int __devinit _snd_emu10k1_init_efx(emu10k1_t *emu)
if ((icode = kcalloc(1, sizeof(*icode), GFP_KERNEL)) == NULL)
return -ENOMEM;
- if ((icode->gpr_map = kcalloc(256 + 160 + 160 + 2 * 512, sizeof(u_int32_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(emu10k1_fx8010_control_gpr_t), GFP_KERNEL)) == NULL ||
(ipcm = kcalloc(1, sizeof(*ipcm), GFP_KERNEL)) == NULL) {
err = -ENOMEM;
goto __err;
}
+ gpr_map = (u32 *)icode->gpr_map;
icode->tram_data_map = icode->gpr_map + 256;
icode->tram_addr_map = icode->tram_data_map + 160;
@@ -1515,19 +1566,19 @@ static int __devinit _snd_emu10k1_init_efx(emu10k1_t *emu)
ipcm->etram[0] = 0;
ipcm->etram[1] = 1;
- icode->gpr_map[gpr + 0] = 0xfffff000;
- icode->gpr_map[gpr + 1] = 0xffff0000;
- icode->gpr_map[gpr + 2] = 0x70000000;
- icode->gpr_map[gpr + 3] = 0x00000007;
- icode->gpr_map[gpr + 4] = 0x001f << 11;
- icode->gpr_map[gpr + 5] = 0x001c << 11;
- icode->gpr_map[gpr + 6] = (0x22 - 0x01) - 1; /* skip at 01 to 22 */
- icode->gpr_map[gpr + 7] = (0x22 - 0x06) - 1; /* skip at 06 to 22 */
- icode->gpr_map[gpr + 8] = 0x2000000 + (2<<11);
- icode->gpr_map[gpr + 9] = 0x4000000 + (2<<11);
- icode->gpr_map[gpr + 10] = 1<<11;
- icode->gpr_map[gpr + 11] = (0x24 - 0x0a) - 1; /* skip at 0a to 24 */
- icode->gpr_map[gpr + 12] = 0;
+ gpr_map[gpr + 0] = 0xfffff000;
+ gpr_map[gpr + 1] = 0xffff0000;
+ gpr_map[gpr + 2] = 0x70000000;
+ gpr_map[gpr + 3] = 0x00000007;
+ gpr_map[gpr + 4] = 0x001f << 11;
+ gpr_map[gpr + 5] = 0x001c << 11;
+ gpr_map[gpr + 6] = (0x22 - 0x01) - 1; /* skip at 01 to 22 */
+ gpr_map[gpr + 7] = (0x22 - 0x06) - 1; /* skip at 06 to 22 */
+ gpr_map[gpr + 8] = 0x2000000 + (2<<11);
+ gpr_map[gpr + 9] = 0x4000000 + (2<<11);
+ gpr_map[gpr + 10] = 1<<11;
+ gpr_map[gpr + 11] = (0x24 - 0x0a) - 1; /* skip at 0a to 24 */
+ gpr_map[gpr + 12] = 0;
/* if the trigger flag is not set, skip */
/* 00: */ OP(icode, &ptr, iMAC0, C_00000000, GPR(ipcm->gpr_trigger), C_00000000, C_00000000);
@@ -1608,19 +1659,19 @@ static int __devinit _snd_emu10k1_init_efx(emu10k1_t *emu)
snd_emu10k1_init_stereo_onoff_control(controls + i++, "Wave Capture Switch", gpr + 2, 0);
gpr += 4;
- /* Music Playback Volume */
+ /* Synth Playback Volume */
for (z = 0; z < 2; z++)
VOLUME_ADD(icode, &ptr, playback + z, 2 + z, gpr + z);
- snd_emu10k1_init_stereo_control(controls + i++, "Music Playback Volume", gpr, 100);
+ snd_emu10k1_init_stereo_control(controls + i++, "Synth Playback Volume", gpr, 100);
gpr += 2;
- /* Music Capture Volume + Switch */
+ /* Synth Capture Volume + Switch */
for (z = 0; z < 2; z++) {
SWITCH(icode, &ptr, tmp + 0, 2 + z, gpr + 2 + z);
VOLUME_ADD(icode, &ptr, capture + z, tmp + 0, gpr + z);
}
- snd_emu10k1_init_stereo_control(controls + i++, "Music Capture Volume", gpr, 0);
- snd_emu10k1_init_stereo_onoff_control(controls + i++, "Music Capture Switch", gpr + 2, 0);
+ snd_emu10k1_init_stereo_control(controls + i++, "Synth Capture Volume", gpr, 0);
+ snd_emu10k1_init_stereo_onoff_control(controls + i++, "Synth Capture Switch", gpr + 2, 0);
gpr += 4;
/* Surround Digital Playback Volume (renamed later without Digital) */
@@ -1930,6 +1981,24 @@ static int __devinit _snd_emu10k1_init_efx(emu10k1_t *emu)
if (emu->fx8010.extout_mask & (1<<EXTOUT_MIC_CAP))
OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_MIC_CAP), GPR(capture + 2), C_00000000, C_00000000);
+ /* EFX capture - capture the 16 EXTINS */
+ OP(icode, &ptr, iACC3, FXBUS2(14), C_00000000, C_00000000, EXTIN(0));
+ OP(icode, &ptr, iACC3, FXBUS2(15), C_00000000, C_00000000, EXTIN(1));
+ OP(icode, &ptr, iACC3, FXBUS2(0), C_00000000, C_00000000, EXTIN(2));
+ OP(icode, &ptr, iACC3, FXBUS2(3), C_00000000, C_00000000, EXTIN(3));
+ /* Dont connect anything to FXBUS2 1 and 2. These are shared with
+ * Center/LFE on the SBLive 5.1. The kX driver only changes the
+ * routing when it detects an SBLive 5.1.
+ *
+ * Since only 14 of the 16 EXTINs are used, this is not a big problem.
+ * We route AC97L and R to FX capture 14 and 15, SPDIF CD in to FX capture
+ * 0 and 3, then the rest of the EXTINs to the corresponding FX capture
+ * channel.
+ */
+ for (z = 4; z < 14; z++) {
+ OP(icode, &ptr, iACC3, FXBUS2(z), C_00000000, C_00000000, EXTIN(z));
+ }
+
if (gpr > tmp) {
snd_BUG();
err = -EIO;
@@ -1949,19 +2018,16 @@ 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 = controls;
+ icode->gpr_add_controls = (emu10k1_fx8010_control_gpr_t __user *)controls;
err = snd_emu10k1_icode_poke(emu, icode);
snd_leave_user(seg);
if (err >= 0)
err = snd_emu10k1_ipcm_poke(emu, ipcm);
__err:
- if (ipcm != NULL)
- kfree(ipcm);
- if (controls != NULL)
- kfree(controls);
+ kfree(ipcm);
+ kfree(controls);
if (icode != NULL) {
- if (icode->gpr_map != NULL)
- kfree(icode->gpr_map);
+ kfree((void *)icode->gpr_map);
kfree(icode);
}
return err;
@@ -2064,7 +2130,7 @@ static int snd_emu10k1_fx8010_info(emu10k1_t *emu, emu10k1_fx8010_info_t *info)
memset(info, 0, sizeof(info));
info->card = emu->card_type;
info->internal_tram_size = emu->fx8010.itram_size;
- info->external_tram_size = emu->fx8010.etram_pages.bytes;
+ info->external_tram_size = emu->fx8010.etram_pages.bytes / 2;
fxbus = fxbuses;
extin = emu->audigy ? audigy_ins : creative_ins;
extout = emu->audigy ? audigy_outs : creative_outs;
diff --git a/sound/pci/emu10k1/emumixer.c b/sound/pci/emu10k1/emumixer.c
index 62ecdec603b0f..044663d31aa77 100644
--- a/sound/pci/emu10k1/emumixer.c
+++ b/sound/pci/emu10k1/emumixer.c
@@ -3,6 +3,7 @@
* Takashi Iwai <tiwai@suse.de>
* Creative Labs, Inc.
* Routines for control of EMU10K1 chips / mixer routines
+ * Multichannel PCM support Copyright (c) Lee Revell <rlrevell@joe-job.com>
*
* BUGS:
* --
@@ -67,6 +68,91 @@ static int snd_emu10k1_spdif_get_mask(snd_kcontrol_t * kcontrol,
return 0;
}
+static int snd_audigy_spdif_output_rate_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+{
+ static char *texts[] = {"44100", "48000", "96000"};
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+ uinfo->count = 1;
+ uinfo->value.enumerated.items = 3;
+ if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
+ uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
+ strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
+ return 0;
+}
+
+static int snd_audigy_spdif_output_rate_get(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t * ucontrol)
+{
+ emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
+ unsigned int tmp;
+ unsigned long flags;
+
+
+ spin_lock_irqsave(&emu->reg_lock, flags);
+ tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0);
+ switch (tmp & A_SPDIF_RATE_MASK) {
+ case A_SPDIF_44100:
+ ucontrol->value.enumerated.item[0] = 0;
+ break;
+ case A_SPDIF_48000:
+ ucontrol->value.enumerated.item[0] = 1;
+ break;
+ case A_SPDIF_96000:
+ ucontrol->value.enumerated.item[0] = 2;
+ break;
+ default:
+ ucontrol->value.enumerated.item[0] = 1;
+ }
+ spin_unlock_irqrestore(&emu->reg_lock, flags);
+ return 0;
+}
+
+static int snd_audigy_spdif_output_rate_put(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t * ucontrol)
+{
+ emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
+ int change;
+ unsigned int reg, val, tmp;
+ unsigned long flags;
+
+ switch(ucontrol->value.enumerated.item[0]) {
+ case 0:
+ val = A_SPDIF_44100;
+ break;
+ case 1:
+ val = A_SPDIF_48000;
+ break;
+ case 2:
+ val = A_SPDIF_96000;
+ break;
+ default:
+ val = A_SPDIF_48000;
+ break;
+ }
+
+
+ spin_lock_irqsave(&emu->reg_lock, flags);
+ reg = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0);
+ tmp = reg & ~A_SPDIF_RATE_MASK;
+ tmp |= val;
+ if ((change = (tmp != reg)))
+ snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, 0, tmp);
+ spin_unlock_irqrestore(&emu->reg_lock, flags);
+ return change;
+}
+
+static snd_kcontrol_new_t snd_audigy_spdif_output_rate =
+{
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Audigy SPDIF Output Sample Rate",
+ .count = 1,
+ .info = snd_audigy_spdif_output_rate_info,
+ .get = snd_audigy_spdif_output_rate_get,
+ .put = snd_audigy_spdif_output_rate_put
+};
+
static int snd_emu10k1_spdif_put(snd_kcontrol_t * kcontrol,
snd_ctl_elem_value_t * ucontrol)
{
@@ -139,6 +225,8 @@ 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)
{
emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
@@ -345,6 +433,200 @@ static snd_kcontrol_new_t snd_emu10k1_attn_control =
.put = snd_emu10k1_attn_put
};
+/* Mutichannel PCM stream controls */
+
+static int snd_emu10k1_efx_send_routing_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+{
+ emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = emu->audigy ? 8 : 4;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = emu->audigy ? 0x3f : 0x0f;
+ return 0;
+}
+
+static int snd_emu10k1_efx_send_routing_get(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t * 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)];
+ int idx;
+ int num_efx = emu->audigy ? 8 : 4;
+ int mask = emu->audigy ? 0x3f : 0x0f;
+
+ spin_lock_irqsave(&emu->reg_lock, flags);
+ for (idx = 0; idx < num_efx; idx++)
+ ucontrol->value.integer.value[idx] =
+ mix->send_routing[0][idx] & mask;
+ spin_unlock_irqrestore(&emu->reg_lock, flags);
+ return 0;
+}
+
+static int snd_emu10k1_efx_send_routing_put(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t * ucontrol)
+{
+ unsigned long flags;
+ emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
+ int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
+ emu10k1_pcm_mixer_t *mix = &emu->efx_pcm_mixer[ch];
+ int change = 0, idx, val;
+ int num_efx = emu->audigy ? 8 : 4;
+ int mask = emu->audigy ? 0x3f : 0x0f;
+
+ spin_lock_irqsave(&emu->reg_lock, flags);
+ for (idx = 0; idx < num_efx; idx++) {
+ val = ucontrol->value.integer.value[idx] & mask;
+ if (mix->send_routing[0][idx] != val) {
+ mix->send_routing[0][idx] = val;
+ change = 1;
+ }
+ }
+
+ if (change && mix->epcm) {
+ if (mix->epcm->voices[ch]) {
+ update_emu10k1_fxrt(emu, mix->epcm->voices[ch]->number,
+ &mix->send_routing[0][0]);
+ }
+ }
+ spin_unlock_irqrestore(&emu->reg_lock, flags);
+ return change;
+}
+
+static snd_kcontrol_new_t snd_emu10k1_efx_send_routing_control =
+{
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = "Multichannel PCM Send Routing",
+ .count = 16,
+ .info = snd_emu10k1_efx_send_routing_info,
+ .get = snd_emu10k1_efx_send_routing_get,
+ .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)
+{
+ emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = emu->audigy ? 8 : 4;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 255;
+ return 0;
+}
+
+static int snd_emu10k1_efx_send_volume_get(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t * 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)];
+ int idx;
+ int num_efx = emu->audigy ? 8 : 4;
+
+ spin_lock_irqsave(&emu->reg_lock, flags);
+ for (idx = 0; idx < num_efx; idx++)
+ ucontrol->value.integer.value[idx] = mix->send_volume[0][idx];
+ spin_unlock_irqrestore(&emu->reg_lock, flags);
+ return 0;
+}
+
+static int snd_emu10k1_efx_send_volume_put(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t * ucontrol)
+{
+ unsigned long flags;
+ emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
+ int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
+ emu10k1_pcm_mixer_t *mix = &emu->efx_pcm_mixer[ch];
+ int change = 0, idx, val;
+ int num_efx = emu->audigy ? 8 : 4;
+
+ spin_lock_irqsave(&emu->reg_lock, flags);
+ for (idx = 0; idx < num_efx; idx++) {
+ val = ucontrol->value.integer.value[idx] & 255;
+ if (mix->send_volume[0][idx] != val) {
+ mix->send_volume[0][idx] = val;
+ change = 1;
+ }
+ }
+ if (change && mix->epcm) {
+ if (mix->epcm->voices[ch]) {
+ update_emu10k1_send_volume(emu, mix->epcm->voices[ch]->number,
+ &mix->send_volume[0][0]);
+ }
+ }
+ spin_unlock_irqrestore(&emu->reg_lock, flags);
+ return change;
+}
+
+
+static snd_kcontrol_new_t snd_emu10k1_efx_send_volume_control =
+{
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = "Multichannel PCM Send Volume",
+ .count = 16,
+ .info = snd_emu10k1_efx_send_volume_info,
+ .get = snd_emu10k1_efx_send_volume_get,
+ .put = snd_emu10k1_efx_send_volume_put
+};
+
+static int snd_emu10k1_efx_attn_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = 1;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 0xffff;
+ return 0;
+}
+
+static int snd_emu10k1_efx_attn_get(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t * ucontrol)
+{
+ emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
+ emu10k1_pcm_mixer_t *mix = &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
+ unsigned long flags;
+
+ spin_lock_irqsave(&emu->reg_lock, flags);
+ ucontrol->value.integer.value[0] = mix->attn[0];
+ spin_unlock_irqrestore(&emu->reg_lock, flags);
+ return 0;
+}
+
+static int snd_emu10k1_efx_attn_put(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t * ucontrol)
+{
+ unsigned long flags;
+ emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
+ int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
+ emu10k1_pcm_mixer_t *mix = &emu->efx_pcm_mixer[ch];
+ int change = 0, val;
+
+ spin_lock_irqsave(&emu->reg_lock, flags);
+ val = ucontrol->value.integer.value[0] & 0xffff;
+ if (mix->attn[0] != val) {
+ mix->attn[0] = val;
+ change = 1;
+ }
+ if (change && mix->epcm) {
+ if (mix->epcm->voices[ch]) {
+ snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[ch]->number, mix->attn[0]);
+ }
+ }
+ spin_unlock_irqrestore(&emu->reg_lock, flags);
+ return change;
+}
+
+static snd_kcontrol_new_t snd_emu10k1_efx_attn_control =
+{
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = "Multichannel PCM Volume",
+ .count = 16,
+ .info = snd_emu10k1_efx_attn_info,
+ .get = snd_emu10k1_efx_attn_get,
+ .put = snd_emu10k1_efx_attn_put
+};
+
static int snd_emu10k1_shared_spdif_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
@@ -524,6 +806,7 @@ int __devinit snd_emu10k1_mixer(emu10k1_t *emu)
memset(&ac97, 0, sizeof(ac97));
ac97.private_data = emu;
ac97.private_free = snd_emu10k1_mixer_free_ac97;
+ ac97.scaps = AC97_SCAP_NO_SPDIF;
if ((err = snd_ac97_mixer(pbus, &ac97, &emu->ac97)) < 0)
return err;
if (emu->audigy) {
@@ -578,7 +861,22 @@ int __devinit snd_emu10k1_mixer(emu10k1_t *emu)
if ((err = snd_ctl_add(card, kctl)))
return err;
- /* intiailize the routing and volume table for each pcm playback stream */
+ if ((kctl = emu->ctl_efx_send_routing = snd_ctl_new1(&snd_emu10k1_efx_send_routing_control, emu)) == NULL)
+ return -ENOMEM;
+ if ((err = snd_ctl_add(card, kctl)))
+ return err;
+
+ if ((kctl = emu->ctl_efx_send_volume = snd_ctl_new1(&snd_emu10k1_efx_send_volume_control, emu)) == NULL)
+ return -ENOMEM;
+ if ((err = snd_ctl_add(card, kctl)))
+ return err;
+
+ if ((kctl = emu->ctl_efx_attn = snd_ctl_new1(&snd_emu10k1_efx_attn_control, emu)) == NULL)
+ return -ENOMEM;
+ if ((err = snd_ctl_add(card, kctl)))
+ return err;
+
+ /* initialize the routing and volume table for each pcm playback stream */
for (pcm = 0; pcm < 32; pcm++) {
emu10k1_pcm_mixer_t *mix;
int v;
@@ -598,17 +896,34 @@ int __devinit snd_emu10k1_mixer(emu10k1_t *emu)
mix->attn[0] = mix->attn[1] = mix->attn[2] = 0xffff;
}
+ /* initialize the routing and volume table for the multichannel playback stream */
+ for (pcm = 0; pcm < NUM_EFX_PLAYBACK; pcm++) {
+ emu10k1_pcm_mixer_t *mix;
+ int v;
+
+ mix = &emu->efx_pcm_mixer[pcm];
+ mix->epcm = NULL;
+
+ mix->send_routing[0][0] = pcm;
+ mix->send_routing[0][1] = (pcm == 0) ? 1 : 0;
+ for (v = 0; v < 2; v++)
+ mix->send_routing[0][2+v] = 13+v;
+ if (emu->audigy)
+ for (v = 0; v < 4; v++)
+ mix->send_routing[0][4+v] = 60+v;
+
+ memset(&mix->send_volume, 0, sizeof(mix->send_volume));
+ mix->send_volume[0][0] = 255;
+
+ mix->attn[0] = 0xffff;
+ }
+
if (! emu->APS) { /* FIXME: APS has these controls? */
/* sb live! and audigy */
if ((kctl = snd_ctl_new1(&snd_emu10k1_spdif_mask_control, emu)) == NULL)
return -ENOMEM;
if ((err = snd_ctl_add(card, kctl)))
return err;
- if ((kctl = ctl_find(card, SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT))) != NULL) {
- /* already defined by ac97, remove it */
- /* FIXME: or do we need both controls? */
- remove_ctl(card, SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT));
- }
if ((kctl = snd_ctl_new1(&snd_emu10k1_spdif_control, emu)) == NULL)
return -ENOMEM;
if ((err = snd_ctl_add(card, kctl)))
@@ -620,6 +935,10 @@ int __devinit snd_emu10k1_mixer(emu10k1_t *emu)
return -ENOMEM;
if ((err = snd_ctl_add(card, kctl)))
return err;
+ if ((kctl = snd_ctl_new1(&snd_audigy_spdif_output_rate, emu)) == NULL)
+ return -ENOMEM;
+ if ((err = snd_ctl_add(card, kctl)))
+ return err;
} else if (! emu->APS) {
/* sb live! */
if ((kctl = snd_ctl_new1(&snd_emu10k1_shared_spdif, emu)) == NULL)
@@ -627,6 +946,10 @@ int __devinit snd_emu10k1_mixer(emu10k1_t *emu)
if ((err = snd_ctl_add(card, kctl)))
return err;
}
-
+ if (emu->audigy && emu->revision == 4) { /* P16V */
+ if ((err = snd_p16v_mixer(emu)))
+ return err;
+ }
+
return 0;
}
diff --git a/sound/pci/emu10k1/emumpu401.c b/sound/pci/emu10k1/emumpu401.c
index 5c4cfc829ce49..eb57458a96654 100644
--- a/sound/pci/emu10k1/emumpu401.c
+++ b/sound/pci/emu10k1/emumpu401.c
@@ -86,10 +86,8 @@ static void do_emu10k1_midi_interrupt(emu10k1_t *emu, emu10k1_midi_t *midi, unsi
mpu401_clear_rx(emu, midi);
} else {
byte = mpu401_read_data(emu, midi);
- spin_unlock(&midi->input_lock);
if (midi->substream_input)
snd_rawmidi_receive(midi->substream_input, &byte, 1);
- spin_lock(&midi->input_lock);
}
}
spin_unlock(&midi->input_lock);
diff --git a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c
index de78ffe9112d0..d1c2a02c486bc 100644
--- a/sound/pci/emu10k1/emupcm.c
+++ b/sound/pci/emu10k1/emupcm.c
@@ -2,6 +2,7 @@
* Copyright (c) by Jaroslav Kysela <perex@suse.cz>
* Creative Labs, Inc.
* Routines for control of EMU10K1 chips / PCM routines
+ * Multichannel PCM support Copyright (c) Lee Revell <rlrevell@joe-job.com>
*
* BUGS:
* --
@@ -82,43 +83,71 @@ static void snd_emu10k1_pcm_efx_interrupt(emu10k1_t *emu, unsigned int status)
}
#endif
snd_pcm_period_elapsed(emu->pcm_capture_efx_substream);
+}
+
+static snd_pcm_uframes_t snd_emu10k1_efx_playback_pointer(snd_pcm_substream_t * substream)
+{
+ emu10k1_t *emu = snd_pcm_substream_chip(substream);
+ snd_pcm_runtime_t *runtime = substream->runtime;
+ emu10k1_pcm_t *epcm = runtime->private_data;
+ unsigned int ptr;
+
+ if (!epcm->running)
+ return 0;
+ ptr = snd_emu10k1_ptr_read(emu, CCCA, epcm->voices[0]->number) & 0x00ffffff;
+ ptr += runtime->buffer_size;
+ ptr -= epcm->ccca_start_addr;
+ ptr %= runtime->buffer_size;
+
+ return ptr;
}
static int snd_emu10k1_pcm_channel_alloc(emu10k1_pcm_t * epcm, int voices)
{
- int err;
+ int err, i;
if (epcm->voices[1] != NULL && voices < 2) {
snd_emu10k1_voice_free(epcm->emu, epcm->voices[1]);
epcm->voices[1] = NULL;
}
- if (voices == 1 && epcm->voices[0] != NULL)
- return 0; /* already allocated */
- if (voices == 2 && epcm->voices[0] != NULL && epcm->voices[1] != NULL)
- return 0;
- if (voices > 1) {
- if (epcm->voices[0] != NULL && epcm->voices[1] == NULL) {
- snd_emu10k1_voice_free(epcm->emu, epcm->voices[0]);
- epcm->voices[0] = NULL;
+ for (i = 0; i < voices; i++) {
+ if (epcm->voices[i] == NULL)
+ break;
+ }
+ if (i == voices)
+ return 0; /* already allocated */
+
+ for (i = 0; i < ARRAY_SIZE(epcm->voices); i++) {
+ if (epcm->voices[i]) {
+ snd_emu10k1_voice_free(epcm->emu, epcm->voices[i]);
+ epcm->voices[i] = NULL;
}
}
- err = snd_emu10k1_voice_alloc(epcm->emu, EMU10K1_PCM, voices > 1, &epcm->voices[0]);
+ err = snd_emu10k1_voice_alloc(epcm->emu,
+ epcm->type == PLAYBACK_EMUVOICE ? EMU10K1_PCM : EMU10K1_EFX,
+ voices,
+ &epcm->voices[0]);
+
if (err < 0)
return err;
epcm->voices[0]->epcm = epcm;
if (voices > 1) {
- epcm->voices[1] = &epcm->emu->voices[epcm->voices[0]->number + 1];
- epcm->voices[1]->epcm = epcm;
+ for (i = 1; i < voices; i++) {
+ epcm->voices[i] = &epcm->emu->voices[epcm->voices[0]->number + i];
+ epcm->voices[i]->epcm = epcm;
+ }
}
if (epcm->extra == NULL) {
- err = snd_emu10k1_voice_alloc(epcm->emu, EMU10K1_PCM, 0, &epcm->extra);
+ err = snd_emu10k1_voice_alloc(epcm->emu,
+ epcm->type == PLAYBACK_EMUVOICE ? EMU10K1_PCM : EMU10K1_EFX,
+ 1,
+ &epcm->extra);
if (err < 0) {
// printk("pcm_channel_alloc: failed extra: voices=%d, frame=%d\n", voices, frame);
- snd_emu10k1_voice_free(epcm->emu, epcm->voices[0]);
- epcm->voices[0] = NULL;
- if (epcm->voices[1])
- snd_emu10k1_voice_free(epcm->emu, epcm->voices[1]);
- epcm->voices[1] = NULL;
+ for (i = 0; i < voices; i++) {
+ snd_emu10k1_voice_free(epcm->emu, epcm->voices[i]);
+ epcm->voices[i] = NULL;
+ }
return err;
}
epcm->extra->epcm = epcm;
@@ -225,22 +254,39 @@ static unsigned int emu10k1_select_interprom(unsigned int pitch_target)
return CCCA_INTERPROM_2;
}
+/*
+ * calculate cache invalidate size
+ *
+ * stereo: channel is stereo
+ * w_16: using 16bit samples
+ *
+ * returns: cache invalidate size in samples
+ */
+static int inline emu10k1_ccis(int stereo, int w_16)
+{
+ if (w_16) {
+ return stereo ? 24 : 26;
+ } else {
+ return stereo ? 24*2 : 26*2;
+ }
+}
static void snd_emu10k1_pcm_init_voice(emu10k1_t *emu,
int master, int extra,
emu10k1_voice_t *evoice,
unsigned int start_addr,
- unsigned int end_addr)
+ unsigned int end_addr,
+ emu10k1_pcm_mixer_t *mix)
{
snd_pcm_substream_t *substream = evoice->epcm->substream;
snd_pcm_runtime_t *runtime = substream->runtime;
- emu10k1_pcm_mixer_t *mix = &emu->pcm_mixer[substream->number];
unsigned int silent_page, tmp;
int voice, stereo, w_16;
unsigned char attn, send_amount[8];
unsigned char send_routing[8];
unsigned long flags;
unsigned int pitch_target;
+ unsigned int ccis;
voice = evoice->number;
stereo = runtime->channels == 2;
@@ -273,10 +319,9 @@ static void snd_emu10k1_pcm_init_voice(emu10k1_t *emu,
memcpy(send_amount, &mix->send_volume[tmp][0], 8);
}
+ ccis = emu10k1_ccis(stereo, w_16);
+
if (master) {
- unsigned int ccis = stereo ? 28 : 30;
- if (w_16)
- ccis *= 2;
evoice->epcm->ccca_start_addr = start_addr + ccis;
if (extra) {
start_addr += ccis;
@@ -310,7 +355,12 @@ static void snd_emu10k1_pcm_init_voice(emu10k1_t *emu,
snd_emu10k1_ptr_write(emu, DSL, voice, end_addr | (send_amount[3] << 24));
snd_emu10k1_ptr_write(emu, PSST, voice, start_addr | (send_amount[2] << 24));
pitch_target = emu10k1_calc_pitch_target(runtime->rate);
- snd_emu10k1_ptr_write(emu, CCCA, voice, evoice->epcm->ccca_start_addr |
+ if (extra)
+ snd_emu10k1_ptr_write(emu, CCCA, voice, start_addr |
+ emu10k1_select_interprom(pitch_target) |
+ (w_16 ? 0 : CCCA_8BITSELECT));
+ else
+ snd_emu10k1_ptr_write(emu, CCCA, voice, (start_addr + ccis) |
emu10k1_select_interprom(pitch_target) |
(w_16 ? 0 : CCCA_8BITSELECT));
// Clear filter delay memory
@@ -398,6 +448,35 @@ 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)
+{
+ emu10k1_t *emu = snd_pcm_substream_chip(substream);
+ snd_pcm_runtime_t *runtime = substream->runtime;
+ emu10k1_pcm_t *epcm;
+ int i;
+
+ if (runtime->private_data == NULL)
+ return 0;
+ epcm = runtime->private_data;
+ if (epcm->extra) {
+ snd_emu10k1_voice_free(epcm->emu, epcm->extra);
+ epcm->extra = NULL;
+ }
+ for (i=0; i < NUM_EFX_PLAYBACK; i++) {
+ if (epcm->voices[i]) {
+ snd_emu10k1_voice_free(epcm->emu, epcm->voices[i]);
+ epcm->voices[i] = NULL;
+ }
+ }
+ if (epcm->memblk) {
+ snd_emu10k1_free_pages(emu, epcm->memblk);
+ epcm->memblk = NULL;
+ epcm->start_addr = 0;
+ }
+ snd_pcm_lib_free_pages(substream);
+ return 0;
+}
+
static int snd_emu10k1_playback_prepare(snd_pcm_substream_t * substream)
{
emu10k1_t *emu = snd_pcm_substream_chip(substream);
@@ -407,20 +486,80 @@ static int snd_emu10k1_playback_prepare(snd_pcm_substream_t * substream)
start_addr = epcm->start_addr;
end_addr = snd_pcm_lib_period_bytes(substream);
- if (runtime->channels == 2)
+ if (runtime->channels == 2) {
+ start_addr >>= 1;
end_addr >>= 1;
+ }
end_addr += start_addr;
snd_emu10k1_pcm_init_voice(emu, 1, 1, epcm->extra,
- start_addr, end_addr);
+ start_addr, end_addr, NULL);
+ start_addr = epcm->start_addr;
end_addr = epcm->start_addr + snd_pcm_lib_buffer_bytes(substream);
snd_emu10k1_pcm_init_voice(emu, 1, 0, epcm->voices[0],
- start_addr, end_addr);
+ start_addr, end_addr,
+ &emu->pcm_mixer[substream->number]);
if (epcm->voices[1])
snd_emu10k1_pcm_init_voice(emu, 0, 0, epcm->voices[1],
- start_addr, end_addr);
+ start_addr, end_addr,
+ &emu->pcm_mixer[substream->number]);
return 0;
}
+static int snd_emu10k1_efx_playback_prepare(snd_pcm_substream_t * substream)
+{
+ emu10k1_t *emu = snd_pcm_substream_chip(substream);
+ snd_pcm_runtime_t *runtime = substream->runtime;
+ emu10k1_pcm_t *epcm = runtime->private_data;
+ unsigned int start_addr, end_addr;
+ unsigned int channel_size;
+ int i;
+
+ start_addr = epcm->start_addr;
+ end_addr = epcm->start_addr + snd_pcm_lib_buffer_bytes(substream);
+
+ /*
+ * the kX driver leaves some space between voices
+ */
+ channel_size = ( end_addr - start_addr ) / NUM_EFX_PLAYBACK;
+
+ snd_emu10k1_pcm_init_voice(emu, 1, 1, epcm->extra,
+ start_addr, start_addr + (channel_size / 2), NULL);
+
+ /* only difference with the master voice is we use it for the pointer */
+ snd_emu10k1_pcm_init_voice(emu, 1, 0, epcm->voices[0],
+ start_addr, start_addr + channel_size,
+ &emu->efx_pcm_mixer[0]);
+
+ start_addr += channel_size;
+ for (i = 1; i < NUM_EFX_PLAYBACK; i++) {
+ snd_emu10k1_pcm_init_voice(emu, 0, 0, epcm->voices[i],
+ start_addr, start_addr + channel_size,
+ &emu->efx_pcm_mixer[i]);
+ start_addr += channel_size;
+ }
+
+ return 0;
+}
+
+static snd_pcm_hardware_t snd_emu10k1_efx_playback =
+{
+ .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_NONINTERLEAVED |
+ SNDRV_PCM_INFO_BLOCK_TRANSFER |
+ SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_PAUSE),
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .rates = SNDRV_PCM_RATE_48000,
+ .rate_min = 48000,
+ .rate_max = 48000,
+ .channels_min = NUM_EFX_PLAYBACK,
+ .channels_max = NUM_EFX_PLAYBACK,
+ .buffer_bytes_max = (64*1024),
+ .period_bytes_min = 64,
+ .period_bytes_max = (64*1024),
+ .periods_min = 2,
+ .periods_max = 2,
+ .fifo_size = 0,
+};
+
static int snd_emu10k1_capture_hw_params(snd_pcm_substream_t * substream,
snd_pcm_hw_params_t * hw_params)
{
@@ -439,6 +578,7 @@ static int snd_emu10k1_capture_prepare(snd_pcm_substream_t * substream)
emu10k1_pcm_t *epcm = runtime->private_data;
int idx;
+ /* zeroing the buffer size will stop capture */
snd_emu10k1_ptr_write(emu, epcm->capture_bs_reg, 0, 0);
switch (epcm->type) {
case CAPTURE_AC97ADC:
@@ -478,67 +618,86 @@ static int snd_emu10k1_capture_prepare(snd_pcm_substream_t * substream)
return 0;
}
-static void snd_emu10k1_playback_invalidate_cache(emu10k1_t *emu, emu10k1_voice_t *evoice)
+static void snd_emu10k1_playback_invalidate_cache(emu10k1_t *emu, int extra, emu10k1_voice_t *evoice)
{
snd_pcm_runtime_t *runtime;
- unsigned int voice, i, ccis, cra = 64, cs, sample;
+ unsigned int voice, stereo, i, ccis, cra = 64, cs, sample;
if (evoice == NULL)
return;
runtime = evoice->epcm->substream->runtime;
voice = evoice->number;
+ stereo = (!extra && runtime->channels == 2);
sample = snd_pcm_format_width(runtime->format) == 16 ? 0 : 0x80808080;
- if (runtime->channels > 1) {
- ccis = 28;
- cs = 4;
- } else {
- ccis = 30;
- cs = 2;
- }
- if (sample == 0) /* 16-bit */
- ccis *= 2;
- for (i = 0; i < cs; i++)
+ ccis = emu10k1_ccis(stereo, sample == 0);
+ // set cs to 2 * number of cache registers beside the invalidated
+ cs = (sample == 0) ? (32-ccis) : (64-ccis+1) >> 1;
+ if (cs > 16) cs = 16;
+ for (i = 0; i < cs; i++) {
snd_emu10k1_ptr_write(emu, CD0 + i, voice, sample);
+ if (stereo) {
+ snd_emu10k1_ptr_write(emu, CD0 + i, voice + 1, sample);
+ }
+ }
// reset cache
snd_emu10k1_ptr_write(emu, CCR_CACHEINVALIDSIZE, voice, 0);
snd_emu10k1_ptr_write(emu, CCR_READADDRESS, voice, cra);
- if (runtime->channels > 1) {
+ if (stereo) {
snd_emu10k1_ptr_write(emu, CCR_CACHEINVALIDSIZE, voice + 1, 0);
snd_emu10k1_ptr_write(emu, CCR_READADDRESS, voice + 1, cra);
}
// fill cache
snd_emu10k1_ptr_write(emu, CCR_CACHEINVALIDSIZE, voice, ccis);
+ if (stereo) {
+ snd_emu10k1_ptr_write(emu, CCR_CACHEINVALIDSIZE, voice+1, ccis);
+ }
}
-static void snd_emu10k1_playback_trigger_voice(emu10k1_t *emu, emu10k1_voice_t *evoice, int master, int extra)
+static void snd_emu10k1_playback_prepare_voice(emu10k1_t *emu, emu10k1_voice_t *evoice,
+ int master, int extra,
+ emu10k1_pcm_mixer_t *mix)
{
snd_pcm_substream_t *substream;
snd_pcm_runtime_t *runtime;
- emu10k1_pcm_mixer_t *mix;
- unsigned int voice, pitch, pitch_target, tmp;
- unsigned int attn;
+ unsigned int attn, vattn;
+ unsigned int voice, tmp;
if (evoice == NULL) /* skip second voice for mono */
return;
substream = evoice->epcm->substream;
runtime = substream->runtime;
- mix = &emu->pcm_mixer[substream->number];
voice = evoice->number;
- pitch = snd_emu10k1_rate_to_pitch(runtime->rate) >> 8;
- pitch_target = emu10k1_calc_pitch_target(runtime->rate);
+
attn = extra ? 0 : 0x00ff;
tmp = runtime->channels == 2 ? (master ? 1 : 2) : 0;
+ vattn = mix != NULL ? (mix->attn[tmp] << 16) : 0;
snd_emu10k1_ptr_write(emu, IFATN, voice, attn);
- snd_emu10k1_ptr_write(emu, VTFT, voice, (mix->attn[tmp] << 16) | 0xffff);
- snd_emu10k1_ptr_write(emu, CVCF, voice, (mix->attn[tmp] << 16) | 0xffff);
- snd_emu10k1_voice_clear_loop_stop(emu, voice);
- if (extra)
- snd_emu10k1_voice_intr_enable(emu, voice);
+ snd_emu10k1_ptr_write(emu, VTFT, voice, vattn | 0xffff);
+ snd_emu10k1_ptr_write(emu, CVCF, voice, vattn | 0xffff);
snd_emu10k1_ptr_write(emu, DCYSUSV, voice, 0x7f7f);
+ 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)
+{
+ snd_pcm_substream_t *substream;
+ snd_pcm_runtime_t *runtime;
+ unsigned int voice, pitch, pitch_target;
+
+ if (evoice == NULL) /* skip second voice for mono */
+ return;
+ substream = evoice->epcm->substream;
+ runtime = substream->runtime;
+ voice = evoice->number;
+
+ pitch = snd_emu10k1_rate_to_pitch(runtime->rate) >> 8;
+ pitch_target = emu10k1_calc_pitch_target(runtime->rate);
snd_emu10k1_ptr_write(emu, PTRX_PITCHTARGET, voice, pitch_target);
- if (master)
+ if (master || evoice->epcm->type == PLAYBACK_EFX)
snd_emu10k1_ptr_write(emu, CPF_CURRENTPITCH, voice, pitch_target);
snd_emu10k1_ptr_write(emu, IP, voice, pitch);
+ if (extra)
+ snd_emu10k1_voice_intr_enable(emu, voice);
}
static void snd_emu10k1_playback_stop_voice(emu10k1_t *emu, emu10k1_voice_t *evoice)
@@ -563,16 +722,21 @@ static int snd_emu10k1_playback_trigger(snd_pcm_substream_t * substream,
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;
int result = 0;
// printk("trigger - emu10k1 = 0x%x, cmd = %i, pointer = %i\n", (int)emu, cmd, substream->ops->pointer(substream));
spin_lock(&emu->reg_lock);
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
- snd_emu10k1_playback_invalidate_cache(emu, epcm->extra); /* do we need this? */
- snd_emu10k1_playback_invalidate_cache(emu, epcm->voices[0]);
+ snd_emu10k1_playback_invalidate_cache(emu, 1, epcm->extra); /* do we need this? */
+ snd_emu10k1_playback_invalidate_cache(emu, 0, epcm->voices[0]);
/* follow thru */
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ 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);
+ snd_emu10k1_playback_prepare_voice(emu, epcm->extra, 1, 1, NULL);
snd_emu10k1_playback_trigger_voice(emu, epcm->voices[0], 1, 0);
snd_emu10k1_playback_trigger_voice(emu, epcm->voices[1], 0, 0);
snd_emu10k1_playback_trigger_voice(emu, epcm->extra, 1, 1);
@@ -601,10 +765,10 @@ static int snd_emu10k1_capture_trigger(snd_pcm_substream_t * substream,
emu10k1_pcm_t *epcm = runtime->private_data;
int result = 0;
- // printk("trigger - emu10k1 = %p, cmd = %i, pointer = %i\n", emu, cmd, substream->ops->pointer(substream));
spin_lock(&emu->reg_lock);
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
+ // 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);
// printk("adccr = 0x%x, adcbs = 0x%x\n", epcm->adccr, epcm->adcbs);
@@ -680,6 +844,56 @@ static snd_pcm_uframes_t snd_emu10k1_playback_pointer(snd_pcm_substream_t * subs
return ptr;
}
+
+static int snd_emu10k1_efx_playback_trigger(snd_pcm_substream_t * 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;
+ int i;
+ int result = 0;
+
+ spin_lock(&emu->reg_lock);
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ // prepare voices
+ for (i = 0; i < NUM_EFX_PLAYBACK; i++) {
+ snd_emu10k1_playback_invalidate_cache(emu, 0, epcm->voices[i]);
+ }
+ snd_emu10k1_playback_invalidate_cache(emu, 1, epcm->extra);
+
+ /* follow thru */
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ 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]);
+ for (i = 1; i < NUM_EFX_PLAYBACK; i++)
+ snd_emu10k1_playback_prepare_voice(emu, epcm->voices[i], 0, 0,
+ &emu->efx_pcm_mixer[i]);
+ snd_emu10k1_playback_trigger_voice(emu, epcm->voices[0], 0, 0);
+ snd_emu10k1_playback_trigger_voice(emu, epcm->extra, 1, 1);
+ for (i = 1; i < NUM_EFX_PLAYBACK; i++)
+ snd_emu10k1_playback_trigger_voice(emu, epcm->voices[i], 0, 0);
+ epcm->running = 1;
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ epcm->running = 0;
+ for (i = 0; i < NUM_EFX_PLAYBACK; i++) {
+ snd_emu10k1_playback_stop_voice(emu, epcm->voices[i]);
+ }
+ snd_emu10k1_playback_stop_voice(emu, epcm->extra);
+ break;
+ default:
+ result = -EINVAL;
+ break;
+ }
+ spin_unlock(&emu->reg_lock);
+ return result;
+}
+
+
static snd_pcm_uframes_t snd_emu10k1_capture_pointer(snd_pcm_substream_t * substream)
{
emu10k1_t *emu = snd_pcm_substream_chip(substream);
@@ -707,9 +921,9 @@ static snd_pcm_hardware_t snd_emu10k1_playback =
SNDRV_PCM_INFO_BLOCK_TRANSFER |
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_48000,
+ .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_96000,
.rate_min = 4000,
- .rate_max = 48000,
+ .rate_max = 96000,
.channels_min = 1,
.channels_max = 2,
.buffer_bytes_max = (128*1024),
@@ -768,6 +982,13 @@ static void snd_emu10k1_pcm_mixer_notify(emu10k1_t *emu, int idx, int 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)
+{
+ 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)
{
emu10k1_pcm_t *epcm = runtime->private_data;
@@ -775,6 +996,53 @@ static void snd_emu10k1_pcm_free_substream(snd_pcm_runtime_t *runtime)
kfree(epcm);
}
+static int snd_emu10k1_efx_playback_close(snd_pcm_substream_t * substream)
+{
+ emu10k1_t *emu = snd_pcm_substream_chip(substream);
+ emu10k1_pcm_mixer_t *mix;
+ int i;
+
+ for (i=0; i < NUM_EFX_PLAYBACK; i++) {
+ mix = &emu->efx_pcm_mixer[i];
+ mix->epcm = NULL;
+ snd_emu10k1_pcm_efx_mixer_notify(emu, i, 0);
+ }
+ return 0;
+}
+
+static int snd_emu10k1_efx_playback_open(snd_pcm_substream_t * 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;
+ int i;
+
+ epcm = kcalloc(1, sizeof(*epcm), GFP_KERNEL);
+ if (epcm == NULL)
+ return -ENOMEM;
+ epcm->emu = emu;
+ epcm->type = PLAYBACK_EFX;
+ epcm->substream = substream;
+
+ emu->pcm_playback_efx_substream = substream;
+
+ runtime->private_data = epcm;
+ runtime->private_free = snd_emu10k1_pcm_free_substream;
+ runtime->hw = snd_emu10k1_efx_playback;
+
+ for (i=0; i < NUM_EFX_PLAYBACK; i++) {
+ mix = &emu->efx_pcm_mixer[i];
+ mix->send_routing[0][0] = i;
+ memset(&mix->send_volume, 0, sizeof(mix->send_volume));
+ mix->send_volume[0][0] = 255;
+ mix->attn[0] = 0xffff;
+ mix->epcm = epcm;
+ snd_emu10k1_pcm_efx_mixer_notify(emu, i, 1);
+ }
+ return 0;
+}
+
static int snd_emu10k1_playback_open(snd_pcm_substream_t * substream)
{
emu10k1_t *emu = snd_pcm_substream_chip(substream);
@@ -969,6 +1237,19 @@ static snd_pcm_ops_t snd_emu10k1_capture_ops = {
.pointer = snd_emu10k1_capture_pointer,
};
+/* EFX playback */
+static snd_pcm_ops_t snd_emu10k1_efx_playback_ops = {
+ .open = snd_emu10k1_efx_playback_open,
+ .close = snd_emu10k1_efx_playback_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = snd_emu10k1_playback_hw_params,
+ .hw_free = snd_emu10k1_efx_playback_hw_free,
+ .prepare = snd_emu10k1_efx_playback_prepare,
+ .trigger = snd_emu10k1_efx_playback_trigger,
+ .pointer = snd_emu10k1_efx_playback_pointer,
+ .page = snd_pcm_sgbuf_ops_page,
+};
+
static void snd_emu10k1_pcm_free(snd_pcm_t *pcm)
{
emu10k1_t *emu = pcm->private_data;
@@ -996,7 +1277,7 @@ int __devinit snd_emu10k1_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, "EMU10K1");
+ strcpy(pcm->name, "ADC Capture/Standard PCM Playback");
emu->pcm = pcm;
for (substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; substream; substream = substream->next)
@@ -1012,6 +1293,39 @@ 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)
+{
+ snd_pcm_t *pcm;
+ snd_pcm_substream_t *substream;
+ int err;
+
+ if (rpcm)
+ *rpcm = NULL;
+
+ if ((err = snd_pcm_new(emu->card, "emu10k1", device, 1, 0, &pcm)) < 0)
+ 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;
+
+ 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)
+ return err;
+
+ if (rpcm)
+ *rpcm = pcm;
+
+ return 0;
+}
+
+
static snd_pcm_ops_t snd_emu10k1_capture_mic_ops = {
.open = snd_emu10k1_capture_mic_open,
.close = snd_emu10k1_capture_mic_close,
@@ -1047,7 +1361,7 @@ int __devinit snd_emu10k1_pcm_mic(emu10k1_t * emu, int device, snd_pcm_t ** rpcm
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_emu10k1_capture_mic_ops);
pcm->info_flags = 0;
- strcpy(pcm->name, "EMU10K1 MIC");
+ strcpy(pcm->name, "Mic Capture");
emu->pcm_mic = pcm;
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(emu->pci), 64*1024, 64*1024);
@@ -1114,7 +1428,7 @@ static int snd_emu10k1_pcm_efx_voices_mask_put(snd_kcontrol_t * kcontrol, snd_ct
static snd_kcontrol_new_t snd_emu10k1_pcm_efx_voices_mask = {
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
- .name = "EFX voices mask",
+ .name = "Captured FX8010 Outputs",
.info = snd_emu10k1_pcm_efx_voices_mask_info,
.get = snd_emu10k1_pcm_efx_voices_mask_get,
.put = snd_emu10k1_pcm_efx_voices_mask_put
@@ -1385,13 +1699,23 @@ int __devinit snd_emu10k1_pcm_efx(emu10k1_t * emu, int device, snd_pcm_t ** rpcm
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_emu10k1_capture_efx_ops);
pcm->info_flags = 0;
- strcpy(pcm->name, "EMU10K1 EFX");
+ strcpy(pcm->name, "Multichannel Capture/PT Playback");
emu->pcm_efx = pcm;
if (rpcm)
*rpcm = pcm;
- emu->efx_voices_mask[0] = FXWC_DEFAULTROUTE_C | FXWC_DEFAULTROUTE_A;
- emu->efx_voices_mask[1] = 0;
+ /* EFX capture - record the "FXBUS2" channels, by default we connect the EXTINs
+ * to these
+ */
+
+ /* emu->efx_voices_mask[0] = FXWC_DEFAULTROUTE_C | FXWC_DEFAULTROUTE_A; */
+ if (emu->audigy) {
+ emu->efx_voices_mask[0] = 0;
+ emu->efx_voices_mask[1] = 0xffff;
+ } else {
+ emu->efx_voices_mask[0] = 0xffff0000;
+ emu->efx_voices_mask[1] = 0;
+ }
snd_ctl_add(emu->card, snd_ctl_new1(&snd_emu10k1_pcm_efx_voices_mask, emu));
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(emu->pci), 64*1024, 64*1024);
diff --git a/sound/pci/emu10k1/emuproc.c b/sound/pci/emu10k1/emuproc.c
index a65fce3bda3dd..d990d5eb45a81 100644
--- a/sound/pci/emu10k1/emuproc.c
+++ b/sound/pci/emu10k1/emuproc.c
@@ -140,38 +140,38 @@ static void snd_emu10k1_proc_read(snd_info_entry_t *entry,
/* 29 */ "???",
/* 30 */ "???",
/* 31 */ "???",
- /* 32 */ "???",
- /* 33 */ "???",
- /* 34 */ "???",
- /* 35 */ "???",
- /* 36 */ "???",
- /* 37 */ "???",
- /* 38 */ "???",
- /* 39 */ "???",
- /* 40 */ "???",
- /* 41 */ "???",
- /* 42 */ "???",
- /* 43 */ "???",
- /* 44 */ "???",
- /* 45 */ "???",
- /* 46 */ "???",
- /* 47 */ "???",
- /* 48 */ "???",
- /* 49 */ "???",
- /* 50 */ "???",
- /* 51 */ "???",
- /* 52 */ "???",
- /* 53 */ "???",
- /* 54 */ "???",
- /* 55 */ "???",
- /* 56 */ "???",
- /* 57 */ "???",
- /* 58 */ "???",
- /* 59 */ "???",
- /* 60 */ "???",
- /* 61 */ "???",
- /* 62 */ "???",
- /* 33 */ "???"
+ /* 32 */ "FXBUS2_0",
+ /* 33 */ "FXBUS2_1",
+ /* 34 */ "FXBUS2_2",
+ /* 35 */ "FXBUS2_3",
+ /* 36 */ "FXBUS2_4",
+ /* 37 */ "FXBUS2_5",
+ /* 38 */ "FXBUS2_6",
+ /* 39 */ "FXBUS2_7",
+ /* 40 */ "FXBUS2_8",
+ /* 41 */ "FXBUS2_9",
+ /* 42 */ "FXBUS2_10",
+ /* 43 */ "FXBUS2_11",
+ /* 44 */ "FXBUS2_12",
+ /* 45 */ "FXBUS2_13",
+ /* 46 */ "FXBUS2_14",
+ /* 47 */ "FXBUS2_15",
+ /* 48 */ "FXBUS2_16",
+ /* 49 */ "FXBUS2_17",
+ /* 50 */ "FXBUS2_18",
+ /* 51 */ "FXBUS2_19",
+ /* 52 */ "FXBUS2_20",
+ /* 53 */ "FXBUS2_21",
+ /* 54 */ "FXBUS2_22",
+ /* 55 */ "FXBUS2_23",
+ /* 56 */ "FXBUS2_24",
+ /* 57 */ "FXBUS2_25",
+ /* 58 */ "FXBUS2_26",
+ /* 59 */ "FXBUS2_27",
+ /* 60 */ "FXBUS2_28",
+ /* 61 */ "FXBUS2_29",
+ /* 62 */ "FXBUS2_30",
+ /* 63 */ "FXBUS2_31"
};
emu10k1_t *emu = entry->private_data;
@@ -184,7 +184,7 @@ static void snd_emu10k1_proc_read(snd_info_entry_t *entry,
snd_iprintf(buffer, "Card : %s\n",
emu->audigy ? "Audigy" : (emu->APS ? "EMU APS" : "Creative"));
snd_iprintf(buffer, "Internal TRAM (words) : 0x%x\n", emu->fx8010.itram_size);
- snd_iprintf(buffer, "External TRAM (words) : 0x%x\n", (int)emu->fx8010.etram_pages.bytes);
+ snd_iprintf(buffer, "External TRAM (words) : 0x%x\n", (int)emu->fx8010.etram_pages.bytes / 2);
snd_iprintf(buffer, "\n");
snd_iprintf(buffer, "Effect Send Routing :\n");
for (idx = 0; idx < NUM_G; idx++) {
@@ -221,7 +221,7 @@ static void snd_emu10k1_proc_read(snd_info_entry_t *entry,
snd_iprintf(buffer, " Output %02i [%s]\n", idx, outputs[idx]);
}
snd_iprintf(buffer, "\nAll FX Outputs :\n");
- for (idx = 0; idx < 32; idx++)
+ for (idx = 0; idx < (emu->audigy ? 64 : 32); idx++)
snd_iprintf(buffer, " Output %02i [%s]\n", idx, outputs[idx]);
snd_emu10k1_proc_spdif_status(emu, buffer, "S/PDIF Output 0", SPCS0, -1);
snd_emu10k1_proc_spdif_status(emu, buffer, "S/PDIF Output 1", SPCS1, -1);
@@ -322,6 +322,26 @@ 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)
+{
+ emu10k1_t *emu = entry->private_data;
+ emu10k1_voice_t *voice;
+ int idx;
+
+ snd_iprintf(buffer, "ch\tuse\tpcm\tefx\tsynth\tmidi\n");
+ for (idx = 0; idx < NUM_G; idx++) {
+ voice = &emu->voices[idx];
+ snd_iprintf(buffer, "%i\t%i\t%i\t%i\t%i\t%i\n",
+ idx,
+ voice->use,
+ voice->pcm,
+ voice->efx,
+ voice->synth,
+ voice->midi);
+ }
+}
+
#ifdef CONFIG_SND_DEBUG
static void snd_emu_proc_io_reg_read(snd_info_entry_t *entry,
snd_info_buffer_t * buffer)
@@ -393,7 +413,7 @@ 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)
+ snd_info_buffer_t * buffer, int iobase, int offset, int length, int voices)
{
emu10k1_t *emu = entry->private_data;
unsigned long value;
@@ -405,7 +425,7 @@ static void snd_emu_proc_ptr_reg_read(snd_info_entry_t *entry,
snd_iprintf(buffer, "Registers 0x%x\n", iobase);
for(i = offset; i < offset+length; i++) {
snd_iprintf(buffer, "%02X: ",i);
- for (j = 0; j < 4; j++) {
+ for (j = 0; j < voices; j++) {
if(iobase == 0)
value = snd_ptr_read(emu, 0, i, j);
else
@@ -446,25 +466,25 @@ static void snd_emu_proc_ptr_reg_write20(snd_info_entry_t *entry,
static void snd_emu_proc_ptr_reg_read00a(snd_info_entry_t *entry,
snd_info_buffer_t * buffer)
{
- snd_emu_proc_ptr_reg_read(entry, buffer, 0, 0, 0x40);
+ 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)
{
- snd_emu_proc_ptr_reg_read(entry, buffer, 0, 0x40, 0x40);
+ 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)
{
- snd_emu_proc_ptr_reg_read(entry, buffer, 0x20, 0, 0x40);
+ 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)
{
- snd_emu_proc_ptr_reg_read(entry, buffer, 0x20, 0x40, 0x40);
+ snd_emu_proc_ptr_reg_read(entry, buffer, 0x20, 0x40, 0x40, 4);
}
#endif
@@ -482,22 +502,22 @@ int __devinit snd_emu10k1_proc_init(emu10k1_t * emu)
entry->c.text.write = snd_emu_proc_io_reg_write;
}
if (! snd_card_proc_new(emu->card, "ptr_regs00a", &entry)) {
- snd_info_set_text_ops(entry, emu, 1024, snd_emu_proc_ptr_reg_read00a);
+ snd_info_set_text_ops(entry, emu, 65536, snd_emu_proc_ptr_reg_read00a);
entry->c.text.write_size = 64;
entry->c.text.write = snd_emu_proc_ptr_reg_write00;
}
if (! snd_card_proc_new(emu->card, "ptr_regs00b", &entry)) {
- snd_info_set_text_ops(entry, emu, 1024, snd_emu_proc_ptr_reg_read00b);
+ snd_info_set_text_ops(entry, emu, 65536, snd_emu_proc_ptr_reg_read00b);
entry->c.text.write_size = 64;
entry->c.text.write = snd_emu_proc_ptr_reg_write00;
}
if (! snd_card_proc_new(emu->card, "ptr_regs20a", &entry)) {
- snd_info_set_text_ops(entry, emu, 1024, snd_emu_proc_ptr_reg_read20a);
+ snd_info_set_text_ops(entry, emu, 65536, snd_emu_proc_ptr_reg_read20a);
entry->c.text.write_size = 64;
entry->c.text.write = snd_emu_proc_ptr_reg_write20;
}
if (! snd_card_proc_new(emu->card, "ptr_regs20b", &entry)) {
- snd_info_set_text_ops(entry, emu, 1024, snd_emu_proc_ptr_reg_read20b);
+ snd_info_set_text_ops(entry, emu, 65536, snd_emu_proc_ptr_reg_read20b);
entry->c.text.write_size = 64;
entry->c.text.write = snd_emu_proc_ptr_reg_write20;
}
@@ -506,6 +526,9 @@ int __devinit snd_emu10k1_proc_init(emu10k1_t * emu)
if (! snd_card_proc_new(emu->card, "emu10k1", &entry))
snd_info_set_text_ops(entry, emu, 2048, snd_emu10k1_proc_read);
+ if (! snd_card_proc_new(emu->card, "voices", &entry))
+ snd_info_set_text_ops(entry, emu, 2048, snd_emu10k1_proc_voices_read);
+
if (! snd_card_proc_new(emu->card, "fx8010_gpr", &entry)) {
entry->content = SNDRV_INFO_CONTENT_DATA;
entry->private_data = emu;
diff --git a/sound/pci/emu10k1/io.c b/sound/pci/emu10k1/io.c
index dfe327a27af8d..b9d3ae0dcab7a 100644
--- a/sound/pci/emu10k1/io.c
+++ b/sound/pci/emu10k1/io.c
@@ -91,6 +91,38 @@ 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 reg,
+ unsigned int chn)
+{
+ unsigned long flags;
+ unsigned int regptr, val;
+
+ regptr = (reg << 16) | chn;
+
+ spin_lock_irqsave(&emu->emu_lock, flags);
+ outl(regptr, emu->port + 0x20 + PTR);
+ val = inl(emu->port + 0x20 + DATA);
+ spin_unlock_irqrestore(&emu->emu_lock, flags);
+ return val;
+}
+
+void snd_emu10k1_ptr20_write(emu10k1_t *emu,
+ unsigned int reg,
+ unsigned int chn,
+ unsigned int data)
+{
+ unsigned int regptr;
+ unsigned long flags;
+
+ regptr = (reg << 16) | chn;
+
+ spin_lock_irqsave(&emu->emu_lock, flags);
+ outl(regptr, emu->port + 0x20 + PTR);
+ outl(data, emu->port + 0x20 + DATA);
+ spin_unlock_irqrestore(&emu->emu_lock, flags);
+}
+
void snd_emu10k1_intr_enable(emu10k1_t *emu, unsigned int intrenb)
{
unsigned long flags;
@@ -170,6 +202,63 @@ 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)
+{
+ unsigned long flags;
+ unsigned int val;
+
+ spin_lock_irqsave(&emu->emu_lock, flags);
+ /* voice interrupt */
+ if (voicenum >= 32) {
+ outl(HLIEH << 16, emu->port + PTR);
+ val = inl(emu->port + DATA);
+ val |= 1 << (voicenum - 32);
+ } else {
+ outl(HLIEL << 16, emu->port + PTR);
+ val = inl(emu->port + DATA);
+ val |= 1 << voicenum;
+ }
+ outl(val, emu->port + DATA);
+ spin_unlock_irqrestore(&emu->emu_lock, flags);
+}
+
+void snd_emu10k1_voice_half_loop_intr_disable(emu10k1_t *emu, unsigned int voicenum)
+{
+ unsigned long flags;
+ unsigned int val;
+
+ spin_lock_irqsave(&emu->emu_lock, flags);
+ /* voice interrupt */
+ if (voicenum >= 32) {
+ outl(HLIEH << 16, emu->port + PTR);
+ val = inl(emu->port + DATA);
+ val &= ~(1 << (voicenum - 32));
+ } else {
+ outl(HLIEL << 16, emu->port + PTR);
+ val = inl(emu->port + DATA);
+ val &= ~(1 << voicenum);
+ }
+ outl(val, emu->port + DATA);
+ spin_unlock_irqrestore(&emu->emu_lock, flags);
+}
+
+void snd_emu10k1_voice_half_loop_intr_ack(emu10k1_t *emu, unsigned int voicenum)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&emu->emu_lock, flags);
+ /* voice interrupt */
+ if (voicenum >= 32) {
+ outl(HLIPH << 16, emu->port + PTR);
+ voicenum = 1 << (voicenum - 32);
+ } else {
+ outl(HLIPL << 16, emu->port + PTR);
+ voicenum = 1 << voicenum;
+ }
+ outl(voicenum, emu->port + DATA);
+ spin_unlock_irqrestore(&emu->emu_lock, flags);
+}
+
void snd_emu10k1_voice_set_loop_stop(emu10k1_t *emu, unsigned int voicenum)
{
unsigned long flags;
diff --git a/sound/pci/emu10k1/irq.c b/sound/pci/emu10k1/irq.c
index 70f4020603c2c..b81a7cafff39e 100644
--- a/sound/pci/emu10k1/irq.c
+++ b/sound/pci/emu10k1/irq.c
@@ -33,7 +33,7 @@
irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
emu10k1_t *emu = dev_id;
- unsigned int status, orig_status;
+ unsigned int status, status2, orig_status, orig_status2;
int handled = 0;
while ((status = inl(emu->port + IPR)) != 0) {
@@ -73,6 +73,21 @@ irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
val >>= 1;
pvoice++;
}
+ val = snd_emu10k1_ptr_read(emu, HLIPL, 0);
+ for (voice = 0; voice <= voice_max; voice++) {
+ if (voice == 0x20)
+ val = snd_emu10k1_ptr_read(emu, HLIPH, 0);
+ if (val & 1) {
+ if (pvoice->use && pvoice->interrupt != NULL) {
+ pvoice->interrupt(emu, pvoice);
+ snd_emu10k1_voice_half_loop_intr_ack(emu, voice);
+ } else {
+ snd_emu10k1_voice_half_loop_intr_disable(emu, voice);
+ }
+ }
+ val >>= 1;
+ pvoice++;
+ }
status &= ~IPR_CHANNELLOOP;
}
status &= ~IPR_CHANNELNUMBERMASK;
@@ -134,7 +149,7 @@ irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
}
if (status) {
unsigned int bits;
- snd_printk(KERN_ERR "emu10k1: unhandled interrupt: 0x%08x\n", status);
+ //snd_printk(KERN_ERR "emu10k1: unhandled interrupt: 0x%08x\n", status);
//make sure any interrupts we don't handle are disabled:
bits = INTE_FXDSPENABLE |
INTE_PCIERRORENABLE |
@@ -155,5 +170,20 @@ irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
}
outl(orig_status, emu->port + IPR); /* ack all */
}
+ if (emu->audigy && emu->revision == 4) { /* 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]);
+ orig_status2 = status2;
+ if(status2 & mask) {
+ if(pvoice->use) {
+ snd_pcm_period_elapsed(pvoice->epcm->substream);
+ } else {
+ snd_printk(KERN_ERR "p16v: status: 0x%08x, mask=0x%08x, pvoice=%p, use=%d\n", status2, mask, pvoice, pvoice->use);
+ }
+ }
+ outl(orig_status2, emu->port + IPR2); /* ack all */
+ }
+ }
return IRQ_RETVAL(handled);
}
diff --git a/sound/pci/emu10k1/p16v.c b/sound/pci/emu10k1/p16v.c
new file mode 100644
index 0000000000000..d03cb2fefc9e2
--- /dev/null
+++ b/sound/pci/emu10k1/p16v.c
@@ -0,0 +1,736 @@
+/*
+ * Copyright (c) by James Courtier-Dutton <James@superbug.demon.co.uk>
+ * Driver p16v chips
+ * Version: 0.22
+ *
+ * FEATURES currently supported:
+ * Output fixed at S32_LE, 2 channel to hw:0,0
+ * Rates: 44.1, 48, 96, 192.
+ *
+ * Changelog:
+ * 0.8
+ * Use separate card based buffer for periods table.
+ * 0.9
+ * Use 2 channel output streams instead of 8 channel.
+ * (8 channel output streams might be good for ASIO type output)
+ * Corrected speaker output, so Front -> Front etc.
+ * 0.10
+ * Fixed missed interrupts.
+ * 0.11
+ * Add Sound card model number and names.
+ * Add Analog volume controls.
+ * 0.12
+ * Corrected playback interrupts. Now interrupt per period, instead of half period.
+ * 0.13
+ * Use single trigger for multichannel.
+ * 0.14
+ * Mic capture now works at fixed: S32_LE, 96000Hz, Stereo.
+ * 0.15
+ * Force buffer_size / period_size == INTEGER.
+ * 0.16
+ * Update p16v.c to work with changed alsa api.
+ * 0.17
+ * Update p16v.c to work with changed alsa api. Removed boot_devs.
+ * 0.18
+ * Merging with snd-emu10k1 driver.
+ * 0.19
+ * One stereo channel at 24bit now works.
+ * 0.20
+ * Added better register defines.
+ * 0.21
+ * Integrated with snd-emu10k1 driver.
+ * 0.22
+ * Removed #if 0 ... #endif
+ *
+ *
+ * BUGS:
+ * Some stability problems when unloading the snd-p16v kernel module.
+ * --
+ *
+ * TODO:
+ * SPDIF out.
+ * Find out how to change capture sample rates. E.g. To record SPDIF at 48000Hz.
+ * Currently capture fixed at 48000Hz.
+ *
+ * --
+ * GENERAL INFO:
+ * Model: SB0240
+ * P16V Chip: CA0151-DBS
+ * Audigy 2 Chip: CA0102-IAT
+ * AC97 Codec: STAC 9721
+ * ADC: Philips 1361T (Stereo 24bit)
+ * DAC: CS4382-K (8-channel, 24bit, 192Khz)
+ *
+ * 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
+ *
+ */
+#include <sound/driver.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/moduleparam.h>
+#include <sound/core.h>
+#include <sound/initval.h>
+#include <sound/pcm.h>
+#include <sound/ac97_codec.h>
+#include <sound/info.h>
+#include <sound/emu10k1.h>
+#include "p16v.h"
+
+#define SET_CHANNEL 0 /* Testing channel outputs 0=Front, 1=Center/LFE, 2=Unknown, 3=Rear */
+#define PCM_FRONT_CHANNEL 0
+#define PCM_REAR_CHANNEL 1
+#define PCM_CENTER_LFE_CHANNEL 2
+#define PCM_UNKNOWN_CHANNEL 3
+#define CONTROL_FRONT_CHANNEL 0
+#define CONTROL_REAR_CHANNEL 3
+#define CONTROL_CENTER_LFE_CHANNEL 1
+#define CONTROL_UNKNOWN_CHANNEL 2
+
+/* Card IDs:
+ * Class 0401: 1102:0004 (rev 04) Subsystem: 1102:2002 -> Audigy2 ZS 7.1 Model:SB0350
+ * Class 0401: 1102:0004 (rev 04) Subsystem: 1102:1007 -> Audigy2 6.1 Model:SB0240
+ * Class 0401: 1102:0004 (rev 04) Subsystem: 1102:1002 -> Audigy2 Platinum Model:SB msb0240230009266
+ * Class 0401: 1102:0004 (rev 04) Subsystem: 1102:2007 -> Audigy4 Pro Model:SB0380 M1SB0380472001901E
+ *
+ */
+
+ /* hardware definition */
+static snd_pcm_hardware_t snd_p16v_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_S32_LE, /* Only supports 24-bit samples padded to 32 bits. */
+ .rates = SNDRV_PCM_RATE_192000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_48000 ,
+ .rate_min = 48000,
+ .rate_max = 192000,
+ .channels_min = 8,
+ .channels_max = 8,
+ .buffer_bytes_max = (32*1024),
+ .period_bytes_min = 64,
+ .period_bytes_max = (16*1024),
+ .periods_min = 2,
+ .periods_max = 8,
+ .fifo_size = 0,
+};
+
+static void snd_p16v_pcm_free_substream(snd_pcm_runtime_t *runtime)
+{
+ snd_pcm_t *epcm = runtime->private_data;
+
+ if (epcm) {
+ //snd_printk("epcm free: %p\n", epcm);
+ kfree(epcm);
+ }
+}
+
+/* open_playback callback */
+static int snd_p16v_pcm_open_playback_channel(snd_pcm_substream_t *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;
+ int err;
+
+ epcm = kcalloc(1, sizeof(*epcm), GFP_KERNEL);
+ //snd_printk("epcm kcalloc: %p\n", epcm);
+
+ if (epcm == NULL)
+ return -ENOMEM;
+ epcm->emu = emu;
+ epcm->substream = substream;
+ //snd_printk("epcm device=%d, channel_id=%d\n", substream->pcm->device, channel_id);
+
+ runtime->private_data = epcm;
+ runtime->private_free = snd_p16v_pcm_free_substream;
+
+ runtime->hw = snd_p16v_playback_hw;
+
+ channel->emu = emu;
+ channel->number = channel_id;
+
+ channel->use=1;
+ //snd_printk("p16v: open channel_id=%d, channel=%p, use=0x%x\n", channel_id, channel, channel->use);
+ //printk("open:channel_id=%d, chip=%p, channel=%p\n",channel_id, chip, channel);
+ //channel->interrupt = snd_p16v_pcm_channel_interrupt;
+ channel->epcm=epcm;
+ if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
+ return err;
+
+ return 0;
+}
+
+/* close callback */
+static int snd_p16v_pcm_close_playback(snd_pcm_substream_t *substream)
+{
+ emu10k1_t *emu = snd_pcm_substream_chip(substream);
+ //snd_pcm_runtime_t *runtime = substream->runtime;
+ //emu10k1_pcm_t *epcm = runtime->private_data;
+ emu->p16v_voices[substream->pcm->device - emu->p16v_device_offset].use=0;
+/* FIXME: maybe zero others */
+ return 0;
+}
+
+static int snd_p16v_pcm_open_playback_front(snd_pcm_substream_t *substream)
+{
+ return snd_p16v_pcm_open_playback_channel(substream, PCM_FRONT_CHANNEL);
+}
+
+/* hw_params callback */
+static int snd_p16v_pcm_hw_params_playback(snd_pcm_substream_t *substream,
+ snd_pcm_hw_params_t * hw_params)
+{
+ int result;
+ //snd_printk("hw_params alloc: substream=%p\n", substream);
+ result = snd_pcm_lib_malloc_pages(substream,
+ params_buffer_bytes(hw_params));
+ //snd_printk("hw_params alloc: result=%d\n", result);
+ //dump_stack();
+ return result;
+}
+
+/* hw_free callback */
+static int snd_p16v_pcm_hw_free_playback(snd_pcm_substream_t *substream)
+{
+ int result;
+ //snd_printk("hw_params free: substream=%p\n", substream);
+ result = snd_pcm_lib_free_pages(substream);
+ //snd_printk("hw_params free: result=%d\n", result);
+ //dump_stack();
+ return result;
+}
+
+/* prepare playback callback */
+static int snd_p16v_pcm_prepare_playback(snd_pcm_substream_t *substream)
+{
+ emu10k1_t *emu = snd_pcm_substream_chip(substream);
+ snd_pcm_runtime_t *runtime = substream->runtime;
+ //emu10k1_pcm_t *epcm = runtime->private_data;
+ 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);
+ int i;
+ u32 tmp;
+
+ //snd_printk("prepare:channel_number=%d, rate=%d, format=0x%x, channels=%d, buffer_size=%ld, period_size=%ld, periods=%u, frames_to_bytes=%d\n",channel, runtime->rate, runtime->format, runtime->channels, runtime->buffer_size, runtime->period_size, runtime->periods, frames_to_bytes(runtime, 1));
+ //snd_printk("dma_addr=%x, dma_area=%p, table_base=%p\n",runtime->dma_addr, runtime->dma_area, table_base);
+ //snd_printk("dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n",emu->p16v_buffer.addr, emu->p16v_buffer.area, emu->p16v_buffer.bytes);
+ tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, channel);
+ switch (runtime->rate) {
+ case 44100:
+ snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe000) | 0x8000); /* FIXME: This will change the capture rate as well! */
+ break;
+ case 48000:
+ snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe000) | 0x0000); /* FIXME: This will change the capture rate as well! */
+ break;
+ case 96000:
+ snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe000) | 0x4000); /* FIXME: This will change the capture rate as well! */
+ break;
+ case 192000:
+ snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe000) | 0x2000); /* FIXME: This will change the capture rate as well! */
+ break;
+ default:
+ snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, 0x0000); /* FIXME: This will change the capture rate as well! */
+ break;
+ }
+ /* 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;
+ }
+
+ snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_ADDR, channel, emu->p16v_buffer.addr+(8*16*channel));
+ snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_SIZE, channel, (runtime->periods - 1) << 19);
+ snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_PTR, channel, 0);
+ snd_emu10k1_ptr20_write(emu, PLAYBACK_DMA_ADDR, channel, runtime->dma_addr);
+ snd_emu10k1_ptr20_write(emu, PLAYBACK_PERIOD_SIZE, channel, frames_to_bytes(runtime, runtime->period_size)<<16); // buffer size in bytes
+ snd_emu10k1_ptr20_write(emu, PLAYBACK_POINTER, channel, 0);
+ snd_emu10k1_ptr20_write(emu, 0x07, channel, 0x0);
+ snd_emu10k1_ptr20_write(emu, 0x08, channel, 0);
+
+ return 0;
+}
+
+static void snd_p16v_intr_enable(emu10k1_t *emu, unsigned int intrenb)
+{
+ unsigned long flags;
+ unsigned int enable;
+
+ spin_lock_irqsave(&emu->emu_lock, flags);
+ enable = inl(emu->port + INTE2) | intrenb;
+ outl(enable, emu->port + INTE2);
+ spin_unlock_irqrestore(&emu->emu_lock, flags);
+}
+
+static void snd_p16v_intr_disable(emu10k1_t *emu, unsigned int intrenb)
+{
+ unsigned long flags;
+ unsigned int disable;
+
+ spin_lock_irqsave(&emu->emu_lock, flags);
+ disable = inl(emu->port + INTE2) & (~intrenb);
+ outl(disable, emu->port + INTE2);
+ spin_unlock_irqrestore(&emu->emu_lock, flags);
+}
+
+/* trigger_playback callback */
+static int snd_p16v_pcm_trigger_playback(snd_pcm_substream_t *substream,
+ int cmd)
+{
+ emu10k1_t *emu = snd_pcm_substream_chip(substream);
+ snd_pcm_runtime_t *runtime;
+ emu10k1_pcm_t *epcm;
+ int channel;
+ int result = 0;
+ struct list_head *pos;
+ snd_pcm_substream_t *s;
+ u32 basic = 0;
+ u32 inte = 0;
+ int running=0;
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ running=1;
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ default:
+ running=0;
+ break;
+ }
+ snd_pcm_group_for_each(pos, substream) {
+ s = snd_pcm_group_substream_entry(pos);
+ runtime = s->runtime;
+ epcm = runtime->private_data;
+ channel = substream->pcm->device-emu->p16v_device_offset;
+ //snd_printk("p16v channel=%d\n",channel);
+ epcm->running = running;
+ basic |= (0x1<<channel);
+ inte |= (INTE2_PLAYBACK_CH_0_LOOP<<channel);
+ snd_pcm_trigger_done(s, substream);
+ }
+ //snd_printk("basic=0x%x, inte=0x%x\n",basic, inte);
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ snd_p16v_intr_enable(emu, inte);
+ snd_emu10k1_ptr20_write(emu, BASIC_INTERRUPT, 0, snd_emu10k1_ptr20_read(emu, BASIC_INTERRUPT, 0)| (basic));
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ snd_emu10k1_ptr20_write(emu, BASIC_INTERRUPT, 0, snd_emu10k1_ptr20_read(emu, BASIC_INTERRUPT, 0) & ~(basic));
+ snd_p16v_intr_disable(emu, inte);
+ break;
+ default:
+ result = -EINVAL;
+ break;
+ }
+ return result;
+}
+
+/* pointer_playback callback */
+static snd_pcm_uframes_t
+snd_p16v_pcm_pointer_playback(snd_pcm_substream_t *substream)
+{
+ emu10k1_t *emu = snd_pcm_substream_chip(substream);
+ snd_pcm_runtime_t *runtime = substream->runtime;
+ emu10k1_pcm_t *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)
+ return 0;
+
+ ptr3 = snd_emu10k1_ptr20_read(emu, PLAYBACK_LIST_PTR, channel);
+ ptr1 = snd_emu10k1_ptr20_read(emu, PLAYBACK_POINTER, channel);
+ ptr4 = snd_emu10k1_ptr20_read(emu, PLAYBACK_LIST_PTR, channel);
+ if (ptr3 != ptr4) ptr1 = snd_emu10k1_ptr20_read(emu, PLAYBACK_POINTER, channel);
+ ptr2 = bytes_to_frames(runtime, ptr1);
+ ptr2+= (ptr4 >> 3) * runtime->period_size;
+ ptr=ptr2;
+ if (ptr >= runtime->buffer_size)
+ ptr -= runtime->buffer_size;
+
+ return ptr;
+}
+
+/* operators */
+static snd_pcm_ops_t snd_p16v_playback_front_ops = {
+ .open = snd_p16v_pcm_open_playback_front,
+ .close = snd_p16v_pcm_close_playback,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = snd_p16v_pcm_hw_params_playback,
+ .hw_free = snd_p16v_pcm_hw_free_playback,
+ .prepare = snd_p16v_pcm_prepare_playback,
+ .trigger = snd_p16v_pcm_trigger_playback,
+ .pointer = snd_p16v_pcm_pointer_playback,
+};
+
+int snd_p16v_free(emu10k1_t *chip)
+{
+ // release the data
+ if (chip->p16v_buffer.area) {
+ snd_dma_free_pages(&chip->p16v_buffer);
+ //snd_printk("period lables free: %p\n", &chip->p16v_buffer);
+ }
+ return 0;
+}
+
+static void snd_p16v_pcm_free(snd_pcm_t *pcm)
+{
+ 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;
+ int err;
+ int capture=0;
+
+ //snd_printk("snd_p16v_pcm called. device=%d\n", device);
+ emu->p16v_device_offset = device;
+ if (rpcm)
+ *rpcm = NULL;
+ //if (device == 0) capture=1;
+ if ((err = snd_pcm_new(emu->card, "p16v", device, 1, capture, &pcm)) < 0)
+ return err;
+
+ pcm->private_data = emu;
+ pcm->private_free = snd_p16v_pcm_free;
+
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_p16v_playback_front_ops);
+
+ pcm->info_flags = 0;
+ pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX;
+ strcpy(pcm->name, "p16v");
+ emu->pcm = 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,
+ snd_dma_pci_data(emu->pci),
+ 64*1024, 64*1024)) < 0) /* FIXME: 32*1024 for sound buffer, between 32and64 for Periods table. */
+ return err;
+ //snd_printk("preallocate playback substream: err=%d\n", err);
+ }
+
+ for (substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
+ substream;
+ substream = substream->next) {
+ if ((err = snd_pcm_lib_preallocate_pages(substream,
+ SNDRV_DMA_TYPE_DEV,
+ snd_dma_pci_data(emu->pci),
+ 64*1024, 64*1024)) < 0)
+ return err;
+ //snd_printk("preallocate capture substream: err=%d\n", err);
+ }
+
+ if (rpcm)
+ *rpcm = pcm;
+
+ return 0;
+}
+
+static int snd_p16v_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = 2;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 255;
+ return 0;
+}
+
+static int snd_p16v_volume_get(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, 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 */
+ } else {
+ 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);
+}
+
+static int snd_p16v_volume_get_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_get(kcontrol, ucontrol, reg, high_low);
+}
+
+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;
+ if (high_low == 1) {
+ value &= 0xffff;
+ value = 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]) );
+ }
+ 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);
+}
+
+static snd_kcontrol_new_t snd_p16v_volume_control_analog_front =
+{
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "HD Analog Front 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 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 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 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 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 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 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 Volume",
+ .info = snd_p16v_volume_info,
+ .get = snd_p16v_volume_get_spdif_rear,
+ .put = snd_p16v_volume_put_spdif_rear
+};
+
+int snd_p16v_mixer(emu10k1_t *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;
+ return 0;
+}
+
diff --git a/sound/pci/emu10k1/p16v.h b/sound/pci/emu10k1/p16v.h
new file mode 100644
index 0000000000000..1532149403360
--- /dev/null
+++ b/sound/pci/emu10k1/p16v.h
@@ -0,0 +1,299 @@
+/*
+ * Copyright (c) by James Courtier-Dutton <James@superbug.demon.co.uk>
+ * Driver p16v chips
+ * Version: 0.21
+ *
+ * FEATURES currently supported:
+ * Output fixed at S32_LE, 2 channel to hw:0,0
+ * Rates: 44.1, 48, 96, 192.
+ *
+ * Changelog:
+ * 0.8
+ * Use separate card based buffer for periods table.
+ * 0.9
+ * Use 2 channel output streams instead of 8 channel.
+ * (8 channel output streams might be good for ASIO type output)
+ * Corrected speaker output, so Front -> Front etc.
+ * 0.10
+ * Fixed missed interrupts.
+ * 0.11
+ * Add Sound card model number and names.
+ * Add Analog volume controls.
+ * 0.12
+ * Corrected playback interrupts. Now interrupt per period, instead of half period.
+ * 0.13
+ * Use single trigger for multichannel.
+ * 0.14
+ * Mic capture now works at fixed: S32_LE, 96000Hz, Stereo.
+ * 0.15
+ * Force buffer_size / period_size == INTEGER.
+ * 0.16
+ * Update p16v.c to work with changed alsa api.
+ * 0.17
+ * Update p16v.c to work with changed alsa api. Removed boot_devs.
+ * 0.18
+ * Merging with snd-emu10k1 driver.
+ * 0.19
+ * One stereo channel at 24bit now works.
+ * 0.20
+ * Added better register defines.
+ * 0.21
+ * Split from p16v.c
+ *
+ *
+ * BUGS:
+ * Some stability problems when unloading the snd-p16v kernel module.
+ * --
+ *
+ * TODO:
+ * SPDIF out.
+ * Find out how to change capture sample rates. E.g. To record SPDIF at 48000Hz.
+ * Currently capture fixed at 48000Hz.
+ *
+ * --
+ * GENERAL INFO:
+ * Model: SB0240
+ * P16V Chip: CA0151-DBS
+ * Audigy 2 Chip: CA0102-IAT
+ * AC97 Codec: STAC 9721
+ * ADC: Philips 1361T (Stereo 24bit)
+ * DAC: CS4382-K (8-channel, 24bit, 192Khz)
+ *
+ * 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 P16V pointer-offset register set, accessed through the PTR2 and DATA2 registers */
+/********************************************************************************************************/
+
+/* The sample rate of the SPDIF outputs is set by modifying a register in the EMU10K2 PTR register A_SPDIF_SAMPLERATE.
+ * The sample rate is also controlled by the same registers that control the rate of the EMU10K2 sample rate converters.
+ */
+
+/* Initally all registers from 0x00 to 0x3f have zero contents. */
+#define PLAYBACK_LIST_ADDR 0x00 /* Base DMA address of a list of pointers to each period/size */
+ /* One list entry: 4 bytes for DMA address,
+ * 4 bytes for period_size << 16.
+ * One list entry is 8 bytes long.
+ * One list entry for each period in the buffer.
+ */
+#define PLAYBACK_LIST_SIZE 0x01 /* Size of list in bytes << 16. E.g. 8 periods -> 0x00380000 */
+#define PLAYBACK_LIST_PTR 0x02 /* Pointer to the current period being played */
+#define PLAYBACK_UNKNOWN3 0x03 /* Not used */
+#define PLAYBACK_DMA_ADDR 0x04 /* Playback DMA addresss */
+#define PLAYBACK_PERIOD_SIZE 0x05 /* Playback period size. win2000 uses 0x04000000 */
+#define PLAYBACK_POINTER 0x06 /* Playback period pointer. Used with PLAYBACK_LIST_PTR to determine buffer position currently in DAC */
+#define PLAYBACK_FIFO_END_ADDRESS 0x07 /* Playback FIFO end address */
+#define PLAYBACK_FIFO_POINTER 0x08 /* Playback FIFO pointer and number of valid sound samples in cache */
+#define PLAYBACK_UNKNOWN9 0x09 /* Not used */
+#define CAPTURE_DMA_ADDR 0x10 /* Capture DMA address */
+#define CAPTURE_BUFFER_SIZE 0x11 /* Capture buffer size */
+#define CAPTURE_POINTER 0x12 /* Capture buffer pointer. Sample currently in ADC */
+#define CAPTURE_FIFO_POINTER 0x13 /* Capture FIFO pointer and number of valid sound samples in cache */
+#define CAPTURE_P16V_VOLUME1 0x14 /* Low: Capture volume 0xXXXX3030 */
+#define CAPTURE_P16V_VOLUME2 0x15 /* High:Has no effect on capture volume */
+#define CAPTURE_P16V_SOURCE 0x16 /* P16V source select. Set to 0x0700E4E5 for AC97 CAPTURE */
+ /* [0:1] Capture input 0 channel select. 0 = Capture output 0.
+ * 1 = Capture output 1.
+ * 2 = Capture output 2.
+ * 3 = Capture output 3.
+ * [3:2] Capture input 1 channel select. 0 = Capture output 0.
+ * 1 = Capture output 1.
+ * 2 = Capture output 2.
+ * 3 = Capture output 3.
+ * [5:4] Capture input 2 channel select. 0 = Capture output 0.
+ * 1 = Capture output 1.
+ * 2 = Capture output 2.
+ * 3 = Capture output 3.
+ * [7:6] Capture input 3 channel select. 0 = Capture output 0.
+ * 1 = Capture output 1.
+ * 2 = Capture output 2.
+ * 3 = Capture output 3.
+ * [9:8] Playback input 0 channel select. 0 = Play output 0.
+ * 1 = Play output 1.
+ * 2 = Play output 2.
+ * 3 = Play output 3.
+ * [11:10] Playback input 1 channel select. 0 = Play output 0.
+ * 1 = Play output 1.
+ * 2 = Play output 2.
+ * 3 = Play output 3.
+ * [13:12] Playback input 2 channel select. 0 = Play output 0.
+ * 1 = Play output 1.
+ * 2 = Play output 2.
+ * 3 = Play output 3.
+ * [15:14] Playback input 3 channel select. 0 = Play output 0.
+ * 1 = Play output 1.
+ * 2 = Play output 2.
+ * 3 = Play output 3.
+ * [19:16] Playback mixer output enable. 1 bit per channel.
+ * [23:20] Capture mixer output enable. 1 bit per channel.
+ * [26:24] FX engine channel capture 0 = 0x60-0x67.
+ * 1 = 0x68-0x6f.
+ * 2 = 0x70-0x77.
+ * 3 = 0x78-0x7f.
+ * 4 = 0x80-0x87.
+ * 5 = 0x88-0x8f.
+ * 6 = 0x90-0x97.
+ * 7 = 0x98-0x9f.
+ * [31:27] Not used.
+ */
+
+ /* 0x1 = capture on.
+ * 0x100 = capture off.
+ * 0x200 = capture off.
+ * 0x1000 = capture off.
+ */
+#define CAPTURE_RATE_STATUS 0x17 /* Capture sample rate. Read only */
+ /* [15:0] Not used.
+ * [18:16] Channel 0 Detected sample rate. 0 - 44.1khz
+ * 1 - 48 khz
+ * 2 - 96 khz
+ * 3 - 192 khz
+ * 7 - undefined rate.
+ * [19] Channel 0. 1 - Valid, 0 - Not Valid.
+ * [22:20] Channel 1 Detected sample rate.
+ * [23] Channel 1. 1 - Valid, 0 - Not Valid.
+ * [26:24] Channel 2 Detected sample rate.
+ * [27] Channel 2. 1 - Valid, 0 - Not Valid.
+ * [30:28] Channel 3 Detected sample rate.
+ * [31] Channel 3. 1 - Valid, 0 - Not Valid.
+ */
+/* 0x18 - 0x1f unused */
+#define PLAYBACK_LAST_SAMPLE 0x20 /* The sample currently being played. Read only */
+/* 0x21 - 0x3f unused */
+#define BASIC_INTERRUPT 0x40 /* Used by both playback and capture interrupt handler */
+ /* Playback (0x1<<channel_id) Don't touch high 16bits. */
+ /* Capture (0x100<<channel_id). not tested */
+ /* Start Playback [3:0] (one bit per channel)
+ * Start Capture [11:8] (one bit per channel)
+ * Record source select for channel 0 [18:16]
+ * Record source select for channel 1 [22:20]
+ * Record source select for channel 2 [26:24]
+ * Record source select for channel 3 [30:28]
+ * 0 - SPDIF channel.
+ * 1 - I2S channel.
+ * 2 - SRC48 channel.
+ * 3 - SRCMulti_SPDIF channel.
+ * 4 - SRCMulti_I2S channel.
+ * 5 - SPDIF channel.
+ * 6 - fxengine capture.
+ * 7 - AC97 capture.
+ */
+ /* Default 41110000.
+ * Writing 0xffffffff hangs the PC.
+ * Writing 0xffff0000 -> 77770000 so it must be some sort of route.
+ * bit 0x1 starts DMA playback on channel_id 0
+ */
+/* 0x41,42 take values from 0 - 0xffffffff, but have no effect on playback */
+/* 0x43,0x48 do not remember settings */
+/* 0x41-45 unused */
+#define WATERMARK 0x46 /* Test bit to indicate cache level usage */
+ /* Values it can have while playing on channel 0.
+ * 0000f000, 0000f004, 0000f008, 0000f00c.
+ * Readonly.
+ */
+/* 0x47-0x4f unused */
+/* 0x50-0x5f Capture cache data */
+#define SRCSel 0x60 /* SRCSel. Default 0x4. Bypass P16V 0x14 */
+ /* [0] 0 = 10K2 audio, 1 = SRC48 mixer output.
+ * [2] 0 = 10K2 audio, 1 = SRCMulti SPDIF mixer output.
+ * [4] 0 = 10K2 audio, 1 = SRCMulti I2S mixer output.
+ */
+ /* SRC48 converts samples rates 44.1, 48, 96, 192 to 48 khz. */
+ /* SRCMulti converts 48khz samples rates to 44.1, 48, 96, 192 to 48. */
+ /* SRC48 and SRCMULTI sample rate select and output select. */
+ /* 0xffffffff -> 0xC0000015
+ * 0xXXXXXXX4 = Enable Front Left/Right
+ * Enable PCMs
+ */
+
+/* 0x61 -> 0x6c are Volume controls */
+#define PLAYBACK_VOLUME_MIXER1 0x61 /* SRC48 Low to mixer input volume control. */
+#define PLAYBACK_VOLUME_MIXER2 0x62 /* SRC48 High to mixer input volume control. */
+#define PLAYBACK_VOLUME_MIXER3 0x63 /* SRCMULTI SPDIF Low to mixer input volume control. */
+#define PLAYBACK_VOLUME_MIXER4 0x64 /* SRCMULTI SPDIF High to mixer input volume control. */
+#define PLAYBACK_VOLUME_MIXER5 0x65 /* SRCMULTI I2S Low to mixer input volume control. */
+#define PLAYBACK_VOLUME_MIXER6 0x66 /* SRCMULTI I2S High to mixer input volume control. */
+#define PLAYBACK_VOLUME_MIXER7 0x67 /* P16V Low to SRCMULTI SPDIF mixer input volume control. */
+#define PLAYBACK_VOLUME_MIXER8 0x68 /* P16V High to SRCMULTI SPDIF mixer input volume control. */
+#define PLAYBACK_VOLUME_MIXER9 0x69 /* P16V Low to SRCMULTI I2S mixer input volume control. */
+ /* 0xXXXX3030 = PCM0 Volume (Front).
+ * 0x3030XXXX = PCM1 Volume (Center)
+ */
+#define PLAYBACK_VOLUME_MIXER10 0x6a /* P16V High to SRCMULTI I2S mixer input volume control. */
+ /* 0x3030XXXX = PCM3 Volume (Rear). */
+#define PLAYBACK_VOLUME_MIXER11 0x6b /* E10K2 Low to SRC48 mixer input volume control. */
+#define PLAYBACK_VOLUME_MIXER12 0x6c /* E10K2 High to SRC48 mixer input volume control. */
+
+#define SRC48_ENABLE 0x6d /* SRC48 input audio enable */
+ /* SRC48 converts samples rates 44.1, 48, 96, 192 to 48 khz. */
+ /* [23:16] The corresponding P16V channel to SRC48 enabled if == 1.
+ * [31:24] The corresponding E10K2 channel to SRC48 enabled.
+ */
+#define SRCMULTI_ENABLE 0x6e /* SRCMulti input audio enable. Default 0xffffffff */
+ /* SRCMulti converts 48khz samples rates to 44.1, 48, 96, 192 to 48. */
+ /* [7:0] The corresponding P16V channel to SRCMulti_I2S enabled if == 1.
+ * [15:8] The corresponding E10K2 channel to SRCMulti I2S enabled.
+ * [23:16] The corresponding P16V channel to SRCMulti SPDIF enabled.
+ * [31:24] The corresponding E10K2 channel to SRCMulti SPDIF enabled.
+ */
+ /* Bypass P16V 0xff00ff00
+ * Bitmap. 0 = Off, 1 = On.
+ * P16V playback outputs:
+ * 0xXXXXXXX1 = PCM0 Left. (Front)
+ * 0xXXXXXXX2 = PCM0 Right.
+ * 0xXXXXXXX4 = PCM1 Left. (Center/LFE)
+ * 0xXXXXXXX8 = PCM1 Right.
+ * 0xXXXXXX1X = PCM2 Left. (Unknown)
+ * 0xXXXXXX2X = PCM2 Right.
+ * 0xXXXXXX4X = PCM3 Left. (Rear)
+ * 0xXXXXXX8X = PCM3 Right.
+ */
+#define AUDIO_OUT_ENABLE 0x6f /* Default: 000100FF */
+ /* [3:0] Does something, but not documented. Probably capture enable.
+ * [7:4] Playback channels enable. not documented.
+ * [16] AC97 output enable if == 1
+ * [30] 0 = SRCMulti_I2S input from fxengine 0x68-0x6f.
+ * 1 = SRCMulti_I2S input from SRC48 output.
+ * [31] 0 = SRCMulti_SPDIF input from fxengine 0x60-0x67.
+ * 1 = SRCMulti_SPDIF input from SRC48 output.
+ */
+ /* 0xffffffff -> C00100FF */
+ /* 0 -> Not playback sound, irq still running */
+ /* 0xXXXXXX10 = PCM0 Left/Right On. (Front)
+ * 0xXXXXXX20 = PCM1 Left/Right On. (Center/LFE)
+ * 0xXXXXXX40 = PCM2 Left/Right On. (Unknown)
+ * 0xXXXXXX80 = PCM3 Left/Right On. (Rear)
+ */
+#define PLAYBACK_SPDIF_SELECT 0x70 /* Default: 12030F00 */
+ /* 0xffffffff -> 3FF30FFF */
+ /* 0x00000001 pauses stream/irq fail. */
+ /* All other bits do not effect playback */
+#define PLAYBACK_SPDIF_SRC_SELECT 0x71 /* Default: 0000E4E4 */
+ /* 0xffffffff -> F33FFFFF */
+ /* All bits do not effect playback */
+#define PLAYBACK_SPDIF_USER_DATA0 0x72 /* SPDIF out user data 0 */
+#define PLAYBACK_SPDIF_USER_DATA1 0x73 /* SPDIF out user data 1 */
+/* 0x74-0x75 unknown */
+#define CAPTURE_SPDIF_CONTROL 0x76 /* SPDIF in control setting */
+#define CAPTURE_SPDIF_STATUS 0x77 /* SPDIF in status */
+#define CAPURE_SPDIF_USER_DATA0 0x78 /* SPDIF in user data 0 */
+#define CAPURE_SPDIF_USER_DATA1 0x79 /* SPDIF in user data 1 */
+#define CAPURE_SPDIF_USER_DATA2 0x7a /* SPDIF in user data 2 */
+
diff --git a/sound/pci/emu10k1/timer.c b/sound/pci/emu10k1/timer.c
index c9c421a647436..d2e364607c1dc 100644
--- a/sound/pci/emu10k1/timer.c
+++ b/sound/pci/emu10k1/timer.c
@@ -1,10 +1,8 @@
/*
* Copyright (c) by Lee Revell <rlrevell@joe-job.com>
- *
+ * Clemens Ladisch <clemens@ladisch.de>
* Routines for control of EMU10K1 chips
*
- * Copied from similar code by Clemens Ladisch in the ymfpci driver
- *
* BUGS:
* --
*
diff --git a/sound/pci/emu10k1/voice.c b/sound/pci/emu10k1/voice.c
index 5afdecba2d392..d251d3440eecc 100644
--- a/sound/pci/emu10k1/voice.c
+++ b/sound/pci/emu10k1/voice.c
@@ -1,8 +1,11 @@
/*
* Copyright (c) by Jaroslav Kysela <perex@suse.cz>
* Creative Labs, Inc.
+ * Lee Revell <rlrevell@joe-job.com>
* Routines for control of EMU10K1 chips - voice manager
*
+ * Rewrote voice allocator for multichannel support - rlrevell 12/2004
+ *
* BUGS:
* --
*
@@ -30,25 +33,62 @@
#include <sound/core.h>
#include <sound/emu10k1.h>
-static int voice_alloc(emu10k1_t *emu, emu10k1_voice_type_t type, int pair, emu10k1_voice_t **rvoice)
+/* Previously the voice allocator started at 0 every time. The new voice
+ * allocator uses a round robin scheme. The next free voice is tracked in
+ * the card record and each allocation begins where the last left off. The
+ * hardware requires stereo interleaved voices be aligned to an even/odd
+ * boundary. For multichannel voice allocation we ensure than the block of
+ * voices does not cross the 32 voice boundary. This simplifies the
+ * multichannel support and ensures we can use a single write to the
+ * (set|clear)_loop_stop registers. Otherwise (for example) the voices would
+ * get out of sync when pausing/resuming a stream.
+ * --rlrevell
+ */
+
+static int voice_alloc(emu10k1_t *emu, emu10k1_voice_type_t type, int number, emu10k1_voice_t **rvoice)
{
- emu10k1_voice_t *voice, *voice2;
- int idx;
+ emu10k1_voice_t *voice;
+ int i, j, k, first_voice, last_voice, skip;
*rvoice = NULL;
- for (idx = 0; idx < 64; idx += pair ? 2 : 1) {
- voice = &emu->voices[idx];
- voice2 = pair ? &emu->voices[idx+1] : NULL;
- if (voice->use || (voice2 && voice2->use))
+ first_voice = last_voice = 0;
+ for (i = emu->next_free_voice, j = 0; j < NUM_G ; i += number, j += number) {
+ // printk("i %d j %d next free %d!\n", i, j, emu->next_free_voice);
+ i %= NUM_G;
+
+ /* stereo voices must be even/odd */
+ if ((number == 2) && (i % 2)) {
+ i++;
continue;
+ }
+
+ skip = 0;
+ for (k = 0; k < number; k++) {
+ voice = &emu->voices[(i+k) % NUM_G];
+ if (voice->use) {
+ skip = 1;
+ break;
+ }
+ }
+ if (!skip) {
+ // printk("allocated voice %d\n", i);
+ first_voice = i;
+ last_voice = (i + number) % NUM_G;
+ emu->next_free_voice = last_voice;
+ break;
+ }
+ }
+
+ if (first_voice == last_voice)
+ return -ENOMEM;
+
+ for (i=0; i < number; i++) {
+ voice = &emu->voices[(first_voice + i) % NUM_G];
+ // printk("voice alloc - %i, %i of %i\n", voice->number, idx-first_voice+1, number);
voice->use = 1;
- if (voice2)
- voice2->use = 1;
switch (type) {
case EMU10K1_PCM:
voice->pcm = 1;
- if (voice2)
- voice2->pcm = 1;
break;
case EMU10K1_SYNTH:
voice->synth = 1;
@@ -56,26 +96,27 @@ static int voice_alloc(emu10k1_t *emu, emu10k1_voice_type_t type, int pair, emu1
case EMU10K1_MIDI:
voice->midi = 1;
break;
+ case EMU10K1_EFX:
+ voice->efx = 1;
+ break;
}
- // printk("voice alloc - %i, pair = %i\n", voice->number, pair);
- *rvoice = voice;
- return 0;
}
- return -ENOMEM;
+ *rvoice = &emu->voices[first_voice];
+ return 0;
}
-int snd_emu10k1_voice_alloc(emu10k1_t *emu, emu10k1_voice_type_t type, int pair, emu10k1_voice_t **rvoice)
+int snd_emu10k1_voice_alloc(emu10k1_t *emu, emu10k1_voice_type_t type, int number, emu10k1_voice_t **rvoice)
{
unsigned long flags;
int result;
snd_assert(rvoice != NULL, return -EINVAL);
- snd_assert(!pair || type == EMU10K1_PCM, return -EINVAL);
+ snd_assert(number, return -EINVAL);
spin_lock_irqsave(&emu->voice_lock, flags);
for (;;) {
- result = voice_alloc(emu, type, pair, rvoice);
- if (result == 0 || type != EMU10K1_PCM)
+ result = voice_alloc(emu, type, number, rvoice);
+ if (result == 0 || type == EMU10K1_SYNTH || type == EMU10K1_MIDI)
break;
/* free a voice from synth */
@@ -84,7 +125,7 @@ int snd_emu10k1_voice_alloc(emu10k1_t *emu, emu10k1_voice_type_t type, int pair,
if (result >= 0) {
emu10k1_voice_t *pvoice = &emu->voices[result];
pvoice->interrupt = NULL;
- pvoice->use = pvoice->pcm = pvoice->synth = pvoice->midi = 0;
+ pvoice->use = pvoice->pcm = pvoice->synth = pvoice->midi = pvoice->efx = 0;
pvoice->epcm = NULL;
}
}
@@ -103,7 +144,7 @@ int snd_emu10k1_voice_free(emu10k1_t *emu, emu10k1_voice_t *pvoice)
snd_assert(pvoice != NULL, return -EINVAL);
spin_lock_irqsave(&emu->voice_lock, flags);
pvoice->interrupt = NULL;
- pvoice->use = pvoice->pcm = pvoice->synth = pvoice->midi = 0;
+ pvoice->use = pvoice->pcm = pvoice->synth = pvoice->midi = pvoice->efx = 0;
pvoice->epcm = NULL;
snd_emu10k1_voice_init(emu, pvoice->number);
spin_unlock_irqrestore(&emu->voice_lock, flags);
diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c
index 900069b69af9d..f910399db5c39 100644
--- a/sound/pci/ens1370.c
+++ b/sound/pci/ens1370.c
@@ -430,7 +430,7 @@ struct _snd_ensoniq {
#endif
#ifdef SUPPORT_JOYSTICK
- struct gameport gameport;
+ struct gameport *gameport;
#endif
};
@@ -1734,43 +1734,99 @@ static int __devinit snd_ensoniq_1370_mixer(ensoniq_t * ensoniq)
#endif /* CHIP1370 */
#ifdef SUPPORT_JOYSTICK
-static int snd_ensoniq_joystick(ensoniq_t *ensoniq, long port)
-{
+
#ifdef CHIP1371
- if (port == 1) { /* auto-detect */
- for (port = 0x200; port <= 0x218; port += 8)
- if (request_region(port, 8, "ens137x: gameport"))
+static int __devinit snd_ensoniq_get_joystick_port(int dev)
+{
+ switch (joystick_port[dev]) {
+ case 0: /* disabled */
+ case 1: /* auto-detect */
+ case 0x200:
+ case 0x208:
+ case 0x210:
+ case 0x218:
+ return joystick_port[dev];
+
+ default:
+ printk(KERN_ERR "ens1371: invalid joystick port %#x", joystick_port[dev]);
+ return 0;
+ }
+}
+#else
+static inline int snd_ensoniq_get_joystick_port(int dev)
+{
+ return joystick[dev] ? 0x200 : 0;
+}
+#endif
+
+static int __devinit snd_ensoniq_create_gameport(ensoniq_t *ensoniq, int dev)
+{
+ struct gameport *gp;
+ int io_port;
+
+ io_port = snd_ensoniq_get_joystick_port(dev);
+
+ switch (io_port) {
+ case 0:
+ return -ENOSYS;
+
+ case 1: /* auto_detect */
+ for (io_port = 0x200; io_port <= 0x218; io_port += 8)
+ if (request_region(io_port, 8, "ens137x: gameport"))
break;
- if (port > 0x218) {
- snd_printk("no gameport available\n");
+ if (io_port > 0x218) {
+ printk(KERN_WARNING "ens137x: no gameport ports available\n");
return -EBUSY;
}
- } else
-#endif
- {
- if (!request_region(port, 8, "ens137x: gameport")) {
- snd_printk("gameport io port 0x%03x in use", ensoniq->gameport.io);
+ break;
+
+ default:
+ if (!request_region(io_port, 8, "ens137x: gameport")) {
+ printk(KERN_WARNING "ens137x: gameport io port 0x%#x in use\n", io_port);
return -EBUSY;
}
+ break;
}
- ensoniq->gameport.io = port;
+
+ ensoniq->gameport = gp = gameport_allocate_port();
+ if (!gp) {
+ printk(KERN_ERR "ens137x: cannot allocate memory for gameport\n");
+ release_region(io_port, 8);
+ return -ENOMEM;
+ }
+
+ gameport_set_name(gp, "ES137x");
+ gameport_set_phys(gp, "pci%s/gameport0", pci_name(ensoniq->pci));
+ gameport_set_dev_parent(gp, &ensoniq->pci->dev);
+ gp->io = io_port;
+
ensoniq->ctrl |= ES_JYSTK_EN;
#ifdef CHIP1371
ensoniq->ctrl &= ~ES_1371_JOY_ASELM;
- ensoniq->ctrl |= ES_1371_JOY_ASEL((ensoniq->gameport.io - 0x200) / 8);
+ ensoniq->ctrl |= ES_1371_JOY_ASEL((io_port - 0x200) / 8);
#endif
outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL));
- gameport_register_port(&ensoniq->gameport);
+
+ gameport_register_port(ensoniq->gameport);
+
return 0;
}
-static void snd_ensoniq_joystick_free(ensoniq_t *ensoniq)
+static void snd_ensoniq_free_gameport(ensoniq_t *ensoniq)
{
- gameport_unregister_port(&ensoniq->gameport);
- ensoniq->ctrl &= ~ES_JYSTK_EN;
- outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL));
- release_region(ensoniq->gameport.io, 8);
+ if (ensoniq->gameport) {
+ int port = ensoniq->gameport->io;
+
+ gameport_unregister_port(ensoniq->gameport);
+ ensoniq->gameport = NULL;
+ ensoniq->ctrl &= ~ES_JYSTK_EN;
+ outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL));
+ release_region(port, 8);
+ }
}
+#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) { }
#endif /* SUPPORT_JOYSTICK */
/*
@@ -1810,10 +1866,7 @@ static void __devinit snd_ensoniq_proc_init(ensoniq_t * ensoniq)
static int snd_ensoniq_free(ensoniq_t *ensoniq)
{
-#ifdef SUPPORT_JOYSTICK
- if (ensoniq->ctrl & ES_JYSTK_EN)
- snd_ensoniq_joystick_free(ensoniq);
-#endif
+ snd_ensoniq_free_gameport(ensoniq);
if (ensoniq->irq < 0)
goto __hw_end;
#ifdef CHIP1370
@@ -2043,9 +2096,7 @@ static void snd_ensoniq_midi_interrupt(ensoniq_t * ensoniq)
if ((status & mask) == 0)
break;
byte = inb(ES_REG(ensoniq, UART_DATA));
- spin_unlock(&ensoniq->reg_lock);
snd_rawmidi_receive(ensoniq->midi_input, &byte, 1);
- spin_lock(&ensoniq->reg_lock);
}
spin_unlock(&ensoniq->reg_lock);
@@ -2313,22 +2364,9 @@ static int __devinit snd_audiopci_probe(struct pci_dev *pci,
snd_card_free(card);
return err;
}
-#ifdef SUPPORT_JOYSTICK
-#ifdef CHIP1371
- switch (joystick_port[dev]) {
- case 1: /* auto-detect */
- case 0x200:
- case 0x208:
- case 0x210:
- case 0x218:
- snd_ensoniq_joystick(ensoniq, joystick_port[dev]);
- break;
- }
-#else
- if (joystick[dev])
- snd_ensoniq_joystick(ensoniq, 0x200);
-#endif
-#endif /* SUPPORT_JOYSTICK */
+
+ snd_ensoniq_create_gameport(ensoniq, dev);
+
strcpy(card->driver, DRIVER_NAME);
strcpy(card->shortname, "Ensoniq AudioPCI");
diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c
index 6057e544050d5..b4ca8adf393c6 100644
--- a/sound/pci/es1938.c
+++ b/sound/pci/es1938.c
@@ -72,6 +72,10 @@ MODULE_SUPPORTED_DEVICE("{{ESS,ES1938},"
"{ESS,ES1969},"
"{TerraTec,128i PCI}}");
+#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
+#define SUPPORT_JOYSTICK 1
+#endif
+
#ifndef PCI_VENDOR_ID_ESS
#define PCI_VENDOR_ID_ESS 0x125d
#endif
@@ -237,8 +241,8 @@ struct _snd_es1938 {
spinlock_t mixer_lock;
snd_info_entry_t *proc_entry;
-#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
- struct gameport gameport;
+#ifdef SUPPORT_JOYSTICK
+ struct gameport *gameport;
#endif
#ifdef CONFIG_PM
unsigned char saved_regs[SAVED_REG_SIZE];
@@ -1381,7 +1385,7 @@ static unsigned char saved_regs[SAVED_REG_SIZE+1] = {
};
-static int es1938_suspend(snd_card_t *card, unsigned int state)
+static int es1938_suspend(snd_card_t *card, pm_message_t state)
{
es1938_t *chip = card->pm_private_data;
unsigned char *s, *d;
@@ -1398,7 +1402,7 @@ static int es1938_suspend(snd_card_t *card, unsigned int state)
return 0;
}
-static int es1938_resume(snd_card_t *card, unsigned int state)
+static int es1938_resume(snd_card_t *card)
{
es1938_t *chip = card->pm_private_data;
unsigned char *s, *d;
@@ -1418,6 +1422,39 @@ static int es1938_resume(snd_card_t *card, unsigned int state)
}
#endif /* CONFIG_PM */
+#ifdef SUPPORT_JOYSTICK
+static int __devinit snd_es1938_create_gameport(es1938_t *chip)
+{
+ struct gameport *gp;
+
+ chip->gameport = gp = gameport_allocate_port();
+ if (!gp) {
+ printk(KERN_ERR "es1938: cannot allocate memory for gameport\n");
+ return -ENOMEM;
+ }
+
+ gameport_set_name(gp, "ES1938");
+ gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci));
+ gameport_set_dev_parent(gp, &chip->pci->dev);
+ gp->io = chip->game_port;
+
+ gameport_register_port(gp);
+
+ return 0;
+}
+
+static void snd_es1938_free_gameport(es1938_t *chip)
+{
+ if (chip->gameport) {
+ gameport_unregister_port(chip->gameport);
+ chip->gameport = NULL;
+ }
+}
+#else
+static inline int snd_es1938_create_gameport(es1938_t *chip) { return -ENOSYS; }
+static inline void snd_es1938_free_gameport(es1938_t *chip) { }
+#endif /* SUPPORT_JOYSTICK */
+
static int snd_es1938_free(es1938_t *chip)
{
/* disable irqs */
@@ -1425,10 +1462,8 @@ static int snd_es1938_free(es1938_t *chip)
if (chip->rmidi)
snd_es1938_mixer_bits(chip, ESSSB_IREG_MPU401CONTROL, 0x40, 0);
-#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
- if (chip->gameport.io)
- gameport_unregister_port(&chip->gameport);
-#endif
+ snd_es1938_free_gameport(chip);
+
if (chip->irq >= 0)
free_irq(chip->irq, (void *)chip);
pci_release_regions(chip->pci);
@@ -1698,10 +1733,7 @@ static int __devinit snd_es1938_probe(struct pci_dev *pci,
snd_es1938_mixer_bits(chip, ESSSB_IREG_MPU401CONTROL, 0x40, 0x40);
}
-#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
- chip->gameport.io = chip->game_port;
- gameport_register_port(&chip->gameport);
-#endif
+ snd_es1938_create_gameport(chip);
if ((err = snd_card_register(card)) < 0) {
snd_card_free(card);
diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c
index 12ac754801a6b..faf63ff19c42a 100644
--- a/sound/pci/es1968.c
+++ b/sound/pci/es1968.c
@@ -586,6 +586,7 @@ struct snd_es1968 {
spinlock_t reg_lock;
spinlock_t ac97_lock;
struct tasklet_struct hwvol_tq;
+ unsigned int in_suspend;
/* Maestro Stuff */
u16 maestro_map[32];
@@ -605,8 +606,7 @@ struct snd_es1968 {
#endif
#ifdef SUPPORT_JOYSTICK
- struct gameport gameport;
- struct resource *res_joystick;
+ struct gameport *gameport;
#endif
};
@@ -1938,6 +1938,9 @@ static void es1968_update_hw_volume(unsigned long private_data)
outb(0x88, chip->io_port + 0x1e);
outb(0x88, chip->io_port + 0x1f);
+ if (chip->in_suspend)
+ return;
+
if (! chip->master_switch || ! chip->master_volume)
return;
@@ -2404,13 +2407,14 @@ static void snd_es1968_start_irq(es1968_t *chip)
/*
* PM support
*/
-static int es1968_suspend(snd_card_t *card, unsigned int state)
+static int es1968_suspend(snd_card_t *card, pm_message_t state)
{
es1968_t *chip = card->pm_private_data;
if (! chip->do_pm)
return 0;
+ chip->in_suspend = 1;
snd_pcm_suspend_all(chip->pcm);
snd_ac97_suspend(chip->ac97);
snd_es1968_bob_stop(chip);
@@ -2419,9 +2423,10 @@ static int es1968_suspend(snd_card_t *card, unsigned int state)
return 0;
}
-static int es1968_resume(snd_card_t *card, unsigned int state)
+static int es1968_resume(snd_card_t *card)
{
es1968_t *chip = card->pm_private_data;
+ struct list_head *p;
if (! chip->do_pm)
return 0;
@@ -2442,14 +2447,81 @@ static int es1968_resume(snd_card_t *card, unsigned int state)
/* restore ac97 state */
snd_ac97_resume(chip->ac97);
+ list_for_each(p, &chip->substream_list) {
+ esschan_t *es = list_entry(p, esschan_t, list);
+ switch (es->mode) {
+ case ESM_MODE_PLAY:
+ snd_es1968_playback_setup(chip, es, es->substream->runtime);
+ break;
+ case ESM_MODE_CAPTURE:
+ snd_es1968_capture_setup(chip, es, es->substream->runtime);
+ break;
+ }
+ }
+
/* start timer again */
if (chip->bobclient)
snd_es1968_bob_start(chip);
+ chip->in_suspend = 0;
return 0;
}
#endif /* CONFIG_PM */
+#ifdef SUPPORT_JOYSTICK
+#define JOYSTICK_ADDR 0x200
+static int __devinit snd_es1968_create_gameport(es1968_t *chip, int dev)
+{
+ struct gameport *gp;
+ struct resource *r;
+ u16 val;
+
+ if (!joystick[dev])
+ return -ENODEV;
+
+ r = request_region(JOYSTICK_ADDR, 8, "ES1968 gameport");
+ if (!r)
+ return -EBUSY;
+
+ chip->gameport = gp = gameport_allocate_port();
+ if (!gp) {
+ printk(KERN_ERR "es1968: cannot allocate memory for gameport\n");
+ release_resource(r);
+ kfree_nocheck(r);
+ return -ENOMEM;
+ }
+
+ pci_read_config_word(chip->pci, ESM_LEGACY_AUDIO_CONTROL, &val);
+ pci_write_config_word(chip->pci, ESM_LEGACY_AUDIO_CONTROL, val | 0x04);
+
+ gameport_set_name(gp, "ES1968 Gameport");
+ gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci));
+ gameport_set_dev_parent(gp, &chip->pci->dev);
+ gp->io = JOYSTICK_ADDR;
+ gameport_set_port_data(gp, r);
+
+ gameport_register_port(gp);
+
+ return 0;
+}
+
+static void snd_es1968_free_gameport(es1968_t *chip)
+{
+ if (chip->gameport) {
+ struct resource *r = gameport_get_port_data(chip->gameport);
+
+ gameport_unregister_port(chip->gameport);
+ chip->gameport = NULL;
+
+ release_resource(r);
+ kfree_nocheck(r);
+ }
+}
+#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) { }
+#endif
+
static int snd_es1968_free(es1968_t *chip)
{
if (chip->io_port) {
@@ -2460,13 +2532,7 @@ static int snd_es1968_free(es1968_t *chip)
if (chip->irq >= 0)
free_irq(chip->irq, (void *)chip);
-#ifdef SUPPORT_JOYSTICK
- if (chip->res_joystick) {
- gameport_unregister_port(&chip->gameport);
- release_resource(chip->res_joystick);
- kfree_nocheck(chip->res_joystick);
- }
-#endif
+ snd_es1968_free_gameport(chip);
snd_es1968_set_acpi(chip, ACPI_D3);
chip->master_switch = NULL;
chip->master_volume = NULL;
@@ -2693,17 +2759,7 @@ static int __devinit snd_es1968_probe(struct pci_dev *pci,
}
}
-#ifdef SUPPORT_JOYSTICK
-#define JOYSTICK_ADDR 0x200
- if (joystick[dev] &&
- (chip->res_joystick = request_region(JOYSTICK_ADDR, 8, "ES1968 gameport")) != NULL) {
- u16 val;
- pci_read_config_word(pci, ESM_LEGACY_AUDIO_CONTROL, &val);
- pci_write_config_word(pci, ESM_LEGACY_AUDIO_CONTROL, val | 0x04);
- chip->gameport.io = JOYSTICK_ADDR;
- gameport_register_port(&chip->gameport);
- }
-#endif
+ snd_es1968_create_gameport(chip, dev);
snd_es1968_start_irq(chip);
diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c
index b67761b8489e5..08e7c5a296d54 100644
--- a/sound/pci/fm801.c
+++ b/sound/pci/fm801.c
@@ -64,7 +64,7 @@ module_param_array(id, charp, NULL, 0444);
MODULE_PARM_DESC(id, "ID string for the FM801 soundcard.");
module_param_array(enable, bool, NULL, 0444);
MODULE_PARM_DESC(enable, "Enable FM801 soundcard.");
-module_param_array(tea575x_tuner, bool, NULL, 0444);
+module_param_array(tea575x_tuner, int, NULL, 0444);
MODULE_PARM_DESC(tea575x_tuner, "Enable TEA575x tuner.");
/*
diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile
new file mode 100644
index 0000000000000..570a59d33b419
--- /dev/null
+++ b/sound/pci/hda/Makefile
@@ -0,0 +1,7 @@
+snd-hda-intel-objs := hda_intel.o
+snd-hda-codec-objs := hda_codec.o hda_generic.o patch_realtek.o patch_cmedia.o patch_analog.o
+ifdef CONFIG_PROC_FS
+snd-hda-codec-objs += hda_proc.o
+endif
+
+obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-intel.o snd-hda-codec.o
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
new file mode 100644
index 0000000000000..9ed117ac0c090
--- /dev/null
+++ b/sound/pci/hda/hda_codec.c
@@ -0,0 +1,1856 @@
+/*
+ * Universal Interface for Intel High Definition Audio Codec
+ *
+ * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
+ *
+ *
+ * This driver is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This driver is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <sound/driver.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/moduleparam.h>
+#include <sound/core.h>
+#include "hda_codec.h"
+#include <sound/asoundef.h>
+#include <sound/initval.h>
+#include "hda_local.h"
+
+
+MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
+MODULE_DESCRIPTION("Universal interface for High Definition Audio Codec");
+MODULE_LICENSE("GPL");
+
+
+/*
+ * vendor / preset table
+ */
+
+struct hda_vendor_id {
+ unsigned int id;
+ const char *name;
+};
+
+/* codec vendor labels */
+static struct hda_vendor_id hda_vendor_ids[] = {
+ { 0x10ec, "Realtek" },
+ { 0x13f6, "C-Media" },
+ { 0x434d, "C-Media" },
+ {} /* terminator */
+};
+
+/* codec presets */
+#include "hda_patch.h"
+
+
+/**
+ * snd_hda_codec_read - send a command and get the response
+ * @codec: the HDA codec
+ * @nid: NID to send the command
+ * @direct: direct flag
+ * @verb: the verb to send
+ * @parm: the parameter for the verb
+ *
+ * Send a single command and read the corresponding response.
+ *
+ * Returns the obtained response value, or -1 for an error.
+ */
+unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid, int direct,
+ unsigned int verb, unsigned int parm)
+{
+ unsigned int res;
+ down(&codec->bus->cmd_mutex);
+ if (! codec->bus->ops.command(codec, nid, direct, verb, parm))
+ res = codec->bus->ops.get_response(codec);
+ else
+ res = (unsigned int)-1;
+ up(&codec->bus->cmd_mutex);
+ return res;
+}
+
+/**
+ * snd_hda_codec_write - send a single command without waiting for response
+ * @codec: the HDA codec
+ * @nid: NID to send the command
+ * @direct: direct flag
+ * @verb: the verb to send
+ * @parm: the parameter for the verb
+ *
+ * Send a single command without waiting for response.
+ *
+ * Returns 0 if successful, or a negative error code.
+ */
+int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int direct,
+ unsigned int verb, unsigned int parm)
+{
+ int err;
+ down(&codec->bus->cmd_mutex);
+ err = codec->bus->ops.command(codec, nid, direct, verb, parm);
+ up(&codec->bus->cmd_mutex);
+ return err;
+}
+
+/**
+ * snd_hda_sequence_write - sequence writes
+ * @codec: the HDA codec
+ * @seq: VERB array to send
+ *
+ * Send the commands sequentially from the given array.
+ * The array must be terminated with NID=0.
+ */
+void snd_hda_sequence_write(struct hda_codec *codec, const struct hda_verb *seq)
+{
+ for (; seq->nid; seq++)
+ snd_hda_codec_write(codec, seq->nid, 0, seq->verb, seq->param);
+}
+
+/**
+ * snd_hda_get_sub_nodes - get the range of sub nodes
+ * @codec: the HDA codec
+ * @nid: NID to parse
+ * @start_id: the pointer to store the start NID
+ *
+ * Parse the NID and store the start NID of its sub-nodes.
+ * Returns the number of sub-nodes.
+ */
+int snd_hda_get_sub_nodes(struct hda_codec *codec, hda_nid_t nid, hda_nid_t *start_id)
+{
+ unsigned int parm;
+
+ parm = snd_hda_param_read(codec, nid, AC_PAR_NODE_COUNT);
+ *start_id = (parm >> 16) & 0x7fff;
+ return (int)(parm & 0x7fff);
+}
+
+/**
+ * snd_hda_get_connections - get connection list
+ * @codec: the HDA codec
+ * @nid: NID to parse
+ * @conn_list: connection list array
+ * @max_conns: max. number of connections to store
+ *
+ * Parses the connection list of the given widget and stores the list
+ * of NIDs.
+ *
+ * Returns the number of connections, or a negative error code.
+ */
+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;
+ unsigned int shift, num_elems, mask;
+
+ snd_assert(conn_list && max_conns > 0, return -EINVAL);
+
+ parm = snd_hda_param_read(codec, nid, AC_PAR_CONNLIST_LEN);
+ if (parm & AC_CLIST_LONG) {
+ /* long form */
+ shift = 16;
+ num_elems = 2;
+ } else {
+ /* short form */
+ shift = 8;
+ num_elems = 4;
+ }
+ conn_len = parm & AC_CLIST_LENGTH;
+ num_tupples = num_elems / 2;
+ mask = (1 << (shift-1)) - 1;
+
+ if (! conn_len)
+ return 0; /* no connection */
+
+ if (conn_len == 1) {
+ /* single connection */
+ parm = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_LIST, 0);
+ conn_list[0] = parm & mask;
+ return 1;
+ }
+
+ /* 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)
+ return -EINVAL;
+ conn_list[conns++] = val2;
+ }
+ }
+ }
+ return conns;
+}
+
+
+/**
+ * snd_hda_queue_unsol_event - add an unsolicited event to queue
+ * @bus: the BUS
+ * @res: unsolicited event (lower 32bit of RIRB entry)
+ * @res_ex: codec addr and flags (upper 32bit or RIRB entry)
+ *
+ * Adds the given event to the queue. The events are processed in
+ * the workqueue asynchronously. Call this function in the interrupt
+ * hanlder when RIRB receives an unsolicited event.
+ *
+ * Returns 0 if successful, or a negative error code.
+ */
+int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex)
+{
+ struct hda_bus_unsolicited *unsol;
+ unsigned int wp;
+
+ if ((unsol = bus->unsol) == NULL)
+ return 0;
+
+ wp = (unsol->wp + 1) % HDA_UNSOL_QUEUE_SIZE;
+ unsol->wp = wp;
+
+ wp <<= 1;
+ unsol->queue[wp] = res;
+ unsol->queue[wp + 1] = res_ex;
+
+ queue_work(unsol->workq, &unsol->work);
+
+ return 0;
+}
+
+/*
+ * process queueud unsolicited events
+ */
+static void process_unsol_events(void *data)
+{
+ struct hda_bus *bus = data;
+ struct hda_bus_unsolicited *unsol = bus->unsol;
+ struct hda_codec *codec;
+ unsigned int rp, caddr, res;
+
+ while (unsol->rp != unsol->wp) {
+ rp = (unsol->rp + 1) % HDA_UNSOL_QUEUE_SIZE;
+ unsol->rp = rp;
+ rp <<= 1;
+ res = unsol->queue[rp];
+ caddr = unsol->queue[rp + 1];
+ if (! (caddr & (1 << 4))) /* no unsolicited event? */
+ continue;
+ codec = bus->caddr_tbl[caddr & 0x0f];
+ if (codec && codec->patch_ops.unsol_event)
+ codec->patch_ops.unsol_event(codec, res);
+ }
+}
+
+/*
+ * initialize unsolicited queue
+ */
+static int init_unsol_queue(struct hda_bus *bus)
+{
+ struct hda_bus_unsolicited *unsol;
+
+ unsol = kcalloc(1, sizeof(*unsol), GFP_KERNEL);
+ if (! unsol) {
+ snd_printk(KERN_ERR "hda_codec: can't allocate unsolicited queue\n");
+ return -ENOMEM;
+ }
+ unsol->workq = create_workqueue("hda_codec");
+ if (! unsol->workq) {
+ snd_printk(KERN_ERR "hda_codec: can't create workqueue\n");
+ kfree(unsol);
+ return -ENOMEM;
+ }
+ INIT_WORK(&unsol->work, process_unsol_events, bus);
+ bus->unsol = unsol;
+ return 0;
+}
+
+/*
+ * destructor
+ */
+static void snd_hda_codec_free(struct hda_codec *codec);
+
+static int snd_hda_bus_free(struct hda_bus *bus)
+{
+ struct list_head *p, *n;
+
+ if (! bus)
+ return 0;
+ if (bus->unsol) {
+ destroy_workqueue(bus->unsol->workq);
+ kfree(bus->unsol);
+ }
+ list_for_each_safe(p, n, &bus->codec_list) {
+ struct hda_codec *codec = list_entry(p, struct hda_codec, list);
+ snd_hda_codec_free(codec);
+ }
+ if (bus->ops.private_free)
+ bus->ops.private_free(bus);
+ kfree(bus);
+ return 0;
+}
+
+static int snd_hda_bus_dev_free(snd_device_t *device)
+{
+ struct hda_bus *bus = device->device_data;
+ return snd_hda_bus_free(bus);
+}
+
+/**
+ * snd_hda_bus_new - create a HDA bus
+ * @card: the card entry
+ * @temp: the template for hda_bus information
+ * @busp: the pointer to store the created bus instance
+ *
+ * Returns 0 if successful, or a negative error code.
+ */
+int snd_hda_bus_new(snd_card_t *card, const struct hda_bus_template *temp,
+ struct hda_bus **busp)
+{
+ struct hda_bus *bus;
+ int err;
+ static snd_device_ops_t dev_ops = {
+ .dev_free = snd_hda_bus_dev_free,
+ };
+
+ snd_assert(temp, return -EINVAL);
+ snd_assert(temp->ops.command && temp->ops.get_response, return -EINVAL);
+
+ if (busp)
+ *busp = NULL;
+
+ bus = kcalloc(1, sizeof(*bus), GFP_KERNEL);
+ if (bus == NULL) {
+ snd_printk(KERN_ERR "can't allocate struct hda_bus\n");
+ return -ENOMEM;
+ }
+
+ bus->card = card;
+ bus->private_data = temp->private_data;
+ bus->pci = temp->pci;
+ bus->modelname = temp->modelname;
+ bus->ops = temp->ops;
+
+ 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;
+ }
+ if (busp)
+ *busp = bus;
+ return 0;
+}
+
+
+/*
+ * find a matching codec preset
+ */
+static const struct hda_codec_preset *find_codec_preset(struct hda_codec *codec)
+{
+ const struct hda_codec_preset **tbl, *preset;
+
+ for (tbl = hda_preset_tables; *tbl; tbl++) {
+ for (preset = *tbl; preset->id; preset++) {
+ u32 mask = preset->mask;
+ if (! mask)
+ mask = ~0;
+ if (preset->id == (codec->vendor_id & mask))
+ return preset;
+ }
+ }
+ return NULL;
+}
+
+/*
+ * snd_hda_get_codec_name - store the codec name
+ */
+void snd_hda_get_codec_name(struct hda_codec *codec,
+ char *name, int namelen)
+{
+ const struct hda_vendor_id *c;
+ const char *vendor = NULL;
+ u16 vendor_id = codec->vendor_id >> 16;
+ char tmp[16];
+
+ for (c = hda_vendor_ids; c->id; c++) {
+ if (c->id == vendor_id) {
+ vendor = c->name;
+ break;
+ }
+ }
+ if (! vendor) {
+ sprintf(tmp, "Generic %04x", vendor_id);
+ vendor = tmp;
+ }
+ if (codec->preset && codec->preset->name)
+ snprintf(name, namelen, "%s %s", vendor, codec->preset->name);
+ else
+ snprintf(name, namelen, "%s ID %x", vendor, codec->vendor_id & 0xffff);
+}
+
+/*
+ * look for an AFG node
+ *
+ * return 0 if not found
+ */
+static int look_for_afg_node(struct hda_codec *codec)
+{
+ int i, total_nodes;
+ hda_nid_t nid;
+
+ total_nodes = snd_hda_get_sub_nodes(codec, AC_NODE_ROOT, &nid);
+ for (i = 0; i < total_nodes; i++, nid++) {
+ if ((snd_hda_param_read(codec, nid, AC_PAR_FUNCTION_TYPE) & 0xff) ==
+ AC_GRP_AUDIO_FUNCTION)
+ return nid;
+ }
+ return 0;
+}
+
+/*
+ * codec destructor
+ */
+static void snd_hda_codec_free(struct hda_codec *codec)
+{
+ if (! codec)
+ return;
+ list_del(&codec->list);
+ codec->bus->caddr_tbl[codec->addr] = NULL;
+ if (codec->patch_ops.free)
+ codec->patch_ops.free(codec);
+ kfree(codec);
+}
+
+static void init_amp_hash(struct hda_codec *codec);
+
+/**
+ * snd_hda_codec_new - create a HDA codec
+ * @bus: the bus to assign
+ * @codec_addr: the codec address
+ * @codecp: the pointer to store the generated codec
+ *
+ * Returns 0 if successful, or a negative error code.
+ */
+int snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
+ struct hda_codec **codecp)
+{
+ struct hda_codec *codec;
+ char component[13];
+ int err;
+
+ snd_assert(bus, return -EINVAL);
+ snd_assert(codec_addr <= HDA_MAX_CODEC_ADDRESS, return -EINVAL);
+
+ if (bus->caddr_tbl[codec_addr]) {
+ snd_printk(KERN_ERR "hda_codec: address 0x%x is already occupied\n", codec_addr);
+ return -EBUSY;
+ }
+
+ codec = kcalloc(1, sizeof(*codec), GFP_KERNEL);
+ if (codec == NULL) {
+ snd_printk(KERN_ERR "can't allocate struct hda_codec\n");
+ return -ENOMEM;
+ }
+
+ codec->bus = bus;
+ codec->addr = codec_addr;
+ init_MUTEX(&codec->spdif_mutex);
+ init_amp_hash(codec);
+
+ list_add_tail(&codec->list, &bus->codec_list);
+ bus->caddr_tbl[codec_addr] = codec;
+
+ codec->vendor_id = snd_hda_param_read(codec, AC_NODE_ROOT, AC_PAR_VENDOR_ID);
+ codec->subsystem_id = snd_hda_param_read(codec, AC_NODE_ROOT, AC_PAR_SUBSYSTEM_ID);
+ codec->revision_id = snd_hda_param_read(codec, AC_NODE_ROOT, AC_PAR_REV_ID);
+
+ /* FIXME: support for multiple AFGs? */
+ codec->afg = look_for_afg_node(codec);
+ if (! codec->afg) {
+ snd_printk(KERN_ERR "hda_codec: no AFG node found\n");
+ snd_hda_codec_free(codec);
+ return -ENODEV;
+ }
+
+ codec->preset = find_codec_preset(codec);
+ if (! *bus->card->mixername)
+ snd_hda_get_codec_name(codec, bus->card->mixername,
+ sizeof(bus->card->mixername));
+
+ if (codec->preset && codec->preset->patch)
+ err = codec->preset->patch(codec);
+ else
+ err = snd_hda_parse_generic_codec(codec);
+ if (err < 0) {
+ snd_hda_codec_free(codec);
+ return err;
+ }
+
+ snd_hda_codec_proc_new(codec);
+
+ sprintf(component, "HDA:%08x", codec->vendor_id);
+ snd_component_add(codec->bus->card, component);
+
+ if (codecp)
+ *codecp = codec;
+ return 0;
+}
+
+/**
+ * snd_hda_codec_setup_stream - set up the codec for streaming
+ * @codec: the CODEC to set up
+ * @nid: the NID to set up
+ * @stream_tag: stream tag to pass, it's between 0x1 and 0xf.
+ * @channel_id: channel id to pass, zero based.
+ * @format: stream format.
+ */
+void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid, u32 stream_tag,
+ int channel_id, int format)
+{
+ snd_printdd("hda_codec_setup_stream: NID=0x%x, stream=0x%x, channel=%d, format=0x%x\n",
+ nid, stream_tag, channel_id, format);
+ snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID,
+ (stream_tag << 4) | channel_id);
+ msleep(1);
+ snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, format);
+}
+
+
+/*
+ * amp access functions
+ */
+
+#define HDA_HASH_KEY(nid,dir,idx) (u32)((nid) + (idx) * 32 + (dir) * 64)
+#define INFO_AMP_CAPS (1<<0)
+#define INFO_AMP_VOL (1<<1)
+
+/* initialize the hash table */
+static void init_amp_hash(struct hda_codec *codec)
+{
+ memset(codec->amp_hash, 0xff, sizeof(codec->amp_hash));
+ codec->num_amp_entries = 0;
+}
+
+/* query the hash. allocate an entry if not found. */
+static struct hda_amp_info *get_alloc_amp_hash(struct hda_codec *codec, u32 key)
+{
+ u16 idx = key % (u16)ARRAY_SIZE(codec->amp_hash);
+ u16 cur = codec->amp_hash[idx];
+ struct hda_amp_info *info;
+
+ while (cur != 0xffff) {
+ info = &codec->amp_info[cur];
+ if (info->key == key)
+ return info;
+ cur = info->next;
+ }
+
+ /* 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;
+ }
+ cur = codec->num_amp_entries++;
+ info = &codec->amp_info[cur];
+ info->key = key;
+ info->status = 0; /* not initialized yet */
+ info->next = codec->amp_hash[idx];
+ codec->amp_hash[idx] = cur;
+
+ return info;
+}
+
+/*
+ * query AMP capabilities for the given widget and direction
+ */
+static u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction)
+{
+ struct hda_amp_info *info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, 0));
+
+ 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))
+ 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);
+ info->status |= INFO_AMP_CAPS;
+ }
+ return info->amp_caps;
+}
+
+/*
+ * read the current volume to info
+ * if the cache exists, read from the cache.
+ */
+static void get_vol_mute(struct hda_codec *codec, struct hda_amp_info *info,
+ hda_nid_t nid, int ch, int direction, int index)
+{
+ u32 val, parm;
+
+ if (info->status & (INFO_AMP_VOL << ch))
+ return;
+
+ parm = ch ? AC_AMP_GET_RIGHT : AC_AMP_GET_LEFT;
+ parm |= direction == HDA_OUTPUT ? AC_AMP_GET_OUTPUT : AC_AMP_GET_INPUT;
+ parm |= index;
+ val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_AMP_GAIN_MUTE, parm);
+ info->vol[ch] = val & 0xff;
+ info->status |= INFO_AMP_VOL << ch;
+}
+
+/*
+ * write the current volume in info to the h/w
+ */
+static void put_vol_mute(struct hda_codec *codec,
+ hda_nid_t nid, int ch, int direction, int index, int val)
+{
+ u32 parm;
+
+ parm = ch ? AC_AMP_SET_RIGHT : AC_AMP_SET_LEFT;
+ parm |= direction == HDA_OUTPUT ? AC_AMP_SET_OUTPUT : AC_AMP_SET_INPUT;
+ parm |= index << AC_AMP_SET_INDEX_SHIFT;
+ parm |= val;
+ snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, parm);
+}
+
+/*
+ * read/write AMP value. The volume is between 0 to 0x7f, 0x80 = mute bit.
+ */
+int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch, int direction, int index)
+{
+ struct hda_amp_info *info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, index));
+ if (! info)
+ return 0;
+ get_vol_mute(codec, info, nid, ch, direction, index);
+ return info->vol[ch];
+}
+
+int snd_hda_codec_amp_write(struct hda_codec *codec, hda_nid_t nid, int ch, int direction, int idx, int val)
+{
+ struct hda_amp_info *info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, idx));
+ if (! info)
+ return 0;
+ get_vol_mute(codec, info, nid, ch, direction, idx);
+ if (info->vol[ch] == val && ! codec->in_resume)
+ return 0;
+ put_vol_mute(codec, nid, ch, direction, idx, val);
+ info->vol[ch] = val;
+ return 1;
+}
+
+
+/*
+ * AMP control callbacks
+ */
+/* retrieve parameters from private_value */
+#define get_amp_nid(kc) ((kc)->private_value & 0xffff)
+#define get_amp_channels(kc) (((kc)->private_value >> 16) & 0x3)
+#define get_amp_direction(kc) (((kc)->private_value >> 18) & 0x1)
+#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)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ u16 nid = get_amp_nid(kcontrol);
+ u8 chs = get_amp_channels(kcontrol);
+ int dir = get_amp_direction(kcontrol);
+ u32 caps;
+
+ caps = query_amp_caps(codec, nid, dir);
+ caps = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT; /* num steps */
+ if (! caps) {
+ printk(KERN_WARNING "hda_codec: num_steps = 0 for NID=0x%x\n", nid);
+ return -EINVAL;
+ }
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = chs == 3 ? 2 : 1;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = caps;
+ return 0;
+}
+
+int snd_hda_mixer_amp_volume_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ hda_nid_t nid = get_amp_nid(kcontrol);
+ int chs = get_amp_channels(kcontrol);
+ int dir = get_amp_direction(kcontrol);
+ int idx = get_amp_index(kcontrol);
+ long *valp = ucontrol->value.integer.value;
+
+ if (chs & 1)
+ *valp++ = snd_hda_codec_amp_read(codec, nid, 0, dir, idx) & 0x7f;
+ if (chs & 2)
+ *valp = snd_hda_codec_amp_read(codec, nid, 1, dir, idx) & 0x7f;
+ return 0;
+}
+
+int snd_hda_mixer_amp_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ hda_nid_t nid = get_amp_nid(kcontrol);
+ int chs = get_amp_channels(kcontrol);
+ int dir = get_amp_direction(kcontrol);
+ int idx = get_amp_index(kcontrol);
+ int val;
+ long *valp = ucontrol->value.integer.value;
+ int change = 0;
+
+ if (chs & 1) {
+ val = *valp & 0x7f;
+ val |= snd_hda_codec_amp_read(codec, nid, 0, dir, idx) & 0x80;
+ change = snd_hda_codec_amp_write(codec, nid, 0, dir, idx, val);
+ valp++;
+ }
+ if (chs & 2) {
+ val = *valp & 0x7f;
+ val |= snd_hda_codec_amp_read(codec, nid, 1, dir, idx) & 0x80;
+ change |= snd_hda_codec_amp_write(codec, nid, 1, dir, idx, val);
+ }
+ return change;
+}
+
+/* switch */
+int snd_hda_mixer_amp_switch_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+ int chs = get_amp_channels(kcontrol);
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+ uinfo->count = chs == 3 ? 2 : 1;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 1;
+ return 0;
+}
+
+int snd_hda_mixer_amp_switch_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ hda_nid_t nid = get_amp_nid(kcontrol);
+ int chs = get_amp_channels(kcontrol);
+ int dir = get_amp_direction(kcontrol);
+ int idx = get_amp_index(kcontrol);
+ long *valp = ucontrol->value.integer.value;
+
+ if (chs & 1)
+ *valp++ = (snd_hda_codec_amp_read(codec, nid, 0, dir, idx) & 0x80) ? 0 : 1;
+ if (chs & 2)
+ *valp = (snd_hda_codec_amp_read(codec, nid, 1, dir, idx) & 0x80) ? 0 : 1;
+ return 0;
+}
+
+int snd_hda_mixer_amp_switch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ hda_nid_t nid = get_amp_nid(kcontrol);
+ int chs = get_amp_channels(kcontrol);
+ int dir = get_amp_direction(kcontrol);
+ int idx = get_amp_index(kcontrol);
+ int val;
+ long *valp = ucontrol->value.integer.value;
+ int change = 0;
+
+ if (chs & 1) {
+ val = snd_hda_codec_amp_read(codec, nid, 0, dir, idx) & 0x7f;
+ val |= *valp ? 0 : 0x80;
+ change = snd_hda_codec_amp_write(codec, nid, 0, dir, idx, val);
+ valp++;
+ }
+ if (chs & 2) {
+ val = snd_hda_codec_amp_read(codec, nid, 1, dir, idx) & 0x7f;
+ val |= *valp ? 0 : 0x80;
+ change = snd_hda_codec_amp_write(codec, nid, 1, dir, idx, val);
+ }
+ return change;
+}
+
+/*
+ * SPDIF out controls
+ */
+
+static int snd_hda_spdif_mask_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *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)
+{
+ ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL |
+ IEC958_AES0_NONAUDIO |
+ IEC958_AES0_CON_EMPHASIS_5015 |
+ IEC958_AES0_CON_NOT_COPYRIGHT;
+ ucontrol->value.iec958.status[1] = IEC958_AES1_CON_CATEGORY |
+ IEC958_AES1_CON_ORIGINAL;
+ return 0;
+}
+
+static int snd_hda_spdif_pmask_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+ ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL |
+ IEC958_AES0_NONAUDIO |
+ IEC958_AES0_PRO_EMPHASIS_5015;
+ return 0;
+}
+
+static int snd_hda_spdif_default_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+
+ ucontrol->value.iec958.status[0] = codec->spdif_status & 0xff;
+ ucontrol->value.iec958.status[1] = (codec->spdif_status >> 8) & 0xff;
+ ucontrol->value.iec958.status[2] = (codec->spdif_status >> 16) & 0xff;
+ ucontrol->value.iec958.status[3] = (codec->spdif_status >> 24) & 0xff;
+
+ return 0;
+}
+
+/* convert from SPDIF status bits to HDA SPDIF bits
+ * bit 0 (DigEn) is always set zero (to be filled later)
+ */
+static unsigned short convert_from_spdif_status(unsigned int sbits)
+{
+ unsigned short val = 0;
+
+ if (sbits & IEC958_AES0_PROFESSIONAL)
+ val |= 1 << 6;
+ if (sbits & IEC958_AES0_NONAUDIO)
+ val |= 1 << 5;
+ if (sbits & IEC958_AES0_PROFESSIONAL) {
+ if ((sbits & IEC958_AES0_PRO_EMPHASIS) == IEC958_AES0_PRO_EMPHASIS_5015)
+ val |= 1 << 3;
+ } else {
+ if ((sbits & IEC958_AES0_CON_EMPHASIS) == IEC958_AES0_CON_EMPHASIS_5015)
+ val |= 1 << 3;
+ if (! (sbits & IEC958_AES0_CON_NOT_COPYRIGHT))
+ val |= 1 << 4;
+ if (sbits & (IEC958_AES1_CON_ORIGINAL << 8))
+ val |= 1 << 7;
+ val |= sbits & (IEC958_AES1_CON_CATEGORY << 8);
+ }
+ return val;
+}
+
+/* convert to SPDIF status bits from HDA SPDIF bits
+ */
+static unsigned int convert_to_spdif_status(unsigned short val)
+{
+ unsigned int sbits = 0;
+
+ if (val & (1 << 5))
+ sbits |= IEC958_AES0_NONAUDIO;
+ if (val & (1 << 6))
+ sbits |= IEC958_AES0_PROFESSIONAL;
+ if (sbits & IEC958_AES0_PROFESSIONAL) {
+ if (sbits & (1 << 3))
+ sbits |= IEC958_AES0_PRO_EMPHASIS_5015;
+ } else {
+ if (val & (1 << 3))
+ sbits |= IEC958_AES0_CON_EMPHASIS_5015;
+ if (! (val & (1 << 4)))
+ sbits |= IEC958_AES0_CON_NOT_COPYRIGHT;
+ if (val & (1 << 7))
+ sbits |= (IEC958_AES1_CON_ORIGINAL << 8);
+ sbits |= val & (0x7f << 8);
+ }
+ return sbits;
+}
+
+static int snd_hda_spdif_default_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ hda_nid_t nid = kcontrol->private_value;
+ unsigned short val;
+ int change;
+
+ down(&codec->spdif_mutex);
+ codec->spdif_status = ucontrol->value.iec958.status[0] |
+ ((unsigned int)ucontrol->value.iec958.status[1] << 8) |
+ ((unsigned int)ucontrol->value.iec958.status[2] << 16) |
+ ((unsigned int)ucontrol->value.iec958.status[3] << 24);
+ val = convert_from_spdif_status(codec->spdif_status);
+ val |= codec->spdif_ctls & 1;
+ change = codec->spdif_ctls != val;
+ codec->spdif_ctls = val;
+
+ if (change || codec->in_resume) {
+ snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, val & 0xff);
+ snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_2, val >> 8);
+ }
+
+ up(&codec->spdif_mutex);
+ return change;
+}
+
+static int snd_hda_spdif_out_switch_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+ uinfo->count = 1;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 1;
+ return 0;
+}
+
+static int snd_hda_spdif_out_switch_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+
+ ucontrol->value.integer.value[0] = codec->spdif_ctls & 1;
+ return 0;
+}
+
+static int snd_hda_spdif_out_switch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ hda_nid_t nid = kcontrol->private_value;
+ unsigned short val;
+ int change;
+
+ down(&codec->spdif_mutex);
+ val = codec->spdif_ctls & ~1;
+ if (ucontrol->value.integer.value[0])
+ val |= 1;
+ change = codec->spdif_ctls != val;
+ if (change || codec->in_resume) {
+ codec->spdif_ctls = val;
+ snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, val & 0xff);
+ snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+ AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT |
+ AC_AMP_SET_OUTPUT | ((val & 1) ? 0 : 0x80));
+ }
+ up(&codec->spdif_mutex);
+ return change;
+}
+
+static snd_kcontrol_new_t dig_mixes[] = {
+ {
+ .access = SNDRV_CTL_ELEM_ACCESS_READ,
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK),
+ .info = snd_hda_spdif_mask_info,
+ .get = snd_hda_spdif_cmask_get,
+ },
+ {
+ .access = SNDRV_CTL_ELEM_ACCESS_READ,
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PRO_MASK),
+ .info = snd_hda_spdif_mask_info,
+ .get = snd_hda_spdif_pmask_get,
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
+ .info = snd_hda_spdif_mask_info,
+ .get = snd_hda_spdif_default_get,
+ .put = snd_hda_spdif_default_put,
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH),
+ .info = snd_hda_spdif_out_switch_info,
+ .get = snd_hda_spdif_out_switch_get,
+ .put = snd_hda_spdif_out_switch_put,
+ },
+ { } /* end */
+};
+
+/**
+ * snd_hda_create_spdif_out_ctls - create Output SPDIF-related controls
+ * @codec: the HDA codec
+ * @nid: audio out widget NID
+ *
+ * Creates controls related with the SPDIF output.
+ * Called from each patch supporting the SPDIF out.
+ *
+ * Returns 0 if successful, or a negative error code.
+ */
+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;
+
+ for (dig_mix = dig_mixes; dig_mix->name; dig_mix++) {
+ kctl = snd_ctl_new1(dig_mix, codec);
+ kctl->private_value = nid;
+ if ((err = snd_ctl_add(codec->bus->card, kctl)) < 0)
+ return err;
+ }
+ codec->spdif_ctls = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_DIGI_CONVERT, 0);
+ codec->spdif_status = convert_to_spdif_status(codec->spdif_ctls);
+ return 0;
+}
+
+/*
+ * SPDIF input
+ */
+
+#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)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+
+ ucontrol->value.integer.value[0] = codec->spdif_in_enable;
+ return 0;
+}
+
+static int snd_hda_spdif_in_switch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ hda_nid_t nid = kcontrol->private_value;
+ unsigned int val = !!ucontrol->value.integer.value[0];
+ int change;
+
+ down(&codec->spdif_mutex);
+ change = codec->spdif_in_enable != val;
+ if (change || codec->in_resume) {
+ codec->spdif_in_enable = val;
+ snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, val);
+ }
+ up(&codec->spdif_mutex);
+ return change;
+}
+
+static int snd_hda_spdif_in_status_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ hda_nid_t nid = kcontrol->private_value;
+ unsigned short val;
+ unsigned int sbits;
+
+ val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_DIGI_CONVERT, 0);
+ sbits = convert_to_spdif_status(val);
+ ucontrol->value.iec958.status[0] = sbits;
+ ucontrol->value.iec958.status[1] = sbits >> 8;
+ ucontrol->value.iec958.status[2] = sbits >> 16;
+ ucontrol->value.iec958.status[3] = sbits >> 24;
+ return 0;
+}
+
+static snd_kcontrol_new_t dig_in_ctls[] = {
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH),
+ .info = snd_hda_spdif_in_switch_info,
+ .get = snd_hda_spdif_in_switch_get,
+ .put = snd_hda_spdif_in_switch_put,
+ },
+ {
+ .access = SNDRV_CTL_ELEM_ACCESS_READ,
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,DEFAULT),
+ .info = snd_hda_spdif_mask_info,
+ .get = snd_hda_spdif_in_status_get,
+ },
+ { } /* end */
+};
+
+/**
+ * snd_hda_create_spdif_in_ctls - create Input SPDIF-related controls
+ * @codec: the HDA codec
+ * @nid: audio in widget NID
+ *
+ * Creates controls related with the SPDIF input.
+ * Called from each patch supporting the SPDIF in.
+ *
+ * Returns 0 if successful, or a negative error code.
+ */
+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;
+
+ for (dig_mix = dig_in_ctls; dig_mix->name; dig_mix++) {
+ kctl = snd_ctl_new1(dig_mix, codec);
+ kctl->private_value = nid;
+ if ((err = snd_ctl_add(codec->bus->card, kctl)) < 0)
+ return err;
+ }
+ codec->spdif_in_enable = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_DIGI_CONVERT, 0) & 1;
+ return 0;
+}
+
+
+/**
+ * snd_hda_build_controls - build mixer controls
+ * @bus: the BUS
+ *
+ * Creates mixer controls for each codec included in the bus.
+ *
+ * Returns 0 if successful, otherwise a negative error code.
+ */
+int snd_hda_build_controls(struct hda_bus *bus)
+{
+ struct list_head *p;
+
+ /* build controls */
+ list_for_each(p, &bus->codec_list) {
+ struct hda_codec *codec = list_entry(p, struct hda_codec, list);
+ int err;
+ if (! codec->patch_ops.build_controls)
+ continue;
+ err = codec->patch_ops.build_controls(codec);
+ if (err < 0)
+ return err;
+ }
+
+ /* initialize */
+ list_for_each(p, &bus->codec_list) {
+ struct hda_codec *codec = list_entry(p, struct hda_codec, list);
+ int err;
+ if (! codec->patch_ops.init)
+ continue;
+ err = codec->patch_ops.init(codec);
+ if (err < 0)
+ return err;
+ }
+ return 0;
+}
+
+
+/*
+ * stream formats
+ */
+static unsigned int rate_bits[][3] = {
+ /* rate in Hz, ALSA rate bitmask, HDA format value */
+ { 8000, SNDRV_PCM_RATE_8000, 0x0500 }, /* 1/6 x 48 */
+ { 11025, SNDRV_PCM_RATE_11025, 0x4300 }, /* 1/4 x 44 */
+ { 16000, SNDRV_PCM_RATE_16000, 0x0200 }, /* 1/3 x 48 */
+ { 22050, SNDRV_PCM_RATE_22050, 0x4100 }, /* 1/2 x 44 */
+ { 32000, SNDRV_PCM_RATE_32000, 0x0a00 }, /* 2/3 x 48 */
+ { 44100, SNDRV_PCM_RATE_44100, 0x4000 }, /* 44 */
+ { 48000, SNDRV_PCM_RATE_48000, 0x0000 }, /* 48 */
+ { 88200, SNDRV_PCM_RATE_88200, 0x4800 }, /* 2 x 44 */
+ { 96000, SNDRV_PCM_RATE_96000, 0x0800 }, /* 2 x 48 */
+ { 176400, SNDRV_PCM_RATE_176400, 0x5800 },/* 4 x 44 */
+ { 192000, SNDRV_PCM_RATE_192000, 0x1800 }, /* 4 x 48 */
+ { 0 }
+};
+
+/**
+ * snd_hda_calc_stream_format - calculate format bitset
+ * @rate: the sample rate
+ * @channels: the number of channels
+ * @format: the PCM format (SNDRV_PCM_FORMAT_XXX)
+ * @maxbps: the max. bps
+ *
+ * Calculate the format bitset from the given rate, channels and th PCM format.
+ *
+ * Return zero if invalid.
+ */
+unsigned int snd_hda_calc_stream_format(unsigned int rate,
+ unsigned int channels,
+ unsigned int format,
+ unsigned int maxbps)
+{
+ int i;
+ unsigned int val = 0;
+
+ for (i = 0; rate_bits[i][0]; i++)
+ if (rate_bits[i][0] == rate) {
+ val = rate_bits[i][2];
+ break;
+ }
+ if (! rate_bits[i][0]) {
+ snd_printdd("invalid rate %d\n", rate);
+ return 0;
+ }
+
+ if (channels == 0 || channels > 8) {
+ snd_printdd("invalid channels %d\n", channels);
+ return 0;
+ }
+ val |= channels - 1;
+
+ switch (snd_pcm_format_width(format)) {
+ case 8: val |= 0x00; break;
+ case 16: val |= 0x10; break;
+ case 20:
+ case 24:
+ case 32:
+ if (maxbps >= 32)
+ val |= 0x40;
+ else if (maxbps >= 24)
+ val |= 0x30;
+ else
+ val |= 0x20;
+ break;
+ default:
+ snd_printdd("invalid format width %d\n", snd_pcm_format_width(format));
+ return 0;
+ }
+
+ return val;
+}
+
+/**
+ * snd_hda_query_supported_pcm - query the supported PCM rates and formats
+ * @codec: the HDA codec
+ * @nid: NID to query
+ * @ratesp: the pointer to store the detected rate bitflags
+ * @formatsp: the pointer to store the detected formats
+ * @bpsp: the pointer to store the detected format widths
+ *
+ * Queries the supported PCM rates and formats. The NULL @ratesp, @formatsp
+ * or @bsps argument is ignored.
+ *
+ * Returns 0 if successful, otherwise a negative error code.
+ */
+int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
+ u32 *ratesp, u64 *formatsp, unsigned int *bpsp)
+{
+ int i;
+ unsigned int val, streams;
+
+ val = 0;
+ if (nid != codec->afg &&
+ snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP) & AC_WCAP_FORMAT_OVRD) {
+ val = snd_hda_param_read(codec, nid, AC_PAR_PCM);
+ if (val == -1)
+ return -EIO;
+ }
+ if (! val)
+ val = snd_hda_param_read(codec, codec->afg, AC_PAR_PCM);
+
+ if (ratesp) {
+ u32 rates = 0;
+ for (i = 0; rate_bits[i][0]; i++) {
+ if (val & (1 << i))
+ rates |= rate_bits[i][1];
+ }
+ *ratesp = rates;
+ }
+
+ if (formatsp || bpsp) {
+ u64 formats = 0;
+ unsigned int bps;
+ unsigned int wcaps;
+
+ wcaps = snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP);
+ streams = snd_hda_param_read(codec, nid, AC_PAR_STREAM);
+ if (streams == -1)
+ return -EIO;
+ if (! streams) {
+ streams = snd_hda_param_read(codec, codec->afg, AC_PAR_STREAM);
+ if (streams == -1)
+ return -EIO;
+ }
+
+ bps = 0;
+ if (streams & AC_SUPFMT_PCM) {
+ if (val & AC_SUPPCM_BITS_8) {
+ formats |= SNDRV_PCM_FMTBIT_U8;
+ bps = 8;
+ }
+ if (val & AC_SUPPCM_BITS_16) {
+ formats |= SNDRV_PCM_FMTBIT_S16_LE;
+ bps = 16;
+ }
+ if (wcaps & AC_WCAP_DIGITAL) {
+ if (val & AC_SUPPCM_BITS_32)
+ formats |= SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE;
+ if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24))
+ formats |= SNDRV_PCM_FMTBIT_S32_LE;
+ if (val & AC_SUPPCM_BITS_24)
+ bps = 24;
+ else if (val & AC_SUPPCM_BITS_20)
+ bps = 20;
+ } else if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24|AC_SUPPCM_BITS_32)) {
+ formats |= SNDRV_PCM_FMTBIT_S32_LE;
+ if (val & AC_SUPPCM_BITS_32)
+ bps = 32;
+ else if (val & AC_SUPPCM_BITS_20)
+ bps = 20;
+ else if (val & AC_SUPPCM_BITS_24)
+ bps = 24;
+ }
+ }
+ else if (streams == AC_SUPFMT_FLOAT32) { /* should be exclusive */
+ formats |= SNDRV_PCM_FMTBIT_FLOAT_LE;
+ bps = 32;
+ } else if (streams == AC_SUPFMT_AC3) { /* should be exclusive */
+ /* temporary hack: we have still no proper support
+ * for the direct AC3 stream...
+ */
+ formats |= SNDRV_PCM_FMTBIT_U8;
+ bps = 8;
+ }
+ if (formatsp)
+ *formatsp = formats;
+ if (bpsp)
+ *bpsp = bps;
+ }
+
+ return 0;
+}
+
+/**
+ * snd_hda_is_supported_format - check whether the given node supports the format val
+ *
+ * Returns 1 if supported, 0 if not.
+ */
+int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid,
+ unsigned int format)
+{
+ int i;
+ 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) {
+ val = snd_hda_param_read(codec, nid, AC_PAR_PCM);
+ if (val == -1)
+ return 0;
+ }
+ if (! val) {
+ val = snd_hda_param_read(codec, codec->afg, AC_PAR_PCM);
+ if (val == -1)
+ return 0;
+ }
+
+ rate = format & 0xff00;
+ for (i = 0; rate_bits[i][0]; i++)
+ if (rate_bits[i][2] == rate) {
+ if (val & (1 << i))
+ break;
+ return 0;
+ }
+ if (! rate_bits[i][0])
+ return 0;
+
+ stream = snd_hda_param_read(codec, nid, AC_PAR_STREAM);
+ if (stream == -1)
+ return 0;
+ if (! stream && nid != codec->afg)
+ stream = snd_hda_param_read(codec, codec->afg, AC_PAR_STREAM);
+ if (! stream || stream == -1)
+ return 0;
+
+ if (stream & AC_SUPFMT_PCM) {
+ switch (format & 0xf0) {
+ case 0x00:
+ if (! (val & AC_SUPPCM_BITS_8))
+ return 0;
+ break;
+ case 0x10:
+ if (! (val & AC_SUPPCM_BITS_16))
+ return 0;
+ break;
+ case 0x20:
+ if (! (val & AC_SUPPCM_BITS_20))
+ return 0;
+ break;
+ case 0x30:
+ if (! (val & AC_SUPPCM_BITS_24))
+ return 0;
+ break;
+ case 0x40:
+ if (! (val & AC_SUPPCM_BITS_32))
+ return 0;
+ break;
+ default:
+ return 0;
+ }
+ } else {
+ /* FIXME: check for float32 and AC3? */
+ }
+
+ return 1;
+}
+
+/*
+ * PCM stuff
+ */
+static int hda_pcm_default_open_close(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ snd_pcm_substream_t *substream)
+{
+ return 0;
+}
+
+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)
+{
+ snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format);
+ return 0;
+}
+
+static int hda_pcm_default_cleanup(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ snd_pcm_substream_t *substream)
+{
+ snd_hda_codec_setup_stream(codec, hinfo->nid, 0, 0, 0);
+ return 0;
+}
+
+static int set_pcm_default_values(struct hda_codec *codec, struct hda_pcm_stream *info)
+{
+ if (info->nid) {
+ /* query support PCM information from the given NID */
+ if (! info->rates || ! info->formats)
+ snd_hda_query_supported_pcm(codec, info->nid,
+ info->rates ? NULL : &info->rates,
+ info->formats ? NULL : &info->formats,
+ info->maxbps ? NULL : &info->maxbps);
+ }
+ if (info->ops.open == NULL)
+ info->ops.open = hda_pcm_default_open_close;
+ if (info->ops.close == NULL)
+ info->ops.close = hda_pcm_default_open_close;
+ if (info->ops.prepare == NULL) {
+ snd_assert(info->nid, return -EINVAL);
+ info->ops.prepare = hda_pcm_default_prepare;
+ }
+ if (info->ops.prepare == NULL) {
+ snd_assert(info->nid, return -EINVAL);
+ info->ops.prepare = hda_pcm_default_prepare;
+ }
+ if (info->ops.cleanup == NULL) {
+ snd_assert(info->nid, return -EINVAL);
+ info->ops.cleanup = hda_pcm_default_cleanup;
+ }
+ return 0;
+}
+
+/**
+ * snd_hda_build_pcms - build PCM information
+ * @bus: the BUS
+ *
+ * Create PCM information for each codec included in the bus.
+ *
+ * The build_pcms codec patch is requested to set up codec->num_pcms and
+ * codec->pcm_info properly. The array is referred by the top-level driver
+ * to create its PCM instances.
+ * The allocated codec->pcm_info should be released in codec->patch_ops.free
+ * callback.
+ *
+ * At least, substreams, channels_min and channels_max must be filled for
+ * each stream. substreams = 0 indicates that the stream doesn't exist.
+ * When rates and/or formats are zero, the supported values are queried
+ * from the given nid. The nid is used also by the default ops.prepare
+ * and ops.cleanup callbacks.
+ *
+ * The driver needs to call ops.open in its open callback. Similarly,
+ * ops.close is supposed to be called in the close callback.
+ * ops.prepare should be called in the prepare or hw_params callback
+ * with the proper parameters for set up.
+ * ops.cleanup should be called in hw_free for clean up of streams.
+ *
+ * This function returns 0 if successfull, or a negative error code.
+ */
+int snd_hda_build_pcms(struct hda_bus *bus)
+{
+ struct list_head *p;
+
+ list_for_each(p, &bus->codec_list) {
+ struct hda_codec *codec = list_entry(p, struct hda_codec, list);
+ unsigned int pcm, s;
+ int err;
+ if (! codec->patch_ops.build_pcms)
+ continue;
+ err = codec->patch_ops.build_pcms(codec);
+ if (err < 0)
+ return err;
+ for (pcm = 0; pcm < codec->num_pcms; pcm++) {
+ for (s = 0; s < 2; s++) {
+ struct hda_pcm_stream *info;
+ info = &codec->pcm_info[pcm].stream[s];
+ if (! info->substreams)
+ continue;
+ err = set_pcm_default_values(codec, info);
+ if (err < 0)
+ return err;
+ }
+ }
+ }
+ return 0;
+}
+
+
+/**
+ * snd_hda_check_board_config - compare the current codec with the config table
+ * @codec: the HDA codec
+ * @tbl: configuration table, terminated by null entries
+ *
+ * Compares the modelname or PCI subsystem id of the current codec with the
+ * given configuration table. If a matching entry is found, returns its
+ * config value (supposed to be 0 or positive).
+ *
+ * If no entries are matching, the function returns a negative value.
+ */
+int snd_hda_check_board_config(struct hda_codec *codec, struct hda_board_config *tbl)
+{
+ struct hda_board_config *c;
+
+ if (codec->bus->modelname) {
+ for (c = tbl; c->modelname || c->pci_vendor; c++) {
+ if (c->modelname &&
+ ! strcmp(codec->bus->modelname, c->modelname)) {
+ snd_printd(KERN_INFO "hda_codec: model '%s' is selected\n", c->modelname);
+ return c->config;
+ }
+ }
+ }
+
+ if (codec->bus->pci) {
+ u16 subsystem_vendor, subsystem_device;
+ pci_read_config_word(codec->bus->pci, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vendor);
+ pci_read_config_word(codec->bus->pci, PCI_SUBSYSTEM_ID, &subsystem_device);
+ for (c = tbl; c->modelname || c->pci_vendor; c++) {
+ if (c->pci_vendor == subsystem_vendor &&
+ c->pci_device == subsystem_device)
+ return c->config;
+ }
+ }
+ return -1;
+}
+
+/**
+ * snd_hda_add_new_ctls - create controls from the array
+ * @codec: the HDA codec
+ * @knew: the array of snd_kcontrol_new_t
+ *
+ * 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 err;
+
+ for (; knew->name; knew++) {
+ err = snd_ctl_add(codec->bus->card, snd_ctl_new1(knew, codec));
+ if (err < 0)
+ return err;
+ }
+ return 0;
+}
+
+
+/*
+ * input MUX helper
+ */
+int snd_hda_input_mux_info(const struct hda_input_mux *imux, snd_ctl_elem_info_t *uinfo)
+{
+ unsigned int index;
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+ uinfo->count = 1;
+ uinfo->value.enumerated.items = imux->num_items;
+ index = uinfo->value.enumerated.item;
+ if (index >= imux->num_items)
+ index = imux->num_items - 1;
+ strcpy(uinfo->value.enumerated.name, imux->items[index].label);
+ return 0;
+}
+
+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,
+ unsigned int *cur_val)
+{
+ unsigned int idx;
+
+ idx = ucontrol->value.enumerated.item[0];
+ if (idx >= imux->num_items)
+ idx = imux->num_items - 1;
+ if (*cur_val == idx && ! codec->in_resume)
+ return 0;
+ snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL,
+ imux->items[idx].index);
+ *cur_val = idx;
+ return 1;
+}
+
+
+/*
+ * Multi-channel / digital-out PCM helper functions
+ */
+
+/*
+ * open the digital out in the exclusive mode
+ */
+int snd_hda_multi_out_dig_open(struct hda_codec *codec, struct hda_multi_out *mout)
+{
+ down(&codec->spdif_mutex);
+ if (mout->dig_out_used) {
+ up(&codec->spdif_mutex);
+ return -EBUSY; /* already being used */
+ }
+ mout->dig_out_used = HDA_DIG_EXCLUSIVE;
+ up(&codec->spdif_mutex);
+ return 0;
+}
+
+/*
+ * release the digital out
+ */
+int snd_hda_multi_out_dig_close(struct hda_codec *codec, struct hda_multi_out *mout)
+{
+ down(&codec->spdif_mutex);
+ mout->dig_out_used = 0;
+ up(&codec->spdif_mutex);
+ return 0;
+}
+
+/*
+ * 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)
+{
+ substream->runtime->hw.channels_max = mout->max_channels;
+ return snd_pcm_hw_constraint_step(substream->runtime, 0,
+ SNDRV_PCM_HW_PARAM_CHANNELS, 2);
+}
+
+/*
+ * set up the i/o for analog out
+ * when the digital out is available, copy the front out to digital out, too.
+ */
+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)
+{
+ 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 */
+ for (i = 1; i < mout->num_dacs; i++) {
+ if (i == HDA_REAR && chs == 2) /* copy front to rear */
+ snd_hda_codec_setup_stream(codec, nids[i], stream_tag, 0, format);
+ else if (chs >= (i + 1) * 2) /* independent out */
+ snd_hda_codec_setup_stream(codec, nids[i], stream_tag, i * 2,
+ format);
+ }
+ return 0;
+}
+
+/*
+ * clean up the setting for analog out
+ */
+int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec, struct hda_multi_out *mout)
+{
+ hda_nid_t *nids = mout->dac_nids;
+ int i;
+
+ for (i = 0; i < mout->num_dacs; i++)
+ snd_hda_codec_setup_stream(codec, nids[i], 0, 0, 0);
+ if (mout->hp_nid)
+ snd_hda_codec_setup_stream(codec, mout->hp_nid, 0, 0, 0);
+ down(&codec->spdif_mutex);
+ if (mout->dig_out_nid && mout->dig_out_used == HDA_DIG_ANALOG_DUP) {
+ snd_hda_codec_setup_stream(codec, mout->dig_out_nid, 0, 0, 0);
+ mout->dig_out_used = 0;
+ }
+ up(&codec->spdif_mutex);
+ return 0;
+}
+
+#ifdef CONFIG_PM
+/*
+ * power management
+ */
+
+/**
+ * snd_hda_suspend - suspend the codecs
+ * @bus: the HDA bus
+ * @state: suspsend state
+ *
+ * Returns 0 if successful.
+ */
+int snd_hda_suspend(struct hda_bus *bus, pm_message_t state)
+{
+ struct list_head *p;
+
+ /* FIXME: should handle power widget capabilities */
+ list_for_each(p, &bus->codec_list) {
+ struct hda_codec *codec = list_entry(p, struct hda_codec, list);
+ if (codec->patch_ops.suspend)
+ codec->patch_ops.suspend(codec, state);
+ }
+ return 0;
+}
+
+/**
+ * snd_hda_resume - resume the codecs
+ * @bus: the HDA bus
+ * @state: resume state
+ *
+ * Returns 0 if successful.
+ */
+int snd_hda_resume(struct hda_bus *bus)
+{
+ struct list_head *p;
+
+ list_for_each(p, &bus->codec_list) {
+ struct hda_codec *codec = list_entry(p, struct hda_codec, list);
+ if (codec->patch_ops.resume)
+ codec->patch_ops.resume(codec);
+ }
+ return 0;
+}
+
+/**
+ * snd_hda_resume_ctls - resume controls in the new control list
+ * @codec: the HDA codec
+ * @knew: the array of snd_kcontrol_new_t
+ *
+ * This function resumes the mixer controls in the snd_kcontrol_new_t 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)
+{
+ snd_ctl_elem_value_t *val;
+
+ val = kmalloc(sizeof(*val), GFP_KERNEL);
+ if (! val)
+ return -ENOMEM;
+ codec->in_resume = 1;
+ for (; knew->name; knew++) {
+ int i, count;
+ count = knew->count ? knew->count : 1;
+ for (i = 0; i < count; i++) {
+ memset(val, 0, sizeof(*val));
+ val->id.iface = knew->iface;
+ val->id.device = knew->device;
+ val->id.subdevice = knew->subdevice;
+ strcpy(val->id.name, knew->name);
+ val->id.index = knew->index ? knew->index : i;
+ /* Assume that get callback reads only from cache,
+ * not accessing to the real hardware
+ */
+ if (snd_ctl_elem_read(codec->bus->card, val) < 0)
+ continue;
+ snd_ctl_elem_write(codec->bus->card, NULL, val);
+ }
+ }
+ codec->in_resume = 0;
+ kfree(val);
+ return 0;
+}
+
+/**
+ * snd_hda_resume_spdif_out - resume the digital out
+ * @codec: the HDA codec
+ */
+int snd_hda_resume_spdif_out(struct hda_codec *codec)
+{
+ return snd_hda_resume_ctls(codec, dig_mixes);
+}
+
+/**
+ * snd_hda_resume_spdif_in - resume the digital in
+ * @codec: the HDA codec
+ */
+int snd_hda_resume_spdif_in(struct hda_codec *codec)
+{
+ return snd_hda_resume_ctls(codec, dig_in_ctls);
+}
+#endif
+
+/*
+ * symbols exported for controller modules
+ */
+EXPORT_SYMBOL(snd_hda_codec_read);
+EXPORT_SYMBOL(snd_hda_codec_write);
+EXPORT_SYMBOL(snd_hda_sequence_write);
+EXPORT_SYMBOL(snd_hda_get_sub_nodes);
+EXPORT_SYMBOL(snd_hda_queue_unsol_event);
+EXPORT_SYMBOL(snd_hda_bus_new);
+EXPORT_SYMBOL(snd_hda_codec_new);
+EXPORT_SYMBOL(snd_hda_codec_setup_stream);
+EXPORT_SYMBOL(snd_hda_calc_stream_format);
+EXPORT_SYMBOL(snd_hda_build_pcms);
+EXPORT_SYMBOL(snd_hda_build_controls);
+#ifdef CONFIG_PM
+EXPORT_SYMBOL(snd_hda_suspend);
+EXPORT_SYMBOL(snd_hda_resume);
+#endif
+
+/*
+ * INIT part
+ */
+
+static int __init alsa_hda_init(void)
+{
+ return 0;
+}
+
+static void __exit alsa_hda_exit(void)
+{
+}
+
+module_init(alsa_hda_init)
+module_exit(alsa_hda_exit)
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
new file mode 100644
index 0000000000000..c9e9dc9c7c98e
--- /dev/null
+++ b/sound/pci/hda/hda_codec.h
@@ -0,0 +1,604 @@
+/*
+ * Universal Interface for Intel High Definition Audio Codec
+ *
+ * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __SOUND_HDA_CODEC_H
+#define __SOUND_HDA_CODEC_H
+
+#include <sound/info.h>
+#include <sound/control.h>
+#include <sound/pcm.h>
+
+/*
+ * nodes
+ */
+#define AC_NODE_ROOT 0x00
+
+/*
+ * function group types
+ */
+enum {
+ AC_GRP_AUDIO_FUNCTION = 0x01,
+ AC_GRP_MODEM_FUNCTION = 0x02,
+};
+
+/*
+ * widget types
+ */
+enum {
+ AC_WID_AUD_OUT, /* Audio Out */
+ AC_WID_AUD_IN, /* Audio In */
+ AC_WID_AUD_MIX, /* Audio Mixer */
+ AC_WID_AUD_SEL, /* Audio Selector */
+ AC_WID_PIN, /* Pin Complex */
+ AC_WID_POWER, /* Power */
+ AC_WID_VOL_KNB, /* Volume Knob */
+ AC_WID_BEEP, /* Beep Generator */
+ AC_WID_VENDOR = 0x0f /* Vendor specific */
+};
+
+/*
+ * GET verbs
+ */
+#define AC_VERB_GET_STREAM_FORMAT 0x0a00
+#define AC_VERB_GET_AMP_GAIN_MUTE 0x0b00
+#define AC_VERB_GET_PROC_COEF 0x0c00
+#define AC_VERB_GET_COEF_INDEX 0x0d00
+#define AC_VERB_PARAMETERS 0x0f00
+#define AC_VERB_GET_CONNECT_SEL 0x0f01
+#define AC_VERB_GET_CONNECT_LIST 0x0f02
+#define AC_VERB_GET_PROC_STATE 0x0f03
+#define AC_VERB_GET_SDI_SELECT 0x0f04
+#define AC_VERB_GET_POWER_STATE 0x0f05
+#define AC_VERB_GET_CONV 0x0f06
+#define AC_VERB_GET_PIN_WIDGET_CONTROL 0x0f07
+#define AC_VERB_GET_UNSOLICITED_RESPONSE 0x0f08
+#define AC_VERB_GET_PIN_SENSE 0x0f09
+#define AC_VERB_GET_BEEP_CONTROL 0x0f0a
+#define AC_VERB_GET_EAPD_BTLENABLE 0x0f0c
+#define AC_VERB_GET_DIGI_CONVERT 0x0f0d
+#define AC_VERB_GET_VOLUME_KNOB_CONTROL 0x0f0f
+/* f10-f1a: GPIO */
+#define AC_VERB_GET_CONFIG_DEFAULT 0x0f1c
+
+/*
+ * SET verbs
+ */
+#define AC_VERB_SET_STREAM_FORMAT 0x200
+#define AC_VERB_SET_AMP_GAIN_MUTE 0x300
+#define AC_VERB_SET_PROC_COEF 0x400
+#define AC_VERB_SET_COEF_INDEX 0x500
+#define AC_VERB_SET_CONNECT_SEL 0x701
+#define AC_VERB_SET_PROC_STATE 0x703
+#define AC_VERB_SET_SDI_SELECT 0x704
+#define AC_VERB_SET_POWER_STATE 0x705
+#define AC_VERB_SET_CHANNEL_STREAMID 0x706
+#define AC_VERB_SET_PIN_WIDGET_CONTROL 0x707
+#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_DIGI_CONVERT_1 0x70d
+#define AC_VERB_SET_DIGI_CONVERT_2 0x70e
+#define AC_VERB_SET_VOLUME_KNOB_CONTROL 0x70f
+#define AC_VERB_SET_CONFIG_DEFAULT_BYTES_0 0x71c
+#define AC_VERB_SET_CONFIG_DEFAULT_BYTES_1 0x71d
+#define AC_VERB_SET_CONFIG_DEFAULT_BYTES_2 0x71e
+#define AC_VERB_SET_CONFIG_DEFAULT_BYTES_3 0x71f
+#define AC_VERB_SET_CODEC_RESET 0x7ff
+
+/*
+ * Parameter IDs
+ */
+#define AC_PAR_VENDOR_ID 0x00
+#define AC_PAR_SUBSYSTEM_ID 0x01
+#define AC_PAR_REV_ID 0x02
+#define AC_PAR_NODE_COUNT 0x04
+#define AC_PAR_FUNCTION_TYPE 0x05
+#define AC_PAR_AUDIO_FG_CAP 0x08
+#define AC_PAR_AUDIO_WIDGET_CAP 0x09
+#define AC_PAR_PCM 0x0a
+#define AC_PAR_STREAM 0x0b
+#define AC_PAR_PIN_CAP 0x0c
+#define AC_PAR_AMP_IN_CAP 0x0d
+#define AC_PAR_CONNLIST_LEN 0x0e
+#define AC_PAR_POWER_STATE 0x0f
+#define AC_PAR_PROC_CAP 0x10
+#define AC_PAR_GPIO_CAP 0x11
+#define AC_PAR_AMP_OUT_CAP 0x12
+
+/*
+ * AC_VERB_PARAMETERS results (32bit)
+ */
+
+/* Function Group Type */
+#define AC_FGT_TYPE (0xff<<0)
+#define AC_FGT_TYPE_SHIFT 0
+#define AC_FGT_UNSOL_CAP (1<<8)
+
+/* Audio Function Group Capabilities */
+#define AC_AFG_OUT_DELAY (0xf<<0)
+#define AC_AFG_IN_DELAY (0xf<<8)
+#define AC_AFG_BEEP_GEN (1<<16)
+
+/* Audio Widget Capabilities */
+#define AC_WCAP_STEREO (1<<0) /* stereo I/O */
+#define AC_WCAP_IN_AMP (1<<1) /* AMP-in present */
+#define AC_WCAP_OUT_AMP (1<<2) /* AMP-out present */
+#define AC_WCAP_AMP_OVRD (1<<3) /* AMP-parameter override */
+#define AC_WCAP_FORMAT_OVRD (1<<4) /* format override */
+#define AC_WCAP_STRIPE (1<<5) /* stripe */
+#define AC_WCAP_PROC_WID (1<<6) /* Proc Widget */
+#define AC_WCAP_UNSOL_CAP (1<<7) /* Unsol capable */
+#define AC_WCAP_CONN_LIST (1<<8) /* connection list */
+#define AC_WCAP_DIGITAL (1<<9) /* digital I/O */
+#define AC_WCAP_POWER (1<<10) /* power control */
+#define AC_WCAP_LR_SWAP (1<<11) /* L/R swap */
+#define AC_WCAP_DELAY (0xf<<16)
+#define AC_WCAP_DELAY_SHIFT 16
+#define AC_WCAP_TYPE (0xf<<20)
+#define AC_WCAP_TYPE_SHIFT 20
+
+/* supported PCM rates and bits */
+#define AC_SUPPCM_RATES (0xfff << 0)
+#define AC_SUPPCM_BITS_8 (1<<16)
+#define AC_SUPPCM_BITS_16 (1<<17)
+#define AC_SUPPCM_BITS_20 (1<<18)
+#define AC_SUPPCM_BITS_24 (1<<19)
+#define AC_SUPPCM_BITS_32 (1<<20)
+
+/* supported PCM stream format */
+#define AC_SUPFMT_PCM (1<<0)
+#define AC_SUPFMT_FLOAT32 (1<<1)
+#define AC_SUPFMT_AC3 (1<<2)
+
+/* Pin widget capabilies */
+#define AC_PINCAP_IMP_SENSE (1<<0) /* impedance sense capable */
+#define AC_PINCAP_TRIG_REQ (1<<1) /* trigger required */
+#define AC_PINCAP_PRES_DETECT (1<<2) /* presence detect capable */
+#define AC_PINCAP_HP_DRV (1<<3) /* headphone drive capable */
+#define AC_PINCAP_OUT (1<<4) /* output capable */
+#define AC_PINCAP_IN (1<<5) /* input capable */
+#define AC_PINCAP_BALANCE (1<<6) /* balanced I/O capable */
+#define AC_PINCAP_VREF (7<<8)
+#define AC_PINCAP_VREF_SHIFT 8
+#define AC_PINCAP_EAPD (1<<16) /* EAPD capable */
+/* Vref status (used in pin cap and pin ctl) */
+#define AC_PIN_VREF_HIZ (1<<0) /* Hi-Z */
+#define AC_PIN_VREF_50 (1<<1) /* 50% */
+#define AC_PIN_VREF_GRD (1<<2) /* ground */
+#define AC_PIN_VREF_80 (1<<4) /* 80% */
+#define AC_PIN_VREF_100 (1<<5) /* 100% */
+
+
+/* Amplifier capabilities */
+#define AC_AMPCAP_OFFSET (0x7f<<0) /* 0dB offset */
+#define AC_AMPCAP_OFFSET_SHIFT 0
+#define AC_AMPCAP_NUM_STEPS (0x7f<<8) /* number of steps */
+#define AC_AMPCAP_NUM_STEPS_SHIFT 8
+#define AC_AMPCAP_STEP_SIZE (0x7f<<16) /* step size 0-32dB in 0.25dB */
+#define AC_AMPCAP_STEP_SIZE_SHIFT 16
+#define AC_AMPCAP_MUTE (1<<31) /* mute capable */
+#define AC_AMPCAP_MUTE_SHIFT 31
+
+/* Connection list */
+#define AC_CLIST_LENGTH (0x7f<<0)
+#define AC_CLIST_LONG (1<<7)
+
+/* Supported power status */
+#define AC_PWRST_D0SUP (1<<0)
+#define AC_PWRST_D1SUP (1<<1)
+#define AC_PWRST_D2SUP (1<<2)
+#define AC_PWRST_D3SUP (1<<3)
+
+/* Processing capabilies */
+#define AC_PCAP_BENIGN (1<<0)
+#define AC_PCAP_NUM_COEF (0xff<<8)
+
+/* Volume knobs capabilities */
+#define AC_KNBCAP_NUM_STEPS (0x7f<<0)
+#define AC_KNBCAP_DELTA (1<<8)
+
+/*
+ * Control Parameters
+ */
+
+/* Amp gain/mute */
+#define AC_AMP_MUTE (1<<8)
+#define AC_AMP_GAIN (0x7f)
+#define AC_AMP_GET_INDEX (0xf<<0)
+
+#define AC_AMP_GET_LEFT (1<<13)
+#define AC_AMP_GET_RIGHT (0<<13)
+#define AC_AMP_GET_OUTPUT (1<<15)
+#define AC_AMP_GET_INPUT (0<<15)
+
+#define AC_AMP_SET_INDEX (0xf<<8)
+#define AC_AMP_SET_INDEX_SHIFT 8
+#define AC_AMP_SET_RIGHT (1<<12)
+#define AC_AMP_SET_LEFT (1<<13)
+#define AC_AMP_SET_INPUT (1<<14)
+#define AC_AMP_SET_OUTPUT (1<<15)
+
+/* DIGITAL1 bits */
+#define AC_DIG1_ENABLE (1<<0)
+#define AC_DIG1_V (1<<1)
+#define AC_DIG1_VCFG (1<<2)
+#define AC_DIG1_EMPHASIS (1<<3)
+#define AC_DIG1_COPYRIGHT (1<<4)
+#define AC_DIG1_NONAUDIO (1<<5)
+#define AC_DIG1_PROFESSIONAL (1<<6)
+#define AC_DIG1_LEVEL (1<<7)
+
+/* Pin widget control - 8bit */
+#define AC_PINCTL_VREFEN (0x7<<0)
+#define AC_PINCTL_IN_EN (1<<5)
+#define AC_PINCTL_OUT_EN (1<<6)
+#define AC_PINCTL_HP_EN (1<<7)
+
+/* configuration default - 32bit */
+#define AC_DEFCFG_SEQUENCE (0xf<<0)
+#define AC_DEFCFG_DEF_ASSOC (0xf<<4)
+#define AC_DEFCFG_MISC (0xf<<8)
+#define AC_DEFCFG_COLOR (0xf<<12)
+#define AC_DEFCFG_COLOR_SHIFT 12
+#define AC_DEFCFG_CONN_TYPE (0xf<<16)
+#define AC_DEFCFG_CONN_TYPE_SHIFT 16
+#define AC_DEFCFG_DEVICE (0xf<<20)
+#define AC_DEFCFG_DEVICE_SHIFT 20
+#define AC_DEFCFG_LOCATION (0x3f<<24)
+#define AC_DEFCFG_LOCATION_SHIFT 24
+#define AC_DEFCFG_PORT_CONN (0x3<<30)
+#define AC_DEFCFG_PORT_CONN_SHIFT 30
+
+/* device device types (0x0-0xf) */
+enum {
+ AC_JACK_LINE_OUT,
+ AC_JACK_SPEAKER,
+ AC_JACK_HP_OUT,
+ AC_JACK_CD,
+ AC_JACK_SPDIF_OUT,
+ AC_JACK_DIG_OTHER_OUT,
+ AC_JACK_MODEM_LINE_SIDE,
+ AC_JACK_MODEM_HAND_SIDE,
+ AC_JACK_LINE_IN,
+ AC_JACK_AUX,
+ AC_JACK_MIC_IN,
+ AC_JACK_TELEPHONY,
+ AC_JACK_SPDIF_IN,
+ AC_JACK_DIG_OTHER_IN,
+ AC_JACK_OTHER = 0xf,
+};
+
+/* jack connection types (0x0-0xf) */
+enum {
+ AC_JACK_CONN_UNKNOWN,
+ AC_JACK_CONN_1_8,
+ AC_JACK_CONN_1_4,
+ AC_JACK_CONN_ATAPI,
+ AC_JACK_CONN_RCA,
+ AC_JACK_CONN_OPTICAL,
+ AC_JACK_CONN_OTHER_DIGITAL,
+ AC_JACK_CONN_OTHER_ANALOG,
+ AC_JACK_CONN_DIN,
+ AC_JACK_CONN_XLR,
+ AC_JACK_CONN_RJ11,
+ AC_JACK_CONN_COMB,
+ AC_JACK_CONN_OTHER = 0xf,
+};
+
+/* jack colors (0x0-0xf) */
+enum {
+ AC_JACK_COLOR_UNKNOWN,
+ AC_JACK_COLOR_BLACK,
+ AC_JACK_COLOR_GREY,
+ AC_JACK_COLOR_BLUE,
+ AC_JACK_COLOR_GREEN,
+ AC_JACK_COLOR_RED,
+ AC_JACK_COLOR_ORANGE,
+ AC_JACK_COLOR_YELLOW,
+ AC_JACK_COLOR_PURPLE,
+ AC_JACK_COLOR_PINK,
+ AC_JACK_COLOR_WHITE = 0xe,
+ AC_JACK_COLOR_OTHER,
+};
+
+/* Jack location (0x0-0x3f) */
+/* common case */
+enum {
+ AC_JACK_LOC_NONE,
+ AC_JACK_LOC_REAR,
+ AC_JACK_LOC_FRONT,
+ AC_JACK_LOC_LEFT,
+ AC_JACK_LOC_RIGHT,
+ AC_JACK_LOC_TOP,
+ AC_JACK_LOC_BOTTOM,
+};
+/* bits 4-5 */
+enum {
+ AC_JACK_LOC_EXTERNAL = 0x00,
+ AC_JACK_LOC_INTERNAL = 0x10,
+ AC_JACK_LOC_SEPARATE = 0x20,
+ AC_JACK_LOC_OTHER = 0x30,
+};
+enum {
+ /* external on primary chasis */
+ AC_JACK_LOC_REAR_PANEL = 0x07,
+ AC_JACK_LOC_DRIVE_BAY,
+ /* internal */
+ AC_JACK_LOC_RISER = 0x17,
+ AC_JACK_LOC_HDMI,
+ AC_JACK_LOC_ATAPI,
+ /* others */
+ AC_JACK_LOC_MOBILE_IN = 0x37,
+ AC_JACK_LOC_MOBILE_OUT,
+};
+
+/* Port connectivity (0-3) */
+enum {
+ AC_JACK_PORT_COMPLEX,
+ AC_JACK_PORT_NONE,
+ AC_JACK_PORT_FIXED,
+ AC_JACK_PORT_BOTH,
+};
+
+/* max. connections to a widget */
+#define HDA_MAX_CONNECTIONS 16
+
+/* max. codec address */
+#define HDA_MAX_CODEC_ADDRESS 0x0f
+
+/*
+ * Structures
+ */
+
+struct hda_bus;
+struct hda_codec;
+struct hda_pcm;
+struct hda_pcm_stream;
+struct hda_bus_unsolicited;
+
+/* NID type */
+typedef u16 hda_nid_t;
+
+/* bus operators */
+struct hda_bus_ops {
+ /* send a single command */
+ int (*command)(struct hda_codec *codec, hda_nid_t nid, int direct,
+ unsigned int verb, unsigned int parm);
+ /* get a response from the last command */
+ unsigned int (*get_response)(struct hda_codec *codec);
+ /* free the private data */
+ void (*private_free)(struct hda_bus *);
+};
+
+/* template to pass to the bus constructor */
+struct hda_bus_template {
+ void *private_data;
+ struct pci_dev *pci;
+ const char *modelname;
+ struct hda_bus_ops ops;
+};
+
+/*
+ * codec bus
+ *
+ * each controller needs to creata a hda_bus to assign the accessor.
+ * A hda_bus contains several codecs in the list codec_list.
+ */
+struct hda_bus {
+ snd_card_t *card;
+
+ /* copied from template */
+ void *private_data;
+ struct pci_dev *pci;
+ const char *modelname;
+ struct hda_bus_ops ops;
+
+ /* codec linked list */
+ struct list_head codec_list;
+ struct hda_codec *caddr_tbl[HDA_MAX_CODEC_ADDRESS]; /* caddr -> codec */
+
+ struct semaphore cmd_mutex;
+
+ /* unsolicited event queue */
+ struct hda_bus_unsolicited *unsol;
+
+ snd_info_entry_t *proc;
+};
+
+/*
+ * codec preset
+ *
+ * Known codecs have the patch to build and set up the controls/PCMs
+ * better than the generic parser.
+ */
+struct hda_codec_preset {
+ unsigned int id;
+ unsigned int mask;
+ unsigned int subs;
+ unsigned int subs_mask;
+ unsigned int rev;
+ const char *name;
+ int (*patch)(struct hda_codec *codec);
+};
+
+/* ops set by the preset patch */
+struct hda_codec_ops {
+ int (*build_controls)(struct hda_codec *codec);
+ int (*build_pcms)(struct hda_codec *codec);
+ int (*init)(struct hda_codec *codec);
+ void (*free)(struct hda_codec *codec);
+ void (*unsol_event)(struct hda_codec *codec, unsigned int res);
+#ifdef CONFIG_PM
+ int (*suspend)(struct hda_codec *codec, pm_message_t state);
+ int (*resume)(struct hda_codec *codec);
+#endif
+};
+
+/* record for amp information cache */
+struct hda_amp_info {
+ u32 key; /* hash key */
+ u32 amp_caps; /* amp capabilities */
+ u16 vol[2]; /* current volume & mute*/
+ u16 status; /* update flag */
+ u16 next; /* next link */
+};
+
+/* PCM callbacks */
+struct hda_pcm_ops {
+ int (*open)(struct hda_pcm_stream *info, struct hda_codec *codec,
+ snd_pcm_substream_t *substream);
+ int (*close)(struct hda_pcm_stream *info, struct hda_codec *codec,
+ snd_pcm_substream_t *substream);
+ int (*prepare)(struct hda_pcm_stream *info, struct hda_codec *codec,
+ unsigned int stream_tag, unsigned int format,
+ snd_pcm_substream_t *substream);
+ int (*cleanup)(struct hda_pcm_stream *info, struct hda_codec *codec,
+ snd_pcm_substream_t *substream);
+};
+
+/* PCM information for each substream */
+struct hda_pcm_stream {
+ unsigned int substreams; /* number of substreams, 0 = not exist */
+ unsigned int channels_min; /* min. number of channels */
+ unsigned int channels_max; /* max. number of channels */
+ hda_nid_t nid; /* default NID to query rates/formats/bps, or set up */
+ u32 rates; /* supported rates */
+ u64 formats; /* supported formats (SNDRV_PCM_FMTBIT_) */
+ unsigned int maxbps; /* supported max. bit per sample */
+ struct hda_pcm_ops ops;
+};
+
+/* for PCM creation */
+struct hda_pcm {
+ char *name;
+ struct hda_pcm_stream stream[2];
+};
+
+/* codec information */
+struct hda_codec {
+ struct hda_bus *bus;
+ unsigned int addr; /* codec addr*/
+ struct list_head list; /* list point */
+
+ hda_nid_t afg; /* AFG node id */
+
+ /* ids */
+ u32 vendor_id;
+ u32 subsystem_id;
+ u32 revision_id;
+
+ /* detected preset */
+ const struct hda_codec_preset *preset;
+
+ /* set by patch */
+ struct hda_codec_ops patch_ops;
+
+ /* resume phase - all controls should update even if
+ * the values are not changed
+ */
+ unsigned int in_resume;
+
+ /* PCM to create, set by patch_ops.build_pcms callback */
+ unsigned int num_pcms;
+ struct hda_pcm *pcm_info;
+
+ /* codec specific info */
+ void *spec;
+
+ /* hash for amp access */
+ u16 amp_hash[32];
+ int num_amp_entries;
+ struct hda_amp_info amp_info[128]; /* big enough? */
+
+ struct semaphore spdif_mutex;
+ unsigned int spdif_status; /* IEC958 status bits */
+ unsigned short spdif_ctls; /* SPDIF control bits */
+ unsigned int spdif_in_enable; /* SPDIF input enable? */
+};
+
+/* direction */
+enum {
+ HDA_INPUT, HDA_OUTPUT
+};
+
+
+/*
+ * constructors
+ */
+int snd_hda_bus_new(snd_card_t *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);
+
+/*
+ * low level functions
+ */
+unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid, int direct,
+ unsigned int verb, unsigned int parm);
+int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int direct,
+ unsigned int verb, unsigned int parm);
+#define snd_hda_param_read(codec, nid, param) snd_hda_codec_read(codec, nid, 0, AC_VERB_PARAMETERS, param)
+int snd_hda_get_sub_nodes(struct hda_codec *codec, hda_nid_t nid, hda_nid_t *start_id);
+int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid, hda_nid_t *conn_list, int max_conns);
+
+struct hda_verb {
+ hda_nid_t nid;
+ u32 verb;
+ u32 param;
+};
+
+void snd_hda_sequence_write(struct hda_codec *codec, const struct hda_verb *seq);
+
+/* unsolicited event */
+int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex);
+
+/*
+ * Mixer
+ */
+int snd_hda_build_controls(struct hda_bus *bus);
+
+/*
+ * PCM
+ */
+int snd_hda_build_pcms(struct hda_bus *bus);
+void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid, u32 stream_tag,
+ int channel_id, int format);
+unsigned int snd_hda_calc_stream_format(unsigned int rate, unsigned int channels,
+ unsigned int format, unsigned int maxbps);
+int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
+ u32 *ratesp, u64 *formatsp, unsigned int *bpsp);
+int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid,
+ unsigned int format);
+
+/*
+ * Misc
+ */
+void snd_hda_get_codec_name(struct hda_codec *codec, char *name, int namelen);
+
+/*
+ * power management
+ */
+#ifdef CONFIG_PM
+int snd_hda_suspend(struct hda_bus *bus, pm_message_t state);
+int snd_hda_resume(struct hda_bus *bus);
+#endif
+
+#endif /* __SOUND_HDA_CODEC_H */
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
new file mode 100644
index 0000000000000..69f7b6c4cf83a
--- /dev/null
+++ b/sound/pci/hda/hda_generic.c
@@ -0,0 +1,906 @@
+/*
+ * Universal Interface for Intel High Definition Audio Codec
+ *
+ * Generic widget tree parser
+ *
+ * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
+ *
+ * This driver is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This driver is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <sound/driver.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <sound/core.h>
+#include "hda_codec.h"
+#include "hda_local.h"
+
+/* widget node for parsing */
+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 */
+ unsigned int wid_caps; /* widget capabilities */
+ unsigned char type; /* widget type */
+ unsigned char pin_ctl; /* pin controls */
+ unsigned char checked; /* the flag indicates that the node is already parsed */
+ unsigned int pin_caps; /* pin widget capabilities */
+ unsigned int def_cfg; /* default configuration */
+ unsigned int amp_out_caps; /* AMP out capabilities */
+ unsigned int amp_in_caps; /* AMP in capabilities */
+ struct list_head list;
+};
+
+/* pathc-specific record */
+struct hda_gspec {
+ struct hda_gnode *dac_node; /* DAC node */
+ struct hda_gnode *out_pin_node; /* Output pin (Line-Out) node */
+ struct hda_gnode *pcm_vol_node; /* Node for PCM volume */
+ unsigned int pcm_vol_index; /* connection of PCM volume */
+
+ struct hda_gnode *adc_node; /* ADC node */
+ struct hda_gnode *cap_vol_node; /* Node for capture volume */
+ unsigned int cur_cap_src; /* current capture source */
+ struct hda_input_mux input_mux;
+ char cap_labels[HDA_MAX_NUM_INPUTS][16];
+
+ unsigned int def_amp_in_caps;
+ unsigned int def_amp_out_caps;
+
+ struct hda_pcm pcm_rec; /* PCM information */
+
+ struct list_head nid_list; /* list of widgets */
+};
+
+/*
+ * retrieve the default device type from the default config value
+ */
+#define get_defcfg_type(node) (((node)->def_cfg & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT)
+#define get_defcfg_location(node) (((node)->def_cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT)
+
+/*
+ * destructor
+ */
+static void snd_hda_generic_free(struct hda_codec *codec)
+{
+ struct hda_gspec *spec = codec->spec;
+ struct list_head *p, *n;
+
+ if (! spec)
+ return;
+ /* free all widgets */
+ list_for_each_safe(p, n, &spec->nid_list) {
+ struct hda_gnode *node = list_entry(p, struct hda_gnode, list);
+ kfree(node);
+ }
+ kfree(spec);
+}
+
+
+/*
+ * add a new widget node and read its attributes
+ */
+static int add_new_node(struct hda_codec *codec, struct hda_gspec *spec, hda_nid_t nid)
+{
+ struct hda_gnode *node;
+ int nconns;
+
+ node = kcalloc(1, 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);
+ if (nconns < 0) {
+ kfree(node);
+ return nconns;
+ }
+ node->nconns = nconns;
+ node->wid_caps = snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP);
+ node->type = (node->wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
+
+ if (node->type == AC_WID_PIN) {
+ node->pin_caps = snd_hda_param_read(codec, node->nid, AC_PAR_PIN_CAP);
+ node->pin_ctl = snd_hda_codec_read(codec, node->nid, 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
+ node->def_cfg = snd_hda_codec_read(codec, node->nid, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
+ }
+
+ if (node->wid_caps & AC_WCAP_OUT_AMP) {
+ if (node->wid_caps & AC_WCAP_AMP_OVRD)
+ node->amp_out_caps = snd_hda_param_read(codec, node->nid, AC_PAR_AMP_OUT_CAP);
+ if (! node->amp_out_caps)
+ node->amp_out_caps = spec->def_amp_out_caps;
+ }
+ if (node->wid_caps & AC_WCAP_IN_AMP) {
+ if (node->wid_caps & AC_WCAP_AMP_OVRD)
+ node->amp_in_caps = snd_hda_param_read(codec, node->nid, AC_PAR_AMP_IN_CAP);
+ if (! node->amp_in_caps)
+ node->amp_in_caps = spec->def_amp_in_caps;
+ }
+ list_add_tail(&node->list, &spec->nid_list);
+ return 0;
+}
+
+/*
+ * build the AFG subtree
+ */
+static int build_afg_tree(struct hda_codec *codec)
+{
+ struct hda_gspec *spec = codec->spec;
+ int i, nodes, err;
+ hda_nid_t nid;
+
+ snd_assert(spec, return -EINVAL);
+
+ spec->def_amp_out_caps = snd_hda_param_read(codec, codec->afg, AC_PAR_AMP_OUT_CAP);
+ spec->def_amp_in_caps = snd_hda_param_read(codec, codec->afg, AC_PAR_AMP_IN_CAP);
+
+ nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid);
+ if (! nid || nodes < 0) {
+ printk(KERN_ERR "Invalid AFG subtree\n");
+ return -EINVAL;
+ }
+
+ /* parse all nodes belonging to the AFG */
+ for (i = 0; i < nodes; i++, nid++) {
+ if ((err = add_new_node(codec, spec, nid)) < 0)
+ return err;
+ }
+
+ return 0;
+}
+
+
+/*
+ * look for the node record for the given NID
+ */
+/* FIXME: should avoid the braindead linear search */
+static struct hda_gnode *hda_get_node(struct hda_gspec *spec, hda_nid_t nid)
+{
+ struct list_head *p;
+ struct hda_gnode *node;
+
+ list_for_each(p, &spec->nid_list) {
+ node = list_entry(p, struct hda_gnode, list);
+ if (node->nid == nid)
+ return node;
+ }
+ return NULL;
+}
+
+/*
+ * unmute (and set max vol) the output amplifier
+ */
+static int unmute_output(struct hda_codec *codec, struct hda_gnode *node)
+{
+ unsigned int val, ofs;
+ snd_printdd("UNMUTE OUT: NID=0x%x\n", node->nid);
+ val = (node->amp_out_caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT;
+ ofs = (node->amp_out_caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT;
+ if (val >= ofs)
+ val -= ofs;
+ val |= AC_AMP_SET_LEFT | AC_AMP_SET_RIGHT;
+ val |= AC_AMP_SET_OUTPUT;
+ return snd_hda_codec_write(codec, node->nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, val);
+}
+
+/*
+ * unmute (and set max vol) the input amplifier
+ */
+static int unmute_input(struct hda_codec *codec, struct hda_gnode *node, unsigned int index)
+{
+ unsigned int val, ofs;
+ snd_printdd("UNMUTE IN: NID=0x%x IDX=0x%x\n", node->nid, index);
+ val = (node->amp_in_caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT;
+ ofs = (node->amp_in_caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT;
+ if (val >= ofs)
+ val -= ofs;
+ val |= AC_AMP_SET_LEFT | AC_AMP_SET_RIGHT;
+ val |= AC_AMP_SET_INPUT;
+ // awk added - fixed to allow unmuting of indexed amps
+ val |= index << AC_AMP_SET_INDEX_SHIFT;
+ return snd_hda_codec_write(codec, node->nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, val);
+}
+
+/*
+ * select the input connection of the given node.
+ */
+static int select_input_connection(struct hda_codec *codec, struct hda_gnode *node,
+ unsigned int index)
+{
+ snd_printdd("CONNECT: NID=0x%x IDX=0x%x\n", node->nid, index);
+ return snd_hda_codec_write(codec, node->nid, 0, AC_VERB_SET_CONNECT_SEL, index);
+}
+
+/*
+ * clear checked flag of each node in the node list
+ */
+static void clear_check_flags(struct hda_gspec *spec)
+{
+ struct list_head *p;
+ struct hda_gnode *node;
+
+ list_for_each(p, &spec->nid_list) {
+ node = list_entry(p, struct hda_gnode, list);
+ node->checked = 0;
+ }
+}
+
+/*
+ * parse the output path recursively until reach to an audio output widget
+ *
+ * returns 0 if not found, 1 if found, or a negative error code.
+ */
+static int parse_output_path(struct hda_codec *codec, struct hda_gspec *spec,
+ struct hda_gnode *node)
+{
+ int i, err;
+ struct hda_gnode *child;
+
+ if (node->checked)
+ return 0;
+
+ node->checked = 1;
+ if (node->type == AC_WID_AUD_OUT) {
+ if (node->wid_caps & AC_WCAP_DIGITAL) {
+ snd_printdd("Skip Digital OUT node %x\n", node->nid);
+ return 0;
+ }
+ snd_printdd("AUD_OUT found %x\n", node->nid);
+ if (spec->dac_node) {
+ /* already DAC node is assigned, just unmute & connect */
+ return node == spec->dac_node;
+ }
+ spec->dac_node = node;
+ if (node->wid_caps & AC_WCAP_OUT_AMP) {
+ spec->pcm_vol_node = node;
+ spec->pcm_vol_index = 0;
+ }
+ return 1; /* found */
+ }
+
+ for (i = 0; i < node->nconns; i++) {
+ child = hda_get_node(spec, node->conn_list[i]);
+ if (! child)
+ continue;
+ err = parse_output_path(codec, spec, child);
+ if (err < 0)
+ return err;
+ else if (err > 0) {
+ /* found one,
+ * select the path, unmute both input and output
+ */
+ if (node->nconns > 1)
+ select_input_connection(codec, node, i);
+ unmute_input(codec, node, i);
+ unmute_output(codec, node);
+ if (! spec->pcm_vol_node) {
+ if (node->wid_caps & AC_WCAP_IN_AMP) {
+ spec->pcm_vol_node = node;
+ spec->pcm_vol_index = i;
+ } else if (node->wid_caps & AC_WCAP_OUT_AMP) {
+ spec->pcm_vol_node = node;
+ spec->pcm_vol_index = 0;
+ }
+ }
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/*
+ * Look for the output PIN widget with the given jack type
+ * and parse the output path to that PIN.
+ *
+ * Returns the PIN node when the path to DAC is established.
+ */
+static struct hda_gnode *parse_output_jack(struct hda_codec *codec,
+ struct hda_gspec *spec,
+ int jack_type)
+{
+ struct list_head *p;
+ struct hda_gnode *node;
+ int err;
+
+ list_for_each(p, &spec->nid_list) {
+ node = list_entry(p, struct hda_gnode, list);
+ if (node->type != AC_WID_PIN)
+ continue;
+ /* output capable? */
+ if (! (node->pin_caps & AC_PINCAP_OUT))
+ continue;
+ if (jack_type >= 0) {
+ if (jack_type != get_defcfg_type(node))
+ continue;
+ if (node->wid_caps & AC_WCAP_DIGITAL)
+ continue; /* skip SPDIF */
+ } else {
+ /* output as default? */
+ if (! (node->pin_ctl & AC_PINCTL_OUT_EN))
+ continue;
+ }
+ clear_check_flags(spec);
+ err = parse_output_path(codec, spec, node);
+ if (err < 0)
+ return NULL;
+ else if (err > 0) {
+ /* unmute the PIN output */
+ unmute_output(codec, node);
+ /* set PIN-Out enable */
+ snd_hda_codec_write(codec, node->nid, 0,
+ AC_VERB_SET_PIN_WIDGET_CONTROL,
+ AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN);
+ return node;
+ }
+ }
+ return NULL;
+}
+
+
+/*
+ * parse outputs
+ */
+static int parse_output(struct hda_codec *codec)
+{
+ struct hda_gspec *spec = codec->spec;
+ struct hda_gnode *node;
+
+ /*
+ * Look for the output PIN widget
+ */
+ /* first, look for the line-out pin */
+ node = parse_output_jack(codec, spec, AC_JACK_LINE_OUT);
+ if (node) /* found, remember the PIN node */
+ spec->out_pin_node = node;
+ /* look for the HP-out pin */
+ node = parse_output_jack(codec, spec, AC_JACK_HP_OUT);
+ if (node) {
+ if (! spec->out_pin_node)
+ spec->out_pin_node = node;
+ }
+
+ if (! spec->out_pin_node) {
+ /* no line-out or HP pins found,
+ * then choose for the first output pin
+ */
+ spec->out_pin_node = parse_output_jack(codec, spec, -1);
+ if (! spec->out_pin_node)
+ snd_printd("hda_generic: no proper output path found\n");
+ }
+
+ return 0;
+}
+
+/*
+ * input MUX
+ */
+
+/* control callbacks */
+static int capture_source_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *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)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct hda_gspec *spec = codec->spec;
+
+ ucontrol->value.enumerated.item[0] = spec->cur_cap_src;
+ return 0;
+}
+
+static int capture_source_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct hda_gspec *spec = codec->spec;
+ return snd_hda_input_mux_put(codec, &spec->input_mux, ucontrol,
+ spec->adc_node->nid, &spec->cur_cap_src);
+}
+
+/*
+ * return the string name of the given input PIN widget
+ */
+static const char *get_input_type(struct hda_gnode *node, unsigned int *pinctl)
+{
+ unsigned int location = get_defcfg_location(node);
+ switch (get_defcfg_type(node)) {
+ case AC_JACK_LINE_IN:
+ if ((location & 0x0f) == AC_JACK_LOC_FRONT)
+ return "Front Line";
+ return "Line";
+ case AC_JACK_CD:
+ if (pinctl)
+ *pinctl |= AC_PIN_VREF_GRD;
+ return "CD";
+ case AC_JACK_AUX:
+ if ((location & 0x0f) == AC_JACK_LOC_FRONT)
+ return "Front Aux";
+ return "Aux";
+ case AC_JACK_MIC_IN:
+ if ((location & 0x0f) == AC_JACK_LOC_FRONT)
+ return "Front Mic";
+ return "Mic";
+ case AC_JACK_SPDIF_IN:
+ return "SPDIF";
+ case AC_JACK_DIG_OTHER_IN:
+ return "Digital";
+ }
+ return NULL;
+}
+
+/*
+ * parse the nodes recursively until reach to the input PIN
+ *
+ * returns 0 if not found, 1 if found, or a negative error code.
+ */
+static int parse_adc_sub_nodes(struct hda_codec *codec, struct hda_gspec *spec,
+ struct hda_gnode *node)
+{
+ int i, err;
+ unsigned int pinctl;
+ char *label;
+ const char *type;
+
+ if (node->checked)
+ return 0;
+
+ node->checked = 1;
+ if (node->type != AC_WID_PIN) {
+ for (i = 0; i < node->nconns; i++) {
+ struct hda_gnode *child;
+ child = hda_get_node(spec, node->conn_list[i]);
+ if (! child)
+ continue;
+ err = parse_adc_sub_nodes(codec, spec, child);
+ if (err < 0)
+ return err;
+ if (err > 0) {
+ /* found one,
+ * select the path, unmute both input and output
+ */
+ if (node->nconns > 1)
+ select_input_connection(codec, node, i);
+ unmute_input(codec, node, i);
+ unmute_output(codec, node);
+ return err;
+ }
+ }
+ return 0;
+ }
+
+ /* input capable? */
+ if (! (node->pin_caps & AC_PINCAP_IN))
+ return 0;
+
+ if (node->wid_caps & AC_WCAP_DIGITAL)
+ return 0; /* skip SPDIF */
+
+ if (spec->input_mux.num_items >= HDA_MAX_NUM_INPUTS) {
+ snd_printk(KERN_ERR "hda_generic: Too many items for capture\n");
+ return -EINVAL;
+ }
+
+ pinctl = AC_PINCTL_IN_EN;
+ /* create a proper capture source label */
+ type = get_input_type(node, &pinctl);
+ if (! type) {
+ /* input as default? */
+ if (! (node->pin_ctl & AC_PINCTL_IN_EN))
+ return 0;
+ type = "Input";
+ }
+ label = spec->cap_labels[spec->input_mux.num_items];
+ strcpy(label, type);
+ spec->input_mux.items[spec->input_mux.num_items].label = label;
+
+ /* unmute the PIN external input */
+ unmute_input(codec, node, 0); /* index = 0? */
+ /* set PIN-In enable */
+ snd_hda_codec_write(codec, node->nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pinctl);
+
+ return 1; /* found */
+}
+
+/*
+ * parse input
+ */
+static int parse_input_path(struct hda_codec *codec, struct hda_gnode *adc_node)
+{
+ struct hda_gspec *spec = codec->spec;
+ struct hda_gnode *node;
+ int i, err;
+
+ snd_printdd("AUD_IN = %x\n", adc_node->nid);
+ clear_check_flags(spec);
+
+ // awk added - fixed no recording due to muted widget
+ unmute_input(codec, adc_node, 0);
+
+ /*
+ * check each connection of the ADC
+ * if it reaches to a proper input PIN, add the path as the
+ * input path.
+ */
+ for (i = 0; i < adc_node->nconns; i++) {
+ node = hda_get_node(spec, adc_node->conn_list[i]);
+ if (! node)
+ continue;
+ err = parse_adc_sub_nodes(codec, spec, node);
+ if (err < 0)
+ return err;
+ else if (err > 0) {
+ struct hda_input_mux_item *csrc = &spec->input_mux.items[spec->input_mux.num_items];
+ char *buf = spec->cap_labels[spec->input_mux.num_items];
+ int ocap;
+ for (ocap = 0; ocap < spec->input_mux.num_items; ocap++) {
+ if (! strcmp(buf, spec->cap_labels[ocap])) {
+ /* same label already exists,
+ * put the index number to be unique
+ */
+ sprintf(buf, "%s %d", spec->cap_labels[ocap],
+ spec->input_mux.num_items);
+ }
+ }
+ csrc->index = i;
+ spec->input_mux.num_items++;
+ }
+ }
+
+ if (! spec->input_mux.num_items)
+ return 0; /* no input path found... */
+
+ snd_printdd("[Capture Source] NID=0x%x, #SRC=%d\n", adc_node->nid, spec->input_mux.num_items);
+ for (i = 0; i < spec->input_mux.num_items; i++)
+ snd_printdd(" [%s] IDX=0x%x\n", spec->input_mux.items[i].label,
+ spec->input_mux.items[i].index);
+
+ spec->adc_node = adc_node;
+ return 1;
+}
+
+/*
+ * parse input
+ */
+static int parse_input(struct hda_codec *codec)
+{
+ struct hda_gspec *spec = codec->spec;
+ struct list_head *p;
+ struct hda_gnode *node;
+ int err;
+
+ /*
+ * At first we look for an audio input widget.
+ * If it reaches to certain input PINs, we take it as the
+ * input path.
+ */
+ list_for_each(p, &spec->nid_list) {
+ node = list_entry(p, struct hda_gnode, list);
+ if (node->wid_caps & AC_WCAP_DIGITAL)
+ continue; /* skip SPDIF */
+ if (node->type == AC_WID_AUD_IN) {
+ err = parse_input_path(codec, node);
+ if (err < 0)
+ return err;
+ else if (err > 0)
+ return 0;
+ }
+ }
+ snd_printd("hda_generic: no proper input path found\n");
+ return 0;
+}
+
+/*
+ * create mixer controls if possible
+ */
+#define DIR_OUT 0x1
+#define DIR_IN 0x2
+
+static int create_mixer(struct hda_codec *codec, struct hda_gnode *node,
+ unsigned int index, const char *type, const char *dir_sfx)
+{
+ char name[32];
+ int err;
+ int created = 0;
+ snd_kcontrol_new_t knew;
+
+ if (type)
+ sprintf(name, "%s %s Switch", type, dir_sfx);
+ else
+ 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);
+ 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);
+ 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;
+ created = 1;
+ }
+
+ if (type)
+ sprintf(name, "%s %s Volume", type, dir_sfx);
+ else
+ 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);
+ 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);
+ 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;
+ created = 1;
+ }
+
+ return created;
+}
+
+/*
+ * check whether the controls with the given name and direction suffix already exist
+ */
+static int check_existing_control(struct hda_codec *codec, const char *type, const char *dir)
+{
+ snd_ctl_elem_id_t id;
+ memset(&id, 0, sizeof(id));
+ sprintf(id.name, "%s %s Volume", type, dir);
+ id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+ if (snd_ctl_find_id(codec->bus->card, &id))
+ return 1;
+ sprintf(id.name, "%s %s Switch", type, dir);
+ id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+ if (snd_ctl_find_id(codec->bus->card, &id))
+ return 1;
+ return 0;
+}
+
+/*
+ * build output mixer controls
+ */
+static int build_output_controls(struct hda_codec *codec)
+{
+ struct hda_gspec *spec = codec->spec;
+ int err;
+
+ err = create_mixer(codec, spec->pcm_vol_node, spec->pcm_vol_index,
+ "PCM", "Playback");
+ if (err < 0)
+ return err;
+ return 0;
+}
+
+/* create capture volume/switch */
+static int build_input_controls(struct hda_codec *codec)
+{
+ struct hda_gspec *spec = codec->spec;
+ struct hda_gnode *adc_node = spec->adc_node;
+ int err;
+
+ if (! adc_node)
+ return 0; /* not found */
+
+ /* create capture volume and switch controls if the ADC has an amp */
+ err = create_mixer(codec, adc_node, 0, NULL, "Capture");
+
+ /* create input MUX if multiple sources are available */
+ if (spec->input_mux.num_items > 1) {
+ static snd_kcontrol_new_t cap_sel = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Capture Source",
+ .info = capture_source_info,
+ .get = capture_source_get,
+ .put = capture_source_put,
+ };
+ if ((err = snd_ctl_add(codec->bus->card, snd_ctl_new1(&cap_sel, codec))) < 0)
+ return err;
+ spec->cur_cap_src = 0;
+ select_input_connection(codec, adc_node, spec->input_mux.items[0].index);
+ }
+ return 0;
+}
+
+
+/*
+ * parse the nodes recursively until reach to the output PIN.
+ *
+ * returns 0 - if not found,
+ * 1 - if found, but no mixer is created
+ * 2 - if found and mixer was already created, (just skip)
+ * a negative error code
+ */
+static int parse_loopback_path(struct hda_codec *codec, struct hda_gspec *spec,
+ struct hda_gnode *node, struct hda_gnode *dest_node,
+ const char *type)
+{
+ int i, err;
+
+ if (node->checked)
+ return 0;
+
+ node->checked = 1;
+ if (node == dest_node) {
+ /* loopback connection found */
+ return 1;
+ }
+
+ for (i = 0; i < node->nconns; i++) {
+ struct hda_gnode *child = hda_get_node(spec, node->conn_list[i]);
+ if (! child)
+ continue;
+ err = parse_loopback_path(codec, spec, child, dest_node, type);
+ if (err < 0)
+ return err;
+ else if (err >= 1) {
+ if (err == 1) {
+ err = create_mixer(codec, node, i, type, "Playback");
+ if (err < 0)
+ return err;
+ if (err > 0)
+ return 2; /* ok, created */
+ /* not created, maybe in the lower path */
+ err = 1;
+ }
+ /* connect and unmute */
+ if (node->nconns > 1)
+ select_input_connection(codec, node, i);
+ unmute_input(codec, node, i);
+ unmute_output(codec, node);
+ return err;
+ }
+ }
+ return 0;
+}
+
+/*
+ * parse the tree and build the loopback controls
+ */
+static int build_loopback_controls(struct hda_codec *codec)
+{
+ struct hda_gspec *spec = codec->spec;
+ struct list_head *p;
+ struct hda_gnode *node;
+ int err;
+ const char *type;
+
+ if (! spec->out_pin_node)
+ return 0;
+
+ list_for_each(p, &spec->nid_list) {
+ node = list_entry(p, struct hda_gnode, list);
+ if (node->type != AC_WID_PIN)
+ continue;
+ /* input capable? */
+ if (! (node->pin_caps & AC_PINCAP_IN))
+ return 0;
+ type = get_input_type(node, NULL);
+ if (type) {
+ if (check_existing_control(codec, type, "Playback"))
+ continue;
+ clear_check_flags(spec);
+ err = parse_loopback_path(codec, spec, spec->out_pin_node,
+ node, type);
+ if (err < 0)
+ return err;
+ if (! err)
+ continue;
+ }
+ }
+ return 0;
+}
+
+/*
+ * build mixer controls
+ */
+static int build_generic_controls(struct hda_codec *codec)
+{
+ int err;
+
+ if ((err = build_input_controls(codec)) < 0 ||
+ (err = build_output_controls(codec)) < 0 ||
+ (err = build_loopback_controls(codec)) < 0)
+ return err;
+
+ return 0;
+}
+
+/*
+ * PCM
+ */
+static struct hda_pcm_stream generic_pcm_playback = {
+ .substreams = 1,
+ .channels_min = 2,
+ .channels_max = 2,
+};
+
+static int build_generic_pcms(struct hda_codec *codec)
+{
+ struct hda_gspec *spec = codec->spec;
+ struct hda_pcm *info = &spec->pcm_rec;
+
+ if (! spec->dac_node && ! spec->adc_node) {
+ snd_printd("hda_generic: no PCM found\n");
+ return 0;
+ }
+
+ codec->num_pcms = 1;
+ codec->pcm_info = info;
+
+ info->name = "HDA Generic";
+ if (spec->dac_node) {
+ info->stream[0] = generic_pcm_playback;
+ info->stream[0].nid = spec->dac_node->nid;
+ }
+ if (spec->adc_node) {
+ info->stream[1] = generic_pcm_playback;
+ info->stream[1].nid = spec->adc_node->nid;
+ }
+
+ return 0;
+}
+
+
+/*
+ */
+static struct hda_codec_ops generic_patch_ops = {
+ .build_controls = build_generic_controls,
+ .build_pcms = build_generic_pcms,
+ .free = snd_hda_generic_free,
+};
+
+/*
+ * the generic parser
+ */
+int snd_hda_parse_generic_codec(struct hda_codec *codec)
+{
+ struct hda_gspec *spec;
+ int err;
+
+ spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
+ if (spec == NULL) {
+ printk(KERN_ERR "hda_generic: can't allocate spec\n");
+ return -ENOMEM;
+ }
+ codec->spec = spec;
+ INIT_LIST_HEAD(&spec->nid_list);
+
+ if ((err = build_afg_tree(codec)) < 0)
+ goto error;
+
+ if ((err = parse_input(codec)) < 0 ||
+ (err = parse_output(codec)) < 0)
+ goto error;
+
+ codec->patch_ops = generic_patch_ops;
+
+ return 0;
+
+ error:
+ snd_hda_generic_free(codec);
+ return err;
+}
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
new file mode 100644
index 0000000000000..d89647a3d449d
--- /dev/null
+++ b/sound/pci/hda/hda_intel.c
@@ -0,0 +1,1449 @@
+/*
+ *
+ * hda_intel.c - Implementation of primary alsa driver code base for Intel HD Audio.
+ *
+ * Copyright(c) 2004 Intel Corporation. All rights reserved.
+ *
+ * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
+ * PeiSen Hou <pshou@realtek.com.tw>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the 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.
+ *
+ * CONTACTS:
+ *
+ * Matt Jared matt.jared@intel.com
+ * Andy Kopp andy.kopp@intel.com
+ * Dan Kogan dan.d.kogan@intel.com
+ *
+ * CHANGES:
+ *
+ * 2004.12.01 Major rewrite by tiwai, merged the work of pshou
+ *
+ */
+
+#include <sound/driver.h>
+#include <asm/io.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <sound/core.h>
+#include <sound/initval.h>
+#include "hda_codec.h"
+
+
+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
+static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
+static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
+static char *model[SNDRV_CARDS];
+
+module_param_array(index, int, NULL, 0444);
+MODULE_PARM_DESC(index, "Index value for Intel HD audio interface.");
+module_param_array(id, charp, NULL, 0444);
+MODULE_PARM_DESC(id, "ID string for Intel HD audio interface.");
+module_param_array(enable, bool, NULL, 0444);
+MODULE_PARM_DESC(enable, "Enable Intel HD audio interface.");
+module_param_array(model, charp, NULL, 0444);
+MODULE_PARM_DESC(model, "Use the given board model.");
+
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE("{{Intel, ICH6},"
+ "{Intel, ICH6M},"
+ "{Intel, ICH7}}");
+MODULE_DESCRIPTION("Intel HDA driver");
+
+#define SFX "hda-intel: "
+
+/*
+ * registers
+ */
+#define ICH6_REG_GCAP 0x00
+#define ICH6_REG_VMIN 0x02
+#define ICH6_REG_VMAJ 0x03
+#define ICH6_REG_OUTPAY 0x04
+#define ICH6_REG_INPAY 0x06
+#define ICH6_REG_GCTL 0x08
+#define ICH6_REG_WAKEEN 0x0c
+#define ICH6_REG_STATESTS 0x0e
+#define ICH6_REG_GSTS 0x10
+#define ICH6_REG_INTCTL 0x20
+#define ICH6_REG_INTSTS 0x24
+#define ICH6_REG_WALCLK 0x30
+#define ICH6_REG_SYNC 0x34
+#define ICH6_REG_CORBLBASE 0x40
+#define ICH6_REG_CORBUBASE 0x44
+#define ICH6_REG_CORBWP 0x48
+#define ICH6_REG_CORBRP 0x4A
+#define ICH6_REG_CORBCTL 0x4c
+#define ICH6_REG_CORBSTS 0x4d
+#define ICH6_REG_CORBSIZE 0x4e
+
+#define ICH6_REG_RIRBLBASE 0x50
+#define ICH6_REG_RIRBUBASE 0x54
+#define ICH6_REG_RIRBWP 0x58
+#define ICH6_REG_RINTCNT 0x5a
+#define ICH6_REG_RIRBCTL 0x5c
+#define ICH6_REG_RIRBSTS 0x5d
+#define ICH6_REG_RIRBSIZE 0x5e
+
+#define ICH6_REG_IC 0x60
+#define ICH6_REG_IR 0x64
+#define ICH6_REG_IRS 0x68
+#define ICH6_IRS_VALID (1<<1)
+#define ICH6_IRS_BUSY (1<<0)
+
+#define ICH6_REG_DPLBASE 0x70
+#define ICH6_REG_DPUBASE 0x74
+#define ICH6_DPLBASE_ENABLE 0x1 /* Enable position buffer */
+
+/* SD offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */
+enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
+
+/* stream register offsets from stream base */
+#define ICH6_REG_SD_CTL 0x00
+#define ICH6_REG_SD_STS 0x03
+#define ICH6_REG_SD_LPIB 0x04
+#define ICH6_REG_SD_CBL 0x08
+#define ICH6_REG_SD_LVI 0x0c
+#define ICH6_REG_SD_FIFOW 0x0e
+#define ICH6_REG_SD_FIFOSIZE 0x10
+#define ICH6_REG_SD_FORMAT 0x12
+#define ICH6_REG_SD_BDLPL 0x18
+#define ICH6_REG_SD_BDLPU 0x1c
+
+/* PCI space */
+#define ICH6_PCIREG_TCSEL 0x44
+
+/*
+ * other constants
+ */
+
+/* max number of SDs */
+#define MAX_ICH6_DEV 8
+/* max number of fragments - we may use more if allocating more pages for BDL */
+#define AZX_MAX_FRAG (PAGE_SIZE / (MAX_ICH6_DEV * 16))
+/* max buffer size - no h/w limit, you can increase as you like */
+#define AZX_MAX_BUF_SIZE (1024*1024*1024)
+/* max number of PCM devics per card */
+#define AZX_MAX_PCMS 8
+
+/* RIRB int mask: overrun[2], response[0] */
+#define RIRB_INT_RESPONSE 0x01
+#define RIRB_INT_OVERRUN 0x04
+#define RIRB_INT_MASK 0x05
+
+/* STATESTS int mask: SD2,SD1,SD0 */
+#define STATESTS_INT_MASK 0x07
+#define AZX_MAX_CODECS 3
+
+/* SD_CTL bits */
+#define SD_CTL_STREAM_RESET 0x01 /* stream reset bit */
+#define SD_CTL_DMA_START 0x02 /* stream DMA start bit */
+#define SD_CTL_STREAM_TAG_MASK (0xf << 20)
+#define SD_CTL_STREAM_TAG_SHIFT 20
+
+/* SD_CTL and SD_STS */
+#define SD_INT_DESC_ERR 0x10 /* descriptor error interrupt */
+#define SD_INT_FIFO_ERR 0x08 /* FIFO error interrupt */
+#define SD_INT_COMPLETE 0x04 /* completion interrupt */
+#define SD_INT_MASK (SD_INT_DESC_ERR|SD_INT_FIFO_ERR|SD_INT_COMPLETE)
+
+/* SD_STS */
+#define SD_STS_FIFO_READY 0x20 /* FIFO ready */
+
+/* INTCTL and INTSTS */
+#define ICH6_INT_ALL_STREAM 0xff /* all stream interrupts */
+#define ICH6_INT_CTRL_EN 0x40000000 /* controller interrupt enable bit */
+#define ICH6_INT_GLOBAL_EN 0x80000000 /* global interrupt enable bit */
+
+/* GCTL reset bit */
+#define ICH6_GCTL_RESET (1<<0)
+
+/* CORB/RIRB control, read/write pointer */
+#define ICH6_RBCTL_DMA_EN 0x02 /* enable DMA */
+#define ICH6_RBCTL_IRQ_EN 0x01 /* enable IRQ */
+#define ICH6_RBRWP_CLR 0x8000 /* read/write pointer clear */
+/* below are so far hardcoded - should read registers in future */
+#define ICH6_MAX_CORB_ENTRIES 256
+#define ICH6_MAX_RIRB_ENTRIES 256
+
+
+/*
+ * Use CORB/RIRB for communication from/to codecs.
+ * This is the way recommended by Intel (see below).
+ */
+#define USE_CORB_RIRB
+
+/*
+ * Define this if use the position buffer instead of reading SD_LPIB
+ * It's not used as default since SD_LPIB seems to give more accurate position
+ */
+/* #define USE_POSBUF */
+
+/*
+ */
+
+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 {
+ u32 *bdl; /* virtual address of the BDL */
+ dma_addr_t bdl_addr; /* physical address of the BDL */
+ volatile u32 *posbuf; /* position buffer pointer */
+
+ unsigned int bufsize; /* size of the play buffer in bytes */
+ unsigned int fragsize; /* size of each period in bytes */
+ unsigned int frags; /* number for period in the play buffer */
+ unsigned int fifo_size; /* FIFO size */
+
+ void __iomem *sd_addr; /* stream descriptor pointer */
+
+ u32 sd_int_sta_mask; /* stream int status mask */
+
+ /* pcm support */
+ snd_pcm_substream_t *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 */
+
+ unsigned int opened: 1;
+ unsigned int running: 1;
+};
+
+/* CORB/RIRB */
+struct snd_azx_rb {
+ u32 *buf; /* CORB/RIRB buffer
+ * Each CORB entry is 4byte, RIRB is 8byte
+ */
+ dma_addr_t addr; /* physical address of CORB/RIRB buffer */
+ /* for RIRB */
+ unsigned short rp, wp; /* read/write pointers */
+ int cmds; /* number of pending requests */
+ u32 res; /* last read value */
+};
+
+struct snd_azx {
+ snd_card_t *card;
+ struct pci_dev *pci;
+
+ /* pci resources */
+ unsigned long addr;
+ void __iomem *remap_addr;
+ int irq;
+
+ /* locks */
+ spinlock_t reg_lock;
+ struct semaphore open_mutex;
+
+ /* streams */
+ azx_dev_t azx_dev[MAX_ICH6_DEV];
+
+ /* PCM */
+ unsigned int pcm_devs;
+ snd_pcm_t *pcm[AZX_MAX_PCMS];
+
+ /* HD codec */
+ unsigned short codec_mask;
+ struct hda_bus *bus;
+
+ /* CORB/RIRB */
+ azx_rb_t corb;
+ azx_rb_t rirb;
+
+ /* BDL, CORB/RIRB and position buffers */
+ struct snd_dma_buffer bdl;
+ struct snd_dma_buffer rb;
+ struct snd_dma_buffer posbuf;
+};
+
+/*
+ * macros for easy use
+ */
+#define azx_writel(chip,reg,value) \
+ writel(value, (chip)->remap_addr + ICH6_REG_##reg)
+#define azx_readl(chip,reg) \
+ readl((chip)->remap_addr + ICH6_REG_##reg)
+#define azx_writew(chip,reg,value) \
+ writew(value, (chip)->remap_addr + ICH6_REG_##reg)
+#define azx_readw(chip,reg) \
+ readw((chip)->remap_addr + ICH6_REG_##reg)
+#define azx_writeb(chip,reg,value) \
+ writeb(value, (chip)->remap_addr + ICH6_REG_##reg)
+#define azx_readb(chip,reg) \
+ readb((chip)->remap_addr + ICH6_REG_##reg)
+
+#define azx_sd_writel(dev,reg,value) \
+ writel(value, (dev)->sd_addr + ICH6_REG_##reg)
+#define azx_sd_readl(dev,reg) \
+ readl((dev)->sd_addr + ICH6_REG_##reg)
+#define azx_sd_writew(dev,reg,value) \
+ writew(value, (dev)->sd_addr + ICH6_REG_##reg)
+#define azx_sd_readw(dev,reg) \
+ readw((dev)->sd_addr + ICH6_REG_##reg)
+#define azx_sd_writeb(dev,reg,value) \
+ writeb(value, (dev)->sd_addr + ICH6_REG_##reg)
+#define azx_sd_readb(dev,reg) \
+ readb((dev)->sd_addr + ICH6_REG_##reg)
+
+/* for pcm support */
+#define get_azx_dev(substream) (azx_dev_t*)(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
+ */
+#define upper_32bit(addr) (sizeof(addr) > 4 ? (u32)((addr) >> 32) : (u32)0)
+
+
+/*
+ * Interface for HD codec
+ */
+
+#ifdef USE_CORB_RIRB
+/*
+ * CORB / RIRB interface
+ */
+static int azx_alloc_cmd_io(azx_t *chip)
+{
+ int err;
+
+ /* single page (at least 4096 bytes) must suffice for both ringbuffes */
+ err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
+ PAGE_SIZE, &chip->rb);
+ if (err < 0) {
+ snd_printk(KERN_ERR SFX "cannot allocate CORB/RIRB\n");
+ return err;
+ }
+ return 0;
+}
+
+static void azx_init_cmd_io(azx_t *chip)
+{
+ /* CORB set up */
+ chip->corb.addr = chip->rb.addr;
+ chip->corb.buf = (u32 *)chip->rb.area;
+ azx_writel(chip, CORBLBASE, (u32)chip->corb.addr);
+ azx_writel(chip, CORBUBASE, upper_32bit(chip->corb.addr));
+
+ /* set the corb write pointer to 0 */
+ azx_writew(chip, CORBWP, 0);
+ /* reset the corb hw read pointer */
+ azx_writew(chip, CORBRP, ICH6_RBRWP_CLR);
+ /* enable corb dma */
+ azx_writeb(chip, CORBCTL, ICH6_RBCTL_DMA_EN);
+
+ /* RIRB set up */
+ chip->rirb.addr = chip->rb.addr + 2048;
+ chip->rirb.buf = (u32 *)(chip->rb.area + 2048);
+ azx_writel(chip, RIRBLBASE, (u32)chip->rirb.addr);
+ azx_writel(chip, RIRBUBASE, upper_32bit(chip->rirb.addr));
+
+ /* reset the rirb hw write pointer */
+ azx_writew(chip, RIRBWP, ICH6_RBRWP_CLR);
+ /* set N=1, get RIRB response interrupt for new entry */
+ azx_writew(chip, RINTCNT, 1);
+ /* enable rirb dma and response irq */
+#ifdef USE_CORB_RIRB
+ azx_writeb(chip, RIRBCTL, ICH6_RBCTL_DMA_EN | ICH6_RBCTL_IRQ_EN);
+#else
+ azx_writeb(chip, RIRBCTL, ICH6_RBCTL_DMA_EN);
+#endif
+ chip->rirb.rp = chip->rirb.cmds = 0;
+}
+
+static void azx_free_cmd_io(azx_t *chip)
+{
+ /* disable ringbuffer DMAs */
+ azx_writeb(chip, RIRBCTL, 0);
+ azx_writeb(chip, CORBCTL, 0);
+}
+
+/* send a command */
+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;
+ unsigned int wp;
+ u32 val;
+
+ val = (u32)(codec->addr & 0x0f) << 28;
+ val |= (u32)direct << 27;
+ val |= (u32)nid << 20;
+ val |= verb << 8;
+ val |= para;
+
+ /* add command to corb */
+ wp = azx_readb(chip, CORBWP);
+ wp++;
+ wp %= ICH6_MAX_CORB_ENTRIES;
+
+ spin_lock_irq(&chip->reg_lock);
+ chip->rirb.cmds++;
+ chip->corb.buf[wp] = cpu_to_le32(val);
+ azx_writel(chip, CORBWP, wp);
+ spin_unlock_irq(&chip->reg_lock);
+
+ return 0;
+}
+
+#define ICH6_RIRB_EX_UNSOL_EV (1<<4)
+
+/* retrieve RIRB entry - called from interrupt handler */
+static void azx_update_rirb(azx_t *chip)
+{
+ unsigned int rp, wp;
+ u32 res, res_ex;
+
+ wp = azx_readb(chip, RIRBWP);
+ if (wp == chip->rirb.wp)
+ return;
+ chip->rirb.wp = wp;
+
+ while (chip->rirb.rp != wp) {
+ chip->rirb.rp++;
+ chip->rirb.rp %= ICH6_MAX_RIRB_ENTRIES;
+
+ rp = chip->rirb.rp << 1; /* an RIRB entry is 8-bytes */
+ res_ex = le32_to_cpu(chip->rirb.buf[rp + 1]);
+ res = le32_to_cpu(chip->rirb.buf[rp]);
+ if (res_ex & ICH6_RIRB_EX_UNSOL_EV)
+ snd_hda_queue_unsol_event(chip->bus, res, res_ex);
+ else if (chip->rirb.cmds) {
+ chip->rirb.cmds--;
+ chip->rirb.res = res;
+ }
+ }
+}
+
+/* receive a response */
+static unsigned int azx_get_response(struct hda_codec *codec)
+{
+ azx_t *chip = codec->bus->private_data;
+ int timeout = 50;
+
+ while (chip->rirb.cmds) {
+ if (! --timeout) {
+ snd_printk(KERN_ERR "azx_get_response timeout\n");
+ chip->rirb.rp = azx_readb(chip, RIRBWP);
+ chip->rirb.cmds = 0;
+ return -1;
+ }
+ msleep(1);
+ }
+ return chip->rirb.res; /* the last value */
+}
+
+#else
+/*
+ * Use the single immediate command instead of CORB/RIRB for simplicity
+ *
+ * Note: according to Intel, this is not preferred use. The command was
+ * intended for the BIOS only, and may get confused with unsolicited
+ * responses. So, we shouldn't use it for normal operation from the
+ * driver.
+ * I left the codes, however, for debugging/testing purposes.
+ */
+
+#define azx_alloc_cmd_io(chip) 0
+#define azx_init_cmd_io(chip)
+#define azx_free_cmd_io(chip)
+
+/* send a command */
+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;
+ u32 val;
+ int timeout = 50;
+
+ val = (u32)(codec->addr & 0x0f) << 28;
+ val |= (u32)direct << 27;
+ val |= (u32)nid << 20;
+ val |= verb << 8;
+ val |= para;
+
+ while (timeout--) {
+ /* check ICB busy bit */
+ if (! (azx_readw(chip, IRS) & ICH6_IRS_BUSY)) {
+ /* Clear IRV valid bit */
+ azx_writew(chip, IRS, azx_readw(chip, IRS) | ICH6_IRS_VALID);
+ azx_writel(chip, IC, val);
+ azx_writew(chip, IRS, azx_readw(chip, IRS) | ICH6_IRS_BUSY);
+ return 0;
+ }
+ udelay(1);
+ }
+ snd_printd(SFX "send_cmd timeout: IRS=0x%x, val=0x%x\n", azx_readw(chip, IRS), val);
+ return -EIO;
+}
+
+/* receive a response */
+static unsigned int azx_get_response(struct hda_codec *codec)
+{
+ azx_t *chip = codec->bus->private_data;
+ int timeout = 50;
+
+ while (timeout--) {
+ /* check IRV busy bit */
+ if (azx_readw(chip, IRS) & ICH6_IRS_VALID)
+ return azx_readl(chip, IR);
+ udelay(1);
+ }
+ snd_printd(SFX "get_response timeout: IRS=0x%x\n", azx_readw(chip, IRS));
+ return (unsigned int)-1;
+}
+
+#define azx_update_rirb(chip)
+
+#endif /* USE_CORB_RIRB */
+
+/* reset codec link */
+static int azx_reset(azx_t *chip)
+{
+ int count;
+
+ /* reset controller */
+ azx_writel(chip, GCTL, azx_readl(chip, GCTL) & ~ICH6_GCTL_RESET);
+
+ count = 50;
+ while (azx_readb(chip, GCTL) && --count)
+ msleep(1);
+
+ /* delay for >= 100us for codec PLL to settle per spec
+ * Rev 0.9 section 5.5.1
+ */
+ msleep(1);
+
+ /* Bring controller out of reset */
+ azx_writeb(chip, GCTL, azx_readb(chip, GCTL) | ICH6_GCTL_RESET);
+
+ count = 50;
+ while (! azx_readb(chip, GCTL) && --count)
+ msleep(1);
+
+ /* Brent Chartrand said to wait >= 540us for codecs to intialize */
+ msleep(1);
+
+ /* check to see if controller is ready */
+ if (! azx_readb(chip, GCTL)) {
+ snd_printd("azx_reset: controller not ready!\n");
+ return -EBUSY;
+ }
+
+ /* detect codecs */
+ if (! chip->codec_mask) {
+ chip->codec_mask = azx_readw(chip, STATESTS);
+ snd_printdd("codec_mask = 0x%x\n", chip->codec_mask);
+ }
+
+ return 0;
+}
+
+
+/*
+ * Lowlevel interface
+ */
+
+/* enable interrupts */
+static void azx_int_enable(azx_t *chip)
+{
+ /* enable controller CIE and GIE */
+ azx_writel(chip, INTCTL, azx_readl(chip, INTCTL) |
+ ICH6_INT_CTRL_EN | ICH6_INT_GLOBAL_EN);
+}
+
+/* disable interrupts */
+static void azx_int_disable(azx_t *chip)
+{
+ int i;
+
+ /* disable interrupts in stream descriptor */
+ for (i = 0; i < MAX_ICH6_DEV; i++) {
+ azx_dev_t *azx_dev = &chip->azx_dev[i];
+ azx_sd_writeb(azx_dev, SD_CTL,
+ azx_sd_readb(azx_dev, SD_CTL) & ~SD_INT_MASK);
+ }
+
+ /* disable SIE for all streams */
+ azx_writeb(chip, INTCTL, 0);
+
+ /* disable controller CIE and GIE */
+ azx_writel(chip, INTCTL, azx_readl(chip, INTCTL) &
+ ~(ICH6_INT_CTRL_EN | ICH6_INT_GLOBAL_EN));
+}
+
+/* clear interrupts */
+static void azx_int_clear(azx_t *chip)
+{
+ int i;
+
+ /* clear stream status */
+ for (i = 0; i < MAX_ICH6_DEV; i++) {
+ azx_dev_t *azx_dev = &chip->azx_dev[i];
+ azx_sd_writeb(azx_dev, SD_STS, SD_INT_MASK);
+ }
+
+ /* clear STATESTS */
+ azx_writeb(chip, STATESTS, STATESTS_INT_MASK);
+
+ /* clear rirb status */
+ azx_writeb(chip, RIRBSTS, RIRB_INT_MASK);
+
+ /* clear int status */
+ azx_writel(chip, INTSTS, ICH6_INT_CTRL_EN | ICH6_INT_ALL_STREAM);
+}
+
+/* start a stream */
+static void azx_stream_start(azx_t *chip, azx_dev_t *azx_dev)
+{
+ /* enable SIE */
+ azx_writeb(chip, INTCTL,
+ azx_readb(chip, INTCTL) | (1 << azx_dev->index));
+ /* set DMA start and interrupt mask */
+ azx_sd_writeb(azx_dev, SD_CTL, azx_sd_readb(azx_dev, SD_CTL) |
+ SD_CTL_DMA_START | SD_INT_MASK);
+}
+
+/* stop a stream */
+static void azx_stream_stop(azx_t *chip, azx_dev_t *azx_dev)
+{
+ /* stop DMA */
+ azx_sd_writeb(azx_dev, SD_CTL, azx_sd_readb(azx_dev, SD_CTL) &
+ ~(SD_CTL_DMA_START | SD_INT_MASK));
+ azx_sd_writeb(azx_dev, SD_STS, SD_INT_MASK); /* to be sure */
+ /* disable SIE */
+ azx_writeb(chip, INTCTL,
+ azx_readb(chip, INTCTL) & ~(1 << azx_dev->index));
+}
+
+
+/*
+ * initialize the chip
+ */
+static void azx_init_chip(azx_t *chip)
+{
+ unsigned char tcsel_reg;
+
+ /* Clear bits 0-2 of PCI register TCSEL (at offset 0x44)
+ * TCSEL == Traffic Class Select Register, which sets PCI express QOS
+ * Ensuring these bits are 0 clears playback static on some HD Audio codecs
+ */
+ pci_read_config_byte (chip->pci, ICH6_PCIREG_TCSEL, &tcsel_reg);
+ pci_write_config_byte(chip->pci, ICH6_PCIREG_TCSEL, tcsel_reg & 0xf8);
+
+ /* reset controller */
+ azx_reset(chip);
+
+ /* initialize interrupts */
+ azx_int_clear(chip);
+ azx_int_enable(chip);
+
+ /* initialize the codec command I/O */
+ azx_init_cmd_io(chip);
+
+#ifdef USE_POSBUF
+ /* program the position buffer */
+ azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr);
+ azx_writel(chip, DPUBASE, upper_32bit(chip->posbuf.addr));
+#endif
+}
+
+
+/*
+ * interrupt handler
+ */
+static irqreturn_t azx_interrupt(int irq, void* dev_id, struct pt_regs *regs)
+{
+ azx_t *chip = dev_id;
+ azx_dev_t *azx_dev;
+ u32 status;
+ int i;
+
+ spin_lock(&chip->reg_lock);
+
+ status = azx_readl(chip, INTSTS);
+ if (status == 0) {
+ spin_unlock(&chip->reg_lock);
+ return IRQ_NONE;
+ }
+
+ for (i = 0; i < MAX_ICH6_DEV; i++) {
+ azx_dev = &chip->azx_dev[i];
+ if (status & azx_dev->sd_int_sta_mask) {
+ azx_sd_writeb(azx_dev, SD_STS, SD_INT_MASK);
+ if (azx_dev->substream && azx_dev->running) {
+ spin_unlock(&chip->reg_lock);
+ snd_pcm_period_elapsed(azx_dev->substream);
+ spin_lock(&chip->reg_lock);
+ }
+ }
+ }
+
+ /* clear rirb int */
+ status = azx_readb(chip, RIRBSTS);
+ if (status & RIRB_INT_MASK) {
+ if (status & RIRB_INT_RESPONSE)
+ azx_update_rirb(chip);
+ azx_writeb(chip, RIRBSTS, RIRB_INT_MASK);
+ }
+
+#if 0
+ /* clear state status int */
+ if (azx_readb(chip, STATESTS) & 0x04)
+ azx_writeb(chip, STATESTS, 0x04);
+#endif
+ spin_unlock(&chip->reg_lock);
+
+ return IRQ_HANDLED;
+}
+
+
+/*
+ * set up BDL entries
+ */
+static void azx_setup_periods(azx_dev_t *azx_dev)
+{
+ u32 *bdl = azx_dev->bdl;
+ dma_addr_t dma_addr = azx_dev->substream->runtime->dma_addr;
+ int idx;
+
+ /* reset BDL address */
+ azx_sd_writel(azx_dev, SD_BDLPL, 0);
+ azx_sd_writel(azx_dev, SD_BDLPU, 0);
+
+ /* program the initial BDL entries */
+ for (idx = 0; idx < azx_dev->frags; idx++) {
+ unsigned int off = idx << 2; /* 4 dword step */
+ dma_addr_t addr = dma_addr + idx * azx_dev->fragsize;
+ /* program the address field of the BDL entry */
+ bdl[off] = cpu_to_le32((u32)addr);
+ bdl[off+1] = cpu_to_le32(upper_32bit(addr));
+
+ /* program the size field of the BDL entry */
+ bdl[off+2] = cpu_to_le32(azx_dev->fragsize);
+
+ /* program the IOC to enable interrupt when buffer completes */
+ bdl[off+3] = cpu_to_le32(0x01);
+ }
+}
+
+/*
+ * set up the SD for streaming
+ */
+static int azx_setup_controller(azx_t *chip, azx_dev_t *azx_dev)
+{
+ unsigned char val;
+ int timeout;
+
+ /* make sure the run bit is zero for SD */
+ azx_sd_writeb(azx_dev, SD_CTL, azx_sd_readb(azx_dev, SD_CTL) & ~SD_CTL_DMA_START);
+ /* reset stream */
+ azx_sd_writeb(azx_dev, SD_CTL, azx_sd_readb(azx_dev, SD_CTL) | SD_CTL_STREAM_RESET);
+ udelay(3);
+ timeout = 300;
+ while (!((val = azx_sd_readb(azx_dev, SD_CTL)) & SD_CTL_STREAM_RESET) &&
+ --timeout)
+ ;
+ val &= ~SD_CTL_STREAM_RESET;
+ azx_sd_writeb(azx_dev, SD_CTL, val);
+ udelay(3);
+
+ timeout = 300;
+ /* waiting for hardware to report that the stream is out of reset */
+ while (((val = azx_sd_readb(azx_dev, SD_CTL)) & SD_CTL_STREAM_RESET) &&
+ --timeout)
+ ;
+
+ /* program the stream_tag */
+ azx_sd_writel(azx_dev, SD_CTL,
+ (azx_sd_readl(azx_dev, SD_CTL) & ~SD_CTL_STREAM_TAG_MASK) |
+ (azx_dev->stream_tag << SD_CTL_STREAM_TAG_SHIFT));
+
+ /* program the length of samples in cyclic buffer */
+ azx_sd_writel(azx_dev, SD_CBL, azx_dev->bufsize);
+
+ /* program the stream format */
+ /* this value needs to be the same as the one programmed */
+ azx_sd_writew(azx_dev, SD_FORMAT, azx_dev->format_val);
+
+ /* program the stream LVI (last valid index) of the BDL */
+ azx_sd_writew(azx_dev, SD_LVI, azx_dev->frags - 1);
+
+ /* program the BDL address */
+ /* lower BDL address */
+ azx_sd_writel(azx_dev, SD_BDLPL, (u32)azx_dev->bdl_addr);
+ /* upper BDL address */
+ azx_sd_writel(azx_dev, SD_BDLPU, upper_32bit(azx_dev->bdl_addr));
+
+#ifdef USE_POSBUF
+ /* enable the position buffer */
+ if (! (azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE))
+ azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr | ICH6_DPLBASE_ENABLE);
+#endif
+ /* set the interrupt enable bits in the descriptor control register */
+ azx_sd_writel(azx_dev, SD_CTL, azx_sd_readl(azx_dev, SD_CTL) | SD_INT_MASK);
+
+ return 0;
+}
+
+
+/*
+ * Codec initialization
+ */
+
+static int __devinit azx_codec_create(azx_t *chip, const char *model)
+{
+ struct hda_bus_template bus_temp;
+ int c, codecs, err;
+
+ memset(&bus_temp, 0, sizeof(bus_temp));
+ bus_temp.private_data = chip;
+ bus_temp.modelname = model;
+ bus_temp.pci = chip->pci;
+ bus_temp.ops.command = azx_send_cmd;
+ bus_temp.ops.get_response = azx_get_response;
+
+ if ((err = snd_hda_bus_new(chip->card, &bus_temp, &chip->bus)) < 0)
+ return err;
+
+ codecs = 0;
+ for (c = 0; c < AZX_MAX_CODECS; c++) {
+ if (chip->codec_mask & (1 << c)) {
+ err = snd_hda_codec_new(chip->bus, c, NULL);
+ if (err < 0)
+ continue;
+ codecs++;
+ }
+ }
+ if (! codecs) {
+ snd_printk(KERN_ERR SFX "no codecs initialized\n");
+ return -ENXIO;
+ }
+
+ return 0;
+}
+
+
+/*
+ * PCM support
+ */
+
+/* assign a stream for the PCM */
+static inline azx_dev_t *azx_assign_device(azx_t *chip, int stream)
+{
+ int dev, i;
+ dev = stream == SNDRV_PCM_STREAM_PLAYBACK ? 4 : 0;
+ for (i = 0; i < 4; i++, dev++)
+ if (! chip->azx_dev[dev].opened) {
+ chip->azx_dev[dev].opened = 1;
+ return &chip->azx_dev[dev];
+ }
+ return NULL;
+}
+
+/* release the assigned stream */
+static inline void azx_release_device(azx_dev_t *azx_dev)
+{
+ azx_dev->opened = 0;
+}
+
+static snd_pcm_hardware_t azx_pcm_hw = {
+ .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_BLOCK_TRANSFER |
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_PAUSE |
+ SNDRV_PCM_INFO_RESUME),
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .rates = SNDRV_PCM_RATE_48000,
+ .rate_min = 48000,
+ .rate_max = 48000,
+ .channels_min = 2,
+ .channels_max = 2,
+ .buffer_bytes_max = AZX_MAX_BUF_SIZE,
+ .period_bytes_min = 128,
+ .period_bytes_max = AZX_MAX_BUF_SIZE / 2,
+ .periods_min = 2,
+ .periods_max = AZX_MAX_FRAG,
+ .fifo_size = 0,
+};
+
+struct azx_pcm {
+ azx_t *chip;
+ struct hda_codec *codec;
+ struct hda_pcm_stream *hinfo[2];
+};
+
+static int azx_pcm_open(snd_pcm_substream_t *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;
+ unsigned long flags;
+ int err;
+
+ down(&chip->open_mutex);
+ azx_dev = azx_assign_device(chip, substream->stream);
+ if (azx_dev == NULL) {
+ up(&chip->open_mutex);
+ return -EBUSY;
+ }
+ runtime->hw = azx_pcm_hw;
+ runtime->hw.channels_min = hinfo->channels_min;
+ runtime->hw.channels_max = hinfo->channels_max;
+ runtime->hw.formats = hinfo->formats;
+ runtime->hw.rates = hinfo->rates;
+ snd_pcm_limit_hw_rates(runtime);
+ snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
+ if ((err = hinfo->ops.open(hinfo, apcm->codec, substream)) < 0) {
+ azx_release_device(azx_dev);
+ up(&chip->open_mutex);
+ return err;
+ }
+ spin_lock_irqsave(&chip->reg_lock, flags);
+ azx_dev->substream = substream;
+ azx_dev->running = 0;
+ spin_unlock_irqrestore(&chip->reg_lock, flags);
+
+ runtime->private_data = azx_dev;
+ up(&chip->open_mutex);
+ return 0;
+}
+
+static int azx_pcm_close(snd_pcm_substream_t *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);
+ unsigned long flags;
+
+ down(&chip->open_mutex);
+ spin_lock_irqsave(&chip->reg_lock, flags);
+ azx_dev->substream = NULL;
+ azx_dev->running = 0;
+ spin_unlock_irqrestore(&chip->reg_lock, flags);
+ azx_release_device(azx_dev);
+ hinfo->ops.close(hinfo, apcm->codec, substream);
+ up(&chip->open_mutex);
+ return 0;
+}
+
+static int azx_pcm_hw_params(snd_pcm_substream_t *substream, snd_pcm_hw_params_t *hw_params)
+{
+ return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
+}
+
+static int azx_pcm_hw_free(snd_pcm_substream_t *substream)
+{
+ struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
+ azx_dev_t *azx_dev = get_azx_dev(substream);
+ struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream];
+
+ /* reset BDL address */
+ azx_sd_writel(azx_dev, SD_BDLPL, 0);
+ azx_sd_writel(azx_dev, SD_BDLPU, 0);
+ azx_sd_writel(azx_dev, SD_CTL, 0);
+
+ hinfo->ops.cleanup(hinfo, apcm->codec, substream);
+
+ return snd_pcm_lib_free_pages(substream);
+}
+
+static int azx_pcm_prepare(snd_pcm_substream_t *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 hda_pcm_stream *hinfo = apcm->hinfo[substream->stream];
+ snd_pcm_runtime_t *runtime = substream->runtime;
+
+ azx_dev->bufsize = snd_pcm_lib_buffer_bytes(substream);
+ azx_dev->fragsize = snd_pcm_lib_period_bytes(substream);
+ azx_dev->frags = azx_dev->bufsize / azx_dev->fragsize;
+ azx_dev->format_val = snd_hda_calc_stream_format(runtime->rate,
+ runtime->channels,
+ runtime->format,
+ hinfo->maxbps);
+ if (! azx_dev->format_val) {
+ snd_printk(KERN_ERR SFX "invalid format_val, rate=%d, ch=%d, format=%d\n",
+ runtime->rate, runtime->channels, runtime->format);
+ return -EINVAL;
+ }
+
+ snd_printdd("azx_pcm_prepare: bufsize=0x%x, fragsize=0x%x, format=0x%x\n",
+ azx_dev->bufsize, azx_dev->fragsize, azx_dev->format_val);
+ azx_setup_periods(azx_dev);
+ azx_setup_controller(chip, azx_dev);
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ azx_dev->fifo_size = azx_sd_readw(azx_dev, SD_FIFOSIZE) + 1;
+ else
+ azx_dev->fifo_size = 0;
+
+ return hinfo->ops.prepare(hinfo, apcm->codec, azx_dev->stream_tag,
+ azx_dev->format_val, substream);
+}
+
+static int azx_pcm_trigger(snd_pcm_substream_t *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;
+ int err = 0;
+
+ spin_lock(&chip->reg_lock);
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_START:
+ azx_stream_start(chip, azx_dev);
+ azx_dev->running = 1;
+ break;
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ case SNDRV_PCM_TRIGGER_STOP:
+ azx_stream_stop(chip, azx_dev);
+ azx_dev->running = 0;
+ break;
+ default:
+ err = -EINVAL;
+ }
+ spin_unlock(&chip->reg_lock);
+ if (cmd == SNDRV_PCM_TRIGGER_PAUSE_PUSH ||
+ cmd == SNDRV_PCM_TRIGGER_STOP) {
+ int timeout = 5000;
+ while (azx_sd_readb(azx_dev, SD_CTL) & SD_CTL_DMA_START && --timeout)
+ ;
+ }
+ return err;
+}
+
+static snd_pcm_uframes_t azx_pcm_pointer(snd_pcm_substream_t *substream)
+{
+ azx_dev_t *azx_dev = get_azx_dev(substream);
+ unsigned int pos;
+
+#ifdef USE_POSBUF
+ /* use the position buffer */
+ pos = *azx_dev->posbuf;
+#else
+ /* read LPIB */
+ pos = azx_sd_readl(azx_dev, SD_LPIB) + 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 = {
+ .open = azx_pcm_open,
+ .close = azx_pcm_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = azx_pcm_hw_params,
+ .hw_free = azx_pcm_hw_free,
+ .prepare = azx_pcm_prepare,
+ .trigger = azx_pcm_trigger,
+ .pointer = azx_pcm_pointer,
+};
+
+static void azx_pcm_free(snd_pcm_t *pcm)
+{
+ kfree(pcm->private_data);
+}
+
+static int __devinit create_codec_pcm(azx_t *chip, struct hda_codec *codec,
+ struct hda_pcm *cpcm, int pcm_dev)
+{
+ int err;
+ snd_pcm_t *pcm;
+ struct azx_pcm *apcm;
+
+ snd_assert(cpcm->stream[0].substreams || cpcm->stream[1].substreams, return -EINVAL);
+ snd_assert(cpcm->name, return -EINVAL);
+
+ err = snd_pcm_new(chip->card, cpcm->name, pcm_dev,
+ cpcm->stream[0].substreams, cpcm->stream[1].substreams,
+ &pcm);
+ if (err < 0)
+ return err;
+ strcpy(pcm->name, cpcm->name);
+ apcm = kmalloc(sizeof(*apcm), GFP_KERNEL);
+ if (apcm == NULL)
+ return -ENOMEM;
+ apcm->chip = chip;
+ apcm->codec = codec;
+ apcm->hinfo[0] = &cpcm->stream[0];
+ apcm->hinfo[1] = &cpcm->stream[1];
+ pcm->private_data = apcm;
+ pcm->private_free = azx_pcm_free;
+ if (cpcm->stream[0].substreams)
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &azx_pcm_ops);
+ if (cpcm->stream[1].substreams)
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &azx_pcm_ops);
+ snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
+ snd_dma_pci_data(chip->pci),
+ 1024 * 64, 1024 * 128);
+ chip->pcm[pcm_dev] = pcm;
+
+ return 0;
+}
+
+static int __devinit azx_pcm_create(azx_t *chip)
+{
+ struct list_head *p;
+ struct hda_codec *codec;
+ int c, err;
+ int pcm_dev;
+
+ if ((err = snd_hda_build_pcms(chip->bus)) < 0)
+ return err;
+
+ pcm_dev = 0;
+ list_for_each(p, &chip->bus->codec_list) {
+ codec = list_entry(p, struct hda_codec, list);
+ for (c = 0; c < codec->num_pcms; c++) {
+ if (pcm_dev >= AZX_MAX_PCMS) {
+ snd_printk(KERN_ERR SFX "Too many PCMs\n");
+ return -EINVAL;
+ }
+ err = create_codec_pcm(chip, codec, &codec->pcm_info[c], pcm_dev);
+ if (err < 0)
+ return err;
+ pcm_dev++;
+ }
+ }
+ return 0;
+}
+
+/*
+ * mixer creation - all stuff is implemented in hda module
+ */
+static int __devinit azx_mixer_create(azx_t *chip)
+{
+ return snd_hda_build_controls(chip->bus);
+}
+
+
+/*
+ * initialize SD streams
+ */
+static int __devinit azx_init_stream(azx_t *chip)
+{
+ int i;
+
+ /* initialize each stream (aka device)
+ * assign the starting bdl address to each stream (device) and initialize
+ */
+ for (i = 0; i < MAX_ICH6_DEV; i++) {
+ unsigned int off = sizeof(u32) * (i * AZX_MAX_FRAG * 4);
+ azx_dev_t *azx_dev = &chip->azx_dev[i];
+ azx_dev->bdl = (u32 *)(chip->bdl.area + off);
+ azx_dev->bdl_addr = chip->bdl.addr + off;
+#ifdef USE_POSBUF
+ azx_dev->posbuf = (volatile u32 *)(chip->posbuf.area + i * 8);
+#endif
+ /* offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */
+ azx_dev->sd_addr = chip->remap_addr + (0x20 * i + 0x80);
+ /* int mask: SDI0=0x01, SDI1=0x02, ... SDO3=0x80 */
+ azx_dev->sd_int_sta_mask = 1 << i;
+ /* stream tag: must be non-zero and unique */
+ azx_dev->index = i;
+ azx_dev->stream_tag = i + 1;
+ }
+
+ return 0;
+}
+
+
+#ifdef CONFIG_PM
+/*
+ * power management
+ */
+static int azx_suspend(snd_card_t *card, pm_message_t state)
+{
+ azx_t *chip = card->pm_private_data;
+ int i;
+
+ for (i = 0; i < chip->pcm_devs; i++)
+ if (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);
+ return 0;
+}
+
+static int azx_resume(snd_card_t *card)
+{
+ azx_t *chip = card->pm_private_data;
+
+ pci_enable_device(chip->pci);
+ pci_set_master(chip->pci);
+ azx_init_chip(chip);
+ snd_hda_resume(chip->bus);
+ return 0;
+}
+#endif /* CONFIG_PM */
+
+
+/*
+ * destructor
+ */
+static int azx_free(azx_t *chip)
+{
+ if (chip->remap_addr) {
+ int i;
+
+ for (i = 0; i < MAX_ICH6_DEV; i++)
+ azx_stream_stop(chip, &chip->azx_dev[i]);
+
+ /* disable interrupts */
+ azx_int_disable(chip);
+ azx_int_clear(chip);
+
+ /* disable CORB/RIRB */
+ azx_free_cmd_io(chip);
+
+ /* disable position buffer */
+ azx_writel(chip, DPLBASE, 0);
+ azx_writel(chip, DPUBASE, 0);
+
+ /* wait a little for interrupts to finish */
+ msleep(1);
+
+ iounmap(chip->remap_addr);
+ }
+
+ if (chip->irq >= 0)
+ free_irq(chip->irq, (void*)chip);
+
+ if (chip->bdl.area)
+ snd_dma_free_pages(&chip->bdl);
+ if (chip->rb.area)
+ snd_dma_free_pages(&chip->rb);
+#ifdef USE_POSBUF
+ if (chip->posbuf.area)
+ snd_dma_free_pages(&chip->posbuf);
+#endif
+ pci_release_regions(chip->pci);
+ pci_disable_device(chip->pci);
+ kfree(chip);
+
+ return 0;
+}
+
+static int azx_dev_free(snd_device_t *device)
+{
+ return azx_free(device->device_data);
+}
+
+/*
+ * constructor
+ */
+static int __devinit azx_create(snd_card_t *card, struct pci_dev *pci, azx_t **rchip)
+{
+ azx_t *chip;
+ int err = 0;
+ static snd_device_ops_t ops = {
+ .dev_free = azx_dev_free,
+ };
+
+ *rchip = NULL;
+
+ if ((err = pci_enable_device(pci)) < 0)
+ return err;
+
+ chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+
+ if (NULL == chip) {
+ snd_printk(KERN_ERR SFX "cannot allocate chip\n");
+ pci_disable_device(pci);
+ return -ENOMEM;
+ }
+
+ spin_lock_init(&chip->reg_lock);
+ init_MUTEX(&chip->open_mutex);
+ chip->card = card;
+ chip->pci = pci;
+ chip->irq = -1;
+
+ if ((err = pci_request_regions(pci, "ICH HD audio")) < 0) {
+ kfree(chip);
+ pci_disable_device(pci);
+ return err;
+ }
+
+ chip->addr = pci_resource_start(pci,0);
+ chip->remap_addr = ioremap_nocache(chip->addr, pci_resource_len(pci,0));
+ if (chip->remap_addr == NULL) {
+ snd_printk(KERN_ERR SFX "ioremap error\n");
+ err = -ENXIO;
+ goto errout;
+ }
+
+ if (request_irq(pci->irq, azx_interrupt, SA_INTERRUPT|SA_SHIRQ,
+ "HDA Intel", (void*)chip)) {
+ snd_printk(KERN_ERR SFX "unable to grab IRQ %d\n", pci->irq);
+ err = -EBUSY;
+ goto errout;
+ }
+ chip->irq = pci->irq;
+
+ pci_set_master(pci);
+ synchronize_irq(chip->irq);
+
+ /* allocate memory for the BDL for each stream */
+ if ((err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
+ PAGE_SIZE, &chip->bdl)) < 0) {
+ snd_printk(KERN_ERR SFX "cannot allocate BDL\n");
+ goto errout;
+ }
+#ifdef USE_POSBUF
+ /* allocate memory for the position buffer */
+ if ((err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
+ MAX_ICH6_DEV * 8, &chip->posbuf)) < 0) {
+ snd_printk(KERN_ERR SFX "cannot allocate posbuf\n");
+ goto errout;
+ }
+#endif
+ /* allocate CORB/RIRB */
+ if ((err = azx_alloc_cmd_io(chip)) < 0)
+ goto errout;
+
+ /* initialize streams */
+ azx_init_stream(chip);
+
+ /* initialize chip */
+ azx_init_chip(chip);
+
+ /* codec detection */
+ if (! chip->codec_mask) {
+ snd_printk(KERN_ERR SFX "no codecs found!\n");
+ err = -ENODEV;
+ goto errout;
+ }
+
+ if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) <0) {
+ snd_printk(KERN_ERR SFX "Error creating device [card]!\n");
+ goto errout;
+ }
+
+ *rchip = chip;
+ return 0;
+
+ errout:
+ azx_free(chip);
+ return err;
+}
+
+static int __devinit azx_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
+{
+ static int dev;
+ snd_card_t *card;
+ azx_t *chip;
+ int err = 0;
+
+ if (dev >= SNDRV_CARDS)
+ return -ENODEV;
+ if (! enable[dev]) {
+ dev++;
+ return -ENOENT;
+ }
+
+ card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
+ if (NULL == card) {
+ snd_printk(KERN_ERR SFX "Error creating card!\n");
+ return -ENOMEM;
+ }
+
+ if ((err = azx_create(card, pci, &chip)) < 0) {
+ snd_card_free(card);
+ return err;
+ }
+
+ strcpy(card->driver, "HDA-Intel");
+ strcpy(card->shortname, "HDA Intel");
+ sprintf(card->longname, "%s at 0x%lx irq %i", card->shortname, chip->addr, chip->irq);
+
+ /* create codec instances */
+ if ((err = azx_codec_create(chip, model[dev])) < 0) {
+ snd_card_free(card);
+ return err;
+ }
+
+ /* create PCM streams */
+ if ((err = azx_pcm_create(chip)) < 0) {
+ snd_card_free(card);
+ return err;
+ }
+
+ /* create mixer controls */
+ if ((err = azx_mixer_create(chip)) < 0) {
+ snd_card_free(card);
+ 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) {
+ snd_card_free(card);
+ return err;
+ }
+
+ pci_set_drvdata(pci, card);
+ dev++;
+
+ return err;
+}
+
+static void __devexit azx_remove(struct pci_dev *pci)
+{
+ snd_card_free(pci_get_drvdata(pci));
+ pci_set_drvdata(pci, NULL);
+}
+
+/* PCI IDs */
+static struct pci_device_id azx_ids[] = {
+ { 0x8086, 0x2668, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ICH6 */
+ { 0x8086, 0x27d8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ICH7 */
+ { 0, }
+};
+MODULE_DEVICE_TABLE(pci, azx_ids);
+
+/* pci_driver definition */
+static struct pci_driver driver = {
+ .name = "HDA Intel",
+ .id_table = azx_ids,
+ .probe = azx_probe,
+ .remove = __devexit_p(azx_remove),
+ SND_PCI_PM_CALLBACKS
+};
+
+static int __init alsa_card_azx_init(void)
+{
+ return pci_module_init(&driver);
+}
+
+static void __exit alsa_card_azx_exit(void)
+{
+ pci_unregister_driver(&driver);
+}
+
+module_init(alsa_card_azx_init)
+module_exit(alsa_card_azx_exit)
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h
new file mode 100644
index 0000000000000..7c7b849875a00
--- /dev/null
+++ b/sound/pci/hda/hda_local.h
@@ -0,0 +1,161 @@
+/*
+ * Universal Interface for Intel High Definition Audio Codec
+ *
+ * Local helper functions
+ *
+ * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __SOUND_HDA_LOCAL_H
+#define __SOUND_HDA_LOCAL_H
+
+/*
+ * for mixer controls
+ */
+#define HDA_COMPOSE_AMP_VAL(nid,chs,idx,dir) ((nid) | ((chs)<<16) | ((dir)<<18) | ((idx)<<19))
+#define HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \
+ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \
+ .info = snd_hda_mixer_amp_volume_info, \
+ .get = snd_hda_mixer_amp_volume_get, \
+ .put = snd_hda_mixer_amp_volume_put, \
+ .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, xindex, direction) }
+#define HDA_CODEC_VOLUME_IDX(xname, xcidx, nid, xindex, direction) \
+ HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, 3, xindex, direction)
+#define HDA_CODEC_VOLUME_MONO(xname, nid, channel, xindex, direction) \
+ HDA_CODEC_VOLUME_MONO_IDX(xname, 0, nid, channel, xindex, direction)
+#define HDA_CODEC_VOLUME(xname, nid, xindex, direction) \
+ HDA_CODEC_VOLUME_MONO(xname, nid, 3, xindex, direction)
+#define HDA_CODEC_MUTE_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \
+ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \
+ .info = snd_hda_mixer_amp_switch_info, \
+ .get = snd_hda_mixer_amp_switch_get, \
+ .put = snd_hda_mixer_amp_switch_put, \
+ .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, xindex, direction) }
+#define HDA_CODEC_MUTE_IDX(xname, xcidx, nid, xindex, direction) \
+ HDA_CODEC_MUTE_MONO_IDX(xname, xcidx, nid, 3, xindex, direction)
+#define HDA_CODEC_MUTE_MONO(xname, nid, channel, xindex, direction) \
+ HDA_CODEC_MUTE_MONO_IDX(xname, 0, nid, channel, xindex, direction)
+#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_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);
+
+/*
+ * input MUX helper
+ */
+#define HDA_MAX_NUM_INPUTS 8
+struct hda_input_mux_item {
+ const char *label;
+ unsigned int index;
+};
+struct hda_input_mux {
+ unsigned int num_items;
+ 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_put(struct hda_codec *codec, const struct hda_input_mux *imux,
+ snd_ctl_elem_value_t *ucontrol, hda_nid_t nid,
+ unsigned int *cur_val);
+
+/*
+ * Multi-channel / digital-out PCM helper
+ */
+
+enum { HDA_FRONT, HDA_REAR, HDA_CLFE, HDA_SIDE }; /* index for dac_nidx */
+enum { HDA_DIG_NONE, HDA_DIG_EXCLUSIVE, HDA_DIG_ANALOG_DUP }; /* dig_out_used */
+
+struct hda_multi_out {
+ int num_dacs; /* # of DACs, must be more than 1 */
+ hda_nid_t *dac_nids; /* DAC list */
+ hda_nid_t hp_nid; /* optional DAC for HP, 0 when not exists */
+ hda_nid_t dig_out_nid; /* digital out audio widget */
+ int max_channels; /* currently supported analog channels */
+ int dig_out_used; /* current usage of digital out (HDA_DIG_XXX) */
+};
+
+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);
+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);
+int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec, struct hda_multi_out *mout);
+
+/*
+ * generic codec parser
+ */
+int snd_hda_parse_generic_codec(struct hda_codec *codec);
+
+/*
+ * generic proc interface
+ */
+#ifdef CONFIG_PROC_FS
+int snd_hda_codec_proc_new(struct hda_codec *codec);
+#else
+static inline int snd_hda_codec_proc_new(struct hda_codec *codec) { return 0; }
+#endif
+
+/*
+ * Misc
+ */
+struct hda_board_config {
+ const char *modelname;
+ int config;
+ unsigned short pci_vendor;
+ unsigned short pci_device;
+};
+
+int snd_hda_check_board_config(struct hda_codec *codec, struct hda_board_config *tbl);
+int snd_hda_add_new_ctls(struct hda_codec *codec, snd_kcontrol_new_t *knew);
+
+/*
+ * power management
+ */
+#ifdef CONFIG_PM
+int snd_hda_resume_ctls(struct hda_codec *codec, snd_kcontrol_new_t *knew);
+int snd_hda_resume_spdif_out(struct hda_codec *codec);
+int snd_hda_resume_spdif_in(struct hda_codec *codec);
+#endif
+
+/*
+ * unsolicited event handler
+ */
+
+#define HDA_UNSOL_QUEUE_SIZE 64
+
+struct hda_bus_unsolicited {
+ /* ring buffer */
+ u32 queue[HDA_UNSOL_QUEUE_SIZE * 2];
+ unsigned int rp, wp;
+
+ /* workqueue */
+ struct workqueue_struct *workq;
+ struct work_struct work;
+};
+
+#endif /* __SOUND_HDA_LOCAL_H */
diff --git a/sound/pci/hda/hda_patch.h b/sound/pci/hda/hda_patch.h
new file mode 100644
index 0000000000000..cf6abce42bc9e
--- /dev/null
+++ b/sound/pci/hda/hda_patch.h
@@ -0,0 +1,17 @@
+/*
+ * HDA Patches - included by hda_codec.c
+ */
+
+/* Realtek codecs */
+extern struct hda_codec_preset snd_hda_preset_realtek[];
+/* C-Media codecs */
+extern struct hda_codec_preset snd_hda_preset_cmedia[];
+/* Analog Devices codecs */
+extern struct hda_codec_preset snd_hda_preset_analog[];
+
+static const struct hda_codec_preset *hda_preset_tables[] = {
+ snd_hda_preset_realtek,
+ snd_hda_preset_cmedia,
+ snd_hda_preset_analog,
+ NULL
+};
diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c
new file mode 100644
index 0000000000000..4d5db7faad8d9
--- /dev/null
+++ b/sound/pci/hda/hda_proc.c
@@ -0,0 +1,298 @@
+/*
+ * Universal Interface for Intel High Definition Audio Codec
+ *
+ * Generic proc interface
+ *
+ * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
+ *
+ *
+ * This driver is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This driver is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <sound/driver.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <sound/core.h>
+#include "hda_codec.h"
+
+static const char *get_wid_type_name(unsigned int wid_value)
+{
+ static char *names[16] = {
+ [AC_WID_AUD_OUT] = "Audio Output",
+ [AC_WID_AUD_IN] = "Audio Input",
+ [AC_WID_AUD_MIX] = "Audio Mixer",
+ [AC_WID_AUD_SEL] = "Audio Selector",
+ [AC_WID_PIN] = "Pin Complex",
+ [AC_WID_POWER] = "Power Widget",
+ [AC_WID_VOL_KNB] = "Volume Knob Widget",
+ [AC_WID_BEEP] = "Beep Generator Widget",
+ [AC_WID_VENDOR] = "Vendor Defined Widget",
+ };
+ wid_value &= 0xf;
+ if (names[wid_value])
+ return names[wid_value];
+ else
+ return "UNKOWN Widget";
+}
+
+static void print_amp_caps(snd_info_buffer_t *buffer,
+ struct hda_codec *codec, hda_nid_t nid, int dir)
+{
+ unsigned int caps;
+ if (dir == HDA_OUTPUT)
+ caps = snd_hda_param_read(codec, nid, AC_PAR_AMP_OUT_CAP);
+ else
+ caps = snd_hda_param_read(codec, nid, AC_PAR_AMP_IN_CAP);
+ if (caps == -1 || caps == 0) {
+ snd_iprintf(buffer, "N/A\n");
+ return;
+ }
+ snd_iprintf(buffer, "ofs=0x%02x, nsteps=0x%02x, stepsize=0x%02x, mute=%x\n",
+ caps & AC_AMPCAP_OFFSET,
+ (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT,
+ (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT,
+ (caps & AC_AMPCAP_MUTE) >> AC_AMPCAP_MUTE_SHIFT);
+}
+
+static void print_amp_vals(snd_info_buffer_t *buffer,
+ struct hda_codec *codec, hda_nid_t nid,
+ int dir, int stereo)
+{
+ unsigned int val;
+ if (stereo) {
+ val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_AMP_GAIN_MUTE,
+ AC_AMP_GET_LEFT |
+ (dir == HDA_OUTPUT ? AC_AMP_GET_OUTPUT :
+ AC_AMP_GET_INPUT));
+ snd_iprintf(buffer, "0x%02x ", val);
+ }
+ val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_AMP_GAIN_MUTE,
+ AC_AMP_GET_RIGHT |
+ (dir == HDA_OUTPUT ? AC_AMP_GET_OUTPUT :
+ AC_AMP_GET_INPUT));
+ snd_iprintf(buffer, "0x%02x\n", val);
+}
+
+static void print_pcm_caps(snd_info_buffer_t *buffer,
+ struct hda_codec *codec, hda_nid_t nid)
+{
+ unsigned int pcm = snd_hda_param_read(codec, nid, AC_PAR_PCM);
+ unsigned int stream = snd_hda_param_read(codec, nid, AC_PAR_STREAM);
+ if (pcm == -1 || stream == -1) {
+ snd_iprintf(buffer, "N/A\n");
+ return;
+ }
+ snd_iprintf(buffer, "rates 0x%03x, bits 0x%02x, types 0x%x\n",
+ pcm & AC_SUPPCM_RATES, (pcm >> 16) & 0xff, stream & 0xf);
+}
+
+static const char *get_jack_location(u32 cfg)
+{
+ static char *bases[7] = {
+ "N/A", "Rear", "Front", "Left", "Right", "Top", "Bottom",
+ };
+ static unsigned char specials_idx[] = {
+ 0x07, 0x08,
+ 0x17, 0x18, 0x19,
+ 0x37, 0x38
+ };
+ static char *specials[] = {
+ "Rear Panel", "Drive Bar",
+ "Riser", "HDMI", "ATAPI",
+ "Mobile-In", "Mobile-Out"
+ };
+ int i;
+ cfg = (cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT;
+ if ((cfg & 0x0f) < 7)
+ return bases[cfg & 0x0f];
+ for (i = 0; i < ARRAY_SIZE(specials_idx); i++) {
+ if (cfg == specials_idx[i])
+ return specials[i];
+ }
+ return "UNKNOWN";
+}
+
+static const char *get_jack_connection(u32 cfg)
+{
+ static char *names[16] = {
+ "Unknown", "1/8", "1/4", "ATAPI",
+ "RCA", "Optical","Digital", "Analog",
+ "DIN", "XLR", "RJ11", "Comb",
+ NULL, NULL, NULL, "Other"
+ };
+ cfg = (cfg & AC_DEFCFG_CONN_TYPE) >> AC_DEFCFG_CONN_TYPE_SHIFT;
+ if (names[cfg])
+ return names[cfg];
+ else
+ return "UNKNOWN";
+}
+
+static const char *get_jack_color(u32 cfg)
+{
+ static char *names[16] = {
+ "Unknown", "Black", "Grey", "Blue",
+ "Green", "Red", "Orange", "Yellow",
+ "Purple", "Pink", NULL, NULL,
+ NULL, NULL, "White", "Other",
+ };
+ cfg = (cfg & AC_DEFCFG_COLOR) >> AC_DEFCFG_COLOR_SHIFT;
+ if (names[cfg])
+ return names[cfg];
+ else
+ return "UNKNOWN";
+}
+
+static void print_pin_caps(snd_info_buffer_t *buffer,
+ struct hda_codec *codec, hda_nid_t nid)
+{
+ static char *jack_types[16] = {
+ "Line Out", "Speaker", "HP Out", "CD",
+ "SPDIF Out", "Digital Out", "Modem Line", "Modem Hand",
+ "Line In", "Aux", "Mic", "Telephony",
+ "SPDIF In", "Digitial In", "Reserved", "Other"
+ };
+ static char *jack_locations[4] = { "Ext", "Int", "Sep", "Oth" };
+ unsigned int caps;
+
+ caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
+ snd_iprintf(buffer, " Pincap 0x08%x:", caps);
+ if (caps & AC_PINCAP_IN)
+ snd_iprintf(buffer, " IN");
+ if (caps & AC_PINCAP_OUT)
+ snd_iprintf(buffer, " OUT");
+ if (caps & AC_PINCAP_HP_DRV)
+ snd_iprintf(buffer, " HP");
+ snd_iprintf(buffer, "\n");
+ caps = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
+ snd_iprintf(buffer, " Pin Default 0x%08x: %s at %s %s\n", caps,
+ jack_types[(caps & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT],
+ jack_locations[(caps >> (AC_DEFCFG_LOCATION_SHIFT + 4)) & 3],
+ get_jack_location(caps));
+ snd_iprintf(buffer, " Conn = %s, Color = %s\n",
+ get_jack_connection(caps),
+ get_jack_color(caps));
+}
+
+
+static void print_codec_info(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
+{
+ struct hda_codec *codec = entry->private_data;
+ char buf[32];
+ hda_nid_t nid;
+ int i, nodes;
+
+ snd_hda_get_codec_name(codec, buf, sizeof(buf));
+ snd_iprintf(buffer, "Codec: %s\n", buf);
+ snd_iprintf(buffer, "Address: %d\n", codec->addr);
+ snd_iprintf(buffer, "Vendor Id: 0x%x\n", codec->vendor_id);
+ snd_iprintf(buffer, "Subsystem Id: 0x%x\n", codec->subsystem_id);
+ snd_iprintf(buffer, "Revision Id: 0x%x\n", codec->revision_id);
+ snd_iprintf(buffer, "Default PCM: ");
+ print_pcm_caps(buffer, codec, codec->afg);
+ snd_iprintf(buffer, "Default Amp-In caps: ");
+ print_amp_caps(buffer, codec, codec->afg, HDA_INPUT);
+ snd_iprintf(buffer, "Default Amp-Out caps: ");
+ print_amp_caps(buffer, codec, codec->afg, HDA_OUTPUT);
+
+ nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid);
+ if (! nid || nodes < 0) {
+ snd_iprintf(buffer, "Invalid AFG subtree\n");
+ return;
+ }
+ for (i = 0; i < nodes; i++, nid++) {
+ unsigned int wid_caps = snd_hda_param_read(codec, nid,
+ AC_PAR_AUDIO_WIDGET_CAP);
+ unsigned int wid_type = (wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
+ snd_iprintf(buffer, "Node 0x%02x [%s] wcaps 0x%x:", nid,
+ get_wid_type_name(wid_type), wid_caps);
+ if (wid_caps & AC_WCAP_STEREO)
+ snd_iprintf(buffer, " Stereo");
+ else
+ snd_iprintf(buffer, " Mono");
+ if (wid_caps & AC_WCAP_DIGITAL)
+ snd_iprintf(buffer, " Digital");
+ if (wid_caps & AC_WCAP_IN_AMP)
+ snd_iprintf(buffer, " Amp-In");
+ if (wid_caps & AC_WCAP_OUT_AMP)
+ snd_iprintf(buffer, " Amp-Out");
+ snd_iprintf(buffer, "\n");
+
+ if (wid_caps & AC_WCAP_IN_AMP) {
+ snd_iprintf(buffer, " Amp-In caps: ");
+ print_amp_caps(buffer, codec, nid, HDA_INPUT);
+ snd_iprintf(buffer, " Amp-In vals: ");
+ print_amp_vals(buffer, codec, nid, HDA_INPUT,
+ wid_caps & AC_WCAP_STEREO);
+ }
+ if (wid_caps & AC_WCAP_OUT_AMP) {
+ snd_iprintf(buffer, " Amp-Out caps: ");
+ print_amp_caps(buffer, codec, nid, HDA_OUTPUT);
+ snd_iprintf(buffer, " Amp-Out vals: ");
+ print_amp_vals(buffer, codec, nid, HDA_OUTPUT,
+ wid_caps & AC_WCAP_STEREO);
+ }
+
+ if (wid_type == AC_WID_PIN) {
+ unsigned int pinctls;
+ print_pin_caps(buffer, codec, nid);
+ pinctls = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
+ snd_iprintf(buffer, " Pin-ctls: 0x%02x:", pinctls);
+ if (pinctls & AC_PINCTL_IN_EN)
+ snd_iprintf(buffer, " IN");
+ if (pinctls & AC_PINCTL_OUT_EN)
+ snd_iprintf(buffer, " OUT");
+ if (pinctls & AC_PINCTL_HP_EN)
+ snd_iprintf(buffer, " HP");
+ snd_iprintf(buffer, "\n");
+ }
+
+ if ((wid_type == AC_WID_AUD_OUT || wid_type == AC_WID_AUD_IN) &&
+ (wid_caps & AC_WCAP_FORMAT_OVRD)) {
+ snd_iprintf(buffer, " PCM: ");
+ print_pcm_caps(buffer, codec, nid);
+ }
+
+ if (wid_caps & AC_WCAP_CONN_LIST) {
+ hda_nid_t conn[HDA_MAX_CONNECTIONS];
+ int c, conn_len;
+ conn_len = snd_hda_get_connections(codec, nid, conn,
+ HDA_MAX_CONNECTIONS);
+ snd_iprintf(buffer, " Connection: %d\n", conn_len);
+ snd_iprintf(buffer, " ");
+ for (c = 0; c < conn_len; c++)
+ snd_iprintf(buffer, " 0x%02x", conn[c]);
+ snd_iprintf(buffer, "\n");
+ }
+ }
+}
+
+/*
+ * create a proc read
+ */
+int snd_hda_codec_proc_new(struct hda_codec *codec)
+{
+ char name[32];
+ snd_info_entry_t *entry;
+ int err;
+
+ snprintf(name, sizeof(name), "codec#%d", codec->addr);
+ err = snd_card_proc_new(codec->bus->card, name, &entry);
+ if (err < 0)
+ return err;
+
+ snd_info_set_text_ops(entry, codec, 32 * 1024, print_codec_info);
+ return 0;
+}
+
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
new file mode 100644
index 0000000000000..75d23849f71ac
--- /dev/null
+++ b/sound/pci/hda/patch_analog.c
@@ -0,0 +1,445 @@
+/*
+ * HD audio interface patch for AD1986A
+ *
+ * Copyright (c) 2005 Takashi Iwai <tiwai@suse.de>
+ *
+ * This driver is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This driver is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <sound/driver.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <sound/core.h>
+#include "hda_codec.h"
+#include "hda_local.h"
+
+struct ad1986a_spec {
+ struct semaphore amp_mutex; /* PCM volume/mute control mutex */
+ struct hda_multi_out multiout; /* playback */
+ unsigned int cur_mux; /* capture source */
+ struct hda_pcm pcm_rec[2]; /* PCM information */
+};
+
+#define AD1986A_SPDIF_OUT 0x02
+#define AD1986A_FRONT_DAC 0x03
+#define AD1986A_SURR_DAC 0x04
+#define AD1986A_CLFE_DAC 0x05
+#define AD1986A_ADC 0x06
+
+static hda_nid_t ad1986a_dac_nids[3] = {
+ AD1986A_FRONT_DAC, AD1986A_SURR_DAC, AD1986A_CLFE_DAC
+};
+
+static struct hda_input_mux ad1986a_capture_source = {
+ .num_items = 7,
+ .items = {
+ { "Mic", 0x0 },
+ { "CD", 0x1 },
+ { "Aux", 0x3 },
+ { "Line", 0x4 },
+ { "Mix", 0x5 },
+ { "Mono", 0x6 },
+ { "Phone", 0x7 },
+ },
+};
+
+/*
+ * PCM control
+ *
+ * bind volumes/mutes of 3 DACs as a single PCM control for simplicity
+ */
+
+#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)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct ad1986a_spec *ad = codec->spec;
+
+ down(&ad->amp_mutex);
+ snd_hda_mixer_amp_volume_get(kcontrol, ucontrol);
+ up(&ad->amp_mutex);
+ return 0;
+}
+
+static int ad1986a_pcm_amp_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct ad1986a_spec *ad = codec->spec;
+ int i, change = 0;
+
+ down(&ad->amp_mutex);
+ for (i = 0; i < ARRAY_SIZE(ad1986a_dac_nids); i++) {
+ kcontrol->private_value = HDA_COMPOSE_AMP_VAL(ad1986a_dac_nids[i], 3, 0, HDA_OUTPUT);
+ change |= snd_hda_mixer_amp_volume_put(kcontrol, ucontrol);
+ }
+ kcontrol->private_value = HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT);
+ up(&ad->amp_mutex);
+ return change;
+}
+
+#define ad1986a_pcm_amp_sw_info snd_hda_mixer_amp_volume_info
+
+static int ad1986a_pcm_amp_sw_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct ad1986a_spec *ad = codec->spec;
+
+ down(&ad->amp_mutex);
+ snd_hda_mixer_amp_switch_get(kcontrol, ucontrol);
+ up(&ad->amp_mutex);
+ return 0;
+}
+
+static int ad1986a_pcm_amp_sw_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct ad1986a_spec *ad = codec->spec;
+ int i, change = 0;
+
+ down(&ad->amp_mutex);
+ for (i = 0; i < ARRAY_SIZE(ad1986a_dac_nids); i++) {
+ kcontrol->private_value = HDA_COMPOSE_AMP_VAL(ad1986a_dac_nids[i], 3, 0, HDA_OUTPUT);
+ change |= snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
+ }
+ kcontrol->private_value = HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT);
+ up(&ad->amp_mutex);
+ return change;
+}
+
+/*
+ * input MUX handling
+ */
+static int ad1986a_mux_enum_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+ return snd_hda_input_mux_info(&ad1986a_capture_source, uinfo);
+}
+
+static int ad1986a_mux_enum_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct ad1986a_spec *spec = codec->spec;
+
+ ucontrol->value.enumerated.item[0] = spec->cur_mux;
+ return 0;
+}
+
+static int ad1986a_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct ad1986a_spec *spec = codec->spec;
+
+ return snd_hda_input_mux_put(codec, &ad1986a_capture_source, ucontrol,
+ AD1986A_ADC, &spec->cur_mux);
+}
+
+/*
+ * mixers
+ */
+static snd_kcontrol_new_t ad1986a_mixers[] = {
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "PCM Playback Volume",
+ .info = ad1986a_pcm_amp_vol_info,
+ .get = ad1986a_pcm_amp_vol_get,
+ .put = ad1986a_pcm_amp_vol_put,
+ .private_value = HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT)
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "PCM Playback Switch",
+ .info = ad1986a_pcm_amp_sw_info,
+ .get = ad1986a_pcm_amp_sw_get,
+ .put = ad1986a_pcm_amp_sw_put,
+ .private_value = HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT)
+ },
+ HDA_CODEC_VOLUME("Front Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Surround Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Surround Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x1d, 1, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x1d, 2, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x1d, 1, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x1d, 2, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Headphone Playback Volume", 0x1a, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Line Playback Switch", 0x17, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Aux Playback Volume", 0x16, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Aux Playback Switch", 0x16, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x18, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x18, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Capture Source",
+ .info = ad1986a_mux_enum_info,
+ .get = ad1986a_mux_enum_get,
+ .put = ad1986a_mux_enum_put,
+ },
+ HDA_CODEC_MUTE("Stereo Downmix Switch", 0x09, 0x0, HDA_OUTPUT),
+ { } /* end */
+};
+
+/*
+ * initialization verbs
+ */
+static struct hda_verb ad1986a_init_verbs[] = {
+ /* Front, Surround, CLFE DAC; mute as default */
+ {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+ {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+ {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+ /* Downmix - off */
+ {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+ /* HP, Line-Out, Surround, CLFE selectors */
+ {0x0a, AC_VERB_SET_CONNECT_SEL, 0x0},
+ {0x0b, AC_VERB_SET_CONNECT_SEL, 0x0},
+ {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
+ {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
+ /* Mono selector */
+ {0x0e, AC_VERB_SET_CONNECT_SEL, 0x0},
+ /* Mic selector: Mic 1/2 pin */
+ {0x0f, AC_VERB_SET_CONNECT_SEL, 0x0},
+ /* Line-in selector: Line-in */
+ {0x10, AC_VERB_SET_CONNECT_SEL, 0x0},
+ /* Mic 1/2 swap */
+ {0x11, AC_VERB_SET_CONNECT_SEL, 0x0},
+ /* Record selector: mic */
+ {0x12, AC_VERB_SET_CONNECT_SEL, 0x0},
+ /* Mic, Phone, CD, Aux, Line-In amp; mute as default */
+ {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+ {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+ {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+ {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+ {0x17, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+ /* PC beep */
+ {0x18, AC_VERB_SET_CONNECT_SEL, 0x0},
+ /* HP, Line-Out, Surround, CLFE, Mono pins; mute as default */
+ {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+ {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+ {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+ {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+ {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+ { } /* end */
+};
+
+
+static int ad1986a_init(struct hda_codec *codec)
+{
+ snd_hda_sequence_write(codec, ad1986a_init_verbs);
+ return 0;
+}
+
+static int ad1986a_build_controls(struct hda_codec *codec)
+{
+ int err;
+
+ err = snd_hda_add_new_ctls(codec, ad1986a_mixers);
+ if (err < 0)
+ return err;
+ err = snd_hda_create_spdif_out_ctls(codec, AD1986A_SPDIF_OUT);
+ if (err < 0)
+ return err;
+ return 0;
+}
+
+/*
+ * Analog playback callbacks
+ */
+static int ad1986a_playback_pcm_open(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ snd_pcm_substream_t *substream)
+{
+ struct ad1986a_spec *spec = codec->spec;
+ return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
+}
+
+static int ad1986a_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 ad1986a_spec *spec = codec->spec;
+ return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag,
+ format, substream);
+}
+
+static int ad1986a_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ snd_pcm_substream_t *substream)
+{
+ struct ad1986a_spec *spec = codec->spec;
+ return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
+}
+
+/*
+ * Digital out
+ */
+static int ad1986a_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ snd_pcm_substream_t *substream)
+{
+ struct ad1986a_spec *spec = codec->spec;
+ return snd_hda_multi_out_dig_open(codec, &spec->multiout);
+}
+
+static int ad1986a_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ snd_pcm_substream_t *substream)
+{
+ struct ad1986a_spec *spec = codec->spec;
+ return snd_hda_multi_out_dig_close(codec, &spec->multiout);
+}
+
+/*
+ * Analog capture
+ */
+static int ad1986a_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ unsigned int stream_tag,
+ unsigned int format,
+ snd_pcm_substream_t *substream)
+{
+ snd_hda_codec_setup_stream(codec, AD1986A_ADC, stream_tag, 0, format);
+ return 0;
+}
+
+static int ad1986a_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ snd_pcm_substream_t *substream)
+{
+ snd_hda_codec_setup_stream(codec, AD1986A_ADC, 0, 0, 0);
+ return 0;
+}
+
+
+/*
+ */
+static struct hda_pcm_stream ad1986a_pcm_analog_playback = {
+ .substreams = 1,
+ .channels_min = 2,
+ .channels_max = 6,
+ .nid = AD1986A_FRONT_DAC, /* NID to query formats and rates */
+ .ops = {
+ .open = ad1986a_playback_pcm_open,
+ .prepare = ad1986a_playback_pcm_prepare,
+ .cleanup = ad1986a_playback_pcm_cleanup
+ },
+};
+
+static struct hda_pcm_stream ad1986a_pcm_analog_capture = {
+ .substreams = 2,
+ .channels_min = 2,
+ .channels_max = 2,
+ .nid = AD1986A_ADC, /* NID to query formats and rates */
+ .ops = {
+ .prepare = ad1986a_capture_pcm_prepare,
+ .cleanup = ad1986a_capture_pcm_cleanup
+ },
+};
+
+static struct hda_pcm_stream ad1986a_pcm_digital_playback = {
+ .substreams = 1,
+ .channels_min = 2,
+ .channels_max = 2,
+ .nid = AD1986A_SPDIF_OUT,
+ .ops = {
+ .open = ad1986a_dig_playback_pcm_open,
+ .close = ad1986a_dig_playback_pcm_close
+ },
+};
+
+static int ad1986a_build_pcms(struct hda_codec *codec)
+{
+ struct ad1986a_spec *spec = codec->spec;
+ struct hda_pcm *info = spec->pcm_rec;
+
+ codec->num_pcms = 2;
+ codec->pcm_info = info;
+
+ info->name = "AD1986A Analog";
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad1986a_pcm_analog_playback;
+ info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad1986a_pcm_analog_capture;
+ info++;
+
+ info->name = "AD1986A Digital";
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad1986a_pcm_digital_playback;
+
+ return 0;
+}
+
+static void ad1986a_free(struct hda_codec *codec)
+{
+ kfree(codec->spec);
+}
+
+#ifdef CONFIG_PM
+static int ad1986a_resume(struct hda_codec *codec)
+{
+ ad1986a_init(codec);
+ snd_hda_resume_ctls(codec, ad1986a_mixers);
+ snd_hda_resume_spdif_out(codec);
+ return 0;
+}
+#endif
+
+static struct hda_codec_ops ad1986a_patch_ops = {
+ .build_controls = ad1986a_build_controls,
+ .build_pcms = ad1986a_build_pcms,
+ .init = ad1986a_init,
+ .free = ad1986a_free,
+#ifdef CONFIG_PM
+ .resume = ad1986a_resume,
+#endif
+};
+
+static int patch_ad1986a(struct hda_codec *codec)
+{
+ struct ad1986a_spec *spec;
+
+ spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
+ if (spec == NULL)
+ return -ENOMEM;
+
+ init_MUTEX(&spec->amp_mutex);
+ codec->spec = spec;
+
+ spec->multiout.max_channels = 6;
+ spec->multiout.num_dacs = ARRAY_SIZE(ad1986a_dac_nids);
+ spec->multiout.dac_nids = ad1986a_dac_nids;
+ spec->multiout.dig_out_nid = AD1986A_SPDIF_OUT;
+
+ codec->patch_ops = ad1986a_patch_ops;
+
+ return 0;
+}
+
+/*
+ * patch entries
+ */
+struct hda_codec_preset snd_hda_preset_analog[] = {
+ { .id = 0x11d41986, .name = "AD1986A", .patch = patch_ad1986a },
+ {} /* terminator */
+};
diff --git a/sound/pci/hda/patch_cmedia.c b/sound/pci/hda/patch_cmedia.c
new file mode 100644
index 0000000000000..b7cc8e4bffb7f
--- /dev/null
+++ b/sound/pci/hda/patch_cmedia.c
@@ -0,0 +1,621 @@
+/*
+ * Universal Interface for Intel High Definition Audio Codec
+ *
+ * HD audio interface patch for C-Media CMI9880
+ *
+ * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
+ *
+ *
+ * This driver is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This driver is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <sound/driver.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <sound/core.h>
+#include "hda_codec.h"
+#include "hda_local.h"
+
+
+/* board config type */
+enum {
+ CMI_MINIMAL, /* back 3-jack */
+ CMI_MIN_FP, /* back 3-jack + front-panel 2-jack */
+ CMI_FULL, /* back 6-jack + front-panel 2-jack */
+ CMI_FULL_DIG, /* back 6-jack + front-panel 2-jack + digital I/O */
+ CMI_ALLOUT, /* back 5-jack + front-panel 2-jack + digital out */
+};
+
+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 */
+
+ /* playback */
+ struct hda_multi_out multiout;
+
+ /* capture */
+ hda_nid_t *adc_nids;
+ hda_nid_t dig_in_nid;
+
+ /* capture source */
+ const struct hda_input_mux *input_mux;
+ unsigned int cur_mux[2];
+
+ /* channel mode */
+ unsigned int num_ch_modes;
+ unsigned int cur_ch_mode;
+ const struct cmi_channel_mode *channel_modes;
+
+ struct hda_pcm pcm_rec[2]; /* PCM information */
+};
+
+/*
+ * input MUX
+ */
+static int cmi_mux_enum_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *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)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct cmi_spec *spec = codec->spec;
+ unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
+
+ ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
+ return 0;
+}
+
+static int cmi_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct cmi_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]);
+}
+
+/*
+ * shared line-in, mic for surrounds
+ */
+
+/* 3-stack / 2 channel */
+static struct hda_verb cmi9880_ch2_init[] = {
+ /* set line-in PIN for input */
+ { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
+ /* set mic PIN for input, also enable vref */
+ { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+ /* route front PCM (DAC1) to HP */
+ { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
+ {}
+};
+
+/* 3-stack / 6 channel */
+static struct hda_verb cmi9880_ch6_init[] = {
+ /* set line-in PIN for output */
+ { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+ /* set mic PIN for output */
+ { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+ /* route front PCM (DAC1) to HP */
+ { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
+ {}
+};
+
+/* 3-stack+front / 8 channel */
+static struct hda_verb cmi9880_ch8_init[] = {
+ /* set line-in PIN for output */
+ { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+ /* set mic PIN for output */
+ { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+ /* route rear-surround PCM (DAC4) to HP */
+ { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x03 },
+ {}
+};
+
+struct cmi_channel_mode {
+ unsigned int channels;
+ const struct hda_verb *sequence;
+};
+
+static struct cmi_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)
+{
+ 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;
+}
+
+static int cmi_ch_mode_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *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;
+}
+
+static int cmi_ch_mode_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *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;
+}
+
+/*
+ */
+static snd_kcontrol_new_t 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),
+ 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", 0x06, 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 = 2,
+ .info = cmi_mux_enum_info,
+ .get = cmi_mux_enum_get,
+ .put = cmi_mux_enum_put,
+ },
+ HDA_CODEC_VOLUME("Capture Volume", 0x08, 0, HDA_INPUT),
+ HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0, HDA_INPUT),
+ HDA_CODEC_MUTE("Capture Switch", 0x08, 0, HDA_INPUT),
+ HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0, HDA_INPUT),
+ HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x23, 0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x23, 0, HDA_OUTPUT),
+ { } /* end */
+};
+
+/*
+ * shared I/O pins
+ */
+static snd_kcontrol_new_t cmi9880_ch_mode_mixer[] = {
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Channel Mode",
+ .info = cmi_ch_mode_info,
+ .get = cmi_ch_mode_get,
+ .put = cmi_ch_mode_put,
+ },
+ { } /* end */
+};
+
+/* AUD-in selections:
+ * 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x1f 0x20
+ */
+static struct hda_input_mux cmi9880_basic_mux = {
+ .num_items = 4,
+ .items = {
+ { "Front Mic", 0x5 },
+ { "Rear Mic", 0x2 },
+ { "Line", 0x1 },
+ { "CD", 0x7 },
+ }
+};
+
+static struct hda_input_mux cmi9880_no_line_mux = {
+ .num_items = 3,
+ .items = {
+ { "Front Mic", 0x5 },
+ { "Rear Mic", 0x2 },
+ { "CD", 0x7 },
+ }
+};
+
+/* front, rear, clfe, rear_surr */
+static hda_nid_t cmi9880_dac_nids[4] = {
+ 0x03, 0x04, 0x05, 0x06
+};
+/* ADC0, ADC1 */
+static hda_nid_t cmi9880_adc_nids[2] = {
+ 0x08, 0x09
+};
+
+#define CMI_DIG_OUT_NID 0x07
+#define CMI_DIG_IN_NID 0x0a
+
+/*
+ */
+static struct hda_verb cmi9880_basic_init[] = {
+ /* port-D for line out (rear panel) */
+ { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+ /* 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, 0x00 },
+ /* port-A for surround (rear panel) */
+ { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+ /* port-G for CLFE (rear panel) */
+ { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+ /* port-H for side (rear panel) */
+ { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+ /* port-C for line-in (rear panel) */
+ { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
+ /* port-B for mic-in (rear panel) with vref */
+ { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+ /* port-F for mic-in (front panel) with vref */
+ { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+ /* CD-in */
+ { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
+ /* route front mic to ADC1/2 */
+ { 0x08, AC_VERB_SET_CONNECT_SEL, 0x05 },
+ { 0x09, AC_VERB_SET_CONNECT_SEL, 0x05 },
+ {} /* terminator */
+};
+
+static struct hda_verb cmi9880_allout_init[] = {
+ /* port-D for line out (rear panel) */
+ { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+ /* 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, 0x00 },
+ /* port-A for side (rear panel) */
+ { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+ /* port-G for CLFE (rear panel) */
+ { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+ /* port-C for surround (rear panel) */
+ { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+ /* port-B for mic-in (rear panel) with vref */
+ { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+ /* port-F for mic-in (front panel) with vref */
+ { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+ /* CD-in */
+ { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
+ /* route front mic to ADC1/2 */
+ { 0x08, AC_VERB_SET_CONNECT_SEL, 0x05 },
+ { 0x09, AC_VERB_SET_CONNECT_SEL, 0x05 },
+ {} /* terminator */
+};
+
+/*
+ */
+static int cmi9880_build_controls(struct hda_codec *codec)
+{
+ struct cmi_spec *spec = codec->spec;
+ int err;
+
+ err = snd_hda_add_new_ctls(codec, cmi9880_basic_mixer);
+ if (err < 0)
+ return err;
+ if (spec->surr_switch) {
+ err = snd_hda_add_new_ctls(codec, cmi9880_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)
+ return err;
+ }
+ if (spec->dig_in_nid) {
+ err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
+ if (err < 0)
+ return err;
+ }
+ return 0;
+}
+
+static int cmi9880_init(struct hda_codec *codec)
+{
+ struct cmi_spec *spec = codec->spec;
+ if (spec->board_config == CMI_ALLOUT)
+ snd_hda_sequence_write(codec, cmi9880_allout_init);
+ else
+ snd_hda_sequence_write(codec, cmi9880_basic_init);
+ return 0;
+}
+
+#ifdef CONFIG_PM
+/*
+ * resume
+ */
+static int cmi9880_resume(struct hda_codec *codec)
+{
+ struct cmi_spec *spec = codec->spec;
+
+ cmi9880_init(codec);
+ snd_hda_resume_ctls(codec, cmi9880_basic_mixer);
+ if (spec->surr_switch)
+ snd_hda_resume_ctls(codec, cmi9880_ch_mode_mixer);
+ if (spec->multiout.dig_out_nid)
+ snd_hda_resume_spdif_out(codec);
+ if (spec->dig_in_nid)
+ snd_hda_resume_spdif_in(codec);
+
+ return 0;
+}
+#endif
+
+/*
+ * Analog playback callbacks
+ */
+static int cmi9880_playback_pcm_open(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ snd_pcm_substream_t *substream)
+{
+ struct cmi_spec *spec = codec->spec;
+ return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
+}
+
+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 cmi_spec *spec = codec->spec;
+ return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag,
+ format, substream);
+}
+
+static int cmi9880_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ snd_pcm_substream_t *substream)
+{
+ struct cmi_spec *spec = codec->spec;
+ return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
+}
+
+/*
+ * Digital out
+ */
+static int cmi9880_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ snd_pcm_substream_t *substream)
+{
+ struct cmi_spec *spec = codec->spec;
+ return snd_hda_multi_out_dig_open(codec, &spec->multiout);
+}
+
+static int cmi9880_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ snd_pcm_substream_t *substream)
+{
+ struct cmi_spec *spec = codec->spec;
+ return snd_hda_multi_out_dig_close(codec, &spec->multiout);
+}
+
+/*
+ * Analog capture
+ */
+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 cmi_spec *spec = codec->spec;
+
+ snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
+ stream_tag, 0, format);
+ return 0;
+}
+
+static int cmi9880_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ snd_pcm_substream_t *substream)
+{
+ struct cmi_spec *spec = codec->spec;
+
+ snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], 0, 0, 0);
+ return 0;
+}
+
+
+/*
+ */
+static struct hda_pcm_stream cmi9880_pcm_analog_playback = {
+ .substreams = 1,
+ .channels_min = 2,
+ .channels_max = 8,
+ .nid = 0x03, /* NID to query formats and rates */
+ .ops = {
+ .open = cmi9880_playback_pcm_open,
+ .prepare = cmi9880_playback_pcm_prepare,
+ .cleanup = cmi9880_playback_pcm_cleanup
+ },
+};
+
+static struct hda_pcm_stream cmi9880_pcm_analog_capture = {
+ .substreams = 2,
+ .channels_min = 2,
+ .channels_max = 2,
+ .nid = 0x08, /* NID to query formats and rates */
+ .ops = {
+ .prepare = cmi9880_capture_pcm_prepare,
+ .cleanup = cmi9880_capture_pcm_cleanup
+ },
+};
+
+static struct hda_pcm_stream cmi9880_pcm_digital_playback = {
+ .substreams = 1,
+ .channels_min = 2,
+ .channels_max = 2,
+ /* NID is set in cmi9880_build_pcms */
+ .ops = {
+ .open = cmi9880_dig_playback_pcm_open,
+ .close = cmi9880_dig_playback_pcm_close
+ },
+};
+
+static struct hda_pcm_stream cmi9880_pcm_digital_capture = {
+ .substreams = 1,
+ .channels_min = 2,
+ .channels_max = 2,
+ /* NID is set in cmi9880_build_pcms */
+};
+
+static int cmi9880_build_pcms(struct hda_codec *codec)
+{
+ struct cmi_spec *spec = codec->spec;
+ struct hda_pcm *info = spec->pcm_rec;
+
+ codec->num_pcms = 1;
+ codec->pcm_info = info;
+
+ info->name = "CMI9880";
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK] = cmi9880_pcm_analog_playback;
+ info->stream[SNDRV_PCM_STREAM_CAPTURE] = cmi9880_pcm_analog_capture;
+
+ if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
+ codec->num_pcms++;
+ info++;
+ info->name = "CMI9880 Digital";
+ if (spec->multiout.dig_out_nid) {
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK] = cmi9880_pcm_digital_playback;
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
+ }
+ if (spec->dig_in_nid) {
+ info->stream[SNDRV_PCM_STREAM_CAPTURE] = cmi9880_pcm_digital_capture;
+ info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
+ }
+ }
+
+ return 0;
+}
+
+static void cmi9880_free(struct hda_codec *codec)
+{
+ kfree(codec->spec);
+}
+
+/*
+ */
+
+static struct hda_board_config cmi9880_cfg_tbl[] = {
+ { .modelname = "minimal", .config = CMI_MINIMAL },
+ { .modelname = "min_fp", .config = CMI_MIN_FP },
+ { .modelname = "full", .config = CMI_FULL },
+ { .modelname = "full_dig", .config = CMI_FULL_DIG },
+ { .modelname = "allout", .config = CMI_ALLOUT },
+ {} /* terminator */
+};
+
+static struct hda_codec_ops cmi9880_patch_ops = {
+ .build_controls = cmi9880_build_controls,
+ .build_pcms = cmi9880_build_pcms,
+ .init = cmi9880_init,
+ .free = cmi9880_free,
+#ifdef CONFIG_PM
+ .resume = cmi9880_resume,
+#endif
+};
+
+static int patch_cmi9880(struct hda_codec *codec)
+{
+ struct cmi_spec *spec;
+
+ spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
+ if (spec == NULL)
+ return -ENOMEM;
+
+ codec->spec = spec;
+ spec->board_config = snd_hda_check_board_config(codec, cmi9880_cfg_tbl);
+ if (spec->board_config < 0) {
+ snd_printd(KERN_INFO "hda_codec: Unknown model for CMI9880\n");
+ spec->board_config = CMI_FULL_DIG; /* try everything */
+ }
+
+ switch (spec->board_config) {
+ case CMI_MINIMAL:
+ case CMI_MIN_FP:
+ spec->surr_switch = 1;
+ if (spec->board_config == CMI_MINIMAL)
+ spec->num_ch_modes = 2;
+ else {
+ spec->front_panel = 1;
+ spec->num_ch_modes = 3;
+ }
+ spec->channel_modes = cmi9880_channel_modes;
+ spec->multiout.max_channels = cmi9880_channel_modes[0].channels;
+ spec->input_mux = &cmi9880_basic_mux;
+ break;
+ case CMI_FULL:
+ case CMI_FULL_DIG:
+ spec->front_panel = 1;
+ spec->multiout.max_channels = 8;
+ spec->input_mux = &cmi9880_basic_mux;
+ if (spec->board_config == CMI_FULL_DIG) {
+ spec->multiout.dig_out_nid = CMI_DIG_OUT_NID;
+ spec->dig_in_nid = CMI_DIG_IN_NID;
+ }
+ break;
+ case CMI_ALLOUT:
+ spec->front_panel = 1;
+ spec->multiout.max_channels = 8;
+ spec->no_line_in = 1;
+ spec->input_mux = &cmi9880_no_line_mux;
+ spec->multiout.dig_out_nid = CMI_DIG_OUT_NID;
+ break;
+ }
+
+ spec->multiout.num_dacs = 4;
+ spec->multiout.dac_nids = cmi9880_dac_nids;
+
+ spec->adc_nids = cmi9880_adc_nids;
+
+ codec->patch_ops = cmi9880_patch_ops;
+
+ return 0;
+}
+
+/*
+ * patch entries
+ */
+struct hda_codec_preset snd_hda_preset_cmedia[] = {
+ { .id = 0x13f69880, .name = "CMI9880", .patch = patch_cmi9880 },
+ { .id = 0x434d4980, .name = "CMI9880", .patch = patch_cmi9880 },
+ {} /* terminator */
+};
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
new file mode 100644
index 0000000000000..17c5062423aee
--- /dev/null
+++ b/sound/pci/hda/patch_realtek.c
@@ -0,0 +1,1503 @@
+/*
+ * Universal Interface for Intel High Definition Audio Codec
+ *
+ * HD audio interface patch for ALC 260/880/882 codecs
+ *
+ * Copyright (c) 2004 PeiSen Hou <pshou@realtek.com.tw>
+ * Takashi Iwai <tiwai@suse.de>
+ *
+ * This driver is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This driver is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <sound/driver.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <sound/core.h>
+#include "hda_codec.h"
+#include "hda_local.h"
+
+
+/* ALC880 board config type */
+enum {
+ ALC880_MINIMAL,
+ ALC880_3ST,
+ ALC880_3ST_DIG,
+ ALC880_5ST,
+ ALC880_5ST_DIG,
+ ALC880_W810,
+};
+
+struct alc_spec {
+ /* codec parameterization */
+ unsigned int front_panel: 1;
+
+ snd_kcontrol_new_t* mixers[2];
+ unsigned int num_mixers;
+
+ struct hda_verb *init_verbs;
+
+ char* stream_name_analog;
+ struct hda_pcm_stream *stream_analog_playback;
+ struct hda_pcm_stream *stream_analog_capture;
+
+ char* stream_name_digital;
+ struct hda_pcm_stream *stream_digital_playback;
+ struct hda_pcm_stream *stream_digital_capture;
+
+ /* playback */
+ struct hda_multi_out multiout;
+
+ /* capture */
+ unsigned int num_adc_nids;
+ hda_nid_t *adc_nids;
+ hda_nid_t dig_in_nid;
+
+ /* capture source */
+ const struct hda_input_mux *input_mux;
+ unsigned int cur_mux[3];
+
+ /* channel model */
+ const struct alc_channel_mode *channel_mode;
+ int num_channel_mode;
+
+ /* PCM information */
+ struct hda_pcm pcm_rec[2];
+};
+
+/* DAC/ADC assignment */
+
+static hda_nid_t alc880_dac_nids[4] = {
+ /* front, rear, clfe, rear_surr */
+ 0x02, 0x05, 0x04, 0x03
+};
+
+static hda_nid_t alc880_w810_dac_nids[3] = {
+ /* front, rear/surround, clfe */
+ 0x02, 0x03, 0x04
+};
+
+static hda_nid_t alc880_adc_nids[3] = {
+ /* ADC0-2 */
+ 0x07, 0x08, 0x09,
+};
+
+#define ALC880_DIGOUT_NID 0x06
+#define ALC880_DIGIN_NID 0x0a
+
+static hda_nid_t alc260_dac_nids[1] = {
+ /* front */
+ 0x02,
+};
+
+static hda_nid_t alc260_adc_nids[2] = {
+ /* ADC0-1 */
+ 0x04, 0x05,
+};
+
+#define ALC260_DIGOUT_NID 0x03
+#define ALC260_DIGIN_NID 0x06
+
+static struct hda_input_mux alc880_capture_source = {
+ .num_items = 4,
+ .items = {
+ { "Mic", 0x0 },
+ { "Front Mic", 0x3 },
+ { "Line", 0x2 },
+ { "CD", 0x4 },
+ },
+};
+
+static struct hda_input_mux alc260_capture_source = {
+ .num_items = 4,
+ .items = {
+ { "Mic", 0x0 },
+ { "Front Mic", 0x1 },
+ { "Line", 0x2 },
+ { "CD", 0x4 },
+ },
+};
+
+/*
+ * input MUX handling
+ */
+static int alc_mux_enum_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *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)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct alc_spec *spec = codec->spec;
+ unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
+
+ ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
+ return 0;
+}
+
+static int alc_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct alc_spec *spec = codec->spec;
+ unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
+ return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
+ spec->adc_nids[adc_idx], &spec->cur_mux[adc_idx]);
+}
+
+/*
+ * channel mode setting
+ */
+struct alc_channel_mode {
+ int channels;
+ const struct hda_verb *sequence;
+};
+
+
+/*
+ * 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 alc880_threestack_ch2_init[] = {
+ /* set pin widget 1Ah (line in) for input */
+ { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
+ /* set pin widget 18h (mic1) for input, for mic also enable the vref */
+ { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+ /* mute the output for Line In PW */
+ { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
+ /* mute for Mic1 PW */
+ { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
+ { } /* end */
+};
+
+/*
+ * 6ch mode
+ * need to set the codec line out and mic 1 pin widgets to outputs
+ */
+static struct hda_verb alc880_threestack_ch6_init[] = {
+ /* set pin widget 1Ah (line in) for output */
+ { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+ /* set pin widget 18h (mic1) for output */
+ { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+ /* unmute the output for Line In PW */
+ { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000 },
+ /* unmute for Mic1 PW */
+ { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000 },
+ /* for rear channel output using Line In 1
+ * set select widget connection (nid = 0x12) - to summer node
+ * for rear NID = 0x0f...offset 3 in connection list
+ */
+ { 0x12, AC_VERB_SET_CONNECT_SEL, 0x3 },
+ /* for Mic1 - retask for center/lfe */
+ /* set select widget connection (nid = 0x10) - to summer node for
+ * front CLFE NID = 0x0e...offset 2 in connection list
+ */
+ { 0x10, AC_VERB_SET_CONNECT_SEL, 0x2 },
+ { } /* end */
+};
+
+static struct alc_channel_mode alc880_threestack_modes[2] = {
+ { 2, alc880_threestack_ch2_init },
+ { 6, alc880_threestack_ch6_init },
+};
+
+
+/*
+ * channel source setting (6/8 channel selection for 5-stack)
+ */
+
+/* set the path ways for 6 channel output
+ * need to set the codec line out and mic 1 pin widgets to inputs
+ */
+static struct hda_verb alc880_fivestack_ch6_init[] = {
+ /* set pin widget 1Ah (line in) for input */
+ { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
+ /* mute the output for Line In PW */
+ { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
+ { } /* end */
+};
+
+/* need to set the codec line out and mic 1 pin widgets to outputs */
+static struct hda_verb alc880_fivestack_ch8_init[] = {
+ /* set pin widget 1Ah (line in) for output */
+ { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+ /* unmute the output for Line In PW */
+ { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000 },
+ /* output for surround channel output using Line In 1 */
+ /* set select widget connection (nid = 0x12) - to summer node
+ * for surr_rear NID = 0x0d...offset 1 in connection list
+ */
+ { 0x12, AC_VERB_SET_CONNECT_SEL, 0x1 },
+ { } /* end */
+};
+
+static struct alc_channel_mode alc880_fivestack_modes[2] = {
+ { 6, alc880_fivestack_ch6_init },
+ { 8, alc880_fivestack_ch8_init },
+};
+
+/*
+ * channel source setting for W810 system
+ *
+ * W810 has rear IO for:
+ * Front (DAC 02)
+ * Surround (DAC 03)
+ * Center/LFE (DAC 04)
+ * Digital out (06)
+ *
+ * The system also has a pair of internal speakers, and a headphone jack.
+ * These are both connected to Line2 on the codec, hence to DAC 02.
+ *
+ * There is a variable resistor to control the speaker or headphone
+ * volume. This is a hardware-only device without a software API.
+ *
+ * Plugging headphones in will disable the internal speakers. This is
+ * implemented in hardware, not via the driver using jack sense. In
+ * a similar fashion, plugging into the rear socket marked "front" will
+ * disable both the speakers and headphones.
+ *
+ * For input, there's a microphone jack, and an "audio in" jack.
+ * These may not do anything useful with this driver yet, because I
+ * haven't setup any initialization verbs for these yet...
+ */
+
+static struct alc_channel_mode alc880_w810_modes[1] = {
+ { 6, NULL }
+};
+
+/*
+ */
+static int alc880_ch_mode_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct alc_spec *spec = codec->spec;
+
+ snd_assert(spec->channel_mode, return -ENXIO);
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+ uinfo->count = 1;
+ uinfo->value.enumerated.items = 2;
+ if (uinfo->value.enumerated.item >= 2)
+ uinfo->value.enumerated.item = 1;
+ sprintf(uinfo->value.enumerated.name, "%dch",
+ spec->channel_mode[uinfo->value.enumerated.item].channels);
+ return 0;
+}
+
+static int alc880_ch_mode_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct alc_spec *spec = codec->spec;
+
+ snd_assert(spec->channel_mode, return -ENXIO);
+ ucontrol->value.enumerated.item[0] =
+ (spec->multiout.max_channels == spec->channel_mode[0].channels) ? 0 : 1;
+ return 0;
+}
+
+static int alc880_ch_mode_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *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;
+}
+
+
+/*
+ */
+
+/* 3-stack mode
+ * Pin assignment: Front=0x14, Line-In/Rear=0x1a, Mic/CLFE=0x18, F-Mic=0x1b
+ * HP=0x19
+ */
+static snd_kcontrol_new_t alc880_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("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Surround Playback Switch", 0x1a, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x18, 1, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x18, 2, 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, 0x3, HDA_INPUT),
+ HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x3, HDA_INPUT),
+ HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
+ HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
+ HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Headphone Playback Switch", 0x19, 0x0, HDA_OUTPUT),
+ 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),
+ {
+ .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 = alc_mux_enum_info,
+ .get = alc_mux_enum_get,
+ .put = alc_mux_enum_put,
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Channel Mode",
+ .info = alc880_ch_mode_info,
+ .get = alc880_ch_mode_get,
+ .put = alc880_ch_mode_put,
+ },
+ { } /* end */
+};
+
+/* 5-stack mode
+ * Pin assignment: Front=0x14, Rear=0x17, CLFE=0x16
+ * Line-In/Side=0x1a, Mic=0x18, F-Mic=0x1b, HP=0x19
+ */
+static snd_kcontrol_new_t alc880_five_stack_mixer[] = {
+ HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Surround Playback Switch", 0x17, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x16, 1, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Side Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Side Playback Switch", 0x1a, 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, 0x3, HDA_INPUT),
+ HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x3, HDA_INPUT),
+ HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
+ HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
+ HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Headphone Playback Switch", 0x19, 0x0, HDA_OUTPUT),
+ 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),
+ {
+ .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 = alc_mux_enum_info,
+ .get = alc_mux_enum_get,
+ .put = alc_mux_enum_put,
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Channel Mode",
+ .info = alc880_ch_mode_info,
+ .get = alc880_ch_mode_get,
+ .put = alc880_ch_mode_put,
+ },
+ { } /* end */
+};
+
+static snd_kcontrol_new_t alc880_w810_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("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x16, 1, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
+ 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 = alc_mux_enum_info,
+ .get = alc_mux_enum_get,
+ .put = alc_mux_enum_put,
+ },
+ { } /* end */
+};
+
+/*
+ */
+static int alc_build_controls(struct hda_codec *codec)
+{
+ struct alc_spec *spec = codec->spec;
+ int err;
+ int i;
+
+ for (i = 0; i < spec->num_mixers; i++) {
+ err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
+ 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)
+ return err;
+ }
+ if (spec->dig_in_nid) {
+ err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
+ if (err < 0)
+ return err;
+ }
+ return 0;
+}
+
+/*
+ * initialize the codec volumes, etc
+ */
+
+static struct hda_verb alc880_init_verbs_three_stack[] = {
+ /* Line In pin widget for input */
+ {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
+ /* CD pin widget for input */
+ {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
+ /* Mic1 (rear panel) pin widget for input and vref at 80% */
+ {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
+ /* Mic2 (front panel) pin widget for input and vref at 80% */
+ {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
+ /* unmute amp left and right */
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
+ /* set connection select to line in (default select for this ADC) */
+ {0x07, AC_VERB_SET_CONNECT_SEL, 0x02},
+ /* unmute front mixer amp left (volume = 0) */
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+ /* mute pin widget amp left and right (no gain on this amp) */
+ {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
+ /* unmute rear mixer amp left and right (volume = 0) */
+ {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+ /* mute pin widget amp left and right (no gain on this amp) */
+ {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
+ /* unmute rear mixer amp left and right (volume = 0) */
+ {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+ /* mute pin widget amp left and right (no gain on this amp) */
+ {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
+
+ /* using rear surround as the path for headphone output */
+ /* unmute rear surround mixer amp left and right (volume = 0) */
+ {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+ /* PASD 3 stack boards use the Mic 2 as the headphone output */
+ /* need to program the selector associated with the Mic 2 pin widget to
+ * surround path (index 0x01) for headphone output */
+ {0x11, AC_VERB_SET_CONNECT_SEL, 0x01},
+ /* mute pin widget amp left and right (no gain on this amp) */
+ {0x19, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
+ /* need to retask the Mic 2 pin widget to output */
+ {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+
+ /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) for mixer widget(nid=0x0B)
+ * to support the input path of analog loopback
+ * Note: PASD motherboards uses the Line In 2 as the input for front panel
+ * mic (mic 2)
+ */
+ /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03 */
+ /* unmute CD */
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
+ /* unmute Line In */
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
+ /* unmute Mic 1 */
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+ /* unmute Line In 2 (for PASD boards Mic 2) */
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))},
+
+ /* Unmute input amps for the line out paths to support the output path of
+ * analog loopback
+ * the mixers on the output path has 2 inputs, one from the DAC and one
+ * from the mixer
+ */
+ /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
+ /* Unmute Front out path */
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+ /* Unmute Surround (used as HP) out path */
+ {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+ {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+ /* Unmute C/LFE out path */
+ {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+ {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8))}, /* mute */
+ /* Unmute rear Surround out path */
+ {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+ {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+
+ { }
+};
+
+static struct hda_verb alc880_init_verbs_five_stack[] = {
+ /* Line In pin widget for input */
+ {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
+ /* CD pin widget for input */
+ {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
+ /* Mic1 (rear panel) pin widget for input and vref at 80% */
+ {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
+ /* Mic2 (front panel) pin widget for input and vref at 80% */
+ {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
+ /* unmute amp left and right */
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
+ /* set connection select to line in (default select for this ADC) */
+ {0x07, AC_VERB_SET_CONNECT_SEL, 0x02},
+ /* unmute front mixer amp left and right (volume = 0) */
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+ /* mute pin widget amp left and right (no gain on this amp) */
+ {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
+ /* five rear and clfe */
+ /* unmute rear mixer amp left and right (volume = 0) */
+ {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+ /* mute pin widget amp left and right (no gain on this amp) */
+ {0x17, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
+ /* unmute clfe mixer amp left and right (volume = 0) */
+ {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+ /* mute pin widget amp left and right (no gain on this amp) */
+ {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
+
+ /* using rear surround as the path for headphone output */
+ /* unmute rear surround mixer amp left and right (volume = 0) */
+ {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+ /* PASD 3 stack boards use the Mic 2 as the headphone output */
+ /* need to program the selector associated with the Mic 2 pin widget to
+ * surround path (index 0x01) for headphone output
+ */
+ {0x11, AC_VERB_SET_CONNECT_SEL, 0x01},
+ /* mute pin widget amp left and right (no gain on this amp) */
+ {0x19, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
+ /* need to retask the Mic 2 pin widget to output */
+ {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+
+ /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) for mixer
+ * widget(nid=0x0B) to support the input path of analog loopback
+ */
+ /* Note: PASD motherboards uses the Line In 2 as the input for front panel mic (mic 2) */
+ /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03*/
+ /* unmute CD */
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
+ /* unmute Line In */
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
+ /* unmute Mic 1 */
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+ /* unmute Line In 2 (for PASD boards Mic 2) */
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))},
+
+ /* Unmute input amps for the line out paths to support the output path of
+ * analog loopback
+ * the mixers on the output path has 2 inputs, one from the DAC and
+ * one from the mixer
+ */
+ /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
+ /* Unmute Front out path */
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+ /* Unmute Surround (used as HP) out path */
+ {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+ {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+ /* Unmute C/LFE out path */
+ {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+ {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8))}, /* mute */
+ /* Unmute rear Surround out path */
+ {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+ {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+
+ { }
+};
+
+static struct hda_verb alc880_w810_init_verbs[] = {
+ /* front channel selector/amp: input 0: DAC: unmuted, (no volume selection) */
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
+
+ /* front channel selector/amp: input 1: capture mix: muted, (no volume selection) */
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7180},
+
+ /* front channel selector/amp: output 0: unmuted, max volume */
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+
+ /* front out pin: muted, (no volume selection) */
+ {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+
+ /* front out pin: NOT headphone enable, out enable, vref disabled */
+ {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+
+
+ /* surround channel selector/amp: input 0: DAC: unmuted, (no volume selection) */
+ {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
+
+ /* surround channel selector/amp: input 1: capture mix: muted, (no volume selection) */
+ {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7180},
+
+ /* surround channel selector/amp: output 0: unmuted, max volume */
+ {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+
+ /* surround out pin: muted, (no volume selection) */
+ {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+
+ /* surround out pin: NOT headphone enable, out enable, vref disabled */
+ {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+
+
+ /* c/lfe channel selector/amp: input 0: DAC: unmuted, (no volume selection) */
+ {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
+
+ /* c/lfe channel selector/amp: input 1: capture mix: muted, (no volume selection) */
+ {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0x7180},
+
+ /* c/lfe channel selector/amp: output 0: unmuted, max volume */
+ {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+
+ /* c/lfe out pin: muted, (no volume selection) */
+ {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+
+ /* c/lfe out pin: NOT headphone enable, out enable, vref disabled */
+ {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+
+
+ /* hphone/speaker input selector: front DAC */
+ {0x13, AC_VERB_SET_CONNECT_SEL, 0x0},
+
+ /* hphone/speaker out pin: muted, (no volume selection) */
+ {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+
+ /* hphone/speaker out pin: NOT headphone enable, out enable, vref disabled */
+ {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+
+
+ { }
+};
+
+static int alc_init(struct hda_codec *codec)
+{
+ struct alc_spec *spec = codec->spec;
+ snd_hda_sequence_write(codec, spec->init_verbs);
+ return 0;
+}
+
+#ifdef CONFIG_PM
+/*
+ * resume
+ */
+static int alc_resume(struct hda_codec *codec)
+{
+ struct alc_spec *spec = codec->spec;
+ int i;
+
+ alc_init(codec);
+ for (i = 0; i < spec->num_mixers; i++) {
+ snd_hda_resume_ctls(codec, spec->mixers[i]);
+ }
+ if (spec->multiout.dig_out_nid)
+ snd_hda_resume_spdif_out(codec);
+ if (spec->dig_in_nid)
+ snd_hda_resume_spdif_in(codec);
+
+ return 0;
+}
+#endif
+
+/*
+ * Analog playback callbacks
+ */
+static int alc880_playback_pcm_open(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ snd_pcm_substream_t *substream)
+{
+ struct alc_spec *spec = codec->spec;
+ return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
+}
+
+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 alc_spec *spec = codec->spec;
+ return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag,
+ format, substream);
+}
+
+static int alc880_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ snd_pcm_substream_t *substream)
+{
+ struct alc_spec *spec = codec->spec;
+ return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
+}
+
+/*
+ * Digital out
+ */
+static int alc880_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ snd_pcm_substream_t *substream)
+{
+ struct alc_spec *spec = codec->spec;
+ return snd_hda_multi_out_dig_open(codec, &spec->multiout);
+}
+
+static int alc880_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ snd_pcm_substream_t *substream)
+{
+ struct alc_spec *spec = codec->spec;
+ return snd_hda_multi_out_dig_close(codec, &spec->multiout);
+}
+
+/*
+ * Analog capture
+ */
+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 alc_spec *spec = codec->spec;
+
+ snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
+ stream_tag, 0, format);
+ return 0;
+}
+
+static int alc880_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ snd_pcm_substream_t *substream)
+{
+ struct alc_spec *spec = codec->spec;
+
+ snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], 0, 0, 0);
+ return 0;
+}
+
+
+/*
+ */
+static struct hda_pcm_stream alc880_pcm_analog_playback = {
+ .substreams = 1,
+ .channels_min = 2,
+ .channels_max = 8,
+ .nid = 0x02, /* NID to query formats and rates */
+ .ops = {
+ .open = alc880_playback_pcm_open,
+ .prepare = alc880_playback_pcm_prepare,
+ .cleanup = alc880_playback_pcm_cleanup
+ },
+};
+
+static struct hda_pcm_stream alc880_pcm_analog_capture = {
+ .substreams = 2,
+ .channels_min = 2,
+ .channels_max = 2,
+ .nid = 0x07, /* NID to query formats and rates */
+ .ops = {
+ .prepare = alc880_capture_pcm_prepare,
+ .cleanup = alc880_capture_pcm_cleanup
+ },
+};
+
+static struct hda_pcm_stream alc880_pcm_digital_playback = {
+ .substreams = 1,
+ .channels_min = 2,
+ .channels_max = 2,
+ /* NID is set in alc_build_pcms */
+ .ops = {
+ .open = alc880_dig_playback_pcm_open,
+ .close = alc880_dig_playback_pcm_close
+ },
+};
+
+static struct hda_pcm_stream alc880_pcm_digital_capture = {
+ .substreams = 1,
+ .channels_min = 2,
+ .channels_max = 2,
+ /* NID is set in alc_build_pcms */
+};
+
+static int alc_build_pcms(struct hda_codec *codec)
+{
+ struct alc_spec *spec = codec->spec;
+ struct hda_pcm *info = spec->pcm_rec;
+ int i;
+
+ codec->num_pcms = 1;
+ 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_CAPTURE] = *(spec->stream_analog_capture);
+
+ 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->multiout.dig_out_nid || spec->dig_in_nid) {
+ codec->num_pcms++;
+ info++;
+ info->name = spec->stream_name_digital;
+ if (spec->multiout.dig_out_nid) {
+ 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) {
+ info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_digital_capture);
+ info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
+ }
+ }
+
+ return 0;
+}
+
+static void alc_free(struct hda_codec *codec)
+{
+ kfree(codec->spec);
+}
+
+/*
+ */
+static struct hda_codec_ops alc_patch_ops = {
+ .build_controls = alc_build_controls,
+ .build_pcms = alc_build_pcms,
+ .init = alc_init,
+ .free = alc_free,
+#ifdef CONFIG_PM
+ .resume = alc_resume,
+#endif
+};
+
+/*
+ */
+
+static struct hda_board_config alc880_cfg_tbl[] = {
+ /* Back 3 jack, front 2 jack */
+ { .modelname = "3stack", .config = ALC880_3ST },
+ { .pci_vendor = 0x8086, .pci_device = 0xe200, .config = ALC880_3ST },
+ { .pci_vendor = 0x8086, .pci_device = 0xe201, .config = ALC880_3ST },
+ { .pci_vendor = 0x8086, .pci_device = 0xe202, .config = ALC880_3ST },
+ { .pci_vendor = 0x8086, .pci_device = 0xe203, .config = ALC880_3ST },
+ { .pci_vendor = 0x8086, .pci_device = 0xe204, .config = ALC880_3ST },
+ { .pci_vendor = 0x8086, .pci_device = 0xe205, .config = ALC880_3ST },
+ { .pci_vendor = 0x8086, .pci_device = 0xe206, .config = ALC880_3ST },
+ { .pci_vendor = 0x8086, .pci_device = 0xe207, .config = ALC880_3ST },
+ { .pci_vendor = 0x8086, .pci_device = 0xe208, .config = ALC880_3ST },
+ { .pci_vendor = 0x8086, .pci_device = 0xe209, .config = ALC880_3ST },
+ { .pci_vendor = 0x8086, .pci_device = 0xe20a, .config = ALC880_3ST },
+ { .pci_vendor = 0x8086, .pci_device = 0xe20b, .config = ALC880_3ST },
+ { .pci_vendor = 0x8086, .pci_device = 0xe20c, .config = ALC880_3ST },
+ { .pci_vendor = 0x8086, .pci_device = 0xe20d, .config = ALC880_3ST },
+ { .pci_vendor = 0x8086, .pci_device = 0xe20e, .config = ALC880_3ST },
+ { .pci_vendor = 0x8086, .pci_device = 0xe20f, .config = ALC880_3ST },
+ { .pci_vendor = 0x8086, .pci_device = 0xe210, .config = ALC880_3ST },
+ { .pci_vendor = 0x8086, .pci_device = 0xe211, .config = ALC880_3ST },
+ { .pci_vendor = 0x8086, .pci_device = 0xe214, .config = ALC880_3ST },
+ { .pci_vendor = 0x8086, .pci_device = 0xe302, .config = ALC880_3ST },
+ { .pci_vendor = 0x8086, .pci_device = 0xe303, .config = ALC880_3ST },
+ { .pci_vendor = 0x8086, .pci_device = 0xe304, .config = ALC880_3ST },
+ { .pci_vendor = 0x8086, .pci_device = 0xe306, .config = ALC880_3ST },
+ { .pci_vendor = 0x8086, .pci_device = 0xe307, .config = ALC880_3ST },
+ { .pci_vendor = 0x8086, .pci_device = 0xe404, .config = ALC880_3ST },
+ { .pci_vendor = 0x8086, .pci_device = 0xa101, .config = ALC880_3ST },
+ { .pci_vendor = 0x107b, .pci_device = 0x3031, .config = ALC880_3ST },
+ { .pci_vendor = 0x107b, .pci_device = 0x4036, .config = ALC880_3ST },
+ { .pci_vendor = 0x107b, .pci_device = 0x4037, .config = ALC880_3ST },
+ { .pci_vendor = 0x107b, .pci_device = 0x4038, .config = ALC880_3ST },
+ { .pci_vendor = 0x107b, .pci_device = 0x4040, .config = ALC880_3ST },
+ { .pci_vendor = 0x107b, .pci_device = 0x4041, .config = ALC880_3ST },
+
+ /* Back 3 jack, front 2 jack (Internal add Aux-In) */
+ { .pci_vendor = 0x1025, .pci_device = 0xe310, .config = ALC880_3ST },
+
+ /* Back 3 jack plus 1 SPDIF out jack, front 2 jack */
+ { .modelname = "3stack-digout", .config = ALC880_3ST_DIG },
+ { .pci_vendor = 0x8086, .pci_device = 0xe308, .config = ALC880_3ST_DIG },
+
+ /* Back 3 jack plus 1 SPDIF out jack, front 2 jack (Internal add Aux-In)*/
+ { .pci_vendor = 0x8086, .pci_device = 0xe305, .config = ALC880_3ST_DIG },
+ { .pci_vendor = 0x8086, .pci_device = 0xd402, .config = ALC880_3ST_DIG },
+ { .pci_vendor = 0x1025, .pci_device = 0xe309, .config = ALC880_3ST_DIG },
+
+ /* Back 5 jack, front 2 jack */
+ { .modelname = "5stack", .config = ALC880_5ST },
+ { .pci_vendor = 0x107b, .pci_device = 0x3033, .config = ALC880_5ST },
+ { .pci_vendor = 0x107b, .pci_device = 0x4039, .config = ALC880_5ST },
+ { .pci_vendor = 0x107b, .pci_device = 0x3032, .config = ALC880_5ST },
+ { .pci_vendor = 0x103c, .pci_device = 0x2a09, .config = ALC880_5ST },
+
+ /* Back 5 jack plus 1 SPDIF out jack, front 2 jack */
+ { .modelname = "5stack-digout", .config = ALC880_5ST_DIG },
+ { .pci_vendor = 0x8086, .pci_device = 0xe224, .config = ALC880_5ST_DIG },
+ { .pci_vendor = 0x8086, .pci_device = 0xe400, .config = ALC880_5ST_DIG },
+ { .pci_vendor = 0x8086, .pci_device = 0xe401, .config = ALC880_5ST_DIG },
+ { .pci_vendor = 0x8086, .pci_device = 0xe402, .config = ALC880_5ST_DIG },
+ { .pci_vendor = 0x8086, .pci_device = 0xd400, .config = ALC880_5ST_DIG },
+ { .pci_vendor = 0x8086, .pci_device = 0xd401, .config = ALC880_5ST_DIG },
+ { .pci_vendor = 0x8086, .pci_device = 0xa100, .config = ALC880_5ST_DIG },
+ { .pci_vendor = 0x1565, .pci_device = 0x8202, .config = ALC880_5ST_DIG },
+
+ { .modelname = "w810", .config = ALC880_W810 },
+ { .pci_vendor = 0x161f, .pci_device = 0x203d, .config = ALC880_W810 },
+
+ {}
+};
+
+static int patch_alc880(struct hda_codec *codec)
+{
+ struct alc_spec *spec;
+ int board_config;
+
+ spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
+ if (spec == NULL)
+ return -ENOMEM;
+
+ codec->spec = spec;
+
+ board_config = snd_hda_check_board_config(codec, alc880_cfg_tbl);
+ if (board_config < 0) {
+ snd_printd(KERN_INFO "hda_codec: Unknown model for ALC880\n");
+ board_config = ALC880_MINIMAL;
+ }
+
+ switch (board_config) {
+ case ALC880_W810:
+ spec->mixers[spec->num_mixers] = alc880_w810_base_mixer;
+ spec->num_mixers++;
+ break;
+ case ALC880_5ST:
+ case ALC880_5ST_DIG:
+ spec->mixers[spec->num_mixers] = alc880_five_stack_mixer;
+ spec->num_mixers++;
+ break;
+ default:
+ spec->mixers[spec->num_mixers] = alc880_base_mixer;
+ spec->num_mixers++;
+ break;
+ }
+
+ switch (board_config) {
+ case ALC880_3ST_DIG:
+ case ALC880_5ST_DIG:
+ case ALC880_W810:
+ spec->multiout.dig_out_nid = ALC880_DIGOUT_NID;
+ break;
+ default:
+ break;
+ }
+
+ switch (board_config) {
+ case ALC880_3ST:
+ case ALC880_3ST_DIG:
+ case ALC880_5ST:
+ case ALC880_5ST_DIG:
+ case ALC880_W810:
+ spec->front_panel = 1;
+ break;
+ default:
+ break;
+ }
+
+ switch (board_config) {
+ case ALC880_5ST:
+ case ALC880_5ST_DIG:
+ spec->init_verbs = alc880_init_verbs_five_stack;
+ spec->channel_mode = alc880_fivestack_modes;
+ spec->num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes);
+ break;
+ case ALC880_W810:
+ spec->init_verbs = alc880_w810_init_verbs;
+ spec->channel_mode = alc880_w810_modes;
+ spec->num_channel_mode = ARRAY_SIZE(alc880_w810_modes);
+ break;
+ default:
+ spec->init_verbs = alc880_init_verbs_three_stack;
+ spec->channel_mode = alc880_threestack_modes;
+ spec->num_channel_mode = ARRAY_SIZE(alc880_threestack_modes);
+ break;
+ }
+
+ spec->stream_name_analog = "ALC880 Analog";
+ spec->stream_analog_playback = &alc880_pcm_analog_playback;
+ spec->stream_analog_capture = &alc880_pcm_analog_capture;
+
+ spec->stream_name_digital = "ALC880 Digital";
+ spec->stream_digital_playback = &alc880_pcm_digital_playback;
+ spec->stream_digital_capture = &alc880_pcm_digital_capture;
+
+ spec->multiout.max_channels = spec->channel_mode[0].channels;
+
+ switch (board_config) {
+ case ALC880_W810:
+ spec->multiout.num_dacs = ARRAY_SIZE(alc880_w810_dac_nids);
+ spec->multiout.dac_nids = alc880_w810_dac_nids;
+ // No dedicated headphone socket - it's shared with built-in speakers.
+ break;
+ default:
+ spec->multiout.num_dacs = ARRAY_SIZE(alc880_dac_nids);
+ spec->multiout.dac_nids = alc880_dac_nids;
+ spec->multiout.hp_nid = 0x03; /* rear-surround NID */
+ break;
+ }
+
+ spec->input_mux = &alc880_capture_source;
+ spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids);
+ spec->adc_nids = alc880_adc_nids;
+
+ codec->patch_ops = alc_patch_ops;
+
+ return 0;
+}
+
+/*
+ * ALC260 support
+ */
+
+/*
+ * This is just place-holder, so there's something for alc_build_pcms to look
+ * at when it calculates the maximum number of channels. ALC260 has no mixer
+ * element which allows changing the channel mode, so the verb list is
+ * never used.
+ */
+static struct alc_channel_mode alc260_modes[1] = {
+ { 2, NULL },
+};
+
+snd_kcontrol_new_t alc260_base_mixer[] = {
+ HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT),
+ /* use LINE2 for the output */
+ /* HDA_CODEC_MUTE("Front Playback Switch", 0x0f, 0x0, HDA_OUTPUT), */
+ HDA_CODEC_MUTE("Front Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+ 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_CODEC_MUTE("Headphone Playback Switch", 0x10, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x11, 1, 0x0, HDA_OUTPUT),
+ 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 struct hda_verb alc260_init_verbs[] = {
+ /* Line In pin widget for input */
+ {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
+ /* CD pin widget for input */
+ {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
+ /* 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-2 is used for line-out in rear */
+ {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+ /* select line-out */
+ {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
+ /* LINE-OUT pin */
+ {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+ /* enable HP */
+ {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+ /* enable Mono */
+ {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+ /* 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) */
+ {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+ /* 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, 0xb080},
+ /* unmute Mono mixer amp left and right (volume = 0) */
+ {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+ /* mute pin widget amp left and right (no gain on this amp) */
+ {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+ /* mute LINE-2 out */
+ {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+ /* 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_pcm_stream alc260_pcm_analog_playback = {
+ .substreams = 1,
+ .channels_min = 2,
+ .channels_max = 2,
+ .nid = 0x2,
+};
+
+static struct hda_pcm_stream alc260_pcm_analog_capture = {
+ .substreams = 1,
+ .channels_min = 2,
+ .channels_max = 2,
+ .nid = 0x4,
+};
+
+static int patch_alc260(struct hda_codec *codec)
+{
+ struct alc_spec *spec;
+
+ spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
+ if (spec == NULL)
+ return -ENOMEM;
+
+ codec->spec = spec;
+
+ spec->mixers[spec->num_mixers] = alc260_base_mixer;
+ spec->num_mixers++;
+
+ spec->init_verbs = alc260_init_verbs;
+ spec->channel_mode = alc260_modes;
+ spec->num_channel_mode = ARRAY_SIZE(alc260_modes);
+
+ 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;
+
+ spec->input_mux = &alc260_capture_source;
+ spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids);
+ spec->adc_nids = alc260_adc_nids;
+
+ codec->patch_ops = alc_patch_ops;
+
+ return 0;
+}
+
+/*
+ * ALC882 support
+ *
+ * ALC882 is almost identical with ALC880 but has cleaner and more flexible
+ * configuration. Each pin widget can choose any input DACs and a mixer.
+ * Each ADC is connected from a mixer of all inputs. This makes possible
+ * 6-channel independent captures.
+ *
+ * In addition, an independent DAC for the multi-playback (not used in this
+ * driver yet).
+ */
+
+static struct alc_channel_mode alc882_ch_modes[1] = {
+ { 8, NULL }
+};
+
+static hda_nid_t alc882_dac_nids[4] = {
+ /* front, rear, clfe, rear_surr */
+ 0x02, 0x03, 0x04, 0x05
+};
+
+static hda_nid_t alc882_adc_nids[3] = {
+ /* ADC0-2 */
+ 0x07, 0x08, 0x09,
+};
+
+/* input MUX */
+/* FIXME: should be a matrix-type input source selection */
+
+static struct hda_input_mux alc882_capture_source = {
+ .num_items = 4,
+ .items = {
+ { "Mic", 0x0 },
+ { "Front Mic", 0x1 },
+ { "Line", 0x2 },
+ { "CD", 0x4 },
+ },
+};
+
+#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)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct alc_spec *spec = codec->spec;
+ const struct hda_input_mux *imux = spec->input_mux;
+ unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
+ static hda_nid_t capture_mixers[3] = { 0x24, 0x23, 0x22 };
+ hda_nid_t nid = capture_mixers[adc_idx];
+ unsigned int *cur_val = &spec->cur_mux[adc_idx];
+ unsigned int i, idx;
+
+ idx = ucontrol->value.enumerated.item[0];
+ if (idx >= imux->num_items)
+ idx = imux->num_items - 1;
+ if (*cur_val == idx && ! codec->in_resume)
+ return 0;
+ for (i = 0; i < imux->num_items; i++) {
+ unsigned int v = (i == idx) ? 0x7000 : 0x7080;
+ snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+ v | (imux->items[i].index << 8));
+ }
+ *cur_val = idx;
+ return 1;
+}
+
+/* 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[] = {
+ HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x16, 1, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Side Playback Switch", 0x17, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 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, 0x1, HDA_INPUT),
+ HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+ HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
+ HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
+ 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,
+ /* .name = "Capture Source", */
+ .name = "Input Source",
+ .count = 3,
+ .info = alc882_mux_enum_info,
+ .get = alc882_mux_enum_get,
+ .put = alc882_mux_enum_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, 0xb000},
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+ /* Rear mixer */
+ {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+ {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+ /* CLFE mixer */
+ {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+ {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+ /* Side mixer */
+ {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+ {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+
+ /* Front Pin: to output mode */
+ {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+ /* Front Pin: mute amp left and right (no volume) */
+ {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
+ /* select Front mixer (0x0c, index 0) */
+ {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
+ /* Rear Pin */
+ {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+ /* Rear Pin: mute amp left and right (no volume) */
+ {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
+ /* select Rear mixer (0x0d, index 1) */
+ {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
+ /* CLFE Pin */
+ {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+ /* CLFE Pin: mute amp left and right (no volume) */
+ {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
+ /* select CLFE mixer (0x0e, index 2) */
+ {0x16, AC_VERB_SET_CONNECT_SEL, 0x02},
+ /* Side Pin */
+ {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+ /* Side Pin: mute amp left and right (no volume) */
+ {0x17, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
+ /* select Side mixer (0x0f, index 3) */
+ {0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
+ /* Headphone Pin */
+ {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+ /* Headphone Pin: mute amp left and right (no volume) */
+ {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
+ /* select Front mixer (0x0c, index 0) */
+ {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
+ /* Mic (rear) pin widget for input and vref at 80% */
+ {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
+ /* Front Mic pin widget for input and vref at 80% */
+ {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
+ /* Line In pin widget for input */
+ {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
+ /* CD pin widget for input */
+ {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
+
+ /* 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))},
+ /* ADC1: unmute amp left and right */
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
+ /* ADC2: unmute amp left and right */
+ {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
+ /* ADC3: unmute amp left and right */
+ {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
+
+ /* Unmute front loopback */
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+ /* Unmute rear loopback */
+ {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+ /* Mute CLFE loopback */
+ {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8))},
+ /* Unmute side loopback */
+ {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+
+ { }
+};
+
+static int patch_alc882(struct hda_codec *codec)
+{
+ struct alc_spec *spec;
+
+ spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
+ if (spec == NULL)
+ return -ENOMEM;
+
+ codec->spec = spec;
+
+ spec->mixers[spec->num_mixers] = alc882_base_mixer;
+ spec->num_mixers++;
+
+ spec->multiout.dig_out_nid = ALC880_DIGOUT_NID;
+ spec->dig_in_nid = ALC880_DIGIN_NID;
+ spec->front_panel = 1;
+ spec->init_verbs = alc882_init_verbs;
+ spec->channel_mode = alc882_ch_modes;
+ spec->num_channel_mode = ARRAY_SIZE(alc882_ch_modes);
+
+ spec->stream_name_analog = "ALC882 Analog";
+ spec->stream_analog_playback = &alc880_pcm_analog_playback;
+ spec->stream_analog_capture = &alc880_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->multiout.max_channels = spec->channel_mode[0].channels;
+ spec->multiout.num_dacs = ARRAY_SIZE(alc882_dac_nids);
+ spec->multiout.dac_nids = alc882_dac_nids;
+
+ spec->input_mux = &alc882_capture_source;
+ spec->num_adc_nids = ARRAY_SIZE(alc882_adc_nids);
+ spec->adc_nids = alc882_adc_nids;
+
+ codec->patch_ops = alc_patch_ops;
+
+ return 0;
+}
+
+/*
+ * patch entries
+ */
+struct hda_codec_preset snd_hda_preset_realtek[] = {
+ { .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 },
+ { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 },
+ { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 },
+ {} /* terminator */
+};
diff --git a/sound/pci/ice1712/Makefile b/sound/pci/ice1712/Makefile
index 8b5e37cf8c6ee..7837cef8855c2 100644
--- a/sound/pci/ice1712/Makefile
+++ b/sound/pci/ice1712/Makefile
@@ -5,7 +5,7 @@
snd-ice17xx-ak4xxx-objs := ak4xxx.o
snd-ice1712-objs := ice1712.o delta.o hoontech.o ews.o
-snd-ice1724-objs := ice1724.o amp.o revo.o aureon.o vt1720_mobo.o pontis.o prodigy192.o
+snd-ice1724-objs := ice1724.o amp.o revo.o aureon.o vt1720_mobo.o pontis.o prodigy192.o juli.o phase.o
# Toplevel Module Dependency
obj-$(CONFIG_SND_ICE1712) += snd-ice1712.o snd-ice17xx-ak4xxx.o
diff --git a/sound/pci/ice1712/ak4xxx.c b/sound/pci/ice1712/ak4xxx.c
index 3c6129f320e6e..ae9dc029ba0d2 100644
--- a/sound/pci/ice1712/ak4xxx.c
+++ b/sound/pci/ice1712/ak4xxx.c
@@ -126,12 +126,16 @@ int snd_ice1712_akm4xxx_init(akm4xxx_t *ak, const akm4xxx_t *temp,
{
struct snd_ak4xxx_private *priv;
- priv = kmalloc(sizeof(*priv), GFP_KERNEL);
- if (priv == NULL)
- return -ENOMEM;
+ if (_priv != NULL) {
+ priv = kmalloc(sizeof(*priv), GFP_KERNEL);
+ if (priv == NULL)
+ return -ENOMEM;
+ *priv = *_priv;
+ } else {
+ priv = NULL;
+ }
*ak = *temp;
ak->card = ice->card;
- *priv = *_priv;
ak->private_value[0] = (unsigned long)priv;
ak->private_data[0] = ice;
if (ak->ops.lock == NULL)
diff --git a/sound/pci/ice1712/envy24ht.h b/sound/pci/ice1712/envy24ht.h
index 375e5fb00c878..f7878020eaa30 100644
--- a/sound/pci/ice1712/envy24ht.h
+++ b/sound/pci/ice1712/envy24ht.h
@@ -106,7 +106,7 @@ enum {
#define VT1724_REG_I2C_BYTE_ADDR 0x11 /* byte */
#define VT1724_REG_I2C_DATA 0x12 /* byte */
#define VT1724_REG_I2C_CTRL 0x13 /* byte */
-#define VT1724_I2C_EEPROM 0x80 /* EEPROM exists */
+#define VT1724_I2C_EEPROM 0x80 /* 1 = EEPROM exists */
#define VT1724_I2C_BUSY 0x01 /* busy bit */
#define VT1724_REG_GPIO_DATA 0x14 /* word */
diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c
index fddd9e0e5c430..79fba6be3503a 100644
--- a/sound/pci/ice1712/ice1712.c
+++ b/sound/pci/ice1712/ice1712.c
@@ -1014,21 +1014,9 @@ 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)
{
unsigned long flags;
- unsigned char val;
+ unsigned char val, old;
unsigned int i;
- spin_lock_irqsave(&ice->reg_lock, flags);
- if (inb(ICEMT(ice, PLAYBACK_CONTROL)) & (ICE1712_CAPTURE_START_SHADOW|
- ICE1712_PLAYBACK_PAUSE|
- ICE1712_PLAYBACK_START)) {
- spin_unlock_irqrestore(&ice->reg_lock, flags);
- return;
- }
- if (!force && is_pro_rate_locked(ice)) {
- spin_unlock_irqrestore(&ice->reg_lock, flags);
- return;
- }
-
switch (rate) {
case 8000: val = 6; break;
case 9600: val = 3; break;
@@ -1049,8 +1037,22 @@ static void snd_ice1712_set_pro_rate(ice1712_t *ice, unsigned int rate, int forc
rate = 48000;
break;
}
- outb(val, ICEMT(ice, RATE));
+ spin_lock_irqsave(&ice->reg_lock, flags);
+ if (inb(ICEMT(ice, PLAYBACK_CONTROL)) & (ICE1712_CAPTURE_START_SHADOW|
+ ICE1712_PLAYBACK_PAUSE|
+ ICE1712_PLAYBACK_START)) {
+ __out:
+ spin_unlock_irqrestore(&ice->reg_lock, flags);
+ return;
+ }
+ if (!force && is_pro_rate_locked(ice))
+ goto __out;
+
+ old = inb(ICEMT(ice, RATE));
+ if (!force && old == val)
+ goto __out;
+ outb(val, ICEMT(ice, RATE));
spin_unlock_irqrestore(&ice->reg_lock, flags);
if (ice->gpio.set_pro_rate)
@@ -2405,6 +2407,7 @@ static int __devinit snd_ice1712_chip_init(ice1712_t *ice)
udelay(200);
snd_ice1712_write(ice, ICE1712_IREG_CONSUMER_POWERDOWN, 0);
}
+ snd_ice1712_set_pro_rate(ice, 48000, 1);
return 0;
}
@@ -2545,6 +2548,7 @@ static int __devinit snd_ice1712_create(snd_card_t * card,
ice->cs8427_timeout = cs8427_timeout;
spin_lock_init(&ice->reg_lock);
init_MUTEX(&ice->gpio_mutex);
+ init_MUTEX(&ice->i2c_mutex);
init_MUTEX(&ice->open_mutex);
ice->gpio.set_mask = snd_ice1712_set_gpio_mask;
ice->gpio.set_dir = snd_ice1712_set_gpio_dir;
diff --git a/sound/pci/ice1712/ice1712.h b/sound/pci/ice1712/ice1712.h
index 4464dd8adf375..8bb1c58c26a00 100644
--- a/sound/pci/ice1712/ice1712.h
+++ b/sound/pci/ice1712/ice1712.h
@@ -27,6 +27,7 @@
#include <sound/rawmidi.h>
#include <sound/i2c.h>
#include <sound/ak4xxx-adda.h>
+#include <sound/ak4114.h>
#include <sound/pcm.h>
@@ -335,11 +336,13 @@ struct _snd_ice1712 {
struct semaphore open_mutex;
snd_pcm_substream_t *pcm_reserved[4];
+ snd_pcm_hw_constraint_list_t *hw_rates; /* card-specific rate constraints */
unsigned int akm_codecs;
akm4xxx_t *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 */
unsigned int cs8427_timeout; /* CS8427 reset timeout in HZ/100 */
@@ -355,12 +358,13 @@ struct _snd_ice1712 {
unsigned int (*get_data)(ice1712_t *ice);
/* misc operators - move to another place? */
void (*set_pro_rate)(ice1712_t *ice, unsigned int rate);
+ void (*i2s_mclk_changed)(ice1712_t *ice);
} gpio;
struct semaphore gpio_mutex;
/* other board-specific data */
union {
- /* additional i2c devices for EWS boards*/
+ /* additional i2c devices for EWS boards */
snd_i2c_device_t *i2cdevs[3];
/* AC97 register cache for Aureon */
struct aureon_spec {
@@ -375,6 +379,10 @@ struct _snd_ice1712 {
unsigned int config;
unsigned short boxconfig[4];
} hoontech;
+ struct {
+ ak4114_t *ak4114;
+ unsigned int analog: 1;
+ } juli;
} spec;
};
@@ -477,7 +485,7 @@ struct snd_ice1712_card_info {
char *driver;
int (*chip_init)(ice1712_t *);
int (*build_controls)(ice1712_t *);
- int no_mpu401: 1;
+ 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 ce70e510a4504..95500f06f0c62 100644
--- a/sound/pci/ice1712/ice1724.c
+++ b/sound/pci/ice1712/ice1724.c
@@ -47,6 +47,8 @@
#include "vt1720_mobo.h"
#include "pontis.h"
#include "prodigy192.h"
+#include "juli.h"
+#include "phase.h"
MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
@@ -59,6 +61,8 @@ MODULE_SUPPORTED_DEVICE("{"
VT1720_MOBO_DEVICE_DESC
PONTIS_DEVICE_DESC
PRODIGY192_DEVICE_DESC
+ JULI_DEVICE_DESC
+ PHASE_DEVICE_DESC
"{VIA,VT1720},"
"{VIA,VT1724},"
"{ICEnsemble,Generic ICE1724},"
@@ -401,23 +405,11 @@ static void snd_vt1724_set_pro_rate(ice1712_t *ice, unsigned int rate, int force
{
unsigned long flags;
unsigned char val, old;
- unsigned int i;
+ unsigned int i, mclk_change;
if (rate > get_max_rate(ice))
return;
- spin_lock_irqsave(&ice->reg_lock, flags);
- if ((inb(ICEMT1724(ice, DMA_CONTROL)) & DMA_STARTS) ||
- (inb(ICEMT1724(ice, DMA_PAUSE)) & DMA_PAUSES)) {
- /* running? we cannot change the rate now... */
- spin_unlock_irqrestore(&ice->reg_lock, flags);
- return;
- }
- if (!force && is_pro_rate_locked(ice)) {
- spin_unlock_irqrestore(&ice->reg_lock, flags);
- return;
- }
-
switch (rate) {
case 8000: val = 6; break;
case 9600: val = 3; break;
@@ -439,8 +431,21 @@ static void snd_vt1724_set_pro_rate(ice1712_t *ice, unsigned int rate, int force
val = 0;
break;
}
+
+ spin_lock_irqsave(&ice->reg_lock, flags);
+ if ((inb(ICEMT1724(ice, DMA_CONTROL)) & DMA_STARTS) ||
+ (inb(ICEMT1724(ice, DMA_PAUSE)) & DMA_PAUSES)) {
+ /* running? we cannot change the rate now... */
+ spin_unlock_irqrestore(&ice->reg_lock, flags);
+ return;
+ }
+ if (!force && is_pro_rate_locked(ice)) {
+ spin_unlock_irqrestore(&ice->reg_lock, flags);
+ return;
+ }
+
old = inb(ICEMT1724(ice, RATE));
- if (old != val)
+ if (force || old != val)
outb(val, ICEMT1724(ice, RATE));
else if (rate == ice->cur_rate) {
spin_unlock_irqrestore(&ice->reg_lock, flags);
@@ -450,6 +455,7 @@ static void snd_vt1724_set_pro_rate(ice1712_t *ice, unsigned int rate, int force
ice->cur_rate = rate;
/* check MT02 */
+ mclk_change = 0;
if (ice->eeprom.data[ICE_EEP2_ACLINK] & VT1724_CFG_PRO_I2S) {
val = old = inb(ICEMT1724(ice, I2S_FORMAT));
if (rate > 96000)
@@ -458,25 +464,23 @@ static void snd_vt1724_set_pro_rate(ice1712_t *ice, unsigned int rate, int force
val &= ~VT1724_MT_I2S_MCLK_128X; /* 256x MCLK */
if (val != old) {
outb(val, ICEMT1724(ice, I2S_FORMAT));
- if (ice->eeprom.subvendor == VT1724_SUBDEVICE_REVOLUTION71) {
- /* FIXME: is this revo only? */
- /* assert PRST# to converters; MT05 bit 7 */
- outb(inb(ICEMT1724(ice, AC97_CMD)) | 0x80, ICEMT1724(ice, AC97_CMD));
- spin_unlock_irqrestore(&ice->reg_lock, flags);
- mdelay(5);
- spin_lock_irqsave(&ice->reg_lock, flags);
- /* deassert PRST# */
- outb(inb(ICEMT1724(ice, AC97_CMD)) & ~0x80, ICEMT1724(ice, AC97_CMD));
- }
+ mclk_change = 1;
}
}
spin_unlock_irqrestore(&ice->reg_lock, flags);
+ if (mclk_change && ice->gpio.i2s_mclk_changed)
+ ice->gpio.i2s_mclk_changed(ice);
+ if (ice->gpio.set_pro_rate)
+ ice->gpio.set_pro_rate(ice, rate);
+
/* set up codecs */
for (i = 0; i < ice->akm_codecs; i++) {
if (ice->akm[i].ops.set_rate_val)
ice->akm[i].ops.set_rate_val(&ice->akm[i], rate);
}
+ if (ice->spdif.ops.setup_rate)
+ ice->spdif.ops.setup_rate(ice, rate);
}
static int snd_vt1724_pcm_hw_params(snd_pcm_substream_t * substream,
@@ -714,6 +718,13 @@ static snd_pcm_hardware_t snd_vt1724_2ch_stereo =
static int set_rate_constraints(ice1712_t *ice, snd_pcm_substream_t *substream)
{
snd_pcm_runtime_t *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);
+ }
if (ice->eeprom.data[ICE_EEP2_ACLINK] & VT1724_CFG_PRO_I2S) {
/* I2S */
/* VT1720 doesn't support more than 96kHz */
@@ -1866,6 +1877,8 @@ static struct snd_ice1712_card_info *card_tables[] __devinitdata = {
snd_vt1720_mobo_cards,
snd_vt1720_pontis_cards,
snd_vt1724_prodigy192_cards,
+ snd_vt1724_juli_cards,
+ snd_vt1724_phase_cards,
NULL,
};
@@ -1878,23 +1891,34 @@ static void wait_i2c_busy(ice1712_t *ice)
int t = 0x10000;
while ((inb(ICEREG1724(ice, I2C_CTRL)) & VT1724_I2C_BUSY) && t--)
;
+ if (t == -1)
+ 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 val;
+
+ down(&ice->i2c_mutex);
outb(addr, ICEREG1724(ice, I2C_BYTE_ADDR));
outb(dev & ~VT1724_I2C_WRITE, ICEREG1724(ice, I2C_DEV_ADDR));
wait_i2c_busy(ice);
- return inb(ICEREG1724(ice, I2C_DATA));
+ val = inb(ICEREG1724(ice, I2C_DATA));
+ up(&ice->i2c_mutex);
+ //printk("i2c_read: [0x%x,0x%x] = 0x%x\n", dev, addr, val);
+ return val;
}
void snd_vt1724_write_i2c(ice1712_t *ice, unsigned char dev, unsigned char addr, unsigned char data)
{
+ down(&ice->i2c_mutex);
wait_i2c_busy(ice);
+ //printk("i2c_write: [0x%x,0x%x] = 0x%x\n", dev, addr, data);
outb(addr, ICEREG1724(ice, I2C_BYTE_ADDR));
outb(data, ICEREG1724(ice, I2C_DATA));
outb(dev | VT1724_I2C_WRITE, ICEREG1724(ice, I2C_DEV_ADDR));
wait_i2c_busy(ice);
+ up(&ice->i2c_mutex);
}
static int __devinit snd_vt1724_read_eeprom(ice1712_t *ice, const char *modelname)
@@ -1906,7 +1930,8 @@ static int __devinit snd_vt1724_read_eeprom(ice1712_t *ice, const char *modelnam
if (! modelname || ! *modelname) {
ice->eeprom.subvendor = 0;
if ((inb(ICEREG1724(ice, I2C_CTRL)) & VT1724_I2C_EEPROM) != 0)
- ice->eeprom.subvendor = (snd_vt1724_read_i2c(ice, dev, 0x00) << 0) |
+ ice->eeprom.subvendor =
+ (snd_vt1724_read_i2c(ice, dev, 0x00) << 0) |
(snd_vt1724_read_i2c(ice, dev, 0x01) << 8) |
(snd_vt1724_read_i2c(ice, dev, 0x02) << 16) |
(snd_vt1724_read_i2c(ice, dev, 0x03) << 24);
@@ -2114,6 +2139,7 @@ static int __devinit snd_vt1724_create(snd_card_t * card,
spin_lock_init(&ice->reg_lock);
init_MUTEX(&ice->gpio_mutex);
init_MUTEX(&ice->open_mutex);
+ init_MUTEX(&ice->i2c_mutex);
ice->gpio.set_mask = snd_vt1724_set_gpio_mask;
ice->gpio.set_dir = snd_vt1724_set_gpio_dir;
ice->gpio.set_data = snd_vt1724_set_gpio_data;
diff --git a/sound/pci/ice1712/juli.c b/sound/pci/ice1712/juli.c
new file mode 100644
index 0000000000000..3fb297b969cd7
--- /dev/null
+++ b/sound/pci/ice1712/juli.c
@@ -0,0 +1,230 @@
+/*
+ * ALSA driver for ICEnsemble VT1724 (Envy24HT)
+ *
+ * Lowlevel functions for ESI Juli@ cards
+ *
+ * Copyright (c) 2004 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <sound/driver.h>
+#include <asm/io.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+
+#include "ice1712.h"
+#include "envy24ht.h"
+#include "juli.h"
+
+/*
+ * chip addresses on I2C bus
+ */
+#define AK4114_ADDR 0x20 /* S/PDIF receiver */
+#define AK4358_ADDR 0x22 /* DAC */
+
+/*
+ * GPIO pins
+ */
+#define GPIO_FREQ_MASK (3<<0)
+#define GPIO_FREQ_32KHZ (0<<0)
+#define GPIO_FREQ_44KHZ (1<<0)
+#define GPIO_FREQ_48KHZ (2<<0)
+#define GPIO_MULTI_MASK (3<<2)
+#define GPIO_MULTI_4X (0<<2)
+#define GPIO_MULTI_2X (1<<2)
+#define GPIO_MULTI_1X (2<<2) /* also external */
+#define GPIO_MULTI_HALF (3<<2)
+#define GPIO_INTERNAL_CLOCK (1<<4)
+#define GPIO_ANALOG_PRESENT (1<<5) /* RO only: 0 = present */
+#define GPIO_RXMCLK_SEL (1<<7) /* must be 0 */
+#define GPIO_AK5385A_CKS0 (1<<8)
+#define GPIO_AK5385A_DFS0 (1<<9) /* swapped with DFS1 according doc? */
+#define GPIO_AK5385A_DFS1 (1<<10)
+#define GPIO_DIGOUT_MONITOR (1<<11) /* 1 = active */
+#define GPIO_DIGIN_MONITOR (1<<12) /* 1 = active */
+#define GPIO_ANAIN_MONITOR (1<<13) /* 1 = active */
+#define GPIO_AK5385A_MCLK (1<<14) /* must be 0 */
+#define GPIO_MUTE_CONTROL (1<<15) /* 0 = off, 1 = on */
+
+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);
+}
+
+static unsigned char juli_ak4114_read(void *private_data, unsigned char reg)
+{
+ return snd_vt1724_read_i2c((ice1712_t *)private_data, AK4114_ADDR, reg);
+}
+
+/*
+ * AK4358 section
+ */
+
+static void juli_akm_lock(akm4xxx_t *ak, int chip)
+{
+}
+
+static void juli_akm_unlock(akm4xxx_t *ak, int chip)
+{
+}
+
+static void juli_akm_write(akm4xxx_t *ak, int chip,
+ unsigned char addr, unsigned char data)
+{
+ ice1712_t *ice = ak->private_data[0];
+
+ snd_assert(chip == 0, return);
+ snd_vt1724_write_i2c(ice, AK4358_ADDR, addr, data);
+}
+
+/*
+ * change the rate of envy24HT, AK4358
+ */
+static void juli_akm_set_rate_val(akm4xxx_t *ak, unsigned int rate)
+{
+ unsigned char old, tmp, dfs;
+
+ if (rate == 0) /* no hint - S/PDIF input is master, simply return */
+ return;
+
+ /* adjust DFS on codecs */
+ if (rate > 96000)
+ dfs = 2;
+ else if (rate > 48000)
+ dfs = 1;
+ else
+ dfs = 0;
+
+ tmp = snd_akm4xxx_get(ak, 0, 2);
+ old = (tmp >> 4) & 0x03;
+ if (old == dfs)
+ return;
+ /* reset DFS */
+ snd_akm4xxx_reset(ak, 1);
+ tmp = snd_akm4xxx_get(ak, 0, 2);
+ tmp &= ~(0x03 << 4);
+ tmp |= dfs << 4;
+ snd_akm4xxx_set(ak, 0, 2, tmp);
+ snd_akm4xxx_reset(ak, 0);
+}
+
+static akm4xxx_t akm_juli_dac __devinitdata = {
+ .type = SND_AK4358,
+ .num_dacs = 2,
+ .ops = {
+ .lock = juli_akm_lock,
+ .unlock = juli_akm_unlock,
+ .write = juli_akm_write,
+ .set_rate_val = juli_akm_set_rate_val
+ }
+};
+
+static int __devinit juli_add_controls(ice1712_t *ice)
+{
+ return snd_ice1712_akm4xxx_build_controls(ice);
+}
+
+/*
+ * initialize the chip
+ */
+static int __devinit juli_init(ice1712_t *ice)
+{
+ static unsigned char ak4114_init_vals[] = {
+ /* AK4117_REG_PWRDN */ AK4114_RST | AK4114_PWN | AK4114_OCKS0 | AK4114_OCKS1,
+ /* AK4114_REQ_FORMAT */ AK4114_DIF_I24I2S,
+ /* AK4114_REG_IO0 */ AK4114_TX1E,
+ /* AK4114_REG_IO1 */ AK4114_EFH_1024 | AK4114_DIT | AK4114_IPS(1),
+ /* AK4114_REG_INT0_MASK */ 0,
+ /* AK4114_REG_INT1_MASK */ 0
+ };
+ static unsigned char ak4114_init_txcsb[] = {
+ 0x41, 0x02, 0x2c, 0x00, 0x00
+ };
+ int err;
+ akm4xxx_t *ak;
+
+#if 0
+ for (err = 0; err < 0x20; err++)
+ juli_ak4114_read(ice, err);
+ juli_ak4114_write(ice, 0, 0x0f);
+ juli_ak4114_read(ice, 0);
+ juli_ak4114_read(ice, 1);
+#endif
+ err = snd_ak4114_create(ice->card,
+ juli_ak4114_read,
+ juli_ak4114_write,
+ ak4114_init_vals, ak4114_init_txcsb,
+ ice, &ice->spec.juli.ak4114);
+ if (err < 0)
+ return err;
+
+ ice->spec.juli.analog = ice->gpio.get_data(ice) & GPIO_ANALOG_PRESENT;
+
+ 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 = kcalloc(1, sizeof(akm4xxx_t), GFP_KERNEL);
+ if (! ak)
+ return -ENOMEM;
+ ice->akm_codecs = 1;
+ if ((err = snd_ice1712_akm4xxx_init(ak, &akm_juli_dac, NULL, ice)) < 0)
+ return err;
+ }
+
+ return 0;
+}
+
+
+/*
+ * Juli@ boards don't provide the EEPROM data except for the vendor IDs.
+ * hence the driver needs to sets up it properly.
+ */
+
+static unsigned char juli_eeprom[] __devinitdata = {
+ 0x20, /* SYSCONF: clock 512, mpu401, 1xADC, 1xDACs */
+ 0x80, /* ACLINK: I2S */
+ 0xf8, /* I2S: vol, 96k, 24bit, 192k */
+ 0xc3, /* SPDIF: out-en, out-int, spdif-in */
+ 0x9f, /* GPIO_DIR */
+ 0xff, /* GPIO_DIR1 */
+ 0x7f, /* GPIO_DIR2 */
+ 0x9f, /* GPIO_MASK */
+ 0xff, /* GPIO_MASK1 */
+ 0x7f, /* GPIO_MASK2 */
+ 0x16, /* GPIO_STATE: internal clock, multiple 1x, 48kHz */
+ 0x80, /* GPIO_STATE1: mute */
+ 0x00, /* GPIO_STATE2 */
+};
+
+/* entry point */
+struct snd_ice1712_card_info snd_vt1724_juli_cards[] __devinitdata = {
+ {
+ .subvendor = VT1724_SUBDEVICE_JULI,
+ .name = "ESI Juli@",
+ .model = "juli",
+ .chip_init = juli_init,
+ .build_controls = juli_add_controls,
+ .eeprom_size = sizeof(juli_eeprom),
+ .eeprom_data = juli_eeprom,
+ },
+ { } /* terminator */
+};
diff --git a/sound/pci/ice1712/juli.h b/sound/pci/ice1712/juli.h
new file mode 100644
index 0000000000000..d9f8534fd92ee
--- /dev/null
+++ b/sound/pci/ice1712/juli.h
@@ -0,0 +1,10 @@
+#ifndef __SOUND_JULI_H
+#define __SOUND_JULI_H
+
+#define JULI_DEVICE_DESC "{ESI,Juli@},"
+
+#define VT1724_SUBDEVICE_JULI 0x31305345 /* Juli@ */
+
+extern struct snd_ice1712_card_info snd_vt1724_juli_cards[];
+
+#endif /* __SOUND_JULI_H */
diff --git a/sound/pci/ice1712/phase.c b/sound/pci/ice1712/phase.c
new file mode 100644
index 0000000000000..d1f90832443c4
--- /dev/null
+++ b/sound/pci/ice1712/phase.c
@@ -0,0 +1,138 @@
+/*
+ * ALSA driver for ICEnsemble ICE1724 (Envy24)
+ *
+ * Lowlevel functions for Terratec PHASE 22
+ *
+ * Copyright (c) 2005 Misha Zhilin <misha@epiphan.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
+ *
+ */
+
+/* PHASE 22 overview:
+ * Audio controller: VIA Envy24HT-S (slightly trimmed down version of Envy24HT)
+ * Analog chip: AK4524 (partially via Philip's 74HCT125)
+ * Digital receiver: CS8414-CS (not supported in this release)
+ *
+ * Envy connects to AK4524
+ * - CS directly from GPIO 10
+ * - CCLK via 74HCT125's gate #4 from GPIO 4
+ * - CDTI via 74HCT125's gate #2 from GPIO 5
+ * CDTI may be completely blocked by 74HCT125's gate #1 controlled by GPIO 3
+ */
+
+#include <sound/driver.h>
+#include <asm/io.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+
+#include "ice1712.h"
+#include "envy24ht.h"
+#include "phase.h"
+
+static akm4xxx_t akm_phase22 __devinitdata = {
+ .type = SND_AK4524,
+ .num_dacs = 2,
+ .num_adcs = 2,
+};
+
+static struct snd_ak4xxx_private akm_phase22_priv __devinitdata = {
+ .caddr = 2,
+ .cif = 1,
+ .data_mask = 1 << 4,
+ .clk_mask = 1 << 5,
+ .cs_mask = 1 << 10,
+ .cs_addr = 1 << 10,
+ .cs_none = 0,
+ .add_flags = 1 << 3,
+ .mask_flags = 0,
+};
+
+static int __devinit phase22_init(ice1712_t *ice)
+{
+ akm4xxx_t *ak;
+ int err;
+
+ // Configure DAC/ADC description for generic part of ice1724
+ switch (ice->eeprom.subvendor) {
+ case VT1724_SUBDEVICE_PHASE22:
+ ice->num_total_dacs = 2;
+ ice->num_total_adcs = 2;
+ ice->vt1720 = 1; // Envy24HT-S have 16 bit wide GPIO
+ break;
+ default:
+ snd_BUG();
+ return -EINVAL;
+ }
+
+ // Initialize analog chips
+ ak = ice->akm = kcalloc(1, sizeof(akm4xxx_t), GFP_KERNEL);
+ if (! ak)
+ return -ENOMEM;
+ ice->akm_codecs = 1;
+ switch (ice->eeprom.subvendor) {
+ case VT1724_SUBDEVICE_PHASE22:
+ if ((err = snd_ice1712_akm4xxx_init(ak, &akm_phase22, &akm_phase22_priv, ice)) < 0)
+ return err;
+ break;
+ }
+
+ return 0;
+}
+
+static int __devinit phase22_add_controls(ice1712_t *ice)
+{
+ int err = 0;
+
+ switch (ice->eeprom.subvendor) {
+ case VT1724_SUBDEVICE_PHASE22:
+ err = snd_ice1712_akm4xxx_build_controls(ice);
+ if (err < 0)
+ return err;
+ }
+ return 0;
+}
+
+static unsigned char phase22_eeprom[] __devinitdata = {
+ 0x00, /* SYSCONF: 1xADC, 1xDACs */
+ 0x80, /* ACLINK: I2S */
+ 0xf8, /* I2S: vol, 96k, 24bit*/
+ 0xc3, /* SPDIF: out-en, out-int, spdif-in */
+ 0xFF, /* GPIO_DIR */
+ 0xFF, /* GPIO_DIR1 */
+ 0xFF, /* GPIO_DIR2 */
+ 0x00, /* GPIO_MASK */
+ 0x00, /* GPIO_MASK1 */
+ 0x00, /* GPIO_MASK2 */
+ 0x00, /* GPIO_STATE: */
+ 0x00, /* GPIO_STATE1: */
+ 0x00, /* GPIO_STATE2 */
+};
+
+struct snd_ice1712_card_info snd_vt1724_phase_cards[] __devinitdata = {
+ {
+ .subvendor = VT1724_SUBDEVICE_PHASE22,
+ .name = "Terratec PHASE 22",
+ .model = "phase22",
+ .chip_init = phase22_init,
+ .build_controls = phase22_add_controls,
+ .eeprom_size = sizeof(phase22_eeprom),
+ .eeprom_data = phase22_eeprom,
+ },
+ { } /* terminator */
+};
diff --git a/sound/pci/ice1712/phase.h b/sound/pci/ice1712/phase.h
new file mode 100644
index 0000000000000..6230cf16989f7
--- /dev/null
+++ b/sound/pci/ice1712/phase.h
@@ -0,0 +1,34 @@
+#ifndef __SOUND_PHASE_H
+#define __SOUND_PHASE_H
+
+/*
+ * ALSA driver for ICEnsemble ICE1712 (Envy24)
+ *
+ * Lowlevel functions for Terratec PHASE 22
+ *
+ * Copyright (c) 2005 Misha Zhilin <misha@epiphan.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
+ *
+ */
+
+#define PHASE_DEVICE_DESC "{Terratec,Phase 22},"
+
+#define VT1724_SUBDEVICE_PHASE22 0x3b155011
+
+/* entry point */
+extern struct snd_ice1712_card_info snd_vt1724_phase_cards[];
+
+#endif /* __SOUND_PHASE */
diff --git a/sound/pci/ice1712/prodigy192.c b/sound/pci/ice1712/prodigy192.c
index c8f59a24db034..d2c5963795d70 100644
--- a/sound/pci/ice1712/prodigy192.c
+++ b/sound/pci/ice1712/prodigy192.c
@@ -36,12 +36,12 @@
#include "prodigy192.h"
#include "stac946x.h"
-static void stac9460_put(ice1712_t *ice, int reg, unsigned char val)
+static inline void stac9460_put(ice1712_t *ice, int reg, unsigned char val)
{
snd_vt1724_write_i2c(ice, PRODIGY192_STAC9460_ADDR, reg, val);
}
-static unsigned char stac9460_get(ice1712_t *ice, int reg)
+static inline unsigned char stac9460_get(ice1712_t *ice, int reg)
{
return snd_vt1724_read_i2c(ice, PRODIGY192_STAC9460_ADDR, reg);
}
diff --git a/sound/pci/ice1712/revo.c b/sound/pci/ice1712/revo.c
index 82db619b22b65..d48d42524ac50 100644
--- a/sound/pci/ice1712/revo.c
+++ b/sound/pci/ice1712/revo.c
@@ -33,6 +33,15 @@
#include "envy24ht.h"
#include "revo.h"
+static void revo_i2s_mclk_changed(ice1712_t *ice)
+{
+ /* assert PRST# to converters; MT05 bit 7 */
+ outb(inb(ICEMT1724(ice, AC97_CMD)) | 0x80, ICEMT1724(ice, AC97_CMD));
+ mdelay(5);
+ /* deassert PRST# */
+ outb(inb(ICEMT1724(ice, AC97_CMD)) & ~0x80, ICEMT1724(ice, AC97_CMD));
+}
+
/*
* change the rate of envy24HT, AK4355 and AK4381
*/
@@ -119,6 +128,17 @@ static struct snd_ak4xxx_private akm_revo_surround_priv __devinitdata = {
.mask_flags = 0,
};
+static unsigned int rates[] = {
+ 32000, 44100, 48000, 64000, 88200, 96000,
+ 176400, 192000,
+};
+
+static snd_pcm_hw_constraint_list_t revo_rates = {
+ .count = ARRAY_SIZE(rates),
+ .list = rates,
+ .mask = 0,
+};
+
static int __devinit revo_init(ice1712_t *ice)
{
akm4xxx_t *ak;
@@ -135,6 +155,8 @@ static int __devinit revo_init(ice1712_t *ice)
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);
if (! ak)
@@ -151,6 +173,8 @@ static int __devinit revo_init(ice1712_t *ice)
break;
}
+ ice->hw_rates = &revo_rates; /* AK codecs don't support lower than 32k */
+
return 0;
}
diff --git a/sound/pci/ice1712/vt1720_mobo.c b/sound/pci/ice1712/vt1720_mobo.c
index 868f6fe33389e..3bd92627231c6 100644
--- a/sound/pci/ice1712/vt1720_mobo.c
+++ b/sound/pci/ice1712/vt1720_mobo.c
@@ -101,6 +101,15 @@ struct snd_ice1712_card_info snd_vt1720_mobo_cards[] __devinitdata = {
.eeprom_size = sizeof(k8x800_eeprom),
.eeprom_data = k8x800_eeprom,
},
+ {
+ .subvendor = VT1720_SUBDEVICE_9CJS,
+ .name = "Chaintech 9CJS",
+ /* identical with k8x800 */
+ .chip_init = k8x800_init,
+ .build_controls = k8x800_add_controls,
+ .eeprom_size = sizeof(k8x800_eeprom),
+ .eeprom_data = k8x800_eeprom,
+ },
{ } /* terminator */
};
diff --git a/sound/pci/ice1712/vt1720_mobo.h b/sound/pci/ice1712/vt1720_mobo.h
index 552be2ce763e7..f949eb804cae0 100644
--- a/sound/pci/ice1712/vt1720_mobo.h
+++ b/sound/pci/ice1712/vt1720_mobo.h
@@ -26,11 +26,13 @@
#define VT1720_MOBO_DEVICE_DESC "{Albatron,K8X800 Pro II},"\
"{Chaintech,ZNF3-150},"\
- "{Chaintech,ZNF3-250},"
+ "{Chaintech,ZNF3-250},"\
+ "{Chaintech,9CJS},"
#define VT1720_SUBDEVICE_K8X800 0xf217052c
#define VT1720_SUBDEVICE_ZNF3_150 0x0f2741f6
#define VT1720_SUBDEVICE_ZNF3_250 0x0f2745f6
+#define VT1720_SUBDEVICE_9CJS 0x0f272327
extern struct snd_ice1712_card_info snd_vt1720_mobo_cards[];
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
index aeaf1651d2f9c..0eb940da9d175 100644
--- a/sound/pci/intel8x0.c
+++ b/sound/pci/intel8x0.c
@@ -118,8 +118,8 @@ MODULE_PARM_DESC(xbox, "Set to 1 for Xbox, if you have problems with the AC'97 c
#ifndef PCI_DEVICE_ID_INTEL_ESB_5
#define PCI_DEVICE_ID_INTEL_ESB_5 0x25a6
#endif
-#ifndef PCI_DEVICE_ID_INTEL_ICH6_3
-#define PCI_DEVICE_ID_INTEL_ICH6_3 0x266e
+#ifndef PCI_DEVICE_ID_INTEL_ICH6_18
+#define PCI_DEVICE_ID_INTEL_ICH6_18 0x266e
#endif
#ifndef PCI_DEVICE_ID_INTEL_ICH7_20
#define PCI_DEVICE_ID_INTEL_ICH7_20 0x27de
@@ -1059,7 +1059,7 @@ static snd_pcm_uframes_t snd_intel8x0_pcm_pointer(snd_pcm_substream_t * substrea
intel8x0_t *chip = snd_pcm_substream_chip(substream);
ichdev_t *ichdev = get_ichdev(substream);
size_t ptr1, ptr;
- int civ, timeout = 10;
+ int civ, timeout = 100;
unsigned int position;
spin_lock(&chip->reg_lock);
@@ -1067,8 +1067,10 @@ static snd_pcm_uframes_t snd_intel8x0_pcm_pointer(snd_pcm_substream_t * substrea
civ = igetbyte(chip, ichdev->reg_offset + ICH_REG_OFF_CIV);
ptr1 = igetword(chip, ichdev->reg_offset + ichdev->roff_picb);
position = ichdev->position;
- if (ptr1 == 0)
- udelay(1);
+ if (ptr1 == 0) {
+ udelay(10);
+ continue;
+ }
if (civ == igetbyte(chip, ichdev->reg_offset + ICH_REG_OFF_CIV) &&
ptr1 == igetword(chip, ichdev->reg_offset + ichdev->roff_picb))
break;
@@ -1761,6 +1763,12 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = {
},
{
.vendor = 0x1028,
+ .device = 0x012c,
+ .name = "Dell Precision 650", /* AD1981A */
+ .type = AC97_TUNE_HP_ONLY
+ },
+ {
+ .vendor = 0x1028,
.device = 0x012d,
.name = "Dell Precision 450", /* AD1981B*/
.type = AC97_TUNE_HP_ONLY
@@ -1772,6 +1780,12 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = {
.type = AC97_TUNE_HP_ONLY
},
{
+ .vendor = 0x1028,
+ .device = 0x0163,
+ .name = "Dell Unknown", /* STAC9750/51 */
+ .type = AC97_TUNE_HP_ONLY
+ },
+ {
.vendor = 0x103c,
.device = 0x006d,
.name = "HP zv5000",
@@ -1838,6 +1852,12 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = {
.type = AC97_TUNE_HP_ONLY
},
{
+ .vendor = 0x10cf,
+ .device = 0x1253,
+ .name = "Fujitsu S6210", /* STAC9750/51 */
+ .type = AC97_TUNE_HP_ONLY
+ },
+ {
.vendor = 0x10f1,
.device = 0x2665,
.name = "Fujitsu-Siemens Celsius", /* AD1981? */
@@ -2012,7 +2032,8 @@ static int __devinit snd_intel8x0_mixer(intel8x0_t *chip, int ac97_clock, const
/* FIXME: my test board doesn't work well with VRA... */
if (chip->device_type == DEVICE_ALI)
pbus->no_vra = 1;
- pbus->dra = 1;
+ else
+ pbus->dra = 1;
chip->ac97_bus = pbus;
ac97.pci = chip->pci;
@@ -2320,7 +2341,7 @@ static int snd_intel8x0_free(intel8x0_t *chip)
/*
* power management
*/
-static int intel8x0_suspend(snd_card_t *card, unsigned int state)
+static int intel8x0_suspend(snd_card_t *card, pm_message_t state)
{
intel8x0_t *chip = card->pm_private_data;
int i;
@@ -2345,7 +2366,7 @@ static int intel8x0_suspend(snd_card_t *card, unsigned int state)
return 0;
}
-static int intel8x0_resume(snd_card_t *card, unsigned int state)
+static int intel8x0_resume(snd_card_t *card)
{
intel8x0_t *chip = card->pm_private_data;
int i;
@@ -2713,7 +2734,7 @@ static struct shortname_table {
{ PCI_DEVICE_ID_INTEL_ICH4, "Intel 82801DB-ICH4" },
{ PCI_DEVICE_ID_INTEL_ICH5, "Intel ICH5" },
{ PCI_DEVICE_ID_INTEL_ESB_5, "Intel 6300ESB" },
- { PCI_DEVICE_ID_INTEL_ICH6_3, "Intel ICH6" },
+ { PCI_DEVICE_ID_INTEL_ICH6_18, "Intel ICH6" },
{ PCI_DEVICE_ID_INTEL_ICH7_20, "Intel ICH7" },
{ PCI_DEVICE_ID_SI_7012, "SiS SI7012" },
{ PCI_DEVICE_ID_NVIDIA_MCP_AUDIO, "NVidia nForce" },
diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c
index 91df9308b0409..67da096d659b3 100644
--- a/sound/pci/intel8x0m.c
+++ b/sound/pci/intel8x0m.c
@@ -35,6 +35,7 @@
#include <sound/pcm.h>
#include <sound/ac97_codec.h>
#include <sound/info.h>
+#include <sound/control.h>
#include <sound/initval.h>
MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
@@ -46,6 +47,8 @@ MODULE_SUPPORTED_DEVICE("{{Intel,82801AA-ICH},"
"{Intel,82801CA-ICH3},"
"{Intel,82801DB-ICH4},"
"{Intel,ICH5},"
+ "{Intel,ICH6},"
+ "{Intel,ICH7},"
"{Intel,MX440},"
"{SiS,7013},"
"{NVidia,NForce Modem},"
@@ -54,7 +57,7 @@ MODULE_SUPPORTED_DEVICE("{{Intel,82801AA-ICH},"
"{NVidia,NForce3 Modem},"
"{AMD,AMD768}}");
-static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
+static int index[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = -2}; /* Exclude the first card */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
static int ac97_clock[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0};
@@ -93,6 +96,12 @@ MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (0 = auto-detect).");
#ifndef PCI_DEVICE_ID_INTEL_ICH5_6
#define PCI_DEVICE_ID_INTEL_ICH5_6 0x24d6
#endif
+#ifndef PCI_DEVICE_ID_INTEL_ICH6_6
+#define PCI_DEVICE_ID_INTEL_ICH6_6 0x266d
+#endif
+#ifndef PCI_DEVICE_ID_INTEL_ICH7_6
+#define PCI_DEVICE_ID_INTEL_ICH7_6 0x27dd
+#endif
#ifndef PCI_DEVICE_ID_SI_7013
#define PCI_DEVICE_ID_SI_7013 0x7013
#endif
@@ -247,7 +256,7 @@ struct _snd_intel8x0m {
snd_pcm_t *pcm[2];
ichdev_t ichd[2];
- int in_ac97_init: 1;
+ unsigned int in_ac97_init: 1;
ac97_bus_t *ac97_bus;
ac97_t *ac97;
@@ -268,6 +277,8 @@ static struct pci_device_id snd_intel8x0m_ids[] = {
{ 0x8086, 0x2486, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* ICH3 */
{ 0x8086, 0x24c6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* ICH4 */
{ 0x8086, 0x24d6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* ICH5 */
+ { 0x8086, 0x266d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* ICH6 */
+ { 0x8086, 0x27dd, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* ICH7 */
{ 0x8086, 0x7196, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* 440MX */
{ 0x1022, 0x7446, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* AMD768 */
{ 0x1039, 0x7013, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_SIS }, /* SI7013 */
@@ -281,9 +292,60 @@ static struct pci_device_id snd_intel8x0m_ids[] = {
#endif
{ 0, }
};
+static int snd_intel8x0m_switch_default_get(snd_kcontrol_t *kcontrol,
+ snd_ctl_elem_value_t *ucontrol);
+static int snd_intel8x0m_switch_default_put(snd_kcontrol_t *kcontrol,
+ snd_ctl_elem_value_t *ucontrol);
+static int snd_intel8x0m_switch_default_info(snd_kcontrol_t *kcontrol,
+ snd_ctl_elem_info_t *uinfo);
+
+#define PRIVATE_VALUE_INITIALIZER(r,m) (((r) & 0xffff) << 16 | ((m) & 0xffff))
+#define PRIVATE_VALUE_MASK(control) ((control)->private_value & 0xffff)
+#define PRIVATE_VALUE_REG(control) (((control)->private_value >> 16) & 0xffff)
+
+static snd_kcontrol_new_t snd_intel8x0m_mixer_switches[] __devinitdata = {
+ { .name = "Off-hook Switch",
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .info = snd_intel8x0m_switch_default_info,
+ .get = snd_intel8x0m_switch_default_get,
+ .put = snd_intel8x0m_switch_default_put,
+ .private_value = PRIVATE_VALUE_INITIALIZER(AC97_GPIO_STATUS,AC97_GPIO_LINE1_OH)
+ }
+};
MODULE_DEVICE_TABLE(pci, snd_intel8x0m_ids);
+static int snd_intel8x0m_switch_default_info(snd_kcontrol_t *kcontrol,
+ snd_ctl_elem_info_t *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+ uinfo->count = 1;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 1;
+ return 0;
+}
+
+static int snd_intel8x0m_switch_default_get(snd_kcontrol_t *kcontrol,
+ snd_ctl_elem_value_t *ucontrol)
+{
+ unsigned short mask = PRIVATE_VALUE_MASK(kcontrol);
+ unsigned short reg = PRIVATE_VALUE_REG(kcontrol);
+ intel8x0_t *chip = snd_kcontrol_chip(kcontrol);
+ unsigned int status;
+ status = snd_ac97_read(chip->ac97, reg) & mask ? 1 : 0;
+ ucontrol->value.integer.value[0] = status;
+ return 0;
+}
+static int snd_intel8x0m_switch_default_put(snd_kcontrol_t *kcontrol,
+ snd_ctl_elem_value_t *ucontrol)
+{
+ unsigned short mask = PRIVATE_VALUE_MASK(kcontrol);
+ unsigned short reg = PRIVATE_VALUE_REG(kcontrol);
+ intel8x0_t *chip = snd_kcontrol_chip(kcontrol);
+ unsigned short new_status = ucontrol->value.integer.value[0] ? mask : ~mask;
+ return snd_ac97_update_bits(chip->ac97, reg,
+ mask, new_status);
+}
/*
* Lowlevel I/O - busmaster
*/
@@ -638,17 +700,12 @@ static snd_pcm_uframes_t snd_intel8x0_pcm_pointer(snd_pcm_substream_t * substrea
static int snd_intel8x0m_pcm_trigger(snd_pcm_substream_t *substream, int cmd)
{
- ichdev_t *ichdev = get_ichdev(substream);
/* hook off/on on start/stop */
- /* TODO: move it to ac97 controls */
+ /* Moved this to mixer control */
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
- snd_ac97_update_bits(ichdev->ac97, AC97_GPIO_STATUS,
- AC97_GPIO_LINE1_OH, AC97_GPIO_LINE1_OH);
break;
case SNDRV_PCM_TRIGGER_STOP:
- snd_ac97_update_bits(ichdev->ac97, AC97_GPIO_STATUS,
- AC97_GPIO_LINE1_OH, ~AC97_GPIO_LINE1_OH);
break;
default:
return -EINVAL;
@@ -890,6 +947,7 @@ static int __devinit snd_intel8x0_mixer(intel8x0_t *chip, int ac97_clock)
ac97_t *x97;
int err;
unsigned int glob_sta = 0;
+ unsigned int idx;
static ac97_bus_ops_t ops = {
.write = snd_intel8x0_codec_write,
.read = snd_intel8x0_codec_read,
@@ -921,10 +979,14 @@ static int __devinit snd_intel8x0_mixer(intel8x0_t *chip, int ac97_clock)
return err;
}
chip->ac97 = x97;
- if(ac97_is_modem(x97) && !chip->ichd[ICHD_MDMIN].ac97 ) {
+ if(ac97_is_modem(x97) && !chip->ichd[ICHD_MDMIN].ac97) {
chip->ichd[ICHD_MDMIN].ac97 = x97;
chip->ichd[ICHD_MDMOUT].ac97 = x97;
}
+ for (idx = 0; idx < ARRAY_SIZE(snd_intel8x0m_mixer_switches); idx++) {
+ if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_intel8x0m_mixer_switches[idx], chip))) < 0)
+ goto __err;
+ }
chip->in_ac97_init = 0;
return 0;
@@ -1078,7 +1140,7 @@ static int snd_intel8x0_free(intel8x0_t *chip)
/*
* power management
*/
-static int intel8x0m_suspend(snd_card_t *card, unsigned int state)
+static int intel8x0m_suspend(snd_card_t *card, pm_message_t state)
{
intel8x0_t *chip = card->pm_private_data;
int i;
@@ -1091,7 +1153,7 @@ static int intel8x0m_suspend(snd_card_t *card, unsigned int state)
return 0;
}
-static int intel8x0m_resume(snd_card_t *card, unsigned int state)
+static int intel8x0m_resume(snd_card_t *card)
{
intel8x0_t *chip = card->pm_private_data;
pci_enable_device(chip->pci);
@@ -1298,6 +1360,8 @@ static struct shortname_table {
{ PCI_DEVICE_ID_INTEL_ICH3_6, "Intel 82801CA-ICH3" },
{ PCI_DEVICE_ID_INTEL_ICH4_6, "Intel 82801DB-ICH4" },
{ PCI_DEVICE_ID_INTEL_ICH5_6, "Intel ICH5" },
+ { PCI_DEVICE_ID_INTEL_ICH6_6, "Intel ICH6" },
+ { PCI_DEVICE_ID_INTEL_ICH7_6, "Intel ICH7" },
{ 0x7446, "AMD AMD768" },
{ PCI_DEVICE_ID_SI_7013, "SiS SI7013" },
{ PCI_DEVICE_ID_NVIDIA_MCP_MODEM, "NVidia nForce" },
diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c
index 4d8b92a0648b4..bb1de20081760 100644
--- a/sound/pci/korg1212/korg1212.c
+++ b/sound/pci/korg1212/korg1212.c
@@ -51,7 +51,7 @@
//#define K1212_LARGEALLOC 1
// ----------------------------------------------------------------------------
-// the following enum defines the valid states of the Korg 1212 I/O card.
+// Valid states of the Korg 1212 I/O card.
// ----------------------------------------------------------------------------
typedef enum {
K1212_STATE_NONEXISTENT, // there is no card here
@@ -85,6 +85,8 @@ typedef enum {
K1212_DB_ConfigureMiscMemory = 6, // tells card where other buffers are.
K1212_DB_TriggerFromAdat = 7, // tells card to trigger from Adat at a specific
// timecode value.
+ K1212_DB_DMAERROR = 0x80, // DMA Error - the PCI bus is congestioned.
+ K1212_DB_CARDSTOPPED = 0x81, // Card has stopped by user request.
K1212_DB_RebootCard = 0xA0, // instructs the card to reboot.
K1212_DB_BootFromDSPPage4 = 0xA4, // instructs the card to boot from the DSP microcode
// on page 4 (local page to card).
@@ -93,11 +95,9 @@ typedef enum {
K1212_DB_StartDSPDownload = 0xAF // tells the card to download its DSP firmware.
} korg1212_dbcnst_t;
-#define K1212_ISRCODE_DMAERROR 0x80
-#define K1212_ISRCODE_CARDSTOPPED 0x81
// ----------------------------------------------------------------------------
-// The following enumeration defines return codes for DeviceIoControl() calls
+// The following enumeration defines return codes
// to the Korg 1212 I/O driver.
// ----------------------------------------------------------------------------
typedef enum {
@@ -116,11 +116,6 @@ typedef enum {
K1212_CMDRET_NoAckFromCard, // the card never acknowledged a command
K1212_CMDRET_BadParams, // bad parameters were provided by the caller
- // --------------------------------------------------------------
- // the following return errors are specific to the wave device
- // driver interface. These will not be encountered by users of
- // the 32 bit DIOC interface (a.k.a. custom or native API).
- // --------------------------------------------------------------
K1212_CMDRET_BadDevice, // the specified wave device was out of range
K1212_CMDRET_BadFormat // the specified wave format is unsupported
} snd_korg1212rc;
@@ -400,9 +395,14 @@ struct _snd_korg1212 {
u16 leftADCInSens; // ADC left channel input sensitivity
u16 rightADCInSens; // ADC right channel input sensitivity
- int opencnt; // Open/Close count
- int setcnt; // SetupForPlay count
- int playcnt; // TriggerPlay count
+ int opencnt; // Open/Close count
+ int setcnt; // SetupForPlay count
+ int playcnt; // TriggerPlay count
+ int errorcnt; // Error Count
+ unsigned long totalerrorcnt; // Total Error Count
+
+ int dsp_is_loaded;
+ int dsp_stop_is_processed;
};
@@ -610,7 +610,7 @@ static snd_korg1212rc snd_korg1212_Send1212Command(korg1212_t *korg1212, korg121
static void snd_korg1212_SendStop(korg1212_t *korg1212)
{
if (! korg1212->stop_pending_cnt) {
- writel(0xffffffff, &korg1212->sharedBufferPtr->cardCommand);
+ korg1212->sharedBufferPtr->cardCommand = 0xffffffff;
/* program the timer */
korg1212->stop_pending_cnt = HZ;
korg1212->timer.expires = jiffies + 1;
@@ -622,9 +622,10 @@ static void snd_korg1212_SendStopAndWait(korg1212_t *korg1212)
{
unsigned long flags;
spin_lock_irqsave(&korg1212->lock, flags);
+ korg1212->dsp_stop_is_processed = 0;
snd_korg1212_SendStop(korg1212);
spin_unlock_irqrestore(&korg1212->lock, flags);
- sleep_on_timeout(&korg1212->wait, (HZ * 3) / 2);
+ wait_event_timeout(korg1212->wait, korg1212->dsp_stop_is_processed, (HZ * 3) / 2);
}
/* timer callback for checking the ack of stop request */
@@ -633,9 +634,10 @@ static void snd_korg1212_timer_func(unsigned long data)
korg1212_t *korg1212 = (korg1212_t *) data;
spin_lock(&korg1212->lock);
- if (readl(&korg1212->sharedBufferPtr->cardCommand) == 0) {
+ 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]);
@@ -647,7 +649,8 @@ static void snd_korg1212_timer_func(unsigned long data)
add_timer(&korg1212->timer);
} else {
snd_printd("korg1212_timer_func timeout\n");
- writel(0, &korg1212->sharedBufferPtr->cardCommand);
+ 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]);
@@ -850,15 +853,12 @@ static int snd_korg1212_SetMonitorMode(korg1212_t *korg1212, MonitorModeSelector
static inline int snd_korg1212_use_is_exclusive(korg1212_t *korg1212)
{
- unsigned long flags;
int ret = 1;
- spin_lock_irqsave(&korg1212->lock, flags);
if ((korg1212->playback_pid != korg1212->capture_pid) &&
(korg1212->playback_pid >= 0) && (korg1212->capture_pid >= 0)) {
ret = 0;
}
- spin_unlock_irqrestore(&korg1212->lock, flags);
return ret;
}
@@ -1179,18 +1179,23 @@ static irqreturn_t snd_korg1212_interrupt(int irq, void *dev_id, struct pt_regs
#if K1212_DEBUG_LEVEL > 0
K1212_DEBUG_PRINTK("K1212_DEBUG: IRQ DNLD count - %ld, %x, [%s].\n", korg1212->irqcount, doorbellValue, stateName[korg1212->cardState]);
#endif
- if (korg1212->cardState == K1212_STATE_DSP_IN_PROCESS)
+ if (korg1212->cardState == K1212_STATE_DSP_IN_PROCESS) {
+ korg1212->dsp_is_loaded = 1;
wake_up(&korg1212->wait);
+ }
break;
// ------------------------------------------------------------------------
// an error occurred - stop the card
// ------------------------------------------------------------------------
- case K1212_ISRCODE_DMAERROR:
+ 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
- writel(0, &korg1212->sharedBufferPtr->cardCommand);
+ snd_printk(KERN_ERR "korg1212: DMA Error\n");
+ korg1212->errorcnt++;
+ korg1212->totalerrorcnt++;
+ korg1212->sharedBufferPtr->cardCommand = 0;
snd_korg1212_setCardState(korg1212, K1212_STATE_ERRORSTOP);
break;
@@ -1198,11 +1203,11 @@ static irqreturn_t snd_korg1212_interrupt(int irq, void *dev_id, struct pt_regs
// the card has stopped by our request. Clear the command word and signal
// the semaphore in case someone is waiting for this.
// ------------------------------------------------------------------------
- case K1212_ISRCODE_CARDSTOPPED:
+ 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
- writel(0, &korg1212->sharedBufferPtr->cardCommand);
+ korg1212->sharedBufferPtr->cardCommand = 0;
break;
default:
@@ -1267,7 +1272,9 @@ static int snd_korg1212_downloadDSPCode(korg1212_t *korg1212)
if (rc) K1212_DEBUG_PRINTK("K1212_DEBUG: Start DSP Download RC = %d [%s]\n", rc, stateName[korg1212->cardState]);
#endif
- if (! sleep_on_timeout(&korg1212->wait, HZ * CARD_BOOT_TIMEOUT))
+ korg1212->dsp_is_loaded = 0;
+ wait_event_timeout(korg1212->wait, korg1212->dsp_is_loaded, HZ * CARD_BOOT_TIMEOUT);
+ if (! korg1212->dsp_is_loaded )
return -EBUSY; /* timeout */
snd_korg1212_OnDSPDownloadComplete(korg1212);
@@ -1439,6 +1446,7 @@ static int snd_korg1212_playback_open(snd_pcm_substream_t *substream)
korg1212->playback_pid = current->pid;
korg1212->periodsize = K1212_PERIODS;
korg1212->channels = K1212_CHANNELS;
+ korg1212->errorcnt = 0;
spin_unlock_irqrestore(&korg1212->lock, flags);
@@ -1457,7 +1465,7 @@ static int snd_korg1212_capture_open(snd_pcm_substream_t *substream)
K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_capture_open [%s]\n", stateName[korg1212->cardState]);
#endif
- snd_pcm_set_sync(substream); // ???
+ snd_pcm_set_sync(substream);
snd_korg1212_OpenCard(korg1212);
@@ -1614,7 +1622,7 @@ static int snd_korg1212_prepare(snd_pcm_substream_t *substream)
spin_unlock_irq(&korg1212->lock);
return -EAGAIN;
/*
- writel(0, &korg1212->sharedBufferPtr->cardCommand);
+ korg1212->sharedBufferPtr->cardCommand = 0;
del_timer(&korg1212->timer);
korg1212->stop_pending_cnt = 0;
*/
@@ -2118,6 +2126,7 @@ static void snd_korg1212_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *b
snd_iprintf(buffer, "Idle mon. State: %d\n", korg1212->idleMonitorOn);
snd_iprintf(buffer, "Cmd retry count: %d\n", korg1212->cmdRetryCount);
snd_iprintf(buffer, " Irq count: %ld\n", korg1212->irqcount);
+ snd_iprintf(buffer, " Error count: %ld\n", korg1212->totalerrorcnt);
}
static void __devinit snd_korg1212_proc_init(korg1212_t *korg1212)
@@ -2235,6 +2244,7 @@ static int __devinit snd_korg1212_create(snd_card_t * card, struct pci_dev *pci,
korg1212->opencnt = 0;
korg1212->playcnt = 0;
korg1212->setcnt = 0;
+ korg1212->totalerrorcnt = 0;
korg1212->playback_pid = -1;
korg1212->capture_pid = -1;
snd_korg1212_setCardState(korg1212, K1212_STATE_UNINITIALIZED);
@@ -2273,7 +2283,7 @@ static int __devinit snd_korg1212_create(snd_card_t * card, struct pci_dev *pci,
#endif
if ((korg1212->iobase = ioremap(korg1212->iomem, iomem_size)) == NULL) {
- snd_printk(KERN_ERR "unable to remap memory region 0x%lx-0x%lx\n", korg1212->iomem,
+ snd_printk(KERN_ERR "korg1212: unable to remap memory region 0x%lx-0x%lx\n", korg1212->iomem,
korg1212->iomem + iomem_size - 1);
snd_korg1212_free(korg1212);
return -EBUSY;
@@ -2284,7 +2294,7 @@ static int __devinit snd_korg1212_create(snd_card_t * card, struct pci_dev *pci,
"korg1212", (void *) korg1212);
if (err) {
- snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
+ snd_printk(KERN_ERR "korg1212: unable to grab IRQ %d\n", pci->irq);
snd_korg1212_free(korg1212);
return -EBUSY;
}
@@ -2332,7 +2342,7 @@ static int __devinit snd_korg1212_create(snd_card_t * card, struct pci_dev *pci,
if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
sizeof(KorgSharedBuffer), &korg1212->dma_shared) < 0) {
- snd_printk(KERN_ERR "can not allocate shared buffer memory (%Zd bytes)\n", sizeof(KorgSharedBuffer));
+ snd_printk(KERN_ERR "korg1212: can not allocate shared buffer memory (%Zd bytes)\n", sizeof(KorgSharedBuffer));
snd_korg1212_free(korg1212);
return -ENOMEM;
}
@@ -2349,7 +2359,7 @@ static int __devinit snd_korg1212_create(snd_card_t * card, struct pci_dev *pci,
if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
korg1212->DataBufsSize, &korg1212->dma_play) < 0) {
- snd_printk(KERN_ERR "can not allocate play data buffer memory (%d bytes)\n", korg1212->DataBufsSize);
+ snd_printk(KERN_ERR "korg1212: can not allocate play data buffer memory (%d bytes)\n", korg1212->DataBufsSize);
snd_korg1212_free(korg1212);
return -ENOMEM;
}
@@ -2363,7 +2373,7 @@ static int __devinit snd_korg1212_create(snd_card_t * card, struct pci_dev *pci,
if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
korg1212->DataBufsSize, &korg1212->dma_rec) < 0) {
- snd_printk(KERN_ERR "can not allocate record data buffer memory (%d bytes)\n", korg1212->DataBufsSize);
+ snd_printk(KERN_ERR "korg1212: can not allocate record data buffer memory (%d bytes)\n", korg1212->DataBufsSize);
snd_korg1212_free(korg1212);
return -ENOMEM;
}
@@ -2395,7 +2405,7 @@ static int __devinit snd_korg1212_create(snd_card_t * card, struct pci_dev *pci,
if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
korg1212->dspCodeSize, &korg1212->dma_dsp) < 0) {
- snd_printk(KERN_ERR "can not allocate dsp code memory (%d bytes)\n", korg1212->dspCodeSize);
+ snd_printk(KERN_ERR "korg1212: can not allocate dsp code memory (%d bytes)\n", korg1212->dspCodeSize);
snd_korg1212_free(korg1212);
return -ENOMEM;
}
@@ -2424,11 +2434,12 @@ static int __devinit snd_korg1212_create(snd_card_t * card, struct pci_dev *pci,
if (snd_korg1212_downloadDSPCode(korg1212))
return -EBUSY;
- printk(KERN_INFO "dspMemPhy = %08x U[%08x]\n"
- "PlayDataPhy = %08x L[%08x]\n"
- "RecDataPhy = %08x L[%08x]\n"
- "VolumeTablePhy = %08x L[%08x]\n"
- "RoutingTablePhy = %08x L[%08x]\n"
+ snd_printk(KERN_ERR
+ "korg1212: dspMemPhy = %08x U[%08x], "
+ "PlayDataPhy = %08x L[%08x]\n"
+ "korg1212: RecDataPhy = %08x L[%08x], "
+ "VolumeTablePhy = %08x L[%08x]\n"
+ "korg1212: RoutingTablePhy = %08x L[%08x], "
"AdatTimeCodePhy = %08x L[%08x]\n",
(int)korg1212->dma_dsp.addr, UpperWordSwap(korg1212->dma_dsp.addr),
korg1212->PlayDataPhy, LowerWordSwap(korg1212->PlayDataPhy),
diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c
index 87fae627b8016..2cf33083d7ccb 100644
--- a/sound/pci/maestro3.c
+++ b/sound/pci/maestro3.c
@@ -820,7 +820,7 @@ struct snd_m3 {
unsigned long iobase;
int irq;
- int allegro_flag : 1;
+ unsigned int allegro_flag : 1;
ac97_t *ac97;
@@ -957,6 +957,13 @@ static struct m3_quirk m3_quirk_list[] = {
.device = 0x80f1,
.amp_gpio = 0x03,
},
+ /* LEGEND ZhaoYang 3100CF */
+ {
+ .name = "LEGEND ZhaoYang 3100CF",
+ .vendor = 0x1509,
+ .device = 0x1740,
+ .amp_gpio = 0x03,
+ },
/* END */
{ NULL }
};
@@ -2385,7 +2392,7 @@ static int snd_m3_free(m3_t *chip)
* APM support
*/
#ifdef CONFIG_PM
-static int m3_suspend(snd_card_t *card, unsigned int state)
+static int m3_suspend(snd_card_t *card, pm_message_t state)
{
m3_t *chip = card->pm_private_data;
int i, index;
@@ -2417,7 +2424,7 @@ static int m3_suspend(snd_card_t *card, unsigned int state)
return 0;
}
-static int m3_resume(snd_card_t *card, unsigned int state)
+static int m3_resume(snd_card_t *card)
{
m3_t *chip = card->pm_private_data;
int i, index;
diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c
index dd9047c50e609..65bb0f47af2c1 100644
--- a/sound/pci/mixart/mixart.c
+++ b/sound/pci/mixart/mixart.c
@@ -1062,7 +1062,7 @@ static int snd_mixart_free(mixart_mgr_t *mgr)
free_irq(mgr->irq, (void *)mgr);
/* reset board if some firmware was loaded */
- if(mgr->hwdep->dsp_loaded) {
+ if(mgr->dsp_loaded) {
snd_mixart_reset_board(mgr);
snd_printdd("reset miXart !\n");
}
@@ -1203,7 +1203,7 @@ static void snd_mixart_proc_read(snd_info_entry_t *entry,
snd_iprintf(buffer, "Digigram miXart (alsa card %d)\n\n", chip->chip_idx);
/* stats available when embedded OS is running */
- if (chip->mgr->hwdep->dsp_loaded & ( 1 << MIXART_MOTHERBOARD_ELF_INDEX)) {
+ if (chip->mgr->dsp_loaded & ( 1 << MIXART_MOTHERBOARD_ELF_INDEX)) {
snd_iprintf(buffer, "- hardware -\n");
switch (chip->mgr->board_type ) {
case MIXART_DAUGHTER_TYPE_NONE : snd_iprintf(buffer, "\tmiXart8 (no daughter board)\n\n"); break;
@@ -1381,7 +1381,7 @@ static int __devinit snd_mixart_probe(struct pci_dev *pci,
}
}
- /* init firmware status (mgr->hwdep->dsp_loaded reset in hwdep_new) */
+ /* init firmware status (mgr->dsp_loaded reset in hwdep_new) */
mgr->board_type = MIXART_DAUGHTER_TYPE_NONE;
/* create array of streaminfo */
diff --git a/sound/pci/mixart/mixart.h b/sound/pci/mixart/mixart.h
index 4cde2638bd4e9..f87152f94c0e9 100644
--- a/sound/pci/mixart/mixart.h
+++ b/sound/pci/mixart/mixart.h
@@ -112,7 +112,7 @@ struct snd_mixart_mgr {
struct semaphore setup_mutex; /* mutex used in hw_params, open and close */
/* hardware interface */
- snd_hwdep_t *hwdep;
+ unsigned int dsp_loaded; /* bit flags of loaded dsp indices */
unsigned int board_type; /* read from embedded once elf file is loaded, 250 = miXart8, 251 = with AES, 252 = with Cobranet */
struct snd_dma_buffer flowinfo;
diff --git a/sound/pci/mixart/mixart_hwdep.c b/sound/pci/mixart/mixart_hwdep.c
index 0da472b7dc722..edd1599fe45e7 100644
--- a/sound/pci/mixart/mixart_hwdep.c
+++ b/sound/pci/mixart/mixart_hwdep.c
@@ -142,26 +142,35 @@ static int mixart_enum_connectors(mixart_mgr_t *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;
+ mixart_enum_connector_resp_t *connector;
+ mixart_audio_info_req_t *audio_info_req;
+ mixart_audio_info_resp_t *audio_info;
+
+ connector = kmalloc(sizeof(*connector), GFP_KERNEL);
+ audio_info_req = kmalloc(sizeof(*audio_info_req), GFP_KERNEL);
+ audio_info = kmalloc(sizeof(*audio_info), GFP_KERNEL);
+ if (! connector || ! audio_info_req || ! audio_info) {
+ err = -ENOMEM;
+ goto __error;
+ }
- audio_info_req.line_max_level = MIXART_FLOAT_P_22_0_TO_HEX;
- audio_info_req.micro_max_level = MIXART_FLOAT_M_20_0_TO_HEX;
- audio_info_req.cd_max_level = MIXART_FLOAT____0_0_TO_HEX;
+ audio_info_req->line_max_level = MIXART_FLOAT_P_22_0_TO_HEX;
+ audio_info_req->micro_max_level = MIXART_FLOAT_M_20_0_TO_HEX;
+ 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.data = NULL;
request.size = 0;
- err = snd_mixart_send_msg(mgr, &request, sizeof(connector), &connector);
- if((err < 0) || (connector.error_code) || (connector.uid_count > MIXART_MAX_PHYS_CONNECTORS)) {
+ err = snd_mixart_send_msg(mgr, &request, sizeof(*connector), connector);
+ if((err < 0) || (connector->error_code) || (connector->uid_count > MIXART_MAX_PHYS_CONNECTORS)) {
snd_printk(KERN_ERR "error MSG_SYSTEM_ENUM_PLAY_CONNECTOR\n");
- return -EINVAL;
+ err = -EINVAL;
+ goto __error;
}
- for(k=0; k < connector.uid_count; k++) {
+ for(k=0; k < connector->uid_count; k++) {
mixart_pipe_t* pipe;
if(k < MIXART_FIRST_DIG_AUDIO_ID) {
@@ -170,25 +179,25 @@ static int mixart_enum_connectors(mixart_mgr_t *mgr)
pipe = &mgr->chip[(k-MIXART_FIRST_DIG_AUDIO_ID)/2]->pipe_out_dig;
}
if(k & 1) {
- pipe->uid_right_connector = connector.uid[k]; /* odd */
+ pipe->uid_right_connector = connector->uid[k]; /* odd */
} else {
- pipe->uid_left_connector = connector.uid[k]; /* even */
+ pipe->uid_left_connector = connector->uid[k]; /* even */
}
- /* snd_printk(KERN_DEBUG "playback connector[%d].object_id = %x\n", k, connector.uid[k].object_id); */
+ /* snd_printk(KERN_DEBUG "playback connector[%d].object_id = %x\n", k, connector->uid[k].object_id); */
/* TODO: really need send_msg MSG_CONNECTOR_GET_AUDIO_INFO for each connector ? perhaps for analog level caps ? */
request.message_id = MSG_CONNECTOR_GET_AUDIO_INFO;
- request.uid = connector.uid[k];
- request.data = &audio_info_req;
- request.size = sizeof(audio_info_req);
+ request.uid = connector->uid[k];
+ request.data = audio_info_req;
+ request.size = sizeof(*audio_info_req);
- err = snd_mixart_send_msg(mgr, &request, sizeof(audio_info), &audio_info);
+ err = snd_mixart_send_msg(mgr, &request, sizeof(*audio_info), audio_info);
if( err < 0 ) {
snd_printk(KERN_ERR "error MSG_CONNECTOR_GET_AUDIO_INFO\n");
- return err;
+ goto __error;
}
- /*snd_printk(KERN_DEBUG "play analog_info.analog_level_present = %x\n", audio_info.info.analog_info.analog_level_present);*/
+ /*snd_printk(KERN_DEBUG "play analog_info.analog_level_present = %x\n", audio_info->info.analog_info.analog_level_present);*/
}
request.message_id = MSG_SYSTEM_ENUM_RECORD_CONNECTOR;
@@ -196,13 +205,14 @@ static int mixart_enum_connectors(mixart_mgr_t *mgr)
request.data = NULL;
request.size = 0;
- err = snd_mixart_send_msg(mgr, &request, sizeof(connector), &connector);
- if((err < 0) || (connector.error_code) || (connector.uid_count > MIXART_MAX_PHYS_CONNECTORS)) {
+ err = snd_mixart_send_msg(mgr, &request, sizeof(*connector), connector);
+ if((err < 0) || (connector->error_code) || (connector->uid_count > MIXART_MAX_PHYS_CONNECTORS)) {
snd_printk(KERN_ERR "error MSG_SYSTEM_ENUM_RECORD_CONNECTOR\n");
- return -EINVAL;
+ err = -EINVAL;
+ goto __error;
}
- for(k=0; k < connector.uid_count; k++) {
+ for(k=0; k < connector->uid_count; k++) {
mixart_pipe_t* pipe;
if(k < MIXART_FIRST_DIG_AUDIO_ID) {
@@ -211,28 +221,34 @@ static int mixart_enum_connectors(mixart_mgr_t *mgr)
pipe = &mgr->chip[(k-MIXART_FIRST_DIG_AUDIO_ID)/2]->pipe_in_dig;
}
if(k & 1) {
- pipe->uid_right_connector = connector.uid[k]; /* odd */
+ pipe->uid_right_connector = connector->uid[k]; /* odd */
} else {
- pipe->uid_left_connector = connector.uid[k]; /* even */
+ pipe->uid_left_connector = connector->uid[k]; /* even */
}
- /* snd_printk(KERN_DEBUG "capture connector[%d].object_id = %x\n", k, connector.uid[k].object_id); */
+ /* snd_printk(KERN_DEBUG "capture connector[%d].object_id = %x\n", k, connector->uid[k].object_id); */
/* TODO: really need send_msg MSG_CONNECTOR_GET_AUDIO_INFO for each connector ? perhaps for analog level caps ? */
request.message_id = MSG_CONNECTOR_GET_AUDIO_INFO;
- request.uid = connector.uid[k];
- request.data = &audio_info_req;
- request.size = sizeof(audio_info_req);
+ request.uid = connector->uid[k];
+ request.data = audio_info_req;
+ request.size = sizeof(*audio_info_req);
- err = snd_mixart_send_msg(mgr, &request, sizeof(audio_info), &audio_info);
+ err = snd_mixart_send_msg(mgr, &request, sizeof(*audio_info), audio_info);
if( err < 0 ) {
snd_printk(KERN_ERR "error MSG_CONNECTOR_GET_AUDIO_INFO\n");
- return err;
+ goto __error;
}
- /*snd_printk(KERN_DEBUG "rec analog_info.analog_level_present = %x\n", audio_info.info.analog_info.analog_level_present);*/
+ /*snd_printk(KERN_DEBUG "rec analog_info.analog_level_present = %x\n", audio_info->info.analog_info.analog_level_present);*/
}
+ err = 0;
- return 0;
+ __error:
+ kfree(connector);
+ kfree(audio_info_req);
+ kfree(audio_info);
+
+ return err;
}
static int mixart_enum_physio(mixart_mgr_t *mgr)
@@ -546,6 +562,7 @@ int snd_mixart_setup_firmware(mixart_mgr_t *mgr)
release_firmware(fw_entry);
if (err < 0)
return err;
+ mgr->dsp_loaded |= 1 << i;
}
return 0;
}
@@ -573,7 +590,7 @@ static int mixart_hwdep_dsp_status(snd_hwdep_t *hw, snd_hwdep_dsp_status_t *info
strcpy(info->id, "miXart");
info->num_dsps = MIXART_HARDW_FILES_MAX_INDEX;
- if (mgr->hwdep->dsp_loaded & (1 << MIXART_MOTHERBOARD_ELF_INDEX))
+ if (mgr->dsp_loaded & (1 << MIXART_MOTHERBOARD_ELF_INDEX))
info->chip_ready = 1;
info->version = MIXART_DRIVER_VERSION;
@@ -599,6 +616,9 @@ static int mixart_hwdep_dsp_load(snd_hwdep_t *hw, snd_hwdep_dsp_image_t *dsp)
}
err = mixart_dsp_load(mgr, dsp->index, &fw);
vfree(fw.data);
+ if (err < 0)
+ return err;
+ mgr->dsp_loaded |= 1 << dsp->index;
return err;
}
@@ -619,8 +639,7 @@ int snd_mixart_setup_firmware(mixart_mgr_t *mgr)
hw->ops.dsp_load = mixart_hwdep_dsp_load;
hw->exclusive = 1;
sprintf(hw->name, SND_MIXART_HWDEP_ID);
- mgr->hwdep = hw;
- mgr->hwdep->dsp_loaded = 0;
+ mgr->dsp_loaded = 0;
return snd_card_register(mgr->chip[0]->card);
}
diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c
index 33e0d6b52ad9f..356fbeac6f9e0 100644
--- a/sound/pci/nm256/nm256.c
+++ b/sound/pci/nm256/nm256.c
@@ -1267,7 +1267,7 @@ 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, unsigned int state)
+static int nm256_suspend(snd_card_t *card, pm_message_t state)
{
nm256_t *chip = card->pm_private_data;
@@ -1278,7 +1278,7 @@ static int nm256_suspend(snd_card_t *card, unsigned int state)
return 0;
}
-static int nm256_resume(snd_card_t *card, unsigned int state)
+static int nm256_resume(snd_card_t *card)
{
nm256_t *chip = card->pm_private_data;
diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c
index a5ed64c368b87..b96acd5a57dbd 100644
--- a/sound/pci/rme32.c
+++ b/sound/pci/rme32.c
@@ -1183,15 +1183,14 @@ static int snd_rme32_playback_fd_ack(snd_pcm_substream_t *substream)
{
rme32_t *rme32 = snd_pcm_substream_chip(substream);
snd_pcm_indirect_t *rec, *cprec;
- unsigned long flags;
rec = &rme32->playback_pcm;
cprec = &rme32->capture_pcm;
- spin_lock_irqsave(&rme32->lock, flags);
+ spin_lock(&rme32->lock);
rec->hw_queue_size = RME32_BUFFER_SIZE;
if (rme32->running & (1 << SNDRV_PCM_STREAM_CAPTURE))
rec->hw_queue_size -= cprec->hw_ready;
- spin_unlock_irqrestore(&rme32->lock, flags);
+ spin_unlock(&rme32->lock);
snd_pcm_indirect_playback_transfer(substream, rec,
snd_rme32_pb_trans_copy);
return 0;
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c
index e35796c908519..12efbf0fab549 100644
--- a/sound/pci/rme9652/hdsp.c
+++ b/sound/pci/rme9652/hdsp.c
@@ -47,8 +47,6 @@
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 precise_ptr[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = 0 }; /* Enable precise pointer */
-static int line_outs_monitor[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = 0}; /* Send all inputs/playback to line outs */
module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for RME Hammerfall DSP interface.");
@@ -56,10 +54,6 @@ module_param_array(id, charp, NULL, 0444);
MODULE_PARM_DESC(id, "ID string for RME Hammerfall DSP interface.");
module_param_array(enable, bool, NULL, 0444);
MODULE_PARM_DESC(enable, "Enable/disable specific Hammerfall DSP soundcards.");
-module_param_array(precise_ptr, bool, NULL, 0444);
-MODULE_PARM_DESC(precise_ptr, "Enable precise pointer (doesn't work reliably).");
-module_param_array(line_outs_monitor, bool, NULL, 0444);
-MODULE_PARM_DESC(line_outs_monitor, "Send all input and playback streams to line outs by default.");
MODULE_AUTHOR("Paul Davis <paul@linuxaudiosystems.com>, Marcus Andersson, Thomas Charbonnel <thomas@undata.org>");
MODULE_DESCRIPTION("RME Hammerfall DSP");
MODULE_LICENSE("GPL");
@@ -445,6 +439,7 @@ struct _hdsp {
snd_pcm_substream_t *playback_substream;
hdsp_midi_t midi[2];
struct tasklet_struct midi_tasklet;
+ int use_midi_tasklet;
int precise_ptr;
u32 control_register; /* cached value */
u32 control2_register; /* cached value */
@@ -472,7 +467,6 @@ struct _hdsp {
pid_t capture_pid;
pid_t playback_pid;
int running;
- int passthru; /* non-zero if doing pass-thru */
int system_sample_rate;
char *channel_map;
int dev;
@@ -659,13 +653,13 @@ static int snd_hdsp_load_firmware_from_cache(hdsp_t *hdsp) {
if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) {
- snd_printk ("loading firmware\n");
+ snd_printk ("Hammerfall-DSP: loading firmware\n");
hdsp_write (hdsp, HDSP_control2Reg, HDSP_S_PROGRAM);
hdsp_write (hdsp, HDSP_fifoData, 0);
if (hdsp_fifo_wait (hdsp, 0, HDSP_LONG_WAIT)) {
- snd_printk ("timeout waiting for download preparation\n");
+ snd_printk ("Hammerfall-DSP: timeout waiting for download preparation\n");
return -EIO;
}
@@ -674,7 +668,7 @@ static int snd_hdsp_load_firmware_from_cache(hdsp_t *hdsp) {
for (i = 0; i < 24413; ++i) {
hdsp_write(hdsp, HDSP_fifoData, hdsp->firmware_cache[i]);
if (hdsp_fifo_wait (hdsp, 127, HDSP_LONG_WAIT)) {
- snd_printk ("timeout during firmware loading\n");
+ snd_printk ("Hammerfall-DSP: timeout during firmware loading\n");
return -EIO;
}
}
@@ -687,7 +681,7 @@ static int snd_hdsp_load_firmware_from_cache(hdsp_t *hdsp) {
}
if (hdsp_fifo_wait (hdsp, 0, HDSP_LONG_WAIT)) {
- snd_printk ("timeout at end of firmware loading\n");
+ snd_printk ("Hammerfall-DSP: timeout at end of firmware loading\n");
return -EIO;
}
@@ -697,11 +691,11 @@ static int snd_hdsp_load_firmware_from_cache(hdsp_t *hdsp) {
hdsp->control2_register = 0;
#endif
hdsp_write (hdsp, HDSP_control2Reg, hdsp->control2_register);
- snd_printk ("finished firmware loading\n");
+ snd_printk ("Hammerfall-DSP: finished firmware loading\n");
}
if (hdsp->state & HDSP_InitializationComplete) {
- snd_printk("firmware loaded from cache, restoring defaults\n");
+ snd_printk("Hammerfall-DSP: firmware loaded from cache, restoring defaults\n");
spin_lock_irqsave(&hdsp->lock, flags);
snd_hdsp_set_defaults(hdsp);
spin_unlock_irqrestore(&hdsp->lock, flags);
@@ -714,16 +708,6 @@ static int snd_hdsp_load_firmware_from_cache(hdsp_t *hdsp) {
static int hdsp_get_iobox_version (hdsp_t *hdsp)
{
- int err;
-
- if (hdsp_check_for_iobox (hdsp)) {
- return -EIO;
- }
-
- if ((err = snd_hdsp_enable_io(hdsp)) < 0) {
- return err;
- }
-
if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) {
hdsp_write (hdsp, HDSP_control2Reg, HDSP_PROGRAM);
@@ -759,7 +743,7 @@ static int hdsp_check_for_firmware (hdsp_t *hdsp)
{
if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return 0;
if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) {
- snd_printk("firmware not present.\n");
+ snd_printk("Hammerfall-DSP: firmware not present.\n");
hdsp->state &= ~HDSP_FirmwareLoaded;
return -EIO;
}
@@ -787,7 +771,7 @@ static int hdsp_fifo_wait(hdsp_t *hdsp, int count, int timeout)
udelay (100);
}
- snd_printk ("wait for FIFO status <= %d failed after %d iterations\n",
+ snd_printk ("Hammerfall-DSP: wait for FIFO status <= %d failed after %d iterations\n",
count, timeout);
return -1;
}
@@ -809,7 +793,7 @@ static int hdsp_write_gain(hdsp_t *hdsp, unsigned int addr, unsigned short data)
if (hdsp->io_type == H9652 || hdsp->io_type == H9632) {
- /* from martin björnsen:
+ /* from martin bjornsen:
"You can only write dwords to the
mixer memory which contain two
@@ -922,7 +906,7 @@ static int hdsp_spdif_sample_rate(hdsp_t *hdsp)
default:
break;
}
- snd_printk ("unknown spdif frequency status; bits = 0x%x, status = 0x%x\n", rate_bits, status);
+ snd_printk ("Hammerfall-DSP: unknown spdif frequency status; bits = 0x%x, status = 0x%x\n", rate_bits, status);
return 0;
}
@@ -1008,7 +992,7 @@ static int hdsp_set_rate(hdsp_t *hdsp, int rate, int called_internally)
if (!(hdsp->control_register & HDSP_ClockModeMaster)) {
if (called_internally) {
/* request from ctl or card initialization */
- snd_printk("device is not running as a clock master: cannot set sample rate.\n");
+ snd_printk("Hammerfall-DSP: device is not running as a clock master: cannot set sample rate.\n");
return -1;
} else {
/* hw_param request while in AutoSync mode */
@@ -1016,11 +1000,11 @@ static int hdsp_set_rate(hdsp_t *hdsp, int rate, int called_internally)
int spdif_freq = hdsp_spdif_sample_rate(hdsp);
if ((spdif_freq == external_freq*2) && (hdsp_autosync_ref(hdsp) >= HDSP_AUTOSYNC_FROM_ADAT1)) {
- snd_printk("Detected ADAT in double speed mode\n");
+ snd_printk("Hammerfall-DSP: Detected ADAT in double speed mode\n");
} else if (hdsp->io_type == H9632 && (spdif_freq == external_freq*4) && (hdsp_autosync_ref(hdsp) >= HDSP_AUTOSYNC_FROM_ADAT1)) {
- snd_printk("Detected ADAT in quad speed mode\n");
+ snd_printk("Hammerfall-DSP: Detected ADAT in quad speed mode\n");
} else if (rate != external_freq) {
- snd_printk("No AutoSync source for requested rate\n");
+ snd_printk("Hammerfall-DSP: No AutoSync source for requested rate\n");
return -1;
}
}
@@ -1102,7 +1086,7 @@ static int hdsp_set_rate(hdsp_t *hdsp, int rate, int called_internally)
}
if (reject_if_open && (hdsp->capture_pid >= 0 || hdsp->playback_pid >= 0)) {
- snd_printk ("cannot change speed mode (capture PID = %d, playback PID = %d)\n",
+ snd_printk ("Hammerfall-DSP: cannot change speed mode (capture PID = %d, playback PID = %d)\n",
hdsp->capture_pid,
hdsp->playback_pid);
return -EBUSY;
@@ -1143,68 +1127,6 @@ static int hdsp_set_rate(hdsp_t *hdsp, int rate, int called_internally)
return 0;
}
-static void hdsp_set_thru(hdsp_t *hdsp, int channel, int enable)
-{
-
- hdsp->passthru = 0;
-
- if (channel < 0) {
-
- int i;
-
- /* set thru for all channels */
-
- if (enable) {
- for (i = 0; i < hdsp->max_channels; i++) {
- hdsp_write_gain (hdsp, hdsp_input_to_output_key(hdsp,i,i), UNITY_GAIN);
- }
- } else {
- for (i = 0; i < hdsp->max_channels; i++) {
- hdsp_write_gain (hdsp, hdsp_input_to_output_key(hdsp,i,i), MINUS_INFINITY_GAIN);
- }
- }
-
- } else {
- int mapped_channel;
-
- snd_assert(channel < hdsp->max_channels, return);
-
- mapped_channel = hdsp->channel_map[channel];
-
- snd_assert(mapped_channel > -1, return);
-
- if (enable) {
- hdsp_write_gain (hdsp, hdsp_input_to_output_key(hdsp,mapped_channel,mapped_channel), UNITY_GAIN);
- } else {
- hdsp_write_gain (hdsp, hdsp_input_to_output_key(hdsp,mapped_channel,mapped_channel), MINUS_INFINITY_GAIN);
- }
- }
-}
-
-static int hdsp_set_passthru(hdsp_t *hdsp, int onoff)
-{
- if (onoff) {
- hdsp_set_thru(hdsp, -1, 1);
- hdsp_reset_hw_pointer(hdsp);
- hdsp_silence_playback(hdsp);
-
- /* we don't want interrupts, so do a
- custom version of hdsp_start_audio().
- */
-
- hdsp->control_register |= (HDSP_Start|HDSP_AudioInterruptEnable|hdsp_encode_latency(7));
-
- hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
- hdsp->passthru = 1;
- } else {
- hdsp_set_thru(hdsp, -1, 0);
- hdsp_stop_audio(hdsp);
- hdsp->passthru = 0;
- }
-
- return 0;
-}
-
/*----------------------------------------------------------------------------
MIDI
----------------------------------------------------------------------------*/
@@ -1345,6 +1267,7 @@ static void snd_hdsp_midi_input_trigger(snd_rawmidi_substream_t * substream, int
}
} else {
hdsp->control_register &= ~ie;
+ tasklet_kill(&hdsp->midi_tasklet);
}
hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
@@ -2741,16 +2664,32 @@ static int snd_hdsp_get_autosync_ref(snd_kcontrol_t * kcontrol, snd_ctl_elem_val
return 0;
}
-#define HDSP_PASSTHRU(xname, xindex) \
+#define HDSP_LINE_OUT(xname, xindex) \
{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
.name = xname, \
.index = xindex, \
- .info = snd_hdsp_info_passthru, \
- .put = snd_hdsp_put_passthru, \
- .get = snd_hdsp_get_passthru \
+ .info = snd_hdsp_info_line_out, \
+ .get = snd_hdsp_get_line_out, \
+ .put = snd_hdsp_put_line_out \
+}
+
+static int hdsp_line_out(hdsp_t *hdsp)
+{
+ return (hdsp->control_register & HDSP_LineOut) ? 1 : 0;
+}
+
+static int hdsp_set_line_output(hdsp_t *hdsp, int out)
+{
+ if (out) {
+ hdsp->control_register |= HDSP_LineOut;
+ } else {
+ hdsp->control_register &= ~HDSP_LineOut;
+ }
+ hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
+ return 0;
}
-static int snd_hdsp_info_passthru(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_hdsp_info_line_out(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
@@ -2759,61 +2698,106 @@ static int snd_hdsp_info_passthru(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t
return 0;
}
-static int snd_hdsp_get_passthru(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_hdsp_get_line_out(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
-
+
spin_lock_irq(&hdsp->lock);
- ucontrol->value.integer.value[0] = hdsp->passthru;
+ ucontrol->value.integer.value[0] = hdsp_line_out(hdsp);
spin_unlock_irq(&hdsp->lock);
return 0;
}
-static int snd_hdsp_put_passthru(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_hdsp_put_line_out(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
int change;
unsigned int val;
- int err = 0;
-
+
if (!snd_hdsp_use_is_exclusive(hdsp))
return -EBUSY;
-
val = ucontrol->value.integer.value[0] & 1;
spin_lock_irq(&hdsp->lock);
- change = (ucontrol->value.integer.value[0] != hdsp->passthru);
- if (change)
- err = hdsp_set_passthru(hdsp, val);
+ change = (int)val != hdsp_line_out(hdsp);
+ hdsp_set_line_output(hdsp, val);
spin_unlock_irq(&hdsp->lock);
- return err ? err : change;
+ return change;
}
-#define HDSP_LINE_OUT(xname, xindex) \
+#define HDSP_PRECISE_POINTER(xname, xindex) \
{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
.name = xname, \
.index = xindex, \
- .info = snd_hdsp_info_line_out, \
- .get = snd_hdsp_get_line_out, \
- .put = snd_hdsp_put_line_out \
+ .info = snd_hdsp_info_precise_pointer, \
+ .get = snd_hdsp_get_precise_pointer, \
+ .put = snd_hdsp_put_precise_pointer \
}
-static int hdsp_line_out(hdsp_t *hdsp)
+static int hdsp_set_precise_pointer(hdsp_t *hdsp, int precise)
{
- return (hdsp->control_register & HDSP_LineOut) ? 1 : 0;
+ if (precise) {
+ hdsp->precise_ptr = 1;
+ } else {
+ hdsp->precise_ptr = 0;
+ }
+ return 0;
}
-static int hdsp_set_line_output(hdsp_t *hdsp, int out)
+static int snd_hdsp_info_precise_pointer(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
{
- if (out) {
- hdsp->control_register |= HDSP_LineOut;
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+ uinfo->count = 1;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 1;
+ return 0;
+}
+
+static int snd_hdsp_get_precise_pointer(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+ hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
+
+ spin_lock_irq(&hdsp->lock);
+ ucontrol->value.integer.value[0] = hdsp->precise_ptr;
+ spin_unlock_irq(&hdsp->lock);
+ return 0;
+}
+
+static int snd_hdsp_put_precise_pointer(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+ hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
+ int change;
+ unsigned int val;
+
+ if (!snd_hdsp_use_is_exclusive(hdsp))
+ return -EBUSY;
+ val = ucontrol->value.integer.value[0] & 1;
+ spin_lock_irq(&hdsp->lock);
+ change = (int)val != hdsp->precise_ptr;
+ hdsp_set_precise_pointer(hdsp, val);
+ spin_unlock_irq(&hdsp->lock);
+ return change;
+}
+
+#define HDSP_USE_MIDI_TASKLET(xname, xindex) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+ .name = xname, \
+ .index = xindex, \
+ .info = snd_hdsp_info_use_midi_tasklet, \
+ .get = snd_hdsp_get_use_midi_tasklet, \
+ .put = snd_hdsp_put_use_midi_tasklet \
+}
+
+static int hdsp_set_use_midi_tasklet(hdsp_t *hdsp, int use_tasklet)
+{
+ if (use_tasklet) {
+ hdsp->use_midi_tasklet = 1;
} else {
- hdsp->control_register &= ~HDSP_LineOut;
+ hdsp->use_midi_tasklet = 0;
}
- hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
return 0;
}
-static int snd_hdsp_info_line_out(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_hdsp_info_use_midi_tasklet(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
@@ -2822,17 +2806,17 @@ 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_use_midi_tasklet(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
spin_lock_irq(&hdsp->lock);
- ucontrol->value.integer.value[0] = hdsp_line_out(hdsp);
+ ucontrol->value.integer.value[0] = hdsp->use_midi_tasklet;
spin_unlock_irq(&hdsp->lock);
return 0;
}
-static int snd_hdsp_put_line_out(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_hdsp_put_use_midi_tasklet(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
int change;
@@ -2842,8 +2826,8 @@ static int snd_hdsp_put_line_out(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
return -EBUSY;
val = ucontrol->value.integer.value[0] & 1;
spin_lock_irq(&hdsp->lock);
- change = (int)val != hdsp_line_out(hdsp);
- hdsp_set_line_output(hdsp, val);
+ change = (int)val != hdsp->use_midi_tasklet;
+ hdsp_set_use_midi_tasklet(hdsp, val);
spin_unlock_irq(&hdsp->lock);
return change;
}
@@ -3139,8 +3123,9 @@ HDSP_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
HDSP_WC_SYNC_CHECK("Word Clock Lock Status", 0),
HDSP_SPDIF_SYNC_CHECK("SPDIF Lock Status", 0),
HDSP_ADATSYNC_SYNC_CHECK("ADAT Sync Lock Status", 0),
-HDSP_PASSTHRU("Passthru", 0),
HDSP_LINE_OUT("Line Out", 0),
+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);
@@ -3240,11 +3225,11 @@ snd_hdsp_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
snd_iprintf(buffer, "Status register: 0x%x\n", status);
snd_iprintf(buffer, "Status2 register: 0x%x\n", status2);
snd_iprintf(buffer, "FIFO status: %d\n", hdsp_read(hdsp, HDSP_fifoStatus) & 0xff);
-
snd_iprintf(buffer, "MIDI1 Output status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusOut0));
snd_iprintf(buffer, "MIDI1 Input status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusIn0));
snd_iprintf(buffer, "MIDI2 Output status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusOut1));
snd_iprintf(buffer, "MIDI2 Input status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusIn1));
+ snd_iprintf(buffer, "Use Midi Tasklet: %s\n", hdsp->use_midi_tasklet ? "on" : "off");
snd_iprintf(buffer, "\n");
@@ -3252,7 +3237,7 @@ snd_hdsp_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
snd_iprintf(buffer, "Buffer Size (Latency): %d samples (2 periods of %lu bytes)\n", x, (unsigned long) hdsp->period_bytes);
snd_iprintf(buffer, "Hardware pointer (frames): %ld\n", hdsp_hw_pointer(hdsp));
- snd_iprintf(buffer, "Passthru: %s\n", hdsp->passthru ? "yes" : "no");
+ snd_iprintf(buffer, "Precise pointer: %s\n", hdsp->precise_ptr ? "on" : "off");
snd_iprintf(buffer, "Line out: %s\n", (hdsp->control_register & HDSP_LineOut) ? "on" : "off");
snd_iprintf(buffer, "Firmware version: %d\n", (status2&HDSP_version0)|(status2&HDSP_version1)<<1|(status2&HDSP_version2)<<2);
@@ -3612,40 +3597,6 @@ static int snd_hdsp_set_defaults(hdsp_t *hdsp)
}
}
- if ((hdsp->io_type != H9652) && line_outs_monitor[hdsp->dev]) {
-
- int lineouts_base;
-
- snd_printk ("sending all inputs and playback streams to line outs.\n");
-
- /* route all inputs to the line outs for easy monitoring. send
- odd numbered channels to right, even to left.
- */
- if (hdsp->io_type == H9632) {
- /* this is the phones/analog output */
- lineouts_base = 10;
- } else {
- lineouts_base = 26;
- }
-
- for (i = 0; i < hdsp->max_channels; i++) {
- if (i & 1) {
- if (hdsp_write_gain (hdsp, hdsp_input_to_output_key (hdsp, i, lineouts_base), UNITY_GAIN) ||
- hdsp_write_gain (hdsp, hdsp_playback_to_output_key (hdsp, i, lineouts_base), UNITY_GAIN)) {
- return -EIO;
- }
- } else {
- if (hdsp_write_gain (hdsp, hdsp_input_to_output_key (hdsp, i, lineouts_base+1), UNITY_GAIN) ||
- hdsp_write_gain (hdsp, hdsp_playback_to_output_key (hdsp, i, lineouts_base+1), UNITY_GAIN)) {
-
- return -EIO;
- }
- }
- }
- }
-
- hdsp->passthru = 0;
-
/* H9632 specific defaults */
if (hdsp->io_type == H9632) {
hdsp->control_register |= (HDSP_DAGainPlus4dBu | HDSP_ADGainPlus4dBu | HDSP_PhoneGain0dB);
@@ -3709,21 +3660,29 @@ static irqreturn_t snd_hdsp_interrupt(int irq, void *dev_id, struct pt_regs *reg
}
if (midi0 && midi0status) {
- /* we disable interrupts for this input until processing is done */
- hdsp->control_register &= ~HDSP_Midi0InterruptEnable;
- hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
- hdsp->midi[0].pending = 1;
- schedule = 1;
+ if (hdsp->use_midi_tasklet) {
+ /* we disable interrupts for this input until processing is done */
+ hdsp->control_register &= ~HDSP_Midi0InterruptEnable;
+ hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
+ hdsp->midi[0].pending = 1;
+ schedule = 1;
+ } else {
+ snd_hdsp_midi_input_read (&hdsp->midi[0]);
+ }
}
- if (midi1 && midi1status) {
- /* we disable interrupts for this input until processing is done */
- hdsp->control_register &= ~HDSP_Midi1InterruptEnable;
- hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
- hdsp->midi[1].pending = 1;
- schedule = 1;
+ if (hdsp->io_type != Multiface && hdsp->io_type != H9632 && midi1 && midi1status) {
+ if (hdsp->use_midi_tasklet) {
+ /* we disable interrupts for this input until processing is done */
+ hdsp->control_register &= ~HDSP_Midi1InterruptEnable;
+ hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
+ hdsp->midi[1].pending = 1;
+ schedule = 1;
+ } else {
+ snd_hdsp_midi_input_read (&hdsp->midi[1]);
+ }
}
- if (schedule)
- tasklet_hi_schedule(&hdsp->midi_tasklet);
+ if (hdsp->use_midi_tasklet && schedule)
+ tasklet_hi_schedule(&hdsp->midi_tasklet);
return IRQ_HANDLED;
}
@@ -3838,10 +3797,10 @@ static int snd_hdsp_hw_params(snd_pcm_substream_t *substream,
if (hdsp_check_for_firmware(hdsp)) {
if (hdsp->state & HDSP_FirmwareCached) {
if (snd_hdsp_load_firmware_from_cache(hdsp) != 0) {
- snd_printk("Firmware loading from cache failed, please upload manually.\n");
+ snd_printk("Hammerfall-DSP: Firmware loading from cache failed, please upload manually.\n");
}
} else {
- snd_printk("No firmware loaded nor cached, please upload firmware.\n");
+ snd_printk("Hammerfall-DSP: No firmware loaded nor cached, please upload firmware.\n");
}
return -EIO;
}
@@ -3957,10 +3916,10 @@ static int snd_hdsp_trigger(snd_pcm_substream_t *substream, int cmd)
if (hdsp_check_for_firmware(hdsp)) {
if (hdsp->state & HDSP_FirmwareCached) {
if (snd_hdsp_load_firmware_from_cache(hdsp) != 0) {
- snd_printk("Firmware loading from cache failed, please upload manually.\n");
+ snd_printk("Hammerfall-DSP: Firmware loading from cache failed, please upload manually.\n");
}
} else {
- snd_printk("No firmware loaded nor cached, please upload firmware.\n");
+ snd_printk("Hammerfall-DSP: No firmware loaded nor cached, please upload firmware.\n");
}
return -EIO;
}
@@ -4035,10 +3994,10 @@ static int snd_hdsp_prepare(snd_pcm_substream_t *substream)
if (hdsp_check_for_firmware(hdsp)) {
if (hdsp->state & HDSP_FirmwareCached) {
if (snd_hdsp_load_firmware_from_cache(hdsp) != 0) {
- snd_printk("Firmware loading from cache failed, please upload manually.\n");
+ snd_printk("Hammerfall-DSP: Firmware loading from cache failed, please upload manually.\n");
}
} else {
- snd_printk("No firmware loaded nor cached, please upload firmware.\n");
+ snd_printk("Hammerfall-DSP: No firmware loaded nor cached, please upload firmware.\n");
}
return -EIO;
}
@@ -4057,7 +4016,11 @@ static snd_pcm_hardware_t snd_hdsp_playback_subinfo =
SNDRV_PCM_INFO_NONINTERLEAVED |
SNDRV_PCM_INFO_SYNC_START |
SNDRV_PCM_INFO_DOUBLE),
+#ifdef SNDRV_BIG_ENDIAN
+ .formats = SNDRV_PCM_FMTBIT_S32_BE,
+#else
.formats = SNDRV_PCM_FMTBIT_S32_LE,
+#endif
.rates = (SNDRV_PCM_RATE_32000 |
SNDRV_PCM_RATE_44100 |
SNDRV_PCM_RATE_48000 |
@@ -4082,7 +4045,11 @@ static snd_pcm_hardware_t snd_hdsp_capture_subinfo =
SNDRV_PCM_INFO_MMAP_VALID |
SNDRV_PCM_INFO_NONINTERLEAVED |
SNDRV_PCM_INFO_SYNC_START),
+#ifdef SNDRV_BIG_ENDIAN
+ .formats = SNDRV_PCM_FMTBIT_S32_BE,
+#else
.formats = SNDRV_PCM_FMTBIT_S32_LE,
+#endif
.rates = (SNDRV_PCM_RATE_32000 |
SNDRV_PCM_RATE_44100 |
SNDRV_PCM_RATE_48000 |
@@ -4290,10 +4257,10 @@ static int snd_hdsp_playback_open(snd_pcm_substream_t *substream)
if (hdsp_check_for_firmware(hdsp)) {
if (hdsp->state & HDSP_FirmwareCached) {
if (snd_hdsp_load_firmware_from_cache(hdsp) != 0) {
- snd_printk("Firmware loading from cache failed, please upload manually.\n");
+ snd_printk("Hammerfall-DSP: Firmware loading from cache failed, please upload manually.\n");
}
} else {
- snd_printk("No firmware loaded nor cached, please upload firmware.\n");
+ snd_printk("Hammerfall-DSP: No firmware loaded nor cached, please upload firmware.\n");
}
return -EIO;
}
@@ -4306,11 +4273,6 @@ static int snd_hdsp_playback_open(snd_pcm_substream_t *substream)
runtime->dma_area = hdsp->playback_buffer;
runtime->dma_bytes = HDSP_DMA_AREA_BYTES;
- if (hdsp->capture_substream == NULL) {
- hdsp_stop_audio(hdsp);
- hdsp_set_thru(hdsp, -1, 0);
- }
-
hdsp->playback_pid = current->pid;
hdsp->playback_substream = substream;
@@ -4373,10 +4335,10 @@ static int snd_hdsp_capture_open(snd_pcm_substream_t *substream)
if (hdsp_check_for_firmware(hdsp)) {
if (hdsp->state & HDSP_FirmwareCached) {
if (snd_hdsp_load_firmware_from_cache(hdsp) != 0) {
- snd_printk("Firmware loading from cache failed, please upload manually.\n");
+ snd_printk("Hammerfall-DSP: Firmware loading from cache failed, please upload manually.\n");
}
} else {
- snd_printk("No firmware loaded nor cached, please upload firmware.\n");
+ snd_printk("Hammerfall-DSP: No firmware loaded nor cached, please upload firmware.\n");
}
return -EIO;
}
@@ -4389,11 +4351,6 @@ static int snd_hdsp_capture_open(snd_pcm_substream_t *substream)
runtime->dma_area = hdsp->capture_buffer;
runtime->dma_bytes = HDSP_DMA_AREA_BYTES;
- if (hdsp->playback_substream == NULL) {
- hdsp_stop_audio(hdsp);
- hdsp_set_thru(hdsp, -1, 0);
- }
-
hdsp->capture_pid = current->pid;
hdsp->capture_substream = substream;
@@ -4553,12 +4510,12 @@ static int hdsp_get_peak(hdsp_t *hdsp, hdsp_peak_rms_t __user *peak_rms)
}
for (i = 0; i < 26; ++i) {
if (copy_u64_le(&peak_rms->playback_rms[i],
- hdsp->iobase + HDSP_playbackRmsLevel + i * 8,
- hdsp->iobase + HDSP_playbackRmsLevel + i * 8 + 4))
+ hdsp->iobase + HDSP_playbackRmsLevel + i * 8 + 4,
+ hdsp->iobase + HDSP_playbackRmsLevel + i * 8))
return -EFAULT;
if (copy_u64_le(&peak_rms->input_rms[i],
- hdsp->iobase + HDSP_inputRmsLevel + i * 8,
- hdsp->iobase + HDSP_inputRmsLevel + i * 8 + 4))
+ hdsp->iobase + HDSP_inputRmsLevel + i * 8 + 4,
+ hdsp->iobase + HDSP_inputRmsLevel + i * 8))
return -EFAULT;
}
return 0;
@@ -4574,7 +4531,7 @@ static int snd_hdsp_hwdep_ioctl(snd_hwdep_t *hw, struct file *file, unsigned int
hdsp_peak_rms_t __user *peak_rms = (hdsp_peak_rms_t __user *)arg;
if (!(hdsp->state & HDSP_FirmwareLoaded)) {
- snd_printk(KERN_ERR "firmware needs to be uploaded to the card.\n");
+ snd_printk(KERN_ERR "Hammerfall-DSP: firmware needs to be uploaded to the card.\n");
return -EINVAL;
}
@@ -4593,7 +4550,7 @@ static int snd_hdsp_hwdep_ioctl(snd_hwdep_t *hw, struct file *file, unsigned int
int i;
if (!(hdsp->state & HDSP_FirmwareLoaded)) {
- snd_printk("Firmware needs to be uploaded to the card.\n");
+ snd_printk("Hammerfall-DSP: Firmware needs to be uploaded to the card.\n");
return -EINVAL;
}
spin_lock_irqsave(&hdsp->lock, flags);
@@ -4618,7 +4575,6 @@ static int snd_hdsp_hwdep_ioctl(snd_hwdep_t *hw, struct file *file, unsigned int
info.clock_source = (unsigned char)hdsp_clock_source(hdsp);
info.autosync_ref = (unsigned char)hdsp_autosync_ref(hdsp);
info.line_out = (unsigned char)hdsp_line_out(hdsp);
- info.passthru = (unsigned char)hdsp->passthru;
if (hdsp->io_type == H9632) {
info.da_gain = (unsigned char)hdsp_da_gain(hdsp);
info.ad_gain = (unsigned char)hdsp_ad_gain(hdsp);
@@ -4661,7 +4617,6 @@ static int snd_hdsp_hwdep_ioctl(snd_hwdep_t *hw, struct file *file, unsigned int
}
break;
}
-#ifndef HDSP_FW_LOADER
case SNDRV_HDSP_IOCTL_UPLOAD_FIRMWARE: {
hdsp_firmware_t __user *firmware;
u32 __user *firmware_data;
@@ -4674,7 +4629,7 @@ static int snd_hdsp_hwdep_ioctl(snd_hwdep_t *hw, struct file *file, unsigned int
if (hdsp->state & (HDSP_FirmwareCached | HDSP_FirmwareLoaded))
return -EBUSY;
- snd_printk("initializing firmware upload\n");
+ snd_printk("Hammerfall-DSP: initializing firmware upload\n");
firmware = (hdsp_firmware_t __user *)argp;
if (get_user(firmware_data, &firmware->firmware_data)) {
@@ -4696,18 +4651,20 @@ static int snd_hdsp_hwdep_ioctl(snd_hwdep_t *hw, struct file *file, unsigned int
}
if (!(hdsp->state & HDSP_InitializationComplete)) {
- snd_hdsp_initialize_channels(hdsp);
-
+ if ((err = snd_hdsp_enable_io(hdsp)) < 0) {
+ return err;
+ }
+
+ snd_hdsp_initialize_channels(hdsp);
snd_hdsp_initialize_midi_flush(hdsp);
if ((err = snd_hdsp_create_alsa_devices(hdsp->card, hdsp)) < 0) {
- snd_printk("error creating alsa devices\n");
+ snd_printk("Hammerfall-DSP: error creating alsa devices\n");
return err;
}
}
break;
}
-#endif
case SNDRV_HDSP_IOCTL_GET_MIXER: {
hdsp_mixer_t __user *mixer = (hdsp_mixer_t __user *)argp;
if (copy_to_user(mixer->matrix, hdsp->mixer_matrix, sizeof(unsigned short)*HDSP_MATRIX_MIXER_SIZE))
@@ -4794,6 +4751,7 @@ static int snd_hdsp_enable_io (hdsp_t *hdsp)
int i;
if (hdsp_fifo_wait (hdsp, 0, 100)) {
+ snd_printk("Hammerfall-DSP: enable_io fifo_wait failed\n");
return -EIO;
}
@@ -4859,24 +4817,25 @@ static int snd_hdsp_create_alsa_devices(snd_card_t *card, hdsp_t *hdsp)
int err;
if ((err = snd_hdsp_create_pcm(card, hdsp)) < 0) {
- snd_printk("Error creating pcm interface\n");
+ snd_printk("Hammerfall-DSP: Error creating pcm interface\n");
return err;
}
if ((err = snd_hdsp_create_midi(card, hdsp, 0)) < 0) {
- snd_printk("Error creating first midi interface\n");
+ snd_printk("Hammerfall-DSP: Error creating first midi interface\n");
return err;
}
-
- if ((err = snd_hdsp_create_midi(card, hdsp, 1)) < 0) {
- snd_printk("Error creating second midi interface\n");
- return err;
+ if (hdsp->io_type == Digiface || hdsp->io_type == H9652) {
+ if ((err = snd_hdsp_create_midi(card, hdsp, 1)) < 0) {
+ snd_printk("Hammerfall-DSP: Error creating second midi interface\n");
+ return err;
+ }
}
if ((err = snd_hdsp_create_controls(card, hdsp)) < 0) {
- snd_printk("Error creating ctl interface\n");
+ snd_printk("Hammerfall-DSP: Error creating ctl interface\n");
return err;
}
@@ -4889,7 +4848,7 @@ static int snd_hdsp_create_alsa_devices(snd_card_t *card, hdsp_t *hdsp)
hdsp->playback_substream = NULL;
if ((err = snd_hdsp_set_defaults(hdsp)) < 0) {
- snd_printk("Error setting default values\n");
+ snd_printk("Hammerfall-DSP: Error setting default values\n");
return err;
}
@@ -4898,7 +4857,7 @@ static int snd_hdsp_create_alsa_devices(snd_card_t *card, hdsp_t *hdsp)
hdsp->port, hdsp->irq);
if ((err = snd_card_register(card)) < 0) {
- snd_printk("error registering card\n");
+ snd_printk("Hammerfall-DSP: error registering card\n");
return err;
}
hdsp->state |= HDSP_InitializationComplete;
@@ -4923,9 +4882,7 @@ static int __devinit hdsp_request_fw_loader(hdsp_t *hdsp)
if (hdsp->io_type == H9652 || hdsp->io_type == H9632)
return 0;
}
- if (hdsp_check_for_iobox (hdsp))
- return -EIO;
-
+
/* caution: max length of firmware filename is 30! */
switch (hdsp->io_type) {
case Multiface:
@@ -4941,16 +4898,16 @@ static int __devinit hdsp_request_fw_loader(hdsp_t *hdsp)
fwfile = "digiface_firmware_rev11.bin";
break;
default:
- snd_printk(KERN_ERR "hdsp: invalid io_type %d\n", hdsp->io_type);
+ snd_printk(KERN_ERR "Hammerfall-DSP: invalid io_type %d\n", hdsp->io_type);
return -EINVAL;
}
if (request_firmware(&fw, fwfile, &hdsp->pci->dev)) {
- snd_printk(KERN_ERR "hdsp: cannot load firmware %s\n", fwfile);
+ snd_printk(KERN_ERR "Hammerfall-DSP: cannot load firmware %s\n", fwfile);
return -ENOENT;
}
if (fw->size < sizeof(hdsp->firmware_cache)) {
- snd_printk(KERN_ERR "hdsp: too short firmware size %d (expected %d)\n",
+ snd_printk(KERN_ERR "Hammerfall-DSP: too short firmware size %d (expected %d)\n",
(int)fw->size, (int)sizeof(hdsp->firmware_cache));
release_firmware(fw);
return -EINVAL;
@@ -4958,7 +4915,7 @@ static int __devinit hdsp_request_fw_loader(hdsp_t *hdsp)
#ifdef SNDRV_BIG_ENDIAN
{
int i;
- u32 *src = (void *)fw->data;
+ u32 *src = (u32*)fw->data;
for (i = 0; i < ARRAY_SIZE(hdsp->firmware_cache); i++, src++)
hdsp->firmware_cache[i] = ((*src & 0x000000ff) << 16) |
((*src & 0x0000ff00) << 8) |
@@ -4969,17 +4926,25 @@ static int __devinit hdsp_request_fw_loader(hdsp_t *hdsp)
memcpy(hdsp->firmware_cache, fw->data, sizeof(hdsp->firmware_cache));
#endif
release_firmware(fw);
-
+
hdsp->state |= HDSP_FirmwareCached;
if ((err = snd_hdsp_load_firmware_from_cache(hdsp)) < 0)
return err;
if (!(hdsp->state & HDSP_InitializationComplete)) {
+ if ((err = snd_hdsp_enable_io(hdsp)) < 0) {
+ return err;
+ }
+
+ if ((err = snd_hdsp_create_hwdep(hdsp->card, hdsp)) < 0) {
+ snd_printk("Hammerfall-DSP: error creating hwdep device\n");
+ return err;
+ }
snd_hdsp_initialize_channels(hdsp);
snd_hdsp_initialize_midi_flush(hdsp);
if ((err = snd_hdsp_create_alsa_devices(hdsp->card, hdsp)) < 0) {
- snd_printk("error creating alsa devices\n");
+ snd_printk("Hammerfall-DSP: error creating alsa devices\n");
return err;
}
}
@@ -4988,8 +4953,7 @@ static int __devinit hdsp_request_fw_loader(hdsp_t *hdsp)
#endif
static int __devinit snd_hdsp_create(snd_card_t *card,
- hdsp_t *hdsp,
- int precise_ptr)
+ hdsp_t *hdsp)
{
struct pci_dev *pci = hdsp->pci;
int err;
@@ -5004,6 +4968,8 @@ static int __devinit snd_hdsp_create(snd_card_t *card,
hdsp->midi[1].input = NULL;
hdsp->midi[0].output = NULL;
hdsp->midi[1].output = NULL;
+ hdsp->midi[0].pending = 0;
+ hdsp->midi[1].pending = 0;
spin_lock_init(&hdsp->midi[0].lock);
spin_lock_init(&hdsp->midi[1].lock);
hdsp->iobase = NULL;
@@ -5019,6 +4985,7 @@ static int __devinit snd_hdsp_create(snd_card_t *card,
tasklet_init(&hdsp->midi_tasklet, hdsp_midi_tasklet, (unsigned long)hdsp);
pci_read_config_word(hdsp->pci, PCI_CLASS_REVISION, &hdsp->firmware_rev);
+ hdsp->firmware_rev &= 0xff;
/* From Martin Bjoernsen :
"It is important that the card's latency timer register in
@@ -5032,27 +4999,17 @@ static int __devinit snd_hdsp_create(snd_card_t *card,
strcpy(card->driver, "H-DSP");
strcpy(card->mixername, "Xilinx FPGA");
- switch (hdsp->firmware_rev & 0xff) {
- case 0xa:
- case 0xb:
- case 0x32:
+ if (hdsp->firmware_rev < 0xa) {
+ return -ENODEV;
+ } else if (hdsp->firmware_rev < 0x64) {
hdsp->card_name = "RME Hammerfall DSP";
- break;
-
- case 0x64:
- case 0x65:
- case 0x68:
+ } else if (hdsp->firmware_rev < 0x96) {
hdsp->card_name = "RME HDSP 9652";
is_9652 = 1;
- break;
- case 0x96:
- case 0x97:
+ } else {
hdsp->card_name = "RME HDSP 9632";
hdsp->max_channels = 16;
- is_9632 = 1;
- break;
- default:
- return -ENODEV;
+ is_9632 = 1;
}
if ((err = pci_enable_device(pci)) < 0) {
@@ -5065,56 +5022,65 @@ static int __devinit snd_hdsp_create(snd_card_t *card,
return err;
hdsp->port = pci_resource_start(pci, 0);
if ((hdsp->iobase = ioremap_nocache(hdsp->port, HDSP_IO_EXTENT)) == NULL) {
- snd_printk("unable to remap region 0x%lx-0x%lx\n", hdsp->port, hdsp->port + HDSP_IO_EXTENT - 1);
+ snd_printk("Hammerfall-DSP: unable to remap region 0x%lx-0x%lx\n", hdsp->port, hdsp->port + HDSP_IO_EXTENT - 1);
return -EBUSY;
}
if (request_irq(pci->irq, snd_hdsp_interrupt, SA_INTERRUPT|SA_SHIRQ, "hdsp", (void *)hdsp)) {
- snd_printk("unable to use IRQ %d\n", pci->irq);
+ snd_printk("Hammerfall-DSP: unable to use IRQ %d\n", pci->irq);
return -EBUSY;
}
hdsp->irq = pci->irq;
- hdsp->precise_ptr = precise_ptr;
+ hdsp->precise_ptr = 1;
+ hdsp->use_midi_tasklet = 1;
if ((err = snd_hdsp_initialize_memory(hdsp)) < 0) {
return err;
}
- if (!is_9652 && !is_9632 && hdsp_check_for_iobox (hdsp)) {
- /* no iobox connected, we defer initialization */
- snd_printk("card initialization pending : waiting for firmware\n");
- if ((err = snd_hdsp_create_hwdep(card, hdsp)) < 0) {
- return err;
+ if (!is_9652 && !is_9632) {
+ /* we wait 2 seconds to let freshly inserted cardbus cards do their hardware init */
+ if ((1000 / HZ) < 2000) {
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout((2000 * HZ + 999) / 1000);
+ } else {
+ mdelay(2000);
+ }
+
+ if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) {
+#ifdef HDSP_FW_LOADER
+ if ((err = hdsp_request_fw_loader(hdsp)) < 0) {
+ /* we don't fail as this can happen
+ if userspace is not ready for
+ firmware upload
+ */
+ snd_printk("Hammerfall-DSP: couldn't get firmware from userspace. try using hdsploader\n");
+ } else {
+ /* init is complete, we return */
+ return 0;
+ }
+#endif
+ /* no iobox connected, we defer initialization */
+ snd_printk("Hammerfall-DSP: card initialization pending : waiting for firmware\n");
+ if ((err = snd_hdsp_create_hwdep(card, hdsp)) < 0) {
+ return err;
+ }
+ return 0;
+ } else {
+ snd_printk("Hammerfall-DSP: Firmware already present, initializing card.\n");
+ if (hdsp_read(hdsp, HDSP_status2Register) & HDSP_version1) {
+ hdsp->io_type = Multiface;
+ } else {
+ hdsp->io_type = Digiface;
+ }
}
- return 0;
}
if ((err = snd_hdsp_enable_io(hdsp)) != 0) {
return err;
}
- if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) {
-#ifdef HDSP_FW_LOADER
- if ((err = hdsp_request_fw_loader(hdsp)) < 0)
- return err;
-#else
- snd_printk("card initialization pending : waiting for firmware\n");
- if ((err = snd_hdsp_create_hwdep(card, hdsp)) < 0) {
- return err;
- }
- return 0;
-#endif
- }
-
- snd_printk("Firmware already loaded, initializing card.\n");
-
- if (hdsp_read(hdsp, HDSP_status2Register) & HDSP_version1) {
- hdsp->io_type = Multiface;
- } else {
- hdsp->io_type = Digiface;
- }
-
if (is_9652) {
hdsp->io_type = H9652;
}
@@ -5143,6 +5109,7 @@ static int snd_hdsp_free(hdsp_t *hdsp)
{
if (hdsp->port) {
/* stop the audio, and cancel all interrupts */
+ tasklet_kill(&hdsp->midi_tasklet);
hdsp->control_register &= ~(HDSP_Start|HDSP_AudioInterruptEnable|HDSP_Midi0InterruptEnable|HDSP_Midi1InterruptEnable);
hdsp_write (hdsp, HDSP_controlRegister, hdsp->control_register);
}
@@ -5194,7 +5161,7 @@ static int __devinit snd_hdsp_probe(struct pci_dev *pci,
hdsp->pci = pci;
snd_card_set_dev(card, &pci->dev);
- if ((err = snd_hdsp_create(card, hdsp, precise_ptr[dev])) < 0) {
+ if ((err = snd_hdsp_create(card, hdsp)) < 0) {
snd_card_free(card);
return err;
}
diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c
index 694a967bad007..cfd2c5fd6ddf5 100644
--- a/sound/pci/sonicvibes.c
+++ b/sound/pci/sonicvibes.c
@@ -46,6 +46,10 @@ MODULE_DESCRIPTION("S3 SonicVibes PCI");
MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("{{S3,SonicVibes PCI}}");
+#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
+#define SUPPORT_JOYSTICK 1
+#endif
+
#ifndef PCI_VENDOR_ID_S3
#define PCI_VENDOR_ID_S3 0x5333
#endif
@@ -242,8 +246,8 @@ struct _snd_sonicvibes {
snd_kcontrol_t *master_mute;
snd_kcontrol_t *master_volume;
-#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
- struct gameport gameport;
+#ifdef SUPPORT_JOYSTICK
+ struct gameport *gameport;
#endif
};
@@ -1163,15 +1167,47 @@ static void __devinit snd_sonicvibes_proc_init(sonicvibes_t * sonic)
*/
+#ifdef SUPPORT_JOYSTICK
static snd_kcontrol_new_t snd_sonicvibes_game_control __devinitdata =
SONICVIBES_SINGLE("Joystick Speed", 0, SV_IREG_GAME_PORT, 1, 15, 0);
-static int snd_sonicvibes_free(sonicvibes_t *sonic)
+static int __devinit snd_sonicvibes_create_gameport(sonicvibes_t *sonic)
{
-#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
- if (sonic->gameport.io)
- gameport_unregister_port(&sonic->gameport);
+ struct gameport *gp;
+
+ sonic->gameport = gp = gameport_allocate_port();
+ if (!gp) {
+ printk(KERN_ERR "sonicvibes: cannot allocate memory for gameport\n");
+ return -ENOMEM;
+ }
+
+ gameport_set_name(gp, "SonicVibes Gameport");
+ gameport_set_phys(gp, "pci%s/gameport0", pci_name(sonic->pci));
+ gameport_set_dev_parent(gp, &sonic->pci->dev);
+ gp->io = sonic->game_port;
+
+ gameport_register_port(gp);
+
+ snd_ctl_add(sonic->card, snd_ctl_new1(&snd_sonicvibes_game_control, sonic));
+
+ return 0;
+}
+
+static void snd_sonicvibes_free_gameport(sonicvibes_t *sonic)
+{
+ if (sonic->gameport) {
+ gameport_unregister_port(sonic->gameport);
+ sonic->gameport = NULL;
+ }
+}
+#else
+static inline int snd_sonicvibes_create_gameport(sonicvibes_t *sonic) { return -ENOSYS; }
+static inline void snd_sonicvibes_free_gameport(sonicvibes_t *sonic) { }
#endif
+
+static int snd_sonicvibes_free(sonicvibes_t *sonic)
+{
+ snd_sonicvibes_free_gameport(sonic);
pci_write_config_dword(sonic->pci, 0x40, sonic->dmaa_port);
pci_write_config_dword(sonic->pci, 0x48, sonic->dmac_port);
if (sonic->irq >= 0)
@@ -1332,7 +1368,6 @@ static int __devinit snd_sonicvibes_create(snd_card_t * card,
snd_sonicvibes_debug(sonic);
#endif
sonic->revision = snd_sonicvibes_in(sonic, SV_IREG_REVISION);
- snd_ctl_add(card, snd_ctl_new1(&snd_sonicvibes_game_control, sonic));
if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, sonic, &ops)) < 0) {
snd_sonicvibes_free(sonic);
@@ -1459,10 +1494,8 @@ static int __devinit snd_sonic_probe(struct pci_dev *pci,
snd_card_free(card);
return err;
}
-#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
- sonic->gameport.io = sonic->game_port;
- gameport_register_port(&sonic->gameport);
-#endif
+
+ snd_sonicvibes_create_gameport(sonic);
if ((err = snd_card_register(card)) < 0) {
snd_card_free(card);
diff --git a/sound/pci/trident/trident.c b/sound/pci/trident/trident.c
index 8304190f855cf..ad58e08d66e2c 100644
--- a/sound/pci/trident/trident.c
+++ b/sound/pci/trident/trident.c
@@ -157,7 +157,7 @@ static int __devinit snd_trident_probe(struct pci_dev *pci,
}
#endif
- snd_trident_gameport(trident);
+ snd_trident_create_gameport(trident);
if ((err = snd_card_register(card)) < 0) {
snd_card_free(card);
diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c
index cafa9abe7e73a..ccd5ca2ba16f5 100644
--- a/sound/pci/trident/trident_main.c
+++ b/sound/pci/trident/trident_main.c
@@ -48,8 +48,8 @@ static int snd_trident_pcm_mixer_build(trident_t *trident, snd_trident_voice_t *
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, unsigned int state);
-static int snd_trident_resume(snd_card_t *card, unsigned int state);
+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);
@@ -3110,37 +3110,28 @@ static int __devinit snd_trident_mixer(trident_t * trident, int pcm_spdif_device
#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
-typedef struct snd_trident_gameport {
- struct gameport info;
- trident_t *chip;
-} trident_gameport_t;
-
static unsigned char snd_trident_gameport_read(struct gameport *gameport)
{
- trident_gameport_t *gp = (trident_gameport_t *)gameport;
- trident_t *chip;
- snd_assert(gp, return 0);
- chip = gp->chip;
+ trident_t *chip = gameport_get_port_data(gameport);
+
+ snd_assert(chip, return 0);
return inb(TRID_REG(chip, GAMEPORT_LEGACY));
}
static void snd_trident_gameport_trigger(struct gameport *gameport)
{
- trident_gameport_t *gp = (trident_gameport_t *)gameport;
- trident_t *chip;
- snd_assert(gp, return);
- chip = gp->chip;
+ trident_t *chip = gameport_get_port_data(gameport);
+
+ snd_assert(chip, return);
outb(0xff, TRID_REG(chip, GAMEPORT_LEGACY));
}
static int snd_trident_gameport_cooked_read(struct gameport *gameport, int *axes, int *buttons)
{
- trident_gameport_t *gp = (trident_gameport_t *)gameport;
- trident_t *chip;
+ trident_t *chip = gameport_get_port_data(gameport);
int i;
- snd_assert(gp, return 0);
- chip = gp->chip;
+ snd_assert(chip, return 0);
*buttons = (~inb(TRID_REG(chip, GAMEPORT_LEGACY)) >> 4) & 0xf;
@@ -3154,10 +3145,9 @@ static int snd_trident_gameport_cooked_read(struct gameport *gameport, int *axes
static int snd_trident_gameport_open(struct gameport *gameport, int mode)
{
- trident_gameport_t *gp = (trident_gameport_t *)gameport;
- trident_t *chip;
- snd_assert(gp, return -1);
- chip = gp->chip;
+ trident_t *chip = gameport_get_port_data(gameport);
+
+ snd_assert(chip, return 0);
switch (mode) {
case GAMEPORT_MODE_COOKED:
@@ -3173,30 +3163,42 @@ static int snd_trident_gameport_open(struct gameport *gameport, int mode)
}
}
-void __devinit snd_trident_gameport(trident_t *chip)
+int __devinit snd_trident_create_gameport(trident_t *chip)
{
- trident_gameport_t *gp;
- gp = kmalloc(sizeof(*gp), GFP_KERNEL);
- if (! gp) {
- snd_printk("cannot allocate gameport area\n");
- return;
+ struct gameport *gp;
+
+ chip->gameport = gp = gameport_allocate_port();
+ if (!gp) {
+ printk(KERN_ERR "trident: cannot allocate memory for gameport\n");
+ return -ENOMEM;
}
- memset(gp, 0, sizeof(*gp));
- gp->chip = chip;
- gp->info.fuzz = 64;
- gp->info.read = snd_trident_gameport_read;
- gp->info.trigger = snd_trident_gameport_trigger;
- gp->info.cooked_read = snd_trident_gameport_cooked_read;
- gp->info.open = snd_trident_gameport_open;
- chip->gameport = gp;
- gameport_register_port(&gp->info);
+ gameport_set_name(gp, "Trident 4DWave");
+ gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci));
+ gameport_set_dev_parent(gp, &chip->pci->dev);
+
+ gameport_set_port_data(gp, chip);
+ gp->fuzz = 64;
+ gp->read = snd_trident_gameport_read;
+ gp->trigger = snd_trident_gameport_trigger;
+ gp->cooked_read = snd_trident_gameport_cooked_read;
+ gp->open = snd_trident_gameport_open;
+
+ gameport_register_port(gp);
+
+ return 0;
}
-#else
-void __devinit snd_trident_gameport(trident_t *chip)
+static inline void snd_trident_free_gameport(trident_t *chip)
{
+ if (chip->gameport) {
+ gameport_unregister_port(chip->gameport);
+ chip->gameport = NULL;
+ }
}
+#else
+int __devinit snd_trident_create_gameport(trident_t *chip) { return -ENOSYS; }
+static inline void snd_trident_free_gameport(trident_t *chip) { }
#endif /* CONFIG_GAMEPORT */
/*
@@ -3661,12 +3663,7 @@ int __devinit snd_trident_create(snd_card_t * card,
static int snd_trident_free(trident_t *trident)
{
-#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
- if (trident->gameport) {
- gameport_unregister_port(&trident->gameport->info);
- kfree(trident->gameport);
- }
-#endif
+ snd_trident_free_gameport(trident);
snd_trident_disable_eso(trident);
// Disable S/PDIF out
if (trident->device == TRIDENT_DEVICE_ID_NX)
@@ -3921,7 +3918,7 @@ 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, unsigned int state)
+static int snd_trident_suspend(snd_card_t *card, pm_message_t state)
{
trident_t *trident = card->pm_private_data;
@@ -3947,7 +3944,7 @@ static int snd_trident_suspend(snd_card_t *card, unsigned int state)
return 0;
}
-static int snd_trident_resume(snd_card_t *card, unsigned int state)
+static int snd_trident_resume(snd_card_t *card)
{
trident_t *trident = card->pm_private_data;
diff --git a/sound/pci/trident/trident_synth.c b/sound/pci/trident/trident_synth.c
index 64aab2346b464..5d5a719b05859 100644
--- a/sound/pci/trident/trident_synth.c
+++ b/sound/pci/trident/trident_synth.c
@@ -525,7 +525,7 @@ static int snd_trident_simple_put_sample(void *private_data, simple_instrument_t
if (trident->synth.current_size + size > trident->synth.max_size)
return -ENOMEM;
- if (verify_area(VERIFY_READ, data, size))
+ if (!access_ok(VERIFY_READ, data, size))
return -EFAULT;
if (trident->tlb.entries) {
@@ -570,7 +570,7 @@ static int snd_trident_simple_get_sample(void *private_data, simple_instrument_t
shift++;
size <<= shift;
- if (verify_area(VERIFY_WRITE, data, size))
+ if (!access_ok(VERIFY_WRITE, data, size))
return -EFAULT;
/* FIXME: not implemented yet */
diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c
index 5b26b52d55e57..f1ce808501da5 100644
--- a/sound/pci/via82xx.c
+++ b/sound/pci/via82xx.c
@@ -367,7 +367,7 @@ struct _snd_via82xx {
unsigned int mpu_port_saved;
#endif
- unsigned char playback_volume[4][2]; /* for VIA8233/C/8235; default = 0 */
+ unsigned char playback_volume[2]; /* for VIA8233/C/8235; default = 0 */
unsigned int intr_mask; /* SGD_SHADOW mask to check interrupts */
@@ -394,8 +394,7 @@ struct _snd_via82xx {
snd_info_entry_t *proc_entry;
#ifdef SUPPORT_JOYSTICK
- struct gameport gameport;
- struct resource *res_joystick;
+ struct gameport *gameport;
#endif
};
@@ -942,8 +941,8 @@ static int snd_via8233_playback_prepare(snd_pcm_substream_t *substream)
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[0], VIADEV_REG(viadev, OFS_PLAYBACK_VOLUME_L));
+ outb(chip->playback_volume[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 */
@@ -1497,17 +1496,15 @@ static int snd_via8233_dxs_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_in
static int snd_via8233_dxs_volume_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
{
via82xx_t *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];
- ucontrol->value.integer.value[1] = VIA_DXS_MAX_VOLUME - chip->playback_volume[idx][1];
+ ucontrol->value.integer.value[0] = VIA_DXS_MAX_VOLUME - chip->playback_volume[0];
+ ucontrol->value.integer.value[1] = VIA_DXS_MAX_VOLUME - chip->playback_volume[1];
return 0;
}
static int snd_via8233_dxs_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
{
via82xx_t *chip = snd_kcontrol_chip(kcontrol);
- unsigned int idx = snd_ctl_get_ioff(kcontrol, &ucontrol->id);
- unsigned long port = chip->port + 0x10 * idx;
+ unsigned int idx;
unsigned char val;
int i, change = 0;
@@ -1516,19 +1513,21 @@ static int snd_via8233_dxs_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_val
if (val > VIA_DXS_MAX_VOLUME)
val = VIA_DXS_MAX_VOLUME;
val = VIA_DXS_MAX_VOLUME - val;
- change |= val != chip->playback_volume[idx][i];
- if (change) {
- chip->playback_volume[idx][i] = val;
- outb(val, port + VIA_REG_OFS_PLAYBACK_VOLUME_L + i);
+ if (val != chip->playback_volume[i]) {
+ change = 1;
+ chip->playback_volume[i] = val;
+ for (idx = 0; idx < 4; idx++) {
+ unsigned long port = chip->port + 0x10 * idx;
+ outb(val, port + VIA_REG_OFS_PLAYBACK_VOLUME_L + i);
+ }
}
}
return change;
}
static snd_kcontrol_new_t snd_via8233_dxs_volume_control __devinitdata = {
- .name = "VIA DXS Playback Volume",
+ .name = "PCM Playback Volume",
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .count = 4,
.info = snd_via8233_dxs_volume_info,
.get = snd_via8233_dxs_volume_get,
.put = snd_via8233_dxs_volume_put,
@@ -1635,11 +1634,70 @@ static int __devinit snd_via82xx_mixer_new(via82xx_t *chip, const char *quirk_ov
return 0;
}
+#ifdef SUPPORT_JOYSTICK
+#define JOYSTICK_ADDR 0x200
+static int __devinit snd_via686_create_gameport(via82xx_t *chip, int dev, unsigned char *legacy)
+{
+ struct gameport *gp;
+ struct resource *r;
+
+ if (!joystick[dev])
+ return -ENODEV;
+
+ r = request_region(JOYSTICK_ADDR, 8, "VIA686 gameport");
+ if (!r) {
+ printk(KERN_WARNING "via82xx: cannot reserve joystick port 0x%#x\n", JOYSTICK_ADDR);
+ return -EBUSY;
+ }
+
+ chip->gameport = gp = gameport_allocate_port();
+ if (!gp) {
+ printk(KERN_ERR "via82xx: cannot allocate memory for gameport\n");
+ release_resource(r);
+ kfree_nocheck(r);
+ return -ENOMEM;
+ }
+
+ gameport_set_name(gp, "VIA686 Gameport");
+ gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci));
+ gameport_set_dev_parent(gp, &chip->pci->dev);
+ gp->io = JOYSTICK_ADDR;
+ gameport_set_port_data(gp, r);
+
+ /* Enable legacy joystick port */
+ *legacy |= VIA_FUNC_ENABLE_GAME;
+ pci_write_config_byte(chip->pci, VIA_FUNC_ENABLE, *legacy);
+
+ gameport_register_port(chip->gameport);
+
+ return 0;
+}
+
+static void snd_via686_free_gameport(via82xx_t *chip)
+{
+ if (chip->gameport) {
+ struct resource *r = gameport_get_port_data(chip->gameport);
+
+ gameport_unregister_port(chip->gameport);
+ chip->gameport = NULL;
+ release_resource(r);
+ kfree_nocheck(r);
+ }
+}
+#else
+static inline int snd_via686_create_gameport(via82xx_t *chip, int dev, unsigned char *legacy)
+{
+ return -ENOSYS;
+}
+static inline void snd_via686_free_gameport(via82xx_t *chip) { }
+#endif
+
+
/*
*
*/
-static int snd_via8233_init_misc(via82xx_t *chip, int dev)
+static int __devinit snd_via8233_init_misc(via82xx_t *chip, int dev)
{
int i, err, caps;
unsigned char val;
@@ -1657,9 +1715,18 @@ static int snd_via8233_init_misc(via82xx_t *chip, int dev)
return err;
}
if (chip->chip_type != TYPE_VIA8233A) {
- err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_via8233_dxs_volume_control, chip));
- if (err < 0)
- return err;
+ /* when no h/w PCM volume control is found, use DXS volume control
+ * as the PCM vol control
+ */
+ snd_ctl_elem_id_t sid;
+ memset(&sid, 0, sizeof(sid));
+ strcpy(sid.name, "PCM Playback Volume");
+ sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+ if (! snd_ctl_find_id(chip->card, &sid)) {
+ err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_via8233_dxs_volume_control, chip));
+ if (err < 0)
+ return err;
+ }
}
/* select spdif data slot 10/11 */
@@ -1671,7 +1738,7 @@ static int snd_via8233_init_misc(via82xx_t *chip, int dev)
return 0;
}
-static int snd_via686_init_misc(via82xx_t *chip, int dev)
+static int __devinit snd_via686_init_misc(via82xx_t *chip, int dev)
{
unsigned char legacy, legacy_cfg;
int rev_h = 0;
@@ -1718,15 +1785,6 @@ static int snd_via686_init_misc(via82xx_t *chip, int dev)
mpu_port[dev] = 0;
}
-#ifdef SUPPORT_JOYSTICK
-#define JOYSTICK_ADDR 0x200
- if (joystick[dev] &&
- (chip->res_joystick = request_region(JOYSTICK_ADDR, 8, "VIA686 gameport")) != NULL) {
- legacy |= VIA_FUNC_ENABLE_GAME;
- chip->gameport.io = JOYSTICK_ADDR;
- }
-#endif
-
pci_write_config_byte(chip->pci, VIA_FUNC_ENABLE, legacy);
pci_write_config_byte(chip->pci, VIA_PNP_CONTROL, legacy_cfg);
if (chip->mpu_res) {
@@ -1741,10 +1799,7 @@ static int snd_via686_init_misc(via82xx_t *chip, int dev)
pci_write_config_byte(chip->pci, VIA_FUNC_ENABLE, legacy);
}
-#ifdef SUPPORT_JOYSTICK
- if (chip->res_joystick)
- gameport_register_port(&chip->gameport);
-#endif
+ snd_via686_create_gameport(chip, dev, &legacy);
#ifdef CONFIG_PM
chip->legacy_saved = legacy;
@@ -1783,14 +1838,10 @@ static void __devinit snd_via82xx_proc_init(via82xx_t *chip)
static int __devinit snd_via82xx_chip_init(via82xx_t *chip)
{
- ac97_t ac97;
unsigned int val;
int max_count;
unsigned char pval;
- memset(&ac97, 0, sizeof(ac97));
- ac97.private_data = chip;
-
#if 0 /* broken on K7M? */
if (chip->chip_type == TYPE_VIA686)
/* disable all legacy ports */
@@ -1842,11 +1893,6 @@ static int __devinit snd_via82xx_chip_init(via82xx_t *chip)
if ((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_BUSY)
snd_printk("AC'97 codec is not ready [0x%x]\n", val);
- /* and then reset codec.. */
- snd_via82xx_codec_ready(chip, 0);
- snd_via82xx_codec_write(&ac97, AC97_RESET, 0x0000);
- snd_via82xx_codec_read(&ac97, 0);
-
#if 0 /* FIXME: we don't support the second codec yet so skip the detection now.. */
snd_via82xx_codec_xwrite(chip, VIA_REG_AC97_READ |
VIA_REG_AC97_SECONDARY_VALID |
@@ -1888,6 +1934,15 @@ static int __devinit snd_via82xx_chip_init(via82xx_t *chip)
}
}
+ if (chip->chip_type != TYPE_VIA8233A) {
+ int i, idx;
+ for (idx = 0; idx < 4; idx++) {
+ unsigned long port = chip->port + 0x10 * idx;
+ for (i = 0; i < 2; i++)
+ outb(chip->playback_volume[i], port + VIA_REG_OFS_PLAYBACK_VOLUME_L + i);
+ }
+ }
+
return 0;
}
@@ -1895,7 +1950,7 @@ static int __devinit snd_via82xx_chip_init(via82xx_t *chip)
/*
* power management
*/
-static int snd_via82xx_suspend(snd_card_t *card, unsigned int state)
+static int snd_via82xx_suspend(snd_card_t *card, pm_message_t state)
{
via82xx_t *chip = card->pm_private_data;
int i;
@@ -1920,10 +1975,10 @@ static int snd_via82xx_suspend(snd_card_t *card, unsigned int state)
return 0;
}
-static int snd_via82xx_resume(snd_card_t *card, unsigned int state)
+static int snd_via82xx_resume(snd_card_t *card)
{
via82xx_t *chip = card->pm_private_data;
- int idx, i;
+ int i;
pci_enable_device(chip->pci);
pci_set_power_state(chip->pci, 0);
@@ -1939,11 +1994,6 @@ static int snd_via82xx_resume(snd_card_t *card, unsigned int state)
pci_write_config_byte(chip->pci, VIA8233_SPDIF_CTRL, chip->spdif_ctrl_saved);
outb(chip->capture_src_saved[0], chip->port + VIA_REG_CAPTURE_CHANNEL);
outb(chip->capture_src_saved[1], chip->port + VIA_REG_CAPTURE_CHANNEL + 0x10);
- for (idx = 0; idx < 4; idx++) {
- unsigned long port = chip->port + 0x10 * idx;
- for (i = 0; i < 2; i++)
- outb(chip->playback_volume[idx][i], port + VIA_REG_OFS_PLAYBACK_VOLUME_L + i);
- }
}
snd_ac97_resume(chip->ac97);
@@ -1973,14 +2023,9 @@ static int snd_via82xx_free(via82xx_t *chip)
kfree_nocheck(chip->mpu_res);
}
pci_release_regions(chip->pci);
+
if (chip->chip_type == TYPE_VIA686) {
-#ifdef SUPPORT_JOYSTICK
- if (chip->res_joystick) {
- gameport_unregister_port(&chip->gameport);
- release_resource(chip->res_joystick);
- kfree_nocheck(chip->res_joystick);
- }
-#endif
+ snd_via686_free_gameport(chip);
pci_write_config_byte(chip->pci, VIA_FUNC_ENABLE, chip->old_legacy);
pci_write_config_byte(chip->pci, VIA_PNP_CONTROL, chip->old_legacy_cfg);
}
@@ -2114,6 +2159,7 @@ static int __devinit check_dxs_list(struct pci_dev *pci)
{ .vendor = 0x1458, .device = 0xa002, .action = VIA_DXS_ENABLE }, /* Gigabyte GA-7VAXP */
{ .vendor = 0x1462, .device = 0x3800, .action = VIA_DXS_ENABLE }, /* MSI KT266 */
{ .vendor = 0x1462, .device = 0x5901, .action = VIA_DXS_NO_VRA }, /* MSI KT6 Delta-SR */
+ { .vendor = 0x1462, .device = 0x7023, .action = VIA_DXS_NO_VRA }, /* MSI K8T Neo2-FI */
{ .vendor = 0x1462, .device = 0x7120, .action = VIA_DXS_ENABLE }, /* MSI KT4V */
{ .vendor = 0x147b, .device = 0x1401, .action = VIA_DXS_ENABLE }, /* ABIT KD7(-RAID) */
{ .vendor = 0x147b, .device = 0x1411, .action = VIA_DXS_ENABLE }, /* ABIT VA-20 */
diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c
index 0b5f2ad290151..ea5c6f6401593 100644
--- a/sound/pci/via82xx_modem.c
+++ b/sound/pci/via82xx_modem.c
@@ -55,7 +55,7 @@ MODULE_DESCRIPTION("VIA VT82xx modem");
MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("{{VIA,VT82C686A/B/C modem,pci}}");
-static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
+static int index[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = -2}; /* Exclude the first card */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
static int ac97_clock[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 48000};
@@ -940,14 +940,10 @@ static void __devinit snd_via82xx_proc_init(via82xx_t *chip)
static int __devinit snd_via82xx_chip_init(via82xx_t *chip)
{
- ac97_t ac97;
unsigned int val;
int max_count;
unsigned char pval;
- memset(&ac97, 0, sizeof(ac97));
- ac97.private_data = chip;
-
pci_read_config_byte(chip->pci, VIA_MC97_CTRL, &pval);
if((pval & VIA_MC97_CTRL_INIT) != VIA_MC97_CTRL_INIT) {
pci_write_config_byte(chip->pci, 0x44, pval|VIA_MC97_CTRL_INIT);
@@ -996,13 +992,6 @@ static int __devinit snd_via82xx_chip_init(via82xx_t *chip)
if ((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_BUSY)
snd_printk("AC'97 codec is not ready [0x%x]\n", val);
- /* and then reset codec.. */
-#if 0 /* do we need it? when? */
- snd_via82xx_codec_ready(chip, 0);
- snd_via82xx_codec_write(&ac97, AC97_RESET, 0x0000);
- snd_via82xx_codec_read(&ac97, 0);
-#endif
-
snd_via82xx_codec_xwrite(chip, VIA_REG_AC97_READ |
VIA_REG_AC97_SECONDARY_VALID |
(VIA_REG_AC97_CODEC_ID_SECONDARY << VIA_REG_AC97_CODEC_ID_SHIFT));
@@ -1034,7 +1023,7 @@ static int __devinit snd_via82xx_chip_init(via82xx_t *chip)
/*
* power management
*/
-static int snd_via82xx_suspend(snd_card_t *card, unsigned int state)
+static int snd_via82xx_suspend(snd_card_t *card, pm_message_t state)
{
via82xx_t *chip = card->pm_private_data;
int i;
@@ -1051,7 +1040,7 @@ static int snd_via82xx_suspend(snd_card_t *card, unsigned int state)
return 0;
}
-static int snd_via82xx_resume(snd_card_t *card, unsigned int state)
+static int snd_via82xx_resume(snd_card_t *card)
{
via82xx_t *chip = card->pm_private_data;
int i;
diff --git a/sound/pci/vx222/vx222_ops.c b/sound/pci/vx222/vx222_ops.c
index 22a9c6a79d889..683e9799976f3 100644
--- a/sound/pci/vx222/vx222_ops.c
+++ b/sound/pci/vx222/vx222_ops.c
@@ -22,6 +22,7 @@
#include <sound/driver.h>
#include <linux/delay.h>
+#include <linux/device.h>
#include <linux/firmware.h>
#include <sound/core.h>
#include <sound/control.h>
diff --git a/sound/pci/ymfpci/ymfpci.c b/sound/pci/ymfpci/ymfpci.c
index a4afa4b694e1c..9f3ef22df08dd 100644
--- a/sound/pci/ymfpci/ymfpci.c
+++ b/sound/pci/ymfpci/ymfpci.c
@@ -79,6 +79,97 @@ 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,
+ int legacy_ctrl, int legacy_ctrl2)
+{
+ struct gameport *gp;
+ struct resource *r = NULL;
+ int io_port = joystick_port[dev];
+
+ if (!io_port)
+ return -ENODEV;
+
+ if (chip->pci->device >= 0x0010) { /* YMF 744/754 */
+
+ if (io_port == 1) {
+ /* auto-detect */
+ if (!(io_port = pci_resource_start(chip->pci, 2)))
+ return -ENODEV;
+ }
+ } else {
+ if (io_port == 1) {
+ /* auto-detect */
+ for (io_port = 0x201; io_port <= 0x205; io_port++) {
+ if (io_port == 0x203)
+ continue;
+ if ((r = request_region(io_port, 1, "YMFPCI gameport")) != NULL)
+ break;
+ }
+ if (!r) {
+ printk(KERN_ERR "ymfpci: no gameport ports available\n");
+ return -EBUSY;
+ }
+ }
+ switch (io_port) {
+ case 0x201: legacy_ctrl2 |= 0 << 6; break;
+ case 0x202: legacy_ctrl2 |= 1 << 6; break;
+ case 0x204: legacy_ctrl2 |= 2 << 6; break;
+ case 0x205: legacy_ctrl2 |= 3 << 6; break;
+ default:
+ printk(KERN_ERR "ymfpci: invalid joystick port %#x", io_port);
+ return -EINVAL;
+ }
+ }
+
+ if (!r && !(r = request_region(io_port, 1, "YMFPCI gameport"))) {
+ printk(KERN_ERR "ymfpci: joystick port %#x is in use.\n", io_port);
+ return -EBUSY;
+ }
+
+ chip->gameport = gp = gameport_allocate_port();
+ if (!gp) {
+ printk(KERN_ERR "ymfpci: cannot allocate memory for gameport\n");
+ release_resource(r);
+ kfree_nocheck(r);
+ return -ENOMEM;
+ }
+
+
+ gameport_set_name(gp, "Yamaha YMF Gameport");
+ gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci));
+ gameport_set_dev_parent(gp, &chip->pci->dev);
+ gp->io = io_port;
+ gameport_set_port_data(gp, r);
+
+ if (chip->pci->device >= 0x0010) /* YMF 744/754 */
+ pci_write_config_word(chip->pci, PCIR_DSXG_JOYBASE, io_port);
+
+ pci_write_config_word(chip->pci, PCIR_DSXG_LEGACY, legacy_ctrl | YMFPCI_LEGACY_JPEN);
+ pci_write_config_word(chip->pci, PCIR_DSXG_ELEGACY, legacy_ctrl2);
+
+ gameport_register_port(chip->gameport);
+
+ return 0;
+}
+
+void snd_ymfpci_free_gameport(ymfpci_t *chip)
+{
+ if (chip->gameport) {
+ struct resource *r = gameport_get_port_data(chip->gameport);
+
+ gameport_unregister_port(chip->gameport);
+ chip->gameport = NULL;
+
+ release_resource(r);
+ kfree_nocheck(r);
+ }
+}
+#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) { }
+#endif /* SUPPORT_JOYSTICK */
+
static int __devinit snd_card_ymfpci_probe(struct pci_dev *pci,
const struct pci_device_id *pci_id)
{
@@ -86,9 +177,6 @@ static int __devinit snd_card_ymfpci_probe(struct pci_dev *pci,
snd_card_t *card;
struct resource *fm_res = NULL;
struct resource *mpu_res = NULL;
-#ifdef SUPPORT_JOYSTICK
- struct resource *joystick_res = NULL;
-#endif
ymfpci_t *chip;
opl3_t *opl3;
char *str;
@@ -138,17 +226,6 @@ static int __devinit snd_card_ymfpci_probe(struct pci_dev *pci,
legacy_ctrl |= YMFPCI_LEGACY_MEN;
pci_write_config_word(pci, PCIR_DSXG_MPU401BASE, mpu_port[dev]);
}
-#ifdef SUPPORT_JOYSTICK
- if (joystick_port[dev] == 1) {
- /* auto-detect */
- joystick_port[dev] = pci_resource_start(pci, 2);
- }
- if (joystick_port[dev] > 0 &&
- (joystick_res = request_region(joystick_port[dev], 1, "YMFPCI gameport")) != NULL) {
- legacy_ctrl |= YMFPCI_LEGACY_JPEN;
- pci_write_config_word(pci, PCIR_DSXG_JOYBASE, joystick_port[dev]);
- }
-#endif
} else {
switch (fm_port[dev]) {
case 0x388: legacy_ctrl2 |= 0; break;
@@ -178,34 +255,6 @@ static int __devinit snd_card_ymfpci_probe(struct pci_dev *pci,
legacy_ctrl2 &= ~YMFPCI_LEGACY2_MPUIO;
mpu_port[dev] = 0;
}
-#ifdef SUPPORT_JOYSTICK
- if (joystick_port[dev] == 1) {
- /* auto-detect */
- long p;
- for (p = 0x201; p <= 0x205; p++) {
- if (p == 0x203) continue;
- if ((joystick_res = request_region(p, 1, "YMFPCI gameport")) != NULL)
- break;
- }
- if (joystick_res)
- joystick_port[dev] = p;
- }
- switch (joystick_port[dev]) {
- case 0x201: legacy_ctrl2 |= 0 << 6; break;
- case 0x202: legacy_ctrl2 |= 1 << 6; break;
- case 0x204: legacy_ctrl2 |= 2 << 6; break;
- case 0x205: legacy_ctrl2 |= 3 << 6; break;
- default: joystick_port[dev] = 0; break;
- }
- if (! joystick_res && joystick_port[dev] > 0)
- joystick_res = request_region(joystick_port[dev], 1, "YMFPCI gameport");
- if (joystick_res) {
- legacy_ctrl |= YMFPCI_LEGACY_JPEN;
- } else {
- legacy_ctrl2 &= ~YMFPCI_LEGACY2_JSIO;
- joystick_port[dev] = 0;
- }
-#endif
}
if (mpu_res) {
legacy_ctrl |= YMFPCI_LEGACY_MIEN;
@@ -226,19 +275,10 @@ static int __devinit snd_card_ymfpci_probe(struct pci_dev *pci,
release_resource(fm_res);
kfree_nocheck(fm_res);
}
-#ifdef SUPPORT_JOYSTICK
- if (joystick_res) {
- release_resource(joystick_res);
- kfree_nocheck(joystick_res);
- }
-#endif
return err;
}
chip->fm_res = fm_res;
chip->mpu_res = mpu_res;
-#ifdef SUPPORT_JOYSTICK
- chip->joystick_res = joystick_res;
-#endif
strcpy(card->driver, str);
sprintf(card->shortname, "Yamaha DS-XG (%s)", str);
sprintf(card->longname, "%s at 0x%lx, irq %i",
@@ -292,12 +332,8 @@ static int __devinit snd_card_ymfpci_probe(struct pci_dev *pci,
return err;
}
}
-#ifdef SUPPORT_JOYSTICK
- if (chip->joystick_res) {
- chip->gameport.io = joystick_port[dev];
- gameport_register_port(&chip->gameport);
- }
-#endif
+
+ snd_ymfpci_create_gameport(chip, dev, legacy_ctrl, legacy_ctrl2);
if ((err = snd_card_register(card)) < 0) {
snd_card_free(card);
diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c
index 4b560a7357b39..05f1629760bc7 100644
--- a/sound/pci/ymfpci/ymfpci_main.c
+++ b/sound/pci/ymfpci/ymfpci_main.c
@@ -2079,14 +2079,7 @@ static int snd_ymfpci_free(ymfpci_t *chip)
release_resource(chip->fm_res);
kfree_nocheck(chip->fm_res);
}
-#ifdef SUPPORT_JOYSTICK
- if (chip->joystick_res) {
- if (chip->gameport.io)
- gameport_unregister_port(&chip->gameport);
- release_resource(chip->joystick_res);
- kfree_nocheck(chip->joystick_res);
- }
-#endif
+ snd_ymfpci_free_gameport(chip);
if (chip->reg_area_virt)
iounmap(chip->reg_area_virt);
if (chip->work_ptr.area)
@@ -2142,7 +2135,7 @@ static int saved_regs_index[] = {
};
#define YDSXGR_NUM_SAVED_REGS ARRAY_SIZE(saved_regs_index)
-static int snd_ymfpci_suspend(snd_card_t *card, unsigned int state)
+static int snd_ymfpci_suspend(snd_card_t *card, pm_message_t state)
{
ymfpci_t *chip = card->pm_private_data;
unsigned int i;
@@ -2161,7 +2154,7 @@ static int snd_ymfpci_suspend(snd_card_t *card, unsigned int state)
return 0;
}
-static int snd_ymfpci_resume(snd_card_t *card, unsigned int state)
+static int snd_ymfpci_resume(snd_card_t *card)
{
ymfpci_t *chip = card->pm_private_data;
unsigned int i;
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf.c b/sound/pcmcia/pdaudiocf/pdaudiocf.c
index e31a990df2757..f72c81cc99527 100644
--- a/sound/pcmcia/pdaudiocf/pdaudiocf.c
+++ b/sound/pcmcia/pdaudiocf/pdaudiocf.c
@@ -272,12 +272,17 @@ static void pdacf_config(dev_link_t *link)
client_handle_t handle = link->handle;
pdacf_t *pdacf = link->priv;
tuple_t tuple;
- cisparse_t parse;
+ cisparse_t *parse = NULL;
config_info_t conf;
u_short buf[32];
int last_fn, last_ret;
snd_printdd(KERN_DEBUG "pdacf_config called\n");
+ parse = kmalloc(sizeof(*parse), GFP_KERNEL);
+ if (! parse) {
+ snd_printk(KERN_ERR "pdacf_config: cannot allocate\n");
+ return;
+ }
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
tuple.Attributes = 0;
tuple.TupleData = (cisdata_t *)buf;
@@ -286,9 +291,10 @@ static void pdacf_config(dev_link_t *link)
tuple.DesiredTuple = CISTPL_CONFIG;
CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
- link->conf.ConfigBase = parse.config.base;
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, parse));
+ link->conf.ConfigBase = parse->config.base;
link->conf.ConfigIndex = 0x5;
+ kfree(parse);
CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf));
link->conf.Vcc = conf.Vcc;
@@ -342,7 +348,7 @@ static int pdacf_event(event_t event, int priority, event_callback_args_t *args)
link->state |= DEV_SUSPEND;
if (chip) {
snd_printdd(KERN_DEBUG "snd_pdacf_suspend calling\n");
- snd_pdacf_suspend(chip->card, 0);
+ snd_pdacf_suspend(chip->card, PMSG_SUSPEND);
}
/* Fall through... */
case CS_EVENT_RESET_PHYSICAL:
@@ -361,7 +367,7 @@ static int pdacf_event(event_t event, int priority, event_callback_args_t *args)
pcmcia_request_configuration(link->handle, &link->conf);
if (chip) {
snd_printdd(KERN_DEBUG "calling snd_pdacf_resume\n");
- snd_pdacf_resume(chip->card, 0);
+ snd_pdacf_resume(chip->card);
}
}
snd_printdd(KERN_DEBUG "resume done!\n");
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf.h b/sound/pcmcia/pdaudiocf/pdaudiocf.h
index ddaa69d542360..c7a9628256eed 100644
--- a/sound/pcmcia/pdaudiocf/pdaudiocf.h
+++ b/sound/pcmcia/pdaudiocf/pdaudiocf.h
@@ -134,8 +134,8 @@ pdacf_t *snd_pdacf_create(snd_card_t *card);
int snd_pdacf_ak4117_create(pdacf_t *pdacf);
void snd_pdacf_powerdown(pdacf_t *chip);
#ifdef CONFIG_PM
-int snd_pdacf_suspend(snd_card_t *card, unsigned int state);
-int snd_pdacf_resume(snd_card_t *card, unsigned int state);
+int snd_pdacf_suspend(snd_card_t *card, pm_message_t state);
+int snd_pdacf_resume(snd_card_t *card);
#endif
int snd_pdacf_pcm_new(pdacf_t *chip);
irqreturn_t pdacf_interrupt(int irq, void *dev, struct pt_regs *regs);
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf_core.c b/sound/pcmcia/pdaudiocf/pdaudiocf_core.c
index f845503bb4493..a2132e3763dd7 100644
--- a/sound/pcmcia/pdaudiocf/pdaudiocf_core.c
+++ b/sound/pcmcia/pdaudiocf/pdaudiocf_core.c
@@ -255,7 +255,7 @@ void snd_pdacf_powerdown(pdacf_t *chip)
#ifdef CONFIG_PM
-int snd_pdacf_suspend(snd_card_t *card, unsigned int state)
+int snd_pdacf_suspend(snd_card_t *card, pm_message_t state)
{
pdacf_t *chip = card->pm_private_data;
u16 val;
@@ -275,7 +275,7 @@ static inline int check_signal(pdacf_t *chip)
return (chip->ak4117->rcs0 & AK4117_UNLCK) == 0;
}
-int snd_pdacf_resume(snd_card_t *card, unsigned int state)
+int snd_pdacf_resume(snd_card_t *card)
{
pdacf_t *chip = card->pm_private_data;
int timeout = 40;
diff --git a/sound/pcmcia/vx/vx_entry.c b/sound/pcmcia/vx/vx_entry.c
index d3c70b02fbbbd..53d8172c52ae3 100644
--- a/sound/pcmcia/vx/vx_entry.c
+++ b/sound/pcmcia/vx/vx_entry.c
@@ -346,7 +346,7 @@ static int vxpocket_event(event_t event, int priority, event_callback_args_t *ar
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, 0);
+ chip->card->pm_suspend(chip->card, PMSG_SUSPEND);
}
/* Fall through... */
case CS_EVENT_RESET_PHYSICAL:
@@ -366,7 +366,7 @@ static int vxpocket_event(event_t event, int priority, event_callback_args_t *ar
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, 0);
+ chip->card->pm_resume(chip->card);
}
}
snd_printdd(KERN_DEBUG "resume done!\n");
diff --git a/sound/pcmcia/vx/vxp_ops.c b/sound/pcmcia/vx/vxp_ops.c
index 74d1685478591..ef6734271607f 100644
--- a/sound/pcmcia/vx/vxp_ops.c
+++ b/sound/pcmcia/vx/vxp_ops.c
@@ -22,6 +22,7 @@
#include <sound/driver.h>
#include <linux/delay.h>
+#include <linux/device.h>
#include <linux/firmware.h>
#include <sound/core.h>
#include <asm/io.h>
diff --git a/sound/ppc/keywest.c b/sound/ppc/keywest.c
index c4904895d94d0..df073a05b5d72 100644
--- a/sound/ppc/keywest.c
+++ b/sound/ppc/keywest.c
@@ -76,8 +76,6 @@ static int keywest_attach_adapter(struct i2c_adapter *adapter)
new_client->flags = 0;
strcpy(i2c_device_name(new_client), keywest_ctx->name);
-
- new_client->id = keywest_ctx->id++; /* Automatically unique */
keywest_ctx->client = new_client;
/* Tell the i2c layer a new client has arrived */
diff --git a/sound/ppc/pmac.c b/sound/ppc/pmac.c
index 2498b75fb6e51..6c4ed90f490e6 100644
--- a/sound/ppc/pmac.c
+++ b/sound/ppc/pmac.c
@@ -40,8 +40,8 @@
#if defined(CONFIG_PM) && defined(CONFIG_PMAC_PBOOK)
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, unsigned int state);
-static int snd_pmac_resume(snd_card_t *card, unsigned int state);
+static int snd_pmac_suspend(snd_card_t *card, pm_message_t state);
+static int snd_pmac_resume(snd_card_t *card);
#endif
@@ -1233,7 +1233,7 @@ 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, unsigned int state)
+static int snd_pmac_suspend(snd_card_t *card, pm_message_t state)
{
pmac_t *chip = card->pm_private_data;
unsigned long flags;
@@ -1254,7 +1254,7 @@ static int snd_pmac_suspend(snd_card_t *card, unsigned int state)
return 0;
}
-static int snd_pmac_resume(snd_card_t *card, unsigned int state)
+static int snd_pmac_resume(snd_card_t *card)
{
pmac_t *chip = card->pm_private_data;
@@ -1294,10 +1294,10 @@ static int snd_pmac_sleep_notify(struct pmu_sleep_notifier *self, int when)
switch (when) {
case PBOOK_SLEEP_NOW:
- snd_pmac_suspend(chip->card, 0);
+ snd_pmac_suspend(chip->card, PMSG_SUSPEND);
break;
case PBOOK_WAKE:
- snd_pmac_resume(chip->card, 0);
+ snd_pmac_resume(chip->card);
break;
}
return PBOOK_SLEEP_OK;
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index e7520f99054c7..84b0bbddbd226 100644
--- a/sound/usb/usbaudio.c
+++ b/sound/usb/usbaudio.c
@@ -1141,7 +1141,7 @@ static int init_usb_pitch(struct usb_device *dev, int iface,
data[0] = 1;
if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR,
USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT,
- PITCH_CONTROL << 8, ep, data, 1, HZ)) < 0) {
+ PITCH_CONTROL << 8, ep, data, 1, 1000)) < 0) {
snd_printk(KERN_ERR "%d:%d:%d: cannot set enable PITCH\n",
dev->devnum, iface, ep);
return err;
@@ -1167,14 +1167,14 @@ static int init_usb_sample_rate(struct usb_device *dev, int iface,
data[2] = rate >> 16;
if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR,
USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT,
- SAMPLING_FREQ_CONTROL << 8, ep, data, 3, HZ)) < 0) {
+ SAMPLING_FREQ_CONTROL << 8, ep, data, 3, 1000)) < 0) {
snd_printk(KERN_ERR "%d:%d:%d: cannot set freq %d to ep 0x%x\n",
dev->devnum, iface, fmt->altsetting, rate, ep);
return err;
}
if ((err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR,
USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_IN,
- SAMPLING_FREQ_CONTROL << 8, ep, data, 3, HZ)) < 0) {
+ SAMPLING_FREQ_CONTROL << 8, ep, data, 3, 1000)) < 0) {
snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq at ep 0x%x\n",
dev->devnum, iface, fmt->altsetting, ep);
return 0; /* some devices don't support reading */
@@ -1606,62 +1606,65 @@ static int hw_rule_format(snd_pcm_hw_params_t *params,
return changed;
}
+#define MAX_MASK 64
+
/*
* check whether the registered audio formats need special hw-constraints
*/
static int check_hw_params_convention(snd_usb_substream_t *subs)
{
int i;
- u32 channels[64];
- u32 rates[64];
+ u32 *channels;
+ u32 *rates;
u32 cmaster, rmaster;
u32 rate_min = 0, rate_max = 0;
struct list_head *p;
+ int err = 1;
- memset(channels, 0, sizeof(channels));
- memset(rates, 0, sizeof(rates));
+ channels = kcalloc(MAX_MASK, sizeof(u32), GFP_KERNEL);
+ rates = kcalloc(MAX_MASK, sizeof(u32), GFP_KERNEL);
list_for_each(p, &subs->fmt_list) {
struct audioformat *f;
f = list_entry(p, struct audioformat, list);
/* unconventional channels? */
if (f->channels > 32)
- return 1;
+ goto __out;
/* continuous rate min/max matches? */
if (f->rates & SNDRV_PCM_RATE_CONTINUOUS) {
if (rate_min && f->rate_min != rate_min)
- return 1;
+ goto __out;
if (rate_max && f->rate_max != rate_max)
- return 1;
+ goto __out;
rate_min = f->rate_min;
rate_max = f->rate_max;
}
/* combination of continuous rates and fixed rates? */
if (rates[f->format] & SNDRV_PCM_RATE_CONTINUOUS) {
if (f->rates != rates[f->format])
- return 1;
+ goto __out;
}
if (f->rates & SNDRV_PCM_RATE_CONTINUOUS) {
if (rates[f->format] && rates[f->format] != f->rates)
- return 1;
+ goto __out;
}
channels[f->format] |= (1 << f->channels);
rates[f->format] |= f->rates;
}
/* check whether channels and rates match for all formats */
cmaster = rmaster = 0;
- for (i = 0; i < 64; i++) {
+ for (i = 0; i < MAX_MASK; i++) {
if (cmaster != channels[i] && cmaster && channels[i])
- return 1;
+ goto __out;
if (rmaster != rates[i] && rmaster && rates[i])
- return 1;
+ goto __out;
if (channels[i])
cmaster = channels[i];
if (rates[i])
rmaster = rates[i];
}
/* check whether channels match for all distinct rates */
- memset(channels, 0, sizeof(channels));
+ memset(channels, 0, MAX_MASK * sizeof(u32));
list_for_each(p, &subs->fmt_list) {
struct audioformat *f;
f = list_entry(p, struct audioformat, list);
@@ -1675,11 +1678,16 @@ static int check_hw_params_convention(snd_usb_substream_t *subs)
cmaster = 0;
for (i = 0; i < 32; i++) {
if (cmaster != channels[i] && cmaster && channels[i])
- return 1;
+ goto __out;
if (channels[i])
cmaster = channels[i];
}
- return 0;
+ err = 0;
+
+ __out:
+ kfree(channels);
+ kfree(rates);
+ return err;
}
@@ -2936,7 +2944,7 @@ static int snd_usb_extigy_boot_quirk(struct usb_device *dev, struct usb_interfac
snd_printdd("sending Extigy boot sequence...\n");
/* Send message to force it to reconnect with full interface. */
err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev,0),
- 0x10, 0x43, 0x0001, 0x000a, NULL, 0, HZ);
+ 0x10, 0x43, 0x0001, 0x000a, NULL, 0, 1000);
if (err < 0) snd_printdd("error sending boot message: %d\n", err);
err = usb_get_descriptor(dev, USB_DT_DEVICE, 0,
&dev->descriptor, sizeof(dev->descriptor));
@@ -2968,6 +2976,9 @@ static int snd_usb_create_quirk(snd_usb_audio_t *chip,
case QUIRK_MIDI_FIXED_ENDPOINT:
case QUIRK_MIDI_YAMAHA:
case QUIRK_MIDI_MIDIMAN:
+ case QUIRK_MIDI_NOVATION:
+ case QUIRK_MIDI_MOTU:
+ case QUIRK_MIDI_EMAGIC:
return snd_usb_create_midi_interface(chip, iface, quirk);
case QUIRK_COMPOSITE:
return create_composite_quirk(chip, iface, quirk);
@@ -2980,6 +2991,8 @@ static int snd_usb_create_quirk(snd_usb_audio_t *chip,
return create_ua700_ua25_quirk(chip, iface);
case QUIRK_AUDIO_EDIROL_UA1000:
return create_ua1000_quirk(chip, iface);
+ case QUIRK_IGNORE_INTERFACE:
+ return 0;
default:
snd_printd(KERN_ERR "invalid quirk type %d\n", quirk->type);
return -ENXIO;
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index 5da9e5ee798cc..eecbf19fcb6fc 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -157,6 +157,10 @@ struct snd_usb_audio {
#define QUIRK_MIDI_STANDARD_INTERFACE 6
#define QUIRK_AUDIO_EDIROL_UA700_UA25 7
#define QUIRK_AUDIO_EDIROL_UA1000 8
+#define QUIRK_IGNORE_INTERFACE 9
+#define QUIRK_MIDI_NOVATION 10
+#define QUIRK_MIDI_MOTU 11
+#define QUIRK_MIDI_EMAGIC 12
typedef struct snd_usb_audio_quirk snd_usb_audio_quirk_t;
typedef struct snd_usb_midi_endpoint_info snd_usb_midi_endpoint_info_t;
@@ -171,7 +175,10 @@ struct snd_usb_audio_quirk {
/* data for QUIRK_MIDI_FIXED_ENDPOINT */
struct snd_usb_midi_endpoint_info {
- int8_t out_ep, in_ep; /* ep number, 0 autodetect */
+ int8_t out_ep; /* ep number, 0 autodetect */
+ uint8_t out_interval; /* interval for interrupt endpoints */
+ int8_t in_ep;
+ uint8_t in_interval;
uint16_t out_cables; /* bitmask */
uint16_t in_cables; /* bitmask */
};
@@ -190,6 +197,13 @@ struct snd_usb_midi_endpoint_info {
/* for QUIRK_AUDIO_EDIROL_UA700_UA25/UA1000, data is NULL */
+/* for QUIRK_IGNORE_INTERFACE, data is NULL */
+
+/* for QUIRK_MIDI_NOVATION and _MOTU, data is NULL */
+
+/* for QUIRK_MIDI_EMAGIC, data points to a snd_usb_midi_endpoint_info
+ * structure (out_cables and in_cables only) */
+
/*
*/
diff --git a/sound/usb/usbmidi.c b/sound/usb/usbmidi.c
index 496e520c5bdee..5d32857ff9554 100644
--- a/sound/usb/usbmidi.c
+++ b/sound/usb/usbmidi.c
@@ -1,7 +1,7 @@
/*
* usbmidi.c - ALSA USB MIDI driver
*
- * Copyright (c) 2002-2004 Clemens Ladisch
+ * Copyright (c) 2002-2005 Clemens Ladisch
* All rights reserved.
*
* Based on the OSS usb-midi driver by NAGANO Daisuke,
@@ -38,6 +38,7 @@
#include <sound/driver.h>
#include <linux/kernel.h>
#include <linux/types.h>
+#include <linux/bitops.h>
#include <linux/interrupt.h>
#include <linux/spinlock.h>
#include <linux/string.h>
@@ -49,6 +50,13 @@
#include <sound/rawmidi.h>
#include "usbaudio.h"
+
+/*
+ * define this to log all USB packets
+ */
+/* #define DUMP_PACKETS */
+
+
MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
MODULE_DESCRIPTION("USB Audio/MIDI helper module");
MODULE_LICENSE("Dual BSD/GPL");
@@ -77,22 +85,33 @@ 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 usb_protocol_ops {
+ void (*input)(snd_usb_midi_in_endpoint_t*, uint8_t*, int);
+ void (*output)(snd_usb_midi_out_endpoint_t*);
+ 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*);
+};
+
struct snd_usb_midi {
snd_usb_audio_t *chip;
struct usb_interface *iface;
const snd_usb_audio_quirk_t *quirk;
snd_rawmidi_t* rmidi;
+ struct usb_protocol_ops* usb_protocol_ops;
struct list_head list;
struct snd_usb_midi_endpoint {
snd_usb_midi_out_endpoint_t *out;
snd_usb_midi_in_endpoint_t *in;
} endpoints[MIDI_MAX_ENDPOINTS];
+ unsigned long input_triggered;
};
struct snd_usb_midi_out_endpoint {
snd_usb_midi_t* umidi;
struct urb* urb;
+ int urb_active;
int max_transfer; /* size of urb buffer */
struct tasklet_struct tasklet;
@@ -113,6 +132,7 @@ struct snd_usb_midi_out_endpoint {
#define STATE_SYSEX_2 6
uint8_t data[2];
} ports[0x10];
+ int current_port;
};
struct snd_usb_midi_in_endpoint {
@@ -121,6 +141,8 @@ struct snd_usb_midi_in_endpoint {
struct usbmidi_in_port {
snd_rawmidi_substream_t* substream;
} ports[0x10];
+ int seen_f5;
+ int current_port;
};
static void snd_usbmidi_do_output(snd_usb_midi_out_endpoint_t* ep);
@@ -156,24 +178,33 @@ static int snd_usbmidi_urb_error(int status)
}
/*
- * Receives a USB MIDI packet.
+ * Receives a chunk of MIDI data.
*/
-static void snd_usbmidi_input_packet(snd_usb_midi_in_endpoint_t* ep,
- uint8_t packet[4])
+static void snd_usbmidi_input_data(snd_usb_midi_in_endpoint_t* ep, int portidx,
+ uint8_t* data, int length)
{
- int cable = packet[0] >> 4;
- usbmidi_in_port_t* port = &ep->ports[cable];
+ usbmidi_in_port_t* port = &ep->ports[portidx];
if (!port->substream) {
- snd_printd("unexpected port %d!\n", cable);
+ snd_printd("unexpected port %d!\n", portidx);
return;
}
- if (!port->substream->runtime ||
- !port->substream->runtime->trigger)
+ if (!test_bit(port->substream->number, &ep->umidi->input_triggered))
return;
- snd_rawmidi_receive(port->substream, &packet[1],
- snd_usbmidi_cin_length[packet[0] & 0x0f]);
+ snd_rawmidi_receive(port->substream, data, length);
+}
+
+#ifdef DUMP_PACKETS
+static void dump_urb(const char *type, const u8 *data, int length)
+{
+ snd_printk(KERN_DEBUG "%s packet: [", type);
+ for (; length > 0; ++data, --length)
+ printk(" %02x", *data);
+ printk(" ]\n");
}
+#else
+#define dump_urb(type, data, length) /* nothing */
+#endif
/*
* Processes the data read from the device.
@@ -183,12 +214,9 @@ static void snd_usbmidi_in_urb_complete(struct urb* urb, struct pt_regs *regs)
snd_usb_midi_in_endpoint_t* ep = urb->context;
if (urb->status == 0) {
- uint8_t* buffer = (uint8_t*)ep->urb->transfer_buffer;
- int i;
-
- for (i = 0; i + 4 <= urb->actual_length; i += 4)
- if (buffer[i] != 0)
- snd_usbmidi_input_packet(ep, &buffer[i]);
+ dump_urb("received", urb->transfer_buffer, urb->actual_length);
+ ep->umidi->usb_protocol_ops->input(ep, urb->transfer_buffer,
+ urb->actual_length);
} else {
if (snd_usbmidi_urb_error(urb->status) < 0)
return;
@@ -200,71 +228,107 @@ 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;
+
+ spin_lock(&ep->buffer_lock);
+ ep->urb_active = 0;
+ spin_unlock(&ep->buffer_lock);
+ if (urb->status < 0) {
+ if (snd_usbmidi_urb_error(urb->status) < 0)
+ return;
+ }
+ snd_usbmidi_do_output(ep);
+}
+
/*
- * Converts the data read from a Midiman device to standard USB MIDI packets.
+ * This is called when some data should be transferred to the device
+ * (from one or more substreams).
*/
-static void snd_usbmidi_in_midiman_complete(struct urb* urb, struct pt_regs *regs)
+static void snd_usbmidi_do_output(snd_usb_midi_out_endpoint_t* ep)
{
- if (urb->status == 0) {
- uint8_t* buffer = (uint8_t*)urb->transfer_buffer;
- int i;
+ struct urb* urb = ep->urb;
+ unsigned long flags;
- for (i = 0; i + 4 <= urb->actual_length; i += 4) {
- if (buffer[i + 3] != 0) {
- /*
- * snd_usbmidi_input_packet() doesn't check the
- * contents of the message, so we simply use
- * some random CIN with the desired length.
- */
- static const uint8_t cin[4] = {
- 0x0, 0xf, 0x2, 0x3
- };
- uint8_t ctl = buffer[i + 3];
- buffer[i + 3] = buffer[i + 2];
- buffer[i + 2] = buffer[i + 1];
- buffer[i + 1] = buffer[i + 0];
- buffer[i + 0] = (ctl & 0xf0) | cin[ctl & 3];
- } else {
- buffer[i + 0] = 0;
- }
- }
+ spin_lock_irqsave(&ep->buffer_lock, flags);
+ if (ep->urb_active || ep->umidi->chip->shutdown) {
+ spin_unlock_irqrestore(&ep->buffer_lock, flags);
+ return;
+ }
+
+ urb->transfer_buffer_length = 0;
+ ep->umidi->usb_protocol_ops->output(ep);
+
+ if (urb->transfer_buffer_length > 0) {
+ dump_urb("sending", urb->transfer_buffer,
+ urb->transfer_buffer_length);
+ urb->dev = ep->umidi->chip->dev;
+ ep->urb_active = snd_usbmidi_submit_urb(urb, GFP_ATOMIC) >= 0;
}
- snd_usbmidi_in_urb_complete(urb, regs);
+ spin_unlock_irqrestore(&ep->buffer_lock, flags);
}
-static void snd_usbmidi_out_urb_complete(struct urb* urb, struct pt_regs *regs)
+static void snd_usbmidi_out_tasklet(unsigned long data)
{
- snd_usb_midi_out_endpoint_t* ep = urb->context;
+ snd_usb_midi_out_endpoint_t* ep = (snd_usb_midi_out_endpoint_t *) data;
- if (urb->status < 0) {
- if (snd_usbmidi_urb_error(urb->status) < 0)
- return;
- }
snd_usbmidi_do_output(ep);
}
+/* helper function to send static data that may not DMA-able */
+static int send_bulk_static_data(snd_usb_midi_out_endpoint_t* ep,
+ const void *data, int len)
+{
+ int err;
+ void *buf = kmalloc(len, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+ memcpy(buf, data, len);
+ dump_urb("sending", buf, len);
+ err = usb_bulk_msg(ep->umidi->chip->dev, ep->urb->pipe, buf, len,
+ NULL, 250);
+ kfree(buf);
+ return err;
+}
+
/*
- * Converts standard USB MIDI packets to what Midman devices expect.
+ * Standard USB MIDI protocol: see the spec.
+ * Midiman protocol: like the standard protocol, but the control byte is the
+ * fourth byte in each packet, and uses length instead of CIN.
*/
-static void snd_usbmidi_convert_to_midiman(struct urb* urb)
+
+static void snd_usbmidi_standard_input(snd_usb_midi_in_endpoint_t* ep,
+ uint8_t* buffer, int buffer_length)
{
- uint8_t* buffer = (uint8_t*)urb->transfer_buffer;
int i;
- for (i = 0; i + 4 <= urb->transfer_buffer_length; i += 4) {
- uint8_t cin = buffer[i];
- buffer[i + 0] = buffer[i + 1];
- buffer[i + 1] = buffer[i + 2];
- buffer[i + 2] = buffer[i + 3];
- buffer[i + 3] = (cin & 0xf0) | snd_usbmidi_cin_length[cin & 0x0f];
- }
+ for (i = 0; i + 3 < buffer_length; i += 4)
+ if (buffer[i] != 0) {
+ int cable = buffer[i] >> 4;
+ int length = snd_usbmidi_cin_length[buffer[i] & 0x0f];
+ snd_usbmidi_input_data(ep, cable, &buffer[i + 1], length);
+ }
+}
+
+static void snd_usbmidi_midiman_input(snd_usb_midi_in_endpoint_t* ep,
+ uint8_t* buffer, int buffer_length)
+{
+ int i;
+
+ for (i = 0; i + 3 < buffer_length; i += 4)
+ if (buffer[i + 3] != 0) {
+ int port = buffer[i + 3] >> 4;
+ int length = buffer[i + 3] & 3;
+ snd_usbmidi_input_data(ep, port, &buffer[i], length);
+ }
}
/*
* Adds one USB MIDI packet to the output buffer.
*/
-static inline void output_packet(struct urb* urb,
- uint8_t p0, uint8_t p1, uint8_t p2, uint8_t p3)
+static void snd_usbmidi_output_standard_packet(struct urb* urb, uint8_t p0,
+ uint8_t p1, uint8_t p2, uint8_t p3)
{
uint8_t* buf = (uint8_t*)urb->transfer_buffer + urb->transfer_buffer_length;
@@ -276,12 +340,29 @@ static inline void output_packet(struct urb* urb,
}
/*
+ * Adds one Midiman packet to the output buffer.
+ */
+static void snd_usbmidi_output_midiman_packet(struct urb* urb, uint8_t p0,
+ uint8_t p1, uint8_t p2, uint8_t p3)
+{
+
+ uint8_t* buf = (uint8_t*)urb->transfer_buffer + urb->transfer_buffer_length;
+ buf[0] = p1;
+ buf[1] = p2;
+ buf[2] = p3;
+ buf[3] = (p0 & 0xf0) | snd_usbmidi_cin_length[p0 & 0x0f];
+ urb->transfer_buffer_length += 4;
+}
+
+/*
* Converts MIDI commands to USB MIDI packets.
*/
static void snd_usbmidi_transmit_byte(usbmidi_out_port_t* port,
uint8_t b, struct urb* urb)
{
uint8_t p0 = port->cable;
+ void (*output_packet)(struct urb*, uint8_t, uint8_t, uint8_t, uint8_t) =
+ port->ep->umidi->usb_protocol_ops->output_packet;
if (b >= 0xf8) {
output_packet(urb, p0 | 0x0f, b, 0, 0);
@@ -370,63 +451,237 @@ static void snd_usbmidi_transmit_byte(usbmidi_out_port_t* port,
}
}
-/*
- * Moves data from one substream buffer to the URB transfer buffer.
- */
-static void snd_usbmidi_transmit(snd_usb_midi_out_endpoint_t* ep, int port_idx)
+static void snd_usbmidi_standard_output(snd_usb_midi_out_endpoint_t* ep)
{
struct urb* urb = ep->urb;
- usbmidi_out_port_t* port = &ep->ports[port_idx];
+ int p;
- while (urb->transfer_buffer_length < ep->max_transfer) {
- uint8_t b;
- if (snd_rawmidi_transmit_peek(port->substream, &b, 1) != 1) {
- port->active = 0;
- break;
+ /* FIXME: lower-numbered ports can starve higher-numbered ports */
+ for (p = 0; p < 0x10; ++p) {
+ usbmidi_out_port_t* port = &ep->ports[p];
+ if (!port->active)
+ continue;
+ while (urb->transfer_buffer_length + 3 < ep->max_transfer) {
+ uint8_t b;
+ if (snd_rawmidi_transmit(port->substream, &b, 1) != 1) {
+ port->active = 0;
+ break;
+ }
+ snd_usbmidi_transmit_byte(port, b, urb);
}
- snd_usbmidi_transmit_byte(port, b, urb);
- snd_rawmidi_transmit_ack(port->substream, 1);
}
}
+static struct usb_protocol_ops snd_usbmidi_standard_ops = {
+ .input = snd_usbmidi_standard_input,
+ .output = snd_usbmidi_standard_output,
+ .output_packet = snd_usbmidi_output_standard_packet,
+};
+
+static struct usb_protocol_ops snd_usbmidi_midiman_ops = {
+ .input = snd_usbmidi_midiman_input,
+ .output = snd_usbmidi_standard_output,
+ .output_packet = snd_usbmidi_output_midiman_packet,
+};
+
/*
- * This is called when some data should be transferred to the device
- * (from one or more substreams).
+ * Novation USB MIDI protocol: number of data bytes is in the first byte
+ * (when receiving) (+1!) or in the second byte (when sending); data begins
+ * at the third byte.
*/
-static void snd_usbmidi_do_output(snd_usb_midi_out_endpoint_t* ep)
+
+static void snd_usbmidi_novation_input(snd_usb_midi_in_endpoint_t* ep,
+ uint8_t* buffer, int buffer_length)
{
- int p;
- struct urb* urb = ep->urb;
- unsigned long flags;
+ if (buffer_length < 2 || !buffer[0] || buffer_length < buffer[0] + 1)
+ return;
+ snd_usbmidi_input_data(ep, 0, &buffer[2], buffer[0] - 1);
+}
- spin_lock_irqsave(&ep->buffer_lock, flags);
- if (urb->status == -EINPROGRESS || ep->umidi->chip->shutdown) {
- spin_unlock_irqrestore(&ep->buffer_lock, flags);
+static void snd_usbmidi_novation_output(snd_usb_midi_out_endpoint_t* ep)
+{
+ uint8_t* transfer_buffer;
+ int count;
+
+ if (!ep->ports[0].active)
+ return;
+ transfer_buffer = ep->urb->transfer_buffer;
+ count = snd_rawmidi_transmit(ep->ports[0].substream,
+ &transfer_buffer[2],
+ ep->max_transfer - 2);
+ if (count < 1) {
+ ep->ports[0].active = 0;
return;
}
+ transfer_buffer[0] = 0;
+ transfer_buffer[1] = count;
+ ep->urb->transfer_buffer_length = 2 + count;
+}
- urb->transfer_buffer_length = 0;
- for (p= 0; p < 0x10; ++p)
- if (ep->ports[p].active)
- snd_usbmidi_transmit(ep, p);
+static struct usb_protocol_ops snd_usbmidi_novation_ops = {
+ .input = snd_usbmidi_novation_input,
+ .output = snd_usbmidi_novation_output,
+};
- if (urb->transfer_buffer_length > 0) {
- if (ep->umidi->quirk && ep->umidi->quirk->type == QUIRK_MIDI_MIDIMAN)
- snd_usbmidi_convert_to_midiman(urb);
+/*
+ * Mark of the Unicorn USB MIDI protocol: raw MIDI.
+ */
- urb->dev = ep->umidi->chip->dev;
- snd_usbmidi_submit_urb(urb, GFP_ATOMIC);
+static void snd_usbmidi_motu_input(snd_usb_midi_in_endpoint_t* ep,
+ uint8_t* buffer, int buffer_length)
+{
+ snd_usbmidi_input_data(ep, 0, buffer, buffer_length);
+}
+
+static void snd_usbmidi_motu_output(snd_usb_midi_out_endpoint_t* ep)
+{
+ int count;
+
+ if (!ep->ports[0].active)
+ return;
+ count = snd_rawmidi_transmit(ep->ports[0].substream,
+ ep->urb->transfer_buffer,
+ ep->max_transfer);
+ if (count < 1) {
+ ep->ports[0].active = 0;
+ return;
}
- spin_unlock_irqrestore(&ep->buffer_lock, flags);
+ ep->urb->transfer_buffer_length = count;
}
-static void snd_usbmidi_out_tasklet(unsigned long data)
+static struct usb_protocol_ops snd_usbmidi_motu_ops = {
+ .input = snd_usbmidi_motu_input,
+ .output = snd_usbmidi_motu_output,
+};
+
+/*
+ * 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)
{
- snd_usb_midi_out_endpoint_t* ep = (snd_usb_midi_out_endpoint_t *) data;
+ static const u8 init_data[] = {
+ /* initialization magic: "get version" */
+ 0xf0,
+ 0x00, 0x20, 0x31, /* Emagic */
+ 0x64, /* Unitor8 */
+ 0x0b, /* version number request */
+ 0x00, /* command version */
+ 0x00, /* EEPROM, box 0 */
+ 0xf7
+ };
+ send_bulk_static_data(ep, init_data, sizeof(init_data));
+ /* while we're at it, pour on more magic */
+ send_bulk_static_data(ep, init_data, sizeof(init_data));
+}
- snd_usbmidi_do_output(ep);
+static void snd_usbmidi_emagic_finish_out(snd_usb_midi_out_endpoint_t* ep)
+{
+ static const u8 finish_data[] = {
+ /* switch to patch mode with last preset */
+ 0xf0,
+ 0x00, 0x20, 0x31, /* Emagic */
+ 0x64, /* Unitor8 */
+ 0x10, /* patch switch command */
+ 0x00, /* command version */
+ 0x7f, /* to all boxes */
+ 0x40, /* last preset in EEPROM */
+ 0xf7
+ };
+ send_bulk_static_data(ep, finish_data, sizeof(finish_data));
+}
+
+static void snd_usbmidi_emagic_input(snd_usb_midi_in_endpoint_t* ep,
+ uint8_t* buffer, int buffer_length)
+{
+ /* ignore padding bytes at end of buffer */
+ while (buffer_length > 0 && buffer[buffer_length - 1] == 0xff)
+ --buffer_length;
+
+ /* handle F5 at end of last buffer */
+ if (ep->seen_f5)
+ goto switch_port;
+
+ while (buffer_length > 0) {
+ int i;
+
+ /* determine size of data until next F5 */
+ for (i = 0; i < buffer_length; ++i)
+ if (buffer[i] == 0xf5)
+ break;
+ snd_usbmidi_input_data(ep, ep->current_port, buffer, i);
+ buffer += i;
+ buffer_length -= i;
+
+ if (buffer_length <= 0)
+ break;
+ /* assert(buffer[0] == 0xf5); */
+ ep->seen_f5 = 1;
+ ++buffer;
+ --buffer_length;
+
+ switch_port:
+ if (buffer_length <= 0)
+ break;
+ if (buffer[0] < 0x80) {
+ ep->current_port = (buffer[0] - 1) & 15;
+ ++buffer;
+ --buffer_length;
+ }
+ ep->seen_f5 = 0;
+ }
+}
+
+static void snd_usbmidi_emagic_output(snd_usb_midi_out_endpoint_t* ep)
+{
+ int port0 = ep->current_port;
+ uint8_t* buf = ep->urb->transfer_buffer;
+ int buf_free = ep->max_transfer;
+ int length, i;
+
+ 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];
+
+ if (!port->active)
+ continue;
+ if (snd_rawmidi_transmit_peek(port->substream, buf, 1) != 1) {
+ port->active = 0;
+ continue;
+ }
+
+ if (portnum != ep->current_port) {
+ if (buf_free < 2)
+ break;
+ ep->current_port = portnum;
+ buf[0] = 0xf5;
+ buf[1] = (portnum + 1) & 15;
+ buf += 2;
+ buf_free -= 2;
+ }
+
+ if (buf_free < 1)
+ break;
+ length = snd_rawmidi_transmit(port->substream, buf, buf_free);
+ if (length > 0) {
+ buf += length;
+ buf_free -= length;
+ if (buf_free < 1)
+ break;
+ }
+ }
+ ep->urb->transfer_buffer_length = ep->max_transfer - buf_free;
}
+static struct usb_protocol_ops snd_usbmidi_emagic_ops = {
+ .input = snd_usbmidi_emagic_input,
+ .output = snd_usbmidi_emagic_output,
+ .init_out_endpoint = snd_usbmidi_emagic_init_out,
+ .finish_out_endpoint = snd_usbmidi_emagic_finish_out,
+};
+
+
static int snd_usbmidi_output_open(snd_rawmidi_substream_t* substream)
{
snd_usb_midi_t* umidi = substream->rmidi->private_data;
@@ -483,6 +738,12 @@ static int snd_usbmidi_input_close(snd_rawmidi_substream_t* substream)
static void snd_usbmidi_input_trigger(snd_rawmidi_substream_t* substream, int up)
{
+ snd_usb_midi_t* umidi = substream->rmidi->private_data;
+
+ if (up)
+ set_bit(substream->number, &umidi->input_triggered);
+ else
+ clear_bit(substream->number, &umidi->input_triggered);
}
static snd_rawmidi_ops_t snd_usbmidi_output_ops = {
@@ -511,57 +772,6 @@ static void snd_usbmidi_in_endpoint_delete(snd_usb_midi_in_endpoint_t* ep)
}
/*
- * For Roland devices, use the alternate setting which uses interrupt
- * transfers for input.
- */
-static struct usb_endpoint_descriptor* snd_usbmidi_get_int_epd(snd_usb_midi_t* umidi)
-{
- struct usb_interface* intf;
- struct usb_host_interface *hostif;
- struct usb_interface_descriptor* intfd;
-
- if (le16_to_cpu(umidi->chip->dev->descriptor.idVendor) != 0x0582)
- return NULL;
- intf = umidi->iface;
- if (!intf || intf->num_altsetting != 2)
- return NULL;
-
- hostif = &intf->altsetting[0];
- intfd = get_iface_desc(hostif);
- if (intfd->bNumEndpoints != 2 ||
- (get_endpoint(hostif, 0)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK ||
- (get_endpoint(hostif, 1)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK)
- return NULL;
-
- hostif = &intf->altsetting[1];
- intfd = get_iface_desc(hostif);
- if (intfd->bNumEndpoints != 2 ||
- (get_endpoint(hostif, 0)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK ||
- (get_endpoint(hostif, 1)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT)
- return NULL;
-
- snd_printdd(KERN_INFO "switching to altsetting %d with int ep\n",
- intfd->bAlternateSetting);
- usb_set_interface(umidi->chip->dev, intfd->bInterfaceNumber,
- intfd->bAlternateSetting);
- return get_endpoint(hostif, 1);
-}
-
-static struct usb_endpoint_descriptor* snd_usbmidi_get_midiman_int_epd(snd_usb_midi_t* umidi)
-{
- struct usb_interface* intf = umidi->iface;
- struct usb_host_interface *hostif;
- struct usb_interface_descriptor *intfd;
- if (!intf)
- return NULL;
- hostif = &intf->altsetting[0];
- intfd = get_iface_desc(hostif);
- if (intfd->bNumEndpoints < 1)
- return NULL;
- return get_endpoint(hostif, 0);
-}
-
-/*
* Creates an input endpoint.
*/
static int snd_usbmidi_in_endpoint_create(snd_usb_midi_t* umidi,
@@ -569,7 +779,6 @@ static int snd_usbmidi_in_endpoint_create(snd_usb_midi_t* umidi,
snd_usb_midi_endpoint_t* rep)
{
snd_usb_midi_in_endpoint_t* ep;
- struct usb_endpoint_descriptor* int_epd;
void* buffer;
unsigned int pipe;
int length;
@@ -580,17 +789,12 @@ static int snd_usbmidi_in_endpoint_create(snd_usb_midi_t* umidi,
return -ENOMEM;
ep->umidi = umidi;
- if (umidi->quirk && umidi->quirk->type == QUIRK_MIDI_MIDIMAN)
- int_epd = snd_usbmidi_get_midiman_int_epd(umidi);
- else
- int_epd = snd_usbmidi_get_int_epd(umidi);
-
ep->urb = usb_alloc_urb(0, GFP_KERNEL);
if (!ep->urb) {
snd_usbmidi_in_endpoint_delete(ep);
return -ENOMEM;
}
- if (int_epd)
+ if (ep_info->in_interval)
pipe = usb_rcvintpipe(umidi->chip->dev, ep_info->in_ep);
else
pipe = usb_rcvbulkpipe(umidi->chip->dev, ep_info->in_ep);
@@ -600,10 +804,10 @@ static int snd_usbmidi_in_endpoint_create(snd_usb_midi_t* umidi,
snd_usbmidi_in_endpoint_delete(ep);
return -ENOMEM;
}
- if (int_epd)
+ if (ep_info->in_interval)
usb_fill_int_urb(ep->urb, umidi->chip->dev, pipe, buffer, length,
snd_usb_complete_callback(snd_usbmidi_in_urb_complete),
- ep, int_epd->bInterval);
+ ep, ep_info->in_interval);
else
usb_fill_bulk_urb(ep->urb, umidi->chip->dev, pipe, buffer, length,
snd_usb_complete_callback(snd_usbmidi_in_urb_complete),
@@ -613,12 +817,12 @@ static int snd_usbmidi_in_endpoint_create(snd_usb_midi_t* umidi,
return 0;
}
-static int snd_usbmidi_count_bits(uint16_t x)
+static unsigned int snd_usbmidi_count_bits(unsigned int x)
{
- int i, bits = 0;
+ unsigned int bits = 0;
- for (i = 0; i < 16; ++i)
- bits += (x & (1 << i)) != 0;
+ for (; x; x >>= 1)
+ bits += x & 1;
return bits;
}
@@ -660,8 +864,9 @@ static int snd_usbmidi_out_endpoint_create(snd_usb_midi_t* umidi,
snd_usbmidi_out_endpoint_delete(ep);
return -ENOMEM;
}
+ /* we never use interrupt output pipes */
pipe = usb_sndbulkpipe(umidi->chip->dev, ep_info->out_ep);
- ep->max_transfer = usb_maxpacket(umidi->chip->dev, pipe, 1) & ~3;
+ ep->max_transfer = usb_maxpacket(umidi->chip->dev, pipe, 1);
buffer = kmalloc(ep->max_transfer, GFP_KERNEL);
if (!buffer) {
snd_usbmidi_out_endpoint_delete(ep);
@@ -680,6 +885,9 @@ static int snd_usbmidi_out_endpoint_create(snd_usb_midi_t* umidi,
ep->ports[i].cable = i << 4;
}
+ if (umidi->usb_protocol_ops->init_out_endpoint)
+ umidi->usb_protocol_ops->init_out_endpoint(ep);
+
rep->out = ep;
return 0;
}
@@ -712,8 +920,11 @@ void snd_usbmidi_disconnect(struct list_head* p, struct usb_driver *driver)
umidi = list_entry(p, snd_usb_midi_t, list);
for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) {
snd_usb_midi_endpoint_t* ep = &umidi->endpoints[i];
- if (ep->out && ep->out->urb)
+ if (ep->out && ep->out->urb) {
usb_kill_urb(ep->out->urb);
+ if (umidi->usb_protocol_ops->finish_out_endpoint)
+ umidi->usb_protocol_ops->finish_out_endpoint(ep->out);
+ }
if (ep->in && ep->in->urb)
usb_kill_urb(ep->in->urb);
}
@@ -819,6 +1030,13 @@ static struct {
/* M-Audio MidiSport 8x8 */
{0x0763, 0x1031, 8, "%s Control"},
{0x0763, 0x1033, 8, "%s Control"},
+ /* MOTU Fastlane */
+ {0x07fd, 0x0001, 0, "%s MIDI A"},
+ {0x07fd, 0x0001, 1, "%s MIDI B"},
+ /* Emagic Unitor8/AMT8/MT4 */
+ {0x086a, 0x0001, 8, "%s Broadcast"},
+ {0x086a, 0x0002, 8, "%s Broadcast"},
+ {0x086a, 0x0003, 4, "%s Broadcast"},
};
static void snd_usbmidi_init_substream(snd_usb_midi_t* umidi,
@@ -928,7 +1146,8 @@ static int snd_usbmidi_get_ms_info(snd_usb_midi_t* umidi,
for (i = 0; i < intfd->bNumEndpoints; ++i) {
hostep = &hostif->endpoint[i];
ep = get_ep_desc(hostep);
- if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK)
+ if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK &&
+ (ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT)
continue;
ms_ep = (struct usb_ms_endpoint_descriptor*)hostep->extra;
if (hostep->extralen < 4 ||
@@ -944,6 +1163,8 @@ static int snd_usbmidi_get_ms_info(snd_usb_midi_t* umidi,
}
}
endpoints[epidx].out_ep = ep->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+ if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)
+ endpoints[epidx].out_interval = ep->bInterval;
endpoints[epidx].out_cables = (1 << ms_ep->bNumEmbMIDIJack) - 1;
snd_printdd(KERN_INFO "EP %02X: %d jack(s)\n",
ep->bEndpointAddress, ms_ep->bNumEmbMIDIJack);
@@ -955,6 +1176,8 @@ static int snd_usbmidi_get_ms_info(snd_usb_midi_t* umidi,
}
}
endpoints[epidx].in_ep = ep->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+ if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)
+ endpoints[epidx].in_interval = ep->bInterval;
endpoints[epidx].in_cables = (1 << ms_ep->bNumEmbMIDIJack) - 1;
snd_printdd(KERN_INFO "EP %02X: %d jack(s)\n",
ep->bEndpointAddress, ms_ep->bNumEmbMIDIJack);
@@ -964,38 +1187,93 @@ static int snd_usbmidi_get_ms_info(snd_usb_midi_t* umidi,
}
/*
- * If the endpoints aren't specified, use the first bulk endpoints in the
- * first alternate setting of the interface.
+ * On Roland devices, use the second alternate setting to be able to use
+ * the interrupt input endpoint.
*/
-static int snd_usbmidi_detect_endpoint(snd_usb_midi_t* umidi,
- snd_usb_midi_endpoint_info_t* endpoint)
+static void snd_usbmidi_switch_roland_altsetting(snd_usb_midi_t* umidi)
+{
+ struct usb_interface* intf;
+ struct usb_host_interface *hostif;
+ struct usb_interface_descriptor* intfd;
+
+ intf = umidi->iface;
+ if (!intf || intf->num_altsetting != 2)
+ return;
+
+ hostif = &intf->altsetting[1];
+ intfd = get_iface_desc(hostif);
+ if (intfd->bNumEndpoints != 2 ||
+ (get_endpoint(hostif, 0)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK ||
+ (get_endpoint(hostif, 1)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT)
+ return;
+
+ snd_printdd(KERN_INFO "switching to altsetting %d with int ep\n",
+ intfd->bAlternateSetting);
+ usb_set_interface(umidi->chip->dev, intfd->bInterfaceNumber,
+ intfd->bAlternateSetting);
+}
+
+/*
+ * 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,
+ int max_endpoints)
{
struct usb_interface* intf;
struct usb_host_interface *hostif;
struct usb_interface_descriptor* intfd;
struct usb_endpoint_descriptor* epd;
- int i;
+ int i, out_eps = 0, in_eps = 0;
+
+ if (le16_to_cpu(umidi->chip->dev->descriptor.idVendor) == 0x0582)
+ snd_usbmidi_switch_roland_altsetting(umidi);
intf = umidi->iface;
if (!intf || intf->num_altsetting < 1)
return -ENOENT;
- hostif = intf->altsetting;
+ hostif = intf->cur_altsetting;
intfd = get_iface_desc(hostif);
- if (intfd->bNumEndpoints < 1)
- return -ENOENT;
for (i = 0; i < intfd->bNumEndpoints; ++i) {
epd = get_endpoint(hostif, i);
- if ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK)
+ if ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK &&
+ (epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT)
continue;
- if (!endpoint->out_ep && endpoint->out_cables &&
- (epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT)
- endpoint->out_ep = epd->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
- if (!endpoint->in_ep && endpoint->in_cables &&
- (epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN)
- endpoint->in_ep = epd->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+ if (out_eps < max_endpoints &&
+ (epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) {
+ endpoint[out_eps].out_ep = epd->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+ if ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)
+ endpoint[out_eps].out_interval = epd->bInterval;
+ ++out_eps;
+ }
+ if (in_eps < max_endpoints &&
+ (epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) {
+ endpoint[in_eps].in_ep = epd->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+ if ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)
+ endpoint[in_eps].in_interval = epd->bInterval;
+ ++in_eps;
+ }
}
- return 0;
+ return (out_eps || in_eps) ? 0 : -ENOENT;
+}
+
+/*
+ * 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)
+{
+ int err, i;
+
+ err = snd_usbmidi_detect_endpoints(umidi, endpoints, MIDI_MAX_ENDPOINTS);
+ for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) {
+ if (endpoints[i].out_ep)
+ endpoints[i].out_cables = 0x0001;
+ if (endpoints[i].in_ep)
+ endpoints[i].in_cables = 0x0001;
+ }
+ return err;
}
/*
@@ -1034,7 +1312,7 @@ static int snd_usbmidi_detect_yamaha(snd_usb_midi_t* umidi,
if (!endpoint->in_cables && !endpoint->out_cables)
return -ENOENT;
- return snd_usbmidi_detect_endpoint(umidi, endpoint);
+ return snd_usbmidi_detect_endpoints(umidi, endpoint, 1);
}
/*
@@ -1098,11 +1376,11 @@ static int snd_usbmidi_create_endpoints_midiman(snd_usb_midi_t* umidi,
return err;
ep_info.in_ep = get_endpoint(hostif, 0)->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+ ep_info.in_interval = get_endpoint(hostif, 0)->bInterval;
ep_info.in_cables = endpoint->in_cables;
err = snd_usbmidi_in_endpoint_create(umidi, &ep_info, &umidi->endpoints[0]);
if (err < 0)
return err;
- umidi->endpoints[0].in->urb->complete = snd_usb_complete_callback(snd_usbmidi_in_midiman_complete);
if (endpoint->out_cables > 0x0001) {
ep_info.out_ep = get_endpoint(hostif, 4)->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
@@ -1203,6 +1481,7 @@ int snd_usb_create_midi_interface(snd_usb_audio_t* chip,
umidi->chip = chip;
umidi->iface = iface;
umidi->quirk = quirk;
+ umidi->usb_protocol_ops = &snd_usbmidi_standard_ops;
/* detect the endpoint(s) to use */
memset(endpoints, 0, sizeof(endpoints));
@@ -1213,16 +1492,31 @@ int snd_usb_create_midi_interface(snd_usb_audio_t* chip,
case QUIRK_MIDI_FIXED_ENDPOINT:
memcpy(&endpoints[0], quirk->data,
sizeof(snd_usb_midi_endpoint_info_t));
- err = snd_usbmidi_detect_endpoint(umidi, &endpoints[0]);
+ err = snd_usbmidi_detect_endpoints(umidi, &endpoints[0], 1);
break;
case QUIRK_MIDI_YAMAHA:
err = snd_usbmidi_detect_yamaha(umidi, &endpoints[0]);
break;
case QUIRK_MIDI_MIDIMAN:
+ umidi->usb_protocol_ops = &snd_usbmidi_midiman_ops;
memcpy(&endpoints[0], quirk->data,
sizeof(snd_usb_midi_endpoint_info_t));
err = 0;
break;
+ case QUIRK_MIDI_NOVATION:
+ umidi->usb_protocol_ops = &snd_usbmidi_novation_ops;
+ err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints);
+ break;
+ case QUIRK_MIDI_MOTU:
+ umidi->usb_protocol_ops = &snd_usbmidi_motu_ops;
+ err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints);
+ break;
+ case QUIRK_MIDI_EMAGIC:
+ umidi->usb_protocol_ops = &snd_usbmidi_emagic_ops;
+ memcpy(&endpoints[0], quirk->data,
+ sizeof(snd_usb_midi_endpoint_info_t));
+ err = snd_usbmidi_detect_endpoints(umidi, &endpoints[0], 1);
+ break;
default:
snd_printd(KERN_ERR "invalid quirk type %d\n", quirk->type);
err = -ENXIO;
diff --git a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c
index ccc0069e458d0..5f1906915aa62 100644
--- a/sound/usb/usbmixer.c
+++ b/sound/usb/usbmixer.c
@@ -305,7 +305,7 @@ static int get_ctl_value(usb_mixer_elem_info_t *cval, int request, int validx, i
request,
USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
validx, cval->ctrlif | (cval->id << 8),
- buf, val_len, HZ / 10) >= 0) {
+ buf, val_len, 100) >= 0) {
*value_ret = convert_signed_value(cval, snd_usb_combine_bytes(buf, val_len));
return 0;
}
@@ -343,7 +343,7 @@ static int set_ctl_value(usb_mixer_elem_info_t *cval, int request, int validx, i
request,
USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
validx, cval->ctrlif | (cval->id << 8),
- buf, val_len, HZ / 10) >= 0)
+ buf, val_len, 100) >= 0)
return 0;
snd_printdd(KERN_ERR "cannot set ctl value: req = 0x%x, wValue = 0x%x, wIndex = 0x%x, type = %d, data = 0x%x/0x%x\n", request, validx, cval->ctrlif | (cval->id << 8), cval->val_type, buf[0], buf[1]);
return -EINVAL;
@@ -1519,7 +1519,7 @@ int snd_usb_create_mixer(snd_usb_audio_t *chip, int ctrlif)
/* check the mapping table */
for (map = usbmix_ctl_maps; map->vendor; map++) {
- if (map->vendor == le16_to_cpu(dev->idVendor) && map->product == le16_to_cpu(dev->idProduct)) {
+ if (map->vendor == state.vendor && map->product == state.product) {
state.map = map->map;
chip->ignore_ctl_error = map->ignore_ctl_error;
break;
diff --git a/sound/usb/usbquirks.h b/sound/usb/usbquirks.h
index e79721ce1af18..88bbd944d4be9 100644
--- a/sound/usb/usbquirks.h
+++ b/sound/usb/usbquirks.h
@@ -72,6 +72,8 @@ YAMAHA_DEVICE(0x1007, "MOTIF8"),
YAMAHA_DEVICE(0x1008, "UX96"),
YAMAHA_DEVICE(0x1009, "UX16"),
YAMAHA_INTERFACE(0x100a, 3, "EOS BX"),
+YAMAHA_DEVICE(0x100c, "UC-MX"),
+YAMAHA_DEVICE(0x100d, "UC-KX"),
YAMAHA_DEVICE(0x100e, "S08"),
YAMAHA_DEVICE(0x100f, "CLP-150"),
YAMAHA_DEVICE(0x1010, "CLP-170"),
@@ -86,6 +88,7 @@ YAMAHA_DEVICE(0x1019, "CVP-208"),
YAMAHA_DEVICE(0x101a, "CVP-210"),
YAMAHA_DEVICE(0x101b, "PSR-1100"),
YAMAHA_DEVICE(0x101c, "PSR-2100"),
+YAMAHA_DEVICE(0x101d, "CLP-175"),
YAMAHA_DEVICE(0x101e, "PSR-K1"),
YAMAHA_DEVICE(0x1020, "EZ-250i"),
YAMAHA_DEVICE(0x1021, "MOTIF ES 6"),
@@ -125,9 +128,12 @@ YAMAHA_DEVICE(0x5005, "ACU16-C"),
YAMAHA_DEVICE(0x5006, "NHB32-C"),
YAMAHA_DEVICE(0x5007, "DM1000"),
YAMAHA_DEVICE(0x5008, "01V96"),
+YAMAHA_DEVICE(0x5009, "SPX2000"),
YAMAHA_DEVICE(0x500a, "PM5D"),
YAMAHA_DEVICE(0x500b, "DME64N"),
YAMAHA_DEVICE(0x500c, "DME24N"),
+YAMAHA_DEVICE(0x500d, NULL),
+YAMAHA_DEVICE(0x500e, NULL),
YAMAHA_DEVICE(0x7000, "DTX"),
YAMAHA_DEVICE(0x7010, "UB99"),
#undef YAMAHA_DEVICE
@@ -629,6 +635,19 @@ YAMAHA_DEVICE(0x7010, "UB99"),
}
},
{
+ USB_DEVICE(0x0582, 0x0042),
+ .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .vendor_name = "Roland",
+ .product_name = "RS-70",
+ .ifnum = 0,
+ .type = QUIRK_MIDI_FIXED_ENDPOINT,
+ .data = & (const snd_usb_midi_endpoint_info_t) {
+ .out_cables = 0x0001,
+ .in_cables = 0x0001
+ }
+ }
+},
+{
USB_DEVICE(0x0582, 0x0044),
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
.vendor_name = "Roland",
@@ -685,19 +704,6 @@ YAMAHA_DEVICE(0x7010, "UB99"),
}
},
{
- USB_DEVICE(0x0582, 0x0065),
- .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
- .vendor_name = "EDIROL",
- .product_name = "PCR-1",
- .ifnum = 0,
- .type = QUIRK_MIDI_FIXED_ENDPOINT,
- .data = & (const snd_usb_midi_endpoint_info_t) {
- .out_cables = 0x0001,
- .in_cables = 0x0003
- }
- }
-},
-{
/*
* This quirk is for the "Advanced Driver" mode. If off, the UA-3FX
* is standard compliant, but has only 16-bit PCM.
@@ -732,6 +738,45 @@ YAMAHA_DEVICE(0x7010, "UB99"),
.type = QUIRK_MIDI_STANDARD_INTERFACE
}
},
+{
+ USB_DEVICE(0x0582, 0x0065),
+ .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .vendor_name = "EDIROL",
+ .product_name = "PCR-1",
+ .ifnum = 0,
+ .type = QUIRK_MIDI_FIXED_ENDPOINT,
+ .data = & (const snd_usb_midi_endpoint_info_t) {
+ .out_cables = 0x0001,
+ .in_cables = 0x0003
+ }
+ }
+},
+{
+ USB_DEVICE_VENDOR_SPEC(0x0582, 0x006a),
+ .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .vendor_name = "Roland",
+ .product_name = "SP-606",
+ .ifnum = 3,
+ .type = QUIRK_MIDI_FIXED_ENDPOINT,
+ .data = & (const snd_usb_midi_endpoint_info_t) {
+ .out_cables = 0x0001,
+ .in_cables = 0x0001
+ }
+ }
+},
+{
+ USB_DEVICE(0x0582, 0x006d),
+ .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .vendor_name = "Roland",
+ .product_name = "FANTOM-X",
+ .ifnum = 0,
+ .type = QUIRK_MIDI_FIXED_ENDPOINT,
+ .data = & (const snd_usb_midi_endpoint_info_t) {
+ .out_cables = 0x0001,
+ .in_cables = 0x0001
+ }
+ }
+},
{ /*
* This quirk is for the "Advanced" modes of the Edirol UA-25.
* If the switch is not in an advanced setting, the UA-25 has
@@ -763,6 +808,19 @@ YAMAHA_DEVICE(0x7010, "UB99"),
}
}
},
+{
+ USB_DEVICE(0x0582, 0x0075),
+ .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .vendor_name = "BOSS",
+ .product_name = "DR-880",
+ .ifnum = 0,
+ .type = QUIRK_MIDI_FIXED_ENDPOINT,
+ .data = & (const snd_usb_midi_endpoint_info_t) {
+ .out_cables = 0x0001,
+ .in_cables = 0x0001
+ }
+ }
+},
/* Midiman/M-Audio devices */
{
@@ -876,6 +934,22 @@ YAMAHA_DEVICE(0x7010, "UB99"),
* but captured samples are big-endian (see usbaudio.c).
*/
{
+ .ifnum = 0,
+ .type = QUIRK_IGNORE_INTERFACE
+ },
+ {
+ .ifnum = 1,
+ .type = QUIRK_IGNORE_INTERFACE
+ },
+ {
+ .ifnum = 2,
+ .type = QUIRK_IGNORE_INTERFACE
+ },
+ {
+ .ifnum = 3,
+ .type = QUIRK_IGNORE_INTERFACE
+ },
+ {
.ifnum = 4,
.type = QUIRK_AUDIO_STANDARD_INTERFACE
},
@@ -884,6 +958,10 @@ YAMAHA_DEVICE(0x7010, "UB99"),
.type = QUIRK_AUDIO_STANDARD_INTERFACE
},
{
+ .ifnum = 6,
+ .type = QUIRK_IGNORE_INTERFACE
+ },
+ {
.ifnum = 7,
.type = QUIRK_AUDIO_STANDARD_INTERFACE
},
@@ -936,27 +1014,81 @@ YAMAHA_DEVICE(0x7010, "UB99"),
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
.vendor_name = "M-Audio",
.product_name = "OmniStudio",
- .ifnum = 9,
- .type = QUIRK_MIDI_MIDIMAN,
- .data = & (const snd_usb_midi_endpoint_info_t) {
- .out_cables = 0x0001,
- .in_cables = 0x0001
+ .ifnum = QUIRK_ANY_INTERFACE,
+ .type = QUIRK_COMPOSITE,
+ .data = & (const snd_usb_audio_quirk_t[]) {
+ {
+ .ifnum = 0,
+ .type = QUIRK_IGNORE_INTERFACE
+ },
+ {
+ .ifnum = 1,
+ .type = QUIRK_IGNORE_INTERFACE
+ },
+ {
+ .ifnum = 2,
+ .type = QUIRK_IGNORE_INTERFACE
+ },
+ {
+ .ifnum = 3,
+ .type = QUIRK_IGNORE_INTERFACE
+ },
+ {
+ .ifnum = 4,
+ .type = QUIRK_AUDIO_STANDARD_INTERFACE
+ },
+ {
+ .ifnum = 5,
+ .type = QUIRK_AUDIO_STANDARD_INTERFACE
+ },
+ {
+ .ifnum = 6,
+ .type = QUIRK_IGNORE_INTERFACE
+ },
+ {
+ .ifnum = 7,
+ .type = QUIRK_AUDIO_STANDARD_INTERFACE
+ },
+ {
+ .ifnum = 8,
+ .type = QUIRK_AUDIO_STANDARD_INTERFACE
+ },
+ {
+ .ifnum = 9,
+ .type = QUIRK_MIDI_MIDIMAN,
+ .data = & (const snd_usb_midi_endpoint_info_t) {
+ .out_cables = 0x0001,
+ .in_cables = 0x0001
+ }
+ },
+ {
+ .ifnum = -1
+ }
}
}
},
/* Mark of the Unicorn devices */
{
- /* thanks to Woodley Packard <sweaglesw@thibs.menloschool.org> */
+ /* thanks to Robert A. Lerche <ral 'at' msbit.com> */
USB_DEVICE(0x07fd, 0x0001),
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
.vendor_name = "MOTU",
.product_name = "Fastlane",
- .ifnum = 1,
- .type = QUIRK_MIDI_FIXED_ENDPOINT,
- .data = & (const snd_usb_midi_endpoint_info_t) {
- .out_cables = 0x0003,
- .in_cables = 0x0003
+ .ifnum = QUIRK_ANY_INTERFACE,
+ .type = QUIRK_COMPOSITE,
+ .data = & (const snd_usb_audio_quirk_t[]) {
+ {
+ .ifnum = 0,
+ .type = QUIRK_MIDI_MOTU
+ },
+ {
+ .ifnum = 1,
+ .type = QUIRK_IGNORE_INTERFACE
+ },
+ {
+ .ifnum = -1
+ }
}
}
},
@@ -972,6 +1104,47 @@ YAMAHA_DEVICE(0x7010, "UB99"),
},
+/* Emagic devices */
+{
+ USB_DEVICE(0x086a, 0x0001),
+ .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .vendor_name = "Emagic",
+ /* .product_name = "Unitor8", */
+ .ifnum = 2,
+ .type = QUIRK_MIDI_EMAGIC,
+ .data = & (const snd_usb_midi_endpoint_info_t) {
+ .out_cables = 0x80ff,
+ .in_cables = 0x80ff
+ }
+ }
+},
+{
+ USB_DEVICE(0x086a, 0x0002),
+ .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .vendor_name = "Emagic",
+ /* .product_name = "AMT8", */
+ .ifnum = 2,
+ .type = QUIRK_MIDI_EMAGIC,
+ .data = & (const snd_usb_midi_endpoint_info_t) {
+ .out_cables = 0x80ff,
+ .in_cables = 0x80ff
+ }
+ }
+},
+{
+ USB_DEVICE(0x086a, 0x0003),
+ .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .vendor_name = "Emagic",
+ /* .product_name = "MT4", */
+ .ifnum = 2,
+ .type = QUIRK_MIDI_EMAGIC,
+ .data = & (const snd_usb_midi_endpoint_info_t) {
+ .out_cables = 0x800f,
+ .in_cables = 0x8003
+ }
+ }
+},
+
{
USB_DEVICE_VENDOR_SPEC(0x0ccd, 0x0013),
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
@@ -982,6 +1155,35 @@ YAMAHA_DEVICE(0x7010, "UB99"),
}
},
+/* Novation EMS devices */
+{
+ USB_DEVICE_VENDOR_SPEC(0x1235, 0x0001),
+ .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .vendor_name = "Novation",
+ .product_name = "ReMOTE Audio/XStation",
+ .ifnum = 4,
+ .type = QUIRK_MIDI_NOVATION
+ }
+},
+{
+ USB_DEVICE_VENDOR_SPEC(0x1235, 0x0002),
+ .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .vendor_name = "Novation",
+ .product_name = "Speedio",
+ .ifnum = 3,
+ .type = QUIRK_MIDI_NOVATION
+ }
+},
+{
+ USB_DEVICE_VENDOR_SPEC(0x1235, 0x4661),
+ .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .vendor_name = "Novation",
+ .product_name = "ReMOTE25",
+ .ifnum = 0,
+ .type = QUIRK_MIDI_NOVATION
+ }
+},
+
{
/*
* Some USB MIDI devices don't have an audio control interface,
diff --git a/sound/usb/usx2y/usX2Yhwdep.c b/sound/usb/usx2y/usX2Yhwdep.c
index 40ca82a3e6c5c..bef9b0c142c40 100644
--- a/sound/usb/usx2y/usX2Yhwdep.c
+++ b/sound/usb/usx2y/usX2Yhwdep.c
@@ -226,7 +226,7 @@ static int snd_usX2Y_hwdep_dsp_load(snd_hwdep_t *hw, snd_hwdep_dsp_image_t *dsp)
if (err)
snd_printk("usb_set_interface error \n");
else
- err = usb_bulk_msg(dev, usb_sndbulkpipe(dev, 2), buf, dsp->length, &lret, 6*HZ);
+ err = usb_bulk_msg(dev, usb_sndbulkpipe(dev, 2), buf, dsp->length, &lret, 6000);
kfree(buf);
}
if (err)
diff --git a/sound/usb/usx2y/usbusx2yaudio.c b/sound/usb/usx2y/usbusx2yaudio.c
index ef89bcde40c94..4c292e0900699 100644
--- a/sound/usb/usx2y/usbusx2yaudio.c
+++ b/sound/usb/usx2y/usbusx2yaudio.c
@@ -415,7 +415,6 @@ static int usX2Y_urbs_allocate(snd_usX2Y_substream_t *subs)
unsigned int pipe;
int is_playback = subs == subs->usX2Y->subs[SNDRV_PCM_STREAM_PLAYBACK];
struct usb_device *dev = subs->usX2Y->chip.dev;
- struct usb_host_endpoint *ep;
pipe = is_playback ? usb_sndisocpipe(dev, subs->endpoint) :
usb_rcvisocpipe(dev, subs->endpoint);